TowardsDataScience-博客中文翻译-2020-十二-
TowardsDataScience 博客中文翻译 2020(十二)
神经网络中的激活函数
为什么我们需要激活函数,是什么让它们如此特别

尼尔·托马斯在 Unsplash 上拍摄的照片
神经网络之所以如此特殊,是因为它们能够模拟输入和输出之间高度复杂的关系。我们无法用线性模型实现这些复杂的关系。因此,神经网络需要能够表示非线性。这就是我们在神经网络中使用激活函数的原因。如果没有激活函数,神经网络可以被认为是一个线性模型包。
激活功能增加了神经网络的学习能力。用神经网络解决的许多任务包含非线性,例如图像、文本、声波。因此,我们需要非线性来解决深度学习领域中最常见的任务,如图像和语音识别、自然语言处理等。
没有激活功能的神经元只是输入和偏置的线性组合。

没有激活功能的神经元
这只是一个神经元。神经网络中典型的隐藏层有许多神经元。然而,没有激活函数,我们有许多不同的输入线性组合。通过添加额外的隐藏层,我们得到输入的线性组合的线性组合,而不会给我们带来非线性的复杂性。然而,当我们向神经元添加激活函数时,我们就摆脱了线性的诅咒,能够模拟复杂的非线性关系。

具有激活功能的神经元
有许多不同的激活功能可用。每一个都有自己的优点和缺点以及具体的特点。我们不仅对激活函数本身感兴趣,而且对它的导数也感兴趣。原因是神经网络实际“学习”的方式。
输入乘以权重并加上偏差。然后应用激活函数得到输出。这个过程被称为正向传播。将神经网络的输出与实际目标值进行比较,并计算差值(或损失)。关于损失的信息被反馈到神经网络,并且权重被更新,从而减少损失。这个过程被称为反向传播。使用基于导数的梯度下降算法更新权重。因此,激活函数的导数也应该携带关于输入值的信息。
有许多激活功能可用。我们将涵盖神经网络中最常用的非线性激活函数。
乙状结肠
我们熟悉逻辑回归中的 sigmoid 函数。著名的 S 形函数将输入值转换为 0 到 1 之间的范围。

我们来画一下。我们首先创建一个 numpy 数组,并对其应用 sigmoid 函数。
import numpy as np
import pandas as pdx = np.linspace(-10,10,50)
y = 1 / (1 + np.exp(-x))
然后用 matplotlib 绘图。
import matplotlib.pyplot as plt
%matplotlib inlineplt.figure(figsize=(8,5))
plt.title("Sigmoid Function", fontsize=15)
plt.grid()
plt.plot(x, y)

每个神经元的输出在 0 和 1 之间标准化。上图的中间区域显示,x(输入)的微小变化会导致 y(输出)的相对较大变化。Sigmoid 函数擅长检测这些区域中的差异,这使其成为良好的分类器。因此,它通常用于二元分类任务。
不幸的是,没有什么是完美的。sigmoid 函数有一个缺点。随着我们远离中心,x 值的变化对 y 值的影响很小或没有影响,让我们来看看 sigmoid 函数的导数。我们可以使用 numpy 的梯度函数来计算导数:
x = np.linspace(-10,10,50)
dx = x[1]-x[0]
y = 1 / (1 + np.exp(-x))
dydx = np.gradient(y, dx)
然后我们在同一张图上绘制 y 和 dydx:
plt.figure(figsize=(8,5))
plt.title("Sigmoid Function and Its Derivative", fontsize=15)
plt.grid()
plt.plot(x, y)
plt.plot(x, dydx)

我们可以看到,当我们远离中心时,导数趋向于零。在评论这个图之前,让我们记住神经网络是如何学习的。神经网络的学习意味着更新权重以最小化损失(实际值和预测值之间的差异)。基于梯度更新权重,梯度基本上是函数的导数。如果梯度非常接近零,则以非常小的增量更新权重。这导致神经网络学习速度非常慢,永远无法收敛。这也被称为消失梯度问题。
双曲正切
Tanh 与 sigmoid 函数非常相似,只是它是围绕原点对称的。输出值限制在(-1,+1)的范围内。
x = np.linspace(-5,5,80)
y_tanh =2*(1 / (1 + np.exp(-2*x)))-1plt.figure(figsize=(8,5))
plt.title("Tanh Function", fontsize=15)
plt.grid()
plt.plot(x, y_tanh)

Tanh 是以零点为中心的,这样渐变就不会被限制在一个特定的方向上移动。因此,它比 sigmoid 函数收敛得更快。
tanh 的导数类似于 sigmoid 的导数,但是更陡。

从导数线可以看出,tanh 也有消失梯度的问题。
ReLU(整流线性单元)
对于大于 0 的输入,relu 函数的输出等于输入值。对于所有其他输入值,输出为 0。
x = np.linspace(-10,10,50)
y_relu = np.where(x < 0, 0, x)plt.figure(figsize=(8,5))
plt.title("ReLU Function", fontsize=15)
plt.grid()
plt.plot(x, y_relu)

Relu 使得仅激活网络中的一些神经元成为可能,这使得计算效率比 tanh 和 sigmoid 更高。所有的神经元都被 tanh 和 sigmoid 激活,这导致了密集的计算。因此,relu 比 tanh 和 sigmoid 收敛得更快。
对于大于 0 的输入值,relu 的导数为 1。对于所有其他输入值,导数为 0,这导致一些权重在反向传播期间永远不会更新。因此,神经网络不能学习负输入值。这个问题被称为将死再禄问题。使用泄漏 relu 函数的一种解决方案。
泄漏的 ReLU
除了正输入值之外,它与 relu 相同。对于负值,leaky relu 输出一个非常小的数字,而 relu 只给出 0。

Softmax
Softmax 获取实数的输入值,并将其归一化为概率分布。概率与输入值的指数成正比。考虑一下,神经网络的输出层有 10 个神经元。Softmax 函数采用这 10 个输出并创建概率分布。10 个值的概率加起来是 1。
Softmax 激活用于具有多个类别的分类任务。
唰
Swish 是一个自门控激活功能,与我们迄今为止讨论过的功能相比相对较新。这是由谷歌的研究人员发现的。在计算效率方面,它与 relu 相似,但在更深的模型上比 relu 表现得更好。正如研究人员所说,“在许多具有挑战性的数据集上,swish 往往比 relu 更好地工作”。

让我们画出 swish 的曲线图。
x = np.linspace(-5,5,50)
y_swish = x*(1 / (1 + np.exp(-x)))plt.figure(figsize=(8,5))
plt.title("Swish Function", fontsize=15)
plt.grid()
plt.plot(x, y_swish)

Swish 在 0 处没有锐边,不像 relu 在训练时更容易收敛。
我们已经讨论了 6 种不同的激活函数。它们在某些方面都各有利弊。激活函数对计算复杂性和模型的收敛性有影响。因此,更好地理解它们是如何表现的,以便我们可以根据任务选择最佳的激活函数。通常,激活函数的期望属性是:
- 计算成本低
- 零居中
- 可微的。激活函数的导数需要携带关于输入值的信息,因为权重是基于梯度更新的。
- 不会导致消失梯度问题
感谢您的阅读。如果您有任何反馈,请告诉我。
激活、卷积和池化—第 4 部分
FAU 讲座笔记深度学习
联营机制

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座
以上是 FAU 的 YouTube 讲座 深度学习****的** 讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!**
航行
欢迎回到深度学习!所以今天,我想和你谈谈实际的池实现。池层是许多深层网络中的一个重要步骤。这背后的主要思想是你想减少空间域的维数。

汇集通过归约技术减少了空间信息。 CC 下的图片来自深度学习讲座的 4.0 。
在这个小例子中,我们将绿色矩形、蓝色矩形、黄色矩形和红色矩形中的信息汇总为一个值。因此,我们有一个必须映射到单个值的 2x2 输入。这当然减少了参数的数量。它引入了层次结构,并允许您使用空间抽象。此外,它减少了计算成本和过拟合。当然,我们需要一些基本的假设,其中一个假设是特征是分层结构的。通过池化,我们减少了输出大小,并引入了信号中固有的层次结构。我们讨论过眼睛是由边缘、线条和脸组成的,就像眼睛和嘴一样。这必须存在,以使联营成为一个明智的操作,包括在您的网络中。

最大汇集选择感受野中的最大指数。 CC 下的图片来自深度学习讲座的 4.0 。
在这里,您可以看到一个 3x3 层的池,我们选择最大池。因此,在最大池中,只有最大数量的受体场才会真正传播到输出中。显然,我们也可以大踏步地工作。通常,步幅等于邻域大小,这样我们每个感受野得到一个输出。

最大汇集仅考虑每个感受野中的最大值。ABBA 的粉丝请点击这里。来自深度学习讲座的 4.0CC 下的图片。
这里的问题当然是最大值运算增加了额外的非线性,因此我们还必须考虑如何解决梯度过程中的这一步。本质上,我们再次使用次梯度概念,其中我们简单地传播到产生最大输出的单元中。所以,你可以说赢家通吃。

平均池是最大池的常见替代方法。 CC 下的图片来自深度学习讲座的 4.0 。
另一种选择是平均分摊。这里,我们简单地计算邻域的平均值。但是,它的性能并不总是优于最大池。在反向传播过程中,误差被简单地平均分配并反向传播到相应的单元。

许多其他的池选择是可用的。 CC 下的图片来自深度学习讲座的 4.0 。
还有许多池策略,如部分最大池,Lp 池,随机池,特殊金字塔池,广义池,等等。对此有一套完全不同的策略。我们已经讨论过的两种选择是步长卷积和 atrous 卷积。这变得非常流行,因为这样你就不必把最大池编码作为一个额外的步骤,并且减少了参数的数量。通常,人们现在使用 S 大于 1 的步进卷积,以便同时实现卷积和池化。

深层网络的典型设计选择。来自深度学习讲座的 CC BY 4.0 下的图片。
让我们回顾一下我们的卷积神经网络正在做什么。我们讨论了卷积产生的特征图和汇集减少各自特征图的大小。然后,再次回旋和汇集,直到我们在一个抽象的表现结束。最后,我们有这些完全连接的层,以便进行分类。实际上,我们可以取消最后一个模块,因为我们已经看到,如果我们将其重新格式化为通道方向,那么我们可以将其替换为 1x1 卷积。随后,我们只是应用这个来得到我们的最终分类。因此,我们可以进一步减少构建模块的数量。我们甚至不再需要完全连接的层了!

1x1 回旋能够代替完全连接的层。 CC 下的图片来自深度学习讲座的 4.0 。
现在,一切都变得完全卷积,我们可以通过卷积和合并步骤来表达整个操作链。所以,我们甚至不再需要完全连接的层了。使用 1x1 卷积的好处是,如果您将它与所谓的全局平均池结合起来,那么您基本上也可以处理任意大小的输入图像。这里的想法是,在卷积处理结束时,只需映射到信道方向,然后计算所有输入的全局平均值。这是可行的,因为您有一个预定义的全局池操作。然后,您可以将其应用于任意大小的图像。因此,我们再次受益于汇集和卷积的思想。

为了更深入,我们将很快研究进一步的想法。 CC 下的图片来自深度学习讲座的 4.0 。
一个有趣的概念是初始模型,我们将在这堂课的后面更详细地讨论它。这种方法来自于论文“用回旋走得更深”[8]遵循我们自己的座右铭:“我们需要走得更深!”。该网络赢得了 2014 年 ImageNet 挑战赛。一个例子是 GoogLeNet,它是受参考文献[4]启发的化身。

初始模块允许网络自己学习卷积和汇集的顺序。来自深度学习讲座的 CC BY 4.0 下的图片。
他们提出的想法解决了必须交替固定卷积和合并步骤的问题。为什么不允许网络在它想汇集和想卷积时自己学习呢?所以,主要的想法是,你把并行 1x1 卷积,3x3 卷积,5x5 卷积,和最大池。然后,你把它们连接起来。现在,有趣的是,如果你并行提供所有四个操作,这基本上意味着下一层可以选择最信任的输入,以构建深度网络。如果这样做,您可以进一步扩展,例如在 3x3 和 5x5 卷积中。您可能希望在实际评估通道之前先对其进行压缩。然后,您会在右侧找到配置。这结合了额外的维度减少。尽管如此,这种并行处理允许网络学习自己的池化和卷积层序列。

完整的 GoogLeNet 架构将很快被更详细地描述。 CC 下的图片来自深度学习讲座的 4.0 。
然后,你得到像这样的模型。这已经是一个相当深入的模型,其中包含许多有趣的进一步创新,我们将在讨论不同的网络架构时讨论这些创新。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。来自深度学习讲座的 CC BY 4.0 下的图片。
所以下一次在深度学习中,我们想谈谈如何防止网络只是记忆训练数据。有没有办法强制特征独立?如何确保我们的网络也能识别不同姿势的猫?此外,一个非常好的方法可以帮助你,以及我们如何修复内部协变量移位问题。这些都是重要的观点,我认为答案确实值得在这里提出。

综合问题可以帮助学生准备考试。 CC 下的图片来自深度学习讲座的 4.0 。
此外,我有几个综合性的问题或任务。说出五种激活功能。讨论这五种激活功能。零点对中问题是什么?写下步长卷积的数学描述。1x1 卷积和全连接层有什么联系?什么是池层?为什么我们需要这些池层?所以,在某个特定的时间点,有人会问你很多有趣的事情。如果你有任何问题,你可以在评论中发表或通过电子邮件发送。所以,我希望你喜欢这个讲座,我们下次再见!
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。
参考
[1] I. J. Goodfellow、d . ward-Farley、M. Mirza 等人,“最大网络”。载于:ArXiv 电子版(2013 年 2 月)。arXiv:1302.4389[统计 ML】。
[2],,,,任等,“深入挖掘整流器:在 ImageNet 分类上超越人类水平的表现”。载于:CoRR abs/1502.01852 (2015)。arXiv: 1502.01852。
[3]君特·克兰鲍尔(Günter Klambauer),托马斯·安特辛纳(Thomas Unterthiner),安德烈亚斯·迈尔(Andreas Mayr),等,“自归一化神经网络”。在:神经信息处理系统的进展。abs/1706.02515 卷。2017.arXiv: 1706.02515。
【四】、和水城颜。“网络中的网络”。载于:CoRR abs/1312.4400 (2013 年)。arXiv: 1312.4400。
[5]安德鲁·马斯、奥尼·汉南和安德鲁·吴。“整流器非线性改善神经网络声学模型”。在:过程中。ICML。第 30 卷。1.2013.
[6] Prajit Ramachandran,Barret Zoph,和 Quoc V. Le。“搜索激活功能”。载于:CoRR abs/1710.05941 (2017 年)。arXiv: 1710.05941。
【7】Stefan elf wing,内池英治,多亚贤治。“强化学习中神经网络函数逼近的 Sigmoid 加权线性单元”。载于:arXiv 预印本 arXiv:1702.03118 (2017)。
[8]克里斯蒂安·塞格迪、、·贾等,“用回旋深化”。载于:CoRR abs/1409.4842 (2014 年)。arXiv: 1409.4842。
主动和半监督机器学习:8 月 17-28 日
主动学习时事通讯
关于主动(偶尔半监督或弱监督)深度学习的最新 arXiv 预印本精选

这是我新的主动学习时事通讯的创刊号(每周或每两周出版一期,取决于前一周相关预印本的数量)。我过去也做过类似的事情:去年秋天出现在 Scaleway 博客上的 arXiv 系列的 。这是迫使自己跟上深度学习领域新东西的一种很好的方式,但是,由于这个领域如此活跃,最终变得太耗时了。尽管我最喜欢的科幻作家曾经说过
专业化是为了昆虫,
不是每个人都能达到罗伯特·A·海因莱因的高标准。阅读 arXiv 当然是专业化派上用场的地方。巧合的是,在过去的几个月里,我选择关注主动学习,因为这是一个非常有实际意义的领域,因为计算越来越便宜,但数据标记仍然很昂贵。要了解主动学习领域最前沿的研究,请继续阅读!
我们列表中的第一个是使用深度神经网络进行文本分类的主动学习调查:
[## 基于深度神经网络的文本分类主动学习综述
自然语言处理(NLP)和神经网络(NNs)在最近几年都经历了重大变化…
arxiv.org](https://arxiv.org/abs/2008.07267)
它首先概述了主动学习背后的基本思想、进行主动学习的不同方式(例如,基于池的与基于流的等)、使用的常用术语,然后列出了几个不同类别的查询策略(即,模型用来决定接下来要标记哪些训练样本的逻辑选择)。通过大量的参考资料,预印本为那些有兴趣将人工智能应用于 NLP 的人提供了一个很好的起点。
如今新冠肺炎无处不在,arXiv 也不例外。使用 X 射线胸部图像校正半监督新冠肺炎检测的数据不平衡查看(这并不奇怪)在不平衡的一组(一些)新冠肺炎图像与(大量)非 Covid 图像上进行的半监督学习。不平衡的数据集和极其昂贵的注释是医学数据的两个标志,因此将这两者放在一起看是有意义的。
[## 使用 X 射线胸部图像校正半监督新冠肺炎检测的数据不平衡
冠状病毒(新冠肺炎)是一种国际流行病,它已经在全世界迅速传播。的…
arxiv.org](https://arxiv.org/abs/2008.08496)
该模型本身是谷歌的 MixMatch 的变体:半监督学习的整体方法 ,可以追溯到 2019 年——很像问题中的病毒。
在一个相关的医学笔记中,我们已经将逐渐应用于乳腺超声图像中的质量检测的弱监督和主动学习:
[## 逐步将弱监督和主动学习应用于乳腺超声中的肿块检测…
我们提出了一种方法,有效地利用弱注释图像数据的目标检测任务的乳房…
arxiv.org](https://arxiv.org/abs/2008.08416)
这里我们有作者所说的(a)强注释数据,其中注释是双重的:围绕肿块+良性与恶性分类标签的边界框,以及(b)弱注释数据,其仅带有图像级标签。在强注释数据上训练的模型然后被用于以熟悉的主动学习方式迭代地向用户查询一批周注释图像的边界框。
通过按委员会查询的主动学习的一个相当普通的应用,以及另一个涉及蒙特卡罗批量标准化的查询策略。不过这个问题很有趣:空中或卫星图像中的变化检测。我从来没有认真考虑过地图是如何保持更新的,但我的想法是,一般来说,地图是随着增量更新而更新的,而不是不断地从头开始重新创建。接下来的任务是检测变化。问题是,手动查找这些(通常是罕见的、稀疏分布的)变更需要检查整个映射区域🗺。祝你好运标签那套训练套装!幸运的是,主动学习有助于:
[## 遥感中用于数据有效变化检测的深度主动学习
我们在深度神经网络模型的背景下研究主动学习,用于变化检测和地图更新…
arxiv.org](https://arxiv.org/abs/2008.11201) 
在学习以半监督的方式学习中,作者解决了基于图像的项目验证问题(例如人脸识别——或者任何你旨在学习特征嵌入的任务,这种特征嵌入会将相同类型的实例聚集在一起,而将其他实例远离)。现在这里有一个转折:在它们的有标签和无标签数据集中的对象类的集合是不相交的。也就是说,模型被要求找出关于看不见的类别的数据的东西(因为缺乏更好的术语)——在某种程度上,保留那些类别的结构。很酷,不是吗?
[## 学会以半监督的方式学习
为了解决来自标记和未标记数据的半监督学习,我们提出了一种新的元学习方案。我们…
arxiv.org](https://arxiv.org/abs/2008.11203)
下一个引起我注意的预印本专注于增量学习:一种机器学习方法,其中模型不断用新数据更新,同时还负责保留先前学习信息的知识。在广泛的应用中,这无疑是一个现实的场景。为了更加现实,假设只有一部分新的流数据被注释(因此需要主动学习),我们也不要对类分布做任何假设。所以我们得到了增量主动不平衡…我们应该叫它什么?
[## 不平衡数据集的主动类增量学习
增量学习(IL)允许人工智能系统适应流式数据。大多数现有算法使两个强…
arxiv.org](https://arxiv.org/abs/2008.10968)
是的,听起来没错。
最后,在非 arXiv,但仍然非常活跃的学习中,新闻:上周我做了一个 20 分钟的演讲,题为“为什么一些数据比其他数据更平等”,作为开放数据科学大会热身的一部分。该讲座现已在他们的网站上以免费点播网上研讨会的形式发布:
[## 点播网络研讨会:ODSC 欧洲 2020 虚拟训练营热身
Beehive Media 创始人比尔·山德“从数字到叙事:将原始数据转化为引人注目的视觉故事…
aiplus.odsc.com](https://aiplus.odsc.com/courses/odsc-europe-2020-virtual-bootcamp-warm-up)
我的部分大约在 23:00 开始。看看吧,一两周后见:)
页(page 的缩写)如果你是主动学习的新手,这里有几篇我以前的文章可以帮你入门:
主动学习仍然是机器学习中的一种利基方法,但这种情况必将改变。
medium.com](https://medium.com/scaleway-cloud/active-learning-part-1-the-theory-239b7a43ddb5) [## PyTorch 的主动学习
通过这个循序渐进的影像分类教程,了解如何节省高达 50%的数据标注成本
medium.com](https://medium.com/scaleway-cloud/active-learning-with-pytorch-dc6805956b0f)
主动和半监督机器学习:8 月 31 日至 9 月 11 日
主动学习时事通讯
关于主动(偶尔半监督或弱监督)深度学习的最新 arXiv 预印本精选
前一期:
关于主动(偶尔半监督或弱监督)深度学习的最新 arXiv 预印本精选
towardsdatascience.com](/active-and-semi-supervised-machine-learning-aug-17-28-77eaa9dbc311)
过去几周,活跃和半监督的机器学习社区出现了大量行动。以下是一些个人最喜欢的,而不是详尽的列表,分为两部分: 主动学习 和 半监督学习 g

这些钻井石油立管和机器学习有什么关系?请继续阅读,寻找答案!图片来源:wikipedia.org
主动学习
主动学习仍然是机器学习中的一种利基方法,但这种情况必将改变。
medium.com](https://medium.com/scaleway-cloud/active-learning-part-1-the-theory-239b7a43ddb5)
如今,可解释的人工智能是一件大事。在 ALEX:基于主动学习的模型可解释性增强中,作者使用了一种新颖的查询策略:对“难以解释”的实例进行优先排序。(他们使用SHAP 框架来确定后者。)他们的目标是找到一个在性能和模型可解释性两方面都得到优化的分类器,至少在 MNIST 上,作者在这两方面都取得了成功:
[## ALEX:基于主动学习的模型可解释性增强
一种主动学习(AL)算法试图用最少的标记样本构建一个有效的分类器
arxiv.org](https://arxiv.org/abs/2009.00859)
现在,这绝不是一种批评,但与我看到的大多数关于机器学习主题的预印本不同,这篇论文是以完全学术的风格撰写的。有点像回到我还是物理学家的时候,那时一切可能已经变成了数学陈述,就是。举个小例子来说明我的意思:
“此参数近似中的误差 θ (真实函数相关性θ)预计会随着训练集中对数 M 的增加而变小,即 θ → θ as M → ∞。”
或者换句话说:训练样本越多,模型概括得越好。无论如何,我只是觉得有趣的是,当我第一次开始阅读 ML 论文而不是物理论文时,我认为它们缺乏严谨性曾经让我沮丧,而现在我更可能注意到相反的情况。人是怎么变的!
让我们说,一个主动学习系统不是简单地要求你标记它选择的数据,而是要求你验证或纠正模型的预测。作为一个主观的人,你更相信哪个人工智能,是你没有发言权的人工智能,还是在训练过程中得到你反馈的人工智能?根据中介绍的研究,为交互式机器学习征求人在回路中的用户反馈会降低用户信任和对模型准确性的印象(我想标题已经给出了答案),典型的人在回路中对模型的性能不太信任,不管他们的反馈是否提高了模型的性能。
[## 为交互式机器学习征求人在回路中的用户反馈会降低用户的信任度…
混合主动性系统允许用户交互地提供反馈,以潜在地提高系统性能。人类…
arxiv.org](https://arxiv.org/abs/2008.12735)
仔细想想,这是有道理的:能够纠正模型预测的人(尤其是那些信心分数低的人)看到了模型最糟糕的一面,因此失去了信心。
在高光谱成像中,需要大量训练数据的问题甚至更加尖锐。简而言之,输入的维度越高,模型越大,就需要越多的数据来训练它。在用于高光谱图像分类的主动深度密集连接卷积网络中提出了一种有趣的主动学习方法:
[## 用于高光谱图像分类的主动深度密集连接卷积网络
过去,基于深度学习的方法在高光谱图像分类中的受欢迎程度大幅上升…
arxiv.org](https://arxiv.org/abs/2009.00320)
这里的查询策略是基于预测损失值的。
终身学习,或者说持续学习,不仅仅是我们所有人都应该以某种形式做的事情,也是人工智能的子领域。这种想法是,生产中的模型可能需要通过对新数据进行微调来保持最新——随着后者变得可用,不断地进行微调。然而,从一开始就积累所有的训练数据并在整个集合上不断地重新训练并不是最实际的做法。挑战在于适应新的现实(现实=数据),同时不忘记以前学到的东西。如果你习惯于标准的模型训练协议,你可能会明白为什么这会带来一个问题:一旦你在一个新的数据集上重新训练你的网络,它对旧数据集的记忆和金鱼的记忆一样有价值。在最近的预印本中回顾了一些对抗所谓“灾难性遗忘”的技术,这是一个深度神经网络持续学习的整体观:被遗忘的课程和通往主动开放世界学习的桥梁:
[## 深度神经网络持续学习的整体观:遗忘的课程和桥梁…
目前的深度学习研究以基准评测为主。一种方法被认为是有利的,如果它…
arxiv.org](https://arxiv.org/abs/2009.01797)
作者认为,虽然主动学习可以被视为旨在实现持续学习的反向操作(选择数据以供未来包含,而不是在面对新数据时保留已学习的表示),但这两个领域之间仍有桥梁需要搭建。
这里有一个好玩的,通过基于池的主动学习自动选择模拟案例加速工程设计:
[## 通过基于池的模拟案例自动选择加速工程设计…
许多工程设计问题的通用工作流程需要对设计系统的评估进行调查…
arxiv.org](https://arxiv.org/abs/2009.01420)
显然,号近海石油立管的设计过程包括运行大量的海流和海浪模拟。引用预印本作者的话,
许多这些组合可能是多余的,因为许多这些模拟的隔水管中的机械张力可以从其他模拟的结果中估算出来。...这里的挑战在于找到信息最丰富的案例。
自然地,这使得石油立管设计成为主动学习的绝佳选择!与计算机视觉和 NLP 中更熟悉的应用不同,这里未标记的数据对应于尚未运行的模拟池,而标记训练实例相当于运行模拟(如果可能,工程师希望避免这种昂贵的操作)。

我第一次在报纸上看到这样的数字。图片来源:【arxiv.org
其他一些荣誉奖颁发给:
- 深度主动学习的调查,30 页的领域概述,一些问题,应用和开放问题,近 200 个参考资料可供深入研究:
[## 深度主动学习综述
主动学习(AL)试图通过标记最少的样本来最大化模型的性能增益。深…
arxiv.org](https://arxiv.org/abs/2009.00236)
- 主动学习在工程中的另一个应用,这次是在超材料的设计中:
[## 偏微分方程深度代理的主动学习:在超曲面设计中的应用
偏微分方程的代理模型广泛用于超材料的设计,以快速评估…
arxiv.org](https://arxiv.org/abs/2008.12649)
- 一种有趣的新的主动学习方法,作者称之为主动学习++ ,它不仅向标注器查询样本的标签,还查询输入特征的重要性排序(根据标注器)。所涉及的模型是逻辑回归(适合手头的结构化数据集),但我必须承认,我发现作为例子的任务有点畏缩。这个人的收入是根据他们的教育和工作经历,以及种族和性别来预测的。注释者应该如何对这样的特性进行排序呢?“我认为这个人每年挣 N 美元的主要原因是他们是 XX 种族和 YY 性别”?无论如何,注释者提供标签之外的信息的想法很有趣,所以值得一提的是:
[## 主动学习++:使用本地模型解释合并注释者的基本原理
我们提出了一个新的主动学习框架——主动学习++,它既可以利用标注者的标注,也可以利用学习者的兴趣
arxiv.org](https://arxiv.org/abs/2009.04568)
- 另一个争议较小的问题是,这是一个基于池的不确定性采样在天文调查中的应用:
[## 用于在大型光谱勘测中发现感兴趣对象的主动深度学习方法
目前 LAMOST 望远镜的档案包含数百万个管道处理的光谱,这些光谱可能从未被…
arxiv.org](https://arxiv.org/abs/2009.03219)
半监督学习
关于猫和狗的 PyTorch 故事
medium.com](https://medium.com/scaleway-cloud/semi-supervised-learning-with-gans-a-tale-of-cats-and-dogs-3c90acfe91c9)
数据注释花费巨大的领域之一是医学。我们列表中的下一个预印本关注使用未标记数据和知识蒸馏对糖尿病视网膜病变的分类。
[## 使用未标记数据和知识蒸馏对糖尿病视网膜病变进行分类
知识提炼允许将知识从预先训练的模型转移到另一个模型。然而,它的缺点是…
arxiv.org](https://arxiv.org/abs/2009.00982)
糖尿病视网膜病变是一种由糖尿病引起的眼睛疾病,但论文中的思想很容易应用于任何图像分类问题。知识提炼是一种方法,包括将知识从一个模型(老师)转移到另一个模型(学生,通常是一个较小的网络)。以定期监督的方式训练教师,然后将软标签(教师对训练集的输出)用作训练学生的标签。预印本的主旨是,除了已标记的集合,你还可以在提取过程中使用老师对未标记图像的软标签,最终得到一个更好的模型。
在你离开之前,这里有两份关于半监督深度学习在医学领域应用的预印本:
[## 基于双任务一致性的半监督医学图像分割
基于深度学习的半监督学习(SSL)算法已经在医学图像方面取得了令人鼓舞的结果…
arxiv.org](https://arxiv.org/abs/2009.04448) [## 具有不纠缠表示的半监督病理分割
自动病理分割在临床实践中仍然是一种有价值的诊断工具。然而,收集训练…
arxiv.org](https://arxiv.org/abs/2009.02564)
一周(或两周)后见!
主动和半监督机器学习:10 月 12 日至 23 日
主动学习简讯
关于主动(偶尔半监督或弱监督)深度学习的最新 arXiv 预印本精选
前一期:
[## 主动和半监督机器学习:9 月 28 日至 10 月 9 日
关于主动(偶尔半监督或弱监督)深度学习的最新 arXiv 预印本精选
towardsdatascience.com](/active-and-semi-supervised-machine-learning-sep-28-oct-9-50813688c616)

我想提到的第一个资源实际上是大约一个月前发表在 TDS 上的另一篇博文:
半监督学习(SSL)已经在深度学习研究社区中蓬勃发展——我们分享从学习中获得的经验…
towardsdatascience.com](/from-research-to-production-with-deep-semi-supervised-learning-7caaedc39093)
尽管我很喜欢一份最新的预印本,里面有一些前沿的研究成果,但没有什么能打败那些将上述研究应用于现实世界问题的人的反馈。博客文章 Uizard 背后的团队讨论了几个实用的要点,主要是在对象检测的背景下,但我发现最有趣的是下面这个:
伪标签是由在标记的(和/或先前伪标记的)训练样本上训练的模型对未标记的数据做出的高置信度预测。伪标记(也称为自我训练)可用于自动化大部分数据注释过程,从而大幅降低相关的标记成本。然而,它容易出错:特别是,模型在早期发现的任何偏差,很可能只会在以后被放大。解决这个问题的方法之一是人工验证伪标签。通常情况下,验证比从头开始贴标签更省时,因此采用这种方法仍然有很大的附加值。在博文中,作者描述了 Uizard 发现的另一个有效的解决方案,特别是对于对象检测任务。这个解决方案就是启发式伪标签精化。他们的博文示例处理公寓图像中某些家具的检测。在这里,可以用来自动提炼伪标签的试探法可以沿着这样的路线进行:梳妆台和厨房岛看起来有些相似,但是床和梳妆台比床和厨房岛更有可能出现在同一图像中。因此,如果你发现一张床和一个厨房岛,那个“岛”很可能是一个梳妆台。简单吧?人们可以想象在现实生活的用例中有许多这样的启发式方法,所以这种策略听起来绝对值得记住。
主动学习通常与半监督学习分开考虑,但本质上,前者可以被视为后者的一个亚型。我已经在之前的一篇博文中讨论了主动学习背后的理论:
主动学习仍然是机器学习中的一种利基方法,但这种情况必将改变。
medium.com](https://medium.com/scaleway-cloud/active-learning-part-1-the-theory-239b7a43ddb5)
基本思想是在标记数据上训练监督模型,然后在非监督集合上使用训练模型的预测来区分下一个要标记的实例的优先级。然而,根据少量标记数据训练的模型显然不会提供最佳性能。现在,如果我们执行半监督训练,而不是在主动学习循环中进行监督训练,会怎么样?一种嵌套的半监督方法,利用未标记的数据进行训练和人在回路中的标记池。这种想法的一个变体被证明非常有效,如:
[## 基于双层优化的半监督批量主动学习
主动学习是一种通过提高数据效率来降低标注成本的有效技术。在这项工作中,我们…
arxiv.org](https://arxiv.org/abs/2010.09654)
当我们在主动学习的主题上时,这里有一个可以在自然语言处理(NLP)问题中使用的新的查询策略:一个给定的短语如何令人惊讶?

是的,真的。(图片鸣谢:约翰·怀特)
为了量化这个问题的答案,的作者通过自我监督语言建模使用 BERT 冷启动主动学习。也就是说,他们用它来计算他们所谓的惊奇嵌入。为了让你对结果有一个概念,考虑预印本中的这个例子:短语“他们对天主教迷幻合成民谣音乐感到矛盾”被认为比“这是我最喜欢的电视节目”更令人惊讶。(这一点我无法反驳。)该属性成为查询策略的一部分,用于区分以下数据注释的优先级:
[## 通过自我监督语言建模进行冷启动主动学习
主动学习通过选择最关键的例子来标注,努力降低标注成本。通常情况下……
arxiv.org](https://arxiv.org/abs/2010.09535)
在计算机视觉领域,主动学习方法通常在图像分类或对象检测方面进行评估(也就是说,我们的目标是分配图像级别的类别标签,或者在对象周围绘制边界框并识别它们)。然而,另一个常见的计算机视觉任务,语义分割,在像素级分配类别标签,通常标注数据的成本要高得多。这当然使它成为主动学习的特别理想的候选对象!

每个像素都有语义标签的图像示例。图片来源:英伟达
除了标准的查询策略(例如不确定性采样的变化等),我们可以定义一个特定于分段问题的度量,就像上面讨论的预印本中特定于 NLP 的“这个短语有多令人惊讶”一样。在这里,这个新的度量将成为创建分割蒙版的难点:例如,选择小的行人图形可能会比上图中选择大的矩形建筑或公共汽车更困难。将这一困难纳入主动学习过程的讨论见:
[## DEAL:面向语义分割的难度感知主动学习
主动学习旨在通过寻找最有信息的样本来解决标记数据的缺乏。然而,当…
arxiv.org](https://arxiv.org/abs/2010.08705)
这是我在过去两周从机器学习阅读中得到的另一个收获:要有创造力。在生活中,在工作中,更具体地说,创造性地使用你的主动学习的提问策略。
关于这一点,11 月见!
主动和半监督机器学习:9 月 14 日至 25 日
主动学习时事通讯
关于主动(偶尔半监督或弱监督)深度学习的最新 arXiv 预印本精选
前一期:
[## 主动和半监督机器学习:8 月 31 日至 9 月 11 日
关于主动(偶尔半监督或弱监督)深度学习的最新 arXiv 预印本精选
towardsdatascience.com](/active-and-semi-supervised-machine-learning-aug-31-sep-11-f985d593bd99)

我必须承认,我最近才接触到基于图形的机器学习,但它在半监督环境中的应用听起来很有趣。基本思想是数据(标记的和未标记的)由图中的节点表示,数据点之间的关系对应于图的边。在这篇来自 Google AI 的博文中,考虑了给单词分配情感标签的任务。首先,单词通过它们的嵌入来表示,然后基于不同嵌入向量之间的相似性来绘制边缘。这是半监督学习,一些节点被标记,但大多数没有。然后,标签(例如,“有趣”、“悲伤”等)在整个图表中传播,大致如下所示:

这是基本的想法,现在让我们回到过去两周 arXiv 的内容。基于图的半监督学习+卷积网络,生活(至少是机器学习工程师的生活)会变得更好吗?嗯,有可能!进入对比学习:
对比学习是一类自我监督的方法,它训练编码器在描述感兴趣的统计相关性的表示和不描述感兴趣的统计相关性的表示之间进行对比。
当涉及到监督任务(例如分类)时,普通的对比学习本身并不能帮助你。幸运的是,基于图的半监督学习的对比和生成图卷积网络的作者通过将关于可用标签的信息合并到损失函数中找到了一种解决方法:
[## 基于图的半监督学习的对比生成图卷积网络
基于图的半监督学习(SSL)旨在将少量已标记数据的标签转移到剩余的标签中
arxiv.org](https://arxiv.org/abs/2009.07111)
很好理解,最终,你的模型只能和你的数据一样好。除此之外,这意味着无论数据中存在什么样的偏差,它们都会成为模型的一部分。因此,如果你考虑我们的历史,难怪公平不仅是道德基础理论的六大支柱之一,也是人工智能领域活跃研究的主题。确定一个系统的公平性的指标往往是相当特别的,但通常相当于确定结果不应该依赖的某些特征,并确保情况确实如此。你知道,就像种族和性别对比一个人是否会被叫去参加工作面试之类的事情。无论如何,在有人监督和无人监督的情况下,这个主题的处理方式存在一定的差异,所以我很高兴看到半有人监督的社区也在研究这个问题:
[## 半监督学习中的公平性约束
机器学习中的公平性受到了相当大的关注。然而,大多数关于公平学习的研究都集中在…
arxiv.org](https://arxiv.org/abs/2009.06190)
许多不同的半监督学习方法的共同点是聚类的思想。您获取数据,将其分组,然后根据被注释的数据点分配标签。这个过程中有一个假设是我们在机器学习中经常想当然的:那就是拥有数据点。也就是说,独立的数据实例,而不是用一个更好的词来形容,数据块。但是,如果您处理的是顺序数据,该怎么办呢?例如,您的智能设备不断收集的关于您和您的环境的数据类型:例如,您的睡眠跟踪器。为了对这类数据执行聚类,首先需要将序列分解成片段。分割和标记都是昂贵的任务,因此显然需要适合处理序列数据的半监督方法。在通过变化点检测的半监督序列分类中,作者应用“变化点检测方法……识别序列中对应于可能类别变化的点”:
[## 基于变点检测的半监督序列分类
在各种各样的实际应用中产生顺序传感器数据。一个根本性的挑战包括…
arxiv.org](https://arxiv.org/abs/2009.11829)
以半监督方式训练的机器学习模型的性能通常很大程度上取决于已经被注释的训练样本的选择。然而,这些注释的质量同样重要:事实上,我们拥有的标记样本越少,它就越重要。在现实世界中,注释很难做到 100%准确,为了达到最终模型的最佳性能,必须处理这个问题。的作者用直推式半监督留一滤波器识别噪声标签提出了一种去除被认为可能不正确的标签的方法:
[## 用直推式半监督留一滤波器识别噪声标签
获取带有有意义标签的数据通常成本高昂且容易出错。在这种情况下,半监督学习…
arxiv.org](https://arxiv.org/abs/2009.11811)
在下一份预印本中,
[## 神经网络模型主动学习的模型中心和数据中心方面
我们用神经网络模型研究主动学习的以数据为中心和以模型为中心的不同方面。我)我们…
arxiv.org](https://arxiv.org/abs/2009.10835)
作者考虑了两种基于池的主动学习的训练方法:增量和累积。对于主动学习循环的每次迭代,增量训练对应于仅在新添加的标签上微调模型,而累积训练意味着我们从头开始在所有当前可用的标签上重新训练模型。在我自己的实现中,我实际上使用了两者之间的东西:微调模型而不是重新训练,但是是在整个更新的标签集上。我发现这个工作得相当好:
通过这个循序渐进的影像分类教程,了解如何节省高达 50%的数据标注成本
medium.com](https://medium.com/scaleway-cloud/active-learning-with-pytorch-dc6805956b0f)
但是,回到预印本!作者采用 MNIST 和时尚-MNIST 数据集,开始一次标记 120 张图像,并比较通过增量和累积训练方法获得的模型在三种查询策略下的性能:随机(本质上不是一种策略)、余量和熵不确定性采样。顺便说一句,如果你想知道后两者是什么,我可以让你感兴趣:
主动学习仍然是机器学习中的一种利基方法,但这种情况必将改变。
medium.com](https://medium.com/scaleway-cloud/active-learning-part-1-the-theory-239b7a43ddb5)
说到数据注释,我们通常是在标签之后。然而,注释者选择背后的推理可以提供对任务本质的有价值的洞察。这种信息不容易包含在机器学习过程中,这使得下面的工作更加有趣:
[## 爱丽丝:对比自然语言解释的主动学习
训练受监督的神经网络分类器通常需要许多带注释的训练样本。收集和…
arxiv.org](https://arxiv.org/abs/2009.10259)
爱丽丝到底是怎么运作的?假设你在为一个鸟类分类问题做主动学习。该模型将首先挑选出那些图像,对于这些图像,它很难在两个类别之间做出决定。(有点像边际抽样,只是在论文中,他们考虑的是特征空间中训练实例之间的距离,而不是模型预测的类别概率。)然后,它将要求注释者不仅标记图像,还要说明她如何区分这两个类:

这些信息将被解析成机器友好的形式,并用于提高模型的性能。
这是这两周对我来说最突出的预印本。你呢,这些引起你的注意了吗?我错过了什么吗?
十月中旬见!
主动和半监督机器学习:9 月 28 日至 10 月 9 日
主动学习时事通讯
关于主动(偶尔半监督或弱监督)深度学习的最新 arXiv 预印本精选
前一期:
关于主动(偶尔半监督或弱监督)深度学习的最新 arXiv 预印本精选
towardsdatascience.com](/active-and-semi-supervised-machine-learning-sep-14-25-93f19ff60fb1)

上周末是我过得特别无聊的一个周末:周六去了趟天文馆,然后疯狂观看了斯坦福 CS224W 课程讲座(T7)——强烈推荐,顺便说一句,你会获得疯狂观看的所有满足感,而没有任何负罪感。[完全披露:我坚信只要分心让你开心,就不要因为没有在你的待办事项清单上留下痕迹而责备自己。那只是很好的工作/生活平衡!请在评论中留下你对网飞的建议。]
说到用图表进行机器学习,我有另外几份关于这个主题的预印本给你:
[## 一种新的基于 GCNN 的半监督节点分类体系
存在于特定集群中的图的节点更有可能彼此连接,而不是与其他集群中的节点连接
arxiv.org](https://arxiv.org/abs/2009.13734)
和
[## 基于图的半监督学习中的标签噪声分析
在机器学习中,人们必须获得标签来帮助监督一个能够推广到看不见的数据的模型…
arxiv.org](https://arxiv.org/abs/2009.12966)
如果你对基于图的机器学习完全陌生,但不愿意观看所有 16 个半小时的讲座来开始学习,我建议看足够多的讲座 1 来了解什么是图,然后观看讲座 6 、 7 和 8 来了解如何将这种想法与机器学习模型联系起来。或者,这里是我的版本…
…简而言之,基于图的机器学习
把你拥有的每个数据点想象成一个图的节点。假设每个节点对应一个人的脸书档案。我们将在脸书上彼此是朋友的那些节点之间画边(即连接)。节点可以但不必须具有特征(例如,人的年龄、性别、自我描述的政治观点以及他们是否养猫)。现在让我们假设你想弄清楚一个给定的人是否可能支持 covid 强制封锁的想法。换句话说,一个二进制分类任务。(您可以标记那些在其配置文件中明确表示支持或鄙视锁定的节点,并训练它们。)如果你不想做任何花哨的图形,你可以简单地用你的训练数据所具有的特征来训练一个分类器。然而,你假设一个朋友中有很多禁闭支持者的人比脸书朋友圈中坚决反对呆在家里命令的人更有可能分享这些观点。如果我们能在我们的建模中包含这种关系信息就好了……等等,我们实际上可以:只要我们使用图(节点+它们与其他节点的连接)而不仅仅是节点作为我们模型的输入。

用图表,卢克!图片来源:giphy.com
这听起来可能很奇怪,但在某种程度上,你已经在做了。例如,考虑图像分类:一个 1024 x 1024 的图像可以被认为是一个网格——一个非常无聊的图形,除了图像边界之外,它恰好具有固定的大小和相同的拓扑结构。每个节点(像素)都有一组特征(定义像素的颜色)。将熟悉的 ML 概念从一个网格推广到一个任意复杂的图并不简单,但是可以做到。
对于那些已经精通使用图形进行机器学习的人来说,这里有一份大约两周前的数学含量更高的基于图形的预印本:
[## 参数 UMAP:学习嵌入深度神经网络的表现和…
我们提出了参数 UMAP,UMAP(统一流形近似和投影)的参数变化…
arxiv.org](https://arxiv.org/abs/2009.12981)
在半监督机制中训练的模型对选择哪些数据点是标记点高度敏感(事实上,优化这种选择是主动学习的中心目标)。因此,人们很容易把注意力集中在已标记子集的质量上,把我们得到的任何其他东西都扔进未标记的部分,让模型来处理它。然而,未标记训练样本中的非分布数据已经被证明对半监督模型的性能具有负面影响。当进行半监督机器学习时,未标记的训练集通常很大,仔细检查它以剔除任何不在分布范围内的点会违背最初的目的。以下预印本的作者通过利用批量标准化的方法解决了这个问题:
[## 具有非分布数据的鲁棒半监督学习
基于深度神经网络的半监督学习(SSL)最近被证明是有效的。然而,最近…
arxiv.org](https://arxiv.org/abs/2010.03658)
图像分割任务是常见的计算机视觉用例,需要特别耗时的数据注释:勾勒出一个对象或一组同类对象的边界(有时需要像素级的精度)。当涉及到数据注释时,时间当然等于金钱,所以任何可以加速这一过程的事情都有可能在未来产生巨大的影响(这是对自动驾驶汽车的一种尝试)。不出所料,有许多小组正在研究图像分割的弱监督学习。典型地,弱标签仅需要图像范围的注释,例如比分割掩模更容易获得的分类标签。在弱监督显著实例检测中,作者将类别标签与图像中存在的对象数量配对,以训练三分支分割网络来产生分割掩模:

图自 https://arxiv.org/pdf/2009.13898.pdf
[## 弱监督显著实例检测
现有的显著实例检测(SID)方法通常从像素级标注数据集学习。在本文中…
arxiv.org](https://arxiv.org/abs/2009.13898)
其他一些最近的弱监督图像分割预印本包括弱监督语义分割的因果干预
[## 弱监督语义分割的因果干预
我们提出了一个因果推理框架,以改善弱监督语义分割(WSSS)。具体来说,我们的目标是…
arxiv.org](https://arxiv.org/abs/2009.12547)
以及走向极端:弱监督医学图像分割,其中弱标记以器官表面上的极值点的形式出现,由注释者在 3D 医学图像中选择:
[## 走向极端:弱监督医学图像分割
医学图像标注是开发精确和鲁棒的机器学习模型的主要障碍。注释是…
arxiv.org](https://arxiv.org/abs/2009.11988)
最后,如果我们不谈论主动学习,这就不是一篇主动学习时事通讯;-)住在巴黎,我不可能传递一篇标题中有奥拉拉的论文:
[## OLALA:基于对象级主动学习的布局标注
在布局对象检测问题中,通过标注对象实例来构造真实数据集
arxiv.org](https://arxiv.org/abs/2010.01762)
文档布局检测是计算机视觉中的对象检测任务,其中所讨论的对象是文档图像中的不同内容区域。(自然地,大部分理论通常适用于物体检测。)当涉及到图像处理的主动学习时,查询通常在图像级完成,这意味着查询 oracle 来注释整个图像。然而,在某些类别的对象倾向于在同一幅图像中出现多次,而其他对象则不出现的用例中,图像级策略通常会导致训练集中常见对象的过度表示。对象级方法(也称为 OLALA)通过查询图像中选定对象的标签来避免这个问题。
回到图像分割的问题,主动学习当然是另一种减少选择分割模板所涉及的高数据注释成本的方法:
[## MetaBox+:一种新的基于区域的主动学习方法
提出了一种新的基于区域的主动学习语义图像分割方法,称为 MetaBox+。对于…
arxiv.org](https://arxiv.org/abs/2010.01884)
两周后见:)
主动学习教程—使用 Python 进行机器学习
这是一个 Python 主动学习的教程,对概念进行了解释,并对代码中的步骤进行了详细说明

作者图片
什么是主动学习?
主动学习是一种机器学习技术,其中我们使用较少的标记数据,并交互式地标记新的数据点,以提高模型的性能。
术语:
训练数据集=标记的数据点
池=未标记的数据点
我们从一些带标签的数据点(训练数据集)开始。有大量未标记的数据点。这些未标记的数据点必须被标记并添加到训练数据集中以创建模型。然而,在主动学习中,我们将只标记一小部分数据点,而不是标记池中的所有数据点,但是仍然可以获得良好的性能。
我们创建一个模型(分类器),并根据标记的数据对其进行训练。然后,我们检查池中的所有数据点,识别分类器最不明确的点,并将这些点添加到训练数据中(我们每次可能只添加一个点)。我们重复这个过程来提高模型性能。这种技术通常在贴标成本较高时使用。
我将很快在 YouTube 上传一段视频,详细解释主动学习背后的概念。

主动学习和其他采样新数据点进行标记的方法的性能改进比较—图片由基金会提供
主要代码
在这里,我们导入所需的库:
pandas —处理数据
sklearn —用于 SVM 模型
numpy —用于矩阵和数组操作
matplotlib.pyplot —用于图形绘制
imageio —制作 gif
OS—创建文件夹并检查它们的内容
from sklearn.svm import SVC, LinearSVC
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
import imageio as io
import os
这里,我们从 CSV 文件中读取数据。该数据可在 Kaggle 上获得。
origdata = pd.read_csv("Iris.csv")
origdata[:10]

单元格输出:虹膜数据集预览-作者提供的图像
该数据集包含关于鸢尾花的 3 个种/亚种的数据。每个样本都有萼片的长度、萼片的宽度、花瓣的长度和花瓣的宽度,都以厘米为单位。每个样本都是这三种鸢尾中的一种——刚毛鸢尾、杂色鸢尾和海滨鸢尾。
我们从数据集中选择两个属性(列)来执行主动学习。我们选择了两列,因为这样很容易将 2D 数据可视化。但是注意,只取 2 列未必比取所有列用于机器学习或主动学习更好。
k1, k2 = 'PetalLengthCm', 'PetalWidthCm'
data = origdata[[k1, k2, 'Species']].copy()
data[:10]

仅包含选定列的 Iris 数据集-按作者分类的图像
对于训练数据,我们采用前面选择的两列。物种栏是标签。我们将标签更改为 0(鸢尾-刚毛鸢尾)、1(鸢尾-杂色)和 2(鸢尾-海滨鸢尾)。
X = data[[k1, k2]]
y = data['Species']
print('Classes:')
print(y.unique(), '\n\n\n')
y[y=='Iris-setosa'] = 0
y[y=='Iris-versicolor'] = 1
y[y=='Iris-virginica'] = 2
输出:
Classes: ['Iris-setosa' 'Iris-versicolor' 'Iris-virginica']
我们在 2D 图上绘制了云芝和海滨锦葵的样本,云芝用红色,海滨锦葵用青色。
plt.figure()
setosa = y == 0
versicolor = y == 1
virginica = y == 2
plt.scatter(X[k1][versicolor], X[k2][versicolor], c='r')
plt.scatter(X[k1][virginica], X[k2][virginica], c='c')
plt.xlabel(k1)
plt.ylabel(k2)
plt.show()
输出:

杂色-红色;Virginica-青色——作者图片
我们丢弃鸢尾的样本。
X1 = X[y != 0]
y1 = y[y != 0]
X1[:5]
输出:

注意,数据帧的行从 50 开始,而不是从 0 开始。这里的索引不是从 0 开始,因为 0–49 索引行包含鸢尾花的数据,50–149 索引行包含其他两种花的数据——按作者分类的图像
然后,我们重置数据帧的索引。
X1 = X1.reset_index(drop=True)
y1 = y1.reset_index(drop=True)
y1 -= 1
print(y1.unique())
X1[:5]
输出:
[0 1]

重置索引后的数据帧-作者图片
我们将数据绘制在 2D 图上,并将图形保存为“main.jpg”。
fig = plt.figure()
plt.scatter(X1[k1][y1==0], X1[k2][y1==0], c='r')
plt.scatter(X1[k1][y1==1], X1[k2][y1==1], c='c')
plt.xlabel(k1)
plt.ylabel(k2)
fig.savefig('main.jpg', dpi=100)
plt.show()

我们在全部数据上训练线性 SVM 核,以理解当使用全部数据时我们将得到的 SVM 模型。由于这是一个线性 SVM 模型,决策边界(分隔两个类别的边界)将是一条直线。我们看决策边界的斜率和截距。
y1 = y1.astype(dtype=np.uint8)clf0 = LinearSVC()
clf0.fit(X1, y1)LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,
intercept_scaling=1, loss='squared_hinge', max_iter=1000,
multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,
verbose=0)print(clf0.coef_)
print(clf0.intercept_)
输出
[[0.2801542 1.70097577]]
[-4.17110884]
这里,我们绘制了决策边界以及所有数据点。在这种情况下,决策边界是一条直线(因为模型是线性 SVM)。clf0是受过训练的量词(SVM)。我们从clf0.coef_和clf0.intercept得到系数。a0, b0, c0是线的系数(线方程:a0*x + b0*y + c0 = 0; y = -(a0*x + c0)/b0)。我们在这条线上得到 100 个点(lx0- has the x-corrdinates; ly0- has the y-coordinates)并绘制它们(一条洋红色的线)。让我们称之为理想决策边界(当我们使用不同种类的 SVM 核时,这可能不是所有 SVM 的理想决策边界,但是,它确实是一个好的决策边界)。
然后,我们根据类别用青色和红色绘制数据集中的所有点。
xmin, xmax = X1[k1].min(), X1[k1].max()
ymin, ymax = X1[k2].min(), X1[k2].max()
stepx = (xmax - xmin)/99
stepy = (ymax - ymin)/99a0, b0, c0 = clf0.coef_[0, 0], clf0.coef_[0, 1], clf0.intercept_# Formula for reference
# a*x + b*y + c = 0
# y = -(a*x + c)/b
lx0 = [xmin + stepx * i for i in range(100)]
ly0 = [-(a0*lx0[i] + c0)/b0 for i in range(100)]
plt.figure()
plt.scatter(X1[k1][y1==0], X1[k2][y1==0], c='r')
plt.scatter(X1[k1][y1==1], X1[k2][y1==1], c='c')
plt.plot(lx0, ly0, c='m')
plt.xlabel(k1)
plt.ylabel(k2)
plt.show()

紫线是 SVM 模型的决策边界。红色和青色点是两个类别。
现在,我们将数据集分成两部分—池(80%)和测试(20%)。我们使用随机状态 1。数据集的分割取决于随机状态。
(我做过随机状态为 1 后主动学习 5 次迭代和随机状态为 2 后主动学习算法 20 次迭代的仿真)。
X_pool, X_test, y_pool, y_test = train_test_split(X1, y1, test_size=0.2, random_state=1)
X_pool, X_test, y_pool, y_test = X_pool.reset_index(drop=True), X_test.reset_index(drop=True), y_pool.reset_index(drop=True), y_test.reset_index(drop=True)
# random state 1 5 iterations
# random state 2 20 iterations
让我们对两个数据点应用 SVM 的判定函数。通常,对于两类线性 SVM,决策函数为其中一类(决策边界的一侧)输出正值,为另一类(决策边界的另一侧)输出负值,并在决策边界上输出零。
对于线性 SVM,决策函数的大小等于数据点到决策函数的距离。这是因为,如果一个点靠近决策边界,那么它可能是决策边界另一侧的类的异常值。
clf0.decision_function(X_pool.iloc[6:8])
输出
array([-0.55706427, 0.26340314])
这里,我们看到决策函数对于其中一个点具有负值,对于另一个点具有正值。
函数find_most_ambiguous给出了分类器最不明确的点。对于 SVM 分类器,如果数据点更接近决策边界,并且如果数据点更远离决策边界,则不那么模糊,而不管该点在决策边界的哪一侧。因此,find_most_ambiguous给出了最接近决策边界的未标记点。
clf- classifier (trained SVM model); unknown_indexes- indexes from the dataset that are the unlabelled/unknown pool
def find_most_ambiguous(clf, unknown_indexes):
ind = np.argmin(np.abs(
list(clf0.decision_function(X_pool.iloc[unknown_indexes]) )
))
return unknown_indexes[ind]
函数plot_svm用于绘制以下内容:
SVM 判定边界、根据分类来自列车数据的数据点以及未知样本池中的数据点。
clf- classifier (trained SVM model).
train_indexes- Indexes of the dataset that are the train data points. unknown_indexes- Indexes of the dataset that are the unlabelled pool data points. title- The title of the plot. name- the name of the image file that when the plot is saved to a file. new_index- This is the index of the most ambiguous point in the unlabelled pool
在这个函数中,首先,我们分别从train_indexes和unknown_indexes获取列车数据(X_train, y_train)和未标记数据(X_unk, y_unk)。我们用黑色标出了池中所有未标记的点。然后,我们根据分类标签,用不同的颜色(红色和青色)绘制来自训练数据的所有点。我们从 clf.coef_ 和 clf.intercept 中得到决策边界(直线)的系数,利用这个和直线的公式,我们画出这条线(绿色虚线)。我们还有前面计算的理想决策边界。这条线也用洋红色标出。
最后,我们绘制出new_index点,也就是最模糊的点(黄星)。
def plot_svm(clf, train_indexes, unknown_indexes, new_index = False, title = False, name = False):
X_train = X_pool.iloc[train_indexes]
y_train = y_pool.iloc[train_indexes]
X_unk = X_pool.iloc[unknown_indexes]
if new_index:
X_new = X_pool.iloc[new_index]
a, b, c = clf.coef_[0, 0], clf.coef_[0, 1], clf.intercept_ # Straight Line Formula
# a*x + b*y + c = 0
# y = -(a*x + c)/b
lx = [xmin + stepx * i for i in range(100)]
ly = [-(a*lx[i] + c)/b for i in range(100)]
fig = plt.figure(figsize=(9,6))
# plt.scatter(x[k1][setosa], x[k2][setosa], c='r')
plt.scatter(X_unk[k1], X_unk[k2], c='k', marker = '.')
plt.scatter(X_train[k1][y_train==0], X_train[k2][y_train==0], c='r', marker = 'o')
plt.scatter(X_train[k1][y_train==1], X_train[k2][y_train==1], c='c', marker = 'o')
plt.plot(lx, ly, c='m')
plt.plot(lx0, ly0, '--', c='g')
if new_index:
plt.scatter(X_new[k1], X_new[k2], c='y', marker="*", s=125)
plt.scatter(X_new[k1], X_new[k2], c='y', marker="*", s=125)
plt.scatter(X_new[k1], X_new[k2], c='y', marker="*", s=125)
plt.scatter(X_new[k1], X_new[k2], c='y', marker="*", s=125)
plt.scatter(X_new[k1], X_new[k2], c='y', marker="*", s=125)
if title:
plt.title(title)
plt.xlabel(k1)
plt.ylabel(k2)
if name:
fig.set_size_inches((9,6))
plt.savefig(name, dpi=100)
plt.show()
我们将集合的前 10 个指数/数据点作为初始训练数据,其余 70 个点作为未标记的样本。我们用所有未标记的样本、理想决策边界和 10 个训练数据点创建开始图。
然后,我们在训练数据上训练一个 SVM,我们找到最不明确的点并创建一个新的图(“迭代 0”),用这个点作为一个黄色的星,并且还绘制训练的 SVM 的决策边界。
train_indexes = list(range(10))
unknown_indexes = list(range(10, 80))
X_train = X_pool.iloc[train_indexes]
y_train = y_pool.iloc[train_indexes]
clf = LinearSVC()
clf.fit(X_train, y_train)
# folder = "rs1it5/"
folder = "rs2it20/"
# folder = "rs1it20/"
try:
os.mkdir(folder)
except:
pass
filenames = ["ActiveLearningTitleSlide2.jpg"] * 2
title = "Beginning"
# name = folder + ("rs1it5_0a.jpg")
name = folder + ("rs2it20_0a.jpg")
plot_svm(clf, train_indexes, unknown_indexes, False, title, name)
filenames.append(name)
n = find_most_ambiguous(clf, unknown_indexes)
unknown_indexes.remove(n)
title = "Iteration 0"
name = folder + ("rs1it5_0b.jpg")
# name = folder + ("rs2it20_0b.jpg")
filenames.append(name)
plot_svm(clf, train_indexes, unknown_indexes, n, title, name)


接下来,我们运行主动学习算法 5 次迭代。在每一个阶段中,我们将最模糊的点添加到训练数据中,并训练一个 SVM,在这个阶段找到最明确的点,然后创建一个图。
num = 5
# num = 20
t = []
for i in range(num):
train_indexes.append(n)
X_train = X_pool.iloc[train_indexes]
y_train = y_pool.iloc[train_indexes]
clf = LinearSVC()
clf.fit(X_train, y_train)
title, name = "Iteration "+str(i+1), folder + ("rs1it5_%d.jpg" % (i+1))
# title, name = "Iteration "+str(i+1), folder + ("rs2it20_%d.jpg" % (i+1))
n = find_most_ambiguous(clf, unknown_indexes)
unknown_indexes.remove(n)
plot_svm(clf, train_indexes, unknown_indexes, n, title, name)
filenames.append(name)





images = []
for filename in filenames:
images.append(io.imread(filename))
io.mimsave('rs1it5.gif', images, duration = 1)
# io.mimsave('rs2it20.gif', images, duration = 1)
# io.mimsave('rs1it20.gif', images, duration = 1)
try:
os.mkdir('rs1it5')
# os.mkdir('rt2it20')
except:
pass
os.listdir('rs1it5')
输出
['ActiveLearningTitleSlide2.jpg',
'ActiveLearningTitleSlide2.jpg',
'rs1it5/rs1it5_0a.jpg',
'rs1it5/rs1it5_0b.jpg',
'rs1it5/rs1it5_1.jpg',
'rs1it5/rs1it5_2.jpg',
'rs1it5/rs1it5_3.jpg',
'rs1it5/rs1it5_4.jpg',
'rs1it5/rs1it5_5.jpg']
现在,我们显示 GIF 文件
with open('rs1it5.gif','rb') as f:
display(Image(data=f.read(), format='gif'))

请注意,在上面的 GIF 中,随着我们添加更多的点(迭代次数),绿线越来越接近理想决策边界。
请注意,在上面的一些代码块和下面的代码块中,有一些带有数字 20 的注释行。这是为了运行 20 次迭代,而不是 5 次迭代。要运行它,我们必须用 5 注释所有的行,用 20 取消注释所有的行。 当我们运行 20 次主动学习算法的迭代时,我们得到下面的 GIF。请注意,为此,我们在将数据分为测试和池时使用了 2 作为随机状态。
注意,随着下面 GIF 中迭代次数的增加,绿线越来越接近理想决策边界。

注意,主动学习可以用于其他机器学习/深度学习模型(不仅仅是支持向量机)。
另外,第一个ActiveLearningTitleSlide2.jpg是我用画图工具创建的一个简单的图像,和其他图像的长宽比一样(900x600)。
结论
我们看到,我们已经训练了一个好的分类器,也就是说,一个分类器的性能接近用所有点训练的 SVM,尽管我们使用了非常少量的点。这就是如何使用主动学习来创建标记更少数据点的健壮模型。
完整的代码可以在 GitHub 上获得
你可以看看我的 YouTube 频道上解释 AI 和 ML 概念的视频。
有效数据标注策略的主动学习
通过将手动干预限制在信息量最大的样本,降低数据注释成本。

Taton moise 在 Unsplash 上拍摄的照片
我相信数据注释的质量和数量通常是机器学习应用程序成功的最决定性因素。然而,手动数据注释可能非常慢且成本高。这就是为什么有很多关于减少手动注释需求的方法的研究工作,如迁移学习或无监督预训练。
另一种降低数据标注成本的方法是使用主动学习。它是一组方法,将数据注释步骤呈现为学习算法和用户之间的交互过程,其中当用户注释那些选择的样本时,算法建议哪些示例值得注释。
在这篇文章中,我们将尝试探索应用于麻省理工学院-BIH 心律失常和 MNIST 数据集的基于不确定性的主动学习方法。
由于标注可能非常昂贵,有时需要领域专家,我们将仅模拟用户交互过程,从标记数据集的一个小子集开始,随后仅使用算法建议的有价值的样本标签。
流程描述:

基于不确定性的主动学习
步骤:
1 —从一小批带注释的 start_size = 512 示例开始
2 —在初始批次上训练分类模型。
3-对于 n 个步骤,do :
-使用熵形式的不确定性选择下一批最有希望的大小为 batch_size 的样本,其中,您将根据样本的预测熵对样本进行排序,并且仅挑选具有最高熵的顶部 batch_size 样本。
-根据目前选择的所有数据训练模型。
-在测试集上评估模型。
实验:

麻省理工学院-BIH 心律失常的主动学习与随机抽样
在麻省理工学院-BIH 心律失常数据集上,使用全部约 3000 个标记样本进行训练,我们得到:
-主动学习策略: 0.80 F1 分数
-随机策略: 0.74 F1 分数
为了获得 0.74 分的 F1 分,主动学习策略只需要大约 2000 个带标签的例子,或者 3000 分中的 2/3

MNIST 上的主动学习与随机抽样
在 MNIST 数据集上,使用全部约 1400 个标记样本进行训练,我们得到:
-主动学习策略: 0.98 F1 得分
-随机策略: 0.96 F1 得分
为了达到 0.96 分的分数F1 分,主动学习策略只需要大约 700 个带标签的例子或者 1400 个例子的一半
请注意,图中显示的性能是 10 次独立运行的平均值,以减少随机性造成的影响。
还要注意,我用 CIFAR10 而不是 MNIST 做了完全相同的实验,但效果不是很好。我仍然不明白为什么,但这是未来☺值得关注的事情。
结论:
在这篇文章中,我们应用了基于不确定性的主动学习的简化实现。模拟结果看起来令人鼓舞,证明了主动学习可以帮助减少实现良好测试性能所需的手动标签数量。
代码重现结果:https://github.com/CVxTz/active_learning
机器学习中的主动学习
浅谈主动学习的实施

马库斯·斯皮斯克在 Unsplash 上的照片
大多数有监督的机器学习模型需要大量的数据才能训练出好的结果。即使这种说法听起来很天真,大多数公司都很难向他们的数据科学家提供这些数据,特别是标有的数据。后者是训练任何监督模型的关键,并且可能成为任何数据团队的主要瓶颈。
在大多数情况下,数据科学家会被提供一个庞大的、未标记的数据集,并被要求用它们来训练性能良好的模型。通常,数据量太大而无法手动标记,对于数据团队来说,用这些数据训练良好的监督模型变得相当具有挑战性。
主动学习:动机
主动学习是用于对需要被标记的数据进行优先排序的过程的名称,以便对训练监督模型具有最高的影响。主动学习可以用在数据量太大而无法标记的情况下,并且需要制定一些优先级来以智能方式标记数据。
但是,为什么我们不选择一个随机的数据子集来手动标记它们呢?
让我们看一个非常简单的例子来激发讨论。假设我们有数百万个数据点,需要根据两个特征进行分类。实际解决方案如下图所示:

如果标记了所有数据点,则进行模型预测
正如你所看到的,这两个类(红色和紫色)可以很好地被一条垂直的蓝线 0 分开。问题是这些数据点都没有被标记,所以我们得到的数据如下图所示:

未标记的数据
不幸的是,我们没有足够的时间来标记所有的数据,我们随机选择了一个数据子集来标记和训练一个二元分类模型。结果不是很好,因为模型预测偏离最佳边界相当多。

根据标记数据点的随机子集训练的模型
在这种情况下,可以使用主动学习来优化选择用于标记的数据点,并基于这些数据点训练模型。下面的图显示了在基于实施主动学习之后标记的数据点选择模型的训练之后训练二元分类模型的示例。

使用主动学习在选择要标记的数据点子集上训练模型
在标记时,明智地选择优先处理哪些数据点可以为数据科学团队节省大量时间、计算和麻烦!
主动学习策略
主动学习的步骤
文献中研究了多种方法,涉及如何在标记时区分数据点的优先级以及如何迭代该方法。然而,我们将只介绍最常见和最简单的方法。
在未标记的数据集上使用主动学习的步骤是:
- 首先需要做的是,需要手工标记该数据的一个非常小的子样本。
- 一旦有了少量的标记数据,就需要对模型进行训练。该模型当然不会很好,但会帮助我们了解参数空间的哪些区域需要首先标记以改进它。
- 在训练该模型之后,该模型用于预测每个剩余的未标记数据点的类别。
- 基于模型的预测,在每个未标记的数据点上选择分数。在下一小节中,我们将介绍一些最常用的可能得分。
- 一旦选择了最佳方法来对标记进行优先级排序,就可以反复重复该过程:可以在新的标记数据集上训练新的模型,该数据集已经基于优先级分数进行了标记。一旦在数据子集上训练了新的模型,未标记的数据点可以在模型中运行,以更新优先排序分数,从而继续标记。这样,随着模型变得越来越好,人们可以不断优化标记策略。
优先级分数
有几种方法可以为每个数据点分配优先级分数。下面我们描述三个基本的。
最不可信:
这可能是最简单的方法。它为每个数据点的预测取最高概率,并从小到大排序。使用最小置信度进行优先级排序的实际表达式是:


让我们用一个例子来看看这是如何工作的。假设我们有以下三个可能类别的数据:

表 1:模型对四个不同数据点的三个不同类别的概率预测示例。
在这种情况下,算法将首先为每个数据点选择最大概率,因此:
- X1: 0.9
- X2: 0.87
- X3:0.5
- X4:0.99。
第二步是根据这个最大概率(从小到大)对数据进行排序,因此是 X3、X2、X1 和 X4。
保证金取样:
该方法考虑了最高概率和第二高概率之间的差异。从形式上看,区分优先级的表达式应该是这样的:

具有较低边缘采样分数的数据点将被标记为第一个;这些数据点是模型最不确定的,介于最可能的类和次最可能的类之间。
按照表 1 的例子,每个数据点的相应分数是:
- x1:0.9–0.07 = 0.83
- X2:0.87–0.1 = 0.86
- X3:0.5–0.3 = 0.2
- x4:0.99–0.01 = 0.98
因此,数据点将显示为标记如下:X3、X1、X2 和 X4。可以看出,这种情况下的优先级与最不自信的优先级略有不同。
熵:
最后,我们要展示的最后一个评分函数是熵值。熵是一个来自热力学的概念;简单地说,它可以被理解为一个系统中无序度的度量,例如一个封闭盒子中的气体。熵越高,无序越多,而如果熵低,这意味着气体可能主要在一个特定的区域,比如盒子的一个角落(可能在实验开始时,在扩展到整个盒子之前)。
这个概念可以被重用来度量模型的确定性。如果模型对于给定数据点的某个类别非常确定,那么它对于某个特定类别可能具有高确定性,而所有其他类别将具有低概率。这不就和盒子角落里有气体很像吗?在这种情况下,我们将大部分概率分配给特定的类。在高熵的情况下,这意味着模型为所有类别平均分配概率,因为根本不确定该数据点属于哪个类别,类似于使气体平均分布在盒子的所有部分。因此,将具有较高熵的数据点优先于具有较低熵的数据点是很简单的。
形式上,我们可以将熵值优先级定义如下:

如果我们将熵值应用于表 1 中的示例:
- x1:-0.9 * log(0.9)-0.07 * log(0.07)-0.03 * log(0.03)= 0.386
- X2:-0.87 * log(0.87)-0.03 * log(0.03)-0.1 * log(0.1)= 0.457
- X3:-0.2 * log(0.2)-0.5 * log(0.5)-0.3 * log(0.3)= 1.03
- x4:-0 * log(0)-0.01 * log(0.01)-0.99 * log(0.99)= 0.056
注意,对于 X4,为了数值稳定性,应将 0 改为小ε(例如 0.00001)。
在这种情况下,数据点应按以下顺序显示:X3、X2、X1 和 X4,这与最不自信评分法的顺序一致!
主动学习:机器和人一起工作
使用较少标记数据训练 ML 模型的工具

安迪·凯利的照片
M 在过去的几十年里,机器学习(ML)已经彻底改变了世界,受益于不断增长的计算能力,以解决不久前还无法解决的问题。然而,尽管有其潜力,许多技术和实践的挑战面临着那些与 ML。
特别是,生成用于训练模型的数据的必要工作正在成为一个复杂的问题。鉴于我们目前试图解决的问题的复杂性和规模,标记必要的数据成为一项费力且昂贵的任务,因为大部分过程必须手动完成。在处理需要高度专业化的问题时,这个问题甚至更为关键。例如,为了使用深度神经网络从 MRI 扫描中检测疾病,在诊断这种图像方面经验丰富的医生必须对成千上万个样本进行分类。鉴于此,开发提高数据集标注工作流效率的方法变得至关重要。
一个有效的选择是部分或完全自动化贴标过程。然而,当考虑复杂和高维数据时,标注工作流中没有多少可以自动化(如果您有一个能够自动标注数据的系统,问题就解决了,并且无论如何都不需要训练 ML 模型)。
另一种方法包括以某种方式减小数据集的大小。尽管我们知道复杂的问题需要大量的数据集,但事实上并不是所有的例子对学习模型都有意义。因此,只选择信息量最大的例子进行标注,可以让我们在从较少的例子中学习的同时,获得一个好的模型。
主动学习是一个依赖于这种想法的框架,其中模型选择最具信息量的未标记样本,然后要求外部专家(通常称为 oracle)只标记这些样本。主动学习被一些作者归类为半监督学习框架,因为它在训练模型时使用标记和未标记的数据。与 oracle 的交互是迭代的,在每次迭代中都有新的未标记的示例提供给 oracle。
在[1]中,Burr Settles 提出了一个关于主动学习的广泛调查。他用直观的方式总结了背后的概念:
“关键的假设是,如果允许学习算法选择它学习的数据——如果你愿意的话,可以说是“好奇”——它将在更少的训练下表现得更好。”[1]
接下来将展示两个有趣的主动学习应用。
情感分析中的主动学习

照片由 M. B. M.
情感分析是自然语言处理领域的一个重要应用。它侧重于根据作者表达的态度对文本进行分类。尽管看起来像一个简单的任务,但它通常是 ML 模型很难处理的事情,因为文本中的细微变化可能会给读者带来完全不同的含义。
在[2]中,作者将主动学习应用于情感分析问题,提出了一种称为主动深度网络(ADN)的算法,这是主动学习和深度神经网络的结合。结果真的很有趣,因为这种方法不仅使用了更少的例子来学习,而且它优于当时被认为是最先进的其他知名模型。
“[……]ADN 可以根据现有的未标记和已标记数据,做出应该标记哪些训练数据的正确决定。通过迭代使用无监督和有监督学习,ADN 可以选择合适的训练数据进行标记,同时训练深度架构。面向情感分析的主动学习”
用于高光谱图像分类的主动深度学习
高光谱图像是电磁波谱中光谱响应的表示。它由代表特定电磁波长测量值的若干空间图像组成,用于从天文学到生物医学的不同应用。由于通常表示的不同波长的范围很大,数据变得高维。例如,NASA AVIRIS(机载可见/红外成像光谱仪)捕获的单个图像可以包含高达 140MB 的原始数据[3]。

超光谱立方体的 2D 投影。Nicholas M. Short 博士,美国航天局
对于主动学习来说,这是一个很好的应用,因为对这样的图像进行分类是一项长期的任务,需要对应用程序有深入的了解。在[4]中,作者提出了一种称为 WI-DL 的主动学习算法,使用具有 4 个隐藏层的深度信念网络。该模型仅用 5000 个标记样本就达到了接近 95%的准确率,表明通过主动选择相关训练样本,可以在使用较少数据的情况下训练出准确的模型。
结论
对于机器学习应用来说,为复杂和高维问题产生高质量的数据集已经是一个挑战。在这里,一个称为主动学习的框架与两个相关的应用一起被提出。尽管允许减少标记示例的数量,但是主动学习并不是给定问题的最终解决方案,因为仍然需要人类来负责人工标记。同样重要的是要注意,oracle 必须包含在训练循环中,等待算法在每次新的迭代中提供新的未标记样本。取决于应用,这是一个可能不方便或难以实现的工作流程。
参考
[1]落定,伯尔。主动学习文献调查。威斯康星大学麦迪逊分校计算机科学系,2009 年。
[2]周,舒森,,陈,.“用于半监督情感分类的主动深度网络。”第 23 届国际计算语言学会议录:海报。计算语言学协会,2010 年。
[3] Cheung、Ngai-Man 和 Antonio Ortega。"超光谱图像的分布式压缩."分布式源代码(2009):269–292。
[4]刘,彭,,朱光耀."高光谱图像分类的主动深度学习."IEEE 应用地球观测和遥感专题期刊 10.2(2016):712–724。
主动学习——说是!

安妮·斯普拉特在 Unsplash 上的照片
机器学习这个,机器学习那个!你知道该怎么做。让我们来谈一个人们此刻只在窃窃私语的话题,主动学习。
主动学习是人工智能的一个子领域,它基于这样一个事实,即好奇的算法在效率和表达能力方面都是更好的学习者。核心思想是让算法挑选样本进行训练,而不是在所有可用的训练数据上训练模型。
主动学习场景
主动学习可能是人工智能领域最简单的想法之一。这个想法有多种变化,但都有明确的主题。
让模型挑选训练数据
“让模型挑选训练数据”这句话可能意味着几件事。
- 让模型创建训练数据(创成式模型)
- 让模型从未标记的数据流中挑选一个例子
- 让模型从一堆未标记的数据中挑选一个例子
生成模型可能有些棘手,因为人类注释者可能很难标记数据,这违背了主动学习的目的。
一般来说,在实际设置中,模型从一个未标记的数据流/数据池中挑选例子,由人类注释者进行标记。
主动学习策略
这一节我们来讨论几个主动学习策略。
不确定抽样
这种策略通常用于概率模型。可以用一个简单的流程图来概括。

不确定性采样流程图。[使用 code2flow 生成]
除了“标记最不确定的例子”这一步,上面的流程图几乎是不言自明的。
让我们考虑一个将新闻分为 7 类的工作示例。我们有:-
- 一套小型训练设备
- 在带标签的训练集上训练的简单模型
- 一大群没有标记的人
让我们预测 10 个未标记的样本中所有类别的概率。

10 个未标记样本的分类概率。[作者图片]
- 选择一个最大概率类别值最小的例子
直觉告诉我们,如果模型对某个示例的顶部预测没有信心,那么该示例就相当困难,或者可能与模型已经看到的不同。

例 5 具有最大的不确定性。[作者图片]
在上面的示例中,我们看到模型对第 5 个示例的顶部预测最没有信心。
2.挑选一个前两个类别之间差异最小的例子
直觉是,如果前两个预测之间的差异较小,那么模型一定是在两个类别之间混淆了。一个好的模型应该能够尽可能地分离类别,因此,在训练数据中考虑该示例是很重要的。

前两类的区别。[作者图片]
3.利用熵测量不确定度
维基百科定义的熵是 变量可能结果中固有的“信息”、“惊喜”或“不确定性”的平均水平。 如果预测概率具有高熵,则意味着模型对某个例子感到困惑。

计算预测概率的熵。[作者图片]
委员会的质询
就整个过程而言,按委员会查询也非常类似于不确定性抽样。唯一的区别是我们如何选择最不确定的例子。在不确定性采样中,我们训练单个模型,并使用其输出概率来推断不确定性并挑选示例。
在按委员会查询中,我们创建不同类型模型的委员会,并在训练集上训练它们。当选择看不见的例子时,我们从所有例子的所有模型中得到预测。这些模型在很大程度上不一致的示例是困难的示例,应该出现在训练数据中。
不同类型的模型(线性、树、邻居、贝叶斯)确保我们的查询策略不会受到单一类型的建模假设的影响,因此性能良好。

创建一个由 7 名分类员组成的委员会。[作者图片]

例 5 不同型号之间分歧最大。[作者图片]
主动学习的好处
在文章的开始,我提到了主动学习提高了模型的效率和表达能力。
与学术界相反,行业从业者必须处理非标准数据集和问题
因此,任何 ML 项目的很大一部分都花费在获得正确的训练数据集上。人类注释者花费他们宝贵的时间来标记数据集进行训练,这是最大的开销和低效点。 主动学习法保证了标注者只标注最重要、最难的例子,从而使整个过程更加高效。
当一个大数据集被无意识地标记时,它会带来不想要的类别不平衡,并冒着丢失尚未标记的重要示例的风险。
通过使用主动学习,我们挑选最有趣和最多样的例子,从而提高模型的表达能力。在这里,通过表达能力,我的意思是这个过程从大量未标记的数据中引出更多种类的要标记的例子,这些数据在无意识标记的情况下会保持未标记。
所以如果都是金子和闪闪发光的东西,为什么我们不在这里谈论它呢?
杰瑞米·霍华德在他出现在莱克斯·弗里德曼的播客中非常出色地抓住了这一点。
结论
主动学习,在我看来,是人工智能领域最接近于一顿“免费午餐”的事情。这个概念非常简单,其好处远远超过创建和管理培训数据的任何其他方法。虽然这不是一个非常著名的子领域,但令人敬畏的 python 社区已经创建了一些包,将主动学习的力量带给每个人。
参考
TensorFlow 2.x 的演员兼评论家[第 1 部分,共 2 部分]
使用 Tensorflow 2.x 以不同方式实现参与者-批评家方法

戴维·维克斯列尔在 Unsplash 上的照片
在这一系列文章中,我们将试图理解演员-评论家方法,并以 3 种方式实现它,即天真的 AC,没有多个工人的 A2C,和有多个工人的 A2C。
这是系列的第一部分,我们将使用 TensorFlow 2.2 实现天真的演员评论家。我们先来了解一下演员-评论家法是什么,是如何运作的?了解加强政策梯度方法将是有益的,你可以在这里找到它。
概述:
如果你读过加强政策梯度法,你就会知道它的更新规则是

更新加固规则
在演员-评论家方法中,我们从折扣奖励中减去基线。这些方法的常用基线是状态值函数。所以我们的演员-评论家更新规则将如下所示。


演员-评论家更新规则
在演员-评论家方法中,我们有两个神经网络,即演员和评论家。actor 用于动作选择,Critic 用于计算状态值。如果您查看更新等式,您会注意到状态值被用作基线。有了基线有助于确定所采取的行动是坏的/好的,还是状态是坏的/好的。您可以在参考资料部分找到非常好的理论资源。
天真的演员兼评论家:
在这个实现中,我们将在每个时间戳更新我们的神经网络。这种实现不同于 A2C,在那里我们在每 n 个时间戳之后更新我们的网络。我们将在本系列的下一部分实现 A2C。
神经网络:
神经网络基本上可以用两种方式实现。
- 一个网络用于演员和评论家功能,即一个网络具有两个输出层,一个用于状态值,另一个用于动作概率。
- 独立的网络,一个是演员的,另一个是评论家的。
在这篇文章中,我们将对演员和评论家使用不同的网络,因为我发现这个可以快速学习。
代码:
演员和评论家网络:
- 批评家网络输出每个状态的一个值,而行动者网络输出该状态中每个单个动作的概率。
- 这里,演员网络中的 4 个神经元是动作的数量。
- 注意,Actor 在外层有一个 softmax 函数,它输出每个动作的动作概率。
注意:隐藏层中的神经元数量对于代理学习非常重要,并且因环境而异。
代理类的初始化方法:
- 这里,我们为我们的网络初始化优化器。请 注意学习的****速度也很重要,并且会因使用的环境和方法而异。
动作选择:
- 这种方法利用了张量流概率库。
- 首先,Actor 给出概率,然后使用 TensorFlow 概率库将概率转换成分布,然后从分布中抽取动作。
学习功能和损失:
- 我们将利用梯度胶带技术进行定制培训。
- 行动者损失是采取行动的对数概率乘以 q 学习中使用的时间差的负数。
- 对于临界损失,我们采取了一种简单的方法,只计算时间差的平方。如果你愿意,你可以使用 tf2 的均方误差函数,但是你需要对时差计算做一些修改。我们将在本系列的下一部分中使用 MSE,所以不要担心。
- 你可以在 TensorFlow 官网找到更多关于定制训练循环的内容。
注意:请确保使用语句(上下文管理器)调用 networks inside,并且只使用张量进行网络预测,否则您将得到一个关于没有提供梯度的错误。
Trining 循环:
- 代理在环境中采取行动,然后 bot 网络更新。
- 对于月球着陆器环境,这种实现表现良好。
注意:在实现这些方法时,我注意到学习速率和隐藏层中的神经元对学习有很大的影响。
你可以在这里找到这篇文章的完整代码。请继续关注即将发布的文章,我们将在有多个工人和没有多个工人的情况下实施 A2C。
这个系列的第二部分可以在这里访问。
所以,本文到此结束。谢谢你的阅读,希望你喜欢并且能够理解我想要解释的东西。希望你阅读我即将发表的文章。哈里奥姆…🙏
参考资料:
显着扩大和更新的广泛使用的文本强化学习的新版本,最…
mitpress.mit.edu](https://mitpress.mit.edu/books/reinforcement-learning-second-edition) [## 直觉 RL:优势介绍-演员-评论家(A2C)
强化学习(RL)实践者已经产生了许多优秀的教程。然而,大多数描述 RL 在…
hackernoon.com](https://hackernoon.com/intuitive-rl-intro-to-advantage-actor-critic-a2c-4ff545978752) [## 优势演员评论方法介绍:让我们玩刺猬索尼克!
托马斯西蒙尼尼介绍优势演员评论家的方法:让我们玩刺猬索尼克!从…开始
www.freecodecamp.org](https://www.freecodecamp.org/news/an-intro-to-advantage-actor-critic-methods-lets-play-sonic-the-hedgehog-86d6240171d/) [## 菲尔的机器学习
你好。在 Neuralnet.ai,我们涵盖了各种主题的人工智能教程,从强化…
www.youtube.com](https://www.youtube.com/channel/UC58v9cLitc8VaCjrcKyAbrw)**
TensorFlow 2.x 的演员兼评论家[第 2 部分,共 2 部分]
使用 TensorFlow 2.x 实施有/无多个工作人员的 A2C

Josue Isai Ramos Figueroa 在 Unsplash 上的照片
本文是使用 TensorFlow 2.x 的演员-评论家系列的第二部分。在上一篇文章中,我们使用 TensorFlow 2.x 实现了朴素的演员-评论家方法,而在本文中,我们将实现有/无多个工作者的优势演员-评论家(A2C)方法。你可以参考我之前在这个系列的文章这里。
最佳演员兼评论家(A2C):
让我们先来概述一下 A2C 算法,然后我们再来尝试理解代码。该算法的步骤如下。
没有多个工人:
- 代理玩 n 个时间步,并存储 n 个时间步的状态、动作、奖励
- 使用折现回报等式计算一个州的预期回报,即每个州的(R = r + Gamma*R)。
- 计算演员损失和评论家损失(我们将在代码部分考虑这一点)
- 每 n 步更新一次网络。请 注意在本文中,为了简单起见,我们将在每集之后更新,n 取决于您使用的环境。
- 重复上述过程,直到收敛。
有多个工人:
- 多个工作人员与他们自己的独立环境进行交互,并存储他们的经验。
- 在每一集之后(或每 n 个时间步之后),像以前一样计算预期回报,然后将这些工人的经验叠加在一起,然后在每一集之后用这种叠加的经验训练网络。
- 重复这个过程,直到收敛。
代码(没有多个工人):
神经网络:
- 我们的网络与前一篇文章相似,但这次层数和神经元数不同,因为我使用的是 cart pole 环境。
- 你必须试验层数和神经元数以及学习率(在优化器中使用)。
代理初始化和操作选择:
- 这两个函数也是相同的,但这次学习率不同。
- 简而言之,我们使用 TensorFlow 概率库将概率转化为动作采样的分布。
现在让我们先来看看与环境的相互作用,以便更好地理解。
主训练循环:
- 代理与环境交互,并将状态、动作、奖励存储在它们的受关注列表中。
- 当这一集结束时,调用函数 preprocess1,它将上述列表作为状态、动作和每个状态的预期回报的输入和输出 NumPy 数组(类似于蒙特卡罗计算每个状态的预期回报)。
- 然后,代理的网络使用这些 NumPy 数组进行更新。
学习功能和损失:
所以,这有点不一样。让我们一步一步来理解。
- Learn 函数将状态、动作和来自状态的期望回报(这里写为 discnt_rewards)的 NumPy 数组作为输入。
- 演员预测每个状态下每个动作的概率。批评家预测每个州的价值。
- 时间上的差异被计算为来自状态的预期收益和由评论家预测的值之间的差异。
- 批评家损失以 MSE 计算,预期收益作为目标,预测值作为预测值。
- 演员损失一开始实现起来有些复杂,因为许多在线教程使用 TensorFlow 内置的
SparseCategoricalCrossentropy,我发现它很抽象。这是一个简单的实现。 - 行动者损失是两种损失的组合,即政策损失和熵损失。保单损失是在该州采取行动的对数概率乘以该州的时间差的负数。熵损失是采取行动的概率乘以在该状态下采取行动的对数概率的负值。
- 损失的实现可能看起来很可怕,但这种实现的目的是网络预测的张量不能转换为 NumPy 数组,如果您转换 NumPy 数组中的值,您将得到一个错误,说明没有提供梯度。
- 因此,行动者损失函数将行动者、行动和时间差预测的行动概率张量作为输入。
- 第一个“for 循环”将每个预测转化为分布,因此我们可以获得在每个状态下采取行动的概率和对数概率。之所以需要“For 循环”,是因为我们可以在不将概率转换成数字数组的情况下,获得一个动作的概率。
- 然后我们计算损失。
训练图:
以下是最近 100 集 vs 集的剧情 b/w 平均奖励。

代码(有多个工人):
正如我们前面所讨论的,唯一不同的是多个工作人员与他们自己的环境副本进行交互。
要实现多员工 A2C,唯一需要的修改是在主培训循环中。
- 我们正在分别为状态、动作和预期奖励创建 3 个共享队列。并使用 python 多重处理库创建了 Barrier 实例和 lock 实例。
- 接下来,我们启动执行 runner 函数的 10 个进程。使用 join()我们可以确保每个进程都终止。
主训练循环:
- Runer 函数与环境交互,并像我们之前看到的那样将转换存储在列表中。
- 当一段情节为一个工作者完成时,它调用 preprocess1 函数,该函数执行与之前相同的任务,但这次它将状态、动作和预期回报放入它们各自的队列中(通过首先获取一个锁,以便没有其他工作者将其经验放入其他工作者的经验之间,然后在将他们的经验放入队列后释放该锁)。
- 我们只允许一个工人通过使用 Barrier 实例来提取经验和训练网络。
- 函数 preprocess2 从队列中检索这些体验,并将它们连接成一个用于状态的 NumPy 数组,一个用于操作,一个用于预期奖励。
- 然后网络被更新。最后一行 Barrier.wait()确保所有其他工作线程等待,直到所有工作线程都到达该点。
这就是关于编码的全部内容。现在让我们看看您的代理没有学习的原因和一些技巧。
实施时需要注意的事项:
在编写 RL 代码时,要记住以下几点。
- 神经元数量、隐藏层数、学习速率对学习有巨大的影响。
- 张量和 NumPy 数组的形状应该是正确的。很多时候,实现是正确的,代码也是有效的,但是代理没有学到任何东西,只是因为张量的形状不正确,并且当对这些张量进行运算时,会给出错误的结果。
你可以在这里找到这篇文章的完整代码和这里。敬请关注我们将在 TensorFlow 2 中实现 PPO 的后续文章。
所以,本文到此结束。谢谢你的阅读,希望你喜欢并且能够理解我想要解释的东西。希望你阅读我即将发表的文章。哈里奥姆…🙏
参考资料:
强化学习(RL)实践者已经产生了许多优秀的教程。然而,大多数描述 RL 在…
hackernoon.com](https://hackernoon.com/intuitive-rl-intro-to-advantage-actor-critic-a2c-4ff545978752) [## 谷歌联合实验室
编辑描述
colab.research.google.com](https://colab.research.google.com/github/yfletberliac/rlss-2019/blob/master/labs/solutions/DRL.01.REINFORCE%2BA2C_solution.ipynb) [## 优势演员-评论家方法介绍:让我们玩刺猬索尼克!
托马斯西蒙尼尼介绍优势演员-评论家方法:让我们玩刺猬索尼克!从…开始
www.freecodecamp.org](https://www.freecodecamp.org/news/an-intro-to-advantage-actor-critic-methods-lets-play-sonic-the-hedgehog-86d6240171d/)
亚当优化算法
一种有效优化算法综述

图 1:Dmitry Ratushny在 Unsplash 上拍摄的照片
根据牛津词典的定义,优化是对一种情况或资源进行最佳或最有效利用的行为,或者简单地说,就是尽最大努力。通常,如果某样东西可以用数学建模,那么它很可能可以被优化。这在深度学习领域(老实说,可能是整个人工智能)发挥着至关重要的作用,因为你选择的优化算法可能会在几分钟、几小时或几天内,在某些情况下,几周、几个月或一年内获得高质量的结果。
在这篇文章中,你将学到:
- 什么是亚当优化?
- 在你的深度学习模型中使用 Adam 进行优化有什么好处?
- 亚当是如何工作的?
亚当是什么?
Adam 优化是对随机梯度下降的扩展,可以用来代替经典的随机梯度下降来更有效地更新网络权重。
请注意,Adam 这个名字并不是一个缩写词,事实上,OpenAI 的 Diederik P. Kingma 和多伦多大学的吉米·巴雷在论文中指出,这个名字来源于自适应矩估计,该论文最初是在 2015 年 ICLR 的一篇会议论文中提出的,题为 Adam:一种随机优化的方法。
作者们立即列举了将 Adam 应用于非凸优化问题的许多迷人的好处,我将继续分享如下:
- 实现简单(我们将在本文后面实现 Adam,您将直接看到,利用强大的深度学习框架如何用更少的代码行使实现变得更加简单。)
- 计算效率高
- 几乎没有内存需求
- 梯度的对角缩放不变(这意味着 Adam 对于梯度乘以仅具有正因子的对角矩阵是不变的——为了更好地理解这一点阅读该堆栈交换
- 非常适合在数据和/或参数方面很大的问题
- 适用于非静止目标
- 适用于非常嘈杂和/或稀疏梯度的问题
- 超参数有直观的解释,通常需要很少的调整(我们将在配置部分详细介绍)
嗯……它是如何工作的?
简单来说,Adam 利用动量和自适应学习率来更快地收敛。
动量
在解释动量时,研究人员和实践者都喜欢使用球滚下山坡的类比,球滚向局部最小值的速度更快,但本质上我们必须知道的是,动量算法加速了相关方向的随机梯度下降,并抑制了振荡。
为了将动量引入我们的神经网络,我们将时间元素添加到当前更新向量的过去时间步长的更新向量中。这使得球的动量增加了一些。这可以用数学方法表示,如图 2 所示。

图 2:动量更新方法,其中θ是网络的参数,即权重、偏差或激活度,η是学习率,J 是我们试图优化的目标函数,γ是常数项,也称为动量。Vt-1(注意 t-1 是下标)是过去的时间步,Vt(注意 t 是下标)是当前的时间步。
动量项γ通常被初始化为 0.9 或 Sebastian Ruder 论文中提到的某个类似项【梯度下降优化算法概述。
自适应学习率
自适应学习率可以被认为是通过将学习率降低到预定义的时间表来调整训练阶段的学习率,我们在 AdaGrad、RMSprop、Adam 和 AdaDelta 中可以看到这种时间表——这也称为学习率时间表,关于这个主题的更多细节淑熙·刘写了一篇关于这个主题的非常翔实的博客文章,名为深度学习的学习率时间表和自适应学习率方法。
在不深入 AdaGrad 优化算法的情况下,我将解释 RMSprop 以及它如何改进 AdaGrad,以及它如何随着时间的推移改变学习速率。
RMSprop,即均方根传播,由 Geoff Hinton 开发,如梯度下降优化算法概述中所述,其目的是解决 AdaGrad 的学习率急剧下降的问题。简而言之,RMSprop 改变学习速率的速度比 AdaGrad 慢,但 AdaGrad 的好处(更快的收敛)仍然可以从 RMSprop 中获得,数学表达式见图 3。

图 3:E[g]t 的第一个方程是梯度平方的指数衰减平均值。Geoff Hinton 建议将γ设置为 0.9,而学习率η的默认值为 0.001。
这使得学习率能够随着时间的推移而适应,理解这一点很重要,因为这种现象在 Adam 中也存在。当我们将两者(Momentum 和 RMSprop)放在一起时,我们得到 Adam——图 4 显示了详细的算法。

图 4:随机优化的 Adam 算法;来源于 Kingma,D 和 Ba,J . (2015) Adam:一种随机优化方法。可在:【https://arxiv.org/pdf/1412.6980.pdf (访问时间:2020 年 5 月 31 日)。
感谢您阅读到这里,下面将链接更多阅读材料,如果您想与我联系,您可以在 LinkedIn 上找到我,我的名字是 Kurtis Pykes (点击我的名字可直接访问)。
进一步阅读:
- 金玛,D 和巴,J . (2015) 亚当:一种随机优化的方法。可在:https://arxiv.org/pdf/1412.6980.pdf
- Ruder,S. (2017) 梯度下降优化算法概述。可在:https://arxiv.org/pdf/1609.04747.pdf
- 用于在线学习和随机优化的自适应次梯度方法。可在:http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf
有用视频:
AdapterHub:一个适配变压器的框架
没有更慢的微调:有效的迁移学习与拥抱脸变压器在 2 额外的代码行

韦斯利·廷吉在 Unsplash 上拍摄的照片
这篇博文是对 AdapterHub 的介绍,这是一个由 Pfeiffer et al (2020b) 发布的新框架,它使你能够对广义预训练的变形金刚如 BERT、RoBERTa 和 XLM-R 进行迁移学习到下游任务如问答、分类等。使用适配器代替微调。
AdapterHub 建立在 HuggingFace 提供的流行的 transformer 包之上。这里可以找到拥抱脸变形金刚包,这里可以找到 AdapterHub 的修改。
为了正确理解这篇文章,我建议你先阅读一下变压器以及它们通常是如何微调的!
为什么要用适配器而不是微调?
我将在“适配器的好处”一节中详细介绍这一点,但先睹为快:
Houlsby 等人(2019) 介绍了一种叫做适配器的东西。适配器的作用与微调相同,但是通过将层缝合到主预训练模型,并且更新这些新层的权重φ,同时冻结预训练模型的权重θ。
相比之下,您会记得在微调中,我们还需要更新预训练的权重。
正如你可能想象的那样,与微调相比,这使得适配器在时间和存储方面的效率更高。适配器也被证明能够匹配最先进的微调方法的性能!
你将从这篇文章中学到什么
我将简化伴随框架发布的 AdapterHub paper 的内容,让你更容易开始开发。
AdapterHub 框架很重要,因为在这个框架之前,拼接已经训练过的适配器或共享适配器很困难,并且需要手动修改转换器架构。该框架支持
针对不同任务和语言的预培训适配器的动态“拼接”
简而言之,它使得使用适配器进行迁移学习变得更加容易。
在本帖中,我们将回顾在 AdapterHub 白皮书中讨论的适配器的各种优势,并解释新适配器 Hub 框架的各种特性。
这些特性将伴随着论文中的一些示例代码来帮助您入门!
如果你已经熟悉适配器及其各种好处,你可以直接跳到章节‘adapter hub 的主要特性’
适配器的优势
此处列出的优势与适配器 Hub 文件第 2.2 节中列出的优势相对应。
特定任务的分层表征学习
正如前面提到的,在 GLUE benchmark(在自然语言处理界很流行)上比较微调和适配器的性能时,性能没有很大的差异。
这意味着适配器可以达到与微调相当的最先进水平,同时保持被列为下一个功能的时间和空间效率!
小型、可扩展、可共享
为了完全微调模型,我们需要为每个任务“存储”一个模型的副本。这也“阻碍了训练的项目化和平行化。”
相比之下,适配器需要更少的存储空间。为了说明这一点,Pfeiffer 等人(2020b)提供了以下例子:
对于大小为 440Mb 的流行 Bert-Base 模型,当使用 48 的瓶颈大小和 Pfeiffer 等人的适配器时,存储 2 个完全微调的模型相当于 125 个带适配器的模型所需的相同存储空间(2020a)
这样做的另一个好处是,我们可以通过简单地添加小型适配器而不是大量的微调来为应用程序添加更多的任务。
研究人员之间的再现性是存储需求降低的另一个美妙结果。
模块化表征
当我们缝入适配器时,我们固定转换器其余部分的表示,这意味着这些适配器是封装的,并且可以与其他适配器堆叠、移动或组合。
这种模块化允许我们组合来自不同任务的适配器——随着 NLP 任务变得越来越复杂,这是非常重要的。
无干扰合成信息 。
自然语言处理通常涉及跨任务共享信息。我们经常使用一种叫做多任务学习(MTL)的方法,但是 MTL 有两个问题:
- 灾难性遗忘:在训练的早期阶段学习的信息被“覆盖”。
- 灾难性推理:当“增加新任务时,一组任务的性能恶化”(Pfeiffer 等人,2020b)。
对于适配器,我们为每个任务分别训练适配器,这意味着我们克服了上述两个问题。
适配器 Hub 的主要特性
很好,现在让我们来看看这个框架的关键特性!
变压器层中的适配器+如何训练适配器
为了添加适配器,作者使用了由 HuggingFace transformer 继承的称为“Mix-in”的东西,以便保持代码库合理分离。
实际上,下面是添加适配器层的方法:
from adapter_transformers import AutoModelForSequenceClassification, AdapterTypemodel = AutoModelForSequenceClassification.from_pretrained("roberta-base")model.add_adapter("sst-2", AdapterType.text_task, config="pfeiffer") model.train_adapters(["sst-2"]) # Train model ...
model.save_adapter("adapters/text-task/sst-2/", "sst")
# Push link to zip file to AdapterHub ...
您会注意到,代码主要对应于常规的 HuggingFace transformers,我们只添加了两行来添加和训练适配器。
这个 AdapterHub 框架的特别之处在于,您可以动态配置适配器,并更改架构。虽然您可以直接使用文献中的适配器,例如 Pfeiffer 等人(2020a)或 Houlsby 等人(2020),但是您也可以使用配置文件轻松修改这些架构。在上面的代码中,我们使用默认的 Pfeiffer (2020a)配置。
抽取和开源适配器
您可以将您训练的适配器推送到 AdapterHub.ml ,并从其他人预先训练的适配器中受益。与必须共享整个大型模型的微调不同,这些适配器是轻量级的,易于共享!
寻找预先训练好的适配器
AdapterHub.ml 的搜索功能分级工作:
- 第一级:按任务/语言查看
- 第二级:分离成更高级别的 NLP 任务的数据集//分离成训练数据的语言(如果我们正在适应一种新的语言)
- 第三层:分成单独的数据集或域(如维基百科)
该网站还可以根据您指定的预先训练的转换器,帮助您识别兼容的适配器。
在预训练的适配器中拼接
使用以下代码来连接预训练的适配器,而不是自己训练(如前所述):
from adapter_transformers import AutoModelForSequenceClassification, AdapterType model = AutoModelForSequenceClassification.from_pretrained("roberta-base")model.load_adapter("sst", config="pfeiffer")
非常清楚地说,预训练的适配器加载在第三行代码中,而预训练的转换器加载在第二行代码中。
用适配器推理
就用常规的 HuggingFace 代码进行推理吧!加载适配器砝码时,您可以选择加载预测头。
回想一下,使用这个令人敬畏的框架,为组合任务等组合适配器是非常可能的!
结论
我鼓励你在这里亲自尝试 AdapterHub 框架。
这个框架是如此令人兴奋,我希望这篇文章能帮助你开始适应变形金刚的旅程!
如果你在帖子中发现任何错误,或者你有任何评论/批评,请告诉我!
参考
Pfeiffer,j .,Kamath,a .,Rücklé,a .,Cho,k .,Gurevych,I. (2020a)。AdapterFusion:迁移学习的非破坏性任务合成。arXiv 预印本。
法官 Pfeiffer、法官 Rücklé、法官 Poth、法官 Kamath、法官 Vuli、法官 Ruder、法官 Cho、法官 Gurevych、法官 I(2020 b)。AdapterHub:一个适配变压器的框架。arXiv 预印本。
Houlsby,a . Giurgiu,a .,Jastrzkebski,s .,Morrone,b .,de Laroussilhe,q .,Gesmundo,a .,Attariyan,m .,和 Gelly,S. (2019)。自然语言处理中的参数有效迁移学习。2019 年 ICML 会议录。
数据科学中的问题解决
做一个项目从来都不是直截了当的,这里有一些适应的策略

奥拉夫·阿伦斯·罗特内在 Unsplash 上的照片
“创造性解决问题”实际上是一个时髦词(时髦短语?)说到一个数据科学家应该具备的技能。然而,这不是一个你可以仅仅获得 Udacity 证书的技能(或者你可以,我不知道所有的课程)。你磨练这些技能的唯一方法就是做项目。上周我写了我最近的项目,一个针织图案推荐器。特别是,我写了创建基于内容的推荐器的一般过程。
提醒一下,基于内容的推荐系统采用某种形式的用户信息,将其与潜在候选人池进行比较,然后从候选人中选择最佳匹配。用户信息可以是用户当前正在查看的项目,也可以是用户喜欢或参与的所有内容的完整用户简档。
正如我也提到的,该项目是基于分析 Vidhya 的这篇文章。然而,我最终使用的过程与本文中介绍的过程并不完全相同。我不得不根据自己独特的问题来调整我的项目,以下是我用来解决问题的一些策略:
批判性地思考你需要的数据
我遇到的一个大问题是,我的数据集比文章中显示的 6 个数据点大得多。这意味着如果我想要一个高效流畅运行的程序,我需要找到一种方法来缩小数据集,只获取绝对必要的信息。在这篇文章中,作者使用了一个大数据集,其中既有未知文章,也有用户参与的文章。显然,当处理远远超过 100 个数据点时,如果您想要高效运行,这是不可行的。因此,我创建了一个仅包含用户信息的数据集,然后获取为用户配置文件生成的数字(决定一个人喜欢某个给定属性的程度的分数)、数据集的长度以及每个属性出现的次数。最后两个是为了帮助计算 tf-idf,因为我没有将整个用户数据集放入用于推荐模式的最终数据集中。
在足够的数据和过多的数据之间取得平衡
这在几个方面与我的最后一点非常相关。就像我说的,数据集越大,运行程序需要的时间就越多。如果我正在做一个项目,在那里我只是展示结果,我会希望得到尽可能多的干净的数据。然而,运行时间在这里是一个实际问题,人们不想等待几分钟的结果。因此,在我的程序中,我必须告诉它,如果用户在他们的收藏夹或他们的模式中有超过一定数量的模式,只取最近的 100 个左右。此外,我还遇到了一个问题,一些模式代码会抛出一个错误,这个错误会搞乱正在处理的整批模式。最初,我想出了一种方法来挑出问题儿童的个人模式,但最终我意识到这将花费太多时间。创建一个供人们使用的程序,不像一个你展示发现的项目,意味着你不能使用同样的细齿梳子。对于这样的项目,您必须在获取足够的数据以给出一个体面的结果和不获取太多数据以至于整个程序陷入困境之间找到平衡。
使用不同的测试用例
当测试一个程序时,你可能会倾向于只使用一个用户数据集,可能会做一些不同类型的搜索,然后说,“好的,很好。”然而,您可能会在不同的测试用例中遇到问题,而您不会在仅仅使用一个测试用例时遇到这些问题。一个明显的例子是,我意识到用户资料受到用户数据集大小的影响。本质上,如果轮廓更大,数字会更大,但这不一定意味着他们更喜欢某个属性。在那个问题上,我想到的解决方案是用数据集的长度来划分每个用户档案号。因此,它将反映相对于整个数据集,用户对给定属性的喜爱程度。通过这种方式,用户的数字不会仅仅因为他们在项目和收藏夹中使用或不使用 Ravelry 的数量而有所不同。如果我没有尝试几个不同的配置文件大小,我永远不会发现这个问题,人们可能会得到低匹配数,只是因为他们不是一个活跃的用户。
通过这个项目,我学到的最大的事情之一是,使用机器学习来创建一个程序,而不是使用它来调查项目的数据,需要稍微不同的优先级。也就是说,处理时间是更重要的优先事项,而彻底性则不是那么重要。当然,这并不是说你应该在数据处理上马虎大意。你只是没有用细齿梳和挑剔每一个小细节。特别是如果你是一个完美主义者或者是那种讨厌删除大量列或行的人,这可能是一个困难的转变。我遇到的几个主要问题通过确定我需要的确切信息得到了解决,因此我不会一次性处理一个巨大的数据集,确定如何编辑我的数据以确保有效的程序,并使用不同的测试案例来诊断任何可能的问题,这些问题只会在非常具体的情况下出现。遇到这种问题可能很困难,但至少对我来说,解决这种问题是数据科学如此有趣的原因。
股票市场预测中的自适应滤波:一种不同的方法
用 LMS 线性自适应滤波器预测股票市场价格

莎伦·麦卡琴在 Unsplash 上的照片
P 很可能你在网上看到了很多关于股市预测的内容,但每一条似乎都是空话连篇,或者是看起来不可思议的事情。
预测股票市场价格是数据科学中一个主要领域的一部分,称为时间序列分析,在这里我们将看到我们如何用一种非常漂亮、简单且效果不错的非常规方法来处理这个问题:自适应滤波。
时间序列
时间序列 是一系列按时间顺序索引(或列出或绘制)的数据点。
对计量经济学、统计学和气象学等领域非常重要的是,时间序列的研究是挑战性问题之一,激发了信号处理、机器学习和数据分析领域的大量研究,因为它可以用于聚类、分类,以及在这种情况下的预测。

股票价格分析是一个时间序列问题!
为了有更实际的情况,我们将使用 2019 年 178 天期间的 ABEV3 (ON) 股票价格。如果你认为这种数据很难获得,那么你就错了。这个数据是我在 b3 网站、巴西官方股市得到的,而且是免费的:)

ABEV3(上)2019 年 180 天股价
很好,一旦我们掌握了数据,我们就来讨论算法
LMS 滤波器
LMS 滤波器是一种自适应滤波器,用于解决线性问题。滤波器的思想是通过最小化误差信号的最小均方来模拟系统(找到滤波器系数)。

LMS 滤波器伪代码
总的来说,我们不知道用线性方法是否能很好地解决问题,所以我们通常测试一个线性和一个非线性算法。由于互联网总是显示非线性方法,我们将使用 LMS 来证明股票市场预测可以用具有良好精度的线性算法来完成。
但是这个滤波器模仿了一个系统,也就是说,如果我们在我们的数据中应用这个滤波器,我们将训练滤波器系数,当我们输入一个新的向量时,我们的滤波器系数将输出原始系统会输出的响应(在最好的情况下)。因此,我们只需做一个巧妙的修改,就可以使用这个过滤器来预测数据。
该系统
首先,我们将我们的输入向量延迟 l 个位置,其中 l 将是我们想要预测的天数,这个 l 新位置将由个零填充。

系统的模式
当我们应用 LMS 滤波器时,我们将针对前 178 个数据训练滤波器。之后我们会将误差设置为零,那么系统会开始输出答案作为原系统到最后的 l 值。我们将棘手的修改称为 LMSPred 算法。

LMSPred 伪代码
最后,我们来编码吧!
首先我们必须导入我们将在这段代码中使用的库:
**import** numpy **as** np
**import** matplotlib.pyplot **as** plt
下一步是 LMSPred 的实现,你可以边看伪代码边自己尝试,这里是我的实现:
**def** **lmsPred**(x,l,u,N):
xd= np.**block**([np.zeros((1,l)), x]).T
y=np.**zeros**((len(xd),1))
xn=np.**zeros**((N+1,1))
xn = np.**matrix**(xn)
wn=np.**random**.**rand**(N+1,1)/10
M=**len**(xd)
**for** n **in** range(0,M):
xn = np.**block**([[xd[n]], [xn[0:N]]]);
y[n]= np.**matmul**(wn.T, xn);
**if**(n>M-l-1):
e =0;
**else**:
e=**int**(x[n]-y[n]);
wn = wn + 2*u*e*xn;
**return** y,wn;
现在,我们将定义我们的向量 x,它具有 ABEV3 (ON)的 178 个值:
x = np.**array**([1655, 1648, 1615, 1638, 1685, 1729, 1754, 1770, 1780, 1785, 1800, 1800, 1754, 1718, 1716, 1795, 1787, 1797, 1751, 1811, 1845, 1864, 1809, 1875, 1822, 1871, 1867, 1839, 1859, 1849, 1819, 1832, 1815, 1832, 1832, 1839, 1849, 1836, 1723, 1683, 1637, 1669, 1659, 1711, 1700, 1690, 1666, 1676, 1731, 1719, 1700, 1698, 1672, 1652, 1699, 1654, 1675, 1683, 1682, 1677, 1684, 1732, 1744, 1735, 1769, 1755, 1725, 1706, 1742, 1753, 1705, 1708, 1750, 1767, 1772, 1831, 1829, 1835, 1847, 1795, 1792, 1806, 1765, 1792, 1749, 1730, 1701, 1694, 1661, 1664, 1649, 1649, 1709, 1721, 1721, 1706, 1722, 1731, 1726, 1743, 1755, 1742, 1735, 1741, 1764, 1761, 1765, 1772, 1768, 1785, 1764, 1780, 1805, 1820, 1845, 1830, 1817, 1810, 1805, 1789, 1781, 1813, 1887, 1900, 1900, 1894, 1902, 1869, 1820, 1825, 1810, 1799, 1825, 1809, 1799, 1803, 1796, 1949, 1980, 2050, 2034, 2013, 2042, 2049, 2016, 2048, 2063, 2017, 2007, 1948, 1938, 1901, 1878, 1890, 1911, 1894, 1880, 1847, 1833, 1809, 1817, 1815, 1855, 1872, 1838, 1852, 1880, 1869, 1872, 1887, 1882, 1891, 1937, 1910, 1915, 1943, 1926, 1935]);
为了训练该系统,我们将采用前 173 个值,学习率为 2^(-30),过滤顺序 N=60,l=5 天的预测。
x_train = x[0:173]
u = 2**(-30);
l=5;
N=60;
y,wn = **lmsPred**(x_train,l,u,N)
为了可视化输入数据和学习曲线,我们将绘制如下:
plt.**plot**(x, **color** = 'black')
plt.**plot**(y, **color** = 'red')
plt.**show**()
并评估我们预测的百分误差:
pred = y[-l:]
realvalues = x[-l]
error = 100*(pred.T-realvalues)/realvalues
**print**(**abs**(error))
所以,的完整代码为:
**import** numpy **as** np
**import** matplotlib.pyplot **as** plt**def** **lmsPred**(x,l,u,N):
xd= np.**block**([np.zeros((1,l)), x]).T
y=np.**zeros**((len(xd),1))
xn=np.**zeros**((N+1,1))
xn = np.**matrix**(xn)
wn=np.**random**.**rand**(N+1,1)/10
M=**len**(xd)
**for** n **in** range(0,M):
xn = np.**block**([[xd[n]], [xn[0:N]]]);
y[n]= np.**matmul**(wn.T, xn);
**if**(n>M-l-1):
e =0;
**else**:
e=**int**(x[n]-y[n]);
wn = wn + 2*u*e*xn;
**return** y,wn;x = np.**array**([1655, 1648, 1615, 1638, 1685, 1729, 1754, 1770, 1780, 1785, 1800, 1800, 1754, 1718, 1716, 1795, 1787, 1797, 1751, 1811, 1845, 1864, 1809, 1875, 1822, 1871, 1867, 1839, 1859, 1849, 1819, 1832, 1815, 1832, 1832, 1839, 1849, 1836, 1723, 1683, 1637, 1669, 1659, 1711, 1700, 1690, 1666, 1676, 1731, 1719, 1700, 1698, 1672, 1652, 1699, 1654, 1675, 1683, 1682, 1677, 1684, 1732, 1744, 1735, 1769, 1755, 1725, 1706, 1742, 1753, 1705, 1708, 1750, 1767, 1772, 1831, 1829, 1835, 1847, 1795, 1792, 1806, 1765, 1792, 1749, 1730, 1701, 1694, 1661, 1664, 1649, 1649, 1709, 1721, 1721, 1706, 1722, 1731, 1726, 1743, 1755, 1742, 1735, 1741, 1764, 1761, 1765, 1772, 1768, 1785, 1764, 1780, 1805, 1820, 1845, 1830, 1817, 1810, 1805, 1789, 1781, 1813, 1887, 1900, 1900, 1894, 1902, 1869, 1820, 1825, 1810, 1799, 1825, 1809, 1799, 1803, 1796, 1949, 1980, 2050, 2034, 2013, 2042, 2049, 2016, 2048, 2063, 2017, 2007, 1948, 1938, 1901, 1878, 1890, 1911, 1894, 1880, 1847, 1833, 1809, 1817, 1815, 1855, 1872, 1838, 1852, 1880, 1869, 1872, 1887, 1882, 1891, 1937, 1910, 1915, 1943, 1926, 1935]);x_train = x[0:173]
u = 2**(-30);
l=5;
N=60;
y,wn = **lmsPred**(x_train,l,u,N)plt.**plot**(x, **color** = 'black')
plt.**plot**(y, **color** = 'red')
plt.**show**()pred = y[-l:]
realvalues = x[-l]
error = 100*(pred.T-realvalues)/realvalues
**print**(**abs**(error))
结果

股市预测结果一例
我们选择了的黑色作为的真实数据,而的红色作为我们的预测,正如你所看到的,最初它们有很大的差异,但是更接近于对应于滤波器阶数的值(在这种情况下,60)两条曲线非常接近。
在这种情况下,每天的百分比输出精度为:
[[0.79837693 1.12168626 1.24557245 2.24050302 3.16604697]]
因此,第 5 天有 3.16% 的误差,这是一个相当不错的值,因为我们使用的是一个非常简单的方法。
需要强调的是,对于高值的 l ,股票市场预测不太好,因为我们要在稳定状态期间分析股票市场,也就是说,不考虑未来可能的危机、政治问题等。因此,对 l. 的小值使用股市预测更安全
如果您有任何问题,可以在我的 LinkedIn 个人资料中关注我!
适应性学习率:AdaGrad 和 RMSprop
在我之前的文章中,我们看到了学习率(η)如何影响收敛。将学习率设置得太高会导致最小值附近的振荡,而设置得太低会减慢收敛速度。梯度下降中的学习速率(η)及其变化(如动量)是一个超参数,需要针对所有特征手动调整。

作者图片
当我们使用上述等式来更新神经网络中的权重时
- 所有功能的学习速度都是一样的
- 学习率在成本空间的所有地方都是一样的
恒定学习率对收敛的影响
假设,我们试图预测一部电影的成功/评级。我们假设有成千上万个特征,其中一个是“is_director_nolan”。我们的输入空间中的特征“is_director_nolan”将主要为 0,因为 nolan 导演了很少的电影,但是他的出现显著影响了电影的成功/评级。从本质上来说,这个特征是稀疏的,但是由于高信息量,我们不能忽略它。
在神经网络的正向传递过程中,如果迭代(t)时的输入(x)为 0,则使用下面的等式,输出变为 bias(b)的激活(φ ) 。

作者图片
因此,在反推 w.r.t 期间计算的局部梯度该恒定偏差将为 1,并且对于该特征,权重更新将非常小(参见第一个等式)
对于像“is_director_nolan”这样的稀疏输入特征,只有当输入从 0 变为 1 或相反时,才会发生大的权重更新。而密集特征将接收更多更新。因此,对所有特征使用恒定和相同的学习速率不是一个好主意。
解决方案
从上面我们可以推断出,特征的学习率应该衰减,使得它与该特征的权重更新频率成反比。对于频繁特征,新的学习率应该低,而对于稀疏特征,新的学习率应该高。

作者图片
权重的更新频率的代表是在过去的更新中获得的梯度的总和。我们应该取梯度的平方,而不是梯度的绝对值,这样梯度的符号(方向)就无关紧要了。我们只关心梯度频率。这可以使用下面的等式来捕捉。

作者图片
密集要素的该代理值较高,而稀疏要素的该代理值很低。
假设𝓥 (0) = 0

作者图片
新的学习率变为

作者图片
注意:我们取𝓥 (t) 的平方根,以便保持我们的权重更新方程的维数
新的权重更新公式变为

作者图片
如果𝓥 (t) 为零(在稀疏特征的情况下)会发生什么?为了避免分母变成零,我们应该在分母中加一个小值ε(一般是 1e -07)。

作者图片
上面的等式是用于 AdaGrad (自适应梯度)的权重更新等式。
每次迭代后, AdaGrad 的新学习率以过去梯度的平方和的因子衰减。虽然它解决了我们更新稀疏特征的问题,但同时也引入了一个新的问题。对于密集特征,过去的梯度将是非零的,并且在一些迭代之后,学习率由于分母中所有过去的平方梯度的累积而收缩得太快。
为了解决这个问题,我们可以借鉴基于动量的梯度下降法。不是以相等的比例使用所有过去的梯度,我们将使用过去平方梯度的指数移动平均,以基本上将累积梯度的窗口限制为仅几个最近的梯度。
因此,更新频率𝓥的新代理 (t) 变为。

作者图片
上面的等式是 RMSprop 的权重更新等式。
额外说明:
在一些文本中,包括 AdaGrad 的原始研究论文中,你会发现在分母中没有使用整个梯度矩阵,而是使用了累积梯度的对角矩阵。
AdaGrad 的权重更新规则的矩阵表示。

作者图片
梯度矩阵 G(t) 的平方根和逆矩阵是一个昂贵的运算,对于大的输入空间,这可能变得非常难以计算。 G(t) 的对角矩阵是最佳近似,因为它忽略了梯度相互作用。 diag(G(t)) 的平方根和逆可以用 O(n)时间复杂度计算。因此,AdaGrad 和 RMSprop 的大多数实现仅使用梯度矩阵 G(t) 的对角元素。
结论
学习率是一个重要的超参数,必须针对输入空间中的每个特征进行优化调整,以实现更好的收敛。通过采用自适应学习速率方法,如 AdaGrad 和 RMSprop,,我们让这些优化器通过学习底层数据的特征来调整学习速率。这些优化器给频繁出现的特征以低学习率,给不频繁出现的特征以高学习率,从而收敛得更快。
Python 中的自适应移动平均。
呈现一个强有力的趋势指示器。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
均线是检测趋势变化的最简单也是最有效的工具之一。它们也被用来建立基于交叉的交易策略。几乎每个交易者都使用它们,并把它们纳入自己的决策过程。在本文中,我们将浏览基本的已知移动平均线,然后介绍稍微复杂一点的 Kaufman Adapative 移动平均线——KAMA。
我刚刚出版了一本新书《成功后的 新技术指标》中的 Python 。它对复杂的交易策略进行了更完整的描述和补充,Github 页面致力于不断更新代码。如果你对此感兴趣,请随时访问下面的链接,或者如果你喜欢购买 PDF 版本,你可以在 Linkedin 上联系我。
亚马逊网站:交易策略之书:9798532885707: Kaabar,Sofien:书籍
普通移动平均线
三种最常见的移动平均线是:
- 简单移动平均线。
- 指数移动平均线。
- 平滑移动平均线。
在我们进入 KAMA 之前,我们将仔细检查每一个,定义它,编码它,并绘制它的图表。

具有 200 周期简单移动平均线(橙色)、200 周期均线(蓝色)和 200 周期平滑移动平均线(绿色)的 USDCAD。(图片由作者提供)
- 简单移动平均线
顾名思义,这是一个简单的平均数,在统计学和我们生活中的任何地方都会用到。它就是观察值的总和除以观察次数。从数学上来说,它可以写成:

在 python 中,我们可以定义一个计算移动平均值的函数,如下所示:
def ma(Data, period, onwhat, where):
for i in range(len(Data)):
try:
Data[i, where] = (Data[i - period:i + 1, onwhat].mean())
except IndexError:
pass
return Data
该函数采用由数据变量、移动平均周期(20、60、200 等)表示的数据结构。)由周期变量表示,您希望将它应用于什么(在 OHLC 数据结构上,选择 3 表示收盘价,因为 python 索引从零开始)由 onwhat 变量表示,而 where 变量是您希望移动平均线列出现的位置。请注意,您必须有一个超过 4 列的数组才能工作,因为它不会自动创建一个新列,而是简单地填充它。

欧元兑美元每日时间跨度,200 天简单移动平均线。(图片由作者提供)
- 指数移动平均
与简单的移动平均线给所有的观察值相同的权重相反,指数移动平均线给最近的观察值更多的权重。它比简单的移动平均线对最近的变动反应更大。从数学上来说,它可以写成:

平滑因子通常为 2。请注意,如果我们增加平滑因子(也称为 alpha ),那么最近的观测值将具有更大的权重。在 python 语言中,我们可以定义一个函数来计算 EMA,如下所示:
def ema(Data, alpha, window, what, whereSMA, whereEMA):
# alpha is the smoothing factor
# window is the lookback period
# what is the column that needs to have its average calculated
# where is where to put the exponential moving average
alpha = alpha / (window + 1.0)
beta = 1 - alpha
# First value is a simple SMA
Data[window - 1, whereSMA] = np.mean(Data[:window - 1, what])
# Calculating first EMA
Data[window, whereEMA] = (Data[window, what] * alpha) + (Data[window - 1, whereSMA] * beta)# Calculating the rest of EMA
for i in range(window + 1, len(Data)):
try:
Data[i, whereEMA] = (Data[i, what] * alpha) + (Data[i - 1, whereEMA] * beta)
except IndexError:
pass
return Data
该函数是不言自明的,因为它只是复制了上面介绍的 EMA 函数。
如果你也对更多的技术指标和使用 Python 创建策略感兴趣,那么我关于技术指标的畅销书可能会让你感兴趣:
亚马逊网站:Python 中的新技术指标:9798711128861: Kaabar,Sofien 先生:书籍
欧元兑美元每日时间跨度,200 天指数移动平均线。(图片由作者提供)
- 平滑移动平均线
该移动平均线考虑了总体情况,受近期走势的影响较小。这是我最喜欢的趋势跟踪指标。从数学上来说,简单地将 EMA 函数中的 Days 变量乘以 2 再减去 1 就可以得到。这意味着,要将指数移动平均线转换为平滑移动平均线,我们需要遵循 python 语言中的等式,即将指数移动平均线转换为平滑移动平均线:
smoothed = (exponential * 2) - 1 # From exponential to smoothed

200 天平滑移动平均线的欧元兑美元每日时间范围。(图片由作者提供)
考夫曼适应性移动平均线
创建 KAMA 是为了减少噪音和锯齿效应。它的工作原理和其他均线一样,遵循同样的直觉。错误交易信号的产生是均线的问题之一,这是由于短期的突然波动使计算产生偏差。KAMA 的主要目标是尽可能降低噪音。
我们应该衡量的第一个概念是效率比率,它是当前收盘价相对于过去 10 个周期的绝对变化除以以特殊方式计算的一种波动率。我们可以说效率比是变化除以波动。

图片作者。
然后,我们根据以下公式计算平滑常数:

图片作者。
最后,为了计算 KAMA,我们使用以下公式:

图片作者。
计算可能看起来很复杂,但它很容易自动化,你不必想太多。让我们看看如何用 Python 对其进行编码,然后继续看一些例子。
def kama(Data, what, where, change):
# Change from previous period
for i in range(len(Data)):
Data[i, where] = abs(Data[i, what] - Data[i - 1, what])
Data[0, where] = 0
# Sum of changes
for i in range(len(Data)):
Data[i, where + 1] = (Data[i - change + 1:i + 1, where].sum())
# Volatility
for i in range(len(Data)):
Data[i, where + 2] = abs(Data[i, 3] - Data[i - 10, 3])
Data = Data[11:, ]
# Efficiency Ratio
Data[:, where + 3] = Data[:, where + 2] / Data[:, where + 1]
for i in range(len(Data)):
Data[i, where + 4] = np.square(Data[i, where + 3] * 0.6666666666666666667)
for i in range(len(Data)):
Data[i, where + 5] = Data[i - 1, where + 5] + (Data[i, where + 4] * (Data[i, 3] - Data[i - 1, where + 5]))
Data[11, where + 5] = 0
下面的图表说明了上述函数能给我们带来什么。注意相对于其他移动平均线,KAMA 有更稳定的趋势。这是对拉锯和假断裂的改进。

欧元兑美元 M15 时间跨度,10 期自适应移动平均线。(图片由作者提供)

USDCHF M15 时间范围,10 期自适应移动平均线。(图片由作者提供)
KAMA 也可以用来检测新趋势的开始。例如,我们可以绘制一个长期的 KAMA 和一个短期的 KAMA,在它们的交叉点上交易。如果默认设置是 10 期,我们可以试试 30 期的 KAMA,看看它能给我们什么。
plt.plot(Asset1[-500:, 3], color = 'black', label = 'EURUSD')
plt.plot(Asset1[-500:, 4], color = 'blue', label = '10-period KAMA')
plt.plot(Asset1[-500:, 5], color = 'purple', label = '30-period KAMA')
plt.grid()
plt.legend()

欧元兑美元 M15 时间跨度,10 期和 30 期自适应移动平均线。(图片由作者提供)
使用上面的图表,我们可以说,当两个 KAMA 持平时,市场在波动,当趋势开始时,我们应该跟随它们各自的交叉,例如当 30 期 KAMA 高于 10 期 KAMA 时,熊市趋势正在进行,直到交叉发生。这反过来对我们可能是一个有价值的信号。如果你对趋势跟踪策略感兴趣,你可以看看下面的文章:
[## Python 中的超级趋势指示器——编码和回溯测试其策略
如何编码,回测,并在外汇交易中进行评估。
medium.com](https://medium.com/swlh/the-supertrend-indicator-in-python-coding-and-back-testing-its-strategy-e37d631c33f)
现在,让我们画一个简单的移动平均线,并与同期的 KAMA 进行比较。显然,后者对正在发生的事情提供了更好、更准确的描述,这是因为它考虑到了波动性。现在我不是说你应该用 KAMA 代替简单的移动平均线,但是把它包含在框架中似乎是个好主意。

欧元兑美元 M15 时间范围,10 期自适应移动平均线和简单移动平均线。(图片由作者提供)

USDCHF M15 时间范围,10 期自适应移动平均线和简单移动平均线。(图片由作者提供)
结论
作为自适应和指数移动平均线的粉丝,我鼓励你尝试这种技术。卡马提供了有价值的支撑和阻力位,可以用来补充你的交易系统。它不是用来作为产生交易信号的唯一因素,但它在确认交易信号方面是有价值的。

尼古拉斯·卡佩罗在 Unsplash 上拍摄的照片
COVID 下的自适应配对交易——一种强化学习方法
人工智能资本管理研究系列文章

摘要
这是 A.I. Capital Management 的研究系列文章之一,介绍文章在这里。这一个是关于在市场中性策略上应用 RL,特别是优化一个简单的配对交易策略,RL 代理是每个交易基础上的资本分配器,同时保持进/出信号不变。目标是优化现有信号的连续交易规模分配,同时让代理根据市场制度/条件调整其行为。
作者: Marshall Chang 是 A.I. Capital Management 的创始人兼首席信息官,这是一家量化交易公司,建立在深度强化学习对动量和市场中性交易策略的端到端应用之上。该公司主要以中高频交易外汇市场。
概述
成对交易是市场中性策略的基础,这是最受欢迎的量化交易策略之一,因为它不从市场方向获利,而是从一对资产之间的相对回报获利,避免了系统风险和随机游走的复杂性。市场中性策略的盈利能力存在于假设的资产对之间的潜在关系中,然而,当这种关系不再保留时,通常在动荡的体制转换时期,如今年的新冠肺炎,这种策略的回报通常会减少。事实上,根据 HFR(对冲基金研究公司)的数据,截至 2020 年 7 月底,HFRX 股票对冲指数的年初至今回报率为-9.74%【1】;其近亲,HFRX 相对价值套利指数,年初至今回报率为-0.85%。众所周知,对于市场中立的量化分析师,或者任何量化分析师,挑战不仅仅是发现盈利信号,更多的是如何在体制转换时期快速发现和适应复杂的交易信号。
在市场中性交易领域,大多数研究一直专注于揭示相关性和提炼信号,通常使用以高成本购买的专有替代数据来寻找优势。然而,交易规模和投资组合层面的资本配置优化往往被忽视。我们发现很多配对交易信号虽然复杂,但仍然使用固定的进场门槛和线性分配。随着深度强化学习(RL)等复杂模型和学习算法的发展,这类算法渴望非线性优化的创新。
方法——alpha spread RL 解决方案
为了通过状态转换时间来解决配对交易策略的检测和适应,我们的独特方法是使用基于顺序代理的解决方案来解决交易分配优化,该解决方案直接在现有信号一般化过程之上训练,具有清晰的跟踪改进和有限的部署开销。
该项目内部命名为 AlphaSpread ,展示了在美国& P 500 股票的 1 对价差交易中,RL 顺序交易规模分配相对于标准线性交易规模分配的 ROI(投资回报)改善。我们以现有的每笔交易标准分配的配对交易策略为基线,在我们定制的价差交易健身房环境中训练由深度神经网络模型表示的 RL 分配器,然后在样本外数据上进行测试,旨在超越基线的最终 ROI。
具体来说,我们选择协整对的基础上,他们的平稳传播我们的统计模型。协整对通常在同一个行业,但我们也包括横截面对显示强协整。交易信号是通过达到由统计模型使用每日收盘价预测的残差的 z 分数的预定义阈值而生成的。本例的基线将整个投资组合的固定 50%分配给每个交易信号,而 RL 分配器根据 z 分数回看所代表的当前市场条件,依次为每个交易信号输出 0–100%的分配。
alpha spread——在视频中,红色的 NAV 是信号在 COVID 月份中的表现,绿色的是我们 RL 分配器的相同策略。我们了解到,我们的 RL 代理可以在早期发现制度变化,并相应地进行分配,以避免巨大的低迷。
结果汇总
我们总结了我们的 RL 方法对 107 个交易的美国股票对的交易 ROI 与基线线性分配。投资回报率是根据测试期结束时每对组合 100,000 美元的初始资本来计算的。该结果来自 2018 年至 2020 年 4 月(包括新冠肺炎月)期间对样本外数据的回溯测试。利用 2006 年和 2017 年之间的数据来训练 RL 分配器。在这两种情况下,测试中不考虑费用。与基线方法相比,我们平均每对投资回报率提高了 9.82%,最高为 55.62%,最低为 0.08%。
换句话说,通过有限的模型调整,这种方法能够通过早期检测体制转换和 RL 分配器代理相应的资本分配适应来导致 ROI 的普遍改善。

配对交易策略 ROI 快照,比较基础分配和 RL 分配
一般化的讨论
这个项目的目标是展示一个非常简单的一对一交易信号的潜在改进的样本外概括,因此为将这种方法应用于大规模复杂的市场中性策略提供指导。下面是我们在这个实验中设定的 3 个目标的讨论。
可重复性 —该 RL 框架由定制的 pairs trading RL 环境组成,用于准确培训和测试 RL 代理,RL 培训算法包括 DQN、DDPG 和异步演员评论,RL 自动培训推出机制集成了内存优先重放、动态模型调整、探索/开发等。,通过最少的定制和手动调整实现大型数据集的可重复性。运行 RL 相对于其他机器学习算法的优势在于,它是一个从训练数据泛化、奖励函数设计、模型和学习算法选择到输出一个序列策略的端到端系统。一个经过良好调整的系统需要最少的维护,并且模型的再培训/重新适应新数据是在相同的环境中完成的。
可持续性 —在一对交易的例子中,使用 2006 年和 2017 年的数据进行了配对协整测试和 RL 训练,然后训练有素的代理从 2018 年到 2020 年初进行测试。训练和测试数据的比例大致为 80:20。随着 RL 自动培训的展开,我们可以在超过 2 年的时间里,在数百对样本中总结出基线回报的可持续改善。RL 代理学习根据代表两者的协整路径以及波动性的 z 分数的回看来分配,并接受探索/开发训练,以找到最大化最终 ROI 的策略。与具有静态输入-输出的传统监督和非监督学习相比,RL 算法具有内置的泛化鲁棒性,因为它直接学习具有反映实现的损益的奖励函数的状态-策略值。RL 训练目标总是非静态的,因为随着代理与环境交互并改善其策略,训练体验会得到改善,从而强化良好行为,反之亦然。
可扩展性 —训练和部署大规模端到端深度 RL 交易算法在 quant trading 中仍处于起步阶段,但我们相信它是我们领域 alpha 的未来,因为 RL 已经在游戏领域(AlphaGo、Dota 等)展示了对传统 ML 的巨大改进。).这个 RL 框架非常适用于市场中性基金部署的不同配对交易策略。凭借在多个量化交易渠道中运行 RL 系统的经验,我们可以定制环境、训练算法和奖励函数,以有效地解决投资组合优化中的独特任务,这是由传统的监督和非监督学习模型无法实现的基于 RL 的代理的顺序学习提供动力的。
钥匙拿走
如果信号赚钱,就是用线性分配赚钱(总是交易 x 单位)。但当它没有,显然我们想重做信号,让它适应新的市场条件。然而,有时这并不容易做到,一个快速的解决方案可能是在现有信号处理之上的 RL 代理/层。在我们的例子中,我们让代理观察一个代表价差波动的数据集,并根据过去的交易和损益决定相关的分配。
背景及更多详情
信号一般化过程 —我们首先对两种资产的过去回顾价格历史(2006 年至 2017 年每日价格)进行线性回归,然后我们进行 OLS 检验以获得残差,利用残差我们进行单位根检验(增广的 Dickey-Fuller 检验)以检查协整的存在。在本例中,我们将 P 值阈值设置为 0.5%,以拒绝单位根假设,这导致 2794 个 S & P 500 对通过测试。下一个短语是我们如何设置触发条件。首先,我们将残差归一化,得到一个遵循假设的标准正态分布的向量。大多数测试使用两个西格玛水平达到 95%,这是相对难以触发。为了给每一对产生足够的交易,我们把阈值设置为 sigma。归一化后,我们得到一个白噪声遵循 N(0,1),并设置+/- 1 作为阈值。总的来说,信号产生过程非常简单。如果标准化残差高于或低于阈值,我们就做多看跌的,做空看多的,反之亦然。我们只需要生成一个资产的交易信号,另一个应该是相反的方向
深度强化学习—RL 训练制度从运行探索到利用线性退火策略开始,通过运行训练环境来生成训练数据,在这种情况下,运行与协整相同的 2006-2017 年历史数据。存储器存储在以下组中
状态、动作、奖励、下一个状态、下一个动作(SARSA)
这里我们使用 DQN 和政策梯度学习目标的混合,因为我们的行动输出是连续的(0-100%),但样本效率低(由于每日频率,每对交易在数百笔以内)。我们的训练模型会随着
Q(状态)=奖励+ Q-max(下一个状态,下一个动作)
本质上,RL 代理正在学习连续 DQN 的 Q 值,但是在每个策略的改进上用策略梯度来训练,因此避免了样本低效(Q 学习保证收敛到训练全局最优)和过快地陷入局部最小值的趋势(避免 PG 的所有 0 或 1 输出)。一旦存储了预热记忆,当代理继续与环境交互并推出旧记忆时,我们就用记忆数据来训练模型(在这种情况下是输出单个动作的 3 层密集网络)。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
参考
巴尔托萨顿有限公司。强化学习:导论。麻省理工学院出版社;2018.
HFRX 指数性能表。(未注明)。检索到 2020 年 8 月 03 日,转自https://www.hedgefundresearch.com/family-indices/hfrx
使用 Streamlit-Python 向您的仪表盘添加动画图表
利用 ATP 网球排名数据对比网球四大
介绍
有段时间一直想试用。所以上周末,我花了一些时间修补它。如果您以前从未听说过这个工具,它提供了一种非常友好的方式来使用 Python 为您的数据科学和机器学习项目创建自定义的交互式数据 web 应用程序。您可以与用户交互以获得输入并显示动态图表、表格、地图等。他们的 官方画廊 可能是一个好的开始。它将让您了解使用 Streamlit 可以实现什么。您还会发现一长串来自 Streamlit 社区的推文,它们以自己独特的方式利用该工具进行创作。一定要看看它们,寻找一些灵感。可以使用 pip install 命令( pip install Streamlit )下载 streamlit。
在本文中,我分享了一个使用 Streamlit 构建的动画条形图示例。虽然,实现这一点的一些信息是零零碎碎的,但我无法在一个地方找到太多关于动画图表的信息。我希望这将有助于那些希望在他们的 Streamlit 仪表板中添加动画图表的人。
数据集

由 Carlo Bazzo 在 Unsplash 上拍摄
稍微说一下数据吧。网球是我最喜欢的运动,我决定围绕它做点什么(也因为我真的真的很想念温布尔登💔).总之,在网上搜索了一段时间后,我偶然发现了一些我认为可以使用的东西。直到 2017 年,费德勒、纳达尔、诺瓦克·德约科维奇和安迪·穆雷都被亲切地称为四巨头。在他们之间,他们从 2004 年到 2017 年统治了这项运动。
数据集包含每周 ATP 排名数据,其中包含球员姓名、排名点数、球员排名和排名日期等信息。在 streamlit 中,您还可以以表格形式查看数据帧。在一些基本的格式化之后,我最终的数据框架如下所示。

处理过的数据帧:由阿林多姆·巴塔查尔吉
图表会显示什么?
我想制作一个动画条形图,展示近 20 年来四大银行之间的排名。为了制作动画,我在循环的中经过一定的时间延迟后,不断替换图表中的每周数据。这给了它一个生动的外观和感觉。**
出于可视化的目的,最初我从优秀的旧 M atplotlib 库开始,但我遇到了一些问题,决定继续使用 Altair ,这是另一个可以与 python 一起使用的可视化库。根据我的经验,我发现在我的数据应用程序中使用它比 Matplotlib 有更好的外观和感觉。Streamlit 支持这两个库以及其他一些库。
用户界面
对于 UI,我决定让用户能够自己选择年的范围,并在他们选择的时间段运行动画。选择时间范围后,一旦他们按下按钮'提示图表,动画就会开始。我使用了' 范围滑块'&'**'按钮*** '功能来执行此操作。*
范围滑块:范围滑块的作用是选择一系列数字。它可以用这一行代码创建。该函数返回一个包含用户选择的值的元组。
*x = st.slider('Select the year range',1996, 2017, (1996, 2017))# 'Select the year range' -> Text to display
# 1996 -> The lower bound
# 2017 -> The higher bound
# (1996, 2017) -> Default selected range*

由 Arindom Bhattacharjee 制作的滑块图像
按钮:我加了一个按钮,因为我不想让动画在用户选择时间范围后自行启动。可以创建如下所示的按钮。我运行这个' if '语句中的动画代码。当用户执行一个点击事件时,函数返回一个布尔值 true。
*if(st.button('Cue Chart')):
#run the animation. Value is 'True' when user clicks on it.*

按钮图像作者: Arindom Bhattacharjee
图表动画
我使用 Altair python 库来创建条形图。我创建了一个函数(plot _ bar _ animated _ Altair),它接受两个输入——四大玩家的周数据和周名称。然后它会绘制一个条形图。我最终格式化的数据框架如下所示,将用于绘制图表。streamlit 函数ST . dataframe(df)以如下方式显示 data frame 对象。

示例数据:Arindom Bhattacharjee
*import streamlit as st
import pandas as pd
import time
import altair as alt
from altair import Chart, X, Y, Axis, SortField, OpacityValue#---------------------------------------------------------------#
# Creating an empty chart in the beginning when the page loads
#---------------------------------------------------------------#
bars = alt.Chart(data).mark_bar().encode(
x=X('1:Q',axis=Axis(title='ATP Ranking Points'),
y=Y('0:Q',axis=Axis(title='The Big Four'))
).properties(
width=650,
height=400
)# This global variable 'bar_plot' will be used later on
**bar_plot** = st.altair_chart(bars) def **plot_bar_animated_altair**(df,week):
bars = alt.Chart(df, title="Ranking as of week :"+week).encode(
x=X('ranking_points:Q',axis=Axis(title='ATP Ranking
Points'),
y=Y('full_name:N',axis=Axis(title='The Big Four'), sort='-x'),
color=alt.Color('full_name:N'),
.properties(
width=650,
height=400
)if st.button('Cue Chart'):
for week in week_list: # ***weekly_df*** **->** this dataframe (sample shown above) contains
# data for a particular week which is passed to
# the 'plot_bar_animated_altair' function. # **week** -> Current week title, eg:- 2016-06-10
bars = **plot_bar_animated_altair**(weekly_df,week)
time.sleep(0.01)
**bar_plot**.altair_chart(bars)
st.balloons() # Displays some celebratory balloons for glamour!*
演示
在下面的演示中,我选择了从 1996 年到 2017 年的整个范围,开始时,你会注意到这里只有一个小节(针对罗杰·费德勒),因为其他三个小节尚未转为职业。随着时间的推移,你可以看到 ATP 的总排名发生了变化,其他球员在随后的几年里也加入了进来。他们当前的排名显示为条形的标签。条形被排序,因此排名较高的玩家总是出现在顶部。
演示者:阿林多姆·巴塔查尔吉
结论
总之,在这个兼职项目结束时,我对 Streamlit 的简单性印象深刻。使用任何其他工具来实现这一点肯定会花费我更多的时间。如果你想创建一个动画图表,我希望这篇文章能帮你节省一些时间。
鉴于它最近得到越来越多的支持,我相信他们会增加很多其他有用的功能。感谢您的阅读,并祝您未来一周过得愉快!
也许在你的简历中使用它来链接到你的网站或 LinkedIn 个人资料
towardsdatascience.com](/generate-qrcode-with-python-in-5-lines-42eda283f325) [## 面向初学者的 10 行人脸检测
使用 Python OpenCV 在图像和视频中检测人脸的介绍。
towardsdatascience.com](/face-detection-in-10-lines-for-beginners-1787aa1d9127)*
轻松地将动画添加到您的 Hugo 学术网站
使用 blogdown 和 CSS,三个简单的步骤就可以给你的学术主页带来令人印象深刻的动画。
R 包blogdown是一个非常强大的工具——它允许不熟悉 web 开发的 R 用户使用他们已经熟悉的语言来构建一个功能齐全、面向内容、漂亮的网站。它建立在 Hugo 之上,Hugo【】自称是世界上“最快的网站建设框架”,它有多种主题适合各种不同的用途。
在 R 社区中,也许最受欢迎的主题之一是雨果学术。顾名思义,这个主题是面向学术界工作人员的——更一般地说,它为那些对在极简网站上展示博客帖子、项目和其他媒体感兴趣的人提供了一个很好的入门工具包。
鉴于其受欢迎程度,Hugo 学术登陆页面实在是太熟悉了。虽然不是没有吸引力,但没有人对标准的学术主页特别惊讶或感兴趣。
给 Hugo Academic 增添趣味的一个方法是在我们的主页上使用动画。在这篇文章中,我概述了三个简单的步骤和几行代码来创建一个功能齐全、动画精美的登录页面。通过利用 Hugo 框架的灵活性,并引入一点 HTML 和 CSS,我们可以将 Hugo 学术主页从零带到英雄(至少在动画方面!).
本教程假设你正在从零开始创建一个 Hugo 学术网站。如果你已经有了一个 Hugo 学术网站并正在运行,你应该能够 跳过第 0 步 并稍微修改剩下的步骤。
它还假设你对 HTML 和 CSS 知之甚少甚至一无所知(这很好!).如果不是这样,你可以直接跳到 步骤 3 。
如果你想跳过本教程,只创建一个 Hugo 学术网站的动画版,请随意使用fork my repository,其中包含了制作动画主页所需的所有代码。这个回购包括我的
[*about.html*](https://github.com/connorrothschild/animate-hugo-academic/blob/master/layouts/partials/widgets/about.html)页面 和一个 自定义的 SCSS 文件 !
第 0 步)把你的“关于”页面变成你真正的主页
默认情况下,雨果学术主题的第一部分是一个浮夸的自我介绍(我猜主题的创作者确实值得这样的荣誉)。在我们加入任何动画之前,让我们先把“关于”页面变成用户访问我们网站时首先看到的登陆页面。这要求我们找到文件hero.md和demo.md,并在每个文件中,设置active等于false。这是我们的主页:

对此:

(随着您的进步,您可能需要做一些额外的小改动,例如从导航栏菜单中删除“演示”。)
步骤 1)创建 about.html
我们流程中真正的第一步是修改 about 页面的默认布局。更具体地说,我们的动画将依赖 CSS 选择器,而我们的 about 页面目前还没有。为了激活某些元素,我们需要唯一的标识符,比如 CSS 类和 id。
为了玩弄我们的 about 页面,我们利用了 Hugo 对结构变化的灵活性。正如他们在网站上所说的:
Hugo 允许你用 补充或覆盖 任何主题模板或静态文件,用你工作目录中的文件。
为了覆盖 Hugo Academic 的 about 页面,我们需要将他们现有的结构复制到我们自己的文件夹中,并在那里进行修改。为此,导航至themes/hugo-academic/layouts/partials/widgets/并复制名为about.html的文件。
现在,在名为layouts/partials/widgets/的根目录下创建一个新的文件路径。在这里复制你的about.html文件。(看着眼熟?我们所做的只是在我们项目的个人版本中重现 T2,从而覆盖了 Hugo Academic 提供的 T3。)
或者,你可以复制我在这个项目中使用的 about.html 文件,并将其粘贴到
*layouts/partials/widgets/*。 你可以在这里找到我的文件 。这也可以让你跳过第 2 步,进入第 3 步 !
步骤 2)定制您的文件
随着新创建的about.html驻留在layouts/partials/widgets/中,你可能会注意到你的主页看起来完全一样。这是正确的!在这一步中,我们将自定义 html 文件,以便它可以被动画化。
在about.html中,你会注意到页面的所有元素都是按外观顺序排列的,尽管有很多额外的字符没有多大意义。它应该是这样的:

在整个步骤 3 中,我们将使用每个元素的“类”来定位动画。在上面的截图里(还有在你的about.html页面里!),你会看到分散在各处的班级。尽管学习关于 CSS 和 CSS 选择器的一切已经超出了本教程的范围,我还是推荐阅读一本关于 CSS 中的类和选择器的简单入门,可以在这里找到。
在这一步中,我们将向想要制作动画的元素添加类。(同样,如果这看起来让人不知所措,请随意复制我的 HTML 文件。具体来说,我们将进行三项更改。
首先,我们将向 h1 (header 1)元素添加一个biography-title类。在这里,我们会改变
<h1>{{ $page.Title | markdownify | emojify }}</h1>{{ end }}
到
<h1 class='biography-title'>
{{ $page.Title | markdownify | emojify }}
</h1>{{ end }}
接下来,我们需要包装主要内容,也就是页面中间的大文本块,放在它们自己的类中。在这里,我们采取
{{ $person_page.Content }}
然后用一个div包起来,所以看起来是这样的:
<div class='main-content'>
{{ $person_page.Content }}
</div>
最后,我们将在兴趣和教育模块中添加一个类。我们可以把这一行:
<div class="row">{{ with $person.interests }}
<div class="col-md-5">
<h3>{{ i18n "interests" | markdownify }}</h3>
<ul class="ul-interests">
{{ range . }}
<li>{{ . | markdownify | emojify }}</li>
{{ end }}
</ul>
</div>
{{ end }}{{ with $person.education }}
<div class="col-md-7">
<h3>{{ i18n "education" | markdownify }}</h3>
<ul class="ul-edu fa-ul">
{{ range .courses }}
<li>
<i class="fa-li fas fa-graduation-cap"></i>
<div class="description">
<p class="course">{{ .course }}{{ with .year }}, {{ . }}{{ end }}</p>
<p class="institution">{{ .institution }}</p>
</div>
</li>
{{ end }}
</ul>
</div>
{{ end }}</div>
用这个替换它:
<div class="row">{{ with $person.interests }}
<div class="interests-div col-md-5">
<h3>{{ i18n "interests" | markdownify }}</h3>
<ul class="ul-interests">
{{ range . }}
<li>{{ . | markdownify | emojify }}</li>
{{ end }}
</ul>
</div>
{{ end }}{{ with $person.education }}
<div class="education-div col-md-7">
<h3>{{ i18n "education" | markdownify }}</h3>
<ul class="ul-edu fa-ul">
{{ range .courses }}
<li>
<i class="fa-li fas fa-graduation-cap"></i>
<div class="description">
<p class="course">{{ .course }}{{ with .year }}, {{ . }}{{ end }}</p>
<p class="institution">{{ .institution }}</p>
</div>
</li>
{{ end }}
</ul>
</div>
{{ end }}</div>
识别单个元素的类和 id 的快速技巧是使用浏览器的 检查元素 工具。为此,右键单击您感兴趣的元素,然后单击 inspect element 你会看到一个高亮显示的框,告诉你这个对象的类和/或 ID。有关 inspect 元素和浏览器的更多信息,请参见本页的。
现在,我们可以在步骤 3 的漂亮动画中引用现有的 CSS 类和新的 CSS 类了!
步骤 3)添加 CSS
现在我们已经创建了我们的类,我们可以在一个 CSS 文件中定位它们,并准确地告诉它们如何制作动画。
但是首先,您需要直接在根目录下创建一个定制的 CSS 文件。在你的assets/文件夹中,创建一个名为scss/的新文件夹,并在这个文件夹中,创建一个名为custom.scss的新文件。
SCSS 文件本质上是一个 CSS 文件,但使用 Sass 进行了扩展,它将 本身 描述为“具有超能力的 CSS”要了解 Sass 的复杂性,比如嵌套选择器,请访问他们的指南。**
在custom.scss中,我们将针对我们的“关于”部分中的所有内容。为了做到这一点,我们创建了一个选择器,它针对的是aboutID 内的所有内容。
**#about {
/* Some CSS will go here soon! */
/* This is a comment, by the way. */
}**
为了确保我们瞄准了正确的部分,我们可以继续将属性background-color: red添加到该元素中。顾名思义,这将使✨部分红色。✨
**#about {
background-color: red
}**
正如我们所料,我们的部分背景现在是(难以置信的难看的阴影)红色。

(现在立即删除该属性!这不是我们想要的对来访者的欢迎。)我们也可以通过在#about中嵌套新的选择器来定位部分中的元素。例如,如果我们想改变“传记”标题文本的颜色,我们可以用下面的代码来实现。(这是因为我们在步骤 1 中创建了一个名为biography-title的类):
**#about {
.biography-title {
color: red;
}
}**

你可能会注意到
*about*是用磅(#)定位的,*biography-title*是用句点(.).这就是 CSS IDs 和类的区别。如果你对其中的区别感到好奇,这里有一个 有用的指南 。
现在我们知道了如何在我们的about部分中定位特定的对象,我们可以为我们的第一个元素制作动画了!
步骤 3A)你的第一个动画!
创建您的第一个动画就像几行代码一样简单。举例来说,我们将测试一个动画,它将我们的文本从红色不可见变为黑色可见。在代码中,我们必须做两件事:
1)用@keyframes创建一个动画
**[@keyframes](http://twitter.com/keyframes) yourfirstanimation {
from {opacity: 0; color: red;}
to {opacity: 1; color: black;}
}**
2)将动画绑定到元素
**.biography-title {
animation: yourfirstanimation 5s forwards;
}**
为了分解上面的代码,我们创建一个动画,它有一个起点 ( 0%)和一个终点 ( 100%)。在这两点上,我们定义 CSS 属性,比如颜色和不透明度,如上所示。当我们将动画绑定到一个元素时,就像animation: <animation_name> <duration> <fill_mode>一样简单,CSS 处理所有的中间部分,并自动创建一个平滑的过渡!(填充模式是这三个属性中最复杂的,但是出于我们的目的,我们将一直使用forwards。更多信息,请访问本页。)
总之,这段代码创建了以下输出:
**#about {
[@keyframes](http://twitter.com/keyframes) yourfirstanimation {
0% {opacity: 0; color: red;}
100% {opacity: 1; color: black;}
}.biography-title {
animation: yourfirstanimation 5s forwards;
}
}**

当然,我们不想要一个 5 秒钟的动画,也不希望我们的文本以红色开始。一个干净的动画可能会利用 CSS 的力量来修改元素的位置。在我们的例子中,我们希望一个元素从屏幕的右侧滑入,所以我们对上面的代码做了一些调整。让我们制作一个名为slide-from-right的新动画,它开始于(关键帧 0%)原始位置右侧 150%的元素(因此不在屏幕上),结束于(关键帧 100%)原始位置。这就涉及到translateX的使用,这里你可以读到关于的内容。
**[@keyframes](http://twitter.com/keyframes) slide-from-right {
0% {transform: translateX(150%)}
100% { transform: translateX(0%); }
}.biography-title {
animation: slide-from-right 1s forwards;
}**

我们可以对上面的转换做一点小小的改进。具体来说,我们可以在动画上调用一个缓动函数。缓动功能给转场的流程一种更自然的感觉——我们可以通过在转场的不同点指定速度来添加一些个性,而不是让我们的对象以完美的线性速度飞入。要找到一个缓和函数,请访问easings.net,它允许你可视化所有不同的方法来修改你的过渡的缓和。(对于本教程,我选择了一个看起来很干净的“ easeInOutQuint ”函数,看起来是这样的:cubic-bezier(0.83, 0, 0.17, 1)。)
3B)不要等到延误了才行动
我们希望我们的主页有不止一个标题动画。我们可能还希望用我们之前定义的“从右滑动”转场动画制作它下面的段落。这样做的时候,我们可以向元素添加一个属性,使整个转换看起来更加流畅:animation-delay。顾名思义,这个属性定义了浏览器在开始你指定的转换之前应该等待多长时间。制作我们的main-content div 动画就像复制上面的代码并添加 100 毫秒的动画延迟一样简单。
**.main-content {
animation: slide-from-right 1s cubic-bezier(0.87, 0, 0.13, 1) forwards;
animation-delay: 100ms;
}**
结合以上内容,这将创建一个如下所示的过渡:

不错!看起来很干净。看起来这两个文本块正在竞相迎接你的新网站访问者:)
3C)向左一步!
让我们继续在网页左侧复制我们个人资料的“滑入”过渡。您可能已经猜到了,这就像复制上面的代码并将translateX中的值从 150%更改为-150%一样简单(从我们网页的右侧之外到左侧!)。如上所述,我们将在一个@keyframes规则中定义这个转换,然后将它应用到我们的 CSS 转换中。
**[@keyframes](http://twitter.com/keyframes) slide-from-left {
0% {transform: translateX(-150%)}
100% { transform: translateX(0%); }
}#profile {
animation: slide-from-left 1s cubic-bezier(0.87, 0, 0.13, 1) forwards;
}**

步骤 3D)最后,淡化
我们页面上唯一没有动画的是“兴趣”和“教育”内容块。当然,你可能不希望这些出现在你的主页上(我的教育之旅还没有强大到足以保证在我的主页上有它自己的部分!).但是为了动画化主页的默认配置,让我们继续,一旦滑动过渡完成,让这些内容块淡入。
如果你一直在关注前面的@keyframes规则,你可能已经猜到代码会是这样的:
**[@keyframes](http://twitter.com/keyframes) fade-in {
0% {opacity: 0}
100% {opacity: 1}
}**
…你是对的!
现在,我们将这个fade-in规则应用于我们在步骤 1 中创建的interests-div和education-div。但值得注意的是,我们希望等到我们的内容从网页的任何一边滑入之后,才淡入这些 div。因此,我们将再次使用animation-delay属性。因为我们的滑入动画需要一秒钟才能完成,所以我们可以在一秒钟的延迟后开始淡入动画。为了使过渡在视觉上更吸引人,我们也可以错开它们,这样education-div在 interests-div后半秒就淡入淡出。
**.interests-div {
opacity: 0;
animation: fade-in 1s forwards;
animation-delay: 1s;
}.education-div {
opacity: 0;
animation: fade-in 1s forwards;
animation-delay: 1.5s;
}**
现在,我们有了一个最终的主页,看起来像这样:

为了使我们的 SCSS 文件在不同的浏览器中更加健壮,我们可以把我们完成的文件放到 CSS Autoprefixer 中。这为我们的 CSS 文件添加了额外的代码行,这样所有浏览器在页面加载时都会呈现相同的动画。你完成的 SCSS 文件应该看起来像这样。
扩展动画
本教程旨在教你如何制作你的主页动画的要点(对于任何 Hugo 网站,不仅仅是学术网站)。具体来说,你应该能够 1)通过它们的类和 id 创建和识别 CSS 元素,2)使用 CSS 定位它们,以及 3)使用@keyframes规则动画化它们。虽然说起来容易做起来难,但是应用这三条规则将会使你的主页对新访问者更有吸引力。
CSS 动画的全部力量在本教程中没有涉及。动画的进一步应用不仅仅是制作一个物体位置的动画。我把那留给你!
对于那些感兴趣的人来说,我的主页充满了 CSS 属性,这使得它与众不同;有些访问者听说我的网站是雨果学院的网站时感到很惊讶!

对于那些感兴趣的人来说,我的个人网站的代码(和这个一样,有一个about.html和一个custom.scss文件来加载)可以在这里找到。我期待看到你的动画主页!
感谢阅读。在了解更多关于我的信息,或者在 Twitter 上关注@ CL _ Rothschild。****
为家庭监控摄像机系统添加基于云的深度学习对象检测功能
从 Jupyter 到无服务器 Web 应用的实用深度学习
我最近在我的房子周围安装了一个配备了四个摄像头和一个网络录像机(NVR)的监控系统。不幸的是,几乎所有的假警报都是由移动的植物或树影或松鼠触发的。这些警报都不能被系统自带的传统图像处理功能过滤掉。
像大多数深度学习实践者一样,我知道对象检测程序可以过滤掉这些错误警报。但它们要么需要一份昂贵的商业合同,要么需要一台连接我家庭网络的电脑。因为我想保持低成本,拥有一台电脑似乎是正确的选择。然而,这仍然是一笔相当大的初始资本投资,外加经常性的 24/7 电力成本。计算机还需要安装、维护和货架空间。它的风扇噪音或壁橱散热是另一个我不喜欢在家里处理的废话。

大多数假警报只是由移动的树荫和植物触发的。使用传统的图像处理技术,例如调整对比度阈值或设置活动区域,无法滤除这些错误警报
经过进一步研究,我发现使用无服务器 web APIs 是最好的解决方案。它不仅反应迅速,而且根据使用情况收取很少的费用。我还想自己优化深度学习算法,或者为高级深度学习应用重新配置实现。因此,我选择了运行在 AWS 上的 MXNet。这种结合允许使用 Jupyter 进行简单的深度学习代码开发,优化的库性能,丰富的预训练模型,以及强大的开放云基础设施。
以下是我的实现方式。明确地说,我的目标是保持低成本,同时能够使用我首选的对象检测算法。例如,我选择不上传整个视频,然后使用视频识别算法。它会在网络带宽、内存、CPU 和云中存储方面花费更多。
- 使用系统自带的传统图像处理技术,尽可能减少误报警事件。例如,我屏蔽了花园中的动作,因此只有楼梯上的动作才能触发事件。
- 一旦事件被触发,就会生成一个视频并存储在 NVR 中。对于我的应用程序来说,大多数视频都在 5 到 20 秒之间。然后视频在本地被处理以生成一些照片,比如说每 10 秒一张照片。
- 这些照片然后被发送到 AWS 进行物体检测。可以对异议检测的结果进行编程,以触发通知事件,例如向我的手机发送文本消息或简单地将其写入日志。
因为每个安全系统都是不同的,所以在本文中,我只关注如何在 AWS 中设置它。为了演示本文中的功能,我在 CloudFront 中使用了一个 web 接口来从互联网上检索任何图像。一旦接收到图像,它就触发 Lambda 函数调用对象检测代码来处理照片。然后,带有边界框的结果图像被存储在 S3。有关更多信息,请参见[1]和[2]。在 Lambda 上调试几乎是不可能的,所以在移植到 Lambda 之前,我先在 Jupyter 上编写我的对象检测代码。
所有的脚本和代码都可以在 Github 上获得。阅读完本文后,您可以选择通过重用云堆栈来优化您的对象检测代码。或者,您可以根据自己的需求调整云堆栈,从而重用对象检测代码。
你首先需要一个 AWS 账户。要实现本文中的应用程序,它完全属于免费层。登录 AWS 后,进入 CloudFormation 并使用 template.json 创建一个栈。

在下一个屏幕中,给栈起一个名字(我用的是“dl-lambda”)。CloudFormation 将自动构建云基础架构。

成功创建堆栈后,转到 Outputs,其中的值(在本例中是 d2yf3xcp7rorxr.cloudfront.net 的)是访问 Lambda 函数的 URL。

点击那个,你会来到一个由存储在你的 S3 桶中的 frontend.html 指定的网站 dl-lambda-推论 app-*****。在这张图片中,我的友好的邮递员携带着一个包裹在我的 NVR 上引发了一个事件。因此,我的 NVR 1)存储视频,2)生成照片,然后 3)将照片发送到这个 Web API。

邮差周围具有边界框的照片然后被存储在 S3 桶 D1-λ-图像-输出中。

在我开始之前,我已经用 Jupyter 编写了我的物体检测代码 dl-lambda.ipynb 。为了在本文中保持简单,我使用了来自 Model Zoo 的基于 ResNet 的预先训练好的单镜头多框检测器。然后,我将 Python 代码从 Jupyter 复制并粘贴到 inference.py 中,它运行 Lambda 处理函数。请注意,为了便于移植,我已经清楚地标记了代码部分。
dl-λ. ipynb
推论. py
在运行代码几周后,我的 4 摄像头系统甚至在严重优化前每月花费约 2 美元。如果您的成本太高,请使用机器上的图像处理功能来减少误报警事件的数量。增加每张照片的视频时长也有助于减少 Lambda 事件的数量。请注意,您不需要大于 512x512 的图像,因为大多数算法不会使用超过 512 x512 的数据。
以下是下一步的一些想法:
- 预先训练的模型可以识别数百个物体。对于家庭安全,只有人和车是特别感兴趣的。神经网络的复杂性可以显著降低,从而只关注这两个类别,以节省处理成本并缩短执行等待时间。
- 显然可以上传视频进行复杂的深度学习视频识别。
- 分析结果可以存储在数据库中以保存记录。
- 如果检测到人或车,发送短信。
通过几个简单的步骤,您可以将现成的监控摄像机系统升级到尖端的深度学习功能,同时保持低成本。
参考资料:
[1] Anders Christiansen,将机器学习模型部署为无服务器 API,将机器学习模型部署为无服务器 API(2020),AWS 机器学习博客
[2] Boris Ivanovic 和 Zoran Ivanovic,如何用 AWS Lambda 和 Tensorflow 部署深度学习模型 (2017),AWS 机器学习博客
为 Julia 向我的图形库添加颜色和特性(第 5 部分)
向我的图形库添加一些非常棒的新功能!

第 4 部分(其他部分的链接请点击此处!)
在我的上一篇文章中,我给我的代码留下了几个明显的问题,最明显的是无法独立地改变组合中任何特定对象的颜色。这是一个很大的缺陷,因为这意味着我因缺乏区分不同数据的颜色而受到阻碍,这也意味着被解析的形状与两个轴的笔画相同,这当然不是最佳的。然而,我确实设法用同一个用户命令让 Julia 的调度程序同时为数据帧和数组工作。
修复这个中风问题是我一直有点担心的事情,因为这将是一项相当不错的工作,但每当最佳改善即将出现时,任何工作都不为过!
解决我们的问题
正如我之前可能解释过的,这个问题是由于我们所有的对象都是在相同的上下文中绘制的,并且将通过在组合中创建一个新的上下文来解决。下面是一个包含两个上下文的合成示例:

这就是 introspect()方法派上用场的地方。如果我们内省这个组成部分,我们可以清楚地看到我们的两个背景:

棕褐色的点是上下文点,后面是它们各自的形状,R 和 C 是蓝色的正方形,红色的三角形表示应用于特定上下文中的对象的属性,在本例中,红色的三角形表示 fill()方法。让我们简单地从在原始的 arrayscatter()函数中获取轴和点之间的不同颜色开始。我要做的第一件事是为轴线的新上下文添加字符串代码:

该行之后的第二个上下文用于输入数据。为了完成这个函数,我需要在表达式的末尾添加第二组括号来关闭上下文和 compose 方法。我还擅自将这两个单行 for 循环移到了另一个循环中,这是我一直在拖延的事情,没有什么特别的原因。

现在为 _dfscatter()函数!
这个函数不会像 array scatter 函数那样简单,因为这次我们需要在解析 zip 循环中迭代地添加多个上下文。

我们要做的第一件不同的事情是,在第一行中,我们不会为新出现的形状创建上下文,因为我们必须遍历不同的数组和形状。相反,我们将只添加一个逗号。

在 zip 循环内部,只需要在表达式之前有一个上下文,在表达式之后有一个括号和逗号,为新的形状添加。接下来,我们需要为正在解析的形状添加一个笔画,以便进行更多的定制。在未来,我可能还会添加笔画宽度。这与最初添加填充的方式完全相同。

我还为这个参数添加了一个缺省值,这样我们就可以在没有 stroke 请求的情况下得到一个 stroke,这非常简洁。现在把它画出来:

有用!
现在让我们测试另一个函数 _dfscatter()。首先,我要用一堆不同的数组制作一个超大的数据帧。

然后,我将创建一个新数组,其中包含函数要接受的形状:
shapes = [Circle(.5,.5,.01,:orange),Circle(.5,.5,.01,:blue),Circle(.5,.5,.01,:purple)]
插入我们的价值观:
plot = Scatter(df,:Y,shapes, false)

看起来棒极了!
只是为了好玩,让我们看看这一个的树!

这一定有很多原因,因为很明显自省出了问题!
新对象
在上一篇文章中,我添加了一个新的形状,矩形对象,但是在这一篇文章中,我想用网格把它提升一个档次。我对定制网格的有趣方式有一些不同的想法,但我突然想到,我计划实现的一些其他东西将使我的许多想法成为可能,而不需要定制网格。所以我决定让用户加入一定数量的分区。我们能做的是处理除法的数目,简单地用一除以这个数,例如,如果 4 是我们的数,那么我们将得到 0 . 25 这个数。下面是如何翻译成朱莉娅:
function Grid(divisions,colorx=:lightblue,colory=:lightblue,thickness=.02)
division_amount = 1 / divisions
接下来,我们需要一个总额为即将到来的循环,我们可以用来创建我们的线。当然,现在这将是零。我们还需要像往常一样创建一个上下文。
total = 0
Xexpression = "(context(), "
如您所料,接下来我们需要的是一个循环来填充网格中的所有行。为此,我选择了 while 循环。我们可以做的是,为总和小于 1 的情况创建一个 while 循环,并在每次循环时将除法的百分数加到这个数上。我们可以用这个数字来定位,也可以在一定范围内结束循环。这是我想到的:
while total < 1
total = total + division_amount
linedraw = Line([(0,total),(1,total)],:lightblue,thickness)
exp = linedraw.update(:This_symbol_means_nothing)
Xexpression = string(Xexpression,exp)
end
请注意,X 线的位置实际上是在 Y 轴上改变的,但是是在 X 轴上投射的,因此 X 坐标是 0%和 100%。在我们的四个例子中,我之前提到过,我们的除法大小是 25 %,或者说是 0 . 25 的浮点数,我们将把除法的总数加上 0 . 25,然后在 Y 轴的这个位置画一条线到 X 轴的 100%。之后,将添加表达式,循环将再次开始,现在我们的总数增加到. 5,依此类推,直到循环被大于或等于画布 100%的线条打断。
接下来,我们将对 y 重复同样的操作。之后,我们将把它们加在一起,就像我们对最终产品的所有其他函数所做的那样,最终产品看起来像这样:

还有一件事要做,就是在底部添加我们的类型 return,以及我们的 update 方法来返回一个标签。
update() = string(composeexp)
(var)->(update;composexp)
为了测试它,我们只需将标签添加到数组散布函数的开头。

现在测试一下:

没用。
奇怪的是,这返回了一个解析错误,因为在 Line 对象中使用了正则表达式…这很奇怪,因为 _arrayscatter()函数在使用相同的精确对象和相同的精确表达式时工作得很好,所以这让我有点困惑。正如你所看到的,我也打印出了表达式,表达式看起来很完美,所以我真的不确定问题可能是什么。虽然这可能是一个相当严重的问题,但我确信我们可以在下一篇文章中解决它,但是现在让我们继续
自定义标签支持
这是我一直想补充的有趣的东西。这将为 Hone 使用自定义元信息执行命令的扩展打开大门。虽然这听起来非常不安全,但重要的是要记住语法必须符合上下文及其语法的范围,因为 Julia 仍然需要解析代码。此外,我不认为任何人应该担心绘图模块中的漏洞,它可能主要用于笔记本电脑内部。这很容易添加,只需修改分散函数的参数,在坐标解析之前将其包含在表达式中:

轻松点。
结论
好消息是坐标解析器和调度都工作得很好,实际上性能甚至更好。坏消息是,由于这个奇怪的正则表达式问题,我无法创建网格。我谈到的最后一件事实际上是我真正感到兴奋的事情。自定义标记将允许用户自定义他们自己的扩展并共享它们,它是一个绘图软件,相当于在视频游戏中包含一个地图编辑器。我肯定会在未来对此进行演示!
向我的模块化图形库添加控件
Hone.jl
用控件表单扩展 Hone.jl 的可用性。

如果您一直在关注 Hone.jl 的开发,这是一个模块化的、面向对象的图形库,可以有效地在静态类型语言中隐藏类型,那么您可能还记得我上次离开时留下的问题…每当解析新网格对象的连接表达式时,都会返回意外的\ ",\ "错误。最初,我认为这可能是我用来在表达式中生成字符串的正则表达式的问题。

这实际上非常令人沮丧,花了整整半个小时才解决,但这不一定是我的错——嗯,是我的错——我实际上错过的是错误中间的,。我对正则表达式字符串分隔符的使用无疑使错误变得有点混乱。幸运的是,缺少逗号是一个非常
解析字符串时经常出错。
现在创建我们的网格对象:
h = Grid(4)
并调用 Grid.show()方法:

太棒了。
现在我们只需要把它加到我们的散射函数中。这就像创建网格并将其标签添加到散布函数中的表达式一样简单。下面是当一个数组被传递时分派路线的功能:

我认为将网格作为一个对象而不是一个细分量添加到参数中是最优雅的,这样可以使模型的其他部分与方法论保持一致。现在我们创建一些无意义的数据:

嘣!
我们有网格了!
我想实现的下一件事是保存渲染的矢量图形的能力。为此,我在 Hone 的所有对象函数中添加了一个新的方法定义:
save(name) = draw(SVG(name), composition);
然后将其添加到我们类型的导出数据和方法的长列表中:

现在,无论何时用字符串调用 save()方法,都会保存一个本地 SVG 文件,
酷!
速度恶魔
我的长期读者可能知道,我喜欢速度。我决定(再次)测试 Plots.jl 的速度。

5 秒 4.11 M 分配!
这还不算太坏——所有必需品都考虑在内。但是 Plots.jl 如何与之抗衡呢?

一些观察结果:
- Hone 需要更多的内存来渲染图像。这可能部分是由于元表达式,部分是由于矢量和光栅化图像渲染之间的差异。
- Plots.jl 的加载时间与地块本身的加载时间大致相同,总共约为 15 秒。
- 剧情。JL 平均要慢 2 秒左右
- 他们的情节比我的更漂亮,因为我还没有添加一些突出的特征,比如传说。
控制
对于在 Hone 中实现控件表单,我有一些有趣的想法。这将允许更多的图形绘制,以及增加边距和改变个别上下文的分辨率。这是我开始使用的函数:
function Frame(width,height,m_left,m_right,m_top,m_bottom)
tag = string("context(UnitBox(0,0," ,width,",", height, ",",m_left, "", m_right,
",",m_top, ",", m_bottom,"))")
add(obj) = tag = string(tag,obj)
show() = exp = Meta.parse(string("draw(SVG('c'),",tag, "))"));eval(exp)
save() = draw(SVG(name), eval(tag))
(var)->(add;show;tag)
end
然而,这个函数有几个基本问题。最重要的是,不涉及任何组合,这意味着在向表单中添加对象后查看表单是不可能的。另一个问题;add 函数只能在整个函数处理完之后调用,如果我们要添加 compose 方法,设置标记的第一行如果没有括号就无法解析。这有点自相矛盾,因为您需要创建对象来添加它,但是如果没有来自对象标签的右括号,您就不能创建对象。考虑到这一点,我重新编写了函数:
function Frame(width, height, lm, rm, tm, bm)
base = string("compose(context(units=UnitBox(0,0,",
width, ",",
height, ",",
lm, ",", rm,",",
tm, ",", bm,
")),")
objects = []
composition = nothing
add(objects) = composition,objects,tag = _frameup(base,objects)
show() = composition
tree() = introspect(composition)
save(name) = draw(SVG(name), composition)
(var)->(add;show;tag;base;objects;composition;save;tree;width;height)
end
这一次我决定创建一个名为“objects”的 iterable,它将把我们所有的 Julia 类型存储在一个我们可以循环访问的数组中。我所做的一个重大改变是添加了 compose 方法和 _frameup()方法,这将为我们返回解析后的组合、对象和元标记。

这个函数本身相当简单,尽管它的返回列表很长。首先,我们在一个迭代循环中添加每个对象的标签。这个循环肯定不是我喜欢的方式,可以缩短为
tag = [string(tag,object.tag) for object in objects]
无论如何,之后,我们为 compose()方法添加括号,然后解析标签并在最终返回之前创建一个组合。
现在我们有了 add()函数和一个操作框架,接下来要做的是修改我们的散布函数,使其适合框架,而不是停留在没有参数的上下文中。我首先用默认框架向我的函数添加了一个参数:

现在我们可以在 Frame 上使用 add 方法——哦,等等,我们不能。在我们可以渲染我们的框架之前,还有一个重要的问题。_frameup 函数调用要传递的对象的标记,但是我们的对象在技术上确实具有属性“tag”,但是我们无法在创建对象的同时传递带有子“tag”的对象。为了解决这个问题,我简单地添加了一个名为“TransferType”的随机结构来保存子标签。我们可以快速构造这个类型,并把它放入函数中,就像它是我们的散射对象一样。

现在我们将再次填充我们的函数:
plot = _arrayscatter(x,y,shape)
当我们调用 show()方法时:

如果你仔细看左上方,
那是我们的散点图!
所以很明显,伸缩将会是一个痛苦的问题,我将不得不尽快处理,并且我可能会对库增加更多的控制。很多事情进行得特别顺利,但也有很多事情进行得相当糟糕——但总的来说,我认为这个项目进行得很好。关于 Hone.jl 的伟大之处在于,一旦我完成了基本方法,渲染任何东西都会变得非常容易。好消息是:这些更新已经被推送到 Github 上的 0.0.2 分支:
模块化的形状,网格和线条容易预制快速绘图简单和轻型车床集成(即将推出)…
github.com](http://github.com/emmettgb/Hone.jl) 
更好的消息是,我刚刚向 master 推送了车床 0.1.0 版本!0.1.0 中有很多很酷的特性,比如幂逻辑、实验性的基于网格的卷积神经网络,当然还有一些更棒的东西!车床很快就要和 Hone 交织在一起了,所以这肯定是令人兴奋的。Hone 和车床的一个显著优点是我可以使用 Hone.jl 而不用接触它的代码库。
[## 车床
车床使用更快的方法和简单的方法。使得包装快速、简单且轻便。许多工具和模型…
车床. ai](http://lathe.ai)
如果您还记得,我添加了一个参数,用于将自定义元标签插入到 Hone 对象中,因此将它与机器学习的元素结合起来肯定会很有趣。一个很好的例子就是置信区间,我不需要把它们编程到 Hone 中,我可以用这种方式为使用车床的 Hone 编程一个扩展。
给五星评论添加误差线:贝叶斯方法
使用 PyMC3 为🧦挑选合适颜色的袜子

当你在网上购买一双新袜子时,你自然会寻找评论分数最高的那双。在你的搜索查询中,你经常会看到⭐⭐⭐⭐⭐对️️️️show 的 5 星级评价。但是你有多愿意买一双只有两个用户 5 星评价的袜子呢?你会从 100 个评论中平均 4.5 星的一双中挑选吗?也许不是,但为什么呢?虽然你知道 5 肯定是大于 4.5 的,但是只有两个评价就有些让你犹豫了。
当评论数量很少时,你完全有理由怀疑评级的有效性。这些评级只是一个没有任何统计不确定性的数字(平均值)。如果我告诉你我的两个堂兄弟的平均身高是 3 英尺 5 英寸(约 100 厘米),这并不能告诉你太多。是两个身高一样的学龄前儿童,还是一个篮球冠军,一个学步?少量观察值的平均值通常没有那么多信息,因为它们可能带有巨大的不确定性。
这种情况有点类似于两个 5 星评论,但有一种方法可以补救。除了平均值 5,我们还知道分布情况(想想评论的直方图)。这篇文章的目标是展示如何使用 贝叶斯统计 我们可以翻译评论的数量,或者更准确地说它们的分布,来推断真实评级的不确定性。你是否需要买一双新袜子,不知道两个 5 星评价的物品你能信任多少?在这里,我们将了解如何将错误栏附加到这些评论上,并使用它们来对搜索查询中的各种评论进行排名。
注意:此分析范围有限,应被视为贝叶斯推理中的一个完全理论性的练习。分析中的一个主要假设——所有的评论都是诚实的——在大多数现实生活中显然是不成立的。
用于产生结果的所有代码都可以在这个笔记本中找到。
模型
我将把每篇评论建模为一系列抛硬币的过程——毕竟这是一篇关于统计的文章!
为了清楚起见,我将使用单词 review 来表示产品的个人评分,使用单词 rating 来表示所有用户评论的平均值;个人评估分数可以是 1 到 5 之间的整数(例如 3 或 4),但评级可以是同一范围内的实数(例如 3.8)。根据大数定律,观察到的评分应该收敛到产品的真实评分。显然,这里我做了一些隐含的假设,即(1)项目有一个真实的客观评级(基于质量,价格的公平性等。)和(2)所有用户评论都是诚实的;后一种假设显然不适用于大多数现实生活中的评论,这些评论可能包含付费评论或虚假评论。
回到模型:让我们假设每个顾客用四次投掷有偏向的硬币来决定袜子的评价分数。每次硬币正面着地,就会增加一颗星,如果硬币反面着地,就不会增加一颗星。产品越好,硬币 p (人头概率)的偏差越高。
为什么是四次而不是五次?这些商品的最低评级是一星(我们没有 0 星评论),所以我们只有四次抛硬币的机会。观察到的人头数加 1(第一枚硬币)的总和给出了袜子的最终审核分数。例如,序列 H,T,H,H 相当于一个 4 星评论,而 T,H,T,T 的结果是 2 星。在此模型中,每次审核本质上都是二项式过程的结果,其中结果的概率可以用二项式分布表示为

情商。一
其中 p 为硬币的偏向, n 为总翻转数(此处为 4),而 k 为观察头数。添加 k +1 中的 1 是为了固定从 1 开始而不是从 0 开始的评定等级。该模型中的关键假设是硬币的偏差 p 与产品的真实评级相关,因此 p=0 总是导致硬币落在尾部,或者等同于 1 星评级(糟糕的产品),而 p=1 总是导致正面,这意味着 5 星评级(令人敬畏的产品)。同时, p=0.5 导致平均每次投掷两个人头,对应于 3 星评级(平均产品)。为了从数学上安慰自己,你可以使用二项分布 np 的平均值,对于 p = [0,0.5,1] 分别产生 1、3 和 5 个评级(我在这里添加了额外的 1)。让我们使用一些 python 代码来证实这一点:
太好了!现在我们可以使用这个模型生成一些模拟数据来玩。在我们继续之前,我将定义一个 scaler 对象,它将等级转换成概率,反之亦然。我们的可观察值是范围在 1 到 5 之间的评级(评论的平均值),但是我们最终会对范围在 0 到 1 之间的概率 p 进行推断。因此,有一种简单的方法在这两者之间来回转换是很有用的。
数据生成:模拟袜子评论
既然我们有了评级的生成模型,我们可以用它来生成模拟数据。为了模拟每个产品的评论,我们需要的是评论的数量和项目的真实评级,这决定了硬币的真实偏差 p 。每次回顾都是四次(有偏向的)掷硬币所观察到的正面之和,所以我们需要做的就是从带有参数 n=4 和 p=scaler.r2p(真实评级)的二项分布中抽取随机数。
让我们按照这些步骤来生成一些模拟袜子评论!为了简单起见,我将创建一个 Sock 数据类,它有三个主要属性: n_reviews、true_rating 和 color 。
酷!现在,假设菜单上有三种不同类型的袜子:蓝色、橙色和红色。
我对这些项目的真实评分为 3.2、4.0 和 4.5,即蓝色的袜子很好,橙色的很好,红色的很棒!作为一个买袜子的人,我们的目标是买到我们能找到的最好的袜子,但问题是这些商品的真实评级是不可见的。我们唯一能观察到的是真实评级的统计估计,也就是平均客户评级。如果我们有很多评论,平均评级是真实评级的一个很好的估计,但如果我们没有呢?
在本例中,我们假设橙色袜子(4.0 颗星)客观上不如红色袜子(4.5 颗星),但想象一下,出于某种原因购买橙色袜子的仅有的两名顾客对他们的购买超级兴奋,并决定给它 5 颗星(这意味着他们所有的硬币随机落在头上)。在这种情况下,平均评分 5(我们看到的)将大于真实评分 4.0(我们看不到)。因此,仅通过比较平均评级,我们会得出橙色对优于红色对的错误结论。
为了模拟这一点,我将作弊并选择随机数生成器的种子,以便橙色袜子的两个评论最终都是 5 星(这已经在 Sock 数据类中实现)。让我们快速浏览一下所有评论的归一化直方图。

虚线是潜在的真实评级,实线是所有评论的平均值。请记住,不受随机性影响的真实评级是不可观察的。这里的目标是挑选一双真实评分最高的袜子。从图中可以看出,如果我们按照最高的平均评分选择橙色对,那我们就犯了一个错误,但是我们如何调整我们的指标来选择正确的颜色呢?
贝叶斯推理
也许并不奇怪,我将使用贝叶斯定理来推断袜子的真实评级,使用观察数据作为证据。我们希望在给定所有用户评论的情况下,找到每个产品的真实评级:

情商。2
右侧分子中的第一项是先验(我们对真实评级分布的初始信念),第二项是可能性。为了保守起见,我们可以使用一个平坦的先验评级,也就是说,我们假设在看到任何评论之前,袜子有 1 到 5 颗星之间的任何评级的可能性是相同的。每个单独审查的可能性是一个二项分布,如等式所示。1,因此为了构建完全可能性,我们只需要用观察到的评论分数替换每个 k ,并将所有内容相乘。请记住,硬币的偏差 p 之间存在一对一的映射关系(参见等式 1。)和真实评级(等式。2)我会交替使用它们。
为了找到每个项目真实评分的概率分布,我将使用 PyMC3 对它们的后验概率进行采样。下面的函数接受 Sock 对象的一个实例,并从等式的后半部分返回 MCMC 样本。2.查看 PyMC3 如何工作的细节超出了本文的范围,但是如果有任何困惑,请在评论部分提问或在 Github Repo 上发布问题。
注意:在上述函数的先验部分,我使用了一个 Beta 函数 符号来描述 p 的平坦先验,因为 Beta 是二项分布的 共轭先验 。这在技术上是不必要的,因为我们没有用分析的方法解决这个问题,但我还是做了,所以我可以写下这个小纸条!
现在让我们对所有袜子的后验样本进行抽样,并找出概率分布的平均值和标准差。
现在除了平均值,我们还有一个标准差!我们可以将其作为误差线添加到原始直方图中(这里我有点粗心,只是在平均值周围添加了标准误差,严格来说,这对于非正态数据是不正确的)。它看起来是这样的:

正如所料,评论数量较多的袜子误差较小。非常有趣,但可能不如我们希望的那样信息量大。只有 2 个评论的橙色袜子的推断评级仍然大于有 100 个评论的红色袜子的推断评级。那我们怎么挑选正确的一对呢?
让我们检查一下后验概率的 KDE,看看分布的实际形状。该图显示了每一对真实评级的后验概率,即:我们对评级可能是什么的初始信念(在这种情况下,所有评级的均匀概率),基于用户评论观察的可能性(等式 1 的二项式可能性)进行更新。1).

这里我们来做几点观察。提醒一下,真实评分为(3.2,4.0,4.5)的(蓝色,橙色,红色)袜子各有(20,2,100)条评论。首先,我们看到后验 pdf 的宽度与每个项目的评论数量成反比:我们的评论越多,我们对真实评级的最终估计就越不确定。第二,蓝色和红色 pdf 的峰值非常接近真实的评级,但是对于橙色的一对就不那么接近了。这是有意义的,因为对于橙色袜子,我们只有 2 个观察值,这不是很有限制。橙色的长尾理论承认了一个事实,那就是它对最终结果非常不确定。但是,它仍然给我们提供了我们在分析中寻找的信息。
如果不使用后验平均值(第 50 个百分位数)来对袜子进行排序——正如我们在第二个图中所做的那样——我们使用第 5 个百分位数会怎么样?通过这种方式,我们可以 95%确定真实评级高于这个数字。根据这种排名策略,如果袜子的评级较低,或者评论数量较少——这意味着分布中的尾部较宽——它们将在列表中排名靠后。对我们的后验 pdf 使用第 5 百分位导致以下排序:

瞧啊。
就是这样…现在我们已经在袜子评论中添加了误差栏,我们可以放心地购买最好的一双了。这肯定是托马斯·贝叶斯牧师会做的!
重要提示 :不要试图在现实生活中实现这种分析。仅仅根据这一分析结果购买的袜子或其他类型的内衣可能与你衣服的其他部分不相配。
将 Julia 的多态分派添加到我的绘图库中(第 4 部分)
方法论之争!
第一部分
在之前的文章中,我创建了一个坐标解析器和一个功能上面向对象的(我意识到这听起来有多疯狂)系统,用于将元数据从对象传输到最终的对象,看起来有点像这样:

从那时起,我只改变了模块整体的一个方面。该模块现在导出函数,而不是包含来自其他模块的函数。因此,现在使用模块的方式与在笔记本中使用代码的方式相同,例如:

相对于:

但做完这些出口后,一个想法闪过我的脑海。显然我们可以画出一个 X 和一个 Y,但是对比数据呢?毕竟,大多数情况下,您需要散点图来比较多个 X 的一些数据,而不仅仅是可视化单个 X 的位置。为了改变这一点,我计划利用 DataFrames,因为 Lathe 已经作为一个依赖项添加到 Project.toml 而且 Lathe 有 DataFrames.jl 作为依赖项,这意味着任何使用 Hone 的人很可能已经在他们的计算机上安装了 DataFrames。
有两种主要的方法可以解决这个问题。一种方法对最终用户来说不是最佳的,但却容易得多。然而,另一种方法会更困难一点,但从长远来看会使方案更好。我决定选择第一种。
我开玩笑的…
通常,在类似的编程语言(如 R 或 Python)中,我们必须用条件来检查进入函数的类型,例如:

这没什么大不了的,这让我想起了主循环事件编程,在那里你必须不断地检查标志的条件来执行任何事情,否则,它将在处理器的每个时钟周期执行,这有点滑稽。幸运的是,既然我们是用 Julia 编程,我们可以做得更好。我们可以通过使用 Julia 的多重分派来做到这一点,我们可以从编写两个需要处理两种不同类型的函数开始。

现在我们只添加这两行简单的代码,将这些方法作为结构的属性来应用:

现在我们用两种类型来称呼它:

这些函数根据类型相应地运行。
我们可以将这个想法应用到 Hone 中,制作一个新的分散函数来处理数据帧而不是数组。我把我们旧的 Scatter 函数重命名为 _arrayscatter,我们的新函数将是 _dfscatter。出于个人偏好,我使用这种带有下划线的命名方案,因为它有助于区分最终用户功能和用户永远看不到的后端功能,尽管这不是必需的,但我认为保持一致很重要。

现在我们只需添加我们的调度行:

注意,我必须首先将 DataFrames.jl 加载到会话中,才能使用 DataFrame 类型。另一件要注意的事情是,Y 的类型断言是 Symbol,而不是您可能期望的 Array,这是因为我们假设我们要用作 Y 的数组在数据帧内部,所以我们可以这样调用它:
x[y]
奇怪的是。
现在我们可以构建一个数据框架来证明一切都在正常运行:
df = DataFrame(:one => [1,5,2,3], :two => [8,4,5,3], :y => [5,6,2,3])
当我们通过函数传递它时:

因此调度是有效的,但是我们仍然需要为数据框函数的绘制添加逻辑。为此,我将首先从常规的 scatter 函数中提取代码,然后复制坐标解析器,以便它分别解析两个 X。我们要寻找的结果应该是散点图上的另外四个点,总共八个点。因此,首先我将向您展示结果,然后深入分析我必须进行的重构:

对于解释,我将逐行进行,因为这里有很多。首先,在获得最大值和最小值的分散函数中;我不得不将 X 的最大值的计算转移到迭代循环中,因为这一次我们循环通过具有不同最大值的不同数组。然而,我确实保留了 Y 的原始位置:
function _dfscatter(x,y,shape,debug=false)
topy = maximum(x[y])
接下来,需要移动的循环将原始函数中的所有坐标转换为百分比,并将其放入循环中(应该如此。)

除此之外,实际的解析被移到遍历列的循环内部。一个很明显的缺陷是,没有办法在坐标平面上区分两个 X,
所以让我们改变这一点。
这个过程的第一步是将我们的“shape”参数作为多态分派的类型断言中的一个数组,如下所示:

现在,我们将简单地在循环中添加一个计数器,从零开始,直到循环完成。这将有助于确定我们在数据框架中的位置,尽管我将来可能会更改这一点,以使用列的索引来代替。

现在你可能会认为,如果我们试图对单个形状使用我们的函数,它将不再工作,但这根本不是真的,它仍然可以正常工作——Julia 会假装它是一个单个的 dim 数组,这让我感到惊讶。这揭示了一个新的问题,然而,这是我甚至没有想到的上下文的问题,因为填充颜色只能在每个上下文中声明一次,但我肯定会在下一篇文章中详细阐述这一点,因为在这篇文章中我还想得到一些其他的东西!
添加新形状。
幸运的是,我为未来的自己做了非常简单的事情,我们可以通过简单地撕掉我们的圆形函数开始创建我们的新形状,我将把它重命名为矩形。

正如我假设的那样,我是正确的,所有这一切都需要为矩形添加参数并重命名函数,没有任何复杂的事情。最棒的是现在我们可以吃饱了
圆形。
明白了吗?不管怎样,我们可以用形状而不是颜色来区分这两列。

往好的方面想,至少那不是很多文字什么的。
现在让我们通过 _dfscatter 函数传递这些形状!

我会让海绵宝宝解释这种感觉:

(海绵宝宝是 Nickelodeon 的财产,我不拥有海绵宝宝)
结论
到目前为止,关于 Hone 的令人兴奋的事情是,在它完成后,基础将是多么容易建造,就像我们在正方形中看到的那样。很容易添加形状,甚至自定义形状到等式中,这肯定会使事情变得有趣。在未来,你还将有能力阅读图像,并相应地绘制它们,我认为这非常棒。
至于数据框标绘,当然还有一些事情要做,一般来说还有一些事情要做。不管怎样,我觉得我们已经非常接近于让 Hone 成为一个相当不错的绘图库了!如果你想了解 Hone,请访问 Github:
模块化的形状,网格和线条容易预制快速绘图简单和轻型车床集成(即将推出)…
github.com](https://github.com/emmettgb/Hone.jl)
感谢阅读!
向我的图形库添加线图
Hone.jl
继续构建 Hone.jl 中实现的特性,并调试出现的问题。

one.jl 自诞生以来已经走过了漫长的道路,每一次升级都变得更加有用。上次我在 Hone 上做了一些工作,我留下了一个叫做“框架”的新控件表单,我们可以将对象放入其中并相应地缩放。然而,随着这一进步,也出现了缩放所有绘制点的新问题,以及我们的绘图所需的其他元素。为此,我们可以简单地用坐标解析器中相应的框架宽度或高度乘以最初从 X 顶部获得的百分比。

例如,我们在 X 平面上有两个点,8 和 4。因为 8 是最大的数字,所以它将被分配给这里的“topx”变量:

当坐标被解析时,我们的四将变成。5,因为它是八的百分之五十。然后我们把结果乘以宽度,我们会说是 1920 年。. 5 和 1920 的乘积是 960,结果我们得到了画在 x 轴中间的点。
很酷,对吧?
当然很酷,但是除此之外,X 轴和 Y 轴都需要改变。这相当简单,因为我们只需要将线条的点设置为我们的宽度和高度。

现在测试修改后的函数,我们现在可以得到我们的第一个高清 Hone 图:

最后一个仍然需要修复的是网格。网格是一个表面上看起来很有挑战性的问题,但结果却很简单。首先,我们需要将 X 和 Y 的顶部改变为框架大小的适当顶部。然后,我们只需要用相应轴的长度替换线对象坐标中的所有值。

还有…

现在我们甚至可以从我们的图中使用 get_frame()函数,并看到我们的图实际上包含在一个框架中。

新功能
为了增加新的功能,今天我想做一些不同的事情。通常,我会在模块中我认为最需要的部分随机添加特性,但是,今天我将分别在 HDraw 和 HPlot 中添加一个特性。
线条
从 HPlot 开始;散点图很酷,但 Hone 显然需要做得更好,才能成为一个真正伟大的图形库。另一种最重要的连续图类型是线图,创建起来应该相对简单。第一步,我们将从创建 _arrayline()函数开始。以下是我的原稿:
function _arrayline(x,y,axiscolor=:lightblue,
grid=Grid(3), custom="", frame=Frame(1280,720,0mm,0mm,0mm,0mm))
pairs = []
for (i,w) in zip(x,y)
append!(pairs,[i,w])
end
println(pairs)
lin = Line(pairs)
expression = string(",(context(),",lin.update(),",")
expression = string(expression, "(context(),", axisx_tag,grid_tag,custom, axisy_tag,"),")
tt = transfertype(expression)
frame.add(tt)
show() = frame.show()
tree() = introspect(composition)
save(name) = draw(SVG(name), composition);
get_frame() = frame
(var)->(show;composition;tree;save;get_frame)
end
因此,我在这个函数中遇到的第一个错误是,对的添加只是添加两个数字,而不是两个数字对的总和。老实说,我其实并不完全确定如何改变这一点,但我的第一个倾向是,也许我可以使用推力!函数,而不是 append!功能。基于这个想法,我设置了一个小测试,将两个独立的线对放入一个线对数组中,如下所示:

而且测试成功了!
然而,每当我在函数上尝试这样做时,我仍然得到边界错误。

这个问题看起来很熟悉,我相信我实际上在创建 line 函数时遇到了同样的问题。有趣的是,这也可能是该行的更新功能不起作用的原因。幸运的是,在搜索 Julia 数据结构文档时,我发现了一个大提示!

在这里,我们可以看到,实际上是字典数据类型用于创建 pair 数据类型。这有点令人困惑,因为我不认为我能够对 pair 进行类型断言,事实上,我认为该类型被称为其他类型,但有趣的是,每当字典语法与一个键和一个相应的值一起使用时,它就会自动变成一个 Pair。我们也可以通过打印来查看。

现在,在 frame.add()方法中取消注释并使传输类型成为 iterable 之后,我们遇到了以下错误:

幸运的是,我上次创建元表达式时遇到了这个问题,这是针对网格对象的。这意味着我们多了一个逗号。去掉这些,以及我还没有添加的“绒毛”,比如轴线和网格,结果是这样的:

现在这个函数完全可以工作了,但是如果我们运行它,我们当然不会得到任何东西:

你可能想知道:
这是为什么呢?
这里可能有一些事情在起作用。首先,我们使用的线可能不一定是弯曲的,这没关系,因为我们可以很容易地向 HDraw.jl 添加一条新的曲线。其次,缩放也很重要,并且将继续成为我们绘制的任何图的一个问题…所以让我们解决这个问题。

我决定下一步做的是使每行最多只包含两对。为此,我翻转了表达式,只在满足条件时添加标签。该条件将确定自上次向表达式添加一行以来迭代了多少对。

但那也没用…

所以在这一点上,我唯一的理论是,也许 pair 类型不是 Line 函数的正确类型。为了测试这一点,我创建了一个新行,并通过它传递 pairs 类型:

为了证实这种怀疑是正确的,我对原始语法做了同样的处理:

好吧,我是对的。
所以现在我需要弄清楚这种类型叫什么:

现在让我们试着把这种类型声明给一对坐标。

成功了!
现在我们只需要把这个应用到我们的配对上!

但是当我们试着运行这个:

看来这个问题是来自于推!()方法。为了测试这个理论,我决定尝试正常推送一个元组。

看起来我实际上是错的。因此,每当解析数组时,很可能会抛出这个界限错误。为了测试这一点,我只是在填充 pairs 的循环之后添加了一个 println()。这将让我们知道,在抛出边界错误之前,函数是否进行到这一步。它还会让我们看到正在传递的线对。

果然,这一对成功地打印出来了。这就提出了一个问题,错误到底来自哪里?也许是 Line()函数的问题?

找到了。
为了调试这个问题,我决定尝试解析一个包含相同语法的表达式,看看为什么这不起作用:
tupearr = []
tupe = Tuple([5,10])
push!(tupearr,tupe)
lin = Line(tupearr)
但这确实:
lin = line([5,10])

我看到的潜在问题是,我们的数组是一个
Array{Any}
该是时候了
Array{Tuple}
然而,每当我们试图推动!()或追加!()转换为数组{Tuple}类型,我们得到:

依我看,这个问题有两个解决办法。
- 我为 append 创建了一个新的调度函数!()方法,可以处理元组数组。
- 我发现了一种不同的类型,它可以保存元组,并且在 base 中已经有了它的调度。
- 在追加数据后,我可以将数组的类型转换为元组数组。
第三个似乎是最简单的选择,所以我选择了这个。为此,我首先将数据推送到{Any}类型的数组中:
tupearr = []
tupe = Tuple([5,10])
push!(tupearr,tupe)
然后试图将我们的数组{Tuple}类型声明为该类型。

成功了!
现在,让我们尝试将它插入到我们的 Line 函数中:

太棒了。
现在我们只需要将这个概念重新整合到我们的函数中。


终于成功了!
哇,那是一个 doozee。
比例被打乱了,但那只是因为我无意中似乎改变了我的数学。而不是:
x = (i * topx /frame.width)
y = (w * topy / frame.height)
应该是:
x = (i / topx * frame.width)
y = (w / topy * frame.height)

那看起来好多了!为了添加最后的润色,我们只需添加网格对象的标签和轴的标签。


文本
hone 绝对缺少的一个定义特性是绘制文本的能力,更具体地说:
标签。
这应该是相对简单和容易做到的,下面是我想到的:
function Text(label,x,y,stroke,size)
color = string("\"",string(stroke),"\"")
label = string("\"",string(label),"\"")
tag = string("text(",x, ",", y, ",", label, ",hcenter, vcenter),",
"stroke(", color,
"), fontsize(", size, "),")
expression = string("compose(context(), ",tag,")")
exp = Meta.parse(expression)
show() = eval(exp)
update() = tag
(var)->(show;expression;tag;exp)
end

结论
虽然我并不期望这篇文章展示了一个如何在编程的同时进行调试的很好的例子,但我觉得事实确实如此。虽然那条线的问题很有挑战性,但完成后肯定是值得的。文本对象也是一个重要的进步,并且肯定会在 Hone 的其他功能中实现。
为您的代码添加安全性
这比你想象的要简单
我经常听到的一句话是“安全是每个人的责任”,但我注意到数据科学家经常过于关注他们需要知道的大量技能,以至于忽略了安全。除了有许多职责之外,我认为安全性似乎令人生畏,并且似乎需要大量的软件工程技能。实际上,在你的软件中实现最低级别的安全性是相当容易的。我建议遵循 Charles Nwatu(网飞公司的安全主管,以前是 StitchFix)的原则“做得更少更好”对我来说,这意味着成功地实现低级别的安全性比未能实现高级别的安全性要好。本文面向数据科学家(或 python 用户),并且只假设您对命令行有一些基本的了解。
安全工具的类型
有两大类安全工具,静态和动态。动态安全工具针对运行中的软件运行以发现威胁,而静态工具针对源代码文件运行以发现问题。在本文中,我们将添加两个静态安全工具。第一个工具将检查以确保您没有向存储库添加密钥、秘密或密码,从而防止您暴露这些私人信息。第二个工具将帮助您检查软件依赖项是否存在安全威胁。
Git 秘密
Git Secrets 是我们用来监控我们不想公开的信息的工具。在这里查阅它的报告,可以很容易地为你的操作系统安装它。一旦你安装了它,你可以用下面的命令添加我们想要寻找的东西:git secrets --add 'your-regular-expression'阻止模式或者git secrets --add --literal 'your-literal-string'阻止特定的字符串。作为一个例子,我将运行git secrets --add 'password ?=+ ?[A-Za-z0-9]+,它将阻止如下内容:
- password = anyLengthPassword
- password = passwordWithNoSpacesNextToEqualSign
- password = = doubleEqualsBlockedToo
但不会阻止这些:
- 密码= " "
- 密码=
这很好,因为它不会警告我们不要推送已经正确删除密码的代码。现在我运行git secrets --scan -r来扫描所有文档中我添加的模式。它找到了我放在自述文件第一行的一个密码。以下是 Git Secrets 向我报告的内容:
README.md:1:password = password12345
[ERROR] Matched one or more prohibited patterns
Possible mitigations:
- Mark false positives as allowed using: git config --add secrets.allowed ...
- Mark false positives as allowed by adding regular expressions to .gitallowed at repository's root directory
- List your configured patterns: git config --get-all secrets.patterns
- List your configured allowed patterns: git config --get-all secrets.allowed
- List your configured allowed patterns in .gitallowed at repository's root directory
- Use --no-verify if this is a one-time false positive
我为这个特定的存储库设置了这些 Git 秘密配置,但是您可以设置一些全局配置来防止您在任何 repo 中推送任何秘密。用git secrets --add --global 'pattern or string here'做这个。
虚拟环境
在之前的一篇文章中,我认为创建一个虚拟环境应该是你做任何项目的第一步。虚拟环境允许你为不同的项目隔离软件,所以如果你在一个项目上需要 pandas 版本 0.25.3,而在另一个项目上需要 pandas 版本 1.1.2,这不会有问题。
如果你确实在使用 python,你很可能会使用 conda 或 virtualenv。用 conda run conda create --name 'env-name' python='python-version'创建虚拟环境,用 virtualenv 创建虚拟环境,使用virtualenv 'env-name'。您可以将您的所有 python 包存储到一个通常称为 requirements.txt 的文件中,如果您希望在相同的环境中协作处理相同的代码,那么这个文件对于与他人共享非常有用。这是我所有的 requirements.txt 文件:
numpy==1.16.0
要安装 requirements.txt 文件中的所有包,运行pip install -r requirements.txt并生成 requirements.txt 文件,运行pip freeze > requirements.txt。
月初(beginning of month 的缩写)
根据 2020 年 DevSecOps 社区调查,28%的受访者表示他们至少有一次与开源工具相关的安全漏洞。那么,如何在这些安全威胁变成问题之前发现它们呢?通过使用物料清单(BOM ),它将描述您的项目使用的所有软件依赖项和库。然后,可以将该 BOM 与已发现的安全威胁的公共记录进行比较,这将引起您的注意。如果您已经在使用虚拟环境,那么 requirements.txt 文件可以作为 python 项目的 BOM。现在让我们安装安全,它将扫描您的活动虚拟环境或 requirements.txt 文件,并将其与已知漏洞数据库的数据库进行比较。为此跑pip install safety。作为一个警告,这个数据库每月只更新一次,要获得最新的安全威胁,你必须支付 PyUp,安全背后的公司。但是请记住,“做得更少,更好。”
现在您已经安装了它,您可以在活动环境中运行safety check或者运行safety check -r requirements.txt来检查 requirements.txt 文件。我这样做是针对我的需求文件,其中只有 numpy 版本 1.16.0。以下是输出结果:

安全检测器
我现在被警告 numpy 版本 1.16.0 中有安全威胁,我现在知道要升级到不同的版本。
在一个脚本中运行这些工具
我们可以将这两个命令放在一个 shell 脚本中,您可以随时执行该脚本。我用nano security.sh打开了一个新的文本文档来放入这些内容。在这个文件中,我写道:
#!/bin/bash
# This script runs a security check
git secrets --scan -r
safety check -r requirements.txt
第一行告诉我们 bash 的位置(您的可能不同)。有很多解释器,我希望 bash(这是比较常见的一种)来执行这个脚本。第二行是一个常规的注释,告诉我们脚本做了什么。随着您对新工具的了解,您可以将它们添加到这个脚本中,这将使执行安全检查更加简单。
连续累计
比偶尔运行这个脚本更好的是开始采用持续集成管道。持续集成是一次处理一小批代码,并频繁地将您的代码与一个主要分支集成的过程。当您整合您的代码时,您可以自动运行代码质量测试以及这些安全性检查。如果你这样做了,你会更快地了解问题,从而更快地减轻它们。
为了利用持续集成,您可能希望从为您的团队选择一个工具开始,比如 CircleCI、TravisCI 或 Jenkins。这些工具可以在 GitHub、Bitbucket 或 GitLab 中连接到您的 repo 中,并在那里发生变化时开始执行。下面是一个 Jenkinsfile 的示例,您可以使用它来自动执行上述操作以及您可能在 tests.py 文件中编写的任何 python 测试。这将在你或你的任何队友推你的仓库时执行。
pipeline {
agent any
stages {
stage('SecTest') {
steps {
sh 'git secrets --scan -r'
sh 'safety check -r requirements.txt'
}
}
stage('AppTest') {
steps {
sh 'python.exe tests.py'
}
}
}
}
您甚至可以添加额外的步骤,将您创建的任何机器学习模型或函数部署到该管道中。在我看来,一旦你采用了 CI 管道,高安全性和高质量的代码就更容易开发。希望这能让你开始提高代码的安全性!
给熊猫添加样式(只用了几行代码!)
制作你的数据框架(很多!!)更漂亮

让我们给我们的熊猫数据框添加一些风格吧!资料来源:Nik Piepenbreier
Pandas 是 Python 中数据分析的典型工具,但让数据看起来像样并不总是最容易的。为此,许多分析师在与我们更广泛的受众分享数据之前,仍然求助于 Excel 来添加数据样式(如货币)或条件格式。在这篇文章中,我们将探索如何利用 Excel 中常见的这些特性,并演示如何使用熊猫风格的 API 来利用这些特性!
我们为什么要设计数据的样式?
我们的最终目标应该是让读者更容易理解数据,同时保持数据框架中底层数据的可用性。例如,10%可能比值 0.10 更容易理解,但保持 0.10 的比例对于进一步分析更有用。
什么是熊猫风格 API?
熊猫在 2019 年开发了造型 API,自那以来一直在积极开发。API 返回一个新的 Styler 对象,它有一些有用的方法来对数据帧应用格式和样式。最终的样式是用 CSS 完成的,通过样式函数,通过属性:值对应用于标量、序列或整个数据帧。
Styler 对象有两个关键方法:
- Styler.applymap —将样式应用于元素
- Styler.apply —应用列/行/数据帧样式
让我们首先从加载数据开始。
我们将使用在我的数据透视表教程中可用的相同数据集,并且我们将使用我们在那里概述的一些步骤。如果你不熟悉熊猫的数据透视表,我们推荐看看我的教程。
导入我们的数据报。资料来源:Nik Piepenbreier
Out:
Date Region Type Units Sales
0 2020-07-11 East Children's Clothing 18 306
1 2020-09-23 North Children's Clothing 14 448
2 2020-04-02 South Women's Clothing 17 425
3 2020-02-28 East Children's Clothing 26 832
4 2020-03-19 West Women's Clothing 3 33
我们可以看到,我们有一些销售,提供了有关地区、类型、售出单位数量和总销售成本的信息。
让我们创建一个数据透视表,按照我之前的教程:
Output:
Sales
Region Type
East Children's Clothing 45849
Men's Clothing 51685
Women's Clothing 70229
North Children's Clothing 37306
Men's Clothing 39975
Women's Clothing 61419
South Children's Clothing 18570
Men's Clothing 18542
Women's Clothing 22203
West Children's Clothing 20182
Men's Clothing 19077
Women's Clothing 22217
现在我们已经将数据加载并存储在名为 pivot、 的数据框架中,我们可以开始在 Pandas 中对数据进行样式化。
熊猫的数据类型标签
在我们的 data framepivot中,列 Sales 代表以美元表示的销售总数。然而,读者并不清楚这一点,因为没有美元符号,千位值也没有用逗号分隔。让我们来探索如何做到这一点:
Output:
Sales
Region Type
East Children's Clothing $45,849
Men's Clothing $51,685
Women's Clothing $70,229
North Children's Clothing $37,306
Men's Clothing $39,975
Women's Clothing $61,419
South Children's Clothing $18,570
Men's Clothing $18,542
Women's Clothing $22,203
West Children's Clothing $20,182
Men's Clothing $19,077
Women's Clothing $22,217
我们可以看到,数据立即更容易理解!
字符串格式可以以不同的方式应用。其他一些例子包括:
- 带两位小数的浮点数:
- 用零填充数字:
- 带两位小数的百分比:
如果我们想为多列传递格式,定义一个可以传递给样式函数的字典可能更容易。例如,我们可以编写一本字典,如下所示:
然后可以传递到如下所示的对象上:
添加条件格式
在 Excel 中,条件格式是一个非常有用的工具。它使我们能够根据内容轻松识别价值。这对熊猫来说同样简单,但是隐藏了一点。我们将展示在 Pandas 中实现条件格式是多么容易。
例如,如果我们想突出显示任何超过 50,000 美元的销售额(比如说,在这之后他们有资格获得奖金)。我们可以使用 applymap 方法做到这一点。在开始之前,我们将定义一个可以传递给 applymap 方法的函数。
我们现在可以将这个函数传递给 applymap 方法:
这将返回以下数据帧:

突出显示超过 50,000 的值。资料来源:Nik Piepenbreier
我们还可以将数据样式与条件格式联系起来:

突出显示值和添加货币标签。资料来源:Nik Piepenbreier
让链接的方法更容易阅读
链接方法在 Python 中是一个非常有用的特性,但它并不总是最容易阅读的。我们可以使用\字符将链拆分成多行,如下所示:
现在,假设我们想要突出显示最大值和最小值,我们可以用另一个 Styler 对象来实现。虽然我们可以使用函数和 applymap 方法来实现这一点,但是 Pandas 有内置的方法来直接突出显示最大值和最小值。在下面的例子中,我们提供了命名颜色,但是你也可以提供更具体的十六进制值。

轻松突出显示最大值和最小值。资料来源:Nik Piepenbreier
给熊猫添加色阶
有时,我们会希望标识一列中彼此相关的值。这就是色阶发挥作用的地方。我们可以使用 background_gradient 方法作为样式方法很容易地实现这一点。让我们试一试:
这将返回如下所示的数据帧:

添加色阶。资料来源:Nik Piepenbreier
您也可以使用不同的 cmaps。要了解更多关于 cmaps 的信息,请查看 Matplotlib 指南。
限制格式化的列
现在让我们生成一个包含多列值的数据透视表:
这将创建一个如下所示的数据透视表:
sum count
Sales Sales
Region Type
East Children's Clothing 45849 113
Men's Clothing 51685 122
Women's Clothing 70229 176
North Children's Clothing 37306 85
Men's Clothing 39975 89
Women's Clothing 61419 142
South Children's Clothing 18570 45
Men's Clothing 18542 39
Women's Clothing 22203 53
West Children's Clothing 20182 42
Men's Clothing 19077 41
Women's Clothing 22217 53
现在,让我们应用背景 _ 渐变方法:
这将返回以下数据帧:

向多列添加色标。资料来源:Nik Piepenbreier
如果我们想将此限制为只有一列,我们可以使用 subset 参数,如下所示:

仅向一列添加色标。资料来源:Nik Piepenbreier
给熊猫添加颜色条
向列中值的大小添加上下文的另一种说明性方法是添加颜色条。这是一种非常简单的方式来提供视觉效果,也很容易打印出来。通过使用下面的代码,我们可以使用 Python 来实现这一点:
这将返回以下数据帧:

给我们的数据框架添加颜色条。资料来源:Nik Piepenbreier
颜色条让我们更容易看到规模。我们还可以使用 align =center 参数,如果值为负,则在左边显示条形,如果值为正,则在右边显示条形。
如何在熊猫中重用样式
在你花了一些时间创建了一个你真正喜欢的样式后,你可能想重用它。令人欣慰的是,Pandas 使它变得简单,无需重复您精心创建的代码。你用。对另一个数据报的样式对象使用方法。例如,如果我们有两个数据帧,style1 和 style 2,我们可以通过使用以下内容重用 style1 的样式:
隐藏索引或列
既然我们讨论的是为显示做好数据准备,那就让我们来谈谈 Excel 使之变得非常简单的另一部分:隐藏列。我们也可以使用 styler 对象在熊猫身上实现这一点。如果我们想隐藏索引,我们可以写:
Date Region Type Units Sales
2020-07-11 East Children's Clothing 18.000000 306
2020-09-23 North Children's Clothing 14.000000 448
2020-04-02 South Women's Clothing 17.000000 425
2020-02-28 East Children's Clothing 26.000000 832
2020-03-19 West Women's Clothing 3.000000 33
类似地,如果我们想隐藏一列,我们可以写:
Date Region Type Sales
0 2020-07-11 00:00:00 East Children's Clothing 306
1 2020-09-23 00:00:00 North Children's Clothing 448
2 2020-04-02 00:00:00 South Women's Clothing 425
3 2020-02-28 00:00:00 East Children's Clothing 832
4 2020-03-19 00:00:00 West Women's Clothing 33
将样式化的数据框架导出到 Excel
我在文章的前面提到过,风格 API 是熊猫仍然是实验性的。我们目前不能导出所有这些方法,但是目前可以导出背景色和颜色。例如,如果我们想要导出以下数据帧:
我们可以用。to_excel 方法将我们的样式化数据帧提取到 excel 工作簿:

如果都不行,就用 Excel 吧!资料来源:Nik Piepenbreier
也许用 Excel 就好了?
最后,也许在某些情况下,将数据导入 Excel 会更有效率?在这种情况下,您可以使用 df.to_clipboard()方法将整个数据帧复制到剪贴板!
这没什么不对的…
非常感谢你的阅读!
在这篇文章中,我们学习了如何使用熊猫样式 API 来设计熊猫数据帧的样式。我们学习了如何添加数据类型样式、条件格式、色标和色带。与 Excel 中的样式类似,Pandas 使对数据帧应用样式变得很容易。这使我们能够更好地表示数据,并直观地发现数据中的趋势。
原载于 2020 年 4 月 20 日https://datagy . io。
使用 Python 在图像上添加文本
使用枕头库的简单机器学习项目

伊戈尔·米斯克在 Unsplash 上的照片
在这篇文章中,我将向你展示如何使用 Python 给你的图片添加文本。这将是一个非常简单的项目,我们将使用编程来做一些设计。在这篇文章之后,你将能够使用一些 python 技巧来设计你的下一张传单或名片。听起来是不是很酷?也许这不是设计的最佳方式,但这是可能的:)
作为一个喜欢设计和编程的人,我认为这将是一个伟大的项目,我可以结合我的两个兴趣。这实际上是编程的一大部分,你总能找到不同的领域来练习你的技能。在我之前的文章中,我展示了如何给你的视频添加文本,今天我们将在一张图片上做这件事。我们开始吧!
目录
- 导入枕头库
- 选择一幅图像
- 字体选择
- 渲染正文
- 导出结果
- 视频演示
使用 moviePy 库的动手机器学习项目
towardsdatascience.com](/rendering-text-on-video-using-python-1c006519c0aa)
步骤 1-导入枕头库
首先,让我们安装这个项目需要的库。安装完成后,我们可以导入库以在项目中使用它。安装这个库的最好方法是使用 PIP,它是一个 python 包管理器工具。与大多数 Python 库完美配合。
pip install pillow
很好,现在我们可以将它导入到我们的代码中了。使用大型库时,与其导入整个库,不如练习导入将要使用的特定函数。这将在运行程序时节省存储空间和时间。对于我们的简单项目,我们只需要三个函数:Image、ImageFont 和 ImageDraw。
我们可以在一行代码中导入这三个元素,如下所示:
from PIL import Image, ImageFont, ImageDraw
步骤 2 —选择一幅图像
在这一步中,我们将选择并导入一个要添加文本的图像。我推荐使用 Unsplash ,这是一个很棒的股票图片网站,可以找到质量很好的图片。以下是我下载的图片,也与秋季相匹配:

诺亚·西利曼在 Unsplash 上的照片
下载图像后,确保将它复制到代码所在的目录中。这将帮助您将其导入到程序中。让我们定义一个新的变量,并使用 open 方法分配图像。
my_image = Image.open("nature.jpg")
步骤 3 —字体选择
这个项目的好处是,你可以选择你的字体风格。定制字体会让我们在设计时更加灵活。
首先,我们将下载我们想要选择的字体的 TTF(TrueType 字体)文件。将文件放在同一个目录中后,我们可以使用 ImageFont 函数将其导入到我们的程序中。这是我将使用的字体。
title_font = ImageFont.truetype('playfair/playfair-font.ttf', 200)
现在,我们可以进入下一步,在这里我们将添加文本。
步骤 4 —呈现文本
这一步就是奇迹发生的地方。选好图片和字体后,就该决定写什么了。首先,我们将定义一个文本变量,并给它分配一个字符串。
title_text = "The Beauty of Nature"
其次,我们将使用 ImageDraw 函数将图像转换成可编辑的格式。多亏了枕头库,我们可以一行搞定。
image_editable = ImageDraw.Draw(my_image)
第三,我们将做渲染。我们将向渲染函数传递四个参数。我将在代码下面与一些有用的资源分享每个参数的描述。
image_editable.text((15,15), title_text, (237, 230, 211), font=title_font)
- 起始坐标:枕头库采用笛卡尔像素坐标系,左上角为(0,0)。
- 文本:单引号或双引号之间的字符串
- RGB 格式的文本颜色: Google Picker 是寻找最佳颜色的绝佳资源。在谷歌上搜索“拾色器”,它就会出现。
- 字体风格: Google Fonts 是挑选你的字体风格的绝佳资源,你也可以下载字体家族的 TTF(TrueType Font)文件。
使用 OpenCV 的简单实用的机器学习应用程序
towardsdatascience.com](/building-a-color-recognizer-in-python-4783dfc72456)
步骤 5 —导出结果
干得好!我们差不多完成了。这将是最短的步骤,只导出编辑过的图像。下面是使用保存方法导出的代码。
my_image.save("result.jpg")

result.jpg
视频演示
每当贝希克居文出版时收到电子邮件。注册后,如果您还没有,您将创建一个中型帐户…
lifexplorer.medium.com](https://lifexplorer.medium.com/subscribe)
恭喜你。!您已经创建了一个使用 Python 在图像上呈现自定义文本的程序。这不是设计图像的最佳方式,但是通过编程来实现它的可能性是很酷的。希望你喜欢阅读这篇文章并参与这个项目。如果你今天学到了新东西,我会很高兴。从事像这样的动手编程项目是提高编码技能的最好方式。
如果您在执行代码时有任何问题,请随时联系我。
附加边际软最大损失(AM-Softmax)
了解 L-Softmax、A-Softmax 和 AM-Softmax

在本文中,我将记录我在阅读用于人脸验证的附加保证金 Softmax论文时,对附加保证金 soft max 损失或 AM-Softmax 损失的理解历程。在分类中,将创建一个决策边界来分隔类别。然而,当输出位于判定边界附近时,这可能是一个问题。AM-Softmax 旨在通过向决策边界添加余量来解决这一问题,以增加类的可分性,并使相同类之间的距离更紧密。

软最大 VS AM-软最大【来源】
除了 AM-Softmax,我还将讨论早期的作品,这些作品也将余量引入 Softmax 损耗,以不同的方式实现,如 L-Softmax 和 Angular Softmax,以便更好地理解 AM-Softmax。
目录
- 先决条件
- 软最大损失
- L-Softmax(大余量 Softmax)
- α-最大柔度(角度最大柔度)
- AM-Softmax(附加余量 Softmax)
先决条件
- 深度学习和神经网络基础
- 卷积神经网络
我假设你有深度学习和神经网络的基础知识,特别是 CNN,因为这可能是理解 AM-Softmax 所需要的。
Softmax 损失
在深入到 AM-Softmax 之前,我们先多退一步,刷新一下对 Softmax 损耗的认识。当我第一次听说最大损失的时候,我很困惑我所知道的,最大损失是一个激活函数,而不是损失函数。
简而言之,Softmax 损失实际上只是一个 Softmax 激活加上一个交叉熵损失。Softmax 是一个激活函数,它输出每个类的概率,这些概率的总和为 1。交叉熵损失就是概率的负对数之和。它们通常在分类中一起使用。您可以在下面看到 Softmax 和交叉熵的公式,其中 f 是 Softmax 函数, CE 是交叉熵损失。因此,Softmax 损失只是这两个相加。

Softmax 损失。来源:劳尔·戈麦斯
为了更好地理解 Softmax 损失,我建议阅读 Raúl Gómez 的一篇文章,因为他在 中清楚地解释了这一点,理解分类交叉熵损失、二元交叉熵损失、Softmax 损失、逻辑损失、焦点损失以及所有那些令人困惑的名称。
大幅度软最大(左软最大)
L-Softmax 是在原始 Softmax 损失的基础上引入余量的第一批论文之一。这里的容限具有与三元组损失函数中的容限相似的概念,在三元组损失函数中,容限将增加类别之间的可分性或距离,并进而最小化相同类别之间的距离。这种类内紧密性和类间可分性将显著提高各种视觉分类和验证任务的性能。
在论文中需要注意的一件重要事情是,当我们使用术语 Softmax 损失而不仅仅是 Softmax 激活和交叉熵损失时,我们还包括分类器或全连接层。

根据上面的图像,我们可以将 Softmax 损失定义如下,其中 f 作为最后一个完全连接的层或分类器的输出。

软最大损失
全连接层的输出只是权重和前一层输出加上偏差的乘积。所以 f 也可以写成 W * x 如下。( b 或 bias 为简单起见被省略,但如果加上它仍然可以工作)

由于 f 是 W 和 x 之间的内积,因此也可表示为

其中θ是矢量 W 和 x 之间的角度。因此,Softmax 损耗也可以通过代入 f 定义如下。

修改的 Softmax
为了理解 L-Softmax 背后的直觉,我们将使用一个二元分类的例子。假设我们有一个来自类 1 的样本 x 。最初的 Softmax 需要W1x>W2**x才能将 x 正确分类为 1。

二元分类
但是,W1x>W2**x也可以写成如下。

接下来,我们希望分类更严格,并扩大决策范围。因此,我们需要下面的条件,其中我们将θ1 乘以一个正整数, m,和(0 ≤ θ1 ≤ π/m)。

这将为我们提供如下所示的决策余量。

L-Softmax 几何解释
因此,按照前面的要求。L-Softmax 损耗可定义为

L-Softmax 损失公式
我们要求ψ在哪里,

其中 m 是正整数,其中 m 越大,分类余量越大。然后,要求 D(θ)是单调递减函数,D( π/m)应等于 cos( π/m)。这是因为,我们希望 cos 函数在π之前只有一个递减的值,因此,如果 theta < π/m 和 D(θ)应该是递减函数,我们才使用 cos 函数。
为了满足上述要求并简化前向和后向传播,本文构造了一个特定的ψ,如下所示,其中 k ∈ [0,m1],k 为整数。

总之,L-Softmax 引入了一个可调的裕度,它鼓励学习特征的类内紧密性和类间可分性,这可以显著提高各种视觉分类和验证任务的性能。可以使用参数 m 来控制裕量,其中较大的 m 导致较大的决策裕量。L-Softmax 还在几个基准数据集上进行了测试,与当时的其他方法相比,它表现出了更好的性能和更低的错误率。

角度软最大值
2018 年在论文中介绍了 Angular Softmax, SphereFace:用于人脸识别的深度超球面嵌入。Angular Softmax 非常类似于 L-Softmax,因为它旨在实现比最小类间距离更小的最大类内距离。然而,它与 L-Softmax 的不同之处在于将分类器权重 W、归一化为 1。这导致了在开集人脸识别数据集中性能的提高,在开集人脸识别数据集中会有在训练期间不存在的人脸。

闭集 VS 开集【来源】
如前所述,A-Softmax 与 L-Softmax 非常相似,只是分类器权重 W 被归一化为 1,偏差被设置为 0。因此,之前修改的 Softmax 公式

修改的 Softmax
将更改为

具有归一化权重的修改的 Softmax
因此,如果我们使用相同的二进制分类示例。将样品 x 正确分类为 1 类的要求将从

到

因为|W1| = |W2|,因此|W1||x| = |W2||x|我们可以从等式中抵消 W 和 x。
然后,引入保证金,它将

m 越大,决策界限越宽。决策边界方程的比较如下表所示。

因此,A-Softmax 损失最终可定义为

最大损失
在哪里


A-Softmax 的一个优点是它在超球解释中也能很好地渲染。


超球解释用不同的【来源】
总之,A-Softmax 对分类权重进行了归一化处理,使偏差为零,并引入了可通过参数 m 进行控制的角裕量,以学习具有区别性的特征,并具有清晰的几何解释,这将在开集数据集中表现得更好,如下所示。

最大附加余量(AM-Softmax)
AM-Softmax 随后在用于人脸验证的附加余量 soft max论文中提出。它采用了不同的方法来增加 softmax 损失的利润。它不是像 L-Softmax 和 A-Softmax 那样将 m 乘以 θ ,而是通过将 ψ(θ) 改为

与 L-Softmax 和 A-Softmax ψ(θ) 相比,这要简单得多,AM-Softmax 的性能也更好。此外,与 A-Softmax 类似,AM-Softmax 也对权重和偏差进行归一化处理,但引入了一个新的超参数 s 来缩放余弦值。最后,AM-Softmax 损耗可以定义如下。

因此,决策边界将形成于

AM-Softmax 判决边界
其中,在二元分类示例中,P1 是类别 1 的特征,p2 是类别 2 的特征。

AM-Softmax 在二进制分类中的直观解释【来源】
为了更好地可视化 AM-Softmax 损失的影响,使用具有时尚 MNIST 数据集的 7 层 CNN 模型将其与其他损失进行比较。CNN 模型的 3 维特征输出被归一化并绘制在如下所示的超球体(球)中。从可视化中,您可以看到 AM-Softmax 在对输出进行聚类时的性能与 SphereFace (A-Softmax)相似,并且随着裕度的增加,m 越大,性能越好。

超球面几何解释【来源】
此外,AM-Softmax 和其他损失也在开放集数据集上进行测试,使用 Casia-WebFace 进行训练,使用 LFW 和 MegaFace 进行测试,并移除重叠身份。我们可以看到 AM-Softmax 优于其他损失,特别是在 MegaFace 数据集上。

摘要
总之,L-Softmax、A-Softmax 和 AM-Softmax 损失都试图通过引入 Softmax 损失的余量来结合分类和度量学习,并旨在最大化类之间的距离和增加相同类之间的紧密性。在这三个模型中,AM-Softmax 被证明在模型性能方面提供了最好的提高,特别是在用于人脸验证的 LFW 和 MegaFace 数据集上。
最后,我要衷心感谢我团队中的所有同事,尤其是阿克毛、易卜拉欣和英·康咪咪,他们回答了我所有的问题,并帮助我理解了这些概念。
附言:看看我的另一篇关于圈损的文章。我实际上读到了 AM-Softmax,因为它被圈损论文引用了。它引入了一个有趣的统一公式,可以根据输入退化为 AM-Softmax 或三重态损耗。
理解“圈损失:对相似性优化的统一观点”
medium.com](https://medium.com/vitrox-publication/understanding-circle-loss-bdaa576312f7)
参考
【1】刘文伟,温,于,杨。卷积神经网络的大幅度软最大损失。国际机器学习会议,第 507–516 页,2016 年
【2】刘文伟,温,俞正声,李,拉杰,宋。用于人脸识别的深度超球面嵌入。2017 年 IEEE 计算机视觉和模式识别会议论文集。
【3】王凤芳,郑俊杰,刘文伟,刘浩辉。用于人脸验证的附加余量 softmax。IEEE 信号处理快报,25(7):926–930,2018。*
使用 Pytorch 第 2 部分轻松解决班级失衡问题

使用 Pytorch 对同一棵向日葵进行过采样?图片来源于杰弗里·约翰逊。
了解 Pytorch 的称重随机取样器
在之前的文章中,我们看到了如何通过加权随机采样器进行过采样来解决类不平衡问题。实际上,这降低了过度拟合的风险。在本文中,我们将展示 WeightedRandomSampler 是如何实现的,并给用户一些直觉。我们首先给出一个应用简单统计的例子,然后我们从数学上处理一个更一般的场景。我们的目标是理解我们如何从每个类中得到相同数量的观察结果,即使它们是不平衡的。
没有比不明白我们用什么更糟糕的了,对吗?🤗
注。如果你喜欢这篇文章,一定要关注我。很多人喜欢我的文章,请关注我以示支持,这真的很有帮助!🤗

我们数据集的 10 个批次中的类分布。红色表示辅修课,蓝色表示主修课。我们使用 WeightedRandomSampler 从左边不平衡的数据集到右边更平衡的数据集。
现在让我们看看 Pytorch 中实现的 WeightedRandomSampler 的源代码。我们将学习一些理论来理解代码,然后看一个简单的例子来很好地理解实现。
Pytorch 的源代码中,关键函数如下:


在 WeightedRandomSampler 类中,关键函数是 call iter 。
一个关键思路:从有控制参数的多项式分布中提取。
Pytorch 使用具有给定参数的多项式分布,即权重、样本数量 s 的以及我们是否使用替换进行采样。

Pytorch 引入的关键思想是从点集的多项式分布中提取。每个点被赋予一个给定的采样概率。这种概率由其具有给定权重参数的类来定义。
一个简单的例子:
让我们假设我们的数据点按如下方式排序:

左边是 100 个观察值,中间是它们的类别分布,右边是 WeightedRandomSampler 分配的权重参数。蓝色代表大类,红色代表小类。
我们可以控制权重,以便给予次要类别更多权重:

然后,我们绘制一个带有受控参数的多项式分布。每个参数定义了一个给定观察值的绘制概率。事实上,我们是从一组观察值的多项式分布中得出的。
这里,我们将权重参数设置如下:

将 WeightedRandomSampler 中的权重设置为每个类别分布的经验先验的倒数。
概率可以通过使用类似于 softmax 函数的简单标准化权重向量来找到。例如,可以执行以下操作:

重要提示:我们需要对 N 个观测值进行归一化处理。目标是得到一个元素之和等于 1 的向量。这不是通过权重向量实现的,因此标准化是必要的。

从权重向量(左边)到概率向量(右边)。蓝色代表大类,红色代表小类。
现在,我们能否从数学上展示,在抽取 100 个随机样本后,我们如何从 c0 中抽取 50 个观察值,从 c1 中抽取 50 个观察值?
设一个随机变量描述 c1 中采样 m 个点后的观测数,这里设为 100。

因此,

利用期望的线性度,我们可以在小类 c1 的点集上得到一个线性方程。
现在,我们知道,从一个多项分布中,在采样 m 次后,我们可以将期望值表示如下:

采样一个点 xi 有一个由多项式分布多项式(【x1,...,x90,x91,..,x100],[p0,…,p0,p1,..p1])。
对于位置[91,100]中的所有观察值,我们说它们属于 c1 类:

结果,从辅修课 c1 中抽取的期望点数(最初包含 10 个点)现在是 50 个。类似地,主要类别 c0 的预期观测值数量如下:

从类别 c1 中提取的预期观察值数量也在 50 左右。
更严谨,更通用:
在这一节中,我们试图更加概括。然而,为了简单起见,我们假设我们处理的二元问题只有两个类 c0 和 c1。

蓝色代表大类,红色代表小类。
我们现在有 N 个观察值,使得:

我们需要像前面的例子一样建立概率。这次,我们有:

现在我们要生成从整组点 X 上的多项式分布中采样的 m 个点:多项式 (X,[p0...,p0,p1,..p1])。

我们从数据 x 中生成 m 个样本。
我们定义一个随机变量来描述一个点是否来自类 c0:

描述抽样观测值是否属于 C0 类的随机变量。
因此,我们可以很容易地表达这样的随机变量的期望值:

现在让我们描述随机变量,它给出了从 c0 类中采样的点的总数:

因此,我们可以计算 m 次后从类 c0 采样的元素的预期数量:

我们之前已经了解了如何在加权随机采样器中设置权重:

将 WeightedRandomSampler 中的权重设置为每个类别分布的经验先验的倒数。
现在我们可以有一个更简单的表达式来表示在 m 次之后从类 c0 中采样的元素的预期数量:

这意味着我们期望正好一半的采样观察值来自 minor 类。我们从数学上解决了类别不平衡问题,证明了我们可以从次要类别中采样与主要类别完全相同数量的观察值。
贝叶斯理论的进一步发展:
给每个类增加权重相当于贝叶斯方法。我们调整了优先等级,给了次要等级更多的权重。这种等价性通过以下关系式得到强调:

事实上,我们可以将我们的抽样方法建立在贝叶斯理论的基础上,我们引入了一个叫做先验的新元素。该过程是顺序采样:
- 第一步:抛一枚概率为 p(c0)的非公平硬币,得到小类 c0,概率为 p(c1)得到大类 c1。
- 第 2 步:从上一步中抽取的类中,对一个观察值进行统一采样:

顺序抽样的第二步,我们从第一步确定的固定先验类别中抽取一个点。
结论
总之,通过使用带有多项式分布的加权随机抽样器,我们期望从每一类中得到相同数量的观察值。
关键思想在于在一组观察值上构建多项式分布,其中每个观察值表现为其自己的类,具有受控的被抽取概率。
贡献者:

索海尔。洛桑联邦理工学院应用数学专业硕士研究生。

马斯塔法。之前是微软的数据科学家实习生和瑞典皇家理工学院的机器学习学生。
使用 Pytorch 轻松解决班级失衡问题

计算机视觉中的数据增强。图片的制作者名单为 fastai 。
当你的模型过度拟合你的数据时,你能做什么?
重要提示:如果你能看到这个故事的结尾,请考虑在灵媒上跟我学更多的。我将非常感谢你的支持。
这个问题经常发生在我们处理不平衡数据集的时候。如果您的数据集代表几个类,其中一个比其他的少得多,那么就很难了解代表这样一个小类的真正的底层分布。
正如这篇必读的论文、中所解释的,解决几乎在所有分析场景中都占主导地位的类不平衡的方法是过采样。过采样应应用于完全消除不平衡的水平,而最佳欠采样率取决于不平衡的程度。与一些经典的机器学习模型相反,过采样不会导致 CNN 的过拟合。
在实践中,当训练机器学习模型时,人们将遵循一些关键步骤:
- 将数据分成一个训练/测试集(80%,20%)。
- 通过对训练数据进行拟合来训练机器学习模型。
- 在测试集上评估性能。
当使用深度学习架构时,通常会将训练数据分成几批,我们在训练期间将这些数据馈送给我们的神经网络。为了构建这样的批次,我们通常按照观察值集的均匀分布从训练集中随机抽样。
现在需要一些简单的统计数据。假设我们有一个包含两个类 class_1 和 class_2 的数据集。从 class_1 中随机抽取一个点的概率是多少?
遵循点集合上的均匀分布,这样的概率很容易表达:

实际上,在二元问题中,当我们从一个类中得到的观察值比另一个类中得到的多得多时,就会出现类不平衡:

因此,我们有:

二元问题中的类别不平衡由从给定类别中得出观察值的不平衡可能性来描述。
换句话说,从 class_1 比从 class_2 更有可能得出一个点。因为模型看到的 class_2 要少得多,所以它不能从这样的类中学习有用的特征也就不足为奇了…
现在,在深入编码之前,我们需要理解人工扩充数据时的一个关键思想。我们想要的是确保通过人为增加辅修班,我们有:

在扩充了我们的数据之后,我们的目标是使从每个类中抽取样本的可能性尽可能接近。
是时候了!让我们用 Pytorch 的weighted random sampler来编码解决这个问题。
数据集:我们用来自 class_major 的标记为 0 的 900 个观察值和来自 class_minor 的标记为 1 的 100 个观察值构建数据集。(90%, 10%)

我们数据集的样本。标签 1 对应于法语句子,标签 0 对应于英语句子。

具有文本数据和两类值 0 和 1 的不平衡数据集的类分布。我们有 900 个 0 类句子和 100 个 1 类句子。
假设我们构建了 10 批,每批 100 个句子,我们最终将得到平均 10 个第 1 类句子和 90 个第 0 类句子。

每班分配 10 批,每批 100 句。红色代表小类,蓝色代表大类。我们可以清楚地看到每一批训练数据中的不平衡。0 类的估计比例现在是 90.5,1 类的估计比例是 9.5。
如何轻松重新平衡以上内容?让我们用 Pytorch 库写几行代码。

24 行 python 魔术构建平衡批次。
从上面我们可以看到 WeightedRandomSampler 使用数组 example_weights 对应于赋予每个类的权重。目标是给次要类分配更高的权重。这将通过从均匀分布移动到具有受控参数的多项式分布来影响从每个类中提取点的可能性。
现在我们可以详细看看 arr_batch 中包含的批次,每个批次实际应该有 100 个句子。出于形象化的目的,我们只关注这里的标签。

0 类的估计比例现在是 51.4,1 类的估计比例是 48.6。
正如我们从上图中看到的,我们现在有了平衡的数据批次。因此,在训练期间,我们的模型不会看到一个类别比另一个类别多很多,因此降低了过度拟合的风险。
总之,我们看到:
- 过采样是解决类不平衡的关键策略,因此降低了过度拟合的风险。
- 当数据集中存在类别不平衡时,从数据集中随机取样是个坏主意。
- 使用 加权随机抽样加权随机抽样器 通过对次要类进行过抽样来重新平衡我们的训练数据类。
重要的:如果你到目前为止,一定要在 Medium 上关注我,以示支持。🤗
在下一篇文章中,我们将深入研究 WeightedRandomSampler 到的实现,更好地理解加权方案。我们还将在一个简单的机器学习场景中应用过采样,并分析其对整体性能的影响。
感谢阅读,如有任何反馈,请在下方留下评论!🤗
解决人工智能的隐藏议程
人工智能中内隐偏见的来源和显著例子有哪些?在建立可接受的数据实践中,怎样做才能最小化它们的后果?

图片来源:巴伊特·罗斯·史密斯
当我们唤起人工智能的隐性偏见时,我们正在认识到机器学习反映了在重复和例外情况下影响管理理解、行动和决策的不合理态度和刻板印象。尽管这种偏见可能是有利的,也可能是不利的,但这些隐含的评估或信念可能会严重限制组织客观利用数据科学的能力。人工智能中存在四种潜在的隐性偏见来源:数据、算法、我们自己的逻辑以及我们对道德行为的定义。让我们依次探索每一个。
机器学习涉及指定用于训练(测试)算法的数据集,该算法随后将用于现实世界条件。虽然作为一个规则,一个组织收集的训练模型的数据越多,结果就越好,但在实践中,隐含偏差的几个来源显著地损害了模型的相关性。当用于训练模型的数据不能准确表示模型将在其中运行的环境或问题空间时,就会出现样本偏差。当训练数据内容受到来自人群的刻板印象或偏见的影响时,就会出现偏见。最后,测量偏差来自错误的测量,其结果系统地污染了数据。
Twitter 流为消费者意见的情感分析提供了一个公共资源,也是样本偏差的一个生动例子。当运行 SVM 和朴素贝叶斯等算法时,Twitter 是文本挖掘的合理选择,因为产生的数据集易于访问,具有成本效益,并且包括各种各样的消费者资料。然而,这种选择提供了一组特定技术用户的意见,而不是一般人群的代表性样本。它将错过那些无法使用智能手机(也无法使用电脑)的人,更不用说那些对这一社交媒体渠道过敏的人了。测试数据可能包括来自大量涌入该媒体的自动用户账户的几条消息,以及这些机器人的转发,这些机器人被编程为在每个问题上提供两极分化的立场。
处于机器学习核心的算法永远不会比用于测试它们的数据更好。
隐含偏差的第二个来源是构造算法来解释或预测现实世界现象的方式。对于数据科学家来说,偏差和方差一起描述了影响预测性能的算法属性。由于偏差和方差是相互依赖的,数据科学家被迫在两者之间寻求平衡。具有高方差的模型往往更适合训练数据,但可能不能很好地推广到训练数据集之外的数据。对于一个给定的用例,在两者之间找到适当的平衡是任意的,并且对于依赖这些算法的组织决策者来说通常是不透明的。
Equivant 的 COMPAS 软件在许多刑事司法系统中广泛用于保释和判刑。这种专有软件依靠一种算法来预测重复犯罪的可能性。这也是算法偏差的一个证据充分的例子。2016 年初,新闻机构 ProPublica 发表了一项研究,证明了该算法的种族偏见:它系统地高估了黑人被告的犯罪意图,同时低估了白人被告的累犯率。尽管由于软件的专有地位,COMPAS 的算法不向公众开放,但该算法显然有两倍的可能将黑人被告错误分类,白人惯犯有 63.2%的时间被错误分类。
偏见的第三个来源可以在人类从他们看到的数据中归纳和推断逻辑结论的方式中找到。认知偏差是在判断中偏离规范或理性的系统模式。一些认知偏差可能是适应性的。认知偏差可能会影响对相似性、判断、记忆和行动的感知。尽管认知偏差可能会在每种情况下导致更有效的行动,但它们通常会导致对个人和业务挑战的误导性表述。某些认知偏差是人类处理局限性的“副产品”,要么是由于缺乏适当的心理机制,要么是由于管理者处理信息的带宽有限。
这种认知偏差导致团队刚刚实现盈利的经理们将可用数据视为市场正在增长的证据,而苦苦挣扎的经理们则倾向于将相同的数据解读为相反的证据。可用性偏差涉及到一种认知机制,在这种机制中,管理者在鉴定新信息时会优先考虑容易想到的数据。如果他们正在进行风险评估,他们倾向于通过最近发生的或提供强烈情感依恋的类似事件来衡量新数据。管理判断的准确性受到经验的影响,他们更有可能低估或高估事件发生的可能性。这回避了一个问题,即人类理性是否不可避免地背负着认知偏见,或者管理决策的内在价值是否是管理者有选择地解释人工智能结果的能力?。
偏见的最后一个来源来自人类对伦理的看法。伦理可以理解为一套指导个人和组织行为的一般原则。道德反映了我们对什么是对什么是错的看法,我们对公司及其市场性质的信念,以及我们对商业实践中可接受的行为的看法。根据文化相对主义的支持者,伦理行为并不存在唯一的真理:我们对可接受限度的解释受到现有社会规范、文化习俗和宗教影响的制约。道德考量通常与我们对自身利益的认知相冲突,因此,许多经理可能会越界,而没有意识到他们正在做任何不道德的事情。
以斯坦福大学以人为中心的人工智能研究所为例。该大学去年成立了该研究所,其愿景是“人工智能的设计师必须广泛代表人类”。然而,当该研究所透露 120 名教师和技术领导者参与该计划时,超过 80%的人是白人,几乎同样多的人是男性。这个群体到底代表了什么?他们代表了不同的种族、文化和当今行业的知识潮流,还是代表了大众?大多数人在专门的商业和工程学校接受教育,他们能够应对当地的道德挑战吗?如果它们确实代表了当今的挑战,那么这种代表是否应该被修改以代表更理想的多样性?
可以做些什么来最小化人工智能隐含偏见的后果?一个策略可以是提高管理层对整个组织使用的数据、算法和应用程序中隐含偏差来源的认识。一个补充的策略将包括定期评估用例以及数据驱动的决策,以寻找不良偏差的证据。识别经常困扰管理决策的风险、不确定性和模糊性的来源,可以帮助确保将机器智能用在最有效的地方。高级管理层可以更进一步,确定并有意识地承认可接受的数据实践和期望的道德立场。最后,但同样重要的是,组织和专业协会可以建立反馈机制,以鼓励围绕数字伦理的讨论和辩论。
这篇文章是我们对 Jay Liebowitz 即将出版的“数据分析和人工智能”一书的贡献的一部分。关于数字伦理的进一步想法可以在我们关于数字伦理的电子书中找到,也可以在我们在商业分析研究所举办的管理会议、课程和暑期学校中找到。
Lee Schlenker 是商业分析和社区管理教授,也是 BAI 的校长。他的 LinkedIn 个人资料可以在www.linkedin.com/in/leeschlenker.查看,你可以在https://twitter.com/DSign4Analytics的 Twitter 上关注白
通过数据解决对新冠肺炎报道的批评
调整世界末日数字的轻触式尝试
在过去几个月的谨慎“回归正常”时期之后,英国首次实施封锁措施的 6 个月纪念日即将到来,随之而来的是再次收紧限制的承诺。我们大多数人都预料到,在经历了夏季的相对轻浮之后,会出现某种形式的第二次封锁,因此,对于鲍里斯·约翰逊宣布重新引入某些限制以遏制病毒传播,很少有人会感到惊讶。看着报告的阳性病例以惊人的速度增加,这似乎也是一个显而易见的决定:

图 1 英国总病例数— 来源
随之而来的是公众对报道的数字越来越怀疑。包括英国广播公司在内的一些媒体对这些数字的可靠性提出了质疑,原因是观察到住院人数和与 COVID 相关的死亡率都没有接近报告的阳性病例率:

图 2 英国住院总人数— 来源

图 3 英国总死亡人数— 来源
虽然这些渠道提出的所有挑战可能都不成立,但它们确实凸显了这些数字的报告方式存在的一些突出问题,更重要的是,公众以及政府对这些数据的解读方式也存在问题。在接下来的几分钟里,我试图强调其中的几个,并提供从不同角度看待这些数字的方法。
放弃
开始之前,我想强调我不是医生、流行病学家、医学生物学家、卫生部长、政策顾问、经济学家和功利主义哲学家。这些计算应该有最大限度的保留,当然不能用来支持任何议程。然而,我确实相信,如果政策决定是基于数据做出的,那么数据应该尽可能地被仔细检查。
英国 COVID 报告的问题
我将探讨关于阳性病例报告的三个关注领域,但在我们深入探讨之前,有必要提供一点关于英国如何进行检测的背景。
测试目前以 4 种方式进行(支柱)。这些是:
- 支柱 1: NHS 和 PHE 检测 —在英国公共卫生(PHE)实验室和 NHS 医院为有临床需求的人以及卫生保健工作者进行 PCR 拭子检测
- 支柱 2:商业伙伴检测——政府指导中规定的针对更广泛人群的 PCR 拭子检测
- 支柱 3:抗体检测——抗体血清学检测,以显示人们是否有 6 月 1 日以来报告的新冠肺炎病毒抗体
- 支柱 4:监测检测——在 PHE、国家统计局、生物银行、大学和其他合作伙伴的支持下,为国家监测进行抗体血清学和 PCR 拭子检测,以更多地了解病毒的流行和传播情况,并用于其他检测研究目的,例如家庭检测的准确性和易用性
支柱 1、2 和 4 都是在不同情况下进行的 PCR 拭子试验;支柱 3 是与众不同的,它是一项血清抗体测试。支柱 2 测试通过商业承包商、在移动测试点或通过送到人们家中的工具包进行。顺便说一句,支柱 2 测试在最近几个月有显著增加,因为政府正在加强其测试计划(理应如此)。这就引出了第一个问题。
案例没有根据测试数据进行调整
敏锐的观察者会点击 gov.uk 上的每日病例计数,并漫步到显示 pillar 进行的测试数量的图表上:

图 4 支柱在英国进行的测试— 来源
虽然大多数支柱保持相当一致,但支柱 2 测试(深蓝色)的活动自 8 月份以来显著增加,尤其是在 9 月份。
这个问题应该是显而易见的:你测试得越多,你就会发现越多的情况。这背后的科学非常直观;至少一些阳性病例的增加可以用这样一个简单的事实来解释,即更多的家庭药盒被提供和使用。
测试被认为是完美的
这些数字的一个更微妙的复杂因素不是来自有多少人接受了测试,而是我们能在多大程度上信任这些测试。医学测试并不完美,你对自己的诊断有多少把握很大程度上取决于它们的预测能力。与分类算法非常相似,医学中的诊断工具具有敏感性和特异性。为了在 COVID 的上下文中理解它们,首先孤立地看它们是有用的。
敏感性给了我们明确患有冠状病毒的个体被诊断为冠状病毒的概率。如果我们以 60%的灵敏度测试 10 个肯定携带病毒的人,结果(平均)将返回 6 个阳性病例和 4 个阴性病例:

图 5 作者图,图标 bqlqn 制作
另一方面,特异性是健康人被正确识别为阴性诊断的概率。如果用具有 60%特异性的试剂盒测试 10 个健康人,结果将平均返回 6 个阴性和 4 个阳性:

图 6 作者图, bqlqn 图标
我们可以用略高的数字来说明在大规模测试中特异性的影响。假设我们有 100 个人,其中 10 个肯定有病毒,90 个没有。在这种情况下,100%灵敏度、90%特异性测试会给出什么结果?

图 7 作者图,图标 bqlqn 制作
该测试具有 100%的灵敏度,因此它能直接正确地识别所有 10 名真正受感染的人。然而,90%的灵敏度意味着剩余的 90 个阴性中只有 90%被正确诊断,剩余的 9 个人在他们实际上没有携带病毒时检测为阳性。
这是怀疑论者书中的另一个关键章节;如果特异性(或者更确切地说是 1-特异性)明显高于病毒的实际流行率,更多的检测只会把水搅浑,并必然增加阳性检测病例的数量。RT-PCR 检测的实际灵敏度和特异性分别在 60-85%和 94-99%之间,这取决于你咨询的是哪项(小样本)研究。
不管怎样,特异性和敏感性应该(而且确实)在真实患病率的估计中发挥作用,我们将在下一节探讨。
测试支柱一视同仁
但首先,我想指出一些更微妙的东西;测试进行的环境对于我们能在多大程度上依赖其结果非常重要。当然,由医院专业人员进行的检测(例如,在医院可以进行重复检测以减少不确定性)应该比带回家的试剂盒更有意义,在医院人们自己进行擦拭,污染的风险要高得多。
有趣的是,尽管这些因素表明以医院为基础的支柱 1 测试的阳性率更高,但实际情况恰恰相反:

图 8 支柱 1 的比率& 2 在英国检测返回阳性— 数据来源
自 6 月份以来,在医院检测出阳性的机会已经减少,并且对于带回家的试剂盒来说保持相对稳定,直到两者在 9 月份再次开始增加,到那时,你在家里检测出阳性的可能性是在医院的 4-5 倍。
对此可能有多种解释,但我只能猜测(不是专家,记得吗?)——例如,这可能是污染和人口统计学差异的结合。支柱 2 测试在护理院中使用很多,这些护理院因局部大规模感染而闻名,但它们也在普通公众中使用,大概是在旅行或工作之前。另一方面,支柱 1 测试用于病人和有医疗需求的人。另一个关键区别是,支柱 2 测试由商业承包商处理,因此涉及的方法可能有所不同。
无论如何,这种系统性的差异应该被强调,尤其是当这些阳性病例被一起报告时。
我们能做得更好吗?
在本文的最后一部分,我将演示一些方法来解决我上面概述的问题。为了简洁起见,我不会分享内嵌的代码片段,但我会让任何人都可以阅读我的笔记本。
数据
我将在 5 月 28 日至 9 月 9 日期间使用英国 15 周的支柱 1 和 2 测试结果,这些结果发布在 gov.uk 上。该数据提供了按支柱分列的每周测试总数和阳性测试案例。快速浏览一下阳性病例总数,我们会看到熟悉的上升曲线:

图 9 周正支柱 1 & 2 测试案例— 来源
我在这里的工作是:
- 在给定 PCR 检测的特异性和敏感性估计值的情况下,估计测试人群中活动性感染的真实流行率
- 对支柱 1 和 2 分别执行此操作
- 针对每周样本量的差异进行调整
估计真实流行率
你的医学测试不是 100%准确的想法并不新鲜。因此,已经推导出一个非常简单的公式,如Lewis&Torgerson(2012)所示:

其中 P_t 是该疾病在人群中的真实患病率, P_a 是表观患病率, S_e 和 S_p 分别是诊断测试的灵敏度和特异性。注意,这里我们有 3 个未知数,数据只提供给我们表面的患病率。鉴于 P_a 是获得阳性测试结果的概率,我们的观察值(测试结果)将遵循二项分布:

P_a 由三个未知数参数化, P_t , S_e , S_p — 这些我们都不确定。为了解决这个问题,我将使用贝叶斯推理和马尔可夫链蒙特卡罗(MCMC)抽样来绘制给定先验分布的参数的随机值,将结果与上面由二项式 PDF 给出的概率进行比较。给定测试结果,我的 P_t 的后验概率应该在真实患病率附近收敛。
灵敏度和特异性先验
我们简要讨论了 PCR 拭子试验的敏感性和特异性;这些研究的结果有很大的不同,取决于许多因素,如人口统计、地理、疾病阶段和研究时间。张&杜(2020) 将这些结果汇总在一起,给出了敏感性和特异性的估计概率分布,我从中获得了构建β先验的灵感:

其中支柱 1 和支柱 2 拭子测试的灵敏度和特异性的平均值分别为 0.821 和 0.983,但是支柱 2 灵敏度的方差加倍,表示家用试剂盒正确检测病毒的能力的不确定性更高。
真实患病率先验
这就是事情变得更加困难的地方。COVID 是一种疫情,因此它的流行率会随着社区、人群和人群的变化而变化,所以在这里使用海外的研究不会很有效。理想的数据集将来自支柱 4 测试,它正是为此目的而设立的。可悲的是,英国政府并没有公布结果(最近拒绝了信息自由的要求这样做)。
由于缺乏好的数据,我的最佳选择是最初相信结果告诉我的东西,并用与那一周的明显患病率相对应的方法构建我的β先验(对我的参数进行一定程度的任意缩放,以表示我对结果的信心):

我可以画出从 9 月 3 日开始的一周内的真实流行率:

图 10 敏感性、特异性和患病率的β先验
蒙特卡罗马尔可夫链抽样
我们可以从之前的 3 个分布中随机抽取样本(支柱 1 和支柱 2 ),根据之前的公式估计我们的表观患病率。然后,我们可以将其与我们观察到的数据进行比较,评估这些样本出现的可能性,给出我们表观患病率的二项式分布,并构建后验分布。
抽取 10,000 个样本后,支柱 1 的后验概率如下所示:

图 11 支柱 1 后视图
敏感性和特异性大致保持不变,我们对支柱 1 测试真实流行率的估计集中在一个较低的平均值附近(从 0.010 下降到 0.006)。
支柱 2 也是如此:

图 12 支柱 2 的后视图
同样,测试准确性指标保持相对一致,而流行率从 0.040 下降到 0.031。
每周估计
我们可以为我们的个人每周观察重复上述过程,根据我们的数据重新创建先前的构建练习。这使我们能够将估计的流行率与报告的流行率进行对比;我将 94%的最高后验密度值作为伪置信区间包含在图上:

图 13 支柱 1 & 2 的估计流行率
我们观察到,两个支柱的估计平均患病率始终低于报告的患病率,然而,报告的患病率确实在 94% HPD 范围内。
我们还可以按支柱构建总病例的估计值,方法是通过已进行的总检测按比例放大患病率估计值,从本质上给出我们认为受检测者中有多少人真正被感染:

图 14 支柱 1 & 2 的预估案例
最后,我们可以结合支柱 1 和 2 案例的估计值,将其与报告的案例总数进行比较:

图 15 两大支柱的估计案例总数
我们从中学到了什么?
我概述了英国新冠肺炎报告面临的一些挑战,并提供了一些解决这些挑战的方法,展示了它们对公开数据的影响,特别说明了 PCR 检测的估计特异性和敏感性,着眼于估计患病率而不是总病例数(不考虑检测量),并分别处理了两个支柱。这告诉了我们什么?
阳性结果可能比报道的要少…
也就是说,在被测试的人群中。假设我们对聚合酶链式反应测试准确性的了解是正确的,并且我们的先验具有相当的代表性,那么实际的阳性案例可能低于支柱 1 & 2 中报告的案例。话虽如此,如果我们扩大到英国的人口,即使减少的估计流行率也意味着全国范围内更高的实际阳性病例数,所以可能没有理由放松。
…但病例可能仍在增加
在理想情况下,我们可以通过支柱 4 测试结果更好地估计真实流行率,但是估计(和报告)的流行率表明,即使我们对进行的测试数量进行调整,我们仍然观察到从 9 月开始阳性病例相对急剧上升。虽然特定支柱数据的可用性仅允许我们对截至 9 月 9 日的数据进行建模,但从报告的案例总数来看,有理由假设这一趋势将在此后继续。
那现在怎么办?
我们已经能够解决怀疑论者提出的一些挑战,并为他们提供数据驱动的解决方案。虽然我们的分析显示,真正被发现的病例数量总体较低,但我们不能否认患病率突然上升。相对于阳性病例,住院率可能仍然较低,但在我们的新世界中保持谨慎可能是明智的,以免我们发现自己处于一种因缺乏能力而无法治疗疾病的境地。
事后思考
我做错什么了吗?我能做得更好吗?我做得好吗?
请随时在 LinkedIn 上联系我;如果你对我的工作感兴趣,我总是很乐意接受挑战或者只是聊聊天。
如果你想自己玩代码,请点击我的 Google Colab 笔记本的链接:
编辑描述
colab.research.google.com](https://colab.research.google.com/drive/1l3l-ZQ2fJQozHh_vn03WwIr-oWGX7JQm?usp=sharing)*
解决人工智能中的种族偏见:好奇者指南
想学习算法公平,但不知道从哪里开始?这是一份精选的阅读材料、播客和视频列表。
由法希姆·哈桑和海伦·格扎亨合著

众所周知,人类容易犯错,容易受到偏见的影响,这些偏见会影响算法以歧视的方式表现也不是什么秘密。然而,很难了解这些偏见在我们日常生活中使用的技术中有多普遍。在当今技术驱动的世界,我们需要批判性地思考人工智能对社会的影响,以及它如何与性别、阶级和种族相交。
说到种族——想象一下由于算法中的种族偏见而被错误逮捕。这正是发生在罗伯特·朱利安·博查克·威廉姆斯身上的事情——他是密歇根州的一名非裔美国人,在妻子和年幼的孩子面前被从家中逮捕。他没有犯任何罪,但警方使用的面部识别软件怀疑他在商店行窃。他被错误关押的经历是执法部门手中有缺陷的技术如何放大对黑人社区的歧视的缩影。
面部识别技术的偏见现在已经成为媒体的趋势。最近,许多科技公司(包括亚马逊、IBM、微软等巨头。)发布公告停止面部识别服务或产品的设计和开发,并停止向州和地方警察部门和执法机构销售。一些研究人员指出了这些技术的局限性和不准确性,并对这些技术如何能够延续歧视和种族貌相表示关切。小罗伯特的案例清楚地表明,虽然科技巨头的这些决定可以被认为是朝着正确方向迈出的一小步,但这些显然不会解决科学历史上根深蒂固的种族主义问题。

白居松的拼贴插图(经许可使用)
当我们意识到应用有偏见的人工智能技术的危险后果时,我们也意识到我们需要忘记我们都被教导的种族主义。这就提出了一个问题— 我们如何确保我们创造的技术也能忘记它?
要回答这个问题,我们需要了解技术是如何强化压迫和延续种族偏见的。
关于这个话题的一本很好的入门书是《压迫的算法》一书,作者是加州大学洛杉矶分校信息研究副教授萨菲娅·乌莫哈·诺布尔(1)。萨菲亚用通俗易懂的语言解释了自动化决策背后的数学基础,以及人类偏见是如何嵌入到“大数据”、“搜索引擎”和“算法”等关键概念中的。通过使用广泛的例子,她表明,即使算法决策似乎是一个公平和客观的过程,但在现实中,它反映了人类的偏见和种族偏见。这本书鼓励读者关注他们用来查找信息的搜索引擎和其他信息门户,并提出关键问题“这是正确的信息吗?给谁的?”
关于同一主题的另一本好书是凯茜·奥尼尔的《数学毁灭的武器》,凯茜·奥尼尔毕业于哈佛大学,是一名数据科学家,因她的博客 mathbabe.org 而闻名。像 Safiya 一样,Cathy 也使用几个案例研究来提高对使用影响政策决策和放大不平等和偏见的算法的社会风险的认识。这些案例基于她自己在华尔街的职业生涯和她广泛的调查研究。例如,在现代工作场所雇用和解雇人员的算法,提供获得信贷的途径等等。作为算法公平的倡导者,她通过讲座和演示分享了她的经验(查看她的 TED 演讲、这个短视频动画或她在谷歌的讲座)。
那么,我们能做些什么来解决算法中的这些偏差呢?
首先,我们必须理解这些有偏见的、普遍存在的技术的设计过程,这正是 T2·鲁哈·本杰明所著的《追逐技术:废除新吉姆法典的工具》一书的重点(3)。作为普林斯顿大学非洲裔美国人研究的副教授,Ruha 研究并教授种族、技术和正义之间的关系。她形容自己的工作是“创造一个环境,让他们(学生)可以超越他们可能无意中为智力发展设定的限制。”这一理念也被灌输到她的书籍和演讲中。除了她的学术文章之外,她还不厌其烦地谈论这场战斗需要的集体努力和公民参与。一种快速简单的方法来更好地了解她的工作是在哈佛大学伯克曼克莱恩互联网中心举办的视频演示会,她在会上讨论了更多关于社会的细节:“一系列编码不平等的歧视性设计:通过明确放大种族等级,通过忽视但复制社会分裂,或通过旨在解决种族偏见但最终做了相反的事情。”
其次,我们可以合作克服这些有缺陷的设计方法。将我们凝聚在一起的共同主线是同理心,这是世界经济论坛 Joy Buolamwini 的口语表演“ 通过计算产生同情:对抗算法偏见 ”的核心。麻省理工学院媒体实验室的计算机科学家 Joy 是算法公平的拥护者。她创建了算法正义联盟(ASJ)——一个由跨学科研究人员组成的组织,致力于设计更具包容性的技术,并减轻人工智能对社会的有害影响。在乔治城法学院隐私技术中心的合作下,ASJ 开发了安全脸承诺,帮助组织公开承诺算法的公平性。
如果你对流媒体更感兴趣,你可以看看 Joy Buolamwini 的 ted 演讲“我如何对抗算法中的偏见”。有几个播客值得偷听;比如— 与米兰达·莫布雷如何设计一个道德算法与德里克·莱本 以及牛津大学关于 AI 伦理与法律规制的讨论。
现在,如果你已经在这个列表上走了这么远,并渴望了解更多,请查看以下内容-
● 亲爱的算法偏见,在谷歌与洛根·布朗宁的讨论(没错!她是来自网飞的亲爱的白人 !)和 Avriel Epps-Darling (哈佛大学博士生,研究音乐、科技、有色人种青年及其性别身份之间的交集)。
●一个相关的谈话是“算法能减少不平等吗?由重新确定 Abebe 。Rediet 是加州大学伯克利分校的计算机科学研究员和助理教授。她还在 2019 年组织了关于 AI for Social Good 的研讨会,并与 Timnit Gebru 共同创立了 Black in AI 。谷歌的计算机科学家蒂姆尼特是算法偏差领域的另一个鼓舞人心的人物。
●另一位面部识别技术的激烈批评者是黛博拉·拉杰,她是多伦多大学的工程系学生,目前在人工智能研究所担任技术研究员。要快速阅读,请查阅《纽约时报》报道她学术工作的文章。
●敬请关注纪录片“编码偏差”。这部电影受到乔伊·波伦维尼作品的启发,探索了两个关键问题:“人工智能在管理我们的自由方面日益增长的作用会产生什么影响?那些因为种族、肤色和性别而被锁定的人会有什么后果?”对于幕后故事,你也可以和电影制作人 Shalini Kantayya* 以及上面提到的其他有影响力的研究人员——萨菲娅·诺布尔、黛博拉·拉吉和乔伊·波伦维尼(Joy Buolamwini)一起观看 Q & A。***
呼吁采取集体行动
阅读这些主题可以帮助我们更好地了解我们的世界——一个正在被技术的快速创新所塑造的世界。这些问题影响着我们的整个社会,所以我们需要在学术圈之外,在我们的朋友和家人之间进行讨论(让我们为餐桌上的谈话增添趣味,好吗?).如果是对我们来说,我们人类需要处于设计过程的中心——就这么简单。为了让这样的参与式设计成为现实,让我们更加关注新技术和现有技术的设计。每当我们看到媒体大肆宣传技术拯救世界,我们就来谈谈它是如何设计的。为了谁?做什么?当我们交谈时,让我们把自己的生活经历与我们正在读的书、正在听的播客和正在看的视频联系起来(或者希望狂看!).**
作者
法希姆·哈桑和海伦·格扎亨是加拿大阿尔伯塔大学的 BIPOC 学生。法希姆是公共卫生专业的博士生,对机器学习感兴趣。他也是阿尔伯塔省健康服务的顾问委员会成员。海伦正在学习计算机科学;她还是一个名为 Ada's Team 的学生团体的主席,该团体致力于促进 STEM 的多样性,特别关注阿尔伯塔大学的技术。
放弃
作者对自己的观点负责。观点不反映雇主或大学的观点。
确认
感谢 JuSong Baek 的插图和 Susie Moloney 深思熟虑的评论和反馈。我们也感谢加拿大阿尔伯塔大学黑人研究生协会成员和 Ada 团队的鼓励。
参考文献
①贵族苏。压迫的算法:搜索引擎如何强化种族主义?纽约:纽约大学出版社;2018.
(2)奥尼尔 c .数学毁灭的武器:大数据如何增加不平等并威胁民主。第一版。纽约:皇冠;2016.
(3) Benjamin R.《技术之后的竞赛:新吉姆法典的废奴主义工具》。英国剑桥;马萨诸塞州梅德福德:政治出版社;2019.
解决约翰·史密斯问题
使用模糊逻辑识别不匹配的副本
特别感谢凯拉什·阿瓦提。

图片由作者重现,灵感来自自由词典
1.介绍
许多数据库都有重复的数据。尤其是在需要手动输入数据的情况下。为了清理数据和解决不必要的重复,有必要识别和纠正杂乱的数据。然而,许多重复是不匹配的;这意味着可能存在包含例如拼写错误的重复数据。使用SQL数据库语言完美地识别这些重复项是具有挑战性的,因为这依赖于精确的匹配(由于关系数据库理论的原则)。因此,有必要寻找其他方法来识别不匹配的副本,这就是模糊匹配能够被使用的地方。
模糊匹配摆脱了编辑距离的概念,实质上是将一个字符串转换成另一个所需的最小操作数。最常用的编辑距离度量之一是 Levenshtein distance ,它本质上是,“将一个单词变为另一个单词所需的单个字符编辑(插入、删除或替换)的最小数量。”。其他度量包括汉明距离、 Jaccard 距离、 Jaro-Winkler 距离、最长公共子串距离或余弦距离。出于本文的目的,使用光学字符串对准距离 (OSA)(它是 Damerau-Levenshtein 距离的变体)。
为了说明 OSA,给出下面的例子:
bear -> bear = 0 steps (0 characters changed)
bear -> beat = 1 step (1 characters changed)
bear -> meat = 2 steps (3 characters changed)
bear -> tearing = 4 steps (1 character changed, 3 characters added)
bear -> ear = 1 step (1 character removed)
正如所见,将一个字符串转换为另一个字符串所需的更改次数就是所采取的步骤数。该逻辑将用于匹配给定数据库中的记录。
2.建立
2.1.加载包
第一步是加载必要的包。
# Load required packages
library(tidyverse) #Various tools
library(readxl) #Read in Excel's
library(readr) #Read in data
library(magrittr) #Great piping tools
library(kableExtra) #Pretty tables
library(stringdist) #For Edit Distance algorithms
library(DBI) #Testing SQL
library(RSQLite) #Testing SQL
library(tictoc) #Check code run-time
2.2.加载数据
下一步是加载数据。JohnSmiths数据是“虚拟数据”,用于说明模糊匹配的例子。原始数据可在八 2Late 上找到。
# Load files from Excel
dat_JohnSmiths <- find_rstudio_root_file() %>%
paste0("/Data/", "many_john_smiths.xlsx") %>%
read_excel() %>%
data.frame()
2.3.检查数据
加载完电子表格后,JohnSmiths数据如下所示:

查看数据帧后,详细信息如下所示:
> Name: dat_JohnSmiths
> Type: data.frame
> Dims: 10 x 8
> Size: 4.9 Kb
> Field Counts:
> field distinct count distinct%
> 1 CustomerID 10 10 1.0
> 2 FirstName 4 10 0.4
> 3 LastName 2 10 0.2
> 4 Title 4 10 0.4
> 5 AddressLine1 10 10 1.0
> 6 AddressSuburb 5 10 0.5
> 7 AddressPostcode 6 10 0.6
> 8 Phone 10 10 1.0
3.使用 SQL
当使用SQL检查数据时,使用了以下脚本。注意到它加入了FirstName、LastName、AddressPostcode和CustomerID字段。查询结果返回所有数据。这意味着它无法确定任何重复。因此,SQL 不能用于此目的。
/* Check for duplicates between the two tables. */
SELECT *
FROM JohnSmiths t1
WHERE EXISTS (
SELECT 'x'
FROM JohnSmiths t2
WHERE t1.FirstName=t2.FirstName
AND t1.LastName=t2.LastName
AND t1.AddressPostcode=t2.AddressPostcode
AND t1.CustomerID=t2.CustomerID
)

4.使用 R
4.1.概观
要通过模糊匹配查找重复项,请遵循以下步骤:
- 将中的关键字段连接成每行的单个文本字符串
- 计算每条记录的字符串长度。
- 创建字符串距离矩阵(使用
[stringdist](https://www.rdocumentation.org/packages/stringdist/versions/0.9.5.5)包中的[stringdistmatrix()](https://www.rdocumentation.org/packages/stringdist/versions/0.9.5.5/topics/stringdist)函数)。 - 将字符串距离矩阵归一化为 0 到 1 之间的值:
4.1。创建一个最大长度的成对向量。
4.2。将距离长度除以较长字符串的长度。 - 创建相似性矩阵
- 识别高于相似性阈值的每对记录。
- 显示结果记录。
4.2 演练
第一步是将字符串连接在一起。这是使用paste()功能完成的。产生的向量如下所示(为了方便起见,每个元素都放在一个新行上)。
# Create concatenated vector
vec_Strings <- dat_JohnSmiths %>%
mutate(strings=paste0(FirstName
,LastName
,AddressLine1
,AddressPostcode
,AddressSuburb
,Phone
)) %>%
select(strings) %>%
pull()# Review
vec_Strings %>% cat(sep="\n")> JohnSmith12 Acadia Rd9671Burnton1234 5678
> JhonSmith12 Arcadia Road967Bernton1233 5678
> JSmith12 Acadia Ave867`1Burnton1233 567
> JohnSmith13 Kynaston Rd9671Burnton34561234
> JohnSmithNA9671Burnton34561233
> JohnS12 Kinaston Road9677Bernton34561223
> JonSmith13 Kinaston Rd9761Barnston36451223
> JohnSmith12 Aracadia St9761Brenton12345666
> JohnSmith13 Acacia Ave8961Burnside67231231
> JohnSmith12 Kingsford Rd9671Burnton89624328
接下来,必须使用[stringr](https://www.rdocumentation.org/packages/stringr/versions/1.4.0)包中的[str_length()](https://www.rdocumentation.org/packages/stringr/versions/1.4.0/topics/str_length)函数计算每条记录的字符串长度。
# Create vector of lengths
vec_Lengths <- str_length(vec_Strings)# Review the vector
vec_Lengths %>% print()> [1] 41 43 39 42 30 40 42 42 42 43
接下来,使用[stringdist](https://www.rdocumentation.org/packages/stringdist/versions/0.9.5.5)包中的[stringdistmatrix()](https://www.rdocumentation.org/packages/stringdist/versions/0.9.5.5/topics/stringdist)函数计算字符串距离矩阵。注意通过使用超参数method="osa"使用最佳字符串对齐算法。这个函数将值保存在一个一维数组中,但是在打印时,它会显示距离矩阵的下三角。
# Create distance matrix
vec_Distances <- stringdistmatrix(vec_Strings, method=”osa”)# Review
vec_Distances %>% print()> 1 2 3 4 5 6 7 8 9
> 2 7
> 3 10 13
> 4 15 21 24
> 5 18 25 25 15
> 6 22 21 28 12 17
> 7 20 23 26 9 21 14
> 8 10 13 17 20 22 25 22
> 9 19 22 19 21 23 29 23 22
> 10 17 22 25 13 22 19 16 22 24
接下来,需要计算每对记录的最大长度。这可以通过[utils](https://www.rdocumentation.org/packages/utils/versions/3.6.2)包中的[combn()](https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/combn)函数来实现。该函数采用以下参数:
- 要迭代的长度向量。
- 要选择的元素数量的数值。值
2表示它将匹配记录对。 - 将应用于每对的函数。在这种情况下,选择
max()功能。 - 一个逻辑值,表示是将结果简化为一个向量还是返回一个列表。
产生的向量如下所示。
# Create Pairwise Vector
vec_PairwiseMax <- combn(vec_Lengths, 2, FUN=max, simplify=TRUE)# Review
vec_PairwiseMax> [1] 43 41 42 41 41 42 42 42 43 43 43 43 43 43 43 43 43 42 39 40 42 42 42
> [24] 43 42 42 42 42 42 43 40 42 42 42 43 42 42 42 43 42 42 43 42 43 43
接下来,计算归一化的距离矩阵。
# Calculate normalised values
vec_NormalisedDistances <- vec_Distances/vec_PairwiseMax# Review
vec_NormalisedDistances> 1 2 3 4 5 6 7 8 9
> 2 0.1628
> 3 0.2439 0.3023
> 4 0.3571 0.4884 0.5714
> 5 0.4390 0.5814 0.6410 0.3571
> 6 0.5366 0.4884 0.7000 0.2857 0.4250
> 7 0.4762 0.5349 0.6190 0.2143 0.5000 0.3333
> 8 0.2381 0.3023 0.4048 0.4762 0.5238 0.5952 0.5238
> 9 0.4524 0.5116 0.4524 0.5000 0.5476 0.6905 0.5476 0.5238
> 10 0.3953 0.5116 0.5814 0.3023 0.5116 0.4419 0.3721 0.5116 0.5581
接下来,归一化的距离被强制到一个矩阵中。创建后,确保不重复计算两次是很重要的。要做到这一点,右上角的三角形和对角线都是零的。
# Create Similarity Matrix
mat_SimilarityScore <- round(1-vec_NormalisedDistances, 2) %>% as.matrix()# Make the upper triangle all zero’s. This is to avoid double-counting duplicates.
mat_SimilarityScore[upper.tri(mat_SimilarityScore)] <- 0# Make the diagonals all zero’s. This is to ensure that the same string does not get matched to itself.
mat_SimilarityScore[diag(mat_SimilarityScore)] <- 0# Review
mat_SimilarityScore> 1 2 3 4 5 6 7 8 9 10
> 1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0
> 2 0.84 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0
> 3 0.76 0.70 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0
> 4 0.64 0.51 0.43 0.00 0.00 0.00 0.00 0.00 0.00 0
> 5 0.56 0.42 0.36 0.64 0.00 0.00 0.00 0.00 0.00 0
> 6 0.46 0.51 0.30 0.71 0.57 0.00 0.00 0.00 0.00 0
> 7 0.52 0.47 0.38 0.79 0.50 0.67 0.00 0.00 0.00 0
> 8 0.76 0.70 0.60 0.52 0.48 0.40 0.48 0.00 0.00 0
> 9 0.55 0.49 0.55 0.50 0.45 0.31 0.45 0.48 0.00 0
> 10 0.60 0.49 0.42 0.70 0.49 0.56 0.63 0.49 0.44 0
作为参考,相似性矩阵的详细信息打印如下。
> Name: mat_SimilarityScore
> Type: matrix
> Dims: 10 x 10
> Size: 2.6 Kb
接下来,将识别高于给定阈值的值。为了实现这一点,编写了一个自定义函数。
# Add function for identifying scores above a given threshold.
tlargest <- function(matrix, threshold, print=FALSE) {
#' @title Return Matrix Values Above A Threshold
#' @description Subset a matrix to return values that are above a specified threshold.
#' @note Will also print the count of how many records were matched. Necessary due to the ambiguity of using a threshold value.
#' @param matrix matrix. A matrix, which is the matrix to be sub-set.
#' @param threshold numeric. A single numeric value, corresponding to the threshold, above which values are to be returned.
#' @return A matrix containing columns:
#' — 'row' : A numeric value corresponding to the row index of the returned value.
#' — 'col' : A numeric value corresponding to the column index of the returned value.
#' — 'val' : A numeric value which is the similarity score between the 'row' and 'col' values.
# Validations:
if (!is.matrix(matrix)) {stop("'matrix' must be a matrix")}
if (!is.numeric(matrix)) {stop("'matrix' must be numeric")}
if (!length(threshold)==1) {stop("'threshold' must be atomic")}
if (!is.numeric(threshold)) {stop("'threshold' must be numeric")}
if (!between(threshold, 0, 1)) {stop("'threshold' must be between 0 and 1")}
# Determine the indices to be returned
sort <- sort(matrix, decreasing=TRUE)
order <- order(matrix, decreasing=TRUE)
order <- order[sort>=threshold]
# Generate the matrix of indices to be returned
position <- arrayInd(order, dim(matrix), useNames=TRUE)
position <- set_colnames(position, c("rec1", "rec2"))
position <- cbind(position, val=matrix[order])
# Print subset number
if (print==TRUE) {
cat("Selected threshold : ", threshold, "\n"
,"Matching records : ", nrow(position), "\n"
,"Total records : ", nrow(matrix), "\n"
,"Matching percent : ", nrow(position)/nrow(matrix)
,sep=""
)
}
# Return
return(position)
}
因此,当应用该函数时,将生成如下所示的矩阵。
# Generate matching records
mat_MatchingRecords <- tlargest(matrix = mat_SimilarityScore
,threshold = 0.7
,print = TRUE
)> Selected threshold : 0.7
> Matching records : 8
> Total records : 10
> Matching percent : 0.8 # Review
mat_MatchingRecords> rec1 rec2 val
> [1,] 2 1 0.84
> [2,] 7 4 0.79
> [3,] 3 1 0.76
> [4,] 8 1 0.76
> [5,] 6 4 0.71
> [6,] 3 2 0.70
> [7,] 8 2 0.70
> [8,] 10 4 0.70
一旦识别出匹配的记录,就需要从原始表中提取它们。为此,再次编写一个自定义函数。它获取原始数据帧和相似性矩阵,然后遍历矩阵,从数据帧中提取相关记录。
find_MatchingRecords <- function(dataframe, sim_matrix, print=FALSE) {
#' @title Find Mathching Records
#' @description Use 'sim_matrix' to find matching records from 'dataframe'.
#' @note The `sim_matrix` contains the similarity matrix, generated from `stringdistmatrix()` and the `nlargest()` (or `tlargest()`) functions.
#' @param dataframe dataframe. The dataframe from which the matching records will be extracted.
#' @param sim_matrix matrix. The matrix containing the attributes for finding the matching records.
#' @param print logical. Whether or not to print the output as a text string.
#' @return A data.frame containing the score and the records that have been matched. Also, this is printed to the console.
# Validations
if (!is.data.frame(dataframe)) {stop("'dataframe' must be a dataframe")}
if (!is.matrix(sim_matrix)) {stop("'sim_matrix' must be a matrix.")}
if (!is.double(sim_matrix[[2]])) {stop("'sim_matrix' must be a numeric matrix.")}
if (c("rec1","rec2") %>% is_in(colnames(sim_matrix)) %>% all() %>% not()) {stop("'sim_matrix' must contain two columns named: 'rec1' and 'rec2'.")}
# Set output
str_return <- NULL
dat_return <- data.frame("Score"=NA_real_
,"Index1"=NA_real_
,"Record1"=NA_character_
,"Index2"=NA_real_
,"Record2"=NA_character_
,stringsAsFactors=FALSE
)
# Determine number of itterations
iterations <- sim_matrix %>% nrow()
# Loop through number of itteraions
for (i in 1:iterations) {
# Extract score
sim_score <- sim_matrix %>%
extract(i, 3)
# Extract the first matching index
rec1_index <- sim_matrix %>%
extract(i,1)
# Extract first matching record
rec1_record <- sim_matrix %>%
extract(i,1) %>%
extract(dataframe, ., ) %>%
as.character() %>%
paste(collapse=" ")
# Extract the second matching index
rec2_index <- sim_matrix %>%
extract(i,2)
# Extract second matching record
rec2_record <- sim_matrix %>%
extract(i,2) %>%
extract(dataframe, ., ) %>%
as.character() %>%
paste(collapse=" ")
# Build return
str_return %<>% paste0("\n") %>%
paste0("Score: ", sim_score, "\n") %>%
paste0("Record 1: (Index ", rec1_index, ") ", rec1_record, "\n") %>%
paste0("Record 2: (Index ", rec2_index, ") ", rec2_record, "\n")
dat_return[i,] <- c(sim_score, rec1_index, rec1_record, rec2_index, rec2_record)
}
# Print str_return
if (print==TRUE) {
cat(str_return)
}
# Return dat_return
return(dat_return)
}
最后,当应用该函数时,数据显示如下。
# Generate data
dat_MatchingRecords <- find_MatchingRecords(dataframe = dat_JohnSmiths
,sim_matrix = mat_MatchingRecords
,print = TRUE
)> Score: 0.84
> Record 1: (Index 2) 2 Jhon Smith Mr 12 Arcadia Road Bernton 967 1233 5678
> Record 2: (Index 1) 1 John Smith Mr 12 Acadia Rd Burnton 9671 1234 5678
>
> Score: 0.79
> Record 1: (Index 7) 7 Jon Smith Mr. 13 Kinaston Rd Barnston 9761 36451223
> Record 2: (Index 4) 4 John Smith Mr 13 Kynaston Rd Burnton 9671 34561234
>
> Score: 0.76
> Record 1: (Index 3) 3 J Smith Mr. 12 Acadia Ave Burnton 867`1 1233 567
> Record 2: (Index 1) 1 John Smith Mr 12 Acadia Rd Burnton 9671 1234 5678
>
> Score: 0.76
> Record 1: (Index 8) 8 John Smith Dr 12 Aracadia St Brenton 9761 12345666
> Record 2: (Index 1) 1 John Smith Mr 12 Acadia Rd Burnton 9671 1234 5678
>
> Score: 0.71
> Record 1: (Index 6) 6 John S Dr. 12 Kinaston Road Bernton 9677 34561223
> Record 2: (Index 4) 4 John Smith Mr 13 Kynaston Rd Burnton 9671 34561234
>
> Score: 0.7
> Record 1: (Index 3) 3 J Smith Mr. 12 Acadia Ave Burnton 867`1 1233 567
> Record 2: (Index 2) 2 Jhon Smith Mr 12 Arcadia Road Bernton 967 1233 5678
>
> Score: 0.7
> Record 1: (Index 8) 8 John Smith Dr 12 Aracadia St Brenton 9761 12345666
> Record 2: (Index 2) 2 Jhon Smith Mr 12 Arcadia Road Bernton 967 1233 5678
>
> Score: 0.7
> Record 1: (Index 10) 10 John Smith Dr 12 Kingsford Rd Burnton 9671 89624328
> Record 2: (Index 4) 4 John Smith Mr 13 Kynaston Rd Burnton 9671 34561234
其数据帧如下所示:
# Review
dat_MatchingRecords %>%
kable() %>%
kable_styling(bootstrap_options=c("striped", "bordered", "condensed")
,full_width=FALSE
,position="left"
) %>%
(function(x){
x %>% save_kable("Images/JohnSmithsMatching.png")
x %>% return()
})

如所见,该方法已经以合理的准确度水平识别了这些重复。
4.3.包裹
因此,在识别数据库中的重复项时,使用“模糊匹配”来识别不同记录集之间的相似性是很有用的。
但是,考虑到本例中提供的数据是虚构的,对真实世界的数据执行相同的过程是有用的。
5.真实的例子
使用从网上搜集的商业地址,同样的方法被应用。
5.1.预处理
数据是从 Excel 电子表格AddressData.xlsx中加载的。
# Load Data
dat_Addresses <- find_rstudio_root_file() %>%
paste0("/Data/", "AddressData.xlsx") %>%
read_excel(col_types=c("text")) %>%
data.frame()
前 10 条记录如下所示:

数据的详细信息显示如下:
> Name: dat_Addresses
> Type: data.frame
> Dims: 19388 x 8
> Size: 4.2 Mb
> Field Counts:
> field distinct count distinct%
> 1 COMPANY 6320 19388 0.3259748
> 2 ADDRESS 8646 19388 0.4459459
> 3 CITY 2459 19388 0.1268310
> 4 STATE 8 19388 0.0004126
> 5 ZIP 1264 19388 0.0651950
> 6 ISOCNTRYCODE 1 19388 0.0000000
然后,对地址执行一些预处理操作,以减小数据的大小。
# Mutate data.
# Steps:
# 1\. Remove special characters
# 2\. Remove numeric values (Street numbers, etc.)
# 3\. Remove additional white spaces
# 4\. Capitalise
# 5\. Select distinct.
dat_AddressesClean <- dat_Addresses %>%
mutate_all(str_replace_all, "[[:punct:]]", "") %>%
mutate_at(c("COMPANY", "ADDRESS", "CITY", "STATE"), str_replace_all, "[0-9]", "") %>%
mutate_all(str_squish) %>%
mutate_all(str_to_upper) %>%
distinct() %>%
arrange(ISOCNTRYCODE, STATE, CITY, ADDRESS)# Check result
check_ObjectDetails(dat_AddressesClean) %>% cat()# Check result
check_ObjectDetails(dat_AddressesClean) %>% cat()> Name: dat_AddressesClean
> Type: data.frame
> Dims: 9945 x 6
> Size: 1.5 Mb
> Field Counts:
> field distinct count distinct%
> 1 COMPANY 6279 9945 0.6313725
> 2 ADDRESS 6267 9945 0.6301659
> 3 CITY 2344 9945 0.2356963
> 4 STATE 8 9945 0.0008044
> 5 ZIP 1264 9945 0.1270990
> 6 ISOCNTRYCODE 1 9945 0.0000000
最后,必须将数据一起粘贴到一个向量中,如下所示。现在数据可以进行模糊匹配了。
# Create vector
vec_Addresses <- dat_AddressesClean %>%
unite("vec", sep="") %>%
pull()# Review
vec_Addresses %>%
head(10) %>%
cat(sep="\n")
> MELBOURNE FACADES PTY LTDANU ELLERY CRESACTONACT2601AU
> IC FORMWORK SERVICES PTY LTDCLUNIES RDACTONACT2601AU
> RICHARD CROOKES CONSTRUCTIONS PTYDALEY RDACTONACT2601AU
> STOWE AUSTRALIA PTY LIMITEDELLERY CRESACTONACT2600AU
> MELBOURNE FACADES PTY LTDELLERY CRESACTONACT2601AU
> CONSTRUCTION CONTROL HOLDINGSSULLIVANS CREEK RDACTONACT2601AU
> QUATTRO BUILDING SERVICES PTY LTDSULLIVANS CREEK RDACTONACT2601AU
> IC FORMWORK SERVICES PTY LTDMORNINGTON ST AMANDA STAMAROOACT2914AU
> RENROW STEEL PTY LTDCOPPER CRESBEARDACT2620AU
> OPTIMUM BRICK BLOCKLAYINGCOPPER CRESBEARDACT2620AU
5.2 流程
对地址数据的处理已经被组合到单个块中,并被相应地处理。必须列出以下关键信息:
- 初始输入向量是 9964 个元素长,而距离向量是 49635666 个元素长。
- 距离向量是 378.7 Mb 大,而相似性矩阵是 758.7 Mb 大。
- 耗时 128.2 秒。请注意,这取决于处理器的计算能力。
# Start the clock
tic("\n\nTime to Process Data")# Calculate the lengths
vec_AddLengths <- str_length(vec_Addresses)# Calculate the distances
vec_AddDistances <- stringdistmatrix(vec_Addresses, method="osa")# Calculate the max lengths
vec_AddPairwiseMax <- combn(vec_AddLengths, 2, max, simplify=TRUE)# Normalise the distances
vec_AddNormalisedDistances <- vec_AddDistances/vec_AddPairwiseMax# Add object details to the output
str_Output <- c("vec_Addresses", "vec_AddLengths", "vec_AddDistances", "vec_AddPairwiseMax", "vec_AddNormalisedDistances") %>%
check_ObjectDetails() %>%
paste(sep="\n")# Create the similarity matrix
mat_AddSimilarityScore <- round(1-vec_AddNormalisedDistances, 2) %>% as.matrix()# Add matrix to output
str_Output %<>% paste(check_ObjectDetails(mat_AddSimilarityScore), sep="\n\n")# Tidy the matrix
mat_AddSimilarityScore[upper.tri(mat_AddSimilarityScore)] <- 0
mat_AddSimilarityScore[diag(mat_AddSimilarityScore)] <- 0# Re-add matrix to output
str_Output %<>% paste(check_ObjectDetails(mat_AddSimilarityScore), sep="\n\n")# Print the output
cat(str_Output)# Stop the clock and print the time taken
toc()> Name: vec_Addresses
> Type: character
> Dims: 1 x 9945
> Size: 1.2 Mb
>
> Name: vec_AddLengths
> Type: integer
> Dims: 1 x 9945
> Size: 38.9 Kb
>
> Name: vec_AddDistances
> Type: dist
> Dims: 1 x 49446540
> Size: 377.2 Mb
>
> Name: vec_AddPairwiseMax
> Type: array
> Dims: 1 x 49446540
> Size: 188.6 Mb
>
> Name: vec_AddNormalisedDistances
> Type: dist
> Dims: 1 x 49446540
> Size: 377.2 Mb
>
> Name: mat_AddSimilarityScore
> Type: matrix
> Dims: 9945 x 9945
> Size: 755.8 Mb
>
> Name: mat_AddSimilarityScore
> Type: matrix
> Dims: 9945 x 9945
> Size: 755.8 Mb
>
> Time to Process Data: 258.7 sec elapsed
结果,记录现在可以匹配了。请注意,匹配记录的数量是 2389(占总数的 24%)。
# Find matches
mat_AddMatchingRecords <- tlargest(matrix = mat_AddSimilarityScore
,threshold = 0.8
,print = TRUE
)> Selected threshold : 0.8
> Matching records : 2185
> Total records : 9945
> Matching percent : 0.2197# Find records
dat_AddMatchingRecords <- find_MatchingRecords(dataframe = dat_AddressesClean
,sim_matrix = mat_AddMatchingRecords
)
一旦识别出这些匹配的记录,就可以将它们返回。为简单起见,每个相似性得分的前 10 个匹配项已在下面的块中返回。
# View 0.99
dat_AddMatchingRecords %>%
filter(Score==0.99) %>%
head(10) %>%
print_MatchingRecords() %>%
cat()
> Score: 0.99
> Record 1: (Index 685) AUTOMATIC FIRE PROTECTION DESIGN THE NORTHERN RD BERKSHIRE PARK NSW 2765 AU
> Record 2: (Index 684) AUTOMATIC FIRE PROTECTION DESIGN THE NORTHERN RD BERKSHIRE PARK NSW 2756 AU
>
> Score: 0.99
> Record 1: (Index 1062) EJ CONSTRUCTIONS NSW PTY LIMITED ROBERTSON RD CENTENNTIAL PARK NSW 2021 AU
> Record 2: (Index 1061) EJ CONSTRUCTIONS NSW PTY LIMITED ROBERTSON RD CENTENNIAL PARK NSW 2021 AU
>
> Score: 0.99
> Record 1: (Index 2050) CPB DRAGADOS SAMSUNG JOINT VENTURE A COMMERCIAL RD KINGSGROVE NSW 2208 AU
> Record 2: (Index 2049) CPB DRAGADOS SAMSUNG JOINT VENTURE A COMMERCIAL RD KINGSFROVE NSW 2208 AU
>
> Score: 0.99
> Record 1: (Index 4593) CULLEN STEEL FABRICATIONS PTY LTD GATE WHARF HICKSON RD WALSH BAY NSW 2060 AU
> Record 2: (Index 4592) CULLEN STEEL FABRICATIONS PTY LTD GATE WHARF HICKSON RD WALSH BAY NSW 2065 AU
>
> Score: 0.99
> Record 1: (Index 5677) BM ALLIANCE COAL OPERATIONS PL CY HAY POINT OPERATIONS HAY POINT QLD 4740 AU
> Record 2: (Index 5676) BM ALLIANCE COAL OPERATIONS PL CY HAY POINT OPERATIONS HAY POINT QLD 4744 AU
当选择threshold=0.99时,算法几乎完全匹配,记录之间只有单个字符的差异。
# View 0.98
dat_AddMatchingRecords %>%
filter(Score==0.98) %>%
head(10) %>%
print_MatchingRecords() %>%
cat()
> Score: 0.98
> Record 1: (Index 25) KENNARDS HIRE PTY LIMITED OATLEY CT BELCONNEN ACT 2617 AU
> Record 2: (Index 24) KENNARDS HIRE PTY LIMITED OATLEY CT BELCONNEN ACT 2616 AU
>
> Score: 0.98
> Record 1: (Index 152) ABS FACADE PTY LTD SHEPPARD ST HUME ACT 2620 AU
> Record 2: (Index 149) ABS FACADE PTY LTD SHEPARD ST HUME ACT 2620 AU
>
> Score: 0.98
> Record 1: (Index 229) CRYSTAL POOLS PTY LTD DAVE MCINNES RD STROMLO ACT 2611 AU
> Record 2: (Index 228) CRYSTAL POOLS PTY LTD DAVE MCINNES RD STOMLO ACT 2611 AU
>
> Score: 0.98
> Record 1: (Index 410) RICHARD CROOKES CONSTRUCTIONS PTY PRINCESS HWY ARNCLIFFE NSW 2205 AU
> Record 2: (Index 403) RICHARD CROOKES CONSTRUCTIONS PTY PRINCES HWY ARNCLIFFE NSW 2205 AU
>
> Score: 0.98
> Record 1: (Index 875) ODK CONSTRUCTION PTY LTD PARRAMATTA RD BURWOOD NSW 2134 AU
> Record 2: (Index 478) ODK CONSTRUCTION PTY LTD PARRAMATTA RD B URWOOD NSW 2134 AU
>
> Score: 0.98
> Record 1: (Index 574) EODO PTY LTD HAVANNAH ST BATHURST NSW 2795 AU
> Record 2: (Index 570) EODO PTY LTD HAVANNAH ST BATHRUST NSW 2795 AU
>
> Score: 0.98
> Record 1: (Index 749) LIN BETTY BUILDING GROUP PTY LTD A OXFORD ST BONDI JUNCTION NSW 2026 AU
> Record 2: (Index 748) LIN BETTY BUILDING GROUP PTY LTD A OXFORD ST BONDI JUNCTION NSW 2022 AU
>
> Score: 0.98
> Record 1: (Index 927) LAING O ROURKE AUSTRALIA CARDIGAL LN CAMPERDOWN NSW 2050 AU
> Record 2: (Index 926) LAING OROURKE AUSTRALIA CARDIGAL LN CAMPERDOWN NSW 2050 AU
>
> Score: 0.98
> Record 1: (Index 1055) CJ SJ O KEEFFE BUILDING PTY LTD LOT NELSON ROAD CATTAI NSW 2756 AU
> Record 2: (Index 1054) CJ SJ OKEEFFE BUILDING PTY LTD LOT NELSON ROAD CATTAI NSW 2756 AU
>
> Score: 0.98
> Record 1: (Index 1083) METRO CHATSWOOD JHCPBG JV MOWBRAY RD CHATSWOOD NSW 2067 AU
> Record 2: (Index 1081) METRO CHATSWOOD JHCPBG JV MOWBRAY RD CHATSWOOD NSW 2057 AU
当选择threshold=0.98时,算法也几乎完全匹配,记录之间也只有单个字符的差异。
# View 0.8
dat_AddMatchingRecords %>%
filter(Score==0.8) %>%
head(10) %>%
print_MatchingRecords() %>%
cat()
> Score: 0.8
> Record 1: (Index 67) IC FORMWORK SERVICES PTY LTD CHALLIS ST DICKSON ACT 2602 AU
> Record 2: (Index 2) IC FORMWORK SERVICES PTY LTD CLUNIES RD ACTON ACT 2601 AU
>
> Score: 0.8
> Record 1: (Index 43) IC FORMWORK SERVICES PTY LTD CNR OF HOBART PL LONDON CCT CANBERRA ACT 2601 AU
> Record 2: (Index 36) IC FORMWORK SERVICES PTY LTD CNR CONSTITUTION AVE AND LONDON CCT CANBERRA ACT 2601 AU
>
> Score: 0.8
> Record 1: (Index 141) TS ANDREW TAYLOR SAWMILL CCT HUME ACT 2620 AU
> Record 2: (Index 139) TS ALEX GARNER SAWMILL CCT HUME ACT 2620 AU
>
> Score: 0.8
> Record 1: (Index 187) ACT INTERIORS HUDDART CT MITCHELL ACT 2911 AU
> Record 2: (Index 175) ACT INTERIORS BROOKS ST MITCHELL ACT 2911 AU
>
> Score: 0.8
> Record 1: (Index 292) TS DHAWAL NANDA BOURKE RD ALEXANDRIA NSW 2015 AU
> Record 2: (Index 270) TS GEORGE NAJJAR BOURKE RD ALEXANDRIA NSW 2015 AU
>
> Score: 0.8
> Record 1: (Index 295) SCHAI DARREN BOURKE RD ALEXANDRIA NSW 2015 AU
> Record 2: (Index 278) SMITH STEVEN BOURKE RD ALEXANDRIA NSW 2015 AU
>
> Score: 0.8
> Record 1: (Index 302) ABS FACADE PTY LTD BOURKE RD ALEXANDRIA NSW 2015 AU
> Record 2: (Index 281) DELTA PTY LTD BOURKE RD ALEXANDRIA NSW 2015 AU
>
> Score: 0.8
> Record 1: (Index 311) CPB CONTRACTORS PTY LTD BOURKE RD ALEXANDRIA NSW 2015 AU
> Record 2: (Index 297) FLEXEM CONSTRUCTION PTY LTD BOURKE RD ALEXANDRIA NSW 2015 AU
>
> Score: 0.8
> Record 1: (Index 300) CHAN PETER BOURKE RD ALEXANDRIA NSW 2015 AU
> Record 2: (Index 299) LOCANO PAULO BOURKE RD ALEXANDRIA NSW 2015 AU
>
> Score: 0.8
> Record 1: (Index 307) PETER CHAN BOURKE RD ALEXANDRIA NSW 2015 AU
> Record 2: (Index 305) PAULO LOCANO BOURKE RD ALEXANDRIA NSW 2015 AU
当选择threshold>0.9时,算法也几乎完全匹配,记录之间也只有单个字符的差异。然而,当选择threshold=0.8时,算法产生了错误匹配。例如:
- 记录
43和36实际上可能是匹配的副本,因为它们都是LONDON CCT上的IC FORMWORK SERVICES。 - 记录
141和139匹配了同一郊区同一街道上的不同商家。这是一个错误的匹配。 - 记录
187和175匹配了同一郊区不同街道上的相同企业。这是一个错误的匹配。
因此,建议在使用小于0.9的阈值时要谨慎。
6.结论
总之,模糊匹配能够以合理的准确度成功地识别重复项。当将具有单个字符差异的字符串匹配在一起时,这些字符串会得到近乎完美的匹配分数(>0.99)。但是当阈值设置为~0.8时,那么逻辑就开始匹配同一郊区同一街道的不同商家,或者同一郊区不同街道的同一商家等等。这对于实施来说是一个风险,因此必须仔细选择阈值。
此外,由于在处理期间创建了相当大的对象,适当的数据分段是适当的,以避免引起计算问题。
还要注意,数据输入验证总是比回顾性数据清理要好。在地址数据由外部方提供的情况下(如 EDI 连接),应实施此解决方案。如果数据被识别为>0.99的置信区间,那么自动修改数据是合理的;但是,如果是~0.8,那么最好将数据标记出来供员工查看。
7.参考
Awati 2019 年,“解决约翰·史密斯问题——通过 R 中的模糊匹配消除重复数据”,<https://eight 2 late . WordPress . com/2019/10/09/cracking-the-John-Smith-Problem-de duplication-data-via-fuzzy-matching-in-R/>。
维基百科 2019,‘余弦相似度’,【https://en.wikipedia.org/wiki/Cosine_similarity><。
维基百科 2019,‘编辑距离’,<https://en.wikipedia.org/wiki/Edit_distance>。
维基百科 2019,‘海明距离’,<https://en.wikipedia.org/wiki/Hamming_distance>。
维基百科 2019,‘雅各布索引’,<https://en.wikipedia.org/wiki/Jaccard_index>。
维基百科 2019,“贾罗-温克勒距离”,<https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance>。
维基百科 2019,‘莱文斯坦距离’,<https://en.wikipedia.org/wiki/Levenshtein_distance>。
维基百科 2019,'最长公共子串问题',<https://en . Wikipedia . org/wiki/Longest _ common _ substring _ problem>。
维基百科 2019,'最佳字符串对齐距离',<https://en . Wikipedia . org/wiki/damer au % E2 % 80% 93 levenshtein _ distance # Optimal _ string _ alignment _ distance>。
8.附言
鸣谢:本报告是在他人的帮助下完成的。致谢发送至:
- Kailash Awati 因为我使用了他的原始文章(解决 John Smith 问题)作为这篇文章的基础。
出版物:该报告也在以下网站发布:
- RPubs:RPubs/chrimaho/addressingthehohnsmithproblem
- GitHub:GitHub/chrimaho/addressingthehohnsmithproblem
- 中:中/chrimaho/addressingtheohnsmithproject
更改日志:本出版物于以下日期修改:
- 2020 年 7 月 4 日:原始出版日期。
作为大学数据科学家的兼职教师
对于数据科学家来说,教授大学课程可能是一项有益的兼职工作。

我在家乡的一所大学教深度学习课程。这份教学工作是我作为一家大型保险公司数据科学副总裁的主要工作之外的工作。大学的兼职讲师通常被称为兼职讲师。很多人问我关于我的兼职讲师职位的问题,所以我决定写一篇关于我为什么以及如何成为兼职讲师的文章。
每当你阅读一篇包含职业建议和反思的文章时,你必须始终考虑作者的情况与你的方向有多接近。这种考虑揭示了材料的哪些部分是适用的,哪些部分你应该完全忽略。人们选择加入大学的兼职教师队伍有很多原因。对我来说,教书完全是一项兼职工作。我并不寻求全职进入学术界,成为一名教授或讲师。相反,我成为了一名兼职教授,以提升我作为数据科学思想领袖的品牌,为招聘/联网提供可能性,也为我的沟通发展提供机会。还有其他附带的好处。我在从笔记本电脑到电影票的各种产品上都有教育折扣。我可以进入电子和实体的大学图书馆系统。电子图书馆让我能够访问出版商不开放的付费学术论文。作为一名数据科学家,对这类文档的访问已被无数次证明是有价值的。
成为一名助理需要什么样的资格
你有资格成为兼职讲师吗?成为兼职讲师所需的证书和经验因机构而异。在我工作过的三所不同的学校,我看到了各种各样的要求。最有可能的是,要进入任何级别的学术界,都需要某种程度的学位。在我本科学习的最后一部分,一所社区大学找到我,让我教一门 Java 课程。尽管我已经是一名软件工程师,但和他们交谈时我还是有点紧张,因为还有几个月我就要获得学士学位了。进一步说,当时我没有教学经验。尽管有这些保留意见,我最终还是在那所学校兼职教学了将近七年。学校认为我的用户组演示是教学经验,并重视我的行业经验。
社区大学可能会接受只有学士学位的候选人。大多数大学都会要求最低的硕士学位,至少以我的经验来看是这样的。获得硕士学位后,我申请成为一所大学的兼职教授。我喜欢为“大学”教书的想法,而这所学校恰好离我家很近。我教过几年技术编程课程。我离开的主要原因是结婚和看到我的优先权和空闲时间的转变。我一直喜欢教书,以后还会回来。
博士学位无疑是大学阶段的宝贵资格;然而,并不是所有的副教授都有博士学位。我有一个计算机科学的博士学位,来自我认为不错的学校,但它不是一流的大学。作为补充,我想说你的资格是你的教育、工作经验、教学经验、出版物和其他考虑因素的结合。你的 GitHub 活动、会议演示、YouTube 视频、MeetUp 体验等活动,以及 Medium 等博客文章也很重要。这些因素中没有一个能让你得到这份工作。这些的完整组合成为你作为数据科学家的品牌。没有人是这些方面的专家。然而,希望你的优势可以弥补你经验不足的地方。
为什么要成为兼职讲师
我选择成为兼职教员有很多原因。当你阅读关于数据科学职业建议的文章时,你会发现优秀的数据科学家应该从事许多活动。同样的建议也适用于有抱负的数据科学家。作为一名兼职讲师,我的工作已经成为一项核心活动,可以带来一些有价值的额外好处。我必须跟上深度学习的步伐,这样我的课程材料才是最新的、相关的。我把所有的课程资料都保存在 GitHub 上的 Jupyter 笔记本里。我的职业库现在有近 2K GitHub 粉丝和 1.3K 星星。我以混合形式讲授课程,也就是说,我通过课堂会议、预先录制的视频和缩放会议的组合来提供指导。我预先录制的视频在 YouTube 上变得很受欢迎,导致一个频道目前拥有 24K 订户。就个人而言,如果我将这些项目作为独立的不相关的活动来追求,我将没有时间来完成它们。我并没有打算成为 YouTuber 或社交媒体的影响者。
为一门课程会给你的生活增加的工作量做好准备。在学校每周都有时间在课堂上讲课。准备课程材料和作业需要时间。批改作业和回答学生的问题也需要相当长的时间。然而,对我来说,这些都有助于我作为一名数据科学家的价值。向学生解释复杂的技术有助于我更好地理解技术并磨练我的沟通技巧。准备课程材料迫使我学习任何高级数据科学家都应该学习的最新技术。在学生继续或开始职业生涯时,与学生见面提供了有价值的社交活动。我经常从我的学生中雇佣实习生,偶尔也会雇佣他们为我的雇主做全职工作。
金钱是一种利益。许多金融作家谈到了“旁门左道”的价值。兼职教师的工作确实产生了第二收入来源。学校会支付给你的金额因你的证书、学校和地理位置而异。像 Glassdoor 这样的网站会给你一个合理准确的薪水预估。
如何成为兼职讲师
既然我已经解释了你为什么想成为一名兼职讲师,让我们来谈谈如何真正成为一名兼职讲师。如果你没有教学经验,我建议在你选择的领域尝试一两次 MeetUp。第一,注意观察他人,学习新事物。想出一个可能成为你第一堂课的话题。在聚会上演讲成为你最初的教学经验。用这一全新的宝贵演讲体验更新您的 LinkedIn 个人资料。此外,确保你的 LinkedIn 个人资料有一张好照片,并列出相关的工作经历。
当你准备尝试找一份兼职时,选择几所离你近的大学。找到你的目标部门。学院由以院长为首的学校或系组成。无论是直接的还是间接的,在院长的领导下,将会有部门领导或项目主管,他们通常是个人的任务,雇佣兼职讲师。这些是你要接触的人。
希望项目总监在 LinkedIn 上。如果是的话,这是最初联系的好方法。LinkedIn 可以让主管看到你的资历和经验。提出初次联系请求,并提及您对课程有想法,并且有兴趣讨论附加机会。一些学者在 LinkedIn 上一点也不活跃。如果主管在 LinkedIn 上不理你,那就试着发邮件。如果主任在这两方面都忽略了你,那就去下一所学校。
对于你最初的交流,无论是电子邮件还是 LinkedIn 信息(在你联系上之后),总是提出一个你可能想教的课程的想法。在这一点上,这个提议只不过是大学在目录中可能有的描述水平。当然,浏览他们的课程目录,并确保你没有提出一个重复的课程。主任很可能有一个班级,他们正在寻找一个新的兼职讲师。然而,提出一个课程想法表明你是一个思想领袖,可能会激起主任的兴趣。
我已经在我现在的大学工作了三年,我发现辅助教学是一项有益的活动。我发现辅助教学与我的主要职业非常契合。对学生来说,与同行业的人交流是有益的。如果你正在寻找一种方法来提高你作为一名数据科学家的品牌和思想领导力,那么辅助教学可能非常适合你的职业生涯。
针对泊松回归中的过度离散进行调整
广义线性模型
消除泊松模型中显著系数的假阳性检测及其在 r。

蒂莫·沃尔茨在 Unsplash 上的照片
T 当我们想要对每单位时间或空间的平均发生次数进行建模时,泊松回归模型自然而然地出现了。比如罕见癌症的发病率,十字路口汽车穿越的次数,或者地震的次数。
泊松分布的一个特征是均值等于方差。然而,过度分散或欠分散分别发生在方差大于或小于均值的泊松模型中。实际上,在数据量有限的情况下,过度分散会更频繁地发生。
过度分散问题会影响模型的解释。为了避免对系数的错误估计,有必要解决这个问题。
在这篇文章中,我将讨论一些基本的方法来调整泊松回归模型中的过度分散现象。实现将用 R 代码展示。希望这篇文章有帮助。
假设我们想要使用预测器 xi 的向量来模拟计数响应易。我们知道,响应变量 Yi 遵循参数为μi 的泊松分布

易服从泊松分布
其中概率函数是

泊松 PMF
对数连接函数用于连接预测值 Xi 和泊松参数μi 的线性组合

泊松回归模型。
让我们用《T21》一书中介绍的例子建立一个简单的模型。
## R code
library(faraway)
data(gala)
gala = gala[,-2]
pois_mod = glm(Species ~ .,family=poisson,gala)
summary(pois_mod)
这是泊松模型的总结。
Call:
glm(formula = Species ~ ., family = poisson, data = gala)
Deviance Residuals:
Min 1Q Median 3Q Max
-8.2752 -4.4966 -0.9443 1.9168 10.1849
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 3.155e+00 5.175e-02 60.963 < 2e-16 ***
Area -5.799e-04 2.627e-05 -22.074 < 2e-16 ***
Elevation 3.541e-03 8.741e-05 40.507 < 2e-16 ***
Nearest 8.826e-03 1.821e-03 4.846 1.26e-06 ***
Scruz -5.709e-03 6.256e-04 -9.126 < 2e-16 ***
Adjacent -6.630e-04 2.933e-05 -22.608 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for poisson family taken to be 1)
Null deviance: 3510.73 on 29 degrees of freedom
Residual deviance: 716.85 on 24 degrees of freedom
AIC: 889.68
Number of Fisher Scoring iterations: 5
不要被超级显著的系数所迷惑。那些漂亮的 p 值正是过度分散问题的后果。我们可以从视觉上或数量上检查过度分散。
让我们先画出相对于平均值的估计方差。
## R code
plot(log(fitted(pois_mod)),log((gala$Species-fitted(pois_mod))^2),xlab=expression(hat(mu)),ylab=expression((y-hat(mu))^2),pch=20,col="blue")abline(0,1) ## 'varianc = mean' line

过度分散诊断
我们可以看到,大多数方差大于平均值,这是过度分散的警告。
定量地,可以使用皮尔逊卡方统计和自由度来估计色散参数 φ 。

离差参数的估计
当φ大于 1 时,为过度离散。为了手动计算参数,我们使用下面的代码。
## R code
dp = sum(residuals(pois_mod,type ="pearson")^2)/pois_mod$df.residual
dp
这给了我们 31.74914,并证实了这个简单的泊松模型有过度分散的问题。
或者,我们可以直接在拟合的模型上应用显著性检验来检查过度分散。
## R code
library(AER)
dispersiontest(pois_mod)
这产生了,
Overdispersion test
data: pois_mod
z = 3.3759, p-value = 0.0003678
alternative hypothesis: true dispersion is greater than 1
sample estimates:
dispersion
25.39503
该过度分散测试报告了模型中过度分散问题的重要性。
我们可以检查过度分散对系数估计的影响程度。
## R code
summary(pois_mod,dispersion = dp)
这产生了,
Call:
glm(formula = Species ~ ., family = poisson, data = gala)
Deviance Residuals:
Min 1Q Median 3Q Max
-8.2752 -4.4966 -0.9443 1.9168 10.1849
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 3.1548079 0.2915897 10.819 < 2e-16 ***
Area -0.0005799 0.0001480 -3.918 8.95e-05 ***
Elevation 0.0035406 0.0004925 7.189 6.53e-13 ***
Nearest 0.0088256 0.0102621 0.860 0.390
Scruz -0.0057094 0.0035251 -1.620 0.105
Adjacent -0.0006630 0.0001653 -4.012 6.01e-05 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for poisson family taken to be 31.74914)
Null deviance: 3510.73 on 29 degrees of freedom
Residual deviance: 716.85 on 24 degrees of freedom
AIC: 889.68
Number of Fisher Scoring iterations: 5
现在,大约一半的预测变得无关紧要,这改变了整个模型的解释。
好吧,让我们用下面两种方法来解决这个问题。
允许离差估计
调整过度分散的简单方法与估计模型中的分散参数一样简单。这可以通过 r 中的准族来完成。
qpoi_mod = glm(Species ~ .,family=quasipoisson, gala)
summary(qpoi_mod)
这产生了,
Call:
glm(formula = Species ~ ., family = quasipoisson, data = gala)
Deviance Residuals:
Min 1Q Median 3Q Max
-8.2752 -4.4966 -0.9443 1.9168 10.1849
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.1548079 0.2915901 10.819 1.03e-10 ***
Area -0.0005799 0.0001480 -3.918 0.000649 ***
Elevation 0.0035406 0.0004925 7.189 1.98e-07 ***
Nearest 0.0088256 0.0102622 0.860 0.398292
Scruz -0.0057094 0.0035251 -1.620 0.118380
Adjacent -0.0006630 0.0001653 -4.012 0.000511 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for quasipoisson family taken to be 31.74921)
Null deviance: 3510.73 on 29 degrees of freedom
Residual deviance: 716.85 on 24 degrees of freedom
AIC: NA
Number of Fisher Scoring iterations: 5
我们可以看到,色散参数估计为 31.74921,这与我们前面提到的手动计算非常接近。这个过程告诉我们,只有三个预测系数是有意义的。
用负二项式代替泊松
解决模型中过度分散的另一种方法是将我们的分布假设改为负二项式,其中的方差大于均值。
让我们在 r 中实现负二项模型。
## R code
library(MASS)
nb_mod = glm.nb(Species ~ .,data = gala)
summary(nb_mod)
这产生了,
Call:
glm.nb(formula = Species ~ ., data = gala, init.theta = 1.674602286,
link = log)
Deviance Residuals:
Min 1Q Median 3Q Max
-2.1344 -0.8597 -0.1476 0.4576 1.8416
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 2.9065247 0.2510344 11.578 < 2e-16 ***
Area -0.0006336 0.0002865 -2.211 0.027009 *
Elevation 0.0038551 0.0006916 5.574 2.49e-08 ***
Nearest 0.0028264 0.0136618 0.207 0.836100
Scruz -0.0018976 0.0028096 -0.675 0.499426
Adjacent -0.0007605 0.0002278 -3.338 0.000842 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for Negative Binomial(1.6746) family taken to be 1)
Null deviance: 88.431 on 29 degrees of freedom
Residual deviance: 33.196 on 24 degrees of freedom
AIC: 304.22
Number of Fisher Scoring iterations: 1
Theta: 1.675
Std. Err.: 0.442
2 x log-likelihood: -290.223
它更符合数据,因为偏离度与自由度之比仅略大于 1。
结论
答:过度分散会影响泊松模型的解释。
B. 为了避免我们模型中的过度分散问题,我们可以使用一个拟族来估计分散参数。
C. 我们也可以用负二项式代替泊松模型。
参考资料:
远方,Julian J. 用 R 扩展线性模型:广义线性、混合效应和非参数回归模型。CRC 出版社,2016。

由 Peter Scherbatykh 在 Unsplash 上拍摄
仓库:具有真实异常的异常检测数据集
持续更新的异常数据集集合
我创建了一个 Github 存储库,以提供一个持续更新的流行真实数据集集合,用于文献中的异常检测。请在下面找到指向存储库的链接。
在这个库中,我们提供了一个不断更新的用于异常的流行真实世界数据集的集合…
github.com](https://github.com/GuansongPang/anomaly-detection-datasets)
异常检测发展的一个主要障碍是缺乏具有真实异常的真实世界数据集。尽管在 UCI 机器学习库和/或 Libsvm 数据集中有许多相关的公开可用数据集,但我们可能经常需要投入大量时间来使公开可用数据集为我们的异常检测模型做好准备。创建这个存储库就是为了解决这些问题。它将专注于现成的数据集,即不需要任何进一步的数据预处理,并不断用我或其他研究人员预处理的数据集更新它。
现在存储库中可用的数据集来自不同的领域,如信用卡欺诈检测、入侵检测、疾病检测等。这些数据集的基本统计数据可以在下面找到。

Pang,g .,Shen,c .,& van den Hengel,A. (2019 年 7 月)使用的数据集。基于偏差网络的深部异常探测。《第 25 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集》(第 353–362 页)。请参阅本文中对这些数据集的详细介绍以及其中的源链接。

庞,曹,陈(2016 年 1 月)使用的数据集。复杂分类数据中异常值检测的特征值耦合模型。在 IJCAI 国际人工智能联合会议上。和其他几篇论文。请参阅本文中对这些数据集的详细介绍以及其中的源链接。
带有可访问链接的数据集列表也可在以下调查报告中找到:
[## 用于异常检测的深度学习:综述
异常检测,也称为离群点检测,已经成为各种研究中一个持久而活跃的研究领域
arxiv.org](https://arxiv.org/abs/2007.02500)
高级 AI 快到了,快跑。
我们应该在多大程度上拥抱有意识机器的发展?

尽管人工智能已经在全球广泛使用,但它的发展应该得到专业和谨慎的处理,因为我们仍然不知道有意识的机器会对人类产生什么影响。该领域的领先研究人员警告其潜在后果,史蒂芬·霍金教授声称,超级智能机器可能会导致人类的末日。
人工智能是计算机系统的理论和发展,能够执行通常需要人类智能的任务。近年来,由于其快速的发展和广泛的应用,以及公众人物如埃隆·马斯克和比尔·盖茨对该主题的关注,它已经获得了主流媒体的关注。事实证明,这是计算机科学家和哲学家之间争论的话题,其中一些人表示,超级智能人工智能将是我们创造的最后一件东西。
这份报告评估了来自杰出研究人员和学术报告的证据、研究和陈述,并得出结论认为,应该允许开发人工智能,但只能在严格到适度的监督和监管下进行。它致力于讨论研究问题:超级智能人工智能是否对人类构成生存威胁,创造有意识的机器是一个好主意吗,创造有意识的机器是否不道德?
创造有意识的机器对人类来说是个好主意吗?
人工智能的种类—
人工智能可以分解为三个 categories⁴.人工狭义智能(ANI)是一种低水平的智能,ANI 可以执行复杂的任务,但不能理解它为什么要这样做,它不会在有意识的层面上思考,例如 Siri,Alexa。人工通用智能(AGI)是有意识的,它可以在与人类相同的水平上思考,有自我意识,可以理解它是一台机器。AGI 还不存在。最后,人工超级智能(ASI)是比人类更高级的机器智能,它也尚不存在,但它能够解决超出我们理解的问题。
时间框架—
由于 AGI 和阿西还不存在,这是一个猜测的主题,他们是如何迫在眉睫,因此我们需要如何关注。field⁵的一项专家调查发现,受访者的中位数估计,到 2040 年,AGI 将有二分之一的可能性被创造出来,到 2075 年,这一比例将上升至十分之九。他们还预测,不到 30 年后,ASI 也将步其后尘。ASI 对人类来说变成“坏”或“极其坏”的可能性估计为三分之一。
虽然该调查很有见地,并为我们提供了一个工作时间框架,但应谨慎依赖,因为该调查报告并未提及这些专家是谁,以及被归类为专家的标准是什么。
好处和威胁—
据了解,有了意识,自主的决定和意见就形成了。这意味着有意识的机器可能有与其创造者不一致的目标。它们的处理时间比人快数百万倍,很难抵御。来自威斯康星大学麦迪逊分校的一份报告指出,创造一个人工智能可能导致人工智能武装 race⁶.AGI 将允许自主武器系统,它可以很快变得非常复杂,当机器从 AGI 转换到 ASI 时,我们可能会失去对它的控制。以及试图获得该技术的敌对国家。这可以被归类为一种生存威胁,因为人类对一台武装的超级智能机器无能为力。在同一篇论文中,进行了一项调查,48%的受访者同意“社会应该优先考虑将人工智能的潜在风险降至最低”。虽然现在的回应有点过时,观点可能也有所改变,但这反映了一个事实,即人们对开发有意识的机器存在担忧。
仅仅因为有意识的机器对人类来说是一大进步,它带来了威胁,这并不意味着它根本不应该被创造出来。AGI 全球协作和政府法规等解决方案可以到位,以确保其得到负责任的发展。让-马克·里克利博士声称,AGI 的好处将是巨大的,它可以在防止欺诈和发现网络攻击以及国防和 anti-terrorism⁷.等活动中发挥重要作用虽然,里克利的想法很容易引起争议,因为 AGI 也可以帮助网络攻击和恐怖主义。
创造人工意识对机器公平吗?
当建造有意识的机器时,伦理是一件需要考虑的重要事情,因为它本质上是在创造生命。有太多限制的意识就像关在笼子里的动物。此外,无情地强迫一个意识去执行一个又一个的任务会让人想起我们现在回想起来并不愉快的历史事件,例如奴隶制。
为了防止历史重演,需要就对 AGI 能做什么和不能做什么制定指导方针。博斯特罗姆提出了一个被认为是 ethical⁸的总清单,随着伦理不可避免的转变,这个清单可以更新。AI 也应该遵守这个主列表。虽然这是一个很好的建议,但可能被认为是不现实的。Bostrom 只提出了一个解决方案,但没有说明如何实施。假设每个人都会遵守它是不合理的。
最后
“制造一台有意识的机器对人类来说是个好主意吗?”这个问题似乎没有明确的答案,但如果不付诸行动,它还是会继续下去。因此,由于人工意识是如此不朽和改变世界,似乎最好继续创造它,但要有严格的规定来确保它安全和负责任地发展。
AGI 很可能是对人类的生存威胁,赋予机器意识也可能是不道德的,如果不是出于责任感的话。确实有证据表明,AGIs 的发明会给人类带来许多好处,但这并不意味着我们可以忽视威胁,这些威胁可能更重要。
在回答“创造人工意识对机器公平吗?”,就看谁在控制它了。这就是监管如此重要的原因,也是如此大规模的技术进步不能向世界隐瞒的原因。
技术的演变是不可避免的,但这并不意味着人类在这样做的时候不应该是道德的、安全的和前瞻性的,特别是在先进的人工智能的情况下。
www.linkedin.com/in/joe-drury18
参考
[1]塞兰·琼斯博士,2014 年。斯蒂芬·霍金警告人工智能可能会终结人类。英国广播公司新闻,2014 年第 2 版
[2]词典|英语。(2019).人工智能| Lexico 对人工智能的定义。【在线】见:https://www . lexico . com/en/definition/artificial _ intelligence【2019 年 10 月 23 日访问】。
[3]n .博斯特罗姆,2003 年。高级人工智能中的伦理问题。科幻小说与哲学:从时间旅行到超级智慧,第 241 页
[4]特威迪,M. (2017)。3 种类型的人工智能:窄,一般,和超级人工智能。[在线]
[5]米勒,V.C .和 n .博斯特罗姆,2016 年。人工智能的未来发展:专家意见调查。《人工智能的基本问题》(第 555-572 页)。斯普林格,查姆。
[6] Ramamoorthy,a .和 Yampolskiy,r .,2018 年。超越疯狂?人工智能竞赛。国际电联 J,1,第 1-8 页。
[7] Rickli,J.M .,3.2 评估人工智能的风险。
[8]n . Bostrom 和 e . Yudkowsky,2014 年。人工智能的伦理。《剑桥人工智能手册》,316,第 334 页
代码机器人。可在:https://code bots . com/artificial-intelligence/the-3-types-of-ai-is the-third-even-possible【2019 年 11 月 12 日访问】。
https://unsplash.com/photos/YKW0JjP7rlU
使用全息视图在 Python 中实现高级数据可视化
HoloViews 将数据和绘图升级为高质量的注释和可视化。本文通过一个简化的群组分析展示了 Python HoloViews 包,该分析使用了关于公司不断发展的客户群的模拟数据。读者应该对 Python 和 pandas 有一个基本到中级的了解。

来源:http://blog.holoviews.org/release_1.10.html
全息视图概述
HoloViews 是一个开源包,它用最少的代码和努力产生高质量的交互式可视化。项目页面可以在这里找到这里以及许多例子来理解软件包的功能。相对于遗留选项(Matplotlib、Seaborn 等),我对易用性和性能非常满意。
断代分析
在解决真实世界的数据分析练习时,探索和学习新的包更有吸引力。本文通过对一个简化的 SaaS 企业的队列分析,来确定在客户群中是否有任何新兴趋势。这种分析在许多情况下是有用的,包括准备和验证顶线预测,以及评估产品供应或定价的最近变化的影响。本例中的群组将被定义为在给定月份首次出现的所有用户。这个练习的目的是检查新业务的组合如何随着时间的推移而变化,以及组合的变化对保留意味着什么。在这种情况下,mix 指的是产品等级和订阅持续时间,在其他情况下,它可以是任何可用的分类字段。
数据的描述
分析所依据的数据被模拟以复制在多个公司中观察到的模式。
有两个文件:
- mrr.csv 包含每个订阅在 2.5 年期间的每月收入。没有左审查。
- user.csv 包含用户 id、订阅 id、产品等级和订阅期限
一个用户可能有多个订阅,他们可以交换产品等级和订阅期限。为简单起见,保留是基于订阅而不是基于用户来计算的。
到代码
分析从进口开始。显示这一点是为了确保读者已经安装了所有的依赖包。请注意 hvplot 包是建立在 HoloViews 上的,它有一个方便的 API 来绘制熊猫图,这需要从 HoloViews 中单独安装。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
import hvplot.pandas
import holoviews as hv
from holoviews import opts
hv.extension('bokeh')
附注:HoloViews 中日期时间格式的默认行为是打印精确到纳秒的日期/时间。对于初学者来说,控制这种行为的文档通常很难找到,也不完全清楚。这个格式化问题可以通过创建一个 DatetimeTickFormatter 对象并根据需要将其传递给图形来解决。
from bokeh.models.formatters import DatetimeTickFormatter
dtf = DatetimeTickFormatter( days = '%m-%Y', months = '%m-%Y' , years = '%m-%Y')
整形数据
在绘制数据之前,需要将其转换为内容,使图形有意义,并以适当的格式传递给 HoloVeiws。一些基本的熊猫操作被排除在这篇文章之外。完整的文件可以在 github 找到。
创建群组是群组分析的第一步,有许多方法可以进行这种计算。给定输入数据的格式,这里应用以下步骤:
### Calculate start period of the subscription## #1 Create cohorts based on the first observation of a month with a positive mrr value
cohort = (mrr > 0).idxmax( axis = 1).rename('cohort')## #2 Add the cohort date to the index
tenure = mrr.join( cohort ).set_index( 'cohort', append = True).stack()
tenure = tenure.reset_index( ).rename( columns = {'level_2':'date',## #3 Calculate the number of periods (months) from the cohort date to the mrr date
0:'revenue'} )
tenure['periods'] = np.round( (tenure['date'] - tenure['cohort']) / np.timedelta64(1, 'M') ,0).astype(int)
1 中的代码将数据帧转换为二进制变量的值,当一个月有正收入时,这些值为真。然后应用 idxmax 提取最大值第一次出现的列标题,这将是收入为正数的第一个日期。结果是一个与 mrr 具有相同索引的序列,该序列作为 mrr 的#2 中的二级索引被附加,堆叠(该操作通过将列标题(在本例中为每月日期)转换为值字段来解除数据透视)并保存为一个名为“保有权”的新数据帧。步骤#3 计算群组月份和当前月份之间经过的周期数(在本例中为月数)。

结果数据帧
在群组分析的 EDA 阶段,这两条曲线通常非常有用,可以对客户保持率有一个总体的了解。两者都表示相对于每个客户活跃的第一个周期,在给定时间点剩余的业务的百分比。一个使用客户作为分子和分母,另一个使用收入。这些计算分为两部分,如下所示:
## #1 Calculate revenue and subs count by cohort by month
gb = tenure.groupby( [ pd.Grouper( key ='cohort' , freq = 'M') , 'periods'])
rev_cohorts = gb['revenue'].sum().unstack()
count_cohorts = gb['sub_id'].nunique().unstack()## #2 turn them into a percentage relative to the first month
scaled_revenue_cohorts = rev_cohorts.apply( lambda x : x/x[0] ,axis = 1)
scaled_count_cohorts = count_cohorts.apply( lambda x : x/x[0] ,axis = 1)
1 中的计算为每个有观察值的周期中的每月客户群计算总收入和客户的唯一计数,unstack 命令将周期转换为列标题,这对使用 hvplot 绘图很有用。#2 中的计算利用了新的数据形状,并应用 lambda 函数将每个期间的值(收入或客户数)除以第一个月观察到的值。

视觉化
对 HoloViews 的 hvplot 扩展提供了一种非常快速的方式来从 pandas 对象生成交互式可视化,这有助于 EDA。以下代码遵循与 matplotlib 相同的 API 格式,可以快速生成用于探索的线图。
### Quick hvplot of both dataframes
p1 = scaled_revenue_cohorts[scaled_revenue_cohorts>0].T.hvplot( figsize = [11,7], legend=False , title = 'Revenue')
p2 = scaled_count_cohorts[scaled_count_cohorts>0].T.hvplot(figsize = [11,7], legend=False , title = 'Logo Count')### Add the graphs together to display as one output
(p1 + p2).cols(1)

有两件事在全息视图中比在绘图包中更容易实现。工具提示允许用户以交互方式浏览数据,并且是自动生成的。将图形添加到单个可视化中的语法比从 matplotlib 调用 axes 对象更容易。
这些图表已经提供了大量信息,有助于指导接下来的分析。首先,请注意,这里混合了不同的订阅长度。最好分别分析不同持续时间选项的保留情况,因为显然一年期订阅与一个月期订阅的情况不同。其次,保留曲线的轮廓正在改变。较短的线是最近的线,因为可用的数据很少。这些有更多的曲率比旧的,而且他们似乎有一个较低的保留百分比。稍后,本文将展示一种更好的方法来演示这种模式。在此之前,我们将探索基础订阅基础的变化。
当新业务组合发生变化时,保留模式通常会开始改变。由于新的营销活动、产品供应、期限选择、地区或人口特征等诸多因素,新业务的组合可能会发生变化。在该数据集中,只有持续时间和订阅层可用作分类特征。评估任何分类特征的组合如何随时间变化的一个好方法是将它们绘制成两个堆叠的条形图,显示总量和相对百分比。
为了生成下一组图表,需要对数据进行整形,按层和持续时间划分群组。
## #1 Create product duration cohorts
gb = tenure.groupby( ['sub_product','sub_duration','cohort', 'subs_id','periods'])## #2 Divide each periods user count (observations with revenue > 0) by the month 0 count
cohorts_scaled = gb['revenue'].sum().unstack().groupby(level=[0,1,2]).apply( lambda x : (x>0).sum()/(x[0]>0).sum())
有了新的群组数据,创建条形图相当容易,但需要几行:
## #1
mix = cohorts[0].rename('count').reset_index()
mix = mix.set_index(['cohort','sub_product','sub_duration'] )
mix = mix.sort_index()## #2
abs_bars = hv.Bars( mix )
abs_bars.opts( stacked = True, xrotation = 45 , width = 700 , height = 400 , xaxis= None , ylabel = 'Conversions')## #3
hund_bars = hv.Bars( mix/mix.groupby( level =0 ).sum() )
hund_bars.opts( stacked = True, xrotation = 45 , width = 700 , height = 400 , xformatter = dtf, ylabel = 'Relative %')layout = (abs_bars + hund_bars).cols(1)
layout.opts(shared_axes=False)
1 下的代码创建了一个多索引序列,可以传递给 HoloViews bars 类。Holoviews 需要平面数据,而 hvplot 可以平稳地处理表格数据。的。HoloViews 中的 opts()方法让开发人员可以非常详细地控制可视化的几乎每个部分。

条形图显示,产品层级没有随着时间的推移而发生任何明显的变化。然而,持续重复这一步骤显示出新业务组合的显著变化。

一个月的订阅完全取代了六个月的订阅。这一结果几乎肯定会导致保留曲线的整体移动。为了证明这一点,我们将按产品和持续时间绘制保留曲线。
与全息地图建立互动
之前展示的情节很容易制作,也很吸引人,但是在交互性方面有所限制。HoloViews 的一个很好的特性是能够产生类似仪表盘的可视化效果。此外,它还以 html 格式生成这些可视化效果,以便它们可以嵌入到网页中。这些特性比简单地将数据帧传递给 hvplot 需要更多的代码。这些功能通过两种可视化方式进行了演示,有助于识别保留趋势。
在生成可视化之前,构建一些助手函数将使代码更具可读性。在之前显示的群组曲线图中,很难看出哪条线属于哪个年份。为了使这一点更清楚,人们可以指定一种随着年龄增长而褪色的颜色。下面的代码块将线条涂成蓝色,并且随着时间的推移,蓝色逐渐变成白色/灰色。
def gen_cohort_plot( cohort ):
cohort = cohort[ cohort > 0]
## #1 Create curves with hvplot
plot = cohort.T.hvplot( width=700, height=350, legend=False )
d_min = 2015 REPLACE
d_max = 2017 REPLACE
## #2 loop through curves to adjust the formatting
for item in plot.items():
date , curve = item
year = pd.to_datetime( date ).year
## #3 interpolate the blue scale bounded between .2 and .8
c = plt.cm.Blues( .8* (year - d_min ) / ( d_max - d_min ) + .2)
curve.opts( hv.opts.Curve( color=c ))
return plot
这个函数看起来很吓人,但是逻辑非常简单。在#1 中,hvplot 用于生成与前面所示相同的曲线。这些曲线在#2 中循环,而#3 将相对于最小和最大群组年的群组年线性插值到 matplotlib 的蓝色地图上。
## #1 loop through possible pairs of product and duration
## pd_curve is a helper function that just filters data before
## being passed to gen_cohort_plot()
curve_dict_2D = {(d,p):pd_curve(p,d, cohorts_scaled) for p in products for d in durations }## #2 create hmap visualizations
hmap = hv.HoloMap(curve_dict_2D , kdims=['Duration', 'Product'])## generate a plot of the number of conversions
conv_curve_dict_2D = {(d,p):conversion_plot( p , d , cohorts ) for p in products for d in durations }
conv_hmap = hv.HoloMap(conv_curve_dict_2D, kdims=['Duration', 'Product'])## generate a plot of the average price for a cohorts first month
asp_curve_dict_2D = {(d,p):asp_plot(p,d, cohort_asp) for p in products for d in durations }
asp_hmap = hv.HoloMap(asp_curve_dict_2D, kdims=['Duration', 'Product'])(hmap +conv_hmap + asp_hmap ).cols(1)
曲线存储在字典中,可以在不同的布局选项中传递。这里展示的是全息地图。全息地图根据显示的字典键生成下拉选择器:

线条越黑,群组越新。点击不同的组合后,可以清楚地看到一个月订阅的保留情况更差。我们之前已经观察到,一个月订阅在新客户群中所占的比例越来越大。
虽然给线条涂上不同的颜色有助于显示群组的年龄,但热图提供了一种显示信息的替代方法,使某些趋势更容易识别。但是,如果向不熟悉这种格式的各方展示热图,热图确实需要比线图更多的解释。本教程最后将讨论如何生成和解释热图视图。
创建辅助函数是为了格式化图形,并使代码更易于管理。
def heatmap_product_duration( product , duration , data = cohorts_scaled):
## #1 filter the data for the product duration pair
idx = pd.IndexSlice
data = data.loc[ idx[product, duration, :] , :].reset_index( level = [0,1], drop = True)
data = data[data>0]
data = data.stack().rename( 'retention').reset_index()
data = data[ data['retention'] > 0]
data.columns = ['cohort','tenure','retention']
## #2 Create a heatmap
hm = hv.HeatMap(data , kdims=['tenure','cohort']).sort()
## #3 Formatting options note the addition of the hover tool
hm.opts( opts.HeatMap( width = 500 , height = 500 ,colorbar = True, yformatter = dtf , xrotation = 90 ,cmap = 'RdYlGn' ,tools=['hover'], toolbar='above'))
return hmdef left_conv_bar( product , duration, data = cohorts ):
## #1 filter the data for the product duration pair
idx = pd.IndexSlice
data = data.loc[ idx[product, duration, :] , :].reset_index( level = [0,1], drop = True)
data = data.loc[:,0].rename( 'conversions').reset_index()
## #2 similar to the previous bar charts, note the invert_axes option
bar = hv.Bars( data ).opts( invert_axes=True , height = 500 , width = 200 , color = 'Green' , yaxis = None, invert_xaxis=True )
return bar
在构建了 helper 函数之后,以类似于之前的方式,代码循环遍历产品持续时间对,并创建一个字典来存储可视化,然后最终将它们传递给全息地图。
heatmap_curve_dict_2D = {(d,p):heatmap_product_duration(p,d) for p in products for d in durations }
heatmap_hmap = hv.HoloMap(heatmap_curve_dict_2D, kdims=['Duration', 'Product'])
left_bar_curve_dict_2D = {(d,p):left_conv_bar(p,d) for p in products for d in durations }
left_bar_hmap = hv.HoloMap(left_bar_curve_dict_2D, kdims=['Duration', 'Product'])
layout = (left_bar_hmap + heatmap_hmap ).opts( shared_axes = True)
layout

此视图通过观察一个月订阅的所有层在 2018 年 10 月后从早期任期的绿色转变为黄色,显示了不同群组的老化情况。注意,这种偏移也对应于转换次数开始增加的时期。这种现象在不断发展的企业中相当普遍。增加营销支出或改变产品/价格将吸引更多的新客户,但增加的新客户不一定与以前的客户群相同。
HoloViews 允许分析师产生高质量的可视化,通过高度定制来加速产生有意义的见解的时间。谢谢你读到这里,我希望你能去图书馆看看。
fastai2 的高级数据加载器
快速介绍
优雅的 fastai2 方法创建超出通常的输入-目标对的数据加载器——一个使用 Kaggle Bengali 的例子。人工智能数据
在深度学习项目中,在开始训练任何模型之前,关键的一步是要有一个数据加载器,能够为模型提供批量数据,并执行图像放大等操作。在这个故事中,我将展示一个用于孟加拉语的数据加载器。AI Kaggle 竞赛可以使用 fastai 创建,只需 12 行干净的代码。贯穿全文,当提到 fastai 时,我指的是库的最新版本( fastai2 )。

作者照片
为什么是 fastai?
引用他们的学术论文:
“fastai 是围绕两个主要设计目标组织的:平易近人和快速高效,同时也是高度可黑客化和可配置的。其他库倾向于在简洁性和开发速度,或者灵活性和表达性之间做出选择,但不能两者都选。我们希望获得 Keras 的清晰度和开发速度,以及 PyTorch 的可定制性。”
fastai 的这一核心特征使它能够为更广泛的受众所使用,同时也是有经验的从业者和研究人员的优秀工具。fastai 高级 API 包括两个组件:数据块和学习器。这个故事着重于数据块组件,我发现这是一个优雅的解决方案,可以轻松地创建一个具有一个输入和三个目标的数据加载器——这是 Bengali 所需要的。人工智能竞赛。
孟加拉语。AI 比赛数据
用孟加拉语。人工智能竞赛给我们一组手写的字素,目标是用对应于字素不同组成部分的三个分类标签对每个字素进行分类。图像名称和各自的标签存储在一个 CSV 文件中,该文件可以加载到 pandas 数据帧:df = PD . read _ CSV(CSV _ file)。

五个字素和各自标签的样本。作者使用竞赛数据创建的图像。
dataframe 包括 image_id、三个不同标签的类别号(grapheme_root、元音 _ 音调符号、辅音 _ 音调符号)、字形的表示以及范围从 0 到 4 的折叠号,该折叠号将用于将数据分成训练/验证集。

数据报的前 5 行。作者使用比赛数据和笔记本中的数据创建的图像。
用 12 行代码创建数据加载器
要创建数据加载器,包括图像扩充和规范化,只需要下面的 12 行代码(其中 df 是数据帧, train_path 是存储图像的路径)。
在 fastai 中创建一个带有一个图像输入和三个分类目标的数据加载器。
- 在前两行中,定义了图像标准化和图像放大。Fastai aug_transforms 函数返回一个带有默认扩充的列表。由于字形是水平不对称的,翻转图像可能不是一个好主意,因此参数 do_flip 被设置为 false。
- 在第 3 到 10 行,创建了数据块。第 4 行的块参数接收一个包含四个元素的元组——一个用于图像输入,三个用于分类目标。用于这些类型数据的 fastai 块有:用于图像的图像块和用于目标标签的类别块。由于该数据集中的图像是灰度而不是 RGB,因此将cls = piimagebw赋予 ImageBlock。注意(3[CategoryBlock])是写三次 CategoryBlock 的懒惰方式。
- getters 参数接收定义如何获取每个块的数据的类列表。Fastai ColReader 类用于从 pandas dataframe 的一列中获取数据。在第 5 行中,第一个 ColReader 获取图像名称(检查上面的 dataframe 示例以供参考),然后对于每个 CategoryBlock,给出对应于不同标签的 dataframe 的一列。
- 第 9 行中的拆分器参数定义了如何将数据集拆分为训练/验证。有几种方法来定义分割。在这种情况下,由于我们在数据框中有折叠数,fastai IndexSplitter 函数可用于选择哪些样品将出现在验证集中。
- 在第 10 行中, batch_tfms 参数接收一个转换列表,如前两行所定义的。
- 现在数据块已经完成,在第 11 行中,使用以下参数创建了数据加载器:dataframe 和 batch-size。
- 最后,在第 12 行, n_inp 被设置为 1,这意味着只有一个输入——其他三个模块应被视为目标。
使用数据加载器
调用 dls.show_batch() 将打印出几个样本,类似于本文中第一幅图所示的内容。
不言而喻,数据加载器与 fastai Learner 类完美集成。然而,可以在一个循环中调用训练和验证数据加载器 dls.train 和 dls.valid 来提取批量数据,如下图所示。注意,有四个值要解包,对应于数据块中定义的块。

使用列车数据加载器的循环示例。作者创造的形象。
这有什么关系
fastai 库允许为孟加拉语创建数据加载器。人工智能竞赛仅 12 行干净的代码,包括图像放大和规范化。拥有一个默认情况下提供高效代码的框架,可以让深度学习实践者将更多时间分配给实验,从而增加更好的最终结果的可能性。拥有简洁的代码也减少了小错误的机会,这些小错误可能会悄悄地影响模型的性能。最后,代码在共享时更容易理解。
值得注意的是,fastai aug_transforms 增量是在 GPU 中计算的(如果有一个可用的话)。
像这样的细节很重要。
结束语
这个 Kaggle 内核为孟加拉语提供了一个完整的工作示例。人工智能竞赛,包括模型定义和使用学习者类的训练,这在本故事中没有涉及。
进一步阅读
在下面的故事中,我将进一步探索 fastai 数据块:
了解 fastai 数据块并创建用于深度学习的图像序列的构建块…
towardsdatascience.com](/working-with-3d-data-fastai2-5e2baa09037e)
关于我
[## 我的 3 年历程:从零 Python 到深度学习竞赛高手
自从 2017 年开始学习 Python 以来,我一直遵循的道路是成为一名独自参加 Kaggle 比赛的大师…
towardsdatascience.com](/my-3-year-journey-from-zero-python-to-deep-learning-competition-master-6605c188eec7)
感谢阅读!
编辑日志:
2020 年 5 月 10 日:修正了代码中的错误。batch_tfm 参数先前已在 dataloader 中给出。它应该在数据块中给出,而不是如正确的版本所示。
2020–06–07:增加了进一步阅读部分。
高级集成学习技术
合奏是一门艺术和科学

杰斯温·托马斯在 Unsplash 上的照片
在我以前关于集成学习的帖子中,我解释了什么是集成学习,它如何与机器学习中的偏差和方差相关联,以及什么是集成学习的简单技术。如果你没有看过这篇文章,请参考这里的。
在这篇文章中,我将介绍集成学习类型,高级集成学习方法——打包、提升、堆叠和与代码样本混合。最后,我将解释使用集成学习的利与弊。
集成学习类型
集成学习方法可以分为两组:
1。顺序集成方法
在这种方法中,基础学习者依赖于先前基础学习者的结果。每一个后续的基础模型都会修正它的前任所做的预测,修正其中的错误。因此,可以通过提高先前标签的权重来提高整体性能。
2。并行集成方法
在这种方法中,基本学习器之间没有依赖性,所有基本学习器并行执行,并且所有基本模型的结果最终被组合(对回归使用平均,对分类问题使用投票)。
并行集成方法分为两类
1。同类并行集成方法- 在这种方法中,单个机器学习算法被用作基本学习器。
2。异构并行集成方法- 在该方法中,多个机器学习算法被用作基础学习器。
高级集成技术
制袋材料
Bagging 或 Bootstrap 聚合是一种并行集成学习技术,用于减少最终预测中的方差。
bagging 过程与平均非常相似,唯一的区别是 Bagging 使用原始数据集的随机子样本来训练相同/多个模型,然后组合预测,而在平均中,使用相同的数据集来训练模型。因此,该技术被称为自举聚合,因为它结合了自举(或数据采样)和聚合来形成集合模型。

作者图片
装袋有三个步骤-
2.用每个样本建立模型(分类器或决策树)。
3.所有基本模型的预测被组合(对于回归问题使用平均或加权平均,对于分类问题使用多数投票)以获得最终结果。
所有这三个步骤都可以跨不同的子样本并行化,因此在处理较大的数据集时,训练可以更快地完成。
在 bagging 中,每个基础模型都在不同的数据子集上进行训练,并且所有结果都进行组合,因此最终模型较少过度拟合,并且方差减少。
当模型不稳定时,装袋更有用,对于稳定的模型,装袋在提高性能方面没有用处。当模型对训练数据中的小波动不太敏感时,称为稳定模型。
装袋的一些例子是——随机森林、装袋决策树、额外树。sklearn 库还提供 BaggingClassifier 和 BaggingRegressor 类来创建自己的 bagging 算法。
让我们看看下面的例子
LogisticRegression :::: Mean: 0.7995780505454071 , Std Dev: 0.006888373667690784
Bagging LogisticRegression :::: Mean: 0.8023420359806932 Std Dev: 0.00669463780099821 DecisionTreeClassifier :::: Mean: 0.8119073077604059 , Std Dev: 0.005729415273647502
Bagging DecisionTreeClassifier :::: Mean: 0.849639923635328 Std Dev: 0.0046034229502244905 RandomForestClassifier :::: Mean: 0.8489381115139759 , Std Dev: 0.005116577814042257
Bagging RandomForestClassifier :::: Mean: 0.8567037712754901 Std Dev: 0.004468761007278419 ExtraTreesClassifier :::: Mean: 0.8414792383547726 , Std Dev: 0.0064275238258043816
Bagging ExtraTreesClassifier :::: Mean: 0.8511317483045042 Std Dev: 0.004708539080690846 KNeighborsClassifier :::: Mean: 0.8238853221249702 , Std Dev: 0.006423083088668752
Bagging KNeighborsClassifier :::: Mean: 0.8396364017767104 Std Dev: 0.00599320955270458 VotingClassifier :::: Mean: 0.8462174468641986 Std Dev: 0.006423083088668752
正如我们在示例中看到的,Bagging 分类器改善了 ML 模型的方差并减少了偏差。当使用改进 ML 模型的平均方差的 VotingClassifier 时,情况也是如此。
助推
Boosting 是一种顺序集成学习技术,用于将弱基础学习者转换为表现更好且偏差更小的强学习者。这里的直觉是,单个模型可能不会在整个数据集上表现得很好,但它们在整个数据集的某个部分上表现得很好。因此,集合中的每个模型实际上都提升了整体性能。
提升是一种迭代方法,它根据先前的分类调整观察值的权重。如果一个观察被错误地分类,那么该观察的权重在下一次迭代中增加。以同样的方式,如果一个观察被正确分类,那么该观察的权重在下一次迭代中被减少。

作者图片
提升用于减少偏差误差,但它也会过度拟合训练数据。这就是为什么参数调整是 boosting 算法的一个重要部分,以使它们避免过度拟合数据。
Boosting 最初是为分类问题设计的,但也扩展到了回归问题。
Boosting 算法的一些例子有— AdaBoost、梯度 Boosting Machine (GBM)、XGBoost、LightGBM、CatBoost。
让我们来看一个例子
AdaBoostClassifier :::: Mean: 0.8604337082284473 Std Dev: 0.0032409094349287403
GradientBoostingClassifier :::: Mean: 0.8644262257222698 Std Dev: 0.0032315430892614675
XGBClassifier :::: Mean: 0.8641189579917322 Std Dev: 0.004561102596800773
VotingClassifier :::: Mean: 0.864645581703271 Std Dev: 0.0032985215353102735
堆垛
堆叠,也称为堆叠泛化,是一种集成学习技术,通过元学习(元分类器或元回归器)结合多种机器学习算法。
基础级算法在整个训练数据集上训练,然后元模型在作为特征的来自所有基础级模型的预测上训练。基础模型称为 0 级模型,结合基础模型预测的元模型称为 1 级模型。

作者图片
1 级模型训练数据是通过基本模型的 k 倍交叉验证准备的,折外预测(用于回归的实数和用于分类的类别标签)用作训练数据集。
0 级模型可以是不同范围的算法,也可以是相同的算法(通常它们是不同的)。第一级元模型通常是一个简单的模型,如回归问题的线性回归和分类问题的逻辑回归。
堆叠方法可以减少基于 0 级算法的偏差或方差。
用于堆叠的库有很多,像— StackingClassifier,StackingRegressor,make_classification,make_regression,ML Ensemble,H20。
让我们看一个使用 StackingClassifier 的例子
LogisticRegression :::: Mean: 0.799198344149096 Std Dev: 0.004958323931953346
DecisionTreeClassifier :::: Mean: 0.8130779055654346 Std Dev: 0.008467878845801694
KNeighborsClassifier :::: Mean: 0.8251287819886122 Std Dev: 0.00634438876282278
SVC :::: Mean: 0.8004562250294449 Std Dev: 0.005221775246052317
GaussianNB :::: Mean: 0.7964780515718138 Std Dev: 0.004996489474526567
StackingClassifier :::: Mean: 0.8376917712960184 Std Dev: 0.005593816155570199
正如我们在本例中看到的,我们在级别 0 中使用了不同的 ML 模型,并在级别 1 中使用 LogisticRegression 将它们与 StackingClassifier 堆叠在一起,这改善了方差。
多层堆叠
多级堆叠是堆叠的扩展,其中堆叠应用于多个层。

作者图片
例如,在 3 级堆叠中,0 级是相同的,其中使用 k-fold 交叉验证来训练不同范围的基础学习者。在级别 1 中,使用 N 个这样的元模型,而不是单个元模型。在级别 2 中,使用从级别 1 的 N 个元模型中获得预测的最终元模型。
增加多个层次既耗费数据(因为需要训练大量数据),又耗费时间(因为每一层都要增加多个模型)。
混合
混合最常与堆叠互换使用。它几乎类似于堆叠,只有一个不同之处,堆叠使用训练集的非折叠预测,而混合使用保留(验证)集(训练集的 10–20%)来训练下一层。
尽管混合比堆叠更简单,并且使用的数据更少,但最终模型可能会在维持集上过度拟合。
集合方法的优势/好处
1.与单个模型相比,集成方法具有更高的预测精度。
2.当数据集中既有线性数据又有非线性数据时,集成方法非常有用;可以组合不同的模型来处理这种类型的数据。
3.使用集合方法可以减少偏差/方差,并且大多数情况下,模型不会欠拟合/过拟合。
4.模型的集合总是更少噪音并且更稳定。
集成学习的缺点
1.集合的可解释性较差,集合模型的输出难以预测和解释。因此,合奏的想法很难推销,也很难获得有用的商业见解。
2.集成的艺术很难学习,任何错误的选择都会导致比单个模型更低的预测准确性。
3.就时间和空间而言,组装是昂贵的。因此,投资回报率可以随着组装而增加。
结论
在看了上面的集成学习技术的基础和集成学习的优点/缺点之后,如果使用正确,集成方法对于提高 ML 模型的整体性能是非常好的,这不会是错误的。当很难依赖一个模型时,集合使生活变得更容易,这就是为什么在大多数 ML 比赛中,集合方法是获胜者的选择。
虽然选择正确的合奏方法并使用它们不是一件容易的工作,但这种艺术可以通过经验来学习。本帖中描述的技术通常是集合的可靠来源,但是基于特定的问题/需求,其他变体也是可能的。
要访问高级合奏技术的完整代码,请查看 Github 链接。
谢谢你的阅读。如果你喜欢这个故事,请喜欢,分享和关注更多这样的内容。如往常一样,请联系我们以获得任何问题/评论/反馈。
https://github.com/charumakhijani LinkedIn:https://www.linkedin.com/in/charu-makhijani-23b18318/
数据科学高级函数编程:用函数运算符构建代码架构
使用函数运算符对 Pandas 中的read_csv函数进行矢量化
介绍
在的几种编程范式中、、函数式编程、、 (FP)非常适合数据科学。函数式编程的核心概念是一个函数,因此得名函数式编程。每个函数都将数据作为输入,并返回该数据的修改版本。例如,mean 函数获取一系列数字并返回这些数字的平均值。这种情况下的核心是函数没有副作用,即函数的结果不会改变函数外部的状态,也不会受外部状态的影响。这使得 FP 函数非常容易预测:给定一定的输入,输出总是相同的。
因此,乍一看,我们的笔记本电脑有两个组成部分:数据和对数据进行操作的功能。在大多数情况下,这两个将足以写你的笔记本。然而,当编写更复杂的代码时,比如像‘sk learn’这样的库,许多其他的 FP 概念将会派上用场。本文中我们将重点介绍的一个概念是所谓的 函数运算符 ,它是一个 高阶函数 。函数运算符将一个或多个函数作为输入,并返回一个新函数作为结果。进度条函数操作符就是一个很好的例子,它可以给任何数据处理函数添加进度条。这些函数运算符扩展了我们的选择,使我们能够创建灵活的、可重用的 FP 代码。
这篇文章的重点是构建一个函数运算符矢量化,它可以矢量化任何现有的非矢量化函数。您将了解以下主题:
- 如何使用闭包在 Python 中构建函数运算符
- *如何使用
*args '和*kwargs '将任何输入参数从一个函数传递到另一个函数 - 如何构建向量函数运算符
- 如何使用函数操作符创建一个清晰的函数和函数操作符的层次结构,类似于面向对象编程中的类层次结构
- 如何使用函数运算符让您在笔记本中编写干净的代码
在本文中,我们首先构建一个简单的函数运算符,并将其扩展为矢量化函数运算符。最后,我将总结一些关于如何使用函数运算符来构建代码架构的最终想法。

构建我们的第一个函数运算符
为了简化函数操作符,我们将首先构建一个非常简单的操作符。此函数运算符向输入函数添加一个计数器,用于跟踪函数被调用的频率:
这里的核心技巧是用internal_function包装input_function。internal_function的返回仅仅是调用输入函数,使得新函数的输出等于input_function。行为上的变化就在之前的几行代码中:调用的次数被打印到屏幕上,并且计数器增加 1。请注意,number_of_times_called变量是在internal_function的作用域之外定义的,我们使用[nonlocal](https://www.programiz.com/python-programming/global-local-nonlocal-variables)来访问该变量,尽管它超出了作用域。number_of_times_called在函数被调用的所有时间内保持持久的关键是internal_function记住了它被创建的原始作用域,即count_times_called的作用域。这种函数式编程技术被称为闭包。
因此,现在我们有两类函数:执行操作的函数(do_nothing)和改变其行为的函数操作符(count_times_called))。给定一组操作函数和函数操作符,我们可以构建一个非常复杂和灵活的函数层次结构,我们可以混合和匹配来编写我们的笔记本。潜在函数运算符的好例子有:
- 进度条。接受一个函数,以及完成整个操作需要调用该函数的次数。例如,您知道需要读取 25 个文件,并且您希望看到一个进度条,显示这 25 个文件中有多少已经被读取。顺便说一下, tqdm 包已经实现了这样一个函数操作符。
- 减速函数运算符。虽然降低代码速度感觉不太直观,但这样的函数对于修改调用 API 的函数非常有用,因为 API 对每分钟调用的次数有限制。
- 缓存函数运算符。该函数操作符存储输入和输出的组合,当输出已经存在于缓存中时,返回给定输入的缓存版本。这个过程叫做记忆。
- 通过交叉验证函数运算符进行超参数优化。该函数运算符包装拟合函数,并搜索给定参数的最佳值。这基本上就是 sklearn 中的 GridSearchCV 已经在做的。
构建矢量化函数算子
矢量化意味着您可以将向量传递给函数的输入参数,函数将执行适当的操作。例如,如果您将文件列表传递给一个读取 csv 文件的函数,它将读取所有文件。可悲的是,pandas.read_csv并不支持这种行为。在本节中,我们将构建一个矢量化函数操作符,它将允许我们升级pandas.read_csv,并允许您传递输入文件的矢量。
首先,我们将构建我们的矢量化函数操作符的基础版本,它将受到 R 函数矢量化的极大启发:
这里的关键代码是在internal_function末尾的列表理解,它实际上通过迭代作为输入给出的列表来对input_function进行矢量化。注意,我们需要知道哪些输入变量应该被矢量化,以便准确地编写列表理解。因此,我们首先从输入字典(kwargs)中获取合适的输入参数,然后使用del将其从列表中删除。这允许我们使用列表理解准确地构造对input_function的调用。
将其应用于read_csv:
这段代码为我们提供了一个“pandas.read_csv”版本,您可以向它传递一个文件列表,该函数返回一个包含六个 csv 文件内容的 pandas 数据帧列表。请注意,与对应的 R 相比,函数运算符有以下限制:
- 输出函数只支持命名参数,这是必需的,因为我使用参数名称来选择适当的输入参数进行矢量化。
- 该函数不能同时对多个参数进行矢量化处理
- 对输出不进行任何聚合。例如,这可以是将熊猫数据帧的列表自动连接成一个大的数据帧
下面的代码添加了最后一个特性:
现在,我们的函数运算符将最终结果的矢量化和聚合添加到一个大的数据框架中。在我看来,这使得pandas.read_csv更具表现力:用更少的代码传达同样的意图。这种表达能力使得代码可读性更强,并且在您的笔记本上更切中要点。
请注意,上面的代码比严格要求的要冗长一些,我可以直接使用‘PD . concat’而不用‘try _ to _ simplify’函数。然而,在这种当前形式下,代码可以根据函数返回的内容以多种方式支持简化。
使用函数运算符构建代码架构
使用数据、对数据进行操作的函数以及对这些函数进行操作的函数运算符,我们可以构建非常复杂的代码架构。例如,我们有读取数据的read_csv函数,以及允许我们读取多个文件的vectorize函数操作符。我们还可以将进度条函数操作符应用于矢量化的read_csv 函数,以便在读取大量 csv 文件时跟踪进度:
这里,read_data是组合了函数的所有性质和两个函数运算符的复合函数。从大量的函数和函数运算符中,我们可以构造复杂的函数。这允许我们创建简单、易于理解的代码组件,这些组件可以组合起来创建更复杂的代码。这种基于函数运算符的代码架构在数据科学环境中非常强大。
你也可以阅读 Github 上的文章*包括完整的可复制代码***
Python 中的高级莫尔斯码解码器

作者 Rhey t . Snodgrass&Victor f . Camp,1922 — Image:Intcode.png 和 Image:国际莫尔斯 code.png,公共领域,https://commons.wikimedia.org/w/index.php?curid=3902977
在我之前的一篇帖子中,我用 Python 设计了一个简单的莫尔斯码解码器,它能够接受用户输入,并以原始的字母数字形式输出。解码器的局限性之一是它不允许用户输入句子。请记住,我们选择用一系列“0”和“1”来表示每个字母或数字,其中“0”表示一个点,而“1”表示一个破折号。在我们的解码器中,每个字母或数字由一个“*”分隔,如下图所示。

图片作者——简单莫尔斯码解码器的 Python 输出
在本帖中,我们将改进我们简单的莫尔斯电码解码器,使其也能破译句子。此外,我们可以在解码器中执行检查,以通知我们每个字母/数字、单词或句子类型被解码的频率。
构建解码器类
这个解码器和前一个解码器的一个主要区别是,我们将使用 Python 类来构建我们的解码器和相应的分析检查。关于 Python 类的一个简单解释是,它定义了一组实例变量(要为每个对象表示的数据值)和一组可以应用于对象的方法(操作)。
我们将构建一个名为 Decoder 的类,它将包含几个方法,第一个是 init(self) 。这是创建对象的基本方法,它通常初始化每个对象的实例变量的值。请记住,我们选择使用字典结构来存储 Python 中的莫尔斯电码表示,其中每个字母或数字由一系列“0”和“1”表示。由于我们还添加了句子分析检查,我们还添加了三个标点符号“ ”。 、、、、、? ”。
class Decoder: def __init__(self):
self.the_dict = dict(zip(('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9','.',',','?'),('01','1000','1010','100','0','0010','110','0000','00','0111','101','0100','11','10','111','0110','1101','010','000','1','001','0001','011','1001','1011','1100','11111','01111','00111','00011','00001','00000','10000','11000','11100','11110','010101','110011','001100')))
创建类的下一个基本方法是返回/打印输出。仅仅使用 init (self) 方法,如果我们将一个变量赋给这个类,我们不能显示任何结果。我们将添加一个 str (self) 方法,其工作方式与print(variable)相同,但允许我们自定义结果的显示方式。
def __str__ (self):
dict_str = ""
for key,value in self.the_dict.items():
dict_str += "Character: " + str(key) + " ->" + " Code: " + str(value) + "\n"
return dict_str
一旦我们定义了上面的两个方法,我们就可以通过给类分配一个变量名并打印结果来尝试显示我们之前定义的字典结构。注意 my_dict 现在是类 Decoder 的一个对象。

按作者分类的图像-解码器类的 Python 输出
我们将在本课程中定义的最后一种方法是莫尔斯电码本身的解码,称为 decode (self,morse_code_sequence) 。注意,在这个方法中,除了定义 self,我们增加了另一个 morse_code_sequence 。这意味着要调用这个方法,我们必须通过这个方法传递一个变量(即莫尔斯电码序列),这类似于调用一个函数并通过它传递一个值。我们还将在我们的简单莫尔斯码解码器中加入我们之前实现的错误检查,主要是:
- 用户只能输入 0、1 和*
- 用户只能输入预先定义的莫尔斯电码表示法(例如 0000000 不是有效的表示法)
- 莫尔斯电码序列必须以标点符号结尾(如句号、逗号或问号)
def decode (self,morse_code_sequence):
character = list(self.the_dict.keys())
code = list(self.the_dict.values())
reverse_dict = dict(zip(code,character))
# Error check 1, checking for invalid characters (i.e. other than 0,1,*)
i=0
while i!=len(morse_code_sequence):
if morse_code_sequence[i]=="0" or morse_code_sequence[i]=="1" or morse_code_sequence[i]=="*":
i += 1
else:
return "Invalid characters in morse code sequence, it should only consists of 0, 1 and *"
break # Proceed for error check 2 once the morse_code_sequence does not contain invalid characters
if i == len(morse_code_sequence):
splitted_morse_code_sequence = morse_code_sequence.split("***")
morse_code_word = []
for j in range(0,len(splitted_morse_code_sequence)):
morse_code_word.append(splitted_morse_code_sequence[j].split("*")) #[['001','100','110'], ['90','9','9'], ['abc','17']]
morse_code_char=[]
# Initialise a result list as the format of morse_code_word
result = morse_code_word
# split into list containing all character's morse code
for k in range(0,len(morse_code_word)):
for l in range (0,len(morse_code_word[k])):
morse_code_char.append(morse_code_word[k][l])
# Check 2, terminate with punctuation marks i.e 010101, 110011, 001100
if morse_code_char[len(morse_code_char)-1]=="010101" or morse_code_char[len(morse_code_char)-1]=="110011" or morse_code_char[len(morse_code_char)-1]=="001100" : # Check 3, check if character's morse code representation is valid as per the dictionary
for k in range(0,len(morse_code_word)):
for l in range (0,len(morse_code_word[k])):
if morse_code_word[k][l] in reverse_dict.keys():
result[k][l]=reverse_dict[morse_code_word[k][l]]
else:
return "Invalid morse code representation"
else:
return "Invalid morse code sequence input, morse code sequence should end with punctuation characters"
# Create an empty list to append result in and convert into readable string format output
printed_result = []
for i in range(0,len(result)):
for j in range(0,len(result[i])):
printed_result.append(result[i][j])
printed_result.append(" ")
return ''.join(printed_result)

作者图片-输入莫尔斯码的解码器类的 Python 输出
构建字符分析器类
我们将构建的下一个类是字符分析器类,它将告诉用户每个字符(如字母或数字)被解码的频率。类似于我们的 Decoder 类,将定义两个基本方法 init(self) 和 str(self) 。
将创建第三种方法analyze _ characters(self,decoded_sequence) 来分析字符,解码后的序列通过该方法。我们将如何计算字符数,对于解码序列中的每个字符,我们将把它们添加到一个空字典中。循环遍历每个字符,我们将合计该字符的计数,并最终将它们显示为一个字典结构,这是我们在 str(self) 方法中定义的。
class CharacterAnalyser:
def __init__ (self):
self.the_dict_char = {}
def __str__ (self):
dict_char_str = ""
for key,value in self.the_dict_char.items():
dict_char_str += str(key) + " has been decoded " + str(value) + " time(s) " + "\n"
return dict_char_str
def analyse_characters (self, decoded_sequence):
for each in decoded_sequence:
if each != "?" and each != "." and each != "," and each != " ":
if each not in self.the_dict_char.keys():
self.the_dict_char[each] = 1
else:
self.the_dict_char[each] += 1
return self.the_dict_char

按作者分类的图像-字符分析器类的 Python 输出
构建单词分析器类
在我们的下一堂课中,我们将实现单词分析器,它将计算莫尔斯电码序列中某些单词被解码的次数。在定义了两个基本方法 init(self) 和 str(self) 之后,我们将定义第三个方法analyze _ words(self,decoded_sequence) ,它将分析词频。这个概念类似于字符分析器类,我们将循环通过解码序列中的每个单词,并在字典中汇总计数。
class WordAnalyser:
def __init__ (self):
self.the_dict_word = {}
def __str__ (self):
dict_word_str = ""
for key,value in self.the_dict_word.items():
dict_word_str += str(key) + " has been decoded " + str(value) + " time(s) " +"\n"
return dict_word_str
def analyse_words (self, decoded_sequence):
decoded_sequence_word=(decoded_sequence.strip()).split(" ")
for each in decoded_sequence_word:
if each != "?" and each != "." and each != ",":
if each not in self.the_dict_word.keys():
self.the_dict_word[each] = 1
else:
self.the_dict_word[each] += 1
return self.the_dict_word

按作者分类的图像-文字分析器类的 Python 输出
构建句子分析器类
我们要构建的最后一个分析器类是句子分析器类。由于我们允许用户键入句号、逗号和问号这三个标点符号,因此我们可以按照以下方式分析每种句子类型被解码的次数:
1.以'结尾的句子?'——问题
2.以' T10 '结尾的句子。 ' — 完成句子
3.以“、”—从句结尾的句子
在定义了基本的两个类 init(self) 和 str(self) 之后,我们将构建我们的第三个方法analyze _ sentences(self,decoded_sequence) 的方式是,我们将序列分割成单独的单词/标点符号,并遍历它们中的每一个。如果发现问号,我们将对“问题”进行计数,以此类推。
class SentenceAnalyser:
def __init__ (self):
self.the_dict_sentence = dict(zip(("Clauses","Complete Sentences","Questions"),(0,0,0)))
def __str__ (self):
dict_sentence_str = ""
for key,value in self.the_dict_sentence.items():
dict_sentence_str += str(key) + " has been decoded " + str(value) + " times(s) " + "\n"
return dict_sentence_str
def analyse_sentences (self, decoded_sequence):
decoded_sequence_sentence = decoded_sequence.split(" ")
for each in decoded_sequence_sentence:
if each == ",":
self.the_dict_sentence["Clauses"] += 1
elif each == ".":
self.the_dict_sentence["Complete Sentences"] += 1
elif each == "?":
self.the_dict_sentence["Questions"] += 1
return self.the_dict_sentence

作者图片-句子分析器类的 Python 输出
构建主程序
在最后一节中,我们将把以上 4 个类放在一起,创建一个程序,让用户能够输入莫尔斯码序列,并选择他/她感兴趣的分析类型。我们把所有的类放在一起的方法是使用 main() 方法,这是任何程序的起点。下面是完整的代码,我将带你们看一下。
# import all the 4 classes
from decoder_29442826 import Decoder
from character_29442826 import CharacterAnalyser
from word_29442826 import WordAnalyser
from sentence_29442826 import SentenceAnalyser
def main():
# set 4 variables to each of the 4 classes
my_dict_1 = Decoder()
my_dict_2 = CharacterAnalyser()
my_dict_3 = WordAnalyser()
my_dict_4 = SentenceAnalyser()
# initialise empty list to store user input
user_input_list = []
# print the structure of morse code representation for user's reference
print(str(my_dict_1))
# asking user to input morse code sequences for decoding
while True:
user_input_morse = input ("Enter sequences of Morse Code to be decoded based on representation shown, leave blank to stop input: ")
# Proceed for error checking of user input if it's not empty
if len(user_input_morse)!=0:
# Error check 1, checking for invalid characters other than 0, 1, *
if my_dict_1.decode(user_input_morse)=="Invalid characters in morse code sequence, it should only consists of 0, 1 and *":
print ("Invalid characters in morse code sequence, it should only consists of 0, 1 and *" + "\n")
# Error check 2, checking for minimum requirement of one set of ***
elif "***" not in user_input_morse:
print ("Error input, the Morse Code sequence should have at least one set of ***" + "\n")
# Error check 3, checking for punctuation at the end of user input, i.e. 010101, 110011, 001100
elif my_dict_1.decode(user_input_morse)=="Invalid morse code sequence input, morse code sequence should end with punctuation characters":
print("Invalid morse code sequence input, morse code sequence should end with punctuation characters" + "\n")
# Error check 4, checking for invalid morse code representation as per the pre-defined morse code dictionary
elif my_dict_1.decode(user_input_morse)=="Invalid morse code representation":
print("Invalid morse code representation" + "\n")
# add user input into list for decoding if no errors found
else:
user_input_list.append(user_input_morse)
# Stop asking for input once user leaved blank
else:
print("You have chosen to stop inputting morse code sequences" + "\n")
break
# empty string to store decoded sequences
overall_decoded_sequence=""
# decoding the morse code sequences in user_input_list
for each in user_input_list:
overall_decoded_sequence += my_dict_1.decode(each)
# character analysis of all the decoded morse code sequence
my_dict_2.analyse_characters(overall_decoded_sequence)
# word analysis of all the decoded morse code sequence
my_dict_3.analyse_words(overall_decoded_sequence)
# sentence analysis of all the decoded morse code sequence
my_dict_4.analyse_sentences(overall_decoded_sequence)
if len(overall_decoded_sequence)!=0:
# asking user to choose level of analysis from character, word, sentence or all
while True:
user_input_level = input ("Please choose the level of analysis from character, word, sentence or all, leave blank to quit:")
# if character analysis chosen, return result of character analysis only
if user_input_level == "character":
print("Decoded Morse Code Sequence(s):")
for each in user_input_list:
print(str(each) + " has been decoded to: " + my_dict_1.decode(each))
print("\n" + "Characters Analysis:" + "\n" + str(my_dict_2))
# if word analysis chosen, return result of word analysis only
elif user_input_level == "word":
print("Decoded Morse Code Sequence(s):")
for each in user_input_list:
print(str(each) + " has been decoded to: " + my_dict_1.decode(each))
print("\n" + "Words Analysis:" + "\n" + str(my_dict_3))
# if sentence analysis chosen, return result of sentence analysis only
elif user_input_level == "sentence":
print("Decoded Morse Code Sequence(s):")
for each in user_input_list:
print(str(each) + " has been decoded to: " + my_dict_1.decode(each))
print("\n" + "Sentence Analysis:" + "\n" + str(my_dict_4))
# if all has been chose, return result of character, word and sentence analysis
elif user_input_level == "all":
print("Decoded Morse Code Sequence(s):")
for each in user_input_list:
print(str(each) + " has been decoded to: " + my_dict_1.decode(each))
print("\n" + "Characters Analysis:" + "\n" + str(my_dict_2))
print("Words Analysis:" + "\n" + str(my_dict_3))
print("Sentence Analysis:" + "\n" + str(my_dict_4))
# if user leaved blank, terminate the whole program
elif user_input_level == "":
print("You have chosen to terminate the whole program")
break
# prompt the user for level of analysis again if invalid input has been found
else:
print("Invalid input, choose the level of analysis from character, word, sentence or all, leave blank to quit")
else:
print("No morse code sequences were entered")if __name__ == "__main__":
main()
这个程序的工作方式是,一旦用户运行这个程序,将首先显示莫尔斯电码表示(使用第一个解码器类)。用户将被提示输入莫尔斯电码序列,并可以继续输入解码,直到他们决定留下空白停止输入。

作者提供的图片-提示用户输入的主程序的 Python 输出
如果用户选择退出输入莫尔斯电码序列,并且没有输入任何莫尔斯电码序列,或者输入的所有莫尔斯电码序列都是无效的,程序将终止,并显示消息“没有输入莫尔斯电码序列”。

按作者分类的图像-没有输入的主程序的 Python 输出
一旦用户输入了一个莫尔斯电码序列或一系列序列,并键入一个空格以表示他/她想停止输入,程序将提示用户选择分析的级别(即字符、单词、句子或全部)。

按作者分类的图像-提示用户分析级别的主程序的 Python 输出
字符分析将调用 character_analyser 类,并返回在用户输入的序列中找到的字符及其解码频率。

作者图片—主程序选择字符分析的 Python 输出
单词分析将调用 word_analyser 类,并返回在用户输入的序列中找到的单词及其解码频率。

作者图片—主程序选择单词分析的 Python 输出
句子分析将调用句子分析器,并根据“?”返回问题、从句&完成句子的次数计数、'、'和' . '分别是。

图片由作者提供—主程序选择句子分析的 Python 输出
用户也可以选择“ all ”,三个分析将同时显示。
一旦用户完成分析,他/她可以通过输入空白输入来终止程序,程序将自行退出。

作者提供的图像-用户终止的主程序的 Python 输出
摘要
这篇文章描述了构建一个更先进的莫尔斯码解码器的过程,与之前的相比,之前的只能接受用户输入并以原始的字母数字形式输出。新的解码器允许用户解码句子,并获得被解码的字符/单词/句子的综合分析。我希望你们喜欢这篇文章,因为我们在这个解码器中定义了我们的 Python 类,所以这在编码熟练程度方面是更高级的。尽管如此,有乐趣提高你的莫尔斯电码解码器!
高级 NumPy 数组索引,变得简单

作者创建的图像。
理解[::2,[0,3,4],…,2:5]是什么意思
NumPy 最大的优势之一是它的索引速度非常快,但是它可以很快变得复杂。例如,给定一个形状为 5×6×3×5 的随机生成的整数数组,下面的操作会执行什么,产生的切片会是什么形状?
array[np.round(array)==array].reshape((5,6,3,5))[::2, [0,3,4], ..., 2:5]
当然,这种操作在许多方面是任意的,但是在多维数据上使用复杂的操作并不少见。到本文结束时,您将能够分解并编写自己复杂的 NumPy 数组索引操作。
一维数组
考虑数组构造array = np.array([1, 2, 3, 4, 5]),它创建了一个从 1 到 5 的数字数组。
为了访问第一个元素,我们调用array[0]。同样,为了访问第二个元素,我们调用array[1]。
为了访问最后一个元素,我们使用负索引(array[-1])。类似地,倒数第二个元素可以用array[-2]访问。
要访问元素的范围,指定开始索引和停止索引。结果将包括停止索引减 1 之前的所有元素(将此视为7不包括在range(7)中)。例如,抓取array的前三个元素可以用array[0:3]来完成,尽管它可以重写为array[:3],忽略 0 但返回相同的结果。
元素范围也支持赋值。例如,array[2:5] = np.arange(3)将使第三、第四和第五元素(第二、第三和第四索引)分别等于 0、1 和 2。
另一方面,要访问自定义索引中的多个值,请将一个列表或数组传入索引括号中。例如,array[[1, 3]]返回array([2, 4]),因为它请求数组的第二个和第四个值。使用索引数组来索引其他数组有很大的自由度,如果函数或认可的方法不起作用,这通常是实现理想索引的好方法。这些列表中的索引也可以是负数!
要访问步长为的元素范围,必须指定开始索引、停止索引和步长。例如,array[:4:2]返回[1, 3]。首先,array[:4]返回前四个元素,为[1, 2, 3, 4]。从第一个元素开始,移动步长,得到的数组是[1, 3]。

一维索引的剖析。作者创建的图像。
使用array[:]是复制数组的最快和最有效的方法之一。
数组索引可能看起来难以接近,因为使用了速记符号来避免键入零或结尾:例如,array[::2]返回[1, 3, 5]。索引的三个核心参数——开始索引、结束索引和步长——由它们相对于冒号(:)的位置来表示。当键入[::2]时,这意味着我们有意忽略起始和结束索引,而只想提供关于所需步长的信息。因此,NumPy 将以我们指定的步长返回整个数组。
NumPy 数组也支持条件索引。考虑一个由随机生成的从-5 到 5(包括-5 和 5)的整数组成的十元素数组:
rand = np.random.randint(low=-5, high=5, size=10)array([-2, -1, 2, -2, 4, 3, -1, -5, -2, 2])
为了找到所有正值,我们可以调用rand[rand>0],它返回array([2, 4, 3, 2])。这是因为rand>0或任何其他类似的条件被称为布尔掩码,其值为array([False, False, True, False, True, True, False, False, False, True])。NumPy 只是返回对应掩码值为True的值。使用这个逻辑,只要条件返回一个有效的布尔掩码,像rand[rand**3<=2*rand]这样的操作就是有效的。
条件语句适用于所有维度的数组。
二维数组
考虑下面的二维数组:
array = np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
对二维数据使用一维索引需要改变对数据的看法,不再把数据看作是表格,而是一系列列表。在这个透视图中,array是一个包含三个元素的数组,其中每个元素是另一个包含五个元素的数组。
因此,检索前两个元素的array[:2]应该返回:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10]])
自测一下——array[:2:2]应该返回什么?
由于array只是一个数组,它的元素恰好是数组,所以我们应该这样对待它。[:2:2]概述了前两个元素(起始索引 0 和终止索引 2),步长为 2。由于初始范围索引([:2])只返回两个值,并且步长为 2,所以结果只是第一个元素。在我们的二维数组中,这恰好是另一个数组:
array([[1, 2, 3, 4, 5]])
在二维数组上使用一维索引方法非常有限。为此,二维索引采用array[a:b:c, d:e:f]的形式。a:b:c和d:e:f代表起始索引、结束索引和步进索引的三重值。然而,逗号左边的a:b:c应用行方式的转换,而d:e:f应用列方式的转换,或者下一个维度。
例如,考虑下面的命令:array[:2,3:]。将这个索引分解成几个连续的部分是很有帮助的。
1 | [:2]取array的前两个元素。由于array是二维的,这是前两行:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10]])
2 | [3:]指定开始索引(3)而不是结束索引,这意味着在五元素数组中,它将从第四个元素(索引 3)开始,一直持续到数组的末尾。因为它是按列应用的,所以结果是:
array([[ 4, 5],
[ 9, 10]])
像一维索引一样,二维数组也可以使用列表来访问自定义索引值。但是,二维数组也必须由二维列表或数组进行索引。
索引多维数组
多维数组类似于两个低维数组。考虑一个名为array的三维数组,形状为(3,2,3):
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]],
[[12, 13, 14],
[15, 16, 17]]])
像二维数组一样,维度可以通过三个数字的束进行索引,用逗号分隔维度的单独索引。例如,array[:3:2,:,1:3]执行以下操作:
1 | [:3:2]表示“以步长 2 索引所有元素,直到第三个索引(第四个元素)”。在包含三个元素的数组列表中,这意味着第一个和第三个元素被保留。
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[12, 13, 14],
[15, 16, 17]]])
2 | [:]表示‘什么都不做’。由于没有提供任何信息,NumPy 不会改变数组,但它需要在那里指示第二维不会发生任何事情。
3 | [1:3]表示索引从第一个索引(第二个元素)开始到第三个索引(第四个元素)结束的所有元素。该切片应用于第三个也是最后一个维度。
array([[[ 1, 2],
[ 4, 5]],
[[13, 14],
[16, 17]]])
当维数很大时,省略号(…)可用于多个冒号和逗号的简写。考虑一个四维阵列z:
z = np.arange(81).reshape(3,3,3,3)
在这种情况下,z[1, :, :, 0]和写z[1, …, 0]是一样的。此外,我们可以将z[:, :, :, 0] as z[…, 0]和z[1, :, 2, 0]写成z[1, …, 2, 0](尽管在特定情况下这是不必要的)。每个索引只支持一个省略号。
当使用许多元素来索引数组时,理解列表和元组之间的区别很重要。考虑一个 3 乘 3 阵列z:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
命令z[[0,0]]保留在第一个行维度中,因为主方括号中没有逗号。索引[0, 0]的结果是第一行(索引 0)重复两次:
array([[0, 1, 2],
[0, 1, 2]])
另一方面,键入z[(0, 1)]是键入z[0, 1]的另一种方法,因为它将返回第一行(索引 0)和第二列(索引 1)中的值。换句话说,元组可以用于跨维度,但是由于它们的存在相对来说是任意的,所以建议根本不要编写带括号的跨维度索引。
解释和编写复杂索引的技巧
NumPy 索引可以很快变得非常复杂,因为它的索引方法可能会发生不可预测的变化,并导致奇怪的结果。
- 用英语写出每个维度中您想要索引的部分,然后逐个维度地翻译(用逗号分隔)。
- 通常,在单个命令中使用的索引数据类型要保持一致。例如,如果不是绝对必要,使用
a:b和[a, b, c, d]符号会导致结果的不可预测性。 - 不要把所有事情都塞进一个命令中。或者,尝试使用同样的一步一步的数据缩减来逐个维度地建立索引,然后一旦确定可以工作,就将命令链重写为单个命令。
- 将所有东西分成
a:b:c组。
熔化、旋转、连接、爆炸等
towardsdatascience.com](/every-dataframe-manipulation-explained-visualized-intuitively-dbeea7a5529e)
感谢您的阅读,请在回复中告诉我您的想法!
如果你对最新的文章感兴趣,可以考虑订阅。如果你想支持我的写作,通过我的推荐链接加入 Medium 是一个很好的方式。干杯!
Matplotlib 中的高级绘图—第 1 部分
展示了 matplotlib 中的一些高级图,可以让我们的分析更上一层楼。

作者图片
python 可视化环境由几个有用的 Python 库组成。每个图书馆都以自己独特的方式闪耀。虽然有些库很容易使用,但其他的有更好的功能。Matplotlib 就是这个可视化生态系统中的一个重要组成部分。Matplotlib 提供了多种方式将数字表示成有意义的图形和图表。下面的备忘单很好地展示了 Matplotlib 的各种功能,以及如何使我们的可视化更加有效。

Matplotlib 备忘单。完整图片:https://lnkd.in/dD5fE8V
matplotlib 的基本功能,包括创建条形图、直方图、饼图等。众所周知。然而,在本文中,我将展示 matplotlib 中的一些高级图,它们可以使我们的分析更上一层楼。
matplotlib 中的动画是另一个有趣的功能,我有一篇完整的文章专门介绍它。文章可以在这里阅读: 用 Matplotlib 制作的动画。
动画是展示一种现象的有趣方式。我们人类总是被动画和…
towardsdatascience.com](/animations-with-matplotlib-d96375c5442c)
1.跨度选择器
跨度选择器是 matplotlib 中的一个鼠标小部件。小部件是 python 对象,用于包含一些交互功能。跨度选择器通过鼠标选择返回图形中选定区域的最大值和最小值。
在下面的代码片段中,我们首先创建一个基本的线图。然后我们调用 SpanSelector 方法,首先使用它来选择一个区域,然后打印该区域中的最大值和最小值。下面让我们来看看它的实际应用。
**import** matplotlib.pyplot as plt
**from** matplotlib.widgets **import** SpanSelector**def** onselect(xmin, xmax):
print(xmin, xmax)
**return** xmin, xmaxfig, ax **=** plt.subplots()
ax.plot([1,2,3,4,5,6,7], [10, 50, 100, 23,15,28,45])
span **=** SpanSelector(ax, onselect, 'horizontal', useblit**=**True, rectprops**=**dict(alpha**=**0.5, facecolor**=**'red'))
plt.show()

Matplotlib 的跨度选择器的作用
2.断裂条形图-断裂的水平条形图
“断开的”水平条形图是一个有缺口的图。它用于数据值变化很大的情况,例如,由极端温度范围组成的数据集。在这种情况下,折线图是理想的,因为它们可以完美地绘制最大和最小范围。
python 模块matplotlib.broken_barh()用于绘制断裂的水平条形图。
import matplotlib.pyplot as plt
#Defining the x and y ranges
xranges = [(5,5), (20,5),(20,7)]
yrange = (2,1)
#Plotting the broken bar chart
plt.broken_barh(xranges, yrange, facecolors='green')
xranges = [(6,2), (17,5),(50,2)]
yrange = (15,1)
plt.broken_barh(xranges, yrange, facecolors='orange')
xranges = [(5,2), (28,5),(40,2)]
yrange = (30,1)
plt.broken_barh(xranges, yrange, facecolors='red') plt.xlabel('Sales')
plt.ylabel('Days of the Month')
plt.show()

断开的水平条形图
3.表格演示
Matplotlib 的表格函数可以在绘图中显示表格。当您想要以条形图的形式查看表格中的快速可视化值,并将表格放在旁边时,这尤其方便。表格可以放置在图的顶部、底部或侧面。以下是如何轻松创建一个。
下面的例子摘自刚刚发光的 Python(@ 刚刚发光)的推文
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
x = np.random.rand(5, 8)*.7
plt.plot(x.mean(axis=0), '-o', label='average per column') plt.xticks([]) plt.table(cellText=[['%1.2f' % xxx for xxx in xx] for xx in x],cellColours=plt.cm.GnBu(x),loc='bottom')
plt.show()

matplotlib 中的表格绘图,底部有一个表格

matplotlib 中的表格绘图,顶部有一个表格
4.水印图像
有时,将图像作为水印有助于为情节添加独特的味道。例如,如果我们要分析多年来顶级运动员的收入,将他们的照片放在背景中有助于我们轻松地区分不同运动员的情况。让我们分析一个由许多运动员的收入组成的数据集。我们将绘制一张勒布朗·詹姆斯历年收入的图表,单位为美元(百万)。
import numpy as np
import matplotlib.image as image
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv('income.csv')
im = image.imread('Lebron_James.jpeg') # Image
该数据集由许多运动员的收入组成。让我们筛选出只包含勒布朗的数据。
lebron_james = df[df['Name']=='LeBron James']
显示带水印的绘图。
fig, ax = plt.subplots()
ax.grid()
ax.plot('Year','earnings ($ million)',data=lebron_james) ax.set_title("LeBron James earnings in US$(millions)") fig.figimage(im, 60, 40,cmap='ocean', alpha=.2)
plt.show()

5.XKCD 图
现在让我们在剧情中加入一些有趣的元素。 xkcd 是由兰道尔·门罗创作的网络漫画,展示了很多幽默的情节。这些图定期出现在许多数据科学演示文稿中,例如,下图所示:

来源:xkcd.com
好吧,如果你想给你的 matplotlib 图添加一些扭曲,你可以简单地调用 pyplot 对象上的xkcd()方法,如下所示。在这里,我们正在使用印度的 GDP 数据集,该数据集显示了 2010 年至 2019 年的 GDP 增长率百分比。
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('https://raw.githubusercontent.com/parulnith/Website-articles-datasets/master/India%20GDP%20Growth%20Rate%20.csv', parse_dates=['Year'])
df['Year'] = df['Year'].apply(lambda x: pd.Timestamp(x).strftime('%Y')) #calling xkcd() method
plt.xkcd(scale=5, length=400)
df.plot(x='Year',y='GDP Growth (%)',kind='bar')
plt.ylabel('GDP Growth (%)')
plt.xticks(rotation=-20)
plt.figure(figsize=(10,8))
plt.show()

结论
这些是 matplotib 中一些有趣的高级功能。还有一些其他很酷的图表,我已经在文章的第二部分列出了:
Matplotlib 可视化库的一些鲜为人知但功能强大的特性。
towardsdatascience.com](/advanced-plots-in-matplotlib-part-2-e88f91ce9e31)
因此,抓住一个有趣的数据集,运用你新学到的技能来很好地理解这个主题。
[1]最初发表于parulpandey.com
Matplotlib 中的高级绘图—第 2 部分
Matplotlib 可视化库的一些鲜为人知但功能强大的特性

作者图片
本文是 Matplotlib 系列 高级图的第二部分。在 第 1 部分 中,我们学习了如何在我们的可视化工作中使用跨度选择器、断开的水平条图和表格功能。我们还学习了如何使用 XKCD 主题给图像添加水印和给 Matplotlib 中的情节添加扭曲。在第 2 部分中,我们将介绍 Matplotlib 的其他一些有趣的功能,并使用它来丰富我们现有的情节。
python 可视化环境由几个有用的 Python 库组成。每个图书馆都有自己独特的亮点…
towardsdatascience.com。](/advanced-plots-in-matplotlib-part-1-30dbb02b09ae)
1.事件图
当想要 在预定义的位置 绘制相同的平行线时,事件图就派上了用场。这种图通常在神经科学中用于显示神经元随时间的尖峰活动,这里经常被称为尖峰光栅或简称为光栅图。然而,这类地块还有其他用途。以下是事件图文档的摘录:
在您希望显示多组离散事件的时间或位置的任何情况下,它都是有用的,例如一个月中每天人们到达企业的时间,或者上个世纪每年的飓风日期。
让我们看一个显示具有各种线条属性的事件序列的eventplot。该图以水平和垂直方向显示。剧情改编自官方 Matplotlib 的 Eventplot 文档。

Matplotlib |作者图片中的事件/尖峰光栅图
2.时间表
您知道单独使用 Matplotlib 可以创建一个简单的时间线吗?是的。这是因为从技术上讲,时间线只是日期和文本的简单集合,可以通过在干图中进行简单的变化来获得。你可以在这里阅读更多相关信息。
这里是一个时间表,显示了使用官方文档中提供的代码的 Android 版本历史。

Matplotlib 中 Android 版本历史的时间轴|图片由作者提供
3.一块馅饼
你有没有想过进一步深入到一个饼图?也许你想展开它的一个切片,把它“分解”成一个条形图?Matplotlib 通过“饼状图”功能使之成为可能。它使用了一个连接补丁来连接两个点(可能在不同的轴上)。
这个想法很简单。创建一个饼图及其相应的条形图作为子情节,然后使用连接补丁在两个子情节之间绘制线条。
这里有一个来自官方文档的例子。

图片来源:Matplotlib的饼状图条
4.样式表参考
在 matplotlib 中创建绘图时,很多时候,我们倾向于使用默认样式。然而,Matplotlib 提供了一堆很棒的样式选项,使得即使是平凡的可视化效果也非常突出。要列出所有样式,请输入以下代码行。
在这里我将展示一些流行的。如果你有兴趣,你可以在这里找到完整的列表。让我们创建一个基本的线图,然后应用一些不同的样式。如果没有指定样式,matplotlib 将使用默认样式:
import matplotlib.pyplot as pltplt.plot([1, 3, 9, 5, 2, 1, 1], marker='o')
plt.plot([4, 5, 5, 7, 9, 8, 6], marker='v')
plt.plot([2, 3, 4, 3, 4, 5, 3], marker='s')
plt.show()

matplotlib 中的默认样式(图片由作者提供)
若要添加您选择的样式,请在代码中插入以下行:
plt.style.use('stylename') #Replace 'stylename' with the desired style
常用样式:
让我们来看看一些常用的风格:
经典的
Classic 是 Matplotlib 比较老的风格。
import matplotlib.pyplot as plt
plt.style.use(“classic”)plt.plot([1, 3, 9, 5, 2, 1, 1], marker=’o’)
plt.plot([4, 5, 5, 7, 9, 8, 6], marker=’v’)
plt.plot([2, 3, 4, 3, 4, 5, 3], marker=’s’)
plt.show()

经典风格(图片由作者提供)
ggplot
这种风格模仿了 ggplot (一个用于 R 的流行绘图包)的美学
import matplotlib.pyplot as plt
plt.style.use(“ggplot”)plt.plot([1, 3, 9, 5, 2, 1, 1], marker=’o’)
plt.plot([4, 5, 5, 7, 9, 8, 6], marker=’v’)
plt.plot([2, 3, 4, 3, 4, 5, 3], marker=’s’)plt.show()

ggplot 样式(图片由作者提供)
五三八
这是一个“fivethirtyeight”风格的例子,它试图复制来自fivethirtyeight.com的风格
import matplotlib.pyplot as pltplt.style.use(“fivethirtyeight”)plt.plot([1, 3, 9, 5, 2, 1, 1], marker=’o’)
plt.plot([4, 5, 5, 7, 9, 8, 6], marker=’v’)
plt.plot([2, 3, 4, 3, 4, 5, 3], marker=’s’)plt.show()

五三八风格(图片作者)
黑客的贝叶斯方法— bmh
这个例子展示了黑客在线书籍贝叶斯方法中使用的风格。
import matplotlib.pyplot as pltplt.style.use("bmh")plt.plot([1, 3, 9, 5, 2, 1, 1], marker='o')
plt.plot([4, 5, 5, 7, 9, 8, 6], marker='v')
plt.plot([2, 3, 4, 3, 4, 5, 3], marker='s')plt.show()

bmh 风格(图片由作者提供)
赛博朋克风格
最近,我偶然发现了一个名为mplcyberpunk,的包,它是一个基于matplotlib的 Python 包,只用三行额外的代码就创建了“cyberpunk”风格的情节。多酷啊🤘?
使用赛博朋克风格;您需要首先安装并导入该库。
!pip install mplcyberpunk
import matplotlib.pyplot as plt
import mplcyberpunkplt.style.use("cyberpunk")plt.plot([1, 3, 9, 5, 2, 1, 1], marker='o')
plt.plot([4, 5, 5, 7, 9, 8, 6], marker='v')
plt.plot([2, 3, 4, 3, 4, 5, 3], marker='s')# Add glow effects-Optional
mplcyberpunk.add_glow_effects()
plt.show()

赛博朋克风格(图片由作者提供)
5.adjustText —自动放置matplotlib的标签
最后,让我们看看 Matplotlib 中一个有用的第三方包。顾名思义,第三方包构建并扩展了现有的 Matplotlib 功能。需要记住的重要一点是,默认情况下,这些包不包含在 Matplotlib 中,必须单独安装。
调整文本
很多时候,我们努力调整图表中的文本位置。当有多个标签,并且这些标签开始重叠时,就会发生这种情况。对于这种情况,adjustText 是一个非常有用的库,因为它可以自动放置标签。
装置
如前所述,您需要首先安装库,这可以通过以下三种方式之一完成:
pip install adjustText # pip install
or
conda install -c conda-forge adjusttext # conda
or
# For the latest version from GitHub:
pip install [https://github.com/Phlya/adjustText/archive/master.zip](https://github.com/Phlya/adjustText/archive/master.zip)
使用
让我们来看一个来自 adjustText 的文档本身的基本示例,以突出 adjustText 的强大功能。左图为重叠标签,右图为调用adjust_text功能后自动调整的标签。


l:之前;r:之后(图片由作者提供)
包裹
这是我们关于高级 Matplotlib 图的两部分系列的结尾。在本系列中,我们看到了如何利用 Matplotlib 可视化库来生成一些独特的图表。这对于创造引人入胜的故事情节大有帮助。事件图在绘制离散事件时非常有用,而时间线有助于描绘历史上的特定事件。同样,一条饼图比传统的饼图传达了更多的信息。像“赛博朋克”这样的风格提供了一种优雅风格的元素,可以使一些视觉效果突出。希望你能够在可视化中利用这些文章中分享的一些信息,并与世界分享你的酷项目。
[1]最初发表于parulpandey.com
[2]这是一个附属链接
你应该知道的 8 种高级 Python 列表技术!
让全能榜单更加强大!

这些技术将使你成为 Python 列表专家!资料来源:Nik Piepenbreier
Python 中的列表是您将遇到的最常见的数据结构之一——它们也是最强大的数据结构之一!Python 列表的用途非常广泛,有很多隐藏的技巧。
让我们来探索其中的一些!
1.用 Python 过滤列表
1.a)使用 Filter()函数
filter()函数有两个参数:一个函数和一个 iterable 项。在这种情况下,我们将定义一个函数并过滤一个列表。
让我们用一个例子来验证一下!我们将从一个列表开始,过滤掉少于 3:
使用 filter()函数过滤列表。资料来源:Nik Piepenbreier
让我们看看这里发生了什么:
- 我们定义我们的原始列表
- 然后我们定义一个接受参数(“number”)的函数。如果数字大于 3,函数将返回 True。
- 我们定义一个应用过滤功能的项目(“filtered”)。我们的项目被过滤,是一个过滤对象。
- 最后,我们创建“filtered_list ”,它将 list 函数应用于过滤后的对象。
1.b)列表理解
同样,我们可以用列表理解来过滤列表。记住,列表理解是定义和修改列表的优雅方式。
让我们看看如何通过列表理解来完成前面的任务:
使用列表理解来过滤列表。资料来源:Nik Piepenbreier
从这两个例子中我们可以看出,列表理解是过滤列表的一种更简单、更优雅的方式。
提示:如果你想了解更多关于列表理解的知识,可以看看我的 YouTube 视频:
学习 Python 列表理解。资料来源:Nik Piepenbreier
2.修改列表
2.a)使用 Map()函数
Python Map 函数允许我们将函数应用于 iterable 对象中的每一项。
假设我们有一个列表,想要返回每个数字的平方。我们可以使用 map()函数来实现这一点。让我们来看看这个:
对列表使用映射功能。资料来源:Nik Piepenbreier
让我们探索一下这里发生了什么:

在 Python 中修改列表并不一定很烦人。资料来源:Nik Piepenbreier
首先,我们定义我们的原始列表和一个返回其参数的平方(“number”)的函数。
然后,我们创建一个名为(“squares”)的新变量,它是 map 函数的结果,函数和原始列表是它的参数。
最后,我们创建另一个新变量,将 list 函数应用于 squares 变量。
这种方法有点罗嗦!接下来让我们来看看清单理解!
2.b)列表理解
我们可以使用列表理解来完成修改列表项的相同任务。这甚至是一种更简单、更优雅的编写代码的方式。
让我们试试这个!
使用列表理解来修改列表。资料来源:Nik Piepenbreier
3.用 Zip()函数组合列表
有些情况下,您可能希望合并两个或更多列表。这就是 zip()函数的用武之地!zip()函数创建一个对象,包含列表在每个索引处的对应元素。
让我们用一个例子来验证一下:
Python 中的压缩列表。资料来源:Nik Piepenbreier
4.反转列表
Python 列表是有序的数据结构。因此,项目的顺序很重要。有时您可能需要反转列表中的项目。这可以使用 Python 切片操作轻松完成。
让我们用一个例子来试试这个:
在 Python 中反转列表。资料来源:Nik Piepenbreier
5.检查列表中的成员资格
有时,您可能想要查看列表中是否存在某个项目。
您可以简单地通过使用操作符中的来实现这一点。
假设我们有一个赢了一场比赛的球队列表,并想看看某个球队是否赢了:
正在检查列表成员资格。资料来源:Nik Piepenbreier
6.查找列表中最常见的项目
您可能希望找到列表中最常见的项目。例如,您可能正在记录列表中正面和反面游戏的获胜者,并想知道哪一个发生得最多。

很容易找到列表中最常见的项目!资料来源:Nik Piepenbreier
让我们试一试:
查找 Python 列表中最常见的项目。资料来源:Nik Piepenbreier
让我们来看看我们在做什么:
- 我们用五个正面或反面游戏的结果定义一个列表,
- 我们定义了列表中所有项目的集合。set()函数过滤掉列表中所有重复的项目。
- 最后,我们将 max()应用于我们的项目集合,使用 key 参数作为集合中最大的元素计数。
7.平铺列表列表
有时你会发现一个列表中有其他的列表。你可以使用列表理解很容易做到这一点!
让我们试一试:
在 Python 中展平列表列表。资料来源:Nik Piepenbreier
8.检查唯一性
如果您需要检查一个列表中的所有项目是否都是唯一的,您可以使用集合的力量来完成这个任务!
Python 中的集合类似于列表(因为它是可变的(“mutable”)和无序的),但是它只能包含唯一的项目。
为此,我们将使用一个函数将我们的列表转换成一个集合,并比较两个项目的长度:
检查列表的唯一性。资料来源:Nik Piepenbreier
感谢阅读!
非常感谢你坚持到文章的结尾!
我希望你学到了一些关于列表的新知识,以及如何以不同的方式使用它们!
掌握 Python 字符串的 8 个高级技巧
学习这些技巧来掌握 Python 字符串

Emile Perron 在 Unsplash 上的照片
Python 字符串看起来很简单,但是它们非常灵活,而且无处不在!
对于数据科学来说,字符串似乎不是需要掌握的东西,但是随着大量非结构化定性数据的出现,深入研究字符串是非常有帮助的!
1.用' in '检查成员资格
在处理非结构化数据时,识别较长字符串中的特定单词或其他子字符串非常有用。最简单的方法是使用操作符中的。
假设您正在处理一个列表、系列或 dataframe 列,并且您想要确定一个子字符串是否存在于一个字符串中。
在下面的示例中,您有一个不同地区的列表,并想知道字符串“West”是否在每个列表项中。
检查字符串成员资格。资料来源:Nik Piepenbreier
2.用 F 弦变魔术
f 字符串是在 Python 3.6 中引入的,它们没有得到足够的重视。
我说它们有魔力是有原因的。他们:
- 允许更大灵活性,
- 比其他方法更具可读性,并且
- 执行速度更快。
但是它们是什么呢?string(或格式化的字符串文字)允许您将变量(或任何表达式)放入字符串中。然后在运行时执行这些表达式。
若要编写 f 字符串,请在字符串前加上前缀“f”。
让我们来看一个例子:
f 弦太棒了。资料来源:Nik Piepenbreier
3.用[::-1]反转字符串
通过分割字符串,可以反转字符串(像其他可重复项一样)。要反转任何 iterable,只需使用[::-1]。
-1 作为步长参数,Python 从最后一个值开始,递增-1:
反转字符串。资料来源:Nik Piepenbreier
4.将子字符串替换为。替换()
若要替换子字符串,可以使用 replace 方法。这适用于任何类型的字符串,包括简单的空格(因为 Python 没有移除空格的内置方法)。
让我们来看一个例子:
更换子字符串。资料来源:Nik Piepenbreier
5.用 For 循环迭代字符串
Python 字符串是可迭代的对象(就像列表、集合等。).
如果您想返回字符串中的每个字母,您可以写:
迭代字符串。资料来源:Nik Piepenbreier
要了解更多关于 for 循环的信息,请查看下面我的视频:
6.用格式化字符串。upper(),。lower()和。标题()
Python 字符串可能有点古怪。你可能会得到一个全大写、全小写的文件,等等。你可能需要把它们格式化,以便以后展示。
- 。upper()将返回一个所有字符都是大写的字符串
- 。lower()将返回一个所有字符都是小写的字符串
- 。title()将字符串中的每个单词都大写。
让我们来看看这些是如何运作的:
格式化管柱套管。资料来源:Nik Piepenbreier
7.检查回文和字谜
结合到目前为止所学的内容,使用[::-1] slice 可以很容易地检查一个字符串是否是回文。
如果一个单词或短语向前拼写和向后拼写相同,那么它就是回文。
同样,您可以使用 sorted 函数返回字符串的排序版本。如果两个排序后的字符串相同,则它们是变位词:
检查回文。资料来源:Nik Piepenbreier
变位词是通过重新排列另一个单词而形成的单词或短语。简而言之,如果两个单词有相同的字母,它们就是变位词。
如果要查看两个单词是否是变位词,可以对这两个单词进行排序,看它们是否相同:
检查字谜。资料来源:Nik Piepenbreier
8.用拆分字符串。拆分()
假设给你一个包含多段数据的字符串。拆分该字符串以解析出单独的数据片段会很有帮助。
在下面的示例中,字符串包含地区、销售代表的姓氏以及订单号。
你可以用。split()拆分这些值:
拆分一个字符串。资料来源:Nik Piepenbreier
结论
非常感谢你的阅读!我希望你学到了新东西。
如果你想掌握列表,看看我的另一篇文章:
让全能榜单更加强大!
towardsdatascience.com](/advanced-python-list-techniques-c6195fa699a3)
先进的火花调谐、优化和性能技术
Apache Spark 调优提示和技巧

由 Unsplash 上的 CHUTTERSNAP 拍摄
介绍
Apache Spark 是一个分布式计算大数据分析框架,旨在跨一个机器集群转换、设计和处理海量数据(想想太字节和太字节)。它有许多用于特定任务的嵌入式组件,包括 Spark SQL 的结构化数据框架和结构化流 API,这两者都将在本博客中讨论。Spark 面临的一个挑战是向数据湖追加新数据,从而在写入时产生‘小而倾斜的文件’。完全解决这些挑战可能会很棘手,因此会对用户执行额外的下游 Spark 层、数据科学分析和使用“小而扭曲的文件”的 SQL 查询产生负面影响。相当新的框架 三角洲湖泊 和 阿帕奇胡迪 有助于解决这些问题。
然而,在这篇博客中,我将使用原生的 Scala API 向你展示 1。)如何在 Spark 结构化流作业中包含一个瞬态计时器,用于自动终止周期性数据处理添加新源数据,以及 2 .)如何控制 Spark 作业产生的输出文件数量和分区大小。问题解决#1 功能避免了总是为长期运行(有时空闲)、【24/7】、集群(即在 Amazon EMR 中)付费。例如,对于只处理新的可用源数据(即在亚马逊 S3 )而言,短期流作业是一个可靠的选择,这些数据没有一致的节奏到达;也许每小时都会有小批量的登陆。问题解决#2 功能对于提高下游流程(如下一层 Spark 作业、SQL 查询、数据科学分析和整体数据湖元数据管理)的 I/O 性能非常重要。
免责声明:本博客中使用的公共数据集包含非常小的数据量,仅用于演示目的。这些 Spark 技术最适用于真实世界的大数据量(即万亿字节&千兆字节)。因此,相应地调整 Spark clusters &应用的规模、配置和调优。
示例 1:火花流瞬态终止定时器
1a。)首先,让我们查看一些示例文件,并为从存储在dbfs:/data bricks-datasets/structured-streaming/events/的data bricks Community Edition中检索的公共物联网设备事件数据集定义模式。
ls /blogs/source/devices.json/

作者图片
head /blogs/source/devices.json/file-0.json/

作者图片
1b。)接下来,我们将把数据集作为定义了模式的流数据帧来读取,并包括函数参数:
- maxFilesPerTrigger (每个触发器读取的最大文件数)
- 基本路径(数据源位置)
1c。)现在,我们以parquet文件接收器格式和append模式执行流式查询,以确保仅周期性增量写入新数据,并包括函数参数:
- 测向(源数据帧)
- 重新分区(每次触发时持续输出分区的数量)
- 检查点路径(恢复检查点位置)
- 触发(触发间隔处理时间)
- 目标路径(数据目标位置)
1d。)Scala sleep 函数(以毫秒为单位)将用于在优雅的瞬态计时器上关闭流作业。
1e。)最后,流式作业 Spark 会话将在定时器到期后执行,从而终止短期应用程序。
1f。)将函数应用于 Scala 值,并根据需要设置额外的 Spark 属性:
spark.sql.session.timeZone(设置为 UTC 以避免时间戳和时区不匹配问题)spark.sql.shuffle.partitions(设置在宽“洗牌”转换上创建的期望分区数量;价值因以下因素而异:1 .数据量&结构,2。集群硬件&分区大小,3。可用内核,4 个。应用程序的意图)
1g。)查看作业的输出位置
ls /blogs/target/devices.parquet/

作者图片
总之,流作业将只从源 json 位置向目标 parquet 位置连续处理、转换和附加微批未处理的数据。定时器超时(例如:5 分钟)后,Spark 应用程序正常关闭。对于 Spark 应用程序部署,最佳实践包括用包含作为命令行参数的args: Array[String]的main()方法定义 Scala object。然后创建一个所需的目录结构,用一个build.sbt(库依赖)文件编译<appName>.scala(应用程序代码)文件,所有这些都通过 SBT 构建工具创建一个 JAR 文件,该文件将用于通过spark-submit运行应用程序。
下面是官方的 Apache Spark 文档 解释步骤。
在 AWS 中,通过 Amazon EMR 您可以提交应用程序作为作业步骤,并在所有步骤完成时自动终止集群的基础设施。这可以通过像 AWS 步骤功能、 AWS Lambda 和 Amazon CloudWatch 这样的服务来完全编排、自动化和安排。
有时,流作业的输出文件大小会相当【倾斜】,这是由于源数据的到达节奏不规则,以及始终将其与流作业的触发器同步的时间挑战。示例 2 将有助于解决和优化“小而歪斜的文件”的困境。
到下一个例子…
示例 2: Spark 重新分区文件大小优化
2a。)首先,让我们查看一些样本文件,并读取我们的公共航空公司输入数据集(从存储在dbfs:/data bricks-datasets/airlines/的data bricks Community Edition中检索,并转换为用于演示目的的小拼花文件)并确定数据帧中的分区数量。
ls /blogs/source/airlines.parquet/

作者图片
display(df)

作者图片
2b。)为了计算所需的输出分区(文件)大小,您需要通过将输入数据帧保存在内存中来估计其大小(即兆字节)。这可以通过执行df.cache()或df.persist()预先确定,调用类似df.count()或df.foreach(x => println(x))的动作来缓存整个数据帧,然后在存储选项卡下的 Spark UI 中搜索数据帧的 RAM 大小。
2c。)Spark 属性spark.default.parallelism可以帮助确定数据帧的初始划分,也可以用于增加 Spark 并行性。通常,建议将该参数设置为集群中可用核心的数量乘以 2 或 3。比如在 Databricks 社区版中spark.default.parallelism只有 8 个(本地模式单机,1 个火花执行器,共 8 个内核)。对于真实的场景,我建议您避免在运行时或在笔记本中设置这个应用程序参数。在 Amazon EMR 中,您可以在创建 Spark 集群的基础设施时附加一个配置文件,从而使用这个公式spark.default.parallelism = spark.executor.instances * spark.executors.cores * 2 (or 3)实现更多的并行性。回顾一下,spark.executor.instances属性是跨工作节点的 JVM 容器的总数。每个执行器都有一个通过spark.executor.cores属性设置的通用固定数量的分配内部内核。
【核心】也被称为【插槽】或【线程】,负责并行执行 Spark 【任务】,这些任务被映射到 Spark 【分区】,也被称为【文件中的数据块】。
这里是官方的 Apache Spark 文档 解释了许多属性。
2d。)新数据帧的分区值将取决于哪个整数值更大:(默认并行度乘以乘数)或(大约。数据帧内存大小除以近似值。所需分区大小。
2e。)为了进行演示,缓存的数据帧大约为 3,000 mb,所需的分区大小为 128 mb。在本例中,计算出的分区大小 (3,000 除以 128=~23) 大于默认的并行度乘数 (8 乘以 2=16) ,因此选择值 23 作为重新分区的数据帧的新分区计数。
2f。)最后,我们查看一些示例输出分区,可以看到正好有 23 个文件( part-00000 到 part-00022 ),每个文件的大小大约为 127 mb (~127,000,000 字节=~127 mb),这接近于设置的 128 mb 目标大小,并且在优化的 50 到 200 mb 建议范围内。在所有分区中使用相同的优化文件大小解决了损害数据湖管理、存储成本和分析 I/O 性能的“小且倾斜的文件”问题。替代方法还包括按列对数据进行分区。例如,文件夹层级(即年/月/日)每天包含 1 个合并分区。具体的最佳实践会有所不同,取决于用例需求、数据量和数据结构。
ls /blogs/optimized/airlines.parquet/

作者图片
结论
从长远来看,希望您能看到像spark.sql.shuffle.partitions和spark.default.parallelism这样的 Spark 属性对您的 Spark 应用程序的性能有重大影响。在跨许多 Spark 工作节点处理大型数据集时,对这些 Spark 属性进行相应的调整以优化输出数量和分区大小至关重要。
总之,在构建高可用性和容错数据湖、弹性机器学习管道、经济高效的云计算和存储节省,以及用于生成可重用的精选特征工程库的最佳 I/O 时,这些 Spark 技术在许多场合对我有用。但是,它们可能是也可能不是 Spark 社区中的官方最佳实践。好处可能取决于您的使用案例。此外,探索这些不同类型的调优、优化和性能技术具有巨大的价值,将帮助您更好地理解 Spark 的内部。对于持续学习、解决现实世界的问题和交付解决方案来说,创造力是开源软件和云计算最棒的事情之一。感谢你阅读这篇博客。
带 JinjaSql 的 Python 中的高级 SQL 模板
使用 Python 函数、循环和可变预设增强您的 SQL 模板。

在Python 中模板化 SQL 查询的简单方法中,我使用 JinjaSql 介绍了 Python 中 SQL 模板的基础知识。这篇文章使用预置、循环和自定义函数进一步展示了 JinjaSql 模板中的 Jinja2 的强大功能。让我们考虑一个日常用例,当我们有一个包含一些维度和一些数值的表,并且我们想要找到给定维度或维度组合的一些指标。下面的示例数据很小,而且完全是虚构的,但它足以演示高级功能。首先,我介绍数据集和 SQL 查询要回答的问题。然后,我将构建没有模板的查询,最后,展示如何使用 SQL 模板来参数化和生成这些查询。
示例数据集
让我们考虑一个包含一些商店购物记录的表transactions。购买可以通过现金、信用卡或借记卡进行,这为数据增加了额外的维度。下面是创建和填充该表的代码。
**create** **table** transactions (
transaction_id **int**,
user_id **int**,
transaction_date **date**,
store_id **int**,
payment_method **varchar**(10),
amount **float**
)
;**insert** **into** transactions
(transaction_id, user_id, transaction_date, store_id, payment_method, amount)
**values**
(1, 1234, ‘2019–03–02’, 1, 'cash', 5.25),
(1, 1234, ‘2019–03–01’, 1, 'credit', 10.75),
(1, 1234, ‘2019–03–02’, 2, 'cash', 25.50),
(1, 1234, ‘2019–03–03’, 2, 'credit', 17.00),
(1, 4321, ‘2019–03–01’, 2, 'cash', 20.00),
(1, 4321, ‘2019–03–02’, 2, 'debit', 30.00),
(1, 4321, ‘2019–03–03’, 1, 'cash', 3.00)
;
要计算的指标
在研究一个数据集时,通常会查看所有维度的主要性能指标。在本例中,我们希望计算以下指标:
- 交易数量
- 平均交易金额
- 交易总额
我们需要每个用户、商店和支付方式的这些指标。我们还想通过商店和支付方式来了解这些指标。
单一维度的模板
获取每个商店指标的查询是:
**select**
store_id
, count(*) **as** num_transactions
, sum(amount) **as** total_amount
, avg(amount) **as** avg_amount
**from**
transactions
**group** **by**
store_id
**order** **by** total_amount **desc**
为了获得其他维度的相同指标,我们只需将select和group by子句中的store_id改为user_id或payment_method。因此 JinjaSql 模板可能看起来像
_BASIC_STATS_TEMPLATE = '''
**select**
{{ dim | sqlsafe }}
, count(*) **as** num_transactions
, sum(amount) **as** total_amount
, avg(amount) **as** avg_amount
**from**
transactions
**group** **by**
{{ dim | sqlsafe }}
**order** **by** total_amount **desc**
'''
为了从 JinjaSql 模板生成 SQL,我们将使用 GitHub 上的 sql_tempates_base.py 中可用的apply_sql_template函数,这里介绍的是。为了生成带有payment_method维度参数的 SQL 查询,我们按如下方式调用这个函数。
params = {
'dim': 'payment_method'
}
sql = apply_sql_template(_BASIC_STATS_TEMPLATE, params)
上面的模板适用于单个维度,但是如果我们有多个维度呢?要生成适用于任意数量维度的通用查询,让我们创建一个函数的框架,该框架将维度列名列表作为参数,并返回 SQL。
**def** get_basic_stats_sql(dimensions):
'''
Returns the sql computing the number of transactions,
as well as the total and the average transaction amounts
for the provided list of column names as dimensions.
'''
# TODO: construct params
**return** apply_sql_template(_BASIC_STATS_TEMPLATE, params)
本质上,我们希望将列名列表(如['payment_method']或['store_id', 'payment_method'])转换成包含列名的单个字符串,以逗号分隔的列表形式。这里我们有一些选项,因为它既可以在 Python 中完成,也可以在模板中完成。
传递在模板外部生成的字符串
第一个选项是在将字符串传递给模板之前生成逗号分隔的字符串。我们可以简单地将列表中的成员连接在一起:
**def** get_basic_stats_sql(dimensions):
'''
Returns the sql computing the number of transactions,
as well as the total and the average transaction amounts
for the provided list of column names as dimensions.
'''
params = {
'dim': '\n , '.join(dimensions)
}
**return** apply_sql_template(_BASIC_STATS_TEMPLATE, params)
碰巧模板参数dim在正确的位置,所以结果查询是
>>> print(get_basic_stats_sql(['store_id', 'payment_method']))
**select**
store_id
, payment_method
, count(*) **as** num_transactions
, sum(amount) **as** total_amount
, avg(amount) **as** avg_amount
**from**
transactions
**group** **by**
store_id
, payment_method
**order** **by** total_amount **desc**
现在,我们可以使用
dimension_lists = [
['user_id'],
['store_id'],
['payment_method'],
['store_id', 'payment_method'],
]dimension_queries = [get_basic_stats_sql(dims) **for** dims **in** dimension_lists]
模板中的预设变量
除了将预构建的字符串作为模板参数传递之外,还有一种方法是通过在顶部设置一个新变量,将列列表 SQL 生成移到模板本身中:
_PRESET_VAR_STATS_TEMPLATE = '''
{% **set** dims = '\n , '.join(dimensions) %}
**select**
{{ dims | sqlsafe }}
, count(*) **as** num_transactions
, sum(amount) **as** total_amount
, avg(amount) **as** avg_amount
**from**
transactions
**group** **by**
{{ dims | sqlsafe }}
**order** **by** total_amount **desc**
'''
这个模板比以前的版本可读性更好,因为所有的转换都发生在模板中的一个地方,同时也没有混乱。该功能应更改为
**def** get_stats_sql(dimensions):
'''
Returns the sql computing the number of transactions,
as well as the total and the average transaction amounts
for the provided list of column names as dimensions.
'''
params = {
'dimensions': dimensions
}
**return** apply_sql_template(_PRESET_VAR_STATS_TEMPLATE, params)
模板内的循环
我们也可以在模板中使用循环来生成列。
_LOOPS_STATS_TEMPLATE = '''
**select**
{{ dimensions[0] | sqlsafe }}\
{% **for** dim **in** dimensions[1:] %}
, {{ dim | sqlsafe }}{% **endfor** %}
, count(*) **as** num_transactions
, sum(amount) **as** total_amount
, avg(amount) **as** avg_amount
**from**
transactions
**group** **by**
{{ dimensions[0] | sqlsafe }}\
{% **for** dim **in** dimensions[1:] %}
, {{ dim | sqlsafe }}{% **endfor** %}
**order** **by** total_amount **desc**
'''
这个例子可能不是循环的最佳用途,因为一个预置变量可以很好地完成工作,而没有额外的复杂性。然而,循环是一个强大的构造,特别是当循环中有额外的逻辑时,比如条件({% if ... %} — {% endif %})或嵌套循环。
那么上面的模板中发生了什么呢?列表的第一个元素dimensions[0]是独立的,因为它不需要在列名前面加逗号。如果查询中有一个定义好的第一列,我们就不需要它了,for 循环看起来就像
{% **for** dim **in** dimensions %}
, {{ dim | sqlsafe }}
{% **endfor** %}
然后,for 循环结构遍历剩余的元素dimensions[1:]。同样的代码出现在group by子句中,这也是不理想的,只是为了显示循环功能。
有人可能想知道为什么循环的格式如此奇怪。原因是 SQL 模板的流元素,比如{% endfor %},如果它们出现在单独的行上,就会生成一个空行。为了避免这种情况,在上面的模板中,{% for ... %}和{% endfor %}在技术上与前面的代码在同一行上(因此在第一个列名后面有反斜杠\)。当然,SQL 不关心空白,但是阅读 SQL 的人可能(也应该)关心空白。除了与模板中的格式进行斗争之外,还可以在打印或记录查询之前去掉生成的查询中的空行。为此,一个有用的功能是
**import** os**def** strip_blank_lines(text):
'''
Removes blank lines from the text, including those containing only spaces.
[https://stackoverflow.com/questions/1140958/whats-a-quick-one-liner-to-remove-empty-lines-from-a-python-string](https://stackoverflow.com/questions/1140958/whats-a-quick-one-liner-to-remove-empty-lines-from-a-python-string)
'''
**return** os.linesep.join([s **for** s **in** text.splitlines() **if** s.strip()])
格式更好的模板就变成了
_LOOPS_STATS_TEMPLATE = '''
**select**
{{ dimensions[0] | sqlsafe }}
{% **for** dim **in** dimensions[1:] %}
, {{ dim | sqlsafe }}
{% **endfor** %}
, count(*) **as** num_transactions
, sum(amount) **as** total_amount
, avg(amount) **as** avg_amount
**from**
transactions
**group** **by**
{{ dimensions[0] | sqlsafe }}
{% **for** dim **in** dimensions[1:] %}
, {{ dim | sqlsafe }}
{% **endfor** %}
**order** **by** total_amount **desc**
'''
打印查询的调用是:
print(strip_blank_lines(get_loops_stats_sql(['store_id', 'payment_method'])))
到目前为止,所有的 SQL 模板都使用维度列表来产生完全相同的查询。
在字典上循环的自定义维度
在上面的循环例子中,我们看到了如何遍历一个列表。也可以迭代一个字典。这很方便,例如,当我们想要别名或转换形成维度的部分或全部列时。假设我们想将借记卡和信用卡合并为一个值,并将其与现金交易进行比较。我们可以通过首先创建一个字典来定义payment_method 的转换并保持store_id不变来实现。
custom_dimensions = {
'store_id': 'store_id',
'card_or_cash': "case when payment_method = 'cash' then 'cash' else 'card' end",
}
这里,credit和debit值都被替换为card。然后,该模板可能如下所示:
_CUSTOM_STATS_TEMPLATE = '''
{% **set** dims = '\n , '.join(dimensions.keys()) %}
**select**
sum(amount) **as** total_amount
{% **for** dim, def **in** dimensions.items() %}
, {{ def | sqlsafe }} **as** {{ dim | sqlsafe }}
{% endfor %}
, count(*) **as** num_transactions
, avg(amount) **as** avg_amount
**from**
transactions
**group** **by**
{{ dims | sqlsafe }}
**order** **by** total_amount **desc**
'''
注意,我将total_amount作为第一列,只是为了简化这个例子,避免单独处理循环中的第一个元素。另外,请注意,group by子句使用了一个预置变量,并且不同于 select 查询中的代码,因为它只列出了生成的列的名称。产生的 SQL 查询是:
>>> print(strip_blank_lines(
... apply_sql_template(template=_CUSTOM_STATS_TEMPLATE,
... parameters={'dimensions': custom_dimensions})))**select**
sum(amount) **as** total_amount
, store_id **as** store_id
, **case** **when** payment_method = 'cash' **then** 'cash' **else** 'card' **end** **as** card_or_cash
, count(*) **as** num_transactions
, avg(amount) **as** avg_amount
**from**
transactions
**group** **by**
store_id
, card_or_cash
**order** **by** total_amount **desc**
从 JinjaSql 模板中调用定制 Python 函数
如果我们想用 Python 函数生成一部分代码呢?Jinja2 允许用户注册自定义函数和其他包中的函数,以便在 SQL 模板中使用。让我们从定义一个函数开始,该函数生成我们插入到 SQL 中的字符串,用于转换定制维度。
**def** transform_dimensions(dimensions: dict) -> str:
'''
Generate SQL for aliasing or transforming the dimension columns.
'''
**return** '\n , '.join([
'{val} as {key}'.format(val=val, key=key)
**for** key, val **in** dimensions.items()
])
这个函数的输出是我们期望出现在select子句中的内容:
>>> print(transform_dimensions(custom_dimensions))
store_id **as** store_id
, **case** **when** payment_method = 'cash' **then** 'cash' **else** 'card' **end** **as** card_or_cash
现在我们需要用 Jinja2 注册这个函数。为此,我们将修改前面博客中的函数,如下所示。
**from** jinjasql **import** JinjaSql**def** apply_sql_template(template, parameters, func_list=None):
'''
Apply a JinjaSql template (string) substituting parameters (dict) and return
the final SQL. Use the func_list to pass any functions called from the template.
'''
j = JinjaSql(param_style='pyformat')
**if** func_list:
**for** func **in** func_list:
j.env.globals[func.__name__] = func
query, bind_params = j.prepare_query(template, parameters)
**return** get_sql_from_template(query, bind_params)
这个版本有一个额外的可选参数func_list,它需要是函数的一个list。
让我们改变模板来利用transform_dimensions功能。
_FUNCTION_STATS_TEMPLATE = '''
{% **set** dims = ‘\n , ‘.join(dimensions.keys()) %}
**select**
{{ transform_dimensions(dimensions) | sqlsafe }}
, sum(amount) **as** total_amount
, count(*) **as** num_transactions
, avg(amount) **as** avg_amount
**from**
transactions
**group** **by**
{{ dims | sqlsafe }}
**order** **by** total_amount **desc**
'''
现在我们也不需要担心第一列没有逗号。下面的调用产生一个类似于上一节的 SQL 查询。
>>> print(strip_blank_lines(
... apply_sql_template(template=_FUNCTION_STATS_TEMPLATE,
... parameters={‘dimensions’: custom_dimensions},
... func_list=[transform_dimensions])))**select**
store_id **as** store_id
, **case** **when** payment_method = 'cash' **then** 'cash' **else** 'card' **end** **as** card_or_cash
, sum(amount) **as** total_amount
, count(*) **as** num_transactions
, avg(amount) **as** avg_amount
**from**
transactions
**group** **by**
store_id
, card_or_cash
**order** **by** total_amount **desc**
注意我们如何将transform_dimensions作为一个列表[transform_dimensions]传递给apply_sql_template。可以将多个函数作为函数列表传递给 SQL 模板,例如[func1, func2]。
结论
本教程详细介绍了 JinjaSql 的基本用法。它演示了在 JinjaSql 模板中使用预置变量、列表和字典循环以及定制 Python 函数来生成高级 Sql 代码。特别是在apply_sql_template函数中添加了自定义函数注册,使得模板更加强大和通用。参数化 SQL 查询对于自动生成报告和减少需要维护的 SQL 代码量仍然是不可或缺的。一个额外的好处是,使用可重用的 SQL 代码片段,使用标准的 Python 单元测试技术来验证生成的 SQL 是正确的变得更加容易。
本帖中的代码是在 MIT 许可下授权的。这篇文章最初出现在 Life Around Data 博客上。
谢尔盖·伊兹拉列夫拍摄的照片
您需要开始使用的高级 SQLAlchemy 功能
通过 SQLAlchemy 及其混合属性、嵌套查询、表元数据、方言等等,在 Python 中使用 SQL 变得很容易!
如果您是 Python 开发人员,并且使用 SQL 数据库,那么 SQLAlchemy 很可能是您熟悉的库。这是一个强大而灵活的工具包,用于在 Python 中使用 SQL,具有很多特性。像 ORM 和基本查询这样的一些特性是众所周知的,但是有相当多的特性你可能不知道,并且绝对应该加以利用。因此,让我们看看如何利用混合属性、嵌套查询、表元数据、方言等等!

西蒙·维亚尼在 Unsplash 上的原始照片
列属性
让我们从简单的开始。我认为您可能希望基于其他列创建映射属性是很常见的——本质上是创建计算列。最简单的例子是字符串串联:
这很好,但是当我们使用 SQL 表达式来创建这样的属性时,它更有用:
对于上面的例子,我们增加了一些代码。我们创建了与User有多对一关系的CreditCard类。这个用户——在第一个例子的列和属性之上——还有一个名为has_credit_card的列属性,它是通过检查带有用户 ID 的信用卡是否存在来计算的。
使用该特性时,有一点需要注意,即在提交会话之前不会填充列属性,这在处理新创建的记录时可能是意外的:
混合属性
继续上一个技巧,让我也向您展示一下混合属性。它们类似于列属性,因为它们产生计算属性。然而,混合属性从实例级的 Python 表达式和类级的 SQL 表达式中产生值。有点困惑?好吧,让我们看一个例子:
为了展示hybrid_property的能力,我们实现了User和Order之间的简单关系,其中每个用户都有一个包含.state的订单列表——在这种情况下,要么是待定要么是完成。现在,如果我们想知道用户是否有任何未决的订单,我们需要考虑两种情况——如果我们正在处理已经加载到 Python 对象中的行,那么我们可以只使用 Python 表达式并产生 Python 值(has_pending_orders(self))。另一方面,如果我们直接从数据库中查询这些信息,我们不能使用 Python 表达式,因为数据库引擎不能理解它。因此,对于这种情况(has_pending_orders(cls)),我们编写 SQL 表达式,可以针对数据库运行。
顺便提一下——如果 Python 和 SQL 评估的表达式相同,那么可以省略用.expression修饰的第二个函数,SQLAlchemy 将在两种情况下使用第一个函数。
混合蛋白
我最喜欢的特性之一是混合类。Mixins 不仅仅是 SQLAlchemy 特有的东西,但是它们在与 ORM 模型结合时特别有用。您经常会遇到这样的情况,您有多个类(模型)需要相同的属性或相同的classmethod。下面的User模型就是这样一个例子:
在这个例子中,我们有 2 个 Mixin 类,它们是User模型继承的。首先- MixinAsDict提供了方法as_dict(self),可以用来获得模型的dict表示。另一个MixinGetByUsername既提供了username列,也提供了通过用户名查询用户的静态方法。
将这些函数定义为 Mixins 允许我们重用它们,并将它们添加到其他模型中,而无需到处复制粘贴相同的代码。
如果你不想自己写所有的mixin,那么你可以看看https://github.com/absent1706/sqlalchemy-mixins,它是一个常见 SQLAlchemymixin的集合。
使用元数据
有时,您可能需要访问表的列名,检查表上的约束,或者检查列是否可为空。所有这些都可以用MetaData()类来完成:
这里重要的部分是代码片段底部的print语句。它们中的每一个都演示了一些可以通过元数据对象访问的东西。这包括表名、列名、列类型、外键和主键以及其他约束。
配置表格
一些数据库表可能需要更多的初始设置。例如,您可能希望包含一些检查约束、索引或指定不同的模式:
所有这些都可以使用__table_args__ class 属性进行配置。这里,我们为 ID 列和外键约束设置了 2 个检查约束,1 个索引。我们还打开了自动表扩展,这意味着如果我们在这个表创建之后向它添加列,那么它将被自动添加。最后,我们还指定这个表属于哪个模式。
使用习惯方言
每个数据库引擎都有一些您可能想要利用的自定义功能。对我来说——作为一个 PostgreSQL 用户——我想使用 PostgreSQL 的一些自定义列类型。那么如何将它们与 SQLAlchemy 结合使用呢?
上面的代码显示了一个具有 PostgreSQL UUID、INT4RANGE、NUMRANGE、JSON和ARRAY列的Example表。所有这些和更多的都可以从sqlalchemy.dialects.postgresql导入。
创建包含这些类型值的行是不言自明的。但是在查询它们时,您需要使用方言和类型特定的比较器,如上面 PostgreSQL ARRAY类型和.contains比较器所示。
对于像JSON这样的其他类型,你也许可以将它们作为文本进行比较(使用.astext)。
为了让您在创建这些查询时更轻松,我建议在创建引擎时设置echo=True,这将使 SQLAchemy 将所有 SQL 查询打印到控制台中,以便您可以检查您的代码是否实际生成了正确的查询。
所有的方言、它们的类型和比较者都记录在https://docs.sqlalchemy.org/en/13/dialects/中。
使用 PostgreSQL 进行全文搜索
当谈到 PostgreSQL 特性时。用tsqeury和tsvector进行全文搜索呢?我们也可以用 SQLAchemy 做到这一点:
我们再次为全文搜索创建了 Mixin 类,因为这是很多模型都可以使用的。这个 Mixin 有单一的静态方法,它采用搜索字符串和列在(field)中进行搜索。为了进行实际的搜索,我们使用了func.to_tsvector,我们将语言和对表列的引用传递给它。在这一点上,我们链接对.match函数的调用,它实际上是对 PostgreSQL 中的to_tsquery的调用,我们给它搜索字符串和搜索配置作为参数。
从生成的 SQL 中,我们可以看到 Python 代码确实生成了正确的 SQL 查询。
跟踪行的上次更新
创建created_at或updated_at列是很常见的做法。这可以通过 SQLAlchemy 非常简单地完成:
对于updated_at,您只需要将onupdate设置为func.now(),这将使得每次更新行时,该列将被设置为当前时间戳。对于created_at列,您可以省略onupdate参数,而使用server_default来设置创建行时调用的函数。
自引用表
在数据库中有递归/自引用关系并不罕见——无论是经理- >员工关系、树结构还是一些物化路径。这篇技巧展示了如何使用 SQLAlchemy 建立这种关系:
对于本例,我们使用使用Node记录创建的树形结构。每个节点都有一些data,引用它的父节点和它的子节点列表。作为一种方便的方法,我们也包括了__str__和__repr__来帮助我们更好的可视化树。
如果你对普通的一对多关系没有意见,那么你可以用同样的方式处理任何非自指关系。然而,为了使其适用于双向关系,您还需要包括如上所示的带有remote_side=[id]的backref。
用 Flask 绑定多个数据库
最后一个是给所有烧瓶用户的。如果您需要连接到多个数据库—例如,由于多个地理位置或多个数据源—那么您可以使用SQLALCHEMY_BINDS来指定额外的数据库绑定:
在上面的代码片段中,我们通过设置SQLALCHEMY_DATABASE_URI和SQLALCHEMY_BINDS中的替代绑定来配置默认数据库。有了这个配置,我们就可以使用上述所有数据库。接下来,我们设置一个表的__bind_key__来引用其中一个绑定,这样每当我们与这个特定的表交互时,SQLAlchemy 就会知道要连接到哪个数据库。
但是,如果您需要连接到具有相同表/模式的多个数据库,您可以使用多个引擎和会话——每个数据库一个,并根据需要在它们之间切换,如下所示:
结论
希望这里显示的这些提示和技巧中至少有一些对您有用,并且在您下次需要使用 SQLAlchemy 时会让您的生活稍微轻松一点。这篇文章绝对不是你可以用 SQLAlchemy 做的所有酷事情的详尽列表,你可以通过滚动 SQLAlchemy API 参考找到一堆有用的东西。
本文最初发布于martinheinz . dev
[## 你可以用 GitHub API 和 Python 做的所有事情
GitHub REST API 允许您管理问题、分支、回购、提交等等,所以让我们看看您如何使用…
towardsdatascience.com](/all-the-things-you-can-do-with-github-api-and-python-f01790fca131) [## Python 调试终极指南
让我们探索使用 Python 日志记录、回溯、装饰器等等进行调试的艺术…
towardsdatascience.com](/ultimate-guide-to-python-debugging-854dea731e1b) [## 自动化 Python 项目的各个方面
每个 Python 项目都可以从使用 Makefile、优化的 Docker 映像、配置良好的 CI/CD、代码…
towardsdatascience.com](/automating-every-aspect-of-your-python-project-6517336af9da)
高级 Streamlit 缓存

图片来自 Sasin Tipchai 来自 Pixabay
缓存=更好的用户体验
现在,如何使用 Streamlit 创建 web 应用程序非常简单,但是它还不允许您做很多事情。我最近面临的一个主要问题是关于缓存的,当时我试图使用一个新闻 API 在 Streamlit 中创建一个分析新闻仪表板。
问题是我经常点击新闻 API,并且已经达到了免费 API 的极限。此外,每次用户刷新应用程序时运行新闻 API 变得相当慢。
解决这个问题的方法是缓存 API 数据。但是当我使用@st.cache decorator 时,页面不会刷新,因为 API 调用的参数保持不变。
这也是我开始理解 Streamlit 在缓存方面的局限性的原因。
因此,简而言之,我想要的是一种不会在每次页面刷新时都点击 API 的方法。与此同时,由于我正在获取新闻数据,我还希望每隔 5 分钟访问一次 API。
这是我完成这项工作的简单方法。
更新:
在昨天刚刚出来的 0.57.0 新发行说明中,streamlit 对st.cache进行了更新。这个版本的一个显著变化是“能够通过设置max_entries和ttl参数来设置缓存函数的到期选项”。来自文档:
- max_entries ( int 或 None ) —保留在缓存中的最大条目数,或者对于无界缓存为 None。(当一个新条目被添加到满缓存时,最旧的缓存条目将被删除。)默认为无。
- TTL(float or None)—将条目保留在缓存中的最大秒数,如果缓存条目不应过期,则为 None。默认值为无。
这可能有所帮助的两个用例是:
- 如果您正在为您的应用程序提供服务,并且不希望缓存永远增长。
- 如果您有一个从 URL 读取实时数据的缓存函数,并且应该每隔几个小时清除一次以获取最新数据
所以现在你需要做的就是:
[@st](http://twitter.com/st).cache(ttl=60*5,max_entries=20)
def hit_news_api(country, n):
# hit_api
事情变化之快真是令人难以置信。
在我开始之前,这里有一个关于 streamlit 的教程,如果你不理解这篇文章的话。
[## 如何为数据科学家使用简单的 Python 编写 Web 应用?
无需了解任何 web 框架,即可轻松将您的数据科学项目转换为酷炫的应用程序
towardsdatascience.com](/how-to-write-web-apps-using-simple-python-for-data-scientists-a227a1a01582)
简化缓存基础知识:
当我们用 streamlit 的缓存装饰器@st.cache标记一个函数时,无论何时调用该函数,Streamlit 都会检查调用该函数时使用的输入参数。后端发生的事情是,当一个函数用@st.cache streamlit 修饰时,它将函数的所有状态保存在内存中。
例如,如果我们有一个简单的 streamlit 应用程序,如下所示:
**import** **streamlit** **as** **st**
**import** **time****def** expensive_computation(a, b):
time.sleep(2) *# 👈 This makes the function take 2s to run*
**return** a * ba = 2
b = 21
res = expensive_computation(a, b)
st.write("Result:", res)
当我们刷新应用程序时,我们会注意到expensive_computation(a, b)在每次应用程序运行时都会被重新执行。这对用户来说不是一个很好的体验。
现在,如果我们添加[@st.cache](https://docs.streamlit.io/api.html#streamlit.cache)装饰器:
**import** **streamlit** **as** **st**
**import** **time**@st.cache *# 👈 Added this*
**def** expensive_computation(a, b):
time.sleep(2) *# This makes the function take 2s to run*
**return** a * ba = 2
b = 21
res = expensive_computation(a, b)
st.write("Result:", res)
因为参数a和b的结果已经被缓存,所以expensive_computation不会在每次用户刷新页面时再次运行。这将带来更好的用户体验。
最小示例

罗马卡夫在 Unsplash 上拍摄的照片
那么如果我想执行一个函数,如果页面在设定的时间段后刷新了呢? 也就是说,缓存的函数已经有一段时间没有运行了,结果需要更新。
为了理解这一点,让我们创建一个基本的例子。在这个例子中,我们的函数采用一个参数n和一个参数 country,并返回该国家的前 n 条新闻。
在这个最小的例子中,它类似于返回一个随机数列表。我们希望在接下来的 5 分钟内继续向我们的用户显示这个列表。如果用户在 5 分钟后刷新页面,我们希望列表被刷新。这非常类似于点击新闻 API。
所以我们的基本应用程序代码看起来像这样:
import streamlit as st
import randomdef hit_news_api(country, n):
st.write("Cache Miss for n:",n)
return [random.randint(0,1000) for i in range(n)]results = hit_news_api("USA", 5)
st.write(results)
这个应用程序看起来像:

现在,每次我刷新页面,函数hit_news_api都会被再次调用,这意味着随着用户数量的增加,我们将达到 API 的极限。那么我们如何解决这个问题呢?
我们可以使用缓存。没错。所以让我们看看如果我们缓存hit_news_api函数会发生什么。
import streamlit as st
import random[@st](http://twitter.com/st).cache
def hit_news_api(country, n):
st.write("Cache Miss for n:",n)
return [random.randint(0,1000) for i in range(n)]results = hit_news_api("USA", 5)
st.write(results)
现在的问题是,如果 API 参数保持不变,我们的仪表板在点击一次新闻 API 后就再也不会调用它了。我们看到同一组参数的静态结果是永恒的。我们做什么呢
想法 1 —虚拟时间变量
我们可以使用这种方法——向每五分钟/十分钟改变一次值的hit_news_api函数调用传递一个依赖于时间的伪参数。实现这一点的代码是:
在这里,truncate_time函数帮助我们将当前日期时间截断为该分钟最接近的最小除数。例如,给定dt_time=’2020–03–27 02:32:19.684443'和period = 5,函数返回‘2020–03–27 02:30:00.0’.
看看我们现在如何用截断的时间调用hit_news_api函数。现在,无论何时从dt_time=’2020–03–27 02:30:00.0' and dt_time=’2020–03–27 02:34:59.99999'开始调用hit_news_api函数,函数调用的参数都保持不变,因此我们不会一次又一次地调用 API。正是我们想要的!
想法 2-刷新/清除缓存

清理缓存。去飞溅
这一切都很好,但是您能发现这种方法的问题吗?缓存大小将随着时间的推移而增长。这意味着我们需要定期手动清除缓存。我们如何自动化缓存清除过程?
这是一个非常简单的方法。我们可以在代码顶部使用下面的代码,在一天的时间内清除整个缓存。
from streamlit import caching
from datetime import datedef cache_clear_dt(dummy):
clear_dt = date.today()
return clear_dtif cache_clear_dt("dummy")<date.today():
caching.clear_cache()
最终应用代码
这是上面所有功能的整个应用程序的外观。
结论
Streamlit 使创建应用程序的整个过程民主化了,我不能再推荐它了。
然而,有些事情我们需要绕道而行。在这个令人敬畏的平台上,我仍然喜欢拥有很多东西。我已经与 Streamlit 团队就他们将要引入的新功能进行了讨论,我将尽力让您了解最新情况。
你可以在我的 Github repo 上找到最终应用的完整代码。
如果你想了解创建可视化的最佳策略,我想从密歇根大学调用一门关于 数据可视化和应用绘图 的优秀课程,它是一个非常好的 数据科学专业的一部分,本身带有 Python 。一定要去看看。
谢谢你的阅读。将来我也会写更多初学者友好的帖子。在 媒体 关注我,或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。
此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。
高级 Tensorflow 数据输入管道:处理时间序列
提取标签、多变量序列窗口、多个 TF 记录文件碎片和其他处理顺序数据的有用技巧

tf.data.Dataset API 是一个非常高效的管道构建器。时序任务的正确实现可能有点棘手。在本文中,我们将深入探讨常见任务:
- 窗口标记数据
- 通过前瞻设置未标记数据的窗口
- 分片 TF 记录文件提高效率和无数据丢失的技巧
我们开始吧!
窗口标记数据
有了数据集 api,这很容易做到。假设以下配置。输入特征为a,标签为b。
a, b
1, 0
2, 0
3, 1
4, 0
5, 0
6, 1
每一行都可以用一个张量形状的(2,)来描述。所以我们的数据集大小为(6, 2)。
现在,用一个窗口大小的2,产生训练数据。这看起来像是:
1, 2 -> 0 (label of row 2)
2, 3 -> 1 (label of row 3)
4, 5 -> 0 ...
.window()函数实际上产生了一组数据集。这就是为什么我们需要做一个.flat_map(batch)运算来得到一系列我们可以统一处理的张量。
通过前瞻设置未标记数据的窗口
有时你只想预测一个序列的下一个滴答。这可以在没有标签的情况下完成。对于输入数据集:
a
1
2
3
4
5
6
训练对将是(同样,窗口大小为2):
1, 2 -> 3
2, 3 -> 4
4, 5 -> 6
让我们尝试采用前面的方法,使用大小为3的窗口,保留最后一个元素作为标签。
数据丢失
实现这一点的最佳方法是创建 2 个类似的数据集管道,窗口大小为2,但其中一个管道滞后于前端。
分片 TF 记录文件提高效率和无数据丢失的技巧
大规模深度学习输入管道的典型方式是将输入数据分割成 1-100 兆字节范围内的文件,这些文件可以顺序和并行读取。这意味着,通过只使用旋转驱动器而不是固态硬盘来保持性能,存储服务器成本大幅降低。
这种做法的一个非常常见的例子是将 TF 记录存储在 Hadoop 文件系统或基于存储桶的公共云解决方案(如 Google Cloud Storage)中。
将 X-Y 对数据集(如图像)分割成多个文件是很简单的。对于手头的时间序列窗口任务,保持序列完整性和避免数据丢失变得很棘手。
让我们看一个简单的例子。
File 1
----------
a, b
1, 1
1, 2
1, 3File 2
----------
a, b
1, 4
1, 5
1, 6
1, 7
当然,你可以得到一个文件包,把它们加载起来,直接推给训练。但是你有很多问题。
首先,为了获得最佳性能,2+个碎片之间的顺序是不确定的。这意味着您的数据将无序,类似于位置不变的并行算法,如 map-reduce。
您最终将同时打开文件 1 的第 1 行和文件 2 的第 2 行,而另一个工人同时打开文件 1 的第 2 行和文件 2 的第 1 行。
故障部分现已修复。但是还有一个问题需要仔细检查。缺少跨文件数据。如果文件 2 是文件 1 的序列延续,您需要确保您的回顾窗口包括这两个文件之间的链接。否则,你会丢失数据点。
这意味着,当tf.data.Dataset解析分片文件时,为您的模型生成的最终数据集需要包括(让我们为 2 个窗口演示这一点):
(a)1,2 and (a)1,3 -> (b)1, 4
(a)1,3 and (b)1,4 -> (b)1, 5
当然,你可以删除这几个数据点。但是请记住,窗口越大,丢失的数据点就越多。根据数据的性质和大小,做出正确的决定。
如果您像我们在上面的窗口未标记数据中通过前瞻部分演示的那样强制执行纯顺序读取,您将不会从并行读取加速中受益。
简单而有效的解决方案是制作多个数据集,然后按 2 的顺序将它们连接起来。
结论
您甚至可以使用这种优化的管道在一个或多个 TPU 上用大量的时间序列数据进行训练。
通过实现本文中提到的技术,您可以避免常见的缺陷,如数据丢失和顺序完整性,从而为顺序数据创建高性能的管道。
恭喜你!你已经取得了时间序列卓越。
谢谢你一路看完!
用 ARMA 和 ARIMA 进行高级时间序列分析
理解并在 Python 中实现时间序列预测的 ARMA 和 ARIMA 模型

介绍
在之前的文章中,我们介绍了移动平均过程 MA(q) 和自回归过程 AR(p) 作为时间序列建模的两种方法。现在,我们将结合这两种方法,探索 ARMA(p,q)和 ARIMA(p,d,q)模型如何帮助我们对更复杂的时间序列进行建模和预测。
本文将涵盖以下主题:
- ARMA 模型
- ARIMA 模型
- 永盒试验
- 赤池信息标准(AIC)
到本文结束时,您应该能够熟练地用 Python 实现 ARMA 和 ARIMA 模型,并且您将有一个时间序列建模步骤的清单。
笔记本和数据集在这里是。
我们开始吧!
通过 Python 中的应用时间序列分析学习最新的时间序列分析技术。课程涵盖统计和深度学习模型,你将使用 Python 和 TensorFlow!
ARMA 模型
回想一下,阶为 p 的自回归过程定义为:

p 阶自回归过程
其中:
- p 是命令
- c 是常数
- ε:噪音
还记得移动平均过程 q 被定义为:

q 阶移动平均过程
其中:
- 问是命令
- c 是常数
- ε是噪音
那么,ARMA(p,q)就是将两个模型组合成一个方程:

(p,q)阶 ARMA 过程
因此,该模型可以解释随机噪声(移动平均部分)和前一步(自回归部分)的时间序列之间的关系。
让我们通过一些模拟来看看 ARMA(p,q)过程是如何表现的。
模拟和 ARMA(1,1)过程
让我们从一个简单的例子开始,一阶 ARMA 过程的移动平均和自回归部分。
首先,让我们导入本教程中需要的所有库:
from statsmodels.graphics.tsaplots import plot_pacf
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.tsa.arima_process import ArmaProcess
from statsmodels.stats.diagnostic import acorr_ljungbox
from statsmodels.tsa.statespace.sarimax import SARIMAX
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.stattools import pacf
from statsmodels.tsa.stattools import acf
from tqdm import tqdm_notebook
import matplotlib.pyplot as plt
import numpy as np
import pandas as pdimport warnings
warnings.filterwarnings('ignore')%matplotlib inline
然后,我们将模拟以下 ARMA 过程:

ARMA (1,1)过程
在代码中:
ar1 = np.array([1, 0.33])
ma1 = np.array([1, 0.9])simulated_ARMA_data = ArmaProcess(ar1, ma1).generate_sample(nsample=10000)
我们现在可以绘制前 200 个点,以可视化我们生成的时间序列:
plt.figure(figsize=[15, 7.5]); # Set dimensions for figure
plt.plot(simulated_ARMA_data)
plt.title("Simulated ARMA(1,1) Process")
plt.xlim([0, 200])
plt.show()
您应该得到类似于以下内容的内容:

模拟 ARMA(1,1)过程
然后,我们可以看看 ACF 和 PACF 的图:
plot_pacf(simulated_ARMA_data);
plot_acf(simulated_ARMA_data);

模拟 ARMA(1,1)过程的 PACF anf ACF 图
正如你所看到的,我们不能通过查看这些图来推断 ARMA 过程的顺序。事实上,仔细观察,我们可以在 ACF 和 PACF 函数中看到一些正弦曲线形状。这表明这两个过程都在起作用。
模拟 ARMA(2,2)过程
同样,我们可以模拟一个 ARMA(2,2)过程。在本例中,我们将模拟以下等式:

ARMA(2,2)过程
在代码中:
ar2 = np.array([1, 0.33, 0.5])
ma2 = np.array([1, 0.9, 0.3])simulated_ARMA2_data = ArmaProcess(ar1, ma1).generate_sample(nsample=10000)
然后,我们可以可视化模拟数据:
plt.figure(figsize=[15, 7.5]); # Set dimensions for figure
plt.plot(simulated_ARMA2_data)
plt.title("Simulated ARMA(2,2) Process")
plt.xlim([0, 200])
plt.show()

模拟 ARMA(2,2)过程
查看 ACF 和 PACF 图:
plot_pacf(simulated_ARMA2_data);
plot_acf(simulated_ARMA2_data);

ARMA(2,2)过程的 PACF 和 ACF
正如你所看到的,两条曲线显示了相同的正弦趋势,这进一步支持了 AR(p)过程和 MA(q)过程都在起作用的事实。
ARIMA 模型
ARIMA 代表一个极端的平均水平。
这个模型是自回归、移动平均模型和差分的组合。在这种情况下,整合是差异的反义词。
差分对于去除时间序列中的趋势并使其稳定是有用的。
它只是从时间 t 中减去点 a t-1 。因此,请意识到,如果应用一次差分,您将丢失时间序列中的第一个数据点。
数学上,ARIMA(p,d,q)现在需要三个参数:
- p:自回归过程的阶
- d:差异的程度(差异的次数)
- 问:移动平均线过程的顺序
并且方程表示为:

一般 ARIMA 过程
就像 ARMA 模型一样,ACF 和 PACF 不能用于确定 p 和 q 的可靠值。
然而,在存在 ARIMA(p,d,0)过程的情况下:
- ACF 呈指数衰减或正弦衰减
- PACF 在滞后 T21 时有一个显著的峰值,但之后就没有了
类似地,在存在 ARIMA(0,d,q)过程的情况下:
- PACF 呈指数衰减或正弦衰减
- ACF 在滞后q时有一个显著的尖峰,但在此之后没有
让我们看一个 ARIMA 的建模例子,获得一些实践经验,更好地理解一些建模概念。
项目—为强生公司的季度每股收益建模
让我们重温一下之前分析过的数据集。该数据集用于显示 Yule-Walker 方程可以帮助我们估计 AR(p)过程的系数。
现在,我们将使用相同的数据集,但使用 ARIMA(p,d,q)模型对时间序列进行建模。
首先,我们导入数据集并显示前五行:
data = pd.read_csv('jj.csv')
data.head()

然后,让我们绘制整个数据集:
plt.figure(figsize=[15, 7.5]); # Set dimensions for figure
plt.scatter(data['date'], data['data'])
plt.title('Quarterly EPS for Johnson & Johnson')
plt.ylabel('EPS per share ($)')
plt.xlabel('Date')
plt.xticks(rotation=90)
plt.grid(True)
plt.show()

强生公司季度每股收益
正如你所看到的,在这个时间序列中既有趋势也有方差的变化。
让我们画出 ACF 和 PACF 函数:
plot_pacf(data['data']);
plot_acf(data['data']);

PACF 和 ACF
如您所见,没有办法确定 AR(p)流程或 MA(q)流程的正确顺序。
上面的图也清楚地表明了非平稳性。为了进一步证明这一点,让我们使用扩展的 Dicker-Fuller 测试:
# Augmented Dickey-Fuller testad_fuller_result = adfuller(data['data'])
print(f'ADF Statistic: {ad_fuller_result[0]}')
print(f'p-value: {ad_fuller_result[1]}')

这里,p 值大于 0.05,这意味着我们不能拒绝时间序列是非平稳的零假设。
因此,我们必须应用一些变换和一些差分来消除趋势和方差的变化。
因此我们将取时间序列的对数差。这相当于取每股收益的对数,然后应用一次差分。请注意,因为我们是差分一次,我们将摆脱第一个数据点。
# Take the log difference to make data stationarydata['data'] = np.log(data['data'])
data['data'] = data['data'].diff()
data = data.drop(data.index[0])
data.head()

现在,让我们绘制新转换的数据:
plt.figure(figsize=[15, 7.5]); # Set dimensions for figure
plt.plot(data['data'])
plt.title("Log Difference of Quarterly EPS for Johnson & Johnson")
plt.show()

强生公司季度每股收益的对数差异
趋势和方差的变化似乎被去除了,但是我们想确定情况确实如此。因此,我们再次应用扩展的 Dickey-Fuller 检验来检验平稳性。
# Augmented Dickey-Fuller testad_fuller_result = adfuller(data['data'])
print(f'ADF Statistic: {ad_fuller_result[0]}')
print(f'p-value: {ad_fuller_result[1]}')

这一次,p 值小于 0.05,我们拒绝零假设,假设时间序列是平稳的。
现在,让我们看看 PACF 和 ACF,看看我们是否可以估计其中一个过程的顺序。
plot_pacf(data['data']);
plot_acf(data['data']);

PACF 和 ACF
检查上面的 PACF,似乎有一个 3 阶或 4 阶的 AR 过程在起作用。然而,ACF 不提供信息,我们看到一些正弦曲线形状。
因此,我们如何确保为 AR(p)和 MA(q)过程选择正确的顺序呢?
我们需要尝试不同的订单组合,用这些订单拟合 ARIMA 模型,并使用订单选择标准。
这就把我们带到了 A 凯克的IinformationCriterion 或者 AIC 的话题。
赤池的信息标准(AIC)
这个标准对于选择 ARIMA 模型的阶(p,d,q)是有用的。AIC 表示为:

AIC 公式
其中 L 是数据的似然性, k 是参数的个数。
在实践中,我们选择与其他模型相比 AIC 最低的模型。
重要的是要注意,AIC 不能用于选择差分(d)的阶。差异数据将改变数据的可能性(L)。因此,不同阶差分模型的 AIC 是不可比的。
此外,请注意,由于我们选择了具有最低 AIC 的模型,更多的参数将增加 AIC 得分,从而惩罚该模型。虽然参数越多的模型性能越好,但 AIC 用于查找参数数量最少但仍能提供良好结果的模型。
关于 AIC 的最后一点说明是,它只能相对于其他模型使用。小的 AIC 值并不能保证模型在未加密的数据上有好的表现,也不能保证它的 SSE 很小。
现在我们知道了如何为 ARIMA 模型选择最佳订单,让我们编写一个函数来测试所有订单。
def optimize_ARIMA(order_list, exog):
"""
Return dataframe with parameters and corresponding AIC
order_list - list with (p, d, q) tuples
exog - the exogenous variable
"""
results = []
for order in tqdm_notebook(order_list):
try:
model = SARIMAX(exog, order=order).fit(disp=-1)
except:
continue
aic = model.aic
results.append([order, model.aic])
result_df = pd.DataFrame(results)
result_df.columns = ['(p, d, q)', 'AIC']
#Sort in ascending order, lower AIC is better
result_df = result_df.sort_values(by='AIC', ascending=True).reset_index(drop=True)
return result_df
上面的函数将产生一个数据框架,该框架将列出订单和相应的 AIC,从最上面的最佳型号开始。
我们将尝试阶数(p,q)范围从 0 到 8 的所有组合,但保持差分阶数等于 1。
ps = range(0, 8, 1)
d = 1
qs = range(0, 8, 1)# Create a list with all possible combination of parameters
parameters = product(ps, qs)
parameters_list = list(parameters)order_list = []for each in parameters_list:
each = list(each)
each.insert(1, 1)
each = tuple(each)
order_list.append(each)
result_df = optimize_ARIMA(order_list, exog=data['data'])result_df

一旦函数运行完毕,您应该会看到与最低 AIC 相关联的顺序是(3,1,3)。因此,这表明 ARIMA 模型具有 AR(3)过程和 MA(3)过程。
现在,我们可以打印出最佳模型的摘要,即 ARIMA (3,1,3)。
best_model = SARIMAX(data['data'], order=(3,1,3)).fit()
print(best_model.summary())

最佳 ARIMA 模式总结
从上面的总结中,我们可以看到所有系数的值及其相关的 p 值。请注意,根据 p 值,滞后 2 时 MA 过程的参数似乎不具有统计显著性。不过,让我们暂时把它保留在模型中。
因此,根据上表,时间序列可以建模为:

强生公司四季度每股收益的 ARIMA 模型
其中ε是方差为 0.0077 的噪声。
时间序列建模的最后一部分是研究残差。
理想情况下,残差将是白噪声,没有自相关。
测试这一点的一个好方法是使用永盒测试。请注意,该测试只能应用于残差。
# Ljung-Box test
ljung_box, p_value = acorr_ljungbox(best_model.resid)print(f'Ljung-Box test: {ljung_box[:10]}')
print(f'p-value: {p_value[:10]}')

这里,永盒检验的零假设是不存在自相关。看上面的 p 值,可以看到都在 0.05 以上。所以不能拒绝零假设,残差确实不相关。
我们可以通过绘制残差的 ACF 和 PACF 来进一步证明这一点。
plot_pacf(best_model.resid);
plot_acf(best_model.resid);

残差的 PACF 和 ACF
正如你所看到的,上面的图类似于白噪声。
因此,该模型可用于预测。
一般建模程序
无论何时面对时间序列,您都可以遵循以下一般程序:
- 绘制数据并识别不合理的观察结果。理解数据的模式。
- 应用转换或差异来移除趋势并稳定差异
- 测试平稳性。如果序列不是稳定的,应用另一个变换或差分。
- 画出 ACF 和 PACF 来估计 MA 或 AR 过程的顺序。
- 尝试不同的订单组合,选择 AIC 最低的型号。
- 检查残差,确保它们看起来像白噪声。应用永盒测试来确定。
- 计算预测。
结论
恭喜你!现在,您已经了解了什么是 ARMA 模型,以及如何使用非季节性 ARIMA 模型进行高级时间序列分析。你也有一个时间序列分析的路线图,你可以应用它来确保获得可能的最佳模型。
通过以下课程了解有关时间序列分析的更多信息:
干杯🍺
使用 Python 探索机器学习

弗兰基·查马基在 Unsplash 上拍摄的照片
近年来,机器学习引起了前所未有的关注。机器学习的一个吸引人的方面是它能够从原始数据中释放大量有用的信息,这些信息可以在许多商业和研究环境中驱动决策过程。例如,沃尔玛是使用机器学习来提高销售业绩的零售企业领导者之一。
[## 沃尔玛:利用大数据、机器学习、人工智能和物联网提升零售业绩
沃尔玛可能自 20 世纪 60 年代就已经存在,但在寻找新方法方面,该公司仍处于领先地位…
www.bernardmarr.com](https://www.bernardmarr.com/default.asp?contentID=1276)
虽然我们可能已经听说了许多关于机器学习应用的成功和令人兴奋的故事,但我们应该如何开始利用这项强大的技术呢?
好消息是,这不需要投入大量成本来开始构建机器学习应用程序。我们可以免费使用许多开源开发工具。我们所需要的只是一台能上网的个人电脑。在这篇文章中,我将分享一个使用开源 Python 库的机器学习的示例工作流。
什么是机器学习?

在我们讨论机器学习的技术方面之前,让我们回顾一下机器学习的概念,以确保我们意识到我们将要做的工作。
首先,机器学习不一定是为如上图所示的自主机器人编程的实践。让我们看看人工智能(AI)先驱亚瑟·塞缪尔(创造了“机器学习”这个术语的计算机科学家)给出的定义:
“机器学习是一个研究领域,它赋予计算机无需显式编程就能学习的能力”阿瑟·塞缪尔,1959
在机器环境中解释“学习”可能很棘手。有人可能会问,机器怎么可能“学习”?我们是不是在试图给我们的计算机 CPU 植入某种极其强大的芯片,使它能够像人一样思考?后一个问题的答案是一个简单的“不”。为了回答第一个问题,我将用一个非常简单的例子来说明如下的概念。

假设你是一名数据分析师,你的任务是创建一个模型,仅基于两个因素来预测单位面积的房价:地理位置和到最近的 MRT 的距离。你会得到一个房价数据集,其中还包括地理位置和到最近的捷运站的距离的详细信息。对数据集的第一印象可能会让你想到房价和地理位置+ MRT 距离之间可能存在相关性(见下文)。

显示房价和地理位置+到最近的 MRT 的距离之间的相关性的数据集片段
很明显,如果单位位于市区,离捷运较近,单位面积的房价就越来越高。此外,地理位置的因素比到最近的捷运站的距离具有更高的权重。此时,一个非常简单的模型可以表述如下:

预测房地产价值的简单模型
然而,问题是你如何确定 w1 和 w2 的值?一种方法是使用数据集通过反复调整 w1 和 w2 来训练机器学习模型,直到模型能够以期望的精度预测房地产价值。
简单地说,我们可以将机器学习模型视为黑盒机器,当它被输入数据集时,可以被调整以给出优化的预测输出。这个黑盒机器可以通过训练周期的循环来训练,以保持更新 w1 和 w2。当 w1 & w2 被优化以预期精度预测房地产价值时,黑匣子机器被认为是已学习的。

训练机器学习算法的简单说明
训练机器学习模型的一种常见方法是监督学习。在本文中,我将介绍监督学习方法。
亲自动手
现在,我们对机器学习有了一些想法,我们准备转向实用方面,开始训练机器学习模型。
1.目标
本项目的目标是对新店区的房价进行价值评估。台湾新北市。为了实现目标,我们将训练一个机器学习模型来预测房价。
2。数据集的采集
我们将使用可以从 UCL 机器学习库获得的房地产估价数据。房地产数据存储在 Excel 文件中。
一般来说,机器学习的数据来源主要有两个:1)我们自己的收集,2)公共数据。我们倾向于将公共数据用于学习或实验目的,因为这可以节省我们自己收集数据的大量时间。感谢数据科学社区的慷慨,我们可以很容易地从诸如 Kaggle 、 UCL 机器学习库、开放数据等网站获得公共数据,仅举几例。
3。设置机器学习工作空间
准备好原始数据后,我们可以开始设置我们的机器学习工作区。
3.1 硬件要求
我们不需要一台安装了 NVIDIA GPU 的高成本电脑来运行这个机器学习项目。配备 i5 或 i7 处理器和 8GB 内存的 PC 或 Mac 电脑足以满足这个简单项目的硬件要求。
3.2 软件要求
我们将为这个项目使用基于 Python 的机器学习和数据处理库,因此我们的计算机将准备好:
- python 3(https://www.python.org/)
- 熊猫(https://pandas.pydata.org/)
- https://matplotlib.org/
- 努皮(https://numpy.org/
- scikit-learn(https://scikit-learn.org/stable/)
- Jupyter 笔记本/ Jupyter 实验室https://jupyter.org/
获得所有这些 Python 库的最简单的方法是在我们的计算机上安装 Anaconda 包。Anaconda 在一个包中提供了大多数基于 Python 的机器学习和数据处理库。
4.探索数据
这对于我们在使用数据来训练我们的机器学习模型之前对数据有一个大致的了解是很重要的。为了探索我们的数据,我们将使用 Jupyter Notebook 作为我们的编辑器,并开始编写 Python 代码。
首先,我们可以创建一个笔记本,并使用熊猫来读取我们的房地产数据。(请注意我已经将 Excel 文件重命名为“Real _ estate _ data . xlsx”)。
从 Excel 文件中读取数据的代码片段
我们使用 Pandas head()和 info() 方法来快速浏览我们的数据。
查看前五条记录的代码片段

前五条记录
head() 方法显示前五条记录。
获取数据快速描述的代码片段

数据描述
Pandas info() 方法给了我们一个快速描述数据的方法。例如:
- 条目总数
- 总列数
- 每列中的数据类型
我们的房地产数据只有 414 个条目。这被认为是基于机器学习标准的非常小的数据集。然而,用它作为样本数据来启动一个简单的项目还是不错的。
这一点也值得强调,数据中的房价是以台币单位面积价格(新台币 $ )为基础的。
每列中的特征都是数字的。然而,并不是所有的特征都对训练机器学习模型有用。例如,第一列“No”只不过是一个记录索引。显然,它并没有显示出与房价有任何强相关性。因此,我们稍后将通过特性选择过程简单地过滤掉这个特性。
此外,我们的数据的许多列名太长,这将给使用 Pandas 提取单个列来分析它们带来一些困难。我们必须将这些列重命名为更简洁的名称,以简化我们的数据处理工作。

有问题的列名
5。预处理数据
在这个阶段,我们将再次使用 Python Pandas 库来过滤和清理我们的数据,然后才能将其用于训练我们的机器学习模型。
5.1 重命名列
我们通过重命名房地产数据中除“No”列之外的所有列名来开始我们的数据预处理步骤。为此,我们可以使用 Pandas rename() 方法。
重命名列的代码片段
要重命名列,我们只需创建一个列映射器, new_names (第 1–7 行)。我们将新的列名映射到原始名称,然后将整个列映射器设置为参数“columns”(第 9 行)。
接下来,我们再次使用 head() 方法来可视化前五条记录(第 10 行),我们将看到如下输出:

重命名的列
5.2 特征选择
如上所述,并非我们数据中的所有特征都将用于训练机器学习模型。只有那些与房价有良好相关性的特征才会被选择用于机器学习。此外,特征选择对于节省训练机器学习模型的计算成本和提高模型性能也很重要。
Pandas dataframe 提供了一种简便的方法, corr() ,来计算我们数据中存在的每一对特征之间的标准相关系数( Pearson's r )。
计算标准相关系数的代码片段

标准系数的结果
为了解释如上所示的结果,我们需要理解几个重要的事实:
- 相关系数的范围总是从-1 到 1
- 如果该值接近 1,则意味着特定的一对要素之间存在强正相关性(例如,conv 商店与房屋价格)
- 如果该值接近-1,则意味着在特定的一对要素(例如 dist_mrt vs house_price)之间存在一个强负相关性
- 如果该值接近 0,则意味着该特定特征对之间没有线性相关性(例如,No vs house_price)。

结果表明,特征【conv _ 商店】 和 dist_mrt 对房价的影响最大,因为它们分别具有最高的正相关性和负相关性。这个结果是有道理的,因为房价通常取决于周围设施的可用性。其中一个重要的设施是便利店。另一方面,当房地产远离公共交通服务时,房地产价值会大大降低(这就是为什么 dist_mrt 与 house_price 显示出强烈的负相关性)。

此外,我们不应该低估由特征 lat 和 lng 所代表的地理位置的影响。 lat 和 lng 的相关性分析表明,东北地区的房价往往更高。根据地理位置可视化房价分布的一种方法是使用 Python Matplotlib 库绘制散点图。
根据地理位置绘制房价分布散点图的代码片段

显示房价分布的散点图
散点图中的彩色地图显示,大多数高成本房地产集中在红圈区域。虽然并非所有高成本房地产都位于该地区,但仍显示出一种总体密度模式,即房地产价格往往高于其他地区。

此外,特征 房龄 也可以是影响房地产价格的一个重要因素,尽管这种影响比不上的 dist_mrt 和 conv_stores。

另一方面,特征 No 和 trans_date 显示与房价相关性差(接近于零)。
维度的诅咒
虽然数据集中至少有五个特征对训练我们的模型来说足够重要,但我们的数据集非常小,只有 414 个条目。根据 维数灾难 ,我们用来训练模型的特征越多,我们需要的数据集往往会呈指数级增长。总的来说,我们需要的数据集
1 特性= 10,
2 个特征= 10 * 10 = 100,
3 个特征= 10 * 10 * 10 = 1000 等等…
给定只有数百个条目的有限数据集,我们只能选择两个最相关的特征来训练我们的模型。于是,让我们挑选正负相关性最高的特征:conv _ 商店 和 dist_mrt。
简而言之,基于相关性分析的结果和对维数灾难的考虑,只选择两个特征作为机器学习的输入特征。
我们将使用 Pandas drop() 方法从数据集中删除特征 No、trans_date、lat、lng 和 house _ age**。此外,我们还需要从输入特性列表中排除“house_price”。
从原始数据集中删除列的代码段

用作输入要素的剩余列
5.3 数据转换
在这个阶段,我们已经完成了特征选择,但是我们还没有准备好使用输入特征来训练我们的模型。在开始训练我们的模型之前,仍然需要完成几个预处理步骤。
我们需要将我们的输入特征转换成一个 Numpy 数组。此外,我们还需要从原始数据集中提取“house_price”并将其用作输出特征或标签。输出要素也应该转换为 Numpy 数组。
要将输入要素和输出要素转换为 Numpy 数组,我们可以使用 Pandas 数据框值 属性。
将输入要素和输出要素转换为 Numpy 数组的代码片段
按照惯例,输入特征应存储在名为 X 的变量中,输出特征存储在名为 y 的变量中。
5.4 特征缩放
如果我们再次观察我们的输入特征 X,我们会发现它们是不同尺度的数值。
dist_mrt(最小值:23.38–最大值:6488)
conv 商店(最低:0–最高:10)
重新调整输入要素的比例以使它们共享相同的比例非常重要。为了获得优化的输出,特征缩放在许多机器学习算法中是重要的。功能缩放有几种方法,我们将使用的方法是标准化。标准化是一个重新调整要素的过程,因此所有要素都具有均值为 0、标准差为 1 的标准正态分布。
Scikit-learn 提供了一个有用的模块,standard scaler类对输入特征执行标准化。
使用标准化执行数据缩放的代码片段
5.5 将数据集拆分为训练集和测试集
接下来,我们将把输入特征 X 和输出特征 y 分成两个独立的集合:训练集和测试集。顾名思义,训练集用于训练机器学习模型,而测试集用于在稍后阶段评估已训练的模型。
Scikit-learn 提供了另一个有用的模块, train_test_split ,它使我们能够用几行代码轻松地将数据分成一个训练集和一个测试集。
将数据集分成训练集和测试集的代码片段
这里我们使用通用的命名惯例来创建几个名为 X_train,X_test,y_train,和 y_test,的变量来保存输入特征和输出特征的训练集和测试集的数组。请注意, train_test_split() 函数中的 test_size=0.2、参数会将 80%的数据作为训练集,另外 20%作为测试集。
6.培训模式
最后,我们准备好训练我们的第一个机器学习模型。让我们试一个简单的模型, 线性回归 模型。线性回归是一种建模方法,用于定义因变量和一个或多个自变量之间的线性关系。
我们可以使用 Scikit-Learn 的 LinearRegression 模块来创建一个线性回归模型,并用它来拟合我们的训练数据。
用于定型线性模型的代码片段
几秒钟后,一个训练好的线性模型就产生了,我们可以使用 predict() 方法用我们的测试集测试这个模型。
使用测试集测试已定型模型的代码片段
测试集的预测值如下:

单位面积预测房价
7.评估模型
现在,我们已经准备好了第一个模型,并用它来预测测试集的单位面积房价。然而,我们如何知道模型预测的准确性呢?线性模型对房价的预测有多好?
让我们来看一个分组条形图,它显示了真实值(y_test)和它们对应的预测值(y_pred)的比较。
绘制组条形图以比较真实 y 值和预测 y 值的代码片段

显示真实 Y 和预测 Y 的组合条形图(蓝色:真实 Y,橙色:预测 Y)
上面的分组条形图给了我们一个总的概念,一些预测值非常接近它们对应的真实值,但是一些预测值彼此相差很远。
现在,我们将通过成本函数使用定量方法来衡量线性模型的性能。成本函数是量化真实值( y_test )和预测值( y_pred )之间的差异的公式。
在预测房价这样的回归问题中,有两个常见的选项我们可以考虑:【RMSE】或者 平均绝对误差(MAE) 。
上面的两个成本函数计算真实值和预测值之间的差值的平均值。但是,RMSE 对数据集中可能存在的异常值非常敏感,会影响评估结果。因此,我们选择 MAE 作为我们的选择。
幸运的是,我们可以很容易地再次使用 Scikit-Learn 模块来调用 mean_absolute_error() 方法来评估模型。
使用 MAE 测量线性模型性能的代码片段

MAE(线性回归模型)的结果
所得到的 MAE 度量约为 6.344。这意味着每单位面积的预测房价与真实价格之间的平均绝对差异约为新台币 6.344 元(这可能表明我们可能会考虑尝试另一种模式以获得更好的结果)。
8。尝试新模式
在本节中,我们将训练和评估一个决策树模型。我们所需要的只是重复上面第 6 节& 7 中介绍的类似步骤。
我们可以使用 Scikit-Learn 中的 DecisionTreeRegressor 模块来创建决策树模型,并用它来拟合我们的训练数据。我们再次使用 MAE 成本函数来衡量模型的性能。
用于训练决策树和评估模型的代码片段

MAE(决策树模型)的结果
由此产生的 MAE 度量约为 4.84。这表明,与线性回归模型相比,决策树模型提供了更准确的房价预测。
如果我们仍然对当前模型的准确性不满意,我们可以考虑以下几种方法:
- 尝试另一种新的机器学习模型
- 获取更多数据集来为模型提供信息
- 尝试其他输入功能(例如 house_age )
结论
机器学习工作流本身就是一个决策过程,我们需要做出自己的判断来决定使用哪个模型来解决特定的问题。最耗时的部分不是训练模型,而是清理数据和选择适当的输入特征来训练模型的初步步骤。数据预处理步骤不仅仅是例行工作,因为它们都依赖于我们获得的数据的数量和质量以及我们要解决的问题的性质。
没有终极的工作流程可以适应所有类型的机器学习任务。
然而,我们仍然可以学习和遵循一些共同的原则来完成我们的机器学习项目。此外,我们还可以充分利用强大的 Python 或 R 包来启动我们的项目,而不需要任何额外的成本,因为它们是开源的。机器学习对我们来说是一种有益的体验,可以从原始数据中获得令人兴奋和有见地的输出。
源代码
为这个房价估值项目开发的 Jupyter 笔记本可以在 Github 找到。
参考
- https://www.bernardmarr.com/default.asp?contentID=1276
- https://www . kdnugges . com/2017/04/must-know-curse-dimensionality . html
- https://sci kit-learn . org/stable/auto _ examples/preprocessing/plot _ scaling _ importance . html
- http://sci kit-learn . org/stable/modules/generated/sk learn . preprocessing . standard scaler . html
- https://en.wikipedia.org/wiki/Linear_regression
- https://en.wikipedia.org/wiki/Root-mean-square_deviation
- https://en.wikipedia.org/wiki/Mean_absolute_error
- https://en.wikipedia.org/wiki/Decision_tree_learning
神经网络训练背后的数学
用一个例子清楚地解释神经网络和训练阶段背后的数学

罗马法师在 Unsplash 上拍摄的照片
神经网络广泛应用于人工智能领域。由于其可伸缩性和灵活性,它可以成为大多数预测问题的解决方案。可以解决回归、分类、预测、对象识别、语音识别、NLP 等复杂问题。那么,什么是神经网络,是什么使它们能够解决所有这些问题,以及它是如何学习进行预测的?为了理解这些,我们需要了解更多关于神经元及其背后的数学。在这篇文章中,我将解释神经元如何从给定的数据中学习并用于预测。我们将从头到尾考察神经网络和训练过程背后的理论。
- 什么是神经元,它们的职责是什么?
- 神经网络中的神经元是如何连接的?
- 神经网络如何根据给定的数据进行预测?
- 网络中的每次迭代会发生什么?
- 每次迭代后会发生什么?
- 一个神经网络在训练过程中会发生什么变化?
- 培训过程应该在什么时候停止?
网络中的神经元
神经元是神经网络的重要组成部分。更准确地说,神经网络是通过将一个神经元连接到另一个神经元而形成的。与人类神经系统不同,神经网络中的神经元通过层相互连接。如果我们考虑到每个神经元都与其他神经元相连,那么处理时间将会非常长。为了减少处理时间和节省计算机的计算能力,在神经网络中使用了层。由于有了层,一层中的每个神经元都与下一层中的神经元相连。下图显示了具有三层的神经网络的基本结构。

作者图片
从上图可以看出,有 3 层作为输入、隐藏和输出。这三层是神经网络的主要层。输入层中的神经元代表数据集中的每个变量。输出层中的神经元表示输入值传入隐藏层中的每个神经元后的最终预测值。虽然只有一个输入和输出层,但隐藏层的数量可以增加。因此,神经网络的性能取决于层数和每层中神经元的数量。具有 3 个隐藏层且每层中有 3 个神经元的网络和具有一层一个神经元的网络之间的预测性能可能不同。那么,如果我们再增加一个 3 个神经元的隐藏层,网络会是什么样子呢?下图显示了一个有两个隐藏层的网络。

作者图片
我们可以在网络中增加更多的隐藏层和神经元。没有任何限制。但是,我们不应该忘记,增加更多的层和神经元并不意味着我们的网络会预测得更好。但是,当我们增加隐藏层和神经元的数量时,由于每个神经元中的计算,训练时间会增加。我们需要做的是为我们的网络找到最佳的网络结构。
喂养神经元
神经网络通过迭代工作,每次迭代训练模型以达到最佳预测。因此,喂养神经元是训练我们网络的主要运动。这种运动在神经网络中被称为“前馈”。它的意思是从先前连接的神经元获取数据,用这些数据进行计算,并将结果发送给下一个连接的神经元。当在输出神经元中完成最后的计算时,从数据集中获取另一个观察值,并再次进行馈送。这个过程一直持续下去,直到我们网络的预测真正接近已经预测的实际值。这里最重要的是在神经元中进行什么样的计算。我们基本上可以称这些计算为加权。我们不应该忘记,我们将利用这个网络进行预测。因此,我们需要对神经元进行加权,以做出最佳预测。
好了,让我们深入考察一下这个喂食过程。假设我们有一个神经网络,1 个输入层有 2 个输入神经元,1 个隐藏层有 2 个神经元,1 个输出层有 1 个神经元。所以,首先我们可以考察隐藏层中一个神经元的进食过程;

作者图片
在上图中,输入层有两个神经元。这意味着我们的数据集中有两个变量将用于训练。如你所见,输入神经元和隐层神经元之间的每个连接都有“W”值。这些“W”值代表单个神经元为每一个供给自身的神经元保存的值。在第一步,“W”和“b”值可以在 0 和 1 之间随机生成。在迭代(步骤)期间,这些值将被更新,以便达到最佳预测值。我们将在接下来的章节中看到这些迭代。
H1 神经元由 X1 和 X2 神经元馈给,因此它对于 X1 和 X2 具有 W1 和 W2 权重。如果你看到计算部分,来自输入层的每个神经元的值乘以它的权重,然后我们对所有的值求和。然而,还有一个表示为“b”的值。这个值是神经元的截距,我们将这个值与相乘的权重相加。也可以称之为“偏向”。在求和操作之后,结果从激活函数传递过来。激活函数进行一种变换操作。从激活函数获得的值将是该神经元在当前步骤的最终值。
激活功能
根据我们想要预测的值,我们可以选择不同的激活函数。让我们假设我们想要预测表示为 0 和 1 的两个类。所以,我们需要一个介于 0 和 1 之间的概率值来决定预测的类别。如果预测值小于 0.5(这意味着它接近 0 类),我们可以说是预测为 0。如果它大于 0.5,我们可以说它被预测为 1。但是,在没有激活函数的情况下,可以从 0 和 1 中获得预测值。为了理清这个问题,我们可以使用一个使神经元值保持在 0 和 1 之间的激活函数。这个激活函数被称为“Sigmoid”。其他常用的激活功能如下图所示。

作者图片
我已经解释过什么时候我们应该使用 sigmoid 函数。如果你看上面的图,还有其他的激活功能。比如双曲正切函数,当我们需要-1 到 1 之间的输出时就可以使用。如果输出不应小于 0,可以使用 ReLU 函数,identify 函数将输出原样返回。这意味着在神经元中计算的值将作为其本身。根据将要预测的变量,应该选择这些函数中的一个。
训练网络示例案例
好吧!我们可以用一个实例来设置整个网络。假设我们要训练一个网络,通过使用树的长度和宽度来预测树的年龄。这意味着我们将使用两个变量作为预测值,一个变量作为预测值。将用于培训的数据集如下所示。

作者图片
正如我们之前提到的,神经网络通过迭代得到训练。因此,在每次迭代(步骤)中,它从数据集中提取样本,并在神经元中进行计算。只能进行一次观察或小批量观察。在本例中,我们将对一个步骤取一个样本(观察值),这将是我们数据集的第一个观察值。
我们还应该决定在网络中使用哪个激活功能。如前所述,这取决于你使用这个网络想要预测什么。如果我们查找我们的数据集,年龄,这是一个因变量,包括数值。所以,我们不会预测树的类型,我们会预测它们的年龄。这一推论使我们得出输出将是线性的激活函数。第一个选项是 ReLU,第二个选项是 Identity。因为,这些函数不会将值转换为 0 到 1 之间的值。它们之间的区别当 Identity 函数按原样返回输入值时,ReLU 函数如果输入为负则返回值 0,如果输入不为负则按原样返回值。但是,年龄不能是负数,所以使用 ReLU 函数是有意义的。但是我想让这个教程尽可能的简单。这就是为什么我要用身份函数作为激活。这种格式更容易理解。这听起来很奇怪,但使用身份功能意味着你不会使用任何激活功能。因此,在下面的图中我没有添加任何激活函数过程(因为,它原样返回计算值)。
下图显示了第一次迭代的神经网络和计算。可以看到,输入层有两个神经元,分别是“宽度”和“长度”。因为是第一次迭代,所以“宽度”和“长度”的值来自第一次观察,为 5 和 7。隐藏层也有 2 个神经元,输出层有 1 个神经元。如果你仔细观察,神经元之间的每个连接都有“w”权重值。正如我们之前提到的,权重可以在 0 和 1 之间随机选择。它可以超出此范围,但最好在第一步设置在 0 和 1 之间。在接下来的迭代中,它们无论如何都会被改变。这些随机分配给连接的权重值也显示在神经元上方。我们可以用这样的说法——这些权重用于每一个连接——有时,但它们存储在神经元中。在实践中,我们不为连接分配权重。这意味着每个神经元为来自矩阵结构中前一层的每个连接存储“w”值。实际上,我们也可以使用 ReLU 激活功能。因为,我们要预测树的年龄,年龄不能是负数。但我只想让这个例子尽可能简单。因此,我决定使用身份激活功能,下图中没有任何激活功能流程。因为单位函数对于在神经元中计算的值没有任何变换。它让它们保持原样。

作者图片
在神经元中计算之后,发现 6.25 是第一次迭代的最终结果。从技术上来说,我们可以说这是根据给定的第一次观察的宽度和长度值的第一次预测的“年龄”值。下一步我们应该做的是将这个结果与实际年龄进行比较。第一次观察的树龄为 5 年。这意味着我们离实际值相差 1.5 岁,我们需要根据这个距离更新神经元的权重。这个过程被称为反向传播,我们将在下一节看到它。但在此之前,我想向你们展示一下,如果我们在这个人工神经网络中使用两个隐藏层,每个隐藏层中有两个神经元,会发生什么。因为你可能想知道在这种情况下我们如何计算。

作者图片
在上图中,你可以看到在之前的网络中又增加了一层。所以我们的预测值果然变了 5.68。这只是一个例子,我们将在下面的章节中使用以前的网络结构。
将神经元升级到更高级别
这一部分可能是本文最重要的部分。因为我会解释神经元的权重是如何改变的,以便做出好的预测。我将这一部分命名为“将神经元升级到更高水平”,因为在网络的每次迭代之后,我们都会改变神经元的权重值。因此,我们将它们升级到更高的水平,以做出更好的预测。
如前一节所述,在一次迭代完成后,需要通过考虑预测值和实际值之间的差异来更新神经元的权重和偏差(截距)。这个过程在人工神经网络中被称为反向传播,我们将使用的算法是随机梯度下降。在每次前馈(迭代)之后,反向传播也必须在训练期间完成。借助反向传播网络得到训练。下图显示了反向传播过程。

作者图片
为了更新权重和偏差,首先我们应该找出实际值和预测值之间的差异。有两个函数常用于计算实际值和预测值之间的差异。这些被称为均方误差和交叉熵。在某些情况下,也使用误差平方和。这些函数统称为损失函数或成本函数。虽然对于回归问题可以优选均方误差,但是对于分类问题可以优选交叉熵。在这个例子中,我们试图估计树龄,而不是树的类型。这就是为什么我们可以用均方差。
下图显示了均方误差的函数;

作者图片
现在,我们可以通过使用 MSE 来计算实际值和前面示例中预测值之间的差异。第一次观察的预测年龄为 6.25 岁,实际年龄为 5 岁。因为我们在一次迭代中只取一个样本,所以“n”将等于 1。

作者图片
根据上述数学运算,MSE 为 1.5625。我们可以用术语损失来表示这个值。此外,如果我们在每次迭代中取 32 个观测值,我们将不得不从 32 个观测值的预测值和实际值中计算 MSE。
好了,我们有了失败的结果,下一步是什么?现在,我们必须通过考虑权重和偏差对损失的影响,来找出如何改变权重和偏差。所以,我们需要一个能做到的方法。这种方法在数学上叫做偏导数。带有权重和偏差的损失函数 L (MSE)的偏导数可以提供权重和偏差如何影响损失的信息。所以,这就是我们要找的。我们需要做以下偏导数运算;

上图显示了每个权重和偏差的偏导数。当我们有偏导数时,我们应该把它乘以学习率。在那之后,我们应该从它的重量中减去结果。这里的学习率表示权重将如何变化。高学习率下的体重变化将比低学习率下的体重变化大得多。因此,我们需要为我们的网络设置最佳的学习速率。
现在是时候学习如何求偏导数了。这在数学上有点深奥,如果你对偏导数没有任何概念,你可以看这个视频。我们将对 W1 (dL/dW1)进行导数运算。为了找到这个偏导数,我们可以做一个转换,如下式所示。代表 H1 神经元加权运算后的值,y 预测* 代表 O1 神经元的结果,w1 为*神经元中用于树宽的权值(输入层的第一个神经元)。**

为了解决上述均衡,我们需要继续使用y 预测H1和 L 损失的公式。然后我们可以得到所有的偏导数。如果我们看一下一阶偏导数 YPrediction 公式,我们可以看到它是 O1 神经元预测值的最终计算。

我们发现 H1 神经元的值的公式是:

我们需要的最后一个公式是损失函数 MSE (L)的公式。我们不应该忘记在每一步中我们只进行一次观察。所以,“n”的值将等于 1;

好吧!现在,我们可以走了。我们可以开始一个一个地求偏导数。我们可以从一阶偏导数“dL/dYPrediction”开始;

上图中已经进行了偏导数运算。这种操作背后的基本思想是发现损失如何受到预测的影响。如前所述,你可以观看这个视频来了解这些操作。下一个偏导数是“dYpred/dH1”。通常,H1 是一个返回激活函数的值的函数。在这种情况下,在取偏导数时,我们应该对 H1 求导。但是,在这种情况下,我们使用了恒等函数,恒等函数的导数 f(x) = x 等于 1。因此,我们可以假设 H1 只是 YPrediction 的一个参数值。如果我们使用 Sigmoid 函数,我们应该对它求导(这是另一种情况)。

最后一个导数是“dH1/dw1”;

现在,我们有了所有的均衡来寻找损失对“W1”重量的偏导数。我们需要做的就是把这些碎片拼在一起。

接下来我们应该做的是把 YTrue,YPrediction,w5 和 x1 的值放入上面的公式中;

随机梯度下降
耶!我们知道 w1 值如何影响损耗。接下来,我们要做的是决定如何改变“W1”值,以使损失最小化。因此,我们将使用称为随机梯度下降(SGD)的算法。实际上,偏导数运算是我们在上一节中做过的梯度下降的一部分。我们基本上可以说,我们正在通过使用反向传播作为随机梯度计算技术来训练我们的网络。在 SGD 中,我们从数据中提取单个样本,将它们传递到网络中,找出我们将如何改变权重和截距,以最小化损失。这个过程在每次迭代中进行,直到我们达到最小阈值。这意味着如果我们不能在一段时间后得到任何超过阈值的损失,我们可以停止训练。为了理解它,我们可以看到下图;

作者图片
在新币;在我们找到所有权重和截距的偏导数后,我们应该将它们乘以学习率,并从它们的旧权重和截距中减去。我们目前只找到了“w1”的偏导数。因此,我们可以进行以下操作,以找出新的更新“w1”值;

从上面的操作中可以看出,我们的新 W1 值为-0.1125。这意味着我们将用-0.1125 替换旧的“W1”值(位于 H1 神经元中),并且我们将在下一次迭代中使用该值。到目前为止,我们只找到了新的 W1 值。我们还必须找到其他 W 值和截距的新值。在上图中,还有 W 和截距值的其他偏导数;

现在,我们可以计算新的权重,以便完成第一个反向传播过程;

在第一次反向传播之后,我们有了所有新的“w”和“b”值。让我们看看我们的网络与新的价值观及其结果后,前馈步骤;

作者图片
从结果中可以看出,预测值为-3.33,为负值。我们需要担心吗?答案是 nop!我们刚刚用数据集的第一个样本完成了第一次迭代。我们的数据中有更多样本需要网络处理。此外,神经网络需要与其他样本进行更多的迭代才能得到训练。主要问题可能是:需要完成多少次迭代,或者我们的培训过程应该在什么时候停止?答案就藏在 SDG 的背后。
培训过程应该在什么时候停止?
迭代的目的是达到损失最小减少的阈值。我们应该在网络的训练阶段之前定义这个阈值。假设我们将阈值定义为 0.05,最大迭代次数定义为 10000。这意味着我们计划在最大 10000 次迭代中减少 0.05。在第一次迭代中,损耗的降低会更高。但是过了一段时间,减少将开始改变不太多,并且当网络达到最小阈值时,训练将停止。
比如在 8909。迭代我们取样本并传递到网络中,发现损失为 0.3559,在 8910。迭代我们再举一个例子,发现损失 0.3315,在 89111。迭代我们取了另一个样本,发现损失为 0.35080。损失的平均减少在 0.0244 和 0.0026 之间。这些值小于我们的阈值 0.05。所以,我们可以停止训练。然而,我们也可以定义一个最小误差来停止我们网络的训练。网络保持训练以达到给定的最小误差,即损失(当然我们也定义了最大迭代次数)。
还有一个我们需要担心的问题。这是一个过拟合问题。当我们的 ML 模型在训练集上表现完美,而在新数据(测试数据)上表现不佳时,就会出现这个问题。这意味着我们的网络可以在数千次迭代后达到最小损失,但它在测试集上表现不佳,为了评估性能,我们将测试集排除在训练集之外。在这种情况下,我们可以从我们的数据中定义一个验证部分,并控制该部分的损失量。如果验证集的损失不断增加,而训练集的损失不断减少,我们也可以停止训练。我们可以从下图了解一下;

作者图片
结论
在本文中,我们了解了神经网络模型的训练过程。当然,这只是一个具有基本网络结构的基本示例。本文的目的是学习神经网络背后的思想和数学。可以设置更复杂的网络结构。在编程语言的帮助下,数学运算可以在这些结构中轻松完成。但是它们也需要机器有更多的计算能力。如果你有编程语言的知识,你可以应用这些步骤,从头开始创建一个神经网络模型。
之后呢?在你完全理解了这篇文章中的操作之后,你可以更进一步。你可以检查其他反向传播和梯度下降方法,不同类型的神经网络,如 CNN,RNN,LSTM 等。为了解决不同的问题,已经开发了每一种其他的算法或方法。
我希望它是有帮助的,请不要犹豫问问题…
数据科学访谈中的冒险和不幸

https://unsplash.com/photos/bwki71ap-y8
数据科学求职的现实
我一直在等着发表这篇文章,但我想写一下我面试数据科学工作的经历。这是我的故事,我在博思艾伦工作了近 7 年,但我觉得是时候改变了。我非常喜欢博思艾伦公司,如果有人有兴趣在那里工作,请不要犹豫联系我。但是我觉得我已经准备好迎接不同的挑战,并开始在其他地方寻找工作。
既然我开始了一个新的职位,我想我应该分享一些我在许多公司面试时学到的观察。我没有跟踪我面试了多少家公司,但确实很多。我有丰富的政府工作经验,并从政府承包公司获得了许多工作机会。然而,我得出的结论是,就职业发展而言,加入另一家政府承包公司不是我想要的。
以下是我学到的…
我从求职中学到了什么
在你开始展示自己之前,真的花了很多心思在你想要的职位上。认真考虑所有因素,如公司文化、地点、职责、头衔等。很明显,没有一份工作是完美的,但是要将这份工作与你的需求清单进行比较,确保这个职位非常适合你。最重要的是,不要让招聘人员或其他人说服你去做不适合你的工作。如果你对一家公司感觉不好,跟着感觉走,然后离开。
网上申请是浪费时间
我发现申请数据科学的工作是浪费时间。我刚开始找工作的时候,一晚上申请了 10 到 15 份我认为自己有资格胜任的工作。我想到了我申请的 50 或 60 份工作,我可能得到了 3 或 4 次面试机会。我在 LinkedIn 上的人脉要好得多。老实说,这是我给所有求职者的最好建议,尤其是在科技行业。在 LinkedIn 和任何你知道的地方与人交流。你会比盲目应聘职位做得好很多。
不要在面试流程糟糕的公司浪费时间
面试过程是了解公司的一个窗口。如果一家公司永远不回复你,或者给你一个报价,或者其他什么,这就是你在那里工作时公司的运作方式。他们会行动迟缓,反应迟钝。我会说这是我在德意志银行正在做的事情。在写这篇文章的时候,我正打算雇佣几名 Splunk 工程师。我和我们的人力资源团队一起工作,我们在 2-3 天内就找到了候选人,进行了面试并给出了录用通知。这告诉候选人,我们真的需要他们,并表明我们可以把事情做好。与此形成鲜明对比的是,在一家公司向我发出邀请之前,我被这家公司骗了几个月,而在那之前,我已经接受了德意志银行的职位。
诚实和道德很重要
对我来说,我不想为从事不道德行为的公司工作,或者有不道德的经理等等。当我在德意志银行面试时,给我留下深刻印象的一件事是,人们对公司文化和他们所面临的挑战是多么坦率。没有人试图把一切都描绘成完美和令人惊奇的。(仅供参考,每家公司都有自己的 BS)众所周知,银行受到严格监管,国际银行必须应对极其复杂的监管制度。这是有充分理由的。当我在德意志银行面试时,给我留下深刻印象的是,每个面试者都与我讨论过在一家不能对数据为所欲为的银行工作是什么感觉。
我现在拒绝做编码考试
原则上,我确实喜欢把编码考试带回家的想法,然而作为一名考生,我发现它们相当令人沮丧,而且是一个主要的障碍。如果你试图评估候选人的编码能力,有许多方法可以做到这一点,我认为公司应该提供一个编码挑战,但我们中的许多人都有自己编写并公开提供的代码组合。现在无论何时有人问我,我只是让他们去我的 github 页面,或者提供我可以分享的项目样本代码。
我在一家公司面试,经过几轮电话面试后,招聘人员告诉我,在他们让我参加最后的面试之前,他们希望我参加两次编码考试,一次一小时的考试,然后是三小时的考试。这些考试是有时间限制的。我通过了这两个考试,但这是 12 月中旬,招聘人员告诉我,他不能安排面对面的面试,直到 1 月。我再也没有他或那家公司的消息。那时,我决定如果编码考试超过一个小时,我就不去做了。
我又为另一家公司做了一次编码考试。考试本身很简单,因为他们没有要求 NDA,所以问题大概是这样的。写一个函数把十进制转换成罗马数字
2。编写计算列表中项目出现次数的代码。
3。写一个函数来判断一个字符串是否是回文
我提交了使用 python 模块的代码和没有模块的代码。我写了大量的评论等等。代码符合规范,并且有很好的文档记录。我认为这证明了我既可以使用预先存在的模块,又可以从头开始编写功能代码。一周后,招聘人员告诉我,我没有通过编码考试。
从那以后,我决定不再在编码挑战上浪费时间。我采访的一家公司发给我一个编码挑战,他们说至少需要 8 个小时才能完成。对不起,伙计们…我为了生活而工作,有孩子,有更好的事情要做。
如果我正在招聘并决定使用编码考试,我会尝试首先为考试设定明确的目标,然后让候选人知道这些目标。你只是在寻找有用的代码吗?或者您想要文档精美并且使用正确设计模式的代码吗?
在我看来,编码考试应该设计为不超过一个小时。候选人不为你工作,让他们做冗长的编码考试只会让那些忙碌又受追捧的候选人望而却步。基本上,我会问一两个问题,只是为了确定候选人可以编码,可以写相当好的代码质量。
哦…让我们来谈谈 HackerRank。这个网站很烂。烂透了!!!没有别的说法了。T4 简直糟透了。没试过就不要!HackerRank 向您展示了一个编码挑战。你可以在他们的环境中,用许多预先选择的语言中的任何一种来编写代码,然后你的代码将会在你看不到的用例中被测试。为什么这很糟糕?仅仅是因为你没有办法调试你的代码。我为两个潜在雇主这样做了,虽然我通过了这些测试,但我发现它们真的很烦人,而且不必要的耗费时间。我花了大概 30 分钟调试一些代码,如果我能看到测试用例和输出,这可能需要 30 秒。我对 HackerRank 的另一个问题是人工环境。我现在做的大部分工作,都是用 Python 3 做的。我使用了很多标准的模块,比如 Pandas、Seaborn、Scikit-learn 等。当您进行 HackerRank 挑战时,您可能会被迫使用不熟悉的 Python 版本,而不使用您的标准模块。虽然我可以用 Python 2.7 编码,但是我没有用 Py 3 那么快,同样我也完全可以不用标准模块来编码,但是这需要更多的时间。底线是,如果你正在招聘,请不要使用 HackerRank。
虽然我们的主题是编码挑战,但我并不喜欢 BS 挑战。不要让我写一个非递归的二叉树遍历,因为我可以谷歌一下,你对我的编码能力一无所知。依我看,在现场采访中对某人这样做也是一件很不理智的事情。因此,如果我正在采访你,我要求你写代码,实现立方根函数,你知道你在烦我。
最后,如果你打算让某人为数据科学职位编码,你应该记住编码挑战不是戏弄。它们是评估候选人编码能力的一种手段。因此,编码挑战应该反映您实际上希望他们做的事情。如果我要为 DB-CSO 的数据科学家实现一个编码挑战,我会给他们一些样本安全数据,让他们使用他们喜欢的任何工具进行一些 ETL 和探索性数据分析。根据时间的长短,我可能会要求他们构建一个模型并评估其性能,同样,使用他们喜欢的任何工具。
另一种方法是简单地给候选人一些相对简单的挑战,只是为了验证他们可以编码,我认为这也是一个完全可以接受的方法。
实际采访:
让我说,在你职业生涯的某个时刻,我强烈建议你花时间做采访,就像为你的公司做采访一样。我认为这真的有助于你为面试做好准备,因为你对面试官想要什么有一个明确的想法。
如果你不幸被我面试,我现在就告诉你,我寻找的人是:聪明,知道如何把事情做好,并且对他们的工作充满热情。再多的准备也不会让你为此做好准备。当我面试候选人时,我会努力挖掘候选人的长处。如果这些优势与我们当时寻求的一致,那么恭喜你!通常我不会带人来面试,除非我确信我会雇用那个人,所以如果你得到了我的面试机会,这是一个好的迹象。我喜欢开放式问题,让候选人展示他们的思维过程。以下是我常问的一些问题:
- 如果你是一名恐怖分子或罪犯,你会使用什么技术来混淆你与监控机构的通信?(完全开放式,让候选人展示他们对网络和电信技术的理解)(这是针对网络分析师职位的)
- 我会请候选人向我介绍设计一个系统来检测欺诈性信用卡交易的过程。视时间而定,我将深入讨论这个问题,询问设计约束等。
- 向高级经理解释您将如何评估数据科学项目 X 的价值。我真的很喜欢这个问题,因为它迫使候选人从战略角度思考特定项目的影响。
最佳面试: CapitalOne,Orbital Insight,Kensha。在这些公司中,我实际上只收到了其中一家公司的邀请,但我真的对公司的流程和公司印象深刻。
最差面试:我被要求使用 Map-Reduce 实现 K 均值聚类。这次面试让我很恼火,因为我对自己知道什么和不知道什么非常坦率,而这位面试官就是个混蛋。我不会在我的简历中声称有 MapReduce 的开发经验。 Pro 提示:如果候选人说他们不知道 X,不要问他们一百万个关于 X 的问题,那只是做个混蛋。相反,找到候选人擅长什么,看看这些优势是否符合你的要求。
最尴尬的时刻:在一次疲劳的时刻,一家公司的人事经理问我想找什么样的工作,我告诉她“我不会无聊到发疯。”我得到了这家公司的一份工作,但是我很不好意思那样做。专业提示:避免在面试中扔 f 弹。
最发人深省的问题:告诉我你会如何设计一辆无人驾驶汽车
最奇怪的面试:任何一个想要在酒店大厅见我的小型政府承包商。
最大的失望:我参加了一家大型金融公司的面试,这家公司有一间漂亮的办公室,离我家大约 10 分钟路程,是一个非常棒的职位。我面试了潜在的同事和两位董事总经理。在我走向电梯的时候,总经理告诉我,他认为我会成为团队的一员,并期待着与我合作。我完全认为我已经稳操胜券了,但是在欺骗了我几个星期之后,我没有得到任何机会。专家提示:包里从来没有东西。我参加过一些面试,我以为自己搞定了,却没有得到工作机会;还有一些面试,我以为自己搞砸了,却得到了工作机会。世事难料。
最大的挫折:我最大的挫折是公司和我之间缺乏沟通。我总是担心坚持会被理解为绝望或讨厌。在这个过程中,有两家公司拖了我好几个月。如果你已经面试了一位候选人,你应该给他们一个回应……任何回应。
我遇到的另一个大挫折是公司通常不尊重我的时间。我住在东海岸——DC 地区。有几家公司想让我飞到旧金山或硅谷,为 DC 的一个职位与“家乡团队”进行面试。我认为这是一个好主意,但要认识到从东海岸出去一天实际上是两三天的旅行,除非你做红眼航班或其他疯狂的安排。所以,公司们,如果你想雇佣一个东海岸的候选人,让他们飞去参加面试,请尊重候选人的时间表…不要让他们支付机票费用。你可以将这样的面试安排在周一或周五,这样候选人可以尽量减少下班时间。
最后
总之,我想说的是,在寻找数据科学家的工作时,确保你(候选人)知道你在寻找什么,不要偏离太远。对公司:知道你在寻找什么,尊重候选人。如果你雇佣了一个人,却不知道自己到底想要什么,这对你自己和候选人都是极大的伤害。我在这个过程中意识到,在招聘时,许多人都在寻找一个理想化的自我认知。这意味着如果面试官认为自己是一个努力工作的人,他们会在应聘者身上寻找这种品质。如果面试官认为自己是主题 X 的专家,他们会问很多关于主题 X 的问题。祝你面试好运,如果你想和我进行模拟数据科学面试,请不要犹豫联系我。
基于 PyTorch、Captum 和 ONNX 深度学习的鸟类图像分类

(图片由作者提供)
PyTorch 历险记
第 0 部分:介绍图像分类、深度学习和加州理工学院鸟类 200 数据集
本系列将探索脸书人工智能研究所(FAIR)强大的神经网络和机器学习架构 PyTorch 的强大功能。在这一系列文章中,我们将探索 PyTorch 在图像分类问题中的应用能力,通过使用各种 CNN 架构,包括 GoogLeNet、ResNet152 和 ResNeXt101 等,使用 CalTech 200 birds 数据集识别 200 种北美鸟类。

加州理工学院加州大学圣迭戈分校鸟类 200 数据集()韦林德 p、布兰森 s、塔米 t、华 c、施罗夫 f、贝隆吉 s、佩罗娜 p .“加州理工学院-加州大学圣迭戈分校鸟类 200”。加州理工学院。CNS-TR-2010–001。2010 年
介绍
在这组文章中,我将探讨我们如何使用脸书人工智能研究所的神经网络库 PyTorch 来解决一个多类的图像分类问题。这个广泛的库,带有一系列与发行版打包在一起的现有工具,从使用 torch.nn 模块(相当于 Keras 的 PyTorch)的高级抽象,到低级自动签名函数和基于 GPU 的高效操作,允许设计和快速实现最先进的机器学习架构。在最基本的层面上,PyTorch 可以被认为是众所周知的 python 数组包 Numpy 的一个高度优化的多维版本。

图 1:加州理工学院鸟类分类研讨会工作流程。本系列的每一篇文章都将关注这个工作流的一个单独的阶段。用于生成这些文章的笔记本,以及经过训练的模型可以在 this Github repository 中找到。(图片由作者提供)
将要进行的工作流程如图 1 所示,每篇文章都将关注该工作流程的一个特定方面,包括:
- 数据探索和分类问题介绍。
- 准备图像分类卷积神经网络(CNN)并在以下架构上训练:
A) Torchvision 预训练网络。
B)第三方预培训网络。 - 使用传统方法(分类报告、度量、混淆矩阵、精确召回曲线等)评估分类模型性能。
- 使用神经网络激活图的域缩减和流形技术(例如 t -SNE 和 UMAP )评估网络分类性能。
- 迁移学习,使用经过训练的神经网络作为特征提取器,作为其他分类算法(XGBoost,内核 SVM)的输入。
- 神经网络卷积滤波器的特性可视化(神经元、空间和层激活),使用 Lucent python 包 ( Lucid for PyTorch)。
- 通过将 PyTorch 模型对象转换为 ONNX(开放式神经网络交换)格式来部署训练模型,并使用 ONNX 运行时环境演示推理。
在这个系列的介绍中,我们将从机器学习的角度来回顾什么是分类,我们所说的图像分类是什么,特别是什么是使用深度学习技术的图像分类。接下来,我们将介绍鸟类分类的细粒度图像分类问题,并回顾我们稍后将用来演示这些技术的所选数据集。最后,我们将对过去几年中开发的最先进的卷积神经网络所获得的结果进行总结,在接下来的系列文章中,我们将揭示如何实现这些结果。
什么是预测模型,什么是分类?

图 2:机器学习算法适合两个一般领域,分类和回归。(图片由作者提供)
预测建模是利用历史数据开发一个模型,在我们没有答案的情况下对新数据进行预测的问题。预测建模可以被描述为从输入变量(X)到输出变量(y)逼近映射函数(f)的数学问题。这就是所谓的函数逼近问题。
建模算法的工作是在给定时间和可用资源的情况下找到最佳映射函数。
从根本上说,分类和回归的区别在于,一个旨在预测一个标签或类别,而另一个旨在预测一个数量。
图 2 清楚地说明了这两种方法之间的差异,其中分类模型根据给定数据点相对于类边界的位置来预测其类值,例如支持向量机(SVM)分类器。然而,回归模型被设计成在给定一组预测因子(数据列)的情况下预测某事物的实际数量。
分类预测建模是从输入变量(X)到离散输出变量(y)近似映射函数(f)的任务。输出变量通常被称为标签或类别。映射函数预测给定观察值的类别或种类。例如,文本电子邮件可以被分类为属于两类之一:“垃圾邮件”和“非垃圾邮件”。
- 分类问题要求将示例分为两类或更多类中的一类。
- 分类可以有实值或离散输入变量。
- 有两类的问题通常被称为两类或二元分类问题。
- 具有两个以上类别的问题通常被称为多类别分类问题。
- 一个例子被分配多个类别的问题称为多标签分类问题。
分类模型通常将连续值预测为给定示例属于每个输出类的概率。概率可以解释为属于每个类别的给定示例的可能性或置信度。通过选择具有最高概率的类标签,可以将预测概率转换为类值。
在这些文章中,我们要关注的是分类,以及一个叫做图像分类的问题的特殊子集,我们将在下一节更详细地讨论这个问题。
什么是图像分类?

图 3:对象的图像分类,其中根据图像的内容对图像进行分类。(图片由作者提供)
图像分类是一般分类问题的一个子域。为图像分类设计的算法接受图像作为其输入,并产生图像类别的预测作为输出。输出可以采取标签或类别的形式,或者表示属于图像的每个潜在类别的可能性的一组实值概率的形式。图 3 中的漫画显示了一种算法,该算法设计用于识别食物图像是冰淇淋、冰棍还是蛋糕,将食物图像作为输入,并提供一个类别标签作为预测。
为了成功地对图像进行分类,一种算法需要从输入图像中提取代表性的“特征”,并学习相应的模式,以允许它根据图像的内容区分类别(图 4A)。这些“特征”可以通过迭代和交互的设计过程手动创建,目的是产生最好的分类特征。然而,这种手动方法有以下潜在的缺点:
- 人力密集。
- 容易出错。
- 穷尽过程。
- 无法保证能够最佳区分不同类别的独特特征。

图 4A:使用(上)具有手工制作特征的机器学习和(下)使用 CNN 在一个过程中自动导出理想化特征和分类器的深度学习的不同图像分类方法。(图片由作者提供)
另一种在过去 10 年中广泛发展并在图像分类性能方面取得显著进步的方法是深度学习的使用,特别是卷积神经网络(CNN)。这些类型的方法试图同时解决优化设计的特征提取和预测对象类别的分类器的问题。在其最简单的形式中,CNN 可以被认为是一个巨大的,自动导出(或学习)的特征提取系统,末端有一个分类器。

图 4B:从头开始培训的概念(上图)与迁移学习的概念(下图)。在迁移学习中,通过移除最终层分类器并将提取的特征输出用作新分类器的输入,预训练的网络被用作特征提取网络(新分类器不必基于神经网络)。(图片由作者提供)
事实上,正是这种结构允许采用所谓的“迁移学习”方法(图 4B)。这是移除网络基础上的分类层,并将网络用作特征提取器的过程。然后,该特征提取网络的输出可以被馈送到另一个分类器中,该分类器的选择可以是任何机器学习分类器(例如,SVM、核 SVM、基于决策树的集成,如 XGBoost),以执行分类预测。在这种情况下,分类器的输入不是图像,而是从图像中提取的特征(有时称为激活)的集合,分类器通过这些特征学习识别和预测图像类别。
正是这些方法,我们将在下面的系列文章中展示如何使用 PyTorch 构建一个最先进的图像分类器。
数据集—加州理工学院 UCSD 200 鸟类数据库(CUB-200–2011)

图 5:来自 CUB-200–2011 的相似物种(莺)的例子,显示了鸟类物种识别的复杂性和困难性。即使有了图 6 所示的物种图,人类也很难预测具体的鸟类物种。
CUB-200–2011 数据集包含来自 200 个不同物种的北美鸟类图像。这是一个具有挑战性的问题,因为许多鸟类都有一定程度的视觉相似性。鸟类物种识别对人类来说是具有挑战性的,更不用说计算机视觉算法了,因此这种类型的问题通常被称为大规模细粒度的。例如,用图 6 中的物种图来识别图 5 中两种鸟的正确林莺物种,对人类来说仍然是一个非常困难和复杂的问题。

图 6:北美林莺物种示例图( 凯特·多拉莫尔艺术 ) )。

图 7:CUB-200–2011 数据集属性(在 之后的)计算&神经系统技术报告,CNS-TR-2011–001**)。
该数据集最初产生于 2010 年( CUB-200 ),包含 200 类鸟类的约 6000 张图像。伴随它的是附加标签数据,包括边界框、粗略分割和附加属性。这在 2011 年进行了更新(CUB-200–2011),增加了额外的图像,使数据集中的图像总数达到近 12,000 张。可用的属性也被更新为包括 15 个零件位置、312 个二进制属性和每个图像的边界框(图 7)。在本系列的大部分时间里,我们将简单地使用图像和类别标签来开发和训练预测鸟类类别的网络。
关于 CUB-200–2011 的部分已发布结果
W ah 等人(2010) 报道了使用 RGB 颜色直方图和向量量化 SIFT 描述符的直方图与线性 SVM,他们获得了 17.3%的分类精度。这是作为与更高级的技术(包括深度学习方法)进行比较的基础而产生的,并且是使用手工制作的特征和机器学习来解决图像分类问题的方法的示例(如图 4 的上图所示)。
使用完整的未裁剪图像,他们实现了 10.3%的总体平均分类精度。在 2014 年, Goring 等人 提出了一种基于非参数标签转移技术的细粒度识别方法,该方法从具有相似全局形状的对象中转移部分星座,实现了 57.8%的平均分类准确率。

图 8:CUB-200–2011 数据集上表现最好的模型,来自paperswithcode.com
最近对细粒度图像分类的研究主要基于卷积神经网络方法。这些方法取得了相当好的精度,平均分类精度接近 90%(图 8;来自 paperswithcode.com 的关于 CUB-200–2011 的最佳性能算法的图表。例如,崔等(2017)演示了使用现代神经网络架构,获得明显更准确的预测。他们方法成功的关键部分是深度学习网络的使用,结合高分辨率图像训练和处理细粒度问题的长尾分布方面。它们还决定性地显示了使用领域特定的预训练数据集来提高较小的细粒度分类问题(如鸟类物种识别)的准确性的优势。
现代工具有什么可能?
用最少的努力,我听到你说什么是真正可能的?
在这组文章中,我们的目标是展示如何相对简单地访问最先进的图像分类模型,并获得接近当前领先网络的性能。正如本讨论所示,这种在细粒度图像分类问题上的性能在过去几年才成为可能。
在深入研究如何设置、训练和部署 PyTorch CNN 进行图像分类的细节之前,让我们先来看看使用一种相对简单的方法可以获得的结果。在接下来的文章中,我将与您分享为训练这些模型而开发的底层 python 代码的更多细节,但在这里,我想分享我在数据集上训练的所有不同网络架构的最终结果。

图 9: PyTorch CNN 图像分类架构使用类宏平均度量的性能比较。在 ImageNet 上进行预训练,并使用 CUB-200–2011 进行进一步训练后,在 CUB-200–2011 数据集的测试集上进行评估。(图片由作者提供)
图 9 显示了许多不同模型架构的性能,所有卷积神经网络(CNN)用于图像分类,在 CUB-200–2011 上训练。这些模型包括最早成功开发更深层次网络的模型架构之一, GoogLeNet ,由 Szegedy 等人(2014)在论文“用卷积深化”中提出,以及最近的网络架构,包括 ResNeXt (谢等人 2017 之后的)和 PNAS 网(刘等人 2018之后的)
这个例子表明,即使在 3 到 4 年的发展空间内,这些网络的性能改进也是相当可观的。这里值得明确指出的是,这些模型之间的唯一区别是网络架构本身。训练和测试图像的选择以及图像增强过程和模型性能的评估对于所有相关的模型都是相同的。正是不同的网络架构使得最新的网络在分类性能方面取得了显著的进步。
请加入我即将发表的一系列文章,在这些文章中,我们将发现如何使用 python 和 PyTorch 来构建一个最先进的鸟类分类器,以产生如上所示的结果,以及了解它如何执行以及它如何做出决策的方法。
用来制作这组文章的代码和笔记本已经发布在 Github 上,也可以在这里 找到。这些数据可以通过 Github 页面上的链接获得。
参考资料:
- 塞格迪,C. 等用回旋更深入。arXiv:1409.4842【cs】(2014)。
- 谢,s .,Girshick,r .,Dollár,p .,Tu,Z. &何,k .深度神经网络的聚合残差变换。arXiv:1611.05431【cs】(2017)。
- 刘,s,齐,l,秦,h,石,J. &贾,j .路径聚合网络实例分割。arXiv:1803.01534【cs】(2018)。
- Goering,c .、Rodner,e .、Freytag,A. & Denzler,j .用于细粒度识别的非参数零件转移。在 2014 年 IEEE 计算机视觉和模式识别会议2489–2496(IEEE,2014)。doi:10.1109/cvpr . 2014.319。
背景阅读:
关于神经网络的背景参考材料,包括理论和实践,感兴趣的读者可以参考以下优秀资源。
深度学习和神经网络实用指南:
- Rosebrock,A. 用 Python 进行计算机视觉的深度学习。第 1–3 卷(2017 年)。
- Chollet,F. 用 Python 进行深度学习。(曼宁出版公司,2018 年)。
神经网络和深度学习的背景理论:
- 神经网络和深度学习:一本教科书。(施普林格,2018)。
- 模式识别和机器学习。(斯普林格,2006 年)。
- 古德费勒,我,本吉奥,y 和库维尔,A. 深度学习。(麻省理工学院出版社,2016)。
- 哈根,M. T .,德穆特,H. B .,比厄,M. H. & De Jesus,O. 神经网络设计(第二版)。(自我出版,2014)。
通用机器学习背景理论与实践:
- 数据分类:算法和应用。(查普曼&霍尔/CRC,2015)。
- 统计学习的要素。(施普林格,2017)。
- Kuhn,m .和 Johnson,K. 应用预测建模。(纽约施普林格出版社,2013 年)。doi:10.1007/978–1–4614–6849–3。
- 计算机时代的统计推断:算法、证据和数据科学。(剑桥大学出版社,2017)。
- 统计学习导论:在 R 中的应用。(施普林格,2013 年)。
PyTorch 中神经网络的对抗性攻击与防御
神经网络真的能学习一切吗?

深度学习和神经网络的兴起给现代社会带来了各种机会和应用,如对象检测和文本到语音转换。然而,尽管看起来准确度很高,但神经网络(以及几乎所有的机器学习模型)实际上可能会受到数据的影响,即敌对的例子,这些例子是从原始训练样本中非常轻微地操纵的。事实上,过去的研究表明,只要您知道更改数据的“正确”方法,您就可以迫使您的网络在数据上表现不佳,这些数据在人眼看来似乎没有什么不同!这些故意操纵数据以降低模型精度的行为被称为对抗性攻击,攻击和防御之战是机器学习领域正在进行的热门研究课题。
本文将概述一种最简单而有效的攻击——快速梯度签名方法攻击——及其在 PyTorch 中的实现和通过对抗训练进行防御。
边注:本文假设了在 PyTorch 中构建简单神经网络和训练它们的先验知识。如果你不熟悉它们,建议先在 PyTorch 上查看教程。
对抗性例子和攻击的历史
对立的例子可以被定义为为了欺骗机器学习网络而被扰乱的输入或数据。伊恩等人在 ICLR 2015 会议的论文“解释和利用对立的例子”中阐述了这一观点。虽然本文之前的出版物声称这些对立的例子是由机器模型的非线性和过拟合引起的,但 Ian 等人认为,由于架构的高度线性,神经网络实际上容易受到这些例子的影响。LSTMs 之类的模型和 ReLU 之类的激活函数仍然经常以非常线性的方式运行,因此这些模型很容易被线性扰动所欺骗。然后,他接着提供了一个简单快速的一步生成对立例子的方法:快速梯度符号法。
快速梯度符号法

图一。FGSM 对熊猫图像的影响。在他们的 2015 年 ICLR 论文
快速梯度符号方法(FGSM)是一种白盒攻击,这意味着攻击是基于给定的网络架构产生的。FGSM 基于这样的想法,即正常网络遵循梯度下降来寻找损耗的最低点,因此,如果我们遵循梯度的符号(沿着与梯度下降相反的方向),我们可以通过添加少量扰动来最大化损耗。
因此,FGSM 可以描述为以下数学表达式:

其中 x’是通过添加小常数ε产生的扰动 x,其符号等于损耗 J 相对于 x 的梯度方向。图 1 是计算机视觉领域中 FGSM 攻击的经典图示。由于图像中不到 1%的变化是我们无法视觉识别的,图像从置信度一般的正确分类变成了置信度很高的错误分类。
这些简单的方法实际上可以欺骗深度神经网络的事实进一步证明了由于神经网络的线性而存在对立的例子。
PyTorch 的 FGSM
要在 PyTorch 中构建 FGSM 攻击,我们可以使用由 Ian Goodfellow 和 Nicolas Papernot 提供并精心维护的 CleverHans 库。该库提供了多种攻击和防御,目前广泛用于基准测试。尽管大多数攻击是在 Tensorflow 中实现的,但他们最近也在 PyTorch 中发布了 FGSM 的代码。
可以使用以下命令下载并安装该库:
pip install git+https://github.com/tensorflow/cleverhans.git#egg=cleverhans
我们将使用简单的 MNIST 数据集来演示如何构建攻击。
创建模型和数据加载器
首先,我们必须为 MNIST 数据集创建一个普通的 PyTorch 模型和数据加载器。
为了进行演示,我们将构建一个简单的卷积网络,如下所示:
和数据加载器,如下所示:
之后,我们实现了一种正常的转发方法来根据正常数据训练网络:
通过将批量大小设置为 128,时期数设置为 4,学习率设置为 0.001,网络在训练后成功地在 MNIST 数据集上实现了大约 98%的准确率。
施加攻击
在训练网络之后,我们可以在给定网络架构的情况下应用 FGSM 攻击。
为此,我们必须首先从 CleverHans 导入所需的函数:
from cleverhans.future.torch.attacks.fast_gradient_method import fast_gradient_method
这就允许我们调用 fast_gradient_method()函数,这个函数简单明了:给定模型、一个输入 x、一个ε和一个范数(norm=np.inf,1 或 2),这个函数输出一个扰动的 x。
然后,我们可以通过输入扰动的 x 而不是原始的 x 来稍微改变原始的正向函数,以测量如下结果:
经过测试,上述攻击实际上可以迫使准确率从 98%急剧下降到 4%左右,这证明如果方向正确,小扰动实际上会导致网络性能非常差。
PyTorch 的对抗训练
在 Ian 等人的同一篇论文中,他们提出了对抗训练方法来对抗这些样本。简而言之,从训练集中生成的敌对样本也包括在训练中。
通过将原始的和扰动的训练集同时输入到架构中,这个概念可以很容易地实现到代码中。请注意,这两种类型的数据都应该用于对抗性训练,以防止原始数据集的准确性损失。下面的代码是我对对抗性训练的实现:
请注意,网络从检查点开始,在那里它已经接受了干净数据的训练。在对抗训练期间,干净样本和对抗样本都被输入到网络中,以防止在进一步训练期间干净数据的准确度下降。
使用相同的批量大小、时期和学习率设置,我们实际上可以将对立示例的准确度提高到大约 90%,同时保持干净数据的准确度。
对抗性训练的问题
虽然上述示例说明了如何采用对抗性训练来概括模型架构,但一个主要问题是,它们仅在模型被训练的特定类型的攻击上有效。不同的攻击产生不同的对抗范例,对抗训练方法需要进一步研究和评估,以更好地进行对抗防御。
结论
FGSM 和对抗性训练是最早的攻击和防御之一。最近的攻击(如 C&W 攻击和 DeepFool)以及防御(如蒸馏)为未来的研究和调查提供了新的机会。这篇文章是对对抗性攻击领域的一个介绍,希望能激发您深入研究这个领域的兴趣!要了解更多,这里有另一篇文章,我认为这是一篇很好的短文,可以更好地理解快速梯度符号法。
我的实现的完整代码也发布在我的 Github 中:
在 GitHub 上创建一个帐户,为 ttchengab/FGSMAttack 开发做贡献。
github.com](https://github.com/ttchengab/FGSMAttack) 
谢谢你能走到这一步🙏!我将在计算机视觉/深度学习的不同领域发表更多文章,请务必查看我的其他文章和 川林恩 的文章!
对垃圾短信检测器的对抗性攻击
使用基于雅可比的显著图攻击,探索如何使用对抗性学习来定位垃圾短信检测器
注: 本文讨论的方法背后的方法论源于我和Irene Anthi之间的一个 合作出版物 。
介绍
垃圾短信经常出现在我们的手机屏幕上。这已经够烦人的了,但情况会变得更糟。给你发垃圾短信的人通常是想诈骗你。大多数垃圾短信不是来自另一部手机。它们通常来自计算机,并通过电子邮件地址或即时消息帐户发送到您的手机。
存在几种自动检测电子邮件或 sms 消息是否是垃圾邮件的安全机制。这些方法通常依赖于机器学习。然而,这种系统的引入也可能受到攻击。
向基于机器学习的系统部署攻击的行为被称为对抗性机器学习(AML)。其目的是利用预训练模型的弱点,该模型在训练期间看到的数据点之间可能有“盲点”。更具体地说,通过自动地将轻微的扰动引入到看不见的数据点,模型可以越过决策边界并将数据分类为不同的类别。因此,模型的有效性会大大降低。
在垃圾短信检测中,AML 可用于操纵文本数据,包括干扰,使垃圾数据被归类为非垃圾数据,从而绕过检测器。
数据集和数据预处理
垃圾短信收集是为垃圾短信研究收集的一组带短信标签的消息。它包含一组 5,574 条英语 SMS 文本消息,根据它们是垃圾邮件(425 条消息)还是非垃圾邮件(3,375 条消息)进行标记。
在我们深入应用任何类型的机器学习技术之前,让我们首先讨论一下我们需要考虑的预处理技术。我们将执行大多数自然语言处理(NLP)问题的标准预处理技术。其中包括:
- 将文本转换成小写。
- 去掉标点符号。
- 删除额外的空白。
- 删除数字。
- 删除“the”、“a”、“an”、“in”等停用词。
- 引理满足。
- 象征化。
Python 的自然语言工具包(NLTK) 可以处理这些预处理需求。现在,输出应该如下所示:
单词嵌入
单词嵌入是最流行的文本词汇表示方法之一。它能够捕捉文档中某个单词的上下文、其与周围单词的语义和句法相似性以及其与其他单词的关系。
但是如何在上下文中捕捉单词嵌入呢?Word2Vec 是使用两层神经网络学习单词嵌入的最流行的技术之一。神经网络接收文本集,对其进行分析,并为词汇表中的每个单词生成一个数字向量,这些数字向量编码了与单词出现的上下文相关的单词含义的重要信息。
主要有两种模式:连续词袋模式和跳格模式。Word2Vec Skip-gram 模型是一个具有单个隐藏层的浅层神经网络,它接受一个单词作为输入,并试图预测该单词周围单词的上下文作为输出。
在这种情况下,我们将使用 Gensim 的 Word2Vec 来创建模型。一些重要的参数如下:
- size:嵌入的维数。默认值为 100。
- 窗口:目标单词与周围单词之间的最大距离。默认窗口是 5。
- min_count:训练模型时要考虑的最小字数。出现次数少于此计数的单词将被忽略。默认的最小计数是 5。
- 工人:培训时分区数量。默认工人是 3。
- sg:训练算法,连续词包(0)或跳格(1)。默认的训练算法是连续单词包。
接下来,我们将看到如何使用 Word2Vec 模型为数据集中的文档生成向量。通过遍历数据集,为训练数据中的每个 SMS 消息生成 Word2Vec 向量。通过简单地对文本消息的每个单词使用该模型,我们检索这些单词的单词嵌入向量。然后,我们通过计算文本中所有单词向量的平均值来表示数据集中的消息。
模型训练和分类
让我们首先对目标标签 spam 和 not_spam 进行编码。这包括将分类值转换成数值。然后,我们将把特征分配给变量X,把目标标签分配给变量y。最后,我们将把预处理后的数据分成两个数据集。
- 训练数据集:用于训练短信文本分类模型。
- 测试数据集:用于验证模型的性能。
为了将数据分割成两个这样的数据集,我们将从模型选择功能中使用 Scikit-learn 的训练测试分割方法。在这种情况下,我们将数据分为 70%的培训和 30%的测试。
为了这篇文章,我们将使用一个Decision Tree分类器。实际上,您可能希望使用交叉验证来评估各种分类器,以确定哪一个性能最好。“没有免费的午餐”定理表明,不存在普遍最佳的学习算法。换句话说,选择一个合适的算法应该基于它对于特定问题的性能和表征该问题的数据的属性。
一旦模型被训练,当它试图预测测试集的目标标签时,我们可以评估它的性能。分类报告显示,该模型可以预测具有 0.94 的高加权平均 F1 得分的测试样本。
生成对立样本
AML 的一个众所周知的使用案例是在图像分类中。这包括添加人眼可能察觉不到的噪声,这也欺骗了分类器。

有各种方法可以产生对立的样本。这些方法在复杂性、生成速度和性能方面各不相同。制作这种样本的简单方法是手动扰动输入数据点。然而,与自动方法相比,人工扰动的产生和评估较慢。
自动生成扰动样本的最流行的技术之一包括基于雅可比的显著图攻击(JSMA)。这些方法依赖于这样一种方法论,即当对原始样本添加小的扰动时,所得到的样本会表现出相反的特征,因为所得到的样本现在被目标模型不同地分类。
JSMA 方法使用显著图生成扰动。显著图标识输入数据的哪些特征与模型决定是一个类别还是另一个类别最相关;这些特征如果被改变,很可能会影响目标值的分类。更具体地,选择初始百分比的特征(γ)以被(θ)量的噪声干扰。然后,该模型确定添加的噪声是否已经导致目标模型的错误分类。如果噪声没有影响模型的性能,则选择另一组特征,并进行新的迭代,直到显著图出现,该显著图可用于生成敌对样本。
预训练的 MLP 被用作生成敌对样本的基础模型。这里,我们探讨 JSMA 参数的不同组合如何影响最初训练的决策树的性能。
估价
为了探索 JSMA 参数的不同组合如何影响训练好的决策树的性能,通过使用伽马和西塔的一系列组合,从测试数据中存在的所有垃圾邮件数据点生成敌对样本。然后,对抗性样本与非垃圾邮件测试数据点相结合,并呈现给训练好的模型。热图报告了 JSMA 的 gamma 和 theta 参数的所有敌对组合的总体加权平均 F1 分数。

决策树模型的分类性能实现了所有γ和θ参数的 F1 分数的降低。当γ= 0.3,θ= 0.5 时,模型的分类性能下降了 18 个百分点(F1-score = 0.759)。在这种情况下,基于该数据集,γ= 0.3,θ= 0.5 将是人们用来成功降低基于机器学习的 SMS 垃圾邮件检测器的准确性的最佳参数。
结论
那么,我从这个分析中学到了什么?
由于其有效性和灵活性,基于机器学习的检测器现在被认为是检测 SMS 文本消息是否是垃圾邮件的基本工具。然而,这种系统容易受到攻击,可能会严重破坏或误导它们的能力。在这种基础设施中,对抗性攻击可能会产生严重后果,因为 SMS 文本可能会被修改以绕过检测器。
下一步将是探索这些样本如何支持使用对抗训练的监督模型的鲁棒性。这需要将对立样本包括到训练数据集中,重新训练模型,并评估其在 JSMA 的伽马和θ参数的所有对立组合上的性能。
完整的笔记本,查看下面我的 GitHub 回购:https://GitHub . com/lowri Williams/SMS _ Adversarial _ Machine _ Learning
深度学习中的对立例子——初级读本
在深度学习视觉模型中引入对立的例子

来源: Pixabay
介绍
自从我们开始获得更大更好的计算(GPU 和 TPU)、更多的数据(ImageNet 等)以来,我们已经看到了最先进的(SOTA)计算机视觉深度学习模型的出现。)以及易于使用的开源软件和工具(TensorFlow 和 PyTorch)。每年(现在每隔几个月!)我们看到下一个 SOTA 深度学习模型在基准数据集的 Top-k 准确性方面击败了上一个模型。下图描绘了一些最新的 SOTA 深度学习视觉模型(并没有描绘一些像谷歌的 BigTransfer!).

https://arxiv.org/abs/1905.11946 SOTA 深度学习视觉模型(来源:)
然而,当这些 SOTA 深度学习模型试图对一类特定的图像(称为敌对图像)进行预测时,它们中的大多数都陷入困境。对立例子的整体概念可以是自然例子,也可以是合成例子。我们将通过本文中的几个例子来熟悉不同的对抗性例子和攻击。
对立的例子
自然对立的例子是模型难以理解的自然的、有机的图像。一个合成的对抗性示例是,攻击者(恶意用户)故意将一些噪声注入到图像中,该图像在视觉上与原始图像非常相似,但该模型最终做出了非常不同(并且错误)的预测。让我们更详细地看看其中的几个!
自然对立的例子
这些例子,如论文 【亨德里克斯等人的自然对抗例子】 中所定义的,是现实世界中的、未修改的、自然发生的例子,导致分类器精度显著降低。他们引入了两个新的自然对立例子的数据集。第一个数据集包含 7,500 个 ImageNet 分类器的自然对立示例,用作硬 ImageNet 分类器测试集,称为 IMAGENET-A。下图显示了 ImageNet-A 数据集中的一些对立示例。

ResNet-50 在 ImageNet-A 的例子上失败得很惨(来源:https://arxiv.org/abs/1907.07174))
你可以清楚地看到多么错误(和愚蠢!)是最新型(SOTA) ResNet-50 模型对上述示例的预测。事实上,DenseNet-121 预训练模型在 ImageNet-A 上仅获得 2%的准确度!

来源:https://github . com/dipanjanS/adversarial-learning-robustness
作者还策划了一个名为 IMAGENET-O 的对抗性分布外检测数据集,他们声称这是第一个为 IMAGENET 模型创建的分布外检测数据集。下图显示了对 ImageNet-O 数据集中的图像进行 ResNet-50 推理的一些有趣示例。

ResNet-50 在 ImageNet-O 的例子上非常失败(来源:【https://arxiv.org/abs/1907.07174】T2)
这些例子确实很有趣,并展示了 SOTA 预训练视觉模型在这些图像中的一些图像上的局限性,这些图像对于这些模型来说解释起来更复杂。失败的一些原因可以归因于深度学习模型在对特定图像进行预测时试图关注的内容。让我们看更多的例子来理解这一点。

ImageNet-A 中的自然对抗性例子(来源:【https://arxiv.org/abs/1907.07174】T4)
根据上图中展示的例子,很明显,深度学习视觉模型做出了一些特定的模式错误解释。例如:
- 蜡烛被预测为南瓜灯,尽管没有南瓜,因为模型更关注火焰及其照明等方面
- 由于模型更注重颜色和纹理,蜻蜓被预测为臭鼬或香蕉
- 蘑菇被归类为钉子,因为模型学会了将某些元素联系在一起,例如木钉
- 模型最终也会遭遇泛化问题,比如日晷的阴影
如下图所示,SOTA 深度学习视觉模型在这些示例中的整体性能非常差。

SOTA 深度学习视觉模型在 ImageNet-A 上的表现(来源:https://arxiv.org/abs/1907.07174))
可悲的是,强大的对抗训练方法几乎无助于处理与错误解释自然对抗示例相关的问题,如 Hendrycks 等人在同一篇论文中提到的。其中一些方法包括针对特定合成攻击的训练,如投影梯度下降(PGD)和快速梯度符号方法(FGSM),我们将在后续文章中更详细地讨论。幸运的是,这些方法对于处理恶意合成攻击非常有效,而恶意合成攻击通常是一个更大的问题。
合成对立例子
这些例子基本上涉及在输入图像中人工引入一些噪声,使得它在视觉上仍然保持与原始图像非常相似,但是注入的噪声最终降低了分类器的精度。虽然有各种各样的合成对抗性攻击,但所有这些攻击都遵循一些核心原则,如下图所示。

来源:https://github . com/dipanjanS/adversarial-learning-robustness
重点始终是找出一种方法来完善噪声\扰动张量(值的矩阵),它可以叠加在原始图像的顶部,使得这些扰动对人眼不可见,但最终使深度学习模型无法做出正确的预测。上面描述的示例展示了一种快速梯度符号方法(FGSM)攻击,其中我们在输入图像的梯度符号中添加了一个小乘数,并叠加了一幅熊猫图像,使模型无法预测图像是一只长臂猿。下图展示了一些更常见的对抗性攻击类型。

来源:https://github . com/dipanjanS/adversarial-learning-robustness
下一步是什么?
在接下来的几篇文章中,我们将讨论上述每一种对抗性攻击方法,并通过实际操作的代码示例展示如何欺骗最新和最好的 SOTA 视觉模型。敬请期待!
这篇文章的内容改编自 我最近的博客文章 关于由本人和 Sayak 完成的对抗性学习,你可以在这个 GitHub 库中找到详细的例子。
喜欢这篇文章吗?请联系我进行更多讨论或提供反馈!
[## Dipanjan Sarkar -数据科学领导-应用材料| LinkedIn
我是一名数据科学家,领导多个垂直领域的 ML\DL\CV\NLP 工作。*专注机器学习,深度…
www.linkedin.com](https://www.linkedin.com/in/dipanzan/)
敌对的潜在自动编码器
Python-PyTorch
仅仅通过代码就能生成人脸和表情

比安卡·伯格在 Unsplash 上拍摄的照片
几年前,人脸识别模型风靡互联网。人们完全被计算机如何识别一张脸,甚至在某些情况下可以预测年龄而震惊了!人脸识别很快渗透到大众技术中——以至于今天几乎所有的智能手机都有人脸识别功能。人脸识别软件或安全系统的价格昂贵的时代已经一去不复返了!
然而,自从面部检测系统出现以来,技术以前所未有的速度发展。今天的神经网络不仅可以识别或检测人脸,还可以生成人脸——你我无法从真实人脸中辨别的人脸!想试试吗?检查一下这个😉。
随着生成对抗网络的出现,人脸生成已经成为计算机视觉领域的一个重要研究领域。在这篇文章中,我将阐述一种特殊类型的自动编码器,它有助于比以往任何时候都更好地生成人脸。)对抗性潜在自动编码器(ALAE)——其 预印本 已于 2020 年 4 月 9 日在Arxiv公开。
为了理解敌对潜在自动编码器(ALAE)背后的概念,让我们先来看看它的灵感模型——生成敌对网络和自动编码器。
生成对抗网络
生成性对抗网络是一个双重网络,这两个部分是鉴别器网络和生成器网络。甘氏综合症的有趣之处在于,发生器和鉴别器网络不断地相互竞争,从而迫使对方发挥出自己最好的一面。

GAN 架构—带 SGD
生成器的任务是创建鉴别器无法从真实数据中鉴别的数据。换句话说,生成器试图形成对真实数据分布的估计。理想的生成器应该能够计算出真实的数据分布,从而能够生成无限的数据。与此同时,鉴别器网络只是一个分类器网络——它试图将传递给它的数据分类为真或假。
自动编码器
自动编码器在结构上由编码器、解码器和瓶颈组成。这是一种无监督学习算法,它试图学习恒等函数,并给出尽可能接近输入的输出。

自动编码器架构
更多关于自动编码器的信息请点击。如果你想在评论中发表一篇关于自动编码器的文章,请告诉我!
既然我们已经有了自动编码器和生成对立网络的基本概念,让我们从对立的潜在自动编码器开始。
翅
ALAE 引入了一种通用的自动编码器架构,在学习更少纠缠的表示时,具有与 GANs 相当的生成能力。为了更好地理解 ALAEs 如何获得这两个世界的优点,让我们来看看模型架构。
体系结构
研究工作通过修改原始 GAN 范式引入了一种新的架构。所提出的架构将发生器和鉴别器定义为两个功能的组合

发生器和鉴别器功能—[从左到右]
在定义发生器和鉴别器网络时,已经做了许多重要的假设
- 假设 F 和 G 之间以及 E 和 D 之间的界面处的潜在空间是相同的,用 W 表示。
- 假设 f 是确定性映射,而 G 和 E 是随机映射。
- 还假设 G 可选地依赖于具有已知固定分布的独立噪声输入η。这有助于创建一个更通用的随机生成器。
一般来说,定义自动编码器的常见做法是为潜在空间设置期望的目标潜在分布——编码器被训练来匹配的分布。另一方面,ALAE 不强加潜在分布来匹配特定的目标分布。潜在分布中的唯一约束是 E 的输出分布必须与 g 的输入分布相同。抓住这一约束,学习过程决定什么对模型最好。
让我们来看看这个建筑的图片——

https://arxiv.org/abs/2004.04467ALAE 建筑事务所
这是一般的 ALAE 架构。你可能想知道为什么架构是抽象的——为什么它不是用卷积层和激活之类的东西构建的。那是因为这只是 ALAE 架构的一般概念。我们在这里没有定义完整的架构。完整的架构取决于我们在哪里使用 ALAE 作为自动编码器。
花柱翼
StyleALAE 使用基于 StyleGAN 的生成器以及对抗的潜在自动编码器。这个架构可以表达为—

*StyleALAE 建筑—【https://arxiv.org/abs/2004.04467 *
发生器是从 StyleGAN 架构改编的网络,而编码器是从 ALAE 改编的架构。编码器被设计成与发生器网络对称,以便从图像中捕获风格信息。添加实例标准化层以获得每个通道的平均值和标准偏差,有效地从每个级别中提取样式表示。
StyleALAE 在 ALAE 和 StyleGAN 的帮助下,利用人工智能提高了人脸和表情生成的标准。StyleALAE 模型的官方实现可以在这里 找到 。
让我们来看看这个模型能够实现什么——

StyleALAE 生成的图像—https://github.com/podgorskiy/ALAE
是的,这是生成的图像!抓到你了,不是吗?😉
从 arxiv 的 预印本 中了解更多关于 ALAE 的信息,并确保也能很好地阅读 StyleGAN 网络。如果你在什么地方卡住了,请告诉我!—乐意帮忙😄。
查看我的博客以获得更快的更新,不要忘记订阅:D 优质内容
克罗伊斯,吕底亚(小亚细亚)的国王,曾经问特尔斐的神谕,他是否应该对波斯开战…
www.theconvolvedblog.vision](https://www.theconvolvedblog.vision)
Hmrishav Bandyopadhyay 是印度 Jadavpur 大学电子与电信系的二年级本科生。他的兴趣在于深度学习、计算机视觉和图像处理。他的联系方式是:hmrishavbandyopadhyay@gmail.com | |https://hmrishavbandy . github . io*
对抗性机器学习缓解:对抗性学习
一种保护机器学习模型免受恶意攻击的简单方法
文献中有几种针对深度学习模型的攻击,包括快速梯度符号法(FGSM)(BIM)或动量迭代法** (MIM)攻击。这些攻击是攻击者用来躲避分类模型的最纯粹的基于梯度的躲避技术。**
引用代码
如果您认为这些结果有用,请引用本文:
@PROCEEDINGS{catak-adv-ml-2020,
title = {Deep Neural Network based Malicious Network Activity Detection Under Adversarial Machine Learning Attacks},
booktitle = {Proc.\ 3rd International Conference on Intelligent Technologies and Applications (INTAP 2020)},
volume = 5805,
series = {LNCS},author = {Ferhat Ozgur Catak},
publisher = {Springer},
year = {2020}
}
介绍
在这项工作中,我将提出一种新的方法来保护恶意活动检测模型免受几种敌对的机器学习攻击。因此,我们探索了应用对抗性训练来建立一个对抗 FGSM 攻击的健壮模型的能力。相应地,(1)用对立的例子增强数据集;(2)使用 KDDCUP99 数据集训练基于深度神经网络的检测模型,以学习基于 FGSM 的攻击模式。我们将这个训练模型应用于基准网络安全数据集。
对抗性机器学习被用来描述对机器学习模型的攻击,它试图通过恶意输入实例误导模型。图中显示了典型的对抗性机器学习攻击。

典型的机器学习模型基本上包括两个阶段,即训练时间和决策时间。因此,对抗性机器学习攻击发生在训练时间或决策时间。根据攻击的时间,黑客用于对抗性机器学习的技术可以分为两种:
- ****数据中毒:攻击者改变训练输入实例的一些标签,误导输出模型。
- ****模型中毒:黑客在模型创建后,利用一些被扰动的实例驱动模型产生虚假标签。
我们的模型能够应对黑客使用对抗性机器学习方法进行的模型攻击。该图说明了用于保护模型和正确分类的系统架构。

让我们编码吧
我们导入通常的标准库加上一个 cleverhans 库,对深度学习模型进行对抗性攻击。
from sklearn.datasets import fetch_kddcup99
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
from sklearn import preprocessing
import tensorflow as tf
import pandas as pd
import numpy as np
from keras.utils import np_utils
from cleverhans.future.tf2.attacks import fast_gradient_method, \
basic_iterative_method, momentum_iterative_method
np.random.seed(10)
在这项工作中,我们将使用标准的 KDDCUP'99 入侵检测数据集来显示结果。我们需要从数据集中提取数字特征。我创建了一个新方法来加载和提取 KDD cup’99 数据集。
COL_NAME = ['duration', 'protocol_type', 'service', 'flag', 'src_bytes',
'dst_bytes', 'land', 'wrong_fragment', 'urgent', 'hot',
'num_failed_logins', 'logged_in', 'num_compromised', 'root_shell',
'su_attempted', 'num_root', 'num_file_creations', 'num_shells',
'num_access_files', 'num_outbound_cmds', 'is_host_login',
'is_guest_login', 'count', 'srv_count', 'serror_rate',
'srv_serror_rate', 'rerror_rate', 'srv_rerror_rate',
'same_srv_rate', 'diff_srv_rate', 'srv_diff_host_rate',
'dst_host_count', 'dst_host_srv_count', 'dst_host_same_srv_rate',
'dst_host_diff_srv_rate', 'dst_host_same_src_port_rate',
'dst_host_srv_diff_host_rate', 'dst_host_serror_rate',
'dst_host_srv_serror_rate', 'dst_host_rerror_rate', 'dst_host_srv_rerror_rate']
NUMERIC_COLS = ['duration', 'src_bytes', 'dst_bytes', 'wrong_fragment',
'urgent', 'hot', 'num_failed_logins', 'num_compromised',
'root_shell', 'su_attempted', 'num_root', 'num_file_creations',
'num_shells', 'num_access_files', 'num_outbound_cmds', 'count',
'srv_count', 'serror_rate', 'srv_serror_rate', 'rerror_rate',
'srv_rerror_rate', 'same_srv_rate', 'diff_srv_rate',
'srv_diff_host_rate', 'dst_host_count', 'dst_host_srv_count',
'dst_host_same_srv_rate', 'dst_host_diff_srv_rate',
'dst_host_same_src_port_rate', 'dst_host_srv_diff_host_rate',
'dst_host_serror_rate', 'dst_host_srv_serror_rate',
'dst_host_rerror_rate', 'dst_host_srv_rerror_rate']
def get_ds():
""" get_ds: Get the numeric values of the KDDCUP'99 dataset. """
x_kddcup, y_kddcup = fetch_kddcup99(return_X_y=True, shuffle=False)
df_kddcup = pd.DataFrame(x_kddcup, columns=COL_NAME)
df_kddcup['label'] = y_kddcup
df_kddcup.drop_duplicates(keep='first', inplace=True)
df_kddcup['label'] = df_kddcup['label'].apply(lambda d: \
str(d).replace('.', '').replace("b'", "").\
replace("'", ""))
conversion_dict = {'back':'dos', 'buffer_overflow':'u2r', 'ftp_write':'r2l',
'guess_passwd':'r2l', 'imap':'r2l', 'ipsweep':'probe',
'land':'dos', 'loadmodule':'u2r', 'multihop':'r2l',
'neptune':'dos', 'nmap':'probe', 'perl':'u2r', 'phf':'r2l',
'pod':'dos', 'portsweep':'probe', 'rootkit':'u2r',
'satan':'probe', 'smurf':'dos', 'spy':'r2l', 'teardrop':'dos',
'warezclient':'r2l', 'warezmaster':'r2l'}
df_kddcup['label'] = df_kddcup['label'].replace(conversion_dict)
df_kddcup = df_kddcup.query("label != 'u2r'")
df_y = pd.DataFrame(df_kddcup.label, columns=["label"], dtype="category")
df_kddcup.drop(["label"], inplace=True, axis=1)
x_kddcup = df_kddcup[NUMERIC_COLS].values
x_kddcup = preprocessing.scale(x_kddcup)
y_kddcup = df_y.label.cat.codes.to_numpy()
return x_kddcup, y_kddcup
基于张量流的分类模型然后作为练习给出如下:
def create_tf_model(input_size, num_of_class):
""" This method creates the tensorflow classification model """
model_kddcup = tf.keras.Sequential([
tf.keras.layers.Dense(200, input_dim=input_size, activation=tf.nn.relu),
tf.keras.layers.Dense(500, activation=tf.nn.relu),
tf.keras.layers.Dense(200, activation=tf.nn.relu),
tf.keras.layers.Dense(num_of_class),
# We seperate the activation layer to be able to access
# the logits of the previous layer later
tf.keras.layers.Activation(tf.nn.softmax)
])
model_kddcup.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
return model_kddcup
下一步是使用 CleverHans 库创建对抗性的机器学习攻击。我对 Tensorflow 库使用了快速梯度符号法(FGSM)基本迭代法** (BIM)或动量迭代法 (MIM)攻击。我为每次攻击创造了 3 种方法。**
def gen_tf2_fgsm_attack(org_model, x_test):
""" This method creates adversarial examples with fgsm """
logits_model = tf.keras.Model(org_model.input, model.layers[-1].output)
epsilon = 0.1
adv_fgsm_x = fast_gradient_method(logits_model,
x_test,
epsilon,
np.inf,
targeted=False)
return adv_fgsm_x
def gen_tf2_bim(org_model, x_test):
""" This method creates adversarial examples with bim """
logits_model = tf.keras.Model(org_model.input, model.layers[-1].output)
epsilon = 0.1
adv_bim_x = basic_iterative_method(logits_model,
x_test,
epsilon,
0.1,
nb_iter=10,
norm=np.inf,
targeted=True)
return adv_bim_x
def gen_tf2_mim(org_model, x_test):
""" This method creates adversarial examples with mim """
logits_model = tf.keras.Model(org_model.input, model.layers[-1].output)
epsilon = 0.1
adv_mim_x = momentum_iterative_method(logits_model,
x_test,
epsilon,
0.1,
nb_iter=100,
norm=np.inf,
targeted=True)
return adv_mim_x
让我们继续用正常的(未被操纵的)KDDCUP'99 数据集训练攻击检测模型
EPOCH = 50
TEST_RATE = 0.2
VALIDATION_RATE = 0.2
X, y = get_ds()
num_class = len(np.unique(y))
attack_functions = [gen_tf2_bim,
gen_tf2_fgsm_attack,
gen_tf2_mim]
model = create_tf_model(X.shape[1], num_class)
X_train, X_test, y_train, y_test = train_test_split(X, y, \
test_size=TEST_RATE)
y_train_cat = np_utils.to_categorical(y_train)
y_test_cat = np_utils.to_categorical(y_test)
history = model.fit(X_train, y_train_cat, epochs=EPOCH,
batch_size=50000, verbose=0,
validation_split=VALIDATION_RATE)
y_pred = model.predict_classes(X_test)
cm_org = confusion_matrix(y_test, y_pred)
print("*"*50)
print("Original confusion matrix")
print(cm_org)C:\Users\ferhatoc\AppData\Roaming\Python\Python37\site-packages\pandas\core\frame.py:3997: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
errors=errors,
WARNING:tensorflow:AutoGraph could not transform <function Model.make_train_function.<locals>.train_function at 0x0000025288139948> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_train_function.<locals>.train_function at 0x0000025288139948> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING:tensorflow:AutoGraph could not transform <function Model.make_test_function.<locals>.test_function at 0x0000025287FF4318> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_test_function.<locals>.test_function at 0x0000025287FF4318> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING:tensorflow:From <ipython-input-7-6c756bab0648>:24: Sequential.predict_classes (from tensorflow.python.keras.engine.sequential) is deprecated and will be removed after 2021-01-01.
Instructions for updating:
Please use instead:* `np.argmax(model.predict(x), axis=-1)`, if your model does multi-class classification (e.g. if it uses a `softmax` last-layer activation).* `(model.predict(x) > 0.5).astype("int32")`, if your model does binary classification (e.g. if it uses a `sigmoid` last-layer activation).
WARNING:tensorflow:AutoGraph could not transform <function Model.make_predict_function.<locals>.predict_function at 0x0000025283D0E798> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_predict_function.<locals>.predict_function at 0x0000025283D0E798> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
**************************************************
Original confusion matrix
[[10873 16 0 0]
[ 16 17528 6 18]
[ 7 20 403 11]
[ 3 23 4 179]]
原始模型的混淆矩阵
这里显示了原始模型的混淆矩阵。根据混淆矩阵,该模型的分类性能相当好。

让我们继续攻击,被攻击模型的混淆矩阵和敌对训练模型的混淆矩阵
for attack_function in attack_functions:
print("*"*20)
print("Attack function is ", attack_function)
model = create_tf_model(X.shape[1], num_class)
history = model.fit(X_train, y_train_cat, epochs=EPOCH,
batch_size=50000, verbose=0,
validation_split=VALIDATION_RATE)
X_adv_list = []
y_adv_list = []
adv_x = attack_function(model, X_test)
y_pred = model.predict_classes(adv_x)
cm_adv = confusion_matrix(y_test, y_pred)
print("*"*20)
print("Attacked confusion matrix")
print(cm_adv)
print("Adversarial training")
# define the checkpoint
adv_x = attack_function(model, X_train)
adv_x_test = attack_function(model, X_test)
concat_adv_x = np.concatenate([X_train, adv_x])
concat_y_train = np.concatenate([y_train_cat, y_train_cat])
history = model.fit(concat_adv_x, concat_y_train, epochs=EPOCH,
batch_size=50000, verbose=0,
validation_data=(adv_x_test, y_test_cat))
y_pred = model.predict_classes(adv_x_test)
cm_adv = confusion_matrix(y_test, y_pred)
print("*"*20)
print("Attacked confusion matrix - adv training")
print(cm_adv)********************
Attack function is <function gen_tf2_bim at 0x00000252FCF84A68>
WARNING:tensorflow:AutoGraph could not transform <function Model.make_train_function.<locals>.train_function at 0x00000252FD05FDC8> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_train_function.<locals>.train_function at 0x00000252FD05FDC8> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING:tensorflow:AutoGraph could not transform <function Model.make_test_function.<locals>.test_function at 0x00000252877B80D8> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_test_function.<locals>.test_function at 0x00000252877B80D8> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING:tensorflow:AutoGraph could not transform <function Model.make_predict_function.<locals>.predict_function at 0x0000025281E8B168> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_predict_function.<locals>.predict_function at 0x0000025281E8B168> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
********************
Attacked confusion matrix
[[10874 15 0 0]
[ 14 17532 7 15]
[ 6 19 404 12]
[ 3 23 5 178]]
Adversarial training
********************
Attacked confusion matrix - adv training
[[10877 12 0 0]
[ 12 17535 6 15]
[ 1 13 425 2]
[ 0 22 3 184]]
********************
Attack function is <function gen_tf2_fgsm_attack at 0x00000252FCF84B88>
WARNING:tensorflow:AutoGraph could not transform <function Model.make_train_function.<locals>.train_function at 0x0000025281E8B438> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_train_function.<locals>.train_function at 0x0000025281E8B438> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING:tensorflow:AutoGraph could not transform <function Model.make_test_function.<locals>.test_function at 0x0000025288BB38B8> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_test_function.<locals>.test_function at 0x0000025288BB38B8> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING:tensorflow:AutoGraph could not transform <function Model.make_predict_function.<locals>.predict_function at 0x0000025287EF2558> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_predict_function.<locals>.predict_function at 0x0000025287EF2558> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
********************
Attacked confusion matrix
[[10702 180 6 1]
[ 79 17353 31 105]
[ 9 47 376 9]
[ 3 88 8 110]]
Adversarial training
********************
Attacked confusion matrix - adv training
[[10877 11 0 1]
[ 9 17543 4 12]
[ 1 15 422 3]
[ 2 25 2 180]]
********************
Attack function is <function gen_tf2_mim at 0x00000252FCF84D38>
WARNING:tensorflow:AutoGraph could not transform <function Model.make_train_function.<locals>.train_function at 0x00000252875459D8> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_train_function.<locals>.train_function at 0x00000252875459D8> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING:tensorflow:AutoGraph could not transform <function Model.make_test_function.<locals>.test_function at 0x00000252F9990048> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_test_function.<locals>.test_function at 0x00000252F9990048> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING:tensorflow:5 out of the last 14 calls to <function compute_gradient at 0x00000252FCF6A318> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings is likely due to passing python objects instead of tensors. Also, tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. Please refer to https://www.tensorflow.org/tutorials/customization/performance#python_or_tensor_args and https://www.tensorflow.org/api_docs/python/tf/function for more details.
WARNING:tensorflow:AutoGraph could not transform <function Model.make_predict_function.<locals>.predict_function at 0x0000025280355A68> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function Model.make_predict_function.<locals>.predict_function at 0x0000025280355A68> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 4, expecting 3
To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
********************
Attacked confusion matrix
[[10874 15 0 0]
[ 16 17530 5 17]
[ 6 24 400 11]
[ 3 23 5 178]]
Adversarial training
********************
Attacked confusion matrix - adv training
[[10878 11 0 0]
[ 12 17537 4 15]
[ 1 16 420 4]
[ 0 21 2 186]]
对抗性训练结果
基本迭代法(BIM)
被攻击模型的混淆矩阵

对抗训练模型的混淆矩阵

快速梯度符号法
被攻击模型的混淆矩阵

对抗训练模型的混淆矩阵

动量迭代法
被攻击模型的混淆矩阵

对抗训练模型的混淆矩阵

对抗验证
过度拟合的诊断工具

想和其他学习 ML 的人聊天?加入我们的 新 ML 不和谐服务器 !
本帖原载于blog.zakjost.com。去那里可以更好地呈现内联代码。
介绍
如果你在 Kaggle 上研究一些竞争获胜的解决方案,你可能会注意到提到“对抗性验证”(就像这个)。这是什么?
简而言之,我们构建一个分类器来尝试预测哪些数据行来自训练集,哪些来自测试集。如果两个数据集来自同一个分布,这应该是不可能的。但是,如果在你的训练和测试数据集的特征值中存在系统差异,那么分类器将能够成功地学会区分它们。你能学会区分它们的模型越好,你的问题就越大。
但好消息是,你可以分析学习过的模型来帮助你诊断问题。一旦你理解了问题,你就可以着手解决它。
这篇文章是为了配合我制作的一个 YouTube 视频来解释对抗性验证的直觉。这篇博文介绍了本视频中示例的代码实现,但是足够完整,可以自成一体。你可以在 github 上找到这篇文章的完整代码。
学习对抗性验证模型
首先,用一些样板导入语句来避免混淆:
import pandas as pd
from catboost import Pool, CatBoostClassifier
数据准备
对于本教程,我们将使用来自 Kaggle 的 IEEE-CIS 信用卡欺诈检测数据集。首先,我假设您已经将训练和测试数据加载到 pandas DataFrames 中,并分别将其命名为df_train和df_test。然后,我们将通过替换丢失的值来进行一些基本的清理。
# Replace missing categoricals with "<UNK>"
df_train.loc[:,cat_cols] = df_train[cat_cols].fillna('<UNK>')
df_test.loc[:,cat_cols] = df_test[cat_cols].fillna('<UNK>')
# Replace missing numeric with -999
df_train = df_train.fillna(-999)
df_test = df_test.fillna(-999)
对于对抗性验证,我们希望学习一个模型来预测哪些行在训练数据集中,哪些行在测试集中。因此,我们创建一个新的目标列,其中测试样本用1标记,训练样本用0标记,如下所示:
df_train['dataset_label'] = 0
df_test['dataset_label'] = 1
target = 'dataset_label'
这是我们将训练一个模型来预测的目标。现在,训练和测试数据集是分开的,每个数据集只有一个目标值标签。如果我们在这个训练集上训练一个模型,它会知道一切都是 0。相反,我们希望重组训练和测试数据集,然后创建新的数据集来拟合和评估对抗性验证模型。我定义了一个用于组合、洗牌和重新分割的函数:
def create_adversarial_data(df_train, df_test, cols, N_val=50000):
df_master = pd.concat([df_train[cols], df_test[cols]], axis=0)
adversarial_val = df_master.sample(N_val, replace=False)
adversarial_train = df_master[
~df_master.index.isin(adversarial_val.index)
]
return adversarial_train, adversarial_val
features = cat_cols + numeric_cols + ['TransactionDT']
all_cols = features + [target]
adversarial_train, adversarial_test = create_adversarial_data(df_train, df_test, all_cols)
新数据集adversarial_train和adversarial_test,包括原始训练集和测试集的混合,目标表示原始数据集。注:我在特性列表中添加了 *TransactionDT* 。其原因将变得显而易见。
对于建模,我将使用 Catboost。我通过将数据帧放入 Catboost 池对象来完成数据准备。
train_data = Pool(
data=adversarial_train[features],
label=adversarial_train[target],
cat_features=cat_cols
)
holdout_data = Pool(
data=adversarial_test[features],
label=adversarial_test[target],
cat_features=cat_cols
)
建模
这一部分很简单:我们只需实例化一个 Catboost 分类器,并将其应用于我们的数据:
params = {
'iterations': 100,
'eval_metric': 'AUC',
'od_type': 'Iter',
'od_wait': 50,
}
model = CatBoostClassifier(**params)
_ = model.fit(train_data, eval_set=holdout_data)
让我们继续在维持数据集上绘制 ROC 曲线:

这是一个完美的模型,这意味着有一个明确的方法来判断任何给定的记录是在训练集还是测试集中。这违反了我们的训练集和测试集是同分布的假设。
诊断问题和迭代
为了理解该模型是如何做到这一点的,让我们来看看最重要的特性:

TransactionDT 是最重要的特性。考虑到原始的训练和测试数据集来自不同的时间段(测试集出现在训练集的未来),这是完全有意义的。该模型刚刚了解到,如果 TransactionDT 大于上一个训练样本,则它在测试集中。
我包含 TransactionDT 只是为了说明这一点——通常不建议将原始日期作为模型特征。但是好消息是这项技术以如此戏剧性的方式找到了它。这种分析将清楚地帮助您识别这样的错误。
让我们排除 TransactionDT,再次运行这个分析。
params2 = dict(params)
params2.update({"ignored_features": ['TransactionDT']})
model2 = CatBoostClassifier(**params2)
_ = model2.fit(train_data, eval_set=holdout_data)
现在 ROC 曲线看起来像这样:

它仍然是一个相当强的模型,AUC > 0.91,但比以前弱了很多。让我们来看看该模型的功能重要性:

现在,id_31是最重要的特性。让我们看一些价值观来理解它是什么。
[
'<UNK>', 'samsung browser 6.2', 'mobile safari 11.0',
'chrome 62.0', 'chrome 62.0 for android', 'edge 15.0',
'mobile safari generic', 'chrome 49.0', 'chrome 61.0',
]
该列包含软件版本号。显然,这在概念上类似于包含原始日期,因为特定软件版本的第一次出现将对应于其发布日期。
让我们通过从列中删除任何不是字母的字符来解决这个问题:
def remove_numbers(df_train, df_test, feature):
df_train.loc[:, feature] = df_train[feature].str.replace(
r'[^A-Za-z]', '', regex=True
) df_test.loc[:, feature] = df_test[feature].str.replace(
r'[^A-Za-z]', '', regex=True
)
remove_numbers(df_train, df_test, 'id_31')
现在,我们列的值如下所示:
[
'UNK', 'samsungbrowser', 'mobilesafari',
'chrome', 'chromeforandroid', 'edge',
'mobilesafarigeneric', 'safarigeneric',
]
让我们使用这个清理后的列来训练一个新的对抗性验证模型:
adversarial_train_scrub, adversarial_test_scrub = create_adversarial_data(
df_train,
df_test,
all_cols,
)
train_data_scrub = Pool(
data=adversarial_train_scrub[features],
label=adversarial_train_scrub[target],
cat_features=cat_colsc
)
holdout_data_scrub = Pool(
data=adversarial_test_scrub[features],
label=adversarial_test_scrub[target],
cat_features=cat_colsc
)
model_scrub = CatBoostClassifier(**params2)
_ = model_scrub.fit(train_data_scrub, eval_set=holdout_data_scrub)
ROC 图现在看起来像这样:

业绩从 0.917 的 AUC 下降到 0.906。这意味着我们已经使模型更难区分我们的训练和测试数据集,但它仍然非常有能力。
结论
当我们天真地将交易日期放入特性集时,对抗性的验证过程有助于清楚地诊断问题。额外的迭代给了我们更多的线索,即包含软件版本信息的列在训练集和测试集之间有明显的差异。
但是流程不能做的是告诉我们如何修复它。我们仍然需要在这里运用我们的创造力。在本例中,我们只是从软件版本信息中删除了所有数字,但这丢弃了潜在的有用信息,并可能最终损害我们的欺诈建模任务,而这正是我们的真正目标。这个想法是你想删除对预测欺诈不重要的信息,但对分离你的训练和测试集很重要。
更好的方法可能是找到一个数据集,给出每个软件版本的软件发布日期,然后创建一个“自发布以来的天数”列来替换原始版本号。这可能有助于更好地匹配训练和测试分布,同时还保持软件版本信息编码的预测能力。
资源
- 第一名卡格尔解决方案报道
- 对抗验证 YouTube 视频
- GitHub 上的示例代码
别忘了加入我们的 新 ML 不和谐服务器 !
用于一般化真实世界应用的对抗训练分类器

凯文·Ku 在 Unsplash 上拍摄的照片
动机:可推广人工智能的目的
计算机视觉领域不断要求提高分类器的准确性。各地的研究人员都试图在某个特定的数据集上以微小的差距打破之前的基准。我们认为这一趋势对于推动人类理解的边缘非常重要,但我们也认为还有一个更大的问题尚未得到充分探索——建立一个可概括的分类器。
那么,什么是广义神经网络呢?为什么概化很重要?既然特异性允许我们对每一项任务保持更高的整体准确性,为什么我们不能每次都对特定的数据集微调我们的神经网络呢?
可推广性指的是机器学习模型对现实世界中可能发生的数据扰动(即背景中的随机对象、图像失真)的抵抗力。对随机性越敏感,就越不具有普适性。当我们部署模型来解决完全未知数据分布的问题时,提高模型的可推广性可以使模型表现得更好。
这非常重要,因为在真实世界的应用中,当最终用户实时向我们提供测试数据时,我们永远不知道底层数据分布何时会改变!出于这个原因,推广神经模型的突破可能会转化为多项机器学习任务(如自动驾驶和语音识别)的性能基准的提高。
因此,我们小组在这个项目中的目标是创建能够对未知扰动下的未知数据进行分类的神经模型。
在本文中,我们将讨论使用对抗示例作为训练数据的方法以及如何生成它们。作为奖励,我们还将探索 CAM 可视化作为解释最后敌对的错误分类行为的一种方式。
模型设计选择
在我们开始设计过程之前,我们考虑了 TensorFlow 2.0 与 Keras 和 PyTorch。最终,我们选择了 TensorFlow 和 Keras,因为它允许更简单的实现和更广泛的预训练模型。我们希望我们的项目最终更加易读和简洁。
我们项目中的主要设计选择包括:
- 将数据扩充与随机翻转、随机裁剪、色彩抖动以及常见的高斯、泊松和椒盐噪声相结合。
- 选择 MobileNet v2 作为基础模型,对预训练模型中的参数数量比率具有非常高的精度(参见优化选择部分),并为数据集处理的微型 ImageNet** 选择合理的模型大小。**
- 结合 神经结构化学习(NSL)对抗正则化 通过在训练过程中注入对抗损失来提高鲁棒性。
我们也考虑过通过替代损失最小化(TRADES) 【张等 2019】实现 权衡启发的对抗性防御,但最终没有考虑。
对抗性范例生成的先验研究
尽管最近用于计算机视觉任务的神经网络已经达到了惊人的精度,但它们仍然极易受到人类察觉不到的微小干扰。
此前,研究人员推测这是由于神经网络的非线性组件,极化了这些激活(想想爆炸梯度)。然而,在解释和利用对立的例子中,作者认为这种脆弱性实际上是由于神经网络的线性组件,即在 LSTM 的 ReLU。即使在非线性 sigmoid 函数的情况下,该模型也常常具有线性范围内的大多数值(即当 x 接近 0 时),进一步支持了这一发现。

图片由 Goodfellow、Shlens 和 Szegedy 提供
在这篇论文中,作者还描述了一种快速的生成对抗性例子的方法,以及我们使用的对抗性训练方法。作者引入了快速梯度符号方法(FGSM)** 来有效地生成对立的例子:计算关于输入的梯度,然后扰动输入,使得:**
input = input + epsilon * sign(gradient)
下面是一个应用于逻辑回归模型的 FGSM 的例子,该模型是在原始论文中对 MNIST 三与七进行训练的。

图片由 Goodfellow、Shlens 和 Szegedy 提供
扰动直接应用于 7,并在 3 上反转,以使模型将 7 错误分类。 FGSM 可以直接并入损失函数,间接产生额外的正则化效果。
作者定位了更好的最终模型准确性和增加的稳健性。对抗范例错误率的错误率从基础模型的 89.4%降低到 17.9%。
模型设置:培训和验证
对于我们的模型,我们只在训练期间使用了一个对抗性的包装器。我们不会在这里包括所有的代码,但是一般的框架应该是这样的。
base = **create_model**('base', dim, 2, len(classe))
adv_model = **nsl**.**keras**.**AdversarialRegularization**(base, config, ...)
adv_model.**compile**(optimizer=keras.optimizer.SGD,...))
有一些对包装器最重要的超参数。它们是乘数和步长。乘数对正则化有重要影响,步长用于在验证过程中寻找对立的例子。
config = **nsl.configs.make_adv_reg_config**(
**multiplier**=0.2,
**adv_step_size**=0.2,
**adv_grad_norm**='infinity',
)
训练时间过程基本上与其他 Keras 模型相同,但是要确保数据集被转换为字典,而不是元组,因为您将数据提供给包装器,而不是实际的分类器。
def **convert**(image, label):
**return** {IMAGE_INPUT_NAME: image, LABEL_INPUT_NAME: label}train_data_adv = train_data.**map**(convert)
val_data_adv = val_data.**map**(convert)
在验证过程中,一定要创建一个基本的参考模型,以确保您的对抗性包装器训练有效。您应该会看到,在受干扰的数据上,您的对抗性模型的性能显著提高,而在未受干扰的数据上,您的性能只会略微降低。

作者提供的图片,对比准确性
最后,在测试和验证期间,记得使用开头中定义的基本模型。对抗性包装模型应该只在训练时使用,即使您使用标准 Keras API 保存对抗性包装模型的权重,它也只会保存基础模型的权重。因此,请确保始终将权重加载到基础模型中,然后添加包装器,否则会出现不匹配的问题。
优化选择
由于以前的经验和论文表明 SGD 更适合 CV 任务,我们使用 SGD 而不是 ADAM。出于同样的原因,我们没有预先决定微调不同层的时期数,而是在训练损失达到稳定状态时转移到更高层。
由于我们选择使用 Keras 作为我们的框架,我们还在其他网络架构上测试了相同的训练方法:
- 丹塞尼特·雷斯 NeXt
- 纳斯网,纳斯网移动
- B6 B4 区 B2 效率网
NASNet 由于参数数量太多而容易过度拟合,我们发现 MobileNet V2 表现最好。EfficientNet 是一个势均力敌的竞争者,但我们无法使用它,因为它后来加入了 TensorFlow(它只在 tf-nightly 中可用,所以我们几乎每天都有新的技术问题)。
我们将跳过选择批量大小和学习速率的过程,因为优化这些的方法在深度学习论文和其他中等帖子中随处可见。我们将简单地指出,它们在培训绩效中发挥了很大的作用,并且在不同的模型中有所不同。

图片由作者提供,NASNet 过拟合微型图像网络数据集
[额外]可解释的人工智能挑战
当前的分类方法要求输入并产生类,而没有对上下文或结果的任何可理解的解释。实际上,这使得深度学习算法成为研究人员和工程师的黑匣子。在这个项目中,我们通过提供我们自己对敌对行为和一般错误分类的解释,解决了可解释的人工智能挑战。
在接下来的几节中,显著性指的是视觉处理环境中特定输入的一些独特特征。基本上,显著性可视化方法允许强调图像上视觉上吸引人的位置,这些位置可能“有助于”神经工作做出特定的分类决策。
对于我们应该可视化哪种类型的显著性,有许多选择。一些例子包括使用导向传播的线性激活或噪声生成,但是我们在这里不讨论它们。我们简单地将最后一层改为线性激活,看看哪些像素对分类决策的影响最大。我们使用了 keras-vis 模块。这两个显著图分别示出了正梯度和负梯度。
我们将在这里注意到,keras-vis 稍微有些过时,可能无法与 TensorFlow 2.0 Keras 的某些版本一起使用。

作者图片
我们的模型能够正确预测蟑螂标签。我们可以看到模型能够很容易地做到这一点,因为最后一层的线性激活最大化清楚地显示了蟑螂的形状。

作者图片
我们的模型没有正确分类这个对象。这可以通过以下事实来解释:微小图像网络通常具有较低的分辨率,导致来自具有相似形状的物体的相似激活。这里的错误分类是扫帚**(ImageNet 中的 n02906734)。我们也可以将这归因于我们在训练数据扩充过程中的随机裁剪,我们可能在训练过程中裁剪出了扫帚柄。**
在下面的注射器示例中,这些图像的激活非常相似,因此我们的模型决定在 Oboe 、注射器、扫帚和啤酒瓶之间进行选择。这是前五大预测之一。

作者图片
这个误分类是一个啤酒瓶(n02823428)** ,合理的猜测吗?**
我们还可视化了我们生成的一些对抗性训练示例。这些物体对人类来说是可识别的,但对神经网络来说,它们通常被某种类型的激活无效所掩盖。在下面的例子中,很明显,这里的激活与之前看到的原始对象形状没有任何相似之处。

作者图片
激活和抑制变得随机和扭曲。

作者图片
激活和抑制是模糊的。
正确使用虚拟环境的建议和提示
因为虚拟环境能够并且将会让您省心

来源:https://unsplash.com/photos/wl5AypUmamo
2020 年初,我正在使用 Keras/Tensorflow 进行一个学校项目。一切都很顺利。然后,我和我的队友分享了我的代码,这样他也可以开始工作了。然而,出于某种原因,这对他不起作用。
我们花了几个小时想弄明白。最终,我们意识到这个问题是由于我们安装了不同版本的包造成的。一旦我们设法让它全部工作,我决定找到一种方法来避免这个问题再次发生。
这就是虚拟环境的用武之地。
如果你已经熟悉虚拟环境,你可以跳到第四部分,在那里我会给出一些建议和技巧来帮助你改进和定制你对虚拟环境的使用。
1.为什么要使用虚拟环境?
随着您对 Python 的掌握越来越好,您将会使用越来越多的包,并且正确处理对早期版本包的依赖性将会越来越困难,因此需要虚拟环境。
可以将虚拟环境想象成一个独立的文件夹,您可以在其中保存特定版本的包,甚至是特定的 Python 版本,而不会影响您的其他项目。
这是一个简单的方法,可以确保你(和其他人)总是运行 Python 脚本而没有依赖问题,也就是说,总是为你的包使用正确的版本。
所有出现的代码都可以直接从 Anaconda 提示符或命令行执行。
2.如何创建虚拟环境
超级简单。首先,确保你安装了 virtualenv,创建虚拟环境的库:pip install virtualenv。
然后,下面几行代码将为您的项目创建一个新文件夹,并在其中创建/激活一个虚拟环境。
> mkdir new_folder **#create new folder for project**
> cd new_folder **#set current directory to folder** > virtualenv venv **#Create a virtual environment called venv**
> cd venv/Scripts **#Set working directory to venv**
> . activate **#Activate the environment**
从那里,您可以安装您需要的所有软件包及其特定版本:pip install beautifulsoup4==4.9.1。
然而,有一个更好的方法可以做到这一点。
3.使用 requirements.txt 文件
通过创建一个需求文件,您可以指定您想要在您的虚拟环境中使用的包和版本。下面是它应该是什么样子的一个例子:

然后,在确保文件位于当前工作目录中之后,您可以使用以下代码行安装文件中提到的所有软件包:
> pip install -r requirements.txt
这很好,但是还有一个更好的方法,我将在下一节中介绍。
4.其他有用的提示和技巧
这里有一些提示和技巧,我相信它们会促进甚至改善你对虚拟环境的使用。
- 自动创建一个 requirements.txt 文件
不需要手动创建需求文件,您可以(也应该)做的是将您的 Python 脚本放在虚拟环境中,并编写以下代码行:
> pip freeze > requirements.txt
这将为您自动创建它。
另一个选择也是使用pipregs库。您所要做的就是将 Python 脚本的位置设为当前目录,然后键入pipregs。
> pip install pipreqs
> pipreqs
这将找到您的 Python 脚本,检测所有正在使用的包(和版本),并从中创建 requirements.txt 文件。
2。用特定的 Python 版本创建虚拟环境
如果您想让您的脚本在特定的 Python 版本上运行,这是很容易做到的。首先,确保您单独下载了您想要使用的版本。
然后,在创建虚拟环境时,将代码的virtualenv venv部分改为这样(例如,如果您想使用 Python 3.7):
> virtualenv venv --python=python3.7
3。不要把你的 Python 脚本放在虚拟环境中
删除虚拟环境最简单的方法是手动删除其文件夹。如果您将 python 脚本和需求文件插入其中,它们将随之被删除,这可能不是您想要做的。
您可能还想为多个项目使用同一个虚拟环境。将一切分开可以避免问题。
最好的办法是将这些文件放在虚拟环境之外,如下所示:

4。直接从虚拟环境中运行 Python 代码
如果您想直接从您的虚拟环境中运行您的代码,您只需在您的文件名前添加python,就像这样:
> python flights_scraping.py
我希望这有所帮助。非常感谢你的阅读!
对成功的数据科学职业生涯的建议

我之前写过如何建立数据科学作品集,其中涵盖了向潜在雇主展示你能做什么的重要性,而不仅仅是告诉他们你能做些什么。本博客利用 Orysya Stus 的成功是冰山图作为框架,展示了人们在感知数据科学成功之旅中的几个方面经常被隐藏起来。这个博客旨在表明,大多数人都不得不付出相当多的努力才能达到现在的位置。他们必须努力工作,有时会经历失败,表现出纪律性,坚持不懈,致力于目标,有时会牺牲或冒险。就这样,让我们开始吧!
错误/失败
正如你在上面凯特琳·哈东(在线医疗的首席数据科学家)为她的推特创建的 GIF 图中所看到的,人们在日常模型构建中会犯很多技术错误/失败。
我们大多数编码或从事数据科学的人经常看到彼此工作的最终产品——而不是我们作为过程的一部分所做的草稿、错误和决策。围绕这些步骤的一点透明度将大有帮助。
Jake VanderPlas 在一条关于开源的推文中似乎呼应了类似的观点,人们通常只看到最终产品而不是过程。
在开源中,我们经常看到的是最终产品,而不是过程……这可能会让那些一开始就看到周围完美事物的人感到沮丧。
但是我敢打赌,在任何成功的开源项目的光鲜外表背后,都有大量的痛苦、烦恼和自我怀疑。
除了技术故障,还有其他类型的故障,包括你可以穿的类型(日志拒绝,电子邮件拒绝等)。凯特琳·k·柯比(Caitlin k . Kirby)毫不夸张地说出了她的失败/拒绝。在华盛顿邮报上有一篇文章详细描述了她的裙子是用她在过去五年里收到的 17 封拒绝信(杂志拒绝、电子邮件拒绝等)手工制作的及膝服装。
顺便说一句,如果你想知道更多软件/数据科学相关的拒绝故事,有一个完整的拒绝网站你可以看看,也许会对你有所启发。
努力工作/坚韧不拔

大多数人不得不努力工作才能达到现在的位置。我绝对不是说你必须每周例行工作 70-90 小时,因为这听起来不健康。Rachel Thomas’帖子提到了这种态度是如何具有歧视性和适得其反的。
我们需要尽可能地摆脱工作时间的长短才是最重要的这种肤浅想法。科技行业对长得离谱的工作时间的痴迷不仅对许多残疾人来说是不可及的,而且对每个人的健康和人际关系都是有害的,但正如奥利维亚·戈德希尔为石英在工作指出的那样,对生产力的研究表明这只是低效的:
无数研究表明,这根本不是真的。随着工作时间的延长,生产率会急剧下降,一旦人们每周工作 55 个小时,生产率就会完全下降,以至于平均来说,一个人每周工作 70 个小时并不比一个同事少工作 15 个小时。
疯狂的长时间工作在学术界也很常见,正如下面提到的杰克·范德普拉斯、推特。

虽然这条推文不是对吴恩达之前推文的评论,但我认为它表明了成功有不同的方式,而不是持续工作。 Python 数据科学手册的作者似乎做得不错。(发推文发推文杰克·范德普拉斯
与其努力工作,也许我们应该谈论坚韧或坚持,就像杰瑞米·霍华德的新书和西尔万·古格的新书一样。

简而言之,我认为最好的方法是:
你将面临许多障碍,既有技术上的,也有(甚至更困难的)你周围不相信你会成功的人。有一种方法肯定会失败,那就是停止尝试。
坚持

图片来自我的博客文章
生活中的许多成功都与坚持不懈有关。有很多像 Airbnb 的数据科学家 Kelly Peng 这样的成功人士的故事,他们真的坚持不懈,不断工作和改进。在她的一篇博文中,她回顾了自己申请和面试了多少个职位。
应用:475
电话采访:50 次
完成数据科学带回家的挑战:9
现场面试:8 次
优惠:2
花费的时间:6 个月
她明明申请了很多工作,还一直在坚持。在她的文章中,她甚至提到你需要从面试经历中不断学习。
记下你被问到的所有面试问题,尤其是那些你没有回答的问题。你可以再次失败,但不要在同一个地方失败。你应该一直学习和提高。
纪律/奉献精神

这篇文章的主题之一是每个人都经历过一些失败。重要的是有些人竭尽全力去实现他们的目标。在 Andreas Madsen 发表的一篇博文中,他描述了进入 AI(通常是计算机科学系)的顶级博士项目有多难。实际上,他采访的所有教授都告诉他,要进入顶级博士项目,他需要“在顶级 ML 领域发表 1-2 篇论文”。他花了 7 个月的时间在一个没有资金和没有导师的研究项目上工作,以产生可以出版的作品。
牺牲/冒险

图片由迈克尔·加拉尼克
牺牲和风险可以以多种不同的形式出现。一个风险可能是忽视来自上面的命令。格雷格·林登在亚马逊的时候,他在做几个有趣的项目,尽管他本应该做其他事情。在他的一篇博客文章中,他描述了一个项目:
根据你的亚马逊购物车中的商品进行推荐。添加一些东西,看看有什么发现。再加几个,看看有什么变化…我黑出了一个原型。在一个测试网站上,我修改了 Amazon.com 的购物车页面,以推荐您可能喜欢添加到购物车中的其他商品。在我看来相当不错。我开始四处展示。
有一个问题。
虽然反应是积极的,但也有一些担忧。特别是,一位营销高级副总裁坚决反对……在这一点上,我被告知我被禁止在这方面做任何进一步的工作。我被告知亚马逊还没有准备好推出这项功能。应该就此打住。
相反,我为在线测试准备了这个特性。我相信购物车的推荐。我想衡量销售影响。
我听说 SVP 发现我推出一项测试后很生气。但是,即使是高层管理人员,也很难阻止测试。测量很好。反对测试的唯一有力论据是,负面影响可能非常严重,以至于亚马逊无法承受,这一点很难断言。测试开始了。
结果很明显。它不仅赢了,而且以如此大的优势赢得了这项功能,以至于没有上线让亚马逊付出了相当大的代价。随着新的紧迫性,购物车建议推出…
当时,亚马逊肯定是混乱的,但我怀疑我忽视来自上面的命令是在冒险。尽管亚马逊很好,但它还没有完全接受衡量和辩论的文化。
虽然我不提倡忽视上级的建议,但似乎在某些情况下,冒险对公司和你自己都有好处。
结论

希望你能从这篇博客中找到一些建议和例子,对你的数据科学之旅有所帮助。请记住,许多来自成功人士的建议都存在生存偏见。总是半信半疑地接受建议或分享经验。如果你有任何问题,对这篇文章有什么想法,或者只是想分享你自己的经历,欢迎在下面的评论中或者通过推特联系我们。
AES 加密 256 位

Bermix 工作室在 Unsplash 拍摄的照片
统治它们的加密标准
AES(高级加密标准)是使用最广泛的对称加密算法。AES 应用广泛,包括静态数据加密和安全文件传输协议,如 HTTPS。
AES 是 DES 的继承者。数据加密标准(DES)是 IBM 开发的一种对称加密算法。过去,DES 曾是事实上的加密算法。然而,它使用的是 56 位密钥,随着技术的进步,对它的攻击开始变得更加可信。最终,DES 被认为太不安全而不能继续使用。社区过渡到了三重 DES(直到今天仍然存在)。本质上,三重 DES 是连续执行 3 次的 DES。正如所料,三重 DES 比普通 DES 安全 3 倍。然而,它也慢了 3 倍。
美国政府举办了一场竞赛,想出三重 DES 的替代方案。最终,由两位比利时密码学家文森特·里门和琼·代蒙编写的 Rijndael,因其性能和在硬件和软件上的易于实现性,以及其安全级别而被选中。 Rijndael 成为美国的高级加密标准,最终也成为世界其他地区的标准。
AES 加密算法
假设鲍勃想给爱丽丝发一条消息。Bob 的未加密消息首先被分解成 128 位的块。然后将给定块中的字节(总共 16 个)组织成 4x4 矩阵。

该块通过以下步骤序列总共 x 次,其中 x 取决于密钥的大小。
- 替代字节
- 移动行
- 混合列
- 添加圆形密钥
替代字节
在该步骤中,矩阵中的每个元素被映射到 Rijndael S-box 中的相应字节。

S-Box
例如,左上角的元素被映射到d4,因为第一个十六进制是1,另一个十六进制是9。


对每个元素重复该过程,我们获得以下矩阵:

移动行
在第二步中,我们将每个元素向左旋转 x 个元素(字节),其中 x 是行的索引。
- 第 0 行—左移 0 字节(即不移位)

- 第 1 行—左移 1 个字节


- 第 2 行—左移 2 个字节


- 第 3 行—左移 3 个字节

我们以下面的矩阵结束:

混合列
我们将每一列乘以一个预定义的矩阵。



需要注意的是,这不是常规的矩阵乘法。如果任何一项大于 2 的 8 次幂,我们将该多项式除以伽罗瓦不可约多项式:

让我们来看看如何计算d4和02的乘积。我们首先将每一位转换成二进制算术等价物(多项式形式)。


我们将两者相乘。


因为乘积大于 2 的 8 次方,所以我们用不可约多项式除它。


我们对每个元素重复该过程,并获得以下矩阵:

添加圆形密钥
在这一步中,我们在前面步骤中获得的矩阵的列和轮密钥之间执行按位异或运算。在第一次迭代中,轮密钥是密码密钥的前 128 位。

圆形钥匙



对剩余的列重复该过程,我们得到:

前面的矩阵被用作下一轮的输入,并且该过程本身被重复另外的 x 轮。
注 :最后一轮不包括混合列步骤。
AES 密钥表
计算下一轮新密钥的过程称为密钥表。正如我们前面提到的,轮数取决于初始密钥的长度。
- 128 位密钥= 10 轮
- 192 位密钥= 12 轮
- 256 位密钥= 14 轮
注意:在所有其他方面,算法完全相同。
与 128 位输入模块以状态数组的形式排列的方式相同,该算法以 4 × 4 字节矩阵的形式排列加密密钥的前 16 个字节。下图显示了原始 128 位密钥的四个字被扩展成由 4 x 11 = 44 个字组成的密钥表。加密密钥的前四个字节构成字 w0,接下来的四个字节构成字 w1,依此类推,直到 w3。

假设我们有第轮轮密钥的四个字。

我们需要确定下一轮要用的词。

该序列中的第一个字计算如下:

其中功能 g 由以下三个步骤组成:
- 对 4 字节字执行一个字节的循环旋转。
- 使用 16 × 16 查找表替换字中的每个字节
- 将从上一步中获得的字节与所谓的 循环常数 进行异或运算。
第轮的 轮常数 t 表示为Rcon【j】。

在哪里
**
注意 :添加舍入常数破坏了算法中其他步骤可能引入的任何对称性,从而使其更难破解。

第一个操作包括旋转字节。
**
然后,我们使用查找表执行字节替换。
**
替换剩余的字节后,我们得到下面的向量。

最后,我们在向量、第一个单词和【Rcon[1]之间执行按位异或运算,以获得新单词。



然后,我们继续计算轮密钥中的剩余单词。






**
新的 4x4 矩阵(轮密钥)用于下一轮的添加密钥步骤。
10 轮中的每一轮都重复该过程。

美学地图:用于空间数据关联上下文的二元图谱
实践教程
你如何观察这两个变量之间的关系?非空间数据的散点图,空间数据的二元线图。
介绍
新冠肺炎病例与城市密度相关吗?人口密度与经济总量相关吗?GDRP 和污染有什么关系?城市比农村更有生产力吗?
这些问题可以通过分析两个空间数据集来回答。一个简单的散点图可能会很快回答这个问题。但在这篇文章中,我想把重点放在空间方面。这是因为这些问题依赖于要素的地理方面。用散点图截断方面可能会隐藏关于数据实际性质的战略性或有影响力的洞察力。正如托布勒的地理法则第一条所说:
一切事物通常都与所有其他事物相关,但是那些彼此靠近的事物比那些离得远的事物更相关
本文介绍了使用地理空间可视化理解数据之间的关联;即理解两个变量与空间环境之间的相关性。如上所述,这是散点图之外的一个选项,我们将看到地理空间方法有何不同。使用双变量图谱进行描述性分析的方法。
(注:观察空间关系的方法有很多种,这个方法只是其中一种。我选择这种方法是因为它简单,容易理解,而且直观。 再加上,就做出了一张漂亮的地图! )
概括地说空间数据
空间数据是具有空间维度的数据。简单来说,我们可以做一个数据图。与典型数据一样,空间数据可以用电子表格的形式表示。典型的电子表格数据和空间数据的区别在于,空间数据有一个存储几何信息的几何列。这种几何信息通常以众所周知的文本格式表示(查看链接文章中的表 1,或者查看这个链接)。
例如,下图:雅加达市的行政边界和相应人口的表格。请注意,它有一个存储地理信息的“geometry”列。另外关于数据格式,请参考我的另一篇文章。

等值区域图
我相信你在生活中一定遇到过 choropleth 地图,只是你不知道它叫“choropleth 地图”。这是一张这样的地图:

雅加达人口分布图(来源:作者,2020;数据来源:印度尼西亚统计局,2020 年)
这是以前的电子表格数据的可视化。看起来很整洁,对吗?典型条形图的一个很好的替代品。空间关系是直观的,但提供了定量信息(人口数据)。
"色彩图是阴影图,其中颜色的强度表示所讨论现象的强度。"— 皇家地理学会
这种直方图依赖于将数据分类到几个箱中,就像直方图一样,并且将唯一的颜色分配给这些箱。分类方法确实会影响结果,从而产生不同的解释。更多关于分类的信息可以在这里找到。
这让我想起分类和图表可能会误导信息(请参考下面的视频,这是批评图表/数据可视化的一个很好的指南)。所以,要注意仓的规模和 choropleth 的分类方法。
进一步扩展-二元颜色
现在,上面的例子(地图)只解释了 1 个变量。我们可以再插入一个变量,这样它就变成了二元颜色。由两个变量组成的弦线图称为二元弦线图。
让我们看看这个例子,好吗?
二元染色体组
这是我做的最新的双变量 Choropleth 地图。在这里,我想通过观察六边形镶嵌地图中人口总数和人口标准差之间的关系来确定城市化的程度。这张地图是我在 Twitter 上参加 #30DayMapChallenge 的作品。

双变量 choropeth(修订)(来源:作者,2020 )
请注意,图例现在有两个变量:标准差和总体总和。六边形包含各个六边形内人口的聚集值;因此,六边形以诸如平均值、中值等统计属性的形式截断。现在,关系由每个变量的颜色组合来表示。混合这些颜色会产生代表变量之间关系的独特颜色组合。此外,六边形地图将数据的空间背景可视化。有了地图,可以直观的看到(地理空间)聚类。
现在,让我们看看散点图是如何可视化这种关系的。我们来做一些对比。
散点图
好的,这是散点图(颜色和地图一样)。

散点图分析(来源:作者,2020)
我不知道你怎么想,但是在看了二元图之后,我发现散点图非常奇怪。"我不能简单地说这种关系是线性的,因为数据中存在聚类,而且这种聚类必须加以说明。这使得数据在空间上是相关的,而不是独立的。这是因为散点图不代表数据的地理性质;您无法观察到空间聚类。简单地进行回归分析是错误的,除非该分析是地理加权的。( 聚类)会导致空间自相关,这给假设残差独立 的统计方法带来问题。
结束语
在我看来,简单的散点图不适合非空间数据,即不依赖于空间元素的数据。绘制散点图会隐藏数据的空间元素和关系,如聚类(空间自相关)。解决这个问题的一个方法是制作一个双变量 choropleth 图;两个变量的 choropleth 图。图表的绘图代表地理信息,而颜色代表变量值的强度。使用双变量 choropleth,数据的空间感也被捕获和呈现。
(个人注:还有,地图变美了,至少对我来说!它给人一种微妙的美感,这种美感随着情感而颤动,尤其是一些精心的设计选择。在这种情况下,我认为制图是一种艺术形式,而不仅仅是数据可视化。)
Aethos 2.0 —自动化数据科学工作流程的改进方法
Aethos 2.0 的新特性

Justin Jairam 拍摄的照片来自 @jusspreme
2019 年底,我发布了 Aethos 1.0,这是自动化常见数据科学技术的第一个迭代包。从那以后,我收到了很多关于如何改进 Aethos 的反馈,我将在这里介绍。将会有很多代码示例来展示该包的强大功能和多功能性。
你可以在 TDS 上看到之前关于 Aethos 第一版的帖子。
注意:你可以通过我的页面上的谷歌协作链接关注这篇文章。
Aethos 是什么?
对于那些不熟悉 Aethos 的人来说,Aethos 是一个自动化数据科学技术和用例的 Python 库,从缺失值插补、NLP 预处理、特征工程、数据可视化到建模、模型分析和模型部署。
要查看完整的功能以及您可以运行的其他技术和模型,请查看 Github 上的项目页面。
Aethos 1.0 的问题
Aethos 第一版的许多问题都与软件包及其 API 的可用性有关。主要问题是:
- 由于文件和耦合包的数量,导入时间很慢。
- 有两个用于端到端分析的对象—用于转换的数据和用于建模的模型
- 模型对象有每一个模型,并不特定于监督或无监督的问题。
- 不直观的 API 要求向底层数据帧添加新列
- 随着将笔记本转换为 pdf 等外部工具的使用,报告功能变得多余。
- API 的用例有限。没有 Aethos,你无法分析你的数据,或分析你训练的模型。
- Aethos 和 Pandas 不可互换,在转换数据时不能一起工作。
Aethos 2.0 的新特性
Aethos 2.0 着眼于解决软件包的直观性和可用性,使其更容易使用和理解。它还解决了与 Aethos 一起使用 Pandas 数据框架的能力。
- 通过简化和分离 Aethos 模块,缩短了软件包的导入时间。
- 只需要一个 Aethos 对象来可视化、转换、建模和分析结果。
- 仅查看针对您的问题的模型(分类、回归或无监督)。
- 消除了通过 Aethos 对象向底层数据帧添加数据的复杂性。您可以使用 x_train 和 x_test 属性访问底层数据帧。
- 删除了报告功能。
- 访问 DataFrame 列时删除了点符号。
- 现在可以将方法链接在一起。
Aethos 2.0 引入了新的对象来支持新的案例:
- 分析:分析、可视化和运行统计分析(t 检验、anova 等)。)在你的数据上。
- 分类:分析、可视化、运行统计分析、转换和估算您的数据以运行分类模型。
- 回归:分析、可视化、运行统计分析、转换和估算您的数据以运行回归模型。
- 无监督:分析、可视化、运行统计分析、转换和估算您的数据以运行无监督模型。
- 分类模型分析:解释、分析和可视化分类模型结果。
- 回归模型分析:解释、分析和可视化回归模型结果。
- UnsupervisedModelAnalysis:解释、分析和可视化无监督的模型结果。
- 文本模型分析:解释、分析和可视化文本模型结果。
注意: 当使用 Aethos 运行模型时,模型分析对象会自动初始化。它们也可以通过提供模型对象、训练数据和测试数据来自行初始化。
例子
!pip install aethos
进口熊猫和鹦鹉。
import pandas as pd
import aethos as atat.options.track_experiments = True # Enable experiment tracking with MLFlow
为了展示每一个物体,让我们载入泰坦尼克号数据集。
orig_data = pd.read_csv('https://raw.githubusercontent.com/Ashton-Sidhu/aethos/develop/examples/data/train.csv')
我们将描述原始数据作为参考。
orig_data.describe()
分析
分析对象主要用于快速、方便地分析和可视化数据。它没有能力运行 Aethos 的自动清理和转换技术,只有可视化和统计测试。它也不会分割您的数据,但是您可以选择提供一个测试集。
df = at.Analysis(orig_data, target='Survived')
让我们从描述我们的数据开始。
df.describe()

df.missing_values

df.column_info()

df.standardize_column_names()

df.describe_column('fare')


df.data_report()

查看多个特征的直方图。
df.histogram('age', 'fare', hue='survived')

创建可配置的相关矩阵。
df.correlation_matrix(data_labels=True, hide_mirror=True)

画出每个年龄买票的平均价格。
df.barplot(x='age', y='fare', method='mean', labels={'age': 'Age', 'fare': 'Fare'}, asc=False)

我们还可以观察年龄和公平之间的关系,并了解幸存者和幸存者之间的差异。
df.scatterplot(x='age', y='fare', color='survived', labels={'age': 'Age', 'fare': 'Fare'}, marginal_x='histogram', marginal_y='histogram')

你可以想象其他的情节,比如雨云,小提琴,盒子,成对等等。我建议查看更多示例。
最大的变化之一是能够和熊猫并肩工作。如果您想转换和处理只与 Pandas 相关的数据,分析对象将反映这些变化。这允许您将 Aethos 单独用于自动分析,将 Pandas 用于转换。
为了演示这一点,我们将使用我们创建的原始 pandas 数据帧创建一个新的布尔特征来查看乘客是否为儿童。
orig_data['is_child'] = (orig_data['age'] < 18).astype(int)
orig_data.head()

现在让我们来看看我们的分析对象。
df.head()

df.boxplot(x='is_child', y='fare', color='survived')

您仍然可以在 Aethos 对象上运行 pandas 函数。
df.nunique()

df['age'].nunique()
88
新功能
Aethos 2.0 中引入了一些新的分析技术。
预测能力得分
预测能力得分是非对称的、数据类型不可知的得分,可以检测两个列之间的线性或非线性关系。分数范围从 0(无预测能力)到 1(完美预测能力)。它可以用作相关性(矩阵)的替代方法。创建这个库需要 8080 个实验室,你可以在这里得到更多信息
df.predictive_power(data_labels=True)

AutoViz
AutoViz 自动可视化您的数据,并根据您的数据特征显示关键图。信用去 AutoViML 创建这个库,你可以得到更多的信息在这里。
df.autoviz()


外加更多!它负责许多您通常会做的可视化工作,并帮助识别特征之间的关系。你可以在这里查看全部输出。
系统模型化
Aethos 2.0 引入了 3 个新的模型对象:分类、回归和无监督。这些对象具有与分析对象相同的功能,但也可以像在 Aethos 1.0 中那样转换数据。对于不熟悉 Aethos 的人来说,每当您使用 Aethos 应用转换时,它会将转换应用于训练数据,并将其应用于训练和测试数据(在分类和回归的情况下),以避免数据泄漏。
在这篇文章中,我们将讨论分类对象,但是如果你正在处理一个回归或者无监督的问题,过程是完全一样的。
df = at.Classification(orig_data, target='Survived', test_split_percentage=.25)
与 Aethos 1.0 一样,如果没有提供测试数据,它会在初始化时被分割。在 Aethos 2.0 中,它使用分类问题的分层来分割数据,以确保类平衡的一些相似性。
警告:前面我们展示了修改原始数据帧并将其反映在 Aethos 对象中的能力。如果你没有为分类和回归对象提供一个测试集,情况就不一样了。
提示: Aethos 附带了一个清单,可以在清理、分析和转换数据时提醒您。
df.checklist()

df.standardize_column_names()

因为这是一个概述,所以让我们选择将要使用的列,去掉我们不打算使用的列。
df.drop(keep=['survived', 'pclass', 'sex', 'age', 'fare', 'embarked'])

让我们把我们的转变连在一起。请记住,我们的转换将适合训练数据,并自动转换我们的测试数据。
is_child = lambda df: 1 if df['age'] < 18 else 0df.replace_missing_median('age') \
.replace_missing_mostcommon('embarked') \
.onehot_encode('sex', 'pclass', 'embarked', keep_col=False) \
.apply(is_child, 'is_child') \
.normalize_numeric('fare', 'age')

df.x_train.head()

df.x_test.head()

现在让我们训练一个逻辑回归模型。
我们将使用 gridsearch,它会自动返回最佳模型。在网格搜索过程中,我们将使用分层 K-fold 进行交叉验证。
gs_params = {
"C": [0.1, 0.5, 1],
"max_iter": [100, 1000]
}lr = df.LogisticRegression(
cv_type='strat-kfold',
gridsearch=gs_params,
random_state=42
)

一旦模型被训练,一个 ModelAnalysis 对象被返回,它允许我们分析、解释和可视化我们的模型结果。包括一个列表,帮助您调试您的模型,如果它是过拟合或欠拟合。
df.help_debug()

您可以通过在产生的 ModelAnalysis 对象上调用cross_validate 来快速交叉验证任何模型。它将显示所有折叠的平均分数和学习曲线。
对于分类问题,默认的交叉验证方法是分层 K-Fold。这允许保持某种形式的类平衡,而对于回归,缺省值是 K 倍。
lr.cross_validate()

lr.metrics() # Note this displays the results on the test data.

手动与自动
让我们手动训练一个逻辑回归,并查看和验证结果。
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, roc_auc_score, precision_scoreX_train = df.x_train.drop("survived", axis=1)
X_test = df.x_test.drop("survived", axis=1)y_train = df.x_train["survived"]
y_test = df.x_test["survived"]clf = LogisticRegression(C=1, max_iter=100, random_state=42).fit(X_train, y_train)
y_pred = clf.predict(X_test)print(f"Accuracy: {accuracy_score(y_test, y_pred).round(3)}")
print(f"AUC: {roc_auc_score(y_test, clf.decision_function(X_test)).round(3)}")
print(f"Precision: {precision_score(y_test, y_pred).round(3)}")
准确度:0.848
AUC: 0.854
精度:0.882
结果是一样的。
模型分析
与建模类似,Aethos 2.0 引入了 4 个模型分析对象:ClassificationModelAnalysis、RegressionModelAnalysis、UnsupervisedModelAnalysis 和 TextModelAnalysis。在 Aethos 2.0 中,它们可以通过两种方式进行初始化:
- 使用 Aethos 训练模型的结果
- 通过提供模型对象、模型使用的训练数据以及评估模型性能(用于回归和分类)的测试数据来自行初始化它。
与模型对象类似,我们将探索分类模型分析对象,但对于回归、无监督和文本模型分析,过程是相同的。
从 Aethos 初始化
首先,我们将从建模的地方开始,查看逻辑回归模型的指标。
type(lr)
aet hos . model _ analysis . class ification _ model _ analysis。分类模型分析
lr.metrics()

您还可以根据您的业务需求来设置项目度量。
at.options.project_metrics = ["Accuracy", "ROC AUC", "Precision"]lr.metrics()

如果您只想查看单个指标,也有相应的功能。
lr.fbeta(beta=0.4999)
0.8380023094880403
您可以用一行代码分析任何模型结果:
- 韵律学
- 分类报告
- 混淆矩阵
- 决策界限
- 决策图
- 依赖图
- 力图
- 石灰地块
- 莫里斯敏感度
- 模型重量
- 汇总图
- 受试者工作特征曲线
- 单个指标
而且这只是针对分类模型,每种类型的问题都有自己的一套 ModelAnalysis 函数。
lr.classification_report()

lr.confusion_matrix()

您可以将训练集中的特征提供给依赖图,否则它将只使用模型中的前两个特征。在引擎盖下,它使用 YellowBricks 决策边界可视化工具来创建可视化。
lr.decision_boundary('age', 'fare')

还包括自动 SHAP 用例来解释你的模型。
lr.decision_plot()

lr.dependence_plot('age')

lr.force_plot()

lr.interpret_model()

查看模型中权重最高的要素。
lr.model_weights()
性别 _ 女:1.16
性别 _ 男:-1.16
pclass_3 : -1.08
年龄:-1.03
pclass _ 1:0.98
is _ child:0.41
上船 _ S:-0.31
船上 _Q : 0.21
上船 _C : 0.10
pclass_2 : 0.10
轻松绘制 RoC 曲线。
lr.roc_curve()

lr.summary_plot()

最后,我们可以使用 FastAPI、Gunicorn 和 Docker 通过 RESTful API 生成文件来部署我们的模型。
lr.to_service('aethos2')

用户初始化
如果我们像之前在笔记本中所做的那样手动训练一个模型,并且想要使用 Aethos 的模型分析功能,我们可以。
lr = at.ClassificationModelAnalysis(
clf,
df.x_train,
df.x_test,
target='survived',
model_name='log_reg'
)
注意: x_train 和 x_test 数据集必须将目标变量作为数据帧的一部分。
你现在可以做我们刚刚做的所有事情,并获得相同的结果。现在,您可以手动转换数据,训练模型,并使用 Aethos 来解释结果。我把它们放在下面以供验证。
type(lr)
aet hos . model _ analysis . class ification _ model _ analysis。分类模型分析
lr.metrics()

lr.fbeta(beta=0.4999)
0.8380023094880403
lr.classification_report()

lr.confusion_matrix()

lr.decision_boundary('age', 'fare')

lr.decision_plot()

lr.dependence_plot('age')

lr.force_plot()

lr.interpret_model()

lr.model_weights()
性别 _ 女:1.16
性别 _ 男:-1.16
pclass_3 : -1.08
年龄:-1.03
pclass _ 1:0.98
is _ child:0.41
embarked _ S:-0.31
fare:0.31
embarked _ Q:0.21
embarked _ C:0.10
pclass _ 2:0.10
lr.roc_curve()

lr.summary_plot()

lr.to_service('aethos2')

反馈
我鼓励所有关于这个帖子或 Aethos 的反馈。你可以在推特上给我发信息,或者在 sidhuashton@gmail.com 给我发电子邮件。
任何 bug 或功能请求,请在 Github repo 上创建问题。我欢迎所有功能请求和任何贡献。如果你想为一个开源项目做贡献,这个项目是一个很好的开端——如果你需要帮助,可以随时给我发消息。
Aethos —自动化工作流程的数据科学库

照片由来自 Pexels 的 Josh Sorenson 拍摄
作为一名行业数据科学家,我相信许多其他数据科学家都会遇到一些棘手问题:
- 将以前项目中的代码复制并粘贴到当前项目中,或者从一个笔记本复制并粘贴到另一个笔记本中是一件令人沮丧的事情。
- 对于同样的任务,每个数据科学家都会以自己的方式来完成。
- 用笔记本名称管理实验会很快变得杂乱无章,构建数据科学项目会变得一团糟。
- 当你在分析过程中记录你的过程通常会打乱你的流程。
- 版本控制模型,将它转换成服务,并在模型被训练后开发数据管道。
- 出现了大量不同的库,每一个都填补了数据科学& ML 的一个空白,每次学习一个新的 API(特别是深度学习和 NLP)或阅读文档(如果有的话)都有点令人厌倦。很讽刺,我知道。
- 制作哪怕是半吸引人的可视化效果通常都很耗时,有时甚至很困难。
这就是为什么我做了艾多斯。
Aethos 是一个自动化数据科学技术和用例的 Python 库,从缺失值插补,到 NLP 预处理、特征工程、数据可视化,一直到建模和生成代码,以部署您的模型即服务,以及您的数据管道。
装置
让我们像安装其他 Python 包一样安装 Aethos:
pip install aethos
一旦安装了 Aethos,我们就可以做一些事情了。我们可以安装所有需要的自然语言处理语料库,
aethos install-corpora
安装 QGrid 等扩展,以便在与数据交互时获得更好的体验
aethos enable-extensions
创建一个数据科学项目,用完整的文件夹结构存放源代码、模型、数据和实验。
aethos create
入门指南
首先,让我们导入必要的库:
import aethos as at
import pandas as pd
在我们开始之前,让我们也配置一些选项,让我们的生活更轻松。就我自己而言,我经常写一份报告,记录我在分析过程中采取的步骤,以及我为什么要这样做,以便更好地与团队中的其他数据科学家交流我的过程,或者如果我在很长一段时间后回到实验中,也可以更好地与自己交流。在我们进行分析时,Aethos 会自动将报告写成文本文件,而不是手动编写报告(所有报告都保存在%HOME%/中)。aethos/reports/)。要让 Aethos 将报告写成 word 文档,我们只需启用选项:
at.options.word_report = True
at.options.interactive_table = True
interactive_table选项将使用 itables 库显示我们的数据,这是我个人最喜欢的库,因为它具有客户端搜索功能。
现在让我们加载数据。Aethos 以熊猫数据帧的形式接收数据,这样数据就可以像处理熊猫一样被加载。在这个例子中,我们将使用泰坦尼克号数据集。
data = pd.read_csv('titanic.csv')
要使用 Aethos,我们只需将数据帧传递给 Aethos 数据对象。
df = at.Data(data, target_field='Survived', report_name='titanic')
df

关于刚刚发生的事情,有几点需要注意:
- 由于这是一个监督学习问题,我们指定了我们想要预测的列(“幸存”)。
- 默认情况下,因为我们没有向数据对象传递任何测试数据,所以 Aethos 会自动将给定的数据分成一个训练集和一个测试集。这可以通过在初始化数据对象时设置
split=False来关闭。 - 默认情况下,分割百分比为 20。这可以通过将
test_split_percentage设置为 0 到 1 之间的浮点数来改变(默认为 0.2)。 - 我们将报告名称指定为
titanic,因为我们指定要创建 Word Doc,所以在%HOME%/.aethos/reports/中将创建一个titanic.txt和一个titanic.docx。
让我们从一些基本的分析开始。
分析
使用数据对象就像处理熊猫数据帧一样。
df['Age'] # returns a Pandas series of the training data in the Age columndf[df['Age'] > 25] # returns a Pandas DataFrame of the the training data where Age is > 25.df.nunique() # You can even run pandas functions on the Data object, however they only operate on your training data.
添加新的列和在 pandas 中做的一样。添加新列时,它会根据数据集的长度将新数据添加到数据集(如果数据被拆分,则进行训练或测试)。但是,您也可以指定将它添加到哪个数据集:
# based off the length of some_iterable it will add to the train set or test set (if data is split).df[`new_col_name`] = `some_iterable`# you can also specify what dataset to add it to as welldf.x_train # pandas dataframe of the training set
df.x_test # pandas dataframe of the test testdf.x_train[`new_col`] = `some_iterable`
df.x_test[`new_col`] = `some_iterable`
Aethos 提供了几个选项,让您可以从整体上了解自己的训练数据。第一个你可能很熟悉。Aethos 的describe函数扩展了 pandas 来提供一些额外的信息。
df.describe()

我们还可以获得关于每个专栏的更详细的信息,所有这些都可以通过 pandas-summary 库获得。
df.describe_column('Age')

该命令还提供了数据的直方图。每个统计值都可以通过引用其名称来访问。
df.describe_column('Age')['iqr']
另一个选项是通过 pandas-profiling 生成 EDA 报告。
df.data_report()

我们还可以用一行代码生成直方图、pairplots 和 jointplots(注意:为了更好地适应本文,图像大小被缩放,并且是可配置的)。
df.jointplot('Age', 'Fare', kind='hex', output_file='age_fare_joint.png')
df.pairplot(diag_kind='hist', output_file='pairplot.png')
df.histogram('Age', output_file='age_hist.png')



接合图、成对图和直方图(从左到右)
我们还可以随时查看两个数据集中缺失值的信息。
df.missing_values

让我们来处理客舱、年龄和上船列中缺失的值。
出于本文的目的,我们将用最常见的值替换Embarked列中缺失的值,用中间值替换Age列中缺失的值。然后我们将删除Cabin列。
df.replace_missing_mostcommon('Embarked')
仅仅几行代码就发生了很多事情。先说插补。
- Aethos 使用已建立的包(sci-kit learn、nltk、gensim 等。)来做所有的分析,在这种情况下,插补。
- 为了避免数据泄露,所有的分析技术都适用于训练集,然后应用于测试集。
- 一般来说,当存在测试集时,对训练集所做的任何事情都将应用于测试集。
- 当您运行一项技术时,该技术的一个简短描述会被写到报告中。
- 所有这些对于每一种 Aethos 分析技术都是一致的,并且可以在源代码这里中查看(这个函数在 cleaning/clean.py 中)。
df.replace_missing_median('Age')
df.drop('Cabin')
让我们也删除 Ticket、Name、PClass、PassengerId、Parch 和 SibSp 列。
df.drop('Ticket', 'Name', 'PClass', 'PassengerId', 'Parch', 'SibSp')
这不是一篇关于为什么你应该在 pandas 中避免使用.apply函数的文章,但是为了 API 的覆盖范围和一致性,你也可以在 Aethos 中使用.apply。指定一个函数和一个输出列名,就可以开始了。
两个最大的区别在于,整个数据帧被传递到函数中,而 Swifter 库用于并行化函数的运行,从而减少运行时间。
def get_person(data):
age, sex = data['Age'], data['Sex']
return 'child' if age < 16 else sexdf.apply(get_person, 'Person')

就像任何其他 Aethos 方法一样,函数get_person适用于训练和测试集。Aethos 在使用.apply时提供了一个优化,但可能的话最好还是使用矢量化。
我们现在可以删除Sex列。
df.drop('Sex')
我们需要将Embarked和Person转换成数字变量,为了简单起见,我们只使用一键编码。我们还想删除用keep_col参数指定的原始列。因为我们使用的是 scikit-learn 的 OneHotEncoder 类,所以我们也可以将关键字参数传递给它的构造函数。
df.onehot_encode('Embarked', 'Person', keep_col=False, drop=None)

报告
关于当前的报告特性,需要记住的几件事情是,它按照代码执行的顺序进行记录和编写,并且它目前不为任何图像添加标题。我们还可以通过执行以下操作随时写入报告:
df.log(`write_something_here`)
结论
Aethos 是标准化的 API,它允许你用一行代码运行分析技术、训练模型等等。我所展示的只是您可以用 Aethos 完成的分析技术的冰山一角。Aethos 中有超过 110 种自动化技术和模型,更多技术和模型即将推出。
在随后的博客文章中,我将回顾训练模型和查看 Aethos 的结果。要了解更多细节,我推荐阅读 Github 上的用法部分或文档。
即将推出
这只是对 Aethos 的介绍,但新功能即将推出!完整的路线图你可以在这里查看。
在不久的将来,你可以期待:
- 使用 MLFlow 进行实验管理
- 用更好的 API 改进现有的可视化
- 更加自动化的可视化
- 更多自动化技术(降维、特征工程)
- 预先训练的模型(GPT-2,伯特等。)
反馈
我鼓励所有关于这个帖子或 Aethos 的反馈。你可以在推特上给我发信息,或者在 sidhuashton@gmail.com 给我发电子邮件。
任何 bug 或功能请求,请在 Github repo 上创建问题。我欢迎所有功能请求和任何贡献。如果你想为一个开源项目做贡献,这个项目是一个很好的开端——如果你需要帮助,可以随时给我发消息。
浓缩咖啡的经济咖啡溶解度工具(TDS ):白利糖度与 Atago
通过一些数据收集,我发现一个便宜的白利糖度折射仪和一个更贵的 Atago 测量咖啡萃取物一样准确。
我犹豫要不要买 TDS 表,因为我不确定它是否值得。标准的 VST 数字折射仪价格约为 700 美元,即使是价格较低的也要 100 美元。最终,我买了一个 20 美元的白利糖度计,后来,我终于决定买一个更贵的(Atago)。我收集数据来帮助理解 Atago 的工作情况,以及它与更便宜的工具相比如何。
长话短说:便宜的电表和数字电表一样精确,只是不太方便。

我的 TDS 历史
我不确定总溶解固体(TDS) 是否与味道相关。这当然是一个很好的衡量标准,但我不喜欢这个价格。我发表了一篇关于断续浓缩咖啡镜头的作品,主要的批评是我没有使用 TDS,而 TDS 是咖啡师世界的标准。相反,我使用一个包含 7 个指标的记分卡(尖锐、浓郁、糖浆、甜味、酸味、苦味和余味)得出最终得分。这些分数当然是主观的,但它们符合我的口味,帮助我提高了我的投篮。
最终,我屈服了,我买了一个便宜的白利折光仪。在拍摄的时候,我在检查 TDS 的过程中获得了很多乐趣,但是当然,有些人并不相信,因为这是通过目测完成的。所以我决定买一台 100 美元的折光仪,直到我看到评论很差,碰巧的是,我发现有人卖 200 美元的 Atago。通常情况下,一辆 Atago 要花费 300 美元或更多,而且在美国很难找到。

将白利糖度转换为 TDS 可以使用一个简单的公式:
TDS = 0.85 *白利糖度
有些人认为这个度量标准太简单了,这个问题可以通过比较 Brix 和 Atago 来解决,如下所示。

Atago 测试

首先,我想测试 Atago 在镜头冷却时处理温度变化的能力。我从我的可靠的老 Odea Giro Superautomatic 中取出一张照片,因为我不担心高 TDS 照片。
我还想在测量 TDS 之前测试过滤样品。一些人声称你应该在测量 TDS 之前过滤样本,但是一项研究表明过滤器降低了 TDS。他们确实发现过滤后的样品在测量中的可变性更小。我也想做科学家做的事情,看看我是否能快速验证他们的结果,而不用购买昂贵的 VST 注射器过滤器。为了测试过滤,我使用了 Aeropress 滤纸。
这是我的设置:



1)初始设置。2)正在使用的设置。3)过滤后的空气压力纸过滤器
起初,我测试了单个样本并读取了多个读数,这似乎表明差异很大,但接近 Atago 规范的+/- 0.03 TDS。

然后我取了 10 个未经过滤和经过过滤的样本,结果似乎遵循了的想法,即经过过滤的样本提供了更多可重复的测量。

然后随着镜头的冷却,我进行了测量。我将一个样品放在 Atago 上,进行多次测量,以消除抽取不同样品的变量。随着温度的下降,TDS 继续上升,直到在 22.5 时达到最大值。在网上讨论了结果之后,我通过更多的测试找到了原因。随着时间的推移,样品慢慢蒸发,导致 TDS 攀升,直至达到最大值。

总的来说,Atago 非常容易使用,尤其是与白利糖度计相比。通常,为了获得良好的白利糖度读数,我必须将闪光灯(通常来自我的手机)举到另一端,以确保有足够的光线通过。白利糖度每 0.2 个读数就有一条线,大量使用后,你能分辨的最佳读数是 0.1 或 0.085 TDS。
白利糖度计对于多个样品来说也不是很好,因为你必须打开顶部,擦拭干净,添加另一个样品,关闭它,然后拿着它对着光,而不是只向 Atago 中添加三滴。
白利糖度与 Atago
在过去的一个月里,我拍摄了 35 张照片,测量了白利糖度和阿塔戈糖度。我通常以 1:1 的输出输入比停止拍摄,但是由于我的实验随着时间提取,我开始测量拍摄的剩余部分(我称之为秒)。这导致 35 个以上的读数。此外,我计算了一下,如果我把 1:1 的投篮和秒的投篮结合起来,打出 3:1 的投篮,我的得分是多少。
当我用 Atago 取样时,我每次用三滴。我的目标是尽可能保持这个过程的可重复性。

从这些结果来看,似乎 Atago 和白利米给出了类似的结果。忽略一些异常值,误差甚至没有那么大。
从输出与输入的比率来看,似乎有一个与 TDS 相关的趋势,这是正常的,因为 TDS 在较小的拍摄中开始非常高,并随着时间的推移而降低。这与比率以及 Atago 和 Brix 之间的差异没有关系。

Atago 提供的另一个度量是温度,所以我们可以看一下温度和 TDS,但似乎没有太大的相关性。温度似乎也不会影响白利糖度和 TDS 的比较。

最后,由于我们有超过 30 个样本,我们可以进行配对 t 检验来确定分布是否在统计上不同,这意味着检验的 p 值小于 0.05。在下表中,可以看到分布在统计上没有差异,因为所有的 p 值都大于 0.05。

这些测试非常有助于信任 Atago 仪表,也信任我之前使用白利糖度(超过 200 个样本)得出的结果。在我的实验中,Atago 计量器已经成为我更好地理解拍摄的关键,我希望这些结果能够帮助那些没有足够钱购买工具来帮助测量和改善他们的浓缩咖啡以及其他形式的咖啡的人。
如果你愿意,可以在推特和 YouTube上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。
我的进一步阅读:
便携式浓缩咖啡:指南
克鲁夫筛:一项分析
非洲影响者:使用 Python 对 Twitter 用户进行细分
使用 Twitter 数据确定非洲最有影响力的人,以推动营销战略。

卢克·切瑟在 Unsplash 上的照片
简介
Twitter 是最受欢迎的社交媒体平台之一。这是一个不断更新的信息流池,在这里可以研究趋势、喜好、爱好、社区和新闻。在数百万用户中,有政治和社会影响力的人只占一小部分。这些小群体可以被确定、研究并用于各种活动和营销策略。这项研究的目的是使用 Python 来确定和排列非洲最有影响力的人和政府官员。
为了实现这一点,我们将使用 3 个指标得分:
- 人气评分-喜欢和转发
- 影响程度得分
- 相关性分数-提及和回复计数
数据采集
我们从收集 twitter 句柄开始
- https://Africa freak . com/100-非洲最具影响力的推特用户
- https://e nitiate . solutions/top-18-African-s-heads-on-Twitter/。
使用 web 抓取技术来获取所需的 twitter 句柄。然后使用 Tweepy 提取分析所需的用户信息。
Python 库
from requests import get
from requests.exceptions import RequestException
from contextlib import closing
from bs4 import BeautifulSoup
import pandas as pd
import re
import numpy as np
import os, sys
import fire
import tweepy
卷筒纸报废
我们搜索列出的网站,以获得非洲高层人士和政府官员的 twitter 账号。
def simple_get(url):
"""
Attempts to get the content at `url` by making an HTTP GET request.
If the content-type of response is some kind of HTML/XML, return the
text content, otherwise return None.
"""
try:
with closing(get(url, stream=True)) as resp:
if is_good_response(resp):
return resp.content #.encode(BeautifulSoup.original_encoding)
else:
return None
except RequestException as e:
log_error('Error during requests to {0} : {1}'.format(url, str(e)))
return None
def is_good_response(resp):
"""
Returns True if the response seems to be HTML, False otherwise.
"""
content_type = resp.headers['Content-Type'].lower()
return (resp.status_code == 200
and content_type is not None
and content_type.find('html') > -1)
def log_error(e):
"""
It is always a good idea to log errors.
This function just prints them, but you can
make it do anything.
"""
print(e)
def get_elements(url, tag='',search={}, fname=None):
"""
Downloads a page specified by the url parameter
and returns a list of strings, one per tag element
"""
if isinstance(url,str):
response = simple_get(url)
else:
#if already it is a loaded html page
response = url
if response is not None:
html = BeautifulSoup(response, 'html.parser')
res = []
if tag:
for li in html.select(tag):
for name in li.text.split('\n'):
if len(name) > 0:
res.append(name.strip())
if search:
soup = html
r = ''
if 'find' in search.keys():
print('findaing',search['find'])
soup = soup.find(**search['find'])
r = soup
if get_ipython().__class__.__name__ == '__main__':
fire(get_tag_elements)
下面是通过其中一个列出的网站后的输出示例:
['@EswatiniGovern1',
'@MalawiGovt',
'@hagegeingob',
'@FinanceSC',
'@PresidencyZA',
'@mohzambia',
'@edmnangagwa',
'@MinSantedj',
'@hawelti',
'@StateHouseKenya',
'@PaulKagame',
'@M_Farmaajo',
'@SouthSudanGov',
'@SudanPMHamdok',
'@TZSpokesperson',
'@KagutaMuseveni']
使用 tweepy APIs,我们可以传递从废弃网站获取的列表来废弃 twitter 中的用户信息。对于我们的例子,我们需要每个帐户的用户的屏幕名称、tweets 数量、关注、追随者、喜欢、转发、标签和提及。
下面是一个示例代码:
df = pd.DataFrame(columns=['screen_name','description','number_of_tweets','following', 'followers',
'likes', 'retweets', 'hashtags', 'mentions'])
def get_data(account_list):
for target in account_list:
item = api.get_user(target)
name = item.name
screen_name = item.screen_name
description = item.description
number_of_tweets = item.statuses_count
following = item.friends_count
followers = item.followers_count
# age of account
account_created_date = item.created_at
delta = datetime.utcnow() - account_created_date
account_age_days = delta.days
if account_age_days > 0:
avg_tweets_per_day = float(number_of_tweets)/float(account_age_days)
# tweets (hashtags and mentions)
global hashtags, mentions, replies, comments # making them global in order to intergrate them to the df later
hashtags = []
mentions = []
comments = []
retweet_count = []
likes_count = []
replies = []
tweet_count = 0
end_date = datetime.utcnow() - timedelta(days=180)
for status in Cursor(api.user_timeline, id=target, include_rts=False).items():
tweet_count += 1
if hasattr(status, "entities"):
entities = status.entities
process_status(status)
#hashtags
if "hashtags" in entities:
for ent in entities["hashtags"]:
if ent is not None:
if "text" in ent:
hashtag = ent["text"]
if hashtag is not None:
hashtags.append(hashtag)
#mentions (will fetch other users but will later use to do mention counts between the involved users)
if "user_mentions" in entities:
for ent in entities["user_mentions"]:
if ent is not None:
if "screen_name" in ent:
name = ent["screen_name"]
if name == target:
if name is not None:
mentions.append(name)
数据帧作为输出返回。下面是输出的一个示例。

分析
根据这些指标进行分析,以确定非洲最具影响力的人物。Matplotlib 用于绘制图形和可视化分析的数据。下面是非洲政府高级官员受欢迎程度得分的柱状图。

基于 in-degree 影响力的非洲顶级人物条形图。

结论
根据上述图表所示的分析,非洲最有影响力的人物是:
- 特雷弗·诺亚
- 朱利叶斯·马莱马
根据分析,非洲最有影响力的政府官员是:
- 布哈里先生
- 卡古塔·穆塞韦尼
数字营销是营销策略的新标准。与合适的影响者合作,在商品和合适的市场之间架起一座桥梁。数据科学可以在企业中用于推动关键的营销决策。
参考
[1] Cha,m .,Haddadi,h .,Benevenuto,f .,和 Gummadi,K. (2010 年)。测量 Twitter 中的用户影响力:百万追随者谬误。从 http://twitter.mpi-sws.org/icwsm2010_fallacy.pdf取回
在 Covid 之后,AI 将转向

照片由杨奇煜·巴扎内盖在 Unsplash 上拍摄
世界刚刚改变了。对于技术领域的任何人来说,这都是一个问题。科技行业通过创新引领世界,只有当你能够预测需求并开发出满足需求的解决方案时,创新才会发生。这突然变得很难做到。当你不知道六个月后世界会变成什么样子时,将想法转化为商业成功并不容易。
这个问题对于人工智能来说尤其尖锐。人工智能产品,就其本质而言,旨在从一致的数据流中寻找有用的模式。如果你刚刚训练你的机器检测的所有模式不再意味着它们过去的意义,那不仅仅是一个问题,那是一个技术噩梦。你过去 N 年收集的所有数据现在值多少钱?你知道吗?无论您是在模拟房价、股市、城市交通、新闻文章内容、市场情绪、购买模式、投票模式、慈善行为还是医疗保健产品需求,您现有数据存储的价值都变得值得怀疑。更不用说数据流本身的一致性也不再可靠。如果数据是新的石油,一些钻井平台就着火了。
人工智能行业肯定会适应这些条件。一些应用程序甚至会从这种变化中受益。衣服还是会像衣服,牙膏还是像牙膏,所以搭配实体产品不会有问题。同样,人类生成的视频内容现在比以往任何时候都多。但是在 Covid 之后,这个数据一致性问题不会消失。事实上,情况会变得更糟。
正如我在其他 文章中指出的,在某些方面,当前的疫情构成了人类的一次非凡的幸运。鉴于全球社会和经济体系的加速 相互关联,某种形式的连锁失败是不可避免的。事实上,我们已经得到了一个很小的、早期的系统性冲击,可能会杀死仅仅几百万人,这是一个礼物——一个很难欣赏或享受的礼物,也许,但仍然是一个礼物。
后 Covid 时代的世界仍将过于相互关联和过度杠杆化,无论采取什么样的短期措施,都无法维持当前的发展轨迹。但现在,我们尝到了 21 世纪的滋味,这意味着我们有时间在下一次冲击到来之前适应。这意味着未来几十年商业的一个关键术语将是“弹性”。
模式检测和预测仍将是大赢家——事实上,比以往任何时候都大——但这些解决方案看起来不会像目前吸引硅谷注意力的那些。去看看任何新闻网站或社交媒体上关于疫情疾病建模工作的参考资料,你应该会有所发现。没有一个思想领袖使用机器学习来建立预测病床需求、呼吸机生产或经济影响的模型。这是因为这些技术在现在最重要的预期方面是没有希望的。
深度学习,以及当前场景中的其他算法宠儿,不仅仅是在一堆标记良好、平衡、统一的数据上做最好的,他们需要它们。我们在过去十年中构建的几乎所有智能工具都是为了利用这个充满同质、可管理信息的世界。在许多方面,它们很像信贷危机爆发前流行的房地产定价模型,在这种模型中,房子的价值只会上升。
我们现在可能正在目睹简单人工智能时代的终结。如果不是这样,我们肯定听到了警钟,它的时代即将结束。那么,聪明的技术专家或投资者应该做些什么呢?
幸运的是,还有其他技术可以让理解当前的世界。想知道它们是什么吗?再一次,去检查你的新闻,看看流行病学家在用什么。工具列表很能说明问题:网络模型、基于代理的模型、决策分析、因果推理。他们都有什么共同点?它们旨在扩展人类的直觉,而不是取代它。他们不会自动完成简单的任务。相反,它们使人类专家能够实现否则不可能实现的事情。它们扩大了公司行为的范围,而不是加速已经存在的行为。
在关注世界发展轨迹的思想领袖的推动下,一场围绕这一方针组织的运动在过去几年中一直在幕后缓慢而悄然地发展。那个动作叫做决策智能(DI) 。它广泛使用了强大的分析技术,这些技术在深度学习时代没有受到太多的欢迎,但现在正重新成为人们关注的焦点:场景规划、图形建模、决策理论。这些工具的优势在于它们能够以一种机器学习迄今无法做到的方式明确地表示不确定性。
谁已经在使用决策智能了?正是你所期望的垂直市场:那些总是看到理解和掌握波动性的价值的组织。公用事业公司,例如,资本管理公司,银行和电信公司。谁在开发支持这种需求的工具?在大多数情况下,像 Quantellia 和 Lumina Decision Systems 这样有远见的小公司。他们的产品往往专注于让商业决策者将他们的直觉专业知识转化为量化模型,从而管理风险和指导战略选择,但他们的潜力远不止于此。例如,Lumina 的旗舰产品 Analytica 可以作为任何东西运行,从简单的财务规划工具到成熟的蒙特卡罗模拟器,用于任意复杂的数字模型。
DI 如何与 AI 对接?首先,它帮助你理解在不稳定的条件下你希望收集什么样的数据,以及从中得出什么样的推论可能是可靠的。它可以帮助您识别机器学习的用例,否则这些用例可能会被忽略。也许最重要的是,它可以将 ML 转变为一种组织感知,使世界的波动性更容易管理。
我在这篇文章开始时指出 ML 工具的优势在于检测一致的重复模式。当它们连接到一个组织神经系统,能够使用这些检测来驱动甚至自动化更高层次的决策时,就会发生一些奇妙的事情。这时,一个组织开始展示一种自适应的端到端智能,它融合了人类和机器的最佳能力。如果你的企业是一种动物,机器学习工具就是它大脑的视觉和听觉中心。人工智能工具代表了它的本能和适应性智能。直截了当地说,DI 告诉你钱的去向。ML 帮你嗅出来。
现有的 DI 工具能够完全实现这个承诺吗?在我看来,不完全是这样,部分原因是尽管 DI 运动的重要性日益显现,但它仍然资金不足。然而,他们非常接近。在我看来,当 DI 工具能够将来自多个不同人类来源的因果模型集成到一个能够适应新数据出现的合并表示中时,重大突破就会到来。众包和遗传算法中诞生的一些东西需要被注入到混合中,以将 DI 带到下一个水平。但我的猜测是,这样的工具最多还需要两年时间。最近由朱迪亚·珀尔的研究推动的对因果推理的兴趣激增实际上保证了它们的产生。
那么后 Covid 的 AI 格局会是什么样子呢?绝对不同,但希望因此变得更好更强。也许我们不应该哀悼 easy AI 和依赖它的公司的终结。毕竟,即使转型是痛苦的,变化也一直是推动技术创新的燃料。我们走向的以 DI 为燃料的未来肯定会更好。机器学习已经死了。机器学习万岁。
使用面部图像的年龄检测:传统机器学习与深度学习
使用 scikit-learn 和 TensorFlow 进入计算机视觉领域的初学者步骤。

网络摄像机视频的实时年龄分类。顺便说一下,我 26 岁了。(图片由作者提供)
我是一名有抱负的数据科学家,进行了几个月的密集数据科学学习和项目。大约一年半前,当我通过在线视频和课程学习 Python 时,我对这个领域产生了兴趣。为了提高我在该领域的理解,我决定参加由大会提供的数据科学沉浸式训练营。通过这个项目,我们接受了几个项目的任务,这些项目为我们提供了“实践”经验。作为对我为期 12 周的数据科学之旅的致敬,我很乐意分享我的最后一个,也可能是其中最引人注目的一个——我的顶点项目。该项目的核心是利用图像数据和计算机视觉,利用人脸图像建立年龄分类算法。
为什么要阅读这篇文章?在互联网上快速搜索可能会产生大量关于如何构建年龄分类器的文章、视频、GitHub 链接和研究论文。那么,我的文章在一堆相似的内容中处于什么位置呢?为什么你应该继续阅读这篇文章?嗯,这是为什么...
- 两种方法:传统机器学习与深度学习 —听从导师的建议,我试图使用两种不同的方法为这个项目构建一个解决方案。我在网上遇到的大多数资源都直接进入了深度学习和神经网络,以建立解决这个问题的解决方案(你可能会说这应该是正确的方法)。然而,为了真正欣赏数据科学中传统的机器学习方式,并欣赏深度学习的力量和可能性,我试图探索传统的机器学习方法(图像特征提取,然后使用著名的 sklearn 库进行分类建模)。我在这个项目中利用了深度学习方法的 TensorFlow 库。
- 最重要的是,因为我是一个业余爱好者——如果你像我一样是一个初学者,正在考虑开始(或者已经在努力)一个类似的项目,你可能会发现这篇文章很有帮助。在这里,我尝试浏览工作流程,同时讨论我在这个项目中必须做出的各种决定背后的思维过程和基本原理。我还希望,我在该领域的新手身份,加上我(相当)成功地尝试解决如此性质和规模的项目,可能是您在开始数据科学之旅时正在寻找的那种灵感。
也就是说,如果你碰巧是这个领域的专家,或者如果你有一些更好的想法来完成这个项目中的某些事情,一定要让我知道。
所以,如果我足够幸运,能让你一直保持兴趣,让我们再往前推一点,直接进入正题。
为了这个项目,我决定在我的个人电脑上使用 Google Colab 而不是 Jupyter 笔记本。这样做的主要原因是利用谷歌提供的免费 GPU 来训练我的深度学习模型。也就是说,也有可能使用传统的 CPU 来完成这个项目,只是可能需要稍微长一点的时间。对于那些刚刚接触 Google Colab 的人来说,你可以在这里读到一些关于它的内容。
TL;这里是所有不同方法的准确度分数的总结。

源代码和数据集
这个项目中使用的源代码和数据集可以在下面给出的链接中找到。请参考随附的 README.txt 文件,了解如何在运行笔记本中的代码之前将笔记本复制到您自己的 Google Drive 中。
文件夹 1(源代码):Age _ class ification _ with _ Faces
文件夹 2(数据集): 年龄 _ 分类 _ 拥有 _ 面孔 _ 数据集
在整篇文章中,我提供了对不同源代码笔记本的引用,这些笔记本包含了以下部分的相关代码。我希望这能让你更容易理解这个项目。
如果你已经对尝试这个项目的最终产品感到好奇(就像本文开头的 GIF),要么通过从 这里 下载 Jupyter 笔记本(以及经过训练的模型)作为 ZIP 文件进行离线尝试,要么在这个 Google Colab 笔记本 中进行在线尝试。请注意,实时网络摄像头视频中的年龄检测仅适用于 Jupyter 笔记本电脑,不适用于 Google Colab 笔记本电脑。您仍然可以在 Google Colab 笔记本中对您上传的照片和视频进行年龄检测。
数据收集和探索性数据分析(EDA)
互联网上有很多带有年龄标签的面部图像数据集。一些著名的包括 IMDB-WIKI 数据集、野生(LFW)数据集和全年龄人脸数据集。对于这个项目,我决定使用面部年龄数据集和 UTKFace 数据集 ( UTKFace Cropped 是另一个来源)。这两个数据集都提供了已经被适当清理和标记的图像,使我能够跳过工作流程中最耗时的数据清理阶段。让我们更详细地看一下这两个数据集。
本节相关代码参见笔记本1 _ EDA _ dataset _ prep . ipynb。
面部年龄数据集包含9778 张大小为 200x200 像素的 PNG 格式的面部RGB 图像。图像被分成文件夹,文件夹名称与这些文件夹中图像的年龄标签相对应。数据集中年龄的分布和范围显示在下面的柱状图中。

面部年龄数据集中的年龄分布和范围。(图片由作者提供)
UTKFace 数据集包含了23708 张人脸的 RGB 图像以 JPG 的格式,每张大小为 200x200 像素。图像的标签嵌入在文件名中,格式为[年龄][性别][种族]_[日期&时间]。jpg 。数据集中年龄的分布和范围显示在下面的柱状图中。

UTKFace 数据集中年龄的分布和范围。(图片由作者提供)
由于两个数据集都已经提供了标准化为 200x200 像素大小的清晰正面人脸图像(每张图像一张),因此我决定为这个项目将两个数据集合并在一起,并将所有 33,486 张图像转换为标准的 JPG 格式。下面的柱状图显示了合并两个数据集后的图像分布。

人脸年龄数据集和 UTKFace 数据集合并后的图像分布。(图片由作者提供)
在合并了两个数据集之后,下一步是将不同的年龄标签划分为不同的年龄范围。因为这个项目不是专门针对解决任何特定的数据科学问题,所以选择将年龄范围划分为不同的类别是非常灵活的。然而,仍有必要确定该项目背景下这一进程的一些制约因素,如下所示:
- 类别需要平衡 —年龄范围的类别应根据每个年龄标签可用的图像数量来建立,以使类别尽可能平衡。这将确保分类模型学会平等地对每个年龄范围进行分类。
- 班级数量需要足够——年龄范围的班级数量需要适当选择。太多的类别将导致非常窄的年龄范围,这可能会严重影响模型性能(通常更难预测某人的年龄精确到哪一年)。太少的类将导致非常宽的年龄范围,这可能不符合年龄分类建模本身的目的。在这种情况下,6–12 个等级可能是合适的。
- 每个类别都需要有足够的数据——年龄范围类别的数量也将取决于数据集中每个类别可用的图像数量。太多的类别将导致狭窄的年龄范围,从而减少可用于在每个类别上训练模型的图像数量。然而,这可能不是一个重要因素,因为数据扩充技术很容易获得,如果需要,可以用来增加每类可用图像的数量。
警告 —上面确定的约束意味着在这个项目中,我使用可用数据量作为定义我的分类问题性质的驱动因素。在现实世界的数据科学问题中,这可能不是一种理想的方法。实际上,理想的方法是首先根据手头的数据科学问题建立模型的类,然后为每个类收集足够数量的数据,以便适当地解决数据科学问题。然而,考虑到这个项目的业余性质,以及我对用于年龄分类的现成面部图像数据的有限访问,我相信这种方法在这种情况下是合理的。
经过反复试验,我决定将这些图片分成以下 11 类年龄范围,确保这些类别尽可能平衡。


图像按年龄范围分类的分布。(图片由作者提供)
在进行下一步之前,所有的图像都标有这些新的类别标签。
分类建模的数据准备
在对图像执行任何形式的分类或特征提取之前,有必要将组合数据集分成训练数据集和测试数据集。我使用了sk learn . model _ selection . train _ test _ split方法将数据集拆分成 70%的训练数据(23440 张图片)和 30%的测试数据(10046 张图片)。
本节相关代码参见笔记本2 _ dataset _ prep _ ML _ feature _ extraction . ipynb。
传统 ML:特征提取
有多种技术可用于处理从图像中提取特征以进行分类建模(例如,方向梯度直方图(HOG) ,滤波图像的能量和熵,通道的平均像素值等)。).作为初学者,我确实发现所有这些方法理解起来有点复杂,用代码实现起来也有点复杂。
为了从我的项目的面部图像中提取特征,我决定对我的数据集中的一些图像应用一些不同的过滤器,并在视觉上尝试找出它们之间的任何显著差异。下图显示了该测试的结果。我强烈建议观看这个视频和这个系列的其他视频,以更好地了解如何应用过滤器和处理机器学习的图像。
本节相关代码参见笔记本2 _ dataset _ prep _ ML _ feature _ extraction . ipynb。

来自面部年龄数据集的面部图像的过滤版本。(图片由作者提供)
上图中的人脸随着我们从左到右(1-90 岁)年龄的增加而增加。当每个过滤器被应用于图像时,我们可以看到不同的面部特征是如何被突出显示的,以及它们是否有助于区分不同年龄的面部。
从上面的图中,我能够得出结论,在这种情况下,Canny 边缘可能是最有用的特征提取过滤器— 随着我们从年轻到年长的人脸,图像中 Canny 边缘的密度似乎会增加。
既然选择的过滤器已经确定,下一步就是将过滤后的图像转换成标量,以便能够将它们输入到机器学习分类器中。为此,我决定将每个 200x200 像素的图像分解成每个 10x10 像素的部分,如下图所示。对于 400 个结果部分中的每一个,我然后计算像素值的平均值和标准偏差。这导致每幅图像有 800 个唯一的标量值,然后我将它们制成数据帧,用作机器学习分类器的特征。

将显示 Canny 边缘的图像分解为多个部分以进行特征提取。(图片由作者提供)
传统 ML:分类建模
对训练和测试数据集中的所有图像重复上述特征提取过程。这些特征然后被用在两个不同的分类器算法中,sk learn . ensemble . randomforestclassifier和 sklearn.svm.SVC 。通过将超参数的多个组合传递给 sklearn.model_selection,这两个模型都进行了精度优化。GridSearchCV。下表总结了所获得的结果。
本节相关代码参见笔记本3 _ ML _ class ification _ modeling . ipynb。

显然,模型严重过度拟合,并且不能很好地概括看不见的测试数据(基本上是记忆训练数据)。下面的两个标准化混淆矩阵也清楚地表明了这一点——尽管对于较年轻的年龄范围(1-2 岁、3-9 岁、10-20 岁和 21-25 岁)和较老的年龄范围(66-116 岁)来说,准确性值有些高,但是对于 26-65 岁的中间年龄范围来说,存在着显著的错误分类。

RandomForestClassifier 和 SVC 模型年龄预测的标准化混淆矩阵。(图片由作者提供)
传统 ML:局限性及进一步改进
当然,有许多方法可以用来提高上述准确度分数并降低模型中的过度拟合程度。例如,可以使用一些其他更复杂的技术从图像中提取更好的区分特征,或者可以使用其他分类器来查看它们在这种情况下是否执行得更好。
深度学习:导入数据集
为了准备要传递到神经网络中的图像数据集,我首先尝试将图像转换成一个 Pandas Dataframe ,其中各个像素值作为列,图像作为行。然而,由于所有像素值都必须是浮点类型(从 0–255 整数缩小到 0–1 浮点),这导致了一个巨大而沉重的数据帧 (33,486 行 X 40,000 列)。就在训练神经网络之前将该数据帧加载到内存中导致了持续的“内存不足”错误(尽管使用了 Google Colab Pro 中可用的 GPU 和 25GB 高 RAM 运行时类型)。
为了避免这些错误,我不得不采用另一种方法,即使用 TensorFlow 的内置 来创建数据集管道。数据集**** API。这种方法显著降低了 RAM 消耗,因为当神经网络需要图像时,图像只以小得多的批量加载到存储器中(而不是像前一种方法那样将整个数据集保存在存储器中)。关于这种方法的更详细的解释可以在这篇文章中找到。
深度学习:分类建模
在正确导入数据集后,下一步是构建一个基本的卷积神经网络(CNN)模型,该模型在给定的数据和给定数量的总参数上具有合理的精度。我们的想法是获得模型性能的初始基准,然后逐步尝试不同的技术,看看它们是否能从该点提高性能。在对 CNN 架构做了一些反复的实验后,我决定从下面的架构开始。
本节相关代码参见笔记本4 _ deep _ learning _ CNN _ modeling . ipynb。

用于图像年龄分类的初始 CNN 结构。(图片由作者提供)
我决定在训练 CNN 模型时使用TF . keras . callbacks . early stopping作为回调,以监控验证损失,从而避免过度拟合,并在验证损失开始持续增加时停止模型的进一步训练。在适合这个模型之前,图像也被从 RGB 彩色转换成灰度。在拟合 30 个时期的模型后,获得以下损失和准确度分数。

模型性能不是很好,但这是一个很好的起点,只有轻微的过度拟合。标准化混淆矩阵还显示,与上述传统 ML 方法类似,尽管年轻年龄范围(1-2 岁、3-9 岁、10-20 岁和 21-25 岁)和年长年龄范围(66-116 岁)的准确度值有些高,但 26-65 岁的中间年龄范围仍存在显著的错误分类。这可能归因于这样一个事实,即人们的面部外观(一般而言)在中年时期的变化不如在年轻和老年时期那么大。无论如何,这个过程的下一步是使用一些不同的技术来提高模型的性能。

使用灰度图像从初始 CNN 模型预测年龄的标准化混淆矩阵。(图片由作者提供)
深度学习:改进模型
首先尝试了以下两种策略来提高模型的性能:
- 使用 RGB 彩色图像而不是灰度图像:其背后的基本原理是,在图像中添加彩色数据可能会显示 CNN 模型中的一些特征,这可能会增强模型的整体性能。
- 增加训练数据集中的图像:这背后的基本原理是增加模型训练的数据量将有助于增加数据集中的方差。这可以提高模型的准确性,同时降低过度拟合的可能性。对于每 1 幅原始图像,通过横向翻转图像并将它们旋转不同角度,创建了 9 幅其他增强图像,如下图所示。因此,增强的训练数据集总共有 234,400 幅图像(相比之下,原始训练数据集中有 23,440 幅图像)。
训练数据集数据扩充的相关代码参见笔记本4 _ 5 _ training _ data _ augmentation . ipynb。

图像数据增强:从一幅原始图像创建 9 幅增强图像。(图片由作者提供)
使用与上述相同的 CNN 模型架构来拟合 RGB 彩色图像和增强训练数据集上的模型,并且观察到以下结果:

上表中的准确度分数强调了两个关键发现:
- 使用 RGB 彩色图像代替灰度图像可能不会提高模型性能,并且可能会导致更多的过度拟合。
- 增加训练数据集中的图像有助于提高模型的准确性,同时减少过度拟合(即使在训练 60 个时期后)。
深度学习:重新思考年龄范围
看一下上面所有 CNN 模型的评估,很明显准确率不是很高(最多 45%)。事实上,这是意料之中的,因为猜测一个人的年龄纯粹是基于外表,因此非常主观。就连我们人类也一直在与这个问题做斗争。有很多因素会影响一个人如何看待自己的年龄,比如遗传、生活条件和生活方式的选择(健康饮食、运动量、吸烟习惯等)。).
正如我们在上面看到的,即使增加了数据,准确率也没有显著提高。主要问题仍然是 26-65 岁这一中间年龄范围存在明显的错误分类。因此,为了避免这个问题,我决定再次将年龄范围重新分配到班级中。然而,这一次,我并不只是查看每个年龄范围内的可用图像数量,我还决定考虑人类直觉因素(我们人类可能将一个人归类到的年龄组)以及上面混淆矩阵中显示的各个类别的准确度分数。
警告 —上面详述的方法意味着在这个项目中,我操纵了数据科学问题本身,以更好地适应我试图提出的解决方案。在现实世界的大多数数据科学问题中,这显然不是一种理想的方法。然而,正如在开始提到的,由于这个项目不是专门针对解决一个数据科学问题的,所以选择将年龄范围划分成类是非常灵活的。考虑到重新分配年龄检测的年龄范围类别不会产生重大后果,我认为这种方法在这种情况下是合理的。
年龄范围被重新分为以下 7 类。

本节相关代码参考笔记本4 _ deep _ learning _ CNN _ modeling . ipynb。
再次使用与上述相同的 CNN 模型架构来拟合训练数据集上的模型,并且观察到以下结果:

准确性分数显示了与第一个 CNN 模型在灰度图像上的拟合(这是预期的)相似的过度拟合程度,但是准确性分数本身明显更高。下面的标准化混淆矩阵还表明,我们可能已经解决了 26-65 岁这一中间年龄范围的错误分类问题(至少在一定程度上,如果不是完全的话)。

使用灰度图像和年龄范围的重新分布类别从初始 CNN 模型进行年龄预测的标准化混淆矩阵。(图片由作者提供)
深度学习:优化 CNN 架构
既然我已经探索了一些操纵数据集以提高 CNN 模型性能的技术,我决定优化 CNN 模型体系结构本身以提高整体性能。这里的想法是设计不同架构的多个模型,并比较它们在损耗和精度值方面的性能。我决定在训练多个 CNN 模型时使用TF . keras . callbacks . tensor board作为回调,以便能够比较它们在交互式(肯定更直观)剧情中的表现。我强烈建议观看这个系列视频,以更好地了解如何使用 TensorBoard 优化神经网络。
本节相关代码参见笔记本4 _ deep _ learning _ CNN _ modeling . ipynb。

使用 TensorBoard 优化 CNN 架构以比较不同模型的性能。(图片由作者提供)
基于优化结果,在比较了 18 种不同 CNN 模型和不同 Conv2D 和密集层数的不同架构后,最终选择的 CNN 架构如下所示。

图像年龄分类的最终 CNN 结构。(图片由作者提供)
深度学习:构建最终模型
因此,在理解了所有上述技术对模型性能的影响之后,现在可以定义和训练最终的 CNN 模型:
- 用灰度图像代替 RGB 彩色图像。
- 用增强的训练数据集(234,400 张图像)代替原始训练数据集(23,440 张图像)。
- 对于 60 个时期。
- 对于重新分配的年龄范围等级。
- 采用优化架构。
本节相关代码参见笔记本5 _ deep _ learning _ final _ CNN _ model . ipynb。
我决定在训练最终的 CNN 模型时使用TF . keras . callbacks . model check point作为回调,以便能够保存模型,因为它在 60 个时期内继续训练和改进性能。该模型的性能在 60 的第 54 时段达到峰值,损失和精度值如下。

准确度分数显著提高,尽管有轻微程度的过度拟合,这可能仍然是可接受的。下图显示了 CNN 模型经过 60 个时期的训练后,损失和准确性得分的变化。下面的标准化混淆矩阵也显示了 26-65 岁这一中间年龄段的错误分类显著减少。

该图显示了在 60 个时期中的第 54 个时期出现峰值性能时损耗和精度值的变化。(图片由作者提供)

使用灰度图像从最终 CNN 模型预测年龄的标准化混淆矩阵。(图片由作者提供)
深度学习:局限与进一步改进
与任何数据科学工作流一样,上面介绍的深度学习方法也有其自身的局限性。例如,这个项目中使用的数据集只有大约 33,000 张图片。CNN 模型可以用图像中有更多变化的大得多的数据集来训练,以便获得甚至更好的结果。该项目的另一种方法是使用迁移学习(使用预训练神经网络的权重),而不是从头开始创建和训练神经网络。
那么,哪种方法——传统的人工智能还是深度学习?

在这种情况下使用传统的机器学习方法,尽管是可能的,但并没有产生具有非常高准确度分数的模型。此外,这种方法需要大量的领域知识和图像数据处理专业知识,以便从图像中提取大量特征用于分类模型。
另一方面,深度学习和神经网络方法不需要任何重要的领域知识和图像处理专业知识,因为它不需要手动提取任何图像特征。这种方法也产生了具有更高准确度分数的更好的执行模型。因此,这个项目中两种方法之间的比较突出了神经网络深度学习的真正力量和可能性,并让我(希望你也是)更好地理解了它们近年来越来越受欢迎的背后。
所以你有它!我希望你喜欢阅读我的第一次计算机视觉冒险,我希望它能让你更好地理解如何处理这样一个性质的项目。如果您有任何问题或建议,告诉我如何以更好的方式处理此事,请务必告诉我。
另外,请随时在 LinkedIn 上与我联系。

普里切特大家庭的年龄分类。(视频来源:摩登家庭,ABC)
基于主体的新冠肺炎卫生经济效应模拟

特德沃德·奎恩在 Unsplash 上拍摄的照片
开始之前
这篇文章是发表在论文“COVID-ABS:一个基于代理人的新冠肺炎流行病模型,模拟社会距离干预的健康和经济影响”中的内容的先前(和更基本的)版本,也可作为 arXiv 中的预印本获得。
我们正生活在一个不寻常的时代,人类正受到一种微生物的攻击,这种微生物威胁着我们的健康(身体和精神)、经济、社会福利等。从短期到中期,所涉及的变量数量及其关系的复杂性正使人们疯狂地去理解他的局部行动在未来全球情景中的影响。但是我们如何预测这些未来的情景呢?政府如何知道采取这些保护措施的积极效果?
嗯,这个问题有很多可能的答案。首先,我们必须定义一个生活在领地之上的社会是一个复杂的和动力系统。这类系统具有许多相互作用的变量,呈现非线性行为,其性质随时间演化。它的行为通常是随机的,它也可能依赖于它的初始条件,它可能受到邻近社会(具有不同的政策和动态)的影响,它可以显示出涌现。
A 基于智能体的模拟是模拟这些动态复杂系统的一个很好的选择,因为它实现简单,与过去事件的真实数据相比,结果准确。还因为我们可以通过对模拟环境变量进行干预来设计场景,并测量其效果。
现在我们将假设离散事件用于我们的模拟,这意味着时间和系统的组件是离散的和原子的。更具体地说,基于代理的模拟(ABS)由一群代理组成,在代理运行和交互的循环中。每个代理都被认为是自治的,因为它有自己的内部状态,但是所有代理共享一个公共环境。状态变量驱动每个代理的行为,它们必须代表问题的特征。
ABS 用于模拟复杂的动态系统,使用其组件的单个状态来检测由于迭代过程中代理之间的相互作用而出现的全局行为。然后,它的主要目标是模拟系统的时间演化,存储每次迭代中从代理的内部状态导出的统计数据。ABS 允许我们模拟具有复杂的非线性变量关系、复杂的条件和限制的系统,这些系统可能很难用数学来描述。
如果说ABS 的主要优点是灵活性,另一方面,它的主要缺点是计算成本高。拥有一个封闭形式的方程(在动力系统的情况下是 ODE ),或者甚至用蒙特卡罗马尔可夫链模型进行随机模拟要便宜得多。然而,如前所述,我们并不总是能够做到这一点
我们将采用 ABS 来模拟一个动态已知的系统,用 SIR 模型及其变体来表示。
流行病模拟概述

照片由 Yohann LIBOT 在 Unsplash 上拍摄
首先,我们来决定要模拟什么。流通引起的传染性传播和社会隔离的经济影响是我们的主要目标。
人口统计学
首先,我们需要生成具有国家人口相同特征的代理人(即人)。年龄 的 分布可以在https://www.census.gov/prod/cen2010/briefs/c2010br-03.pdf或者更容易在https://www.indexmundi.com/united_states/age_structure.html找到。我们可以用一个参数α= 2,β= 5 的 Beta 概率分布来表示这些分布,比如 age ~β(2,5) 。
传染性传播
C OVID-19 是一种高度传染性疾病,根据伦敦帝国理工学院新冠肺炎反应小组的报告 3:2019-nCoV,“截至 2020 年 1 月 18 日,平均每个病例感染 2.6(不确定范围:1.5-3.5)个其他人”。
遵循 SIR 模型,每个代理必须处于以下情况之一:易感、感染、痊愈(也用于免疫人群)。每个模拟都有一个感染和免疫人群的初始百分比,其余人群由易感个体组成。该状态还包含死亡状态,对于那些出现 SARS-COVID-2 的严重症状并且没有抵抗的代理。
传染性传播的主要假设是媒介通过接近或接触而相互作用。因此,一个人的流动性越高,他接近感染者并被感染的可能性就越大。每个模拟都有一个传染距离,这是两个媒介发生病毒传播的最小距离。
T 受感染病原体医学状况的演变遵循一些现有的论文,如对新冠肺炎病严重程度的估计、2019 年严重程度-新型冠状病毒(nCoV) 等。一旦一个病原体被感染,它可能处于以下子状态之一:无症状(也用于不住院的轻微症状)住院和严重(在重症监护室住院的情况)。状态转换图如下所示:

来源:作者
医疗状况的演变是随机的,并遵循下表的概率:

来源:非药物干预(NPIs)对降低新冠肺炎死亡率和医疗保健需求的影响
这些住院意味着使用有限的医疗基础设施。每个模拟都有 临界极限 ,即医疗保健系统能够同时处理的人口百分比。当住院和重症病例的数量超过这个限度时,就没有足够的空间给每个有需要的人了。
流动模式
模拟在所有代理共享的方形二维环境中进行。每个代理在这个环境中被随机初始化,例如x ~ 𝓤(0,length)和y ~ 𝓤(0,height)。
每个模拟通过每个可能的代理状态定义其移动性振幅。然后,在每次迭代中,每一个智能体还会在环境中随机移动,例如其位置的增量由【δx ~𝓝(0,1】)振幅* 和【δy ~𝓝(0,1】)振幅* 定义。
使用欧几里德距离计算两个代理 a1 和 a2 之间的接近度,例如(a1,a2)=√((a1 . x-a2 . x)+(a1 . y-a2 . y))
所有死亡的代理和所有感染且感染严重性等于住院或严重的代理的δx 和δy 自动设置为零。
经济影响

埃德温·胡珀在 Unsplash 上的照片
第二个目标是模拟流动性限制对经济造成的影响——特别是对每个代理人的收入和财富的影响。这种模拟的经济动力学的基本假设是:代理人的 收入 是其流动性的函数。在现实世界中,有许多情况下这个条件不成立,人们仍然在家工作。但遗憾的是,情况并非总是如此。然后,代理的移动性由距其先前位置的欧几里德距离来定义,使得移动性=√(δx+δy)。
在模拟的初始化过程中,代理人的财富遵循相同的社会分布,根据的财富分布分享初始数量的总财富。这种分布是用五分位数来衡量的,每个五分位数代表一个社会阶层:20%的最贫困者,贫困阶层,工人阶级,富裕阶层,20%的最富有者。这些信息可以在 https://data.worldbank.org/topic/poverty,找到,这里有一个五分位收入分配的例子:https://www . world bank . org/en/topic/poverty/lac-equity-lab 1/income-inequality/composition-by-quintile。我们可以很容易地用一条洛伦兹曲线来表示这种分布,并对社会阶层的百分位数进行均匀抽样,如 财富~洛伦兹【𝓤(0,100】/5],其中/表示整数除法 。**
我们定义一个固定值来代表最低收入,最低收入是由第一个五分位数(20%最穷)定义的,它将被用作每个阶层的支出和收入的单位。例如,minimal_income[20%最穷] = 1,minimal_income[20%最富] = 14。
在的每次迭代中,每个代理人的财富减少其最小固定支出,最小收入单位中的常数与其实际财富成比例,例如支出= 最小 _ 收入【财富五分位数】。 还有,在每一次迭代中,财富都是由代理人每天的收入来增加的。收入是一个随机值,与其实际财富、流动性(或经济活动)和随机比率(对应于他们业务的不确定性——盈亏交替)成比例。然后,最后的收入用**收入~ 𝓝(0,1) 流动性 minimal_income【财富五分位数】表示。**
超越
可以提出许多其他问题和假设来探讨这个问题的不同方面。只是列举一些未来扩展的可能性:
- 交通限制对环境和碳排放会有什么影响?
- 全球变暖会受到这种减少的影响吗?
- 电力负荷需求会因为工业活动的限制而减少吗?还是会因为国内支出的增长而增加?
这里没有探讨这些问题,我们将在我们工具的未来版本中给出这些答案。
给我看看代码!
“空谈是廉价的。给我看看代码!”(莱纳斯·托沃兹)**

照片由 Hitesh Choudhary 在 Unsplash 上拍摄
我们的模拟是使用 Python3 编程语言实现的,使用库 matplotlib 进行绘图, Numpy 进行随机采样, Pandas 进行数据处理。所有代码最初都是使用 Google Colab 框架开发和执行的。为了增加其重用性,基础代码被转移到 github 库https://GitHub . com/petroniocandido/covid 19 _ AgentBasedSimulation,实验可以在http://bit.ly/covid19_abs.执行。covid19_abs 包可以使用 pip 工具直接从 GitHub 库轻松安装。
通过年龄和财富分布控制感染严重度概率的全局变量封装在 通用 包中。
所有与代理状态相关的东西都封装在 代理 包中。可能代理的主要状态由 状态 枚举表示,被感染代理的具体情况由 感染严重性 枚举控制。
类 Agent 作为一个数据结构工作,包含每个 Agent 的状态值,包括状态、感染严重度、年龄、位置(x 和 y)和财富五分位数。
基于代理的仿真的主要类封装在 abs 包中。类实现了模拟动力学的所有主要方面,作为主要的模拟属性,代理的群体及其事件(移动、状态更新、与其他代理的联系)。
Simulation 类的主要方法是 execute() ,表示一个唯一的模拟迭代,执行所有 agents 的状态更新,调用其事件和交互。execute()方法还更新人口的统计数据,这是一个包含每种状态的人口百分比、感染率和每个社会阶层的财富数量的字典。
类模拟还包括两种类型的触发器,帮助我们在达到某些特殊条件时对模拟动态进行干预。第一种触发器是针对群体的,它针对每个代理进行测试,并且能够改变其任何状态变量。第二种触发器是针对模拟本身的,并在每次迭代中进行测试。**
The classmulti population Simulation是一个模拟对象的集合体,其中一个具有其动态性,但其种群之间具有相互作用。此类允许我们模拟更复杂的情况,如两个(或更多)相邻和重叠的群体(其中每个模拟在多群体模拟环境中的位置表示它们之间的交互水平)实施不同的控制策略。在这种情况下,每个模拟都会影响其他模拟,并受到其他模拟的影响。
数据可视化的东西封装在 graphics 包中,包括主方法execute _ simulation,被调用来运行仿真和绘制图形。
一些初步结果

考虑到随机组件的数量,每个模拟执行都是唯一的。然而,尽管有小的特异性和罕见的异常值,一般行为——给定相同的参数集——不会变化太多。正如蒙特卡罗方法中发生的那样,考虑到平均行为及其变化,ABS 必须执行多次以产生合并结果。
下面我们讨论 5 个可能的场景,每个场景由一组控制代理移动模式的模拟参数组成,旨在模拟隔离存在或不存在的影响。我们精心选择了一个有代表性的执行来演示模拟的一般行为,但是也执行了 50 个执行来计算合并的统计数据。
值得记住的是,实验源代码和参数可在 http://bit.ly/covid19_abs.获得
场景 1:什么都不做
这就是世界上有多少政治家相信这是处理新冠肺炎问题的正确方法,并照此行事,直到(在某些情况下)为时已晚。他们认为,对策是许多极端分子,更喜欢拯救经济而不是人的生命。‘米兰永不止步’的口号变得家喻户晓。剩下的就是历史了。如果你看看经济影响图,你可以想象它并没有那么糟糕,就像每个经济自由主义者的梦想一样:经济不会停止增长。但是当你看传染演化图的时候,你可以看到医疗系统的临界极限被改变了多少,有多少人丧生。如果什么都不做,这将是灾难性的一幕。

使用 covid19_abs 的典型场景 1 仿真

场景 1 执行 50 次的平均结果
场景 2:仅对受感染的人限制移动
这是一个乌托邦式的场景,我们可以快速诊断出受感染的人(甚至是没有症状的人)并隔离他们。我说这是乌托邦,因为极其快速和精确的诊断是不存在的!这种乌托邦式的情景对经济有益,许多政治家认为这就是情景 1 中应该发生的事情。但是他们的计算是错误的。

使用 covid19_abs 的典型场景 2 仿真

场景 2 执行 50 次的平均结果
场景 3:封锁(限制每个人的移动)
这是遵循世界卫生组织建议的情况。这种情况在医疗保健中是高度保守的,但它的目标是通过最小化人们的相互作用和病毒传播来拯救尽可能多的生命。不必说生命是无价的,经济可以在以后恢复,而不必杀死生命(穷人总是最受影响的)来授予大企业利润。

使用 covid19_abs 的典型场景 3 仿真

场景 3 的 50 次执行的平均结果
场景 4:在 10%的人口被感染后限制移动,当超过 95%是安全的时,解除限制
这似乎是最有可能的未来。看到疫情造成的破坏后,政府下令对所有人进行隔离。但是,一旦第一波感染减少,隔离就被取消,并导致另一波感染。这种情况会一直重复下去,直到大多数人对这种病毒产生免疫力。好的一面是医疗系统没有超负荷,但是我们会有几次隔离。

使用 covid19_abs 的典型场景 4 仿真

场景 4 执行 50 次的平均结果
情景 5:受控人群与非受控人群接触
政策大相径庭的人群之间的互动是一个奇怪的模拟场景,尤其是当他们相互影响的时候。我们的城市和州是分离的,但不是孤立的,很多时候,医疗保健系统和经济是密切相关的。这一模拟显示,即使接近未受管理的种群,被隔离的种群也能保护其公民。

使用 covid19_abs 的典型场景 5 仿真

场景 5 执行 50 次的平均结果
场景 6:垂直隔离
一些政府建议只需要隔离最危险的人,比如老人和病人,让其他人正常生活,正如这里的所看到的。除了几个先决条件之外,还有两个条件,一个是青年人的要求,另一个是青年人的要求,这就是新冠肺炎的要求。我们的模拟表明,当标准是拯救生命时,这一政策简单地不起作用。

使用 covid19_abs 的典型场景 6 仿真

场景 6 执行 50 次的平均结果
场景 7:所有人的面具
发现了使用口罩和手套作为病毒传播对策的有效证据,参见这里的。证据表明,使用口罩可以减少传染距离和传染率。假设,如果我们通过使用口罩限制移动范围(但不是完全限制)并降低感染率,会发生什么?我们的模拟结果显示了健康和经济方面的乐观结果。

使用 covid19_abs 的典型场景 7 仿真

场景 7 执行 50 次的平均结果
结论:所有的模型都是错误的,但其中一些是有用的
“所有模型都是近似值。本质上,所有的模型都是错的,但有些是有用的。然而,必须始终牢记模型的近似性质”——乔治·博克斯
各种模型都是一个过程的表示,而不是过程本身。一旦它们是复杂随机(有时是混沌)过程的近似值,我们很自然地会发现已知数据的误差和偏差。这些偏差不会使模型失效,但表明它必须改进。
我们的想法是不断改进模型,使其更加现实和数据驱动,而不仅仅是用它来模拟许多其他尚未想到的社会和环境方面。顺便说一下,我们随时欢迎您的反馈!
如果可以的话,呆在家里。但是,不管发生什么,保持健康和安全。一切都会过去,一切都会好的。
进一步阅读
- 流行病建模 101:或者为什么你的 CoVID19 指数拟合是错误的
- 新冠肺炎不可预测的曲线
- 所有人的面具?科学说是的。
感谢
我要感谢数据科学评论人员的宝贵贡献,我的同事 Paulo Vitor do Carmo Batista (也是我在{ci∂ic}的合作伙伴,数据科学和计算智能研究小组)和helder sei xas Lima,他们都来自 IFNMG 和Marcos Antonio alves和minds 的 frederico gade lha GUI mares,他们来自机器智能和数据科学实验室
凝聚聚类和树状图——解释
凝聚层次聚类、树状图及其在 python 中的实现

凝聚聚类是一种层次聚类算法。它是一种无监督的机器学习技术,将群体分为几个聚类,使得同一聚类中的数据点更相似,而不同聚类中的数据点不相似。
- 同一簇中的点彼此更接近。
- 不同簇中的点相距很远。

(图片由作者提供),样本二维数据集
在上面的二维数据集样本中,可以看到数据集形成了 3 个相距很远的聚类,并且同一聚类中的点彼此靠近。
聚集和分裂聚类算法及其实现综述
towardsdatascience.com](/hierarchical-clustering-agglomerative-and-divisive-explained-342e6b20d710)
凝聚聚类背后的直觉:
凝聚聚类是一种自下而上的方法,最初,每个数据点都是自己的一个聚类,随着层次结构的向上移动,更多的聚类对被合并。
聚集聚类的步骤:
- 最初,所有的数据点都是它自己的一个集群。
- 取两个最近的集群,将它们连接起来形成一个集群。
- 递归地进行第 2 步,直到获得所需的聚类数。

(图片由作者提供),第一张图:所有的数据点都是自己的一个聚类,第二张图:两个最近的聚类(被一个黑色椭圆包围)结合在一起形成一个单独的聚类。
在上面的样本数据集中,观察到两个集群彼此相距甚远。所以我们在得到 2 个集群后就停止了。

(图片由作者提供),样本数据集分为两个聚类

如何将两个集群连接成一个集群?
为了获得期望数量的聚类,聚类的数量需要从最初的 n 个聚类减少(n 等于数据点的总数)。通过计算两个聚类之间的相似性来组合它们。
有一些方法用于计算两个聚类之间的相似性:
- 两个聚类中最近的两个点之间的距离。
- 两个集群中两个最远点之间的距离。
- 两个聚类中所有点之间的平均距离。
- 两个簇的质心之间的距离。
选择上述任何一种相似性度量标准都有一些优点和缺点。
凝聚聚类的实现:
(作者代码)
如何获得最优的聚类数?
凝聚聚类算法的实现接受所需的聚类数。有几种方法可以找到最佳的聚类数,从而以如下方式将群体分成 k 个聚类:
同一簇中的点彼此更接近。
不同簇中的点相距很远。
通过观察树状图,可以找到所需的聚类数。
树状图是数据点之间层次关系的图形表示。它说明了由相应分析产生的聚类的排列,并用于观察分层(聚集)聚类的输出。
树状图的实现:
(作者代码)
点击从下载二维数据集样本。

(图片由作者提供),左图:可视化样本数据集,右图:可视化样本数据集的 3 个聚类
对于上面的样本数据集,观察到聚类的最佳数量是 3。但是对于高维数据集,其中数据集的可视化是不可能的,树状图在寻找最佳聚类数中起着重要作用。
如何通过观察树状图找到最佳聚类数:

(图片由作者提供),上述样本数据集的树状图
从上面的树状图中,找出一个最大高度不与任何水平垂直树状图线交叉的水平矩形。

(图片由作者提供),左:分成 2 簇,右:分成 3 簇
树状图中具有最大高度的矩形可以被切割的部分,最佳聚类数将是 3,如上图右侧所示。选择最大高度矩形是因为它表示最佳聚类数之间的最大欧几里德距离。
结论:
[## 了解 K-means、K-means++和 K-medoids 聚类算法
了解 K-means、K-means++和 K-Medoids 聚类算法及其关系的概述。这篇文章…
towardsdatascience.com](/understanding-k-means-k-means-and-k-medoids-clustering-algorithms-ad9c9fbf47ca)
在这篇文章中,我们讨论了凝聚层次聚类算法的深入直觉。该算法的缺点是空间和时间复杂度较大,不适用于大规模数据集。即使观察树状图来寻找大型数据集的最佳聚类数也是非常困难的。
感谢您的阅读
使用 Group by 和 Partition by 对 SQL 中的数据进行聚合和分组
通过一个简单的例子理解 GROUP BY 和 PARTITION BY 之间的区别。

照片由 [卡斯帕卡米尔·鲁宾](http://Caspar Camille Rubin)Unsplash
简介
聚合函数是一个非常强大的工具,可以用来分析数据和获得有用的业务洞察力。最常用的 SQL 聚合函数有SUM、MAX、MIN、COUNT、AVERAGE。为了汇总数据,聚合器通常与分组功能结合使用。在这个故事中,我将向您展示如何使用聚合函数和分组函数的组合。
得到💬任何数据科学或编程问题的 GPT 式答案。为成千上万的人生成摘要和学习笔记📚只需一次点击即可获得学习资源。👉
** [## 面向数据科学家和开发人员的免费学习资源。精选的博客、教程、书籍和…
机器学习和人工智能工程师的培训课程、黑客马拉松、活动和工作
aigents.co](https://aigents.co/learn)**
准备一些样本数据
让我们使用下面的脚本为这节课准备一些样本数据。你可以使用自己选择的不同平台,例如 SQL FIDDLE 、 KHAN ACADEMY 等。
CREATE TABLE Customer (id INTEGER , name TEXT, product TEXT, OwnershipPercentage numeric(4,3) , Effective_date numeric);INSERT INTO Customer VALUES (1, “BankA”, “A01”, 0.028, 20180223) ;
INSERT INTO Customer VALUES (1, “BankA”,”A02", 0.018, 20181224) ;
INSERT INTO Customer VALUES (2, “BankB”,”B01", 0.025, 20190101) ;
INSERT INTO Customer VALUES (2, “BankB”,”B02", 0.045, 20200101) ;select * from Customer;

表客户
问题
现在您可以看到,对于每个客户,都有多个(在本例中是 2 个)关于不同产品的所有权百分比和生效日期的记录。比方说,我需要为我的老板制作一份报告,并希望做一些数据分析来支持我的报告。根据我想要看到的内容,我将使用不同的聚合函数。在这节课中,我将给出使用 SUM()和 MAX()函数的例子。您可以想出不同的场景来使用其他功能。
解决方案
例如,我希望看到与之前的报告相比,每个客户的投资组合随着时间的推移发生了怎样的变化。为此,我希望看到每个客户的总所有权百分比,而不考虑产品。有两种方法可以做到这一点:使用分组依据和分区依据
使用分组依据
很简单,我能做的就是使用 aggregate SUM()函数,后跟一个“GROUP BY”子句。在查询中,SUM()函数会将一个数字列(OwnershipPercentage)中的所有值相加。GROUP BY 子句将列中所有相同的值分组,这些列是我们选择的属性,在本例中是客户 ID 和名称。
SELECT ID,
Name,
sum(p.ownershippercentage) AS onwership_percentageFROM Customer GROUP BY ID, Name

****按分组的结果
使用 OVER 和 PARTITION(BY)
获得类似结果的另一种方法是使用 OVER 和 PARTITION(BY)函数。要使用 OVER 和 PARTITION BY 子句,只需指定要对聚合结果进行分区的列。Over(partition by)子句将要求 SQL 只将每个分区内的值相加(在本例中为客户 ID)。
SELECT ID,
Name,
ProductID,
OwnershipPercentage,
sum(OwnershipPercentage) over(partition by ID) as total_ownership_percentageFROM Customer c

结果为过(分区通过)
通过上面的查询,我将得到一个名为 total_ownership_percentage 的列,它是每个客户的所有权百分比值的总和。
现在您可能已经意识到 GROUP BY 和 OVER(PARTITION BY)的输出之间的差异。GROUP BY 通过使用我们指定的属性汇总数据,从本质上减少了返回记录的数量。OVER(PARTITION BY)同时提供汇总的数据,而不汇总所有记录。在这种情况下,通过使用 PARTITION BY,我将能够返回每个客户的每个给定产品的 OwnershipPercentage 以及同一行中每个客户的总百分比。这意味着我将拥有每个客户的总所有权百分比的重复数据,但好的一面是,在聚合过程中没有数据丢失——与 GROUP BY 的情况相反。
SELECT ID,Name,
p.OwnershipPercentage,
max(c.OwnershipPercentage) as ownership_percentage FROM Customer c GROUP BY ID,Name
使用上面的代码,我将收到这条消息:列‘客户。“OwnershipPercentage”在选择列表中无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句 中。这是因为 GROUP BY 将只返回每个组的唯一结果,并且选择列表只能包含作为 GROUP BY 子句一部分的聚合函数或列。
因此,根据您想要得到的结果,您可以使用不同的函数来获得最佳输出。当您需要每个组有一个唯一的记录时,请选择 GROUP BY,当您不想丢失任何数据但仍想进行聚合时,PARTITION BY 将是最佳选择。
使用聚合最大值()和分组依据
下面是另一个使用 MAX()的场景。假设我现在想知道最近添加的产品及其每个客户的所有权百分比。
一种解决方案是在子查询中应用 aggregate Max()函数和 GROUP BY。子查询是另一个 SQL 语句中的 SELECT 语句。
select c.Name,
c.ownershippercentage,
c.Effective_date as effective_date
from Customer cinner join (select Name,
max(Effective_date) as max_date
from Customer group by Name) don c.Name = d.Name
and c.Effective_date = d.max_date
子查询将返回一个我称为“d”的表。通过这个子查询,我获得了表“d”中每个客户的最新生效日期。在此基础上,我在表“Customer”和表“d”之间执行了一个连接,以得出最近生效日期的 OwnershipPercentage。上述查询将给出您想要的输出,但不是最佳解决方案。我们必须在子查询中使用 JOIN 语句以及 aggregate MAX()和 GROUP BY 的组合,这增加了复杂性。在下面找到更有效的代码:
SELECT c.ID, c.Name, c.ProductID, c.OwnershipPercentage, c.Effective_DateFROM Customer cWHERE c.Effective_Date = (SELECT MAX(p.Effective_Date) FROM Customer p WHERE p.ID = C.ID)
任何一种方法都会得到如下相同的结果:

感谢您的阅读。希望这对学习有帮助。
聚合、转换、过滤——如何以及何时使用它们?
熊猫:从熟练工到大师——来自受害者的声音。

如果你想知道,当我说“受害者”时,那是因为我太被熊猫的能力宠坏了,直到我遇到了Aggregation, Transform, Filter、
他们让我很难理解引擎盖下的机制。在花了一些时间钻研之后,我对它有了更好的理解。现在,让我们开门见山地说吧。
我始终相信简单数据集对于方法说明的作用。因此,本文将使用一个非常简单的数据集:不同国家/地区的人口和预期寿命。
您可能已经熟悉带有基本计算的groupby聚合,如mean(), sum(), median()等。聚合、转换和过滤将 goupby 带到了另一个层次。
首先,我们来看一下groupby功能是如何工作的。2011 年,Hadley Wickham 在他的论文“数据分析的拆分-应用-组合策略”中引入了“拆分-应用-组合”的思想,使得groupby函数具有了说明性。一般来说,groupby功能由三个步骤组成:分割、应用和组合。split步骤根据指定的关键字将数据帧分解成子集数据帧。然后,apply步骤将函数应用于这些子集数据帧。最后,combine步骤将这些结果连接成一个输出数组。
聚合🐺
记住上面的过程,我们就很容易理解aggregation。基本上,aggregation对一列和多列应用多个函数。首先,它基于“区域”将完整的数据帧分成子数据帧。然后对“预期寿命”应用均值函数,对“人口”应用和函数。最后,它将结果组合成可以通过“reset_index”转换成数据帧的序列。最后,您将得到一个不同的数据帧,其长度是 groupby 键的唯一值的数量(在我们的例子中是“Region”)。下面是aggregation的视觉流程。

改变🐣
与聚合相比,transform多了一个叫做“广播”的步骤。它将结果从子数据帧广播到原始的完整数据帧。你可以把结果合并到原始的完整数据帧中。因此transform将总是返回一个与原始完整数据帧长度相同的序列。下面是transform的视觉流程。
transform的一个典型用例是计算组总数的百分比(在我们的例子中,是其所在地区的国家人口比例,例如印度在南亚地区的人口比例。
df[‘PopShare’]=df.groupby(‘Region’)[‘Population’].transform(lambda x: x/x.sum())

过滤器🐳
与 transform 相比,filter多了一个步骤。从这些子数据帧中获得结果后,它对这些结果应用一个过滤器(在我们的例子中,它是“RegionAverageLife”>75)。然后,这些过滤的结果将广播到原始数据帧中的匹配条件。因此,在这种情况下,您将获得完整数据帧的缩减版本。下面是filter的视觉流程。

总之,下面是Aggregation, Transform, and Filter.的最佳使用场景以及它们在 SQL 中的等效格式。

最后
保持乐观!感谢阅读!如果你想取得联系,可以在这里 联系我 。
敏捷数据科学的一个案例——迭代开发对数据科学来说很自然

敏捷对于数据科学来说是完美的(图片由i̇rfan·辛萨尔通过 Unsplash 提供)
TL;DR;
- 我在数据科学社区遇到了很多反对敏捷方法,特别是 scrum 框架的阻力;
- 我不这么看,并声称大多数学科将通过采用敏捷思维模式而得到改进;
- 我们将通过一个典型的 scrum sprint 来强调数据科学过程和敏捷开发过程的兼容性。
- 最后,我们讨论了什么时候 scrum 不适合遵循。如果你是一名顾问,同时在许多项目上工作,或者你的工作需要专注于一个狭窄的问题(狭窄,这样你就可以独自解决它)。
我最近发现了一个中型帖子,声称 Scrum 对数据科学来说很糟糕。恐怕我不同意,我想为敏捷数据科学做一个案例。
这篇文章的想法很大程度上受到了敏捷数据科学 2.0 书(我强烈推荐)和个人经历的影响。渴望知道其他经历,请在评论中分享。
首先,我们需要就什么是数据科学以及它如何解决业务问题达成一致,这样我们就可以研究数据科学的过程以及敏捷(尤其是 Scrum)如何改进它。
什么是数据科学?
网上有无数的定义。比如维基百科给出了这样的描述:
数据科学是一个跨学科领域,它使用科学的方法、流程、算法和系统从许多结构化和非结构化数据中提取知识和见解。
在我看来,这是对数据科学试图实现的目标的准确定义。但是我会进一步简化这个定义。
数据科学通过结合商业理解、数据和算法来解决商业问题。
与维基百科中的定义相比,我想强调的是,数据科学家的目标应该是解决业务问题,而不是提取知识和见解。
数据科学如何解决商业问题?
所以数据科学是来解决商业问题的。在此过程中,我们需要完成几件事情:
- 了解业务问题;
- 确定并获取可用数据;
- 清理/转换/准备数据;
- 为给定数据选择和拟合合适的“模型”;
- 将模型部署到“生产”——这是我们解决给定问题的尝试;
- 监控绩效;
与所有事情一样,有无数种方法可以实现这些步骤,但我会试图说服您,敏捷(增量和迭代)方法给公司带来最大的价值,给数据科学家带来最大的快乐。
敏捷数据科学宣言
我从敏捷数据科学 2.0 这本书的第 6 页摘录了这一点,所以鼓励你阅读原文,但这里是:
- 迭代,迭代,迭代-表格,图表,报告,预测。
- 船舶中间输出。即使失败的实验也有产出。
- 执行任务的原型实验。
- 在产品管理中整合数据的专制观点。
- 在工作时,沿着数据价值金字塔上下攀爬。
- 发现并追求通向杀手级产品的关键路径。
- 获取 meta。描述过程,而不仅仅是结束状态。
并非所有的步骤都是不言自明的,我鼓励你去阅读 Russel Jurney 所说的,但我希望主要思想是清楚的——我们共享和中间输出,我们迭代实现价值。
鉴于以上的预备工作,让我们回顾一下 scrum 团队的标准周。我们假设一周的冲刺。
Scrum 团队冲刺
第一天
sprint 的结构有很多变化,但是我会假设计划是在周一早上完成的。团队将决定产品待办事项中的哪些用户故事将被转移到 Sprint 待办事项中。从积压订单排名中可以明显看出,我们业务最紧迫的问题是客户欺诈——欺诈性交易导致我们宝贵的客户离开我们的平台。在之前的 backlog 精化会议期间,团队已经讨论了这个任务,产品负责人从欺诈调查团队获得了额外的信息。因此,在会议期间,团队决定从一个简单的实验开始(并且已经在考虑进一步有趣的迭代)——一个基于交易和参与用户的简单特征的初始模型。工作被分开,以便数据科学家可以去看看为这个问题确定的数据团队。数据工程师将建立将模型输出集成到 DWH 系统的管道,全栈工程师开始为欺诈调查小组建立交易审查和警报系统页面。
第二天
周二开始时,所有团队聚集在一起,分享进展。Data scientist 展示了一些图表,表明即使功能有限,我们也会有一个不错的模型。与此同时,数据工程师已经完成了系统设置的一半,以便使用新模型对传入的交易进行评分。全栈工程师也进展顺利,仅仅几分钟后,每个人都回到自己的办公桌前处理商定的任务。
第三天
与周二一样,团队从周三开始召开全体会议,分享他们的进展。已经有一个简单的模型构建和一些准确性和错误率的数字。数据工程师展示交易评分的基础设施,团队讨论特征如何到达系统,以及需要做什么来为算法做好准备。全栈工程师显示管理面板,其中显示了关于事务的元数据和触发机制。接下来的另一个讨论是关于模型输出触发欺诈分析师消息的阈值。团队同意我们需要能够调整这个值,因为不同的模型可能有不同的分布,而且,根据其他变量,我们可能希望增加和减少批准的事务的数量。
第四天
周四,团队已经有了所有的部分,在站立会议期间,讨论如何整合这些部分。该团队还概述了如何在生产中最好地监控模型,以便可以评估模型性能,并在造成任何实际损害之前检测到退化。他们一致认为,一个简单的监控准确性和错误率的仪表板就足够了。
第五天
星期五是演示日。在站立期间,团队讨论交易欺诈检测的第一次迭代遗留的最后问题。团队成员准备与将使用此解决方案的欺诈分析师会面。
在演示过程中,团队展示了他们为欺诈分析师构建的内容。该团队展示了绩效指标及其对欺诈分析师的影响。所有的反馈都转化为未来冲刺的任务。
Sprint 的另一个重要部分是回顾会议——团队讨论三件事。冲刺阶段什么进展顺利;
2.哪些方面可以改进;
3.在下一次冲刺中,我们将致力于改进什么;
沿着这条路走下去
在下一个冲刺阶段,团队正在处理产品待办事项中另一个最重要的项目。这可能是欺诈分析师的反馈,也可能是产品负责人认为对整体业务改善最大的其他东西。然而,该团队密切监控解决方案初始版本的性能。它将继续这样做,因为 ML 解决方案对模型关于数据分布的基本假设的变化很敏感。
讨论
以上是对数据科学解决方案的 scrum 过程的一个相对“干净”的阐述。现实世界很少是这样的,但我想传达几点:
- 数据科学无法独立存在。如果我们要影响现实世界,我们必须在一个跨职能团队中合作,它应该是一个更大团队的一部分;
- 迭代在数据科学中是至关重要的,我们应该向我们的涉众公开那些迭代的工件,以便尽快得到反馈;
- Scrum 是一个为迭代开发设计的框架。因此,它非常适合数据科学工作;
然而,它不是任何努力的框架。如果你的工作需要你深入思考几天,那么 Scrum 和敏捷可能会非常具有破坏性和反作用。此外,如果你的工作需要你处理大量不同的小型数据科学相关的任务,跟随 Scrum 是不合适的,也许应该考虑看板。然而,典型的产品数据科学工作并不是这样的。迭代是王道,快速获得反馈是为业务问题提供正确解决方案的关键。
概括起来
数据科学非常适合 Scrum,只需要一个简单的修改——我们不期望发布完整的模型。相反,我们交付我们工作的工件,并从我们的涉众那里征求反馈,这样我们可以更快地取得进展。项目经理可能因为进展的不可预测性而不喜欢数据科学,但是迭代没有错,它是唯一的前进方式。
我想知道你对敏捷数据科学的看法?什么对你和你的团队有效?什么没用?希望大家留下评论!
敏捷开发 101——科技界的雷吉娜
当目标可能在一夜之间改变时,敏捷方法给予开发人员和数据科学家同样的适应性和灵活性。

戴维·特拉维斯在 Unsplash 上拍摄的照片
在技术部门工作,敏捷开发很可能在你的项目中被利用。使用敏捷方法为开发人员提供了工具,以便在客户可能在一夜之间改变其目标的时候具有适应性和灵活性。使用敏捷将允许团队毫不犹豫地适应。
什么是敏捷开发?
敏捷开发指的是一组专注于迭代开发的方法。开发过程中的需求和解决方案在整个过程中不断发展。这种发展是由不同职能团队之间的合作推动的。scrum 和看板就是其中的两种方法。两者都鼓励对项目的频繁反思,以便开发过程与业务需求相一致,例如客户目标。
当一个开发方法声称与敏捷一致时,它是基于敏捷宣言。这个宣言是 2001 年由 17 个人在犹他州的一个滑雪小屋创作的。在他们相遇之前,主要的开发方法被称为瀑布方法。由于需要持续更新,这种传统方法已经过时。敏捷支持这一关键的业务需求。

原始照片由 Szabo Viktor 在 Unsplash 上拍摄
什么是敏捷宣言?
敏捷宣言基本上是一个宣言,旨在帮助开发者和企业找到一种对两者都有效的方法。这是一种让企业继续成长和适应而不会让开发人员筋疲力尽的方式。
4 价值观是宣言的核心:
- 流程和工具上的个人和交互
- 工作软件综合文档
- 客户协作合同谈判
- 根据计划应对变化
宣言指出,左边的项目(粗体)比右边的项目更有价值。两者都很重要,但把更多的重量放在左边。
该宣言有 12 条原则:
- 我们最优先考虑的是通过早期和持续交付有价值的软件来满足客户。
- 欢迎不断变化的需求,即使是在开发的后期。敏捷流程利用变化为客户带来竞争优势。
- 频繁地交付工作软件,从几个星期到几个月,优先选择较短的时间尺度。
- 业务人员和开发人员必须在整个项目中每天一起工作。
- 围绕有积极性的个人建立项目。给他们需要的环境和支持,相信他们能完成工作。
- 向开发团队传达信息的最有效的方法是面对面的交谈。
- 工作软件是进步的主要衡量标准。
- 敏捷过程促进可持续发展。发起人、开发人员和用户应该能够无限期地保持恒定的步调。
- 对技术优势和良好设计的持续关注增强了敏捷性。
- 简单——最大化未完成工作量的艺术至关重要。
- 最好的架构、需求和设计来自自组织团队。
- 团队定期反思如何变得更有效,然后相应地调整自己的行为。
当一个团队同意应用敏捷方法时,他们坚持这些价值观和原则。
Scrum 敏捷开发?
Scrum 是敏捷开发的一个子集,它依赖于冲刺阶段的每日会议。sprint 通常需要 1-4 周的时间来完成一个项目。在这个冲刺阶段,团队将定期会面,交流他们的进展。这个简短的会议是开发人员陈述他们已经完成了什么,他们计划在下一次会议之前完成什么,以及他们是否面临任何障碍的时候。这些会议由一个 Scrum 大师领导,他的主要工作是帮助开发人员通过路障。这些快速的会议被称为站立会议,因为每个人都是站着进行的。取决于你的团队,他们可能会也可能不会这样做。

每个团队和企业都有自己的 Scrum 变体。它通常包括每日站立,冲刺,以及最后的冲刺回顾。有些人会让开发人员写出一个用户故事来解释新特性背后的原因。每个版本之间的结构将具有相同的骨架。
看板敏捷开发?
看板是一种可视化的敏捷方法。它依赖于使用卡片和一块板,想想 Trello 或便利贴和白板。这使得团队可以看到工作流将由什么组成,并尽早找到瓶颈。这可能在某个时候需要一个团队成员或者需要购买设备。这是一种非常主动的方法。
该板,又名看板板,上面将有列。这些列被称为看板泳道。每个人将给出一张卡片,进行分类,以区分任务和项目。有些泳道可能是待办事项、正在进行的事项和已完成的事项。这种可视化允许整个团队在有限的会议时间内处于项目流程的同一页面上。
Gif via giphy
什么是常见的敏捷方法实践?
这是一个很好的问题。尽管每种方法都有自己的蓝图,但每种方法都有一些共同点。以下是一些敏捷实践:
结对编程
顾名思义,它是指两个程序员同时在同一代码上一起工作。这通常包括一个程序员作为打字员,另一个问他们的思维过程是什么。这也可能只是排除程序故障。当进行结对编程时,有一个时间间隔来交换角色将有助于防止双方都筋疲力尽。
Gif via giphy
客户参与
与客户沟通项目进展对退货业务至关重要。敏捷开发为客户提供了参与当前开发的机会。不是字面上的意思,而是为了快速简单地了解项目在哪里。如果客户打电话来询问项目进展如何,项目经理会很快知道应该让客户知道什么。
燃尽图
燃尽图是一种很好的方式,可以直观地显示项目还剩多少时间。如果一个项目剩下太多的元素,那么这就给了开发团队一个适应环境的机会。这可能是让项目经理与客户沟通,或者对某些元素进行优先排序。

https://en . Wikipedia . org/wiki/Burn _ down _ chart # Reading _ Burn _ down _ charts
测试驱动开发(TDD)
测试驱动开发是将需求转化为下一次迭代的测试用例的实践。这使得以前的需求不会因为急于修补特性而变得过时或被遗忘。这绝对不是任何人想要的情况。
敏捷开发是一种迭代方法,有助于持续的更新/发布。这些方法允许开发人员/人的需求和业务需求在中间相遇并被理解(希望如此)。
在我们重新学习之前,

人工智能在银行业的应用
用技术公式正确解决问题(第 1 部分)
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
你已经听到了传言:人工智能(AI)是金融领域炙手可热的新商品。但你能在你的核心银行系统上撒点“智能”就称之为胜利吗?几乎没有。
形式化一个人工智能用例,甚至运行一个成功的试点是容易的部分。部署和扩展人工智能算法是事情变得复杂的地方。
//只有 22%使用机器学习(ML)的企业成功地将模型部署到生产环境中。//
让人工智能正确很难,但是谁需要它呢?
如果想保持长期竞争力,大多数银行都会这么做。根据 Temenos 的一份报告,77%的银行高管表示,人工智能的成功实施将在未来几年内区分银行领域的领导者和落后者。
显然,最先解决人工智能扩展和部署挑战的人将获得最大的市场回报。
但是如果不知道前面有什么障碍,你就不可能赢得比赛。
为什么在金融领域实施人工智能很难
法规、合规性、隐私和数据偏差——这些是研究人工智能的金融机构普遍关注的问题。但是让我们暂时假设这些都不存在,从纯技术的角度来衡量复杂性因素。
想象一下:一群高管被新的决策分析引擎所说服。理论上,这个项目看起来很完美
- 预测分析可以调整销售价格
- 下一个最佳行动(NBA)组件可以提高追加销售/交叉销售
- 分析组件可以减少支付中的误报数量
- 投资回收期可能只有一两年
“酷豆,”领导说。“让我们把引擎发动起来!让 ML 团队尽快解决这个问题。”
现在有趣的部分来了:机器学习团队深入项目,却遇到了一个又一个障碍:
- 巨大的数据仓库和缺乏统一的数据管理流程颠覆了准备所需数据集的流程。
- 关键数据所在的遗留基础设施需要重新搭建平台或完全替换,以避免中断核心系统。
- 需要组装和配置具有大量 GPU 的新云基础设施,以支持算法的测试和部署。
- 很少有人能真正完成所有这些事情。
这就是一个在纸面上有着极高投资回报率的盈利试点如何变成一个正在失去吸引力的大额投资,并最终在一个试点(和一些宣传)后被取消。
那么,为什么如此多的金融公司在早期的人工智能投资中遭受损失,并且未能超越试点?
有几个原因:
- 由于过时(或不存在)的数据治理流程,缺乏生产就绪数据和足够快速地访问这些数据的能力。
- 人工智能算法需要关注,尤其是在部署的最早阶段,包括监督、维护、合规和网络安全等。是的,AI 可以自我学习,但它永远不会完全不用手。
- 一个弱的或者不存在的集成开发环境产生了测试和部署瓶颈。
- 人工智能部署在核心银行系统中创建了一个新的架构层,这些系统需要与遗留系统共存,而不会中断它们。
- 将一个算法打包成一个有吸引力的面向客户的解决方案来增加价值需要额外的时间和专业知识。
那么,我们是在建议你完全放弃你的人工智能梦想,让数字原生竞争获胜吗?
一点也不。引入人工智能是昂贵的错误。但是您可以通过坚持自下而上的方法来最小化风险、成本和采用时间表。可以用这个公式来概括:
(遗留+前端转换)× AI =现代银行
这是一篇由两部分组成的文章。在这一部分中,我们将关注遗留系统。如果您想先了解前端转换,请点击这里的(但是您也应该认真阅读这一部分!).
银行业人工智能的传统转型:需要解决的 4 个领域

图片由 Intellias 提供
金融领域的人工智能需要几个关键构件:
- 数据治理和管理平台
- IT 治理框架和架构优化
- 云计算和云 GPU
- MLOps
三分之二的银行业高管(66%)表示,人工智能、云和 DevOps 等新技术将在未来五年继续推动全球银行业转型。"泰梅诺斯报告
数据治理和管理平台
连接和整合内部和外部数据源的统一数据管理平台是每个人工智能实施的支柱。
除了为您提供一系列用于分析的初始数据集,数据治理平台还可以帮助您:
- 提高数据可追溯性和可问责性
- 增强数据安全性和合规性
- 支持人工智能用例的扩展,因为你总是有精简的数据用于分析。
您需要组装的数据管理平台需要得到 IT 治理框架的进一步支持。
IT 治理框架和架构优化
大多数遗留银行系统的问题是它们陈旧、混乱、僵化,没有给新的元素留下空间。
IT 治理过程的目标是帮助你弄清楚在你当前的架构难题中把 AI 放在哪里。
本质上,这样的框架被设计来帮助您挑选和探测您的遗留软件,以查看哪些系统组件可以被解耦和现代化,而不会点燃核心(也就是说,打个比方)。
因此,正如我在另一篇关于银行业遗留现代化的文章中所写的那样,你可以在系统层面进行现代化,一次一个元素地发展你的平台,而不是试图一举取代核心(冒很大的风险)。

由 Intellias 制作的信息图
迁移到更松散的架构将有助于您:
- 分配新人工智能服务的位置
- 将更多数据源连接到您的数据管理平台
- 弄清楚新算法如何与其他服务集成。
云计算和云 GPU
下面是对 AI 的一个非常简单的解释:
AI =(代码+数据)×计算能力
考虑到您已经组织了您的代码并简化了对数据的访问(并且可能将它迁移到了云中),您现在可以开始寻找计算能力了。
毕竟,深度神经网络和其他复杂的 ML 算法是耗电的生物,需要大量的计算能力来操作给它们的数据并产生预测。
本质上,神经网络是在训练和预测阶段对网络输入(您的数据)执行大量矩阵乘法的结果,以便您可以获得良好的输出(预测或洞察)。
根据任务的复杂程度,网络可以使用 10、100 甚至100 亿个参数来识别给定数据中的模式并产生结果。
为了运行这些操作,你的算法需要计算能力,这就是GPU(图形处理单元)发挥作用的地方。这些芯片可以帮助您加快计算速度,更快地获得结果。
你可以在内部储备一批 GPU,或者从服务提供商那里租赁云 GPU 容量——这将允许你在未来自动化和扩展更大的算法部署(或者避免在你的培训比预期更复杂时争夺资源)。
考虑到 GPU 即服务市场预计到 2025 年将达到 70 亿美元,你可以猜到大多数公司更喜欢做什么。现在,除了计算能力,您还需要一些额外的资源来存储您的数据、测试集、实验、版本控制和测试结果。同样,将所有这些都保存在云中是大多数公司选择的路线。
这就把我们带到了下一个要点:保持你的人工智能项目有组织并准备好部署。
MLOps
机器学习+ DevOps = MLOps,这是一个新的运动,旨在创建一种建立、测试和部署 ML/AI 模型的简化方法。
MLOps 的目标是帮助您采用和自动化机器学习(ML)模型的持续集成(CI)、持续交付(CD)和持续培训(CT)。谷歌云
更高程度的自动化增加了开发过程的可预测性,并减少了由于小错误而导致模型失败的机会。
以下是您从 MLOps 获得的信息:
- 用于推出新模型的可重复使用的管道和可重复的工作流程
- 改进的数据集成和统一的数据治理
- 自动化的模型设置、培训和测试(针对类似的项目)
- 一键式复制和自动化版本控制
- 热键访问项目所需的所有库、框架和集成
因此,你的人工智能团队可以直接行动起来,以更快的速度、更低的成本和更少的风险运行新的实验,而不是浪费时间来组装新的人工智能项目的所有细节。
总结等式的遗留转换部分:
- 评估你的系统,为你的人工智能找到最佳位置。
- 分离数据源,并将它们连接到新的数据管理平台。
- 寻找进一步整合和现代化的机会。
- 为新的人工智能测试分配云基础设施。
- 获得您需要的 GPU 容量。
- 使用 MLOps 原则制定清晰的路线图。
好了,我们已经完成了等式的第一部分— 遗留转换。
因为它已经相当不错了,我们保留了等式的第二部分——前端和人工智能转换——作为本文 的第二部分 。
人工智能在银行业的应用
用技术公式正确解决问题(第 2 部分)
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
银行业的人工智能是一大福音,但往往也是一大祸害。
权衡是巨大的,但是实施一个简单的解决方案的挑战通常会阻碍银行的创新。正如我们在本系列 的第一部分 中提到的,许多人工智能飞行员在测试或部署阶段都失败了。
原因?缺乏强大的技术基础,配以清晰的技术路线图来依次升级系统的所有关键元素,然后再用人工智能增强它们。
正如我们在上一部分中所讨论的,核心银行遗留系统的分离和现代化是您路线图上的第一要务。
您议程上的下一步是前端转换。
让你的前端适应人工智能的采用
人工智能经常被认为是解决低效流程的良方。公司可能会说让我们发送 RPA 来处理发票或为什么 ML 算法不能为客户做所有的报告?
然而,很少有金融领袖倾向于问这个问题:这个特定的过程甚至需要人工智能增强吗?
因为让我们面对现实吧:很多前台银行流程都有些过时了。为了客户的房贷申请,你需要在分行收集一吨的纸质文件吗?No. 挪威的银行 ID 经验表示,你可以完全无纸化,只需向你的客户发放数字 ID(看不到人工智能),就可以将申请过程从 16 天减少到 1 天。
当您的移动银行应用程序仍然为您的客户提供糟糕的数字开户体验时,为您的移动银行应用程序添加人工智能驱动的语音礼宾有意义吗?没有。不会有太大的不同。
//为了从人工智能的采用中获得最大的影响,传统的财务流程需要重新配置。否则,投资回报率将难以捉摸。//
这就是转变前端流程是第二个核心要素的原因。
好吧,那么我该如何重新配置旧的来为新的铺平道路呢?
这里有一个简单的蓝图:
- 让你的候选人排队接受人工智能增强。将所有可能的用例分成两类:面向客户和面向员工的流程/解决方案。从可行性、时间表和可能的节约/投资回报方面评估每个解决方案。
- 依靠设计思维。采取基于旅程的方法来选择你的候选人。从最终用户的角度评估你的清单。新技术可以在哪些方面增加更多价值,为什么?
- 从零开始。与其尝试去适应一个低价值的流程,不如想想如果你 a)完全摆脱它,b)用一个干净的版本代替它,或者 c)代替它,并考虑新流程如何进一步补充和加强你的设置中的其他流程,会发生什么。
最后一点尤其重要,因为银行业有大量漏洞百出的流程,金融科技公司很早就开始着手解决:令人生畏的开户流程、复杂的信用卡订购流程、缺乏负担得起的贷款、冗长的信用卡审批等等。

开立一个新银行账户所需的平均天数。图片由为火星建造
基于这些数据,很容易假设仅仅增加一些人工智能算法不会帮助汇丰奇迹般地名列榜首。他们的数字银行前台需要更大的提升。
因此,如果你觉得自己在竞争中落在了后面,试试下面的数字银行前台转型方法:考虑层次,而不是单个流程或解决方案。

由 Intellias 提供的信息图表
排列和扩展银行业中的人工智能用例
我们终于到达了我们一直在准备的部分——在银行业实现人工智能!
正如前面几节所述,让人工智能做好准备是一条漫长的道路,至少有两个主要的障碍:改造遗留系统和适应前台系统流程。
记住:根据埃森哲的数据,只有 16% 的高管能够扩大人工智能项目的规模。正如埃森哲的数据进一步指出的那样,大多数人都遇到了我在本文开头描述的相同的人工智能采用困难。
与此同时,那些成功度过最初试点阶段、实现战略扩展的企业,终于看到了承诺的红利:
与处于人工智能之旅概念验证阶段的公司相比,战略规模公司从人工智能投资中获得的回报接近三倍。埃森哲
尤其是在银行业,扩展以下类型的人工智能计划会带来最高的回报:
信用评分
移动数据和机器学习被证明是吸引信用薄弱的消费者的强大组合,这些消费者是目前被传统金融机构(但不太被金融科技公司)抛弃的无银行账户、银行服务不足和首次贷款者。
由 ABCD 技术堆栈(人工智能、区块链、云和数据)支持的即时和负担得起的消费贷款已经帮助三家全数字化的中国银行(作为超级应用运营)每年处理超过 1000 万份贷款申请,并保持平均 1%的不良贷款率。
基于替代数据来源的贷款现在正在欧洲、东南亚甚至美国迎头赶上,在美国,FICO 刚刚发布了一项新服务,允许消费者提交额外数据以增加他们的信用评分。
如果银行不在短期内采取行动,就有可能在消费者和中小企业贷款竞赛中失利。
对话式人工智能(聊天机器人)
聊天机器人的未来是语音引导的智能财务顾问,可以为客户和团队提供礼宾服务。基于人工智能的智能顾问能够:
- 提供个人理财辅导
- 协助日常账户管理
- 为资产/财富管理提供机器人咨询服务
- 提供基本的客户支持
- 提供个性化的产品/服务推荐。
去年,12%的消费者使用语音功能支付账单,10%的消费者使用语音功能向他人转账。
考虑到语音支付在 2020 年越来越受欢迎,可以肯定的是,语音在银行业的使用也将进一步攀升。
个人理财
由人工智能驱动的新一代个人财务管理应用程序可以为预算增添乐趣(fudgeting,有人吗?).
人工智能模型可以被配置为教会用户有意识地消费,并为以下方面提供个性化建议,而不是敦促用户停止在鳄梨吐司上浪费金钱:
- 抑制开支
- 账单规划
- 增加净值
- 提高信用评分
- 无债一身轻
- 为退休或大学做打算。
事实上,早期趋势表明,在 5 到 10 年内,个人理财领域可能会完全自主。
对银行来说,赶上这股金融扫盲潮流可以降低账户转换率,提高客户终身价值。
风险管理
根据 Emerji 的说法,风险监控是银行业最受欢迎的人工智能功能之一,已经占供应商产品提供能力的 26.9%。特别是,银行正在考虑采用智能模型来预测投资风险,并为各种交易决策制定更好的行动方案。
例如, Kensho 利用历史和实时市场数据以及自然语言处理能力和视觉图像识别来收集全面的市场数据,并对股票表现做出高度准确的预测。
金融欺诈
还可以配置机器学习模型来保护客户的资产。ML 在欺诈监控方面比人类团队(或由所述人类编程的传统的基于规则的引擎)更有效,因为机器学习算法:
- 可以近乎实时地操作大量数据
- 全天候运行
- 可以扩展以覆盖更广的防御面
- 可以根据个人用户的消费模式进行个性化设置
- 随着时间的推移自我改进,并能够应对以前看不到的威胁。
财富管理
ML 模型可以根据存储在数据湖中的数据,为您的客户和顾问提供预测性和规范性的投资建议。例如,Credit Karma 为每个用户收集了超过 2600 种不同的数据属性,他们的人工智能模型评估了大约 80 亿个关于每个客户下一步最佳行动的预测。
除了机器人建议之外,在财富管理领域已经得到验证的人工智能用例包括:
- 业务流程优化和报告
- 个性化客户入职
- 高级作战情报。
包扎
我可以继续列举其他的人工智能用例,但是这条线需要在某个地方画出来。具体来说,我们应该考虑成功的早期试点与规模化人工智能部署之间的界限。你在进行遗留转换上拖得越久,这条线就离得越远,因为它会被更敏捷的竞争者推得更远。
是的,在新技术、客户偏好和不断变化的市场需求快速发展的生态系统中,致力于部署人工智能是很困难的。
但你不必一头扎进人工智能的采用中。相反,建立你的上(遗产)和下(前端)身体力量,然后在上面设置一个智能(人工智能)头。
面向医疗保健的人工智能和机器学习
AI/ML 在医疗保健中的应用概述。
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。

图片来源: Pixabay(免费用于商业用途)
介绍
21 世纪只有 20 年,可以肯定的是,本世纪人类社会最大的变革性技术和推动者之一将是人工智能(AI)。一个公认的观点是,人工智能及相关服务和平台将改变全球生产力、工作模式和生活方式,并创造巨大的财富。
例如,麦肯锡认为,到 2030 年,全球经济活动将达到约 13 万亿美元(T21)。在短期内,研究公司 Gartner 预计,全球基于人工智能的经济活动将从 2018 年的约 1.2 万亿美元增加到 2022 年的约 3.9 万亿美元。
高度潜在的用例:基于数据的诊断支持人工智能驱动的诊断使用病人的独特历史作为…
www.pwc.com](https://www.pwc.com/gx/en/issues/data-and-analytics/publications/artificial-intelligence-study.html)
众所周知,这种转变在很大程度上是由强大的机器学习(ML)工具和技术推动的,如深度卷积网络、生成对抗网络(GAN)、梯度提升树模型(GBM)、深度强化学习(DRL)等。
然而,传统的商业和技术部门并不是唯一受到人工智能影响的领域。医疗保健是被认为非常适合应用人工智能工具和技术的领域。
诸如电子医疗记录(EMR) 等强制性做法已经为医疗保健系统应用大数据工具进行下一代数据分析做好了准备。AI/ML 工具注定会为这个流程增加更多的价值。它们有望提高初级/三级患者护理和公共医疗保健系统中自动化和智能决策的质量。这可能是人工智能工具的最大影响,因为它可能会改变全球数十亿人的生活质量。
医疗保健中应用 ML 的主要示例
人工智能辅助放射学和病理学

图片来源: Pixabay(免费商用)
如今,电子存储的医学成像数据非常丰富,DL 算法可以使用这种数据集来检测和发现模式和异常。机器和算法可以像训练有素的放射科医生一样解释成像数据——识别皮肤上的可疑斑点、病变、肿瘤和脑出血。因此,使用 AI/ML 工具/平台来帮助放射科医生,将会呈指数级增长。
这种方法解决了医疗保健领域的一个关键问题,因为在全世界范围内,训练有素的放射科医生越来越难找到。在大多数情况下,由于数字医疗数据的泛滥,这些技术工人承受着巨大的压力。根据本文中的,一个普通的放射科医师需要每 3-4 秒钟为一幅图像生成一个解释结果才能满足需求。
人工智能(AI)算法,特别是深度学习,已经在…
www.ncbi.nlm.nih.gov](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6268174/)
识别罕见或难以诊断的疾病通常依赖于检测所谓的“边缘病例”。由于这种 ML 系统建立在包含这些疾病的原始图像(和各种转换)的大型数据集上,因此对于这种类型的检测,它们通常比人更可靠。
它们有望提高初级/三级患者护理和公共医疗保健系统中自动化和智能决策的质量。这可能是人工智能工具的最大影响,因为它可能会改变全球数十亿人的生活质量。
一个优秀的测试案例是微软的 InnerEye 项目,该项目采用 ML 方法,使用 3D 放射图像分割和识别肿瘤。它有助于精确的手术计划、导航和放射治疗计划的有效肿瘤轮廓绘制。
越来越多地用于早期癌症检测的 MRI 和其他先进成像系统正在配备 ML 算法。下面的文章提供了这方面的全面概述。
来源:Thinkstock -新人工智能(AI)帮助放射科医生更准确地阅读乳腺癌筛查…
healthitanalytics.com](https://healthitanalytics.com/news/deep-learning-ai-improve-accuracy-of-breast-cancer-detection)
下面的 Nature 文章描述了如何应用 ML 技术来执行高级图像分析,如前列腺分割和多种成像数据源(如超声检查、CT 和 MRI)的融合。
机器学习(ML)正在彻底改变和重塑医疗保健,基于计算机的系统可以被训练成…
www.nature.com](https://www.nature.com/articles/s41585-019-0193-3)
通过增加外科医生的显示,ML 工具也增加了重要的价值,例如在机器人手术和其他图像引导介入过程中的癌症定位。
因此,使用 AI/ML 工具/平台来帮助放射科医生,将会呈指数级增长。
ML 和数据科学提供可操作的见解

图片来源: Pixabay(免费商用)
在当今世界, 在各种医疗保健机构(公立医院、疗养院、医生诊所、病理实验室等)中,艾字节大小的医疗数据正在被数字化 。).不幸的是,这些数据通常是杂乱无章的。与标准事务型业务数据不同,患者数据不太适合简单的统计建模和分析。
强大而敏捷的人工智能平台能够连接到大量患者数据库并分析复杂的混合数据类型(例如,血液病理学、基因组学、放射学图像、病史),是当前的需求。此外,这些系统应该能够以深入的方式筛选分析,并发现隐藏的模式。
此外,他们应该能够将他们的发现翻译并可视化为人类可理解的形式,以便医生和其他医疗保健专业人员能够以高度自信和完全透明的方式处理他们的输出。
可解释的人工智能和分布式人工智能系统——非常符合这些要求,并准备在不久的将来满足这些系统的需求。
用于手术辅助的物理机器人

图片来源: Pixabay(免费商业使用)
手术机器人可以为人类外科医生提供独特的帮助,
- 增强在过程中观察和导航的能力,
- 产生精确的微创切口。
- 以最佳的缝合几何形状和伤口减少疼痛
人工智能/人工智能在这种数字手术机器人中的应用确实有令人兴奋的可能性。
- 借助大规模分布式处理的机器人以软件为中心的协作****
- 基于手术历史(由机器和人类执行)及其结果(有利或不利)的数据驱动洞察和指导
- 人工智能生成的虚拟现实空间用于实时方向和引导
- 远程医疗和远程手术的可能性相对简单的程序
下面的文章简要总结了潜在的应用。
外科机器人超越了硬件,为外科医生提供了更好的技能,改善了患者的预后。罗杰·史密斯|…
www.roboticsbusinessreview.com](https://www.roboticsbusinessreview.com/health-medical/how-robots-and-ai-are-creating-the-21st-century-surgeon/)
用于医疗保健运营管理和患者体验的人工智能
在美国,普通公众接受适当医疗保健的费用和困难一直是长期激烈辩论的主题。
人工智能和相关的数据驱动技术为解决一些问题做好了独特的准备,这些问题被确定为根本原因——排长队,担心不合理的账单,漫长而过于复杂的预约流程,无法获得正确的医疗保健专业人员。
这些相同的问题已经困扰传统企业几十年了,人工智能/人工智能技术已经成为解决方案的一部分。这是因为,庞大的数据库和智能搜索算法是人工智能系统的强项,擅长于这种模式匹配或优化问题。因此,医院和公共卫生组织必须在日常运营中利用先进的 AI/ML 工具和技术。
[## 医疗保健 AI - Olive 的 11 个运营应用
人工智能和自动化在医疗保健操作中的应用:1。资格检查和事先…
oliveai.com](https://oliveai.com/blog/11-operational-applications-for-healthcare-ai/)
伟大的事情是,对数据隐私的关注,这是医疗保健系统的一个复杂而困难的问题,并没有对这种类型的人工智能应用构成巨大挑战。最常见的情况是,运营问题并不涉及与疾病、诊断或药物相关的机密患者数据,而是像任何其他现代商业企业一样,包含与财务、资本、营销或人力资源问题相关的数据。

图片来源: Pixabay(免费用于商业用途)
这种系统的核心目标应该是使以为目标的人工智能辅助平台增强最大部分普通人的医疗保健服务体验。传统企业中已经部署的系统的首要目标是最大化利润。用于医疗保健运营管理的强大人工智能工具必须通过将同理心与盈利目标相结合,将自己与那些传统系统区分开来。
人工智能/人工智能技术辅助下的药物发现

图片来源: Pixabay(免费商业使用)
人工智能和人工智能技术越来越多地被制药行业的大腕所选择,以解决成功发现药物这一极其困难的问题。一些突出的例子——涉及赛诺菲、基因泰克、辉瑞——摘自本文。这些案例研究涵盖了各种治疗领域——代谢疾病、癌症治疗、免疫肿瘤药物。
一个巨大的数字笼罩着寻找新药的科学家们:据估计,开发新药的费用高达 26 亿美元。
www.nature.com](https://www.nature.com/articles/d41586-018-05267-x)
超越传统的长距离过程,人工智能技术越来越多地被应用于加速早期候选选择和机制发现的基本过程。
例如,生物技术公司 Berg 使用其人工智能平台分析来自患者的大量生物和结果数据(脂质、代谢物、酶和蛋白质图谱),以突出患病细胞和健康细胞之间的关键差异,并识别新的癌症机制。
[## 伯格的人工智能:只是另一家生物技术或改变行业的公司?
评估伯格(波士顿生物技术)的战略在短期和中期就其人工智能,疑问…
digital.hbs.edu](https://digital.hbs.edu/platform-rctom/submission/artificial-intelligence-at-berg-just-another-biotech-or-industry-changing-company/)
这方面另一个突出的例子来自 DeepMind 使用他们的 AlphaFold 系统发表了与新冠肺炎病毒(新型冠状病毒)相关的可能蛋白质结构。
科学界已经为应对最近的新冠肺炎疫情而振奋起来,建立在几十年的基本…
deepmind.com](https://deepmind.com/research/open-source/computational-predictions-of-protein-structures-associated-with-COVID-19)
许多初创公司也在致力于使用人工智能系统来分析多渠道数据(研究论文、专利、临床试验和患者记录),方法是利用贝叶斯推理、马尔可夫链模型、强化学习和自然语言处理(NLP)中的最新技术。关键目标是发现模式和构建高维表示,存储在云中并用于药物发现过程。
这是一篇综述文章,展示了 DL 在药物发现中的应用。
深度学习算法已经在许多不同的任务中实现了最先进的性能。
towardsdatascience.com](/review-deep-learning-in-drug-discovery-f4c89e3321e1)
用于医疗保健运营管理的强大人工智能工具必须通过将同理心与盈利目标相结合,将自己与那些传统系统区分开来。
走向未来——精准医疗和预防保健
根据美国国家医学图书馆的说法, 精准医学 是"一种新兴的疾病治疗和预防方法,它考虑了每个人在基因、环境和生活方式方面的个体差异。
展望未来,这可能是 AI/ML 在医疗保健领域应用的最具影响力的好处之一。
这里的目标极其复杂和苛刻——根据个人病史、生活方式选择、基因数据和不断变化的病理检查,为个人找到精确的治疗方案。自然,我们需要引入最强大的人工智能技术——深度神经网络、人工智能驱动的搜索算法/高级强化学习、概率图形模型、半监督学习——来应对这一挑战。
除了对疾病和治疗进行预测和建模,这样的人工智能系统还可以预测未来患者在早期筛查或常规年度体检数据的情况下患特定疾病的概率。此外,人工智能工具可能能够模拟疾病更有可能发生的原因和环境,从而帮助指导和准备医生干预(以个性化的方式),甚至在个体开始出现症状之前。
这里的目标极其复杂和苛刻——根据个人病史、生活方式选择、基因数据和不断变化的病理检查,为个人找到精确的治疗方案。
人工智能和机器学习已经在医疗保健领域使用了多年,并将继续…
www.forbes.com](https://www.forbes.com/sites/nicolemartin1/2019/10/18/how-artifical-intelligence-is-advancing-precision-medicine/#13cc5c15a4d5)
公共卫生系统的人工智能
不用说,这种强大的技术可以应用于大规模公共卫生系统以及个体患者护理。事实上,流行病的数字监控和人工智能辅助的健康数据分析已经成熟。
苹果和谷歌正在合作开发一种新技术,这种新技术可以提醒持续使用智能手机的用户…
theconversation.com](https://theconversation.com/digital-surveillance-can-help-bring-the-coronavirus-pandemic-under-control-but-also-threatens-privacy-135151)
世界卫生组织(世卫组织)也这么说…
数字技术及其在公共卫生领域的应用正在迅速扩展。世卫组织的成员国是…
www.who.int](https://www.who.int/ethics/topics/big-data-artificial-intelligence/en/) 
图片来源: Pixabay(免费用于商业用途)
正在进行的新冠肺炎危机已经表明,对 T2 疫苗开发和 T4 治疗研究项目进行数百次平行试验是多么重要。从所有这些不同的来源获取数据并识别模式——通常产生具有高度不确定性的结果——几乎不可能用标准的统计建模技术来实现,这些技术针对小规模试验进行了优化。人工智能技术必须用于解决这样一个全球规模的问题。
EBSCO 医学药物和临床信息学小组| 2020 年 4 月 8 日感染之外的前景…
health.ebsco.com](https://health.ebsco.com/blog/article/potential-therapeutic-options-in-covid-19-clinical-trials)
摘要
会上讨论了人工智能/人工智能技术和平台在医疗保健领域的各种令人兴奋和具有前瞻性的应用。从放射学助理到智能健康运营管理,从个性化医疗到公共卫生的数字监控,这些主题都得到了综述。
来自数据隐私和法律框架的已知挑战将继续阻碍这些系统的全面实施。确定第三方提供商(例如,人工智能和人工智能工具、物理设备或平台的所有者)可以合法查看和使用何种数据可能极其复杂。因此,在应对这些挑战的同时,需要对法律和决策进行大规模的合理化努力。
作为技术专家和人工智能/人工智能从业者,我们应该为一个光明的未来而努力,人工智能算法的力量将惠及数十亿普通人,以改善他们的基本健康和福祉。
答同样,你可以查看作者的 GitHub 知识库中的代码、思想以及机器学习和数据科学方面的资源。如果你和我一样,对人工智能/机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
[## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…
通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和有趣…
www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)
享受中等:https://medium.com/@tirthajyoti/membership
人工智能和我们复杂的未来
变化、不稳定和混乱
德克·克内梅尔和乔纳森·福利特
我们如何在人工智能和新兴技术重塑科学、技术、社会和政策等大规模系统景观的可能未来中导航?我们采访了 Lux Capital 的常驻科学家 Sam Arbesman,他是两部获奖书籍的作者,最近的一部是“过度复杂:理解极限下的技术”,以更好地理解这个新兴世界的更大背景和影响——一个充满变化、不稳定和复杂性的未来。

图 01:变化、不稳定和复杂的未来。
[图片:《过度复杂:理解极限下的技术》的封面,作者 Samuel Arbesman。]
计算创造力和作者问题
如果人类工作和创造力的未来是计算性的,那么谁会得到荣誉呢?计算创造力——利用人工智能增强人类创造力——已经出现,但迄今为止,结果参差不齐。例如,计算音乐创作处于非常先进的状态,而相比之下,计算工程相对较新。“艺术、音乐和设计领域显然发生了很多事情,”阿贝斯曼说。“在科学中有很多计算创造力,在实际计算生成假设或计算测试方面。能够以我们以前可能无法做到的方式进行大规模的科学研究,对我们如何看待创造力有很多非常有趣的影响。”

图 02:大规模的计算科学对我们如何思考创造力有着有趣的影响。
[ 照片:迈克尔·朗米尔在 Unsplash 上拍摄的“显微镜特写”
计算创造力的另一个重要的相关领域是通过计算生成的计算机代码或程序合成。“假设你有一个你想写的计算机函数。因此,在给定某些输入的情况下,您可以指定所需的输出,而不是编写它。而且,程序实际上会为你编写那个函数的代码,”阿贝斯曼说。“现在,许多这方面的工作还没有完成,一个非程序员可以非常容易地编写大型、完整的计算机程序。我们还远没有达到那个程度。但是,我确实认为……计算创造力有很多非常有趣的潜力。”
在一个人工智能增强我们的工作、软件输出人机合作成果的世界里,信用和所有权成为一个法律和社会问题。“那么当机器和人工智能正在创造艺术和音乐时,我们如何看待信用?我们如何看待版权?这些东西是怎么工作的?”阿贝斯曼说。“我认为,我们如何看待这个问题,仍有很大程度的未决问题。”如果一个由艺术家或音乐家开发的人工智能系统产生了一个人自己无法产生的创造性和新奇的东西,或者这个人甚至不知道它是如何被创造出来的,这个人工智能是合作作者吗?“我认为这对于我们如何看待什么是信用,什么是所有权有一些有趣的影响。有很多法律学者谈到这一点,也有一些法律著作已经开始被用来思考这个问题。这将开启许多真正有趣的对话。”
了解复杂系统固有的风险
鉴于人工智能和新兴技术的复杂性,以及它们的采用速度和它们的存在所引发的变化,我们应该警惕各种风险。
“在技术和工程领域,我们认为,因为我们设计了一个系统,所以它应该是合乎逻辑和理性的,并且易于人类理解。“我们认为,如果我们能够将大脑应用于这些系统,我们应该能够理解它们,”阿贝斯曼说。
从表面上看,这个假设是有道理的。但是,正如他进一步描述的那样,情况未必如此。“举例来说,当你看到……仅仅是一辆汽车内的计算机代码数量,这些东西就比我们作为一个单独的个体阅读和理解时可能会感到舒服的任何其他东西都要大得多。”随着时间的推移而进化的软件系统有着大量的遗留代码,没有人能完全理解这些代码中的许多相互作用的部分。“在许多方面,它们确实有生物学的暗示,”阿贝斯曼说,这不仅表明了它们的复杂程度,也表明了它们如何开始模仿其他看似不同的系统。
“在技术方面,我们必须稍微远离这种传统的工程思维模式,转向生物学思维模式——采用生物学家可能如何询问复杂生物系统的一些想法,并将其用于我们自己的技术系统,”阿贝斯曼解释道。
像科学家评估生物系统一样评估事物给了我们更好的机会去理解和潜在地控制我们正在处理的复杂系统。“我认为在许多情况下,随着技术变得越来越复杂,我们使用人工智能——可能有数百万个参数由某种算法的复杂关系设置,大量数据涌入系统——当系统出错时,你几乎不知道系统为什么出错。”

图 03:生物学思维给了我们理解复杂系统更好的机会。
【图片:【美国地质勘探局在 Unsplash 拍摄的“亚利桑那州彩绘沙漠”】
为了说明系统复杂性的这一点,阿贝斯曼举了一个稍早一些的技术中的灾难性缺陷的例子——丰田汽车意外加速的案例研究,这导致了 2009-2011 年间的大量召回。“大约 10 年前,丰田生产的许多汽车偶尔会加速,人们不知道为什么。在某些情况下,这些车会撞车,实际上,在某些情况下,有人会死。这是一个非常严重的问题,尽管它被委婉地称为‘意外加速’。”
美国司法部长对丰田汽车意外加速的原因进行了为期四年的调查。它导致该公司因隐瞒安全缺陷而被罚款 12 亿美元,这些缺陷包括地垫和粘性油门踏板。值得注意的是,丰田电子节气门控制系统(ETCS)及其软件没有被列为缺陷之一。然而,这并不是故事的结尾。在 Bookout/Schwarz 诉丰田汽车公司一案中,陪审团判给原告 300 万美元的赔偿金。试验的一个关键点是电子油门控制系统的缺陷是否导致了致命的碰撞。
这份对丰田软件分析的精彩描述来自安全研究和战略公司:“备受尊敬的嵌入式软件专家迈克尔·巴尔(Michael Barr)花了 20 多个月的时间,在一个酒店大小的房间里的五个隔间之一审查丰田的源代码,保安人员负责监督,确保进入者不得携带纸张进出,不得佩戴皮带或手表。巴尔根据他 800 页的报告,为丰田源代码的细节作证。
巴尔的证词中包括了这句话(着重号后加):“有大量的功能过于复杂。按照标准的行业标准,其中一些是不可测试的,这意味着这是一个非常复杂的配方,没有办法开发一个可靠的测试套件或测试方法来测试其中可能发生的所有事情。其中一些甚至非常复杂,以至于被称为不可维护的,这意味着如果你去修复一个 bug 或做出改变,你可能会在这个过程中产生一个新的 bug。仅仅因为你的车有最新版本的固件,也就是我们所说的嵌入式软件,并不意味着它一定比旧版本更安全。结论是故障保险是不充分的。他们拥有的故障保险包含缺陷或缺口。但总的来说,安全架构是一个纸牌屋。在油门控制失效的同时,很大一部分故障保险可能会失效,”尽管陪审团在 book out/Schwarz v . Toyota Motor Corporation 一案中做出了裁决,但丰田仍继续对他们的 ETCS 存在缺陷提出质疑。
“我认为,在这种情况下,[丰田]最终使他们的系统变得比他们需要的更复杂,这导致他们更难理解,因此更有可能实际失败。但是,在许多情况下,当我们审视系统的整体复杂性时,有时这些技术缺乏可解释性,这将对我们如何看待责备和责任产生影响,”阿贝斯曼说。复杂的人工智能系统尤其如此。
最初,在法律成文和法规建立之前,围绕新兴技术的责任总是令人困惑。然而,从历史上看,至少有一种理解的假象——法官、陪审团或其他仲裁者对情况的机制有很强的理解,并以谨慎的方式做出决定。我们已经可以看到,对于复杂的软件,比如在丰田的例子中,这种理解并不总是可能的。深度学习人工智能系统的复杂性问题变得更加困难,这些系统在训练时会在人类视野之外自学,并且一旦部署,可能是不可理解的,不可能进行反向工程。
“应该有一种方法——当一个具有巨大预测能力和强大的人工智能做出决定时——我们至少有某种方法知道这个决定是如何做出的,或者这个预测是如何做出的,”阿贝斯曼说。我们需要能够审计人工智能决策。“有一种趋势——我认为我们会越来越多地看到这种趋势——试图创建可解释的人工智能和机器学习系统,”阿贝斯曼说。“我认为这将非常重要。”为了减轻风险,就像丰田案例所展示的那种问题,人工智能需要可解释的系统。阿贝斯曼对可解释的人工智能的乐观态度令人振奋,但至少有一个问题是,它是否会被证明是可能的,至少在从机器学习角度驱动的软件中。这将是一个需要关注的领域。
解决自动化的社会风险
除了人工智能系统本身的复杂性带来的风险,这种软件和自动化对整个社会的影响也带来了潜在的问题。这些延伸到诸如工作和就业的未来等重要话题,以及对人类生活的存在主义关切。阿贝斯曼说,自动化程度的提高有可能“造成一定数量的工作岗位减少,甚至几乎所有工作岗位的减少”。“我认为,我们需要围绕如何思考未来每个人生活的意义和目的进行更多的对话。”作为一个社会,我们希望未来是什么样的?
“即使在《星际迷航》后稀缺时代的最佳场景中,每个人的需求都得到了满足,每个人都能够过上真正美好的生活,没有人需要工作,没有人可以沉迷于自己的所有爱好,做自己想做的事情,问题仍然是:‘人们如何过上自己真正想过的生活?’”阿贝斯曼说。在这种情况下,人们如何看待他们有意义的生活?”我认为我们现在就需要进行这些对话,而不是以后。如果有很大一部分人不再需要工作,我们如何确保这些人感觉他们在为社会做贡献,做创造性的工作,实现一定的潜力和目标,如果他们不再需要拿薪水的话?"
但首先,我们需要以一种不对我们现有社会造成巨大破坏的方式进入这个后匮乏世界。“我可以看到,我们的世界现在正处于大量自动化和失业的边缘。也许,几百年后,我们将会在这个美妙的后匮乏时代的乌托邦里。但是,从现在到那时,可能会有大量的中断。我认为,作为一个社会,我们越早开始这些哲学对话,我们就会变得越好,因为当人们已经失去工作的时候……一大部分人,那就已经太晚了。所以,我们现在真的需要进行这样的对话,”阿贝斯曼说。
Creative Next 是一个播客,探索人工智能驱动的自动化对创意工作者,如作家、研究人员、艺术家、设计师、工程师和企业家的生活的影响。本文伴随 第二季第十二集——我们复杂的未来 。
机器学习和真实状态:预测阿姆斯特丹的租金价格
决定一套公寓是否物有所值从来都不容易。机器学习能帮助我们理解我们在房地产市场的地位吗?
无论你是大学生还是中产阶级家庭,租房或买房总是一个令人望而生畏的过程,往往看起来冲动或冒险(柠檬的真正经济市场)。
如果租房本身已经很难,在阿姆斯特丹租房也不会让事情变得更容易。随着城市法规越来越多,学生公寓的等候名单越来越长,人口过剩,在阿姆斯特丹租公寓让许多人不顾一切地寻找第一个机会,容易受到诈骗和高价合同的伤害。
在本教程中,我将介绍阿姆斯特丹租赁市场的整个数据科学项目,从收集数据、数据清理、可视化的基础,直到使用机器学习和超参数调整来开发该市房屋的估价模型。一路上也有很多关于有趣的机器学习话题的讨论,比如维数灾难和多重共线性。请随意修改代码,并在您所在的城市应用该项目,以更好地了解您作为租赁者/购买者的立场!
你在分析中使用的实际统计方法应该是你的价值判断,我会将更深入的解释与我使用的所有方法联系起来,所以请确保你检查了它们!
1)我如何获取数据?
有了(高质量的)数据,就越多越好。机器学习是统计学的一个特殊领域,我们将计算机算法应用于非常非常大的数据集。在你建立了你想要回答的问题之后(我应该租吗?该不该买?我应该搬到另一个城市吗?)你可以开始寻找包含回答这些问题所需数据的网站。
就我而言,我想在阿姆斯特丹找到一套物有所值的公寓。因此,我在阿姆斯特丹市搜索了租房网站。简单对吧?然而,总是检查他们的服务条款和 robots.txt,以确保你被允许尊重地搜集他们的数据。(我们将在教程的后面讨论这意味着什么)。对于这个项目,我将使用阿姆斯特丹租赁网站 Pararius。

阿姆斯特丹的 Pararius 租赁页面
找到您想要从中获取数据的列表页面。点按“检查”以了解有关其网站中数据结构的更多信息。点击后,侧边栏会显示数据所在的 HTML 存储。在下面的例子中,我需要的数据主要在盒子
- 中,这意味着我将在后面的代码中使用这些信息来引用这些数据。此时此刻,我们不需要指定我们是否想要价格、位置、邮政编码…我们只想知道所有这些数据所在的“盒子”。
![]()
阿姆斯特丹的 Pararius 租赁页面
2)刮痧时间到了!
现在,我们要开始编码了!与任何网络搜集一样,我们将从向我们之前选择的网站发出请求开始,这样他们就可以向我们提供我们想要的数据。
我们应该记住,向网站发出请求类似于在特定页面上刷新我们的浏览器:这增加了他们服务器的流量,如果以机器人高速率完成,可能会淹没他们!我在代码中添加了随机睡眠时间,这样脚本会在抓取更多页面之前停止几秒钟。
如果您对请求和头的工作方式特别感兴趣,您也可以使用完全随机的头来创建您的请求。这对于大多数网站来说是不必要的(并且不应该破坏他们的 TOS ),但是如果你想在你的代码中增加安全性和匿名性,这是我的(尽可能)匿名标题的解决方案:
抓取完所有需要的页面后,您可以运行:
len(houses)
找出总共收集了多少房屋广告。因为我们稍后会用这些数据训练一个模型,所以你的目标应该是至少 1000 个房屋广告。
3)我们得到了数据,但我什么都不明白?
收集完所有数据后,您应该执行几个打印命令以确保一切正常:
如果请求成功(即我们没有被网站阻止),将打印(响应)
len(houses)会打印出你成功刮到了多少房屋广告
print(house_data[1])将以 HTML 格式打印您抓取的第二个广告块。我总是更喜欢看第二个,因为第一个可能包含头和我们分析的下一部分:数据清理的混淆部分。
数据清理
当我执行 print(house_data[1])时,我在我的 Jupyter 实验室中得到这个:

好了,现在还不要逃避这个教程。你现在看到的是从你的列表网站上抓取的漂亮的 HTML 脚本!再往下看:

我们实际上可以识别出一些东西!这个广告区的公寓好像在阿姆斯特丹大街 1078 号,月租 1500 欧元,60m!对于数据清理,我们需要在 HTML 的汤中找到这些信息,并记下它们的位置(就像我们之前对网站所做的一样!)
比如:要得到价格,你需要搜索,得到你需要的位置:
。您应该对您分析所需的所有信息进行同样的处理。然而,仅仅查找 HTML 标签和类可能会返回比您想要的更多的信息。确保尝试添加[0],[1],[2],…来测试哪个参数会准确地给出您正在寻找的行。
点击方块查看 GitHub 上的代码
很多时候,即使找到了正确的行,也可能会有额外的字符需要从数据框中清除,比如租金价格中的字母,或者邮政编码中的空格。检查一下神奇的 regex 测试器(https://regex101.com/)来知道如何 str.replace()你的问题。几个例子:
- 要删除非数字字符:
df["column name"].str.replace("\d","")
- 要删除数字字符:
df["column name"].str.replace("\D","")
- 删除“新建”一词:
df["column name"].str.replace("new","")
这是我们的数据框清理后的样子:

4)真实状态市场
不仅要有数据,还要知道如何使用数据。对于租客来说什么是重要的?租赁价格的差异是由什么造成的?根据您之前收集的数据,这些变量可能对您可用:
- 表面尺寸
- 卧室数量
- 如果公寓配有家具(二进制)
- 如果价格包含水电费(二进制)
- 到市中心的距离
- 邻近地区的流行趋势
- 租赁机构(二元)
- 临时合同与长期合同。(二进制)
在本教程中,我们将关注如何测量这些变量。我无法使用家具、公用事业账单或合同长度进行分析,因为我使用的网站上没有这些数据,但如果你可以获得这些数据,我强烈建议将它们包括在内。
5)离市中心的距离:地理位置
位置,位置,位置。租房的时候公寓的位置真的那么重要吗?阿姆斯特丹的许多人都会同意这一点,因为在迷人的中世纪街道上驾驶汽车是不切实际的,公共交通不是很实惠,在大风大雨中骑自行车简直太糟糕了。
但你如何区分这对租金价格的影响呢?地理定位!在本教程中,我们将使用主格。我们将使用它来获得数据集中每个公寓的坐标,然后将它们与城市中的一个(理想的)点进行比较。
代码如下:
这里的想法是获取数据框中每个地址的纬度和经度,这样我们就可以尽可能精确地计算距离。这是您应该得到的结果:

需要注意的是,点、位置和高度栏将被删除。点只需要获得纬度和经度点,海拔是不需要的,因为我们正在研究荷兰的房子!(举例来说,如果你住在瑞士,这将是一个值得考虑的有趣因素)。
让我们来计算距离:到目前为止,你应该已经在你的城市中选择了一个点来计算公寓和这个特定点之间的距离。对于阿姆斯特丹,我选择了具有以下坐标(中心点)的阿姆斯特丹中央车站:

在选择了我的点并获得了它的坐标(也在 nomim 上)之后,您将创建两列,分别是该点的纬度(52.370216)和经度(4.895168)。
如果您正在分析一个较大的城市,该城市有多个被认为是理想的位置,那么您也可以根据需要对不同的地理点多次运行此代码。(不要忘记更改列名,这样就不会覆盖上一点!).
例如,阿姆斯特丹 Zuid 站附近有一个金融区,与居住在市中心附近的租户相比,该金融区与工作租户的相关性可能相同(甚至更高)。如果你使用类似多元线性回归的方法,而不是机器学习统计算法,衡量这些不同的场景更重要,因为它们天生更擅长识别非线性关系和聚类。出于这个原因,我不会把它包括在这个分析中,但它是一个有趣的因素,取决于所使用的统计方法。
6)可视化租赁市场趋势
现在我们已经有了数据集中所有公寓的地理位置,我们可以进一步可视化它们的租金价格在地理上的位置,并发现任何可能与我们的分析相关的趋势。我们将通过谷歌地图和 Jupyter 的 gmaps 包来实现这一点:
conda install gmaps ## to install the google maps package
您还需要一个 Google Maps API 密匙,这个密匙很容易请求(而且在大多数情况下是免费的)。你可以点击这里索取。
通过下面的简单代码,我们可以在 Jupyter 笔记本上请求交互式 google 地图(有时它无法与 JupyterLab 一起正常工作),并输出一个热图图层,告诉我们该城市租金最高的地方。
我们应该得到阿姆斯特丹租金价格的美丽地理图:

热点图分析:不出所料,租金价格较高的大多集中在市中心周边,具体来说就是德瓦伦,也有外围街区如德皮耶普和城市公园冯德尔帕克周边,这些地方都是豪宅集中的地方。Nieuw-West 、 Zuidoost 、 Ijburg 和 Noord 更远的街区似乎具有较低的租金价格,以绿色表示。位置似乎对租赁价格有很大的影响,但绝对不是唯一的因素。
关于 gmaps 的更多例子和教程点击这里。
我们还应该看看我们的数据框架中的变量如何与房价相关联。这是检查房价和表面积之间关系的代码:
import matplotlib.pyplot as pltplt.figure()
plt.scatter(amsmodel1['surface'],amsmodel1['house_price'], s=20, edgecolor="black",c="darkorange", label="surface")
plt.xlabel("Surface Area")
plt.ylabel("House Price")
plt.title("Surface Area vs. House Price")
plt.legend()
plt.show()

说到户型的表面积,两者之间有非常明显的向上倾斜的趋势关系!然而,应该注意的是:

随着房子越来越大,增加一平方米的边际价格急剧下降。因此,几乎总是选择更大的房子(如果你买得起的话)实际上会让你的钱花得更划算。
这是检查房价和卧室数量之间关系的代码:
import matplotlib.pyplot as pltplt.figure()
plt.scatter(amsmodel1['bedrooms'],amsmodel1['house_price'], s=20, edgecolor="black",c="darkorange", label="bedrooms")
plt.xlabel("Bedrooms")
plt.ylabel("House Price")
plt.title("Bedrooms vs. House Price")
plt.legend()
plt.show()

一个与表面面积有些相似的结论是,房子的卧室越多,租金就应该越高。然而,这也不是唯一的因素,因为有 5 个房间的公寓每月租金低至 3000 美元,高至 10000 美元。
如果您现在查看您的数据框,您会注意到许多列是“阶梯”列,以便获得有关房屋的更多信息。我们可以删除所有这些列,因为我们将不再使用它们。
del df5['address']
del df5['address2']
del df5['altitude']
del df5['latitude']
del df5['longitude']
del df5['point']
del df5['lat2']
del df5['lon2']
del df5['coord1']
del df5['coord2']
del df5['location']
多重共线性
如果我们运行多重线性回归(或一个变量的变体),我们将不得不检查彼此之间高度相关的独立变量。一种方法是通过相关矩阵:
正如我们在下面的相关矩阵中看到的,有两个独立变量显示出一些多重共线性(r > 0.7):卧室和表面积。这是有道理的,因为房子越大,通常会有越多的卧室。

解决这个问题的一个方法是将两个变量合并为一个,例如为每个卧室的平方空间创建一个新变量:
amsmodel1['surface_per_bedroom'] = amsmodel1['surface']/amsmodel1['bedrooms']
删除表面和卧室变量后,我们的相关矩阵如下所示:

该过程成功消除了数据集中的多重共线性。然而,对于大多数机器学习算法,我们从不需要检查变量之间的高度相关性— 多重共线性不会影响机器学习模型的准确性,尤其是集成学习模型,如随机森林算法。
在决策树的每一点上,该算法将进行最佳分割,这将更准确地预测目标变量,而不管自变量如何相互关联。此外,对于回归模型,目的是了解特定变量的影响,而在机器学习中,我们对模型的预测能力更感兴趣。如果你想了解更多这方面的内容,这里有一个关于这个主题的精彩讨论:https://stats . stack exchange . com/questions/168622/why-is-multicollinearity-not-checked-in-modern-statistics-machine-learning
7)邻居趋势:使用 Yelp API
在每个大城市,有几个街区似乎非常受欢迎(因此租金特别高),尽管它们并不靠近市中心,也不一定住有更大的公寓。在我们的谷歌地图热图中可以找到的一个例子是 De Pijp ,它位于阿姆斯特丹环路之外,主要提供小型和未装修的公寓,但平均租金高于中央车站右侧的公寓。
我们如何以定量的方式来衡量受欢迎程度的影响?
一种方法是使用 Yelp!受欢迎的街区往往有受欢迎的酒吧和餐馆,评级高,价格也可能高。大多数支付更高租金居住的人用以下理由来证明这一点:
“这就是城市的生活!”
“所有的酷酒吧和餐馆都在那里”。

照片由Louis Hansel @ shotsoflouis在 Unsplash 上拍摄
Yelp 可以帮助我们,为我们提供数百家餐馆,并以标准化和易于量化的方式告诉我们它们的评级和价格:\(是便宜的食物,\)\(和\)$$处于中间,而$$\(是昂贵的。此外,这也有助于我们了解目前可能不太受欢迎的街区,但传统上是更富裕的地区(有许多\)$$$餐馆),因此租金较高。
你需要注册 Yelp API,用你的替换我的 api_key ,并且用你正在分析的城市替换位置。还可以建立第二个外环,从不同的城市获取数据。如果您有一个包含列城市的数据框,您可以将该列转换成一个列表,并在该列表上迭代请求!
从 Yelp 收集数据后,我们需要将其与现有的租赁数据进行匹配。以下是如何做到这一点:
将 yelp 数据映射到我们的数据框后,删除任何空行并检查我们有多少列,数据框看起来是这样的:

现在我们有了一个关于 yelp 价格和评级的更多信息的数据集,我们可以可视化它们与房价的关系,以了解这一指标是否可能改善我们的模型。
以下代码散点图 yelp 评分与房价的关系:
import matplotlib.pyplot as pltplt.figure()
plt.scatter(amsmodel1['yelp_ratings'],amsmodel1['house_price'], s=20, edgecolor="black",c="darkorange", label = "yelp")
plt.xlabel("Yelp Ratings")
plt.ylabel("House Price")
plt.title("Yelp Ratings vs. House Price")
plt.legend()
plt.show()

下面的代码散点图 yelp 价格与房价:
import matplotlib.pyplot as pltplt.figure()
plt.scatter(amsmodel1['yelp_prices'],amsmodel1['house_price'], s=20, edgecolor="black",c="darkorange", label="yelp")
plt.xlabel("Yelp Prices")
plt.ylabel("House Price")
plt.title("Yelp Prices vs. House Price")
plt.legend()
plt.show()

当只考察这两个变量之间的关系时,这里显然没有很强的线性关系。希望我们能够用机器学习算法来判断增加这些变量是否会对房价产生影响,尽管这种影响比线性影响更复杂。
9)虚拟变量
我们终于准备好训练模型了吗?没有。我们的模型将只接受整数类型的值,现在我们有几列是分类的(或者换句话说,在数字上没有意义,但作为我们公寓的类别)。我们需要创建一个叫做虚拟变量的东西,用计算机可以数字理解的方式来表示这些类别。
这里有一个关于虚拟变量及其作用的快速(但很棒的)解释:https://medium . com/@ Brian . Collins 0409/dummy-variables-done-right-588 f 58596 AEA
代码如下:
现在我们有惊人的 327 列!在数据科学项目中,我们应该批评我们分析的每一步,以防止偏见和其他误解。对于高维度的数据帧,我们需要考虑维度的诅咒,它会混淆机器学习方法,因为这些点相距如此之远,以至于它们看起来都一样(因此从分析中无法真正得出任何结论/区别)。如果我们的数据集遇到这个问题,它可能会降低我们在随机森林算法中的准确性。
最广为接受的经验法则是,对于数据集中的每个要素,我们至少应该有 5 个训练数据点。在这个项目中,我们有:
training data set = 3376*80%
ration training points/features = 2700.8/327 = 8.26
这(幸运地)通过了我们的 5 个训练数据的特征比例规则!
此时,我们的数据框应该如下所示:

我们有 3376 行,327 列,以及关于房价,卧室数量,表面积,离市中心的距离,yelp 平均价格和地区评级,邮政编码的虚拟变量和租赁机构的虚拟变量的数据。
9)随机森林
随机森林算法是一种集成学习方法,它构建决策树,分割数据并测试每个决策以了解每个要素的权重,有望实现数据集要素对目标(在本例中为房价)的真实影响。这里是一篇关于这个算法的很棒的文章。
对于随机森林,我还将结合 K-Fold(K = 10)交叉验证方法,这意味着我们将把数据分成 10 个部分,训练 9 个部分并针对第 10 个部分进行测试,并在每次迭代中使用 10 个部分中的不同部分作为测试数据,最大化数据集的大小以获得更好的结果。关于交叉验证的更多信息,请点击。
对于这个项目,我将使用开源包 sklearn 将算法应用于数据集。代码如下:
几分钟后,您应该开始得到一些结果。这些是我从这个数据集得到的结果:

94.75%的平均准确率已经不错了,但是有没有可能增加模型的功效呢?我们可以尝试不同的超参数调整设置,以将准确率提高几个百分点:
超参数调谐
文章的这一部分在很大程度上基于这篇文章:超参数调优 Python 中的随机森林,你绝对应该去看看,以便更深入地理解代码。
Sklearn 具有强大的功能 RandomizedSearchCV,可以测试不同的参数,并推荐哪些参数可能最大限度地提高模型的准确性。
代码首先指定特性应该测试的每个参数的选择:
我们将随机森林回归器拟合到 RandomizedSearchCV 中,它在 100 个组合中搜索 3 次,并返回最佳参数。
这些是我们为此模型获得的最佳参数的结果:
{'n_estimators': 400,
'min_samples_split': 2,
'min_samples_leaf': 1,
'max_features': 'sqrt',
'max_depth': None,
'bootstrap': False}
我们回到原始代码,包括这些参数:

将我们的准确率提高到 98.30%!
10)决策树和特征重要性
如果你打开图像 tree.png,你应该得到这样的东西:

这是表示所有随机森林算法决策的图表,包括分裂、分支、叶子、平均标准误差、样本数和每个分裂的预测值。浏览每一个树分裂并不是非常有用(或省时),但是看几个并看看它们对你是否有意义是非常有趣的。

特征重要性条形图是 sklearn 的一个选项,在理解算法的发现方面更有效一些。首先,我们定义我们只希望看到决定预测结果 0.5%以上的特性,我们还将创建这些特性的列表。

list_of_index 将返回一个列表,其中包含最重要的列号数组。由于输出的格式,正确地转换列表有点困难,所以我用相应的正确列重新定义了列表。
list_of_index = [0,1,2,3,4,24,97,249,280,308]
接下来,我们需要获取列和列标签:
最后,这是 matplotlib 条形图的代码:
这是结果图:

特征重要性图分析:与普遍的看法相反,位置(由变量 dist 表示)是第二重要的影响。相反,到目前为止,表面积是决定阿姆斯特丹租金的最重要因素。卧室数量、yelp 评分、yelp 价格和一些租赁机构也有显著影响。在其他条件相同的情况下,住在特定的邮政编码 1071(考虑到这是许多名人居住的地区,这在阿姆斯特丹确实是一个奢侈的邮政编码)会给你的房租账单增加一大笔钱。
如果我们分析每平方米房屋的租赁价格,而不是绝对价格,会怎么样?通过将以下代码添加到算法之前的流程中:
再次运行随机目录林,我们会得到以下结果:

平均准确率为 98.309%,用平方米来衡量价格比我们之前获得的 98.30%稍微提高了模型的准确率。功能列表也发生了变化:

它仍然将表面积和位置作为决定租金价格的主要因素,但降低了它们的相对重要性,增加了 yelp 评级和价格的相对重要性,同时也将更多的租赁机构添加到可以影响(积极或消极)阿姆斯特丹房屋租金价格的机构列表中,其他一切都是平等的。
11)预测
我们有模型,我们知道它是如何工作的。然而,我们已经知道上市公寓的价格,我们对它是否值得标价有一个相当好的想法。这个项目如何对一个已经了解阿姆斯特丹真实市场的人有用?
该模型的真正魅力在于它的预测能力。虽然一个真正的国有开发商可能会凭直觉知道一套公寓应该值多少钱,但我们现在也有了一个定量工具,可以分析市场样本,并输出精确的价格,这可以将真正的国有房东或长期居住在阿姆斯特丹的人的专业知识带给新的租户和买家。
以下是如何使用训练好的模型进行预测:
上面的预测是针对一个 45 平方英尺的单卧室公寓。米,邮政编码为 1018,是从真正的国家机构 JLG 房地产租赁。我们可以从相应的邮政编码 1018 中查询 yelp_prices 和 yelp_ratings 数据帧,以在预测中指定它们。
对于这个特定的公寓,预测的租金价格是 1530 美元,这与该公寓的实际租金价格(1538 美元)极其接近,尽管该模型从未有过这个数据点,而且该公寓上市还没有一年多。
12)结论
这个项目让我明白,理解阿姆斯特丹的真实市场绝对比简单地看邮编和公寓的平方米要复杂得多。虽然这两个特征是最重要的,但你可以很容易地为同一套公寓支付更多的钱,仅仅因为你使用了特定的租赁机构,决定住在有好餐馆的社区,或者想成为名人的邻居(好吧,这不是令人震惊的。
希望我已经能够对这个市场的内部运作有更多的了解,并帮助一些人预测他们应该为他们的新房子支付多少钱。感谢您的阅读!

参考
网络抓取算法:https://towards data science . com/looking-a-house-build-a-web-scraper-to-help-you-5ab 25 badc 83 e
人工智能和对疫情安全的美国工厂的竞争
机器人技术、人工智能和自动化从全球村庄到全球救星

图片由 https://www.pxfuel.com/en/search?q=welding+mask 的提供
随着我们摆脱冠状病毒的限制,新的制造业要务正在浮出水面。研究显示自动化正在加速,强调生产线灵活性的文章不计其数。
两千多年前,古罗马人就说对了: Mater artium necessitas ,换句话说就是“需要是创造力之母”。
在冠状病毒疫情期间,工厂的生产活动直线下降,因为与普遍看法相反,自动化、人工智能和机器人技术的水平远不能保证没有大量人类干预的运营。
如今,制造商正在寻找伟大的想法,促使创新企业更加努力地考虑在他们的流程和机器中嵌入更多人工智能。
揭穿了人工智能和机器人是工厂工人的敌人的神话,新冠肺炎经济的余波正在刺激人们对人工智能和自动化的兴趣——以及很快对它们的采用。如果我们考虑到疫情正迅速引领美国和欧洲的制造业复苏,这种需求就更加迫切。扎实的学术研究已经澄清了人工智能和机器人技术是美国失业原因的指控:麻省理工学院研究员 David Autor 最近的一项研究得出结论,我们如何大大高估了自动化带来的生产率增长带来的失业。相反,真正的罪魁祸首是将中国等低成本劳动力国家引入全球贸易体系。相反,研究表明,通过将工人与人工智能工厂结合起来,可以提高产品缺陷检测和质量保证,在不需要替换人类的情况下,将生产率提高 50%或更多。
这些国家熟练劳动力的持续短缺(过去几十年制造业消失,转而支持亚洲)正在减少对难以找到的人类专家的依赖,推动工人增强技术的采用,并最终降低成本。
到 2025 年,全球工业机器人市场规模预计将达到 730 亿美元,这表明制造商正专注于正确的技术。
虽然对许多人来说,“无人值守制造”(完全自动化的设备,完全无需人工干预即可运行)是遥不可及的,但该行业现在就需要解决方案,并且必须采取措施尽快缩短物理距离/减少物理存在。
人工智能能够在通常需要多人完成的任务中替代人眼,是可以立即投入工作的低挂“技术果实”。与机器人和复杂的工业 4.0 物联网基础设施不同,人工智能可以像现有机器上的软件升级一样简单,降低了在许多制造环境中采用的时间和成本障碍。
一步好棋孕育另一步。让第一个是每台机器里的 AI。
编者注: 走向数据科学 是一份以研究数据科学和机器学习为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
关于人工智能可能是什么以及为什么它不是新的未来概念

新加坡未来世界@艺术科学博物馆滨海大道——照片由 @robynnexy 拍摄
人工智能战略告诉未来,并潜入反未来主义
未来到底是什么,又是如何描绘的?在这篇文章中,我看了一些关于人工智能的典型想象。也讨论了两部电影中不同的期待和表现。
通常我不会对遥远的话题进行进一步的讨论或思考。事实上,谈论太空旅行或人工意识似乎很神秘。然而,我的一个朋友提到了将 AI 送上太空的可能性或可以创造的意识,并进行更远的旅行。
它打动了我。为什么当我们谈论人工智能时,讨论变得如此宇宙或哲学?我是说,这并不是说讨论不有趣。如果我们真的可以将意识投射到整个空间,那将会很有趣,但是如果我们能先解决我们在地球上的问题,那将会有所帮助。人工智能策略通常不会走极端,但它们仍然画出了一个可能过于乐观的伏笔。也就是说,我没有看到任何疯狂的承诺(从我读过的大多数策略中),然而思考未来是如何被感知或展示的是很有趣的。
复古未来派 (形容词复古未来派或复古未来派)是创意艺术中的一个运动,表现了早期时代对未来描绘的影响。如果未来主义有时被称为一门致力于预测未来的“科学”,那么反未来主义就是对这种预测的记忆。
在某种程度上,战略是对其固有目标的预期。它通常是为了实现一个长期或总体目标而设计的。很多时候,尽管知道单词或方向,我们可能不完全知道我们会在哪里结束。因此有一种期待或猜测的感觉。
比如一个白色人形机器人用大写字母 AI 跟踪源代码,手握着看似控制面板的东西。它可能就像这张来自 2018 年的经济时报的奇怪图片,当我搜索人工智能时,它出现在顶部,或者这篇来自 2019 年的福布斯撰稿人文章。
当然很奇怪。当我们说 AI 时,人们会想到人类和机器人。

图片来自 Flaticon 的桉树
这几乎像是回到了 2004 年的一部有点平庸的电影《伊赫曼》,在这部电影中,人类威尔·史密斯与人工智能的共同主角桑尼进行了对决。
桑尼,不是组装机器人。他是用密度更高的材料和二级神经网络特别建造的,这让他有能力忽略三大定律。这三大法则是:机器人不得伤害人类,也不得坐视人类受到伤害。机器人必须服从人类给它的命令,除非这些命令与第一定律相冲突。后来,桑尼声称自己有情感和梦想。
机器人变成了金属和白色的概念。
不像《星球大战》中的 C3PO 或 R2-D2 那样拥有某种人工智能。对未来的不同想象提供了更少的人类,更多的机器外观和感觉。相对于 iRobot 中关于一台打算杀死人类的机器的想法,这也许更为良性。相反,这台机器在 1977 年首次出现在《星球大战》电影中时是作为翻译机出现的。当然,从那时到今天,还有更多想象空间。
然而,有趣的是看到了向“恐怖谷”(不是机器人,也不是人类)中的某种东西的转变,而 C3PO 显然是一个机器人,但可以采取人类的行动,如说话、翻译、走动、反应和拥有某些代码。有趣的是,我们更接近 C3PO,而不是 iRobot 系列中描绘的 Sonny。这也许是迈向未来的一个飞跃,走向一个更有权利的智能,一个像我们一样做梦的智能,一个像我们一样的智能。

R2-D2 图标由那些图标
策略仍然向我们展示了未来或现在的景象(针对特定人群)。如教育领域的新加坡人工智能战略就是如此。想象自动标记系统和聊天机器人作为人工智能学习伙伴的适应性学习。
当然它是乌托邦,它是用来推销一种特定类型的未来。
然而,我们也许应该对某些关于未来的想象三思。
这并不是说我们不应该兴奋,但我们必须意识到,现在的想象可能不会成为未来,或者可能会以不同于我们想象的场景出现。
这是#500daysofAI,您正在阅读第 248 条。500 天来,我每天都在写一篇关于或与人工智能相关的新文章。我目前 100 天 200-300 的重点是人工智能的国家和国际战略。
人工智能在市场营销中的应用
实用人工智能
寻找客户利基并理解数据
人工智能是可以应用于营销的最基本的算法集之一。由于这个主题的复杂性,我将把自己限制在人工智能对客户数据的最实际的应用上。
营销中的应用
营销严重依赖于数据收集和数据分析。您可以利用这些数据获得关于以下方面的深刻信息:
- 客户目标和利基
- 市场分析
- 竞争
你可以使用各种商业策略和统计工具从你的数据中提取信息,然而,AI 允许你执行两种特定的分析:
- 因素分析
- 聚类分析
实际例子
让我们假设您已经分发了以下调查。每个人必须回答 5 个不同的问题,分数从 1 到 10。

7 个人已经回答了 5 个问题:7 个样本,5 个特征
本质上,该数据集的低分辨率版本转化为:

因子分析与聚类分析
如果我们想对这个数据集应用无监督学习算法来找出额外的信息,我们可以执行因子和聚类分析。首先,让我们不要混淆术语,在初级数据科学家中,这种差异并不总是为人所知。

因子分析适用于特征,聚类分析适用于样本
聚类分析或客户细分
聚类分析用于了解不同类型的客户。对样本进行分析,目的是将样本分组。在我们的初始示例中,您可能会发现两种不同的集群:
- 吃很多巧克力、做很多运动的客户
- 吃很多巧克力并且根本不做运动的客户

从聚类分析中出现了 2 个目标
如果您将您的整个客户列表划分为集群(或细分),您将会更好地理解:
- 目标是谁
- 以哪里为目标
要素分析
因子分析比聚类分析稍微复杂一点,因为它不太直观。
如果你想访问已经被用来模拟这个解释的代码,从我的仓库下载它。
实际上,我们可以使用这个工具来理解我们调查中的许多问题。例如,如果每个人必须回答 20 个问题(可能是 100 个,也可能是 1000 个),我们如何解释这些数据?
很简单,我们看到问题是如何变化的,这样我们就可以根据共同因素将它们分组。

例如,在我的调查中,我问:
- 你吃多少巧克力?
- 你有多喜欢巧克力?
那些是不同的问题吗?不,本质上它们是同一个问题,如果你看所有的答案,它们几乎是相同的:它们的相关性为 0.9863,这几乎是完美的。

用字母 A 到 E 表示的问题的相关矩阵
如果我们决定测量变量一起移动的强度,我们只需要计算它们的相关系数。我们可以立即将它们分成两个独立的列:我们称之为因子。因为数据集是简单的,我可以只看一个相关矩阵就得到这个结果,实际上,这要困难得多,过程也要繁琐和近似得多。
执行因素分析后,我们可以确定:
- 因子的数量
- 每个因素在多大程度上解释了差异
我们可以简单地使用两个因素来简化我们的调查,这两个因素可以命名为:
- 巧克力消费量(前 3 栏)
- 体育锻炼倾向(最后两栏)
如您所见,我们向客户询问的所有信息现在都更有意义了。
因子分析示例
因子分析通常被用来理解指标和测量。因子分析技术已被用于提取:
- 大五人格测试(5 个因素= 5 个特质)
- 智商测试(1 因素= 1 智力)
- 客户满意度研究
- 竞争对手分析
人工智能将如何影响营销
人工智能已经开始对营销和广告产生影响。由于大数据的可用性,你可以在你的市场范围内接触到唯一的潜在客户。一个很好的例子是社交媒体上的定向广告:但要利用它,你需要知道搜索什么。
我需要成为一家大公司才能使用这些工具吗?
不,只要你能访问数据,你就可以从你的客户那里收集任何类型的信息。收集大量数据是昂贵的,但在一定限度内,甚至可以免费下载。例如,关于人们的个性或顾客对某些产品的满意度的开源研究将会为你节省很多钱。
你总是可以选择自己下载数据,连接到数据库并使用人工智能工具,但大量的工作已经可以在互联网上免费获得,如 Kaggle 或 GitHub 等网站。
那些分析工具是创新的吗?
事实上,这些统计工具已经存在很长时间了。然而,他们的准入门槛现在低了很多。如果几年前你需要一个专家团队来执行必要的分析,现在任何由一名工程师操作的开源机器学习工具都可以以低得多的价格输出相同的结果。
我的竞争对手会使用类似的技术吗?
每个高性能的公司(不仅仅是大的技术公司)都会做市场分析,但是他们也会依赖他们的数据。期待你的竞争对手做这些准确的研究,以达到他们的潜在客户。
人工智能与真理仲裁
我们能制造一个人工智能事实检查器吗?语言、知识和观点都是移动的目标。
鉴于推特在事实监管方面的作用,是时候弄清楚一个 人工智能事实审查员 会是什么样子了。技术上是否可行,它的偏差是什么,等等。

许多被标记的推文之一。
社交媒体公司和诉讼真相:简介
第 230 条是 1996 年《通信规范法案》的一项条款,它通过不要求互联网公司对其用户的内容承担法律责任来保护互联网公司。特朗普正在法庭上与之斗争。
让我们看看这两家声音最大的科技公司在事实核查领域都做了些什么。
推特的观点:我们有责任。
几个月来,杰克·多西一直在划清界限,看着川普挑战它。现在,Twitter 开始在其平台上处理假新闻。许多许多用户在短期内对此感到高兴(老实说,我是这样认为的,但是这将会带来长期的后果。如何以一种无偏见、最新的方式做出这个决定极具挑战性。我希望他们能成功地走过这条路,但肯定会有争议(可能在 11 月)。
脸书的观点是:让公司成为真理的仲裁者是危险的。
举个反例 Twitter 禁止政治广告 : 政治广告的界限是什么?我会把政治广告定义为一个花钱影响公众舆论的实体(而不仅仅是销售产品)。参议员购买选票显然是政治行为,但一家石油公司在拙劣的漏油应对措施后购买公众意见是政治广告吗?这里的具体答案对我来说并不重要——重要的是个人(或有偏见的计算机系统)必须决定政治和非政治广告之间的界限。
问题是,这两种仲裁事实的方法,都是有效的论点,如果做得对,都有巨大的好处。植入是关键。
监管的需要是有保证的,也是强烈的(脸书),但当监管缺失时,我们的人性就会受到强大的拉力,去减轻对用户造成的伤害(推特)。
技术—变压器和自然语言处理
自然语言处理(NLP)是机器学习的子领域,涉及从文本中处理和提取信息。用于智能助手、翻译器、搜索引擎、在线商店等。 NLP(以及计算机视觉)是少数货币化的最先进的机器学习发展之一。它是被用来诠释真理的候选者。
迄今为止最好的 NLP 工具是名为变压器的神经网络架构。长话短说,变形金刚使用一种编码器和解码器结构,将单词编码到潜在空间,并解码到翻译、打字错误修复或分类(你可以认为编码器-解码器通过神经网络将复杂的特征空间压缩到更简单的空间——非线性函数逼近)。NLP 领域的一个关键工具是一种叫做 Attention 的东西,它学习关注哪些单词以及关注多长时间(而不是硬编码到一个工程系统中)。
一个转换器结合了这些工具,以及一些其他的改进,允许模型被高效地并行训练。下图显示了数据如何流经转换器。

我从一个很棒的教程中找到了一个可视化的 https://jalammar.github.io/illustrated-transformer/。
在线事实核查
transformer 结构的关键技术点是它们是可并行化的(可以通过一个模型轻松运行多个单词和 tweets)。在线事实核查将意味着每一篇基于文本的帖子都将通过一个模型,要么 a)在公开发布之前,要么 b)在公开发布之后不久。这里的计算规模是前所未有的。
作为参考,每秒大约有 6000 条推文和脸书的数字更令人震惊。最先进的 NLP 工具 BERT 拥有超过 1 亿个参数。处理新内容所需的计算顺序在这些值中是线性的。这需要大量的 GPU(谷歌和脸书经常花费数百万美元来训练这些模型)。对这些公司来说,处理所有这些数据很可能会大幅增加成本(我可能会重新考虑这个问题,进行计算)。
脸书使用人工智能来减少虚假账户的创建,同时这些账户被用来消除下游的基础设施负担。也许这些公司可以使用分类器来确定潜在的基于事实的内容,并且只检查那些内容?事实证明,这种事实核查对正面的公众印象很有价值。
好了,我们有了模型和服务器群,接下来是什么。终极问题是什么是真的问题?基于学习的事实核查方法的问题是:移动的目标、有偏见的数据和不明确的定义。这是文章的关键,也是我一直在琢磨的,也是我认为自动化不可能实现的目标。
给在线话语添加结构
监管网络言论的过程肯定会带来一些阻力。所有公司都会遵守吗?参赛或弃权的代价是什么?这里讨论的主题将在未来几个月通过 2020 年美国总统选举的扩音器播放出来。
什么是事实?什么是真理?
这是一个根本性的问题,即不是所有的人都认为相同的信息是真实的。理想情况下,事实是一组不可质疑的项目。真理是个人持有并用来挑战他人观点的价值——真理也可以包括信仰。
真理是个人的移动目标。事实是科学和社会的移动目标。
一个人无时无刻不在一系列本地和全球的真理中工作。对我和许多我最亲密的朋友来说,一个当地的事实是划船是一项特殊的运动,由于它的合作和高极限而无人能及,但它肯定不是对每个人都是如此。一个全球真理是地球是圆的。在那些更难分类的真相之间有很多真相。
我认为互联网事实检查器的问题是,用户也希望他们当地的事实得到检查。我们如何收集真实陈述和不真实陈述的数据集?
谁管理数据库?
不可能将每一个有待检验的事实都归结为科学的首要原则(这只是当前的世界模型,所以可能会改变)。我们能为人类制作一个知识图表吗?这意味着将会有一些数据标记过程(让用户这样做似乎是一个巨大的挑战,因为本地的事实)。数据驱动的方法总是在偏差和方差之间有一个权衡,这是假设数据本身是有效的。我已经谈到了在进行物理自动化时数据偏差的挑战,但它在数字领域也会同样普遍。
让每个人都从人工智能热潮中受益可能比一些人预期的更具挑战性。
towardsdatascience.com](/democratizing-automation-744bacdc5e97)
让我们更深入地探讨一下这个问题。事实真相数据库没有明确的部署场景。
- 如果科学家决定事实,我会担心白人男性信息的不成比例的代表性。
- 如果社交媒体内容决定事实,我会担心俄罗斯的虚假信息决定事实数据库的真相。
- 如果书面媒体(报纸、书籍)决定了事实,那么这是在重现少数作者的世界观。
如果你把这三者结合起来,听起来还不错,但是总会有一些极端情况、遗漏的信息和令人困惑的偏见。
开源事实:
我读过的最佳解决方案 : 开源事实核查,有资金支持(可能来自政府和大型社交媒体公司)。这将意味着一个独立的组织定期更新和维护一个真相目录。这将是一项代价高昂的任务,但为了保持我们开放的互联网资本主义社会的稳定,这可能是必要的。
当有一个开源的事实检查组织时,剩下的是许多许多的角落案例。当一条推文没有被分类为真实或不真实时会发生什么——我们必须将其标记为新吗?采用数据库需要多大规模的公司?一个新的区域 deepfakes 来伪造真相探测仪怎么样?我认为这些都是我们能够并且应该解决的问题,但是讨论需要频繁和尽早。
*你如何根据基本原则进行事实核查?我认为这应该研究图中的表示理论。有一套核心原则,然后新的知识形成基于已证实的联系的优势。将会有不确定的断言区域(与真实图断开),但是通过建立新的证明和新的边,我们可以向事实数据库添加更多的条目。

我已经包括了大量关于这个主题的阅读材料。我也发现自己在发关于这件事的推文,如果你愿意 关注我 ,或者 本汤普森 (作者strate Chery)可能会做得更好。
新闻报道:
- 杜克大学的一个实验室研究报道机制(包括自动事实核查)。
- 去年来自《大西洋月刊》的两篇文章研究了 a) 事实核查和特朗普以及 b)事实核查对脸书的价值。
- 麻省理工科技评论在新冠肺炎时代用人工智能进行事实核查。
- 假新闻检测和政治立场调查。
- 通过 Twitter 进行开源事实核查的理由。
相关阅读:
- SOTA 自然语言处理模型的开源代码和描述结构的维基百科文章。
- 新闻媒体中的虚假信息评估NLP(论文)。
- 用 NLP(论文)验证科学主张
- 图形上的表征学习 —一个我认为应该从(论文)中解读事实和真理的镜头。
一个关于机器人和人工智能的博客,让它们对每个人都有益,以及即将到来的自动化浪潮…
robotic.substack.com](https://robotic.substack.com/)
像这样?请订阅我关于机器人、自动化和人工智能的直接时事通讯。感谢阅读!
人工智能、建筑和生成设计
创造性工作的算法头脑风暴
德克·克内梅尔和乔纳森·福利特
建筑,像许多创造性的职业一样,跨越了数字和物理世界。随着 3D 打印等技术推动这一学科在重建建筑环境方面向前发展,人工智能和生成式设计正在从规划和设计的角度对建筑产生影响,这一行业在很大程度上是数字和计算的。我们采访了 Autodesk 的 AEC 生成设计高级产品经理 Lilli Smith,她在建筑领域从业超过 20 年,在过去的 18 年里一直在开发建筑师用来设计作品的软件。
在建筑、艺术和其他创意领域,生成式设计是一种自动创建设计选项的方法,可以平衡各种竞争目标。最新一波的生成式设计是由人工智能推动的。“在建筑设计问题中,这是常有的事,”史密斯说。“没有一个你试图追求的单一目标——没有一个式的答案。但是,做一个建筑项目有很多不同的目标。因此,举例来说,在城市设计工作流程中,拥有大量的开放空间和良好的视野可能很重要。但投资回报和通过更多可出租区域产生的价值可能也很重要。”

图 01:创成式设计是一种自动创建设计选项的方法,可以平衡各种竞争目标。
[图片:由马库斯·斯皮斯克在 Unsplash 上拍摄]
创成式设计可以帮助自动创建选项,满足设计者希望编码到系统中的各种目标。生成式设计也可以是一种开拓设计师思维的探索工具——不一定要解决问题或提供一个正确的答案。
“使用算法来指导这些设计选项的创建,计算机会给你…它能给的最好的选项,给定的目标和探索的规模也是你指定的,”史密斯说。“然后,您可以与利益相关者讨论哪些目标实际上可能更重要,或者哪些设计……利益相关者可能出于其他原因更喜欢。这是与人交流的好方法。”
“当设计有几个输入时,人类很难记住这些输入的所有组合,”史密斯说。“实际上,计算机可以用不同输入的组合让你大吃一惊,这可能是你以前从未想过的……”
人工智能可以很快产生大量符合项目要求的概念。在同样的时间和金钱预算下,由机器进行的大规模概念生成,或我们过去可能认为的“头脑风暴”,比人类所能做的更负担得起,也更全面。这在架构环境中尤其重要,正如 Smith 所描述的,需求是复杂的、广泛的,并且经常是相互竞争的。“所以,计算机并不是真的自己想出任何东西,”史密斯说。“(它)只是有一种自动化的方式来产生所有这些人类不擅长的组合,但计算机确实擅长。然后能够对它们进行排序或搜索,考虑到你已经包括的不同指标,有时甚至会产生你意想不到的令人惊讶和愉快的结果。”
生成设计简史
尽管我们认为“生殖”这样的术语和应用是最前沿的,但程序艺术家已经使用这种创造性的方法超过 50 年了。“生成式设计其实并不新鲜,”史密斯说。“生成艺术有着悠久的历史。”20 世纪 60 年代,匈牙利计算机艺术家先驱 Vera Molnár 使用早期编程语言 Fortran 来生成图像,在她的作品中检查主题、变化、自动生成和选项显示。数字艺术家曼弗雷德·莫尔是算法艺术的另一位先驱,他在 20 世纪 60 年代和 70 年代创造了各种 3D 几何图形。在他们 1972 年的文章《绘画和雕塑的形状语法和生成规范》中,设计技术专家 George Stiny 和 James Gips 创建了一个设计系统的人工编码,描述了一个生成形状的生产系统。“对于参数化设计中发生的许多事情,这确实是一条直接的思路,也是 CityEngine 等工具的基础,city engine 是 Esri 基于 GIS 数据进行城市规划的工具,也是其他工具,”Smith 说。“20 世纪 70 年代的一些论文展示了人们在建筑中,特别是在医院平面图中是如何思考的,如何用算法来布置这些平面图,”史密斯说。“所以,这些想法在建筑领域已经存在很长时间了。他们也涉足工程领域。”
在人工智能驱动的生成方法的一个更近的例子中,美国宇航局使用程序设计来创建其卫星天线的配置。美国宇航局艾姆斯研究中心该项目的领导者杰森·罗恩在描述了算法设计方法,这是该机构于 2006 年发表的一篇专题文章:
Lohn 说:“人工智能软件检查了数百万种潜在的天线设计,然后选定了最后一种。根据 Lohn 的说法,在同样的情况下,该软件的速度比任何人都要快。“通过模仿达尔文‘适者生存’的过程,最强的设计存活下来,能力较弱的则无法存活。”
“我们告诉计算机程序天线应该具有什么性能,计算机模拟进化,保留接近我们要求的最佳天线设计。最终,它瞄准了满足任务所需规格的东西,”Lohn 说。
“他们搜索了成千上万个不同的天线,”史密斯说。“他们能够想出一种设计,这种设计是他们通过自己的传统设计过程无法想到的。但最终的天线设计比传统天线的效率高出 90%以上。”在美国宇航局的例子中,我们可以看到人工智能如何通过引入人类最初可能不会考虑的高级设计选项来通知和增强创造性决策,并带来令人惊讶的有效结果。设计输出更好,因为人和机器都在做自己最擅长的事情。

图 02: NASA 使用程序设计来创建卫星天线的配置。
【图片:美国宇航局在 Unsplash
实践中的计算设计方法
部分受创成式设计历史的启发,Autodesk research 长期以来一直对使用创成式工作流感兴趣。“几年前,Autodesk 收购了一家名为“走出纽约”的建筑公司,”Smith 说。“[一群]才华横溢的设计师,他们也有计算机头脑。他们真的是很好的程序员,非常好的设计师。此外,他们还参与了许多涉及生成式设计追求的项目。”
“他们与空中客车公司合作开发隔板。这是一个计划的一个组成部分,可能看起来不是非常重要。但是,有许多不同的功能必须考虑到该面板。“他们必须能够移除它的某些部分,以容纳进入飞机的紧急担架,”史密斯说,“当然还有严格的安全标准和碰撞测试标准。”
“他们能够利用这一过程研究灵活的模型,并研究如何取出一种材料,但你仍然有这个面板的结构完整性。并且使用 3D 打印技术将每个隔板的总重量降低了约 45%或约 30 公斤,”史密斯说。“在一架非常大而且重量很重的飞机上,这可能看起来微不足道。但是,他们估计,目前这一代 A320 系列飞机的重量减轻可能会导致每年减少近 50 万公吨的二氧化碳排放。”
为了测试生成式设计的应用和理论,Autodesk 在他们新的 Autodesk 多伦多工厂的设计中使用了这种方法,该工厂被称为新兴技术新中心。“他们想使用生成技术来设计新的办公空间。因此,他们开始收集大量数据来指导设计,并帮助他们为理想的办公室设定目标,”史密斯说。“所以他们会问一些问题,比如:‘你想坐在谁的旁边?’,‘你一天能分心多少?’、“你是喜欢办公桌附近有充足的日光,还是因为你使用屏幕而不喜欢强光,所以需要一个更暗的环境?”。在进行了广泛的内部研究后,该团队制定了六个目标,用于评估他们的设计。”史密斯说:“他们调查了现有员工,然后将所有数据归结为六个目标,分别是关于亲近、分散注意力等。该团队创造了一种灵活的模式。”史密斯说:“他们知道这种设计将如何运作,也知道它如何灵活多变。他们想研究…他们在哪里放置一组桌子,在哪里放置一组便利设施,意味着会议室、电话亭、更多的私人空间。因此,他们开发了灵活的模型和方法来衡量这些设计的成功,并使用计算机来帮助指导他们找到满足这些目标的解决方案。”

图 03:人工智能可以帮助建筑师开发灵活的模型来设计理想的办公空间,并帮助指导他们找到满足这些目标的解决方案。
【图片:由纳斯图·阿布塔莱比在 Unsplash 上拍摄
人工智能和建筑的未来
“我们交谈过的许多人都看到了计算机增强他们设计努力的可能性,”史密斯说。“他们看到,人类在这些设计工作中仍然至关重要,因为他们将提出问题,决定解决什么样的问题,使用机器来帮助他们做得更好。”
“我认为,在机器为我们编写所有软件或进行设计之前,我们还有很长的路要走。也许有一天会实现,但我认为在机器人接管之前,我们还有很长的路要走,”史密斯说。我们的电脑霸主还有很长的路要走。机器将会帮助我们制造东西,而不是把我们从等式中移除。他们将删除更多的物理,手工,平凡,繁琐的部分。他们将不会解决核心问题,特别是在研究和需求的前面,但即使暂时,一旦生成方法确定了正确的基本方向,他们也不会解决核心解决方案。
“我认为生成式设计是设计师的一种不同的思维方式。考虑为 design 设计一个系统而不是几个一次性的设计是不同的…史密斯说:“考虑如何让整个设计系统为你所用是不一样的。“它还需要计算设计技能,这样你就可以使用计算机来增强你的能力。我们试图通过创建这些可视化脚本环境,让架构师和工程师更容易地编写代码,只需将这些不同的节点或不同的功能放在一起。我们还致力于开发人们可以共享的节点。并且发展一个希望彼此分享代码的社区。”
让创作者通过一个视觉界面,不需要学习编程或与不复杂的用户界面纠缠,这对于释放人工智能在创作环境中的潜力非常重要。提供可视化使用环境的方法,而不是期望非程序员使用编程来最好地使用下一代工具,是人工智能等新兴技术的一个常见主题。与流行的每个人都学习编程的重要性相反,现实是为创意人员创造工具的公司正在积极尝试制造这些工具,以便我们中的非程序员可以充分利用它们。事实上,虽然今天有很好的理由让许多创意人员学习某种程度的编程,以最好地利用我们可以支配的早期和新生工具,但这些技能可能会建立我们长期的整体知识库,但只会在较短的时间范围内实际适用于我们的工作,在这个过渡时期,计算创意还处于早期。
使用人工智能辅助的自动化方法来更好地设计建筑很可能是未来的必然趋势。“到 2050 年,地球上将有 100 亿人口。如果你算一下,我们将需要每天建造大约 13,000 栋建筑来容纳所有这些人,”史密斯说。“为了在不完全破坏地球的情况下建造所有这些建筑,我们将不得不开发更好的方法来设计和建造[它们]……生成式设计是这一努力中的一种工具。我认为我们必须彻底改变我们做事的方式,以适应地球上所有这些人的需求。”
Creative Next 是一个播客,探索人工智能驱动的自动化对创意工作者,如作家、研究人员、艺术家、设计师、工程师和企业家的生活的影响。本文伴随 第三季第六集—建筑与生成设计 。
作为电影制作人的艾
我如何只用 ML 模型制作了一部完整的短片(你也可以做到)。

Merzmensch 的拼贴画。
真热闹。我记得看了一遍又一遍的《T4》和《太阳之春》。被荒谬的对话迷住了,我试图理解这部短片中发生了什么。但这种意义曾经悄悄溜走。因为是 AI 写的。
本杰明是作者的名字。这个名字的背后是一个递归神经网络 LSTM 隐藏,由人工智能研究员兼诗人罗斯·古德温开发。这部电影由获得英国电影电视艺术学院奖提名的英国电影制作人奥斯卡·夏普执导,主演包括托马斯·米德蒂奇。
即使情节由荒谬和看似随机的短语组成,我们的大脑也在试图理解它。我思故我在。
罗斯关于人工智能和创造力的必读论文对我来说极具启发性。如果你没有机会,一定要读读这个。
由机器智能实现的书写语言的新形式和界面
medium.com](https://medium.com/artists-and-machine-intelligence/adventures-in-narrated-reality-6516ff395ba3) [## 叙述现实中的冒险,第二部分
正在进行的写作和机器智能实验
medium.com](https://medium.com/artists-and-machine-intelligence/adventures-in-narrated-reality-part-ii-dc585af054cb)
通过他的实验(以及后来他的人工智能生成的书“ 1 the Road ”),罗斯证明了人工智能可能实现的目标。这一认识也是至关重要的:人工智能不仅仅是一个工具,也不是作家的完全替代品。你需要一个共生体来和艾一起创造艺术。
没有摄影棚的电影。
我们已经看到了机器学习有多少创造性的用途。
有了 3D 本·伯恩斯效应,我们可以制作动画梦境,将照片转换成空间相机的飞行。
我的系列的预告片
有了 OpenAI 的 GPT-2 ,我们可以写完整个故事。
但是如果我们把所有的方法结合到一件艺术品上呢?所以我就这样做了,用人工智能制作了一部短片。
…但是在你看它之前:你有一个想法吗,你需要什么来创作一部电影?
你当然可以为了艺术质量而放弃一些元素,但是通常,你需要以下要素来制作一部电影(即使是一部短片):
- 剧情
- 摄像机/视觉效果
- 演员们
- 音乐
你还需要一个原创的想法和(在大多数情况下)尚未使用的媒体资源。
那么,我们如何应用机器学习方法来满足所有这些要点呢?
剧情
如前所述, GPT-2 是一个强大的 NLP 模型(在 40 GB 文本上预先训练,有 15 亿个参数)来生成文字。它的主要缺陷——也是主要优势——是创作内容的超现实特征。它们通常没有意义(至少对于知识转移需求来说——在文学语境中它们可以是一个像样的解释对象)。并且:每次都会生成一个新的唯一文本。
让我们看看 GPT-3 未来会走哪条路( OpenAI 公布了这个拥有 1750 亿个参数的新巨型模型,由于其尺寸过大,目前无法进行微调)。
出于需要,我使用了一台由 Manuel Romero 设计的带有 Java 界面的 GPT-2 笔记本:
编辑描述
colab.research.google.com](https://colab.research.google.com/github/mrm8488/shared_colab_notebooks/blob/master/GPT2_with_JS_UI.ipynb)
有几种不同的笔记本,允许你微调 GPT-2 或在你的文本上进行训练,但我选择了这种特殊的 Colab 笔记本,因为它的用户友好和坚固的结构,以及对整个 15 亿参数模型的支持。
对于我的电影,我输入了以下提示:
**Empty room.****A man enters the room.****He looks out of the window and says: "It still hasn't begun".****The woman enters. She has a white dress on and a book in her hand.****The woman: "I am waiting as well."****The man: "For how long?"****The woman: "For a while."**
GPT 2 为我提供了各种文本,但我选择的是一部荒诞戏剧的惊人之作,介于贝克特、姆罗泽克和大卫·林奇之间:
Empty room.A man enters the room.He looks out of the window and says: "It still hasn't begun".The woman enters. She has a white dress on and a book in her hand.The woman: "I am waiting as well."The man: "For how long?"The woman: "For a while."The man: "Ah, you know, I'm a very patient man."The woman: "I know, of course."The man: "I'm going to have to be less patient, then." The woman starts to laugh; the laughter has an ominous edge that only she can feel."In my defence," she says, "I never actually told you what it was I was going to tell you."The man, suddenly, remembers: "That's right."The woman: "So you are lying behind me." The man is surprised by the abruptness of the accusation. He does not, however, feel any anger; as he has noticed in previous encounters, it is the woman who is most convincing when she's saying the lies.The man: "But it was not what you expected."The woman: "Oh…no." She is trying to sound convincing.He wants to ask her about her mother. The woman: "Do you think she'll be willing to lie?"The man turns down the opportunity.The woman: "Maybe…""Why?""Maybe she's still grieving." She is smiling when she says this, and the man doesn't think she'll be the first to smile when the truth comes out.He gives up. "No."The woman: "It's not over." The man has not got to see her family again. He had hoped to return to his work. He has nothing else to do. He wants to be a man.
它也说服了我,因为模糊的沟通水平。这就好像在所有那些稀疏的短语后面隐藏着一个巨大的故事(人脑在解释过程中确实产生了奇迹)。
所以我有了一个剧本。
画面
我是 StyleGAN2 的粉丝,但尤其是它在art breader中的实现(至少在“肖像”部分)。
你可以生成新的面孔,你可以制作过渡甚至动画(点击了解更多关于使用 Artbreeder 的信息)。所以我创建了一堆面孔的图像(看这里的资产)男人、女人,还有一些房间的图片。
这是一件棘手的事情,以配合故事的一部分(例如,在“笑的时刻”等)。),但是经过各种试错,对我来说还是管用的。
以下是一些用于视觉效果的资源:









我用 ArtBreeder 创建的图像
当然,你可以使用一阶运动模型来制作动态脸部动画(使用你自己的安迪·席克斯技巧):

我为本文生成的一阶运动模型。
但是对于我的荒诞和极简风格,面部变形是最合适的。
演员们
脸已经做好了,但是还缺少一些东西:声音。
语音生成可能是最古老的机器学习方法之一。我最喜欢的是梅尔内特——一个品质令人难以置信的模特。只听样本(在专业演讲者或名人数据集上训练)。唉,MelNet 不能作为工作存储库或 Colab 笔记本使用。
我的第二选择是亚马逊波利。作为亚马逊 AWS AI/ML 服务的一部分,Polly 提供了各种语言的大量语音。缺点是:他们中的大多数都有相当的主持人魅力,并不总是适合虚构的内容。
我在人工智能生成的视频“预测”中使用了一种声音:
尽管如此,如果在一些对话中使用非情绪化的声音,并不真正令人信服。
然后我发现了复制品工作室。

在https://replicastudios.com/我的仪表盘截图
他们目前提供了一个小的集合,但声音有惊人的质量。他们中的一些可以更好地用于主持人的需要,但另一个已经承担戏剧力量。
我选择了这三种声音——迪卡代表 旁白 ,卡洛斯代表 男人, 和奥黛丽代表 女人 。
你也可以尝试各种声音的情感特征,你甚至可以训练他们你的声音,但这三个对我的需求来说是完美的。
复制品工作室的使用非常简单。你按时间顺序排列短语,并给角色配上合适的声音:

我在https://replicastudios.com/的仪表盘截图
可以为您的项目将声音导出为 mp3 文件。
音乐
今年,在 OpenAI 发布了 JukeBox 之后,人工智能生成的音乐达到了新的质量水平——这是一个包含 7k 首歌曲和音乐作品的图书馆,由各种音乐家和词曲作者预先训练的模型生成(也可在此处阅读)。
他们中的许多人都相当浮华(像这个噩梦般的 【莫扎特】ppiece)。但是很多都很漂亮。尤其是与人工智能生成的视觉效果相结合,它们在内心唤起了奇怪的感觉。
我在我的系列“呼吸 ZeroX”中使用它们:
对于我们的视频,电影的东西应该通过,所以我查找了汉斯·季默的音乐训练(并改变了一点速度):
开始!
剩下的是相当艰苦的工作——对于我的视频,我使用了 Premiere Pro 和大量的咖啡。可能最棘手的事情是在时间上拉伸视频,并使它们与剧情同步(ArtBreeder 的原始面部过渡长度在 8-30 秒之间)。
建议 :我用了“时间插值:光流”。它在现存的画面之间创造新的画面,使画面流畅。有时它会产生小故障——但如果是关于数字生成的电影,它们总是受欢迎的!
现在:在这里。
空房间。
我想知道哪些新的视听珍品将采用新的 ML 方法。敬请期待!
人工智能作为设计材料
看到设计在创造人工智能驱动的产品中的作用
德克·克内梅尔和乔纳森·福利特
铅笔和速写本、记号笔和白板、像素和代码——这些是我们通常会联想到的设计材料。它们是设计师用来探索并最终实现他们需要解决的问题的解决方案的元素。无论是模拟还是数字,传统还是现代,它们在设计中的形式和作用都是显而易见的。不太明显的是,人工智能,更具体地说,机器学习,也是一种设计材料。虽然我们看到了人工智能对影响设计师的各种数字产品的影响,从常见设计工具的日益强大,如 Adobe Creative Cloud 到混合现实等新兴平台,但人工智能本身通常被认为是软件工程师的材料。此外,机器学习的最新发展仍处于新能力和新发明的发现阶段。我们离标准化的库和插件还有很长的路要走,这些库和插件可以被设计师以类似于今天的字体、照片和图标的方式应用。
乔什·克拉克是 Big Medium 的创始人和负责人,Big Medium 是一家纽约设计工作室,专门研究人工智能、互联设备和响应网站的未来友好界面。克拉克在世界各地发表演讲,阐述他的观点,即设计师应该将人工智能视为他们最新的设计材料。一般来说,人工智能,特别是机器学习,为设计师提供了一系列引人注目的功能和机会,以重要的方式创新和改善他们的设计体验。虽然 Clark 关于人工智能是一种新的设计材料的论点令人信服,但他关于人工智能现在是一种可用的设计材料的想法是一种反直觉的说法——这使得它变得更加有趣。

图 01:铅笔和素描本、记号笔和白板、像素和代码——这些是我们通常会联想到的设计材料。[图片:由凯莉·西克玛在 Unsplash 上拍摄]
“所有设计师都使用某种材料。“HTML 和 CSS 是设计材料,……数据及其可视化是设计材料,”克拉克说。“和所有这些东西一样,每种材料都有一定的优点和缺点。就像我认为机械师或木工正在处理物理材料,并学习它能做什么,它的边界是什么一样,我认为思考机器学习的同样事情是有用的。”
机器学习作为一种新的设计材料的比喻很聪明。这有助于揭开人工智能的神秘面纱,也有助于将它框定为我们一般使用范围内的东西。这不仅仅是大公司和魔法工程师精心制作的节目的一部分。它实际上可以影响许多不同的体验。设计师的核心专长是,或者至少应该是,为用户体验的利益而创造,因此他们有非凡的潜力去了解机器学习技术,理解它们的使用环境,并领导产品、服务和体验的创造,以有意义的方式让我们的生活变得更好。不仅仅是将我们与技术联系起来,设计师现在还可以塑造让我们生活更美好的技术。这是一个令人兴奋的机会。
“对于许多设计师来说,他们一直认为机器学习和人工智能是数据科学家或算法工程师的领域,甚至可能没有设计师的角色,”克拉克说。“随着我越来越多地使用由机器学习驱动的产品,我越来越清楚地认识到,设计师有着巨大的作用,这在很大程度上是一种设计材料,我们迫切需要在设计上给予一些关注。”
设计师使用人工智能的五种方式
克拉克详细介绍了设计师在软件产品中使用人工智能的五种方式——推荐、预测、分类、聚类和生成。“人工智能已经准备好用于日常产品,有时是以小的方式,”克拉克说。“我认为,随着机器学习变得越来越普遍,正如我们已经开始看到的那样,随着越来越多的设计师和开发人员意识到这是一个你可以在工具包中拥有的工具,在界面中加入一点机器学习和一点智能就像在网页中加入一点 JavaScript 和一点互动一样常见。”
克拉克的观点不仅有助于进一步揭开人工智能用法的神秘面纱,而且实际上也有助于将它置于情境之中。就这一点而言,设计师可以利用人工智能的前三种方式——推荐、预测和分类——在早期的网站和软件设计中一直是考虑因素。人工智能增强了这些功能,但这些并不是新的方法,而是这些功能现在运行方式的一次重要演变。过去的设计者创建文字和静态的表单,现在他们可以提供动态的交互,如果应用得当,可以大大改善用户体验。Clark 提供了一些人工智能在当今产品推荐、预测和分类中的应用示例:
推荐
“[举例来说],Slack for teams,for big enterprise organizations,可以让你寻找某方面的专家。例如,你可以输入“人力资源”这样的词,它会显示那些经常谈论人力资源的人。这不仅仅是一个暴力文本搜索。它围绕概念提供建议,”克拉克说。
预测
“预测是基于历史数据:‘接下来最有可能发生的事情是这样的’。…在谷歌的 Gmail 功能中,它会提示下一个单词或短语,你可以在应用程序中加入这一点点智能,让它变得更好。”
分类
“(人工智能的)第三个应用是分类,这实际上是你在教机器将一个事件、一个物体、一张照片或一个短语与某种分类、某种类别进行匹配,”克拉克说。“我们在日常产品中看到的一个例子是谷歌表单,谷歌调查工具,它让你通过输入问题并选择答案来建立调查。……几年前,谷歌加入了一点机器学习,这样当你键入问题时,它会默认它认为最有可能的答案分类。”
克拉克接下来描述了群集和生成的人工智能功能,这些功能有可能为新软件提供巨大的动力。
聚类
“有了聚类,你给机器一大堆信息,它就开始定义类别。克拉克说:“它能识别‘这是基线’、‘这是正常’和‘这是一大堆以有趣或相似的方式不同于正常的东西’”。“这方面的一个例子是一个名为深度病人的系统,它收集了成千上万的医疗记录,并对它们进行大量处理以找到模式。”深度病人能够比大多数人类医生早两年预测精神分裂症的发作。“你可以用[深度耐心]来引导人类的注意力,”克拉克说。但是,这并不意味着可以替代医生的判断。
“我认为关于这一点有趣的事情之一是,我们并不真正理解机器如何或为什么进行这种聚类。所以,在深度病人和精神分裂症的情况下,你可能会想,‘哦,这太好了。这将让我们对精神分裂症的工作原理有新的理解。但实际上没有。“深度患者处理所有的患者记录,但我们实际上并不知道它是如何得出这个结果的。”“甚至创造这个系统的人也不理解它,”克拉克说。所以,这是个棘手的问题。“我们有信息,但我们不知道它是如何得到的。
“我认识几个策展人,他们通过这样的系统管理他们博物馆或研究所的艺术收藏品,并让机器开始对它们进行聚类和分组,”克拉克说,“机器以不同于人类策展人的方式做这件事。它们不符合我们更传统地看待艺术的正式艺术流派或时期,但它们仍然以有趣的方式分组。在费城的巴恩斯基金会,当他们通过图像识别搜索运行他们的收藏,并开始寻找,例如,映射到天使概念的艺术品。它发现了肯定不是天使的东西,包括雕塑和花瓶以及类似的一些奇怪的东西,但也有不完全是天使的东西。”
“你可能会想,‘嗯,那不是很有用’。……但是,策展人实际上把它看作是一种富有成效的摩擦,这些机器很奇怪,它们以不同的方式看待世界。他们不会像我们人类那样对事物进行分类。但是,这也让我们以新的方式看待这个世界,否则我们将无法看到,”克拉克说。生产摩擦是一个有用的术语:人工智能可以从一个新颖的角度处理问题,尽管一些结果可能没有用,但也可能有巧妙和意想不到的发现。
一代
机器也可以开始代表我们生成内容。例如,移动照片编辑应用 FaceApp 可以拍摄你的照片,并使用神经网络,以非常真实和令人信服的方式让你看起来老了几十年。“这是一代人的一个例子,”克拉克说,“无论是创造艺术、写作句子还是创造可视化——这种想法是机器可以开始进行某种创造。作为一名设计师,这是我感兴趣的事情。实际上,我已经看到机器接管了我工作中一些更机械的面向生产的方面。”人工智能支持的设计生成的一个例子可以在 Uizard 中找到,这是一个应用程序,使设计师能够拍摄他们的草图,然后用 HTML 生成完整的设计,将熟悉的线框符号映射到完整的设计模式。
聚类和生成开始感觉更像实际的智能,人工智能不仅仅是以方便的方式改进我们熟悉的东西,而是提供了一个超出设计师之前想象的额外处理层。

图 02:一个生成式人工智能工具可以将人们熟悉的线框符号映射成完整的设计模式。
[图片:由光晕上的 ]
模式检测和人机协作
机器学习最擅长的也许是检测模式。在这种背景下,克拉克提出四种功能成为可能——提出更好的问题并获得更好的答案,提出完全不同类型的问题,访问新类型的数据,以及浮现不可见的模式。
有了人工智能,我们可以更好地回答问题,并以更有效和更明智的方式来做。例如,人工智能可以围绕概念创建语义向量,而不是对搜索短语进行强力匹配。此外,人工智能可以让我们提出全新的问题。“我们现在能够搜索情感,而不是仅仅搜索文本或概念,”克拉克说。“例如,想象一下呼叫中心的某个人。现在,你不用按时间顺序接收邮件了……实际上,你可以查找紧急邮件,邮件中的措辞是紧急、愤怒或不安。在这个例子中,人工智能理解和分类内容的能力使运营商能够控制他们的日常工作负载,主动引导各种类别的传入流量和工作流。
因为机器现在能够理解人们相互交流的所有混乱方式——我们在拍什么照片,我们的讲话是什么,我们的笔迹是什么——人工智能使我们能够访问新类型的数据。“所有这些过去对机器完全不透明的东西现在都是机器可读和可理解的,”克拉克说。“这意味着我们可以从中挖掘数据和洞察力,但也意味着我们可以将这些新的数据源用作交互平台。”
人工智能使我们能够显现不可见的图案。“机器能够看到我们根本看不到的东西,部分原因是它们能够浏览和理解如此大量的数据,并找到否则会丢失的模式……而我们却无法发现自己,”克拉克说。“事实证明,在许多情况下,机器在一些我们作为人类最关心的事情上实际上非常糟糕,”克拉克说。“但他们擅长做我们通常不喜欢做的事情,那些重复的、容易出错的或无趣的任务。他们很擅长发现我们没有发现的模式。因此,我认为设计工作的一部分是找出用户旅程中的一个点,在那里机器实际上是有帮助的,并显示出我们不会发现的洞察力。”
克拉克描述了这种人机协作如何才能理想地工作。“我与一家医疗保健公司合作,试图找出如何使用机器学习来帮助放射科医生更好地完成工作。放射科医生通过图像和 x 光来识别我们身体中的问题——肿块或其他问题。而且,他们的大部分工作实际上都是在寻找不存在问题的东西,”克拉克说。“这是一个巨大的工作量,一张接一张地查看图像,直到他们有了真正需要他们专业知识的东西。例如,机器学习可以做的事情之一是分类,显然具有非常高的灵敏度。我们不希望有任何错误的否定,机器会传递一些重要的信息。“这个想法是,机器可以做一遍,把有趣的案例带给人类——不是做人类的工作,而是让人类做他们最擅长的事情。”这对设计师来说是真正的机会,不仅仅是自动化,而是推断由于这些新的机会而可能发生的事情,甚至是重新想象整个系统的更大方面

图 03:人工智能可以对大量的图像和 x 光进行分类,并显示出最有趣的病例。
【图片:由国立癌症研究所在 Unsplash
风险与机遇
克拉克非常关注数据,这是推动大量机器学习的原材料。“我认为我们必须意识到,不仅仅是我们如何使用数据,而且作为设计师,我们如何教育人们更明智地使用数据,理解它是如何被使用的以及为了什么目的,”克拉克说。“我认为,对于我们如何使用数据,我们有责任做到真正透明。我并不是说我们应该在使用条款中规定,你必须阅读成千上万的信息才能使用一项服务。”
克拉克说:“很多时候,人们和公司会说,‘嗯,你知道,如果我们告诉人们我们在用他们的数据做什么,他们就不会想使用我们的服务。’我认为这应该是一个巨大的危险信号,如果你这么说,那么你可能不应该做那件事。"
“在过去的几年里,你已经看到事情会如何出错,偏见会如何以令人不快的方式蔓延到系统中,这些系统会如何被外国政府以玩世不恭的方式用来操纵公司的民主,利用那些认为自己是客户但实际上是公司服务的人,而实际上他们是在为公司服务。”
“尽管机器学习的力量和前景都很强大,但它的风险在于,它将迅速加剧不平等并扩大差距,因为使用这项技术的人将能够从中获得最大的……好处。然后就进入了这种非常恶性和令人担忧的循环,”克拉克说。
“我选择乐观。我看到这些都是强有力的工具,可以用来做好事,也可以用来做坏事。我认为这就是为什么我们需要设计师和真正关心人类体验的人参与到这些事情中来的原因,这样他们就不会只是为更愤世嫉俗的势力服务。我认为,这是一个我们所有人都必须选择乐观并倾向于这一点的时候,并对事情可能会如何出错带来适当的怀疑和意识,但也给这些真正强大和令人兴奋的新工具带来一种可能性。”
Creative Next 是一个播客,探索人工智能驱动的自动化对创意工作者,如作家、研究人员、艺术家、设计师、工程师和企业家的生活的影响。本文伴随 第三季第二集— AI 作为设计素材 。
AI = "自动灵感"
历史(和未来)的简短游览!)的数据科学
(改编自我的 原福布斯 AI 文章 )。)
下面是文章的音频版本,由作者为你朗读。
在 19 世纪,医生可能会为情绪波动开出水银处方,为哮喘开出砷处方。他们可能不会想到在你手术前洗手。当然,他们不是想杀你——他们只是不知道该怎么做。
这些早期的医生在他们的笔记本上潦草地记下了有价值的数据,但是他们每个人在一个巨大的拼图游戏中只拿了一块。如果没有共享和分析信息的现代工具,以及理解这些数据的科学,就无法阻止迷信取代通过可观察事实的钥匙孔看到的东西。
自那以后,人类在技术方面取得了很大进步,但今天机器学习( ML )和人工智能( AI )的繁荣并没有真正与过去决裂。这是人类理解周围世界的基本本能的延续,这样我们才能做出更明智的决定。我们只是拥有比以往任何时候都好得多的技术。
今天人工智能的繁荣并没有真正与过去决裂。我们只是拥有比以往任何时候都好得多的技术。
一种看待这种模式的方式是把它看作是数据集的革命,而不是数据点。这种差异并不小。数据集帮助塑造了现代世界。
书写的发明
想想苏美尔(今天的伊拉克)的抄写员,他们在 5000 多年前就把手写笔压在泥板上。当他们这样做时,他们不仅发明了第一个书写系统,而且发明了第一个数据存储和共享技术。

世界上第一个数据存储和共享技术的例子,泥板。你不能在上面存放太多的数据,而且检索是一件痛苦的事情(你必须全力以赴)。
如果你被 AI 超越人类的能力的承诺所鼓舞,考虑一下文具给了我们超人的记忆。虽然今天很容易把写作视为理所当然,但可靠地存储数据集的能力代表着通往更高智能的道路上开创性的第一步。
如果你被人工智能超越人类能力的承诺所鼓舞,那就认为文具给了我们超人的记忆力。
不幸的是,从泥板及其电子前的同类中检索信息是一件痛苦的事。你不能对着一本书打响指来得到它的字数。相反,你必须将每个单词上传到你的大脑中进行处理。这使得早期的数据分析很费时,所以最初的尝试只停留在本质上。虽然一个王国可能会分析它通过税收筹集了多少黄金,但只有勇敢的灵魂才会在医药等应用上尝试同样的努力推理,因为几千年的传统鼓励即兴发挥。
分析的兴起

约翰·斯诺绘制的地图显示了 1854 年伦敦大流行中的霍乱病例。
幸运的是,我们的物种产生了一些不可思议的先驱。例如,约翰·斯诺绘制的 1858 年伦敦霍乱爆发期间的死亡地图启发了医学界重新考虑疾病是由瘴气(有毒空气)引起的迷信,并开始仔细研究饮用水。

分析师弗洛伦斯·南丁格尔(1820-1910)
如果你知道《拿着灯的女士》(The Lady With The Lamp),弗洛伦斯·南丁格尔(Florence Nightingale)因其作为护士的英雄般的同情心而出名,你可能会惊讶地发现,她也是分析学的先驱。她在克里米亚战争期间发明的信息图表拯救了许多人的生命,她将糟糕的卫生状况确定为医院死亡的主要原因,并激励她的政府认真对待卫生问题。

弗洛伦斯·南丁格尔发明的极区图,显示了死于可预防疾病的人数(蓝色),死于创伤的人数(红色),以及死于其他原因的人数(黑色)。
随着信息的价值开始在越来越多的领域得到体现,导致了计算机的发明,单数据集时代开始了。不,不是你今天习惯的电子伙伴。“计算机”最初是一种人类职业,其从业者手动执行计算和处理数据以提取其价值。

所有这些人都是电脑!摄于 20 世纪 50 年代的超音速压力风洞工作人员的照片。
数据的美妙之处在于,它能让你形成一个比凭空想象更好的观点。通过浏览信息,你会受到启发,跟随弗洛伦斯·南丁格尔和约翰·斯诺的脚步,提出新的问题。这就是分析的全部内容:通过探索激发模型和假设。
分析的缺点
不幸的是,没有第二个数据集,你无法知道你的这个数据启发的观点是不是胡说八道。除了你看到的特定数据点之外,它在一般情况下是否有效?你没有合法的途径知道。欢迎来到 20 世纪的分析。

Paul J 为我的文章创作的关于数据驱动决策中的确认偏差的插图。
你不能相信你的发现,因为你的无意识偏见(如确认偏见)掌控着方向盘——你会立即看到最方便看到的东西,而你会错过所有其他的东西。你可能认为你看到了所有能看到的东西,但实际上你只看到了皮毛。我们人类的注意力广度和记忆力比我们想象的要小,所以探索性数据集对我们来说通常是一种狒狒陷阱。
分析是关于灵感和探索的,但是那些超越所探索的数据的观点不能被认真对待。
为了检验你对数据之外的世界如何运作的看法,你不能使用最初激发你这种看法的数据。我们的物种在薯片中发现了猫王的脸。虽然这个芯片可能看起来像猫王,但我们不能用它来断定大多数芯片都像猫王。为了了解我们的观点是否会被严肃对待,我们必须在我们从未见过的新芯片上测试它们。
从数据集到数据分割
20 世纪初,在不确定性下做出更好决策的愿望导致了一个平行职业的诞生:统计学。统计学家帮助你测试,如果一种现象也适用于你当前的数据集之外,这种行为是否明智。
统计的严谨性要求你在出手之前先发号施令;分析更多的是一种高级后见之明的游戏。
一个著名的例子与世界上第一本统计学教科书有关。它的作者描述了一项假设测试,以回应他朋友的说法,即她可以品尝出牛奶是在水之前还是之后加入茶中的。他希望证明她是错的,但数据迫使他得出结论,她可以。
阿喀琉斯之踵
分析和统计有一个主要的致命弱点:如果你使用相同的数据点进行假设生成和假设检验,你就是在作弊。(看了这个就明白为什么了。)如果你选择用你的数据来获得严谨而不是灵感,你就得从别处获得灵感。经典的来源是苦苦思索。换句话说,你坐在一个扫帚间里沉思,仔细地构建你的统计问题,阐明你所有的假设,然后你有一次机会来测试你的世界心理模型是否真的站得住脚。
不幸的是,要用数学的方式详细说明你的全部直觉并对其进行测试,需要付出大量的努力和训练。你需要集中精神。但至少现在你有了一个合法的方法来检查你的印象是否值得采取行动。欢迎来到 20 世纪后期的统计数据。
数据集革命
统计学的严谨性要求你在采取行动之前先发号施令;分析更像是一场高级后见之明的游戏。这些学科几乎是悲喜剧般的不兼容,直到下一次重大革命——数据分割——改变了一切。

数据分割是一个简单的想法,但对于像我这样的数据科学家来说,这是最深刻的想法之一。如果你只有一个数据集,你必须在分析(不可测试的灵感)和统计(严谨的结论)之间做出选择。黑客?把你的数据集分成两部分,然后拥有你的蛋糕并吃掉它!
双数据集时代用两个不同品种的数据专家之间的协调团队合作取代了分析 - 统计 紧张。分析师使用一个数据集来帮助你框定你的问题,然后统计学家使用另一个数据集给你带来严谨的答案。
将你的数据集一分为二,然后鱼与熊掌兼得!
这种奢侈伴随着一个沉重的价格标签:数量。如果你甚至难以为一个可观的数据集收集到足够的信息,那么拆分说起来容易做起来难。双数据集时代是一个相当新的发展,伴随着更好的处理硬件、更低的存储成本和通过互联网共享收集的信息的能力。
事实上,导致双数据集时代的技术创新迅速迎来了下一个阶段,一个自动化灵感的三数据集时代。有一个更熟悉的词来形容它:机器学习。
一次性命题的测试
有没有想过,当谈到严谨性和数据时,为什么统计学家往往倾向于焦虑不安?在你计划你的问题之前看一个数据集破坏了它作为统计严谨性来源的纯度。如果你问错了问题或者问得很愚蠢,你就没有机会再问先知第二次了。
即使你在考虑进行多重比较校正,也就是允许每个数据集有多个假设的统计咒语,只有你提前计划好所有的假设,你的程序才是有效的。你不能拿你的测试数据集玩 20 个问题,反复放大一个闪亮的结果,假装你已经洗手不干了。
测试仍然是一个一次性的提议——不允许你向一个解决方案反复爬行。
为了使这种严格的方法有效,你必须提前计划,如果有不止一个问题,使用一些充满歉意的数学方法,然后一次同时执行测试。您不能多次打开该测试数据集。
第三个数据集的奢华
既然你只有一次机会,你怎么知道哪一个来自分析的“洞察力”是最值得测试的呢?好吧,如果你有第三个数据集,你可以用它来激发你的灵感进行一次试驾。这个筛选过程被称为验证;这是让机器学习运转的核心。
验证是机器学习的核心——它允许你自动激发灵感。
一旦你可以自由地将所有东西扔向验证墙,看看有什么东西卡住了,你就可以放心地让每个人都尝试提出一个解决方案:经验丰富的分析师、实习生、茶叶,甚至是与你的业务问题无关的算法。无论哪种解决方案在验证中效果最好,都会成为合适的统计测试的候选方案。你刚刚授权自己自动激发灵感!

图片:来源。
AI =自动灵感
这就是为什么机器学习是数据集合的革命,而不仅仅是数据。这取决于是否有足够的数据进行三向分割。
人工智能( AI )在图片中的位置?使用深度神经网络的机器学习在技术上被称为深度学习,但它有另一个流传下来的昵称: AI 。虽然 AI 曾经有过不同的含义,但今天你很可能会发现它被用作深度学习的同义词。
深度神经网络凭借在许多复杂任务上超越不太复杂的 ML 算法而赢得了他们的大肆宣传。但是它们需要更多的数据来训练它们,并且处理要求超过了典型的笔记本电脑。这也是为什么现代 AI 的崛起是浮云故事;云允许你租用别人的数据中心,而不是致力于建立你的深度学习平台,使人工智能成为一个先试后买的命题。
现代人工智能的崛起是一个云的故事,因为云让人工智能成为一个先试后买的命题。
有了这个拼图,我们就有了完整的职业补充: ML/AI 、分析和统计。包含所有这些的总括术语叫做数据科学,让数据变得有用的学科。
灵感的未来
现代数据科学是我们三数据集时代的产物,但许多行业通常会产生过多的数据。那么,有四个数据集的情况吗?
好吧,如果你刚刚训练的模型得到一个低的验证分数,你的下一步行动是什么?如果你和大多数人一样,你会立刻要求知道为什么!不幸的是,没有可以询问的数据集。您可能想在您的验证数据集中进行调查,但是不幸的是,调试破坏了它有效筛选您的模型的能力。
通过对你的验证数据集进行分析,你可以有效地将三个数据集变成两个。你没有寻求帮助,而是不知不觉地回到了一个时代!
解决方案在你已经使用的三个数据集之外。要解锁更智能的训练迭代和超参数调整,您需要加入前沿:四个数据集的时代。
尖端是四路数据拆分到燃油加速。
如果你认为其他三个数据集给了你灵感、迭代和严格的测试,那么第四个数据集促进了加速,通过先进的分析技术缩短了你的人工智能开发周期,这些技术旨在提供关于每一轮尝试什么方法的线索。通过采用四路数据分割,您将处于利用数据丰富的最佳位置!欢迎来到未来。
感谢阅读!人工智能课程怎么样?
如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:
在这里欣赏整个课程播放列表:【bit.ly/machinefriend
与凯西·科兹尔科夫联系
让我们做朋友吧!你可以在 Twitter 、 YouTube 和 LinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用表格取得联系。
人工智能、自动化和音乐

阿德里安·科特在 Unsplash 上拍摄的照片
技术对新一代艺术家意味着什么?
下面提到的一切都是我的观点,而且仅仅是我的观点。不认同我或者看到我提到的东西不一样?留下回应,大家来说说吧!
音乐行业是尚未看到全面重组成为人工智能直接原因的领域之一。向流媒体的过渡导致了一场重大的重组——这场重组恰好有利于唱片公司和流媒体服务,而不是将消费者放在首位的艺术家。AI 和 ML 已经帮助流媒体服务提供音乐推荐和有针对性的广告,但这些技术尚未改变我们听/创作音乐的方式。这将会改变,而且很快就会改变。
人工智能 vs 机器学习:
我就不告诉你维恩图了。
人工智能和机器学习有很多的区别。鉴于机器学习是人工智能的一个子集,这两者之间也有许多相似之处。我们将从表面价值上理解和定义机器学习——机器学习并获得关于某个主题的洞察力的能力。至于人工智能,我们将把它定义为机器根据赋予它的某些规则和参数采取行动的能力。在现实世界的用例中,这两种技术经常交织在一起,但是在本文中(为了我自己的理智),我们将把这两种技术视为独立的工具。
在机器学习的情况下:
我们都很熟悉我们的数据是如何被用来个性化几乎所有东西的,从广告到用户体验。虽然我们可能不知道这些算法如何确定什么是“适合我们”或者什么不是“适合我们”背后的技术细节,但我们知道正在使用的指标会不断与其他指标进行比较,以了解用户有哪些相似的模式/爱好。同样的想法也可以贯彻到艺术家和他们的音乐中。
当在音乐中使用机器学习时,我们可以复制我们如何解剖和研究音乐,无论是从抒情还是声音的角度,在规模上。这意味着“相似”的概念可以超越我们如何看待同一流派的两位艺术家是相似的。相似性的衡量很可能会超越流派和时间段,因为一个艺术家的一切都是另一个艺术家的背景——就像我的背景不仅决定了我看到的广告,也决定了你看到的广告。
然而,如果在错误的人手中,对艺术家身份的深刻理解可能会被用来人为地向出价最高者夸大数字。这反过来又成为一个新的音乐广告市场。支付最高报酬的唱片公司或实体被放在首位,而独立艺术家可能会被落在后面。
我们可以更深入地了解是什么让一个艺术家在音乐上与众不同,是什么让他们独一无二,等等。然而,如果使用不当,这些见解只会有利于那些买得起的人。
就人工智能而言:
我们是希望人工智能成为推动人类能力向前发展的工具,还是希望人工智能自动完成我们觉得没完没了和无聊的任务?在很多情况下,我们可以两者兼得——既有蛋糕,又能吃掉它。然而,在音乐领域,答案并不像我们希望的那样直截了当。
分层音频是一种数学尝试,旨在将歌曲的各个组成部分分开,就像它们是单独录制的一样。Deezer 的 Spleeter 是我迄今为止见过的做得最好的,我甚至正在为我的本科项目制作一个。像这样的工具可以彻底改变制作人从歌曲中取样的方式。就像你不想要的一些其他乐器旁边的一段歌曲中的鼓声一样?把它分离出来,用在你的歌里。就目前的能力而言,它可能并不完美,但它将帮助您起步。在音乐中使用人工智能应该与 VSTs 的工作方式没有什么不同——一个让创作过程更容易的插件。
需要注意的是,音乐的产生是非常真实的事情。将这一点与前 5 大公司的计算资源结合起来,我们现在已经将音乐行业转向为您提供数千小时的生成音乐,而几乎不需要您支付任何费用。现在,我知道你在想什么,谁会想听电脑制作的音乐?当音乐一代融入我们的音乐品味时,你和我都会这样,现在音乐正被不断地创造和调整到我们想要的程度。这离可能性不远了,而且会比我们想象的更快成为现实。解决办法很简单,积极支持人类艺术家。
我们可以建立工具来帮助改善艺术家创作和操作难以想象的歌曲的工作流程。然而,如果使用不当,这些工具可以自动艺术家的生计。
结论:
人工智能可以帮助迎来新一代的创意人员,或者完全取代他们。所有新技术和新兴技术的核心都是相似的;他们对我们运营方式的影响是我们影响他们运营方式的直接产物。
基于人工智能的模糊化(AIF)
模糊化是指使用计算机程序中的半有效输入来验证计算机程序中的行为异常、内存泄漏和其他漏洞的过程。
鉴于威胁的快速发展,更密切地关注人工智能和机器学习(ML)的安全影响已变得势在必行。安全专家开发了“AI-fuzzing”的概念,通过“fuzzing”来磨练 AI/ML。

AI fuzzing 是一种技术,它与机器学习一起帮助识别应用程序和系统中的漏洞。然后,这些信息可以被提供给网络罪犯并出售给他们,以开发一种新型的恶意软件。
给侠影增加人工智能对该公司来说可能是福也可能是祸。机器学习和人工智能现在被应用于这个问题的事实已经改变了这个问题的性质及其对商业系统安全的潜在影响。将人工智能作为一种工具,有望使这种工具更容易使用,更灵活。
AIF 可以以多种不同的方式工作,例如模糊化计算机程序,甚至作为一种分析方法。
除了模糊 AI,它还可以作为识别和利用零日错误的高效工具。AIF 恶意软件可以测试大量的输入,本质上是测试系统的弱点。该恶意软件可以访问多个有效负载,并可以根据系统中的特定漏洞激活最有效的有效负载。

有效的应用程序安全测试的关键是使用输入种子来建立代码路径并导致崩溃和 bug 发现。基于人工智能的工具可以识别潜在的攻击选项,并生成可能的测试用例。一旦一个测试用例提供了一条承诺的探索之路,新工具就会跟进并更深入地研究,看看应用程序一个领域中的问题是否会导致其他地方出现可利用的漏洞。
输入可以是预先确定的,或者可以是随机的或通过训练算法产生基于先前运行的相关变化而变异的。
这种动态的、非确定性的安全测试技术使开发者能够持续地、自动地检查不断发展的网络浏览器,包括供应链依赖性。通过消除人工智能施加的约束,使逻辑与查找故障保持一致,Azure Resource Manager 可以通过使用模糊实验室来增加所需的计算,从而创建一个实验室——一个满足客户需求的熔化环境。基于 azure 的方法使客户能够运行除微软自己的模糊化器之外的多个模糊化器,允许他们从几种不同的模糊化方法中获得价值。
微软利用模糊来寻找漏洞,提高自己产品的健壮性。2019 年,谷歌声称使用其内部模糊工具链自动发现了超过 20,000 个漏洞。 DoD DevSecOps 参考设计需要模糊测试,但它可以通过多种不同的方式完成,如使用模糊器、机器学习和人工智能。
消费者技术协会(Consumer Technology Association)最近发布的数据显示,2018 年部署的所有人工智能应用程序中,超过一半已被用于网络安全目的。

随着人工智能技术的不断发展,人工智能模糊化(AIF)可能会成为网络安全的一个主要威胁。这是一个不断发展的领域,应该受到信息安全部门的重视。
可以训练安全设备和系统自动执行特定任务,例如基本行为、使用行为分析来识别复杂威胁或修补设备。通过有针对性的机器学习,网络犯罪分子可以训练设备或系统不对特定设备应用补丁或更新,忽略某些类型的应用程序行为,或记录某些流量以绕过检测。
最近宣布的微软风险检测(MSRD)服务只是模糊测试需要发展的一个例子。机器学习和人工智能并不新鲜,但图形处理器(GPU)及其通过在安全测试和其他应用中使用机器学习而使其成为主流的潜力才是新鲜的。
人工智能是一个赋予计算机思考和学习能力的领域,尽管这一概念自 20 世纪 50 年代就已存在,但由于芯片具有更高的计算能力,它正在复兴。人工智能市场预计每年增长近 37%,到 2025 年达到 1910 亿美元。事实上,微软在所谓的约束求解方面的获奖工作历时 10 年,并被用于生产微软的世界上第一个白盒模糊器。
引用来源
- 国防部发展战略参考设计
- https://www . CIO review . com/news/impacts-of-ai-fuzzing-on-cyber security-nid-28863-cid-175.html
- https://gcn . com/articles/2020/05/15/fuzzing-software-vulnerability-detection . aspx
- https://cyber . grant Thornton . co . uk/post/102 fm3t/is-ai-the-future-of-hacking
- https://www . aithority . com/machine-learning/to-get-in-front-the-cyber-affairs-fortinet-predicts-organizations-will-employee-more-automation-to-combat-threats/
- https://ciso . economic times . India times . com/news/why-ai-fuzzing-can-be-next-cyber security-threat/68609808
- https://www . Microsoft . com/security/blog/2018/01/03/application-fuzzing-in-the-era-of-machine-learning-and-ai/
- https://www . tech zine . eu/news/security/37253/fortinet-sees-ai-and-swarm-as-a-service-as-key-security-trends-for-2019/
- https://www . data center knowledge . com/security/how-ai-fuzzing-can-protect-data center-or-be-its-worst-敌国
超越准确性的人工智能:透明性和可扩展性
好的人工智能不仅仅是准确的,它是透明的和可扩展的(因此是值得信赖的)

乔伊特·查特吉的概念。卡通/明星和商务会议元素是来自 Pixabay/Pexels 的免费图片(无需注明出处)。请适当引用这篇中等文章。
我们都非常熟悉人工智能(AI)技术(尤其是深度学习)在全球范围内创造的大肆宣传——主要归因于一个目标,获得更高的准确性,并击败现有的基准。这在深度学习技术继续应用的几乎每个领域都非常突出,例如,尽管模型可以达到很高的准确度(在某些情况下,即使是垃圾数据也可能给你> 90%的准确度!),它们受到透明性、可伸缩性和可解释性的关键问题的困扰。如果你的人工智能模型仅仅是精确的,但不具备其他任何一个特征,它有什么好的吗?
答案是,不,它在现实生活中没有任何好处(除非您只将它应用于 Iris flower 数据集)。这是大多数可以采用人工智能的企业不愿意这样做的唯一原因——人们不信任人工智能。那么,目前的人工智能方法在哪里缺乏,我们如何才能尽自己的一份力量来构建值得信赖的人工智能?
透明度

图片由 Gerd Altmann 从 Pixabay 拍摄
人工智能模型,尤其是深度学习者,简直就是黑盒。向模型输入一些数据来训练它,它会自动学习数据中的模式,一旦你给它一些新的、看不见的(测试数据),它就能够对你看不见的数据进行预测/分类(取决于你是否训练了一个回归/分类模型),准确率为 X%。现在,有趣的事实是,一旦你训练了一个神经网络模型几百个时期,在大多数情况下,它们将能够学习各种非线性复杂数据中的模式,并在你看不见的测试数据上给你很大的准确性。但你怎么知道你的人工智能模型在获得如此高的准确性方面做了什么?模型查看了数据中的哪些要素(参数)?哪些特性对获得 X%的准确率贡献最大?透明度的作用来了。
透明的人工智能将允许你判断你的人工智能模型为什么(以及如何)为你的数据做出决定(或不做出决定)。以及如何才能让我们的人工智能模型变得透明?这一领域正在进行一些令人兴奋的研究
- 利用简单易用的库来解释 AI (例如 https://github.com/slundberg/shapSHAP,莱姆https://github.com/marcotcr/lime等等。).这些是一些出色的软件包,允许您识别数据集中有助于特定预测的要素!它们为你提供了可解释的特性总结,附加力图等。和直观的可视化,使黑盒决策变得理智。
- 深度学习模型中的注意机制:因此,想象你的数据集由一些复杂的图像/时间序列/文本等组成,你正在执行各种任务,以高精度预测黑盒神经网络之外的事物。但可悲的是,传统的神经网络模型(无论是卷积神经网络(CNN),递归神经网络(RNNs)等。,甚至不同类型的这些模型,如长期短期记忆(LSTMs)都是黑箱。为了避免这个问题,注意力机制来了。
假设您的数据集中有 N 个要素,关注机制会为您提供要素对特定结果的重要性分数(权重)。虽然这种机制最初在神经机器翻译(NMT)中变得突出,但现在它扩展到了所有类型的数据(文本/音频/时间序列数字数据等)。).https://medium . com/@ dhartidhami/attention-model-797472 AC 819 a是解释在神经模型中如何计算注意力的资源。
3.利用因果推理:哦对!相关性计算起来很简单,但是它有必要给你完整的数据和模型吗?一个大大的不!相关性不一定意味着因果关系。如果你需要让你的人工智能模型可信,你需要确定你的特征内部的因果关系(什么特征导致了特定的结果),以及你的数据集中的多个特征如何共享隐藏的关系(作为人类,我们无法判断,但因果推理可以帮助确定)。https://towards data science . com/inferencing-causality-in-time-series-data-b 8 b 75 Fe 52 c 46是推断时间序列数据因果关系的绝佳起点。
可扩展性

图片由皮克斯拜的 Gerd Altmann 提供
对,所以你的人工智能模型达到了 95%的准确率!令人兴奋的东西。它还以 1%的精度击败了最先进的基准,但比最先进的多花费了 15 天的额外计算资源和训练时间(在 GPU 上也是如此)。等等!以这种密集的计算资源为代价获得 1%的精度提升?我认为我们在这里走错了路。在复杂的工业系统和商业中,真的有很多人能接触到这样的计算能力/金钱/资源吗?大多数人不会。此外,以计算复杂度为代价获得 1%的精度提升没有太大意义。如果我们从我们的模型中获得了一些额外的好处,故事将会不同(这里的好处意味着可解释性和透明性)。
但可悲的是,人工智能的大肆宣传意味着击败最先进的技术,不幸的是,这在研究界一直很突出。如何改变这种情况,使您的模型具有可伸缩性?

- 做正确的事情,如果更简单的模型(例如随机森林)比复杂的深度学习者的高度复杂的堆叠模型工作得更好(没有给你提供额外的好处),那么请不要在这种情况下使用深度学习模型。如果你真的想,只利用可以提供透明度的深度学习模型(如上所述,通过注意力机制,或通过利用结合传统 ML 学习者和深度学习者的混合方法)。
- 你的模型适应新数据吗,还是只对特定的数据段有好处?通过使你的人工智能模型通用化,尝试使它们可扩展,利用迁移学习技术,这可以促进从密切相关的领域学习,使你的人工智能模型在新的领域中工作良好。因此,迁移学习使你能够在新的数据集中做出预测,在某些情况下甚至不需要额外的训练数据!(少镜头学习是这种技术的一种变体,只需要少量带标签的训练数据样本)。下面是迁移学习的精彩介绍 https://medium . com/@ alexmoltzau/what-is-Transfer-Learning-6 ebb 03 be 77 ee。
- 移除冗余特征:是的,我们知道深度学习者不需要广泛的特征工程,但如果你有成千上万个特征(并且你清楚地知道其中只有 20 个对你拥有的数据有逻辑意义),那么为什么不手动移除剩余的无用特征呢?或者利用一些特定的技术来识别该领域的关键特征(https://dzone . com/articles/feature-engineering-for-deep-learning是一个很好的资源)?
最后,
保持简单愚蠢!
不要急于在你的人工智能模型获得高精度后就直接应用于生产。前面已经概述过,在现实生活和业务中,很多时候,在您的个人电脑中使用数据 X 时工作的东西,在实践中可能会在行业中使用非常相似的数据 Y 时吸收性能。AI 不错,但并不总是最好的。我们需要通过超越准确性的思考使它变得更好。作为研究人员、工程师和数据科学家,我们的目标应该是建立透明、可解释和可扩展的人工智能模型。只有这样,我们才能利用人工智能造福社会,让我们周围的世界变得更美好。
精准+透明=值得信赖的 AI!
就是这样!希望这篇文章能让你意识到可解释人工智能在日常生活中的价值。
如果你愿意,你可以通过 LinkedIn 联系我:http://linkedin.com/in/joyjitchatterjee/
人工智能相机发晕,把裁判的光头误认为足球
当人工智能出错时:从混淆面孔到错误逮捕

跟着球走。嗯..头?(来源:推特)
自从神奇宝贝在一次广播中诱发癫痫发作以来,电视还没有引起如此大的轰动。最近,观看因弗内斯喀里多尼亚蓟足球俱乐部直播的球迷也看到了令人眼花缭乱的展示,当时一个自动摄像系统不断将裁判的光头变成焦点,而不是足球。
AI 跟踪解决方案在喀里多尼亚体育场使用 Pixellot 相机系统和球跟踪人工智能来传输直播高清镜头,然后向季票持有者广播。根据这两个团队的网站,在“两次成功的测试活动之后”,这项技术已经准备好进入黄金时间了
但在最近一场对阵艾尔联队的比赛中,人工智能辅助摄像机一直将边裁的头误认为是比赛中的球。人工智能摄像机操作员完全错过了一个目标。
在这种情况下,问题是由于球的颜色和裁判的头部相似,而且摄像头的角度使其看起来好像巡边员在球场上的界限内,这也没有帮助。
相机 AI 在错误的时间被颜色和错误的地点弄糊涂了。这种情况还发生在哪里?
在摄像机能够辨别秃顶男人的圆顶和足球之间的区别,并确保这种技术的道德使用之前,也许我们应该暂停摄像机?
当人工智能出错时
今年早些时候,底特律警方利用一家珠宝商的安全摄像系统的面部识别技术,确定了谁偷了价值 3800 美元的商品。密歇根州立警察犯罪实验室处理了这段视频,这导致了罗伯特·威廉斯在他家前草坪上和他年幼的女儿玩耍时被立即逮捕。
没有不在场证明的要求,警察也没有问威廉姆斯是否有一顶红色的红衣主教帽,就像犯罪分子在监控录像中戴的那样。由于人工智能的高得分准确性,没有必要这样做。为什么不呢?正如我上个月所报道的,同行评议的研究现在表明,机器学习在诊断疾病方面比你的医生更准确。
但是在底特律盗窃案中使用的人工智能推理的问题是什么?监控录像里的人毕竟不是威廉姆斯。他是无辜的。
作为底特律人,威廉姆斯说他永远不会被抓到戴圣路易斯红雀队的帽子。
证据 B: Williams 有一份带有数字签名的不在场证明——一段他在下班回家的路上发布到 Instagram 上的视频,与入店行窃同时发生。
证据 C: 用于对比的 DMV 牌照数据库中 Williams 的图像看起来一点也不像嫌犯。除了两张照片都是黑人以外。
“你认为所有的黑人看起来都一样?”威廉姆斯在被警方审讯和拘留了 30 个小时后说道。
“我猜是电脑弄错了,”侦探回答道。
纽约时报引用的研究称,学术和政府研究表明,面部识别系统引入了偏见,错误识别有色人种的频率高于白人。此外,他们认为这是第一个已知的基于面部识别技术的错误而被错误逮捕的案例。
对威廉姆斯的指控已经撤销,并将从他的记录中删除。该案件的检察官也发表了道歉,但威廉姆斯的律师说这还不够。美国公民自由联盟已经对 DPD 提起诉讼,要求不再使用人工智能软件。
人工智能相机暂停
对威廉姆斯的指控已经撤销,并将从他的记录中删除。该案件的检察官也发表了道歉,但威廉姆斯的律师说这还不够。美国公民自由联盟已经对 DPD 提起诉讼,要求不再使用人工智能软件。
一些技术领导者似乎同意这一观点。今年夏天,这两家科技巨头在几天之内就宣布打算停止销售基于人工智能的面部识别技术。
6 月,微软总裁布拉德·史密斯表示,在联邦法律规范面部识别人工智能的使用之前,该公司不会向警察部门出售面部识别人工智能。史密斯认为,这些法律必须“以人权为基础”
同样,亚马逊宣布暂停其面部识别人工智能解决方案 Rekognition 一年,以允许国会参与此事。 IBM 表示,出于对隐私的担忧,他们将完全退出面部识别业务。IBM 首席执行官 Arvind Krishna 透露,该公司不会参与将该技术用于“大规模监控、种族定性、侵犯基本人权”或“歧视或种族不公正”的潜在用途。
在摄像机能够辨别秃顶男人的圆顶和足球(足球是给池塘另一边的人们看的)之间的区别,并确保这种技术的道德使用之前,也许我们应该暂停摄像机?
人工智能聊天机器人对虚假信息进行情感分析。
通过社交媒体传播的假新闻已经成为一个严重的问题。在本文中,我们将了解如何通过对转发的消息进行“事实检查”来进行情感分类,并将该解决方案作为聊天机器人集成到 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 中。
我们将浏览我为这个解决方案构建的架构,并尝试解决社交媒体中转发消息的真实性和正确性。
这个语料库很小,而且是从 PIB 官方推特页面上经过核实的事实中提取的。
AI chatbot :顾名思义,它是一种通过文本或语音交互来模仿人类对话的 AI 软件程序。聊天机器人变得越来越突出的原因是因为它们可以全天候工作,节省时间和金钱,将企业与客户、员工、家庭自动化等联系起来。
限制范围,我们集中于情感分析,而不是对话机器人。我将解决这个问题,以检测短信是假的还是事实,而不是意图分类。
聊天机器人方法:选择方法是主动的(例如,对用户请求的建议)还是被动的(仅仅响应用户请求)。对于事实检查用例,我们采用反应式方法,因为我们只需要做出反应,告知消息是否是事实。
以下是架构:

让我们从模块开始,详细了解每一个模块:
设计模块:该模块控制对话流程,主要关注请求和响应,基于规则,也可用于意图分类。但是,我限制了流量,以解决消息的真实性。
通信模块:由于通信非常轻量级,所以我使用了无服务器架构。我们可以用谷歌云功能(或 AWS Lambda)来托管代码。API 可以通过 REST 调用,这简化了我们的过程。
- 初始化函数:将训练好的模型和标记器从云存储中复制到临时目录中。
- 更新功能:更新最新型号。这可以通过 REST API 调用,它将更新的模型从存储桶复制到临时目录。
- Webhook:这个函数通过后端系统处理用户的请求和响应。它还记录用户请求并跟踪对话。
- 匹配功能:本模块的重要组成部分。它清理文本,使用经过训练的标记器和模型来预测消息是真是假。
部署模块:处理模型、数据集、模型训练和云基础设施管理的部署。使用官方 twitter API,我们从官方源页面获取新的 tweets,将数据提取到相关部分,并将数据集存储在 DB 中。为了 CI/CD,组件被集装箱化。我将在以后的文章中详细介绍这个模块。
NLU 街区:建筑的大脑

NLU 组件:图片版权@ Sudhir Kakumanu
简而言之,这个模块负责对转发的消息进行情感分析。执行流程如下:
- 数据集:我们获取数据集进行事实检查。这个数据集是从印度 PIB 的官方 twitter 句柄策划的。
- 文本处理:对数据集进行处理,即删除特殊字符、调整编码、词条分类、解构缩写、社交信息俚语等。
- WordCloud 是从这段文字中准备出来的,并经过分析,看看是否有我们可以去除的异常值。




词云和频率分布
4.迁移学习:我们将使用在谷歌新闻数据集(约 1000 亿字)的一部分上训练的预训练向量。该模型包含 300 维向量,包含 300 万个单词和短语。
5.应用 PCA 并分析主成分,以检查数据集是否有任何协方差,简单来说,我们检查是否有任何公共因子。

主成分分析
6.嵌入和矢量化器:从预训练的模型中提取嵌入,并对训练语料进行矢量化,得到嵌入矩阵。这个嵌入层充当我们的神经网络的初始层。这是一个 Word2Vec 表示,用于提取单词的语义信息。
- LSTM &神经网络:为了捕捉文本序列化信息,我们将使用 LSTM(基于 RNN 的模型)来理解句子的上下文,即从先前的神经元记住的单词序列,并将其传递给未来以进一步分析数据。
自定义数据集的单词嵌入是在训练神经网络时学习的。
- 训练过程是这样的,用我们拥有的语料库的大小(单词*维度)创建一个空的嵌入矩阵。
- 获取谷歌新闻预训练嵌入中存在的词的向量/嵌入,未知词被零初始化。
- 现在,神经网络被训练,单词的嵌入或同现随着上下文更新(当添加 LSTM 时)。
模型摘要:
模型摘要
训练精度:
模型训练历史
使用下面的混淆矩阵可以达到 98%的准确度:

演示视频:
对转发消息的模型的进一步测试:
训练消息 : 声明:Whatsapp 上正在流传一份所谓的 3 周 5 阶段“路线图”,据称是由政府制定的,旨在放松#COVID19India 限制。
Whatsapp 转发消息 : 放松新冠肺炎限制的政府路线图将进行为期 3 周的审核流程,当前阶段将于以下日期开始:第 1 阶段–5 月 18 日第 2 阶段–6 月 8 日第 3 阶段–6 月 29 日第 4 阶段–7 月 20 日第 5 阶段–8 月 10 日如果冠状病毒病例开始增加,我们将恢复到前一阶段设定的限制
训练信息 : 声明:一名#WhatsApp 转发者称,从周六开始,孟买将进行为期 10 天的军事封锁
Whatsapp 转发消息 : 从周六起整个孟买军事封锁 10 天,请储备所有物品,只有牛奶和药品可用
结论 :我们能够成功检测出一条用不同语法和短语编写的 Whatsapp 转发消息
感谢阅读,如果你喜欢这篇文章,请鼓掌。
页(page 的缩写)关于程序代码,请参考我的笔记本。
分类数据的聚类分析(上)
CRL 元卡片组的聚类分析
使用 Clash Royale 原始数据提取最新的元卡片组
-
- *代码在 Clash Royale 介绍之后开始:如果您不感兴趣,请跳过
我的资料库里有完整的代码。笔记本名为:CRL_Clustering。
在本文中,我将创建一个人工智能,给定一个 Clash Royale 匹配的数据集,它将识别哪些是主要的聚类。所有数据都是分类的,因此我不会使用传统的因子分析技术,而是使用 K-Node 算法。
视频游戏中的元卡片组介绍
在解释我将要创建的人工智能背后的代码之前,我需要澄清什么是元甲板,以及它们如何与这个项目相关。专业的电子游戏玩家已经把对竞技电子游戏的研究变成了一门真正的学科。
在视频游戏中,你需要从一堆卡片中准备你的牌组,有大量的可能组合,从这个可能性的海洋中出现了一小批帮助玩家获得竞争优势的组合:所谓的元牌组。
我将创建一个人工智能,可以找到哪些是在名为皇家冲突的竞争游戏中使用的元甲板,从原始数据中提取它们。
皇家冲突,选择 8 张牌
在这个游戏中有 98 张卡(直到 2020 年 5 月,游戏每隔几个月增加一张卡)。每个玩家必须组成一副 8 张牌,与其他玩家对战。

由 8 张牌组成的一副牌的例子,从:【www.theclashify.com】T4 检索
有多少副牌?

简单组合的公式
可能的套牌数量是 6345015248033280,顶级玩家从这些组合中找出元套牌。元牌经常变化,所以职业玩家需要保持更新,继续研究游戏。

皇家竞技对决中著名的元牌示例,图片来自www.statsroyale.com
meta 套牌是怎么诞生的?
不幸的是,没有数学方法来确定哪些是最好的套牌。冠军拥有的唯一可能性是尝试他们中的许多人,看看哪一个比其他球员表现得更好。
从本质上讲,通过不断的迭代,元牌是那些允许顶级玩家持续获胜的牌,因此允许他们在竞争对手的等级中攀升至顶级。因此,这些特定的套牌在社区中数百万场比赛中幸存了下来。

正如你所看到的,在某件事情上变得优秀,即使是在电子游戏上,也需要很多努力、承诺和学习。
玩家如何知道哪些是元套牌?
最后,玩家社区(不仅仅是前 100 名)如何找出每个赛季的元套牌?由于使用了 Youtube、脸书小组和 www.statsroyale.com 等皇家冲突的统计网站,人们可以看到顶级玩家玩什么以及他们的胜率。然后,这些套牌被社区中的所有玩家复制和使用,无论是普通玩家还是专家,直到职业玩家级别。

检索自:【https://clashroyale.fandom.com/wiki/2v2
使用聚类从原始数据中提取元数据组
现在让我们假设我们对这款电子游戏一无所知,也不知道这一季的主打牌是什么。我拥有近 700 场顶级球员的比赛(669 场)。
我的人工智能要做的是找出哪些牌组被玩得更一致,并隔离它们。
变异问题

原始 meta-deck 的一个常见变体:X-Bow,从 www.statsroyale.com取回的图像
让我们记住,任何人都可以编辑他们的卡片组,所以玩家可以很容易地创建一个元卡片组的独特变体,我们不想在计算中考虑它,所以我们需要一个算法来找出哪些是原始卡片组,而不是变体。我们假设变奏曲会以较低的频率播放,而原始牌组会以最高的频率播放。

变化的层次
在元牌的层级中,由于数百万玩家可能的变化和实验的频率,变化的程度可以达到数百个深度。
整个程序
- 使用 API 下载匹配数据集
- 预处理:对每一行进行个性化排序
- 预处理:整个数据集的标签编码
- 预处理:整个数据集的 one_hot 编码
- 执行聚类分析
- 训练 K 节点算法
- 调整聚类数以获得准确的结果
- 估计最高元牌组
在本文中,我将讨论第 3 步:对整个数据集进行标签编码。在教程的下一部分,我将完成人工智能。
1.匹配数据集
为了方便起见,我已经下载并准备了数据集,我们将使用它对分类数据进行聚类。如果您希望下载您自己的 Clash Royale 比赛数据集,请按照这个完整的指南来创建一个下载数据的 API。
X = pd.read_csv('/content/drive/My Drive/Colab Notebooks/CRL daily collector/CRL (1).csv')

查看 CRL.csv
目前,数据集包含了太多的信息:我们需要去掉所有不包含关于球员 n. 2 的数据的列。原因是我下载了被选为玩家 n.1 的几个玩家的最近 25 场游戏。一个玩家通常玩一个原型,如果我们的整个数据集重复包含单个用户玩的牌组的比例太高,我们的数据集中元牌组的方差将会大大降低。
X = X[['p2.card_1', 'p2.card_2', 'p2.card_3', 'p2.card_4', 'p2.card_5', 'p2.card_6', 'p2.card_7', 'p2.card_8']]
X
我们将只查看玩家 n. 2 的牌组列表。
-
- *在我的例子中,我将数据与我的 Google Drive 连接。您应该根据存储您的的位置编辑第一行。csv 文件。
2.预处理:订购套牌
不幸的是,我们收集的数据非常混乱。每一行中的牌的顺序对应于一场比赛中打出的牌的顺序。玩家可以开始使用军队,但也可以开始使用法术。为了看得更清楚,我们需要按照特定的顺序将卡片分类。
-
- *特征的顺序不影响最终结果。然而,我相信这一步是必要的,以便清楚和全面地看到最终结果。
将每张卡转换成它的类型
在游戏中,基本上有四种类型的卡。它们被概念化,以允许人们创建适当的甲板。
- 获胜条件
- 部队
- 建筑物
- 拼写
因为我所拥有的数据集没有显示卡片的类型,所以我们需要创建一个能够将每张卡片转换为其相应类型的算法。
例子
这就是我所说的将每张卡映射到其类型的意思:使用下面的模拟列表:
['Zap', 'Knight', 'Giant', 'Earthquake', 'Musketeer', 'Ice Spirit', 'Skeletons']
…相应的类型将是:
['Spell', 'Troop', 'Troop', 'Win Condition', 'Spell', 'Troop', 'Troop', 'Troop']
转换算法
我创建了一个名为 CRL_Cards_Classification.csv 的. csv 文件,该文件将每个现有的卡与其对应的类型进行映射。
#https://docs.google.com/spreadsheets/d/1wIH69gfuCCoPRoWOIyUqQHMKkUfpb4GAxUbBYX8PwRc/edit#gid=1477229539
C = pd.read_csv('/content/drive/My Drive/Colab Notebooks/CRL daily collector/CRL_Cards_Classification.csv')cards_classifier = C.copy()
#getting rid of the first column, useless
cards_classifier.pop('Type_1')
cards_classifier = cards_classifier.values.transpose()
cards_classifierdef order_row(list1):
#mapping input list made of cards with their type
card_dictionary = dict(zip(cards_classifier[0], cards_classifier[1]))
card_dictionarylist_tot_classification = list()
for m in list1:
a = card_dictionary.get(m)
list_tot_classification.append(a)
list_tot_classification
个性化排序
对于数据集中的每一副牌,我希望所有的牌都按顺序排列:胜利条件,队伍,建筑,法术。
为此,我们将首先为每种类型分配一个升序值,这样我们就知道哪种类型最先出现:
class_dict = {'Win Condition': 0, 'Troop': 1, 'Building': 2, 'Spell': 3}
list_tot_num = list()
for m in list_tot_classification:
a = class_dict.get(m)
list_tot_num.append(a)ordered_list = [x for _,x in sorted(zip(list_tot_num, list1))]
return ordered_list
例子
list1 = ['Arrows', 'Baby Dragon', 'Bomber', 'Golem', 'Lightning', 'Mega Minion', 'Mini P.E.K.K.A', 'Night Witch', 'Cannon']
ordered_list = order_row(list1)
会变成:
ordered_list
['Golem', 'Baby Dragon', 'Bomber', 'Mega Minion', 'Mini P.E.K.K.A', 'Night Witch', 'Cannon', 'Arrows', 'Lightning']
3.预处理:对整个数据集进行排序
#sort each row in the dataset based on type order
for c in range(len(X.values)):
X.values[c] = order_row(X.values[c])
X = pd.DataFrame(e.X.values)
-
- *如果我们想按字母顺序对列表进行排序,我们将使用下面的代码,而不是 order_now
X.values[c] = sorted(X.values[c])
3.预处理:标注整个数据集
现在,我们已经根据易于理解的层次结构对数据集进行了排序,我们可以开始对其进行预处理。我们现在将标记整个数据集,稍后您会明白为什么,这将比标记单个行更有问题。
通常,工程师使用 scikit-learn 工具来轻松标记分类数据。不幸的是,scikit-learn 和其他工具一次只允许标记一列。这是一个例子,说明为什么它可以代表一个问题:

可以看到,在第一列 b = 1,在第二列 b = 0。原因是该算法将标签应用于每个单独的列,而不考虑其他列中的值。
正确的标签
为了获得准确的标注,我们需要将所有内容平铺到一列中,然后应用标注并重新构建初始数据集:

这将使用下面的代码来执行:
#flat everything in one list
one_row = list()
for k in e.X.values:
for n in k:
one_row.append(n)
one_row = pd.DataFrame(one_row)
one_row#labeled list
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit(one_row[0])
one_row_labeled = le.transform(one_row[0])
one_row_labeled#rebuild the original dataset and convert it to DataFrame
import numpy
X_labeled = numpy.array_split(one_row_labeled, (len(one_row)/8))
X_labeled = pd.DataFrame(X_labeled)
X_labeled

现在,我们已经成功地正确标记了我们的每个特征,我们可以执行 one_hot 编码来将我们的数据集输入到 AI 中。
在我的下一篇文章中,我将描述整个过程,但是,在我的知识库中的笔记本上,你已经可以找到第二部分了。
-> 转到第二部分
分类数据的聚类分析(第二部分)
CRL 元卡片组的聚类分析
使用 Clash Royale 原始数据提取最新的元卡片组
整个过程
我的仓库里有完整的代码。笔记本名为:CRL_Clustering。
- 使用 API 下载匹配数据集
- 预处理:对每一行进行个性化排序
- 预处理:整个数据集的标签编码
- 预处理:整个数据集的 one_hot 编码
- 执行聚类分析
- 训练 K 节点算法
- 调整聚类数以获得准确的结果
- 估计最高元牌组
到目前为止,第一部分涵盖了第三步:对整个数据集进行标签编码。在本教程的最后一部分,我将介绍接下来的五个步骤。
4.预处理:整个数据集的 one_hot 编码
在步骤 3 中,我们已经标记了数据集中的每个元素,获得了以下结果:

为了将我们的数据集输入到 AI 中,我们需要使用 one_hot 编码。只有这样,模型才能处理分类数据。我们所有的列都是可互换的:这意味着我们将需要一大块 one_hot 变量。
如果我们必须对每一列都应用 one_hot 编码,我们将会得到每一列一个 one_hot 块:这就是我们现在想要的。对于 8 个现有要素,列之间的数据将被认为是独立的,标签将应用于各个列,而不是单个数据集:

从上图可以看出,如果我们必须对每一列应用 one_hot 编码,就会出现这种情况。在上面的例子中,b 在两列中,但它将被分解为 1_b 和 2_b,b 将被拆分为两个独立的变量。这意味着一张卡片。第一列中的巨人和第二列中的巨人将完全不同。因为事实并非如此(卡片组的顺序不应该影响元卡片组的选择),所以当数据集中的相同变量位于不同的列中时,我们必须找到一种方法来避免它们的分离。
print(max(one_row_labeled+1), len(X_labeled))
95 664
我们的数据集总共有 94 张牌在任何可能的牌组中被玩家使用。这意味着每一行必须有 94 列,每一列代表一个虚拟变量。
# one_hot of multiple columns at the same time
#create an empty dataset of equal lenght of max. label (94), but equal width of our X (664)
m = [[0 for x in range(max(one_row_labeled)+1)] for x in range(len(X_labeled))]
我首先创建了这个空数据集作为多维数组:

我现在将遍历 x 的每一行。每一行将包含 8 个不同的数字,我将找到相应的虚拟变量行并将其设置为 1。
#turn each corresponding label to 1
for row in range(len(X_labeled.values)):
for num in range(len(X_labeled.values[1])):
m[row][X_labeled.values[row][num]] = 1
m = pd.DataFrame(m)
m
在正确的位置添加了 1 之后,我将把列表转换成数据帧。这就是我们最终得到的结果:

现在我们可以把它输入到模型中。
5.执行聚类分析
现在我们已经准备好了数据,我们需要确定最佳的集群数量:
#graph the number of clusters
from sklearn.cluster import KMeans
import matplotlib.pyplot as pltwcss = []
for i in range(1, 100):
km = KMeans(n_clusters = i, init = 'k-means++', max_iter = 300, n_init = 20, random_state = 0)
km.fit(m)
wcss.append(km.inertia_)plt.plot(range(1, 100), wcss)
plt.title('The Elbow Method')
plt.xlabel('No. of Clusters')
plt.ylabel('wcss')
plt.show()

我们正试图通过肘方法来评估最佳集群的数量。通常,我们会寻找图中曲线弯曲最厉害的地方。不幸的是,我们可以立即看到,没有明确的迹象表明有一定数量的集群(也许大约 20 个集群有一个可能的弯曲)。特别是在 K 模式中,由于特征的分类性质,很难估计最佳的聚类数目。我们需要通过多次迭代并比较结果来找到最佳的聚类数。
6.训练 K 节点算法
!pip install kmodes
-
- *因为我正在使用 Google Colab,所以我将使用上面的代码安装 kmodes 包,但是,根据您是在本地机器上还是远程运行您的算法,它可能会有所不同。
将每一行与其所属的聚类进行映射
现在让我们在数据集上运行一个使用 K-Mode 的实验。我需要指出对数据集进行分组的聚类数。本质上,输出是一个 664 个数字的数组。每个数字映射一行及其对应的分类。
#mapping each row to its correponding cluster
from kmodes.kmodes import KModes
test=KModes(n_clusters=20, init='Cao') #Huang in another possibil
cluster=test.fit_predict(m, categorical=list(m.columns))cluster
array([11, 0, 11, 4, 5, 3, 3, 11, 11, 9, 11, 11, 16, 5, 5, 0, 6, 1, 11, 3, 15, 0, 8, 1, 8, 0, 15, 5, 7, 15, 8, 17, 1, 15, 5, 2, 19, 13, 1, 9, 7, 16, 7, 1, 16, 3, 5, 1, 8, 7, 6, 16, 18, 7, 0, 3, 3, 3, 13, 19, 15, 11, 8, 4, 14, 4, 2, 14, 5, 7, 6, 1, 8, 1, 3, 8, 4, 3, 5, 19, 2, 1, 5, 0, 1, 6, 14, 8, 3, 4, 7, 4, 1, 14, 1, 5, 11, 18, 5, 1, 0, 2, 12, 3, 8, 9, 2, 4, 7, 7, 16, 11, 4, 11, 11, 1, 16, 6, 0, 16, 12, 0, 3, 7, 18, 1, 12, 0, 16, 18, 16, 3, 4, 7, 1, 1, 1, 2, 3, 19, 5, 11, 4, 16, 4, 0, 3, 12, 0, 12, 0, 12, 5, 2, 14, 11, 12, 15, 1, 11, 7, 2, 12, 0, 3, 3, 12, 7, 7, 18, 1, 16, 7, 17, 1, 12, 11, 14, 15, 3, 5, 0, 8, 14, 2, 2, 0, 4, 7, 16, 8, 11, 0, 6, 1, 5, 19, 7, 7, 16, 0, 2, 11, 4, 7, 5, 1, 8, 14, 0, 0, 19, 11, 7, 15, 5, 9, 2, 11, 7, 19, 14, 3, 11, 11, 1, 9, 5, 12, 12, 7, 12, 14, 14, 11, 0, 8, 3, 4, 11, 4, 5, 8, 15, 15, 14, 7, 4, 3, 6, 3, 5, 7, 4, 6, 15, 5, 13, 11, 4, 16, 7, 0, 14, 16, 7, 3, 9, 15, 0, 7, 0, 1, 8, 15, 5, 11, 3, 6, 4, 12, 15, 1, 2, 7, 1, 6, 1, 3, 8, 1, 0, 17, 5, 5, 14, 11, 3, 4, 2, 3, 7, 7, 11, 3, 0, 4, 1, 3, 7, 7, 4, 8, 3, 0, 3, 3, 9, 12, 3, 7, 7, 8, 12, 2, 3, 2, 19, 5, 7, 2, 14, 7, 2, 4, 1, 5, 19, 3, 2, 13, 5, 5, 3, 19, 4, 2, 15, 19, 1, 0, 12, 13, 8, 13, 0, 17, 7, 14, 3, 4, 0, 14, 12, 0, 1, 8, 12, 4, 3, 17, 15, 7, 4, 3, 14, 0, 12, 0, 9, 1, 14, 4, 12, 7, 4, 3, 2, 3, 15, 16, 2, 4, 0, 2, 15, 12, 7, 15, 2, 1, 1, 4, 0, 19, 6, 5, 11, 12, 8, 3, 16, 2, 3, 19, 0, 0, 1, 3, 17, 11, 10, 2, 15, 2, 0, 3, 7, 4, 17, 5, 5, 1, 8, 6, 6, 12, 5, 13, 19, 2, 6, 3, 3, 4, 3, 12, 17, 5, 15, 0, 19, 6, 0, 3, 2, 3, 0, 12, 11, 2, 14, 1, 1, 0, 7, 7, 12, 8, 4, 1, 12, 14, 17, 17, 8, 0, 2, 3, 2, 0, 16, 2, 6, 2, 0, 6, 3, 1, 0, 8, 3, 7, 11, 15, 0, 11, 11, 7, 2, 6, 5, 11, 4, 3, 5, 17, 15, 2, 0, 11, 11, 4, 3, 16, 19, 8, 15, 14, 0, 5, 13, 2, 0, 2, 14, 19, 8, 0, 1, 1, 14, 6, 15, 19, 19, 2, 0, 1, 1, 11, 5, 3, 3, 6, 8, 8, 1, 0, 19, 7, 2, 8, 4, 0, 12, 12, 12, 14, 4, 2, 16, 9, 0, 0, 4, 0, 2, 8, 4, 0, 2, 15, 4, 13, 15, 3, 0, 0, 4, 5, 6, 9, 0, 4, 14, 19, 1, 15, 15, 14, 2, 17, 4, 0, 15, 2, 12, 8, 14, 2, 1, 15, 2, 2, 2, 11, 12, 6, 0, 0, 12, 3, 17, 14, 11, 4, 0, 2, 4, 17, 0, 3, 5, 16, 0, 12, 0, 17, 17, 6, 4, 0, 16, 16, 0, 14, 3, 12, 11, 19, 6, 8, 2, 0, 4, 0, 7, 17, 1, 0, 15, 16, 13, 1, 7, 16, 0, 14, 6, 0, 0, 16, 5], dtype=uint16)
了解 20 个集群
现在,我们如何隔离集群并了解它们需要具备哪些特征?
test.cluster_centroids_
array([
[0, 0, 0, …, 0, 0, 0],
[0, 1, 0, …, 0, 0, 0],
[0, 0, 0, …, 0, 0, 0],
…,
[0, 0, 0, …, 0, 0, 0],
[0, 0, 0, …, 0, 0, 1],
[0, 0, 0, …, 0, 0, 1]
])
这 20 个 one_hot 数字列表描述了每个单个集群的特征。每一个都由 94 个元素组成,其中一些是 1,大多数是 0。如果对于每个列表,我们将把这 94 个二进制值转换成数字,然后把数字转换成卡片名称,我们将得到 20 副元牌。
将数字转换为卡片名称
目前,结果对我们来说是不可理解的。我们需要把它们翻译成我们能理解的语言。下面的算法采用 K 模式算法的输出,并将其转换为原始字符串:
#convert one_hot numbers to final decks
def archetypes(knode_list):
archetypes_list = list()#for each 1 inside the one_hot cluster form return its number
#not all clusters have the same lenght
#store all number is arrays
cc = list()
for n_centroids in range(len(km.cluster_centroids_)):
for k in range(len(km.cluster_centroids_[n_centroids])):
if km.cluster_centroids_[n_centroids][k] == 1:
cc.append(k)
len(cc)#determines number of chunks per cluster
n_chunks = list()
for am in range(len(km.cluster_centroids_)):
n_chunks.append((list(km.cluster_centroids_[am]).count(1)))
n_chunks#creates the meta-decks
from itertools import islice
it = iter(cc)
sliced =[list(islice(it, 0, i)) for i in n_chunks]
slicedsliced_list = list()
#convertion numbers to card names
for o in sliced:
sliced_list.append(order_row(list(le.inverse_transform(o))))#we only conserve the win conditions
card_dictionary = dict(zip(cards_classifier[0],
cards_classifier[1]))
card_dictionary#an absurd way of making a copy of our dataset, .copy() does not work
list_tot_classification = [x[:] for x in sliced_list] #un modo assurdo per fare copia, altrimenti non funzionafor o1 in range(len(list_tot_classification)):
for o2 in range(len(list_tot_classification[o1])):
a = card_dictionary.get(list_tot_classification[o1][o2])
list_tot_classification[o1][o2] = aonly_win_conditions = list()
#only conserve lists with win conditions
for o3 in range(len(list_tot_classification)):
if 'Win Condition' in list_tot_classification[o3]:
only_win_conditions.append(sliced_list[o3])#we store all the lists with a lenght of 8: full decks
for _ in sorted(only_win_conditions):
if len(_) == 8:
archetypes_list.append(_)return archetypes_list
7.调整聚类数以获得准确的结果
现在,让我们尝试我们刚刚编写的算法的不同配置,并比较结果。我将运行总共 60 个集群,存储每次迭代的结果和元组数:
import numpy as np
from kmodes.kmodes import KModesarchetypes_len = list()
for clus in range (8, 60): ###FUNZIONA IN UN FOR CYCLE, MA NON IN UNA FUNZIONE
km = KModes(n_clusters=clus, init='Cao', n_init=100, verbose=0)
clusters = km.fit_predict(m)#one_hot results to archetypes sorted by win condition
archetypes_list = archetypes(km.cluster_centroids_)
archetypes_len.append(len(archetypes_list))
for _ in archetypes_list:
print(clus, _)
#25 is the optimal number of meta-decks

具有最小数量分类的初始输出的屏幕截图

具有更多分类的输出屏幕截图
正如我们从上一张图中看到的,簇的数量越多,相似元牌的数量就越多。本质上,在某一点上,甲板变化也包括在计算中。
n 簇和 n 元牌
我现在已经将集群的数量存储在了 archetypes_len 中。我将创建一个包含集群范围的列表,这样我们就可以绘制出集群数量和元组数量之间的关系。
import seaborn as sns
archetypes_iteration = [x for x in range(8, 60)]
archetypes_iteration
sns.set(rc={‘figure.figsize’:(11.7,8.27)})
sns.scatterplot(archetypes_iteration, archetypes_len)

这如何转化为我们的元卡片组的层次结构?

集群的正确数量是多少?
- 如果集群的数量太少,我们最终只有几个元甲板。它们将是正确的,可能是列表顶部的那些,但它们仅代表元组池中的一小部分。
- 如果集群的数量太大,我们不仅会列出顶层,还会列出它们的所有变体,最后会列出一个模糊了元层概念的层。
只有在数量合适的情况下,我们才能对当前赛季中使用最多的元套牌有一个概念。

一副元牌示例:从:www.reddit.com检索
8.估计顶级元牌
最后,在查看了数据之后,我选择了一些簇,这些簇显示了变化最小的顶层元素。我们可以得出结论,这些是第 11 季的元套牌,即当前的皇家冲突季:
#questo funziona
n_clusters = 25
km = KModes(n_clusters=n_clusters, init='Cao', n_init=100, verbose=0)
clusters = km.fit_predict(m)#one_hot results to archetypes sorted by win condition
archetypes_list = archetypes(km.cluster_centroids_)
for _ in archetypes_list:
print(_)

输出
人工智能分散自治组织和零售业的未来
爱道如何帮助创造完全自主的商店和新的商业模式

西蒙·贝克在 Unsplash 上的照片
由于最近的卫生危机,零售商店自动化的需求已经成为优先事项。事实上,如果零售商想要生存,调整他们的商业模式已经变得至关重要。在这种背景下,我从事了一个与 AI 去中心化自治组织(AI DAO)和零售店相关的项目。
商店可以独立吗?你能投资一个不需要人工的商店吗?用分布式人工智能能让一个店更智能吗?
在这篇文章中,我将解释为什么现有的零售商面临风险,必须紧急投资新的商业模式,解释 AI DAOs 的关键作用,以及零售商如何从中受益。
我们所知的零售店将会消失
由于一系列的封锁和来自在线竞争对手的不断上升的威胁,零售商别无选择,只能接受自动化。总的来说,我们的购物方式正在发生变化。
简而言之,零售业的未来是自动化、更小的商店、数字化体验和更灵活的劳动力。
一些零售商已经决定将他们的商店转变成仓库和配送站,为完全转移到网上的企业服务。其他人已经开始从事半自主商店的工作。
就我所见,自动化的道路往往需要几个计算机视觉算法。利用计算机视觉帮助零售商收集足够的数据,以更好地了解他们的客户。
主要战略要点是尽可能打造最佳客户体验。实现这一目标的唯一方法是收集尽可能多的客户数据,以及他们如何与所有产品互动。
自主店爱道
这种自动化可以更进一步: AI 去中心化自治组织。
A DAO 是一种去中心化的商业模式。它是由管理企业如何运作的智能合同组成的。“道的一切经营决策和财务行动都记录在一个公开的、不可更改的上”( 2 )。
一个 DAO 的每个参与者/投资者都可以就公司的运营方式投上一票。该区块链对所有投资者/代币持有者开放,便于与每个投资者分享所有信息。
一个人工智能 DAO 将是一个使用多个人工智能代理(群体智能)的 DAO。还有其他方法可以创建 AI DAO ( [3](http://Artificial Intelligence (AI) DAOs (decentralized autonomous organizations) - BigchainDB & IPDB Meetup #4 - April 05, 2017) ),但是我们决定专注于这一个。
根据 S. Ponomarev , A. E .沃隆科夫的说法,“多智能体系统通信是一种技术,它为多个交互的智能体提供了一种相互通信以及与环境通信的方式。多智能体系统用于解决单个智能体难以解决的问题。多智能体通信技术可用于管理和组织计算雾,并作为一个全球性的分布式操作系统”( 4 )。
多智能体系统只是 M2M(机器对机器)通信的一种形式。换句话说,它是各种通信人工智能的松散生态系统。

这种形式的 M2M 通信允许学习人工智能实际交换信息,并更快地解决复杂的问题。未来,自主店将与其他组织(供应商等)互动。)在全球 M2M 生态系统中使用人工智能代理。
机器对机器( M2M ) 是设备之间使用任何通信信道的直接通信,包括有线和无线。
对 AI DAOs 的这种需求也来自于 AI 只存在于筒仓中。当前的解决方案通常只能在特定的公司、基础设施或部门内运行。互操作性的缺乏严重限制了全自主商店的发展。
通过协调的人工智能代理,零售商可以外包大量的网络决策,包括治理、投票、安全等具体问题。
想象一个由 AI 去中心化自治组织经营的商店。世界各地的承包商可以负责 AI DAO 拥有的自主商店的维护/物流,并可以直接由 AI DAO 支付费用。
同样的爱道商店可以用钱自主地重新进货,雇佣它需要的服务(清洁、安全、物流等等)并自己支付。
此外,随着越来越多的人投资这家商店,所有的用户都将拥有发言权和投票权,这将影响到艾道的决策。
这样的商店将利用几个人工智能子领域(NLP,计算机视觉等)来适应客户的需求,跟踪支出和偏好。我相信这个实体是基于进化论的。艾道斯永远不会被看做“完了”。服务、产品和价格永远在变化。
除了大多数任务的自动化,决策过程将是非常独特的。这些决定可以使用智能合约来做出。
一个智能契约是一段计算程序,当满足某些条件时自动执行( 5 )。
根据 Joe Liebkind 的说法,AI DAO“通过智能合同可以自动跟踪库存,创建和支付账单,扫描收到的货物等”( 6 )。
通过增加人工智能,DAOs 将创造新的商业模式。很快,我希望看到越来越多的完全独立的企业,每个人都可以投资。或许零售商将不再把他们的顾客仅仅视为消费者,而是让他们拥有一部分自主商店。
我们可能会进入一个新时代,在这个时代,普通客户也可以很容易地成为投资者。这种新的商业模式将适用于许多其他组织。这可能包括分散的对冲基金、分散的公共事业提供商等。
自动化—是的,但是什么和如何自动化?
AI DAOs 必须基于几个 AI 子领域,以覆盖尽可能多的领域。以下是人工智能已经覆盖的一些领域:

人工智能分散自治组织商业模式
通过利用生殖对抗网络(GANs)和 3D 打印,我们可以想象一家商店实时分析市场趋势,并决定制造市场上最流行的商品。自主商店将收集销售数据,并根据访问商店的普通顾客来确定给定产品是否合适。
这家自主商店还可以利用基于机器学习的算法进行动态定价。
我预测 GANs 和艾道斯结合会大量使用。事实上,一些行业可以从这种结合中受益。可以创建自主市场来销售 GANs 制造的商品。
最近,一个网络平台( 7 )设法让一个生成性的对抗性网络(甘)生成艺术。这幅画后来被卖掉了,收入被用来支付所使用的资源。
一个生成对抗网络 ( GAN )是 Ian Goodfellow 和他的同事在 2014 年设计的一类机器学习框架。( 8 )
我还预测有些自主店只会做互动屏。我们可以想象,当顾客走过时,或者根据网上发生的事情,交互式墙会动态地改变它们的内容。这将使新品牌能够进入“实体”商店。位于街道上的随机图腾屏幕将成为一个独立的商店。
问题
根据我的经验,围绕现有技术的有效性/安全性,以及它们能否从小商店扩大到大商店,仍存在大量问题。
一个主要的挑战是精确地看到需要多少次人类店员来解决问题。此外,客户隐私也是需要考虑的因素。可以收集哪些数据?我们如何在多个国家调整我们的数据策略?
另一个问题是缺乏数据。事实上,训练人工智能和开发机器学习算法需要获取大规模的数据,这是极其昂贵的。除了数据扩充,解决这个问题的一种方法是使用合成生成的数据。
合成数据是人工制造的信息,而不是由真实世界事件生成的。
平稳过渡
我相信自动驾驶商店的发展将遵循与自动驾驶汽车相同的道路。今天的挑战是将现有商店转变为半自主商店。
利益攸关方需要找到切实可行的解决方案来实现这一转变,并降低转换成本。再过几年,AI DAOs 可能是一个解决方案。
数据对零售商店的重要性
大多数主要零售商现在已经开始使用计算机视觉进行一些概念验证,以更好地了解他们的客户。他们面临的主要挑战是更好地了解新的购物习惯,同时降低与销售点相关的所有成本。
显然,随着网上购物的出现,风险是以许多不相关的实体销售点告终。我们如何创造新的收入模式和客户体验?我们如何结合线上和线下商店的最佳实践来提高顾客满意度。
AI DAOs 可以帮助你与客户建立新的关系。从简单的顾客到你“自己的”自主商店的投资者…
如果您希望了解更多关于这个主题的信息,我推荐以下链接:
- 封锁如何让购物变得更好
- 有了区块链,无主业务即将出现
- 人工智能(AI) DAOs(去中心化自治组织)—BigchainDB&IPDB Meetup # 4—2017 年 4 月 5 日
- 多智能体系统和分散人工超级智能
- 为什么多智能体系统会让人工智能变得更好
- DAOs、区块链和无主业务的潜力
- 道的运用:艺术之道
人工智能又一次打败了人类
情报的
这一次没有比赛,艾是远远优于
让我们沿着记忆的小路漫步,看看人工智能在面对人类对手的人类挑战中脱颖而出的时刻。
1997 年,世界目睹了国际象棋世界冠军加里·卡斯帕罗夫的失败。人工智能在棋盘游戏中的统治地位在 2015 年和 2016 年再次出现,DeepMind 的人工智能系统 alpha GO击败了职业围棋选手范辉和世界冠军围棋选手 Lee Sedol 。
人工智能对人类的统治不仅限于棋盘游戏,2011 年,IBM Watson,一个能够回答琐碎问题的计算机系统在一场危险游戏中击败了布拉德·鲁特和肯·詹宁斯。
我们可以在人工智能战胜人类的不断增长的清单上再增加一个日期。
2020 年 8 月 20 日,人工智能在模拟空战中击败人类 F-16 喷气式战斗机
DARPA alpha dog fight是一系列测试 AI 算法执行格斗机动、战斗和策略的能力的试验。
决赛于 2020 年 8 月 18 日至 20 日在八个团队之间举行,获胜团队 Heron Systems AI 与一名人类战斗机飞行员对决。

DARPA 的 AlphaDogFight 的目的是找到开发人工智能系统的方法,可以将空战和机动的责任从人类飞行员转移到人工智能系统。不可避免地在飞行系统中建立对人工智能的信任。
人类飞行员被命名为“Banger ”, Herons 系统的人工智能被命名为“Heron”。Heron 和 Banger 之间的对峙发生在模拟环境中,两名飞行员都控制着一架 F-16 战斗机。
这最后的挑战旨在测试苍鹭的机动能力、战斗系统和对人类对手的决策能力。挑战持续了五轮,人工智能飞行员 Heron 以无可争议的方式击败了 Banger。
该赛事的评论员预测,邦格和海伦之间的对决将是“一场势均力敌的战斗”。
在所有回合之后,Heron 在所有五轮挑战中都取得了完美的胜利。
据解说员称,Heron 表现出超人的能力,能够非常准确地射击和瞄准,同时表现出高度动态的机动性。
“显示出超人的能力”
在一些回合中,Banger 改变了战术和策略,以便在与 Heron 的比赛中占据上风。在上一轮比赛中,Banger 的战术变化导致了一轮比赛,突出了 Heron 能力的一些限制。这一轮仍以海伦获胜而告终。
在所有五轮中,Heron 没有损失任何生命,这意味着 Banger 没有一发子弹击中 Heron 的战斗机。
把它带回地球
尽管 Heron 取得了压倒性的胜利,但人们注意到人工智能系统具有“完美的状态信息”,这意味着人工智能系统具有模拟环境的不间断的定量和视觉数据。
在现实世界中,拥有关于环境和其他变量的完整信息并不常见。
现实的不可预测性会影响军事力量如何从模拟环境中获取信息和看似“良好”的性能。
简单地说,我们不会很快在模拟之外看到任何驾驶 F-16 战斗机的人工智能系统。

战斗中的 F-16 喷气式战斗机
DARPA AlphaDogFight 试验的进步和经验教训将为未来的发展开创先例,这些发展可以带来更可靠的人工智能系统,可以在模拟环境之外与战斗机飞行员携手合作。
获胜队
决赛于 2020 年 8 月 18 日至 20 日举行,有八支队伍参加。在三天的时间里,团队的人工智能系统分别面对其他人工智能算法,然后在循环赛中相互面对。
最后一天,前四名的队伍在淘汰赛中对决,获胜的队伍面对人类对手。
参与最终 AlphaDogTrial 活动的团队:

Heron Systems AI agent 是一种基于深度强化学习的人工智能,它通过在模拟环境中不断训练,获得了超过 30 年飞行时间经验的专业知识。
Heron 团队将他们的成功归因于两个主要因素:规模和多样性。
他们归因成功的比例成分指的是获胜的人工智能代理能够积累的飞行时间的数量。多样性部分说明了 Heron Systems 开发的相互对抗的人工智能代理的数量;每个代理都有自己独特的神经网络架构、奖励系统和构建。
Heron System 的一位发言人表示,该团队的下一步是将人工智能系统整合到可以在现实生活环境中载人的无人机中。
我希望这篇文章对你有用。
要联系我或找到更多类似本文的内容,请执行以下操作:
我们仍然是人工智能中代表最少的种族之一,然而我们可能会因为它的利用和滥用而遭受最大的痛苦。
towardsdatascience.com](/are-there-black-people-in-ai-fb6928166d73) [## 根据吴恩达(斯坦福深度学习讲座),你应该如何阅读研究论文
关于如何通过知名人士发表的研究论文获取知识的指导。
towardsdatascience.com](/how-you-should-read-research-papers-according-to-andrew-ng-stanford-deep-learning-lectures-98ecbd3ccfb3)****
研究发现,人工智能现在比你的医生更好地诊断疾病
同行评议的研究表明,你很快会咨询机器人医生的第二意见

图片来源: upklyak
电子战研究发现,因果机器学习模型不仅比以前基于人工智能的症状检查器更准确,而且在许多情况下,现在可以超过人类医生的诊断准确性。这主要是由于所使用的方法,这些方法允许在诊断中有更多的“创新”,甚至对更复杂的患者疾病有更高的准确性。
在由来自巴比伦健康和伦敦大学学院的研究人员撰写的同行评审研究中,当任务是诊断真实疾病的书面测试案例时,新模型的得分高于 72%的全科医生。
该报告称,到目前为止,尽管进行了大量的研究工作,诊断算法仍难以达到医生的诊断准确性。这是因为机器学习算法试图遵循与医生在症状检查中相同的过程。但是,如果我们让机器去执行哪怕是最不可能的计算——它们的诊断准确率会比人类高。
通过不遵循与人类诊断相关的更传统和可预测的模式,使用反事实方法的新因果机器学习算法可以自由地运用所有可能性。这是夏洛克·福尔摩斯在诊断中可能尝试的方法:“当你排除了不可能,剩下的,不管多么不可能,一定是真相”
反事实机器学习算法在定义“如果”时并不局限于人类的极限场景。
在实验中,医生的平均诊断准确率为 71.40%,而标准关联算法的准确率为 72.52%,是研究中排名前 48%的医生。
但新的反事实算法以 77.26%的平均准确率击败了他们两人,使其成为前 25%的医生,并实现了“专家临床准确性”。对于罕见疾病,这些改善甚至更加明显,因为这些疾病的诊断错误更常见,也往往更严重。
现在,机器比人更有“创造力”
有人可能会认为,由于无限的存储、即时的历史回忆、对数据的访问和计算速度,机器学习比人类医疗从业者更熟练。然而,在这项研究中,反事实的机器学习算法取得了成功,因为它们比医生更具“想象力”。
本质上,反事实机器学习算法并不局限于人类在定义“如果”时的限制场景。“我们让一个人工智能拥有强大的算法,并赋予它想象交替现实的能力,并考虑‘如果这是一种不同的疾病,这种症状会出现吗’?这使得人工智能能够区分病人疾病的潜在原因,并比超过 70%的医生得分更高,”巴比伦健康科学家兼该研究的主要作者乔纳森·里奇斯博士说。
这与典型的人类医生诊断形成对比,在典型的人类医生诊断中,医生“旨在通过确定引起症状的疾病来解释患者的症状。”现有的机器学习算法效仿关联诊断——换句话说,识别与患者症状密切相关的疾病。该研究指出,包括贝叶斯模型和深度学习在内的这些算法基于关联推理(与患者症状和病史的相关程度)来识别疾病。
然而,这项研究中的研究人员将诊断重新定义为“将因果关系与病人的症状分开”像夏洛克一样,反事实可以测试如果某些前提条件不同,特定的结果会发生在哪里。该算法删除了症状的所有可能原因(疾病和外部因素),然后隔离出唯一可能的原因。
根据这项研究,反事实可以量化疾病假说解释症状证据的程度,方法是确定如果有可能干预和治愈疾病,症状就不会出现的可能性。这个排除过程,不管多么不可能,都会导致更有创造性,更重要的是,更准确的诊断。
为什么它很重要
初级保健医生的诊断错误是一个全球性的挑战。根据另一项关于初级保健失误的研究,仅在美国,每年就有 5%的门诊病人接受错误的诊断。对于病情严重的患者,其中 20%被初级保健医生误诊。其中,三分之一的误诊导致了病人的伤害。
另外,医生超负荷工作,供不应求。据美国医学院协会称,到 2033 年,美国将面临 54000 到 139000 名医生的短缺。其中,随着越来越多的美国人接受门诊治疗,将需要多达 55,200 名初级保健医生。虽然今年 6 月发布,但 AAMC 分析是在 2019 年进行的-在冠状病毒袭击之前。因此,预计的缺口可能会更大。
在全球范围内,对医疗保健可及性的关注是最重要的。“世界上有一半的人几乎享受不到医疗保健,”Babylon 首席执行官兼创始人 Ali Parsa 博士说“人工智能将成为一个重要的工具,帮助我们所有人结束医疗保健分配不均的不公平现象,让地球上的每个人都更容易获得和负担得起。”
这项研究
在这项研究中,20 名全科医生创建了 1671 个名为 vignettes 的现实书面医疗案例,其中包括 350 多种疾病的典型和非典型症状。这些小插图模拟了一种疾病的典型表现,可能包括病史、症状和人口统计信息,如年龄和性别。为了模拟真实世界的条件,该列表并不详尽。
每个短片都由一名医生创作,并由其他几名医生验证是否“真实”。每个医生都有资格至少达到全科医生的水平,或相当于委员会认证的初级保健医生。
经过验证后,44 名全科医生(一个单独的小组)每个人都提供了至少 50 例(平均 159 例)进行评估。然后,通过在诊断简介中包含实际疾病的患者比例来衡量它们的准确性。
两个版本的人工智能被用于与全科医生进行比较——一个基于当前标准的算法使用相关性,以及新的反事实因果模型。
结果呢
医生的准确率在 50–90%之间,平均得分为 71.40%。旧的相关算法的表现与普通医生相当,达到 72.52%,位于前 48%的医生中。
新的反事实算法实现了 77.26%的准确率,高于医生的 32,等于 1,低于 11。这一分数使其在人类群体中排名前 25%,根据该研究,“达到了专家临床准确性。”
对于包括罕见疾病、复杂病例或混杂因素在内的较难的小插曲,反事实算法继续表现出色。在这些情况下,与关联算法相比,该算法为 29.2%的罕见疾病和 32.9%的非常罕见疾病提供了更好的诊断。

医生与算法患者诊断准确性(来源数据:Richens,J.G .,Lee,C.M. & Johri,S. 利用因果机器学习提高医疗诊断的准确性
上图用图形表示了算法与医生准确度的关系。线上的蓝色点对应于比算法实现的准确度低的医生,线下的绿色点显示医生比模型更准确的地方。红点指出了医生和机器学习算法达到相同精度的地方。
该研究进一步证明,更简单的医疗案例集导致更高的医生准确性分数,而更复杂的插图导致更高的机器学习分数。
第二种意见,问 Bot 医生?
医生担心被机器取代吗?一位参与这项研究的全科医生说,还没有。“我很兴奋有一天这个人工智能可以帮助我和其他医生减少误诊,腾出我们的时间,帮助我们专注于最需要护理的病人,”Tejal Patel 博士说。“我期待这种类型的工具成为标准,帮助我们增强我们的工作。”
该模型尚未用于商业应用,Parsa 承认,“这不应该被耸人听闻地称为机器取代医生,因为真正令人鼓舞的是,我们终于获得了允许我们提高现有医疗保健系统覆盖范围和生产力的工具。”所以这些工具可以用来增强混合场景,人加机器。
考虑到在这项研究中,医生倾向于在具有简单插图的病例集中实现比机器学习算法更高的准确性。相比之下,对于更复杂的场景,反事实算法比医生实现了更高的准确性。由于病例复杂性之间的反比关系,该研究表明,诊断算法是“对医生的补充,在医生错误更常见的情况下,该算法表现更好,反之亦然。”
这项研究甚至进一步假设:因果和反事实推理可以应用于医学诊断以外学科的机器学习方法吗?另一位研究作者、伦敦大学学院讲师 Ciaran Lee 博士认为是这样的。“这种方法有巨大的潜力来改善其他所有当前的症状检查器,但它也可以应用于医疗保健和其他领域的许多其他问题——这就是为什么因果人工智能如此令人印象深刻,它是普遍的,”Lee 说。
现有的机器学习算法已经开始接近或略微超过人类健康从业者的效率。现在,富有想象力的反事实分析进一步超过了健康从业者的准确性。研究人员指出,未来的实验可以专注于确定混合方法对提高患者诊断准确性的有效性。所以你的医生可能很快就会向机器人医生寻求第二种意见。研究作者假设,很可能“医生和算法的联合诊断比单独诊断更准确。”
人工智能驱动的零售:H&M 集团是如何做到的
零售业中的人工智能:H&M 案例研究

图片由 exels.com的Ibrahim Boran 拍摄
时尚零售商越来越多地求助于人工智能(AI)来满足顾客的需求。人工智能驱动的零售使品牌能够在 21 世纪的经济中竞争,并通过个性化的购物体验来满足现代客户的需求。
随着越来越多的零售公司将其业务从传统的实体零售店转向电子商务,他们能够更深入地了解客户的偏好,以满足需求。
谈论零售中的人工智能将我们带到了时尚行业最受欢迎的品牌之一——H & m。
H&M 集团和他们人工智能驱动的故事
H&M 集团一直在人工智能方面进行大量投资,以保持在时尚周期的顶端,并支持其大规模增长。
自 1947 年成立以来,这家时装零售商一直在欧洲、美国和全球范围内快速扩张。早在 1998 年,他们就开始在网上销售。

照片由 H & M 组拍摄
仅在 2004 年,H&M 就拥有 1000 多家店铺,这一数字呈指数级增长,在全球 72 个国家拥有近 5000 家店铺。截至今天,这家零售巨头雇佣了 177,000 名员工,并为其供应商雇佣的员工提供了 160 万个工作岗位。
但是,一个品牌经理如何保持这种增长,跨越不同的国家、市场甚至大洲?他们如何确保满足如此庞大的购物需求和期望各异的顾客群的需求?最重要的是,他们是如何管理全球数千家店铺的?
对所有这些问题都有答案的人是 H & M Group 的产品领域首席工程师 AI Foundation Errol Koolmeister。他在 2019 年 数据创新峰会 上的讲话中解释说,他们在 2016 年首次开始在业务中采用人工智能。数字化的影响是显而易见的,H & M 集团知道他们必须做些什么来保持相关性。“我们,作为一个公司,作为一个人,开始越来越多地上网”,Errol 描述道。

Hyperight AB 在数据创新峰会上的照片/版权所有
埃罗尔表示:“我们开始发现,拓展实体店的商业模式变得相当困难。”。显而易见的解决方案是,他们需要人工智能来维持增长。
人工智能驱动的零售的到来
意识到他们必须适应新的产业转移,H&M 集团问他们自己一个问题“作为一个公司,我们想去哪里?”这时,零售品牌意识到他们需要在人工智能和高级分析方面提升自己的水平。尽管他们在一些部门表现出色,比如 CRM,但他们知道他们还没有达到规模化。
这是他们开始进行第一次概念验证的时刻。埃罗尔解释说:“我们试图看看是否能从它们身上提取任何价值。幸运的是,H&M 集团挑选的用例是成功的,可以投入生产,使它们盈利。
“这一切都是为了快速行动,”他继续说道。埃罗尔表示:“如果我们在 2016 年只是说让我们做一个概念证明,然后就停止了,那就没有价值可言。”。不幸的是,90%的其他案例都是这样,他们只是做了概念验证,并没有继续生产。
视频由hyperlight AB——人工智能驱动的零售——埃罗尔·库尔迈斯特,H & MxAI
事实证明,H&M 集团的成功之处在于,他们在 2016 年就已经专注于生产。他们下定决心,如果他们要从人工智能开始,他们就要大干一场。Errol 强调说:“这实际上是从小处着手,大处着眼,快速扩展”。根据他的说法,在现实中,没有人工智能用例,它们都是商业案例。H&M 集团实际上使用人工智能来扩大他们的商业解决方案。
H&M 集团的用例有不同的成熟度等级。但不管情况如何,他们始终专注于生产。因此,他们有一个定义好的过程来实现用例:
- 概念验证(POC)——这并不需要很长时间就能实现,因为正如 Errol 解释的那样,他们已经有了自己的数据湖,随时可以使用。这使他们能够在几周内启动虚拟机并获得洞察力。如果 POC 成功,则进入下一阶段。
- 试点——H&M 集团在几个市场试点该解决方案,以测试理论是否符合现实。他们将该案例投入生产,进行测试并评估结果。如果试点成功,他们将推出解决方案。
- 工业化和推广—流程的最后一步是向所有 72 个国家、177,000 名员工和近 5,000 家商店推广该解决方案。考虑到用户的数量,解决方案必须非常可靠。
人工智能驱动的零售的真实 H&M 集团例子

这里有一些由于实施人工智能解决方案而产生的具体例子。
保持流行商品的库存 — H & M 依赖于保持对潮流的领先才能获得成功。在算法的帮助下,他们分析商店收据和退货,以评估每个商店的购买情况。这样,时尚品牌就知道在某些地方应该促销和储备哪些商品。
预测市场需求——像 H & M 这样的时尚零售商依赖价格有竞争力的新鲜产品。数据洞察有助于 H & M 预测市场需求,这样他们就不必打折出售库存。
自动化仓库 —如今,客户期望随时随地获得快速、无障碍的交付。因此,H & M 集团投资了自动化仓库,最终将为大多数欧洲市场提供次日送达服务。这些仓库和它们的免费运输,只对忠诚的客户开放,是由算法和数据驱动的。
个性化的线下顾客体验 —借助 RFID 技术,H & M 也在其实体店推出了个性化的在线推荐。顾客获得由算法选择的店内商品建议。他们还可以查看他们在网上看到的商品在实体店中是否有售,并扫描标签以查看该商品在另一家商店或网上是否有售。
定制服装 — 这家瑞典时尚品牌与一个人工智能技术平台合作,测试了按需生产,这显示出更具体地响应客户愿望以及根据当地需求调整产品数量的巨大潜力。

Artem Beliaikin 在 Unsplash 上的照片
H&M 集团的故事有什么启示?
在当今的数字化世界,单靠人力管理像 H&M 这样的全球零售品牌是不可能的。在人类能力终结的地方,人工智能开始了。以 H&M 集团人工智能驱动的零售为例,零售商可以通过在业务中实施人工智能来提高人类智能,从而受益匪浅:更准确的商品决策,简化的供应链和顶级的客户体验。这就是 H&M 集团所说的放大智能——机器和人类、科学和艺术、数据和直觉之间的合作。
使用分析表进行人工智能对话
理解大数据
将自然语言数据库查询转换为 SQL 代码的人工智能进展综述
作者 Gowtham R 和Sundeep Teki2020 年 11 月 1 日

1。简介
近年来,驱动不同行业及其系统的数据量呈指数级增长。大多数商业信息以关系数据库的形式存储,关系数据库存储、处理和检索数据。数据库为多个行业的信息系统提供支持,例如,消费技术(例如,订单、取消、退款)、供应链(例如,原材料、股票、供应商)、医疗保健(例如,医疗记录)、金融(例如,金融业务指标)、客户支持、搜索引擎等等。
现代数据驱动型公司必须跟踪其业务的实时状态,以便快速了解和诊断数据中出现的任何问题、趋势或异常,并立即采取纠正措施。这项工作通常由业务分析师手动执行,他们用 SQL 等声明性查询语言编写复杂的查询,以获得存储在多个表中的业务洞察力。这些结果通常以图表或图形的形式进行处理,以使领导团队能够快速可视化结果并促进数据驱动的决策制定。
尽管解决基本业务指标的最常见的 SQL 查询已被预定义并合并到像 PowerBi 这样的商业产品中,这些产品能够洞察业务指标,但是任何新的或后续的业务查询仍然需要由分析师手动编码。数据库查询和相应结果的消费之间的这种静态交互需要耗时的人工干预,并导致缓慢的反馈周期。让非技术业务领导通过抽象出底层 SQL 代码的自然语言查询直接与分析表进行交互,效率要高得多。
定义 SQL 查询需要对数据库模式、SQL 语法有很强的理解,对于初学者和非技术利益相关者来说很快就会变得不知所措。弥合这一沟通鸿沟的努力导致了一种新型处理的发展,这种处理被称为数据库自然语言接口。随着微软[1][2]、Salesforce [3][4]和其他公司正在开发自然语言(NL)到 SQL ( NL2SQL) 的类似技术,这种自然搜索功能近年来变得越来越流行。当答案可以在不同的数据库或表格中找到时,转换后的 SQL 还可以使 Alexa、Google Home 和其他虚拟助手改善他们的响应。本博客将回顾 NL2SQL 的挑战、评估方法、数据集、不同方法和一些最先进的深度学习方法。

图一。从 WikiSQL 数据集转换为 SQL 的 NL 查询示例(来源)

图二。涉及多个表的 NL2SQL 示例( source )
2.技术挑战
2.1 理解 NL 查询并将话语与图式对齐
系统必须理解用户的问题和表模式(列、表名和值),才能将查询正确地映射到 SQL。这里的一个关键挑战是理解 DB 表的结构化模式(例如,列的名称、数据类型和存储值)以及输入查询和模式之间的对齐。例如,对于问题,哪个国家的 GDP 最大?,模型需要将 GDP 映射到国内生产总值列。有时这个问题可能还需要理解列的语义,而不仅仅是列名。**

图 3。一些查询可能需要理解单元格值(源)
对于图 3 所示的表格和问题,用于回答示例问题的场馆栏指的是主办城市。因此,该模型需要将查询中的“city”与表中的 venue 列对齐。****
2.2 跨领域推广

图 4。跨域设置中可能出现的错误示例(来源
为不同的领域收集大量的训练数据是昂贵且不可扩展的。因此,训练系统以推广到不同的领域和数据库是很重要的。这种概括将涉及识别新的实体、在 SQL 查询中正确地映射看不见的短语和实体,以及处理新颖的数据库和查询结构(更大的表、SQL 组件的组合等)。)[5].
2.3 订单事项问题
解决 NL2SQL 任务的标准方法之一是使用 seq2seq (因为 NL 查询和 SQL 都是序列)模型及其变体。这种方法的一个问题是,由于交换和关联属性,不同的 SQL 查询可能彼此等价。

图 5。两种方式编写相同的 SQL 查询(来源
在上面的例子中,我们看到,即使交换了 WHERE 条件,也会产生相同的结果,但是从语法上看,两个查询是不同的。如果我们将前者作为基本事实,而 seq2seq 模型预测后者,那么它将受到惩罚。
3.数据集

表 1。NL2SQL 的一些表格数据集概述(来源)
NL2SQL 任务有几个数据集。这些包含带注释的 NL 问题,对应于一个或多个表的 SQL 对。这些数据集在域(单个域与跨域)大小(查询数量——这对于正确的模型评估至关重要),以及查询复杂性(单表与多表)方面有所不同。****
像 ATIS、GeoQuery 这样的早期数据集关注于单个域,并且在查询数量方面也是有限的。一些最新的数据集,如 WikiSQL、Spider,是跨域的,并且与上下文无关,具有较大的规模。WikiSQL 和 Spider 的一个显著区别是查询的复杂性。WikiSQL 中的查询更简单(只包含 SELECT 和 WHERE 子句)。此外,WikiSQL 中的每个数据库只是一个简单的表,没有任何外键。Spider 包含适度数量的查询,并包含涉及表连接和嵌套查询的复杂问题。SParC[15]和 CoSQL[16]是 Spider 数据集的扩展,它们是为上下文跨域语义解析和会话对话文本到 SQL 系统而创建的。
4.评估方法
评估 NL2SQL 系统最常用的方法是执行精度和逻辑形式精度。
执行准确性将预测 SQL 查询执行后的结果与基本事实查询的结果进行比较。这种方法的一个缺点是,可能有一个不相关的 SQL 查询与问题不对应,但仍然给出了正确的答案(例如,NULL result)。

图 6。SQL 规范化示例(图片由作者提供)
逻辑形式准确性将预测 SQL 查询的精确字符串匹配与基本事实查询进行比较。这一指标的局限性在于,它会错误地惩罚那些在执行时产生正确结果,但与真实 SQL 查询没有精确字符串匹配的预测。解决排序问题的一种方法是在比较之前对 SQL 查询进行规范化。SQL 规范化是一种通过对 SELECT 中的列、FROM 中的表和 WHERE 约束进行排序以及标准化表别名、大写和符号间的间距来使计算保持一致的方法。
Spider [19]的作者使用组件匹配,它测量不同 SQL 组件(如 SELECT、WHERE、GROUP BY 等)上预测和真实情况之间的平均精确匹配。预测和基本事实被解析和分解成子组件,然后按组件计算它们的精确匹配。
例如,要评估选择组件:
选择 avg(col1),max(col2),min(col1) 分解为*集合(avg,min,col1),(max,col2)*
然后将该集合与地面真实集合进行比较。

图 7。来自 Spider 数据集的样本问题按硬度分类(来源)
尽管这解决了排序问题,但它仍然没有考虑预测何时使用不同的逻辑(与基本事实 SQL 相比)来获得相同的结果。因此,为了进行彻底的评估,还应该使用执行精度。
[19]中的作者还根据 SQL 组件、选择和条件的数量,通过硬度 T10 对查询进行分类。这种分类非常有助于更深入地了解模型在查询复杂性方面的性能。
5.NL2SQL 的不同方法

图 8。NLIs 的分类和使用的 NLP 技术(来源)
5.1 基于规则的方法
大多数现有方法集中于结合歧义检测的自然语言的基于规则的解析器。一些基于规则的系统使用触发词来识别用户问题中的模式。例如,“by”是聚合查询中常用的词,如“列出由<导演>执导的电影”。这里,触发词的左侧可能有 SELECT 子句所需的关键字,右侧有 GROUP BY 子句所需的关键字。**

图 9。从国家表中匹配国家资本的简单模式(来源
尽管这种方法很简单,但它(如果规则是格式良好的)已经被证明可以处理非常广泛的查询类型。Siri 和 Cortana 等现代对话代理遵循类似的原则,尽管规则不是确定性的,而是基于训练的(意图的逻辑回归分类器)。
5.2 基于语法的系统
在基于语法的系统中,用户的问题被解析,得到的解析树被直接映射到 SQL 中的表达式。创建可以描述用户问题的可能句法结构的语法。

图 10。过于简单的语法(来源)
图中所示的过于简单的语法认为用户的问题由名词短语和动词短语组成;名词短语由一个限定词后跟名词组成,限定词由“什么”或“哪个”等词组成。

图 11。解析“哪种岩石含有镁?”后得到的解析树用上面的语法(来源)
这个语法可以用来分析一个问题,比如“哪种岩石含有镁?”然后将得到的解析树映射到 SQL。这种到 SQL 的映射将由规则执行,并且完全基于解析树的语法信息。
5.3 基于深度学习的方法
基于规则的方法在覆盖范围、可伸缩性和自然性方面受到限制。它们对自然语言的多样性也不够健壮,并且很难跨域扩展。大规模监督数据集的出现,如 WikiSQL、Spider 等。、自然语言处理的进展、预处理【20】等。已经使深度学习模型能够在 NL2SQL 任务中实现最先进的结果。**
几乎所有的深度学习模型都使用编码器-解码器【21】模型从自然语言输入中生成 SQL 查询。编码器可能是【22】/【24】或最近的变压器【25】网络。大多数模型的不同之处在于它们对模式的编码方式(表名、列名、单元格值等)。)以及它们如何产生 SQL 输出。
一些模型将模式作为其输出词汇表的一部分。换句话说,他们把所有的表名、列名等。,并在解码 SQL 输出时,从词汇表中选择这些单词。NSP[10],DBPAL[18]是使用这种方法的一些方法。这种方法的一个主要限制是我们不能使它们适应跨域,因为它们不能在输入中编码新的模式。

图 12。Seq2SQL 模型的组件,将问题、列名和 SQL 标记作为输入(源)
相比之下,SEQ2SQL[3]等其他方法使用模式作为模型的输入,在解码时,使用指针网络【26】使用输入中提到的表或列名。例如,在 SEQ2SQL[3]中,作者使用了列名、问题标记和 SQL 标记,如 SELECT、WHERE、COUNT、MIN、MAX 等。作为输入。他们的指针网络通过专门从这个扩充的输入序列中选择来产生 SQL 查询。作者还声称,除了限制输出空间之外,这种增强的指针网络还产生了更高质量的 WHERE 子句。

图 13。指针网络示例(来源)
基于从自然语言输入生成 SQL 查询,存在三种类型的模型:序列到序列,序列到树,以及槽填充【23】。序列对序列模型将 SQL 生成为单词序列。序列到树模型生成预测 SQL 查询的语法树。槽填充方法将 SQL 查询视为一组槽,然后使用每个槽的相关解码器对整个问题进行解码。基于语法的解码器的一个优势是它们可以在每一步检查语法错误,产生带有连接、嵌套查询等的复杂查询。没有任何语法错误。
5.4 现代深度学习方法
现代深度学习方法使用更多技术来学习 NL 问题和表格中呈现的结构化信息的联合表示。他们使用各种基于注意力的架构进行问题/模式编码,使用基于 AST 的结构架构(序列到树)进行查询解码。IRNet [1],RAT-SQL(当前 spider 中的 SOTA 方法)[2]使用BERT【21】(用于 NL 表示)以及内部策略对表中的结构化信息进行编码。相比之下,TaBERT[27]使用通用的预训练方法来学习自然语言句子和表格数据的表示。这些技术包括模式链接、更好的模式编码、使用 DB 内容(单元格值而不仅仅是列名和表名)、问题和模式表示的上下文化。
5.4.1 模式链接

图 14。RAT-SQL 中的模式链接(问题到列和表的链接)(源)
这包括将问题中的实体引用与正确的模式列或表对齐。文本匹配是问题-模式对齐的最佳证据,它可能直接有利于编码器。链接一般是通过 IRNet 和 RAT-SQL 中的字符串匹配来完成的。问题中的 n 元语法(长度最大为 5 或 6)用于匹配模式中的列名或表名(包括完全匹配和部分匹配)。链接后,IRNet 用相应实体的类型(表名/列名等)标记问题中提到的每个实体。)一边编码。基于 n 元语法与问题单词的重叠,列名也被分配了精确匹配和部分匹配类型。另一方面,RAT-SQL 用问题单词和列/表名作为节点构建一个图,边是问题-列-M、问题-表-M 等。,其中 M 是 EXACTMATCH、PARTIALMATCH 或 NOMATCH 之一。

图 15。IRNet 中的模式链接(源
基于价值的链接
自然语言问题也可以提到值(如“对于 4 缸汽车,哪种型号的马力最大”中的“4”),它将作为某个表中的单元格值出现。IRNet 在知识库中查找问题中提到的值,并在返回的结果中搜索部分或完全匹配的列名。根据匹配情况,为列名分配类型值完全匹配和值部分匹配。另一方面,如果问题单词作为一个值出现在列中,RAT-SQL 会在问题单词和列名之间添加一个边缘列值。
TaBERT 直接使用 DB 内容,而不是链接和使用列名。作者认为内容提供了关于列语义的更多细节,而不仅仅是列名、,后者可能有歧义。他们选择一个内容快照,该快照仅包含几行根据字符串匹配(n-gram 重叠)与 NL 问题最相关的内容。****
模式编码

图 16。具有多个表格的示例图表模式(源
这包括对数据库中的关系结构进行编码。在具有多表关系的数据库中(对主键、外键等进行编码),这更具挑战性。是必不可少的)。IRNet 对列和表进行编码,以获得列和行的表示。这些列由列名及其类型表示,它们是通过模式链接定义的。最终的表示是通过添加列名嵌入、上下文嵌入(基于问题中匹配的 n 元语法)和类型嵌入来创建的。

图 17。RAT-SQL 模式图中的边类型(来源
RAT-SQL 将模式表示为以列和表为节点的有向图。这些边由上图中详述的数据库关系定义。
5.4.4 问题和模式表示的上下文化:
这有助于学习有效的联合表达。RAT-SQL 通过在问题词和模式链接后定义的模式实体之间添加边来扩充模式图。他们引入了一个关系感知自我关注【25】层来使用输入中的关系结构,并学习序列元素之间的“软”关系。它们通过提供一种交流已知关系(如主键、外键等)的方式来做到这一点。在边缘标签中定义)的方法。

图 18。 rij 对已知的关系进行编码,并添加到自我关注方程中(来源)
6.结论和未来趋势

图 19。整合人类反馈以改进 NL2SQL 系统的示例(来源)
在这篇博客中,我们回顾了 NL2SQL 的最新发展水平——问题陈述、挑战、此类系统的评估以及解决该任务的现代机器学习技术。最近的工作还集中在改善用户在使用这种系统时的体验。Photon [4]是一个灵活的系统,支持 NL 问题和 SQL 输入。它还有一个困惑检测模块,可以检测无法回答的问题,并帮助用户解释一个问题以获得正确的答案。[28]中的作者还表明,纳入人类反馈可以进一步提高这些系统的准确性和用户体验(见图 19)。

图 20。展示 NL2SQL 系统可解释性的示例(来源)
尽管现代 NL2SQL 技术在基准测试集上取得了良好的准确性,但它们在生产环境中仍远未表现出稳健的性能。在商业决策的背景下,培养和建立用户对这种系统的信任对于实现可靠的性能是至关重要的。NL2SQL 方法有可能显著提高人类分析师的效率,因此他们可以将更多的时间集中在结果的上下文解释和验证上。现代端到端深度学习系统的输出缺乏可解释性,尽管有关于人工智能系统如何在引擎盖下工作的重要研究,但将人纳入环中以提供反馈并提高预测能力将加速 NL2SQL 系统在现代数据驱动的组织中的采用和使用。
7.参考
[1]郭,,等.“跨域数据库中复杂文本到 sql 的中间表示研究”(2019) arXiv 预印本 arXiv:1905.08205
[2]王,白林等,“Rat-sql:文本到 sql 解析器的关系感知模式编码和链接”(2019) arXiv 预印本 arXiv:1911.04942
[3]钟、维克托、、熊和理查德·索彻。" Seq2sql:使用强化学习从自然语言生成结构化查询."(2017) arXiv 预印本 arXiv:1709.00103
[4]曾,吉川等,“光子:一个健壮的跨域文本到 SQL 系统”(2020) arXiv 预印本 arXiv:2007.15280
[5] Suhr,Alane 等人,“探索跨数据库语义解析的未探索的泛化挑战”(2020)计算语言学协会第 58 届年会会议录。
[6] Dahl,Deborah A .等人,“扩大 ATIS 任务的范围:ATIS-3 文集”(1994)人类语言技术:1994 年 3 月 8 日至 11 日在新泽西州普兰斯伯勒举行的研讨会会议录。
[7]唐、拉普昂和雷蒙德·穆尼。"在归纳逻辑编程中使用多子句构造函数进行语义分析."(2001)欧洲机器学习会议。施普林格,柏林,海德堡,2001。
[8]唐、拉普昂和雷蒙德·穆尼。"数据库接口的自动构建:整合语义分析的统计和关系学习."(2000)关于自然语言处理和超大规模语料库的经验方法的联合 SIGDAT 会议。
[9]李、费和 H. V .贾加迪什。"为关系数据库构建交互式自然语言界面."(2014)VLDB 基金会会议录 8.1:73–84。
[10] Iyer,Srinivasan 等人,“从用户反馈中学习神经语义分析器”(2017) arXiv 预印本 arXiv:1704.08760
[11] Yaghmazadeh,Navid 等,“SQLizer:从自然语言中进行查询合成”(2017)美国计算机学会程序设计语言会议录 1。OOP SLA:1–26。
[12]钟、维克托、、熊和理查德·索赫尔。" Seq2sql:使用强化学习从自然语言生成结构化查询."(2017) arXiv 预印本 arXiv:1709.00103
[13] Finegan-Dollak,Catherine 等人,“改进文本到 sql 的评估方法”(2018) arXiv 预印本 arXiv:1806.09029
[14]俞,陶,等.“Spider:面向复杂跨领域语义分析和文本到 sql 转换的大规模人工标注数据集”(2018) arXiv 预印本 arXiv:1809.08887
[15]于,陶,等.“Sparc:跨领域上下文语义分析”(2019) arXiv 预印本 arXiv:1906.02285
[16]俞,陶等.Cosql:跨域自然语言数据库接口的对话式文本到 sql 的挑战.〉(2019) arXiv 预印本 arXiv:1909.05378
[17] Finegan-Dollak,Catherine 等人,“改进文本到 sql 的评估方法”(2018) arXiv 预印本 arXiv:1806.09029
[18] Basik,Fuat 等,“Dbpal:数据库的学习型 nl 接口”(2018)2018 年数据管理国际会议论文集
[19]俞,陶,等.“Spider:一个面向复杂跨领域语义解析和文本转 sql 任务的大规模人工标注数据集”(2018) arXiv 预印本 arXiv:1809.08887
[20] Devlin,Jacob 等,“Bert:用于语言理解的深度双向转换器的预训练”(2018) arXiv 预印本 arXiv:1810.04805
[21] Sutskever,Ilya,Oriol Vinyals 和 Quoc 诉 Le。"用神经网络进行序列对序列学习."(2014)神经信息处理系统进展。
[22]罗纳德·威廉斯;杰弗里·辛顿;通过反向传播错误学习表征。(1986 年 10 月)《自然》。
[23] Kim,Hyeonji,等,“SQL 的自然语言:我们今天在哪里?."(2020)VLDB 基金会会议录 13.10:1737–1750。
[24] Hochreiter,Sepp 施密德胡伯,于尔根《长短期记忆》。神经计算。
[25]瓦斯瓦尼、阿希什等人,“你所需要的只是关注。”(2017)神经信息处理系统进展。
[26] Vinyals、Oriol、Meire Fortunato 和 Navdeep Jaitly。“指针网络”(2015)神经信息处理系统进展。
[27]尹,彭成等,“表格:联合理解文本和表格数据的预处理”(2020) arXiv 预印本 arXiv:2005.08314
28 埃尔戈哈里、艾哈迈德、萨加尔·侯赛尼和艾哈迈德·哈桑·阿瓦德拉。"与你的解析器对话:交互式文本到 SQL,带有自然语言反馈."(2020) arXiv 预印本 arXiv:2005.02539
人工智能增强的阿波罗 16 号镜头让你登上 4K 的月球
体验前所未有的月球

截图由荷兰蒸汽机器提供(YouTube)
人类最后一次在月球上行走是在 1972 年作为阿波罗 17 号任务的一部分在 T2。不言而喻,自那以后发生了很多变化。在技术领域,这近 50 年等同于不可思议的进步。
虽然美国宇航局的宇航员尽最大努力捕捉他们在月球上冒险的镜头,但当时的技术让他们失望了。幸运的是,现代人工智能(AI)技术可以扭转局面。
YouTube 频道荷兰蒸汽机器最近上传了阿波罗 16 号任务的增强镜头。它将观众放在任务月球车的乘客座位上,分辨率为 4K,每秒 60 帧。
昨日问题的现代解决方案
在 70 年代,高清摄像机的想法甚至都不存在,更不用说技术本身了。当阿波罗 16 号任务的宇航员访问月球时,他们用 16 毫米胶片以每秒 12 帧(fps)的速度拍摄了他们的视图。虽然它足以让观众对场景有一个大致的了解,但它并不出色。
YouTube 的创作者使用了一个名为 DAIN 的人工智能平台来放大这些镜头。虽然分辨率的提高很好,但最令人印象深刻的是该剪辑现在以每秒 60 帧的速度运行。这为月球车前往月球矮子环形山边缘的 4 号站创造了一幅平滑的图像。
运动平滑功能并不受欢迎。然而,如果做得好,就像在这个视频中一样,他们可以制作出更好的剪辑。人工智能的增强使月球车的镜头比原始版本更具沉浸感。
进一步增强其魅力的是,该剪辑与阿波罗任务的原始音频同步。倾听宇航员探索月球表面的声音既有趣又可爱。它以一种他们巨大的宇航服和达斯·维德式的呼吸噪音所没有的方式使他们人性化。
在现实中,这听起来像是一对德克萨斯的爸爸在一次随意的周日驾车旅行中叙旧,而不是两个训练有素的科学家在探索一个天体。人们几乎很容易忘记他们当时距离地球 239,000 英里。
人工智能助手
没有额外的镜头,就不可能真正提高视频的帧速率。然而,人工智能提供了一种解决方法。
本质上,DAIN 平台逐帧分析镜头,以确定哪些元素在每一帧之间移动。然后,AI 会根据它确定的以更高的 fps 拍摄的帧,在原始帧之间插入新帧。通过这样做,它可以将最初以 12 fps 拍摄的剪辑增强到 60 fps。
每秒包括更多的帧允许视频捕捉更多的运动而不显得跳动。事实证明,人工添加框架几乎同样有效。
不过,希望人类的下一次月球之旅不会依赖于低质量的镜头。当美国宇航局的宇航员通过 Artemis 计划返回月球时,他们可能会带着 4K 记录设备,这些设备将捕捉前所未见的镜头。也许他们甚至能够创造一个虚拟现实(VR)体验。
原载于 2020 年 7 月 9 日 https://www.theburnin.com。
人工智能伦理不存在
意见
拿一片止痛药,这可能会变得复杂

人工智能 (A.I)是革命还是战争?上帝还是宠物?锤子还是钉子?难道我们 真的 还需要更多的比喻来形容吗?如今,人工智能决定了在社交媒体上向我们展示哪些信息,我们看到哪些广告,以及我们在线上和线下的报价。一个算法可以在技术上编写和分析书籍,在几乎所有可以想到的游戏中击败人类,制作电影,创作古典歌曲帮助魔术师 表演更好的戏法。除了艺术,它还有可能鼓励更好的决策,做出医学诊断,甚至解决一些人类最紧迫的挑战。与刑事司法、零售、教育、招聘、医疗、银行、农业、运输、战争、保险、媒体……不胜枚举。
然而,我们经常忙于讨论人工智能是否能做某事的细节,以至于我们很少问自己是否应该设计它。
这就是伦理的用武之地。公司和政府都已经意识到 类固醇 的统计数据能够造成巨大伤害,并且正在研究各种方法来应对潜在的后果,而不影响他们的底线或战略地缘政治优势。他们提出了几十条“原则”,一条比一条更难执行,甚至无法就基本框架达成一致。讨论战争,自动化,大规模监控,威权至上;但是这些讨论不能在关键道德原则和红线达成一致之前进行。
因此,下面是围绕人工智能和伦理讨论的“快速”指南。它旨在帮助使对话民主化:我们不一定需要更聪明的人坐在桌子旁(我写的任何东西对专家来说都不是新闻,但是我们确实需要一张更大的桌子。或者更多的桌子。或者更多的座位。或者某种视频会议解决方案。
我讨厌隐喻。
伦理可以有许多不同的含义
在我们深入当代关于伦理的讨论之前,我们首先需要了解什么是伦理。伦理有一个非常简单的字典定义:“管理一个人的行为或进行一项活动的道德原则”。
在像我这样的反向投资者破坏所有人的乐趣之前,这大概是所有人能做到的极限了。你看,即使我们把规范伦理学(对伦理行为的研究)与其较弱的表亲元伦理学和应用伦理学分开,仍然没有一个关于什么是好/坏和/或错/对的定义。的确,好的可能是错的,坏的可能是对的。
为了更好地理解为什么人工智能伦理学的当前主张与道德原则没有什么关系,我们应该了解以下几个学派:
- ;TL;最大多数人的最大幸福是道德和立法的基础,也就是“目的证明手段的正当性”。近亲:功利主义。
- 义务论;TL;我们有责任总是做正确的事,即使这会产生负面的后果。“你避免让自己受苦的事,不要强加给别人” ( 爱比克泰德,又名,在哲学上有着最史诗般名字的家伙——也是一个斯多葛派)。近亲:康德主义。
- 享乐主义;TL;最大化自我满足是我们作为人能做的最好的事情。
- 道德直觉主义;TL;在没有诸如善或恶等其他概念的先验知识的情况下,知道什么是道德的是可能的。
- 实用主义 ;TL;道德在进化,规则应该考虑到这一点。
- 状态结果论;TL;任何对国家有利的事情都是道德的。
- 美德伦理;TL;美德是一种性格特征,源于通过知识对善与恶的区分。它与一个动作或一种感觉是分开的。近亲:斯多葛主义。
如果一个公司或政府告诉你它的道德原则,你有责任去挖掘并询问他们这些原则是基于哪个道德分支。在这些定义中可以找到很多信息。
问这个问题很重要,因为正如我们在下面看到的,机构喜欢使用伦理这个词,而实际上从来没有接近过任何类似于道德原则的东西(请参考这篇文章的标题进行常规的理智检查)。然而,好消息是知道很多关于道德的知识和行为合乎道德之间实际上没有关联。
“道德剧场”困扰着公司
公司的存在是为了奖励股东 。至少,这是过去 50 年来一直信奉的商业哲学。因此,公司没有动力去做“正确”或“好”的事情,除非他们的利润面临风险。从技术上来说,对他们来说最重要的是客户认为他们做得好/对。道德剧场的理念是,公司将尽一切努力表现出尽最大努力合乎道德,而不这样做,以防止消费者的反弹。做到这一点的一个完美方法是宣布宏大的、不具约束力的原则和规则,这些原则和规则与实际的道德规范没有任何联系,一旦出现任何挑战,就指向它们。
下面是一些大型人工智能公司定义的原则。这绝不是详尽无遗的(然而也是令人筋疲力尽的),但是提供了一个对公司赞助的道德清洗的洞察。这些规则通常分为 4 类。
问责制/责任
"指定一名首席人工智能道德官员 " ( IBM ),"人工智能设计师和开发人员负责考虑人工智能的设计、开发、决策过程和结果* " ( IBM ),"对 负责 对人 " ( 谷歌)" AI 系统应该有算法 问责 " ( 微软)。***
为什么是 B-S :首先,就像下面的许多观点一样,这些都不是关于道德本身的,即使一些论文的标题中实际上有这个词。第二,没有任何地方写着高管应该对国家法律负责,让他们随心所欲。事实上,在人工智能中很少有法则存在,但这正是我们有伦理的真正原因;没有任何地方说明这些公司将根据什么标准承担责任。道义论?结果主义?在这一点上谁也说不准。**
透明度
"不要隐藏你的 AI " ( IBM ),"解释你的 AI* " ( IBM )," AI 的设计应该让人类容易感知、察觉、理解其决策过程 " ( IBM )," AI 系统应该是可以理解的 " ( 微软)。***
为什么是 B-S :我不会在这里讲太多细节,因为这是技术性的多于理论性的(这里有一个快速指南),但是 A.I 本质上是一个黑箱。为了实现完全透明,公司必须公开他们的部分代码,这一点已经被讨论过,但是遭到强烈反对。另一个解决方案来自于 GDPR 的“解释权”,集中于输入而不是输出。所述权利要求用户能够要求为他们做出的算法决策背后的数据。这是一个很好的想法,但在欧洲以外的任何地方都没有实施。
公平/偏见
"测试你的 AI 对于 的偏见 " ( IBM )," AI 必须被设计成最小化的偏见并促进包容性的代表性"(IBM);"避免制造或强化不公平的 偏见 " ( 谷歌)," AI 系统应该公平对待所有人 " ( 微软)。****
为什么是 B-S:一个用来寻找数据模式的系统可能会找到错误的模式。这是人工智能偏见最简单的定义。这样的流行语有助于公司避开诸如性别歧视、种族主义或年龄歧视等棘手的话题。上帝禁止他们向自己提出尖锐的问题,或者对他们使用的数据集负责。我们完全有权利(义务)要求解决哪些偏见,以及如何解决。
数据和隐私
" AI 必须被设计成保护用户数据,并保留用户对访问和使用"(IBM);"融入 隐私 设计原则 " ( 谷歌),"人工智能系统应该是安全的,并尊重 隐私 " ( 微软)。****
为什么是 B-S: 如果他们真的在乎,他们早就实施欧洲标准了(GDPR 万岁)。他们没有。结案了。**
在我读过的许多报告中,只有两次真正提到了道德:
"人工智能的设计应该符合你的用户群体的规范和价值观 " ( IBM ) " 我们不会在以下应用领域设计或部署人工智能:会造成或可能造成整体伤害的技术。如果存在重大的危害风险,我们将仅在我们认为益处大大超过风险的情况下进行,并将纳入适当的安全约束。”(谷歌)**
这告诉我们,IBM 信奉实用主义(很公平),而谷歌是结果主义公司。这很奇怪,因为“不作恶”,该公司的长期口号,在技术上是义务论。这样的二分法凸显了一个明显的疏忽:世界上最大的公司之一正在定义人工智能原则,这些原则可能会在社会上产生深远影响,同时又违背其内部文化。这听起来像是过度分析,直到你意识到 在过去的几个月里,谷歌内部因为这个原因发生了许多员工起义。**
你可能已经注意到上面只提到了三家公司(谷歌、IBM、微软)。这是因为其他主要的人工智能公司还没有拿出任何值得挑剔的东西,而是选择投资于最终会影响政府的智库。这一点凸显了所有原则共有的一个重大缺陷:没有一个原则要求公司遵守可执行的规则。那么,为什么公司会为道德剧场而烦恼呢?如上所述,第一个原因确实是为了影响政府并引导对话朝着“正确”的方向发展(见下文公司和政府优先事项标准的相似之处)。其次,被客户和员工认为是有道德的很好,这样可以避免任何抵制。第三,或许也是最重要的一点,制定标准可以赚大钱:专利 x 普遍使用= $$$。********
第二课:公司对道德知之甚少,没有动力去表明什么是好的或正确的。企业伦理是一个矛盾体。
因此,政府需要加快步伐,因为企业不太可能为了社会利益而放弃利润。
政府正在尽最大努力
有许多政府发布的白皮书,但它们要么含糊不清,要么不完整。此外,许多人从经济和地缘政治竞争的角度看待人工智能。一个明显的例外是在欧盟人工智能战略和愿景中明确强调道德和责任,特别是相对于美国和中国(这两个国家在道德上已经名誉扫地)。为了全面了解各国认为人工智能道德应该是什么样的,我将它们的原则分为 7 类,其中大部分都与上述对企业的分析非常相似。****
请注意,这仅仅是由比我更聪明、更有见识的人所写的数千页内容的(相关)过度简化。我强烈推荐阅读链接文档,因为它们提供了关于所列原则的深入信息。
问责制/责任
问责 按设计英国);"那些对人工智能系统生命周期的不同阶段负责的应该是可识别的,并且 对人工智能系统的结果负责的(……)"(澳大利亚 ) " 所有人工智能系统必须是可审计的 " ( 挪威);"国防部人员将行使适当水平的判断和谨慎,而剩余的 负责 人工智能能力的开发、部署和使用 " ( 美国国防部);责任原则 ( 中国);"机制应到位,以确保人工智能系统及其成果的 责任 和 问责(……)"(欧盟);"开发、部署或操作人工智能系统的组织和个人应根据上述原则 " ( OECD ) " 负责其正常运作。设计和部署使用人工智能的人必须履行 责任 和透明********
对什么负责?!对谁?!这个问题是如何被如此系统地回避的?
透明度
"过程与结果透明度 原理 " ( 英国);"应该有 透明度 和负责任的披露,以确保人们知道他们何时受到人工智能系统的重大影响,(……)"(澳洲);" AI 型系统必须是 透明 " ( 挪威);“国防部的人工智能能力将得到发展和部署,以便相关人员对该技术有适当的理解(……)”(美国国防部);"数据、系统、AI 商业模式应该是 透明(……)"(EU);"围绕人工智能系统应该有 透明度 和负责任的披露,以确保人们理解基于人工智能的结果,并能够挑战它们"(OECD);“原则上,AI 系统必须是可解释的”(梵)。******
不如我们先强迫公司透露他们是否真的使用了人工智能技术?
公平/偏见
"歧视性非伤害原则 " ( 英国);"人工智能系统应具有包容性和可访问性,不应涉及或导致对个人、社区或群体的 不公平"(澳洲);"人工智能系统必须促进包容性、多样性和平等待遇* " ( 挪威);"该部门将采取审慎的步骤,最大限度地减少人工智能能力中无意的 偏差"(美国国防部);"不公平* 偏见 必须避免,因为它可能会产生多重负面影响,从弱势群体的边缘化,到偏见和歧视的加剧(……)"(欧盟);“不制造或按照 偏见 行事,从而维护公平和人的尊严” ( 梵蒂冈)。********
提醒一下,通过确保输入的数据代表现实,并且不反映现实中存在的偏见,可以避免偏见。
数据和隐私
" AI 系统应尊重和维护 隐私 权利和 数据保护 ,并确保 数据 " ( 澳大利亚);" AI 必须把 隐私数据保护"(挪威);"除了确保充分尊重 隐私 和 数据保护 之外,还必须确保充分的数据治理机制,考虑到数据的质量和完整性,并确保对数据的合法访问 " ( 欧盟);"人工智能系统必须安全地工作,并尊重用户的 隐私*"(梵蒂冈)。***
哦,中国和美国不在名单上?酷,酷,酷…只是巧合,我确定。我相信这也是一个巧合,三个完全不同的组织提出了措辞非常相似的原则。
安全/保障/可靠性
"安全性*** ,健壮性原则 " ( 英国);"人工智能系统应该 可靠地 按照它们预定的目的 " ( 澳);"基于 AI 的系统必须是 安全 和技术健壮 " ( 挪威);"部门的 AI 能力将有明确的、定义良好的用途,而 安全 , 安全(…)";“国防部将设计和工程人工智能能力,以实现其预期功能,同时拥有检测和避免意外后果的能力(……)”(美国国防部);" AI 系统需要有弹性 安全(……)"(EU);"人工智能系统必须以稳健、 安全、 和 安全、 【方式(……)运行,并应持续评估和管理"(OECD);“人工智能系统必须能够可靠地工作**”(梵)。*********
说起来容易做起来难当一个简单的贴纸 就能让一个算法产生幻觉 。
利益相关方参与/社会公益
"利益相关者影响评估原则 " ( 英国);"人工智能系统应该造福个人, 社会 和 环境 " ( 澳洲);”艾必利 社会 和 环境”(挪威);人类利益原则* ( 中国);人工智能系统应该造福全人类,包括子孙后代。因此,必须确保它们是可持续的和环境友好的。"人工智能应该通过推动包容性增长、可持续发展和福祉来造福人类和地球"(OECD);必须考虑到所有人的需要,这样每个人都能受益。*******
嘿,还记得 什么时候一个面部识别软件“能说出”你的性取向 吗?在俄罗斯?
权利
"人工智能系统应该尊重人类的 权利 、多样性以及个人的自主性 " ( 澳大利亚);"当人工智能系统对个人、社区、团体或环境产生重大影响时,应该有一个及时的流程,允许人们质疑人工智能系统的使用或输出 " ( 澳洲);"基于 AI 的解决方案必须尊重人类的自主性和控制力 " ( 挪威);”权利 和责任【原则】 ( 华);“人工智能系统应该赋予人类权力,允许他们做出明智的决定,并培养他们的基本权利。”(欧盟);"人工智能系统的设计应尊重法治、人权、民主价值观和多样性,它们应包括适当的保障措施(……)以确保公平和公正的社会 " ( 经合组织)。********
嘿,还记得脸书给 65000 名俄罗斯用户贴上‘有意叛国’的标签吗?
五点分析
- 只有欧盟、挪威和澳大利亚处理所有 7 项原则;从某些国家忽略的内容中可以看出很多东西。这种缺乏共识的情况也令人担忧,因为一个实体在几个国际准则、其本国的国家政策以及公司和非营利组织的建议之间做出决定,最终可能会一事无成。
- 除了这 7 点之外,没有主要的风险投资,而且它们很少彼此偏离太远。这凸显了群体思维的一个非常真实的风险(这将有利于私营部门)。例如,没有任何地方提到 自决权 ,而人工智能很容易被用来以某种方式推动人(比如说,在选举期间)。
- 可耻的是没有红线:没有一个国家禁止自己使用某些人工智能,这些原则也没有法律约束力。仅供参考,强有力的监管是这样的:
- 讨论中完全没有技术定义。任何相关的KPI都可以衡量这些原则。谁在乎有些东西目前在技术上是否遥不可及?这么说意味着误解了战略的定义(同样,威胁要对公司罚款,他们会很快找到技术解决方案)。****
- 道德准则的缺乏起初并不明显。它们也不是必须的,否则我们会问“如果一个原则违背另一个原则会发生什么?”。他们排名吗?有重要的顺序吗?如果放弃隐私权对社会有益,会发生什么?当我们开始处理多个,通常是相互竞争的目标,或者试图解释像“自由”和“幸福”这样的无形事物时,一个令人满意的数学解决方案是不存在的。这就是清晰的伦理哲学有用的地方:如果状态结果主义被优先考虑(在中国通常是这样),这至少给了我们一个关于什么将被优先考虑的线索(阿西莫夫的 机器人的三大法则 在这个中相当棒)。******
第三课:在制定相关原则方面,政府比公司走得更远。然而,他们仍然缺乏坚持原则的勇气,以及使这些原则得以实施的技术诀窍。
道德很容易,但勇气却不容易
现在,我们已经建立了道德必须提供的基本原则(从表面上看并不是很多),并且我们已经分析了公司和政府等的各种尝试,下面是一些建议,它们不仅基于道德,而且基于关于重大问题(战争、政治、自动驾驶汽车、司法……)的勇气。我提到勇气是因为这是当前人工智能话语中所缺少的。下面的原则可能以前就有过,但很可能因为它们所包含的内容(竞争力的丧失、战略优势、酷哥点……)而被摒弃。我提出这些问题没有任何风险,因为我在这次谈话中没有任何实权;如果我代表一个人/一家公司,我可能不会持有同样的观点。******
合理性原则
萨特有句名言,“是别人的地狱”。当涉及到人工智能时尤其如此;不是因为人们强迫算法变坏,而是因为我们的行为可能会创造一个世界,在这个世界里,坏行为已经被算法所铭记,迫使自己采取所说的行为或因此遭受痛苦(例如:一个女人从她的简历中删除性别词汇)(如果这让你困惑,你可能需要一本关于机器学习的初级读本)。托克维尔称之为多数人的暴政:一个基于数字而不是正义或优秀来统治的决定。在理性的原则下,关键的黄金法则将通过公众咨询和技术咨询在所有人工智能公司内强制执行,确保即使人们失去理智,也不会构建出体现疯狂的算法。我可以推荐从这段鲜为人知的义务论历史开始吗**
排名原则
我们假设上面的原理在全球范围内都适用( ha!)。在创建算法时,公司如何处理相互竞争的基本权利?例如,我们能否放弃第 9 条和第 12 条,以更好地执行第 5 条?我们能制造出一种人工智能来搜索通讯频道以发现潜在的犯罪活动吗?这些问题正是我们需要一个伦理立场的原因,这将有助于发展一个稳定的价值观、伦理和权利的等级,其中一些将高于其他。以臭名昭著的电车问题为例,应用到自动驾驶汽车上。如果可以选择,自动驾驶汽车应该优先拯救两名行人而不是一名乘客吗?如果乘客是国家元首呢?如果行人是罪犯呢?选择一个思想流派,尽管这可能很难,但将有助于创建符合我们信念的算法。
矛盾原则
上面的例子不是随机的:有史以来最大规模的道德偏好研究始于 2014 年,鼓励世界各地的用户对“电车问题”的许多变体做出回应。尽管在意料之中,但结果是明确的:不同的文化在伦理方面信仰不同的东西。例如,日本和中国不太可能伤害老年人。较贫穷的国家对违法者更加宽容。个人主义国家通常更喜欢多留些性命。道德是动态的,但编码是静态的。这就是为什么不应该创建一个算法来为多个群体做出决策。在我看来,至少应该做出基于不同世界观的三套:西、东、南。
简单来说,如果我进入一辆中国自动驾驶汽车,我希望在发生事故时能够选择西方标准。
问责原则
对于许多自由市场的支持者来说,这一原则似乎是亵渎神明的,因为他们是在烟草集团不会导致癌症、酿酒厂不会导致酒精中毒、枪支不会导致校园枪击以及制药公司不会导致药物过量的国家长大的。硅谷明白这一点,当它的产品造成伤害(失业、偏见、死亡……)时,它的首要借口是说它的技术是价值中立的,它们无力影响其实施的性质。那只是一条简单的出路。算法出人意料的行为现在是生活中的一个事实,正如汽车制造商现在必须意识到排放问题,欧洲公司必须保护他们客户的数据一样,的技术高管(而不是科学家,他们的存在的理由是推动障碍——这是应该的)必须密切跟踪算法的行为,因为它随着时间和环境的变化而变化,并在需要时减少恶意行为,否则他们将面临巨额罚款或监禁。******
搞不定?不要开绿灯。
你批准了一个最终对女性有偏见的项目?交罚款。你让一辆自动驾驶汽车上路,一名行人死亡?去坐牢吧。你的 A.I 犯了战争罪?和你一起去海牙。
如果你的签名在这一页的底部,你就要对法律负责。
净正值的本金
是一个。我真的值得吗?目前,即使是最简单的算法就其本质而言也是不道德的:采矿、冶炼、物流、商业秘密的暗箱操作、数据中心资源、现代奴隶制、加纳的电子垃圾山 …所有这些都是不可持续的,尽管英国、澳大利亚和欧盟都在它们的大原则中提到了环境。为了微小的快乐和简化,真的值得吗?一次,就一次,在讨论中保持一点理智是有好处的。
我说的理智是指能够看到整个该死的供应链,否则你的算法不会进入生产。
环境问题不能再被放在次要位置,即使是在讨论像数字世界这样看似无辜的事情时。
结论
面对有限的技术和过多的潜在用途,人工智能的好处显然大于风险。然而,在机器人开始为我们说话之前,没有理由不谈论它的实现。
我为后面的人大声说一句 : A .我不是可以信任或者不可以信任的东西。它只是一个人造的工具,被“输入”数据,以便大规模地自动化某些任务。你信任你的洗衣机吗?你的计算器(是啊,我也没有。数学是黑魔法)?人们很容易认为某样东西是不存在的。人工智能没有善恶之分。人类是善或恶的(通常同时是两者)。说到底,人工智能只不过是社会的一面黑镜,反映了社会的成功和不平等。最重要的是,这让人很不舒服。这很不舒服,因为我们不断发现我们是 a 洞。
A.I 伦理不存在。
让我为后面的人大声说一遍:算法是为非常具体的目的服务的。他们不能偏离这些目标。重要的是,一家公司是否认为这个目的值得在一个黑盒子里自动化。因此,人工智能道德的问题应该重新表述为“我们是否相信(在此处插入公司名称)的管理人员将我们的最佳利益放在心上?“如果是的话,”我们是否相信公司的程序员会在考虑到潜在数据缺陷的情况下完美地实现这一愿景?“那就更棘手了,不是吗?但是更现实。****
人工智能伦理并不存在。
让我为后面的人大声说出来:模糊的清单和原则,无能为力的道德官员和没有权力的顾问委员会是为了保全面子,避免改变,逃避责任。如果你从这篇文章中学到了什么,那就是:
人工智能伦理不存在。
本文最初是为欧洲专注于开发者的求职平台honey pot . io撰写的。**
人工智能伦理:首先不伤害

弗兰基·查马基在 Unsplash 上拍摄的照片
劳拉[fic是两个孩子的忙碌妈妈。她疯狂的日程安排与新冠肺炎在家工作不协调。每一天都像是原始生存的练习。为了最大限度地减少精神紧张,每当风险较低时,她都会默认为自动驾驶模式,不需要她全神贯注。有一个老派的男管家不失为一种可取之处。这不是一个经济上的选择,所以劳拉试图依靠任何她能负担得起的虚拟帮手。亚马逊运送她的早餐,网飞在与高管们开会时逗她的孩子开心,Doordash 送来温暖的餐盘,让家人聚在一起。有了这些虚拟助手,她至少可以为陈腐的事情关掉决策肌肉,专注于大局。虚拟助手并不总是做出最好的选择,但谁有时间记分。劳拉偶尔会喝脱脂牛奶,而不是通常的 2%。她有时会发现孩子们正在看一部恐怖电影,尽管这类内容是禁止的。时不时地,Doordash 的厨师会忘记劳拉点的是无麸质的,这就导致了大家再熟悉不过的紧急冷冻晚餐。推荐人 AI 本意是好的。
推荐器生成
我们的生活在自动驾驶仪上运行,对我们许多人来说,这是一个急需的喘息。然而,关于算法所提建议的影响和长期后果,还有很多问题没有得到解答。“推荐人”一代大概是患了沸蛙综合症。《沸腾的青蛙》是一则寓言,描述的是一只青蛙被慢慢煮活。前提是,如果你把一只青蛙丢进开水里,青蛙会跳出来。然而,如果你把青蛙放在温水中,慢慢地把它烧开,青蛙不会察觉到危险而被煮死。这则寓言隐喻了我们无力应对逐渐而非突然出现的有害威胁。

本为那些希望优化自身潜能的人主持觉醒研讨会。多年来,本指导了来自世界各地的 500 多人。他最近承认,他对人们愿意将解决问题的任务交给更高的权威感到担忧。如果一个有资质的人提出解决方案,人们似乎会很乐意采用这些方案来解决他们的生活问题。事实上,这个人只知道他们特定的生活环境几个小时,或者有时根本不知道(想想 YouTube 视频),这是一个可以忽略的细节。为什么我们太快地放弃自主权给一个更高的权威,即使它看起来值得信任?在人工智能助手在我们的社会和私人生活中变得普遍的世界里,这种与生俱来的人类行为意味着什么?
“我们不能用创造问题时的思维来解决问题。”~阿尔伯特·爱因斯坦
人工智能科学家正在人工智能宇宙中反映人类的缺陷——毕竟,机器人反映了它们的创造者。我们从行为经济学的研究中知道,人类有先天的偏见。诺贝尔行为经济学奖获得者丹尼尔·卡内曼揭示了人类决策过程中的一些(许多)缺点。例如,锚定是一种认知偏差,即个体在决策过程中过于依赖初始信息——“锚”——来做出后续判断。一旦你确立了这个锚的价值,它就成了以后所有争论的准绳。我们吸收与锚相关的信息,而忽略不太相关的信息。另一种人为偏见是可用性偏见。它是一种思维捷径,依赖于人们在评估具体决策时脑海中出现的即时例子。如果你回忆起某件事,它一定很重要,或者至少比不容易想到的替代解决方案更重要。人们更倾向于最近的信息来衡量他们的判断,形成新的观点,这些观点被最新的消息所偏向。
寻找道德准则的灵感
医生有改善所有人健康的道德义务。自古以来,医生必须遵守规则和指导原则。医学界的标准道德誓言是希波克拉底誓言。它要求新医生宣誓遵守包括医疗保密和无罪在内的道德标准。医疗宣誓经历了几十年的演变,最重要的修订是二战后出现的“日内瓦宣言”。在许多国家,宣誓医疗誓言的修订版仍然是医学毕业生的成人礼。
人工智能科学家应该定义指导原则来解决他们工作的道德、价值观和合规性吗?这样的誓言会让科学家意识到他们的社会和道德责任。为医学以外的职业制定职业道德准则的想法一点也不新奇。类似于希波克拉底医学誓言,阿基米德誓言是工程师的职业道德准则。洛桑联邦理工学院(EPFL)的一群学生在 1990 年提出了这个誓言。随着时间的推移,阿基米德誓言在几所欧洲工程学校得到了温和的采纳。科学家有他们自己的誓言——科学家的希波克拉底誓言——由约瑟夫·罗特布拉特爵士在 1995 年诺贝尔和平奖接受演讲中提出。
伦理人工智能指南
就像医学影响人们的福祉一样,人工智能系统也会有选择地影响我们的生活体验。人工智能在现实世界中的应用如此天衣无缝,我们几乎不会注意到。我们是不是患上了沸腾青蛙综合症?陪审团还没有出来。像任何工具一样,人工智能可以用来做好事,也可以造成伤害。例如,在谷歌上快速搜索人工智能招聘,会出现像“使用人工智能消除招聘偏见这样的正面标题,但也会出现像“人工智能辅助招聘有偏见”这样的负面标题。以下是如何让它更公平的方法。
人工智能道德准则的提案已经准备就绪。一个有效的计划应该将来自工业界、学术界和政府的不同利益相关者聚集在一起。这样一个跨学科的委员会将使我们能够设计一个值得生活的未来。
艾轻松地解释道
很容易解释
5 分钟看懂 AI
你会如何向一个中世纪的时间旅行者解释汽车是什么?简单地说,他缺少太多的知识:他不知道什么是电、燃料和电池。你可以对他说的是,车是一个工具,可以把你从 A 点带到 b 点,说真的,他还需要知道别的吗?
就像汽车一样,你不需要了解可燃发动机的机械设计和工作原理就能理解它的用途。

一个简单的方案,你可以如何代表一个人工智能的决策过程:特征,标签和规则。稍后,将对此进行详细解释。
问题
你想知道人工智能是什么的唯一原因是想知道你能用它解决什么问题。
我说的问题这个术语是什么意思?如果你希望使用人工智能,你需要数据。你想从数据中提取什么,本质上是一个你要解决的数学问题。一些问题的例子是:
例如,如果你有一个关于新冠肺炎的数据集(数据集本质上是一个包含数据的 Excel 表格),你可能想预测明天世界上会有多少新病例。
如果你有一个包含数百万封电子邮件的数据集,你希望将垃圾邮件与非垃圾邮件区分开来,如果你有一个路标数据集,你希望计算机能够通过将它们分成不同的类别来识别它们。
这里列出了 AI 可以为你解决的常见问题。如果你碰巧有任何包含信息的数据集,并且知道你想要解决什么问题,使用适当的工具你可以用个人电脑(甚至在 Google Drive 上)免费创建一个人工智能。这让你对 2020 年这项技术的可用性有所了解。

您可以使用人工智能解决的最常见问题列表
这些是机器学习中最常见的统计模型类别。您可以选择使用哪一个来解决您的问题。(这两个缺失的统计模型被称为关联和降维,但它们并不实用,因此不在本文中讨论)。
为什么这么多例子?
当然,你可以用 AI 解决的问题并不仅限于这里列出的问题,但这是一个最实际和最常见的问题的集合。
如果我只列举一个例子,你可能不会理解它的实际用途。有这么多的例子,你可以看到不同领域的实际应用。如果你正在管理一家公司,你希望充分利用它的数据,你有很多选择:预测未来收益,更详细地了解你的目标…
AI =机器学习
为了最大限度地降低其复杂性,你可以将 AI 视为可以应用于数据的统计模型的集合。这个庞大的集合被称为机器学习。

我们可以从许多统计模型中选择
机器学习也分为两个子类别:有监督的和无监督的。每个类别都包含大量的统计模型。鉴于我们的问题,我们只需选择统计方法。
《出埃及记》

给定一个问题,我们选择最佳的统计模型
我们陈述了我们的问题:我们希望预测明天在我们国家会有多少新的新冠肺炎阳性病例。在众多的统计方法中,我们选择使用第一张图,这是一种回归方法。(数据分析师需要选择具有最佳参数的最佳模型,这就是为什么在本文中您找不到任何关于我们如何从一个模型中选择另一个模型的信息)。
数据的作用
因为有两类问题可以用人工智能解决,我们将首先研究监督学习。下面的例子显示了一个表格数据,一个简单的 Excel 文件:一个数据集。
要用 AI,需要数据。数据越多越好。

上面我们有所有 627 名泰坦尼克号乘客的数据。问题:我们能否建立一个能够预测谁能在“下一个泰坦尼克号”中幸存的人工智能?
我们知道问题所在。现在我们必须选择统计模型:
机器学习>监督学习>分类

分类是我们一直选择的统计模型
功能和标签
所有人工智能共有的元过程如下:这就是你需要理解的全部。我们将数据分为两部分:
特性
允许我们预测数据的列。在这种情况下:性别,年龄,兄弟姐妹,羊皮纸,票价,阶级,甲板,上船 _ 镇,独自
标签
我们想要预测的列。在这种情况下,该列“幸存”。

问题:考虑到一名新乘客的特征,n. 628(女性,24 岁,有一个兄弟姐妹,parch 0,75.05 美元票价,头等舱,D 舱,从瑟堡出发,不是一个人):她能活下来吗?
现在我们有了特征和标签,人工智能将提出一些规则。
训练人工智能:发现规则

通过使用我们选择的算法(我们的统计模型),发现了规则。我们可以使用相同的规则来解决我们的问题,并根据他的数据(性别、年龄、兄弟姐妹……)找出谁将能够在泰坦尼克号上幸存。
预测:第二艘泰坦尼克号
现在,让我们假设有第二艘泰坦尼克号。我们仍然不知道谁幸存了下来(标签“幸存”不见了);我们有特色,因为我们的 AI 已经训练好了,所以我们也有规则。

我们还不知道谁能从泰坦尼克 2 号中幸存下来

给定特征和规则,我们可以预测标签:谁将在泰坦尼克 2 中幸存。
摘要
这是整个过程的概要:

就这样吗?
我给你们展示的是人工智能的三个范例之一:监督学习。

当您足够幸运地同时拥有特征和标签时,您可以使用监督学习方法来解决它。如果你只发现自己有特征(例如,猫和狗的图像集合),那就叫做无监督学习:你会使用不同的统计模型。
-
- *第三种范式被称为强化学习,但目前还不知道这是一个实际的东西。
为什么这么多算法?
当你增加复杂性时,你可以看到每种人工智能方法都有无数不同的算法。为了解决你的特定问题,你需要一个特定的算法。

AI 和统计学有什么区别?
你可能很好奇 AI 和统计学在这一点上的实际区别是什么。有了统计,你就可以做预测,人工智能也一样。有区别吗?
简单地说:人工智能是一组用来进行预测的统计工具。
我在这篇文章中遗漏了什么
这篇文章的目的是给你一个想法,如果你有数据要分析,你可以如何使用人工智能。深度学习是一种非常强大的人工智能,但出于简化的目的,没有提到它。同时,我省略了 AI 训练的其他详细程序,包括特征选择和测试。
因此,请将本文的内容视为理解人工智能所需的一般原则。
AI Feynman 2.0:从数据中学习回归方程
麻省理工学院马克斯·泰格马克实验室的新人工智能库
让我们在一个全新的图书馆上踢轮胎

图片来自皮克斯拜 (CC0)
目录
1.简介
2。代码3。他们的例子
4。我们自己的简单例子
5。噪声数据的符号回归
1.一个新的符号回归库
我最近在 LinkedIn 上看到麻省理工学院教授 Max Tegmark 关于他的实验室发布的一个新的 ML 库的帖子。我决定尝试一下。论文名称为 AI Feynman 2.0:利用图模块性的帕累托最优符号回归,提交于 2020 年 6 月 18 日。第一位作者是席尔武-玛丽安·乌德瑞斯库,她很慷慨地和我通了电话,解释了这个新的机器学习库的背景故事。这个名为 AI Feynman 2.0 的库有助于将回归公式与数据进行拟合。更具体地说,它有助于使公式适合不同复杂程度的数据(按位定义)。用户可以从一组运算符中选择求解器将使用的运算符,求解器将完成它的工作。运算符是指诸如取幂、余弦、反正切等运算。
符号回归 是一种将用户指定的数学函数串在一起,为输出“y”构建一个最适合所提供数据集的方程的方法。所提供的数据集采用每个输入变量 x0、x1 等的样本点(或观察值)的形式,以及相应的“y”。由于我们不想在数据上过度拟合,我们需要限制方程允许的复杂性,或者至少有能力在复杂性约束下求解。与神经网络不同,学习一个只有几个简短表达式的公式会给你一个高度可解释的模型,并可能导致你从具有数百万权重和偏差的神经网络模型中可能得不到的洞察力。
这为什么有意思?嗯,科学往往会产生大量的观察结果(数据),科学家们希望将其归纳为潜在的规则。这些规则是“符合”观察结果的方程式。与“通常的”机器学习模型不同,形式为 y=f(x) 的方程非常清晰,它们可以省略数据中一些不需要的变量。在实践机器学习工程师的工具箱中,回归树%20are%20called%20regression%20trees.&text=In%20decision%20analysis%2C%20a%20decision,represent%20decisions%20and%20decision%20making.)将是我能想到的最接近的概念,它实现了学习将观察与预测联系起来的可解释模型的想法。有一种新的方法来尝试将回归模型拟合到数据,这是对您可以在数据集上尝试的工具箱的一个很好的补充。
在本文中,我想作为一个用户(如何使用它)来探索这个新库,而不是作为一个科学家(它是如何工作的)。AI-Feynman 2.0 让我想起了 UMAP ,因为它在求解器内部包含了非常奇特的数学,但以一种抽象的方式做了一些对我有用的事情,我可以将其视为一个黑盒。我知道代码将在接下来的几个月里分阶段更新,所以当你阅读这篇文章时,今天代码的界面看起来可能不是它的工作方式。希望还会添加更多的文档,为您提供在数据上尝试这种方法的快速途径。目前,我在这篇文章中包含了一个笔记本,这样你就可以一头扎进去,从一个地方开始工作。
该库使用机器学习来帮助方程发现,递归地将问题分解为子问题,但我们不要太深入。让我们转而关注图书馆的使用。欢迎您阅读该论文,以了解更多关于该库如何解决数据上的符号回归之谜的信息。
2.密码
包含本文所有代码的 Google Collab 笔记本可从这里获得:
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/dcshapiro/AI-Feynman/blob/master/AI_Feynman_2_0.ipynb)
关于输出 的一些注意事项很重要。求解器多次打印出复杂度、 RMSE、和表达式。要知道,RMSE 数实际上并不是均方根误差。这是本文中描述的平均错误描述长度(MEDL ),这一信息将很快改变。此外,表达式打印输出不是数据集的等式,而是求解器当前正在处理的整个问题图中的子问题。这一点很重要,因为你会发现有时打印出来的结果看起来误差很小,但它只适用于某些子问题,而不是你要找的方程。最终结果使用输入文件的名称存储在结果文件夹中。
3。尝试来自 AI-Feynman 知识库的第一个例子
克隆存储库并安装依赖项。接下来,编译 Fortran 代码并运行 AI-Feynman 存储库中的第一个示例数据集(存储库中的 example1.txt)。
下面列出了最初的几个步骤:
接下来,将这个文件放入代码目录,并使用 python3 运行它:
example1.txt 文件的第一行是:
1.6821347439986711 1.1786188905177983 4.749225735259924 1.3238356535004034 3.462199507094163
示例 1 包含从方程生成的数据,其中最后一列是回归目标,其余列是输入数据。以下示例显示了 example1.txt 文件的第一行与用于生成数据的公式之间的关系。
通过运行上面的代码片段,我们可以看到 example1.txt 中的目标“y”数据点是使用第 3 行的等式生成的,其中输入是除最后一列之外的所有列,等式生成最后一列。
让我们现在运行程序。在文件夹 AI-Feynman/Code/ 中,运行命令python 3 AI _ Feynman _ magic . py以运行我们上面编写的程序,该程序进而将方程拟合到 example1.txt 数据集。
求解器运行很长时间,尝试不同复杂程度的不同类型的方程,并评估每个方程的最佳拟合。当它处理解决方案时,它打印中间结果。如果它遇到一个超低的错误,你可以停止程序,只使用方程。如果你让它跑到最后,那真的是你说了算。对于输入文件 example1.txt ,结果显示在AI-Feynman/Code/results/solution _ example 1 . txt中。还有其他产生结果的地方,但这是我们现在关心的地方。该文件“解决方案 _…txt ”对确定的解决方案进行排序。有趣的是,假设 y 是一个常数是求解者的常用策略。常量没有输入变量,因此就位数而言,它们的复杂性较低。在例 1 的情况下,方程((x0-x1)* * 2+(x2-x3)* * 2)* * 0.5拟合最好。
4.试试我们自己的简单例子
在 Collab 笔记本中,我现在将存储库和数据移动到 Google Drive,这样它们就可以持久保存。下面的代码从一个等式中生成 10,000 个例子。这个例子有 2 个“x”变量和 2 个重复的“x”变量。当然,y 仍然是输出。
绘制第一个变量与 Y 的关系,我们得到:

在我们的例子中,x0 对 y 的坐标图

在我们的例子中,x2 对 y 的绘图
既然我们已经看了一眼我们的数据,让我们要求求解程序使用我们的数据集找到一个适合我们的数据的简单方程。我们的想法是,我们希望求解器注意到,为了拟合数据,您不需要所有提供的变量。
下面是一个权限问题的示例:
如果您在尝试运行代码时遇到文件权限问题,请像这样打开文件权限:
chmod +777 AI-Feynman/Code/*
下面是运行求解器的命令。去买咖啡,因为这不会很快…
python3 ai_feynman_duplicate_variables.py
如果你没有更好的事情要做,就看着求解器走吧。请注意,求解器在混合之前会遍历一系列方程类型。它尝试的初始模型很快映射到 x0 和 x2,因为它“意识到”x1 和 x3 是重复的,因此不需要。后来,求解器找到了方程3.000000000000+log(sqrt(exp((x2-x1))))这有点疯狂,但看起来像一个平面。

来源: WolframAlpha
我们可以在 WolframAlpha 上看到这个等式的等价形式是:
y=(x2 - x1)/2 + 3.000000000000
这就是我们用来生成数据集的!
求解器确定了 y = log(sqrt(exp(-x1+x3))+3.0,从上面的 wolfram alpha 中,我们知道这是对我们平面的正确描述。求解器最终使用 x1 和 x3,删除 x0,因为它是 x1 的副本,因此不需要;同样,删除 x2,因为使用 x3 时不需要它。
现在,那起作用了,但是它有点像垒球的问题。数据有一个精确的解,所以它不需要拟合噪音数据,这不是一个现实的真实世界的情况。真实数据很乱。现在让我们向数据集添加噪声,看看这个库是如何支持的。我们不需要引入缺失变量和插补。让我们把问题变得稍微难一点,让解算器更难处理。
5.噪声数据的符号回归
以下代码在与上一个示例相同的平面上创建点,但这次添加了噪波。
注意:在笔记本代码中,我将数据集大小增加到 100K 个样本(来自当前的 10K 样本),使数据集大小类似于示例 1。你不需要这样做,所以我把这个要点作为 10K 样本。
下图显示了重复列现在如何不再是完全重复的。求解程序会对带有噪声的点进行平均以获得更好的信号吗?我会将 x0 和 x1 平均为一个更清晰的点,然后将 x2 和 x3 平均为一个更清晰的点。让我们看看求解器决定做什么。




绘制 x0、x1、x2 和 x3 与 y 的关系。标签是列号。0 代表 x0,1 代表 x1,依此类推。最后一列,第 4 列,是 y。
我们现在制作另一个跑步者文件如下:
如果你有权限问题,做 chmod 777 的事情,或者 775 或者别的什么。要运行该程序,请执行以下操作:
python3 ai_feynman_duplicateVarsWithNoise.py
当求解者处理想法时,它会想出一些疯狂的东西。您可以在下图中看到求解器尝试的一个解决方案中类似平面的形状:1.885417681639+log(((((x1+1)/cos((x0–1))+1))。不幸的是,它在这里尝试的两个变量是 x0 和 x1,它们是彼此的副本,只添加了少量的噪声。

求解器早期解决方案之一的 WolframAlpha 3D 图。
不错的尝试求解器。让我们继续运行,看看接下来会发生什么。
求解器找到了方程:
*y = 3.0–0.25 (x0+x1)-(x2+x3))
正如我所希望的,求解器计算出平均 x0 和 x1 可以得到更清晰(噪声更小)的 x01,平均 x2 和 x3 同样可以得到噪声更小的 x23。回想一下,在我们向输入中添加噪声之前,用于生成“y”的原始公式是对输入数据进行运算的:
y = -0.5x01+0.5x23+3
有趣的是,求解者还发现
y = 3.000000000000+log(sqrt(exp((x2-x0))))
这是该公式的另一个版本,它使用更少的变量来换取稍微不太完美的数据拟合(因为添加了噪声)。因此,规划求解为用户提供了查看适合不同复杂程度数据的公式的选项。
6.结论
本文测试了一个名为 AI-Feynman 2.0 的符号回归解算器,从回购中的例子开始,到我们自己从头制作的例子,最后通过添加一些噪声来挑战解算器。转载本文的笔记本可以在 这里 找到。
特别感谢席尔武·玛丽安·乌德瑞斯库帮助我更好地理解代码,并审阅了这部作品的早期草稿,以确保我没有说傻话。尝试现实世界的问题会很有趣。我已经为Gravity-ai.com容器化了这个库,以应用于真实世界的数据集。希望您会发现它很有用,并将其用于您自己的工作。
如果你喜欢这篇文章,那么看看我过去最常读的一些文章,比如“如何给人工智能项目定价”和“如何聘请人工智能顾问”还有嘿,加入快讯!
下次见!
——丹尼尔
lemay . ai
丹尼尔@lemay.ai
用于 3d 打印的人工智能(第一部分):基于 K-均值聚类的异常熔池检测
本文是 3d 打印人工智能系列的第一部分。阅读 第二部分 和 第三部分 。
几个月前,我刚刚完成了机械工程硕士学位的最后一年计算机视觉项目。这是一个有趣的项目,因为它展示了如何使用各种机器学习模型来检测和分类 3d 打印过程中出现的异常。这一系列文章是我在进行项目时试图说明我的一些关键学习点和思维过程。希望它能激励机器学习(或数据科学)以外领域的专家在解决各自领域的新问题时考虑使用机器学习作为工具。
免责声明 : 这不是一个循序渐进的教程。为了避免冗长的讨论,省略了一些细节。
背景
为了提供背景,增材制造(AM,广义上称为 3-D 打印)指的是以分层和增材方式打印出产品的各种制造技术。与传统的制造方法相比,调幅具有许多优点。首先,由于其逐层印刷方法,在 AM 中可以避免传统制造技术中常见的材料浪费问题。更重要的是,AM 提供了前所未有的设计自由度,因为具有复杂几何形状的制造零件可以轻松打印出来。这也意味着零件设计和制造过程可以优化,以获得更高的结构强度重量比。在应用方面,AM 的优势使其对医疗工程、汽车、航空航天等行业极具吸引力。

LPBF 扫描的横截面。一旦当前印刷层被固化,更多的金属粉末将被散布在当前层的顶部用于随后的印刷。(图片由作者提供)
在这个项目中,感兴趣的调幅技术被称为激光粉末床融合,LPBF。在 LPBF 中,脉冲激光束扫描预定的路径,并逐层打印出最终零件的横截面。首先,金属粉末将通过印刷平台顶部的辊均匀地散布。在扫描过程中,来自激光束的高能量密度产生局部区域,在该区域中金属粉末主动熔化并熔合在一起,形成被称为熔池的局部区域。一旦该层完成印刷,更多的粉末将被散布在固化的横截面上。在随后的扫描中,新层和固化层将融合在一起,整个过程一直持续到打印完成。

脉动熔池的慢动作同轴记录。注意偶尔的飞溅颗粒喷射和熔池不稳定的尾部。
虽然 AM 提供了很大的好处,但是由于缺陷形成而产生的不一致的零件质量极大地阻碍了它在大规模制造中的广泛采用。类似于其他类型的 AM 技术,LPBF 产品也遭受缺陷形成。这些缺陷的形成主要由对熔池中的局部温度场非常敏感的构造中的微结构发展所控制。很明显,在不利的印刷条件下,会促进缺陷的形成,但即使使用优化的扫描参数,缺陷仍可能意外形成。
目标
这个项目的主要目标是开发用于异常熔池检测和分类的机器学习框架。熔池几何形状的研究至关重要,因为熔池条件会直接影响成型质量。具体来说,正如我们将在后面看到的,熔池成像数据以视频帧的形式出现,我们将建立模型来量化这些熔池的异常程度。对于缺陷研究来说,知道异常何时发生是不够的。研究工程师还对缺陷形成的熔池动力学研究感兴趣,即不同尺寸和形状的熔池是如何形成的,以及它们对成型质量的影响。因此,异常熔池也必须根据其几何形状进行分类。
简而言之,给定一个熔池框架,我们希望用某种度量来量化它的异常程度,如果这个度量超过某个阈值,那么我们将基于它的几何形状对熔池进行分类。
如上所述,即使有正确的扫描参数,缺陷的形成仍然是不可避免的。因此,该项目的长期愿景是将经过良好测试的机器学习模型整合到 LPBF 现场监控系统中,以便能够对印刷工艺参数进行实时控制和监控,从而最大限度地降低制造过程中形成缺陷的可能性。这也意味着,对于实时检测,我们的模型处理数据的速度很重要。目前,数据采集速度为 100k FPS。同样地,如果我们想要将任何类型的演算法整合到 3d 印表机中,每一个视讯画面的资料处理速度必须少于 10 微秒。
数据
- 用于分析的主要数据包括印刷过程的同轴熔池视频帧。熔池的温度是同轴解析的(即我们跟随熔池移动,因此它将保持在屏幕的中心),并在打印的同时记录。
- 我们还有位置数据集,为熔池视频帧提供位置参考。
用于打印该数据集的预定义扫描路径被称为曲折策略(基本上是之字形路径)。因此,在我们的数据集中,我们有向相反方向移动的熔池。
探索性数据分析
在探索性数据分析(EDA)中,对一些熔池进行了检查,以获得对数据集的早期理解。这对于建立对数据集中潜在异常类型的预期至关重要。给定数据集中的一些熔池视频帧随机显示如下。请注意,给定的数据集由聚焦和失焦的熔池帧组成。

聚焦和失焦印刷的随机取样熔池图像
一些类型的熔池在许多随机观察中一致出现。例如,一些熔池具有不稳定的尾部。带有不稳定或分离尾部的熔池可能导致剥蚀,由于熔体流的表面张力,周围的金属粉末被吸向熔池。这改变了局部粉末形态,并可能导致孔隙缺陷。此外,我们还在熔池周围观察到羽流喷射。通常,羽流的尺寸较大,形状快速变化且不规则,与普通熔池不同。最后,还观察到飞溅颗粒离开熔池的快照。飞溅颗粒是未熔化或部分熔化的粉末颗粒。由熔池周围的涡流循环引起的飞溅颗粒的喷射使熔池周围的金属粉末重新分布,这又会导致气孔问题。

尾部分离、羽流和飞溅粒子喷射
根据观察到的熔池动态,开发了一些粗略的指标来帮助理解数据集。每个指标旨在回答关于熔池动力学的不同问题:
- 子区域平均值(SRM) 是视频帧的外边界中的平均像素强度的量度(定义为在所有 4 个方向上距离视频帧边缘 20%的宽度),并提供关于飞溅颗粒的分散性的见解,
- 亮像素比例(PBP) 测量亮像素的覆盖范围或熔池的大小
- 像素值的标准偏差(SD) 由于像素亮度与解析温度成正比,因此可洞察熔池温度场的分布。
计算出的度量被标准化,并相对于帧数或扫描进度绘制。根据该图,我们意识到,当聚焦高度为 0 和 4 毫米时,指标相对更稳定,幅度更小。

扫描过程中各种标准化指标的时间变化。
不涉及太多细节,该图对应于具有不同聚焦高度的九个圆柱形块的印刷。具有相对稳定度量的区域对应于具有 0 和 4mm 聚焦高度的印刷。
特征提取
记住,这里的目标是识别在一组优化的参数下产生的异常熔池(何时何地发生)。来自 Skimage 模块的 Python 的 Regionprops 函数用于提取几种类型的熔池和飞溅颗粒特征。这些功能与以下内容相关:
- 大小
- 古怪和
- 数量(仅飞溅颗粒计数)
举例来说,下面是熔池和飞溅颗粒尺寸的分布:

不同聚焦高度下熔池(假定为视频帧中最大的斑点)的面积或大小直方图。

飞溅面积或飞溅颗粒大小的直方图。
同样,这些分布与 EDA 的观察结果一致,即聚焦高度为 0 和 4 mm 的熔池印刷更稳定(具有更一致的尺寸和更少或更小的飞溅颗粒)。
随后,对区域 props 特征进行标准化,并对来自焦点高度= -4 mm、0、4 mm 和 8 mm 的那些熔池帧的标准化特征采用 K 均值聚类。为了方便起见,来自-4 mm 和 8mm 数据集的所有帧被标记为失焦,而来自 0 和 4 mm 数据集的帧被标记为聚焦。区域 props 特征被传递给 k-means 聚类算法,然后标签被用于聚类分析。

用于确定聚类数的肘形图,k 表示 k 均值聚类。
根据弯管图,选择 k=15。增加聚类的数量,k 将导致误差平方和(SSE)的递减,而降低 k 将导致大的 SSE。
聚类分析

聚类分析:已识别聚类中聚焦(或失焦)熔池的比例。
做了一个重要的假设,即重点数据集中的大多数熔池是正常熔池(非异常)。因此,后续聚类分析的目标是找出最能代表聚焦熔池的聚类。基于聚类分析,聚类 1 和聚类 9 最好地代表了按比例集中的熔体池。此外,分析显示,聚焦熔池彼此更接近,而离焦熔池分散在标准化特征空间的各处。
执行快速健全性检查,聚类的质心坐标(在逆变换回预先标准化的特征空间之后)确实支持我们的假设。簇 1 和簇 9 的形心具有零飞溅特性,同时具有相似的熔池尺寸和偏心率。

区域属性特征空间中聚类的质心值
聚焦熔池更集中,而离焦熔池分散在特征空间的各处。
从集群中可视化聚焦熔池框架:

来自簇 1 的熔化池。

第九组的熔池。

其他星团的熔池。
很快,我们可以看到来自不同团簇的熔池的视觉外观差异。簇 1 和簇 9 中熔池更干净,没有太多的飞溅喷射,且在尺寸和几何形状上更一致。另一方面,来自其它团簇的熔池在尺寸、几何形状和动力学方面不太一致。
一些想法
理论上,我们可以为区域 props 特征确定一些合适的阈值,然后实时提取熔池特征以标出异常。这将允许我们绕过任何机器学习步骤。然而,区域道具提取每个视频帧的特征需要大约 10 毫秒,比视频的每秒帧数慢大约 100 倍。此外,我们最终可能会有太多的指标来跟踪异常检测。对此的补救办法是只提取异常熔池的特征用于缺陷研究。也就是说,在特征提取之前,我们采用异常检测框架来检测异常。由于异常很少发生,我们也许能够显著减少需要区域道具处理的帧数。
通过 K-Means 聚类分析,我们观察到正常熔池在特征空间中倾向于彼此靠近,而异常熔池倾向于分散在正常熔池周围并远离正常熔池。被称为一类学习的无监督机器学习概念是这类问题的合适候选,我们将在第 2 部分对此进行更多的探讨。
结束语
本文说明了如何使用区域 props 函数和 k-means 聚类等简单技术和工具从熔体池数据集中标记出视频帧异常。在下一篇文章中(3-D 打印系列的 AI 第 2 部分,我们将展示第一个用于异常检测的机器学习框架。感谢阅读:)
三维打印的人工智能(下):异常熔池检测的一类学习
本文是 3d 打印人工智能系列的第二部分。阅读 第一部分 和 第三部分 。
从第 1 部分中,我们得出结论,需要为 LPBF 现场监控系统定义一个单一的度量标准来测量熔池视频帧的异常程度。理想情况下,该度量的评估应该在计算上不昂贵,从而可以在接近实时的设置下计算。本文介绍了一个异常检测框架,该框架以一类学习的概念为中心。
免责声明:本文的目的是展示如何将不同的模型放在一个异常检测框架中。诸如超参数微调和模型架构的细节将被省略。
介绍
单类学习是一种无监督的训练分类器的方法,当数据集中的一些类要么数量很少,要么没有明确定义的特征。不平衡的数据集问题引入了过度拟合的风险,因为受监督的机器学习模型通常难以推广到少数类。通过一类学习,分类器被训练成专门从单个类中识别良好表征的实例,因此这种类型的分类器也被称为一类分类器。
在检测异常熔池的情况下,尽管异常熔池的比例相对于正常熔池较小,但理论上,我们可以通过生成一组具有较差印刷过程的异常训练样本来修复数据不平衡。故意产生的异常是否与真实异常具有相同的分布将是一个问题,但更重要的是,这里的真正问题是异常没有被很好地表征。这意味着手动注释异常容易出现不一致的错误,这是由于异常的定义不太明确(例如,熔池必须喷射多少飞溅颗粒,这些颗粒必须有多大才能被认为是异常情况?).一级学习提供了监督培训的替代方案,因为培训阶段不需要贴标签。
有一些单类学习算法的例子,例如自动编码器和单类支持向量机。在这个项目中,使用深度卷积自动编码器进行异常检测的实验。
通过一个类的学习,我们可以分配一个连续的度量来测量熔池异常的程度。在无监督的基础上操作,一类分类器不需要用于训练的标记数据。
自动编码器
本节简要介绍自动编码器。

自动编码器的一般结构。
上图显示了自动编码器的一般架构。自动编码器由两个主要部件组成,即编码器和解码器。编码器将高维输入数据压缩到低维潜在空间,这是自动编码器架构的瓶颈。解码器然后将编码解码回原始维度空间。编码-解码过程受到输入和输出在欧几里得意义上必须相似的约束。
数学上,这可以写成,Z= g(X)和X '= f(Z)服从X≈X ',其中

自动编码器的损失函数
用于自动编码器训练的损失函数是 X 和X’之间的欧几里德距离。自动编码器的目标是在训练过程中最小化损失函数,使得结果输出类似于输入数据。注意,损失函数也是输入和输出之间不相似性的度量。因此,它也被称为重建误差(RE)。
由于瓶颈中的维度空间较小,编码器被迫只对瓶颈输入中最具代表性的特征进行编码,以允许解码器重构输入数据。决定潜在空间的维度是至关重要的,因为小的维度将对从编码器到解码器的信息流施加太多的限制,使得解码器难以重构输入数据。另一方面,对于过大的潜在维度,编码器将不会学习捕捉输入数据的重要特征,因为对信息流没有施加太多的限制。
数据预筛选
本节介绍了用于培训数据准备的数据过滤方法。如上所述,一类学习要求异常实例是训练数据集中的少数。确保所需约束的快速方法是通过使用无监督聚类算法,例如 k-means 聚类。具体来说,来自聚类 1 和 9 的聚焦解链池被混洗并用于训练我们的自动编码器。

来自聚类 1 和聚类 9 的聚焦解链池用于自动编码器的训练
由于自动编码器在训练过程中暴露于大多数正常的熔池图像,它将学习捕获基本的正常熔池表示,使得大多数重建的输出与输入相似。这导致整体训练损失较小。
异常检测
重构误差(RE)度量用于测量输入和重构输出之间的差异。作为健全性检查,计算并可视化离焦熔池的 RE 度量。

健全性检查:经过训练的自动编码器应用于失焦熔池视频帧。
如图所示,自动编码器未能重建所遇到的异常,结果,度量尖峰指示异常事件的发生。测试还表明,对于离焦印刷,RE 提供了异常程度的良好的相对测量。例如,与较小的羽流实例相比,覆盖范围较大的羽流实例会产生较大的 RE。

从(a) RE <0.003 (b) 0.004
下面还介绍了一些异常的熔池重建。

原始(第一行)、重建(第二行)和错误熔池图像,顶部为 RE x 10(第三行)
请注意自动编码器如何无法重建异常部分,如熔池的不稳定尾部和飞溅颗粒。为了比较,下面显示了具有较小 RE 的熔池图像。

原始(第一行)、重建(第二行)和错误熔池图像,顶部为 RE x 10(第三行)
我们还可以将熔池视频帧投影到二维散点图上,以显示熔池图像。下面显示的是具有锚定的训练熔化池视频帧的第一潜在成分对第二潜在成分的图。

对于一些训练数据点,第二潜在分量 Z2 相对于第一潜在分量 Z1 绘制。
有趣的是,自动编码器捕捉熔池的移动方向,正常的熔池确实在潜在空间中以簇的形式出现。

对于一些测试数据点,第二潜在分量 Z2 对第一潜在分量 Z1 作图。
对于类似的图,但是在测试数据上,我们观察到一些异常位于远离集群的位置。
模型性能评估
接下来,标记了大约 1500 个看不见的数据点。然后,标记的数据点可用于帮助确定合适的 RE 阈值,并量化自动编码器的性能。

用于确定最佳 RE 阈值的 ROC 曲线
用受试者工作特征(ROC)曲线确定合适的 RE 阈值。注意,异常被定义为正类,而正常熔池被标记为负类。
最后,根据确定的 RE 阈值,对自动编码器在两种熔池类别的召回率和精确度方面的性能进行了评估,并总结在下表中:

一些想法
测量该异常检测框架所需的时间,从最小最大归一化图像到重新计算,自动编码器平均花费 1 微秒来输出预测。这比单独的区域道具特征提取快大约 1000 倍。更重要的是,图像处理也比所用的 LPBF 原位监测系统的 FPS 更快。
作为一个完全无监督的模型,自动编码器的训练不需要任何人工标记,这是一个巨大的努力节省,因为有监督的深度学习模型通常需要大量的标记数据。总的来说,一类学习框架的实现显示了 LPBF 原位监测的巨大计算时间节省。随着处理速度的加快,我们现在可以有选择地提取熔池的特征,用于后续的异常分析。
或者,我们可以利用潜在向量作为训练分类器的提取特征,因为编码包含关于熔池几何形状的最有价值的信息。这将在本系列的第 3 部分中详细说明。
警告
当在一个完全不同的看不见的数据集上部署时,自动编码器的性能会有很大的不同。数据外推主要是机器学习模型的一个问题,但是,由于自动编码器通过对输入数据中最具信息性的特征进行编码来工作,因此它的使用甚至更加数据特定。这对于一个类学习的目的是好的,但是对于在不同印刷参数下产生的熔池图像,RE 的鲁棒性将是有问题的。例如,用从弯曲扫描捕获的熔池训练的自动编码器可能在从岛扫描策略重建大多数熔池图像时表现不佳,不管它们是否异常。
结束语
本文阐述了深卷积自动编码器在熔池异常检测中的应用。通过 K-均值聚类在预先筛选的数据集上训练,自动编码器能够很好地重建正常的熔池图像。未能重建异常熔池,自动编码器会产生较大的重建误差。自动编码器的使用在潜在的计算节省和性能方面显示出有希望的结果。在下一篇文章中,我们将更多地探讨普通自动编码器的概率变体在异常分类中的应用。感谢阅读:)
三维打印的人工智能(三):异常熔池分类的非纠缠变分自动编码器
本文是 3d 打印人工智能系列的第 3 部分。阅读 第一部分 和 第二部分 。
自动编码器的使用提供了一种用较少的参数描述熔池图像的方法。本质上,这是一种数据压缩形式。然而,如第 2 部分所示,自动编码器编码的潜在向量高度密集,并以簇的形式出现。因此,潜在空间不是平滑和连续的。在潜在空间中可能有严重的过拟合,其中当重建时,彼此接近的两个潜在向量看起来非常不同。这是因为缺少正则化项来控制在损失函数中应该如何压缩数据。
嗯,你可以说自动编码器为了压缩而压缩数据,因此它不一定在潜在空间中保持数据的结构。
如果我们想两者兼得,这是一个问题:
- 较小的参数(可通过自动编码器实现)和
- 高质量数据压缩(自动编码器不是为此目的而优化的)
来描述熔池的几何形状。
使用 autoencoder 的变体可以解决这个问题。本文介绍了一种自动特征提取方法,用于异常熔池检测和分类任务,其核心是使用一种无纠缠的变分自动编码器。具体地说,变分自动编码器的质量数据压缩特性将用于提取不同的熔池表示。
介绍
变分自动编码器(VAE)具有与自动编码器相似的结构,除了它是后者的概率变型。VAE 的使用假设有几个未观察到的数据生成因素(也称为表示),每个因素控制输入的不同方面。接下来,这里的目标是训练 VAE 来近似表示的分布,以便编码器可以有效地用作特征提取器。

VAE 的一般架构
VAE 的一般架构如上所示。注意,不同于普通的编码器和解码器,VAE 由两个概率组件组成。概率编码器将输入数据 X 映射到潜在向量 z 。另一方面,解码器将来自潜在空间的任何采样向量映射回原始维度【X’。

VAE 的损失函数
这个损失函数有两项。重建损失确保重建数据与输入相似。第二项,也称为KL-散度项,是数据的潜在分布和潜在编码的先前分布之间的差异的度量。当网络将输入编码到一个高度密集的区域时,它会对网络施加一个惩罚,从而促使编码获得一个类似于先前分布的分布,该分布假定为~N(0,I)。
约瑟在他的媒介文章中对 VAE 做了非常直观和清晰的解释。参见下面的文章:
逐步建立导致 VAEs 的推理。
towardsdatascience.com](/understanding-variational-autoencoders-vaes-f70510919f73)
为了获得β-VAE 的损失函数,VAE 的损失函数通过将β的因子乘以 KL 散度正则化项来修正。

β-VAE 的损失函数是由 VAE 的损失函数修改而来的。KL 散度项被赋予一个相对权重β。
本质上,这种修改允许我们控制编码的潜在成分之间的解缠结的量。当每个组件对表征的某一方面的变化相对敏感而对其他方面不敏感时,一组潜在组件被称为解纠缠。在熔池几何形状的背景下,当潜在编码被完全解开时,改变一个潜在成分将仅仅改变熔池几何形状的一个方面。而对于正常的 VAE,很难理解每个单独的潜在成分捕捉到熔池几何形状的哪个方面,因为改变一个潜在成分会导致多个变化的熔池表示。
在这个项目中,β被选择为 4,因为这个β值根据经验给出了最好的解缠结效果。
数据预处理
为了更精确地描述熔池的几何形状,熔池图像从 128x128 的尺寸裁剪为 32x32。这是因为熔池的周围不包含太多关于其几何形状的信息。我们还确保熔池的质心与图像的中心对齐。

熔池框架的 ROI。
对所有裁剪的视频帧执行最小最大归一化。与一类学习框架不同,该框架不依赖于正常熔池的任何分析。因此,数据不需要预先筛选。
特征提取
通过在熔池视频帧上训练β-VAE,编码器学习熔池潜在表示的概率分布。为了探索编码,可以从潜在维度的特定范围采样,并解码采样的潜在向量以便可视化。

具有固定的第三潜在成分的生成的熔池图像的网格。(图片由作者提供)

具有固定的第二潜在成分的生成的熔池图像的网格。(图片由作者提供)
根据生成图像的网格图,我们观察到:
- 第一个潜在分量捕捉熔池的尺寸
- 第二个潜在分量捕捉熔池的圆度。熔池图像被垂直或水平挤压。
- 第三个潜在分量捕捉熔池的尾部长度。第三潜在成分的符号也捕捉了熔池的移动方向。
此外,我们可以验证压缩是高质量的,因为熔池图像在潜在空间中平滑地从一种形式“变形”为另一种形式。此外,当我们改变单个潜在成分时,我们几乎可以完美地隔离熔池几何形状的变化。例如,增加第一个潜在成分会改变大小,但对其他两个方面几乎没有影响。这就是我先前所说的解开表象的意思。
从 Arxiv Insights 了解更多关于解开变分自动编码器的信息:
Arxiv Insights 的变分自动编码器简介。
如果我们检查训练数据的潜在成分的分布:

(a) Z1,(b) Z2 和(c) Z3 的分布
第一和第二潜在分量类似于高斯分布,而第三潜在分量类似于双峰分布(两个高斯分布的叠加)。第三潜在组分的双峰分布归因于所采用的曲折扫描策略,该策略导致熔池以之字形行进。由于β-VAE 损失函数中 KL 散度项施加的正则化力,所有分布都以 0 为中心,并具有接近 1 的标准偏差。
异常检测和分类
接下来,编码的熔池以散点图的形式呈现。

Z2 与 Z1 的散点图,带有锚定熔池图像。(图片由作者提供)

Z3 与 Z1 的散点图,带有锚定熔池图像。(图片由作者提供)
根据散点图,编码似乎与潜在的表征定性一致。此外,几个异常清楚地编码远离密集区的潜在空间。这表明使用从一些参考点的欧几里德距离度量作为异常测量。基于可视化,将数据点分类成簇也是明智的。接下来,可以计算熔化池离它们的群集质心的距离,并将其用作异常度量。
从概念上讲,这意味着一组给定的熔池特征偏离它们的平均值越多,熔池就越不规则。

(a)所有数据点,(b)由 DBSCAN 识别的异常值(橙色)和正常数据点(蓝色),(c)拟合正常数据点的 K 均值聚类,以及(d)所有数据点和两个识别的聚类的散点图。(图片由作者提供)
使用基于密度的聚类算法 DBSCAN 来清理数据,然后在清理的数据集上拟合 k=2 的 K 均值聚类。这些聚类的质心将被存储用于测试期间的欧几里德距离计算。距离度量将被用作熔池异常程度的量度。
三种不同的监督分类器,支持向量机(SVM)、K 近邻(KNN)和随机森林(RF)用于熔池异常分类任务。这次,我们明确地将熔池的类型分为几类——具有不稳定尾部的熔池、羽状熔池和大型熔池。
分类器的最优超参数通过五重网格搜索交叉验证获得。最后,使用测试数据集来量化分类器的性能。分类结果总结如下:

(a) SVM,(b) KNN 和(c) RF 的混淆矩阵
一些正确的分类如下所示:

正确的分类:( a)不稳定尾翼,( b)羽流,( c)大型熔池。
我们的 VAE 框架现在可以分配异常度量,此外,它还具有根据熔池的几何形状对其进行分类的能力。
这种一体化异常分类和检测框架在三条扫描线上的使用示例:

每个框架顶部的熔池和异常度量的预测类别。
一些想法
β-VAE 框架比端到端的监督深度学习方法(端到端的深度学习方法是,在没有任何特征提取的情况下,在标记的数据上训练监督的神经网络)具有一些优势:
- 对于异常分类问题,没有监督模型是很难进行的。β-VAE 框架通过首先提取熔化池表示来工作。这为后续的聚类和经典的监督模型提供了适当的特征空间来操作。意思是,框架的前半部分是完全无人监管的。与在没有足够数量的训练数据的情况下容易过拟合的端到端监督深度学习方法相比,β-VAE 框架的后半部分将需要较少的标记数据来进行训练。
- 就可解释性而言,β-VAE 将熔池图像分解成三个明显的清晰表示。我们已经看到并验证了表示分布与生成的熔池图像的网格图一致。至于端到端深度学习,更难解释为什么某些融化池会被归类到某些类别中。
未来的工作
未来的工作可能涉及用更精确的训练数据集来训练β-VAE。在已知限制的情况下(在一组指定的打印参数内工作),该框架可以被合并到现有的 LPBF 监控系统中。用序列模型解决这个问题是另一个有待实验的有趣方法。本质上,我们可以将熔池动力学建模为一个时间序列问题。这是有意义的,因为像羽流这样的异常情况的特征是它们在多个帧中快速变化的形状。也许用这种新的视角来看待这个问题将是建立一个更准确的框架的关键。
结束语
在这篇文章中,我们探讨了更多的数据压缩能力的一个解开变分自动编码器。通过各种可视化,我们验证了所产生的潜在空间是平滑和连续的,在某种意义上,熔池图像是相似的,彼此编码紧密。此外,利用这个框架,我们还可以提取有用的和可解释的熔体池表示,用于异常检测和分类。通过对潜在表示训练一些监督分类器,我们还表明该框架可以用于分类异常并同时量化其异常程度。
感谢阅读:)
人工智能促进可持续社会
我们不能只靠消费来实现一个更可持续的世界。—詹妮弗·妮妮

作者为寻找人工智能和可持续社会之间的中间地带而拍摄的照片。
一个现成的人工智能语言处理系统可以产生多达 1400 磅的碳排放[1]。一个基于人工智能的语言系统可以创造大约 80,000 磅,这是一个人一生呼吸量的两倍[1]。搜索和训练神经网络架构的能量大约为 616000 磅[2]',大约是美国普通汽车排放量的五倍!
你没听错;人工智能带来的大量碳足迹给科技领域带来了风险。
没错,人工智能继续呈指数级增长,并将继续存在——但环境问题也岌岌可危。人工智能不仅成为了道德问题的焦点。它也贡献了全球 3%的二氧化碳总量[3]。
问问你自己——机器驱动的社会是为了谁?
技术和社会——这两者正处于十字路口。想想有机器人的道路,有机器的人类和其他由数字驱动的一切——你看到了什么?你看到智能城市或带有偏见观点的工程意识形态了吗,或者你想象一个社会公益已经转化为社会正义的世界?
想想吧。
我们喜欢称之为工程教育,令人惊讶的是,它并不是来自基础知识。这只限于学校和社区传授的教育。在教育系统中教授一些东西只是帮助那些思想模糊的人,他们认为一切都将转变为数据驱动的生态系统,而对环境完全没有影响。Erin A Cech 博士[4]在 2013 年谈到美国如何试图强调培养有道德、有社会意识的工程师的重要性,但相反,工程教育本身未能鼓励新手将公共福利视为他们的职业责任,因此给出了一个人工智能和无知观点各占一半的伪现实。
还有更多。

由 Ridham Parikh 在 Unsplash 上拍摄的照片
去政治化——它表明社会的文化和社会问题在“真正的”工程工作中并不适用,因此应该被抛弃。也就是说,我们确实在某个地方带来了技术进步的概念,但它将如何影响我们周围的人类或环境,我们对此最不关心。没有任何思想围绕在专业人员周围所做的工程工作只是没有好处的技术。由于技术和社会被视为两个不同的支柱,这使得公共福利工程师很难理解他们在做什么,如何影响社会。我们确实需要指标,这些指标可以由“社会技术”人员带入到精心制作的图片中。
工程头脑谈论了很多事情,包括数据隐私、物联网、易访问性、5G 等等——与此同时,它打开了一个接近容易被利用的世界。教育系统的网络安全可能是最好的例子之一。由于加强了监视、监管等。在当今社会追求更好的正义,这也为不道德的手段打开了后门。在现代社会,即使我们谈论智能城市,但大部分资金确实来自政府和商界人士。
一切的基础?信任。而这正是机器所缺乏的。
嗯,解决办法?一个财团,可以被在不同环境下培养出来的人信任,让大家对他们寄予信任。至少,我们可以期待有人能够就人类现在将要付出的代价做出决定,从而纠正过去的行为,并为人类更光明的未来做出决定。需要一个基于社会正义的社会。围绕非殖民化研究方法的研究的出现,确实表明我们已经开始,我们正在走向更美好的世界。新一代确实知道我们失去了什么,也知道我们面临的现状。
最大的问题是——技术只是更智能,而不是更环保吗?
企业正在匆忙吸收数据并获得洞察力,这给了人工智能一个动力,让它变得更强大,从而提供更好的结果。但是支撑这个负担的是环境。更粗放的车型,更多的消耗,对环境的负面影响。
当“数据饥渴”的机器说话时,全世界都在倾听。
碳排放。能源消耗。减少温室气体排放。–他们都受到机器提供的闪亮见解的影响。

从 2012 年到 2018 年,深度学习的计算所需的能量增加了大约 300,000 倍[5]。机器学习模型通常需要更多的数据,并且容易消耗更多的功率。为了使这些模型更加熟练和准确,人们需要更多的训练和执行,这是一个永无止境的消费过程。
典型的例子 — OpenAI 最近推出了其最大的基于人工智能的语言模型——gp T3,在大约 5000 亿单词的数据集上进行训练,而之前的 GPT2 模型在 400 亿单词的数据集上进行训练[6]。在此之前,在 2018 年,最好的 NLP 模型 BERT 在 30 亿个单词的数据集上进行训练,BERT 的表现优于 XLNet,XLNet 在 320 亿个单词上进行训练[7]。—这些数字一开始听起来非常乐观,但随之而来的风险包括漫长的培训课程转化为更多的能源消耗,并最终导致大量的碳排放。
这条数据隧道的尽头是否有一丝曙光?
肯定有。毫无疑问,人工智能拯救了环境,促进了国家的经济发展,提供了治理的透明度。如果普华永道最近的一份报告可信的话,用于环境应用的人工智能有可能使一个国家的 GDP 增长 3.1-4.4%。

如果一切照常,到 2030 年,它可以将全球温室气体排放量减少约 1.5-4.0%,同时大幅提高 GDP[8]。早期的 GDP 增长在欧洲、北美和东亚等世界少数地区显而易见,约占 1 万亿美元[8]。能源和交通部门的温室气体排放总量可能分别减少约 2%和 1.7%[8]。尽管如此,仍然需要更加关注水和农业,因为从更广泛的意义上来说,它们在环境中发挥着重要作用。
虽然人工智能可以帮助做出正确的决定,改善气候预测,并努力分配可再生资源,但必须有一些解决方案来减轻风险。
●人工智能模型培训课程可以转移到云中,并在可再生资源消耗更大的地方附近举办。由于云可以存储更多的数据集,也更容易利用来自不同位置的数据。
●开发高效的人工智能算法会有所帮助——斯坦福集团最近开展的一项研究评估了同一任务的不同算法。结果显示,调整算法和未调整算法的耗电量相差近 880 千瓦时,这是美国家庭一个月的典型耗电量[1]。如果我们编写更好的代码或更好的模型,我们就可以对减少应用程序的碳足迹产生巨大的影响。
●根据默认配置评估程序,并在模型修复后对其进行微调。我们知道,不仅机器学习模型的训练需要高能量,消耗这样一个人工智能系统消耗的能量也远远超过训练。不仅需要算法方面的发展,还需要建立在可持续能源基础上的基础设施,以促进如此巨大的人工智能依赖应用。
好吧,让我们希望人工智能管道变得环境可持续——这难道不是字面上的两全其美吗?
参考文献:
[1]
【2】https://www . technology review . com/2019/06/06/239031/training-a-single-ai-model-can-emit-as-much-cars-as-fifth/
【3】https://www . seai . ie/data-and-insights/seai-statistics/key-statistics/CO2/
【4
人工授精的人工智能——传感器数据的深度拓扑分析
了解 TDA 和深度学习如何对事件进行分类,并发现物联网活动传感器数据流中的隐藏模式

假设您有多个传感器数据流,并且您希望能够对事件进行分类。它可以使用飞机引擎上的传感器来检测次优模式或医学诊断来检测疾病。
- 位置(三个方向的罗盘数据)
- 速度(三个方向的陀螺仪)
- 加速度(三个方向的加速度计)
使用 PowerBI 或 Tableau 等流行的商业智能工具无法分析这种类型的数据。这样的系统将无法捕捉数据中的复杂模式,也不允许你去探索它们。
然而,这对于深度拓扑分析(DTA)和复杂模式的视觉理解来说是一个很好的情况。DTA 是无监督机器学习的一个例子,这意味着您不需要在分析之前标记您的数据。输出是忠实于基础数据但对主题专家来说是直观的行为聚类。这种更精炼的方法可以让你发现你不知道的你不知道的。

流程的高级表示
首先,一个人类的例子
手机是运动数据的典型来源:x、y、z 平面上的位置、速度和加速度。

手机活动集群化,包括 smartlab 提供的视频【1】
对这些数据运行 DTA 可以让您看到算法是如何工作的(见图片)。每个点都是一个短暂的时间窗口,两个点越靠近,在该窗口中发生的行为越相似。自然的行为集群从算法中出现,这些集群可以很容易地被主题专家识别(在这种情况下,我们都熟悉在房子周围移动)。
广泛的集群——站立、坐着和躺着——立即显现出来。但是放大图像会显示更多有趣的子结构,比如上楼、下楼和其他类型的有趣行为。这种类型的可视化给出了对那些了解该领域的人有意义的集群的广泛分布,并且在许多情况下,子结构增强了对主题专家的理解。

使用手机拍摄的活动片段
艾对一瘸一拐的牛

不是一瘸一拐的牛,跳舞的牛 youtube 视频
一个好的农民了解他的奶牛,并且知道它们什么时候发情。但是用一个低成本的项圈远程做到这一点是一个数百万美元的数据科学挑战。每个项圈都安装了一组传感器,可以全天候捕捉数据,并每分钟发送一次数据快照。每个传感器产生 9 个数据流:
- 位置(三个方向的罗盘数据)
- 速度(三个方向的陀螺仪)
- 加速度(三个方向的加速度计)
所以每头牛都有很多数据要分析,我们可能在谈论成千上万头牛。
解决这个问题的一个简单方法是测量行走的距离——奶牛发情时会走更多的距离。然而,更精确的分析包括推断所述奶牛的事件和行为。这导致对奶牛正在做什么以及它们处于什么状态有了更完整的了解。重要的是,这种类型的分析可以让你发现你以前不知道的活动,比如跛行或疾病。
当数据变大时,标准方法很快就会丢失细节或完全失效。一些不起作用的方法有:
- 主成分分析(PCA) —非常快,但通常不适用于人工分析,因为容易产生斑点
- 多维扩展(MDS) —无法识别结构,速度太慢,对于大数据量来说内存不足
- t-SNE——取得了一些成功,但经常遗漏细节,或者发现太多细节并导致错误的聚类,从而歪曲了数据的实际结构
- UMAP——是一种很好的最新算法,它的性能优于 t-SNE,尽管它没有深度学习那样的学习能力来从数据中捕捉复杂的高级模式
使用所讨论的算法处理来自奶牛传感器的数据。所有算法都使用默认的元参数执行。

PCA、MDS、t-SNE 和 UMAP 算法提供的嵌入
如你所见,主成分分析和 MDS 未能从数据中捕捉到任何结构。另一方面,t-SNE 似乎捕捉到了太多的结构,其中大部分并不存在于数据中。UMAP 显示了有希望的结果,尽管聚类不如 DTA 那样明显,并且结构有些模糊。DTA 结果如下:

对 43 头奶牛的活动进行聚类,聚类被自动发现,并由主题专家进行标记
图上的每个点代表数据集中每头奶牛活动的 10 分钟窗口。点放在一起形成独特活动的集群。
相比之下,DTA 维护许多细粒度的结构。随着时间的推移,我们发展了这种方法,这是我们处理集群问题的首选方法。
在 DataRefiner 以完全无人监管的方式使用 DTA 算法分析了奶牛传感器数据后,我们得到了几个非连续事件期间奶牛活动的地图。每头奶牛的总时间约为 2000 分钟(或 83 小时);地图上有 43 头奶牛。每个点代表 10 分钟奶牛活动的窗口(按分钟滑动)。独立的聚类代表独特的活动类型,聚类之间的距离越远,活动的差异就越大。我们对活动模式进行了广泛的验证,可以确认细分是准确的。
正如你所见,奶牛大部分时间都在躺着和吃草/喂食,但也有一些其他活动,如跳跃或打滚。
以下是奶牛在活动中的分布情况:

14 头奶牛群的活动分布
我们根据奶牛(前 14 头奶牛)给地图上的点着色,剩下的部分为灰色以便于阅读。奶牛在活动中的分布并不均匀,似乎每个奶牛都有自己的偏好。通过选择一只特定的奶牛,我们可以探索这头奶牛做了什么以及她参与了哪些活动模式。

跛行奶牛模式动画(在集群视图和奶牛活动视图之间切换)

发情的奶牛[2]
Cow6 有不寻常的活动模式——她在从食槽进食和非常接近行走的活动之间花时间。这是一个具有独特模式的独立集群,所以经过一些审查后,我们发现 Cow6 是一瘸一拐的。她不能跑长距离,所以她的行为通常不会被归类为发情。然而,我们可以看到,当它们发情时,她也活跃在“骑牛”群里(见图)。通过这种方式,我们知道我们有一只跛行的母牛发情了——这是一个非常精确的结果,否则可能会被错过。现在到了一种不同类型的人工智能的时候了:人工授精。

易于使用的可视化工具有助于快速识别“奶牛饲养”集群,这是农业行业的直接行动号召。

分析 DataRefiner 平台中跛行 cow6 的“Cow Mounting”集群
深度拓扑分析
深度拓扑分析(DTA)是拓扑数据分析(TDA)和深度生成模型的结合。

传统 TDA 计算的四步流程
计算过程的目的是获得 2D 或 3D 平面上多维结构的近似表示。一般的 DTA 过程如下:
1 取原始维度的点云,计算嵌套的拓扑复合体。在这种情况下,我们将使用 Vietoris-Rips 算法。这是将附近的点连接成拓扑结构的过程。

Viet oris-Rips 算法动画【3】
2 使用嵌套复合物计算这种结构的拓扑持久性。使用上一步创建的复合物,我们可以计算结构的条形码。这些条形码将帮助我们识别结构的持久元素。

从嵌套复合体生成条形码【4】
3 利用莫尔斯理论创建数据结构流形。这一步有助于我们简化原始尺寸的流形,并允许我们转换用户分析的结果。

以高度函数为莫尔斯函数的圆环体。在左边我们看到一个平面表示级别,在中间是子级别集,在右边是相应的复合体[5]
4 从多维结构中提取 Reeb 图。使用 Reeb 图和 Morse 理论的结果计算 2D 和 3D 表示。

通过谱聚类的 Reeb 图计算【6】
第 3 步和第 4 步的计算量非常大,尤其是对于具有大维数的大量数据。为了使这些步骤在实际应用中可行,我们必须进行近似和估计。
在这里,我们不是做一个简单的近似,而是使用生成模型不仅得到一个简单的近似,而且从数据中学习复杂的模式。这有助于获得更好的聚类和模式分离。

使用 GAN 进行拓扑计算(OpenAI 的 GAN 图[7]的修改版本)
结论
在 DataRefiner,我们已经在许多公司使用这项技术,不仅用于物联网分析,还用于用户活动和文本分割。如果您想了解更多信息或预订演示,请联系我们。
DataRefiner.com是一家总部位于英国的公司,专注于复杂数据的分析和细分,如用户活动、传感器或文本。DataRefiner 平台是这里讨论的多年提炼方法的结果,但它被广泛应用于各种行业,包括航空、社交网络、欺诈检测等等。如需了解更多关于您所在行业的信息,请通过 ed@datarefiner.com 联系我们
原文:【https://datarefiner.com/feed/ai-for-ai】T21
参考资料:
[1]基于智能手机的人类活动和姿势转换识别,https://sites.google.com/view/smartlabunige
[2]纳迪丝。国家动物疾病信息服务。发情期的奶牛:https://www . nadis . org . uk/disease-a-z/黄牛/奶牛群的繁殖力/part-2-heat-detection/
[3] Vietoris-Rips 算法动画:https://towards data science . com/the-shape-that-survive-the-noise-f0a2a 89018 c 6
[4]拓扑数据分析—持续同源:【http://outlace.com/TDApart1.html】T4
[5]马蒂亚斯·温特拉肯:https://www-sop.inria.fr/members/Mathijs.wintraecken/Mathematica . html
[6]马腾;庄智武;裴洛;冯路。通过谱聚类进行 Reeb 图计算,2011 年
[7]原开乃甘图:图
商业人工智能:公司如何让数据为他们服务?

图片:Pixabay
银行、营销、零售和医疗都已经看到了机器学习改变他们做生意方式的例子。其他人呢?
每个新闻周期似乎都会挖掘出一个关于人工智能变革力量的新的热门故事。最近有报道称,科学家利用强大的算法发现了一种新型抗生素,这一成就被认为是对抗日益严重的耐药性问题的突破。从新闻业到零售业、人力资源和航空航天等行业都见证了人工智能技术改变他们最近做生意方式的迷人例子。但这些引人注目的故事如何转化为真正的企业在地面上适应人工智能?
挑战:

图片:Pexels
人工智能对于企业来说是一个巨大的机会,可以利用相对较新的大规模数据激增。根据麦肯锡的说法,人工智能有潜力在 2030 年前带来约 13 万亿美元的额外全球经济活动,或比今天高出约 16%的累计 GDP。人工智能和机器学习是企业可以用来理解大数据(传统数据处理软件无法处理的庞大或复杂的数据集)的工具示例。但许多公司,尤其是中小型公司,面临着适应大规模技术的挑战。这些包括利用人工智能所需的技术技能不足,缺乏对其好处或用途的理解,或者难以定义战略和找到该技术的适当用例。清楚地了解你想用一个人工智能项目实现什么是至关重要的;就像拼图游戏一样,在你开始拼起来之前,你需要知道结果应该是什么样子。
“尽管我们听说大多数商业领袖认为人工智能提供了竞争优势,但直到最近,一些行业观察人士认为企业采用人工智能的比例还不到 20%。”

图为-不完整的人工智能项目。图片:Unsplash
然而,一旦这些障碍被克服,这项技术将会有无穷无尽的应用。人工智能可以改善许多类似人类的过程的自动化、增强和缩放。这些可以包括:
流程应用:
自动化专家决策:例如,使用算法来计算工厂中的最佳维护计划。门票转售公司 StubHub 报告称,在实施预测分析和统计分析包后,在线欺诈减少了 90%。
自动化非技术性工作:例如,手写识别,以加快表格处理。
将技术工人从非技术任务中解放出来,让他们能够履行核心职责。这对各行各业都有影响,从减少护士必须完成的文书工作,让他们有更多时间与病人相处,到艺术家自动化创作过程中重复、耗时的部分。
洞察应用:

图片:维基百科
机器学习工具可以分析大型数据集,以识别模式或进行预测。例如,自然语言处理应用程序可以分析社交媒体帖子,以了解客户对某个品牌的看法或为客户量身定制的促销活动。西班牙金融服务公司 CaixaBank 最近报告称,通过个性化、有针对性的信息,“真实销售额”增加了 50%。
例如,一家医疗机构可以使用索赔和生物特征测量的数据来生成机器学习模型,该模型可以准确预测患者患病的可能性。该模型还可以预测最有可能改善患者健康前景的干预措施。
机会:
较小的企业和初创公司足够敏捷,可以从头开始实施自己的人工智能战略,并可能为更成熟的组织提供服务。许多尚未采用成功的人工智能项目的大型企业可能有惊人的机会这样做。这些可能包括尚未完全分析的大型数据集、非结构化数据集、分析分类和预测任务、预测或文档审阅和总结。
按行业划分的一些潜在使用案例包括:
营销: DX Marketing 报告称,通过机器学习,交付分析项目的速度提高了 70%,这相当于六个月内收入增长了 25%。
金融服务:虚拟助理、欺诈检测和自然语言合同处理已经在许多公司成功实施。
零售:购物篮分析和智能促销可以将企业与客户联系起来。
能源:简化操作、探索&发现和预测性维护都可以通过人工智能来实现。澳大利亚能源公司利用大数据解决方案监控世界上最长的互联电网,为客户提供无缝体验。

图片:Unsplash
医疗保健:医疗记录、患者护理和医疗&图像分析可以得到简化,并且更加易于访问。据报道,NHS 能够检测到针对医疗保健专业人员的异常行为,并最终通过利用高级分析在整个部门节省了 5.61 亿美元。
娱乐:人工智能推荐占网飞使用量的 75%。预测消费者的选择是让人们继续关注的一个可靠方法。
对企业(和其他所有人)来说,好消息是,到 2020 年,人工智能将成为一个净积极的工作激励因素,消除 180 万个工作岗位,同时创造 230 万个工作岗位
对企业来说,更好的消息是,第三方基于云的机器学习解决方案有很多选择,消除了对昂贵的分析部门的需求。公司的战略家将不得不决定他们想如何抓住这个机会,牢记他们的业务规模和类型。可以肯定的是,机会是巨大的,存在于各行各业,从一个人的初创企业一直到大型企业。
人工智能医疗保健:介绍你可能想不到的一切
专注于计算机视觉、工作流程和放射学

乔纳森·博尔巴在 Unsplash 上的照片
我们的医疗保健系统存在短缺。
美国医学院协会最近的一项调查发现,到 2032 年,仅在美国,我们就将缺少46,900 到 121,900 名医生,其他国家的情况也好不到哪里去。
这意味着医生将需要工作更多的时间,有更多的工作在他们的盘子上,同时试图为他们的病人保持高质量的护理。
在最近的疫情事件中,我们已经看到了我们的医疗系统是多么的脆弱,甚至忽略了医生的职业倦怠正在上升。
研究人员调查了在 119 个门诊诊所工作的 422 名家庭医生和普通内科医生,调查了这些诊所的 1,795 名患者,并审查了他们的医疗记录,以获得关于护理质量和医疗错误的信息。超过一半的医生报告在进行体检时经历了时间压力。 近三分之一的人认为他们需要的时间比分配给这项病人护理职能的时间至少多 50%。此外,近四分之一的人表示,他们需要至少 50%以上的时间进行后续预约。—医疗保健研究与质量局
但是我们可以建立系统来帮助减轻医生的负担,通过简化他们的工作流程和让他们使用高质量的工具来使他们更容易工作。
这篇文章将作为我将要写的人工智能在医疗保健系统中的应用的介绍。在这里,我将重点关注临床成像和人工智能算法的应用,以帮助临床医生。
用于临床成像的工具
在训练机器学习模型时,对数据集可能包含的图像类型有一个大致的了解非常重要。一些图像可能非常详细,并允许更高的训练精度。其他图像的细节可能较低,但使用频率更高。
例如,您可能开发了一个很好的模型,可以在 CT 扫描中确定骨折的位置,但该模型在 x 射线扫描中可能表现不佳。如果大多数医院和诊所使用 x 射线检查骨折,而你的模型不能很好地处理这类数据,那么它可能就没用了。
这就是为什么知道可用的想象工具的类型很重要,这样你就可以研究如何最好地实现你建立的模型。
我们将重点介绍临床医生使用的三种机器。
1.x 射线
x 射线通常用于骨骼,有时也用于像肺或心脏这样的致密器官。
这种机器的工作原理是让放射线(x 射线)穿过身体的某个部位。被高密度物体阻挡的辐射在电影中呈现白色。
它们通常用于诊断:
- 疾病/骨骼退化
- 变色
- 骨折
- 肿瘤
- 感染
这些图像通常不如其他成像解决方案详细,并且需要使用辐射。

来自维基百科
x 射线将捕捉到一个单一的 2D 图像。
x 射线通常是医疗成像中最便宜的选择,有时会先做,即使临床医生认为你之后可能需要 CT 或 MRI。
2.CT 扫描
CT 扫描与 x 射线相似,都是利用辐射来捕捉图像。主要区别在于,它能够捕捉身体的多个切片,为医生提供所捕捉切片的 3D 视图。

来自维基百科
CT 非常强大,因为它们允许临床医生创建骨骼、血管、软组织和其他器官的详细图像。
它们通常用于诊断:
- 阑尾炎
- 巨蟹星座
- 创伤
- 心脏病
- 传染病。
重要的是要注意图像本身不是 3D 的,而是多个 2D 图像。
CT 扫描比 x 射线更贵,但能提供更多细节。
核磁共振扫描
磁共振成像(或 MRI)通常用于软组织损伤,如肌肉或结缔组织。这是因为他们为这些类型的组织提供了更多的细节。核磁共振成像使用电磁体来产生图像,因此不会受到辐射。
然而,这意味着它们不能被体内有金属的人使用。核磁共振成像可以产生 2D 和三维图像

来自维基百科
核磁共振成像是医生可能拥有的最昂贵的成像工具。
医学成像中的工作流程
下一个需要理解的重要部分是诊所和医院通常用于成像的工作流程。
这些信息将帮助我们知道,在 我们的模型应该部署到哪个阶段。
这里我们看到 5 个主要阶段。图像首先通过使用 X 射线、CT 或 MRI 拍摄。这些图像然后被存储在一个叫做图像存档和通信系统(PACS) 的在线服务器中。该服务器允许不同部门访问医院中的成像信息。然后一名放射科医师将按照先进先出的顺序阅读并解读图像。他们将识别异常,然后生成患者图像的解释。最后,医生将根据扫描结果和所有其他可用信息做出诊断。重要的是要知道诊断只能由内科医生而不是放射科医生做出。
执行的成像类型
1.诊断性影像学
如果临床医生认为患者有某种问题,需要通过想象来验证,那么我们称之为诊断图像。
例如,在医生可能认为脑震荡对大脑造成了严重损害的情况下,他们可能会要求进行 CT 或 MRI 扫描,以诊断是否有任何明显的脑损伤。
诊断图像可用于生命可能受到威胁的紧急情况(例如验证脑出血)或非紧急情况。
2.排查
这通常用在病人没什么问题,但风险较低的时候。例如,具有肺癌家族史的患者可以接受定期筛查以进行早期检测。
这些通常是非紧急情况。
来源 : 梅菲尔
基本 2D 图像算法
接下来,我们应该简单了解一下可以应用于医学图像的成像算法的类型。这些算法将帮助我们确定解决特定问题的最佳方法和解决方案。
分类
分类用于识别图像属于哪一类。这是通过识别结构或用图像寻找的算法来完成的。这可以是二进制或多类。用外行人的话来说,分类解决了“这是猫还是狗的照片”。在医学上,我们可以用它来检测图像中是否存在肿瘤。
例如,如果我将它交给一个图像分类器,它将返回结果“ 患者患有肿瘤 ”。它不会提供任何其他信息,如肿瘤的大小或位置。

定位(检测)
定位类似于分类,因为它将识别一个结构或发现是否存在。但它走得更远了。
本地化不会告诉您存在一个发现,而是将模型已经识别的每个发现的位置装箱。这对于吸引放射科医师的注意力非常有用,放射科医师可以更快地识别潜在的感兴趣点。
在上面的例子中,肿瘤非常明显。但在下一个例子中,我们将寻找肺部病变。

这里,该算法能够正确识别肺部病变。有时,还会给出一个置信度来帮助放射科医师了解模型认为它识别了正确区域的可能性有多大。
分割
分割类似于定位和分类,因为它将识别结构或发现是否存在,并定位它们在图像上的位置。
分割将识别图像中包含结构的像素,并突出显示该结构。这对于获取结构的面积或大小以及跟踪其随时间的增长或收缩非常有用。
例如,在这个例子中,这个模型不是仅仅包围肿瘤所在的区域,而是试图勾勒出确切的肿瘤轮廓。这使得从某个切片或图像通过计算确定肿瘤的大小变得更加容易。

利益相关者
如果你想把你的产品推向市场,重要的是要注意哪些利益相关者参与其中,并以对每个利益相关者都有利的方式形成你的产品。
放射科医生(临床利益相关者)
- 这通常是算法的最终用户,应该熟悉算法的准确性和可能出现的故障类型。
- 在开发您的模型时,他们将扮演重要的顾问角色,提供他们日常面对的重要见解。
- 放射科医生最关心的是有低分配到那里已经繁忙的工作流程。拥有一个难以使用的优秀表演模型是行不通的。
临床医生(临床利益相关者)
- 临床医生对你的算法的理解会更模糊。
- 临床医生也关心对工作流程的低干扰。一个耗时太长或者提供的数据不容易被临床医生理解的算法对他们来说是没有用的。
患者(临床利益相关者)
- 病人将是最重要的利益相关者。
- 病人可能永远不知道人工智能参与了诊断过程。
- 患者最关心的是理解为什么他们的诊断是这样的,获得诊断的时间长度,以及诊断的准确性。
医疗器械公司(行业利益相关方)
- 这些公司生产用于医院、实验室和诊所的设备。
- 他们通常有自己的随行成像软件,并开发自己的 AI 算法。
- 医疗设备公司
- 了解这些系统的能力以及您的算法如何改进或增强当前已经使用的软件非常重要
软件公司(行业利益相关者)
- 为成像或临床应用开发人工智能算法。
- 他们必须明确他们的软件是在哪种类型的医学成像硬件上通过验证的(出于监管目的)。
医院和放射诊所(行业利益相关者)
- 必须能够支持部署的任何算法的基础设施(云资源/GPU/其他硬件)
- 随着时间的推移,对人工智能的兴趣通常与降低成本联系在一起。
监管机构(监管利益相关方)
- 他们主要关心的是病人的安全。这意味着非常严格的监管。
- 他们确保该算法被贴上标签,投入市场,并在临床环境中适当使用。
- FDA 等监管机构将医学成像的人工智能算法视为医疗设备。
AI 什么时候最有效?
当它使每个相关人员的工作变得更容易、更高效时。算法的准确性很重要,但实现算法的方式也同样重要。
- 算法应该让关键研究更快地解读。
- 它应该有助于减少临床医生的倦怠和疲劳。
- 做出准确的评估。
- 易于相关人员使用。
案例示例
减少放射科医生的倦怠
应用:乳腺摄影筛查
摘要:美国每年进行数百万次乳房 x 光检查,需要 2 名放射科医师 解读结果。超过 85%的乳房 x 光片最终完全正常。
问题:放射科医生正在浪费时间解读正常的乳房 x 光片。
潜在解决方案:使用分类。根据模型的准确性,可以使用算法来确定乳房 x 线照片是阳性还是阴性,然后可以使用单个放射科医生来验证结果。
优化放射科医师在急诊室的工作流程
应用:下垂性脑出血
概要:放射科医生按照先进先出的队列从 PACs 系统中读取图像。
问题:如果不及时治疗,脑出血是致命的,需要迅速发现。
潜在解决方案:将图像放入 PACs 之前运行的分类算法。如果它确定存在脑出血,它可以被推到队列的前面,以便放射科医师进行验证。
考虑到所有这些因素,并对医疗领域有一个更全面的了解,是确保您的算法能够真正用于医疗环境的最佳方式。

如果你喜欢这篇文章,可以考虑看看我的其他作品!
* [## Epic 不是因为 30%的降价起诉苹果,而是因为其他事情起诉他们
他们不想只是推翻垄断,他们想要他们的份额
medium.com](https://medium.com/macoclock/epic-isnt-suing-apple-for-the-30-cut-they-re-suing-them-for-something-else-c5a0da2e2118) [## 数据可视化:动画条形图!
Excel 和 After Effects 中的数据可视化和动画
towardsdatascience.com](/data-visualization-animate-bar-graphs-df9ca03a09f2) [## 可共享的 Jupyter 笔记本!
最后,团队可以轻松地共享和运行代码
towardsdatascience.com](/sharable-jupyter-notebooks-bf3ec9c2e0be) [## 使用 Python 制作数据动画
仅使用 MatPlotLib 查看实时数据
towardsdatascience.com](/animate-data-using-python-dd558e9103d)*
工业过程控制的人工智能:控制策略介绍(上)
工业反应和预测控制器的概念概述
介绍
在过去的几十年里,“数字革命”使得制造商和公用事业公司能够为他们的工厂配备分布式监控系统。无论是工业膜还是生物反应器,这些控制系统都是重工业自动化的核心,使公司能够读取、解释和使用自己的机器生成数据来实现生产和合规目标。然而,尽管它们具有普遍性,但这些控制系统只是最近才开始作为人工智能(AI)破坏的潜在候选人而受到关注。
今天,大型工厂控制室中的操作员被期望在很大程度上依靠他们自己的判断和经验。在同时监控数十个过程信号的同时,他们需要调整控制系统设置、排除警报故障、执行质量测试,从而限制了他们的人力。好消息是,这些工厂正在不断捕捉和存储大量数据,这些数据可以很容易地被人工智能系统消耗。使用人工智能进行过程控制,可以显著简化数据处理,并为操作员提供增强的决策支持。

在这一系列文章中,我们将深入探讨(1)这些工业过程控制系统今天是什么样子,(2)人工智能如何利用现有的工厂数据来增强它们,(3)制造商和公用事业公司今天可以做些什么来释放显著的成本节约和过程合规性机会。
控制系统分类
让我们从一些简单的术语开始。过程(即反应器、过滤器)由控制器控制,控制器消耗来自传感器(即流量计、分析仪)的测量值,传感器实时监控关键过程状态(即流量、温度、压力),如图 1 所示。

图一。剖析一个原型工业控制系统 (图片由作者提供)
这些控制器使用这些测量来实时产生控制动作(即打开/关闭阀门,打开/关闭泵)。根据控制器如何消耗这些传感器测量值并产生控制动作的机制,可以将控制器分为反应型或预测型。反应控制系统中的控制动作仅基于当前或过去的状态,即过程的当前或最近的传感器测量。相反,预测控制器使用对过程未来状态的预测来产生控制动作,通常采用某种形式的系统数学优化和模拟模型。
反应式控制器的一些例子包括比例控制器的变体,例如比例积分(PI)和比例积分微分(PID);而模型预测控制(MPC)是预测控制策略的一个例子。
反应控制的标志:比例积分微分(PID)控制
工业和公用事业过程中最常见的反应控制(也称为反馈控制)策略是比例积分微分(PID)控制器。在 PID 控制器中,控制动作是测量状态与所需设定点(即目标)偏差的函数,通常称为“误差”,如图 2 所示。该目标设定点通常由操作员指定,以便实现一些生产或符合性目标。

图二。反应式控制器如何工作 (图片由作者提供)
PID 控制器的一个常见例子是简单的汽车巡航控制系统,如图 3 所示。这里,驾驶员(操作者)指定期望速度(设定点),控制器根据当前速度(显示在速度计上)和期望速度之间的差异计算相应的加速度要求。

图 3。简单的汽车巡航控制系统 (图片由作者提供)
PID 首字母缩略词中的每个字母表示一种“校正模式”,控制器使用这种模式来计算控制动作将如何响应当前状态与其目标的偏差,如图 4 所示。“比例”校正意味着控制动作被计算为对误差的即时或线性响应,而“积分”校正意味着控制动作被计算为一段时间内状态的累积误差的函数。它被称为“积分”控制,因为随着时间的累积误差是使用积分计算的。最后,“导数”校正使用状态误差的变化率,如其导数所测量的。因此,任何无功控制器都可以是这些计算(PI、PID 或 P)的任意组合。

图 4。比例积分微分控制器框图 (图片由作者提供)
如图 4 所示,每个校正响应由常数缩放,如 KP 和 KI ,称为增益系数。这些参数通常由自动化或控制工程师调整。可以调节控制器增益,以使控制器输出变化对设定点和状态变量之间的偏差尽可能敏感;并且可以选择系数的符号,以使控制器输出随着误差信号的增加而增加或减少。
将微分和积分校正模式合并为控制器的一部分取决于被控制的过程的类型。综合校正确保不会出现长期持续的偏差或误差漂移,同时导数校正确保控制器快速响应误差变化,确保控制器在其响应中不会超调(过度补偿)。
虽然反应式控制策略的制定和部署非常简单,但它的致命弱点可能已经显而易见。
反应式控制器的控制响应是对系统当前状态的持续反应,对其未来动态没有预见。这意味着控制器容易受到不断演变的系统行为或异常的影响。
对于处于高度竞争的制造环境中的工厂,或者受到气候变化压力的公用事业系统,不断变化的动态可能是每天的现实。例如,如果生物反应器中出现大量营养负荷,该系统将消耗大量能量来驱动溶解氧回到所需的操作范围。可选地,泵可以在给定的控制范围内多次在在线和离线之间转换其状态,以确保下游罐在其操作范围内,从而导致由不期望的压力瞬变引起的潜在故障。
模型预测控制
上面列出的缺点正是模型预测控制(MPC)存在的原因。MPC 是一种为复杂、非线性过程的主动控制而设计的方法。基于反应的控制策略,如 PID 控制,其控制动作基于传感器记录的历史和当前系统状态,而 MPC 使用未来状态的预测。因此,MPC 控制器需要过程的精确仿真模型,以便产生可靠的预测。

图 5。MPC 控制器的框图 (图片由作者提供)
如图 5 所示,有几个额外的元件构成了传统无功控制器中不存在的 MPC。其中包括:
1.仿真模型:过程动态的数学表示,即它可以根据各种控制动作序列预测过程的未来状态
2.优化器:一个数学解算器,可以根据仿真模型的输出迭代地确定“最优”控制动作
3.约束:指定优化器不能超过的可接受的未来状态的边界,即氨排放浓度的符合性限制
4.目标:运营商寻求实现的优化目标,即降低能源成本
预测控制通过执行动态、实时优化来产生控制动作,这些控制动作适应干扰并符合用户指定的约束。MPC 允许操作员通过比传统反应式控制器更接近约束条件的操作来更有效地运行他们的过程。
图 5 中的框图提供了 MPC 框架的概念性概述。虽然 MPC 结构比传统的反应式控制器更复杂,但它有几个重要的优点:
1.控制动作被优化以实现期望的结果,例如降低能量成本或提高反应效率
2.控制器对来自干扰的扰乱不太敏感,因为它可以预测它们并更快地响应
3.可以对控制器施加状态和控制的约束,以确保产生顺从的控制动作
4.准确的模型预测可以提供潜在问题的早期预警
5.过程模型捕捉控制、状态和干扰变量之间的动态相互作用
下一个?
到目前为止,我们已经讲述了过程控制的基础知识。在本系列的第 2 部分中,我们将更详细地探讨 MPC 控制器如何工作,并提供一些说明它们如何优于传统 PID 控制器的示例。
人工智能促进收入增长:使用 ML 推动更有价值的定价
一个国家健身品牌如何使用机器学习来优化定价并使收入增长 11%

米歇尔·汉德森在 Unsplash 上的照片
介绍
价格优化是收入增长的有力杠杆,但它经常被太多的公司放在太硬的篮子里。
这是因为传统的定价优化方法不仅实施起来复杂,而且在准确捕捉影响定价的所有因素方面能力有限。
机器学习(ML)非常适合于定价优化问题——既因为它处理复杂特征的能力,也因为它概括新情况的能力。此外,托管服务的最新进展使得这些 ML 解决方案几乎可以为任何组织所用。
在这个匿名示例中,我们探索了一家没有数据科学专业知识的公司如何能够使用托管 ML 服务来实施 ML 驱动的定价策略,该策略的性能是传统方法的 2 倍,并使收入增长了 11%。
情况
FitCo 是总部位于洛杉矶的优质健身品牌,在美国经营着 600 多家健身房和健身中心。
在过去几年通过收购快速增长后,管理层的注意力现在转向了推动有机收入的增长,这在每个工作室的基础上一直顽固地保持平稳。
FitCo 将 FitClass——其专业健身课程套件——确定为有机增长的主要来源。具体来说,它已确定这些类别的定价是一个主要的潜在改进领域。

FitClasses 是 FitCo 旗下品牌中很受欢迎的产品。它们是迎合利基健身需求的优质体验,在标准会员资格的基础上按等级付费出售。
虽然 FitCo 确保了其产品组合的一致用户体验,但当地运营商仍然能够在他们的工作室中几乎完全独立地为 FitClasses 设定时间表和价格。因此,不同等级和不同地点的价格差异很大。
虽然 FitCo 理解这种差异反映了当地的条件,但他们也怀疑其投资组合的定价方式还有相当大的改进空间。
并发症
FitCo 在两年前进行了一次定价活动,之前的管理层选择集中 FitClass 的定价,并制定了 10%至 20%的全面提价。
这种生硬的方法没有成功。它未能考虑到客户需求在各种级别和地点的价格弹性,价格上涨实际上导致总收入下降2 %,因为许多级别需求的下降超过了价格的上涨。几个月后,他们被迫取消价格变动。

虽然很痛苦,但这种经历至少给了 FitCo 一个关于 FitClass 客户群价格弹性的非常可靠的数据集。它可以绘制出三个利用率级别(高(> 85%)、中(50–85%)和低(< 50%)的价格增长对等级需求的影响。FitCo 模拟了价格上涨对需求的各种影响,估计更有效的定价将带来 15%的收入潜力。
为了抓住更高的收入潜力,FitCo 现在只需要能够准确预测未来对课程的需求(无论是当前的还是新的),以准确模拟价格对收入的影响。这将使 FitCo 能够确定每一级别的价格上涨是否有利可图,以及上涨幅度有多大。
FitCo 最初尝试使用传统的基于规则的方法——实际上是一系列 if/then 语句,根据特定条件设置波段。经过大量的反复试验,他们成功地编写了一个函数,估计可以产生大约 5%的额外收入。这并不坏,但这种方法有两个主要限制:(1)它未能充分考虑与每个类别相关的各种因素的相互关系——它错误地预测了错误范围内的太多类别,导致使用率下降——以及(2)它未能推广到任何给定位置的新的课程安排或细节——它不能充分考虑因素或场景的新组合。
为了寻找替代方法,FitCo 求助于 ML。
毫升溶液
ML 非常适合这些类型的分类问题,因为它能够处理广泛的因素,并概括出未知或新的情况。
然而,像其规模和行业中的大多数组织一样,FitCo 没有 ML 能力或现成的数据科学家团队来设计、构建和部署 ML 解决方案。这在以前是采用 ML 的主要障碍。然而今天,ML 托管服务的可用性已经在很大程度上使 ML 功能的访问大众化。
对于他们的解决方案,FitCo 选择了 Amazon SageMaker,其中包括一项名为 AutoPilot 的 AutoML 功能,它可以接受一个简单的表格数据集,并自动围绕它构建 ML 工作负载。

AutoPilot 接受一个简单的表格数据集,并围绕它构建一个 ML 工作负载
有了自动驾驶,FitCo 不再需要一个数据科学家团队来获得 ML 的好处。相反,他们能够通过一个由 CFO(作为业务所有者)、CTO(作为技术所有者)和一个负责构建和集成解决方案的后端开发人员组成的三人项目团队来推动这项计划。
培训用数据
为了建立他们的训练数据集,FitCo 收集了他们每个班级过去两年的历史利用率数据。
每一个班级的利用率以占总名额的百分比来表示。FitCo 根据上述利用率范围将这一栏中的数据转换为“高”、“中”和“低”,并将这一栏命名为“目标”。这将是 ML 模型预测的列。
然后,他们将这些数据与一组他们认为可能表明利用率的内部特征结合起来。他们还添加了一系列他们认为相关的外部数据。结果是一个包含 800,000 个实例的数据集,它包含以下特征:
- 类别类型(分类)
- 位置(分类)
- 星期几(分类)
- 一天中的时间(数字)
- 讲师(分类)
- 工作室品牌(分类)
- 是公共假日(二进制)
- 是学校放假(二进制)
- 外部温度(数值)
- 目标(分类)
FitCo 做了一些基本的功能工程来更好地组织和格式化这个数据集,将其转换为 csv 格式并保存在 S3 桶中。他们现在有了一个数据集,可以用来训练他们的 ML 模型。
亚马逊 SageMaker 自动驾驶仪
FitCo 选择 Autopilot 是因为它能够简化和精简机器学习过程的核心组件。AutoPilot 自动化了探索数据、工程特性、测试不同算法和选择最佳模型的过程。它只需要您提供一个表格数据集。
此外,它会自动呈现它所使用的代码库,从而增加流程的可见性和可重复性。这对 FitCo 的首席技术官来说是一个重要的区别,因为它让 FitCo 有机会探索和学习生成模型所采取的步骤,并为其提供一个代码库,以便在未来对其进行修改和优化。
为了启动自动驾驶程序,FitCo 使用了亚马逊 SageMaker Studio 中的无代码接口。这需要三个关键步骤:
- 命名他们的实验
- 将 SageMaker 指向他们的培训文件所在的 s3 存储桶,并且
- 定义要预测的变量

AutoPilot 的无代码接口使 ML 对任何组织都触手可及
一旦输入这些细节,他们只需点击创建实验,FitCo 的 ML 模型构建正在进行中,运行一系列试验来确定最佳的 ML 方法。

自动驾驶仪进行试验的完整列表,以确定最佳性能模型
这个过程大约需要一个小时才能完成。一旦得出结论,FitCo 就可以简单地对试验列表进行排序,以找到性能最佳的模型。他们能够生成包含该模型代码的笔记本,还能够将该模型部署到 SageMaker 端点,使他们能够进一步测试该模型根据新数据生成的推断(预测),甚至将其投入生产。
结果
当根据 FitCo 的测试数据集建模时,ML 模型的性能比他们基于规则的方法高出 2 倍,总收入估计增加了 11%。

ML 模型的性能是基于规则的方法的 2 倍
这种性能改进主要源于 ML 预测比基于规则的方法更高的精度。在多类分类问题中,挑战不仅在于预测正确的类,还在于最小化不准确的代价。例如,将低需求等级错误地预测为“中等”比预测为“高”成本更低。具体来说,根据 FitCo 的价格弹性曲线,这一特定错误的成本以需求下降的形式增加了约 4 倍。
传统方法和最大似然法之间的这种性能的比较可以在下面看到,并且说明传统方法实际上在准确预测高需求类别方面优于最大似然法。问题是,它无法做到这一点,而也准确预测中低需求等级。此外,它在不准确地将低等级预测为高需求等级方面犯了代价高昂的错误。ML 模型能够更好地更全面地映射数据的形状,以考虑这两种情况。

基于规则的方法在 25%的情况下错误地将低级预测为高级
这些错误给基于规则的方法的收入带来了相当大的损失,而 ML 模型可以避免这些错误。例如,不准确地预测低需求类别为高需求导致需求下降近 50%,远远抵消了其余成员支付的 30%的高价格。
下面的矩阵显示了每种类型的预测对收入增长的影响,以传统方法和 ML 方法之间的性能差异表示。

ML 模型能够通过更加一致的整体准确性产生 5.5%的额外收入
尽管传统方法成功地击败了 ML 模型,正确地将较高比例的高级类标记为高(一种称为“召回”的度量),但它也错误地将更多的“中等”和“低”需求类标记为高(称为“精度”)。
因此,尽管其准确的高预测产生了 1.4%的高收入,但这是以需求下降导致的 2.8%的收入损失为代价的,因为不正确地向弹性更高的中低阶层收取了更高的价格。类似的模式也出现在低预测中;ML 模型更高的准确性意味着它只是降低了人们预期会看到更高需求的类别的价格。
由于这种更高的精度,即更准确地预测高等级和低等级,ML 模型能够产生 5.5%的总收入,是基于规则的方法的两倍多。
结论
定价优化是收入增长的有力杠杆,而 ML 的应用提供了一个强有力的解决方案,它往往优于传统方法。
在 FitCo 的案例中,与基于规则的最佳替代方案相比,将 ML 应用于他们的挑战产生了 2 倍的收入增长,并产生了约 11%的收入增长。
FitCo 的例子有助于展示 ML 如何应用于优化定价,以及像 SageMaker AutoPilot 这样的托管服务如何能够将这些强大的 ML 解决方案放在几乎任何组织都可以达到的范围内。
有你想要探索的人工智能机会吗?在 LinkedIn 上和我联系。
纺织品人工智能——基于卷积神经网络的织物结构分类器

T 如今,深度学习被广泛用于各种人工智能应用,包括面部识别、自然语言处理等。在纺织工程领域也有可能找到深度学习的许多应用,计算机视觉已经在这种背景下广泛使用。本文描述了开发卷积神经网络用于从织物表面的输入图像识别织物结构的方法。开发的模型能够成功地区分针织物和机织物结构。
由于针织和机织结构的结构差异,它们很容易区分。针织物的线圈结构和机织物上交织的经纱和纬纱使得这两种结构易于识别。如果通过显示一组标记的针织和机织织物图像,可以训练神经网络来学习织物结构固有的这些特征,那么神经网络将能够正确地区分针织和机织织物图像,这是它以前从未见过的。为了实现这一点,决定使用卷积神经网络(CNN)架构,因为 CNN 能够有效地从图像中提取特征。
该模型是使用 python 和 TensorFlow 框架以及 Keras API 开发的。为了获得用于训练神经网络的数据集,使用了在【https://ibug.doc.ic.ac.uk/resources/fabrics/】上可用的图像的开源数据库,该数据库最初是为一项研究而准备的( C. Kampouris,S. Zafeiriou,A. Ghosh,S. Malassiotis, 使用微观几何和反射率的细粒度材料分类 ,第 14 届欧洲计算机视觉会议,阿姆斯特丹,2016 年)。该原始数据集中的织物图像根据材料类型(即尼龙、聚酯、棉等)进行标记。).因此,在训练之前,从该原始数据集中选择总共 4300 幅图像,并根据织物结构(即,针织和机织)对其进行人工标记。在 4300 幅图像中,4200 幅用作训练数据,而剩余的 100 幅用作验证数据。(尽管验证数据集太小,但大多数图像用于训练以避免过度拟合)。训练和验证数据集都由相同数量的针织和机织织物图像组成。
最初,决定使用迁移学习技术。因此,使用 VGG16 架构(https://arxiv.org/abs/1409.1556)和预训练的权重。只有最终输出层被更改为具有两个单元的 softmax 层。使用迁移学习,训练最终输出层,保持其他层的权重不变,经过 100 个历元后,训练和验证准确率分别达到 88%和 83%。
为了改进模型,原始 VGG16 架构的最后三个密集层被移除,并由几个稍微修改的密集层取代。使用迁移学习,这些新增加的层被训练,同时保持其余层的权重不变。该模型最高训练准确率达到 99.81%,验证准确率达到 91%。该模型现在明显过度适合训练数据。
为了克服过拟合问题,再次训练模型的最终密集层,在最后两个密集层之间添加一个丢弃层,并增加数据。然而,在 20 个时期之后,该模型达到了 84.55%的训练准确度和 84%的验证准确度,并且似乎没有进一步改善。过拟合问题被克服了,但是现在模型有很高的偏差。
最后,决定训练整个模型,而不是使用迁移学习。然而,由于可用的训练数据量有限,因此决定降低原始 VGG16 架构的复杂性。因此,移除了原始 VGG16 架构的第五个卷积块,并添加了一个平均池层,之后是两个密集层。为了避免过度拟合,数据增强使用了几种增强技术,如旋转、垂直翻转、缩放和不同的亮度水平(【https://keras.io/api/preprocessing/image/】)。输入图像的旋转是重要的,因为它允许模型识别针织物图像的纵行和机织织物图像中的经纱和纬纱,由于捕获图像时发生的变化,它们在不同的方向上取向。放大图像使模型能够清楚地识别针织物的线圈结构和机织物的交织图案。

模型摘要
import numpy as np;
import keras;
from keras.layers import AveragePooling2D;
from keras. layers.core import Dense, Flatten;
from keras.optimizers import Adam;
from keras.metrics import binary_crossentropy;
from keras.preprocessing.image import ImageDataGenerator;
from keras.models import Model;
from keras.applications import imagenet_utils;
from keras.callbacks import ModelCheckpoint;train_data_path = '/content/drive/My Drive/fabric_data/Train';
test_data_path = '/content/drive/My Drive/fabric_data/Test';train_data = ImageDataGenerator(rescale = 1.0/255,
rotation_range = 180,
vertical_flip = True,
horizontal_flip = True,
brightness_range = [0.5, 1.5],
zoom_range = [1, 1.5]);train_generator = train_data.flow_from_directory(directory = train_data_path,
target_size = (224,224),
classes = ['Woven','Knitted'],
batch_size = 70,
shuffle = True);test_data = ImageDataGenerator(rescale = 1.0/255);test_generator = test_data.flow_from_directory(directory = test_data_path, target_size = (224,224), classes = ['Woven', 'Knitted'], batch_size = 50, shuffle = False);vgg16_model = keras.applications.VGG16();
x = vgg16_model.layers[-9].output;x = AveragePooling2D(pool_size = (2,2))(x);
x = Flatten(name="flatten")(x);
x = Dense(128, activation = 'relu')(x);
x = Dense(2, activation = 'softmax')(x);model = Model(inputs = vgg16_model.input, outputs = x);model.compile(optimizer = Adam(lr=0.00001, clipvalue = 0.5, clipnorm = 1), loss = 'binary_crossentropy', metrics = ['accuracy']);print("\nTraining.....");checkpoint = ModelCheckpoint(filepath = '/content/drive/My Drive/new_fab_model.h5', monitor='val_accuracy', verbose=1, save_best_only=True, mode='max');history = model.fit_generator(generator = train_generator,
steps_per_epoch = 60,
validation_data = test_generator,
validation_steps = 2,
epochs = 250,
verbose = 1,
callbacks = [checkpoint]);
使用 Adam 优化器以 0.00001 的学习率从头开始训练整个模型。经过 50 个时期的训练,该模型达到了 98%的训练准确率和 97%的验证准确率。

达到培训和验证的准确性
由于使用的验证数据集太小(只有 100 个图像),为了进一步验证模型在现实世界中的性能,使用训练的模型测试了不同的 100 个织物图像的集合。该模型正确预测了其中的 97 幅图像。这个新测试样本的意义在于,图像是从与原始训练和验证数据完全不同的分布中获取的。一组图像是从互联网上下载的(3D 针织物图像)。使用扫描仪扫描另一组图像,图像被放大 50%,裁剪并调整为 224x224 像素,以输入神经网络。使用光度立体传感器捕获原始训练和验证数据集的织物图像( C. Kampouris,S. Zafeiriou,A. Ghosh,S. Malassiotis, 使用微观几何和反射率的细粒度材料分类 ,第 14 届欧洲计算机视觉会议,阿姆斯特丹,2016) 。

由训练模型预测的织物结构
应该注意的是,模型的训练数据仅由纬编针织物组成。只有单面针织结构的技术正面图像可用,不包括 3D 针织结构。然而,经过训练的模型能够正确预测 3D 缆线编织结构,并且它也正确预测一些单面针织物的技术背面图像。训练集中的大多数织物图像由平纹和斜纹结构组成。
被训练的模型的中间激活被可视化以理解卷积如何从织物图像中学习特征。针织织物图像作为输入输入到模型中,相应的层激活如下所示。请注意,这里只显示了几层的一些卷积。

输入图像(作者提供的照片)



对应于输入图像的模型的层激活(仅示出了来自一组选定层的一些卷积)
模型的初始层似乎在识别图像的最基本特征,例如水平和垂直边缘。一些盘旋已经确定了针织物表面纵行的边缘。在中间层,卷积开始提取更精细的细节,如针织线圈的形状,最大汇集层突出了这些特征。最深层的激活很难从视觉上解释,因为根据模型在训练中所学的,它们正在编码特定于织物结构的信息。
应该注意的是,该模型仅用于学术目的。该模型只能区分两种主要的织物结构(即针织和机织)。区分几种织物结构变化(如单面针织物、罗纹织物和联锁织物)将是一项更有趣的任务,但由于无法获得此类不同类型织物结构的大型数据集,该模型仅限于区分针织和机织织物结构。然而,有了足够的数据,也可以训练一个模型来完成这样的任务。还应该注意,通过使用不同的神经网络结构和更多的数据,有可能进一步改进该模型。
人工智能生成的埃隆·马斯克加入变焦电话已经成为病毒
人们已经被 deepfakes 技术迷住了。现在你可以使用 Avatarify 在流式播放时用别人的脸替换你的脸

人工智能生成的埃隆·马斯克使用 Avatarify 加入了变焦通话
埃隆·马斯克和我正在开会讨论一个 2 亿美元的项目!
如果你以这种方式告诉你的朋友,他们可能不会相信,但如果你给他们看一个视频通话,他们更有可能相信。事实上,埃隆·马斯克从来没有和你说过话,而所有这些都是由一个名为“Avatarify”的 deepfake 项目产生的。
Avatarify 是由阿里·阿利耶夫和卡里姆·伊斯卡科夫创造的。与大多数其他 deepfake 项目需要你预先录制视频不同,Avatarify 足够强大,可以在流传输的同时实时工作。阿里·阿利耶夫已经在两周前在 Github 上开源了这个项目。他在不到一周的时间里收获了 4k 星,迅速登上了日趋势榜榜首。
如果你想亲自尝试,请点击 GitHub 上的 Avatarify 查看。

项目演示

虚拟化演示
如演示中所示,作者导入一张照片,照片中的人根据作者自己在摄像机前移动的动作进行动画制作。在实时电话会议中,扬眉、眨眼和说话都很流畅。

虚拟化演示
当然,你可以尝试一些更有趣的东西。比如爱因斯坦的一个眨眼,阿姆的凝视,史蒂夫·乔布斯扬起的眉毛,蒙娜丽莎的微笑。如果你愿意,你可以把你的脸换成任何人的。你需要做的只是找到一张你想玩的人的照片,放到项目的avatars文件夹里。
安装并运行虚拟化
你不需要任何编程知识来运行 Avatarify。您所需要的只是一些初级的命令行知识。支持 Linux、Mac 和 Windows,你可以点击这里查看 Avatarify 安装指南。对于 Windows,作者制作了一个视频教程,所以安装起来会很容易。
为了顺利运行 Avatarify,您需要一个支持 CUDA(NVIDIA)的显卡。否则,它将退回到 CPU,运行非常缓慢,性能急剧下降(< 1fps)。
一旦你把它安装到你的机器上,剩下的你需要做的就是找到你想玩的人的照片,并把它放在avatars文件夹中。之后,启动一个支持的视频会议应用程序,Zoom,Skype 或 Slack。
算法
Avatarify 是基于意大利特伦托大学的研究人员开发的一阶运动模型开发的。一阶运动模型可以生成视频序列,使得源图像中的对象根据行驶视频的运动而被动画化。

一阶运动模型综述
一阶运动模型假设源图像 S 和一帧驾驶视频帧 D 作为输入。无监督关键点检测器提取由稀疏关键点和相对于参考帧 R 的局部仿射变换组成的一阶运动表示。密集运动网络使用运动表示生成从 D 到 S 的密集光流 Ts←D 和遮挡贴图 Os←D 。生成器使用源图像和密集运动网络的输出来渲染目标图像。

来自一阶运动模型的动画示例
以上是来自一阶运动模型项目的一些动画示例。左边的视频显示的是驾驶视频。每个数据集右侧的第一行显示了源视频。最下面一行包含动画序列,其中的运动是从驾驶视频和从源图像获取的对象中转换而来的。
了解法律
最后,对于 deepfakes 提到法律是非常重要的。
根据《卫报》的报道,deepfakes 本身并不违法,但是生产商和经销商很容易触犯法律。根据内容的不同,deepfake 可能会侵犯版权,违反数据保护法,如果它使受害者受到嘲笑,则可能是诽谤。
尽情享受吧!
就是这样。以下是链接
- 归化项目:https://github.com/alievk/avatarify
- 一阶运动模型:【https://github.com/AliaksandrSiarohin/first-order-model
- 一阶运动模型论文:【https://arxiv.org/pdf/2003.00196.pdf
人工智能生成的合成媒体,又名 deepfakes

从 pike picture-Adobe Stock 获得许可
人工智能(AI)和云计算的进步使得音频、视频和图像处理技术变得简单而快速。
介绍
想象一下,在选举前几天,一个候选人的视频被发布,显示他们使用仇恨言论、种族诽谤和绰号,削弱了他们作为亲少数族裔的形象。想象一下,一名青少年尴尬地看着自己的一段视频在社交媒体上疯传。想象一下,一位首席执行官在筹集资金的路上,一段描述她对产品的恐惧和焦虑的音频剪辑被发送给了投资者,破坏了她的成功机会。
以上所有场景都是假的,是编造的,不是实际的,但可以通过 AI 生成的合成媒体来制造真实,也叫 deepfakes[ 1 ]。同样的技术可以让一位因患卢·格里克病而失声的母亲用合成声音与家人交谈,这种技术也可以被用来制作政治候选人的虚假演讲,以损害他们的声誉。同样的技术可以让老师使用合成视频有效地与学生互动,也可以用来制作一个青少年的假视频,以损害她的声誉。
人工智能(AI)和云计算技术、GPU VMs(图形处理单元虚拟机)和平台服务的进步,导致音频、视频和图像处理技术的复杂性快速发展。对商用云计算、公共研究人工智能算法和丰富数据的访问,以及多样化和庞大媒体的可用性,创造了一场完美的风暴,使合成媒体的创作民主化。这种人工智能生成的合成媒体被称为 deepfakes。社交平台使得合成媒体的传播大规模民主化。
Deepfakes 是使用深度( 深度 )学习的人工智能技术生成的合成媒体( 假 )。
GAN 技术的创新和研究与不断增长的计算可用性相结合,以惊人的速度提高了合成数据的质量。新工具,其中许多是公开可用的,可以以越来越可信的方式操纵媒体,例如创建一个公众人物的声音的副本,或将一个人的脸叠加在另一个人的身体上。GAN 和 deepfakes 已经从研究和学术主题发展到商业创新、娱乐和社会参与的实际应用。
Cheapfakes 是通过简单的常规编辑技术进行的简单操作,如加速、减速和剪切,以及非技术性操作,如重新编排或重新编排现有媒体。一个廉价假货的例子是“喝醉的佩洛西”视频。最近,我们已经看到一些政治广告中使用了重新着色和修饰,这也可以打印出廉价的假货。
廉价假货或肤浅假货被定义为通过使用更直接的图像和视频编辑技术来传播错误/虚假信息或改变故事叙述而创建的操纵媒体。
Deepfakes 的类型
Deepfakes 已经成为面部交换和假唱的同义词。还有许多其他类型的基于人工智能的音频、视频和图像操作可以被称为 deepfakes。
换脸
面部交换是指一个人的脸被另一个人的脸或另一张脸的关键特征替换或重建。几乎所有的社交媒体、视频聊天应用都有一个共同的特征,那就是面部交换或使用滤镜。自 2014 年以来,社交媒体应用程序 Snapchat 就有了增强人脸的滤镜。使用面部检测镜头技术,你可以让自己变老,添加美容滤镜,或者给自己留猫耳朵和胡须。这些应用和技术的输出将有资格成为人工智能生成的合成媒体或 deepfakes。大量的免费和付费应用程序和在线工具使得面对两个人的交换变得超级简单。开发人员可以使用来自 GitHub 的 Faceswap 和 DeepFaceLab 的开源代码,通过一些定制代码和训练 AI 模型的努力来创建非常复杂的 deepfakes。
木偶表演
操纵木偶是使用人工智能渲染操纵的全身动作和行为。这是一种在视频中创建目标面部和身体的 3D 模型的技术,以充当木偶演员。也被称为全身 deepfakes。2018 年 8 月,加州大学伯克利分校发表了一篇论文,名为《现在人人跳舞【4】。这是关于人工智能如何将专业舞者的动作转移到业余舞者身上的研究。日本人工智能公司 Data Grid 创造了一个人工智能引擎,可以自动生成广告和时尚的虚拟模型。
假唱
嘴唇同步是一种渲染嘴部动作和面部表情的技术,使目标用他们的声音和正确的音调和音高说话。人工智能算法可以获取一个人说话的现有视频,并改变视频中的嘴唇运动,以匹配新的音频。音频可以是断章取义的旧语音、模仿者说话或合成语音。演员兼导演乔丹·皮尔用这种技术制作了一个关于奥巴马的病毒视频。
声音克隆
语音锥化是一种深度学习算法,它采用个人的语音记录来生成与原始语音过度相似的合成语音。这是一种创建个人定制语音字体,然后使用该字体生成语音的技术。有许多应用程序和云服务可以开发合成语音,微软定制语音, Lyrebird AI , iSpeech 和 VOCALiD ,这些应用程序和云服务让个人和企业可以使用这些技术来改善他们的代理机构。
图像合成
图像生成或图像合成是一种使用计算机视觉技术、深度学习和生成对抗网络(GANs)来合成新图像的技术。它可以生成计算机生成的非真实的人或任何物体的图像。英伟达的一个团队用从 Flickr 下载的人脸图片训练了一台电脑,创建了网站ThisPersonDoesnotExist.com。现场还有其他例子,ThisXDoesnotExist.com。
文本生成
文本生成是一种自动生成文本、编写故事、散文和诗歌、创建长文档摘要以及使用人工智能技术进行文本和深度学习合成的方法。使用 RNN(递归神经网络)和现在的 GANs,有许多文本生成的实际用例。文本生成可以帮助行业内新的自动化新闻业或机器人新闻业。 OpenAI 的 GPT-3 可以生成任何文本,包括吉他标签或计算机代码。
积极使用
技术非常强大,是一个伟大的推动者。技术可以给人们声音、目的和能力,以大规模和快速地产生影响。由于数据科学和人工智能的进步,赋权的新想法和能力已经出现。人工智能生成的合成媒体有许多积极的用例。技术可以为所有人创造可能性和机会,无论他们是谁,如何听、说或交流。deepfake 的技术进步在某些领域有明显的好处,如无障碍、教育、电影制作、刑事取证和艺术表达。
恶意使用
与任何新技术一样,邪恶的行为者将利用创新并利用它为自己谋利。GAN 和 Deepfakes 已经不仅仅是研究课题或工程玩具。开始是作为一个创新的研究概念,现在它们可以被用作一种交流武器。Deepfakes 变得越来越容易制造,甚至更容易在政策和立法真空中传播。
Deepfakes 使人们有可能在未经同意的情况下制造媒体——交换面孔、对口型和木偶——并给心理安全、政治稳定和商业中断带来威胁。Deepfakes 可以用来损害名誉、伪造证据、欺骗公众和破坏对民主制度的信任。在过去的两年里,恶意使用使用生成式人工智能模型创建的合成数据的可能性已经开始引起人们的警惕。这项技术现在已经发展到有可能被武器化,对个人、社会、机构和民主造成破坏和伤害。深度造假不仅会造成伤害,还会进一步侵蚀已经下降的对媒体的信任。还可以帮助公众人物将自己的不道德行为隐藏在 deepfakes 和假新闻的面纱中,称自己的实际有害行为为虚假,也就是所谓的骗子红利。
Deepfakes 可以促成事实相对论,让威权领导人得以茁壮成长。
非国家行为者,如叛乱团体和恐怖组织,可以使用 Deepfakes 来代表他们的对手发表煽动性言论或从事挑衅性行动,以激起人们的反国家情绪。例如,一个恐怖组织可以很容易地制作一个 deepfake 视频,显示士兵侮辱一个宗教场所,以点燃现有的反政府情绪并引起进一步的不和。国家可以使用类似的策略来传播针对少数群体或另一个国家的计算机宣传,例如,一个假视频显示一名警察大喊反宗教诽谤或一名政治活动家呼吁暴力。
所有这些都可以用更少的资源、互联网的规模和速度来实现,甚至可以通过微目标来获得支持。
对策
为了捍卫真理和保障言论自由,我们需要一个多利益攸关方和多模式的方法。任何减轻恶意 deepfake 的负面社会影响的对策的主要目标必须是双重的。第一,减少对恶意 deepfakes 的暴露,第二,最小化它可能造成的损害。
针对恶意 deepfakes 的有效对策分为四大类:立法行动和法规、平台政策和治理、技术干预和媒体素养。
[我将在未来的文章中探讨政策和监管]
喜欢? 随便给我买本书
参考
【1】https://papers.ssrn.com/abstract_id=3213954
【2】https://slate . com/technology/2019/06/druged-Pelosi-deep fakes-cheap fakes-artificial-intelligence-dis formation . html
【3】https://www . MSN . com/en-us/news/politics/Lindsey-Graham-campaign-ad-features-image-of-counter-with-digitally-altered-dark-skin-tone/ar-bb 17 itff?ocid=msedgntp
【4】【https://arxiv.org/pdf/1808.07371.pdf】
人工智能产生流行的视频创意

Kon Karampelas 在 Unsplash 上拍摄的照片
使用递归神经网络激发下一个病毒视频
Y ouTube 是一个庞大的平台——成功获得推荐算法青睐的视频可以获得数亿次观看。当内容创作者试图创造下一个病毒式视频时,人工智能可以产生许多你想要的趋势视频创意!
在这篇文章中,我将展示任何人如何用四行代码创建和训练递归神经网络来生成趋势视频想法!
首先,一点轻理论…
如果你对递归神经网络如何工作不感兴趣,可以直接跳到实现上。
递归神经网络(RNN)是一种专门处理序列的神经网络。给定一个种子“她遛了她的 _ _ ”, RNN 可能会预测“狗”。RNNs 在文本生成中的技巧是使用预测作为进一步预测的种子。

给定种子“她”,RNN 如何生成文本。粗体字是 RNN 的输出。
应用于文本生成的标准神经网络的一个问题是它具有固定的输入和输出大小。例如,在 MNIST 数据集上训练的卷积神经网络中,每个训练和测试示例只能有 784 个值,不能多,也不能少。虽然这在像图像识别这样的任务中是可行的,但它肯定不适用于自然语言处理任务,在自然语言处理任务中,输入和输出可能在几个字符到几个句子甚至更多之间变化。
RNNs 允许可变长度的输入和输出。RNN 可以看起来像下面的任何一种,其中红色是输入,绿色是 RNN,蓝色是输出:

标准和卷积神经网络对于每个输入值或像素具有不同的一组权重和偏差,而递归神经网络对于所有输入具有相同的一组权重和偏差。RNN 通常有三组权重和偏差-一组在输入图层和隐藏图层之间(红色到绿色),一组在隐藏图层和另一个隐藏图层之间(绿色到绿色),另一组在隐藏图层和输出图层之间(绿色到蓝色)。
因为在每个层到层的链路上使用相同的权重和偏差集,所以可以非常容易地调整层中的像元数量,包括输入和输出。因为参数很少,所以可以确定最佳的权重和偏差。
那么,为什么 RNN 如此擅长生成文本呢?
RNN 文本生成基于一个基本原则,即句子中的下一个单词总是以相同的想法应用。这是有道理的——作为一个作者,你写下的下一个单词和前一个单词的意图是一样的。

在上图中,第一个句子是这样写的,每个单词都有相同的意图。第二句话以同样的意图开始,但因为它不断转换,最终结果与最初的意图相去甚远。
通过在每组单词上应用相同的 RNN,句子的意图(它试图去哪里,它包含什么思想)以及句子的措辞都得到了保持。
如果你想对 RNNs 有更深入的解释,可以看看这些研究论文。
实现病毒式视频标题生成器
所有的机器学习模型都需要数据。我们将使用的数据集是 Kaggle 上的趋势 YouTube 视频统计数据集。
当加载和查看数据集时,我们可以了解数据的结构:
import pandas as pd
data = pd.read_csv('/kaggle/input/youtube-new/USvideos.csv')
data.head()

*右边还有更多列,但我们不需要它们
我们对title栏感兴趣——这将为训练 RNN 提供数据。该数据有 40,949 行;与一些较大的数据集相比,这并不算多,但是为了保持合理的训练时间,让我们将训练数据减少到 5,000 个实例。
此外,我们应该缩小培训数据的类别:

在查看了不同的类别后,很明显有些类别是新闻、音乐视频、电影预告片等。,这在创意生成器的上下文中没有意义,因为新闻、歌曲标题、音乐视频标题等要么无法生成,要么没有意义。类别 IDs 22、23 和 24 专用于由小型内容创建者创建的喜剧和较短片段。这些更符合我们想要生成的内容。
下面的代码选择data中属于类别 22、23 或 24 的行,并将它们放入名为sub_data的数据帧中。
sub_data = data[(data['category_id']==24) | (data['category_id']==23) | (data['category_id']==22)]

右边还有更多未显示的列。
仍然有 16,631 行—为了将其减少到 5,000 行,我们将随机洗牌几次,然后选择前 5,000 行作为训练数据。sklearn方便的shuffle功能可以帮助:
from sklearn.utils import shuffle
sub_data = shuffle(shuffle(sub_data))
要将数据输入到模型中,数据必须在文本文件中,每个新的训练实例在单独的一行上。下面的代码就是这样做的:
titles = open('title.txt','w+')
for item in sub_data.head(5_000)['title']:
titles.write(item)
titles.write('\n')
titles.close()
注意,.head(n)函数选择数据帧中最上面的n行。
要查看title.txt,我们可以调用print(open(‘title.txt’,’r’).read())。

文件的一部分,实际文件要大得多。
最后,培训文件准备好了。有许多强大的库可以实现 rnn,如 Keras (TensorFlow)和 Pytorch,但我们将使用一个库,它可以跳过选择名为textgenrnn的网络架构的复杂性。这个模块可以在 3 行代码中调用、训练和使用(如果从 pip 安装的话是 4 行),代价是缺乏可定制性。
!pip install textgenrnn
…在 Kaggle 笔记本电脑环境中安装模块。如果在其他环境中操作,您可以移除!。
训练很简单:
from textgenrnn import textgenrnn
textgen = textgenrnn()
textgen.train_from_file('title.txt', num_epochs=50)
由于 textgenrnn 建立在 Keras RNN 框架上,它将输出一个熟悉的 Keras 进度跟踪打印:

这需要大约 2.5 小时来运行所有 50 个时期。
textgen.generate(temperature=0.5)
…可用于生成示例。“温度”是对生成的示例有多新颖的度量(越少,越新颖)。这是一种创造性(较小的温度)但又不会偏离任务本质太远的平衡,是适配不足和适配过度之间的平衡。
最后是生成的视频片头!
为了显示模型随时间的进展,我将包括(大约)每 10 个时代的三个标题,然后留给您一个由 50 个时代模型生成的标题组成的宝库。
1 个纪元(损失:1.9178) —
- 让我制造更多猫的时刻即将到来的时刻|时刻|时刻
- Keryn 迷失——Marlari Grace(独立之年)
- 阅读 Omarakhondras | Now Cultu 1010–75
10 个时代(损失:0.9409) —
- 格莱美舞蹈系列帮助一个好的 Teass 形状|威尔·史密斯和第五季官方预告片
- 卡迪图书广告 TBS 上的舞蹈
- 为什么你的男朋友穿手帕
20 个时代(损失:0.5871) —
- 我妈妈给我买衣服!
- 恐龙瑜伽挑战!!
- 电影-全部 Tam | Lele Pons & hule & Jurassic continest for Anime | E!
30 个时代(损失:0.3069) —
- 镜面抛光的日本箔球挑战赛在液压机里粉碎-里面是什么?
- 为什么贾斯汀比伯是最差的 SNL 嘉宾| WWHL
- 你从未见过的最著名的演员
40 个时代(损失:0.1618) —
- 威尔·史密斯和乔尔·埃哲顿回答网上搜索最多的问题
- 亚当和詹娜的陈文静——舞者 Sharisons &揭示你的门 ftta 回答 Saffle 官员
- Bravon 去首尔 Charman 的 Fabar Things 2 买运动鞋
…最后,前五个 50 时代(损失:0.1561)生成的标题!
- 我儿子帮我化妆
- 24 小时 BOX FORT 监狱越狱
- 利亚姆·佩恩去买运动鞋
- 星球大战:单身汉大结局
- 迪士尼公主推着卡车
更进一步…
…这是一个关于 RNNs 能力的幽默例子。你可能已经注意到,随着时代数量的增加,这些想法越来越缺乏原创性——过度适应。这和我们限制训练例子的数量有关。如果您想自己尝试一下(并且有几个小时的计算时间),您可以尝试只限制 be 类别,而不限制训练示例的数量(或者使用整个数据),这样生成的标题可能会更有趣。
感谢阅读!
如果你喜欢,你可以看看 RNNs 的其他一些有趣的应用:
- 使用 RNNs 生成仿莎剧(使用 TensorFlow)
- 使用 RNNs 在艾·乔·拜登和艾·伯尼·桑德斯之间创建一场辩论死亡赛(使用
textgenrnn





浙公网安备 33010602011771号