TowardsDataScience 博客中文翻译 2020(八十六)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

TensorFlow 2.x 的演员兼评论家[第 2 部分,共 2 部分]

原文:https://towardsdatascience.com/actor-critic-with-tensorflow-2-x-part-2of-2-b8ceb7e059db?source=collection_archive---------21-----------------------

使用 TensorFlow 2.x 实施有/无多个工作人员的 A2C

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

Josue Isai Ramos Figueroa 在 Unsplash 上的照片

本文是使用 TensorFlow 2.x 的演员-评论家系列的第二部分。在上一篇文章中,我们使用 TensorFlow 2.x 实现了朴素的演员-评论家方法,而在本文中,我们将实现有/无多个工作者的优势演员-评论家(A2C)方法。你可以参考我之前在这个系列的文章这里

最佳演员兼评论家(A2C):

让我们先来概述一下 A2C 算法,然后我们再来尝试理解代码。该算法的步骤如下。

没有多个工人:

  1. 代理玩 n 个时间步,并存储 n 个时间步的状态、动作、奖励
  2. 使用折现回报等式计算一个州的预期回报,即每个州的(R = r + Gamma*R)。
  3. 计算演员损失和评论家损失(我们将在代码部分考虑这一点)
  4. 每 n 步更新一次网络。 注意在本文中,为了简单起见,我们将在每集之后更新,n 取决于您使用的环境。
  5. 重复上述过程,直到收敛。

有多个工人:

  1. 多个工作人员与他们自己的独立环境进行交互,并存储他们的经验。
  2. 在每一集之后(或每 n 个时间步之后),像以前一样计算预期回报,然后将这些工人的经验叠加在一起,然后在每一集之后用这种叠加的经验训练网络。
  3. 重复这个过程,直到收敛。

代码(没有多个工人):

神经网络:

  1. 我们的网络与前一篇文章相似,但这次层数和神经元数不同,因为我使用的是 cart pole 环境。
  2. 你必须试验层数和神经元数以及学习率(在优化器中使用)。

代理初始化和操作选择:

  1. 这两个函数也是相同的,但这次学习率不同。
  2. 简而言之,我们使用 TensorFlow 概率库将概率转化为动作采样的分布。

现在让我们先来看看与环境的相互作用,以便更好地理解。

主训练循环:

  1. 代理与环境交互,并将状态、动作、奖励存储在它们的受关注列表中。
  2. 当这一集结束时,调用函数 preprocess1,它将上述列表作为状态、动作和每个状态的预期回报的输入和输出 NumPy 数组(类似于蒙特卡罗计算每个状态的预期回报)。
  3. 然后,代理的网络使用这些 NumPy 数组进行更新。

学习功能和损失:

所以,这有点不一样。让我们一步一步来理解。

  1. Learn 函数将状态、动作和来自状态的期望回报(这里写为 discnt_rewards)的 NumPy 数组作为输入。
  2. 演员预测每个状态下每个动作的概率。批评家预测每个州的价值。
  3. 时间上的差异被计算为来自状态的预期收益和由评论家预测的值之间的差异。
  4. 批评家损失以 MSE 计算,预期收益作为目标,预测值作为预测值。
  5. 演员损失一开始实现起来有些复杂,因为许多在线教程使用 TensorFlow 内置的SparseCategoricalCrossentropy,我发现它很抽象。这是一个简单的实现。
  6. 行动者损失是两种损失的组合,即政策损失和熵损失。保单损失是在该州采取行动的对数概率乘以该州的时间差的负数。熵损失是采取行动的概率乘以在该状态下采取行动的对数概率的负值。
  7. 损失的实现可能看起来很可怕,但这种实现的目的是网络预测的张量不能转换为 NumPy 数组,如果您转换 NumPy 数组中的值,您将得到一个错误,说明没有提供梯度。
  8. 因此,行动者损失函数将行动者、行动和时间差预测的行动概率张量作为输入。
  9. 第一个“for 循环”将每个预测转化为分布,因此我们可以获得在每个状态下采取行动的概率和对数概率。之所以需要“For 循环”,是因为我们可以在不将概率转换成数字数组的情况下,获得一个动作的概率。
  10. 然后我们计算损失。

训练图:

以下是最近 100 集 vs 集的剧情 b/w 平均奖励。

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

代码(有多个工人):

正如我们前面所讨论的,唯一不同的是多个工作人员与他们自己的环境副本进行交互。

要实现多员工 A2C,唯一需要的修改是在主培训循环中。

  1. 我们正在分别为状态、动作和预期奖励创建 3 个共享队列。并使用 python 多重处理库创建了 Barrier 实例和 lock 实例。
  2. 接下来,我们启动执行 runner 函数的 10 个进程。使用 join()我们可以确保每个进程都终止。

主训练循环:

  1. Runer 函数与环境交互,并像我们之前看到的那样将转换存储在列表中。
  2. 当一段情节为一个工作者完成时,它调用 preprocess1 函数,该函数执行与之前相同的任务,但这次它将状态、动作和预期回报放入它们各自的队列中(通过首先获取一个锁,以便没有其他工作者将其经验放入其他工作者的经验之间,然后在将他们的经验放入队列后释放该锁)。
  3. 我们只允许一个工人通过使用 Barrier 实例来提取经验和训练网络。
  4. 函数 preprocess2 从队列中检索这些体验,并将它们连接成一个用于状态的 NumPy 数组,一个用于操作,一个用于预期奖励。
  5. 然后网络被更新。最后一行 Barrier.wait()确保所有其他工作线程等待,直到所有工作线程都到达该点。

这就是关于编码的全部内容。现在让我们看看您的代理没有学习的原因和一些技巧。

实施时需要注意的事项:

在编写 RL 代码时,要记住以下几点。

  1. 神经元数量、隐藏层数、学习速率对学习有巨大的影响。
  2. 张量和 NumPy 数组的形状应该是正确的。很多时候,实现是正确的,代码也是有效的,但是代理没有学到任何东西,只是因为张量的形状不正确,并且当对这些张量进行运算时,会给出错误的结果。

你可以在这里找到这篇文章的完整代码和这里。敬请关注我们将在 TensorFlow 2 中实现 PPO 的后续文章。

所以,本文到此结束。谢谢你的阅读,希望你喜欢并且能够理解我想要解释的东西。希望你阅读我即将发表的文章。哈里奥姆…🙏

参考资料:

[## 直觉 RL:优势介绍-演员-评论家(A2C)

强化学习(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/)

亚当优化算法

原文:https://towardsdatascience.com/adam-optimization-algorithm-1cdc9b12724a?source=collection_archive---------11-----------------------

一种有效优化算法综述

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

图 1:Dmitry RatushnyUnsplash 上拍摄的照片

根据牛津词典的定义,优化是对一种情况或资源进行最佳或最有效利用的行为,或者简单地说,就是尽最大努力。通常,如果某样东西可以用数学建模,那么它很可能可以被优化。这在深度学习领域(老实说,可能是整个人工智能)发挥着至关重要的作用,因为你选择的优化算法可能会在几分钟、几小时或几天内,在某些情况下,几周、几个月或一年内获得高质量的结果。

在这篇文章中,你将学到:

  • 什么是亚当优化?
  • 在你的深度学习模型中使用 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 (点击我的名字可直接访问)。

进一步阅读:

有用视频:

AdapterHub:一个适配变压器的框架

原文:https://towardsdatascience.com/adapterhub-a-framework-for-adapting-transformers-a21d0ab202a0?source=collection_archive---------22-----------------------

没有更慢的微调:有效的迁移学习与拥抱脸变压器在 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 会议录。

数据科学中的问题解决

原文:https://towardsdatascience.com/adapting-in-data-science-dbbd6dfb3f93?source=collection_archive---------67-----------------------

做一个项目从来都不是直截了当的,这里有一些适应的策略

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

奥拉夫·阿伦斯·罗特内在 Unsplash 上的照片

“创造性解决问题”实际上是一个时髦词(时髦短语?)说到一个数据科学家应该具备的技能。然而,这不是一个你可以仅仅获得 Udacity 证书的技能(或者你可以,我不知道所有的课程)。你磨练这些技能的唯一方法就是做项目。上周我写了我最近的项目,一个针织图案推荐器。特别是,我写了创建基于内容的推荐器的一般过程。

提醒一下,基于内容的推荐系统采用某种形式的用户信息,将其与潜在候选人池进行比较,然后从候选人中选择最佳匹配。用户信息可以是用户当前正在查看的项目,也可以是用户喜欢或参与的所有内容的完整用户简档。

正如我也提到的,该项目是基于分析 Vidhya 的这篇文章。然而,我最终使用的过程与本文中介绍的过程并不完全相同。我不得不根据自己独特的问题来调整我的项目,以下是我用来解决问题的一些策略:

批判性地思考你需要的数据

我遇到的一个大问题是,我的数据集比文章中显示的 6 个数据点大得多。这意味着如果我想要一个高效流畅运行的程序,我需要找到一种方法来缩小数据集,只获取绝对必要的信息。在这篇文章中,作者使用了一个大数据集,其中既有未知文章,也有用户参与的文章。显然,当处理远远超过 100 个数据点时,如果您想要高效运行,这是不可行的。因此,我创建了一个仅包含用户信息的数据集,然后获取为用户配置文件生成的数字(决定一个人喜欢某个给定属性的程度的分数)、数据集的长度以及每个属性出现的次数。最后两个是为了帮助计算 tf-idf,因为我没有将整个用户数据集放入用于推荐模式的最终数据集中。

在足够的数据和过多的数据之间取得平衡

这在几个方面与我的最后一点非常相关。就像我说的,数据集越大,运行程序需要的时间就越多。如果我正在做一个项目,在那里我只是展示结果,我会希望得到尽可能多的干净的数据。然而,运行时间在这里是一个实际问题,人们不想等待几分钟的结果。因此,在我的程序中,我必须告诉它,如果用户在他们的收藏夹或他们的模式中有超过一定数量的模式,只取最近的 100 个左右。此外,我还遇到了一个问题,一些模式代码会抛出一个错误,这个错误会搞乱正在处理的整批模式。最初,我想出了一种方法来挑出问题儿童的个人模式,但最终我意识到这将花费太多时间。创建一个供人们使用的程序,不像一个你展示发现的项目,意味着你不能使用同样的细齿梳子。对于这样的项目,您必须在获取足够的数据以给出一个体面的结果和不获取太多数据以至于整个程序陷入困境之间找到平衡。

使用不同的测试用例

当测试一个程序时,你可能会倾向于只使用一个用户数据集,可能会做一些不同类型的搜索,然后说,“好的,很好。”然而,您可能会在不同的测试用例中遇到问题,而您不会在仅仅使用一个测试用例时遇到这些问题。一个明显的例子是,我意识到用户资料受到用户数据集大小的影响。本质上,如果轮廓更大,数字会更大,但这不一定意味着他们更喜欢某个属性。在那个问题上,我想到的解决方案是用数据集的长度来划分每个用户档案号。因此,它将反映相对于整个数据集,用户对给定属性的喜爱程度。通过这种方式,用户的数字不会仅仅因为他们在项目和收藏夹中使用或不使用 Ravelry 的数量而有所不同。如果我没有尝试几个不同的配置文件大小,我永远不会发现这个问题,人们可能会得到低匹配数,只是因为他们不是一个活跃的用户。

通过这个项目,我学到的最大的事情之一是,使用机器学习来创建一个程序,而不是使用它来调查项目的数据,需要稍微不同的优先级。也就是说,处理时间是更重要的优先事项,而彻底性则不是那么重要。当然,这并不是说你应该在数据处理上马虎大意。你只是没有用细齿梳和挑剔每一个小细节。特别是如果你是一个完美主义者或者是那种讨厌删除大量列或行的人,这可能是一个困难的转变。我遇到的几个主要问题通过确定我需要的确切信息得到了解决,因此我不会一次性处理一个巨大的数据集,确定如何编辑我的数据以确保有效的程序,并使用不同的测试案例来诊断任何可能的问题,这些问题只会在非常具体的情况下出现。遇到这种问题可能很困难,但至少对我来说,解决这种问题是数据科学如此有趣的原因。

股票市场预测中的自适应滤波:一种不同的方法

原文:https://towardsdatascience.com/adaptive-filtering-in-stock-market-prediction-2db9ad7ae7f9?source=collection_archive---------26-----------------------

用 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

原文:https://towardsdatascience.com/adaptive-learning-rate-adagrad-and-rmsprop-46a7d547d244?source=collection_archive---------29-----------------------

在我之前的文章中,我们看到了学习率(η)如何影响收敛。将学习率设置得太高会导致最小值附近的振荡,而设置得太低会减慢收敛速度。梯度下降中的学习速率(η)及其变化(如动量)是一个超参数,需要针对所有特征手动调整。

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

作者图片

当我们使用上述等式来更新神经网络中的权重时

  1. 所有功能的学习速度都是一样的
  2. 学习率在成本空间的所有地方都是一样的

恒定学习率对收敛的影响

假设,我们试图预测一部电影的成功/评级。我们假设有成千上万个特征,其中一个是“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) 的对角元素。

结论

学习率是一个重要的超参数,必须针对输入空间中的每个特征进行优化调整,以实现更好的收敛。通过采用自适应学习速率方法,如 AdaGradRMSprop,,我们让这些优化器通过学习底层数据的特征来调整学习速率。这些优化器给频繁出现的特征以低学习率,给不频繁出现的特征以高学习率,从而收敛得更快。

Python 中的自适应移动平均。

原文:https://towardsdatascience.com/adaptive-moving-average-in-python-56c98a4de7fd?source=collection_archive---------13-----------------------

呈现一个强有力的趋势指示器。

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

均线是检测趋势变化的最简单也是最有效的工具之一。它们也被用来建立基于交叉的交易策略。几乎每个交易者都使用它们,并把它们纳入自己的决策过程。在本文中,我们将浏览基本的已知移动平均线,然后介绍稍微复杂一点的 Kaufman Adapative 移动平均线——KAMA。

我刚刚出版了一本新书《成功后的 新技术指标》中的 Python 。它对复杂的交易策略进行了更完整的描述和补充,Github 页面致力于不断更新代码。如果你对此感兴趣,请随时访问下面的链接,或者如果你喜欢购买 PDF 版本,你可以在 Linkedin 上联系我。

[## 交易策略之书

亚马逊网站:交易策略之书:9798532885707: Kaabar,Sofien:书籍

www.amazon.com](https://www.amazon.com/gp/product/B09919GQ22/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=B09919GQ22&linkCode=as2&tag=sofien-20&linkId=bc5df3f6ab0f3af2df79641c56b949ba)

普通移动平均线

三种最常见的移动平均线是:

  • 简单移动平均线。
  • 指数移动平均线。
  • 平滑移动平均线。

在我们进入 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 中的新技术指标

亚马逊网站:Python 中的新技术指标:9798711128861: Kaabar,Sofien 先生:书籍

www.amazon.com](https://www.amazon.com/gp/product/B08WZL1PNL/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=B08WZL1PNL&linkCode=as2&tag=sofien-20&linkId=e3cb9716bb6a07cf6c8b9fb585412b07) 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

欧元兑美元每日时间跨度,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 下的自适应配对交易——一种强化学习方法

原文:https://towardsdatascience.com/adaptive-pair-trading-under-covid-19-a-reinforcement-learning-approach-ff17e6a8f0d6?source=collection_archive---------34-----------------------

人工智能资本管理研究系列文章

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

M. B. M.Unsplash 上拍摄的照片

摘要

这是 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 向您的仪表盘添加动画图表

原文:https://towardsdatascience.com/add-animated-charts-to-your-dashboards-with-streamlit-python-f41863f1ef7c?source=collection_archive---------17-----------------------

利用 ATP 网球排名数据对比网球四大

介绍

有段时间一直想试用。所以上周末,我花了一些时间修补它。如果您以前从未听说过这个工具,它提供了一种非常友好的方式来使用 Python 为您的数据科学和机器学习项目创建自定义的交互式数据 web 应用程序。您可以与用户交互以获得输入并显示动态图表、表格、地图等。他们的 官方画廊 可能是一个好的开始。它将让您了解使用 Streamlit 可以实现什么。您还会发现一长串来自 Streamlit 社区的推文,它们以自己独特的方式利用该工具进行创作。一定要看看它们,寻找一些灵感。可以使用 pip install 命令( pip install Streamlit )下载 streamlit。

在本文中,我分享了一个使用 Streamlit 构建的动画条形图示例。虽然,实现这一点的一些信息是零零碎碎的,但我无法在一个地方找到太多关于动画图表的信息。我希望这将有助于那些希望在他们的 Streamlit 仪表板中添加动画图表的人。

数据集

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

Carlo BazzoUnsplash 上拍摄

稍微说一下数据吧。网球是我最喜欢的运动,我决定围绕它做点什么(也因为我真的真的很想念温布尔登💔).总之,在网上搜索了一段时间后,我偶然发现了一些我认为可以使用的东西。直到 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 的简单性印象深刻。使用任何其他工具来实现这一点肯定会花费我更多的时间。如果你想创建一个动画图表,我希望这篇文章能帮你节省一些时间。

鉴于它最近得到越来越多的支持,我相信他们会增加很多其他有用的功能。感谢您的阅读,并祝您未来一周过得愉快!

* [## 用 Python 生成 5 行二维码

也许在你的简历中使用它来链接到你的网站或 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 学术网站

原文:https://towardsdatascience.com/add-animations-to-your-hugo-academic-site-easily-6aae61b52bd7?source=collection_archive---------43-----------------------

使用 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.mddemo.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-diveducation-div。但值得注意的是,我们希望等到我们的内容从网页的任何一边滑入之后,才淡入这些 div。因此,我们将再次使用animation-delay属性。因为我们的滑入动画需要一秒钟才能完成,所以我们可以在一秒钟的延迟后开始淡入动画。为了使过渡在视觉上更吸引人,我们也可以错开它们,这样education-divinterests-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***

为家庭监控摄像机系统添加基于云的深度学习对象检测功能

原文:https://towardsdatascience.com/adding-cloud-based-deep-learning-object-detection-capability-to-home-surveillance-camera-systems-df797a0dd6f?source=collection_archive---------41-----------------------

从 Jupyter 到无服务器 Web 应用的实用深度学习

我最近在我的房子周围安装了一个配备了四个摄像头和一个网络录像机(NVR)的监控系统。不幸的是,几乎所有的假警报都是由移动的植物或树影或松鼠触发的。这些警报都不能被系统自带的传统图像处理功能过滤掉。

像大多数深度学习实践者一样,我知道对象检测程序可以过滤掉这些错误警报。但它们要么需要一份昂贵的商业合同,要么需要一台连接我家庭网络的电脑。因为我想保持低成本,拥有一台电脑似乎是正确的选择。然而,这仍然是一笔相当大的初始资本投资,外加经常性的 24/7 电力成本。计算机还需要安装、维护和货架空间。它的风扇噪音或壁橱散热是另一个我不喜欢在家里处理的废话。

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

大多数假警报只是由移动的树荫和植物触发的。使用传统的图像处理技术,例如调整对比度阈值或设置活动区域,无法滤除这些错误警报

经过进一步研究,我发现使用无服务器 web APIs 是最好的解决方案。它不仅反应迅速,而且根据使用情况收取很少的费用。我还想自己优化深度学习算法,或者为高级深度学习应用重新配置实现。因此,我选择了运行在 AWS 上的 MXNet。这种结合允许使用 Jupyter 进行简单的深度学习代码开发,优化的库性能,丰富的预训练模型,以及强大的开放云基础设施。

以下是我的实现方式。明确地说,我的目标是保持低成本,同时能够使用我首选的对象检测算法。例如,我选择不上传整个视频,然后使用视频识别算法。它会在网络带宽、内存、CPU 和云中存储方面花费更多。

  1. 使用系统自带的传统图像处理技术,尽可能减少误报警事件。例如,我屏蔽了花园中的动作,因此只有楼梯上的动作才能触发事件。
  2. 一旦事件被触发,就会生成一个视频并存储在 NVR 中。对于我的应用程序来说,大多数视频都在 5 到 20 秒之间。然后视频在本地被处理以生成一些照片,比如说每 10 秒一张照片。
  3. 这些照片然后被发送到 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. 预先训练的模型可以识别数百个物体。对于家庭安全,只有人和车是特别感兴趣的。神经网络的复杂性可以显著降低,从而只关注这两个类别,以节省处理成本并缩短执行等待时间。
  2. 显然可以上传视频进行复杂的深度学习视频识别。
  3. 分析结果可以存储在数据库中以保存记录。
  4. 如果检测到人或车,发送短信。

通过几个简单的步骤,您可以将现成的监控摄像机系统升级到尖端的深度学习功能,同时保持低成本。

参考资料:

[1] Anders Christiansen,将机器学习模型部署为无服务器 API,将机器学习模型部署为无服务器 API(2020),AWS 机器学习博客

[2] Boris Ivanovic 和 Zoran Ivanovic,如何用 AWS Lambda 和 Tensorflow 部署深度学习模型 (2017),AWS 机器学习博客

为 Julia 向我的图形库添加颜色和特性(第 5 部分)

原文:https://towardsdatascience.com/adding-color-and-features-to-my-graphing-library-for-julia-part-5-15426b00dcaf?source=collection_archive---------68-----------------------

向我的图形库添加一些非常棒的新功能!

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

第 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 仍然需要解析代码。此外,我不认为任何人应该担心绘图模块中的漏洞,它可能主要用于笔记本电脑内部。这很容易添加,只需修改分散函数的参数,在坐标解析之前将其包含在表达式中:

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

轻松点。

结论

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

向我的模块化图形库添加控件

原文:https://towardsdatascience.com/adding-control-to-my-modular-graphing-library-2c5424a8d3b7?source=collection_archive---------61-----------------------

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 分支:

[## emmettgb/Hone.jl

模块化的形状,网格和线条容易预制快速绘图简单和轻型车床集成(即将推出)…

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 编程一个扩展。

给五星评论添加误差线:贝叶斯方法

原文:https://towardsdatascience.com/adding-error-bars-to-5-star-reviews-a-bayesian-approach-d6fef78b3382?source=collection_archive---------56-----------------------

使用 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_ratingcolor

酷!现在,假设菜单上有三种不同类型的袜子:蓝色、橙色和红色。

我对这些项目的真实评分为 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 部分)

原文:https://towardsdatascience.com/adding-julias-polymorphic-dispatch-to-my-plotting-library-part-4-1446e924774f?source=collection_archive---------62-----------------------

方法论之争!

第一部分

第二部

第三部

笔记本

在之前的文章中,我创建了一个坐标解析器和一个功能上面向对象的(我意识到这听起来有多疯狂)系统,用于将元数据从对象传输到最终的对象,看起来有点像这样:

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

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

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

相对于:

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

但做完这些出口后,一个想法闪过我的脑海。显然我们可以画出一个 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:

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

模块化的形状,网格和线条容易预制快速绘图简单和轻型车床集成(即将推出)…

github.com](https://github.com/emmettgb/Hone.jl)

感谢阅读!

向我的图形库添加线图

原文:https://towardsdatascience.com/adding-line-graphs-to-my-graphing-library-eb6447a0c726?source=collection_archive---------60-----------------------

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 的其他功能中实现。

为您的代码添加安全性

原文:https://towardsdatascience.com/adding-security-to-your-code-1378ff123240?source=collection_archive---------21-----------------------

这比你想象的要简单

我经常听到的一句话是“安全是每个人的责任”,但我注意到数据科学家经常过于关注他们需要知道的大量技能,以至于忽略了安全。除了有许多职责之外,我认为安全性似乎令人生畏,并且似乎需要大量的软件工程技能。实际上,在你的软件中实现最低级别的安全性是相当容易的。我建议遵循 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 管道,高安全性和高质量的代码就更容易开发。希望这能让你开始提高代码的安全性!

给熊猫添加样式(只用了几行代码!)

原文:https://towardsdatascience.com/adding-style-to-pandas-in-just-a-few-lines-of-code-be942f65b3a5?source=collection_archive---------14-----------------------

制作你的数据框架(很多!!)更漂亮

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

让我们给我们的熊猫数据框添加一些风格吧!资料来源:Nik Piepenbreier

Pandas 是 Python 中数据分析的典型工具,但让数据看起来像样并不总是最容易的。为此,许多分析师在与我们更广泛的受众分享数据之前,仍然求助于 Excel 来添加数据样式(如货币)或条件格式。在这篇文章中,我们将探索如何利用 Excel 中常见的这些特性,并演示如何使用熊猫风格的 API 来利用这些特性!

我们为什么要设计数据的样式?

我们的最终目标应该是让读者更容易理解数据,同时保持数据框架中底层数据的可用性。例如,10%可能比值 0.10 更容易理解,但保持 0.10 的比例对于进一步分析更有用。

什么是熊猫风格 API?

熊猫在 2019 年开发了造型 API,自那以来一直在积极开发。API 返回一个新的 Styler 对象,它有一些有用的方法来对数据帧应用格式和样式。最终的样式是用 CSS 完成的,通过样式函数,通过属性:值对应用于标量、序列或整个数据帧。

Styler 对象有两个关键方法:

  1. Styler.applymap —将样式应用于元素
  2. 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

我们可以看到,数据立即更容易理解!

字符串格式可以以不同的方式应用。其他一些例子包括:

  • 带两位小数的浮点数:{:.2f}
  • 用零填充数字:{:0>2d}
  • 带两位小数的百分比:{:.2%}

如果我们想为多列传递格式,定义一个可以传递给样式函数的字典可能更容易。例如,我们可以编写一本字典,如下所示:

然后可以传递到如下所示的对象上:

添加条件格式

在 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值