解码你的基因
神经网络能解开我们 DNA 的秘密吗?
我通过总结激动人心的新研究论文来探索人工智能对传统科学的影响。在这篇文章中我讨论的是另一篇很酷的论文:《深度递归神经网络对牛津纳米孔测序数据的 DNA 碱基修饰检测》( 《自然通讯》,10,2449,2019 )。
1 |你背后的代码
你身体的每一部分都是你的 DNA(脱氧核糖核酸)的产物,DNA 是一种复杂的遗传密码,精确地描述了你的细胞应该做什么。我们都知道 DNA 分子著名的双螺旋形状:它由称为“碱基”(胞嘧啶[C]、鸟嘌呤[G]、腺嘌呤[A]和胸腺嘧啶[T])的不同化学单元组成,它们结合在一起形成美丽的螺旋链。这有点像二进制计算机代码,但不是 1 和 0 的序列,而是 Cs、Gs、As 和 Ts。这些链中 CGAT 碱基的精确序列编码了你和地球上其他动物的一切。
DNA 的双螺旋结构。图片来自pixabay.com
一个真正重要的生物过程是 DNA 甲基化:这是一个简单的化学甲基(CH3)被添加到正常的 DNA 碱基中:下图显示了这种变化有多小。虽然这种变化看起来很小,但它可能对基因调控、衰老甚至癌症产生巨大影响。人们甚至认为这些甲基化可以作为癌症治疗的治疗靶点!
正常胞嘧啶(DNA 中的 C 碱基)和甲基化版本的比较。在知识共享许可的许可下复制。
2|用纳米技术绘制 DNA 变化图
显然,我们能够绘制出我们遗传密码中的修改是非常重要的……但这实际上很难做到。目前的技术噪音大,分辨率低,因此确实需要改进。最近的一个想法是基于一种非常酷的纳米孔技术。你可以看看这个很棒的视频展示了它是如何工作的,但基本上离子电流是通过含有微小纳米孔的聚合物膜。当感兴趣的分子穿过这些小孔,从膜的一侧移动到另一侧时,电流以特有的方式受到干扰。所以你放入 DNA 分子,你会得到一个 2D 序列的变化的电子信号,可以用来识别遗传密码。这项技术最近被用来在仅仅 7 小时 内测序新冠肺炎的全部遗传密码!
尽管这个系统非常擅长获得整个 DNA 序列,但要定位存在微妙甲基化的位置有点困难,因为理解信号是依赖于上下文的。甲基化可以通过比较甲基化和未甲基化 DNA 序列的纳米孔电子信号来定位。
显示 DNA 穿过膜在电子信号中产生干扰的示意图。
3 | ML 能帮上什么忙?
如果你在序列数据中寻找模式,RNNs(递归神经网络)是最好的架构。如果你不熟悉,让我们快速看一下它们是如何工作的。
典型的“前馈”神经网络遵循将随机初始化的权重和偏差应用于输入以预测输出的过程。当将生成的输出与目标输出进行比较时,会计算出一个误差(或“损失”)。这种损失然后通过网络传播回来,以更新权重和偏差,目的是提高输出。在训练期间,这个过程用不同的输入反复重复,直到网络有希望学会产生准确的输出。这只是一个非常简单的概述,但总结了主要原则。
如果您预测的不是单个输出,而是一系列输出,该怎么办?从概念上讲,RNN 可以被认为是一系列相连的前馈网络,信息在它们之间传递。被传递的信息是隐藏状态,它代表所有先前输入到网络的信息。在 RNN 的每一步,前一步生成的隐藏状态以及下一个序列输入都会被传入。然后,这将返回一个输出以及要再次传递的新隐藏状态。这使得 RNN 能够保留迄今为止看到的序列信息的“记忆”,并使它们对于理解序列数据非常有用。你可以在这里找到一个更加数学化的描述。
让我们来看看 RNNs 究竟是如何破译 DNA 修改的。
通过 RNN 表示信息的移动
4|用 RNNs 解开 DNA
在本文中,开发了一种新工具“DeepMod”。这是一个双向 RNN(它向前和向后传递序列信息),具有长短期记忆(LSTM);点击查看 lstm的精彩摘要。
DeepMod 将参考遗传密码和纳米孔电信号作为输入。电信号中的“事件”(由纳米孔测序仪产生的一系列信号点)与参考中的 DNA 代码对齐。这是使用 BWA-MEM 实现的,这是一种将 DNA 序列与参考基因组匹配的比对算法。这种算法能够匹配长达百万碱基的 DNA 序列!
作者使用输入信号的 7 特征向量描述;与事件相关的信号平均值、标准偏差和信号点数,结合 DNA 碱基的四个特征描述(A、C、G 或 T)。这作为网络的输入(见下面的体系结构),预测信号事件是否是修改碱基的结果。
该算法首先使用来自大肠杆菌细菌 DNA 的数据进行训练和优化。发现具有 3 个隐藏层的 21 单元 LSTM 在保持合理的计算成本的同时实现了高精度的结果。对几个不同大肠杆菌数据集的分析显示了惊人的单碱基甲基化图谱分辨率。此外,该网络在识别哪些碱基被甲基化方面显示出很高的精确度(高达 0.99)。
显示具有 LSTM 的 DeepMod RNN 的结构的图表,表明电子输入如何通过网络输出对感兴趣位点甲基化的预测。在知识共享许可下,经原文许可复制。
T4:这能绘制出人类的遗传密码吗?
是啊!**尽管 Deepmod 只在细菌 DNA 数据上进行训练,但它被用来对人类 DNA 中的甲基化进行准确预测。**这项跨物种测试确实令人兴奋,因为它表明,在一个物种上训练的模型可以用来精确绘制该模型从未见过的物种的 DNA 结构。也许这个模型也可以应用到不同物种的负荷上,看到这些结果真的会很令人兴奋!
这是一个很好的例子,说明了神经网络归纳新任务和加快科学学习速度的能力。这也是一个很好的例子,机器学习被应用于当前的科学问题,以产生一个即时和实用的解决方案。DeepMod 代码现在可以在线获得,作者计划为未来的用户维护和更新它。这个工具分析人类 DNA 修改的高速和高精度能力可能有助于理解和治疗不同的疾病,如癌症,所以这是一个非常酷的结果!
图片来自pixabay.com
6|最终想法
尽管取得了这些巨大的成果,但还是有一些事情需要记住:
- DeepMod 只对两种类型的 DNA 甲基化进行了训练和测试,但实际上有许多不同的类型。需要更多的测试来了解这个模型是否可以用来定位真实 DNA 中存在的大范围的修饰。
- 该模型没有检测 RNA(核糖核酸),DNA 的单链表亲。对于编码、解码和基因表达来说,这是一种必不可少的生物分子,所以看看这个模型在这项任务中的表现将会非常有趣。
- 最后,该模型严重依赖于使用 BWA-MEM 将输入信号与参考 DNA 进行比对。如果对齐不良,模型的性能将受到严重影响,并且在培训时需要记住这种依赖性。
总的来说,这是一个非常有前途的神经网络物理应用,如果你喜欢这个简短的总结,我鼓励你阅读原始论文以获得关于 DeepMod 框架、训练和验证过程的更深入的细节。
逐步分解量子机器学习算法。
二元分类器的变分电路。
量子计算机在 15 年前被认为是科幻小说。
现在,这些机器真实存在,并在云上公开。我们相信它们可以解决在经典计算机上无法解决的问题,应用于化学、最优化、机器学习、密码学和许多其他领域。
10 月,谷歌宣布了量子优势,这意味着量子计算机第一次能够比任何现有的经典计算机更快地执行特定任务。实际上,在谷歌和 IBM 之间有一场争论,谷歌声称这项任务在经典计算机上需要 10,000 年的时间,而 IBM 则表示几个小时就可以完成。在所有情况下,量子计算机都需要几分钟,因此这是该技术潜力的证明。
在这篇文章中,我有兴趣解释量子计算如何用于机器学习。
我将展示如何用一台 2 量子位的量子计算机构建一个简单的二进制分类器。
在第一部分,我为不熟悉量子计算的读者介绍了量子计算的基础知识。然后我解释了 ML 中 QC 的一般用法,并分解了算法的不同部分。最后给出了在 iris 数据集上的实验结果。
玛利亚·舒尔德、阿历克斯·鲍恰洛夫、克里斯塔·斯沃雷和内森·维贝的作品详细解释了这种方法。
量子计算 101
资料来源:xkcd.com
现在让我们描述一下理解本文其余部分所需的量子计算基础知识。
量子物理学的基本原理是**在足够小的尺度下,世界变得具有概率性。**一个粒子不能像宇宙中的行星、恒星那样用固定的坐标来描述,而是用波函数来描述,波函数是粒子位于空间某个区域的概率。
量子态
理解量子态对于量子计算的进一步发展至关重要。
量子系统的大多数特征都不是确定性的(有些是确定性的,比如质量或电荷),它们是概率性地分布在一组可能的状态中。然而,测量这些特征将产生一个单一的值,以及相关的概率。这叫做测量。
比如一个电子既不是自旋向上也不是自旋向下,而是以 0.5 的概率自旋向上或者自旋向下。自旋的测量结果将是 50%的时间向上自旋,50%的时间向下自旋。
这种与不同状态相关的概率组合被称为量子态。你应该把量子系统看成一个骰子。骰子没有固定的数值,只允许你掷出去读取结果。那么你会说骰子的状态是 1,2,3,4,5,6,每个概率是 1/6。如果你考虑一个得到 6 的概率为 0.5 的作弊骰子,你会说骰子的状态是概率为 0.1 的 1,2,3,4,5 和概率为 0.5 的 6。
量子态的通俗例子是薛定谔的猫,它有一定概率可以是死的,也可以是活的。打开盒子就是在“测量”猫的状态。
量子态用括号符号|s >表示。对于电子来说,它应该是|上>或|下>。不同状态的线性组合如下所示。
一般的量子态。
在这种情况下,𝑎_s 被称为与状态|s >相关的振幅,它是一个复数,如|𝑎_s|是系统处于状态|s >的概率。
同样的原理,量子计算机的基本砖块是量子比特,或量子比特。与经典比特相反,量子比特没有确定值 0 或 1,而是以某种概率处于状态|0 >或|1 >。
更正式的说法是,一个量子位记为|q> = 𝑎|0>+𝑏|1>,𝑎和 b 是两个复数,比如|𝑎| +|𝑏| =1。
一个量子位可以处于|0 >或|1 >状态,但是几个量子位会发生什么呢?
两个量子位的状态被标注为|00 >、|01 >、|10 >和|11 >,这给出了 4 种可能的状态。
3 个量子比特呢?您有 8 种可能性:|000 >,|001 >,|010 >,|011 >,|100 >,|101 >,|110 >,|111 >
你可以通过在一个 ket 上并列不同量子位的值来记录任意数量量子位的状态,比如|000110101010 >。为了简化它,请注意所获得的二进制字符串的十进制等效值,例如|101 >是|5 >。
**一般来说, n 个量子位给出 2 个 ⁿ 个可能状态。意味着有了 300 个量子比特,你可以拥有比宇宙中原子数量还要多的状态!!**这是量子计算潜力的关键要素。
于是, n 个量子位的一般量子态是一个复数矢量,其平方模之和等于 1。
n 个量子比特的一般量子态。
量子态也用矢量格式表示,如下例所示。可以看出,范数平方总是等于 1,因此常数 1/sqrt(2)和 1/sqrt(3)。
量子算符
一旦我们有了量子态,对它进行操作就好了。这是量子算符的工作。
量子算符是量子态上的线性算符,因此它们可以由复矩阵 A. 表示。此外,它们是酉矩阵,这意味着 A 的逆是它的共轭转置,记为 A 。
这个性质确保量子算符的输出保持量子态,这意味着振幅的平方模的和是 1。
量子算符也被称为量子门,类似于经典计算。给量子计算机编程就是写一系列要在量子位上执行的门。
作用于一个量子位的基本门的两个例子是标为 X 的非门和标为 h 的哈达玛门。
矩阵格式的 x 门和 H 门。
X 门翻转量子位(类似于经典的非门),H 门创建量子位的相等叠加状态(在经典计算中没有等价物)。我们有以下身份:
- X|0> = |1 >
- X|1> = |0 >
- X(𝑎|0>+𝑏|1>) = 𝑎|1>+𝑏|0>
- H|0> = (|0> + |1>)/sqrt(2)
- H|1> = (|0> -|1>)/sqrt(2)
为什么使用量子计算有优势?
到目前为止,我们已经看到,量子态是离散的概率分布,量子算符可以对这些分布进行线性运算。也可以通过测量状态从分布中取样。
创建一个分布,进行计算并从中取样也可以由经典计算机完成(例如用 numpy.random )。然而,这不是立即的,并且需要几个隐藏的中间步骤(创建伪随机整数生成器、从统一规律采样、取 cdf 的逆,等等)。所有这些过程通常是昂贵的。
量子计算机是一种物理设备,它将利用量子力学定律,以一种廉价的方式为你进行所有这些概率运算。
经典位的基本运算是进行 1+1、0+0、1+0、翻转位等。有了这组基本操作,您就能够对两个整数的加法进行编码,然后进行乘法运算,接下来就是其他算法了。
量子计算机的基本操作是创建一个骰子,投掷它并读取结果。从那里,你创建许多其他算法。这些算法有时可以为在传统计算机上执行的相同操作提供巨大的加速。
计算机科学的核心是把问题分成简单的步骤,然后交给一台机器,让它非常快速地执行这些简单的步骤。有了量子计算,你把你的问题分成了比以前更多的步骤,量子计算机可以非常快地执行这些步骤。你希望总成本低于一台传统计算机的成本。
身体上是什么?
来源:IBM Research ( Flickr )
存在很多技术,所有硬件提供商都在尝试自己的技术。它可以是硅中捕获的电子、冷原子或光子,我们可以单独控制它们。其他方法,如拓扑量子位,使用的基本粒子只在这种情况下研究。
在所有情况下,它归结为能够在个体水平上控制基本粒子。这是非常困难的,因为一切对环境的噪音都很敏感,这解释了建造量子计算机的困难。
总而言之,量子态是代表离散概率分布的复矢量。
量子算符是这些向量上的线性算符,其输出保持量子态。
衡量一个状态就是从潜在的概率分布中取样。
量子计算机是比经典计算机执行这些操作更快的物理设备。
在机器学习中使用
在二元分类问题中,比方说将图像标记为猫或狗,目标是从训练集构建预测器。换句话说,我们希望构建一个函数 f 比如 f(图像) ∈ { 猫,狗 }给出尽可能接近现实的结果。
通常情况下, f 的图像代表图像属于某一类或另一类的概率,例如, f(图像)= P(图像=狗)。
这种概率形式非常适合量子计算,我们希望建立一个量子态|ψ>,例如
|ψ(image)> =*P(image = dog)|0>+P(image = cat)|*1>
实际上,|ψ>是通过一组参数化门和输入数据构建的。多次测量可以估计不同的结果概率。
优化电路就是找到最接近现实可能性的参数。这一步对于所有的 ML 算法都是一样的,只是这次我们通过量子测量来计算结果。
我们希望在量子计算机上执行所有这些操作会比在经典计算机上更便宜。具体来说,我们希望制备和测量量子态比在 CPU 和 GPU 上执行矩阵产品更快/更便宜。
对于狗/猫分类问题,卷积神经网络表现得非常好,量子计算不太可能会更好。但是对于不同的配置,在高维空间中,有可能在特定问题上性能会更好。
参数化量子电路
量子计算探索的一个完整领域是变分电路或参数化量子电路的使用。
参数化量子电路的一般思想是创建具有可调参数的量子电路,并且该电路的有效测量将接近感兴趣的量。然后,我们可以根据电路的参数最小化这个感兴趣的量。
让我们深入一个具体的例子来说明这一点。
我们考虑以下门,并将其应用于|0 >。
我们有 U(𝜃,ϕ,λ)| 0 > = cos(𝜃/2)|0>+e^(Iϕ)sin(𝜃/2)|1>。
假设我们想最大化结果的熵,也就是
E(𝜃,ϕ,λ)=-p(u | 0 > = 0)*log(p(u | 0>= 0))-p(u | 0>= 1)*log(p(u | 0>= 1))= -cos(𝜃/2)*log(cos(𝜃/2))-sin(𝜃/2)*log(sin(𝜃/2))
那么,最佳参数是𝜃 = π/2,ϕ和λ可以取任意值。
这个例子非常简单,所以一切都可以通过分析来计算,但在更复杂的电路中,概率是通过多次测量来估计的。
当你想用一个容易计算的参数化概率分布(如高斯混合分布)来近似一个未知的难以处理的概率分布时,这个过程与变分法(变分法的名字由此而来)是一样的。
在分类问题中,人们想要创建以下参数化的量子态:
|ψ(图片; 𝜃 ) > = P(图片=狗;)|0>+p(image = cat;)| 1>****
请注意,上述表达式中的 𝜃 与前一个门的𝜃参数不一样。
训练的步骤是找到最好的等概率接近现实。这是通过经典的优化技术如梯度下降来实现的。******
问题是
我们考虑一个二进制分类问题,在{0,1} 中输入实向量𝑥,二进制输出 y 。
我们想要建造一个量子电路,它的输出是一个量子态
|ψ(x;)>=p(y = 0 | x;)|0>+p(y = 1 | x;)| 1>************
该算法
所提出的算法由 3 个步骤组成:
- 状态准备
- 模型电路
- 测量
第一步叫做态准备,它包括将经典数据嵌入量子态。有几种方法可以做到这一点,其中一种被称为振幅编码。它包括把一个矢量的坐标映射成一个量子态的振幅值。它要求向量标准化,并具有二维幂。当数据集不满足这一条件时,可以填充并重正化向量。
振幅编码程序。
对于熟悉量子电路符号的读者来说,状态准备电路如下:
2 量子位和 4 维输入向量的状态准备电路。
第二步是模型电路,严格来说还是分类器。参数化酉算子 U(𝜃) 是创建的,使得|ψ(x;𝜃)>=u(𝜃)|ϕ(x)>。这是一系列的将军 U ( 在前面的小节 ) 和 CNOT 盖茨(更多关于 CNOT 门的信息在这里)。**
最后一步是测量步骤,通过执行几次测量来估计属于某个类别的概率。这相当于从分布中多次取样。****
最终电路如下:
量子分类器的最终电路。
培养
执行训练以最小化二进制交叉熵损失。
使用批量随机梯度下降。计算损失函数的梯度并不明显。幸运的是,它们可以通过其他量子电路来估计。
这部分我就不赘述了,因为它比较技术性,需要更多的量子计算知识。如果你想了解更多,我鼓励你去看看这个笔记本(最后的链接)。
实验和结果
该算法已经在 iris 数据集的二进制分类上进行测试,该数据集具有大约 100 个 2 个特征的点。它已经用 IBM 开发的框架 Qiskit 实现了。完整的代码和详细的解释可以在这里找到。
如图所示,该算法运行良好。它在验证集中达到了几乎 100%的准确率。
主要的不方便就是很慢,至少在我一般电脑上的 Qiskit 模拟器上。代码当然可以优化,但是必须记住,这只是一个验证一般方法的玩具示例。这个问题必须足够复杂,量子计算才有用。
算法的最终结果。
结论
量子计算是一种完全不同的计算范式。在大状态空间上计算概率分布并对其进行线性运算是一种自然的方法。
这是一个很好的机器学习工具,但我们需要等待更好的硬件来开发实际的用例。
谢谢你的帮助,有很多信息,我尽量让它简洁。我希望你能更好地理解量子计算,以及如何将其用于机器学习。
欢迎分享您的反馈,您可以在 LinkedIn 上联系我,或者对文章发表回应。
参考资料和资源
- 玛利亚·舒尔德、亚历克斯·鲍恰洛夫、克里斯塔·斯沃雷和内森·维贝,以电路为中心的量子分类器 (2018)
- 同样的算法由 Xanadu 在 PennyLane 库中实现:https://PennyLane . ai/qml/demos/tutorial _ variable _ classifier . html
- 完整代码及解释笔记本:https://github.com/Slimane33/QuantumClassifier
去融合混淆矩阵
数据科学家使用模型从数据中得出一些结论。在监督学习的情况下,由于输入和输出(标签)都可以用于我们的数据,我们可以尝试找到一个将输入映射到标签的函数。该模型将从一组特定的数据中学习,结果将在另一组数据中进行测试。我们将参考训练数据作为我们用于第一个任务的值和用于后者的测试数据。一旦模型被测试,下一步就是在做任何决定之前找出它的性能。混淆矩阵是用于描述分类模型成功与否的表格。
混淆矩阵中的元素
我们从分类器中决定的可以是‘肯定的’或‘否定的’(是/否——有/没有)。另一方面,从我们与之比较的原始数据来看,也有两种可能的结果:“真”或“假”(是/否——有/没有)。因此,我们的表现是对来自实际数据和预测的“真/假”与“正/负”的验证。我们想衡量我们对测试数据的预测有多成功。
我们的预测分为 4 类,由可能的组合来代表。
2 * 2 种可能的结果!!!
- 真阳性(TP): 我们预测‘是’,并且它是正确的(“真”)
- 真否定(TN): 我们预测‘不’,也是正确的。
- 假阳性(FP): 我们预测了阳性结果,但它被错误地预测了。
- 假阴性(FN): 我们预测了一个阴性结果,它是“假的”
根据混淆矩阵计算的指标
实际阳性:TP + FN 和预测阳性:TP + FP
这 4 个数字说明不了什么,因为我们对积极结果的百分比一无所知。我将介绍从混淆矩阵中计算出的 3 个指标。
精度。这个百分比帮助我们确定我们的模型有多“准确”,即模型做出正确预测的百分比。然而,使用准确性作为评估模型的主要度量标准存在一些限制。我们在研究中没有考虑假阴性。对于一家招聘公司来说,我们会拒绝一个符合条件的候选人。
大多数情况下使用更好的度量标准:精确度和召回率(或灵敏度)。
Precision 讲述了我们的分类器在检测正面观察时的性能。正确分类的阳性与预测阳性总数的比率。预测的阳性率有多少是正确的?
精度= TP/(TP+FP);分母是预测的总阳性数
回忆(也称为 TP 率):模型在挑选积极的观察时有多敏感。它回答了这样一个问题:模型捕捉到的阳性占所有实际阳性的百分比是多少?
回忆(或敏感度)= TP / (TP+FN)
每个环境都是独特的,基于场景,数据科学家将决定什么样的指标适合他的模型。此外,他还必须考虑什么样的错误是可以接受的。这将帮助他选择假阳性和假阴性之间的界限。
如果你有任何想法,并想讨论,请让连接。
解构咖啡:分割烘焙、研磨和分层以获得更好的浓缩咖啡
使用分离咖啡混合物的断奏浓缩咖啡的下一次进化
一年多前,我开发了一种叫做断续浓缩咖啡的技术,用筛子将咖啡渣分成细粒、中粒和粗粒。然后我做了一个分层(断奏)镜头,首先放精细层,然后是粗糙层,然后是中间层。我发现每一层都提供了特定的味道,有助于整体的味道,通过这种方法,我得到了更好的味道。然后我就开始胡思乱想了。
分裂断奏捣实拍摄使用中等和黑暗的烘烤。
我开始考虑咖啡烘焙。我不喜欢单一产地的咖啡,因为我发现它们不均衡,而且我已经在家烘焙了三年。通常,我会将一颗非洲的咖啡豆和一颗南美的咖啡豆混合在一起,制成一种很棒的混合物。我在烘烤前混合,因为我不想把时间花在烘烤两次和烘烤后混合上。
然而,分离颗粒大小的一个自然延伸是分离咖啡混合物以分离豆类。我忍不住让过程变得更复杂,因为在那个时候,我有最复杂的浓缩咖啡准备程序。我介绍了历史、断续浓缩咖啡和断续捣实的咖啡的技术,并展示了几个月来收集的一些数据,以展示它如何在味道和 EY 方面产生更好的照片。
技术发展
为了实验,我分别烘焙了两种咖啡豆的典型混合物。我将混合物分开,并分别磨碎和过筛。我开始尝试一个六层的断奏镜头:2 个精细层,2 个粗糙层,和 2 个中间层。我通过交替选择哪一层先出现,哪一层从分离中受益最大来检测味道。我发现只有精细的那一层需要被分离,但是哪一层先出现对这项技术的益处有影响。
在第一个实验中,我分别烤了哥伦比亚蜂蜜工艺的布宜诺斯艾利斯格沙和卢旺达干工艺的鲁西齐尼亚卡伦佐。然后我把它们分别磨碎过筛,开始测试。我立刻看到了分数差异。我不知道它们有多重要,在我开始分割所有镜头的时候,我只会在烤肉的前两个镜头中改变方向。
细豆 1,细豆 2,夯实,粗混合,中混合,夯实
我收集了一些不同烧烤的数据,这些数据不足以得出任何强有力的结论,但肯定会有不同烧烤之间的差异。这是一场正面交锋:
这种比较着眼于无分割与两种不同方向:
对断奏捣固的交叉应用
断奏捣固是断奏击球的派生物。我在研究一些夏威夷的深色烘焙咖啡,我发现把所有的咖啡渣都放在过滤器里太乱了。于是我开始只放一半,分发,捣实,接着放另一半。与此同时,我对断奏浓缩咖啡有了更深的理解,我发现中间层(断奏镜头中的顶层)是决定镜头如何根据其夯实程度来判断是否成功的关键层。
我尝试在常规击球的前半段做一个较重的夯实,然后在上半段做一个较轻的夯实,于是断奏夯实技术诞生了。我开始跟踪底层压力,我发现底层压力在 300 克到 500 克之间是最佳的。对于顶层,我使用一个校平机,我跟踪校平机的深度。
当我对这种技术感到更加安全后,我开始将烤肉分成四层。我将称重并分配前两层,夯实,称重并分配后两层,然后整平。
对于断奏夯实准备,我还发现了分裂豆子的好处。准备工作包括两层,顶层和底层,底层比第一层夯实得更紧。类似于分割一杯不连续的浓缩咖啡,顶层不需要被分割。为了简单起见,我通常把它分开。
数据和分析
我花了一年的时间收集这些数据,但困难在于确保我有可控制的样本。在过去的一年里,我的技术发生了很大的变化,我会定期采集一些有无分裂的样本。最近,我整理了数据集,我发现我有合理数量的样本来说服自己,这种现象不是因为我的确认偏差,而是可以观察到的。
原始数据
绩效指标
最终得分是 7 个指标(强烈、浓郁、糖浆、甜味、酸味、苦味和余味)记分卡的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难,会影响最终得分。
使用折射仪测量总溶解固体(TDS ),该数字用于确定提取到杯中的咖啡的百分比,并结合一杯咖啡的输出重量和咖啡的输入重量,称为提取率(EY)。
分裂分析
查看所有数据的一些散点图,很难看到常规镜头和分裂镜头的分离。这是由于我的数据收集造成的数据不平衡。
所以让我们把这些数据简化成每次烘烤的最佳组合,普通的和分开的。
模式似乎有点清晰,但我们有成对的数据,所以让我们比较一下每个镜头。就品味(最终得分)而言,分镜头似乎比普通镜头更好,对 EY 来说,它们往往更好。
当在折线图而不是散点图上查看时,我们可以对照片进行排序,并查看它们的表现。有一些异常,但不是随机的。
我们可以通过统计测试来了解这些结果差异是否具有统计显著性。就口味而言,他们是,但 ey 在分布上还是有点太接近了。需要更多的数据,但与此同时,我一直在努力增加 EY,所以我希望即使 EY 保持不变,味道也在改善。我没有足够的数据来显示这种或那种趋势。
我们可以通过烘焙和不连续浓缩咖啡或不连续捣实咖啡来进一步分解这些数据。就味道而言,有些烤肉并没有太多好处,但有些却有。对 EY 来说,有一种烤肉尤其成问题(2020 年 4 月 6 日)。
对于 2020 年 4 月 6 日的烘烤,其中两个镜头基于顶部或底部分割烘烤,而不是同时分割顶部和底部层。因此,这是 9 克的一个烤,9 克的另一个,而不是 4.5 豆 1,4.5 豆 2 在底部和顶部相同。除去这两个样本,EY 现在有了统计上的显著改善(阈值是 p 值< 0.05)。
我们可以扩展数据,将相同的常规镜头与不同的分裂镜头进行多次比较,因为分裂镜头的数量远大于常规镜头。并不是所有的分镜头都很棒。我只是在比较最好的分镜头和普通镜头。其中一些镜头有较低的最终得分和/或 EY,因为他们参与了其他实验,如加热豆,冷却研磨,或修改分配器。
健全性检查
其中一个不受控制的变量,也是我所希望的,是产出与投入的比率。理想情况下,每个镜头都是一样的,但是艺术的一部分是视觉上的结束。有些人使用天平,但我一直使用量杯,我知道给出期望输出水平的音量范围。然后我在拍摄后用标尺测量输出。在这次收集开始时,该比率通常为 0.9 比 1.1,到最后,该比率已经漂移到 1.2 比 1.4。
让我们假设 EY 和比率之间有一个线性关系,我们可以做一个最佳拟合线,如下所示。有各种各样的摆动,但我们仍然可以使用它来调整所有的 EY 到 EY 在 1:1 的比例。用于这种线性关系的镜头比成对的镜头多,因为我尽可能多地包括了那些烘烤的镜头,即使它们没有成对。
然后,我们可以看看调整后的 EY 氏综合症的配对,并测试统计显著性。同样,我们在 2020 年 4 月 6 日的烧烤中遇到了类似的问题,因为它们不是以相同的方式进行断奏和篡改。去除这些因素后,分割镜头和常规镜头之间的差异具有统计学意义。
这个结果不应该太令人惊讶,因为成对的镜头是在同一时间帧内拍摄的,所以比率的范围通常是相似的。
我在这里展示了一个基于断奏概念的作品,通过将烘焙咖啡豆分开来进一步改进浓缩咖啡。其结果是口味和提取得到了改善。这种分割烘焙的断奏技术对我的浓缩咖啡日常工作产生了持久的影响,这些实验进一步证明了浓缩咖啡的制作过程仍然是神秘的,还有发展的空间。
如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。
我的进一步阅读:
解构关于置信区间的常见误解
置信区间的逐步推导以及我们如何经常曲解它们。
置信区间通常被用作区间估计的常规方法。如果你曾经应用过这种方法,你可能会遇到这种说法:
- 对于 90%的置信区间,真实参数位于该区间内的概率为 90%。
似乎是合法的,不是吗?至少,在我看来,一开始是合法的。这是对置信区间最常见的误解之一。根据[ 1 ]的数据,59%的被调查研究人员落入了这个陷阱。我也不例外。
因此,让我们回到起点,在一个简单的环境中应用置信区间,并认识到为什么这种常见的误解是错误的。
区间的求导
假设我们想估计一个城市居民的平均身高。假设这个城市生活着一百万人,身高呈正态分布。假设我们知道真实的分布参数,比如说,平均身高是1.8m标准差是 0.1m 。这些是总体参数,我们通常不知道,希望通过测量来估计。
居住在城市中的所有人的身高分布。
当然,如果我们测量一百万人的身高,就可以得到真实的平均值,根本不需要任何估算。但在现实中,我们通常进行有限的实验,并希望使用总体中的一些有限样本来估计真实参数。
假设我们随机抽取 50 个人,测量他们的身高。这 50 个人是我们人口中的一个样本。我们给它们取一个代号“Subset-1”。我们可以通过计算子集 1 的平均身高(样本平均值)来估计城市中所有人的平均身高。这样做,我们就会得到一个所谓的 点估计 。
50 个随机人群平均身高的点估计
然而,如果我们随机抽取另一个 50 人的子集,平均身高的值会有所不同。每个随机子集都会给我们不同的结果。我们应该如何选择能够更好地估计真实值的唯一子集呢?
没有办法确定哪个子集会给我们更好的结果。为了将这种不确定性考虑在内,我们可以计算一个区间来估计真实的均值。那就是所谓的 区间估计 。
我们来找这样一个区间:
这是对真实平均身高(样本平均值)的估计:
50 个人的不同子集将产生不同的估计,这就是为什么平均身高也是具有某种分布的随机变量。这是带有参数的样本平均值的采样分布:
其中 s 是样本的估计标准差:
对于子集 1,我们得到以下结果:
因此,对于基于子集 1 的平均高度分布,我们得到:
让我们画出这个分布图:
子集 1 的平均高度的估计分布
我们预计,如果我们对不同人群重复测量,平均身高值将遵循相同的分布。例如,这种测量值的 90% 将匹配区间【1.757;1.803] 。让我们放大 x 轴,并在图表中查看:**
子集 1 平均高度的估计分布
这是子集 1 的 90%置信区间。
如果我们使用常用的公式和 Z 表,我们会得到相同的结果:
那么,我们如何解释上述区间的 90%置信水平呢?
考虑到这个区间的形成方式,我们可以得出结论,该区间覆盖了 50 个随机人的平均身高测量值的 90%。因此,人们可以期望在未来 90%的测量中找到这样一个区间内的平均高度。我们可以通过随机抽取 100 个 50 人的子集,计算平均身高,并将其与我们的分布进行比较来检查:
红色虚线——由 50 名随机抽样的人重复计算 100 次平均身高的结果。
但是这样的期望肯定不能满足现实。正如我们所看到的,落在估计的90%区间之外的测量值(红色虚线)的数量远大于 10。原因是我们已经根据某个随机样本均值计算了我们的区间。90%的观测值只有与真实值相匹配才会落在估计区间内。我们可以绘制真实区间,因为我们知道真实参数:
红色虚线—100 次估计的结果,50 个随机人群的平均身高
但是,如果我们重复我们的测量,并建立一个置信区间,比如说,20 个随机抽样的子集,每个子集 50 人,会发生什么?以下是我们将得到的结果:
蓝线——20 个随机样本的 90%置信区间,每个样本 50 人。红色虚线——真实平均值。
可以看出,20 个置信区间中有 2 个不包括真实平均值。因此,如果我们继续进行这样的实验,一个给定的置信区间包含真实参数的几率将趋于 90% 。这就是信心水平的意义所在。
现在让我们回到主要问题:
我们是否可以说,一旦创建了一个区间,真参数(我们例子中的平均身高)就会以 90%的概率落在这样一个区间内?
答案是否定的,没有办法得出这样的概率。一旦创建了区间,真实的参数要么在区间内,要么在区间外,没有人能明确地确定它到底落在哪里。我们只能说这样的区间可能包含真实均值的频率,这就是置信度的意义所在。
置信区间的本质是它们可能包含真实值。在我们的例子中,置信区间倾向于包含 90%试验中的真实值。但这并不意味着对于某个特定的区间,有 90%的机会在该区间内找到真实值。
最后,让我们看一看原始资料,发现纽曼(作为置信区间的最初支持者)写到了它[ 2 ]:
构建置信区间的理论统计学家可以与机会游戏的组织者进行比较,在该游戏中,游戏者有一定范围的可能性可供选择,而无论他实际选择什么,他获胜的概率以及银行失败的概率都具有永久相同的值,1 — α 。赌徒对赌什么的选择,超出了银行的控制,对应于真实意义的不受控制的可能性,具有这样或那样的价值。银行赢得游戏的情况对应于真实均值实际值的正确陈述。在这两种情况下,在一长串未来“游戏”中“成功”的频率是大致已知的。另一方面,如果银行的所有者,比方说,在轮盘赌的情况下,知道在特定的游戏中球停在了区域№1,该信息不会以任何方式帮助他猜测赌徒们是如何下注的。同样,一旦抽取了样本,确定了置信区间的值,这里采用的概率计算就无助于提供里面的真实值是什么这个问题的答案。
结论
如果遇到或者需要计算一个置信区间*【a;b]* 对于置信水平 α ,你需要记住:
- 置信水平不意味着真实值落入*[a;b]* 是等于α;
- 置信水平 α 是而不是落在α内的样本数据的百分比;b];
- 置信水平 α 是而不是真实平均值落在内的实验百分比;b] 。
置信水平 α 意味着通过使用不同的样本进行重复的区间计算,我们将得到一个置信区间的百分比,包括一个倾向于 α的真实总体参数。
如果你发现一些置信区间概念令人困惑,我鼓励你去看看维基百科文章[ 3 ]中的其他误解和研究。
用 Python 修饰类中定义的方法
类中的方法修饰符
图片来自 Roselyn Tirado via Unsplash
装饰方法
Decorators 为 Python 中的函数和方法添加功能提供了一种方便而优雅的方式。装饰器可以通过多种不同的方式实现。decorators 的一个有用用例涉及到将它们与类中定义的方法一起使用。在我们创建的类中修饰方法可以扩展已定义方法的功能。例如,我们可以实现数据完整性检查,或者将方法调用的输出写入文件。我们选择做什么真的取决于我们自己。方法装饰者只是为我们提供了以优雅的方式扩展功能的工具。
和往常一样,用一个例子可以很好地展示 decorators 和方法的使用。
在下面的例子中,我创建了一个名为 NumericalOps 的简单类,它需要两个参数,val1 和 val2。在 init 构造函数中,这些参数被设置为对象中的属性。接下来,我在这个类中定义了 2 个方法,即 multiply_together 和 power。
让我们提出一个相当琐碎和做作的场景。我希望对象中设置的两个属性 val1 和 val2 是数字整数。multiply_together 方法只是将两个值相乘,然后返回该操作的值。重要的是,在 Python 中,可以对一个字符串进行乘法运算,比如用一个整数。当我们创建 NumericalOps 类 x 的实例并传入两个参数 2 和’ my_string '时,就演示了这一点,如下例的控制台输出所示。
为了提供数据输入完整性,可以使用装饰器来装饰类中定义的方法。目前,在示例中,装饰器@integer_check 被注释掉了。
为了提供数据完整性,我将编写一个名为 interger_check 的装饰器。要装饰一个类中的方法,首先使用“@”符号,后跟装饰函数的名称。
装饰器只是一个函数,它将一个函数作为参数,然后返回和另一个函数。在这里,当我们用 integer_check 修饰 multiply_together 时,integer 函数被调用。multiply_together 方法作为参数传递给 integer_check 函数,并返回 inner。然后调用本地内部函数,它接受我们称为 ref 的对象,并使用 isinstance 函数检查属性。如果传递了一个非整数类型,例如“my_string”,则会引发一个 TypeError 异常,并且会向控制台输出一条消息,告诉用户他们哪里出错了。但是,如果两个参数都是整数,inner 将返回原始方法,并将对象作为参数传递。
这个例子的源代码可以在我的 GitHub 页面上找到,这里的和下面的。
对多个方法使用同一个装饰器
为了增加 decorators 的可用性和实用性,我们可以将它们的实现设计为使用多种方法。
同样,这最好用一个例子来说明,所以让我们以上一节中的例子为基础。
让我们提议,我也希望 integer_check 装饰器验证我们在 power 方法中使用的指数也是一个整数。这在逻辑上是有意义的,因为当我们调用 power 方法时,它只是调用 multiply_together 方法,并将该方法的返回值乘以指数。因此,在每种情况下,我都需要确保 val1、val2 和指数都是整数。
为了实现这种行为,我对 integer_check 装饰器进行了修改。我只是在装饰器内部定义的局部内部函数中为 expo 参数设置了一个默认参数。现在,如果我们在我们的实例 y 上调用 power 方法,inner 将被返回,然后用我们在内部定义中标记为 ref 的对象和 expo 值进行调用。
在条件块中,如果 expo 被传递,我们使用 isinstance 函数检查它的类型,如果它不是整数,则引发错误,或者如果指数和 val1 和 val2 都是整数,则返回带有对象和指数的方法。
有用的是,我们仍然可以在 multiply_together 方法上使用 integer_check 装饰器,因为 expo 的缺省值为 None。
现在,我们有了一个装饰器,它可以在我们的类中跨多个方法执行用户输入验证。
使用整数作为输入,我们在控制台输出中得到预期的行为。
对于错误的输入(非整数类型),我们得到一个有用的指示性错误消息。
这个例子的源代码可以在这里找到。
摘要
当然,和往常一样,给出的例子相当琐碎和做作。还有其他方法来实现这里看到的行为,不需要装饰者。我在这里的目的是演示装饰器是如何工作的,以及如何将它们整合到您的代码设计中。对于那些感兴趣的人,我还写了另外两个教程,详细介绍了如何使用装饰器来装饰函数 s,以及装饰器本身如何成为一个类。这两篇文章的链接可以通过访问链接找到。
Python 中装饰器的介绍
了解如何改变对象的行为
来源:https://www . dreams time . com/photos-images/autumn-scene . html
介绍
我们习惯于在函数中传递和返回各种数据类型。是时候开始从函数传递和返回函数了。我们举个例子。
在这个例子中,我们有一个名为test
的函数,它根据一个条件调用两个内部函数中的一个。
然而,我们也可以返回对函数的引用,而不是调用函数。然后可以使用该引用来调用该函数。我们再举一个例子。
在这个例子中,我们返回的是_inner
而不是_inner().
,这种引用的返回和以后的使用是 Python 中装饰器的基本思想。
装修工
装饰器只不过是 Python 中函数的包装器。它将感兴趣的函数作为参数,在调用它之前和之后执行某些任务并返回结果。
我们传递一个引用say_hello
给我们的装饰器,然后它返回一个wrapper.
,我们用这个包装器调用我们的函数。
现在,我们不希望每次使用 decorators 时都键入所有这些内容。我们不需要。由于 Python 的语法糖,我们可以做同样的事情,如下所示:
现在让我们稍微修改一下装饰函数。现在,它非常有限。它不接受任何参数,也不返回函数返回的值。我们来补充一下。
这是编写装饰函数的一个很好的模板。让我们尝试一些简单的例子。这些不是最好的例子,但是,我希望它们可以作为一个好的起点和尝试新奇事物的动力。
1.检查统计数据
我们已经看到标准化在任何数据科学应用中都是重要的一步。因此,每当我们归一化某个东西时,我们可能想要检查归一化前后的平均值和标准偏差。为此,我们可以这样做
当我们在卷积后归一化图像以确保所有值都在 0 到 255 之间时,也可以使用这种方法。
2.强制性文件
您可以使用__doc__
属性访问功能文档。如果您正在开发一个能够自动生成文档的高级应用程序,您会希望确保您的所有代码都有文档记录。让我们试试:
查看 Python 中的 inspect 库,了解更多关于如何在 Python 中检查和使用活动对象的信息。
3.注释
类似于文档,我们可以改变注释在 Python 中的行为。当我们在 Python 中使用注释时,通常是为了确保输入和输出是某种类型。
但是,我们可以将注释用于其他用途。也许我们可以使用 output 注释将输出强制转换为预期的数据类型,如果它还不是该类型的话。
结论:
这就是本文的全部内容。我希望它能很好地介绍 Python 中的装饰者。从这里开始。了解装饰者更高级的用例。学习如何将它们应用到课堂上。学习其他库,把它们和 decorators 结合起来,构建一些有用的东西。
Decorators 和元类(下一篇文章)可以作为强大的工具,按照您想要的方式定制 Python。
~快乐学习
@ Python 中的 Decorators🍃(高级)
提升你的 Python 编程水平(奖励 : *args
**kwargs
)……🔥
B 自己比赛吧,它确实包含了很多代码。✌
这些为什么难以理解,不用我解释,就是你在这里的原因**(不要指望理论只有代码)**。但是你真的需要写装饰者吗?
编写 Python 代码的乐趣应该在于看到短小、简洁、易读的类,这些类用少量清晰的代码表达了大量的动作——而不是让读者厌烦得要死的大量琐碎代码。古迪奥·范·罗森。(python 的创造者)
目录:(可点击)
- 什么是装修工?
- 操纵 Python 函数。
1 。给多个变量分配一个函数。
2。在函数中创建函数。
3 。将一个函数作为参数传递给其他函数。
4。函数可以返回其他函数。 - 如何表示和使用装饰者。
- 装饰者的真实例子。
1。=>*获取某个功能的执行时间。*2
。Deco=>并行运行 python 函数。
3。ShowMe=>获取 CPU 时间文件等一个 python 函数。**** - Python 内置的类装饰器。
1。@ class method
2。 @staticmethod
3。@属性
****加成:学习如何使用*args
& **kwargs
decorator 只不过是在不改变现有方法的情况下向现有方法添加新功能的函数。
要理解 Decorators,你需要理解 Python 中的函数,函数是一级对象,也就是说,我们可以给同一个函数分配多个变量,或者我们甚至可以将它们作为参数发送给其他函数。
让我们看看用 python 函数可以做的一些很酷的事情。
1.将一个函数赋给多个变量。
**>>> **def** func(x):
... return x.upper()
>>> func("roar")
'ROAR'>>> new_func = func ***# Assign func to a variable.***>>> new_func("meow")
'MEOW'>>> **del** func
# We can call the new_func even after deleting the func
>>> new_func("meow "*2)
'MEOW MEOW '**
2.在函数中创建函数。(对C/C++
程序员来说是新的。)
****def** factorial(n):
*"""
Calculates the factorial of n,
n => integer and n >= 0.
"""*
**if** type(n) == int **and** n >= 0:
**if** n == 0:
**return** 1
**else**:
**return** n * factorial(n-1) ***#*** ***Recursive Call***
**else**:
**raise** **TypeError**("n should be an integer and n >= 0")**
上面的代码有什么缺陷?
factorial(10)
递归检查 10,9,8,7…的类型,这是不必要的。我们可以通过使用内部函数很好地解决这个问题。
****def** factorial(n):
*"""
Calculates the factorial of n,
n => integer and n >= 0.
"""*
**def** inner_factorial(n):
**if** n == 0:
**return** 1
**else**:
**return** n * inner_factorial(n-1)
**if** type(n) == int **and** n >=0:
**return** inner_factorial(n)
**else**:
**raise** **TypeError**("n should be an integer and n >= 0")**
嘿,你可以用一个室内设计师。好的,让我们等等。
3.将函数作为参数传递给其他函数。
****import math
def** sin_cos(func, var):
print("Call this" + **func.__name__** +"function")
print(func(var))sin_cos(**math.sin**, 60) # -0.3048106211022167
sin_cos(**math.cos**, 45) # 0.5253219888177297**
4.函数可以返回其他函数。
****def** sound(range):
"""
Args: range (Type of sound). (<class 'str'>)
Return: function object of the sound (<class 'function'>)
"""
**def** loud(x):
print(x.upper() + '🐯')
**def** low(x):
print(x.lower() + '🐱')
**if** range == 'loud':
**return** loud
**else**:
**return** lowtiger = sound("loud") ***# you can use this as a functions.***
tiger("roar..") **# ROAR..🐯**cat = sound("low")
cat("MEOW..") **# meow..🐱****
当我第一次看到这个的时候,我也有点困惑。对于每个范围,sound
返回其各自的函数。一个更有用的例子是创建一个 n 次多项式。
***Ref:* [https://www.python-course.eu/python3_decorators.php#Functions-returning-Functions](https://www.python-course.eu/python3_decorators.php#Functions-returning-Functions)**def** polynomial_creator(a, b, c):
"""
**Creates 2nd degree polynomial functions**
"""
**def** polynomial(x):
**return** a * x**2 + b * x + c
**return** polynomial
p1 = polynomial_creator(2, 3, -1)
p2 = polynomial_creator(-1, 2, 1)x = -2
print(x, p1(x), p2(x)) # -2 1 -7**
简短练习: 试写一个以次数和参数为自变量,返回一个 n 次多项式的函数。
查尔斯·德鲁维奥在 Unsplash 上拍摄的照片
完成了基础工作,接下来就很棘手了。(👀)
让我们从一个简单的装饰器开始,它在函数运行之前打印出它的名字。
🦋用你自己的例子来试试吧🦋
****🔥 Pro 提示:通过使用*args
你可以给一个函数发送不同长度的变量。*args
将其作为元组接受。了解更多 [*args](https://realpython.com/python-kwargs-and-args/)
和 [*kwargs](https://realpython.com/python-kwargs-and-args/)
decorators 的语法与我们在上面的例子中表达的不同。通常用**@**
( 美化你的代码)来表示。
🦋用你自己的例子来试试吧🦋
🔥 ProTip: 通过使用 Code-Medium 你可以直接从你的 Medium 文章中 创建 & 编辑 GitHub Gists。(如上图)。
注意:使用 decorator 包装函数时,原始函数的属性,如 doc (docstring)、name(函数名)、module(定义函数的模块)将会丢失。
尽管可以在 decorator 函数中覆盖它们,但 python 有一个内置的 decorator @ wraps 来做这件事。
如果你仔细看,我会打印每个函数的输出,如果你想返回一个输出的话。您需要在包装函数中添加一个额外的 return。
使用 decorators 时返回的用法。
为了更好地理解,让我们看一些装饰者的真实例子。
- 定时器: 跟踪一个函数运行所用的时间。
🏄♂️理解args 和kwargs 复制代码并通过传递不同的变量来运行它🏄♂️**
****🔥 Pro 提示:您可以通过使用original_looper = looper.__wrapped__
( 假设您已经使用了 *@wraps*
)解包来访问原始函数
2. Deco: 一个自动并行化 python 程序的库Link。******
Alex Sherman 创建了这个简单的库,名为 deco,它允许 python 函数并行运行,只需添加一个装饰器很酷吧…!。**
你要并行运行的函数用 @concurrent
修饰,调用并行函数的函数用 @synchronized 修饰
****@concurrent** # We add this for the concurrent function
**def** process_lat_lon(lat, lon, data):
#Does some work which takes a while
**return** result
# And we add this for the function which calls the concurrent function
**@synchronized
def** process_data_set(data):
results = **defaultdict**(dict)
**for** lat **in** range(...):
**for** lon **in** range(...):
results[lat][lon] = process_lat_lon(lat, lon, data)
**return** results**
****亲提示🔥:更快运行 python 代码的类似但先进的科学计算库是 numba 。
3. Showme : ShowMe 是一组简单的非常有用的 Python 函数装饰器。它允许您查看跟踪信息、执行时间、cputime 和函数文档。 链接 。
打印传入的参数和函数调用。
****ref:** [https://github.com/navdeep-G/showme](https://github.com/navdeep-G/showme)@showme.trace
def complex_function(a, b, c, **kwargs):
...
>>> complex_function('alpha', 'beta', False, debug=True)
calling haystack.submodule.complex_function with
args: ({'a': 'alpha', 'b': 'beta', 'c': False},)
kwargs: {'debug': True}**
打印功能执行时间。
**@showme.time
def some_function(a):
...
>>> some_function()
Execution speed of __main__.some_function:
0.000688076019287 seconds**
打印功能 CPU-执行时间。
**@showme.cputime
def complex_function(a, b, c):
...
>>> complex_function()
CPU time for __main__.complex_function:
3 function calls in 0.013 CPU seconds
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.013 0.013 0.013 0.013 test_time.py:6(test)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {range}**
参考资料部分提供了更多示例的链接。
到目前为止,您已经了解了装饰人员是如何工作的,并且创建了自己的装饰人员。让我们看看一些内置的 Python 装饰器。
流行的内置 Python 装饰器
**@classmethod:**
创建类的一个实例。(通 *cls*
非 *self*
)
**示例:假设你从不同的数据类型中获取数据,而不是创建多个类,我们可以使用@classmethod 来处理它。
Python 中@classmethod 的用法。
**@staticmethod:**
你可以在不创建类实例的情况下使用这个装饰器的方法。(无需通过 *self*
)
举例 : 假设你想为一个包含一些逻辑但却是该类的 not 属性的类创建一些 helper 函数。
**@Property**
:OOPs 中使用get
& set
命令的一种方式。
每次你调用set
或get
到盒子的maxlimit
值,它会通过@property
和@maxlimit.setter.
参考文献:
- 高级 Python 作者 Brend Klein。
-如果你喜欢 python 你会爱上 真正的 Python 。
-详细介绍@ property如何工作。
——牛逼巨蟒 装修工 。
我知道这很长,但是如果你到了这里👏敬你。不断学习,不断成长。
Python 中的装饰者:数据科学家的基础
用一个具体的例子来理解基础!
戈兰·艾沃斯在 Unsplash 上的照片
Python 中的 Decorators 用于扩展可调用对象的功能,而无需修改其结构。基本上,装饰函数包装另一个函数来增强或修改它的行为。
这篇文章将向你介绍 Python 中装饰者的基础知识。
让我们编写一个包含装饰器实现示例的 Python3 代码:
装饰定义
def **decorator_func_logger**(**target_func**):
def **wrapper_func**():
print("Before calling", **target_func**.__name__)
target_func()
print("After calling", **target_func**.__name__)
return **wrapper_func** def **target()**:
print('Python is in the decorated target function')**dec_func** = **decorator_func_logger**(**target**)
**dec_func()*****Output:***air-MacBook-Air:$ **python DecoratorsExample.py**
('Before calling', 'target')
Python is in the decorated target function
('After calling', 'target')
上面的装饰结构帮助我们在调用目标函数之前和之后在控制台上显示一些注释。
下面是定义装饰器的简单步骤;
- 首先,我们应该定义一个可调用的对象,比如一个装饰函数,其中也包含一个包装函数。
- 装饰函数应该将一个目标函数作为参数。
- 它应该返回包装函数,该函数扩展了作为参数传递的目标函数。
- 包装函数应包含一个目标函数调用以及扩展目标函数行为的代码。
多鲁克·耶梅尼西在 Unsplash 上拍摄的照片
def **decorator_func_logger**(**target_func**):
def **wrapper_func**():
print("Before calling", **target_func**.__name__)
target_func()
print("After calling", **target_func**.__name__)
return **wrapper_func**@**decorator_func_logger**
def **target()**:
print('Python is in the decorated target function')**target()*****Output:***air-MacBook-Air:$ **python DecoratorsExample.py**
('Before calling', 'target')
Python is in the decorated target function
('After calling', 'target')
在 Python 提供的语法糖的帮助下,我们可以简化 decorator 定义,如上所示。
注意@decorator _ func _ logger被添加在我们想要修饰的 target 函数之前。然后我们可以直接调用目标函数。不需要像我们在第一个例子中所做的那样,显式地分配装饰器。
多鲁克·耶梅尼奇在 Unsplash 上拍摄的照片
用参数定义多个装饰器和装饰函数
**import time***def* **decorator_func_logger(*target_func*):**
*def* **wrapper_func(*****args, **kwargs****):**
print("Before calling", target_func.__name__)
**target_func(*****args, **kwargs****)**
print("After calling", target_func.__name__)
return **wrapper_func***def* **decorator_func_timeit(*target_func*):**
*def* **wrapper_func(*****args, **kwargs****):**
ts = time.time()
**target_func(*****args, **kwargs****)**
te = time.time()
print (target_func.__name__, (te - ts) * 1000)
return **wrapper_func****@decorator_func_logger
@decorator_func_timeit**
*def* **target(*loop*):**
count = 0
print('Python is in the decorated target function')
for number in range(loop):
count += number**target(100)
target(3000)*****Output:***air-MacBook-Air:$ **python DecoratorsExample.py**('Before calling', 'wrapper_func')
Python is in the decorated target function
('target', 0.015974044799804688)
('After calling', 'wrapper_func')('Before calling', 'wrapper_func')
Python is in the decorated target function
('target', 0.47397613525390625)
('After calling', 'wrapper_func')
通过使用’ @ '语法在目标函数之前添加几个装饰器,可以很容易地用多个装饰器来装饰目标函数。装饰器的执行顺序将与它们在目标函数之前的排列顺序相同。
注意,在我们的目标函数中有一个参数 loop 。只要包装函数使用相同的参数,这就没有问题。为了确保装饰器可以灵活地接受任意数量的参数,包装器函数使用了 **(*args,kwargs) 参数。
关键要点
- Decorators 定义了可重用的代码块,您可以将这些代码块应用到可调用的对象(函数、方法、类、对象)来修改或扩展其行为,而无需修改对象本身。
- 考虑到你的脚本中有许多函数执行许多不同的任务,你需要给所有的函数添加特定的行为。在这种情况下,将相同的代码块复制到函数中以获得所需的功能并不是一个好的解决方案。你可以简单地修饰你的函数。
结论
在这篇文章中,我解释了 Python 中 decorators 的基础知识。
这篇文章中的代码可以在我的 GitHub 库中找到。
我希望这篇文章对你有用。
感谢您的阅读!
TensorFlow 2.0 中的自回归过程表示
张量流中自回归过程的一阶泰勒级数表示
张量流 2.0
与业务相关的时间序列通常是非连续的,或离散的,基于时间的过程。从操作上来说,对于企业来说,知道或者能够量化一个时间序列在未来什么时候会达到顶峰或者低谷可能是有用的。目标是捕捉趋势和周期模式,并预测未来大于 1 个样本的信号。示例笔记本可在本文的张量流公式部分获得。
趋势、周期性和噪声
在大多数与商业相关的应用中,时间序列在一段时间内具有非常数的均值和方差,或者可以说是非平稳。这与电路、音频系统和通信系统分析中使用的静态信号和系统形成对比。平均值变化的方向表示时间序列的趋势。噪声的变化也可能是某个随机过程的函数。这种噪声可能随着时间的变化而增大或减小。
有一个粒度时间限制到哪个周期或循环模式可以被捕获。在数字信号处理中,奈奎斯特速率是捕获周期为 n 的重复出现的模式所需的最小采样周期。本质上,采样速率需要小于重复出现模式的半个周期。例如,假设数据中有一个功能,它每 6 个小时测量一次销售额。可以捕获的最精细的模式是每 12 小时重复一次的模式。
自回归模型公式
自回归模型和开环反馈系统(一种控制系统)有一些相似之处。这两个系统都依赖于模型先前的输出。我们希望这两个系统都是稳定的,也就是说,不会爆发成指数输出。这些系统的不同之处在于,自回归预测可能依赖于多个滞后输入特征。自回归模型的形式如式(0)所示。
其中 T 是滞后要素的数量,w 表示自回归权重,y(t-i)表示滞后时间序列,y*(t+1)是 t+1 时的预测值。
目标是使用一阶泰勒级数近似值创建自回归模型的线性化形式。自回归公式是递归的,这意味着下一个值取决于前一个值的级联。y(t+1)处的值是使用时间步长 t 周围的 f(t+1)的泰勒级数展开来估计的。等式(2)显示了使用一阶泰勒级数近似的 y(t+1)的估计值。注意,等式(2)右侧的-1 常数将被权重吸收。
其中 f(t)是一个递归密集层,它用一些误差项表示 y(t),y*是预测输出,w_t 是权重,T 是滞后特征的数量。等式(2)示出了简单情况下的泰勒级数展开,其中 y(t+1)取决于先前的值,即 f(t+1)。我使用 f(t)而不是 y(t)的原因是因为 y(t)代表实际滞后的数据点,而不是依赖于时间的自回归函数。
在方程(3.1)中,f(t+1)相对于 f(t)的偏导数是相对于 w(t)取的。这种偏导数产生 f(t),即前一个函数值,可以用一阶泰勒级数展开式再次展开。有趣的是,这将导致类似于自回归公式的模型公式。区别在于滞后特征是有限的和离散的,而不是无限的。
(3.2)可以通过用每个滞后时间步长的先前时间序列值替换递归层 f(t)而被重新表述为线性模型,即 f(t)的值被 y(t)替换。最后,可以添加额外的滞后成分来创建自回归模型。
用于训练自回归模型的最终形式在等式(4)中示出。截距被限制为自回归权重之和。这使得该模型对中心趋势没有偏见,并且随着时间的推移具有适应性。
其中 N 是数据点的数量,T 是滞后要素的总数,w 表示自回归权重,y(t-i)表示滞后时间序列,y*(t+1)是 t+1 时的预测值。等式(5)中所示的目标函数 MSE 相对于参数是可微分的,并且可以用 TensorFlow 来优化。
应用同样的逻辑,可以预测多变量时间序列。所有时间序列的前一个值用作协变量,以同时预测所有时间序列的下一个值。在这种情况下,截距是输出节点的自回归权重之和。多元公式允许堆叠多个自回归层,以创建深度自回归模型。
澳大利亚墨尔本的每日最低温度和降雨量
澳大利亚墨尔本日最低温度和降雨量数据集用于建立自回归预测模型。该数据集包括从 1981 年开始的 3625 天的温度和降雨量。有一些丢失的值,但是这些值是为每个系列插入的。这些序列同时预测使用深度自回归模型。
温度
下图显示了整个时间段墨尔本的气温。随着时间的推移,温度似乎有明显的周期性变化。
降雨
下图显示了墨尔本不同时间段的降雨量系列。降雨量被限制在每天 0 厘米的降雨量,这使得使用自回归模型建模变得困难。为了使用降雨量,创建了降雨量的 60 滚动平均值,如下图所示。
数据集构建
- 这两个系列,即温度和降雨量,在训练之前首先被标准化。
- 数据集是通过为时间序列中的每个观察值创建 365 个滞后特征来构建的。例如,观测 365+1 将具有之前的 365*2 特征。
- 前 365 个观察值从训练数据集中排除,以避免丢失值。
- 两个时间序列的最后 1,130 个观测值,即 3 年,被用作检验预测有效性的保留集。
张量流公式
下面的代码块显示了上述自回归模型的 TensorFlow 代码。示例笔记本可在这里找到。
该模型具有大小为(N,M)的输入,其中 N 是数据点的数量,M 对应于降雨和温度的 730 个滞后特征。大小为 30 的隐藏层与自回归激活一起使用。该模型用随机梯度下降、均方误差损失、Adam 优化器、早期停止和小学习率来训练。虽然利用了早期停止,但它可能不是必要的,因为自回归模型产生的结果应该是固有地正则化的。
滚雪球自回归时间序列
可以通过将以前的预测滚雪球式地加入自回归模型来创建预测。滚雪球式的时间序列的方差可能有随时间增加的趋势,或者变得不稳定,即使实际的时间序列是稳定的。一个不合适的模型可能会变得不稳定,并随着时间的推移而发生变化。如果预测的滚雪球式的时间序列始终偏于实际趋势之上或之下,就会出现不稳定性。在模型公式中,约束截距应随着时间的推移产生更大的稳定性和适应性。
为了评估预测稳定性,该模型在不同的随机训练验证分裂上训练了 100 次,并且创建了 100 个模型。为保留集上的每个模型生成了一个滚雪球式的时间序列。期望值和标准差分别用于创建预测和置信区间。
温度预报结果
降雨量(60 滚动平均值)预测结果
在上面的图中,实际观测值、训练预测值和滚雪球式预测值分别用绿色、蓝色和橙色系列表示。温度的预测值和预报值似乎捕捉到了全球周期模式。然而,100 个预测的变化没有捕捉到时间的变化。降雨量的预测值(60 个滚动平均值)在训练数据集中似乎过拟合。过度拟合可能是由于使用了滚动平均特征。该系列的趋势在崩溃为周期性模式之前,准确地捕捉了约 1 年的预测值。大约 1 年后未能准确捕捉到趋势。
结论
自回归函数的一阶近似用于制定目标函数和模型定义。发现自回归激活层的截距被约束为输入权重的和。通过堆叠自回归层,使用 TensorFlow 2.0 创建了深度自回归模型。该模式被用来同时预报澳大利亚墨尔本的温度和降雨量。自回归公式不适用于截断时间序列,需要滚动平均变换来预测降雨量。这些预测是通过将以前的预测滚雪球式地回归到模型中来创建的。该模型似乎捕捉到了小的全球趋势和周期性模式。
FB Prophet 预测比较
该模型与 FB Prophet 相比如何?Prophet 是一个完整的时间序列预测套件,有许多可调参数。为了比较,我使用了来自快速入门教程的开箱即用模型。
Prophet 似乎使用了周期图模型。它基本上挑选出顶部的周期频率 f,并将其包装在正弦和余弦函数中,以创建特征集,即 sin(f)和 cos(f)。该软件包似乎也使用了逻辑回归模型的输出。逻辑回归模型预测序列是上升还是下降。该软件包似乎支持向预测中添加额外的变量,但似乎还不支持同步多变量预测。该比较已添加到示例笔记本中。
温度预报结果
降雨量(60 滚动平均值)预测结果
在上面的图中,实际观测值、训练预测值和滚雪球式预测值分别用绿色、蓝色和橙色系列表示。温度的预测值和预报值似乎捕捉到了全球周期模式。100 个预测的变化捕捉到了随时间的变化。温度趋势似乎是上升的,但这可能不是实际趋势。降雨量的预测值(60 个滚动平均值)似乎反映了一种一般的年度周期模式。该模式在整个验证过程中是一致的。降雨量似乎呈下降趋势,但这可能不是实际趋势。
深度语境化的词汇表征——一种新的词汇嵌入方法
桑迪·米勒在 Unsplash 上拍摄的照片
单词表示是现代自然语言处理系统的组成部分。单词表示基本上给了我们一种方法,将一段文本转换成我们的计算机系统可以阅读的数字。
多年来,已经开发了许多单词表示法,旨在捕捉单词的语义和句法依赖性。开发能够捕捉人类语言微妙之处的好的单词表示是一项极其困难的任务。好的单词表示应该把相似的单词放在一起。例如,单词flight
的表示应该比单词apple.
的表示更接近于单词plane
的表示。另一个重要的考虑是语言的多义性。这是一个单词在不同的上下文中呈现不同含义的能力。举个例子,
一天一个
*Apple*
医生远离我。*Apple*
今天发布了其最新的 iPhone 型号
在上面的两个句子中,单词“Apple”有不同的含义,单词表示必须考虑到这一点,而不是独立于上下文计算单词的相同表示。
单词编码的历史
对单词进行编码的最简单的方法可能是标签编码或者对每个唯一的单词进行一次热编码。标签编码遇到了在机器学习模型中加入偏差的问题。被给予较高标签的单词可以被模型感知为更重要。
标签编码的例子
为了缓解这个问题,独热编码用一个向量来表示每个单词,该向量的特定位置被标记为 1,其余位置都是 0。向量的长度是我们的训练语料库中的总字数,可以是几千万。拥有如此巨大和稀疏的向量会导致计算和存储问题,从而使这种表示对于现实世界的应用不切实际。
一键编码的例子
2013 年,谷歌通过开发其 Word2Vec 模型取得了突破,在单词表示领域迈出了巨大的步伐。Word2Vec 考虑了单词含义的上下文相关性质,这意味着它基于分布式语义的思想。通俗地说,我们可以用下面这句名言来总结这一点。
从一个人交的朋友你就可以知道他说了什么——约翰·鲁珀特·弗斯
因此,为了计算一个单词的表示,我们将首先尝试学习该单词出现的上下文。与出现在远处的单词相比,在一个句子中彼此靠近的单词将被给予相似的表示。经过训练的 Word2Vec 模型为我们提供了有意义的输出,如下所示:
这里我们展示了 Word2Vec 为每个单词找到的最相似的单词——摘自 TurkuNLP 小组的在线演示。
尽管它没有遭受简单方法的不良属性,但它确实有一些限制。
- 它不能为模型以前没有见过的单词产生表示。这些被称为词汇之外的单词。
- 它不能很好地学习生僻字的表达。
斯坦福研究人员发布的模型 GloVe ,是分布式语义学小组的又一成员。尽管它通过考虑除了局部上下文之外的单词的整体共现统计来改进 Word2Vec 模型,但是它仍然遭受与 Word2Vec 相同的问题。
那么,一个算法如何计算出它以前没有见过的单词或者很少在文本中出现的单词的表示呢?进入 深度语境化的文字表述 ,甚至在 NAACL 2018 正式发表之前就受到了很多关注。所提出的模型在几乎每个 NLP 基准上都取得了最先进的结果。由于这一点,以及它的独创性,它被授予了 NAACL 的杰出论文这个模型如何解决与先前模型相关的问题?
让我们深入这项突破性的工作,并尝试分解细节。
介绍
这篇论文提供的第一个观点是,为了解释词汇之外的单词,我们必须将单词分解成原子单位并对它们进行处理。这使得该模型能够获得对单词形成过程的一些洞察。例如,该模型没有将单词“destroying”作为输入,而是将单词视为字符组合的并集*‘de+stabilize+ing’*。
本文讨论的第二个问题是语言多义性问题。它认识到一个词根据上下文可能有一个以上的意思。所以它不会给一个单词分配任何一个向量。相反,它通过将整个序列作为输入来计算单词的表示。
ELMo:来自语言模型的嵌入
埃尔莫模型:摘要——由阿鲁纳布·戈什创建
ELMo 主要由三个单元组成——(I)卷积神经网络(CNN),(ii)双向长短期记忆(LSTM),以及(iii)嵌入。
模型的输入?
ELMo 的输入完全是基于字符的。我们使用字符嵌入将每个字符转换成一个矢量,然后传递给 CNN 层。字符嵌入使我们能够超越以前模型的缺点。首先,字符嵌入可以提取单词嵌入可能遗漏的语言细节。其次,我们可以有效地表示词汇以外的单词,这是一个巨大的飞跃。
CNN 层的作用?
CNN 层将他们正在处理的单词的字符嵌入作为输入,并通过拾取 n-gram 特征来计算更强大的表示。CNN 层本质上是从呈现给它的令牌阵列中计算特征,从而提取一些统计、时间和空间信息。该输出然后被传递到双向 LSTM 层。
双向长短期记忆层的作用?
我们知道,LSTM 的核心是保存它已经看到的输入信息。这对于序列建模任务非常有用,因为记住先前的上下文是至关重要的。一般来说,LSTM 的是单向的;也就是说,他们只考虑过去的信息来预测结果?
另一方面,双向 LSTM 考虑来自两端的输入,一个来自过去,另一个来自未来,以做出预测。它可以通过考虑两个 LSTM 来做到这一点,一个从过去到未来,另一个从未来到过去。通过连接来自两个 LSTMs 的隐藏状态,它可以在任何时间点保存关于整个序列的信息。
举例来说,这是向前和向后 LSTM 将处理的内容:
前锋 LSTM: 她去玩了……
落后的 LSTM: …用她的球棒和球。
如你所见,双向 LSTM 通过理解过去和未来,擅长预测缺失的单词。
嵌入/输出
这就是 ELMo 模型真正脱离以前的架构的地方。以前的架构只是使用 LSTM 模型的最终隐藏状态作为单词表示,而 ELMo 考虑了 LSTM 所有隐藏状态的线性组合。LSTM 隐藏状态的权重是特定于任务的。这意味着,根据制图表达的用途,ELMo 模型将为每个图层赋予不同的权重。这是非常有利的,因为正如作者所展示的,不同的层捕获了语言的不同属性。
在他们的内在评估中,他们已经表明较高级别的 LSTM 状态捕捉单词意义的上下文相关方面,而较低级别的状态模拟语言句法的方面。同时暴露所有这些层允许模型选择它认为对手边的任务更有用的表示。例如,较高级别的层可能更有利于词义消歧任务。相比之下,较低级别的层对于诸如词性标注之类的任务可能更有用。
以这种方式组合内部状态允许非常丰富的单词表示
结果
实验结果证明了 ELMo 模型的有效性。ELMo 在一系列自然语言处理问题上,从问题回答到情感分析,都有显著的进步。ELMo 生成的表示很容易添加到现有的架构中,增强的模型实现了最先进的性能!
以下是 ELMo 达到最先进(SOTA)性能的任务:
论文结果— 艾尔默,作者 allenlp
这种无所不包的结果,以及它的应用的普遍性,使得这篇论文成为自然语言处理领域的一个重要里程碑。
结论
本文介绍了一种学习单词的高质量深度上下文相关表示的通用方法。这允许我们利用从单个模型获得的知识,并将其应用于不同的任务。我们不是为一个新任务从头开始训练一个模型,而是把 ELMo 学到的表示传递给它。
通过这个模型,我们可以利用迁移学习和半监督学习的力量。我们已经在计算机视觉中看到了这种方法的好处。众所周知,当任务中的数据不足时,在 ImageNet 数据集上进行预训练以扩充新模型是提高性能的一种好方法。
有了 ELMo,我们现在可以进入语言模型迁移学习的领域。看到我们将来如何在它的基础上发展是令人兴奋的!
下次见!
用于量子计算机的深度卷积神经网络
这项工作发表在《2020 年学习表征国际会议论文集》(ICLR)上,详细内容可以查看相关的论文 。
爱因斯坦和他令人费解的自我。(来源:我自己)
量子计算机会被用来做什么?量子计算机很有希望帮助解决许多领域的难题,包括机器学习。
在这项工作中,我们提出了在量子计算机上卷积神经网络 (CNN)的理论实现。我们称这种算法为 QCNN ,我们证明它可以比 CNN 运行更快,并且具有良好的准确性。这是与约尔达尼什·克里尼迪斯和阿努帕姆·普拉卡什的合作作品。
为了实现这一点,我们不得不提出卷积乘积的量子版本,找到实现非线性和合并的方法,以及对代表图像的量子态进行断层成像的新方法,这种量子态代表图像保留有意义的信息。
CNN 和量子计算机的超短介绍
简而言之,我们可以说量子物理系统可以描述为 2^n 维的某个希尔伯特空间中的向量,其中 n 是粒子数。事实上,这些向量代表了许多可能观测值的叠加。
另一方面,机器学习,特别是神经网络,粗略地利用向量和矩阵来理解或处理数据。量子机器学习(QML)旨在使用量子系统对矢量进行编码,并通过新的量子算法对其进行学习。一个关键的概念是,在许多向量上使用量子叠加,我们可以同时处理它们。
谷歌的量子计算机最近实现了“量子至上”。(来源:谷歌)
我不会深入解释量子计算或 QML。更多细节,我邀请新人阅读之前关于量子 k-means 的帖子(发表在neur IPS2019):
这项工作发表在 2019 年 NeurIPS 会议录上,你可以查看相关论文了解更多细节,以及…
towardsdatascience.com](/quantum-machine-learning-a-faster-clustering-algorithm-on-a-quantum-computer-9a5bf5a3061c)
卷积神经网络(CNN)是一种用于图像分类、信号处理等的流行且有效的神经网络类型。在大多数层中,卷积乘积应用于输入,被视为图像或张量。随后通常是一个非线性和汇集层。如果你不熟悉,网上有很多教程,尤其是这个技术介绍。
3D 张量输入 X^l (RGB 图像)和 4D 张量核 K^l.之间的卷积积(来源:我自己)
量子卷积层
在这一章中,我将通过集中在一层来解释什么是量子 CNN。
作为矩阵乘法的卷积乘积
这里的核心思想是,我们可以用矩阵乘法来重新表示卷积积。
X^l 和 K^l 之间的卷积等价于它们的整形形式 A^l 和 F^l.之间的矩阵乘法。输出 Y^l+1 可以被整形为卷积结果 X^l+1.(来源:我自己)
该算法首先加载量子叠加矩阵的所有行和列。然后我们使用之前开发的量子内积估计来近似输出的每个像素。实际上,这就像只计算一个输出像素(图上的红点),但在量子叠加中这样做允许同时计算所有像素!然后,我们可以同时对它们中的每一个应用非线性。
不幸的是,我们所拥有的只是一个所有像素并行存在的量子态,这并不意味着我们可以访问所有像素。如果我们打开“量子盒”并查看结果(一个测量,我们将每次随机只看到一个输出像素。在我们打开盒子之前,这里有所有的“漂浮”。就像著名的活死人猫。没错。
只提取有意义的信息
为了处理这个问题,我们引入了一种方法来只检索最有意义的像素。事实上,量子叠加中的每个输出像素都有一个振幅,关系到被看到的概率如果我们测量这个系统的话。在我们的算法中,我们强制这个幅度等于像素值。因此,高值的输出像素更有可能被看到。
在 CNN 中,输出中的高值像素非常重要。它们表示输入中存在特定模式的区域。通过了解不同图案出现的位置,神经网络理解图像。因此,这些高值像素携带有意义的信息,我们可以丢弃其他像素,希望 CNN 能够适应。
图像上量子效应(噪声、随机性、采样)的小例子。这给人一种直觉,即我们在仅采样高值像素后仍然可以“理解”图像。(来源:我自己)
请注意,在对这些输出像素进行采样时,我们可以在存储它们时应用任何类型的池(技术细节请参见论文)。我们将这些像素存储在一个传统的存储器中,这样我们可以重新加载它们作为下一层的输入。
更快的运行时间
传统上,CNN 层需要时间**(输出大小 x 内核大小 ) 。这就是为什么用大量大型内核来训练这些网络会变得昂贵。我们的量子 CNN** 需要时间**(**(σx 输出大小) x Q) 其中 σ 是我们从输出(< 1)中抽取样本的比例, Q 代表一束量子精度参数和数据相关参数。不再依赖内核大小(数量和维度),这可以允许更深层次的 CNN。更多细节参见文件。
量子反向传播
有了这个量子 CNN 的设计,我们现在想用量子算法来训练它。训练包括按照梯度下降规则更新核参数。一个更快的量子算法也可以在这里找到,它几乎等同于通常的梯度下降,但有一些额外的误差。
实验
QCNN 和量子反向传播看起来不错,但是隐含了大量的近似、噪声和随机性。尽管有这些人工制品,CNN 还能学习吗?在学习分类手写数字(MNIST 数据集)的任务上,我们比较了小型经典 CNN 的训练和 QCNN 的模拟。这表明 QCNN 可以以相似的精度学习。
量子和经典 CNN 训练曲线的比较。 σ 是每层之后从输出中抽取的高值像素的比例。除了太小的 σ 之外,QCNN 可以以良好的准确度学习。注意,这个数值模拟很小,只给出直觉,不是证明。(来源:我自己)
结论
在这项工作中,我们设计了第一个量子算法,通过引入量子卷积积和一种新的检索有意义信息的方法,几乎精确地复制了任何经典的 CNN 结构。它可以允许一个明显更快的 CNN,有更深更大的输入或内核。我们还开发了一个量子反向传播算法,并模拟了整个训练过程。
**开放性问题:**我们能在更大的架构上训练 QCNN 吗?用其他数据集?当然,当一台完整的量子计算机准备就绪时,量子 CNN 会有多好?
参考
[1] J. Allow, I. Kerenidis 等.前馈神经网络的量子算法(2018)
[2] Y. LeCun,Y. Bengio 等.基于梯度的学习应用于文档识别。IEEE 会议录(1998)
[3] G. Brassard,P. Hoyer 等.量子振幅放大与估计AMS 当代数学丛书。(2000)
[4] I. Kerenidis , J. Landman 等. q-means:一种无监督机器学习的量子算法。”载于神经信息处理系统进展(NeurIPS) (2019)。
[5] S. Chakraborty,A. Gilyén 等人在 ICALP (2019)的会议录 中的分组编码矩阵幂的力量:通过更快的哈密顿模拟改进回归技术
深度卷积 Vs Wasserstein 生成对抗网络
了解 b/w DCGAN 和 WGAN 的差异。使用 TensorFlow 2.x 实现 WGAN
丁满·克劳斯在 Unsplash 上的照片
在本文中,我们将尝试了解两种基本 GAN 类型(即 DCGAN 和 WGAN)的区别,还将了解它们的区别以及 WGAN 在 TensorFlow 2.x 中的实现。我使用 TensorFlow 的官方教程代码 DCGAN 作为本教程的基础代码,并针对 WGAN 对其进行了修改。你可以在这里找到。
DCGAN
- DCGAN 像其他 GAN 一样由两个神经网络组成,即一个生成器和一个鉴别器。
- 生成器将随机噪声作为输入,并输出生成的假图像。
- 鉴别器将真实和伪造图像作为输入,并输出值 b/w 0 和 1,即图像真实或伪造的置信度。
- DCGAN 使用二进制交叉熵作为损失函数。
- 生成器看不到真实图像,仅通过来自鉴别器的反馈进行学习。
- 生成器的目标是通过生成逼真的假图像来欺骗鉴别器。而鉴别器的目标是正确识别真实和伪造的图像。
DCGAN 中的问题
DCGAN 中出现的一些问题是由于使用了二进制交叉熵损失,如下所示。
- 模式崩溃:这是一个术语(在 GAN 的上下文中),用来定义 GAN 无法生成不同的类镜像。例如:当用 MNIST 数据集训练时,GAN 可能只能生成一种类型的数,而不是所有 10 种,即它可能只生成“2”或一些其他数。你也可以举一个例子,甘只能够产生一个品种的狗,如哈士奇,但甘训练所有品种的狗。
- **消失梯度:**由于鉴别器的置信值是只能为 b/w 0 和 1 的单个值,并且目标是获得尽可能接近 1 的值,因此计算的梯度接近于零,并且因此,生成器不能获得太多信息并且不能学习。因此,这可能导致一个强鉴别器,这将导致一个差的发生器。
解决办法
上述问题的一个解决方案是使用接近推土机距离的 Wasserstein 损失(EMD 是从一个分布到另一个分布所需的努力量。在我们的情况下,我们希望使生成的图像分布等于真实的图像分布)。WGAN 利用了 Wasserstein 损耗,所以我们现在来谈谈 WGAN。
WGAN
如上所述,WGAN 利用了 Wasserstein 损耗,因此让我们了解发生器和鉴别器的目的。
瓦瑟斯坦损失{ E(d®) — E(d(F)) }
- 因此,我们的损失是鉴别器输出对真实图像的 b/w 期望值与鉴别器输出对所产生的伪图像的期望值之差。
- 鉴别器的目标是最大化这个差异,而生成器的目标是最小化这个差异。
- 注 : 为了使用 Wasserstein 损耗,我们的鉴别器需要是 1-L (1-Lipschitz)连续的,即梯度的范数在每个点上必须至多为 1。
让我们来看一种加强 1-1 连续性的方法。
梯度惩罚
梯度惩罚用于加强 1-L 连续性,并作为鉴别器梯度的正则化添加到损失中。以下是计算梯度损失的步骤。
- 通过**(real _ image * epsilon+fake _ image *(1—epsilon))**从真实和虚假图像计算插值图像。
- 然后,计算鉴频器输出相对于插值图像的梯度。之后,计算梯度的范数。
- 然后,惩罚被计算为(norm-1)的平方的平均值,因为我们希望范数接近 1。
生成器和鉴别器的目标
因此,发生器的最终目标是增加鉴频器假输出的平均值。鉴别器的目标是加权惩罚的 w 损失。
训练 WGAN
训练 WGAN 时,鉴别器每步训练多次,而生成器每步训练一次。
结论
WGAN 导致稳定的训练,并解决了我们在 DCGAN 中面临的模式崩溃和消失梯度的问题。
但这一切都是有代价的,即 WGAN 在训练时比 DCGAN 慢。
你可以在这里找到这篇文章的完整代码。敬请关注即将发布的文章,我们将在 TensorFlow 2 中实现一些有条件和可控的 gan。
所以,本文到此结束。谢谢你的阅读,希望你喜欢并且能够理解我想要解释的内容。希望你阅读我即将发表的文章。哈里奥姆…🙏
参考
由 DeepLearning.AI 提供关于 GANs 生成对抗网络(GANs)是强大的机器学习模型…
www.coursera.org](https://www.coursera.org/specializations/generative-adversarial-networks-gans) [## Keras 文档:WGAN-GP 覆盖` Model.train_step ’
作者:A_K_Nain 创建日期:2020/05/9 最近修改时间:2020/05/9 内容简介:用 Wasserstein 实现甘…
keras.io](https://keras.io/examples/generative/wgan_gp/)
使用 Amazon SageMaker 进行深度需求预测
介绍
在本文中,我们探索如何使用深度学习方法,通过使用亚马逊 SageMaker 进行需求预测。
TL;DR :这个项目的代码可以在 GitHub 上获得,只需一次点击 AWS CloudFormation 模板就可以设置所需的堆栈。
什么是需求预测?
需求预测使用历史时间序列数据来帮助简化跨业务的供需决策过程。例子包括预测
- 下个月将在多个地点雇佣客户代表
- 下个季度跨多个地区的产品销售
- 视频流服务第二天的云服务器使用情况
- 下周多个地区的用电量
- 物联网设备和传感器等能源消耗
时间序列预测概述
任何用时间索引的数据都是时序数据。时间序列数据分为单变量和多变量。例如,单个家庭的总用电量是一段时间内的单变量时间序列。这是一个单变量时间序列的样子,一些预测用绿色表示
预测为绿色的单变量时间序列: GluonTS 教程
当多个单变量时间序列相互叠加时,称为多变量时间序列。例如,一个街区中 10 个不同(但相关)家庭的总用电量构成了一个多变量时间序列数据。这样的数据封装了更多的信息,比如在邻域内的相关性。因此,我们有可能利用这些共享的信息对每个家庭进行更好的预测。
时间序列预测的现状方法包括自回归方法,如
- 单变量时间序列数据的自回归综合移动平均 (ARIMA)
- 向量自回归 (VAR)用于多变量时间序列数据
这些经典方法的一个缺点是,它们需要在模型训练之前进行繁琐的数据预处理和特征工程,例如合并各种数据归一化、滞后、不同的时间尺度、一些分类数据、处理缺失值等。所有通常用平稳性假设。然而,深度学习(DL)模型可以自动执行这些步骤。此外,众所周知,在数据足够多的领域,如计算机视觉或自然语言处理中,DL 方法已经超过了经典方法,但是时间序列数据呢?
时间序列预测的深度学习
在时间序列预测中使用深度学习方法已经成为一个主要的研究点,特别是对于(平稳/非平稳)多变量时间序列数据。借助高度优化的专用框架,如 Apache MXNet 、 PyTorch 和 TensorFlow ,具备快速 GPU 支持的训练和推理能力。
研究表明,DL 方法优于前述经典方法 ARIMA 和 VAR,特别是在处理大量具有分类特征和缺失值的(相关)多变量时间序列数据时。一个原因是神经网络模型可以预测新事件的季节性,因为这些全局模型在整个数据集上共同学习模式*,并且可以更好地将学习到的规律外推至新系列。一种这样的方法是 LSTNet,来自用深度神经网络建模长期和短期时间模式。*
LSTNet 是如何工作的?
*LSTNet 是最先进的 DL 预测方法之一。 我们已经把它 贡献给了 GluonTS ,它目前是基于 MXNet Gluon API 。LSTNet 的优势在于它将传统的自回归线性模型与非线性神经网络部分并行结合。这使得非线性 DL 模型对于违反尺度变化的时间序列更加鲁棒。
以下是 LSTNet 架构,其中包含一个*
- 卷积为第一层,后面是
- 递归和跳跃递归层
- 结合非线性特征和线性特征的全连通层
图片取自 用深度神经网络 建模长期和短期时间模式
数据
在本次演示中,我们将使用多变量时间序列 电力消耗数据。可以通过 GluonTS 直接下载数据的干净版本。数据包含3211 小时频率的时间序列,其中
- 训练数据从2012–01–01 00:00:00开始,到2014–05–26 19:00:00结束
- 测试数据具有从2014–05–26 19:00:00到2014–05–27 19:00:00的附加数据
这是熊猫数据框架中标准化训练数据的快照
组件和架构概述
数据集存储在 S3 存储桶中。使用亚马逊 SageMaker 的项目有如下三个主要组成部分:
- 标准化数据的预处理步骤,设计为微服务来处理重型作业
- 训练一个 LSTNet 模型,并检查预测的指标,如 sMAPE
- (可选)部署并创建一个连接到 Amazon CloudWatch 进行监控的实时预测 HTTPS 端点
*这个完整的代码项目可以在 GitHub 中获得。遵循单键设置的说明。
以下是视觉架构指南:*
深度需求预测架构
使用 Amazon SageMaker MXNet Estimator 进行训练
因为我们使用 GluonTS,我们需要通过提供train.py
作为我们的入口点,使用 MXNet 估计器来训练我们的模型。例如,我们为context_length=12
的 1 个时期训练我们的模型,T1 是过去 12 小时电力消耗的训练窗口大小,以预测未来 6 小时prediction_length=6
的测试窗口大小。
*import logging
from sagemaker.mxnet import MXNetCONTEXT_LENGTH = 12
PREDICTION_LENGTH = 6hyperparameters = {
'context_length': CONTEXT_LENGTH,
'prediction_length': PREDICTION_LENGTH,
'skip_size': 4,
'ar_window': 4,
'channels': 72,
'scaling': False,
'output_activation': 'sigmoid',
'epochs': 1,
}estimator = MXNet(entry_point='train.py',
source_dir='deep_demand_forecast',
role=role,
train_instance_count=1,
train_instance_type='ml.p3.2xlarge',
framework_version="1.6.0",
py_version='py3',
hyperparameters=hyperparameters,
output_path=train_output,
code_location=code_location,
sagemaker_session=session,
container_log_level=logging.DEBUG,
)estimator.fit(train_data)*
韵律学
时序预测中最常见的评估指标之一是
- 对称平均绝对百分比误差 (sMAPE),用于量化模型预测不足或预测过度的程度,其中时间 t 的预测为英尺,时间 t 的实际值为的
图片取自 维基百科
When 可以直观地将其与另一个有用的指标进行比较,即平均绝对标度误差 (MASE),其值越接近零,通常预测就越好。我们使用牛郎星 Python 包来交互式地检查它们的关系。
最后,我们可以交互式地可视化预测与训练和测试数据。例如,以下是训练、测试和预测结果中前 10 个时间序列协变量的样本。
如您所见,在捕捉总体趋势方面,该模型在 1 个时期内表现相对较好。人们可以使用 Amazon SageMaker Python SDK 中的 HyperparameterTuner 来获得这些数据的最新结果。
部署端点
根据业务目标,例如在发电站设施中,当我们对模型离线运行的方式感到满意时,我们可以直接在 Amazon SageMaker 笔记本电脑中部署一个端点,如下所示:
***from sagemaker.mxnet import MXNetModelmodel = MXNetModel(model_data,
role,
entry_point='inference.py',
source_dir='deep_demand_forecast',
py_version='py3',
framework_version='1.6.0',
)predictor = model.deploy(instance_type='ml.m4.xlarge', initial_instance_count=1)***
之后,我们可以用一些request_data
点击端点,在一行代码中获得带有自动 JSON 序列化和反序列化特性的预测
***predictions = predictor.predict(request_data)***
结论
***感谢您通读这篇文章!
在这篇博客中,我们通过使用 Amazon SageMaker 进行预处理、训练、测试和部署,展示了深度学习模型如何用于需求预测应用。我们很想听听你的意见。如有任何问题、评论或反馈,请使用 GitHub 问题。***
承认
最后但同样重要的是,我要感谢 Vishaal Kapoor 、 Jonathan Chung 和 Adriana Simmons 在撰写本文时提供的宝贵反馈。
了解更多信息
亚马逊 SageMaker:https://docs.aws.amazon.com/sagemaker/index.html
用亚马逊 SageMaker 进行深度需求预测:https://github.com/awslabs/sagemaker-deep-demand-forecastGluonTS:https://arxiv.org/pdf/1906.05264.pdf和https://github.com/awslabs/gluon-tsLSTNet:https://arxiv.org/pdf/1703.07015.pdf
[1]: Dua,d .和 Graff,C. (2019)。 UCI 机器学习知识库 ,加州尔湾:加州大学信息与计算机科学学院
采用 TensorFlow 2.x 的深度确定性和双延迟深度确定性策略梯度
DDPG 和 TD3 的 TensorFlow 2.x 实施
摄影爱好在 Unsplash 上
在本文中,我们将使用 TensorFlow 2.x 实现深度确定性策略梯度和双延迟深度确定性策略梯度方法。我们不会深入研究理论,只会涵盖基本内容。在你继续学习之前,建议你先熟悉一下 DQN 和双 DQN。对于这篇文章,我将菲尔博士的 Td3 PyTorch 代码转换为 TensorFlow,对于 DDPG,我采用了他的目标网络更新方法。请参考他的 youtube 频道这里(编码 RL 的最佳 youtube 频道)。
DDPG:
DDPG 用于有连续活动空间的环境。DDPG 结合了 DQN 和演员评论家的方法。让我们试着用代码来理解。
网络:
- 我们的批评家网络将状态和行为作为输入,这些输入被连接在一起。
- 批评家网络输出特定状态下的行动值。
- 我们正在使用一个连续的环境,这就是我们使用 tanh 激活(输出值 b/w -1 和 1)的原因,输出是动作的长度,即在“LunarLanderContinuous-v2”中,一个动作被表示为一个数组[-1 1],所以这里的长度是 2。
代理类别和操作选择:
- 在 DDPG,我们有演员和评论家的目标网络,就像在 DQN 我们有目标网络一样。
- 请注意,我们已经编译了目标网络,因为我们不想在将权重从主网络复制到目标网络时出错。
- 我们还使用了重放缓冲区来存储体验。
- 对于动作选择,首先,我们将状态转换为张量,然后将其传递给 actor-network。
- 为了训练,我们在动作中添加了噪音,为了测试,我们不会添加任何噪音。
- 我们将剪切最大和最小动作值的动作 b/w 范围。
更新目标网络:
- 更新 ddpg 和 td3 中的目标网络使用软更新,即我们每次都会稍微更新权重。
- 网络可以按照研究报告中的解释进行更新。
图片经由https://arxiv.org/pdf/1509.02971.pdf
训练功能:
图片来自https://arxiv.org/pdf/1509.02971.pdf
- 首先,我们从重放缓冲区中抽取经验样本,并将它们转换成张量。
- 评论家损失的目标值是通过使用行动者的目标网络预测下一个状态的行动来计算的,然后使用这些行动,我们使用评论家的目标网络来获得下一个状态的值。
- 然后,我们应用贝尔曼方程计算目标值(target _ values = rewards+selfγ* target _ next _ state _ values * done)。请注意,在训练时,此处的“完成”存储为(1-完成)。
- 我们的预测值是从缓冲样本中提取状态和动作的主评价网络的输出。
- 然后根据目标值和预测值的 MSE 计算临界损失。
- 参与者损失被计算为批评家主要值的负值,输入作为主要参与者预测的行动。
- 然后,我们用 0.005 的 tau 更新我们的目标网络。
训练循环:
- 我们的训练循环很简单,即它在每个行动步骤中相互作用并储存经验和学习。
TD3PG:
TD3 受到双 DQN 的启发,解决了评论家值被高估的问题,与 DDPG 相比有以下变化。
- 除了他们的目标网络之外,使用两个主要的评论家网络。
- 延迟演员网络的更新。
- 动作噪音调节。
我们将只讨论 DDPG 代码的不同之处。
代理类别:
- 在代理课程中,我们有两个主要的评论家网络和他们各自的目标网络。
- 在动作选择中,我们在一些步骤之后停止向动作添加噪声。
训练功能:
- td3 列车功能与 DDPG 列车功能只有 3 处不同。
- 首先,通过添加噪声,然后在最大和最小动作的范围内裁剪动作,来自演员的目标网络的动作被规则化。
- 第二,下一状态值和当前状态值都是目标评论家和两个主要评论家网络。并且对于下一个状态值和当前状态值都考虑最少两个网络。
- 第三,在每 2 步之后训练演员网络。
所以,这都是关于实现上的差异。现在让我们看看训练结果。
DDPG vs TD3PG:
这两个图显示了在过去 100 集内,两种算法在“LunarLanderContinuous-v2”中达到平均分数 200 所拍摄的集。
由作者制作并通过 matplotlib 生成的图像
正如你所看到的,TD3 算法在 400 集的最后 100 集中得到了平均 200 英镑的奖励。而 DDPG 在 560 集之后只得了 100 分。
由作者制作并通过 matplotlib 生成的图像
实施时需要注意的事项:
在编写 RL 代码时,要记住以下几点。
- 神经元的数量、隐藏层数、学习速率对学习有巨大的影响。
- 张量和 NumPy 数组的形状应该是正确的。很多时候,实现是正确的,代码也是有效的,但是代理没有学到任何东西,只是因为张量的形状不正确,并且当对这些张量进行运算时,会给出错误的结果。
你可以在这里找到这篇文章的完整代码和这里。敬请关注即将发布的文章,我们将在 TensorFlow 2 中实现更多 RL 算法和深度学习算法。
所以,本文到此结束。谢谢你的阅读,希望你喜欢并且能够理解我想要解释的内容。希望你阅读我即将发表的文章。哈里奥姆…🙏
参考资料:
[## 具有深度强化学习的连续控制
我们将深度 Q 学习成功背后的思想应用于持续行动领域。我们提出一个…
arxiv.org](https://arxiv.org/abs/1509.02971) [## TD3:学习用人工智能跑步
学习构建强化学习中最强大和最先进的算法之一,TD3
towardsdatascience.com](/td3-learning-to-run-with-ai-40dfc512f93) [## 菲尔的机器学习
你好。在 Neuralnet.ai,我们涵盖了各种主题的人工智能教程,从强化…
www.youtube.com](https://www.youtube.com/channel/UC58v9cLitc8VaCjrcKyAbrw)
深度确定性政策梯度(DDPG):理论与实施
深度确定性策略梯度(DDPG)是一种结合了 Q 学习和策略梯度的强化学习技术。DDPG 作为一个演员兼评论家的技术包括两种模式:演员和评论家。执行元是一个策略网络,它将状态作为输入,输出精确的动作(连续的),而不是动作的概率分布。批评家是一个 Q 值网络,它将状态和行为作为输入,输出 Q 值。 DDPG 是一个“关”——政策法。DDPG 用于连续动作设置,而 DDPG 的“确定性”是指演员直接计算动作,而不是动作的概率分布。DDPG 被用在连续的动作场景中,是对普通演员兼评论家的改进。
有很多实现 DDPG 在线的库,但是它们有很大的开销,对于初学者来说不容易理解。我决定编写一个简单的 TF2 实现,涵盖 DDPG 方法的重要部分。
让我们深入研究这项技术的理论。
理论
在 DQN,通过对所有动作的 Q 值取 argmax 来采取最优动作。在 DDPG,演员是一个政策网络,正是这样做的。它直接输出动作(动作可以是连续的),绕过 argmax。
政策网络
车型
该策略是确定性的,因为它直接输出动作。为了促进探索,一些高斯噪声被添加到由策略确定的动作中。为了计算一个状态的 Q 值,执行器输出被馈入 Q 网络以计算 Q 值。这仅在计算 TD 误差期间进行,我们将在后面描述。
演员和评论家被拴在一起
为了稳定学习,我们为评论家和演员创建了目标网络。这些目标网络将基于主网络进行“软”更新。我们稍后将讨论这些更新。
损失函数
现在我们已经描述了模型架构,我们继续展示如何训练模型,或者更确切地说,两个模型的损失函数是什么。评论家(Q)和演员(mu)的损失函数是,
演员和评论家的损失
我们先分析行动者(政策网)损失。损耗就是这些状态的 Q 值之和。为了计算 Q 值,我们使用评论家网络并传递由演员网络计算的动作。我们希望最大化这个结果,因为我们希望获得最大的收益/Q 值。
临界损失是一个简单的 TD 误差,我们使用目标网络来计算下一个状态的 Q 值。我们需要最小化这个损失。为了向后传播误差,我们需要 Q 函数的导数。对于临界损失,Q 值的导数是直接的,因为μ被视为常数,然而,对于因子损失,μ函数包含在 Q 值内。为此,我们将使用链式法则,
演员损失链规则
我们现在有所有的损失和衍生品。
目标更新
为了在训练期间增加稳定性,我们包括目标评论家和演员网络,以在 TD 误差计算中计算下一状态的 Q 值。与主/当前网络相比,目标网络是延迟网络。基于主网络定期更新目标的权重。在 DQN,目标定期复制主网络权重,这被称为“硬更新”。在 DDPG,我们执行**“软更新”**,其中只有一小部分主要权重以下列方式转移,
目标网络更新 rle
τ是通常被选择为接近 1(例如 0.999)的参数。
有了这个理论,我们现在可以看看它的实现。
履行
型号
现在我们到了模型创建阶段。在这个实现中,我们将使用一个简单的健身房环境( Pendulum-v0 )。我们的演员和评论家网络将只由密集的层组成。我们提醒读者,行动者是以国家为输入的政策网络,其输出是行动。批评家将状态和动作作为输入,并输出状态-动作对的 Q 值。在评论家网络的最初 DDPG 论文中,动作在中间层进入网络,而不是从开始进入网络。这样做只是为了提高性能/稳定性,我们不会诉诸这种伎俩。对我们来说,行动和状态输入将从一开始就进入批评网络。我们编写一个函数来生成演员和评论家,
模型生成器功能
函数 ANN2 使用 input_shape 和 layer_size 参数生成评论家和演员网络。两个网络的隐藏层都有**【relu】激活。演员的输出层将是一个【tanh】**,(映射连续动作-1 到 1),评论家的输出层将是“无”作为其 Q 值。演员网络的输出可以通过一个因子来缩放,以使动作对应于环境动作范围。
模型初始化
我们初始化 4 个网络:主要演员和评论家以及目标演员和评论家,
模型初始化
重放缓冲器
与其他深度强化学习技术一样,DDPG 依赖于使用重放缓冲区来实现稳定性。重放缓冲区需要保持新旧体验的平衡。
简单的重放缓冲实现
训练
现在我们直接使用上面定义的损失函数来训练我们的网络。为了在 TF2 计算损耗和梯度,需要在 TF 中进行计算。GradientTape()块。TF2 建议对不同的网络使用不同的梯度带。我们训练的实施看起来像这样,
训练循环
让我们快速浏览一下这段代码。我们首先从重放缓冲区中取样。对于参与者,我们首先计算状态(X)上的动作,然后使用 critic 使用计算的动作和状态(X)来计算 Q 值。在反向传播过程中,critic 保持不变,因为我们只区分 wrt 因素变量。损失中的负号是存在的,因为在优化中我们希望最大化这个损失。
对于临界误差,我们使用目标网络来计算用于 TD 误差计算的 Q 目标。使用主评价网络计算当前状态(X) Q 值。在这个过程中,行动者保持不变。
车型更新
目标模型需要基于主模型进行更新。我们使用前面描述的等式更新它们,
这就完成了我们对 DDPG 方法的实施。
结果
我们在钟摆 v0 环境下运行 DDPG 100 集,得到如下回报。
培训回报
完整的代码实现可以在这里找到。
参考文献
- 深度强化学习的连续控制。
- DDPG 实现: Github
- 打开艾 DDPG
使用 Python 深入研究层次分析法
Clem Onojeghuo 在 Unsplash 拍摄的照片
对这种多标准决策方法的高度概述,以及一个使用案例。
前言
在一生中,一个人会做出许多决定,从几乎没有影响的最微不足道的决定,到会改变一生的决定。几乎总是,这些情况涉及 X 个选项和 Y 个判断标准。
示例 A
想象你在超市,你想买早餐麦片。你站在一排排的麦片前,不确定该买哪一种。你在找什么?
- 价格 :麦片不能太贵
- 口味 :可能是里面有巧克力的东西?
- 营养 :混合水果或燕麦的东西。
这些是您浏览产品时想到的一些标准。比方说,你拿起水果圈,磨砂片和幸运符。你在脑海中运行每一个标准,并将它们相互比较。然后你做了一个决定,把磨砂薄片放进你的购物车。
示例 B
你正在加纳一个小村庄的市政厅主持一个会议。作为水利项目代表团的负责人,您被分配到在村子里安装一系列水泵的任务。在你面前的是各种各样的利益相关者——村里的长者、地质学家和工程师。
在这次会议中,你将选择安装水泵的地点,并列出一系列标准—
- 地下水位: 该地点必须有相当高的地下水位;
- 人口 :附近必须有最小数量的人居住才能使装置有用;
- 费用 :运行材料和物资的费用必须在项目资金之内。
你与村里的长者、地质学家和工程师交谈,拟定了 15 个可能修建水泵的地点。经过多次讨论和权衡意见后,你将范围缩小到 5 个在选择标准列表中排名靠前的地方。
尽管这两个例子在影响范围和应用领域上有很大的不同,但问题是非常相似的——在面对多种、通常是相互冲突的标准时做出决定。
在这篇文章中,我将对层次分析法提供一个高层次的解释,这是解决这种多准则决策问题的一种可能的技术。在这个过程中,我还将向您展示如何用 Python 从头开始实现这项技术。
介绍
层次分析法是托马斯·萨蒂教授在 20 世纪 70 年代提出的一种多准则决策方法。
这是一种通过在数学框架内量化主观信念来帮助决策者做出明智决策的方法。
AHP 是关于不同数量的相对测量,是决策分析和运筹学领域的交叉点。
图 1—布鲁内利 2015 年[1]
AHP 在许多领域都很流行,从供应链到可持续系统、环境管理、投资组合选择等等。它之所以受欢迎,是因为它非常直观,允许决策者以透明的方式整理他们的主观信念。
该过程
层次分析法,本质上就是给不同的选项分配不同的权重,并对其进行汇总的过程。然而,美妙之处在于得出这些权重的方式,以及主观信念的量化。
让我向你们简单介绍一下 AHP 的高度直观的过程—
- **第一步:**定义流程的最终目标。在上面分享的例子中,目标分别是购买早餐麦片和选择合适的安装点;
- 第二步:列出你手头上实现目标的各种选择。这些选项被称为*‘备选方案’*。
- 第三步:列出你评估上述选择的不同标准。这些可能涉及标准的子级别,并且完全取决于您想要的详细程度,尤其是当选项彼此非常相似时。
- 第 4 步:从第 1 步到第 3 步建立层次结构。如果你熟悉图论,那么你可以想象这是一个有向无环图。每个节点之间的连接暗示了它们在评估中的考虑。
图 2——评估层级的示例[2]
- 步骤 5 :每一个标准和子标准的成对比较,以确定它们的权重。
- 步骤 6 :将每个备选方案与每个子标准进行成对比较,以确定其权重。
- 步骤 7 :对每个备选方案的所有这些权重(加权算术和)进行总体求和,并根据这个加权和对它们进行排序。
- 第八步:计算一致性比率。这是与临界值表相比,主观评估一致性的度量。如果发现不一致,请返回步骤 5。
所以从这些步骤中,你可以看到这个过程是如何得到它的名字的,以及为什么它在应用方面如此受欢迎。现在,让我们来看看这个过程的核心——主观信念的量化。
评估
AHP 的关键词是成对 比较。我们都知道一次比较三个以上的选项有多难。为了消除这一困难,Saaty 教授建议对备选方案/标准进行成对比较。这种比较/评估是通过指定代表不同重要程度的强度来完成的,这是他用语言学定义的[3]。
对于每个标准/子标准/目标[1],被评估/评定的备选方案被编译成一个 n x n 成对比较矩阵 A 。
这里, wi 和 wj 是上表中重要的权重或强度。您可以立即看到评估矩阵是对称的,这使得计算更加容易。
一旦创建了评估矩阵,下一步就是将其转换成向量。该向量对矩阵中存在的信息进行编码,并被称为优先级向量。
有几种方法可以计算这个优先级向量。一种方法是获得 Perron-Frobenius 特征向量[4],或者简单地获得矩阵的归一化特征向量。另一种方法是计算相应行上的元素的几何平均值除以归一化项,使得优先级向量的分量最终加起来为 1 [1]。这种方法是归一化特征向量方法的一种近似。
评估的最后一步是为每个子标准生成的优先级向量的加权算术和,并对它们进行排序以对备选方案进行排序。
一致性比率
层次分析法的基本假设是决策者是理性的。这基本上意味着决策者被假定为每次对相同的问题都应用相同的主观信念。然而,在现实中,情况可能并非如此。Saaty 教授通过提出一致性指数 CI 来解决这种不确定性
其中λ_ max是成对比较矩阵的最大特征值,并且 n 是备选方案的数量。
为了缩放不同大小的矩阵,开发了一致性比率 CR
其中, RI_n 是从足够大的一组大小为 n 的随机生成矩阵中获得的 CI 的平均估计值。Saaty 教授给出了 RI_n 的查找表,
如何使用 CR? —根据 Saaty 教授的说法,在实践中,应该接受 CR ≤ 0.1 的矩阵,拒绝大于 0.1 的值。CR = 0.1 的值基本上意味着这些判断有 10%的不一致性,就好像它们是随机给出的一样。通过选择较低的 CR,可以尝试减少这种不一致性,唯一的方法是返回并重新评估主观权重。
唷,这有很多理论,所以让我们继续用 Python 实现一个简单的用例
用 Python 实现层次分析法
据我所知,目前只有一个开发良好的 python 库用于 AHP — pyAHP,但是让我们使用前面描述的过程从头开始编写代码。这里,我将使用[1]中的一个典型用例来说明这个过程。(说实话,在 Excel 中实现相当容易!)
代码可以在我的 GitHub 仓库中找到
问题定义
假设你想去欧洲度假,你计划去几个有趣的城市。你心中有几个城市——马德里、汉堡和巴黎,但你的预算只允许你去其中的一个。为了帮助您获得最大的回报,您决定使用 AHP 来帮助您缩小合适城市的范围。
目标、标准和备选方案
总体目标显然是你个人的满意度。备选方案是{罗马、马德里、巴黎},让我们想象您选择以下标准来评估每个城市—{气候、观光、环境}。让我们建立等级制度-
图 3——用例的层次结构(图片由作者提供)
导入库
好了,让我们从导入两个库开始评估过程
import numpy as np
import pandas as pd
创建成对比较矩阵
我们利用了比较矩阵的对称性质,只接受上三角矩阵的输入。
# Number of options
n = 3# Creating default matrix of ones
A = np.ones([n,n])# Running a for loop to take input from user and populate the upper triangular elements
for i in range(0,n):
for j in range(0,n):
if i<j:
aij = input('How important is option{} over option{} ?: '.format(i,j))
A[i,j] = float(aij) #Upper triangular elements
A[j,i] = 1/float(aij) #Lower triangular elements
请记住,我们的标准集是{气候、观光、环境},因此选项 0 是气候,选项 1 是观光,选项 2 是环境。我们运行这段代码来为标准权重生成成对比较矩阵。
How important is option0 over option1 ?: 0.5
How important is option0 over option2 ?: 0.25
How important is option1 over option2 ?: 0.5
这可以解释为—
气候比观光机会重要两倍,比城市环境重要四倍。观光机会的重要性是城市环境的两倍
一旦生成矩阵,我们通过归一化最大特征值的特征向量来计算优先级向量。该特征向量中的元素是标准的权重。
e = np.linalg.eig(A)[1][:,0]
p = e/e.sum()>>> array([0.14285714, 0.28571429, 0.57142857])
这两段代码被组合成一个函数
def pairwise_matrix(n):A = np.ones([n,n])
for i in range(0,n):
for j in range(0,n):
if i<j:
aij = input('How important is option{} over option{} ?: '.format(i,j))
A[i,j] = float(aij)
A[j,i] = 1/float(aij)#Computing the priority vector
eig_val = np.linalg.eig(A)[0].max()
eig_vec = np.linalg.eig(A)[1][:,0]
p = eig_vec/eig_vec.sum()
return p, eig_val
我们称这个函数为生成成对比较矩阵和优先级向量,用于根据每个标准评估每个备选方案。记得我们的备选方案集是—{罗马、马德里、巴黎}。
每个矩阵的优先级向量是—
pr_c = pairwise_matrix(3)[0] #All Criteria
pr_c0 = pairwise_matrix(3)[0] #Criteria 0: Climate
pr_c1 = pairwise_matrix(3)[0] #Criteria 1: Sightseeing
pr_c2 = pairwise_matrix(3)[0] #Criteria 2: Environment#Priority Vector for Criteria 0 pr_c0
>>> array([0.44444444, 0.44444444, 0.11111111])#Priority Vector for Criteria 1 pr_c1
>>> array([0.6, 0.3, 0.1])#Priority Vector for Criteria 2pr_c2
>>> array([0.09090909, 0.18181818, 0.72727273])
我们还计算了每个比较矩阵的一致性比率。对于 n= 3,RI_n 应为 0.5247。所有矩阵的最大特征值是 3。因此,根据之前的公式,每个矩阵的 CR 将为 0,即< 0.1 and hence acceptable.
The final step is to get their weighted arithmetic sum to yield the rank vector
r = pr_c0*pr_c[0] + pr_c1*pr_c[1] + pr_c2*pr_c[2]
print(r)>>> [0.28686869 0.25310245 0.46002886]
The weighted arithmetic sum for 巴黎比罗马或马德里高得多,因此它被指定为 rank1,其次是罗马和马德里。
这就对了!在 AHP 的帮助下,你成功地将自己的主观分析量化,决定飞往 巴黎 !
结论
AHP 的主要缺陷是当由不同的一组人评估时,备选方案的排序颠倒了。另一个问题是将其纳入运筹学的哲学基础。
话虽如此,层次分析法仍然是一种流行的 MCDM 方法,并且相对容易实现和解释。除了 python 之外,还有一些商业软件,比如 SuperDecisions,可以帮助您创建层次结构并执行成对评估。
有更多的 MCDM 方法来弥补层次分析法的不足,并且在数学基础方面更先进。一些想到的是 PROMETHEE,托普西斯等。
参考
[1]布鲁内利,马特奥。2015.层次分析法简介。斯普林格在运筹学中的作用。第 83 页。978–3–319–12502–2(电子版)。
[2]https://en . Wikipedia . org/wiki/Analytic _ hierarchy _ process _ % E2 % 80% 93 _ car _ example
[3] T.L .萨蒂,用层次分析法进行决策。里面的《服务科学》2008 年第 1 卷第 1 期
[4]https://en . Wikipedia . org/wiki/Perron % E2 % 80% 93 Frobenius _ theorem
我希望这篇文章对你有所帮助,并感谢你的反馈!
再见!
深入探究自组织地图的竞争学习
互联网上无监督人工神经网络中自组织映射(SOMs)竞争学习背后的最佳解释!
自组织映射是最流行的无监督学习人工神经网络之一,其中系统没有关于输入数据的特征或特性以及输出数据的类别标签的先验知识。网络根据样本输入模式之间的相似性来学习形成样本输入模式的类别/聚类。集群中的模式具有相似的特征。关于什么特征对于分类是重要的,以及有多少类,没有先验知识。网络本身会针对不同类别的输入进行调整,正如其名称所示,它们会自我组织。加权层中的节点数量对应于不同类别的数量。它基于竞争学习。
自组织地图网络结构
什么是竞争学习?
在竞争学习中,与权重相关联的节点相互竞争以赢得输入模式(向量)。对于每个不同的输入模式,具有最高响应的节点被确定并被宣布为获胜者。仅训练与获胜节点相关联的权重,以使它们更类似于输入模式(向量)。所有其他节点的权重不变。赢家通吃,输家一无所有。所以它叫做赢家通吃算法(输家什么也得不到)。
节点的强度=加权和
为输出节点 1
Y1 = X1W11+ X2W21 + X3W31 +………+ XDWD1
每个节点与具有 D 个元素的权重向量相关联
输入向量X—【X1,X2,X3……】。,XD]
Y1 的权重向量——【W11,W21,W31,…。,WD1]
训练算法
- 估计类别数(输出节点数)
- 随机设置权重并归一化
- 应用标准化的输入向量 X
- 计算每个节点的强度(即加权和)
- 确定具有最高响应的节点 i
- 宣布节点 i 为‘获胜者’(I具有与 X 最相似的权重)
- 训练节点 i 的权重,使它们更加类似于 X
培训过程
培训期间:
- 获胜者的权重向量变得更加等于当前输入向量
- 换句话说,当前的输入向量被传递给胜利者
培训后:
- 获胜者携带它赢得的输入(获胜节点的权重向量现在保留它已被训练的输入模式)
- 任何类似于先前的连续输入选择该节点作为获胜者
大多数神经网络专家不知道训练过程背后的理论。据说在训练期间,获胜者的权重向量变得更等于当前输入向量。但是大多数人缺乏关于使权重向量等于输入向量的理论的知识。所以在这里我想用神经竞争的基础数学来解释这个理论。
标量和向量
数量
- 标量只有大小,如长度、面积、体积、速度、质量、密度、压力、温度
矢量
- 向量既有大小又有方向,例如位移、方向、速度、加速度、动量、力、重量
输入向量和权重向量的归一化
- 为了便于训练,输入向量和权重向量都被归一化为一个单位长度
- 标准化过程解释如下
考虑矢量
x =[X1 X2 X3……XD]
X 的范数=
正常化
- 矢量的范数被称为矢量的“强度”,即它的大小
- 归一化向量的范数是 1(单位向量)
- 即如果 X 是矢量
例如 X = [0.2,0.1,1.4,0.2];
标准化的
X = [0.1397 0.0698 0.9778 0.1397]
归一化的范数
x = 0((0.1397)2+(0.0698)2+0.9778)2+0.1397)2)= 1
正常化
标准化向量的元素介于 0 和 1 之间。当输入特征来自不同的尺度时,例如[1.2 0.001 10.6],归一化使它们达到统一的标准。当权重向量也被归一化时,训练过程变得简单。当所有输入模式被归一化为单位长度时,它们可以被表示为单位球体中的不同半径(不同方向)。
标准化为单位长度的输入模式,单位长度由单位球体中的半径表示
下图显示了单位球体中的归一化权重向量和该现有球体中表示的输入向量。
单位球中表示输入向量和权重向量
这里每个向量的长度= 1。
正常化前后
正常化前后
网络对训练集进行编码所需的是权重向量与该集中存在的任何聚类对齐。每个集群至少由一个节点表示。那么当一个向量被呈现给网络时,就会有一个节点,或者一组节点,对输入做出最大的响应。
两个向量的相似性
两个向量的相似性
- 如果 X1 = [x1,x2,x3,x4]且 Y1 = [y1,y2,y3,y4],则 X1 = Y1
惟一可能是
x1 = y1
x2 = y2
x3 = y3
x4 = y4
X1 和 Y1 被称为是“相同的”。
- 考虑向量 X 和 Y
点积 X.Y = |X||Y|。Cos q
|X|-向量长度
q——两个向量之间的夹角
如果|X| = 1 且|Y| = 1
X.Y = Cos q 和 0 <= Cos q <= 1
If q -> 0(那么 Cosq -> 1)
两个单位矢量重合
也就是说,两个向量(X 和 Y)的等于
即 X 与 Y 重合
训练两个向量使其相等的过程
X.Y = |X|。| Y | Cosq= 1.1 . Cosq
当 q - > 0 矢量 X =矢量 Y
所以我们改变两个向量之间的角度 q,以使两个归一化向量相等。
som 的培训
因此,在训练过程中,我们为给定的输入模式找到一个具有最高响应值的获胜节点。然后,使获胜者的权重向量更等于当前输入向量。根据上面的数学解释,我们在训练期间所做的是调整归一化输入向量和获胜节点的归一化权重向量之间的角度,直到这两个向量彼此一致。换句话说,直到两个矢量相等。
训练使得特定节点的权重类似于所施加的输入。换句话说,输入向量以其权重的形式被“转移”到获胜节点。当应用相似的输入向量时,相同获胜者的加权和将是最高的。
培训过程
类似地,对所有输入模式继续这一过程,直到输入向量与每个输入模式的获胜节点的权重向量一致。
训练方程——koho nen 学习规则
Kohonen 学习规则
我们可以使用 Kohonen 学习规则来验证这一数学解释,在 koho nen 学习规则中,仅对输出为 1 的获胜输出节点调整网络权重。否则,权重调整为零,因为输出为零。当输出为 1 时,通过使获胜节点的输入向量 X 和权重向量 W 彼此相等来调整权重。这是通过调整这两个向量之间的角度来实现的。当两个向量彼此一致时,网络被训练,并且不需要进一步的权重调整。对所有的输入模式继续这个过程,直到人工神经网络被完全训练。
最终想法
我希望这篇文章能帮助你理解无监督人工神经网络中自组织映射(SOMs)竞争学习背后的实际理论。写这篇文章的目的是与世界其他地方分享我的经验丰富的讲师的重要知识。这一切都要归功于我的大学高级讲师 H.L. Premaratne 博士,
- 神经网络和模式识别
- 图像处理和计算机视觉
这是根据他的要求写的,因为互联网上缺乏解释这一理论的文章。我希望你们都能从这方面的专家那里获得宝贵的知识。
谢谢大家!!!…
深入探究网飞的推荐系统
网飞如何通过个性化实现 80%的流时间
在 Unsplash 上由 Thibault Penin 拍摄的照片
在这个时代,网飞是大多数人的同义词,是电影和电视节目的首选流媒体服务。然而,大多数人不知道的是,网飞在 20 世纪 90 年代末开始采用订阅模式,将 DVD 邮寄到美国的家庭。
Netflix 奖
2000 年,网飞推出了个性化电影推荐,2006 年,推出了 **Netflix 奖、机器学习和数据挖掘竞赛,奖金为 100 万美元。当时,网飞使用了其专有的推荐系统cinema tech,该系统的均方根误差(RMSE)为 0.9525,并要求人们将这一基准提高 10%。一年后能够实现目标或接近目标的团队将获得奖金。
一年后,2007 年进步奖的获得者使用了矩阵分解(T10)和受限玻尔兹曼机器(T12)的线性组合,实现了 0.88 的 RMSE。在对源代码做了一些修改后,网飞将这些算法投入生产。值得注意的是,尽管一些团队在 2009 年实现了 0.8567 的 RMSE,但该公司并没有将这些算法投入生产,因为需要工程努力来获得边际精度增加。这为现实生活中的推荐系统提供了重要的一点——模型改进和工程努力之间总是存在积极的关系。
流媒体——新的消费方式
网飞没有采纳 Netflix 奖项的改进模式的一个更重要的原因是,它在 2007 年引入了流媒体。随着流媒体的出现,数据量急剧增加。它必须改变其推荐系统生成推荐和接收数据的方式。
快进到 2020 年,网飞已经从美国邮寄 DVD 的邮件服务转变为拥有 1.828 亿用户的全球流媒体服务。因此,它的推荐系统从预测收视率的回归问题转变为排名问题、页面生成问题、用户体验最大化问题(定义为最大化流媒体播放的小时数,即个性化所有可以个性化的内容)。本文旨在解决的主要问题是:
网飞用什么作为它的推荐系统?
网飞作为一个企业
网飞有一个基于订阅的模式。简单来说,网飞的会员越多,收入就越高。收入可以被视为三个因素的函数:
- 新用户获取率
- 取消率
- 前成员重新加入的比率
网飞的推荐系统有多重要?
80%的流时间是通过网飞的推荐系统实现的,这是一个非常令人印象深刻的数字。此外,网飞相信,创造一个用户体验,将寻求提高保留率,这反过来又转化为客户获取的节省(估计截至 2016 年每年 1B 美元)。
网飞推荐系统
网飞如何对头衔进行排名?
很明显,网飞利用了基于行的两级排名系统,排名发生在:
- 每行内(最强的建议在左边)
- 跨行(最强烈的建议在顶部)
来源:网飞科技博客
每行突出显示一个特定的主题(例如,前 10 名、趋势、恐怖等),并且通常使用一种算法来生成。每个成员的主页由大约 40 行多达 75 个项目组成,这取决于成员使用的设备。
为什么是行?
优势可以从两个角度来看——1)作为用户,当呈现一排相似的项目时,它更连贯,然后决定他或她是否有兴趣观看该类别中的某些内容;2)作为一家公司,收集反馈更容易,因为向右滚动一行表示感兴趣,而向下滚动(忽略该行)表示不感兴趣(不一定不相关)。
**有趣的事实:**你知道吗,艺术品也会根据你的个人资料和喜好而个性化?点击了解更多!
用的是什么算法?
网飞使用了其论文中提到的各种排名器,尽管每个模型的架构细节并没有具体说明。以下是它们的概要:
个性化视频排名(PVR) —这是一种通用算法,通常根据某种标准(例如暴力电视节目、美剧、爱情片等)并结合用户特征和受欢迎程度等次要特征来过滤目录。
PVR 生成项目的示例
Top-N Video Ranker——类似于 PVR,除了它只看排名的头部,看整个目录。这是优化使用的指标,看看目录排名的头部(如地图@K,NDCG)。
前 N 名排名生成标题的示例
趋势现在排名更靠前——这种算法捕捉了网飞推断为强预测因素的时间趋势。这些短期趋势可能从几分钟到几天不等。这些事件/趋势通常是:
- 具有季节性趋势并会重复发生的事件(如情人节导致浪漫视频消费上升)
- 一次性的短期事件(如冠状病毒或其他灾难,导致对相关纪录片的短期兴趣)
趋势 Now ranker 生成标题的示例
继续查看排名者 —该算法查看成员已经消费但尚未完成的项目,通常为:
- 情节性内容(如戏剧系列)
- 非情节性的内容,可以一点一点地消费(例如,完成一半的电影,独立于情节的连续剧,如《黑镜》)
该算法计算成员继续观看的概率,并包括其他上下文感知信号(例如,自观看以来经过的时间、放弃点、观看的设备等)。
继续观看排名器生成标题的示例
在 Justin Basilico [2]的演讲中,他介绍了 RNNs 在时间敏感序列预测中的应用,我认为这种算法中使用了 RNNs。他设计出,网飞可以利用特定成员过去的游戏以及上下文信息,并以此预测该成员的下一个游戏可能是什么。特别地,使用连续时间和离散时间上下文作为输入执行得最好。
来源:来自[2]的剪辑幻灯片
视频-视频相似性排名—也就是因为你看了(BYW)
该算法基本上类似于基于内容的过滤算法。根据成员消费的项目,该算法计算其他类似的项目(使用项目-项目相似性矩阵)并返回最相似的项目。在其他算法中,这一个是非个人化的,因为没有利用其他的边特征。然而,它是个性化的,在某种意义上说,它是一个有意识的选择,显示一个特定项目的类似项目,一个成员的主页(更多细节在下面的页面生成)。
BYW 生成标题的示例
行生成过程
上述每个算法都经历了下图所示的行生成过程。例如,如果 PVR 正在查看言情标题,它将找到符合该类型的候选,同时拿出证据来支持一行的呈现(例如,该成员先前观看过的言情电影)。根据我的理解,这种证据选择算法被合并(或一起使用)到上面列出的所有其他排序算法中,以创建一个更精确的项目列表排序(见下面网飞的模型工作流程图)。
这个证据选择算法 使用“所有【网飞】显示的信息都在页面的左上方,包括网飞奖上被重点关注的预测星级;大纲;显示的关于视频的其他事实,例如任何奖项、演员阵容或其他元数据;以及[网飞]用来在用户界面的行和其他地方支持[他们的]建议的图像。【1】”
五种算法中的每一种都经历了相同的行生成过程,如下图所示。
来源:网飞科技博客[3]
页面生成
在算法生成候选行(已经在每个行向量中排序)之后,网飞如何决定显示这 10,000 行中的哪一行呢?
网飞的工作流程模型
历史上,网飞一直使用基于模板的方法来解决页面生成的问题,即大量的行争夺宝贵的屏幕空间。这是一项不仅注重准确性,而且同时提供多样性、可访问性和稳定性的任务。其他考虑因素包括硬件能力(使用什么设备)以及哪些行/列在第一眼和滚动时是可见的。
这意味着网飞想要准确地预测用户在那个时段想看什么,但不要忘记他/她可能想继续看中途中断的视频。与此同时,它希望通过提供一些新鲜的东西来突出其目录的深度,并可能捕捉到成员所在地区正在发生的趋势。最后,当用户与网飞互动了一段时间,并习惯于以某种方式浏览页面时,稳定性是必要的。
有了所有这些要求,我们就可以理解为什么基于模板的方法一开始就能很好地工作,因为我们可以随时满足一些固定的标准。然而,在提供良好的会员体验方面,拥有许多这样的规则自然会使网飞处于局部最优状态。
那么我们如何处理这个行排序问题呢?
基于行的方法
基于行的方法使用现有的推荐或学习排序方法来对每行进行评分,并基于这些分数对它们进行排序。这种方法可能相对较快,但缺乏多样性。一个成员可能最终会看到一个满是符合他/她兴趣的行的页面,但是行与行之间可能非常相似。那么我们如何融合多样性呢?
分阶段进场
对行上升方法的一个改进是使用阶段式方法,其中每一行都像上面的方法一样评分。但是,从第一行开始按顺序选择行,每当选择一行时,都会重新计算下一行,以考虑它与前面的行以及已经为页面选择的前面的项目的关系。这是一个简单的贪婪的阶段式方法。
我们可以通过使用 k 行前瞻方法来改进这一点,在计算每行的得分时,我们考虑接下来的 k 行。然而,这两种方法都不能获得全局最优。
机器学习方法
网飞使用的解决方案和方法是一种机器学习方法,他们的目标是通过训练一个模型来创建一个评分函数,该模型使用他们为其成员创建的主页的历史信息,包括他们实际看到的内容,他们如何互动以及他们玩了什么。
当然,还有许多其他功能和方式可以为算法表示主页中的特定行。它可以简单到使用所有的项目元数据(作为嵌入)并聚合它们,或者按位置索引它们。不管用什么特性来表示页面,主要目标是生成假设的页面,并查看用户会与哪些项目进行交互。然后使用页面级度量进行评分,例如 Precision@m-by-n 和 Recall@m-by-n (它们是对 Precision@k 和 Recall@k 的改编,但是是在二维空间中)。
页面级指标(来源:学习个性化主页)
冷启动、部署和大数据
冷启动问题
古老的冷启动问题——网飞也有。传统上,网飞试图通过要求新成员填写一份调查来“启动”推荐,从而获得一些用户偏好信息来抑制这种行为[6]。如果跳过这一步,推荐引擎将会提供一组多样且受欢迎的标题。
此外,最近在这个新冠肺炎时期,网飞党(一个 Chrome 扩展)被创建,在我看来,这对于抑制这个冷启动问题有巨大的影响,因为这些数据可能会被送回网飞进行分析。
简单地说,网飞曾经是单人活动(至少是可以被网飞监控的)。你可以一个人在家或者和一群朋友一起看比赛,但是网飞不知道你和谁一起看比赛。有了网飞派对,网飞可能会创建一个你与谁互动过的图表,并可能会执行一种类似协同过滤的算法,为新用户做推荐。
这都是关于测试的
线下评价和线上评价的差距依然存在。虽然离线指标有助于评估我们的模型在训练数据上的表现,但不能保证这些结果会转化为用户体验的实际改善(即总观看时间)。因此,网飞团队建立了一个令人难以置信的高效 A/B 测试流程来快速测试他们构建的这些新算法。
请记住,A/B 测试本身是一门艺术,因为有许多变量需要考虑,包括如何选择控制和测试组,如何确定 A/B 测试是否具有统计意义(即,从整体上改善整体用户体验),选择控制/测试组大小,在 A/B 测试中使用什么指标,等等。
从根本上说,离线评估有助于网飞确定 何时 将模型投入 A/B 测试,以及 将哪些 模型投入 A/B 测试。你可以在这里阅读更多关于网飞的 A/B 测试实验过程。
数据,数据,数据和更多的数据
通过在线流媒体,网飞管理和访问的数据是无限的。只有采用正确的架构才能管理如此大量的数据,即分离离线在线 和 近线 计算。
使用离线计算,对数据量和算法计算复杂性的限制较少,因为它以批处理方式运行,具有宽松的定时要求。但是,它很容易在两次更新之间变得陈旧,因为最新的数据也没有并入。对于个性化架构,一个关键问题是以无缝的方式结合在线和离线计算。
通过在线计算,我们期望对最近的事件和用户交互做出响应,因此必须实时完成。因此,在线计算不能太复杂且计算成本高。此外,回退机制是必要的,例如恢复到预先计算的结果。
有了近线计算,我们在这两种方法之间找到了一个折中方案,它可以执行类似在线的计算,但不需要实时服务,允许它(计算和服务)异步。这为对每个事件进行更复杂的处理打开了大门,例如更新推荐以反映在成员开始观看电影后立即观看了该电影。这对增量学习算法很有用。
下图显示了网飞的详细建筑图。
来源:个性化和推荐的系统架构[5]
要深入了解这些组件是如何使用的,请阅读下面的博客文章。
结论
来源: UX 星球:Binging on the Algorithm
也就是说,是时候狂欢了——看男孩们!在新冠肺炎的艰难时期保持安全。感谢上帝给了网飞。
支持我! —如果你喜欢我的内容并且没有订阅 Medium,请考虑支持我并通过我的推荐链接在这里(注:你的一部分会员费将作为推荐费分摊给我)。
参考
[1] 网飞推荐系统
[2] 个性化的最新趋势:网飞的观点
[3] 学习个性化主页
[4] 一切都是为了测试:网飞实验平台
[6] 网飞的推荐系统如何运作