TowardsDataScience-博客中文翻译-2016-2018-三十一-

news/2024/10/13 15:22:42

TowardsDataScience 博客中文翻译 2016~2018(三十一)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

主成分分析:你的教程和代码

原文:https://towardsdatascience.com/principal-component-analysis-your-tutorial-and-code-9719d3d3f376?source=collection_archive---------5-----------------------

想获得灵感?快来加入我的 超级行情快讯 。😎

你的数据是你的机器学习模型的生命燃料。总是有许多 ML 技术可供选择并应用于特定的问题,但是没有大量的好数据,你不会走得很远。在机器学习应用程序中,数据通常是大多数性能提升背后的驱动因素。

有时这些数据可能很复杂。你拥有太多,以至于理解它的全部含义以及哪些部分是真正重要的可能很有挑战性。简而言之,降维是一种帮助我们从宏观层面更好地理解数据的技术。它减少了数据集的特征数量,这样我们只剩下最重要的部分。

主成分分析(PCA)是一种简单而强大的降维技术。通过它,我们可以直接减少特征变量的数量,从而缩小重要特征的范围并节省计算量。从高层次来看,PCA 有三个主要步骤:

(1)计算数据的协方差矩阵

(2)计算该协方差矩阵的特征值和向量

(3)使用特征值和向量只选择最重要的特征向量,然后将数据转换到这些向量上以减少维数!

整个过程如上图所示,其中我们的数据已经从 1000 个点的三维空间转换到 100 个点的二维空间。这在计算上节省了 10 倍!

(1)计算协方差矩阵

PCA 产生一个特征子空间,该特征子空间使沿着特征向量的方差最大化。因此,为了适当地测量这些特征向量的方差,它们必须被适当地平衡。为了实现这一点,我们首先归一化我们的数据,使其具有零均值和单位方差,这样在我们的计算中每个特征将被同等地加权。假设我们的数据集叫做 X :

两个变量的协方差衡量它们的“相关”程度。如果两个变量有一个正的协方差,那么当一个变量增加时,另一个也增加;对于负协方差,特征变量的值将在相反的方向上变化。协方差矩阵只是一个数组,其中每个值基于矩阵中的 x-y 位置指定两个特征变量之间的协方差。公式是:

其中顶部有线的 x 是 x 的每个特征的平均值向量。请注意,当我们将转置矩阵乘以原始矩阵时,我们最终会将每个数据点的每个特征相乘!在 numpy 代码中,它看起来像这样:

(2)计算特征值和向量

我们的协方差矩阵的本征向量(主分量)表示新特征空间的向量方向,本征值表示这些向量的幅度。因为我们在看我们的协方差矩阵,特征值量化每个向量的贡献方差。

如果一个特征向量具有一个相应的高量值的特征值,这意味着我们的数据在特征空间中沿着该向量具有高方差。因此,这个向量包含了我们数据的大量信息,因为沿着这个向量的任何移动都会导致很大的“差异”。另一方面,具有小特征值的向量具有低方差,因此当沿着该向量移动时,我们的数据不会变化很大。因为当沿着特定的特征向量移动时没有什么变化,即改变该特征向量的值不会对我们的数据产生很大影响,所以我们可以说该特征不是很重要,并且我们可以移除它。

这就是 PCA 中特征值和向量的全部本质。找出在表示我们的数据时最重要的向量,并丢弃其余的。在 numpy 中,计算我们的协方差矩阵的特征向量和值是一个简单的一行程序。之后,我们将根据特征值对特征向量进行降序排序。

(3)到新向量的投影

在这一点上,我们有一个特征向量列表,根据它们的特征值按照对数据集的“重要性”排序。现在我们要做的是选择我们需要的最重要的特征向量,并丢弃其余的。我们可以通过查看向量的解释的方差百分比来以一种聪明的方式做到这一点。这个百分比量化了有多少信息(方差)可以归因于总的 100%中的每个主成分。

我们举个例子来说明。假设我们有一个数据集,它最初有 10 个特征向量。计算协方差矩阵后,我们发现特征值为:

[12, 10, 8, 7, 5, 1, 0.1, 0.03, 0.005, 0.0009]

这个数组的总和= 43.1359。但是第一个6值代表:

42 / 43.1359 =总数的 99.68%!这意味着我们的前 5 个特征向量有效地保存了关于我们数据集的 99.68%的方差信息。因此,我们可以丢弃最后 4 个特征向量,因为它们只包含 0.32%的信息,这对于节省 40%的计算来说是值得的牺牲!

因此,我们可以简单地定义一个阈值,根据该阈值我们可以决定是保留还是丢弃每个特征向量。在下面的代码中,我们简单地根据所选的 97%的阈值来计算我们想要保留的特征向量的数量。

最后一步是将我们的数据实际投影到我们决定保留的向量上。我们通过构建一个投影矩阵来做到这一点:这只是一个矩阵的花哨词,我们将乘以它来将我们的数据投影到新的向量上。为了创建它,我们简单地连接所有我们决定保留的特征向量。我们的最后一步是简单地取原始数据和投影矩阵之间的点积。

瞧啊。尺寸缩小!

喜欢学习?

在推特上关注我,我会在那里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上与我联系

人工智能和机器学习原理

原文:https://towardsdatascience.com/principles-of-artificial-intelligence-machine-learning-122be27d33a4?source=collection_archive---------2-----------------------

自从我在谷歌工作以来,人工智能一直吸引着我,从检测谷歌云上的欺诈到预测 YouTube Red 上的用户保留率。为了拓宽我的专业经验,我加入了百度风投,成为其第一个夏季投资助理,与才华横溢的创始人一起创建人工智能创业公司。

现在在宾夕法尼亚大学沃顿商学院,我正在寻找机会结识有着有趣的人工智能相关想法的人,并了解人工智能生态系统内的最新创新。在商学院的头两个月,我联系到了尼古拉斯·林德,他是沃顿商学院二年级的 MBA 学生,在 IBM Watson 实习,担任数据科学家。我们立即意识到我们对人工智能的共同热情,为我们的同学制作了一份关于人工智能和机器学习(ML)的午餐和学习。

利用以下资料,我们试图:

  • 定义人工智能并描述其在商业中的应用
  • 解码“深度学习”和“认知计算”等流行语
  • 强调 AI / ML 中使用的分析技术和最佳实践
  • 最终,培养未来的人工智能领导者

午餐学习很受欢迎。当它变得明显,这是手头的话题,而不是吸引了大量观众的免费比萨饼,我惊讶于兴趣的程度。令人欣慰的是,听到同学们有兴趣了解更多关于该技术及其在解决日常业务挑战方面的实际应用。尼克和我现在正在建立一个基础,使这些研讨会成为一项持续的努力,以便工程、设计和宾夕法尼亚大学各学院的更多人能够从中受益。

沃顿商学院注重量化的严谨性,这已经让我觉得它非常适合我。在未来的两年里,我期待着与志同道合的人接触,无论是在课堂上还是在课堂外,与同龄人分享我关于 AI 的知识,并反过来向他们学习。通过共同努力扩大宾夕法尼亚大学在这一新领域的影响力和声誉,我相信我们都能成长为下一代领导者,在人工智能时代推动公司前进。

我很想听听你的想法。如果你觉得这篇文章或这些资料有用,请把它们推荐给你的朋友和同事!

确定数据科学工作的优先顺序

原文:https://towardsdatascience.com/prioritizing-data-science-work-936b3765fd45?source=collection_archive---------5-----------------------

在你能做的许多事情中做出选择

作为一名试图支持一个组织的数据科学家,您必须不断地决定您应该从事什么任务。您可能正在管理各种任务,例如:

  • 直接来自利益相关者的任务,比如为明天的大型会议制作一段时间内的销售图表,
  • 你个人认为具有长期效益的想法,比如制作一个 CLV 模型来预测高价值客户,以及
  • 来自其他业务部门的模糊任务,比如帮助确定为什么某个地区的客户保持率似乎下降了。

很难平衡什么是最重要的事情,什么可以放在次要位置,尤其是当你有很多人要求你分析的时候。通常,人们认为对他们非常重要的工作对整个企业来说可能并不重要。与提出数据科学请求的人相比,你通常是一名资历较浅的员工,这使得直截了当地说不变得更加复杂,即使你不容易做到这一点。所有这些创造了一个环境,在这个环境中,你做什么的决定会极大地影响业务,但你也会在选择什么方面受到限制。

这是我个人在职业生涯中纠结过的话题。当公司里的人带着关于数据的问题来找我时,我几乎总是想回答他们,不让他们失望。通常我认为这些请求很有趣!然而,试图满足每一个要求是不可持续的,因为对答案的要求是无止境的。此外,用数据回答一个问题通常会引出新的问题,因此满足请求通常会产生额外的工作,而不是减少剩余的工作量。

我逐渐意识到,在考虑进行可能的分析时,我首先要回答两个问题:

  1. 知道这个分析结果对公司有实质性影响吗?而且,
  2. 这项创新工作是否为企业带来了新的东西?

对这两个问题的回答产生了四种截然不同的工作类型:

我们都希望我们正在做的事情(创新且有影响力)😊

理想的项目是既创新又改变业务的项目。一个示例项目是创建一个客户流失模型,为赢回客户的营销工作提供动力。这是那种首先让人们进入数据科学的工作。不幸的是,没有多少项目属于这一类——只是很难找到你能真正改变一个企业的开创性地方。如果你发现一个属于这一类的项目,尽你所能让它启动。

提供证据(不创新,但有影响力)🙂

这些项目并不创新,但却改变了业务,所以从定义上来说,做这些工作是有价值的。这通常意味着为每个人都怀疑是真的事情提供证据——这不是特别创新,但会有所帮助。例如,企业中的人可能会怀疑特定人群的客户不太可能再次光顾。没有证据证明这些预感是正确的,人们就不愿意尝试解决营销问题。如果你能做一些分析表明假设是正确的,你就能帮助企业找到解决方案。这不是迷人的工作,向人们展示他们已经认为是真实的东西不是特别令人惊叹,但它仍然是有用的。如果你得到这样的工作,试着去做。

象牙塔(创新但没有影响力)🤨

这是创新的工作,但对业务没有用处,这可能是一笔巨大的沉没成本。这些项目通常来自数据科学团队内部,当人们对基于方法论上有趣的事物的建模或分析的新领域有想法时。一个示例项目是尝试使用机器学习来细分客户,而不知道您将使用这些细分做什么。如果没有一个来自数据团队之外的对项目有用的人,那么工作可能不会有任何进展。作为一名数据科学家,很容易感觉到一旦你完成了这个项目,人们就会发现它的用处。在实践中,如果你不能立即看到项目的用途,那么业务人员可能也不能。不要被困在这些项目中,因为他们会让数据科学家看起来好像没有贡献。

报告(既无创新也无影响力)😴

不能改变任何事情并且没有创新的工作通常会被报道。这是为人们提供数字和 KPI,以便他们可以监控业务,确保一切顺利运行。有时,企业会有很好的流程来审查报告并找出机会所在。其他时候,这些报告会定期创建,但从来不会被查看。进行报告的最佳情况是,您可以设置一个自动化流程,以便在每次需要新报告时快速生成报告。最糟糕的情况是,每次您需要更新它时,这都是一个繁重的手动过程,这会拖累您的整体工作能力。作为一名数据科学家,你越能避免这成为你的工作就越好。

因此,尽可能优先考虑那些影响公司并具有创新性的项目(我们都希望自己正在做的工作)。否则,尝试做一些不创新但有用的工作,向人们提供证据,以帮助推动业务向前发展。确保你远离象牙塔,不做与业务无关的有趣工作,避免只做报告。祝你好运!

如果你想要大量的方法来帮助你在数据科学领域发展职业生涯,可以看看我和 Emily Robinson 写的书: 在数据科学领域建立职业生涯 。我们将带您了解成为数据科学家所需的技能,找到您的第一份工作,然后晋升到高级职位。

概率图形模型—简介

原文:https://towardsdatascience.com/probabilistic-graphical-models-introduction-f7c919069d5c?source=collection_archive---------4-----------------------

概率图形模型或 PGM 是用于创建复杂现实世界场景概率 模型,并以紧凑图形表示来表示它们的框架。这个定义本身是非常抽象的,涉及到许多需要自己空间的术语,所以让我们一个一个地来看这些术语。

M odel 模型是我们想要分析的真实世界场景或问题的声明性表示。当我说声明性时,它意味着它不是派生的,而是由领域专家使用其对问题的领域知识或通过使用来自历史数据集的静态学习算法来声明或定义的,然后使用任何数学工具如图形或甚至简单地由方程来表示。
为 ex 在线性回归

Where Y is the outcome we want to predict given the feature vector X that affects the output. So here we assume (model) Y as a linear function of the input X which is parameterised by Theta.

为什么我们需要对问题建模?因为两个主要原因
1。它允许我们将非结构化的现实世界问题转化为结构化的数学表示
2。它允许我们将问题(模型表示)与其解决方案(算法)隔离,这意味着一旦我们有了问题的数学模型,我们就可以应用任何算法来解决它,例如,对于上述模型,我们可以使用梯度下降或任何其他方法来解决它,模型不会改变。

因为不确定性,我们通常感兴趣解决的问题的性质或者我们想要进行的查询的类型都是概率性的。造成这种情况的原因有很多。例如,对问题的不完全了解、有噪声的观察结果或对问题有贡献但不能/没有包括在模型中的一些属性。

在上面的例子中,我们使用了模型的数学表示,但是在现实世界中,情况是复杂的,经常涉及大量的变量。很多时候,图形表示帮助我们更好地可视化,然后我们使用图论来减少所有参与变量的相关组合的数量,以更紧凑地表示高维度概率分布模型。

我将使用一些与概率和统计相关的基本术语和概念来讨论 PDMs。那些在单独的帖子 【基础概率论与统计】 中有涉及。

如果模型能帮助我们理解现实世界的现象,让我们对世界在特定条件下的行为做出有用的预测,那么它通常是有用的。我们经常想在模型上做的那种查询本质上是预测当其他事情已经发生/观察到时可能会发生什么。为了回答这样的问题,我们需要考虑世界状态的所有组成部分(随机变量),并以某种方式表示它们。我们已经学过“联合分布”,我们代表一个事件的所有可能结果。因此,这意味着我们有工具来表示我们的模型,它可以覆盖所有可能的场景,这就是“联合概率分布表”(暂时仅限于离散随机变量)。那我们为什么要讨论 PGM?
问题是,即使对于一个简单的模型,变量 n 的数量也可能在 100 个的范围内,如果每个变量都能获得平均 d 值,则联合分布表的大小可能非常大。因此,表格可能不是表示复杂模型的可行方法,尽管从概念上讲它们是足够的,但是计算限制不允许它们。我们需要一些其他的表示方法,因为图形的稀疏性,它似乎是一个很好的选择。使用图来表示这种概率模型有许多优点。

  1. 即使涉及到大量的随机变量,它们也不一定都是相互依赖的。如果两个随机变量是独立的,我们不需要考虑它们在连接分布表中的所有组合,这意味着理想情况下表中的行数会更少。图论具有表示这种依赖性和独立性固有能力。
  2. 从某种意义上说,图形表示是灵活的,人们不需要获得关于世界的所有知识来建立模型。一个人可以从他对世界的理解开始,建立一个模型,它会根据它所拥有的知识来行动。当一个人获得更多的知识时,他可以将同样的知识递增地应用于模型(添加/更新节点、边),并且模型将基于新的信息产生改进的结果。
  3. 因为图是标准数学结构,所以它不仅允许对概率分布进行编码,而且为预测查询的查询模型提供了非常清晰的接口。

由于 PGM 基于图论,它们可以分为两类,即有向图无向图。有一个 PGM 家族使用有向图是贝叶斯网络,另一个使用无向图是马尔可夫网络。尽管它们都来源于图论,但它们的直觉有很多不同,并且都需要自己的空间,我将在单独的帖子中讨论它们。

深度学习背景下的概率统计解释

原文:https://towardsdatascience.com/probability-and-statistics-explained-in-the-context-of-deep-learning-ed1509b2eb3f?source=collection_archive---------3-----------------------

让你快速起床的实用方法

Photo by Josh Appel on Unsplash

本文面向希望获得概率统计知识的深度学习初学者,也可供从业者参考。

在我的上一篇文章中,我用自上而下的方法写了关于深度学习的线性代数的概念(文章的链接)(如果你对线性代数没有足够的了解,请先阅读)。这里使用了同样的自顶向下的方法。首先提供用例的描述,然后是概念。

所有示例代码都使用 python 和 numpy。公式以图像的形式提供,以便重复使用。

目录:

  • 介绍
  • 概率基础
  • 集中趋势和可变性的度量
  • 离散概率分布,二项式分布
  • 连续概率分布、均匀分布和正态分布
  • 模型精度测量工具
  • 随机过程和马尔可夫链
  • 概率规划
  • 外部资源

简介:

概率是量化不确定事物的科学。大多数机器学习和深度学习系统利用大量数据来学习数据中的模式。每当数据被用于一个系统而不是唯一的逻辑时,不确定性就会增加,而每当不确定性增加时,概率就变得相关了。

通过将概率引入深度学习系统,我们将常识引入系统。否则,该系统将会非常脆弱,将不会有用。在深度学习中,使用了几种模型,如贝叶斯模型、概率图形模型、隐马尔可夫模型。它们完全依赖于概率概念。

真实世界的数据是混乱的。由于深度学习系统利用真实世界的数据,它们需要一种工具来处理混乱。

使用简单且不确定的系统总是比使用复杂但确定且脆弱的系统更实际。

这里介绍的概率和统计的版本是实际科目的高度简化版本。两者都是非常庞大和独立的研究课题。但是这里写的概念对于一个深度学习的追求者来说已经足够了。在本文的最后,我留下了一些关于这些主题的资源的链接。

概率基础:

如果你开始深度学习,导师提供给你的第一个例子(可能)是 MNIST 手写数字识别任务。这就像深度学习的 hello 世界。

mnist dataset

任务是对手写数字进行分类并标记。正如我前面提到的,你为完成这项任务而创建的机器学习系统是不准确或不确定的。这些图像是 28*28 像素的图像。例如,考虑以下用于此任务的神经网络。

输入图层是输入图像大小的展平矢量(28*28=784)。它被传递到一个层,在该层中,输入向量与权重相乘,并与偏差向量相加。这一层有 10 个神经元。这是暗示有 10 位数。然后他们通过一个 softmax 激活功能。

在这个步骤之后,它们不输出精确的数字,而是输出长度为 10 的向量,其中每个元素是每个数字的概率值。

我们使用 argmax 来获取输出向量中具有最高值的概率的索引。(哪个是预测)

说到这里,我们将再次详细讨论 softmax。这里的要点是,为了理解这个神经网络,我们必须理解一些概率的基础知识。

向量y=【y0,y1,y2,y3,y4,y5,y6,y7,y8,y9】

这里面概率在哪里?

样本空间 : 实验中所有可能值的集合。(在上面的例子中,输入可以来自一组图像,因此它是输入的样本空间,类似地,输出预测可以取从数字 0 到 9 的任何值,因此这些数字是输出预测的样本空间。)

随机变量 : 可以随机取样本空间不同值的变量。在上面的神经网络中,输入向量 x 是一个随机变量,输出‘预测’是一个随机变量,神经网络的权重也是一个随机变量(因为它们是用概率分布随机初始化的。)

概率分布:概率分布是对随机变量在样本空间中取不同值的可能性的描述。在神经网络中,权重由概率分布初始化。输出向量 y 遵循 softmax 分布,soft max 分布也是显示 X 取不同数字值的概率的概率分布。(通常,softmax 提供分类值的概率)

在这个例子中,概率分布 y 是离散的(具有 10 个离散值。)而在其他一些情况下,它可能是连续的(样本空间也是连续的)。在离散分布中,概率分布由 P(x= x ) 表示的概率质量函数(pmf)提供。在上例中,softmax 函数是随机变量 x 的 pmf。

如果你看到输出向量 y = [0.03,0.5,0.07,0.04,0.06,0.05,0.05,0.06,0.04,0.1]的某个实例

这有什么特别的?如果仔细观察,它们的总和都是 1.0,argmax 显示索引 1 的最大值为 0.5,表明该值应该是 1。

这种累加到 1.0 的性质叫做归一化。此外,这些值必须介于 0 和 1 之间。不可能的事件用 0 表示,确定的事件用 1 表示。

同样的条件也适用于连续变量。(一会儿就知道了。)

3 个基本定义:

在任何概率书或课程中,你总是在一开始就学习这三个基础知识。它们是条件概率、边际概率和联合概率。

联合概率 : 两个事件同时发生的概率是多少。用 P(y=y,x=x)或 P(y 和 x) 表示。例子:同时看到太阳和月亮的概率非常低。

条件概率 : 假设另一个事件 x 已经发生,某个事件 y 发生的概率是多少。用 P(y = y | x =x) 表示。既然另一个事件 x 已经发生,它的概率不可能为零。例:吃完后喝水的概率很高。

边际概率 : 随机变量超集的一个子集的概率是多少。例如:人留长发的概率是男人留长发的概率和女人留长发的概率之和。(此处长发随机变量保持不变,性别随机变量改变。)

贝叶斯定理:它描述了一个事件发生的概率,这个概率是基于与该事件相关的其他事件的先验知识。

贝叶斯定理利用了概率中的信念概念。“我有 40%的把握这个事件会发生”并不等同于“骰子有 16%的几率显示 6”。前者利用信念,被称为贝叶斯概率,而后者依赖于以前的数据,被称为频率主义概率。 阅读更多

贝叶斯定理还被用于一种最简单的机器学习算法,称为朴素贝叶斯算法。见 sklearn 文档。

集中趋势和变化的测量:

平均值:平均值是数据的算术平均值。数字文件

import numpy as np
a = np.array([[1,2,3,4,5,6]])
np.mean(a,axis=0)

中位数:数据的中间值。数字文件。

np.median(a,axis=0)

模式:数据的频繁出现值。科学文件。

import numpy as np
from scipy import statsstats.mode(a)

期望值:某个变量 X 关于某个分布 P(X= x )是从 P 中抽取 x 时 X 的平均值

期望值等于数据集的统计平均值。看为什么。

方差:数据相对于平均值的可变性的度量。

import numpy as np
a = np.array([[1,2,3,4,5,6]])np.var(a)

对于随机变量,方差由下式给出:

这个公式和上面的公式意思一样。数字文档。

标准差:是方差的平方根。数字文档。

import numpy as np
np.std(a)

还有一些其他的变量度量,如范围和四分位间距。看这里

共方差:显示两个变量如何线性相关。Numpy 输出协方差矩阵,其中 Cij 表示 xi 和 xj 之间的协方差。数字文件

np.cov(a)

概率分布:

正如我在开始提到的,神经网络的几个组成部分是随机变量。随机变量的值来自概率分布。在许多情况下,我们只使用某些类型的概率分布。有些是,

二项分布:二项随机变量是一个随机实验的 n 次试验的成功次数。当随机变量只能有两种结果(成功和失败)时,称随机变量 x 遵循二项分布。自然,二项分布是针对离散随机变量的。 numpy 文档。

import numpy as npn=10 # number of trialsp=0.5 # probability of success
s=1000 # size
np.random.binomial(n,p,s)

连续分布:这些是为连续随机变量定义的。在连续分布中,我们用 p(x)表示的概率密度函数(pdf)来描述分布。

他们的积分等于 1。

如果你对微积分不太熟悉看这里,

均匀分布:这是最简单的连续分布形式,样本空间中的每个元素都是等概率。数字文档

import numpy as np
np.random.uniform(low=1, high=10,size=100)

正态分布:“从混沌中有序”

这是所有发行版中最重要的。也称为高斯分布。在缺乏关于实数分布形式的先验知识的情况下,正态分布是一个很好的选择,因为它具有高熵,并且中心极限定理表明几个独立随机变量的和是正态分布的。数量单据

import numpy as np
mu = 0
sigma = 1
np.random.normal(mu,sigma,size=100)

在一个正态分布中,如果均值为 0,标准差为 1,则称为标准正态分布。

the famous bell curve

在机器学习中,你经常会遇到‘规范化’和‘标准化’这两个词。我们上面所做的获得标准正态分布的过程称为标准化,而将数据集值的范围限制在 0.0 到 1.0 之间的过程称为归一化。然而,这些术语经常互换。

from sklearn.preprocessing import StandardScaler
import numpy as npdata = np.array([1,2,3,4,5])
scaler = StandardScaler()
scaler.fit_transform(data)

在这个阶段,我们遇到了几个公式和定义。如果你把这些都背下来,那是非常有用的。(或者以此文作为参考!)还有其他重要的分布,如指数分布和泊松分布。参考此处快速浏览。

Softmax 分布:在本文开头,我提到了关于 Softmax。这是一种概率分布。它最适合用于表示 N 类分类分布中的 1 类。也是深度学习中最常用的分布。区分起来很方便。

def softmax(x):e_x = np.exp(x - np.max(x))return e_x / e_x.sum(axis=0)##the np.max(x) is used just for numerical stability.it is Not ##formula

模型精度测量工具:

为了衡量深度学习模型的性能,我们使用几个概念。了解这些概念非常重要。它们被称为度量。在上面的 MNIST 神经网络中,如果神经网络正确地预测了 100 幅输入图像中的 95 幅,那么它的准确度被认为是 95%,以此类推。(这部分用 sklearn python 库举例。)

你可以直观地理解准确性,但理论是,它是在总的获得结果中正确结果的命题。

准确性是一个非常简单的衡量标准,有时可能会提供错误的见解。在某些情况下,更高的准确性并不意味着我们的模型工作正常。为了澄清这一点,首先看下面的定义,

  • 真阳性(TP): 正例数,如此标注。
  • 假阳性(FP): 阴性样本数,标注为阳性。
  • 真否定(TN): 否定例数,如此标注。
  • 假阴性(FN): 阳性例数,标为阴性。
Accuracy = (TP + TN)/(TP + FP + TN + FN)

混淆矩阵:包含 TP、FP、TN、FN 值的矩阵。

confusion matrix

from sklearn.metrics import confusion_matrix
y_true = [2, 0, 2, 2, 0, 1]
y_pred = [0, 0, 2, 2, 0, 2]
confusion_matrix(y_true, y_pred)

现在,想象一个二进制分类器,输出 1 或 0。如果一切正常,模型没有偏差,它就表示实际的准确性。但是,如果我们调整模型,使其始终为 0(或始终为 1)(现在模型的预测能力为零)。但是我们仍然会得到很高的精度!考虑一下桌子。

 Classified positive  Classified negative 
Positive class         0 (TP)            25 (FN)
Negative class         0 (FP)           125 (TN)

这个表很明显模型很差(因为所有的正类例子都分类错误)但是准确率 83%!!

精度和召回率:所以我们选择另外两个指标——精度和召回率。

精度告诉你有多少选择的对象是正确的

回忆告诉你选择了多少正确的对象。

在上面的例子中,精确度和召回率都是 0.0,这表明模型非常差。

F1 得分:是精度和召回率的调和平均值。

F1 分 0 代表最差,1 代表最好。利用这一点,我们可以解决准确性度量的混乱行为。

Sklearn 有一个 classification_report 函数,您可以调用它来获得 precision、recall 和 f1 分数。

**>>> from** **sklearn.metrics** **import** classification_report
**>>>** y_true = [0, 1, 2, 2, 2]
**>>>** y_pred = [0, 0, 2, 2, 1]
**>>>** target_names = ['class 0', 'class 1', 'class 2']
**>>>** print(classification_report(y_true, y_pred, target_names=target_names))precision    recall  f1-score   supportclass 0       0.50      1.00      0.67         1class 1       0.00      0.00      0.00         1class 2       1.00      0.67      0.80         3micro avg       0.60      0.60      0.60         5macro avg       0.50      0.56      0.49         5
weighted avg       0.70      0.60      0.61         5

平均绝对误差:原始值与预测值之差的平均值。

均方误差:原始值和预测值之差的平方的平均值。

**from** **sklearn.metrics** **import** mean_squared_error
y_true = [3, -0.5, 2, 7]
y_pred = [2.5, 0.0, 2, 8]
mean_squared_error(y_true, y_pred)

均方误差被广泛使用,因为它更容易计算梯度。

接收机工作特性(ROC) 曲线:ROC 曲线是一个图,显示了分类模型的性能,如我们的数字识别器示例。它有两个参数——真阳性率(TPR)和假阳性率(FPR)。 TPR 和 recall 一样,也叫灵敏度。FPR 也是 1-特异性。

将这两者相对于彼此进行绘图,以获得下图(通过改变分类阈值并再次重复预测结果,获得绘图的几个值。).该 ROC 曲线下的面积是准确度的量度。

曲线下面积(AUC)的解释:当 AUC=1.0 时,模型最佳。当 AUC=0.5 时,模型最差。但是,如果 AUC=0.0,那么模型将重复结果。(就像把 1 归类为 0,把 0 归类为 1 一样)。

**import** **numpy** **as** **np**
**from** **sklearn.metrics** **import** roc_auc_score
y_true = np.array([0, 0, 1, 1])
y_scores = np.array([0.1, 0.4, 0.35, 0.8])
roc_auc_score(y_true, y_scores)

更多信息:看这里和这里。

使用梯形规则计算 AUC(sk learn 使用此规则 ): 看这里

随机过程、马尔可夫链和图形模型;

随机过程是由一些值索引的随机变量的集合。直观上,随机过程或随机过程是一种现象的数学模型,这种现象对于观察者来说是以不可预测的方式进行的。下一个事件的结果是不依赖于当前事件的结果。例如,一系列的硬币投掷。

如果随机过程中随机变量被索引的索引集来自一个离散的自然数,则该过程称为离散时间随机过程或随机序列。如果指标集位于实数线上,则该过程为连续时间随机过程。如果指标集位于笛卡儿平面或某些更高维的欧几里得平面,那么这个过程就称为随机场

随机过程是概率中非常有趣的一部分。它们被用来模拟与时间相关的事物,如天气预报、股票市场、自然现象等。有几个随机过程。这里我们重点关注马尔可夫链。想要更详细的资料,请参考维基百科。

马尔可夫链:

马尔可夫链是一个概率自动机。它有状态。它描述了一系列事件,其中从一个状态转移到另一个状态的概率仅取决于前一个事件。这里是对马尔可夫链的极好的直观解释。

这是描述天气状况的马尔可夫链。这些值代表从一种状态转换到另一种状态的概率。

马尔可夫链用于简单的系统,如下一个单词预测、语言生成、声音生成和许多其他系统。

称为隐马尔可夫模型的马尔可夫链的扩展用于语音识别系统。

我已经停止了随机过程,并计划写一篇关于它们的文章,因为这个概念太长了。

概率规划:

一种新的编程范式已经发展成为概率编程。这些语言或库有助于模拟贝叶斯风格的机器学习。这是一个令人兴奋的研究领域,受到人工智能社区和软件工程社区的支持。这些语言很容易支持概率函数和模型,如高斯模型、马尔可夫模型等。

优步去年创建了一个这样的用于编写概率程序的库,名为 pyro ,它以 pytorch (一个深度学习库)作为后端来支持 python。

pyro library logo

如果你喜欢这篇关于深度学习的概率和统计的文章,请为这篇文章鼓掌。这里提供的内容是面向深度学习初学者的,也可以作为深度学习从业者的参考资料。但是对于初学者来说,我还会推荐几个其他很棒的外部资源来巩固他们在有趣的概率领域的知识。( 虽然你通过这篇文章获得的知识已经足够进行深度学习 )

外部资源:

关于深度学习和机器学习的超赞免费课程: fast.ai

微积分的直观解释: 3blue1brown

深度学习最佳书籍:深度学习书籍

随机过程:谢尔登·m·罗斯

统计学:拉里·乏色曼的《T2 统计大全》

概率论:威廉·费勒

数据科学的概率与统计第一部分

原文:https://towardsdatascience.com/probability-and-statistics-for-data-science-part-1-3eed6051c40d?source=collection_archive---------4-----------------------

概率和统计构成了数据科学的基础。概率论对做预测很有帮助。估计和预测是数据科学的重要组成部分。借助统计方法,我们作出估计,以便进一步分析。因此,统计方法在很大程度上依赖于概率论。所有的概率和统计都依赖于数据。

数据

数据是我们收集的关于某事或事实的信息(观察结果)和收集在一起用于参考或分析的统计数据。

数据——已经转化为计算机可以处理的形式的事实(数字、文字、测量、观察等)的集合

为什么数据很重要?

  • 通过识别两个变量之间可能存在的关系,帮助了解更多关于数据的信息。
  • 有助于预测未来或根据以前的数据趋势进行预测。
  • 有助于确定数据之间可能存在的模式。
  • 通过发现数据中的异常,帮助发现欺诈。

如今数据很重要,因为我们可以从中推断出重要的信息。现在让我们深入研究数据是如何分类的。数据可以有两种类型:分类数据和数字数据。例如,在一家银行,我们的地区、职业类别、性别遵循分类数据,因为数据在固定的某个值内,而余额、信用评分、年龄、任期月份遵循数值连续分布,因为数据可以遵循无限范围的值。

注:分类数据可以通过条形图、饼图、帕累托图可视化。数字数据可以通过柱状图、线图、散点图来可视化

描述统计学

描述性统计是对信息集合的特征进行定量描述或总结的汇总统计。它帮助我们更好地了解我们的数据。它用于描述数据的特征。

数据的测量水平

定性和定量数据与上述分类和数值数据非常相似。

名义:这个级别的数据使用名称、标签或质量进行分类。例如:品牌名称,邮政编码,性别。

序数:本级数据可以按顺序排列或排名,可以比较。例如:成绩、明星评论、比赛名次、日期

Interval :该级别的数据可以按其在一个数值范围内的情况进行排序,并且可以计算出数据点之间有意义的差异。例:摄氏温度,出生年份

比率:此级别的数据类似于区间级别,但增加了固有零的属性。可以对这些数据点进行数学计算。身高,年龄,体重

看看这个:数据| Mahrita Harahap

总体或样本数据

在进行任何数据分析之前,我们应该确定我们正在处理的数据是总体数据还是样本数据。

人群:所有物品(N)的集合,它包括我们研究的每一个单元。这是很难定义和衡量的特点,如平均,模式被称为参数。

样本:总体(n)的子集,它只包括少数几个总体单位。它是随机选择的,特性的测量称为统计。

例如,假设您想知道电影订阅服务的订阅者的平均收入(参数)。我们随机抽取 1000 个用户样本,并确定他们的平均 income(x̄是 34,500 美元(统计)。我们的结论是,人口平均收入(μ)也可能接近 34,500 美元。

在看数据分布之前。让我们来看看数据的度量。

集中趋势测量

集中趋势的度量是试图通过识别一组数据中的中心位置来描述该组数据的单个值。因此,集中趋势的度量有时被称为集中位置的度量。它们也被归类为汇总统计。

平均值:平均值等于数据集中所有值的总和除以数据集中值的个数,即计算出的平均值。易受异常值的影响当添加异常值时,会出现偏差,即偏离典型的中心值。

中值:中值是按数量级排列的数据集的中间值。中位数是平均值的更好替代,因为它受数据异常值和偏斜度的影响较小。中间值比典型的中心值更接近。

如果值的总数是奇数,则

如果值的总数是偶数

模式:模式是数据集中最常出现的值。因此,模式有时会认为模式是最受欢迎的选项。

例如,在包含{13,35,54,54,55,56 57,67,85,89,96}个值的数据集中。平均值为 60.09。中位数是 56。众数是 54。

不对称的度量

偏斜度:偏斜度是统计分布中的不对称,其中曲线出现扭曲或向左或向右偏斜。偏斜度表示数据是否集中在一侧。

Source: Pearson Mode Skewness: Definition and Formulas

正偏度:正偏度是当均值>中位数>时的模式。离群值向右倾斜,即尾部向右倾斜。

负偏度:负偏度是当均值<中位数<众数。离群值向左倾斜,即尾部向左倾斜。

偏斜度很重要,因为它告诉我们数据分布在哪里。

2003 年的全球收入分配是高度右倾的。我们可以看到,2003 年的平均值为 3,451 美元(绿色),高于中位数 1,090 美元。这表明全球收入分配不均。大多数个人收入低于 2,000 美元,收入高于 14,000 美元的人数较少,因此出现了偏态。但根据预测,收入不平等似乎在 2035 年会随着时间的推移而减少。

可变性(离差)的测量

集中趋势的度量给出了代表整体值的单个值;然而,中心趋势不能完全描述观察结果。离差的度量有助于我们研究项目的可变性,即数据的分布。

记住:总体数据有 N 个数据点,样本数据有(n-1)个数据点。(n-1)称为贝塞尔校正,用于减少偏差。

范围:一个数据的最大值和最小值之差,称为分布的范围。范围不考虑一个系列的所有值,即它只考虑极端项目,中间项目不被认为是重要的。例如:对于{13,33,45,67,70},范围是 57,即(70–13)。

方差:方差衡量每个点到平均值的距离平方和,即平均值周围的离差。

方差是所有平方偏差的平均值。

注意:值和方差的单位不相等,因此我们使用另一个可变性度量。

标准差:由于方差受单位差影响,所以使用标准差。方差的平方根就是标准差。它说明了数据在数据集平均值附近的集中程度。

例如:{3,5,6,9,10}是数据集中的值。

变异系数(CV): 又称相对标准差。它是标准偏差与数据集平均值的比率。

标准差是单个数据集的可变性。而变异系数可用于比较两个数据集。

从上面的例子可以看出,CV 是一样的。两种方法都很精确。所以这是完美的比较。

四分位数的度量

考虑到每个数据点,四分位数更容易理解。

查看我之前的帖子——在箱线图部分,我已经详细阐述了四分位数。

关系的度量

关系的度量用于找出两个变量之间的比较。

协方差:协方差是对两个变量的可变性之间关系的度量,即它度量变量的变化程度,当一个变量发生变化时,另一个变量是否会发生相同/相似的变化。

协方差没有给出关于两个变量之间关系的有效信息,因为它没有被归一化。

相关性:相关性让我们更好地理解协方差。它是归一化协方差。相关性告诉我们变量之间的相关程度。它也被称为皮尔逊相关系数。

相关值的范围从-1 到 1。-1 表示负相关,即一个独立变量增加,另一个因变量减少。1 表示正相关,即一个独立变量增加,另一个因变量增加。0 表示变量相互独立。

举个例子,

相关性 0.889 告诉我们身高和体重有正相关关系。很明显,随着一个人身高的增加,体重也会增加。

注:相关并不意味着因果关系,对于一些奇怪的相关为虚假相关。

结论

在本文中,我们学习了描述性统计,它通过理解数据集中的关键特征来帮助我们更好地了解我们的数据。

增强树的概率校准

原文:https://towardsdatascience.com/probability-calibration-for-boosted-trees-24cbd0f0ccae?source=collection_archive---------2-----------------------

背景:概率校准的开创性论文:http://www . cs . Cornell . edu/~ caru ana/Niculescu . scldbst . CRC . rev 4 . pdf

增强决策树通常会产生良好的准确度、精确度和 ROC 面积。然而,因为来自增强的输出不是很好校准的后验概率,所以增强产生差的平方误差和交叉熵。它倾向于保守地预测概率,意味着更接近于中间值而不是极端值。以下是提升对预测概率的影响:

校准良好的分类器是概率分类器,其模型的输出可以直接解释为置信度。例如,校准良好的(二元)分类器应该对样本进行分类,使得在它给出接近 0.8 的预测值的样本中,大约 80%实际上属于正类。下图比较了不同分类器的概率预测的校准情况:

默认情况下,LogisticRegression 返回校准良好的预测,因为它直接优化了对数损失。相反,其他方法返回有偏差的概率;带着不同的偏见。

执行概率预测校准的两种方法是:基于 Platt 的 sigmoid 模型的参数方法和基于保序回归的非参数方法。应使用不用于模型拟合的测试/验证数据进行概率校准。

普拉特标度:

普拉特的缩放相当于在分类器输出上训练逻辑回归模型。

您实际上创建了一个新的数据集,它具有相同的标签,但只有一个维度(未校准分类器的概率输出)。然后,在这个新的数据集上进行训练,并将未校准的分类器的概率输出作为这个校准方法的输入,该方法返回一个校准的概率。在 Platt 的情况下,我们本质上只是对未校准分类器相对于真实类别标签的概率输出执行逻辑回归。

逻辑回归模型是 f(x)= y。y 是输入数据的真实标签,x 是基本分类器的预测概率。现在,您使用逻辑回归的预测概率作为校准分类器的真实概率。

保序回归:

其思想是拟合分段常数非减函数,而不是逻辑回归。分段常数非递减意味着阶梯形。通过池相邻违规者算法(PAVA)实现。PAVA 是线性排序保序回归的线性时间(和线性记忆)算法。

训练保序回归的方法是相似的:

f(x) = y,y 是输入数据的真实标签,x 是基本分类器的预测概率。等渗模型将通过 x(基础分类器的预测概率)对数据进行分类,然后拟合一个阶跃函数来给出真实标签的概率。

其他资源:

http://fastml . com/classifier-calibration-with-Platts-scaling-and-isotonic-regression/

https://jmetzen.github.io/2015-04-14/calibration.html

【https://scikit-learn.org/stable/modules/calibration.html

解释概率概念:参数估计的贝叶斯推断。

原文:https://towardsdatascience.com/probability-concepts-explained-bayesian-inference-for-parameter-estimation-90e8930e5348?source=collection_archive---------0-----------------------

Pixabay

介绍

在之前的博文中,我提到了机器学习和统计模型中参数估计的最大似然法。在这篇文章中,我们将回顾另一种使用贝叶斯推理的参数估计方法。我还将展示如何将这种方法视为最大似然法的推广,以及在什么情况下这两种方法是等价的。

假设了一些概率论的基础知识,例如边际概率和条件概率。这些概念在我的系列的第一篇文章中有解释。此外,了解高斯分布的一些基本知识也很有帮助,但这不是必需的。

贝叶斯定理

在介绍贝叶斯推理之前,有必要了解一下贝叶斯定理。贝叶斯定理真的很酷。它的有用之处在于,它允许我们使用一些我们已经拥有的知识或信念(通常称为先验)来帮助我们计算相关事件的概率。例如,如果我们想找出在炎热晴朗的日子里卖冰淇淋的概率,贝叶斯定理为我们提供了工具,让我们利用先验知识来判断在任何其他类型的日子里(下雨、刮风、下雪等)卖冰淇淋的概率。).我们稍后会详细讨论这一点,所以如果你还不明白,请不要担心。

数学定义

数学上,贝叶斯定理被定义为:

其中 AB 是事件, P(A|B) 是事件 A 发生的条件概率,假设事件 B 已经发生( P(B|A) 具有相同的含义,但是具有 AB 反转的角色)以及 P(A)

例子

数学定义常常让人觉得太抽象和可怕,所以让我们用一个例子来理解这一点。我在介绍性博客文章中给出的一个例子是关于从一包传统扑克牌中挑选一张牌。一副牌中有 52 张牌,其中 26 张为红色,26 张为黑色。假设我们知道这张牌是红色的,那么这张牌是 4 的概率是多少?

为了把它转换成我们在上面看到的数学符号,我们可以说事件 A 是牌是 4 的事件,事件 B 是牌是红色的。因此,上式中的 P(A|B) 就是我们例子中的 P(4|red) ,这就是我们要计算的。我们之前计算出这个概率等于 1/13(有 26 张红牌,其中两张是 4),但是让我们用贝叶斯定理来计算。

我们需要找到右边各项的概率。它们是:

  1. P(B|A) = P(red|4) = 1/2
  2. P(A) = P(4) = 4/52 = 1/13
  3. P(B) = P(红色)= 1/2

当我们将这些数字代入上述贝叶斯定理的方程时,我们得到 1/13,这就是我们所期待的答案。

贝叶斯定理是如何让我们整合先验信念的?

上面我提到了贝叶斯定理允许我们整合先验信念,但是仅仅通过上面的等式很难看出它是如何允许我们这样做的。因此,让我们看看如何使用上面的冰淇淋和天气示例来实现这一点。

让 A 代表我们卖冰淇淋的事件,B 代表天气的事件。然后我们可能会问在给定的天气类型下,在任何一天卖出冰淇淋的可能性有多大?从数学上来说,这可以写成 P(A =冰淇淋销售额| B =天气类型),相当于等式的左侧。

右手边的 P(A)是被称为先验的表达式。在我们的例子中,这是 P(A =冰淇淋销售额),即不管外面的天气如何,销售冰淇淋的(边际)概率。P(A)被称为先验,因为我们可能已经知道冰淇淋销售的边际概率。例如,我可以查看这样的数据:潜在的 100 人中有 30 人实际上在某个地方的某个商店购买了冰淇淋。所以我的 P(A =冰淇淋销售额)= 30/100 = 0.3,在我了解天气之前。这就是贝叶斯定理允许我们整合先验信息的方式。

注意:我在上面提到过,我可以从商店中找到数据来获得先验信息,但是没有什么可以阻止我编造一个完全主观的先验,这个先验不是基于任何数据的。有人可能会根据个人经验或特定领域的知识得出一个先验知识,但重要的是要知道最终的计算将会受到这个选择的影响。我会在后面的文章中更详细地讲述先前信念的强度如何影响结果。

贝叶斯推理

定义

现在我们知道什么是贝叶斯定理以及如何使用它,我们可以开始回答问题什么是贝叶斯推理?**

首先,【统计】推断是从数据中推断出关于人口或概率分布的性质的过程。在我之前关于最大可能性的文章中,我们做到了这一点。根据一组观察到的数据点,我们确定了平均值的最大似然估计。

贝叶斯推断因此就是使用贝叶斯定理从数据中推导出关于人口或概率分布的属性的过程。就这样。

对分布使用贝叶斯定理

到目前为止,我上面给出的例子都是用一个数字来表示贝叶斯定理方程中的每一项。这意味着我们得到的答案也是个位数。但是,也可能有单个数字不合适的时候。

在上面的冰淇淋例子中,我们看到卖冰淇淋的先验概率是 0.3。然而,如果 0.3 只是我的最佳猜测,但我对这个值有点不确定。概率也可以是 0.25 或者 0.4。在这种情况下,我们先前信念的分布可能更合适(见下图)。这种分布被称为先验分布

2 distributions that represent our prior probability of selling ice on any given day. The peak value of both the blue and gold curves occur around the value of 0.3 which, as we said above, is our best guess of our prior probability of selling ice cream. The fact that f(x) is non-zero of other values of x shows that we’re not completely certain that 0.3 is the true value of selling ice cream. The blue curve shows that it’s likely to be anywhere between 0 and 0.5, whereas the gold curve shows that it’s likely to be anywhere between 0 and 1. The fact that the gold curve is more spread out and has a smaller peak than the blue curve means that a prior probability expressed by the gold curve is “less certain” about the true value than the blue curve.

以类似的方式,我们可以用分布来表示贝叶斯定理中的其他项。当我们处理模型时,我们通常需要使用分布。

贝叶斯定理的模型形式

在上面贝叶斯定理的介绍性定义中,我使用了事件 A 和 B,但是当贝叶斯定理的模型形式在文献中陈述时,通常使用不同的符号。我们来介绍一下。

我们通常会看到θ,而不是事件 A,这个符号叫做θ。θ是我们感兴趣的,它代表了一组参数。因此,如果我们试图估计高斯分布的参数值,那么θ代表均值μ和标准差σ(数学上写为θ= {μ,σ})。

而不是事件 B,我们会看到数据或者 y = {y1,y2,…,yn}。这些代表数据,即我们拥有的一组观察值。我将在等式中显式使用数据,希望让等式不那么神秘。

所以现在模型形式的贝叶斯定理被写成:

我们已经看到 P(θ)是先验分布。它代表了我们对参数真实值的信念,就像我们的分布代表了我们对卖冰淇淋概率的信念。

P(θ|数据)*左边称为后验分布。**这是一个分布,代表我们对参数值的信念,在我们计算了右侧的所有数据后,将观察到的数据考虑在内。*

P(data |θ)是我们以前遇到过的东西。如果你坚持到我上一篇关于最大可能性的文章的结尾,那么你会记得我们说过 L(数据;μ,σ) 是似然分布(对于高斯分布)。嗯P(data |θ)*正是这个,是似然分布的变相。有时候会写成ℒ(θ;数据)但这里是一回事。***

因此,我们可以使用用我们的可能性更新的先验信念来计算我们参数的后验分布。**

这给了我们足够的信息来通过一个使用贝叶斯推断的参数推断的例子。但是首先…

为什么我完全不顾 P(数据)?

嗯,除了数据的边际分布之外,它并没有什么特别的名字,尽管它有时被称为证据。记住,我们只对参数值感兴趣,但是 P(data) 对它们没有任何引用。实际上, P(数据)甚至都没有评估到一个分布。只是一个数字。我们已经观察了数据,所以我们可以计算 P(数据)。一般来说,计算 P(数据)非常困难的并且有很多方法可以计算它。Prasoon Goyal 的这篇博客文章解释了这样做的几种方法。

P(data) 之所以重要,是因为得出的数字是一个归一化常数。概率分布的必要条件之一是一个事件所有可能结果的总和等于 1(例如,在 6 面骰子上掷出 1、2、3、4、5 或 6 的总概率等于 1)。归一化常数通过确保分布的和(我应该说是整数,因为它通常是一个连续分布,但现在这样说太迂腐了)等于 1,来确保最终的后验分布是一个真实的概率分布。

在某些情况下,我们不关心分布的这种性质。我们只关心分布的峰值出现在哪里,而不管分布是否正态化。在这种情况下,许多人把贝叶斯定理的模型形式写成

其中∝表示“成比例”。这清楚地表明,真实的后验分布不等于右侧,因为我们没有考虑归一化常数 P(数据)

贝叶斯推理例子

干得好,走了这么远。在所有那些理论之后,你可能需要休息一下。但是,让我们继续看一个推理可能会派上用场的例子。我们要用的例子是,计算氢键的长度。你不需要知道氢键是什么。我只是用这个作为例子,因为它是我在读博士期间想出来帮助一个朋友的(我们当时在生物化学系,这就是为什么它当时是相关的)。

I’ve included this image because I think it looks nice, helps to break up the dense text and is kind of related to the example that we’re going to go through. Don’t worry, you don’t need to understand the figure to understand what we’re about to go through on Bayesian inference. In case you’re wondering, I made the figure with Inkscape.

让我们假设氢键在 3.2-4.0 之间(在谷歌上快速搜索给了我这个信息。ngströ是一个距离单位,其中 1 等于 0.1 纳米,所以我们谈论的是非常微小的距离)。这些信息将构成我的先验知识。就概率分布而言,我将把它重新表述为均值μ = 3.6,标准差σ = 0.2 的高斯分布(见下图)。

Our prior probability for the length of a hydrogen bond. This is represented by a Gaussian distribution with mean μ = 3.6Å and standard deviation σ = 0.2Å.

现在,我们看到了一些数据(5 个数据点是从平均值为 3,标准偏差为 0.4 的高斯分布中随机产生的,准确地说)。在现实世界中,这些数据将来自科学实验的结果,该实验给出了测量的氢键长度(图 3 中的金点)。我们可以从数据中推导出一个可能性分布,就像我们在上一篇关于最大可能性的文章中所做的那样。假设数据是从一个可以用高斯分布描述的过程中生成的,我们得到了一个由下图中的黄金曲线表示的似然分布。请注意,5 个数据点平均值的最大似然估计值小于 3(约 2.8)

Prior probability for the distance of a hydrogen bond in blue and the likelihood distribution in gold derived from the 5 gold data points.

现在我们有两个高斯分布,蓝色代表先验,金色代表可能性。我们不关心归一化常数,所以我们有计算非归一化后验分布所需的一切。回想一下,表示高斯分布概率密度的等式是

所以我们要把其中的两个相乘。我不会在这里讨论数学,因为它变得很乱。如果你对数学感兴趣,那么你可以在本文的前 2 页看到它的表现。由此产生的后验分布在下图中显示为粉红色。

The posterior distribution in pink generated by multiplying the blue and gold distributions.

现在我们有了氢键长度的后验分布,我们可以从中得出统计数据。例如,我们可以使用分布的期望值来估计距离。或者我们可以计算方差来量化我们结论的不确定性。根据后验分布计算的最常见的统计数据之一是众数。这通常用作感兴趣参数真实值的估计,称为最大后验概率估计,或简称为估计。在这种情况下,后验分布也是高斯分布,因此平均值等于众数(和中值),氢键距离的 MAP 估计值位于分布的峰值,约为 3.2。

结束语

为什么我总是用高斯函数?

你会注意到,在我所有涉及分布的例子中,我都使用高斯分布。一个主要原因是它使数学变得容易多了。但是对于贝叶斯推理的例子,它需要计算 2 个分布的乘积。我说这很乱,所以我没有做数学。但即使我自己没有做数学计算,我也知道后验概率是高斯分布。这是因为高斯分布有一个特殊的属性,使得它很容易处理。就高斯似然函数而言,它与自身共轭。这意味着,如果我把一个高斯先验分布乘以一个高斯似然函数,我将得到一个高斯后验函数。后验分布和先验分布都来自同一个分布族(它们都是高斯分布)这一事实意味着它们被称为共轭分布。在这种情况下,先验分布被称为共轭先验。

在许多推理情况下,可能性和先验被选择成使得结果分布是共轭的,因为这使得数学更容易。数据科学中的一个例子是潜在狄利克雷分配(LDA) 这是一种无监督学习算法,用于在几个文本文档(称为语料库)中查找主题。在埃德温·陈的博客中可以找到关于 LDA 的很好的介绍。

在某些情况下,我们不能简单地选择先验或似然性来计算后验分布。有时可能性和/或先验分布看起来很可怕,手工计算后验概率是不容易或不可能的。在这些情况下,我们可以用不同的方法来计算后验分布。最常见的方法之一是使用一种叫做马尔可夫链蒙特卡罗方法的技术。Ben Shaver 写了一篇名为的精彩文章,介绍了马尔可夫链蒙特卡罗方法,以一种非常通俗易懂的方式解释了这种技术。

当我们得到新数据时会发生什么?

贝叶斯推理的一个伟大之处是,你不需要大量的数据来使用它。1 次观察足以更新先验。事实上,贝叶斯框架允许你在数据到来时实时迭代更新你的信念。它是这样工作的:你对某事有一个先验的信念(例如一个参数的值),然后你接收一些数据。你可以像上面那样通过计算后验分布来更新你的信念。之后,我们会收到更多的数据。所以我们的后验变成了新的先验。我们可以用从新数据导出的可能性来更新新的先验,并且我们再次得到新的后验概率。这个循环可以无限期地继续下去,所以你会不断地更新你的信念。

卡尔曼滤波器(及其变种)就是一个很好的例子。它被用于许多场景,但可能是数据科学中最引人注目的是它在无人驾驶汽车上的应用。我在攻读数学蛋白质晶体学博士期间使用了一种叫做无味卡尔曼滤波器的变体,并为实现它们的开源包做出了贡献。为了更好的直观描述卡尔曼滤波器,请看这篇博文:卡尔曼滤波器如何工作,图片由蒂姆·巴布提供。

利用前科作为规则

我们在上述氢键长度示例中生成的数据表明,2.8 是最佳估计值。然而,如果我们仅根据数据进行估计,我们可能会有过度拟合的风险。如果数据收集过程出现问题,这将是一个巨大的问题。我们可以用先验知识在贝叶斯框架中解决这个问题。在我们的例子中,使用以 3.6 为中心的高斯先验得到后验分布,给出氢键长度的 MAP 估计值为 3.2。这表明当估计参数值时,我们的先验可以作为正则化器。

我们对先验概率和可能性的权重取决于两个分布之间的相对不确定性。在下图中,我们可以直观地看到这一点。颜色同上,蓝色代表先验分布,金色代表可能性,粉色代表后验分布。在左图中,您可以看到我们的先验(蓝色)比可能性(金色)分散得少得多。因此,后验概率更像前验概率。右图中的情况正好相反。

因此,如果我们希望增加参数的正则化,我们可以选择缩小与可能性相关的先验分布。

米歇尔·格林写了一篇名为贝叶斯先验和过度拟合的真相的文章,更详细地讨论了这个问题,并给出了如何设定先验的建议。

什么时候 MAP 估计等于最大似然估计?

当先验分布均匀时,MAP 估计等于 MLE。下面是一个均匀分布的例子。

Uniform distribution

我们可以看到的是,均匀分布对 x 轴(是一条水平线)上的每个值赋予相等的权重。直观上,它表示缺乏关于哪些值最有可能的任何先验知识。在这种情况下,所有的权重都分配给了似然函数,因此当我们将先验乘以似然性时,得到的后验与似然性完全相似。因此,最大似然法可以看作是 MAP 的一个特例。

*当我开始写这篇文章时,我真的没有想到它会这么长,所以非常感谢你能走这么远。我真的很感激。一如既往,如果有任何不清楚的地方或者我在上面犯了一些错误,请随时留下评论。在本系列的下一篇文章中,我可能会尝试讨论我在这篇文章中忽略的标准化常数 *P(数据)的边缘化问题。当然,除非有人想让我看别的东西;)

感谢您的阅读。

概率概念讲解:简介

原文:https://towardsdatascience.com/probability-concepts-explained-introduction-a7c0316de465?source=collection_archive---------0-----------------------

这些年来,我阅读了许多关于概率论不同方面的文本和文章,每一篇似乎都需要不同程度的先决知识来理解正在发生的事情。我绝不是这一领域的专家,但我觉得我可以通过写一系列通俗易懂的文章来解释概率中的各种概念。这是该系列的第一篇,将介绍一些基本的定义。

定义和符号

概率通常与至少一个事件相关联。这个事件可以是任何事情。玩具事件的例子包括掷骰子或者从袋子里拿出一个彩球。在这些例子中,事件的结果是随机的(你不能确定当你掷骰子时骰子将显示的值),所以代表这些事件结果的变量被称为随机变量(通常缩写为 RV)。

我们经常对知道随机变量取某一值的概率感兴趣。例如,当我掷出一个 6 面骰子时,它落在 3 上的概率是多少?“公平”这个词在这里很重要,因为它告诉我们骰子落在六个面中任何一个面上的概率;1,2,3,4,5 和 6 相等。直觉上,你可能会告诉我答案是 1/6。正确!但是我们如何用数学方法来写呢?首先,我们需要明白,这里的随机变量是与掷骰子相关的事件的结果。通常,随机变量用大写字母表示,这里,我们用 X 表示。因此,我们想知道 X = 3 的概率是多少。但是由于数学家在记东西的时候很懒,所以问“概率是多少?”就是用字母 p,因此我们可以写“当我掷出一个 6 面骰子,它落在 3 上的概率是多少?”数学上为“P(X=3)”

概率的三种类型

上面介绍了随机变量的概念和概率的一些符号。然而,概率可能变得相当复杂。也许首先要明白的是,概率有不同的类型。可以是边缘关节条件

边际概率: 如果 A 是一个事件,那么边际概率就是那个事件发生的概率,P(A)。举例:假设我们有一副传统扑克牌,边际概率的一个例子是从一副牌中抽出一张红色牌的概率:P(red) = 0.5。

联合概率: 两个或多个事件相交的概率。从视觉上看,它是维恩图上两个事件圆圈的交点(见下图)。如果 A 和 B 是两个事件,那么这两个事件的联合概率记为 P(A B)。举例:从一副牌中抽出一张牌是红色且数值为 4 的概率为 P(红色和 4) = 2/52 = 1/26。(一副传统扑克牌中有 52 张牌,两张红色的是红心和方块)。稍后我们将更详细地讨论这个例子。

条件概率: 条件概率是在已知其他事件已经发生的情况下,某些事件发生的概率。如果 A 和 B 是两个事件,那么假设 B 已经发生,A 发生的条件概率记为 P(A|B)。例:给定我们抽了一张红卡,一张牌是四的概率是 P(4|red) = 2/26 = 1/13。(一副牌有 52 张,26 张红的,26 张黑的。现在因为我们已经挑选了一张红色的卡片,我们知道只有 26 张卡片可供选择,因此为什么第一个分母是 26)。

Venn diagram showing the ‘space’ of outcomes of 2 events A and B. In the diagram the 2 events overlap. This overlap represents the joint probability, i.e. the probability of both event A and event B happening. If there was no overlap between the events then the joint probability would be zero.

链接概率类型:一般乘法规则

一般乘法法则是一个美丽的等式,它将三种概率联系在一起:

示例的进一步解释

有时,区分联合概率和条件概率可能会非常令人困惑,因此,使用从一副扑克牌中挑选一张牌的示例,让我们尝试将这种差异彻底搞清楚。

在这种情况下,我们想找出选择一张红和 4 的概率,即联合概率 P(红和 4) 我想让你想象所有 52 张牌都面朝下,然后随机选择一张。在这 52 张牌中,2 张为红色,4 张(4 张为方块,4 张为红心)。因此联合概率是 2/52 = 1/26

在这种情况下,我们想找出选择一张 4 的概率,假设我知道这张牌已经是红色的,即条件概率, P(4|red),我想让你再次想象拥有所有 52 张牌。然而,在随机挑选一张牌之前,你要对牌进行分类,并选择所有 26 张红色的牌。现在你把这 26 张牌面朝下,随机选一张。同样,其中两张红牌是 4,所以条件概率是 2/26 = 1/13

或者,如果你喜欢数学,我们可以使用上面定义的一般乘法规则来计算联合概率。我们首先重新排列,使联合概率 P(A B)成为等式的主体(换句话说,让我们把 P(A B)放在等号的左边,其他的放在右边)。重新排列后我们得到 P(A B) = P(A|B) ✕ P(B)。设 A 是牌是 a 4 的事件,B 是牌是红色的事件。P(A|B) = 1/13 正如我们上面说的和 P(B) = 1/2(一半的牌是红色的)。因此 P(A B) = 1/13 ✕ 1/2 = 1/26。

概率规则:“与”和“或”

“与”规则

我们已经看到了伪装成联合概率的“和”场景,但是我们还不知道如何计算“和”场景中的概率。我们来看一个例子。假设我们有两个事件:事件 A——掷一枚公平的硬币,事件 B——掷一枚公平的骰子。我们可能有兴趣知道掷出 6 和硬币正面朝上的概率。因此,为了计算掷出 6 和硬币落地头的联合概率,我们可以重新排列上面的一般乘法规则,得到 P(A B) = P(A|B) ✕ P(B) 我们知道事件 A 是掷硬币,B 是掷骰子。所以 P(A|B) term 问"假设我在骰子上掷出 6,硬币正面朝上的概率是多少?"这就是我们直观地理解抛硬币的结果并不取决于骰子的滚动。据说这些事件是独立的。在这种情况下,无论我们掷什么骰子,掷硬币的结果都是一样的。数学上我们将此表示为 P(A|B) = P(A)。因此当事件相互独立时,联合概率就是事件的个体边际概率的乘积:P(A ∩ B) = P(A) ✕ P(B)。所以 p(硬币落地人头和滚动 a 6)= p(a =人头,B=6) = 1/2 ✕ 1/6 = 1/12。

注意,我写的是 P(A =正面,B=6)。事件之间的逗号是联合概率的简写(你会在文献中看到这一点)。

应该注意的是,在许多真实世界的场景中,事件被假定为独立的,即使实际情况并非如此。这主要是因为它使数学变得简单多了。好处是结果通常非常有用。朴素贝叶斯方法可能是数据科学中最常见的例子,通常在文本分类问题中给出相当好的结果。

‘或’规则

根据“和”法则,我们必须将个体概率相乘。当我们处于“或”的情况时,我们必须将个体概率相加,然后减去交集。数学上我们把这个写成 P(AB)= P(A)+P(B)-P(AB)。你会问我们为什么要这么做?这又回到了上图中的维恩图。如果我们把 A 的圆和 B 的圆相加,那就意味着我们把交点加了两次。因此,我们需要减去交集。

所以让我们改变上面的例子,找出掷出 6 或者硬币正面朝上的概率。这就是 P(硬币落地人头或滚动 A 6)= P(A =人头B = 6)= 1/2+1/6-1/12 = 6/12+2/12-1/12 = 7/12

请注意,符号被称为“并集”,用于“或”场景。

有些时候我们不需要减去交集。当维恩图中的两个圆不重叠时,就会发生这种情况。当两个事件的圆圈不重叠时,我们说这些事件是互斥的。这暗示交集为零,数学上写成 P(A ∩ B) = 0。让我们做一个涵盖这种情况的例子。假设我们掷骰子,我们想知道掷出 5 或 6 的概率。这些事件是互斥的,因为我不能掷出 5 和 6。因此,它们在维恩图中的圆不重叠。所以掷出 5 或者 6 的概率等于 1/6 + 1/6 = 2/6 = 1/3(我们什么都没减去)。

包裹

谢谢你能走到这一步。如果有的话,我希望我的漫谈对你来说是可以理解的,即使你没有学到任何新的东西。如果有任何不清楚的地方或者我在上面犯了一些错误,请随时留下评论。在本系列的后续文章中,我将介绍一些更高级的概念。下一篇文章将解释最大似然,并通过一个例子来说明。

概率概念解释:边缘化

原文:https://towardsdatascience.com/probability-concepts-explained-marginalisation-2296846344fc?source=collection_archive---------0-----------------------

介绍

在这篇文章中,我将解释边缘化的概念,并通过一个例子来解决一个相当简单的最大似然问题。这篇文章需要一些基本概率概念的知识,你可以在我这个系列的介绍性博客文章中找到解释。

什么是边缘化

边缘化是一种需要对一个变量的可能值求和来确定另一个变量的边际贡献的方法。这个定义听起来有点抽象,所以让我们试着用一个例子来说明这一点

假设我们对天气如何影响英国人的快乐感兴趣。我们可以用数学方法把它写成 P(幸福|天气),即在给定天气类型的情况下,某人幸福水平的概率是多少。

假设我们有测量某人快乐程度的设备和定义,还记录了英格兰和苏格兰的天气情况。现在,苏格兰人总体上比英格兰人更幸福是可行的。问题是,人们总是有一个国籍,所以我不能在测量中摆脱它。所以我们实际测量的是 P(幸福,国家|天气),也就是说,我们同时在看幸福和国家。

边缘化告诉我们,如果我们对所有国家的可能性求和,就可以计算出我们想要的数量(记住,英国由 3 个国家组成:英格兰、苏格兰和威尔士),即 P(幸福|天气)= P(幸福,国家=英格兰|天气)+ P(幸福,国家=苏格兰|天气)+ P(幸福,国家=威尔士|天气)。

就是这样!边缘化告诉我们,只要把一些概率相加,就能得到想要的概率量。一旦我们计算出我们的答案(它可以是单个值或分布),我们就可以得到我们想要的任何属性(推论)。

相关定义

如果这个概念听起来与你相似,但你以前没有听说过边缘化,这可能是因为你听说过它被称为一个不同的名字。有时这种方法被称为,即剔除有害变量。积分本质上是一个变量“相加”的另一种说法,你正在求和的变量被称为“有害变量”。因此,在上面的示例中,“country”变量是有害变量。

如果您正在使用概率图形模型,那么边缘化是一种您可以执行精确推理的方法(即,您可以从您感兴趣的分布中写下精确的数量,例如,可以从分布中精确计算出平均值)。在这个语境中边缘化是一种方法,有时与 同义使用,变量消去。

例子:骰子未知的骰子游戏。

我将仔细阅读世界上最好的数学和计算晶体学家之一艾利·j·麦考伊写的精彩的喜欢可能性论文中给出的例子。如果你正在寻找关于骰子的各种最大似然概念(如对数似然、中心极限定理等)的很好的介绍。)那么我强烈推荐。

假设我们有四个骰子:4 面骰子,6 面骰子,8 面骰子和 10 面骰子(如下所示)。

The 4 dice that we have. From left to right: 4-sided die, 6-sided die, 10-sided die and an 8-sided die

游戏

  • 我把一个六面和一个八面的骰子放在一个红色的盒子里,一个四面和十面的骰子放在一个蓝色的盒子里。
  • 我从红色和蓝色的盒子中随机选择一个骰子,并把它们放入黄色的盒子中。
  • 我从黄色盒子里随机选择一个骰子,掷骰子,告诉你结果。

玩游戏后,我们被告知结果是 3。我们要回答的问题是:骰子最初最有可能来自红盒子还是蓝盒子?

Graphic depiction of the game described above

接近解决方案

为了解决这个问题,我们必须计算出当我们掷出 3, L (box=red| dice roll=3)时,骰子从红色盒子中取出的可能性,以及当我们掷出 3, L (box=blue| dice roll=3)时,骰子从蓝色盒子中取出的可能性。无论哪个概率最高,都是我们给出的答案。

那么我们如何计算L(box =红色|掷骰子=3)和L(box =蓝色|掷骰子=3)?

首先要知道的是,可能性和概率通过以下等式相关联:

关于这一点的解释,请参见我关于最大似然的帖子的结尾。

这意味着,可能性, L (box=red| dice roll=3),相当于在骰子来自红色盒子的情况下,找出掷出 3 的概率,即 P (dice roll=3 | box=red)。同样L(box =蓝色|掷骰子=3) = P (掷骰子= 3 | box =蓝色)。

让我们假设我们已经从红盒子中选择了一个骰子。它可以是六面或八面模具。我有 50%的机会选择两个死者中的一个。假设我选择六面骰子。也就是说,我必须从黄色盒子中选择六面骰子,然后掷出 3。因此这种情况下的概率由下式给出:

只是为了说明一下。“1/2”来自于我有 50%的机会从红色盒子中随机选择 6 面骰子,因为它也包含 8 面骰子。“1/6”是因为我有一个 6 面骰子,因此有 1/6 的机会掷出 3。

请注意,答案中没有包含任何关于从黄色盒子中挑选 6 面骰子的概率的内容。这是因为在这种情况下,从黄色盒子中挑选六面骰子的概率是 1(您可能认为是 1/2,因为黄色盒子包含 6 面骰子和我从蓝色盒子中挑选的任何骰子)。这是因为我们正在计算从 6 面骰子掷出 3 的条件概率,假设骰子来自红色盒子。因此,在另一个场景中,我们在黄色框中选择另一个骰子是不可能的,因为另一个骰子最初来自蓝色框。给定我们从红框中选择的条件,我们只能从黄框中选择 6 面骰子,因此从黄框中选择 6 面骰子的概率是 1。

以类似的方式,我们可以计算结果为 3 的概率,我们实际上已经从红盒子中挑选了 8 面骰子。这一次的概率是

我们现在已经完成了计算骰子来自红盒子的概率所需的几乎所有工作。记住,红盒子只包含 6 面和 8 面骰子,所以我们要做的就是找出骰子是 6 面还是 8 面的概率。从的介绍文章中,我们知道在的情况下,我们需要将概率相加。因此,骰子来自红盒子的概率是

对于那些不熟悉上式中数字之间的“wavey”等号的人来说,它的意思是“大约等于”。真正的答案是 0.1458333333……(3 永远继续下去,我们说这是 3 的循环),但我变懒了,只给出了小数点后 3 位的答案(即四舍五入到小数点后 3 位)。为了明确我们没有给出准确答案的事实,我们通常使用“wavey”等号。

我们可以对蓝盒子做同样的计算

骰子最初来自蓝盒的概率更高,因此使用最大似然法,我们可以得出骰子最有可能来自蓝盒的结论。

那个例子中的边缘化在哪里?

对于那些观察力非常敏锐的人来说,你会注意到我在那个例子部分一次都没有使用“边缘化”这个词。这是因为我想让你直观地理解如何计算从盒子中挑选骰子的概率。

如果你看上面蓝框的等式,你会看到我们把所有可能性的概率加在一起,即挑选 4 面骰子和 10 面骰子。这是边缘化!我们对讨厌的变量(骰子)求和。注意,在那个游戏中,我们根本没有观察到我们选择的骰子,我们也不需要观察!我们需要知道的只是结果(掷骰子= 3)和骰子的所有可能值。这就是它如此强大的原因。我们可以计算出我们从未观察到的事情的概率。只要我们知道有害变量的可能值,我们总是可以使用它来执行边缘化,并计算不同变量的分布。

注释

这是我让我们写一些更可怕的方程的部分,但是请耐心听我说,我会尽力让它变得容易理解。

让我们想想我们刚刚在示例中做了什么。我们从联合概率开始, P (掷骰子,骰子|盒子)(即掷骰子是 3,骰子是我们选择掷骰子的骰子,盒子是我们选择骰子的原始盒子;蓝色或红色)。一旦我们执行边缘化,我们就以条件概率结束, P (掷骰子|盒子)。这是边缘化的主要好处之一。我们可以从联合概率到条件概率。

事实上我们也可以从联合概率到边际概率。如果你看到边缘化的数学定义,这就是你会看到的典型形式。如果你还没看好数学定义,…你很幸运。你马上就要看到了。

大的 ol' ∑是懒惰的数学家符号,表示“把所有的东西加起来”,它下面的【y】告诉我们应该把什么加起来。所以等式是这样说的,“如果你想要 X 的边际概率(等号的左边),那么你需要把 Y 的每个可能结果的 X 和 Y 的联合概率加起来”

联合概率有时很难处理,所以我们可以使用概率中的一般乘法规则重写右边的联合概率,我在介绍性博客帖子中展示过。

最右边的等式是条件分布和边际分布的乘积,有时边际分布更容易计算。

正如我之前提到的,∑告诉我们“将一切相加”。我没有提到的是,只有当变量为“离散”时,才会使用特定符号。我的意思是,变量只能取有限数量的值。在前面的例子中,我们对离散的讨厌变量求和(例如,英国国家只能是英格兰、威尔士或苏格兰,骰子只有有限的结果数,例如 6 面的从 1 到 6)。但是离散值不一定是有限的。例如,它们可以是所有的正整数(即正整数),如 1、2、3、…。等等。

然而,当我们处理在给定范围内具有无限个可能值的变量时(例如,0 到 10 米之间的距离测量可以具有无限个值,例如 5 米、5.1 米、5.01 米、5.001 米、5.0001 米……等等),我们将这些变量称为“连续变量,并且我们不使用∑符号。相反,我们使用∫。这个符号仍然告诉我们,我们必须把所有的东西加起来,但是我们知道这个讨厌的变量是连续的,所以我们把边际化写成

这与上面离散变量情况下的边际化方程意思相同。结尾的“d y ”告诉我们要积分什么(“积分”是我们在处理连续变量时对“加法”的称呼)。

“d y 是必要的原因是,如果我们不声明它,我们要积分的东西并不总是很明显。考虑干扰变量是围绕圆的角度的情况。我们知道角度在 0 到 360 度之间,或者更专业地说,我们喜欢用弧度来代替我们所说的从 0 到 2π的角度

Source: Wikipedia. Radians in a circle

所以我们可能会想写

我们知道我们需要对从 0 到 2π的值进行积分,但是我们是对 X 的值进行积分还是对 Y 的值进行积分呢?全世界的数学家都渴望为上述暴行打我一巴掌。

为了解决这个问题,我们将“d y 放在最后,以明确我们正在对 0 和 2π之间的 Y 值进行积分,这意味着我们也知道答案是 X 上的边际分布(如下)。

对那些感兴趣的人来说,积分从 0 到 2π的角度是我们在 X 射线晶体学中必须做的事情,这是我博士学位的领域,因为有一个叫做相位问题。这基本上是一个问题,我们不能在实验中测量“相位”,而相位可以像角度一样被数学处理。因此,为了计算我们观察到的数据的理论分布,我们必须忽略这些阶段。

亚当·凯莱赫在他的因果包中使用边缘化来消除混杂变量的影响。他还使用一般乘法法则,把边际化写成我们上面讨论过的条件分布和边际分布的乘积。你可以在他的博客中读到。

结束语

概率的链式法则

在上面的计算中,我们实际上使用了一个相当普通的概率程序,甚至没有意识到这一点。我们使用的结果是概率的链式法则(不要与微分的链式法则混淆)。它指出

它允许我们将联合概率(左侧)写成条件概率和边际概率(右侧)的乘积

这在计算联合分布时经常用到,因为正如我们已经提到的,确定条件概率和边际概率更容易。

要查看我们在哪里使用了上面的结果,请记住我们使用了等式

比较这些等式,我们可以让 A =骰子滚动,B =骰子,C =盒子。这意味着我们可以把上面等式的左边写成

现在让我们来理解这些。

  • P (掷骰子= 3|骰子= 6 面,盒子=红色)是我们掷出 3 的概率,假设我们拿起 6 面骰子,它在红色盒子里。这等于 1/6。
  • P (骰子= 6 面|盒子=红色)是我们从红色盒子中选择 6 面骰子的概率。这等于 1/2。

因此,我们得到 1/2 ✕ 1/6,这正是我们在这个例子中通过直觉确定的结果。

这里我们用三个变量展示了链式法则。如果你看看维基百科上链式法则的定义(看起来更可怕),你会看到它对于四个变量和无限多个变量的样子。

这看起来很可怕,但想法是一样的。我们在左边有一个联合概率分布,我们想把它写成右边的条件概率和边际概率的乘积。

用于贝叶斯推理

如果你读了我以前关于贝叶斯推理的文章,你会知道贝叶斯定理的模型形式被写成

我提到过,我们经常不计算分母 P(数据),也称为归一化常数,因为在许多情况下它可能太难计算,我们并不总是需要它。

在某些情况下,我们可以精确计算,边缘化会有所帮助。如果我们将边缘化方程写成与上述“符号”部分中连续变量情况相同的形式,我们得到

显而易见,我们通过所有可能的参数值对右侧进行积分。在某些情况下,我们可以精确地或近似地计算这个表达式,这样我们就可以得到一个归一化的后验分布。

再次感谢你能走到这一步。我知道这篇文章包含了很多数学知识,但我希望它有意义。如果有什么不清楚的,你想让我写的或者我可以改进的地方,请不要犹豫让我知道。

谢谢大家!

概率概念解释:最大似然估计

原文:https://towardsdatascience.com/probability-concepts-explained-maximum-likelihood-estimation-c7b4342fdbb1?source=collection_archive---------0-----------------------

介绍

在这篇文章中,我将解释什么是参数估计的最大似然法,并通过一个简单的例子来演示这种方法。有些内容需要基本概率概念的知识,如联合概率的定义和事件的独立性。我已经写了一篇关于这些先决条件的博文,所以如果你认为你需要复习,请随意阅读。

什么是参数?

通常在机器学习中,我们使用一个模型来描述产生观察到的数据的过程。例如,我们可以使用随机森林模型来分类客户是否会取消服务订阅(称为流失建模),或者我们可以使用线性模型来预测公司将产生的收入,具体取决于他们可能在广告上花费多少(这将是线性回归的一个例子)。每个模型都包含自己的一组参数,这些参数最终定义了模型的外观。

对于线性模型,我们可以写为 y = mx + c 。在本例中, x 可以代表广告支出,而 y 可能是产生的收入。 mc 是该型号的参数。这些参数的不同值将产生不同的线条(见下图)。

Three linear models with different parameter values.

所以参数定义了模型的蓝图。只有为参数选择了特定的值,我们才能得到描述给定现象的模型的实例。

最大似然估计的直观解释

最大似然估计是一种确定模型参数值的方法。发现参数值使得它们最大化由模型描述的过程产生实际观察到的数据的可能性。

上面的定义听起来可能仍然有点晦涩,所以让我们通过一个例子来帮助理解这一点。

假设我们从某个过程中观察到了 10 个数据点。例如,每个数据点可以代表学生回答一个特定的考试问题所需的时间长度(以秒为单位)。下图显示了这 10 个数据点

The 10 (hypothetical) data points that we have observed

我们首先必须决定我们认为最能描述数据生成过程的模型。这部分很重要。至少,我们应该对使用哪种模型有一个好的想法。这通常来自于一些领域的专业知识,但我们不会在这里讨论。

对于这些数据,我们假设数据生成过程可以用高斯(正态)分布来充分描述。对上图的直观观察表明,高斯分布似乎是合理的,因为这 10 个点中的大部分都集中在中间,只有少数点分散在左右两边。(在只有 10 个数据点的情况下匆忙做出这种决定是不明智的,但考虑到这些数据点是我生成的,我们会照做的)。

回想一下,高斯分布有两个参数。平均值μ和标准差σ。这些参数的不同值会产生不同的曲线(就像上面的直线一样)。我们想知道哪条曲线最有可能产生我们观察到的数据点?(见下图)。最大似然估计是一种方法,可以找到μ和σ的值,从而得到最符合数据的曲线。

The 10 data points and possible Gaussian distributions from which the data were drawn. f1 is normally distributed with mean 10 and variance 2.25 (variance is equal to the square of the standard deviation), this is also denoted f1 ∼ N (10, 2.25). f2 ∼ N (10, 9), f3 ∼ N (10, 0.25) and f4 ∼ N (8, 2.25). The goal of maximum likelihood is to find the parameter values that give the distribution that maximise the probability of observing the data.

生成数据的真实分布是 f1 ~ N(10,2.25),即上图中的蓝色曲线。

计算最大似然估计

现在我们对什么是最大似然估计有了直观的理解,我们可以继续学习如何计算参数值。我们找到的值称为最大似然估计(MLE)。

我们将再次用一个例子来证明这一点。假设我们这次有三个数据点,并且我们假设它们是从一个由高斯分布充分描述的过程中产生的。这几点是 9,9.5,11。我们如何计算高斯分布μ和σ的参数值的最大似然估计?

我们要计算的是观察所有数据的总概率,即所有观察数据点的联合概率分布。要做到这一点,我们需要计算一些条件概率,这可能会变得非常困难。所以在这里我们要做第一个假设。假设每个数据点独立于其他数据点生成。这个假设使数学变得容易多了。如果事件(即生成数据的过程)是独立的,那么观察所有数据的总概率是单独观察每个数据点的乘积(即边际概率的乘积)。

观察由高斯分布产生的单个数据点 x,的概率密度由下式给出:

符号P(x;μ,σ) 是为了强调它后面出现的符号是概率分布的参数。因此,它不应该与条件概率(通常用垂直线表示,例如 P(A| B))混淆。

在我们的例子中,观察三个数据点的总(联合)概率密度由下式给出:

我们只需计算出导致给出上述表达式最大值的 μσ 的值。

如果你在数学课上学过微积分,那么你可能会意识到有一种技术可以帮助我们找到函数的最大值(和最小值)。这叫做分化。我们要做的就是找到函数的导数,将导函数设置为零,然后重新排列方程,使感兴趣的参数成为方程的主题。瞧,我们就有了参数的最大似然值。我现在将介绍这些步骤,但我将假设读者知道如何对常见函数进行微分。如果你想要更详细的解释,请在评论中告诉我。

对数可能性

上面的总概率表达式实际上很难区分,所以几乎总是通过取表达式的自然对数来简化。这绝对没问题,因为自然对数是一个单调递增的函数。这意味着,如果 x 轴上的值增加,y 轴上的值也会增加(见下图)。这很重要,因为它确保了概率对数的最大值出现在与原始概率函数相同的点上。因此,我们可以用更简单的对数似然代替原始似然。

Monotonic behaviour of the original function, y = x on the left and the (natural) logarithm function y = ln(x). These functions are both monotonic because as you go from left to right on the x-axis the y value always increases.

Example of a non-monotonic function because as you go from left to right on the graph the value of f(x) goes up, then goes down and then goes back up again.

对原始表达式进行记录可以得到:

这个表达式可以用对数定律再次简化,得到:

这个表达式可以求导以找到最大值。在这个例子中,我们将找到均值μ的极大似然估计。为此,我们取函数对μ的偏导数,给出

最后,将等式左侧设置为零,然后重新排列μ,得出:

这就是μ的最大似然估计。我们也可以用σ做同样的事情,但我将把它留给有兴趣的读者做练习。

结束语

最大似然估计总能以精确的方式求解吗?

是简短的回答。更有可能的是,在现实世界中,对数似然函数的导数在分析上仍然是难以处理的(即,手动区分函数太难/不可能)。因此,像期望最大化算法这样的迭代方法被用于寻找参数估计的数值解。尽管如此,总体想法还是一样的。

那么为什么是最大似然而不是最大概率呢?

这只是统计学家的迂腐(但有充分的理由)。大多数人倾向于交替使用概率和可能性,但统计学家和概率理论家区分两者。通过查看等式,可以更好地找出混淆的原因。

这些表达式是相等的!那么这意味着什么呢?我们先定义一下 P(数据;μ,σ) ?表示“用模型参数μ和σ观察数据的概率密度”。值得注意的是,我们可以将其推广到任何数量的参数和任何分布。

另一方面 L(μ,σ;data) 表示“给定我们观察到的一堆数据,参数μ和σ取某些值的可能性。”

上面的等式表明,给定参数的数据的概率密度等于给定数据的参数的似然性。但是,尽管这两个东西是相等的,但可能性和概率密度从根本上提出了不同的问题——一个是关于数据的问题,另一个是关于参数值的问题。这就是为什么这种方法被称为最大似然而不是最大概率。

最小二乘最小化何时与最大似然估计相同?

最小平方最小化是机器学习中估计模型参数值的另一种常用方法。事实证明,当模型被假设为高斯型时,MLE 估计相当于最小二乘法。如需更深入的数学推导,请查看这些幻灯片。

通过理解它们的目标,我们可以直观地解释这两种方法之间的联系。对于最小二乘参数估计,我们希望找到使数据点和回归线之间的总平方距离最小的线(见下图)。在最大似然估计中,我们希望最大化数据的总概率。当假设高斯分布时,当数据点越接近平均值时,就找到了最大概率。由于高斯分布是对称的,这相当于最小化数据点和平均值之间的距离。

Regression line showing data points with random Gaussian noise

如果有任何不清楚的地方或者我在上面犯了一些错误,请随时留下评论。在下一篇文章中,我计划介绍贝叶斯推理以及它如何用于参数估计。

感谢您的阅读。

概率概念讲解:概率分布(导论第 3 部分)

原文:https://towardsdatascience.com/probability-concepts-explained-probability-distributions-introduction-part-3-4a5db81858dc?source=collection_archive---------1-----------------------

在我的第一篇和第二篇介绍性文章中,我介绍了符号、基本概率定律和公理。这些都是让数学家兴奋的事情。然而,当我们使用概率分布时,概率论在实践中经常是有用的。

概率分布被用于许多领域,但我们很少解释它们是什么。通常假设读者已经知道了(我假设的比我应该假设的更多)。所以我将在这篇文章中解释它们是什么。

什么是概率分布?

回想一下,随机变量的值是随机事件的结果(如果这对你没有任何意义,请参阅第一篇介绍文章)。例如,随机变量可能是掷骰子或掷硬币的结果。

一个 概率分布 是一个随机变量的所有可能结果及其对应概率值的列表。

举一个具体的例子,这里是一个公平的 6 面骰子的概率分布。

The probability distribution for a fair six-sided die

明确地说,这是一个有限支持的离散单变量概率分布的例子。这有点拗口,所以让我们试着把这句话分解并理解它。

这意味着如果我选择任何两个连续的结果。我找不到介于两者之间的结果。例如,如果我们认为 1 和 2 是掷出六面骰子的结果,那么我不能有介于两者之间的结果(例如,我可以有 1.5 的结果)。在数学中,我们会说结果列表是可数的(但我们不要沿着定义和理解可数和不可数集合的道路走下去。变得很奇怪)。你大概能猜到当我们得到连续概率分布时,情况就不再是这样了。

单变量= 表示我们只有一个(随机)变量。在这种情况下,我们只有掷骰子的结果。相反,如果我们有不止一个变量,那么我们说我们有一个多元分布。在我们有两个变量的特定情况下,我们经常说这是一个二元分布

这意味着结果的数量是有限的。支持本质上是定义了概率分布的结果。所以我们例子中的支撑是。一、二、三、四、五、六。由于这不是无限数量的值,这意味着支持是有限的。

函数介绍

为什么我们要讨论函数?

在上面滚动六面骰子的例子中,只有六种可能的结果,所以我们可以在表格中写下整个概率分布。在许多情况下,结果的数量可能要大得多,因此写一个表格会很乏味。更糟糕的是,可能的结果的数量可能是无限的,在这种情况下,祝你好运写一张表。

为了解决为每个分布写一个表的问题,我们可以定义一个函数来代替。该函数允许我们简洁地定义概率分布

因此,让我们首先定义一个函数,然后我们将移动到用于概率分布的函数。

什么是函数?

在非常抽象的层面上,函数是一个接受输入并返回输出的盒子。在绝大多数情况下,函数实际上必须对输入做一些事情,以使输出有用。

让我们定义我们自己的函数。假设这个函数接受一个数字作为输入,在输入的数字上加 2,然后返回新的数字作为输出。我们的函数(作为一个盒子)看起来像这样:

The abstract depiction of a function as a box that takes input and returns an output. In this case, the function adds 2 to the input.

因此,如果我们的输入是 5,我们的函数会将它加上 2,并返回输出 5+2 = 7。

函数符号

现在,为我们想要创建的每个函数绘制上面的图表是很乏味的。相反,我们使用符号/字母来表示图表,使其更加简洁。我们不用“输入”这个词,而是用“x”;我们不用“函数”这个词,而是用“f”;我们不用“输出”这个词,而是用“f(x)”。所以上图现在可以写成

Our function is written with symbols instead of words to make this more concise

这更好,但是,我们仍然有一个问题,我们必须画一个图来理解这个函数在做什么。但是我们是数学家,我们不想因为画一个盒子而浪费宝贵的能量,所以我们想出了一个更好的写函数的方法,这意味着我们不需要画任何东西。我们可以从数学上定义我们的函数为

Our function is now written without having to draw arrows and boxes.

这相当于上图,因为我们可以清楚地看到函数 f 的输入是 x,我们已经调用了函数 f,我们知道该函数将 2 加到输入中,并返回 x + 2 作为输出。

值得注意的是,函数和输入的字母选择是任意的。我可以说“a”是输入,我可以调用函数“add_two ”,所以我的函数是

Another way of writing the same function

而这个完全等同于上面的功能。

其中一个主要的收获是,通过一个函数,我们可以看到如何转换任何输入。对于函数 f(x) = x+ 2,我们知道如果输入是 x=10 或者输入是 x=10000 该怎么办。所以我们不需要像之前那样写下一个表格。

我想在这里说明的最后一点是,我们将要使用的函数只能将数字作为输入和输出。但是,函数可以把你喜欢的任何东西作为输入,输出你喜欢的任何东西(甚至不输出任何东西)。例如,我们可以用编程语言编写一个函数,将一个文本字符串作为输入,输出该字符串的第一个字母。以下是 Python 编程语言中此函数的一个示例

用图形表示函数

假设函数的主要好处之一是让我们知道如何转换任何输入,我们也可以使用这些知识来显式地可视化函数。让我们坚持我们的例子 f(x) = x+2。图形看起来是这样的:

Graphical representation of our function f(x) = x + 2

我们可以沿着底部的水平轴读取,因为我们的输入数字和左侧垂直轴上的相应数字是输出值 f(x) = x+2。例如,我们可以看到,代表函数的蓝线与垂直(白色)线在 x=1 处与水平(白色)线 f(x) = 3 相交的点相交。这从图形上说明了 f(1) = 1 + 2 = 3。

函数的参数

函数最重要的特征之一是参数。参数是你在函数中找到的数字,你不需要把它作为输入。在我们的例子中,f(x) = x + 2,数字“2”是一个参数,因为我们需要它来定义函数,但我们没有把它作为函数的输入。

参数之所以重要,是因为它们在决定输出时起着直接的作用。比如我们定义另一个函数 h(x) = x+3。函数 f(x) = x+2 和我们的新函数 h(x) = x+3 之间的唯一区别是参数的值(我们现在有了“3”而不是“2”)。这种差异意味着对于相同的输入,我们得到的输出是完全不同的。让我们用图表来看一下。

The difference between our functions f(x) = x + 2 and h(x) = x + 3

参数可以说是概率(分布)函数最重要的特征,因为它们定义了函数的输出,告诉我们随机过程中某些结果的可能性。在数据科学中出现的问题中,我们经常试图估计参数,我以前写过两种方法可以用来估计它们:最大似然估计和贝叶斯推断。

现在我们准备用函数的语言来讨论概率分布。

概率质量函数:离散概率分布

当我们使用概率函数来描述离散概率分布时,我们称之为概率质量函数(通常缩写为 pmf)。

记得在关于概率概念的第一篇介绍文章中,我们用大写字母 X 表示的随机变量的概率,取一个小写字母 X 表示的值,记为 P(X=x)。因此,如果我们使用掷骰子作为随机变量,我们可以将骰子落在数字 3 上的概率写成 P(X=3) = 1/6。

概率质量函数,我们称之为 f,返回一个结果的概率。因此,概率质量函数写为:

我知道这变得有点可怕和数学化,但是请原谅我。我们上面看到的等式说,概率质量函数“f”只是返回结果 x 的概率。

所以让我们回到公平的 6 面骰子的例子(你可能已经厌倦了这个例子)。概率质量函数 f 只返回结果的概率。因此掷出 3 的概率是 f(3) = 1/6。就是这样。

因为概率质量函数返回概率,所以它必须遵守我在之前的文章中描述的概率规则(公理)。也就是说,概率质量函数输出 0 和 1 之间的值,并且所有结果的概率质量函数(pmf)之和等于 1。数学上我们可以把这两个条件写成

我们已经看到,我们可以把离散概率分布写成表格和函数。我们也可以用图形来表示骰子滚动的例子

Graphical representation of the probability distribution for outcomes of rolling a fair six-sided die

离散概率分布示例:伯努利分布

一些概率分布出现得如此频繁,以至于它们被广泛研究并被命名。一种经常出现的离散分布叫做伯努利分布。它描述了有两种可能结果的过程的概率分布。这方面的一个例子是掷硬币,结果是正面或反面。

伯努利分布的概率质量函数为

这里,x 表示结果,取值为 1 或 0。所以我们可以说正面= 1,反面= 0。p 是表示结果为 1 的概率的参数。因此,在一个公平的硬币的情况下,正面或反面落地的概率是 0.5,我们将设置 p = 0.5。

通常我们想明确概率密度函数中包含的参数,所以我们写

请注意,我们使用分号来分隔输入变量和参数。

概率密度函数:连续概率分布

有时我们关心有连续结果的随机变量的概率。例子包括从人群中随机选取的成年人的身高,或者出租车司机在下一份工作之前必须等待的时间。对于这些例子,随机变量最好用连续概率分布来描述。

当我们用一个概率函数来描述一个连续的概率分布时,我们称之为概率密度函数(通常缩写为 pdf)。

概率密度函数在概念上比概率质量函数稍微复杂一些,但是不要担心,我们会实现的。我认为最简单的方法是从一个连续概率分布的例子开始,然后讨论它的性质。

连续概率分布示例:正态分布

正态分布可能是所有概率和统计中最常见的分布。它出现如此频繁的一个主要原因是由于中心极限定理。我们不会在这篇文章中深入探讨,但这里有一篇由卡森·福特撰写的名为“科学家需要知道的唯一定理数据”的好文章,它解释了什么是定理以及它与正态分布的关系。

正态分布的概率密度函数定义为

其中,参数(即分号后的符号)代表总体的均值μ(分布的中心点)和标准差σ(分布的分布程度)。

如果我们将平均值设为 0(μ= 0),标准差设为 1 (σ=1),那么我们得到的分布如下所示

Normal distribution with mean = 0 and standard deviation equal to 1

正态分布是一个具有无限支持度的连续单变量概率分布的例子。所谓无限支持,我的意思是我们可以计算负无穷大和正无穷大之间所有结果的概率密度函数值。在数学中,我们有时会说它被支撑在整实线上。

连续概率分布的性质

首先要注意的是,纵轴上的数字从零开始向上。这是一个概率密度函数必须遵守的规则。概率密度函数的任何输出值都大于或等于零。用数学术语来说,我们会说输出是非负的,或者用数学方法写成

然而,与概率质量函数不同,概率密度函数的输出是而不是概率值。这是一个非常重要的区别,其中一个我很抱歉忘记了。

为了从概率密度函数中得到概率,我们需要找到曲线下的面积。因此,从均值= 3、标准差= 1 的分布示例中,我们可以通过找到下图中所示的面积来确定结果介于 0 和 1 之间的概率

The area shaded is the probability of the outcome being between 0 and 1.

数学上我们可以这样写

我们可以把这个理解为“(左手边)0 和 1 之间的概率密度函数的积分等于随机变量的结果在 0 和 1 之间的概率(右手边)”。

请原谅我没有明确地介绍积分以及它们是如何工作的(在我的关于边缘化的帖子中,我对积分有一个简短的概念性介绍,但它没有教你如何计算它们)。如果你不知道它们,那么你现在需要知道的是,这是一种求曲线下面积的数学方法,在这种情况下,它给出了结果的概率。也许我需要写一个简短的系列来介绍微积分。

我们现在已经看到了概率密度函数的另一个性质。也就是说,两个结果之间的概率,比如‘a’和‘b’,是这两个点之间的概率密度函数的积分(这相当于找到由‘a’和‘b’点之间的概率密度函数产生的曲线下的面积)。数学上这是

请记住,我们仍然必须遵循概率分布规则,即所有可能结果的总和等于 1 的规则。如果我们把范围从“负无穷大”一直设置到“正无穷大”,我们就可以涵盖所有可能的值。因此,要使函数成为概率密度函数,以下条件必须成立

这表示负无穷大和正无穷大之间曲线下的面积等于 1。

关于连续概率分布,需要知道的一件重要事情(从概念上来说,这可能很难理解)是,随机变量等于特定结果的概率是 0。例如,如果我们试图得到结果等于数字 2 的概率

这可能在概念上看起来很奇怪,但是如果你理解微积分,那么它应该会更有意义。我不打算在这篇文章中讨论微积分。相反,我想让你们从这个事实中得到的是,我们只能谈论发生在两个值之间的概率。或者我们可以问一个结果大于或小于特定值的概率。我们不能询问一个结果等于特定值的概率。

眼尖的读者可能已经注意到,我使用了“小于()”符号,而不是“小于或等于(≤)”和“大于或等于(≥)”符号。对于连续的概率分布,这实际上并不重要,因为它们是相同的。我的意思是

所以随机变量在 a 和 b 之间取值的概率等于它在 a 和 b 之间取值的概率。

参数的重要性

我们看到参数值可以改变函数的输出值,概率分布也一样。

Two normal distributions with different parameters give completely different probability outcomes.

在上图中,我们绘制了两个正态分布的概率密度函数。蓝色分布的参数值μ=0,σ=1,而红色分布的参数值μ=2,σ=0.5。

现在可以更清楚地看到为什么使用错误的参数值会产生与您预期的结果相差很大的结果。

摘要

哇!那比我预期的要长得多。让我们总结一下要点:

  • 概率分布是结果及其相关概率的列表。
  • 我们可以用表格写小分布,但是用函数概括大分布更容易。
  • 代表离散概率分布的函数称为概率质量函数
  • 代表连续概率分布的函数称为概率密度函数。
  • 代表概率分布的函数仍然必须遵守概率规则
  • 概率质量函数的输出是概率,而由概率密度函数产生的曲线下的面积代表概率
  • 概率函数的参数在定义随机变量结果的概率中起着核心作用。

我最初想在这篇文章中讨论多元分布,但它太长了,所以我们将在以后的文章中讨论它。

现在你已经对概率分布有了基本的了解,看看肖恩·欧文的这篇伟大的文章,它涵盖了数据科学中常用的概率分布。他出色地解释了为什么数据科学中会出现每种分布,所以这是对概率分布更实际的观察。更详细的概率分布列表,请查看维基百科页面(列表很长)。

一如既往,感谢你读到这里。我希望这是有用的,你从中学到了一些东西。请随时留下您的意见、建议和问题。

概率概念讲解:概率规则(导论第二部分)

原文:https://towardsdatascience.com/probability-concepts-explained-rules-of-probability-introduction-part-2-2a9d5a1a9df4?source=collection_archive---------6-----------------------

当我写本系列的第篇介绍性文章时,我介绍了一些基本的概率概念(边际概率、条件概率和联合概率、独立性和互斥性,以及组合概率的“与”和“或”规则)。然而,我错过了一些其他的基本规则,我认为这些规则是理所当然的,并假设读者在我写后续文章时已经知道了。

因此,在这篇文章中,我将介绍概率论中的一些核心规则。如果你是这方面的新手,那么我推荐你在这里浏览一下的第一篇介绍性文章,这样你就可以熟悉符号和一些定义。

概率规则(公理)

当数学家探索新的数学领域时,他们通常从一套定义他们能做什么的规则开始。这有点像是第一个发明足球(soccer)的游戏,并制定规则说'只有 11 名球员在球场上为球队效力,你不能用手触球,越位规则等'。一旦制定了这些规则,球员和经理们就可以自由地探索和创造新的球技和花式团队。

概率论(以及一般的数学)没有什么不同。我们把这些规则叫做 公理 。一旦规则被设定,数学家们就会疯狂地探索新的定理和结果。只要坚持公理,那么你就可以做你想做的事情

让我们过一遍概率公理。

公理 1

第一条规则规定事件发生的概率大于或等于零。其实我们可以更进一步说,事件发生的概率在 0 到 1(含)之间。

让我们用数学方法来写。如果我们说一个事件的概率在 0 和 1 之间(包括 0 和 1 ),那么我们可以这样写

当我说“事件”时,我的意思是“发生了一些事情”。例如,我们可能在谈论明天的天气,而结果可能是明天下雨。所以明天下雨的概率可能是 0.5。数学上,我们把它写成

有可能把结果归入一个事件,说一个事件是明天下雨或下雪的结果。这样,一个 事件实际上就是一个结果的集合。

公理 2

这条规则规定至少一个可能结果发生的概率是 1。我冒昧地进一步说,如果你把所有可能结果的概率加起来,你会得到概率 1。核心数学家会纠缠我,因为围绕这个有一些警告,但对于我们将遇到的大多数情况,第二个声明将成立。

让我们以滚动一个公平的 6 面骰子为例。如果我掷骰子,那么六个结果中有一个是可能的。骰子会落在 1,2,3,4,5 或 6 上。因此我至少得到其中一个结果的概率是 1。概率等于 1 意味着我们确定

我的第二个观点仍然成立。有六分之一的可能性,掷出其中任何一个的概率是 1/6。所以如果我们把得到 1,2,3,4,5 或 6 的概率加起来,我们得到 1。见下文

P(骰子= 1) + P(骰子= 2) + P(骰子= 3) + P(骰子= 4) + P(骰子= 5) + P(骰子= 6)= 1/6+1/6+1/6+1/6+1/6+1/6+1/6 = 6/6 = 1。

写出总和中的所有项是非常乏味的,特别是当你有数百个结果时,所以为了简化它,数学家会写

是的,那个看起来像“E”的大符号只是告诉我们把东西加起来,它上面和下面的东西告诉我们从哪里开始和结束。所以这里说“从 i=1 开始,一直到 I = 6”

因此,我们现在可以将语句“所有可能结果的个体概率相加将等于 1”数学上为:

我们用一个特殊的术语来代替“所有可能的结果”——它被称为样本空间。因此,6 面骰子的结果 1、2、3、4、5 和 6 实际上是样本空间。数学上,样本空间用ω表示。所以我们也可以用数学方法把上面写为

公理 3

这条公理可能是最难理解的,但是我在介绍互斥性的文章中提到了它。我先陈述公理,然后举例说明。

公理说如果两个事件是互斥的(即两个事件不能同时发生),那么其中一个事件发生的概率等于它们发生的个体(边际)概率之和。我告诉过你这很令人困惑。让我们用第一篇介绍性文章中的例子来澄清这一点。

假设我们掷出一个 6 面骰子,我们想知道掷出 5 或 6 的概率。这些事件是 互斥 因为我不能同时掷出一个 5 和一个 6。所以掷出 5 或 6 的概率等于掷出 5 的概率加上掷出 6 的概率:1/6 + 1/6 = 2/6 = 1/3。

数学上我们可以把这个公理写成

假设结果 1 和结果 2 是互斥的(它们不可能同时发生)。

我知道这篇文章很可能比我以前的文章更枯燥,考虑到我在这个系列中的其他文章也都是关于数学的,我认为覆盖一些理解更高级的东西经常需要但却被错误假设的基础知识是很重要的。

下一篇文章也将是介绍性的,我的目的是解释什么是概率分布,以及你可以得到的不同类型(离散、连续、单变量和多变量)。

感谢阅读

使用 Python 和 Numpy 的加权抛硬币游戏中的概率

原文:https://towardsdatascience.com/probability-in-a-weighted-coin-flip-game-using-python-and-numpy-bc1686c49a35?source=collection_archive---------0-----------------------

本周一个简短有趣的问题:

两个玩家正在玩一个游戏,从玩家 1 开始,他们掷一枚不一定是公平的硬币。第一个抛头的人获胜。一枚硬币正面朝上的概率是 p 。参与人 1 赢得比赛的概率是多少?

Photo by Andriyko Podilnyk on Unsplash

我们可以用 python 中的一个简单函数来探讨这个问题。让我们编写一个接受两个参数的函数:1。)要玩的游戏的数量,以及 2。)抛硬币导致正面的概率(设置为默认值 0.5 或 50%)。

我们姑且称这个函数为“P1 _ 赢 _ 概率 _ 加权 _ 硬币 _ 游戏”

我们可以用下面的代码模拟这个游戏:

import numpy as npdef P1_win_prob_weighted_coin_game(num_games, prob_heads=.5): player_one_wins = 0 for n in range(0,num_games): num_flips = 0 win = 0while win == 0: turn = np.random.uniform(0,1) num_flips += 1 if turn <= prob_heads: if num_flips % 2 != 0: player_one_wins += 1 win += 1 return float(player_one_wins)/float(num_games)

现在,让我们一步一步地简单介绍一下。

import numpy as npdef P1_win_prob_weighted_coin_game(num_games, prob_heads = 0.5): player_one_wins = 0

我们从导入 numpy 开始,因为我们可以利用它的随机选择功能来模拟这个游戏的抛硬币机制。

我们定义函数的名称,并指定两个参数。我们将默认正面概率设置为 0.5,以防我们只是想使用公平硬币指定一些游戏来查看结果。显然,我们可以在这里随意输入自定义概率。

我们还为玩家 1 赢得的游戏数量设置了一个全局计数器,每轮模拟从 0 开始。

 for n in range(0,num_games): num_flips = 0 win = 0while win == 0: turn = np.random.uniform(0,1) num_flips += 1

现在,对于指定模拟次数(例如,range(0,num_games ))的每场游戏,我们将从零开始计算掷硬币的次数。这既能记录游戏进行了多长时间,也能帮助我们在一次正面朝上的情况下确定谁是赢家。

我们还指定了一个获胜条件“win ”,它将帮助我们知道游戏何时完成。当 win 仍然等于零时,玩家继续掷硬币。每“转”一次构成硬币的一次翻转,它是在 0 和 1 之间随机选择的十进制值。每走一个回合,我们的 num_flips 计数器就加一。

 if turn <= prob_heads: if num_flips % 2 != 0: player_one_wins += 1 win += 1

如果随机选择的“回合”值小于或等于我们设置的“prob_heads”值,我们认为这是一个获胜条件。

我们可以这样理解:如果翻转头部的概率是 0.6,那么 0 和 1 之间的 60%的值可以被解释为头部翻转(例如,0.0 和 0.6 之间的所有值)。

一旦满足获胜条件,我们就检查硬币被抛了多少次。因为参与人 1 总是第一个掷硬币,我们知道奇数次掷硬币意味着参与人 1 是最后一个走的,因此是赢家。如果玩家 1 赢了游戏,我们在函数的顶部给我们的玩家 1 赢计数器加 1。我们还将“win”的值更改为 1.0,这将中断当前游戏,并在预设的模拟次数内开始下一个游戏。

 return float(player_one_wins)/float(num_games)

一旦所有模拟运行完毕,该函数将返回玩家 1 赢得的游戏数除以所玩游戏的总数。这将表示为十进制的获胜百分比。

好吧!现在我们已经写好了函数,让我们用一枚硬币玩 50,000 次游戏,看看会有什么结果:

P1_win_prob_weighted_coin_game(50000)0.66848

在超过 50,000 场比赛中,我们看到一号玩家有明显的优势。事实上,玩家 1 有大约 2/3 的机会因为先抛硬币而赢得游戏,即使使用公平硬币。

如果我们调整硬币正面朝上的概率呢?如果硬币有 75%的机会正面朝上呢?

P1_win_prob_weighted_coin_game(50000, .75)0.80066

在 75%的抛硬币中,一个有重量的硬币朝上,玩家 1 有 80%的机会获胜。

如果我们真的降低头部出现的可能性呢?比方说,如果正面只出现 1%的几率呢?

P1_win_prob_weighted_coin_game(50000, .01)0.50498

只有当我们大幅度降低正面朝上的可能性时,两个玩家才有大致相同的获胜机会。

有趣的东西!你可以随意摆弄这个函数,看看不同的模拟次数和正面概率如何影响玩家 1 获胜的可能性。

感谢阅读!

概率第一部分:每个人的概率。

原文:https://towardsdatascience.com/probability-part-1-probability-for-everyone-a-s-4fbc9dcc2f80?source=collection_archive---------3-----------------------

受我正在上的一门概率论课程的启发,这篇博客试图在直观的层面上解释概率数学理论的基础。顾名思义,这篇文章是为每个人准备的,不管他的数学水平和能力如何。将会有一些数学,但是请随意跳过这些部分。重要的东西出现在数学之间。

如果你正在读这篇文章,那么在某个时候你已经遇到了机遇。机遇与自然交织在一起,就像行星围绕太阳旋转,或者我们的遗传密码解开并从一代转化到下一代。但与宇宙运动定律不同,机会是不确定的。每次你玩掷骰子的游戏,或者出门前忘记查看天气,或者点击音乐流媒体服务上的下一步,你都是在赌运气。这一切都无法确定宇宙将会扮演什么角色。

正如我们所知,机遇是指某件事情发生的可能性——比如你掷骰子,或者你回家的路上阳光灿烂。概率是对某件事情发生的可能性的度量,即你掷出 6 的概率是 1/6(当然假设骰子是你所期望的)。

在日常生活中,概率是我们试图预测自然,让我们面对它,人类储存了什么的最佳猜测。例如,你可能想知道今天你会有三个看起来很棒的甜甜圈,裹着糖屑(就像上面的一样)。

概率论是我们测量宇宙中不确定性的尝试。

这是一个宇宙如何发挥作用的完美例子。当我今天早上开始写这篇文章时,阳光灿烂。一整天都是这样,除了在回家的路上,你瞧,一片失控的乌云散开了。出乎意料!

对机会和概率的数学研究可以追溯到 16 世纪的意大利和法国。在此期间,文艺复兴时期的数学家杰拉尔莫·卡尔达诺、皮耶·德·费玛和布莱士·帕斯卡主要关心的是计算他们在掷骰子游戏中获胜的几率。然而,正如我们所知,现代概率理论是在 20 世纪随着测度理论的发展而进步的。

测度论的目标是构建一种比较数学中集合的相对大小的系统方法。由于一个事件发生的概率恰好是该事件发生的可能性的度量,测度论成为研究概率的自然框架。

测量理论的问题(对我们来说)是它很快变得非常抽象。尽管如此,我还是会试着介绍研究概率的数学框架,而不会深入测度论。让我们看看能走多远。

激励人心的例子

考虑一个掷两个公平骰子的游戏。我们想测量任何一次掷骰子累积到一个给定数字的可能性。例如,如果我们掷出 3 和 6,我们得到 9。数学上,我们可以用函数 X 来表示,取对(3,6)到 9:

X(3,6) → 9

我们想要考虑所有这些掷骰子的可能组合的集合。我们称这个集合为ω(大写ω,我们可以简洁地列举如下

ω= {(I,j): 1 ≤ i,j ≤ 6}

对(3,6)则是ω的成员,我们写为:(3,6)∈ω

然而,如果我们考虑给定掷骰子的总数为 9 的事件,那么存在不止一个可能的组合,即配对:

A = {(3,6),(4,5),(5,4),(6,3) }

对上述集合中的任何一对进行 X(采样)评估,我们将得到 9。注意集合 A 不是ω的一个元素(成员),但它显然包含了ω的元素!所以我们需要一些基于ω的东西,只是更宽泛。

这激发了事件* 、ℱ的族的概念,它包含来自ω的元素的所有可能的组合,包括ω本身的整体,以及表示为∅.的空集本质上,ℱ是一组集合,因此为了一致性,单个卷采用{(3,6)}。

集合 a 则是的一个元素,即 A ∈ ℱ。

现在我们有了一组事件,我们可以继续我们的目标,测量这些事件的可能性。我们做这件事的数学上精确的方式是相当复杂的,但是凭直觉(甚至可能是现实的),我们可以把一个事件的概率看作是该事件相对于某件事情发生的总体可能性的可能性。为此,如果 F ℱ是任何事件,那么计算其概率的一种方法是:

ℙ(F) = 尺寸 (F)/ 尺寸(ω)

当然,模糊之处在于 F 或ω的大小的确切含义,但这是另一天的辩论!在我们的简单示例中,这相当容易:

一个骰子的情况下,一次掷骰有 6 个结果,姑且称之为θ= { 1,2,3,4,5,6}。掷出 1 只有一种方法,所以

ℙ(1) = 尺寸 ({1})/ 尺寸(θ)= 1/6

在ω_ 1 上,系列事件的元素的一个例子是{1,2},我们可以将其解释为滚动 1 2,这具有概率

ℙ({1,2}) = 大小 ({1,2})/ 大小(ω_ 1)= 2/6 = 1/3

有两个骰子的情况下,有 6 = 36 种可能的结果,ω的定义如上所述。然后

ℙ((1,2)) = 尺寸 ({(1,2)})/ 尺寸(ω)= 1/36

并如上取 A:

ℙ(A) = 尺寸 (A)/ 尺寸(ω)= 4/36 = 1/9

配备了一组结果ω、一系列事件ℱ和一个概率测度ℙ,我们几乎拥有了展示概率论基本思想所需的一切。缺少的成分是我们在本节开始时定义的函数:x。这个函数是一个棘手的对象,处理它需要一些小心。换句话说,需要更多的数学知识,我们很快会讲到。现在,我将声称我们可以使用 X 对示例游戏的随机性进行编码。

*从技术上讲,ℱ就是我们所说的ω上的𝝈-algebra。

背景

这个鼓舞人心的例子给了我们足够的材料来更全面地描述这个场景。

三元组(ω,ℱ,ℙ)被称为一个概率空间如果ℙ(ω= 1。在这种情况下,将ℱ元素发送到区间[0,1]中的数字的映射,

ℙ:ℱ →[0,1]

被称为概率度量

要求(ω)= 1 反映了这样一个逻辑:在(ω)的世界里,从ω开始一定会有什么事情发生。

元素 A ∈ ℱ被称为事件,而元素𝛚(小写ω)∈ω(等价于{𝛚} ∈ ℱ)被称为基本事件(或实现)。

中的事件由基本事件组成(或者缺少基本事件,例如你 掷出两个 6 的事件)。

下一步是定义随机变量的概念。我们的直觉告诉我们,这一定是某种随机取值的变量。从数学上来说,这并不容易定义。正式定义将以如下方式遵循我们的直觉:

当我们衡量一个事件的概率时,我们从衡量我们有多大可能 观察到 一个事件开始。

在骰子示例中,我们可以观察到两个骰子的和以四种方式为 9,按集合 a 的元素列出。我们通常会从一组结果开始做同样的事情,并测量可能导致该结果的可能性集合的大小。

我们将此形式化如下:设 x:ω→ℝ是一个函数,它将基本事件从ω发送到实数线(即我们熟悉的所有常用数字)。那么函数 x 将是一个随机变量如果任意子集 b 的逆像⊂ℝ(符号⊂用来表示 b 是ℝ的子集)包含在ℱ.中

一个函数的 给定集合 b 的逆像 是它发送给 b 的元素的集合,对于 x:ω→ℝ,这里定义为:**

x⁻(b)= {𝛚ω:x(𝛚)b }**

其中 B ⊂ ℝ

例如,如果我们从两个骰子游戏的工作示例中返回到函数 X。则 9 的逆像(取{9}为ℝ的子集)为

X⁻ ({9}) = {(i,j)∈ω:x((I,j)) = 9}

= {(i,j)∈ω:I+j = 9 }

= {(3,6), (4,5), (5,4), (6,3)}

= A

我们知道 A ∈ ℱ.到目前为止,一切顺利。事实上,既然我们把空集、∅作为ℱ的一部分包括在内,那么事实证明,ℝ的任何子集的逆像都在ℱ.所以 X 满足条件,它是一个随机变量。

*实际上,这个条件是一个技术要求,在大多数(计算)设置中我们不必担心。相反,我们会更关心我们最终使用的设置是否合理。

随机变量和随机性

将数学与我们的直觉联系起来,我们如何解释形式条件 x:ω→ℝ是一个随机变量** if X⁻ (B) ∈ ℱ对于实数的任何子集 B ⊂ ℝ?我们可以这样想:**

如果我们做一些观察,b,也就是可量化的,那么 X⁻ (B)就是可能事件的集合,通过它 随机变量 x 引出 B 。换句话说,相对的 大小 X⁻ (B)是 b 的 几率 由 x 的 随机生成机制**

事实上,这正是我们在使用概率度量来度量B 的可能性时所做的事情:**

ℙ(x(b))=ℙ({𝛚∈ω:x(𝛚)⊂b })**

受这种等价性的激励,以及对直觉连贯性的渴望(通常我们不会用逆像来思考事件!),我们可以简单地写

ℙ(X ⊂ B)代替ℙ(X^{-1}(B))

我们可以把这个表示理解为随机变量 X 落在 B 概率。

然而,集合包含符号看起来有点笨拙,只是为了技术上的完整性。我们可以通过书写使东西更容易阅读

ℙ(X = B)代替ℙ(X ⊂ B)

我们把这个理解为 X 等于 B 概率,简单来说就是随机变量 X 取值 B 概率。

回到我们的例子,如果我们取 B = {9},然后简单地写 9 而不是{9},我们可以恢复掷骰子游戏中两个数总和为 9 的概率的通常符号:

ℙ(X = 9) = 1/9

最后,我们可以采取一种更直接的方法来测量概率,从一个感兴趣的事件开始,比如产生一些观察的 A ∈ ℱ。为了测量其可能性,我们从评估该事件的随机变量开始:

B = X(A) = {X(𝛚): 𝛚 ∈ A}

然后我们计算:

ℙ(a)= ℙ(x(a)= ℙ(x = ℙ(b)

根据上下文,选择更清楚的符号。

奖金

给定任何一组𝕌,我们说如果ℙ(𝕌= 1,𝕌几乎必然发生。这就解释了题目。

由 Patrick Fore 在 Unsplash 上拍摄的照片

原载于 2017 年 11 月 23 日jontysinai . github . io

概率第 2 部分:条件概率

原文:https://towardsdatascience.com/probability-part-2-conditional-probability-5410826d4f7f?source=collection_archive---------8-----------------------

这是我写的关于概率的系列博客的第二篇。在这篇文章中,我介绍了条件概率的基本概念,它允许我们在概率计算中加入额外的信息。条件概率背后的思想自然会引出概率论中最重要的思想,即贝叶斯定理。与第一篇文章一样,你可以在这里读到,这种方法是用测度论的数学思想来解释条件概率。同样,和第一篇文章一样,这篇文章是给任何人看的,不管你是否学过数学。

掷骰子的游戏

在我的上一篇文章中,我讨论了概率作为一种测量事件不确定性的方法。我们认为概率是给一个事件产生特定结果的机会分配一个权重,我们相对于其他可能的结果来衡量这个权重。我们定义了一个事件空间,我们称之为ω。在这个事件空间中,我们定义了一个随机变量 x,作为一个函数,它将每个事件映射到我们观察到的结果,在ℝ:的实际线上编码为数字

x:ω→ℝ.

结果的概率是相对于整个事件空间大小的映射到该结果的可能事件数量的大小:**

:ℱ → [0,1]。

我们称可能事件的集合为随机变量的原像。如果 b 是一个结果,那么 b 的原像是 X⁻ (B),b 的概率是原像的相对大小,由 (X⁻ (B))给出

例如,在上一篇文章的骰子示例中,我们考虑了掷出两个骰子并把数字相加的实验,如果我们观察到一个结果* 9,那么有四个可能的事件加起来可能是 9,即(3,6)、(4,5)、(5,4)和(6,3)。我们称这个集合为 A。由于ω中有 36 种可能的结果,因此我们可以通过 A 相对于ω的相对大小来衡量得到 9 的概率。如果 X 是代表我们实验的随机变量,那么 A 是观察 X = 9 的原像,A 的概率是*

(一)= 4/36 = 1/9。

思考过去

然而,如果我们能够整合以前发生过的事件的信息会怎么样呢?例如,假设我们不是一次滚动两个骰子,而是一次滚动一个。在这种情况下,根据第一次掷骰的结果,得到 9 的概率会有所不同。为了说明这一点,我们来看一个例子,我们的第一次掷骰子是 3。在第一个场景中,在掷骰子之前,总共有 36 种可能的配置。然而,现在我们已经观察到一个骰子为 3,配置的总数减少了,即集合:**

B = {(3,1),(3,2),(3,3),(3,4),(3,5),(3,6) }。

在这种情况下,只有一种可能的结果是 9:我们在第二次掷骰子时得到 6。我们现在怎么计算 9 的概率?在这篇博文的结尾,我们将会看到计算总不确定性需要概率论中一个基本而重要的结果,即贝叶斯定理。我们将朝着这一点努力,但现在我们将从最简单的场景开始。

利用我们已经知道的

我们已经把问题简化为我们已经掷出了 3 的事件,所以我们所有的不确定性仅仅在于第二次掷出。在这种情况下,我们看到总共只有 6 个可能的事件,其中只有导致 9。使用与上一篇文章相同的逻辑,我们已经掷出 3 个的概率为 9,* 概率为 :*

(观察一个 9 |滚一个 3) = 1/6。

首先要注意的是,这种概率高于完全不确定的情况,其中 (A) = 1/9。这是有道理的,因为掷出 3 极大地增加了我们得到 9 的机会,即使 6 个配置中只有一个是有效的。为了更好地理解这一点,假设我们第一次没有掷出 3,那么我们的可能事件空间,我们称之为𝚯(capital 希腊字母“theta”)有 30 种可能的配置。在这个空间上,有 3 种可能的构形通向 9,即(4,5),(5,4)和(6,3)。因此,假设我们在第一次掷骰子时没有掷出 3,那么得到 9 的概率是:

(观察一个 9 |没有滚过一个 3) = 3/30 = 1/10,

这比完全不确定的情况要少,甚至比我们第一次掷出 3 的情况还要少。很明显,第一次掷出 3 会增加我们得到 9 的机会。

其实比那个更笼统。任何增加我们到达 A 的机会的掷骰子,毕竟是 X = 9 的前像,将会增加我们的机会。这个基本思想可以用图表来解释。

概率的形状

让我们回到之前的陈述,我说过结果 B 的概率是由它的原像的相对大小给出的:

**ℙ(b)=size(x⁻(b))/尺寸(ω)。

让我们用图形来解释这意味着什么。我们可以将ω中的事件可视化为阴影区域,例如集合 X⁻ (B),为简单起见,我们简单地将其标记为 b,如下所示:

虽然这些可视化只是一种启发,对于测量概率来说太不精确,但它们有助于可视化不同事件如何相互作用,以及它们的概率可能如何相互作用。

例如,如果 A 是我们的掷骰数加起来为 9 的事件,我们可以把它包括在我们的图中,现在很清楚,这个事件正好在一点上与 B 相交:对(3,6)。

这是导致 9 的一种配置,第一次掷出 3。但是,既然这是ω中的一个点,为什么我们不把它的概率度量为 ℙ( (3,6))= 1/36 呢?那要看我们在找什么了。我们尤其对 9 的概率感兴趣,因为我们已经掷出了 3* 。如果我们已经掷出了一个 3,那么我们就不在整个空间ω中了。*

像(2,4),(1,5)和(4,1)这样的构型对我们来说已经不存在了,所以显然我们必须重新定义我们感兴趣的空间。

重估尺寸

要了解如何做到这一点,让我们回到 A 和 B 的图表。如果我们已经掷出了 3,那么我们可用的可能配置就从整个ω缩小到了集合 B!这个收缩动作也排除了 A 中的一些配置,除了(3,6),它在 A 和 b 的交集中,我们可以形象地把它想成:

现在,当我们假设概率为 9,假设我们掷出了 3,我们必须重新评估我们如何在现在可能的情况下衡量大小。9 的原像现在只是交集。由于假设事件 B 已经发生(通过事件空间收缩到 B 来可视化),我们测量原像相对于 B 的大小,因此

(观察 a 9 |滚 a 3)=(a | b)= size(a∩b)/size(b)= 1/6

条件概率

我刚才所展示的被称为事件的条件概率。它是事件 A 的概率,条件取决于事件 B。通过将条件视为对事件空间大小的限制,我们可以将给定 B 的条件概率度量为

(A| B) =大小(a∩b)/大小(b)。

我们可以通过记住任何事件的概率是由该事件相对于整个集合的大小给出的来使这一点更加直观,即:

(B) =尺寸(b)/尺寸(ω)。

轻微的手动重排给出:

尺寸(B) =尺寸(ω)(b)、

因为大小(ω)总是正的,所以我们可以这样做。我们可以得到集合 A ∩ B 的类似公式。将这两个公式代入我们的条件概率表达式,得到

(A| B) =尺寸(ω)(a∩b)/尺寸(ω)(b)、

这简化为

**ℙ(a | b)=(a∩b)/(b)。

回归直觉

直观地说,给定 B,A 的概率等于 A B 的概率除以恰好为 B 的概率。通过推导示例中的公式,我们将这种划分理解为事件空间的收缩。数学上这种收缩动作被称为事件空间的到条件空间的投影。

从初等数学中我们立即知道,为了避免除法错误,B 的概率不能为零。事实上,这加强了我们的直觉,因为我们不能以不可能的事件为条件!

最后,我们可以把交集看作是我们感兴趣的事件对条件事件的限制。的确,A 和 B 的交集可以认为是集合 A 到集合 B 的投影,也就是条件空间。

总而言之,我们可以把 条件概率 *看成是投射到某个(更小)条件空间* 上的概率。**

贝叶斯定理:概率的基本性质

事实证明,交集是对称的:A 到 B 的投影与 B 到 A 的投影是相同的。事实上,前面的图加强了这一点。

基于同样的程序,我们可以很容易地推导出条件概率

**ℙ(b | a)=(a∩b)/(a)。

再一次,因为 (A)是正的并且不可能是零,我们可以使用数学上的手算来推导交集概率的表达式:

**ℙ(a∩b)=(b | a)(a)。

这就说 A B 的概率是给定 A 的 B 的条件概率乘以恰好 A 的概率。**

直觉上,如果我们考虑 B 的条件概率,假设 A 已经发生,并且我们考虑 A 的概率,那么我们必须考虑两者的概率。

但是我们从前面知道,如果我们有了交集的概率,我们可以投影 B 的条件空间来计算逆概率:给定 B 的条件概率,由下式给出:

**ℙ(a | b)=(a∩b)/(b)} =(b | a)(a)/(b)。

这个最终结果被称为贝叶斯定理

在这个公式中,如果 A 是我们感兴趣的事件,B 是条件事件,那么数量

被称为给定 b 的后验概率

数量

被称为给定 b 的可能性

最后是数量

(一)

简单地称为 a 的先验概率。

直观上,A 的先验是 A 在考虑任何其他事件之前的原始概率。可能性虽然被视为 B 的条件概率,但也可以被认为是 A 依赖 B 的可能性的度量。要理解为什么,回想一下我们通过考虑交集的对称性来推导出可能性在公式中的位置。最后后验是条件作用于 b 后 A 的最终概率

贝叶斯定理的重要性

从根本上说,贝叶斯定理通过考虑我们的总不确定性,给了我们一种测量条件概率的方法。这是我在这篇文章前面承诺的观点。在本例中,我们可以通过考虑贝叶斯定理中的所有量来直接测量 (观察 a } 9 |掷出的 a ^ 3),而不是一次考虑一个,然后列举第一次掷出 a ^ 3 后总事件空间如何变化。

我将把这作为一个练习,但是通过仔细考虑可能性(提示:回忆一下我们如何利用交集的对称性得出可能性),你可以计算后验概率,并且看到它产生相同的结果。**

虽然从我使用测量理论直觉推导条件概率的基本例子中并不明显,但在某些情况下,计算可能性比直接测量感兴趣的后验概率要容易得多。这篇文章旨在介绍条件概率,所以我不会在这里详细介绍。然而,对于那些感兴趣的人,我建议阅读已故的大卫·麦凯的书的第三章《信息论、推理和学习算法,这里有免费的。

虽然 ITILA(缩写为)已经被更现代的机器学习教科书所取代(考虑到机器学习的研究速度,它们也不会过时太久),但它仍然是学习算法的基本参考,特别是从概率的角度来看。

偶然性呢?

人们有一种自然的倾向,认为条件概率是一种因果关系。如果我们以 B 为 A 的条件,这是否意味着 B 导致 A。一般来说,情况并非如此,陷入这个陷阱是危险的。事实上,在推导过程中,我认为条件作用在某种意义上是对称的,如果我们能以 B 为条件,那么我们也能以 a 为条件。事实上,贝叶斯定理要求我们认为条件概率(后验概率)取决于它们的条件逆(可能性)。

因果关系是统计学中最难理解的概念之一。这要求我们重新思考统计关系的建模方式。将来,根据我对基本思想的理解程度,我希望能写一系列关于因果推理的类似博客。

卢卡斯·布拉塞克在 Unsplash 上拍摄的照片

原载于 2018 年 12 月 23 日jontysinai . github . io

学习机器学习—概率论基础

原文:https://towardsdatascience.com/probabiliy-theory-basics-4ef523ae0820?source=collection_archive---------0-----------------------

介绍

在这个系列中,我想探索一些来自统计学的介绍性概念,这些概念可能对那些学习机器或刷新知识的人有所帮助。这些主题是数据科学的核心,并且经常出现在丰富多样的主题中。从头再来一遍总是好的——这样我们可能会发现以前隐藏的新知识,所以让我们继续。

第一部分将介绍概率论的基础知识。

可能性

既然我们已经有了这么好的数学工具,为什么我们还需要概率呢?我们用微积分来处理无穷小尺度上的函数,并测量它们如何变化。我们发展了代数来解方程,我们还有几十个其他的数学领域来帮助我们解决我们能想到的几乎任何类型的难题。

困难的是,我们都生活在一个混乱的宇宙中,在这个宇宙中,很多时候事情都无法精确测量。当我们研究真实世界的过程时,我们想要了解扭曲我们实验的无数随机事件。不确定性无处不在,我们必须驯服它来满足我们的需求。这就是概率论和统计学发挥作用的时候。

如今,这些学科处于人工智能、粒子物理、社会科学、生物信息学以及我们日常生活的中心。

如果我们要讨论统计学,最好先确定什么是概率。其实这个问题没有单一的最佳答案。我们将在下面讨论概率论的各种观点。

常客概率

想象一下,给了我们一枚硬币,我们想检查它是否公平。我们如何解决这个问题?让我们试着做一些实验,如果正面朝上,记下 1,如果看到反面,记下 0。重复这 1000 次投掷,并计算每个 0 和 1。在我们进行了一些冗长的实验后,我们得到了这些结果:600 个正面(1)和 400 个反面(0)。如果我们接着计算过去出现正面或反面的频率,我们将分别得到 60%和 40%。这些频率可以解释为硬币正面朝上或反面朝上的概率。这被称为一种频率主义者对概率的观点。

条件概率

我们经常想知道一个事件发生的概率,如果其他事件已经发生的话。我们把一个事件的条件概率 A 给定事件 B 写成 P(A | B) 。以下雨为例:

  • 如果我们看到打雷,下雨的可能性有多大
  • 假设天气晴朗,下雨的可能性有多大?

从这张欧拉图我们可以看出 P(Rain | Thunder) = 1 :看到打雷的时候总是在下雨(是的,不完全是这样,但我们在例子中会把这当成是真的)。

P(雨|晴)呢?从视觉上看,这个概率很小,但是我们如何用数学公式来表达它,并进行精确的计算呢?条件概率定义为:

换句话说,我们将下雨和晴天的概率除以晴天的概率。

从属和独立事件

如果一个事件的概率不以任何方式影响另一个事件,则称该事件是独立的。以掷骰子第一次和第二次得到 2 的概率为例。这些事件是独立的。我们可以这样表述

但是为什么这个公式有效呢?首先,让我们将第一次和第二次投掷的事件重命名为 AB 以消除符号混乱,然后将掷骰子的概率明确重写为我们目前看到的两次掷骰子的联合概率:

而现在把 P(A) 乘以 P(B) (没什么变化,可以抵消掉)回想一下条件概率的定义:

如果我们从右向左阅读上面的表达式,我们会发现 P(A | B) = P(A) 。基本上,这意味着 A 独立于 B!同样的道理也适用于 P(B) 并且我们完成了。

贝叶斯概率观

有一种看待概率的替代方法叫做贝叶斯方法。统计学的频率主义方法假设存在一个我们正在寻找的模型参数的最佳具体组合。另一方面,贝叶斯方法以概率方式处理参数,并将它们视为随机变量。在贝叶斯统计中,每个参数都有自己的概率分布,它告诉我们参数给定数据的可能性有多大。从数学上讲,这可以写成

这一切都始于一个简单的定理,它允许我们基于先验知识计算条件概率:

尽管简单,贝叶斯定理有着巨大的价值,广泛的应用领域,甚至是统计学的一个特殊分支——贝叶斯统计。如果你对贝叶斯定理是如何推导出来的感兴趣,有一篇关于贝叶斯定理的非常好的博文——一点也不难。

分布

什么是概率分布?这是一个告诉我们在一些实验中不同可能结果的概率的定律,以数学函数的形式表达。正如每个函数一样,分布可能有一些参数来调整其行为。

当我们测量抛硬币事件的相对频率时,我们实际上已经计算了所谓的经验概率分布。事实证明,我们世界中的许多不确定过程都可以用概率分布来描述。例如,我们的硬币结果有一个伯努利分布,如果我们想在 n 次试验后计算正面概率,我们可以使用二项式分布。

引入一个类似于可能在概率环境中使用的变量的概念是很方便的——随机变量。每个随机变量都有一个分配给它的分布。随机变量按照惯例用大写字母书写,我们可以用 ~ 符号来指定分配给变量的分布。

这意味着随机变量 X 根据伯努利分布分布,成功概率(头数)等于 0.6

连续和离散概率分布

概率分布有两种形式:离散分布处理的是具有有限可数数值的随机变量,就像硬币和伯努利分布一样。离散分布由称为概率质量函数(PMF)的函数定义,连续分布处理连续随机变量,这些变量(理论上)可以有无穷多个值。想想用噪声传感器测量的速度和加速度。连续分布由称为概率密度函数(PDF)的函数定义

这些类型的分布在数学处理上有所不同:你通常会对离散分布使用求和 ,对连续概率分布使用积分 。以期望值为例:

样本和统计数据

假设我们正在做人类身高的研究,渴望发表一篇令人瞠目结舌的科学论文。我们测量了街上一些陌生人的身高,因此我们的测量是独立的。我们从真实总体中随机选择数据子集的过程称为抽样。统计是用于使用样本中的值来汇总数据的函数。您之前可能遇到的统计数据是样本均值:

另一个例子是样本方差:

这个公式从整体上捕捉了所有数据点与其平均值的差异。

如果我想要更多呢?

你想深入学习概率论和统计学?太好了!无论你是想对机器学习背后的理论有一个坚实的理解,还是仅仅出于好奇,你肯定会从这些知识中受益。

  • 入门级 : 可汗学院是一个很棒的免费资源。这门课程将以非常直观和简单的形式让你了解基础知识
  • 拉里·乏色曼的《统计学》是一个伟大而简洁的资源,它将向你展示统计学中几乎所有的重要主题。注意,这本书假设你熟悉线性代数和微积分
  • 高级水平:我敢打赌,到这个时候,你会量身定制你的个人阅读清单🙃

如果你喜欢这篇文章,请留下💚。它让我知道我在帮忙。

用“人工智能挑战者全球人工智能大赛”解决问题

原文:https://towardsdatascience.com/problem-solving-with-ai-challenger-global-ai-contest-e788e03dd5a2?source=collection_archive---------29-----------------------

参加中国数据科学平台 AI Challenger 主办的计算机视觉大赛的体会

在这篇文章中,我将分享我在中国机器学习竞赛中解决视频分类问题的经验。

竞争对手有很多数据科学平台。我们过去常常想到 ka ggle——最受欢迎的一个。无论如何,有许多其他平台为数据科学家提供了具有挑战性的任务,现在是探索它们的好时机。这就是为什么我和我的队友 Alexey Grigorev 参加了中国平台 AI Challenger 的短视频实时分类比赛。非常感谢卡格尔大师阿图尔·库津成为我们这次比赛的导师。他帮助我们提出创造性的想法,并为我们提供了一台 GPU 服务器。

竞争描述

视频数据集大约 2 TB 大,并被分成训练集和验证集。有 2 个测试集:测试 A 和测试 b。每个视频可能有 1 到 3 个标签,因此这是一个多标签分类。例如,下面是一个视频帧,有两个类:钢琴和婴儿

以下是可能的标签的完整列表:

这场比赛有一个复杂的评估标准。除了准确性之外,时间限制也被作为一个评估指标。您可能会认为它是从输入一个视频到输出一个预测所用的总时间。

最后,将这两个公式考虑在内,以提交的结果和参考点之间的加权距离来计算综合指标。你可以在这里阅读更多关于指标的信息。

关键的想法是,组织者希望从数据科学社区获得一种可用于工业的高速应用。对于提交材料,参赛者必须加载图像 docker 包。

训练神经网络

我们混合使用了神经网络和更简单的模型来为最终预测做一个集成。我们尝试了不同的网络架构。最好的结果是使用 se_resnet50。“挤压和激励”模块以最小的计算成本提高了 resnet 模型的质量。您可以在本出版物中了解更多关于该架构的信息。作为训练模型的基线,我们从提取第一帧开始。学习率为 0.001,每 30 个时期衰减 10。时代的总数是 150。作为一个优化器,具有重量衰减和动量的随机梯度下降被用于更快的收敛。有趣的是,尽管事实上我们有多标签和多类问题,但我们用 BCEwithlogitsloss 得到了不好的结果。相反,我们使用交叉熵损失,这大大提高了准确性。质量差距的原因可能是数据中缺乏多标签的例子。我们花一些时间思考如何预测多个标签。例如,我们训练了一个二元分类器来预测一个例子是否有一个或多个标签。另一个问题是课程的门槛。我们分析了类别分布并计算了类别的权重。这个想法是,如果二进制分类器预测一个例子有一个以上的标签,则添加一些系数来加权。在这种情况下,我们可以达到一些我们以前没有考虑到的类的阈值。

无论如何,我们没有对类使用阈值,因为根据度量标准,我们知道给定一个具有多个标签的示例,最好只预测其中一个标签,而不是预测一个多余的标签。用这样的方法做实验,让多类预测模型更加稳定,还有很大的空间。

尝试经典的 ML 算法进行组合

解决方案的另一部分是,我们在全局汇集后从神经网络中提取特征,并将这些特征用作更简单的分类器的输入,如梯度增强、逻辑回归和支持向量机。最终集成由四个最好的单一模型(神经网络、对数注册、SVM、catboost)与多数投票分类器组合而成。这个模型在测试 A 中给了我们 0.76 分,但不幸的是这不足以让我们进步。

聚合视频帧并面临新问题

下一步是将聚合添加到神经网络训练中。现在,我们从每个视频中提取五个随机帧,并使用最频繁的标签作为单个预测。我们做了同样的事情来提取经典模型的新特征,效果非常好,我们在验证上得到了 0.91。我们对这些结果感到高兴。截止日期前一周,我们决定提交,但现在我们面临着时间问题。模型是快速的,但是根据规则,还需要考虑视频预处理的时间。我们注意到提取一帧大约需要 0.03-0.05 毫秒。不幸的是,这不允许我们匹配提交限制。

然后,我们决定使用聚合来训练模型,但在一个随机帧上进行预测。这比我们之前没有任何聚合的模型要好一些。验证的得分为 0.81,测试 A 的得分为 0.79,单次预测的时间约为 0.11 毫秒。我们有一个在 GPU 上解码视频以加快进程的想法,但我们没有足够的时间来管理如何使用 docker。这是我们的销售渠道:

竞争氛围

let me add some words about competition organization. AIChallenger pretends to be a global data science platform, but it has a lot of work before it gets there. We faced technical problems while participating, mostly with the docker submission. This Challenge was organized by MeiTu company (美图). For example competition started on 3rd of september but information about the docker instructions appeared on website only up to 12th of october. All instructions were in Chinese language. We accidentally got to know that organizers were assisting participants in Chinese messenger WeChat, but it was also in Chinese and didn’t help foreign competitors. The funny thing was that even the submit button was in Chinese. We once even wrote a comment on the forum to encourage organizers to solve technical problems, but it only partly helped. In the future i hope we will see a better level of organization and technical support.

结束语

我们的比赛就这样结束了。尽管我们没能提交最好的模型,但还是值得一试。我们了解了如何解决这类机器学习问题。此外,在这个项目上工作了近 3 个月后,我们现在有了一个很好的管道,你可以在 github 这里找到。

然而,一个好的趋势是,挑战规则迫使竞争对手考虑设计一种用于生产的算法。因此,除了建模之外,它还有助于提高代码优化和创建可重用管道的技能。最后,我想鼓励大家探索新的数据科学平台,并继续参加比赛,以更好地应对这些挑战。

流程博客#6 —可视化

原文:https://towardsdatascience.com/process-blog-6-visualization-10732336e01a?source=collection_archive---------0-----------------------

该过程

本周,我们的 sprint 专注于使用专业软件 Tableau 和 2015 年西雅图 911 电话的数据集来创建数据的可视化。因为当我们被分配任务时,我刚刚参加了最后一次期中考试,我想没有比减压更好的事情了——推而广之,就是聚会。最后,我把自己的想象提供给了一个 UW 的学生,他在希腊生活之外寻找一个可以参加的派对,但却不知道何时何地可以找到一个。为了回答我的用户组关于何时何地可以找到最好的聚会的问题,我创建了三个可视化工具:

Visualization 1: Number of Noise Complaints by Weekday

Visualization 2: Number of Noise Complaints by Hour of the Day

Visualization 3: Areas in the U-District with 20+ Noise Complaints

(所有的可视化可以在:https://public.tableau.com/profile/alex.katson#!找到/viz home/whandwhere to find the best parties/whandwhere to find the best parties

我将搜索范围限制在 U 区附近,因为它离大学很近,并且只使用了噪音投诉或酒精/大麻违规的记录,因为大多数好的聚会往往会将喧闹的气氛与某种形式的物质结合起来。(顺便说一句,如果你想知道,数据显示你应该在周五、周六或周日晚上 10 点左右去东北第 19 大道的 45xx 街区,这样你就可以在警察打电话之前享受一下了)。

那又怎样?

我在创建可视化时遇到的一个主要问题是,我的标准似乎太宽泛了。例如,噪音投诉电话不仅是由喧闹的聚会产生的,而且未成年人被发现饮酒并不总是在聚会上。然而,我认为我的可视化是基于相关性的,而不是基于因果关系的,这意味着电话录音数量较多的一天或地区比电话较少的地区更有可能举行聚会。这就是为什么“where”可视化只包括具有 20 个或更多记录的块,因为我觉得这是一个合适的样本大小,可以作为一个可能由于不仅仅是巧合而有呼叫进入的区域来包括。在未来,我认为,如果有机会,我可以找到一个与数据更直接相关的研究问题,或者寻找一个与我正在研究的问题更密切相关的数据集。

未来

在不久的将来,我可以看到可视化技术在为我和我的朋友们寻找一个住在校外的公寓或房子方面是有用的。利用网上的房源,我可以根据卧室数量或其他限制因素对可能的地方进行排序。我还可以使用我们在本周 sprint 中获得的数据集,使用 Tableau 中可用的地图可视化,检查最安全的区域在哪里,同时仍然靠近校园。鉴于我和我的朋友们在寻找一个离校园合理距离内的合适地点时遇到了一些困难,我觉得可视化可能会在我们继续寻找的过程中证明是非常有用的。

用 Python 处理 XML—element tree

原文:https://towardsdatascience.com/processing-xml-in-python-elementtree-c8992941efd2?source=collection_archive---------0-----------------------

初学者指南

“shallow focus photography of spider web” by Robert Anasch on Unsplash

了解如何使用 Python ElementTree 包解析、浏览、修改和填充 XML 文件,用于循环和 XPath 表达式。作为一名数据科学家,您会发现理解 XML 对于 web 抓取和解析结构化文档的一般实践都是非常有用的

可扩展标记语言 (XML)是一种标记语言,它通过定义一组机器可读和人类可读格式的规则来编码文档。从 SGML(标准通用标记语言)扩展而来,它让我们描述文档的结构。在 XML 中,我们可以定义自定义标签。我们也可以使用 XML 作为交换信息的标准格式。

  • XML 文档有几个部分,叫做 元素 ,由一个开始和一个结束标签 定义。标签是一种标记结构,以<开始,以>结束。开始标记和结束标记之间的字符(如果有的话)是元素的内容。元素可以包含标记,包括其他元素,这些元素称为“子元素”。
  • 最大的顶级元素称为 ,它包含所有其他元素。
  • 属性是存在于开始标记或空元素标记中的名称-值对。XML 属性只能有一个值,并且每个属性在每个元素中最多只能出现一次。

这里有一张movies.xml的快照,我们将在本教程中使用:

<?xml version="1.0"?>
<collection><genre category="Action"><decade years="1980s"><movie favorite="True" title="Indiana Jones: The raiders of the lost Ark"><format multiple="No">DVD</format><year>1981</year><rating>PG</rating><description>'Archaeologist and adventurer Indiana Jones is hired by the U.S. government to find the Ark of  the Covenant before the Nazis.'</description></movie><movie favorite="True" title="THE KARATE KID"><format multiple="Yes">DVD,Online</format><year>1984</year><rating>PG</rating><description>None provided.</description></movie><movie favorite="False" title="Back 2 the Future"><format multiple="False">Blu-ray</format><year>1985</year><rating>PG</rating><description>Marty McFly</description></movie></decade><decade years="1990s"><movie favorite="False" title="X-Men"><format multiple="Yes">dvd, digital</format><year>2000</year><rating>PG-13</rating><description>Two mutants come to a private academy for their kind whose resident superhero team must oppose a terrorist organization with similar powers.</description></movie><movie favorite="True" title="Batman Returns"><format multiple="No">VHS</format><year>1992</year><rating>PG13</rating><description>NA.</description></movie><movie favorite="False" title="Reservoir Dogs"><format multiple="No">Online</format><year>1992</year><rating>R</rating><description>WhAtEvER I Want!!!?!</description></movie></decade>    </genre><genre category="Thriller"><decade years="1970s"><movie favorite="False" title="ALIEN"><format multiple="Yes">DVD</format><year>1979</year><rating>R</rating><description>"""""""""</description></movie></decade><decade years="1980s"><movie favorite="True" title="Ferris Bueller's Day Off"><format multiple="No">DVD</format><year>1986</year><rating>PG13</rating><description>Funny movie on funny guy </description></movie><movie favorite="FALSE" title="American Psycho"><format multiple="No">blue-ray</format><year>2000</year><rating>Unrated</rating><description>psychopathic Bateman</description></movie></decade></genre>

元素树简介

XML 树结构使得导航、修改和移除在程序上相对简单。Python 有一个内置的库, ElementTree ,它有读取和操作 XML(和其他类似结构的文件)的函数。

一、导入ElementTree。使用ET的化名是很常见的做法:

**import xml.etree.ElementTree as ET**

解析 XML 数据

在提供的 XML 文件中,有一个描述电影的基本集合。唯一的问题是数据很乱!这个收藏有很多不同的管理者,每个人都有自己的方式将数据输入文件。本教程的主要目标是用 Python 阅读和理解文件,然后解决问题。

首先你需要用ElementTree读入文件。

**tree = ET.parse('movies.xml')
root = tree.getroot()**

现在已经初始化了树,您应该查看 XML 并打印出值,以便理解树是如何构造的。

**root.tag**'collection'

在顶层,您会看到这个 XML 植根于collection标签。

**root.attrib**{}

对于循环

通过使用一个简单的“for”循环,可以很容易地迭代根中的子元素(通常称为“子元素”)。

**for child in root:print(child.tag, child.attrib)**genre {'category': 'Action'}
genre {'category': 'Thriller'}
genre {'category': 'Comedy'}

现在你知道根collection的孩子都是genre。为了指定流派,XML 使用属性category。根据genre元素,有动作片、惊悚片和喜剧片。

通常,了解整个树中的所有元素是很有帮助的。一个有用的功能是root.iter()

**[elem.tag for elem in root.iter()]**['collection','genre','decade','movie','format','year','rating','description','movie',....'movie','format','year','rating','description']

有一种查看整个文档的有用方法。如果将根传递给.tostring()方法,就可以返回整个文档。在 ElementTree 中,这个方法采用了一种稍微奇怪的形式。

由于 ElementTree 是一个功能强大的库,它不仅可以解释 XML,还必须指定显示为字符串的文档的编码和解码。

您可以扩展iter()函数的用途,以帮助查找感兴趣的特定元素。root.iter()将列出根下与指定元素匹配的所有子元素。这里,您将列出树中movie元素的所有属性:

**for movie in root.iter('movie'):print(movie.attrib)**{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}

XPath 表达式

很多时候元素没有属性,它们只有文本内容。使用属性.text,可以打印出这个内容。

现在,打印出电影的所有描述。

**for description in root.iter('description'):print(description.text)**'Archaeologist and adventurer Indiana Jones is hired by the U.S. government to find the Ark of the Covenant before the Nazis.'None provided.
Marty McFly
Two mutants come to a private academy for their kind whose resident superhero team must oppose a terrorist organization with similar powers.
NA.
WhAtEvER I Want!!!?!
"""""""""
Funny movie about a funny guy
psychopathic Bateman
What a joke!
Emma Stone = Hester Prynne
Tim (Rudd) is a rising executive who “succeeds” in finding the perfect guest, IRS employee Barry (Carell), for his boss’ monthly event, a so-called “dinner for idiots,” which offers certain 
advantages to the exec who shows up with the biggest buffoon.Who ya gonna call?
Robin Hood slaying

打印出 XML 很有帮助,但是 XPath 是一种查询语言,用于快速方便地搜索 XML。然而,理解 XPath 对于扫描和填充 XML 至关重要。ElementTree有一个.findall()函数,它将遍历被引用元素的直接子元素。

在这里,您将搜索 1992 年上映的电影树:

**for movie in root.findall("./genre/decade/movie/[year='1992']"):print(movie.attrib)**{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}

函数.findall()总是从指定的元素开始。这种类型的功能对于“查找和替换”来说非常强大。你甚至可以搜索属性!

现在,只打印多种格式的电影(一个属性)。

**for movie in root.findall("./genre/decade/movie/format/[@multiple='Yes']"):print(movie.attrib)**{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}

集思广益,为什么在这种情况下,print 语句返回multiple的“是”值。想想“for”循环是怎么定义的。

提示:在 XPath 内部使用'...'返回当前元素的父元素。

**for movie in root.findall("./genre/decade/movie/format[@multiple='Yes']..."):print(movie.attrib)**{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}

修改 XML

早些时候,电影的名字是绝对的混乱。现在,再把它们打印出来:

**for movie in root.iter('movie'):print(movie.attrib)**{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}

在未来修正后面 2 中的 2。这应该是一个查找和替换的问题。编写代码以找到标题“Back 2 the Future”并将其保存为变量:

**b2tf = root.find("./genre/decade/movie[@title='Back 2 the Future']")
print(b2tf)**<Element 'movie' at 0x10ce00ef8>

注意,使用.find()方法返回树的一个元素。很多时候,编辑元素中的内容更有用。

将 Back 2 未来元素变量的title属性修改为“回到未来”。然后,打印出变量的属性以查看您的更改。通过访问元素的属性,然后给它分配一个新值,可以很容易地做到这一点:

**b2tf.attrib["title"] = "Back to the Future"
print(b2tf.attrib)**{'favorite': 'False', 'title': 'Back to the Future'}

将您的更改写回 XML,以便它们在文档中永久固定。再次打印出您的电影属性,以确保您的更改生效。使用.write()方法来做这件事:

**tree.write("movies.xml")****tree = ET.parse('movies.xml')
root = tree.getroot()****for movie in root.iter('movie'):print(movie.attrib)**{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back to the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}

修复属性

multiple属性有些地方不正确。使用ElementTree根据电影的格式来固定指示器。首先,打印format属性和文本,看看哪些部分需要修复。

**for form in root.findall("./genre/decade/movie/format"):print(form.attrib, form.text)**{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,Online
{'multiple': 'False'} Blu-ray
{'multiple': 'Yes'} dvd, digital
{'multiple': 'No'} VHS
{'multiple': 'No'} Online
{'multiple': 'Yes'} DVD
{'multiple': 'No'} DVD
{'multiple': 'No'} blue-ray
{'multiple': 'Yes'} DVD,VHS
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,digital,Netflix
{'multiple': 'No'} Online,VHS
{'multiple': 'No'} Blu_Ray

这个标签需要做一些工作。

您可以使用正则表达式来查找逗号——这将告诉您multiple属性应该是“是”还是“否”。使用.set()方法可以很容易地添加和修改属性。

**import re****for form in root.findall("./genre/decade/movie/format"):# Search for the commas in the format textmatch = re.search(',',form.text)if match:form.set('multiple','Yes')else:form.set('multiple','No')****# Write out the tree to the file again
tree.write("movies.xml")****tree = ET.parse('movies.xml')
root = tree.getroot()****for form in root.findall("./genre/decade/movie/format"):print(form.attrib, form.text)**{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,Online
{'multiple': 'No'} Blu-ray
{'multiple': 'Yes'} dvd, digital
{'multiple': 'No'} VHS
{'multiple': 'No'} Online
{'multiple': 'No'} DVD
{'multiple': 'No'} DVD
{'multiple': 'No'} blue-ray
{'multiple': 'Yes'} DVD,VHS
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,digital,Netflix
{'multiple': 'Yes'} Online,VHS
{'multiple': 'No'} Blu_Ray

移动元素

一些数据被放在了错误的年代。使用你所学到的关于 XML 和ElementTree的知识来查找和修复十年数据错误。

在整个文档中打印出decade标签和year标签将会很有用。

**for decade in root.findall("./genre/decade"):print(decade.attrib)for year in decade.findall("./movie/year"):print(year.text)**{'years': '1980s'}
1981 
1984 
1985 
{'years': '1990s'}
2000 
1992 
1992  
{'years': '1970s'}
1979 
{'years': '1980s'}
1986 
2000 
{'years': '1960s'}
1966 
{'years': '2010s'}
2010 
2011 
{'years': '1980s'}
1984 
{'years': '1990s'}
1991

这两年是错误的十年,是 2000 年代的电影。使用 XPath 表达式找出这些电影是什么。

**for movie in root.findall("./genre/decade/movie/[year='2000']"):print(movie.attrib)**{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'FALSE', 'title': 'American Psycho'}

为了转移 x 战警的数据,你必须在动作片中添加一个新的十年标签,即 2000 年代。可以使用.SubElement()方法将这个标签添加到 XML 的末尾。

**action = root.find("./genre[@category='Action']")
new_dec = ET.SubElement(action, 'decade')
new_dec.attrib["years"] = '2000s'**

现在分别使用.append().remove()将 x 战警电影添加到 2000 年代,并将其从 20 世纪 90 年代删除。

**xmen = root.find("./genre/decade/movie[@title='X-Men']")
dec2000s = root.find("./genre[@category='Action']/decade[@years='2000s']")
dec2000s.append(xmen)
dec1990s = root.find("./genre[@category='Action']/decade[@years='1990s']")
dec1990s.remove(xmen)**

构建 XML 文档

很好,所以你可以把整部电影推进到一个新的十年。将您的更改保存回 XML。

**tree.write("movies.xml")****tree = ET.parse('movies.xml')
root = tree.getroot()****print(ET.tostring(root, encoding='utf8').decode('utf8'))**

结论

ElementTree 是一个重要的 Python 库,允许您解析和导航 XML 文档。使用 ElementTree 将 XML 文档分解成一个易于使用的树结构。如果有疑问,打印出来(print(ET.tostring(root, encoding='utf8').decode('utf8')))——使用这个有用的 print 语句一次性查看整个 XML 文档。

参考文献

  • 斯蒂芬·豪森发布的原始帖子:数据营
  • Python 3 文档:元素树
  • 维基百科: XML

产品分析偏差和 KPI

原文:https://towardsdatascience.com/product-analytics-bias-and-kpis-6aa160aa8c20?source=collection_archive---------3-----------------------

产品分析是一个具有挑战性的领域,它是产品、产品经理和用户之间的连接层。它要求你理解产品的技术层面,以及如何量化用户对它的反应。
产品分析最大限度地利用了数字中的硬性事实和用户的软性主观接受。你面临着天平的两端——这些数字是否显示了我们的期望,如果没有,为什么?

你的用户不是代码行。他们是独立的,多样的,有时是出乎意料的。关于我们用户的先验知识,结合心理学和社会假设,就像统计一样,是你工具箱的一部分。

在这篇文章中,我将回顾我在过去的分析项目中遇到的一些社会偏见事件。

Vitruvian Man

早期采用者偏见

你的用户希望每个版本都有更好的产品,而公司正在努力满足他们。产品版本之间的比较,无论是新的硬件版本、应用程序版本还是新的设计,通常都以时间线图的形式进行,比较显示新版本与旧版本的关键指标。这种比较通常会在最初的几天或几周内显示出强烈的积极迹象,最终会减少并变得积极,但不如最初几天那么强烈。
让我们假设苹果发布了一款新的 iPhone 设备,它拥有更好的 Siri(苹果个人助理)算法。为了表明改变的成功,决定使用的 KPI 是“每个活跃用户每天使用 Siri 的平均次数”,这表明一个更好的算法将使用户更经常地使用 Siri。

同样,这是一个假设的图表,我们将使用它作为早期适配器偏差的例子。我们可以看到,在最初的几天里,所选择的度量天空火箭也有很高的方差,直到两个星期过去了,度量仍然高于以前的版本,但没有最初几天那么高。

Hypothetical Graph — Siri Usages per Active User

这张图表没有显示的是谁是新 iPhone X 的用户?他们是持有之前 iPhone 8 版本的同一批用户吗?
第一批接触任何产品新版本的用户被称为早期采用者,他们不同于一般人群。他们致力于产品,并等待看到它的变化。能不能把 iPhone 死忠粉丝和广大用户比一比?

削弱这种偏差的一种方法是将采用率与测量图平行,并消除版本之间的过渡时间,或者将比较限制在同一人群中。只看最终采用新版本的用户,将允许我们在假设任何变化都是由于用户与新版本的交互方式而不是由于选择性用户偏见的情况下,在 iPhone 版本之间进行比较。然而,同样的用户在遇到变化时也会有不同的反应,这就给我们带来了下一个心理偏差。

新奇效果

来自 维基百科:
新奇效应是指当新技术开始实施时,绩效最初有所提高的趋势,这不是因为学习或成就的任何实际提高,而是对新技术兴趣增加的反应”

这是发布新版本或新功能后多次看到的另一种心理反应。用户会部分地与变化互动,只是因为它是新的,而不是它的价值。这种偏见倾向于损害我们对用户短期和长期影响的观点。你会发现,一旦 AB 测试获得所需的显著性值,这种偏差也会停止 AB 测试,事实上,如果实验运行更长时间,P 值将稳定在非显著性水平。有关这方面的更多信息,请点击此处:

[## 社会产品实验挑战

当谈到社交应用功能时,你会发现有太多关于用户如何接受新的或改变的观点…

towardsdatascience.com](/social-product-experimentation-challenges-3298546a6b0f)

默认效果

产品经理广泛使用产品中的默认设置,这是一个强有力的工具,可以将用户推向期望的行为。这就是让用户先决定或替用户选择与要求用户通过选择加入或选择退出默认选项来主动实施更改之间的区别。你可能在购买机票时见过这种情况,航空公司会自动将行李保险添加到你的订单中,而无需询问,你需要明确取消这一选择。
回到产品分析,更改产品中的默认设置将推动衡量标准的变化,但不是因为用户已经更改或发现了产品中的新价值。您的用户会倾向于坚持默认设置,因为需要做出改变,并且当他们不确定如何评估手头的其他选项时。

平衡 KPI

KPI(关键绩效指标)是以稳健清晰的方式衡量您朝着目标前进的最佳方式。一些关键绩效指标在不同行业中是通用的,如 MAU(每月活跃用户),而一些更具体,如市场的平均订单价值(AOV)。
就像偏见的例子一样,KPI 也可能讲述一个可能误导或不能展现全貌的故事。
受平均订单价值 KPI 驱动的市场公司可能会尝试推荐价格更高的产品,或者在漏斗中添加另一个步骤,以推荐向购物车添加更多商品,从而增加最终订单价值。只看 AOV 会显示所选 KPI 的改进,但会忽略另外两个 KPI:

完成订单漏斗的用户百分比——因漏斗中引入的额外步骤而降低。
回头客的百分比——由于推荐价格更高的产品而不是最符合用户需求的产品而下降。

使用相互平衡的多个 KPI 是看到全貌的方法,并且可以避免会增加一个 KPI 而降低另一个 KPI 的极端行为。一些文章将这些 KPI 称为计数器 KPI。

这三篇文章很好地列出了一般应用程序、市场和创业公司的不同 KPI。

[## 产品管理和分析:你应该测量什么指标?

产品组织越来越多地谈论数据如何成为他们决策过程的核心。但是,什么…

medium.com](https://medium.com/product-breakdown/product-management-analytics-what-metrics-should-you-be-measuring-241609b1950d) [## 10 个重要的市场 KPI

市场是非常强大的。他们席卷了我们经济的方方面面,改变了商品和…

medium.com](https://medium.com/@algovc/10-marketplace-kpis-that-matter-22e0fd2d2779) [## 十二金刚:在推销你的创业公司之前,你必须知道的 12 个关键绩效指标

对于一家公司的创始人来说,深入了解公司的关键绩效至关重要…

medium.com](https://medium.com/startupsco/the-dirty-dozen-12-kpis-you-must-know-before-pitching-your-startup-9791192bbda5)

让我们以主要在数量和质量之间平衡的 KPI 元组列表结束。当然,一些 KPI 可以有多个选项。

ARPU(每用户平均收入)

活跃用户中付费用户的百分比
你的优质产品与你的所有用户相关

CPI(每次安装成本)或 CAC(客户获取成本)

LTV(生命周期价值)
您的 CPI 活动是否会导致用户质量下降

从所有交易中防止欺诈交易(真阳性)

合法交易丢失(假阳性)
您是否在防止欺诈的同时也伤害了合法用户

完成购买漏斗的用户百分比
与来自购买用户的返回购买用户百分比
推动购买,同时忽略用户不满

解决的支持票证百分比

重新打开的票证百分比
支持数量或质量

感谢阅读,
哈雷尔·雷查维娅,
Viber 数据分析师

产品分析——如何衡量软件开发的成功

原文:https://towardsdatascience.com/product-analytics-how-to-measure-your-software-development-success-7a6bc765dbab?source=collection_archive---------7-----------------------

能衡量的就能完成。如今,随着低成本数据的出现和新技术浪潮的到来,这一点尤其正确,新技术使我们能够更深入地分析数据。

我们如何判断我的产品开发是否高效?

我的新软件发布成功了吗?

我们需要跟踪什么遥测数据?

这些问题出现得太频繁了,一劳永逸地解决这些问题很重要。让我给你看一个回答所有这些问题的框架!

一些方法

人们经常用来评估产品质量的一个经典方法是基于业务绩效指标;获取、销售、保留。从理论上看,这似乎是个好主意,但是这个要求太高了。如果你发布了一个有新特性的更新,如何快速评估设计是否成功?通过分析记忆是否会随着时间的推移而减少?这将花费太多的时间来看到一个效果,这是不好的,因为它阻止你快速失败和重复,直到软件产生期望的结果。

另一种方法是评估给定群组的使用情况。这是有道理的。您可以将一个群组与新设计进行比较,也可以将一个群组与旧设计进行比较(通过 A / B 测试或谨慎选择相似的时间段)。然而,这种方法虽然比第一种好,但并不仅仅针对产品开发。换句话说,这个方法对于产品团队来说不够具体。如果销售部门改变了流程,或者营销部门在公司网站上遇到了技术问题,该怎么办?不够好。

心脏框架

这个框架是由谷歌风险团队开发的。我喜欢这样的事实:它实现起来非常简单,并且直接与产品和设计团队交流!

HEART 框架是一个框架,它使你能够根据设计目标(你通过设计一个特性想要达到什么)将一个版本分解成更小的成功度量。

主要的设计目标是:

  • 快乐:让用户更快乐地使用你的新功能或界面。
  • 参与度:方便用户发现你的特色并与之互动。
  • 采用:让用户在一段时间内对你的软件更加上瘾。
  • 留存:让用户随着时间的推移对你的软件越来越上瘾。
  • 任务成功:确保用户可以轻松完成操作。

HEART Framework

在这里,重要的是要理解度量本身是没有用的。您需要确保:

  1. 您的软件已正确标记(标记是使用遥测技术创建数据的操作,遥测技术可用于测量用户的操作)。MixPanel、Google Analytics 和 Kissmetrics 等好工具都是低成本的。
  2. 您在发布之后跟踪度量标准。
  3. 您要确保根据您将向团队提供的极具可操作性的见解进行纠正和改进!

流程

HEART Framework measurement process

要记住的事情

这个练习是由特征完成的。即使您的软件版本包含 3 个不同的特性,您也希望单独验证它们。

功能将有多个目标。通常,需要 2-3 个目标的组合。例如,如果你想优化保留,你也要确保你的功能被用户采用。尽管如此,如果你有一个专门的产品分析师,你可能想更细化。否则,保留一些您能够保持的指标(2-3)。

确保您可以测量每个指标。提醒您确保将这些指标用作标记文档。从长远来看,这会节省你很多时间。

与您的团队一起审核指标结果。验证每个指标后,作为一个团队对其进行评审。与其他更高层次的指标相比,这将使团队真正了解哪些方面可以改进。

结论

自从我在我的公司实施了这个框架,讨论和焦点已经明显转移到真正重要的事情上:产品是否符合我们的期望,用户对我们的产品是否满意。这也使我对软件标记有了一个系统的方法,从经验来看,这通常是不完美的。

我强烈建议实现这个框架和方法,因为在与产品团队、以产品为中心的组织中的设计师进行交互时,这个方法确实不言自明。

人工智能时代的产品定义

原文:https://towardsdatascience.com/product-definition-in-the-age-of-ai-619a417e3415?source=collection_archive---------4-----------------------

十年前,软件正在吞噬世界。但是,现在看起来人工智能正在吞噬世界。没有一天不发布新的算法、框架或库,使得将复杂的数学转化为杀手级产品变得更加容易。然而,有一点似乎很明显,那就是人工智能软件的产品定义。

原因并不太难理解。定义人工智能产品很难,也没有行业标准的方法论可言。在这篇文章中,我不会试图提供任何银弹,而只是分享一些想法和经验。但是在我们跳到基于人工智能的软件的具体例子之前,让我们先来看两个来自软件世界的典型例子。

传统软件开发

我们对产品定义的大部分直觉和方法来自传统的软件开发。在理想的情况下,构建软件产品包括以下步骤:从关于消费者行为的业务假设开始,从假设中导出规范,根据规范构建软件,测试软件是否符合规范,在生产中部署软件,以及确定假设的有效性。

一个电子商务网站的商业假设的例子可能是“如果我们实现一次点击结账过程,那么这将导致更高的转化率”。商业假设是对商业直觉的编纂,这可能是由大量的市场研究提供的。然而,一旦一个假设被公式化,它的前提(如果和那么之间的部分)的范围通常是非常狭窄和简单的。

产品规格只不过是满足商业假设前提的必要和充分条件的表示。对于上述假设,相应的规范可以是一键结账流程的线框。注意,我们可以明确地从假设中推导出规格说明。根据规范构建软件是一件复杂的事情。然而,一旦构建完成,检查它是否满足规范是相对简单的。该规范为构建和测试软件提供了充分的基础。

规范和测试之间的联系尤其重要。为了测试的目的,一个软件被视为一个给定输入产生输出的系统。传统的软件测试依赖于一个完整的、独立的测试预言的存在,即枚举所有可能的输入并为每个输入生成预期输出的方法,独立于软件本身。鉴于此,测试的目标是“简单地”验证软件是否为每个输入产生正确的输出。测试预言来自规范,而规范又来自假设的前提。因此,(前提)假设的简单性和狭隘性在传统软件开发的可行性中起着决定性的作用。

在传统的软件开发中,开发团队的目标是通过根据业务直觉构建软件来为业务产生价值。业务假设和产品规范一起构成了业务和软件之间的重要桥梁,也是每个人交互的共同基础。因此,假设和规范需要以产品经理、软件开发人员和测试人员可以理解的方式编写。

在传统的做事方式(即瀑布)中,不同的步骤(如假设生成或规范)是为整个产品顺序执行的。每个步骤都由不同的专家小组执行,并在不同步骤之间进行详细交接。事实证明这是一种相当低效的做事方式。因此,在更现代的敏捷/精益方法中,产品在短时间的迭代中被构建成小块。名义上,整个团队参与执行每个切片的所有步骤。典型地,假设和规范被编纂在一个用户故事或一个近亲中。

学术科学计算

另一端是在物理学和相关领域常见的高性能科学计算。例子包括预测亚原子粒子行为的晶格量子色动力学,以及许多学科中的计算流体动力学。在科学计算中,编写一个软件来寻找某个问题的(通常是近似的)答案。

科学计算很少考虑到上面提到的假设/规范分裂。考虑晶格量子色动力学的例子。这里的基本假设是“如果我们用量子色动力学理论来计算物理量,那么它们将非常接近我们从实验中得到的结果”。构建一个软件来测试这一假设的规范可能包括量子色动力学方程和“构建一个软件来根据这些方程计算物理量”的戒律。这实际上是对晶格量子色动力学的合理描述,但作为规范并不好,因为它对我们测试软件没有帮助。

使用不同技术的组合来执行科学计算的测试:精确可解的情况(可能有一些输入的输出可以使用替代方法精确计算),限制条件(通常结果在某些限制下容易计算,例如输入趋向于零或无穷大),以及试探法(给定以前的经验,输出是否“有意义”)。与商业软件测试相比,科学计算中的测试覆盖率,即测试中包含的(输入,输出)对的比例,通常要低得多。此外,测试方法需要对领域有非常深刻的理解。通常,这不是一个问题,因为软件的构建和测试通常是由科学家完成的,而他们恰好也是领域专家。

一般来说,科学计算中的假设和软件之间没有明确的解耦。这导致了规范的概念没有多大用处。因此,完整而独立的测试预言是不存在的:软件是根据输入(问题)来计算输出(答案)的。如果我们有另一种计算答案的方法,那么我们就不需要首先编写软件了!

人工智能产品

就其核心而言,人工智能软件开发非常类似于学术科学计算,因为假设与软件紧密耦合,导致不存在测试预言。然而,基于人工智能的商业产品的构建方式与传统软件开发非常相似;受商业直觉的驱使。此外,基于人工智能的产品往往是在看起来非常类似于传统软件开发团队的团队中开发的,只是增加了一个或多个数据科学家。其核心性质和开发方法之间的这种阻抗使得产品定义对于基于人工智能的产品来说非常具有挑战性。

具体来说,让我们考虑一个电子商务网站推荐系统的典型例子。基于商业直觉的一个可能的假设可能是“如果向客户展示相关产品,那么转换率将会增加”。这个几乎显而易见的假设抓住了建立推荐系统背后的基本动机。此外,它的优点是任何参与构建电子商务软件的人都容易理解。它也足够广泛,可以支持非常强大的人工智能算法的开发。

但是,从定义产品的角度来看,这个假设并不好。不可能从中得出明确的规范。问题在于“相关”一词的模糊性——在这种情况下什么是相关的?当涉及到派生产品规格,以及构建和测试软件时,它并不是非常有用。

那么这给我们留下了什么?在我们继续深入之前,让我们试着去理解构建一个商业假设所涉及的不同维度。我认为,我们需要考虑两个主要的相关方面。

第一个维度是假设的一般性。传统的软件开发基于这样一种假设,即可以将市场研究和商业直觉提取到一组狭窄但有用的假设中,然后用这些假设来构建软件。另一方面,基于人工智能的算法的全部力量来自于能够从非常一般的假设出发。考虑前面提到的推荐系统的情况。我们可以将假设缩小到“如果我们向试图购买尿布的男性用户展示啤酒,那么这将增加篮子的大小。”显然,在这种情况下,我们将能够从中导出精确的规范,并构建软件来支持它。在这种情况下,恭喜你,你刚刚建立了你的第一个基于规则的系统!如果我们要利用人工智能的力量,那么这种狭隘的假设不是答案。

第二个维度是假设的可理解性。这种可理解性是关于普通产品开发团队的所有成员都知道的公共词汇。考虑假设“给定一个上下文(由用户的历史、用户的特征、产品目录定义),以及在具有相似上下文的历史数据上训练的两个算法,其中相似性按照,如果基于来自具有较高分数的算法的推荐来显示产品,那么这将导致较高的尽管上面的假设对于支持算法开发来说是足够通用的,但是在目前,对于产品开发中的非数据科学家来说,它几乎是不可理解的。

我们需要记住另一个重要的约束。真正面向业务的数据科学人才稀缺。因此,在谷歌和脸书这样的巨头之外,基于人工智能的产品将继续被开发,至少在不久的将来,在数据科学家、商业分析师、软件开发人员和软件测试人员的多样化团队中,他们充其量对彼此的领域有着肤浅的了解。

鉴于上述限制,我们不能完全牺牲可理解性。另一方面,如果我们要利用人工智能的力量,那么我们也不能完全牺牲通用性。然而,这里要注意的重要一点是,在大多数情况下,没有必要开发“最好的”或最强大的算法。相反,我们需要的是开发一个“足够好”的解决方案。然而,当你在构建一个新的东西时,通常不可能计算出达到“足够好”阶段所涉及的工作量(根据工时),也就是说,你不能用时间框来确定一个可行的解决方案!

事实上,足够好的界限可以也应该根据商业现实来设定。缺少的是常用词汇。为了理解共享词汇的重要性,让我们考虑一下科学研究的例子,特别是科学方法。通过敏捷和精益运动,科学方法已经在软件开发社区中得到推广。很大程度上没有强调的是,在一个学科中拥有一个通用词汇对于科学方法起作用的重要性。典型的科学方法包括试图通过建立一个假设来理解一个现象,从它构建一个理论,运行模拟和实验来验证它。这些步骤中的每一步通常由不同的科学家小组执行,他们可能不深入了解彼此的工作。然而,他们详细了解的是每一部作品中的主张和结果。这是可能的,因为它们共享一个词汇表。在物理学中,这个词汇通常是建立在数学之上的。在化学方面,除了数学和化学反应的语言。其他科学学科也是如此。

我们当前的软件开发词汇很大程度上是由 web 开发设定的。这种主要由线框构成的词汇在构思基于人工智能的产品时完全没有用,可能应该是第一个需要扔出窗外的东西。

与物理学一样,人工智能的常用词汇也建立在数学之上,更重要的元素是概率论和统计、线性代数和优化原理。人工智能产品开发的词汇表必须由上述的“用户友好”子集组成。例如,一个人能够创建和解释一个线框,而不需要理解 API 调用是如何进行的,或者市场研究是如何完成的。人工智能的“线框”相当于什么?我认为一个好的起点是描述性统计,即业务假设和产品规格至少需要使用描述性统计的词汇来编写。

在人工智能时代,另一个需要受到挑战的公认观点是,市场研究和软件开发是完全不同和分离的学科,软件的目标是提供一种验证商业假设的方法,而不是提供信息。对于基于人工智能的软件来说,这个假设显然是错误的。由于基于人工智能的软件中假设和软件之间的紧密耦合,几乎不可能将学习(或探索)和实践(或利用)阶段分开。有鉴于此,重要的是不仅要把人工智能作为验证商业直觉的工具,还要把它作为建立商业直觉的工具。

事实上,一旦一个人有了足够的知识,相关的动作要么可以直接导出,要么可以经常使用现成的人工智能算法来计算出相关的动作。因此,人工智能产品假说的主要焦点可能应该是学习,而不一定是做。而什么是需要学习的信息也应该由 AI 来告知。

与任何新的范式转换技术一样,业务流程需要一段时间才能跟上。AI 也不例外。从长远来看,我相信在更广泛的产品开发社区中对人工智能的基本理解是解决方案。然而,从短期来看,我们不能指望产品经理一夜之间成为数据科学家。然而,我们可以期待他们成为数据素养。另一方面,我们应该期待数据科学家从他们的算法中抬起头来,理解企业价值创造的基础。

产品发布公告:Mateverse 高级— V 1.0

原文:https://towardsdatascience.com/product-launch-announcement-mateverse-high-level-v-1-0-e51577dab05f?source=collection_archive---------9-----------------------

让你在 5 分钟内训练 ML 模型,并将机器学习引入 IFTTT 的产品变得更加先进。

S 我们中的一些人已经在我们的业务中实现了机器学习,还有一些人仍在考虑使用它。统计数据预测,到 2021 年,人工智能的使用将大幅增加。许多人反复写了人工智能技术将如何变革的主题,并将人工智能称为第三次工业革命。我们不打算深入探讨这个问题,但让我们来看看 Mateverse 是如何出现的。

TL;博士对人工智能在社会中的巨大影响的故事是:机器学习正在渗透到每一个其他商业组织。因此,这使得他们的流程(内部和外部)变得非常简单。

从大公司开始,以满足独特客户需求的多种销售转换达到顶峰,开始进入较小的组织。诸如分析、销售台、用户界面等领域在小公司中经历了巨大的转变。现在,消息比以往传播得更快。

Source: McKinsey Global Institute

坦率地说,除了成本之外,没有什么能阻止较小的组织实现较大的组织所能实现的。这种昂贵的事情对较小的组织来说是一种折磨。很快,通过开源算法和预训练的人工智能模型的可用性,人工智能及其重要的对等物机器学习变得可以访问。

另一个没有被很多人注意到的事实是如此猖獗的适应在世界各地的公司中发生的时候,猜猜谁是 ML 项目出问题的首当其冲者?他们是分析师和数据科学家,他们独自承担推动分析的任务,几乎没有其他部门的帮助。有很多数据科学家跳槽或从事非常不满意的工作的案例,要么是因为他们没有机会做他们力所能及的事情,要么是因为他们被迫在基础设施不足的情况下完成喜马拉雅山的任务。

我们真的不能责怪任何人,考虑到人工智能和人工智能是非常新的技术,试图摆脱他们周围的炒作和恐惧。

我们在 Mate Labs 开始构建我们的产品——Mate verse,在确定和了解所有的基础上好吧,行业的斗争已经在我们之前尝试过的各种项目中进行。当我们一段时间以来试图为机器学习中涉及的巨大而平凡的过程找到一个可靠的解决方案时, Mateverse V1.0 终于问世了点燃..时代..与世界上的科技公司斗争,并在一个致力于帮助我们将人工智能带给大众的社区中寻找意愿。

斗争(勇气)是真实的。

在用 Mateverse beta 版本测试了这个想法之后,我们从大型跨国公司背后的小型企业和分析师那里得到了压倒性的回应,这些小型企业和分析师以前不知道 ML 如何帮助他们的业务,或者没有太多的发挥空间。mate verse 无需为建模编写一行代码,使公司部署预测模型变得简单了数倍,并为他们的业务带来了加速的影响。

回到阻碍企业实施 ML 的因素,我们将把这些点联系起来,并与您讨论如何,其中 Mateverse 是一个成本削减者,也是一个“努力削减者”。

也许,带你了解 Mateverse 如何削减成本和精力的最佳方式是通过机器学习的步骤。让我们举一个构建预测分析模型的最佳例子

虽然自动化机器学习中的当前解决方案看起来如下:

获取数据— ->完美的预测

绝对不是那样的。

惹恼数据科学家的最好方法是假设手头有一些数据就太容易了。更糟糕的是,不完整和不一致的数据永远无法完成一个项目。

尽管如此,我们还是有办法让数据科学家更容易更快地部署模型,我的意思是,快得多。

为了部署预测模型(举个最好的例子),所涉及的步骤可以总结如下:

  1. 数据收集

在数据收集阶段,Mateverse 支持所有常见类型的数据库 HDFS/RDBMS/NoSQL,或者你可以只上传一个 CSV 文件,数据库就创建好了。就这么简单。

Image 1 — Mateverse Workflow chart

2。数据准备

数据准备从连接数据库中的多个表开始。这需要使用 SQL 脚本的技能,这是一项有点乏味的任务。现在, Mateverse 为用户提供了一个图形界面来做这件事。表连接功能允许最终用户以 7 种不同的方式创建混合数据集

此外,在大多数情况下,一个数据分析师/科学家团队处理一个数据集,由于数据集的数量和大小,他们会将其划分为子集。然而,多人同步处理同一个数据集以前从未得到过支持。现在,通过 Mateverse 的 pro-collaboration 平台,团队管理员可以分配/委派职责,每个成员可以同时处理同一个数据集,同时保持对团队其他成员所做编辑的更新。

3。数据清理

数据清理的经典方法包括分析师和数据科学家在多个步骤之间周旋,同时专注于几个点。收集的数据并不总是完美的形式。事实上,从来都不是。假设从零售商店收集数据,可能会有一些丢失的值未能在系统中注册,或者以难以检索的格式存储。如果没有丢失数据,也可能有不适合、不相关或不可用的数据。数据也可能被混淆、歪曲和归类到错误的部分。如果听这个很难,处理这些错误是数据人员一直在努力的事情。因此,当数据科学家被期望在一夜之间转变数据时,难怪他们会感到沮丧。

Mateverse V1.0 — Automated Data Cleaning

从技术角度来说,一些数据清理方法是—缺失值处理、数据标记化和异常值检测。

Mateverse 已经把这个变成了一键式流程。你怎么问?我们已经建立了一个智能系统,它已经在成千上万的数据集上进行了准确的训练。

Mateverse V1.0 — Manual Data Cleaning

4。数据格式化

数据处理的这一部分是数据科学家仔细研究的又一套乏味的方法。这是数据科学家确保被清理的数据中没有错误,然后对其应用转换的地方。理解收集的数据是机器学习的主要工作人工。除非这部分数据准备能够得出准确的预测,否则机器的学习可能会犯下严重的错误。

一组规则指导这一阶段的数据准备。这些规则/方法包括:分类、聚类、回归和排序。再次以零售业为例,这些规则集可以帮助机器学习给定数据之间的关系。明显的分类,像性别或者年龄,或者不那么明显的聚类,像消费习惯,财务能力等等。只有过了这个阶段,数据科学家才能松一口气,因为她/他的大部分工作已经完成。

Mateverse 将消除流程中涉及的过多人工工作,并让专家们花费大量时间来试验不同类型的模型。

Image 2 — Comparison- Mateverse vs other automated ML platforms

既然我们已经建立了近乎完美的数据集,下一步就是训练一个预测模型。这涉及到两个步骤:

5。算法选择

机器学习的核心在于选择合适的算法。算法的作用是从准备好的数据中做出解释。特定算法的选择取决于最终模型的预期功能。这些算法从统计算法到基于树的算法,再到贝叶斯算法。事实上,有无数种可能的算法。

数据科学家对数百种算法进行实验,以最终选择能够获得最佳结果的算法。

6。超参数优化/模型训练

根据模型试图解决的特定问题,在模型上使用超参数调整。超参数调整可创建最佳预测模型。这是一个复杂的过程,优化机器学习的这一部分是一项艰巨的任务。

Mateverse V1.0 — Automated Machine Learning

Mateverse 通过模仿数据科学家处理问题的方式,使前面提到的步骤成为一键操作的过程,反过来优化数据科学家的工作,就像她的助理 T21 一样。

7。可视化效果

你会发现数据分析师对他们的可视化很挑剔,这并不罕见,因为正确和适当的可视化会给数据带来价值和清晰度。我们在 Mateverse 中支持超过四打可视化图表。

Mateverse has in-built support for an array of visualization charts, some of which are shown here.

8。部署

Mateverse 允许在数据流上部署模型,预测是实时的,并且在现场。你可以部署在 Mateverse 的仪表盘上进行实时更新,也可以使用 API 将其集成到自己的产品中。

如果你认为这个平台对你有帮助,请在这里告诉我们。

关于

Mate Labs 我们已经构建了 Mateverse ,一个机器学习平台,在这里你可以在几分钟 s 内构建定制的 ML 模型,而无需编写一行代码。我们的平台让每个人都能轻松构建和训练机器学习模型,无需编写一行代码。欢迎致电mate @ mate labs . in联系我们

让我们携起手来。

Twitter 上与我们分享你的想法。

如果你有新的建议,请告诉我们。我们的耳朵和眼睛总是为真正令人兴奋的事情而张开。

生产数据科学

原文:https://towardsdatascience.com/production-data-science-3a42dee5208?source=collection_archive---------8-----------------------

面向生产的协作数据科学工作流

去年,在萨塔利亚,我正在进行一个合作数据科学项目。项目进展顺利,但是我和我的合作者忽略了好的实践,当探索和建模数据时,我们没有记住我们最终是在构建一个产品。当我们自动化生产我们的最佳模型时,这些疏忽在工作接近尾声时浮出水面。

在我们完成这个项目后,我寻找现有的方法来开展协作数据科学,并在脑海中留下一个最终产品。我只能找到一些关于这个主题的资源,而且我找到的资源只集中在特定的领域,比如数据科学的测试。此外,在与数据科学学生交谈时,我了解到他们也没有学习良好的编码实践或与其他人合作的有效方法。

我从查看可以轻松应用于数据科学的软件开发实践开始。最直接的选择是使用 Python 虚拟环境来确保工作的可重复性,使用 Git 和 Python 打包工具来简化软件的安装和贡献过程。尽管我知道这些实践和工具,但通过遵循在线数据科学教程,我养成了只分享 Jupyter 笔记本的习惯。 Jupyter 笔记本适用于独立的探索性分析,但仅靠笔记本不足以创造产品。然而,我不想放弃笔记本,因为它们是一个很好的工具,提供了一个交互式的非线性平台,适合探索性分析。那时,我一方面有探索性分析,另一方面有生产化,我想把它们结合在一个简单的工作流程中。

敏捷软件开发中的一个通用工作流交替进行新特性的开发和重构。这个循环允许包含满足当前用户需求的新特性,同时保持代码库的精简和稳定。在数据科学中,为用户开发新功能被通过数据探索寻找洞察力所取代。这一观察引出了生产数据科学工作流的中心主题:探索-重构循环

如上图所示,探索-重构循环交替进行探索和重构。探索通过分析增加了新的洞察力,从而增加了项目的复杂性。重构通过将部分分析整理到产品代码库中来降低复杂性。换句话说,生产代码库是用于获得洞察力的代码的一个提炼版本。最重要的是,洞察力部分来自代码,主要来自演绎推理。数据科学家使用代码,就像夏洛克·福尔摩斯使用化学来为他的推理路线获取证据一样。

Jupyter notebooks 允许我们使用格式化文本叙述我们的推论,并在同一文档中编写支持代码。然而,文本解释通常不被重视,并且被冗长的代码所掩盖。因此,在数据科学中,重构应该包括代码和基于文本的推理。将来自 Jupyter 笔记本的代码重构为 Python 包将演绎推理变成了笔记本的主角。在代码的支持下,笔记本变成了一块画布,通过使用文本来证明关于数据的一个观点。这类似于文化编程,其中文本被用来解释和证明代码本身。在这种观点下,所有的细节都被剥离,笔记本是文本和代码的结合。

同样,在中,定量信息的视觉显示, Tufte 将信息图形定义为数据墨水和非数据墨水的组合。数据墨水是代表数据的墨水量,非数据墨水代表其余部分。因为承载信息的是数据墨水,所以数据墨水应该是信息图形的主角。当非数据墨水抢镜时,信息稀释了无信息内容。Tufte 建议通过合理地最大化数据墨水和最小化非数据墨水来改善信息图形。同样,当把笔记本看作推理的手段时,文字应该是主角;文本不应被代码遮蔽。这导致了重构笔记本的一个简单规则:文本重于代码。

我在软件开发中遇到过类似的想法:功能是资产,代码是负债。换句话说,功能是软件应该提供的,同时保持一个小的代码库,因为代码库越大,维护成本越高,出现错误的几率也就越大。数据墨水优于非数据墨水、文本优于代码、功能优于代码的共同点是,在工作中要考虑到与他人的合作,也就是说,要关心人们在工作中的体验。

类似地, Python 、吉多·范·罗苏姆的创造者指出代码被读取的次数比它被编写的次数多得多。的确, Python 的设计强调可读性。忽略可读性,我们可以通过不清理代码来节省一个小时,而每个合作者可能会损失两个小时来理解它。如果我们与三个人合作,节省了一个小时,六个小时可能会浪费在挫折中。所以,如果每个人都这样做,每个人都输了。相反,如果每个人都与他人一起工作,那么每个人都是赢家。此外,当谈到其他人时,我不仅指我们的合作者,也指我们未来的自己。原因是,几个月后我们很可能会忘记我们现在正在做的事情的细节,我们将处于与我们的合作者相似的地位。出于这些原因,以下原则在整个生产数据科学工作流程中设定了主题:让其他人和你未来自己的生活更轻松

放松他人的生活和探索-重构循环是生产数据科学工作流的本质。在这个工作流程中,我们从建立一个项目开始,这个项目的结构强调协作,协调勘探和生产。有了这个结构,我们进入探索-重构循环的第一阶段:探索。在这里,我们使用 Jupyter 笔记本来分析数据,形成假设,测试它们,并使用获得的知识来建立预测模型。一旦我们完成了一个分析,我们在文本代码规则的指导下重构笔记本的主要部分。代码从笔记本流向生产代码库,推理线成为笔记本的主角。探索和重构然后迭代直到我们到达最终产品。

点击了解生产数据科学工作流程。

查看我个人网站上的文章!

使用自定义 IPython 扩展进行富有成效的研究

原文:https://towardsdatascience.com/productive-research-with-custom-ipython-extensions-fc7627756370?source=collection_archive---------9-----------------------

在过去的一年里,我对数据科学和机器学习越来越感兴趣。在这样做的时候,我注意到每次我想进行一些研究时,我都必须在 IPython 和 Jupyter notebook 中执行相同的重复任务,这使我脱离了心流。为了解决这个问题,我构建了一些定制的 IPython 扩展,极大地提高了我的工作效率。我想和你们分享这些扩展,我是如何构建它们的,以及我如何在日常研究中使用它们。扩展的示例代码可以在下面找到。此外,在这篇文章的第二部分中,我还谈到了我是如何将 BigQuery 支持直接构建到 IPython 中的。

作为深入研究数据科学和机器学习的必然副作用,我一直在写大量的 Python,我真的很喜欢。Python 实际上是数据科学的通用语。这产生了一个令人难以置信的工具和技术生态系统。我特别喜欢用 Jupyter 笔记本在 IPython 、尤其是内部做研究分析。说到快速原型和探索,Jupyter 是一个梦想。它允许我以一种简单、直观的方式快速尝试想法。这也迫使我记录下我是如何找到一个问题的最终解决方案的,这在重新整理一些我很久没看的旧工作时非常有用。

当我第一次启动 iPython/Jupyter 时,我几乎总是预先导入相同的模块:

如果您从事大量的数据科学工作,这应该是您非常熟悉的前奏。如果没有,这些是使用 python 进行研究和分析时使用的一些核心数据处理和可视化库。

在将完全相同的样板文件输入 20 个笔记本后,我开始寻找将这些导入文件自动放入我的环境的方法。

输入自定义 IPython 扩展。扩展允许您连接到您的 IPython 环境,并根据您的需要修改它。这正是我要找的🙏🏻。我首先制作了自己的自定义扩展,将所有这些库导入到研究环境中,并配置了 matplotlib。

首先,如果你想知道: InteractiveShell业务是关于什么的,那是 Python 的类型提示语法的一部分。我已经习惯了使用这种语法,因为当它与 VSCode 的 Python 扩展一起使用时,它提供了很好的开发人员工效学,这是我的首选 Python 开发环境。load_ipython_extension基本上是 ipython 扩展的main()函数;当一个扩展最初通过%[re]load_ext被加载时,它被调用,并用于引导扩展,以及“注册魔法”(稍后将详细介绍!).上面,我使用 enable_matplotlib() 以及 push() 方法来代替必须手写这个前奏。

一旦我有了扩展的框架,我就写了一个简单的setup.py脚本,用来符号化扩展,这样我就可以从任何笔记本上加载它。在运行设置脚本之前,我添加了install_requires作为对我是否处于正确环境的健康检查。

这几乎是我开始工作所需要的全部。一旦我运行了python setup.py develop,我就可以在任何笔记本或 IPython shell 上使用我的扩展了!

注意,我在那里使用了 *reload_ext* ,这样,如果我重新运行该命令,它仍然会工作(因为 *reload_ext* 是幂等的)

我只需要这一行就可以加载我想使用的所有库。随着时间的推移,这种按键的节省真的对我很有帮助。此外,通常当我在命令行上打开 IPython 时,这是因为我有一个想快速尝试的想法。在加载时拥有我需要的所有库使我保持流畅,而不必记住(或复制/粘贴)样板文件。

继续阅读这篇博文的第 2 部分,看看如何使用✨cell magic✨直接从 IPython 查询 BigQuery 。

使用定制 IPython 扩展进行富有成效的研究,第 2 部分:BigQuery 魔术

原文:https://towardsdatascience.com/productive-research-with-custom-ipython-extensions-part-2-bigquery-magic-edc3e311fdc5?source=collection_archive---------9-----------------------

在完成了用于导入数据科学库的自定义 IPython 自动加载器扩展之后,我试图为自己节省更多的时间。我想通过从 IPython 查询 BigQuery 直接访问我的数据仓库中的数据。这篇博文描述了我解决这个问题的方法。我在底部添加了一个“附录”,展示了使用我的扩展对 BigQuery HackerNews 数据集进行的一些示例分析。

然而,我应该指出,BigQuery Python 客户端实际上内置了 IPython 支持。我在不知道这一点的情况下构建了我的扩展,但我仍然发现这个练习很有用,因为它揭开了 IPython 扩展的神秘面纱。

我使用 Google 的 BigQuery 作为我的首选数据仓库;它非常健壮,速度非常快,易于使用,而且性价比超高。大多数时候,我发现自己在查询 BigQuery,并使用 BigQuery 的 python 客户端库将结果加载到 dataframe 中。如果我可以在 IPython 单元格中键入一个 SQL 查询,并让单元格在 BigQuery 上执行该 SQL 并将结果存储在 DataFrame 中,这不是很棒吗?我希望能够做这样的事情:

事实证明,通过使用单元格魔术,在 IPython 中将 BigQuery 的 SQL 直接嵌入笔记本单元格是可能的。单元格魔术是那些看起来像%%this的命令,它读取整个单元格的内容并调用注册的魔术函数,这两个位置参数linecell.``line包含用于调用单元格魔术的行的字符串,例如%%bq行。cell参数也是一个包含单元格其余内容的字符串,不包括行。
如果我们以上面的例子为例,魔术函数bq将被调用,其中"--name hn_daily_comment_counts"作为line参数,而"SELECT\n...\nday ASC;"——或者初始行之后的剩余单元格的内容——作为cell参数。

我们可以将 BigQuery python 客户端与 cell magic API 一起使用,让 magic 函数查询 BigQuery 并返回结果。

正如你在上面看到的,我在一个ResearchEnvMagics类中包含了我所有的魔法(在这个例子中只有一个)。重要的是,这个类继承自 IPython 的 Magics 类,并且附加了@magics_class装饰器。

我还使用了 IPython 的 magic_arguments 包,以便允许向我的 cell magic 传递额外的配置参数,类似于您在命令行上使用的。这是 IPython magics 的一个常见模式,因此他们为它提供了一个内置的包,这太棒了!

这里的最后一步是通过扩展加载钩子向 IPython 注册这些 magics:

这就是全部了!现在,magic 功能已注册,可以在 Jupyter 笔记本中使用,轻松进行研究并获得见解。

当然,在构建了这个 BigQuery magic 之后,有一天晚上我通过挖掘客户端库 API 文档发现它已经随 IPython magics 一起发布了😑。我希望在某个地方已经记录了这一点,但是我仍然喜欢构建它,并且在 IPython 中学到了很多关于细胞魔法的知识。下一步,我想弄清楚如何为 BigQuery 单元格魔术添加 SQL 语法突出显示。

我希望您觉得这很有用,如果您在研究环境中使用特殊的定制 IPython magics,请在评论中告诉我!愿意分享信息和建议。请查看下面的内容,了解 BigQuery 的 HackerNews 数据集中一些示例查询的扩展。

Simple example using BigQuery to display daily comment counts.

A more advanced example looking at comment “shocks” by taking the weekly moving average and dividing it by the weekly moving standard deviation.

Cleaning, annotating, and charting the data from the previous query. Note that I used scale() above while I was examining the data in order to de-mean it. Apparently, a post on dealing with alienation was a huge driver of comments on HackerNews around the 2008–2010 time. Very poignant, and probably deserves an article unto itself.

用数据流生产 ML 模型

原文:https://towardsdatascience.com/productizing-ml-models-with-dataflow-99a224ce9f19?source=collection_archive---------2-----------------------

Source (PublicDomainPicture): https://pixabay.com/en/baby-boy-child-childhood-computer-84627/

在我的数据科学职业生涯中,我面临的一个关键挑战是将探索性分析的发现转化为可扩展的模型,为产品提供动力。在游戏行业,我建立了几个预测模型来识别玩家流失,但将这些模型投入生产总是很困难。我曾经写过 Twitch 上用于生产模型的一些流程,但是每个产品团队都需要独特的方法和不同的基础设施。

在意外收获,我们授权我们的数据科学团队拥有产品化模型的过程。我们没有依赖工程团队将模型规范转化为生产系统,而是为我们的数据科学家提供缩放模型所需的工具。为了实现这一点,我们使用预测模型标记语言( PMML )和谷歌的云数据流。以下是我们在意外收获构建和部署模型的工作流程:

  1. 模型是用 R 或 Python 离线训练的
  2. 训练有素的模型被翻译到 PMML
  3. 数据流作业接收用于生产的 PMML 模型

这种方法使数据科学家能够在本地使用采样数据集来训练模型,然后在我们的整个数据集上使用结果模型规范。步骤 3 可能需要工程团队的一些初始支持,但只需要设置一次。使用这种方法意味着我们的数据科学团队可以使用 PMML 支持的任何预测模型,利用托管数据流服务意味着团队无需担心维护基础架构。

本教程介绍了使用 Java SDK for Cloud Dataflow 从 R 中训练的离线模型转换为产品化模型的步骤。本教程中的所有代码都可以在我的 github 档案中找到。我们使用可用于 BigQuery 的出生率公共数据集,并训练一个线性回归模型来基于许多因素预测婴儿出生体重。数据流作业从公共数据集中读取记录,将训练好的回归模型应用于每条记录,并将结果写入我们的 BigQuery 项目中的一个表。这是我们的数据科学团队在为客户构建定制模型时采用的工作流,例如使用随机森林模型进行线索评分。

我们需要做的第一件事是熟悉出生率数据集,它记录了 1969 年至 2008 年间美国的出生人数。本中的帖子提供了关于该数据集的更多详细信息。我们使用 BigQuery web 接口编写一个查询来对数据集进行采样。该查询为每次出生提取以下属性:

  • 年份:出生的年份
  • 复数:分娩的孩子数
  • apgar_5min: 新生儿出生 5 分钟后的健康评分
  • 母亲 _ 年龄:母亲的年龄
  • 父亲 _ 年龄:父亲的年龄
  • 妊娠周数:进入妊娠的周数
  • 这位母亲生了几个孩子
  • 母亲已婚:孩子出生时,母亲已婚吗?
  • 体重 _ 磅:婴儿的体重(我们预测的)

为了在 R 中处理这个数据集,我们使用了优秀的 bigrquery 库,这使得将 BigQuery 结果读入数据帧变得很容易。我们提取一个样本数据集如下:

**library**(bigrquery)
project <- "gcp_project_id"sql <- "SELECT year, plurality, apgar_5min, mother_age, father_age,    gestation_weeks, ever_born, mother_married, weight_poundsFROM `bigquery-public-data.samples.natality`order by rand() LIMIT 10000 
"df <- query_exec(sql, project = project, use_legacy_sql = **FALSE**)

然后,我们可以对数据集进行各种操作,如summary(df)hist(df$df$weight_pounds),这将生成下面的图表,显示婴儿体重在采样数据集中的分布。

Distribution of birth weights in the sampled data set.

接下来,我们训练一个线性回归模型来预测出生体重,并计算误差指标:

lm <- lm(weight_pounds ~ ., data = df)
summary(lm)cor(df$weight_pounds, predict(lm, df))
mean(abs(df$weight_pounds - predict(lm, df))) sqrt(mean(abs(df$weight_pounds - predict(lm, df)^2)))

这会产生以下结果:

  • 相关系数:0.335
  • 平均误差:0.928
  • RMSE: 6.825

模型性能相当弱,可以探索其他算法和功能来改进它。由于这篇文章的目标是专注于将模型产品化,因此经过训练的模型就足够了。用于训练模型的完整笔记本可在这里获得。

翻译成 PMML 下一步就是把训练好的模型翻译成 PMML。 r2pmml R 包和 jpmml-r 工具使这一过程变得简单,并支持各种不同的算法。第一个库将 R 模型对象直接转换成 PMML 文件,而第二个库需要将模型对象保存到 RDS 文件,然后运行命令行工具。我们使用第一个库直接进行翻译:

**library**(r2pmml)
r2pmml(lm, "natality.pmml")

这段代码生成下面的 pmml 文件。PMML 文件格式指定用于模型的数据字段、要执行的计算类型(回归)以及模型的结构。在这种情况下,模型的结构是一组系数,定义如下:

<RegressionTable intercept="7.5619">   <NumericPredictor name="year" coefficient="3.6683E-4"/>   <NumericPredictor name="plurality" coefficient="-2.0459"/>   <NumericPredictor name="apgar_5min" coefficient="9.4773E-5"/>   ...<NumericPredictor name="mother_married" coefficient="0.2784"/>  
</RegressionTable>

我们现在有了一个模型规范,可以将其产品化并应用于我们的整个数据集。

使用云数据流进行产品化 使用 Dataflow Java SDK 时,您可以定义一个要在一组对象上执行的操作图,服务将根据需要自动配置硬件进行扩展。在这种情况下,我们的图是一组三个操作:从 BigQuery 读取数据,计算每条记录的模型预测,并将结果写回 BigQuery。本教程生成以下数据流 DAG:

The Dataflow graph of operations used in this tutorial.

我们使用 IntelliJ IDEA 来创作和部署数据流作业。虽然设置 Java 环境超出了本教程的范围,但是用于构建项目的 pom 文件可以在这里获得。它包括对数据流 sdk 和 JPMML 库的以下依赖关系:

<dependency>            <groupId>com.google.cloud.dataflow</groupId>              <artifactId>google-cloud-dataflow-java-sdk-all</artifactId>   <version>2.2.0</version>        
</dependency><dependency>            <groupId>org.jpmml</groupId>            <artifactId>pmml-evaluator</artifactId>            <version>1.3.9</version>  
</dependency>

如上图所示,我们的数据流工作由三个步骤组成,我们将详细介绍这三个步骤。在讨论这些步骤之前,我们需要创建管道对象:

PmmlPipeline.Options options = PipelineOptionsFactory.fromArgs(args).withValidation().as(PmmlPipeline.Options.class); 
Pipeline pipeline = Pipeline.create(options);

我们创建一个管道对象,它定义了应用于对象集合的一组操作。在我们的例子中,管道正在对一组 TableRow 对象进行操作。我们将一个选项类作为输入传递给 pipeline 类,该类为数据流作业定义了一组运行时参数,例如用于运行作业的 GCP 临时位置。

管道中的第一步是从公共 BigQuery 数据集中读取数据。从这一步返回的对象是 TableRow 对象的一个p 集合。特征查询字符串定义要运行的查询,并且我们指定在运行查询时要使用标准 SQL。

private static final String featureQuery =     "SELECT year, plurality, apgar_5min ... weight_pounds\n" +"FROM `bigquery-public-data.samples.natality`";pipeline.apply(BigQueryIO.read().fromQuery(featureQuery)           .usingStandardSql().withoutResultFlattening())

下一步是将模型预测应用于数据集中的每条记录。我们定义了一个 PTransform 来加载模型规范,然后应用一个 DoFn 在每个 TableRow 上执行模型计算。

.apply("PMML Application", new PTransform<PCollection<TableRow>,PCollection<TableRow>>() {model = new RegressionModelEvaluator(PMMLUtil.unmarshal(Resources.getResource("natality.pmml").openStream()));return input.apply("To Predictions", ParDo.of(new DoFn<TableRow, TableRow>() {           @ProcessElement          public void processElement(ProcessContext c) throws Exception {/* Apply Model */
}})))

应用模型代码段如下所示。它检索 TableRow 以创建估计值,为 pmml 对象创建输入字段的映射,使用模型估计出生体重,创建新的 TableRow 以存储出生的实际和预测体重,然后将此对象添加到此 DoFn 的输出中。总而言之,这个应用步骤加载模型,定义一个函数来转换输入集合中的每个记录,并创建预测对象的输出集合。

TableRow row = c.element();HashMap<FieldName, Double> inputs = new HashMap<>();            
for (String key : row.keySet()) {              if (!key.equals("weight_pounds")) {                   inputs.put(FieldName.create(key), Double.parseDouble(row.get(key).toString()));              }
}Double estimate =(Double)model.evaluate(inputs).get(FieldName.create("weight_pounds"));TableRow prediction = new TableRow();            prediction.set("actual_weight", Double.parseDouble(row.get("weight_pounds").toString()));            prediction.set("predicted_weight", estimate);c.output(prediction);

最后一步是将结果写回 BigQuery。在本课的前面,我们定义了将记录写回 BigQuery 时要使用的模式。

List<TableFieldSchema> fields = new ArrayList<>();    
fields.add(new TableFieldSchema().setName("actual_weight").setType("FLOAT64"));    
fields.add(new TableFieldSchema().setName("predicted_weight").setType("FLOAT64"));    
TableSchema schema = new TableSchema().setFields(fields);.apply(BigQueryIO.writeTableRows().to(String.format("%s:%s.%s",  PROJECT_ID, dataset, table))   .withCreateDisposition(BigQueryIO.Write.CreateDisposition     .CREATE_IF_NEEDED).withSchema(schema));pipeline.run();

我们现在已经定义了一个管道,可以运行它来为整个数据集创建预测。这个类的完整代码清单可以在这里找到。运行这个类将启动一个数据流作业,该作业将生成上面显示的 DAG,并将提供许多 GCE 实例来完成该作业。下面是一个用于运行此管道的自动缩放示例:

Autoscaling the Model Predicting Task

当作业完成时,输出是 BigQuery 项目中的一个新表,它存储了出生率数据集中所有记录的预测和实际权重。如果我们想要运行一个新的模型,我们只需要在数据流作业中指向一个新的 PMML 文件。运行离线分析和数据流项目所需的所有文件都可以在 Github 上获得。

数据流是一个伟大的工具,使数据科学家能够将他们的模型产品化。它提供了一个可扩展到大型数据集的托管环境,并使数据科学团队能够拥有更多生产流程。

本·韦伯是意外收获数据的首席数据科学家,我们的任务是确定世界上每个家庭的净资产。

ProGAN:NVIDIA 如何生成前所未有质量的图像

原文:https://towardsdatascience.com/progan-how-nvidia-generated-images-of-unprecedented-quality-51c98ec2cbd2?source=collection_archive---------3-----------------------

Images generated by progressively growing GANs with ProGAN. These are not real people. *Image taken from the paper.

逐渐生长的 GANs 使它们变得更大更稳定

上面高分辨率图像中的人看起来可能是真实的,但实际上不是——他们是由一个对数百万名人图像进行训练的程序合成的。“ProGAN”是 NVIDIA 首创的一种生成性对抗网络的口语术语。Karras 等人去年在为提高质量、稳定性和变异而进行的 GANs 渐进生长中发表了该研究。在这篇文章中,我们将通过这篇文章来了解这种类型的网络是如何工作的,它是如何产生像上面这样的图像的,以及为什么这是一个突破。

这篇文章假设你熟悉一般视觉任务的深度学习,但不是说你对 GANs 有广泛的了解。

甘斯简史

一种新的生成模型

生成敌对网络(GANs)已经存在几年了。蒙特利尔大学的 Ian Goodfellow 和他的同事在 2014 年的一篇著名论文中介绍了它们,从那以后它们一直是一个热门的研究领域。

简而言之,GANs 是一种生成模型,它试图合成与训练数据难以区分的新数据。这是一种无监督学习的形式。它有两个竞争锁定的神经网络:一个是发生器,它被输入一个随机数向量并输出合成数据;一个是鉴别器,它被输入一条数据并输出它来自训练集的概率(与合成相对)。换句话说,生成器创建“假的”,鉴别器试图将这些“假的”样本与“真的”样本区分开来。

In a typical GAN, a random code z is fed into the generator G to produce a ‘fake’ sample. A discriminator network D is then (separately) fed both the generated sample x’, and a real sample x from the training set. It assigns a probability of being ‘real’ to each, which depends on how convincing the fake is, and how sophisticated the discriminator has become. Both these probabilities are then used to compute the adversarial loss, from which we train both D and G via backprop.

这两个网络开始时在它们的任务中表现很差,但是当训练顺利时,它们协同改进,直到生成器产生令人信服的假货。这两个网络陷入了一场零和游戏,其中一个网络的成功相当于另一个网络的失败。正因为如此,在任何给定时间损失函数的值都不能告诉我们系统整体训练得如何,只能告诉我们发生器或鉴别器相对于另一个做得如何。

我们输入到生成器中的随机代码尤其重要。它是使合成样本成为新的和独特的噪声源。它也倾向于以有趣的方式控制输出。当我们在随机码的向量空间周围进行线性插值时,相应生成的输出也进行平滑插值,有时甚至以我们人类直观的方式进行插值。

Digits obtained in a GAN trained on MNIST by linearly interpolating the random code z. As you can see, it appears to smoothly transition from a 1 to a 5, suggesting that it has learned some internal representation of these numbers. *Image taken from the Goodfellow paper.

挑战和局限

虽然这对于对学习无标记数据表示的新方法感兴趣的研究人员来说非常令人兴奋,但是在实践中使用 GANs 通常是相当困难的。从一开始,从业者就注意到他们在训练中面临挑战。这很大程度上是由于一个叫做模式崩溃的问题。当鉴别器基本上“赢得”游戏,并且生成器的训练梯度变得越来越没用时,模式崩溃就会发生。这可能在训练期间相对较快地发生,并且当它发生时,生成器每次都开始输出几乎相同的样本。它停止变好。

就连伊恩·古德费勒也承认,他很幸运,因为他根据直觉尝试为他的第一个 GAN 选择的超参数有效——它们可能很容易失败。自那以后的几年里,研究界已经想出了许多方法来使训练更加可靠。某些体系结构似乎比其他体系结构工作得更好,并且已经探索了几种对抗性损失函数的变体。其中一些似乎比其他的更稳定。我建议甘人生而平等吗?Lucic 等人的一项大规模研究,如果您想了解更多信息,这是一篇关于 GAN 景观的优秀综述。

然而,这些方法都没有完全消除这个问题,模式崩溃的理论原因仍然是一个积极的研究领域。

生成图像

图像生成的一个重大改进发生在 2016 年,当时拉德福德等人发表了利用深度卷积生成对抗网络的无监督表示学习。他们发现了一系列 GAN 架构,可以很好地创建图像,简称为“DC GAN”。DCGANs 摆脱了某些 CNN 中使用的池层,并依靠卷积和转置卷积来改变表示大小。大多数层之后是批量规范化和泄漏 ReLU 激活。

然而,即使是 DCGANs 也只能创建特定大小的图像。图像的分辨率越高,鉴别者就越容易区分“真”图像和“假”图像。这使得模式崩溃的可能性更大。虽然合成 32x32 甚至 128x128 的图像已经成为常规的教程材料,但在实践中生成分辨率高于 512x512 的图像仍然具有挑战性。

我应该注意到,一些图像到图像的转换技术 可以处理高分辨率,但这是一项不同的任务,因为这些技术只学习改变输入图像的表面特征,而不是从头开始生成全新的图像。

可以想象,从零开始生成大型图像的困难严重限制了 GANs 在许多实际应用中的实用性。

向更高的图像分辨率发展

正是在这种背景下,NVIDIA 的团队在本文的顶部展示了由他们的新程序生成的令人震惊的 1024x1024 图像。更好的是,他们不知道为什么他们的技术不能用于合成更高分辨率的图像。这甚至比以前的 GANs 更有效率(就训练时间而言)。

生长 gan

该团队并没有像通常那样尝试一次训练发生器和鉴别器的所有层,而是逐渐地生长它们的 GAN,一次一层,以处理分辨率越来越高的图像版本。

The ProGAN starts out generating very low resolution images. When training stabilizes, a new layer is added and the resolution is doubled. This continues until the output reaches the desired resolution. By progressively growing the networks in this fashion, high-level structure is learned first, and training is stabilized.

为了做到这一点,他们首先人为地将他们的训练图像缩小到一个非常小的起始分辨率(只有 4x4 像素)。他们创建了一个只有几层的生成器来合成这种低分辨率的图像,以及一个相应的镜像架构鉴别器。因为这些网络非常小,所以它们训练相对较快,并且只学习了在严重模糊的图像中可见的大规模结构。

当第一层完成训练后,他们将另一层添加到 G 和 D,将输出分辨率加倍到 8×8。早期层中训练的权重被保留,但不被锁定,新层逐渐淡入以帮助稳定过渡(稍后将详细介绍)。训练继续进行,直到 GAN 再次合成令人信服的图像,这一次是在新的 8×8 分辨率下。

通过这种方式,他们继续添加图层,将分辨率提高一倍,并进行训练,直到达到所需的输出大小。

种植甘蔗的有效性

通过逐渐提高分辨率,我们不断要求网络学习整个问题中更简单的部分。增量学习过程极大地稳定了训练。这与我们将在下面讨论的一些训练细节相结合,降低了模式崩溃的可能性。

从低到高分辨率的趋势也迫使逐渐增长的网络首先关注高级结构(在图像的最模糊版本中可辨别的模式),然后填充细节。这通过降低网络将得到某些严重错误的高级结构的可能性来提高最终图像的质量。

逐渐增加网络规模也比一次初始化所有层的更传统的方法在计算上更有效。层数越少,训练速度越快,因为其中的参数越少。由于除了最后一组训练迭代之外的所有迭代都是用最终层的子集来完成的,这导致了一些令人印象深刻的效率增益。Karras 等人发现,根据输出分辨率的不同,他们的程序通常比相应的传统 GAN 快 2-6 倍。

*This graph reflects the superior training efficiency of progressive growth. For a given amount of training time, ProGAN (green) was able to train on many more images than a traditional GAN (blue). The difference is most extreme in early training, since this is when the progressively grown network is smallest. Image taken from the paper.

建筑

除了逐渐扩大网络,NVIDIA 论文的作者还进行了其他几项架构更改,以促进稳定、高效的培训。

给定分辨率 k 的生成器架构遵循一个熟悉的高级模式:每组层都将表示大小加倍,并将通道数量减半,直到输出层创建一个只有三个对应于 RGB 通道的图像。鉴别器的作用几乎完全相反,它将制图表达的大小减半,并将每组图层的通道数加倍。在这两种网络中,通过将滤波器的数量限制在合理的值(如 512)来中断通道倍增模式,以防止参数的总数变得太高。

在这个意义上,ProGAN 类似于早期的图像生成 GANs。DCGAN 使用了类似的结构。

然而,DCGAN 使用转置卷积来改变表示大小。相比之下,ProGAN 使用最近邻进行向上扩展,使用平均池进行向下扩展。这些是简单的操作,不需要学习参数。然后是两个卷积层。

A detailed view of the generator architecture, when it has “grown” to resolution k. Each set of layers doubles the resolution size with a nearest neighbor upscaling operation followed by two convolutions. To stabilize training, the most recently added layer is “faded in”. This process is controlled by α, a number between 0 and 1 that is linearly increased over many training iterations until the new layer is fully in place.

“淡入”新图层

每次在现有分辨率下完成训练时,通过添加一组新的层使分辨率加倍,网络逐渐增长。当添加新层时,先前层中的参数保持可训练状态。

为了防止突然增加新的顶层对先前存在的较低层造成冲击,顶层被线性“淡入”。这种淡入由参数 α 控制,该参数在许多训练迭代过程中从 0 线性插值到 1。如上图所示,最终生成的图像是生成器中最后一层和倒数第二层的加权和。

像素标准化

作者使用了像素归一化,而不是通常使用的批量归一化。这个“pixelnorm”层没有可训练的权重。它将每个像素中的特征向量归一化为单位长度,并应用于生成器中的卷积层之后。这样做是为了防止信号幅度在训练期间失控。

The values of each pixel (x, y)* across C channels are normalized to a fixed length. Here, a is the input tensor, b is the output tensor, and ε is a small value to prevent dividing by zero.*

鉴别器

生成器和鉴别器大致是彼此的镜像,并且总是同步增长。鉴别器获取一个输入图像 x ,它或者是发生器的输出,或者是缩小到当前训练分辨率的训练图像。作为典型的 GAN 鉴别器,它试图将“真实的”训练集图像与“虚假的”生成的图像区分开。它输出 D(x),这是一个捕获鉴别器对输入图像来自训练集的置信度的值。

A detailed view of the discriminator architecture, when it has “grown” to resolution k. Here, x is the input image (either generated or from the training set), α is the extent to which the last generator layer is “faded in”, and D(x) is the probability the generator has assigned to x being from the training set. The representation size is halved at each set of layers by an average pooling operation.

小批量标准偏差

一般来说,GANs 倾向于产生比训练集中发现的变化少的样本。解决这一问题的一种方法是让鉴别器计算整个批次的统计数据,并使用该信息来帮助区分“真实的”训练数据批次和“虚假的”生成的批次。这鼓励生成器产生更多的变化,使得跨生成的批次计算的统计数据更接近于来自训练数据批次的统计数据。

在 ProGAN 中,这是通过在鉴别器末端附近插入一个“迷你批次标准偏差”层来实现的。这一层没有可训练的参数。它计算整批特征图像素的标准偏差,并将它们作为额外通道附加。

均衡学习率

作者发现,为了确保发生器和鉴别器之间的良性竞争,各层以相似的速度学习是至关重要的。为了达到这个均衡学习率,他们根据一个层的权重来缩放该层的权重。他们使用与在 He 初始化中使用的相同公式来做这个,除了他们在训练期间每个向前传球时在中做这个,而不仅仅是在初始化时。**

Learning rates can be equalized across layers by scaling the weights before every forward pass. For example, before performing a convolution with f filters of size [k, k, c], we would scale the weights of those filters as shown above.

由于这种干预,权重初始化不需要任何花哨的技巧——简单地用标准正态分布初始化权重就可以了。

损失函数

作者表示,损失函数的选择与他们的贡献是正交的——这意味着上述改进都不依赖于特定的损失函数。使用最近几年出现的任何流行的 GAN 损耗函数都是合理的。

然而,如果你希望完全遵循这篇论文,他们使用了改进的 Wasserstein 损失函数,也称为 WGAN-GP 。这是一个比较常见的损失函数,已经被证明可以稳定训练,提高收敛的几率。

The WGAN-GP loss equations. Here, x’ is the generated image, x is an image from the training set, and D is the discriminator. GP is a gradient penalty that helps stabilize training. The a term in the gradient penalty refers to a tensor of random numbers between 0 and 1, chosen uniformly at random. It is common to set λ = 10. Since we usually train in batches, the above losses are usually averaged over the minibatch.

需要注意的是,WGAN-GP 损失函数期望 D(x)和 D(x’)是无界的实数值。换句话说,鉴别器的输出是而不是预期的 0 和 1 之间的值。这与传统的 GAN 公式略有不同,后者将鉴频器的输出视为概率。

结果

如果你已经做到了这一步,恭喜你!现在,您已经对最先进的图像生成算法之一有了很好的理解。如果你想看到更多的训练细节,有一个由 NVIDIA 团队发布的优秀的官方实现。他们也有一个关于这个话题的谈话。

The output of ProGAN when we smoothly interpolate over the input vector, z.

感谢阅读!我希望这是一个有用的概述。如果你对这篇文章有任何问题、修正或建议,请留下你的评论。

编程文献 II —连续性是递归的

原文:https://towardsdatascience.com/programming-literature-ii-continuity-is-recursive-1efc44474acd?source=collection_archive---------5-----------------------

更进一步,翻译了一部经典作品

不久前,我在 medium 上写了一篇文章,介绍了“编程文学”这个相当愚蠢的想法。要点是为人类而不是为计算机写程序,把它们写成文学作品,努力追求美观和表现力,而不是其他品质,比如可维护性或…功能性。

这样一种艺术的可能表现形式之一(我能称之为艺术吗?)可能是对原创故事的阐述,就像上一篇文章中的那样。但正如其他媒体一样,它可以从前辈那里获得灵感,在这种情况下,是以翻译现有文学作品的形式。

事实上,它最初的目的不是为了证明一个原创的故事,而是基于一个我认为具有独特特征的作品,可以用编程语言非常明确地表达出来。它也非常短,易于管理。这个故事是胡里奥·科塔萨尔的《T2 公园的延续》。

事不宜迟,故事是这样的:

You can find the original here

你看到了吗?公园的连续性是一个以与故事开头完全吻合的事件结尾的故事。也就是说,如果你读到故事的结尾,又从头开始读,故事继续,有意义。它还无限期地在一个故事中嵌套一个故事。

作为一名程序员,当我想到这一点时,我首先想到的是 递归 。这在原著中并不明确,但人们可以说公园的连续性是一个递归的故事:一旦它结束,它引用自己并再次开始,重复相同的事件。

在翻译版本中,我冒昧地通过调用:

continuity(theMan, theNovel)

到目前为止,这是我用编程写的最长的故事。它也是第一部从自然语言翻译过来的作品。那么,从这个练习中我们可以得出什么结论呢?

翻译比预期的要难

故事很短。不会发生很多事。尽管如此,我还是很难把它翻译成 Groovy,主要是因为它有相当多的不常见和广泛的句子,并且为这些句子想出好的和有效的表达需要大量的大脑周期。

结果似乎过于复杂

我的目标之一是试图保留大部分用自然语言表达的信息。这导致代码看起来比它应该的更复杂。作为程序员,我们被训练得尽可能保持代码简单。我们到处拥抱亲吻原则。此外,至少对我来说,代码美丽的部分原因是它的简单性。

所以当我看着用 Groovy 写的故事时,我不禁觉得应该更简单一些。

没有太多的编程正在进行

我喜欢在第一个故事中包含一些常见的编程模式和工具,比如声明一个类,或者使用数组文字和范围来表示重复。在某种程度上,通过使用这些工具和模式,故事利用了它所使用的语言。

我发现在这个故事中很难使用它们,不知道是因为我专注于尽可能忠实地翻译,还是因为这个故事没有提供很多使用它们的机会。

有用!(作为文学作品)

我可能有偏见,但我认为一个人可以阅读这个故事,理解它,跟随它,享受它,甚至发现它很美。我个人更喜欢原著,但我也能享受阅读这本书的乐趣。

那么,下一步是什么?

我可能会尝试用静态类型的语言写一个原创的故事,并让它编译。和诗歌一样,用受限的语言讲述一些东西,也有一点美。

我也一直在寻找类似的想法,并发现一些其他人做的工作。我大学里的一个老师甚至设法为学生写了一个练习,讲述《守望者》电影的故事,一个学生写了一个 Haskell 程序,可以编译,也是一部文学作品。我可能也会对此稍加评论。

和以前一样,我想鼓励任何读到这篇文章的人用他最喜欢的语言写下他/她自己的故事。

感谢您的阅读!

Python 中的进度条

原文:https://towardsdatascience.com/progress-bars-in-python-4b44e8a4c482?source=collection_archive---------3-----------------------

就像被监视的锅永远不会沸腾一样,被监视的循环永远不会结束。当处理大型数据集时,即使是最简单的操作也会花费小时。进度条有助于减少数据处理工作的麻烦,因为:

  1. 你会得到一个可靠的估计需要多长时间。
  2. 如果卡住了,你可以立即看到。

第一点在商业环境中尤其有价值,有一个可靠的交货估计可以让你看起来非常专业。我发现的给 Python 代码添加进度条的最好的/唯一的方法是使用 tqdm 。虽然 tqdm 超级容易使用,但是设置起来可能有点麻烦,尤其是如果您使用 JupyterLab (您完全应该这样做)。

tqdm in action

在仔细研究了 StackOverflow 和一些尝试和错误之后,我想我已经找到了一个让 tqdm 启动并运行的可靠方法(即使是使用 JupyterLab)!

设置 tqdm

首先,用您选择的包管理器(pip、pipenv、anaconda 等)安装 tqdm。安装完成后,您可以运行以下命令来激活 JupyterLab 的 ipywidgets 插件,

> pip install ipywidgets 
> jupyter nbextension enable --py widgetsnbextension
> jupyter labextension install @jupyter-widgets/jupyterlab-manager

要在笔记本中激活 tqdm,您只需添加一个单元格,

%%capture
from tqdm import tqdm_notebook as tqdm
tqdm().pandas()

如果您只是打算在脚本中使用 tqdm,那么您可以跳过这两个步骤!

使用 tqdm

tqdm()包装任何 iterable 都可以得到进度条。举个例子,

my_list = list(range(100))for x in tqdm(my_list):pass

会给你一个(非常快的)进度条。您还可以更明确地使用 tqdm,

my_list = list(range(100))with tqdm(total=len(my_list)) as pbar:for x in my_list:pbar.update(1)

还有一个熊猫的整合,

df.progress_apply(lambda x: pass)

关于使用 tqdm 的更多内容,包括嵌套进度条,请查看他们的文档。

级数

原文:https://towardsdatascience.com/progressions-eb79a573f7f1?source=collection_archive---------4-----------------------

利用马尔可夫链提取歌曲相似度

你和你的朋友在公路旅行,播放列表中出现了经典的 Ice Ice Baby 简介。为了这一刻,你已经在浴室里练习了 1000 次;这是你的重大突破。引子结束时,你突然开始一段激烈的说唱,只听到:

“嗯,巴巴·德
嗯,流浪汉巴德……”——女王

这是皇后乐队的《压力下的 T3》和《T4》,在接下来的旅程中,你尴尬地沉默着,承受着谦卑的压力。

不要对自己太苛刻!许多歌曲听起来极其相似,无论是相似的旋律还是匹配的歌词。现代歌曲往往遵循同样的和弦结构。这就是为什么有时你可能会听到一首歌曲的器乐部分,并认为这是一首不同的歌曲。现代音乐并不缺乏创造力或创新,而是朝着观众认为在审美上悦耳的方向发展。

Progressions 是一个网络应用程序,允许你选择一首歌曲或键入和弦进行,并对和弦进行类似的其他歌曲进行排名。这对初学吉他的人来说可能是有用的,可以增加他们的弹药库,找到与他们已经知道的歌曲相似的歌曲。这也可以帮助音乐编曲者找到他们可以拼凑成一首混合曲或混搭曲的曲调。或者你可以简单地用它来探索流行歌曲之间的相似性。

先决条件:使用术语和概念时对音乐理论的基本理解

介绍

仅仅一首歌就包含了丰富的信息。每个小节、和弦、音符、节奏值和音量强度都会随时间变化。此外,每种乐器或声音都会发出不同的音调属性,从而创建数据层。除此之外,我们还有关于歌曲基调、创作时间、流派等等的元数据。音乐学家多年的研究让位于从提取主题或可识别的结构以及历史背景中识别歌曲的复杂性。自然语言处理技术已经被用于分析歌词,而录音的信号处理已经被用于诸如流派分类之类的事情。世界上有超过 9700 万首歌曲,音乐无疑提供了大数据。

音乐的时间性允许我们把一首曲子作为一系列事件来分析。例如,约翰·科尔特兰的《大踏步》 improv 就是一系列不同音符的简单组合,带有一点随机性。这让我们可以将音乐建模为一个随机过程,一系列发生在某个时间媒介上的随机事件。

对随机过程建模的一个简单方法是使用马尔可夫链。一阶马尔可夫链遵循下面的简单性质。

Markov Property

这就是说,序列中下一个状态的概率只是有条件地依赖于当前状态。在一段旋律中,下一个音符的值只取决于当前的音符,而不考虑之前旋律的其余部分。关于马尔可夫链更深入的解释可以在我之前的文章这里中找到。

在这个项目中,我们将给定歌曲的每个和弦视为一阶马尔可夫模型中的一个状态。我们如何得到和弦,我们从哪里得到歌曲?

数据集

数据来自于《终极吉他》,我们在那里搜集了有史以来最受欢迎的 1000 个标签。在此,我们提取了用户在该网站上列出的 1000 首歌曲的歌名、艺术家、和弦和流行度。所有的数据都存储在 MySQL 数据库中。在报告的自述文件中可以找到更详细的关于抓取方法和数据库设置的描述。

寻找相似之处

有了我们的歌曲集,我们希望能够选择一首歌曲,然后根据和弦进行找到与之相似的歌曲。用于存储马尔可夫模型的数据结构是转移矩阵。因此,对于每首歌,我们创建一个转换矩阵,存储从一个和弦到另一个和弦的概率。借助可靠的线性代数,我们可以找到矩阵之间的欧几里德距离。

Euclidean Distance Between Transition Matrices

这个公式着眼于两个转移矩阵,用不同的概率符号表示。这给了我们歌曲之间的距离,其中固有的更短的距离意味着分布更接近(更相似),反之亦然。

在这个项目中,我们更关注歌曲的和弦结构,而不是和弦名称或音调。比如披头士:随遇而安沿用了标志性的C 调的 I-V-vi-IV 和弦结构,和弦名称为 C-G-Am-F 。阿黛尔的《像你这样的人》在相似度上排名第三,并且有一个和弦进行的合唱。这也是 I-V-vi-IV 结构但现在在 a 调中,因此,我们可以突出显示结构相似的歌曲而不管原来的调。

一点数据管理

如果我们所有的歌曲都是 c 调,那么确定和弦结构就容易多了。当然,我们数据库中的歌曲并不都是同一个调。因此,我们必须想出一种方法来确定给定歌曲的基调。

当用户在 UltimateGuitarTabs 上创建标签时,他们可以选择输入他们正在跳转的歌曲的音调。尽管如此,它并不完全可靠。有些歌曲需要变音器,因此键和变音器指示品不在一条线上。一些用户输入了完全错误的密钥,而另一些用户根本没有输入密钥。

Key Table

音乐理论告诉我们,当我们处于一个特定的调时,只有某些和弦会听起来很好听。每一行都包含可能的和弦,如果一首歌曲在那个特定的调上,就可以播放这些和弦。我们所要做的就是计算每一个和弦被弹奏的次数,然后计算每一行的总和。具有最大总和的行将被标记为该歌曲的关键字。

因为这个键表只包含大调、小调和减和弦,我们还必须清理我们提取的和弦,以移除任何其他和弦质量(即,sus、7、13、aug 等)。

注意:这是一种启发式方法,决不会每次都给你正确的密钥,但这是我们目前能做的最好的了。

所有的抓取、存储和转换都在 Python3 中完成。现在我们有了清晰的和弦和确定相似性的方法,我们现在可以构建应用程序了!

建立和使用级数

我们决定使用 Flask+Angular.js 来创建应用程序。Flask 使我们能够将数据发送到前端,Angular.js 允许我们在引导 HTML 页面上很好地显示数据。我们的 Flask 功能还与 MySQL 数据库交互以查询数据。

Main View of Progressions

用户既可以点击表格中的歌曲,也可以输入自己的和弦进行!当用户点击一首歌曲时,会出现一个新页面,显示类似歌曲的列表,以及 UltimateGuitar 上原始标签的链接。当用户提供和弦进行时,显示和弦进行的估计键以及数据库中的类似歌曲。

Result after choosing Pumped Up Kicks by Foster the People

总结

我们从 UltimateGuitar 上的前 1000 个排行榜中搜集和弦序列,并将所有信息存储在 MySQL 数据库中。我们将所有和弦序列标准化为 C 调,只包含大调、小调和减和弦。使用马尔可夫模型,我们为每首歌曲的和弦序列创建了一个转移矩阵,并且能够计算歌曲之间的欧几里德距离来测量相似性。使用 Flask 和 Angular.js 通过 web 应用程序显示结果。

未来的工作

  • 正如我们之前所说,一阶马尔可夫链是对和弦进行序列建模的基本方法。因此,使用高阶或变阶马尔可夫模型可以改进应用。
  • 我们寻找答案的方法是一种基本的音乐理论技巧。使用信号处理技术或隐马尔可夫模型来分类歌曲关键字的其他新颖方法已经被使用,但是可能不适合这个数据集。需要对音乐信息检索领域进行更多的研究。
  • 去除和弦质量以仅具有大调/小调和弦降低了我们寻找相似歌曲的方法的准确性。在我们的计算中,我们可能想把复杂的弦和简化的弦都包括进去。例如,如果一首歌曲有和弦 Cmin6/G,我们可能希望在状态空间中使用该和弦及其基础 Cm。但是,在我们的转换矩阵中存储所有的和弦类型会创建非常大的稀疏填充的矩阵。计算出的距离平均会更短。
  • 可以使用除欧几里得距离度量之外的其他距离度量。使用像 Kullback-Leibler (KL)散度这样的度量是比较概率分布的一种选择。我们对转移矩阵(TM)的使用使得这变得复杂,因为我们可以计算 KL-divergence 行的歌曲,但不是作为一个整体。此外,任何距离矩阵的功效都依赖于我们的建模方法,在这种情况下,这是一个简单的一阶马尔可夫链。
  • 因为我们的焦点是找到具有相似和弦结构的歌曲,所以确定歌曲的真实和弦结构(即,I-V-vi-IV)并将其显示给用户也是必要的。

应用程序的存储库可以在这里找到。它仍然是一项正在进行中的工作,所以建议是高度鼓励!

查看我之前在发表的关于使用可变长度马尔可夫模型人工生成布鲁斯旋律的帖子

如有任何问题,请随时联系 me !希望你喜欢这篇文章!

PGGAN 创建逼真的面孔

原文:https://towardsdatascience.com/progressive-gans-new-training-trend-for-2018-c18cb0190239?source=collection_archive---------3-----------------------

2018 年深度学习的新趋势

Ian Goodfellow 早在 2014 年就在蒙特利尔大学发明了世代对抗网络。他们已经有了一个很好的开始,显示出图像生成质量的潜在增长,打破了以前由受限玻尔兹曼机器、可变自动编码器等设定的所有基准。这个框架仍然是生成高质量图像的最成功的方法之一。此外,该框架产生易于处理的网络(与通过近似推理计算的 RBM 相反),且很容易仅使用误差反向传播来训练。

多年来,GANs 的许多变体被发明出来,但第一个最成功的进展是 DCGAN,它生成了质量更好的图像,还发现了各种稳定训练过程的技术,因为众所周知,随着一个网络变得比另一个更强,学习无法完成,GANs 在训练时非常不稳定。另一个问题是模式崩溃,生成器无法生成新的图像。除了训练问题,GANs 很快转向不同的方向,如生成高分辨率图像,图像修复,制作音乐等。

进步甘斯

最近,在撰写本文时,NVIDIA 的一项研究揭示了一种训练 GANs 的新技术,他们称之为GANs的渐进生长。他们采取了一种完全不同且出乎意料的训练方法。并且这种技术产生新颖的并且不容易与原作或赝品相区分的真实图像。

只是看一看👀观看下面的视频,了解这种新训练方法的潜力!

Celebrity Face Generation (Novel Faces)

扩大网络

他们用于训练网络的方法是,首先从生成器 G 生成 4x4 分辨率的图像,并将它们与缩放到相同分辨率的真实图像一起送入鉴别器进行训练。请注意,他们使用的图像来自 CelebA 数据集,尺寸为 1024x1024。现在,在网络学习对于宽空间特征饱和之后,两个网络都随着更高分辨率的层慢慢淡入到 GD 中。

研究人员使用残差网络,通过增加残差网络存在的权重,将这些更高分辨率的卷积层淡化到两个网络中。卷积分辨率(新层)增加了 2 倍,在这种情况下是从 4×4 增加到 8×8。这意味着现在 G 生成 8×8 图像(而不是以前的 4×4 图像)并作为 8×8 图像输入到 D 中。原始实像也被缩放到 8×8,用于将它们馈送到 DGD 的先前 4×4 卷积层仍然保持可训练。

网络的渐隐进入 GD 借助残差网络让较高分辨率层渐隐进入网络而不影响训练有素的较低分辨率层。

图层被对称地淡入 GD 中。通过将分辨率增加 2 倍,分辨率逐步增加到 1024x1024。这种方式网络学习图像的宽空间特征和更高分辨率层中的局部空间特征,因为GANs 增长,因此称为 GANs 的渐进增长

虽然有些图像是不正确的,例如有时头发和前额混在一起,有些照片中的眼睛彼此不相似,等等。但总的来说,网络生成的图像非常好,而且还是高清的!

接下来呢?

为了更深入的理解,请看一下研究论文:为了提高质量、稳定性和变化而进行的 GANs 渐进生长。还可以在 GitHub 上查看我的推理(生成器)网络对的实现。代码是用 PyTorch 编写的,可以让你从潜在空间生成图像。

在 GitHub 、 Instagram 、 Twitter 上追踪我。

TensorFlow 中的渐进式学习和网络增长

原文:https://towardsdatascience.com/progressive-learning-and-network-growing-in-tensorflow-e41414f304d2?source=collection_archive---------9-----------------------

在许多真实世界的应用中,在网络已经被训练之后,新的训练数据变得可用。特别是对于大型神经网络,每当新信息可用时,重新训练完整的模型将是非常乏味的。对于引入的每个新类别或其他信息,简单地向网络添加新节点,并保持所有其他先前训练的权重,会容易得多。在这篇文章中,我将简要介绍如何在 TensorFlow 中实现这一点,以及它对网络性能的影响。

我将在 CIFAR-10 数据集上演示该过程和结果,但本文结尾链接的 Git 存储库也提供了 MNIST 和 CIFAR-100 的代码和结果,可以很容易地适用于任何其他这类数据集。我使用的网络结构非常简单,由两个卷积层组成,后面是一个具有 512 个神经元的全连接层和一个具有与数据集中的类一样多的神经元的读出层。

Network structure used for the following experiments. On CIFAR-10 it reaches an accuracy of ~55%.

在这个渐进学习网络的例子中,训练从 CIFAR-10 的十个课程中的六个开始。在每个时期之后,引入一个新的类,直到五个时期之后,所有十个类都在数据集中。为了让网络在新添加的类上进行训练,它需要为该类提供一个新的输出节点。这意味着网络的最后一层以及与之相连的权重随着每一个新类别的增加而增加。为了在 TensorFlow 中实现这一点,我用新大小的新图层重新初始化完整的最后一层。

# Define initializer (old weights + random samples from them for the new node(s) )
initializer = tf.constant_initializer(np.append(weights,np.random.choice(weights.flatten(),(512,1)),axis=1)) # Initialize new last layer of size (512 x numClasses)            tf.variable_scope(tf.get_variable_scope(),reuse=tf.AUTO_REUSE):outLog,Wname =      newLastInit(hidden_layer,numOutP,initializer)acc,CE = evaluate(outLog,desired)accuracy = tf.reduce_mean(tf.cast(acc, tf.float32))cross_entropy = tf.reduce_mean(CE)                   learning_rate = 1e-4optimizer = tf.train.AdamOptimizer(learning_rate,name='op_0')# get name of new layer
weightName = Wname# define gradients
gradient = tf.gradients(cross_entropy, weightName)[0]# define training goal
training_step = optimizer.minimize(cross_entropy)# get all uninitialized variables
uninitialized_vars = getUnititialized(tf.all_variables())# initialize all uninitialized variables
init_new_vars_op = tf.initialize_variables(uninitialized_vars)# Start training for the next epoch
session.run(init_new_vars_op)

连接到新的最后一层的权重最好用来自前一时期的已训练的weights来初始化。连接到新添加的节点的权重可以从旧的weights或随机分布中随机采样。这种权重初始化导致比用随机数或小常数初始化所有权重明显更好的结果,因为它保留了在先前时期中学习的所有信息。

Comparison of three weight initializations with network growing. The blue boxes represent the size of the last layer. The number in the orange circle states how many classes are in the training and validation set. The red lines mark the start of a new epoch and the initialization of a new class and a new node in the last layer.

对于所有三种权重初始化,每当引入一个新类时,您都可以看到性能下降。然而,前两次初始化(恒定和随机初始化)的下降比用旧的权重初始化时大得多,因为旧的权重初始化保留了已经学习的信息,并且只有新的类需要从头开始训练。当比较旧类的网络性能和新类的性能时,可以看出性能下降主要是由后者引起的。相对而言,新班级的引入并没有影响旧班级的表现。

Network performance on the old classes compared to the performance on the new class. Red lines mark the start of a new epoch and a new class introduction.

看着这些图,当保留旧的权重时,似乎添加新的类和增长网络对关于旧的类的已经学习的信息几乎没有影响。但是它是如何影响整体测试精度的呢(黑线)?

为了将网络增长与数据集中所有类的传统训练进行比较,我在每种条件下训练网络 100 次,然后比较每种条件下产生的 100 个测试准确度的分布。此外,我添加了一个名为 No Growing 的条件,其中最后一层保持静态(总是包含 10 个节点),只有数据集随着时间的推移而增长。这相当于从开始就初始化一个更大的输出层,以便为新的类留出一些空间,而不必在训练期间改变网络结构,但是限制了可以添加的类的最大数量。

Distribution of 100 test accuracies for each of the three conditions after training for five epochs on CIFAR-10.

正常的网络训练(M=0.50,SD=0.01)明显优于连续学习条件(增长(M=0.48,SD=0.01)和不增长(M=0.49,SD=0.01)),p <0.001. However, the normal training had a strong advantage since it could train on each example for each class five times. The two continuously learning networks had much less time to train on the classes that were introduced later on. In the most extreme case, the images of the class introduced last were only seen once by the networks as opposed to five times by the normally trained network.

When training for longer after the last class has been introduced one can see how the two continuously learning networks catch up to the normal network after 30 epochs of post training, from then on no significant difference can be found anymore, F(2,297), p=0.06.

Distribution of 100 test accuracies for each of the three condition comparing the number of epochs that were used for post training. KeepTrain=0 therefor means that no post training was performed and reprsents the same results as shown in the previous figure. KeepTrain=30 means that after the last class introduction the network was trained for 30 more epochs.

These results show that a network can be trained with iterative class introduction and can still reach a comparable performance to a network trained with all classes from the beginning on. The continuously learning networks take a bit more time to reach a performance comparable to the performance of a normally trained network but this effect can be explained by the lower exposure of the network to the classes which were added later on. In a real world application this can be a simple solution for adding new information to an already trained network without having to start training from scratch again.

代码:https://github . com/vkakerbeck/progressive-Growing-Networks

项目 Diversita:当机器学习遇到用户体验

原文:https://towardsdatascience.com/project-diversita-an-intelligent-edge-computing-device-31adbd0d4076?source=collection_archive---------9-----------------------

在这个为期两个季度的研究生项目中,我探索了如何释放机器学习的力量,以满足上一代技术难以满足的要求,同时考虑到以人为中心的设计和工程。

背景

Project Diversita 是微软于 2018 年在 AI for Earth initiative 下在GIX大学发起的“启动项目”。它旨在通过利用边缘技术上的机器学习(ML)来支持生物多样性研究。微软研究院已经基于非自然主义者数据集训练了 ML 模型。

我接受了机器学习和传感器方面的培训,但是在这个项目中,我的角色主要是产品设计。面临的挑战是探索潜在的市场空间,并找到最适合我们技术骨干的利基市场。

时间跨度

2018 年 6 月 27 日至 2018 年 12 月 7 日

关于团队

一个十人小组由大学的学生(菲尔普斯夏、哈尔张、本凯勒和我)和微软的研究人员(丹莫里斯、卢卡斯约帕)/工程师(魏永德、、、、艾丽卡梅内塞斯、朱)组成

在项目中的作用

产品设计师(UX,身份证),产品经理,用户研究员

总体目标

  • 研究市场,以确定一个利基相机陷阱场景,以破坏微软在人工智能方面的能力。
  • 对客户来说是可取的,对业务是可行的,对工程是可行的。
  • 开发工作原型来证明这个概念。

关键词

机器学习、边缘计算、树莓派、物联网、计算机视觉

1.产品的定义

来自微软的原始输入

在微软园区的启动会议上,微软方面的项目团队提出了以下要求:

  • 面向消费者:最终产品应该面向消费者,能够扰乱相机陷阱市场;
  • 移动性:最终产品应该易于携带;
  • 连接性:最终产品应该能够连接到其他设备或云。

为了更好地了解主题,我们的团队分三个阶段研究了该案例:

  1. 竞争分析;
  2. 用户调研:访谈;
  3. 用户研究:调查。

1.1.竞争分析

本研究旨在回答三个研究问题,并提取启发和指导概念设计的见解。这些见解来自对竞争对手产品发现的推理。

研究问题是:

  • 竞争对手的产品如何适应特定的使用情形?
  • 成像产品有哪些合适的交互模式?
  • 开发我们产品的好方法是什么?

确定的竞争对手

“竞争者”包括直接竞争者和间接竞争者。直接竞争对手是可能与我们的潜在产品竞争的产品。而间接竞争对手是在特定维度上与我们的潜在产品有相似之处的产品。在本研究中,“间接竞争对手”不需要能够替代本项目的预期解决方案。本研究选择的间接竞争对手包括共享类似功能(例如图像捕捉)或可以在同一场景中共存的产品或服务(例如双筒望远镜、野生动物跟踪系统)。

观察指标

在浏览竞争对手的产品时,团队成员记下了产品三个方面的发现— 1。业务方面;2.交互体验;3.发展方式。

从竞争分析中获得的见解

四名团队成员促成了 84 项调查结果。84 项调查结果中有 44 项是关于用例/业务模型或用户交互体验,其余是关于工程解决方案的调查结果。基于这些发现,我们提取了以下见解:

  1. 平台即服务。 —该产品可以是不同服务的通用平台。当产品联网时,协同效应可以产生额外的价值。价值可以打包成服务出售。
  2. 以差异化为优势。 —低成本、可移动、无需连接、隐私。边缘设备上的机器学习可以仅针对特定用例进行设计,这使得它与智能手机相比成本较低。与云上的 ML 相比,它节省了订阅信用和连接费用。
  3. 利用分层策略扩大市场规模。 —向市场提供低成本 MVP,通过允许更多的试购来刺激需求。
  4. 寻求与社区合作,以打破特定的利基市场。 —无论是专业社区还是居住社区,与他们紧密合作,解决他们的独特问题,是踏足市场的有效途径。
  5. 授权他人。 —除了是一个独立的产品。该产品作为一个模块也是可行的,该模块可以利用/授权其他产品来实现与独立产品类似的功能。
  6. 主动服务,倾听用户。 —用户的反馈是迭代和改进的宝贵输入。预测用户的挫折感,并准备结构良好的资源来帮助用户。
  7. 为分享而生。分享是人类的天性。让用户自由表达既能满足他们的愿望,又能创造超越用户的影响力。
  8. 传递用户关心的东西。 —用户关心结果。他们不介意封闭背后的算法或工程努力。避免使用术语或提示用户配置不必要的对话框。
  9. 形式遵循功能。 —逻辑设计既实用又美观。通过采用逻辑工业设计,可以用更低的成本实现相同的功能,为客户留下更多的空间来创造价值。
  10. 使用手机作为界面。 —智能手机屏幕具有丰富的交互性。将特定操作转移到智能手机可以降低设备成本,实现更好的交互体验。
  11. 冗余带来可靠性。 —为同一目的使用多组组件可以增强系统的性能。此外,它使系统更加健壮。
  12. 准备扩张。 —为特定模块留出开放的末端将使产品能够以较小的努力适应不同的场景。

竞争分析的结论

通过竞争分析,我们探索了项目多样性的竞争空间。根据我们提取的见解,Project Diversita 的预期产品应该采用边缘设备上的 ML 的差异化优势来与智能手机和其他竞争对手竞争。通过寻求与社区的合作,产品可以通过扰乱利基市场来扩大其市场。从长远来看,它应该为扩展到更多的场景做好准备;设备节点可以作为一个整体形成一个平台来提供服务。在设计产品时,我们应该牢记以用户为中心的原则——倾听他们的声音,并提供能够激励他们参与生物多样性保护行动的东西。

1.2.1.用户研究

用户研究的研究问题是:

  • 在什么场景下,人们希望识别自己附近的野生动物?
  • 不同的利益相关者群体对自然界持有什么样的观点,这些观点如何影响他们的行为和购买?
  • 当前 ML on Edge 设置的技术能力和局限性是什么?

面试

In one of the user interview sessions, the participant was an active hiker and world traveller. She showed us her tools for species recognition and shared her opinion on design’s impact on the environment.

我们采访了主题专家(SME)和潜在用户(有后院并愿意与动物互动的人)。我们采用亲和图对访谈数据进行处理。主题演讲被聚合到不同的集群中—场景、特征、用户属性、动机、关注点。基于这五个亲和组,我们确定了该项目的障碍、动机、用户要求和其他方向。

Interview data processing.

障碍:

  1. 遭遇物种缺乏变异。–在用户访谈中提到的物种不到 10 种。在 100 个样本的调查中,提到的物种不到 20 种。
  2. 识别结果的准确性。–SME 3 *:“研究人员在发表经过同行评审的论文时,要求准确度高(98%)。
  3. 维护。–SME 3:“每年有 10-20%的摄像机损坏或被盗。”
  4. 伦理问题。——增加人与动物的互动有好处吗?

动机:

  1. 好奇+参与。–U1 *:“我想知道喂鸟器发生了什么事。”"我需要一些可操作的信息。"
  2. 安全+安保。–U2:“当土狼来了,提醒对方注意。”
  3. 社交网络。–U2:“当麋鹿来到我们家门前的湿地时,我会给邻居发短信。”

用户请求:

  1. 语音识别。–U2:“鸟类照片很难捕捉,但很容易听到。”
  2. 菌群识别。U1:“我做蘑菇。有些人觉得它令人生畏,因为很难确定它是否可以食用。”
  3. 足迹识别。–U2:“雪地环境中的动物脚印就在小路旁边,很容易辨认。”
  4. 超过认可。–U1:“我更想知道如何改进,而不仅仅是识别物种。”

其他说明:

  • 浮潜。–浮潜时,人们有很大机会在短时间内接触多种物种。此外,水下没有连接。边缘语言可以利用它的优势来区别于其他计算平台。
  • 保护性研究与保存
  • —入侵物种清除;
  • —无线电遥测钻铤;
  • —遗传取样。
  • 保护区管理:
  • —监控外壳;
  • ——城市发展生态影响评价。

注:SMEx =主题专家 x 号;Ux =用户编号 x。

1.2.2.调查

该小组从拥有房子的参与者那里收集了定量数据。该团队总共收集了 120 个样本,并分析了结果,以提取关于兴趣的见解,从而在不同的场景中利用动物识别能力。结果反映了对应用程序最感兴趣的目标的更多共同特征。他们是有后院的房主,并拥有宠物,尤其是猫和狗。这些见解将在下一阶段指导团队进行概念设计和方向选择。

研究问题如下:

  • 在什么场景下,人们希望识别自己附近的野生动物?
  • 人们出于什么原因想要购买一个设备来监控他们的后院?
  • 从用户的角度来看,边缘计算设备能给他们带来什么好处?

调查工具

谷歌表单,亚马逊土耳其机器人,Tableau。

分析方法论

我们从两个方面分析了数据。首先,我们从定量方面分析了数据。我们使用这些数据来缩小范围并支持角色制作过程。同时,我们希望了解不同场景的潜在用户规模,作为我们市场研究的一部分,以找出可能的最大市场。同时,我们分析了所有的开放式问题,以从受访者那里获得更多的灵感和有价值的想法,这将有助于我们了解更多的可能情况以及支持或反对我们想法的证据。

调查感悟:

  1. 后院的潜在市场可能是巨大的。
  2. 对于消费者来说,他们会认为这款设备更像是一款娱乐设备。
  3. 人们监视他们后院主要是出于安全目的。
  4. 养宠物的人更有可能购买这些设备。
  5. 人们关心的是参与而不是技术。

1.3.概念发展

我主持了一个概念创作的头脑风暴会议。构思有两组限制:技术限制和非技术限制。技术上的局限性:1 .机器学习模型只能识别陆地动物;2.该设备需要移动性。因此,我们需要平衡性能和功耗;3.作为项目投入,它必须具有连接能力。非技术制约因素:1 .设备应该面向消费者;2.我们只有七周的时间来做这个项目。

思维能力

考虑到这些限制,该团队提出了以下想法:

  1. 邻里好奇心:一种将设备捕获的动物分享给社区的设备。给他们一个空间来分享在他们的地方目睹野生动物的经历。
  2. 小朋友的守护:用设备捕捉孩子与家中宠物玩耍的瞬间。当捕捉到危险的动物时,警告父母他们的孩子或宠物的安全威胁。
  3. 露营发现:放在帐篷外或露营地点附近的设备。捕捉路过的动物。
  4. 自然之窗:残疾人如何体验自然。他/她可以设置该设备,并在家中的森林中查看经过他设置的设备的动物的照片。
  5. 掠夺者监视:作为一个邻里监视系统,许多设备协同工作来监视附近的院子、道路和绿化带,并提防危险的动物。当食肉动物出现时向居民发出警报,这样他们就可以避开它们,呆在家里,保持安全。
  6. 露营守卫:设置在帐篷上或食物储藏室旁,在你睡觉的时候为你提防掠食者,记录你露营旅行中令人兴奋的动物遭遇。
  7. 植物和动物移动维基:大多数时候,当你去一个有外来物种的地方旅行时,你没有手机网络覆盖。如果你能在给它们拍一张令人惊叹的照片的同时获得物种的名称和信息,那就太好了。
  8. Smart GoPro :帮助用户捕捉身边有不认识的动物的瞬间。
  9. 宠物跟踪器:帮助用户跟踪宠物在后院的活动。
  10. 捕食者警报:提醒用户警惕附近即将到来的捕食者。
  11. 保护平台:联网摄像陷阱,实现研究和保护自然的新方式。
  12. 人工智能喂鸟器:对到达喂鸟器的鸟进行计数和分类,以了解如何最好地促进当地的生物多样性。
  13. 猎人用 AI 步道摄像头:帮助猎人更好地了解鹿的数量,从而知道有选择地去除哪些。

我们综合了这些想法,想出了三个概念:

  • 理念一:好奇心——利用 ML on Edge 满足人们的好奇心和教育目的。示例场景:带着设备去野营,设置好设备,去享受大自然。回来检查捕获的图像。
  • 概念二:安全——识别可能威胁孩子或宠物安全的物种。必要时发出警告。示例场景:在需要的地方部署设备。配置要监控的物种。如果检测到目标物种,向用户发送通知。
  • 概念三:平台 —部署一个设备网络,实现保护研究和管理的新方法。示例场景:保护区管理、入侵物种应对、围栏安全、气候监测。

解决方案描述/工作分解结构

该系统应该有三大支柱:

  • 设备(物联网套件):套件会部署在用户需要的地方。它会扫描场地,如果有动物经过,就会唤醒相机并拍照。照片将在设备上进行本地处理。如果边缘 ML 模型确定图像中有动物,设备将通过无线连接将图像发送到云服务。
  • Azure services :当云服务收到图片时,云上 ML 模型会分析图片提取物种信息。随着试剂盒发送的图像数据的积累,这些数据可用于 ML 模型进化。在图像接收到作为其元数据一部分的物种识别结果之后。云上的通知服务将根据用户的设置确定图像是否应该触发通知操作。
  • 应用控制台:应用是用户与物联网套件和云服务交互的入口。用户可以配置物联网套件和云服务的设置。例如,用户可以设置系统在物联网套件检测到郊狼时向他/她发送通知。该应用程序是一个内容分发渠道。用户可以观看由该设备捕获的正面图像。也是一个社交平台。多个用户可以共享来自同一设备或设备网络的数据,并就内容进行通信。此外,该应用程序是用户反馈识别质量的反馈渠道——用户可以对识别质量进行评级,并提供正确的物种名称。由于时间和资源限制,该应用程序将针对移动网络浏览器而不是原生应用程序进行开发。

从长远来看,该系统应该允许多个套件形成一个物联网网络。可以添加更多功能,如工作流程简化、远程触发、行为映射、年龄/性别识别,为客户带来更多价值。

2.原型开发

2.1.用户旅程映射

我起草了一份用户旅程图来生成功能列表:

硬件:

  1. 开关按钮打开/关闭相机;
  2. 重置按钮;
  3. 手动捕获按钮;
  4. 状态的 LED 指示器;
  5. 工业设计:可在典型场景下部署——柱子/墙/树;
  6. 检测视野中运动物体的传感器。

软件:

  1. 登录;
  2. 设备管理;
  3. 任务管理;
  4. 本地 ML 处理;
  5. Azure ML API
  6. 推送通知服务。

2.2.用户体验

在这个项目中,我负责产品设计,包括产品定义、数字体验和物理原型。

2.2.1。数字体验

这项服务的数字接触点是应用程序。最初,当我们计划这个项目时,由于我们团队中没有人有开发原生 iOS/Android 应用程序的实践经验,我们决定开发一个 web 应用程序。所以当我设计产品的时候,我只用了基本的网络交互模式,比如滚动和点击。考虑到时间限制(四个人,两个月),该应用程序只能提供非常基本的功能——注册/登录,添加设备,设置触发器,查看拍摄的图像。事实上,最小的可行产品已经是团队的一个挑战——我们还需要测试和开发硬件部分,在 Edge 和 Azure 上配置和测试 ML,设计机械结构并制作原型。

2.2.2。物理体验

经过 60 多天的实验,我们的团队确定了用于最终原型的最终组件集。这些部件的物理尺寸以及它们相互连接的方式成为了原型外形的限制因素。

我使用 CAD 工具来安排电路系统的空间关系,并仔细考虑用户将如何使用该产品。V2 原型是为了评估我的设计和 3D 打印机的性能而制作的。基于我们教员的反馈和我的观察,我进一步将模型迭代到 V3。

与使用 360mL ABS 的 V2 相比,V3 仅消耗 268 mL,即少消耗 25.6%的材料,但保持相同的强度(请参考下图)。此外,新的设计使我们能够密封部件和外壳之间的所有间隙,使其成为一种防水设备。

通过点击这个链接,你可以交互式地查看 CAD 模型。

Parts just got printed from the Stratasys F170 machine, the chamber was still very hot.

The back of the prototype, from left to right: University of Washington (UW), Global Innovation eXchange (GIX), Microsoft. Someone joked it was Word, Excel, Windows.

I designed the device with a tripod mounting point.

The viewfinder was my answer to a teammate’s plan to add a video streaming feature, which was just for the user to check what the camera can see. I’m proud to solve a seemingly tricky requirement with a stone age solution.

3.以后

3.1.Diversita+

在我们最后一次展示的舞台上,我评论了 Diversita cam:

然而,我们的长远眼光不仅仅是照相机。

当我们有一个支持 ML 的摄像头矩阵时,我们可以形成一个平台,这是一个智能边缘设备的平台。其可用于收集数据并从世界中获得洞察力,例如,监测水的纯度、环境的变化等等。

Diversita 项目的本质是使用边缘技术上的机器学习来识别特定的模式,并相应地对不同的结果做出反应。虽然 Diversita 是为陆地动物建造的,但我个人开发了 diversi ta+——技术框架场景的扩展——用于水下。用于训练模型的数据集可以是单个物种如鲨鱼、鳐鱼、梭鱼的光学相机图像。也可能是声纳反射模式。总的来说,Diversita+可用于协助海滩安全监测、海洋动物研究和水质监测。

三个示例概念:

  1. 狩猎区(hunt away):部署在海滩或类似地方的围栏系统,用于监控和抵御威胁人类生命的海洋物种。
  2. Remora:ML on Edge 设备,安装在船舶吃水线以下的船舷,它结合来自光学相机和声纳阵列的图像,识别海洋生物物种,并对数据收集的位置进行地理标记。
  3. 海马:集成了电子显微镜和边缘计算模块的设备。

如果你有兴趣,请查看以下文档了解详细描述:http://bit.ly/2EFxdgj。

3.2.媒体报道

photo credit: Scott Eklund

我们的团队很幸运地在微软上发表了一篇关于:http://bit.ly/2GxYvYA问题的报道。当这个故事发布时,微软总裁布拉德·史密斯转发了它。看到我们的合影出现在最有价值的上市公司总裁 Twitter 账户的时间轴上,真是令人惊讶。

3.3.信用

最后,我想给以下的人热烈的掌声:

  • 布莱克·汉纳福德、琳达·瓦格纳、约翰·莱蒂:感谢他们的指导和帮助;
  • 尼古拉斯·艾姆斯:为我们提供了可靠的制造设备;
  • 肯特·福斯特:为微软和 UW 牵线搭桥,使该项目成为可能;
  • 微软项目团队:为我们提供了这个参与这个项目的机会,特别感谢杨思雨,当我们的机器停机时,他及时联系了微软园区的制造部门;
  • 马克西姆·苏尔盖伊:作为我们的第五名成员,为我们提供焊接工具、螺丝和胶水。

本文原载于我的博客:https://catalium . net/project _ diversita _ when _ machine _ learning _ meets _ user _ experience/

潘德雷肯计划:命运大订单的人工智能机器人

原文:https://towardsdatascience.com/project-pendragon-an-ai-bot-for-fate-grand-order-23f51b6e3268?source=collection_archive---------6-----------------------

作为一名数据科学家,我经常不会真的对我的模型做任何事情。我投入了大量的时间来建立数据集,准备数据,训练模型,调整它们的超参数,然后我将它们存储起来,再也不会被看到。所以我想这一次我会试着把它们整合到一起。

潘德雷肯计划使用三个 Pytorch 神经网络的主干来决定在手机游戏《命运大令》( FGO)中什么时候出什么牌。对于一些人来说,这可能是我过度工程的解决方案,但对我来说,这是一个有趣的项目,实际上节省了我每天在游戏中的项目农业的时间。尤其是在早上,当我让机器人运行一些任务时,有额外的 10-15 分钟是很有用的。

这里的是 github 回购的链接

A previously trained face detection model only detects the center character, Altria Pendragon, FGO’s version of King Arthur Pendragon, but not either of the other two characters. The the other two characters are more in the background and faces are partly obstructed. Also the object detection model was trained on season 4 of The Flash… so it doesn’t actually have exposure to cartoon characters, I could build a specific network for that though. I’m using that model (calling it Flashpoint for now) as part of a raspberry pi remote greeter which could also be a good blog post…

FGO 的一些背景。这是一款移动设备的日本角色扮演游戏,你可以通过从一副牌中选择动作牌来控制角色。在任何给定的时间,你将有 3 个角色在场上,每个角色有 5 张自己的行动卡。动作牌有三种,艺术牌、巴斯特牌和快速牌,每种牌的数量取决于角色。每回合从 15 张牌中给你发 5 张牌(每个角色 5 张),没有替换,并且允许你选择 3 张牌作为该回合的行动。一个额外的机制是建造卡链有奖励。选择三张相同类型的卡片。链的例子见下面的两个图像。

Arts Chain: Pick 3 arts cards, can be from the same or different characters. Can do the same thing for any of the 3 card types

brave chain: pick 3 cards from the same character

当我坐下来思考我可以做的事情时,我意识到我可以使用一系列神经网络,通过 python 向游戏发送输入来选择卡片,来创建一个玩 FGO 的机器人。对机器人来说,一个基本但有效的游戏策略是,只要有可能,它就玩牌链。卡链在使用时会带来伤害或其他奖励,使用它们会使回合更有效率,因为伤害更高,因此战斗时间更短。

在开始编码之前,我必须弄清楚我希望机器人遵循的一般流程,以下是我想到的逻辑结构。

  • 开始时,它会查看是否能看到“攻击”按钮,如果找到,它会按下按钮并进入该回合的阶段,在该阶段中,它会从 5 张命令卡中挑选 3 张
  • 机器人会检查这 5 张牌中是否有 3 张是同一角色的。如果是这样,那么它就创造了“勇敢链”
  • 如果没有找到勇敢链,那么它将查看所有的卡,检查它们的类型,并寻找 3 张相同类型的卡来创建卡链。
  • 如果没有找到卡链。那么它将按以下优先级顺序播放。艺术卡,巴斯特卡和快速卡。(我倾向于在我的游戏中优先考虑艺术卡,因为它们为 FGO 中被称为“高贵幻影”的角色收取终极能力,所以我让机器人这样做)出于同样的原因,这也是机器人在不同链中尝试玩牌的顺序。
  • 一旦完成,它将开始检查攻击按钮的重新出现,机器人的回合将再次开始。

因此,在这个过程中,识别攻击按钮和卡类型的能力是传统的 CNN,而寻找同一人物的 3 张卡是连体 CNN。

我使用 Pytorch 构建了所有的网络,并在 1060 或 1080 Nvidia GPU 上对它们进行了训练。

然而,在这之前,第一步是让 FGO 在我的电脑上运行,这比我想象的要难。

Bot identifies that the first, second, and fifth card are all of the same character and so it constructs a chain using those three cards.

在个人电脑上运行 FGO

虽然这应该是很好很简单的,但是一些谷歌搜索很快让我知道,目前没有任何模拟器可以轻松支持 FGO,并且像在 Android 上使用开发者功能这样的选项与 FGO 不兼容。

所以在短暂的绝望之后,我偶然想到了用微软的 TeamViewer 来控制我的 android 设备。由于我通常使用 TeamViewer 来远程访问我的计算机,这看起来是一个优雅的想法,而且它证明工作得很好。使用 android TeamViewer 主机应用程序,我可以将我的手机添加到我现有的帐户中。对我来说,唯一的缺点是我的手机在长时间使用后会过热

设置好之后,我必须确认我能够启动 FGO,并测试通过 python 的 pyautogui 向它发送鼠标点击。令人欣慰的是,这是成功的,所以下一步是捕捉游戏屏幕的屏幕截图,并隔离神经网络将查看的部分,获得适当的 xy 坐标,以裁剪出图像的这些部分。

第一部分是玩家回合开始时出现在屏幕上的“攻击”按钮。一旦它出现,玩家按下它,并被允许选择他们的行动“命令卡”。到目前为止,我的策略是让机器人每秒检查一次攻击按钮,如果它检测到这个按钮,它将执行其余的代码。

clipping of the TeamViewer screen that gets fed into my bot for analysis

点击攻击按钮后的下一步是确定“命令卡”在下一个屏幕上的位置。我还注意到,五个命令卡总是位于屏幕上的相同位置,这意味着我也可以从屏幕上裁剪出命令卡,并作为输入输入到网络中。

Showing placement of command cards on the screen

现在我有了提取输入的方法,我需要运行它们。我已经准备好训练我需要的神经网络。

Bot identifies that there are 3 cards of the same color (card 2,3 and 5) and selects them to make a card chain

利用预训练 Pytorch CNNs

对于这两个网络,第一步是为我关心的班级获取图像数据。

第一个是二进制分类问题,以检测“攻击按钮”,我浏览了游戏镜头,剪出了几十个攻击按钮和按钮不存在的例子,这是大多数时间。

对于第二个分类器,我浏览了游戏片段,剪下了大约 60 张三种不同颜色的动作卡片。对于这一张,我预计虽然每张卡片上的面孔不同,但颜色是相同的,所以它会学会优先考虑卡片的颜色。

现在我已经有了两个小数据集,我准备好开始构建模型了。尝试从零开始训练网络是愚蠢的,所以我决定利用 Pytorch 中包含的预训练网络。像大多数图像分类问题一样,我采取的第一个方法是利用 Pytorch 的预训练网络,在这种情况下,我针对我的分类问题对现有网络进行了微调。Pytorch 的文档中列出了基本流程。像微调或使用预训练网络作为特征提取器这样的事情使我们能够利用网络,这些网络已经学习了图像分类的有用权重,我们希望这些权重将推广到我们的特定用例。

对于这两个模型,我使用了 Resnet 的变体(Resnet 18 和 50),我可能会使用两个 Resnet 18 实例,但决定尝试一下,看看在我的显卡上使用更大的 Resnet 50 模型需要多长时间。我对每个网络进行了大约 5 个时期的训练,对于这两个分类任务,它们都达到了大约 95%的准确率

确定卡类型的网络是 Resnet 50,它构成了我的机器人的主干。因为一旦我决定了卡的类型,我就可以形成卡链,这可能是最常见的卡链类型。见下面的例子,机器人识别,然后创建“艺术”链。

Bot identifies cards 1,3, and 5 as a chain.

用连体神经网络寻找勇敢的锁链

第二种类型的卡链是通过选择 3 张相同角色的卡创建的。所以从概念上来说,这比第一种卡链要难一点。目标必须是识别在已经分发的 5 张牌中,何时至少有 3 张牌是由同一人物发出的。

有几种方法可以解决这个问题。首先是建立一个经典的 CNN,学会识别游戏中的所有角色。这是可行的,但收集数据会很麻烦,因为至少有 100 个字符,并且很难获得足够大规模的数据以使网络收敛,甚至很难进行适当的微调。因此,在这种情况下,我想我可以应用我在以前的帖子中谈到的东西,暹罗神经网络。

有了暹罗网络,我可以使用一个相当小的数据集来训练一个网络,使其善于识别不同颜色卡片上的人脸的相似性。这也意味着我将能够极大地增加数据集,因为我现在将进行成对比较。

为了做到这一点,我利用了这个存储库中的数据集函数进行面部相似性分析,并修改了网络结构以包括最大池,部分是因为我的计算机将耗尽内存,但也因为我发现了一些改进,因为初始网络即使在变得更深时也保持了原始图像的大小,最大池被应用于让网络通过附加层来学习更复杂的图像特征。

这里的暹罗网络被训练为最大化或最小化两个输入图像的特征向量之间的欧几里德距离,这取决于它们是否相同。因此,对于我部署模型,我可以用它来测试一个命令卡与其他 4 个命令卡,并寻找相似性匹配。从计算的角度来看,这样做的一个缺点是,我将每张卡与所有其他卡进行比较,因此最坏情况下的运行时间是 N。

请参见下文,了解如何做到这一点。图像对可以通过网络输入,然后通过获取两个输出向量之间的欧几里德距离,可以得到网络看到的两个图像的不同之处(分数越低意味着越相似)。在这个例子中,网络运行良好,但仍有改进的空间。我发现很多人物最终看起来与侧面肖像相当相似,所以我可能需要包括更多这些更难比较的例子来帮助加强网络。

These are two cards by the same character and is really the comparison that this network was designed to make. By finding 3 of these matches the bot can create a brave chain and get an extra attack as a result (how the game rewards 3 cards by the same character)

Example of dissimilar pair, score of 1.17 is quire high

another more dissimilar pair

one where the network marks two characters as being similar while they are different. As discussed above this is probably the main area of improvement. The network was only trained on around 40 characters with 3 or so cards from each.

虽然还有待改进,但暹罗网络在实地确实表现良好。见下面的一些例子,它循环通过 5 张卡片,并将每张卡片与所有其他卡片进行比较。当它找到一个三元组时,该三元组被提供给机器人,机器人选择适当的卡来创建链。

bot uses siamese network to identify cards 3,4, and 5 as all being the same character so it constructs a brave chain

结束语

这个机器人是一个好的开始,它可以相当胜任地玩 FGO,在某种意义上它可以清除我让它通过的高等级任务。然而,它没有利用许多额外的游戏机制,这些机制可以提高它的效率。

  • 聪明地使用角色的终极能力,在 FGO 被称为“高贵的幻影”(NPs)。到目前为止,我让机器人在一定数量的回合后尝试使用角色的 NPs,他们可能会在那场战斗中用它来对付老板或更强的敌人,而不是浪费在早期较弱的敌人身上。
  • 利用 FGO 的阶级亲和系统。本质上是一个石头剪子布类型的设置,每个角色都有一个给定的职业,相对于其他职业有优势和劣势。有利的使用它会给你一个伤害加成,而不利的配对是一个伤害。
  • 让 bot 使用角色“技能”。在 FGO,角色技能在正确的时候非常有用,可以增加伤害,治疗盟友,减少敌人的负担等等。机器人目前没有利用这些,因此错过了很多。

机器人的下一个阶段可能是强化学习的应用,但这很难,因为 FGO 有一个行动点系统,在那里每场战斗都需要 X 个行动点,当你用完它们时,你必须让它们充电……这意味着我很难让它探索数千次迭代。另一个选择是建立一个模拟的 FGO 环境供它探索。这是可能的,但是会非常耗时。

编辑:作为一个后续帖子,我为上面提到的 FGO 制作了强化学习机器人,你可以在这里查看。我建立了一个自定义的游戏环境,让机器人通过玩数千种游戏来学习,发现它学会了一些很酷的行为!

这里的是 github 回购的链接

项目潘德雷肯第 2 部分:命运大订单的强化学习机器人

原文:https://towardsdatascience.com/project-pendragon-part-2-a-reinforcement-learning-bot-for-fate-grand-order-7bc75c87c4f3?source=collection_archive---------12-----------------------

Fate Grand Order wallpaper that I passed through a YOLOv2 object detector I fine tuned to detect human faces, it is somewhat surprising that it detects any cartoon faces…

在我之前的帖子中,我概述了一个我为玩手机游戏《命运大令》(FGO)而制作的机器人,昵称为潘德雷肯。潘德雷肯机器人的核心是三个神经网络,两个经典 CNN 和一个暹罗 CNN。网络的输出被机器人用来决定它被分发的五张卡中的哪张卡该轮到它玩。

在上一篇文章的最后,我讨论了一些可能的后续步骤,我提到的其中一个步骤是使用强化学习来训练一个模型,让它自己选择卡片,而无需我为它制定规则。我认为这将是非常困难的,因为我必须从头开始为机器人建立一个实验环境…但我继续这样做,因为我觉得这将是一个有趣的项目,值得付出额外的努力。这篇文章将介绍我如何为机器人建立一个简化的 FGO 环境,构建一个神经网络来决定选择哪张牌,使用强化学习来训练它,以及我对它所学游戏的印象。

在训练并将新的强化学习网络整合到我为扮演 FGO 而构建的框架中后,我决定给它取个昵称。现在我用的是 潘德雷肯。FGO 制作角色,然后是邪恶的“改变”版本,让他们不用做太多额外的开发就能制作更多的角色(并增加他们的收入)。所以我想我最初的潘德雷肯机器人可以使用一个,可能是邪恶的,强化学习的对等物。

作为一些背景,FGO 是一种游戏,玩家每回合发五张牌,他们从这五张牌中挑选三张作为该回合的行动。每种类型的卡都有自己的属性,以不同的组合使用它们有不同的好处。例如,玩三张相同颜色的牌会在牌的基础统计上增加额外的奖励。奖金的性质取决于卡的类型。艺术卡(蓝色)充能强大的终极能力,巴斯特卡(红色)造成额外伤害,快速卡(绿色)创造致命一击的可能性,双倍伤害。我试着在这篇文章中解释重要的游戏机制,但是请随意查看上一篇文章以获得组成 FGO 的其他通用机制的更详细的概述。

Pendragon Alter building an “Arts chain” picking 3 Arts cards

构建命运大秩序环境

像许多其他人一样,我使用 OpenAI 的健身房库,使用其他人的代码来训练一些简单的强化学习模型,但这是我这个项目的一部分动机,因为我想看看它是如何从头构建一个定制环境的。这方面的很多灵感来自于 2016 年斯科特·罗马(Scott Rome)的一篇帖子,他在帖子中创建了一个环境来训练网络玩 21 点(此处)。

在 FGO,玩家通常在任何给定的时间有 3 个角色在场上,大约有 9 个对手在三个以上的波中产卵。为了简化这一点,我将我的环境构建成一对一的战斗,两个实体的目标是通过每回合造成伤害来将对手的生命值减少到 0。

目前,这些战斗的基本结构是一个循环,每一次迭代都由两个团队组成,当一个团队的生命值降至 0 时,两个团队都会造成伤害。

敌人团队每回合在一个范围内随机选择一个数字来造成伤害,我认为这个简单的解决方案暂时可行,合理地调整敌人的伤害比重建他们如何处理伤害更重要。另一方面,玩家团队根据他们从五张牌中选出的三张牌组合造成伤害,这五张牌是根据他们的初始牌组发出的。我这样做是为了更好地反映玩家在 FGO 的战斗方式。

实现见 github 回购行 275–432 中的Colosseum . py

一旦这个循环建立起来,我就开始添加 FGO 用来放大伤害的后端计算和机制。我找到了这些计算和机制的值(这里)。

这些后端机制的一些示例:

  1. 崇高幻象(NPs):是 FGO 中人物拥有的强大终极能力,通常会造成大量伤害。NP 在使用前必须充电到 100%,这在“NP 量表”中进行跟踪。当前费用通过使用某些卡来增加。在我的实现中,当玩家的 NP 标准达到 100%时,该 NP 在下一回合被用来造成额外的伤害。玩家充能其角色的 NPs 的能力对于他们成功清除 FGO 战役至关重要。
  2. 致命一击:致命一击的百分比几率基于“致命之星”的生成。临界星生成的速率根据你使用的牌而变化。恒星在第 N 回合生成,在第 N+1 回合消耗。星星的数量增加了造成致命伤害的可能性。虽然成功获得致命一击有一些随机性,但如果你成功击中,你会造成双倍伤害,这是非常有价值的。
  3. 将一张牌放在三张牌链的不同位置会有奖励。例如,链中的第一张卡对链中的所有卡都有奖励,而第三张卡的属性显著增加。这使得使用链中的第一和第三张牌变得非常重要。我的潘德雷肯机器人,实际上没有很好地利用这个机制,新的强化学习机器人在这方面做得更好,详情见最后一节。
  4. 卡链:正如我之前提到的,将三张相同类型(颜色)的卡放在一起会有奖励,因为卡的统计数据被放大了。这种奖励加上从放卡中得到的奖励有助于使卡链在游戏中变得非常强大,因此是加入游戏环境的必要条件。

这些额外的机制可以在coloseum . py的第 104–235 行找到

构建神经网络

为了开始构建将网络整合到我的新游戏环境中的机制,我必须决定如何表示模型的动作空间。我的第一轮头脑风暴让我希望模型根据三种不同的牌类型(艺术牌、巴斯特牌、快速牌)来对不同的牌进行分类。但是我很快就碰壁了,见下文。

Hand: “Arts”, “Quick”, ”Quick”, “Buster”, “Arts”
output: “Arts”, “Arts”, “Arts”

我如何压缩输出,这样当只有两张可用时,它就不会尝试使用三张艺术卡?

我想不出一种优雅的方式来做到这一点,所以我不得不回到绘图板,想出一种方法来表示动作空间,这样每个输出节点总是有效的,它只需选择最好的一个。

我最终采用的方法是让行动空间成为从五个可能的卡槽中选择三个卡槽的所有可能的排列。我在这里的思考过程是,不要考虑牌的类型会不断变化,总会有五个有效的牌槽。因此,60 种可能的排列,即从 5 个顺序重要的位置中挑选 3 个,可能是表示动作空间的好方法。参见下面的前一手牌示例,对于前一手牌示例的输入,所有输出 1-60 均有效。

Hand: “Arts”, “Quick”, ”Quick”, “Buster”, “Arts”
output_1: “Card 1”, “Card 2”, “Card 3”
output_2: “Card 1”, “Card 2”, “Card 4”
...
output_60: “Card 5”, “Card 4”, “Card 3”

这意味着我构建的任何网络都将有 5 个输入节点代表 5 个卡插槽,60 个输出节点代表从 5 张卡中选出 3 张卡进行替换的所有方法。

netlearner.py 包含完整的网络代码,以及网络如何根据当前游戏状态采取行动,并根据观察到的结果更新自身。

起初,我担心网络是否能够在不同的类别之间归纳出“玩三张相同类型的牌是好的”这样的概念。给定两个输入向量:

Hand_1: “Arts”, “Arts”, ”Quick”, “Buster”, “Arts”
Hand_2: “Buster”, “Quick”, ”Arts”, “Arts”, “Arts”

我对这种方法的一个担心是,网络是否会认识到从任意一手牌中挑选三张艺术牌是一个好策略,因为选择“牌 1”、“牌 2”、“牌 5”和“牌 3”、“牌 4”、“牌 5”可以通过使用多个节点来完成?然而,网络确实学会了这种行为,我感到惊喜。

Pendragon Alter constructing another Arts Chain by picking the node corresponding to cards 3,2, and 4

深度 Q 学习

在强化学习中,没有初始数据集,我们允许网络探索环境的行动空间,在该空间中,它因不同的决策而受到奖励和惩罚,以便它可以尝试发现如何最佳地导航环境。

基本流程如下:

  1. 代理(在这种情况下是网络)被告知游戏的当前状态。这可能是一款雅达利乒乓游戏的像素,也可能是你选择的任何代表。在我的情况下,这是一个长度为 5 的牌列表。
  2. 代理从动作空间中选择一个动作。在 Pong 的例子中,Andrej Karpathy 把它作为上升的概率。我的 FGO 游戏是 60 种可能的卡槽组合中哪一种最好。然而,应该注意的是,在强化学习中,存在探索与利用的概念。本质上是说,有时应该随机选择一个动作,而不是简单地做代理认为最好的事情。这有助于代理探索和发现额外的奖励,否则如果它只是利用它知道的奖励,它将不会发现。
  3. 行动被归入环境,任何奖励被收集,环境进入下一个状态、框架或回合。机械地,我这样做是通过将奖励添加到网络输出的卡槽组合中。对于正的奖励,该类别在输出数组中的值增加,并且网络将再次看到给定该输入,该特定类别是有益的。
  4. 代理根据其收到的奖励进行更新。在奖励被用于修改输出阵列之后,网络以修改后的输出阵列为目标在初始输入状态上被训练。这有助于巩固好的选择,同时也考虑到坏的选择。
  5. 冲洗并重复。

这个过程循环可以在 斗兽场. py 中看到,其中战斗类调用网络来获得动作,并在每次迭代和游戏结束时用奖励更新自己。

如何奖励行为良好的机器人?

excerpt from FGO official comics making a joke about how players are addicted to rolling for new characters, but talks about rewards so figured I would include it

这一部分花了很多实验,但最终我发现了一套奖励,这个机器人工作得很好。最初我只对战斗的最终结果进行奖励,基本上是赢+1,输-1。在这一点上,机器人会展示一些有益的卡放置的知识,但没有更高级的行为,如持续建立卡链。在最初的几轮训练中,在我构建的定制环境中,网络的成功率很少超过 30%。最好的运行可能有 50%的胜率,但仍有很大的改进空间。因此,为了调整这一点,我在游戏中增加了额外的奖励,因为成功地使用了游戏中更复杂的机制。

为了尝试让机器人学习这些更高级的机制,我在环境中添加了额外的奖励。我添加的第一个奖励是打三张同类型的牌(艺术、巴斯特或快速),这对模型有帮助。经过一些测试后,我还为机器人增加了一个奖励,使其 NP 标准达到 100%。如前所述,卡牌链极大地放大了单个卡牌的效果,NPs 经常被玩家用来一次性完成战斗,所以我觉得这两者对机器人的成功都很重要。

我认为这样做的一个缺点是,机器人会强调做这些动作,这可能是我过度限制机器人来满足我对游戏的看法。在未来,我可能会通过为机器人添加一个记忆机制来解决这个问题,以跟踪一场完整的战斗中的所有行动和奖励,然后进行评估,而不仅仅是在每回合结束后进行评估。然而,在我目前的设置中,我每回合都进行评估,我发现这种奖励结构是有效的。

有了这些额外的奖励,我能够让机器人在训练时有大约 60-70%的胜率,经过更多的调整,最终网络在训练 50,000 场战斗后有大约 80%的胜率。我通过跟踪机器人在 10,000 场游戏中的表现来衡量这些胜率,所以当我说 60%时,这意味着它在过去的 10,000 场游戏中赢了大约 6,000 场,等等。

这些成功率可能会进一步增加,但我发现网络已经学会了一些好的和非常有趣的行为,我将在下面讨论。

潘德雷肯·奥尔特的结果以及与原始潘德雷肯机器人的比较

所以能够赢得我所经历的 80%的模拟战斗是很好的,但是现在我们来看看它在实际游戏中的表现。

为此,我将强化学习机器人集成到我在上一篇文章中构建的框架中,以与 FGO 手机游戏进行交互,并让它玩了一些比赛。

我之前概述过,我觉得接近 FGO 的一个好策略是让机器人在任何可能的时候玩卡牌链,然后我让它按照艺术、巴斯特和快速的顺序玩牌。我发现潘德雷肯·奥尔特玩艺术和巴斯特牌和链条相当一致。

Pendragon Alter picking a Buster chain based on card input

然而,虽然它玩快速链,但它并不总是这样做。相反,如果有两张相同类型的牌,其中有三张快速牌。它将在卡槽 2 中播放一张快速卡,在卡槽 1 和 3 中播放另外两张卡。(见下文)。这最大化了放在插槽 1 和 3 中的两张卡的效果。

Alter ignoring a Quick Chain to charge its NP using Arts cards in the first and third slot

如果有三张快速卡,一张艺术卡和一张巴斯特卡,它所做的是将巴斯特卡或艺术卡混合到第二个卡槽中,而不是打出三张快速卡来形成快速链。这意味着机器人放弃获得玩快速链的奖励(增加致命几率),要么现在造成更多伤害,要么进一步充能。

Alter ignoring a Quick Chain to charge its NP using Arts cards in the second slot

这让我很感兴趣,因为,首先,如果没有必要,它似乎没有发展出玩快速卡的爱好。这可能是因为我初始化的 15 副牌中只有三张快速牌,而有六张艺术牌和六张毁灭牌。所以它会更习惯玩艺术和巴斯特牌。第二个有趣的细节是,正如我上面讨论的,潘德雷肯·奥尔特似乎对第一和第三张牌槽中的扑克牌的额外奖励有一些直觉。

潘德雷肯·奥尔特建筑对第一张和第三张牌有额外奖励的一些理解也在没有锁链可用的情况下展示。在下面的例子中,它没有选择任何一张快速卡,而是用两张巴斯特卡和一张艺术卡建立了一个链。通过在链的开始和结束放置巴斯特牌,链将在该手牌的任何牌组合中造成最大的伤害,而中艺牌将帮助它提高 NP 标准。所以基本上潘德雷肯圣坛在充能的同时试图最大化自己的伤害。

Pendragon Alter maximizing damage by playing Buster cards in slots 1 and 3 while filling the 2nd card slot with an Arts card

当没有卡链可用时,我会认为潘德雷肯 Alter 优于我以前的潘德雷肯机器人,因为它更好地利用了卡链中的位置。下面是这两个机器人如何玩之前 GIF 中看到的那手牌。

Hand: "Buster","Quick","Arts","Buster","QuickProject Pendragon Bot: “Arts”, “Buster”, “Buster”
Alter Pendragon Bot: “Buster”, “Arts”, “Buster"

非常相似,但交换前两个卡槽的区别很重要。

我建立了潘德雷肯计划来玩所有可用的艺术牌,然后是巴斯特,然后是奎克。这意味着它将总是使用所有可用的艺术牌,但它不会最大化艺术牌的效果或巴斯特牌的伤害。最大化这两样东西的方法是玩潘德雷肯·奥尔特玩的那手牌。第一张巴斯特卡增加包括最后一张巴斯特卡在内的整个链的伤害,中间的艺术卡比第一个槽中的艺术卡造成更多的 NP 增益,最后一张巴斯特卡的伤害将增加第一张和第三张卡槽奖励。

因此,虽然我可以在潘德雷肯项目中添加逻辑来解决这一问题,但它暴露了我最初算法中的一个弱点,以及强化学习训练的潘德雷肯·奥尔特击败我最初机器人的一个领域。

最终注释

到目前为止,这些帖子受到了许多其他数据科学家及其工作的启发。Sentdex 的侠盗猎车手教程系列 , Chintan Trivedi 的关于他如何训练一个网络玩 FiFA 的帖子,以及之前提到的 Scott Rome 关于训练一个网络玩 21 点的帖子等等。因此,感谢所有为数据科学社区做出贡献的人,让它拥有如此丰富的信息!

虽然潘德雷肯·奥尔特展示了一些基本的强化学习如何产生一些有趣的结果,但仍有改进的空间。正如我提到的,能够考虑整个游戏而不是一轮一轮地玩将是机器人的另一个有趣的扩展。

在本系列的第 1 部分中,我构建了一个由三个神经网络驱动的基于规则的机器人来玩命运大令。第 2 部分展示了我如何构建一个可能是邪恶的“Alter”,强化学习的对等物。因此,我写第 3 部分来展示这两个机器人面对面放置时的情况似乎很合适。

项目潘德雷肯第 3 部分:斗兽场摊牌

原文:https://towardsdatascience.com/project-pendragon-part-3-the-colosseum-showdown-b7a855dd141?source=collection_archive---------19-----------------------

Screenshot from one of my speed runs for this blog post.

在我之前的两篇文章中,我讲述了我如何构建两个机器人来玩游戏《命运大令》(FGO)。第一个机器人(潘德雷肯)利用三个 Pytorch CNNs,两个经典的和一个暹罗的,根据我建立的算法识别卡片并播放它们。第二个机器人(潘德雷肯·奥尔特)在定制的游戏环境中接受训练,使用基于 Keras+Tensorflow 的强化学习,自行学习挑选卡片来玩 FGO。

我发现这两个机器人都能够完成大部分任务,包括一些 80-90 级以上的任务,这表明他们能够很好地扮演 FGO。然而,我还没有明确测试的是机器人在相互比较中表现如何,以及它们与人类玩家相比如何,在这种情况下就是我。

第三篇文章将介绍我对这两个机器人的性能进行对比测试的过程,以及我对如何改进它们的想法。就其本质而言,它不像前两篇文章那样具有技术性,而是对这两个机器人的性能进行定量和定性的比较。

由于 FGO 并不跟踪效率或分数之类的东西,我认为对这两个机器人进行基准测试的最佳方式是让它们使用相同的团队重复运行特定的任务。谁跑得更快,谁就是赢家。

指定时间和地点:

根据标题,你大概能猜到摊牌地点。我选择了 FGO 一年一度的尼禄节的最后一场比赛,选手们在罗马斗兽场与无数不同的敌人战斗。这个特殊任务的名字叫“回合”。回合是一个结束游戏水平 80+。除了推荐的高等级之外,这个任务的另一个困难之处是敌人类型的混合。

这种混合的敌人意味着你很难通过使用有利的职业配对来完成任务。所以这是我能为机器人选择的最难的任务之一,因为它们天生就必须靠暴力来完成。这个增加的难度意味着如果他们选择了糟糕的卡组合,他们将会受到游戏更严厉的惩罚。如果他们选择了不好的卡片组合,最好的情况是多花几个回合才能赢,或者在最坏的情况下会彻底输了,被消灭。

screenshot from the final battle of “The Rounds” quest. It is basically a battle against different knights of the round table. On several occasions the bots got stuck trying to defeat Tristan the red haired character on the left. He would fire his own ultimate several times and defeat multiple members of the bot teams and even managed to wipe out the Pendragon Bot on one occasion

选择团队

设计团队组成需要一点思考,这样他们才能发挥机器人的优势。一个人类玩家可能会尝试使用一个主要伤害制造者和两个辅助角色的组合。由于我的机器人不能使用辅助角色,在阵容中使用它们是相当无用的。因此,我决定在团队组成中尽可能多的增加力量,通过将三个最大等级的伤害处理者作为团队的主要部分,使之成为一场蛮力战斗。团队中的其他人是较弱的角色,我可以根据可用点数将他们放入团队中(见下图中的总成本 105/105)。

If anyone watches Critical Role, yes that is a Critical Role team name reference

规则和约束

因为我也是作为人类基准在这里竞争,所以解释机器人目前的限制很重要,这样我就可以匹配它们。

机器人有三个主要的限制,对我来说也很重要。

首先,我没有为机器人创造一种使用角色技能的方法。技能通常是强大的加成,可以叠加在一起放大攻击。我还没有为机器人建立一个使用技能的方法,因为让他们聪明地使用技能比仅仅编写脚本让他们在 x 回合使用技能要难一些。

第二,机器人从前到后依次清除敌人 1、2 和 3。玩家可以从技术上选择攻击哪个敌人,如果他们的手对某个特定的敌人没有优势,或者他们可能想攻击某个特定的角色,因为他们很危险。

最后,我给机器人添加了一个协议,他们在第十回合之前不会使用他们的终极能力,高贵幻影。我发现这大约是机器人进入最后一轮战斗所花的时间。如果我不包括这一点,机器人可能会在非常不合适的时候使用它们的 NPs,它们很大程度上被浪费了。这模拟了普通玩家的策略,在前两波攻击 NPs,在第三波(包含最后的 bosses)释放他们,以在一个回合中结束最后一波。

所以作为这场比赛中的人类选手,我也把自己限制在这些规则之内。快速重新总结如下

  1. 不能使用角色技能
  2. 不能选择敌人,必须从前到后攻击他们
  3. 在第十回合前不能使用终极能力,高贵幻象。

将这些功能添加到机器人上会是潘德雷肯或潘德雷肯变更代码库项目的一个很酷的补充!

由于这个任务中的敌人和这些限制,我相信理论上一个团队完成这个任务的最低回合数是 10。如果所有的 3 个 NPs 没有被使用,那么这个任务可以很容易地再拖 4-5 个回合。

谁生,谁死,谁讲述你的故事?

为了比赛,我让两个机器人中的每一个和我自己使用上面的团队组成和指定的规则运行“回合”任务 10 次。

我花了几个小时运行这个任务 30 次,部分原因是因为我在这个博客系列的第 1 部分提到过,在长时间使用 Teamviewer 后,我的手机会发热。然而结果很有趣…

最初的潘德雷肯机器人和强化学习训练的潘德雷肯·奥尔特乍一看表现非常相似,平均分别为 12.8 圈和 12.5 圈。此外,每个机器人都能够在 10 次转向时达到该测试的理论最佳分数。有趣的是差异,你会注意到潘德雷肯机器人的标准差更大,因为分数范围从 10-17,而潘德雷肯奥尔特的分数范围在 10-14 之间。

我在运行这些测试时注意到,当它们能够满足最佳情况时,两个机器人都做得很好。开始的三个角色在前两波战斗中幸存下来,给他们的 NPs 充能,然后在第三波包含老板的战斗中立刻释放他们。这两个机器人有时能够做到这一点,因为它们都优先使用艺术卡来给它们的 NPs 充电。最初的潘德雷肯是因为我硬编码了那个行为,而潘德雷肯改动是因为它自己学习了那个行为,以便在我为它构建的定制环境中获得 80%的成功率。

这两个机器人之间的差异可以在他们无法在第 10 回合获胜时看到,这通常发生在一个或多个开始的三个角色在第 10 回合之前被选中并击败时。原始的潘德雷肯几次被逼得走投无路,所以在测试中,它的得分是 15 分和 17 分。特别是到了 17 强的那一轮,整个团队都被电脑 AI 消灭了。这可能被认为是最坏的结果。潘德雷肯·奥尔特拥有更紧密的分布,最高得分为 14 分,并且从未像最初的机器人那样被推回到墙上。

这种紧密的分布很可能是由于潘德雷肯·奥尔特从第二部的自定义环境中的强化训练中学到了更好的游戏性。特别是潘德雷肯·奥尔特学到的游戏玩法是通过优先使用艺术卡和巴斯特卡来最大化伤害和 NP 收益,同时降低第三种卡类型的优先级,快速卡。

类似于我在第二部分中强调的,结合潘德雷肯·奥尔特对第一和第三张牌奖励的了解,下面可以看到一些艺术和巴斯特牌的优先排序的例子。

In this case Pendragon Alter chooses Arts cards in slots 1 and 3 and a buster card in slot 2. This is a choice the maximizes NP gain and helps Pendragon Alter get to that final wave with all of its NPs charged

这并不是说快速卡不好,但它们的伤害更低,并且不会对 NPs 收取那么多费用。由于致命一击,它们创造了更高伤害的随机机会,并且需要团队定制使用它们。然而,我所效力的球队并不像某些组合那样受益于致命一击。所以潘德雷肯改变学习去优先化快速卡让它在使用我扮演的角色时比原来的潘德雷肯平均造成更多的伤害。

这种快速卡的去优先化在潘德雷肯圣坛中表现为能够在早期回合中击败一个额外的敌人,或者能够在战斗后期输出更多的伤害。相比之下,最初的潘德雷肯机器人会浪费一个关键的游戏后期回合,通过玩更多的快速卡来造成更少的伤害,从而使游戏拖得更长。这种差异使潘德雷肯·奥尔特的团队在整个战斗中免受额外的伤害,并帮助它在最初的机器人努力消灭对手并因此受到额外伤害时持续清除任务。

下面是一个早期的游戏例子,潘德雷肯·奥尔特在牌槽 1 和 3 中挑选两张艺术牌,然后用一张快速牌来填充槽 2。最初潘德雷肯会打出三张快速卡,由于快速卡的低伤害输出,我不确定它是否能够击败最后一个敌人。如果敌人没有被击败,那么机器人的团队将受到另一轮的伤害。

潘德雷肯·阿尔特能够造成更多伤害的另一个地方是有三张快速卡的情况。最初的潘德雷肯机器人会玩快速链,因为这是它被编码要做的。然而,潘德雷肯·阿尔特并不总是玩这种牌,而是玩高伤害牌或能帮助他更快建立 NP 标准的牌。

This is an example Pendgraon Alter playing a higher damage hand that still generates critical stars, rather than simply generating critical stars, but dealing relatively little damage.

结束语

所以在这种情况下,经过强化学习训练的潘德雷肯·奥尔特击败了我亲手制作的潘德雷肯机器人。我认为这是一个非常酷的结果,因为在我建立强化学习环境之前,作为一个相当有经验的玩家,潘德雷肯·奥尔特比我更好地学会了如何玩 FGO。在那种环境下,我不得不研究 FGO 是如何计算伤害的,潘德雷肯·奥尔特可以从中学习。

虽然潘德雷肯·奥尔特击败了我最初的潘德雷肯机器人,但他们仍然没有超过人类玩家。即使有和他们一样的限制,我也能在十个回合中持续获胜。主要的区别是我能够应用更多的知识,比如利用职业亲和力系统,FGO 使用的石头剪刀布风格的职业系统,并确保我对所有角色的 NPs 充电,使他们都达到 100%,而不是像机器人一样不知道他们在充电谁的 NPs 就试图充电。

这些差异是机器人可以改进的地方,或者是游戏当前状态的更大背景。输入关于哪些卡对当前目标敌人有效的信息将有助于机器人优先使用哪些卡。让机器人可以检查他们团队中每个角色的当前状态,这可能有助于他们选择出牌来帮助收取特定角色的 NP,即使这是仅基于卡选择的次优移动。

如果我能在机器人中建立一些这样的功能,也许能在 FGO 达到接近人类的表现。这将是一个更崇高但也很有趣的更新,在未来我将不得不为此而努力。

感谢您阅读本系列,希望您也觉得有趣!

托弗计划:脸书·佩奇反应预测计划

原文:https://towardsdatascience.com/project-topher-facebook-page-reaction-prediction-program-95bcf4916892?source=collection_archive---------3-----------------------

我终于在旧金山大会完成了为期 12 周的数据科学沉浸式项目。对我来说,学习前沿数据分析&机器学习技术是一次非常好的经历。

本课程的重点部分是“顶点工程”。我想出了一个在脸书商业页面上建立一个反应预测程序的主意。我在这个项目中主要使用了自然语言处理和分类建模技术。

动机

我为我的顶点项目选择这个主题,因为大约 5 年前当我还是一名营销经理时,我真的很想有这样一个项目。我不得不为我每天管理的每个社交媒体设计内容,却不知道我的预期绩效结果。我必须根据我在脸书分析工具上的发帖记录和我的直觉,在社交平台上发布新的东西。如果当时我有一个自动反应程序,可能会对我更好。我根据公司的发帖历史设定策略,尽可能多地获得反馈,但这是一项如此不可预测的工作。因此,我决定建立一个社交网络反应预测程序,帮助几乎每天都在创建在线营销内容的社交媒体经理。首先,我选择创建一个脸书·佩奇反应预测程序,托弗。

1)Post from Whole Foods Market Facebook Page: ‘Status message’ and ‘Link text’ are highlighted by red lines

产品设计

我设计 Topher 是为了帮助社交媒体经理在过去分析他们的发帖历史和竞争对手的帖子时表现得比他们的平均表现更好。换句话说,这个程序显示你是否会得到比你目前得到的平均反应更多的反应。

该产品的目标是预测给定用户文本输入后的反应。脸书因其“喜欢”按钮而闻名,但它在去年(2016 年 3 月)推出了亚情感表情符号,如积极的爱、哈哈、哇,消极的悲伤和愤怒。

2)Facebook added sub emoting emojis such as Love, Haha, Wow, Sad and Angry in March, 2016

我把这些反应分成三类:积极的反应,消极的反应。我设计了这个程序来预测这篇文章,在给定文本输入的情况下,是否会比脸书页面上的平均表现获得更多的每个反应类别的数字。当你在页面上写下你的文字输入后,这个程序会自动评估你的表现。我没有在这个分析中包括“分享数量”和“评论数量”,因为我们无法仅用数字来推断分享和评论的哪个行为是积极的还是消极的。

数据集

我使用脸书 API 从 5 个杂货店页面获取了大约 15k 个帖子。数据包含文本和每种反应类型的反应数量。脸书提供的数据有两部分文本:“状态消息”和“链接文本”,在上图(图 1)中用红线突出显示。除了文本数据,该数据还包括其他信息,如“内容类型”、“发布日期”、“内容链接”等。我最初分析了“全食超市”数据集,后来将我的分析扩展到另外 4 个数据集。

数据预处理

首先,我从数据集中过滤掉一些极端的异常值和反应数量很少的帖子。除此之外,数据的分布是极其正偏的,所以我采用自然对数变换来使我的数据呈正态分布。由于该程序旨在帮助你获得比你之前帖子的平均数量更多的喜欢或积极反应,过滤这些帖子将有助于我的模型的一致性。

3)Remove outliers -> natural log transformed -> remove posts with least number of reactions

除此之外,如果你的帖子是付费的,那么比普通粉丝数量有更高的可能性接触到更多的人,也更有可能获得更多的反应。事实上,当我比较离群值的文本时,我无法说出离群值和只有文本数据的正常帖子之间的任何特殊差异。因此,我怀疑那些极端的异常值可能是付费的帖子,或者那些有大量回复的帖子可能有一些背景。然而,这次我无法证明这个假设,因为我无法获得关于每个页面上哪个帖子是有机的或付费的信息。因此,这次我只是为了模型的一致性而将它们过滤掉。

4)Texts from normal posts

第二,我把两列文字合并成一列,因为“状态消息”和“链接文字”同时出现在一篇文章中。在整个项目中,我意识到文本越多,建模的结果就越好。

第三,为了简单起见,我从文本中删除了特殊字符、数字和链接名(比如‘https://…’)。

第四,数据规范化。由于每个页面的粉丝数量不同,曝光度也不同。当我将我的分析扩展到另外 4 个数据集(如 Safeway、Sprouts、Walmart 和 Kroger)时,我将每个反应的数量除以每个页面的粉丝数量进行了归一化。

5)pairplot for num_likes and num_reactions

最后,当我研究变量之间的相关性时,我注意到反应的数量和喜欢的数量高度相关。这是因为在 2016 年 5 月之前,“赞”是脸书上唯一的情感反应按钮,超过 95%的反应来自“赞数”。

从现在开始,我将主要解释全食超市数据集(WFM)的数据分析和建模过程。

自然语言处理

对于文本数据处理,我使用了 Scikit-learn(sklearn)、NLTK 和 Gensim 库来分析文本数据。

首先,我使用停用词去除频繁但不必要的词,并使用 Tf-idf 向量机创建文本稀疏矩阵,该向量机赋予频繁和重要的词更多的权重。Tf-idf 是“术语频率和逆文档频率”的缩写,它是一种数字统计,旨在反映一个词对集合或语料库中的文档有多重要,并且是广泛用于信息检索的技术。除此之外,我过滤掉了在整个语料库中只出现一次的最不常用的词。

6)distribution of most frequent words(x-axis: frequency rate)

7)distribution of least frequent words(x-axis: frequency rate)

我必须查看真实的单词,确定哪些单词是不必要的或重要的,更新包含要从原始语料库中过滤的单词的停用单词列表,并一遍又一遍地调查单词的分布。这可能是一项非常乏味的工作,但对于自然语言处理来说却非常重要。

我还研究了 n 元语法,这对于相邻单词的序列是有用的。N-gram 是来自给定文本序列的 n 项的连续序列。我能够理解哪些单词经常一起使用,并更好地理解上下文中的单词。

在清理和过滤不必要的单词后创建的文本稀疏矩阵将被用作预测器,以预测一个帖子是否会在建模中获得更高的反应数。

更多特色工程

对于分类建模,我使用上面的 tf-idf 矢量器创建了一个文本预测器。然而,仅使用标记化的文本数据,我无法获得高准确度分数,因此我必须想出更多的特征工程技术。我尝试创建了几个功能,如使用 word2vec 的文本向量表示、内容类型、可读性和文本列长度。

首先说明结论,文本长度可以有效区分低于平均文本和高于平均文本。当我查看数据时,我可以看到较短的文本通常会得到更多的反应,所以我创建了一个文本长度列,并使用预测器进行分类建模。

  1. mean of number of reactions for text length

除此之外,“内容类型”列稍微增加了准确性分数。然而,我没有包括这个功能,因为我的程序不会接收输入的内容类型(如视频,图片,只有文本)将用于这个职位。数据类型和反应数量之间肯定存在正相关关系。然而,我决定这次不包括这个特性,我将在不久的将来把它与图像和视频分析结合起来

  1. video and photo has the most biggest number of likes(mean)

型号选择

下面是我为托弗做的最终模型的解剖图。

目标

Topher 将新的用户文本输入分为 2 类(低于/高于平均值),每类 3 种反应。

  • 反应:喜欢,积极反应(爱,哈哈,哇),消极反应(悲伤,愤怒)
  • 目标类:低于平均类(类 0),高于平均类(类 1)

预测值

  • 清理和标记文本数据
  • 文本长度

模型:带有决策树分类器的 Adaboost 分类器

我的最终模型是 Adaboost(Adaptive Boosting 的缩写)分类器,这是一种用于集成方法的机器学习元算法。

决策树分类器

决策树分类器是该模型的基础分类器。决策树分类器根据输入变量中最显著差异将输入数据划分为预定义类别。由于决策的重复过程看起来像树的节点,因此被称为决策树。

Adaboost 分类器

Adaboost 分类器将基分类器的性能训练成强分类器。根据 Scikit-learn 文档,boosting 基本估计量是按顺序构建的,人们试图减少组合估计量的偏差。其动机是将几个弱模型组合起来,产生一个强大的集合。

弱模型被顺序添加,使用加权的训练数据进行训练。该过程继续,直到已经创建了预设数量的弱学习者(用户参数),或者不能对训练数据集进行进一步的改进。

我以 7:3 的比例将数据集分为训练数据集和测试数据集。我用训练数据训练我的模型,并用测试数据集测试模型。最后,在使用 Adaboost 分类器的所有五个源/数量喜欢的情况下,我的准确度得分为 0.87。这意味着我的分类模型以 87%的准确率预测了输入文本的性能。

10) Accuracy score comparison_ number of likes model

查看 Topher 的最终模型,总共有 6 个分类模型在一起工作。我最初开始只分析全食超市数据集的每个反应(赞数、赞数和负数),并将我的分析扩展到所有 5 个杂货店数据集。通过这六个模型,用户不仅可以将他们的文本输入结果与他们自己过去的数据集进行比较,还可以与他们的竞争对手进行比较。

  1. Accuracy score table_all models

我对积极和消极反应的准确率更高。你可以看到红线框里的数字。然而,这些对于这个模型来说并不是好的分数,因为这些模型是过度拟合的。

根据维基百科,在过度拟合中,统计模型描述的是随机误差或噪声,而不是潜在的关系。过度拟合发生在模型过于复杂的时候,例如相对于观察值的数量有太多的 p 参数。过拟合的模型具有较差的预测性能,因为它对训练数据的微小波动反应过度。在这种情况下,num_pos 和 num_neg 的这 4 个模型几乎只预测了一个类别(低于平均值)。

这是因为阳性和阴性反应的数据数量非常少(不到整个数据集的 5%)。由于 Adaboost 容易对小数据集和太多参数(在这种情况下,文本稀疏矩阵超过 16,000 列)过度拟合,这种情况发生在这四个模型上。然而,我没有排除这些模型,因为我假设当我以后获得更多数据时,我可以改善这个问题。

模型性能评估

我的最佳模型有 87%的准确率。精度是正确预测的观测值之比。这个分数是选择最佳模型的直观的和主要的度量,但是这对于分类器的性能评估是不够的。为了更彻底地评估分类模型,我还使用了 Scikit 中的一个常规函数——学习库,分类报告。我将用我的主模型和 num_likes 的 5 个杂货店数据集来分析模型性能。

分类报告

分类报告有 3 个主要的分类指标:精确度、召回率和 f-1 分数。

  • 精度表示所选类别中正确阳性结果的比率:真阳性/(真阳性+假阳性)
  • 召回率表示相关数据中正确预测的阳性事件的比率:真阳性/(真阳性+假阴性)
  • f-1 分数是精确度和召回率的调和/加权平均值。因此,这个分数同时考虑了误报和漏报。直观上,它不像精确度那样容易理解,但是 F1 通常比精确度更有用,尤其是当你的职业分布不均匀的时候。:2(召回率精确度)/(召回率+精确度)

Classification report for the main model with 5 grocery store dataset for num_likes

从我的最佳模型的分类报告来看,每个分数看起来都很不错。不同类别之间在精确度和召回率方面存在一些差异,但总体而言,该模型在超过 16,000 个特征(标记化单词)的情况下工作良好。

网络应用

我使用 Flask 和 Reactjs 与一名开发人员一起创建了一个 web 应用程序。这个程序被设计成当你在输入框中输入你的文本时立即显示结果。

程序演示

下面是 Topher 演示页面。第一个窗口仅用于 WFM 数据集,第二个窗口基于 5 个杂货店数据集。当您想要查看仅使用过去的数据时,您的文本输入将如何执行时,您可以使用第一个窗口。如果您想与他人比较您的表现,您可以在第二个窗口中键入文本。

例如,在第一个框中键入“复活节快乐”,然后您会看到您的输入将获得比平均数量更多的反应。在这个演示中,“高于平均受欢迎程度”意味着你将获得比你之前帖子平均更多的“喜欢”。

这个项目现在不对公众开放。当我很快创建一个供公众使用的网站时,我会在这里链接该程序。

未来工作

对于这个项目,我专注于文本分析,试图捕捉文本和反应之间的关系。直观地说,图片和视频的质量对吸引用户关注脸书有着最大的影响。为了检验我的假设,我对周围的人做了一个简短的调查。

问题:当你看这个帖子的时候,你首先看到了什么?

  1. 状态消息
  2. 图片/视频
  3. 链接文本

我询问的大多数人(60 人中有 58 人)回答说
图片首先引起了他们的注意,然后是“链接文本”和“状态消息”。我想很快将项目范围扩大到图像&视频。

关于作者

我是加州圣何塞的一名热情的数据科学/机器学习从业者。我是一个终身学习者,目前对 NLP 和深度学习非常感兴趣。你也可以在 Linkedin 上找到我。

表现出自信

原文:https://towardsdatascience.com/projecting-confidence-5fe3a799913d?source=collection_archive---------15-----------------------

概率赛马如何遣散公众

受唐纳德·川普在 2016 年大选中令人震惊地击败希拉里·克林顿的启发,肖恩·韦斯特伍德、伊普塔赫·莱克斯和我开始探究这样一个问题:elecion 的预测——尤其是概率性预测——是否有助于制造一种对克林顿获胜的虚假信心,并最终导致许多左翼人士在选举日留在家中。

选举后,纽约杂志引用了希拉里本人的话:

有人真的在寻求赦免……’很抱歉我没有投票。我以为你不需要我。“我不知道我们将如何计算有多少人认为它是稳操胜券的,因为百分比一直被抛给人们——”“哦,她有 88%的机会赢!

预测可能影响了选举,这有可能吗?

为了影响选举,它必须出现在媒体上,接触潜在选民,压低投票率,并对克林顿支持者(和/或克林顿竞选者)产生比特朗普更大的影响。

与过去的选举周期相比,2016 年媒体对概率预测的报道明显增多:

(谷歌新闻索引的提及概率预测的文章数量。)

我们的研究(见下面的结果)表明,在民调中领先的候选人更容易受到概率预测的影响。2016 年,那是希拉里。

但不管 2016 年如何,当你看谁在社交媒体和电视媒体上接触这些材料时,你会发现这些渠道拥有左倾的观众。根据概率展示民意调查汇总结果的网站拥有左倾(负面)的社交媒体受众——只有不强调获胜概率的 realclearpolitics.com 拥有保守的受众:

这些数据来自那些分享链接到脸书各种投票聚合网站的人的平均自我报告意识形态,这些数据来自本文的复制材料。

当你看一下主要电视广播对概率预测的报道平衡时,你会发现对 MSNBC 的报道更多,那里有更自由的观众。

预测者到底有多大影响力?

嗯,FiveThirtyEight 的 2018 年报道似乎已经很有影响力了。在他们的实时预测显示共和党获得众议院席位的几率在晚上 8 点 15 分左右达到 60%后,PredictIt 预测共和党的几率升至 50%以上,美国政府债券收益率短暂飙升 2-4 个基点。

这种激增似乎已经发生,因为许多大的,共和党占主导地位的地区在那些支持民主党的地区之前开始报告回报,还因为它从部分选票统计中做出推论:

这是由 FT.com 的布莱恩·格里利首先报道的。他们报告说,由于市场预期在共和党控制下(高支出、低税收),美国债券收益率上升。

这只是一种关联吗?有可能,但在美国几乎没有其他事情发生,就像上面 FT.com 的文章指出的那样,欧洲现在是凌晨 1 点。

Josh Tucker 在一篇猴子笼博文中提出,2012 年,538 可能正在推动预测市场。

我们对预测和感知的研究

我们的研究显示,概率性的选举预测让一场比赛看起来不那么激烈。国家概率调查实验的参与者在看到概率预测后,比看到同等的投票份额估计和误差幅度后,更加确定一个候选人将赢得假设的比赛。这是一个很大的影响——这些是置信区间而不是标准误差,p 值低于 10^-11.

人们为什么会这样做?

这里需要更多的研究,但我们确实有一些线索。首先,公众最熟悉的选举指标——投票份额估计——的微小差异通常对应于候选人获胜概率的巨大差异。

Andy Gelman 在 2012 年的一篇博文中顺便提到了这一点,质疑 538 在其网站上传达预测时使用的十进制精度(0.1%):

没错:0.1%的获胜概率变化对应着 0.004 个百分点的两党选票份额。我看不出想象如此精确的选举预测有什么意义……

其次,人们有时会混淆概率预测和投票份额预测,并错误地得出结论,认为候选人预计会赢得 85%的选票,而不是有 85%的机会赢得选举。在我们的实验中,大约十分之一的人会这样做。

正如约书亚·本顿在推特中指出的,TalkingPointsMemo.com犯了这样一个错误:

最后,人们倾向于从定性的角度思考事件发生的概率 (Sunstein,2002) , (Keren,1991) 。有 85%的可能性某事会发生意味着它将会发生。这些研究可能有助于解释为什么在 2016 年大选后,如此多的人批评预测者“搞错了”(见这个和这个)。

投票呢?

也许最关键的是,我们发现显示更多井喷的概率预测会降低投票率。在研究 1 中,我们发现基于自我报告的证据有限。在研究 2 中,我们表明,当参与者面临模拟现实世界投票的激励时,当概率预测显示一名候选人获胜的可能性更高时,他们不太可能投票。然而,他们对投票份额的变化没有反应。

这真的会影响现实世界的投票吗?

想想 2016 年——异常多的民主党人认为领先的候选人会以相当大的优势获胜:

在选举前的民意调查中,认为领先的候选人将会以相当大的优势赢得 T21 的人,比认为这是一场势均力敌的选举的人说他们在选举后投票的可能性低大约 3 个百分点。这是在控制了选举年、之前的投票率和政党身份之后。

这里的数据来自美国全国选举研究(ANES)的数据,可以追溯到 1952 年。

过去的社会科学研究也提供了证据,证明认为竞争激烈会提高投票率。一些最好的证据来自分析投票结束前公布投票后民调结果的影响的工作,这显然消除了不确定性。研究东海岸电视网为一个或另一个候选人“提前打电话”对西海岸投票率的影响的工作通常发现微小但具有实质性意义的影响,尽管这些电话发生在选举日的后期(德利·卡皮尼,1984) ,(苏德曼,1986) 。利用投票改革作为自然实验的类似工作显示,在出口民调公布后,法国海外领地的投票率下降了整整 12 个百分点 (Morton,Muller,Page,& Torgler,2015) 。这些设计不会与竞选团队在竞争激烈的竞选中投入更多资金的趋势相混淆。

研究人员一致发现,更严格的选举和更高的投票率之间存在强有力的关联。 (Cancela & Geys,2016) 供点评】。此外, (Nicholson & Miller,1997) 从统计模型中提供证据表明,先前的选举结果也解释了超出竞选支出的投票率,尤其是在没有良好的投票数据的情况下。

实地实验提供了额外的证据,表明对更激烈的选举竞争的感知会增加投票率。这项工作发现,当民调结果显示通过电话传递一场势均力敌的比赛时,会对投票率产生实质性影响[在那些被触及的人中, (Biggers,Hendry,Gerber,& Huber,2017) ],但当依靠明信片传递近距离信息时,结果为零[无法验证是否实际阅读了该处理,(缺少参考文献);(比格斯,亨德利,格柏,&胡伯,2017) 。最后,在 2012 年总统大选前几周进行的一项研究发现,在公布表面上显示奥巴马与罗姆尼不分上下的民调结果时,自我报告的选举后投票率更高[这与现存的显示奥巴马轻松领先的民调数据不一致, (Vannette & Westwood,n.d.) ]。

这也会影响政治家吗?

候选人对选举接近程度的看法会影响竞选和代表 (Enos & Hersh,2015) , (Mutz,1997) 。

这些看法也可以影响政策决定——例如,在 2016 年选举之前,据报道,奥巴马政府对克林顿获胜的信心是对俄罗斯干预选举保持沉默的一个因素。

前联邦调查局局长詹姆斯·科米表示,由于对希拉里获胜充满信心,他觉得自己有责任在 10 月 28 日写信给国会,表示他将重新调查希拉里的电子邮件。科米解释了他的行为,基于他对克林顿获胜的某种信念:“(她)会当选总统,如果我对美国人民隐瞒这一点,她当选的那一刻,这一点出现的那一刻,她就是非法的”。内特·西尔弗一度表示,“科米的信可能让希拉里输掉了选举。''

媒体报道 华盛顿邮报, FiveThirthyEight 的政治播客,纽约杂志,政治专线。

参考文献

  1. Keneally,M. (2018)。科米说每个人——包括他自己——都认为克林顿会赢得 2016 年大选。美国广播公司新闻。ABC 新闻网。检索自https://ABC news . go . com/Politics/comey-included-thought-Clinton-win-2016-election/story?id=54486869
  2. Biggers,D. R .,Hendry,D. J .,Gerber,A. S .,& Huber,G. A. (2017)。关于选举接近程度是否(以及为什么)影响投票率的实验证据。从 https://huber.research.yale.edu/materials/67_paper.pdf 取回
  3. 坎塞拉,j .,&盖斯,B. (2016)。解释投票率:国家和地方选举的荟萃分析。选举研究42 ,264–275。
  4. Enos,R. D .,& Hersh,E. D. (2015)。竞选对选举接近度的看法:不确定性、恐惧和过度自信。《英国政治科学杂志》,1–19 页。
  5. 莫顿,R. B .,穆勒,d .,佩奇,l .,和托格勒,B. (2015)。出口民调、投票率和从众投票:来自自然实验的证据。欧洲经济评论77 ,65–81。https://doi . org/http://dx . doi . org/10.1016/j . euro ecorev . 2015 . 03 . 012
  6. Geys,B. (2006 年)。解释投票率:总体水平研究综述。选举研究25 (4),637–663。
  7. 桑斯坦(2002 年)。情绪、最坏情况和法律。《耶鲁法律杂志》112 (1),第 61–107 页。
  8. 尼科尔森,S. P .,,米勒,R. A. (1997)。1986 年和 1988 年国会选举中的先验信念和投票率。政治研究季刊50 (1),199–213。
  9. 穆茨,哥伦比亚特区(1997 年)。动力机制:是思维让它如此吗?《政治杂志》59 (1),第 104–125 页。
  10. 克伦,G. (1991 年)。校准和概率判断:概念和方法问题。心理学报77 (3),217–273。
  11. 苏德曼(1986 年)。出口民调会影响投票行为吗?舆情季刊50 (3),331–339。
  12. 德利·卡皮尼,硕士(1984 年)。拉拢选民?1980 年电视网提前宣布总统竞选的后果。《政治杂志》46 (3),866–885 页。
  13. 选举前的民意调查能影响投票率吗?来自随机实验的证据。检索自https://www.dartmouth.edu/seanjwestwood/papers/polling . pdf

原载于https://solomonmg.github.io/projects/1_project/

数据的承诺和陷阱,或者不是所有的数据都是一样的。

原文:https://towardsdatascience.com/promise-and-pitfalls-of-data-or-not-all-data-is-created-the-same-14f59123e3a4?source=collection_archive---------6-----------------------

大约十年前,当“数据科学”变得流行时,许多观察家附和并胜利地宣布“科学方法”的时代已经结束,例如,根据《连线》杂志上这篇令人眼花缭乱的文章。许多科学家理所当然地感到震惊,并发出了歧义——我特别喜欢彼得·诺维格回复的这篇深思熟虑的文章,他是我深深敬佩的人。但是,就数据的更随意的用户而言,我怀疑《连线》杂志比像诺维格这样的真正的科学家做得更正确。底线是,当涉及到他们在“业务”中可能不会遇到的罕见事件时,人们不在乎“真实”的解释。他们想要“有效”的精巧的解决方案,不管深入的解释是什么。如果 Google Translate 在不真正理解这些语言及其各种细微差别和复杂性的情况下,能够高效地翻译需要翻译的常见文档,为什么不呢?如果所有复杂的理论都只与日常商业交易中不会出现的少数不寻常的情况有关(例如,诗歌、古日语中的宫廷行话、一些奇怪的稀有语言,或者其他什么),为什么要为所有的理论化费心呢?不管我们喜不喜欢,Google Translate 的成功在于认识到翻译中 95%的复杂性和怪异之处与不到 1%的怪异案例有关,并且在开发翻译引擎时可以省去它们——至少在最初阶段是这样。

这不是翻译算法所独有的。相当可靠的数据既便宜又丰富。与复杂的理论相比,它们可以用于创建相对简单的度量,并以熟练的方式表现良好。他们失败的地方是相对较少的“怪异”案例,从大的方面来看,这些案例不寻常到足以被安全地忽略——除非它们可能是相关的。还有另外两个领域,我对引入数据科学方法既着迷又沮丧:政治和棒球。识别和衡量“优秀的棒球技术”或“意识形态”本质上是一项不可能的任务:我们不知道它们到底是什么,就像翻译普希金的诗歌一样。但是翻译俄语并不需要理解普希金的诗歌,毕竟,即使对俄罗斯人来说也没有多大意义。有很多更容易、更容易翻译的文档可以用来训练你的算法,而且大多数文档更接近这些常规文档,而不是普希金。因此,一个好的政治观察家或一个好的侦察兵在遇到奇怪的情况时可以胜过算法,就像一个好的翻译可以比算法更好地翻译普希金一样。但是,对于绝大多数任务来说,这种专业知识要么很少或根本没有改善常规算法,要么甚至可能表现更差。

这突出表明的问题是一个经典的统计问题,即异方差问题,但与通常描述的方式略有不同:根据模型的情况,误差在所有数据中的分布并不相同,或者换句话说,不同的模型在预测能力方面对不同的数据子集有不同的“效率”。当然,这是所谓的投资“反模式”思维或“ε理论”背后的基本观点。但我不认为这必然超出了算法思维的范围,只要人们不期望相同的算法对所有数据都同样有效——我在这里广义地定义“算法”。举一个简单的例子,如果条件 A 成立,数据生成过程总是产生 1,但如果条件 B 成立,则返回 2 或 0,但概率相等,如果条件 B 很少发生,但有一定的规律性,则可以通过使用两层方法进行改进:如果 A 预测 1,如果 B 预测 2 或 0。 一刀切的模式:总是预测 1,这对于线性思维来说是“正确的”,但前提是分析师故意忽略 A 和 B 之间的区别。这种改善只会是微不足道的,尤其是在 B 很少的情况下,而且它仍然会经常出错——如果我们无法预测最佳对策应该是 2 还是 0——这确实处于不确定性领域,鉴于手头的数据,但仍然是一种改善。 有人可能会说,如果一个星探说一个毫无意义的潜在客户仍然会很棒,如果这个星探很好,在这个潜在客户身上投资一点可能是值得的,数据就见鬼去吧。(我在某种程度上颠倒了赫伯特·魏斯伯格的论点,但是,我认为我忠实地抓住了他的真正论点:当我们从事统计分析时,我们确实必须故意无知——因为这是统计学的全部意义——但是我们需要认识到,当我们有机会时,我们已经准备好并愿意学习。

但是这需要一个理论,任何理论都需要评估它的有用性。一个球探根据一个理论来运作,这个理论是关于一个好的棒球运动员是如何形成的,这个理论可能不是普遍适用的——至少不是那么成功。如果这个理论不是普遍适用的,我认为正确的做法是不要彻底抛弃它,而是留下一种可能性,即这个理论仍然是好的,但只是对一些数据子集而言——如果那个数据子集能够以足够高的可靠性被识别,它仍然是有用的。因此,一个只适用于将俄语诗歌翻译成英语的理论可能仍然是好的——即使相对于统计算法而言,它对翻译军备限制条约并不那么有用。(顺便提一句,诺维格针对这一点提供了另一篇深思熟虑的文章,作为对乔姆斯基观点的回应。)如果球探能够比从一个天真的统计模型中推断出的机会更好地识别出在那些矮小和骨瘦如柴的人中脱颖而出的投手,那么也许我们已经在数据中识别出了他的理论应该得到更好机会的利基。

正如我在之前提到的,数据的问题,特别是当涉及到“大”数据时,是绝大多数样本与我们感兴趣处理的问题没有什么关系:如果我们想知道国会议员可能如何投票表决一项关于糖的修正案,比如说,从压倒一切的关注是投票给政党的大量投票中收集的数据并不特别适用,除非糖的问题不知何故成为了一个政党的问题。但是,即使记录的投票数量可能会成倍增加,大多数新的投票都会被精确地记录下来,以便国会议员可以按照政党路线突出他们的投票——这使得从中得出的措施几乎没有用处。现在,这本身就很重要——过去,国会议员会在他们投票的地方隐藏选票,并试图突出他们投票的地方,这对于选民来说是相对容易的,因为国会记录,即使记录了投票,也不容易获得。但关键是潜在样本本身正在以有意义的方式发生变化,而故意忽视这一点并坚持认为“意识形态”正在变化是误导性的,特别是当涉及到更罕见但仍具有潜在重要性的选票时,这些选票中的“地区关注”超过了“政党考虑”。

我认为解决方案是重新思考盲目崇拜大数据,但明智地怀疑其影响。大数据让我们对全局有了更准确的理解,这比没有数据我们所能获得的任何东西都更准确。但是它的发现掩盖了那些被错误地归为“错误”的微妙的小模式。然而,正是因为数据如此之大,它也提供了发现这些微妙模式的机会,如果一个人屈尊更仔细地观察,套用里科弗上将的话,具有讽刺意味的是,一个伟大的工程师而不是科学家,意识到这些细节才是拯救之所在。

PS。按照我的想象,统计建模的未来可能会如下发展。最近,参数不同地应用于数据的不同子集的多水平类型模型风靡一时:它提供了一种手段,以某种严格的措施来识别主要效应的差异及其统计意义。问题是,根据上面示例中确定的问题,数据子集之间的关键差异通常不是实质性影响,而是噪声量:对于始终为 1 的子集和以相等概率取值为 2 或 0 的子集,最佳预测值仍然是 1。如果一个人所寻求的只是确定“正确”的答案,而不考虑“错误”的程度,那么总是选择 2 以 B 为条件将是更好的反应。如果担心平均误差,但得到“正确”的答案仍然比总是错误更有价值,那么根据 B 在 0 和 2 之间随机猜测比得出它总是 1 的结论更好。像这样的嵌套决策模型在博弈论中并不少见。我不明白为什么这不应该适用于一个统计模型——其中感兴趣的关键统计数据应该是不同数据子集的条件方差,也就是说,即使抛开同质假设的伪装——即使它可能禁止用一个方程来总结整个数据,我认为这无论如何都是一个危险的错误偶像。

PPS。关于诺维格和乔姆斯基,我想我提出的是第三种方法,不同于两者,但吸收了两者的要素。正如诺维格所描述的,乔姆斯基的宇宙是“数学化的”(或者,我称之为“公理化的”)。)命题之所以为真,是因为它们是真的,并且它们依赖于某种“永恒的真理”,无论是上帝还是逻辑。现实是混乱的,它偏离了这个真理。例如,优秀的运动员最终会成为糟糕的棒球运动员。但是这种模式对于一些数据子集来说更为明显。我们不需要太多的公理化理论来处理常规数据。如果数据显示一种模式,那就取代了理论。但问题是,数据向我们展示的模式是什么?对于数据的某些子集,这种模式可能很明显。对其他人来说,可能不是。对于后者,我们需要理论,这样我们才能看到。在政治心理学中,有一个术语叫做“酒鬼的搜索”,我认为这个术语被滥用了。这个故事认为,一个丢了钥匙的醉汉在明亮的灯光下寻找,即使他把钥匙丢在了其他地方,因为他看不到他到底把钥匙丢在了哪里。我不认为一个人需要成为一个酒鬼来承受这种痛苦,或者,事实上,如果这是愚蠢的。就像诺维格引用的利奥·布雷曼的观点一样,我们基于我们所能看到和理解的东西开发了一个世界如何运作的模型,不一定是因为这个模型是真实的,或者,再次借用诺维格的例子,我们不是去火星——我们是去天文学家指定的火星“模型”。如果我们没有一组可靠的数据来构建这个模型,我们需要根据我们认为我们对宇宙的了解来推测,以便构建这个模型。这就是理论的用武之地。我认为,当我们处理大量不同的数据时,不同的理论有不同的位置来更好地适应不同的数据。

前瞻性法医数据科学——有可能预测犯罪并预防犯罪吗?

原文:https://towardsdatascience.com/prospective-forensic-data-science-is-it-possible-to-predict-a-crime-and-prevent-it-28b48ba19825?source=collection_archive---------8-----------------------

社交网络中的数字足迹已经成为寻找罪犯的信息来源。例如,在巴西,一些与种族主义有关的案件由于 FaceBook (FB)上的种族主义帖子而受到指使。例如,2015 年 10 月,非裔巴西电视和电影明星 Tais Araújo *因其肤色和发型而成为 facebook 上种族主义评论的受害者。结果,大约有 30 人根据他们的 FB 档案被调查,其中五人因为他们的职位被逮捕。与那些罪犯所想的相反,远程计算机提供的明显的匿名性是他们犯罪的证据。数字足迹的好用途!

此外,数字足迹已经被用来防止潜在的更有害的犯罪。在里约热内卢举办夏季奥运会之前,巴西联邦警察发现了一个据称与 ISIS 有关联的组织,该组织正计划对奥运设施进行恐怖袭击。该组织利用脸书和推特赞美 ISIS,庆祝世界各地的恐怖袭击。他们还使用 WhatsApp 和 Telegram 等即时通讯应用程序来交换信息和策划攻击。联邦警察切断了他们的通讯,暴露了他们的计划,这足以将他们的行为定性为犯罪。

此类犯罪引发了另一个问题:即时通讯服务提供商是否应该为了与当局合作而中断用户对话?1988 年《巴西宪法》(第 5 条第十二款)规定,通信保密不可侵犯,除非法官作为一项非常措施并在法律规定的情况下下令保密。当然,这种数字通信在巴西宪法颁布时并不存在,但最高法院将这种豁免权延伸到了这些新技术。2016 年 5 月发生了一件不寻常的案件,当时联邦警察正在调查毒品生产商和经销商。一名来自一个小镇的联邦法官下令 WhatsApp 的所有者 FaceBook 披露嫌疑人的信息。脸书拒绝这样做,声称他们没有这个信息了。由于拒绝,这位法官下令 WhatsApp 必须在巴西全境离线 72 小时。由于这款应用在巴西被广泛使用,包括用于商业,整个巴西都因为这一法令而变得疯狂。该判决仅执行了几个小时,因为该判决被更高一级法院推翻。

事实是,FaceBook 有权访问 WhatsApp 用户的对话内容。用户协议明确说明了。该内容用于向用户投放广告。问题是:如果当局要求,FaceBook 和其他即时通讯服务提供商应该存储他们的用户对话并披露吗?或者至少受到公正的对待?

然而,这段历史可以有另一个篇章。如果这些即时通讯服务可以访问用户的聊天内容,并通过文本分析了解他们,那么在一些可控和合法的情况下,当有强有力的证据表明他们的用户正在犯罪时,他们是否应该向当局发出警报?例如,算法可以被训练来识别婴儿色情图像。当一个人向另一个人发送这种图像时,他们应该被用来识别这种犯罪吗?**文本分析可用于理解关于女性奴役的对话。为了发现这种罪行而中断交流并可能暴露数百万人,这样做值得吗?此外,这些算法可以被训练来识别这种犯罪何时仍在计划中。当一个潜在的罪犯将要犯罪时,即时通讯提供商能警告政策吗?

未来的法医数据科学可以实现这种打击/预防犯罪的场景,这类似于汤姆·克鲁斯的电影少数派报告。但是,正如电影中一样,预测算法可能会出错或有偏差(有意或无意)。有了这个,一个无辜的生命可能就毁了。嗯……从这个可能的世界中,大量的伦理问题涌现出来。然而,这不是本文的主题,这些问题可以在其他时间出现。

*葡萄牙语参考文献

  • *发送这种图像的简单行为并不意味着犯罪。例如,心理学家可能会将这样的图像发送给另一个人,以帮助解决问题。

脸书波士顿环球报交通的原型分析

原文:https://towardsdatascience.com/proto-analysis-of-boston-globe-traffic-on-facebook-db66bcda3693?source=collection_archive---------7-----------------------

2013 年 7 月 18 日更新:在这篇文章中,你会发现大量关于统计和关键指标的解释。如果你已经熟悉它们,请参考由尼曼新闻实验室发布的一份整洁的摘要。上周,我在波士顿环球报做了一个简短的演讲,展示了我的初步分析,该分析考察了《波士顿环球报》的文章是如何通过其脸书版被感知的。通过我的分析,我希望回答两个问题。《波士顿环球报》员工在社交媒体平台上分享哪些类型的故事?反过来,不同类型的分享故事如何不同地影响脸书用户的阅读和分享?通过回答这两个问题,我旨在通过脸书提供的三个衡量标准,找出员工的意图与读者的兴趣在多大程度上保持一致,以及在意图和感知之间是否存在差距,这将标志着改进的空间。

  • 我研究了《波士顿环球报》脸书版两周内分享的 215 个故事。
  • 我发现了几个与注意力相关的属性:
  • 图像大小(无、缩略图、单列和双列)
  • 标题中有无“中断”标签
  • 共享时间(小时和工作日)
  • 编辑定义的新闻主题(商业、都市、体育等。)
  • 是否与波士顿马拉松爆炸案有关
  • 工作人员的努力与脸书用户的阅读和分享之间存在差距。

我通过页面管理员的内置功能脸书洞察将数据导出到电子表格文件,然后在开源统计工具 R 中进行分析。为了节省时间,我将数据集保持得相当小,特别是因为我手动清理了数据并标记了一些变量,因为自动化对它们来说是不可行的。我总共检查了今年 5 月 7 日至 21 日分享的 215 个故事。

我的分析完全依赖于三个指标脸书洞察特性:达成参与用户,以及谈论这个。根据脸书的说法, reach 被定义为“看过你帖子的唯一人数”;参与用户为“点击你的帖子的唯一人数”;将此描述为“从你的页面帖子中创建了一个故事的独特人数。当有人喜欢、评论或分享你的帖子时,故事就产生了;回答您发布的问题;或响应您的事件”。这些指标以各种方式作为独立访问者的绝对数量,反映了从被动阅读到主动分享的用户行为。

下一节讨论一些人可能不熟悉的统计细节。请点击此处直接跳转到调查结果和影响部分。
我在本次分析中使用的统计工具是负二项式回归,我想详细说明两个术语,回归和负二项式,以证明我选择的研究方法。回归是用来估计变量之间关系的统计过程。变量在分析中有不同的作用,有些被称为自变量,有些被称为因变量。因变量衡量我们期望增加或减少的属性,如预期寿命、幸福度和犯罪率。自变量衡量影响、预测因变量结果或与因变量结果相关的因素,如教育水平、血压、警察人数等。自变量和因变量决不是预先确定的,而是为各种研究问题自由分配的。例如,我们可以根据一个毕业生的教育水平来估计她的收入,或者根据她的收入来估计一个人获得硕士学位的可能性。

在我分析脸书数据的案例中,我选择了三个关键指标作为因变量,即到达参与用户谈论这个。自变量是可能影响这些结果的共享职位的不同方面。我包括的方面是新闻部分、图像大小、“突发”标签、出版时间和工作日。特别是,我创建了一个二元独立变量,将故事标记为与波士顿马拉松爆炸案相关或无关,因为这个话题一直是《环球时报》员工密切关注的话题。

我选择回归的原因是因为它允许单独评估每个自变量与因变量的关联。这对分析非常重要。例如,据报道,死于乳腺癌的黑人女性比白人女性多。那么我们是否可以假设,从生物学上讲,黑人女性面临着更高的患病风险?也许不是。如果我们将女性的职业、教育和收入纳入分析,我们会发现,如果处于相同的社会经济地位,黑人和白人女性在患乳腺癌方面没有显著差异。

再以分析新闻故事的研究为例,我们可能观察到故事 A 比故事 B 被更多的人阅读,我们能声称故事 A 比故事 B 更有趣吗?还是那句话,也许不是。我们可能会发现,故事 A 是在早上 8 点人们上班途中查看脸书的时候分享的,而故事 B 是在上午 11 点人们通常忙于工作的时候分享的。同样,故事 A 涵盖体育,故事 B 涵盖国际关系,而体育新闻通常比国际新闻更受欢迎。因此,为了控制新闻报道的各个方面,我需要运行回归来获得更可靠的结果。

关于哪种类型的回归最合适的问题,一个快速的回答是泊松回归,因为它处理计数数据,例如人们一周看多少次电视,美国一年发生多少次龙卷风,以及有多少人在收银台前等着你。因为我收集的数据违反了泊松回归的一个假设(均值和方差相等),所以我选择了一种替代方法,称为负二项式回归,因为这是处理我的数据所表达的过度分散的一个好选择。对于那些对这些和其他分析方法的描述感兴趣的人, UCLA 分享了很多关于统计分析的教程,包括负二项式回归。

负二项式回归生成的系数是对数比。为了使研究结果更容易理解,在下一节中,我用指数系数来表示比率。

这项研究受到了脸书关于媒体公司良好实践的报告的启发。脸书收集了使用脸书网页的新闻机构样本,并根据它们的各种实践得出结论。相比之下,我的研究只关注了波士顿环球报,我的发现并不总是与脸书给出的建议一致。
脸书发现,“包含‘突发事件’或‘突发新闻’的帖子比不包含‘突发新闻’的帖子的参与度高出 57%。”相比之下,我没有发现在吸引用户或传播病毒方面有什么显著的不同。我发现的唯一区别是 reach 显著增加了 60%。由此,我们可以推断,“打破”标签并没有抑制“参与用户”或谈论这一点,并增加了覆盖面。
就说明性图片而言,可以在脸书页面的帖子中观察到四种尺寸。它们是零图像或无图像、缩略图、单栏图像和双栏图像,但双栏图像在用户的新闻订阅源上看不到,只能在脸书页面上看到。出于研究目的,我保留了“双栏”作为图像大小。从下面的图表中,你可以看到图片大小是如何影响脸书用户的注意力的。比率是指数系数。

  • 很明显,用图像来说明一个故事比没有图像要好。
  • 缩略图看起来并不比没有图像有显著的不同。
  • 图片越大,分享的故事就越受欢迎。

关于波士顿马拉松爆炸案的报道在脸书吸引了更多的注意力。在三个关键指标中,达到参与用户和【T4 谈到这个,这些故事将指标提高了 31%、97%和 64%。然而,当我观察用户如何参与赞、评论和分享时,我意识到人们不一定“喜欢”与爆炸相关的故事。这并不奇怪,因为“喜欢”一个可怕的故事可能会给一些人造成认知冲突,因此他们不会对“喜欢”它感到舒服。关于评论和分享,轰炸相关的报道获得了 90%和 80%的增长。同样,这里的比率是指数系数。因为数据集只持续了两周,我不认为共享工作日的相关性是可靠的。然而,它足够大,可以比较一天中的 24 小时。下图显示了员工是如何分享这些故事的,以及脸书用户是如何看待这些故事的。从中,我们可以看出:

  • 更多的故事是在工作时间分享的。
  • 然而,从这三个指标来看,在工作时间内,性能并不是很好。
  • 交通似乎在美国东部时间上午 8 点左右和晚上 11 点—凌晨 2 点左右达到高峰。
  • 西海岸可能会导致午夜后的滞后。

我和《波士顿环球报》的乔尔·艾布拉姆斯讨论了为什么高峰出现在清晨和深夜。对于这种现象,我们想出了两种理论。首先,人们在工作前后更频繁地查看脸书,例如,在上下班途中或在床上。其次,相当不合作的是,新闻编辑室在那些“空闲”时间分享的故事更少,因为社交媒体编辑也不在工作。因此,这些时间可能会出现新职位短缺,因此对寻求关注者的竞争较少。在未来,我们可以尝试在清晨和深夜分享故事,看看我们是否有可能提高流量。《波士顿环球报》的工作人员预先确定了总共 12 个新闻部分:艺术、商业、思想、生活方式、杂志、都市、新闻、观点、幻灯片、专题、体育和升级。(升级帖子是邀请人们将其会员资格升级为订户的广告。)下图显示了员工在不同主题间分享的故事数量,以及不同主题如何与 reach、参与用户和讨论话题相关联。在员工的分享和读者的关注之间,事实上存在一些差距。

回归分析更精确地评估了不同的新闻栏目如何影响脸书的报道表现。艺术新闻作为基线,其他新闻部分与之进行比较。结果显示为比率(例如,20%意味着只有艺术新闻的五分之一好,300%意味着是艺术新闻的三倍好)。请注意,置信区间是回归估计的指数,这就是上区间大于下区间的原因。现在,我们可以根据新闻对性能的影响对其进行分类:

  • 按员工分摊金额排序,由高到低依次为:
  • 地铁,体育,新闻,生活方式,艺术,商业,意见,幻灯片/杂志/升级,想法和特别。
  • 按范围排序,最重要的是:
  • 观点、幻灯片、生活方式和业务
  • 按参与用户排序,排名靠前的是:
  • 观点、都市、生活方式和商业
  • 通过讨论这一点来排序,最重要的是:
  • 幻灯片、观点、体育和地铁。
  • 员工持股和读者看法之间的不一致,可能是调整的起点。

为了比较这两个维度(员工的帖子和读者的注意力),我把它们分散在一张图表上。在这个图表中,横轴代表员工分享了多少故事,纵轴代表脸书读者对这些故事的看法,即到达参与用户谈论这个。数据经过对数转换,这样数据点可以被压缩在一起,以获得更合理的视图。事实上,这里的单位并不重要,因为我们希望看到的是努力与结果的比率。或者效率。为了表明读者对工作人员努力的反应的效率,我粗略地将新闻主题分为高、中、低三个等级,并以黄色、灰色和白色为背景。看起来,给定相同数量的帖子,意见参与了更多的活动,照片幻灯片更容易传播。与此同时,我们可以看到分享的观点和照片幻灯片相当少。按版块发布的文章数量和它们捕获的流量之间存在差距,这可能是一个富有成效的分析点,用于未来文章共享选择的调整。具体来说,这项研究表明,如果有更多关于观点、照片幻灯片、商业和生活方式的帖子,会有更多的读者参与进来。

下面的图表显示了一个趋势:当故事接触到更多的读者时,更多的读者会参与到更多围绕故事的活动中,每个点代表一个共享的故事。这个趋势出现在到达参与用户谈论这个之间大致呈线性关系。与此同时,我们可以很容易地分辨出一些在趋势线下摇摆的圆圈,它们位于红色圆圈中。那么,为什么这些故事产生的活动较少呢?

病毒传播程度,或所谓的谈话率,有助于发现这些表现不佳的故事。该指标被计算为谈论该达成的比率。我将列出最少和最多的对话故事,并对内容中观察到的模式进行快速总结。

  1. 俄克拉荷马城雷霆队的明星凯文·杜兰特今天承诺为昨天毁灭性的 T2 龙卷风后的恢复工作捐赠 100 万美元。【http://b.globe.com/191OR6r
  2. 夏天住在波士顿公园(冬天住在富兰克林公园动物园)的天鹅罗密欧与朱丽叶,今天回到那里,标志着春天的季节真正到来了。见照片:http://b.globe.com/ZOid4O
  3. 阿诺德树木园的紫丁香盛开了。这张照片是昨天在植物园拍摄的,官方名称是丁香星期天。如果你有机会顺便来看看。环球员工照片/ Yoon S. Byun
  4. 向飞行员问好。它今天进行了首次运行,并计划于下周末正式亮相,这是大约 25 年来第一次提供从波士顿到科德角的服务。http://b.globe.com/13xiois 你会骑它吗?
  5. 马拉松爆炸案在一毫秒内切断了马克·富卡里勒的右腿(如图,和他的未婚妻珍·里根在一起)。它放过了左派,但也差不了多少。现在,他和他的家人正处于痛苦的等待中,看他的“好”腿能否保住。http://b.globe.com/11igVlA
  6. 在一场 EF-4 龙卷风袭击后,一名儿童被从俄克拉荷马州摩尔市广场塔小学的废墟中救出。风速高达每小时 200 英里的龙卷风,宽度达一英里,并留下大片破坏区域。http://b.globe.com/12pP8KY
  7. “这是波士顿体育史上最伟大的时刻之一,”《环球时报》的丹·沙乌格内西写道,布鲁因斯队激动人心地战胜了枫叶队。“然后奇迹出现了……布鲁因斯队得分了,得分了得分了。”http://b.globe.com/18H5GTZ
  8. 波士顿运动协会邀请所有未能到达完成 2013 年波士顿马拉松的参赛者参加明年的比赛。这影响了 5633 名跑步者。
  9. 在加时赛的 15:40 分,布拉德·马尔尚为布鲁因斯队攻入制胜一球。故事:http://b.globe.com/10vZlak(图片来源:美联社)
  10. 在得知她有 87%的机会患乳腺癌后,女演员安吉丽娜·朱莉接受了预防性的双乳房切除术。朱莉今天在纽约时报专栏上分享了她的故事:http://nyti.ms/18HZFX3环保局照片
  11. 基思·雷丁的惊悚片《几乎是蓝色的》在查尔斯镇工作剧院上映,与其说是蓝色,不如说是黑色的 http://goo.gl/PwlBT
  12. #辣椒肉菜饭的食谱http://goo.gl/PwlBT
  13. 新:马修吉尔伯特的 Buzzsaw 专栏。环球影评人马修·吉尔伯特(Matthew Gilbert)问道,作为最受崇拜的“发展受阻”,带着一季大小的“集转储”回归,给观众太多会让他们无话可说吗?http://b.globe.com/10a7Sg5
  14. 用这些时尚的母亲节礼物让妈妈感到更加特别。
  15. 菲尼克斯太阳队任命前波士顿凯尔特人队的 33 岁的瑞安·麦克多诺为他们的新总经理。
  16. 专辑评论:巴兹·鲁赫曼改编的电影《了不起的盖茨比》(The Great Gatsby)的配乐由 Jay-Z 策划,是对那个时代的梦幻再现,将 20 世纪 20 年代的爵士乐置于现代流行音乐和嘻哈音乐的背景下。奇怪的是,原声音乐缺少的是心。
  17. 创新的躁动和冒险的感觉是 Iron & Wine 最新专辑《幽灵上的幽灵》(Ghost on Ghost)的核心,萨姆·梁(Sam Beam)将于今晚在伯克利表演中心(Berklee Performance Center)举行一场演出来庆祝这张专辑。
  18. 书评:深受喜爱的《追风筝的人》的作者卡勒德·胡赛尼,带着《群山回响》回到了他的祖国阿富汗崎岖的土地上
  19. 乔恩·莱斯特在芝加哥的六局比赛中失六分,白袜队以 6 比 4 击败红袜队。
  20. 雅虎将以 11 亿美元收购 Tumblr。你认为这将有助于重振雅虎品牌吗?Tumblr 是一个好的投资吗?

以下是我对故事潜在对话模式的快速总结。

  • 漂亮和令人愉快的东西是最容易交流的,比如照片幻灯片。
  • 也是高度对话式的:有一个问题,但已经(或将会)有一个解决方案:
  • 在体育比赛中奇迹般获胜,打破了平局
  • 未能完成马拉松,但被邀请回来做这件事
  • 马拉松爆炸受害者,但得到了医疗护理
  • 自然灾害,但孩子们得救了
  • 癌症的机会,但干预使其最小化
  • 最不健谈的:
  • 艺术相关(音乐、电影、书籍等。)
  • 事实信息(体育比分、已达成的商业交易等。
  • 高参与度和低参与度与之前的研究一致,即更高的情绪反应会导致更频繁的表达。
  • 限制
  • 数据集相当小(n = 215)
  • 因此,更多的抽样误差和结果偏差
  • 也省略了考察分享的频率会如何影响读者的感知(分享的故事越多越好,或者反之亦然,或者无所谓?)
  • 未来的研究
  • 时间序列数据
  • 人口统计(性别、年龄范围、地点等。)
  • 设备(网络与移动、平台类型等。)

原载于 2013 年 7 月 14 日 sonya2song.blogspot.com。****

推荐系统原型

原文:https://towardsdatascience.com/prototyping-a-recommendation-system-8e4dd4a50675?source=collection_archive---------2-----------------------

R、Java、Scala 和 SQL 的 Hello World

Amazon.com recommendations for “Mahout in Action”

Twitch 有许多由推荐系统驱动的产品,包括 VOD 推荐、剪辑推荐和类似的频道。在将 Twitch 的一个推荐系统产品化之前,科学团队首先制作了一个推荐系统的原型,看看输出结果对我们的一个产品是否有用。建立推荐原型的成本可能很低,这篇文章提供了用四种不同的编程语言构建推荐系统的例子。

每个例子都使用不同的库来构建一个使用协同过滤的推荐系统原型。本文介绍了 Amazon.com 使用的协作过滤方法,而 Mahout in Action 则很好地概述了推荐系统中使用的不同算法和相似性度量。我还在 EverQuest Landmark 的市场上的 GDC 演讲中提供了推荐系统的概述。除了使用交替最小二乘法(ALS)的 Scala 示例之外,以下所有示例都使用了基于用户的协同过滤。

这些示例加载一个数据集,然后为 ID 为 101 的用户推荐五个商品。在这些例子中使用的合成数据集是用户购买游戏的集合,其中每一行包括用户 ID 和游戏 ID。所有示例的示例数据集和源代码可在 GitHub 上获得。

如果 R 是你选择的编程语言,那么 recommenderlab 软件包可以让你很容易地构建不同的推荐系统。该软件包在 CRAN 存储库中可用,可以使用标准的 install.packages 函数进行安装。加载后,该包提供了一个推荐器函数,它将数据矩阵和推荐方法作为输入。在这个脚本中,数据矩阵是从一个 CSV 文件中加载的,使用的方法是基于用户的协同过滤。然后使用预测函数为用户 101 检索五个项目。

install.packages("recommenderlab")
library(recommenderlab)matrix <- as(read.csv("Games.csv"),"realRatingMatrix")
model <-Recommender(matrix, method = "UBCF")
games <- predict(model, matrix["101",], n=5)
as(games, "list")

Java:Apache Mahout Mahout 是一个用 Java 实现的机器学习库,提供了多种协同过滤算法。Mahout 用一个 UserNeighborhood 类实现了基于用户的协作过滤,这个类指定了用户需要有多相似才能提供商品推荐的反馈。此示例使用 Tanimoto 相似性度量来查找用户之间的相似性,该度量计算共享游戏的数量(交集)与玩家拥有的游戏总数(联合)的比率。这个 CSV 文件被用作数据模型的输入,该数据模型然后被传递给推荐器对象。一旦推荐对象被实例化,就可以使用推荐方法为特定用户创建游戏推荐列表。

import org.apache.mahout.cf.taste.*;DataModel model = new FileDataModel(new File("Games.csv"));UserSimilarity similarity = newTanimotoCoefficientSimilarity(model);
UserNeighborhood neighborhood = new ThresholdUserNeighborhood(0.1, similarity, model);
UserBasedRecommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);List recommendations = recommender.recommend(101, 5);
System.out.println(recommendations);

Apache Spark 是构建推荐系统越来越流行的工具之一,它提供了一个名为 MLlib 的内置库,其中包括一组机器学习算法。该示例首先运行一个查询来检索 UserID、GameID 元组格式的游戏购买,然后将数据框转换为 ALS 模型可以使用的评级集合。本例中使用了隐式数据反馈,这就是为什么使用了 trainImplicit 方法而不是 train 方法。训练方法的输入参数是游戏评级、要使用的潜在特征的数量、为矩阵分解执行的迭代次数、用于正则化的λ参数以及指定如何测量隐式评级的 alpha 参数。一旦模型被训练好,就可以使用推荐产品方法为用户检索推荐的游戏列表。

import org.apache.spark.mllib.recommendation._val games = sqlContext.read.format("com.databricks.spark.csv").option("header", "false")  .option("inferSchema", "true")  .load("/Users/bgweber/spark/Games.csv")val ratings = games.rdd.map(row =>Rating(row.getInt(0), row.getInt(1), 1)
)val rank = 10
val model = ALS.trainImplicit(ratings, rank, 5, 0.01, 1)
val recommendations = model.recommendProducts(101, 5)
recommendations.foreach(println)

在将数据提取到运行 Spark 或 R 的机器上太慢或太贵的情况下,您可以使用 SQL 来构建一个推荐系统的原型。这种方法使用起来可能计算量很大,但是对于抽查一些结果是有用的。下面的例子使用 Spark SQL,因为我想让这个例子对于所提供的数据集是可重复的。代码的第一部分从 CSV 文件加载表,并将加载的数据框注册为临时表。示例的第二部分包括 SQL CTAs,它准备数据,然后为单个用户的游戏评分。内部查询通过查找重叠游戏的比率除以购买的游戏总数来计算用户之间的 Tanimoto 系数,外部查询返回每个检索到的游戏的总分数。

val games = sqlContext.read.format("com.databricks.spark.csv").option("header", "false")  .option("inferSchema", "true")  .load("/Users/bgweber/spark/Games.csv")games.registerTempTable("games")val result = sqlContext.sql("""
with users as (select _c0 as User_ID, sum(1) as NumGames from games group by 1 
)
, purchases as (select _c0 as User_ID, _c1 as Game_ID, NumGames from games gjoin users uon g._c0 = u.User_ID
)
select u.User_ID, v.Game_ID, sum(Tanimoto) as GameWeight
from ( select u.User_ID, v.User_ID as Other_User_ID,count(u.Game_ID)/(u.NumGames + v.NumGames - count(u.Game_ID)) as Tanimotofrom purchases uJoin purchases von u.Game_ID = v.Game_ID where u.User_ID = 101group by u.User_ID, v.User_ID, u.NumGames, v.NumGames
) u
Join purchases von Other_User_ID = v.User_ID
group by u.User_ID, v.Game_ID
order by GameWeight desc
""")result.show(5)

评估 这些脚本提供了如何为特定用户检索游戏建议的示例。评估推荐器质量的一种方法是使用定性方法,其中为一小组用户手动检查推荐器的输出。另一种方法是使用不同库中包含的内置评估指标。例如,recommenderlab 和 MLlib 提供了用于计算 ROC 曲线的函数,这些曲线可用于评估不同的系统配置。在评估推荐者时,将推荐系统的性能与其他手工制作的方法进行比较也是一种很好的做法,例如畅销书排行榜。

一步一步建立推荐系统原型第 1 部分:基于 KNN 项目的协同过滤

原文:https://towardsdatascience.com/prototyping-a-recommender-system-step-by-step-part-1-knn-item-based-collaborative-filtering-637969614ea?source=collection_archive---------1-----------------------

Movie Recommender Systems

第二部分推荐系统可以在这里找到

推荐系统

我们今天使用的大多数互联网产品都是由推荐系统驱动的。Youtube、网飞、亚马逊、Pinterest 和许多其他互联网产品都依靠推荐系统来过滤数百万内容,并向用户提供个性化推荐。推荐系统得到了充分的研究,并被证明为互联网企业及其消费者提供了巨大的价值。事实上,当我听到网飞在 2009 年向一个开发团队颁发 100 万美元奖金的消息时,我感到非常震惊,因为一种算法将公司推荐系统的准确率提高了 10%。

Netflix Prize Leader Board

尽管推荐系统是那些价值数十亿美元的生意的秘密来源,但推荐系统的原型可以是非常低的成本,并且不需要科学家团队。你其实可以为自己开发自己的个性化推荐器。只需要一些基本的机器学习技术和 Python 中的实现。在这篇文章中,我们将从头开始,并通过如何原型最小可行的电影推荐过程。

方法

推荐系统可以大致分为三类:基于内容的系统协同过滤系统混合系统(使用其他两种系统的组合)。

An Overview of Recommendation Systems

*基于内容的方法利用项目的一系列离散特征来推荐具有相似属性的附加项目。

协同过滤方法根据用户过去的行为(先前购买或选择的项目和/或对这些项目给出的数字评级)以及其他用户做出的类似决定来建立模型。该模型然后被用于预测用户可能感兴趣的项目(或项目的评级)。

混合方法结合了前两种方法。大多数企业可能在他们的产品推荐系统中使用混合方法。*

在这篇文章中,我们将从最常见的方法协同过滤开始,用一个简单的普通版本。在以后的文章中,我们将开发更先进和复杂的方法来进一步提高推荐器的性能和可伸缩性。

让我们建立一个电影推荐器

我喜欢看电影,所以我决定建立一个电影推荐器。看看我的推荐者对我的电影偏好有多了解,这将是一件很酷的事情。我们将回顾我们的电影数据集,ML 模型的选择,如何评估我们的推荐器,最后我将给出一些关于这种方法的优点和缺点。

数据

*有时候很难找到一个好的数据集来开始。不过,我还是鼓励你去发现有趣的数据集,建立自己的推荐器。我发现在这个 页面 上有一些不错的数据集。除了建立一个电影推荐器,建立一个食物或约会推荐器也很有趣。只是一个想法!

为了构建一个电影推荐器,我选择 MovieLens 数据集。它包含 58,098 部电影的 27,753,444 个评级和 1,108,997 个标签应用。这些数据是由 283,228 名用户在 1995 年 1 月 9 日至 2018 年 9 月 26 日之间创建的。等级从 1 到 5。

我们将只使用来自 MovieLens 数据集的两个文件:ratings.csvmovies.csv。分级数据提供了用户对电影的分级。每行有三个字段:['userId', 'movieId', 'rating']。每一行都可以看作是用户和电影之间交互的记录。电影数据为收视率数据中的每个'movieId'提供电影标题和类型。*

*import os
import pandas as pd# configure file path
data_path = os.path.join(os.environ['DATA_PATH'], 'MovieLens')
movies_filename = 'movies.csv'
ratings_filename = 'ratings.csv'# read data
df_movies = pd.read_csv(os.path.join(data_path, movies_filename),usecols=['movieId', 'title'],dtype={'movieId': 'int32', 'title': 'str'})df_ratings = pd.read_csv(os.path.join(data_path, ratings_filename),usecols=['userId', 'movieId', 'rating'],dtype={'userId': 'int32', 'movieId': 'int32', 'rating': 'float32'})*

让我们快速看一下这两个数据集:电影和收视率

数据过滤

在现实世界中,从电影评级等显式反馈中收集的数据可能非常稀少,数据点主要从非常受欢迎的项目(电影)和高度参与的用户中收集。大量鲜为人知的项目(电影)根本没有评级。我们来看一下电影收视率分布图。

Rating Frequency is a “long tail” distribution. Only a small fraction of the items are rated frequently. Such items are referred to as popular items. The vast majority of items are rated rarely.

如果我们放大或以对数标度绘制它,我们可以发现 58,098 部电影中只有大约 13,500 部获得了超过 100 个用户的评级,其余大部分都很少为人所知,很少或没有用户互动。这些稀疏的评级对于大多数用户来说不太可预测,并且对于喜欢晦涩电影的个人来说高度敏感,这使得模式非常嘈杂。

大多数模型基于用户评级模式进行推荐。为了消除噪声模式并避免由于大数据集导致的“内存错误”,我们将过滤我们的分级数据帧以仅显示流行电影。过滤后,我们在收视率数据中剩下 13,500 部电影,这对推荐模型来说足够了。

建模

协同过滤系统利用用户的动作推荐其他电影。通常,它们可以是基于用户的,也可以是基于项目的。基于项目的方法通常优于基于用户的方法。由于用户的动态特性,基于用户的方法通常更难扩展,而项目通常不会发生太大变化,并且基于项目的方法通常可以离线计算并提供服务,而无需不断地重新训练。**

为了实现基于项目的协同过滤,* KNN 是一个完美的模型,也是推荐系统开发的一个非常好的基线。但是什么是 KNN 呢? KNN 是一种非参数的、懒惰的学习方法。它使用一个数据库,其中的数据点被分成几个聚类,以便对新样本进行推断。***

KNN 不对底层数据分布做任何假设,但它依赖于* 特征相似度。当 KNN 对一部电影做出推断时,KNN 将计算目标电影与其数据库中所有其他电影之间的“距离”,然后对其距离进行排名,并返回前 K 部最近邻电影作为最相似的电影推荐。***

Illustration of how KNN makes classification about new sample

等等,但是我们如何把收视率的数据框架输入 KNN 模型呢?首先,我们需要将评级的数据框架转换成 KNN 模型可以使用的适当格式。我们希望数据在一个m x n数组中,其中m是电影数量,n是用户数量。为了重塑收视率的数据框架,我们将pivot将数据框架转换为宽格式,电影作为行,用户作为列。然后,我们将使用0 s 来填充缺失的观察值,因为我们将执行线性代数运算(计算向量之间的距离)。让我们称这个新的数据帧为“电影特写数据帧”。

我们的电影特征数据帧是一个极其稀疏的矩阵,形状为13,500 x 113,291。我们绝对不希望将大部分数据类型为float320数据全部提供给 KNN。为了更有效的计算和更少的内存占用,我们需要将数据帧的值转换成一个 scipy 稀疏矩阵

***from scipy.sparse import csr_matrix# pivot ratings into movie features
df_movie_features = df_ratings.pivot(index='movieId',columns='userId',values='rating'
).fillna(0)*# convert dataframe of movie features to scipy sparse matrix*
mat_movie_features = csr_matrix(df_movie_features.values)***

现在我们的训练数据有一个非常高的维度。如果在目标函数中使用“欧氏距离”,KNN 的性能将遭受 维数灾难欧几里德距离在高维空间中是没有帮助的,因为所有向量与搜索查询向量(目标电影的特征)几乎是等距的。相反,我们将使用余弦相似度进行最近邻搜索。还有另一种处理高维数据中最近邻搜索的流行方法, 位置敏感哈希 ,我们不会在本文中讨论。**

来做一些电影推荐吧

在我们对数据进行预处理并将收视率的数据帧转换成电影特征的稀疏矩阵之后,我们需要用适当的超参数来配置我们的 KNN 模型:

***from sklearn.neighbors import NearestNeighborsmodel_knn = NearestNeighbors(metric='cosine', algorithm='brute', n_neighbors=20, n_jobs=-1)***

最后可以给自己做一些电影推荐。让我们在 KNN 推荐器中实现一个make_recommendations方法。

snippet of our final step in KNN recommender’s implementation

这个片段演示了我们推荐器实现中的make_recommendations方法。请在我的 GitHub Repo 中找到推荐器应用的详细源代码。

如果你去我的源代码页面,你会看到我把一个 KNN 推荐系统放在一个脚本中,作为一个小的 python 应用程序。我将我的推荐器应用程序参数化,并暴露了两个选项,movie_nametop_n,供用户使用。现在想请我的推荐人推荐 10 部和《钢铁侠》最相似的电影。所以我们可以在 bash 荐里面运行下面的终端(linux/mac):(指令的命令可以在 这里找到 )

***python src/knn_recommender.py --movie_name "Iron Man" --top_n 10***

List of movie recommendations based on my favorite movie: “Iron Man”

万岁!!我们的推荐系统确实有效!!现在我们有自己的电影推荐人了。

一些想法

乍一看,我的推荐人似乎给我留下了深刻的印象。我喜欢它推荐的所有电影。但如果我们真的仔细想想,它们都是 2008 年与《钢铁侠》同期非常受欢迎的电影。很有可能当时看《钢铁侠》的人大概也看了一些推荐的电影。这份电影列表不仅在同一时代很受欢迎,而且有着非常相似的类型和主题。

***作为一个电影爱好者,我大概是在寻找没看过的电影或者不同题材的电影。推荐不同主题的电影允许用户探索不同的口味,并保持用户对推荐产品的兴趣。另一方面,缺乏多样性会让用户感到厌烦,对产品的参与度降低。

所以我们才有效地识别出中存在的两个缺点😗**

  1. 人气偏向:推荐者倾向于推荐人气商品
  2. 项目冷启动问题:推荐器无法推荐新的或不太为人所知的项目,因为项目没有或很少交互

回想一下电影评分频率分布图:

“Long Tail” Property in Rating Frequency Distribution

只有很小一部分电影有很多用户互动,而“长尾”电影则没有。在商业环境中,高频商品往往是相对有竞争力的商品,对商家来说利润很少。另一方面,频率较低的项目利润空间较大。

我们如何改进我们的电影推荐系统来解决以上两个缺点?我们将在下一篇文章中介绍一种更复杂的方法来改进电影推荐系统: 一步一步建立推荐系统原型第二部分:协同过滤中的交替最小二乘(ALS)矩阵分解

摘要

在这篇文章中,我们简要介绍了推荐系统中的三种方法:基于内容的、协同过滤的和混合的。我们在 KNN 学习了如何通过几个步骤来原型化基于项目的协同过滤!这篇博文的 Jupyter 笔记本版本可以在 这里 找到。如果你想玩我的源码*,可以在这里 找到[。

在我的下一篇文章中,我们将讨论推荐系统中更高级的主题,并利用 Spark 来构建一个可扩展的推荐系统。敬请期待!在那之前,尽情享受机器学习和推荐器吧!](https://github.com/KevinLiao159/MyDataSciencePortfolio/blob/master/movie_recommender/src/knn_recommender.py)***

喜欢你读的书吗?在我的 Github 查看更多数据科学/机器学习项目: 凯文的数据科学作品集

一步一步建立推荐系统的原型第二部分:协同过滤中的交替最小二乘矩阵分解

原文:https://towardsdatascience.com/prototyping-a-recommender-system-step-by-step-part-2-alternating-least-square-als-matrix-4a76c58714a1?source=collection_archive---------1-----------------------

Item Based Collaborative Filtering Movie Recommender

第一部分的推荐系统可以在这里找到

在上一篇文章中,我们讨论了很多如何构建我们自己的推荐系统,并且用 PandasScikit-learn 实现了一个 KNN 基于项目的协同过滤电影推荐器。KNN 推荐系统的源代码可以在我的 Github repo 中找到。

在本帖中,我们将讨论如何用更复杂的机器学习技术来改进我们的电影推荐系统:矩阵分解。在这篇文章的后面,我们将讨论为什么我们要在协同过滤中使用矩阵分解,什么是矩阵分解,它是如何在 Spark 中实现的。**

基于项目的协同过滤的缺点

Output of KNN Item Based Collaborative Filtering Recommender From Previous Post

上一篇 的最后一节,我们向模特询问了一些电影推荐。在我们评估了推荐的电影列表后,我们很快发现了 KNN 方法的两个明显的局限性。一是“人气偏差”,二是“物品冷启动问题”。如果底层的训练数据太大而不适合一台机器,就会有另一个限制,即“可伸缩性问题”

  • ****流行偏好:指系统推荐互动最多的电影,没有任何个性化
  • ****项目冷启动问题:指添加到目录中的电影没有互动或者互动很少,而推荐者依靠电影的互动来进行推荐
  • ****可扩展性问题:指当越来越多的用户和电影加入我们的数据库时,缺乏扩展到更大数据集的能力

以上三点对于协同过滤推荐系统来说都是非常典型的挑战。它们与用户-电影(或电影-用户)交互矩阵一起自然到达,其中每个条目记录用户i和电影j的交互。在现实世界中,绝大多数电影很少甚至根本没有得到用户的评价。我们看到的是一个极其稀疏的矩阵,99%以上的条目都缺少值。

Sparse Rating Data

有了这样的稀疏矩阵,有哪些 ML 算法可以训练出来,可靠的做出推断?为了找到问题的解决方案,我们正在有效地解决数据稀疏问题。

矩阵分解

在协同过滤中,矩阵分解是针对稀疏数据问题的最先进的解决方案,尽管它是从 Netflix 奖挑战赛 开始广为人知的。

Matrix Factorization of Movie Ratings Data

什么是矩阵分解?矩阵分解只是线性代数中矩阵的一系列数学运算。具体地说,矩阵分解是将矩阵分解成矩阵的乘积。在协同过滤的情况下,矩阵分解算法通过用户-项目交互矩阵分解为两个低维度矩形矩阵的乘积来工作。一个矩阵可以被视为用户矩阵,其中行代表用户,列是潜在因素。另一个矩阵是项目矩阵,其中行是潜在因素,列代表项目。

矩阵分解如何解决我们的问题?

  1. 模型学习将评级矩阵分解为用户和电影表示,这允许模型为用户预测更好的个性化电影评级
  2. 通过矩阵分解,不太出名的电影可以像受欢迎的电影一样具有丰富的潜在表示,这提高了推荐器推荐不太出名的电影的能力

在稀疏用户-项目交互矩阵中,用户u将给予项目i的预测评级被计算为:

where H is user matrix, W is item matrix

用户u对项目i的评分可以表示为用户潜在向量和项目潜在向量的点积。

注意,在上面的公式中,潜在因素的数量可以通过交叉验证来调整。潜在因素是用户-项目交互矩阵投影出的低维潜在空间中的特征。矩阵分解背后的思想是使用潜在因素在低得多的维度空间中表示用户偏好或电影主题。矩阵分解是机器学习中非常有效的降维技术之一。

Variance Explained By Components In PCA

很像 PCA成分的概念,潜在因素的数量决定了我们想要在一个低维空间中存储的抽象信息量。具有一个潜在因子的矩阵分解相当于最受欢迎的最受欢迎的推荐器(例如,推荐具有最多交互而没有任何个性化的项目)。增加潜在因素的数量将改善个性化,直到因素的数量变得太高,此时模型开始过度拟合。避免过度拟合的常见策略是将正则化项添加到目标函数中。

矩阵分解的目的是最小化真实评级和预测评级之间的误差:

where H is user matrix, W is item matrix

一旦我们有了目标函数,我们只需要一个训练例程(例如梯度下降)来完成一个矩阵分解算法的实现。这个实现实际上叫做 Funk SVD 。它是以西蒙·芬克的名字命名的,他在 2006 年网飞奖挑战中与研究界分享了他的发现。

Scaling Machine Learning Applications With Distributed Computing

尽管 Funk SVD 在那段时间对于单机的矩阵分解非常有效,但是随着今天数据量的增长,它不具有可伸缩性。对于兆兆字节甚至千兆字节的数据,不可能将如此大的数据加载到一台机器上。因此,我们需要一个机器学习模型(或框架),它可以在机器集群中传播的数据集上进行训练。

带 Spark ML 的交替最小二乘法(ALS)

交替最小二乘法(ALS)也是一种矩阵分解算法,它以并行方式运行。ALS 是在 Apache Spark ML 中实现的,是为大规模协同过滤问题而构建的。ALS 在解决收视率数据的可扩展性和稀疏性方面做得很好,它很简单,可以很好地扩展到非常大的数据集。

ALS 背后的一些高层次想法是:

  • 其目标函数与 Funk SVD 略有不同:ALS 使用 L2 正则化,而 Funk 使用 L1 正则化
  • 其训练套路不同:ALS 最小化两个损失函数交替;它首先固定用户矩阵,然后用项目矩阵进行梯度下降;然后,它保持项目矩阵固定,并与用户矩阵运行梯度下降
  • 它的可伸缩性:ALS 在来自一个机器集群的底层训练数据的多个分区上以并行运行它的梯度下降

Pseudocode For SGD In Matrix Factorization

如果你有兴趣了解更多关于 ALS 的知识,可以在本文中找到更多细节:Netflix 奖大规模并行协同过滤

就像其他机器学习算法一样,ALS 也有自己的一套超参数。我们可能想通过保持验证交叉验证来调整它的超参数。

交替最小二乘法(ALS)中最重要的超参数:

  • maxIter:要运行的最大迭代次数(默认为 10)
  • 等级:模型中潜在因素的数量(默认为 10)
  • reg param:ALS 中的正则化参数(默认为 1.0)

超参数调整是许多机器学习项目中高度重复的任务。我们可以将它编码到一个函数中,以加速调优迭代。

经过调优,我们找到了超参数的最佳选择:maxIter=10regParam=0.05rank=20

实施 ALS 推荐系统

现在我们知道我们有一个精彩的电影推荐模型,接下来的问题是:我们如何将我们的精彩模型产品化为推荐系统?机器学习模型产品化是另一个大话题,我不会详细谈论它。在这篇文章中,我将展示如何为 ALS 推荐者建立一个 MVP(最小可行产品)版本。

要将模型产品化,我们需要围绕模型建立工作流。典型的 ML 工作流程大致从通过一组预定义的 ETL 作业、离线/在线模型训练的数据准备开始,然后将训练好的模型吸收到 web 服务中用于生产。在我们的例子中,我们将构建一个非常简单的电影推荐器来完成这项工作。我们的工作流程如下:

  1. 新用户输入他/她喜欢的电影,然后系统为该模型创建新的用户-电影交互样本
  2. 系统根据新输入的数据重新训练 ALS 模型
  3. 系统创建用于推理的电影数据(在我的例子中,我从数据中抽取所有电影)
  4. 系统为用户对所有电影进行分级预测
  5. 系统基于电影分级预测的排名为该用户输出前 N 个电影推荐

下面是我们的 MVP 推荐系统的一小段源代码:

snippet of our final step in ALS recommender’s implementation

这个片段演示了我们推荐器实现中的make_recommendations方法。请在我的 GitHub Repo 中找到推荐器应用的详细源代码。

我们来做一些推荐吧

一旦我们在 python 脚本中将 ALS 推荐系统实现为一个小的 Pyspark 程序,我们就可以将我们的 spark 应用程序提交到具有客户端部署模式或集群部署模式的集群,并享受分布式计算的强大功能。

最后,我们完成了技术细节和实现。现在让我们向我们的推荐人要一些电影推荐。我将假装一个新用户,将我最喜欢的电影“钢铁侠”再次输入这个新的推荐系统。看看它给我推荐了哪些电影。希望它们不是我之前看过很多遍的热门电影列表。

出于演示的目的,我通过在终端中运行以下命令在本地提交我的 spark 应用程序:(命令的指令可以在这里找到)

**spark-submit --master local[4] --driver-memory 4g --executor-memory 8g src/als_recommender.py --movie_name "Iron Man" --top_n 10**

List of Movie Recommendations Based On My Favorite Movie: “Iron Man”

耶!!用 Spark 成功运行我们的电影推荐器。

这份新的电影推荐名单与之前的 KNN 推荐名单完全不同,非常有趣!!我从未看过这份新名单中的任何一部电影。我发现新的推荐者向我推荐不寻常的电影非常令人惊讶。对于其他用户来说,它们可能太不寻常了,这是有问题的。

进一步改进我们的电影推荐系统的一个想法是将这个新的电影推荐列表与 KNN 推荐器的先前列表混合。我们基本上实现了一个混合推荐系统,这个混合推荐系统可以向用户提供流行和不太了解的内容。

摘要

在这篇文章中,我们介绍了如何用矩阵分解来改进协同过滤推荐系统。我们了解到矩阵分解可以解决协同过滤中的“流行偏见”和“项目冷启动”问题。我们还利用 Spark ML 实现了使用交替最小二乘(ALS)** 的分布式推荐系统。这篇博文的 Jupyter 笔记本版本可以在这里 找到 。如果你想玩我的源码,可以在这里 找到。**

在我的下一篇文章中,我们将深入探讨矩阵分解技术。我们可以用 Keras 中的神经网络实现开发一个更一般化形式的矩阵分解模型。敬请期待!在那之前,尽情享受机器学习和推荐器吧!

喜欢你读的书吗?在我的 Github 查看更多数据科学/机器学习项目: 凯文的数据科学作品集

提供对增长可能性和潜在风险的洞察

原文:https://towardsdatascience.com/providing-insight-into-growth-possibilities-and-potential-risks-c7d801559efb?source=collection_archive---------3-----------------------

我喜欢大数据,因为迄今为止我仍在试图理解它的所有潜力。

大数据是非常大的数据集,可以通过计算分析来揭示模式、趋势和关联,尤其是与人类行为和互动相关的模式、趋势和关联。- 谷歌

这不是一篇关于大数据的文章。但是大数据对于这里的概念是必不可少的。预测分析及其给企业带来远见的潜力是关键。

预测分析是高级分析的一个分支,用于预测未知的未来事件。预测分析使用来自数据挖掘、统计、建模、机器学习和人工智能的许多技术来分析当前数据,以预测未来。- 谷歌

我的研究集中在保险行业。基于一些正在做的事情,以及这个行业可能需要一些变革的事实。

公平地说,保险业有点名气。是否与服务差、方法过时缺乏灵活性不合适的盖子有关。对于许多个人和企业来说,为未来风险做准备被排在“待办事项”清单的最后,这并不奇怪。

我们大多数人都没有意识到我们可能持有的对我们有益的所有潜在保险政策。除了强制保险- 汽车保险如果你有一辆车和健康保险。我们不关心其他形式的保险。

保险单是一份详细说明保险合同条款的文件。- 谷歌

投保人是以其名义持有保险单的个人或团体。

我以“需要一种工具来帮助保险公司预测他们的投保人需要和感兴趣的政策,而不是传统的人寿、健康、汽车和教育政策”为主题。

小型保险公司没有明确的方法来了解客户的需求。因此,没有办法为他们提供服务于大量人群的独特定制政策。然而,许多保险公司拥有丰富的客户历史数据。为什么不与承销商合作,利用这些数据来开发符合当今企业和个人需求的产品呢?

这种工具应该是一种方式,让公司首先了解投保人的新趋势、他们面临的风险因素和可能的后果。除了优化适合投保人的保单,

到目前为止,我的研究中的其他亮点包括一份报告,该报告强调全球预测分析市场将从 2015 年27.4 亿美元增长到 2020 年92 亿美元。预测期内**年复合增长率( CAGR )为 27.4%。该报告进一步指出,由于传统商业智能(BI)技术向高级分析技术的转变,预测分析市场正在快速增长。此外,结构化和非结构化数据激增。(又名大数据)******

在 it 的核心,分析是关于解决业务问题。因此,向企业提出问题才是关键。所以他们想出自己的答案,并提出新的问题来探索。这样,见解更加及时和有价值。

对分析的一个常见抨击是,它专注于过去的活动在报告中提供的见解不能帮助公司制定有效的竞争战略。预测分析旨在改变这种情况。通过使用统计算法和机器学习技术来预测未来结果的可能性。

预测分析也越来越主流。得益于 API(应用程序编程接口)、web 服务、预测模型标记语言(PMML)和其他开发工具和技术,这些工具和技术使公司更容易将其纳入业务分析程序。

目前,启动预测分析计划的成本可能相当高。好消息是,公司可以使用开源预测分析工具来保持低成本,同时探索预测分析的可能性。

以上想法只是沧海一粟。使用预测分析的技术解决方案的范围跨越到许多其他领域。如果您有兴趣继续这一对话或有可能有益的材料/资源,请在 LinkedIn 上找到或与我分享。

保险业面临的其他一些关键挑战:

  • 管理索赔和风险的成本上升。
  • 努力提高盈利能力。
  • 大多数财产、意外、健康和福利保险公司的承保和调查资源有限,无法分析、审查、评估和支付索赔。
  • 建立新业务、保持现有客户和满足客户满意度要求的竞争压力。
  • 政策价格总是显得武断和过高。
  • 比较不同保险公司的保险几乎是不可能的。
  • 当你得到你想要的东西时,很少有透明度。

归根结底,我们需要保险。我们需要它发展成更适合消费者的产品。所以可以少一些人讨厌保险,多一些人从中受益。仍然是可持续发展的生意。不要在这场竞赛中被排除在外,以获得做出明智的实时决策的能力和手段。

我们看到的未来是,企业从洞察走向可操作的远见。

刺猬索尼克 2 和 3 的近似策略优化(PPO)

原文:https://towardsdatascience.com/proximal-policy-optimization-ppo-with-sonic-the-hedgehog-2-and-3-c9c21dbed5e?source=collection_archive---------2-----------------------

我们推出了新的免费、更新、 从初学者到专家的深度强化学习课程,用拥抱面对🤗

👉新版教程:https://huggingface.co/deep-rl-course/unit0/introduction

下面的章节是以前的版本,新版本在这里👉https://huggingface.co/deep-rl-course/unit5/introduction?fw=pt

我们推出了新的免费、更新、 从初学者到专家的深度强化学习课程,带着拥抱脸🤗

👉新版教程:https://huggingface.co/deep-rl-course/unit0/introduction

下面的章节是以前的版本,新版本在这里👉https://huggingface.co/deep-rl-course/unit5/introduction?fw=pt

几周前,OpenAI 在深度强化学习方面取得了突破。他们用 OpenAI five 击败了一些世界上最好的 Dota2 玩家,open ai five 是一个由 5 名代理组成的团队。不幸的是,他们在第二次经历中失败了。

Dota2

这一突破之所以成为可能,得益于强大的硬件架构和使用最先进的算法:PPO 又名近似策略优化。

最近策略优化的中心思想是避免太大的策略更新。为了做到这一点,我们使用一个比率来告诉我们新旧政策之间的差异,并将该比率从 0.8 削减到 1.2。这样做将确保我们的政策更新不会太大。

此外,PPO 引入了另一项创新,即通过在小批量取样中运行 K 个梯度下降周期来训练药剂。如果你读过我关于 A2C 和刺猬索尼克的文章,我们已经实现了。

所以今天,我们将深入了解 PPO 架构,我们将实现一个近似策略优化(PPO)代理,它可以学习玩刺猬索尼克 1、2 和 3!

然而,如果你想能够理解 PPO,你需要首先掌握 A2C,如果不是这样,在这里阅读 A2C 教程。

政策梯度目标函数的问题

还记得我们学习政策梯度的时候,我们学习了政策目标函数或者你更喜欢政策损失。

这个想法是,通过对这个函数采取梯度上升步骤(这相当于对这个函数的负值采取梯度下降),我们将推动我们的代理人采取导致更高回报的行动,并避免不良行动。

然而,问题来自于步长:

  • 太小,训练过程太慢
  • 过高,训练中可变性太大。

When there is enormous variability in the training (Robot Icons made by Smashicons)

这就是 PPO 有用的地方,其思想是 PPO 通过限制每个训练步骤的策略更新来提高演员训练的稳定性。

为了能够做到这一点,PPO 引入了一个新的目标函数,称为“削波替代目标函数”,该函数将使用一个削波将政策变化限制在一个小范围内。

引入截取的替代目标函数

首先,正如本堆栈溢出答案中所解释的,我们可以使用当前策略下的操作概率除以先前策略下的操作概率,而不是使用 log pi 来跟踪操作的影响。

Taken from PPO paper

我们可以看到 rt(θ)表示新旧策略之间的概率比:

  • 如果 rt(θ) >1,则意味着动作在当前策略中比在旧策略中更有可能发生。
  • 如果 rt(θ)在 0 和 1 之间:这意味着当前政策采取行动的可能性小于旧政策。

因此,我们新的目标函数可以是:

Taken from PPO paper

然而,在没有约束的情况下,如果所采取的行动在我们当前的政策中比在我们以前的政策中更有可能,这将导致大的政策梯度步骤,并导致过度的政策更新。

因此,我们需要通过惩罚导致比率偏离 1 的变化来约束这个目标函数(在纸上比率只能从 0.8 变化到 1.2)。通过这样做,我们将确保不会有太大的政策更新,因为新政策不能与旧政策相差太大。

为此,我们有两种解决方案:

  • TRPO(信赖域策略优化)使用目标函数之外的 KL 散度约束来约束策略更新。但是这种方法实现起来非常复杂,并且需要更多的计算时间。
  • PPO 修剪概率比直接在目标函数与其修剪代理目标函数。

The Clipped Surrogate Objective function

对于截取的替代目标函数,我们有两个概率比,一个是非截取的,一个是在一个范围内截取的(在[1-𝜖,1+𝜖]之间),ε是一个超参数,它帮助我们定义这个截取范围(在论文中𝜖 = 0.2)。

然后,我们取削波和非削波目标的最小值,,因此最终目标是未削波目标的下界(悲观界)。

因此,我们有两种情况要考虑:

Taken from PPO paper

  • 情况 1:优势为> 0

如果ȃt > 0则表示动作优于该状态下所有动作的平均值。因此,我们应该鼓励我们的新政策,以增加在该州采取行动的可能性。

因此,这意味着增加 r(t),因为我们增加了新策略的概率(因为 At *新策略)和分母旧策略保持不变。

Taken from PPO paper

然而,由于修剪,rt(𝜽)只会增长到和 1+𝜖.一样多这意味着,与旧策略相比,这一行动的可能性不可能增加 100 倍(因为剪辑)。

为什么?,因为我们不想过多地更新我们的政策。原因很简单,记住在那种状态下采取行动只是一次尝试,这并不意味着它总是会带来超级积极的回报,所以我们不想太贪心,因为这会导致糟糕的政策。

→综上所述,在积极优势的情况下,我们希望增加在该步骤采取该行动的概率,但不要太多。

  • 情况 2:当优势ȃt 小于 0 时

如果ȃt< 0, the action should be discouraged because negative effect of the outcome. Consequently, rt will be decreased (因为当前政策比旧政策采取行动的可能性更小)而是因为剪辑的,rt 只会减少到和 1-𝜖.一样小

同样,我们不希望因为过于贪婪而对政策做出重大改变,完全降低采取行动的可能性,因为这会导致负面优势。

总而言之,由于这个被删减的替代目标,我们限制了新政策与旧政策的差异范围。因为我们去除了概率比移出区间的激励。因为,剪辑有渐变的效果。如果比率为> 1+e 或< 1-e,梯度将等于 0(无斜率)。

因此,我们看到,这两个裁剪区域防止我们过于贪婪,试图一次更新太多,并在该样本提供良好近似的区域之外进行更新。

最终剪切替代目标损失:

实现一个 A2C 风格的 PPO 代理,播放刺猬索尼克系列(索尼克 2 和 3)

所以现在,我们准备以 A2C 的方式实现一个 PPO 代理。A2C 风格意味着它遵循 A2C 文章中解释的相同过程。

同样,这个实现比本课程的之前的实现要复杂得多。我们开始实现最先进的算法,所以我们需要越来越高效地使用我们的代码。这就是为什么在这个实现中,我们将代码分离到不同的对象和文件中。

要实现一个 PPO 代理,你需要阅读下面的笔记本,它包含了一个完整的 PPO 过程的模式和每一部分解释的代码。

实现在这里的 GitHub repo 中。

仅此而已!您刚刚创建了一个学习播放刺猬索尼克 1、2 和 3 的代理。太棒了。你需要在 1 个 GPU 上进行大约 10 到 15 个小时的训练,才能拥有一个好的代理。

不要忘记自己实现代码的每一部分。尝试修改代码真的很重要。尝试修改超参数,使用另一个环境。尝试是最好的学习方式,所以尽情享受吧!

花点时间考虑一下你在本课程第一章****:之后取得的所有成就,我们从简单的文本游戏(OpenAI taxi-v2)发展到复杂的游戏,例如使用越来越强大架构的《毁灭战士》和《刺猬索尼克》。这太棒了!

下一次,我们将研究深度强化学习中最令人兴奋的新策略之一:好奇心驱动的学习。****

如果你喜欢我的文章,请点击👏下面是你喜欢文章的次数,所以其他人会在媒体上看到它。别忘了跟着我!

如果你有任何想法,评论,问题,欢迎在下面评论或者发邮件给我:hello@simoninithomas.com,或者发推特给我 @ThomasSimonini 。

不断学习,保持牛逼!

深度强化学习课程:

我们正在用 Tensorflow 制作深度强化学习课程的视频版本📹这里我们重点关注 tensorflow 的实现部分这里。****

第一部分:强化学习简介

第 2 部分:用 Q-Learning 更深入地研究强化学习

第 3 部分:深度 Q 学习简介:让我们玩毁灭战士

第 3 部分+: 深度 Q 学习的改进:决斗双 DQN,优先体验重放,固定 Q 目标

第四部分:关于厄运和翻转的政策梯度的介绍

第五部分:优势演员介绍评论家方法:我们来玩刺猬索尼克吧!

第七部分:好奇心驱动的学习变得简单第一部分

心理学——可能改变总统选举的数学

原文:https://towardsdatascience.com/psychographics-the-math-that-may-have-turned-a-presidential-election-d4b24363b2a3?source=collection_archive---------10-----------------------

除非你一直躲在岩石下或社交媒体自由区,否则你一定听说过脸书/剑桥分析公司的丑闻。如果指控属实,那么剑桥分析公司所做的事情的合法性(或者说非法性)是毋庸置疑的;他们使用的数据是非法获得的(未经适当同意)。然而,这一事件也引起了人们对他们用来将数据转化为可操作见解的实际算法技术的强烈关注。心理剖析的神秘艺术和微妙科学。

“貌相”这个词会立刻让我们大多数人产生负面情绪。我们都听说过基于种族、性别或年龄的貌相。没有人喜欢因为我们无法控制的特征而被放在一个盒子里。但是,我们不能把貌相和刻板印象混为一谈。种族或性别貌相是刻板印象的例子。侧写是根据对个人的了解来预测一个人的选择和行动的行为。刻板印象是一种狭隘的、完全不科学的形象化形式;这是一种基于无根据的概括对个人形成看法的行为,这种概括主要源于偏见和无知。刻板印象和剖析之间的关系类似于智能设计和物种起源研究之间的关系。这两者都是很大程度上不可信的方法论,用来支持一个人未经证实的信念,它们给整个领域带来了坏名声。

任何科学方法的基础都是从证据中学习。至少一个世纪以来,心理学家一直试图通过分析模型来捕捉人类行为。然而,这些模型的成功和可靠性是相当有限的,尤其是与它们在物理科学中的同行相比。这主要是因为人类远比原子或分子复杂。任何有用的人类行为模型都必须能够将个人的可观察特征与他/她的选择联系起来。然而,可能的特征和选择的空间即使不是无限的,也是非常大的。我们现在知道,人们需要复杂的算法来确定哪些选择是可预测的,哪些特征是重要的预测因素。这些算法的复杂性的一个直接后果是,它们需要大量的数据和计算能力来工作。

人类行为定量理论所需的数据和计算能力直到大约十年或二十年前才出现。心理学家和市场商人一直试图在调查的基础上理解行为。然而,调查作为数据收集机制从根本上说是有限的。他们受到自我选择偏差(即,你只从那些选择回答调查的人那里获得数据)、调查设计偏差(即,你只问那些你根据你的偏差或模型认为重要的问题)和数据稀缺(在前互联网时代,你可以通过调查接触的人数有严重的限制)。因此,这种分析得出的结果根本不足以被称为定量科学。像往常一样,当科学还没有到来时,生活还在继续。一些人(主要是营销人员)试图使用人口统计学参数,如年龄、性别、种族、地点等。,混合了一些描述性统计数据和直觉的魔力酱,对人类行为做出过于简单的概括。这被称为人口统计细分。其他人只是用偏见取代统计数据,并诉诸刻板印象。

随着新世纪的到来,一切都变了。我们将计算转移到了云端,这使得越来越多的人能够训练和验证越来越复杂的算法。然后,社交媒体网络出现了。脸书、推特、Instagram 和它们的表亲是名副其实的人类行为实验室。社交媒体网络摆脱了传统调查所面临的问题。另一方面,他们的问题是数据爆炸。表面上看,脸书或推特上的大部分数据都是琐碎的,可能看起来像噪音。脸书上的赞真的能说出你性格中的有趣之处吗?它们能用来预测你未来的选择吗?在一系列的论文中,Michal Kosinski 和他的合作者发现答案是肯定的。在一篇里程碑式的论文中,他们令人信服地证明了脸书的“喜欢”可以用来辨别个人的性格特征。在接下来的一篇论文中,他们展示了给定足够的数据,计算机算法在这方面比人类更好,包括亲密的家人和朋友。最后,在另一个重要的后续研究中,他们表明这些性格特征可以用来预测一个人可能做出的选择。

这些研究人员的主要贡献不是革命性的新算法。这也不是第一次证明一个领域中过去的行为可以用来预测同一领域中未来的行为;亚马逊和网飞等公司已经在各自的领域展示了这一点。科辛斯基及其合作者展示的是,由看似微不足道的互动(如脸书的“喜欢”)组成的大量数字足迹的总和可以用来预测未来的选择,从而影响完全不相关领域的未来行动。这是一个令人难以置信的强大的认识。

《剑桥分析》利用这些见解来影响选举。但是他们不是第一个使用心理测量学的人,也不会是最后一个。事实上,在科辛斯基的研究之前,心理测量学的潜力在很多方面都是显而易见的。在 T2,有很多公司和机构正在以完全合法的方式使用某种形式的心理图形。例如,经济合作与发展组织正在进行一项研究,研究各种个人和环境因素对不同城市学生社交和情感技能的影响。目标是为政策制定者提供设计更好的政策工具的见解,以便在学生中促进这些社会情感技能。这项研究将使用人格特质的五因素模型;剑桥分析公司用来建模的模型。经济合作与发展组织的研究是一个明显的例子,表明心理学可以用于明确的好处。

自从认知诞生以来,侧写就一直存在。任何时候你和一个人互动,或者可能和一个有知觉的生物互动,你都会被侧写。大多数或者几乎所有这样的剖析都是基于不完整的信息和“有缺陷的”算法。人们经常因为肤色在机场被骚扰,或者因为姓氏被列入禁飞名单。在这种情况下,很难认为无偏见的数据驱动算法不会提供更好的替代方案。

很大一部分关于心理图形的歇斯底里源于缺乏关于心理图形是什么以及它能做什么的知识。我们每个人都愿意相信自己是独一无二的。在很多方面我们都是。但是,在许多其他方面,我们是可以预测的。心理学不是魔术,它是数学。它只能学习可以学习的东西,只能预测可以预测的东西。使一个人独一无二的东西将永远隐藏在心理分析之外。甚至当涉及到可以被认为是可预测的影响时,它也只能对大型群体做出预计在大部分时间内成立的统计预测。换句话说,给定足够多的数据和足够强大的算法,对于你个性的可预测方面,心理测量学可能在大多数时候都是正确的,但不是所有时候。

区分数据收集的合法性和我们处理数据的道德性是非常重要的。围绕剑桥分析丑闻的问题首先与数据是如何获得的有关。这些问题最容易回答。几乎任何理智的人都会同意,应该有关于收集个人数据的合理法律。更难回答的是,这些数据的合法用途是什么,即使这些数据是在尽可能广泛的同意下收集的。

概括地说,心理测量学可以以两种不同(但相关)的方式使用。第一个是理解并提供大规模的人类行为的见解。经合组织的研究就是这种用法的一个例子。第二是微观目标和说服。这种用法在营销中最有效。它在选举政治中的效力充其量可能是微不足道的。在这两种情况下,人们可以认为心理测量学中使用的(数学)方法比现状更符合伦理(更公正)。因此,在目前的状态下,除了数据隐私之外,很少有关于心理测量学的伦理问题;数据隐私并不是心理学独有的问题。

然而,我们关心的是未来。心理测量学,当与认知科学相结合时,有可能通过说服塑造人类行为。人们可以设想将这种技术用于善的方面,例如增强我们的良性方面,如利他主义或帮助有抑郁症症状的个人,或者用于恶的方面,例如利用仇外心理或与病理成瘾相关的特征。这种未来心理学的伦理有点类似于基因编辑的伦理。就像基因编辑、原子能或互联网一样,心理学的这种未来科学将不会受到道德判断的影响。但它的用途不会。我们作为当代的居民,有责任放眼我们集体的道德景观,并确定这一未来的界限。

社交媒体分享心理学:关注、情绪和反应

原文:https://towardsdatascience.com/psychology-of-sharing-on-social-media-attention-emotion-and-reaction-707f164e4136?source=collection_archive---------6-----------------------

我很高兴看到我的 《波士顿环球报》/脸书的研究受到好奇的读者的欢迎,并被几个组织特别报道,如哈佛尼曼新闻实验室、 Chartbeat 、社会新鲜和 ISHP 咨询。与此同时,我一直在不同的地方就这项研究发表演讲,包括波士顿环球报、伦敦 Mozilla Festival、汉堡 Spiegel Online 和 Hacks/Hackers Berlin。如果你觉得这项研究很有趣,并想进一步讨论,请在 Twitter 上给我打电话 @sonya2song 或给我发邮件 sonya2song#gmail。也请随意下载为我的演讲开发的幻灯片(最后更新于 2013 年 12 月 9 日)。

在之前的研究中,我展示了数据分析,研究用户如何阅读和分享《波士顿环球报》在脸书页面上的帖子。在这个扩展分析中,我加入了定性分析,重点是内容、认知和情感。我的目标是帮助新闻编辑室更好地在社交媒体上推广他们的故事,并吸引更多的关注。

为了实现这个目标,我一直在挖掘心理学文献寻找灵感。欣喜之余,我发现了一些适用于社交媒体环境的理论和发现:

  • 快速和慢速两种思维模式会吸引不同类型的注意力。
  • 在社交媒体上分享是
  • 充满感情,
  • 受自我形象管理的约束,也
  • 担心与他人的关系。

同样,这份报告是基于脸书洞察的三个关键指标:触达、参与用户和谈论这个。根据脸书的说法, reach 被定义为“看过你帖子的独特人数”;参与用户为“点击过你帖子的唯一人数”;将此描述为“从你的页面帖子中创造故事的独特人数。当有人喜欢、评论或分享你的帖子时,故事就产生了;回答您发布的问题;或响应您的事件”。这些指标以各种方式作为独立访问者的绝对数量,反映了从被动消费到主动互动的用户行为。

# # # # # # # # # # # # # # # # # # # # # #

在对脸书的波士顿环球报流量的原型分析中,我报告了关于图像大小和“突破”标签的发现。一般的模式是,与没有图像相比,用图像来说明帖子与更高的流量相关联,与缩略图相比,大图像也是如此。这个模式适用于脸书的三个关键指标(图 2)。此外,仅仅“打破”与更高的触及度相关,尽管与参与或谈论这一点无关(图 1)。事实上,不仅是突发新闻,其他大写单词也与更高的触及范围相关联,包括天气监视、重大更新、大图、NOW LIVE 等。作为一名努力工作的记者,你可能会告诉我,读者被这种肤浅的东西吸引,比如大照片和突发新闻,这令人不安。但对你来说好消息是,原始伎俩引发的关注是相当廉价的。为了获得更多的关注,复杂的信息会是一个更好的选择,我们将在认知紧张和系统 2 一节中讨论。

Figure 1: “Breaking” is associated with higher “reach”

Figure 2: Larger images are associated with higher traffic

作为一个不太正面的例子, 麻省理工科技评论 可能会告诉我们如何获得很少的关注。看它的脸书页,我们可以看到很多大大的 T,肯定是杂志的 logo。很明显,故事是以链接的形式分享的,脸书会自动提取其徽标。因此,这些故事没有有趣或简单相关的视觉伴侣。重复的 T 也可能让粉丝们对这个符号视而不见。可悲的情况是,尽管这篇评论产生了许多激动人心的故事,但它在脸书的存在远非令人信服——你可能已经注意到了图 3 中的少量分享和喜欢。

Figure 3: Facebook Page of MIT Technology Review

# # # # # # # # # # # # # # # # # # # # # #

理解我们如何处理简单和复杂的刺激(如文本、图片、谜题等)。),(2011)思维,快与慢的 是一本好书。在本书中,卡尼曼考察了与人类两种思维模式相关的各种理论和发现:系统 1(快)和系统 2(慢)。

系统 1——无意识注意

系统 1 处理对生存至关重要的先天技能,它快速自动地工作。一个例子是,在我们意识到发生了什么之前,我们把手指从火中抽回。还有一个就是在空旷的高速公路上开车。系统 1 是完全无意识的,例如,当看到 1 + 1 = ____,我们会觉得必须去填空。换句话说,系统 1 不能关闭,因为它对我们的生存至关重要。当听到像爆炸这样的突然噪音时,我们会把头转向声源,想知道危险是否出现。除了天生的技能,通过长期练习获得的能力也可以由系统 1 处理,例如为国际象棋大师设想下一步,或者为计算机科学家设想 210 = 1024。

系统 2——有意识的注意力

相比之下,系统 2 处理习得的技能,如外语、逻辑推理、数学等。又慢又费力,就像我们计算 23 x 67 = ____ 时的感受。换句话说,它需要更多的关注,就像如果有人以前没有这样做过,就从左边开车。与系统 1 不同,系统 2 并不总是袖手旁观,这就是为什么我们容易受到营销和广告技术的影响。此外,当我们累了、饿了或心情不好时,可以停止使用系统 2。想象一下熬夜备考后参加考试有多艰难。

分工和最小努力定律

在系统 1 和系统 2 之间,劳动力被划分。大多数时候,我们处于系统 1 的快速模式。同时,系统 1 评估环境,并确定是否需要调用系统 2 进行额外的工作。当检测到困难、冲突和压力时,系统 2 将被调动并控制局面。系统 2 处理由系统 1 感知的信息,并在必要时纠正它。此外,系统 2 克服了系统 1 的冲击。例如,当争论升级时,我们必须努力抑制工作中的情绪。因此,系统 2 拥有最终决定权。

然而,懒惰是我们作为动物的天性,我们倾向于为未来意想不到的威胁保留能量。因为脑力劳动也消耗资源(例如葡萄糖),所以它的能力有限。因此,我们天生厌恶努力,让系统 1 领先。

现在考虑我们如何使用社交媒体:我们浏览帖子的速度相当快。虽然我们偶尔会在快速滚动或大或小的屏幕时陷入在线辩论,但我们通常会感到放松、宽慰,甚至高兴。换句话说,我们来到社交媒体是为了一段轻松的时光,而不是挑战。

认知易与系统 1

这种社交媒体上的轻松时光就是卡尼曼(2011)所说的“认知轻松”。他将认知放松描述为“事情进展顺利的迹象——没有威胁,没有重大新闻,不需要转移注意力或调动努力”(第 59 页)。换句话说,系统 1 在负责,系统 2 在打瞌睡。

Figure 4:Causes and consequences of cognitive ease

图 4:认知容易的原因和后果图 4 说明了认知容易的各种原因和后果。(也许你已经感觉到广告商一直在利用的认知理论:重复、清晰和快乐更有可能让你感觉更好,并说服你相信某些产品或服务值得你花钱)。就像清晰的显示一样,易读性影响我们解析一条信息的难易程度。

突发新闻和易读性

高度易读的文本将导致认知上的放松,并很好地纵容系统 1。看看下面卡尼曼给出的例子:

阿道夫·希特勒出生于 1892 年。

阿道夫·希特勒出生于 1887 年。实验表明,与第二种说法相比,更多的人会相信第一种说法是正确的——事实是希特勒出生于 1889 年。正如您所猜测的那样简单:第一条语句用粗体显示,更加易读。

如果我们将这一心理发现移植到社交媒体上,我们可能会意识到突发新闻也在扮演类似的角色,从而吸引更多的注意力,尽管几乎是无意识的。由于我们无法定制我们在社交媒体上发布的文本的大小、颜色或字体,使用大写字母是我们改变帖子易读性水平的唯一选择。如果你不顾一切地想要克服社交媒体上的障碍,你可能会发现 lolcats 很鼓舞人心。

像大写文字一样,大图片也是抚慰系统 1 的养眼糖果,吸引社交媒体用户几乎无意识的注意。

简单的文本和可读性

迎合系统 1 的另一种方法是使文本简单且易于解析。可读性用来衡量这方面。已经建立了许多公式来测量可读性。

正如所料,每个词的平均音节数与所有三个指标负相关,即“触及”、“参与用户”和“谈论这个”。这对社交媒体编辑的启示是准备迎合快速阅读的信息,因为人们经常被社交媒体上的系统 1 所引导,即使各种媒体渠道的受众在不同的水平上说出可读的语言(查看图 8 中跨新闻编辑室的可读性水平)。据推测,一旦人们被带离脸书,他们就会从快节奏转为慢节奏。但在此之前,每个帖子都只有一瞬间来吸引人们的注意力。

在简单语言的主题上,奥威尔强调,不管文学用途如何,简单的词语增强了语言作为表达思想的工具。你可以用下面的例子来测试自己,看看你是否能顺利地将注意力从这个句子的第一个词移到最后一个词。

对当代现象的客观考虑迫使我们得出这样的结论:竞争活动中的成功或失败并不表现出与先天能力相称的趋势,而是必须始终考虑相当多的不可预测因素

政治和英语,乔治·奥威尔,1946

这一段实际上是奥威尔从《传道书》中“翻译”出来的,以表明文本可能会不必要的困难。原文如下:

“我又转念,见日光之下,跑得快的不一定能赛跑,强壮的不一定能争战,智慧的不一定能得食物,聪明的不一定能致富,有才能的不一定能得宠。但时间和机会发生在他们身上。”

为了让奥威尔的观点更加准确,根据弗莱斯奇-金凯德公式,原文得分为 18.5,而译文得分为 27.5,我将在认知压力和系统 2 一节中介绍这个公式。

启动效应和在社交媒体上提问

与系统 1 相关,心理学家发现了很多有趣的现象,比如启动效应。启动效应是一个总括性的概念,讨论人们在几乎无意识的影响下的行为。例如,让两组人完成 SO _ P;在这个任务之前,一组看吃的,另一组看洗的。吃组更有可能以汤和其他肥皂的形式完成。在这里,吃素汤,洗素皂。

另一个与无意识影响相关的实验是在纽卡斯特大学进行的(巴特森等人,2006 )。一个诚实的盒子被放在办公室里,用来收取茶和咖啡的费用。价目表上方依次展示了不同的海报。海报没有文字,但有两个主题,眼睛或花朵。结果(图 5)显示,在“有眼睛”的几周里,比“有花”的几周支付了更多的钱。这个实验很好地证明了“启动现象出现在系统 1 中,而你没有意识到它们”(Kahneman,2011 年,第 57 页)。

Figure 5: Eyes on you, Bateson et al., 2006

如果我们将这一概念应用于社交媒体,我们会发现什么?我从一个小任务开始探索证据。研究的问题是:在社交媒体上提出的问题能引导人们回答这些问题的行为吗?也就是说,一个问号会在一篇帖子上产生更多评论吗?

Figure 6: Asking questions is associated with more comments.

是的,在控制新闻部分、分享时间和其他因素后,问题与更多评论显著相关(注意:与喜欢或分享无关)。一般模式是,更多的接触与更多的参与相关,更多的参与与更多的喜欢、分享和评论相关(见图 10)。相比之下,有问题的帖子更有可能出现在趋势线上方,表明表现更好,尽管下方有一些异常值。根据两周内收集的样本,有问题的帖子会有 80%以上的评论。

同样,这个发现的概念是不要像突发新闻的诱惑一样过度使用它。虽然人们说没有所谓的愚蠢问题,但当你的问题不那么聪明时,你会很清楚。此外,“素数的影响很大,但不一定很大”(Kahneman,2011 年,第 56 页)。这表明内容本身仍然是流量的主要驱动力,而促销在一定程度上有所帮助。

在讨论各种启动效应和锚定效应这两种与快速思维模式(系统 1)相关的现象时,卡尼曼指出,尽管我们可以做出额外的努力来控制我们的系统 1,但无意识地受到影响是人类的本性。下面的引语应该可以缓解读者和记者对这些发现的道德担忧:

你的思想和行为可能会受到你根本没有注意到的刺激的影响,甚至是你完全没有意识到的刺激。启动研究的主要寓意是,我们的思想和行为受到当下环境的影响,比我们知道或想要的要多得多。许多人发现启动结果不可信,因为它们不符合主观经验。许多其他人发现结果令人不安,因为它们威胁到主观能动性和自主性……如果风险很高,你应该动员自己(你的系统 2)来对抗这种影响。(第 128 页)。

现在,你们这些辛勤工作的记者将会从这项研究中了解到一些令人鼓舞和兴奋的发现:你们复杂的信息应该得到更多的关注,不一定是更高的数量,但可能是更高的质量。

Figure 7: Causes and consequences of cognitive strain

与认知放松相反,认知紧张具有相反的原因和后果(图 7)。在系统 2 的指导下,人们变得更加警惕,犯的错误更少,但同时变得更没有创造力,感觉更加努力。

给定漂亮的流程图,在实践中,我们应该如何激活系统 2 并让人们的慢思维参与进来?这里有一个有趣的实验。有些棘手的问题人们经常会弄错。其中三个包含在 Shane Frederick 的认知反射测试中。这个测试非常棘手,即使是顶尖学校的学生也会给出错误的答案。然而,当用褪色的劣质印刷品进行测试时,错误率从 90%下降到 35% ( Alter 等人,2007 )。这个实验表明,认知紧张会调动第二系统,而第二系统会进行缓慢而仔细的思考。

复杂文本和更多评论

在社交媒体上,我们可以用什么样的认知压力来吸引读者?更复杂的文本可能是一种方法,例如包含更多单词的句子和包含更多音节的单词。

为了衡量脸书文本的复杂程度,我在研究中采用了 Flesch-Kincaid 等级水平。这个工具已经被调整以反映美国读者理解给定文本所需的教育年限。例如,一篇得分为 5.2 的文章可以被五年级以上的学生理解。F-K 水平建立在每个单词的平均音节数和每个句子的平均单词数的基础上,计算如下:

Flesch-Kincaid Grade Level =(每个单词 11.8 *音节)+(每个句子 0.39 *单词)-15.59 在脸书,各种媒体渠道以反映在它们自己的出版物中的风格呈现它们自己。图 8 中的可读性分数是根据七家媒体在脸书的最新 200 篇文章计算出来的。

Figure 8: The median score of Flesch-Kincaid. BuzzFeed: 4.83, Boston.com: 6.01, Boston Globe: 7.23, Washington Post: 7.37, CNN: 9.69, New Yorker: 12.91, The Economist: 14.62.

记者们的激动人心的消息来了。更复杂的文本与更多的评论相关(再次注意:与分享或喜欢无关)!不过,效果并不明显:K-F 水平多 12 分,评论就多 12%。在图 9 中,点的饱和度和大小表示文章的可读性分数。更大和更饱和的点更有可能落在趋势线之上,表明表现更好。

Figure 9: Harder text is associated with more comments

快速和慢速思维模式可能有助于解释这一证据。当文字看起来很难时,一些社交媒体用户会放弃,继续下一篇文章。那些决定阅读复杂帖子的人实际上是在进行缓慢的思考,缓慢的思考让他们更好地理解信息并形成观点。因此,就像糟糕的印刷与更好的答案相关一样,复杂的文本似乎与读者更多的评论相关。

除了心理学角度,其他因素也可能有助于解释这一证据。1)文本的整体复杂性可以暗示帖子的重要性,因此更复杂的文本可以吸引更多的查看和点击。以及 2)复杂的消息往往更长,并且更长的消息显示在更大的文本块中。因此,对于脸书用户来说,更复杂、更长的帖子需要花费更多的时间来解析,从而吸引更多的注意力。在我的统计分析中,这两个参数(消息的重要性和解析时间)没有被控制,所以不能排除它们的影响。

紧张+放松=交谈

三个脸书 KPI 之间的一般模式是,更多的接触与更多的参与相关联,更多的参与与更多的喜欢、分享和评论相关联(图 10)。这种趋势出现在 reach、参与用户和谈论这之间的大致线性关系中(经过对数转换)。同时,我们可以很容易地辨别趋势线上下的异常值。那么,为什么这些故事产生的活动较少呢?

Figure 10: Reach vs. Engagement vs. Talking about this (log-transformed)

为了量化这个问题,一些人开发了一个叫做对话率的指标。此指标计算为“谈论此事”与“达到”的比率。我将列出最少和最多的对话故事,并对内容中观察到的模式进行快速总结。让我们先来看看对话最多和最少的故事,并试图调查它们为什么会变成这样。

最会说话的故事

  1. 俄克拉荷马城雷霆队的明星凯文·杜兰特今天承诺为昨天毁灭性的 T2 龙卷风后的恢复工作捐赠 100 万美元。【http://b.globe.com/191OR6r
  2. 夏天住在波士顿公园(冬天住在富兰克林公园动物园)的天鹅罗密欧与朱丽叶,今天回到那里,标志着春天的季节真正到来了。见照片:http://b.globe.com/ZOid4O
  3. 阿诺德树木园的紫丁香盛开了。这张照片是昨天在植物园拍摄的,官方名称是丁香星期天。如果你有机会顺便来看看。环球员工照片/ Yoon S. Byun
  4. 向飞行员问好。它今天进行了首次运行,并计划于下周末正式亮相,这是大约 25 年来第一次从波斯顿到科德角的服务。http://b.globe.com/13xiois:你会骑它吗?
  5. 马拉松爆炸 在一毫秒内切断了马克·富卡里勒(如图,和他的未婚妻珍·雷根)的右腿。它放过了左派,但也差不了多少。现在,他和他的家人正处于痛苦的等待游戏中,看他的“好的”腿 能否保住。http://b.globe.com/11igVlA
  6. 在一场 EF-4 龙卷风袭击后,一名儿童被从俄克拉荷马州摩尔市广场塔小学的废墟中救出。风速高达每小时 200 英里的龙卷风,宽度达一英里,并留下大片破坏区域。http://b.globe.com/12pP8KY
  7. “这是波士顿体育史上最伟大的时刻之一,”《环球时报》的丹·沙乌格内西写道,布鲁因斯队激动人心地战胜了枫叶队。“然后奇迹出现了……布鲁因斯进球了,进球了,进球了”http://b.globe.com/18H5GTZ
  8. 波士顿运动协会邀请所有未能完成 2013 年波士顿马拉松的参赛者参加明年的比赛。这影响了 5633 名跑步者。
  9. 布拉德·马尔尚在加时赛的 15:40 分钟时,为布鲁因斯队攻入制胜一球。故事:【http://b.globe.com/10vZlak(图片来源:美联社)
  10. 在得知她有 87%的机会患乳腺癌后,女演员安吉丽娜·朱莉接受了预防性的双乳房切除术。朱莉今天在纽约时报专栏上分享了她的故事:http://nyti.ms/18HZFX3环保局照片

最少对话的故事

  1. 基思·雷丁的惊悚片《几乎是蓝色的》在查尔斯镇工作剧院上映,与其说是蓝色,不如说是 http://goo.gl/PwlBT 的黑色
  2. 海鲜饭辣椒的配方http://goo.gl/PwlBT

  3. 新:马修吉尔伯特的 Buzzsaw 专栏。环球影评人马修·吉尔伯特(Matthew Gilbert)问道,作为最受崇拜的“发展受阻”,带着一季大小的“集转储”回归,给观众太多会让他们无话可说吗?http://b.globe.com/10a7Sg5
  4. 用这些时尚的母亲节礼物让妈妈感到更加特别。
  5. 菲尼克斯太阳队任命前波士顿凯尔特人队的 33 岁的瑞安·麦克多诺为他们的新总经理。
  6. 专辑评论:巴兹·鲁赫曼改编的电影《了不起的盖茨比》(The Great Gatsby)的配乐由 Jay-Z 策划,是对那个时代的梦幻再现,将 20 世纪 20 年代的爵士乐置于现代流行音乐和嘻哈音乐的背景下。奇怪的是,原声音乐缺少的是心。
  7. 创新的躁动和冒险的感觉是 Iron & Wine 最新专辑《幽灵上的幽灵》(Ghost on Ghost)的核心,萨姆·梁(Sam Beam)将于今晚在伯克利表演中心(Berklee Performance Center)举行一场演出来庆祝这张专辑。
  8. 书评:深受喜爱的《追风筝的人》的作者卡勒德·胡赛尼,带着《群山回响》回到了他的祖国阿富汗崎岖的土地上
  9. 乔恩·莱斯特在芝加哥的六局比赛中失六分,白袜队以 6 比 4 击败红袜队。
  10. 雅虎将以 11 亿美元收购 Tumblr。你认为这将有助于重振雅虎品牌吗?Tumblr 是一个好的投资吗?

下面是我对故事对话潜力相关模式的快速总结。

  • 漂亮和令人愉快的东西是最容易交流的,比如照片幻灯片。
  • 也是高度对话式的:有一个问题,但已经(或将会)有一个解决方案:
  • 在体育比赛中奇迹般获胜,打破了平局
  • 未能完成马拉松,但被邀请回来做这件事
  • 马拉松爆炸受害者,但得到了医疗护理
  • 自然灾害,但孩子们得救了
  • 癌症的机会,但干预使其最小化
  • 两个城市分开了 25 年,但最近联系起来了
  • 最不健谈的:
  • 艺术相关(音乐、电影、书籍等。)
  • 事实信息(体育比分、已达成的商业交易等。

对话也可以通过快速和慢速思维框架来解释。两种美丽的照片(天鹅和紫丁香)可能会吸引系统 1,并有助于对话。相比之下,其他八个热门对话故事根本没有漂亮的照片。相反,他们首先提出一个问题(平局、龙卷风、癌症、断线等。)然后提供一个解决方案或者一个凯旋。这种模式我命名为张力释放,由一个转折点组合而成。由于转折点扰乱了信息的流动,它可能会减缓人们的思维,并使系统 2 发生反应。

Figure 11: How to attract System 1 and System 2 for higher traffic

综上所述,在社交媒体上吸引眼球的方式多种多样。漂亮的照片、简单的信息和大写的单词可能会吸引系统 1 的一些无意识的注意。为了吸引更多有意识的和有意义的注意,我们可以在信息中强调惊喜、复杂的语言和转折点。这两种方法都有助于在社交媒体上获得更多的关注和流量(见图 11)。有些人可能会说这些方法是骗人的。然而,我认为,判断取决于目标。如果我们的目标是真诚地接触更多的观众,增加新闻编辑室的公民影响力,那么这些技术的使用是合理和恰当的。在这里我想引用卡尼曼对此的看法:

所有这些都是很好的建议,但我们不应该忘乎所以。如果你的信息明显是无意义的,或者与你的听众知道是真实的事实相矛盾,那么高质量的纸张、明亮的颜色、押韵或简单的语言都不会有太大的帮助。做这些实验的心理学家并不认为人是愚蠢的或容易受骗的。 心理学家认为,我们生活中的大部分时间都是由系统 1 的印象引导的……——如何写一条有说服力的信息,丹尼尔·卡内曼(2011 年,第 64 页)

    • — * — * — * — * — * — * — * -

图 12:评论与分享(对数转换)
人们在脸书上有三种表达方式:喜欢、分享和评论。一般来说,喜欢超过分享和评论,因为这是人们可以承受的最便宜的表达方式,除了一些负面或有争议的信息(图 12),这些信息使“喜欢”与人们的认知相矛盾。这一发现并非脸书独有,其他网络媒体也是如此。在 YouTube 上,尽管有大量的观看,但竖起大拇指或向下只占总观看数的 0.22%,评论占更小的比例 0.16%的人会留下评论( Cha et al .,2007);在维基百科上,4.6%的访问与编辑有关;在 Flickr 上,20%的用户曾经上传过照片( Auchard,2007 )。当我问评论和分享哪个数字更大时,问题就变得棘手了。对此的最佳回答是:视情况而定。在图 12 中,线条标记了匹配注释的股份;上面有更多的分享,下面有更多的评论。这里有一对案例(图 13)。第一个帖子是滚石封面,以波士顿爆炸案嫌疑人为主角。它收集了大约 600 条评论和 100 条分享(你可能也注意到了,它只获得了 57 个赞,比分享和评论都少)。第二个例子是以英雄警察和受害者为主题的另类封面,吸引了约 100 条评论和 600 次分享。这两个帖子是关于同一个主题,但是它们引发的活动是不同的。

Figure 13: Contrast between comments and shares

为了回答为什么人们会通过分享或评论做出反应,让我们来看看更多的例子。它们是股票超过评论最多的极端例子,反之亦然。

  1. 你留在了芝加哥:黑鹰队今天投放了一整页的《波士顿环球报》广告,向布鲁因斯和波士顿人民表达感谢和赞扬。http://bo.st/14BGdHL
  2. 昨晚,旧金山市政厅被彩虹旗的颜色点亮,最高法院的裁决为同性婚姻在经历了长达五年的激烈法律斗争后在加州恢复扫清了道路。故事:http://bo.st/18inxlD环保局照片
  3. 这可能是我们见过的波士顿上空最好的烟火照片。《环球时报》摄影师马修·j·李摄我们希望每个人都有一个美好的 7 月 4 日!更多庆祝活动的照片:http://bo.st/18AIVmv
  4. 德文·文森特与我们分享了一张《T4》的另类滚石封面。
  5. 大卫·奥尔蒂斯在他的第一次击球中击出二垒安打,成为棒球史上安打次数最多的指定击球手,并在一局后击出两分全垒打,带领红袜队在周三晚上以 11 比 4 战胜西雅图水手队。http://bo.st/16t6Wpz
  6. “波士顿强”是第十届里维尔海滩沙雕节的中心主题,该节将持续到周日。
  7. 我们今年最喜欢的摄影作品之一:2013 年国家地理旅行者摄影比赛的获胜者。这里可以看到东方尖叫猫头鹰在做它们最擅长的事情。你最好有一双锐利的眼睛来发现这些小猛禽。
  8. 上个月出生在圣安东尼奥动物园的一只双头龟变得如此受欢迎,以至于它现在有了自己的脸书主页。你可以在这里找到《末路狂花》的剧情:http://on.fb.me/1e4rdWB
  9. 红袜队在从七月开始到八月结束的 15 局胜利后,又回到了第一的位置。在周四午夜过后 14 分钟结束的比赛中,斯蒂芬·德鲁最终以决定性的一击帮助波士顿以 5 比 4 战胜西雅图水手队。http://bo.st/169Fcrn
  10. 今晚在芬威公园,红袜队以 8 比 2 轻松击败水手队。http://bo.st/158PjQu
  11. 《滚石》杂志的最新封面刊登了一张马拉松爆炸案嫌犯焦卡尔·萨纳耶夫的照片。这样合适吗?http://bo.st/15lJKKX
  12. 非常悲伤的消息:宾夕法尼亚州西部两岁的洛根·史蒂文森在上周父母的婚礼上担任伴郎后,昨晚死在了母亲的怀里。
  13. 这条死去的鲨鱼今天早上被发现躺在楠塔基特的海狗酿酒酒吧前。
  14. Tedeschi 食品店和 CVS 都承诺不刊登封面上有马拉松爆炸案嫌疑人 Dzhohkar Tsarnaev 的《滚石》杂志。
  15. 一名英国研究人员声称,规律的性生活(T3)可能是看起来年轻 7 岁的秘密。
  16. 乔治·齐默尔曼判决之后,前奥巴马顾问范·琼斯在推特上发布了这张照片,照片上小马丁·路德·金穿着帽衫……你认为这张照片上 MLK 穿着帽衫合适吗?
  17. 南茜·克里根和棠雅·哈丁将会在二月份作为一部新纪录片的一部分回到聚光灯下,这部纪录片将会在奥运期间在 NBC 电视台播出。你会看吗?
  18. 据 TSN 报道,作为周四多方交易的一部分,布鲁因斯将把泰勒·塞金送到达拉斯来交换路易·埃里克森。这笔交易用塞金、里奇·佩维利和小联盟球员瑞安·巴顿来交换埃里克森、乔·莫罗、雷利·史密斯和马特·弗雷泽。http://bo.st/17Or9Jv
  19. 一名康涅狄格州八年级学生拼错了“危险”的正确答案问题,并为此丢了钱说他被骗了。你同意吗?
  20. 我们正处于热浪之中,所以让我们来谈谈冰淇淋吧。新英格兰最好的冰激凌店是哪家?请在评论中发表你最喜欢的。谢谢!

# # # # # # # # # # # # # # # # # # # # # #

审视以上 20 个帖子的一个角度是情绪。一些心理学家研究情绪与信息传播的关系( Rimé,1991;彼得斯,2009 年。当故事是关于其他人的插曲时,情绪会起到如下作用:

  • 人们与不同的观众分享充满不同情感的故事,比如家人和朋友,而不是陌生人。
  • 在不同类型的情绪中,有些比其他的更常见。在离线环境中,人们发现兴趣、快乐和厌恶更容易被分享。
  • 一种情感越强烈,一个故事就越有可能被分享。

一些学者已经将情绪研究应用到媒体领域。例如, Berger 和 Milkman (2012)研究了从《纽约时报》头版收集的 6956 篇文章和电子邮件分享的频率。他们发现,高唤醒情绪与更多的电子邮件分享有关,包括积极(敬畏和娱乐)和消极(焦虑和愤怒)情绪。此外,研究人员发现,当一个故事变得不那么情绪化时,读者可能会分享它。他们控制了其他因素,如头版位置,并讨论了情绪和信息传递之间的复杂关系。他们的发现与之前在离线环境下进行的研究一致。

请注意,这项研究是在 2008 年进行的,当时调查人员关注的是新媒体而不是社交媒体,以及通过电子邮件进行的窄播而不是通过社交媒体进行的广播。尽管如此,他们的发现对社交媒体仍有影响。从脸书上面的 20 个帖子中,我们还可以观察到一个与情绪有关的模式。快乐的(同性婚姻,红袜队的胜利)和有趣的(最佳烟火,双头乌龟)故事被分享的比评论的多。

社会关系维护

相比之下,悲伤的(死亡,损失)和可鄙的(各种嫌疑人,体育丑闻)故事被评论多于分享。看看脸书,我们认识到它是一个连接朋友和家人的场所。这一特点可能会导致分享和评论之间的分歧,因为评论将允许用户在半匿名的空间内参与,远离他们的朋友和家人。

也许还有其他原因可以解释为什么脸书的一些故事比其他故事更容易分享。脸书以积极的情感氛围(皮尤研究,2012 )和和谐的社会关系而闻名——猜猜为什么没有不喜欢按钮被引入脸书。

我们可以怀疑为什么我们更喜欢保持良好的社会关系有各种各样的动机。一些学者认为,良好的社会关系表明人际吸引和信任,有助于获得社会支持,并有助于传递对职业表现至关重要的信息和资源( Podolny 和 Baron,1997 )。另一些人则称之为互惠,假设人们给予,同时期望在以后得到回报。

尽管这些动机多种多样,但人们通常都是为了保持良好的社会关系。因此,这种行为也应该在脸书这个社交网络中心观察到,它的用户应该努力取悦他人,避免冒犯他人。这意味着,如果一个帖子警告恶劣天气,人们更有可能在社交关系中分享它(信息交换)。另一方面,如果一个政治或宗教故事肯定会让一些用户的父母、朋友或老板感到不安,他们会不愿意通过分享来羞辱他们。或者,如果它与社交圈的信仰一致(体育胜利、同性婚姻、正义感),分享是首选。

尽管如此,当一个故事读起来有争议和情绪化时,人们会产生一种冲动去表达他们的观点。在这些情况下,我们会注意到一个帖子下产生了很多评论,尽管它可能不会导致很多分享。

自我形象管理

除了维持与他人的关系,人们还倾向于改善和管理他们在社会生活中的存在。高夫曼 (1959)将日常生活比作戏剧表演;在这两种情况下,人们会认出一个特定的场景,并把自己呈现在一个已知的观众面前。不仅通过面对面的互动,人们还试图通过将自己与有形物体(如品牌商品)联系起来来建立理想的自我形象。正如汤普森和赫希曼指出的:“消费通过一个人的财产所传达的形象和风格来产生一个想要的自我”(1995 年,第 151 页)。

类似的现象在网上也观察到了。例如,个人网站所有者可能会遵循“我们就是我们发布的东西”的座右铭,因为他们可以通过随心所欲地展示品牌标志和产品来管理他们的在线自我形象,而不是财务拮据的现实生活( Schau & Gilly,2003 )。在约会网站上,人们变得相当谨慎,因为个人资料和照片往往是精心挑选的,如果不是完全误导的话。我们还听说,青少年痴迷于频繁改善他们的网上形象,并为此感到疲惫不堪。同样,我们怀疑脸书页面(品牌、名人、新闻媒体等。)也被用来塑造和提高人们在网上的形象,或者理想的自我形象。

在社交媒体上,“我分享所以我在”。脸书用户策划和分享的新闻故事不可避免地也传达了他们理想的自我形象。以 Wired 为例,它频繁“极客”粉丝。复杂的电路和图表往往是高度共享的,如下图截图所示。我相信连线拥有高科技受众,但这些“极客”故事仍然可以被非技术读者策划为装饰品。

再比如《纽约时报》的脸书页面,如下图截图所示。它的帖子既时髦又聪明(科学、健康、可爱的小贴士),被高度分享。

# # # # # # # # # # # # # # # # # # # # # #

在这篇文章中,我强调了我对社交媒体的研究,尤其是脸书如何看待《波士顿环球报》的帖子。这是我第一次分析后的后续研究,重点是实证证据。解释为什么观察到各种类型的阅读和分享行为是这项研究的目的。我采用的理论和得出的结论包括:

  • 人们不断地在快速和慢速思维模式之间切换。
  • 在社交媒体上,人们大多被快速模式所引导。
  • 为了迎合快速思维模式,我们应该更好地利用形象,保持语言简单。
  • 另一方面,不要犹豫地讲述复杂的故事,因为它们可能会让人们慢慢思考,从而获得更多的反馈。
  • 如果你想鼓励讨论,请提问。
  • 如果你想让一个故事变得有对话性,用一种紧张感和一种解脱感来表现一个转折点,因为转折点会吸引注意力。
  • 如果你想看到更多的分享,考虑在故事中注入情感;积极的(敬畏和娱乐)和消极的(愤怒和焦虑)情绪都可能起作用。
  • 除了情绪,聪明也有用,因为人们试图以一种理想的方式呈现自己。在科学、健康和时尚故事方面表现出一些好的品味,他们将有更好的机会被选中。
  • 如果你的故事没有被广泛分享,而是被狂热地评论,这可能是由其中的争议引起的,因为人们珍惜社会关系,避免通过分享令人不快的故事来扰乱家人、朋友和同事。

随着我的研究的发展,这一指导方针将会持续更长时间,但我绝不把它作为新闻编辑室应该严格采用的处方,因为 1)过度使用这些策略可能会让读者疲惫不堪,2)创造力最有效。我认为,这个列表的目的是作为一个营养事实标签,帮助新闻编辑室调查为什么有些帖子会出现,而另一些则不会,因为你包括或排除了一些成分。尽管如此,这完全取决于个体社交媒体编辑来制定他们的最佳策略,以推广已经发布的新闻故事。也就是说,在我看来,在社交媒体上分享新闻故事可能比新闻更与广告相关,因为这些故事已经作为最终产品完成了。接下来是一场注意力之战,以及说服读者分享的努力。

# # # # # # # # # # # # # # # # # # # # # #

我在分析中使用的统计工具是负二项式回归来控制新闻报道的各个方面。我控制的因素是新闻部分(由波士顿环球报定义)和一天中的共享时间以及一周中的一天。在分析这三个 KPI 时,我控制了另外两个。关于省略变量的更详细的解释,请查看我以前的博客文章“独立变量、因变量和负二项式回归”中关于实证的部分:对脸书的波士顿环球报流量的原型分析。

另一个值得注意的是,脸书最近重新定义了指标,所以未来的研究可能会显示不同的数字。尽管如此,潜在的理论应该仍然适用,因为我们人类对自己的行为相当执着。

作为 Knight-Mozilla OpenNews 的研究员,我一直得到《波士顿环球报》的持续支持,他们的支持使得这项研究得以进行。我非常感谢《环球时报》的工作人员与我分享数据,因为他们的好意帮助我和许多其他新闻编辑室了解人们如何在社交媒体上阅读和分享新闻。我希望这项研究有助于确保其在网络媒体世界的领先地位,不仅通过响应性设计,还通过社交媒体的战略使用。

与《波士顿环球报》合作是一种特权,这种特权是通过 OpenNews 提供的。我无法表达对丹·辛克和艾丽卡·欧文斯的感激之情,他们是伙伴计划背后的人,感谢他们的信任和支持。今年太棒了!

此外,我要感谢我在密歇根州立大学的导师史蒂夫·怀尔德曼,他一直支持我的研究。丹尼尔·卡内曼的思考,快与慢,史蒂夫推荐的那本书,在这项研究中给了我很多启发。我还要感谢安·克朗罗德教授和我在 MSU 的同学黄冠雄。他们在广告和营销方面的专业知识帮助我丰富了这项研究。

原载于 2013 年 11 月 14 日 sonya2song.blogspot.com

在 Excel 中提取股票数据并创建高效的前沿

原文:https://towardsdatascience.com/pulling-stock-data-and-creating-an-efficient-frontier-in-excel-181291aa7f04?source=collection_archive---------7-----------------------

我在之前的一篇文章中提到了如何从 Google Finance 获得(几乎)实时股票数据。然而,如果你开始从不同的市场提取数据,每日历史汇率将没有意义,因为不同的市场在不同的日子休市。这在试图弄清楚股票之间的相关性时会产生问题。解决这个问题的一个办法是拉每月的利率,因为每个月调整后的股票价格将是一个更好的相关性指标。

Python 有一个很棒的库,叫做 pandas_datareader ,它允许你将历史信息拉入 pandas 数据帧。唯一的缺点是,如果一个 API 被否决,你的代码会崩溃。因此,我选择使用雅虎财经的历史数据下载功能来创建这个教程。本文的目标是提取大量全球历史数据(超过 20 年的价值),然后使用现代投资组合理论(均值方差优化)创建一个有效的前沿。有效边界有助于根据给定的风险承受能力和预期回报来决定投资组合中的资产配置。

概观

投资组合优化的目标是获取给定风险容忍度下的年化预期回报。回报与权重组合(资产配置)相关联,以帮助决定投资策略。在这种分析中将使用的优化策略是现代投资组合理论(Markowitz,1952),通常称为均值方差优化(MVO),由 Harry Markowitz 于 1952 年提出。MVO 模型只考虑历史结果,因此仅限于此。它将无法考虑其他可能影响模型的因素,如“观点”或对未来市场预测的洞察力。一个更强大的模型,可以纳入未来的优化是布莱克-利特曼模型(布莱克&利特曼,1992 年),通过引入用户输入的具体意见,对市场回报的资产配置过程。

数据收集

在这篇文章中,我将通过一个 excel 工作簿来指导你,这样你就可以准确地理解发生了什么。如果你愿意,你可以在这里下载 excel 工作簿。

为了避免高昂的主动管理成本,我选择使用指数基金作为优化的精选资产。市场指数拥有最长的股票信息历史,不会有单个公司股票的风险。历史上,市场一直在增长,通过使用市场指数,预期回报将处于市场平均水平,这远远好于年复一年地试图跑赢市场。此外,指数有助于在地理位置和资产类型方面提供更大的风险敞口。选择以下指数进行优化(表 1)。

[Excel Workbook sheet: Names]

Table 1. Breakdown of assets chosen for optimization

由于投资者将是加拿大人,我着眼于三个不同地区的地理前景:加拿大、美国和国际。此外,根据资产类型,选择了股票、固定收益和商品的混合。

由于优化将着眼于未来 30 年以上,收集的数据越多越好。数据收集自 1996 年 7 月 1 日至 2018 年 3 月 1 日,涵盖约 22 年的数据。这是一种权衡,要么获取更多年的数据,要么排除固定收益基金,因为这些资产的可用数据有限。为了避免由于世界各地不同的市场关闭而导致数据收集日期不一致,收集了每月数据。这一时间框架涵盖了一些市场崩溃,包括 1997 年的亚洲金融危机(迈克尔和约翰,未注明日期),2000 年至 2002 年的互联网崩溃(贝蒂,市场崩溃:互联网崩溃(2000 年至 2002 年),以及 2007 年至 2009 年的房地产泡沫/信贷危机(贝蒂,市场崩溃:房地产泡沫和信贷危机(2007 年至 2009 年),未注明日期)。

调整后的月度收盘价来自雅虎财经(历史股票数据),通过应用过滤器从以下参数中提取:

  • 时间段:1996 年 7 月 1 日—2018 年 3 月 1 日
  • 显示:历史价格
  • 频率:每月

每项资产的数据以指数各自的货币形式收集,并输出到 csv 文件中。不需要货币转换,因为百分比回报是为退货计算的。

How to pull historical stock data from Yahoo Finance

优化过程

月度回报

[Excel Workbook sheet: Adjusted Closing]

调整后的收盘价取自每个指数,然后整理成表格。

[Excel Workbook sheet: Returns]

在那之后,月度回报以百分比的形式计算,即从当月的收盘价中减去上月的收盘价,然后除以上月的收盘价。

R i =(收盘价 i-收盘价 i-1) /收盘价 i-1

取所有回报的平均值,得到每项资产的平均月回报。然后将这些平均值乘以 12,得到年平均回报率。

协方差和标准差

[Excel Workbook sheet: Cov-STD-Cor]

通过将每个资产与所有其他相应的资产进行比较来创建协方差矩阵。该矩阵对于理解每项资产的风险及其与其他资产的关系至关重要。

每项资产的标准差是通过查看月度回报得出的。然后用它来计算相关矩阵。

该公式的上半部分是 excel 工作簿中的协方差矩阵,下半部分是 D 矩阵。将这两者相除,就得到了相关矩阵

相互关系

相关性对于理解两个资产有多相似很重要。相关性越高,它们就越有可能向同一方向移动。负相关意味着如果一种资产上升,另一种资产就会下降,反之亦然。

不出所料,资产与自身有 100%的相关性。此外,S&P500 (GSPC)与道琼斯工业股票交易所(DJI)的相关度为 95%。这很直观,因为两个指数之间有很多重叠。另一个有趣的发现是,美国国债与公司债券指数高度负相关。

效率限界

[Excel Workbook sheet: Efficient Frontier]

为了创建一个有效的边界,期望收益 E(R p)最大化,同时将标准差σ p 限制在特定值。每个资产 I 的权重是 w i。相关系数ρ ij 是资产 I 和 j 之间的相关性。

在我们做任何事情之前,重要的是要记住每年的预期收益和标准差。因为我们采用了月收盘价,所以将它们乘以 12,如工作表中单元格 A2 所示。

Excel 的求解器插件用于计算这些最大值。如果您尚未在中添加规划求解,请转到文件->选项->加载项->管理:Excel 加载项转到->单击规划求解加载项,然后选择确定。如果操作正确,现在应该可以在 excel 的数据窗格中看到规划求解选项。

每项资产的权重被限制为正值,以避免卖空,上限为 20%,以确保多样化。针对投资组合(STD_P)的标准差的多个不同迭代运行求解器,以获得有效边界的不同点。在大约 15 个场景之后,投资组合的预期收益(E(R_P))被绘制成相对于 STD_P 的图,从而得到你的有效边界。为了确保你得到一个好的边界,确保你最大化预期收益,但也最小化它。当然你只会关心最大预期收益,因为你为什么想要更少的钱?

正如预期的那样,回报率较高的投资组合全部是风险较高的股票,风险最小的投资组合在固定收益资产中的权重较大。

风险最小的最佳点是年预期收益率为 4.55%,投资组合由以下资产组成:

Optimal point with minimal risk is an annual Expected Return of 4.55%

引用的作品

贝蒂(未注明日期)。市场崩溃:房地产泡沫和信贷危机(2007-2009)。从 Investopedia 检索到:【https://www.investopedia.com/features/crashes/crashes9.asp

贝蒂(未注明日期)。市场崩盘:互联网崩盘(2000 年至 2002 年)。从 Investopedia 检索:https://www.investopedia.com/features/crashes/crashes8.asp

布莱克,f .和利特曼,R. (1992 年)。全球投资组合优化。财务分析期刊,28–43 页。

历史库存数据。(未注明)。检索 2017 年 03 月 16 日,来自雅虎财经:https://finance.yahoo.com/quote/%5EN225/history?周期 1=975646800 &周期 2=1521086400 &间隔=1mo &过滤器=历史&频率=1mo

马尔科维茨(1952 年)。投资组合选择。金融杂志,77–91。

免责声明— 本文内容仅供参考。这不是买卖任何证券或实施任何投资策略的建议。

迈克尔和约翰。亚洲金融危机。检索自美联储历史:https://www . federalreservehistory . org/essays/Asian _ financial _ crisis

原载于 2018 年 3 月 21 日https://www.shafquatarefeen.com

Pusha T vs. Drake:用数据备份他们的 diss 轨迹

原文:https://towardsdatascience.com/pusha-t-vs-drake-backing-up-their-diss-tracks-with-data-1083e6159c75?source=collection_archive---------12-----------------------

也许没有必要花太多时间来写一篇关于德雷克和普沙塔之间的争论的介绍,实际上网上没有一个地方没有报道过这个。如果你错过了;这两个说唱歌手多年前就开始争吵,在《出埃及记 23:1》和《一石二鸟》等歌曲中互相攻击。有了这种新的“红外线”轨道,Pusha T 似乎重新点燃了牛肉。

在过去一周左右的时间里,共发行了四首歌曲,其中两首由 Pusha T 发行,两首由 Drake 发行,不过据推测,Drake 发行的第二首歌曲是官方单曲,与这两位说唱歌手之间的恩怨无关。

在阅读了他们的歌词并理解了他们在 genius.com 的含义后,我认为对他们互相射击的镜头做一些数据检查会很有趣。

数据集

像往常一样,简要描述所有提取和收集的数据,以便进行实际分析;

  • 我们需要以前发行的专辑中所有单曲的歌词。通过 Genius 的 API,我能够从 Drake 和 Pusha T 的最后 7 张专辑中提取所有歌词。
  • 我想了解他们的音乐听起来怎么样。我们可以通过 Spotify 的 API 获得这些信息,并使用他们的音频功能端点。
  • 由于有人向所谓的代笔人、开枪,我也想知道这两位艺术家发行的歌曲的所有相关贡献者。这一信息是通过 genius.com 收集的。

做愤怒检查

普莎 T 在他的音乐中提到德雷克生气的地方有两行。第一个是指德雷克的音乐在过去几年里一直很愤怒。第二个出现在 Pusha T 的《T4》的结尾,讲述了 Adidon 的故事,他提到了德雷克的新单曲,他很沮丧。

好,进入愤怒检查!我们可以通过 Spotify 的音频功能进行一些调查。他们的衡量标准之一被称为“效价”分数,从 0(悲伤/愤怒)到 1(快乐)不等。

下图显示了这两位艺术家多年来的平均价态度量。计算出每张专辑和发行年份的平均值,未收录到专辑中的单曲不包括在此图表中。

德雷克的平均化合价为 0.35 分。他的专辑的浏览量在这一指标上得分最低,效价得分为 0.27。然而,在他的最新发行的专辑中,德雷克提升了他的情绪,拥有比《更多生命》之前的 4 张专辑更高的评分。我很想知道我们会在他即将发行的专辑中得到什么分数。

Drake’s valence scores throughout the years (album average)

如果我们看一下 Pusha T 的化合价分数,我们会看到的平均值为 0.44 。然而,他的最新版本 DAYTONA 显示了他迄今为止最低的化合价得分,比他的平均得分低 0.14。

Pusha T’s valence scores throughout the years (album average)

很有可能这种特殊的体裁平均来说在化合价上得分很低。为了对这些化合价分数有一个准确的印象,最好将这些分数与其他大型嘻哈歌手的分数进行比较。因此,我提取了 Spotify 最大的 Hip Hop 播放列表 RapCaviar 的化合价分数,因为这个播放列表展示了这个流派中最大的艺术家。结果发现,纳入播放列表的所有曲目的平均效价分数为 0.44 ,略高于两位说唱歌手最新发布的平均效价分数。

推广援助和职业复兴

在德雷克的“Duppy free style”中的一句台词上,他估计普沙·T 的专辑《DAYTONA》将获得的额外关注将导致额外的 20,000 张销量。他还提到,Pusha T 的标签 G.O.O.D. Music 可以期待发票。德雷克接着在他的 Instagram 上发布了这张发票。

在谷歌了一下T21 之后,我设法计算出相当于 1 张专辑销量的流量是 1500 次流量。这意味着德雷克声称将为普沙·T 的新专辑《代托纳》带来额外的 3000 万个视频流。Pusha T 之前的专辑在 Spotify 上产生了 6200 多万个流,所以我们必须看看他最新的 DAYTONA 项目的流计数是多少,该项目已经推出了 9 天。

那么,如果 G . o . o . d . Music 很高兴他们获得了 Pusha T 的额外推广,并愿意支付发票,那又怎么样呢?据数字音乐新闻报道,Spotify 上每次音频播放的费用估计为 0.00397 美元。如果我们认为这些信息是真实的,我们可以计算出 G . o . o . d . music 需要产生多少个流来回馈 OVO 声音(德雷克的标签)。如果我们看看他们标签上的三位艺术家,我们会看到一些重要的每月听众人数。Kanye West 每月有 2600 万听众,而大肖恩有 1400 万听众,Pusha 有 500 万。

假设所有这些听众只播放这三位艺术家的两首歌曲(考虑到他们中的两位在本月发行了新专辑,这可能是最少的),那么你每个月就已经积累了9000 万次播放。将这个数额乘以每次播放的预计支出,你会得到仅一个月的357.000 美元的收入,仅 Spotify 一家。虽然这只是收入,没有考虑版税,但基于 Spotify 一个月的流媒体播放量,支付发票应该不会太难,对吗?;-)

“我的钩子做到了,我的歌词做到了,我的精神做到了,我无所畏惧”

两位艺术家都多次提到所谓的代笔人。因此,我很想知道每张专辑的作者和制作人的数量。下面的可视化显示了一个散点图,y 轴上是制作者的数量,x 轴上是作者的数量。

The amount of writers vs. amount of producers per album

当谈到写歌词时,另一件要检查的事情是词汇密度;独特词数除以总词数(也称词重复)。我已经包括了两位艺术家最近两张专辑的歌词,并查看了总字数和不同单词的数量(不包括所有单词长度低于 3 个字符的单词)。

  • 德雷克的字数为14381普莎 T 的字数为6016(这确实受一张专辑的曲目数量影响)。
  • 在单词统计中,德雷克有 2793 个独特单词,而普沙有 2139 个独特的单词。
  • 当计算词汇密度时,我们得到 Drake 的分数为 0.20,Pusha 的分数为 0.35。
  • 德雷克的平均字长为 4.44,普莎 T 的平均字长为 4.62。

“让史蒂文谈谈流媒体和 Shazam 数字”

这一个太难抵抗了,在他的“红外线”轨道中有一个 Pusha T 线,实际上指的是流式数字。然而,德雷克在流数据方面胜过 Pusha T 可能不会让你们感到惊讶。因为这篇文章的目的是检查事实,所以我在下面列出了一些不同之处。

Drake 在 Spotify 上每月有 4800 万听众(世界第一),而 Pusha T 每月有近 600 万听众。鉴于 Pusha T 发行了新专辑,他的听众可能会在下个月增加。德雷克在 Spotify 上有 2000 万粉丝,普沙 T 有 78 万粉丝。最后,自从提到了 Shazam,我还查看了每个艺术家的 Shazam 总数:Drake 积累了 6300 万 Shazam,而 Pusha T 积累了 670 万 Shazam。

Drake vs. Pusha T — Streaming Stats

放弃

  • 这绝不是一种选择立场的方式,因为我喜欢 G.O.O.D .的音乐和德雷克,而只是一种有趣的方式来看待这两位艺术家之间的牛肉。
  • 除了 Shazam 总数之外,Spotify 是唯一考虑的流媒体服务。

感谢阅读!如果你喜欢读这篇文章👏🏻很感激。

在这里找到更多我写的关于音乐的故事。

展现你最好的一面:沟通的新领域

原文:https://towardsdatascience.com/put-your-best-face-forward-the-new-frontier-of-communication-218abb8f538d?source=collection_archive---------1-----------------------

Data Science Popup LA @ FullScreen HQ

2013 年,当我开始在多米诺数据实验室担任营销主管时,我不太确定如何制定我们的增长战略。我尝试、测试和重复了许多不同的策略,直到有一个被卡住。多米诺数据科学弹出窗口起飞了,行业趋势过去和现在都很清楚:更小、更专注的会议带来更大的想法、更好的网络和更光明的前景。我离开了达美乐,让其发展壮大 Formulated.by ,该公司最初是一家数字营销机构,后来发展成为一家提供数字和面对面体验的机构。在面对面方面,我们制定了关注价值和内容的亲密会议,将思想和行业领袖面对面地聚集在一起,以建立新的关系,并获得人才、前景和客户。我很高兴接到杰克·帕尔默的电话,他是 Plotly 的首席执行官,他也看到并理解了行业趋势——私人会议——我们一起创建了 PLOTCON 。在超额销售了第一个 PLOTCON(我们在纽约杀死了它!)我们的一个赞助商找到了我;营销副总裁 Stephanie Mcreynold 聘请我们为 Alation 开发一个名为“策划”的新活动系列。酷的是,我们的模型在许多领域都是可适应和可访问的。

我们已经与顶级品牌合作并得到它们的支持,如:思科、Salesforce、Capital One、戴尔、维亚康姆、奥瑞利媒体、美国银行、全屏、红牛媒体、亚马逊、IBM、AWS、英特尔软件、微软、Groupon、Ebay 和许多其他品牌。

我们的客户名单也在稳步增长:AWS、O'Rielly Media、IBM、Domino Data Lab、Plotly、Data。World、Reltio、Pariveda、Alation、Dataversity +其他。

我也组建了一个很棒的顾问团队。O'Reilly Media 的业务战略和分析副总裁 Roger Magoulas 让我们的业务战略保持专注,并始终领先一步。脸书活动的顾问 Mike Sly 为我们的销售战略注入了活力,并帮助我们找到了优秀的人才。Domino 的首席数据科学家 Eduardo Arino de la Rubia 是我们的行业专家和数据科学专家。我们的顾问团由 Plotly 的创始人兼首席执行官 Jack Palmer 和 O'Reilly Media 的高级顾问 Q McCallum 组成。这些影响者共同推动我们加速前进,引领我们走向成功。

我们的活动以人为本,将品牌、影响者和人才聚集在一个空间,只有一个目标:解决所有值得解决的问题。我们计划前端有趣和轻松的会议,后端组织和优化。

时事 | 数据科学沙龙 NYC|DSS MIA|DSS SEA|DSS LA|DSS ATX

在数字方面,我们使用科学的方法,通过研发来推动合格的销售线索。我们整合了搜索引擎优化(SEO)、点击付费(PPC)、公共关系(PR)、电子邮件营销、有针对性的展示广告和社交媒体活动,以及一点点科学知识,只推动最合格的线索,最重要的是传播您的品牌意识。我们的团队将与您的团队合作,围绕您的品牌/产品建立一个强大的社区。瞄准本地、全国或全球的客户,以满足您的需求。

给我们写封短信:info@formulated.by 并顺道拜访https://formulated.by/

真诚地
安娜·安妮辛 &团队

将“优步运动”数据付诸行动—机器学习方法

原文:https://towardsdatascience.com/putting-uber-movement-data-into-action-machine-learning-approach-71a4b9ed0acd?source=collection_archive---------9-----------------------

“一切都与其他一切相关。但近的东西比远的东西更有关联。”

地理第一定律

优步于 2017 年初推出了其优步机芯服务。它由数十亿条行程数据组成,并提供对所选城市不同区域之间行程时间汇总的访问。它创造了巨大的热情,但同时也引起了研究人员、移动专家和城市规划者的怀疑。那么,优步是否正在将数据民主化,并提供免费工具来访问其庞大的数据库?也许没有那么多,但它仍然做出了巨大的努力来聚合和可视化世界各地不同城市的数据量。

Uber Movement Tool

那么我们这里有什么?我们有一个基于所选原点的旅行时间的等时线映射的好例子。对于一天中的不同时间,行进时间也被分段。让我们只指定工作日和早高峰。

Range

对于数据科学家和分析师来说,最重要的是,这些数据可以以 CSV 格式下载。但是问题是,可以下载的数据没有按照“一天中的时间”进行分段因此,您可以下载一年中某个季度的所有出发地到所有目的地的旅行时间数据,但是可用的聚合仅限于一周中某一天的每月、每小时和每天。我们稍后会谈到这一点。

Download Options

移动评估即服务

移动性是智能城市项目和位置智能的朗朗上口的术语。可以把它看作是一项服务,它根据您旅行的起点和目的地以及一天中的时间,为您提供在您居住的城市中的估计旅行时间。一天中的时间甚至可以涵盖季节性,因为你不会期望在炎热的夏季午后和灰色的冬季晨雾中有相同的旅行时间。此外,选择一个精确的日期可能会产生无尽的搜索:5 月份的周末是早上的高峰,因为你在一年中的这个时候去巴塞罗那旅行;或者是夏天的中午,周五下午 15:20 左右,因为你在伦敦进行暑期实习。优步的运动数据仅仅是个开始。

Not that mobile, is it?

这种服务的潜力对于试图将位置智能整合到其服务中的公司来说意义重大。零售和批发企业正试图评估他们所在地区的集水区,房地产公司希望评估位置的可达性,物流和货运公司希望(并且需要)知道旅行时间,因为他们运输货物。

挑战:旅行时间预测

那么,为了提供这样的服务并根据到达不同地区的时间来评估位置,我们需要知道什么呢?简而言之,旅行时间。我们要么需要一个旅行时间矩阵,要么能够即时创建一个。机器学习方法是基于足够大的历史旅行时间数据集来训练您的模型,以便它可以准确预测具有源位置、目的地位置和日期的新旅行查询的旅行时间。基本上,我们需要一个给定城市内的庞大数据集和一个合适的机器学习模型。

作为一家科技公司,优步将这个问题称为价值十亿美元的问题。旅行时间,或者用他们的行话来说,ETA(预计到达时间),是他们业务的关键绩效指标之一。

Not time travel! Travel time! (That’s also a billion-dollar question, though.)

机器学习爱好者可能已经记得几个 Kaggle 比赛中的这个挑战,例如这个关于识别纽约出租车旅行持续时间的比赛,以及最近的这个关于纽约出租车费用预测的比赛。他们都广泛关注纽约市,主要覆盖曼哈顿和布鲁克林。

我的问题是,我们应该在优步运动数据的基础上建立我们的模型,这个数据的主要挑战是什么?为什么我们要对它建模而不仅仅是查询呢?

动机

首先,我们需要定义我们的视角。我们的移动性评估需要能够为感兴趣的城市创建月、日、甚至小时精度的高精度旅行时间预测。我们正在使用机器学习方法,所以我们需要一个大的数据集。

然而,优步的数据集存在几个问题:

  • 它没有涵盖每个时间间隔的所有源和目标对。因为有时给定路线上没有足够的行程供他们汇总并添加到他们的 CSV 中,所以存在缺口。
  • 它不提供可下载格式的特定日期时间范围的聚合数据。这意味着 3 个月内所有周一或下午 1 点从出发地到目的地的平均旅行时间。
  • 它是按地区汇总的。它没有行程起点和终点的位置(经度/纬度)。
  • 当然,它只涵盖了世界上选定的城市。它可能不包括你感兴趣的那个。

Kaggle / NYC 旅行数据也有重要问题:

  • 它主要覆盖曼哈顿,这是一个比伦敦这样的大都市小得多的地区。仅仅了解整个城市的动态是不够的。
  • 曼哈顿有曼哈顿距离!它涉及一个相对简单的计算模型。为世界上大多数城市构建模型时,计算两个位置之间的距离并不容易。你需要路由软件。

Finding your way in Manhattan

最后,为大城市创建行程时间预测的主要问题是历史数据并对其进行智能过滤。在这个领域,数据非常有价值,非常大,而且很难获取。你需要缩小它的尺寸来模拟它。想出一条特定的路线和这条路线上的旅行时间。如果你想得到每小时的精度,你的数据要乘以 24。对于周精度,乘以 7,对于一个季度的日精度,再乘以 90。它呈指数增长。然后,想想在一个大城市可能有成千上万条路线。

The exponential growth of spatiotemporal data

您可能会很快想到,您需要对这些数据进行建模,而不是将这些组合中的每一个都存储在数据库中。即使对于建模,您也可以通过选择特定的起点和终点来缩减数据,因为在一个城市中几乎有无限多种不同路线的组合。

优步运动数据和建模在这一点上发挥了作用:

  • 使用优步移动数据可以帮助您了解如何在大城市选择 OD(起点-终点)矩阵对,以便有最少的路线组合来定义最大旅行时间(因此交通拥堵)可变性

1-问问你自己:你需要选择多少个原点?

2-然后问:有几个目的地?

3-最后,你可以:为城市的不同部分优化你的选择。

  • 以这种方式使用的优步流动数据可以帮助您了解大城市中人员的真实流动和流动性。
  • 对于建模,有了模型后,只需搜索特定的位置对作为路径,而忽略数据集中缺失的数据。机器学习已经帮你解决了这个问题。

开拍。

介绍完毕,我将总结一下我将要向您展示的步骤:

1-下载并浏览伦敦的每周汇总数据集。(因为它是一个足够大的数据集,而且我喜欢伦敦!)

2-对于数据准备,整合和格式化数据。

3-选择一个模型并应用它。评估准确性指标。

4-在地图上可视化预测误差。将其与数据探索中的发现进行比较。

5-比较谷歌地图和模型之间的一些旅行时间结果。

6-评论模型中可能的改进。包括我们所学的部分。

数据理解

我们将首先访问优步运动网站并导航至伦敦。然后,我们将下载“每周汇总”的 CSV 文件在这种情况下,我们将选择截至目前的最新季度:2018 年第 1 季度。

我们还需要地理边界文件来设置区域坐标。

我们将汇总数据。如你所见,那里有将近 300 万张唱片!从起点区域到终点区域,我们可以找到编码为 1 到 7 的一周中每一天的平均行程时间(dow)。

str(my_london_mv_wa)'data.frame':	2885292 obs. of  7 variables:$ sourceid                                : int  705 137 131 702 $ dstid                                   : int  167 201 261 197 131 232 157 451 302 137 ...$ dow                                     : int  7 7 7 7 7 1 7 7 $ mean_travel_time                        : num  1699 1628 3157 $ standard_deviation_travel_time          : num  600 541 688 206 $ geometric_mean_travel_time              : num  1621 1556 3088 $ geometric_standard_deviation_travel_time: num  1.34 1.34 1.23 

我们需要将“sourceid”和“dstid”映射到区域。我们会读 geoJSON 文件。它有伦敦 983 个地区的定义。对于它们中的每一个,都有一个限定该区域的边界多边形。 多边形 表示定义边界的一列路段。每个线段都有一个由经度和纬度定义的起点和终点。

library(jsonlite)library(geosphere)# load objects
my_london_regions<-jsonlite::fromJSON("london_lsoa.json")# check your region list
head(my_london_regions$features$properties)# polygon coordinates for each region
str(my_london_regions$features$geometry$coordinates)

现在让我们变戏法,然后解释这里发生了什么。

my_london_polygons=my_london_regions$features$geometry$coordinates
my_temp_poly<-my_london_polygons[[1]]
poly_len<-length(my_temp_poly)/2
poly_df<- data.frame(lng=my_temp_poly[1,1,1:poly_len,1], lat=my_temp_poly[1,1,1:poly_len,2])
my_poly_matrix<- data.matrix(poly_df)
temp_centroid<-centroid(my_poly_matrix)

我们将多边形坐标保存到一个对象中。作为演示,开始区域 1 的程序。因为我们的形状是一个多边形,我们可以用它的形心来定义这个多边形。这是因为我们需要每个区域有一个单一的位置坐标。我们来自“地圈”包的质心函数可以计算出来。我们以要求的格式给出输入。最后,我们得到了该区域的质心。让我们想象一下,看看我们做了什么。我们将使用传单包装。

leaflet(temp_centroid) %>% addTiles() %>% addMarkers() %>% addPolygons(lng= poly_df$lng, lat=poly_df$lat)

Geometrical center of the polygon is centroid.

这是我们所期望的。区域 1 有一个边界多边形,我们已经计算了它的质心。现在,区域 1 由这个位置中心定义:质心纬度和经度。很容易对每个区域重复此过程,并准备一个最终列表:

head(my_london_centroids_450,3)id         lng      lat
1 212 -0.16909585 51.49332
2  82 -0.04042633 51.39922
3 884 -0.02818667 51.45673
...

数据准备

我们的最终数据集需要有一个源位置、目的位置、日期和距离。我们已经在上一节中准备了区域的质心坐标,以便在地图上看到我们的区域。剩下的就是选择一个区域子集,然后计算每个起点和终点对之间的距离。让我们开始吧。

a-子集化

为什么我们不用所有的 983 地区呢?如果你还记得文章开头的那段话,近的东西更相关。附近地区的旅行时间相似。如果我们对区域进行子集划分,我们的最终数据集将会更小,建模时间也会缩短。我们还对这些区域进行了子集划分,因为计算距离的成本很高,并且子集划分会导致要计算的路线组合数量减少。

现在,我们的数据集有 983 个不同的地区,平均而言,它们有大约 450 个目的地。经过几次子集设置和建模试验(为了评估准确性),我们将随机选择 450 个起始区域,并为每个区域选择 150 个随机目的地。让我们看看这是什么样子:

Randomly selected 450 origin region centroids inside London city boundaries.

Here are 150 trips (destinations) from region 1. The circle has a 15km radius.

因此,大多数行程的半径为 15 公里,也包括一些到希思罗机场的行程。我们可以很容易地说,通过检查其他地区,我们的模型将足够好地预测行程的旅行时间(1)大约 15 公里的距离和(2)到机场。

我们还对 450 个产地的密度分布感兴趣。r 有强大的地理空间软件包来帮助我们。

library(spatstat)
## create a point pattern object
my_london_centroids_450_pp<-ppp(my_london_centroids_450[,2],my_london_centroids_450[,3],c(-0.4762373 , 0.2932338) ,c(51.32092 ,51.67806))#visualize densityplot(density(my_london_centroids_450_pp))

The density of our origin locations (regions).

The rasterized density image on top of London map

因此,我们的原点位置的密度在中心较高,在外围较低。同样,我们可以在建模之前进行粗略的猜测,并且可以说预测误差在中心会更小,因为有更多的原点位置(区域)。

再次使用强大的“spatstat”和“geosphere”软件包,我们可以进一步分析到目的地的距离的细节。他们可以使用点模式对象、“nnwhich”和“geoDist”函数轻松地为我们提供附近邻居的 kth:

# closest first 5 neighbor distance to destination idshead(my_london_centroids_450_nd3[,c(1,5,6,7,11,12)]) id       gd1       gd2       gd3      gd4      gd5
1 212  573.0708  807.4307  710.0935 1694.490 1325.124
2  82 1086.2706 1370.0332 1389.9356 3018.098 2943.296
3 884  641.8115  767.1245 1204.1413 2428.555 2320.905
...

b-距离计算

让我们在建模之前考虑最后一件事:我们需要计算起点和终点对之间的距离。我们不能依赖曼哈顿距离或直线距离。它需要是一个人开车走的真实距离,所以我们需要一个路由软件,可以根据城市中的特定路线计算两点之间的距离。

为此,我们有几个选择。像谷歌地图 API 这样的付费选项可能会很贵(数百美元),因为我们将有大约 67500 条路线(450 个起点*150 个目的地)。路由最全的免费软件是 OSRM (开源路由机) OpenStreetMap 用的。

library(osrm)#calculate distance
my_route_d<-osrmRoute(src=my_london_centroids_450[my_r1,] , dst=my_london_centroids_450[my_r2,], overview = FALSE)# route segments if needed to draw a polyline
my_route<-osrmRoute(src=my_london_centroids_450[my_r1,] , dst=my_london_centroids_450[my_r2,])

Calculations from OSRM results are drawn with Leaflet

OSRM 软件包默认使用演示 OSRM 服务器,并且仅限于合理和负责任的使用。我们不希望通过发送成千上万的请求在演示服务器中造成瓶颈。我们需要自己的路由服务器!

这里有一个简洁的教程描述了如何在 Ubuntu 机器上设置你自己的 OSRM 服务器。好消息是你不需要成为一个 Unix 专家来设置它。菜鸟级别的熟悉就够了。我个人用的是 Ubuntu Xenial 16.04 的 m4.xlarge 类型的亚马逊 EC2 实例。

完成后,我们可以将 OSRM 服务器选项设置为新的服务器 IP:

options**(**osrm.server **=** "http://xxx.xx.xx.xx:5000/"**)**

现在,我们已经准备好计算起点和终点对的每个路线组合的距离。

建模

最后,我们准备好了有趣的部分。准备完毕后,让我们看看我们的数据集:

head(my_london_sample_wa450150)lng_o    lat_o      lng_d    lat_d     dow distance   travel_time
-0.374081 51.5598 -0.4705937 51.54076   5    10.92        1048.46
-0.399517 51.4904 -0.4705937 51.54076   3    27.86         947.94
-0.368098 51.5900 -0.4705937 51.54076   4    14.30         1550.46
...

我们有起点/目的地坐标、星期几、距离和以秒为单位的旅行时间。这个数据集有 421,727 行。

在行程时间预测中,有两种受欢迎的算法。同样在的同一场演讲中,优步将它们列为:

The four preferred algorithms by Uber in Travel Time Prediction

我们将尝试随机森林。这是一种开箱即用的算法,需要最少的特征工程。为数据集的 70%(大约 290,000 行)创建训练集后:

modFitrf<-randomForest(travel_time ~ dow+lng_o+lat_o+lng_d+lat_d+distance,data=training_shuf[,c(3:9)],ntree=100)# resultrandomForest(formula = travel_time ~ dow + lng_o + lat_o +      lng_d + lat_d + distance, data = training_shuf[, c(3:9)],      ntree = 100) Type of random forest: regressionNumber of trees: 100
No. of variables tried at each split: 2Mean of squared residuals: 18061.1% Var explained: 96.84

在类型为 m4.2xlarge 的亚马逊 EC2 实例中,这个过程需要大约 2 个小时。

训练误差为 3.2%,测试误差为 5.4%。我们还有一个维持数据集,它引用了在对它们进行子集化时没有包含在我们的模型中的区域。对于维持数据集,从剩余区域中随机选择 100 个区域,错误率为 10.8%。

模型评估

让我们在伦敦地图上直观地显示我们的预测误差。

Test error rates grouped.

事实证明,我们的直觉是正确的。我们在中心区域的错误更少,希思罗机场也有一个黑点,这意味着它的错误率更低。

在数字上,我们也可以计算相关性。到中心的距离和预测误差之间的相关性是公平的。

cor(my_london_centroids_450_hm$distc,  my_london_centroids_450_hm$testprc)[1] 0.5463132

我们可以再次使用我们的空间包“spatstat”来可视化我们的错误率。这一次,我们将使用空间插值来平滑 2 维空间上的错误率。

library(spatstat)# assign corresponding prediction errors to our coordinates in 2-d
marks(my_london_centroids_450_pp) <-my_london_centroids_450_hm$testprc## apply inverse distance weighting / spatial interpolation
plot(idw(my_london_centroids_450_pp))

Our interpolation graphic is worth the effort. Again we can observe the regions with a low error rate

我们现在可以试试我们的伦敦旅行时间预测器。我们来做个随机对比。我们将在谷歌地图中随机选择两个点:

Google Maps calculates 21 minutes travel time on Monday evening

然后,我们将使用 OSRM 计算相同点之间的距离,并将所需的参数传递给我们的模型,以预测旅行时间。

library(osrm)lon_o<-0.054089 ; lat_o<-51.591831
lon_d<-0.114256 ; lat_d<-51.553765# calculate distance
my_distance<-osrmRoute(src = data.frame(id=1,lon= lon_o , lat=lat_o) ,dst= data.frame(id=2,lon=lon_d  , lat=lat_d), overview = FALSE)[2]# get route
my_route<-osrmRoute(src = data.frame(id=1,lon= lon_o , lat=lat_o) ,dst= data.frame(id=2,lon=lon_d  , lat=lat_d))# calculate travel time with our model for monday
travel_time<-predict(modFitrf, data.frame(dow=1, lng_o= lon_o,lat_o=lat_o,lng_d=lon_d ,lat_d=lat_d,distance=my_distance) )

让我们来看看结果:

Prediction from our model visualized on Leaflet

即使在一个不靠近中心的地区,我们的模型也做出了相当不错的预测,只差几分钟就错过了谷歌地图的预测。

通过使用插值测试误差率,我们可以找到原点位置的预期测试误差率。

my_image[list(x= 0.054089,y=51.591831)]
[1] 0.06567522

因此,根据 2 维空间中测试误差率的分布,我们预计该区域的传播时间误差约为 6%。

自然,我们面临着更高的错误率,因为我们使用的优步运动数据集没有每小时的精度。我们只是对周一做了一个整体预测,无法捕捉高峰或非高峰时间。此外,请注意,我们使用的是第一季度的数据,这意味着我们主要是对冬季进行预测,但这一比较是在 2018 年 9 月进行的。我们没有真正捕捉到季节变化。

最终注释

基于伦敦 2018 年第一季度的优步运动数据,我们使用随机森林算法通过机器学习制作了一个旅行时间预测器。

可能的改进:

  • 可以分析每小时汇总的数据。有了这些数据,我们就可以将我们的模型与来自每小时聚合数据的模型相结合,以获得更精确的结果来捕捉交通拥堵的每日变化。
  • 现在我们有了第一批结果,可以更有策略地进行子集化。很明显,我们需要更多的郊区区域来进一步降低错误率。
  • 我们可以为中心和郊区创建单独的模型。可以针对不同的型号单独调整型号。喜欢在随机森林的郊外有更多的树的深度。
  • 我们可以尝试其他算法(KNN、XGboost 或神经网络),并将它们组合成一个整体。
  • 可以对一年中的其他季度进行相同的建模,以捕捉季节性。

我们可以从中学到什么:

  • 因为我们有时空数据,所以需要空间分析。
  • 插值是探索和使用此类数据的强大转换工具。
  • 起点和终点区域的选择是一种优化问题。我们正试图捕捉旅行时间预测中的最大可变性,同时将始发地和目的地的数量保持在最小。

想听听大家的意见和建议!

请随时通过 LinkedIn 和 Github 联系我。

PyCon India 2018 —数据科学家的体验

原文:https://towardsdatascience.com/pycon-india-2018-a-data-scientists-experience-a7ca59e26ea9?source=collection_archive---------19-----------------------

The team behind PyCon India 2018

每年秋天来临的时候,它都会在世界各地掀起一场大规模的会议、研讨会和黑客马拉松。其中之一是派康的非常自己的派康印度

PyCon India 汇集了技术专家、科学家、一般开发人员和 Python 开发人员、开源贡献者、数据极客和软件开发人员(具体而言)

今年,PyCon India 十周年庆典在海得拉巴市的海得拉巴国际会议中心(HICC)举行,约有 16000 名与会者在不同领域使用 Python,从为科学图书馆做出贡献到自动化和维护发电厂。

那么,我们开始吧,让我们看看 2018 年印度 PyCon 上发生了什么😍:

一般来说,PyCon India 从各种 Python 库和框架的研讨会和实际操作开始,这些库和框架用于解决许多问题的各个领域。激动吗?什么问题?谁解决?怎么解决?…🤔🙄

让我们看看他们🤗研讨会…👨🏻‍💻

Exploring PyTorch for AI assistance in medical imaging

这个人是深度学习工程师(哇,工程师🙃)解决医疗保健面临的问题。他说,“就像在我们的日常生活中一样,人工智能和机器人越来越成为我们医疗保健生态系统的一部分。目前医疗保健被打破了;医生短缺;护理质量差。迫切需要为整个医疗行业提供援助,以改善医疗保健”(嗯,没错😌)

这个会议说明了我们作为工程师有多棒,今天谁关心健康(如果你关心的话👏🏻)? Abhishek Kumar 和 Aditya Bagari 震撼了本次会议,他们带领观众从介绍 PyTorch 到解释卷积神经网络以及如何在充满挑战的敏感医疗保健领域使用它。

Decoding Bollywood with Python and Data Science

敲门敲门。这是马克·加西亚和他的朋友希曼舒。Marc 是 Python 数据分析库 Pandas 的核心开发人员🐼🐼
但是,等等!告诉我谁更受欢迎,卡特里娜·卡伊夫迪皮卡·帕度柯妮?从故事情节来看,什么电影最像 PK

惊讶吗?好奇想知道?😃

在这个工作室中,他们收集 IMDB 数据,在熊猫中进行处理,制作美丽的图案,并在散景和其他带有宝莱坞数据的酷东西中可视化,看看他们的 github repo 并享受吧!!!

本次研讨会展示了 Python 及其开源库的另一个令人惊叹的应用,这个人展示了 Python 如何简化地理空间数据(矢量数据和栅格数据)的分析。

他说,“地理空间表示在日常生活中非常普遍,例如甚至在简单的与地图、航空/卫星图像等旅行相关的对话中。在数字时代,地理空间数据被广泛生产和消费,其比例越来越大。Python 及其免费和开源库提供了各种简单有效的工具来可视化和分析地理空间数据"

他向我们介绍了一个名为 GeoPandas 的出色的 python 库,这是一个开源项目,旨在使使用 Python 处理地理空间数据变得更加容易。GeoPandas 扩展了熊猫使用的数据类型,允许对几何类型进行空间操作。几何运算由 shapely 完成。Geopandas 进一步依赖 fiona 进行文件访问,依赖 descartes 和 matplotlib 进行绘图。(酷😍,没有?).别忘了留意他的 GitHub 报告。

JupyterHub and Binder

Carol Wiling 是 Project Jupyter(是的,你没看错)和 CPython 的核心开发人员之一,也是 Python 软件基金会的前主任。

她参加了一个关于 Python 中科学计算以及 JupyterLab 如何用于此目的的精彩会议

她用 JupyterLab 和它在数据科学和科学计算中的应用告诫与会者(是的,哈哈)

在本次会议中,我们了解了 JupyterLab 用户可以使用的新用户界面功能。稍后,我们将超越 JupyterLab 的个人工作流,看看 JupyterHub 如何将 JupyterLab 带给用户组。最后,我们讨论了 Binder 及其为 Jupyter 笔记本和其他设备提供短暂计算环境的能力。这是她对案例研究的幻灯片

嘿,你认识照片上的这个人吗(不认识?😱)?他是 SciPy,NumPy 和 Numba 的创造者。特拉维斯·奥列芬特是你在 Python 中进行科学和数值计算的原因。(你用 anaconda 吗?他也是幕后黑手🤓)

是的,他拿走了车间!他说所有使用 Numba,NumPy 的人都是“他的人”

在这个研讨会上,他讨论了用 Numba 和 Dask 扩展 Python,他解释了 Python 的编译器是如何工作的(什么?编译器?)并使用 JIT 编译器增强 Python 的计算能力💪🏻

这些是 2018 年印度 PyCon 第一天的几个研讨会的亮点!

现在怎么办?发布会!!!😻😻

Conference Hall (empty, han?)

人们为什么参加会议🤔?嗯,也许是因为以下原因?
1。走廊对话
2。伟大的会谈(我知道你不看网上会谈)
3。潜在的职业机会(许多人通过 PyCon 找到工作)
4。与创业公司和公司建立关系网。开始进入开源领域
,这样的例子不胜枚举…🚀

在会议期间,我必须在登记处管理门票、t 恤和礼品,我们做得很好(你可以问与会者🤷🏻‍).我真的很喜欢登记的匆忙(等等😼)

会议以开幕致辞开始,以 2018 年印度 PyCon 主席 Manivannan Elangovan 的闭幕致辞结束。 但是等等!这中间发生了什么?好了,让我们来看看亮点!

主题会议、机构群体讲座、赞助商讲座、照明讲座和各种平行讲座都在这两天举行。人们分散在 HICC 的各个房间和大厅。

这四位传奇人物是主题演讲人,他们都让我和众多与会者着迷。

着迷?怎么会?这些人是我们今天所看到的人工智能的原因,这些人是我们今天如何处理数据的原因!

阿明·罗纳彻(Flask framework 的创始人,用 Python 编写的令人敬畏的 web 应用程序框架)是第一个主旨发言人,随后是特拉维斯、卡罗尔和西杜。我永远不会忘记在这两天的会议中我看到并记下的一些精彩内容

这个闪电谈话中的传奇展示了他如何运用自己的天赋、技能和热情去营救喀拉拉邦洪水的受害者。他是 Django 的开发者 Biswas,在喀拉拉邦洪水灾民的大量请求中,他帮助 keralarescue.in 运行。

Carol Wiling 在她的演讲中分享了一些关于 Python 及其未来的很酷的统计数据。她已经编码 41 年了!

她说1989 年的 Python,
154,293 个项目,
1,094,879 个版本,
1,503,765 个文件,
268,049 个用户

在这里你可以看到很多谦卑,人们坐下来听数据科学家达薇亚关于自然语言处理的演讲。

阿明·罗纳切尔讨论了 Python 的“T2”对复杂性的恐惧。

阿明 @mitsuhiko 在 @pyconindia 的主题演讲中表示愿意应对 #Python 及其社区的挑战,这非常了不起。我们只有通过深入看待我们的挑战来学习。向 Rust 等其他社区学习是个好主意。

给你,在会议的第二天晚上,玛琳·姆汉加米与卡罗尔和阿明进行了激烈的讨论。

Marlene 是 Python 软件基金会的主任,也是津巴布韦 Python 用户组的联合创始人

嗯,有一个 Durgaput Linux 用户组 的聚会,这是一个大多数学生在开源和自由软件基金会的海洋中开始他们职业生涯的地方。

在这里,我开始了我的数据科学之旅,学到了技术伦理,学到了自由软件运动的遗产和许多东西。十年前,库沙尔·达斯创立了 DGPLUG,帮助学生在从事牙线工作后最终找到工作

Alumni and Community of Durgapur Linux User Group’s very own Summer training

👨🏻‍💻👨🏻‍💻👨🏻‍💻👨🏻‍💻👨🏻‍💻发展冲刺👨🏻‍💻👨🏻‍💻👨🏻‍💻👨🏻‍💻👨🏻‍💻

在 PyCon 的 Devsprints 上又是一个伟大的日子(但不是最后一天),开发人员聚集在一起,通过贡献他们天赋的编码技能来解决问题

数据人马克·加西亚激励我们为熊猫做贡献,并简化这个令人敬畏的数据工具

令人敬畏的 Jupyter 女人 Carol Willing 坐在椅子上指导开发人员,并指导我们解决 Jupyter 项目中的问题

阿明(烧瓶创建者)、特拉维斯·奥列芬特(T1)(Scipy 创建者)、卡罗尔·威林(CPython 核心开发人员和 Jupyter 核心开发人员)、马克·细川玉子(熊猫核心人员)都非常谦逊,乐于助人。他们站了几个小时来回答与会者的问题,吃饭的时候,休息的时候,会议结束后,哇!编码,交谈,指导,吃,享受这个 PyCon 。

Jobs Board at PyCon

那么,这就是 2018 年印度 PyCon 的结束。人们编码、指导、建立联系、交谈等等

无论如何,我只见过创业的人和研究员,他们给了我很多关于我们(我和我亲爱的朋友)即将到来的商业想法的建议(上帝保佑)

这一次,人们聚集在这个国家最好的会议中心之一,它以热情好客而闻名

人们得到了工作推荐,初创公司和跨国公司展示了他们的产品,Python 核心开发人员、Pandas 核心开发人员和 Jupyter、Scipy 开发人员来到现场,与开发人员互动

人们寻求他们的指导来为这些令人敬畏的项目做贡献,一些公开的问题已经在 Devsprints 中解决了

开源人员听到了一个好消息,他们将获得一份有报酬的工作(如果他们将自己的想法转化为业务,并拥有自己的创业公司,而不是免费提供他们的想法,这将更加有益,也许他们可以成为独角兽🦄)

为语言而来,为社区而留——布雷特

PyData 伦敦 Meetup 2017 年 4 月评论,由初学者。

原文:https://towardsdatascience.com/pydata-london-meetup-april-2017-review-by-a-beginner-fddff980a745?source=collection_archive---------4-----------------------

Will it be totally beyond me? Or not?

PyData London Meetup ,一场众所周知很难买到票的聚会。PyData London 每个月都有一个重要的等候名单,你必须非常迅速地确认你的出席。在之前的活动后,我在酒吧见过组织者和与会者(这是 Meetup 的传统),我知道社区和会谈的质量将是高质量的,我在正确的地方继续我的数据科学教育。如果你没有买到活动的门票,但仍然想与社区成员见面,请关注 PyData LondonTwitterfeed,了解聚会后他们去的酒吧的位置。

位置

聚会不动了。有免费的食物和啤酒你为什么要喝?这是因为 meetup 一直由 AHL 的慈善团队主办。这使得组织者可以将更多的精力花在聚会的其他方面,而不是每月寻找新的地点。因此,聚会的质量每个月都在提高。

但是,因为地点没有改变,meetup 现在经常在宣布的几天内达到最大容量。).不幸的是,这意味着每次只有 230 人可以参加,人们确实错过了。组织团队知道这一点,几乎所有的谈话都在网上结束,并分享给 meetup 小组。一个重要的小组还会在会后去附近的酒吧喝一杯。你没有参加只是错过了一点点,这要归功于组织者和演讲者。尽管由于这种制度,meetup 将存在更长时间,但难以参加的方面确保了获得门票的行为将被视为更重要的事件,实际与会者与提供的位置的比率在可预见的未来将保持高水平。

主要会谈

Ju Lui 用机器学习预测泰坦尼克号幸存者

Are they even looking into each others eyes!?

用他的第二选择语言 Python 现场编码 45 分钟?对朱露来说没问题。从初学者的角度来看,这是对机器学习的完美介绍。前半部分致力于通过使用熊猫包来可视化和理解泰坦尼克号幸存者的数据,房间里的每个人都能够与演讲者保持在同一水平上。全部实时编码,没有错误。强壮。

Ju Lui visualising the data focusing on variables such as sex, class and survival.

我的统计学教育已经深入到多元线性回归分析,演讲的最后三分之一超出了我的理解范围,但并没有多到让我与演讲脱节。在达到这一步之前理解了数据,我可以理解 90%的讨论内容,并理解正在进行的监督学习。总的来说,这次谈话质量很高,富有教育意义和娱乐性。鉴于这场演讲 95%都是现场直播的,后续演讲的门槛已经定得很高了。相关 GitHub 。

叶戈尔·克拉夫——用于实时分析的异步流式 Python

The Push approach with added silhouette. The addition of Keeping up with the Kardashians on the right is a unique aspect of PyData London.

叶戈尔·克拉夫,在两家大银行做了 10 年的量化分析师,现在是人工智能的负责人和 Dagon Analytics 的创始人。这个演讲集中在人工智能的另一个非常重要的部分。数据系统允许数据结构化和可访问,因此算法可以轻松完成任务。

The Logic for swapping from a Push approach to a Pull approach.

该讲座重点讨论了数据框架内的推方法,然后将其改为由 asyncio 和 Kafka 支持的拉方法。决定从推式系统转变为拉式系统背后的逻辑得到了很好的解释和可视化。讲座以一个快速演示结束,展示了在笔记本电脑上运行的系统。这次讲座比上一次的水平更高,但仍然允许那些没有相关经验的人理解和学习。又是精彩的谈话!

The Pull Solution

闪电谈话

最多 5 分钟。走吧。

马蒂·莱拉——戴着手套的手

Matti Lyra 从德国赶来参加这次演讲,并通知 PyData 伦敦社区 PyData 柏林,这是继 PyData 伦敦之后的另一场会议。在 5 分钟之内向一群人传达有用的信息是很难的。马蒂用了 2 分钟。我没有经验,所以我会给你一个描述和一个合适的 GitHub 工具的链接。

word 2 vec 和 GloVe 形式的分布式单词表示在过去 5 年中变得非常流行。虽然斯坦福大学 NLP 小组已经发布了他们训练过的手套向量,但数据格式并不方便。我将展示一个我编写的小工具“GloVe2H5 ”,它使访问预先训练好的向量变得更加容易。

Adam Hill——构建企业所有权数据的图表模型以揭露潜在的腐败

Eric Pickles publically acknowledged the work done by DataKind.

Adam Hill 从 Matti 的演讲中抽出空闲时间,让他讨论 DataKind 如何使用公司的公开数据来了解公司所有权。最初是一个 15 分钟的演讲,将信息压缩到 7 分钟并没有降低工作的重要性。通过能够可视化和分析公司的所有权图表,可以研究许多关于避税天堂和部分所有权的见解。结果已传达给政府,政府公开承认这一良好工作,目前正在调查中使用。这里有的幻灯片。

Celine bou dier——谷歌数据工作室测试版生活教育工具数据代码仪表板

Celine Boudier 向我们介绍了 Ocado 的一项名为“ Code for Life 的非营利计划,旨在创建免费的开源游戏,帮助儿童学习计算。第一局快速路由器已经在行动了!席琳想让我们了解谷歌数据工作室。Celine 和他的团队使用该软件将他们收集的数据可视化,并使其更易于与其他人交流。这些易于制作的可视化让他们能够理解他们网站上的行为,因为它是基于网络的,这有助于他们解决选择使用基于 Linux 的系统可能带来的问题(没有表格)。幻灯片。

围捕

聚会很棒,组织得很好,主题和社区都以高质量相互匹配。在聚会期间,我遇到了许多优秀的人,我期待在以后的活动中遇到更多的人!

判决:到社区报名就走!初学者或有经验者。

下一个事件: PyData 伦敦会议。在这里买票。五月没有聚会。

截至 2017 年 7 月 4 日,我既不是数据科学家,也不是 APM。我的宏伟目标是成为一名拥有良好数据科学知识和/或背景的产品经理。如果你愿意帮助我,哪怕只是一点点,请通过 LinkedIn 联系我,或者通过 Twitter 联系我,Twitter 是 T2,robwin 是 T3。我会肯定地回答,这将是巨大的赞赏。我正在寻找一个可以一起学习和创造价值的团队。

在 Kaggle Titanic 数据集上测试 PySpark ML 和 XGBoost 完全集成

原文:https://towardsdatascience.com/pyspark-and-xgboost-integration-tested-on-the-kaggle-titanic-dataset-4e75a568bdb?source=collection_archive---------1-----------------------

在本教程中,我们将讨论如何使用标准的机器学习管道来集成 PySpark 和 XGBoost。

我们将使用来自“泰坦尼克号:机器从灾难中学习”的数据,这是众多 Kaggle 比赛之一,在 T2 举行。

本文的新版本包括 PySpark 和 XGBoost 1.7.0+之间的原生集成,可以在 这里 找到。

在开始之前,请了解您应该熟悉 Apache Spark 和 Xgboost 和 Python。

本教程中使用的代码可以在 github 上的 Jupyther 笔记本中找到。

如果你对本教程的设置有任何问题,你可以查看另一篇解释如何在 docker 中运行的文章。

步骤 1:下载或构建 XGBoost jars

python 代码需要两个 scala jars 依赖项才能工作。您可以直接从 maven 下载它们:

  • xgboost4j
  • xgboost4j-spark

如果你想自己建造它们,你可以从我以前的教程中找到方法。

步骤 2:下载 XGBoost python 包装器

你可以从这里下载 PySpark XGBoost 代码。这是我们将要编写的部分和 XGBoost scala 实现之间的接口。我们将在教程的后面看到如何将它集成到代码中。

第三步:开始一个新的 Jupyter 笔记本

我们将开始一个新的笔记本,以便能够编写我们的代码:

jupyter notebook 

步骤 4:将定制的 XGBoost jars 添加到 Spark 应用程序中

在启动 Spark 之前,我们需要添加之前下载的 jar。我们可以使用--jars标志来做到这一点:

import os
os.environ['PYSPARK_SUBMIT_ARGS'] = '--jars xgboost4j-spark-0.72.jar,xgboost4j-0.72.jar pyspark-shell'

步骤 5:将 PySpark 集成到 Jupyther 笔记本中

使 PySpark 可用的最简单的方法是使用[findspark](https://github.com/minrk/findspark)包:

import findspark
findspark.init()

步骤 6:开始 spark 会话

我们现在准备开始 spark 会话。我们正在创建一个 spark 应用程序,它将在本地运行,并将使用与使用local[*]的内核一样多的线程:

spark = SparkSession\.builder\.appName("PySpark XGBOOST Titanic")\.master("local[*]")\.getOrCreate()

步骤 7:添加 PySpark XGBoost 包装器代码

现在我们有了 spark 会话,我们可以添加之前下载的包装器代码:

spark.sparkContext.addPyFile("YOUR_PATH/sparkxgb.zip")

步骤 8:定义模式

接下来,我们定义从 csv 读取的数据的模式。这通常是一个比让 spark 推断模式更好的实践,因为它消耗更少的资源,并且我们完全控制字段。

schema = StructType([StructField("PassengerId", DoubleType()),StructField("Survival", DoubleType()),StructField("Pclass", DoubleType()),StructField("Name", StringType()),StructField("Sex", StringType()),StructField("Age", DoubleType()),StructField("SibSp", DoubleType()),StructField("Parch", DoubleType()),StructField("Ticket", StringType()),StructField("Fare", DoubleType()),StructField("Cabin", StringType()),StructField("Embarked", StringType())])

步骤 9:将 csv 数据读入数据帧

我们将 csv 读入一个DataFrame,确保我们提到我们有一个头,并且我们还用 0:

df_raw = spark\.read\.option("header", "true")\.schema(schema)\.csv("YOUR_PATH/train.csv")df = df_raw.na.fill(0)

步骤 10: C 将标称值转换为数值

在浏览这一步的代码之前,让我们简单地浏览一下 Spark ML 的一些概念。他们引入了 ML pipelines 的概念,ML pipelines 是建立在DataFrames之上的一组高级 API,使得将多个算法合并到一个进程中变得更加容易。管道的主要元件是TransformerEstimator。第一个可以表示一个可以将一个DataFrame转换成另一个DataFrame的算法,而后者是一个可以适合一个DataFrame来产生一个Transformer的算法。

为了将标称值转换成数值,我们需要为每列定义一个Transformer:

sexIndexer = StringIndexer()\.setInputCol("Sex")\.setOutputCol("SexIndex")\.setHandleInvalid("keep")cabinIndexer = StringIndexer()\.setInputCol("Cabin")\.setOutputCol("CabinIndex")\.setHandleInvalid("keep")embarkedIndexer = StringIndexer()\.setInputCol("Embarked")\.setOutputCol("EmbarkedIndex")\.setHandleInvalid("keep")

我们使用StringIndexer来转换这些值。对于每个Transformer,我们将定义包含修改值的输入列和输出列。

步骤 11: A 将列组装成特征向量

我们将使用另一个Transformer将 XGBoost Estimator分类中使用的列组装成一个向量:

vectorAssembler = VectorAssembler()\.setInputCols(["Pclass", "SexIndex", "Age", "SibSp", "Parch", "Fare", "CabinIndex", "EmbarkedIndex"])\.setOutputCol("features")

步骤 12:定义 XGBoostEstimator

在这一步中,我们将定义产生模型的Estimator。这里使用的大多数参数都是默认的:

xgboost = XGBoostEstimator(featuresCol="features", labelCol="Survival", predictionCol="prediction"
)

我们只定义了feature, label(必须匹配来自DataFrame的列)和包含分类器输出的新的prediction列。

步骤 13: B 建立管道和分类器

在我们创建了所有单独的步骤之后,我们可以定义实际的管道和操作顺序:

pipeline = Pipeline().setStages([sexIndexer, cabinIndexer, embarkedIndexer, vectorAssembler, xgboost])

输入DataFrame将被转换多次,最终将产生用我们的数据训练的模型。

步骤 14:训练模型并根据新的测试数据进行预测

我们首先将数据分为训练和测试,然后我们用训练数据拟合模型,最后我们看看我们为每个乘客获得了什么预测:

trainDF, testDF = df.randomSplit([0.8, 0.2], seed=24)model = pipeline.fit(trainDF)model.transform(testDF).select(col("PassengerId"), col("prediction")).show()

PySpark UDFs 和恒星膨胀

原文:https://towardsdatascience.com/pyspark-udfs-and-star-expansion-b50f501dcb7b?source=collection_archive---------3-----------------------

在很大程度上,我发现从主要从事 SQL 工作到主要从事 Spark 工作的转变是平稳的。熟悉 SQLalchemy 和 Django 这样的 ORM,适应起来并不难。选择、过滤、连接、分组以及诸如此类的事情都或多或少地按照它们在 SQL 中的方式工作。我认为构建一个数据查询是有逻辑的,对这种逻辑的感觉是战斗中最困难的部分——剩下的只是实现。

在我看来,Spark 的难点在于资源管理。找出内核、内存(堆内和堆外)和执行器的正确平衡是一门艺术,而不是科学,Spark 给你的错误消息通常只能提供最少的信息。我发现很少有好的 Spark 培训材料。也许我因为主要使用 PyData 和 SQL 堆栈而被宠坏了:当我有关于 Pandas 或 Postgres 的问题时,我会搜索它,它几乎总能给我一些相当完整的文档和工作示例,经常给我一些信息丰富的博客帖子,并且通常给我至少一个有用的堆栈交换问题。当我有一个关于 Spark 的问题时,我会在 Google 上搜索它,通常会得到一个文档页面,简单地确认该方法在技术上是存在的。仅此而已。

当涉及到 PySpark 用户定义函数(UDF)时,我发现资源管理特别棘手。Python UDFs 是在 Spark 中进行数据科学研究的一种方便且经常必要的方式,尽管它们不如使用内置 Spark 函数甚至 Scala UDFs 高效。使用 Python UDF 时,了解 Spark 如何评估它很重要。考虑下面的例子,该例子假设火花数据帧‘SDF’具有两个数字列‘col 1’和‘col 2 ’:

**import** pyspark.sql.functions as f
**import** pyspark.sql.types as t**def** my_function(arg1, arg2):argsum **=** arg1 **+** arg2argdiff **=** arg1 **-** arg2argprod **=** arg1 ***** arg2**return** argsum, argdiff, argprodschema **=** t.StructType([t.StructField('sum', t.FloatType(), False),t.StructField('difference', t.FloatType(), False),t.StructField('product', t.FloatType(), False),
])my_function_udf **=** f.udf(my_function, schema)results_sdf **=** (sdf.select(my_function_udf(f.col('col1'), f.col('col2')).alias('metrics'))   # call the UDF.select(f.col('metrics.*')) # expand into separate columns
)

如果在执行上述代码块后调用` results_sdf.explain()',您应该会看到这样一行内容:

BatchEvalPython [my_function(col1#87, col2#88), my_function(col1#87, col2#88), my_function(col1#87, col2#88)]

这意味着,为了对度量字段进行星形扩展,Spark 将调用您的 udf 三次——对模式中的每个项目调用一次。这意味着你将使用一个已经低效的函数并多次运行它。

通过对代码做一点小小的修改,就可以让 Spark 只计算一次 UDF:

results_sdf **=** (sdf.select(f.explode(f.array(my_function_udf(f.col('col1'), f.col('col2')))).alias('metrics')).select(f.col('metrics.*'))
)

将结果封装在一个数组中,然后分解该数组会产生一些开销,但是与只计算一次 UDF 所节省的资源相比,这些开销是微不足道的:

BatchEvalPython [my_function(col1#87, col2#88)]

您可以通过在进行 star 扩展之前对数据帧进行持久化或检查点操作来获得相同的结果,但是这样会耗尽内存和磁盘空间,您可能不希望这样做。

Python 和 Slack:天生一对

原文:https://towardsdatascience.com/python-and-slack-a-natural-match-60b136883d4d?source=collection_archive---------3-----------------------

(Source)

如何使用 Python 以编程方式发送 Slack 消息、发布绘图和监控机器学习模型

当你知道你能用 Python 做多少事情时,生活就会变得更加美好。当我阅读 用 Python 自动化枯燥的东西,并看到有一些例行任务——比如任何与电子表格有关的事情——我不再需要浪费时间时,我的日常工作流程发生了第一次转变。相反,我可以花几分钟写一个 Python 程序(好吧,一开始可能要花几个小时),运行脚本,然后坐下来看乏味的工作自行完成。

第二个转变发生在我意识到几乎任何带有 API 的服务— 应用编程接口 —都可以用 Python 操作的时候。你可以在 Spotify ( Spotipy 库)、Twitter(python-Twitter)、Wikipedia(Wikipedia API)和 Slack(Slackerfor Python)等应用中做的任何事情,都可以通过 Python 代码来完成。

这意味着您不必局限于在应用程序中与这些服务进行交互,而是可以编写代码来自动化复杂的工作流或构建新工具。

在本文中,我们将看到如何使用 Slacker Python 库以编程方式与 Slack 交互。我们将能够从工作区检索任何数据,更改频道和用户的设置,发布消息,上传文件,创建应用程序,甚至实时监控机器学习结果。完整的代码可以在 GitHub 的 Jupyter 笔记本上获得。

Real-time monitoring of machine learning in Slack.

懒鬼入门

Slacker 是 Slack API 的 Python 接口。它包装了 Slack API 服务(完全由 Slack 支持),并允许我们编写 Python 代码,而不是自己格式化对 API 的请求。这意味着构建查询的时间要少得多,与 Slack 的交互也更容易。在使用 Slacker 库时,Slacker API 方法文档非常有用(它的文档相对较少)。无论你想在闲暇时做什么,只要你愿意做一点搜索,你都可以通过这个库来做!

入门指南

首先,您需要创建一个松弛工作空间。我假设如果你有信心编写 Python 代码,你可以自己处理这一步。我建议创建一个新的工作空间,在这里你是测试交互的管理员。下一步是获取遗留 API 令牌。如果您已登录工作区,请前往此链接。确保将您的令牌放在安全的地方!

使用您的 API 令牌向 Slacker 进行身份验证,如下所示:

from slacker import Slacker# Authenticate with slacker
slack = Slacker(slack_api_token)

通过打印出工作区的名称来检查您是否已连接:

# Check for success
if slack.api.test().successful:print(f"Connected to {slack.team.info().body['team']['name']}.")
else:print('Try Again!') **Connected to Data Analysis.**

与时差互动

在 slack 中你可以做的任何事情(好的,几乎任何事情)都可以通过 Python 与 API 的接口来完成。(点击查看完整的方法列表)。例如,下面是我们可以对渠道做的一切:

信息检索

让我们从一些简单的数据检索开始。每次我们在Slacker中使用不同的函数时,我们都会得到一个响应对象,其中body保存结果(如果请求成功)。我们可以检索很多不同的信息。例如,以下是渠道和目的:

# Make a request to get the channels
r = slack.channels.list()
channels = r.body*# Iterate through channels*
for c in channels['channels']:print(f'Channel {c["name"]} Purpose: {c["purpose"]["value"]}') **Channel general Purpose: This channel is for workspace-wide communication and announcements. All members are in this channel.****Channel python_content Purpose: Data Science and Python****Channel random Purpose: Deep philosophical discussions****Channel testing_exp Purpose: Experimental testing of interactions.**

如果我们想检查用户(成员),下面是代码和结果:

from IPython.display import Image# Find all users
users = slack.users.list().bodyfor u in users['members']:*# Print some information*print(f'User: {u["name"]}, Real Name: {u["real_name"]},                  Time Zone: {u["tz_label"]}.')print(f'Current Status: {u["profile"]["status_text"]}')*# Get image data and show*Image(user['profile']['image_192'])

Users in our workspace

这个工作区挺寂寞的!我们可以在频道中搜索文件或消息,查看频道的历史记录,甚至查看“请勿打扰”设置:

(在这种情况下,用户是指 id。我们可以找到带有slack.users.get_user_id(username)的用户名的用户 id。

更改设置和属性

我们不仅可以找到我们想要的任何信息,还可以改变属性。也许我想告诉我的团队让我一个人呆着:

# Set do not disturb for 2 hours
slack.dnd.set_snooze(num_minutes=120)

我还可以更改我的个人资料设置:

slack.users.profile.set(user = 'wjk68', name = 'status_text', value = 'Writing some code')
slack.users.profile.set(user = 'wjk68', name = 'status_emoji',value = ':male-technologist')

关于表情符号的话题,你可以使用表情符号代码来指定你想要的图标。最简单的方法就是去 Slack,搜索你想要的表情符号,然后复制出现的代码:

Searching for an emoji code.

想创建一个新的频道并设定目的?两行 python 代码:

# Create a new channel and set purpose
slack.channels.create('python_content_new')
slack.channels.set_purpose('python_content_new', 'Data Science and Python')

发布消息

当然,我们不只是想成为信息的被动消费者。我们要和世界对话!幸运的是,Slacker让我们可以轻松发布到任何频道:

# Post a message
slack.chat.post_message(channel='python_content',text='Have a great day!',username='Python Test',icon_url='http://devarea.com/wp-content/uploads/2017/11/python-300x300.png')

如果我们设置了username,那么消息将作为机器人发布。我们可以通过指定 url 或表情符号来选择图标。我们也可以用<@user_id>提到具体用户或者犯下终极之罪通知大家:

slack.chat.post_message(channel='python_content',text='<!everyone> *This is not atest!*',username='Alert',icon_emoji=':female-firefighter:')

消息可以像我们想要的那样复杂。使用附件,我们可以格式化消息,甚至创建游戏!有关所有选项,请参考 Slack API 关于格式化消息的文档。

Message formatting

App created via a message

您可以使用交互消息构建复杂的应用程序工作流。

上传文件

上传本地文件是另一个单行程序:

slack.files.upload(file_='images/volcano_crater.jpg',channels=['random'], title='Volcano Crater',initial_comment='This would make a great          display background')

Uploaded files.

如果我们已经做了一些很酷的分析,并想与团队分享这些图,我们保存这些数字并上传:

我们还可以使用 API 删除文件或消息、添加评论、创建私人聊天、邀请用户、设置提醒等等。

监控机器学习训练

好了,是时候认真对待一些真正的工作了。在这里,我们将发送消息来监控卷积神经网络(CNN)的训练进度。我正在使用 Keras 的脚本来训练 CNN 识别 MNIST 数字。有了 Keras 中的自定义回调,我们可以在每个时期结束时用当前统计数据向 Slack 发送一条消息。S ee 笔记本完整代码,但基本轮廓在下面(这是伪代码,不会太跑):

现在,我们可以在 Slack 中获得实时深度学习更新!

在训练结束时,我们可以创建一些训练曲线并发布出来:

发布预测

最后,一旦我们的模型训练完毕,我们就可以发布来自测试集的预测:

Predictions from convolutional neural network on test set.

这款做的相当不错!对于这个简单的例子,监控可能是不必要的,但是有很多用例跟踪一个模型或者发布持续集成结果。我整夜运行模型,当我不想去命令窗口查看进度时,只查看 Slack 是有用的。

当有事情需要你注意时,自动发布到 Slack 或通知你的写作工具可以让你把注意力转移到更重要的事情上。最终,程序化的工作流减少了花费在繁琐任务上的时间和精力。

Reduce the amount of tedium in your life with Python! (Book available for free).

结论

虽然 Slack 等应用程序可以用来娱乐,但如果使用得当,它们也可以提高生产率。此外,如果我们意识到这些应用程序可以通过 Python 访问它们的 API,我们就可以通过编程来控制它们,从而提高效率。

在本文中,我们看到了如何通过 Python 中的Slacker库与 Slack 交互。这个库让我们可以访问 Slack API,这意味着我们几乎可以控制工作空间的每个方面。除了其他事情,我们可以

  • 检索频道、消息和用户信息
  • 更改和管理用户、渠道和团队设置
  • 发布包括应用程序在内的消息
  • 跟踪机器学习的进度并绘制结果

如果 Slack 不是你最喜欢的应用程序(尽管它应该取代你的电子邮件),看看 Python API 接口的列表。即使这个特殊的用例对你来说没有吸引力,但是我们可以使用 Python 来完成日常任务的想法是很有说服力的,因为它使我们更有效率。

一如既往,我欢迎反馈和建设性的批评。可以通过 Twitter @koehrsen_will 或者通过我的个人网站 willk.online 找到我。

基于 Python 的 Matplotlib 绘图

原文:https://towardsdatascience.com/python-based-plotting-with-matplotlib-8e1c301e2799?source=collection_archive---------7-----------------------

如果你是一个使用 Python 的分析师,你的面包和黄油可能由 matplotlib、pandas、numpy 和 sklearn 组成。在这篇博客中,我将讲述使用 matplotlib 绘图的基础知识。所有的 Jupyter 笔记本都在这里:
https://github . com/snaz rul 1/PyRevolution/tree/master/matplotlib

介绍

图形和轴

2D 策划

三维绘图

数据科学的 Python 基础

原文:https://towardsdatascience.com/python-basics-for-data-science-6a6c987f2755?source=collection_archive---------1-----------------------

Source: https://www.quora.com/Can-you-suggest-some-good-books-websites-for-learning-Python-for-a-layman

Python 数据类型

在 Python 中,我们有许多数据类型。最常见的有 float(浮点)、int(整数)、str(字符串)、bool(布尔)、list、dict(字典)。

  • 浮点数-用于实数。
  • int——用于整数。
  • str -用于文本。我们可以用单引号'value',双引号"value",或者三引号"""value"""来定义字符串。用三重引号括起来的字符串可以在多行上,新行将包含在变量值中。它们也用于编写函数文档。
  • bool -用于真值。用于对数据执行过滤操作。
  • list -用于存储值的集合。
  • dict -用来存储一个键值对。

我们可以使用type(variable_name)函数来检查特定变量的类型。Python 中的运算符根据变量的类型有不同的行为,并且每种类型都有不同的内置方法。

这里我们可以看一些用 Python 创建浮点、整数、字符串和布尔值的例子。

Python 列表

Python 列表是一种基本的序列类型。我们可以使用这种类型来存储值的集合。一个列表可以包含任何类型的值。一个列表可能包含另一个值的嵌套列表。这并不常用,但是您可以拥有一个混合了 Python 类型的列表。您可以使用方括号创建一个新的,如下所示:

fruits = ["pineapple", "apple", "lemon", "strawberry", "orange", "kiwi"]

子集列表

您可以使用索引从列表中获取一个或多个元素。在 Python 中,索引从0.开始,因此列表中的第一个元素将有一个索引0。我们也可以使用负索引来访问元素。列表中的最后一个元素将有一个索引-1,最后一个元素之前的元素将有一个索引-2,依此类推。Python 中还有一个叫做列表切片的东西,可以用来从一个列表中获取多个元素。我们可以这样用:sliceable[start_index:end_index:step].

  • start_index是切片的起始索引,该索引处的元素将包含在结果中,默认值为0
  • end_index是切片的结束索引,该索引处的元素将不包含在结果中,默认值为length of the list。此外,如果步长为负,默认值可以是- length of the list -1。如果跳过这一步,您将获得从开始索引到结尾的所有元素。
  • step是指数增加的量,
    默认值为1。如果我们为步长设置一个负值,我们将向后移动。

列表操作

  • 我们可以使用append方法或plus operator向列表中添加一个或多个元素。如果在两个列表上使用加号运算符,Python 将给出两个列表内容的新列表。
  • 我们可以使用已经用于索引和列表切片的方括号将一个或多个元素更改为 list。
  • 我们可以用remove(value)方法从列表中删除一个元素。此方法将删除带有传递值的列表的第一个元素。

理解 Python 中列表的幕后工作方式很重要。当你创建一个新的列表my_list时,你将列表存储在你的计算机内存中,列表的地址存储在my_list变量中。变量my_list不包含列表中的元素。它包含对列表的引用。如果我们像这样复制一个只有等号的列表my_list_copy = my_list,你将在my_list_copy变量中复制引用,而不是列表值。所以,如果你想复制实际值,你可以使用list(my_list)函数或切片[:]

Python 词典

字典用于存储键值对。当你想用唯一键索引你的值时,它们会很有帮助。在 Python 中,你可以使用花括号创建一个字典。此外,键和值由冒号分隔。如果我们想得到给定键的值,我们可以这样做:our_dict[key]

字典与列表

让我们看一个例子,将列表和字典进行比较。假设我们有一些电影,你想为它们存储收视率。此外,我们希望通过电影名称快速访问电影的分级。我们可以通过使用两个列表或一本字典来做到这一点。在示例中,movies.index(“Ex Machina”)代码返回“ex 玛奇纳”电影的索引。

Movie rating using lists.

Movie ratings using a dictionary.

在这种情况下,使用字典是一种更直观和方便的方式来表示评级。

字典操作

我们可以添加更新从我们的字典中删除数据。当我们想要添加或更新数据时,我们可以简单地使用这个代码our_dict[key] = value。当我们想要删除一个键-值对时,我们这样做del(our_dict[key])

我们还可以像这样检查给定的键是否在我们的字典中:key in our_dict

功能

函数是解决特定任务的一段可重用代码。我们可以像这样使用def关键字来编写函数:

但是 Python 中有很多内置函数,比如max(iterable [, key]),min(iterable [, key])type(object)round(number [, ndigits])等。因此,在许多情况下,当我们需要一个函数来解决一个给定的任务时,我们可以研究一个内置的函数来解决这个任务或者一个 Python 包来解决这个问题。我们不必“多此一举”。

大多数函数接受一些输入并返回一些输出。这些函数有参数,Python 将函数调用中传递的输入与参数匹配。如果一个参数用方括号括起来,那么它就是可选的。

我们可以使用函数help([object])?function_name来查看任何函数的文档。如果我们使用 Jupyter Notebook,help函数将显示当前单元格中的文档,而第二个选项将显示页面中的文档。

方法

我们已经看到,我们有字符串,浮点,整数,布尔,等等。在 Python 中。这些数据结构的每一个都是一个对象。方法是根据对象类型对给定对象可用的函数。因此,每个对象都有一个特定的类型和一组依赖于该类型的方法。

不同类型的对象可以有相同名称的方法。根据对象的类型,方法有不同的行为。

小心!一些方法可以改变它们被调用的对象。例如,在列表类型上调用的append()方法。

包装

模块是包含 Python 定义和语句的文件。模块指定了解决特定问题的函数、方法和新的 Python 类型。

包是目录中模块的集合。Python 有许多可用的包,涵盖了不同的问题。比如“NumPy”、“matplotlib”、“seaborn”、“scikit-learn”都是非常著名的数据科学包。

  • “NumPy”用于高效地处理数组
  • “matplotlib”和“seaborn”是用于数据可视化的流行库
  • “scikit-learn”是一个强大的机器学习库

默认情况下,Python 中有一些可用的包,但也有很多我们需要但默认情况下没有的包。如果我们想使用某个包,我们必须已经安装了它,或者只是使用 pip(Python 的包维护系统)来安装它。

然而,还有一种东西叫做“蟒蛇”。

Anaconda 发行版是一个免费的、易于安装的包管理器、环境管理器和 Python 发行版,包含 1,000 多个开源包,并有免费的社区支持。

所以,如果你不想安装很多包,我会推荐你使用“Anaconda”。这个发行版中有这么多有用的包。

导入报表

一旦安装了所需的包,就可以将它们导入到 Python 文件中。我们可以从中导入整个包、子模块或特定功能。此外,我们可以为包添加别名。从下面的例子中,我们可以看到导入语句的不同方式。

Simple Import Statement

Import statement With an Alias

Import Submodule From a Package With an Alias

Import Only One Function From a Package

我们也可以做这样的事情from numpy import *。这里的星号表示从该模块导入所有内容。这个 import 语句在当前名称空间中创建对由numpy模块定义的所有公共对象的引用。换句话说,我们可以使用numpy中所有可用的函数,只使用不带前缀的名字。例如,现在我们可以使用 NumPy 的绝对函数,如absolute()而不是numpy.absolute()
但是,我不建议您使用它,因为:

  • 如果我们像那样从一些模块中导入所有的函数,那么当前的名称空间将会充满如此多的函数,如果有人查看我们的代码,他或她可能会搞不清哪个包是特定的函数。
  • 如果两个模块有一个同名的函数,第二个导入将覆盖第一个的函数。

NumPy

NumPy 是使用 Python 进行科学计算的基础包。它非常快而且容易使用。这个软件包帮助我们逐元素地进行计算。

常规的 Python 列表不知道如何对元素进行操作。当然,我们可以使用 Python 列表,但是它们很慢,并且我们需要更多的代码来实现想要的结果。在大多数情况下,更好的决定是使用NumPy

与常规 Python 列表不同,NumPy 数组总是只有一种类型。如果我们将不同类型的数组传递给np.array(),我们可以使用参数dtype选择想要的类型。如果未给定此参数,则类型将被确定为保存对象所需的最小类型。

NumPy Array — Type Converting

NumPy 数组自带属性和方法。还记得 Python 中的操作符对不同的数据类型有不同的行为吗?在 NumPy 中,操作符的行为是基于元素的。

Operators on NumPy Array

如果我们检查 NumPy 数组的类型,结果将是numpy.ndarray。Ndarray 表示 n 维数组。在上面的例子中,我们使用了一维数组,但是没有什么可以阻止我们制作 2 维、3 维、4 维或更多维的数组。我们可以在一个数组上做子集化,与这个数组的维数无关。我将给你们展示一些二维数组的例子。

Subsetting 2-dimensional arrays

如果我们想知道数组有多少个维度,每个维度有多少个元素,我们可以使用shape属性。对于二维数组,元组的第一个元素是行数,第二个元素是列数。

NumPy Shape Attribute

基本统计

分析数据的第一步是熟悉数据。NumPy 有很多方法可以帮助我们做到这一点。我们将看到一些对数据进行统计的基本方法。

  • np.mean() -返回算术平均值(元素之和除以元素长度)。
  • np.median() -返回中间值(传递的数组的排序副本的中间值,如果数组的长度是偶数-将计算两个中间值的平均值)
  • np.corrcoef() -返回一个相关矩阵。当我们想知道数据集中的两个变量之间,或者换句话说,两个长度相同的数组之间,是否存在相关性时,这个函数非常有用。
  • np.std() -返回标准偏差

Generating Basic Statistics using NumPy

从上面的例子中,我们可以看到学习时间和成绩之间有很高的相关性。
同样,我们可以看到:

  • 学习时间的平均值为 4.6 小时
  • 学习时间的中位数是 4.0
  • 学习时间的标准偏差是 3.2

NumPy 也有一些基本的函数,如np.sort()np.sum(),它们也存在于基本的 Python 列表中。这里需要注意的一点是,NumPy 在数组中强制使用单一类型,这样可以加快计算速度。

练习

我已经准备了一些练习,包括子集,元素操作和基本统计。如果你愿意,你可以试着解决它们。

  • 子集化 Python 列表
  • 子集化二维数组
  • NumPy 元素式运算
  • NumPy 基本统计

互动版

这里的是在 Deepnote (云托管 Jupyter 笔记本平台)上传的这篇文章的交互版本。请随意查看并使用示例。

我的其他博客文章

  • Jupyter 笔记本快捷键。
  • Python 基础:迭代和循环
  • Python 基础:列表理解
  • Python 数据科学:Matplotlib 数据可视化简介
  • 使用 Python 的数据科学:使用 pandas 加载、子集化和过滤数据简介
  • 文本自然语言处理简介

商务化人际关系网

这是我在 LinkedIn 上的简介,如果你想和我联系的话。我将很高兴与你联系在一起。

最后的话

谢谢你的阅读。如果你喜欢这个帖子,请按住拍手键分享给你的朋友。另外,我很高兴听到你的反馈。如果你想在我写新博客时得到通知,你可以订阅我的简讯。

Python 基础:迭代、可迭代对象、迭代器和循环

原文:https://towardsdatascience.com/python-basics-iteration-and-looping-6ca63b30835c?source=collection_archive---------0-----------------------

Source: https://www.quora.com/Can-you-suggest-some-good-books-websites-for-learning-Python-for-a-layman

看完这篇博文,你就知道了:

  • Python 中的迭代如何工作幕后
  • 什么是迭代器迭代器以及如何创建它们
  • 什么是迭代器协议
  • 什么是懒评
  • 什么是发生器函数发生器表达式

Python 的 for 循环

Python 没有传统的for循环。让我们来看一段伪代码,看看传统的 for 循环在许多其他编程语言中是什么样子的。

A Pseudocode of for loop

  • 在进入循环之前,初始化器部分只执行一次。
  • 条件段必须是一个布尔表达式。如果该表达式的计算结果为 True,则执行下一次循环迭代。
  • 迭代器部分定义了每次迭代后发生的事情。

现在,让我们看看如何用 JavaScript 编写传统的 for 循环。

Simple For Loop in JavaScript

输出:

10
12
15
18
20

许多其他编程语言都有这种 for 循环,但是 Python 没有。不过, Python 有个叫**for** 循环的东西,但是它的工作方式就像是 foreach 循环

Simple For Loop in Python

输出:

10
12
15
18
20

从上面的例子中,我们可以看到在 Python 的for循环中,我们没有任何我们之前见过的部分。没有初始化、条件或迭代器部分。

可重复的

iterable 是一个能够让逐个返回成员 的对象。换句话说,iterable 是可以用 Python 中的for循环遍历的任何东西。

顺序

序列是非常常见的类型可迭代。内置序列类型的一些示例有 列表字符串元组

Lists, Tuples, and Strings in Python

它们通过__getitem()__特殊方法(索引)使用整数索引支持高效的元素访问,并定义一个返回序列的长度__length()__方法。

Element access using indices.

输出:

10
blueberry
❤

同样,我们可以对它们使用切片技术。如果你不知道什么是切片,可以在我讲解的时候查一下我之前文章的一篇。切片技术的解释在“子集列表”一节中。

Slicing Sequences.

输出:

[10, 12]
('pineapple', 'blueberry')
love Python ❤️

其他可重复项目

Python 中的很多东西都是可迭代的,但并不都是序列。字典文件对象集合生成器都是可迭代的,但没有一个是序列。

Sets, Dictionaries, Files, and Generators.

Python 的 for 循环不使用索引

让我们考虑一下如何在不使用 Python 中的for循环的情况下循环遍历一个 iterable。我们中的一些人可能认为我们可以使用一个while循环并生成索引来实现这一点。

输出:

1
2
3
4
5

这种方法似乎对列表和其他序列对象非常有效。非序列对象呢?他们不支持索引,所以这种方法对他们不适用。

输出:

**--------------------------------------------------------------------**
**TypeError**                          Traceback (most recent call last)
**<ipython-input-22-af1fab82d68f>** in <module>**()**2 numbers **=** **{1,** **2,** **3,** **4,** **5,** **6,** **7,** **8,** **9,** **10}**3 **while** index **<** len**(**numbers**):**
**----> 4** print**(**numbers**[**index**])**5     index **+=** **1****TypeError**: 'set' object does not support indexing

嗯,但是 Python 的 for 循环是如何处理这些可重复项的呢?我们可以看到它适用于集合。

Iterate over a set.

输出:

1
2
3
4
5

迭代器

迭代器是一个表示数据流的对象。您可以通过将iter()内置函数应用于可迭代对象来创建迭代器对象。

输出:

<list_iterator object at 0x000001DBCEC33B70>
<tuple_iterator object at 0x000001DBCEC33B00>
<str_iterator object at 0x000001DBCEC33C18>

你可以使用一个迭代器来手动循环它来自的可迭代。迭代器向内置函数next()的重复传递会返回中的连续项。一旦你消费了迭代器中的一个条目,它就消失了。当没有更多的数据可用时,产生一个StopIteration异常。

输出:

10
20
30**--------------------------------------------------------------------**
**StopIteration**                      Traceback (most recent call last)
**<ipython-input-14-fd36f9d8809f>** in <module>**()**4 print**(**next**(**iterator**))**5 print**(**next**(**iterator**))**
**----> 6** print**(**next**(**iterator**))****StopIteration**:

在幕后,Python 的for循环正在使用迭代器。

理解 Python 的 for 循环是如何工作的

Source: https://www.incredible-web.com/blog/performance-of-for-loops-with-javascript/

现在,我们知道了什么是 iterables 和迭代器,以及如何使用它们。我们可以尝试定义一个循环遍历 iterable 的函数,而不使用for循环。

为此,我们需要:

  • 从给定的可迭代对象创建一个迭代器
  • 从迭代器中反复获取下一个项目
  • 执行想要的动作
  • 停止循环,如果我们在尝试获取下一个项目时遇到了Stop iteration异常

Custom For Loop in Python. Source: https://opensource.com/article/18/3/loop-better-deeper-look-iteration-python

让我们试着用一组数字和print内置函数来使用这个函数。

Custom For Loop in Python - Usage.

输出:

1
2
3
4
5

我们可以看到,我们定义的函数非常适合集合,集合不是序列。这一次我们可以通过任何可迭代的并且它将工作。在幕后,Python 中所有形式的循环遍历 iterables 都是这样工作的。

迭代器协议

迭代器对象需要支持以下两种方法,它们共同构成迭代器协议:

  • 迭代器。iter()
    返回迭代器对象本身。这是允许容器(也称为集合)和迭代器与forin语句一起使用所必需的。
  • 迭代器。next()
    从容器中返回下一个项目。如果没有更多的项目,引发 StopIteration 异常。

从上面的方法描述中,我们看到我们可以在迭代器上循环。所以迭代器也是可迭代的。

记住,当我们将iter()函数应用于一个可迭代对象时,我们得到了一个迭代器。如果我们在迭代器上调用iter()函数,它总是返回给我们自己

输出:

True
100
200
300

关于迭代器的附加注释

这听起来可能有点令人困惑。但是,如果第一次的事情没有全部理解,也不用担心。让我们回顾一下!

  • 一个可迭代的是你可以循环遍历的东西。
  • 一个迭代器是一个代表数据流的对象。它在一个 iterable 上进行迭代

此外,在 Python 中,迭代器也是可迭代的,充当它们自己的迭代器

然而,区别在于迭代器没有一些可迭代的特性。它们没有长度并且不能被转位

例子

Iterators No Length Error

输出:

**--------------------------------------------------------------------**
**TypeError**                          Traceback (most recent call last)
**<ipython-input-15-778b5f9befc3>** in <module>**()**1 numbers **=** **[100,** **200,** **300]**2 iterator **=** iter**(**numbers**)**
**----> 3** print**(**len**(**iterator**))****TypeError**: object of type 'list_iterator' has no len()

Indexing Iterators Error

输出:

**--------------------------------------------------------------------**
**TypeError**                          Traceback (most recent call last)
**<ipython-input-16-64c378cb8a99>** in <module>**()**1 numbers **=** **[100,** **200,** **300]**2 iterator **=** iter**(**numbers**)**
**----> 3** print**(**iterator**[0])****TypeError**: 'list_iterator' object is not subscriptable

迭代器很懒

Source: https://giphy.com/gifs/animal-lazy-spirit-gdUxfKtxSxqtq

迭代器允许我们使用和创建惰性可迭代对象,它们不做任何工作,直到我们向它们请求下一项。

来源:https://open source . com/article/18/3/loop-better-deep-look-iteration-python

由于它们的懒惰,迭代器可以帮助我们处理无限长的迭代器。在某些情况下,我们甚至不能在内存中存储所有的信息,所以我们可以使用迭代器,它可以在我们每次请求时给出下一项。迭代器可以为我们节省大量内存CPU 时间

这种做法叫做 懒评

迭代器无处不在

我们已经看到了一些迭代器的例子。此外,Python 有许多内置的迭代器类。例如,enumeratereversed对象是迭代器。

列举例子

输出:

<class 'enumerate'>
(0, 'apple')

反例

输出:

<class 'reversed'>
blueberry

Python 的zipmapfiler对象也是迭代器。

Zip 示例

输出:

<class 'zip'>
(1, 1)
(2, 4)

地图示例

输出:

<class 'map'>
1
4

过滤器示例

输出:

<class 'filter'>
3

而且 Python 中的文件对象也是迭代器。

输出:

<class '_io.TextIOWrapper'>
This is the first line.This is the second line.This is the third line.

我们还可以使用items()方法迭代 Python 字典键值对

输出:

<class 'dict_items'>
name Ventsislav
age 24

很多人用 Python 解决数据科学问题。在某些情况下,您处理的数据可能非常大。在这种情况下,我们无法将所有数据加载到内存中。

解决方案是数据分块加载,然后对每个块执行所需的操作,丢弃该块并加载下一个数据块。换句话说我们需要创建一个迭代器。我们可以通过使用熊猫中的read_csv函数来实现这一点。我们只需要指定块大小

大型数据集示例

在这个例子中,我们将看到一个名为“鸢尾物种的小数据集的想法,但同样的概念也适用于非常大的数据集。我已经更改了栏目名称,你可以在这里找到我的版本。

输出:

{'Iris-setosa': 50, 'Iris-versicolor': 50, 'Iris-virginica': 50}

Python 标准库中和第三方库中有许多迭代器对象。

通过定义类创建自定义迭代器

在某些情况下,我们可能想要创建一个自定义迭代器。我们可以通过定义一个具有 initnextiter 方法的类来做到这一点。

让我们试着创建一个自定义迭代器类,生成最小值和最大值之间的数字。

输出:

<class '__main__.generate_numbers'>
40
41
42

我们可以看到这是可行的。然而,使用生成器函数生成器表达式来创建定制迭代器要容易得多。

生成器函数和生成器表达式

通常,当我们想要创建一个自定义迭代器时,我们使用一个生成器函数生成器表达式。它们使用起来更简单,并且需要更少的 T21 代码来达到同样的效果。

发电机功能

让我们从 Python 文档中看看什么是生成器函数。

返回一个生成器迭代器的函数。它看起来像一个普通的函数,除了它包含用于产生一系列值[**yield**](https://docs.python.org/3.7/reference/simple_stmts.html#yield) 表达式,这些值可在 for 循环中使用,或者可以用[**next(**](https://docs.python.org/3.7/library/functions.html#next)**)** 函数一次检索一个。

来源:https://docs.python.org/3.7/glossary.html#term-generator

现在,我们可以尝试使用生成器函数来重新创建我们的自定义迭代器。

输出:

<class 'generator'>
10
11
12

产量表达式是将生成函数与普通函数分开的东西。这个表达式帮助我们利用迭代器的惰性

每个[yield](https://docs.python.org/3.7/reference/simple_stmts.html#yield)会暂时挂起处理,记住位置执行状态(包括局部变量和挂起的 try 语句)。当生成器迭代器恢复时,它从停止的地方继续(与每次调用都从头开始的函数相反)。

来源:https://docs . python . org/3.7/glossary . html # term-generator-iterator

生成器表达式

生成器表达式非常类似于****列表理解。就像列表理解一样,一般表达都是简洁。在大多数情况下,它们是用一行代码编写的。

返回迭代器的表达式。它看起来像一个普通表达式,后跟一个定义循环变量、范围的[for](https://docs.python.org/3.7/reference/compound_stmts.html#for)表达式和一个可选的[if](https://docs.python.org/3.7/reference/compound_stmts.html#if)表达式。

来源:https://docs . python . org/3.7/glossary . html # term-generator-expression

通式为: (iterable 中迭代器变量的输出表达式)

让我们看看如何定义一个简单的生成器表达式。

输出:

<class 'generator'>
1
4
9

我们还可以在的 iterable 上添加一个条件表达式。我们可以这样做:

输出:

<class 'generator'>
[4, 16]

它们可以通过多个条件表达式 对****可迭代进行更复杂的过滤。

输出:

<class 'generator'>
[16]

同样,我们可以在的输出表达式上添加一个 if-else 子句 ,如下所示:

输出:

<class 'generator'>
['odd', 'even', 'odd', 'even', 'odd']

要点/总结

  • 一个可迭代的是你可以循环遍历的东西。
  • 序列可迭代的一种非常常见的类型。
  • Python 中的很多东西都是可迭代的,但并不都是序列。
  • 一个迭代器是一个代表数据流的对象。它对一个 iterable 进行迭代。您可以使用迭代器来获取的下一个值或对其进行循环。一旦,你在一个迭代器上循环,就没有流值了。
  • 迭代器使用惰性评估方法。
  • Python 中很多内置的类都是迭代器
  • 生成器函数是返回迭代器的函数。
  • 一个生成器表达式是返回一个迭代器的表达式。

接下来读什么?

  • 你可以看看 itertools 库。这个库包括创建迭代器的函数,用于有效的循环。
  • 你也可以阅读文档或者阅读/观看下面的一些资源。
  • 我的下一篇文章是关于 Python 中的列表理解。

资源

  • https://open source . com/article/18/3/loop-better-deep-look-iteration-python
  • https://www.youtube.com/watch?v=V2PkkMS2Ack
  • https://www . data camp . com/community/tutorials/python-iterator-tutorial
  • https://www . data camp . com/courses/python-data-science-toolbox-part-2
  • https://en.wikipedia.org/wiki/Foreach_loop
  • https://docs.python.org/3.7/glossary.html#term-sequence
  • https://docs.python.org/3.7/glossary.html#term-generator
  • https://docs . python . org/3.7/library/STD types . html # iterator-types
  • https://docs.python.org/3/howto/functional.html?#iterators

我的其他博客文章

你也可以看看我以前的博文。

  • Jupyter 笔记本快捷键
  • 面向数据科学的 Python 基础知识
  • Python 基础:列表理解
  • Python 数据科学:Matplotlib 数据可视化简介
  • 使用 Python 的数据科学:使用 pandas 加载、子集化和过滤数据简介
  • [文本自然语言处理导论](http://Introduction to Natural Language Processing for Text)

时事通讯

如果你想在我发表新的博客文章时得到通知,你可以订阅我的简讯。

商务化人际关系网

这是我在 LinkedIn 上的简介,如果你想和我联系的话。我将很高兴与你联系在一起。

最后的话

谢谢你的阅读。我希望你喜欢这篇文章。如果你喜欢,请按住拍手键,分享给你的朋友。我很高兴听到你的反馈。如果你有什么问题,尽管问。😉

Python 基础:列表理解

原文:https://towardsdatascience.com/python-basics-list-comprehensions-631278f22c40?source=collection_archive---------1-----------------------

阅读本文后,您将了解到:

  • Python 中的列表理解是什么
  • 什么是集合 理解字典理解

什么是列表理解?

List comprehensions 为我们提供了一个简单的方法来创建一个基于一些 iterable 的列表。在创建过程中,来自 iterable 的元素可以有条件地包含在新列表中,并根据需要转换

一个可迭代你可以在上循环的东西。如果你想要更详细的解释,你可以阅读我之前的博客文章。

列表理解的组成部分包括:

  • 输出表达式 ( 可选)
  • 可迭代
  • 迭代器变量,代表可迭代对象的成员

例子

输出:

[1, 4, 9, 16, 25]

我们还可以创建更高级的列表理解,其中包括在 iterable 上的条件语句

例子

输出:

[9, 16, 25]

列表理解 vs 循环

列表理解在计算上以及在编码空间和时间上都比循环for更有效。通常,它们是用单行代码编写的。****

让我们看看使用一个for循环得到与上一个例子相同的结果还需要多少空间。

我们可以清楚地看到,上面的列表理解要容易得多。但是,请记住:

每个列表理解都可以重写为 for 循环,但不是每个 for 循环都可以重写为列表理解。

来源:https://trey hunner . com/2015/12/python-list-comprehensions-now-in-color/

计算速度呢?我们可以使用timeit库来比较for循环的速度和列表理解的速度。我们还可以使用number参数传递执行的数量。我们将这个参数设置为 100 万。

输出:

**6.255051373276501
3.7140220287915326**

我已经在我的机器上运行过了,所以你可以得到不同的结果。然而,列表理解的实现在所有情况下都会更快。

列表理解与映射和过滤

列表理解是从函数式编程语言 Haskell 借用来的简洁符号。我们可以把它们看作是filtermap函数的语法糖。

我们已经看到,列表理解可以很好地替代for循环,因为它们更紧凑、更快。

λ函数

Lambda 函数是小型匿名函数。它们可以有任意数量的参数,但只能有一个表达式。

大多数情况下,lambda 函数是作为参数传递给函数的,这些函数需要一个函数对象作为它们的参数之一,比如mapfilter

地图功能

map 函数返回一个迭代器,该迭代器将函数应用于 iterable 的每一项,并产生结果。我们来对比一下列表理解。

输出:

**[1, 4, 9, 16, 25]
[1, 4, 9, 16, 25]**

过滤功能

filter 函数从传递的 函数 返回 true 的 iterable 的元素中构造一个迭代器。同样,让我们比较一下过滤函数和列表理解。

输出:

**[2, 4]
[2, 4]**

更复杂的列表理解

此外,当我们创建一个列表理解时,我们可以在 iterable 上有许多条件语句

输出:

**[6, 18]**

而且,我们还可以在输出表达式上有一个 if-else 子句

输出:

**['small', 'big']**

可读性

我们可以看到一些列表理解可能非常复杂,很难读懂。Python 允许在括号和大括号之间换行。我们可以利用这一点使我们复杂的理解更具可读性。

例如,我们可以把上一个例子转换成这样:

输出:

**['small', 'big']**

然而,要小心列表理解,在某些情况下使用for循环更好。如果你的代码不可读,最好使用 for 循环。

嵌套 For 循环

在某些情况下,我们需要嵌套的for循环来完成一些任务。在这种情况下,我们也可以使用列表理解来达到同样的结果。

假设我们有一个矩阵,我们想把它展平。我们可以像这样用两个for循环轻松做到这一点:

输出:

**[1, 2, 3, 4, 5, 6, 7, 8, 9]**

我们可以使用列表理解来达到同样的结果。
提示:for 子句顺序与原 for 循环中的保持不变。

输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

嵌套列表理解

在其他情况下,我们可能需要创建一个矩阵。我们可以用嵌套列表理解做到这一点。这听起来有点疯狂,但概念很简单。

一个列表理解返回一个列表,对吗?因此,如果我们将一个列表理解放在另一个列表理解的输出表达式中,我们将得到一个矩阵作为结果。

输出:

[[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]

[range](https://docs.python.org/3/library/stdtypes.html#range)类型表示不可变的数字序列,通常用于在[for](https://docs.python.org/3/reference/compound_stmts.html#for)循环中循环特定的次数

来源:https://docs.python.org/3/library/stdtypes.html#ranges

其他理解

在 Python 中,我们还有字典理解集合理解。我们看到的所有原则对于这些理解也是一样的。我们只需要知道一些非常小的细节就可以创建一个字典或一套理解。

词典释义

为了创建字典理解,我们只需要将括号[]改为花括号{}。另外,在输出表达式中,我们需要用冒号:分隔键和值。

输出:

{'beer': 2.0, 'fish': 5.0, 'apple': 1.0}

集合理解

为了创建一个集合理解,我们只需要将括号[]改为花括号{}

输出:

{0, 1, 100, 144, 400, 900}

生成器表达式

在这里,我只想提一下,Python 还有一个叫生成器表达式的东西。它们与列表理解非常相似。不同的是,它们使用圆括号().并且,它们不在内存中存储列表。他们使用 懒评 手法。

如果你使用返回无限流或大量数据的迭代器,那么列表理解是没有用的。在这些情况下,生成器表达式更可取

来源:https://docs.python.org/3/howto/functional.html

如果你想了解更多关于生成器表达式的知识,你可以查看我在之前的博客文章。

摘要

  • ****列表理解为我们提供了一个简单的方法来创建一个基于一些可迭代的列表
  • 这种理解比在循环中使用 a 更加有效。
  • 我们可以在理解中使用条件语句。
  • 对于内置的mapfilter 函数,理解是一个很好的选择
  • 我们可以有嵌套的理解。
  • 在 Python 中,我们还有字典理解集合理解
  • 当我们处理大量数据的无限流时,生成器表达式更好。

资源

  • https://trey hunner . com/2015/12/python-list-comprehensions-now-in-color/
  • https://www . data camp . com/community/tutorials/python-list-comprehension
  • https://www.w3schools.com/python/python_lambda.asp
  • https://talkai . blog/2018/08/29/python IC-better-if-list-comprehension-else-map-and-filter/
  • https://docs.python.org/3/library/functions.htmlT40https://docs.python.org/3/howto/functional.html

我的其他博客文章

你也可以看看我以前的博文。

  • Jupyter 笔记本快捷键
  • 数据科学的 Python 基础知识
  • Python 基础:迭代、可迭代、迭代器和循环
  • Python 数据科学:Matplotlib 数据可视化简介
  • 使用 Python 的数据科学:使用 pandas 加载、子集化和过滤数据简介
  • [文本自然语言处理导论](http://Introduction to Natural Language Processing for Text)

时事通讯

如果你想在我发表新的博客文章时得到通知,你可以订阅我的简讯。

商务化人际关系网

这是我在 LinkedIn 上的简介,如果你想和我联系的话。我将很高兴与你联系在一起。

最后的话

谢谢你的阅读。我希望你喜欢这篇文章。如果你喜欢,请按住拍手键,分享给你的朋友。我很高兴听到你的反馈。如果你有什么问题,尽管问。😉

用于识别季节性客户的 Python 代码

原文:https://towardsdatascience.com/python-code-for-identifying-seasonal-customers-4bd36dc7fcda?source=collection_archive---------5-----------------------

我以前写过如何使用时间序列来识别数据库中具有季节性使用模式的客户。如果你想详细了解,你可以在这里找到文章。

如果您想长话短说:为了识别具有季节性使用模式的客户,我采用了按月汇总的 customer_id、月、年和使用数据,并按 id、年和月排序。我们只能评估与我们在一起至少 2 年的客户的季节性,以允许算法识别模式。所以数据(完全虚构,只是为了说明)看起来像这样:

您会注意到数据中缺少了五月、八月、九月和十月。这意味着该客户在那几个月没有任何使用。因此,第一项任务是填补数据集中缺失的零。我把数据库里的数据拉进来,命名为“原创”。这里我没有提供连接数据库的代码,因为我们使用 Netezza SQL。

代码如下(有些缩进对于较长的行是不正确的,抱歉!)🙂

import pandas as pa 
import numpy as np ## Outfile is just because we're going to export our results as a .csv to save them. outfile = '[put your file path here].csv' ## Headings in the .csv that I'm going to output filledIn = pa.DataFrame(columns=['customer_id','yr','mnth','usage']) ##original was just the name of my dataframe with data grouped = original.groupby(by='customer_id') 
def yearmonth_to_justmonth(year, month): return year * 12 + month - 1 ##Defining a function to fill in the zeros. def fillInForOwner(group): min = group.head(1).iloc[0] max = group.tail(1).iloc[0]       minMonths = yearmonth_to_justmonth(min.yr, min.mnth) maxMonths = yearmonth_to_justmonth(max.yr, max.mnth)filled_index = pa.Index(np.arange(minMonths, maxMonths, 1),name="filled_months") group['months'] = group.yr * 12 + group.mnth - 1 group = group.set_index('months') group = group.reindex(filled_index) group.customer_id = min.customer_id group.yr = group.index // 12 group.mnth = group.index % 12 + 1group.usage = np.where(group.usage.isnull(), 0,group.usage).astype(int) return group filledIn = grouped.apply(fillInForOwner) 
newIndex = pa.Index(np.arange(filledIn.customer_id.count())) ## Printing out the results to a .csv 
filledIn = filledIn.set_index(newIndex) 
filledIn.to_csv(outfile) ## I also print results on the screen 
print(filledIn)

接下来,我选择在 Python 中为时间序列部分运行 R。实际上,我遇到了一个值得一提的小问题。我在我的计算机上安装了 64 位和 32 位版本的 R,并指向还没有安装我的所有包的 R 版本(来自 Python)。尴尬的真相:我手动将文件从一个文件夹复制粘贴到另一个文件夹。我确信有一种更“正确”的方法,但是将它们复制并粘贴到目录中正确的文件夹是可行的。

还有一个小问题,值得一提的是,用 Python 运行 R 代码并不是我尝试的第一种方法。您实际上可以使用 Python 语言来运行 R 代码,但是我很难做到这一点,所以我选择了 rpy2 路线。

这里我导入 rpy2 来利用 Python 中的 R 代码。这些也是我需要的所有库。

import rpy2 as r from rpy2.robjects.packages import importr from rpy2.robjects import r, pandas2ri, globalenvpandas2ri.activate() base = importr('base') 
colorspace = importr('colorspace') 
forecast = importr('forecast') 
times = importr('timeSeries') 
stats = importr('stats')

接下来,我逐一查看了每位顾客。我会找到他们的开始月份/年份和结束月份/年份,并为每个客户创建一个时间序列对象。我包含了一个 try/except 语句,因为我最初尝试在没有 try/except 语句的情况下运行它,在它已经运行了几个小时之后,它被一个客户卡住了,不太理想。

在创建了时间序列对象之后,我简单地询问 R 模型中是否有季节性成分,并打印出客户 id 以及它们是否是季节性的。

 ##Again, this is just for saving your results to a .csv 
outfile = '[put your file path here].csv' 
seasonal_output = pa.DataFrame(columns=['customer_id', 'seasonal']) ### Now we're going to loop through our customers 
for customerid, dataForCustomer in filledIn.groupby(by=['customer_id']): startYear = dataForCustomer.head(1).iloc[0].yr startMonth = dataForCustomer.head(1).iloc[0].mnth endYear = dataForCustomer.tail(1).iloc[0].yr endMonth = dataForCustomer.tail(1).iloc[0].mnth #Creating a time series object customerTS = stats.ts(dataForOwner.SENDS.astype(int),start=base.c(startYear,startMonth), end=base.c(endYear, endMonth), frequency=12)r.assign('customerTS', customerTS) ##Here comes the R code piece try:  seasonal = r(''' fit<-tbats(customerTS, seasonal.periods = 12, use.parallel= TRUE) fit$seasonal ''') except: seasonal = 1 seasonal_output = seasonal_output.append({'customer_id':customerid, 'seasonal': seasonal}, ignore_index=True) print(f' {customerid} | {seasonal} ') print(seasonal_output) 
seasonal_output.to_csv(outfile)

这个输出将成为我正在进行的聚类分析的一个特征。我还将做一些工作来确定每个客户的最小和最大使用月数,并将其存储在数据库中。很快,市场营销将能够利用这一点来开展更加个性化的活动。

如果你想订阅我未来的文章,你可以在这里订阅。

原载于 2018 年 7 月 1 日【datamovesme.com】

如何设置 Python 数据科学环境—设置使用 Python 处理数据科学问题的 Anaconda 环境

原文:https://towardsdatascience.com/python-data-science-environment-setting-up-anaconda-environments-for-working-on-data-science-8b4bfbc3cd39?source=collection_archive---------2-----------------------

最初发表于【softwarejargon.com】 在我的博客上找到这篇文章的更新版本【https://softwarejargon.com/blog】

在本文中,我将解释并展示如何使用 python 和 Anaconda 以及 PyCharm 来建立一个 Python 数据科学环境,为使用最流行的 Python 库进行机器学习/数据科学的本地实验做好准备。

这篇文章主要针对 Mac 用户,但是,不要惊慌,我将对如何在 Windows 上实现相同的结果进行简短的评论。我自己两个都用,所以没有偏好。

要求—您应该熟悉以下主题:

  • 具备 bash 命令或命令行的基本知识(取决于操作系统,Mac 或 Windows)

将安装以下软件。

  • 蟒蛇
  • PyCharm(社区版)

下面是感兴趣的 Python 库。如果您有兴趣阅读更多内容,我提供了每个库文档的链接。

  • numpy
  • 熊猫
  • scikit-learn
  • matplotlib

安装 Anaconda

Anaconda 可以从这里下载。遵循安装说明。安装没有什么特别的,因此,如果你按照屏幕上的安装说明,一切都会好的。

安装 PyCharm

PyCharm 可以从这里下载。我推荐安装社区版的 PyCharm,因为它是免费的。

至于 Anaconda 安装,同样适用于 Pycharm 安装。安装软件时按照屏幕上的说明操作,一切都会好的。

使用 Conda CLI 创建环境

安装 Anaconda 后,打开一个终端窗口,键入conda并按回车键。如果你看到类似下图的东西,那么你已经成功安装了 Anaconda 和 Conda CLI。

Envs 文件夹的默认路径是/Users/<your user name>/anaconda/envs/,所有创建的环境都将放在这个文件夹中。

在创建一个新环境之前,我总是将 cd 放到 envs 文件夹中。所以如果你想继续 cd 到 envs 文件夹。执行以下命令。

cd /Users/<your user name>/anaconda/envs/

请记住,只有在默认目录下安装了 Anaconda,这种方法才有效。否则,导航到您的安装位置。

为了创建新的环境,请执行以下命令。

conda create --name TestEnv python=3

在我们可以在新环境中安装任何新的 python 库之前,我们需要激活该环境。要激活创建的环境,请执行以下命令。

conda activate TestEnv

接下来,我们要安装四个第三方 Python 库。为此,请执行以下命令。

conda install numpy pandas scikit-learn matplotlib

这应该会安装四个库 numpy、pandas、scikit-learn 和 matplotlib。就开始学习机器学习而言,这四个库应该会让你走得很远。

当库安装完成后,您可以通过启动 Python 控制台来检查一切是否正常。这是通过执行以下命令来实现的。

python

Python 控制台启动并运行后,对四个库分别执行以下命令并按 enter 键。

>>>import numpy 
>>>import pandas 
>>>import sklearn
>>>import matplotlib

如果库安装正确,您应该不会得到任何错误。

在 PyCharm 中创建项目

现在您已经安装了 Anaconda 并创建了一个环境。现在我们想使用 PyCharm 创建一个项目,并使用创建的环境执行 Python 代码。这里我假设您已经安装了 PyCharm。

首先,我们想创建一个文件夹,作为我们的项目文件夹。您可以在计算机上的任意位置创建该文件夹。我经常使用 Dropbox,因此,我所有的本地项目文件夹都是在/Users/<your user name>/Dropbox/project_folders/路径下创建的。

创建一个项目文件夹,例如,名为 ProjectTestEnv。

现在打开 PyCharm 点击打开。当 PyCharm 打开时,您应该会看到类似下图的内容。

浏览到最近创建的项目文件夹,然后单击打开。PyCharm 现在将开始一个新项目。

在 PyCharm 中为我们的项目设置解释器

现在,每次我们执行 Pycharm 项目中的代码时,我们都希望代码使用我们新创建的 Conda 环境,在那里我们已经安装了我们想要使用的库。

当 PyCharm 完成启动新项目时,导航到“py charm”->“Preferences”。

一个新窗口将会打开。选择“翻译”,点击右上角的图标,然后点击“添加…”

一个新窗口将会打开。在这里选择“虚拟环境”,然后单击“现有环境”,然后单击包含“…”的图标。一个新窗口将会打开。在这里,您必须导航到创建的环境,例如/Users/<your user name>/anaconda/envs/TestEnv/bin/python3。现在对所有三个打开的窗口按“确定”。PyCharm 现在应该将创建的环境设置为您的项目解释器。

仅此而已。现在,您可以使用 PyCharm 在项目文件夹中创建 python 文件,只需右键单击文件夹概述并添加新的 python 文件。然后,您可以执行项目文件夹中的任何 python 文件,方法是右键单击该文件并选择“Run ' '”

我发现最有用的 Conda 命令列表

conda create --name <my environment name> python=<python version>

该命令由两部分组成。第一部分conda create --name后面是您想要为您的环境指定的名称,它创建了 conda 环境。下一部分python=3指定您希望在环境中安装哪个版本的 python。通过执行conda create --name TestEnv python=2.7,conda CLI 将创建一个安装了 Python 2.7 的名为 TestEnv 的环境。

source activate <my environment name>

该命令激活特定的环境。如果我们已经创建了一个名为 TestEnv 的环境,我们可以通过执行下面的命令source activate TestEnv来激活这个环境。该命令在 Windows 上略有不同。在 Windows 上,你会写activate TestEnv

source deactivate

该命令停用环境。在 Windows 上也略有不同。在 Windows 上你会写deactivate

conda install <library name>

激活已创建的环境后,您可能需要安装额外的库,除非您可以使用预安装的核心 Python 库进行管理。但是,当您需要安装第三方库时,您将希望使用上面的 Conda CLI 命令。例如,在激活环境 TestEnv 之后,您需要安装 pandas 库,这是通过执行conda install pandas来完成的。这将安装最新的可用熊猫图书馆版本。

conda update <library name>

如果您在某个时候需要更新您已经安装的库,您可以通过使用上面的命令来完成。例如,您已经安装了 pandas 库,过一会儿,您需要将库更新到一个新的版本,这是通过执行conda update pandas来完成的。这将把熊猫图书馆更新到最新版本。

conda remove --name <my environment name> <library name>

当您想要从激活的环境中删除已安装的库时,可以使用此命令。例如,您已经创建了环境 TestEnv 并激活了该环境,此外,您还在活动环境中安装了库 pandas。现在你需要删除图书馆熊猫。这是通过执行conda remove --name TestEnv pandas完成的。

conda remove --name <my environment name> --all

当您需要删除已创建的环境及其安装的第三方库时,可以使用此命令。例如,在创建环境 TestEnv 并安装库 pandas 之后。为了删除这个环境及其安装的库,您可以执行conda remove --name TestEnv --all

conda update

如果需要将整个 Anaconda 安装更新到最新版本,可以执行上面的命令。

如果你有兴趣了解我更多。请访问我在 LinkedIn 上的个人简介【https://www.linkedin.com/in/vedranmarkulj/

感谢阅读。如果你对我将来写的关于机器学习和类似主题的帖子感兴趣,请在媒体和 LinkedIn 上关注我。更多文章即将发表。

Python 数据可视化工具

原文:https://towardsdatascience.com/python-data-visualization-tools-bf44c07452d9?source=collection_archive---------10-----------------------

Python 星期五:挑战#6

I wish I knew how to make this graph.

利用数据寻找相关性是一项很有价值的技能。但是能够将这些发现传达给其他不熟悉数据集的人也是非常有价值的。了解到这一点,我决定做一些谷歌搜索来找出我应该学习什么工具来展示我的数据项目。

我很快找到了这篇关于 Python 数据可视化库的博文,有几条引起了我的注意。

我想尝试的可视化工具列表

  • Seaborn
  • 散景
  • 臀的
  • geoplotlib
  • 闪光
  • missingno【这个我不能不演示,是口袋妖怪参考!]

我怎么能只选择其中一个呢?我不想只选择一个,但我认为 Seaborn 是一个给定的,因为它是基于 matplotlib 的,并且我已经学习了相当多的相关知识(感谢 Dataquest!).

我喜欢 geoplotlib 的想法,因为热图。我肯定会在未来的某个时候构建一个热图。我根本不在乎这是什么。我只想建立一个热图,并知道我做到了。

但是现在,它将会是 Seaborn

挑战:3 个问题

使用我一直在用的数据集

  1. 车重和 MPG 有关系吗?
  2. 气缸数量与 MPG 相关吗?
  3. 总马力和 MPG 有关系吗?

这些问题似乎是显而易见的,但我从未真正看到任何数据来支持这些概念。这就是它的乐趣所在。用数据支持一个想法,和一开始就有想法一样重要。

看看我的图表!

这里的是生成下图的代码的 github repo。line1.py、line2.py 和 line3.py 是图表,按它们在这里出现的顺序排列。

MPG 与重量

MPG vs Weight

汽车的重量和每加仑行驶的英里数之间有着非常紧密的联系。理所应当!移动更多的重量需要更多的能量!

MPG 与气缸数量的关系

MPG vs. Number of Cylinders

另一个真正可靠的关联!虽然有奇怪的异常在 38 分钟的标记。我想这可能是因为有一个不完整的数据集,或者是一个主要是 4 缸发动机的不平衡的数据集…但我还没有制作一个图表来检查这一点😄

MPG 与马力

MPG vs. Horsepower

这是我所期望的图表,但是这个图表在几个方面被搞乱了。趋势看起来是对的,但是我的 x-tick 标签顺序不对。我不确定为什么会这样,因为它用来制图的数据是正确排序的。这可能是因为 seaborn 在绘制线条时内置了一些“平均”功能。

我将不得不做更多的调查,但今晚我没有时间了。

我的一些“问题”

  1. 进口 Seaborn 有困难。首先,我将我在 seaborn.py 上工作的文件命名为😞哇,你不能进口那种东西。我认为问题出在我的 linter 上,因为它仍然显示无法导入 seaborn,但它仍然在运行。
  2. 我想皮林特是因为海伯恩被安装了蟒蛇而生气吧?我不知道,我重启了机器,它在终端中运行,但 VSCode 仍然在抱怨无法导入“seaborn ”,尽管它肯定是在终端中导入和执行的。
  3. 我不知道如何在睡觉前把我的 x 轴刻度按正确的顺序排列,也不知道如何避免马力的平均值。

外卖

我已经认识到,我不擅长挑选最能有效传达相关性的东西。此外,我还有很多关于组织和清理数据的知识要学,以便为制图做好准备。

感谢阅读!💚

Windows 10 上深度学习的 Python 环境设置

原文:https://towardsdatascience.com/python-environment-setup-for-deep-learning-on-windows-10-c373786e36d1?source=collection_archive---------1-----------------------

TensorFlow 2.0 logo design

关于如何开始深度学习的详细介绍,从在 Microsoft Windows 10 上启用适合它的环境开始。要安装的框架将是 Keras API,使用 Google 的 TensorFlow GPU 版本作为后端引擎。

这个指南是我在自己的深度学习项目中使用的相同程序,它对我很有帮助。本指南的目的是在一个地方积累所有必要的和更新的信息,而不是在整个谷歌搜索。

让我们开始吧。

本指南已更新至 TensorFlow 2.1 版本

目录

  1. 什么是深度学习?
  2. PC 硬件设置
  3. PC 软件设置
  4. Python 解释器
  5. Python IDE

什么是深度学习?

深度学习是机器学习的一个子集,它利用多层人工神经网络在对象检测、语音识别、语言翻译等任务中提供最先进的准确性。

深度学习不同于传统的机器学习技术,它们可以从图像、视频或文本等数据中自动学习表示,而不需要引入手工编码的规则或人类领域知识。它们高度灵活的架构可以直接从原始数据中学习,当提供更多数据时,可以提高它们的预测准确性。

电脑硬件设置

为了在任何数据集上执行深度学习,软件/程序需要足够强大的计算机系统来处理必要的计算能力。因此,需要以下最低规格:

1)中央处理器(CPU) —英特尔酷睿 i5 第六代处理器或更高。AMD 同等处理器也是最佳选择。

2) RAM —最低 8 GB,建议 16 GB 或更高。

3)图形处理单元(GPU) — NVIDIA GeForce GTX 940 或更高。AMD GPUs 无论如何都无法进行深度学习。

支持深度学习的 NVIDIA CUDA GPU

4)操作系统 —微软 Windows 10(建议 64 位)Pro 或 Home。我建议在继续之前将 Windows 10 更新到最新版本。

注:对于笔记本电脑,理想的选择是从任何合适的供应商处购买游戏笔记本电脑,如华硕、联想军团、宏碁掠夺者、外星人等。

电脑软件设置

现在,为了执行深度学习,我们将使用一种称为 GPU 计算的方法,该方法将复杂的数学计算导向 GPU,而不是 CPU,从而显著减少整体计算时间。为此,我们按以下顺序安装几个组件:

Microsoft Visual Studio IDE

Visual Studio 对于接下来两个组件的安装至关重要。我推荐 Visual Studio 2019(因为我正在使用它),因为它的性能超越了它的所有前辈,安装也从未像现在这样简单快捷。但是有一个范围,你可以使用 2012 年到 2019 年的任何 VS 版本。

下载 Visual Studio 2019

下载 Visual Studio 2017 及更早版本

如果您安装了 Visual Studio 2019,则必须将其更新到 16.4 或更高版本。VS 2019 的新安装默认更新。

安装 Visual Studio 2019(或 2017,因为它与 2019 相似)后,请确保“使用 C++进行桌面开发”工作负载与以下组件一起安装:

  1. MSVC v 142-VS 2019 c++ x64/x86 构建工具(v14.24)
  2. Windows 10 SDK(任何版本)

NVIDIA GeForce 体验

该工具旨在更新您的 NVIDIA GPU 驱动程序,这样做要容易得多,如果您有 NVIDIA GPU,强烈建议安装该工具

下载 NVIDIA GeForce 体验

安装它,你需要创建一个帐户才能使用它。您应该会看到这样的屏幕

NVIDIA GeForce Experience Drivers page

在红色框中,您可以看到一个标记为“检查更新”的按钮。自动更新功能不可靠,因此在继续下载下一个软件之前,请手动检查更新。

如果你的驱动程序更新了,那么很好,你可以继续前进。如果没有,请更新它,虽然 CUDA 工具包附带驱动程序,但建议从这里开始更新,因为它们在发布时只包含最低驱动程序要求(因为您可能在发布日期后的某个时间使用它)。

NVIDIA CUDA 工具包

该软件组件是使 GPU 能够进行 GPU 计算所必需的。我们将下载版本 10.0,因为这是与我们将要安装的框架兼容的版本。

注意:TensorFlow 2.1 仅兼容 CUDA Toolkit 10.1。

下载 CUDA 工具包 10.1

CUDA 10.1 的官方 Windows 安装文档

接下来,您需要进入 CUDA 安装中的 samples 文件夹,如果您在安装过程中选择了默认路径,它位于:

C:\ProgramData\NVIDIA Corporation\CUDA Samples\v10.1\1_Utilities\deviceQuery

并选择适合您系统上安装的 VS 版本的 VS 解决方案,并在您安装的 Visual Studio 版本上运行它。如果您有 Visual Studio 2017,请运行 VS 2017 的 Visual Studio 解决方案。在运行解决方案的结果中,您应该已经获得

The result of deviceQuery CUDA Sample tested on CUDA 10.0 using VS2017 (Code compiles similarly across other CUDA versions).

安装通过验证后,您需要将 CUDA Toolkit 添加到 Path 环境中,这可以通过以下方法完成:

第一步

Right click on the ‘This PC’ shortcut and select Properties

第二步

Then select Advanced System Settings (left upper corner)

第三步

Select Environment Variables

步骤#4

Go to the bottom scroll-able window and select the Path variable by double clicking on it

第 5 步

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\lib\x64
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\include

Add the CUDA 9.0 paths in the variable

英伟达 cuDNN

下载 NVIDIA cuDNN

你需要注册一个 NVIDIA 开发者帐户来下载它,这是免费的,没有那么麻烦。为 CUDA 10.1 下载 cuDNN 7.6.X。

下载后,解压它,你将有 3 个文件,然后做:

a) Copy <installpath>\cuda\bin\cudnn64_7.dll to C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin.

b) Copy <installpath>\cuda\ include\cudnn.h to C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\include.

c) Copy <installpath>\cuda\lib\x64\cudnn.lib to C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\lib\x64.

一旦完成,你的 GPU 现在准备执行 GPU 计算。

Python 解释器

现在我们已经配置好了 GPU,是时候安装我们的 python 解释器了,我们将在 Anaconda 中使用它。它被认为比传统的 python 安装要好用得多,而且运行起来也更好。

我们可以安装这种解释器的两种变体,称为 Anaconda 和 Miniconda。要选择搭配哪个,请参考以下指南(摘自官方文档):

如果您符合以下条件,请选择 Anaconda:

  • 对 conda 或 Python 来说是新的
  • 比如一下子自动安装 Python 和 150 多个科学软件包的便利
  • 有时间和磁盘空间(几分钟和 5 GB),和/或
  • 不想安装你想单独使用的每个软件包。

如果您符合以下条件,请选择 Miniconda:

  • 不要介意单独安装您想要使用的每个软件包。
  • 没有时间或磁盘空间一次安装超过 150 个软件包,和/或
  • 只是想快速访问 Python 和 conda 命令,并希望以后整理其他程序。

我自己用 Miniconda。蟒蛇很臃肿。许多软件包从未使用过,如果需要的话,仍然可以很容易地安装。

注意:建议(但不是必须)下载您选择的解释器的 Python 3 版本,因为 Python 2 即将寿终正寝。

点击下载蟒蛇

点击下载 Miniconda

一旦你安装了你选择的解释器,就该安装需要的软件包了。打开 Anaconda 提示符并键入命令:

conda update conda

对于只支持 Anaconda 的用户,在您键入上面的命令之后,接下来键入:

conda update anaconda

暂时不要关闭 Anaconda 提示符。

注:TensorFlow 在 Windows 10 上支持 Python 3.5、3.6、3.7。虽然 TensorFlow 2.1 将是 TensorFlow 最终支持 Python 2 的版本(不考虑 OS)。

现在是时候创建我们的环境了,我们可以通过 Anaconda 提示符轻松地完成这项工作(在这种情况下,我们将创建一个名为 TensorFlow-GPU 的 Python 3.7 环境):

conda create -n TensorFlow-GPU python=3.7

我们成功地创造了新的环境。

暂时不要关闭 Anaconda 提示符。

张量流

现在,我们开始安装 tensorflow GPU 版本,为此,我们首先激活我们新创建的环境。只需输入:

conda activate TensorFlow-GPU

接下来我们安装 TensorFlow 2.1(基础包 tensorflow 已经包含对 CPU 和 GPU 的支持,并将根据系统 ) :

pip install tensorflow

pip 版本是官方支持的,而 conda 版本是社区支持的。谷歌建议安装 pip 版本。

TensorFlow 1.13 版及更高版本预装了 Keras,并与 tensor flow 一起构建,因此用户无需安装单独的 Keras 包。

现在要测试环境,调用命令:

python

然后键入:

>>import tensorflow as tf

如果这是您得到的结果:

>>import tensorflow as tf
>>

则意味着安装成功。现在我们转到 IDE。您可以关闭提示。

python IDE/文本编辑器

以下两者在调试、林挺和智能自动完成 Python 代码方面都非常出色,速度和精度都快得惊人。

  1. Visual Studio 代码安装了这些必要的 扩展。
  2. PyCharm:面向专业开发人员的 Python IDE。

这样你就可以开始你的机器学习之旅了。

结束了

Connect with the Raven team on Telegram

Python 探索性数据分析教程

原文:https://towardsdatascience.com/python-exploratory-data-analysis-tutorial-84d70ec43233?source=collection_archive---------4-----------------------

最初发布于https://www . data camp . com/community/tutorials/explorative-data-analysis-python

正如您现在所知道的,Python 数据操作库 Pandas 用于数据操作;对于那些刚刚起步的人来说,这可能意味着这个包只能在预处理数据时方便使用,但事实并非如此:Pandas 还可以很好地探索您的数据,并在您完成数据预处理后存储它。

此外,对于那些一直在关注 DataCamp 的 Python 教程或已经了解了 SciPy、NumPy、Matplotlib 和 Pandas 基础知识的人来说,重温一下您已经积累的一些知识可能是个好主意。

今天的教程实际上将向您介绍一些使用上述所有包高效浏览数据的方法,以便您可以开始对数据进行建模:

  • 您将首先学习如何导入数据,这是您在开始分析之前需要成功完成的第一步。
  • 如果你不确定探索性数据分析(EDA) 是什么,EDA 和数据挖掘的确切区别是什么,本节将在你开始教程之前为你解释!
  • 然后,你会得到你的数据的一个基本描述。您将专注于获取一些描述性统计数据,检查数据帧的第一行和最后一行,从数据中检索样本,等等。你会发现这是一个很好的方式来获得对数据的初步感觉,并且可能已经对它有了更好的理解!
  • 在收集了一些关于数据的信息后,通过查询或索引数据来更深入地查看它可能也是一个好主意。您可以使用这种技术来测试您对数据的一些基本假设。
  • 现在您已经检查了您的数据,您可能已经看到了您的分析可能感兴趣的一些特性:您将看到哪些特性可以通过特性工程和特性选择对您的分析产生积极的影响。
  • 接下来,您将看到初步探索是好的,但您还需要了解您的数据可能带来的挑战,例如缺失值或异常值,当然,还有您如何应对这些挑战
  • 最后,您还将学习如何发现数据中的模式,方法是使用 Python 数据可视化包 Matplotlib 和 Bokeh 轻松快速地可视化数据,或者使用特定函数计算属性之间的相关性。

阅读全文 [这里](http://As you will know by now, the Python data manipulation library Pandas is used for data manipulation; For those who are just starting out, this might imply that this package can only be handy when preprocessing data, but much less is true: Pandas is also great to explore your data and to store it after you’re done preprocessing the data. Additionally, for those who have been following DataCamp’s Python tutorials or that have already been introduced to the basics of SciPy, NumPy, Matplotlib and Pandas, it might be a good idea to recap some of the knowledge that you have built up. Today’s tutorial will actually introduce you to some ways to explore your data efficiently with all the above packages so that you can start modeling your data: You’ll first learn how to import data, which is the first step that you need to complete successfully before you can start your analysis. If you're not sure what Exploratory Data Analysis (EDA) is and what the exact difference between EDA and Data Mining is, this section will explain it for you before you start the tutorial! Then, you’ll get a basic description of your data. You’ll focus on getting some descriptive statistics, checking out the first and last rows of your DataFrame, retrieving samples from your data, etc. You’ll see that this is a great way to get an initial feeling with your data and maybe understand it a bit better already! After gathering some information on your data, it might also be a good idea to also take a deeper look at it by querying or indexing the data. You can use this technique to test some of the basic hypotheses that you might have about the data. Now that you have inspected your data, you'll probably already see that there are some features that can be of interest to your analysis: you'll see which ones can influence your analysis positively with feature engineering and feature selection. Next, you’ll see that an initial exploration is good, but you will also need to have an idea of the challenges that your data can pose, such as missing values or outliers, and, of course, how you can handle those challenges, and Lastly, you’ll also learn how to discover patterns in your data, by either visualizing your data easily and quickly with the Python data visualization packages Matplotlib and Bokeh, or by using specific functions to compute the correlation between attributes.)

导入数据

要开始探索您的数据,您需要从实际加载数据开始。你可能已经知道了这一点,但是多亏了 Pandas 库,这变成了一个简单的任务:你按照惯例以pd的形式导入包,然后使用read_csv()函数,向它传递可以找到数据的 URL 和一个header参数。最后一个参数可以用来确保数据被正确读入:数据的第一行不会被解释为数据帧的列名。

或者,您还可以指定其他参数来确保数据被正确读入:您可以指定与sepdelimiter参数一起使用的分隔符,与names一起使用的列名,或者与index_col一起用作结果数据帧的行标签的列。

但是这些并不是您可以添加到read_csv()函数中的所有参数。在文档中详细阅读该函数及其参数。

注意,在这种情况下,您使用了read_csv(),因为数据碰巧是逗号分隔的格式。如果您的文件有另一个分隔符,您也可以考虑使用其他函数加载您的数据,如read_table()read_excel()read_fwf()read_clipboard,分别读入一般分隔文件、Excel 文件、固定宽度格式数据和复制到剪贴板的数据。

此外,您会发现read_sql()是将 SQL 查询或数据库表读入数据帧的选项之一。对于更多的输入功能,请考虑 Pandas 文档的本节。

什么是探索性数据分析(EDA)?

探索性数据分析(EDA)一方面用于回答问题、测试业务假设、为进一步分析生成假设。另一方面,也可以用它来为建模准备数据。这两者的共同点可能是对您的数据有很好的了解,以获得您需要的答案,或者开发一种直觉来解释未来建模的结果。

有很多方法可以达到这些目标:你可以获得数据的基本描述,可视化它,识别其中的模式,识别使用数据的挑战,等等。

在阅读有关 EDA 的内容时,您会经常看到的一件事情是数据分析。数据概要分析通过描述性统计对数据集进行汇总。您希望使用各种测量方法来更好地了解数据集。数据概要分析的目标是对您的数据有一个坚实的理解,以便您以后可以开始以各种方式查询和可视化您的数据。然而,这并不意味着您不需要迭代:正是因为数据概要分析与汇总您的数据集有关,所以它经常用于评估数据质量。根据数据分析的结果,您可能会决定更正、丢弃或以不同方式处理您的数据。

在下一篇文章中,您将了解更多关于数据分析的内容。

EDA 和数据挖掘

EDA 不同于数据挖掘,尽管两者密切相关,因为许多 EDA 技术已经被用于数据挖掘。这两者的目标也非常相似:EDA 确实确保您以一种有趣的特性和特性之间的关系将变得更加清晰的方式探索数据。在 EDA 中,您通常会使用各种技术探索和比较许多不同的变量,以搜索和找到系统模式。另一方面,数据挖掘关注的是从数据中提取模式。这些模式提供了对变量之间关系的洞察,可以用来改进业务决策。同样,在这两种情况下,你都没有关于变量之间关系的先验期望或不完整的期望。

但是,一般来说,数据挖掘可以说是更面向应用,而 EDA 关注的是底层现象的基本性质。换句话说,数据挖掘相对不太关心识别所涉及变量之间的特定关系。因此,数据挖掘接受“黑盒”方法来进行数据探索,不仅使用 EDA 中也使用的技术,还使用神经网络等技术来生成有效的预测,但不识别预测所基于的变量之间关系的特定性质。

数据的基本描述

就像你在上面读到的,EDA 就是要了解你的数据。要做到这一点,最基本的步骤之一是获得数据的基本描述。对数据的基本描述确实是一个非常宽泛的术语:您可以将其解释为获取数据信息的一种快速而简单的方式,获取数据信息的一种简单、易于理解的方式,对数据的一种基本感觉,等等。

本节不会对这些解释进行区分:它确实会向您介绍一些可以快速收集数据框架信息的方法,这些方法很容易理解。

例如,您可以使用describe()函数获得排除 NaN 值的各种汇总统计信息。考虑这个代码示例。

您会看到该函数返回数据的计数、平均值、标准差、最小值和最大值以及分位数。当然,请注意,Python 中有许多包可以提供这些统计数据,包括 Pandas 本身。使用该功能只是获取这些信息的方法之一。

还要注意,如果您还没有这样做,您肯定需要花时间深入研究描述性统计数据。您可以使用这些描述性统计数据来开始评估数据的质量。然后,你将能够决定你是否需要纠正,丢弃或以另一种方式处理数据。这通常是数据分析步骤。EDA 中的这一步旨在更好地理解数据元素及其异常,并了解数据一方面如何与文档相匹配,另一方面如何适应业务需求。

请注意在您进行探索性数据分析时,您将回到数据分析步骤,因为您将经历的步骤会影响数据的质量。

既然您已经对数据集有了大致的了解,那么更仔细地查看数据本身也是一个好主意。借助熊猫图书馆的head()tail()功能,你可以很容易地分别检查出你的数据帧的第一行和最后一行。

使用下面 DataCamp 轻量块中的head()tail()功能检查手写数字数据的第一行和最后五行。你可以在这个 DataCamp Light 代码块里试试。

当你不熟悉这类数据时,你会发现head()tail()函数的结果并不能说明什么。

你可能只会看到一堆带有数字值的行和列。如果您还没有阅读过数据集描述的话,请考虑阅读一下,这将为您提供关于数据是如何收集的相关信息,还会说明属性和行数,这可以方便地检查您是否正确导入了数据。

此外,回到最初的发现:行中的数值。乍一看,您可能不认为有问题,因为整数值看起来是正确的,并且当您第一次查看它时没有出现任何标志。

但是,如果您已经在您面前的另一个数据集上完成了所有这些操作,并且该数据集可能具有例如日期时间信息,那么快速浏览这些代码行的结果可能会提出以下问题:“我的数据是作为日期时间读入的吗?”,“这个怎么查?”以及“我如何改变数据类型?”。

这些是您通常会在数据分析步骤中解决的更深层次的问题,将在下一篇文章中解决。

如果您有一个大型数据集,您可以考虑对数据进行采样,作为快速了解数据的一种简单方法。作为第一个简单的方法,你可以使用 Pandas 中的sample()函数,就像你在这里看到的。

另一种可能更复杂的方法是创建一个随机索引,然后从数据帧中获取随机行。你会看到下面的代码使用了random包,它有一个模块sample,可以让你结合range()len()对数据进行采样。请注意,您还可以利用ix来选择您想要包含在样本中的数据帧的确切行。

如果你不知道为什么在这种情况下使用ix, data camp 更具体的教程会有所帮助!它详细介绍了这些更一般的主题。点击上面的链接去看看吧!

现在,让我们练习一下 Python 技巧吧!从这里开始练习。

现在,您已经收集了一些关于数据的基本信息,最好是稍微深入一点,了解数据可能带来的挑战。如果您已经完成了数据分析步骤,您将意识到丢失的值,您将知道哪些值可能是异常值,等等。

最初发表于【www.datacamp.com】

Python for Android:开始构建 Kivy 跨平台应用程序

原文:https://towardsdatascience.com/python-for-android-start-building-kivy-cross-platform-applications-6cf867d44612?source=collection_archive---------2-----------------------

本教程介绍了使用 Linux Ubuntu 发行版使用 Kivy 跨平台 Python 框架创建 Android 应用程序所需的步骤。在开始安装 Kivy 并启动和运行它之前,需要安装它的依赖项。大部分时间用于通过安装运行所需的库来准备 Kivy 环境。在本教程中,Kivy 本身将安装在一个虚拟环境中。

本教程中使用的平台是带有 Python 3.6.5 的 Linux Ubuntu 18.04。在其他平台上运行 Kivy 会存在一些差异。为了能够安装库、浏览操作系统的目录、复制/删除/提取文件、运行 Python 脚本,读者应该对 Linux 终端命令和 Python 有一个基本的了解。

本教程包含以下几个部分:

  1. 介绍
  2. 安装 Kivy 依赖项
  3. 为安装 Kivy 创建虚拟环境
  4. 安装 Cython
  5. 安装 Kivy
  6. 进口基维
  7. 创建简单的 Kivy 应用
  8. 安装 Buildozer
  9. 正在创建 buildozer.spec 文件
  10. 使用 Buildozer 构建 Android 应用程序
  11. 参考

1.介绍

Kivy 用于创建自然的用户界面,具有抽象和模块化的优点。它将开发人员从不必要的复杂细节中分离出来,只给出简单的 API 来完成复杂的任务。因此,您应该确定 Kivy 将使用什么样的后端库来完成它的任务。我们将使用 SDL ( 简单直接媒体层)跨平台库,通过 OpenGL 对图形硬件进行低级访问。除了 SDL,GStreamer 等其他库也用于处理音频和视频。因为这样的库是用 C 写的,所以需要 Cython。

2.安装 Kivy 依赖项

根据 Kivy Linux 安装说明(【https://kivy.org/docs/installation/installation-linux.html】T2),下面是获得 SDL2 和 GStreamer 需要安装的库。注意,您可以选择在 Kivy 中使用哪个 Python 版本,对于 Python 2 使用 pythonpython-dev ,或者对于 python3 使用 python3python3-dev 。Pip 安装在下面,供以后准备 Kivy 虚拟环境时使用。

**ahmed-gad@ubuntu:~$ sudo apt install -y \****python-pip \****build-essential \****git \****python3 \****python3-dev \****ffmpeg \****libsdl2-dev \****libsdl2-image-dev \****libsdl2-mixer-dev \****libsdl2-ttf-dev \****libportmidi-dev \****libswscale-dev \****libavformat-dev \****libavcodec-dev \****zlib1g-dev \****libgstreamer1.0 \****gstreamer1.0-plugins-base \****gstreamer1.0-plugins-good**

3.为安装 Kivy 创建虚拟环境

准备好 Kivy 依赖项后,我们可以通过创建虚拟环境来开始安装 Kivy。不要求使用虚拟环境来运行 Kivy,但建议将 Kivy 与其他现有项目分开。

在开始创建虚拟环境之前,我们应该确保创建虚拟环境所需的工具已经安装并更新。以下命令确保 virtualenvsetuptools 工具已经存在并更新。

**ahmed-gad@ubuntu:~$ sudo pip install --upgrade pip virtualenv setuptools**

virtualenv 用于创建隔离的 Python 环境。有关虚拟环境优势的更多信息,您可以访问本页https://virtualenv.pypa.io/en/stable/。 setuptools 用于打包 Python 项目。

之后,我们准备创建 Kivy 虚拟环境。以下命令创建了一个名为 mykivyinstall 的环境。

**ahmed-gad@ubuntu:~$ virtualenv --no-site-packages mykivyinstall**

— no-site-packages 参数用于将环境与主 Python 安装隔离开来。这是在不影响任何其他项目的情况下,在那个项目上自由地工作。

发出该命令后,预计会在当前目录中获得一个根据虚拟环境名称命名的新文件夹,如图 1 所示。

Figure 1. Creating Kivy virtual environment.

前面的命令将在环境中使用默认的 Python 解释器。它可能是 Python 2,我们希望与 Python 3 合作。因此,我们可以使用下面的命令中的 -p 选项来明确指定使用哪个 Python 解释器:

**ahmed-gad@ubuntu:~$ virtualenv --no-site-packages -p /usr/bin/python3 mykivyinstall**

创建虚拟环境后,我们可以激活它来开始安装 Kivy。可以基于以下命令激活它。

**ahmed-gad@ubuntu:~$ . mykivyinstall/bin/activate**

点号()。)是一个内置命令,执行作为参数传递的文件内容。它是命令源的同义词。因此,前面的命令与此命令相同:

**ahmed-gad@ubuntu:~$ *source* mykivyinstall/bin/activate**

激活虚拟环境后,命令提示符应更改如下:

**(mykivyinstall) ahmed-gad@ubuntu:~$**

4.安装 Cython

在安装 Kivy 之前,根据以下命令将 Cython 安装在这样的环境中:

**(mykivyinstall) ahmed-gad@ubuntu:~$ pip install cython=0.25.2**

请注意,Cython 的版本取决于要安装的 Kivy 的版本。在当前日期,最新的 Kivy 版本是 1.10.0 ,它需要 Cython 0.25.2 ,这就是为什么在上面的命令中使用它。之后,我们准备安装 Kivy。

5.安装 Kivy

可以根据以下命令使用 pip 安装 Kivy:

**(mykivyinstall) ahmed-gad@ubuntu:~$ pip install kivy**

在这个命令之后,Kivy 会自动下载并安装。但是请注意,Kivy 的安装是最难的部分,因为有许多依赖项是基于机器、平台以及您已经拥有和缺少的库而变化的。这个过程并不简单,您应该寻找其他方法来解决安装错误。例如,Kivy 可以通过使用 wheel 文件或根据以下命令克隆其 github 项目来安装:

**(mykivyinstall) ahmed-gad@ubuntu:~$ pip install git+https://github.com/kivy/kivy.git@master**

6.进口基维

达到 is 阶段后,预计 Kivy 会成功安装并运行在您的机器上。我们可以通过导入 Kivy 来测试这个环境,如图 2 所示。虚拟环境被激活,Python 被激活,Kivy 被成功导入。

Figure 2. Testing the virtual environment.

在确保 Kivy 运行良好之后,我们准备创建我们的第一个 Kivy 应用程序。

7.创建简单的 Kivy 应用

Kivy 应用程序只是一个保存 Kivy 代码的简单 Python 文件。我们的应用程序中的文件将被命名为“ main.py ”。原因是在构建移动应用的时候,必须有一个名为“ main.py 的文件,这是应用的入口。要创建的应用程序将有三个 Kivy 小部件,分别是文本输入标签、按钮。这些小部件使用方框布局垂直显示在一个窗口中。它们将按照添加到框布局的顺序出现。换句话说,文本输入将是第一个小部件,其次是标签,最后是底部的按钮。当点击按钮时,在文本输入中输入的文本将显示在标签上。下面是应用程序的 Kivy 代码。

1\.  **import** kivy.app
  1. 导入 kivy.uix.boxlayout
  2. 导入 kivy.uix.textinput
  3. 导入 kivy.uix.label
  4. 导入 kivy.uix.button
  5. 简单应用程序(kivy.app.App):
  6. def build(自我):
  7. self . textinput = kivy . uix . textinput . textinput()
  8. self . label = kivy . uix . label . label(text = "您的消息。")
  9. self . button = kivy . uix . button . button(text = "点击我。")
  10. self . button . bind(on _ press = self . display message)
  11. self . box layout = kivy . uix . box layout . box layout(orientation = " vertical ")
  12. self . box layout . add _ widget(self . textinput)
  13. self . box layout . add _ widget(self . label)
  14. self . box layout . add _ widget(self . button)
  15. 返回 self.boxLayout
  16. def 显示消息(self,btn):
  17. self . label . text = self . textinput . text
  18. 如果 name == "main ":
  19. simpleApp = SimpleApp()
  20. simpleApp.run()

build 方法是应用程序运行后调用的方法,因此它用于初始化 Kivy GUI 窗口。这三个小部件被创建,然后被添加到框布局中。bind 方法将一个回调方法附加到单击时要执行的按钮上。回调方法名为“ displayMessage ”,它将标签文本设置为文本输入小部件中输入的文本。只有通过确保 if 语句中的“_ _ name _ _”变量具有值“_ _ main _ _”来执行 main.py 文件,应用程序才会运行。做那件事是好习惯。为了运行该应用程序,需要两个步骤。首先是激活先前创建的名为" mykivyinstall "的 Kivy 虚拟环境。第二个是在导航到应用程序文件所在的文件夹后,运行应用程序文件“ main.py ”。这些步骤如图 3 所示。

Figure 3. Activating the virtual environment.

图 4 显示了带有之前创建的三个小部件的窗口。请注意,窗口高度在它的三个小部件之间平均分配,因此每个小部件只有窗口高度的三分之一。在本例中,在文本输入中输入了“ Hello Kivy ”消息。当按钮被点击时,信息将出现在标签上。

Figure 4. Simple Kivy application.

至此,成功创建了一个 Kivy 桌面应用程序。我们现在可以开始将这个项目打包成一个 Android 应用程序。

8.安装 Buildozer

Buildozer 工具用于将项目打包成 Android 应用。一旦安装完毕, Buildozer 就会自动完成构建 Android 应用的过程。为了安装 Buildozer ,有一些依赖关系。除了之前安装的 Cython 和 git,还有一些其他的库需要安装。根据http://buildozer.readthedocs.io/en/latest/installation.html中的安装说明,可以使用以下 Ubuntu 命令下载并安装所有依赖项:

**ahmed-gad@ubuntu:~$ sudo dpkg --add-architecture i386****ahmed-gad@ubuntu:~$ sudo get install build-essential ccache libncurses5:i386 libstdc++6:i386 libgtk2.0-0:i386 libpangox-1.0-0:i386 libpangoxft-1.0-0:i386 libidn11:i386 python2.7 python2.7-dev openjdk-8-jdk unzip zlib1g-dev zlib1g:i386**

可以使用这个命令安装 Buildozer。该命令确保 Buildozer 已安装并升级。

**ahmed-gad@ubuntu:~$ sudo install –upgrade buildozer**

成功安装 Buildozer 后,让我们准备好所有需要的文件,以便成功构建 android 应用程序。

9.正在创建 buildozer.spec 文件

我们的项目结构如图 5 所示。有一个名为 simpleapp 的文件夹,里面放着之前创建的 main.py 文件。Kivy 的美妙之处在于,同样的 Python 文件将在 Android 应用程序中不加修改地使用。但是还有另一个名为 buildozer.spec 的文件,这是构建这个应用程序所必需的。这个文件包含了 Android 应用程序的信息,比如标题和版本。如何创建该文件?

Figure 5. Project structure.

可以使用 buildozer 工具生成 buildozer.spec 文件。将当前工作目录设为应用程序 main.py 文件所在的目录后,发出以下命令:

**ahmed-gad@ubuntu:~/Desktop/simpleapp$ buildozer init**

将会出现一条消息,表明 buildozer.spec 文件已经创建,如图 6 所示。

Figure 6. Generating the buildozer.spec file.

buildozer.spec 文件中 Android 应用的一些重要属性如下:

**[app]****title = Simple Application****package.name = simpleapp****package.domain = org.simpleapp****source.dir = .****source.include_exts = py,png,jpg,kv,atlas****version = 0.1****requirements = kivy****orientation = portrait****osx.python_version = 3****osx.kivy_version = 1.9.1****fullscreen = 0**

例如,title 保存应用程序的标题,source directory 引用应用程序的目录,在这种情况下设置为当前目录、app 版本、Python 和 Kivy 版本等。这些字段位于规范文件的【app】部分。你可以在这个链接http://buildozer . readthedocs . io/en/latest/specifications . html查看 app 规范。您还可以编辑规范文件,以更改您认为值得修改的任何字段。

准备好构建 Android 应用程序所需的所有文件后,让我们开始构建它。

10.使用 Buildozer 构建 Android 应用程序

Buildozer 是构建 Android 应用程序的好工具,因为它根据所有需求准备环境,以便成功构建应用程序。这些需求比如 python-for-android 、Android SDKNDK 等等。在 app 目录中,可以使用以下命令构建它:

**ahmed-gad@ubuntu:~/Desktop/simpleapp$ buildozer android release**

图 7 显示了输入命令时的响应。当第一次构建应用程序时,Buildozer 必须下载所有这些依赖项。下载和安装它们需要时间。耐心点。

Figure 7. Building the Kivy project.

该命令执行后,APK 文件将位于项目目录 /simpleapp/下的这个位置。buildozer/Android/platform/build/dists/simple app/bin。APK 的文件可以转移到安卓设备上运行。此外,还可以将 Android 设备连接到机器,使用一个命令构建、部署和运行应用程序,如下所示:

**ahmed-gad@ubuntu:~/Desktop/simpleapp$ buildozer android release deploy run**

图 8 显示了 Android 应用程序的运行。

Figure 8. Running the Android application.

11.参考

小菲,风尘仆仆。使用 Python 在 Kivy: Mobile 中创建应用程序。“奥莱利媒体公司”,2014 年。

https://kivy.org/docs/installation/installation-linux.html

【https://virtualenv.pypa.io/en/stable/

https://kivy.org/docs/guide/architecture.html

https://github.com/kivy/kivy/blob/master/kivy/

http://buildozer.readthedocs.io/en/latest/installation.html

https://buildozer.readthedocs.io/en/stable/quickstart.html

原文可在 LinkedIn 本页面查看:https://www . LinkedIn . com/pulse/python-Android-start-building-kivy-cross-platform-applications-gad

联系作者:

电子邮件:ahmed.f.gad@gmail.com

领英:https://linkedin.com/in/ahmedfgad

用于数据科学的 Python:你可能已经忘记的 8 个概念

原文:https://towardsdatascience.com/python-for-data-science-8-concepts-you-may-have-forgotten-i-did-825966908393?source=collection_archive---------1-----------------------

掌握 Python、NumPy 和 Pandas 中的小东西

Source: Unsplash

问题是

如果你曾经发现自己在编程时一遍又一遍地查找相同的问题、概念或语法,你并不孤单。

我发现自己经常这样做。

虽然在 StackOverflow 或其他资源上查找东西并不是不自然的,但它确实会使您的速度变慢,并对您是否完全理解这门语言提出质疑。

我们生活在这样一个世界里,似乎随时都有无限量的可访问的免费资源,只需一次搜索就能找到。然而,这可能是福也可能是祸。如果没有得到有效的管理,过度依赖这些资源会养成不良的习惯,这会让你长期落后。

Source: xkcd

就我个人而言,我发现自己多次从类似的讨论线索中提取代码,而不是花时间学习和巩固概念,以便下次我可以自己复制代码。

这种方法是懒惰的,虽然它可能是短期内阻力最小的方法,但它最终会伤害你的成长、生产力和回忆语法的能力。

目标

最近,我一直在 Udemy 上学习一门名为 Python 的在线数据科学课程(哦,天哪,我听起来像 Youtube 上的那家伙)。在本系列的早期讲座中,我想起了在 Python 中执行数据分析时经常忽略的一些概念和语法。

为了一劳永逸地巩固我对这些概念的理解,并为你们节省一些 StackOverflow 搜索,这里有一些我在使用 Python、NumPy 和 Pandas 时经常忘记的东西。

我已经为每个概念提供了一个简短的描述和示例,但是为了您的利益,我还将提供视频和其他资源的链接,以便更深入地探索每个概念。

单行列表理解

每次需要定义某种列表时都要编写一个 for 循环,这很繁琐,幸运的是 Python 有一个内置的方法,只用一行代码就可以解决这个问题。语法可能有点难理解,但是一旦你熟悉了这种技术,你就会经常使用它。

Source: Trey Hunner

看看上面和下面的例子,看看你通常是如何用 for 循环理解列表,而不是用一行简单的代码创建列表,而不需要循环。

x = [1,2,3,4]
out = []
for item in x:out.append(item**2)
print(out)**[1, 4, 9, 16]**# vs.x = [1,2,3,4]
out = [item**2 for item in x]
print(out)**[1, 4, 9, 16]**

λ函数

是否厌倦了为有限的用例创建一个又一个函数?兰姆达功能来拯救!Lambda 函数用于在 Python 中创建小型、一次性和匿名的函数对象。基本上,他们让你创建一个函数,而不创建函数

lambda 函数的基本语法是:

lambda arguments: expression

请注意,lambda 函数可以做常规函数能做的一切,只要只有一个表达式。查看下面的简单示例和即将播放的视频,更好地感受 lambda 函数的强大功能:

double = lambda x: x * 2
print(double(5))**10**

贴图和滤镜

一旦掌握了 lambda 函数,学习将它们与 map 和 filter 函数配对会是一个强大的工具。

具体来说,map 接受一个列表,并通过对每个元素执行某种操作将其转换为一个新列表。在这个例子中,它遍历每个元素并将自身乘以 2 的结果映射到一个新的列表。请注意,list 函数只是将输出转换为列表类型。

# Map
seq = [1, 2, 3, 4, 5]
result = list(map(lambda var: var*2, seq))
print(result)**[2, 4, 6, 8, 10]**

filter 函数接受一个列表和一个规则,很像 map,但是它通过将每个元素与布尔过滤规则进行比较来返回原始列表的子集。

# Filter
seq = [1, 2, 3, 4, 5]
result = list(filter(lambda x: x > 2, seq))
print(result)**[3, 4, 5]**

Arange 和 Linspace

要创建快速简单的 Numpy 数组,只需看看 arange 和 linspace 函数就行了。每一种都有其特定的用途,但这里的吸引力(而不是使用范围)是它们输出 NumPy 数组,这通常更容易用于数据科学。

Arange 返回给定间隔内间隔均匀的值。除了起点和终点,如果需要,还可以定义步长或数据类型。请注意,停止点是一个“截止”值,因此它不会包含在数组输出中。

# np.arange(start, stop, step)
np.arange(3, 7, 2)**array([3, 5])**

Linspace 非常相似,但略有不同。Linspace 返回指定间隔内间隔均匀的数字。因此,给定一个起点和终点,以及一些值,linspace 将在一个 NumPy 数组中为您平均分配它们。这对于数据可视化和绘图时声明轴特别有帮助。

# np.linspace(start, stop, num)
np.linspace(2.0, 3.0, num=5)**array([ 2.0,  2.25,  2.5,  2.75, 3.0])**

轴的真正含义是什么

您可能在删除 Pandas 中的列或对 NumPy 矩阵中的值求和时遇到过这种情况。如果没有,那么在某个时候你肯定会的。现在让我们以删除一列为例:

df.drop('Row A', axis=0)
df.drop('Column A', axis=1)

我不知道我写了多少遍这行代码,才知道为什么要声明 axis 是什么。正如您可能从上面推导出的那样,如果您想要处理列,请将 axis 设置为 1,如果您想要行,请将其设置为 0。但这是为什么呢?我最喜欢的推理,或者至少我记得是这样的:

df.shape**(# of Rows, # of Columns)**

从 Pandas dataframe 调用 shape 属性会返回一个元组,第一个值表示行数,第二个值表示列数。如果你想一想这在 Python 中是如何索引的,行是 0,列是 1,就像我们如何声明轴值一样。很疯狂,对吧?

串联,合并,并连接

如果您熟悉 SQL,那么这些概念对您来说可能会容易得多。总之,这些函数本质上只是以特定方式组合数据帧的方法。很难跟踪哪一个在哪个时间使用是最好的,所以让我们来回顾一下。

Concat 允许用户将一个或多个数据帧附加到彼此的下方或旁边(取决于您如何定义轴)。

Merge 将用作主键的特定公共列上的多个数据帧组合在一起。

Join 与 merge 非常相似,它组合了两个数据帧。但是,它基于索引而不是某个指定的列来联接它们。

查看优秀的熊猫文档,了解具体的语法和更具体的例子,以及您可能遇到的一些特殊情况。

熊猫申请

把 apply 想象成一个地图函数,但是是为熊猫数据帧或者更具体地说,为系列制作的。如果您不太熟悉,Series 在很大程度上与 NumPy 数组非常相似。

Apply 根据您的指定将函数发送到列或行中的每个元素。您可能会想象这有多有用,特别是对于格式化和操作整个 DataFrame 列的值,而根本不需要循环。

数据透视表

最后但肯定不是最不重要的是数据透视表。如果您熟悉 Microsoft Excel,那么您可能在某些方面听说过数据透视表。Pandas 内置的 pivot_table 函数创建一个电子表格样式的数据透视表作为数据帧。请注意,数据透视表中的级别存储在结果数据帧的索引和列的 MultiIndex 对象中。

包扎

暂时就这样了。我希望这些概述能够有效地唤起您对使用 Python 进行数据科学时经常遇到的重要但有些棘手的方法、函数和概念的记忆。就我个人而言,我知道即使是写下这些并试图用简单的术语解释它们的行为也帮了我很多。

感谢阅读!请随意查看我下面的一些类似文章,并订阅我的时事通讯中的 以获得有趣的链接和新内容。

  • 为新的和有抱负的数据科学家汇编建议
  • 对于数据科学家来说,入职应该是什么样的?
  • 13 份面向数据科学家的重要新闻简报:重新制作

你可以在 Medium 上关注我更多类似的帖子,也可以在 Twitter 上找到我。想了解更多关于我和我在做什么,请查看我的网站。

用于数据科学和机器学习的 Python 训练营回顾

原文:https://towardsdatascience.com/python-for-data-science-and-machine-learning-bootcamp-review-48081471a96b?source=collection_archive---------3-----------------------

热门在线课程的思考和收获

Python for Data Science and Machine Learning Bootcamp

介绍

我今年夏天来到这里,最初的目标是回顾与使用 Python 进行数据科学相关的基本概念。我认为实现这一目标的最佳方式是通过在线课程和独立的并行项目。根据我的经验,我发现这种设置给了我适当的结构和灵活性来最有效地学习。

幸运的是,许多数据科学家已经承担了分析各种在线课程利弊的任务,所以我所要做的就是查看信息,并决定哪一个最适合我。最值得注意的是, David Venturi 在下面链接了几个非常好的帖子,就是为了做这个而设计的。

[## 我根据数千个数据点,对互联网上的每一门数据科学导论课程进行了排名

一年前,我退出了加拿大最好的计算机科学项目之一。我开始创建自己的数据…

medium.freecodecamp.org](https://medium.freecodecamp.org/i-ranked-all-the-best-data-science-intro-courses-based-on-thousands-of-data-points-db5dc7e3eb8e) [## 互联网上最好的数据科学课程,根据您的评论排名

一年半前,我退出了加拿大最好的计算机科学项目之一。我开始创造我自己的…

medium.freecodecamp.org](https://medium.freecodecamp.org/the-best-data-science-courses-on-the-internet-ranked-by-your-reviews-6dc5b910ea40)

经过一些思考和更多的研究,我终于能够将我的选择缩小到 Udemy 上的一门热门课程,名为Python for Data Science and Machine Learning boot camp。本课程分为几个小部分,涉及从数据分析到实现机器学习算法,再到开始使用 Spark 和 TensorFlow 的方方面面。下面你会发现一个更令人兴奋的正式摘录,摘自课程概述:

您准备好开始成为数据科学家的道路了吗!

本综合课程将指导您学习如何使用 Python 的强大功能来分析数据,创建漂亮的可视化效果,以及使用强大的机器学习算法!

这一综合课程可与通常花费数千美元的其他数据科学训练营相媲美,但现在您只需花费一小部分成本就可以了解所有信息!拥有超过 100 场高清视频讲座和每场讲座的详细代码笔记本这是 Udemy 上最全面的数据科学和机器学习课程之一!

我们将教你如何用 Python 编程,如何创建令人惊叹的数据可视化,以及如何用 Python 使用机器学习!

平均来说,在过去的几个星期里,我每天都要完成一个部分,我会在接下来的几天内完成。虽然这种经历在我脑海中仍然记忆犹新,但我想我应该为那些关注 Python 数据科学课程的人写一篇关于这门课程的全面评论。如果你想了解课程本身,请点击下面的链接:

[## Python 用于数据科学和机器学习训练营

了解如何使用 NumPy、Pandas、Seaborn、Matplotlib、Plotly、Scikit-Learn、机器学习、Tensorflow 等等!

www.udemy.com](https://www.udemy.com/python-for-data-science-and-machine-learning-bootcamp/learn/v4/overview)

好人

首先也是最重要的一点,我喜欢整个课程中的讲座。它们大概是完美的长度,通常相当简洁,尽管我建议以至少 1.25 倍的速度观看,因为有时事情会移动得有点慢。这些概念得到了很好的解释,尤其是在早期关于 NumPy 和 Pandas 的数据分析讲座中。道具交给教官,荷西给那个。

我还认为课程的结构非常好。从理论转向观察其他人将概念应用到实践中,并最终进行回顾和修正,这似乎是一条可行之路。

涵盖的主题的广度也令人印象深刻,尤其是针对初级和中级数据科学家的课程。该课程在某种程度上触及了你能想象到的一切,从 Python 基础到 NLP 再到深度学习。

Overview of topics covered

最后,课程中包含的 Jupyter 笔记本和解决方案概述是我最喜欢的部分。我发现很难有动力去完成通过网络课程布置的作业,但这里的情况并非如此。我喜欢解决练习题,并渴望事后查看解答笔记本和复习讲座。

坏事

尽管如此,我还是对这门课有一些批评。我发现,尽管花了一半的时间在机器学习算法上,但内容并不深入。公平地说,我认为这很大程度上是因为这个课程是针对初学者的——这一点在概述中有明确说明。

然而,我发现在第三或第四个 ML 部分之后,用最小理论应用不同的算法变得重复。就我的目的而言,我希望看到一些相同的旧的 scikit-learn 调用被更基本的 ML 理论和概念所取代。

最后,值得一提的是,这门课程的费用约为 10 美元。这是非常合理的,我没有问题咳出多余的零钱。话虽如此,我也相信你可以从内容创作者那里免费找到同等质量甚至更好的在线内容,比如像 Siraj 和sendex等。

丑陋的

这与这门特定的课程没有任何关系,但是可能值得一提。在过去几年中,Udemy 作为一个组织受到了一些抵制。几个帖子和视频已经进入了这个话题,像这个来自平台上的一位前讲师,最近,下面链接的视频来自 Youtube 上一个受欢迎的内容提供商。

就我个人而言,这是我在 Udemy 上的第一次体验,我对这个平台没有任何问题,但有一些有趣的观点值得你下次注册课程时考虑。

最终外卖

总的来说,这门课做得非常好。尽管有付费墙,还是有超过 100,000 名学生注册了这门课程。对于数据科学的初学者来说,它是一个很好的起点,对于更有经验的从业者来说,它是一个有效的快速回顾。

然而,如果你真的想要一个强大的机器学习基础,我建议将这门课程与一门更理论化的课程配对,比如吴恩达在 Coursera 上广受好评的机器学习课程。

最后,关于付费墙,我非常有信心,如果你足够努力的话,在网上可以免费获得同等的,甚至更好的资料。当您选择参加本课程时,您实际上是在为购买在线课程所带来的结构和责任付费。对我来说,这个选择是有意义的,最终,这个课程证明是时间和金钱的可靠投资。

最终评分:4/5 星

感谢阅读!如果你喜欢这篇文章,请继续向鼓掌按钮展示你的爱。对更多的帖子感兴趣吗?请务必关注我并订阅下面的我的简讯以接收任何新内容。想了解更多关于我和我在做什么,请查看我的网站。

用于数据科学的 Python:第 1 部分

原文:https://towardsdatascience.com/python-for-data-science-part-1-759524eb493b?source=collection_archive---------6-----------------------

Python 有许多应用——web 开发、桌面 GUI、软件开发、商业应用和科学/数字计算。在本系列中,我们将重点关注如何在数据科学中使用 Python 中的数值计算。

在本模块中,我们将了解 Python 的以下基本功能:

1.Python 函数

2.数据类型和序列

3.日期和时间

4.希腊字母的第 11 个

5.地图

6.过滤器

7.减少

8.活力

9.For 循环

10.列表理解

1。Python 函数

函数是一段代码,只有被调用时才会运行。您可以将数据(称为参数)传递给函数。让我们写一个函数将两个数相乘。

*#multiply two numbers using a python function* **def** multiply(x,y):z = x*y**return** z#call the function to multiply the numbers 2 and 3
multiply(2,3)

输出:6

2。Python 数据类型和序列

Python 有内置的数据类型来存储数字和字符数据。让我们来看看几种常见的类型。

type(' My name is Rohan')

输出:str

type(1)

输出:int

type(1.0)

输出:浮点

type(**None**) #None signifies 'no value' or 'empty value'

输出:NoneType

type(multiply) #multiply is a function we created previously

输出:功能

现在,让我们看看如何存储数字和字符的列表,以及如何执行一些基本的操作。

i .元组:它们是不可变的数据结构,不像列表那样不能被改变

a = (1,2,3,4)
type(a)

输出:元组

二。列表:它们是可变对象

b = [1,2,3,4]
type(b)

输出:列表

让我们给上面创建的列表 b 添加一个数字。

b.append(2.2) *#append to list using this function*
print(b)

输出:[1,2,3,4,2.2]

遍历列表并打印数字

**for** number **in** b: *#looping through list*print(number)

输出:

1
2
3
4
2.2

现在,让我们连接两个列表

[1,2,3] + [1,'abc','de'] *#concatenate lists*

输出:[1,2,3,1,' abc ',' de']

创建包含重复数字的列表。

[1,2]*3 *#repeat lists*

输出:[1,2,1,2,1,2]

检查您正在搜索的对象是否在列表中。

3 **in** b *#in operator to check if required object is in list*

输出:真

将列表解包到单独的变量中。

a,b = ('abc','def')
print(a)
print(b)

输出:abc
def

iii。字符串:字符串存储角色对象

x = 'My name is Rohan'

从字符串中访问字符:

x[0] *#Access first letter*

输出:‘M’

x[0:2] *#Accesses two letters*

输出:“我的”

x[:-1] *#Accesses everything except last letter*

输出:'我叫 Roha'

x[10:] *#returns all the characters from 10th position till end*

输出:“罗汉”

现在,让我们连接两个字符串。

first = 'Rohan'
last = 'Joseph'Name = first + ' ' + last *#string concatenation* print(Name)

输出:罗汉约瑟夫

使用“拆分”功能拆分前一个字符串中的单词。

Name.split(' ') *#split the words in a string using split function*

输出:['罗汉','约瑟']

只显示第一个单词。

Name.split(' ')[0] *#Show the first word*

输出:“罗汉”

现在,只显示字符串中的第二个单词

Name.split(' ')[1] *#Show the second word*

输出:“约瑟夫”

要将数字数据连接为字符串,请先将数字转换为字符串

*#for concatenation convert objects to strings*
'Rohan' + str(2)

输出:罗汉 2

四。字典:字典是一个集合,它不是有序的,而是有索引的——它们有键和值。

c = {"Name" : "Rohan", "Height" : 176}
type(c)

输出:字典

打印包含在字典中的数据

print(c)

输出: { '姓名':'罗汉','身高':176}

基于关键字访问字典值

c['Name'] *#Access Name*

输出:《罗汉》

c['Height']

输出:176

打印字典中的所有关键字

*#print all the keys*
**for** i **in** c:print(i)

输出:名称
高度

打印字典中的所有值

**for** i **in** c.values():print(i)

输出:罗汉
176

遍历字典中的所有条目

**for** name, height **in** c.items():print(name)print(height)

输出:名称
罗汉
高度
176

3.Python 日期和时间

以下模块帮助我们以简单的方式操作日期和时间变量。

**import** **datetime** **as** **dt**
**import** **time** **as** **tm**

以秒为单位打印当前时间(从 1970 年 1 月 1 日开始)

tm.time() *#print current time in seconds from January 1, 1970*

输出:1532483980.5827992

*#convert timestamp to datetime* dtnow = dt.datetime.fromtimestamp(tm.time()) 
dtnow.year

输出:2018

获取今天的日期

today = dt.date.today()
today

输出:datetime.date(2018,7,30)

从今天的日期中减去 100 天

delta = dt.timedelta(days=100)
today - delta

输出:datetime.date(2018,4,21)

4.地图功能

Map function 将给定函数应用于给定序列的每一项后,返回结果列表。例如,让我们找出两对列表之间的最小值。

a = [1,2,3,10]
b = [5,6,2,9]c = map(min,a,b) *#Find the minimum between two pairs of lists***for** item **in** c:print(item) *#print the minimum of the pairs*

输出:1
2
2
9

5.λ函数

Lambda 函数用于在 Python 中创建小型、一次性和匿名的函数对象。

function = **lambda** a,b,c : a+b+c *#function to add three numbers* function(2,2,3) *#call the function*

输出:7

6.滤波函数

Filter 提供了一种简单的方法来过滤掉列表中的所有元素。Filter(语法:filter(function,list))需要一个函数作为它的第一个参数,为此可以使用 lambda 。例如,让我们从列表中只过滤掉大于 5 的数字

x = [1,2,3,4,5,6,7,8,9] #create a list
x2 = filter(lambda a : a>5, x) #filter using filter functionprint(list(x2))

输出:[6,7,8,9]

7.减少功能

Reduce 是一个在列表上执行一些计算并返回结果的函数。它对列表中的连续值对应用滚动计算。举个例子,让我们计算一个列表中所有数字的乘积。

from functools import reduce #import reduce function
y = [1,2,3,4,5] #create list
reduce(lambda a,b : a*b,y) #use reduce

输出:120

8。压缩功能

Zip 函数返回一个元组列表,其中第 i 个元组包含来自每个序列的第 i 个元素。让我们看一个例子。

a = [1,2,3,4] #create two lists
b = [5,6,7,8]c = zip(a,b) #Use the zip function
print(list(c))

输出:[(1,5),(2,6),(3,7),(4,8)]

如果 zip 函数中使用的序列不相等,则返回的列表的长度将被截断为最短序列的长度。

a = [1,2] *#create two lists*
b = [5,6,7,8]c = zip(a,b) *#Use the zip function*
print(c)

输出:[(1,5),(2,6)]

9.For 循环

当您有一个代码块需要重复固定次数时,通常使用 For 循环。

让我们使用 for 循环来打印从 1 到 100 的偶数列表。

*#return even numbers from 1 to 100*even=[]
**for** i **in** range(100):**if** i%2 ==0:even.append(i)**else**:**None**print(even) #print the list

输出:【0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80

10.列表理解

列表理解提供了一种更简单的创建列表的方法。继续同一个例子,让我们使用列表理解创建一个从 1 到 100 的偶数列表。

even = [i for i in range(100) if i%2==0]
print(even)

输出:【0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80

我们看到的特性有助于理解用于数值计算的 Python 的基本特性。除了这些内置函数,还有其他库,如 NumpyPandas(我们将在 即将发布的文章 ) 中查看),它们在数据科学中被广泛使用。

资源:

  1. https://docs.python.org/
  2. https://www . coursera . org/specializations/data-science-python

在 LinkedIn 上连接,并查看 Github(如下)以获得完整的笔记本。

[## rohanjoseph 93/用于数据科学的 Python

Python-for-data-science -用 Python 学习数据科学

github.com](https://github.com/rohanjoseph93/Python-for-data-science/blob/master/Python for Data Science - Part 1.ipynb)

用于数据科学的 Python:第 2 部分

原文:https://towardsdatascience.com/python-for-data-science-part-2-373d6473fa40?source=collection_archive---------4-----------------------

在 Python for data science 系列的第 1 部分中,我们看了 Python 中数值计算的基本内置函数。在这一部分,我们将看看 Numpy 库。

Numpy 是 Python 中科学计算的基础包。它提供了对大型多维数组的支持,也提供了对这些数组进行操作的高级数学函数。

很好,让我们看看如何使用 Numpy 库进行基本的数组操作。

Numpy 图书馆

首先,我们需要在 Python 中导入 numpy。

import numpy as np

让我们创建一个 numpy 数组。

np.array([1,2,3])

输出:数组([1,2,3])

现在,让我们创建一个多维数组。

a = np.array([[1,2,3],[4,5,6]]) 
a

输出:数组([[1,2,3],
[4,5,6])

检查形状(数组的行和列)。

a.shape

输出:(2,3)

在 1 到 30 之间创建一个间距均匀的数组,差值为 2。

b = np.arange(1,30,2)
b

输出:数组([ 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29])

将上面的数组重新塑造成想要的形状。

b.reshape(5,3) 

输出:数组([[ 1,3,5],
,【7,9,11】,
,【13,15,17】,
,【19,21,23】,
,【25,27,29】)

在区间 1 和 5 之间生成一个等间距列表。(在这里花一分钟来理解‘Lin space’和‘arange’之间的区别)

c = np.linspace(1,5,20)
c

输出:数组(【1。,1.21052632,1.42105263,1.63157895,1.84210526,
2.05263158,2.26315789,2.4736848,2.684842,2.6843,2.89473684,
3.105266,3.])

现在,就地改变数组的形状(“resize”功能就地改变数组的形状,不同于“reshape”)

c.resize(5,4)
c

输出:数组([[ 1。,1.21052632,1.42105263,1.63157895],
,【1.84210526,2.05263158,2.26315789,2.47368421】,
,【2.68421053,2.89473684,3.10526316,3.37】。]])

创建一个所有元素都为 1 的数组。

d = np.ones((2,2))
d

输出:数组([[ 1。, 1.],
【1。, 1.]])

创建一个用零填充的数组。

e = np.zeros((3,3))
e

输出:数组([[ 0。, 0., 0.],
【0。, 0., 0.],
【0。, 0., 0.]])

创建对角线值= 1 的对角矩阵

f = np.eye(2)
f

输出:数组([[ 1。, 0.],
【0。, 1.]])

仅从数组中提取对角线值。

np.diag(f)

输出:数组(【1。, 1.])

创建由重复列表组成的数组

g = np.array([1,2,3]*5)
g

输出:数组(【1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3】)

现在,使用 repeat 函数将数组中的每个元素重复 n 次。

np.repeat([1,2,3],3)

输出:数组([1,1,1,2,2,2,3,3,3])

生成两个所需形状的数组,用 0 到 1 之间的随机值填充。

g = np.random.rand(2,3)
print(g)
h = np.random.rand(2,3)
print(h)

输出:

[[0.61631842 0.28352987 0.56174714]
【0.54302204 0.47257786 0.21923943]]

[[0.57233679 0.22981962 0.15870184]
【0.52548056 0.81495971 0.22014512]]

垂直堆叠上面创建的两个数组

i = np.vstack([h,g])
i

输出:

数组([[ 0.57233679,0.22981962,0.15870184],
【0.52548056,0.81495971,0.22014512】,
,【0.61631842,0.28352987,0.56174714],【T30

现在,让我们把它们水平堆叠起来。

j = np.hstack([h,g])
j

输出:

数组([[ 0.57233679,0.22981962,0.15870184,0.61631842,0.28352987,
0.56174714],
[ 0.52548056,0.81495971,0.22014512,0.544512

很好,现在让我们执行一些数组操作。首先让我们创建两个随机数组

k = np.random.rand(2,2)
l = np.random.rand(2,2)
print(k)
print(l)

输出:

[[0.02430146 0.14448542]
【0.54428337 0.40332494]]

[[0.77574886 0.08747577]
【0.51484157 0.92319888]]

让我们做元素加法。

m = k + l
m

输出:数组([[ 0.80005032,0.23196118],
,【1.05912494,1.32652381])

元素减法。

n = k-l
n

输出:数组([[-0.75144739,0.05700965],
,【0.02944179,-0.51987394])

让我们对每个元素进行 2 次幂运算。

p = k**2
p

输出:数组([[ 0.00059056,0.02087604],
,【0.29624438,0.162671 ]])

现在,让我们执行两个数组 k 和 l 的点积,而不是元素运算。

q = k.dot(l)
q

输出:数组([[ 0.09323893,0.13551456],
,【0.62987564,0.41996073]])

让我们创建一个新的数组并转置它。

a = np.array([[1,2],[3,4]])
a

输出:

数组([[1,2],
,[3,4])

a.T

输出:

数组([[1,3],
,[2,4])

现在,检查数组中元素的数据类型。

a.dtype

输出:dtype('int32')

更改数组的数据类型。

b = a.astype('f')
b.dtype

输出:dtype('float32')

现在,让我们看看数组中的一些数学函数,从数组的 sum 开始。

c = np.array([1,2,3,4,5])
c.sum()

输出:15

数组元素的最大值。

c.max()

输出:5

数组元素的平均值

c.mean()

输出:3

现在,让我们检索数组最大值的索引。

c.argmax()

输出:4

c.argmin()

输出:0

创建一个由前十个整数的平方组成的数组。

d = np.arange(10)**2
d

输出:数组([ 0,1,4,9,16,25,36,49,64,81],dtype=int32)

使用 index 访问上述数组中的值。

d[2]

输出:4

d[1:5]

输出:数组([ 1,4,9,16],dtype=int32)

使用负号反向访问变量。

d[-1:]

输出:数组([81],dtype=int32)

现在,根据步长访问数组的某些元素。

d[1:10:2] *#d[start:stop:stepsize]*

输出:数组([ 1,9,25,49,81],dtype=int32)

创建多维数组

e = np.arange(36)
e.resize(6,6)
e

输出:数组([[ 0,1,2,3,4,5],

,【12,13,14,15,16,17】,
,【18,19,20,21,22,23】,
,【24,25,26,27,28,29】,
,【30,30

访问第二行和第三列

e[1,2]

输出:8

访问第二行和第 3 至 7 列。请注意,行和列的编号从 0 开始。

e[1, 2:6]

输出:数组([ 8,9,10,11])

选择第 2 行之前的所有行以及除最后一列之外的所有列

e[:2,:-1]

输出:数组([[ 0,1,2,3,4],
[ 6,7,8,9,10])

从数组中选择大于 20 的值。

e[e>20]

输出:数组(【21,22,23,24,25,26,27,28,29,30,31,32,33,34,35】)

如果元素值大于 20,则将数组元素的值赋为 20。

e[e>20] = 20
e

输出:数组([[ 0,1,2,3,4,5],
,【6,7,8,9,10,11】,
,【12,13,14,15,16,17】,
,【18,19,20,20,20】,
,【20,20,20,20】,

要将一个数组复制到另一个变量上,请始终使用 copy 函数。

f = e.copy()
f

输出:数组([[ 0,1,2,3,4,5],
,【6,7,8,9,10,11】,
,【12,13,14,15,16,17】,
,【18,19,20,20,20】,
,【20,20,20,20】,

用一组 1 到 10 之间的随机整数创建一个数组。将数组指定为 4*4 的形状

g = np.random.randin(1,10,(4,4))
g

输出:数组([[9,7,1,4],
[1,4,3,6],
[2,5,5,1],
[2,2,9,9])

很好,我们已经了解了在 Numpy 中创建、访问和操作数组。在系列的下一部分,我们将会看到一个建立在 Numpy 图书馆基础上的图书馆——熊猫图书馆。Pandas 是一个库,它使得 Python 中的数据操作和分析更加容易。它为数字表和时间序列提供数据结构和操作。

在 LinkedIn 上连接,并查看 Github(如下)以获得完整的笔记本。

[## rohanjoseph 93/用于数据科学的 Python

Python-for-data-science -用 Python 学习数据科学

github.com](https://github.com/rohanjoseph93/Python-for-data-science/blob/master/Python for Data Science - Part 2.ipynb)

用于数据科学的 Python:第 3 部分

原文:https://towardsdatascience.com/python-for-data-science-part-3-be9b08660af9?source=collection_archive---------5-----------------------

在“Python 用于数据科学”系列的前几部分中,我们研究了:

第 1 部分:Python 中的基本内置特性,如函数、数据类型、日期/时间、映射、归约、过滤、lambda 函数等。

第 2 部分:用于创建、访问和操作数组的 Numpy 库

在本文中,我们将关注最广泛使用的数据分析库——Pandas。它的名字是怎么来的?熊猫这个名字来源于埃尔塔。面板数据由对相同个体的多个时间段的观察组成。

Pandas 提供易于使用的数据结构和数据分析工具来创建和操作数据集。我们将会看到熊猫的以下特征:

  1. 系列和数据框架
  2. 查询系列
  3. 读写文件
  4. 索引
  5. 合并
  6. 聚集
  7. 过滤

和往常一样,第一步是导入库。让我们导入熊猫和 numpy 库。

import pandas as pd
import numpy as np

1.熊猫系列

系列是一维数据结构,可以保存任何数据类型,如整数和字符串。它类似于 Python 中的列表。

首先,让我们创建一个列表

name = ['Rohan','Joseph','Rohit']
name

输出:['罗汉','约瑟夫','罗希特']

现在,让我们将同一个列表转换成熊猫系列。

name = pd.Series(name)
name

输出:

0 罗汉
1 约瑟夫
2 罗希特
dtype:object

我们可以观察到熊猫系列显示了指数以及每个位置的值。同样,让我们创建一个字典,并将其转换为熊猫系列。

sport = {'cricket' : 'India','soccer' : 'UK','Football' : 'USA'}sport = pd.Series(sport)
sport

输出:

板球印度
足球英国
足球美国
d 类型:对象

字典的“键”成为序列中的索引,字典的“值”保持为序列的值。让我们通过查询一个熊猫系列来进一步理解这一点。

2.查询熊猫系列

让我们继续上面创建的同一个系列“运动”。让我们访问系列中的第三个值

sport.iloc[2]

输出:“美国”

“iloc”用于根据值的整数位置选择值。现在,让我们使用值的索引来访问同一个值。

sport.loc['Football']

输出:“美国”

太好了,让我们把一系列的值加起来

a = pd.Series([1,2,3])
np.sum(a) #np sum function is a faster than the in-built function

输出:6

向现有系列添加数据。

a = pd.Series([1,2,3])
a.loc[‘City’] = ‘Delhi’

输出:

**0 1
1 2
2 3
城市德里
d 类型:对象 **

让我们创建一个具有相同索引的多个值的序列。

b = pd.Series([‘a’,’b’,’c’,’d’],index=[‘e’,’e’,’e’,’e’])
b

输出:

e a
e b
e c
e d
d type:object

3.熊猫数据框

Dataframe 是具有不同数据类型(字符串、整数、日期等)的列的二维数据结构。).

让我们在熊猫中创建一个数据框架。我们正在创建一个包含三列的数据集——姓名、职业和年龄。

df1 = pd.DataFrame([{'Name' : 'John', 'Occupation' :  'Data Scientist', 'Age' : 25},{'Name' : 'David', 'Occupation' :  'Analyst', 'Age' : 28},{'Name' : 'Mark', 'Occupation' :  'Teacher', 'Age' : 30}],index=['1','2','3'] )df1

输出:

现在,让我们通过追加两个系列来创建一个数据帧。

s1 = pd.Series({'Name' : 'Rohan','Age':'25'})
s2 = pd.Series({'Name' : 'Rohit','Age' : 28})]
df1 = pd.DataFrame([s1,s2],index=['1','2'])
df1

输出:

4.读写文件

让我们看看如何读取 csv 文件。

iris = pd.read_csv('C:\\Users\\rohan\\Documents\\Analytics\\Data\\iris.csv')

让我们看看文件的前 5 行。

iris.head()

输出:

将文件保存回本地目录。

iris.to_csv('iris2.csv')

5.索引数据帧

检查上一步导入的 iris 数据集的索引。

iris.index.values

输出:

现在,将索引改为物种名称。“名称”列将显示为索引,并替换先前的索引。

b = iris.set_index('Name')
b.head()

输出:

要恢复到以前的索引,只需按如下方式重置索引。

c = b.reset_index()
c.index.values

输出:

6.合并数据帧

让我们再次导入虹膜数据,并将其与另一个数据集合并。

df1 = pd.read_csv('iris.csv')
df1.head()

输出:

创建一个新的 dataframe 以与此合并。

df2 = pd.DataFrame([{'Name' : 'setosa', 'Species' : 'Species 1'},{'Name':'versicolor','Species':'Species 2'},{'Name':'virginica','Species':'Species 3'}])
df2

输出:

通过执行一个内部连接,在名称列上合并上述两个数据集

df3 = pd.merge(df1,df2,how='inner',left_on='Name',right_on='Name')
df3.head()

输出:

7.聚合函数

让我们聚集 iris 数据集中的几列。首先,让我们找出每个物种的平均萼片长度。

df1.groupby('Name')['SepalLength'].mean()

输出:

现在,让我们按物种找出所有数字列的平均值。

df1.groupby('Name')[['SepalLength','SepalWidth','PetalLength','PetalWidth']].mean()

输出:输出:

而不是找到所有列的平均值;让我们对一列(萼片长度)取平均值,对另一列(萼片宽度)求和

a=df1.groupby('Name').agg({'SepalLength':'mean','SepalWidth':'sum'})
a

输出:输出:

让我们重命名这些列。

a.rename(columns={'SepalLength':'Avg_SepalLength','SepalWidth':'Sum_SepalWidth'})

输出:

8.过滤数据帧

让我们再一次导入 iris 数据集,并执行操作来划分数据集的子集。首先,让我们对萼片长度大于 7 厘米的数据进行分组。

iris = pd.read_csv(‘iris.csv’)  #import file
a = iris[(iris.SepalLength>7)]
a.head()

输出:

现在,让我们根据两个条件对数据进行子集划分。

b = iris[(iris.SepalLength>5) & (iris.PetalLength>6)]
b.head()

输出:

通过对“名称”列进行筛选来对数据进行子集划分。

c = iris[iris['Name']=='versicolor']
c.head()

再次过滤姓名列,但过滤两个姓名。

d = iris[iris['Name'].isin(['virginica','versicolor'])]
d.head()

输出:

我们在这篇文章中看到的是在数据科学中使用的 Pandas 中最常用的功能,尽管还有更多功能值得了解,如广播、数据透视表、多索引和可视化。在本系列的下一部分中,我们将继续我们的旅程,看看我们如何将 Pandas 与其他功能结合起来操作数据。

在 LinkedIn 上连接,并查看 Github(如下)以获得完整的笔记本。

[## rohanjoseph 93/用于数据科学的 Python

Python-for-data-science -用 Python 学习数据科学

github.com](https://github.com/rohanjoseph93/Python-for-data-science/blob/master/Python for Data Science - Part 3.ipynb)

用于数据科学的 Python:第 4 部分

原文:https://towardsdatascience.com/python-for-data-science-part-4-6087cb811a29?source=collection_archive---------16-----------------------

在 Python for data science 系列文章的第 3 部分中,我们查看了 pandas 库及其最常用的功能——读写文件、索引、合并、聚合、过滤等。在这一部分中,我们将继续深入研究 Pandas 库,看看它如何与其他 Python 函数一起用于查询数据帧。

让我们从导入所有必需的库开始。

import pandas as pd
import os
import numpy as np

现在,设置工作目录并导入 iris 数据集。

os.chdir('C:\\Users\\rohan\\Documents\\Analytics\\Data')
a = pd.read_csv('iris.csv')
a.head()

输出:

1。数字列的描述性统计

总结(平均值、标准偏差、最小值、最大值等。)使用 describe 函数的数据集的数字列。

a.describe()

输出:

2。基于条件创建列

让我们创建一个名为' SepalLength_Size' 的新列,如果萼片长度≥ 5,则包含“高”,如果萼片长度< 5,则包含“低”。

有许多方法可以执行上述任务。让我们来看看四种不同的方法。

  1. 首先,让我们通过使用 np.where 函数来执行这个任务。
a['SepalLength_Size'] = np.where(a['SepalLength']>=5,'High','Low')
a.head()

输出:

2.现在,使用列表理解(如果你忘了那是什么,在第一部分中检查一下)来完成同样的任务。此外,列表理解通常比所有其他方法更快。

a['SepalLength_Size'] = ['High' if x >= 5 else 'Low' for x in a['SepalLength'] ]

输出:

3.现在,让我们使用 pandas dataframe 中的‘assign’函数创建列。

def size(row_number):if row_number["SepalLength"] >=5:return 'High'else:return 'Low'a = a.assign(SepalLength_Size=a.apply(size, axis=1))a.head()

输出:

4.最后,让我们使用 lambda 函数。

a['SepalLength_Size'] = a['SepalLength'].map( lambda x: 'High' if x >= 5 else 'Low')

输出:

3.列的唯一值

a['Name'].unique()

输出:

仅获取“名称”列的唯一值的数量。

a['Name'].nunique()

输出: 3

4。十字页签(类似 Excel 中的透视表)

此函数用于查找两个或多个因子的简单交叉列表。让我们使用列“Name”和“SepalLength_Size”(我们创建的新列),看看它是如何工作的。

pd.crosstab(a['Name'],a['SepalLength_Size'])

输出:输出:

上面的十字标签提供了每种组合的行数,例如,有 30 个具有高萼片长度的刚毛藻种。

让我们再做一次交叉制表,找出每个桶中萼片的平均长度。

pd.crosstab(a['Name'],a['SepalLength_Size'],values=a['SepalLength'],aggfunc=np.mean)

5.排序值

让我们按“萼片长度”对数据进行分类。

a.sort_values('SepalLength')

输出:输出:

首先按“名称”排序(升序),然后按“萼片长度”排序(降序)。

a.sort_values(['Name','SepalLength'],ascending=[True,False])

输出:

检查所有列的数据类型

6。检查列数据类型

a.dtypes

输出:

7.宁滨数字列

在 iris 数据集中创建一个新列来存储“萼片长度”。我们可以使用“剪切”功能来执行此操作。

bins = [0, 1, 2, 3, 4, 5,6,7]
a[‘bins’] = pd.cut(a[‘SepalLength’], bins)

输出:

现在,使用“value_counts”函数计算每个存储桶下有多少行。

输出:

这涵盖了在数据科学中经常使用的大部分熊猫函数。在接下来的部分中,我们将会看到 Python 中的可视化和假设检验。

在 LinkedIn 上连接,并查看 Github(如下)以获得完整的笔记本。

[## rohanjoseph 93/用于数据科学的 Python

Python-for-data-science -用 Python 学习数据科学

github.com](https://github.com/rohanjoseph93/Python-for-data-science/blob/master/Python for data science - Part 4.ipynb)

面向金融的 python:Dash by Plotly

原文:https://towardsdatascience.com/python-for-finance-dash-by-plotly-ccf84045b8be?source=collection_archive---------3-----------------------

在 Dash by Plotly 中使用交互式图表扩展 Jupyter 笔记本股票投资组合分析。

By Carlos Muza on Unsplash.

利用 Python 进行股票投资组合分析的第 2 部分。

在本系列的第一部分中,我讨论了由于我已经越来越习惯于使用pandas,我是如何显著增加使用Python进行财务分析的。在第 1 部分的文章中,我们回顾了如何利用pandasYahoo Finance API在很大程度上自动化股票投资组合绩效的跟踪和基准测试。在这篇文章结束时,你已经生成了一个丰富的数据集,可以计算出在相同的持有期内,投资组合头寸相对于同等规模的标准普尔 500 指数头寸的相对百分比和美元价值回报。你还可以确定每个头寸对你整体投资组合回报的贡献,或许最重要的是,你投资标准普尔 500 指数 ETF 或指数基金是否会更好。最后,你使用Plotly进行可视化,这样更容易理解哪些头寸驱动了最大的价值,它们相对于标准普尔 500 指数的年初至今势头是什么样的,如果有任何头寸下跌,你可能想考虑撤资,也就是“跟踪止损”。

在 Jupyter notebook 中构建这个初始过程的过程中,我学到了很多东西,我还发现写一篇文章非常有帮助,这篇文章浏览了笔记本,解释了代码,并讲述了我在每个可视化背后的想法。这篇后续文章将比前一篇更短,目的也更直接。虽然我不断发现我创建的笔记本有助于跟踪我的股票投资组合,但我一直打算学习并整合一个用于构建分析仪表板/网络应用程序的Python框架。对我来说,最重要的用例之一是能够选择特定的位置和时间框架,然后动态地评估每个位置的相对性能。将来,我很可能会将此评估案例扩展到我不拥有但正在考虑收购的职位。在今年剩下的时间里,我希望通过学习Flask,使用Heroku部署应用程序,以及理想情况下开发某种类型的数据管道来自动提取和加载最终 web 应用程序的新数据,来进一步加深我对构建 web 应用程序的理解。虽然我仍然处于这个过程的早期,在这篇文章中,我将讨论我上次讨论的笔记本的扩展,以及我使用Dash by Plotly,又名Dash的初始开发。

阴谋地破折号。

如果你已经阅读或参考了第 1 部分,你会发现一旦你创建了主数据框架,你就使用Plotly来生成评估相对于标准普尔 500 指数的投资组合表现的可视化。Plotly 是一个非常丰富的库,相对于其他 Python 可视化库如SeabornMatplotlib,我更喜欢使用Plotly来创建可视化。在此基础上,我的最终目标是为我的投资组合分析提供一个交互式仪表板/ web 应用程序。我正在继续寻找这个问题的最佳解决方案,同时我已经开始探索Dash的使用。Plotly 将 Dash 定义为构建 web 应用程序的 Python 框架,其额外的好处是不需要 JavaScript。正如我链接到的登录页面上所示,它构建在 Plotly.js、React 和 Flask 之上。

到目前为止,我所看到的最初好处是,一旦您熟悉并熟悉了PlotlyDash就是仪表板开发的自然延伸。比起简单地把你的可视化内容放在你进行分析的Jupyter笔记本里,我确实看到了创建一个独立的交互式网络应用的价值。Dash通过“下拉菜单、滑块和图表等现代 UI 元素”提供增强的交互性和操纵数据的能力。该功能直接支持我的股票投资组合分析的最终目标,包括进行“假设分析”的能力,以及交互式研究潜在机会和快速了解关键驱动因素和情景的能力。考虑到所有这些,至少对我来说,与Dash的学习曲线不是无关紧要的。

何塞·波尔蒂利亚的“使用 Plotly 和 Dash 的交互式 Python 仪表盘”

为了缩短我通读 Dash 文档并对其进行全面故障诊断的时间,我报名参加了 Udemy 网站上何塞·波尔蒂利亚的课程。该课程详细页面可以在这里找到。我学过 Jose 的一些课程,目前正在学他的Flask课程。我认为他是一个非常可靠和有帮助的讲师——虽然他通常不认为丰富的编程经验是他的课程的先决条件,但在这个Dash课程中,他建议至少要非常熟悉Python。特别是,强烈建议您充分理解可视化的Plotly's语法,包括使用pandas。学完课程后,你仍将对你能用Dash构建的东西略知一二。然而,我发现这个课程是一个非常有帮助的开端,特别是因为 Jose 使用了datareader和财务数据和例子,包括动态绘制股票价格图表。

从 Jupyter 笔记本移植数据,以便在 Dash 中与之交互。

入门指南

类似于第 1 部分,我在 GitHub 上创建了另一个 repo,其中包含创建最终Dash仪表板所需的所有文件和代码。

下面总结了包括的内容以及如何开始:

  1. 投资组合 Python Notebook _ Dash _ blog _ example . ipynb—这与第 1 部分的 Jupyter 笔记本非常相似;新增内容包括最后两个部分:一个是“股票回报比较”部分,这是我在使用Dash之前作为概念验证而构建的,还有一个是“数据输出”,在这里我为分析生成的数据创建 csv 文件;这些用作Dash仪表板中使用的数据源。
  2. 样本股票收购日期 _ 成本. xlsx —这是玩具投资组合文件,您将使用或修改该文件进行投资组合评估。
  3. requirements.txt —这里应该有你需要的所有库。我建议在 Anaconda 中创建一个虚拟环境,下面会进一步讨论。
  4. Mock _ Portfolio _ dash . py—这是Dash仪表板的代码,我们将在下面介绍。

根据我的报告的自述文件,我建议使用 Anaconda 创建一个虚拟环境。下面是关于 Anaconda 虚拟环境的快速解释和更多细节的链接:

我推荐 Python 3.6 或更高版本,这样您就可以使用提供的 csv 文件在本地运行Dash仪表板。这里的是关于如何在Anaconda中建立虚拟环境的非常详尽的解释。

最后,正如在第 1 部分中提到的,一旦您的环境设置好了,除了需求文件中的库之外,如果您想要 Yahoo Finance datareader 在笔记本中运行,您还需要在您的虚拟环境中运行pip install fix-yahoo-finance

使用 Dash

如果您已经使用 Python 3.6 建立了一个虚拟环境,并且已经安装了必要的库,那么您应该能够使用 Dash dashboard 代码运行Python文件。

对于那些不太熟悉的人:一旦进入您的虚拟环境,您需要将目录 cd 更改为保存回购文件的位置。举个简单的例子,如果您打开 Anaconda 提示符,并且在 Documents 文件夹中,文件保存在您的桌面上,您可以执行以下操作:

cd **..** *# This will take you up one folder in the directory.*cd  Desktop *# this will take you to your Desktop.*dir *# This is the windows command to display all files in the directory.  You should see the Mock_Portfolio_Dash.py file listed.*python Mock_Portfolio_Dash**.**py *# this will run the Dash file*
*# You will then go to your browser and input the URL where Python says your dashboard is running on localhost.*

如果您想了解 Jupyter 笔记本和生成投资组合数据集的完整解释,请参考第 1 部分。在 Jupyter 笔记本的末尾,您会在“数据输出”部分看到以下代码。这些小的添加会将 CSV 文件发送到您的本地目录。第一个是完整的投资组合数据集,您可以从中生成所有的可视化效果,第二个提供了您将在第一个新股票图表的下拉选择中使用的报价器列表。

*# Generate the base file that will be used for Dash dashboard.*merged_portfolio_sp_latest_YTD_sp_closing_high**.**to_csv('analyzed_portfolio.csv')

我将强调 Mock Portfolio Python 文件的一些关键方面,并分享如何在本地运行仪表板。

以供参考。py 文件,下面是运行这个Dash仪表板时应该看到的前三个图表的屏幕截图。

First three charts in Dash Stock Portfolio Analyses dashboard.

在开始的时候。py 文件中,您导入包含在 requirements.txt 文件中的库,然后编写

app **=** dash**.**Dash()

为了实例化 Dash 应用程序。然后创建两个 dataframe 对象,tickersdata。ticker 将用于图表下拉列表中的股票 ticker,而data数据框是用于所有可视化评估的最终数据集。

您将整个仪表板包装在一个 Div 中,然后开始在这个主 Div 中添加图表组件。中的第 35–72 行。py 文件生成“相对收益比较”图表,包括股票代码下拉列表、开始/结束日期范围、提交按钮和图表输出。为了简洁起见,我将在。py 文件。

html**.**H1('Relative Returns Comparison'),html**.**Div([html**.**H3('Enter a stock symbol:', style**=**{'paddingRight': '30px'}),dcc**.**Dropdown(id**=**'my_ticker_symbol',options **=** options,value **=** ['SPY'], multi **=** True*# style={'fontSize': 24, 'width': 75}*)	]

如上所述,使用Dash意味着您不需要在应用程序中添加 JavaScript。在上面的代码块中,我们用 H1 标签标记输出,创建另一个 Div,然后使用 dash_core_components 库中的下拉菜单。您将 id 设置为“my_ticker_symbol ”,我们稍后将回顾它在何处发挥作用,从选项列表(从 tickers dataframe 生成)中设置默认值“SPY ”,然后将多选设置为真。这里有一点学习曲线,至少对我来说是这样,何塞·波尔蒂利亚的课程可以通过提供总结Dash文档的切实例子来缩短你的学习时间——何塞实际上在他的课程中使用了一个类似于股票列表下拉列表和日期范围选择器的例子。

在这下面的第 75–93 行,您将看到仪表板左下方图表的代码。该图表与第 1 部分中 Jupyter 笔记本中提供的相同,但是我发现在仪表板布局中使用Dash来显示所有这些输出比在 Jupyter 笔记本中更好的用户体验,也更容易使用(与我迄今为止使用的其他任何东西相比,我仍然更喜欢使用笔记本来进行分析)。

*# YTD Returns versus S&P 500 section*html**.**H1('YTD and Total Position Returns versus S&P 500'),dcc**.**Graph(id**=**'ytd1',figure **=** {'data':[go**.**Bar(x **=** data['Ticker'][0:20],y **=** data['Share YTD'][0:20],name **=** 'Ticker YTD'),go**.**Scatter(x **=** data['Ticker'][0:20],y **=** data['SP 500 YTD'][0:20],name **=** 'SP500 YTD')],'layout':go**.**Layout(title**=**'YTD Return vs S&P 500 YTD',barmode**=**'group', xaxis **=** {'title':'Ticker'},yaxis **=** {'title':'Returns', 'tickformat':".2%"})}, style**=**{'width': '50%', 'display':'inline-block'})

对于那些习惯使用Plotly的人来说,在创建绘制Plotly图形所需的数据和布局对象方面,语法应该是熟悉的。上面包含的语法不同于笔记本中图表使用的语法,因为我更喜欢创建跟踪,基于这些跟踪生成数据对象,并在布局对象中使用dict语法。在学习 Jose 的课程和回顾Dash文档时,我发现在Dash中更容易遵循这种语法——在解决结束标记、括号、花括号等问题时,有时会变得难以处理,所以我专注于习惯这种结构。

@app.callback(Output('my_graph', 'figure'),[Input('submit-button', 'n_clicks')],[State('my_ticker_symbol', 'value'),State('my_date_picker', 'start_date'),State('my_date_picker', 'end_date') ])
**def** **update_graph**(n_clicks, stock_ticker, start_date, end_date):start **=** datetime**.**strptime(start_date[:10], '%Y-%m-%d')end **=** datetime**.**strptime(end_date[:10], '%Y-%m-%d') traces **=** []**for** tic **in** stock_ticker:df **=** web**.**DataReader(tic, 'iex', start, end)traces**.**append({'x':df**.**index, 'y':(df['close']**/**df['close']**.**iloc[0])**-**1, 'name': tic})fig **=** {'data': traces,'layout': {'title':stock_ticker}}**return** fig**if** __name__ **==** '__main__':app**.**run_server()

第 229-252 行(如上所述)驱动了第一个“相对收益比较”图表的交互性。下面是这段代码的简要概述:

  • 为了创建交互式图表,Dash使用了一个回调装饰器:“我们的应用程序接口的“输入”和“输出”是通过app.callback装饰器以声明方式描述的。”
  • 在应用程序回调中,我们输出 dcc。先前指定的标识为“my_graph”的图形。
  • 您使用 Submit 按钮作为输入,我们有三个默认状态,“my_ticker_symbol”和在 dcc 中声明的默认“SPY”值。之前讨论过的下拉列表,以及 2018 年 1 月 1 日的默认开始日期和今天的结束日期。
  • 回调下面是回调装饰器包装的函数。如Dash文档所述,当输入属性改变时,装饰器包装的函数会被自动调用。“Dash 向函数提供输入属性的新值作为输入参数,Dash 使用函数返回的任何内容更新输出组件的属性。”
  • 在 for 循环中,对于 y 值,我将任意给定日期df['close']的收盘价除以由所提供的日期范围(df['close'].iloc[0])生成的序列中的第一个收盘价。
  • 我这样做是为了观察指数为 0(日期范围的起点)的两只或多只股票的相对表现。鉴于股价的巨大差异,这使得比较一只交易价格超过 1800 美元的股票(如 AMZN)与另一只交易价格低于 100 美元的股票(如 WMT)的相对表现容易得多。
  • 我会很快提到,有时会有一种误解,即如果一只股票以较低的价格交易,它就是“便宜的”,如果它以 AMZN 目前的价格交易,它就是“昂贵的”。鉴于这种误解,公司有时会拆分股票,以使股价看起来更能让小投资者承受,即使公司的价值/市值保持不变。
  • 不管怎样,这个图表的好处是,它允许你使用动态的日期范围,快速发现一只股票相对于标准普尔 500 的超/差表现。这提供了关于对你整个投资组合的价值贡献的有用信息,也提供了何时该考虑减持表现不佳的股票的有用信息。

结论和未来的考虑。

这就结束了我对Dash进行股票投资组合分析的初步回顾。像以前一样,您有一个可扩展的 Jupyter 笔记本和投资组合数据集,现在您可以将其作为 csv 文件读出,并在交互式Dash仪表板中查看。正如之前在第一部分中所讨论的,这种方法仍然有一些需要改进的地方,包括需要将股息作为股东总回报的一部分,以及需要能够评估活跃和所有(包括撤资)头寸。

我发现这种方法的最大好处包括额外的交互性,以及我对所有图表的仪表板布局的偏好,而不是 Jupyter notebook 中单独的单元格。未来,我计划加入更强的互动性,包括更多的“假设分析”来评估个股对整体表现的贡献。

我目前考虑使用数据管道交付端到端 web 应用程序的其他选项包括:

  • 使用 Google BigQuery 进行模式分析: 我在之前已经写过,我是多么喜欢在以前的公司使用模式分析。Mode 的好处包括它已经支持丰富的可视化(不需要编码),包括一个内置的 Python 笔记本。然而,我不相信 Mode 有办法从金融 API 中提取数据,包括雅虎金融和 IEX。来自这些 API 源的数据可以读入一个私有数据库,例如使用 Google BigQuery,您可以连接到 Mode。然而,目前这似乎是一个限制,因为我相信我未来的更多图表和用例将需要从 API 中提取数据(而不是存储在数据库中)。
  • Heroku with Postgres and Pipeline:作为 Jose 课程的一部分,他向您展示了如何将Dash应用部署到Heroku(他的课程的另一个好处)。截至目前,我认为利用 Heroku 的应用程序功能是一个潜在的长期解决方案。这是我选择何塞的Flask课程的另一个原因;我从未构建过 web 应用程序,他展示了如何使用 SQLAlchemy 作为 Flask 应用程序的数据库。为了加深我对在 Heroku 上部署带有数据库的应用程序的理解,我的重点将是确定在一个交互式 web 应用程序中获取要分析的 finance-API 数据的最佳方式,我可以按照指定的时间表用新数据刷新该应用程序。

对我来说,长期的解决方案需要更多的学习,但这绝对是我想在今年剩下的时间里接受的挑战。我希望这篇文章对你有用,我欢迎评论中的任何反馈,包括我没有提到的,你认为更适合这个应用及其分析的其他选项。

如果你喜欢这篇文章,如果你能点击“拍手”图标让我知道并帮助增加我的作品的发行量,那将是非常棒的。

也可以在 twitter 上联系我, @kevinboller ,我的个人博客可以在这里找到。感谢阅读!

金融 Python:股票投资组合分析

原文:https://towardsdatascience.com/python-for-finance-stock-portfolio-analyses-6da4c3e61054?source=collection_archive---------0-----------------------

我最近的两篇博文是关于用 Python 扩展分析洞察力的;第一部分可以在这里找到,第二部分可以在这里找到。我写这些已经有几个月了,主要是因为去年 11 月我把家搬到了西雅图,加入了亚马逊;我花了大部分时间在我的主要项目上,确定我们的全球推广计划和相关的商业智能路线图。

在我离开我以前的公司 FloSports 之前,我们正在对整个组织的分析报告进行彻底检查(数据、营销、产品等),这次彻底检查的一部分包括我们的财务报告。虽然我很早就离开了这个实现,但在过去的几个月里,我继续广泛使用 Python 进行财务分析,尤其是pandas。在这篇文章中,我将分享我如何利用一些非常有用的在线资源,Yahoo Finance API(需要一个解决方案,可能需要未来的数据源替换),以及Jupyter notebook来在很大程度上自动跟踪和衡量股票投资组合的表现。

PME 和基准个股表现概述

作为一个快速的背景,我从 2002 年开始投资我自己的股票投资组合,并在几年前为我的投资组合开发了一个金融模型。多年来,我会下载历史价格并将数据加载到金融模型中——虽然在线经纪人计算已实现和未实现的回报,以及收入和股息,但我喜欢在模型中拥有历史数据,因为我自己进行分析来评估头寸。我从未在在线经纪人和服务中发现的一个观点/报告是类似于“公共市场等价物”的分析。简而言之,公开市场等价物(PME)是私募股权行业中使用的一组分析,用于比较私募股权基金相对于行业基准的表现。更多细节在这里。

与此相关,绝大多数股票投资组合经理无法选择长期表现优于大盘(如标准普尔 500)的股票投资组合(20 只积极管理的国内基金中有 1 只跑赢指数基金)。即使一些个股表现出色,其他股票的表现不佳也往往超过表现更好的股票,这意味着总体而言,投资者的情况比单纯投资指数基金更糟。在商学院期间,我了解了 PME,并把一个概念上类似的分析纳入了对我目前持有的公共股票的评估。为了正确地做到这一点,你应该衡量每个投资组合头寸(持有期)相对于相同持有期内标准普尔 500 等值美元投资的投资流入时间。举例来说,如果你在 2016 年 6 月 1 日购买了一只股票,并且你仍然持有它,你会想要比较这只股票在这一时期的回报率与 2016 年 6 月 1 日同等美元投资在标准普尔 500 指数中的回报率(我们的基准例子)。除此之外,你可能会发现,即使一只股票表现相对较好,它仍可能落后于同期标准普尔 500 指数的回报。

过去,我从雅虎财经(Yahoo Finance)下载历史价格数据,并在 excel 中使用指数和匹配功能来计算每个头寸相对于标准普尔 500 的相对持有期表现。虽然这是实现这一目标的好方法,但在 Jupyter notebook 中使用pandas进行同样的操作更具可伸缩性和可扩展性。每当您下载新数据并加载到 excel 中时,您不可避免地需要修改一些公式并验证错误。使用pandas,添加新的计算,比如累积 ROI 倍数(我将介绍),几乎不需要时间就可以实现。我使用Plotly的视觉化效果是高度可重复的,在产生洞察力方面更有用。

披露: 本帖无任何内容应视为投资建议。过去的表现不一定代表未来的回报。这些是关于如何使用 pandas 导入不同时间间隔的小样本股票数据,并根据某个指数衡量其个别表现的一般示例。你应该向你的财务顾问提出所有与投资相关的问题。

除了贡献本教程之外,我还将继续修改和构建这种方法,并在本文的最后概述了进一步开发的一些考虑因素。我相信这篇文章会对初级到中级的面向数据科学的金融专业人士有所帮助,特别是因为这应该扩展到许多其他类型的金融分析。这种方法是“类似 PME”的,因为它在相等的持有期内测量投资流入。由于公开市场投资比私募股权投资更具流动性,并且假设你遵循跟踪止损方法,在我看来,更重要的是专注于积极持股——通常可取的做法是减持表现低于基准的股票,或者出于各种原因你不再想持有的股票,而我采取长期观点,只要他们拥有我,我就很高兴持有表现出色的股票。

资源:

  • 我目前是 DataCamp 的订户(未来的帖子将在 DataCamp 上发布),这个关于 Python 金融的社区教程非常棒。
  • 我为这篇文章创建了回购,包括 Python 笔记本和 excel 文件。
  • 如果你想看完整的互动版(因为 Jupyter > GitHub 集成太牛逼了),可以在这里用 nbviewer 查看。

我们想要实现的目标概述:

  • 使用 Yahoo Finance API 导入标准普尔 500 和样本股票数据
  • 创建一个合并的投资组合“主”文件,该文件将样本投资组合数据框架与历史股票行情和历史标准普尔 500 数据相结合
  • 确定每笔投资收购日的标准普尔 500 收盘价,这样我们就可以用同样的投资金额计算标准普尔 500 的等价股票头寸
  • 计算这段时间内投资组合头寸相对于标准普尔 500 回报的相对百分比和美元价值回报
  • 计算累积投资组合回报和投资回报率倍数,以评估该示例投资组合与市场指数相比的表现
  • 更重要的一点是:动态计算每个头寸相对于跟踪止损的表现,例如,如果一个头寸收盘时比收盘高点低 25%,考虑在下一个交易日卖出该头寸。
  • 形象化
  • 总回报比较——每个头寸相对于指数基准的回报百分比
  • 一段时间内的累积回报——每个头寸相对于基准的收益/(损失)
  • 一段时间内的累计投资——鉴于上述情况,与同等权重和时间周期的标准普尔 500 投资相比,总体投资回报如何?
  • 最高价比较的调整收盘百分比——自买入以来,每个头寸相对于其调整收盘最高价的最近收盘百分比是多少?

投资组合 Python 笔记本

数据导入和数据框操作

您将从导入必要的 Python 库开始,导入Plotly离线模块,并读入我们的样例组合数据框架。

*# Import initial libraries*import pandas **as** pd
import numpy **as** np
import datetime
import matplotlib.pyplot **as** plt
import plotly.graph_objs **as** go
**%**matplotlib inline*# Imports in order to be able to use Plotly offline.*
from plotly import __version__
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot**print**(__version__) *# requires version >= 1.9.0*init_notebook_mode(connected**=**True)*# Import the Sample worksheet with acquisition dates and initial cost basis:*portfolio_df **=** pd**.**read_excel('Sample stocks acquisition dates_costs.xlsx', sheetname**=**'Sample')portfolio_df**.**head(10)

现在,您已经阅读了样本投资组合文件,您将创建几个变量来捕获标准普尔 500 和所有投资组合报价机的日期范围。请注意,这是该笔记本要求每周更新的少数几个方面之一(调整日期范围,以包括最近的交易周,在这里,我们正在运行截至 2018 年 3 月 9 日的价格)。

*# Date Ranges for SP 500 and for all tickers*
*# Modify these date ranges each week.**# The below will pull back stock prices from the start date until end date specified.*
start_sp **=** datetime**.**datetime(2013, 1, 1)
end_sp **=** datetime**.**datetime(2018, 3, 9)*# This variable is used for YTD performance.*
end_of_last_year **=** datetime**.**datetime(2017, 12, 29)*# These are separate if for some reason want different date range than SP.*
stocks_start **=** datetime**.**datetime(2013, 1, 1)
stocks_end **=** datetime**.**datetime(2018, 3, 9)

正如 Python 金融培训帖子中提到的,pandas-datareader包使我们能够从像 Google、Yahoo!金融与世界银行。这里我将重点介绍雅虎!金融,尽管我已经和 Quantopian 初步合作过,并且也已经开始把quandl作为一个数据源。正如 DataCamp 帖子中提到的,Yahoo API 端点最近发生了变化,这需要安装一个临时修复程序,以便 Yahoo!金融到工作。我在下面的代码中做了一些必要的小调整。我注意到一些小的数据问题,数据并不总是如预期的那样读入,或者最后一个交易日有时会丢失。虽然这些问题相对较少,但我会继续关注雅虎!金融将是未来最好、最可靠的数据来源。

*# Leveraged from the helpful Datacamp Python Finance trading blog post.*from pandas_datareader import data **as** pdr
import fix_yahoo_finance **as** yf
yf**.**pdr_override() *# <== that's all it takes :-)*sp500 **=** pdr**.**get_data_yahoo('^GSPC', start_sp,end_sp)sp500**.**head()

如果你用你自己的笔记本在跟踪,一旦你成功地从雅虎的 API 中读取数据,你应该会看到类似下面的内容:

在加载标准普尔 500 数据后,您将看到我检查了数据帧的头部和尾部,并压缩数据帧,使其只包含Adj Close列。Adjusted Close栏和Close栏的不同之处在于,调整后的收盘反映了股息(参见下面的未来发展领域)。当一家公司派发股息时,股价会因每股股息的大小而下跌,因为该公司正在分配公司收益的一部分。为了这个分析的目的,您只需要分析这个列。我还创建了一个数据框架,其中只包括标准普尔在 2017 年最后一天(2018 年初)调整后的收盘价;这是为了对单个股票相对于标准普尔 500 指数的表现进行年初至今的比较。

在下面的代码中,您在我们的投资组合样本数据框架中创建了一个所有报价机的数组。然后,您编写一个函数,将所有报价机及其相关数据读入一个新的数据框架,这与您对 S&P500 采取的方法基本相同,但适用于投资组合的所有报价机。

*# Generate a dynamic list of tickers to pull from Yahoo Finance API based on the imported file with tickers.*
tickers **=** portfolio_df['Ticker']**.**unique()
tickers*# Stock comparison code***def** **get**(tickers, startdate, enddate):**def** **data**(ticker):**return** (pdr**.**get_data_yahoo(ticker, start**=**startdate, end**=**enddate))datas **=** map(data, tickers)**return**(pd**.**concat(datas, keys**=**tickers, names**=**['Ticker', 'Date']))all_data **=** get(tickers, stocks_start, stocks_end)

与标准普尔 500 数据框架一样,您将创建一个adj_close数据框架,其中只有用于您所有股票报价机的Adj Close列。如果你看看我上面链接的 repo 中的笔记本,这段代码被分成了比下面更多的代码块。为了在这里进行描述,我在下面列出了导致我们最初的merged_portfolio数据帧的所有代码。

*# Also only pulling the ticker, date and adj. close columns for our tickers.*adj_close **=** all_data[['Adj Close']]**.**reset_index()
adj_close**.**head()*# Grabbing the ticker close from the end of last year*
adj_close_start **=** adj_close[adj_close['Date']**==**end_of_last_year]
adj_close_start**.**head()*# Grab the latest stock close price*adj_close_latest **=** adj_close[adj_close['Date']**==**stocks_end]
adj_close_latestadj_close_latest**.**set_index('Ticker', inplace**=**True)
adj_close_latest**.**head()*# Set portfolio index prior to merging with the adj close latest.*
portfolio_df**.**set_index(['Ticker'], inplace**=**True)portfolio_df**.**head()*# Merge the portfolio dataframe with the adj close dataframe; they are being joined by their indexes.*merged_portfolio **=** pd**.**merge(portfolio_df, adj_close_latest, left_index**=**True, right_index**=**True)
merged_portfolio**.**head()*# The below creates a new column which is the ticker return; takes the latest adjusted close for each position*
*# and divides that by the initial share cost.*merged_portfolio['ticker return'] **=** merged_portfolio['Adj Close'] **/** merged_portfolio['Unit Cost'] **-** 1merged_portfolio

根据你对pandas的熟悉程度,这将会非常简单,甚至有点让人不知所措。下面,我将解开这些行是做什么的:

  • 你所采取的整体方法是一个分割-应用-组合的例子(注意这下载了一个 PDF)。
  • all_data[['Adj Close']]行创建一个新的 dataframe,只包含列表中提供的列;这里Adj Close是列表中唯一提供的项目。
  • 使用这一行代码adj_close[adj_close['Date']==end_of_last_year],您将过滤adj_close数据帧,只过滤数据的Date列等于您之前在end_of_last_year变量(2017,12,29)中指定的日期的行。
  • 您还可以设置adj_close_latestportfolio_df数据帧的索引。我这样做是因为这是合并两个数据帧的方法。merge函数非常类似于 SQL 连接,是我经常使用的一个非常有用的函数。
  • merge函数中,指定左侧数据帧(portfolio_df)和右侧数据帧(adj_close_latest)。通过指定left_indexright_index等于 True,您声明这两个数据帧共享一个公共索引,并且您将在这个索引上连接这两个数据帧。
  • 最后,创建一个名为'ticker return'的新列。这通过将Adj Close除以Unit Cost(股票的初始购买价格)并减去 1 来计算每个股票头寸的百分比回报。这类似于在 excel 中计算一个公式并将其携带下来,但在pandas中,这是用一行代码完成的。

你已经获得了标准普尔 500 和个股的单个数据框架,你开始开发一个“主”数据框架,我们将使用它进行计算、可视化和任何进一步的分析。接下来,您将进一步使用 pandas merge函数,继续构建这个“主”数据框架。下面,您重置当前数据帧的索引,并开始将较小的数据帧与主数据帧连接起来。同样,下面的代码块在Jupyter笔记本中被进一步分解;在这里,我采取了与之前类似的方法,我将分享下面的代码,然后分解代码块下面的关键标注。

merged_portfolio**.**reset_index(inplace**=**True)*# Here we are merging the new dataframe with the sp500 adjusted closes since the sp start price based on* 
*# each ticker's acquisition date and sp500 close date.*merged_portfolio_sp **=** pd**.**merge(merged_portfolio, sp_500_adj_close, left_on**=**'Acquisition Date', right_on**=**'Date')
*# .set_index('Ticker')**# We will delete the additional date column which is created from this merge.*
*# We then rename columns to Latest Date and then reflect Ticker Adj Close and SP 500 Initial Close.***del** merged_portfolio_sp['Date_y']merged_portfolio_sp**.**rename(columns**=**{'Date_x': 'Latest Date', 'Adj Close_x': 'Ticker Adj Close', 'Adj Close_y': 'SP 500 Initial Close'}, inplace**=**True)*# This new column determines what SP 500 equivalent purchase would have been at purchase date of stock.*
merged_portfolio_sp['Equiv SP Shares'] **=** merged_portfolio_sp['Cost Basis'] **/** merged_portfolio_sp['SP 500 Initial Close']
merged_portfolio_sp**.**head()*# We are joining the developing dataframe with the sp500 closes again, this time with the latest close for SP.*
merged_portfolio_sp_latest **=** pd**.**merge(merged_portfolio_sp, sp_500_adj_close, left_on**=**'Latest Date', right_on**=**'Date')*# Once again need to delete the new Date column added as it's redundant to Latest Date.* 
*# Modify Adj Close from the sp dataframe to distinguish it by calling it the SP 500 Latest Close.***del** merged_portfolio_sp_latest['Date']merged_portfolio_sp_latest**.**rename(columns**=**{'Adj Close': 'SP 500 Latest Close'}, inplace**=**True)merged_portfolio_sp_latest**.**head()
  • 使用merged_portfolio上的reset_index来展平主数据框,并连接较小数据框的相关列。
  • merged_portfolio_sp行,将当前主数据帧(merged_portfolio)与sp_500_adj_close合并;你这样做是为了得到标准普尔在每个头寸购买日的收盘价——这允许你跟踪标准普尔在持有每个头寸的同一时间段(从购买日到最近的市场收盘日)的表现。
  • 这里的合并与之前略有不同,我们在左侧数据帧的Acquisition Date列和右侧数据帧的Date列进行了连接。
  • 完成合并后,您将拥有不需要的额外列——因为我们的主数据框架最终将拥有大量用于分析的列,所以在此过程中删除重复和不必要的列非常重要。
  • 有几种方法可以删除不必要的列并执行各种列名清理;为了简单起见,我使用python del,然后用熊猫rename的方法重命名几列,通过重命名为Ticker Adj Close来澄清股票代码的Adj Close列;你可以用SP 500 Initial Close来区分 S & P 的初始调整关闭。
  • 当您计算merged_portfolio_sp['Equiv SP Shares']时,您这样做是为了能够计算出在您获得每个股票头寸的日期收盘时标准普尔 500 的等值:如果您在一个新的股票头寸上花费了 5000 美元,您可能已经在标准普尔 500 上花费了 5000 美元;继续这个例子,如果标准普尔 500 指数在购买时的交易价格是每股 2500 美元,你就可以购买 2 股。之后,如果标准普尔 500 指数的交易价格为每股 3000 美元,你的股份将价值 6000 美元(相当于 2 股*每股 3000 美元),在可比的时间段内,你将有 1000 美元的账面利润。
  • 在代码块的其余部分,您接下来执行类似的合并,这一次加入标准普尔 500 的最新收盘数据—这提供了计算 S&P 相对于每个头寸持有期的可比回报所需的第二部分:每个股票收购日的标准普尔 500 价格和标准普尔 500 的最新收盘数据。

现在,您已经用以下内容进一步开发了您的“主”数据框架:

  • 每个投资组合头寸在头寸收购日的价格、份额和价值,以及最新的市场收盘价。
  • 每只股票在等价头寸收购日的等价标准普尔 500 价格、股份和价值,以及最新的标准普尔 500 收盘价。

鉴于上述情况,您接下来将执行必要的计算,以比较每个头寸的表现,以及该策略/一篮子股票相对于可比美元投资和标准普尔 500 持有时间的整体表现。

下面是您添加到“主”数据框架的新列的摘要。

  • 在第一列['SP Return']中,您创建了一个列来计算标准普尔 500 指数在每个头寸的持有期内的绝对百分比回报(注意,这是绝对回报,而不是年化回报)。在第二列(['Abs. Return Compare'])中,您比较了同一时间段内['ticker return'](每个仓位的回报)与['SP Return']
  • 在接下来的三列['Ticker Share Value']['SP 500 Value']['Abs Value Compare']中,我们根据我们持有的股票乘以最新调整后的收盘价来计算美元价值(市值)(并从股票行情自动收录器中减去 S & P 回报,以计算超额/(低于)业绩)。
  • 最后,['Stock Gain / (Loss)']['SP 500 Gain / (Loss)']栏计算我们每个头寸的未实现美元损益和可比标准普尔 500 的损益;这让我们能够比较每个头寸与简单地将这些美元投资于标准普尔 500 指数的价值影响。
*# Percent return of SP from acquisition date of position through latest trading day.*
merged_portfolio_sp_latest['SP Return'] **=** merged_portfolio_sp_latest['SP 500 Latest Close'] **/** merged_portfolio_sp_latest['SP 500 Initial Close'] **-** 1*# This is a new column which takes the tickers return and subtracts the sp 500 equivalent range return.*
merged_portfolio_sp_latest['Abs. Return Compare'] **=** merged_portfolio_sp_latest['ticker return'] **-** merged_portfolio_sp_latest['SP Return']*# This is a new column where we calculate the ticker's share value by multiplying the original quantity by the latest close.*
merged_portfolio_sp_latest['Ticker Share Value'] **=** merged_portfolio_sp_latest['Quantity'] ***** merged_portfolio_sp_latest['Ticker Adj Close']*# We calculate the equivalent SP 500 Value if we take the original SP shares * the latest SP 500 share price.*
merged_portfolio_sp_latest['SP 500 Value'] **=** merged_portfolio_sp_latest['Equiv SP Shares'] ***** merged_portfolio_sp_latest['SP 500 Latest Close']*# This is a new column where we take the current market value for the shares and subtract the SP 500 value.*
merged_portfolio_sp_latest['Abs Value Compare'] **=** merged_portfolio_sp_latest['Ticker Share Value'] **-** merged_portfolio_sp_latest['SP 500 Value']*# This column calculates profit / loss for stock position.*
merged_portfolio_sp_latest['Stock Gain / (Loss)'] **=** merged_portfolio_sp_latest['Ticker Share Value'] **-** merged_portfolio_sp_latest['Cost Basis']*# This column calculates profit / loss for SP 500.*
merged_portfolio_sp_latest['SP 500 Gain / (Loss)'] **=** merged_portfolio_sp_latest['SP 500 Value'] **-** merged_portfolio_sp_latest['Cost Basis']merged_portfolio_sp_latest**.**head()

现在,您已经了解了将您的投资组合的表现与同等投资于标准普尔 500 的投资组合进行比较所需的内容。接下来的两个代码块部分允许您 I)比较每个头寸相对于标准普尔 500 的 YTD 表现(衡量动量和您的头寸如何调整),以及 ii)比较每个投资组合头寸相对于其最近收盘高点的最近收盘价(这允许您评估头寸是否触发了跟踪止损,例如,收盘时比收盘高点低 25%。

下面,我将从 YTD 性能代码块开始,并在下面进一步提供有关代码的细节。

*# Merge the overall dataframe with the adj close start of year dataframe for YTD tracking of tickers.*merged_portfolio_sp_latest_YTD **=** pd**.**merge(merged_portfolio_sp_latest, adj_close_start, on**=**'Ticker')
*# , how='outer'**# Deleting date again as it's an unnecessary column.  Explaining that new column is the Ticker Start of Year Close.***del** merged_portfolio_sp_latest_YTD['Date']merged_portfolio_sp_latest_YTD**.**rename(columns**=**{'Adj Close': 'Ticker Start Year Close'}, inplace**=**True)*# Join the SP 500 start of year with current dataframe for SP 500 ytd comparisons to tickers.*merged_portfolio_sp_latest_YTD_sp **=** pd**.**merge(merged_portfolio_sp_latest_YTD, sp_500_adj_close_start, left_on**=**'Start of Year', right_on**=**'Date')*# Deleting another unneeded Date column.***del** merged_portfolio_sp_latest_YTD_sp['Date']*# Renaming so that it's clear this column is SP 500 start of year close.*
merged_portfolio_sp_latest_YTD_sp**.**rename(columns**=**{'Adj Close': 'SP Start Year Close'}, inplace**=**True)*# YTD return for portfolio position.*
merged_portfolio_sp_latest_YTD_sp['Share YTD'] **=** merged_portfolio_sp_latest_YTD_sp['Ticker Adj Close'] **/** merged_portfolio_sp_latest_YTD_sp['Ticker Start Year Close'] **-** 1*# YTD return for SP to run compares.*
merged_portfolio_sp_latest_YTD_sp['SP 500 YTD'] **=** merged_portfolio_sp_latest_YTD_sp['SP 500 Latest Close'] **/** merged_portfolio_sp_latest_YTD_sp['SP Start Year Close'] **-** 1
  • 创建merged_portfolio_sp_latest_YTD数据帧时,您现在将“主”数据帧与adj_close_start数据帧合并;作为一个快速提醒,您是通过过滤adj_close数据帧来创建这个数据帧的,其中'Date'列等于变量end_of_last_year;你这样做是因为这是衡量 YTD(年初至今)股票和指数表现的方法;去年的收盘价格是下一年的起始价格。
  • 从这里开始,我们再次使用del删除不必要的列,并使用rename方法阐明“主”数据帧新添加的列。
  • 最后,我们获取每个股票(在['Ticker Adj Close']列中)并计算每个股票的 YTD 回报(对于'SP 500 Latest Close'列中的每个值,我们还有一个 S & P 500 等值)。

在下面的代码块中,您使用sort_values方法对我们的“主”数据框架进行重新排序,然后计算累积投资组合投资(您的持仓获取成本的总和),以及投资组合持仓的累积价值和理论标准普尔 500 指数投资的累积价值。这使你能够看到你的总投资组合,包括在整个期间不同时间的投资,与你只投资于一个指数的策略相比是如何的。稍后,您将使用['Cum Ticker ROI Mult']来帮助您形象化每项投资对您的总体投资回报(ROI)的贡献或减少。

merged_portfolio_sp_latest_YTD_sp **=** merged_portfolio_sp_latest_YTD_sp**.**sort_values(by**=**'Ticker', ascending**=**True)*# Cumulative sum of original investment*
merged_portfolio_sp_latest_YTD_sp['Cum Invst'] **=** merged_portfolio_sp_latest_YTD_sp['Cost Basis']**.**cumsum()*# Cumulative sum of Ticker Share Value (latest FMV based on initial quantity purchased).*
merged_portfolio_sp_latest_YTD_sp['Cum Ticker Returns'] **=** merged_portfolio_sp_latest_YTD_sp['Ticker Share Value']**.**cumsum()*# Cumulative sum of SP Share Value (latest FMV driven off of initial SP equiv purchase).*
merged_portfolio_sp_latest_YTD_sp['Cum SP Returns'] **=** merged_portfolio_sp_latest_YTD_sp['SP 500 Value']**.**cumsum()*# Cumulative CoC multiple return for stock investments*
merged_portfolio_sp_latest_YTD_sp['Cum Ticker ROI Mult'] **=** merged_portfolio_sp_latest_YTD_sp['Cum Ticker Returns'] **/** merged_portfolio_sp_latest_YTD_sp['Cum Invst']merged_portfolio_sp_latest_YTD_sp**.**head()

现在,您已经接近尾声,几乎准备好开始可视化您的数据,并评估您的投资组合的单个股票和整体策略表现的优势和劣势。

和以前一样,我包含了主要的代码块,用于确定头寸相对于最近收盘价的交易位置;然后,我将在下面进一步解包代码。

*# Need to factor in that some positions were purchased much more recently than others.*
*# Join adj_close dataframe with portfolio in order to have acquisition date.*portfolio_df**.**reset_index(inplace**=**True)adj_close_acq_date **=** pd**.**merge(adj_close, portfolio_df, on**=**'Ticker')*# delete_columns = ['Quantity', 'Unit Cost', 'Cost Basis', 'Start of Year']***del** adj_close_acq_date['Quantity']
**del** adj_close_acq_date['Unit Cost']
**del** adj_close_acq_date['Cost Basis']
**del** adj_close_acq_date['Start of Year']*# Sort by these columns in this order in order to make it clearer where compare for each position should begin.*
adj_close_acq_date**.**sort_values(by**=**['Ticker', 'Acquisition Date', 'Date'], ascending**=**[True, True, True], inplace**=**True)*# Anything less than 0 means that the stock close was prior to acquisition.*
adj_close_acq_date['Date Delta'] **=** adj_close_acq_date['Date'] **-** adj_close_acq_date['Acquisition Date']adj_close_acq_date['Date Delta'] **=** adj_close_acq_date[['Date Delta']]**.**apply(pd**.**to_numeric)*# Modified the dataframe being evaluated to look at highest close which occurred after Acquisition Date (aka, not prior to purchase).*adj_close_acq_date_modified **=** adj_close_acq_date[adj_close_acq_date['Date Delta']**>=**0]*# This pivot table will index on the Ticker and Acquisition Date, and find the max adjusted close.*adj_close_pivot **=** adj_close_acq_date_modified**.**pivot_table(index**=**['Ticker', 'Acquisition Date'], values**=**'Adj Close', aggfunc**=**np**.**max)adj_close_pivot**.**reset_index(inplace**=**True)*# Merge the adj close pivot table with the adj_close table in order to grab the date of the Adj Close High (good to know).*adj_close_pivot_merged **=** pd**.**merge(adj_close_pivot, adj_close, on**=**['Ticker', 'Adj Close'])*# Merge the Adj Close pivot table with the master dataframe to have the closing high since you have owned the stock.*merged_portfolio_sp_latest_YTD_sp_closing_high **=** pd**.**merge(merged_portfolio_sp_latest_YTD_sp, adj_close_pivot_merged, on**=**['Ticker', 'Acquisition Date'])*# Renaming so that it's clear that the new columns are closing high and closing high date.*
merged_portfolio_sp_latest_YTD_sp_closing_high**.**rename(columns**=**{'Adj Close': 'Closing High Adj Close', 'Date': 'Closing High Adj Close Date'}, inplace**=**True)merged_portfolio_sp_latest_YTD_sp_closing_high['Pct off High'] **=** merged_portfolio_sp_latest_YTD_sp_closing_high['Ticker Adj Close'] **/** merged_portfolio_sp_latest_YTD_sp_closing_high['Closing High Adj Close'] **-** 1 merged_portfolio_sp_latest_YTD_sp_closing_high
  • 首先,将adj_close数据帧与portfolio_df数据帧合并;这是你第三次利用这个adj_close数据框架来进行单独的分析,然后将它与整个“主”数据框架相结合。
  • 这种初始合并不是特别有用,因为你有日期和调整后的收盘价,这些日期和价格都在你收购每个头寸的日期之前;因此,我们将对收购日期后的数据进行子集化,然后找到从那时起的max收盘价。
  • 我再次使用del删除合并后的 dataframe 中不需要的列;这是我应该重构的代码,因为创建一个列表,例如cols_to_keep,然后用它过滤数据帧将是一个更好的方法——作为参考,多次运行del代码块将会抛出一个错误,您需要重新初始化您的数据帧,然后再次运行del代码块。
  • 在删除不必要的列之后,使用sort_values方法,按照'Ticker''Acquisition Date''Date'列对值进行排序(都是升序);您这样做是为了确保所有的股票行都排序在一起,我们按收购日期(以防我们不止一次购买同一只股票)和日期升序排序,以便过滤出您的头寸收购日期之前的日期。换句话说,你只关心收盘高点,因为你已经建仓了。
  • 为了过滤我们的数据框架,您创建了一个新列['Date Delta'],它是通过日期和采集日期列之间的差异计算的。
  • 然后将该列转换成数字列,并创建一个名为adj_close_acq_date_modified的新数据帧,其中['Date Delta']为> = 0。这确保了你只评估自你买入每个头寸之日起的收盘高点。
  • 现在您已经有了adj_close_acq_date_modified数据框架,我们将使用一个非常强大的名为pivot_table的 pandas 函数。如果您熟悉 Excel 中的数据透视表,该函数与此类似,您可以基于单个或多个索引透视数据,指定要计算的值和要透视的列,还可以使用agg functions(利用numpy)。
  • 使用pivot_table函数,我们以报价机和采集日期为中心,并指定我们希望找到每个位置的最大值(np.max)Adj Close;这允许您将每个头寸的最近调整收盘价与此最高调整收盘价进行比较。
  • 现在您有了一个adj_close_pivot数据帧,您重置了索引并在adj_close数据帧上再次连接它。这就创建了adj_close_pivot_merged数据框架,它告诉你何时买入了每个头寸,以及自买入以来触及收盘高点的日期。
  • 最后,我们将“主”数据帧与最后一个较小的数据帧adj_close_pivot_merged合并。
  • 这样做之后,您现在能够计算所需的最后一列['Pct off High']。你用['Ticker Adj Close']除以['Closing High Adj Close'],然后减去 1。请注意,该百分比将始终为负,除非该股票碰巧在最近评估的交易日有最高收盘价(在这种情况下为零)(如果是这样,这通常是一个非常好的迹象)。

这是一个非常重要的提升,现在是我们期待已久的可视化的时候了。如果你继续在你自己的笔记本上跟随,你现在有一个非常丰富的数据框架,有许多计算的投资组合指标,如下所示:

总回报和累计回报可视化

对于所有这些可视化,您将使用Plotly,它允许您完全不用代码就可以制作 D3 图表。虽然我也用MatplotlibSeaborn,但是我真的很看重Plotly的互动性;一旦你习惯了,语法变得相当简单,动态图表也很容易获得。

下面的第一个图表比较了每个头寸相对于标准普尔 500 的总回报(头寸和标准普尔 500 假设投资的持有期相同)。在下面,你会看到在他们不同的持有期,8 个位置中的 6 个跑赢了标准普尔。最后两个,Twitter(实际上有负回报)和沃尔玛跑输了同等时间的标准普尔 500 投资。

由于这些可视化相对相似,我将解释生成上述 Plotly 可视化所需的代码,对于其余的,我将只总结每个可视化的观察结果。

trace1 **=** go**.**Bar(x **=** merged_portfolio_sp_latest_YTD_sp_closing_high['Ticker'][0:10],y **=** merged_portfolio_sp_latest_YTD_sp_closing_high['ticker return'][0:10],name **=** 'Ticker Total Return')trace2 **=** go**.**Scatter(x **=** merged_portfolio_sp_latest_YTD_sp_closing_high['Ticker'][0:10],y **=** merged_portfolio_sp_latest_YTD_sp_closing_high['SP Return'][0:10],name **=** 'SP500 Total Return')data **=** [trace1, trace2]layout **=** go**.**Layout(title **=** 'Total Return vs S&P 500', barmode **=** 'group', yaxis**=**dict(title**=**'Returns', tickformat**=**".2%"), xaxis**=**dict(title**=**'Ticker'), legend**=**dict(x**=.**8,y**=**1))fig **=** go**.**Figure(data**=**data, layout**=**layout)
iplot(fig)
  • 当使用Plotly时,您创建traces,它将绘制您指定的 x 和 y 数据。在这里,您在 trace1 中指定要绘制一个条形图,每个报价器在 x 轴上,每个报价器的回报率在 y 轴上。
  • 在 trace2 中,为了稍微分解一下数据,我们将使用一个散点图,在 x 轴上显示股票,在 y 轴上显示 S&P 回报率。
  • 当棒线在线上时,单个股票(8 次中的 6 次)的表现超过了标准普尔 500。
  • 然后用这些跟踪创建一个数据对象,然后为图表提供一个布局;在这种情况下,您需要指定标题、barmode 和图例的位置。您还可以为 y 轴系列传入标题和刻度格式(小数点后两位的百分比格式)。
  • 然后您使用go.Figure创建一个图形对象,指定数据和布局对象,您之前将它们命名为datalayout

下面的图表显示了每个仓位相对于标准普尔 500 的盈利/(亏损)金额,以及股票总回报率%。虽然通常建议您为您的头寸分配相等的头寸规模(或可能根据隐含波动率确定头寸规模),但情况可能并非总是如此。对于波动性较小的投资,您可能会比风险较高的头寸投资更多(或者您可能有其他头寸规模调整规则)。有鉴于此,这种可视化显示了每个位置的回报和美元价值的贡献,你的整体投资组合的回报。

在这里,你可以看到,虽然你在脸书的投资比其他头寸略少,但这只股票在这个模拟投资组合中获得了约 2 万美元的回报,比同期同等标准普尔 500 投资的 4 倍回报率还要高。

下面的图表利用了您创建的累积列:'Cum Invst''Cum SP Returns''Cum Ticker Returns''Cum Ticker ROI Mult'

  • 在 x 轴上,你按字母顺序对投资组合进行了排序。每个头寸显示该头寸的初始投资和总价值(投资加上收益或减去损失),以及之前的头寸。
  • 为了进一步解释,根据在 AAPL 的约 8k 美元投资,这增长到约 22.5k 美元(收益为 14k 美元),而标准普尔的总价值为 15k 美元。这是对 AAPL 初始投资的 2.75 倍回报(8k 美元投资的 22.5k 价值是约 2.75 倍 ROI)。
  • 继续说 FB,你总共投资了约 1.6 万美元(两个头寸都是 8 万美元),现在已经超过 5 万美元,总回报超过 3 倍,这意味着 FB 扩大了你的整体投资组合投资回报率。
  • 沿着 x 轴往下,您会看到 TWTR 和 WMT 都降低了整体投资组合的投资回报率,这是显而易见的,因为两者的表现都不如 S&P,但我相信通过这种可视化,贡献的幅度会更明显。
  • 需要注意的是,考虑到不同的持有期,这种累积方法对于一些基于买入时间的头寸来说有点像苹果和橘子的组合。但是,您可以通过细分成更小的数据框架来隔离这种分析,并单独比较持有期更一致的头寸。例如,你可以分别比较你在 2H 2016 年和 1H 2017 年的购买情况。

高比较的调整收盘百分比

您的最终图表比较了每个头寸的最新收盘价与买入后调整后的收盘价的差距。这通常是要考虑的一个重要的可视化:

  • 当一只股票以更高的价格收盘时,通常建议你也调整跟踪止损。举例来说,这里有一个例子:
  • 一个头寸以 10 美元买入,翻倍至 20 美元——使用 25%的跟踪止损,如果第二天该头寸收于 15 美元($ 15/$ 20–1 =(25%)),你会想考虑卖出该头寸。
  • 如果仓位增加到 25 美元,你可以考虑将你的跟踪止损移动到 18.75 美元($ 18.75/$ 25–1 =(25%))。
  • 如前所述,本文无意成为财务建议;不同的交易系统有不同的跟踪止损规则,这是一个说明性的例子。
  • 跟踪止损意在帮助保持收益,通常对减轻投资情绪很重要;虽然很容易看到你的头寸的当前回报,但往往需要手动(或者如果你使用跟踪止损服务,有点昂贵)计算你的头寸离跟踪止损有多近。
  • 这种最终的可视化使您可以很容易地评估您正在查看的任何日期;在图表中,我们看到 AAPL、MTCH 和 NFLX 都在 2018 年 3 月 9 日收盘于收盘高点(通常是一个非常好的迹象)。
  • 然而,TWTR 比最高收盘价低 25%以上(截至 2018 年 3 月 9 日,比最高收盘价低 33%),WMT 比最高收盘价低约 20%。
  • 在这种情况下,你可能想卖掉 TWTR,继续密切关注 WMT 的表现。

方法的限制和总结

现在,您有了一个相对可扩展的 Jupyter 笔记本和投资组合数据集,您可以使用它来评估您的股票投资组合,并在您认为合适的时候添加新的指标和可视化。

请注意,虽然本笔记本对投资组合进行了相当全面的审查,但以下内容尚未纳入考虑范围,会对整体比较产生影响,并可能为未来发展提供很大的空间:

  • 如前所述,本笔记本侧重于积极持仓——理想情况下,我们将评估所有头寸,包括已平仓和积极持仓,以便对个人相对于替代方案的投资策略有一个真正全面的了解,如指数比较。
  • 这里的方法不考虑分红。当我们评估调整后的收盘价(反映股息)时,总股东回报结合股价升值和股息来显示股票的总回报;虽然这更难做到,但我正在评估将来是否会包括这一点。
  • 与此相关的是,投资者也可以将股息再投资于某个头寸,而不是进行现金分配;可以说,这甚至比股息会计更复杂,因为收购成本低且分散,在持有一个头寸的几年时间里,你可能每年有四个(或更多)收购日期用于股息再投资股票。

考虑到这些未来的领域,我们在这里取得了很多成就;这包括使用雅虎导入标准普尔 500 和股票数据。金融的 API,并创建一个主数据框架,将您的投资组合与历史股票和比较标准普尔 500 价格相结合。这样,你就可以计算每个头寸的绝对百分比和美元价值回报(并与同期标准普尔 500 投资进行比较),以及每个头寸对你的整体投资组合表现的累积影响。你也可以根据自己的交易规则动态监控你的跟踪止损。你还创造了可视化效果,让你更好地洞察你的主数据框架,关注不同的指标和每个位置对每个指标的贡献。

我希望你觉得这个教程有用,我欢迎评论中的任何反馈。你也可以在推特上联系我, @kevinboller ,我的个人博客可以在这里找到。

面向 Matlab 用户的 Python

原文:https://towardsdatascience.com/python-for-matlab-users-ac3e0b8463a5?source=collection_archive---------5-----------------------

我注意到人们面临的一个普遍问题(尤其是在工程界)是从学术界到工业界的过渡。大多数学校更喜欢让我们使用 Matlab。无论你是电子工程师、化学工程师还是纳米工程师,你很可能在整个大学生涯中都不得不使用 Matlab(除了一点点 C/C++)。业界最近的一个趋势是从 Matlab 过渡到 Python。这可能是由于 1000 多美元的许可费,内存分配的低效率,缺乏开源库,甚至是大多数软件开发人员讨厌 Matlab 语法的事实。幸运的是,Matlab 和 Python 中的语法非常相似(如果你忽略 Matlab 索引从 1 开始而不是从 0 开始的事实)。在本教程中,我为 Matlab 用户介绍了数据分析和可视化领域的 Python 基础知识。

虽然代码可以在这个博客上找到,但我也在 youtube 上发布了相同的材料:

矩阵操作

Matlab 用户首先感兴趣的事情之一是线性代数和矩阵操作。Python 的数学库 numpy 附带了各种工具来执行简单的数学运算。

import numpy as np

让我们假设我们希望首先导出下面的矩阵, A :

对于那些习惯于简单 matlab 语法的人,可以使用以下内容:

A = np.matrix('1,1,1 ; 2,4,5 ; 5,7,6')

然而,Python 逻辑是以向量的形式工作的。因此,最终习惯以下语法很重要:

A = np.matrix([[1,1,1],[2,4,6],[5,7,6]])

现在我们已经定义了我们的矩阵,我们可以首先得到(0,0)值:

A[0,0]

输出:
T3 1

接下来,我们只能得到第一列:

A[:,0]

输出:
[[1]
【2】
【5】]

最后,就第一行:

A[0,:]

输出:
[[1 1 1]]

数学运算

既然我们已经成功地复制了矩阵操作,让我们尝试执行一些基本的数学运算。我们可以使用相同的 Numpy 库和上一节的矩阵 A

添加第一行的值:

np.sum(A[0,:])

输出:
3

A 与其自身的点积:

np.dot(A,A)

输出:
[【8,12,13】,
【40,60,62】,
【49,75,83】]

A 与其自身的叉积:

np.cross(A,A)

输出:
[[0,0,0],
【0,0,0】,
【0,0,0】]

数据绘图

最后,在可视化数据时,绘图非常重要。Python 的 Matplotlib 函数提供了一组广泛的函数来执行绘图操作。

import matplotlib.pyplot as pltplt.figure()
plt.plot(A[:,0])
plt.plot(A[:,1])
plt.title('Sample Matlab type Plot')
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()

输出:

面向运动科学家的 Python:描述性统计

原文:https://towardsdatascience.com/python-for-sport-scientists-descriptive-statistics-96ed7e66ab3c?source=collection_archive---------1-----------------------

了解如何使用易于理解的 Python 代码开始分析运动员相关数据集

Python 在过去的几年里越来越受欢迎,是世界上许多数据科学家的首选语言。它也越来越受体育科学家的欢迎,这并非偶然,因为他们每天都要处理大量的数据。

虽然这篇文章可能对初学 Python 的体育科学家有所帮助,但它并不是对这种语言本身的介绍。更确切地说,它是对如何以一种更实用的方式解决问题和分析数据进行推理的介绍。

此外,本文将使用基本的描述性统计来说明如何构建可组合的函数式 Python 代码来解决问题。

在第一部分,我将介绍集中趋势的两种基本计算方法:平均值和中值。第二部分应用同样的原理计算标准差和方差。最后一部分通过计算两个变量之间的关系来介绍双变量分析。

第 1 部分:平均值和中位数

体育科学家一直在研究关于运动员的数据集,能够调用数据点列表上的mean来获得对它的总体了解是很有用的。在有异常值的数据集的情况下(我们毕竟是在和运动员一起工作),我们可能需要使用median来找出第 50 百分位。

定义平均值

虽然 Python 有统计库可以导入这些函数,但我相信,研究这些统计库对于为以后解决更复杂的问题打下基础非常有帮助。当我们使用平方和或均方误差等可组合函数时,这将更有意义。

让我们首先创建一个.py文件并定义函数mean。下面是一个返回平均值的纯函数:

*# Python 3*
def mean (x):return sum(x) / len(x)

注意,sum()len()是 python 自带的函数,它们返回 Python 数据结构的总和长度。这里的mean函数是一个简单的函数,这意味着它没有副作用(给定相同的输入,它总是返回相同的结果。)

定义中位数

计算中值比平均值稍微复杂一些,但是足够简单。寻找数字列表的中值取决于找到排序列表的一半长度:half = lambda arr: len(arr) / 2。然而,这个函数有两个问题,假设我们要用它来查找索引(从 0 开始。)第一个问题是,它返回一个 float,我们需要一个整数来寻找索引处的值。第二个问题是,如果数字的长度是偶数,我们希望它返回中间两个索引中的第一个。我们可以使用int()函数来解决这个问题。让我们将它添加到我们的文件中:

half()函数现在返回中间的索引(或者在偶数列表的情况下,返回两个中间索引中的第一个):

evenList = [11, 12, 13, 14]
oddList = [21, 22, 23]half(evenList)
# 1half(oddList)
# 1

定义median的下一步是返回该索引处的值。如果长度是偶数,我们需要返回arr[half(arr)]arr[half(arr) + 1]值的平均值来得到中值。因此,让我们最后编写中值函数,并将其添加到我们的文件中:

def median (arr):sortedList = sorted(arr)index = half(sortedList)if isEven(len(sortedList)):return mean([ sortedList[index], sortedList[index + 1] ])else:return sortedList[index]

瞧啊。从上面调用median(evenList)会返回12.5,调用median(oddList)会返回22

这很酷,因为我们使用了刚刚定义的mean()函数!这是用函数编程最有趣的部分——它们作为简单的构件,可以用来解决任何问题。此外,请注意,我们必须在对数据集进行操作之前使用本机sorted()函数返回数据集的排序副本,这对于获得正确的中值至关重要。

把它放在一起

让我们在一个有点实际的例子中使用这两个函数。我将使用一个基本数据集,其中包含一些来自培训课程的 GPS 数据:

data = [{"name": "John",  "distance": 5602,  "high-speed-running": 504},{"name": "Mike",  "distance": 5242,  "high-speed-running": 622},{"name": "Chad",  "distance": 4825,  "high-speed-running": 453},{"name": "Phil",  "distance": 611,   "high-speed-running": 500},{"name": "Tyler", "distance": 5436,  "high-speed-running": 409}
]

这是一个字典列表,所以我们不能就这样叫mean(data[“distance”])。让我们在文件顶部导入方便的pandas库,将数据集转换成 Pandas 数据帧,这样我们就可以简单地对数据集的元素调用mean:

现在我们可以调用mean(df['distance'])返回4343.2。调用median(df[‘distance’])返回5242

要考虑的事情: 在这个特定的数据集中,为什么我们可能要在分析中使用*median*函数而不是*mean*?或者反之亦然。

第 2 部分:标准差和方差

标准差和方差密切相关。例如,方差被定义为标准偏差的平方(或者标准偏差是方差的平方根)。对于可组合的函数,这几乎太容易了!

差异

我们可以从方差开始,因为我们要做的就是对它求平方来得到标准差。我们在第 1 部分中定义的mean函数也将派上用场,还有 Python 的原生len函数。

查看样本方差的等式,并考虑到我们将对其求平方以获得标准差,继续定义一个值的平方函数似乎是一个好主意:

def square(x):return x * x

下一位有点复杂,但是我们可以用一个叫做sumOfSquaredDifferences的函数来计算分子:

def sumOfSquaredDifferences (arr):xBar = mean(arr)differences = map(lambda x: x - xBar, arr)squaredDifferences = map(square, differences)return sum(squaredDifferences)sprintEfforts = [88, 56, 51, 34, 50, 22, 61, 79, 90, 49]sumOfSquaredDifferences(sprintEfforts)
*# 4444*

这个函数本质上是计算每个值和平均值的差(使用高阶map函数),然后求差的平方,并求出平方差的和。够简单!

现在找到样本方差很容易:

def variance (arr):n = len(arr)return sumOfSquaredDifferences(arr) / (n-1)variance(sprintEfforts)
*# 493.7*

标准偏差

总的来说,差异很大,但我们希望有一个我们更熟悉的衡量标准。幸运的是,计算方差的标准差轻而易举,因为它就是方差的平方根:

def sqrt (x):return x**(1/2)def stDev (arr):return sqrt(variance(arr))stDev(sprintEfforts)
*# 22.2*

除了 Python 对幂操作符(**)的古怪语法,这非常简单。让我们将它应用于第 1 部分中的 GPS 分数数据集:

stDev(df['high-speed-running'])
*# 79.62*

第 1 部分中更新后的文件应该是这样的:

关于构成函数的思考

事实证明,将具有单一目的的小而纯的函数组合在一起,有助于将基本的统计概念融入生活。这些统计计算对于实践良好的编程原则来说是完美的。

我们已经用了很多maplambda函数。这些是处理数据列表的基础。为了最有效地构建可组合的功能性代码,尝试掌握并理解如何在任何语言中使用像mapfilterreduce这样的高阶函数是一个好主意。

第 3 部分:相关性

到目前为止,我们已经定义了单变量分析的函数,这些函数对于演示使用单个数据数组非常有用。

现在我们可以应用同样的逻辑,通过探索相关性来进行双变量分析。

绘制数据

使用数据集的首要规则是绘制数据以了解我们在处理什么。为了简单起见,让我们使用import seaborn as sns来创建情节:

该数据集基于第 1 部分和第 2 部分中使用的虚构数据集。但是,如果这些数据代表一个培训课程,则该数据集可以是相同指标的每周总计。这段代码将产生以下情节:

酷!我们马上就能看出“距离”和“高速奔跑”之间有着很强的正线性关系。

皮尔逊氏 r

下一步是通过找出皮尔逊相关系数来对其进行量化,皮尔逊相关系数可以用以下公式表示:

让我们把它分成几部分。我们将需要count代表 nsum代表σ,sqrt,以及square。此外,我们将需要map遍历每个 x 和 y 索引,并将它们相乘,以及对它们求平方。让我们从使用count将 n 添加到我们的文件开始:

# Python3
def n (arr):return arr.count()

下一步是映射每个“x”和“y”对,并返回它们乘积的总和:

def product (x, y):return x * ydef sumXTimesY (x, y):return sum(map(product, x, y))

现在我们可以很容易地定义分子:

def numerator (x, y):return n(x) * sumXTimesY(x, y) - sum(x) * sum(y)

分母看起来有点复杂,需要分解成最小的部分。我们来定义一下sumOfSquares:

def sumOfSquares (val):return sum(map(square, val))

现在,在第 2 部分的sqrt函数的帮助下,我们有了定义分母的所有工具:

def denominator (x, y):return sqrt((n(x) * sumOfSquares(x) - square(sum(x))) * (n(y) * sumOfSquares(y) - square(sum(y))))

现在,我们可以将它们放在文件的最终版本中:

不算太寒酸!我们不仅在**0.88**的 r 处看到了“距离”和“高速奔跑”之间非常强的关系,而且我们已经使用易于推理的功能性和可组合代码将它们放在一起。此外,以这种方式分解皮尔逊 r 公式,可以更深入地理解两个变量之间的关系到底是什么样子。

总结想法

值得重申的是,使用执行统计繁重任务的库是正确的方法,但是本文的重点是使用简单的函数概念来解决复杂的问题。

本文介绍了两个非常强大的数据可视化和分析库:Seaborn 和 Pandas。Seaborn 是一个基于 Matplotlib 的统计可视化库。由于它的简单性和灵活性,它是我进行高级统计绘图的首选库。Pandas 是一个非常棒的数据分析工具包,对于有电子表格工作背景的体育科学家来说非常有吸引力。

我写这篇文章的目的是为体育科学家提供构建功能代码库的工具,并理解如何以模块化和功能化的方式分析数据集。

Python 有一个内置的 Logo Turtle,非常适合强化学习

原文:https://towardsdatascience.com/python-has-a-built-in-logo-turtle-and-its-great-for-reinforcement-learning-6b0dca4acb73?source=collection_archive---------13-----------------------

不久前,我在伯克利教授一门关于数据分析的课程,其中一个练习让学生通过 Python stdlib 来寻找感兴趣的模块。我也浏览了文档,很高兴地发现 Python 有一只乌龟!你还记得吗?

FORWARD 10
LEFT 90

我在 90 年代上的高中还不够富裕,无法拥有一只内置钢笔的机器乌龟(小小提琴开始演奏),但我记得我被这个神奇生物在屏幕上的动作迷住了,我想当时它正在一个橡子阿基米德上运行,这是今天芯片巨头 ARM 的早期产品。我从来不需要一个肺活量描记器,因为海龟在数学曼荼罗的生产中充分地占据了它的位置。

Thanks SchoolCoders (https://www.flickr.com/photos/schoolcoders/)

我在这里和这里之前写过关于强化学习的文章:这是一个我特别感兴趣的话题,因为它提供了一条通往 AGI(奇点)的道路,同时真正暴露了今天深度学习和人工智能的局限性。

框架问题和 Python 的海龟

我想创造一个代理,它能教会自己尽可能长时间地在屏幕上移动:避开屏幕的边缘,也避免撞到自己(像旧的贪吃蛇游戏那样)。

The turtle agent taking some mostly random actions early in training

直觉上,这应该会导致海龟盘绕在自己身上。

我很快发现了 Python 的内置 turtle 的一个可悲的问题:它绘制到一个 Tkinter 画布(如果你以前没有用 Python 做过 GUI 开发,就把它想象成‘某个对象’——像我一样!)而且没有办法从那个画布上读回像素。

所以,我实现了自己的 turtle 库,它包装了内置的(仍然使用它来绘制到屏幕),但也保持画布的 NumPy 数组可用(以及指定数量的先前帧,这对 RL 很有用)。它为 RL 提供了其他一些方便的功能,你可以在我的 Github 这里抓取这个库。我用来做这个项目的最终代码在那个 repo 的examples 文件夹里。

下面是我构建的env.step()函数。你可以看到有 3 种可能的动作,两种结束游戏的情况(海龟离开屏幕或回到它的尾巴),在一集结束时给出的累积奖励(向前移动会产生更高的奖励),以及该动作的即时奖励(每个动作获得 1 个奖励)。

My ‘env.step’ function follows OpenAI’s (state, reward, done, msg) model. Going forward yields a higher reward than spinning around in place. ‘UserConditionException’ is when the turtle attempts to go back over its trail — it dies.

强化学习原则

早期的文章提供了更多的背景知识,但是原理非常简单:

  • 一个代理在一个环境中做出一个动作,并获得一个奖励。
  • 奖励由两部分组成:即时奖励(即密集奖励)(代理人吃了一个苹果),以及延期奖励(即稀疏奖励)(代理人吃了 10 个苹果,赢得了游戏)。
  • 代理人的批评部分比较它对奖励的期望(给定环境的状态和它采取的行动;那些期望开始是随机的)与它收到的实际回报。它们排列得越紧密越好:这意味着它可以用作亏损信号。
  • 延期奖励(从现在到游戏结束的每一步乘以一些折扣因子)被添加到早期奖励中,这样代理人在每一时间步都知道自己在该时间步的行为最终是否带来了好的奖励。

这是演员兼评论家 RL,因为本质上有两个代理人:一个演员,和一个评论家。我们用一个有两个头的神经网络来实现它们。

行动者网络具有对应于可能动作数量的多个输出;选择的动作是其中的软最大值。(输出层的每个神经元的激活或值被解释为一种概率,softmax 确保在 3 种可能的操作下,每个神经元的最大激活为 0.33,因此很容易选择具有最高值的一个)。

不仅仅是批评者在学习如何更好地估计回报,行动者也在学习如何更好地行动:

  • 当不可能的行动产生高回报时,损失信号增加,当行动确定性增加时,损失信号减少。一般来说,随着时间的推移,产生回报的行为应该变得更加确定。

因为行动损失和价值损失都被归为‘损失’(谁能说它们的走向是否一致?),而且因为演员和评论家的网络没有太大的差异——显然需要大量的数据(迭代、时代、剧集、播放次数)才能实现融合。

最后一个重要因素是鼓励探索而不是开发,也就是说,避免局部最小值。有几种方法可以做到这一点,在我制作的代理中结合了这些方法:

  • Epsilon greedy(选择一个随机行动,有时随着时间的推移,概率会下降epsilon——当概率呈指数下降时,我们说‘退火’而不是下降,以防你想知道)
  • 随机地干扰来自环境的奖励信号
  • 任何神经网络的输出都不太可能达到 1.0 的概率。不要每次只选择与最大输出相对应的动作,而是从它的概率分布中取样。
  • 神经网络中的丢失增加了固有的随机性。

这些方法中的每一种都需要更多的训练周期,但它们确实会产生更聪明的代理。幸运的是,在这种玩游戏的 RL 中不缺少数据;只要我们允许,代理可以玩。

代理及其结果

我制作的代理最终非常简单:两个卷积层,两个具有不同非线性的完全连接层,以及前面提到的由线性层组成的两个头。

It learns to avoid the edges of the canvas and avoid itself by going in a spiral

作为网络的输入,我制作了一个当前帧/画布的堆栈,加上前两个帧。(每一帧只有一个像素和/或海龟的方向不同)。

An unremarkable actor-critic network with epsilon-greedy learning built in.

我做这个学到的东西

如果你以前读过我的文章,你可能知道,我不会说制作这只 RL 海龟很容易。我学到的一些东西:

  • 一如既往,奖励设计(即时和游戏结束时)是困难的,挑剔的,不完全直观的。
  • 更多的噪音和熵源确实有助于探索阶段。不要以为一个就够了。
  • 动作头和值头仅仅包含一个线性层是不够的。每个磁头有两层,中间有非线性,当固定在网络的主要“主体”上时,工作得更好。
  • RL 很容易达到稳定状态。通常五分钟训练和五小时训练后的损失没有太大区别。
  • 将类似“last_action”的信号注入网络的后续层(绕过卷积层,并试图为网络提供一些有用的时间相关上下文)不一定有帮助。
  • 随机选择海龟的起始位置和角度使得问题变得更加复杂。我认为这将有助于代理学习泛化,但至少在我给它的训练时间里,它大大降低了收敛速度。
  • 一个 200x200 的网格,其中大部分是稀疏的(没有太多进展),只有一个单一的像素线厚度,并且在我提供给网络的 3 个时间序列帧之间没有太大的差异,导致学习相当缓慢。

The training loop — where the ‘magic’ happens.

愚蠢的特工问题,未来的工作

随着时间的推移,随着它在边缘附近左转或右转的概率变得更高,我制作的代理在避免它方面变得更好,而不是学习永不超出屏幕边界的硬性规则。它没有常识!很难说代理人学到了什么。

那么,你如何将习得的或部分习得的概率分布具体化为实际的规则呢?这可以给一个更有效的代理,也可以学习得更快。有时可以打破的规则,或者当一些规则不再有用时,彻底忘记它们,又如何呢?

当然,还有一个经典的 RL 问题,代理在这里学到的东西在例如太空入侵者的游戏中是没有用的。代理没有海龟和它的踪迹以及屏幕边缘的概念,只有一串张量,它不知疲倦地一遍又一遍地相乘,并根据一些导数进行调整。奖励信号是手工编码的,当然,尽可能长时间的演奏本身就是一种不错的奖励。为什么还没有人找到内在激励人工智能的方法?

AGI 就要来了,但我们仍然需要解决巨大的工程和哲学挑战。谦逊的 Python 海龟继续为我提供了一个有趣的测试平台。

感谢您的阅读!我喜欢和人们谈论 AGI,特别是我们如何从现在的位置开始建设,所以如果你愿意,请联系我们。接下来还有更多:)

Python 是解决任何问题的完美工具

原文:https://towardsdatascience.com/python-is-the-perfect-tool-for-any-problem-f2ba42889a85?source=collection_archive---------4-----------------------

反思我的第一个 Python 程序

反思总是一种有益的(有时是有趣的)练习。出于怀旧的原因——如果一个人可以怀旧两年前的东西——我想分享我的第一个 Python 程序。当我还是一名航空航天工程专业的学生时,我最初选择 Python 是为了避免使用电子表格,当时我并不知道这将是一个多么好的决定。

我的 Python 教育始于 Al Sweigart 的书 用 Python 自动化枯燥的东西 ,这是一本优秀的基于应用程序的书,用简单的程序完成有用的任务。当我学习一个新的主题时,我会寻找任何使用它的机会,我需要用 Python 解决一个问题。幸运的是,我找到了一个课堂所需的 200 美元的教科书。我个人对教科书的限制是大约 20 美元(自动化枯燥的东西在网上是免费的),我甚至拒绝租借这本书。我急切地想在第一次作业前拿到这本书,于是我看到这本书可以通过亚马逊的新账户免费试用一周。我拿到这本书一个星期,就可以做第一个作业了。虽然我可以一周一次地创建新账户,但我需要一个更好的解决方案。进入 Python 和我的第一个编程应用。

中许多有用的库之一是 pyautogui ,它允许你通过 Python 控制键盘和鼠标。他们说,当你有一把锤子时,每个问题看起来都像钉子,这里的情况就是如此。Python 和 pyautogui 允许我按箭头键并截屏,我将这两者结合起来,提出了一个解决图书问题的方案。我写了我的第一个程序来自动翻阅书中的每一页并截图。结束程序只有 10 行长,但我为它感到自豪,就像我在航空航天工程中做的任何事情一样!以下是整个计划:

import pyautogui
import time# Sleep for 5 seconds to allow me to open book
time.sleep(5)# Range can be changed depending on the number of pages
for i in range(1000): # Turn pagepyautogui.keyDown('right')pyautogui.keyUp('right') # Take and save a screenshotpyautogui.screenshot('images/page_%d.pdf' % i)time.sleep(0.05)

运行这个程序非常简单(我鼓励任何人去尝试)。我将脚本保存为 book_screenshot.py,然后在同一个文件夹中弹出一个命令提示符并键入:

python book_screenshot.py

然后我会有 5 秒钟的时间翻到这本书,并把它全屏显示。该程序将完成剩下的工作,翻阅每一页,并截图保存为 pdf 格式。然后,我可以将所有的 pdf 文件合并成一个文件,并拥有这本书的副本(法律问题)!诚然,这是一个相当可怕的副本,因为它无法被搜索,但我尽可能使用我的“书”的任何借口。

I could watch this for hours

这个例子展示了我在继续接受数据科学教育的过程中一直铭记的两个要点:

  1. 学习新技能的最好方法是找到你需要解决的问题。
  2. 你不需要完全掌握一项技能才有用。

仅用几行代码和一本免费的在线书籍,我就编写了一个实际上已经投入使用的程序。学习基础知识可能很乏味,我第一次学习 Python 的尝试在几个小时内就失败了,因为我陷入了数据结构和循环之类的想法。改变策略,我开始开发解决实际问题的方法,并最终学到了基本原理。编程和数据科学需要掌握的东西太多了,但你不需要一下子学会所有的东西。挑一个你需要解决的问题,开始行动吧!

从那以后,我制作了几个更复杂的节目,但我仍然津津有味地记得这第一个剧本!

分享你的第一个节目!我欢迎讨论、反馈和建设性的批评。可以通过 Twitter @koehrsen_will 联系到我。

用 Python 绘制马科维茨有效边界

原文:https://towardsdatascience.com/python-markowitz-optimization-b5e1623060f5?source=collection_archive---------0-----------------------

这篇文章是关于计算夏普比率的文章的后续。在知道如何获得夏普比率后,我们将模拟几千种可能的投资组合配置,并将结果绘制成图表。有了这个,我们可以很容易地找到我们愿意承担的任何给定风险水平的股票的最佳配置。

与上一篇文章一样,我们需要加载数据。我将使用四个简单的文件,有两列——日期和收盘价。你可以用自己的数据,或者在 Quandl 里找点东西,这个用途很好。我们有 4 家公司——亚马逊、IBM、思科和苹果。每个文件分别加载为 amznibm思科aapl 。下面印的是 aapl 的头像。

我们希望将所有价格合并到一个名为股票的数据框架中,这里有一种方法。

我们需要对这个数据框架做的一件事是标准化数据。我将使用对数回报,因为它更方便,而且它负责项目其余部分的标准化。将一切转换成对数回报很简单。可以把它想象成一个算术日收益率的对数(它是通过把第 n 天的价格除以第 n-1 天的价格得到的)。

围绕这一点,事情开始变得有趣起来!我们需要为循环准备一个,它将模拟四只股票的几种不同组合,并保存它们的夏普比率。我要用 6000 个作品集,但是如果你的电脑太慢的话可以少用一点。代码顶部的随机种子确保我每次都得到相同的随机数,以保证可重复性。

从这里,我们可以获得模拟中出现的最大夏普比率以及它出现的行,因此我们可以获得其中的权重。

所以最佳投资组合在指数 5451 上。让我们检查该指数中的分配权重,并保存回报率和波动性数据,以便稍后在图表中使用。

我们有了绘制图表所需的一切,可以根据波动率(或风险)和回报率来比较所有组合,并用夏普比率来着色。红点是从上面的计算中获得的,它代表具有最大夏普比率的模拟的回报和波动性。

我们已经可以在图表中看到子弹形状,这种形状勾勒出了我们稍后将绘制的有效边界。为此,我们需要定义更多的函数。第一个函数 get_ret_vol_sr 将返回一个数组,其中包含任意给定权重集的 return波动率夏普比率

第二个函数 neg_sharpe 将从一些权重中返回负的 sharpe 比率(稍后我们将使用它来最小化)。

第三个函数 check_sum 将检查权重的总和,其必须为 1。如果总和为 1,它将返回 0(零)。

接下来,我们需要创建一个变量来包含我们的约束,比如 check_sum 。我们还将定义一个初始猜测和具体的界限,以帮助最小化更快更有效。我们最初的猜测将是每只股票 25%(或 0.25),每只股票的界限将是一个元组(0,1),因为权重的范围可以从 0 到 1。

进入最小化功能。我选择了“SLSQP”方法,因为这是大多数一般最小化问题使用的方法。如果你想知道,它代表序列最小二乘规划。确保用上面定义的变量传递初始方法、边界和约束。如果我们打印变量,它看起来会像这样:

我们需要字典中的键 x ,它是一个数组,包含具有最大夏普比率的投资组合的权重。如果我们使用我们的函数 get_ret_vol_sr ,我们得到回报、波动率和夏普比率:

因此,我们获得了比之前模拟更好的夏普比率(1.0307,而不是之前的 1.0287)。

我们现在准备检查所有的最优投资组合,这基本上是我们的有效边界。有效边界是在任何给定的风险水平下,使我们获得最高预期回报的投资组合集合。或者从另一个角度来看,期望回报的最小风险。为了追踪这条线,我们可以定义一个变量 frontier_y 。回到上面的图表,我们可以看到最大回报不会比 0.3 高太多,所以 frontier_y 将被定义为从 0 到 0.3。

为了完成边界的绘制,我们定义了最后一个函数来帮助我们最小化波动性。它将返回给定权重的波动率(指数 1)。

现在,帮助我们得到有效边界的 x 值的最后一点代码。我们使用与上面相同的代码,只是对约束做了一些修改。循环的基本上是遍历我们之前定义的 frontier_y 中的每一个可能值,并获得波动率(图表中我们的 x 轴)的最小结果(这是关键的【乐趣】)。

最后,我们可以通过传递变量 frontier_xfrontier_y 来绘制实际的有效边界。

Markowitz Efficient Frontier mapped in red

这些是使用 Python 进行 Markowitz 投资组合优化的步骤。当你投入更多的股票,对不同的风险策略进行结果测试时,事情就变得更有趣了。当然,这种类型的分析总是基于过去,因此它不能保证未来的结果。尽管如此,它可以给你一个特定策略的预期输出的好主意。

欢迎提问或在下方留言!编码快乐!

如果你对 Python 的金融分析感兴趣,有两本很棒的书,几乎涵盖了你需要的所有内容:

  • 金融 python:https://amzn.to/3SE6Mu0
  • 用 Python 写金融理论:【https://amzn.to/3SC4Vpq

声明:本文中的一些链接是附属链接。这意味着,对你来说零成本,如果你通过链接完成购买,我将赚取代销商佣金!

熊猫 vs. Spark:如何处理数据帧(下)

原文:https://towardsdatascience.com/python-pandas-vs-scala-how-to-handle-dataframes-part-ii-d3e5efe8287d?source=collection_archive---------6-----------------------

“Panda statues on gray concrete stairs during daytime” by chuttersnap on Unsplash. “Scala” means “stairway” in Italian, my native language: hence the choice of the picture. It just seemed appropriate.

前几天我发表了一篇帖子比较 Python 和 Scala 的基本命令:如何处理列表和数组、函数、循环、字典等等。随着我继续练习 Scala,似乎应该继续第二部分,比较如何在两种编程语言中处理数据帧,以便在建模过程之前准备好数据。在 Python 中,我们将通过使用 Pandas 库来完成所有这些,而在 Scala 中,我们将使用 Spark。

在这个练习中,我将使用 Titanic train 数据集,该数据集可以通过链接轻松下载。此外,我在 Databricks 中进行了 Scala 实践:如果你也这样做,记得首先通过点击 Data 导入数据集,然后添加数据。

1.读取数据帧

我将导入并命名我的数据帧 df ,在 Python 中这将只有两行代码。如果您将 train.csv 保存在笔记本所在的同一个文件夹中,这将有效。

import pandas as pd
df = pd.read_csv('train.csv')

Scala 需要更多的输入。

var df = sqlContext.read.format("csv").option("header", "true").option("inferSchema", "true").load("Filestore/tables/train.csv")

让我们看看这里发生了什么。Scala 不假设你的数据集有一个头,所以我们需要指定它。另外,Python 会自动为 dataframe 列分配一个 dtype,而 Scala 不会这样做,除非我们指定.option("inferSchema", "true")。还要注意,我没有导入 Spark Dataframe,因为我在 Databricks 中练习 Scala,它是预加载的。否则我们将需要这样做。

注意:在 Python 中布尔值是大写的,而在 Scala 中是小写的!

2.显示数据帧的前几行

Python 中,df.head()将默认显示前五行:输出如下。

df.head() output in Python.

如果您希望看到的行数不是 5,您可以在括号中传递一个不同的数字。 Scala 及其df.show(),将默认显示前 20 行。

df.show() in Scala.

如果我们想让它更短,并且去掉省略号,以便阅读列的全部内容,我们可以运行df.show(5, false)

3.数据帧列和数据类型

要检索列名,在这两种情况下我们只需键入df.columns : ScalaPandas 将分别返回一个数组和一个字符串索引。

如果我们想要检查 dtypes,那么对于两种语言来说,命令还是一样的:df.dtypes。Pandas 将返回一个 Series 对象,而 Scala 将返回一个元组数组,每个元组分别包含

df.dtypes in Python

列和数据类型。因此,如果我们在 Python 中想要检查年龄列是什么类型,我们运行df.dtypes['Age'],而在 Scala 中我们需要过滤并使用元组索引:df.dtypes.filter(colTup => colTup._1 == "Age")

4.汇总统计数据

这是每个数据科学家在探索他/她的数据时做的另一件事:汇总统计。对于每一个数字列,我们可以看到诸如计数、均值、中值、偏差等信息,以便立即看到是否有什么地方看起来不对劲。在这两种情况下,这将返回一个数据帧,其中列是原始数据帧的数字列,行是统计值。

Python 中,我们键入df.describe(),而在ScalaT4【中。我们必须在后一种情况下添加.show()的原因是因为 Scala 不会自动输出结果数据帧,而 Python 会自动输出(只要我们不把它赋给新变量)。

5.选择列

假设我们希望看到列的子集,例如名称为和的列保留了下来。

Python 中,我们可以不加区分地使用df[['Name','Survived]]df.loc[:,['Name','Survived]。请记住,这里的:表示“所有行”。

Scala 中,我们会键入df.select("Name","Survived").show()。如果你想把子集赋给一个新变量,记得省略.show()

6.过滤

假设我们想看看幸存乘客的姓名和职业。我们需要在幸存列中过滤一个条件,然后选择其他条件。

Python 中,我们将再次使用.loc,通过在行的位置传递过滤器,然后用列表选择列。基本上和上面的例子一样,但是用一个过滤器代替了:,这意味着df.loc[df['Survived'] == 1, ['Name','Pclass']]

Scala 中我们将使用.filter后跟.select,也就是df.filter("Survived = 1").select("Name","Pclass").show()

6.1.过滤空值

如果我们想要检查空值,例如在开始的列中,它将像普通过滤器一样工作,只是条件不同。

Python 中,我们在传递条件时应用.isnull(),在本例中是df[df['Embarked'].isnull()]。由于我们没有指定任何列,这将返回一个 dataframe,它将包含所有原始列,但只有包含值的行是空的。

Scala 中,我们将再次使用.filter:df.filter("Embarked IS NULL").show()。注意,我们在 Scala 中传递的布尔过滤器有点像 SQL 查询。

7.输入空值

在数据集中输入空值之前,我们应该始终进行一些思考,因为它会影响我们的最终模型,我们希望对此保持谨慎。然而,仅仅出于演示的目的,假设我们想将字符串“N/A”归入数据帧中的空值。

我们可以用df = df.fillna('N/A')df.fillna('N/A', inplace = True)Python 中这样做。

Scala 中,非常类似地,这将通过df = df.na.fill("N/A")来实现。记住在这种情况下不要使用.show(),因为我们正在将修改后的数据帧赋给一个变量。

8.重命名列

这是你在 Scala 中需要确定的事情,因为机器学习模型需要两个名为特征标签的列来训练。然而,举例来说,如果您不喜欢某个列的命名方式,您可能也想在 Pandas 中这样做。为此,我们想将幸存的列改为标签

Python 中,我们将传递一个字典,其中的键和值分别是列的旧名称和新名称。这种情况下会是df.rename(columns = {"Survived": "label"}, inplace = True)

Scala 中,这等于df = df.withColumnRenamed("Survived", "label")

9.分组依据和聚合

假设我们想要分别计算男性和女性的最大年龄,在这种情况下.groubpby会派上用场。不仅检索最大值;在.groupby之后,我们可以使用各种聚合函数:均值、计数、中位数等等。对于这个例子,我们坚持使用.max()

Python 中,这将是df.groupby('Sex').mean()['Age']。如果我们不在.mean()后指定['Age'],这将返回一个 dataframe,其中包含所有数字列的最大值,并按性别分组。

Scala 中,我们首先需要导入我们想要使用的聚合函数。

import org.apache.spark.sql.functions.max
df.groupBy("Sex").agg(max("Age")).show()

10.创建新列

这对于特征工程来说非常有用,我们可能想要结合两个变量来看它们的交互是如何与目标相关的。出于纯粹的演示目的,让我们看看如何创建一个包含在年龄费用之间的产品的列。

在 Python 中,这非常简单。

df['Age_times_Fare'] = df['Age'] * df['Fare']

Scala 中,我们需要将$放在我们想要使用的列的名称之前,以便考虑具有相应名称的列对象。

df = df.withColumn("AgeTimesFare", $"Age" * $"Fare")

11.相互关系

探索数字变量和目标之间的相关性总是很方便的,在 Python 中,只需运行df.corr()就可以获得所有数字变量之间的相关系数矩阵。如果您想查看相关性,假设在年龄票价之间,我们只需指定列:df[['Age','Fare']].corr()

在 Scala 中,我们首先需要导入,然后通过指定列来运行命令。

import org.apache.spark.sql.functions.corr
df.select(corr("Age","Fare")).show()

就是这个!我希望你觉得这篇文章很有用,就像我写这篇文章一样有用。我打算发表第三部分,在那里我可以通过机器学习模型的例子来完成这个循环!

请随意查看:

本帖第一部分。

我的其他中帖。

我的 LinkedIn 个人资料。

感谢您的阅读!

Python 绘图 API:通过 flask API 展示您的科学 python 绘图

原文:https://towardsdatascience.com/python-plotting-api-expose-your-scientific-python-plots-through-a-flask-api-31ec7555c4a8?source=collection_archive---------6-----------------------

在我作为数据科学家的日常工作中,我经常需要将相对复杂的情节集成到后台应用程序中。这些图主要用于说明算法决策,并为运营部门提供数据直觉。

一种可能的方法是构建一个返回数据的 API,并让应用程序的前端使用或多或少复杂的 javascript 图表库来呈现数据。现在,每当我想改变一些东西时,我都需要改变前端和后端。

因此,我寻找一种快速、简单和可维护的解决方案,使绘图在任何 web 前端应用程序中都可用。我还寻找一种解决方案,允许我在一个地方改变我的图,而当例如一些新的功能请求进来时,总是需要改变前端。

我想到的只是用 matplotlib 、 seaborn 等在 python 中构建情节,然后通过 flask 将它们暴露在网络上。听起来容易吗?这很容易!我会一步一步地教你。也许对你和我一样有帮助。

我们需要什么组件:

  • 数据集:我们将使用来自 scikit-learn 的乳腺癌数据集
  • :让我们从 seaborn 的简单相关图开始
  • 一个 API :这里我们将使用烧瓶创建一个简单的 API

因此,让我们首先加载数据并绘制图表:

Plotting a plot and return it as BytesIO

A correlation matrix plot

这将导致情节左。如你所见,这里的技巧是将绘图保存到 BytesIO 对象中。我们现在可以通过 flask API 公开这个 BytesIO 对象,这样就完成了!

A simple endpoint to return the plot

在上面的代码片段中,我们创建了一个非常简单的端点,当客户端通过给定的路径请求时,它应该返回一个绘图图像。因此,如果您的服务器运行在 localhost 上,图像将在http://localhost:5000/plots/breast _ cancer _ data/correlation _ matrix下提供。

有了 flask,你可以使用 send_file 函数来帮助你发送一个文件到请求的客户端。在我们的例子中,这个文件是存储在 io 中的生成图。BytesIO 对象。我们只要把它传递给函数,就有了一个工作端点。你现在可以启动 flask 应用程序,你会看到:它的工作!

为了让我们的最终用户访问这个情节,我们现在将在一个 HTML 网站上集成图像。您可以只使用图像标签,它将开箱即用:

现在,您学习了如何通过 API 来展示您的科学计划。这样,您就可以帮助其他人在日常工作中更好地理解数据,而无需启动自己的 jupyter 笔记本服务器。

如果您需要更复杂的需要参数化的图,例如给定的时间范围,您可以使用查询参数,并将它们从 flask 传递到您的绘图函数。

为了说明这一点,我整理了一个更简洁的 gitlab 存储库,为您提供了更多的示例,此外还展示了一种将 dockerized flask 应用程序部署到 Heroku 的方法:

https://gitlab.com/dice89/python-plotting-api

您可以在以下位置找到部署的应用程序:

【https://python-sci-plotting.herokuapp.com/

我希望这篇博客教了你一个很好的小技巧,对你有所帮助!

Python 绘图基础

原文:https://towardsdatascience.com/python-plotting-basics-simple-charts-with-matplotlib-seaborn-and-plotly-e36346952a3a?source=collection_archive---------1-----------------------

使用 Matplotlib、Seaborn 和 Plotly 的简单图表

本教程将介绍如何使用三个 Python 绘图库的基础知识——Matplotlib、Seaborn 和 Plotly。阅读完本教程后,您应该能够使用这三个库来:

  • 绘制基本条形图和饼图
  • 设置和自定义绘图特征,如标题、轴和标签
  • 设置绘图的常规图形样式/特征,如自定义字体和颜色选择
  • 理解静态 Matplotlib 和交互式 Plotly 图形在使用和风格上的区别

我在这些图表中使用的数据是基于少数故事和来自山谷中的大象的调查结果,这是一项对 200 多名科技界女性的调查。

Matplotlib,Seaborn,和 Plotly 的区别

我听说过 Matplotlib 被称为 python 绘图包的“祖父”。它真的拥有绘制数据所需的一切,而且网上有很多关于如何使用它的例子。我发现它的缺点是,它的默认风格并不总是视觉上吸引人,而且学习如何做出你想要的调整可能很复杂。有时看起来应该很简单的事情需要几行代码。

Seaborn 是 Matplotlib 的补充,从下面的例子可以看出,它是建立在 Matplotlib 功能之上的。它有更美观的默认样式选项和特定图表——特别是可视化统计数据,它使创建引人注目的图形变得容易,而使用 Matplotlib 可能会很复杂。

Plotly 是一个集成了 Python API 的在线可视化库。在您设置您的帐户后,当您创建图表时,它们会自动链接到您的文件中(并且根据您的帐户/文件设置是公开的)。它相对容易使用,并提供交互式绘图功能,可以很容易地嵌入到网站中。它还具有良好的默认风格特征。

设置我们的库和数据框架

我使用 Pandas 来组织这些地块的数据,并首先通过以下导入为我的 Jupyter 笔记本设置参数。请注意,%matplotlib inline 只允许您运行笔记本并在输出中自动生成绘图,您只需设置一次 Plotly 默认凭证。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.font_manager
%matplotlib inlineimport plotly.plotly  as py
import plotly.graph_objs as go
plotly.tools.set_credentials_file(username='***', api_key='***')

我用熊猫建立了一个数据框。我们绘制的信息如下所示:

Fig.1 — Sample Responses from www.elephantinthevalley.com

Matplotlib 条形图示例

以下代码使用 Matplotlib 生成如下所示的条形图。您可以看到,我们首先将我们的图形设置为具有指定图形大小的子图。然后,我们使用处理所有默认样式/值的 rcParams 函数,设置我们希望作为 Matplotlib 绘图的默认文本和颜色参数。请注意,当您在下面的示例中使用 rcParams 时,它充当一个全局参数,并且您在每次使用 Matplotlib 时都要更改默认样式。

在这个例子中,我使用了一个自定义调色板,它是一个颜色列表,但是也可以(对于分组条形图来说是必要的)为您想要用于条形图的每组数据使用一个颜色值。还要注意,除了使用十六进制颜色代码,您还可以使用库支持的颜色名称。

我们设置总标题、轴标签、轴限制,甚至使用 rotation 参数旋转 x 轴刻度标签。

fig, ax = plt.subplots(figsize = (12,6))plt.rcParams['font.sans-serif'] = 'Arial'
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['text.color'] = '#909090'
plt.rcParams['axes.labelcolor']= '#909090'
plt.rcParams['xtick.color'] = '#909090'
plt.rcParams['ytick.color'] = '#909090'
plt.rcParams['font.size']=12color_palette_list = ['#009ACD', '#ADD8E6', '#63D1F4', '#0EBFE9',   '#C1F0F6', '#0099CC']ind = np.arange(len(df['Question']))bars1 = ax.bar(ind, df['Percentage of Respondents'], color = color_palette_list, label='Percentage of yes responses to question')ax.set_title("Elephant in the Valley Survey Results")
ax.set_ylabel("Percentage of Yes Responses to Question")
ax.set_ylim((0,100))
ax.set_xticks(range(0,len(ind)))
ax.set_xticklabels(list(df['Q Code']), rotation=70)
ax.set_xlabel("Question Key")

这会产生以下输出:

Fig.3 — Matplotlib Bar Chart Example

Matplotlib 饼图示例

下面的代码生成了下图所示的饼图。与我们的条形图示例一样,我们首先将图形设置为子图,然后通过 rcParams 重置默认的 Matplotlib 样式参数。在这种情况下,我们也在下面的代码中定义我们的数据,而不是从我们的数据框中获取。我们选择分解饼图部分,因此设置了一个名为 explode 的变量,我们将颜色选项设置为前面定义的调色板列表中的前两个条目。将轴设置为“相等”可以确保我们得到一个圆形饼图。Autopct 将我们的值格式化为带有一组小数点的字符串。我们还指定了饼图的起始角度,以获得我们想要的格式,并使用 pctdistance 和 labeldistance 放置我们的文本。

在我们设置标题后,我们还选择为该图表使用图例,并指定图例不应有框架/可见边界框,我们通过使用指定的bbox_to_anchor参数“锚定”图例来专门设置图例位置。有用提示——如果您想让图例位于图形之外,首先将位置参数指定为一个特定的角,如“左上角”,然后使用 bbox_to_anchor 指定您想要将图例的“左上角”固定到的位置。

fig, ax = plt.subplots()plt.rcParams['font.sans-serif'] = 'Arial'
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['text.color'] = '#909090'
plt.rcParams['axes.labelcolor']= '#909090'
plt.rcParams['xtick.color'] = '#909090'
plt.rcParams['ytick.color'] = '#909090'
plt.rcParams['font.size']=12labels = ['Bay Area / Silicon Valley', 'Non Bay Area / Silicon Valley']
percentages = [91, 9]
explode=(0.1,0)ax.pie(percentages, explode=explode, labels=labels,  colors=color_palette_list[0:2], autopct='%1.0f%%', shadow=False, startangle=0,   pctdistance=1.2,labeldistance=1.4)
ax.axis('equal')ax.set_title("Elephant in the Valley Survey Respondent Make-up")
ax.legend(frameon=False, bbox_to_anchor=(1.5,0.8))

这会产生以下输出:

Fig. 4 — Matplotlib Pie Chart Example

Seaborn 条形图示例

从下面的代码可以看出,Seaborn 实际上只是 Matplotlib 的一个包装器。在这个特殊的例子中,我们覆盖了默认的 rcParams 并使用了这样一个简单的图表类型,无论您是使用 Matplotlib 还是 Seaborn 绘图都没有任何区别,但是对于不改变默认样式或更复杂的绘图类型的快速图形,我发现 Seaborn 通常是不错的选择。

fig, ax = plt.subplots(figsize = (12,6))plt.rcParams['font.sans-serif'] = 'Arial'
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['text.color'] = '#909090'
plt.rcParams['axes.labelcolor']= '#909090'
plt.rcParams['xtick.color'] = '#909090'
plt.rcParams['ytick.color'] = '#909090'
plt.rcParams['font.size']=12ind = np.arange(len(df['Question']))color_palette_list = ['#009ACD', '#ADD8E6', '#63D1F4', '#0EBFE9', '#C1F0F6', '#0099CC']sns.barplot(x=df['Q Code'], y = df['Percentage of Respondents'],  data = df, palette=color_palette_list, label="Percentage of yes responses to question", ax=ax, ci=None)ax.set_title("Elephant in the Valley Survey Results")
ax.set_ylabel("Percentage of Yes Responses to Question")
ax.set_ylim(0,100)
ax.set_xlabel("Question Key")
ax.set_xticks(range(0,len(ind)))
ax.set_xticklabels(list(df['Q Code']), rotation=45)

这里唯一的区别是我们使用了sns.barplot,输出可以是相同的:

Fig. 5 — Seaborn Bar Chart Example

Plotly 条形图示例

下面的代码使用 Plotly 设置了我们的条形图。我们正在导入我们的库,并使用相同的调色板。然后我们设置我们的条形图参数,接着是我们的整体布局参数,如我们的标题,然后我们使用字典来设置我们想要的参数,如我们的轴和字体。在这些字典中,我们能够指定子参数,如 x 轴刻度标签旋转和 y 轴范围。然后,我们创建我们的图形,向它提供我们的数据和布局,并将我们的文件输出到我们的 Plotly 帐户,以便我们可以将其作为交互式 web 图形嵌入。

import  plotly.plotly  as py
import plotly.graph_objs as gocolor_palette_list = ['#009ACD', '#ADD8E6', '#63D1F4', '#0EBFE9', '#C1F0F6', '#0099CC']trace = go.Bar(x=df['Q Code'],y=df['Percentage of Respondents'],marker=dict(color=color_palette_list))data = [trace]layout = go.Layout(title='Elephant in the Valley Survey Results',font=dict(color='#909090'),xaxis=dict(title='Question Key',titlefont=dict(family='Arial, sans-serif',size=12,color='#909090'),showticklabels=True,tickangle=-45,tickfont=dict(family='Arial, sans-serif',size=12,color='#909090'),),yaxis=dict(range=[0,100],title="Percentage of Yes Responses to Question",titlefont=dict(family='Arial, sans-serif',size=12,color='#909090'),showticklabels=True,tickangle=0,tickfont=dict(family='Arial, sans-serif',size=12,color='#909090'))
)fig = go.Figure(data=data, layout=layout)
py.iplot(fig, filename='barplot-elephant-in-the-valley')

这会产生以下输出:

Fig. 6 — Plotly Bar Chart Example

Plotly 饼状图示例

到目前为止,您可能已经了解了我们是如何格式化和调用 Matplotlib 和 Plotly 中的参数来构建可视化的。让我们来看最后一个图表——一个如何使用 Plotly 创建类似于上图的饼状图的例子。

下面的代码设置并输出我们的图表。我们通过旋转参数来指定我们的起始角度,并使用 hover over 参数来记录当我们将鼠标悬停在饼图的每个组件上时应该可以获得哪些信息。

labels = ['Bay Area / Silicon Valley', 'Non Bay Area / Silicon Valley']
percentages = [91, 9]trace = go.Pie(labels=labels, hoverinfo='label+percent', values=percentages, textposition='outside',marker=dict(colors=color_palette_list[0:2]),rotation=90)layout = go.Layout(title="Elephant in the Valley Survey Respondent Make-up",font=dict(family='Arial', size=12, color='#909090'),legend=dict(x=0.9, y=0.5))data = [trace]fig = go.Figure(data=data, layout=layout)
py.iplot(fig, filename='basic_pie_chart_elephant_in_the_valley')

这会产生以下输出:

Fig. 7 — Plotly Pie Chart Example

就这样,我们完成了条形图和饼图的创建和定制。希望这有助于您学习如何使用这些库,以便为您的数据创建定制的图形解决方案。

最后,我想提一下,我认为谨慎使用饼图是很重要的。虽然它们被认为是一种“基本”图表类型,但它们通常不会增加对基础数据的理解,所以要谨慎使用它们,并且只在你知道它们对理解有价值的情况下使用。

密谋愉快!

资源:

  • Python 的 Plotly 入门
  • Matplotlib rcParams 文档
  • Seaborn

15 分钟 Python 编程第 1 部分

原文:https://towardsdatascience.com/python-programming-in-15-min-part-1-3ad2d773834c?source=collection_archive---------2-----------------------

关于 Python

Python 3.0 也称为 Python 3000,是一种简单易学、功能强大的编程语言。它具有高效的高级数据结构和简单而有效的面向对象编程方法。Python 优雅的语法和动态类型,加上它的解释性质,使它成为大多数平台上许多领域中脚本和快速应用程序开发的理想语言。

安装 Python 3

[## 下载 Python

Python 编程语言的官方主页

www.python.org](https://www.python.org/downloads/)

第一个程序

让我们编写第一个程序,打印“Hello World!”

在 Python 中,我们使用 print(" ")函数在屏幕上显示文本。我们用引号来标记字符串的开始和结束;它们不会出现在结果中。
我们可以用两种方式运行 python 程序:

  1. Python Shell
  2. Python 脚本

使用 Python Shell

在机器上安装 Python 之后,要在命令提示符或终端中打开 Python shell 类型“python3 ”,这将开始一个交互式 Python 会话。此交互式会话不会将您的任何代码保存在文件中;一旦您退出 shell,它就会过期。

在您的 Python shell 中,您将找到当前运行的 Python 版本、一些信息和三个等待您命令的箭头。现在让我们编写代码,在 Python shell 中打印 Hello World。

>>> print(“Hello, World!”)
Hello, World!
>>>

你一按 enter 键,Python 解释器就运行代码并给出输出。

通用 python shell 用于随时测试程序。使用帮助(任何东西)获取文档。它比任何网络界面都要快。

执行 Python 脚本

要运行 Python 脚本,请将 Python 代码保存在. py 文件中,并在命令提示符或终端中使用 python3 file_name.py 运行程序。

例如:
hello_world.py

print("Hello, World!")

$python3 hello_world.py
你好,世界!

在执行此操作之前,请确保更改了保存文件的目录。

当你编写大块的 Python 代码时,我们需要使用脚本模式。

您可以使用不同的文本编辑器来编写 Python 脚本,如 Sublime Text、Atom Editor。

数字和变量

我们知道数字无处不在,所以让我们看看 Python 是如何处理数字的。Python shell 可以当计算器用;您可以在 python shell 中执行基本的数学运算,如加法、除法等。

示例:

>>>3 + 3
6
>>>(84949*292)/322
77034
>>>

在 Python 中,我们有三种不同的数字类型,它们是整数、浮点数和复数。整数是没有小数部分的数字,可以是正数、负数或无符号数(零)。浮点值是带有小数部分的数字。

在编程中,变量只不过是某种东西的名称。变量名区分大小写。

要在 Python 中声明一个变量,你必须给出它的名字,后跟一个等号和初始化值。

当您一直将值赋给同一个变量名时,Python 会用新值替换旧值。

Python3 支持以下数据类型:

1.布尔
2。整数
3。浮子
4。复合体
5。线

数据类型. py

python3 数据类型. py

True <class 'bool'>167 <class 'int'>153.5 <class 'float'>(16.789+12323.45j) <class 'complex'>Mustang <class 'str'>

注意:不要以数字开始变量名。

用线串

在 python 中,字符串是用单引号或双引号括起来的字符序列。字符串是不可变的 Unicode 点序列。

示例:

字符串. py

python3 strings.py

<class ‘str’>
<class ‘str’>
Stark , CEO at Queen’s Consolidate

Python 格式化

使用。格式()

有时我们可能想用变量值构造字符串,这种字符串的概念性构造称为字符串插值。

示例:

插值. py

python3 插值. py

Hey Agent 47, your code number is 1011010.

数据结构

为了有效地组织和处理内存中的数据,我们使用数据结构,在 Python 中,我们有不同类型的数据结构和对它们执行的几种操作。

现在我们将讨论 Python 中的三种主要数据结构(列表、元组、字典)

列表

列表是有序的、可变的值序列,类似于 C 和 C++中的数组。

为了在 Python 中声明一个列表,我们给出了用逗号分隔的列表名称。

my_list = [item_1, item_2, item_3, item_4]

类似于字符串索引,列表索引从 0 开始,列表可以被切片、连接等等。

示例:

lists.py

python3 列表. py

<class 'list'>
['Paris', 'New York', 'Melbourne', 'Swiss']
Paris
New York
Swiss

注意:负索引从列表末尾开始,索引值为-1。

我们在列表上有几个方法,这里有几个例子。

列表 _ 方法. py

python3 list_methods.py

['Pen', 'Pencil', 'Notepad', 'Eraser']
['Pen', 'Pencil', 'Files', 'Notepad', 'Eraser']

index 方法在列表中查找给定值,并返回索引值。索引方法用于搜索值发生的位置。

这是列表方法的几个例子,要了解更多我们可以使用 help(list)获得所有的列表方法。

元组

元组是有序的、不可变的值序列。声明元组类似于列表,我们只是将值放在一对括号中。

my_tuple = (item_1, item_2, item_3)

元组是不可变的,这意味着我们不能在元组中添加或删除项,而且元组没有索引方法。

为什么要用元组?

元组比列表更快,也更安全。它们是写保护的,一旦声明,我们就不能添加新的项目。

元组. py

python3 tuple.py

<class 'tuple'>
('Oxygen', 'Hydrogen', 'Nitrogen')

词典

字典是无序的键值对集合。键和值可以是不同的数据类型。每个值都有一个惟一的键,作为字典中该值的标识符。

定义字典

my_dictionary = {key_1 : value1, key_2 : value2 , key_3 : value3}

示例:

my_dict.py

python3 my_dict.py

<class 'dict'>
{'jack': 4098, 'sape': 4139, 'robb': 2323}
{'jack': 4098, 'robb': 2323}

条件句(if,elif,else)

我们总是需要检查条件并相应地改变程序行为的能力。条件语句给了我们能力。最简单的形式是“if”语句。

条件语句测试一个表达式,看它是真还是假,并根据结果进行运算。

if expression:statement(s)

注意:Python 必须知道当条件为真时必须执行的语句数量。为了实现这一点,出现了缩进的概念。标题下的所有语句(如果在这种情况下)必须保持相同的缩进级别(4 个空格)。

缩进的概念适用于整个 Python 程序。

例如:
临时温度

python3 临时版本

Let’s go to the party!

如果有两种可能的条件,那么我们用 if,else 语句。

例子:
movie_plan.py

python3 电影 _ 计划. py

Tickets are available, Let’s go to the movie.

多重条件

如果我们有两个以上的可能性,我们需要两个以上的分支。所以我们使用链式条件语句。elif 这个词是 else if 的缩写。elif 语句没有限制,但是最后一个分支必须是 else 语句。

示例:

calc_bmi.py

python3 clac_bmi.py

Computing…
Your bmi is 23.765432098765434
Perfect ! Normal weight

感谢阅读!

第 2 部分和第 3 部分使用以下链接

[## 15 分钟 Python 编程第 2 部分

控制流程、功能、面向对象。

medium.com](https://medium.com/towards-data-science/python-programming-in-15-min-part-2-480f78713544) [## 15 分钟 Python 编程第 3 部分

异常、模块、包

medium.com](https://medium.com/towards-data-science/python-programming-in-15-min-part-3-ce882f9ab9b2)

参考:Python 编程的现代方法——瓦姆西·鞍马,皮尔森印度公司。

https://github.com/vamsi/python-programming-modern-approach

感谢 Richa Kulkarni 对故事的贡献。

已编辑:已添加字符串。

15 分钟 Python 编程第 2 部分

原文:https://towardsdatascience.com/python-programming-in-15-min-part-2-480f78713544?source=collection_archive---------3-----------------------

控制流程、功能、面向对象。

控制流程

for 循环

Python 中的 for 循环能够遍历任何序列的项,比如 list 或 string。

它以任何有序的顺序遍历项目,即字符串、列表、元组、字典的键和其他可迭代的术语。python for 循环以关键字 for 开始,后面是一个变量属性,它将保存后面的序列对象的值。

for 循环的语法

for variable in sequence:statement(s)

示例:

colors.py

python3 colors.py

Red
Black
Blue
White
Pink

数学 _ 表格. py

在这种情况下,我们只打印语句块中的值。

python3 数学 _ 表格. py

1 times 5 is 5
2 times 5 is 10
3 times 5 is 15
4 times 5 is 20
5 times 5 is 25

While 循环

只要给定的条件为真,Python 编程语言中的 while 循环语句就会重复执行目标语句。与 for 循环不同,while 循环不会运行 n 次,而是直到满足定义的条件。

While 循环的语法

while condition:statement(s)

示例:

倒计时 _ 定时器. py

范围功能

Python 中的 range 函数生成一个数字列表,可用于循环迭代和其他少数情况。

现在让我们看看范围函数是如何工作的

range(n)
range(begin, end)

range(n)生成从 1 开始到(n-1)结束的整数。

range(begin,end)生成从 begin 开始到 end-1 结束的整数。

$python3

范围(8)

范围(0,8)

示例:

打印值域函数迭代的数字的平方。

方形. py

python3 广场. py

1
4
9
16
25
36

功能

函数是执行特定任务的可重用代码块。它是一个小的计算单元,可以接受参数,也可以返回值。

注意:函数体必须像“if”语句一样缩进。

声明函数

关键字def引入了一个函数定义,后跟函数名和带括号的形参列表。构成函数体的语句从下一行开始,必须缩进。

句法上,

*def function_name(formal parameters):statement(s)*

注意:声明一个函数并不运行这个函数。为了运行,您必须使用函数名调用函数。

例子

greet.py

python3 greet.py

*Hello ! Welcome to the party.*

在这个程序中,我们创建了一个名为 greet 的函数,没有空括号之类的参数。该函数被定义为打印一个名为“Hello!欢迎参加聚会。”

所以调用函数只是打印给定的字符串。

带参数的函数。

函数可以接受参数,这些参数是你提供给函数的值,这样函数就可以利用这些参数做一些事情。参数在函数定义中的一对括号内指定,用逗号分隔。

示例:

greet_names.py

python3 greet_names.py

*Hello Flash
Hello Arrow
Hello Bat*

factorial.py

python3 factorial.py

*The factorial of number is 120*

参见递归,变量范围。

面向对象 Python 简介

在我们迄今为止编写的所有程序中,我们都是围绕函数来设计程序的,即操作数据的语句块。这被称为面向过程的编程方式。还有另一种组织你的程序的方法,就是把数据和功能结合起来,把它包装在一个叫做类的东西里面。这被称为面向对象编程范例。

快速浏览一下面向对象术语的基础知识。

:类是创建单个对象的蓝图。

对象:一个真实世界的实体,有状态和行为。

让我们用类中的类方法创建一个类 Person。

*class Person():def say(self):print("Hello")*

现在让我们为这个类创建一个对象实例。

*class Person():def say(self):print("Hello") jackman = Person()
jackman.say()*

进一步扩展这个情节让我们创建两个带参数的方法,hello 和 bye。

methods_examples.py

python3 method_examples.py

*Hello Lee How are you ?
Nice Meeting You Edison*

注意: Self 是所有实例方法的默认参数

这需要我们为每个类方法重复实例变量,而不是用实例变量创建一个对象。现在是时候使用构造函数了。

构造函数

Python 中的构造函数是在一个特殊的方法 init 下编写的。

现在让我们为一个对象写一个构造函数。在这个例子中,让我们用实例变量 name 和 year_of_birth 创建一个对象。在类中编写构造函数的过程消除了每个实例方法中实例变量的重复。

constructors.py

python3 构造函数. py

*Name of the person is Vihar
Your are 19 Years Old*

类和对象示例:

银行 _ 账户. py

python3 银行账户. py

*100
50
40
90*

使用第 3 部分的以下链接

* [## 15 分钟 Python 编程第 3 部分

异常、模块、包

medium.com](https://medium.com/towards-data-science/python-programming-in-15-min-part-3-ce882f9ab9b2)

如果您错过了《15 分钟》第 1 部分中的 Python 编程,请浏览链接。

[## 15 分钟 Python 编程第 1 部分

关于 Python

medium.com](https://medium.com/towards-data-science/python-programming-in-15-min-part-1-3ad2d773834c)

参考:Python 编程的现代方法——瓦姆西·鞍马,皮尔森印度公司。

https://github.com/vamsi/python-programming-modern-approach

感谢 Sai Tejaswie 对故事的少许贡献。

请继续关注第三部分。*

15 分钟 Python 编程第 3 部分

原文:https://towardsdatascience.com/python-programming-in-15-min-part-3-ce882f9ab9b2?source=collection_archive---------5-----------------------

异常、模块、包

错误和异常

Python 中最常见的观点是,它处理所有异常错误。一个异常是一个错误或其他异常情况发生的信号。有几个内置的异常,它指示某些条件,如 IndentationError:意外缩进,ZeroDivisionError:被零除。您还可以定义例外情况。

程序是易受影响的。如果代码总是返回有效的结果就好了,但有时无法计算出正确的结果。

例如,不能将一个数除以零,也不能访问负项列表中的第三个元素。

到目前为止,错误消息还没有被提及,但是如果您尝试过这些例子,您可能已经看到了一些。(至少)有两种不同的错误:

1.语法错误
2。异常

语法错误

语法错误,也称为解析错误,可能是您在学习 Python 时最常见的抱怨。语法错误几乎总是致命的,也就是说,几乎没有办法成功执行一段包含语法错误的代码。

示例:

>>> print("Hello
File "<stdin>", line 1
print("Hello^
SyntaxError: EOL while scanning string literal

该错误是由箭头前面的标记引起的。在本例中,在 print()函数中检测到错误,因为括号没有闭合。

>>> while True print("Hello World !")
File "<stdin>", line 1
while True print("Hello World !")^
SyntaxError: invalid syntax

由于 while 循环的条件后缺少冒号“:”,因此遇到了语法错误。

异常情况

当程序中发生异常情况时,就会发生异常。例如,如果您要读取一个不存在的文件,或者在程序运行时不小心删除了该文件,该怎么办?这种情况使用异常来处理。

类似地,如果你的程序有一些错误的语句呢?
这是由 Python 处理的,它告诉你有一个错误。

示例:

考虑一个简单的打印函数调用。如果我们把 print 这个词拼错成了 Print 呢?注意这里的大写。在这种情况下,Python 会引发语法错误。

>>> Print("Hello there !")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'Print' is not defined

观察器:引发了一个 NameError,并且还打印出了检测到错误的位置。

现在让我们看看 Python 中几种错误

当一个数被零除时。

>>> 2/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

IndexError:当索引超出范围时。

>>> list = [1,2,3]
>>> list[4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range

TypeError:当操作或函数应用于不适当类型的对象时引发

>>> '2' + 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: must be str, not int

KeyError:当字典使用不当时会发生。

>>> dict = {'a' : 'Stark', 'b': 'Steve'}
>>> dict['c']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'c'

异常处理

像许多其他编程语言一样,Python 也有异常处理。我们可以使用 try except for 语句处理异常。我们基本上将常规语句放在 try 块中,并将所有错误处理程序放在 except 块中。

示例:

handling_exception.py

python3 handling_exception.py

You can't divide by zero.

捕捉 Python 中的特定异常

try 子句可以有任意数量的 except 子句来以不同的方式处理它们,但是在出现异常的情况下,只会执行一个子句。

我们可以使用一组值在 except 子句中指定多个异常。下面是一个伪代码示例。

try:
# do somethingpassexcept ValueError:
# handle ValueError exceptionpassexcept (TypeError, ZeroDivisionError):
# handle multiple exceptions
# TypeError and ZeroDivisionErrorpassexcept:
# handle all other exceptionspass

引发异常

在 Python 编程中,当运行时出现相应的错误时,会引发异常,但是我们可以使用关键字 raise 强制引发异常。

示例:引发键盘中断

>>> raise KeyboardInterrupt
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyboardInterrupt
>>>

提高内存错误

>>> raise MemoryError(“Argument”)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
MemoryError: Argument

让我们提出一个值错误并排除这个错误。

提升 _ 错误. py

python3 提升 _error.py

Enter a negative integer: 5
That is not a negative number!

试试……终于

Python 中的 try 语句可以有一个可选的 finally 子句。这个子句无论如何都要执行,一般用来释放外部资源。

文件处理. py

在这里,它尝试打开当前目录中的 text.txt 文件,否则将引发一个 FileNotFoundError 错误。

模块

Python 附带了数百个模块,可以做各种各样事情。也可以从互联网上下载第三方模块。

Python 包括一组称为标准库的模块,例如,math,cmath,它包含实数和复数的数学函数,但还有更多。

使用 import 语句导入模块。

import module_name

现在让我们导入几个模块并在其中运行函数。

>>> import math
>>> math.pi
3.141592653589793
>>> math.sin(0)
0.0
>>> math.cos(45)
0.5253219888177297

这里,我们导入了数学模块,并使用 sin 和 cos 函数来返回值。

>>> import time
>>> print(time.asctime())
Thu Jul 27 01:47:01 2017

在本例中,我们导入了时间模块,并从该模块调用了 asctime 函数,该函数以字符串形式返回当前时间。

还有一种导入方式是使用 import 语句。

>>> from time import asctime
>>> asctime()
'Thu Jul 27 01:49:10 2017'

这里,我们只从时间模块中导入了 asctime 函数。

套餐

考虑一个声音包,组织你的 Python 代码的方式创造了令人敬畏的包。

sound/                        **Top-level package**__init__.py               Initialise the sound packageformats/                      **Sub-package** for file format__init__.pywavread.pywavwrite.pyaiffread.py...effects/                      **Sub-package** for sound effects__init__.pyecho.pysurround.pyreverse.py...filters/                      **Sub-package** for filters__init__.pyequalizer.pyvocoder.pykaraoke.py...

第三方包

Python 拥有最大的创建 Python 包的社区。在https://pypi.python.org/pypi有超过 100,000 种包装可供选择。

Python 包是所有模块的集合,这些模块恰当地连接成一个形式,并且是分布式的 PyPi,Python 包索引维护可用 Python 包的列表。现在,当您完成 pip 设置后,进入命令提示符或终端,并说

pip install <package-name>

运行此命令后,包将被安装到您的 python 库中。您可以将包导入到您的程序中。

恭喜您已经完成了基本的 Python 编程!

向所有阅读并支持这篇报道的人致敬。

第 1 部分和第 2 部分使用以下链接。

[## 15 分钟 Python 编程第 1 部分

关于 Python

medium.com](https://medium.com/towards-data-science/python-programming-in-15-min-part-1-3ad2d773834c) [## 15 分钟 Python 编程第 2 部分

控制流程、功能、面向对象。

medium.com](https://medium.com/towards-data-science/python-programming-in-15-min-part-2-480f78713544)

写作方式和例子的灵感来自《Python 编程的现代方法》一书。

启动 GitHub 回购,传播爱。

[## vamsi/python-编程-现代方法

python 编程-现代方法-Python 编程工具包:现代方法书。参考书中的步骤…

github.com](https://github.com/vamsi/python-programming-modern-approach)

感谢 Richa Kulkarni 对故事的少许贡献。

感谢阅读。如果你觉得这个故事有帮助,请点击下面的💚去传播爱。

BigQuery 中的 Python PyPI stats:重新集群

原文:https://towardsdatascience.com/python-pypi-stats-in-bigquery-reclustered-d80e583e1bfe?source=collection_archive---------25-----------------------

Top growing 2018 Python packages (arbitrary selection and highlights)

让我们深入研究 Python 安装活动的原始日志。在这篇文章中,我们将看到如何测量一个包的流行度,哪个 Python 版本使用它,以及如何充分利用我们的查询。

Python 软件基金会为 Python 包索引中的每次下载提供原始元数据,包括从pip install开始的活动。现在,任何人都可以使用他们的免费的每月万亿字节的 BigQuery 分析来把握 Python 社区的脉搏,或者只是跟随他们喜欢的项目的趋势。这也是库作者决定他们应该支持什么平台的一个很好的工具。

你可以直接从来源阅读更多关于它的信息:

[## 分析 PyPI 包下载——Python 打包用户指南

本节将介绍如何使用 PyPI 包数据集来了解关于托管的一个(或多个)包的下载的更多信息…

packaging.python.org](https://packaging.python.org/guides/analyzing-pypi-package-downloads/)

例如,如果我们想检查 PySpark 自从holden karau推出以来的受欢迎程度,我们可以这样做:

SELECT TIMESTAMP_TRUNC(timestamp, WEEK) week, REGEXP_EXTRACT(details.python, r'^\d*\.\d*') python, COUNT(*) downloads
FROM `the-psf.pypi.downloads2017*`
WHERE file.project='pyspark'
GROUP BY week, python
ORDER BY week8.4 sec elapsed, 200.88 GB processed # find improvements below

PySpark downloads during 2017. Something seems weird.

在 10 月至 11 月期间,您可以看到一些奇怪的事情发生:Python 3.6 的下载量激增。谁干的?我们不知道——但是使用 BigQuery,我们可以自由地过滤掉这种可疑的活动,以便更好地了解情况:

SELECT TIMESTAMP_TRUNC(timestamp, WEEK) week, REGEXP_EXTRACT(details.python, r'^\d*\.\d*') python, COUNT(*) downloads
FROM `the-psf.pypi.downloads2017*`
WHERE file.project='pyspark'
GROUP BY week, python
HAVING python != '3.6' AND week<'2017-12-30'
ORDER BY week9.0 sec elapsed, 200.88 GB processed # find improvements below

PySpark downloads during 2017, excluding Python 3.6.

现在这看起来更好了:一旦我们排除 Python 3.6,我们会看到 PySpark 的健康采用曲线——由 Python 2.7 安装所主导。

这表明,获得原始数据比仅仅预先汇总数据更能让我们的数据更有洞察力。您可能已经注意到,我们每次都必须查询 200GB 的数据——很快就耗尽了我们每月的 1tb 免费查询量。

让我们利用集群表的能力来改进这一点。

聚集表上的相同查询

让我们重写一个聚集表上的最后一个查询:

SELECT TIMESTAMP_TRUNC(timestamp, WEEK) week, REGEXP_EXTRACT(details.python, r'^\d*\.\d*') python, COUNT(*) downloads
FROM `fh-bigquery.pypi.pypi_2017`
WHERE project='pyspark'
AND timestamp>'2000-01-01' # nag
GROUP BY week, python
HAVING python != '3.6' AND week<'2017-12-30'
ORDER BY week5.4 sec elapsed, 9.65 GB processed # winning

这很酷:如果您使用我的集群表而不是现有的官方表,同样的查询将只扫描大约 5%的数据。

注意事项:

  • FROM fh-bigquery.pypi.pypi_2017``是您可以找到我的集群表的地方。我每年创造一个。
  • FROM fh-bigquery.pypi.pypi_20*``让你年年匹配。
  • WHERE project=’pyspark'允许您从集群中受益,集群可以在这些表格中根据项目名称进行修剪。
  • 原始表上的file.project必须由project替换,因为集群不能在嵌套列上工作(还不能)。
  • timestamp>'2000-01-01'这是我强有力地提醒您这些是时间分区表的方式。如果您将查询限制在一年中的一段时间内,那么您查询的数据会相应减少——或者您可以从一个非常早的日期开始明确地询问所有数据。
  • REGEXP_EXTRACT(details.python, r’^\d*\.\d*’)将 Python 版本保留到最高有效位。
  • 这些查询将只与#standardSQL一起运行,因为#legacySQL不支持集群表。

我说“我的集群表”是因为我提供它们作为一个非官方的地方来获取这些日志,同时我们改进这个过程。根据您的反馈和意见,我们将努力将这些改进整合到官方资料库中。

工作日志

重新聚类

为了对每年的现有数据进行重新聚类,我做了如下工作:

CREATE TABLE `fh-bigquery.pypi.pypi_2017`
PARTITION BY DATE(timestamp)
CLUSTER BY project, country_code
OPTIONS(description="repartitioned and clustered from [https://bigquery.cloud.google.com/table/the-psf:pypi.downloads20180906](https://bigquery.cloud.google.com/table/the-psf:pypi.downloads20180906)", require_partition_filter=true
)
AS
SELECT file.project project, STRUCT(file.filename, file.type, file.version) file, * EXCEPT(file)
FROM `the-psf.pypi.downloads2017*`34 min elapsed, 2.44 TB processed

每日更新

每天凌晨 3 点,我将运行一个计划查询,添加前一天的数据:

INSERT INTO `fh-bigquery.pypi.pypi_2018` (project, file, timestamp, country_code, url, details, tls_protocol, tls_cipher)SELECT file.project project, STRUCT(file.filename, file.type, file.version) file, * EXCEPT(file)
FROM `the-psf.pypi.downloads2018*`
WHERE _TABLE_SUFFIX = FORMAT_TIMESTAMP('%m%d', TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR))
AND timestamp > ( # for idempotencySELECT MAX(timestamp) FROM `fh-bigquery.pypi.pypi_2018` WHERE timestamp>TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24*2 HOUR)
)48.9 sec elapsed, 24.83 GB processed

Configuring a scheduled query

常见问题解答

BigQuery 说它将处理大量的千兆字节,而我预期的要少一些

使用聚簇表,BigQuery 在运行查询之前给出了最大可计费字节的估计值——但是如果可能的话,查询可能会比这个值小。

一些例子:

SELECT *
FROM `fh-bigquery.pypi.pypi_2017`
WHERE timestamp>='2017-12-01'
LIMIT 1# 1.6s elapsed, 28.6 MB processed
# Stops scanning when it finds the first rowSELECT *
FROM `fh-bigquery.pypi.pypi_2017`
WHERE timestamp>='2017-12-01'
AND project='rpy2'
LIMIT 12.0s elapsed, 386 MB processed
# Finds the cluster that contains 'rpy2' and scans thatSELECT *
FROM `fh-bigquery.pypi.pypi_2017`
WHERE timestamp>='2017-12-01'
AND project='88888'
LIMIT 12.4s elapsed, 4.58 GB processed
# Finds the clusters which could contain '88888', but it's not thereSELECT *
FROM `fh-bigquery.pypi.pypi_2017`
WHERE timestamp>='2017-12-01'
AND project LIKE '%random%'
LIMIT 11.8s elapsed, 171 MB processed
# Opens all the clusters, until one contains a *random* projectSELECT *
FROM `fh-bigquery.pypi.pypi_2017`
WHERE timestamp>='2017-12-01'
AND project LIKE '%DOESNT-EXIST%'
LIMIT 12.7s elapsed, 221 GB processed
# Opens all the clusters, and keeps searching for an un-existing pattern

承认

  • 感谢 Donald Stufft ,让这一切成为可能。
  • 欢迎 di_codes 加入 GCP 团队。

后续步骤

我们应该将这些聚集的表移动到官方回购中,但让我们先讨论它们:

  • Python distutils-sig@讨论主题。

想要更多的故事?查看我的媒体,关注我的推特,订阅 reddit.com/r/bigquery。并且尝试 big query——每个月你都可以从免费获得一个完整的万亿字节的分析。

[## 这些是真正的堆栈溢出趋势:使用页面视图

直到今天,获得 Stack Overflow 的季度浏览量并不容易。了解如何获得这些…

towardsdatascience.com](/these-are-the-real-stack-overflow-trends-use-the-pageviews-c439903cd1a)

Python Seaborn 统计数据可视化备忘单

原文:https://towardsdatascience.com/python-seaborn-cheat-sheet-for-statistical-data-visualization-5428d07d2c9b?source=collection_archive---------7-----------------------

您现在很可能已经知道,通过数据可视化完成的数据故事讲述是每个数据科学家的一项基本技能:在您将原始数据转化为理解、见解和知识之后,您还需要将这些发现有效地传达给您的受众。

对于大多数初学者来说,他们使用的第一个 Python 数据可视化库自然是 Matplotlib。这是一个 Python 2D 绘图库,使用户能够制作出版物质量的图形。这是一个相当大的库,当你学习时,一个备忘单肯定会派上用场,但是当你设法有效地使用这个库时,你也将能够获得洞察力并更好地与其他包一起工作,例如 Pandas,它们打算随着时间的推移与 Matplotlib 建立更多的绘图集成。

您将能够处理的另一个包是 Seaborn,它是 Python 的统计数据可视化库。

DataCamp 为那些准备好开始使用这个数据可视化库的人创建了一个 Seaborn cheat sheet,并提供了一个方便的单页参考。

您将看到这个备忘单向您展示了用 Python 制作漂亮的统计图的五个基本步骤。

查看信息图 此处

本备忘单将带您完成绘制这些图所需的五个步骤:您将看到如何加载数据、设置图形美学、绘制、定制,以及最终使用 Seaborn 显示或保存您的图。

一旦你开始使用这个备忘单,以前看起来很难的事情肯定会变得更加清晰!结合 Seaborn Gallery 、文档和我们的教程使用。

此外,不要错过我们的其他数据科学备忘单,包括SciPyNumpyScikit-Learn

原载于www.datacamp.com

Python 集和集合论

原文:https://towardsdatascience.com/python-sets-and-set-theory-2ace093d1607?source=collection_archive---------5-----------------------

了解 Python 集合:它们是什么,如何创建它们,何时使用它们,内置函数,以及它们与集合论运算的关系。

集合与列表和元组

列表和元组是在序列中存储值的标准 Python 数据类型。集合是另一种也存储值的标准 Python 数据类型。主要区别在于,与列表或元组不同,集合不能多次出现相同的元素,也不能存储无序值。

Python 集合的优势

因为集合不能多次出现相同的元素,所以集合对于有效地从列表或元组中删除重复值以及执行像联合和交集这样的常见数学运算非常有用。

本教程将向您介绍几个关于 Python 集合和集合论的主题:

  • 如何初始化空集和有值集?
  • 如何在集合中添加和删除值
  • 如何有效地将集合用于成员资格测试和从列表中删除重复值等任务。
  • 如何执行常见的集合运算,如并集、交集、差集和对称差集。
  • 集合和冷冻集合的区别

就这样,让我们开始吧。

初始化集合

集合是不同的(唯一的)不可变值的可变集合,这些值是无序的。

您可以使用set()初始化空集。

emptySet = set()

要用值初始化一个集合,您可以向set()传递一个列表。

dataScientist = set(['Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS']) dataEngineer = set(['Python', 'Java', 'Scala', 'Git', 'SQL', 'Hadoop'])

如果您查看上面的 dataScientist 和 dataEngineer 变量的输出,请注意集合中的值没有按照中添加的顺序排列。这是因为集合是无序的。

包含值的集合也可以用花括号初始化。

dataScientist = {'Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS'} dataEngineer = {'Python', 'Java', 'Scala', 'Git', 'SQL', 'Hadoop'}

请记住,花括号只能用于初始化包含值的集合。下图显示了使用不带值的花括号是初始化字典而不是集合的方法之一。

添加和删除集合中的值

要在集合中添加或删除值,首先必须初始化集合。

# Initialize set with values 
graphicDesigner = {'InDesign', 'Photoshop', 'Acrobat', 'Premiere', 'Bridge'}

向集合中添加值

您可以使用add方法向集合中添加一个值。

graphicDesigner.add('Illustrator')

需要注意的是,您只能向集合中添加不可变的值(如字符串或元组)。例如,如果您试图向集合中添加列表,将会得到一个 TypeError。

graphicDesigner.add(['Powerpoint', 'Blender'])

有几种方法可以从集合中删除一个值。

选项 1: 您可以使用remove方法从集合中删除一个值。

graphicDesigner.remove('Illustrator')

这种方法的缺点是,如果您试图删除一个不在您的集合中的值,您将得到一个 KeyError。

选项 2: 您可以使用discard方法从集合中移除一个值。

graphicDesigner.discard('Premiere')

这种方法相对于remove方法的好处是,如果您试图删除一个不属于集合的值,您将不会得到一个 KeyError。如果您熟悉字典,您可能会发现这与字典方法 get 的工作方式类似。

选项 3: 您还可以使用pop方法来移除和返回集合中的任意值。

graphicDesigner.pop()

需要注意的是,如果集合为空,该方法会引发一个 KeyError。

从集合中删除所有值

您可以使用clear方法从集合中移除所有值。

graphicDesigner.clear()

遍历一个集合

像许多标准 python 数据类型一样,可以遍历一个集合。

# Initialize a set 
dataScientist = {'Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS'} for skill in dataScientist: print(skill)

如果您查看在 dataScientist 中打印每个值的输出,请注意,在集合中打印的值没有按照它们被添加的顺序。这是因为集合是无序的。

将集合转换为有序值

本教程强调了集合是无序的。如果您发现您需要以有序的形式从集合中获取值,那么您可以使用sorted函数,它输出一个有序的列表。

type(sorted(dataScientist))

下面的代码按字母降序输出数据集 dataScientist 中的值(本例中为 Z-A)。

sorted(dataScientist, reverse = True)

从列表中删除重复项

本节的部分内容之前已经在教程 18 个最常见的 Python 列表问题中探讨过,但是需要强调的是,集合是从列表中删除重复项的最快方式。为了说明这一点,让我们研究两种方法之间的性能差异。

方法 1: 使用集合从列表中删除重复项。

print(list(set([1, 2, 3, 1, 7])))

方法 2: 使用列表理解来删除列表中的重复项(如果你想复习列表理解,请参见本教程)。

def remove_duplicates(original):unique = [][unique.append(n) for n in original if n not in unique]return(unique)print(remove_duplicates([1, 2, 3, 1, 7]))

可以使用timeit库来测量性能差异,该库允许您对 Python 代码计时。下面的代码为每种方法运行代码 10000 次,并以秒为单位输出总时间。

import timeit# Approach 1: Execution time 
print(timeit.timeit('list(set([1, 2, 3, 1, 7]))', number=10000))# Approach 2: Execution time
print(timeit.timeit('remove_duplicates([1, 2, 3, 1, 7])', globals=globals(), number=10000))

比较这两种方法表明,使用集合来删除重复项更有效。虽然这看起来像是时间上的一个小差异,但是如果你有非常大的列表,它可以节省你很多时间。

设置操作方法

Python 中集合的一个常见用途是计算标准数学运算,如并、交、差和对称差。下图显示了两个集合 A 和 b 上的几个标准数学运算。每个维恩图的红色部分是给定集合运算的结果集合。

Python 集合提供了允许您执行这些数学运算的方法,以及提供等效结果的运算符。

在探索这些方法之前,让我们从初始化两组数据科学家和数据工程师开始。

dataScientist = set(['Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS'])
dataEngineer = set(['Python', 'Java', 'Scala', 'Git', 'SQL', 'Hadoop'])

联盟

表示为 dataScientist ∪ dataEngineer 的并集是 dataScientist 和/或 dataEngineer 的所有值的集合。您可以使用union方法找出两个集合中的所有唯一值。

# set built-in function union
dataScientist.union(dataEngineer)# Equivalent Result 
dataScientist | dataEngineer

从并集返回的集合可以被可视化为下面维恩图的红色部分。

交集

两个集合 dataScientist 和 dataEngineer 的交集表示为 dataScientist ∩ dataEngineer,它是 dataScientist 和 dataEngineer 的所有值的集合。

# Intersection operation
dataScientist.intersection(dataEngineer)# Equivalent Result
dataScientist & dataEngineer

从交集返回的集合可以被可视化为下面维恩图的红色部分。

您可能会发现,在这种情况下,您希望确保两个集合没有公共值。换句话说,你希望两个集合的交集是空的。这两个集合称为不相交集合。您可以通过使用isdisjoint方法来测试不相交的集合。

# Initialize a set
graphicDesigner = {'Illustrator', 'InDesign', 'Photoshop'}# These sets have elements in common so it would return False
dataScientist.isdisjoint(dataEngineer)# These sets have no elements in common so it would return True
dataScientist.isdisjoint(graphicDesigner)

您可以注意到,在下面维恩图所示的交集中,不相交集 dataScientist 和 graphicDesigner 没有共同的值。

差异

两个集合 dataScientist 和 dataEngineer 的差,表示为 dataScientist \ dataEngineer,是 dataScientist 的所有值的集合,这些值不是 dataEngineer 的值。

# Difference Operation
dataScientist.difference(dataEngineer)# Equivalent Result
dataScientist - dataEngineer

从差异返回的集合可以被可视化为下面维恩图的红色部分。

对称 _ 差异

两个数据集 dataScientist 和 dataEngineer 的对称差表示为 dataScientist △ dataEngineer,它是恰好是两个集合中一个集合的值而不是两个集合的值的集合。

# Symmetric Difference Operation
dataScientist.symmetric_difference(dataEngineer)# Equivalent Result
dataScientist ^ dataEngineer

从对称差返回的集合可以被可视化为下面维恩图的红色部分。

集合理解

您可能之前已经了解了列表理解、字典理解和生成器理解。还有一套理解。集合理解非常相似。Python 中的集合理解可以按如下方式构造:

{skill for skill in ['SQL', 'SQL', 'PYTHON', 'PYTHON']}

上面的输出是两个值的集合,因为集合不能有相同元素的多次出现。

使用集合理解背后的想法是让你用代码写和推理,就像你用手做数学一样。

{skill for skill in ['GIT', 'PYTHON', 'SQL'] if skill not in {'GIT', 'PYTHON', 'JAVA'}}

上面的代码类似于您之前了解到的集合差异。只是看起来有点不一样。

会员测试

成员资格测试检查特定元素是否包含在序列中,例如字符串、列表、元组或集合。在 Python 中使用集合的一个主要优点是它们为成员测试进行了高度优化。例如,集合比列表更有效地进行成员资格测试。如果你有计算机科学背景,这是因为对于列表,集合中成员测试的平均用例时间复杂度是 O(1)比 O(n)。

下面的代码显示了一个使用列表的成员测试。

# Initialize a list
possibleList = ['Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS', 'Java', 'Spark', 'Scala']# Membership test
'Python' in possibleList

对于器械包也可以做类似的事情。集合只是碰巧更有效率。

# Initialize a set
possibleSet = {'Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS', 'Java', 'Spark', 'Scala'}# Membership test
'Python' in possibleSet

由于possibleSet是一个集合,值'Python'possibleSet的值,这可以表示为'Python'possibleSet

如果你有一个不属于集合的值,比如'Fortran',它将被表示为'Fortran'possibleSet

子集

理解成员关系的一个实际应用是子集。

我们先初始化两组。

possibleSkills = {'Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS'} mySkills = {'Python', 'R'}

如果集合mySkills的每个值也是集合possibleSkills的值,那么mySkills被称为possibleSkills的子集,数学上写成mySkillspossibleSkills

您可以使用issubset方法查看一个集合是否是另一个集合的子集。

mySkills.issubset(possibleSkills)

因为该方法在这种情况下返回 True,所以它是一个子集。在下面的维恩图中,注意集合mySkills的每个值也是集合possibleSkills的值。

冰冻集

您遇到了嵌套列表和元组。

# Nested Lists and Tuples
nestedLists = [['the', 12], ['to', 11], ['of', 9], ['and', 7], ['that', 6]]
nestedTuples = (('the', 12), ('to', 11), ('of', 9), ('and', 7), ('that', 6))

嵌套集合的问题是你通常不能有嵌套集合,因为集合不能包含可变值。

在这种情况下,您可能希望使用冷冻箱。除了 frozenset 是不可变的之外,frozenset 与集合非常相似。

你可以用frozenset()制作一个冰冻人。

# Initialize a frozenset
immutableSet = frozenset()

如果您使用类似下面代码的 frozenset,您可以创建一个嵌套集。

nestedSets = set([frozenset()])

重要的是要记住,frozenset 的一个主要缺点是,由于它们是不可变的,这意味着您不能添加或删除值。

结论

Python 集合对于从列表等集合中有效移除重复值以及执行联合和交集等常见数学运算非常有用。人们经常遇到的一些挑战是何时使用各种数据类型。例如,如果你觉得不确定什么时候使用字典比使用字典更有利,我鼓励你去看看 DataCamp 的日常练习模式。如果您对本教程有任何问题或想法,请在下面的评论中或通过 Twitter 联系我们。

最初发表于www.datacamp.com

Python 与 Scala:基本命令的比较(第一部分)

原文:https://towardsdatascience.com/python-vs-scala-a-comparison-of-the-basic-commands-fae23b3ede23?source=collection_archive---------3-----------------------

“MacBook Pro on brown wooden table” by Max Nelson on Unsplash

我最近开始玩一点 Scala,我不得不说这是一种创伤。我喜欢学习新事物,但在用 Python 编程数月后,在解决数据科学问题时将它放在一边并切换模式是不自然的。在学习一门新语言的时候,不管是编码还是口语,出现这种情况是很正常的。我们倾向于用我们知道的东西来填补我们不知道的东西的空白,即使它们不属于我们试图写/说的语言!当试图学习一门新语言时,完全被你想学的语言所包围是很重要的,但首先,在已知语言和新语言之间建立良好的平行关系是很重要的,至少在开始时是如此。这对我很有用,我是一个双语的人,在成年后很快就学会了第二语言。一开始,我需要意大利语(我所知道的语言)和英语(我正在学习的语言)之间的联系,但是随着我的英语越来越流利,我开始忘记平行关系,因为这变得很自然,我不再需要先在脑子里翻译它了。事实上,我决定写这篇文章的原因是为了在 Python 和 Scala 之间建立并行性,对于像我一样精通其中一种,并开始学习另一种的人来说。

我最初是想把重点放在熊猫/Sklearn 和 Spark 上,但我意识到,不先把基础打好,意义不大。这就是为什么在这篇文章中,我们将看看 Python 和 Scala 的基础知识:如何处理字符串、列表、字典等等。我打算在不久的将来发表第二部分,其中我将介绍如何用两种语言处理数据帧和构建预测模型。

1.重要的事情先来

第一个区别是当编码是这两种语言时使用的约定:如果你不遵循它,这不会抛出一个错误或任何类似的东西,但它只是一个编码者遵循的非书面规则。

当定义一个新的变量、函数或其他东西时,我们总是选择一个对我们有意义的名字,这个名字很可能由两个或更多的单词组成。如果是这种情况,在 Python 中我们将使用snake_case,而在 Scala 中camelCase:差别是显而易见的。在蛇的情况下,所有的单词都是小写的,我们使用_来分隔它们,在骆驼的情况下没有分隔,除了第一个单词,所有的单词都是大写的。

另一个显著的区别是我们如何定义两种语言中的变量。在 Python 中,我们只需创建一个名称,并将其赋给我们需要的值,而在 Scala 中,我们需要指定我们是在定义一个变量还是一个值,我们通过在名称前分别放置varval来做到这一点(注意,无论我们是在赋数值还是字符串,这都是有效的)。

Initializing values and variables in Scala.

varval的区别很简单:变量可以修改,而值不能。在图中所示的例子中,我实例化了一个var字符串,然后将其更改为:all good。然后,我将同一个字符串赋给了一个val,并试图再次改变它:不可行。

在 Python 中,不需要指定:如果你想改变你之前分配的东西,这取决于你。在 Python 的情况下,我只需要做string = 'my_string'

另一个普遍的区别是关于注释。在 Python 中,只有一种方法可以做到这一点,不管是单行还是多行,那就是在每一行的注释前加一个#:

# this is a commented line in Python

Scala 提供了两种注释方式,要么将//放在每一行,要么将注释放在/**/之间:

// this is a commented line in Scala
/* and this is a multiline comment, still in Scala...
...just choose! */

现在,非常基础的解释,让我们看看潜水更深。

2.列表和数组

list(Python 中的)或 Array(Scala 中的)是最重要的对象:它们可以包含字符串和/或数字,我们可以操作它们,遍历它们,添加或减去元素等等。它们基本上可以服务于任何目的,我不认为我曾经不使用它们编码过任何东西,所以让我们看看我们可以用它们做什么,以及如何做。

2.1.规定

让我们创建一个包含数字和字符串混合的列表。

my_list = [2, 5, 'apple', 78] **# Python**

var myArray = Array(2, 5, "apple", 78) **// Scala**
**/* notice that in Scala I wrapped the string between "", and that is the only way to do it! In python you can use both "" and '' indifferently */**

2.2.索引

列表和数组都是零索引的,这意味着第一个元素放在索引 0 处。所以,如果我们想提取第二个元素:

my_list[1] **# Python** uses [] to index

myArray(1) **// Scala** uses () to index

2.3.限幅

在这两种语言中,切片时不会计算第二个索引。所以,如果我们想提取前三个元素:

my_list[0:3] **# Python** slicing works like indexing

myArray.slice(0,3) **// Scala** needs the .slice()

2.4.检查第一个、最后一个、最大和最小元素

**# Python**my_list[0]     # first element
my_list[-1]    # last element
max(my_list)   # maximum element
min(my_list)   # minimum element# NOTE: min() and max() will work exclusively if the list contains 
# numbers only!**// Scala**myArray.head    // first element
myArray(0)      // other way to check the first element
myArray.last    // last element
myArray.max     // maximum element
myArray.min     // minimum element/* NOTE: .min and .max will work exclusively if the array contains numbers only!*/

2.5.总和与乘积

对于 min 和 max,只有当列表/数组只包含数字时,才支持这些操作。此外,为了将 Python 列表中的所有元素相乘,我们需要建立一个for循环,这将在本文中进一步讨论。与 Scala 不同,它没有预加载的功能。

sum(my_list) # summing elements in **Python**'s list

// **Scala**
myArray.sum   // summing elements in array
myArray.product  // multiplying elements in array

2.6.添加元素

列表和数组是没有顺序的,所以通常的做法是在末尾添加元素。假设我们想要添加字符串"last words":

my_list.append('last words') # adding at the end of **Python**'s list

myArray :+= "last words" // adding at the end of **Scala**'s array

如果出于某种原因,我们想在最开始添加一些东西,就说数字99:

my_list.insert(0, 99) # this is a generic method in **Python**. The 
# first number you specify in the parenthesis is the index of the 
# position where you want to add the element.
# 0 means that you want the element to be added at the very 
# beginningmyArray +:= 99 /* adding an element at the beginning of **Scala**'s array */

3.打印

这也是我们在编码时一直使用的东西,幸运的是这两种语言之间只有一点点差别。

print("whatever you want") # printing in **Python**

println("whatever you want") // printing in **Scala**

4.For 循环

这里有一些不同:Python 需要缩进来创建语句后的块和冒号,而 Scala 需要括号中的 for 条件,以及不需要缩进的花括号中的块。尽管如此,我还是喜欢使用缩进,它让代码看起来更整洁。

# for loop in **Python**
for i in my_list:print(i)// for loop in **Scala**
for (i <- myArray){println(i)
}

5.映射和/或过滤

在 Python 中,所有的事情都可以通过使用列表理解来完成。在 Scala 中,我们将不得不使用函数。

5.1.绘图

假设我们有一个只有数值的列表/数组,我们想把它们都增加三倍。

[i*3 for i in my_list] # mapping in **Python**

myArray.map(i => i*3) // mapping in **Scala**

5.2.过滤

假设我们有一个只有数值的列表/数组,我们想只过滤那些能被 3 整除的数值。

[i for i in my_list if i%3 == 0] # filtering in **Python**

myArray.filter(i => i%3 == 0) // filtering in **Scala**

5.3.过滤和映射

如果我们想找到偶数并且只将它们乘以 3 呢?

[i*3 for i in my_list if i%2 == 0] # **Python**

myArray.filter(i => i%2 == 0).map(i => i*3) // **Scala**

6.字典/地图

虽然它们在两种语言中的名称不同,但它们完全是一回事。它们都有keys,我们给它们赋值values

6.1.创建字典/地图

让我们创建一个存储我的名、姓和年龄的数据库,并假设我 18 岁。

# **Python**
my_dict = {
'first_name': 'Emma',
'last_name': 'Grimaldi',
'age': 18
}

在 Scala 中,我们可以用两种不同的方式做到这一点。

// **Scala** mode 1
var myMap = (
"firstName" -> "Emma",
"lastName" -> "Grimaldi",
"age" -> 18
)// Scala mode 2
var myMap = (
("firstName", "Emma"),
("lastName", "Grimaldi"),
("age", 18)
)

6.2.添加到字典/地图

让我们把我的原籍国加入我的字典/地图。

my_dict['country_of_origin'] = 'Italy' # creating new key in **Python**

myMap += ("countryOfOrigin" -> "Italy") /* creating new key in **Scala** */

6.3.索引

这与索引列表/数组的工作方式相同,但是我们使用的是键,而不是位置。如果我想看我的名字:

# **Python**
my_dict['first_name']// **Scala**
myMap("firstName")

6.4.环

如果我们想打印字典/映射,在这两种情况下,我们都必须通过键和值进行 for 循环。

# Python
for key, value in my_dict.items():print(key)print(value)// Scala
for ((key, value) <- myMap){println(key)println(value)
}

7.元组

是的,它们在两种语言中的叫法是一样的!但是,虽然它们在 Python 中是零索引,但在 Scala 中却不是。让我们创建一个元组(1, 2, 3),然后调用第一个值。

# Python
my_tup = (1, 2, 3)
my_tup[0]
# the indexing is the same as lists// Scala
myTup = (1, 2, 3)
myTup._1
// the indexing is way different than arrays!

8.设置

是的,另一个共同的名字!在下面的两个例子中,集合将只包含1, 3, 5,因为集合不接受副本。

my_set = {1, 3, 5, 1} # in **Python**, sets are defined by curly braces

mySet = Set(1, 3, 5, 1) // **Scala**

9.功能

到目前为止,我们已经做了很多,如果你成功了,做得很好!这是这篇文章的最后一段,幸运的是在 Python 和 Scala 之间定义函数并没有太大的不同。它们都以def开头,而前者需要一个return语句,后者不需要。另一方面,Scala 想知道我们将要输入和输出什么类型的变量,而 Python 并不关心。让我们编写一个非常简单的函数,它接受一个字符串作为输入,并返回前 5 个字符。

# **Python**
def chop_string(input_string):return input_string[0:5]

缩进在 Python 中也很重要,否则函数将不起作用。Scala 只是喜欢它的花括号。

// **Scala**
def chopString(inputString: String): String = {inputString.slice(0, 5)
}

就是这样!我希望这对那些刚刚开始熟悉 Python 或 Scala 的人有所帮助。下一步将构建类似的指南,探索熊猫/sklearn 和 sparks 的不同之处,期待!我希望你也一样!

如果你想知道为什么应该使用 Python 而不是 Scala,或者反之亦然,我发现下面的图片非常有助于澄清两者之间的直接差异。

source link

请随意查看:

本帖第二部分

我的其他媒体帖子。

我的 LinkedIn 个人资料。

感谢您的阅读!

Python Web 框架-Python 中 Web 框架的详细列表

原文:https://towardsdatascience.com/python-web-framework-a-detailed-list-of-web-frameworks-in-python-1916d3c6222d?source=collection_archive---------3-----------------------

Python Web Framework — A Detailed List of Web Frameworks in Python

什么是 Python Web 框架?

Python Web framework 是允许开发人员编写 Web 应用程序或服务的包或模块的集合。有了它,开发人员不需要处理像协议、套接字或进程/线程管理这样的底层细节。

Python web 框架将帮助您:

  • 解释请求(获取表单参数,处理 cookies 和会话,..)
  • 产生响应(以 HTML 或其他格式呈现数据,..)
  • 持久存储数据(和其他东西)

现在,让我们看看最有用和最著名的 Python web 框架,来帮助您进行 web 开发。

学习: Python 元组 vs 列表——列表和元组的比较

Python 全栈框架

Python 中的全栈框架试图为应用程序提供完整的解决方案。它试图为堆栈中的每一层提供组件。

a.姜戈

Django Python 是为有期限的完美主义者设计的框架。有了它,你可以用更少的时间和代码构建更好的 Web 应用。Django 以专注于自动化而闻名。它还信奉干(不要重复自己)原则。

Django 最初是为内容管理系统开发的,但是现在被用于多种 web 应用程序。这是因为它的模板、自动数据库生成、DB 访问层和自动管理界面生成。它还提供了一个用于开发的 web 服务器。

使用 Django Python 的大公司有- Instagram、Pinterest、Disqus、Mozilla、华盛顿时报和 Bitbucket。事实上,当我们想到“框架”和“Python”这两个术语时,首先想到的是 Django。
我们将在下一课看到更多关于姜戈的内容。

b.涡轮齿轮

Python TurboGears — Python Web 框架

使用 TurboGears,您可以在几分钟内创建一个数据库驱动的、可扩展的应用程序。

它是一个带有 ORM 的 MVC web 框架,具有真正的多数据库支持和对水平数据分区的支持。它还有一个小部件系统来简化 AJAX 应用程序的开发。你可以另外安装它的模板引擎 Kajiki。

了解:如何在 Windows 上安装 Python

TurboGears 是一个微框架和全栈解决方案。它的 PyPI 包叫做 tg.devtools。

c.web2py

Python Web 框架— Python web2py

使用 web2py,您可以通过提供的 web 界面开发、部署、调试、测试、管理数据库和维护应用程序。它没有配置文件,你甚至可以从 USB 驱动器上运行它。

web2py 使用 MVC 内置的票务系统来管理错误。

d.立方体网络

CubicWeb 是一个语义 Web 应用框架,它以查询语言和选择+查看机制为特色。它还具有多个数据库、安全性、工作流和可重用组件。

e.姜戈-霍索奇

Django-hotsauce 是一个通用的 web 工具包,位于 Django 和其他框架之上。它是一个交互式 Pythonic API,允许您使用 WSGI 1.0 规范创建可伸缩的 web 应用程序。它还为 Schevo DBMS、Durus、ZODB 和 Authkit 项目提供了本机绑定。

学习:2018 年我应该学习 Python 的 7 个理由

f.乔托

一个严格的 MVC 框架,严格分离模型、视图和控制器元素,Giotto 确保设计者、Web 开发者和系统管理员可以独立工作。它还包括控制器模块,允许您在 web、irc 或命令行上构建应用程序。这些都是最流行的 Python web 框架。

g.神交

Grok 构建在现有的 Zope 3 库之上。它旨在通过强调约定胜于配置和 DRY(不要重复自己)来提供更容易的学习曲线和更敏捷的开发体验。

h.塔架

Python Web Framework — Python Pylons

Pylons 是一个轻量级 Web 框架,旨在实现灵活性和快速开发。它结合了 Ruby、Python 和 Perl 的最佳思想,形成了一个结构化但极其灵活的 Python Web 框架。有了 Pylons,Web 开发变得快速、灵活和容易。塔是建立在粘贴的顶部。但在与金字塔合并形成塔项目后,它处于仅维护状态。

一.里尔

可以使用 Reahl 用纯 Python 开发 web 应用。但是,您可以使用常规 Python 代码来使用、定制或编写小部件。这些小部件描述了特定的服务器端和客户端行为。

j.喘息网

Wheezy 是一个轻量级、高性能和高并发性的 WSGI web 框架。它的主要特性包括路由、模型更新/验证、身份验证/授权、具有依赖性的内容缓存、中间件等等。有了这些,我们就能建立现代、高效的网络。

k.Zope2

Python Web Framework — Python Zope

Zope2 是 Python web 框架的鼻祖,它是一个网络家族。它是一个 web 框架和通用应用服务器。今天,它主要用于 CMS。我们还有 Zope3,它是一个独立的框架和相关库的集合。

长度龙卷风

Python Web Framework — Tornado

虽然 Tornado 并不出名,但它在非阻塞 I/O 方面非常出色。您可以扩展它来处理数万个开放连接。它为长轮询、WebSockets 和其他需要持续连接的应用提供了一个完美的框架。官方上,Tornado 只支持 Linux 和 BSD OS (Windows 和 Mac OS X-仅用于开发)。Tornado 起源于 FriendFeed 项目,现在属于脸书。

Python 中的非全栈框架

Python 非全栈框架将提供基础应用服务器。这要么作为它自己的独立进程在 Apache 上运行,要么在其他环境中运行。我们来看看最受欢迎的。

a.蟒蛇瓶

Bottle 是一个简单快速的微框架,可以用来创建小型 Web 应用程序。它提供带有 URL 参数支持、模板、键/值数据库和内置 HTTP 服务器的请求调度路由。它还为第三方 WSGI/HTTP-server 和模板引擎提供了适配器。这些都在一个文件中;除了 Python 标准库之外,没有任何依赖关系。

b.樱桃派

Python Web Framework — Python CherryPy

这是一个 pythonic 化的、面向对象的 HTTP 框架。CherryPy 支持的 web 应用程序是一个独立的 Python 应用程序,它嵌入了自己的多线程 web 服务器。在某种程度上,CherryPy 是程序员和问题之间的一种方式。它还支持各种 web 服务器,如 Apache、IIS 等。CherryPy 将允许您一次启动多个 HTTP 服务器。

c.蟒蛇皮烧瓶

Python Web 框架— Python Flask

就像我们之前说过的,Flask 是 Python 的一个微框架。它包括一个内置的开发服务器和单元测试支持。它还完全支持 Unicode,支持 RESTful 请求调度和 WSGI 遵从性。

学习: Python 正则表达式

当你想开发小而简单的应用程序时,Flask 会很有用。有了它,您可以随心所欲地操作您的数据库——使用 SQLAlchemy 或其他任何东西。LinkedIn 和 Pinterest 使用 goof Flask 就是一个例子。

d.紧抱

Python Web Framework — Python Hug

Hug 是 Python 最快的 web 框架之一。有了它,您可以构建 API。它支持几个 API 版本、自动 API 文档和注释驱动的验证。它构建在另一个 JSON 框架 Falcon 之上。

e.金字塔

Python Web Framework — pyramid-positive

与我们目前讨论的一些不同,Pyramid 是大型应用程序的框架。它是灵活的;金字塔 web 应用程序从单个文件模块开始,并演变成一个雄心勃勃的项目。你可以说它使现实世界的 Web 应用程序开发和部署变得更加有趣、可预测和高效。实际上,金字塔是一个塔架项目。

f.信天翁

它是一个小型、灵活的 Python 工具包,允许您开发高度有状态的 Web 应用程序。Albatross 部署到 CGI、FastCGI 和 ModPython 服务器。

g.电路

Circuits 很像 CherryPy,但它是开发独立多进程应用程序的高效 web 框架。它支持并发、异步 I/O 组件,并且是事件驱动的。

h.猎鹰

Python Web Framework — Python Falcon

Falcon 是一个面向小型应用程序、应用程序后端和高级框架的微框架,它鼓励遵循 REST 的概念。它是 Python 最快的 web 框架之一,被 EMC、Hurricane Electric、OpenStack、Opera Software、Wargaming 和其他公司使用。

一.咆哮者

Python Web Framework — Python Growler

Growler 构建于 asyncio 之上,灵感来源于 Node.js 的 Connect 和 Express 框架,如果想要 ORM 或者模板化,必须手动安装。它通过中间件链来处理请求。

j.更多路径

MorePath 是一个灵活的、模型驱动的 web 框架。它支持 REST,关注可重用性和可扩展性。

k.比重瓶

Pycnic 是 Python 开发 JSON APIs 最快的 web 框架之一。该框架是面向对象的,并针对 JSON APIs 进行了优化。它只包含创建 Web APIs 的工具,这些工具占用的内存更少。

长度萨尼奇

Python Web Framework — Python Sanic

Sanic 是一个类似烧瓶的框架,但是速度很快。它支持异步请求处理程序,并使代码非阻塞和快速。

这就是 Python Web 框架教程。希望你喜欢我们的解释。

结论

这些是 Python web 开发中最著名的 Python Web 框架。你喜欢 python web 开发框架吗?告诉我们,你最喜欢哪一个?或者,如果您对 Python web 框架有任何疑问,请发表评论。

带有 Flask 和 Raspberry Pi 的 Python WebServer

原文:https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d?source=collection_archive---------0-----------------------

让我们创建一个简单的网络服务器来控制你家里的事情。有很多方法可以做到这一点。例如,在我的教程:IoT——仅使用 HTML 和 Shell 脚本通过互联网控制 Raspberry Pi 机器人中,我们已经探索了如何使用light tpd web 服务器通过本地网络控制机器人。对于这里的这个项目,我们将使用 FLASK ,一个非常简单和免费的 Python 微框架。有了 Flask,通过互联网控制 Raspberry GPIOs 将变得非常简单。

看完这篇教程,请访问它的续篇: 从数据到图形:一个带 Flask 和 SQLite 的 Web Jorney

1.介绍

Flask 被称为微框架,因为它不需要特殊的工具或库。它没有数据库抽象层、表单验证或任何其他组件,而现有的第三方库提供了通用功能。然而,Flask 支持可以添加应用程序特性的扩展,就好像它们是在 Flask 本身中实现的一样。

在本教程中,我们将使用 Raspberry Pi 作为本地 Web 服务器,我们将通过一个简单的网页来控制其 3 个编程为输出的 gpio(充当致动器)和监视器 2 个编程为输入的 gpio(传感器)。

上面的框图显示了我们想要实现的目标

下面的视频可以给出一些提示:

请注意,您将在这里学习的使用 Flask 的 Python WebServer 可以直接应用于任何 Linux/OS 机器,并对 Windows PCs 进行一些调整(不幸的是,这不是我的专业领域)。

2.安装 FLASK 并设置您的 RPi 服务器

砂箱安装

首先要做的是在你的树莓派上安装 Flask。转到终端并输入:

sudo apt-get install python3-flask

当你开始一个新项目时,最好是创建一个文件夹来组织你的文件。例如:

mkdir rpiWebServer

上面的命令将创建一个名为“Server”的文件夹。我们将在那里保存我们的 python 文件(应用程序):

/home/pi/Documents/Server

在这个文件夹中,让我们创建另外两个子文件夹:静态用于 CSS 和最终的 JavaScript 文件,以及模板用于 HTML 文件(或者更准确地说,Jinja2 模板。但是不要担心。转到您新创建的文件夹:

cd rpiWebServer

并创建两个新的子文件夹:

mkdir static

mkdir templates

最终的文件夹“树”,看起来会像:

/rpiWebServer/static/templates

Python 服务器应用程序

现在,让我们用 Flask 创建我们的第一个 python 服务器:

  • 打开你的 Python3 IDE,Thonny 或者 Geany。
  • 在您的 IDE 上复制下面的“Hello Word”代码,并将其保存为例如 helloWorld.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():return 'Hello world'
if __name__ == '__main__':app.run(debug=True, port=80, host='0.0.0.0')

上述代码的作用是:

1.将 Flask 模块加载到 Python 脚本中:

from flask import Flask

2.创建名为 app 的 Flask 对象:

app = Flask(__name__)

3.当有人访问服务器的根 URL ('/')时,运行 index()函数。在这种情况下,只发送文本“Hello World!”通过“返回”到客户的网络浏览器

def index():return "Hello Word"

4.一旦这个脚本从命令行在终端上运行,服务器就开始“监听”端口 80,报告任何错误:

if __name__ == '__main__':app.run(debug=True, port=80, host='0.0.0.0')

Raspberry PI IP 地址:

如果您不确定您的 RPi IP 地址,请在您的终端上运行:

ifconfig

在 wlan0: section 你会找到。就我而言:

10.0.1.27

运行应用程序

现在,运行上面的应用程序:

sudo python3 helloWorld.py

在上面的第一张图片上,你可以看到终端上会出现什么。除非您键入[CTRL] + [C],否则应用程序将会运行。

现在,你必须打开与你的树莓连接到同一个 wifi 网络的任何网络浏览器,并键入它的 IP 地址,如上面第二张图片所示。如上图所示,“Hello World”应该会出现在您的浏览器中。

注意上图底部有 2 条线。这几行显示两个不同的 web 浏览器请求了根 URL,我们的服务器返回了 HTTP 状态代码 200 表示“OK”。我在 RPI 本身(10.1.0.27)和我的 Mac (10.1.0.10)上输入了我们的 RPi 服务器地址。对于每个新的请求,只要应用程序正在运行,终端就会出现一个新的行。

3.创建合适的服务器网页

让我们完善我们的“Hello World”应用程序,创建一个 HTML 模板和一个 CSS 文件来设计我们的页面。事实上,这是很重要的,否则,你将会使 Python 脚本变得复杂。

模板

创建一个位于“模板”子文件夹中的 HTML 文件,我们可以使用单独的文件,在需要插入动态数据的地方放置占位符。

因此,我们将创建一个名为index.html的文件,保存在 /templates 中。您可以使用任何文本编辑器来创建您的 HTML 文件。可以是 Geany、终端的“nano”或位于“附件”主菜单下的 RPi 文本编辑器(LeafPad)。

GEANY 可用于同时处理所有项目文件。py;。html 和。css)对于更大更复杂的项目来说,这是一个很好的选择

好了,让我们创建 /templates/index.html :

<!DOCTYPE html><head><title>{{ title }}</title></head><body><h1>Hello, World!</h1><h2>The date and time on the server is: {{ time }}</h2></body>
</html>

注意,HTML 模板中的 双花括号 中的任何内容都被解释为一个变量,该变量将通过 render_template 函数从 Python 脚本传递给它。

现在,让我们创建一个新的 Python 脚本。我们将把它命名为 helloWorldTemplate.py:

'''
Code created by Matt Richardson 
for details, visit:  http://mattrichardson.com/Raspberry-Pi-Flask/inde...
'''
from flask import Flask, render_template
import datetime
app = Flask(__name__)
@app.route("/")
def hello():now = datetime.datetime.now()timeString = now.strftime("%Y-%m-%d %H:%M")templateData = {'title' : 'HELLO!','time': timeString}return render_template('index.html', **templateData)
if __name__ == "__main__":app.run(host='0.0.0.0', port=80, debug=True)

注意,我们使用“now”对象中的日期和时间创建了一个格式化的string("timeString"),其中存储了当前时间。

在上面的代码中,下一件重要的事情是我们创建了一个变量字典(一组键,比如与值相关联的标题,比如 HELLO!)传递到模板中。在“返回”上,我们将使用模板数据字典中的变量将index.html模板返回到网络浏览器。

执行 Python 脚本:

sudo python3 helloWorldTemplate.py

打开任何网络浏览器,输入您的 RPi IP 地址。上图是结果。

请注意,每当您使用 Python 脚本传递的实际变量数据刷新页面时,页面的内容都会发生动态变化。在我们的例子中,“标题”是一个固定值,但是“时间”每秒都在改变它。

现在,让我们在页面上添加一些样式,创建一个 CSS 文件并将其存储在/static/style.css 上:

body {background: blue;color: yellow;
}

您还必须修改 index.html 文件,通知它查找 style.css 文件。您可以在“head”处插入“link”:

<!DOCTYPE html><head><title>{{ title }}</title><link rel="stylesheet" href="../static/style.css/"></head><body><h1>Hello, World!</h1><h2>The date and time on the server is: {{ time }}</h2></body>
</html>

记住,index.html 在“下”/template,style.css 在“下”/static,所以,注意,你必须告诉 HTML 再次“向上”和“向下”去寻找 static 子文件夹:../static/style . CSS .

下图是新风格的网页!

有关 Raspberry Pi 的更详细的 Flask 概述,请访问 Raspberry Pi 组织项目:python-we b-server-with-Flask。

4.硬件

硬件很简单。仅遵循上述电气连接。

5.读取 GPIO 状态

现在让我们通过监控它们的 GPIOs 来读取我们的“传感器”的状态。

Python 脚本

让我们创建一个新的 Python 脚本,并将其命名为 app.py:

'''Raspberry Pi GPIO Status and Control
'''
import RPi.GPIO as GPIO
from flask import Flask, render_template
app = Flask(__name__)
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
button = 20
senPIR = 16
buttonSts = GPIO.LOW
senPIRSts = GPIO.LOW# Set button and PIR sensor pins as an input
GPIO.setup(button, GPIO.IN)   
GPIO.setup(senPIR, GPIO.IN)@app.route("/")
def index():# Read Sensors StatusbuttonSts = GPIO.input(button)senPIRSts = GPIO.input(senPIR)templateData = {'title' : 'GPIO input Status!','button'  : buttonSts,'senPIR'  : senPIRSts}return render_template('index.html', **templateData)
if __name__ == "__main__":app.run(host='0.0.0.0', port=80, debug=True)

注意,我们所做的只是将 GIPOs 20 和 16 定义为输入,读取其值并将其存储在两个变量上:buttonSts 和 senPIRSts。在函数 index()中,我们将通过变量字典中的“button”和“senPIR”变量将这些值传递给我们的网页: templateData。

创建 app.py 后,在终端上运行它:

python3 app.py

模板

我们还创建一个新的 index.html 来显示两个传感器的 GPIO 状态:

<!DOCTYPE html><head><title>{{ title }}</title><link rel="stylesheet" href='../static/style.css'/></head><body><h1>{{ title }}</h1><h2>Button pressed:  {{ button }}</h1><h2>Motion detected: {{ senPIR }}</h2></body>
</html>

不要忘记刷新页面以查看结果。

按下按钮或在 PIR 传感器前移动并刷新页面。

图为网页。

6.控制 GPIOs

现在我们知道了如何“读取”GPIO 状态,让我们来改变它们。我们要做的是通过网页“命令”这些“致动器”。我们有 3 个 led 连接到树莓 GPIOs。远程命令他们,我们将改变他们的地位从低到高,反之亦然。例如,我们可以用继电器代替发光二极管来控制你房间的灯和/或风扇。

python 脚本

让我们创建一个新的 Python 脚本,并将其命名为 app.py:

'''Raspberry Pi GPIO Status and Control
'''
import RPi.GPIO as GPIO
from flask import Flask, render_template, request
app = Flask(__name__)
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
#define actuators GPIOs
ledRed = 13
ledYlw = 19
ledGrn = 26
#initialize GPIO status variables
ledRedSts = 0
ledYlwSts = 0
ledGrnSts = 0
# Define led pins as output
GPIO.setup(ledRed, GPIO.OUT)   
GPIO.setup(ledYlw, GPIO.OUT) 
GPIO.setup(ledGrn, GPIO.OUT) 
# turn leds OFF 
GPIO.output(ledRed, GPIO.LOW)
GPIO.output(ledYlw, GPIO.LOW)
GPIO.output(ledGrn, GPIO.LOW)@app.route("/")
def index():# Read Sensors StatusledRedSts = GPIO.input(ledRed)ledYlwSts = GPIO.input(ledYlw)ledGrnSts = GPIO.input(ledGrn)templateData = {'title' : 'GPIO output Status!','ledRed'  : ledRedSts,'ledYlw'  : ledYlwSts,'ledGrn'  : ledGrnSts,}return render_template('index.html', **templateData)@app.route("/<deviceName>/<action>")
def action(deviceName, action):if deviceName == 'ledRed':actuator = ledRedif deviceName == 'ledYlw':actuator = ledYlwif deviceName == 'ledGrn':actuator = ledGrnif action == "on":GPIO.output(actuator, GPIO.HIGH)if action == "off":GPIO.output(actuator, GPIO.LOW)ledRedSts = GPIO.input(ledRed)ledYlwSts = GPIO.input(ledYlw)ledGrnSts = GPIO.input(ledGrn)templateData = {'ledRed'  : ledRedSts,'ledYlw'  : ledYlwSts,'ledGrn'  : ledGrnSts,}return render_template('index.html', **templateData)
if __name__ == "__main__":app.run(host='0.0.0.0', port=80, debug=True)

我们在上述代码中的新内容是新的“路线”:

@app.route("/<deviceName>/<action>")

在网页上,呼叫将按照以下格式生成:

[http://10.0.1.27/ledRed/on](http://10.0.1.27/ledRed/on)

或者

[http://10.0.1.27/ledRed/off](http://10.0.1.27/ledRed/off)

对于上面的例子, ledRed 是“设备名称”,而 onoff 是可能的“动作”的例子。

这些路线将被识别并适当地“工作”。主要步骤是:

  • 例如,在其等效的 GPIO 引脚上转换字符串“ledRED”。整数变量 ledRed 相当于 GPIO13。我们将把这个值存储在变量“执行器”上
  • 对于每个致动器,我们将分析“动作”,或“命令”并正确地动作。例如,如果“action = on ”,我们必须使用命令:GPIO.output(actuator,GPIO。高)
  • 更新每个执行器的状态
  • 更新变量库
  • 把数据还给 index.html

模板

现在让我们创建一个 index.html 来显示每个执行器的 GPIO 状态,更重要的是,创建“按钮”来发送命令:

<!DOCTYPE html><head><title>GPIO Control</title><link rel="stylesheet" href='../static/style.css'/></head><body><h1>Actuators</h1><h2> Status </h2><h3> RED LED ==>  {{ ledRed  }}</h3><h3> YLW LED ==>  {{ ledYlw  }}</h3><h3> GRN LED ==>  {{ ledGrn  }}</h3><br><h2> Commands </h2><h3> RED LED Ctrl ==> <a href="/ledRed/on" class="button">TURN ON</a>  <a href="/ledRed/off"class="button">TURN OFF</a></h3><h3> YLW LED Ctrl ==> <a href="/ledYlw/on" class="button">TURN ON</a>  <a href="/ledYlw/off"class="button">TURN OFF</a></h3><h3> GRN LED Ctrl ==> <a href="/ledGrn/on" class="button">TURN ON</a>  <a href="/ledGrn/off"class="button">TURN OFF</a></h3></body>
</html>

只为了给一个更好的“伏”,我创建了一个类“按钮”。如果你愿意,你只能保留正常链接。

在 style.css 文件下:

body {background: blue;color: yellow;
}
.button {font: bold 15px Arial;text-decoration: none;background-color: #EEEEEE;color: #333333;padding: 2px 6px 2px 6px;border-top: 1px solid #CCCCCC;border-right: 1px solid #333333;border-bottom: 1px solid #333333;border-left: 1px solid #CCCCCC;
}

图为控制我们的执行器的网站。

7.集成传感器和执行器

现在,我们必须将之前开发的两个部分放在一起。最终的 Python 脚本如下所示:

'''Raspberry Pi GPIO Status and Control
'''
import RPi.GPIO as GPIO
from flask import Flask, render_template, request
app = Flask(__name__)
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
#define sensors GPIOs
button = 20
senPIR = 16
#define actuators GPIOs
ledRed = 13
ledYlw = 19
ledGrn = 26
#initialize GPIO status variables
buttonSts = 0
senPIRSts = 0
ledRedSts = 0
ledYlwSts = 0
ledGrnSts = 0
# Define button and PIR sensor pins as an input
GPIO.setup(button, GPIO.IN)   
GPIO.setup(senPIR, GPIO.IN)
# Define led pins as output
GPIO.setup(ledRed, GPIO.OUT)   
GPIO.setup(ledYlw, GPIO.OUT) 
GPIO.setup(ledGrn, GPIO.OUT) 
# turn leds OFF 
GPIO.output(ledRed, GPIO.LOW)
GPIO.output(ledYlw, GPIO.LOW)
GPIO.output(ledGrn, GPIO.LOW)@app.route("/")
def index():# Read GPIO StatusbuttonSts = GPIO.input(button)senPIRSts = GPIO.input(senPIR)ledRedSts = GPIO.input(ledRed)ledYlwSts = GPIO.input(ledYlw)ledGrnSts = GPIO.input(ledGrn)templateData = {'button'  : buttonSts,'senPIR'  : senPIRSts,'ledRed'  : ledRedSts,'ledYlw'  : ledYlwSts,'ledGrn'  : ledGrnSts,}return render_template('index.html', **templateData)@app.route("/<deviceName>/<action>")
def action(deviceName, action):if deviceName == 'ledRed':actuator = ledRedif deviceName == 'ledYlw':actuator = ledYlwif deviceName == 'ledGrn':actuator = ledGrnif action == "on":GPIO.output(actuator, GPIO.HIGH)if action == "off":GPIO.output(actuator, GPIO.LOW)buttonSts = GPIO.input(button)senPIRSts = GPIO.input(senPIR)ledRedSts = GPIO.input(ledRed)ledYlwSts = GPIO.input(ledYlw)ledGrnSts = GPIO.input(ledGrn)templateData = {'button'  : buttonSts,'senPIR'  : senPIRSts,'ledRed'  : ledRedSts,'ledYlw'  : ledYlwSts,'ledGrn'  : ledGrnSts,}return render_template('index.html', **templateData)
if __name__ == "__main__":app.run(host='0.0.0.0', port=80, debug=True)

最后的 index.html:

<!DOCTYPE html><head><title>GPIO Control</title><link rel="stylesheet" href='../static/master.css'/></head><body><h1>RPi GPIO Control</h1><h2> Sensor Status </h2><h3> BUTTON ==>  {{ button  }}</h3><h3> MOTION ==>  {{ senPIR  }}</h3><br><h2> Actuator Status </h2><h3> RED LED ==>  {{ ledRed  }}</h3><h3> YLW LED ==>  {{ ledYlw  }}</h3><h3> GRN LED ==>  {{ ledGrn  }}</h3><br><h2> Commands </h2><h3> RED LED Ctrl ==> <a href="/ledRed/on" class="button">TURN ON</a>  <a href="/ledRed/off"class="button">TURN OFF</a></h3><h3> YLW LED Ctrl ==> <a href="/ledYlw/on" class="button">TURN ON</a>  <a href="/ledYlw/off"class="button">TURN OFF</a></h3><h3> GRN LED Ctrl ==> <a href="/ledGrn/on" class="button">TURN ON</a>  <a href="/ledGrn/off"class="button">TURN OFF</a></h3></body>
</html>

图为最终的网页。

8.使用模板更进一步

正如我们之前简单讨论过的, render_template()函数调用与 Flask 框架捆绑在一起的 Jinja2 模板引擎。Jinja2 用 render_template()调用中提供的参数给出的相应值替换{{ … }}块。

但这并不仅仅是 Jinja2 能做的。例如,模板也支持在{% … %}块中给出的控制语句。我们可以改变我们的 index.html 模板,以便添加条件语句,根据执行器的实际值来部署特定的按钮。换句话说,“切换”致动器状态。让我们用条件语句重写 index.html 的状态和命令部分:

<!DOCTYPE html> <head> <title>GPIO Control</title> <link rel="stylesheet" href='../static/master.css'/> </head> <body> <h1>RPi GPIO Control</h1> <h2> Sensor Status </h2> <h3> BUTTON ==>  {{ button  }}</h3> <h3> MOTION ==>  {{ senPIR  }}</h3> <br> <h2> Actuator Status & Control </h2> <h3> RED LED ==>  {{ ledRed  }}  ==>   {% if  ledRed   == 1 %} <a href="/ledRed/off"class="button">TURN OFF</a> {% else %} <a href="/ledRed/on" class="button">TURN ON</a>  {% endif %}	 </h3> <h3> YLW LED ==>  {{ ledYlw  }}  ==>   {% if  ledYlw   == 1 %} <a href="/ledYlw/off"class="button">TURN OFF</a> {% else %} <a href="/ledYlw/on" class="button">TURN ON</a>  {% endif %}	 </h3> <h3> GRN LED ==>  {{ ledGrn  }}  ==>   {% if  ledGrn   == 1 %} <a href="/ledGrn/off"class="button">TURN OFF</a> {% else %} <a href="/ledGrn/on" class="button">TURN ON</a>  {% endif %}	 </h3> </body> 
</html>

下图显示了结果:

这只是 Python 和 Flask 所能做的一小部分。如果你真的想深入了解 Flask,你可以跟随 Miguel Grimberg 的伟大教程:Flask Mega 教程,

9.结论

一如既往,我希望这个项目可以帮助其他人找到进入令人兴奋的电子世界的方法!

详情和最终代码,请访问我的 GitHub 仓库: RPi-Flask-WebServer

而要学习如何处理数据、图形、数据库,也可以看我的教程:从数据到图形。带烧瓶和 SQLite 的 Web Jorney

更多项目,请访问我的博客:【MJRoBot.org

来自世界南部的 Saludos!

下节课再见!

谢谢你,

马塞洛

Python 的生成器表达式:将大型数据集放入内存

原文:https://towardsdatascience.com/pythons-list-generators-what-when-how-and-why-2a560abd3879?source=collection_archive---------5-----------------------

Don’t forget to stay hydrated while you code. Source: Pixabay

生成器表达式是 Python 中一个有趣的特性,它允许我们创建延迟生成的可迭代对象。如果您的数据不适合内存,它们可能是解决方案。

这篇文章是我写的介绍列表理解表达的那篇文章的后续,如果你以前从未接触过这个主题,我建议你在这篇文章之前读一读。

什么是生成器表达式?

为了用生成器创建一个 Iterable,你所要做的就是写一个 List Comprehension,但是用圆括号代替方括号。所有关于列表理解的语法规则在这里都适用:你可以用一个结尾的 if 子句过滤一个生成器,并用两个嵌套的 for 循环从一个矩阵中生成一个生成器。

不过生成器有一个有趣的特性,那就是它们以一种懒惰的方式生成它们的 Iterable 对象:Iterable 中的第 i 个元素直到必要时才会被创建(因此不会占用宝贵的虚拟内存)。作为一个 catch,您不能像对列表那样对生成器进行索引或切片——而不是从 Iterable 中检索任意元素,您只能按顺序迭代它。这也是为什么不能在生成器上调用 len 函数的原因。

使用发电机的优势:一个简单的实验

为了证明发电机为什么有用,我进行了以下实验:

如您所见,生成器存储“相同”的信息,仅使用 80 字节,而列表占用了 80Mb。发电机的加载速度也快了很多,虽然我们在这里谈论的是几秒钟。很明显,在任何内存不足的问题中,用生成器替换列表可能是一个明智的选择,只要我们记住前面提到的注意事项(不要任意检索,不要进行 len 检查)。

作为迭代器的生成器

对于那些有 Java/C++背景的人来说,知道生成器可以和类似迭代器的接口一起使用可能会很有趣。这是通过使用 Python 2 中的 next 方法和 Python 3+中的 next 函数来完成的。这里有一个关于我们如何在 Python 2.7 中迭代生成器的例子:

我们通常会像其他可迭代对象一样迭代它:使用一个 for 循环。然而,给定循环结束或继续的非平凡条件,我们可能会在想要手动迭代的情况下结束。为此,我们将调用的下一个方法(Python 2)或函数(Python 3),直到它抛出一个 StopIteration 异常。请注意,在检索时单独生成每个元素所花费的时间加起来将与以非懒惰方式初始化整个列表所花费的时间一样多。最后,给定一个生成器,我们总是可以通过调用 list(our_generator),支付全部初始化成本,将它转换成一个普通的旧非懒惰列表。**

发电机的一个常见用法你可能错过了

我的一位令人敬畏的读者提交了发电机的另一种使用方式。您可能熟悉我们在 Python 中打开文件并迭代其行的方式:

该代码片段实际上使用生成器一行一行地缓慢加载文件。你看,我们一直在使用发电机!下一部夏马兰的电影怎么样?

总而言之,我们可以在任何情况下使用生成器,只要我们只需要迭代它们的结果,而不需要关心切片、索引或返回。在这些情况下使用它们通常是好的,因为我们将能够在内存中容纳非常大的数据集,而不会损失表达能力或计算时间——只要我们只需要迭代它们,一次一个对象或一行。

这是我对生成器表达式的介绍,我希望你会觉得有用。如果您认为我应该介绍任何用例,或者您认为我应该提到的任何重要特性,以及您发现的任何明显错误,请告诉我!我也很高兴知道在阅读本文后,您是否在代码中的任何地方应用了生成器。

最后,有一本我喜欢的 O'Reilly 的书,当我开始我的数据科学之旅时,我发现它非常有用。用 Python 叫做从零开始的数据科学,大概也是我得到这份工作的一半原因。如果你读到这里,你可能会喜欢它!

你可以在我的 个人网站 看到我正在做的事情以及我最近的文章和笔记。

一如既往,继续编码!

PyTorch:第一个程序并遍历

原文:https://towardsdatascience.com/pytorch-first-program-and-walk-through-ceb739134ab9?source=collection_archive---------2-----------------------

我看到 Fast.ai 正在 PyTorch 上转移,我看到 PyTorch 最适合研究原型。因此,我决定在 PyTorch 中实现一些研究论文。我已经在平行点研究过 C-DSSM 模型。但是我的实现是在喀拉斯。我将强调黑客的观点,将代码从 Keras 移植到 PyTorch,而不是博客中的研究观点。
我的实现在nish Nik/Deep-Semantic-Similarity-Model-py torch,我也记录了代码。
更多关于 C-DSSM 车型在这里。

  1. C-DSSM 模型接受多个输入。一个是查询,正面单据和负面单据。在 Keras 中,您可以传递一个列表:
Model(inputs = [query, pos_doc] + neg_docs, outputs = prob)
# where query and pos_doc is the numpy array and neg_docs is a list of numpy array

在 PyTorch 中,您可以:

def forward(self, q, pos, negs):
# this is in the class definition itself, you can easily access negs[0] for the 0th element of list. I was surprised to find that it works with list
# Another way would have been:
# def forward(self, x):
#     q = x[0]
#     pos = x[1]
#     negs = x[2:]

2.C-DSSM 模型中的第一层是 Conv1d 层。所以,我对比了 Keras 和 PyTorch 的 conv1d 文档。在喀拉斯:

keras.layers.convolutional.Conv1D(filters, kernel_size, strides=1, padding='valid', dilation_rate=1, activation=**None**, use_bias=**True**, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=**None**, bias_regularizer=**None**, activity_regularizer=**None**, kernel_constraint=**None**, bias_constraint=**None**)

在 PyTorch:

*class* torch.nn.Conv1d(*in_channels*, *out_channels*, *kernel_size*, *stride=1*, *padding=0*, *dilation=1*, *groups=1*, *bias=True*)

我必须说明:

  1. 内核大小:与 Keras 内核大小相同
  2. out_channels :同 Keras 滤镜
  3. in_channels :输入的通道数

我对 in_channels 感到困惑,我曾设想一个 590000 的输入,其中内核将排成一行并给出 5300 的输出。但是我错了

PyTorch 拥有动态图形,这也是为什么它对程序员来说很棒的原因,你可以看到图形创建时发生了什么。

所以我输入了:

lq
( 0 ,.,.) = 1.8577e-01 8.3356e-01 8.5541e-01 … 1.1579e-01 6.4221e-01 6.4712e-018.3658e-01 1.4647e-01 2.0220e-01 … 2.2165e-01 2.1841e-01 3.0833e-017.1619e-01 1.8811e-01 1.6903e-01 … 9.2867e-01 5.6902e-01 9.1074e-019.4578e-01 9.4889e-01 8.4584e-01 … 3.7839e-01 3.6997e-01 2.7487e-016.4675e-01 2.5806e-01 3.1640e-01 … 9.8110e-01 8.6193e-01 1.0357e-02
[torch.FloatTensor of size 3x5x90000]

我对它进行了卷积核运算,权重为:

( 0 ,.,.) = 
3.0515e-01
-3.3296e-01
-4.1675e-01
1.3134e-01
4.1769e-01

和偏差:

0.1725

得到的结果是:

qc4.5800e-02 5.3139e-01 5.3828e-01 … 2.0578e-01 4.6649e-01 -7.2540e-02-7.0118e-02 -5.8567e-01 -5.5335e-01 … 3.0976e-01 -3.3483e-02 -1.3638e-01-8.8448e-02 -4.1210e-02 -8.5710e-02 … -6.0755e-01 -5.5320e-01 -4.0962e-01… ⋱ … -2.8095e-01 1.1081e-01 7.9184e-02 … -3.7869e-01 -1.7801e-01 -4.1227e-01-8.7498e-01 -8.1998e-01 -8.2176e-01 … -7.7750e-01 -8.6171e-01 -5.1366e-01-5.7234e-01 -2.5415e-01 -2.5126e-01 … -5.8857e-01 -4.8405e-01 -2.4303e-01
[torch.FloatTensor of size 3x300x90000]

让我们手动计算:(内核权重*输入)+偏差

0.30515 * 0.18577 + -0.33296 * 0.83658 + -0.41675 * 0.71619 + 0.13134 * 0.94578 + 0.41769 * 0.645 + 0.1725

结果是:

0.045796651399999944

哪个接近 qc[0][0][0]
注意:我刚刚展示了第一维度的第 0 个元素。(仅与数学相关的内容)
因此,这个动态图让我直观地了解了 Conv1d 在 PyTorch 中是如何按列操作的。
上面的代码很简单:

query_len = 5
lq = np.random.rand(3, query_len, WORD_DEPTH)
lq = Variable(torch.from_numpy(lq).float())
query_conv = nn.Conv1d(WORD_DEPTH, K, FILTER_LENGTH)
# print(lq)
# print (query_conv.weight)
# print (query_conv.bias)
qc = query_conv(lq)
# print (qc)

3.在获得查询、pos 和否定文档的所有向量之后。我们必须计算余弦相似度,在 Keras 中你必须为它创建一个新层。在 PyTorch:

dots = [q_s.dot(pos_s)]
dots = dots + [q_s.dot(neg_s) for neg_s in neg_ss]

变得如此简单:)

4.现在dots是一个列表,要把它转换成 PyTorch 变量,我们只需做:

dots = torch.stack(dots)

PS:这是我在 PyTorch 中的第一个实现,如果代码中有任何问题或者你不明白的地方,请联系我。
我的 twitter 句柄是nishan tiamgithub 句柄是 nishnik 。

Pytorch:如何以及何时使用模块、顺序、模块列表和模块指令

原文:https://towardsdatascience.com/pytorch-how-and-when-to-use-module-sequential-modulelist-and-moduledict-7a54597b5f17?source=collection_archive---------3-----------------------

Photo by Markus Spiske on Unsplash

嘿,我在LinkedIn过来打个招呼👋

在 Pytorch 1.7 更新

你可以在这里找到代码

Pytorch 是一个开源的深度学习框架,提供了一种创建 ML 模型的智能方式。即使文档做得很好,我仍然发现大多数人仍然能够写出糟糕的、没有条理的 PyTorch 代码。

今天我们来看看 PyTorch 的三个主要构建模块是如何使用的:Module, Sequential and ModuleList。我们将从一个例子开始,并不断改进。

这四个类都包含在torch.nn

模块:主要构建模块

模块是主要的构建模块,它定义了所有神经网络的基类,您必须对其进行子类化。

让我们创建一个经典的 CNN 分类器作为示例:

MyCNNClassifier( (conv1): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (bn1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (bn2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (fc1): Linear(in_features=25088, out_features=1024, bias=True) (fc2): Linear(in_features=1024, out_features=10, bias=True) )

这是一个非常简单的分类器,编码部分使用两层 3x3 convs + batchnorm + relu,解码部分使用两个线性层。如果您不熟悉 PyTorch,您可能以前见过这种类型的编码,但是有两个问题。

如果我们想增加一层,我们必须再次在__init__forward函数中写很多代码。此外,如果我们有一些想要在另一个模型中使用的公共块,例如 3x3 conv + batchnorm + relu,我们必须重新编写它。

连续:堆叠和合并层

顺序是模块的容器,可以堆叠在一起,同时运行。

你可以注意到我们已经把所有东西都储存到self里了。我们可以使用Sequential来改进我们的代码。

MyCNNClassifier( (conv_block1): Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) (conv_block2): Sequential( (0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) (decoder): Sequential( (0): Linear(in_features=25088, out_features=1024, bias=True) (1): Sigmoid() (2): Linear(in_features=1024, out_features=10, bias=True) ) )

好多了 uhu?

你有没有注意到conv_block1conv_block2看起来几乎一样?我们可以创建一个重述nn.Sequential的函数来简化代码!

然后我们可以在模块中调用这个函数

MyCNNClassifier( (conv_block1): Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) (conv_block2): Sequential( (0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) (decoder): Sequential( (0): Linear(in_features=25088, out_features=1024, bias=True) (1): Sigmoid() (2): Linear(in_features=1024, out_features=10, bias=True) ) )

更干净!还是conv_block1conv_block2差不多!我们可以用nn.Sequential合并它们

MyCNNClassifier( (encoder): Sequential( (0): Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) (1): Sequential( (0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) ) (decoder): Sequential( (0): Linear(in_features=25088, out_features=1024, bias=True) (1): Sigmoid() (2): Linear(in_features=1024, out_features=10, bias=True) ) )

self.encoder现占据展位conv_block。我们已经为我们的模型解耦了逻辑,使它更容易阅读和重用。我们的conv_block功能可以导入到另一个模型中使用。

动态连续:一次创建多个层

如果我们可以在self.encoder中添加一个新的层,硬编码会不方便:

如果我们可以将大小定义为一个数组并自动创建所有的层,而不需要写入每一层,这是不是很好?幸运的是,我们可以创建一个数组并将其传递给Sequential

MyCNNClassifier( (encoder): Sequential( (0): Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) (1): Sequential( (0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) ) (decoder): Sequential( (0): Linear(in_features=25088, out_features=1024, bias=True) (1): Sigmoid() (2): Linear(in_features=1024, out_features=10, bias=True) ) )

我们来分解一下。我们创建了一个数组self.enc_sizes来保存编码器的大小。然后我们通过迭代大小创建一个数组conv_blocks。因为我们必须给 booth 一个尺寸,并给每一层一个特大号,所以我们通过将数组移动一位来实现数组本身。

为了清楚起见,看一下下面的例子:

1 32 32 64

然后,由于Sequential不接受列表,我们通过使用*操作符来分解它。

Tada!现在,如果我们只想添加一个尺寸,我们可以很容易地在列表中添加一个新的数字。将大小作为参数是一种常见的做法。

MyCNNClassifier( (encoder): Sequential( (0): Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) (1): Sequential( (0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) (2): Sequential( (0): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) ) (decoder): Sequential( (0): Linear(in_features=25088, out_features=1024, bias=True) (1): Sigmoid() (2): Linear(in_features=1024, out_features=10, bias=True) ) )

我们可以对解码器部分做同样的事情

MyCNNClassifier( (encoder): Sequential( (0): Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) (1): Sequential( (0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) ) (decoder): Sequential( (0): Sequential( (0): Linear(in_features=25088, out_features=1024, bias=True) (1): Sigmoid() ) (1): Sequential( (0): Linear(in_features=1024, out_features=512, bias=True) (1): Sigmoid() ) ) (last): Linear(in_features=512, out_features=10, bias=True) )

我们遵循相同的模式,我们为解码部分创建一个新的块,linear + sigmoid,并传递一个包含大小的数组。我们必须添加一个self.last,因为我们不想激活输出

现在,我们甚至可以将我们的模型一分为二!编码器+解码器

MyCNNClassifier( (encoder): MyEncoder( (conv_blokcs): Sequential( (0): Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) (1): Sequential( (0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() ) ) ) (decoder): MyDecoder( (dec_blocks): Sequential( (0): Sequential( (0): Linear(in_features=1024, out_features=512, bias=True) (1): Sigmoid() ) ) (last): Linear(in_features=512, out_features=10, bias=True) ) )

注意MyEncoderMyDecoder也可以是返回nn.Sequential的函数。我更喜欢对模型使用第一种模式,对构建模块使用第二种模式。

通过将我们的模块分成子模块,共享代码、调试代码、T23 测试代码变得更加容易。

ModuleList:当我们需要迭代时

ModuleList允许您将Module存储为列表。当你需要遍历层并存储/使用一些信息时,比如在 U-net 中,它会很有用。

Sequential之间的主要区别是ModuleList没有forward方法,所以内层没有连接。假设我们需要解码器中每个层的每个输出,我们可以通过以下方式存储它:

torch.Size([4, 16]) torch.Size([4, 32]) [None, None]

ModuleDict:当我们需要选择时

如果我们想在我们的conv_block中切换到LearkyRelu呢?我们可以使用ModuleDict创建一个Module的字典,并在需要时动态切换Module

Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): LeakyReLU(negative_slope=0.01) ) Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU() )

最终实施

让我们把一切都结束吧!

MyCNNClassifier( (encoder): MyEncoder( (conv_blokcs): Sequential( (0): Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): LeakyReLU(negative_slope=0.01) ) (1): Sequential( (0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): LeakyReLU(negative_slope=0.01) ) ) ) (decoder): MyDecoder( (dec_blocks): Sequential( (0): Sequential( (0): Linear(in_features=1024, out_features=512, bias=True) (1): Sigmoid() ) ) (last): Linear(in_features=512, out_features=10, bias=True) ) )

结论

你可以在这里找到代码

综上所述。

  • 当你有一个由多个小块组成大块时,使用Module
  • 当你想从层中创建一个小块时,使用Sequential
  • 当你需要迭代一些层或构建块并做一些事情时,使用ModuleList
  • 当需要参数化模型的某些模块时,例如激活功能,使用ModuleDict

那都是乡亲们!

感谢您的阅读

原载于gist.github.com

Pytorch 实现实时风格转换的感知损失

原文:https://towardsdatascience.com/pytorch-implementation-of-perceptual-losses-for-real-time-style-transfer-8d608e2e9902?source=collection_archive---------2-----------------------

在这篇文章中,我将简要回顾我在 Pytorch 中编写和训练实时风格转换模型的经历。这项工作在很大程度上基于 Abhishek Kadian 的实现,,它工作得非常好。我做了一些修改,既是为了好玩,也是为了更熟悉 Pytorch。

该模型使用中描述的方法进行实时风格转换和超分辨率以及实例归一化。(未实现超分辨率)

我在实现中添加了三个主要部分:

  1. 使用官方预培训的 VGG 模型
  2. 在培训期间输出中间结果
  3. 添加总变差正则化如文中所述

使用官方预先训练的 VGG 模型

Model structure from the paper

首先,我们需要快速浏览一下模型结构。本文的主要贡献是提出将生成的图像前馈到预训练的图像分类模型,并从一些中间层提取输出来计算损失,这将产生类似于 Gatys 等人的的结果,但具有明显更少的计算资源。因此,该结构的第一部分是一个“图像变换网络”,它从输入图像生成新的图像。而第二部分简单来说就是一个“损耗网络”,也就是前馈部分。损失网络的权重是固定的,在训练过程中不会更新。

Abhishek 的实现使用传统的 VGG 模型,具有 BGR 信道顺序和[-103.939,-116.779,-123.680]到中心信道的偏移(这似乎也是该论文所使用的)。【pytorch 官方预训车型使用统一格式:

所有预训练模型都期望输入图像以相同的方式归一化,即形状为(3 x H x W)的 3 通道 RGB 图像的小批量,其中 H 和 W 预计至少为 224。必须将图像加载到[0,1]的范围内,然后使用mean = [0.485, 0.456, 0.406]std = [0.229, 0.224, 0.225]进行归一化

下面是从官方预训练模型中提取输出的代码:

**LossOutput = namedtuple("LossOutput", ["relu1_2", "relu2_2", "relu3_3", "relu4_3"])
# [https://discuss.pytorch.org/t/how-to-extract-features-of-an-image-from-a-trained-model/119/3](https://discuss.pytorch.org/t/how-to-extract-features-of-an-image-from-a-trained-model/119/3)
class LossNetwork(torch.nn.Module):def __init__(self, vgg_model):super(LossNetwork, self).__init__()self.vgg_layers = vgg_model.featuresself.layer_name_mapping = {'3': "relu1_2",'8': "relu2_2",'15': "relu3_3",'22': "relu4_3"}def forward(self, x):output = {}for name, module in self.vgg_layers._modules.items():x = module(x)if name in self.layer_name_mapping:output[self.layer_name_mapping[name]] = xreturn LossOutput(**output)**

启动:

**vgg_model = vgg.vgg16(pretrained=True)
if torch.cuda.is_available():vgg_model.cuda()
loss_network = LossNetwork(vgg_model)
loss_network.eval()**

除非明确指定,否则在 VGG 模型中没有批处理规范化。因此,激活值与之前的实现相比有很大不同。一般来说,你需要按比例增加样式损失(gram 矩阵),因为大多数激活小于 1,采用点积会使它更小。

在培训期间输出中间结果

Epoch 2, 75200th training sample

这在根据风格权重比例调整内容权重时很有帮助。您可以在训练过程中停止训练并重新调整参数,而不必等待 4 个小时才能完成训练。

添加总变差正则化如文中所述

论文在实验部分提到了这一点,但似乎 Abhishek 并没有实现:

输出图像用总变分正则化进行正则化,强度在 1 × 10e-6 和 1 ×10e-4 之间,通过每个样式目标的交叉验证进行选择。

The total variation norm formula for 2D signal images from Wikipedia

这很容易实现:

**reg_loss = REGULARIZATION * (torch.sum(torch.abs(y[:, :, :, :-1] - y[:, :, :, 1:])) + torch.sum(torch.abs(y[:, :, :-1, :] - y[:, :, 1:, :]))
)**

Pytorch 亲笔签名将为您处理反向传播。在实践中,我还没有发现如何调整正则化权重。到目前为止,我使用的权重似乎对输出图像没有太大影响。

培训结果

该模型使用 Microsoft COCO 数据集进行训练。图像的大小被调整为 256×256,网络被训练大约 2 个时期,批次大小为 4(与纸张相同)。使用 GTX1070 的训练时间约为 4 到 4.5 小时,与论文报道的时间相当。根据我粗略的实验,大量的计算时间被用于标准化输入图像。如果我们使用原始的 VGG 模型(未测试),训练可能会更快。在一些手动调整之后,内容权重与样式的比率通常被设置为 1 : 10e3 ~ 10e5。

An example model (waterfall) (pardon my poor GIMP skill…)

因为网络是完全卷积的,你可以在测试时间向网络提供比 256 x 256 更大或更小的图像。我写了一些脚本来转换动画 gif 和视频,使用 scikit-video 和 ffmpeg 来取乐:

Some additional style images used

Mosaic-styled cat typing

原视频鸣谢:背包环游新西兰。处理速度在每秒 4 帧左右。我没有调准帧率,所以下面几个视频的时间都比原来慢。

Mosaic style

Candy Style

经验教训

  1. 记住将输出 numpy 数组裁剪到[0,255]范围,并将其转换为 uint8。否则 matplot.pyplot.imshow 会显示奇怪的结果。花了相当多的时间在错误的方向上调试,认为模型训练代码有一些严重的错误。
  2. 记得使用 model.train() 和 model.eval()。它仅对包含丢弃或批量规范化图层的模型有效,但这是一个需要保持的好习惯。如果你来自喀拉斯,尤其容易忘记。

可能的改进和未来的工作

  1. 有时网络会在开放区域生成一些奇怪的补丁。还不知道是哪里来的,怎么修。
  2. 对于不同风格的图像,为 relu1_2、relu2_2、relu3_3、relu4_3 输出分配不同的权重可能会产生更好的结果。
  3. 尝试使用不同的预训练网络作为损耗网络。
  4. 也尝试实现超分辨率
  5. 比较来自循环的结果。我试过 CycleGAN,但训练时间太长,我当时失去了耐心。应该稍后再试。
  6. 生成视频时,调整连续帧之间的变化。这应该有助于减少播放过程中的闪烁。我听说有人使用这种技术,但还不知道如何实际操作。

A sample of the weird patches

感谢阅读!

代码位于本 Github repo 的。由于这基本上是一个个人有趣的项目,文档是不存在的,代码的主要部分驻留在两个 Jupyter 笔记本中: style-transfer.ipynb 和 Video.ipynb 。很抱歉。

(2011/11/30 更新:修复了上述笔记本的链接。与此同时,这里有更新版本的笔记本:01-image-style-transfer . ipynb和 03-Video-Creation.ipynb 。)

PyTorch 教程精华

原文:https://towardsdatascience.com/pytorch-tutorial-distilled-95ce8781a89c?source=collection_archive---------2-----------------------

从 TensorFlow 迁移到 PyTorch

当我刚开始研究 PyTorch 时,几天后我就放弃了。与 TensorFlow 相比,我很难理解这个框架的核心概念。这就是为什么我把它放在我的“知识书架”上,然后忘记了它。但是不久前,PyTorch 的新版本发布了。所以我决定再给它一次机会。过了一段时间,我明白了这个框架真的很容易使用,它让我很高兴用 PyTorch 编码。在这篇文章中,我会试着解释清楚它的核心概念,这样你会有动力至少现在就试一试,而不是在几年或更久之后。我们将涵盖一些基本原则和一些先进的东西,如学习率调度,自定义层等。

资源

首先,你应该知道 PyTorch 的文档和教程是分开存放的。有时,由于快速的开发和版本变化,他们可能不会见面。所以填免费调查源代码。它非常清晰明了。最好提一下,有很棒的 PyTorch 论坛,在那里你可以问任何合适的问题,你会很快得到答案。对于 PyTorch 用户来说,这个地方似乎比 StackOverflow 更受欢迎。

PyTorch as NumPy

所以让我们深入 PyTorch 本身。PyTorch 的主要构件是张量。真的,它们和 NumPy 的很像。Tensors 支持很多相同的 API,所以有时你可以使用 PyTorch 作为 NumPy 的替代。你可能会问这是什么原因。主要目标是 PyTorch 可以利用 GPU,以便您可以将数据预处理或任何其他计算密集型工作转移到机器学习领域。很容易将张量从 NumPy 转换成 PyTorch,反之亦然。让我们检查一些代码示例:

从张量到变量

张量是 PyTorch 中令人敬畏的一部分。但主要我们想要的是建立一些神经网络。什么是反向传播?当然我们可以手动实现,但是这是什么原因呢?谢天谢地,自动微分存在。为了支持它,PyTorch 为你提供了变量。变量是张量之上的包装器。有了它们,我们可以建立我们的计算图,并在以后自动计算梯度。每个变量实例都有两个属性:.data包含初始张量本身,.grad包含相应张量的梯度。

您可能会注意到,我们已经手动计算并应用了我们的梯度。太乏味了。我们有优化器吗?当然啦!

现在我们所有的变量都会自动更新。但是你应该从上一个片段中得到的要点是:在计算新的梯度之前,我们仍然应该手动置零梯度。这是 PyTorch 的核心概念之一。有时,我们为什么要这样做可能不是很明显,但另一方面,我们可以完全控制我们的渐变,何时以及如何应用它们。

静态与动态计算图

PyTorch 和 TensorFlow 的下一个主要区别是它们的图形表示方法。Tensorflow 使用静态图,这意味着我们定义它一次,然后一次又一次地执行那个图。在 PyTorch 中,每次向前传递都会定义一个新的计算图。一开始,这些方法之间的区别并不是很大。但是当你想调试你的代码或者定义一些条件语句时,动态图就变得很少了。您可以直接使用您喜欢的调试器!比较 while 循环语句的下两个定义 TensorFlow 中的第一个和 PyTorch 中的第二个:

在我看来,第二个解决办法比第一个容易得多。你对此有什么看法?

模型定义

好了,现在我们看到在 PyTorch 中构建一些 if/else/while 复杂语句很容易。但是让我们回到通常的模型。该框架提供了非常类似于 Keras 的现成层构造器:

nn包定义了一组模块,大致相当于神经网络层。模块接收输入变量并计算输出变量,但也可以保存内部状态,例如包含可学习参数的变量。nn包还定义了一组在训练神经网络时常用的有用的损失函数。

此外,如果我们想构建更复杂的模型,我们可以子类化提供的nn.Module类。当然,这两种方法可以混合使用。

__init__方法中,我们应该定义所有将在以后使用的层。在forward方法中,我们应该提出如何使用已经定义的层的步骤。像往常一样,向后传球将被自动计算。

自定义层

但是如果我们想定义一些带有非标准 backprop 的定制模型呢?这里有一个例子——XNOR 网络公司:

我不会深究细节,更多关于这种类型的网络,你可以在初始论文中读到。与我们的问题相关的是,反向传播应该只应用于小于 1 和大于-1 的权重。在 PyTorch 中,它可以很容易地实现:

正如你所看到的,我们应该只定义两个方法:一个用于向前传递,一个用于向后传递。如果我们需要从正向传递中访问一些变量,我们可以将它们存储在ctx变量中。注意:在以前的 API 中,向前/向后方法不是静态的,我们将所需的变量存储为self.save_for_backward(input),并以input, _ = self.saved_tensors的形式访问它们。

使用 CUDA 训练模型

我们之前讨论过如何将一个张量传递给 CUDA。但是如果要传递整个模型,从模型本身调用.cuda()方法就可以了,把每个输入变量包装到.cuda()就够了。在所有的计算之后,我们应该用.cpu()方法得到结果。

此外,PyTorch 在源代码中支持直接设备分配:

因为有时我们希望在 CPU 和 GPU 上运行相同的模型,而不修改代码,所以我提出了某种包装器:

重量初始化

在张量流中,权重初始化主要在张量声明期间进行。PyTorch 提供了另一种方法——首先,应该声明张量,下一步应该改变张量的权重。权重可以初始化为对张量属性的直接访问,调用torch.nn.init包中的一堆方法。这个决定可能不是很直接,但当您想要用相同的初始化来初始化某个类型的所有层时,它会变得很有用。

从反向中排除子图

有时,当您想要重新训练模型的某些层或为生产模式做准备时,您可以禁用某些层的亲笔签名机制,这非常有用。为此, PyTorch 提供了两个标志 : requires_gradvolatile。第一个将禁用当前层的渐变,但子节点仍然可以计算一些。第二个将禁用当前层和所有子节点的自动签名。

培训过程

PyTorch 中还存在其他一些附加功能。例如,你可以使用学习率调度器,它将根据一些规则调整你的学习率。或者,您可以启用/禁用具有单个训练标志的批量定额层和辍学。如果你想很容易改变随机种子分别为 CPU 和 GPU。

此外,您可以打印关于您的模型的信息,或者用几行代码保存/加载它。如果你的模型是用 OrderedDict 或基于类的模型来初始化的,那么字符串表示将包含层的名称。

根据 PyTorch 文档,使用state_dict()方法的保存模型更可取。

记录

记录训练过程是非常重要的一部分。不幸的是,PyTorch 没有任何类似 tensorboard 的工具。因此,您可以使用带有 Python 日志模块的普通文本日志,或者尝试一些第三方库:

  • 用于实验的简单记录器
  • tensor board 的语言无关接口
  • 在不接触张量流的情况下记录张量板事件
  • py torch 的张量板
  • 脸书可视化智慧图书馆

数据处理

您可能还记得 TensorFlow 中提出的数据加载器,甚至试图实现其中的一些。对我来说,花了大约 4 个小时或更多的时间来了解所有管道应该如何工作。

Image source: TensorFlow docs

最初,我想在这里添加一些代码,但我认为这样的 gif 将足以解释所有事情如何发生的基本想法。

PyTorch 开发者决定不重新发明轮子。他们只是使用多重处理。要创建您自己的定制数据加载器,从torch.utils.data.Dataset继承您的类并更改一些方法就足够了:

你应该知道的两件事。首先,图像尺寸不同于张量流。它们是[batch _ size x channels x height x width]。但是这种转换可以通过预处理步骤torchvision.transforms.ToTensor()在没有交互的情况下完成。在转换包中也有很多有用的实用程序。

第二件重要的事情是你可以在 GPU 上使用固定内存。为此,您只需要为一个cuda()调用添加一个额外的标志async=True,并从带有标志pin_memory=True的数据加载器中获取固定批次。关于此功能的更多信息在这里讨论。

最终架构概述

现在你知道了模型、优化器和许多其他东西。什么才是把它们全部合并的正确方法?我建议将您的模型和所有包装器拆分成这样的构件:

为了清楚起见,这里有一些伪代码:

结论

我希望这篇文章能让你理解 PyTorch 的要点:

  • 它可以作为 Numpy 的替代产品
  • 这对于原型制作来说真的很快
  • 调试和使用条件流很容易
  • 有许多现成的好工具

PyTorch 是一个快速发展的框架,有一个很棒的社区。我认为今天是尝试的最佳时机!

PyTorch 与 TensorFlow: 1 个月总结

原文:https://towardsdatascience.com/pytorch-vs-tensorflow-1-month-summary-35d138590f9?source=collection_archive---------0-----------------------

py torch 与 TensorFlow 合作一个月后的对比。

在我深度学习工作的大部分时间里,我一直是 TensorFlow 的用户。然而,当我加入英伟达时,我们决定改用 py torch——只是作为一种测试。以上是我对它的体验。

装置

安装非常简单明了。PyTorch 可以通过 PIP 安装,也可以从源代码构建。PyTorch 还提供 Docker 图像,可以用作您自己项目的基础图像。

PyTorch 不像 TensorFlow 那样有指定的 CPU 和 GPU 版本。虽然这使安装更容易,但如果您想同时支持 CPU 和 GPU 的使用,它会生成更多的代码。

值得注意的是 PyTorch 还没有提供正式的 windows 发行版。有到 windows 的非官方端口,但是没有 PyTorch 的支持。

使用

PyTorch 提供了一个非常 Pythonic 化的 API。这与 TensorFlow 有很大不同,在 tensor flow 中,您应该定义所有的张量和图形,然后在一个会话中运行它。

在我看来,这会产生更多但更干净的代码。PyTorch 图必须在从 PyTorch nn.Module类继承的类中定义。当图形运行时,调用一个forward()函数。使用这种“约定优于配置”的方法,图的位置总是已知的,并且变量不会在代码的其余部分全部定义。

这种“新”的方法需要一些时间来适应,但我认为如果你以前在深度学习之外使用过 Python,这是非常直观的。

根据一些评论,PyTorch 还在许多模型上显示出比 TensorFlow 更好的性能。

证明文件

文件大部分是完整的。我总能找到函数或模块的定义。与 TensorFlow 相反,在 tensor flow 中,所有函数都只有一个页面,PyTorch 每个模块只使用一个页面。如果你来自谷歌,寻找一个功能,这就有点困难了。

社区

显然 PyTorch 的社区没有 TensorFlow 的社区大。然而,许多人喜欢在空闲时间使用 PyTorch,即使他们在工作中使用 TensorFlow。我认为 PyTorch 一退出 Beta,这种情况就会改变。

目前来看,在 PyTorch 中找到精通的人还是有点困难。

这个社区非常大,官方论坛上的问题通常都能很快得到答案,因此很多伟大的神经网络实现的例子都被翻译成 PyTorch。

工具和助手

尽管 PyTorch 提供了相当多的工具,但是缺少一些非常有用的工具。缺少的最有用的工具之一是 TensorFlow 的 TensorBoard。这使得虚拟化有点困难。

还有一些很常用的帮手不见了。这比 TensorFlow 需要更多的自写代码。

结论

PyTorch 是 TensorFlow 的绝佳替代品。由于 PyTorch 仍处于测试阶段,我希望在可用性、文档和性能方面有更多的变化和改进。

PyTorch 非常 pythonic 化,使用起来感觉很舒服。它有一个很好的社区和文档。据说比 TensorFlow 还快一点。

然而,与 TensorFlow 相比,这个社区仍然很小,并且缺少一些有用的工具,如 TensorBoard。

PyTorch 与 TensorFlow —发现差异

原文:https://towardsdatascience.com/pytorch-vs-tensorflow-spotting-the-difference-25c75777377b?source=collection_archive---------0-----------------------

在这篇文章中,我想探讨两个流行的深度学习框架:PyTorch 和 TensorFlow 之间的一些关键异同。为什么是这两个而不是其他的?有许多深度学习框架,其中许多是可行的工具,我选择这两个只是因为我对具体比较它们感兴趣。

起源

TensorFlow 由 Google Brain 开发,并在 Google 积极用于研究和生产需求。它的闭源前身叫做 DistBelief。

PyTorch 是在脸书开发和使用的基于 lua 的 Torch 框架的表亲。然而,PyTorch 并不是一套简单的支持流行语言的包装器,它被重新编写和修改以使速度更快,感觉更自然。

比较两个框架的最好方法是在两个框架中都编写一些代码。我已经为这个帖子写了一个配套的 jupyter 笔记本,你可以在这里得到它。所有代码都将在帖子中提供。

首先,让我们为两个框架中的以下函数编写一个简单的近似器:

我们将尝试找到未知参数φ给定数据 x 和函数值 f(x) 。是的,使用随机梯度下降是一种矫枉过正,解析解可能很容易找到,但这个问题将作为一个简单的例子很好地服务于我们的目的。

我们将首先用 PyTorch 解决这个问题:

如果你在深度学习框架方面有一些经验,你可能已经注意到我们正在手工实现梯度下降。不太方便吧?令人高兴的是,PyTorch 拥有optimize模块,其中包含了诸如 RMSProp 或 Adam 等流行优化算法的实现。我们将带着动力使用新加坡元

Loss function and exponent plots for PyTorch

正如你所看到的,我们很快从训练数据中推断出真实指数。现在让我们继续张量流:

Loss function and exponent plots for TensorFlow

如您所见,TensorFlow 中的实现也可以工作(令人惊讶的是🙃).它花费了更多的迭代来恢复指数,但我确信原因是我没有充分利用 optimiser 的参数来达到可比的结果。

现在我们准备探索一些不同之处。

差异#0 —采用

目前,TensorFlow 被许多研究人员和行业专业人士视为随身工具。这个框架有很好的文档记录,如果文档还不够,互联网上有很多写得非常好的教程。你可以在 github 上找到数百个已经实现和训练过的模型,从这里开始。

PyTorch 与其竞争对手相比相对较新(仍处于测试阶段),但它的发展势头很快。文档和官方教程也不错。PyTorch 还包括几个超级易用的流行计算机视觉架构的实现。

区别#1 —动态与静态图形定义

这两个框架都在张量上操作,并将任何模型视为有向无环图(DAG ),但是它们在如何定义它们上有很大的不同。

TensorFlow 遵循“数据即代码,代码即数据”习语。在 TensorFlow 中,您可以在模型运行之前静态定义图形。与外部世界的所有通信都是通过tf.Session对象和tf.Placeholder进行的,它们是在运行时将被外部数据替代的张量。

在 PyTorch 中,事情更加命令化和动态化:您可以随时定义、更改和执行节点,没有特殊的会话接口或占位符。总的来说,该框架与 Python 语言集成得更紧密,大多数时候感觉更原生。当你在 TensorFlow 中写作时,有时你会觉得你的模型在一堵砖墙后面,有几个小孔可以沟通。无论如何,这听起来或多或少还是一个品味问题。

然而,这些方法不仅在软件工程的角度上有所不同:有几种动态神经网络体系结构可以从动态方法中受益。回想一下 RNNs:对于静态图,输入序列长度将保持不变。这意味着,如果你为英语句子开发一个情感分析模型,你必须将句子长度固定到某个最大值,并用零填充所有较小的序列。不太方便吧。在递归 RNNs 和树形 RNNs 领域,你会遇到更多的问题。目前 Tensorflow 通过 Tensorflow Fold 对动态输入的支持有限。PyTorch 默认拥有它。

区别#2 —调试

由于 PyTorch 中的计算图是在运行时定义的,所以您可以使用我们最喜欢的 Python 调试工具,如 pdb、ipdb、PyCharm 调试器或旧的可信打印语句。

TensorFlow 就不是这样。您可以选择使用名为 tfdbg 的特殊工具,该工具允许在运行时计算张量流表达式,并浏览会话范围内的所有张量和操作。当然,你不能用它来调试任何 python 代码,所以有必要单独使用 pdb。

差异#3 —可视化

Tensorboard 在可视化方面非常棒😎。这个工具是 TensorFlow 自带的,对于调试和比较不同的训练运行非常有用。例如,假设您训练了一个模型,然后调整了一些超参数并再次训练它。两次运行可以同时显示在 Tensorboard 上,以指示可能的差异。Tensorboard 可以:

  • 显示模型图
  • 绘制标量变量
  • 可视化分布和直方图
  • 可视化图像
  • 可视化嵌入
  • 播放音频

Tensorboard 可以显示各种摘要,这些摘要可以通过tf.summary模块收集。我们将为我们的玩具指数示例定义汇总操作,并使用tf.summary.FileWriter将它们保存到磁盘。

启动 Tensorboard 执行tensorboard --logdir=./tensorboard。这个工具在云实例上使用非常方便,因为它是一个 webapp。

PyTorch 这边的 Tensorboard 竞争对手是 visdom 。它功能不全,但使用起来更方便。另外,与 Tensorboard 的集成确实存在。此外,您可以自由使用标准绘图工具— matplotlib 和 seaborn 。

差异#4 —部署

如果我们开始谈论部署,TensorFlow 现在显然是赢家:它有 TensorFlow 服务,这是一个在专用 gRPC 服务器上部署您的模型的框架。也支持移动。

当我们切换回 PyTorch 时,我们可能会使用 Flask 或另一种替代方式在模型之上编写一个 REST API。如果 gRPC 不适合您的用例,这也可以用张量流模型来完成。然而,如果性能是一个问题,TensorFlow 服务可能是一个更好的选择。

Tensorflow 还支持 PyTorch 目前缺乏的分布式训练。

差异#5 —数据并行

PyTorch 区别于 TensorFlow 的最大特征之一是声明式数据并行性:您可以使用torch.nn.DataParallel包装任何模块,它将(几乎神奇地)在批处理维度上并行化。通过这种方式,您几乎可以毫不费力地利用多个 GPU。

另一方面,TensorFlow 允许您微调要在特定设备上运行的每个操作。尽管如此,定义并行性需要更多的手动操作,并且需要仔细思考。考虑在 TensorFlow 中实现类似于DataParallel的代码:

def make_parallel(fn, num_gpus, **kwargs):in_splits = {}for k, v in kwargs.items():in_splits[k] = tf.split(v, num_gpus)out_split = []for i in range(num_gpus):with tf.device(tf.DeviceSpec(device_type="GPU", device_index=i)):with tf.variable_scope(tf.get_variable_scope(), reuse=tf.AUTO_REUSE):out_split.append(fn(**{k : v[i] for k, v in in_splits.items()}))return tf.concat(out_split, axis=0)def model(a, b):return a + bc = make_parallel(model, 2, a=a, b=b)

也就是说,当使用 TensorFlow 时,你可以实现你在 PyTorch 中可以做的一切,但需要更多的努力(你有更多的控制权作为奖励)。

同样值得注意的是,这两个框架都支持分布式执行,并为定义集群提供了高级接口。

区别# 6——框架还是库

让我们为手写数字建立一个 CNN 分类器。现在 PyTorch 将真正开始看起来像一个框架。回想一下,编程框架为我们提供了某些领域中有用的抽象,以及使用它们来解决具体问题的便捷方式。这就是框架和库的本质区别。

这里我们介绍datasets模块,它包含用于测试深度学习架构的流行数据集的包装器。另外nn.Module用于构建一个定制的卷积神经网络分类器。nn.Module是 PyTorch 给我们创建复杂深度学习架构的一个积木。在torch.nn包中有大量现成的模块,我们可以将其用作我们模型的基础。请注意 PyTorch 如何使用面向对象的方法来定义基本的构建模块,并在提供通过子类化来扩展功能的能力的同时,给我们一些“轨道”来继续前进。

下面是对稍加修改的版本 https://github . com/py torch/examples/blob/master/mnist/main . py:

普通 TensorFlow 感觉更像一个库,而不是一个框架:所有的操作都是非常低级的,即使你可能不想写,也需要编写大量的样板代码(让我们一次又一次地定义这些偏差和权重……)。

随着时间的推移,围绕 TensorFlow 出现了一整套高级包装器的生态系统。这些都旨在简化您使用库的方式。他们中的许多人目前位于tensorflow.contrib模块(这不被认为是一个稳定的 API),一些人开始迁移到主存储库(见tf.layers)。

所以,在如何使用 TensorFlow 以及什么样的框架最适合这个任务上,你有很大的自由度: TFLearn , tf.contrib.learn , Sonnet , Keras ,plain tf.layers等。老实说,Keras 值得另一篇文章,但目前不在这个比较的范围之内。

这里我们将使用tf.layerstf.contrib.learn来构建我们的 CNN 分类器。代码遵循TF . layers 官方教程:

因此,TensorFlow 和 PyTorch 都提供了有用的抽象来减少样板代码的数量并加速模型开发。它们之间的主要区别是 PyTorch 可能感觉更“pythonic 化”,并且具有面向对象的方法,而 TensorFlow 有几个选项供您选择。

我个人认为 PyTorch 更清晰,对开发者更友好。它的torch.nn.Module给了你以 OOP 方式定义可重用模块的能力,我发现这种方法非常灵活和强大。稍后你可以通过torch.nn.Sequential组成各种模块(你好,✋🏻).此外,所有内置模块都在一个功能表中,这非常方便。总的来说,API 的所有部分都配合得很好。

当然,你可以用普通的 TensorFlow 编写非常简洁的代码,但是在你得到它之前需要更多的技巧和反复试验。当使用 Keras 或 TFLearn 这样的高级框架时,至少要准备好失去 TensorFlow 提供的一些灵活性。

结论

TensorFlow 是一个非常强大和成熟的深度学习库,具有强大的可视化功能和几个用于高级模型开发的选项。它具有生产就绪型部署选项和对移动平台的支持。如果您满足以下条件,TensorFlow 是一个不错的选择:

  • 为生产开发模型
  • 开发需要在移动平台上部署的模型
  • 想要良好的社区支持和全面的文档
  • 想要各种形式的丰富学习资源(TensorFlow 有一整个 MOOC
  • 想要或需要使用 Tensorboard
  • 需要使用大规模分布式模型训练

PyTorch 仍然是一个发展势头迅猛的年轻框架。如果您符合以下条件,您可能会发现它非常适合:

  • 做研究或者你的生产非功能需求不是很苛刻
  • 想要更好的开发和调试体验
  • 万物蟒

如果你有时间,最好的建议是两者都试试,看看哪一个最适合你的需求。

如果你喜欢这篇文章,请留下一些👏。它让我知道我在帮忙。

PyTorch 1.0 笔记

PyTorch 1.0 即将发布。它引入了许多令人惊叹的特性,包括原生 C++ API、JIT 编译和 ONNX 集成。这意味着您将能够编写生产就绪的服务,并做 TensorFlow 服务所做的事情。这是 PyTorch 迈出的一大步,肯定会增强它作为研究和生产用途的全功能框架的地位。

联系我们

需要 TensorFlow 或 PyTorch 的帮助?请通过 datalab@cinimex.ru 联系我们

想要定期获得关于数据科学和创业的有趣资源吗?

跟我来🐦推特和📝中等。

Q-Bay:用模拟拍卖解释 Q-Learning

原文:https://towardsdatascience.com/q-bay-explaining-q-learning-with-simulated-auctions-f85bac990c60?source=collection_archive---------10-----------------------

强化学习是一个热门话题,近年来,DeepMind 的 AlphaGo 等复杂系统利用一种叫做深度 Q 学习的方法取得了引人注目的成功,但它们是如何工作的?本文解释了 Q-Learning(深度 Q-Learning 背后的强化学习方法)是如何工作的,首先看一个应用于一个简单得多的问题的例子,即地铁网络的一个小部分的导航,然后看一个稍微复杂一点的例子,即拍卖。

Our q-Bay agent

Q 学习背后的理念

在一个 Q-Learning 问题中,一个智能体试图学习一种导航其环境的最佳方式,通过估计在任何一点它可用的哪个即时动作最有可能导致最佳的长期结果,该结果由达到某个目标状态(或多个状态)所获得的奖励来定义。这可能是选择哪一步棋最有可能赢得围棋比赛,哪一次出价最有可能以好价钱赢得拍卖,或者在地铁系统中选择哪条路线,我将在这里更详细地解释 Q-learning 背后的直觉。

Q 学习代理的世界围绕着两个矩阵——R 矩阵和 Q 矩阵。R 矩阵表示代理将在其中操作的环境,从代理可能处于的状态、代理从每个状态可用的动作(通常被视为移动到其他状态)以及到达一个状态所收到的奖励来看。代理不知道整个 R 矩阵;它所能看到的是它能立即采取的行动。

R-matrix for navigation of a small section of the London Underground

上表是一个 R 矩阵,用于导航图中所示的一小部分伦敦地铁,目标是到达托特纳姆黑尔站。表中的每一行描述一个状态,每一列中的值代表代理移动到另一个状态所获得的奖励。例如,当在斯坦福德山时,经纪人可以留在斯坦福德山,或者搬到七姐妹。但是如果这是代理人能看到的全部,并且两个移动有相同的回报,代理人如何能算出哪个移动是最好的?这就是 Q 矩阵的用武之地。

Q 矩阵表示代理积累的关于其环境的知识。它与 R-矩阵的结构相同,但在开始时,它的所有值都是 0(因为它还没有学到任何东西)。它只知道,它希望获得最大回报。因此,代理开始探索它的世界,每次移动后,它都用它所学到的东西更新它的 Q 矩阵。这可以通过以下等式来实现:

简而言之,这意味着在每一步棋后,代理人都会更新它对刚才所做选择的价值的估计,基于它得到的回报,它对这一步棋的价值的现有估计,以及它对现在可用的这一步棋的价值的现有估计。

让我们看一下这个例子。由于代理正在探索,假设它随机选择了一个选项,这个随机选择是从斯坦福德山移动到七姐妹。现在,因为这一步的回报是 0,所有当前的 Q 值都是 0,没有新的知识来更新我们的 Q 矩阵,所以什么都没有改变。

现在经纪人面临四个选择:留在七姐妹,或者搬到托特纳姆黑尔,芬斯伯里公园,或者回到斯坦福山。同样,经纪人无法在这些选项中做出选择,所以只能随机选择,为了简单起见,我们会说是去托特纳姆黑尔。这一次,它确实得到了回报,所以这一步的 Q 值更新了 100 倍的学习率(我们假设α和γ都是 0.1)。

Q 矩阵现在看起来像这样:

因为代理已经达到目标,所以该集结束,并且代理被放置在随机站中以再次开始该过程。然而这一次,它有了一些知识。下一次它从斯坦福德山移动到七姐妹时,它将看到它的一个可用的下一个动作具有值,这将意味着状态/动作对值也得到更新,即使它没有得到任何奖励:

就最终目标而言,这一步是有价值的,因为它导致了另一步,而这一步会带来回报。

从这个简单的例子中,您可以看到,经过多次重复,达到目标所获得的奖励值是如何通过前面所有可能的选择进行反馈的,直到代理最终制定出从任何站点采取的最佳移动,以便尽快达到其目标。您可能还会看到,这将需要大量的重复,并且将问题扩大,即使是相对简单的任务,也会使涉及的矩阵非常大(伦敦网络上有 427 个车站,我们只研究了 6 个!).

回到本文开头提到的标题抓取 Deep-Q 系统,这些系统运行在所需矩阵的复杂性和大小使这种方法不切实际的环境中(例如,围棋有 10 种⁷⁰可能状态)。他们不是试图学习和记住每个可能的状态/动作对的值,而是使用神经网络来学习近似这些值(如果你想一想,这很像我们在遇到以前从未遇到过的情况时所做的)。然而,他们仍然致力于相同的基本原则,即从经验中学习,根据预期的长期回报来评估给定状态和行为的价值。

q 湾

我的理学硕士同学莎拉·斯科特和我在一个简单的拍卖游戏中实现了 Q-learning,首先是一个代理,然后是两个代理。拍卖和上述场景的第一个主要区别是时间依赖性。在地铁的例子中,没有时间限制——代理可以花它需要的时间来达到它的目标,直到它这样做,情节才结束。它也总是因为达到目标而获得相同的奖励,不管它在哪个时间段达到目标。在拍卖中,这显然是不同的——有预先确定的移动次数,只有在最后一段时间才会收到奖励。这将我们的两个矩阵的形状从二维变为三维,尽管在新的维度上的运动是预先确定的(因为时间总是增加 1)。

在这个游戏中,状态是代理的当前出价,动作是向新出价的移动。代理人开始时没有出价,每次都可以提高出价,保持不变,或者退出拍卖。代理在拍卖中具有该物品的预设价值,并且奖励是该价值与赢得拍卖时支付的价格之间的差(因此,无论出价如何,代理未赢得拍卖都获得 0,但是超额支付可以获得负奖励)。

代理人行为的一个关键因素,我上面没有提到,是探索政策。在每一步行动中,代理人都有一个选择,是应该遵循当前的估计以获得最大的回报(exploit),还是在不同的路线上冒险,这可能会导致一个未发现的路径,以获得更好的解决方案(explore)。如果代理人太热衷于利用,那么它很可能会选择它找到的第一条路径来获得积极的结果,这可能是好的,但不太可能是最佳的。如果它过于热衷于探索,它将无法实现其回报最大化的总体目标。

在探索和利用之间找到平衡对代理识别最优路径的速度有很大的影响,在我们的实验中,这可能比学习率或折扣因子更重要。实现这种行为的常用方法是使用衰减参数ε,它决定了代理在每次移动时探索的概率。在学习之初,代理什么都不知道,所以我们希望它多多探索。渐渐地,随着它的知识增加,我们希望它走向更贪婪的方法,在那里它经常利用,探索更少,所以我们需要 epsilon 随时间减少。我们使用两个衰减因子来控制这种变化。每次学习后,epsilon 更新如下:

其中,df1 是接近 1 的数字(例如,0.9999),这导致ε在每次转动时仅减小很小的量,df2 是更小的数字(例如,0.99),这导致ε减小得更快。

下面的两个图表显示了使用这些参数的两种不同设置训练单个代理的结果。

在这里,我们可以看到ε衰变得太快了。代理人找到了一种从每集获得 3 英镑奖励的方法,并很快停止了探索,尽管这不是最优策略,甚至不是代理人经历过的最佳奖励。

这一次,我们可以看到代理人花费了更长的时间来探索,并逐渐走向剥削(随着紫色线移动得更高),在 3000 多集后越过阈值( d )之前,并切换到完全剥削行为,这一次在每一集中都实现了最大奖励。

多智能体 Q-学习

虽然单个代理人的场景展示了一些有趣的行为,但最优解对大多数人来说可能是直观上显而易见的——在任何时候出价 1,然后坚持这个出价。在有多个代理的情况下,最佳方法并不那么明显,并且根据所遵循的策略而变化(例如,我是将其他代理视为竞争对手还是合作伙伴?).

为了让自己更进一步,并开始探索这些博弈论的思想,我们用两个代理实现了我们的拍卖,使用了三种不同的策略,这是由 Q 更新规则的变化引入的。为了简单起见(ish ),拍卖被限制在一个时间段内,每个代理遵循相同的策略,并对拍卖项目赋予相同的价值,因此两者的 R 矩阵是相同的。允许的最高出价是 4,项目的价值是 3,出价-1 表示从拍卖中退出。

增加玩家的数量会增加状态的数量(因此也会增加动作的数量),因为状态需要代表每个单独玩家的出价。这意味着,如果有 k 个可能的出价和 n 个参与者,那么现在就有个 k^n 个状态,这再次说明了场景中看似微小的变化会多么迅速地导致环境复杂性的大幅增加。

我们尝试在确定性的回合顺序和随机性的回合顺序之间进行切换,在确定性的回合顺序中,一个代理总是先移动,而在随机性的回合顺序中,代理仍然依次移动,但先移动的玩家在每集开始时确定。如果出现平局,任何一方都没有赢得奖励。

标准 Q 学习

在两个玩家都遵循与单人游戏相同的策略的情况下,双方都知道,无论谁先移动,都无法获得积极的奖励,因为第二个玩家总是可以出价高于他们或迫使平手,因此满足于不出价(这仍然比通过支付赔率赢得拍卖要好)。然后第二个玩家叫牌并得到奖励。

Bidding behaviour in the final 100 episodes

朋友-Q

Friend-Q 是对前面描述的 Q-Learning 规则的改编:

这意味着每个代理寻找具有最高估计值的一对动作(每个玩家一个)。实际上,它是假设另一个代理人会对它采取利他行为。与前一种情况一样,先行动的玩家学会出价 0,允许第二个玩家出价 1 并赢得最大可能的奖励。

Foe-Q

Foe-Q 是一个极小极大策略;假设其他代理人都在努力使其报酬最小化,代理人正在努力使其报酬最大化,如下式所示(从 0 号玩家的角度):

在这个场景中,我们的实现产生了一些有问题的结果。人们可能会认为,第一个行动的代理人将学会出价低于物品价值的最高价格,让对手选择要么出价高于物品,要么与物品的出价相当,从而导致任何一方都没有任何回报。虽然这种情况确实会发生,但我们的代理无法确定一种恒定的方法,即使在 Q 矩阵已经收敛之后,这表明我们的代码可能有问题,我们甚至可能已经处于这样一个点,即用某种形式的值近似函数(可以是神经网络,但也可以是更简单的东西,如线性回归)来替换我们的值矩阵。

包扎

除了我们在这里尝试的以外,还有许多可供研究的选项,例如:

  • 当代理对该项目有不同的价值时会发生什么?
  • 如果代理遵循不同的策略会发生什么?
  • 如果两个代理同时出价会发生什么?
  • 在多代理、多时间段场景中会发生什么?

…等等,但希望这篇文章已经让你很好地理解了这种流行的强化学习方法背后的思想,以及我们可以开始扩展它的一些方法,而不仅仅是最简单的例子。

所有的代码(大部分是莎拉写的!)可以在 GitHub 上获得(如果你能解决 Foe-Q 问题,欢迎拉请求!).它是用 python 写的,主要使用了 Numpy、Pandas 和 Matplotlib。感谢阅读,如果你喜欢,请留下一些掌声!

Q 学习和深度 Q 网络

原文:https://towardsdatascience.com/q-learning-and-deep-q-networks-436380e8396a?source=collection_archive---------14-----------------------

强化学习的旅程还在继续……是时候分析一下臭名昭著的 Q-learning 了,看看它是如何成为 AI 领域的新标准的(在神经网络的一点帮助下)。

重要的事情先来。在的上一篇帖子中,我们看到了强化学习背后的基本概念,我们使用代理、环境、状态(S)、动作(A)和奖励(R)来构建问题。我们讨论了如何将整个过程描述为马尔可夫决策过程,并引入了术语策略和值。最后,我们对基本方法进行了一个快速的高层次概述。

请记住,目标是找到最佳策略,而策略是状态和动作之间的映射。所以,我们需要找到当我们站在一个特定的状态下采取什么行动来最大化我们的预期回报。找到最优策略的一种方法是利用价值函数(一种无模型技术)。

在这里,我们将得到新的东西。事实上,现在有两种价值函数在使用。状态值函数 V(s)和动作值函数 Q(s,a)。

  • 状态价值函数:是根据政策从一个状态行动时达到的预期收益。
  • 动作价值函数:给定状态和动作的期望收益。

你可能会问有什么区别?第一个值是特定状态的值。第二个是该状态的值加上来自该状态的所有可能动作的值。

当我们有了动作值函数,即 Q 值,我们可以简单地从一个状态中选择执行具有最高值的动作。但是我们如何找到 Q 值呢?

什么是 Q 学习?

所以,我们将从试错中学习 Q 值?没错。我们初始化 Q,我们选择一个动作并执行它,我们通过测量回报来评估它,并相应地更新 Q。首先,随机性将是一个关键因素,但随着智能体探索环境,算法将为每个状态和动作找到最佳 Q 值。我们可以用数学来描述这个吗?

谢谢理查德 E. 贝尔曼。上述方程被称为贝尔曼方程,并在今天的研究中发挥了巨大作用。但是它说明了什么?

Q 值,也就是一个状态和动作的最大未来回报,是当前回报加上下一个状态的最大未来回报。如果你仔细想想,这很有道理。Gamma (γ)是一个介于[0,1]之间的数字,它用于随着时间的推移对奖励进行折现,假设开始时的行为比结束时的行为更重要(这一假设被许多现实生活中的用例所证实)。结果,我们可以迭代更新 Q 值

这里要理解的基本概念是,贝尔曼方程将状态彼此联系起来,因此,它将作用值函数联系起来。这有助于我们迭代环境并计算最佳值,从而为我们提供最佳策略。

最简单的形式是,Q 值是一个矩阵,状态是行,动作是列。我们随机初始化 Q 矩阵,智能体开始与环境互动,并测量每个动作的回报。然后,它计算观察到的 Q 值并更新矩阵。

探索与开发

如上所述,该算法是一种贪婪算法,因为它总是选择具有最佳值的动作。但如果某个行为产生非常大回报的概率非常小呢?代理永远不会到达那里。这是通过添加随机探索修复的。每隔一段时间,代理会执行一次随机移动,不考虑最优策略。但是因为我们希望算法在某个点上收敛,所以随着游戏的进行,我们降低了采取随机行动的概率。

为什么要深入?

q 学习好。没有人能否认这一点。但是它在大的状态空间中无效的事实仍然存在。想象一个有 1000 个状态,每个状态有 1000 个动作的游戏。我们需要一张包含一百万个单元格的表格。与国际象棋或围棋相比,这是一个非常小的状态空间。还有,Q 学习不能用于未知状态,因为它不能从以前的状态推断出新状态的 Q 值。

如果我们用机器学习模型来近似 Q 值呢。如果我们用神经网络来逼近它们呢?这个简单的想法(当然还有执行)是 DeepMind 以 5 亿美元从谷歌收购的原因。DeepMind 提出了一个名为 Deep Q Learner 的算法,并用它来玩 Atari 游戏,掌握得无懈可击。

在深度 Q 学习中,我们利用神经网络来逼近 Q 值函数。网络接收状态作为输入(无论是当前状态的帧还是单个值),并输出所有可能动作的 Q 值。最大的产出是我们下一步的行动。我们可以看到,我们并不局限于完全连接的神经网络,但我们可以使用卷积、递归和任何其他类型的模型来满足我们的需求。

我认为是时候在实践中使用所有这些东西,并教代理人玩山地车了。目标是让一辆汽车开上一座小山。这辆汽车的发动机不够强劲,不能一次爬完这座山。所以,成功的唯一方法就是来回开车造势。

我将解释更多关于深度 Q 网络和代码。首先,我们应该建立一个具有 3 个密集层的神经网络,我们将使用 Adam 优化来训练它。

关键点:

  • 代理拥有一个包含所有过去经历的记忆缓冲区。
  • 他的下一步行动由网络的最大输出(Q 值)决定。
  • 损失函数是预测 Q 值和目标 Q 值的均方误差。
  • 根据贝尔曼方程,我们知道目标是 R + g*max(Q)。
  • 目标值和预测值之间的差异称为时间差异误差(TD 误差)

在我们训练我们的 DQN 之前,我们需要解决一个对代理如何学习估计 Q 值起着至关重要作用的问题,这就是:

体验回放

体验重放是一个概念,我们通过重放帮助代理记住并且不忘记它以前的动作。每隔一段时间,我们会对一批以前的经历进行采样(存储在一个缓冲区中),然后反馈给网络。这样,代理重温了它的过去并改善了它的记忆。这项任务的另一个原因是迫使代理人从振荡中释放自己,振荡是由于一些状态之间的高度相关性而发生的,并导致重复相同的动作。

最后,我们让我们的代理与环境互动,并训练他预测每个下一步行动的 Q 值

如你所见,这与 Q 表示例的过程完全相同,不同之处在于,下一个动作来自 DQN 预测,而不是 Q 表。因此,它可以应用于未知的状态。这就是神经网络的神奇之处。

你刚刚创造了一个学习开车上山的代理。太棒了。而且更牛逼的是,完全相同的代码(我是说复制粘贴)可以用在更多的游戏中,从 Atari、超级马里奥到 Doom(!!!)

厉害!

我保证,再坚持一会儿。

厉害!

在下一集,我们将继续深入 Q 学习领域,讨论一些更高级的技术,如双 DQN 网络、决斗 DQN 和优先体验重放。

一会儿见…

如果你有任何想法、评论、问题或者你只是想了解我的最新内容,请随时与我联系LinkedinTwitterinsta gramGithub或者********

要阅读整个深度强化学习课程,学习所有你需要了解的人工智能知识,去 这里

最初发布于 2018 年 10 月 1 日sergioskar . github . io

q-局部搜索

原文:https://towardsdatascience.com/q-localsearch-51e276d04d20?source=collection_archive---------12-----------------------

Photo by Franki Chamaki on Unsplash

一种基于 Q 学习的特征选择算法

“这次我不会再开什么无聊的玩笑,也不会做什么参考”,她就是这么说的!

在今天的文章中,我将尝试向您解释我上周一直在做什么,以及我在我的上一篇文章中谈论的内容,任何评论或建议都将是很好的,即使您觉得您并不关心,也许您正在从一个可能有所帮助的角度看待它,您可以在此链接中找到完整的代码(确保选择分支:“local-search-rl”)。

总之,在这部分代码中,你可以看到有初始局部搜索函数和 q-局部搜索函数,保持代码的可扩展性很好,所以当我需要实现一个新算法时,我所要做的就是在它们之间进行选择,因为它们不会影响其他部分。

BSO algorithm

如果我们在蜜蜂的水平上考虑局部搜索的初始算法,它进行穷举搜索,换句话说,它采用解决方案,一个接一个地翻转它的所有位,并每次进行评估,这使得复杂性,如果我们将其作为训练模型的成本,相当于模型的属性数量(例如声纳数据集,有 60 个属性, 这意味着我们将训练 60 个模型)并且这仅针对单个蜜蜂,并且针对单次迭代,这使得复杂度: o(最大 Iter x Nbr 蜜蜂 x Nbr 本地 Iter x Nbr 属性)

这是初始的本地搜索功能:

The original local search algorithm

Q-LocalSearch 背后的想法是提供“过滤”数据的子集(仍然是可选的),智能地翻转属性,或者换句话说,根据策略,以避免穷举搜索。

我们首先解释什么是 Q-Learning:

Q-learning 是由(Watkins & Dayan,1992)提出的一种无模型、非策略的强化学习算法。它包括评估状态-动作对的良好性。状态 s 和行动 a 的 q 值定义为在状态 s 采取行动 a,然后遵循政策的预期累积回报。

Reinforcement learning basic classification, Source

蒙特卡罗树搜索 (MCTS)、状态-动作-奖励-状态-动作 (SARSA)和 Q-Learning 是这种分类的一些示例算法。

q 表

Q-Table 只是简单的跟踪表的一个花哨的名字,就像 T2 ADL T3 在他的文章 T5 中所说的。它通常由 2D 数组组成,其中行代表状态,列代表可能的动作,因为当您处理特性选择时,使用静态数据结构是不明智的,所以我使用字典列表[索引是 nbrOnes(state)]字典列表[关键字是“state”][关键字是“action”](python 中的字典或 dict,就像 JAVA 中的 HashMap)

q_table[nbrOnes(state)][“state”][“action”]

q 函数

Q 学习算法基于下面给出的贝尔曼最优方程:

Q(状态,动作)= R(状态,动作)+ Gamma * Max[Q(下一个状态,所有动作)]

The Q-function explained

这就是我们每次更新表的方式,我们使用 Q 值来选择下一个状态,在这种情况下,要翻转哪些属性,这是 Q-LocalSearch 函数:

The Q-localSearch algorithm

概述

为了概括我们今天在这里所做的事情,我们谈到了 Q-learning,以及我们如何使用它来制作所谓的 Q-LocalSearch 函数,这是一种使用 Q-learning 算法进行特征选择的方法。

对于这个模型,我们有:

  • ****状态:是特征的组合
  • ****动作:翻转特征
  • ****奖励:目前,我们认为状态动作的准确性(适合度)是一种奖励,但是在下一篇文章中,我们可能会更深入,看看为什么它不是定义它的最佳方式。

我真的希望你喜欢它,我试图把我认为重要的一切,如果你需要更多的细节,不要犹豫留下评论,或 PM 我。

是的,你可以随时查看我的上一篇文章。

原载于 2018 年 12 月 26 日amineremache.blogspot.com**

基于深度学习的计算机视觉在制造业中的质量检测

原文:https://towardsdatascience.com/quality-inspection-in-manufacturing-using-deep-learning-based-computer-vision-daa3f8f74f45?source=collection_archive---------5-----------------------

通过图像识别去除劣质材料来提高产量

作者:帕萨·德卡罗希特·米塔尔

工业制造中的自动化:

当今制造业自动化水平的提高也要求在很少人工干预的情况下实现材料质量检测的自动化。自动化质量检测的趋势是达到人类水平或更高的精度。为了保持竞争力,现代工业企业努力实现自动化的数量和质量,而不牺牲其中一个。这篇文章向用户展示了深度学习的一个用例,并展示了优化整个堆栈(算法、推理框架和硬件加速器)以获得最佳性能的需求。

质量检测深度学习:

为了达到行业标准,制造企业的质量检查员通常在产品制造完成后检查产品质量,这是一项耗时的人工工作,不合格产品会导致上游工厂产能、耗材、劳动力和成本的浪费。随着人工智能的现代趋势,工业企业正在寻求在生产周期中使用基于深度学习的计算机视觉技术来自动化材料质量检测。目标是最大限度地减少人工干预,同时达到人类水平或更高的精度,并优化工厂产能、劳动力成本等。深度学习的用途是多种多样的,从自动驾驶汽车中的物体检测到医学成像中的疾病检测,深度学习已经被证明可以达到人类水平的准确性,甚至更好。

什么是深度学习?

深度学习是学习数据的深度结构化和非结构化表示的领域。当数据庞大而复杂时,深度学习是人工智能的发展趋势,可以抽象出更好的结果。深度学习架构由神经网络的深层组成,如输入层、隐藏层和输出层。隐藏层用于理解数据的复杂结构。神经网络不需要被编程来执行复杂的任务。千兆字节到兆兆字节的数据被馈送到神经网络架构,以便自己学习。下面是深度神经网络的示例:

卷积神经网络:

卷积神经网络是一类常用于图像分析的深度神经网络。卷积层对输入应用卷积运算,并将结果传递给下一层。例如,1000 乘 1000 像素的图像有一百万个特征。如果第一个隐藏层有 1000 个神经元,那么在第一个隐藏层之后,它最终会有 10 亿个特征。有这么多特征,很难防止神经网络用较少的数据过度拟合。训练一个具有十亿个特征的神经网络的计算和存储要求是非常高的。卷积运算为这一问题带来了解决方案,因为它减少了自由要素的数量,从而允许网络更深且要素更少。与完全连接的图层相比,使用卷积图层有两个主要优势-参数共享和连接稀疏。

卷积神经网络在图像中寻找模式。图像与较小的矩阵进行卷积,并且该卷积寻找图像中的模式。前几层可以识别线/角/边等,这些模式被传递到更深的神经网络层,以识别更复杂的特征。CNN 的这个属性确实很擅长识别图像中的物体。

卷积神经网络(又名 ConvNet)只不过是一系列层。三种主要类型的层用于构建 ConvNet 架构:卷积层池层全连接层。这些层是堆叠的层,以形成完整的 ConvNet 架构:

图片来源:http://cs231n.github.io/convolutional-networks/

下图阐明了卷积层的概念:

下图阐明了池层(平均或最大池)的概念:

以下是 CNN 最初的架构之一:

可视化 CNN :

以下是平面上裂纹的图像:

类似于 LENET-5 架构的两层 Conv(一个 3X3 过滤器)、ReLU 和 Max Pooling (2X2)应用于上面的裂缝图像。从下面可以看出,CNN 架构关注的是裂缝区域的区块及其在整个表面的扩散:

案例分析:

为了保持我们工作的机密性,我们在下面呈现一个抽象用例:

问题陈述:

检测硬件制造中的劣质材料是一个容易出错且耗时的手动过程,会导致误报(将劣质材料检测为优质材料)。如果在生产线末端检测到有缺陷的组件/零件,就会造成上游劳动力、耗材、工厂产能和收入的损失。另一方面,如果未检测到的不良零件进入最终产品,将会影响客户和市场反应。这可能对本组织的声誉造成不可挽回的损害。

总结:

我们使用深度学习对硬件产品进行自动化缺陷检测。在我们的硬件制造过程中,可能会出现划痕/裂纹等损坏,使我们的产品无法用于生产线的后续工序。我们的深度学习应用程序以人类水平的精度在毫秒内检测到裂纹/划痕等缺陷,并通过热图解释图像中的缺陷区域。

我们深度学习架构的细节:

为了更好地描述,我们在下面使用一个带有集成芯片的电路板示例图像:

我们的第一次进场:

我们采用了纯计算机视觉方法(非机器学习方法)的组合来从原始图像中提取感兴趣区域(ROI ),并采用纯深度学习方法来检测 ROI 中的缺陷。

为什么在 DL 之前提取 ROI?

当捕捉图像时,相机组件、照明等。专注于赛道的整个区域(下图)。我们只检查芯片区域的缺陷,不检查电路中的其他区域。我们通过几个实验发现,当神经网络仅关注感兴趣的区域而不是整个区域时,DL 准确性显著增加。

  • 首先用计算机视觉(非机器学习方法)提取“感兴趣区域(ROI)”。这里,我们对图像进行多种处理,如灰度缩放、腐蚀、膨胀、关闭图像等变换。并最终根据用例类型/产品类型等从图像中绘制出 ROI。侵蚀的基本概念就像土壤侵蚀一样——它侵蚀掉前景对象的边界。扩张与侵蚀正好相反,它增加了前景对象的大小。通常,在像噪声去除这样的情况下,侵蚀之后是膨胀。开放只是侵蚀和扩张的另一个名称。它在消除噪音方面很有用。关闭与打开相反,先膨胀后侵蚀。它在关闭前景对象内的小孔或对象上的小黑点时很有用。梯度变换是图像的膨胀和腐蚀之间的差异。总的来说,这些步骤有助于打开原始图像中几乎看不见的裂缝/划痕。参考下图:

  • 第二,使用深度神经网络(基于深度神经网络(CNN)的模型)来检测缺陷,使用已证实的 CNN 拓扑,例如 Inception Net(又名 Google Net)、Res Net、Dense Net:

为了找到最佳架构,需要进行实验的其他一些领域

  • 数据扩充:我们有几千张被标记为缺陷的独特图像,还有几千张被标记为良好图像。扩充对于避免过度适应训练集至关重要。我们做了 X 个随机裁剪和 Y 个旋转(1 个原始图像产生 XY 个增强图像)。在增强之后,我们有 XY 千个有缺陷的图像和 X*Y 千个好的图像。参考 CNN 在这方面的一篇原始论文https://papers . nips . cc/paper/4824-imagenet-class ification-with-deep-convolutionary-neural-networks . pdf
  • 初始化策略用于 CNN 拓扑结构:

我们用自己的 FC 层和 sigmoid 层(二进制分类)替换了最终连接的层,如下图所示:

对于每个 CNN 拓扑,我们考虑 ImageNet 初始化,而不是随机初始化每一层中的权重,当我们使用 ImageNet 初始化时,我们的 DL 准确性比随机大大增加。

  • 损失函数优化器:

交叉熵损失:交叉熵损失,或对数损失,测量分类模型的性能,其输出是 0 和 1 之间的概率值。交叉熵损失随着预测概率偏离实际标签而增加。因此,当实际观察值为 1 时,预测概率为 0.01 将是糟糕的,并导致高损失值。完美的模型的对数损失为 0

SGD内斯特罗夫动量:SGD 或随机梯度下降是一种迭代方法用于优化一个可微 目标函数(损失函数),它是随机的,因为它从数据中抽取随机样本来做梯度下降更新。动量是梯度的移动平均值,它用于更新网络的权重,并有助于在正确的方向上加速梯度。内斯特罗夫是最近开始流行的一个版本的动量。

我们的第二种方法:

对第一种方法的评论:在提取感兴趣区域时,每当产品类型、电路板类型/芯片类型(在我们的抽象示例中)、摄像机设置/方向等发生变化时,都需要重写代码。这是不可伸缩的。

解决方案:我们构建了一个端到端的两步 DL 架构。在第一步中,我们没有使用 CV 方法,而是使用 DL 方法来预测 ROI 本身。我们用边界框工具&手动创建了一个带标签的数据集,我们让训练一个 DL 架构来预测 ROI。这种技术的一个缺点是标签数据集必须足够明确和广泛,以包括所有产品类型等。(在我们的抽象示例的情况下,为电路板类型/芯片类型)用于深度神经网络在看不见的图像上很好地概括。参考下图:

  • CNN ROI 生成器损失函数:

我们最初使用基于平方距离的损失函数如下:

在验证集上对 Resnet50 模型进行 20 个时期的训练后,我们在平均遗漏面积和 IOU 上实现了以下验证指标:

平均漏测面积= 8.52 * 10–3

Ave. IOU(交集/并集)= 0.7817

我们希望至少在欠条上有所改进

我们想出了一个基于面积的损失,请参考下图,以了解我们如何使用基本数学来计算地面真实值和预测标签之间的相交面积。在损失函数中,我们希望惩罚错过的区域和超出的区域。理想情况下,我们希望对遗漏区域的惩罚多于对超出区域的惩罚:

上面的损失函数是可微的,因此我们可以对损失函数进行梯度下降优化

  • CNN ROI 生成器增强:我们只是在训练时间和测试时间在我们预测的 ROI 上增加了 5%(左右)的余量
  • CNN ROI 生成器结果:我们使用 resnet 50(ImageNet initialization)topology 和 SGD +内斯特罗夫动量优化器,其中=2,=1 在区域基于损失如上所述。为多个时期训练 Resnet50 模型,我们希望最小化我们的平均值。错过的区域和最大化我们的平均值。IOU(最佳 IOU 为‘1’)。经过 20 个时期的训练后,我们在验证集上实现了以下内容,通过基于面积的损失和增加,我们改进了(如上所述)我们关于遗漏面积和 IOU 的验证度量:

平均缺失面积= 3.65 * 10–3

平均 IOU(并集上的交集)= 0.8577

实验&基准:

图像总数:几千张图像

数据分割:80:10:10 分割,仅使用独特的图像

使用的框架:PyTorch & Tensorflow / Keras

重量初始化:在 ImageNet 上预先训练

优化器:学习率= 0.001 的 SGD,使用动量= 0.9 的内斯特罗夫

损失:交叉熵

批量:12 个

纪元总数:24

图像形状:224 x224 x3(Inception V3 除外,它需要 299x299x3)

标准:最低验证损失

我们对这两种方法的基准测试相当接近,CV+DL(第一种)方法的结果比 DL+DL(第二种)方法好不了多少。我们相信,如果我们能创建一个广泛和明确的带标签的包围盒数据集,我们的 DL+DL 会更好。

成功完成训练后,必须找到推理解决方案来完成整个端到端解决方案。我们使用英特尔 OpenVino 软件来优化除 CPU 之外的不同类型硬件中的推理,如 FPGA、英特尔 Movidius 等。

推论:

英特尔开放 Vino :基于卷积神经网络(CNN),英特尔开放 Vino 工具包将工作负载扩展到整个英特尔硬件,并最大限度地提高性能:

-在边缘实现基于 CNN 的深度学习推理

-使用通用 API 支持跨计算机视觉加速器(CPU、GPU、英特尔 Movidius 神经计算棒和 FPGA)的异构执行

-通过函数库和预先优化的内核加快上市时间

-包括针对 OpenCV 和 OpenVX*的优化调用

请参考以下开放式葡萄酒架构图:

两步部署:

-第一步是使用模型优化器将预训练模型转换成 IRs:

产生一个有效的中间表示:如果这个主转换工件无效,那么推理机就不能运行。模型优化器的主要职责是生成两个文件来形成中间表示。

产生优化的中间表示:预训练的模型包含对训练很重要的层,例如丢弃层。这些层在推理过程中没有用,可能会增加推理时间。在许多情况下,这些层可以从生成的中间表示中自动移除。但是,如果一组层可以表示为一个数学运算,因此可以表示为一个层,则模型优化器会识别这种模式并用一个层替换这些层。结果是一个比原始模型层数更少的中间表示。这减少了推断时间。

IR 是描述整个模型的一对文件:

。xml :描述网络拓扑

。bin :包含权重和偏差二进制数据

-第二步是使用推理引擎来读取、加载和推理 IR 文件,使用跨 CPU、GPU 或 VPU 硬件的通用 API

打开 Vino 文档:https://software . Intel . com/en-us/inference-trained-models-with-Intel-dl-deployment-toolkit-beta-2017 R3

样本图像上的推理基准:

很明显,使用软件堆栈进行优化对于减少推理时间至关重要。使用 OpenVino 软件优化,延迟时间提高了 30 到 100 倍。此外,英特尔 Movidius 和 FPGA 等其他英特尔硬件加速器也进行了相同的推理测试。目的是看看加速器相对于传统 CPU 能有多少改进。下面是一些关于示例图像的推理基准:

使用英特尔 Movidius Myriad1,使用 NCS SDK 将我们的 Resnet-50 Tensorflow/Keras 模型转换为 NCS 图形,Raspberry Pi 托管图像,推理由 movidius stick 中的视觉处理单元执行。movidius stick 的计算能力较低,因此该加速器没有提供大的性能提升。此外,使用的软件框架是一个 NCS 图,它可能不包含 OpenVino 等框架的所有性能提升(稀疏性、量化等)。

*使用为我们的 Resnet-50 型号提供的位流,在 linux 机器上使用 Open Vino 配置和编程 FPGA 板。FPGA 就像一个真正的加速器,在相同的软件框架(OpenVino)下,比 CPU 进一步提高了约 10 倍。

上述性能数字清楚地表明,需要一个整体视图来提高深度学习性能。优化的软件堆栈和硬件加速器都是实现最佳性能所必需的。

用热图可视化我们的 CNN:

通常,深度神经网络因可解释性低而受到批评,大多数深度学习解决方案在标签分类完成时就停止了。我们想解释我们的结果,为什么 CNN 架构将一个图像标记为好或坏(我们案例研究的二进制分类),CNN 最关注图像中的哪个区域。

基于麻省理工学院https://arxiv.org/pdf/1512.04150.pdf的这项研究,已经提出了结合全局最大池层的类激活图来定位特定于类的图像区域。

全球平均池通常作为一个正则化,防止在训练期间过度拟合。本研究证实,全局平均池层的优势不仅仅是作为一个正则化层,只要稍加调整,网络就能保持其卓越的定位能力,直到最后一层。这种调整允许在单次向前传递中容易地识别区别性图像区域,用于各种各样的任务,甚至那些网络最初没有被训练的任务。

以下是使用 ImageNet 上训练的 Resnet-50 架构,在“平面上的裂纹”图像上使用该技术的热图解释。正如我们所看到的,热图聚焦于下面的裂缝区域,尽管建筑并没有在这样的图像上训练——

总结&结论:

通过基于深度学习的计算机视觉,我们实现了人类水平的准确性,并且我们的两种方法——c v+ DL 和 DL+DL(在本博客的前面讨论过)都更好。我们的解决方案是独特的——我们不仅使用深度学习进行分类,还使用图像本身的热图来解释缺陷区域。

人的因素不能完全分离,但我们可以大大减少人为干预。最佳模型总是在 FPR(假阳性率)和 FNR(假阴性率)或精确度和召回率之间微调。对于我们的用例,我们使用一个针对低 FNR(高召回率)优化的模型成功地自动化了缺陷检测。我们大幅降低了人工审查率。通过我们的案例研究,我们证明了我们可以通过深度学习实现材料检测自动化,并降低人工审查率。

参考资料:

https://www . coursera . org/learn/卷积神经网络

https://arxiv.org/abs/1512.03385

http://cs231n.github.io/convolutional-networks/

https://papers . nips . cc/paper/4824-imagenet-class ification-with-deep-convolutionary-neural-networks . pdf

www.quora.com

【https://arxiv.org/pdf/1512.04150.pdf

https://keras.io/

https://pytorch.org/

https://opencv.org/

https://software.intel.com/en-us/openvino-toolkit/

https://movidius.github.io/ncsdk/

分位数回归,从线性模型到树再到深度学习

原文:https://towardsdatascience.com/quantile-regression-from-linear-models-to-trees-to-deep-learning-af3738b527c3?source=collection_archive---------4-----------------------

假设一位房地产分析师想根据房屋年龄和离就业中心的距离等因素来预测房价。典型的目标将是在给定这些因素的情况下,生成最佳房价点估计值,其中“最佳”通常指的是使与现实的平方偏差最小化的估计值。

但是如果他们不仅想预测一个单一的估计值,还想预测可能的范围呢?这被称为预测区间,产生它们的一般方法被称为分位数回归。在这篇文章中,我将描述这个问题是如何形式化的;如何用六种线性的、基于树的、深度学习的方法实现(用 Python — 这里是 Jupyter 笔记本);以及它们在真实数据集上的表现。

分位数回归最小化分位数损失

正如回归最小化平方误差损失函数来预测单点估计一样,分位数回归在预测某个分位数时最小化分位数损失。最常见的分位数是中间值,或第 50 个百分位数,在这种情况下,分位数损失就是绝对误差的总和。其他分位数可以给出预测区间的端点;例如,中间 80%的范围由第 10 和第 90 个百分位数定义。分位数损失根据所评估的分位数而不同,例如,对于较高的分位数,负误差越多,惩罚越多;对于较低的分位数,正误差越多,惩罚越多。

在深入研究公式之前,假设我们已经对一个真值为零的单点进行了预测,我们的预测范围从-1 到+1;也就是说,我们的误差范围也是从-1 到+1。该图显示了分位数损失如何随误差而变化,具体取决于分位数。

让我们分别看一下每一行:

  • 中间的蓝线显示了中位数,其围绕零对称,其中所有损失都等于零,因为预测是完美的。到目前为止看起来不错:中间值旨在将预测集一分为二,因此我们希望对低估和高估进行同等的权衡。我们很快就会看到,中位数周围的分位数损失是绝对偏差的一半,因此-1 和+1 都是 0.5,0 是 0。
  • 浅蓝色线显示第 10 个百分位数,负误差损失较低,正误差损失较高。第 10 个百分位数意味着我们认为有 10%的可能性真实值低于预测值,因此低估比高估损失更小是有意义的。
  • 深蓝色线显示第 90 百分位,是第 10 百分位的反向模式。

对于低估和高估的预测,我们也可以通过分位数来观察这一点。分位数越高,分位数损失函数对低估的惩罚越多,对高估的惩罚越少。

鉴于这种直觉,以下是分位数损失公式(来源):

在 Python 代码中,我们可以用maximum语句替换分支逻辑:

def quantile_loss(q, y, f):# q: Quantile to be evaluated, e.g., 0.5 for median.# y: True value.# f: Fitted (predicted) value.e = y - freturn np.maximum(q * e, (q - 1) * e)

接下来,我们将了解六种方法——OLS、线性分位数回归、随机森林、梯度增强、Keras 和 tensor flow——并了解它们如何处理一些真实数据。

数据

该分析将使用波士顿住房数据集,该数据集包含代表波士顿地区城镇的 506 个观察值。它包括 13 个特征和目标,即业主自住房屋的中值。因此,分位数回归预测的是房屋中值低于某个值的城镇(而不是房屋)的比例。

我对 80%的模型进行训练,对剩下的 20%进行测试。为了更容易可视化,第一组模型使用了一个单一的特征:AGE,1940 年之前建造的业主自住单元的比例。正如我们可能预料的那样,有旧房子的城镇有较低的房屋价值,尽管这种关系是吵闹的。

对于每种方法,我们将预测测试集上的第 10、30、50、70 和 90 个百分点。

普通最小二乘法

尽管 OLS 预测的是平均值而不是中值,但我们仍然可以根据标准误差和逆正态 CDF 来计算预测区间:

def ols_quantile(m, X, q):# m: OLS statsmodels model.# X: X matrix.# q: Quantile.mean_pred = m.predict(X)se = np.sqrt(m.scale)return mean_pred + norm.ppf(q) * se

这种基线方法产生以平均值(预测为中位数)为中心的线性和平行分位数。一个调整良好的模型将显示大约 80%的点在顶线和底线之间。请注意,这些点与第一个散点图不同,因为这里我们显示的是评估样本外预测的测试集。

线性分位数回归

线性模型从平均值扩展到中位数和其他分位数。线性分位数回归预测给定的分位数,放松了 OLS 的平行趋势假设,同时仍然保持线性(在引擎盖下,它最小化了分位数损失)。这是用statsmodels直截了当的说法:

sm.QuantReg(train_labels, X_train).fit(q=q).predict(X_test)
# Provide q.

随机森林

我们第一次离开线性模型是随机森林,一个树木的集合。虽然这个模型没有明确地预测分位数,但我们可以将每棵树视为一个可能的值,并使用其经验 CDF ( Ando Saabas 在此)计算分位数:

def rf_quantile(m, X, q):# m: sklearn random forests model.# X: X matrix.# q: Quantile.rf_preds = []for estimator in m.estimators_:rf_preds.append(estimator.predict(X))# One row per record.rf_preds = np.array(rf_preds).transpose()return np.percentile(rf_preds, q * 100, axis=1)

在这种情况下,它变得有点疯狂,表明过度拟合。由于随机森林更常用于高维数据集,我们将在向模型添加更多要素后再讨论它们。

梯度推进

另一种基于树的方法是梯度提升,scikit-learn的实现,其中支持显式分位数预测:

ensemble.GradientBoostingRegressor(loss='quantile', alpha=q)

虽然不像随机森林那样不稳定,但在单特征模型上看起来也不太好。

深度学习

Keras 是一个用户友好的神经网络工具包包装器,包括 TensorFlow 。我们可以使用深度神经网络通过传递分位数损失函数来预测分位数。代码有点复杂,所以查看一下 Jupyter 笔记本或阅读更多来自Sachin Abeywardana 的内容,看看它是如何工作的。

最深层的网络是带有纽结的线性模型(称为校正线性单位,或 ReLUs ),我们可以在这里直观地看到:Keras 预测,大约 70%建于 1940 年之前的城镇的房屋价值会出现更多的聚集,而在非常低和非常高的年龄段会出现更多的分散。基于测试数据的拟合,这似乎是一个很好的预测。

张量流

Keras 的一个缺点是每个分位数必须单独训练。为了利用分位数共有的模式,我们必须使用 TensorFlow 本身。参见朱庇特笔记本和雅各布·茨威格的文章了解更多信息。

我们可以在其预测中看到分位数之间的这种共同学习,其中模型学习一个共同的扭结,而不是每个分位数的单独扭结。这看起来是一个受奥卡姆启发的好选择。

哪个做得最好?

目测表明深度学习做得很好,线性模型做得还可以,基于树的方法做得很差,但是我们能量化哪个最好吗?是的,我们可以,使用测试集的分位数损失。

回想一下,分位数损失因分位数而异。因为我们计算了五个分位数,所以测试集中的每个观察值都有五个分位数损失。所有分位数观察的平均值证实了视觉直觉:随机森林表现最差,而张量流表现最好。

我们也可以通过分位数来打破这一点,揭示出基于树的方法在第 90 个百分位数表现特别差,而深度学习在较低的分位数表现最好。

较大的数据集为 OLS 提供了更多的改进机会

因此,随机森林对于这种单要素数据集来说很糟糕,但这不是它们的用途。如果我们将其他 12 个特征添加到波士顿住房模型中会发生什么?

基于树的方法卷土重来,虽然 OLS 有所改善,但 OLS 和其他非树方法之间的差距越来越大。

现实世界的问题往往超出预测手段。也许一个应用开发者感兴趣的不仅仅是用户的预期使用量,还有他们成为超级用户的概率。或者某车险公司想知道不同门槛下司机高额理赔的几率。经济学家可能希望从一个数据集到另一个数据集随机估算信息,从 CDF 中挑选以确保适当的变化(我将在后续文章中探讨这个例子)。

分位数回归对于这些用例中的每一个都是有价值的,机器学习工具通常可以胜过线性模型,尤其是易于使用的基于树的方法。在你自己的数据上尝试一下,让我知道效果如何!

量化基金和新的哑钱

原文:https://towardsdatascience.com/quantitative-funds-and-the-new-dumb-money-e0d88072dbaf?source=collection_archive---------4-----------------------

大多数量化基金是新的“傻钱”来源,在不知情和无技能的散户供应减少的时候,这些钱可以被用来获利。此类基金的运营限制使它们很容易成为目标。

交易是零和游戏。尽管有些人认为事实并非如此,但他们这样做是自担风险的。如果交易者不明白利润必须来自其他市场参与者的损失,那么失败的条件已经存在。然而,说服任何拒绝理解这一事实的人并不是本文的目的。

在 20 世纪 80 年代和 90 年代,当交易非常流行的时候,专业交易者和其他熟练的市场参与者能够因为哑币的供应而获得可观的利润。不熟练和不知情的散户交易者使用未经测试的方法,如图表模式是 CTA、做市商、熟练专业交易者和其他消息灵通的市场参与者的主要利润来源。网络泡沫破灭后,在随后的熊市中,大多数不熟练的交易者退出了市场,其中一些成为了被动投资者。难怪 CTA 和其他熟练的市场参与者的回报一直很低,因为:周围没有足够的哑资金供应。我已经说了很多年了,最近得到了尼尔·伯格的证实。

鉴于以上对市场现实的介绍,至少在过去的 10 年里,交易者产生 alpha 变得更加困难。顺便说一句,由于各国央行的不懈干预,被动投资者在股市中获得了巨额回报,但这场派对很快就会结束。此外,这些被动投资者面临着很高的风险,即在某个时间点,央行可能会试图获利了结,并为地方政府的社会政策提供资金,我认为这是投资趋势股票市场的主要意图。实际上,央行抛售可能导致下一轮熊市,而不是地缘政治事件。

坏消息是,现在已经没有多少散户傻钱了。好消息是,有许多新的量化基金。虽然操作这些基金的人很聪明,有数学和编程技能,但他们没有市场经验,尽管他们认为自己有,因为他们认为交易市场相当于在读了一些相关书籍后部署一个算法。大多数人发现这还不算太晚,在叔叔点。我有一些故事要分享,但我不会。

量化对冲基金的局限性

熟练的专业交易者可以利用量化对冲基金的一些局限性:

1。高容量交易算法

基金期望资金流入,因此它们的策略应该适应这一点。这就限制了他们可以使用的策略类型。为了增加容量,必须交易大量的工具,这通常可以在股票市场上获得,因为期货市场的流动性要低得多。标准普尔 500 成分是构成合适宇宙的一个例子。交易大量的证券降低了回报方差,但由于偏差-方差权衡,通过实施弱模型也降低了预期回报。简而言之,高容量限制通常会导致弱模型和高交易摩擦下的低回报。

专业交易者可以利用这一限制,专注于交易模型相对较快的指数 ETF。由于再平衡,这些交易所交易基金的价格行为会影响潜在价格行为。最终结果是,对冲基金最终以更低的价格交易个股。

从容量限制中获利的另一种更先进的方法是采用非常快速的算法。HFT 交易者已经这样做了,但是如果滞后很小,中低频交易者可以受益。

2。低β限制

大多数量化对冲基金要求业绩与市场相关性低。这意味着β值尽可能接近 0。然而,这排除了一大类基于风险调整的高盈利模式。例如,自开始以来,SPY 中的 1-12 个月移动平均动量规则的夏普比率为 0.90,而买入并持有的夏普比率为 0.55,但贝塔系数为 0.48,远远高于预期阈值。

Source: Portfolio Visualizer

专业交易者可以使用类似的模型,尽管他们有更高的贝塔系数,但他们仍然会降低对冲基金的利润潜力,因为对冲基金要求更低的贝塔系数。

上述模型是作为一个例子提出的,但它的未来表现很可能也会受到哑金和央行支持的不利影响。这被称为“行人”策略,这只是一个例子。

3。依靠学术研究者的建议

依赖学术研究人员可能是对冲基金能做的最糟糕的事情。学术研究人员和专业熟练的交易者在心态上有很大的不同。

我最近看到一位学术研究人员向对冲基金做了一个关于使用机器学习的演示。对我来说显而易见的是,尽管这位研究人员是一个拥有高级数学技能的聪明人,但他使用了怪异的术语,目的是为了制造炒作和给人留下印象。

数据挖掘偏见和 p-hacking 是一个问题,但学术研究的解决方案模棱两可,并忽略了一个事实,即过度拟合的模型可以很好地工作甚至几十年,并在 p-hacking 显而易见之前实现巨额财富。在交易中,知道市场条件何时变化比估计数据挖掘偏差重要得多。实际上,只要市场条件保持不变,过度拟合模型可能是一个好的解决方案。我在我的论文里有例子 关于交易策略评估的量化主张的局限性 。我收到人们的电子邮件,告诉我这篇论文如何改变了他们对战略发展和市场的整体看法。不用说:我不期待学术研究者的任何赞扬,因为他们的目标是不同的。

4。很多量化基金都在劫难逃

为什么我把这个列为限制?在我看来,这是因为任何认为 algos 很容易赚钱的人最终都会失败。任何有切身体会的人都知道,交易不仅仅是算法。有许多因素会影响性能。保持一切都在雷达下是一项艰巨的工作,需要一大群高度自律的员工和任务共享(雷伊·达里奥和布里奇沃特原则),或者保持小规模运营——专注于几个流动市场的独角戏。因素、特征、机器学习、算法、回溯测试、数据挖掘偏差、花哨的平台等等。可能不到工作的 50%。另外 50%是关于执行、维护和处理突发事件。

总结

新的量化基金有几个限制,专业交易者可以利用并获利。高容量要求,低贝塔约束,依赖学术建议,认为算法交易是灵丹妙药就是其中的一些。量化对冲基金是新的哑钱,尽管操作它们的人可能很聪明,受过高等教育。零和游戏是无情的。

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

这篇文章最初发表在价格行动实验室博客

如有任何问题或意见,欢迎在推特上联系: @mikeharrisNY

免责声明

关于作者:迈克尔·哈里斯(Michael Harris)是一名交易者和畅销书作家。他也是 17 年前第一个识别价格行为无参数模式的商业软件的开发者。在过去的七年里,他一直致力于开发 DLPAL,这是一个软件程序,可以用来识别市场数据中的短期异常,与固定模型和机器学习模型一起使用。点击此处了解更多信息。

量子优势,或者量子计算机工作的实际演示

原文:https://towardsdatascience.com/quantum-advantage-b3458646bd9?source=collection_archive---------8-----------------------

量子计算在科技界变得越来越明显。有十几家硬件公司,每家都在试图建立自己的量子计算机,从 Xanadu 这样的小型初创公司,到 D-Wave 或 Rigetti 这样的中型公司,再到谷歌、微软或 IBM 这样的大型企业。最重要的是,有几十家软件公司试图在现有的不完善的设备上实现量子算法。今天,我们生活在 NISQ 时代——嘈杂的中等规模量子——明年将有多达 128 个量子比特可用。

硬件公司正忙于扩大量子计算机的规模,提高计算的保真度,减少噪音。然而,每个人心里想的都是量子优势,这是一个实际的证明,量子计算机可以比经典计算机更好地解决现实世界的问题。

展示量子优势是硬件和软件公司的圣杯。谷歌最近宣布与美国宇航局合作,共同致力于此,里盖蒂设立了 100 万美元的奖金“用于量子云服务平台上量子优势的首次决定性展示”,普遍预期这一目标应该可以在未来 12 个月内实现。

量子优势并不意味着量子计算机会突然取代经典计算机。它更多的是证明,对于经典计算机难以解决的一些问题,量子计算能够提供令人信服的解决方案。到目前为止,当提供量子推进的解决方案后来再次被经典计算机击败时,有很多激动人心的事情,但也有很多破碎的梦想和倒退,例如尤因·唐在去年夏天的一些案例中展示了这一点(查看的论文或在量子中的故事)。

努力展示量子优势是我们公司波尔科技的主要目标之一。我们专注于优化问题,特别是在运输和物流方面,因为我们相信我们将能够在那里展示量子优势。对于在 NISQ 设备上演示量子优势的问题,我们有两个一般性的假设:

  1. 经典计算机难以解决且规模迅速扩大(例如指数级)的问题;
  2. 稀疏的数据集,来自难以生成或经典近似的概率分布。

例如,通过某些蒙特卡罗模拟、强力方法和全树搜索来满足这些类型的假设。现实世界的应用包括优化特定问题和稀疏数据的预测。这正是我们现在在波尔科技公司关注的问题。我们希望在接下来的 12 个月内展示量子计算的优势和广泛的商业应用。

我们认为,要实现这一宏伟目标,我们需要尽可能多地引进人才。这就是为什么两个月前我们决定启动 bqResearcher 计划来聚集量子计算社区,为这个单一目标而共同努力。我们的大部分研究是开源的,我们希望它保持这种方式,以便取得更快的进展。

最终,量子优势的结论性证明将成为计算本身历史上的一个伟大里程碑。

量子人工生命在这里

原文:https://towardsdatascience.com/quantum-artificial-life-is-here-b748d74f15b3?source=collection_archive---------11-----------------------

Photo by rawpixel on Unsplash

QUTIS(量子信息科学技术)组研究人员在 IBM 的云量子计算机 ibmqx4 中成功实现了量子人工生命。这是世界首例。被模拟的不仅仅是生命:生物体甚至在进化。目标是:在量子计算机上模拟自然进化。为什么我喜欢这条新闻?因为即使模拟的生物体非常简单,但这个主题涉及了很多领域和现象。更重要的是,实验显示了量子优势:量子计算相对于经典计算的明显优势。在接下来的内容中,我将给出几个实验涉及的主题的例子,以提供一些新闻背景。

人工生命

什么是艺术人生?人工生命 (Alife)可以被描述为通过使用模拟对自然生命或其某些方面的研究。生命分为三种:软生命(用软件建模)、硬生命(用硬件建模,像机器人)和湿生命(用生物化学建模;这包括合成 DNA 的产生)。soft alife 的一个例子是 Craig Reynolds 开发的著名 boids 程序,它是对鸟类群集行为的模拟。QUTIS 所做的是在量子计算机上实现的软存活。

演变

是的,量子计算机模拟中的简单生物甚至会进化。生物体具有基因型(编码遗传或可遗传信息)和表型(它们的外观,由它们的基因型和与环境的相互作用决定),并最终死亡,每一代的遗传信息都受到自然选择的影响。

量子计算

对量子计算的完整介绍超出了本帖的范围;不过,短一点的应该就够了。正如你可能知道的,“普通”计算机用比特工作,比特可以有两个值,通常称为 0 和 1。两位可以有四种位值组合:00、01、10 和 11。对于三位,这个数是 8。更一般地说, n 位可以有 2 的幂的 n 个值的组合。量子计算机用量子比特(量子比特)代替比特。一个量子位,当被测量时,会是 0 或 1,就像一个经典位一样。然而,在被测量之前,一个量子位可以处于两种状态的叠加状态。这意味着量子位有概率为 0,有概率为 1。一个 n 量子位的集合可以是所有 2 的 2 次方个经典值组合的叠加,直到测量完成:然后叠加崩溃,量子位全部为 0 或 1。因此,具有 n 个量子位的量子计算机可以同时执行 2 的 n 次方个计算,而具有 n 个位的经典计算机一次只能执行其中一个。这就是量子计算机强大背后的理念。

量子纠缠

好吧,孩子,这是一个巨大的主题。简而言之,经历量子纠缠的粒子具有依赖于彼此量子态的量子态,即使粒子相距甚远。结合量子叠加的想法,你会得到有趣的东西。比如,想象两个量子纠缠粒子叠加。现在把其中一个移到一百万光年之外,另一个保持在附近。测量你附近粒子的量子态,粒子会从叠加态坍缩到你测量的状态。这立刻使远处的粒子从它的叠加态坍缩,因为它与你刚刚测量的粒子是量子纠缠的。你似乎让事情发生得如此之远如此之快,以至于光都无法以如此快的速度传播到那里。这似乎违反了相对论,但实际上并没有。我可能会写一个帖子来更详细地解释这一点。

那么量子纠缠如何在量子生命实验中发挥作用呢?不同个体之间的关系是通过量子纠缠来实现的。例如,当一个个体通过自我复制从另一个个体“出生”时,这些个体的基因型之间存在关系,这在量子纠缠的两个个体的基因中实现。在经典计算机上,需要额外的变量来存储这些关系;量子计算机在这里显然有优势。

就像我说的,QUTIS Group 创建的模拟非常棒,因为它触及了如此多有趣的主题,并显示了量子至上。在未来,随着更大的量子计算机运行更复杂的模拟,研究人员可能会进化出更有趣的生物,甚至是智能生物。我们可以研究宇宙中生命和智慧的起源,同时学习更多关于量子计算机的知识!

量子计算?/!

原文:https://towardsdatascience.com/quantum-computing-5b715976e61d?source=collection_archive---------5-----------------------

零和一。这就是我们迄今为止对计算的想象。这就是经典计算。但是一个全新的概念正在改变我们对计算的看法。

在经典计算机中,一切都围绕着晶体管这个最基本的存储单元。众所周知,晶体管基本上是一个开关,不是开就是关,因此代表二进制 1 或 0。如今,晶体管的典型尺寸约为 14 纳米,比人类红细胞小 500 倍。随着这一规模的缩小,我们正在接近经典计算能够正常工作的极限。原因是经典物理在量子关系中不太适用。一个著名的例子是量子隧道效应,在这种效应中,电子会穿过一个传统上无法逾越的障碍。

但是科学家们正在通过建造量子计算机来利用这些不寻常的特性。

经典计算就像独唱——一行接一行的纯音。量子计算就像一首交响乐——许多音调相互干扰。― Seth Lloyd ,宇宙编程:量子计算机科学家挑战宇宙

正如经典计算机由比特驱动一样,量子计算机由量子比特驱动。这些量子比特有各种各样的属性,比如叠加和纠缠。

叠加:想象一次抛硬币。我们知道抛硬币的结果是二进制的,正面或反面。但我们也知道,一枚硬币可以停留在未定状态。当它在空气中时,它的状态还没有定义,或者我们也可以说它在两种状态中。这种同时拥有两种状态的原理,定义了量子位元最重要的属性,称为叠加态。我们大多数人都已经听说过经典的斯克罗登吉尔的猫的故事中的叠加,一只猫既是死的又是活的。当你试图测量一个量子位时,它会坍缩到一个确定的状态。如果我们有 4 个经典位,我们就有 2 个^4 = 16 个可能的值组合,你可以一次使用其中的任何一个组合。但是 4 个量子位可以同时存在于所有 16 种组合中。

纠缠:两个量子比特可以以这样一种方式相互绑定,即一个量子比特的状态变化会使另一个量子比特立即做出反应。这意味着使用一个纠缠的量子位,我们可以推导出另一个的性质。

就像使用逻辑门操纵经典比特一样,使用量子门操纵量子比特。量子门以叠加态和旋转概率作为输入,给出另一个叠加态作为输出,最终将这些叠加态压缩成实际的 0 和 1 序列。这允许同时进行一整套计算。

与经典计算机相比,量子计算机需要更少的迭代,尽管你不能用现在的量子计算机做很多事情。传统的数据库搜索可能需要 N 次迭代,而量子计算机只需要平方根 N 次迭代。1994 年,彼得·肖尔令人惊讶地发现了解决整数因式分解和离散对数问题的有效量子 T2 算法,此后,人们对该领域的兴趣大增。由于大多数当前的经典密码术假定这两个问题在计算上是困难的,实际建造和使用量子计算机的能力将允许我们破解大多数当前的经典密码系统。

几乎每个顶级公司都在研究量子计算机。谷歌的 Bristlecone,一种新的量子计算芯片,具有 72 个量子位,或量子位,使量子至上的竞赛更接近尾声,超过了 50 个量子位量子计算机的前纪录保持者 IBM。量子优势或“量子优势”是量子计算设备解决经典计算机实际上无法解决的问题的潜在能力。

现在重要的问题来了,我如何开始写量子算法。微软用它的量子开发工具包回答了这个问题。微软的量子开发工具包附带了一个名为 Q# 的专注于量子的领域特定语言,一个量子模拟环境,以及许多开源库和初学者样本。

要在需要约 30 个量子位的模拟环境中运行典型的量子算法,需要一台 RAM 约为 16 GB 的计算机,这个数字呈指数级增长。当你从 30 量子位增加到 40 量子位时,这个数字从 16GB 增加到大约 16TB。为了帮助解决这个问题,微软提供了一个托管在 azure 上的量子模拟器。

你今天就可以写出你的第一个量子算法。要开始,只需在你的系统上安装微软量子开发工具包https://marketplace.visualstudio.com/items?itemName = quantum . quantum-dev kit-vs code。

您可以将它用于 visual studio 社区或 visual studio 代码。现在克隆这个库https://github.com/microsoft/quantum,并试用这些样本。要运行这些示例,您只需要有 quantum-devkit 和。NET SDK。

Message Teleportation code running on my system. Transfering message between 2 qubits

量子计算的一些好读物。

罗纳德·德·沃尔夫讲座笔记:【https://homepages.cwi.nl/~rdewolf/qcnotes.pdf】T2

学习 Q#和了解微软量子开发工具包:https://docs . Microsoft . com/en-us/quantum/quantum-writeaquantumprogram?view = qsharp-preview&tabs = tabid-vs 2017

量子计算作者 Jozef grus ka:http://www2 . fiit . stuba . sk/~ kvasnicka/Quantum computing/grus ka _ QC . pdf

量子计算和人工智能喜结连理

原文:https://towardsdatascience.com/quantum-computing-and-ai-tie-the-knot-d4440267451b?source=collection_archive---------4-----------------------

2018 年,量子技术人员和大胆的开发人员正在使用量子算法来改造人工神经网络优化领域:机器学习和 AI 的蜜蜂膝盖。因此,我们可以满怀信心地说,多亏了量子算法,量子计算和人工智能的未来无可救药地纠缠在一起。因此,让我们深入探究在数字时代兴风作浪的量子算法。我将特别关注量子退火(与感觉押韵),这是一种独特的动物,它似乎在一个人工智能丰富的领域茁壮成长,而经典算法往往难以或完全失败:训练人工神经网络。

训练你的神经网络有困难?加入俱乐部…

相当令人惊讶的是,你可以训练人工神经网络,如 RNNs 和CNN变得明智,不会犯两次同样的错误。正是这种遵循埃丝特·戴森建议的能力使神经网络成为驱动机器学习和人工智能的智能引擎。也就是说,训练神经网络是一项众所周知的棘手任务。但这并没有阻止研究人员和编码人员在过去几年里努力工作,寻找新的方法来减少尖端优化算法的训练错误。减少误差问题的第一次尝试是众所周知的爬山法。让我们浏览一遍。

爬山

属于爬山俱乐部的优化算法总是在进行下一步之前检查梯度(或多或少是一个图形函数的斜率的陡度)。但是这冒着错过图表中真实活动的风险。登山者经常发现自己面临的两个敌人是高原问题局部最小值问题。总之,这些问题就相当于徒步旅行者在海市蜃楼般的沙漠中迷路,或者被困在一个泥泞的小山谷中。但是让我们深入挖掘一下…

高原问题

当一个优化过程进入平台期时,这意味着它对于每个输入(x)得到大致相同的输出(y)。因为对于长的平坦延伸,函数的斜率为零或接近零,所以优化算法在找到边之前可能会耗尽时间。就像闪闪发光的沙漠海市蜃楼一样,平坦函数的长期延伸会产生一种错觉,即当你还没有接近它时,你已经达到了最佳状态(在这种情况下是全局最小值)。

source: safaribooksonline.com

局部最小值问题

局部最小值是一个函数图中相对较小的谷,其最深和最重要的谷位于别处。你可以把优化过程(当它在一个函数中寻找最小值的时候)想象成一个沙滩球:它会向山下滚去,最终停在眼前风景的最低点,即使在附近小山的另一边有一个更深的山谷。这就是问题所在。

source: safaribooksonline.com

最激动人心的解决方案

除了传统的爬山方法,还有很多其他的方法可以帮助你走出由局部最小值问题引起的可怕的山谷和由高原问题引起的沙漠海市蜃楼。但是为了手头的目的,让我们只关注最令人兴奋的解决方案:模拟退火。这是一种野生的优化动物,它正在以一种计算巧妙的方式处理山谷和高原,至少值得思考几段时间…

最热门和最酷的经典优化算法

开门见山地说,模拟退火从物理学中偷师,将时间和温度捆绑在一个优雅的算法中。是的,你没看错:一个带有温度参数的算法。当你运行一个模拟退火算法时,它从手边的函数的整个景观中开始一个完全随机的、狂热的选择序列。这是流程中最热的阶段。但是,随着温度参数随着时间的推移而下降,随机选择覆盖的景观范围越来越窄。最后,我们进入过程的阶段,因为算法开始瞄准(如果运气好的话)最深的谷或最高的峰,那里是优化的圣杯:全局最小值或最大值。

虽然模拟退火算法中的代码通常包含一些复杂的数学运算,但时间和温度之间的潜在联系是很容易理解的。想象一下,一个炽热的东西在未知的地方疯狂移动,击中了视线内的一切,并向我们报告了一张非常粗略的地形图。然后,你可以想象逐渐变冷的东西越来越慢,越来越小心地穿过越来越窄的地形区域,记录它们进一步潜入最深的山谷或爬上最高峰的细节……好吧,如果你仍然不确定我到底在说什么,这里有一个优秀的动画应该可以做到这一点。

量子退火(哦,多好的感觉)

当传统爬山法的其他替代方案都不理想时,模拟退火通常可以让你摆脱困境。但这是一种极其专业的方法,它至少有一个令人不寒而栗的缺点:你必须无限长时间地运行该算法,才能平稳地达到绝对零度,从而保证你在能源格局中达到真正的全球最小值或最大值。因为你可能没有永恒的空闲,你永远不会知道你的优化解决方案是否陷入了另一个陷阱。

进入量子退火。首先,重要的是要记住,量子退火算法的基本形式与模拟退火算法非常相似。为什么?因为量子隧穿强度在量子退火中的作用与温度在模拟退火中的作用相同。久而久之,量子退火炉中的量子隧穿强度急剧下降,就像模拟退火炉中的温度急剧下降一样。也很容易想象隧道强度和温度之间的相似性。久而久之和量子隧穿强度下降,系统变得越来越舒适,在能源景观的每个渐进更深的山谷,越来越不倾向于隧道的出路。最终,当它发现自己(理想情况下)处于能源领域最深、最舒适的谷底(也就是全球最小值)时,它会完全放弃挖隧道。

不是你祖母的量子计算机

你一定会注意到,相对传统的量子计算机和量子退火计算机之间的第一个区别是它们使用的量子位数量。虽然传统量子计算机的最新技术在 2018 年推出了几十个量子位,但领先的量子退火器拥有超过 2000 个量子位。当然,代价是量子退火器不是通用的,而是专门的量子计算机,在技术上只处理优化问题和采样问题。因为解决最优化问题被认为是通往人工智能乐土的关键途径之一,所以从现在开始我将把重点放在它上面。

令人眩晕的混乱状态

在我们将量子退火算法应用于量子退火器中的量子位池之前,它们是一团乱麻:一个最模糊且不相连的配置。这意味着我们一开始对量子系统一无所知,它可能处于任何 2^n 不同状态(其中 n 是量子比特的数量)。对于一台拥有 2000 个量子位的量子退火机来说,这是一个疯狂的可能状态数。如果你对此有任何疑问,试着在你最喜欢的计算器中输入 2 个⁰⁰⁰来寻求第二种意见。

量子许愿井

单个量子位总是从初始的多云叠加状态开始,这使它们处于最小可能的能量。物理学家喜欢把这种最低能量状态想象成量子势阱的底部,看起来有点像一个大字母 u。

U

0/1

然后量子退火出现,迫使叠加态分成两半,两个状态,两个底部:0 和 1。结果看起来更像一个大写字母 W:

W

0 1

量子退火者的下一步是开始在量子概率游戏中装载骰子以支持房子。

偏见

在外加磁场的帮助下,量子退火器推动每个量子位严重偏向 01: ,有利于上面 W 中的第一次或第二次倾斜。

连接器

当量子退火机通过磁场给骰子(也就是单个量子位)加载偏置时,他们也在忙着通过耦合器用理论线将成对的骰子绑在一起。具体来说,一个耦合器可以做两件事情中的一件。它可以保证一对量子比特始终处于同一状态:要么都是 0 ,要么都是 1它可以保证两个相邻的量子位始终处于相反的状态: 01 ,或 10 。量子耦合器使用(惊喜,惊喜)量子纠缠将量子比特捆绑在一起,创建耦合。

塑造能源景观

作为一名使用 quantum annealer 的有抱负的开发人员,您的工作是通过编码一组偏差和耦合来加载所有的 quantum 骰子,这些偏差和耦合定义了您希望可靠的 annealer 解决的优化问题。另一种看待它的方式是,你正在雕刻,或者至少产生一个复杂的能量景观,它由峰和谷组成,代表了你的最优化问题中所有可能的结果。然后你就可以让量子 annealer 去搜索并找出能源领域最深的谷底,这也是最优解。如果你一直成功,那么你的量子退火能力可能有助于为子孙后代提供新一代的机器学习和人工智能。

量子计算和人工智能新闻

2017 年 8 月 31 日,大学太空研究协会(USRA) 宣布与美国宇航局和谷歌合作,将量子人工智能实验室(量子人工智能实验室)的量子退火计算机升级为 D-Wave 2000Q 。最新的 D-Wave 拥有几乎是其前身两倍的量子位和“绝热量子计算”的新诀窍,正在追求优化问题池中更大的鱼。USRA 团队甚至着眼于使用量子算法和 D-Wave 来解决“NASA 任务中涉及的挑战性计算问题”另一方面,合作伙伴谷歌已经盯上了人工智能:

我们对将量子计算应用于人工智能和机器学习特别感兴趣。

但不仅仅是谷歌和美国宇航局可以访问量子人工智能实验室。信不信由你,你也可以。如果你是一个合格的候选人,你可能会有一些时间和最新的 D-Wave 一起尝试你的天才想法。用实验室自己的话说,“通话开启。”

嗯,这就是我今天的全部内容。如果你喜欢这篇文章,我会非常兴奋,如果你点击拍手按钮:)或与你好奇的朋友分享。我在我的个人博客(jasonroell.com)上有更多类似的东西,或者你可以订阅我的媒体简介,让我一写完文章就发给你!(多牛逼?!)

无论如何,再次感谢你的阅读祝你有美好的一天!

量子计算解释!

原文:https://towardsdatascience.com/quantum-computing-explained-a114999299ca?source=collection_archive---------0-----------------------

在亚原子水平上,我们所知道的关于经典物理学的每一件事情都破裂了,不仅仅是小幅度的破裂,而是大规模的破裂。欢迎来到量子力学的世界,准备好大吃一惊吧。

在我们开始谈论量子计算之前,我们必须很好地理解什么是量子力学,它有什么特别之处,以及量子力学现象如何帮助我们执行高级计算。

关于量子力学的最初研究可以追溯到 17 世纪,当时科学家提出了光的波动理论 ( 光可以同时展示波动理论和粒子理论)。光量子的存在是由 马克斯·普朗克 在 1900 年提出的,这一观点被 阿尔伯特·爱因斯坦 进一步加强,他指出,光是由称为光子的微小粒子组成的,每个光子都具有能量。 一般来说,量子力学在原子和亚原子粒子的尺度上处理物质的行为及其与能量的相互作用。

随着量子力学的出现, 牛顿力学(或经典力学 ) 开始在基础层面消退。光本身的某些特定性质无法用经典物理学解释,氢光谱系列,例如,当氢气在一个管中加热并观察发射的光时,可以注意到氢原子的发射光谱包含多个光谱系列,而不是连续发射的光(或电磁辐射),是的,它更像是颜色的条带,与经典物理学的预期不同。丹麦物理学家 尼尔斯·玻尔 对此提出了一个解释,即波尔模型,在该模型中,他将原子描述为一个带正电荷的小原子核,周围是 电子,这些电子围绕着原子核以圆形轨道 运行——类似于太阳系的结构。每个轨道对应不同的能级。能量的变化,如电子围绕原子核从一个轨道转移到另一个轨道,是在离散的量子中完成的。术语量子跃迁指的是从一个离散能级到另一个离散能级的突然 运动,没有平滑过渡 。没有“中间”。

量子跳跃是特殊的,因为电子的运动不是渐进的,它只是从一个轨道上消失,然后出现在下一个轨道上,没有中间状态,并释放(或吸收)一定量的能量。这让事情变得有趣了。Bhor 解释说,这个层次的能量不能再细分,它被称为量子,一种特定的最小能量。这种能级的第一个见解是由一位名叫普朗克的物理学家提供的,所以我们称它为普朗克常数。所以,一般来说,原子中电子的能量是量子化的。

这只是开始,经典物理的可预测性被量子物理的潜力所颠覆。这是当时许多物理学家非常关心的问题。为什么电子遵循量子化轨道而没有中间态?

路易·德布罗意 1923 年的论文回答了这个问题。他解释说 物质可以表现出粒子性和波动性 就像光一样。电子的波动性质要求它们获得特定的波长,这是允许它们适应轨道的。但是在这个轨道上,由于电子的波动性质,电子可以存在于任何地方,而不仅仅是某个特定的点。这从根本上不同于经典物理学,但被实验证明。因为质量较大的物质,如我们人类,具有高动量,并且这种物质的波长会小得多,因为质量与德布罗意波长成反比。因此,德布罗意解释的效果在宏观层面上减弱了。

1927 年,戴维孙和热尔默进行的双缝实验证明,光和物质可以表现出经典定义的波和粒子的性质。托马斯·杨在 1801 年做了一个类似但更简单的双缝实验。当光线穿过屏障上的两个狭缝时,会在另一侧的屏幕上形成干涉图案。(穿过双缝的光不会在屏幕上形成双带图案)这些实验有趣的部分是,即使我们一次通过一个电子/光子,干涉图案也会在屏幕/探测器上形成。这怎么可能呢?这意味着,如果我们从一个源发送一个电子通过一个双缝(我们不知道电子通过哪个缝),电子出现在屏幕(或探测器)另一侧的位置是随机的(意味着它可以在干涉图案中的任何地方)。如果我们发送大量的电子,就会在另一边形成干涉图案。这意味着每个单个电子必须表现出波的性质,否则它不会干扰任何其他东西,在势垒一侧的单个电子波将在双缝势垒的另一侧产生两个波(就像单个水波穿过两个孔可以在另一侧形成两个波),这两个波相互作用形成干涉图案。

Erwin Schrodinger 发表了一个方程,其中 将运动的电子描述为一个穿过 传播的波。这个方程也被称为薛定谔方程,它帮助他获得了 1933 年的诺贝尔物理学奖。

德国物理学家和数学家梅克斯·玻恩阐明了概率密度函数,它将所有这一切描述为发现电子为波的一种 可能性。 这是在他研究了玻尔模型的电子轨道之后,这有助于他和沃纳·海森堡一起阐明量子力学的矩阵力学表示。一年后,海森堡提出了海森堡的测不准原理,认为即使在理论上,粒子的位置和速度也不能同时精确测量。

沃纳·海森堡和尼尔斯·玻尔一起设计了量子力学的哥本哈根解释,该解释指出 物理系统在被测量之前通常不具有确定的属性,量子力学只能预测测量将产生某些结果的概率。测量的行为将导致波函数坍缩,把概率变成一个可能的值。

阿尔伯特·爱因斯坦回应道

“上帝不和宇宙玩骰子”

尼尔斯·玻尔回答道

"别再告诉上帝该怎么处理他的骰子了。"

即使是有史以来最聪明的人也很难理解量子物理学的全部内容。但是在双缝实验中很明显,如果我们在任何一个缝上放置一个测量装置,试图找出电子通过哪个缝,干涉图样就会消失。

强烈建议观看此视频:

所以,在没有观察的情况下,把现实赋予宇宙是没有意义的。在测量间隔中,量子系统确实是所有可能性质的模糊混合物。这就是量子叠加,正常的物质宇宙只有在测量的瞬间才有意义。

就我们的电子而言,叠加可以描述为电子同时处于不同位置的可能性。根据测不准原理,这也适用于电子的自旋(它是角动量的一种固有形式)。电子可以在所有方向上自旋,直到我们测量它的自旋,测量时自旋要么与测量方向一致,要么与测量方向相反。这也称为加速旋转或减速旋转。

量子系统中的情况不同乍一看也难以把握,为了放松我们可能需要看一段猫的视频。薛定谔的猫呢?

让我们也看看这个..

简而言之,一只猫在一个封闭的盒子里,盒子里有某种东西(比如说炸丨药)可能会杀死它,也可能不会杀死它,这是叠加态,这意味着对外界来说,猫要么活着,要么死了。所以直到我们打开盒子,观察到猫有一半的概率是死的,一半的概率是活的。

这个实验还有一个更重要的含义,那就是在封闭的盒子里会发生什么。如果猫感觉到爆炸,它就会死,如果它感觉不到爆炸,它就会活着。cat 的状态与 explosive 的状态有某种联系。在量子世界中,这被描述为量子纠缠。****

量子纠缠是一种现象,通过这种现象,一个以上的粒子,共同产生或密切相互作用,可以开始一种关系,每个粒子的量子状态不能独立描述(如果猫死了,爆炸/如果爆炸的猫死了)。因此,粒子不能独立描述,它们成为一个连接的系统,测量一个会影响另一个的状态。即使当它们相隔很远时,这种属性也将被保留。

例如,考虑两个纠缠的电子,我们将考虑电子的自旋(可以考虑位置或动量,我们将自旋视为角动量)在产生时总和为零。现在我们可以把这些电子分开任意距离,并独立地测量它们。如果第一个电子测量自旋向上,那么另一个将总是自旋向下,反之亦然。而测量的效果是瞬间发生的,意味着比光速还快。

纠缠的量子粒子以概率状态存在,只有当其中一个粒子被测量时才会失去叠加态,而另一个粒子会瞬间受到影响,即使相隔任何距离,这种想法让当时的许多科学家疯狂。它甚至包括爱因斯坦,他称之为“超距幽灵行动”。他甚至提出了 EPR 悖论,它说两个粒子相互作用形成深层关系,信息被编码在一些关于可能状态的“隐藏参数”中。就像一个电子说,如果有人测量我,我会旋转,另一个说我会旋转。否则,它发送信息的速度将超过光速,从而打破相对论。

阿兰方面在 1980 年用基于约翰·斯图尔特·贝尔 1964 年提出的贝尔定理的贝尔检验实验推翻了 EPR 佯谬。是的,量子世界是真实的,幽灵般的行为确实存在。

现在让我们用量子计算的观点重新开始每一件事…让我们再做一次。

****量子计算研究直接利用叠加、纠缠等量子力学现象对数据进行运算的理论计算系统。

在经典计算机中,我们将任何数据转换为 0 和 1,即所谓的 位。 实际上是对高电压和低电压进行处理,然后将它们通过一系列称为逻辑门的门,这些门可以操纵数据来计算出结果。逻辑门如与、或、非、异或等。可以以不同的方式排列来处理这些位并产生输出。它可以做简单的操作,如复杂加密的加法。逻辑门是通过使用晶体管来实现的,现在晶体管依靠硅半导体的特性来执行操作,而不是使用机械开关。

当然,经典计算机速度快、效率高,但它们不擅长处理涉及指数复杂性的问题,如 整数因式分解 。尤其是整数进一步限定为质数时的质因数分解(半质因数分解)。基本上,找到两个大素数的乘积是很容易的,但是在给定乘积的情况下,用经典计算机找到产生乘积的数需要大量的计算。事实上,这种复杂性是包括 RSA 在内的许多密码系统的基础。

那么量子计算机如何解决这个问题呢?

在量子计算中,基本计算单位是一个量子位,它可以表示信息。量子位与普通位有一些相似之处,例如它可以被测量为 0 或 1。但是量子比特的威力在于它像叠加和纠缠一样的量子力学性质。一个量子位可以同时处于零态和一态。一个量子位的状态用“ket 0”和“ket 1”符号来表示,记为 |0 >|1 > ,基本的测量状态类似于经典的 0 和 1。

真实量子计算机中的量子比特到底可以是什么?它可以是有自旋的电子,有极化的光子,杂质自旋,俘获离子,中性原子,半导体电路等等。

简单量子位的超位置可以用下面的布洛赫球来表示

这看起来可能有点复杂,但我们需要记住的要点是,单个量子位在任何时候都可以处于 |0 >|1 > 的超级位置,它可以表示为

a | 0>+b | 1>+

其中 a 和 b 分别是被测量的量子位的振幅(与概率成比例)为 0 和 1,并且 a + b =1

因此,一个量子位可以处于两个状态的叠加位置,一旦它被测量,它将根据每个状态的概率返回两个状态中的一个。所以测量一个量子位本身对系统有影响,所以测量一个量子位类似于一个影响量子位状态的门。

如果我们考虑一个以上,比如说两个,量子位的事情变得更有趣,基本状态将是 00,01,10,11 但是量子位可以同时处于所有四个状态的超级位置。所以这应该表示为

a | 00>+b | 01>+c | 10>+d | 11>+

为了表示两个量子位,我们需要 4 个概率/振幅(a,b,c,d),如果我们有三个量子位,我们将需要 8 个。因此,如果我们有 n 个量子比特,我们将需要 2^n 数来代表这个量子系统的整体状态。因此,通过少量增加量子位的数量,我们将能够产生能够代表巨大状态的系统,这与经典计算机不同。

即使描述超位置所需的信息量随着量子位的数量呈指数增长,由于量子测量的基本限制,我们也无法访问所有这些信息。叠加态中电子的自旋可以是所有方向的,但是当我们测量时,它只能是向上或向下的一个方向。我们也不能预测结果,它是基于与状态相关的概率的(例如:一半时间上升,一半时间下降)。这意味着,为了充分发挥量子计算机的潜力,我们需要开发量子算法,探索存储在量子位超级位置的大量信息的存在,并在计算结束时,让系统处于我们可以确定地检测到的基态之一。

在量子计算机中,有可能存在两个值相反的量子位,但在我们测量之前,单个量子位的值是未知的。这是可能的,因为量子纠缠。假设我们有两个零态的电子量子位,然后我们通过施加电磁波使第一个电子/量子位处于叠加态,该电磁波具有与零和一态之间的能量差成比例的特定频率。现在,当我们试图通过施加第一电子/量子比特处于零状态时所需频率的电磁波来调整第二电子/量子比特时,处于超位置的第一电子/量子比特将对第二量子比特的自旋产生影响,并且第二电子/量子比特也将移动到叠加状态(非稳定状态)。所以这两个量子位的状态将会纠缠在一起,如果我们测量第一个并得到向上自旋,那么另一个将给出向下自旋,反之亦然。这种纠结,在任何远距离都会持之以恒。在我们测量它们之前,这两个量子位元只能被视为一个具有可能值的单一系统。这在经典计算机中是不可能的,因为有两个比特没有值,而是相反的值。

因此,量子位元数目的增加,将会成倍增加可能的纠缠态数目。需要注意的一个关键点是,量子纠缠可能非常脆弱(量子退相干),任何利用这一点的系统都应该具有非常小的外部干扰。

量子电路(量子计算的模型)的积木是量子逻辑门。它们就像经典计算世界的逻辑门,但与许多经典逻辑门不同的是, 量子逻辑门是可逆的 。这是因为量子力学要求量子系统永远不会随时间丢失信息,并且它必须总是能够重建过去。

你能想到任何通往量子世界的经典大门吗?

“与”门不会成功,因为 1 和 0、0 和 1 的输出都是 0。

是,没有什么能到达量子世界

非 0 = 1,非 1 =0

这是可逆的,如果输出为零,则输入为 1,如果输出为 1,则输入为零。这个门在量子世界中被称为泡利-X 门**。它映射 |0 > |1 >|1 > |0 >**

****哈达玛门也作用于单个量子位,并产生叠加态。

****交换门交换两个量子位。即 |10 > |01 > 以此类推。

****受控门作用于 2 个或更多的量子位,其中一个或多个量子位作为某种操作的控制。例如,受控非门(或 CNOT )作用于 2 个量子位,只有当第一个量子位为|1 >时,才对第二个量子位进行非运算,否则保持不变。

CNOT 门:

在 CNOT 门的情况下,我们可以看到每个输出都是不同的,没有模糊性,状态可以恢复。

在基于电子自旋的量子计算机中,CNOT 门很容易实现。由于控制比特和目标比特靠得很近,控制比特的自旋对目标比特有一定的影响,它决定了我们能否用一定的电磁波翻转目标。

CNOT 门也可以用来产生控制和目标的纠缠态。如果我们先用阿达玛门来控制,然后再用 CNOT 门,控制和目标就会叠加纠缠在一起。CNOT 门通常在量子计算中用来产生纠缠态。

CNOT 和任意量子位旋转可以在量子计算机中实现任何逻辑功能。

你可以在这里找到其他可用的量子门。

测量一个量子位也可以改变系统的状态,功能非常类似于门,但它不是一个实际的量子门。

为了让量子计算机工作,我们应该能够改变任意量子位的属性,我们应该能够通过在一个或多个量子位之间进行交互来运行量子逻辑门。

现在我们需要利用所有这些逻辑来创建一些有用的算法。使用量子计算机来执行计算简单的操作是没有意义的,因为经典计算机可以以更低的成本完成这一操作。由于基础设施本身是复杂的,并且量子计算机可以同时处理大量的状态,量子计算机的有效使用被限制在特定的领域,如寻找质因数、搜索大量数据等。这是计算密集型的。

****量子算法是一个循序渐进的过程,其中的每一步都可以在量子计算机上执行,这将涉及量子属性,如叠加和纠缠。已经有不同的算法可用,更多的算法正在开发中。

Shor 的整数因式分解算法 因其在密码学中的应用而成为最著名的算法之一。

格罗弗算法 也是众所周知的,用于搜索非结构化数据库或无序列表。

你可以在这里找到其他有趣的算法。

下面我们来探讨一下 格罗弗算法的一个小变种 用于搜索的量子算法。

首先,考虑 N 个电话号码和姓名的列表,我们需要从中找到特定号码的名称

与提供指数级速度增长的普通量子算法不同,Grover 的算法仅提供二次速度增长。复杂度将是可能元素数量 n 的平方根的函数。与可能具有复杂度 n 的经典算法相比,这要高效得多。Grover 的算法使用振幅放大工作。

在我们的例子中,我们将只考虑四个数字,它们可以用两个量子位来表示,我们需要找到与 10 相关的名字

a | 00>+b | 01>+c | 10>+d | 11>+

其中 a、b、c 和 d 是幅度,a=b=c=d。

这就是 Grover 算法中的第一步就是把量子比特放在超位。

****第二步是应用一个 oracle 函数,该函数将我们正在寻找的项目的振幅翻转到相反的方向。在这种情况下,c 变成了-c,现在 a=b=d,c 不同,是负数。

****第三步是应用一个放大函数,放大每个振幅和相等叠加态振幅之间的差异。因为-c 的值与其他振幅有很大的差异,所以与 a、b 或 d 相比,c 的值迅速增加。

现在,如果我们测量量子位,第三个状态将以最大概率返回(步骤 2 和 3 可以再次应用以增加概率)。因此,使用这种技术,我们可以通过一次性将所有可用值加载到量子位中来解决搜索问题。可用的量子位越多,我们能处理的问题域就越大。

一切都很好,但是运行这一切的硬件呢?

量子计算机的当前实现是基于半导体的。从这些半导体产生的量子位应该远离任何外部干扰。否则,这些量子位的量子力学特性将会丢失。因此,这些量子计算机的温度保持在非常接近绝对零度,这种设置以及微观水平的计算会使量子计算机非常昂贵。精确的微波/电磁波可以用来改变量子位的状态。通常情况下,经典计算机与量子计算机一起使用来帮助处理。

IBM Q 是行业首创,旨在为商业和科学领域构建商用通用量子计算机。 IBM Q Experience 允许我们使用 online composer 或免费使用其 python 库来运行量子算法。这些系统中量子位元的数量相对较少,但肯定会快速增加。

D-Wave Systems 是这个领域的另一个主要参与者,他们的旗舰产品是 2000 量子比特 D-Wave 2000Q 量子计算机。D-Wave 产品被谷歌等公司广泛用于运行量子人工智能实验室和美国宇航局的研究。

D-Wave 机器使用量子退火来执行其操作。这对于优化问题的解决方案非常有用,可以快速搜索空间,找到成为解决方案的全局最小值。这种方法对于某些问题领域可能会更快,但使用量子退火的系统将会发现很难运行某些算法,如著名的 Shor 算法。

另一方面,IBM 提供的通用量子计算将服务于更广泛的问题领域,并允许我们设计更复杂的算法。但是用通用量子计算来设计这些算法可能会很复杂,并且在系统设计和一致性方面也有自己的挑战。

量子力学是一个本质上令人震惊的科学领域,它所提供的计算能力只是冰山一角。它在生物学(它可以通过叠加解释突变)、计算机硬件(解释半导体芯片的特性),甚至可以解释人类的期望或想法如何影响未来,正如全球意识项目所解释的,该项目实验证明“当人类意识变得连贯时,随机系统的行为可能会改变”。是的人类思维与量子物理之间确实存在的奇怪关系。此外,它还可以用于 量子隐形传态 ,据中国科学家报道,他们已经将地球上一个光子的量子态传输到近地轨道卫星上的另一个光子。量子力学有潜力改变我们以经典方式知道和做的每一件事。

我希望你明白一些事情…

“如果你认为你懂量子力学,那你就不懂量子力学。”理查德·费曼

谢谢你的时间。

Python 程序员的量子计算笔记:复数

原文:https://towardsdatascience.com/quantum-computing-notes-for-a-python-programmer-complex-numbers-2e1a574bdb88?source=collection_archive---------5-----------------------

Image from — https://phys.org/news/2017-11-simple-beautiful-quantum.html

但是如果量子力学不是通常意义上的物理学——如果它不是关于物质、能量、波或粒子的——那么它是关于什么的呢?

从我的角度来看,它是关于信息和概率
和可观察到的事物,以及它们之间的相互关系。

自德谟克里特斯以来的量子计算(第 110 页)

这些系列笔记,最初是我为自己写的,是我希望成为一个关于量子力学基本方面,更准确地说是关于量子计算的小系列。我不会试图对任何我不完全理解的事情做出任何流行科学的、不着边际的解释。当类似的事情发生时,我会诚实地写下我不理解的事实(可能会发生很多次)。但除此之外,这组特殊的音符还有一个非常特殊的用途。它们是从开发人员的角度编写的。这意味着,即使它们本质上是严格的,它们的一个主要焦点是放在实现部分,准确地说是使用 Python。

我为什么要写这些笔记?

我已经给出了上述论点的一个方面,但我只想在这里声明,我属于一类愚蠢的人,他们什么都不懂,除非他们试图向别人解释,还试图用手做。我写这些笔记的原因也是试图向我自己解释量子力学和量子计算的神秘而迷人的主题。

顾名思义,它们是纯粹的笔记。这意味着,他们可能有涂鸦,错误,不成熟的想法和解决方案。尽管如此,这些笔记确实有一个有用的特点。我可以回头看看它们并改正我的错误(并在我改正的时候更新它们),同时(希望)像我这样的人也能跟着做并从中受益。

另一方面,我不会给任何人任何其他的理由去遵循这些笔记。我不会告诉你“量子计算将会改变一切。你需要掌握它,它是下一个“数据科学”(我们没有证据,除了一类问题,QC 实际上提供了超越经典计算的任何好处)或“RSA 处于危险之中,让我们拯救它”或诸如此类的事情。量子力学和量子计算本身就是非常有趣和迷人的学习科目。我在学习它们的时候很开心。我只想尽可能地分享快乐。仅此而已。

我已经对高中水平的数学有了基本的了解,比如基础代数,基础集合论,三角学。任何其他数学形式都将在途中推导出来。

好吧,你相信了吗?那我们跳进去吧!

我们的旅程从复数开始

我们记得复数,对吗?在高中数学的某个阶段,到处都是那些看起来很有趣的数字和符号?它们是什么?更重要的是,为什么我们(事实上地球上所有的量子力学和量子计算文献)需要它们?让我们稍微回到基础。我们从下面的等式开始。

在计算机科学中,我们称这些方程为“多项式”。现在,这可能不是显而易见的,但是如果我们稍微思考一下,我们会发现,我们可以通过指定系数来唯一地表示一个多项式。作为一个例子,上面的一个是多项式 P(x) = {1,-1 }({ x 的最高次幂的系数,然后是下一个,…直到常数项})看着多项式我们可以说 P ⊂ ℝ,即p 的成员取自所有实数的集合。关于多项式,我们通常会问的另一件事是——“它的根是什么?”根是方程的解。他们可以是很多人。像下面这样解上面的方程

给了我们等式的两个根。例如+1 和-1,它们正好在ℝ.的范围内到目前为止一切顺利。比方说,当我们试图解决

这给了我们√3。啊!我们有麻烦了。我们有一个⊂ ℝ,它的根不是来自 r。数学上我们说——“ℝis不是代数闭的”。

当我们试图解决时,问题变得更糟

因为根是… √-1,在平方根符号下有一个负数违背了我们的标准代数直觉,然而我们试图求解的方程是有效的,因此我们需要一种方法来表达这些新的数字。这就是我们发展虚数概念的原因。虚数,记为 i ,定义为√-1。复数是这样一个数,它有两个分量,一个实数,一个虚数。

如果我们仔细研究,我们会发现,真正“代数闭”的数的集合是ℂ,也就是所有复数的集合。这是一个非常重要的属性。我们将会看到在进行量子计算时,我们如何从中受益。形式上我们说——“任何系数来自ℂ的多项式,都有ℂ".的根

查看以下麻省理工开放式课程的精彩视频,进一步了解复数在量子力学中的重要性。

复数代数

一个复数通常是这样表示的——a+Ib 这里我们说 a 是复数的实部, b 是复数的虚部。我们可以在一个复数上定义如下

设 z = a +ib 是一个复数,那么 Re{z} = a,Im{z} = b,这样我们就得到了实部和虚部。

我们可以定义两种基本运算,例如对复数的+和*(加法和乘法)。它们看起来如下

  • 要将两个复数相加,我们只需分别将实部和虚部相加。所以,如果 a+ i b 和 c+ i d 是两个复数那么它们的和可以写成——(a+b)+I(c+d)。如果我们用 Z1 和 Z2 来表示它们,那么从复数之和的定义中可以清楚地看出 Z1+Z2 = Z2 + Z1
  • 为了将上述两个复数相乘,我们所做的是简单的乘法,然后重新排列(记住 i = -1)。看起来是这样的——(a+Ib)(c+Id)=(AC-BD)+I*(ad+BC)。同样清楚的是,Z1 * Z2 = Z2 * Z1

一旦我们定义了加法和乘法,我们就可以问这样的问题:“什么是加法恒等式?”"什么是乘法逆运算?"等等。有些答案很直接。加法恒等式是 0+ i 0。a+ i b 的加法逆是-a +i (-b)但是乘法呢?嗯,稍微想一想,我们就能看出乘法恒等式是 1+ i 0。利用 Z * (1/Z) = 1+0 i 的恒等式我们可以求出乘法逆。我们可以验证,复数ℂ的集合在这两种运算下形成了 。(如果你不知道什么是 字段 ,那么你可能想看看这里的)

关于复数,我们还需要了解其他一些事情。

  • 共轭——复数 Z 的共轭写为 Z 上面的一条杠,通过改变复数分量的符号来定义。所以 a+ i b 的共轭是 a- i b
  • 一个复数的模数——设 a+ i b 是一个复数那么模数定义为√ (a +b)。我们把它写成复数旁边的两条平行线。比如— |Z|。利用共轭的定义和乘法是如何定义的,很容易说明√( Z *共轭(Z)) = |Z| = √ (a +b )

我们在定义复数代数的各个方面时所做的选择,以及它自己的性质,当我们第一次看到它们时,可能看起来有点武断,但如果我们研究复数的几何,那么它看起来一点也不武断或随意。我们将在这些笔记的下一页看到这一点。

第一页到此为止。在下一页,我们将看到复数的几何以及一些 Python 代码(毕竟这是给 Python 程序员的一个提示)。如果你喜欢这个音符,请尽可能多的鼓掌。这对我将是鼓舞人心的。

来源

  1. 计算机科学家的量子计算
  2. 量子纠缠的数学 —布兰道、哈罗等。
  3. 虚数视觉指南——更好的解释。
  4. 量子力学的本质第二部分:复数
  5. 麻省理工学院 8.04 量子物理 I,2016 年春季

这里是第二部分,如果你喜欢这个就继续吧:)

Python 程序员的量子计算笔记:复数的几何

原文:https://towardsdatascience.com/quantum-computing-notes-for-a-python-programmer-geometry-of-complex-numbers-469a6265e0c7?source=collection_archive---------21-----------------------

Polar representation of 1+2i

你好,欢迎回来!在本系列的前一期中,我们看了复数代数。在现在的这幅中,我们将看到它的几何解释。我们还将探索一些 Python 代码来表示复数的各个方面。

如何在二维平面上表示一个复数

复数有一种直观简单的方式来表达自己,几何。从物理学的角度来看这也很有趣。这种表示复数的方式最初是由法国数学家 Jean-Robert Argand 于 1813 年提出的,因此它被称为 Argand 图以纪念他的贡献。

事情是这样的。如果我们有一个复数 z = a+ i b,那么我们可以用 X 轴表示 Re{z},Y 轴表示 Im{z}。看起来是这样的。

Argand Representation of a+ib

它说,如果我们从原点开始,然后在 X 轴上移动“a”的距离,然后沿着 Y 轴移动“b”的距离,那么我们就到达了由 a+ i b 表示的点,它非常简洁优雅。但它的用处不止于此。这与乘法规则相结合,将为我们提供一个非常有用的工具来毫不费力地执行旋转和缩放。但是为了做到这一点,我们需要理解如何以极坐标形式表示复数。

Polar form of complex number

与帖子相关的所有代码都可以在本笔记本中找到

从上图和使用基本的三角学可以清楚地看出

x = r * cos θ 和 y = r * sin θ。

然后利用简单的毕达哥拉斯法则我们也可以推断

r= |x+Iy | =√(x+y)

θ = arctan(y/x)

如果我们现在使用这些关系,那么我们可以重写

x+Iy = r * cos(θ)+Ir * sin(θ)= r (T27)cos(θ)+Isin*(θ))**

在这里,我们要停下来,记住数学最著名的公式之一,欧拉公式。它只是简单地说了以下内容—

Euler’s Formula

这是杰出的。因为它将指数函数与三角函数联系起来。(要想简单直观地证明这一点,你可以查看由而非小熊猫发布的这篇帖子。这基本上取决于泰勒级数展开。).利用这个公式,我们可以把最后一个方程改写成下面的形式

其中 Z = a+ i b(或者 x+ i y 或者随便你怎么说:),我们已经定义了 r 和 θ。

用复数乘一个东西是什么?

嗯,很简单,把一个数乘以一个复数,把它旋转复数的角度。让我再告诉你一遍——

  • 将一个数乘以一个复数,将该数旋转复数的角度。

假设我们有一个复数 1+ i 2。它可以用下图来表示

现在我们想把它旋转 45 度。嗯,如果我们计算的话我们会看到,45°角的复数是 1+ i 。因此,如果我们将 1+2 i 乘以 1+ i ,我们将执行 45°旋转。但是…

我们是 Python 程序员

没错!我们不喜欢这么多手工的东西。我们宁愿用 Python 编写一个优雅的解决方案来为我们完成这项工作。女士们,先生们,我们提出的“旋转”功能旋转一个复数的任何给定的角度。

import mathdef rotate(number, degree):n = numberreturn (math.e**(math.radians(degree)*1j)) * n

对之前给定的数字应用“旋转”。我们得到下面的图(我显示了原始数字和旋转后的数字)

Rotating a given number by 45º

等等,那个“1j”是什么?

Python 是一种非常强大的语言,像许多其他东西一样,它也支持开箱即用的复数。python 中定义复数的方式是在虚数部分附加一个“j”(为什么“ j ”?为什么不是那个熟悉的“”?那个我没看懂)。事情是这样的

c = 1+2j
print("c, Re{c} = %d Im{c} = %d and Length : "%d" % (c.real, c.imag, abs(c)))

“abs”给出了复数的长度(意思是√ (x +y ))

“c.real”给出实部,“c.imag”给出虚部。

角度怎么弄?

内置的复杂数据类型非常方便,但也非常基本。它不支持一些高级操作。为此,我们有“cmath”(复杂数学的缩写)模块。为了得到一个复数的角度,我们将使用“cmath”中的“phase”函数

import cmathc = 1+2j
cmath.phase(c)

趣味活动:用 Python 证明欧拉恒等式

我们知道著名的欧拉恒等式(也被称为数学中最美的方程)

Euler’s Identity

下面是一行代码,使用 Python 验证了这一点

import math
print ((math.e**(math.pi*1j)).real + 1)

它将打印“0.0”

查看下面的笔记本,了解详细的代码示例

这次到此为止。我知道这是一个非常基本和简短的介绍复数,但是,我希望你喜欢它。您可以随时查阅高级资料(在资料部分列出)进行进一步阅读。

感谢您的阅读。如果你喜欢这篇文章,请尽情鼓掌,这会鼓励我写更多。我们将在第三部分再次见面,届时我们将讨论量子力学的一个中心思想:线性。

来源

  • 计算机科学家的量子计算
  • 虚数视觉指南——更好解释。
  • 复数的几何 —汉斯·施韦德菲格
  • 量子力学的本质第二部分:复数

联系我!(如果你愿意)我很乐意听到你的反馈。

用 Python 实现量子物理可视化

原文:https://towardsdatascience.com/quantum-physics-visualization-with-python-35df8b365ff?source=collection_archive---------2-----------------------

在这个博客上,我决定复习一些大学水平的量子化学,来推导电子轨道。额外有趣的部分是,我们将会可视化波函数和电子概率..用 Python!

薛定谔方程

1926 年,Erwin Schrodinger 提出了著名的波动方程,将系统的能量与其波动特性联系起来。因为它在氢原子上的应用相当复杂,我们将首先用波动方程来求解盒中粒子。用 1D 表示的薛定谔波动方程是

可视化盒子中的粒子

现在,为了简化我们的方程,我们假设盒子中有一个粒子。

Particle In A Box

盒子里的粒子问题并不对应于任何真实的化学系统。在我们的上下文中,它的用处在于它阐明了几个量子力学特征。势垒处的势能设为无穷大(即粒子不能逃逸),势垒内的势能设为 0。在这些条件下,经典力学预言,粒子在盒子的任何部分都有相等的概率,粒子的动能允许有任何值。考虑到这个假设,我们得到了粒子在势垒处和盒子内部的能量的不同方程。

在势垒处,V 是无穷大,因此粒子不存在:

在盒子内部,V 是零,因此波可以具有任何有限值:

在盒子里,我们可以重新排列方程式如下:

正如我们在上面看到的,波函数是这样的,如果微分两次,应该给出相同的函数乘以 e。正弦函数具有这种行为。

现在,我们需要评估常数α和α的值。对于α,我们使用势垒处的波动方程,其中波函数等于 0。

现在代入α的值:

我们可以通过要求波函数归一化来确定 A 的值。这是因为,粒子一定存在于盒子的某个地方。因此,在盒子中找到粒子的概率之和是 1:

代入这些值,最终的波和能量方程为:

使用 Python 可视化能量和波函数:

import matplotlib.pyplot as plt
import numpy as np#Constants
h = 6.626e-34
m = 9.11e-31#Values for L and x
x_list = np.linspace(0,1,100)
L = 1def psi(n,L,x):return np.sqrt(2/L)*np.sin(n*np.pi*x/L)def psi_2(n,L,x):return np.square(psi(n,L,x))plt.figure(figsize=(15,10))
plt.suptitle("Wave Functions", fontsize=18)for n in range(1,4):#Empty lists for energy and psi wavepsi_2_list = []psi_list = []for x in x_list:psi_2_list.append(psi_2(n,L,x))psi_list.append(psi(n,L,x)) plt.subplot(3,2,2*n-1)plt.plot(x_list, psi_list)plt.xlabel("L", fontsize=13)plt.ylabel("Ψ", fontsize=13)plt.xticks(np.arange(0, 1, step=0.5))plt.title("n="+str(n), fontsize=16)plt.grid() plt.subplot(3,2,2*n)plt.plot(x_list, psi_2_list)plt.xlabel("L", fontsize=13)plt.ylabel("Ψ*Ψ", fontsize=13)plt.xticks(np.arange(0, 1, step=0.5))plt.title("n="+str(n), fontsize=16)plt.grid()plt.tight_layout(rect=[0, 0.03, 1, 0.95])

请注意,在一些区域中,ψ和ψ*ψ在相同的区域中都为零。这就是所谓的节点。轨道的能级不是连续的。它们存在于不同的层次,由节点的位置来表示。此外,随着 n 值的增加,盒子内部的波密度也增加。

可视化轨道

现在,为了得到关于量子数的波动方程,它需要以下 3D 格式:

现在,变量的分离取决于原子的类型,这太复杂了,无法在这篇博文中讨论。相反,我们将直接为绘图编写解决方案。下面,我们将使用氢原子的 R 和 Y 的函数,而不用推导它们。

首先,让我们看看 1s 轨道:

1s 波函数揭示了当我们远离原子核时,电子出现的概率呈指数下降。它也揭示了一个球形。

import matplotlib.pyplot as plt
import numpy as np#Probability of 1s
def prob_1s(x,y,z):r=np.sqrt(np.square(x)+np.square(y)+np.square(z))#Remember.. probability is psi squared!return np.square(np.exp(-r)/np.sqrt(np.pi))#Random coordinates
x=np.linspace(0,1,30)
y=np.linspace(0,1,30)
z=np.linspace(0,1,30)elements = []
probability = []for ix in x:for iy in y:for iz in z:#Serialize into 1D objectelements.append(str((ix,iy,iz)))probability.append(prob_1s(ix,iy,iz))#Ensure sum of probability is 1
probability = probability/sum(probability)#Getting electron coordinates based on probabiliy
coord = np.random.choice(elements, size=100000, replace=True, p=probability)
elem_mat = [i.split(',') for i in coord]
elem_mat = np.matrix(elem_mat)
x_coords = [float(i.item()[1:]) for i in elem_mat[:,0]] 
y_coords = [float(i.item()) for i in elem_mat[:,1]] 
z_coords = [float(i.item()[0:-1]) for i in elem_mat[:,2]]#Plotting
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x_coords, y_coords, z_coords, alpha=0.05, s=2)
ax.set_title("Hydrogen 1s density")
plt.show()

从上面的电子密度图中很难看出。然而,你可以看到它是球形的。当我们离中心越远,密度就越小。一般来说,截止点是当电子出现的概率为 99%时。

对于其他 spdf 轨道,也可以得到相同的密度图。希望这篇博客已经激发了你对量子物理和 Python 编程的兴趣!关于基于 python 的可视化的更多内容,请查看我的博客:基于 Python 的 Matplotlib 绘图

四分卫

原文:https://towardsdatascience.com/quarterbacks-82a1ace17311?source=collection_archive---------7-----------------------

这是另一个关于幻想作品的四集系列,部分链接到我之前的“破碎”系列。在这个系列中,我将关注每个团队的幻想作品。具体来说,每个位置的幻想 12 强球员和其他幻想 12 强球员在同一支球队打球的比例是多少。从这个系列赛开始,我将着眼于四分卫的位置。请关注本系列的下三篇文章,关于跑卫、外接球手和紧逼端。

问题

在其他三个技能位置上,fantasy QB1 与其他 12 强玩家的游戏比例是多少?换句话说,有百分之多少的 fantasy QB1 玩家也玩 fantasy RB1、WR1 或 TE1?

数据

为了这项研究,我找出了自 2000 年以来每个位置上排名前 12 的球员。从那里,我发现哪些 QB1 也和另一个 12 强幻想玩家在同一个队里玩。为了澄清,以下是 2016 年前五大 QB:

最后三列中的任何一列的“1”意味着 QB 也在该位置上与前 12 名球员一起比赛。最后三列中的“0”意味着 QB 没有在那个位置上与前 12 名球员一起比赛。例如,Aaron Rodgersplayed 使用了 12 强的梦幻接球手,但没有使用 12 强的梦幻跑锋或严密的末端。另一方面,柯克考辛斯打了一个前 12 名的梦幻紧密端,但没有打前 12 名的梦幻跑卫或接球手。自 2000 年以来,每一个排名前 12 的 QB 都是如此。

结果

在你深入阅读这个图表之前,让我解释一下发生了什么。首先,你会注意到我把前 12 名幻想四分卫分成了三个子类别:整体(第一类)、上半部分(第二类)和下半部分(第三类)。每个聚类有三个条形,每个条形代表一个技能位置(RB、WR、TE)。每个条形显示了每个位置前 12 名玩家的百分比,假设他们玩的是幻想 QB1。每个条形上方的数字是每个子类别中幻想 QB1 的预期数量,这些 QB1 将与该条形各自位置上的前 12 名幻想玩家一起玩。

例如,图表的这一部分对应于上面的第一个分类,它是整个子类别。这个集群显示了有多少 QB1 将在其他三个技能位置上与另一个 12 强幻想玩家一起玩。每个条形上方的数字是将在该条形位置与另一名前 12 名玩家一起玩的幻想 QB1 的预期数量。例如,我们可以预计大约五个幻想 QB1 也玩一个幻想 RB1(蓝色条)。此外,我们可以预计大约六个幻想 QB1 的发挥要么幻想 WR1 或 TE1(橙色和灰色酒吧)。

现在您已经理解了图表,我们可以看看第二和第三个子类别,即上半部分和下半部分。当我们将前 12 名分解为前 6 名和后 6 名时,分布稍微有些倾斜。例如,我们可以预计大约 3-4 个前 6 名 QB 使用 fantasy WR1,而只有 2-3 个后 6 名 QB 使用前 12 名 fantasy receiver。在紧尾位置,数字也是类似的,我们可以预计有三个前 6 名 QB 与 TE1 一起玩,而只有 2-3 个后 6 名 QB 与 TE1 一起玩。至于跑卫,划分相当均匀,前 6 名和后 6 名都有大约 2-3 名 QB1 使用 RB1。

解释和结论

这是什么意思?首先,我们可以期待更多的 QB1 玩家玩梦幻 WR1 或 TE1,而不是 RB1,这是有道理的。除非进攻是非常动态的,也就是去年的猎鹰队,否则传球比赛的成功通常会给跑动中的比赛带来打击。如果一个球队的 RB1 也是一个很好的传球接球手,就像猎鹰队进攻中的德文塔·弗里曼一样,那会很有帮助。然而,从这个意义上来说,去年似乎是一个异数,因为只有 5 个 QB1 与 fantasy WR1 一起比赛,但有 7 个 QB1 与 fantasy RB1 一起比赛。这可能是由于跑卫位置的“复兴”,特别是后场的 3 人后卫是很好的接球手。这种趋势还会继续吗?过去几年表明它不会,但它有一个机会,现在在联盟中打球的老黄牛。

我试图找到前 12 名 QB 和其他前 12 名玩家之间的额外相似之处,但总体来说,这似乎非常随机。在很大程度上,你可以依靠某个 QBs 来完成 QB1,同时也支持至少一个 WR1 或 TE1。亚伦·罗杰斯、汤姆·布拉迪和德鲁·布里斯都是 QB1 的常客,他们也一直支持 WR1 或者 TE1。卡森·帕尔默、埃利·曼宁和马特·莱恩都支持 WR1,但这并不总是让他们成为 QB1。然而,当他们作为 QB1 完成时,他们总是支持 WR1。有一个四分卫特别让我印象深刻:菲利普·里弗斯。在里弗斯手下,充电器从来没有幻想过 WR1(抱歉基南艾伦)。事实上,充电器上一次 WR1 是在 2000 赛季之前。然而,里弗斯是 TE1 的永久支持者。难道不是安东尼奥·盖茨(很快就是亨特·亨利)吗?

总的来说,我们可以预计大约一半的 QB1 支持 12 强梦幻接收机或紧端。我们还可以预计,前 12 名 QB 中约有 5 名将使用 fantasy RB1,但鉴于跑锋力量的转移,这一数字可能会增加。总而言之,顶级 QB 相对来说是可预测的,它们的顶级接收者或紧密末端通常会顺其自然。QB 排名的下半部分更不可预测,因此并不总是支持前 12 名的幻想接收机。至于苏格兰皇家银行,其在 12 家顶级 QB 中的分布相当均匀,甚至比接收方更难预测。和 QB1 一起玩的 RB1 通常也是通过空气获得产量的主力,或者他们的 QB 勉强进入前 12 名。

感谢阅读,请务必关注本系列的下一篇文章,关于跑卫,接下来是接球手和紧逼端。敬请期待!

原载于 2017 年 9 月 18 日【dynastyfootballfactory.com】

在 Hadoop 中有效地查询数据,满足您对数据科学的渴望

原文:https://towardsdatascience.com/query-data-effectively-in-hadoop-to-feed-your-hungry-data-science-ideas-c0a23fc4b9e0?source=collection_archive---------5-----------------------

Elephants in safari

我的公司的大数据越来越大,Hadoop 是 2015 年的热门话题,顺应这一趋势,我的公司决定从使用 Netezza 迁移到使用 Hadoop。因为我很久以前就在科技新闻中读到过 Hadoop,所以我对即将到来的迁移感到兴奋,并且想玩一玩这个新玩具。

从蜂巢到黑斑羚

在 2016 年末和 2017 年,我进入了我们的 Hadoop 环境,开始使用 Hive、Impala、Spark SQL 为我的分析项目广泛查询 HDFS 数据。在 Hive 中进行了几次查询后,我开始发现 Hadoop 比我预期的慢(比 Netezza 慢)。我的同事提醒我,Hive 是为大批量 map reduce 作业设计的,而不是为快速分析查询设计的。后来,由于内存问题和其他问题,我的 Hive 作业开始失败,我不得不使用许多设置,如''设置 MapReduce . map . memory . MB = 9000;set MapReduce . map . Java . opts =-xmx 7200m;‘让我的蜂巢工作正常运转。在我的 Hive 作业中,我使用了两个以上的设置来实现正确的配置和期望的性能。

使用 Hive 设置促使我获得关于 Hadoop 架构和集群操作的知识。然而,分布式系统中的 DevOps 毕竟不是我的游戏。很快,我转向 Spark SQL 和 Impala 寻求更好的解决方案。在 Spark SQL 中,我面临类似的配置挑战(还记得 Spark config 设置命令吗?./bin/spark-submit --name "My app" --master yarn --conf spark.executor.memory=4 g myApp.jar)而我在 Spark SQL(这是 Spark 1.6)中运行复杂查询时遇到了失败。尽管 Spark SQL 可以无缝连接查询数据和建模数据,如下面的代码片段所示:

data = sqlContet.sql("select outcomes, label1, lable2 from sampleTable") labeled_data = data.map(lambda line: LabeledPoint(line[0],line[1:])) training, test = labeled_data.randomSplit([0.6,0.4], seed=1) model=LogisticRegressionWithLBFGS.train(training, intercept=1,validateData=1)

我最终选择了 Impala 作为我的主要查询工具,因为我发现 Impala 不仅比 Hive 和 Spark SQL 快,而且只需要最小的性能调优开销。

当然,我不能不小心使用黑斑羚。为了获得良好的 Impala 性能,我需要仔细制定查询策略,并努力管理元数据。在长时间运行的作业中,黑斑羚不如 Hive 可靠,因此我会将黑斑羚的作业重写到 Hive 中,以用于生产目的。下面的链接是一篇比较 Hive、Impala 和 Spark SQL 的 IEEE 文章。这篇文章大部分支持我所经历的。

[## Hive、Impala 和 Spark 的性能比较 SQL - IEEE 会议出版物

大数据中的快速查询对于挖掘有价值的信息以提高系统性能非常重要。至…

ieeexplore.ieee.org](http://ieeexplore.ieee.org/document/7334737/)

查询工具选择及更多

这三种查询技术在大数据生态系统中都有自己的位置,但是当涉及到数据科学工作的迭代和探索方面时,我确实认为 Impala 等快速查询可以最有效地帮助数据科学家为他们的数据科学实验选择和整合数据源(然后使用 Spark SQL/Spark 进行建模,使用 Hive 进行生产级数据管道)。大的东西有很多小的部分。为了实现大的飞跃,我们需要快速测试小步骤的能力。在查询工具选择决策上,既要考虑其在大数据环境下的性能,也要考虑其在中等数据环境下的性能,既要考虑批处理模式下的性能,也要考虑交互模式下的性能。

数据科学家对数据、洞察和模型非常感兴趣,而 DevOps 或 DataOps 对他们的吸引力并不大。我认为减少开发工作对数据科学家来说是可取的,他们可以把更多的时间花在他们的增值上。我花在为 Hive 寻找合适的内存设置上的时间并不是很有趣。今天,我的公司在内部使用 Hadoop,我的公司可能很快就会开始在云中使用 Hadoop。许多大数据云平台承诺最小开发运维。这听起来很棒,但我愿意在接受之前仔细评估这个承诺。

在模型创建生命周期中,数据准备非常耗时。好的查询工具可以帮助我们更快地建立模型,因此我们应该给予查询工具更多的关注。在这里分享我的经验和观点,我也有兴趣从读者那里了解潜在的不同体验。在下面留下评论或者直接给我发 Twitter 消息@yuzhouyz。

为迈向数据科学而写作

原文:https://towardsdatascience.com/questions-96667b06af5?source=collection_archive---------0-----------------------

最后更新于 2023 年 3 月

与更广泛的受众分享您的概念、想法和代码

About us — Photo by Mia Baker

新作者

首次与 TDS 分享您的作品之前,您需要了解的所有信息:

  1. 为什么会成为投稿人?
  2. 提交规则
  3. 指引
  4. 长篇帖子、专栏和在线书籍
  5. 如何才能有所贡献?
  6. 常见问题

当前作者

为已经用 TDS 出版的作者提供的资源和建议:

[## 如何充分利用你作为 TDS 作者的经历

我们的资源和常见问题快速指南

towardsdatascience.com](/how-to-make-the-most-of-your-experience-as-a-tds-author-b1e056be63f1)

为什么要成为投稿人?

走向数据科学公司经营一个独立的媒体出版物。我们正在寻找作家提出专注于数据科学、机器学习、人工智能和编程的最新内容。如果你喜欢写这些话题,请继续读下去!

用你的文章接触更广泛的读者。我们是世界上最受欢迎的数据科学博客之一,也是拥有超过 60 万追随者的最受欢迎的媒体出版物。

以下是我们为确保你的文章能被尽可能多的读者所接受而做的一些事情:

  • 我们有一个自定义域(towardsdatascience.com,而不是 medium.com/towards-data-science),可以帮助你的文章带来更多的流量。
  • 我们与 Medium 密切合作,确保 TDS 中的故事符合 Medium 的编辑和发行标准,因此 TDS 中的故事经常会进一步发行。
  • 我们在出版物的页面和社交媒体上展示我们的内容: Linkedin 和 Twitter 。
  • 我们发送以故事和作家为特色的时事通讯。

通过 中等合伙人计划 挣钱。作者可以选择对 TDS 上的故事进行计量,并通过媒体合作伙伴计划基于媒体成员的参与度来赚钱。“计量”是指让一个故事有资格在 Medium 的计量付费墙后面赚钱。

作为媒体合作伙伴计划的一部分,作者保留他们通过媒体帐户获得的 100%的收入。但是,中等合作伙伴计划不是由 TDS 管理的,我们不会直接向自愿投稿的投稿人支付费用。

您将仍然是您作品 的唯一所有者,并且可以随时删除它,甚至在我们发布它之后。我们的编辑和社区提供的反馈将出现在你文章的相关位置。你可以拒绝或回复他们。

提交规则

在提交你的文章之前,有一些基本的事情你需要知道。确保你很好地阅读了每一点,并理解它们,因为通过向 TDS 提交文章,你同意遵守所有这些。

  1. Medium 的 规则 服务条款 适用于面向数据科学(TDS),因为它是一个媒体出版物。在提交文章之前,请务必阅读。
  2. 我们发布的每篇文章都采用了 媒体的策展方针 这意味着如果你的帖子质量不够高,不符合指导原则,我们不会将它发布到数据科学上。
  3. 请花几分钟时间熟悉一下我们的 作者使用条款和条件 ,以及我们的 隐私政策——它们规定了贡献者和 TDS 之间的关系。
  4. 请不要一次提交超过三个故事。为了确保及时回复所有作者,我们要求您一次最多只向我们发送三个故事,并等待我们的回复,然后再发送下一个故事。如果你写了一个更长的系列,你可以一次发完,但是请在你的第一个帖子里留个便条让我们的团队知道。
  5. 你可以对已发表的文章做一些小的编辑,只要他们尊重我们的规则和指导方针。此外,您可以随时从我们的出版物中删除您的文章。
  6. 您与我们分享的任何文章必须完全是您自己的原创作品;你不能把其他作家的话当成你自己的话来呈现,我们也不允许人工智能生成文本,即使你是促成其创作的人。
  7. 我们可能会直接编辑您的内容,以纠正基本的拼写错误,并更新最少的格式设置。此外,我们可能会删除来源不明的图片。
  8. 我们可以以任何理由删除你在数据科学上发布的任何文章。如果我们这样做,你的内容将不会丢失,但仍然托管在 Medium.com 和重定向到那里。
  9. 如果我们的编辑团队发现一处或多处违反我们的规则,我们可以从我们的出版物中删除您和您的所有文章,并将它们报告给 Medium。

指导方针

如何让你的文章准备出版!

我们的目标是在创新、信息和哲学之间取得平衡。我们想听听你的意见!但是我们确实要求,如果你不是一个专业作家,你在准备你的文章时考虑以下几点。我们想发表人们想读的高质量、专业的文章。

1.你的故事是一个需要被讲述的故事吗?

动笔之前,先问问自己:这个故事是不是一个需要讲的故事?

如果你已经读了很多文章讨论同一个问题或者解释同一个概念,在写另一篇文章之前要三思。如果你有一个激进的、新的观点,我们想听听你的意见……但是,我们需要你说服我们,你的文章是与众不同的,能打动我们的读者。

相反,如果你的文章涉及一个服务不足的领域或提出一个新的想法或方法,这正是我们所追求的!

2.你的信息是什么?

从一开始就让我们知道你的主要信息是什么。给你的作品一个简洁的介绍,告诉我们:

  • 你的小说创意是什么?
  • 我们为什么要关心?
  • 你打算如何证明你的观点?

一旦你解决了这个问题,你就可以随心所欲地交谈了,但是要不断地回到中心信息,给我们一个可靠的结论。

请记住,《走向数据科学》不是你的个人博客,请保持敏锐和切题!

3.在互联网上,没有人知道你是一只狗

你有了一个新的想法或做事的新方法,你想告诉社区并开始讨论。太棒了,这也是我们想要的,但我们不会想当然地认为你知道你在说什么,或者我们应该不加批判地相信你说的话……你必须说服我们(你的观众):

  • 主题很重要
  • 有一个缺口需要填补
  • 你有答案了
  • 你的解决方案有效
  • 你的想法是基于想法和证据的逻辑发展
  • 如果你给我们一个教程,告诉我们为什么人们需要使用这个工具,为什么你的方法比已经发表的方法更好。

你可以通过解释背景、展示例子、提供实验或者只是展示你从各种来源提取的数据如何让你综合这个新想法来做到这一点。

有反对你的观点或发现的论点吗?解释为什么那个解释与你的想法相冲突,为什么你的想法在上面。

4.你有没有一个有深刻见解的小标题?

如果你向上滚动到这一页的顶部,你会看到一个标题和副标题的例子。你的文章需要有一个短标题和一个长副标题,告诉读者你的文章是关于什么的,或者为什么他们应该阅读它。你的标题有助于吸引潜在的读者,并使你的意图清晰。为了保持一致并给读者最好的体验,我们不允许标题或副标题全部大写。我们也要求你避免在你的标题和副标题中使用脏话。

当你的副标题位于标题正下方且格式正确时,它会出现在一些帖子预览中,这有助于提高你的点击率。要在 Medium 上正确设置字幕格式,请将其打出,突出显示文本,然后在弹出窗口中单击两个 t 中较小的一个。

5.是什么让你的帖子对读者有价值?

一篇成功的帖子有一个明确的目标,并且会兑现它的承诺。如果你的标题告诉我们你要解开一个复杂的算法,展示一个新库的好处,或者带领我们通过你自己的数据管道,确保这篇文章的其余部分能够完成。这里有一些建议可以帮助你计划和执行一篇精心制作的文章:

1。决定你的主题是什么——什么不是 如果你不确定你的帖子将会是关于什么的,当你的读者阅读它时,他们知道的机会很小。定义你的文章要解决的问题,并坚持下去:任何与你文章的核心无关的东西都应该被剔除。

2。根据你的主题制定一个清晰的计划 ,为你的文章勾勒出一个清晰的结构,并记住它将遵循的整体结构。请记住,你的主要目标是让你的读者参与进来并保持良好的导向,所以考虑格式以及如何将主题分成易于理解的部分永远不会太早。考虑沿途添加章节标题,使你的结构清晰可见。

3。使用清晰的、行动驱动的语言 如果你仍然在寻找作为数据科学作者的个人声音,一个好的开始就是保持事物的干净、清晰和易于理解。

如果你的文章充满了中性的、一般的动词(如 be、have、go、become、make 等。),尽量混入更精准的动作动词。当有意义时,使用具体的、生动的描述词,而不是沉闷的描述词(例如,根据上下文,你可以用“无摩擦”、“可访问”或“直截了当”来代替“容易”)。

在与 TDS 分享之前,不要忘记校对几次你的草稿——寻找拼写、标点和语法问题,并尽最大努力改正它们。如果你需要一些外部支持,像 Grammarly 这样的工具可能并不完美,但它们会有所帮助;请一个信任的朋友来看一看从来都不是一个坏主意,大声朗读或聆听你的帖子也不是一个坏主意。

如果你想在基础知识之外扩展你的工具包,互联网上有很多很好的写作资源。这里有一些想法可以帮助你开始:

  • 为学术期刊写作的 10 个技巧。守护者
  • 来自成功作家的 6 条最佳建议
  • 史蒂芬·平克的风格感

4。包括你自己的图像、图表和 gif 图片让你的读者理解你的要点的最有效的方法之一就是用你引人注目的视觉效果来说明它们。

例如,如果你在谈论你建立的数据管道,文本只能带你到这里;添加图表或流程图可以使事情更加清晰。如果你正在讲述一个算法或另一个抽象的概念,用图表、图画或 gif 来补充你的口头描述,使它更加具体。(如果你使用的是其他人创作的图片,你需要仔细地找到并引用它们——阅读下面的图片指南,了解更多细节。)

一个强大的视觉组件会吸引你的读者的注意力,并引导他们阅读你的文章。这也将帮助你作为一个作者发展个人风格,在媒体上增加你的追随者数量,并在社交媒体上吸引更多的关注。

6.你的代码和方程式显示得好吗?

TDS 读者喜欢修改您与他们分享的想法和工作流,这意味着在您的帖子中包含代码实现和相关等式通常是一个好主意。

为了使代码片段更容易访问和使用,避免截图。相反,这里有两个解决方案供您选择:

  • 使用介质的本机代码块&内联代码
  • 嵌入 GitHub gists

为了与你的读者分享数学方程式, Embed.fun 是一个很好的选择。或者,您可以使用 Unicode 字符并上传结果方程的图像。

当你在文章中包含代码或等式时,一定要解释清楚,并围绕它添加一些上下文,以便所有层次的读者都能理解。

要了解更多关于在你的媒体文章中使用这些嵌入和其他内容,请查看这个资源。

7.检查你的事实

每当你提供一个事实,如果它不是不言自明的,让我们知道你从哪里学到的。告诉我们你的来源是谁,你的数据来自哪里。如果我们想进行对话,我们需要达成共识。也许你说的一些事情会引发一场讨论,但是如果我们想确保我们没有误解,我们需要回到原文,自己阅读,以防我们错过了拼图中的一个重要部分,这使得你说的一切都有意义。

8.你的结论是否切中要害,不具有推广性?

请确保你在文章的结尾包含一个结论。这是帮助你的读者回顾并记住你所讲述的要点或观点的好方法。你也可以用你的结论链接一篇原创帖子或者几篇相关文章。

请不要要求鼓掌,不要包含三个以上的链接到以前发表的文章。读者知道他们可以点击你的个人资料来查看你的所有帖子,他们知道他们可以关注你,所以没有必要请求它。

向您的媒体档案或社交媒体帐户添加额外链接是可以的,但请避免使用行动号召(CTA)按钮。

对于您的参考文献,请遵守以下格式:

【X】n .姓名,职务(年份),来源

例如,您的第一个参考应该是这样的:

[1] A. Pesah,A. Wehenkel 和 G. Louppe,(2018),NeurIPS 2018 元学习研讨会

9.你的标签够精确吗?

你的标签越具体,读者就越容易找到你的文章,我们也越容易对你的文章进行分类并推荐给相关读者。

我们可能会在发布前更改一两个标签。我们这样做只是为了让我们的不同部分与我们的读者相关。例如,我们希望避免将一篇关于线性回归的文章贴上“人工智能”的标签。

10.你有惊艳的形象吗?

一个伟大的形象会吸引和激发读者。这就是为什么所有最好的报纸总是展示令人难以置信的图片。

你可以这样做,为你的帖子添加一个精彩的特色图片:

  • 使用。Unsplash 上的大部分内容都是可以不用征得同意就可以使用的。你可以在这里了解更多关于他们的执照

** [## 中等+不光滑

Unsplash 上的每一张照片,现在都有介质版。

medium.com](https://medium.com/unsplash/medium-unsplash-2fee8d662dd1)

  • 自己拿一个。几乎可以肯定的是,你的手机足以捕捉到你周围的凉爽图像。你甚至可能已经在你的手机上有了一张图片,这将是你文章的一个很好的补充。
  • 做一个很棒的图。如果你的文章涉及数据分析,花些时间制作至少一张真正独一无二的图表。可以试试 R,Python,D3.js 或者 Plotly。

如果您决定为您的文章中使用的图像购买许可证,请注意我们只允许在以下许可证下使用图像:(I)不过期;以及(ii)可在 TDS 出版物上用于商业目的。您有责任确保遵守许可使用条款。您还必须在图像下方包含一个标题,如下所示,或按照许可提供商的其他要求:“图像通过【您的姓名】下的【许可提供商的姓名】获得。”最后,请给我们发电子邮件,告知我们所购买许可的收据或其他证据的副本,以及相应的许可使用条款。

如果你选择使用人工智能工具(如 DALL E 2、DALL E、Midjourney 或 Stable Diffusion 等)为你的文章创建图像,你有责任确保你已经阅读、理解并遵循了该工具的条款。您在 TDS 上使用的任何图像都必须获得商业使用许可,包括人工智能生成的图像。并非所有的人工智能工具都允许将图像用于商业目的,有些需要付费才能使用。

你用 AI 工具生成的图像不能侵犯其他创作者的版权。如果人工智能生成的图像与现有的版权图像或虚构角色(如哈利·波特、弗雷德·弗林斯通等)相似或相同。),不允许在 TDS 上使用。使用你的最佳判断,避免人工智能生成的图像复制或接近模仿另一个作品。如果有疑问,使用图像搜索工具——像谷歌镜头、 TinEye 或其他——来检查你的图像是否与现有作品过于相似。我们还可能要求您提供您在 AI 工具中使用的文本提示的详细信息,以确认您没有使用受版权保护的作品的名称。

您的文本提示不能使用真实人物的名字,如果您的图像中有真实人物(无论是名人、政治家还是其他任何人),也不能使用。

请记住引用你的图片来源,即使你没有法律义务这样做。如果您自己创建了一张图片,您可以在标题中添加(图片作者)。无论您决定采用哪种方式,您的图像源应该如下所示:

(Left) Photo by Marco Xu on Unsplash | (Middle) Photo by Nubia Navarro (nubikini) from Pexels | (Right) Image by Micha Sager from Pixabay

(Left) Photo by the author | (Middle) Photo from Toronto Machine Learning Summit (TMLS), 2018. Reposted with permission | (Right) Plato in his academy, drawing after a painting by Swedish painter Carl Johan Wahlbom, Public Domain.

你的图片应该有来源和链接。如果您自己创建了图像,您可以添加“按作者分类的图像”。

如果你创作了一幅受现有图片轻微启发的图片,请添加标题“图片由作者创作,灵感来自出处[包含链接]。”如果您已经编辑了现有的图片,请确保您有权使用和编辑该图片,并附上标题“图片来源[包含链接],经作者许可编辑。”

危险区🚩

未经所有者明确许可,请勿使用您在网上找到的图像(包括徽标和 gif)。将源添加到图像并不授予您使用它的权利。

11。你从哪里得到的数据?

走向数据科学团队致力于创建一个尊重数据科学作者、研究人员和读者的社区。对于我们的作者来说,这意味着尊重他人的工作,注意尊重与图像、出版材料和数据相关的版权。请始终确保您有权收集、分析和展示您在文章中使用的数据。

有很多很好的免费数据来源。尝试搜索大学数据库、政府开放数据网站和国际机构,如 UCI 欧文机器学习库、美国政府和世界银行开放数据。不要忘记那些保存着与物理、天体物理、地球科学、体育和政治等领域相关的特定数据的网站,如 CERN 、 NASA 和 FiveThirtyEight 。

TDS 是由商业实体 Medium 托管的商业出版物。因此,在将您的文章提交给我们之前,请验证您的数据集是 许可用于商业用途的 ,或者获得使用它的书面许可。请注意,并非我们列出的网站上的所有数据集都可以使用。无论您从哪里获得数据,我们都建议您仔细检查数据集是否允许商业使用。

如果你不确定自己是否有权将其用于商业目的,可以考虑联系所有者。许多作者收到一封精心设计的电子邮件后会得到快速、积极的回复。解释您打算如何使用这些数据,分享您的文章或想法,并提供 TDS 的链接。当你得到许可时,请将一份副本发送到 publication@towardsdatascience.com给我们。

如果您计划使用 web 抓取来创建自己的数据集,这一点尤其重要。如果网站没有明确允许出于商业目的的数据抓取,我们强烈建议您联系网站所有者以获得许可。没有明确的许可,我们不能发表你的作品,所以请通过电子邮件转发给我们一份。

有时候,简单的效果最好!如果您只是想要一个数据集来解释算法是如何工作的,您总是可以创建一个人工的或模拟的数据集。这里有一个快速的教程,和一篇文章,它使用了一个你可能会觉得有帮助的模拟数据集。

请记住添加一个链接到存储数据集的站点,并在您的文章中注明所有者/创建者。理想情况下,这是在第一次提到数据集时完成的,或者在文章末尾的资源列表中完成。请仔细遵循您在网站上找到的与归属相关的任何说明。如果您已经创建了自己的人工或模拟数据集,提及这一点也很重要。

我们知道解释许可证可能具有挑战性。你有责任确保在 TDS 发表的文章中展示你的数据和发现,但如果你遇到困难,请联系我们的编辑团队寻求帮助。我们宁愿在您项目的早期阶段与您合作,而不是因为数据集许可问题而不得不拒绝您完成的文章。

12.你尊重过媒体的指导方针吗?

我们发布的每篇文章都采用了 Medium 的监管指南。这意味着,如果你的帖子质量不够高,无法进行管理,或者没有遵循管理指南,我们不会将它发布到数据科学上。

[## 媒体的策展指南:作家需要知道的一切

我们的编辑策展团队每天审查数以千计的故事。我们有超过 35 名策展人,他们拥有各种各样的…

help.medium.com](https://help.medium.com/hc/en-us/articles/360006362473-Medium-s-Curation-Guidelines-everything-writers-need-to-know)

13。你的内容是原创吗?

虽然我们确实接受已经发布的内容(例如,在您的个人博客或网站上),但我们的重点是向读者推广和分享新的原创内容。这意味着,通过首先(或独家)在 TDS 上发布您的文章,您将有更大的机会出现在我们的出版物、我们的社交媒体渠道和我们的时事通讯中。

我们喜欢原创内容,因为这是我们的观众从未见过的东西。我们希望尽可能多地接触新材料,并保持 TDS 的新鲜和最新。

原创性也意味着你(和你的合著者,如果有的话)是你文章中每一个元素的唯一创造者。任何时候你依靠别人的话,你必须引用和引述他们适当,否则我们认为这是一个抄袭的例子。这当然适用于人类作者,但也适用于人工智能生成的文本。我们一般不允许任何由 TDS 上的 ChatGPT 之类的工具创建的语言;如果您的文章讨论了这些工具,并且您希望包括您生成的文本示例,请尽量减少这些示例,引用它们的来源和您使用的提示,并且非常清楚(例如,通过使用引号)人工智能生成部分的开始和结束位置。

14.在提交帖子之前,您收到任何反馈了吗?

养成在发表文章前向朋友寻求反馈的习惯。在那篇文章上花了这么大力气,你不会想让一个愚蠢的错误把读者推开。

15.您的媒体简介是否已正确完成?

请附上你的真实姓名、一张照片和一份简历。我们不发表匿名作者的文章——当读者将你的文字与一个真实的人联系起来时,更容易与他们建立信任。

使用你的个人资料来介绍你自己、你的专长、你的成就——优化它将有助于你与你的受众发展一种有意义的关系,而不仅仅是一篇帖子。如果你不确定你的简历应该包括什么,这里有一些有用的建议,告诉你如何确保简历既有效又有吸引力。

如果你是一家公司,并希望与我们一起发表,请注意,我们几乎只发表来自一个真实人物的媒体简介的文章。

16.你好点了吗?

花一分钟思考一下你目前为止所做的工作,以及你希望发表的文章。你给谁带来了什么价值?与你以前发表的文章相比,这篇文章在哪些方面更好或更差?

长篇文章、专栏和在线书籍

有很多话要说?很好。我们喜欢深入复杂的话题,我们的读者也是如此。以下是你如何在 TDS 上发表长篇文章、专栏和在线书籍的方法。

长格式帖子

我们喜欢长篇大论!如果你的文章阅读时间少于 25 分钟,我们建议你不要把它分成多个片段——保持原样。一篇文章可以让读者更容易地搜索和找到他们需要的所有信息,也不太可能错过你论点的重要部分。

要创建更流畅的阅读体验,您可以添加目录来引导读者阅读您的文章。添加高质量的图像和大量的空白也是一个好主意——长文本不一定是一堵文字墙。

我们会定期在我们的深度潜水页面添加最吸引人和最有想法的长篇帖子。

如果你的帖子的阅读时间超过 25 分钟,或者如果你打算在多篇文章中关注同一主题并持续更长时间,你可以创建自己的 TDS 专栏。只需要三个步骤:

  1. 为你的帖子添加自定义标签。这个标签必须是独一无二的,并能反映你项目的主题。每次你发布带有那个标签的帖子,它都会被添加到你的专栏登陆页:towards data science . com/tagged/【你的标签】。
  2. 给你的帖子添加一个踢球者。就像在你的标题上面加了一个副标题。
  3. 将你的 kicker 链接到你专栏的登陆页面。

如果您在这个过程中遇到任何问题,请在这里告诉我们,我们将帮助您创建它。如果你想看看专栏是什么样的,可以看看 Callum Ballard 的音乐和 Kate Marie Lewis 的社交距离。

您可以创建一个 TDS 专栏,并邀请多位作者投稿。只要让你的同事知道你决定使用哪个标签,他们就可以在他们的文章中添加相同的标签。这里是我们团队的一些例子。

在线书籍

如果你有一个开放式的话题,打算写一段时间,专栏是一个很好的形式。另一方面,如果你的想法有一个有限的、确定的范围,并且从一篇文章到下一篇文章有一个清晰的进展感,你可能想创作一系列感觉更像在线书籍的文章。这是我们推荐使用的格式。

保持每篇文章(或“章节”)的阅读时间在 12 到 25 分钟之间,目标是一个系列至少有 5 篇文章(但可能不超过 16 篇)。您可以在每篇文章中添加指向前面或后面项目的链接,例如,在引言和/或结论中。

要发布您的在线图书,您可以一次性将所有文章提交给我们的编辑团队,或者在完成每篇文章后逐一提交。我们将对它们进行审查,并在它们出现时发布,因此请在您的草稿中添加一个快速的私人注释(最好添加到您的标题中,我们不太可能会错过它),让我们知道您的帖子是计划中的在线图书项目的一部分。

请确保每篇文章或在线书籍章节都遵循与 TDS 发布的任何其他帖子相同的准则和规则。如果你决定向第三方出版商出售或独家授权你的书,你必须确保他们同意你继续用 TDS 出版这本书。如果您没有此类同意,您有责任从 TDS 出版物中删除您的内容。

如何提交文章?

注意:如果你在 TDS 上的最新文章在 2020 年 1 月 1 日之前发表,请通过我们下面的在线表格提交你的下一篇文章。随着 TDS 近年来的发展,我们已经更新了我们的指南和作者术语,您需要在与我们一起发布下一篇帖子之前查看它们。

要成为作家,请使用我们的 表格 发送您的文章。请注意我们只在介质上工作。我们不校对你的博客、PDF 或谷歌文档上发表的文章。此外,由于我们收到的提交量很大,我们不能保证对提交的每篇文章都进行回复。

Contribute

如果您对我们的在线表格有问题,您可以通过电子邮件向 publication@towardsdatascience.com 发送您文章的链接。请确保遵循下面列出的说明:

  • 不要通过电子邮件向我们发送您已经通过我们的表格发送的文章。
  • 虽然我们有一个开放的提交政策,我们不接受或发表所有提交给我们的文章。由于我们收到的邮件数量,我们无法保证回复每封邮件。
  • 请注意我们只在介质上工作。我们不校对你的博客、PDF 或谷歌文档上发表的文章。
  • 我们只发表遵循 媒体的策展方针 的文章。
  • 在电子邮件中附上您的简历或 LinkedIn 个人资料的链接
  • 使用您的专业或学术电子邮件地址。这有助于我们验证您的个人资料和简历。

最后,一旦你向我们发表了你的第一篇文章,我们将把你作为投稿人添加到 TDS 媒体出版物中,你将能够直接通过媒体提交后续文章

常见问题

  • 我把文章提交给 TDS 会怎么样?
  • 我可以复制帖子吗?如果原文章是外媒,是。但是不要重复你已经在媒体上发表的文章。
  • 我可以写我公司的产品吗?
  • 我的帖子被拒绝了,你能告诉我为什么吗?
  • 我可以付费出版吗?不

我们所有的常见问题**

为数据科学快速研究熊猫

原文:https://towardsdatascience.com/quick-dive-into-pandas-for-data-science-cc1c1a80d9c4?source=collection_archive---------0-----------------------

Pandas — Data Science Fundamentals

Pandas 是一个基于 NumPy 构建的开源 python 库。它允许您进行快速分析以及数据清理和准备。想到熊猫的一个简单方法就是简单地把它看作 Python 版的微软 Excel。

我喜欢熊猫的一个很酷的地方是,它可以很好地处理来自各种来源的数据,例如;Excel 表格、csv 文件、sql 文件甚至网页。

安装熊猫

如果您有 Anaconda ,您可以简单地从您的终端或命令提示符安装 Pandas,使用:

conda install pandas

如果您的计算机上没有 Anaconda,请使用以下命令从您的终端安装 Pandas:

pip install pandas

熊猫数据结构

系列

Series 是一维数组,与 NumPy 数组非常相似。事实上,Series 是建立在 NumPy 数组对象之上的。series 与 NumPy 数组的不同之处在于 Series 可以有一个访问标签,使用该标签可以对其进行索引。

import numpy as np
import pandas as pd

以下是创建熊猫系列的基本语法:

my_series = pd.Series(data, index)

从上面可以看出,data可以是任何对象类型,比如字典、列表,甚至是一个 NumPy 数组,而index表示系列将被索引的轴标签。

我们将从各种对象类型中创建一个系列。

注:需要注意的是,index 轴是可选的。意思是,你可以决定不传进去。如果没有索引被传递,Pandas 将创建一个默认值index,其值[0, ..., len(data) - 1]如下所示:

每当从 Python 字典创建 Series 时,Pandas 将键设置为 Series 的index,并将值设置为相应的数据点,如上面的out[24]所示。

Pandas 系列与 NumPy 数组的区别在于 Pandas 系列可以保存各种对象类型。

从系列中抓取信息

我们可以像使用 python 字典一样从一个系列中获取信息:

对数列进行算术运算

基于index完成系列操作。当我们使用任何数学运算,如-、+、/、*,pandas 使用index 的值进行计算。结果值随后被转换成浮点数,这样你就不会丢失任何信息。

从上面来看,熊猫在这个系列中找不到匹配的,它给了它一个NaN值。

数据帧

数据帧是二维数据结构,其中数据以表格形式排列,即以行和列排列。熊猫数据框使处理你的数据变得容易。您可以选择、替换列和行,甚至重塑您的数据。

以下是创建数据帧的基本语法:

pd.DataFrame(data,index)

让我们创建一个 5 行 4 列的随机数数据帧:

正如我们所见,上面的每个专栏实际上只是一个熊猫系列,它们都有一个共同的index。因此,可以肯定地说,数据帧是共享相同index的系列的集合。在下面的示例中,我们将从一个系列中创建一个数据帧:

从数据帧中选择列

使用括号符号[],我们可以很容易地从数据帧中抓取对象,就像处理 Series 一样。先来抢个专栏name:

因为我们获取了单个列,所以它返回一个系列。继续使用type()确认返回的数据类型:

如果我们获取多个列,结果将是一个数据帧:

向数据框架添加列

当创建一个新列时,您必须像它已经存在一样定义它。有数据框架的:

我们可以通过重新创建新列或从现有列添加新列,如下所示:

从数据帧中删除行/列

我们可以使用.drop()功能删除一行或一列。为此,我们必须为指定axis=0 ,为指定axis=1

值得注意的是,无论何时使用.drop() 方法,Pandas 都不会永久删除一行/一列,除非您告诉它这样做。这是因为熊猫不希望你意外丢失数据。

打电话df确认。要永久删除一行/一列,您必须像这样设置inplace=True:

选择数据帧中的行

要选择行,我们必须使用接受标签名的.loc[]或接受行的索引位置的.iloc[]来调用行的位置。

我们也可以像在 NumPy 中那样,通过指定我们想要的行和列,使用列符号:来选择行和列的子集。假设我们想要第'c'行的'Name’:

条件选择

Pandas 允许您使用括号符号[]进行条件选择。下面的示例返回其中'W'>0 : 的行

假设我们只想返回列'X'的值,其中'W'>0 :

继续尝试这个:df[df['W']>0][['X','Y']] ,你应该得到这个:

上述一行抽象也可以通过将其分解为多个步骤来实现:

my_series = df['W']>0
result = df[my_series]
my_cols = ['X','Y']
result[my_cols]

使用多个条件,我们可以通过使用逻辑操作符& (AND)和| (OR)来获得数据帧中的值。例如,要返回值,其中'W'>0'X'>1 使用:

重置数据帧的索引

当你的索引看起来不完全是你想要的样子时,你可以使用.reset_index()很容易地重置它。这将我们的 DataFrame 索引重置为名为index 的列,Pandas 的默认索引值[0, ..., len(data) - 1]是我们的新索引。

不出所料,.reset_index()不会永久重置索引,直到您指定:.reset_index(inplace=True)

设置数据帧的索引

类似地,我们可以通过使用set_index()函数来指定想要使用哪一列作为我们的索引标签。为此,我们将创建一个名为"ID'的新列,并将其设置为我们的新索引:

不像*.reset_index()*重置旧的索引并使用默认的熊猫索引作为我们的新索引,*.set_index()*完全覆盖旧的索引。

多级指标( MultiIndex) 和指标层次

多索引只是一个元组数组,其中每个元组都是唯一的。它可以从一个数组列表(使用MultiIndex.from_arrays)、一个元组数组(使用MultiIndex.from_tuples)或一组交叉的可重复项(使用MultiIndex.from_product)中创建。

让我们从一个 turple 创建一个 MultiIndex:

我们可以继续使用.loc[]从 MultiIndex 中获取行,如下所示:

正如我们所看到的,我们的数据框架df的前两列没有名字。我们可以像这样用.index.names给它们命名:

横切面的行列

使用.xs方法,我们可以很容易地选择多索引中特定级别的数据。例如,假设我们想要获取所有级别,其中Num = 22:

缺失数据

很多时候,当你使用 Pandas 读入数据并且有缺失点时,Pandas 会自动用一个NaN or Null值来填充这些缺失点。因此,我们可以使用.dropna()删除那些自动填充的值,或者使用.fillna().填充它们

假设我们有一个数据框架:

使用.dropna()方法,我们告诉 Pandas 删除任何有一个或多个缺失值的行或列。要删除一行,使用.dropna(axis=0).dropna(axis=1)删除一列。

注意,如果您没有指定轴,Pandas 默认假设您正在删除一行。

同样,使用.fillna()方法,我们可以用我们想要的值替换数据帧中缺失的值。让我们用10替换所有的NaN值:

我们也可以选择只填充特定列或行中缺少的值。让我们用平均值替换列'A'中缺失的值:

从上面可以看出,列'A'的平均值是 2.0,因此它用 2.0 替换了第二行。

同样,.dropna().fillna()不会永久出现,直到您设置了inplace=True

分组依据

Grouby 允许您根据列对行进行分组,以便您可以对它们执行聚合函数(如求和、均值、中值、标准差等)。

使用.groupby()方法,我们可以根据'Company' 列对行进行分组,并对其调用聚合函数.mean():

如你所见,我们的结果是每个公司的平均值。

计数

使用count() 方法,我们可以获得一个项目在数据帧中出现的次数。

形容

.describe()方法用于获得数据帧的概貌。它为我们提供了每个数据帧索引的摘要。

如果你不喜欢这个布局,你可以使用.transpose()方法得到一个不同的布局。

连接、合并和连接数据帧

串联

串联基本上将数据帧粘合在一起。当连接数据帧时,请记住,维度应该沿着要连接的轴匹配。拥有,数据帧列表:

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],'B': ['B0', 'B1', 'B2', 'B3'],'C': ['C0', 'C1', 'C2', 'C3'],'D': ['D0', 'D1', 'D2', 'D3']},index=[0, 1, 2, 3])df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],'B': ['B4', 'B5', 'B6', 'B7'],'C': ['C4', 'C5', 'C6', 'C7'],'D': ['D4', 'D5', 'D6', 'D7']},index=[4, 5, 6, 7]) df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],'B': ['B8', 'B9', 'B10', 'B11'],'C': ['C8', 'C9', 'C10', 'C11'],'D': ['D8', 'D9', 'D10', 'D11']},index=[8, 9, 10, 11])

我们可以使用pd.concat()方法连接它们:

因为我们没有指定希望在哪个轴上发生串联,所以默认情况下,Pandas 使用行轴。它把两行连接在一起。如果我们希望沿着列进行连接,我们必须设置axis=1:

注意这里我们有一堆缺失的值。这是因为 DataFrame 没有包含我们希望它连接的所有索引的值。因此,当使用pd.concat()时,确保您的数据正确包含轴上的所有信息。

合并

使用pd.merge()函数,Pandas 允许您像合并 SQL 表一样合并数据帧。合并数据帧的语法是pd.merge(left, right, how='inner', on='Key'left表示应该出现在左侧的数据帧,right表示应该出现在右侧的数据帧,how='inner'表示合并操作应该作为交集inner还是并集Outer来处理。最后,on='Key'表示发生合并的键列。在合并功能发生之前,该键列在所有数据帧中必须是相似的。

有两个数据帧都有一个key列,我们可以这样合并它们:

我们还可以通过简单地传递键来合并多个键:

加入

对于将两个可能索引不同的数据帧的列组合成单个数据帧,联接是一种更方便的方法。联接类似于合并,但不同之处在于联接方法发生在索引键而不是列上。

在数据帧中查找唯一值

唯一值就是数据帧中的不同值。在数据帧中查找唯一值有三种主要的有用方法。

使用.unique(),我们可以找到以下数据帧的col2中的所有唯一值:

我们可以选择使用.nunique()来计算数据帧中唯一值的数量,而不是显示唯一值:

最后,我们可以决定使用.value_counts()只返回一个惟一值在一列中出现的次数:

apply()方法

.apply()方法用于调用数据帧上的自定义函数。想象我们有一个函数:

在上面的例子中,我们将函数传播给列中的每个元素。我们还可以将内置函数应用于数据帧。假设我们想要得到col3中字符串的长度:

有时,您可能会定义一个最终只使用一次的函数。不用在几行代码中定义这样的函数,您可以简单地使用 lambda 表达式,这是该函数的简化版本。例如,我们可以用 lambda 表达式来表示上面ln[47]中的平方函数:

获取数据帧属性

属性是数据帧的列名和索引名。假设我们不确定数据帧中的列名是否包含空格字符,我们可以简单地获得它们的属性:

对数据帧进行排序和排序

假设我们想要显示数据帧,其中某一列以升序显示,我们可以使用.sort_values():很容易地对其进行排序

如您所见,col2中的值是从最低到最高显示的。还要注意index是如何连接到每一行的,这样信息就不会丢失。

查找空值

假设您有一个大型数据集,Pandas 使用.isnull():使得定位空值变得非常容易

透视表

您可能已经熟悉 Excel 中的数据透视表。数据透视表是汇总另一个表中数据的表。它使您能够自动对存储在一个表中的数据进行分组、切片、筛选、排序、计数、合计或平均。有数据框架的:

我们可以使用语法从它创建一个数据透视表:.pivot_table(data, values='', index=[''], columns=['']).其中values表示我们想要组成数据点的列,index是您想要对数据进行分组的列,columns表示应该定义数据帧的列。你可以在这里阅读更多关于数据透视表的内容。

在上面的例子中,我们得到了一些NaN值,因为对于那些特定的点没有匹配的值。

数据输入和输出

使用pd.read_方法,Pandas 允许您从各种来源访问数据,例如:excel 表、csv、sql 或 html。

要引用任何文件,你必须确保它与你的 jupyter 笔记本在同一个目录下。

读取 CSV 文件

使用pd.read_csv()我们可以将. csv 文件的内容输出为数据帧,如下所示:

写入 CSV 文件

我们可以创建一个数据帧,并使用.to_csv()将其存储在一个.csv文件中,如下所示:

要确认数据已保存,请继续阅读您刚刚使用pd.read_csv('New_dataframe')创建的 csv 文件。

从 Excel 文件中读取

Excel 文件是很好的数据来源。使用pd.read_excel()我们可以从 excel 文件导入数据。请记住,Pandas 只能导入 excel 文件中的数据,而不能导入宏、图像或公式。excel 文件中有宏、图像或公式会导致pd.read_excel() 方法崩溃。

假设我们有一个 excel 文件'excel_output.xlsx',让我们继续输出它的内容:

请记住,每个 excel 文件都包含一个或多个工作表。在我们的例子中,Sheet1指的是我们想要读取的'excel_output.xlsx'中的特定工作表。

写入 Excel 文件

就像我们对 csv 所做的那样,我们可以创建一个数据帧,并使用.to_excel()将其存储在一个.xlsx文件中,如下所示:

从 HTML 中读取

要从 HTML 文件中读取数据,需要安装 htmllib5、lxml 和 BeautifulSoup4。在您的终端运行中:

conda install lxml
conda install html5lib
conda install BeautifulSoup4

使用.read_html()让我们告诉熊猫从这个 html 页面读取表格。由于该页面中有不同的表,我们可以使用索引号[0, ..., len(tables) - 1]来访问我们想要的特定表。对于本例,我们将返回该页面中的第二个表。

本教程到此结束,恭喜!

如果您完成了本课,您应该对什么是 Pandas 以及如何使用它进行数据准备有很好的了解。你现在需要做的就是练习!练习!练习!。

有问题,遇到困难或者只是想打个招呼?请使用评论框。如果这个教程在某些方面对你有帮助,给我看一些👏。

快速绘画:世界上最大的涂鸦数据集

原文:https://towardsdatascience.com/quick-draw-the-worlds-largest-doodle-dataset-823c22ffce6b?source=collection_archive---------8-----------------------

谷歌的一个团队开始让猜字谜游戏变得更有趣,最终获得了世界上最大的涂鸦数据集,以及一个强大的机器学习模型。他们是怎么做到的?

什么是快速绘制?

“快,画!”是一款最初在 2016 年谷歌 I/O 上推出的游戏,在这款游戏中,一名玩家会被提示画出一个物体的图片,另一名玩家需要猜测这是什么。就像猜字谜一样。

2017 年,谷歌研究中心的 Magenta 团队将这一想法向前推进了一步,使用这个带标签的数据集来训练草图-RNN 模型,试图实时预测玩家正在画什么,而不是要求第二个玩家进行猜测。游戏已经上线,现在已经收集了超过 10 亿张手绘涂鸦!

让我们来看看来自快速绘制的一些绘图。这里我们看到西兰花被很多玩家抽中。

How would you draw broccoli?

请注意,不同的玩家对海洋的描绘略有不同。

浏览数据集可能非常有趣。如果你发现一些看起来不合适的地方,你实际上可以在这一页上修改它。会让数据对大家更好!

快速绘制数据集

该团队已经开源了这些数据,并且采用了多种格式。你可以在他们的 GitHub 页面了解更多信息。

有 4 种格式:首先是存储在。ndjson)格式。这些文件编码了每个涂鸦的全套信息。它包含每幅画的每一笔的计时信息。

还有一个简化版,存储格式相同(。ndjson),它应用了一些预处理来规范化数据。简化版也可作为二进制格式,以便更有效地存储和传输。有一些如何使用 Python 和 NodeJS 读取文件的例子。

第四种格式采用简化的数据,并将其呈现为 numpy 格式的 28x28 灰度位图。npy 格式,可以用 np.load()加载。

为什么是 28x28?嗯,它是任何现有的用于处理 MNIST 数据的代码的完美替代品。因此,如果你在寻找比 10 个手写数字更新奇的东西,你可以尝试处理 300 多种不同类别的涂鸦。

在快速绘制中使用 RNNs

如果你想变得有趣,使用完整的数据集(公平的警告,它相当大!),你可能想使用递归神经网络(RNN)来完成这项工作,因为它会从笔画的序列中学习。在一个奇妙的事件中,有一个专门针对在快速绘制数据集上使用 RNNs 的指南,所以如果你有兴趣尝试一下,请查看教程。考虑到训练时间,第一次可能只对数据的一个子集这样做:)

快速绘图的数据探索与可视化

如果您想进一步研究数据集,可以使用 Facets 可视化 quickdraw 数据集。Facets 团队甚至冒昧地将其放在网上,并给了我们一些预置来玩!你可以在这里进入页面。我们可以加载一些随机的椅子,看看不同的玩家如何从世界各地画出椅子。

All the chairs

我们还可以看到哪些画被认为是椅子,哪些没有被选中。有许多预置视图也值得一试,它们可以作为进一步分析的有趣起点。

感谢阅读本集云 AI 冒险。如果你喜欢这个系列,请为这篇文章鼓掌让我知道。如果你想要更多的机器学习动作,一定要关注 Medium 上的me或订阅 YouTube 频道以捕捉未来的剧集。更多剧集即将推出!

快速实现 Yolo V2 与 Keras!

原文:https://towardsdatascience.com/quick-implementation-of-yolo-v2-with-keras-ebf6eb40c684?source=collection_archive---------1-----------------------

I do not hold ownership to any of the above pictures. These are merely used for educational purposes to describe the concepts.

多年来,实时多目标定位一直是数字图像处理领域的一个大争论。随着深度学习和卷积神经网络的发明,这些努力已经产生了非常有前景的结果,训练有素的模型能够非常准确地检测许多类别的对象,这种能力现在已经掌握在我们手中。

在这篇文章中,我打算介绍一个著名的模型,称为 Yolo,代表“你只看一次”,由 Joseph Redmo 等人提出,该模型已经朝着对象的快速多本地化及其使用 Keras 的实现迈出了一大步,Keras 是一个高级深度学习库。

让我们首先看一下分类、定位和检测这三个术语之间的区别。我们经常在图像处理领域听到这些术语,它们在应用中各不相同。
分类 —指识别图像中是否存在给定对象。常见的例子:猫或不猫。
定位 —不仅指识别图像中是否存在给定对象,还指使用边界框来区分对象的位置。
检测 —简单地说就是在一幅图像中进行多次定位。

Yolo 正在解决图像中物体的检测问题,随着 Yolo V2 论文的发表,这一技术在该领域迅速推广。让我们看看约洛·V2 算法的主要步骤。这些可以指出如下:

  • 使用网格分割图像(例如:19x19)
    将图像分割成一个由更小图像组成的网格,可以更容易地检测到每个单元内的物体。
  • 在每个网格单元上执行图像分类和定位
    每个单元的向量表示检测到物体的概率,边界框的尺寸和检测到的图像的类别作为该步骤的输出给出。
  • 执行阈值处理,删除多个检测到的实例
    阈值处理选择概率最高的单元,以便选择更正确的边界框
  • 执行非最大值抑制以进一步细化方框
    非最大值抑制技术提供了一种便捷的方法,使用一种称为并集交集的计算来进一步细化结果

附加点-锚定框用于检测一个网格单元中的多个对象。与其他算法相比,这是约罗 V2 算法的一个特点。

Yolo 的第一个实现是由 Joseph Redmon 等人使用 C 语言中称为 Darknet 的模型提出的,随着该方法的发展,还构建了当前更流行的 ML 库(如 Tensorflow 和 Keras)的实现。

我的 Github 库在这里展示了一个使用 Keras 的算法的快速实现。使用该代码,任何人都可以用自己的图像进行测试,并深入了解其工作原理。关于它的安装和执行的所有细节可以在回购中找到。

请在您的应用程序中自由使用代码,并分享传播知识!

快速 ML 概念:张量

原文:https://towardsdatascience.com/quick-ml-concepts-tensors-eb1330d7760f?source=collection_archive---------3-----------------------

机器学习的基本构件简介

Tensorflow、Tensorlab、深度张量化网络、张量化 lstm……很多机器学习技术的名称中都嵌入了“张量”这个词,这并不奇怪。但是张量是什么呢?它们与机器学习有什么关系?在快速 ML 概念的第一部分,我的目标是提供一个简短而简明的张量是什么的总结。

Photo by Olav Ahrens Røtne on Unsplash

不要让“张量”这个词吓到你。它只不过是一个简单的数学概念。张量是将标量、向量和矩阵推广到更高维的数学对象。如果你熟悉基本的线性代数,你应该不难理解什么是张量。简而言之,一维张量可以表示为一个向量。你可能已经猜到,二维张量可以用矩阵来表示。

尽管很容易将张量概括为多维矩阵,范围从0N 维,但记住张量是动态的很重要。即张量在与其他数学实体交互时会发生变换。另一方面,矩阵并不总是具有这种性质。引用自 Steven Steinke 的精彩文章关于张量和矩阵的根本区别:任何秩为 2 的张量都可以表示为矩阵,但并不是每个矩阵都真的是秩为 2 的张量

张量运算

张量运算很简单。考虑以下张量:

a = np.array([[[4,1,2],[3,5,2],[1,6,7]][[2,1,0],[5,4,3],[6,8,9]][[1,2,3],[2,3,4],[5,5,5]]])
b = np.array([[[1,1,1],[2,2,2],[3,3,3]][[4,4,4],[5,5,5],[6,6,6]][[7,7,7],[8,8,8],[9,9,9]]])

很容易看出,两个张量的秩都是 3。也就是说,它们有三个轴。您可以通过 Python 中的以下代码来检查张量的维度

a.ndim
>>> 3

上述两个张量的相加产生一个张量,其中每个标量值是父张量中标量的元素相加。

print(a+b)
>>> [[[5,2,3],[5,7,4],[4,9,10]][[6,5,4],[10,9,8],[12,14,15]][[8,10,11],[10,11,12],[14,14,14]]]

如果你有兴趣了解更多关于张量运算的知识, Jason Brownlee 的优秀张量教程总结了包括张量点和 Hadamart 积在内的几种常见的张量运算。

机器学习中的张量

那么张量和机器学习有什么关系呢?

记住,大多数机器在没有任何数据的情况下无法学习。而现代数据往往是多维的。张量可以通过对多维数据进行编码,在 ML 中发挥重要作用。比如一张图片一般用三个字段来表示:宽度、高度、深度(颜色)。把它编码成 3D 张量是完全有意义的。然而,我们更多的是在处理成千上万的图片。因此,这就是第四个字段样本大小发挥作用的地方。一系列图像,如著名的 MNIST 数据集,可以很容易地存储在 tensor flow的 4D 张量中。这种表示方式可以轻松解决涉及大数据的问题。

Photo by Daniele Levis Pelusi on Unsplash

现实生活中的一个例子是,在大多数推荐系统中,基于模型的协同过滤方法,如矩阵分解,没有将上下文信息集成到模型中的灵活性。通过使用 N 维张量而不是传统的 2D 用户项目矩阵,研究人员开发了一个更强大的模型,提供上下文感知的推荐。近年来计算能力的提高也使得这些繁重的张量运算得以实现。

此时你可能会疑惑:为什么机器学习算法大多依赖向量和矩阵,而深度学习算法和神经网络大多依赖张量?一个简单的答案是,深度学习通常涉及数百个甚至数千个维度和领域。正如我们之前所讨论的,这最好用张量来表示,因为它们可以表示从N 维的任何东西。在计算机视觉问题中,如默克分子活动挑战,图像可以很容易地被分解成几百个特征。因此,张量可以最好地被视为在机器学习和深度学习的背景下包装和存储数据特征的容器。

感谢你阅读我的文章。

纽约市 2017 年地层快速说明

原文:https://towardsdatascience.com/quick-notes-on-strata-2017-nyc-9c92679fbed4?source=collection_archive---------7-----------------------

我现在明白为什么张量流是一件大事了

这是一种简洁的线性代数和优化方法,可以利用多个后端。它还附带了一系列由谷歌致力于这项任务的大量数学家开发的预扫描算法。

您可以将它用于传统的机器学习、基于非传统优化的任务(例如样条拟合)以及任何作为线性代数的工作。预计快速计算的下一件事是将更多的运算转换成线性代数。向 Ted Dunning 大声欢呼,感谢他带给我这个家。

Tensorflow 可能是谷歌云的杀手级应用

看起来大多数其他部署 tensorflow 的方式都是一种痛苦。如果你是一个开发者,我想是时候升级谷歌云了。

模型操作正在成为一件事

很多关于将机器学习投入生产的东西。因为模型(当前制作的)本质上是在一个环境中训练的,并且是永恒的和无空间的,所以当前的技术需要一种可操作的方法。

特别是,将您的模型训练方法简化为自动化管道。然后,为每一个新的环境进行再培训(就像一个诊所或一辆卡车一样精细)。

当输出预测的分布明显偏离训练集中的分布时,重新训练您的模型。重大差异标准是一个判断问题。

监控有效性——你的模型改变了人们的行为方式,这破坏了它的有效性。这对好的参与者(例如,医生决定让谁住院)和坏的参与者(例如,黑客试图欺骗你的黑客检测器)都是如此。

特别是在训练数据稀少的情况下,您需要考虑预测和训练的替代方法。David Talby 举了一个通过电子邮件流检测银行欺诈行为的例子。简单的分类器不起作用,因为类别(坏消息与好消息)是如此不平衡,以至于所有标准方法都会过度适应好的类别,并说每条消息都是好的(也许百万分之一是坏的)。相反,他和他的团队有一个回归预测不良概率,向(现有的)人工审查团队显示消息,并根据人类的反应进行重新训练。

模型设计者必须结合因果关系或 GTFO

有足够多的经验法则和足够多的 GPU,使用标准模型类型很快就会实现自动化。已经有商业工具和开源工具在很大程度上实现了自动调优。特征工程和模型类型选择即将实现自动化。

制作一个建模管道,接受标记的数据,并在其上训练一个模型,而不需要任何人工来理解功能或模型或调整它们,这将是一个标准的工程任务,在 5 年内完成,并在 10 年内完全产品化。这在很大程度上是因为当前的技术是纯粹的、无上下文的模式学习者。随着人类学习如何使用这些技术,开发的启发和技术正在作为他们自己的优化算法被操作,允许解决方案空间的自动导航。

数据准备不会消失。更好的工具是存在的,对于迭代缓慢的东西,人类将站在数据准备的一边。对于快速发展的事物,数据工程师将建立在线和自动化系统,至少将人工处理减少到可管理的数量。

关于即将发生的事情就说这么多。因果关系是正在发生的事情。

这至少有两个方面:

  1. 选择与基础过程相对应的数学模型;和
  2. 对基础流程的部分进行建模,以创建一个包含已知因果关系的完整模型

第一个很好的例子是由给出的,他通过用三次样条拟合数据来模拟期货交易量和波动性之间的关系。在这种情况下,该模型至少更易于训练,但也限制了所需的再训练量(因为样条线段对其相邻线段的影响随着样条中链接的数量而消失)。随着时间的推移,这一过程还会随着环境和市场的潜在变化而永远持续下去,因此样条曲线是这一过程的一个更自然的模型,而不是试图用一个巨大的多项式来拟合所有的时间。

并非巧合的是,现在另一个流行词是“可解释性”。有些供应商专注于理解标准非线性模型(最著名的是神经网络)的动态技术。来自 H2O 的演讲很有趣,也很聪明,如果你需要关心你的通用模型在做什么,你可能会想使用这些技术。然而,如果您确实选择使用实际上对应于底层流程的模型,那么解释经过训练的模型应该会容易得多。

第二个的一个很好的例子是一位演讲者,他的公司( VNomics )制造实体卡车的“数字双胞胎”。人们对这个讲座很感兴趣,事实上,我希望它能安排成一个为期一天的研讨会,但与此最相关的是,他的公司有卡车每个部件的性能模型(例如,这个卡车模型有这个特殊的传动系统和这个制动系统模型)。这些模型被用作第一步,以将传感器读数提取到特征中,这些特征被输入到更一般的燃料经济性回归模型中。通过这种方式,模型(a)结合了正在发生的事情的知识,而不是仅仅将原始数据放入模型中,并依赖回归模型进行分类;以及(b)提取模型本身是可组合和可重用的,允许每辆卡车具有定制的特征提取器流水线,而无需编写新代码。

这些“数字双胞胎”模型的第二个强大之处在于,它们可以用作物理模型中 A/B 测试变化的基线(例如,轮胎充气的不同方式)。同样,如果你想解释你的模型是怎么回事,故意设计特征提取和产生数据的东西的变化会有帮助。

不性感的技术仍然很重要

能力差距越来越大,后来者正在被甩在后面

当我们中的一些人在关于机器学习的操作方面的演示中明智地点头时,其他人正在参加 40 分钟的演示,基本信息是“这实际上很难,你的团队需要时间来提升技术”以及人们描述云基础设施上的数据仓库看起来像什么。

如果您的团队发现大数据很难,或者您想带着计划进入项目,请联系我。我和我的团队很乐意为你安排计划、培训和执行。

参展商包括许多销售解决方案以支持数据科学团队的人,以及与开源工具没有明显区别的商业内存分布式数据库,但真的没有人销售真正的 on-ramp 解决方案。值得注意的是,除了木桶之外,没有任何东西将端到端的执行联系在一起。天文学家 io 没有参展,尽管我认为他们是唯一一个试图在 ramp 上提供真实主机的团体。

有许多针对数据准备和数据发现的解决方案,但很少关注数据平面安全和控制。数据发现、编目和控制领域的开源解决方案仍然是主要供应商的可怕挡箭牌,或者在 herd (来自 FINRA)的情况下,这显然是一个功能非常全面的解决方案,但几乎没有文档。

我怀疑这一领域的低成本选择将是与编排解决方案相关的目录,如 AWS 的 Glue,或天文学家. io 。

关注业务案例

经验继续证明,数据工程或分析工作必须发生在业务案例的上下文中,以及对数据作为资产的持续承诺中。人们倾向于将“大数据”和“深度学习”视为神奇的仙尘,工程人员可以将仙尘洒在业务上,以实现神奇的结果。

不幸的是,事实并非如此,有些供应商很乐意向您销售基于这一前提的解决方案。公平地说,他们中的许多人,他们的解决方案可能会加速您的工程团队的进展,使他们免受架构错误的影响,但是您仍然有一个半生不熟的数据平台在寻找应用程序。

如果你确实在数据中看到了机会,但不太确定如何计划,请联系我。我和我的团队可以帮助您制定战略和产品愿景,建立成功的工程团队,并指导您选择最适合您的供应商和解决方案。

快速回顾,进入具有代理的嵌入式模型

原文:https://towardsdatascience.com/quick-review-to-leap-into-embedded-models-with-proxies-c6f39e24d06d?source=collection_archive---------16-----------------------

作为后续工作,我制作了一个 Jupyter 笔记本。这里收集的部分图片取自那里:【https://arxiv.org/pdf/1703.07464.pdf】https://github . com/rachuism/food-classifier-proxy-NCA/blob/master/visualization . ipynb 还有这里:

顾名思义,嵌入是为了让东西变得更小。在深度学习的情况下,它包括将项目(例如,电影、文本等)映射到低维实向量,使相似的项目彼此靠近。

所以让我们以一部电影的推荐系统为例。我们需要跟踪每个用户的口味来提取数据。但是,如果我们正在跟踪一组,例如,一百万部电影呢?对整个集合进行编码将如下所示:

Taken from Google’s developers course

这对于处理深度学习模型是非常低效的。相反,我们试图使用各种数学技术来减少这个空间的维数。下图显示了巨大的编码是如何“嵌入”网络的。

Taken from Google’s developers course

在我的模型的训练期间,嵌入大小被选择为 64。这就是为什么当张量被打印出来时,有 64 个元素塑造了它:

这个项目的另一个关键词是“代理”,在这个例子中,它是作为模型参数的一部分学习的。它努力将一个数据集表示成一个点。根据经验,在代理上公式化的学习问题表现出比其他度量学习方法更快的收敛。

作为一个帮助理解它的例子,让我们首先理解“三元组”的概念:有一个“锚”点 x ,我们想减少到另一个相似点 y 的距离,并增加到不同点z的距离。下图试图简化理解:

Taken from the aforementioned paper

让我们想象我们的定位点是孤立的红色圆圈,它离其余的圆圈较近,离星星较远。这是总结代理意图的最佳实例。在下面的方案中,右图显示了一个大点如何表示一组点。

Taken from the aforementioned paper

可以看出,代理充当每个点集的上限表示。在这些距离上计算损耗,试图保持 x 尽可能靠近 y 并尽可能远离z

资料组

该数据集由 20 个食物类别和每个类别的 100 张图像组成。所选的种类有苹果派、面包布丁、牛肉片、甜菜沙拉、巧克力蛋糕、巧克力慕斯、甜甜圈、贝奈特饼、本尼迪克特蛋卷、法式面包卷、汤团、虾和玉米粉、烤三文鱼、猪排、千层面、馄饨、煎饼、法式吐司、意大利肉酱面、泰式炒面。

链接到数据集(UPMC-20 国集团):http://visiir.lip6.fr/

培训和评估

下图解释了评估系统的工作流程。首先,将训练集提供给推荐算法,该算法产生可用于生成新预测的推荐模型。为了评估该模型,将保留的测试集提供给学习模型,其中为每个用户-项目对生成预测。具有已知标签的预测(真值)然后被用作评估算法的输入,以产生评估结果。

因为我只处理了 20 个类,所以我将其中的 50%用于训练集,50%用于评估

对于远程度量学习来说,类的数量很少,因为与类内变化相比,类内变化很大。这就是后来 NMI 抛出低值的原因。

预言。邻域成分分析

NCA 由一种监督学习方法组成,用于根据给定的数据距离度量将多元数据分类到不同的类中。(k 个最近邻居)。在“预测”步骤中,我使用:sk learn . metrics . pairwise . pairwise _ distances(X)来查找更接近我的查询的图像。

在这个例子中,我选择作为查询的图像是小菜一碟,经过一些转换(输入被调整为 256 × 256 像素,然后被随机裁剪为 227 × 227。像素的亮度已被缩放)看起来像这样:

UPMC20 dataset

对该照片的检索是来自同一类(蛋糕)的图像:

UPMC20 dataset

理解日志

纪元的数量已被设置为 20。有两个概念可以理解在“评估步骤”中损失是如何计算的

.log file

NMI:归一化互信息,定义为聚类和地面实况的互信息与其调和平均值的比值。它量化了通过其他随机变量获得的关于一个变量的信息量。

k 时回忆:k 时回忆是前 k 项推荐中相关项目的比例。所以在 R@1 的的情况下,它意味着相关项目出现在第一个位置的概率为 40%,在 R@8 的情况下,它意味着相关项目出现在前 8 个位置的概率为 84%。这就是为什么参数“K”越大,其召回率越大的原因。数学上可以定义为:召回@k =(推荐项目数@k 相关)/(相关项目总数)。

参考

[## 推荐系统的召回率和 k 精度

附例详细说明

medium.com](https://medium.com/@m_n_malaeb/recall-and-precision-at-k-for-recommender-systems-618483226c54)

不要大惊小怪使用代理的距离度量学习https://arxiv.org/pdf/1703.07464.pdf

伦理人工智能设计的快速押韵

原文:https://towardsdatascience.com/quick-rhymes-for-ethical-ai-designs-2f5afba090e7?source=collection_archive---------13-----------------------

我最近在读丹尼尔·卡内曼的《思考的快慢》,其中一部分讲述了如何写出令人难忘的信息。要点——人们记得押韵的东西。

我想我应该写几首关于伦理人工智能的押韵诗,希望下次你开始一个项目时会想到。

开始了。

喂你的人工智能偏向数据

稍后会显示出这种偏见

阿勒格尼州立大学曾经创造了一种算法来帮助警察,建议他们巡逻的路线以及他们应该停下来搜查的人。它偏向于检查黑人人口较多的社区。

为什么?这并不是因为黑人天生就有什么不好的地方。这是因为该算法是基于人类警察生成的数据集进行训练的。那些警察,不管是有意还是无意,都有自己的种族偏见。给人工智能输入同样的数据,它也会有偏差。

我们希望人工智能做出理性的决定,并帮助人类识别和避免偏见。因此,当你训练一个人工智能时,确保你使用的是无偏见的数据。

延伸阅读

弗吉尼亚·尤班克斯的《自动化不平等》

显示你的算法不透明

如果它的意思不明显

想象一下,你申请了一笔抵押贷款,而自动验证系统拒绝了你。你问它为什么,你得到的答案是;

那不是很透明…你想要的是简单明了的英语(或者任何最适合你的语言!),对其得出结论的原因的通俗易懂的描述。

如果处理得当,这对企业也有好处。算法如何工作的复杂性通常是一个区别点。我们被 Spotify、网飞和亚马逊这样的企业所吸引,部分原因是它们的算法能够很好地了解我们是谁,并做出明智的推荐。共享简单语言的含义和意图而不是代码保留了这一优势。

延伸阅读

未来生命研究所的透明可解释人工智能

无方向性的情报不好

如果我们自己的价值观不被理解

我们为什么要造 AI?为了人类的利益。即使我们变得自私,这也是为了至少一个人的利益。如果我们追求智慧或者追求智慧本身,却不知道我们人类的价值观是什么,也没有办法将其编码到系统中,那么它与我们的价值观相一致的机会就像是在瞎猜。

这个主题领域被称为人工智能对齐

延伸阅读

罗辛·沙阿的《校准通讯》

什么是我的 AI 调整

保罗·克里斯蒂亚诺所著《一切》

Nick Bostrom 的超智能

分享就是关怀

好吧,我扯掉了这个。但如果一个人或一家企业创造了能产生大量财富的人工智能,而这种财富是没人能追上的,特别是因为他们可以用这笔财富来打造一个更有能力的系统,那这笔财富就应该被分享。如果我们现在就这样做,那就太好了,就算没有人工智能(这是一厢情愿的想法),但如果我们考虑到一种技术可以创造比没有人工智能时我们所能创造的财富多几个数量级的财富,这个问题就会变得更加严重。

进一步阅读

机器人的崛起:马丁·福特的技术与大规模失业威胁

你还没有释放你的人工智能

你还有责任

除非在非常特殊的情况下,你在人工智能中创造意识,而我们没有达到这种状态的路线图,否则创造者对人工智能的所作所为负有伦理和道德责任。Virginia Eubanks 在这方面做了一些很好的工作——我们将自动化作为抽象的道德层。

进一步阅读

哈佛大学人工智能解释能力

你对合乎道德的人工智能有什么看法吗?请在下面发布!

对这个话题感兴趣吗?

加入会议小组 AI 道德伦敦

订阅我在 media上的博客

Quora x 柏林独角兽

原文:https://towardsdatascience.com/quora-x-unicorn-berlin-d04650c07641?source=collection_archive---------9-----------------------

CEO Adam D’Angelo describing Quora to the audience at Unicorn Berlin

在德国首都回答你的问题

在一个名为“ Unicorn ”的地方参加活动,你永远不知道会听到什么。

我很想看看柏林的合作空间,并从 Quora 首席执行官亚当·德安杰洛那里收集一些智慧的珍珠,他是联邦德国创业银行组织邀请来演讲的。我目前正在支持拜耳的 Grants4Apps 团队,该团队将创新的数字健康创业公司与制药机会联系起来。所以我喜欢抓住柏林的数字脉搏,此刻,它正涌动着到的能量。

但是回到晚上的嘉宾。也许你听说过 D ' angelo——一家叫做脸书的小公司的前首席技术官?如果你在德国这里搜索 Quora,你会收到一个等待列表邀请,但是下载应用程序。这是一个聪明的论坛,有至少 2 亿访问者的知识丰富、不断增长的社区来回答你的问题。

以下是来自 D'Angelo 的转述要点——这些要点引起了我的注意,可能对创新者和初创公司有所帮助。尤其是不限制自己想象力的重要性。

在产品上

个性化和机器学习:对用户有益的也对企业有益。Quora 特别重视这两个话题。但事实证明,很难教会机器识别讽刺。为了给用户创造一个安全的地方来提问,并期待高质量的答案,人类的努力(即 Quora 的 200 名员工,加上其用户对事情的报道)填补了机器学习还不能达到的地方。

国际化 b4 货币化

基本上,扩大你的用户群,然后担心美元。投资人要看用户。由于英语市场的激烈竞争,D'Angelo 希望专注于使英语产品尽可能的好和有用。通过他们在其他语言上的工作(到目前为止是西班牙语和法语),他们已经开始理解语言和文化的细微差别是如何影响用户兴趣和行为的。语言生态系统必须可持续发展。

投资建议?

来自 WestTechVentures 的主持人 Alexander klpin 厚脸皮地询问“投资建议”,例如,D'Angelo 在 Instagram 上有一些不错的预感。事实证明,最佳实践可以归结为依靠一个良好的网络,并坚持你所知道的游戏。

D'Angelo 以一种自我宣称的“随机”(但我要补充的是非常成功)的方式,在他有密切私人关系的地方进行投资。他根据他认识的人筛选选择,并且(对我们来说很可悲)远离生物技术,因为他认为其他人更了解这个领域。他坚持自己的优势:消费互联网和社交网络。很公平。目前为止创造了奇迹。

Smaller group conversation with Adam D’Angelo

问&一个见解

自然有机会,观众们向这位说话温和的技术大师提问。他们想知道至少四件事:

问:你是如何克服用户的痛点的?

答:通过听他们说。Quora 非常依赖 A/B 测试和用户研究作为良好的信息来源。做你的市场调查,真正了解你的市场。D'Angelo 回忆说参加了一次维基会议,这次会议极大地塑造了他的观点…

与许多实际用户交谈,记住有时他们的“想象力仅限于当前的挫折。”但是不要让你的梦想成真。

双 Q:作为 CEO 最艰难的时刻是什么?聊天机器人的兴起对你的产品有什么影响?

答:2011 年,Quora 的发展速度超过了其技术基础设施的承受能力。这导致了成长的烦恼,因为某些项目不得不被牺牲。人们在这些领域投入了感情,所以很糟糕。(我猜这是真的,因为他回答的时候声音真的很颤抖。我想所有观众都注意到了。)问题的第二部分:他对聊天机器人持“等等看”的态度,称带屏幕的设备比纯音频设备更有机会。他兴奋地强调,Quora 的重要趋势是机器学习和人工智能。

问:在脸书和 Quora 工作过,是什么让一个团队成功?

答:个人需要擅长他们所做的事情:工程和设计等。但他们也要善于在一个团队中,否则团队无法存在。你如何解决问题很重要。团队应该围绕使命和价值观保持一致,团队中的一个人应该对决策负责,即使这意味着艰难的权衡。

问:最后,Quora 关注错别字吗?

甲:目前没有。显然,答案的质量不是基于拼写,而是基于社区提供的内容。因为用户被鼓励使用他们的真实姓名和学术证书,这增加了讨论的真实性。Quora 团队似乎对如何分析回复更感兴趣,也许是训练一台机器来阅读、分类和引用它们。

活动结束后,人们聚在一起喝酒和交流。我遇到一个人,他刚从多伦多搬到柏林,在一家金融科技加速器工作。柏林一直吸引着国际人才和演讲者。

对于即将到来的独角兽活动,请查看:【http://unicorn.berlin/events/

如果你要去柏林露天科技,亚当·安吉洛将于 7 月 12 日 13:15 在 1 号演播室发表演讲。信息此处。

The memorable, iconic logo of Unicorn Berlin

R-CNN,快速 R-CNN,更快 R-CNN,YOLO —目标检测算法

原文:https://towardsdatascience.com/r-cnn-fast-r-cnn-faster-r-cnn-yolo-object-detection-algorithms-36d53571365e?source=collection_archive---------1-----------------------

了解对象检测算法

介绍

计算机视觉是一个跨学科领域,近年来(自 CNN 以来)获得了巨大的牵引力,自动驾驶汽车占据了中心舞台。计算机视觉的另一个组成部分是对象检测。目标检测有助于姿态估计、车辆检测、监视等。对象检测算法和分类算法之间的区别在于,在检测算法中,我们试图在感兴趣的对象周围绘制一个边界框,以在图像中定位它。此外,在对象检测情况下,您可能不一定只绘制一个边界框,可能有许多边界框表示图像中感兴趣的不同对象,并且您事先不知道有多少个边界框。

您无法通过构建一个标准卷积网络,然后构建一个全连接层来解决这个问题的主要原因是,输出层的长度是可变的,而不是恒定的,这是因为感兴趣对象的出现次数是不固定的。解决这个问题的简单方法是从图像中提取不同的感兴趣区域,并使用 CNN 对该区域中物体的存在进行分类。这种方法的问题是感兴趣的对象在图像中可能具有不同的空间位置和不同的纵横比。因此,你将不得不选择大量的区域,这可能会在计算上爆炸。因此,像 R-CNN、YOLO 等算法已经被开发来寻找这些事件并快速找到它们。

R-CNN

为了绕过选择大量区域的问题, Ross Girshick 等人。提出了一种方法,我们使用选择性搜索从图像中提取 2000 个区域,他称之为区域建议。因此,现在,你可以只处理 2000 个区域,而不是试图对大量的区域进行分类。这 2000 个区域建议是使用下面写的选择性搜索算法生成的。

Selective Search:
1\. Generate initial sub-segmentation, we generate many candidate     regions
2\. Use greedy algorithm to recursively combine similar regions into larger ones 
3\. Use the generated regions to produce the final candidate region proposals 

R-CNN

要了解更多关于选择性搜索算法的信息,请点击此链接。这 2000 个候选区域提议被扭曲成正方形,并被馈送到卷积神经网络,该网络产生 4096 维特征向量作为输出。CNN 充当特征提取器,输出密集层由从图像中提取的特征组成,提取的特征被馈送到 SVM 中,以对候选区域提议中的对象的存在进行分类。除了预测区域提议内对象的存在之外,该算法还预测四个偏移值,以提高边界框的精度。例如,给定一个区域提议,该算法将预测到一个人的存在,但是该区域提议中的那个人的脸可能已经被切成两半。因此,偏移值有助于调整区域提议的边界框。

R-CNN

R-CNN 的问题

  • 训练网络仍然需要大量的时间,因为你必须对每幅图像的 2000 个区域提议进行分类。
  • 它不能实时实现,因为每个测试图像需要大约 47 秒。
  • 选择性搜索算法是一种固定算法。因此,在那个阶段没有学习发生。这可能导致产生坏的候选区域提议。

快速 R-CNN

Fast R-CNN

前一篇论文(R-CNN)的同一作者解决了 R-CNN 的一些缺点,以建立更快的对象检测算法,它被称为快速 R-CNN。该方法类似于 R-CNN 算法。但是,我们不是将区域建议提供给 CNN,而是将输入图像提供给 CNN,以生成卷积特征图。从卷积特征图中,我们确定建议的区域,并将其扭曲成正方形,通过使用 RoI 池层,我们将它们重新调整为固定大小,以便可以将其输入到完全连接的层。根据 RoI 特征向量,我们使用 softmax 层来预测建议区域的类别以及边界框的偏移值。

“快速 R-CNN”比 R-CNN 更快的原因是,你不必每次都向卷积神经网络馈送 2000 个区域提议。相反,每个图像只进行一次卷积运算,并从中生成特征图。

Comparison of object detection algorithms

从上面的图表中,您可以推断出快速 R-CNN 在训练和测试会话中明显快于 R-CNN。当您在测试期间查看快速 R-CNN 的性能时,与不使用区域建议相比,包含区域建议会显著降低算法的速度。因此,区域建议成为影响快速 R-CNN 算法性能的瓶颈。

更快的 R-CNN

Faster R-CNN

上述两种算法(R-CNN 和快速 R-CNN)都使用选择性搜索来找出区域建议。选择性搜索是一个缓慢而耗时的过程,会影响网络的性能。因此,任等人。提出了一种对象检测算法,消除了选择性搜索算法,并让网络学习区域建议。

类似于快速 R-CNN,图像作为输入被提供给卷积网络,该网络提供卷积特征图。不是在特征图上使用选择性搜索算法来识别区域提议,而是使用单独的网络来预测区域提议。然后,使用 RoI 池层对预测的区域提议进行整形,然后使用 RoI 池层对提议区域内的图像进行分类,并预测边界框的偏移值。

Comparison of test-time speed of object detection algorithms

从上面的图表中,你可以看到更快的 R-CNN 比它的前辈快得多。因此,它甚至可以用于实时物体检测。

YOLO——你只能看一次

所有先前的对象检测算法都使用区域来定位图像中的对象。网络不会看到完整的图像。取而代之的是图像中包含物体的概率较高的部分。YOLO 或你只看一次是一个对象检测算法,与上面看到的基于区域的算法有很大不同。在 YOLO,单个卷积网络预测边界框和这些框的类别概率。

YOLO

YOLO 的工作原理是,我们把一幅图像分割成一个 SxS 网格,在每个网格中我们取 m 个边界框。对于每个边界框,网络输出该边界框的类概率和偏移值。具有高于阈值的分类概率的边界框被选择并用于定位图像内的对象。

YOLO 比其他物体检测算法快几个数量级(每秒 45 帧)。YOLO 算法的局限性在于它会与图像中的小对象进行斗争,例如它可能难以检测到一群鸟。这是由于算法的空间限制。

结论

计算机视觉会议每年都在观察新的激进概念,我想我们正一步一步地走向人工智能令人瞠目结舌的表现(如果还没有的话!).只会变得更好。我希望这些概念在这篇文章中变得清晰,谢谢:)

参考

  1. https://arxiv.org/pdf/1311.2524.pdf
  2. 【https://arxiv.org/pdf/1504.08083.pdf
  3. https://arxiv.org/pdf/1506.01497.pdf
  4. https://arxiv.org/pdf/1506.02640v5.pdf
  5. http://cs 231n . Stanford . edu/slides/2017/cs 231n _ 2017 _ lecture 11 . pdf

r 代表 GTFS——获得每条线路每小时的行驶次数

原文:https://towardsdatascience.com/r-for-gtfs-getting-the-number-of-trips-per-hour-for-each-line-4d22491e3944?source=collection_archive---------3-----------------------

我最近一直在 R 中处理 GTFS 文件,想分享一些我到目前为止学到的东西。

几周前,我的一个客户问我们是否可以根据一条线路每小时的行驶次数给他们的公交线路涂上颜色。为此,我首先要计算这个数字。

在本文中,我将解释如何使用 r 从 GTFS 中获取给定线路的出行次数。然后,我将展示如何将该信息导出到 Excel 并制作图表。

你可以从我的 GitHub 库获得完整的代码作为 HTML 或 R Markdown 。

什么是 GTFS?

如果你已经熟悉 GTFS,你可以跳到下一部分。

GTFS 代表“通用交通馈送规范”,是一个面向交通机构的世界知名开源标准。如果你属于公交行业,我敢肯定你已经知道你可以用它来管理信息的基本知识(这是公交机构如何与谷歌地图进行通信,等等)。如果你没听说过,想了解更多,推荐你看看他们的规格这里。

图书馆

如果您想完全按照本文中详细描述的脚本进行操作,您必须确保安装了以下库:

library(tidyverse)
library(pryr)
library(dplyr)
library(ggplot2)

您只需复制代码,在 RStudio 中运行它,就万事大吉了。

将数据导入 R

对于这篇文章,我使用了 GTFS 的 PTO(称为 EMT)公开提供的在这里。尽管如此,如果您愿意,您可以使用自己的 GTFS 来跟踪这篇文章。

一旦我们下载了文件,我们要做的第一件事就是把它导入到 r。因为 GTFS 文件实际上是。zip 文件,我们将使用下一个脚本对其进行解压缩,并将文件作为数据帧导入:

zip <- "/Users/santiagotoso/Descktop/transitEMT.zip"
outDir <- substring(zip, 1, nchar(zip)-4)dir.create(outDir)
setwd(outDir)unzip(zip, exdir = outDir)trips <- read_csv("trips.txt")
routes <- read_csv("routes.txt")
stop_times <- read_csv("stop_times.txt", col_types= cols(arrival_time = col_character(), departure_time = col_character()))

第一行代码是映射 zip 文件的位置(您应该根据自己文件的信息来更改它)。然后,在第二行代码中,我们定义了以。zip 文件:我们获取整个字符串并保留除最后 4 个字符之外的所有内容。zip)。像那样,‘outDir’其实就是“/Users/santiagotoso/Descktop/trans item”。

在第三行中,我们创建一个目录,按照‘outDir’中的定义进行放置和命名。最后,我们解压文件并读取。txt 文件在里面。

现在我们有四个数据帧,每个数据帧对应这个练习的一个相关文件:行程、路线和停留时间。

请注意,当导入“停止时间”时,我们强制将“到达时间”和“离开时间”变量转换为字符。其原因是,有些行程发生在午夜之后,格式类似于 26:45 小时。这变成了 R 中的 NA,我们通过将它们设为字符来避免这种情况。我们稍后会处理它们。

到目前为止我们有什么?

如果你习惯于和 GTFS 一起工作,你可能不需要这个部分。如果您仍在学习如何使用 GTFS 文件,现在花一点时间看看我们拥有的每个文件的信息可能会有所帮助,它们如何相互连接,以及哪个文件包含我们需要的信息,以获得一条线路每小时的行程数。

  • trips.txt: 该文件存储每个行程的高级信息。是 id,路线,方向,service_id,形状等。请注意,形状是由行程定义的,而不是由路线定义的。

  • routes.txt: 该文件存储每条路线的信息。是 id,长短名,颜色等。

  • stop_times.txt: 该文件存储每次行程的详细信息。更准确地说,每个行程的停靠点顺序以及每个停靠点的经过时间。它没有关于路线本身的信息,但是它通过 trip_id 与 trips.txt 相关。

总之,我们可以解释这三个文件之间的关系,如下图所示。

连接数据框

正如我们可以从上一节推断的那样,我们将从“stop_times”数据框中获得每小时的出行次数。棘手的是,在“stop_times”中,没有变量告诉我们行程的路线。要获得这些信息,我们首先要通过“旅行”。此数据框保存“行程标识”(出现在“停靠时间”)和“路线标识”(出现在路线中)之间的关系。

为了在同一个数据框中获得我们需要的所有信息,我们将从“停止时间”一直到“路线”遍历上图。

stop_times <- stop_times *%>%* left_join(trips) *%>%* left_join(routes) *%>%* select(route_id, route_short_name, trip_id, stop_id, service_id, arrival_time, departure_time, direction_id, shape_id, stop_sequence)

首先,我们把停车时间和行程联系起来。此时,数据帧具有 route_id 和 trip_id。然后我们用“路线”把它连接起来。

最后,我们选择相关变量继续。你可以用' head()'函数来看看最终的数据帧。

head(stop_times)

现在,我们有所有站点的通过时间(检查“stop_sequence”列)。但是我们只需要第一站来计算每小时的行程数。此外,考虑到旅行是往返的,我们只需要一个方向。如果没有,我们可能会复制每小时的旅行次数。

另外,请注意“到达时间”和“离开时间”是字符。这不允许我们用它们进行数学运算。

最后,‘service _ id’列告诉我们,在 GTFS 覆盖的时间段内,有许多不同的服务在运行。在计算每小时的行程数之前,我们需要选择一个。

在下一节中,我们将看到如何解决所有这些问题。

过滤和转换数据

选择具有更多行程的服务标识

为了解决上面列出的问题,我们可以首先从寻找我们想要使用的“service_id”开始。我们可以通过许多不同的方式来完成,如果您使用自己的数据,最有可能的是您已经知道要分析哪个服务。就本文的目的而言,只需要更多的旅行。

trips *%>%* group_by(service_id) *%>%* count(service_id) *%>%*arrange(desc(n))

第一行按“服务标识”对行程进行分组。然后,我们计算每个“service_id”的旅行次数,最后,我们对它进行排序。

该数据集中最大的服务似乎是“LA ”,因此我们将在之后对其进行过滤。下面,我们将变量“bigger_service”定义为上面所示数据的第一行。

bigger_service <- trips *%>%* group_by(service_id) *%>%* count(service_id) *%>%*arrange(desc(n)) *%>%* head(1)

按服务标识、停止顺序和方向标识过滤

现在,我们可以过滤“停止时间”,以便只保留与我们的目的相关的信息。

为此,我们将只保留更多行程(LA)的“service_id ”,只保留每次行程的第一站和每次行程的一个方向。

stop_times <- stop_times %>% filter(stop_sequence == 1 & direction_id == 0 &service_id == bigger_service$service_id)head(stop_times)

将字符转换成数字

现在,我们只保留了与我们的目的相关的数据,我们需要将“到达时间”和“离开时间”(或至少其中之一)转换成数字,以便我们对它们进行数学运算。

事实上,由于我们要计算每小时的旅行次数,我们并不真的需要分钟。我们只需要获得小时值,以便能够在以后对它们进行分组。这样,像“07:28:00”和“07:45:00”这样的字符将变成数字“7 ”,这足以让我们计算出从早上 7 点到早上 8 点每小时有两趟车。

如果我们只需要记下小时数,这就容易了。当我们发现超过 24 小时的数字时,棘手的部分就来了。在这种情况下,“25:00:00”实际上是指凌晨 1 点。为了解决这个问题,我们将进行改造。

stop_times <- stop_times %>% mutate(arrival_time = ifelse(as.integer(substr(arrival_time, 1, 2)) < 24,as.integer(substr(arrival_time, 1, 2)),as.integer(substr(arrival_time, 1, 2)) - 24),departure_time = ifelse(as.integer(substr(departure_time, 1, 2)) < 24,as.integer(substr(departure_time, 1, 2)),as.integer(substr(departure_time, 1, 2)) -24))
head(stop_times)

现在看起来相当不错。请注意,我们必须运行“ifelse”条件来处理大于 24 的数字。如果是的话,我们从他们那里拿走了 24 个。就像这样,25h 变成 1h,这正是我们要找的。

另外,我们只记录了到达和离开的时间。现在,我们可以根据这些变量中的一个进行分组,并计算每个时间窗口中的旅行次数。

那么,每条线路每小时的行驶次数是多少?

我们的最后一步是计算每条线路每小时的行驶次数。感谢我们经历的所有麻烦,现在这将变得非常容易。

output_data <- stop_times *%>%* group_by_at(vars(route_id, route_short_name, arrival_time)) *%>%* count(arrival_time)head(output_data)

就在那里!我们现在知道了每条线路每小时的行驶次数。

尽管如此,我们可以把它变得更好。为此,我们将再次更改“arrival_time”的格式,从“6”更改为“6:00”。

output_data <- stop_times *%>%* group_by_at(vars(route_id, route_short_name, arrival_time)) *%>%* count(arrival_time) *%>%* mutate(time_window = paste(arrival_time, '00', sep = ':')) *%>%* select(route_id, route_short_name, arrival_time, time_window, n)head(output_data)

在下面几节中,我们将了解如何将这些数据下载到一个. csv 文件(可以用 Excel 打开),并使用 ggplot()为其中一条线制作条形图和折线图。

导出到 csv 文件

这个很简单:

write_csv(output_data, "/Users/santiagotoso/Descktop/transitEMT/trips_per_hour.csv" )

你只需要改变路径到你想要的方向。

创建每小时旅行次数的图表

在本节中,我们将看到如何创建一个条形图和折线图来显示一条特定线路每小时的行程数。

为此,我们要做的第一件事是过滤某一特定行的信息。例如,我将选择第 1 行。

line <- output_data *%>%* filter(route_id == '001')View(line)

在绘制代表数字的字符(或者在这种情况下代表时间)时,重要的一点是对它们进行因式分解,以便它们作为数字进行排序。如果我们不这样做,它们将被排序为字符串(字符),这意味着我们将首先有 10:00,然后 11:00 等等,而不是 6:00。为了说明这一点,我在下面展示了如果我们现在进行因式分解之前(注意 x 轴),我们的图表会是什么样子:

为了避免这种不良行为,我们需要先分解“时间窗口”。

line$time_window <- factor(line$time_window, levels = unique(line$time_window))

条形图

现在我们已经分解了 x 轴,我们将使用 ggplot()制作一个条形图。

g_bar <- ggplot(data = line,aes(x = time_window, y = n)) + geom_bar(stat = 'identity')g_bar

就我个人而言,我喜欢我的图表更干净,更鲜艳一点。如果这也是您的情况,您可以使用下面的代码获得更好的结果。

g_bar <- ggplot(data = line,aes(x = time_window, y = n)) + geom_bar(stat = 'identity', fill = 'steelblue', color = 'steelblue') + geom_text(aes(label = n), vjust = -0.3, color = "black", size = 3) +scale_fill_brewer(palette="Dark2")+labs(title = paste('Trips by hour for route', line$route_short_name, sep = ' '),x = "Time window",y = '') +theme(panel.grid = element_blank(), panel.background = element_blank(), axis.line.x = element_line(colour = "grey"), axis.line.y = element_blank(),axis.text.x = element_text(angle = 90, hjust = 1),axis.text.y = element_blank(),axis.ticks.x = element_line(colour = "grey"),axis.ticks.y = element_blank(),plot.title = element_text(hjust = 0.5) )g_bar

折线图

我们将直接制作漂亮的图表,但请记住,您可以做更简单的版本,复制条形图的代码并将其更改为折线图。

g_line <- ggplot(data = line,aes(x = time_window, y = n, group = 1)) + geom_line(color = 'steelblue') +geom_point(color = 'steelblue') +geom_text(aes(label = n), vjust = -0.8,color = "black",size = 3) +scale_fill_brewer(palette="Dark2")+labs(title = paste('Trips by hour for route', line$route_short_name, sep = ' '),x = "Time window",y = '') +theme(panel.grid = element_blank(),panel.background = element_blank(),axis.line.x = element_line(colour = "grey"),axis.line.y = element_blank(),axis.text.x = element_text(angle = 90, hjust = 1),axis.text.y = element_blank(),axis.ticks.x = element_line(colour = "grey"),axis.ticks.y = element_blank(),plot.title = element_text(hjust = 0.5))g_line

结论

我们看到了如何将一个 GTFS 导入到 R 中并研究它。然后,我们研究了数据框架之间的关系,只保留了获得我们所寻求的洞察力所需的数据。

如图所示,用于从 GTFS 获得每小时旅行次数的数学和方法非常简单,不需要很深的数学知识,也不需要 R 语言。这是一个非常好的方式来开始学习 R,并探索你可以从你的 GTFS 中获得的一些见解。

你怎么想呢?对你有帮助吗?请让我知道你在下面评论的想法。

记住,你可以从我的 GitHub 库中获得原始代码、html 或 R Markdown 。

这篇故事最初发表于:https://www . LinkedIn . com/pulse/r-gtfs-getting-number-trips-per-hour-each-line-toso/?已发布=t

初学者 r 公式教程

原文:https://towardsdatascience.com/r-formula-tutorial-for-beginners-1a6d88e2d0bb?source=collection_archive---------5-----------------------

想一想,R 中的很多函数都利用了公式:像ggplot2statslatticedplyr等包都在用!使用这些 R 对象的常见函数示例有glm()lm()facet_wrap()等。但是这些公式到底是什么,为什么要用呢?

这些只是本教程希望回答的一些问题:

提示:您有兴趣在统计建模的背景下学习更多的公式吗?看看 DataCamp 的多元与 Logistic 回归课程。

R 中的数据结构

因为公式是 R 编程语言中的一个特殊类,所以简单地修改一下这种编程语言中可用的数据类型和数据结构是一个好主意。

记住 R 是一种面向对象的编程语言:这种语言是围绕对象来组织的。R 中的一切都是对象。

让我们从头开始:在编程中,你使用数据结构存储数据,函数处理数据。数据结构是组织在计算机内存中的数据的接口。正如 R 语言定义所说,R 并不提供对计算机内存的直接访问,而是提供一些你可以称为“对象”的特殊数据结构。每个数据结构都是为优化存储、访问或处理的某个方面而设计的。

R 中的五种主要数据结构是:

  • 原子向量,
  • 列表,
  • 矩阵,
  • 数据帧,以及
  • 排列
# Create variables 
a <- c(1,2,3,4,5,6,7,8,9) 
b <- list(x = LifeCycleSavings[,1], y = LifeCycleSavings[,2])

提示:你可以使用typeof()函数返回一个 R 对象的类型。对象的类型告诉您关于任何对象的(R 内部)类型或存储模式的更多信息:

# Retrieve the types of `a` and `b` 
typeof(a) 
typeof(b)

双份

'列表'

在上面定义变量ab的例子中,您可以看到数据结构包含数据元素序列。这些元素可以是相同或不同的数据类型。您可以在 R 中找到以下 6 种原子数据类型:

  • 数字,如10054,包含整数。
  • 字符,如"Hello""True""23.4",由键盘字符串组成。;
  • 逻辑的,如TRUEFALSE,由“真值”组成;
  • raw,如48 65 6c 6c 6f,由比特组成;
  • 复数,如2+5i,包含复数;最后一点,
  • double,如3.14,包含十进制数。

在 r 中,几乎所有的对象都有属性。例如,您可能已经知道矩阵和数组只是简单的向量,属性dim和可选的dimnames被附加到向量上。属性用于实现 r 中使用的类结构。作为一种面向对象的编程语言,类的概念以及方法是它的核心。类是对象的定义。它定义了对象包含的信息以及如何使用该对象。

看看下面的例子:

# Retrieve the classes of `a` and `b` 
class(a) 
class(b)

'数字'

'列表'

注意如果一个对象没有class属性,它有一个隐式类,“矩阵”、“数组”或mode()函数的结果。

您可能遇到的一些特殊类是日期和公式;而这最后一个就是今天教程的题目!

R 中的公式是什么?

当你阅读本教程的介绍时,你可能已经看到了在使用像ggplot2这样的包或者像lm()这样的函数时出现的公式。因为您通常在这些函数调用中使用公式来表达统计模型的思想,所以在建模函数和一些图形函数中经常使用这些 R 对象是合乎逻辑的。

对吗?

然而,公式并不局限于模型。它们是一个强大的通用工具,允许您捕获两件事情:

  • 未赋值的表达式,以及
  • 创建表达式的上下文或环境。

这解释了为什么在函数调用中使用公式来生成“特殊行为”:它们允许您捕获变量的值,而无需对它们求值,以便它们可以被函数解释。

记住数据结构后,您就可以将这些 R 对象描述为“语言”对象或未赋值的表达式,它们具有一个“公式”类和一个存储环境的属性。

在上一节中,您看到了对象具有某些(R internal)类型,这些类型指示对象是如何存储的。在这种情况下,公式是“语言”类型的对象。

但是这到底意味着什么呢?

嗯,当你处理 R 语言本身时,你通常会遇到这种类型的对象。为了更好地理解这一点,请看下面的例子:

# Retrieve the object type 
typeof(quote(x * 10)) # Retrieve the class 
class(quote(x * 10))

“语言”

“呼叫”

在上面的例子中,你要求 R 返回quote(x*10)的类型和类。结果你看到quote(x*10)的类型是'language',而class'call'

这绝对不是一个公式,因为你需要用class()来返回'formula'

但那是什么呢?

R 中的公式的特征是波浪号操作符~。有了这个操作符,您实际上可以说:“捕捉这段代码的含义,而不用马上对它进行评估”。这也解释了为什么你可以把 R 中的公式看作一个“引用”操作符。

但是公式到底是什么样子的呢?仔细看看下面一行代码:

# A formula 
c <- y ~ x 
d <- y ~ x + b # Double check the class of `c` 
class(c)

公式

波浪号(~)左侧的变量称为“因变量”,而右侧的变量称为“自变量”,由加号+连接。

很高兴知道这些变量的名称会根据上下文而变化。你可能已经看到自变量以“预测值(变量)”、“受控变量”、“特征”等形式出现。同样,你可能会遇到因变量,如“反应变量”、“结果变量”或“标签”。

注意尽管您在上面的代码块中定义的公式d包含几个变量,但公式的基本结构实际上只是波浪号~和至少一个独立或右侧变量。

记住公式实际上是具有存储环境属性的语言对象:

# Return the type of `d` 
typeof(d) # Retrieve the attributes of `d` 
attributes(d)

“语言”

$class [1] "formula" 
$.Environment <environment: R_GlobalEnv>

正如你在上面的例子中看到的,公式中包含的变量可以是向量。但是,您经常会看到公式中包含的变量来自数据框,就像下面的示例一样:

Sepal.Width ~ Petal.Width + log(Petal.Length) + Species

注意当创建公式本身时,不会访问任何已分配给公式中符号的数据值。

现在你已经知道了 R 中的公式是什么样子,它们是什么,最好提一下底层的公式对象是不同的,这取决于你有一个单边还是双边的公式。你可以通过观察左边的变量来识别前者。如果没有,就像~ x中一样,你有一个片面的公式。

这也意味着单侧公式的长度为 2,而双侧公式的长度为 3。

不完全信服?看看下面的代码块。您可以借助方括号:[[]]来访问公式的元素。

e <- ~ x + y + z 
f <- y ~ x + b # Return the length of `g` 
length(e) 
length(f) # Retrieve the elements at index 1 and 2 
e[[1]] 
e[[2]] 
f[[3]]

2

3

`~` x + y + z 
x + b

为什么在 R 中使用公式?

如您所见,公式是功能强大的通用工具,允许您捕获变量的值,而无需对它们求值,以便它们可以被函数解释。这已经是为什么应该在 r 中使用公式的答案的一部分了。

此外,您使用这些 R 对象来表达变量之间的关系。

比如下面代码块中的第一行代码,你用第一行代码说“y 是 x,a,b 的函数”;当然,你也可以遇到更复杂的公式,比如在第二行代码中,你的意思是“萼片宽度是花瓣宽度的函数,取决于物种”。

y ~ x + a + b 
Sepal.Width ~ Petal.Width | Species

在 R 中使用公式

现在,您已经了解了这些特殊 R 对象的“是什么”和“为什么”,是时候了解如何使用基本公式以及更复杂的公式了!在本节中,您不仅会看到如何创建和连接基本公式,还会发现如何在运算符的帮助下构建更复杂的公式。

如果您想了解更多关于如何在 R 中创建公式、连接公式、使用公式运算符以及如何在 R 中检查公式的信息,请访问 原始教程

何时使用公式

到目前为止,您已经了解到 R 公式是通用工具,并不局限于建模,并且您已经看到了一些可以使用公式的例子。在本节中,您将更深入地了解最后一个主题:您将看到一些可以利用这些工具的案例。当然,您将会涉及到诸如latticestats之类的软件包的建模和图形功能,但是您也将会涉及到dplyr中的非标准评估。

转到 原创教程 阅读全节。

r 配方奶粉包

之前,您已经看到您可以使用as.formulaupdate()all.vars等函数来创建和检查您的公式。...这些都是简单的操作和处理,但是高级的公式处理呢?也许下面这些套餐会让你有些兴趣!

Formula套餐

最近,这个包发表在 CRAN 上。这款套装非常适合那些想让配方更上一层楼的人。这个包扩展了基类formula

更具体地说,Formula对象扩展了基本的公式对象:使用这个包,您实际上可以定义公式,这些公式接受一个附加的公式操作符|来分隔多个部分,或者可以在左侧包含所有的公式操作符(包括管道字符)来支持多个响应。

您将能够创建的公式示例如下:

  • 多部分公式,如y ~ x1 + x2 | u1 + u2 + u3 | v1 + v2
  • 多响应公式,如y1 + y2 ~ x1 + x2 + x3
  • 多部分响应,如y1 | y2 + y3 ~ x,以及
  • 以上三者的组合。
# Load package 
library(Formula) # Create formulas 
f1 <- y ~ x1 + x2 | z1 + z2 + z3 
F1 <- Formula(f1) # Retrieve the class of `F1` 
class(F1)

注意功能as.formula()is.formula()在这个包中也被更新:你将使用is.Formula()as.Formula()来代替!

在这里阅读更多。

这个包是最近发布的,它为你提供了“操作公式、表达式、调用、赋值和其他 R 对象的编程工具”。这是一大堆,但本质上,这一切都归结为:您可以使用这个包来访问和修改公式结构,以及提取和替换那些 R 对象的名称和符号。这个包裹是克里斯托弗·布朗写的。

在使用这个包时,您可能会发现以下一些有用的东西:

  • get.vars():代替all.vars(),这个函数会从各种 R 对象中提取变量名,但是所有符号等。将被插入到变量的名称中。
  • invert():您可以使用此功能反转对象中的运算符,如公式。
  • is.one.sided():这个函数可以很方便的判断一个函数是单边的还是双边的。

记住一个公式如果长这样就是片面的:~x;当表述为x~y时,它将是双面的。

有兴趣了解更多套餐?查看 原教程

还有更多的发现!

万岁!你已经完成了 R 公式的教程。如果你想了解更多,一定要看看 Hadley Wickham 的数据科学 书籍 R,其中有一章专门介绍 R 中的公式和模型族

您能想出更多可以找到公式或更多可以用来操作公式的包的例子吗?随时在推特上告诉我: @willems_karlijn 。

原载于www.datacamp.com

朗:从零到英雄

原文:https://towardsdatascience.com/r-lang-zero-to-hero-c59a9f66841c?source=collection_archive---------7-----------------------

统计计算和图形指南。

R 语言简介。

r 是一个计算环境,它结合了一种叫做 S 的编程语言,实现了用数据编程的思想。它对线性代数、微分方程和随机有强大的数值分析工具。r 编程通过提供一组内置的函数和库让你了解数据可视化。r 的图形前端有很多,目前最好的似乎是 RStudio。然而,在了解这些之前,您应该先了解一下 R 本身。

为什么是 R?

  1. r 是灵活的。
  2. r 是强大的。
  3. r 不仅仅是一个统计计算包;这是一种编程语言。
  4. r 被设计成以问题设计的方式运行。
  5. r 在处理数据和存储设备方面效率很高。

用 R 语言编写的代码片段对用户来说总是可用的,所以对任务的小改动通常只需要对代码进行小改动——这种差别可以在更短的时间内完成。

在你的机器上安装 R

下载 R ,请选择您喜欢的摇柄镜。

R 工作室

RStudio 让 R 更容易上手。它包括一个代码编辑器,调试和可视化工具。它是一个(IDE ),包括一个控制台、支持直接代码执行的语法高亮编辑器,以及用于绘图、历史、调试和工作空间管理的工具。

从以下链接下载 R-Studio。

[## RStudio

控制你的 R 代码 RStudio 是一个 R 的集成开发环境(IDE)。

www.rstudio.com](https://www.rstudio.com/products/rstudio/)

A Snapshot of RStudio

交互使用 R

在机器上安装 R 之后,在终端或 shell 中点击 R 启动 R 交互式 Shell。默认提示是' > ',在 UNIX 上可能与 shell 提示相同,因此可能看起来什么也没发生,它将等待用户的指令。

您可以将 R Shell 用作计算器,您可以从做简单的数学运算到高级机器学习算法。

要退出 R 程序,命令是

> q()

这将从 R Shell 中退出。您也可以通过在退出后按“y”来保存工作区会话。如果希望继续而不保存,只需按“n”,这将使您返回到终端/shell。

让我们开始打印“Hello World!”在 R 互动壳里。

在 R 中,我们使用 print()函数返回参数中给定的字符串。

$R
> print("Hello World!")
[1] "Hello World!"
>

R 中的注释

正如我们所知,每种编程语言都需要注释,R 支持注释,而注释会被解释器忽略。

这就是我们在 r 中使用注释的方式。

# This is a comment in R
# print("This doesn't work")

变量

在编程中,变量只不过是某种东西的名称。R 中的变量可以存储一个原子向量、一组原子向量或许多 R 对象的组合。r 名称区分大小写。要为数据结构创建名称,我们必须遵循以下规则:

注意:名称以。被认为是系统名,使用ls()-函数时并不总是可见的。

现在让我们看看如何在 R 中声明变量

a <- 3

这行代码声明了一个变量“a ”,并将其赋值为 3。

typeof()函数返回变量的数据类型。

type(a)
[1] "double"

R 中的数据类型

Numeric (real 或 decimal): Decimal 值在 r 中称为 Numeric,它是默认的计算数据类型。

Integer: 为了在 R 中创建一个 Integer 变量,我们调用 as integer 函数。

Character: 一个 Character 对象用来表示 r 中的字符串值,我们用 as character()函数把对象转换成字符值。

逻辑:逻辑值通常是通过变量之间的比较产生的。

复:R 中的复数值通过纯虚数值 I 来定义。

解释数据类型的代码片段。

为了从 shell 中执行 R 文件,我们使用命令“Rscript filename”。r "

[1] 3
[1] "double"
[1] "Stark"
[1] "character"
[1] TRUE
[1] "logical"
[1] 1+4i
[1] "complex"

注意:R 语言中的字符串是字符。

算术运算

所有的基本运算,如加、减、除、乘。Etc 可以在 r 中执行

[1] 6
[1] 1
[1] 315
[1] 8.333333
[1] 3
[1] 1
[1] 125

R 中的数据结构

原子向量

向量是 R 中最常用的数据结构。它是相同基本类型的数据元素序列。向量中的成员正式称为分量。向量可以是最常见的characterlogicalintegernumeric.元素的向量

我们使用 vector()函数创建一个空向量,下面的代码片段展示了我们如何声明一个向量。

x <- vector()
> character(5)
[1] "" "" "" "" ""

列表

R lang 中的列表充当容器。它们是包含其他对象通用向量。与原子向量不同,列表的变量不限于单一模式,可以包括任何数据类型的混合。一个列表可以包含其他列表。这使得它们不同于原子向量。

R 中的列表是使用 list()函数创建的。

my_list <- list("Red", TRUE, 51.23)
[1] "Red"
[[2]]
[1] TRUE
[[3]]
[1] 51.23[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]][1] "Sun"
[[5]]
[1] "Mon"
[[6]]
[1] "Tue"

[数]矩阵

矩阵是 r 中特殊类型的向量。矩阵是以二维矩形布局排列的数据元素的集合。矩阵有行和列。

现在,让我们创建一个 2x2 矩阵,我们使用矩阵函数,并将行和列作为参数发送。行数为 nrow ,列数为 ncol

my_matrix <- matrix(nrow = 2, ncol = 2)
 [,1] [,2] [,3] [,4]
[1,] 59.0 22.3 31.2  9.5
[2,] 55.0 19.7 30.4 13.8
[3,] 53.5 20.8 30.6 14.8
[4,] 55.0 20.3 30.3 15.2
[5,] 52.5 20.8 30.3 15.5
[6,] 57.5 21.5 30.8 15.6
[7,] 53.0 20.6 32.5 15.6
[8,] 55.0 21.5 34.0 15.7

数据帧

数据帧是 R 语言中最常用的数据结构之一。数据以表格的形式表示,表格中有许多行和列。

我们通常将 csv 文件读入数据帧,为此我们使用 read.csv()函数或 read.table()函数,并将 csv 文件名作为参数发送。

我们还可以使用 data.frame()函数创建一个数据框。

> df <- data.frame(id = letters[1:5], x = 1:10, y = rnorm(10))
> df
> ##    id  x        y
> ## 1   a  1 -1.37593
> ## 2   b  2  0.47094
> ## 3   c  3 -0.16046
> ## 4   d  4 -1.36914
> ## 5   e  5  0.39763

这些是我们应用于数据框以得出最小结论的几个重要函数。

head() —查看前 6 行

tail() —查看最后 6 行

dim()-请参见尺寸

nrow() —行数

ncol() —列数

str() —每列的结构

因素

因子几乎都是有标签的整数。虽然因子看起来(并且经常表现)像字符向量,但它们实际上是整数,当把它们当作字符串时需要小心。有些字符串方法会将因子强制转换为字符串,而有些则会抛出错误。

可以用factor()创建因子。输入通常是一个字符向量。

> x <- factor(c("yes", "no", "no", "yes", "yes"))
> x
[1] yes no  no  yes yes
Levels: no yes
# table(x) will return a frequency table.

控制结构

这些允许您控制脚本的执行流程,通常是在函数内部。常见的包括:

  1. 如果,否则
  2. 在…期间
  3. 重复
  4. 破裂

如果-否则

我们总是需要检查条件并相应地改变程序行为的能力。条件语句给了我们能力。最简单的形式是“if”语句。

if (condition) {# do something
} else {# do something else
}

例子,

x is less than 10

For 循环

R 中的 for 循环能够迭代任何序列的项,比如列表或向量。

for (i in 1:5) {print(i)
}

这就是我们在 R 中声明 for 循环的方式,它接受 iterable 变量(I)并迭代直到给定的范围(这里是 10)

1
2
3
4
5

实现 for 循环的几种方法。

[1] NA
[1] NA
[1] NA
[1] NA[1] "apples"
[1] "oranges"
[1] "bananas"
[1] "strawberries"[1] "apples"
[1] "oranges"
[1] "bananas"
[1] "strawberries"[1] "apples"
[1] "oranges"
[1] "bananas"
[1] "strawberries"

在…期间

只要给定的条件为真,R lang 中的 while 循环语句就会重复执行目标语句。与 for 循环不同,while 循环不会运行 n 次,而是直到满足定义的条件。

While 循环的语法

while(condition){statementsiteration
}

这是一个我们如何实现一个简单的 while 循环的例子,

1
2
3
4
5

重复和中断

重复循环用于多次迭代代码块。重复循环中没有退出循环的条件检查。

重复和中断的语法

repeat{conditionstatementsbreak
}

现在让我们使用 repeat 和 break 打印前五个数字。

[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

功能

在任何编程语言中,函数的主要用途是可重用性。它们是组织在一起执行特定任务的一组语句。R 中有各种内置函数,R 中的一些内置函数有 sum()、min()、max()、mean()等。

在 R 中声明函数的语法

function_name <- function(arg_1, arg_2, ...) {function body 
}

现在让我们创建一个函数来按顺序打印数字的立方。

216

R 中的可视化

可视化数据是决策的重要解决方案之一。r 编程语言为创建数据故事和可视化提供了一套最好的内置函数和库(如 ggplot2、leaflet、lattice)。

现在,让我们在 RStudio 中使用 ggplot2 创建一个简单的线图,为此我们需要安装 ggplot2 包,您会在左上角找到控制台。运行命令 install.packages("package_name ")。

> install.packages("ggplot2")

我们现在将导入一个内置的数据集(mpg ),并绘制一个简单的图表。

关于 mpg 数据集:这是 1999 年和 2008 年 38 种流行车型的燃油经济性数据。

  1. 具有 234 行和 11 个变量的数据框
  2. displ —发动机排量,单位为升
  3. 公路——公路英里/加仑

感谢阅读!

这篇文章的代码可以在 AaqilShaik 的这里找到。

感谢阅读。如果你觉得这个故事有帮助,请点击下面的👏去传播爱。

r:等级与顺序

原文:https://towardsdatascience.com/r-rank-vs-order-753cc7665951?source=collection_archive---------1-----------------------

如果你正在学习 R,你可能已经遇到过 排序 等级 顺序 函数。因为在语义上有相似性,甚至重叠,问题出现了:每一个具体做什么,每一个的用例是什么?

这三个函数都要求它们运算的值是可比较的。 R 中的比较适用于字符串、数字、复杂和逻辑日期类型。

等级与顺序混淆

排序、等级和顺序是 r 中的函数。它们可以应用于向量或因子。如果你习惯用行和列来考虑数据,那么向量代表一列数据。因子是从向量中创建的,代表离散的带标签的值。在下面的 R 代码中,X 加载了数据,然后进行排序、排名和排序。 R 将结果报告为向量。

X = c(3,2,1) 
X 
3 2 1 
sort(X)
[1] 1 2 3
rank(X)
[1] 1 2 3
order(X)
[1] 1 2 3

这似乎够清楚了:

  • 使用“c”ombine 函数将数据加载到向量中
  • 当您查看 X 时,它会按照加载时的方式排列
  • 当你对 X 进行排序时,你会看到一个向量,它包含 X 中的值,这些值按升序排列
  • 当您对 X 进行排序时,您会看到一个向量,其中包含 X 中按升序排列的值(类似于排序)
  • 当您 X 排序时,您会看到一个包含 X 中按升序排列的值的向量(类似于 sort)

现在,让我们在创建 X 向量和运行这些函数时应用一个简单的排列。

X = c(2,3,1) 
X 
2 3 1
sort(X)
[1] 1 2 3
rank(X)
[1] 2 3 1
order(X)
[1] 3 1 2

在上面的输出中,排序函数肯定了我们上面所说的,但是等级顺序更难解释。现在,看一个不同的向量,在不同的整数范围上有相似的排列。

X = c(5,6,4) 
X 
5 6 4
sort(X)
[1] 4 5 6
rank(X)
[1] 2 3 1
order(X)
[1] 3 1 2

在上面的代码中,我们看到“5,6,4”的等级和顺序与“2,3,1”相同。这两个序列具有相同的等级和顺序的原因是等级和顺序报告的是相对位置,而不是相对值。等级和顺序基于向量中数据升序排序的结果。具体来说,rank 和 order 返回的值的范围是原始序列中值的索引范围。

  • Rank 引用值在排序向量中的位置,与原始序列的顺序相同
  • 顺序返回原始值的位置,按照排序的顺序,即从最小值到最大值

下图有助于将按等级和顺序报告的值与它们来自的职位联系在一起。

对合循环

首先呈现的“1,2,3”序列返回秩和序的向量“1,2,3 ”,它实际上是一个特殊的序列,因为这些值和“1,2,3”的几个其他排列导致秩和序表现为对合函数。一个无意识函数是一个它自己的反函数。

**X = c(1,2,3)
RANK(X) == ORDER(X) == X
RANK(ORDER(X)) == X
ORDER(RANK(X)) == 1:length(X)**

在下面的代码中,您可以看到“1,2,3”的所有六种排列都经过了测试,以确定它们是否是对合的(一个应用两次就会给出初始值的函数)。没有导致对合功能的两种排列可以通过它们分解成的循环来识别。有关对合循环的更多信息,请参见下面的文章R 中的秩与序。

X = c(1,2,3)
all(order(rank(X)) == X)
[1] TRUEX = c(2,3,1)
all(order(rank(X)) == X)
[1] FALSEX = c(3,1,2)
all(order(rank(X)) == X)
[1] FALSEX = c(1,3,2)
all(order(rank(X)) == X)
[1] TRUEX = c(2,1,3)
all(order(rank(X)) == X)
[1] TRUEX = c(3,2,1)
all(order(rank(X)) == X)
[1] TRUEall(order(X)[rank(X)] == rank(x)[order(X)]) == 1:length(X)
TRUE

虽然学习查看简单的数据集来帮助理解函数的行为很有吸引力,但当数据的排列影响函数的输出时,它会导致混乱的结论。

排序序列

对于任何升序排列的向量序列,下面的代码演示了顺序等级之间的关系,因为它们相互作用。将始终等于

X = c(100,200,300)
all(order(X)[rank(X)] == rank(X)[order(X)])
TRUE

此外,下面的代码验证了对于任何升序序列,秩的顺序和顺序的秩将始终等于由有序元素的位置组成的向量。

x = c(100,200,300)
all(order(X)[rank(X)] == 1:length(X))
TRUE
all(rank(X)[order(X)] == 1:length(X))
TRUE
1:length(X)
[1] 1 2 3

订单函数的用例

您可以使用 order 函数对数据帧进行排序。

排序命令可用于创建一个新的向量,从任何可比较值的向量到按升序排列的向量。默认的排序顺序是升序,但是可以选择降序,也可以选择处理未定义的值和指定排序方法。

当您将数据从文件系统读入一个数据帧或者用代码构建该数据帧时,您拥有一个包含不同类型数据的行和列的结构。为了按列值对数据框的行进行“排序”,无论是单列还是多列,都必须使用命令,因为命令只对向量进行排序。

为了了解其工作原理,下面的示例从加载到矢量中的原始数据构建了一个数据框。这些数据也可以很容易地从 CSV 或其他格式的文本文件中读入。注:将最后一条指令括在括号中会导致数据帧被 test.data 变量引用,并显示 test.data 变量中的内容。显示的第一个整数是由 R 分配给数据帧中各行的计数器标识符。

size = 5
sex=sample(c("male","female"),size,replace=T)
age = sample(21:100, size, replace=T)
degree = sample(c("BA","BS","MS","MBA"), size, replace=T)
(test.data = data.frame(sex=sex, age=age, degree=degree))sex age  degree
1 female  30     BA
2   male  49     BA
3   male  39    MBA
4   male  27     MS
5   male  61     MS

我们可以使用 order 命令按年龄对数据进行排序。向 order 函数传递要排序的列的名称,并且顺序为升序。order 命令的结果是一个向量,其中每个值引用原始数据框中项目的位置值,并且它本身位于排序数据的位置。例如,原始数据帧中的第一年龄是 30,而排序数据帧中的第一年龄 30 将在第二位置。因此,值 1 位于顺序向量的第 2 个位置。

一旦获得顺序向量,它将用于从原始测试数据中提取数据。您可以在结果中看到原始的计数器 id,以及它如何匹配用于排序的顺序向量。r 使用带有行、列名称的方括号从数据帧(或矩阵)中提取数据。

order(test.data$age)
[1] 4 1 3 2 5test.data[order(test.data$age),]
sex age degree
4   male  27     MS
1 female  30     BA
3   male  39    MBA
2   male  49     BA
5   male  61     MS

通过在 order 命令指定的列名前使用负号,可以按降序对数据框进行排序。

order(-test.data$age)
[1] 5 2 3 1 4test.data[order(-test.data$age),]5   male  61     MS
2   male  49     BA
3   male  39    MBA
1 female  30     BA
4   male  27     MS

我们还可以通过向 order 命令添加多列来提供多列排序。

order(test.data$degree,-test.data$age)
[1] 2 1 3 5 4
test.data[order(test.data$degree,-test.data$age),]sex age degree
2   male  49     BA
1 female  30     BA
3   male  39    MBA
5   male  61     MS
4   male  27     MS

等级函数的用例

您可以使用 rank 函数创建一个值,该值表示一个值在其序列中的相对位置。

IEEE 提供了一份 2017 年十大编程语言的清单。它们存储在一个文件中,在我的本地文件系统中,按照语言名称的字母顺序排序。下面的代码将它们读入一个变量,这个变量通过名称 language.ieee 引用它们并显示内容。

(language.ieee =read.csv(file="language-scores.csv"))X   language score
1   2          C  99.7
2   5         C#  87.7
3   4        C++  97.1
4   9         Go  75.1
5   3       Java  99.5
6   7 JavaScript  85.6
7   8        PHP  81.2
8   1     Python 100.0
9   6          R  87.7
10 10      Swift  73.1

我们可以得到一个排序数据的向量。排名向量中的数据显示为 float,因为有平局: C#R 并列第 5 和第 6 名。rank 函数中有处理平局的选项,但默认情况下是使用“平均”方法,并为每个平均分赋值。这些值本身通过值在原始数据集中的位置来表示相应值的降序。较高的等级值代表较大的数据值。

rank(language.ieee$score)
9.0  5.5  7.0  2.0  8.0  4.0  3.0 10.0  5.5  1.0

我可以使用 rank vector,通过向 order 命令提供负秩,按秩对数据进行排序,也就是分数的降序。

language.ieee[order(-rank(language.ieee$score)),]X   language score
8   1     Python 100.0
1   2          C  99.7
5   3       Java  99.5
3   4        C++  97.1
2   5         C#  87.7
9   6          R  87.7
6   7 JavaScript  85.6
7   8        PHP  81.2
4   9         Go  75.1
10 10      Swift  73.1 

计算秩不仅用于排序数据。排名的相关性可以用来检验两个变量之间关系的零假设。由于变量的类型和规模可能不同,秩提供了一种规范化。例如,参见关于使用斯皮尔曼等级相关性的研究:【https://geographyfieldwork.com/SpearmansRank.htm。

结论

R 是一种统计编程语言,具有许多帮助格式化和处理数据的功能。它的服务通过函数调用来提供。除了阅读文档之外,通过这些函数运行数据集也有助于弄清楚它们到底做了什么。Sort、Order 和 Rank 在语义上是相同的,但在实践中,它们有非常不同的用途,有时会相互配合以达到预期的结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/71088.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

TowardsDataScience-博客中文翻译-2016-2018-三十八-

TowardsDataScience 博客中文翻译 2016~2018(三十八)原文:TowardsDataScience Blog 协议:CC BY-NC-SA 4.0Python 属性的原因和方式原文:https://towardsdatascience.com/the-why-and-how-of-python-properties-b791817cf4b9?source=collection_archive---------3--------…

2024-2025-1 20241327 《计算机基础与程序设计》第三周学习总结

作业信息 |2024-2025-1-计算机基础与程序设计)| |-- |- |2024-2025-1计算机基础与程序设计第二周作业)| |快速浏览一遍教材计算机科学概论(第七版),课本每章提出至少一个自己不懂的或最想解决的问题并在期末回答这些问题 |作业正文|https://www.cnblogs.com/shr060414/p/18…

『模拟赛』多校A层冲刺NOIP2024模拟赛06(更新 T4)

『模拟赛记录』多校A层冲刺NOIP2024模拟赛06Rank 比较还行A. 小 Z 的手套(gloves) 签。 最大值最小,一眼二分答案。双指针 check 一下就完了,复杂度 \(\mathcal{O(n\log n)}\)。点击查看代码 #include<bits/stdc++.h> #define fo(x, y, z) for(register int (x) = (y…

Grafana学习笔记1

安装 Grafana容器镜像拉取 docker pull grafana/grafana启用Grafana容器 命名为Grafa,再把主机端口3000映射到容器端口3000,把主机上的目录/path/to/your/grafana/data(这个路径自己定义)挂载到容器内的目录/var/lib/grafana,设置管理员密码为admin,使用已经拉取的镜像grafan…

4.漏洞挖掘(长期)

具体漏洞复现,见奇安信攻防社区的帖子。 国庆假期,试挖漏洞算是揭开的漏洞挖掘的面纱。第一个练手的漏洞是敏感信息漏洞。一开始,手工查找,google搜索,后来在chatGPTd 帮助下,学习研究脚本进行扫描。 但现在了,脚本不太好研究下去了,并且没太大兴趣继续,感觉太low了,…

Mysql(1)—简介及Windows环境下载安装

MySQL是一个流行的关系型数据库管理系统(RDBMS),它基于结构化查询语言(SQL)进行操作。MySQL由瑞典MySQL AB公司开发,后来被Sun Microsystems收购,最终成为Oracle公司的产品。它是最广泛使用的开源数据库之一,通常用于Web应用程序、数据仓库和企业应用。Mysql(1)—简介及…

linux练习题(二)

习题练习前预备知识(如下图):## linux练习题(二)习题以及参考答案 1、将/etc/passwd 拷贝到/home下并更名为test。cp /etc/passwd /home/test 2、在/tmp下建立test1到test9父子级目录,mkdir -p /tmp/test1/test2/test3/test4/test5/test6/test7/test8/test9 如果说该条命…

JAVA环境配置

JAVA开发环境配置 1.去官网下载JDK 找到对应的电脑版本进行安装,记住安装位置 2.安装完成后进入我的电脑-属性-高级系统设置-环境变量,点击系统变量下的新建,变量名必须为JAVA_HOME,变量值就是你刚刚的安装路径3.接着在系统变量中找到Path双击,新建如下两个,如图所示如果…