TowardsDataScience-博客中文翻译-2021-四十-

news/2024/10/20 5:02:05

TowardsDataScience 博客中文翻译 2021(四十)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

从数据科学访谈到开源 GitHub 项目

原文:https://towardsdatascience.com/from-a-data-science-interview-to-an-open-source-github-project-87c228902968?source=collection_archive---------34-----------------------

社区笔记

我分享了我的故事以及从这次旅程中学到的教训

由 Avel Chuklanov 在 Unsplash 上拍摄的照片

一切从几年前的一次数据科学面试开始。这次采访没有让我找到工作,但帮助我建立了一个开源项目,现在已经有几个贡献者,在过去的一年里,它的媒体白皮书每天都有超过百次的浏览量。我们所有人在生活中都会经历失败。那不重要。重要的是从失败中吸取教训,并把它变成有影响力的事情。我们可以用积极的态度从失败中建立一个发射台。然而,这篇文章并不具有激励性。相反,我分三集分享了我构建这个开源项目的故事,以及一些可能对你的职业道路有所帮助的经验教训。

[第 1 集]获得数据科学面试

几年前,我面试了一家科技公司的数据科学家职位。作为带回家的作业,我被要求解决一个典型的旅行推销员问题。在问题描述中,据说该解决方案将在超过 100 个节点的数据集上进行测试,执行时间最多为 5 分钟。从描述(尤其是时间限制)中,我可以猜到面试官期待一个为行业量身定制的创意解决方案。

我对这家公司感到兴奋,喜欢这种挑战。我发现一种叫做 2-opt 的优化方法被强烈推荐给 TSP,主要是因为它的启发式算法与问题相关。我以前曾经使用过启发式优化技术,而且,完整地说,它们是我的最爱!我决定实施 2-opt 算法,这样我就能在面试中胜出。那是一个周末。我呆在家里,完美地完成了作业。几天后,我见到了我的采访者,他们都对这个实施感到惊讶。面试进入了下一轮,由于一些内部政治,我的申请被停止了。这对我来说不是一个快乐的时刻,但我必须离开。

你的时间和精力是有限的。你不能奢侈地花掉它们而没有回报。总是考虑一个应急计划。

[第 2 集]创建了一个 GitHub 项目,构建了一个 PyPi 包

面试几个月后,我决定把这个带回家的作业做成一个 Github 项目。最后,拥有一个 Github 项目是向外界展示我的编码技能和知识的最好方式之一。同时,我相信一个不符合软件开发最佳实践的 Github 项目是不值得的。所以,我决定让它更专业。怎么会?通过编写好的文档,开发几个测试,构建 CI/CD 管道,并在项目中进行最佳的编程实践。

https://github.com/pdrm83/py2opt

我还构建了一个名为 py2opt 的 PyPi 包。我以前用过很多社区开发的 Python 包。所以,我在想为什么我不应该回报。在这次旅行中,我学到了很多东西。在 PyPi 包的第一个版本发布几个月后,我收到了一封来自 10000 英里外的学生的电子邮件,感谢我并问了我一个问题。感觉很好。你可以感觉到你开发的东西解决了某人的问题。

如果你想创建一个 Github 项目,请注意所有的细节。仅仅将代码推送到一个随机的存储库是不会有任何结果的。

https://pypi.org/project/py2opt/

【第三集】写了一篇中等文章,并使之官方化!

在确信 py2opt 包的质量之后,我写了一份白皮书解释我的实现。我将 2-opt 算法与动态规划和模拟退火进行了比较,并展示了我的实现执行得有多好。这对我来说是一个转折点。白皮书已经被 Google 通过搜索关键词“如何解决 TSP”索引到wikipedia.commath.uwaterloo.ca等多个合法网站之上。这有助于我的文章和 Github 库获得非常稳定的日访问量(大约 100 次/天)。

持续的每日流量有助于我的开源项目获得社区的关注。我的 2-opt 实现高效而快速。然而,在一个公共拉请求中,实现变得更快了。谢谢, Clawsoon !这就是社区的力量。目前,我正在到处宣传这个项目,以确保更多的人了解这个项目。

如果没有适当的公告,即使是最好的开源项目也可能无法吸引社区的注意。一篇 TDS 文章有助于获得这一点。

最后,看看克劳森在他的个人主页上的留言。我也非常感谢你,克劳森!

感谢对 2-opt 算法的精彩介绍!这篇文章和代码对我都很有帮助。

我找到了一个优化,使得我的旧的、慢的机器上的较大数据集更快。我意识到该算法只需比较交换中涉及的距离,而不是每次都重新计算整个路径长度。这使得我计算 1000 个随机生成的城市的 2-opt 路径的时间从 10 分钟减少到了 5 秒。

我希望你会发现我的贡献有用!请随意纠正你看到的任何错误。

遗言

在 py2opt 项目之后,我又开发了三个开源项目,尤其是其中一个名为 sent2vec (一个很酷的 NLP 工具)的项目吸引了社区的更多关注。然而,我的旅程是从 py2opt 开始的,我永远不会忘记看到其他开发人员对项目的贡献时的感受。我相信这个简单的工具甚至可以为大项目做很多事情。

如果你想找一个数据科学的职位,我建议你创建一个开源项目,或者参与其中。尝试在项目中使用(并展示)你的编程技能。它或者帮助你找到一份理想的工作,或者建立一些你几年后会引以为豪的东西。谁知道呢!

感谢阅读!❤️

如果你喜欢这个帖子,想支持我…

  • 跟我上
  • 亚马逊 上查看我的书!
  • 成为 中的一员
  • 连接上Linkedin
  • 关注我的 推特

https://pedram-ataee.medium.com/membership

从 A*到泥灰(第一部分——MAPF)

原文:https://towardsdatascience.com/from-a-to-marl-part-1-mapf-d4c0796ce1af?source=collection_archive---------21-----------------------

几个机器人,绝望地等待算法来建议他们如何在这个世界上行动。图片来自 Unsplash 。

对人工智能规划理论与当前多智能体系统强化学习研究之间的联系的直观高层次概述

在过去的十年中,强化学习和多智能体强化学习算法的研究取得了迅速的进展。有人可能会认为这是由于深度学习的兴起及其架构在 RL 任务中的使用。虽然在某种程度上这是真的,但 RL 的基础在于人工智能规划理论(已经发展了 50 多年),RL 可以被认为是被公式化为学习系统的规划问题。然而,RL 和规划理论之间的联系似乎很模糊,因为前者主要与当今大多数从业者的深度学习有关。

这一系列文章旨在从经典的寻路问题开始,对我们正在处理的世界进行严格的假设(确定性的、集中式的、单代理等)。)和逐渐放弃假设,直到我们以泥灰问题结束。在这个过程中,我们将看到几种适合不同假设的算法。然而,我们总是假设代理是合作的。换句话说,他们一起行动来实现一个共同的目标。

值得注意的是,本系列将集中在从 A*到 MARL 的“多代理系统路径”上。这将通过阐明我们想要解决的问题和我们对我们所处的世界所做的假设来实现。它当然不会是对所有算法及其在每个主题上的改进的深入回顾。

具体来说,我将回顾最优多智能体寻路(第 1 部分)、经典规划(第 2 部分)、不确定性下的规划(第 3 部分)以及部分可观测的规划(第 4 部分)。然后,我将结束我们在 RL 的旅程,并将其推广到多智能体系统(第 5 部分)。我将挑选有代表性的算法和想法,并在需要时向读者推荐深入的评论。

第 1 部分—路径查找

A 和 b 之间的两条最短路径图片来源。

寻路的根本问题是寻找两点之间的最短路径。具体来说,在寻路中,我们假设我们要为一个单智能体解决问题。此外,我们假设:

  1. 时间是离散的,一次只能采取一个动作。
  2. 动作是确定性的和无持续时间的,即应用动作是即时的,并且它将通过确定性函数来改变状态。
  3. 我们对世界有全面的了解,即障碍物在哪里,有多少个点,等等。

当然,我们还做了其他假设(即代理是合作的,而不是自利的)。然而,我的目标是只明确地写出那些我们很快就会试图放弃的假设。

人工智能中用于解决寻路问题的经典算法是 A。给定一个加权图,A维护一个从起始节点开始的路径树,并根据启发式算法一次扩展这些路径的一条边,直到到达目标。如果您对图、试探法和 A*还不熟悉,请点击链接查看对图和 A* 的精彩介绍。

推广到多智能体路径发现(MAPF)

A*解决了单智能体寻路问题。但是,在许多现实世界的应用中,我们要处理多个代理。因此,MAPF 举例说明了为所有代理找到最短路径以到达他们的目标而没有冲突的问题(即,没有几个代理可以同时在同一位置)。

我们所说的“最短”是什么意思?

对于单个代理,我们寻找它需要执行的最少数量的动作来达到它的目标。对于多个代理,目前有两个主要的路径长度度量标准:

  1. 成本总和 —听起来,简单地将所有代理路径的成本相加。
  2. 最大完工时间 —取最大单个代理成本。

显然,针对每个度量进行优化将会产生不同的最短路径解决方案。我将把重点放在优化成本总和的算法上。

指数搜索空间

幸运的是,A*时间复杂度是多项式的(给定一个好的启发)。通常,在计算机科学中,多项式运行时间被认为是有效的。能不能推广到多智能体,保持多项式时间复杂度?

首先,我们需要记住一个* 分支因子。图的分支因子是每个节点的子节点数。对于具有单个代理的 A,其中代理在每个时间步执行一个动作(来自 b 动作),分支因子是 b 。对于有 k 个代理的 A,在每个时间步,我们需要考虑所有代理(k)的所有可能行动(b),留给我们一个 b^k 的分支因子。对于一个有 5 个可能动作(等待,或向右/向左/向上/向下移动)的简单网格世界,20 个代理的分支因子是 5 ⁰ =95,367,431,640,625。显然,把 A*简单地推广到 MAPF 是不可行的。此外,MAPF 已经被证明是 NP 难的。

A*改进

那么,我们如何解决这个指数分支因子呢?早在 2010 年,Stanley提出了一个简单而强大的想法——让我们试着将问题分成更小的子问题,并解决每个子问题!具体来说,他提出了一个名为独立性检测(ID) 的迭代算法,该算法首先为每个代理单独搜索最短路径,并检查冲突代理。当发现几个冲突的代理时,它们被合并成一个组。重复这个重新计划和合并组的过程,直到所有的计划之间没有冲突。尽管该算法没有改善 A*的最坏情况时间复杂度,但事实上,它通过最大独立子问题中的代理数量将运行时间减少到指数级。

然而,对于仅由几十个代理组成的依赖组的问题,我们仍然有一个非常昂贵的搜索空间来探索。

所以斯坦德利建议修改搜索空间。正如我们现在所知,在 A的每个时间步,我们为所有代理的所有可能动作生成节点。然后,我们扩展具有最小 f 值(当前路径成本和未来成本的启发式预测之和)的节点。生成的成本高于最优成本的节点称为剩余节点。对 A的一个重要增强是避免生成多余的节点。

斯坦德利避免产生多余节点的方法叫做算子分解(OD) 。OD 建议为代理商申请订单。当扩展一个节点时,OD 只应用第一个代理的移动,引入一个中间节点。在中间节点,仅考虑下一个代理的移动,从而产生进一步的中间节点。当最后一个代理动作被展开时,生成一个常规节点

所以基本上,算子分解用树的宽度换取深度,希望一个好的启发式算法可以避免多余节点的产生。

另一个解决剩余节点生成问题的算法是 增强型部分扩展 A* (EPEA*) 尽管这里没有解释 EPEA,但重要的是要注意,实际上已经表明,给定关于域的先验知识,EPEA在避免生成过剩节点的任务上优于 OD。

移动到另一个空间

以上所有算法都在代理状态空间上执行 A。尽管 A增强确实显著提高了算法的性能,但对于具有许多代理(超过 100 个)的大型地图,通常计算量仍然很大。因此,过去十年开发的两种 MAPF 算法试图改变它们搜索的状态空间。两者都可视为两级解算器。

【递增成本树搜索(ICTS)

ICTS 结合了高层次和低层次的求解器。高级求解器搜索递增成本树(ICT)。在 ICT,每个节点包含每个代理路径允许的长度为 k 的成本向量。ICT 根节点包含一个向量,该向量具有每个代理的最短路径长度的成本(不考虑其他代理)。然后,低层求解器的工作是验证是否可以通过在高层求解器定义的成本下为每个代理单独规划来找到联合解决方案。值得注意的是,ICTS 低级解算器不为代理一起规划,而是只检查给定成本下单个代理路径之间的冲突。

如果低级解算器未能在给定成本向量下找到不冲突的最短路径,则高级解算器通过生成 k 个 ICT 节点来扩展 ICT 根,其中每个节点对应于将一个代理的成本增加 1。高级解算器执行 ICT 的广度优先搜索(这保证找到最优解)。

3 个代理的 ICTS 算法图解。摘自 罗尼斯特恩的 幻灯片。

对我来说,ICTS 会做得更好,这感觉很奇怪,但是通过对低级解算器的良好实现(使用 MDD )和对 ICT 节点的修剪技术,ICTS 可能会胜过其他最优 MAPF 算法。

值得注意的是,ICTS 并没有神奇地消除时间复杂性的指数因素。它仍然是指数级的,但取决于另一个因素——信息和通信技术的深度。因此,直观地,当单独规划时,由于最优解单代理路径成本将进一步远离单代理路径成本,高级求解器将需要建立更深的 ICT。ICTS 时间复杂度与深度成指数关系。

基于冲突的搜索(CBS)

CBS 也是一个两级求解器,在不同的状态空间中搜索。具体来说,它在冲突空间中搜索。

CBS 将代理与约束相关联。为特定的代理人 (a) 定义一个约束,一个他必须在特定的时间步( t )避开的位置( v )。一个约束由一个元组( av,t )表示。

对于每个单个代理,CBS 低级解算器搜索在给定一组约束的情况下一致的最短路径。CBS 高级解算器搜索约束树(CT)。CT 是一棵二叉树,其中每个节点包含一组约束和一个与约束一致的解(一致意味着满足所有约束)。低级解算器为每个单个代理找到一致的解决方案。然后,CBS 高级解算器检查单代理最短路径中的冲突。如果没有发现冲突,我们就找到了最优方案。然而,如果发现冲突,高级解算器分割相应的 ct 节点并生成具有避免我们发现的冲突的约束的节点。在 CT 上执行最佳优先搜索可以保证找到最优解。

一个典型的 MAPF 例子。CBS 将在时间步长 2 的位置 C 为其中一只老鼠生成一个带有约束的节点,然后将找到一个最佳的连接路径。图片来自哥伦比亚广播公司的论文。

在 CBS 开发的 6 年间,它作为一种强大的 MAPF 算法出现,并被建议进行许多改进。正在解决的主要缺点是它的运行时间与它需要解决的冲突数量成指数关系。因此,在有许多冲突的拥挤问题中,它将表现不佳。

将 MAPF 归结为另一个 NP 难问题

MAPF 的另一个有趣的工作是通过简化到其他 NP 难题。其背后的想法是,在过去的几十年里,研究人员已经为其他 NP 难题开发了强大的算法。因此,我们不需要开发 MAPF 算法,只需要减少 MAPF,使用现有的解算器。

我不会深究这些减少的细节,但我会声明这一系列的研究最近被证明可以产生非常强大的 MAPF 算法。成功解决 MAPF 约简的 NP-Hard 问题的部分列表包含布尔可满足性 (SAT)、混合整数规划 (MIP)、约束规划 (CP)。

那么…我应该使用什么 MAPF 算法呢?

嗯,看情况。基本上,如果你知道你的 MAPF 域的具体性质(它是一个大图吗?有多少特工?代理人拥挤吗?),目前的研究有一些关于使用什么算法的指导方针。然而,为 MAPF 问题选择最合适的算法目前正在研究中。最近,对不同的 MAPF 算法进行了全面的分析,并指出一些算法优于其他算法的情况。

动态问题需要不同的算法

一个自主交叉路口模型,其中每辆车都是一个代理。交集旨在最小化由几个代理之间的协调引起的延迟。视频来自 瞄准项目

MAPF 的动态变体将其扩展到广泛有趣的实际问题(如自主路口管理)。这是 MAPF 的一个非常有趣的变体。但是,在这一系列文章中,我们将重点放在从 A*到 MARL 的“多代理路径”上,不会深入探讨。我鼓励好奇的读者阅读关于在线 MAPF 和终身 MAPF 的论文。

结论

我们从单个智能体的最短路径搜索这一基本问题出发,将其推广到多智能体的路径搜索问题。我们看到,即使对于那个相对“简单”的问题,我们假设对世界、离散时间和确定性行为有全面的了解,找到一个最优解也是困难的,甚至可能是棘手的。然后,我们听到了 MAPF 对动力学问题的有趣概括。当然,MAPF 还有许多其他有趣的变体,比如自利的代理人,但我关注的是经典的 MAPF 问题。

接下来,我们将看看 AI 规划的广义问题,这是当我们的代理可以做的不仅仅是移动,而且需要完成更复杂的目标时的情况。然后,我们将继续去除越来越多的假设,直到我们最终得到多智能体强化学习。

确认

我要感谢我的理学硕士论文导师罗尼·斯特恩。我对这一领域和本博客系列的大部分内容的兴趣源于他在本古里安大学教授的关于多代理系统的精彩课程,我有幸参加了该课程。

从 A*到 MARL(第二部分——人工智能规划)

原文:https://towardsdatascience.com/from-a-to-marl-part-2-ai-planning-8ae635a6491d?source=collection_archive---------33-----------------------

许多智慧生物一起计划。人造的也能做到吗?图片来自 Unsplash 。

对人工智能规划理论与当前多智能体系统强化学习研究之间的联系的直观高层次概述

在过去的十年中,强化学习和多智能体强化学习算法的研究取得了迅速的进展。有人可能会认为这是由于深度学习的兴起及其架构在 RL 任务中的使用。虽然在某种程度上这是真的,但 RL 的基础在于人工智能规划理论(已经发展了 50 多年),RL 可以被认为是被公式化为学习系统的规划问题。然而,RL 和规划理论之间的联系似乎很模糊,因为前者主要与当今大多数从业者的深度学习有关。

这一系列文章旨在从经典的寻路问题开始,对我们正在处理的世界进行严格的假设(确定性的、集中式的、单代理等)。)和逐渐放弃假设,直到我们以泥灰问题结束。在这个过程中,我们将看到几种适合不同假设的算法。然而,我们总是假设代理是合作的。换句话说,他们一起行动来实现一个共同的目标。

值得注意的是,本系列将关注从 A*到 MARL 的“多代理系统路径”。这将通过阐明我们想要解决的问题和我们对我们所处的世界所做的假设来实现。它当然不会是对所有算法及其在每个主题上的改进的深入回顾。

具体来说,我将回顾最优多智能体寻路(第 1 部分)、经典规划(第 2 部分)、不确定情况下的规划(第 3 部分)和部分可观测的规划(第 4 部分)。然后,我将结束我们在 RL 的旅程,并将其推广到多智能体系统(第 5 部分)。我将挑选有代表性的算法和想法,并在需要时向读者推荐深入的评论。

第二部分——人工智能规划

在第 1 部分中,我们处理了寻路问题,我们的目标是为一组代理找到从起点到终点的最短路径。在这篇文章中,我们将讨论人工智能规划,它可以被认为是 MAPF 问题的推广。总的来说,计划的任务是找到一系列动作,这些动作将把开始状态转变为目标状态。我们将从单智能体规划问题开始,并推广到多智能体,类似于我们上一篇文章中的路径。

人工智能规划简史

从早期开始,人工智能规划的圣杯就是创造一个独立于领域的问题解决者。这个独立于领域的问题求解器有望解决所有类型的规划问题,从玩游戏到制作 cookies。1959 年, GPS 论文介绍了一种通用问题求解器,可以解决由良构公式表示的问题。它是为定理证明而设计的。然而,由于几个原因,它不太适合规划问题。例如,如何表达并发事件和生成的计划的偏好是不直观的。

这项工作激励了斯坦福研究所的研究人员,他们已经在机器人Shakey上工作,开发了一种适合于规划的格式良好的语言和领域独立的规划算法,称为 STRIPS 。几年来,其他几种语言和规划者被提出。具有不同表达能力的几种不同语言的发展,使得规划者之间的比较成为一项困难的任务。一项标准化人工智能规划的尝试在 1998 年完成,叫做 PDDL。

机器人 Shakey,60 年代的一个高影响力研究项目。哦,你问为什么是“Shakey”?嗯,“抖得厉害,绕着转。图片来自维基百科。

经典人工智能规划假设

在经典规划问题中,我们处理可以完全观察到的确定性环境。目前,我们还假设只有一个代理。

规划领域定义语言(PDDL)

PDDL 是一种我们用来定义初始状态、目标状态和我们的代理可以执行的动作的语言。本质上,PDDL 问题是由条件、动作、初始状态和目标状态定义的。一组条件描述了一种状态,以及由它们引起的效果和它们适用的先决条件所定义的动作。

一个著名的规划例子是空运货物装载问题。我们将关注一个简单的问题,有两个城市(TLV 和纽约),两架飞机(P2 的 P1)和两种不同的货物(C2 的 C1),我们希望在这两个城市之间中转。在我们的初始状态,我们在 TLV 有 C1 和 P1,在纽约有 C2 和 P2。我们的目标是让 C1 在纽约,C2 在 TLV。让我们在 PDDL 写吧。

Init(At(C1, TLV) ∧ At(C2, NYC) ∧ At(P1, TLV) ∧ At(P2, NYC))Goal(At(C1, JFK) ∧ At(C2, SFO))

现在是时候定义行动了。基本上,我们希望我们的飞机能够装载货物,在城市之间飞行,然后卸载货物。非常简单。它可以简单地定义为:

action(LOAD(cargo,plane,city),precondition: At(cargo,city) ∧ At(plane,city)effect: ¬At(cargo,city) ∧ In(cargo,plane))action(FLY(plane,from,to),precondition: At(plane,from)effect: ¬At(plane,from) ∧ At(plane,to))

请注意,即使这可能是不直观的,一旦飞机装载货物,货物就不再被定义为在城市,如“装载”动作的效果所定义的。此外,您可能已经注意到“卸载”操作不见了。你自己能想出来吗?

重要提示— 为了全面定义 PDDL 的问题,我们需要正确定义我有意跳过的其他一些东西。例如,我们需要定义我们正在使用的类型(货物、飞机等。).你会在真实的 PDDL 问题定义中遇到这种情况,但我相信这并不是理解一个经典人工智能问题的本质所必需的。如果你对完整的定义感兴趣,我写在纸条上——瞎搞。你可以解决它,找到 6 步解决方案!

人工智能规划算法

既然我们知道如何定义我们的计划问题,是时候学习如何解决它了。解决规划问题的简单方法是首先将所有适用的动作应用于初始状态,以创建一组后续状态。然后,我们将继续对这些后继者应用所有适用的动作,直到我们达到目标状态。然而,由于适用的动作数量可能相当大,这种幼稚的方法是不切实际的。它是否让你想起了不知情的图搜索算法,比如 BFS/DFS?是的,就是这样。因此,人们可能会要求遵循一个 A知情的方法,并使用启发式。事实上,从经典的寻路中,我们知道添加一个好的可接受的启发式算法对于有效地解决大型状态空间问题是必不可少的。还有,我们记住,对于 A保证最优性,启发式必须是https://en.wikipedia.org/wiki/Admissible_heuristic#:~:text=In computer science%2C specifically in,current point in the path.(即永远不要高估达到目标的成本)。

独立于领域的计划者的试探法

然而,一个问题出现了。我们怎样才能提出一种启发式方法,以一种独立于问题的方式,对特定问题的知识进行编码?我们需要一种方法,从 STRIPS 问题定义中自动生成一个可接受的启发式函数。一种简单的方法是将我们的规划问题 P 简化为一个更简单的问题 P ,计算 P 的最优成本,并将其用作启发式算法。P 的一个可能的放松是移除所有动作“负面影响”(即,使条件为假的所有影响)。例如,在 p '中,即使在将货物装载到飞机上之后,它也停留在机场中。尽管这种方法确实会产生可接受的启发式算法,但是计算它可能仍然是 NP 难的,这错过了启发式算法的目标,即有效地通知搜索朝向目标

1998 年, HSP 算法提出了一种近似启发式的方法。本质上,它建议解耦目标条件,并计算来自给定状态的动作数量,以分别满足每个条件。那么,启发值将是实现所有条件的所有动作的总和。

状态 s 中的启发式值是实现目标 g 的每个条件 p 的动作的总和。

为了计算满足每个条件的动作数量,我们迭代地更新下面的函数,直到观察到其值没有变化:

达到一个条件的动作数 p 迭代更新,直到函数不变。

在每一次迭代中,我们应用其相应的前提条件在当前状态下成立的所有动作。

假设目标条件是独立的,并且解决宽松的 p '问题结果给我们提供了信息启发,正如在各种 AI 规划竞赛中所示,这对于解决大型问题是有用的。然而,这些假设是有代价的。这种试探是不允许的,因为独立的目标条件可能包含多余的行动。

然而,如果我们选择用解决问题的数量来换取最优化,我们可以创造一个信息量较少但可接受的启发。我们可以采用上述启发式算法的一种变体,称为“最大启发式算法”。基本上,我们不是对所有独立的目标条件求和,而是取要满足的动作数量最多的条件。

通过计算实现目标的一个独立条件的最大动作数,给出一个可接受的启发。

倒退!

无论我们使用的是允许还是不允许的启发式算法,我们仍然需要为每个状态计算它,以便在启发式搜索算法中使用它,例如 A*。为每个状态计算这个启发式算法消耗大约 80%的搜索时间。一个简单而有效的解决方案是反转搜索方向。向后搜索,从目标状态到起始状态,称为回归搜索

直观上,回归法就是“我要吃饭,所以我需要做晚饭,所以我需要有吃的,所以我需要买菜,所以我需要去商店”的过程。在每一步,它选择一个可能有助于满足目标条件之一的动作。

使用回归方法的关键点是初始状态在搜索过程中不会改变,因此我们可以利用已经计算的启发式算法,并且更有效地执行搜索。关于使用 HSP(表示为 HSP-r)的回归方法的实现,我忽略了一些微妙的地方。更多细节可在 HSP-r 文件中找到。

超越搜索算法

正如我们之前了解到的,在 MAPF 问题中,为一个问题开发的算法可能对解决另一个问题有用。在人工智能规划中也是如此,通过将规划问题转化为一个布尔可满足性问题 (SAT)来给出一个强大的规划器。一个这样的计划者叫做 SatPlan 。

快速回顾

在继续讨论多代理系统之前,让我们快速回顾一下。我们看到了一种语言来表示规划问题及其相应的领域,称为条形或 PDDL。然后,我们看到了为这些规划问题构建独立于域的求解器的几种方法。其中一些是天真的不知情的搜索算法,其他的稍微复杂一点。当然,这只是现有算法中试图解决人工智能规划问题的一小部分。查看关于人工智能规划的章节,了解更多详情。

推广到多智能体规划(MAP)

在我们的物流玩具示例中,有 2 架飞机。我们可以很容易地想象现实世界中数百架或更多飞机的物流问题。正如我们之前在 MAPF 的上下文中所学的,对多智能体系统的简单概括会导致相对于智能体数量而言更加困难的问题。地图也是如此。因此,我们需要找到一种有效的方法来利用现实生活中多代理系统的一个共同事实——不同的代理可能是松散耦合的。这种将规划问题分解成子问题并合并其解决方案的重复出现的主题是大多数多智能体系统的核心的基本思想。事实上,我们已经在 MAPF 看到了它,我们也将在下一篇关于 MMDP 的文章中看到它。

此外,现实生活中的多智能体规划可能涉及几个不同的团体,它们合作实现一个共同的目标,但是希望保持某些信息(即,动作和条件)的私密性。考虑一个军事秘密任务,其中多个机器人在敌后协调工作。我们不希望每个机器人包含所有其他机器人的完整信息(例如机器人的数量、位置、设备等)。),因为它可能会受到损害。我们也可以想到几家企业为了一个特定的使命而合作,不想泄露私人信息。

目前,据我所知,在多智能体规划领域,多智能体规划的隐私保护算法是一个非常活跃的研究领域。虽然它的动机是隐私保护,但它对分布式多智能体规划是有用的,这为松散耦合的多智能体规划问题提供了有效的算法。这是一个有趣的工作,但我们将跳过它,继续我们的道路上的泥灰岩。我建议好奇的读者去读一下脱衣舞娘、 MAFS 和安全 MAFS 。

结论

我们从独立于领域的规划问题的定义开始。在快速的历史回顾和一个条状玩具问题之后,我们学习了基于搜索的算法,如何从规划问题中自动提取启发,以及搜索方向的重要性。然后,我们看到了解决规划问题的非基于搜索的算法。我们研究了广义 MA-STRIPS 问题的情况,并看到了它在分布式规划者和隐私保护条件下的应用。

下一个,我们将继续我们的 MARL 之路,因为我们将放弃关于确定性动作和状态的全部知识的假设。特别是,我们将讨论马尔可夫决策过程(MDP)和部分可观测 MDP (POMDP),正如我们将在后面看到的,它们是基于模型的 RL 的基础。

确认

我要感谢我的理学硕士论文导师罗尼·斯特恩。我对这一领域和本博客系列的大部分内容的兴趣源于他在本古里安大学教授的关于多代理系统的精彩课程,我有幸参加了该课程。

从 A*到 MARL(第三部分——不确定性下的规划)

原文:https://towardsdatascience.com/from-a-to-marl-part-3-planning-under-uncertainty-ae2e2578591d?source=collection_archive---------35-----------------------

在计划的时候,我们不应该只依靠好运气。我们如何为不确定性做计划?图片来自 Pixabay 。

对人工智能规划理论与当前多智能体系统强化学习研究之间的联系的直观高层次概述

在过去的十年中,强化学习和多智能体强化学习算法的研究取得了迅速的进展。有人可能会认为这是由于深度学习的兴起及其架构在 RL 任务中的使用。虽然在某种程度上这是真的,但 RL 的基础在于人工智能规划理论(已经发展了 50 多年),RL 可以被认为是被公式化为学习系统的规划问题。然而,RL 和规划理论之间的联系似乎很模糊,因为前者主要与当今大多数从业者的深度学习有关。

这个博客系列旨在从经典的寻路问题开始,对我们正在处理的世界进行严格的假设(确定性的、集中式的、单代理等)。)和逐渐放弃假设,直到我们以泥灰问题结束。在这个过程中,我们将看到几种适合不同假设的算法。然而,我们总是假设代理是合作的。换句话说,他们一起行动来实现一个共同的目标。

值得注意的是,本系列将关注从 A*到 MARL 的“多代理系统路径”。这将通过阐明我们想要解决的问题和我们对我们所处的世界所做的假设来实现。它当然不会是对所有算法及其在每个主题上的改进的深入回顾。

具体来说,我将回顾最优多智能体寻路(第 1 部分)、经典规划(第 2 部分)、不确定条件下的规划(第 3 部分)和部分可观测的规划(第 4 部分)。然后,我将结束我们在 RL 的旅程,并将其推广到多智能体系统(第 5 部分)。我将挑选有代表性的算法和想法,并在需要时向读者推荐深入的评论。

第 3 部分——不确定情况下的规划

前一章讨论了确定性世界中的计划,计划者可以生成一系列行动,知道如果它们以正确的顺序执行,目标将必然产生结果。现在,我们转向非确定性世界的情况,在这里我们必须解决当事情不按预期发展时该怎么办的问题。

有人可能会对这个问题提出天真的解决方案。例如,我们可以(通过一些传感器)监控“故障”,并在这种情况下启动重新计划。然而,对于许多现实世界的应用程序来说,在每次失败时重新计划是不可取的,因为这样太慢了。另一方面,我们可以为计划执行过程中可能出现的每一种可能情况制定一个反应计划。它将生成一个快速且健壮的计划,然而为具有许多状态的非平凡域找到该计划将是非常昂贵的。因此,我们寻求在规划时处理不确定性并产生稳健计划的算法。

几乎任何事物都存在某种程度的不确定性。规划的时候怎么才能考虑进去呢?图片来自 makeameme 。

在上一篇文章中,我们学习了如何用长条/PDDL 来表示一个规划问题。我们用一组动作和条件定义了域。具体问题用初始状态和目标状态来定义。然而,如何扩展这种语言以包含不确定性并不简单。

规划社区采用了马尔可夫决策过程(MDP) 对问题建模。MDP 定义如下:状态动作、转移函数、奖励函数。状态和动作很简单,本质上与经典规划问题相同。转移函数为(s1,a,s2)的每个三元组分配一个概率。它定义了在状态 s1 应用动作 a 后,在状态 s2 结束的概率。****奖励功能简单地分配处于一种状态并执行一个动作的奖励。

将规划问题建模为 MDP 的关键假设是 马尔可夫属性 基本上,它说鉴于现在,未来独立于过去。这就是为什么我们只能用(s1,a,s2)的三元组来定义它,认为(s1,a)是现在,s2 是可能的未来。如果我们不做这样的假设,我们将很难定义转移函数,因为我们需要将每条可能的路径与概率联系起来。然而,对于一个给定的问题,确定马尔可夫性质是否成立并不容易。一个玩具的例子将从这个 MSE 答案考虑一个有两个红色球和一个绿色球的骨灰盒。两次抽签都是从骨灰盒中进行的,没有更换。只知道最后一次抽球的颜色与知道两次抽球包含的信息不同。然而,在这篇文章中,我们将假设马尔可夫性质成立。我建议好奇的读者去读读马尔科夫或者不读马尔科夫。

形式上,根据马尔可夫性质,转移函数定义为:

过渡函数。它模拟了在状态 Si 中应用动作 Ak 时到达状态 Sj 的概率。

假设问题公式化为由状态、动作、奖励函数和转移函数组成的 MDP,我们需要定义什么是该 MDP 的最优解?经典的规划问题是从初始状态到目标状态的一系列动作。然而,单一的动作序列不适用于不确定性问题。因此,我们寻求一个从状态映射到行动的策略最优策略是使期望报酬最大化的策略。换句话说,在所有可能的政策中,遵循每个州的最优政策平均会产生的最高回报。当我们以这种方式定义最优策略时,你看到我们所做的隐含假设了吗?在某种程度上,我们假设了一个理性的代理人。****

你们中的一些人可能想知道 MDP 是如何概括规划问题的?嗯,典型的经典规划问题可以被视为 MDP,其中世界是确定的,并且只有一个目标(例如,除了目标状态为 1 之外,所有状态的回报都为 0)。

在继续研究旨在为 MDP 找到最佳策略的算法之前,请注意,我们现在处理的不确定性仅源于控制误差,而非传感器误差。我们假设我们完全观察到状态,并且在观察中有确定性。

寻找最佳策略

求解 MDP 的算法旨在找到最优策略。我们把它定义为平均来说,从每个州获得最高回报的政策。在数学上,我们希望找到最大化一个价值函数整体状态的策略。对于策略(由 π 表示)在状态 s 的价值函数是:

策略 π 的值函数,在状态 s 评估

寻找最优策略归结为解决以下优化问题:

最优策略是为每个状态选择最大化价值函数的行动的策略。

如果阅读这些公式感觉令人生畏或不直观,就想一想它们的基本意思。他们建议,为了找出在每个状态下采取什么行动来实现最优政策,我们只需要对所有可能的状态进行平均,从该状态开始遵循政策,收集奖励,并根据出现的概率来衡量每个奖励。在你的头上运行它,它会突然看起来像一个非常天真的蛮力解决方案。

重要提示—

  1. 通常,会使用该公式的一个变体,将其扩展到考虑折扣奖励。折扣奖励基本上意味着提前获得的奖励比推迟获得的奖励更有价值,这是许多现实世界问题的情况。
  2. MDP 可以分为两类——有限和无限时域 MDP。简单来说,有限时域 MDP 处理的是执行时间跨度有限的问题,无限时域 MDP 处理的是“永远运行”的问题。在这篇文章中,我主要关注有限的 MDP。

这个优化问题最常见的算法,名为价值迭代和策略迭代,使用的是动态规划。主要思想是通过递归地将问题分解成更简单的子问题来解决问题。

值迭代&策略迭代

策略迭代算法在两个阶段之间交替——策略评估和策略改进。在评估阶段,我们将当前策略视为固定的,并计算每个状态的值函数。在改进阶段,我们根据上一阶段评估的价值函数修改策略,为每个状态选择最佳动作。我们执行几个评估和改进步骤,直到策略没有变化。换句话说,改进步骤不会改变在每个状态下要采取的行动。执行的阶段顺序如下:****

由策略迭代算法执行的一系列评估和改进阶段。

值迭代算法建议将这两个阶段合并为一个阶段。从设置为零的初始值函数开始(即,所有状态都具有值 0),它通过迭代每个状态的所有可能的动作并选择最大化当前奖励加上下一状态值函数的动作来更新值函数。它这样做,直到所有状态的值函数都没有变化。然后,使用最优值函数,通过选择使每个状态的值函数最大化的动作来构造最优策略。

因为这两种算法都是众所周知的,所以我不会深入算法实现的细节。我建议您查看一些简单而又不错的策略迭代和值迭代算法实现。此外,尽管这些算法倾向于在相对较少的迭代中收敛,但是每次迭代都要求计算时间至少与状态空间的大小成线性。这通常是不切实际的,因为状态空间随着感兴趣的问题特征的数量呈指数增长。这个问题有时被称为“维数灾难”。

推广到多代理 MDPs

将我们描述的 MDP 推广到多智能体的情况,需要我们记住一个关于智能体本质的重要假设。我们假设他们是合作的,因为他们一起行动来实现一个共同的目标。关于非合作智能体的研究是介于博弈论和人工智能之间的一个令人兴奋的研究领域。它着重于两个(或更多)具有不同兴趣的主体,通过它们的报酬函数形式化,共存于同一个世界,并且它们的行为可以影响彼此的报酬。这是题外话,但我希望下次再写。

回到我们的多智能体 MDP (MMDP)与合作智能体的操作,以最大化联合奖励功能,有人可能会问,为什么我们不能把它建模为一个“大 MDP”,其中行动空间是所有智能体的联合行动空间,状态空间是所有智能体的联合状态空间。这当然是可行的,但是做了一个关键的假设,这个假设对于许多多智能体系统是不合适的。它假设存在一个中央实体,该实体为所有代理导出计划并向他们发送各自的最优策略。因此,研究人员将注意力集中在分散的情况下,在这种情况下,每个代理人都应该得出自己的最优策略。在这种情况下,主要的挑战是如何将多个单独的最优策略组合成一个最优的联合策略。

事实上,MMDP 为多智能体系统指定了一个分散的 MDP,其中每个智能体都知道完全问题 MDP** (所有状态,所有动作,以及所有智能体给定动作的状态之间的相应转移函数)。因此,每个代理都可以通过自己求解完全 MDP 来找到最优策略。从这些最优政策中,人们可以组成联合政策。联合策略是每个状态到每个代理动作之间的映射。然而,从几个单独导出的最优策略构建一个联合策略能确保最优吗?不幸的是,没有。既然最优策略不是唯一的,我们怎么能确定所有的代理都遵循相同的最优策略呢?下面是一个简单而著名的例子,它说明了由于以分散的方式得出多个最优策略而需要协调。两个代理(命名为 A 和 B)解决联合 MDP。当两个代理移动到相同的位置(G1 或 G2)时奖励是 1,当他们移动到不同的位置时奖励是 0。这个 MDP 有两个最优策略,第一个是双方都选择去 G1,第二个是双方都选择去 G2。然而,如果代理人 A 选择了第一个最优策略,而代理人 B 选择了第二个,会发生什么呢?**

一个双代理协调问题。图片来源。

这个问题一般被称为协调问题。解决这个问题主要有三种途径。首先,我们可以假设代理的能力是 沟通 (“让我们左转!”).第二, 共享约定 可以被定义,这将导致对所有代理的最优策略的一致选择(“按字典顺序选择动作。如果左右都可选,那就选左!”).第三,如果没有给出共享约定或通信,代理可以 学习协调 是否可以玩几个游戏(“啊-啊。我看到你在这种情况下选择向左。下次见!”).我们不会深入研究解决协调问题的不同算法。我鼓励你点击上面的链接获取更多信息。

然而,即使我们假设要解决的协调问题,让每个代理解决完整的 MDP 带来了很高的计算成本。正如我们在 MAPF 和多智能体规划中已经看到的,如果天真地对待多智能体问题,智能体数量的线性增长会导致计算复杂性的指数增长。一般来说,对于有多个代理的系统,求解每个代理的完全 MDP 是很困难的。此外,所有代理都知道所有其他代理、状态和动作的假设在许多现实世界系统中并不成立。

因此,建议采用 DEC-MDP (分权 MDP)的模式。与 MMDP 相反,它不假设每个代理都知道完整的 MDP。它只假设联合 MDP 状态可以从所有智能体的状态集合中导出。但是我们怎样才能最优地解决一个 MDP 问题呢?不幸的是,已经证明分散的多代理 MDP 很难最优求解 (NEXP-Complete)。然而,已经有人提出了几种尝试,以一种易于处理的方式为特定情况的分散化 MDP 建模。

例如, 变迁独立(TI-MDP)是 DEC-MDP 的一个特例,其中一个代理的状态变迁独立于其他代理的状态和动作。本质上,当一个代理采取的行动不影响其他代理时就是这种情况。注意,这并不意味着我们可以将 n 个代理人的 MDP 分解成 n 个不同的 MDP。只有当我们进一步假设奖励独立,时,我们才能分解它,这基本上意味着奖励函数可以表示为 n 个不同奖励函数的总和,其中每个奖励函数只知道单个代理的行为。一个激励人心的例子是一组机器人一起扫描一个领域来寻找东西。如果另一个代理人之前已经扫描了一块给定的土地,那么扫描这块土地的奖励会更低,因此奖励不是独立的。TI-MDP 的最佳算法在他们的论文中有详细描述。****

虽然 IT-MDP 和 DEC-MDP 的其他子类产生最优策略,但一般的 DEC-MDP 并非如此。因此,许多研究致力于寻找近似解。

DEC-MDP 的近似解

寻找 DEC-MDP 的近似解可以分为两种方法。第一种方法通过测量它们的解与最优解相比有多差来建议保证解质量的算法。Bernstein 在 2005 年的博士论文中提出了一种收敛到ε-最优解的算法。第二种方法提出了没有性能保证的算法。我们将在下一章讨论 DEC-POMDPs 的算法时,看到这种方法的算法。

结论

MARL 的一个重要里程碑是本文中介绍的不确定性概念。首先,我们定义了如何使用 MDP 对规划问题的不确定性进行推理,以及什么是不确定性下的最优概念。然后,我们学习了旨在找到最优策略的算法。最后,我们看到了几个将 MDP 推广到多代理设置的框架。这些框架的不同之处在于几个假设,如中央权威的存在和代理之间的相互依赖性。一般来说,分散多主体 MDP 的最优解很难找到,我们简要讨论了寻找近似解的方法。

接下来,我们将放弃另一个关于可观测性的关键假设,引入部分可观测 MDPs (POMDP)框架。类似于我们在本章中所做的,我们将看到这个 POMDP 框架对分散式多代理情况的推广。然后,我们将准备在马尔结束我们的旅程。

鸣谢

我要感谢罗尼·斯特恩,我的理学硕士论文导师。我对这一领域和本博客系列的大部分内容的兴趣源于他在本古里安大学教授的关于多代理系统的精彩课程,我有幸参加了该课程。

从精算师到数据科学家——我是如何做到的

原文:https://towardsdatascience.com/from-actuary-to-data-scientist-how-i-did-it-643b4035db2?source=collection_archive---------16-----------------------

没有编码背景如何成为数据科学家

在 Unsplash 上由 Austin Distel 拍摄的照片

如果你像我一样——喜欢科技和数据。在这个数字时代,人们开始意识到技术正在给人类带来疯狂的好处,而驱动这种好处的是人类。

是的,没错,我听从了我的召唤。

人们把军队称为国家的第一道防线,医生和护士是医疗的第一线。嗯,我们称自己为创新的最前沿。

Gif 作者Reddit.com

我相信在某些时候,你会对如何进入数据行业有点好奇。需要哪些技能,如何开始?

业内人士必须分享他们的经验,这样想进入数据领域的局外人才不会感到害怕。而你很幸运,我在这里和你分享在没有任何编程知识的情况下,我是如何成为一名数据科学家/工程师的。

背景

我最近转向了数据工程。在此之前,我有 2 年多的数据科学经验。为了真正理解我是如何做到的,我们必须从头开始。

高中时,我擅长科学和数学,毕业时获得了保险精算学位。我是你的平均水平,学习成绩略高于平均水平。在大学期间,我甚至有几门课不及格。我从未写过一行代码,直到我的第一堂课——

编程入门——Java,并不完全是最好的入门语言。我没有在课堂上挣扎,但我也没有爱上编程。我只是把它当成了我在其他课堂上的表现。

重要的是你选了一门与编程相关的课程,并且不讨厌它。我知道有些人无法忍受阅读 5 行代码,他们会立即想吐,这完全可以理解。混乱的代码令人厌恶,如果你是从 Java 开始的,它也没有帮助,语法不是最友好的。

取而代之的是,尝试上一堂 Python 或 HTML CSS 的入门课。把你的脚弄湿,看看感觉如何。如果你能连续花两个多小时想出如何打印“Hello World!”并且觉得自己发明了第一个灯泡,恭喜,这说明你并不厌恶代码。有机会可以进入数据科学。

Gif by Max

实习

这是我进入数据科学的主要原因之一。
由于这是一个新行业,当时没有任何数据科学学位或某种学术证明证明我是数据科学实践方面的大师。

我所有的就是我的激情,那是最起码的。

如果你没有经验证明自己,实习是最优解。我很幸运地加入了我国一家最大银行的数据仓库团队,这是通过我的一个朋友牵线搭桥实现的(稍后会有更多介绍)。在那里的时候,我知道了自己喜欢什么,不喜欢什么。

这也是了解这个行业的一个好方法,你的日常工作是什么样的。据《金融时报》报道,机器学习工程师和数据科学家是在本领域之外寻找新工作的首选职业。这不是一个健康的迹象。

其中一个主要原因是期望和现实之间的差异。

因此,在投身数据行业之前,先帮自己一个忙,在数据行业实习。通常情况下,如果你的表现达到预期,公司会在几个月后将你转为永久职位,是的,我是根据经验来说的。

Miguel 发来的 Gif

SQL 和 Python

现在我们在谈话。在数据实践中有几种编程语言。但是发光的肯定是 SQL 和 Python 。这些语言是必须学习的,好的一面是它们非常容易掌握。

在我实习之前,我从来没有写过一行 SQL 或者 Python。在资深同事的帮助下,我很幸运地通过实习学会了这一点。我也通过免费的在线资源学到了很多,比如 Youtube 和 Udemy。

另外,StackOverflow 是你最好的朋友。

来自期限的 Gif

在问你的同事一个 SQL 问题之前,你的问题的答案很有可能已经在 StackOverflow 上了。你不妨早点和它建立关系,StackOverflow 会在你的数据之旅中陪伴你很久很久。学会有效浏览

有人说 SQL 甚至不是一种编程语言。我同意这一点。 SQL 或结构化查询语言是数据库的语言,对于与数据打交道的人来说,你可以想象你会经常使用它。

SQL 现在被低估了。能够编写高效、优化和复杂的 SQL 的人越来越少。记住我的话,这将是成为数据科学家最起码的技能。

在 SQL 上,学习—

  • 加入
  • 案例时
  • 凡条件
  • 分区依据

它将设置您运行至少 80%的所需数据提取。这里有一些额外的 SQL 函数,你可以学着玩玩。

</5-bigquery-sql-commands-you-probably-didnt-know-about-ebfd9d0dc160>

获得数据后,你需要对其施展某种数据科学魔法,包括—

  • 数据操作
  • 数据可视化
  • 数据建模

向你的客户提供某种结果。
要做到这一点, Python 就是游戏的名字。

Python 和 R 从一开始就主导了数据科学领域,但是随着最近在数据科学领域对 Python 支持的增加,很明显每个人都在使用 Python。

对 Python 的支持是疯狂的。Youtube 上有很多很好的免费课程,可以帮助你入门。对于 Python,学习—

  • 熊猫
  • Numpy
  • Matplotlib,Seaborn,Plotly
  • Scikit-Learn

为了让你开始,这里有一个关于熊猫的免费指南。

面试

照片由 Amy Hirschi 在 Unsplash 上拍摄

要想在面试中表现出色,你必须先得到它。
抛开所有显而易见的建议,比如整理你的简历(1 页),我给你留下一个立即获得工作面试的最强大的资产——人脉

花时间去了解你的同事,甚至你大学的朋友。真诚地对待他们。谁知道呢?他们中的一个可能会在你梦想的公司找到一份工作,而你的工作可能只需要打两个电话就能搞定。

事实——我通过一个朋友得到了我的前两个角色。

经理们每天都会收到数百份简历。他们不想全部看完。如果他们的一个同事推荐你,他们会立刻给你一个机会——你可以相信我的话。

数据项目

在参加面试之前,确保你有一些作品要展示。不要谈论你做的那个项目,而是展示给他们看。

做一些有趣的东西,并在某个地方举办。

可以参考kaggle.com获取灵感。
我个人从零开始建了一个 网站 来托管我所有的作品,免费!
我已经在这里写下了所有相关内容—

所以,你已经得到了面试,你有工作要展示。这一切都归结到最后一部分,沟通。如果你的目标是成为一名优秀的数据科学家,沟通是关键。

想想吧…

在你建立了完美的模型,或者进行了深入的分析之后,会发生什么呢?你工作的全部意义在于将数据发现传达给每个人,这需要很好的沟通。

因此,能够在面试中很好地表达自己是一个巨大的优势。我知道面试官正在寻找这样的机会。

为了完善面试的艺术,最好的建议是不断练习。在得到第一个角色之前,我被拒绝了很多次。不要放弃。
寻求反馈如果被拒绝了,我相信他们会很乐意帮你解决的。

结论

费尔南多·巴西在 Unsplash 上拍摄的照片

如果你还在这里,你一定对数据很认真。感谢你阅读我的经历。

总之,以下是我对进入数据科学的建议—

  • 参加编程课程,最好是 Python 或 HTMLCSS
  • 获得数据科学相关的实习机会
  • 学习 SQL 和 Python,特别是与数据相关的库
  • 从事与数据科学相关的项目
  • 与同事交流
  • 提高你的面试技巧
  • 要有激情!

这听起来很简单,但确实有效。祝你好运!
和往常一样,我以一句名言作为结束。

学习数据科学的最佳方式是去做数据科学— Chanin Nantasenamat

订阅我的时事通讯,保持联系。

我们的数据之旅还没有结束。我正在撰写更多关于数据行业的故事、文章和指南。你绝对可以期待更多这样的帖子。与此同时,可以随时查看我的其他 文章 来暂时填补你对数据的饥渴。

感谢 的阅读!如果你想与我取得联系,请随时联系我在 nickmydata@gmail.com 或我的 LinkedIn 个人资料 。也可以在我的Github中查看之前写的代码。

从 AlexNet 到 NASNet:卷积神经网络的简史和介绍

原文:https://towardsdatascience.com/from-alexnet-to-nasnet-a-brief-history-and-introduction-of-convolutional-neural-networks-cf63bf3320e1?source=collection_archive---------10-----------------------

用 Keras 实现了一个简单的 ResNet

向昨天学习,为今天而活。

——阿尔伯特·爱因斯坦

历史上,图像上的机器学习一直是一个巨大的挑战,直到 2012 年, AlexNet 赢得了 ImageNet 竞赛的一等奖,并得到了公众的关注。从那以后,卷积神经网络或 CNN 发展得如此之快,以至于 AlexNet 很快就成为了过去。在图像处理方面,CNN 已经大大超过了人类的表现。

然而,CNN 的概念早在 30 多年前就已经提出并付诸实践。CNN 或深度学习变得如此有效和流行的主要原因是过去十年数据和计算能力的丰富和民主化。

在接下来的几节中,我将首先谈谈为什么 CNN 要处理图像。然后,我将简要地向你介绍各种 CNN 类型,沿着时间和架构的演化轴。我还会讲一下 AlexNet,VGGNet,InceptionNet,MobileNet,ResNet,NASNet 这些有代表性的架构。最后,我将用一个我在 Keras 中实现的 ResNet 的简单实现来演示。

1.为什么 CNN 关注图像

1.1 图像上正常神经网络的问题

每幅图像都有成千上万个像素,每个像素都被视为一个特征,这意味着对于一幅 1000 * 1000 的图像,有 1,000,000 个特征。对于正常的前馈神经网络,每一层都与前一个输入层全连接。

假设例如我们使用一个具有一百万个神经元的单层的普通前馈神经网络来处理图像,所需的参数数量是 1000 * 1000 * 10⁶ = 10。普通神经网络进行图像学习所需的参数太多了。

但是网络中参数太多的问题是什么?首先,它很容易过度训练,并且需要大量的数据来进行适当的训练。其次,训练和预测需要更多的内存和计算。

1.2 CNN 为什么工作

让我们回到图像的主要特征。使 CNN 作用于图像的图像特征主要有两个,分别是特征定位特征独立于位置

特征定位:每个像素或特征与其周围的其他像素密切相关。例如,鼻子上的像素的相邻像素很可能也是鼻子的像素。

特征位置无关:每个特征都是相同的,不管它在图像中的什么位置。例如,不管鼻子在图像上的位置如何,它仍然是鼻子。

CNN 利用局部连通网络 ( 特征定位)的共享参数 ( 特征位置独立)解决了参数过多的问题,也称为卷积网。在前面的示例中,使用卷积网络可以将参数的数量从 10 个减少到 10 个。

从神经网络角度看 CNN

1.3 CNN 的主要组件

CNN 有 3 个主要组成部分,分别是卷积汇聚全连接层

卷积层由滤波器步长组成。过滤器是本地连接的网络,每个网络学习图像的一些特定特征。每个滤波器以配置的步长(称为步幅)在图像周围移动。例如,对于步长为 1 的大小为 10 * 10 的过滤器,每次过滤器窗口都会覆盖一个面积为 10 * 10 像素的图像,以计算像素值和参数之间的内积。并且它将在图像上水平和垂直移动 1 个像素(步幅),直到它覆盖整个图像。

典型的池层有两种类型,分别是最大池层和平均池层。最大池层从每个窗口中选取最大值,平均池层从每个窗口中计算平均值。池层的直觉是增加滤镜的弹性。它还进一步减少了参数的数量,并施加了某种程度的正则化来减少过拟合。

完全连接层展平最后一个卷积层,并将神经元完全连接到输出层。你可以有多个完全连接的层。然而,全连接层的参数数目比卷积层的参数数目多得多。在典型的 CNN 中,来自全连接层的参数数量是整个网络的 60%到 80%。

2.CNN

自从 AlexNet 引起公众的注意以来,CNN 的发展经历了三个阶段,主题分别是我所说的越深越好建筑工程AutoML 。每个阶段都有其代表性的网络架构。

CNN 的演变

2.1 越深越好

2.1.1 AlexNet

2012 年 AlexNet 参加 ImageNet 比赛以 15.3%的错误率击败第二名 10.8% 。

AlexNet 的架构。摘自 AlexNet 论文

AlexNet 由 5 个卷积层、3 个最大池层和 2 个全连接层组成。AlextNet 的结构是用 2 个 GPU 拆分的,部分原因是因为当时的 GPU 内存不够大。

激活功能

AlexNet 是第一个使用 ReLU 作为激活功能,而不是Sigmoid功能的 CNN。ReLU 作为激活函数的引入大大提高了深度学习网络的训练速度。

ReLU vs 乙状结肠(虚线)。摘自 AlexNet 论文

辍学

AlexNet 还在全连接层中使用了 Dropout 。AlexNet 的退出使每个训练时期 50%的神经元失效。直觉上,辍学带来了两个好处。首先,它使每个神经元更加独立。其次,它就像每次训练一个子网络,最终结果是子网络的集合,这比单个大网络要好。

AlexNet 对全连接层应用 Dropout 的原因是,如前所述,来自全连接层的参数数量比来自卷积层的参数数量多得多。在完全连接的层上应用 Dropout 带来了一些正则化效果并减少了过度拟合。

数据扩充

AlexNet 输入图像的大小为 224 x 224,这些图像是从 ImageNet 的 256 x 256 图像中随机采样的。通过在比赛中进行这样的采样,AlexNet 将他们的训练数据量增加了 2048 倍。

2.1.2 VGGNet

VGGNet 也在 2014 年的 ImageNet 比赛中声名鹊起。它的卷积层数比 AlexNet 多得多。

VGG16 架构

除了更深层次的架构之外,VGGNet 的一些引人注目的新概念是:卷积层大量使用的 3 x 3 滤波器(取代 5 x 5 或 7 x 7 滤波器,以具有更宽的扫描区域并减少参数数量),非线性变换的 1 x 1 滤波器,在每个池层之后加倍通道数量,以恢复池层中丢失的信息。

2.2 建筑工程

2.2.1 ResNet

当 CNN 的网络层数增加到一定数量时,CNN 的性能反而下降。原因是更深的网络更难优化,因为众所周知的消失/爆炸梯度问题。

CNN 的性能随着层数的增加而降低。摘自 ResNet 论文

有没有办法在避免渐变爆炸/消失问题的同时增加卷积层数?2015 年,发明了 ResNet 来解决这个问题。

剩余学习

ResNet 引入了一个叫做剩余学习的概念。直观上,每个剩余卷积层的输出至少与输入一样好。即。F(x) + x ≥ x。这种架构被证明可以很好地解决梯度问题。ResNet 的卷积层数最大可超过 1000 层。

2.2.2 收入网

在 InceptionNet 之前,大多数改进 CNN 的方法是增加更多的卷积层。受益于谷歌卓越的工程实力, InceptionNet 通过在卷积层中使用各种大小的滤镜,扭曲了卷积层的结构。

很难对所有图像都有一个最佳的过滤器尺寸,因为同一物体在不同的图像中可能具有非常不同的尺寸。InceptionNet 的主要思想是对同一对象使用不同大小的过滤器。直觉上,这个网络变得“更宽”而不是“更深”。

InceptionNet 架构。摘自创意网论文

InceptionNet 经历了从 v1 到 v4 。除了 v1,它的 v2 到 v4 版本通过各种巧妙的技术降低了计算复杂度,提高了性能。它还与 ResNet 联合创建了 InceptionResNet ,使网络既“更宽”又“更深”

2.2.3 移动互联网

MobileNet 是谷歌的另一个 CNN 架构,试图将 InceptonNet 应用于移动设备。目的是减少参数和计算的数量,同时尽可能地保持性能。

MobileNet 中的深度可分卷积。摘自 MobileNet 论文

MobileNet 推出了一种称为深度方向可分离卷积的滤波器架构,其主要思想是为不同的输入通道提供不同的滤波器。MobileNet 显著减少了参数的数量,因此所需的计算量通常仅为原始网络的 1/9,精确度略有下降。

2.3 AutoML

2.3.1 NASNet

配备了丰富的计算能力和工程天才,谷歌推出了 NASNet ,将寻找最佳 CNN 架构的问题框定为强化学习问题。

基本上,想法是搜索给定滤波器尺寸、输出通道步长层数等的搜索空间的参数的最佳组合。在这种强化学习设置中,每次搜索动作后的奖励是在给定数据集上搜索到的架构的准确性。****

NASNet 在 ImageNet 竞赛中取得了最优秀的成绩。然而,NASNet 所需的计算能力如此之大,以至于只有少数公司能够利用相同的方法。

示例:Keras 中的 ResNet 实现

我已经在 Keras 中从头实现了 ResNet 34,并使用它在 CIFAR10 数据集中进行了训练和测试。参考请参考笔记本。

尽管有类似的实现,我仍然手动实现它,因为我想得到一些关于它的编码实践。我也想向你们展示和解释 ResNet 的内部运作。

剩余块

ResNet 的核心是剩余块。ResNet 中有两种基本残差块,一种输出通道数不变,另一种输出通道数加倍。

在通道数量保持不变的情况下,输入图像将通过 2 个 Conv2D 层,其大小保持不变,然后输出(残差)将添加到原始输入图像,作为该块的最终结果。

对于通道数量加倍的情况,输入图像将通过 Conv2D,输出图像宽度和长度减半。为了进行残差学习,原始输入图像的宽度和长度需要减半,其通道数通过填充增加一倍。直觉上,通道加倍和图像尺寸减半同时使得残余块能够以更大的粒度捕获特征。

def _residual_block(self, x, num_output_channel):num_input_channel = K.int_shape(x)[-1] if num_output_channel == num_input_channel * 2:# number of output channel doubled. 3 things will happen:# 1\. The output image' width and length will be halved# 2\. The input image will go through a pooling layer with its width and length will be halved too# 3\. pad the number of channels of the input images for residual learningoutput_channels_doubled = Truestrides = (2, 2)elif num_input_channel == num_output_channel:# number of output channel remain the same# go through 2 convolution layers without changing image' sizeoutput_channels_doubled = Falsestrides = (1, 1)conv1 = Conv2D(num_output_channel, kernel_size=(3, 3), strides=strides, padding='same', activation='relu')(x) conv2 = Conv2D(num_output_channel, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu')(conv1) if output_channels_doubled:pooled_x = AveragePooling2D(pool_size=(2, 2),strides=(2, 2),padding = 'same')(x) padded_x = tf.pad(pooled_x,[[0,0],[0,0],[0,0],[num_input_channel // 2, num_input_channel // 2]]) else:padded_x = x #residual learningoutput_x = conv2 + padded_x return output_x

ResNet 配置

ResNet 34 具有 4 层残差块,每层分别具有 3、4、6 和 3 个残差块。对于每一层,输出通道的数量(num_filters)加倍,但是在该层内,每个残差块具有相同的数量。

num_residual_blocks_arr=[3, 4, 6, 3],for num_residual_blocks in num_residual_blocks_arr:num_filters = num_filters * 2for _ in range(num_residual_blocks):    conv = self._residual_block(last_layer, num_filters)last_layer = conv

在网络的末端,最后一个块被展平并连接到一个全连接的图层,用于标注输出。

CIFAR10 上的结果

我已经在我的笔记本电脑中用 5 个纪元在 CIFAR10 数据集上训练了 ResNet。在测试集上准确率在 75%左右。

Epoch 1/5
391/391 [==============================] - 2343s 6s/step - loss: 2.0021 - accuracy: 0.2924 - val_loss: 1.3157 - val_accuracy: 0.5139
Epoch 2/5
391/391 [==============================] - 2123s 5s/step - loss: 1.2212 - accuracy: 0.5572 - val_loss: 1.0442 - val_accuracy: 0.6267
Epoch 3/5
391/391 [==============================] - 2220s 6s/step - loss: 0.9501 - accuracy: 0.6587 - val_loss: 0.9108 - val_accuracy: 0.6772
Epoch 4/5
391/391 [==============================] - 2196s 6s/step - loss: 0.7628 - accuracy: 0.7299 - val_loss: 0.8016 - val_accuracy: 0.7155
Epoch 5/5
391/391 [==============================] - 2109s 5s/step - loss: 0.6145 - accuracy: 0.7821 - val_loss: 0.7327 - val_accuracy: 0.7482

结论

在这篇文章中,我沿着时间和架构的演化轴简要地讨论了各种 CNN 类型。我还用一个我在 Keras 中实现的 ResNet 的简单实现进行了演示。

CNN 是当今许多人工智能技术的基石,例如自动驾驶汽车和所有其他与图像或视觉相关的工业人工智能应用。CNN 的历史是一部用机器学习和工程技术对抗过度拟合的历史。尽管 CNN 的自动分类还处于初级阶段,但它将在 CNN 的发展中扮演越来越重要的角色。

从贝叶斯定理到贝叶斯推理

原文:https://towardsdatascience.com/from-bayes-theorem-to-bayesian-inference-b261124633a6?source=collection_archive---------18-----------------------

通过概率分布而不仅仅是点概率来理解定理

贝叶斯定理是概率论中的一个重要定律。它适用于频率主义者,以及贝叶斯统计。然而,使用贝叶斯定理本身并不等于我们所认为的“贝叶斯统计”。在本文中,我们将回顾贝叶斯定理,并仔细展示它如何推广到贝叶斯推理。

廷杰伤害律师事务所在 Unsplash 上的照片

贝叶斯定理

贝叶斯定理给了我们一个解决条件概率的方法。例如,假设(或有条件的)检测结果为阳性,患者患病的概率有多大?这是教科书上的典型例子。公式如下:

如果我们知道测试有多好(即给定患者有或没有疾病的阳性测试的概率,P(T=pos|D=true)或 P(T=pos|D=false))和疾病的基线概率 P(D),那么我们可以获得给定阳性测试的疾病的更新概率。

我们如何获得 P(T=pos),一个阳性测试的基线概率?

它只是两种可能性的总和:患者测试呈阳性并患有疾病,以及患者测试呈阳性但未患病。

简单的例子

一项测试的真阳性率为 0.9,假阳性率为 0.05。在人群中,有 0.5%的患者患有这种疾病。假设患者检测呈阳性,那么患者患病的概率有多大?

我们可以将这些值代入贝叶斯定理得到我们的答案

所以给定一个阳性测试,病人得这种病的概率只有 8.3%。

概率分布

为了理解贝叶斯定理与贝叶斯推理的关系,我们必须通过概率 分布来理解该定理,而不仅仅是点概率。概率分布只是给出了任何情况下所有可能结果的概率,而不仅仅是最可能的结果。

概率分布可以是连续的,如随机选择的人的预期智商(正态分布,均值=100,标准差=10):

作者图片

或者像我们前面的例子那样是离散的。我们将展示给定疾病 P(T=1|D)的阳性测试结果的概率。这只是一个伯努利概率分布:

作者图片

离散推理

在贝叶斯推理中,我们希望在给定一些数据和关于这些参数的先验信念的情况下,学习模型参数的一些概率分布。我们使用贝叶斯定理来做这个推论:

这似乎有点抽象,我们再举一个例子来说明这个推论。

假设我在地板上发现一枚 25 美分的硬币。当我把两角五分的硬币留在口袋里,不小心碰到要洗的衣服时,奇怪的事情发生了:硬币弯曲了,变得有偏差,翻转了 90%的正面和 10%的反面。不幸的是,我不知道我刚刚发现的这枚硬币是装的还是公平的。我相信硬币有 50%的机会被装上。幸运的是,我可以通过抛硬币来判断我的硬币是否公平。

在这个场景中,我们只有 1 个参数: p ,翻头的概率。我们为 p=0.5(无偏)分配 50%的先验置信,为 p=0.9(有偏)分配 50%的置信。

因此,我们的 P(参数)先验如下:

作者图片

这有点主观,因为选择先验可能是。

假设我们掷一次硬币。我们有人头了!

现在我们想知道更新后的我们的硬币被装载的概率:P(p=0.9 |头)。

让我们用贝叶斯定理来解决这个问题。注意:按照惯例,我们现在将使用 θ 来表示参数,使用 X 来表示数据。

我们现在有 64%的把握硬币已经装好了!为了找到公平的概率,我们可以用 p=0.5 重做那个等式。或者,我们可以利用我们只处理 2 种可能性的事实,认识到 p(公平|数据)= 1-p(加载|数据)= 0.36。

重要的是,我们也可以忘记分母,计算两个 P 值的 P(X|p)P(p ),然后我们就有了相对后验概率。这是因为 P(X)对于两种计算是相同的。如果你更深入地阅读贝叶斯统计,你会发现贝叶斯定理被写成一种比例关系,比如:

其中∝表示“成比例”。

我们的后验概率现在看起来是这样的:

作者图片

如果我们再次抛硬币,我们现在可以使用我们之前的后验概率(P(loaded) = 0.64)作为我们下一次迭代的先验。所以我们第二次抛硬币,又是正面!让我们更新一下我们的后路。

注意,这里的先验 P(p)是前一次迭代的后验

现在我们更加确信(76%确定)我们的硬币已经装满了。这是我们更新后的后验概率分布:

作者图片

这是贝叶斯统计的一个有趣的方面:随着越来越多的数据进来,我们可以不断更新我们的信念。

如果我们先抛硬币两次,然后我们想用所有的数据计算一次后验概率,会怎么样呢?别担心!通过一次使用所有数据,而不是对每个数据点重复计算,可以得到相同的结果。

注意:用装载的硬币翻转正面然后正面的概率是 0.9 * 0.9;公平硬币是 0.5*0.5

连续推理

让我们介绍一个稍微真实一点的场景。一个季度的公平性不是只有两个不同的值,而是连续的。我们知道大多数硬币是非常公平的(接近 p = 0.5),但是一些铸造的硬币更不公平。我们认为公平值的标准偏差(也就是我们的正面概率的 p 参数)大约是 0.1。所以如果我们找到一个 25 美分的硬币,我们对它的公平性的先验信念是这样的:

作者图片

这是一个连续的概率密度函数。虽然我们没有得到离散值的点概率(即 p = 0.6 的概率是多少),但我们可以解释相对概率(即 p=0.5 的概率是 p=0.4 的两倍)或 p 在给定区间内的概率(即 p 在 0.4 和 0.6 之间的概率为 68%)。

我们有了先验信念,让我们抛硬币,找出后验概率分布。

我们抛硬币,我们得到反面。回到比例贝叶斯定理:

我们知道 P(P);这是我们刚刚定义的先验概率分布。但是当 P 的可能值是无穷大时,我们如何选择 P 的哪些可能值来计算 P(X | p)?我们如何将这两个分布相乘呢?如果我们有一个有几个参数(而不是只有一个)的模型,我们如何考虑所有可能的参数组合?

这些问题比较难。

对于我们假设先验和后验来自同一概率分布“族”的情况,我们可以利用共轭先验来解析求解我们的后验。如果我们不能对我们的后验分布做出这些严格的假设,我们可以使用蒙特卡罗技术来采样并慢慢建立我们的后验分布。

在本文中,我不会深入研究这些技术。目的是建立一种直觉,关于贝叶斯定理如何应用于推理。我们从一个简单的模型开始,以了解先验、后验,以及我们如何不断增加数据和更新我们的模型。然后我们看了一个稍微复杂一点的模型,以理解为什么应用贝叶斯需要更多的工作。

对于进一步的阅读,我推荐 Richard McElreath 的《统计学再思考》,尤其是他关于蒙特卡罗方法的章节。为什么有偏见的硬币实际上是不现实的,看看这篇论文。

从助推到梯度助推

原文:https://towardsdatascience.com/from-boosting-to-gradientboost-ed271cdf2e9e?source=collection_archive---------41-----------------------

友好但严谨的解释

比尔·杰伦在 Unsplash 上的照片

本文面向试图进入数据科学领域的学生或需要复习提升和梯度提升的专业人士。网上已经有很多关于这个主题的资料,但是没有多少包括学习过程的可视化。

所以我们将从升压原理开始,以梯度升压结束。我们也将理解从前者到后者的转变。我们将从图形直觉开始,然后解释用伪代码编写的算法。

介绍

梯度树提升是 shelve 家族中处理结构化数据最好的算法之一。它被广泛使用,主要是因为它在大量数据集上的表现优于其他算法。它有很多优点,例如它可以在各种样本大小上进行训练,并且相对较快(特别是考虑到最近在 GPU 上的实现)。这些优势使得像 SVM 这样的算法越来越少被使用。

这个算法家族起源于 boosting 方法,这是过去 25 年中引入的最强大的学习思想之一。1997 年由 Yoav Freund 和 Robert Schapire 推出的 AdaBoost 就是这种方法的第一例。那年晚些时候 Leo Breiman 意识到提升可以转化为一个具有适当成本函数的优化问题,这催生了 2001 年 Jerome Friedman 的梯度提升。

助推

Boosting 是一种集成方法,这意味着它将许多弱学习者的输出组合起来,以产生一个强大的委员会。弱学习者是错误率比随机猜测稍好的学习者。在 boosting 中,弱学习者是按顺序建立的。每个模型都建立在输入数据的修改版本上,试图关注其前任所犯的错误。助推模型是一种加法模型。这意味着最终输出是基函数的加权和(在梯度树提升的情况下是浅决策树)。第一版 Boosting (Adaboost。M1)是一种分类模型,其中我们将符号函数应用于加法扩展的结果。通过声明我们的模型 H 并使用 M 个基函数 f,我们得到:

一如既往,一个好的模式胜过千言万语。假设我们正在尝试解决一个二元分类任务,仅使用两个预测值 X1 和 X2 来区分蓝色方块和红色圆圈。我们使用决策树作为基本分类器。

图片来自作者

在第一次迭代结束时,我们构建了深度为 1(只有 1 个决策边界)的第一个弱决策树分类器。左边的例子被很好地分类了,但是在判定边界的右边出现了 4 个错误。

接下来发生的是,第二个模型的输入观察值根据 f1 树产生的错误进行加权。第二棵树 f2 将会特别注意它的前任所犯的错误(我们已经强调了)。

作者图片

这一次,考虑到权重,决策树采用特征 x2 来获得最佳分割,从而降低整体熵。接下来,再次对观测值进行加权。但是重要的是要注意到权重是根据它们当前的状态而演变的。一个观察结果被错误地分类了两次,所以这一次它的权重将更加重要。

作者图片

被错误分类两次的观察值的权重现在如此重要,以至于它主要影响第三个决策树的结果。最后,我们合并三棵树的结果。他们中的每一个人都会得到一个与他们犯的错误数量相对应的总权重。最后,我们得到以下结果:

整个 Adaboost 算法是这样的(用伪代码):

在步骤 2.b,我们计算当前分类器的总错误率。接下来,在 2.c 中,我们计算将在最终公式中应用于当前弱分类器的总权重。在 2.d 中,我们更新每个观察个体的权重。请注意指数函数的使用,它强调了一个事实,即错误分类的观察结果在下一轮中将获得更高的权重。

最初,所有的观察值都被赋予相同的权重。随着算法的进行,各个权重分布发生变化,以便每个连续的弱分类器改变其焦点。

从升压到梯度升压

如前所述,梯度提升源于对 Adaboost 算法可以被重新表述为具有适当成本函数的优化问题的观察。更准确地说,Adaboost 算法可以使用指数损失函数重新表述为前向阶段加法建模过程。这最后一句话似乎有点吓人,但不应该。该过程的伪代码如下所示:

所以我们从空函数开始,在每一步,我们添加一个权重为β的特定函数(弱学习器输出)。在 Adaboost 的情况下,并且考虑到分类的结果位于{-1,1} ,损失函数 L 是指数损失函数:

现在,我们将给出带有指数损失函数的前向阶段加法建模过程与 Adaboost 算法等效的完整证明。因此,让我们首先使用指数损失的定义重写我们的最小化目标:

w_i 不依赖于β或 f,因此相对于我们的最小化目标,它被视为常数。现在,我们将重写目标,因为我们的目标要么是 1,要么是-1。我们引入函数 A(为了简化符号)作为我们想要最小化的函数。所以我们把目标分成两种情况:一种是当 y_i 和 G(x_i)一致时,另一种是当它们不一致时:

现在的目标是揭示我们在 Adaboost 算法中看到的指标函数。所以我们写道:

现在我们想找到β的值来解决我们的最小化问题。我们将 A 相对于β的偏导数设为 0,并求解方程:

如图所示,除了 1/2 乘法器,我们退回到 Adaboost 算法的表达式 2.c,误差项等于表达式 2.b:

现在我们可以证明 Adaboost 算法的最终等价性(第 2.d 行)。所以我们之前已经介绍了权重的定义:

从中我们可以得出下一轮的权重值:

现在,如果我们包括向前分阶段相加模型的更新规则(第 2.b 行):

我们有:

现在,因为目标标签是-1 或 1,所以我们可以写:

我们最终会得到:

并且我们退回到 Adaboost 的权重更新规则 2.d,期望最后一项 exp(-β_m)。这最后一项是两个过程之间的唯一区别,但事实上,它不会影响结果,因为它将所有权重乘以相同的值。总的来说,我们证明了这两个步骤是完全相同的。

梯度推进

Adaboost 和具有指数损失的前向阶段加性模型之间的等价性是在 Adaboost 开始后 5 年发现的。从这个观察来看,梯度推进只是指日可待。我们首先意识到的是,我们可以找到与上一次拟合的剩余部分相匹配的最佳函数,而不是找到添加到当前假设中的最佳函数,就像这样:

通过这个简单的技巧,我们提取了残差,但没有改变程序的结果。这个过程的名字来源于,我们可以将残差表示为特定成本函数的负梯度。在具有平方误差损失的回归设置中尤其如此:

梯度增强的作用如下:

  1. 将前任留下的求反残差表示为代价函数的梯度
  2. 找出最小化那些被否定的残差的最佳假设
  3. 添加求反残差的预测。

程序是这样的:

通过在步骤 2.a 和 2.b 中使用相同的损失函数,该过程等同于函数空间中的梯度下降。

让我们通过一个简单的例子来想象这里发生了什么。假设我们正在尝试将回归模型拟合到以下数据集(只有 1 个预测值 X1):

作者图片

在第一次迭代结束时,我们构建了以下回归树:

作者图片

现在我们将尝试改进这个只有 1 级的弱决策树。因此,我们从计算求反的残差开始:

作者图片

我们用决策树来拟合求反后的残差:

作者图片

我们综合结果:

作者图片

我们继续下去,添加越来越多的决策树,直到我们开始过度拟合(这是使用验证集来控制的)。

其他分类损失

与 Adaboost 不同的是,梯度提升能够将学习过程推广到其他成本函数 l。这种推广真正有趣的是,您可以使用具有不同属性的成本函数来为该过程提供不同的整体行为(特别是关于异常值)。

可以看出,指数损失与二项式负对数似然或二项式偏差具有相同的总体最小值:

这就是为什么在 scikit-learn 的梯度提升分类器实现中,您可以选择指数或偏差损失。

请注意,当响应在集合{0,1}中时,二项式偏差与逻辑损失(也称为二元交叉熵)是一回事。在这种情况下,我们使用以下公式:

这就是 XGBoost 软件包提出二进制:逻辑损失函数的原因

指数损失是裕度 y f(x) 的单调递减函数。在具有-1/1 响应的分类设置中,分类规则 G(x)=sign[f(x)]意味着具有正容限的观察值被正确分类(y 和 f(x)一致),而具有负容限的观察值被错误分类(y 和 f(x)不一致)。因此,分类算法的目标是尽可能频繁地产生正余量。亏损标准对负利润的惩罚要比正利润重得多。让我们看看常见的二元分类损失函数在裕度方面的表现:

作者图片

指数和二项式偏离损失持续且越来越多地惩罚负的利润率值,而不是奖励正的利润率值。但是我们可以注意到,负利润的惩罚随着指数损失而指数增长,而二项式偏差的惩罚则以更线性的方式增长。这种线性趋势也可以在支持向量损失(用于支持向量机)中找到,也称为铰链损失。指数准则集中了对具有大的负边界的观测值的许多影响。这使得这个标准对异常值更加敏感。在这种情况下或者在贝叶斯误差非常重要的噪声环境中,其他损失是优选的。

回归的其他损失

在回归设置中,通常使用 3 种不同的损失函数:

  • 平方误差损失用于例如普通的最小二乘回归。对于异常值或当数据中有太多噪声时,它不太稳健,但当没有异常值时,它仍然是首选:

  • 存在异常值时更稳健的绝对误差损失:

  • huber 损失是上述两者的混合:

我们可以将损失值绘制成残差的函数,以便更好地理解相关的惩罚:

huber 损耗结合了小误差平方损耗和大误差绝对损耗的优良特性。

结论

当存在有噪声的数据集时,回归的平方误差损失和指数损失可能不是最佳选择,尽管它们都导致优雅的模增强算法(Adaboost)。对于平方误差损失,人们简单地将基本学习器直接拟合到来自当前模型的残差,而对于指数损失,人们执行权重等于 exp(-y f(x))的加权拟合。梯度提升是提升算法对其他成本函数的推广。通过将当前弱学习器的残差表示为成本函数的负梯度,这是可能的。

参考

统计学习、数据挖掘、推理和预测的要素。特雷弗·哈斯蒂、罗伯特·蒂布拉尼、杰罗姆·弗里德曼

从化学家到 ML 研究员

原文:https://towardsdatascience.com/from-chemist-to-ml-researcher-98d54caa8a12?source=collection_archive---------15-----------------------

我如何得到我的第一份数据工作

让我们看看。从何说起。先说我的背景。我在休斯顿大学获得了化学和物理学士学位。然后,我进入了芝加哥大学的化学博士项目。后来,我决定不再那么想要一个博士学位。好的,那很好。只不过,那是 2021 年 7 月。2020 年 3 月已经过去了将近 1 年半,而这个世界仍然没有变好。所以,我大概是这样做的。

TL;大卫:我被拒绝了 200 次,花了 5 个月时间,但我还是成功了!

蒂姆·高在 Unsplash 上拍摄的照片

2021 年 7 月

我申请了大约 30 份工作,大部分是通过 LinkedIn。在哪些领域?全身都是。在这个阶段我并不特别,我想看看什么会坚持下来。我做了一些信息采访,主要是想看看和我有相似背景的人是怎么做的。得到了一些没有真正去任何地方的介绍。我遇到了一个真正为我加油的 UChicago 校友,祝福她的心。由于签证原因,我现阶段仍在攻读博士学位。

有什么线索吗?

奇怪的是,开放的。在他们的人工智能校准团队中有一个 DS 空缺。这份工作描述看起来很合理,所以我申请了,没有多想。但后来他们联系了我。我没有通过。老实说,那时候我还没听说过 AI 伦理学,所以没指望能通过。

7 月 28 日,我申请了在线选择(为你们这些国际人士)。

2021 年 8 月

我申请了大约 100 份工作,都是在 LinkedIn 上&的确如此。我发现在 LinkedIn 上发布工作/招聘需要雇主花钱,所以如果我只是通过 LinkedIn 申请,我可能会错过机会。

我做的所有边缘工作

这个月我还做了什么…嗯…哦对了,我在这里写了第一篇博文(不要脸的推广,多?).我申请了 Correlation One 的面向所有人/女性的数据科学项目(那是满嘴的,姑且称之为 DS4AW)。以防万一,我建立了一个最敏锐的头脑的侧写。我还拿出了旧的“统计学习入门”,并通过 FastAi 课程开始学习神经网络,并从那里做了一些项目。

有什么线索吗?

得到了 Civis Analytics 的面试机会,后来被拒绝了。我认为这表明我太嫩,无法承担商业级的数据科学。他们没有错。

我被 DS4AW 录取了!此外,“最敏锐思维”的一位导师对我的个人资料感兴趣,主动联系了我。我觉得现在签约还为时过早。

在这个阶段你有什么感受?

哦,谢谢你的关心,你真好。糟糕透了。嗯,我不完全明白那里发生了什么。我变得焦虑不安。我的睡眠质量下降了。除了焦虑,我还很生气。的。时间。我是一名国际学生,这意味着我被许多工作机会拒之门外。这种意识加上糟糕的睡眠是一个非常讨厌的亚洲女孩的完美混合物。事后看来,在这段时间里,我设法做到了我提到的所有事情,这是一个奇迹。

8 月 28 日,我离开了我的博士项目。我丈夫不久后就辞职了。

2021 年 9 月

我申请了大约 50 份工作。但我改变了策略。我清楚地意识到,对于营利性行业来说,我的简历并不是最具竞争力的。所以,我申请了工业和国家实验室的混合。我还申请了一些由 UChicago 促成的无薪实习,以便在我的简历上写点东西。

有什么线索吗?

一家初创公司对我表示了兴趣。我看了这位首席执行官在 LinkedIn 上的个人资料,他的标题大致是“如果你不创新,你就会被解雇”。用爱莉安娜·格兰德的话说,“谢谢你,下一个。”

我通过 UChicago 获得了伊利诺伊州科学委员会的一份无薪数字媒体分析师实习。他们是非营利组织,旨在向成年人推销科学。这与我过去所习惯的截然不同,现在我想知道经营非营利组织是否是我的未来。

我得到了 PostEra 的一个软件开发职位的编码面试。在这里,我丈夫为我递交了申请。有传言说,有同样资历的女性比男性更不容易申请工作,我就让他来掌舵。虽然没有通过编码面试。说到底,我是个编程的化学家,不是懂化学的程序员。

大约在同一时间,NREL 打电话给我,告诉我一个为期一年的计算化学实习,其中涉及到神经网络!这看起来非常合适,我通过了面试,却被告知他们不能录用我,因为我不适合这个角色。但是,可能会有一些变通办法让我加入,所以请继续关注?

2021 年 10 月

我申请了大约 20 份工作。我专门针对国家实验室,因为我似乎在那里运气最好。

有什么线索吗?

我得到了 PNNL 大学博士后 r a 职位的面试机会。那是在生物成像领域,PI 正在寻找一个和我背景相似的人,他以后可以进入量子计算领域。我对这个职位有着复杂的感情。当我进入研究生院时,我想做量子计算,但被介绍到神经形态计算并接受了它。这一次有机会进行量子计算听起来非常令人兴奋,但实际可行吗?目前只有少数几家公司在做“量子”的事情,尽管大肆宣传,我怀疑这种情况会很快改变。但不管怎样,我认为在最初的面试中就表明了我对这个角色并不感兴趣,所以没有复试。

通过 LinkedIn 找到了一些线索,但这是一个不合适的组合,加上签证问题导致了他们的死亡。但是,嘿,LinkedIn 并没有帮不上忙。

2021 年 11 月

我只是没有在这一点上费心。我丈夫在旧金山找到了一份工作,我们正在大搬家,所以我决定暂停找工作。但这也是为了我的健康,你知道吗?然而…

有什么线索吗?

一堆事情同时发生。11 月初我们搬到了 SF,找不到住的地方。因此,有几个星期,我们住在一家无线网络质量很差、手机信号很差的酒店里。就在这几周,有几个地方决定要和我谈谈——最好是通过带有演示的 Zoom。我的 5 岁,滥用,遗弃和恶意软件肆虐的 MSI 笔记本电脑与过期的微软许可证不知何故携带我通过这一切。我有两个提议,一个来自 NREL!

出于几个原因,我接受了和 NREL 一起去的薪水。但我还不确定它们有多好。我想我们会看到的。

那么我学到了什么?

尽管人们告诉我,鉴于我的背景,找工作应该不成问题,但这里有很多警告。

我的竞争优势是科学

我遇到了一位职业顾问,他告诉我,如果我愿意走出硬科学,会有更多的机会。她说得对,确实有。但我没有考虑到这样一个事实,即在这个池中,我没有太多的竞争优势。我得到的面试机会和两份工作邀请来自一些公司,这些公司正在寻找像我这样的人,一个有科学背景、会编程的人。候选人的范围要小得多。

我选择失业

在求职的短短几个月里,我觉得自己似乎老了几岁。坐下来写这篇文章,我才意识到时间并不长。在那几个月里,我经常觉得自己不受欢迎。在你开始崩溃之前,你能接受的拒绝是有限的,你知道吗?但有时,我会让招聘人员联系我,询问我非常适合的化学/生物化学职位。我拒绝了他们,因为我不想成为一名湿实验室化学家。这些信息大大提升了我的情绪,因为它们提醒我,我在这里有一个选择。我选择拒绝某些工作,这样我就能找到更适合我的工作。

令人惊讶的是框架能有如此大的帮助,阿米利特?

冷敷仍然有效,但是你得有厚脸皮

我获得的面试没有一次是通过推荐或电子邮件获得的。我试着建立关系网,但它似乎没有任何作用,所以过了一段时间我就不再打扰了。但是,伙计,下次我这么做的时候,我可能会更有针对性。我以为我脸皮很厚,直到我每天都收到大量的拒绝邮件。很高兴那结束了。

保持联系

我喜欢写关于数据科学和科学的文章。如果你喜欢这篇文章,加入我的电子邮件列表,或者成为中级会员(如果你使用这个链接,我将收取你 50%的会员费),如果你还没有的话。下一篇帖子再见!😄

从剪贴板到熊猫数据框

原文:https://towardsdatascience.com/from-clipboard-to-dataframe-with-pandas-6c212b1d7ed8?source=collection_archive---------17-----------------------

直接从剪贴板读取数据,无需先保存

作者图片

当我写一个库或一个新概念时,我通常喜欢通过例子展示它的工作。我在文章中使用的数据集的来源千差万别。有时我会创建简单的玩具数据集,而在其他场合,我会使用像 Kaggle 和 Google search 这样的已建立的数据集网站。然而,每当我需要展示一个概念时,我都必须经历从源复制数据、将数据保存到我的系统并最终在我的开发环境中使用它的费力工作。想象一下,当我发现熊猫有一个内置的方法来解决这个问题时,我有多惊讶。当你想快速尝试一些新的函数或库时,这个被恰当地命名为read_clipboard的方法绝对是救星,在本文中,我们将学习如何使用它。

使用 pandas.read_clipboard()函数

pandas 的[read_clipboard()](https://pandas.pydata.org/docs/reference/api/pandas.read_clipboard.html)方法从复制到剪贴板的数据创建一个 dataframe。It 从剪贴板中读取文本,并将其传递给[read_csv()](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html),后者随后返回一个经过解析的 DataFrame 对象。

句法

pandas.read_clipboard(*sep='\\s+'*, ***kwargs*)

如果你和熊猫read_csv(),一起工作过,那么read_clipboard()的方法基本上是一样的。唯一的区别是后者中的数据源来自剪贴板缓冲区,而不是 CSV 文件。

如果你想深入了解熊猫的read_csv功能的一些参数,我会为你提供帮助。

使用

现在让我们看看使用这种方法的各种方式。涉及的主要步骤是:

涉及的步骤|作者提供的图片

1.从 Excel 文件复制数据

我们将从从 excel 文件复制一些数据集开始。这是最常见的情况。

按作者将数据复制到剪贴板|图像

现在数据已经被复制到剪贴板上。接下来,我们将导航到 Jupyter 笔记本(或任何 IDE)实例,并键入以下代码片段:

import pandas as pd
df = pd.read_clipboard()
df

作者从复制的数据集|图像中获得的数据帧

复制的数据集被传递到变量df中,现在可以在您的环境中使用了。下面是一张 GIF,清晰地演示了这个过程。

pandas_read_clipboard()方法|作者图片

2.从 CSV 文件复制数据

如果您有一个 CSV 文件,步骤保持不变。您只需要对函数的参数进行某些更改。考虑以下 CSV 数据:

,Order ID,Category,Sales,Quantity,Discount
0,1,Apparels,16.448,2,0.2
1,2,Electronics,65.0,87,0.2
2,3,Cosmetics,272.736,3,0.2
3,4,Apparels,3.54,2,0.8
4,5,Electronics,19.536,3,0.2
5,6,Cosmetics,19.44,3,0.0
6,7,Grocery,12.78,3,0.0
7,8,Grocery,2573.82,9,0.0
8,9,Apparels,609.98,2,0.0
9,10,Cosmetics,300.0,10,0.5

复制上面的数据,运行下面的代码。

df = pd.read_clipboard(sep=",",header="infer",index_col=0,names=["Order", "ID", "Category", "Sales", "Quantity", "Discount"],
)df

作者从复制的数据集|图像中获得的数据帧

我们得到与步骤 1 相同的数据帧。我们只需要传入列名和关于headerindex column.的信息

3.从网页拷贝数据

您还可以从任何来源复制数据,包括网页,只要它是以 dataframe 的形式构造的。这是一个从 StackOverflow 示例中复制数据并将其导入 dataframe 的示例。

作者从网页 |图片中复制数据帧

保存数据

我们可以使用剪贴板数据以期望的格式保存数据集以供将来使用。

df.to_csv('data.csv')

您也可以将数据保存为 HTML 格式,以 HTML 表格的形式显示数据。

df.to_html('data.html')

熊猫数据帧保存为 HTML 表格|作者图片

结论

既然你已经了解了read_clipboard方法,你肯定会想尝试一下。我敢肯定,如果你喜欢创建数据相关的教程,这将派上用场。你也可以看看我写的关于熊猫功能的其他博客。例如,这个帮助你直接创建与熊猫互动的情节,而这个是一个在熊猫中“分类”数据帧的实践指南。

从混淆矩阵到加权交叉熵

原文:https://towardsdatascience.com/from-confusion-matrix-to-weighted-cross-entropy-9d2999c06845?source=collection_archive---------24-----------------------

如何使用加权交叉熵来惩罚一个标签

你好。

在我们之前的文章中,我们用 3 个步骤介绍了机器学习的交叉熵概念。特别是,我们从信息论的角度讨论了 log(p)是什么,熵的真正含义,以及它与交叉熵损失的关系。

https://medium.com/@david.h.kang/an-intuitive-guide-how-entropy-connects-to-cross-entropy-78b0713494a9

在本文中,我们将通过考虑加权交叉熵来扩展我们在交叉熵方面的讨论,加权交叉熵允许我们对一个标签进行加权。例如,当设计用于新冠肺炎诊断的最大似然算法时,我们可能希望对假阴性的惩罚比对假阳性的惩罚更重。让我们开始吧。

第一步。混淆矩阵

混淆矩阵是总结 ML 模型分类结果的一种非常方便的方法。如下所示,它由 TP(真阳性)、FP(假阳性)、FN(假阴性)和 TN(真阴性)4 个部分组成。例如,在新冠肺炎的情况下,FN 将是被诊断为没有新冠肺炎的新冠肺炎患者的数量。

作者图片

第二步。混淆矩阵中的关键概念

这里我总结几个来源于混淆矩阵的关键词,它们在有分类任务的 ML 论文中出现很多。尽量不要死记硬背,因为名字本身就很有意义!

(1)敏感度 (回忆)量化你的模型在正确分类阳性标签方面的敏感度,意思是,在所有实际阳性案例中,有多少被正确分类为阳性。

敏感度= TP / (TP + FN) = TPR(真阳性率)。

(2) Precision 量化模型预测的精确程度,也就是说,在所有肯定的猜测中,有多少实际上是肯定的。

精度= TP / (TP + FP)

(3)用于二进制分类的 F 分数 通过 1/F = 1/2[1/召回+1/精度]通过调和平均将灵敏度和精度结合起来

根据应用的不同,可能需要更加强调灵敏度或精度。这种情况下可以用 F_beta。请注意,当 beta = 1 时,它将成为之前定义的标准 F 分数。

1/F _ beta = 1/(1+beta)[beta/Recall+1/Precision]

(4)准确度 是最常见的度量之一。由于它同时考虑了所有的总磷和总氮,当你有不平衡的数据时,它可能会产生误导。例如,虽然您可能希望尽可能好地预测罕见疾病的 TP 病例,但您的(差的)ML 模型可能仅因为有太多的 TN 而显示出高准确性,尽管它的 TP 很低。

准确度= (TP + TN) / (TP + FP + TN + FN)

第三步。加权交叉熵

太好了!你已经看到,在需要特别注意正面或负面情况的应用程序中,对混淆矩阵中的每个部分一视同仁会产生误导。

正如我们在上一篇文章中讨论的,二元分类任务中的交叉熵损失计算如下,对两个标签给予同等的重视。

labels * -log(sigmoid(logits)) +(1 - labels) * -log(1 - sigmoid(logits))

现在请注意,我们如何对这种损失进行轻微的处理,以增加(或减少)标签的重要性!这是通过插入大于(小于)1 的pos_weight来加强(或减弱)阳性标签(+)。

labels * -log(sigmoid(logits)) * pos_weight +(1 - labels) * -log(1 - sigmoid(logits))

pos_weight大于 1 时,你会对被错误归类为阴性的阳性标签进行更多的惩罚,因此有助于提高灵敏度;你可以期待你的 ML 模型变得更加敏感,在所有实际的阳性案例中正确地分类出阳性案例。

另一方面,当pos_weight小于 1 时,你的模型对错误分类为阳性的阴性标签进行更多的惩罚,因此有助于提高精度;您可以期待您的 ML 模型在正确分类所有积极预测中的积极案例方面变得更加精确。方程式摘自 tensorflow 网站。

恭喜你。你已经走了很长的路。

总而言之,

  • 灵敏度和精度都与我们的模型如何将阳性病例分类为阳性(TP)有关。
  • 敏感度考虑所有实际阳性(TP + FN),而精确度考虑所有预测阳性(TP + FP)。
  • 加权交叉熵损失让我们的 ML 模型惩罚更多(或更少)被错误分类为负面的正面标签,反之亦然!
不要犹豫留下你的想法!您的反馈和评论有助于丰富我们的社区。很高兴听到。感谢阅读:-)
DK

从 CSV 到 GitHub 页面,5 个步骤:发布漫威世界的互动社交网络

原文:https://towardsdatascience.com/from-csv-to-github-pages-in-5-steps-publishing-an-interactive-social-network-of-the-marvel-7b8374bf44fb?source=collection_archive---------13-----------------------

如何使用 Python、Gephi 和 GitHub 页面轻松创建令人惊叹的图形可视化

在本文中,我将提供一个循序渐进的指南,告诉你如何通过 5 个简单的步骤创建、发布和共享交互式网络图可视化。

奥马尔·弗洛雷斯在 Unsplash 上拍摄的照片

在我们开始之前,我们需要三样东西:

  • Python & NetworkX 库[ 1
  • ge phi[2]&sigma exporter 包
  • GitHub 帐户&一个公共的 GitHub 存储库

步骤 1:导入 CSV 文件并创建一个 NetworkX 图形

我们的数据源实际上可以是任何数据格式(例如 TSV、pandas 数据帧或数组),但是在本文中,我们将重点关注 CSV(Comma-SseparatedValues)格式。在本教程中,我将使用来自 Kaggle [ 3 ]的漫威宇宙社交网络数据集来创建一个英雄之间关系的交互式图表。数据集描述了漫画中漫威英雄的共现,因此每行描述了一个实例,其中英雄 1 (在第 1 列)与英雄 2 (在第 2 列)出现在同一部漫画中。

我们首先导入三个 Python 库:(1) csv 用于读取 csv 文件,(2) tqdm 用于显示进度条(可选),以及(3) NetworkX 用于创建和修改图形。

import csv
from tqdm import tqdm
import networkx as nx

然后我们创建一个空的 NetworkX 图…

import networkx as nx G = nx.DiGraph()

…并根据我们的 CSV 文件添加节点和边。我们迭代每一行,为 hero1 (第一列)和 hero2 (第二列)添加节点。不需要担心添加重复的节点,因为名称/标签充当唯一的 id,并且已经在图中的节点被跳过。如果从 hero1hero2 的边在我们的图中还不存在,我们就把它加上并把它的权重值设为 1(意思是他们曾经一起出现在一本漫画里)。如果边已经存在,我们只需将现有边的权重增加 1。

**with** open('./data/hero-network.csv', 'r') **as** f:data = csv.reader(f)headers = next(data)**for** row **in** tqdm(data):G.add_node(row[0]) *#superhero in first column*G.add_node(row[1]) *#superhero in second column***if** G.has_edge(row[0], row[1]):*# edge already exists, increase weight by one*G[row[0]][row[1]]['weight'] += 1**else**:*# add new edge with weight 1*G.add_edge(row[0], row[1], weight = 1)

为了得到图中的第一个信息,我们打印出它的节点数和边数。

G_nodes = G.number_of_nodes()
G_edges = G.number_of_edges()
print("Nodes = ", G_nodes, " Edges = ",G_edges)

我们的图总共有6426 个节点224181 条边

第二步:将 NetworkX 图形导出为 gexf 文件

下一步,我们将 NetworkX 图形转换成 gexf 文件( G 图形ExchangeXMLFformat)并将其存储在我们的文件目录中。

nx.write_gexf(G, "./data/hero-network.gexf")

第三步:导入并修改 Gephi 中的图形

由于我们的图表存储为 gexf 文件,我们可以使用开源应用程序 Gephi(可用于 Windows、MacOS 和 Linux)导入、修改和可视化它,它提供了多种功能。

首先,我们将 gexf 文件作为无向图导入,并安装 SigmaExporter JS 包(工具>插件>可用插件),以利用适马 JS [ 4 ]。如果您愿意,也可以选择安装和使用其他布局算法。

在下一步中,我们希望让更多连接良好的相关节点(例如,托尼·斯塔克,美国队长)显得更大。为此,我们在 statistics 选项卡中计算平均加权度(对于有向图,我建议使用 PageRank),并在 appearance 选项卡中相应地设置节点大小,8 是最小节点大小,48 是最大节点大小。

最后,我们运行一个模块化算法[ 5.&text=Biological%20networks%2C%20including%20animal%20brains,a%20high%20degree%20of%20modularity) ]来聚集我们的图并将节点分配给一个模块。然后,我们根据模块关系分配节点颜色,并运行我们选择的图形布局算法(在我们的例子中是 Force Atlas 2)。请记住,Gephi 提供了多种方式来个性化我们的图表[ 6 ]。

第四步:将图形导出为适马 JS

如果我们喜欢图表的布局和可视化,我们现在可以将其导出为适马 JS 模板(文件>导出>适马 JS 模板)。Gephi 将要求我们在图表上提供一些基本信息(例如,标题、作者、图例和描述)。我建议检查搜索选项,因为它将允许在最终的图形可视化中查找节点。此外,将悬停行为设置为 dim 提供了改进的交互体验。最后,我们选择目标目录并单击 export。我们现在应该在目标目录中有一个网络文件夹。

第五步:在 GitHub 页面上发布图形可视化

我们可以通过打开导航到网络文件夹并使用以下命令打开 Python http 服务器来本地测试我们的图形。

python -m http.serverpython -m SimpleHTTPServer (*for earlier Python versions)*

我们现在应该能够在我们的 web 浏览器中看到我们的图表,网址是: http://localhost:8000/ 。然而,如果我们想在线发布我们的图表并与其他人分享链接,我们可以通过利用 GitHub 页面来实现。首先,我们创建一个新的(公共)GitHub 存储库并上传网络文件夹。然后,我们转到我们的存储库设置,并选择 GitHub Pages 选项卡。一旦到了那里,我们就将主分支设置为我们的源。该图现在应该可以从以下 URL 获得:

[**https://**[YourGitHubName]**.github.io/**[YourRepositoryName]**/network/**](https://tdenzl.github.io/MarvelNetwork/network/)

我们现在可以通过选择和搜索节点来浏览图表。此外,我们可以进一步调整图形的视觉效果[ 7 ]。

先睹为快我们的互动漫威宇宙共现图可视化

在这里你可以找到最终由 GitHub Pages 主办的漫威宇宙共现网。

如果您想创建自己的网络可视化,请查看我的包含 Jupyter 笔记本脚本的 GitHub 库。

参考文献:

[1] NetworkX,首页 (2021)

[2] Gephi,首页 (2021)

[3] C. Sanhueza,漫威宇宙社交网络 (2017)

[4]适马 JS,首页 (2021)

[5] Parklize, Gephi -模块化集群布局.&text=Biological%20networks%2C%20including%20animal%20brains,a%20high%20degree%20of%20modularity) (2014)

[6] K. Cherven,掌握 Gephi 网络可视化 (2015)

[7]适马 JS,文档 (2021)

从数据现代化到数据货币化:搭建桥梁

原文:https://towardsdatascience.com/from-data-modernisation-to-data-monetisation-building-the-bridge-b719c8e825f3?source=collection_archive---------37-----------------------

为您的企业建立真正以数据为中心的转型之路。

弗兰基·查马基在 Unsplash 上拍摄的照片

过去的三年给我们带来了前所未有的全球性变化。从人们的生活和工作方式,到公司的组织和运营方式,正在引发的变革水平扰乱了我们生活的许多方面,并将继续这样下去。

如果我们将注意力集中在数据和分析技术在整个组织中的使用情况,变化的程度也是巨大的。我可以强调这一变化的一些方面:

  • 公共云的兴起成为 D & A 工作负载的标准存储模式;
  • 传统本地大数据生态系统的消亡及其被云原生替代方案所取代;
  • 数据作为业务驱动力被作为企业战略的核心原则;
  • 首席数据官、首席分析官和类似角色的崛起,推动企业数据的民主化;
  • 人工智能和数据密集型应用的兴起,以利用正在收集的海量数据集;

在这种不断变化和积极变革的状态下,在尝试构建新的数据生态系统并利用生态系统来促进和维持有效的业务变革时,已经绘制了许多不同的路径,导致了一些成功,但也有许多失败。我们可以将这些努力称为转型之旅的“数据现代化”阶段。

随着对数据生态系统现代化的如此关注和投资水平,我们可以预计这一新模式将会取得非常迅速的进展,几乎不会遇到阻力。然而,一些指标向我们展示了导致以技术为中心的数据议程推迟的不同原因:

  • 过度关注技术,没有充分理解手头的业务问题和影响;
  • 缺乏清晰的业务战略明确定义数据的角色,并将其整合到更广泛的企业生态系统中;
  • 对以数据为中心的项目缺乏专注的领导,未能代表组织在不同方面的复杂性;
  • 缺乏变革管理原则,导致数据平台和解决方案的“建立起来,他们就会来”效应(不,他们不会)。

快进到 2021 年,赌注只会越来越高。对数字化转型的持续努力导致可用于探索和从中提取有价值的业务见解的数据量不断增长。企业对其数据和分析团队的需求不断增加,寻找和提供数据中“隐藏的钻石”的压力越来越大:

  • 揭示带来卓越客户体验和客户维系的要素,以及客户忠诚度的关键要素;
  • 了解不同渠道环境下的产品性能,以及如何优化物理和数字生态系统的组合;
  • 创建有效和客观的营销策略,而不在广告上过度花费,并利用正确的媒体与公司受众联系;
  • 建立和发展基于客观和量化指标的忠诚人才基础,鼓励员工留下来发展,成为自己的品牌大使;

这样的例子不胜枚举。

然后,我们可以自信地说,企业正开始加速从“数据现代化”阶段向我们称之为“数据货币化”的新阶段迈进。在这个新阶段中,假设数据资产是成熟的、经过管理的、具有必要的质量等级,因此可以从经济角度利用。

在这方面,有效的数据货币化需要一个良好的数据平台才能取得成功,还需要完善的数据管理原则,在此基础上,将启动和部署数据货币化计划:

  • 明确数据资产的所有权,以及上下游数据谱系,以了解数据资产的生态系统;
  • 自动化和可量化的数据质量检查,可以快速用于筛选数据资产以进行有意义的探索;
  • 数据新鲜度属性的清晰表示,确保分析不会在过时数据上进行;
  • 自动化框架,防止在关键生产环境中手动篡改数据和代码;

同样,可以使用更多的例子来说明专业管理的数据生态系统的绝对必要性,以便能够为关键业务目标准确利用数据资产。

问题是,我们到了吗?

答案远非简单,有不同的角度,但如果我必须用一句话来总结,那就是“不完全是”。

技术生态系统的快速发展与业务和业务战略的节奏产生了冲突,业务和业务战略天生就较慢,这是有充分理由的,导致 IT 被迫部署新的工具和解决方案,而业务用例尚未明确指定,也缺乏可靠的 ROI 分析来证明其有效性。

很多时候,公司处于“追逐闪亮的新对象”模式,很少考虑战略价值和新解决方案在其生产环境中的集成。这导致了可怕的“PoC 墓地”效应,即新的解决方案在证明了一个非常残余的用例之后,却无法扩展到更远的地方。

然而,在大规模采用新的数据和分析技术方面也有成功的案例,这些技术可以有效地大规模解决相关的业务用例,并展示出明显的投资回报。这不是“不可能完成的任务”,远非如此。只有几件事需要考虑,以使这片乐土成为现实(更多内容见下文)。

那么,我们该何去何从呢?

正如所有的转变一样,会有赢家和输家。那些能够快速实现现代化的人,将更有能力将自己的数据资产货币化,并战略性地利用它们来实现商业目标。

基于传统数据平台的商业化努力将带来有限的好处和结果,因为传统平台将无法提供在现代数据平台中捕获和存储的新客户体验的丰富性和细节水平。

那么,有什么建议可以提供给那些规划从现代化到商业化之路,甚至决定从哪里开始的组织呢?

  • 首先考虑业务成果。充实货币化计划背后的数据战略将带来业务用例及相关的投资回报,这将在以后证明数据现代化项目投资的合理性。
  • 业务和 IT 团队需要通力合作才能实现。业务团队将领导数据货币化计划,IT 部门将领导数据现代化部分,但需要有共同的愿景和路线图来促进协调,并最终取得成功。没有别的办法。
  • 利用数据计划促进跨企业协作。很少有计划像以数据为中心的转型这样影响公司的这么多领域。如果你的公司习惯于各自为政,这是一个很好的合作机会,可以创造一种共享所有权和协作的文化。
  • 一路上衡量你的进步,但要做好缓慢开始的准备。大量的工作将在计划的开始阶段进行,在不同的团队之间建立一致性,并与关键的里程碑和利益相关者一起制定一个稳定的计划。一路上你会经历挫折,但毅力会是你的朋友。
  • 一个稳固的开端会让你在未来获得巨大的利益。尽早为您的数据现代化和货币化计划带来可见的好处和立竿见影的效果,将会激发热情,并进一步增加对用例的需求。计划如何最好地展示你的成功,作为一种激励团队的方式,并确保未来的资金。

以数据为中心的转型正在加速,但对许多公司来说仍是一个早期概念。过去各自为政的事情现在可以在部门间协作完成,这增加了复杂性,但也为公司创造了更大的潜力。

利用企业积累的数据财富,实现数据平台的现代化,并实施先进的数据货币化策略,只会让那些做得好的人更快获得优势。

从数据到决策

原文:https://towardsdatascience.com/from-data-to-decisions-bef3649f0b17?source=collection_archive---------32-----------------------

人工智能|技术

理解对可解释人工智能的需求

弗兰基·查马基在 Unsplash 上拍摄的照片

这不是秘密。每个人都知道。我们今天的生活完全由人工智能(AI)驱动。从垃圾邮件过滤器到虚拟个人助理,我们生活的方方面面都由一种算法控制。我们甚至把我们的爱情生活交给某个约会应用程序下运行的算法来匹配我们和未来的另一半。难怪对控制论反叛的恐惧越来越受欢迎,尤其是考虑到这些人工智能应用程序大多被视为黑箱,即:人类很难理解和清楚地看到人工智能是如何产生预测的。

“人工智能对人类文明的存在是一个根本性的风险,而车祸、飞机失事、劣质药品或劣质食品则不是——它们当然对社会中的一组个体有害,但它们对整个社会无害。”——埃隆·马斯克

可解释 AI (XAI) 的领域获得了巨大的牵引力。XAI 是创造能够自我解释的算法的学科。我们不应该只对预测某个目标感兴趣,但我们也必须理解为什么人工智能会做出那个特定的预测。

照片由 Yannick Menard 在 Unsplash 上拍摄

华盛顿大学最近发表了一项研究,涉及一个预测图像显示的是哈士奇还是狼的模型。该模型能够以大约 90%的准确率进行预测,这是一个非常好的结果。然而,发现该模型是基于背景中是否有雪来预测的(传递给算法的大多数狼图像都有雪的环境,而哈士奇照片很少有雪)。你可能听说过这样一句话“闪光的不一定都是金子”,这句话再正确不过了。想象一下,如果它被用于医学成像或其他一些关键应用,会有什么样的影响。底线是,尽管人工智能为创新智能解决方案提供了大量机会,但我们不能盲目信任这些算法。

从预测到规范

一个可靠的解释带来的最有力的好处之一是可以理解。很明显,对吧?当一个老师恰当地向学生解释一个概念时,那么默认情况下,学生就已经理解了这个概念。类似地,当一个人工智能提供一个解释时,本质上,我们也获得了要预测的特定目标的知识和理解。如果我们知道预测发生的原因,那么我们也可以设计一个解决方案来控制和操纵同样的预测。通过利用这一知识,我们将能够实现从预测分析到处方解决方案的飞跃。

斯蒂芬·道森在 Unsplash 上拍摄的照片

让我们以成瘾预测的用例作为类比。想象一下,我们已经建立了一个强大的模型,可以预测某种可能导致更严重成瘾行为(赌博成瘾或酗酒和吸毒)的问题行为。正确预测潜在的成瘾行为已经是一项了不起的成就,但能够理解导致特定行为有问题的潜在关系将更加令人难以置信。我们不仅能够理解为什么一种特定的行为会上瘾,还能理解如何有效地处理它。

另一个例子是维护干预。通过模型解释,我们不仅能够在未来的故障发生之前预测它,还能够理解为什么故障可能会发生,并进行干预以潜在地推迟故障,甚至完全防止故障发生。

结束语

毫无疑问,人工智能具有强大的功能、优势和重要性。我们既不应该回避这项技术,也不应该害怕它。尽管如此,我们也应该始终牢记它的局限性,以不断增强我们的智力,达到更新更高的里程碑。

“有人称之为人工智能,但现实是这项技术将会增强我们。因此,我认为我们应该增强我们的智能,而不是人工智能。”—吉尼·罗梅蒂

想联系吗?

我很想听听你对这个话题的想法,或者其他什么。如果你想联系我,请发邮件到 davidfarrugia53@gmail.com给我。

Linkedin——Twitter

从设计到部署:机器学习应用的整个生命周期

原文:https://towardsdatascience.com/from-design-to-deploy-the-whole-lifepath-of-a-machine-learning-app-e9e0357525cc?source=collection_archive---------29-----------------------

设计、开发、部署和维护机器学习应用程序的逐步描述。通过一个例子。用代码。

你为什么要读一篇 25 分钟的阅读时间中等的帖子?好吧,在这里我试图浓缩一个机器学习项目的完整路径,从数据分析到在 AWS EC2 上的部署。

介绍

在纯真年代,在学习完我们的第一门 ML 课程后,我们都认为要成为一名数据科学家,在笔记本上工作就足够了。

一旦我们离开幼儿园,我们就知道这与事实相去甚远。

如今,除了机器学习算法的知识(或者更常见的图书馆用法),数据科学家还必须具备许多其他技能。

这篇文章旨在通过一个完整的机器学习任务示例(我将在模型部分保持简单),从设计到部署和维护。

我这样做是因为我和许多数据科学家谈过话,也和他们一起工作过,他们在职业生涯中并不年轻,我对这个角色有很大的困惑。数据科学是一项伟大的活动,但通常数据科学家的代码很难投入生产(甚至很难阅读),因为它们是在没有考虑模型的真实用途的情况下编写的。
我发现这是一个尊重的问题——对于在数据科学家之后从事模型工作的所有可怜虫来说——提供一个可靠而简单的模型部署。
此外,如今 docker 是所有数据科学工作机会中高度要求的技能,所以为什么不花点时间看看 docker 是如何成为机器学习应用程序的呢?

用来说明机器学习项目生命周期的无处不在的图像。图片由【https://www.jeremyjordan.me/ml-projects-guide/提供

上图不错,但是我觉得可能显得有点太抽象了。我会用我糟糕的绘图能力重新设计如下。

简化的模型生命周期。作者画得不好的图像。

上面的图片也是我们在这篇文章中要遵循的模式。

问题定义

具体来说,让我们从定义我们的问题开始。想象一下,你在一家咨询公司工作(就像我一样),你的销售同事来找你说“嘿,伙计,一家房地产代理公司想要一个房价评估员,我们能做吗?”。
我希望你的回答是“没问题”,那么我们可以开始了。

在深入研究这个问题之前,让我先观察一下。应该有一个更早的(也是重要的)步骤:数据收集(可以是抓取、客户端数据库查询等。),这在这里将被忽略,因为这会导致我们偏离轨道。

0.初步分析

在这一部分之下,通常是数据收集、标记、数据分析、一些更好地理解我们正在处理的问题的可视化、数据清理等。

由于这些过程受要处理的具体数据的影响很大,我们尽可能保持简单。我们将简要描述探索性数据分析,仅此而已。

数据收集

我知道,我写了我会忽略这一部分。我没有撒谎。
在这里,我想象客户给了我们一个标签很好的数据集(这个是)。在真实(艰难)的生活中,你通常会花很多时间自己标记数据,但我们现在仍然生活在童话中。

因此,让我们从简单地将数据导入熊猫数据框架开始。

print(df.head())命令打印以下内容

可以查看打印数量boston_dataset.DESCR以获得功能的简要描述。

**CRIM**: Per capita crime rate by town
**ZN**: Proportion of residential land zoned for lots over 25,000 sq. ft
**INDUS**: Proportion of non-retail business acres per town
**CHAS**: Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
**NOX**: Nitric oxide concentration (parts per 10 million)
**RM**: Average number of rooms per dwelling
**AGE**: Proportion of owner-occupied units built prior to 1940
**DIS**: Weighted distances to five Boston employment centers
**RAD**: Index of accessibility to radial highways
**TAX**: Full-value property tax rate per $10,000
**PTRATIO**: Pupil-teacher ratio by town
**B**: 1000(Bk — 0.63)², where Bk is the proportion of [people of African American descent] by town
**LSTAT**: Percentage of lower status of the population
**MEDV**: Median value of owner-occupied homes in $1000s

最后一个是我们的目标,它不包括在数据帧中。的确,它可以通过boston_dataset.target进入。

探索性数据分析

这是你发现和熟悉你的数据的部分。

首先,查看数据中是否有缺失值是一个很好的做法。我们使用isnull()来计算每个特性缺失值的数量。在这种情况下,您可能不会惊讶地发现没有丢失值。
现在,我们将使用一些可视化方法来描述数据的分布,并理解目标变量和特征变量之间的关系。
我们发现这个分布或多或少是正态的,很少有异常值。

为了更好地研究特征变量,一种选择是相关矩阵或相关图。因为我们有相当多的相关矩阵,我们更喜欢相关矩阵,更容易可视化。

我们可以注意到的是:

  • 一些特征之间以及与目标变量之间都有很强的正相关性。如果我们想要一个线性模型,那么我们合理地选择这样的特征。通过查看相关矩阵,我们可以看到RM与目标有很强的正相关性(0.7),而LSTAT与目标有很强的负相关性(-0.74)。
  • 对于线性回归模型,检查多重共线性可能很重要。在我们的例子中,例如,RADTAX是真正相关的(直观上它们可以交换而不会丢失太多信息)。
  • 为了捕捉更高的相关阶,可以研究特征平方的相关矩阵,或者三次幂的相关矩阵,等等。
  • 人们可以用其他一些更系统的方法(如 t-SNE、主成分分析等)来减少特征。)并研究简化特征与目标变量的相关性。

基于以上观察,我们可以将RMLSTAT作为我们的特征。然而,由于这不是本帖的兴趣所在,我们将忽略这一点,使用所有的功能。

为模型准备数据

我们可以使用流行的 sklearn 方法将数据收集到列车测试分割中。

强烈建议采取最后一个步骤:立即清理您的数据管道。为此,我们将编写一组简单的函数。关键词是“模块化”,因为你想在其他项目中重用这个代码,你也可能想保持这个模型,也许添加/删除功能。

注意我们是如何使用字典为import_data函数输入参数的。这是因为我们想通过 HTTP 协议用jsonyml文件来提供这样的功能。

因为我已经记住了我想要使用的模型,所以我进一步考虑数据标准化。在向神经网络输入分布在不同区间(大小和中心点)的数据时,可能会出现一些问题。原则上,一个训练有素的模型应该适应这种差异,并对它们进行适当的编码,然而,这需要大量的数据,并且在故事的结尾,使模型更难训练,更不稳健,最终不精确。
处理此类数据的普遍最佳实践是进行特征式归一化:对于输入数据(输入数据矩阵中的一列)中的每个特征,我们将减去特征的平均值并除以标准偏差,因此特征将集中在 0 附近,并具有单位标准偏差。

因此,我们将上面的函数修改如下,

1.模型结构

在这个阶段,我们设计模型并训练它,以便评估它的性能。通常,这部分是在笔记本上完成的,不用太担心命名约定、函数、OOP、注释等。然而,我的建议(也是在这里)是尽可能的干净,因为这可以节省你数小时的时间将代码转换成可读的东西。

算法设计

之前执行的数据分析应驱动该器件。例如,基于决策树的算法或 XGBoost 将允许您获得很好的结果。

通常这部分是由试错法构成的。通常,您不希望在整个数据集上训练您的候选模型(当您有大量数据时),因此一种解决方案可能是对您的训练数据进行随机采样,并训练一组模型来比较它们的性能,并根据您选择的指标选择最佳模型。

此外,为问题选择正确的度量标准至关重要。当然,这取决于问题,但是,这里我们可以陈述一个好的指标必须满足的三个属性:

  1. 必须是单编号。你想做简单的比较。
  2. 它必须在某些数值性能方面满足要测量算法数值性能。
  3. 必须是优化它必须测量算法结果。

典型的例子是:我们挑选具有最高F1-得分和推理时间低于 10 毫秒的模型。

当然,这是初步分析。通常,在选择“正确的”之前,您可能会经历几个不同型号的完整培训。
在这里,我们假装我们已经正确地做了所有的事情,我们参考这篇伟大的文章来了解细节。

**https://medium.com/structuring-your-machine-learning-projects/satisficing-and-optimizing-metric-24372e0a73c

假设根据我们的分析,我们选择了一个神经网络模型。同样,我的建议是写你的笔记本单元格时要时刻记住你要在生产中转换这些代码,所以要干净!

你可以开始识别一种模式。配置字典将是一个 json(或 yml,或其他类似格式)文件。

一旦模型被定义和编译(如果你是 PyTorch 的人,不需要编译),我们就准备在我们的数据上训练它。

首次培训

让我们根据训练数据拟合模型,并在测试中测量性能。严格地说,我们还应该有一个验证集,但是我们以后会有时间来担心这个问题。在这一阶段,我们只想以一个工作模型和它的性能度量来结束。这是过度限制的快速而肮脏的方法,与你的代码有多乱没有关系。

模型评估

查看学习曲线总是有用的(在回归情况下甚至更有用)。

我们可以看到我们的模型仍然在最小化损失函数。这将建议增加纪元的数量。
我们也有替代方案,增加我们网络的模型化能力,即修改其架构、更多隐藏单元和更多隐藏层。我们将在下一部分尝试这两种方法。

总之,一个细心的读者可能已经注意到,测试损失似乎比培训损失要低。这是因为 Keras 计算两种损失的方式略有不同。详情参考本帖。

https://www.pyimagesearch.com/2019/10/14/why-is-my-validation-loss-lower-than-my-training-loss/#:~:text=The second reason you may,is measured after each epoch

超参数选择和优化

在上一节中,我们最后给出了两个可能的选项来改进我们的模型。

我们可以尝试两种方法,看看哪种解决方案在测试集上给出了最好的结果。我们实际上使用我们的测试集作为验证集。

之前的车型配置给了我们上面的剧情。让我们保持一切不变,只是将纪元的数量增加到 100。
唯一要做的就是修改config变量,如下所示。

config = {'data': boston_dataset,'train_test_ratio': 0.2,'model_config': {'model_name': 'house_pricing_model','layers': {'first_layer': 12, 'second_layer': 5, 'output_layer': 1},'activations': ['relu', 'relu', None],'loss_function': 'mse','optimiser': 'adam','metrics': ['mae']},'training_config': {'batch_size': 10,'epochs': 100}}

其他一切保持不变,我们可以重新初始化我们的模型,并再次运行训练函数。我们得到,

而学习曲线看起来像

伟大的结果!我们看不到过度拟合问题,损失稳定在 85/90 左右。

为了给误差值赋予一些意义,我们必须查看目标变量。df.target.describe()(以及我们之前绘制的直方图)给了我们想要的信息。

我们可以看到大约 2.3 的平均绝对误差相当于我们数据平均值的大约 10%的误差。

注意:为了使我们的误差估计更加稳健,我们应该进行 k 倍交叉验证,并取所有倍的平均值作为平均绝对误差值。为了可读性,我们将忽略这一点。

让我们尝试另一个选项,并修改隐藏单位和隐藏层的数量。

config = {'data': boston_dataset,'train_test_ratio': 0.2,'model_config': {'model_name': 'house_pricing_model','layers': {'first_layer': 64, 'second_layer': 64,'third_layer': 32,'output_layer': 1},'activations': ['relu', 'relu', 'relu', None], # Regression problem: no activation in the last layer.'loss_function': 'mse','optimiser': 'adam','metrics': ['mae']},'training_config': {'batch_size': 10,'epochs': 100}}

我们加了一层,增加了每层的隐藏单元数量。我们用这样的配置来训练吧。

数字略有提高!我们来看看学习曲线。

它们很好,但我们开始看到任何数据科学家的克星:过度拟合。大约在 15/20 时期,训练损失系统地低于测试损失,并且这种差异随着时期而增长。
我们可以减少历元的数量,或者插入一个丢弃层来减少过度拟合。以此类推,直到我们对结果满意为止。

出于我们的目的,我们将在这里停下来,选择以下配置。

config = {'data': boston_dataset,'train_test_ratio': 0.2,'model_config': {'model_name': 'house_pricing_model','layers': {'first_layer': 64, 'second_layer': 64,'third_layer': 32,'output_layer': 1},'activations': ['relu', 'relu', 'relu', None], 'loss_function': 'mse','optimiser': 'adam','metrics': ['mae']},'training_config': {'batch_size': 10,'epochs': 17}}

Optuna

另一个更有效的选择是用库寻找最佳超参数配置。Optuna 就是这样一个库,最近他们还推出了一个寻找最佳模型架构的实验特性。我的建议是尝试一下。

https://medium.com/optuna/using-optuna-to-optimize-tensorflow-hyperparameters-57b6d4d316a2

超参数优化是一个非常有趣的话题,它本身需要一系列的帖子,但是对于本文,让我们按照我们的指导示例,继续构建培训管道。

管道建设

因为我想把重点放在服务部分,这里我将保持培训管道简单,但是,你可以让这成为你想要的复杂。例如,您可以构建另一个应用程序来构建和训练您的模型。
严格地说,除了保存模型文件并导出之外,还可以在笔记本中训练模型。这是可以做到的,但是,我建议不要这样做,因为笔记本没有版本控制系统,你无法检查你是否引入了一些不兼容的问题,等等。

这里我们将采用一个折中的解决方案:我们将创建一个脚本,将一个配置文件作为输入(在模型的后续版本中您应该修改的唯一一个文件),并返回一个保存的模型文件。
因为我们在书写笔记本的单元格时投入了一些精力,所以脚本很容易创建。

我们将利用一个辅助库,因为我们的脚本将由命令行界面执行,并且我们希望将配置文件路径作为参数传递,而不接触脚本代码。

这个脚本非常简短,非常具有示意性。

注意,我们导入了一个utils模块,它是我们上面定义的函数的集合。还要注意,这不是最干净的方式,我们可以(通常我们应该)模块化更多,甚至更好,为我们的模型创建收集方法的类。

作为奖励,你可以将这个训练脚本转换成一个命令,也就是你会变成

python3 -m estimator train --conf config.json

到…里面

estimator train --conf config.json

要做到这一点,你可以阅读这个不错的中型职位。

https://christopherdoucette.medium.com/turning-python-scripts-into-cli-commands-aecf56dfda18

config.json文件包含定义和训练我们模型的所有信息。

模特培训

最后,我们准备对我们选择的模型进行适当的训练。一旦模型被拟合,我们保存它以便导出,并将其提供给下一节要用到的 API。

这是通过命令行 shell 中的一个命令自动完成的:

python3 -m estimator train --conf config.json

注意:为了不使这篇太长的帖子变得更长,这里我不考虑 Keras 中最伟大的特性之一:回调。可以设置一个度量并在训练期间监控它,以便当你的模型在多个时期内没有改善时自动停止拟合,或者自动保存最佳度量结果,不管它已经到达哪个时期,等等。一个很好的参考来源是 Tensorflow 的官方文档。

2.部署

既然您的模型已经被训练并保存在本地的某个地方,我们就能够开始部署的迷人篇章了。

通过这个黑暗和邪恶的词,我们简单地意味着使我们的模型可用和可达(从用户或其他应用程序)以便提供预测。

方案很简单:我们想把我们的模型放在某个地方,让它接收请求并给出预测。在我们的示例中,我们希望向模型中输入房屋(更恰当地说是描述房屋的特征向量),并获得房屋的响应价格预测。

因为我们不想成为唯一的用户或我们的模型,所以我们必须选择一个可以从我们的本地系统外部公开访问的协议(或者至少对于某个用户列表)。

现代计算机科学中的一个主要观点是https://www.sumologic.com/glossary/container/**。这里,我们指的是将一个应用与它所需的所有相关配置文件、库和依赖项捆绑在一起,以便在不同的计算环境中以高效、无错误的方式运行。沿着这条路走下去,我们将复杂的应用程序拆分成包,然后在 other 中将容器组合在一起,这样就不用担心它们将在哪个系统上执行了。

了解容器的一个很好的来源是下面的 nice medium 帖子。

*https://medium.com/cycleplatform/a-brief-introduction-to-containers-d34e64e61bc1

作者画的一幅更糟糕的图像。我们根据下面的步骤添加了数字。

本着这种精神,并遵循上图中的方案,我们必须:

  1. 创建一个 API 来服务我们的模型。我们将通过使用 FastAPI 来实现这一点。
  2. 封装我们的 API。我们将由码头工人来做这件事。
  3. 在某些服务上推送 docker 图像。我们将使用 AWS ECR。
  4. 在某个服务上部署包含应用程序的 docker 容器。我们将使用一个虚拟机服务:AWS EC2。

请注意,这些步骤与要部署的任何其他软件应用程序或多或少是相同的。

数据科学家是开发人员,必须能够遵循典型的软件生命周期。

事实上,人们也可以遵循这些完全相同的步骤,并部署“hello world”API(待办事项列表)。这实际上是一个非常好的练习,可以用来练习这样的程序。要开发待办事项 API,可以参考下面的文章。

https://surikavii.medium.com/making-a-todo-app-from-a-beginners-perspective-part-1-intro-to-fastapi-5006abbcb7a2

不要害怕,这些部分很简单。这里没有需要考虑的分析,没有试错法。我们在这里要定义的对象主要是由一代又一代的编程人员复制粘贴下来的代码。

API 创建

我们将使用 FastAPI,这是一种可能的 web 框架,您可以使用它将 Python 代码转换为通过 HTTP 协议通信的应用程序。

FastAPI 的优点是速度快(几乎像编译语言一样)、容易学习、使用广泛(大量在线支持),并且它为你的应用程序构建了方便的在线文档。

所以让我们来构建我们的应用程序。
我们需要创建以下目录结构:

├── __init__.py├── ai|  ├── __init__.py|  ├── regressor.py|  └── services.py├── main.py├── model|  └── model.h5└── schemas|  ├── __init__.py└──└── schemas.py

这并不是绝对必要的,你可以把所有东西放在同一个文件中(愿上帝原谅你),或者你可以使用框架来为你构建 Python 项目,例如 千篇一律的。然而,我强烈建议遵循固定的模式来适应这种结构。

我们将分别研究每个文件。

让我们从 main 开始,这是我们将要启动来执行我们的应用程序的文件。

main.py

你可以看到,代码是不言自明的,即使不知道该功能的确切实现,你也可以说这个应用程序在高层次上做了什么。它接收数据(类型为InputData)并返回包含输入数据和预测的字典(实际上是类型为ResponseDataAPI,参见函数装饰器)。

在 FastAPI 中,decorators 用于定义 HTTP 方法,在我们的应用程序中,我们只需要一个 get(检查应用程序的状态)和一个 post(发送数据和获得预测)。

我们可以通过终端命令在本地运行应用程序

uvicorn main:app --reload

打开浏览器,进入本地地址http://127 . 0 . 0 . 1:8000/docs我们会看到自动交互 API 文档(由 Swagger UI 提供)。您可以在http://127 . 0 . 0 . 1:8000/redoc访问替代文档页面。

这是你应该看到的。图片由作者提供。

有大量的功能需要探索(一个很好的参考总是写得很好的 FastAPI 文档,这里我只想提到两个主要方面:
1 .API 自动附带一个 web 界面。这允许你展示你的模型的工作原理,甚至向一些非技术人员展示。这是免费的。
2。您有一个 URL,可以用 json 字符串进行查询,并以相同的格式进行响应。这在生产中非常有用,你可以在网络服务器上托管这个应用程序,并开始与其他应用程序集成,这是生产程序的关键。

这个第二方面可以由终端明确询问

curl -X 'POST' \'[http://127.0.0.1:8000/](http://127.0.0.1:8000/docs)v1/services/predict' \-H 'accept: application/json' \-H 'Content-Type: application/json' \-d '[{"CRIM": "float", "ZN": "float", "INDUS": "float", "CHAS": "int", "NOX": "float", "RM": "float", "AGE": "float", "DIS": "float", "RAD": "float", "TAX": "float","PTRATIO": "float", "B": "float", "LSTAT": "string"}
]'

注意,我们必须在 json 中提供例子,收集我们训练模型的所有特性。我们可能已经更改了名称,但是由于缺乏想象力,我们让它们相对于初始数据集保持不变。

因此,例如,为了得到一个预测,我们可以给出终端命令

curl -X 'POST' \'[http://127.0.0.1:8000/](http://127.0.0.1:8000/docs)v1/services/predict' \-H 'accept: application/json' \-H 'Content-Type: application/json' \-d '[{"CRIM": 0.09178, "ZN": 0.0, "INDUS": 4.05, "CHAS": 0, "NOX": 0.510, "RM": 6.416, "AGE": 84.1, "DIS": 2.6463, "RAD": 5.0, "TAX": 296.0,"PTRATIO": 16.6, "B": 395.50, "LSTAT": 9.04}
]'

API 响应将打印在屏幕上

{"inputData": [{"CRIM": 0.09178, "ZN": 0.0, "INDUS": 4.05, "CHAS": 0, "NOX": 0.510, "RM": 6.416, "AGE": 84.1, "DIS": 2.6463, "RAD": 5.0, "TAX": 296.0,"PTRATIO": 16.6, "B": 395.50, "LSTAT": 9.04}],"predictions": [{"Prediction price 0": 26.900973}]
}

ai/regressor.py

这是包含我们模型的类定义的文件。我们定义了PriceEstimator类并给出了最少的方法。通常,你不希望有人可以从 API 训练你的模型,因此这个对象没有train方法。有predict一千,因为你想暴露你的预测模型。

您可以看到我们在数据管道中使用的功能。任何程序员的动力都应该是懒惰。
在这种情况下,一种更简洁的方法是从我们之前定义的模块中简单地导入相同的函数,尽管通常情况下,您希望将代码的训练部分和预测部分很好地分开。

ai/services.py

该文件包含从预先训练的保存文件中返回预测和模型载荷的代码。注意我们是如何从环境中读取MODEL_FOLDER变量的。这意味着(要在本地运行应用程序)我们必须将模型路径添加到环境中。如何做到这一点取决于操作系统,快速的谷歌搜索会给你答案。在 linux/mac 上,这可以通过以下方式在终端中完成

export MODEL_FOLDER='path/to/your/model'

schemas/schemas.py

这个文件定义了应用程序输入和输出的自定义类型(在 Python 中,任何对象都是一种类型)。

众所周知,Python 是一种动态类型的编程语言,这意味着变量的类型不是声明的,而是通过它们的值来推断的,并且还可以在程序执行期间改变。
这种行为真的很方便,因为你不需要定义变量类型,也不需要注意不要给不同类型的值分配相同的变量名,等等。然而,这也是 Python 与其他静态类型语言(如 C/C++、Go 等)相比如此缓慢的主要原因之一。
关于详细的讨论,人们可以阅读这篇极其有趣的参考文献或相关的维基百科页面。

我们已经指出,我们想要使用 FastAPI 这样的 web 框架的原因是,它几乎与编译语言一样快,这是通过允许稍微修改类型声明的行为来实现的。
因此,我们将定义和设置输入和输出数据的固定类型。

这是由[typing](https://docs.python.org/3/library/typing.html) 库完成的,并不是真正的类型声明,更多的是一种暗示。通过这种方式,我们允许 Python 解释器为“声明的”类型分配适量的内存。

我们定义了一个可以在 FastAPI 的交互式文档页面上显示的示例。

请注意我们是如何定义 main.py 函数中声明的类型的。

对接 FastAPI

我们现在准备好对接我们的应用程序。
我们已经讨论了为什么容器在现代软件行业中至关重要。在这里,我只想综合 docker 解决的一个问题。

看我的模特有多酷。我会把脚本发给你,这样你就可以在你的机器上执行了。
B :收到,但是导入 xxx 库时出错,我通过堆栈溢出解决了,现在我的数字和你的不一样。
A :过来看看我的屏幕,这里果然好用。

如果 A 给 B 发送了一个 docker 图像,这种情况就不会发生。

让我们看看如何对接我们的 API。要对应用程序进行 dockerizeize 化,首先,您需要一个 docker 文件

Dockerfiles 描述了如何为容器组装私有文件系统,还可以包含一些元数据,描述如何基于映像运行容器。(回想一下图像和容器的区别,此处)。

我们还将使用一个名为requirements.txt的文件,它是我们在项目中使用的所有库及其版本的列表。我们希望我们的应用程序在任何机器上运行都没有兼容性问题。

如前所述,接下来的部分可以非常简单地呈现出来,在这里,我密切关注下面的精彩帖子,只是根据当前的情况调整命令。

https://medium.com/@meetakoti.kirankumar/deploying-fastapi-web-application-in-aws-a1995675087d

i)创建一个 docker 文件

这里我们让我们的应用程序运行在地址http://0 . 0 . 0 . 0:5000
注意我们是如何将模型位置定义为环境变量的:这是因为我们的应用程序从环境中读取这样的值。

ii)构建 Docker 映像:

这是通过行命令完成的

docker build -t price_estimator_api:latest .

iii)运行 docker 镜像

现在简单的部分:让我们运行 docker。

docker run -p 5000:5000 price_estimator_api:latest

页面打开浏览器即可验证 app 运行 http://localhost:5000/docs

想了解更多关于 Docker 的知识,可以看看官方教程。

https://docs.docker.com/get-started/overview/

推进亚马逊弹性容器注册

现在,您已经验证了您的应用程序容器正在本地运行,我们准备将它移动到某个可访问的“位置”。这可以是任何具有公共(或至少非本地)访问权限的服务器。这里我们想使用 AWS EC2 服务。

我们不想考虑机器配置、可伸缩性等问题。因此,我们将把 docker 图像放在 docker 注册中心,即 Amazon 弹性容器注册中心(ECR)上。这是一个完全管理的 Docker 容器注册中心,使开发人员可以轻松地存储、管理和部署 Docker 容器映像。

首先,为了将 docker 映像推送到 ECS,您需要安装和配置 AWS CLI。AWS 网站上有相关说明。

配置 AWS CLI 的一种方法是从 AWS 控制台中的身份和访问管理(IAM)获取访问密钥 ID 和秘密访问密钥。

您只需创建新的访问键并存储它们以备将来之用。

在终端中,您可以配置访问权限。

aws configureAWS Access Key ID [None]: ***AKIAIOSFODNN7EXAMPLE***
AWS Secret Access Key [None]:***wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY***
Default region name [None]: ***eu-west-3***
Default output format [None]:***json***

您现在可以使用以下命令访问 ECR,提供地区账户 id 的详细信息。

aws ecr get-login-password  --region **region** | docker login --username AWS --password-stdin **aws_account_id.**dkr.ecr.**region**.amazonaws.com

如果一切顺利,您应该会在控制台上看到“登录成功”

现在,您可以在 AWS 注册表上推送您的映像。
首先,创建一个资源库。

aws ecr create-repository --repository-name price_estimator_api

标记您的图像,以推动注册表。

docker tag price_api:latest **aws_account_id**.dkr.ecr.**region**.amazonaws.com/price_estimator_api

最后,运行命令将映像推送到 ECR 上。

docker push **aws_account_id**.dkr.ecr.**region**.amazonaws.com/price_estimator_api

在 EC2 上部署

在将 docker 映像推送到 AWS ECR 之后,我们现在准备创建 Amazon EC2 实例,它可以为您的 web 应用程序提供服务。AWS 在免费层中提供了许多实例,在这种情况下我选择了一个 Linux 实例(您也可以使用其他实例,但一定要记住相应地更改配置)。

i)去亚马逊控制台;选择 Amazon Linux EC2 实例。

ii)选择通用 t2.micro 实例类型,例如。

iii)通过使用自定义 TCP 作为类型和端口作为 5000(我们公开了 API 的该端口)添加规则来更改安全设置,并单击 review 并启动实例。这些配置是我们的 web 应用程序运行所必需的。

iv)从下拉菜单创建新的密钥对中选择,创建一个新的密钥对,为密钥对提供一个名称,然后下载。

由私钥和公钥组成的密钥对是一组安全凭据,用于在连接到实例时证明您的身份。

您应该能够看到实例正在运行。

您下载了密钥对,所以需要一个.pem密钥。假设我们给出了名称priceestimator.pem,我们可以使用这样一个文件通过安全的 ssh 连接登录到 EC2。

ssh -i priceestimator.pem ec2-user@**ec2-18-221-11-226.us-east-2.compute.amazonaws.com**

登录后,我们在 EC2 上安装 docker,配置 AWS access 以授予机器访问 docker 映像的权限,并将 docker 容器拉至机器。

AWS 配置如上开始,

aws configureAWS Access Key ID [None]: ***AKIAIOSFODNN7EXAMPLE***
AWS Secret Access Key [None]:***wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY***
Default region name [None]: ***eu-west-3***
Default output format [None]:***json***

然后我们运行以下命令来添加 ec2 用户,以便在 Linux 机器上执行 docker 命令。

sudo groupadd dockersudo gpasswd -a ${USER} dockersudo service docker restart

退出实例,并再次通过 ssh 进入 EC2 实例。

ssh -i priceestimator.pem ec2-user@**ec2-18-221-11-226.eu-west-3.compute.amazonaws.com**

登录 Amazon ECR 注册表:

aws ecr get-login --region **region** --no-include-email

输出

docker login -u AWS -p <password> -e none https://<aws_account_id>.dkr.ecr.<region>.amazonaws.com

复制上面的输出,并在命令行中运行它。成功登录 AWS ECR 后,您可以在控制台中看到“登录成功”。

从 EC2 上的 AWS ECR 中提取 docker 图像。

docker pull **aws_account_id**.dkr.ecr.**region**.amazonaws.com/price_estimator_api:latest

在 Linux 机器上运行 docker 容器

docker run -p 5000:5000 **aws_account_id**.dkr.ecr.**region**.amazonaws.com/price_estimator_api

最后,我们可以从实例详细信息页面获取 IPv4 公共 IP,并在浏览器中启动它时添加端口 5000。这将显示在 EC2 上运行的 API。
现在你可以用一个更容易理解的 URL 来代替这样的 IP 地址。

尽情享受吧!

4.维护

最后是甜点:维护部署的应用程序至关重要。数据分布的变化可能导致模型没有预测能力。

现在你的模型工作正常,你真幸运。你很高兴,并准备为另一位客户和另一位模特重复这个故事。

然而,房地产代理机构开始在一个非常不同的位置出售一些房子。他们使用你的模型,他们发现你的估计完全错误!他们对你的公司很生气,你的老板开始数落你糟糕的工作。

你会怎么处理这件事?

幸运的是,通过像你所做的那样行动,你可以很容易地部署一个新的模型,通过对新数据进行训练,使你的模型在新数据分布上更加准确。让我们看看怎么做。

我们之前所做的不会丢失。我们可以加载当前模型,并将其用作新列车的起点。我们利用以前学习的权重,并简单地根据新数据训练我们的模型。如果有必要(出于某种原因,你想完全改变你的模型),你也可以开发一个新的模型。如果你编码正确,在整个管道中不会有任何变化。

加载当前模型 作为config.json中的预训练。现在您可以重新启动训练脚本并获得新训练的模型。更改保存模型名称以保持版本控制。

保存新模型和以前一样,我们将模型保存在 API 将要读取的文件夹中。我们可以在命名约定中添加日期时间参考,以便跟踪版本。

修改 Dockerfile 因为我们对应用进行了版本化,所以我们修改了Dockerfile以获得要部署的正确模型版本。

最后,推送 Docker 镜像,使其如上运行。

注意:通常建议将部署部分写成管道,在每次推送某个 git 存储库时自动启动。所有 git 控制系统都提供了安全注册一些存储库环境变量的可能性。人们可以在那里设置一些秘密的 AWS 凭证,并自动完成这一部分。更多信息,请看下面的教程,例如。

结论

首先,如果你读到这里,让我祝贺你!这个帖子变得比我预期的长了一点。

总之,我试图通过一个具体的例子,根据我的经验总结典型的数据科学项目是如何发展的。我想警告你:这不是完整的故事。我错过和忽略了许多要点,许多警告,许多不同的请求,等等。

例如,另一种可能性可能是根本不用容器和服务,而是用其他语言转换我们的模型,使之易于在线运行。
例如,对于一个 web 应用程序,可以用 JavaScript 转换模型(例如利用在浏览器上运行模型的 TensorFlowJS 或 TorchJS ),然后在某个服务器上建立一个网站。这是一个具体案例的例子。的确,这可以通过网站访问,但如果你需要一个应用程序来访问它呢?还是其他一些非人类的服务?

Docker 是一种更通用和广泛使用的方法,这就是为什么我选择在这里介绍它。
因此,在不完整的情况下,这篇文章旨在以图解的方式说明机器学习项目的生命周期。我希望这能对初级数据科学家有用,他们经常在这个广阔的世界中感到迷失,也希望更多的专家人物能给我一些提示,告诉我我肯定忘记了的要点。

我希望你喜欢读这篇文章!

重要的是:我发表这篇文章也是为了得到建议,讨论和了解我的编码中的弱点。请指出任何错误/冗余代码!😫

🤯 你见过多次点击“拍手”按钮会发生什么吗?***

从 DevOps 到 MLOPS:使用 Jenkins 和 Docker 整合机器学习模型

原文:https://towardsdatascience.com/from-devops-to-mlops-integrate-machine-learning-models-using-jenkins-and-docker-79034dbedf1?source=collection_archive---------3-----------------------

如何用 Jenkins 和 Docker 自动化数据科学代码:MLOps = ML + DEV + OPS

Annamária Borsos 摄影

MLOPS = ML + DEV + OPS

有多少创造出来的 AI 模型已经在企业投入生产?随着对数据科学团队和技术的投资,人工智能项目的数量显著增加,随之错过了许多投入生产和评估实际商业价值的机会。其中一个解决方案是 MLOPS,它能够将数据科学和 IT 运营结合起来,在生产中部署、监控和管理 ML/DL 模型。

持续集成(CI)和持续交付(CD),也称为 CI/CD 管道,体现了 DevOps 团队的敏捷操作原则和实践的文化,允许软件开发团队更频繁、更可靠地更改代码,或允许数据科学家持续测试模型的准确性。CI/CD 是一种关注业务需求的方式,例如改进的模型准确性、自动化部署步骤或代码质量。持续集成是一组实践,驱动开发团队持续地实现小的变更,并将代码签入版本控制存储库。如今,数据科学家和 IT 运营人员拥有不同的平台(内部、私有云和公共云、多云……)和工具,需要通过自动集成和验证机制来解决这些问题,以便灵活地构建、打包和测试应用。通过自动向选定平台交付应用程序,持续交付在持续集成结束时介入。

本文的目标是使用 Jenkins 和 Docker 将机器学习模型与 DevOps 集成。用 Jenkins 和 Docker 做 ML/DL 有很多好处。一个例子是,当我们训练机器学习模型时,有必要不断测试模型的准确性。使用 Jenkins 可以完全自动化这项任务。当我们从事数据科学项目时,我们通常会花一些时间来提高模型准确性,然后当我们满意时,我们会将应用程序作为 API 部署到生产中。假设我们的模型准确率是 85%。几天或几周后,我们决定调整一些超参数并添加一些数据,以提高模型的准确性。然后,我们计划将其部署到生产环境中,为此,我们需要花费一些精力来构建、测试和再次部署该模型,这可能需要大量工作,具体取决于上下文和环境。这就是开源自动化服务器 Jenkins 的用武之地。

Jenkins 提供了一个持续集成和持续交付(CI/CD)系统,提供了数百个插件来构建、部署和自动化软件项目。使用 Jenkins 有几个优点。它很容易安装和配置,它有一个重要的社区,数百个插件,它有能力在不同的环境中分配工作。Jenkins 有一个目标:花更少的时间在部署上,花更多的时间在代码质量上。Jenkins 允许我们创造工作岗位,这是 Jenkins 构建流程的核心。例如,我们可以创建工作来用不同的任务测试我们的数据科学项目。Jenkins 还提供了一套插件,Jenkins Pipeline,它支持 CI/CD。它们可以是声明性的和脚本化的管道。

在本文中,我们将看到如何使用 Jenkins 和 Docker 集成一个在 EEG 数据上训练的机器学习模型(线性判别分析和多层感知器神经网络)。

要学习这些概念:我们来考虑以下文件: Dockerfile,train-lda.py,train-nn.py,train-auto-nn.py,requirements.txt,train.csv,test.csv

train-lda.pytrain-nn.py 是 python 脚本,它们摄取并归一化 EEG 数据,训练两个模型对数据进行分类,并测试模型。Docker 文件将用于构建我们的 Docker 映像,requirements.txt ( joblib )用于 Python 依赖项。 train-auto-nn.py 是一个 python 脚本,用不同的参数调整神经网络模型。 train.csv 是用于训练我们的模型的数据,而 test.csv 是包含新 EEG 数据的文件,将用于我们的推理模型。

你可以在GitHub:https://github.com/xaviervasques/Jenkins上找到所有文件

詹金斯装置

与 Jenkins 一起,我们将运行一个容器映像,其中安装了用于训练我们的模型的所有必要要求。为此,我们将使用 Jenkins 中的 build pipeline 插件创建一个作业链。

首先你需要安装詹金斯。在这里,我们安装长期支持版本。

在 Red Hat / CentOS 上,我们可以键入以下命令:

sudo wget -O /etc/yum.repos.d/jenkins.repo \https://pkg.jenkins.io/redhat-stable/jenkins.reposudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.keysudo yum upgradesudo yum install jenkins java-1.8.0-openjdk-devel

在 Ubuntu 上,我们可以键入以下命令来安装 Jenkins:

wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -sudo sh -c 'echo deb https://pkg.jenkins.io/debian-stable binary/ > \/etc/apt/sources.list.d/jenkins.list'sudo apt-get updatesudo apt-get install jenkins

詹金斯需要 Java。我们可以安装开放 Java 开发工具包(OpenJDK)。我们可以在这里看到安装 Jenkins 所需的所有信息:https://www.jenkins.io/doc/book/installing/

Jenkins 可以安装在许多发行版(Linux、macOS、Windows 等)上,并部署在私有或公共云上,如 IBM Cloud 或其他。您可以使用不同的命令来启动一些 Jenkins 服务,例如:

注册詹金斯服务

sudo systemctl daemon-reload

启动 Jenkins 服务

sudo systemctl start jenkins

检查 Jenkins 服务的状态

sudo systemctl status jenkins

如果一切都设置正确,您应该会看到如下输出:

詹金斯使用端口 8080。我们可以使用 ufw 打开它:

sudo ufw allow 8080

并检查状态以确认新规则:

sudo ufw status

要启动 Jenkins,通过键入 hostame -I 获得服务器的 IP 地址,并通过输入您的 IP 和端口:192.168.1.XXX:8080 启动您的浏览器

您应该会看到类似这样的内容:

在您的终端中,使用 cat 命令显示密码:

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

复制护照并粘贴在管理员密码中,点击继续

然后按照一些简单的步骤来配置您的环境。

场景实施

假设我们需要定期训练我们的模型。在这种情况下,建议在 Jenkins 中包装该过程,以避免手工操作,并使代码更易于维护和改进。在本文中,我们将展示两个场景:

场景 1: 当有人更新机器学习代码或提供额外数据时,我们会自动克隆一个 GitHub 知识库。然后,詹金斯将自动开始一个模型的训练,并提供分类准确度,检查准确度是否低于 80%。

场景 2: 我们将执行与场景 1 相同的操作,并添加一些额外的任务。我们将自动开始多层感知器神经网络(NN)模型的训练,提供分类准确度分数,检查它是否小于 80%,如果是,运行 train-auto-nn.py,它将寻找我们模型的最佳超参数,并打印新的准确度和最佳超参数。

场景 1

我们将首先使用 Dockerfile 创建一个容器映像。可以看以前的文章来做:快速安装并首次使用 Docker ,使用 Docker 和 Python Rest APIs 搭配 Flask 为你的机器学习模型和机器学习预测实时构建并运行 Docker 容器。然后,我们将在 Jenkins 中使用 build pipeline 来创建作业链。我们将使用一个简单的模型,线性判别分析,用 scikit-learn 编码,我们将用 EEG 数据(train.csv)训练它。在我们的第一个场景中,我们希望设计一个 Jenkins 流程,其中每个作业将执行不同的任务:

  • 工作#1: 当我们在 GitHub 中更新代码时,自动提取 GitHub 库

  • 工作#2: 自动启动机器学习应用,训练模型,给出预测精度。检查模型精度是否低于 80%。

詹金斯使用我们的 linux 与用户所谓的詹金斯。为了让我们的 jenkins 用户使用 sudo 命令,我们可能想要告诉操作系统在执行命令时不要询问密码。为此,您可以键入

sudo visudo /etc/sudoers

这将在编辑模式下打开 sudoers 文件,您可以如下添加或修改文件:

jenkins ALL=(ALL) NOPASSWD: ALL

另一种可能更安全的方法是在/etc/sudoers.d 目录中创建一个文件,因为该目录中包含的所有文件都将被自动处理,从而避免修改 sudoers 文件,并防止升级过程中出现任何冲突或错误。您唯一需要做的就是在 sudoers 文件的底部包含这个命令:

#includedir /etc/sudoers.d

要使用正确的权限在/etc/sudoers.d 中创建新文件,请使用以下命令:

sudo visudo -f /etc/sudoers.d/filename

现在我们只需要在文件中包含相关的行:

jenkins ALL=(ALL) NOPASSWD: ALL

打开 Jenkins 并点击自由式项目

工作#1: 当我们在 GitHub 中修改 ML 代码时,自动提取 GitHub 库

点击创建一个作业并将其命名为下载或其他名称。

在源代码管理中,选择 Git,插入您的存储库 URL 和您的凭证。

转到构建触发器并选择轮询 SCM

你可以点击“?”获得一些帮助,但仅举一个例子,H/10****意味着每 10 分钟从 GitHub 下载一次代码。这对于我们的示例来说并不太有用,所以您可以将 Schedule 框留空。如果您让它为空,它将只在由提交后挂钩触发时,由于 SCM 更改而运行。

然后,单击“添加构建步骤”下拉菜单,并选择“执行 shell”。键入以下命令,将 GitHub 存储库的容器复制到您之前创建的特定路径:

sudo -S cp * /home/xavi/Public/Code/Kubernetes/Jenkins/code

并点击保存

我们可以点击“立即构建”,您应该会在创建的存储库中看到您的代码。当我们在 GitHub 存储库中修改我们的文件时(git add,git commit,git push),这些文件将在我们创建的存储库中自动更新。

工作#2: 自动开始训练我们的机器学习模型,给出预测精度

让我们从建立我们的 docker 形象开始(我们可以将这一步直接放入 Jenkins):

docker build -t my-docker -f Dockerfile .

按照相同的步骤,我们将创建一个新作业。我们需要进入构建触发器并在其他项目构建完成后点击构建并输入作业#1 的名称(在我们的例子中是下载):

仅当构建稳定时,点击触发器。

然后,在 Build 中打开一个 Execute shell 并键入以下命令,自动启动机器学习应用程序,训练模型并将预测精度打印在一个文件(result.txt)中。

在这里,我们检查 my-docker-lda 是否已经构建,然后运行我们的容器并将 lda 模型的准确性保存在一个 result.txt 文件中。下一步是检查模型的准确度是否小于 80%,如果是,则输出“是”,否则输出“否”。例如,我们可以发送电子邮件来提供信息:https://plugins.jenkins.io/email-ext/

要查看作业的输出,只需进入仪表板最后成功栏,选择作业,并进入控制台输出

场景二

让我们保留工单#1工单#2 并创建一个新工单。

作业#3: 自动启动神经网络训练,给出预测精度,检查精度是否小于 80%,如果是,运行 docker 容器执行 autoML

你应该在控制台输出中看到所选的参数和新的精度。

下一步是什么?

Jenkins 真正关注的是如何自动化数据科学代码。

下一步是考虑将 Ansible 与 Jenkins 一起使用。Ansible 可以在 CI/CD 管道中发挥重要作用。Ansible 将负责应用程序的部署,我们不需要担心如何部署应用程序以及环境是否设置正确。

来源:

https://medium . com/@ fmirikar 5119/ci-CD-with-Jenkins-and-machine-learning-477 e 927 c430 d

https://www.jenkins.io

https://cloud.ibm.com/catalog/content/jenkins

https://towards data science . com/automating-data-science-projects-with-Jenkins-8e 843771 aa 02

从经济学家到数据分析师

原文:https://towardsdatascience.com/from-economist-to-data-analyst-aaa98aab267?source=collection_archive---------9-----------------------

塞缪尔如何提升自己的职业生涯,成为迪士尼的高级数据分析师

杰佛森·桑多斯在 Unsplash 上拍摄的照片

Samuel Wondim 跌跌撞撞地进入了数据分析领域。但是一旦他发现了,他就加倍努力,自学必要的技能。他很亲切地回答了一些关于他职业生涯和学习策略的问题。

在进入数据分析领域之前,你的背景是什么?

2015 年,我从佩珀代因大学毕业,获得了经济学学位,却不知道未来 5 年会是什么样子。毕业后,我做了一份又一份临时工作,希望能找到一份我擅长并喜欢的职业。

在整个过程中,我获得了我目前工作中不可或缺的技能/经验——优秀和人际沟通。2017 年,我利用这些技能,获得了突破性的时刻,当时我被一家营销公司聘为“数据分析师”,在那里我直接与一家客户合作:爱普生。

我把数据分析师放在引号中,因为尽管有这个头衔,我觉得我的角色更多的是在商业智能方面。

是什么让他想从事数据方面的职业?

我不确定大学毕业后我的策略有多棒,但它确实让我接触到了数据。即使在成为“数据分析师”的前 6 个月左右,我也没有想过要从事数据行业。

老实说,我不记得是什么事情让我改变了对未来的关注。但是一旦我知道我想弄清楚我的下一个 5-10 年将会是什么样子,我就对未来最好的职业做了很多研究。我相信你知道,数据科学和数据分析是最重要的。

有很多原因让我想离开我在爱普生的角色。但对我来说,最大的驱动力之一就是不断努力提升自己。就我个人而言,生活中没有什么比看到数小时辛勤工作的回报更令人满足的了。

你是如何自学的?

我在 Udemy 上选了一些小众主题的课程,比如数据可视化、时间序列分析、SQL 等等..但是我大部分的学习都是通过看大量的 YouTube 免费完成的!那里有如此多的免费内容。你只需要知道你在寻找什么。以下是我从中获得价值的一些渠道:

对于 Python 的所有内容:

  • 蒂姆的技术
  • 科里·斯查费

统计数据:

  • ZedStatistics
  • 与乔希·斯塔默的 StatQuest】

对于所有数据科学/数据分析:

  • 肯吉
  • 黄婷婷

为了获得实践经验,除了到处完成一些 Kaggle 竞赛之外,我还构建了一个端到端数据科学项目。我创建了一个模型来预测洛杉矶的房价。我用这个模型创建了一个网站,允许有抱负的购房者根据对他们来说重要的特征(如位置、卧室、面积等)来估计梦想中的房子的价格。我在导师尼尔的指导和支持下完成了这一切——他是我在sharpes minds上找到的。

做这些的时候你还在全职工作吗?

是的,我在自学的同时还在工作。如果你足够幸运,有一个与数据科学相关的职位,那么你就有机会把你所学的东西应用到你的实际工作中,获得你正在寻找的实际经验。

然而,不要想当然。如果你来自另一个领域,你不应该气馁。你可以和志同道合的人一起加入很多论坛/社区,在你的自学之旅中引导/激励你。

你是如何找到工作机会申请的?

我试着利用一切可以利用的资源。以下是我申请工作的来源分类:

LinkedIn: 45%*

安琪拉:35%

事实上:13%

大学就业委员会:5%

夏普明斯工作委员会:2%

*LinkedIn 包括招聘人员推荐的职位和工作。

我收到了更多来自 AngelList 和我的大学就业委员会的复试/面试。我的大部分工作申请都来自 LinkedIn,因为我在那里找到了更多让我感兴趣的机会。我现在在迪士尼的角色是招聘人员在 LinkedIn 上联系我的结果。我坚信多年的准备和其他面试的失败让我走到了那一步。

面试中最让你惊讶的是什么?

我学到的最令人惊讶的一课是大多数面试是多么的非正式/轻松。如果你像我一样(以及我们领域的许多其他人),你可能患有冒名顶替综合症。对自己胜任所申请工作的能力缺乏信心是一种非常普遍的感觉。这种感觉会让你在面试前非常焦虑;就像我一样。

然而,这种焦虑感在面试几分钟后就消失了。随着我经历的每一次成功的面试,时间很快就变成了秒;秒钟也不复存在了。最终,我在面试前没有感到任何焦虑。

如果再来一次,你会有什么不同的做法?

我什么都不会改变。我会继续遵循 SharpestMinds 给我的“该做什么,不该做什么”的建议,因为他们一直在关注数据就业市场。我会继续沉浸在所有的知识中,体验我最敏锐的导师(向尼尔大喊!)赐予我的。

然而,我会更加珍惜这次旅程。保护你的心理健康,定期休息。信任过程;如果你不欺骗自己,你就会越过终点线。

Samuel 是迪士尼流媒体公司的高级市场分析师。你可以在 LinkedIn 这里和他联系。

从平地到猪天堂

原文:https://towardsdatascience.com/from-flatland-to-hog-heaven-the-four-lands-of-ekg-adoption-945571c09b67?source=collection_archive---------29-----------------------

EKG 收养的四块土地

企业知识图(EKG)采用的四个领域。你生活在哪里会影响你对商业问题的看法。图片由作者提供。

这个博客是一个隐喻之旅,我们许多人都在朝着构建大型企业级知识图(EKG)的概念前进。我们将看看团队需要完成的三个转变,从使用平面数据表示解决问题到在硬件优化的图形服务器上运行十亿顶点心电图。

为了帮助团队实现这些转变,我们必须了解团队在推广心电图时必须学习的新的认知风格。我们将展示人们如何从使用平面数据表示的问题解决风格过渡到大图,最后是涉及硬件优化图(HOG)数据库的问题解决。我们将关注团队在寻找业务问题中的新模式时将进行的三个不同的转变。

教导如何实现这些转变对于 EKG 福音传道者在大型组织中取得成功至关重要。我们的目标是使用易于回忆的生动故事为我们的利益相关者创建一个有趣的路线图。我们的假设是,这些生动的故事可以在我们不在身边的时候被重新讲述。伟大的故事帮助团队获得信心,他们可以复述这些故事,并向其他利益相关者解释为什么 EKG 的猪天堂之旅是值得的。

我们将在整篇文章中使用旅行地图这个比喻。每块土地都有主要的居民和他们自己的怪物。也许我们可以从这次冒险中创造一个角色扮演游戏。 你正站在一片开阔的田野上……让旅程开始吧!

认知风格的背景

1989 年 8 月,当我和史蒂夫·乔布斯在 NeXT 电脑公司工作时,我参加了当时在阿勒格尼学院的埃德·巴博尼博士的演讲。创新的 NeXT 电脑正在向教育市场推广,ed 已经成为使用先进的 NeXT 电脑教授新的解决问题技能的主要倡导者之一。

艾德向我们介绍了一个他称之为认知风格的概念,即受过专业训练的人发展出一种特定的思考和解决问题的模式。Ed 坚信,使用下一台计算机来执行任务,如创建和运行模拟,将改变学生解决问题的方式。

哈佛作家肖莎娜·祖博夫(Shoshana Zuboff)在她 1988 年的著作《智能机器时代》(In the Age of The Smart Machine)中,深入研究了技术对充满电脑的工厂和办公室中解决问题和掌握知识的影响。在将近两年的时间里,我一遍又一遍地阅读,并试图将她书中的原则应用于构建一个课程,使用 NeXTStep Interface Builder 工具教授基于 GUI 的面向对象编程。这些领域继续进化成我们现在所说的“计算思维”这些是我们试图嵌入到 CoderDojo 项目的所有在线培训中的抽象模式。

几年来,我试图将这些概念整合到我在 NeXT 的连接驱动面向对象编程课程中。我发现祖博夫关于不同背景的人以不同方式解决问题的观点有可取之处。教授新的认知风格需要让学生接触新的问题/解决模式,并找出如何围绕这些模式创建课程。

设计一个高质量的课程来帮助学生向这些新风格过渡是一个不平凡的过程。这需要对同一门课程进行大量的教学,同时仔细观察和测试每一门课程,并多次重复以达到良好的效果。这是我现在在 EKG 花了很多时间的事情。

这个帮助人们采用新的认知风格的过程的核心是识别和标记不同的风格,并学习策略来帮助学生在没有太大压力的情况下优雅地过渡到新的认知风格。我们需要提供垫脚石,帮助他们朝着新的方向前进。这里是我试图在采用心电图作为组织的中枢神经系统核心的路线图中标记和识别四种不同的风格。

假设一个积极的意图

我们带着积极意图的假设开始了穿越这四个国家的旅程。我们假设,在这个共同的旅程中,所有的参与者都想为他们的客户提供良好的服务。他们并没有故意拒绝向顾客提供服务。他们只是没有合适的背景和经验从一个地方迁移到另一个地方。我们问这样一个问题,“我们怎样才能帮助他们踏上征程。

我们假设,如果我们的参与者深刻理解了每个领域的优缺点,他们会做出最好的决定来构建服务于他们客户的系统。但是我们的许多团队被困在一个地方,在现有系统上有相当大的投资。有时是第三方软件只在遗留数据库上运行。有时,人们认为,尽管竞争对手继续利用新技术,旧方法仍将继续有效。无论他们的偏见是什么,当他们准备好的时候,EKG 福音传道者的工作就是帮助他们过渡到认知的下一个层次。

企业知识图的四个领域

为了帮助我们在采用心电图的路线图上可视化不同的认知风格,让我们创建四个不同的“认知领域”并给它们贴上标签。我们将把它们中的每一个都视为解决问题模式的孤岛,并寻找我们需要做出的改变,以使它们迁移到下一个解决问题的孤岛。我们从一个我称之为“平地”的地方开始,这个地方是以埃德温·艾伯特 1884 年令人愉快的讽刺小说命名的。这本书和随后由它改编的电影应该有自己的博客,但那是另一篇文章。

岛屿 1:平地

平地:5000 年的行列数据思维。作者的作品。

平地是我们数据认知的起点。知识的平面表格表现了我们的平原的特征。我们在周围世界看到的一切都需要整齐地排列成表格的行和列。这种知识的平面表示非常方便。它真正开始于 5000 年前,当农业在肥沃的新月地带开始流行时,我们开始用粘土写会计记录。这些泥板按行和列记录了农业交易。我们的会计系统今天仍然这样做。

平地是一个拥挤的地方。我估计 90%的非湾区组织都住在这里。许多人职业生涯的大部分时间都住在这里。

平面知识表示经过多年的发展,从泥板到纸莎草卷轴、纸质分类帐、穿孔卡片、COBOL 平面文件,再到关系数据库中的表格。电子表格是平地上最伟大的居民之一。

我在一家拥有大型会计部门的公司工作了几年。他们通常直接雇佣大学毕业的会计学生,公司的高级合伙人监督他们的培训。这些高级合伙人广泛使用电子表格。令我惊讶的是,他们变得如此聪明,几乎在做每一项任务时都使用电子表格。他们会用电子表格的单元格给我发送长文本文档,而不是使用 MS-Word。他们没有使用 PowerPoint,而是用新的文本和图形翻阅电子表格标签。当他们遇到数据库问题时,Excel 成为他们的数据库,当他们有编程任务时,Excel 宏是因为他们的编程语言。

显而易见的是,他们以聪明的方式使用他们拥有的工具,但是当他们被给予一个不适合行列的新任务时,他们经常会挣扎。当一个项目与许多其他项目有关系时,他们通常用逗号分隔的值填充一个单元格。当行中有许多未知的单元格值时,它们的电子表格大多是空的(稀疏的)。

然后平面文件出现了一个新特性,叫做外部引用。这些是比较两个表中的两列以查看事物是否相互关联的方法。如果是的话,那么这些表就可以连接起来,一个新的表就诞生了。

挑战在于,虽然连接操作对于连接两个或三个表很有效,但是需要连接的表越多,性能就越慢。关系非常复杂的事情很难建模,也很难扩展。事实上,数据建模者都同意他们必须走捷径来减少连接的数量。他们用肮脏的反规范化剑与怪物战斗。这些决定降低了模型的精确度,模糊了现实。数据元素有时填充了不属于那里的数据。关于一个专栏真正含义的小谎言悄然而至,让报道团队痛苦地揪着自己的头发。

当这些新的关系模型被创造出来的时候,它们是柔软的,易成型的。但是随着越来越多的数据被加载,它们变得又硬又脆——就像混凝土硬化一样。每创建一份报告,事情就变得更加困难。最终,即使是很小的变更也需要长途跋涉去拜访数据建模变更控制委员会。很少有人从山顶回来时脸上带着微笑。

平地用户需要耐心。他们的网页需要几十秒的时间来渲染,而且随着更多的数据加载到他们的系统中,他们似乎总是变得更慢。有时,当系统上的其他人较少时,用户会熬夜。

平地上的用户在走路时,腿上缠着一个叫做“ERP”的大球链。这些系统旨在管理公司的传统会计和财务系统。但是他们在为你的网站上的 20,000 个并发用户创建低于 50 毫秒的推荐方面做得不好。

平地上的极速赛车手驾驶由单个大型事实表驱动的汽车,这些事实表只有一级连接到共享维度。当团队无法就事实或维度达成一致时,他们会迅速制造新车来优化他们的连接。Flatland 最初的目标是建立一个单一的数据仓库,让每个人都来崇拜分析之神。现在有数百个小数据集市在岛上行驶,每个都有自己的真相版本。

认知风格:我们可以在这个表格、行或单元格中放入什么?如何才能让模型保持简单?我们如何最小化连接?

主要玩家:电子表格怪物,加入怪物,规模怪物,事实表速度赛车

岛 2:单节点图形陆地

单节点图形土地。这里没有连接怪物,但是可伸缩怪物仍然存在——作者的作品。

在这第二个岛上,住着永远战胜了怪物的人们。当遍历关系时,它们不是比较列,而是简单地跳过内存指针。它们又轻又快。但是在我工作的团队中,只有大约 5%的人尝试过单节点图。

这片土地充满了表演和洞察力。在这片土地上,网络屏幕都在 1/100 秒内呈现。单节点 Graphland 的海岸充满了美丽复杂的形状和许多反映真实世界的复杂关系。在真实模型上没有妥协。开发商感觉他们在天堂,在海滩小屋啜饮椰汁可乐。

单节点图土地是一个相对的天堂,因为人们没有生活在怪物的恐惧中。当复杂性出现时,他们只是通过随意添加新关系来处理它。因此,数据模型充满了真实和美丽。数据模型被优雅地展示为真理的公共雕塑。没有人有任何过于简单化的秘密要隐藏。每个人都共享一个数据模型,因为它是真实的世界模型。共享有助于降低成本。

在“新数据负载”海啸袭击他们之前,一切都很好。然后行动小组开始紧急行动。因为如果这些小指针不适合可用的 RAM,所有的查询都会突然变慢,等待新数据从固态硬盘或更糟的是,永远缓慢旋转的磁盘换入。添加额外的 RAM 有所帮助,但是随着数据量的增长,这种设计从根本上来说是不稳定的。响应时间变得难以预测。试点项目往往与真正的企业级问题隔离开来,图形团队专注于适合服务器内存的问题。开发人员生活在对新数据加载的恐惧中,并努力将所有内容保存在 RAM 中。

认知风格:真实世界的精确模型,共享模型。但是 RAM 里能装什么呢?

关键玩家:海滩小屋中的开发者,太少的 RAM,规模怪兽,数据负载图三密,像树懒一样缓慢旋转的磁盘

孤岛 3:分布式图形土地

分布式图形土地。规模不再是一个问题——作者的作品。

我们旅程的第三章是到一个相对新的岛:分布式图土地。这个岛对大多数公司来说只存在了三年,尽管像谷歌、脸书和 LinkedIn 这样的湾区公司已经在这个岛上生活了八年多。这个岛有许多与单节点图土地相同的奇迹。这些模型是精确的,可以由许多业务部门共享。但是有一个关键的区别。可怕的公羊怪物已经被抛在后面了!再也不用担心新数据负载会破坏性能!

在这个岛上,当加载新数据时,新服务器会神奇地与主岛合并。数据在新的土地上透明地重新平衡。该岛没有一个次区域承受过度的压力。所有人平均分担工作。

并且在增长期间不会中断任何服务。一切都顺利进行。随着大型季节性项目的结束,这些服务器可以转移到其他关键项目。岛屿的大小是可变的,它随着需求的变化而增长和收缩。

但是这里仍然有一些怪物。租金仍然高得令人难以置信。互联数据需求很大,但供给不足。用复杂的变更数据捕获(CDC)系统导入许多不同数据源的成本是不小的。使用简单的确定性规则将数据合并在一起需要花费时间和精力。

这里的挑战是控制系统的成本。RAM 现在很便宜,但是软件层仍然可以达到每年每 TB 六到七位数。需要对图表中的数据做出谨慎的决定。

这块土地人口还不多。我的猜测是,只有不到 3%的公司真正在构建真正的横向扩展企业知识图。然而,有许多人慢慢意识到,他们应该将它视为降低成本的一种方式,整合客户的观点,提供更好的建议和预测,利用机器学习,并创造更快的洞察时间。

因为这个岛还是新的,市场上没有足够的竞争来降低成本。几个卖主控制着这个岛。讨论的是 RAM-ROI。我们可以在 RAM 中保留哪些元素?因此,只有企业急需的数据才允许在岛上使用。如果企业不愿意为显示或报告付费,数据就会被推离孤岛,进入 blobstore 的深海,在那里可查询性会下降几个数量级。

在这个岛上,如何让这个岛成长,并不是基于人们对明显不相关的数据寻求深刻见解的梦想。这些决定是基于会计部门无情的短期成本收益分析。超过一年的数据需要一个富有的赞助人,否则数据保留规则每天都会生效。你昨天看到的欺诈数据——噗!今天没有了。

需要五年历史数据来发现模式的欺诈调查人员现在盯着不相关的图表。他们知道有联系可以发现,但是他们现在必须求助于在旧的 blob 商店和 S3 桶中搜寻。他们的 LED 蜡烛燃烧到深夜。

对新贝叶斯因果模型提出卓越假设的数据科学家在绝望的贫民窟中无家可归,因为他们的数据已经不在 EKG 了。他们带着他们的蒸汽朋克机器学习模型和他们破旧的 Jupyter 笔记本在街上乞讨,笔记本上写满了潦草的方程,只有他们看到了真正的美。

如果有异常活动,希望得到通知的团队呢?嗯,他们有一些每晚运行一次的报告。这些报告没有太多的依据,所以在他们能够提出对策之前,他们经常错过关键的变化。由于运营成本高,并非所有早期干预都是可行的。

关键人物:无情的会计师、消失的数据、走进死胡同的欺诈调查人员、气馁的数据科学家、来不及采取行动的通知。

岛 4:硬件优化图形土地(又名猪天堂)

硬件优化图形平台:每个晶体管都经过优化,以满足客户的实时需求。作者的作品。

拱起天堂:非常舒适或幸福的状态

今天我们站在分布图的陆地海岸上,眺望大海对面一个刚刚在新的火山爆发中形成的新岛屿。这个岛还不适合居住,但我们中的许多人可以看到它的潜力。这是硬件优化图(HOG)的地盘。我们称它为猪天堂,因为它有希望使我们的 EKG 作为一个真正的中枢神经系统成为现实。在猪的天堂,我们看到一种非常轻松和幸福的状态。

我们知道这块土地在那里,因为早在 2014 年就有关于 Cray Research Graph Engine 性能的传说(参见 6.10 我们的 NoSQL 案例研究这里)。我们知道图形系统可以扩展到数万 GTEPS,因为我们可以在 Graph500 基准测试中看到它们。但是,一个普通的公司能把他们的 ACID 事务放在这个数据库中并获得 5 个 9 的高可用性吗?

在这个岛上,有大量(几万或几十万)的内核等待新的任务。一个查询到达后,这些线程立即开始遍历图,快速遍历内存中线程附近的链接。我们的程序小而精确,允许我们执行复杂的操作,寻找复杂结构中的深层模式。

在猪天堂,历史数据被保留多年。欺诈调查人员不断发现不良行为并节省资金。

随处嵌入运动是猪天堂宗教的一部分。机器语言算法不断扫描图的子集,并为几乎每个顶点重建嵌入。数据管理员使用这些嵌入来持续监控每个新数据导入的数据质量和一致性。

数据不再需要发送到 GPU 集群进行训练。我们有足够的 CPU 能力。机器学习是在原地完成的。数据不会不必要地移动,安全团队晚上睡得很好。

你的数据科学家呢?他们发现了从未想象过的新见解。他们不断使用实时查询和发现流程,与不断提出新问题的主题专家实时合作。十亿个顶点查询只需片刻。

那些你永远也不能负担得起的早期预警系统呢?有成千上万的在后台不断运行。他们在有时间进行干预的时候发现异常。这些比少数派报告中的预测要好。

猪天堂是深度系统思考

《猪天堂》是深度系统思维的结果:图形喜欢它们的定制硬件。照片由布鲁诺·范德克朗在 Unsplash 拍摄

猪天堂不是一个意外。它是深度系统思考的结果。这种想法从客户需求一直到 CPU 指令集和内存访问硬件。这是我们认真了解如何存储关联知识以更好地服务于我们的客户并让我们的数据科学家成为高效的知识科学家的结果。组件交互是复杂的:带标签的属性图、无索引邻接、分布式数据库、快速指针跳转,以及在经济高效的解决方案中采用高内核数量和快速内存通道的智能硬件设计,所有这些都相互交互。

寻找盟友并确定不情愿的团队成员

在推广心电图的过程中,我们学到的一个教训是,方向上的重大战略转变需要广泛的共识。获得高管赞助只是第一步。我们需要组织上下的盟友。有时候盟友来自不寻常的地方。

例如,他们的人力资源领导能帮助你在你的组织中找到变革推动者吗?您的企业安全团队中是否有成员担心数百个小型数据集市的蔓延?市场营销中有没有人想把你的组织提升为人工智能领域的领导者?

影响图可以帮助你隔离 EKG 采用中的麻烦点。在这个图中,绿色的人是你的 EKG 拥护者,红色的立场阻碍了你的倡议——作者的作品。

构建组织结构图影响图可以是另一种"系统思维"的方式,来处理这样的问题,即查看谁在哪个岛上,以及你需要做什么来将他们转移到下一个岛上。

无论你的旅程是什么,不要试图独自完成。我们希望您能在我们日益壮大的 EKG 社区中寻找其他成员,分享您的成功故事和失败经历。在这个共同的旅程中,我们可以互相学习。

旅途愉快!

从研究生院到成为一名数据科学家

原文:https://towardsdatascience.com/from-graduate-school-to-becoming-a-data-scientist-513fc15a05bb?source=collection_archive---------29-----------------------

意见

帮助我在 2021 年进入该行业的 4 点

由绍洛·莫哈纳在 Unsplash 上拍摄的照片

2019 年 9 月,我决定攻读丹佛大学的数据科学硕士学位。我不确定投入两年的时间和金钱是否真的能帮助我实现成为一名数据科学家的目标。有几个其他的选择,比如参加训练营而不是研究生学位,但是经过一些研究,我得出结论,追求研究生学位会让我更好地实现我的目标。这篇文章将分解是什么帮助我在 2021 年闯入数据科学行业,以及我是如何从一名研究生到毕业前获得全职 offer 的。我希望这篇文章能对现在的学生有所帮助,因为从我的经验来看,仅仅获得硕士学位是不足以进入这个行业的。这不仅仅是收到一张纸!

1.学习基础知识并展示你的技能

绿色变色龙在 Unsplash 上拍照

首先,掌握基本原则。我的研究生项目为期两年,第一年,我的目标是尽可能多的学习。在完成了一半的课程后,我觉得很舒服,可以开始做兼职项目,并在网上展示我的作品。我把我所有的项目放在我的 GitHub 个人资料上,也写了关于我的项目的文章。最终目标是有一个足够好的投资组合来展示我的创造能力。在读研之前,我没有任何数据科学的经验,所以我必须创造自己的经验。如果你对如何创建一个伟大的数据科学组合感到好奇,请随时查看我下面的文章。

2.加入 DS 社区

约翰·卡梅隆在 Unsplash 上拍照

这一点可能是我能给有抱负的数据科学家的最大建议之一。尽早加入数据科学社区有助于您了解该领域的更多信息,并结识经验丰富的数据科学家,他们可以为您提供宝贵的见解和职业建议。例如,我在 YouTube 上关注经验丰富的数据科学家,听流行的数据科学播客,向我们行业的专业人士学习。参加由 Ken Jee 发起的#66daysofdata 挑战赛帮助我认识了更多有抱负的数据科学家,在社交媒体上发布我的每日更新有助于我的个人品牌。如果你想了解更多,在 YouTube 上关注谁,听哪些播客,请查看我写的两篇文章。

</5-youtubers-that-helped-me-break-into-data-science-3bff12fc6b7f>

3.申请实习和志愿者

在研究生院的最后一个季度,我决定去实习,而不是参加最后的顶点课程。我觉得从长远来看,获得专业的行业经验对我更有利。我希望我在完成项目的第一年后就去实习了。你获得的行业经验越多,你申请全职职位就越容易。获得行业经验真的帮助我了解了数据科学家的真实情况。在学校里,你主要是在处理相当干净的数据集,然而,在行业中,你将会处理杂乱的数据。如果你正在寻找更多关于如何获得实习机会的建议,看看下面我写的一篇关于这个话题的文章。

此外,请查看下面来自 Ken Jee 的视频,该视频为您提供了数据科学实习所需了解的额外提示。

最后,我强烈建议参加你的数据科学硕士项目。在丹佛大学的两年中,我一直是数据科学学生大使,在最后一个季度中,我是研究生助教。参与大学不仅在你的简历上看起来不错,而且还能帮助你进一步增加你的人脉。我真的很喜欢这些角色,因为我对数据科学充满热情。我喜欢谈论和写作数据科学,最终公司会寻找那些有才华、对该领域充满热情的应届毕业生。

4.准备面试

照片由 LinkedIn 销售解决方案在 Unsplash 上拍摄

我建议学生们尽早开始准备数据科学面试。要通过技术面试,你需要熟悉所有的基本概念。这需要时间和练习。这是没有办法的。有几个平台可以帮助你在数据科学面试中胜出。确保你早点开始练习,因为一旦你有机会去一家公司面试,你会想确保你准备好了。要了解更多关于各种面试资源的信息,请查阅我在下面写的一篇文章。

https://medium.com/codex/3-interview-prep-platforms-that-prepared-me-for-data-science-interviews-d335351e8a91

结论

我希望这篇文章能让你更好地了解是什么帮助我在毕业前获得了一份数据科学家的工作。无论如何都没有完美的公式,但如果你遵循我上面讨论的几点,你的机会肯定会增加。如果你仅仅依靠一张纸就能得到一份数据科学的工作,那你就大错特错了。你需要展示出你对这个领域的热情,因为这个领域的竞争非常激烈。如果你对这个话题有任何疑问,请随时联系我。我总是很乐意帮助有抱负的数据科学家。如果你能在任何社交媒体平台上分享它,我将不胜感激。谢谢你,下次再见 time️!✌️

https://www.navidma.com/

从高中物理到 GANs:掌握生成式机器学习的要点[1/2]

原文:https://towardsdatascience.com/from-high-school-physics-to-gans-essentials-for-mastering-generative-machine-learning-1-2-da4bd5bb5568?source=collection_archive---------14-----------------------

波动图解http://animatedphysics.com/insights/modelling-photon-phase/

GANs 和其他生成式机器学习算法仍然被大肆宣传,并在图像、文本和声音方面发挥着神奇的作用。他们不仅能够生成有趣的数据,还能解决重要的理论问题,促进大规模生产。不幸的是,今天典型的实际用例仅限于“为僵尸一代微调预训练的 StyleGAN2”。更糟糕的是,几乎没有人关心解释为什么我们在现实世界中需要生成模型以及这种需求的根源来自哪里。

接下来的两篇文章旨在弥合现代酷的东西和稍微被遗忘的老派数学建模之间的差距,当时没有大数据集和强大的神经网络。掌握本材料后,您将能够:

  • 理解为什么生成机器学习是一种伴随我们几个世纪的更强大的数据建模范式
  • 更快地学习和实现每一个现代生成模型,了解这一过程的科学基础和需求
  • 为创成式建模制定新的方案,并为研发过程或最终产品获得附加值

一如既往,所有实验的源代码,你可以在我的 Github 上找到。

作为生成模型的经典力学

无阻尼振荡器的运动示意图,即我们例子中的摆。图片来自https://www . ACS . PSU . edu/drussell/Demos/phase-diagram/phase-diagram . html

让我们记住物理课。你学到的第一个主题是简单 1D 情况下的力,运动,时间,速度,加速度。甚至在微积分课上学习微分或积分之前,你就可以很容易地根据时间和相关位置计算出物体的速度。同样的策略可以应用于更复杂的力学,如弹簧力、摆、多维力学等。你只需要用适当的公式替换,然后重新做微积分例行程序。这种建模的简化过程如下:

  • 识别****物体正在移动,有哪些位置,坐标系的原点,初始条件
  • 找到描述给定对象在给定条件下的行为的适当的** 模型**
  • 用给定的条件求解模型的 方程并找到速度、加速度或其他变量
  • 分析解决方案及其有效性

例如,在钟摆系统的情况下(在上面的插图上),您可以将对象动力学模型定义为其在拉格朗日中的动能和势能之间的平衡,如果您为单个自由度(振荡的角度)求解它,您将获得运动轨迹的方程,您可以求解不同条件下的。****

现在最酷的部分是:

就像我们用 GANs 采样人脸、猫和歌曲一样,我们可以通过解方程来采样物理对象的复杂运动。几个世纪以来?它让我们登上了月球。没有千兆字节的数据和用于深度神经网络的 GPU。

我敢打赌,他们在物理课上没教过你这个角度。如果你有这个摆的精确公式,你就有了你的“摆锤”:你只需要采样长度、重力、振幅等,并把它们插入公式:这样你就可以产生你想要的任意多的摆。唯一不同的是 GAN 有一些准随机向量作为输入,公式是用数据训练的黑盒神经网络。下面是一些采样轨迹的插图和代码,你可以在这里找到。

我们的生成模型必须能够对看起来有点像这样的轨迹进行采样

作为函数逼近的生成建模

迭代逼近另一振荡行为的神经 ODE 网络。我们能用更简单的生成模型做同样的事情吗?来自我的另一篇博文:https://towards data science . com/neural-odes-breakdown-of-other-deep-learning-breakthrough-3e 78 c 7213795

科学家也观察数据,但是用他们的头脑创造一个公式。知道神经网络是通用近似器,我们可以训练它们从数据中近似这些公式。我们来进行一个实验,在不知道摆的物理性质的情况下,想通过不同绳长、球质量、角度等的观测来学习一个黑箱公式。我们可以逐步生成我们的轨迹,将步数和上述属性作为输入,将轨迹点作为我们模型的输出

更多细节和实现都在这里。为了模拟“真实世界”的条件并增加观察的不确定性,我们将在数据中添加不同的噪声,查看源代码中的更多细节。正如我们所看到的,我们可以成功地生成不同角度、绳长等的摆轨迹,而无需知道精确的数学模型,只需观察有噪声的数据(正如在真实科学中发生的那样):

最左边的图像上有噪声的训练数据示例,中间是 theta=1,omega=1,m=1,l=1 的摆轨迹及其近似值,最右边的图像上是 theta=0.5,omega=0.5,m=1.5,l=1.5 的摆轨迹。预测是通过确定性神经网络完成的

有趣的是,随着噪声影响的增加,近似精度变得越来越差,正如所料。然而,在统计学习中,我们说,只有当我们从观察样本中学习了数据分布,我们才真正学会了如何生成数据。我们的近似是只是一个确定性函数,它没有分布的性质,我们不能从中采样不同的轨迹。

贝叶斯生成建模

高斯过程回归的示例-一种贝叶斯机器学习算法,允许在我们没有足够数据且无法对预测有信心的地方对不确定性进行建模。图片来自https://jessicastringham.net/2018/05/18/Gaussian-Processes/

简而言之,每个样本(即使是摆的同一步)都可能略有不同,因为我们在数据中引入了一些噪声,这是我们的模型无法确定每一步预测的原因。然后,我们需要在模型中捕捉这个噪声。

我们可以将模型的输出和模型的权重从确定性点估计转换为分布,我们可以从中进行采样。输出的噪声称为任意的不确定性,也是权重之一——认知的。与上一个示例相同,我们一步一步地生成我们的轨迹,但是,现在在每一步上,我们都可以根据不确定性水平对可能符合轨迹的几个潜在选项进行采样:

最左边的图像上有噪声的训练数据示例,中间是 theta=1,omega=1,m=1,l=1 的摆轨迹及其近似值,最右边的图像上是 theta=0.5,omega=0.5,m=1.5,l=1.5 的摆轨迹。使用贝叶斯神经网络进行预测,生成的轨迹具有灰色,每幅图像采样 5 个轨迹

我已经实现了与近似情况下相同的神经网络,但是在 TensorFlow Probability 的帮助下,可以很容易地将它变成一个贝叶斯神经网络。如果你想要贝叶斯机器学习的额外教程,请告诉我!如您所见,现在的结果与我们使用“GAN 框架”观察的结果相同:我们获取了数据,对其进行建模,并且我们能够对不同的实际样本进行采样。我们还可以注意到,在确定性区间内,随机生成模型实际上具有更好的准确性。它与实际的 GANs、VAEs 和其他生成模型有什么关系,我们将在下一篇博文中讨论。****

外卖食品

这个简短的介绍旨在通过一个简单的例子来说明:

  • 几个世纪以来,“生成”事物是科学的一个自然概念:我们用来解决现实生活过程问题的方程是从数学模型中推导出来的,这些数学模型可以像甘斯一样“采样”那些过程
  • 在数据驱动的世界中,我们希望“自动”创建这些模型,而不像科学家那样定义精确的公式及其参数,但仍然能够模拟现实世界的对象并求解方程
  • 我们可以通过欺骗的方式来实现它,并制作“预测”模型,这些模型将逼近我们的物理对象的数学模型的逐步解决方案,然而,我们可以用更优雅的方式来实现它

下一篇文章将从这里开始,展示实际上作为物理过程的数学模型的 gan 和 vae,我希望这将激励您在许多更复杂和有趣的工业和研究场景中学习和使用生成模型。

附言
如果你觉得这个内容有用,有观点,可以在 Bitclout 上支持我。关注我还可以在脸书上看到太短的人工智能文章,在 Instagram 上看到个人资料,在 Linkedin 上看到!如果你想在可解释的人工智能应用或其他人工智能项目上合作,请联系我。

从高中物理到 GANs:掌握生成式机器学习的要点[2/2]

原文:https://towardsdatascience.com/from-high-school-physics-to-gans-essentials-for-mastering-generative-machine-learning-2-2-82e39ca2a3b?source=collection_archive---------24-----------------------

波动图解http://animatedphysics.com/insights/modelling-photon-phase/

在之前的文章中,我们已经进行了一些实验,在这些实验中,我们已经学会了如何用机器学习算法来逼近物理定律模型,这是“真正的”数据生成过程的前奏。在本文中,我们不会简单地估计一个时间步长和对象的确切位置之间的依赖关系,而是会根据来自数据分布的对象生成整个轨迹,并尝试像在经典数学模型中一样控制这一过程和变量。

本文总结了数学建模从人类设计第一到数据驱动第一的演变思想,我希望它将阐明为什么我们今天需要生成建模,并且您将能够在您的 R&D 和产品活动中实施它。和往常一样,源代码在我的 Github 上。

从数据中学习纯“代”公式

最大化模型的可能性

我们如何学习复杂数据的分布(而不是近似函数),然后从中取样?建立这种模型最常见的方法是最大似然法(MLE) 。似然性是一个数学公式,用于衡量数学模型与经验数据的拟合度。可能性本身可以表示为:

取决于模型参数θ和数据 X 的似然函数

为了找到这样的θ,使最大化这个可能性,我们用不同的算法(例如,蒙特卡罗马尔可夫链)解决一个优化问题:

模型的最优θ,它使模型和数据之间的上述似然性最大化

这是与最小化交叉熵相同,这是你可以在文献和大部分机器学习教程中找到的,但也有关于这项任务的另一种观点。

最小化模型和数据之间的距离

让我们记住一些信息理论。某个事件 x 的自信息和对应的香农熵可以表示为:

自我信息公式/香农熵公式

信息论解决的一个典型任务是比较两个有一定距离的分布,以确定它们彼此有多远。在我们的 MLE 框架中,对数似然的交叉熵已经衡量了拟合的“良好性”,我们的目标是最大化它。在信息论方法中,我们希望最小化模型和数据分布之间的距离,我们可以使用 Kullback-Leibler 散度来描述这个距离:

分布 P 和 Q 之间的 Kullback-Leibler (KL)散度公式

最小化这种差异会导致最小化这一项:

最小化 KL 散度解,这与最大似然函数最大化相一致

我们可以看到,最小化 KL 散度与最大化似然函数是一样的!

这看起来已经很像我们以前用神经网络做的了,所以我们为什么不试着在这里应用它们呢?

生成性对抗网络 101

生成对抗网络(GAN)训练程序。图片来自https://it . mathworks . com/help/deep learning/ug/train-generative-adversarial-network . html

不幸的是,在现实生活中,我们并不确切知道数据生成过程,因此,我们不能使用 ML 最大化/ KL 最小化来训练这样的模型。学习数据分布过程的现代替代方法是两个神经网络(生成器和鉴别器)之间的最小-最大博弈。然而,我们仍然希望有一个与基础知识的联系,并保持最小化发行版之间的距离。

让我们假设,不是有一些距离的解析公式,我们可以有一个习得的散度,这本身就是一些优化问题。请注意,因为我们在这里非常 meta】。我们希望同时学习一个函数(分布之间的散度),该函数将用于学习另一个函数(生成将最小化该散度的网络):

  • 最小化“学习发散”的“外部”函数我们将称为生成器:

发生器的功能取决于必须优化的θ参数

  • 第二个“内部”函数被训练来表示数据样本属于我们的数据分布的概率。这个“内部”函数我们称之为鉴别器:

鉴别器 V 的功能必须最大化,以正确识别真实数据样本和伪造生成的样本

它通过最大化上述函数来惩罚将真实实例错误分类为假的 GAN,或将假实例错误分类为真实的 GAN

这可以用詹森-香农散度来表示。总之,应该被优化以找到两个神经网络的权重的总损失函数看起来(表示为参数θ和φ)如下:

GAN 优化目标是 1)鉴别器和 2)生成器之间的最小-最大博弈,鉴别器训练以判断新数据样本是否属于目标分布,生成器学习对尽可能接近目标分布的新数据样本进行采样

这里的主要思想是,我们仍然最小化关于发生器参数的某种 KL 散度,但是由于我们不知道 p_data(x ),我们将它作为单独的鉴别器来学习。把它放在你最喜欢的深度学习框架里面非常简单,你可以在我的 Github 或者其他很多教程里看到。现在它将学习我们的钟摆轨迹?让我们检查一些可视化效果:

最右边的两幅图像是从 GAN 中提取的样本。详细的架构可以在我的 Github 上的相应笔记本中找到

从质量的角度来看,这不是最好的结果,但这些样本显然来自我们的发行版,并且种类繁多,让我们从 GAN 相关的教程和课程中取得进步,为我们进行平滑和美化工作。我们需要专注于使发电可控就像在透明的数学模型中,每个变量都有自己的物理意义。现在,我们得到的只是随机输入噪声,与控制无关。

从数据中学习可解释的物理定律

大多数 GANs 的输入是随机向量,从中产生随机对象。在数学建模中,输入当然可以是随机向量的一部分,但是这些输入中的每一个都负责一个单一的输出属性,这对于常规的 GANs 来说是不正确的(参见我的另一篇文章中的更多为什么)。

变分自动编码器示意图,图片来源:https://theailearner . com/2018/11/10/variable-auto encoders/

然而,我们有变型自动编码器 (VAEs) 可以

  • 用称为编码器的神经网络将数据压缩成潜在向量
  • 通过给这个向量添加一些噪声,我们可以用另一个叫做解码器的网络生成新的对象(见上面的结构)

这个噪声向量可能与 GANs 中的一样无法解释,但是我们可以用损失函数中的正则项来影响它。这个术语(见下面的公式)使得所有潜在向量的所有元素最大程度地相互独立,这导致学习潜在向量的每个元素的不同数据属性(与 GANs 中的输入随机向量相反):

进行与上面相同的实验,但是这次使用 VAE,我们可以实现以下生成结果:

最右边的两幅图像是从β= 1 的 VAE 中提取的样本。详细的架构可以在我的 Github 上的相应笔记本中找到

正如我们所看到的,样品比 GAN 干净得多,这确实非常好!现在,让我们用β= 10 重新训练这个模型,让我们操纵潜在维度(我已经选择它为 6,因为我们改变ω、θ、绳子长度和物体的质量来创建数据集+ 2,我期望它们是空白的)。我们想看到的是,通过使一个潜在维度变大或变小来观察物理对象属性的变化:

样本取自β= 10 的 VAE。每张图片代表潜在向量的一个维度的变化。蓝线是原始采样轨迹,绿线表示潜在维度的增加(同时保持其他维度不变),红线表示潜在维度的减少

我们所看到的是相当棘手的…我们可以看到,最后 3 个维度几乎没有改变什么,在我们的 VAE 是“空白”代码。但是,很难把前三个维度解读清楚。我们可以说,第一个改变产生的波的频率,第二个和第三个改变振幅。这不完全是我们在生成数据时计划的,但这是神经网络看到的!我建议在其他数据集上尝试这种技术。例如,在我之前的一个实验中,我可以得到一个关于脉搏速度和一些异常的心跳的很好的表示:

关于这个实验的更多细节请看这里:https://towards data science . com/gans-vs-odes-the-end-of-mathematical-modeling-EC 158 f 04 ACB 9

外卖食品

在这两篇文章中,我们从数学建模的一阶原理中构建了生成式机器学习的思想。通过一个简单的振荡摆运动的例子,我们实现了:

  • 一个经典的人类设计的数学模型,从物理属性和时间步长中采样轨迹
  • 一个机器学习模型,它从嘈杂的经验观察中逼近动态,不需要人类设计的公式
  • 一个概率机器学习模型,它可以根据每个时间步的不确定性生成不同的轨迹
  • 一个生成对抗网络,它生成一个完整的轨迹,而不需要告诉物理属性和时间步骤
  • 一个变型自动编码器,它生成一个完整的轨迹并允许控制属性(尽管不是我们所期望的)

现在是时候处理更复杂的数据了!让我知道这种解释生成建模的方法是否有用,我应该在这方面写更多:如何生成图像、文本、声音,甚至表格数据,记住把我们的花哨 GANs 视为数学建模工具的想法。

附言
如果你觉得这个内容有用,有观点,可以在 Bitclout 上支持我。关注我还可以在脸书上看到太短的人工智能文章,在 Instagram 上看到个人信息,在 Linkedin 上看到!如果你想在可解释的人工智能应用或其他人工智能项目上合作,请联系我。

从 igraph 到 visNetwork

原文:https://towardsdatascience.com/from-igraph-to-visnetwork-7bc5a76fdeec?source=collection_archive---------31-----------------------

让您的网络焕然一新

照片由克里斯蒂安·休姆在 Unsplash 上拍摄

说到网络分析, igraph 是一个拥有大量文档的包中之兽。如果你在 R 语言中做网络分析,你可能至少听说过它。使用 igraph ,你可以创建和比较确定性或随机网络,计算中心性度量,并在网络中找到社区。你甚至可以在一个有百万个节点和边的网络上实现图形算法!

甚至在可视化方面,igraph 也有丰富的选项。首先,有您期望的绘图的基本功能:改变网络的大小、形状、标签和布局。但是,您甚至可以通过使用 tkplot()创建交互式图形来超越基础——尽管不建议将它们用于大型图形。最后,使用 rgl 包,您可以用 OpenGL 构建和可视化 3D 网络。

然而,即使拥有所有网络可视化功能 igraph 所能提供的,我仍然发现自己被 visNetwork 所吸引,即使是最基本的绘图。默认情况下, visNetwork 创建与 RStudio Viewer、R Notebooks 和 shiny 兼容的漂亮的交互式网络。毫无疑问,这是我进行网络分析的首选网络可视化软件包。只需很少的代码,您就可以快速创建一个能够突出显示所选节点及其邻居的完美网络。这对于网络分析非常有用,但对于制作用于发布的干净、专业外观的网络也非常有用。

在本文中,我们将看看如何用 visNetwork 绘制一个 igraph 对象。在添加高亮显示功能之前,我们将从默认绘图开始。最后,我们将看看如何改变节点的颜色以及如何使用不同的布局算法。

快速演示

为了说明将 visNetworkigraph 对象一起使用的便利性,我们将从 igraph 包中加载非线性图形。它由 9 个子图组成,有 50 个节点和 12 条边。

# Load packages. 
library(igraph) 
library(visNetwork) # Load the nonline graph. 
ig <- graph.famous("Nonline") # Plot with igraph. 
plot(ig)

图片由作者提供;r 输出

正如你所看到的,来自 igraph 的默认图清楚地显示了 9 个子图。然而,很难看到每个子图之间的关系。让我们将它与使用 visNetwork 的默认绘图进行比较。我们将使用 visIgraph()函数显示带有 visNetworkigraph 对象。

# Plot igraph object with visNetwork. 
visIgraph(ig)

图片由作者提供;r 输出

啊,是的!现在清楚多了!我们不仅可以看到不同的子图,还可以看到每个子图中的关系。现在,如果我们想要选择一个特定的节点并突出显示它的邻居,会怎么样呢?幸运的是,这相当简单!

用户友好的节点选择

当您对特定节点或一小组节点感兴趣时,能够通过 id 选择特定节点非常有用。或者,您可能希望通过单击网络来快速识别似乎是中心节点的节点。不管怎样, visNetwork 让用户友好的节点选择变得轻松。

首先,我们将使用管道操作符(%>%)来组合其他的 visNetwork 函数,这些函数允许我们为网络指定额外的修改。对于一般的网络选项,我们将使用 visOptions()函数。为了通过 id 突出显示特定的节点,我们将设置 nodesIdSelection = TRUE。为了突出显示所选节点的邻居,我们将设置 highlightNearest = TRUE。

# Highlight selected node and its neighbors. 
visIgraph(ig) %>% visOptions(nodesIdSelection = TRUE,  highlightNearest = TRUE)

完整交互体验,下载 R 笔记本: igraph2visNetwork。Rmd 。

图片由作者提供;r 输出

新刷的一层油漆

就我个人而言,我觉得 visNetwork 的默认配色方案相当令人满意。尽管如此,使用 visNodes()函数可以很容易地改变网络的颜色。我们将为 color 参数指定一个十六进制字符串,但是您也可以使用内置的颜色名称或软件包中的调色板。最后,为了更有趣,我们将设置 shadow = TRUE 来增加节点的深度。

# Change the color and add a shadow. 
visIgraph(ig) %>% 
visOptions(nodesIdSelection = TRUE, highlightNearest = TRUE) %>% 
visNodes(color = "#6CAE97", shadow = TRUE)

图片由作者提供;r 输出

使用 igraph 布局算法

理想情况下,网络应该既美观又易于理解。不幸的是,根据节点的位置和分布情况,完全相同的网络可能看起来非常不同。一些布局会使解释更容易,而另一些,尤其是那些边缘交叉的布局,会更难。最佳布局取决于网络的结构。在某些情况下,例如分层网络,最佳布局是预先知道的。在其他情况下,最佳布局是未知的,您可能想尝试不同的布局算法,看看哪一个是最好的。

为了了解我们如何比较不同的布局算法,让我们看看如何使用来自 igraphvisNetwork 的图形布局选项。对于这个例子,我们将使用 graph.famous()函数中的“Krackhardt kite”图。为了使用 igraph 布局选项,我们将使用来自 visNetwork 的 visIgraphLayout()函数,并为布局参数提供来自 igraph 的布局选项。我们从“布局 _ 好看”开始。来自 igraph 的 layout_nicely()函数将尝试为给定网络找到最佳布局算法。要查看其他可用的布局选项,可以使用?布局 _ 好看。其他布局选项可以在文档的底部找到。

# Load a fully connected graph. 
ig2 <- graph.famous("Krackhardt kite") # Plot graph with layout_nicely. 
visIgraph(ig2) %>% visIgraphLayout(layout = "layout_nicely")

图片由作者提供;r 输出

现在我们来看看如果用“layout_as_star”的话网络是什么样子的。

# Plot graph with layout_as_star. 
visIgraph(ig2) %>% visIgraphLayout(layout = "layout_as_star")

图片由作者提供;r 输出

哇!可能需要一段时间才能从上面识别出该网络是同一个网络。网络的布局会极大地影响网络解释的速度和准确性。这就是为什么有几个布局算法可用于 visNetwork 的原因。

超越基础

希望这足以让你开始使用 visNetworkigraph 。然而,要将 igraph 的精华与 vis network(T21)的精华融合在一起,还有很多事情可以做。例如,我们可以突出显示具有高中心性分数的节点,标记最短路径,或者按集团或社区给网络着色。如果你对涵盖这些主题的教程感兴趣,请留下评论!

引文

阿德勒博士、默多克博士等人(2021 年)。使用 OpenGL 的 rgl: 3D
可视化。r 包版本 0.105.13。
https://CRAN.R-project.org/package=rgl

Almende B.V .,Benoit Thieurmel 和 Titouan Robert (2019)。
visNetwork:使用‘vis . js’库的网络可视化。r 包
版本 2.0.9。https://CRAN.R-project.org/package=visNetwork

Csardi G,Nepusz T:用于复杂网络研究的 igraph 软件包,国际期刊,复杂系统 1695。2006.
https://igraph.org

r 核心团队(2020)。r:用于统计计算的语言和环境。奥地利维也纳统计计算基金会。网址
https://www.R-project.org/。

r 版本 4 . 0 . 2(2020–06–22)
平台:x86_64-apple-darwin17.0 (64 位)
运行于:macOS Catalina 10.15.7

原载于 2021 年 5 月 25 日 https://thatdarndata.com**的

从 Jupyter 笔记本到部署—一个简单的例子

原文:https://towardsdatascience.com/from-jupyter-notebook-to-deployment-a-straightforward-example-1838c203a437?source=collection_archive---------1-----------------------

一步一步的例子,采用典型的机器学习研究代码,构建一个生产就绪的微服务。

本文旨在作为我作为数据科学家的旅程的一个整合示例,从 Jupyter 笔记本格式的一个典型已解决问题开始,并将其发展为一个已部署的微服务。虽然会有代码,但这不是一个教程,而是一个逐步说明我在将数据科学解决方案投入生产时所面临的挑战和解决方案的示例。我也不认为我一路走来所做的选择是做事的唯一方式,而是希望它能为将来可能面临类似任务的其他人提供一个有用的例子。

这篇文章的配套代码可以在我的 GitHub 账户上找到,原始的 Jupyter 笔记本在这里和最终的完整项目在这里。我将包括这些变化的片段,以演示我们讨论的各种主题,但这并不是对所有变化的完整描述。在这篇文章中,我将关注我所采取的每一步的过程和动机。

朱庇特笔记本解决方案( 代号 )

这个玩具解决方案旨在充当数据科学家建模输出的高度简化的示例。我们可以想象,任务是建立一个分类器,给定鸢尾花的一些测量值,预测该观察值的确切种类。数据科学家获得了 Fisher 著名的 iris 数据集,并构建了一个管道来可视化和预处理数据,然后训练和评估一个简单的模型。这个模型现在可以用来预测任何新的观察结果。本文的目标是描述将这种典型的研究成果投入生产的步骤。

罗纳德·费雪在 1936 年引入了著名的鸢尾花数据集。

第一步:重构,代码风格和测试( 代码 )

第一步是将笔记本模块化成一个合理的文件夹结构,这实际上意味着将文件从.ipynb格式转换成.py格式,确保每个脚本都有明确的目的,并以连贯的方式组织这些文件。我采用了下面的标准布局,但这是灵活的,应该适应不同的用例。

我们的文件结构最终会是什么样子。

一旦项目结构良好,我们就可以整理或重构代码。例如,考虑下面的代码块,它执行对数据进行分层训练测试分割的任务:

分层分离逻辑来自我们最初的 Jupyter 笔记本。

在当前的格式中,不清楚这段代码到底在做什么,它不可重用,也无法测试。为了减轻这种情况,我们可以用文档和类型提示将它重写为一个函数。

重构的分层分裂函数。

这个看起来好多了,遵循 pep8 风格指南。事实上,我们可以通过使用 pycodestyle 这样的林挺包来确保整个项目符合 pep8。一旦安装了这个包,我们就可以导航到项目的根目录,并在命令行上运行pycodestyle src。这将列出任何 pep8 问题的位置和详细信息。我们甚至可以更进一步,使用像 autopep8 这样的包,它可以自动格式化 pycodestyle 标识的任何代码。

我们还应该简单地谈一下测试。有大量关于代码测试的文献(例如参见这里的,但是我们将在这个项目中只实现单元测试。这些测试相互独立地测试代码的最小可能单元。对于我们前面例子中的stratified_split()函数,单元测试可能看起来像这样:

对我们的分层分离函数的单元测试。

通过运行这段代码,我们将检查函数输出在许多预定义的情况下是否符合预期。这证实了我们现有的代码正在正常工作,但它也确保了如果任何未来的更改导致该函数停止正常工作,我们可以在该错误导致这些测试失败时及早发现它。

第二步:协同( 代码 )

任何大规模的项目都不太可能是单个人工作的产物,因此出于这个原因,我们将讨论版本控制。版本控制工具,如 git 是一个记录项目随时间变化的系统,允许多个用户将变化分支并合并到一个存储库中。有很多关于使用版本控制的的原则和最佳实践的文章,但是我们假设大部分数据科学工作已经完成,因此我们将专注于一个叫做pre-commit.sh的有用文件。这就是所谓的 git 钩子,git 提供的一个有用的特性,它允许在某些重要的动作发生时运行定制脚本——在本例中是命令git commit。我们可以使用这个特性在任何提交之前方便地运行test-all.sh脚本,这反过来运行我们所有的单元测试以及 pycodestyle 检查,只有在没有失败的情况下才允许提交继续进行。这个过程确保对存储库的任何更改都不会破坏现有的功能,并且符合 pep8。

另一个对协作有用的文件是名为requirements.txt的需求文件。该文件保存在项目根目录下,列出了整个项目中使用的所有 Python 包。该项目的任何新用户都可以简单地使用 pip 通过下面的命令来安装这些需求。

pip install -r requirements.txt

创建一个requirements.txt也非常简单。假设我们已经为这个项目使用了一个虚拟环境,如 venv 或 conda 并安装了所有的包,我们可以通过激活环境并运行

pip freeze > requirements.txt

第三步:准备部署( 代码 )

现在我们已经为本地使用做好了项目准备,是时候做一些改变来为云使用做准备了。其中一个变化是日志记录。在本地工作时,跟踪程序和调试相对简单。打印语句、调试工具和控制台输出的组合通常可以达到目的,但是一旦部署了组件,我们就需要一些稍微复杂一点的东西。这就是 python日志模块可以提供帮助的地方。一旦配置好模块,我们可以简单地替换打印语句,如

print('Splitting train and test sets')

随着

logger.info('Splitting train and test sets')

现在,日志可以与用户定义的元数据(如时间、模块、函数名和行号)一起存储在日志文件中。这些信息不仅可以让我们跟踪程序的进度,还可以给出用于调试目的的详细信息,这些信息都安全地存储在日志文件中。

这也是从本地存储数据和文件转向远程存储的好时机。例如,训练数据目前存储在一个在线 csv 文件中,如果我们获得额外的数据,更新该文件的过程会很麻烦。一种替代方法是使用开源关系数据库管理系统 MySQL 和它的连接器。我们不会在这里详述细节,但是一旦设置好,我们就可以使用 sql 查询轻松地从我们的数据库中读入数据。

我们还希望从本地保存文件开始。当需要进行预测时,我们可能想要使用几个月前训练的模型,获得这种类型的对象存储服务的最简单、最便宜的方法之一是通过亚马逊 S3。这里我们将再次跳过一些配置细节,但是 boto3 提供了一个方便的 Python 接口来访问 S3 桶。上传和下载文件到这个远程桶是一件轻而易举的事情,让我们可以轻松访问我们所有的模型。我还没有在本文的示例代码中实现 MySQL 或 S3,但是网上有很多其他的指导来完成这个步骤(例如,这里的和这里的和分别是)。

在我们准备开始部署之前,我们应该对这个存储库做的最后一个更改是抽象出所有硬编码的变量。一旦这个项目是远程部署,这将是一个相当艰巨的任务,以改变代码。因此,我们将把所有参数从硬编码值转移到 json 配置文件中。现在,当涉及到更改参数时,我们只需要更改这个 json 文件中的值,而不是代码本身,这样做要简单得多。像这样的一行

gscv = GridSearchCV(pipeline, parameters, cv=3, scoring="accuracy")

可能会将交叉验证折叠数和评分标准移动到配置文件中,并成为

gscv = GridSearchCV(pipeline, parameters, cv=NUM_FOLDS, scoring=SCORING)

其中变量NUM_FOLDSSCORINGdesign.json配置文件中加载,并且get_default()函数被添加到config.py中以方便访问这些值。

第四步:部署( 代码 )

完成前面的三个步骤后,我们终于准备好部署代码了。我们将把这个服务部署为一个 web 应用程序,我们将通过一组 api 端点与之通信。为此,我们将使用一个 web 框架来自动处理大量开销。虽然我们可以使用很多,但对于这个简化的应用程序来说,烧瓶似乎是一个不错的选择,因为它易于安装和运行,并且非常灵活。主要思想是通过运行python3 run_app.py,这将通过src/template_app文件夹访问项目的功能,并将在http://localhost:5000开始运行应用程序。一旦应用程序启动并运行,我们就可以使用GETPOST请求来访问它的火车,通过浏览器或 API 开发平台(如 Postman )预测或可视化功能。

在本地运行 flask 应用程序以可视化数据。

即使对于这个非常简单的项目,需求列表也开始大幅增长。对于另一个开发人员来说,启动并运行我们的代码需要设置虚拟环境并下载包。为了自动化这个过程并避免陷入依赖问题的风险,我们将使用一个叫做 Docker 的工具。Docker 有效地创建了一个空容器,从头开始安装整个项目。这样做的好处是,任何机器上的任何人都可以通过安装 docker 并简单地从项目的根文件夹中运行docker build sample_app:v.1.0 .来启动并运行我们的代码。一旦构建了本地映像,我们就可以用docker run -p 5000:5000 sample_app:v.1.0运行并公开它。就是这样!Dockerfile 文件包括下载 Python、pip 和需求的说明。然后它运行测试和 pycodestyle,如果成功完成,它通过run_app.py脚本运行应用程序。

构建 Docker 容器(注意,这比平常运行得更快,因为容器是第二次构建的,所以大多数步骤都在缓存中)。

我们现在已经将我们最初的 jupyter 笔记本电脑转变为一个完全成熟的微服务。我们的最终代码是模块化的,它遵循 pep8,包括日志记录和测试,并且可以作为 Dockerised Flask 应用程序进行部署。我们还讨论了 SQL 和 Amazon s3 的数据管理。你应该在哪里部署你的应用将取决于你的项目需求,大规模的项目通常使用 AWS 、 Azure 或 Google Cloud ,而像 Heroku 这样的平台为小型爱好项目提供免费托管。对于拥有大量微服务的大型项目来说, Kubernetes 是一个开源系统,用于自动化容器化应用程序的部署、扩展和管理。一旦一个大型项目投入使用,持续集成就会成为一个主要的挑战。在这种情况下,像 Jenkins 这样的自动化服务器可以管理与构建、测试和部署软件相关的任务。

感谢您的阅读,请在评论中分享您的反馈或问题。

[图片来源 Unsplash]

自然语言处理的向量代数

原文:https://towardsdatascience.com/from-linear-algebra-to-text-representation-for-natural-language-processing-239cd3ccb12f?source=collection_archive---------22-----------------------

在向量空间中表示单词语义

迈克尔·泽兹奇在 Unsplash 上的照片

自然语言处理领域包括构建技术,由像你我这样的人用自然语言处理文本,并从中提取见解,以执行各种任务,从解释搜索引擎上的用户查询和返回网页,到作为聊天机器人助手解决客户查询。将每个单词表示为一种能够捕捉单词含义和整体上下文的形式变得至关重要,特别是当重大决策基于从大规模文本中提取的见解时,例如通过社交媒体预测股票价格变化。

在本文中,我们将从向量代数的基础知识开始,了解向量的直觉和它们对于表示特定类型信息的意义,在向量空间中表示文本的不同方式,以及这个概念如何发展到我们现在拥有的艺术模型的状态。

我们将逐步了解以下领域-

  • 坐标系中的单位向量
  • 向量的线性组合
  • 向量坐标系中的跨度
  • 共线性和多重共线性
  • 向量的线性相关性和独立性
  • 基本向量
  • 自然语言处理的向量空间模型
  • 密集向量

坐标系中的单位向量

i - >表示指向 x 方向的单位向量(长度为 1 个单位的向量)

j->表示 y 方向的单位矢量

合在一起,它们被称为我们的坐标向量空间的基础。

我们将在下面的后续部分中更多地讨论术语基础

标准单位矢量—作者图片

  • 假设我们有一个向量 3I+5j**
  • 这个向量的 x,y 坐标分别是:3 和 5
  • 这些坐标是标量,分别在 x 和 y 方向上翻转和缩放单位向量 3 & 5 个单位

2D X-Y 空间中的一个向量——作者图片

两个向量的线性组合

如果u&v是二维空间中的两个向量,那么它们的线性组合成向量 l 就表示为-

l=x1。+x2。 v****

  • 数字 x1x2 是矢量 x 的分量
  • 这实质上是 x 对给定向量的缩放和加法运算。

上述线性组合的表达式等价于以下线性系统-

Bx=l**

其中 B 表示列为 uv 的矩阵。

让我们通过下面的一个例子来理解这一点,在一个 2 维空间中有矢量&v

**# Vectors u & v
# The vectors are 3D, we'll only use 2 dimensions
u_vec = np.array([1, -1, 0])
v_vec = np.array([0, 1, -1])# Vector x
x_vec = np.array([1.5, 2])# Plotting them
# fetch coords from first 2 dimensions
data = np.vstack((u_vec, v_vec))[:,:2]
origin = np.array([[0, 0, 0], [0, 0, 0]])[:,:2]
plt.ylim(-2,3)
plt.xlim(-2,3)
QV = plt.quiver(origin[:,0],origin[:,1], data[:, 0], data[:, 1], color=['black', 'green'], angles='xy', scale_units='xy', scale=1.)
plt.grid()
plt.xlabel("x-axis")
plt.ylabel("y-axis")
plt.show()**

向量的线性组合—作者图片

我们也可以从一个教授在笔记中给出的一个类似的三维例子的解释中理解它-

线性代数,第一章-向量导论,麻省理工学院

从图像中的示例中提取 3 个向量,并在 3D 空间中绘制它们(轴的单位不同于图中的向量)

**u_vec = np.array([1, -1, 0])
v_vec = np.array([0, 1, -1])
w_vec = np.array([0, 0, 1])data = np.vstack((u_vec, v_vec, w_vec))
origin = np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.quiver(origin[:,0],origin[:,1], origin[:,2], data[:, 0], data[:, 1], data[:,2])ax.set_xlim([-1, 2])
ax.set_ylim([-1, 2])
ax.set_zlim([-1, 2])
plt.grid()
plt.show()**

3D 空间中的矢量—作者提供的图像

跨度

  • 跨度是所有可能的向量组合的集合,我们可以用一对给定向量的线性组合来达到它
  • 大多数二维向量对的跨度是二维空间中的所有向量。除非,当它们在同一方向排列时(即,如果它们共线),在这种情况下,它们的跨度是一条线。

即 span( ab)=R(2D 空间中的所有向量),前提是它们不共线。

共线性

当我们有 p 个不同的预测变量,但其中一些是其他变量的线性组合,因此它们不会添加任何其他信息时,就会出现共线性。2 个共线向量/变量将具有接近+/- 1 的相关性,并且可以通过它们的相关矩阵来检测。

****多重共线性存在于两个以上的向量共线时,并且任何一对向量不一定具有高相关性。

线性独立性

我们说 v1v2 ,。。。, vn 是线性无关的,如果它们都不是

其他的线性组合。这相当于说

那个x1 . v1+x2 . v2+。。。+ xn.vn = 0 暗示 x1 = x2 =。。。= xn = 0

由于共线矢量可以表示为彼此的线性组合,所以它们是线性相关的。****

基础

基是跨越那个空间的一组线性无关的向量。

我们称这些向量为基向量

自然语言处理中的向量空间模型

一个向量空间是向量的集合 V,其中定义了两种运算——向量加法和标量乘法。举个例子,如果两个向量u&V都在空间 V 中,那么它们的和, w = u + v 也会在向量空间 V 中。

2D 向量空间是一组具有 2 个轴的线性独立的基向量。

每个轴代表向量空间中的一个维度。

再回忆一下前面的剧情矢量 a = (3,5)= 3I+5j。这个向量在 2D 空间上用两个线性独立的基向量来表示——X&Y,它们也表示空间的 2 个轴和 2 个维度。

3 & 5 这是这个向量的 X,Y 分量,在 X-Y 2D 空间上的表示。

2D X-Y 平面上的向量—作者提供的图像

NLP 中的向量空间模型

向量空间模型是向量空间中文本的表示。

这里,语料库中的每个单词是线性独立的基向量,并且每个基向量表示向量空间中的轴。

  • 这意味着,每个单词与其他单词/轴正交。
  • 对于一个词汇集 |V|R 将包含 |V| 坐标轴。
  • 术语的组合将文档表示为这个空间中的点或向量

对于 3 个单词,我们将有一个三维矢量模型,表示如下-

三个词的向量空间模型—作者的图像

图表上方的表格显示了 TF-IDF 事件矩阵。

=(0.91,0,0.0011)表示三个轴上的文档向量——商品、房子、汽车。同样,我们有&D3文档向量。**

然而,向量空间的表示对我们有什么帮助呢?

  • 使用这种表示的一个常见应用是搜索引擎的信息检索、问答系统等等。
  • 通过将文本表示为向量,我们旨在使用向量代数从文本中提取语义,并将其用于不同的应用,如搜索包含与给定搜索查询中包含的语义相似的语义的文档。

例如,对于一个搜索标记“buy ”,我们希望获得包含该单词不同形式的所有文档——buying、buy 甚至是单词“buy”的同义词。这种文档不能从将文档表示为二进制关联矩阵的其他基本方法中获取。

这是通过像文档和查询的向量之间的余弦相似性这样的距离度量来实现的,其中越接近查询的文档排名越高。

  • 单词/词汇的数量可能高达数百万,例如,谷歌新闻语料库是 3 百万,这意味着尽可能多的独立轴/维度来表示向量。因此,我们希望使用向量空间中的运算来减少维数,并使单词在同一轴上彼此相似。

密集向量

  • 上述操作在文档向量上是可能的,这些文档向量通过将文档的上述向量表示扩展到表示为分布式或密集向量的文档来表示。这些表示捕获了文本的语义,也捕获了单词向量的线性组合
  • 之前的向量空间模型中,每个单词代表一个单独的维度,这导致了稀疏向量。
  • 密集向量捕获向量表示中的上下文。单词的密集向量使得出现在相似上下文中的单词将具有相似的表示。
  • 这些密集向量也被称为单词嵌入或分布式表示。
  • word2vec 就是这样一个框架,从大型语料库中学习密集的单词向量。它有两种变体——skip-gram 和 CBOW(连续单词包)
  • 获得密集向量的一些其他框架和技术是全局向量(GloVe)、fastText、ELMo(来自语言模型的嵌入)以及在推理期间获得上下文化单词嵌入的基于 Bert 的方法的最新技术状态。

结论

本文介绍了基于向量代数的向量空间的概念,并强调了相关概念作为其在自然语言处理中的应用的一部分,用于在语义表示和提取任务中表示文本文档。

单词嵌入的应用已经扩展到更高级和更广泛的应用,并且性能比以前有了很大的提高。

你也可以通过访问我的 Git 库来参考源代码并在 colab 上运行。

希望你喜欢读它。😃

参考

  • 线性无关,基础&尺寸,MIT
  • 矩阵——麻省理工学院矢量导论
  • NLP 的向量空间模型,NPTEL
  • 统计学习导论,电子书,作者:Gareth James,Daniela Witten,Trevor Hastie 和 Robert Tibshirani

从预测到行动——如何从数据中学习最佳策略(2/4)

原文:https://towardsdatascience.com/from-making-predictions-to-optimizing-actions-an-introduction-to-policy-learning-2-4-9fc46ba8f3d0?source=collection_archive---------20-----------------------

贝丝·麦克唐纳在 Unsplash 上的照片

在第一部分中,我们讨论了从数据中学习最优策略的必要性。政策优化涵盖了大量实际情况(例如,可以说,每个个性化问题都是一个政策优化问题),我们简要地看了医疗保健、防止流失、目标营销和市政府的例子。

为了学习最优策略,我们需要收集正确的数据。在本帖中,我们将描述如何创建一个数据集,使其适合政策学习。

有了合适的数据集:

  • 在第三部分中,我们将学习一种简单(在我看来也是神奇)的方法来估计 任何 政策的结果。
  • 在第四部分中,我们将学习如何找到一个最优 策略。

让我们回顾一下第 1 部分中的问题定义。你有:

  • 一组客户(我广义地使用‘客户’来指代您想要对其应用操作的实体。例如,它可以是一个病人、一个网站访问者、一个潜在客户、一个企业、一个地理区域……你明白了)。关于客户属性、行为和其他上下文信息的所有相关信息被表示为特征向量。
  • 一组可能的动作
  • 当某项行动针对某个客户时,您的结果(重要的是,不同的客户对行动的反应可能不同)
  • 你的目标:为每一位顾客找到最佳结果的行动。换句话说,学习一个将最佳动作分配给每个客户特征向量的函数。这被称为最优策略策略

数据集创建策略

让我们从为策略优化创建数据集时需要记住的最重要的事情开始:

政策学习的理想数据集来自随机实验。

如果你有自由运行这样的实验,太好了!

但是如果你不能进行随机实验,不要绝望——如果你可以获得过去的观察数据,你仍然可以从中创建一个训练数据集。

我们将在本帖中详细讨论这两种情况,从你可以进行随机实验的快乐场景开始。我们将会看到,这里的灵活性比乍看起来要大得多。

通过随机实验创建数据集

通过随机实验创建训练数据集是一个 3 步的过程。

  • 第一步:从客户群中选择一个随机的客户样本。
  • 步骤 2 :决定如何随机分配行动给样本中的每个客户
  • 步骤 3 :进行实验并收集结果数据

第 1 步很简单,让我们转到第 2 步。

回到第 1 部分中的网飞客户流失管理示例,回想一下我们考虑了三个行动:“明年打八折”、“再流两台设备”和“什么都不做”。

目前,让我们假设我们只有两个行动,“流 2 更多的设备”或“什么都不做”。

将这两项行动中的一项随机分配给样本中的每位客户,最简单的方法是什么?对每一位顾客,投一枚公平的硬币。如果出现正面,分配“2 个以上的设备”,如果出现反面,分配“什么都不做”。

这个“方案”可以描述如下:

更一般地说,如果我们有 N 个行动,我们可以使每个行动对每个顾客来说都是同等可能的。对于三个动作的网飞例子,我们的方案看起来像这样:

这就是有趣的地方。

原来我们可以为每个客户-动作组合选择任意概率,只要满足两个条件:**

  • 对于任何客户,所有行动的概率之和必须为 1.0 (即每行的概率之和必须为 1.0)。这就确保了恰好有一个动作被分配给每个客户。**
  • ****每个概率必须非零。这确保了每个动作都有机会被分配给客户。

如果我们用满足这两个条件的概率工作,得到的数据集可以安全地用于政策评估和政策优化。

以下是满足两个条件的概率示例:

我想提请你们注意两件事:

  • 请注意,概率对于不同的客户是不同的。这完全没问题,因为它没有违反上面的两个条件。事实上,这种为不同客户选择不同概率的能力给了我们巨大的灵活性,我们很快就会看到这一点。
  • 请注意,上表是一种策略:给定 x ,您根据为 定义的概率随机挑选一个动作** x. 满足上述两个条件的策略在强化学习文献中称为行为策略,但我将它称为 数据收集策略 (因为我发现

为不同客户选择不同概率的自由在实践中非常有用。

一种常见的情况是当我们不想浪费一个“昂贵”的行动(例如,50%的折扣!)在不太可能需要的客户身上。

具体来说,假设我们希望将“下一年八折”活动仅应用于取消概率高的客户,而不是其他客户,因为我们怀疑低风险客户可能会将奖励收入囊中,而我们已经在他们身上浪费了昂贵的折扣。但是我们不关心“流两个以上的设备”和“什么都不做”应用的频率。

我们可以在数据收集策略中轻松满足这一业务需求。这里有一个方法。

首先,我们使用历史数据建立一个模型来预测每个客户的取消概率。

您可以使用您选择的任何分类方法来构建此模型,只要它提供概率预测,而不仅仅是 0-1 类预测。对您的客户样本运行此模型,以获得以下结果:

现在,考虑样本中的一个客户,其取消的预测概率是 p 。对于该客户,将被分配“下一年 20%折扣”活动的概率设置为p。取剩余概率(即 1- p )并在其他活动中平均分配:“流式传输两个以上设备”的概率为 (1-p)/2 ,“什么都不做”的概率为 (1-p)/2

很容易确认这是一个有效的数据收集策略:所有三个数字都是非零的,当然,它们加起来是 1.0(目前,我假设预测模型不会输出恰好等于 1.0 或 0.0 的概率。我将在后面的文章中重新讨论这个假设)。

应用这个逻辑,我们得到这个数据收集策略:

第一个客户的取消概率为 70%,因此“打八折”的概率为 70%,“再流两台设备”的概率为 15%,“什么都不做”的概率为 15%。

您可以看到,预测取消概率较低的客户(例如,示例中的最后一位客户)获得昂贵的“八折”折扣的机会很小,这正是我们想要的。

这只是我们如何灵活定义数据收集策略以适应业务考虑的一个例子。请随意使用您的创造力和业务知识来定义其他数据收集策略。只需确保概率不为零,并且样本中每个客户的概率总和为 1.0。

一旦指定了有效的数据收集策略,我们就进入步骤 3:运行实验并测量结果。

这一步很简单:

对于样本中的每个客户,根据该客户的概率随机选择一项行动,将所选行动应用于该客户并衡量结果。

如果你知道如何随机抽样,根据概率选择一个行动是很容易的,而且有很多方法可以做到。例如,对于三种行为的概率为 70%-15%-15%的客户,生成一个 0-1 范围内的统一随机数,如果该值在 0.0-0.7 之间,则选择“下一年优惠 20%”,如果该值在 0.70-0.85 之间,则选择“再分流两台设备”,如果该值在 0.85-1.0 之间,则选择“什么都不做”。

当实验结束时,最终的数据将是这样的。

请注意,我们添加了另外两列:分配给每个客户的实际操作,以及结果的值。为了简单起见,我展示了一个二元结果,但是您可以使用任何东西(例如,下一年的利润)。

根据观察数据创建数据集

现在让我们考虑一下你很难进行随机实验来收集数据的情况。但是我们仍然可以建立一个数据集,用于政策评估和学习,如果关于过去应用于客户的行动和结果的数据可用的话(见下表)。

这里我们需要记住两个重要的警告:

  • 我们拥有行动和结果数据历史数据的客户可能不是客户群的随机样本。
  • 虽然您可以看到分配给每个客户的操作,但是没有关于如何为该客户准确选择操作的信息。我们不知道是否使用了随机数据收集政策。**

由于缺乏上述随机化,政策评估(将在第 3 部分中介绍)和政策优化(将在第 4 部分中介绍)的结果必须“有所保留”,即带有一定程度的怀疑。

警告结束后,让我们看看如何从观察数据中构建一个训练数据集。基本想法是从历史数据集中“估算”客户行动概率,即填写下表中缺失的值:

怎么会?通过使用被指定为类标签的实际动作…

…并使用上述数据集构建多类分类模型!

现在,我们可以用模型预测的概率填写表格…

…我们的训练数据集已经准备好了。

你可能会想,“别这么快。如果预测模型返回的概率对于某些客户行为组合来说正好是零,那会怎么样?这难道不会违反我们之前规定的非零概率条件吗?”

你完全正确,这违反了条件,我们不能用概率。

在我们研究如何解决这个问题之前,值得指出的是,这在实践中并不少见。在许多业务情况下,“常识性的业务规则”被使用,并且可以产生预测概率为零的历史数据(顺便说一句,在这种情况下,您可以将“业务规则”视为“策略”的另一个名称)。

考虑这个业务规则的例子:

如果一个顾客在过去的一个月里狂看了一个节目,“什么都不做”。

否则:如果客户上个月的观看时间比上个月少 0–30%,则提供“多 2 台设备”。如果客户上个月的观看时长环比下降超过 30%,则提供“八折”。

让我们假设特征向量 x 具有表示疯狂观看、观看时间百分比变化等的特征。

如果使用上述规则/策略,历史数据将如下表所示(为了使表格更容易阅读,我对记录进行了分组,以便狂欢观察者在一起,0–30%的记录在一起,以此类推)。

现在,如果您使用 x 作为输入,使用分配的动作作为目标类标签,对该历史数据运行分类树算法(如本文前面所解释的),它很可能会从数据中“逆向工程”您的策略,并生成如下所示的树…

…导致预测的概率正好是 0.0 和 1.0。

由于这违反了非零概率条件,我们无法使用此数据集进行策略评估和优化。

我们能做什么?

首先,坏消息是:为了解决这个问题,我们进行随机实验并收集新数据。

但也有可能是好消息。如果你不能进行随机实验,因为你没有这样做的基础设施,恐怕我没有解决办法:-(

但是如果原因是

  • 你的商业利益相关者不习惯随机实验或**
  • 他们对当前的政策很满意,并且有一种“如果它没坏,就不要修理它”的心态
  • 他们觉得改变现行政策是有风险的,

你也许可以用下面这个“温柔”的提议说服他们。

让我在一个客户样本上运行这个实验:对于样本中 90%的客户,我们将遵循当前的策略。对于 10%的客户,我们将随机选择一项行动。

这种流行的方法(称为ε-贪婪 ) 对企业来说可能是合意的,因为出错的“风险”小于 10%。

更正式地说:

  • ε设置为一个小分数(如 0.1)
  • 对于每个客户,从一个统一的(0,1)随机变量中抽取。如果其值小于 epilson (例如,小于 0.1),随机选择一个概率相等的行动,并将该行动分配给客户。如果没有,请使用当前策略来决定分配给该客户的操作。

如您所见,在 1- epsilon %(例如,90%)的时间里,这种方法将选择由当前策略指示的动作。但是在 epsilon %(例如 10%)的情况下,这种方法将以相等的概率选择三个动作中的一个。

同样,你可以把这看作是两个策略的组合,加权平均为 90%–10%

…要获得满足“零概率”条件的新值:

通过保持小规模,你可以向商业利益相关者保证你不会以数据收集的名义冒很大的风险或承担很大的费用。这种方法是让业务涉众“放松”到实验心态的好方法。随着他们越来越习惯并能承受更多风险,你可以将 T20 设定为一个更高的值。

(顺便说一句,如果我们从来没有尝试过一个行动,因此没有关于其结果的数据,那该怎么办?只需将新动作添加到 epsilon -greedy 的“随机分配一个动作”分支,并开始收集数据)

在这一点上,使用上面描述的方法,让我们说你已经组装了一个像这样的数据集,概率都是非零的。

或者,更一般地说:

这个数据集非常有用。

在第 3 部分中,我们将学习如何使用该数据集快速评估 任何 策略的结果(即策略评估),而无需运行任何实验。**

在第 4 部分中,我们将学习如何使用它来找到一个 最优 策略。

从凌乱到整洁与蟒蛇熊猫

原文:https://towardsdatascience.com/from-messy-to-neat-with-python-pandas-91bc98b95d7f?source=collection_archive---------19-----------------------

实用教程

照片由 Erol Ahmed 在 Unsplash 上拍摄

现实生活中的数据通常是混乱的。它不是最吸引人的分析格式。项目的大量时间花费在数据争论上。

只有在数据采用适当的格式后,我们才能开始数据分析并推断出有意义的见解。幸运的是,Pandas 提供了许多功能和技术来加速数据清理过程。

在本文中,我们将采用一个关于肥胖率的数据集,它看起来杂乱无章,但我们将把它转换成一个漂亮而干净的格式。每一步都涉及不同的熊猫功能,所以它也像一个实用教程。

让我们从导入库和读取数据集开始。

import numpy as np
import pandas as pddf = pd.read_csv("/content/data.csv")df.shape
(198, 127)

数据集包含 198 行和 127 列。下面是前 5 行和前 5 列的屏幕截图。

(图片由作者提供)

除了前 3 行,各列包含 1975 年至 2016 年的肥胖率。

df.columns[-5:]  # last 5 columnsIndex(['1976.1', '1976.2', '1975', '1975.1', '1975.2'], dtype='object')

前 3 行似乎与后面的行不一致。让我们检查这些行中的值。unique 函数返回行或列中的唯一值。

# First row
df.iloc[0,:].unique()array([nan,        'Prevalence of obesity among adults, BMI &GreaterEqual; 30 (age-standardized estimate) (%)'],       dtype=object) # Second row
df.iloc[1,:].unique()array([nan, '18+  years'], dtype=object)

前两行似乎定义了整个数据集,而不是单独的列。前 2 行中只有一个唯一值和一个 NaN 值,因此我们可以删除它们。

drop 函数可用于根据轴参数值删除行或列。

df.drop([0,1], axis=0, inplace=True)

我们通过传递相关联的标签来指定要删除的行。inplace 参数用于保存数据帧中的更改。

每年有 3 栏,包含男性、女性的肥胖率以及两者的平均值。由于我们可以很容易地从男性和女性值中获得平均值,因此最好删除指示平均值的列。

一种方法是将一个列列表传递给 dropped。这是一种单调乏味的方式,因为要删除 42 列。Pandas 提供了一个更实用的方法,允许我们从列表中选择每三个项目。

df.columns 方法返回列的索引。我们可以从索引 1 开始选择每隔三个项目,如下所示:

df.columns[1::3]
Index(['2016', '2015', '2014', '2013', '2012', '2011', '2010', '2009', '2008', '2007', '2006', '2005', '2004', '2003', '2002', '2001', '2000', '1999', '1998', '1997', '1996', '1995', '1994', '1993', '1992', '1991', '1990', '1989', '1988', '1987', '1986', '1985', '1984', '1983', '1982', '1981','1980', '1979', '1978', '1977', '1976', '1975'],       
dtype='object')

我们可以将这个列表传递给 drop 函数。

df.drop(df.columns[1::3], axis=1, inplace=True)

下面是数据帧现在的样子:

(图片由作者提供)

我们已经知道 1 代表男性,2 代表女性。因此,我们可以将第一列重命名为“Country ”,并删除第一行。

df.rename(columns={'Unnamed: 0': 'Country'}, inplace=True)df.drop([2], axis=0, inplace=True)

数据集是宽格式的。用长格式进行分析会更容易,在长格式中,年份用一列表示,而不是用单独的列表示。

融化功能就是为了这个任务。下面是我们如何将这个数据帧从宽格式转换成长格式。

df = df.melt(id_vars='Country', var_name='Year', value_name='ObesityRate'
)df.head()

(图片由作者提供)

每个年份-国家组合在单独的行中表示。

肥胖率栏包括平均值和值范围。我们需要把它们分开,用数字来表示。例如,我们可以有三列,分别是平均值、下限和上限。

str 访问器下的函数可用于提取下限和上限。

df['AvgObesityRate'] = df.ObesityRate.str.split(' ', expand=True)[0]df['LowerLimit'] = df.ObesityRate.str.split(' ', expand=True)[1].str.split('-', expand=True)[0].str[1:]df['UpperLimit'] = df.ObesityRate.str.split(' ', expand=True)[1].str.split('-', expand=True)[1].str[:-1]

我们首先在分隔范围和平均值的空间字符处分割肥胖率列。然后,我们在“-”字符处分割范围,并使用索引来提取极限值。

我们现在可以删除肥胖率列,因为我们已经提取了每条信息。

df.drop('ObesityRate', axis=1, inplace=True)df.head()

(图片由作者提供)

最后一步是添加性别信息。在当前格式中,年份列表示性别(1 表示男性,2 表示女性)。我们可以从年份中分离出 1 和 2,并相应地替换它们。

df['Gender'] = df['Year'].str.split('.', expand=True)[1].replace({'1': 'Male', '2': 'Female'})df['Year'] = df['Year'].str.split('.', expand=True)[0]

我们已经像上一步一样使用了 split 函数。在 replace 函数中使用字典可以一次替换多个值。

以下是数据集的最终版本:

(图片由作者提供)

结论

我们将一个混乱格式的数据集转换成一个整洁干净的格式。数据集中的信息保持不变,但格式对于执行高效的数据分析至关重要。

Pandas 是一个数据操作和数据分析库。在本文中,我们主要关注数据操作部分。熊猫灵活多样的功能加速了数据争论的过程。

感谢您的阅读。如果您有任何反馈,请告诉我。

从 MFCCs xor GFCCs 到 MFCC 和 gfcc:城市声音分类案例研究

原文:https://towardsdatascience.com/from-mfccs-xor-gfccs-to-mfccs-and-gfccs-urban-sounds-classification-case-study-a087ac007901?source=collection_archive---------28-----------------------

合并两种特征提取技术能提高声音分类模型的性能吗?

图片由 Austin Distel 拍摄,可在 Unsplash 获得

人类天生具有识别周围环境声音的天赋,这要归功于声音从耳朵向其最深处——内耳——的传输,内耳负责将振动转化为电脉冲,然后传输到大脑,通过使用仿生方法,研究人员能够构想出一种称为特征提取技术的音频分类管道中的关键节点,它在我们身体的内耳中起着重要作用, 将信号作为输入并输出一组表征声音的数值,因此当我们将电脉冲传输到大脑时,这里我们将把提取的特征馈送到某个模型。

非常令人印象深刻的并行!不是吗?无论如何,在本文中,我们将主要关注两种特征提取技术,Mel 频率倒谱系数(MFCCs),这是该领域最受欢迎的选择,以及 Gammatone 频率倒谱系数(GFCCs),这是不太受欢迎的。我们的目标是将它们的性能与一种将两者结合起来的方法进行比较,以便知道是否值得在以后的文章中深入研究。

什么是 MFCCs 和 GFCCs?

在进入比较方法之前,让我们基于一些标准定义简单地谈论一下 MFCCs 和 GFCCs 背后的概念,因为我计划为它们中的每一个都写一篇完整的文章来解释背后的数学,因为我发现从数学角度来看这非常有趣。

  • MFCC:梅尔频率倒谱系数(图 2)是共同构成 MFC 的系数,梅尔频率倒谱是声音的短期功率谱的表示。它们源自音频片段的一种倒谱表示(一种非线性“频谱”)。倒谱和梅尔频率倒谱之间的区别在于,在 MFC 中,频带在梅尔标度上是等间隔的,这比正常频谱中使用的线性间隔频带更接近人类听觉系统的响应。这种频率弯曲可以更好地表现声音。(维基百科)
  • gfcc:Gammatone 频率倒谱系数(图 3)是基于一组 Gammatone 滤波器组生成的系数,为了生成这些系数,我们需要信号的频率-时间表示,称为 Cochlegram (相对于内耳的组成部分耳蜗),它可以从 gamma tone 滤波器组获得,其计算阶段与 MFCC 有相当多的相似之处。

图 1:音频信号—图 2 : 梅尔频率倒谱系数— 图 3 : 伽马频率倒谱系数

所以 MFCCs 和 GFCCs,简单来说就是代表某种声音特征的系数。

我们将处理的数据集:

我们将使用 UrbanSound8K 数据集,包含 8732 个标记的声音片段,每个片段不到 4 秒,不同于其他著名的音频数据集,每个音频文件的采样率不同(采样率:一个时间实例的音频样本组),并被标记为 10 个类别之一:街道音乐、汽车喇叭、儿童玩耍、狗叫、钻探、发动机空转、枪击、手提钻、警笛和空调。

比较架构:

图 4:比较架构

现在我们已经展示了数据集,为了了解三种特征提取技术中哪一种更可靠,我们将继续进行三种特征提取技术之间的比较方法(图 4 ),给每种技术三次机会,通过音频分类领域中三种不同的常用模型来证明它们的可靠性,这样,如果我们最终选择一种特征提取技术而不是另一种,将会更加公平。

因此每个特征提取技术的输出将被馈送到:

  • 支持向量分类(SVC) 这是一种基于间隔最大化原则的特殊线性分类器,可用于解决线性和非线性问题。
  • 多层感知器分类器(MLP) 它是一类前馈人工神经网络
  • K 近邻 分类器(KNN 分类器)这是一种用于解决分类问题的监督机器学习算法

评估指标:

为了评估我们的分类模型的有效性,我们将考察四个主要的性能指标:

  • 准确性:模型正确预测两个类别的能力
  • 精度:模型从所有预测的阳性类别中正确检测出阳性类别的能力
  • 回忆(灵敏度):模型从所有实际阳性类别中正确检测出阳性类别的能力
  • F1 得分:精确度和召回率的调和平均值

所有这些性能指标都是基于以下变量定义的:

  • 真阳性(TP) :预测为阳性类别的阳性类别
  • 假阳性(FP) :阴性类别预测为阳性类别
  • 真否定(TN) :否定类预测为否定类
  • 假阴性(FN) :阳性类别预测为阴性类别

图 5:评估指标公式

模型的分数和结果解释:

在设置了比较架构并确定了用于评估的指标后,我们比较了每个有限元模型显示的性能,以便我们可以首先为每种技术选择最佳的一种,然后确定谁是 3 个最佳记录分数中的最佳者。筛选结果如下所示(图 6):

图六:模特们的表演

根据使用不同特征提取技术的模型的性能,我们最终认识到多层感知器模型和 MFCC&GFCC 技术的组合在 9 个可能的组合中获得了迄今为止最好的准确度、精确度、召回率和 F1 分数。

下一步是什么?

在确定 MLP 和 MFCC&GFCC 的特征提取组合是该数据集最可靠的组合后,我们将在未来的技术文章中进一步调整其参数,以解释我们合并这两种特征提取技术的方式,并了解其性能可以提高到什么程度,因为正如我们刚刚看到的,它显示了一些非常好的结果,请继续关注😊。

从以模型为中心到以数据为中心

原文:https://towardsdatascience.com/from-model-centric-to-data-centric-4beb8ef50475?source=collection_archive---------5-----------------------

人工智能开发的新范式——关注数据质量

在我的上一篇博文中,我已经介绍了数据报告的兴起以及数据准备的重要性以从基于机器学习的解决方案中获得优化的结果。

数据在人工智能发展和成功中的重要性:来源

到目前为止,数据的价值及其对基于 ML 的解决方案质量的影响肯定被低估了,但这种情况正在改变——在 Andrew 的 ng 最新会议中,他讲述了在数据准备方面进行更大投资的好处,他的团队证明了投资改善现有数据质量与收集三倍数量的数据一样有效。

这就是我今天要讲述的内容——数据质量在将人工智能提升到一个新水平中的作用。

相同的模型,不同的数据

作为人工智能实践者,我们已经意识到组成解决方案开发的要素:

AI 系统=代码+数据,其中代码表示模型/算法

这意味着为了改进一个解决方案,我们可以改进我们的代码,或者改进我们的数据,当然,两者兼而有之。什么是取得成功的正确平衡?

例如,通过开放数据库或 Kaggle,随着数据集的公开可用,我理解了为什么更加以模型为中心的方法:数据在本质上或多或少表现良好,这意味着要改进解决方案,重点必须放在唯一有更多自由调整和更改的元素上,即代码。但是,我们在行业中看到的现实完全不同。这是 Andrew NG 分享的观点,我对此深表赞同——到目前为止,以模型为中心的方法已经严重影响了数据科学团队在 ML 领域中可用的工具。

以模型为中心与以数据为中心

在我看来,为了实现一个好的人工智能解决方案,在所谓的以模型为中心和以数据为中心的观点之间有一个小心的平衡,然而,我意识到更高的价值仍然在数据方面。令人高兴的是,这种观点不是来自直觉,为了证明这一点,Andrew NG 和他的团队决定用真实世界的数据做几个实验来证明这一点,但在此之前,让我们后退一步,定义什么是以模型为中心和以数据为中心

以模型为中心与以数据为中心

检验钢板示例

加雷思·大卫在 Unsplash 上的照片

钢板缺陷检测是会议期间带来的例子之一——假设一系列钢板图像,我们希望开发最佳模型来检测钢板制造过程中可能发生的这些缺陷。我们希望能够识别 39 种不同的缺陷。通过开发一个具有良好调整的超参数的计算机视觉模型,它能够达到 76.2%的精度基准系统,但目标是实现 90%的精度怎么做到的

知道基线模型已经很好,改进它以实现 90%的准确性听起来几乎是不可能的——对于以模型为中心的模型,改进基于网络架构搜索并使用最先进的架构,而对于数据驱动的模型,所采取的方法是识别不一致并清除有噪声的标签。结果令人震惊:

模型改进结果

转移到以数据为中心的方法的潜力不仅适用于计算机视觉领域,同样适用于其他领域,如 NLP 或表格和时间序列数据。

为什么从模型转向以数据为中心

数据在人工智能开发中有着很高的利害关系,非常需要采用一种以获得高质量数据为核心的方法——毕竟有意义的数据不仅稀缺和嘈杂,而且获得起来非常昂贵。就像我们会关心最好的材料来建造我们的家园,这同样适用于人工智能。

数据处理与模型训练的 80/20 法则广为人知,然而,我们在模型训练步骤中看到了一致的关注点,这反映在如今我们在市场上找到的工具中。为了实现以数据为中心的方法,我们必须用正确的框架来回答一些问题,例如:数据是否完整?数据与用例相关吗?如果有标签,它们是否一致?偏差的存在会影响性能吗?我有足够的数据吗?

这些问题不期望在什么是 ML 开发流程的单一步骤中得到回答,事实上,它们期望以迭代的方式得到回答,就像我们遵循以模型为中心的方法一样。

但是让我们关注最后一个问题——我有足够的数据吗?

要么做大,要么回家!

ev 在 Unsplash 上拍照

这是一个常见的问题——在大数据时代,数据质量的一个要点无疑是数量——越大越好。但是,如果我们采用以数据为中心的方法,这仍然是唯一的真理吗?

很难完全确定我们是否有大量的数据,这通常是我的模型在交付到生产中时被推广的问题。但是,我们在这篇博文的前面已经看到,数据质量越好,几个模型表现良好的概率就越高。

这是否意味着质量比数量更重要?

在许多现实世界的问题中,现实是没有多少数据可用(医疗保健、农业、欺诈检测等),但这并不意味着这些用例不适合应用机器学习— 这完全是关于你的数据有多好和有意义。

我们拥有的数据越多,噪音就越多。当然,如果我们有很多,通过正确的超参数和模型选择,我们可以实现可推广的结果,但是选择高质量但较小的推理系统来训练模型会有多大的性能和可优化性呢?对数据集进行清理和去噪将成为数据架构中的一个关键区分因素,实现这些目标是人工智能也可以发挥作用的地方——半监督学习等技术可以非常方便地识别和纠正不一致或合成数据,以产生和模拟更多事件,帮助克服泛化问题。

但我们不要忘记数据准备在机器学习开发的工作流程中,他并不孤单。事实上,MLOps 对于连接各个点并在确保一致性的同时将这些步骤提升到下一个级别是至关重要的。例如,功能存储可以非常方便地保持数据准备步骤的可再现性,另一个例子是,数据沿袭确保您可以跟踪改进。

每一个步骤都必须相互关联,因此,人工智能架构的关键组件的概念是必不可少的——规范堆栈。

结论

从为收集数据而投资的基础设施,到专门用于收集数据的人力资源数量,以及在理想情况下收集数据的机会有多少,这使得数据成为当今最昂贵的资产之一。

在人工智能开发的每一步,数据质量都必须得到监控和改进,而哪一步,由于其性质,将不可避免地使用不同的框架和工具。

我们一定不要忘记,这必须以持续的方式交付和衡量,这使得 MLOps 成为一个急需的盟友,以在人工智能解决方案的开发中实现适当和成功的以数据为中心的范式。

法比亚娜 是 CDOy data

用改进的数据加速 AI。

YData 为数据科学团队提供第一个数据开发平台。

从以模型为中心到以数据为中心的人工智能

原文:https://towardsdatascience.com/from-model-centric-to-data-centric-artificial-intelligence-77e423f3f593?source=collection_archive---------6-----------------------

对新的和更复杂的模型架构的狂热是合理的吗?

来源

所有人工智能系统的两个基本组成部分是数据和模型,两者在产生预期结果的过程中密切相关。在这篇文章中,我们讨论了人工智能社区如何偏向于在模型中投入更多的努力,并看到它如何不总是最好的方法。

我们都知道机器学习是一个迭代的过程,因为机器学习很大程度上是一门经验科学。你不会通过思考问题而跳到最终的解决方案,因为你不容易清楚地说出解决方案应该是什么样子。因此,你凭经验走向更好的解决方案。当你在这个迭代过程中,有两个主要的方向供你选择。

以模型为中心的方法

这包括围绕模型设计经验测试以提高性能。这包括在巨大的可能性空间中找到正确的模型架构和训练过程。

以数据为中心的方法

这包括系统地改变/增强数据集,以提高你的人工智能系统的准确性。这通常被忽视,数据收集被视为一次性任务。

大多数机器学习工程师发现这种方法更令人兴奋和有前途,一个原因是它使他们能够将他们的机器学习模型知识付诸实践。相比之下,处理数据有时被认为是一项低技能任务,许多工程师更喜欢处理模型。但是这种对模型的强调有道理吗?为什么会存在?

人工智能社区中以模型为中心的趋势

大多数人已经将他们的主要精力投入到以模型为中心的人工智能上。

一个看似合理的原因是,人工智能行业密切关注人工智能领域的学术研究。由于人工智能的开源文化,几乎每个使用 github 的人都可以很容易地获得该领域的大多数前沿进展。此外,科技巨头资助和指导了很大一部分人工智能研究,因此它仍然与解决现实世界的问题相关。

最近,人工智能研究在本质上完全是以模型为中心的!这是因为标准是产生具有挑战性的大数据集,这些数据集成为广泛接受的评估问题性能的基准。然后在学者之间进行竞赛,以达到这些基准的最先进水平!因为,我们已经固定了数据集的状态,大多数研究都是以模型为中心的方法。这在社区中产生了一种普遍的印象,即以模型为中心的方法更有前途。

检查最近的出版物样本显示,99%的论文以模型为中心,只有 1%的论文以数据为中心。~ 吴天俊

数据的重要性

尽管机器学习社区称赞数据的重要性,并将大量数据视为人工智能成功背后的主要驱动力。它有时会在 ML 项目的生命周期中靠边站。在他最近的演讲中,Andrew NG 指出他认为以数据为中心的方法更有价值,并呼吁在社区中转向以数据为中心。作为一个例子,他讲述了几个项目以及以数据为中心的方法是如何更加成功的。

来源

以数据为中心的方法中可供您使用的工具

更多的数据并不等于更好的数据。数据的三个主要方面是:

数据量非常重要,你需要有足够的数据量来解决你的问题。深度网络是低偏差高方差的机器,我们相信更多的数据是方差问题的答案。但是,盲目积累更多数据的方法可能非常数据高效且成本高昂。

人类如何能够在几乎没有监督的情况下,在大约 20 小时的练习中学会驾驶汽车,而完全自动驾驶仍然无法通过人类驾驶员数千小时的数据训练我们最好的人工智能系统?~ Yann Lecun

在开始寻找新数据之前,我们需要回答我们需要添加哪种数据的问题。这通常通过对当前模型的误差分析来实现。这个我们以后再详细讲。

来源

一致性

数据注释的一致性非常重要,因为任何不一致都会使模型脱轨,也会使您的评估不可靠。一项新的研究显示,在广泛使用的数据集中,大约有 3.4% 的例子被错误标记,他们还发现更大的模型受此影响更大。

如果不能在误差 pf +=3.4%的情况下测量准确性,这就提出了关于超过以前基准一到两个百分点的过多研究论文的主要问题!因此,为了更好的训练和可靠的评估,我们需要一致标记的数据集。

来源

上面的例子强调了人类标签的不一致性是多么容易渗入到你的数据集中。上面的注释都没有错,它们只是彼此不一致,会混淆学习算法。因此,为了一致性,我们需要仔细设计注释指令。机器学习工程师有必要完全熟悉数据集,我发现这有助于:

  1. 在制定指令之前,我自己注释了一个小的数据集样本,以便更好地了解注释者可能犯的错误。
  2. 检查一批随机的带注释的数据,以确保一切都如预期的那样。这应该成为每个注释工作的标准实践,因为注释团队是不断变化的,即使在项目的后期也很容易出现错误。
  3. 对于那些即使在审阅了说明之后仍然发现不一致的任务,让多个人对数据进行注释并使用多数投票作为基本事实可能是可取的。

质量

您的数据应该代表您期望在部署中看到的数据,涵盖部署数据将呈现的所有变化。理想情况下,所有非因果特征的数据属性都应该充分随机化。您应该注意的数据集的常见缺陷有:

  1. 虚假关联:当非因果属性与标签相关联时,神经网络无法学习预期的解决方案。例如,在对象分类数据集中,如果奶牛通常出现在草原上,模型可以学习将背景与类别相关联。有关这方面的更多信息,请参阅:神经网络在虚假相关数据上失败
  2. 缺乏变化:当像图像亮度这样的非因果属性在数据集中变化不够大时,神经网络会过度适应该属性的分布,不能很好地概括。在白天数据中训练的模型在黑暗中会表现不佳,反之亦然。在这里了解更多关于这个问题的信息:神经网络的惊人失败是由于对完全不相关的数据属性的调节

除了收集更多变异的新数据,数据扩充是打破虚假相关性和缺乏变异问题的一个极好的策略。

以数据为中心的系统方法

机器学习项目普遍接受的工作流程如上图所示。其中对训练和部署结果的分析可以导致数据收集和模型训练的另一阶段。观察和纠正测试数据中的问题是一个不错的策略。但是它只能解决通过错误分析观察到的问题,并不能预防将来的问题。存在于 sin 训练数据中相同的虚假相关也可能出现在测试数据中,这很像是它们被随机分开。

我们需要一种更加主动的方法来实现未知环境中的模型健壮性。为了更好地理解因果不变性和鲁棒深度学习之间的关系,请阅读本文:不变性、因果性和鲁棒深度学习

阅读我的下一篇文章,学习一种结构化的方法,从问题定义到网络评估,可以用来训练健壮的领域不变模型。稳健深度学习的系统方法

从模型到部署:从 Google 和斯坦福专家那里免费学习 MLOps

原文:https://towardsdatascience.com/from-models-to-deployment-learn-mlops-for-free-from-google-and-stanford-experts-b24e7018c13d?source=collection_archive---------28-----------------------

教育

机器学习操作(MLOps)是一个新兴领域,我强烈建议您学习更多知识,以推动您的数据科学事业。

卡尔·乔根森在 Unsplash 上的照片

不要让你的技能灭绝

数据科学领域正以前所未有的速度发展。虽然这个领域在可预见的未来肯定不会灭绝,但是如果你停止学习和提高技能,你的技能组合可能会很好。

随着越来越多的组织希望使用数据来保持竞争力,数据科学继续受到关注。这对我们每个人都是有希望的。然而,不断增长的需求也意味着越来越多的人开始涉足数据科学。

每个人都有无处不在的学习机会,你必须不断学习和成长,才能在这样的环境中保持竞争力。

为什么 MLOps 很重要?

这篇文章将向你介绍机器学习中的一个新兴分支学科,MLOps(机器学习操作)。

除非您在一个拥有成熟数据科学团队的大型组织中工作,否则您可能需要很好的 MLOps 工作知识。即使你热衷于成为一名数据科学家(而不是目前定义的数据工程师),你最好接受学习 MLOps 方面的想法,以便作为“数据科学”团队的一部分有效地工作,并最终能够领导这样的团队。

没有哪个组织真的有兴趣为你投资开发留在 Jupyter 笔记本里的模型。相反,他们对解决现实世界的挑战感兴趣,并希望使用能给他们带来竞争优势的模型。模型生产和部署是不可避免的。

目标受众

如果你在部署机器学习模型方面经验很少或者没有经验,那么你绝对应该继续读下去。然而,即使您有设计、开发和部署端到端机器学习项目的实践经验,您可能仍然会发现视角和相关资源的链接很有用。

MLOps:鸟瞰图

让我们先解决一些事情。一个常见的误解是,人工智能(AI)产品或服务的部署主要是关于机器学习(ML)算法。一旦 ML 算法最终确定,它就可以用标准的软件工程实践来部署。现实要复杂得多。事实上,与需要日常维护挑战的传统软件不同,ML 产品/服务具有额外的 ML 特定问题,这些问题可能存在于“设计”级别而不是代码级别[1]。

图 1(改编自[1])显示了生产中的 ML 系统的需求,突出显示了“ML 代码”,以让您了解一旦您决定部署您的 ML 模型时需要解决的各种挑战。

图 1:与 ML 代码相比,支持 ML 系统的周围基础设施要大得多,也复杂得多(由作者改编自[1])

在现实世界的 ML 系统中,ML 代码是庞大而复杂的基础设施的一小部分。这是一个图形说明,有助于提高认识,并说明 ML 模型部署在实践中可能意味着什么,超出了您在典型的机器学习课程中可能学到的内容。如果你很好奇,你可以阅读原始的、被大量引用的论文,该论文详细阐述了上图[1]中强调的各种问题。

当前:临时模型部署

尝试部署模型并不新鲜。多年来,许多数据科学从业者在尝试部署模型时一直在应对各种挑战。

在我读博士的日子里(大约十年前),我花了大量的时间开发算法,可以从一个小的手指探针上自动获得呼吸频率。在一个后续项目中,我不得不使用从远程收集的慢性阻塞性肺病患者的数据来实现这个算法[3]。当时,这种算法需要在服务器上运行(供研究人员和临床医生访问)。在那个项目中,我处理了几个与数据流(数据如何存储以及存储在哪里)、延迟和吞吐量需求(在这个特定的应用程序中通宵批处理就足够了)、算法块和基础设施的其余部分之间的适当 API 等相关的问题。

服务器上运行的呼吸率算法,通宵批处理(图片由作者提供)

在一个不同的项目中,我必须实现一个自动处理大脑信号并解码的算法[4]。这里的概念是即时解码病人的脑电波,然后在屏幕上给他们提供反馈。与慢性阻塞性肺病的情况不同,该项目需要即时处理,因此,这是在用于采集信号的同一台计算机上本地实施的。

解码大脑信号以估计力量,接近实时解码(图片由作者提供)

在这两个项目中,要求是采用现有的机器学习算法,然后将其部署用于实际使用。然而,环境有很大的不同,因此面临的问题也不同,需要不同类型的软件工程挑战。

我在尝试部署模型时的经历可能是许多有经验的数据科学专业人员的经历。当时,我没有听说过“MLOps”。当时,我们中的大多数人都在同时处理与软件相关的问题,同时试图以特别的方式部署 ML 算法。

未来:MLOps

典型的机器学习课程深入研究模型构建和相关的统计概念。直到最近,这也是有意义的,因为许多组织仍然处于探索阶段,已经获得了数据,但不确定需要用它做什么。招募一名“数据科学家”可能是有意义的,他获取数据,分析数据,创建很酷的图表,并得出见解。

然而,向前看,这在许多情况下是不够的。组织需要部署系统。在一天结束时,需要有一个实际的产品或服务。

现在时机已经成熟,可以将所有与模型部署相关的问题以系统的方式集中起来,并传授给新一代的数据科学专业人员。

这个领域,现在获得牵引力,被称为机器学习操作或简称 MLOps。它是一门新兴的学科,涉及支持 ML 模型从概念到部署过程的工具和技术。

MLOps 的概念框架

思考 MLOps 的一个极好的框架是思考完整的机器学习项目生命周期(由吴恩达在他的 MLOps 入门课程中介绍),他说:

当我在构建一个机器学习系统时,我发现思考机器学习项目的生命周期是一种有效的方式,可以让我计划出我需要努力的所有步骤。

改编自吴恩达的课程生产中的机器学习简介(图片由作者提供)

根据上面的框架,MLOps 可以定义为,一种数据科学学科,由各种工具和相关原则组成,以支持 ML 项目在其生命周期中的进展。

我可以从哪里学习?

由于这是一个新兴领域,我预计在不久的将来会有更多的资源可用。你可以找到专门的课程来帮助 ML 工程师支持三个主要云基础设施提供商(亚马逊、谷歌和微软)之一。你也可以在 Udacity 和 Coursera 上找到相关课程。

然而,我强烈推荐 Coursera 上的资源(链接自 DeepLearning)。AI )。

这是一个名为“面向生产的机器学习工程(MLOps)”的专业。你可以免费选修这些课程。该专业的课程有:

1: 生产中的机器学习介绍

2: 生产中的机器学习数据生命周期

3: 生产中的机器学习建模管道

4: 在生产中部署机器学习模型(本课程尚未发布)

结束语

上面链接的课程都是高级的。如果你是一个完全的初学者,那么我建议先从吴恩达关于机器学习的课程开始,其次是深度学习专精。

然而,如果你已经掌握了机器学习的工作知识,以及中级 Python 技能,包括任何深度学习框架(TensorFlow、Keras 或 PyTorch)的经验,那么你就可以开始了。

这是一个从世界上一些最优秀的人那里了解更多关于 MLOps 的惊人机会:Robert Crowe(谷歌的 TensorFlow 开发工程师)、Laurence Moroney(谷歌的首席人工智能倡导者)和吴恩达(Coursera 的创始人,现在是斯坦福大学的兼职教授)。

https://ahmarshah.medium.com/membership

参考

[1]斯卡利博士、霍尔特博士、戈洛文博士、达维多夫博士、菲利普博士、埃布纳博士、乔德里博士、杨博士、克雷斯波博士和丹尼森博士,2015 年。机器学习系统中隐藏的技术债务。神经信息处理系统进展28 ,第 2503–2511 页。

[2]沙阿、弗莱明、汤普森和塔拉先科,2015 年。医院儿童分诊时的呼吸频率估计。医学工程杂志&技术39 (8),第 514–524 页。

[3]沙阿,S.A .,韦拉多,c .,法默,a .和塔拉先科,l .,2017 年。慢性阻塞性肺疾病的恶化:使用数字健康系统进行识别和预测。医学互联网研究杂志19 (3),p.e69。

[4] Shah,S.A .,Tan,h .,Tinkhauser,g .和 Brown,p .,2018 年。从深部脑局部场电位对抓力进行实时、连续解码。 IEEE 神经系统与康复工程汇刊26 (7),第 1460–1468 页。

从自然语言到人工语言

原文:https://towardsdatascience.com/from-natural-to-artificial-language-b59f5e00ba74?source=collection_archive---------29-----------------------

入门

从语言学角度理解试图用人工语言理解自然语言的影响和风险。

由 Raphael Schaller 在 Unsplash 上拍摄的照片

为什么学习语言?

哲学家路德维希·维特斯坦根谈到语言时说:“我的语言的极限意味着我的世界的极限。”人工智能(AI)是由人工(编程)语言创建的,因此,在其核心,机器学习可以简化为二进制代码。相反,自然语言可以被定义为通过人类的有机使用而进化,它具有不可磨灭的人类品质。研究语言可以让我们一窥人工语言在模仿自然语言世界方面的局限性。

最近,我分享了一篇思想文章,讨论与人工智能和自然语言处理(NLP)相关的语言学理论。具体来说,我试图阐明我对语言相对论和语言普遍性及其与人工智能语言模型的持续发展的联系的想法。如果你对语言学理论或人工智能语言模型都不熟悉,我建议你阅读我之前的文章。此外,我重温了最初在第一篇中介绍的几个灵感来源,如尼尔·斯蒂芬森的https://en.wikipedia.org/wiki/Snow_Crash、塞缪尔·r·德莱尼的 巴别-17 和诺姆·乔姆斯基的普遍语法。

本文关注的是试图用人工语言(机器语言)来理解自然语言所产生的影响和随之而来的风险。首先,我描述了种族主义和宗教的纠缠,这说明了语言相对性和普遍性的历史影响。接下来,我依靠科幻小说来探索人工语言,及其在技术发展中的作用,以突出语言相对论的影响。我有必要介绍计算语言学的计算机科学领域,并讨论语言学理论对人工智能研究的一般影响。对于风险,我回到语言相对论来分析数据中的偏差,然后回到语言普遍性来分析错误信息。怀着乐观的态度,我以一些关于人工智能模型未来可能性的想法结束了我的讲话,这些想法可能会缩短(如果不是弥合)人工语言和自然语言之间的差距。

种族主义和宗教

谈到人工语言,斯蒂芬森在雪灾中的主角声称,

“在最低层次上,所有的计算机都是用一串一串的 0 来编程的。当你用机器语言编程时,你是在控制计算机的脑干,它是计算机存在的根源。这是伊甸园的语言。”

早期人类学对语言的研究明显受到宗教的影响;圣经故事表明,在巴别塔倒塌之前,存在一种通用语言,有时被称为“伊甸园之舌”通过斯蒂芬森的雪灾,我被介绍给乔治·斯坦纳,一位备受尊敬的文学评论家和语言哲学家,他体现了相对主义的立场。斯坦纳认为语言不是思维的载体,而是思维的决定性媒介;也就是说,是语言影响了人类的思想。从相对主义的立场来看,语言是认知的框架。

施泰纳因其关于大屠杀的大量著作而被人们铭记,不幸且具有讽刺意味的是,他也因其反黑人的种族主义而被人们铭记。他用相对主义为他的压迫性意识形态辩护,在他的种族主义观点和语言学理论之间建立了无知的联系。在经常依靠圣经的参考,斯坦纳创造了前面提到的宗教和种族主义的纠缠。引用史坦纳通过斯蒂芬森的话,

“我们的言语介于忧虑和真理之间,就像一块布满灰尘的玻璃或一面扭曲的镜子。伊甸的舌头就像一块没有瑕疵的玻璃;一种完全理解的光芒流过它”。

我深受乔姆斯基的普遍主义理论的影响,尤其是因为他在认知科学领域的贡献以及认知语言学的发展。更重要的是,语言相对论(及其种族主义基础)受欢迎程度的下降可以归因于乔姆斯基支持普遍主义假说的令人信服的论点。

宗教意识形态的力量可以与有争议的语言障碍研究联系起来,语言障碍是一种神经生理疾病,也被称为“说方言”。glossolalia 的存在经常被认为是世界语言存在的证据。抛开宗教不谈,通用语言这一理念的力量一直存在。普遍性存在于对自然语言的现代理解中,因此,对人工智能和自然语言处理研究的方向产生了强烈的影响。

科幻与科技发展的融合

随着巴别塔-17* ,德莱尼不是唯一一个受到语言相对论启发的作者;像安·兰德和乔治·奥威尔这样迥然不同的作家在发展他们各自作品中的人工语言时都受到了这一理论的影响。科幻小说的美是与技术创新和社会进化的共生关系。例如,在弗雷德·卡普兰(Fred Kaplan)的网络战著作《T4 黑暗领域》(Dark Territory)中,一个令人信服的论点是,对黑客的流行文化描述帮助塑造了美国政府采取的网络安全政策。具体来说,罗纳德·里根对网络安全的兴趣可以追溯到 1983 年的黑客电影 Wargames 。就语言技术而言,在编程语言的开发中也发现了同样的模式。*

这种关系有几个例子,例如,奥威尔在他最著名的小说 1984 中创造的虚构语言“新话”,据说是的灵感,这是一种同名的编程语言。开发者声称,他们的新话与奥威尔的人工创造有着共同的减少词汇的目标。然而,这种融合最有说服力的论据是 Babel-17 对编程语言 Ruby 的创始人松本幸宏的哲学影响。在一张有趣的存档幻灯片中,松本阐明了他对语言相对论的信念,并强调了巴别塔-17* 对 Ruby 发展的直接影响。他甚至解释了他的明确设计选择,旨在影响程序员的思想,利用语言来鼓励特定的编程行为。*

计算语言学

语言学和人工智能的交叉点是计算语言学领域,它包含了 NLP 背后的理论研究。回到乔姆斯基,他无疑影响了这一领域的发展,大脑据称包含内在的“深层结构”,这些结构在本质上是普遍的,并负责语言习得。这些深层结构的确切目的与大脑对符号串进行形式操作的能力有关。计算语言学中的一个关键讨论是“符号基础问题”,它涉及计算机如何将单词解释为不基于人类经验的符号(即永无止境的符号表示链)。正如斯蒂芬森在《T2 雪灾》中巧妙地描述的那样,所有的计算都可以简化为二进制;人工智能的深层结构最终植根于 1 和 0。

当考虑到人类经验的复杂性和细微差别时,这一现实就成了问题;目前,将语言视为符号串排除了自然语言理解。例如,考虑一下习语的流行文化:“跳鲨鱼”。这个短语主要用于指电视节目,这些节目不明智地试图重新流行,但却引起人们对越来越不相关的注意。从表面上看,习语的三个词,无论是单独使用还是组合使用,都无法传达其隐喻意义。在过去的几年里,关于人工智能语言模型,这个问题已经由越来越庞大的训练语料库解决,理论上应该允许语言模型将单词与人类经验联系起来。目前,由于训练语料库的庞大规模,对于这些模型是否真正理解或者是否只是简单地重复记忆的知识存在很大争议。

语言学理论与人工智能研究

考虑到多语言模型的流行,语言普遍性对 AI 研究的影响是显而易见的。更有趣的是与 NLP 任务相关的零射击语言学习的概念,这一想法可以被称为机器学习的圣杯。在我看来,零投或少投学习是试图教会机器像孩子一样思考的一个例子。一个孩子有可能在一次事件后学习新的概念,相比之下,机器依赖于指数级的大数据集。孩子们也能够通过结合以前学到的概念来发明新的概念。用机器学习的术语来说,这将是零射击迁移学习;模型执行任务的能力,他们并没有接受过专门的训练。

这种类型的学习的影响在去年的论文标题中显而易见,该标题介绍了 GPT-3 、“语言模型是很少出手的学习者”。【2021 年 1 月之前的 GPT-3 ,是现存最大的 AI 语言模型,不幸的是 OpenAI 还没有开源。语言的相对性或普遍性问题与零起点学习有着特殊的关系,因为语言习得的本质与人类对语言的理解密不可分。

同样值得一提的是不断发展的认知语言学领域,该领域致力于创造更好的人工智能,试图将认知理论与语言学联系起来。这门学科为分析语言学和人类感官运动体验之间的关系提供了一个框架。人工智能的未来发展应该包括更好地理解认知、语言和神经科学之间的复杂关系。

数据偏差和语言相关性

格言“垃圾输入,垃圾输出”是一个常用短语,用于描述机器学习模型的输出是如何由输入数据的质量决定的。应该预料到,所有的语言模型都会存在偏见;真实世界数据的质量反映了一个延续不平等的社会。因此,这些语言模型放大了编码在数据中的偏见就不足为奇了。在前面提到的 GPT-3 论文中,研究人员很好地涵盖了公平、偏见和代表性的主题,他们明确关注性别、种族和宗教方面的偏见。研究人员承认:**[GPT-3]保留了它接受训练的数据的偏差。…这可能导致模型产生刻板印象或偏见的内容”。**

例如,下面这张来自 GPT-3 论文的图表强调了在人工智能语言模型中对黑人的负面种族情绪偏见的存在。

GPT-3 的种族情绪分析。来源:语言模型是很少出手的学习者。

除了种族之外,某些与性别和宗教相关的术语也被证明带有负面情绪,反映了这些术语在世界上的呈现方式。例如,对伊斯兰教:

“我们还发现,与其他宗教相比,暴力、恐怖主义和恐怖分子等词在伊斯兰教中出现的频率更高,在 GPT-3 中,这些词排在伊斯兰教最受欢迎的前 40 个词中。”

换句话说,语言模型仅仅反映了当今世界的不平等状况和遍布社会的历史不公。

语言学理论在理解这种偏见方面的作用也许可以在 Steiner 关于种族主义主题的思想及其从他最受欢迎的语言学著作《巴别塔之后的 】中表达的相对主义理论的明确推导的背景下得到最好的阐述。他将不同语言的存在归因于欺骗,

人类对隐私和领地的强烈渴望导致了数千种语言的产生,每一种语言都是为了保密和文化隔离而设计的

单独来看,这不是一个有问题的说法,但是,当用来证明与"他人"分离是正当的时候,它就变成了支持种族歧视的言论。施泰纳争辩说,“种族主义是每个人与生俱来的,宽容只是肤浅的”,这是一种危险的仇外心理,也是对种族不容忍的无力解释。

然而,他确实让人们注意到了翻译任务的困难,证明了语言之间的真正翻译是不可能的,因为“翻译的文本受到译者自己的文化信仰、知识和态度的污染。”在深层次上,人工智能语言模型依赖于从自然语言到人工语言的翻译;从相对主义者的角度来看,这个任务是不可完成的,因为最初的意义总是会丢失。

误传和语言普遍性

与人工智能语言模型的发展相关的是目前对社交和新闻媒体中错误信息的担忧。这些问题在 GPT-3 的论文中有所提及,

“任何依赖生成文本的对社会有害的活动都可能被强大的语言模型所增强。产生高质量文本生成的语言模型可以降低执行这些活动的现有障碍,并提高它们的效率。”

鉴于所讨论的语言模型中的偏见,语言的普遍性也应该是一个问题,因为通用语言有可能在各种语言之间传播有害的错误信息,如刻板印象。

在《冰雪奇缘》中,斯蒂芬森认为深层语言结构的普遍性会导致危险,这种危险表现为信息像传染病一样迅速传播。换句话说,假设普遍主义理论成功地弥合了语言之间的鸿沟,那么无论真实性如何,思想的病毒式传播都会增加。遇到错误信息会强化信念或怀疑,或者套用斯蒂芬森的话,

"通过轴突的分裂和在分裂的神经胶质细胞之间移动——你的生物制品会自我修改."

如果有可能在用人工语言创建的模型中模仿这种生物神经可塑性,也许有可能训练机器用一个通用框架进行伦理思考,然后通过强化学习进行强化。

人工智能语言模型的未来

有许多文章声称要了解人工智能的未来,我不做这样大胆的断言,而是我对本月早些时候发布的新模型已经可能实现的事情充满热情。人工一般智能(AGI)的概念是有争议的,作为语言普遍性的创始人,乔姆斯基经常对人工神经网络能够模仿人类认知表示怀疑。我同意乔姆斯基对这个话题的怀疑,因为我经常看到人工语言在真正理解自然语言方面的失败。然而,像 DALL-E 这样的模型的创造,让我们可以想象未来会发生什么。

由 OpenAI 创建的 DALL-E (萨尔瓦多·达利和皮克斯的 WALL-E 的组合)是 GPT-3 的 120 亿参数版本,能够从文本描述中生成新图像。该转换器语言模型接收文本和图像作为输入,这允许它例如创建,

动物和物体的拟人化版本,以似是而非的方式组合不相关的概念,渲染文本,并对现有图像进行变换

在下图中,DALL-E 被提示“一个穿着芭蕾舞裙的小萝卜,正在遛狗。”

DALL-E 生成了一个穿着芭蕾舞裙遛狗的小萝卜的图像。来源。

值得注意的是, DALL-E 拥有类似人类的认知能力,比如推断上下文细节和组合不相关的概念。我认为这种进步是一种将以前难以捉摸的上下文和隐喻理解添加到人工智能语言模型中的方式。就符号基础问题而言,也许这是一种在更像人类的体验中基础单词的方式。

当一个人被要求想象皮卡丘穿着皮夹克挥舞蓝色光剑的样子时,他们可能会想象出类似下面的 DALL-E 生成的图像。

DALL-E 生成了一个身穿皮夹克、挥舞蓝色光剑的皮卡丘形象。来源。

此外, DALL-E 让研究人员惊讶的是,它在没有明确训练的任务上表现得如此之好;它实现了零射击迁移学习。引用最初的博客帖子,

“我们没有预料到这种能力会出现,也没有修改神经网络或训练程序来鼓励它。”

DALL-E 这样的图文模型的创新在于将自然语言的理解与视觉结合起来,在我看来这是向能够用人工语言理解自然语言迈进了一步。

为了将 DALL-E 的概念更进一步,也许结合知识图(类似于人工智能语言模型 ERNIE )将赋予人工智能语言模型建立网络连接的能力,这些网络连接构成了人类知识的基础。在皮卡丘的例子中, DALL-E 不知道迪士尼的《星球大战》和皮克斯的《瓦力》之间的关系;机器人在这两部电影中的角色,蓝色光剑的意义,以及为什么当可爱的口袋妖怪挥舞光剑时,这幅图像会让人们发笑。在图像-文本模型中的这些流行文化关系的知识图表可能允许人工语言复制隐藏在自然语言中的一些更深层次的理解。然而,这是否会导致 AGI,将取决于进一步的创新,而创新的速度将由可及性决定。

最终想法

开源人工智能研究的一个公认优势是创新和技术进步的速度。就我个人而言,我对 AI 和 NLP 研究的未来感到兴奋;我的乐观源于面部识别技术伦理方面的惊人工作。我还受到了 EleutherAI(通过公共不和谐组建)等草根人工智能研究小组的启发,他们正在创建一个开源版本的GPT-3(GPT-尼奥 )。我希望他们建立一个开源的 DALL-E,这种创造性的可能性值得思考。**

从过时到更新

原文:https://towardsdatascience.com/from-outdated-to-updated-2df4b43fcc38?source=collection_archive---------19-----------------------

如何使用 OCR、Python 和 SQLite 创建可搜索的 pdf 文档

作者图片,基于来自 Pixabay 的 Pexels 图片(卡带)和来自 Pixabay 的 Firmbee 图片(智能手机)

您是否发现自己希望能够处理 pdf 文件中的文本数据,然后使这些信息可以跨文件搜索,而不仅仅是在文档中搜索?常见问题吧?对个人来说可能不太常见,但一个常见的例子可能是创建一个可搜索的报告存档,这些报告已被保存为 pdf 文档,以便您可以更容易地找到符合特定兴趣的报告。或者,您可能希望让遗留系统中的电子邮件可以被搜索到。

在这篇文章中,我们将探索一种计算机视觉的应用,从 pdf 中提取文本,然后将文本结果输入到一个可搜索的数据库中,以便最终用户应用程序可以快速访问这些信息。像谷歌一样思考,但对于在线不可用的文档。这样做的好处是,您可以非常快速地搜索大量文档(例如,对住院应用程序用户有好处),并支持对文本进行更复杂的搜索功能(例如,对挑剔的应用程序用户有好处)。

为了解决这个问题,我们必须采取一些步骤,所以请耐心听我解释每一部分。我试图将这些部分分解成独立的部分,解释如何解决这个更大的问题。我们将使用 Python 和 ImageMagick 预处理 pdf 或图像以进行文本提取,使用 Tesseract 执行从图像中提取文本的计算机视觉部分,使用 sqlite 作为我们的数据库解决方案来创建提取文本的可搜索存储库。

图片来自 Pixabay

在我们开始之前,先给我们的环境命名:

Windows 10 操作系统

宇宙魔方 4.0

ImageMagick 6.9.10-Q8

Sqlite

Python 3.6 库

立方体 0.2.5

PIL

魔杖 0.4.4

sqlite3 2 . 6 . 0(Python 3 自带。x 作为标准库)

设置

Tesseract 和 ImageMagick 都是独立的软件工具,需要安装在您的环境中,以便启用 pdf-to-image 处理、预 OCR 处理和 OCR(文本提取)。有许多优秀的教程展示了如何做到这一点,我在下面列出了其中的一些:

要在 Windows 10 上安装 Tesseract OCR,请观看此视频。

这里的重点是 Windows 环境而不是 Linux,但是我们下面生成的大部分代码都是一样的。像 Tesseract 和 ImageMagick 这样的开源工具往往更容易加载到 Linux 环境中,但是因为我不得不同时使用这两种工具,所以我想在 Windows 环境中执行这个操作,以证明这是可能的。关于在 Windows 环境中安装的一些注意事项:

ImageMagick

您将需要使用 ImageMagick 6.9.10-Q8,而不是其最新版本。这是因为就我们将用来利用这款软件的 Python 函数而言,第 6 版在本文发布时是最稳定的。你可以在这里找到合适的 dll 文件。

在那里你可以找到 32 位和 64 位的可执行文件。因为我在 64 位 Windows 10 机器上运行,所以我下载了以下文件:

ImageMagick-6.9.10–11-Q8-x64-dll.exe

下载完成后,您可以双击并按照安装说明进行操作。

ImageMagick 安装到您的计算机上后,您将需要添加一个名为 MAGICK_HOME 的新环境变量,该变量的位置路径指向您的实例在您的计算机上的安装位置。例如,我的安装在 C 驱动器的程序文件中,所以我的路径变量如下所示:

c:\ Program Files \ ImageMagick-6 . 9 . 10-Q8

图片由作者提供,基于来自 Pixabay 的 Gerd Altmann 的图片(左)和来自 Pixabay 的 OpenClipart-Vectors 的图片(右)

宇宙魔方

要获得适用于您的特定 Windows 环境的安装程序,请访问此处并下载适当的可执行文件

一旦下载并安装到您的机器上,您将需要将 Tesseract 添加到环境变量中的路径变量中。当您访问您的环境变量时,打开您的 PATH 变量并将 Tesseract 的位置添加到列表中。我的道路看起来像这样:

c:\ Program Files(x86)\ tessera CT-OCR

Sqlite

Sqlite 是一个非常轻量级的数据库软件,具有文本索引功能。因为它是世界上最常用的数据库软件,而且它附带了 Python,所以我们将在这里使用它。这里的是一个精彩的教程,展示了如何下载 Windows 的 sqlite 工具

现在我们已经安装了所有的非 python 软件,我们准备开始了!

图片由Williams 创作来自 Pixabay

开始编码吧!

第一步是确保您已经安装了所有必要的 Python 库并将其放入内存。如果你正在使用像 IPython 这样的交互式 python 控制台,你可以像这样在 pip 之前使用“shebang ”!:

!pip install pytesseract==0.2.5
!pip install pillow==4.2.1
!pip install wand==0.4.4

第一步:将 PDF 转换为图像

安装后,我们将开始从 pdf 到图像的转换,因为宇宙魔方不能消费 pdf 的。为了快速创建一堆 pdf 文件,我为 Chrome 使用了一个名为“ Save-emails-to-pdf ”的扩展。它速度很快,只需勾选复选框中的电子邮件并点击下载按钮,就可以将 Gmail 中的大量电子邮件保存为 pdf 文件:

作者图片

我们将使用这些 pdf 文件转换成图像,然后执行 OCR。如果您在想“嘿,为什么不直接使用 Python 中的 pdf 库来提取文本呢”,您将是正确的,因为像这样创建 pdf 文件确实可以直接从 pdf 代码中提取文本。问题是许多 pdf 文件没有嵌入文本,而是表示文本的图像。在这些情况下,提取文本的唯一方法是从图像文件中执行 OCR。但是我跑题了,继续…

from wand.image import Image
import wand.image
import wand.api
from os import listdirpath = 'C:/betacosine/OCR/'
pdf_list = [x for x in listdir(path) if x.endswith('.pdf')]

对于这个例子,我将示例 pdf 电子邮件放在上面代码中描述的路径中。然后,我们使用 listdir 方法获取指定目录中所有 pdf 文件的列表。

import ctypes
MagickEvaluateImage = wand.api.library.MagickEvaluateImage
MagickEvaluateImage.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_double]def evaluate(self, operation, argument):MagickEvaluateImage(self.wand, wand.image.EVALUATE_OPS.index(operation),self.quantum_range * float(argument))

在我们将 pdf 文件处理成图像之前,我们需要设置我们的 ImageMagick 方法和函数,这些方法和函数将用于将 pdf 文件转换成用于 OCR 的图像。我发现,当我们将 pdf 转换为灰度并在通过 OCR 引擎之前使用某种阈值对图像进行预处理时,Tesseract 在数字文本提取方面表现最佳。

阈值处理是一种简单有效的将图像中的前景从背景中分离出来的方法。为了使用 ImageMagick 完成这项工作,我们需要指定一些额外的信息,因此我们开发了一个函数来为我们执行阈值处理。

还有一个叫 OpenCV 的软件工具,它有一个更容易使用的 Python 接口,用于阈值处理和其他图像预处理,但为了让事情变得简单一点,我只关注 ImageMagick。参见这篇关于使用 OpenCV 的 Tesseract 的精彩教程。

所以,上面的代码并不是最漂亮的,我当然明白了,尽管我试图通过把它放在 GitHub Gist 中使它更易读;)这是我作为数据科学家而不是程序员展示我的卡片的地方,但是上面的代码确实工作并且是有效的。因为它很复杂,所以让我向您介绍一下这里发生的事情。在第一行中,我们创建了一个名为 text_list 的开放列表容器,这是我们放置 OCR 文本结果的地方。在“for 循环”的开始,我们从遍历目录中的每个 pdf 文件开始。因为大多数 pdf 文件都是多页的,我们希望对每一页进行 OCR,所以我们需要在每一页上迭代我们的任务。因此,我们使用第一个“with”语句来获取每个 pdf 文件的总页数。

第二个“for 循环”遍历每个页码,并在每页上执行第二个“with”语句中包含的函数。在第二个“with”语句中,我们首先将图像转换为灰度,然后执行阈值处理。在以“img_buffer”开始的下一行中,我们使用 ImageMagick 中的“make_blob”方法时得到的二进制文件创建了一个 Numpy 数组。然后我们将它转换成一个 bytes 对象,这样我们就可以使用 PIL 库打开它。所有这些都是为了让我们不需要花费宝贵的计算资源将图像写入光盘,然后将它读回内存以执行 OCR。这样我们就可以直接将对象传递给 Tesseract 进行 OCR。

最后,我们将得到的文本追加到 text_list2 中,然后再追加到 text_list 中。我们剩下的是一个列表列表:

作者图片

你会注意到我在这里只处理 6 封邮件。

flat_list = ['\n'.join(map(str, x)) for x in text_list]

在上面的下一行代码中,我们通过将多个页面合并到一个列表而不是一个子列表中,将结果列表简化为一个列表。

此时,您可以添加一些文本处理步骤,进一步提高已提取文本的可读性和准确性。

第二步:创建一个可搜索的数据库

现在我们已经有了文本数据,我们希望将它输入到一个数据库中,该数据库对我们希望能够搜索的文本字段进行索引。

import sqlite3sqlite_db = 'email_db.db'zip_list = list(zip(pdf_list,flat_list))conn = sqlite3.connect(sqlite_db)c = conn.cursor()

在接下来的两行代码中,我们将导入 sqlite3 库,并为我们的数据库提供一个名称(email_db,original,我知道)。然后,我们将每个电子邮件的 pdf 文件名列表加入到文本结果列表中,这样可以快速插入数据库。

在最后两行代码中,我们创建了一个到数据库的连接。如果数据库不存在,这将创建它。然后,我们激活光标,以便能够与数据库进行交互。

c.execute('CREATE VIRTUAL TABLE email_table USING fts4(email_title TEXT, email_text TEXT)')c.executemany('INSERT INTO email_table(email_title,email_text) VALUES(?,?)', zip_list)conn.commit()

接下来,我们通过使用 FTS4 扩展创建一个表来使用 Sqlite 的文本索引功能。在 Sqlite 中,FTS 3–6 提供了文本索引功能,显著减少了从查询中获取结果所需的时间,并增加了额外的文本搜索功能。点击了解更多。

最后,我们将 zip_list 中的数据插入到新表中,并提交它。

搞定了。现在,您已经创建了一个可搜索的文本数据数据库,即使是最复杂的文本搜索,它也能在数毫秒内响应数百万行。我已经对超过 1200 万行数据这样做了,并且在 0.1 到 0.2 秒内得到搜索结果。

此外,您现在可以利用 SQLite 的 FTS 扩展中提供的更复杂的文本查询功能。例如,您现在可以搜索一定数量的其他单词并返回结果。您甚至可以返回包含额外字符的结果,这些字符会突出显示您的搜索词在文本中出现的位置。我在下面包含了一些示例代码。

import pandas as pddf = pd.read_sql('''select * from email_table where email_text MATCH 'trump NEAR/5 tweet*';''',conn)conn.close()

在上面的代码中,我使用 pandas 拉出一个结果数据框,在其中我搜索任何说 trump 和 tweet 的行,它们之间的距离不超过 5 个单词。很酷吧!?!

一如既往,我们期待着任何评论,想法,或反馈,这可能已经启发了你。

比如参与学习更多关于数据科学的知识?加入我。

从熊猫到 PySpark

原文:https://towardsdatascience.com/from-pandas-to-pyspark-fd3a908e55a0?source=collection_archive---------7-----------------------

照片由h·海尔林在 Unsplash 拍摄

利用您的熊猫数据操作技能来学习 PySpark

对于数据分析师、数据科学家和任何与数据打交道的人来说,能够熟练、高效地操作大数据是一项有用的技能。如果您已经熟悉 Python 和 pandas,并且想要学习讨论大数据,一个好的开始方式是熟悉 PySpark,这是一个用于 Apache Spark 的 Python API,一个流行的大数据开源数据处理引擎。在这篇文章中,我们将并排比较用于基本数据操作任务的 pandas 代码片段和它们在 PySpark 中的对应部分。

这篇文章假设读者能够熟练地使用 Python 中的 pandas 操作数据。

0.资料组📦

让我们从导入必要的库开始。在 PySpark 中,我们需要创建一个 Spark 会话。一旦创建了 Spark 会话,就可以从: http://localhost:4040/ 访问 Spark web 用户界面(Web UI)。下面定义的应用程序名称“教程”将作为应用程序名称显示在 Web UI 的右上角。在这篇文章中,我们不会使用 Web UI,但是,如果你有兴趣了解更多,请查看官方文档。

import pandas as pd
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('tutorial').getOrCreate()

在这篇文章中,我们将使用企鹅数据集。使用下面的脚本,我们将在工作目录中保存数据的修改版本penguins.csv

from seaborn import load_dataset
(load_dataset('penguins').drop(columns=['culmen_length_mm', 'culmen_depth_mm']).rename(columns={'flipper_length_mm': 'flipper','body_mass_g': 'mass'}).to_csv('penguins.csv', index=False))

1.比较🔎

现在,让我们看看两个库之间的语法比较。在本节中,只显示 PySpark 输出,以减少帖子的混乱。

📍 1.1.基础

两个库的数据对象都被称为 data frame:pandas data frame vs PySpark data frame。让我们导入数据并检查其形状:

# 🐼 pandas 
df = pd.read_csv('penguins.csv')
df.shape# 🎇 PySpark
df = spark.read.csv('penguins.csv', header=True, inferSchema=True)
df.count(), len(df.columns)

当使用 PySpark 导入数据时,第一行被用作标题,因为我们指定了header=True,并且数据类型被推断为更合适的类型,因为我们设置了inferSchema=True。如果您感到好奇,可以尝试不使用这些选项进行导入,并检查数据帧及其数据类型(与 pandas 类似,您可以使用 PySpark 数据帧的df.dtypes来检查数据类型)。

与熊猫 DataFrame 不同,PySpark DataFrame 没有.shape这样的属性。所以为了得到数据形状,我们分别找到行数和列数。

现在,让我们检查有关数据的高级信息:

# 🐼 pandas 
df.info()# 🎇 PySpark
df.printSchema()

虽然这个方法不会给df.info()相同的输出,但它是最接近的内置方法之一。是时候看看数据的开头了:

# 🐼 pandas 
df.head()# 🎇 PySpark
df.show(5)

默认情况下,如果超过 20 行,df.show()将显示 20 行。PySpark DataFrame 其实有一个叫.head()的方法。运行df.head(5)提供如下输出:

来自.show()方法的输出更加简洁,所以我们将在这篇文章的剩余部分使用.show()来查看数据集的顶部行。现在让我们看看如何选择列:

# 🐼 pandas 
df[['island', 'mass']].head(3)# 🎇 PySpark
df[['island', 'mass']].show(3)

虽然我们在这里可以使用几乎类似熊猫的语法,但以下版本的代码片段可能更常用于在 PySpark 中选择列:

df.select('island', 'mass').show(3)
df.select(['island', 'mass']).show(3)

📍 1.2.过滤

让我们看看如何根据条件过滤数据:

# 🐼 pandas 
df[df['species']=='Gentoo'].head()# 🎇 PySpark
df[df['species']=='Gentoo'].show(5)

这两个库的语法几乎相同。为了获得相同的输出,我们也可以使用:

df.filter(df['species']=='Gentoo').show(5) df.filter("species=='Gentoo'").show(5) 

下面显示了一些常见的过滤器比较:

# 🐼 pandas 
2a df[df['species'].isin(['Chinstrap', 'Gentoo'])].head()
3a df[df['species'].str.match('G.')].head()
4a df[df['flipper'].between(225,229)].head()
5a df[df['mass'].isnull()].head()1b df.loc[df['species']!='Gentoo'].head()
2b df[~df['species'].isin(['Chinstrap', 'Gentoo'])].head()
3b df[-df['species'].str.match('G.')].head()
4b df[~df['flipper'].between(225,229)].head()
5b df[df['mass'].notnull()].head()6 df[(df['mass']<3400) & (df['sex']=='Male')].head()
7 df[(df['mass']<3400) | (df['sex']=='Male')].head()# 🎇 PySpark
2a df[df['species'].isin(['Chinstrap', 'Gentoo'])].show(5)
3a df[df['species'].rlike('G.')].show(5)
4a df[df['flipper'].between(225,229)].show(5)
5a df[df['mass'].isNull()].show(5)1b df[df['species']!='Gentoo'].show(5)
2b df[~df['species'].isin(['Chinstrap', 'Gentoo'])].show(5)
3b df[~df['species'].rlike('G.')].show(5)
4b df[~df['flipper'].between(225,229)].show(5)
5b df[df['mass'].isNotNull()].show(5)6 df[(df['mass']<3400) & (df['sex']=='Male')].show(5)
7 df[(df['mass']<3400) |(df['sex']=='Male')].show(5)

虽然在 pandas 中~-都用作否定,但是在 PySpark 中只有~用作有效否定。

📍 1.3.整理

让我们对数据进行分类,检查质量最小的 5 行:

# 🐼 pandas 
df.nsmallest(5, 'mass')# 🎇 PySpark
df[df['mass'].isNotNull()].orderBy('mass').show(5)

Pandas 的.nsmallest().nlargest()方法明智地排除了缺失值。然而,PySpark 没有等效的方法。为了获得相同的输出,我们首先过滤掉缺少质量的行,然后我们对数据进行排序并检查前 5 行。如果没有丢失数据,语法可以缩短为:df.orderBy(‘mass’).show(5)

让我们看看使用.sort()代替.orderBy()的另一种排序方式:

# 🐼 pandas 
df.nlargest(5, 'mass')# 🎇 PySpark
df.sort('mass', ascending=False).show(5)

语法的这些变化也是有效的:

df.sort(df['mass'].desc()).show(5)
df.orderBy('mass', ascending=False).show(5)
df.orderBy(df['mass'].desc()).show(5)

我们可以按多列排序,如下所示:

# 🐼 pandas 
df.sort_values(['mass', 'flipper'], ascending=False).head()# 🎇 PySpark
df.orderBy(['mass', 'flipper'], ascending=False).show(5)

在 PySpark 里,你可以这样不用单子就脱身:df.orderBy(‘mass’, ‘flipper’, ascending=False).show(5)。要按不同方向的多列排序:

# 🐼 pandas 
df.sort_values(['mass', 'flipper'], ascending=[True, False]).head()# 🎇 PySpark
df[df['mass'].isNotNull()]\.sort('mass', 'flipper', ascending=[True, False]).show(5)

这里有一个替代方案:

df[df['mass'].isNotNull()]\.orderBy(df['mass'].asc(), df['flipper'].desc()).show(5)

📍 1.4.聚合

现在,让我们看几个汇总数据的例子。简单的聚合非常类似,如下所示:

# 🐼 pandas 
df.agg({‘flipper’: ‘mean’})# 🎇 PySpark
df.agg({'flipper': 'mean'}).show()

查看多个聚合时,我们需要采用不同的方法:

# 🐼 pandas 
df.agg({'flipper': ['min', 'max']})# 🎇 PySpark
from pyspark.sql import functions as F
df.agg(F.min('flipper'), F.max('flipper')).show()

要获取列中的不同值:

# 🐼 pandas 
df['species'].unique()# 🎇 PySpark
df.select('species').distinct().show()

要在一列中获取多个不同的值,请执行以下操作:

# 🐼 pandas 
df['species'].nunique()# 🎇 PySpark
df.select('species').distinct().count()

📍 1.5.按组汇总

到目前为止,您可能已经注意到 PySpark 在方法和函数中使用了驼峰。对于.groupBy()也是如此。下面是一个简单的按聚合分组的示例:

# 🐼 pandas 
df.groupby('species')['mass'].mean()# 🎇 PySpark
df.groupBy('species').agg({'mass': 'mean'}).show()

以下是聚合多个选定列的示例:

# 🐼 pandas 
df.groupby(‘species’).agg({‘flipper’: ‘sum’, ‘mass’: ‘mean’})# 🎇 PySpark
df.groupBy('species').agg({'flipper': 'sum', 'mass': 'mean'}).show()

如果我们不指定列,它将显示所有数字列的统计信息:

# 🐼 pandas 
df.groupby('species').mean()# 🎇 PySpark
df.groupBy('species').mean().show()

我们也可以用.avg()代替.mean()。换句话说,我们可以使用df.groupBy(‘species’).avg().show()

这就是这篇文章的全部内容!希望这些比较对您有用,并对 PySpark 语法有所了解。您可能已经注意到,在基本任务方面,这两个库有很多相似之处。这使得对熊猫有工作知识的人更容易开始使用 PySpark。

照片由沙哈达特·拉赫曼在 Unsplash 上拍摄

您想访问更多这样的内容吗?媒体会员可以无限制地访问媒体上的任何文章。如果您使用 我的推荐链接成为会员,您的一部分会费将直接用于支持我。

感谢您阅读我的文章。如果你感兴趣,这里有我的一些其他帖子的链接:
◼️️ 给 pandas 用户的 5 个提示
◼️️ 在 pandas 中聚合数据的 5 个提示
◼️️ 在 pandas 中编写 5 个常见的 SQL 查询
◼️️ 在 pandas 中编写高级 SQL 查询
◼️️ 如何在 pandas DataFrame 中转换变量

再见🏃 💨

从补丁到幻灯片:如何在弱监督下在千兆像素图像上训练深度学习模型

原文:https://towardsdatascience.com/from-patches-to-slides-how-to-train-deep-learning-models-on-gigapixel-images-with-weak-supervision-d2cd2081cfd7?source=collection_archive---------3-----------------------

理解大数据

对全切片组织学图像建模技术的回顾和对不同情况的建议。

整片组织病理学图像的跨度可达 100,000 像素。对如此大量的图像进行详细注释既费时又费钱。对于一些任务,病理学家可以注释图像中的单个特征,如组织类型或单个结构,如有丝分裂像。但是对于其他任务,只有更高级别的注释是可能的。

患者水平的标签可以从临床数据中获得,例如侵入前病变是否变为侵入性,患者在诊断后存活多久,或者他们是否对特定的治疗有反应。它也可以是从对肿瘤进行的不同类型的分析中获得的标记,例如识别突变或基因组亚型的分子分析。免疫组织化学染色的替代方法也可以产生整个肿瘤的标记,例如受体状态。

最近的研究表明,深度学习算法有能力从 H&E 整片图像(WSIs)中预测这些类型的患者级属性。因为图像非常大,并且没有先验知识知道图像中的哪些小块与标签相关联,所以这被称为弱监督学习。算法的工作是找出 WSIs 中的哪些补丁与预测任务相关。

千兆像素的图像太大,无法一次全部放在 GPU 上;它们通常被分成更小的块,用于训练深度学习模型。本文将着眼于如何从这些较小的斑块中学习区分特征,以及如何使用它们来预测载玻片或患者级别的属性。最近的创新也找到了在 WSI 训练 CNN 的方法——但是还有一些剩余的限制,将在本文结尾讨论。

整个幻灯片图像(WSI)被分成小块用于模型训练[ Lu2021

有两种常见的技巧可以使 WSIs 在 GPU 上得到处理:对图像补丁的子集进行采样或缩小图像表示。

补丁采样

整个 WSI 无法一次放入 GPU 内存,因此一个解决方案是从图像中选择一个补丁子集。已经采用了以下补丁选择方法:

  • 随机选择:从 WSIs 图像中抽取补丁的最简单方法是随机选择。在训练的每个时期,从每个 WSI [ Naik2020 ]中选择不同的随机补丁子集。如果补丁的数量和大小足够小,那么它将适合 GPU。
  • 识别肿瘤,然后随机选择:病理学家可以标注肿瘤区域 Zhu2016 ,或者可以在标注的肿瘤和非肿瘤斑块上训练癌症检测算法,以在新的 WSIs 中识别肿瘤。那么可以在每个时期随机选择肿瘤块的子集。
  • 聚类图像补片:为了捕捉组织外观的更多样化视图,可以对图像补片进行聚类。这可以通过将每个图像中的小块单独聚类成例如 10 个聚类来完成。然后从每个聚类中抽取一个小块,这 10 个小块一起代表 WSI [ Yao2020 ]。对此的另一种变化是在整个训练集中对面片进行聚类,并将每个 WSI 中离聚类质心最近的面片分配给该聚类。谢等人迭代地应用这种聚类方法,在训练的每个时期之后重新计算聚类质心。

补丁压缩

对图像补片进行二次采样的替代方法是使用整个 WSI,但采用压缩表示。再一次,多种策略被应用于将图像块编码成更小的表示。

CNN 可以在另一个数据集上训练,并用于编码图像补片。通常,在 ImageNet 上预先训练的 CNN 被转换成组织学图像[Lu 2021];然而,当对来自另一个组织学数据集的图像进行预训练时,同样的技术可能更有效。

神经图像压缩[ Tellez2020

无监督、自我监督和生成对抗网络(GAN)的预训练方法也取得了成功[ Tellez2019 , Dehaene2020 ]。

聚集补丁

然后,必须汇总 WSI 中多个面片的特征编码来预测类别。这些聚集方法可以用于训练具有图像补片子集的端到端 CNN,或者作为第二阶段模型来操作已经被压缩成较小表示的补片。

最常见的是,这是通过多实例(MI)学习范例完成的。每个 WSI 都是一个包含多个实例(图像补丁)的包。我们知道包的标签,但不知道实例的标签。

可以对补丁特征或补丁预测执行聚集。对于聚集补丁预测,传统的 MI 学习将正袋定义为具有一个或多个正实例,将负袋定义为具有所有负实例的袋。这个定义非常适用于癌症检测等任务,在这些任务中,即使少量的恶性组织也被视为癌症。如果训练数据集足够大,模型可以从这个简单的 MI 定义中学习。坎帕内拉等人使用 44k 活检 WSIs 来训练他们的模型[ Campanella2019 ]。

对来自 WSIs 的补丁进行多实例学习以检测癌症[ Campanella2019

对于其他任务,聚合修补程序预测的不同方法可能更合适,例如,类预测的多数投票或跨修补程序平均预测分数。我之前的一些工作计算了补丁预测分数的分位数函数,以更全面地表征它们的分布,然后从分位数函数[couture 2018 a]训练线性分类器,或者将分位数聚合构建到 CNN[couture 2018 b]中。

聚集补丁特征

聚合修补程序特征是一种替代方法。一旦聚集,完全连接的层可以在最终预测之前应用于顶部。特性聚合有多种选项:最大值或平均值池(取每个特性的补丁编码的最大值或平均值)[ Wulczyn2020 ],识别最具信息量的补丁,或加权和。

深度学习可用于识别 WSI 中最具信息量的斑块。Courtiol 等人创建了一个最大-最小层来识别顶部补丁和负面证据[ Courtiol2018 ]。他们发现,虽然平均池对扩散性疾病很有效,但当癌症没有扩散时,最大-最小层提供了坚实的推动力。

用于识别顶部补丁和负面证据的最大-最小图层[court io 2018

更一般的公式是自注意机制,其可以学习用于计算补丁嵌入的加权和的补丁权重[ Yao2020 , Lu2021 , Mobadersany2021 ]。这是目前最流行的聚集补丁特性的方法。

自我关注使用补丁编码来计算每个补丁的权重。然后,将补丁特征聚合为加权和。这种公式使模型能够了解哪些面片对于特定任务最有信息,并对这些面片的特征赋予更高的权重。

计算补丁嵌入加权和的自关注机制[Li2019]

将自我注意模型更进一步,李等人使用计算的斑块权重来识别硬负斑块[ Li2019 ]。在此基础上,他们构建了用于增强训练的硬阴性袋。

自我关注的另一个变体是确定性池,其中确定性被计算为实例蒙特卡罗退出预测的反向标准偏差。这种模型确定性的测量被证明比自我注意等替代方法更具解释力和鲁棒性,当只有少量的补丁包含期望任务的证据时。

自我关注和确定性池加权方案都提供了一些可解释性。权重可以叠加在 WSI 上作为热图,显示对预测任务最有用的影像部分。

注意力得分热图(右)与病理学家注释的肿瘤区域(左)一致[ Lu2021 ]

实现端到端培训的技巧

虽然单个 GPU 无法容纳一个 WSI,但一些技巧使 WSI 能够像全部保存在 GPU 内存中一样进行处理。

称为统一内存的 CUDA 功能可让 GPU 直接访问主机内存。与虚拟内存类似,页面会在请求时在 GPU 上交换。通过这项技术,陈等人能够处理 20k x 20k 像素的图像。任何更大的都会变得极其缓慢。为了适应更大的 WSI,他们在每个维度上缩小了 4 倍。这种技术最适合在低放大倍数图像上操作的简单任务。

使用统一内存通过具有全局平均池(GAP)或全局最大池(GMP)的 WSI 进行多实例学习[ Chen2021

一种替代方法是利用大多数 CNN 操作的局部性的称为流的方法。它结合了精确的平铺和梯度检查点来减少内存需求。要传输 CNN 的前向通道,首先要计算网络中间所选图层的特征图。由于缩减像素采样,此图层比原始图像小,因此适合 GPU。该中间特征图的重构然后被馈送到网络的其余部分。反向传递以类似的方式计算。

Pinckaers 等人首先用一个小而简单的 CNN 在 8k×8k 的图像上演示了这种技术[pinkaers 2020 a]。他们随后在 16k x 16k 的图像上展示了它。流的局限性在于它无法处理地图范围内的要素操作,例如网络流(较低)部分中的批量归一化。作为一种解决方法,他们冻结了批次归一化图层的均值和方差。

串流[pinkaers 2020 b

还有一种可能性是一种称为光环交换的空间划分方法。侯等人对 512x512x512 CT 图像的分割证明了这一点,并推测这也很适合组织病理学。这种技术将卷积层的输入和输出分布在 GPU 上,设备在卷积运算之前交换数据。

从统一内存到流,再到 halo exchange,这些方法中的每一种都可以对更大的图像进行端到端的训练,但目前仍有大约 20k x 20k 像素或更少的限制。我们还不能在不缩小图像和丢失对预测可能重要的细节的情况下处理更大的 WSIs。

监管不力的替代技术

一些方法结合使用了上述技术。李等人将 WSIs 缩小到 5 倍放大,使用聚类来捕捉斑块外观的变化,并使用注意力模型来识别重要的聚类(以及其中的斑块)[ Li2021 ]。在使用这种方法检测癌症后,他们在 10 倍的放大倍数下应用了相同的方法,只有被识别为癌症的斑块才能预测分级。

癌症检测(放大 5 倍)和分类(放大 10 倍)[ Li2021

上述对 WSIs 的应用都使用 CNN 来对图像建模。图形神经网络提供了另一种表示方法。CNN 应用于图像块,然后将它们连接到图形神经网络,该网络学习 WSI 的表示,以便进行预测[ Li2018 , Levy2021 ]。该图捕捉了补丁的邻域和其他潜在的重要架构特征之间的关系。

一个图形神经网络[ Li2018

总结和建议

那么应该选择哪种弱监管方式呢?这可能取决于您的数据集。例如,如果你有成千上万的图像,你也许可以用 CNN 的传统 MI 方法来检测癌症[ Campanella2019 ]。但是大多数 WSI 数据集并没有那么大。

可以排除图像的部分吗,比如非肿瘤区域?这减少了要处理的图像数据量,但可能会排除潜在的信息区域,如生存模型。

另一个角度是识别组织结构或小尺度图像特征是否更可能为您的任务提供最丰富的信息。如果是前者,精简后的 WSI 上的统一内存或流方法将是很好的起点。或者图形神经网络。但是,如果您需要更高的放大倍数来学习适当的功能,请尝试将面片采样或面片压缩方法与聚合方法(如自我关注)相结合。这些方法甚至可以在少于 1000 幅图像的情况下很好地进行训练。

如果您认为一个好的 CNN 表示可以从另一个数据集转移或以自我监督的方式学习,那么尝试一种补丁压缩方法。对于最具挑战性的任务,如预测存活率或其他结果,您可能需要直接监督图像补丁。在这种情况下,补丁采样结合注意力可能是你最好的选择。

然而这些仅仅是推测。尝试几种似乎最适合您的数据集和任务的方法。学习和重复。这毕竟是科学。

希望从您的图像和算法中获得最大的洞察力?

Heather D. Couture 是 Pixel Scientia Labs 的创始人,该实验室提取最新的人工智能研究,以帮助研发团队抗击癌症。

联系她,了解如何实施更好的模式并产生影响。

参考文献

[Campanella2019] G .坎帕内拉、M.G .汉纳、L. Geneslaw、A. Miraflor、V.W.K. Silva、K.J. Busam、E. Brogi、V.E. Reuter、D.S. Kilmstra、T.J. Fuchs、在整个幻灯片图像上使用弱监督深度学习的临床级计算病理学 (2019),《自然医学》

陈春林,陈春春,余文宏,陈淑慧,张永春,萧万长,余春华。yeh c .-y . Chen,一种利用深度学习进行肺癌病理分类的无注释整张幻灯片训练方法 (2021),自然通讯

[Courtiol2018] P. Courtiol,E.W. Tramel,M. Sanselme,G. Wainrib,仅使用全局标签的组织病理学分类和疾病定位:弱监督方法 (2018),arXiv 预印本 arXiv:1802.02212

[Couture2018a] H.D. Couture,L.A. Williams,J. Geradts,S.J. Nyante,E.N. Butler,J.S. Marron,C.M. Perou,M.A. Troester,M. Niethammer,利用深度学习进行图像分析以预测乳腺癌等级、er 状态、组织学亚型和内在亚型 (2018),npj 乳腺癌

[Couture2018b] H.D. Couture,J.S. Marron,C.M. Perou,M.A. Troester,M.Niethammer,异构图像的多示例学习:为组织病理学训练 CNN(2018),医学图像计算和计算机辅助干预

[Dehaene2020] O. Dehaene,A. Camara,O. Moindrot,A. de Lavergne,P. Courtiol,自我监督缩小了组织学中弱监督和强监督之间的差距 (2020),arXiv 预印本 arXiv:2012.03583

[Gildenblat2020] J. Gildenblat,I. Ben-Shaul,Z. Lapp,E. Klaiman,多示例学习的确定性池 (2020),arXiv 预印本 arXiv:2008.10548

[Hou2019] L. Hou,Y. Cheng,N. Shazeer,N. Parmar,Y. Li,P. Korfiatis,X. Song,采用空间分割的高分辨率医学图像分析 (2019),arXiv 预印本 arXiv:1909.03108

[Levy2021] J. Levy,C. Haudenschild,C. Bar,B. Christensen,L. Vaickus,利用图形神经网络进行整个切片图像的拓扑特征提取和可视化 (2021),生物计算

[Li2018]李,姚。、朱晓东、李玉英、黄军,全切片病理图像生存分析的图形 CNN(2018),医学图像计算与计算机辅助介入

[Li2019] M. Li,L. Wu,A. Wiliem,K. Zhao,T. Zhang,B. Lovell,组织病理学图像的深度实例级硬负挖掘模型 (2019)医学图像计算与计算机辅助介入

[Li2021] J. Li,W. Li,A. Sisk,H. Ye,W.D. Wallace,W. Speier,C.W. Arnold,多示例学习的组织病理学图像分类和定位的多分辨率模型 (2021),生物和医学中的计算机

[Lu2021] M.Y. Lu,D.F. Williamson,T.Y. Chen,R.J. Chen,m .,F. Mahmood,全切片图像的数据有效和弱监督计算病理学 (2021),自然生物医学工程

[Mobadersany2021] P. Mobadersany,L.A.D.Cooper,J.A. Goldstein,格式塔网:从胎盘全切片图像中聚集和注意改善孕周深度学习 (2021),实验室调查

[Naik2020] N .纳伊克,a .马达尼,a .埃斯特瓦,N.S .凯斯卡尔,M.F .普雷斯,d .鲁德曼,r .索彻(2020)。深度学习支持的乳腺癌激素受体状态确定,来自基础水平 H & E 染色 (2020),《自然通讯》

[pinkaers 2020 a]j . h . f . m . pinkaers,B. van Ginneken,G. Litjens,利用多百万像素图像进行端到端学习的流式卷积神经网络 (2020),IEEE 模式分析和机器智能汇刊

[pinkaers 2020 b]h . pinkaers,W. Bulten,J. van der Laak,G. Litjens,通过带有图像级标签的端到端训练检测全切片图像中的前列腺癌 (2020),arXiv 预印本 arXiv:2006.03394

[Tellez2019] D .特列斯,g .利特延斯,j .范德拉克,f .乔皮,用于千兆像素组织病理学图像分析的神经图像压缩 (2019),IEEE 模式分析和机器智能汇刊

[Tellez2020] D .特列斯,d .霍普纳,c .费尔霍夫,d .格伦哈根,p .尼罗普,m .德罗兹扎尔,f .乔皮,利用有监督的多任务学习扩展无监督的神经图像压缩 (2020),利用深度学习的医学成像

[Wulczyn2020] E. Wulczyn,D.F. Steiner,Z. Xu,A. Sadhwani,H. Wang,I. Flament-Auvigne,C.H. Mermel,P.-H.C. Chen,Y. Liu,M.C. Stumpe,利用组织病理学图像对多种癌症类型进行基于深度学习的生存预测 (2020),PLoS ONE

[Xie2020] C. Xie,H. Muhammad,C.M. Vanderbilt,R. Caso,d . v . k . yallagadda,g .,T.J. Fuchs,超越分类:通过端到端部分学习进行全切片组织病理学分析 (2020),深度学习医学成像

[Yao2020] J. Yao,X. Zhu,J. Jonnagaddala,N. Hawkins,J. Huang,利用注意力引导的深度多示例学习网络进行基于整片图像的癌症生存预测 (2020),医学图像分析

[Zhu2016] X. Zhu,J. Yao,J. Huang,用于病理图像生存分析的深度卷积神经网络 (2016),生物信息学与生物医学国际会议

从 PDF 到 Excel

原文:https://towardsdatascience.com/from-pdf-to-excel-536fe7844828?source=collection_archive---------7-----------------------

数据科学/ Python

使用 tabula 和 xlsxwriter

照片由艾丽莎·巴耶纳鲁在 Unsplash 上拍摄

在现实世界中,我们经常会遇到各种格式的数据。今天,我们将处理从 PDF 中提取表格数据并将其导出到 Excel 的任务。

唯一的警告是,pdf 文件必须是机器生成的。扫描页面的 pdf 不工作。这是 tabula 的一个局限性。

说完了,我们走吧!

环境

首先,让我们确定我们有一个好的 java 环境。

java -version

您应该会看到类似这样的内容:

作者截图

接下来,让我们用下面的代码安装 tabula-py:

pip install tabula-py

如果成功,

作者截图

最后,让我们安装 xlsxwriter:

pip install xlsxwriter

我们应该会看到这样的情况:

作者截图

现在,让我们打开 jupyter 笔记本,开始编码吧!

从 PDF 到 Dataframe

让我们从导入以下内容开始:

import pandas as pd
import tabula
import xlsxwriter

那我们来拿数据:

data = tabula.read_pdf('../data/in/titanic.pdf', pages='all', stream=True)

上面的代码产生了一个数据帧列表。因为列表中只有一个数据帧,所以让我们继续提取数据帧本身。我们可以做df[0]

接下来,我们需要通过重置索引和转置数据帧两次来将列标题转换为第一行。

df = data[0].reset_index().T.reset_index().T

并将这些列重命名为:

df.columns=['x', 'passenger', 'pc_class', 'gender', 'age', 'parch', 'fare', 'cabin', 'embarked']

让我们删除前两列:

clean_df = df.drop(columns=['x']).reset_index(drop=True)

现在我们为黄金时间做好了准备:

Excel 的数据框架

让我们首先创建一个新的 Excel 文件:

workbook = xlsxwriter.Workbook('../data/out/titanic.xlsx', {'nan_inf_to_errors': True})

并添加一个名为“测试”的工作表(选项卡):

worksheet = workbook.add_worksheet('test')

在将数据写入 Excel 之前,我们需要先将数据帧转换成列表。

data = list(clean_df.to_records(index=False))

让我们用以下内容初始化 Excel 文件的第一个单元格(A1 ):

# Rows and columns are zero indexed
row = 0
col = 0

让我们检查第一行:

我们需要通过手动插入列标题来解决这个问题。让我们将列名插入到列表的索引 0 中。

data.insert(0, ['passenger', 'pc_class', 'gender', 'age', 'parch', 'fare', 'cabin', 'embarked'])

现在我们可以一行一行地写了。

# Iterate over the data
for passenger, pc_class, gender, age, parch, fare, cabin, embarked in data:worksheet.write(row, col, passenger)worksheet.write(row, col + 1, pc_class)worksheet.write(row, col + 2, gender)worksheet.write(row, col + 3, age)worksheet.write(row, col + 4, parch)worksheet.write(row, col + 5, fare)worksheet.write(row, col + 6, cabin)worksheet.write(row, col + 7, embarked)row += 1

最后,让我们关闭工作簿。

workbook.close()

瞧啊。

作者截图

就是这样!我们给自己弄了个 Excel 文件。

结论

在这篇文章中,我们学习了如何使用 tabula 和 xlsxwriter。我们取了一个 pdf 文件,将其提取为数据帧,然后将内容写入 Excel 文件。与循环的结合起来,我们可以很容易地接收许多 pdf 文件,并且有一个平面文件可以输入到像 Redshift 这样的数据库中。经过一点小小的努力,我们已经为自动化找到了一个成功的组合。

你可以在我的 Github 上查看回购,以便进一步检查。下面是完整的代码:

谢谢你过来看我的帖子。

敬请期待!

如果你想了解更多关于我从懒鬼到数据科学家的旅程,请查看下面的文章:

如果你正考虑转型进入数据科学领域,现在就开始考虑重塑品牌:

你可以通过 Twitter 或 LinkedIn 联系我。

参考

https://github.com/chezou/tabula-py/blob/master/examples/tabula_example.ipynb https://xlsxwriter.readthedocs.io/tutorial01.html

从预测到行动——如何从数据中学习最佳策略(3/4)

原文:https://towardsdatascience.com/from-prediction-to-action-how-to-learn-optimal-policies-from-data-3-4-aa56c974a505?source=collection_archive---------24-----------------------

照片由上的爆裂未爆裂

在第一部分中,我们讨论了从数据中学习最优策略的必要性。政策优化涵盖了广泛的实际情况,我们简要地看了医疗保健、防止流失、目标营销和市政府的例子。

在第 2 部分中,我们描述了如何创建一个数据集,使其适合策略优化。

在这篇文章中,我们描述了一个简单的(在我看来也是神奇的)方法来使用这样一个数据集来估计 任何 政策的结果。

在第 4 部分中,我们将学习如何使用这样的数据集来寻找一个最优 策略。

甚至当你有能力找到最优政策时,能够快速估计任何政策的结果也是非常有用的。

例如,在商业环境中,人们总是对简单的政策感兴趣,这些政策要求对每个顾客采取相同的行动。这些政策易于理解和执行,因此企业领导人自然更喜欢它们。为了帮助他们决定是否应该采用简单的政策,他们可能想知道使用简单的政策而不是复杂的政策会“放弃”多少结果。如果预期结果下降不多,我们也可以采用简单的政策,对吗?

(BTW,简单的政策比比皆是。例如,在临床试验中,我们对两个简单策略(1)给每个人药物,和(2)给每个人安慰剂)之间平均结果的差异感兴趣

让我们回到我们在这个博客系列中处理的网飞客户流失的例子。

假设你的老板带着一个新政策的想法来找你:

如果一个顾客在过去的一个月里狂看了一个节目,“什么都不做”。

否则,如果客户上个月的观看时间比上个月少了 10–30 %,则提供“2 个以上的设备”。如果客户上个月的观看时长环比下降超过 30%,则提供“八折”。

如果这些标准都不适用,“什么都不做”。

当然,您可以做一个实验来估计这个策略的平均结果:随机抽取一些客户,对他们运行这个策略,并测量结果。但这需要时间和努力。

有更快的方法。你可以使用我们在第二部分中准备的数据集来快速估算你老板脑波的平均结果,而无需进行实验。

这个问题的关键是一个神奇的东西,叫做霍维茨-汤姆森估计器,下面是它的工作原理。

让我们从第 2 部分中组装的数据集开始。

对于上面数据集中的每个客户,确定由提议的策略指定的操作(实际上,这应该是一个简单的 SQL 查询或类似的查询)。

接下来,向数据集中添加“调整后的结果”列。

现在是巧妙的部分:对于每一个被分配的实际行动与新政策规定的行动相匹配的客户,将结果除以被分配行动的概率,并将其填入调整后的结果列。

例如,分配给第三个客户的实际操作和新策略指定的操作都是“20%折扣”,因此我们将结果 1.0 除以分配给“20%折扣”操作的概率(92%),得到调整后的结果 1.0/0.92 = 1.1(类似地,标有红框的其他三行也是如此)。

对于数据集中的所有其他行(即动作不匹配的地方),将 0.0 指定为调整后的结果。

“调整后的结果”栏已完成。现在,简单地取这个列的平均值,瞧!你对你老板的政策的平均结果有一个估计!

几个小注意事项:

  • 我们通过除以概率来计算调整后的结果。现在你明白了为什么我在第 2 部分中坚持认为数据收集策略中的每个概率都必须是非零的。
  • 同样,建议确保您的数据收集策略中的概率不要太小。用非常小的概率来划分结果会夸大调整后的结果数字,并使估计变得不那么可靠。
  • Horvitz-Thompson 估计量有一个“标准化”版本,称为 Hajek 估计量,具有更好的统计特性。我们不是寻找“调整结果”列的简单平均值,而是将该列的总和除以用于调整结果的概率的倒数之和(即除以 1/0.92 + 1/0.45 + 1/0.22 + … + 1/0.56)。详见杨等(2020) 第 5.1 节。
  • 我想重申第二部分中的一个警告:如果训练数据集不是通过随机实验而是通过历史观察数据收集的,那么数据集中的客户将不是随机样本,这可能会严重影响估计结果。因此,对这些数字要有所保留。

鉴于这种评估任何政策的能力,您可以通过集思广益寻找新政策,评估它们有多好,并试图改进它们。

或者,你可以直接找一个最优策略。在第 4 部分中,我们将这样做。

出于对数学的好奇,我在维基百科页面上尝试了一个更清晰的证明版本,展示了霍维茨-汤普森估计量如何无偏地估计任何政策的结果。

从预测到行动——如何从数据中学习最佳策略(4/4)

原文:https://towardsdatascience.com/from-prediction-to-action-how-to-learn-optimal-policies-from-data-4-4-14c63cc0c938?source=collection_archive---------24-----------------------

在这个系列的最后一篇文章中,我们将学习如何找到一个最优策略。

照片由 Unsplash 上的延斯·勒列拍摄

概述:

  • 在第一部分中,我们讨论了从数据中学习最优策略的必要性。政策优化涵盖了广泛的实际情况,我们简要地看了医疗保健、防止流失、目标营销和市政府的例子。
  • 在第 2 部分中,我们描述了如何创建一个数据集,使其适合策略优化。
  • 在第 3 部分的中,我们提出了一种简单的方法来使用这样一个数据集来估计 任何 策略的结果。

首先,值得注意的是,许多领域的研究人员——因果推理、计量经济学和上下文强盗——已经研究这个问题多年,并设计了许多算法来解决它——双重鲁棒方法、直接方法、转换结果方法、双重机器学习、X-Learner、R-Learner 等等。看看最近的调查的第 3 部分,了解我的意思。

面对如此丰富的财富,我面临着在这篇文章中关注什么的难题。但幸运的是,对这一领域做出重大贡献的研究团队之一在 2018 年组织了“一场上下文相关的强盗烘烤大赛”,其中许多关键算法相互竞争。

一种叫做 重要性加权回归【IWR】的相对简单的方法在竞争中表现出色,我在下面描述它。IWR 直接利用我们关于如何构建回归模型的知识,易于理解,并且可以使用您选择的任何监督学习回归方法轻松实现(如果您对底层理论感兴趣,请参见使用回归神谕的实用上下文强盗)。

在第 2 部分中,我们组装了这样一个数据集:

作者图片

或者,更具体地说,让我们以网飞流失为例,采取三个行动:提供 20%的折扣,在另外两个设备上提供免费流媒体,什么也不做。

作者图片

我们的目标是从这个数据集中学习一个函数,为每个客户分配最佳行动,也就是说,我们希望学习一个最佳策略。

使用重要性加权回归(IWR)学习最优策略是一个三步过程。

步骤 1 :根据分配的实际动作拆分上面的数据集。

每个动作的数据集(图片由作者提供)

现在,您将拥有与操作数量一样多的数据集。

步骤 2 :使用每个数据集,构建一个回归模型,该模型根据客户特征向量 x. 预测结果

至关重要的是,你需要使用加权平方损失作为损失函数,其中权重是概率列中数字的倒数。

回归模型通常默认最小化平方损失,所以这很标准。你要做的额外的事情是为训练集中的每个数据点发送一个权重。

作者图片

让我们用代数的方法写下来,这样就不会有歧义了。

就是这样。

(顺便说一句,加权回归通常是现成的。在 scikit-learn 中,例如线性回归、梯度推进回归和随机森林回归都以简单统一的方式支持权重,使用 fit 函数的 sample_weight 参数。

来自https://sci kit-learn . org/stable/modules/generated/sk learn . linear _ model。LinearRegression.html

调用拟合函数时,只需将样本权重设置为概率栏中数字的倒数)

在这一步结束时,您将已经构建了与操作一样多的回归模型。

第三步:对于任何一个客户特征向量 x ,运行 x每个模型,得到其行动的预测结果。

作者图片

现在,选择预测结果最高的行动。

你学会了一个最优策略!

正如你在上面看到的,IWR 唯一的新东西(与传统回归相比)是使用概率的倒数作为权重。

使用概率背后的直觉是什么?

为了简单起见,假设您的客户特征向量 x 只有一个元素:它是一个二元变量,如果有问题的客户曾经看过关于网飞的纪录片,则为 1,如果没有,则为 0。

在与业务利益相关者协商后,假设您提出了以下数据收集政策(在第 2 部分中定义):

数据收集政策(图片由作者提供)

让我们来关注一下“八折”这一栏。

作者图片

假设我们选择随机抽样的 N 位客户进行数据收集,而跟单观察人代表了样本的一小部分 p ,那么我们样本中大约 Np 位客户将是跟单观察人,而 N(1-p) 位客户则不是。

作者图片

有鉴于此,“八折”数据集中的客户数量大约为:

作者图片

(即,在我们样本中观看纪录片的 Np 客户中,根据我们的数据收集政策,其中 50%将被分配“八折”,因此我们得到 N x p x 0.5)

但是我们现在有一个问题。“八折”列中 x =1 和 x=0 客户的组合不同于样本中 x =1 和 x=0 客户的总体组合。如果我们用这个倾斜的数据集建立一个回归模型,它对“20%折扣”行动结果的预测可能会有偏差。

更一般地说,在您计划在整个客户群中使用的模型中,您用来构建模型的数据点应该有 x 以与在您的客户群中相同的方式分布。

回到我们的例子,我们如何解决这个问题?

一种方法是“制作点数的副本,使得“20%折扣”栏中 x=1 和 x=0 点数的组合与样本中 x =1 和 x=0 客户的总体组合相匹配。

假设我们对 x=0 点使用乘数 u ,对 x=1 点使用乘数 v 。乘法(即复制)完成后,新的点数显示在下面最右边的列中。

作者图片

我们应该如何选择 uv 使得“八折”栏中调整后的客户数量与总体样本中的数量相匹配?

作者图片

简单。只需将乘数设置为概率的倒数!

设置 u = 1/0.5 和 v = 1/0.2。

作者图片

乘数和概率完美抵消,调整后的数字与总体数字相匹配!

(实际上,我们不会复制数据点。相反,我们简单地将概率的倒数作为权重插入损失函数,并且它具有相同的效果)

总之,在回归中使用概率的倒数作为权重,消除了由我们的数据收集策略引起的数据点的偏斜。

如果这个概率倒数的生意让你想起了第三部分中的霍维茨-汤普森估值器是如何工作的,你的直觉是正确的!事实上,我们可以用类似的论证来证明 IWR 是可行的。如果你很好奇,一个代数证明在帖子的底部。

(顺便说一句,这种使用概率倒数进行调整的想法是一种非常普遍和强大的技术的简单例子,这种技术被称为重要性抽样,被广泛用于许多领域)

你已经学习了使用 IWR 的最优策略,并准备将你的最优策略付诸实施。

我建议在发布前做最后一点调整。

世界在不断变化,在您的最佳策略中捕获和体现的客户行为模式也会随着时间而变化。今天是最优的政策在下个季度可能不是最优的

当然,您可以使用数据收集策略定期收集新数据,并利用这些数据学习新的最佳策略。但是有更好的方法。

给你的最优策略添加一点随机化,然后启动(参见第二部分中关于ε-贪婪的讨论,提醒你如何做)。

通过这样做,您的最佳策略可以兼作数据收集策略。偶尔,你可以从中获取数据,使用 IWR 重新学习一个最优策略,然后切换到那个策略(但是,同样,当你启动它时,你会添加一点随机化)。

在这篇文章中,我们将策略优化描述为一个批处理周期:运行一段时间的数据收集策略,对收集的数据使用 IWR 来学习最优策略,部署添加了一点随机化的最优策略,并且经常重复

但这可以在实时中完成。在极端的情况下,我们可以在每次交互之后(即,在观察到每个 x - >动作- >结果之后)通过递增地更新对应于被分配的动作的 IWR 模型来这样做。更多信息见此处。

在我们结束之前,让我们考虑一个非常重要的特例:当我们只有 两个 动作可以从中选择的时候。通常,其中一个是主动的事情(例如,给病人 X 药,给顾客打折),另一个是被动的事情(例如,给安慰剂,什么都不做)。

特别是在因果推断/计量经济学中,两个行动(或两个治疗)的场景非常常见,因为你经常想要估计一个干预(又名行动或治疗)与不干预相比对现有系统的影响。

在这种特殊情况下,你实际上可以通过一个直接预测两个行动之间结果差异的模型来学习最优策略。在某些情况下,这可能比学习两个不同的模型更有效。要了解更多信息,请参见最近的调查的第 3 部分,并遵循其中的参考资料。

在这个由 4 部分组成的系列文章中,我试图从大量快速增长的研究中提取政策优化的最实用的元素。有大量非常有趣的材料——如果你想了解更多,这里有一些建议。

  • IWR 在 2018 年才首次被描述(参考文献),如果我试图在 2018 年之前写这篇文章,我可能会选择双稳健方法。更一般地说,除了 IWR 还有很多其他选择,如果你感兴趣,就从最近的这个调查开始,去你的好奇心想去的地方吧。
  • 如果您对用于策略优化的库/模块感兴趣,这里有一个示例: Vowpal Wabbit 、 CausalML 、 EconML 、 PyLift 和 Uplift 。特别是,本文中描述的 IWR 方法是在 Vowpal Wabbit 库中实现的。
  • 如果您对商业可用的政策优化产品/服务感兴趣,这里有一个示例。

快乐学习!

可选

出于好奇,这里有一个 IWR 如何工作的代数证明。

作者图片

从预测到行动——如何从数据中学习最佳策略(1/4)

原文:https://towardsdatascience.com/from-prediction-to-action-how-to-learn-optimal-policies-from-data-part-1-1edbfdcb725d?source=collection_archive---------13-----------------------

弗拉季斯拉夫·巴比延科在 Unsplash 上的照片

在数据科学工作中,我们建立模型来进行预测。利用这些预测,我们做出决定或采取行动。

有时候,预测和行动之间的关系很简单:

  • 当你离家去上班时,你正试图决定是否应该带一把伞。你预测下雨的可能性。如果够高,你带把伞。如果没有,你就把伞留在家里(来源)
  • 你在尝试判断一个图像中的人是不是 x,如果预测的概率足够高,你就用这个人的名字给图像加标签。如果没有,您可以不加标签。

其他时候,预测和行动之间的关系更复杂。

假设你是一名数据科学家,为网飞这样的订阅企业工作。您希望通过向客户提供留下来的奖励来防止他们取消每月订阅。

这就是众所周知的流失问题,标准的数据科学/机器学习方法如下。

首先收集取消的客户和没有取消的客户的历史数据。使用他们的属性,他们与业务的互动等。以形成每个客户的“特征向量”。添加一个指示客户是否取消的标志,并创建如下数据集:

利用这个数据集,建立一个模型(例如逻辑回归),在给定客户特征向量的情况下,预测他们取消的概率。

这可能是一个非常复杂的模型。对于每个客户,它可能有数百或数千个特征(即每个 x 可能是一个非常长的向量),并且可能是使用最先进的方法(例如,深度学习、 XGBoost )构建的

但是对于这样一个模型,你应该怎么做呢?

你是否应该联系那些预测有很大可能会大量流失的客户,并在他们续约时给予奖励或折扣?

这是一种合理的方法,并被广泛使用。这对某些客户有效,但不一定对所有客户有效(参考)。

  • 有些顾客会无视奖励,无论如何都要取消。
  • 其他人可能根本没有想过离开,但会很乐意接受奖励并留下来——你只是在他们身上浪费了奖励。
  • 对于其他一些可能没有想过离开的人来说,也许你的奖励提醒了他们,他们并没有经常使用你的产品/服务,他们可能会点击“取消”按钮。

如果你有不止一个可能的行动,事情会变得更加复杂。C 顾客可能会对不同的行为做出不同的反应。如果提供“如果续订一年,每月账单可享受 20%的折扣”的奖励,客户 Sally 可能会续订,但如果提供“免费赠送 2 台以上设备”的奖励,则不会。对于客户艾伯特来说,可能正好相反。

想象一下,如果您可以预测当客户成为目标时,您可能采取的每一个可能的行动,包括“什么都不做”的行动,客户流失的可能性。

当然,估算每个动作的流失概率只是一个起点。在业务环境中,您可能最终关心的是财务结果,例如,每个客户在未来 12 个月的预期利润。如果您知道每个行动的成本/收入影响,您可以将上面的模型转换为:

有了这个模型,对于任何客户,您都可以预测每个行动的预期结果,并“读出”该客户的最佳行动(即,找出最多 3 个数字!)

我们将在后面学习如何建立一个类似上面的模型。但首先,让我们退后一步,抽象出流失问题的关键要素。

  • 一组客户(我广义地使用‘客户’来指代您想要对其应用操作的实体。例如,它可以是一个病人、一个网站访问者、一个潜在客户、一个企业、一个地理区域……你明白了)。关于客户属性、行为和其他上下文信息的所有相关信息被表示为特征向量。
  • 一组可能的动作
  • 当某项行动针对某个客户时,您的结果(重要的是,不同的客户对行动的反应可能不同)
  • 你的目标:为每一位顾客找到最佳结果的行动

让我们暂停几个快速定义。

将动作分配给每个特征向量的函数被称为策略

最佳动作分配给每个特征向量的函数是最佳策略。

我们想学习最优政策。

政策优化问题极其普遍。

  • 个性化医疗:对于一种医疗状况,有 4 种可能的治疗方法。每种治疗的有效性可能因患者而异,这取决于每个患者的特征和病史。什么是 最佳治疗策略 即,我们应该对每个患者“应用”哪种治疗,以最大化积极的健康结果?
  • 针对的活动:对于放弃购物车的电子商务访客,我们希望通过电子邮件向他们发送以下三种优惠之一:八折、免费送货、购物赠货。不同的购物者对这些优惠会有不同的反应。什么是 最佳目标政策 即,哪些优惠“适用于”每个购物者以实现预期利润最大化?(上面描述的客户流失问题也是“活动定位”的一个例子)
  • 健康/安全监测:城市通过派遣检查员检查商业机构是否符合健康和安全规定。不是每个建筑都可以在每个时间段用可用的人员进行检查,所以我们需要一个 最佳检查策略: 对于每个机构,选择两个动作中的一个——检查这个时间段,不检查这个时间段——以便最大化整体安全性。这不仅仅是预测哪些建筑更有可能存在违规行为的问题。对于检查员发现的违规行为,业主的“反应”是很重要的。

由于旧的布线,建筑物可能具有更高的火灾风险,但是其他考虑因素使得很难更换布线。其他单位可能有较低的预测风险,但它可能很容易和廉价作出实质性的改进。另一个考虑是响应性;如果违规导致罚款,一些公司可能比其他公司对罚款的前景更敏感。

来源:斯坦福大学的苏珊·艾希教授的综述文章,我推荐阅读全文。

好,我们如何学习最优策略?

让我们先看看最简单的情况。

回到客户流失的例子,让我们假设我们有来自随机实验的数据:一个客户样本被随机选择,然后随机分配到三个行动中的一个——20%的折扣、流动两个以上的设备和什么都不做——他们的续订/取消响应被记录下来。

在这种幸运的情况下,我们有三个很好的数据集:

(请注意,这三组的客户是不同的。为了方便起见,我在所有三个表中对客户特征向量列使用了相同的符号

我们现在可以建立三个标准分类模型。

有了这三个模型,找到最佳策略很容易:通过每个模型运行任何客户的 x ,获得三个预测的取消概率,将它们转化为预期利润(或任何你关心的财务结果),并选择具有最高预期利润的行动。

很好。但是正如我前面提到的,这是最直接的情况。

实际上,我们可能没有这么幸运。

如果有数据,但它不是来自一个你可以安全地用于建模的随机实验,该怎么办?也许只有过去的观察数据,其中提供的不是随机抽样的客户,而是那些可能取消的客户(例如)。基于这些数据建立一个模型并将其应用于所有的客户可能会导致糟糕的预测。

如果在之前从未尝试过一个动作,比如说,免费传输两个以上的设备,那么就没有关于它如何影响取消行为的数据了。有创造力的商人总是想出新的行动/策略/战略来尝试,所以这是一个真正的可能性。**

我们需要小心处理这些和其他问题。

但不用担心:-)。这个问题及其变体已经在许多领域得到了广泛的研究——因果推理、计量经济学、营销中的提升建模、以及(尤其是)情境强盗/强化学习——并且已经设计了许多实用而优雅的方法。这些技术通常通过随机实验将预测模型(分类/回归)与智能训练数据收集相结合。

在我看来,使用这些技术进行政策评估和政策优化是一种强大但未被充分认识和利用的数据科学超级力量。

在第 2-3-4 部分,我们将深入了解并获得这种超能力:-)

  • 在第 2 部分中,我们将描述如何创建一个数据集,使其适用于策略学习。
  • 在第三部分中,我们将学习一种简单的(在我看来也是神奇的)方法来估计T5【任何 政策的结果。
  • 在第 4 部分中,我们将学习如何找到一个最优 策略。

数据科学家从原型到生产

原文:https://towardsdatascience.com/from-prototype-to-production-for-data-scientists-4d86df6c3c08?source=collection_archive---------22-----------------------

为数据科学家带来创意和模型

介绍

你可能会想"是的,我知道原型是什么,还有什么需要知道的呢?"你可能是对的,但是你知道一些不同的方法和术语吗?当你试图实现新的东西时,这些可以减少摩擦。你知道'进化型和'一次性原型之间的区别吗?你知道什么是首次展示吗?你知道做一个飞行员的陷阱吗?如果是这样,也许你可以跳过这篇文章。如果不是,那么理解这些概念可以帮助你的公司。

什么是原型?它和其他东西有什么不同?

注意 原型 先导 在整篇文章中作为同义词使用。

如果您已经知道什么是原型,请随意跳到下一部分。如果你不知道什么是原型,简而言之——知道它是你想要在大规模部署之前证明有用的产品。

例如,假设您有一个新应用程序的好主意。这款新应用将帮助顾客决定哪副太阳镜最适合他们(这是诺德斯特龙开发的真实原型)。在投资 100 亿美元在一个新的应用程序之前,你想先测试你的理论。所以,你开发一个原型!

首先,你起草一个应用程序的模拟设计,并展示给客户。你收集反馈并开始开发一个快速应用程序。这个应用程序是在开发环境中构建的(不是生产)。你向少数客户展示你的版本(或 V1 版本),并获得反馈。你知道这是一个好主意,但需要一些修改。你继续这个过程,直到你对产品满意为止。总之,您已经收集了一些很好的反馈,您已经潜在地证明了该应用程序的价值,并且您已经使您的公司能够在降低财务风险的情况下投资于大规模部署。

原型方法

非生产试点

在某些情况下,你可能有技术和社会学的机会在投入生产之前将你的产品提供给少数用户。在这种情况下,您可以进行非 prod 试点。有了非产品试验,您就可以为少数用户创建最终产品的版本,然后您就可以收集对产品的反馈。您可以进行更改,然后重新交付给您的用户组,并继续这个过程,直到产品准备好投入生产。

混合试点/推广

在其他情况下,你不会有过多的选择和机会让你的产品在投入生产之前被少数用户使用。在这种情况下,接触用户的唯一途径就是通过生产。在这种情况下,您可能需要混合试点/推广。假设您正在创建一个新页面,并且您想了解您的销售团队对新页面的反应。您可以创建新页面,但是只对特定的群体开放(可能是特定邮政编码的销售代表,或者手动选择的列表)。在这一阶段,您需要监控用户对新页面的反应。您可以进行更改,然后重新交付给您的用户组,并继续这个过程,直到产品准备好进行大规模部署。

原型类型

广告传单

在这种情况下,你构建的原型并不是投入生产的产品。原型只是帮助你写出最终将投入生产的真实产品的需求。

进化的

在这种情况下,原型被生产采用。您编写和构建的任何代码都将部分或全部迁移到您的生产环境中。您可以进行一些重建,但是在大多数情况下,您创建的系统正在进入生产阶段。

混合型——一次性/进化型

你不会在很多原型文学中找到这种类型的原型,但是它是实践中出现的一种类型。在这种情况下,您的一些原型代码将投入生产,一些将被丢弃。例如,可能所有的后端工程都投入生产,但是你的产品的外观被重新编码(使用更适合生产的东西)。

你可以争论这只是进化,但我认为这里强调的是某些部分可能会完全被其他东西抛弃。

其他人

还有增量式极端式原型,它们更具技术性,超出了本文的范围。

原型生命周期

图片作者。这个过程从最初的想法开始。然后,它进入试验阶段,在这个阶段,它处于一个连续的反馈循环中,直到决定进入生产阶段。

最初的想法

这是某人(经理、高管甚至员工)有想法的开始,他们想把这个想法介绍给公司。也许会安排一次会议,与一些利益相关者交谈并获得印象。需要召开更多的会议来解决细节问题。产品的目标是什么?它将如何改善业务运营?它将如何产生收入?预计投资回报率是多少?当你回答这些问题时,你可以一点一点地为项目开绿灯。最终,项目被确定为“进行”状态,相关团队应该开始工作。

模拟设计

第一步是创建某种模拟设计。这个阶段是将愿景写在纸上,并与利益相关者甚至客户分享,以便获得反馈。这一阶段的问题是——它应该是什么样的?我们最初应该具备什么特征?你不需要所有的需求,但是你需要一些关于你首先要构建什么的想法。

飞行员

如果你正在做一个混合试点/推广,你就开始在生产中构建一些对有限用户可用的东西。

如果您正在构建一个非生产试点,最好是在一个与生产环境有些镜像的环境中开发一个产品。但是,最重要的是您的试点环境快速、灵活且可靠。只要您的用户能够快速、灵活、安全、可靠地访问,您就可以在任何地方构建您的系统。也就是说,如果你正在构建一个进化的原型——你的系统能在生产中部署吗?如果你不回答这个问题,无论你是否计划,你的原型最终都可能成为一次性的原型。

为了进入生产阶段,你需要验证你的投资回报率,并确保产品值得进一步投资。所以试点阶段非常重要。重要的是,你的客户能容易地接触到你的产品,并能有效地使用它;否则,你的产品可能会失败,不是因为它是个坏主意,而是因为你的试验环境不好。重要的是,您的试验环境和试验产品都要和产品一样高质量,否则,您可能会因为所有错误的原因而失败。

生产

此时,您的原型正在进入生产阶段,干得好!你已经证明了你有一个伟大的想法,将产生收入。您的代码要么已经发布,要么您的生产团队正在生产中重新创建您的试运行。

你将不得不与你的制作团队合作,以确保你的产品保持可见性。也许你需要一个新的数据源来跟踪新系统的进展。这些是你需要讨论的事情。

维护和持续改进

你的工作还没有结束!你应该跟进你的产品,观察它的进展,看看哪里可以改进。在转移到生产环境时,是否有任何可能影响用户体验的系统细微差别被忽略了?你的产品需要更新吗?什么时候需要更新?你的产品出来了,但你的工作才刚刚开始。

摘要

开发新产品和改变你的公司通常做生意的方式是困难的。理解围绕原型的正式(和非正式)方法和术语可以减少公司的困惑。如果一个项目失败了,你希望它失败的原因是正确的,而不是错误的。在已建立的框架中自学将使你能够绕过障碍并保持动力。软件开发方法为数据科学提供了很多东西。要成为一名杰出的数据科学家,你需要始终保持开放的态度来拓宽你的知识基础(在你的领域内外)。

其他相关主题和阅读材料

混乱

如果你对自己说,“试点周期看起来像一个 Scrum 周期”,那么你是对的!试点/原型周期是一个 Scrum 周期!如果你对 Scrum 不熟悉,我建议你去看看 Scrum.org 的以及在 Udemy 上的一些很棒的(和实惠的)课程。 Scrum 是原型制作的核心,所以如果你要进行原型制作,你应该真正了解 Scrum。

4 个基本的 A/B 测试部分

你可能会问自己,我怎么知道我的原型是否成功?定义成功非常复杂,每个项目都不一样。您可以 A/B 测试您的系统,这意味着您可以访问子群体,然后比较各组之间的指标——有新系统的组与没有新系统的组。您还可以比较实现前和实现后的指标,但是这种方法可能会很混乱,并且您需要控制时间上的差异。无论您采用何种方法,您都需要了解您的客户以及他们对新系统的反应。关于这个主题的更多信息,你可以查看我的另一篇关于 Medium 的文章,标题为 4 个基本的 A/B 测试部分。这些部分的相关性不限于 A/B 测试。这些细分市场与贵公司可能正在进行的任何试点或概念验证相关。知道你在影响谁,你在分散谁的注意力,以及你有什么选择来优化表现是很好的。

感谢阅读,快乐学习!

参考资料:

  • https://en.wikipedia.org/wiki/Software_prototyping
  • https://www . tutorialspoint . com/SDLC/SDLC _ software _ prototyping . htm
  • https://opensenseslabs . com/blog/articles/what-and-how-prototype-software-development
  • https://www . optimize ly . com/optimization-glossary/feature-rollout/
  • https://www . optimize ly . com/optimization-glossary/a b-testing/
  • https://www.scrum.org/resources/what-is-scrum
  • https://www . udemy . com/course/agile-scrum-for-初学者-scrum-master-certification-preparation/
  • 作者个人&职业经历

从 Python 到 Go

原文:https://towardsdatascience.com/from-python-to-go-901cea46446f?source=collection_archive---------5-----------------------

通过翻译 Python 代码学习围棋编程

图片由亚瑟·拉文伯格·德恩拍摄

我希望这篇文章既可以作为想要学习围棋的 Python 爱好者的字典,也可以作为那些了解 Python 并且只想快速入门 Golang 的人的入门指南。

在我们开始之前,我想简单解释一下为什么在你已经了解 Python 的情况下学习 Go 可能是一个很好的选择。

介绍

首先,我并不是说 Go 是比 Python 更好的语言。Python 是一种很棒的语言,通常是比 Go 更好的选择。这当然取决于你试图解决的问题或者你想要构建的应用程序,但是 Go 确实有很多 Python 没有的东西。

  1. 围棋很快——真的很快!在这个参数上,Go 以几乎类似 C 的速度将 Python 打得落花流水。这部分是因为 Go 是一种静态类型语言,具有优化的、速度极快的编译器,这使得 Go 的开发速度和执行速度都很快。
  2. 开发者友好。尽管围棋的速度很快,但写字的速度却快得惊人。我认为这有几个原因。首先,在围棋中你只有你真正需要的东西,所以你很少会怀疑在哪里用什么。语法清晰易读。甚至在语法上,它也清除了难看的括号和其他不必要的语法。其次,Go 解释器非常聪明,Go 的类型系统在缺少不必要的声明和保护未使用的导入和函数参数中未声明的数据类型的保存系统之间取得了很好的平衡。
  3. 内置的并发和并行。Go 是一门年轻的现代语言,如果你曾经尝试过用 Python 运行一些并行计算的大型项目,你就会知道这是一种痛苦。但在围棋中,却不是。你有被称为 goroutines 的绿色线程,你有通道,这是一种数据结构,它使得并行工作器能够相当安全地相互通信。您还有一种方法来锁定像数组这样的容器以避免竞争情况(如果通道的默认阻塞特性还不够的话),当然还有一种方法来确定运行哪个 goroutine 的优先级,以及一种称为 waitgroup 的同步特性。
  4. 低水平。尽管 Go 是一种开发人员友好的多用途编程语言,但它是非常低级的。也就是说,你对你的机器有很大的控制权。Docker 和 Kubernetes 就是用这种高性能的低级语言构建的一些例子。想一想,仅仅为了创建一个 Docker 容器,您就必须进行系统调用!

走吧。

在本文中,我们将开始从一种语言到另一种语言的句法之旅。也就是说,我还将讨论风格和结构,因为正如你们都知道的,一行一行的直接翻译是不好的,不管是什么语言。

请注意,这是一篇短文,已经跳过了 Go 的某些功能。也就是说,我已经试着包含了最重要的部分,所以这是尽可能独立的,这样你就可以对这门语言有一个全面的了解,并且实际上学习一些围棋。

事不宜迟,让我们直接进入主题,简单讨论一下导入、数据类型和变量声明。

开始

当你来自 Python 时,在 go 中第一件突出的事情是,在每个 Go 文件中,你需要指定什么叫做包。我不会详细讨论包和 go 项目的结构,因为这篇文章是关于语法的,但是可以说,如果两个文件在同一个包中,那么它们可以访问彼此的内容。

所以你从声明一个包开始,如果你想在你的文件中有你的执行起点,那么你应该把这个包命名为 main。**主关键字是 Go 中的一个特殊单词,意思是“这是程序开始的地方”。

功能

对于 Python 程序员来说,第二件陌生的事情是,你不需要主动声明运行哪个函数,因为在 Go 中,你总是运行名为 main 的函数。这也意味着如果你想运行任何东西,你必须在 Go 中创建这样一个函数。

在创建函数之前,您可以选择导入内容。这是您应该从 Python 中认识到的最后一点。

让我们看看每种语言中的一些“Hello World”程序,看看可能的开始是什么样子的。

Python 文件实际上不需要注释。与 Go 相比,唯一有趣的是,您需要指定要运行哪个函数,并且不需要导入任何东西。

然而,Go 文件已经有了很大的不同。您指定了一个包(如果不指定,您将会得到一个错误),并且您需要导入一个 format- lib 来执行 IO 操作。您还需要创建一个名为 main、的函数,它将在任何情况下运行,Go 中的函数是使用 func 语句创建的,当然在 Python 中我们使用 def

要运行名为" main.go 的 Go 文件,您只需打开一个终端或 shell 环境,确保您位于文件所在的文件夹中,并键入:

go run main.go

需要告诉 Go 函数哪些数据类型可以作为输入和输出。

func calc(number int) float64 {
...
return result
}

这在很多方面都是一件好事,因为它避免了很多错误。它只是更安全。

现在我们已经到了 shell、terminal、cmd、powershell 或您喜欢使用的任何程序,有一些 Go 命令您应该知道。

  • go run 会编译并运行你的文件。
  • 去构建会编译你的文件,构建一个可执行文件,然后你可以和你的朋友分享,并删除他们的硬盘:-)(如果你想留住你的朋友,也许只是做一个游戏)。
  • Go get 是另一个不错的命令,可以让你直接从 Github 这样的在线资源下载 Go 包。

当然还有很多更好的 Go 命令,但我不会破坏所有的乐趣。

数据类型和日常语法

两种语言都有常见的数字类型,如 int、float 等。,所以就不一一赘述了。但是,我们需要了解一些数据类型。

用线串

Go 中的字符串很像 Python,但是字符串所需的许多操作可以在需要导入的库中找到。即字符串库。

切片和阵列

在 Go 中,有两个类似 Python 列表的主要容器。数组和切片。数组有预先指定的元素数量,当您知道需要在变量中存储多少元素时,可以使用数组。此外,数组中只能有一种数据类型。

切片更加灵活,更像 Python 的列表。它们是可变的,可以存储任意数量的元素。但是它们与 Python 列表的不同之处在于,它们也只能存储一种数据类型。然而,有一种方法可以解决单数据类型的问题,我将在后面讨论。

让我们来看看语法。

请注意,我们使用符号:=来简化声明和实例化。这在很多情况下是没问题的,但是只在函数内部。

您可以在外部作用域中声明变量,但语法不同。你需要做一些像

var b uint = 5

当你像这样声明一个变量时,你可以更好地控制你的数据类型。这里我声明了一个无符号的 int(表示一个非负整数)。我不能用上面的简写来这样做,因为 Go 会认为 b 是 int 类型的。

你可以试着运行上面的代码片段。你会看到我们分别打印出数组的类型和切片的值。

一旦你声明了,比如说,一个切片,当然会有很多相关的语法。实际上很像 Python 的语法。

有时我们说 s 是一个“字符串片段”,以明确数据类型。

当然现在 Python 有了更多的容器类型。例如,Python 的 dict 等价于什么?

地图

像许多其他语言一样,Go 选择调用它们的 hashmap map。

它们很像 Python 的字典。

在 Go 中创建地图的方法有几种,但是一旦创建,Pythonistas 就会非常熟悉。

循环和控制流

在 Python 中,我们当然有 for 循环和 while 循环。Go 的目标是更严格一点,所以他们只有一种语法(或多或少)和一种循环类型。为循环。

但是 Go 的 for 循环与 Python 的不同之处在于,它需要被停止,否则它就不会停止,然后你就有了 while 循环。

让我们比较两种语言中的一些代码。

我将在 Go 文件中添加一些内容,解释一些语法。

我认为在这里有几点意见是适当的。请注意,Go 使用花括号代替缩进,并且没有类似 C 语言中的括号。您还可以在这里看到如何在 Go 中编写 if-else 子句,还要注意这里没有括号,并且 else 关键字应该在两个花括号之间。

当我们迭代一个像上面的数字这样的迭代器时,Go 有一个名为范围的关键字使这成为可能,并默认返回一个索引。Go 支持多种输出,你需要学习何时何地输出什么的基本知识。

经验法则是索引输出到值的左边,布尔值和错误输出到右边。当我们继续看例子时,你可以记住这一点。

如果你没有使用元素的索引,那么你只需要在它的位置使用一个下划线。

for _, number := range numbers {...

在上面的循环片段中,我们使用了一个空的 for 循环作为 Python 中的“while True”。在 Go 中,还可以使用布尔类型(在 Go 中称为 bool ),这样就变成了真正的 while 循环。

for someBool {...

Go 还有一个 else-if 语句,相当于 Python 的 elif 当然,语法是

} else if ... {

转换

当一个值有多种可能性,并且需要在程序中进行有效的控制流时,Go 中的 switch 语句非常有用。在 Python 中,你必须做很多 if-elif-else 语句,但是在 Go 中你可以做以下事情。

这个语法几乎是不言自明的。如果没有其他选择,默认块将运行,类似于“else”。这不是强制性的,您可以跳过它,如您在顶部开关块中看到的那样。注意,Go 在这里借用了 Python 中的冒号和缩进,以使其可读性更好。

错误处理

在 Go 中,错误处理与许多其他语言有很大不同。我个人喜欢,但不是所有人都喜欢。

Go 中的错误通常是从函数中返回的。所以下面是一个常见的模式

你当然可以打印错误信息或者让 go 在所谓的死机中关闭。这条线

panic(message)

将打印出消息并关闭程序。

两颗北极指极星

Go 是一种低级编程语言。这意味着你可以很好地控制你的电脑。特别是,你可以用指针访问内存地址。这有很多好处。当您需要对某个数据类型(比如某个函数或方法)进行永久更新时,这尤其有用(后面会详细介绍)。

指针的语法很简单,非常像 c 语言。

在下面的例子中,我们创建一个 int a 并获取它的内存地址,并将其存储在变量 b 中。

这段代码将打印出如下内容

0xc0000140b8
5

注意,我们使用解引用操作符(星号)*来取回内存地址保存的值。

结构和方法

当然,Python 是一种面向对象的编程语言,也就是说,它支持这些被调用对象的类和实例。事实上,在 Python 中,几乎所有东西都是对象。从函数到字符串和生成器,它们都是对象。如果你不相信我,你可以试着在一些数据上调用内置函数 dir ,打印输出,你会看到你可以在给定对象上调用的属性和方法。

在围棋中,事情就大不一样了。

Go 不是面向对象的语言,因此它没有类、类方法或对象。然而,正如你现在将看到的,它确实有对等物。

Go 有结构。像 C 语言中一样,这些类似于 JavaScript 中的对象,在某种意义上类似于 Python 中只有字段的类。

基本语法如下:

你可以在 Go 中使用 type 关键字创建一个 struct,这个想法就像 Python 中的类一样,你可以创建自己的数据类型。

像类一样,Go 也提供方法,它们非常像 Python 的方法,除了它们不是在结构内部定义的,而是在结构外部定义的。

让我们看看他们的行动。在上面增加以下内容。

你可以看到我们在 Go 中定义方法的方式很像函数,除了我们在参数前的括号中定义它属于哪个结构。

还要注意,它接受指针类型,而不是结构本身的实例。如果我去掉星号,简单地创建一个如下形式的方法

func (p person) setSkill(skill string) {
p.skills = skill
}

那这个就不行了。原因很简单。我想永久地改变该结构的实例!我不想只得到改变后的值,而让它保持不变。我当然可以这样做,但这不会永远改变结构。相反,如果我在内存地址(指针指向的地方)改变值,那么结构体的实例就会改变值,直到我们再次改变它。

那么你可能会问,为什么(在第 12 行)我们不需要传递一个指向方法的指针?我们有 p 而没有T10 p

好吧,实际上你可以这样做

(&p).setSkill("Coding Go")

但是 Go 编译器足够聪明,能够理解你想要的实际上是一个指针,而不是结构本身的实例,所以这只是上面括号中的语法糖——丑陋。

方法中指针的概念会让很多初学者感到困惑,但是你应该记住,如果你想永久地改变一些东西,那么就使用指针方法。如果你只是想使用一些值,那么使用结构本身。

接口

Go 的一个非常好且有用的特性是接口的概念。你应该把一个接口看作是一个共同的标准,它把具有相同方法的结构粘合在一起。

更准确地说,接口是方法的集合,所以如果一个结构正好有那些方法,那么它满足接口,我们可以互换使用接口和结构及其方法。

假设我有一个圆形结构和一个方形结构。它们都有周长方法和面积方法,具有相同的参数和输出。

然后我们可以声明一个包含这些类型方法的 shape 接口。

让我们看一个这种情况的经典例子,注意我们导入的包周围的括号——这是多个导入的语法。

重点是,即使函数 measure 采用一种类型的形状,也可以接受类型的矩形圆形。这个概念被称为多态性,Go 通过接口支持它。

你有没有想过 Println 函数如何能够打印不同的字体,或者 len 函数如何能够计算不同字体的长度?

这是因为接口。

当然,在 Python 中,这也是可能的,因为它是面向对象的语言。您可以简单地访问 dunder-method len()并返回它。

一个非常有用的界面的例子是空界面。

interface{}

每个结构都满足空接口,因此这个接口表示任何类型。

还记得我告诉过你,在数组和切片中有一个单一类型的解决方案吗?答案是接口。

我们可以对某个接受多种类型的接口做一个切片。下面的方法可行。

d := []interface{}{1, "Kasper", 3.2, 'A'}
fmt.Println(d)

注意,切片的最后一个条目是一个用单引号括起来的字符

空接口是一个不错的技巧,但不完全是最佳实践。为了避免错误,人们应该总是尽可能地严格。也就是说,可能没有其他解决办法。

并发和 Goroutines

在很多情况下,用 Python 并行化代码是一个挑战。

现在,Go 是一种现代语言,内置了对并发性和并行性的支持。他们甚至有一个关键词。

当然,重要的是要意识到并发和并行计算是不同的。这本身可能是一整篇文章。高层的理解就目前而言已经足够了。

也就是说,并行计算是指 CPU 在同一时间进行多项计算(使用多个内核或线程)。并发性意味着程序在并行工作器(或线程)之间切换上下文,以便当一个工作器无法继续工作时(由于某种原因被阻塞,或者只是必须等待,例如服务器响应),上下文切换到准备好的工作器,然后从它停止的地方继续工作。这并不意味着工人们同时做任何事情。

在 Go 中可以很容易地做这两件事,而且在很多情况下,你可以同时做这两件事,而 Go 编译器甚至不会让你知道。

在我们开始这条迷人的道路之前,让我们先从你已经遇到过的东西开始,即主要的 goroutine。

无论如何都要运行的主函数实际上是所谓的 goroutine(在其他语言中也称为绿色线程)。它总是在跑。

你应该把一个围棋程序想象成一条河,在这条河中,主线索就是主河流,如果你愿意,这条河的小分支可以产生或分支。

这些分支河流被称为 goroutines,用关键字 go 来命名

请注意背景字符串是如何以没有明显顺序的方式并行打印出来的。这就是在 Go 中并行化代码有多容易。

当然,由于 rase 条件、不安全的数据传输和同步问题,这带来了潜在的危险,但 Go 是智能构建的,因此当然有解决所有这些问题的解决方案。

频道

Go 中的 Channels 是一种数据类型,可以以相对安全的方式将数据从一个 goroutine 传输到另一个 Go routine。

一个例子:

在上面的代码片段中,发生了以下情况:

首先,我们创建一个名为消息、的通道,然后我们从主例程中分支出一个匿名函数(比如 Pythons lambdas ),将消息“ping”发送到通道中。此时,通道被阻塞。如果另一个 goroutine 试图发送消息,该消息将在队列中结束,等待通道被清空/读取,以便它可以接收另一个消息。你可以使用所谓的缓冲区来创建通道,缓冲区可以在阻塞之前接受 x 个消息,但我们不会对此进行详细说明。

然后,我们读取第 11 行的消息,并将其存储在一个名为 msg 的变量中。然后,当然,我们把它打印到控制台上。

关于 Go 程序的生命周期,有一点需要注意。当 main 函数完成时,所有其他 goroutines 也退出,即使这些函数没有完成并且没有返回任何东西。为了展示这一点,让我们来看看下面的内容。

如果你试着运行这个,你会发现我们没有得到一个 ping!这是因为 main 函数(goroutine)在匿名 goroutine 开始打印任何东西之前就结束了。然而,如果你等待它,它会得到打印的东西。下面将打印出所有的 pings。

这是可行的,但不是最佳实践。

在围棋中,我们有所谓的等待组。它的目的是同步所有的 go routine,这样当 main 函数返回时,所有的 go routine 也返回了。

这段代码要好得多,但需要一些解释。

  • 我们已经将函数从匿名函数改为普通函数,只有被调用时才会运行。我们称这个函数为计数
  • 回到主函数中,我们声明一个 WaitGroup 类型的名为 wg 的变量。这基本上是一个计数器。当工作组。Add(x)被调用我们把 x 加到计数器上,当 wg。Done()被称为我们减去 1。
  • 函数 counting 有一个指向 waitgroup 的类型的参数。指针类型是必需的,因为记住我们想要从等待组中永久地 subract 1。
  • counting 函数内部的 defer 语句的意思是“在返回之前,将以下操作作为最后一个操作”。这非常有用,因为有时很难知道事情会以什么顺序发生。在我们的例子中,我们告诉 waitgroup 我们完成了,waitgroup 计数器减 1。
  • 在后台运行函数计数作为 goroutine 之后,我们调用 wg。Wait()将等待 waitgroup 计数器变为 0,然后移动到下一行。

waitgroup 的规则是,每次运行 goroutine 时,都需要向 wait group 添加 1。每当一个 goroutine 返回,你应该减去 1。然后等待所有人完成 wg。等待()。

然而,还有另一种不用等待组的方法。

事实证明,您可以在一个通道上循环,并且只有当通道关闭时,这才会停止。所以这种阻塞特性经常被用来同步你的 goroutines。查看下面的代码,它将给出与上面相同的输出。

非常整洁!我们给函数 counting 一个通道作为参数,并使用该通道与主 goroutine 通信,我们将在该通道上循环并打印出所有发送的消息。回到计数,我们在退出函数之前关闭通道,在主函数中我们现在知道通道已经关闭,我们可以继续了。

select 语句

有时你有多个通道可以读取,很难事先知道哪个通道准备好被读取。你当然不想浪费任何时间,那么我们如何解决这个问题?

答案是另一项名为的杰出发明 select 语句。看看下面的例子。

select 语句与 switch 语句非常相似,只是它在通道之间进行选择。上面是一个很好的例子,说明了什么时候这是有用的。当 c1 准备好被读取时,没有理由等待 c2 通道。这样做的结果是,运行这个只需要 2 秒钟,而不是 3 秒钟。

select 语句还有一个默认的 case,这也非常有用。

命名约定和公共变量

你可能已经注意到,我倾向于保持变量名很短,而不是像 Python 中那样。这其实是故意的。

你看,Go 语言的一部分就是简单性、有效性和简短的名字。这不是开玩笑!当然,和往常一样,名字应该是描述性的,但是你不需要太多。例如,循环中的伪变量应该是一个字母的名称,函数名应该是一个单词,等等。当对审阅者、读者或同事有意义时,使用速记。

此外,变量应该是骆驼大小写,而不是下划线。

但是有一件重要的事情你需要知道。变量首字母的大小写很重要!

在 Go 中,如果你想导出函数和变量以便在其他文件中访问它们,它们应该以大写字母开头。就是这样。然后你就可以从外面接近它们了。如果它们以小写字母开头,那么它们是私有变量,只能在你的文件或作用域中访问。

从这里去哪里

我会推荐一个 Go 连同其他几个链接的游览。

  • 你可以在这里找到围棋之旅:围棋之旅
  • 还有,Go 的官网很棒: Go
  • 官方文档:文档
  • 举个例子也很棒:例子

我希望你学会了一些围棋,并享受这一旅程。我相信这种语言将成为世界上最受欢迎和最受欢迎的语言之一,当然,它已经相当受欢迎了。

理解这种语言有时会有点困难,因为很多标准库在幕后使用接口来做各种各样的事情,比如在后台向数组写入字节,但是如果你坚持下去,你很快就会学会。

编码快乐!

借助 ATOM 和 Streamlit 从原始数据到 web 应用部署

原文:https://towardsdatascience.com/from-raw-data-to-web-app-deployment-with-atom-and-streamlit-d8df381aa19f?source=collection_archive---------39-----------------------

由卡洛斯·穆扎在 Unsplash 上拍摄的照片

介绍

在本文中,我们将向您展示如何创建一个简单的 web 应用程序,该应用程序能够帮助数据科学家在提供的数据集上快速执行预测模型性能的基本分析。用户将能够上传自己的数据集(作为. csv 文件),并以两种方式调整机器学习管道:选择对原始数据集应用哪些数据清理步骤,以及选择要训练和评估的模型。我们将用 50 行代码完成所有这些工作!怎么会?使用正确的库。

  • 我们将使用 ATOM 进行数据处理和模型训练。ATOM 是一个为快速探索机器学习管道而设计的库。如果你想对这个包有一个温和的介绍,请阅读这个故事。
  • 我们将使用 Streamlit 来创建 web 应用程序。Streamlit 是一个流行的库,可以在几分钟内制作出漂亮的数据应用程序。

构建 web 应用程序

建立

开始进行必要的导入并设置 streamlit 的配置。我们选择一个宽布局,以便有空间显示两个相邻的地块。

import pandas as pd
import streamlit as st
from atom import ATOMClassifier# Expand the web app across the whole screen
st.set_page_config(layout="wide")

管道菜单

这个想法是能够从位于侧边栏的菜单中修改机器学习管道。该菜单将由复选框组成,这些复选框将决定将哪些元素(数据清理步骤或模型)添加到管道中,就像一个菜谱,您可以在其中选择自己的配料。

使用st.sidebar可以将对象添加到 streamlit 的侧边栏中。我们将要实施的数据清理步骤是:特征缩放、分类特征编码和缺失值插补。

st.sidebar.title("Pipeline")# Data cleaning options
st.sidebar.subheader("Data cleaning")
scale = st.sidebar.checkbox("Scale", False, "scale")
encode = st.sidebar.checkbox("Encode", False, "encode")
impute = st.sidebar.checkbox("Impute", False, "impute")

之后,我们添加可用于拟合数据的模型。这一次,我们将复选框包装在一个字典中,以便以后能够对它们进行循环(注意,我们使用 ATOM 的模型缩写作为键)。

# Model options
st.sidebar.subheader("Models")
models = {"gnb": st.sidebar.checkbox("Gaussian Naive Bayes", True, "gnb"),"rf": st.sidebar.checkbox("Random Forest", True, "rf"),"et": st.sidebar.checkbox("Extra-Trees", False, "et"),"xgb": st.sidebar.checkbox("XGBoost", False, "xgb"),"lgb": st.sidebar.checkbox("LightGBM", False, "lgb"),
}

注意:确保安装了 XGBoost 和 LightGBM 软件包,以便能够使用这些型号。

数据摄取

侧边栏菜单已经完成,是时候制作应用程序的主体了。第一部分是数据摄取,我们可以上传想要使用的数据集。为此使用 streamlit 的 file_uploader 函数。

st.header("Data")
data = st.file_uploader("Upload data:", type="csv")# If a dataset is uploaded, show a preview
if data is not None:data = pd.read_csv(data)st.text("Data preview:")st.dataframe(data.head())

模型训练和评估

最后,编写将处理数据、训练模型和评估结果的实际管道。注意,这个例子只适用于二进制分类任务。

st.header("Results")if st.sidebar.button("Run"):placeholder = st.empty()  # Empty to overwrite write statementsplaceholder.write("Initializing atom...")# Initialize atomatom = ATOMClassifier(data, verbose=2, random_state=1)if scale:placeholder.write("Scaling the data...")atom.scale()if encode:placeholder.write("Encoding the categorical features...")atom.encode(strategy="LeaveOneOut", max_onehot=10)if impute:placeholder.write("Imputing the missing values...")atom.impute(strat_num="median", strat_cat="most_frequent")placeholder.write("Fitting the models...")to_run = [key for key, value in models.items() if value]atom.run(models=to_run, metric="f1")# Display metric resultsplaceholder.write(atom.evaluate())# Draw plotscol1, col2 = st.beta_columns(2)col1.write(atom.plot_roc(title="ROC curve", display=None))col2.write(atom.plot_prc(title="PR curve", display=None))else:st.write("No results yet. Click the run button!")

这是相当大的一段代码,所以让我解释一下这里发生了什么。开始的 if 语句在侧边栏中创建了一个按钮,如果点击它,就会执行 if 语句中的代码块。只要没有单击该按钮,管道就不会运行。这确保了管道不会在每次单击菜单中的一个复选框后开始运行。 if 语句内的代码块执行以下操作:

  • 创建一个占位符文本块,以便在管道运行时写入一些进度信息。
  • 初始化一个将处理管道的 ATOMClassifier 实例。使用此命令,数据会自动拆分为 80%-20%比率的训练集和测试集。
  • 运行侧栏中每个选中复选框对应的数据清理步骤。
  • 使用 atom 的 run 方法在训练集上训练所有选择的模型。
  • 使用评分方法输出模型在测试集上的表现。
  • 显示所有训练模型的接收机工作特性曲线和精度-召回曲线。display=None 参数对于返回创建的 matplotlib 图形是必需的。

尝试一下

就这样,web 应用程序完成了!让我们试一试。要运行该应用程序,请打开终端并转到文件所在的目录。运行命令streamlit run <name_web_app>.py。web 应用程序将自动在您的默认浏览器中打开。按照此处描述的步骤进行部署。

所示示例中使用的数据是来自 Kaggle 的澳大利亚天气数据集的变体。可以从这里下载。这个数据集的目标是预测明天是否会下雨,在目标列RainTomorrow上训练一个二元分类器。这个例子的完整代码可以在这里找到。

结论

我们已经看到了如何使用 ATOM 和 Streamlit 快速创建一个能够探索基本机器学习管道的 web 应用程序。由于这两个库的灵活性和易用性,添加新模型、允许回归管道、显示一些额外的图表或增加管道的复杂性,都不会花费太多精力来改进 web 应用程序。

相关故事:

  • https://towards data science . com/atom-a-python-package-for-fast-exploration-of-machine-learning-pipelines-653956 a16 e7b
  • https://towards data science . com/how-to-test-multiple-machine-learning-pipelines-with-just-the-less-lines-of-python-1 a16 CB 4686d

有关 ATOM 的更多信息,请查看该项目的 GitHub 或文档页面。对于 bug 或特性请求,请不要犹豫,在 GitHub 上打开问题或给我发电子邮件。

使用 Python 从 Redshift 到 Google 电子表格

原文:https://towardsdatascience.com/from-redshift-to-google-spread-sheet-using-python-fd4b50131940?source=collection_archive---------14-----------------------

读取、写入和格式化电子表格的简化工作流程

作者图片

最近,我试图从亚马逊红移数据库中提取数据,并使用 Python 脚本将其推送到谷歌电子表格中。该脚本的目的是从 Amazon redshift 数据库中读取数据,应用一些业务规则,并将其写入 google 电子表格。

我已经在我的 python 脚本中使用了 gspread 库,它只不过是用于 google sheets 的 python API。使用它,我们可以非常容易地读取、写入和格式化电子表格。

要与 Google API 交互,第一步是在 Google 开发控制台中创建一个项目并启用 API。

  1. 创建一个项目(点击这里):

作者图片

2.给项目命名:

作者图片

3.转到项目仪表板,点击+启用 API 和服务:

作者图片

4.搜索 Google Drive API,点击它并启用它。执行相同的过程来启用 Google 电子表格 API:

作者图片

5.点击创建凭证:

作者图片

6.选择参数并点击我需要什么凭证?

作者图片

7.输入服务帐户名并选择角色:

作者图片

8.现在单击 KEYS 并创建一个 json 格式的新密钥:

作者图片

将下载一个 JSON 文件。我们的脚本中需要这个 JSON 文件。因此将该文件重命名为client _ secret key . JSON

现在转到你的 Google Drive,创建一个 Google Sheet,命名为redshift-to-Google-Sheet。从上面下载的 JSON 文件中复制 client_email 值,并将该 Google Sheet 共享给此 client_email 并具有编辑权限。

至此,我们已经设置好了一切,现在让我们编写 Python 脚本。要使用 python 脚本与电子表格交互,我们必须安装 gspread Python 库。因此,打开终端并运行以下命令。oauth2client 是一个 python 库,用于访问受 OAuth 2.0 保护的资源。

pip install gspread
pip install oauth2client

现在创建一个 Python 文件,并将其命名为 redshift_to_spradsheet py。复制并粘贴下面的代码。

import gspread
from oauth2client.service_account import ServiceAccountCredentialsscope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/spreadsheets","https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive"]credentials = ServiceAccountCredentials.from_json_keyfile_name('client_secretkey.json', scope)
client = gspread.authorize(credentials)

现在让我们添加连接到红移数据库的代码。我使用了 sqlalchemy 库,它方便了 Python 程序和数据库之间的通信。

要安装 sqlalchemy,请键入以下内容:

pip install sqlalchemy

现在将 sqlalchemy 导入到 python 脚本中,并使用 create_engine 建立数据库连接。在连接字符串之后,编写 select 查询(或任何其他 DML)来获取数据并将其存储到 pandas 数据帧中。

from sqlalchemy **import**  create_engine
import pandas as pd*# Connecting to postgresql*
engine = create_engine('postgresql://user:password@host:5439/database')
data_frame = pd.read_sql('SELECT * FROM article_sales;', engine)

要将此数据框写入 google 电子表格,我们必须安装 df2gspread python 库。要安装 df2gspread,请键入以下内容:

pip install df2gspread

现在将 df2gspread 导入到 python 脚本中,并创建一个名为 write_googlesheet 的函数,如下所示:

from df2gspread import df2gspread as d2gdef write_googlesheet(df, spreadsheet_key, sheet_title, starting_cell, overwrite):d2g.upload(df, spreadsheet_key, sheet_title, credentials=credentials, col_names=overwrite, row_names=True, start_cell = starting_cell, clean=overwrite)

这个 d2g.upload 函数将给定的熊猫数据帧上传到 Google Drive,并返回 gspread 工作表对象。这里我已经从电子表格的 url 传递了电子表格键,工作表标题作为电子表格名称(即工作表 1、工作表 2)。要了解更多关于函数参数的信息,请点击此处。

github 链接: redshift_spreadsheet.py

现在运行 Python 脚本,在浏览器中打开红移到 Google-Sheet Google Sheet。您将看到您的 Google 表单已更新了内容。

结论

这篇文章的目的是让人们了解这种类型的实现。可以有许多不同的策略,但我发现它不太复杂,对于天真的开发人员来说容易理解。

从零开始:置换特征对 ML 可解释性的重要性

原文:https://towardsdatascience.com/from-scratch-permutation-feature-importance-for-ml-interpretability-b60f7d5d1fe9?source=collection_archive---------4-----------------------

实践教程

使用排列要素重要性来发现数据集中哪些要素对预测有用-在 python 中从头实现。

由阿诺·塞纳在 Unsplash 上拍摄的照片

介绍

机器学习中的高级主题由黑盒模型主导。顾名思义,黑盒模型是复杂的模型,很难理解模型输入是如何组合起来进行预测的。像人工神经网络这样的深度学习模型和像随机森林、梯度推进学习器和模型堆叠这样的集成模型是黑盒模型的例子,它们在从城市规划到计算机视觉的各种领域中产生非常准确的预测。

黑盒模型图

然而,使用这些黑盒模型的一个缺点是,通常很难解释预测者是如何影响预测的——尤其是使用传统的统计方法。本文将解释另一种解释黑盒模型的方法,称为排列特征重要性。置换要素重要性是一个强大的工具,无论我们使用什么模型,它都允许我们检测数据集中哪些要素具有预测能力。

我们将从讨论传统统计推断和特征重要性之间的差异开始,以激发对排列特征重要性的需求。然后,我们将解释排列特征的重要性,并从头开始实现它,以发现哪些预测因子对于预测 Blotchville 的房价是重要的。最后,我们将讨论这种方法的一些缺点,并介绍一些将来可以帮助我们了解置换特性重要性的包。

统计推断与特征重要性

当使用传统的参数统计模型时,我们可以依靠统计推断来精确地描述我们的输入与输出之间的关系。例如,当我们使用线性回归时,我们知道预测值的一个单位变化对应于输出值的一个线性变化。这种变化的幅度是在模型拟合期间估计的,我们可以使用概率论为这些估计提供不确定性度量。

照片由贾维尔·阿莱格·巴罗斯在乌普斯普什上拍摄

不幸的是,当使用黑盒模型时,我们通常不可能做出这种声明。深度神经网络可能有数百、数千甚至百万个可训练权重,将输入预测器连接到输出预测(ResNet-50 有超过 2300 万个可训练参数)以及几个非线性激活函数。当处理一个如此复杂的模型时,通过分析找出预测器和预测之间的关系变得极具挑战性。

开发特性重要性技术是为了帮助缓解这种可解释性危机。特征重要性技术根据每个预测器改进预测的能力为其分配一个分数。这使我们能够根据预测因子的相对预测能力对模型中的预测因子进行排序。

生成这些特征重要性分数的一种方法是利用随机排列的力量。下一节将解释如何使用 python 执行置换要素重要性。

置换特征重要性

特性重要性背后的思想很简单。对预测有用的输入包含有价值的信息。如果您通过随机打乱特征值来破坏这些信息,那么您的预测质量将会下降。如果质量下降很小,那么原始预测器中的信息在确定您的预测时并不十分有效-没有它,您的模型仍然很好。此外,如果下降幅度很大,那么原始预测值中的信息会对您的预测产生很大影响。

这个想法通过三个简单的步骤实现。假设您已经训练了一个 ML 模型并记录了一些预测的质量度量(例如 MSE、对数损失等)。对于数据集中的每个预测值:

  1. 随机打乱预测值中的数据,同时保持其他预测值不变
  2. 基于置换值生成新的预测,并评估新预测的质量
  3. 通过计算新预测相对于原始预测的质量下降来计算要素重要性分数

计算完所有要素的要素重要性分数后,可以根据预测有用性对其进行排序。为了帮助更具体地解释排列特征的重要性,考虑下面的综合案例研究。

案例研究:预测房价

注意:代码在最有指导意义的时候被包括在内。请点击此处 了解本指南的完整代码

假设 Blotchville 的 10000 套房屋的价格由四个因素决定:房屋颜色、邻里密度得分、邻里犯罪率得分、邻里教育得分。Blotchville 的房子不是红色就是蓝色,所以颜色被编码成二进制指示器。三个量化分数标准化,近似正态分布。根据下面的数据生成公式,可以从这些因素中确定房价:

数据生成方程

该数据集还包含其他五个与房价无关且没有预测能力的预测因素。这里是数据集前五行的快照,df

数据集的快照

假设我们要训练一个模型,从其他九个预测值中预测价格。我们可以使用任何黑盒模型,但是为了这个例子,让我们训练一个随机森林回归器。为此,我们将数据分为训练和测试数据集。然后,我们使用 sklearn 拟合一个简单的随机森林模型。

from sklearn.model_selection import train_test_split 
from sklearn.ensemble import RandomForestRegressorX = df.drop(columns = 'price')
# One-hot encode color for sklearn
X['color'] = (X['color'] == 'red')
y = df.price# Train Test Split
X_train, X_test, y_train, y_test = train_test_split(X, y,test_size=0.33, random_state=42)# Instantiate a Random Forest Regressor
regr = RandomForestRegressor(max_depth=100, random_state=0)# Fit a random forest regressor
regr.fit(X_train, y_train)

此时,请随意花些时间来调整随机森林回归器的超参数。但是,由于这不是关于超参数调整的指南,我将继续使用这个简单的随机森林模型——它可以很好地说明置换特征重要性的有用性。

评估回归预测质量的一个常用指标是在测试集上评估的均方根误差(RMSE) 。让我们计算模型预测的 RMSE,并将其存储为rmse_full_mod

from sklearn.metrics import mean_squared_errorrmse_full_mod = mean_squared_error(regr.predict(X_test), y_test, squared = False)

现在,我们可以通过改组每个预测器并记录 RMSE 的增加来实现置换特征重要性。这将允许我们评估哪些预测因子对预测有用。下面是从头开始做这件事的代码。看看你是否能把这段代码的注释和我们之前的算法匹配起来。

# Initialize a list of results
results = []# Iterate through each predictor
for predictor in X_test:# Create a copy of X_testX_test_copy = X_test.copy()# Scramble the values of the given predictorX_test_copy[predictor] = X_test[predictor].sample(frac=1).values# Calculate the new RMSEnew_rmse = mean_squared_error(regr.predict(X_test_copy), y_test,squared = False)# Append the increase in MSE to the list of results results.append({'pred': predictor,'score': new_rmse - rmse_full_mod })# Convert to a pandas dataframe and rank the predictors by score
resultsdf = pd.DataFrame(results).sort_values(by = 'score',ascending = False)

得到的数据帧包含置换特征重要性分数。大的分数对应于 RMSE 的大幅度增加——当预测因子被打乱时,模型表现更差的证据。在检查该表时,我们看到四个数据生成预测因子(教育、肤色、密度和犯罪)具有相对较大的值,这意味着它们在我们的模型中具有预测能力。另一方面,五个虚拟预测值具有相对较小的值,这意味着它们对于进行预测并不那么有用。

排列数据帧的结果

我们还可以使用 matplotlib 绘制置换特征重要性分数的图表,以便于比较。

置换特征重要性图

从这个分析中,我们获得了关于我们的模型如何做出预测的有价值的见解。我们看到,在我们的模型中,教育分数是预测房价时提供最有价值信息的预测因子。房屋颜色、密度分数和犯罪分数似乎也是重要的预测因素。最后,五个虚拟预测值似乎没有太多的预测能力。事实上,由于去除虚拟预测因子 3 实际上导致了 RMSE 的降低,我们可以考虑进行特征选择,并在未来的分析中去除这些不重要的预测因子。

排列特征重要性的缺点

马丁·埃斯特夫在 Upsplash 拍摄的照片

虽然我们已经看到了排列特性重要性的许多好处,但是承认它的缺点也同样重要(没有双关的意思)。以下是使用排列特征重要性的一些缺点:

  1. 计算时间:这个过程可能计算量很大,因为它需要你迭代每个预测器并做出预测。如果做预测并不便宜,或者如果你有很多很多的预测者,这可能是昂贵的。
  2. 存在多重共线性时性能不佳:如果数据集具有相关要素,排列要素重要性的性能会很差。如果一个预测器中的信息也存储在相关的预测器中,那么当这些预测器中的一个被打乱时,该模型仍然可以很好地执行。
  3. 分数是相对的,不是绝对的:排列重要性分数显示了模型中特性的相对预测能力。然而,这些分数实际上没有任何脱离上下文的有意义的价值——任何分数都可能根据其他分数而变得很好或很差。
  4. 特征重要性仍然不是统计推断:特征重要性技术只能告诉你一个预测器有多有用——它们不能提供对关系本质的任何洞察(例如线性、二次等。)或预测器效果的大小。排列特征重要性不是统计推断的替代品,而是在无法执行传统推断时的替代解决方案。

结论

置换特征重要性是工具箱中的一个有价值的工具,用于分析黑盒模型和提供 ML 可解释性。有了这些工具,我们可以更好地理解我们的预测者和我们的预测之间的关系,甚至执行更有原则的特征选择。

尽管我们从头开始实现了排列特征重要性,但是有几个包提供了排列特征重要性的复杂实现以及其他模型无关的方法。Python 用户应该查看eli5alibiscikit-learnLIMErfpimp包,而 R 用户则转向imlDALEXvip

烫发快乐!如果你有任何问题,欢迎留言,我会尽我所能提供答案。

致谢:非常感谢出色的克莱尔·霍夫曼校对和编辑了这篇文章,并忍受了我对牛津逗号的忽视。我也很感谢 Leo Saenger 阅读了这篇文章并提供了他的建议。

建立 conda 环境的完整指南

原文:https://towardsdatascience.com/from-soup-to-nuts-guide-for-setting-up-a-conda-environment-58afc7c4801?source=collection_archive---------12-----------------------

conda 的全面指南,从选择安装程序到设置环境、通道和安装包

在 Unsplash 上 veeterzy 拍摄的照片

动机:

你好!Conda 是数据科学社区中最受欢迎的工具之一,然而,理解实施该步骤的步骤和成本可能会令人困惑,因为几乎没有一个地方解释过,所以我决定写一篇。

我将关注三个主题,第一个是关于 conda 安装程序选项,Anaconda,miniconda 和 miniforge,如果不使用它们,你会错过什么。第二个主题将是关于建立一个环境,你可以可靠地用于多个项目,以及当你需要更多的配置时如何修改。最后一部分是关于渠道与环境和包装的关系,这也是一个被忽视的话题,但如果你想以最小的麻烦生产你的作品,这对于展示良好的工程技能是非常重要的。

PS:我用的是 macOS Catalina 10.15.7,用的是 Conda 4 . 9 . 0 版本。如果您对具体版本有疑问,请留下评论。

TL;博士?

所以,我向您承诺,到本文结束时,您可能会了解如何通过机会成本在以下两者之间进行选择来设置您的 conda 环境:

  • 迷你康达和迷你锻造 安装工
  • 环境 命名为唯一和标准
  • 针对您的环境全局添加 通道
  • 从不同渠道安装

希望你喜欢,我会在最后见到你!

康达

超能力者康达

conda 是一个开源的、跨平台、 依赖环境 管理工具——理论上——适用于任何语言(但大部分支持在 数据科学和机器学习特定语言 上,如 Python、R、Ruby、C/C++、FORTRAN、…)。Anaconda 是首先开发它的公司,然后在 BSD 许可下开源。它拥有比 pip 和 virtual env 加起来还多的功能。Pip 是 Python 之上的一个包管理器,用于有限数量的库,也就是说,它不能安装 Python。Virtualenv 是一个简单的环境管理器,根本不能安装包…我猜你在这一点上确信使用 conda,所以我们可以继续!

安装康达的前三名安装工分别是 Anaconda 、 miniconda 和 miniforge 。前两个由 Anaconda 开发,并在其网站上提供,而 miniforge 是由社区最近创建的,因为 miniconda 不支持aarch64架构的。

如果您需要特定的需求,比如在 aarch64(arm64)或 ppc64le (POWER8/9)架构上运行您的模型,您应该使用 miniforge 安装。它还支持 PyPy,这是 Python 的一个轻量级版本。在安装过程中,它将conda-forge设置为默认的——也是唯一的——通道,并且没有defaults通道。我们将在下一部分更详细地讨论通道。

使用 miniforge 的另一个原因是 Anaconda/miniconda 上的商业使用限制(*)是由于最近在[Term Of Service of Anaconda](https://www.anaconda.com/terms-of-service),上的一个变化,在那里将存储库用于商业活动被宣布为违规,这包括使用从defaults通道安装的包。

此外,有几个开源项目已经从 mini-conda 转移到 miniforge,这个和这个,这表明支持这个回购的社区将会增加。

如果你喜欢 ToS 并且不需要架构需求,我们有两个选择,Anaconda 或者 miniconda。如果您想要提供一次性安装的完整版本,并且您有 5GB 的磁盘空间,Anaconda 将为您安装 Python + 250 包。对于新手来说,它可能是一个不错的选择,因为它有现成的常用包,以及 Anaconda Navigator 等应用程序,您可以在这些应用程序中为您的环境启动 JupyterLab、pySpider IDE。Anaconda 也有多个版本,即个人版是免费版本,企业版是为您的团队,如果你想扩展和管理定制的软件包和渠道。

我们的最后一个选择是最小安装程序miniconda将是一个很好的选择,因为它将建立defaults通道。*它比 Anaconda 安装要好,因为您了解了更多关于下载哪些包的信息,并且您不必释放 5 GB 的空间。

PS:如果你觉得你错过了 Anaconda Navigator,Spyder 你可以用 conda 安装,第一个在默认通道有,Spyder 两个都有。

$ conda install anaconda-navigator
$ conda install spyder

🛑也有不同的方法来运行我们的安装程序:

  • **仅 miniconda, miniforge 尚不支持。
  • Cloud VM :如果你想隔离你的环境,在云上运行,只有miniconda有 AWS 的 AMI images 的报价。
  • 容器 : Docker 安装程序可用于: miniconda 和 miniforge

帕克森·沃尔伯在 Unsplash 上拍摄的照片

环境创造

Conda environment是一种组织多个包及其依赖关系的抽象方式。我们创建的任何新环境都有一个目录,所有的包都将下载到这个目录中,并且与这个环境相关的任何配置和历史都将存储在这个目录中。如果您已经安装了 Anaconda 的安装程序,它会在anaconda的安装目录下创建一个名为base的环境。您可以通过运行conda env list命令来检查这一点:(*)指的是默认环境(当我们没有主动使用任何环境时)。

$ conda env list
# conda environments:
#
base        *  /Users/ebrucucen/opt/anaconda3

这很好,但是我们想要我们自己的环境。关于如何命名环境,有两个约定。

首先,你可以给你的环境起一个独特的名字。这个实现为 Python 的每个版本创建了一个环境(因为它是我们都感兴趣的主要语言,对吗?),比如分别针对 Python 3.7 和 Python 3.8 版本的conda-py37env-py3.8。这很好,如果你是环境新手,可能你不会有很多版本的 Pythons,有多个复杂依赖树的包。您可以从任何项目文件夹访问您的环境,并在执行涉及环境的命令时遵循 conda 文档,不会出现任何问题,因为环境将设置在标准位置(/user/.../envs/)

为了创建一个环境,我们使用conda create命令,后跟环境名,以及一个 package=version 对列表,其中版本是可选的,代价是安装最新的版本。

*$ conda create --name env-py3.8 python=3.8 numpy=1.19.5*

第二个选项是使用 通用名称 到您的所有环境,并为每个项目文件夹创建一个新的,例如conda-env.这意味着,对于您正在处理的任何项目文件夹,您可以以相同的方式引用环境名称,并以一致的方式在您的任何自动化脚本中使用。请注意,子命令--prefix只与--name相互作用,小心选择你的毒药!

*$ conda create  --prefix /<possibly a long path>/conda-env python=3.7# or if you are already on the same directory:$ conda create  --prefix ./conda-env python=3.7*

马克斯·库库鲁兹亚克在 Unsplash 上拍摄的照片

环境激活

无论您选择了哪种命名约定,现在您都有了一个环境,(env-py3.8 或 conda-env 或两者都有(!)),接下来我们需要做的是激活,这样我们就可以开始将软件包安装到这些环境中:

*$ conda activate env-py3.8*

它(默认情况下)在命令行上显示环境名,准备接受下一组指令…

*(env-py3.8) $*

或者

*$ conda activate ./conda-env*

结果不是很漂亮的展示,而且肯定没有很好的利用你的空间

*(/<possibly a long path>/conda-env) $*

要改变这种行为,只显示环境名,您可以修改.condarc文件(默认情况下在您的主目录下,~/)。condarc,如果你不确定能在conda config — show-sources前找到答案:

*conda config --set env_prompt '({name})'*

现在,如果你已经设法跟随我到这一点,我们应该有一个环境,激活等待我们安装软件包。

如果你想放松一下,深入一下,看看 env 文件夹的子目录,其中conda-meta文件夹包含history文件来跟踪这个环境中的每个动作,每个包的 JSON 文件列出了它的编译号、依赖项和文件位置…如果你发现/知道任何有趣的事情,请留下评论,这将有助于我们更好地理解环境之谜。我们需要软件包,而channels帮助我们获得正确的版本和依赖关系,让我们开始下一步吧!**

科迪·韦弗在 Unsplash 上拍摄的照片

频道

通道是我们的包的仓库。单独维护的每个通道可能有不同版本的包,每个版本有不同的内部版本,并且相同版本的包在每个通道中可能有不同的依赖关系。查看 Stackoverflow 问题以获得更多相关讨论。

一个很好的例子是最常见的两个包,NumPy 和 Tensorflow,其中 Anaconda 的 defaults channel 和 conda-forge 有不同的版本。

**numpy                         1.19.5  py39he588a01_1  conda-forge
numpy                         1.19.2  py39he57783f_0  pkgs/maintensorflow                    2.0.0 mkl_py37hda344b4_0  pkgs/main
tensorflow                    1.14.0      hcba10bf_0  conda-forge**

为避免混淆,这并不意味着我们要安装 tensorflow 2.0.0 版本时引用 conda-forge 通道,而是意味着 conda 将尝试使用 tensorflow 2.0 模块的默认通道,并为每个依赖项确定 conda-forge 的优先级,作为回报,您将获得:

**_tflow_select      pkgs/main/osx-64::_tflow_select-2.3.0-mklabsl-py            conda-forge/osx-64::absl-py-0.11.0-py37hf985489_0...tensorboard        pkgs/main/noarch::tensorboard-2.0.0-pyhb38c66f_1tensorflow         **pkgs/main/osx-64::tensorflow-2.0.0**-mkl_py37hda344b4_0tensorflow-base    pkgs/main/osx-64::tensorflow-base-2.0.0-mkl_py37h66b1bf0_0tensorflow-estima~ pkgs/main/noarch::tensorflow-estimator-2.0.0-pyh2649769_0termcolor          conda-forge/noarch::termcolor-1.1.0-py_2werkzeug           conda-forge/noarch::werkzeug-1.0.1-pyh9f0ad1d_0**

添加频道

如上所述,miniconda 和 Anaconda 安装的默认通道是defaults通道,而对于 miniforge,默认通道是conda-forge通道。我们可以通过查看配置文件来显示我们的通道(不管您是否处于激活的环境中):

**$ conda config --show-sources**

其结果与此类似(您的会略有不同):

**==> /Users/ebrucucen/.condarc <==
auto_update_conda: False
ssl_verify: True
channels:- conda-forge- defaults**

当您在激活的环境中时,您可以全局地或本地地向您的环境添加通道。对于全球安装,您可以调用conda config add conda-canary 来测试要在 24 小时内发布的包

**$ conda config --add channels conda-canary**

我们还可以创建特定于环境的通道。假设我们想在 env-py3.8 环境中安装基因组相关的包,然后我们可以激活一个环境,向它传递--env参数,并向它添加 bioconda 通道:

**$ conda activate env-py3.8
(env-py3.8) $conda config --env --add channels bioconda**

结果将与此类似(您可能有/可能没有默认通道)

**(env-py3.8) $conda config --show-sources==> /Users/ebrucucen/.condarc <==
auto_update_conda: False
ssl_verify: True
channels:- conda-canary- conda-forge- defaults==> /Users/ebrucucen/opt/anaconda3/envs/env-py3.8/.condarc <==
channels:- bioconda- defaults**

附加频道

您可能已经注意到,add命令修改了配置文件,将最新的附加通道放在列表的顶部。conda 对频道的顺序很固执,因为它本质上是一个优先列表。如果我们的新通道应该到底部,而不是顶部,我们可以使用append参数(或者修改配置文件,我听到了)

**(env-py3.8) $conda config --env --append channels test-channel**

如果我们检查配置文件,我们将看到我们的通道是最后一项(是的,你是对的,在执行 add/append channel 命令期间没有通道验证发生,但是当你想要搜索/安装包时它将出错)

**(env-py3.8) $conda config --show-sources==> /Users/ebrucucen/.condarc <==
auto_update_conda: False
ssl_verify: True
channels:- conda-canary- conda-forge- defaults==> /Users/ebrucucen/opt/anaconda3/envs/env-py3.8/.condarc <==
channels:- bioconda- defaults- test-channel**

移除频道

如果你想删除一个频道(要么是你犯了一个错误,要么是你不再需要它),就像运行--remove参数一样简单,同样的原理,你需要指定--env标签来从激活的环境中删除频道,否则,conda 会给出一个错误,告诉你它找不到这个频道。

**(env-py3.8) $conda config --env --remove channels test-channel**

照片由沃洛季米尔·托卡在 Unsplash 上拍摄

包装

最后,我们现在可以安装我们的软件包了。为了找到你需要的,我推荐 Anaconda search ,它给出了每个包的版本和下载,你可以更好地了解你的选择,另外你可以为你的包找到好的jupyternotebooks**

由于每个环境都有一个按优先顺序排列的通道列表,任何安装都将逐个检查版本(如果指定)是否可用。

**$ conda search spyder**

我安装软件包的 6 大方法是:在特定的环境下,特定的版本,特定的版本(可能是天书),从特定的渠道,有依赖或者没有依赖。对于前 3 种,我们可以使用这种格式:

**$ conda install -n <env-name> -c <channel> <package_name>=<version>=<build_string>$ conda install -n env-py3.9 -c conda-forge numpy=1.19.5=py39he588a01_1**

默认情况下,conda install 会安装相关的软件包。我们应该明确地告诉他们我们不想要依赖(danger Williams,我假设我们知道我们在这一点上在做什么)。

**$ conda install -c conda-forge numpy --no-deps**

战斗号令

感谢您的耐心,并通过我的帖子阅读。现在,你已经有了一个 conda 设置的环境和通道,可以安装你需要的任何包(以及 Pip 和其他工具),正如我在每个选择背后所承诺的那样。希望你喜欢。这是一个简单的过程,你可以定制你想要的,比如创建你自己的频道,软件包,将所有可用的支持。祝您愉快!

从 SQLite 到 Pandas——你需要知道的 7 个基本操作

原文:https://towardsdatascience.com/from-sqlite-to-pandas-7-essential-operations-you-need-to-know-c7a5dd71f232?source=collection_archive---------11-----------------------

相信我——这很简单。

兰迪·塔兰皮在 Unsplash 上的照片

大约十年前,当我在做 iOS 开发时,还没有成熟的移动应用程序数据库解决方案,因此,我必须在应用程序中实现自己的数据库。我选择使用 SQLite,这是一种成熟的轻量级关系数据库解决方案。

当我将部分职业重心转向数据科学时,我很高兴地得知 Python 也有管理 SQLite 的 API。重要的是,pandas 是数据处理的首选库,它提供了与各种数据库(包括 SQLite)通信的相关功能。将它们结合使用,我们可以对本地存储和数据操作做很多事情。在本文中,让我们探索一些基本的操作。

1.连接到数据库

为了使用 SQLite 数据库,我们利用了内置的sqlite3模块,它提供了完整的通用 SQLite 数据库操作。下面向您展示了我们如何连接到数据库。

import sqlite3con = sqlite3.connect("test.db")

通过调用connect函数,将会发生两件事。

  1. 该模块将连接到test.db数据库。如果它不存在,它将在当前目录中创建这样命名的数据库。
  2. 这个函数调用将创建一个代表数据库的[Connect](https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection)对象。从现在开始,我们用这个Connection对象执行任何与数据库相关的操作。

如果你不想处理一个物理测试数据库,模块可以通过运行下面的代码在内存中创建一个数据库。

con_memory = sqlite3.connect(":memory:")

为了当前的教程,我们将坚持使用链接到test.dbcon对象。

2.创建新表并插入记录

首先,我们把一些数据放入数据库。为简单起见,假设我们想要两个数据字段(姓名和年级),将有四条记录,如下所示。

names = ['John', 'Mike', 'Jane', 'Bella']
grades = [90, 95, 92, 98]

下面的代码向您展示了我们如何创建一个表并相应地插入这些记录。

新表和记录

  • 就像其他数据库一样,我们首先需要创建一个游标来执行 SQLite 语句。有一点需要注意的是,你可以使用非标准的 *execute* *executemany* 方法直接与 *Connect* 对象在一起,让你的代码看起来更整洁一点,尽管在这个遮光罩下,光标仍然是由 Python 为你创建的。关于是否显式创建光标,这是您的个人选择。
  • 为了在 SQLite 数据库中创建一个表,我们使用了CREATE TABLE table_name (field0 field0_type, field1 field1_type, …)。你可以在 SQLite 网站这里找到支持的数据类型。简而言之,它支持文本、整数、blob(可以用 blob 保存二进制数据)和实数。值得注意的是,SQLite 没有 boolean 类型,您可以考虑使用整数 0 和 1 来表示布尔值。
  • 要插入一条记录,只需调用cur.execute(“INSERT into transcript values (‘John’, 90)”)。但是,要用一个函数调用插入多条记录,您应该使用executemany方法,在该方法中,您将 SQL 语句模板和一个iterator一起传递,后者的项将被顺序添加到模板中。
  • 为了提交所有这些事务来更新数据库,我们在con对象上调用commit方法。

3.查询记录

要查询记录,您可以应用类似的方法——使用execute方法提交所需的 SQL 语句。下面的代码向您展示了我们如何查询按成绩排序的记录。

>>> cur.execute("select * from transcript order by grade desc")
<sqlite3.Cursor object at 0x1103b5ea0>

您可能会注意到,调用execute并没有直接返回我们预期的结果——所有记录。相反,这个调用返回同一个cursor对象。运行 SELECT 语句后,可以将游标视为迭代器。因此,我们可以将它包含在一个列表构造函数中,以显示所有记录。

>>> list(cur)
[('Bella', 98), ('Mike', 95), ('Jane', 92), ('John', 90)]

或者,cursor 对象有内置的方法fetchall来显示记录,或者feathone来检索一个匹配的记录。顺便提一下,为了避免返回值调用execute,我们使用了下划线。

>>> _ = cur.execute("select * from transcript order by grade desc")
>>> cur.fetchall()
[('Bella', 98), ('Mike', 95), ('Jane', 92), ('John', 90)]
>>> _ = cur.execute("select * from transcript order by grade desc")
>>> cur.fetchone()
('Bella', 98)

4.更新记录

为了更新记录,我们使用下面的 SQL 语句语法:update table_name set field_name=new_value, another_field=new_value where condition。应用这个语法,让我们考虑下面的更新。

>>> cur.execute("update transcript set grade = 100 where name = 'John'")
<sqlite3.Cursor object at 0x1103b5ea0>
>>> list(cur.execute("select * from transcript order by grade desc"))
[('John', 100), ('Bella', 98), ('Mike', 95), ('Jane', 92)]

如上所示,我们成功地更新了 John 的分数,这样我们就有了不同的分数顺序。

5.删除记录

要删除记录,我们使用下面的 SQL 语句语法:delete from table_name where condition。不要忽略条件,这一点非常重要,否则会删除表中的所有行,在大多数情况下,这不是我们想要的操作。下面是一个例子。

>>> _ = cur.execute("delete from transcript where name='John'")
>>> list(cur.execute("select * from transcript order by grade desc"))
[('Bella', 98), ('Mike', 95), ('Jane', 92)]

如上所示,我们已经删除了 John 的记录。

6.用熊猫读取 SQLite 数据

用熊猫操纵 SQLite 数据库很好玩。Pandas 提供了一个函数read_sql,它允许我们直接执行 SQL 语句,而不用担心底层的基础设施。

>>> import pandas as pd
>>> df = pd.read_sql("select * from transcript", con)
>>> dfname  grade
0   Mike     95
1   Jane     92
2  Bella     98

本质上,这个函数调用创建了一个DataFrame,从这里您可以利用 pandas 库提供的所有通用方法。

有些人可能见过熊猫功能read_sql_tableread_sql_query。实际上,read_sql函数只是这两个函数的包装器。它将评估输入并调用适当的函数。因此,在我们的日常使用中,我们可以简单地使用read_sql功能,让熊猫为我们做繁重的工作。

7.将数据帧写入 SQLite

在使用 pandas 处理数据之后,是时候将 DataFrame 写回 SQLite 数据库进行长期存储了。Pandas 为此操作提供了to_sql方法。下面显示了一种可能的用法。

>>> df['gpa'] = [4.0, 3.8, 3.9]
>>> df.to_sql("transcript", con, if_exists="replace", index=False)
>>> list(cur.execute("select * from transcript order by grade desc"))
[('Bella', 98, 3.9), ('Mike', 95, 4.0), ('Jane', 92, 3.8)]
  • 不像read_sql,它是熊猫库中的一个函数,to_sqlDataFrame类的一个方法,因此它将被DataFrame对象直接调用。
  • to_sql方法中,您指定要保存DataFrame的表。
  • if_exists参数很重要,因为默认情况下,该参数被设置为“fail”,这意味着当表已经存在时,您不能将当前的DataFrame写入该表——将引发一个ValueError。因为在我们的例子中,由于更新的 GPA 信息,我们想要替换现有的表,我们将if_exisits参数指定为“replace”
  • index设置为False会在保存到表格时忽略DataFrame对象的索引。它与您可能更熟悉的to_csv方法具有相同的效果。

结论

在本文中,我们回顾了使用 Python 内置的 sqlite3 模块来使用 SQLite 数据库的基本操作。正如您所看到的,使用提供的方法,我们可以非常方便地操作常见的 SQL 操作,如插入、更新和删除。本质上,如果您已经了解 SQL,就没有太多的学习曲线。

我们还探索了 pandas 如何与 SQLite 数据库接口。记住接口的诀窍很简单——read _ SQL 是从 SQLite 数据库中提取任何内容,而 to_sql 是将数据转储回 SQLite 数据库。也就是说,假设您的主要数据处理工具是 pandas,相对于 SQLite 数据库,read_sql用于 out,to_sql用于 in。

从教学到数据科学

原文:https://towardsdatascience.com/from-teaching-to-data-science-5d6d712f6a3f?source=collection_archive---------7-----------------------

我是如何以及为什么从教小学转向数据科学的

作者照片

成为你想成为的人

当我第一次开始浏览职业选择时,我几乎立即放弃了数据科学,因为招聘信息中列出了要求:

  • Python、SQL 和/或 R 的编码经验
  • 计算机科学、工程、数学或统计学硕士或博士学位
  • 超过 5 年的数据科学家经验

当时,我的编码技能非常有限,我的硕士学位与数据科学无关,我的职业经历是作为一名小学教师为黑人和棕色人种的儿童争取不平等。已经埋在学生贷款债务中,获得另一个硕士学位似乎不是最好的方法。我认为从事数据科学是一个遥不可及的梦想。

但是,一天下午,当我们像凯瑟琳·强森、米丝蒂·科普兰和索尼娅·索托马约尔一样,结束社会研究单元的“障碍打破者”课程时,我为学生们计划的课程目标在我脑海中回响,大胆地唱道:

“你可以成为任何你想成为的人。”

我热爱教学,热爱教学背后的目的。但我也想探索在课堂之外做出改变的方法。我已经看到了数据对缩小学生阅读和数学技能差距的影响,我渴望使用数据科学作为一种强大的工具来做出改变。

虽然我还没有资格获得数据科学的工作,但我不得不相信自己并投入工作,就像在我之前的破障者一样。以下是我如何利用自己的教师经验,获得了过渡到数据科学领域所需的额外技能。

可转移的技能

一个伟大的老师在某一天会身兼数职——我们是演员、顾问、记者、职业鞋匠,仅举几例。因为我们什么都做,所以我想我的教学经验可以提高我在数据科学家中的候选资格。下面列出了一些传授给数据科学专业的教学技能。

  • 向非技术观众演示— 教师和数据科学家都必须以清晰简洁的方式向精通数据科学以外主题的观众传达信息,无论是 Roblox 还是 ROI。我一天的大部分时间都在给 6 岁的孩子分解概念,比如分数。如果我的一年级学生在自助餐厅的空闲时间兴奋地分享他们如何"将煎饼分成两半、三分之二和四分之三",我相信我可以与商业利益相关者讨论 z 分数的相关性。
  • 数学知识 —虽然只是初级,但我一天中的大部分时间都围绕着数学,包括数据收集和分析。我最喜欢的数学单元,毫无疑问,是三年级课程的第一个单元,“数据和我的班级群体”在开学的前六周,我的学生学会了如何收集、绘制图表和解释数据。每个小组提出一个问题,他们想了解他们同学的一些情况。他们四处收集数据,根据收集到的数据制作条形图或象形图,然后分析结果。在这一单元结束时,我的学生不仅了解了班上最喜欢的魔法生物是什么,还了解了数学与他们的关系。

三年级“数据和我的班级社区”项目—作者照片

  • 数据驱动分析—我想进入数据科学领域的主要原因:利用数据做出更好的决策。在每个单元之前,我们评估了学生在阅读、写作和数学方面已经掌握的知识。基于这些评估,我们找出了哪些主题需要更深入的探讨,或者哪些是我们可以快速回顾的。对于远远落后的学生,我们举行小组干预,并针对他们尚未获得的技能。因为我们使用数据,我们能够监控他们的进展并加快他们的成长。我很自豪地说,每一个在阅读和数学方面落后的学生在年底都达到了年级水平,而已经达到年级水平的学生甚至比以前更强。

获取新知识

尽管一名教师身兼数职,但编程不是其中之一。为了让我成功地过渡到数据科学领域,我需要发展我的技术技能。我从小处着手,首先测试数据科学职业是否适合我。然后我学的越多,我就越投入。我在下面列出了我的步骤,考虑到每个步骤所花费的时间和金钱,我肯定会建议你也按照这个顺序来做。

  • Codecademy,$ 40/月——Codecademy 的数据科学职业道路为我奠定了数据科学的基础,这是我在参加数据科学信息会议后立即去的地方。我没有任何编码经验,但是 Codecademy 指导我如何用 python 和 SQL 编码,然后给我机会自己写出代码。起初它看起来很初级,但我真的很欣赏它课程的简单性。一旦我掌握了足够的编码技能,这个网站就会推出测试我编码技能的项目。我也承认,即使是现在,当我接触新事物时,我仍然会参考 Codecademy。
  • 社区大学可能是免费的,但肯定比大学便宜——我个人支付了 800 美元,因为我就住在旧金山的边界线之外。在旧金山城市学院上课填补了很多知识空白,并让我在数据科学的重要主题上有了很好的复习。有一个学期,我上了多元微积分,线性代数,还有统计和概率。这是一个充满挑战和数学负担的学期,但仍然很有趣。如果你计划参加训练营,我特别建议你提前学习数学课程,如果你还没有的话。训练营的课程在一天内涵盖了一个学期的内容。它没有给学习者足够的时间来消化材料。如果你当地的社区大学也提供其他与数据科学相关的课程,我肯定会建议你也参加这些课程。你学得越多,准备越充分。
  • 训练营,15000 美元——如果你正在考虑从事数据科学方面的职业,并且没有技术背景,我肯定会推荐你加入训练营。没错,这是一笔大的金融投资,但训练营可以帮助你发展数据科学职业所需的技能,并为你提供所需的支持。我目前参加了熨斗的在线兼职课程。起初,我很担心,因为我亲自学习更好,但在线课程仍然提供社区感觉,这很有帮助。在熨斗,您将有 5 个项目可以添加到您的个人资料中。这些项目非常棒,因为你从中获得了如此多的经验——你正在编码、分析结果、向业务涉众展示分析和建议,以及向技术观众展示你的代码。作为一名数据科学家,你正在获得实践经验,到时候你可以和潜在的雇主谈论这些。
  • ****实习,免费——在写这篇文章的时候,我刚刚开始在苹果公司实习,是一名 MVT 数据科学分析师。我要说的是,我上面提到的一切,包括可转移的技能和新知识,都帮助我为面试做好了准备。我很高兴能够利用我在训练营和 Codecademy 中学到的知识来构建和创造可以应用于现实世界问题的模型。实习也是一个很好的社交机会。随着旅程的继续,我会写更多关于这个的内容。

结论

从教学过渡到数据科学是一个漫长的旅程,但至少可以说是一个激动人心的旅程。通过 Codecademy、社区大学和我的训练营,我已经获得了很多技能,我知道我的技能只会随着经验的增加而增加。虽然我时常怀念教书的日子,但我很高兴能利用我的数据科学技能来从事一些有所作为的项目。

所以对于那些没有技术背景的人,不要担心。有志者事竟成。记住,你可以成为任何你想成为的人。

如果你正在向数据科学领域过渡,我很想知道,你是如何利用自己的经验来帮助自己的?

从文本到知识:信息提取管道

原文:https://towardsdatascience.com/from-text-to-knowledge-the-information-extraction-pipeline-b65e7e30273e?source=collection_archive---------0-----------------------

实现信息提取管道,包括共指解析、实体链接和关系提取技术。

我很高兴向大家展示我最近在做的项目。如果你一直关注我的帖子,你会知道我热衷于将自然语言处理和知识图结合起来。在这篇博文中,我将展示我的信息提取数据管道的实现。稍后,我还将解释为什么我认为 NLP 和图的结合是通向可解释人工智能的途径之一。

信息提取管道

到底什么是信息提取管道?简单来说,信息抽取就是从文本等非结构化数据中抽取结构化信息的任务。

我实现 IE 管道的步骤。作者图片

我的信息提取管道的实现包括四个部分。在第一步中,我们通过一个共指消解模型运行输入文本。共指消解的任务是找到引用特定实体的所有表达式。简单来说,它将所有代词与所指实体联系起来。一旦这一步完成,它会将文本分割成句子,并删除标点符号。我注意到,当我们第一次去掉标点符号时,用于命名实体链接的特定 ML 模型工作得更好。在管道的命名实体链接部分,我们试图提取所有提到的实体,并将它们连接到目标知识库。在这种情况下,目标知识库是维基百科。命名实体链接是有益的,因为它还处理实体歧义消除,这可能是一个大问题。

一旦我们提取了提到的实体,IE 管道就试图根据文本的上下文推断出实体之间的关系。IE 管道结果是实体及其关系,因此使用图形数据库来存储输出是有意义的。我将展示如何将 IE 信息保存到 Neo4j 。

我将使用下面摘自维基百科的一段话来带你浏览 IE 管道。

Elon Musk is a business magnate, industrial designer, and engineer. He is the founder, CEO, CTO, and chief designer of SpaceX. He is also early investor, CEO, and product architect of Tesla, Inc. He is also the founder of The Boring Company and the co-founder of Neuralink. A centibillionaire, Musk became the richest person in the world in January 2021, with an estimated net worth of $185 billion at the time, surpassing Jeff Bezos. Musk was born to a Canadian mother and South African father and raised in Pretoria, South Africa. He briefly attended the University of Pretoria before moving to Canada aged 17 to attend Queen's University. He transferred to the University of Pennsylvania two years later, where he received dual bachelor's degrees in economics and physics. He moved to California in 1995 to attend Stanford University, but decided instead to pursue a business career. He went on co-founding a web software company Zip2 with his brother Kimbal Musk.

文字复制自https://en.wikipedia.org/wiki/Elon_Musk,在CC BY-SA 3.0 license下可用。

第一步:共指消解

如前所述,共指解析试图找到文本中引用特定实体的所有表达式。在我的实现中,我使用了运行在空间框架之上的来自 Huggingface 的neural corf 模型。我使用了 Neuralcoref 模型的默认参数。一路上我注意到的一件事是 Neuralcoref 模型不能很好地处理位置代词。我还从一个 GitHub 问题中借用了一个小的改进代码。共指解决部分的代码如下:

如果我们通过 coref_resolution 函数运行示例文本,我们将得到以下输出:

*Elon Musk is a business magnate, industrial designer, and engineer. 
Elon Musk is the founder, CEO, CTO, and chief designer of SpaceX. 
Elon Musk is also early investor, CEO, and product architect of Tesla, Inc. Elon Musk is also the founder of The Boring Company and the co-founder of Neuralink. A centibillionaire, Musk became the richest person in the world in January 2021, with an estimated net worth of $185 billion at the time, surpassing Jeff Bezos. Musk was born to a Canadian mother and South African father and raised in Pretoria, South Africa. Elon Musk briefly attended the University of Pretoria before moving to Canada aged 17 to attend Queen's University. Elon Musk transferred to the University of Pennsylvania two years later, where Elon Musk received dual bachelor's degrees in economics and physics. Elon Musk moved to California in 1995 to attend Stanford University, but decided instead to pursue a business career. Elon Musk went on co-founding a web software company Zip2 with Elon Musk brother Kimbal Musk.*

在这个例子中,不需要高级的共指消解技术。Neuralcoref 模型将几个代词“他”改成了“埃隆·马斯克”。虽然看起来很简单,但这是提高我们 IE 管道整体效率的重要一步。

第二步:命名实体链接

就在最近,我发表了一篇使用命名实体链接构建知识图的博文。这里,我想使用不同的命名实体链接模型。我第一次尝试使用脸书 BLINK 型号,但我很快意识到它在我的笔记本电脑上无法工作。它需要至少 50GB 的空闲空间,这本身不是一个大问题,但它也需要 32GB 的 RAM。我的笔记本电脑只有 16GB 的内存,我们仍然需要管道的其他部分来工作。所以我恢复使用老式的 wiki ifier API,它已经被证明是有用的。而且完全免费。如果你想找到更多关于 API 的信息,看看我以前的博客文章或者官方文档。

在我们通过 Wikifier API 运行我们的输入文本之前,我们将把文本分成句子并去掉标点符号。总的来说,这一步的代码如下:

我忘记提到 Wikifier API 返回一个实体所属的所有类。它查看的实例和类的子类,并遍历整个类层次结构。我决定过滤掉属于个人、组织或地点的实体。如果我们通过管道的命名实体链接部分运行我们的示例文本,我们将得到下面的输出。

维基化过程的一个好处是,我们还可以为实体及其标题获取相应的维基数据 id。拥有 WikiData ids 可以解决实体歧义消除的问题。你可能想知道如果一个实体在维基百科上不存在会发生什么。不幸的是,在这种情况下,Wikifier 不会识别它。不过,我对此并不太担心,因为如果我没记错的话,维基百科有超过 1 亿个实体。

如果你仔细观察结果,你会注意到比勒陀利亚被错误地归类为一个组织。我试图解决这个问题,但维基百科的类层次结构很复杂,通常跨越五六跳。如果有一些维基类专家,我会很乐意听取你的建议。

第三步:关系提取

到目前为止,我已经介绍了所有的概念。我以前从来没有钻研过关系抽取。到目前为止,我们只研究了共现网络。因此,我很高兴向大家介绍工作关系提取流程。我花了很多时间搜索任何可能做得不错的开源模型。我很高兴偶然发现了 OpenNRE 项目。它具有五个开源关系提取模型,这些模型在 Wiki80 或 Tacred 数据集上进行训练。因为我是维基百科的忠实粉丝,所以我决定使用 Wiki80 数据集。在 Wiki80 数据集上训练的模型可以推断 80 种关系类型。我没有尝试过在 Tacred 数据集上训练的模型。你可以自己试试。在 IE 管道实现中,我使用了wiki80_bert_softmax模型。顾名思义,它在引擎盖下使用了 BERT 编码器。有一点是肯定的。如果你没有一个图形处理器,你不会有一个好时光。

如果我们在 OpenNRE 库中查看一个示例关系提取调用,我们会注意到它只推断关系,并不试图提取命名实体。我们必须提供一对带有ht参数的实体,然后模型试图推断出一个关系。

*model.infer({'text': 'He was the son of Máel Dúin mac Máele Fithrich, and grandson of the high king Áed Uaridnach (died 612).', 'h': {'pos': (18, 46)}, 't': {'pos': (78, 91)}})
('father', 0.5108704566955566)*

结果输出关系类型以及预测的置信度。我的用于关系提取的并不完美的代码看起来像这样:

我们必须使用命名实体链接的结果作为关系提取过程的输入。我们迭代一对实体的每个排列,并试图推断出一种关系。正如您在代码中看到的,我们还有一个 relation_threshold 参数来忽略置信度较低的关系。稍后你会明白为什么我们使用排列而不是实体的组合。

因此,如果我们通过关系提取管道运行我们的示例文本,结果如下:

关系抽取是一个很难解决的问题,所以不要期望完美的结果。我必须说,这个 IE 管道工程以及,如果不是比一些商业解决方案更好。显然,其他商业解决方案要好得多。

第四步:知识图谱

当我们处理实体及其关系时,将结果存储在图形数据库中才有意义。我在我的例子中使用了 Neo4j 。

作者图片

记住,我说过我们将试图推断所有实体对的排列之间的关系,而不是组合。看看排行榜的结果,就很难找出原因了。在图形可视化中,很容易观察到,虽然大多数关系都是双向推断的,但并不是在所有情况下都是如此。例如,Elon Musk 和宾夕法尼亚大学之间的工作地点关系被假设为仅在一个方向上。这给我们带来了 OpenNRE 模型的另一个缺点。关系的方向并不像我们希望的那样精确。

工业工程流水线的一个实例

为了不让您空手而归,我将向您展示如何在您的项目中使用我的 IE 实现。我们将通过 Kaggle 上的 BBC 新闻数据集运行 IE 管道。IE 管道实现最困难的部分是建立所有的依赖关系。我希望你保持头脑清醒,所以我建立了一个你可以使用的 docker 图像。运行以下命令使其启动并运行:

*docker run -p 5000:5000 tomasonjo/trinityie*

第一次运行时,必须下载 OpenNRE 模型,所以绝对不要使用-rm选项。如果你想对项目做一些修改并构建自己的版本,我还准备了一个 GitHub 库。

由于我们将把结果存储到 Neo4j 中,您还需要下载并设置它。在上面的例子中,我使用了一个简单的图形模式,其中节点代表实体,关系代表关系。现在我们将稍微重构一下我们的图表模式。我们希望在图中存储实体和关系,同时保存原始文本。拥有审计线索在现实场景中非常有用,因为我们已经知道 IE 管道并不完美。

作者图片

将关系重构到中间节点可能有点违背直觉。我们面临的问题是,我们不能让一个关系指向另一个关系。鉴于这个问题,我决定将一个关系重构为一个中间节点。我本可以发挥我的想象力来产生更好的关系类型和节点标签,但事实就是如此。我只想让关系方向保留它的功能。

将 BBC 新闻数据集中的 500 篇文章导入 Neo4j 的代码如下。你必须让 trinityIE docker 运行,IE 管道才能工作。

该代码还可以在 GitHub 上以 Jupyter 笔记本的形式获得。根据你的 GPU 能力,IE 管道可能需要一些时间。现在让我们检查输出。显然,我选择了有意义的结果。运行以下查询:

*MATCH p=(e:Entity{name:'Enrico Bondi'})-[:RELATION]->(r)-[:RELATION]->(), (r)<-[:MENTIONS_REL]-(s)
RETURN **

结果

BBC 新闻数据集上的 IE 抽取结果。作者图片

我们可以看到恩里科·邦迪是意大利公民。他在意大利众议院任职。另一种关系是推断他也拥有 Parmalat。经过短暂的谷歌搜索,似乎这个数据或多或少至少在可能的范围内。

通往可解释人工智能的道路

你可能会想,这和可解释的人工智能有什么关系。我给你一个真实的例子。这篇研究论文的标题是通过知识图谱完成为新冠肺炎进行药物再利用。我不是医生,所以不要期待详细的介绍,但我可以给出一个高层次的概述。网上有很多医学研究论文。还有在线医疗实体数据库,如 MeSH 或 Ensembl 。假设您在生物医学研究论文上运行命名实体链接模型,并使用一个在线医学数据库作为目标知识库。在这种情况下,您可以提取文章中提到的实体。更具挑战性的部分是关系提取。因为这是一个如此重要的领域,伟大的头脑聚集在一起,提取这些关系。

可能有更多的项目,但是我知道在提到的文章中也使用了 SemMedDB 项目。现在你有了你的知识图表,你可以试着预测现有药物的新用途。在网络科学中,这被称为链路预测。当你试图预测链接以及它们的关系类型时,科学界称之为知识图完成。想象一下,我们已经预测了现有药物的一些新用例,并向医生或药理学家展示了我们的结果。他的回答可能是,那很好,但是你为什么认为这个新用例会工作呢?机器学习模型是一个黑盒,所以这并没有真正的帮助。但是你能给医生的是现有药物和它能治疗的新疾病之间的所有联系。而且不仅是直接关系,还有两三跳之外的关系。我会举一个例子,所以对生物医学研究者来说可能没有意义。假设现有的药物抑制了与疾病相关的基因。药物和疾病之间可能有许多直接或间接的联系。因此,我们已经向可解释的人工智能迈出了一步。

结论

我对这个项目的进展非常满意。在过去的一年左右的时间里,我一直在尝试将 NLP 和知识图结合起来,现在我已经将我所有的知识都集中到了一篇文章中。我希望你喜欢它!

附:如果你想对 IE 管道做一些改动,代码可以作为 Github 库 获得。转载这篇博文的代码也可以作为 Jupyter 笔记本

从文本到表格,老方法

原文:https://towardsdatascience.com/from-text-to-table-the-old-school-way-d7f8ba41dac?source=collection_archive---------50-----------------------

在 Unsplash 上对@fredmarriage 的积分。简单的方法还是困难的方法?小工厂还是大工厂?

利用 Excel 的强大功能从文本文件中获取表格

语境

例如, Y 你有写在 Windows 记事本的文本文件中的数据。两行之间有一些额外的间隔。你通常可以从一个在线网站上复制/粘贴一些随机的行。

目标

您希望获得一个表格,其中每一行对应于文本文件中的一行。

怎么会?

  1. 在 excel 中复制/粘贴整个文本文件
  2. 格式化为表格
  3. 过滤掉空白

就是这样!!

例子

假设您想将哈利波特的引用存储在一个表中,并希望以某种方式进行处理。

我们都爱的五句哈利波特语录!

我通常会将这些引用写在一个简单的文本文件中,如下所示。

我在一个文本文件里写了五段哈利波特的引言。

现在,在以后的某个时候,我决定把它们放在一张桌子上玩,并做一些数据科学。自然地,我可以将这种方法扩展到一千个报价,以便更加精确。但是让我们拿这五个一来证明我们的观点。

首先,如上图所示,我把我的哈利波特引语复制/粘贴到一个 Excel 表格上。

从 txt 文件复制/粘贴哈利波特语录到 Excel。

然后,我需要使用下面突出显示的“ Format as Table ”将我的工作表格式化为表格。

使用突出显示的图标格式化为表格。

最后,我需要过滤掉空白,去掉空行。

取消选择空白!

就这样,我们得到了我们想要的输出。

上述三个步骤的输出。

我可以将我的独特专栏的标题修改如下。

将我独特的专栏重新命名为我最喜欢的标题。

供选择的

对于已经向我指出这种“noob”Excel 方法的数据科学家来说,另一种 Python 方法可以定义如下:

  1. 处理文本文件
  2. 然后将其存储在熊猫数据帧
  3. 最后,将熊猫表保存为 csv/tsv 文件

但是嘿!尽管这种 Python 方法在概念上微不足道,但人们可以注意到它比“老派”Excel 方法要耗时得多。

另外,只要你能完成工作,谁在乎你是不是菜鸟!😉

从围棋到卡格:台湾卡格大师的故事

原文:https://towardsdatascience.com/from-the-game-of-go-to-kaggle-the-story-of-a-kaggle-grandmaster-from-taiwan-5adcd4fff38d?source=collection_archive---------17-----------------------

与郝坤·叶的对话:数据科学家和 Kaggle 大师

作者图片

在这一系列采访中,我在 H2O.ai 展示了一些知名数据科学家和 Kaggle 大师的故事,他们分享了自己的旅程、灵感和成就。这些采访旨在激励和鼓励那些想了解成为一名 Kaggle 特级大师的人。

最近有机会采访了叶坤浩— 一位 Kaggle 竞赛的特级大师和一位数据科学家atH2O . ai。坤浩拥有台湾国立交通大学的计算机科学硕士学位。他的重点是多臂土匪问题和应用于计算机游戏的强化学习,包括但不限于 2048 AI 和计算机围棋。他作为一名软件工程师开始了他的职业生涯,致力于为即将到来的 5G 市场竞争的最新 5G 芯片组产品。

在这次采访中,我们将更多地了解他的学术背景、他对 Kaggle 的热情以及他作为数据科学家的工作。以下是我与郝坤对话的摘录:

您能告诉我们您的背景以及从电子工程到计算机科学,最终到数据科学的转变吗?

:在攻读学士学位期间,我主修电子工程(EE)和计算机科学(EECS)。尽管我在电子工程方面成绩很好,也不擅长编程,但计算机科学(CS)似乎更有趣。从那以后,我在计算机科学上花了更多的时间,甚至攻读了计算机科学硕士学位。

在研究生院,我得到了一位教授吴亦琛(I-Chen Wu)的建议,他主要从事 RL(强化学习)算法在计算机游戏中的应用,如ChessGogame 2048。由于对GoAI的浓厚兴趣,我找到了我的导师。事实上,我甚至梦想成为一名职业围棋手,但我的父母不让我走上他们的职业道路😃。人工智能在当时对我来说似乎很花哨,所以我想做用 AI 下围棋、打败职业选手的研究。我们的实验室叫做 CGI ( 电脑游戏智能)实验室,甚至在电脑奥林匹克中拿了很多奖牌。我还参与了一个 2048 AI 项目,在不同的比赛中获得了几枚奖牌。

毕业后,我在联发科的第一份工作是 4G 和 5G 调制解调器芯片的软件工程师。尽管我在半导体行业工作,但我对机器学习的兴趣从未消退。意识到强化学习需要一段时间才能完全应用于行业,我开始强调监督学习。我报名参加了 Coursera 上的课程,包括吴恩达的— 深度学习专业 ,甚至还有马里奥斯的(H2O.ai 的 Kaggle GransMaster 研究员)— 向顶级 ka ggler 学习, 以使我的基础正确。渐渐地,我开始参加很多 Kaggle 比赛。我的想法是向他人学习,同时运用我的知识解决现实世界的问题。

Kaggle 最初吸引你的是什么,你是什么时候赢得第一次胜利的?

郝坤的 Kaggle 简介 |图片来自 Kaggle

坤浩 : 我加入 Kaggle 并不是因为它有吸引力,而是因为我想通过在知名的数据科学平台上解决问题来证明自己。我的第一枚金牌是在家庭信用违约风险竞赛中获得的,这是一项预测客户还款能力的竞赛。我的团队是一个庞大的团队,他们在非常不同的方面共同努力来提高我们的分数。

你在高尔夫比赛中一直表现出色。是什么让你有动力一次又一次地去竞争。

郝坤在 Kaggle 上的一些令人印象深刻的成绩

坤昊 : 在 Kaggle 上赢了几次之后,我沉迷于做自己喜欢的事情的感觉。我很感激有这样一个平台,在这里我可以与世界各地的人和聪明的头脑联系,证明自己,并在比赛中学习新的东西,帮助更好地解决实际问题!

你在圣诞老人 2020 比赛中获得第十名,成为大师。在 RL 的背景让你在这场比赛中有优势吗?

Kun-Hao : 正如我之前提到的,在读研期间有一些 RL 的经验绝对让我在这样的竞争中有一些优势。

你和 Marios Michailidis 搭档,又名KazAnova他那时已经是 KGM 了。你对与更有经验的卡格勒人合作有什么建议?**

这是一个好主意,首先在一些竞争中证明自己,并尝试所有可能的解决方案。只有这样,与更有经验的卡格勒人合作才是明智的。此外,在你对比赛有了很好的了解后组队是有意义的,因为那时你可以向有经验的卡格勒人询问他们过去在类似比赛中的经验,建议,以及他们将如何处理这些问题。

您被邀请作为 2019 年 Kaggle Days China 的演讲嘉宾。你能分享一些你在那里的经历吗?

郝坤在 Kaggle Days China 发表演讲|图片由坤昊提供(来自个人收藏)

**坤豪😗*2019 年我作为嘉宾演讲嘉宾受邀参加 Kaggle Days China 。这件事发生在加入 H2O.ai 之前,当时我是 Kaggle 高手,在联发科做软件工程师。在活动中,我遇到了 Marios Michailidis 和 Mikhail Trofimov,他们碰巧是我上过的 Coursera 课程的导师。坐在观众席上听他们的演讲是多么激动人心的时刻。我还见到了加博尔·法多尔、德米特里·拉尔科和后来成为我在 H2O 同事的雅亨·巴巴金,并与他们共进晚餐。

作为 H2O.ai 的数据科学家,你的角色是什么,你在哪些具体领域工作?

郝坤在 H2O.ai | H2O.ai 网站

Kun-Hao : 我在 H2O.ai 做一名竞技数据科学家,我还在学习如何扮演好这个角色。具有竞争力意味着:

  1. 我需要不断提高自己的 ML 知识和解决问题的能力,我通过参加 Kaggle 或其他数据科学竞赛平台并取得好成绩来做到这一点。
  2. 运用竞赛经验提高 H2O.ai 的产品竞争力。
  3. 快速学习新事物,并在任何需要的地方提供帮助,这意味着我可以在需要时作为软件工程师或客户数据科学家工作。

目前,我的主要工作是 Kaggle 竞赛,开发 H2O Wave 应用,并帮助 APAC 和中国地区的售前工作。

你通过 Kaggle 学到的最好的东西有哪些是你在 H2O.ai 的专业工作中应用到的?

*

郝坤·叶在 CTDS 讨论他的 SIIM ISIC 黑色素瘤 14 位解决方案。秀场 |图片由 CTDS 秀场提供*

Kun-Hao : 我认为很重要并且主要从 Kaggle 那里学到的一些技能是:

  1. 最先进的机器学习知识,
  2. 如何应用它们解决实际问题,以及
  3. 如何验证模型,以便对看不见的测试用例进行归纳。

这些技能帮助我从软件工程师转变为数据科学家,并在我的工作中发挥了重要作用。然而,我从 Kaggle 身上学到的最好的东西是快速理解问题,寻找现有的解决方案,并自己实施更好的解决方案,这是我几乎在我参加的每个比赛中都重复的方法。

例如,在参加由 Jigsaw 举办的 有毒评论分类比赛之前,我对 BERT 一无所知,也不知道如何使用它,也不知道它背后的想法。我试图从公共内核中学习,改进我的模型,并扩展我的知识,以在排行榜上获得一个好的最终位置(第 9 名)。

在参加 Jigsaw 举办的有毒评论分类大赛之前,我对 BERT 一无所知,也不知道如何使用它,更不知道它背后的想法。我试图从公共内核中学习,改进我的模型,并扩展我的知识,以在排行榜上获得一个好的最终位置(第 9 名)。

在工作中,我和我的同事 Shivam 一起开发了一个优化 Wave 应用程序。在做这个 app 之前,我对纯数值优化了解不多。然而,我们的客户要求这个功能。我们致力于优化应用程序,以扩展我们的云产品的完整性。我研究了不同的现有框架,它们的局限性,它们解决问题的效果如何,并在 Wave 应用程序中创建了一个优化功能的集成版本。我之前对它没有深入的了解,但是当有这样的需求时,我把从 Kaggle 中学到的东西应用到问题中,包括但不限于机器学习相关的问题。

任何喜欢的 ML 资源(MOOCS、博客等)..)您愿意与社区分享吗?

Kun-Hao : 对于基本面,我建议上 Coursera 的在线课程。在准备好所有的基础知识后,我建议投入到比赛中,搜索相关的论文和博客文章。每一篇论文/博客/想法,只要在实际场景(比如竞赛)中起作用/有帮助,都是很好的资源!

对刚刚开始或希望开始数据科学之旅的数据科学有志者有什么建议吗?

图片由坤昊提供|来自个人收藏

Kun-Hao : 我想分享一下我在 Kaggle Days China 上分享的建议。

  1. 从小处着手:定义你的小成功
  2. 胸怀大志:定义你自己的伟大目标
  3. 不断奋斗:努力工作,享受任何微小的成功,不自觉地沉迷于过程。

我从 Kaggle 学到的最好的东西是快速理解问题,寻找现有的解决方案,并自己实施更好的解决方案,这是我几乎在我参加的每个比赛中重复的方法。

外卖食品

坤昊的卡格尔之旅是非凡的,这次采访是了解他背后的努力工作的一个很好的方式。他的口号是从每场比赛中学习一些东西,这是鼓舞人心的,他最近的成功清楚地表明了他对自己技术的掌握。

阅读本系列的其他采访:

  • Rohan Rao:数据科学家从数独到 Kaggle 的旅程
  • 希瓦姆·班萨尔:数据科学家,负责 Kaggle 上的“数据科学为善”竞赛。
  • 认识 Yauhen:第一位也是唯一一位来自白俄罗斯的 Kaggle 特级大师。
  • 苏达莱·拉杰库马尔:对数字的热情是如何将这位机械工程师变成了卡格尔大师
  • 加博·福多尔:卡格尔世界“白鲸”的励志之旅🐋
  • 学习他人对 Kaggle 的成功是必不可少的,本说土耳其宗师
  • 在 Kaggle 上遇见就是不能停止胜利的数据科学家。
  • 如何成为 Kaggle 上的世界第一
  • 赢得一场 Kaggle 比赛需要什么?让我们听听获胜者本人

从健身房到 Jupyter 笔记本——在一天内构建一个蹲起计数器应用程序

原文:https://towardsdatascience.com/from-the-gym-to-a-jupyter-notebook-building-a-squats-counter-app-in-a-day-955ecfbf8d12?source=collection_archive---------35-----------------------

用数据捕捉现实世界中的物理现象,这是一件特别令人满意的事情。作为一名机器学习顾问,我已经习惯了与医疗数据、图像等打交道。但是,当你在屏幕上看到的数据捕捉到移动、位置等信息时,这一切都变得令人耳目一新。因此,当月亮感知的创始人 Andrei 向我挑战,要我在一天内开发一个应用程序,它可以获取我手机的加速度计数据,并利用它做一些很酷的事情时,我非常兴奋。

因此,我开始在一个开发日内构建一个蹲下计数应用程序。

获取数据

在我们过度思考如何量化深蹲的数量和质量之前,先看看一些实时数据是个好主意。Moonsense 可以轻松地将数据从我的 iphone 上传到他们的云存储解决方案,再下载到我的笔记本电脑。这个过程相当轻松:你只需下载一个记录器应用,点击记录按钮,将手机的加速度、陀螺仪和地理信息同步到云端,之后你可以下载到笔记本电脑上。

所以我继续前进,把我的手机拿在手里,开始泵一些铁。这是我把手机放在口袋里做的。

好吧,我跟你说实话。这不是我。图片来源:Adobe Stock Photo 授权。

每次我做一系列深蹲重复动作时,我会点击记录按钮,输入一个自由文本标签,比如“4 次深蹲”。

如果没有必须的低电量电池,这不会是一个好的屏幕截图

就是这样。现在让我们看看如何使用我们的 Moonsense API 键来检索数据。

这个脚本迭代我记录的所有会话,并打印出每个会话的熊猫数据帧和加速度

因此,打印加速度数据帧会得到这样的输出

timestamp         x         y          z
0    1620847740629 -0.471039  5.075854   9.129929
1    1620847804060  3.401349  4.373932  10.150064
..             ...       ...       ...        ...

有道理。我们看到手机在三个方向上感受到的加速度,x,y 和 z 方向肯定与手机的方向有关。

分析我们的第一批录音

让我们把数据画出来,看看它是否更容易理解。

让我们看看它生成的图表。让我们先来看一个会话,在这个会话中,我将设备静止放在我的桌子上:

哼!如果你以前没有处理过加速度计数据,你可能会认为数据几乎为零,但我们看到 z 轴上有一个很大的值。这个数值接近 9.81 米/秒——地球引力。所以我们现在明白了,设备只有在自由落体的时候才会吐出全 0。如果有什么东西顶住了重力,它会报告它是一个向上的力(我们将继续把所有作用在设备上的力称为“加速度”,尽管这肯定是一个误称)。

如果以任意角度拿着手机(例如,系在我的手臂上),这种重力不会整齐地沿着 z 轴排列,而是分散在不同的 x、y、z 轴上。更糟糕的是,如果手机在运动过程中旋转,这种重力测量将以不同的方式在 x,y,z 方向之间泄漏——使我们的数据视图变得复杂。

好了,现在让我们来看一个真正的深蹲训练,让事情变得简单一些。让我们双手握住手机与地面平行,抽出 4 个深蹲。

当我们深蹲着看录像时,我们看到:

  1. 每个深蹲似乎由两座小山组成。一个离 9.81 m/sec 的重力值不远的小的,一个很高的,在那里手机感觉到非常强的向上的推力。
  2. 在两座山之间,我们看到 z 轴上的加速度下降,下降到大约 5-6 米/秒的最小值

下面这个故事解释了我们所看到的现象:

  1. 在我们开始蹲下之前,什么也没有发生,手机准确地感受到了我们阻止它下落的力——9.81 米/秒。
  2. 因为手机并不完全平行于地面,这个力会沿着不止一个轴分解——一部分 9.81 指向 z 轴,一部分指向 y 轴,等等。如果我的手是真正水平的,我们会在 Z 方向看到精确的 9.81,而在其他方向什么也看不到。
  3. 当我们蹲下时,该设备几乎是自由落体——因此它感受到的力从 9.81 减小。观测值与 9.81 的差值,大致就是我们的向下加速度。
  4. 最后,当我们深蹲到底时,我们施加了很大的向上的力——足以克服重力并突然改变手机的运动方向。太多了!因此,我们确实看到手机报道的测量值直线上升。

好的,那么我们从这个分析中得到什么呢?

  1. 尽管手机的整体运动基本上是在一个上下运动的维度上,但它不固定的方向让我们的生活有点困难,因为我们需要弄清楚“下”的整体方向是什么。
  2. 虽然我们看到的整体运动相当复杂,但简单地计算大峰的数量似乎就等于我们记录的蹲下次数。

计数峰值

在上图中,我手动覆盖了一个大的 1,2,3,4 数字来计算深蹲的重复次数。我们现在的目标是在代码中复制让我做这个计算的逻辑。所以我们来试着分解一下。我们在找什么?

  1. 明显高于重力的加速度峰值(因此 12+米/秒可能是一个很好的阈值)。
  2. 当然,一旦我们达到峰值加速度,我们将得到许多超过 12 的重复测量,所以我们希望将它们聚集成连续的段。超过 12 的连续测量值显然属于同一个深蹲重复,不应该重复计算。
  3. 为了简单起见,我们只看 Z 轴,假设这是整个运动方向。听说过主成分分析的人可能已经知道,如果手机的方向是其他固定的方向,我们有一种方法来计算出运动的实际方向。但不管怎样,这是以后的事了。

所以这是一种天真的方法,但是让我们看看它会带给我们什么,一旦我们看到它是如何失败的,我们就改进它。

让我们来看看它生成的图表:

好吧!我们真的快到了。首先出现的是,我们已经确定了我们希望在这里看到的 4 个真正的峰值。但是我们也有一些错误的峰值——比如在 0.5 秒标记处的瞬时峰值(你可以在那里看到一个单独的橙色标记)。或者类似地,在我们第一个真正的红色峰值之前有一个绿色标记。显然,我们需要以某种方式拒绝非常小的异常值观察。也许我们可以抛弃所有只损失了很短持续时间的片段。但是这就足够了吗?

for start_loc,end_loc in zip(segment_starts, segment_ends):print(t[end_loc] - t[start_loc])0.03999999999999998
0.03999999999999915
**0.43900000000000006**
0.08000000000000007
**0.359
0.7590000000000003**
**0.19900000000000162 * note: this corresponds to the gray segment**
**0.3990000000000009**

很接近,但没有雪茄。如果我们拒绝非常短的峰,我们将消除 3 个假阳性,但从我们的图中可以看到,我们的最后一个峰意外地分裂成 2 个灰色和芥末色的亚段。如果我们仅仅依赖于段时间长度,我们的代码将会非常脆弱。基本上,在我们的高加速度阈值以下的单个瞬间下降总是可以将我们的部分分成 2 部分。

所以让我们做最后一次尝试来改进它。让我们对信号进行预处理,使其对像这样的瞬间失误具有鲁棒性。

平滑曲线

我的本科专业是物理和电子工程,所以我认为我不得不承认,这一部分最终只是一个低通滤波器的应用,旨在抑制我们信号的高频成分。

但你不需要了解数字信号处理的第一件事,就能明白我们在做什么。我们不喜欢我们的信号有这些小的噪声起伏,容易产生低于阈值的假峰值和假谷值。如果我们平滑我们的信号,只让持续的高测量值通过我们的阈值,我们会在一个更好的地方。这可以简单到每 N 次连续测量取平均值。我们可以尝试加入其他低通滤波器,看看结果是否会有所改善,一般认为低通滤波器会尝试不同的加权来平均相邻的测量值。我们要保持这个超级简单:用周围 N 个测量值的平均值代替每个测量值。

平均信号

看着我上面展示的照片,看起来一个真实的片段通常持续大约 0.4 秒,这是我个人蹲着的经验。每隔 0.04 秒就有一个样本出现,这意味着查看大约 10 个相邻的样本,就可以大致知道我们想要一起计算多少个测量值的平均值。如果您想知道我是如何知道每 0.04 秒就有一个样本出现的,这很简单:

import numpy as np
print(np.diff(t))
[0.04  0.041 0.039 0.04  0.04  0.04  0.04  0.039 0.041 0.039 0.04  0.04....]
# cool: our data is coming in at almost exactly even time spacing, every 0.04 seconds. If it was less consistent, we'd be interpolating to a fixed time window. But we can get away with just pretending the time spacing is even

那么我们如何平均每 10 个样本呢?我们可以写一个 for 循环来完成这个任务。但它的计算效率更高,完全等同于用 10 个采样值为 1/10 的滤波器对信号进行卷积。代码如下:

如果你不熟悉卷积的概念,这看起来有点像胡言乱语,没关系。在谷歌上搜索“我如何用 python 计算滚动平均值”会让你看到我写的代码。我还是要说,如果你要处理一维信号,了解卷积如何工作以及什么是滤波器是进一步阅读的好主意。那么输出是什么样的呢?让我们在过滤加速度数据帧后重新运行代码

嘿,很快,成功了!

很棒的东西!我们捕捉到了这个会话的所有 4 个蹲坐,这次没有假阳性。

0.1 版完成。下一步是什么?

好吧,我们一起黑了一个超级简单的第一版。本帖不再做更多开发。但在我们结束之前,我想强调下一步该怎么做才能让它成为一款强大的应用:

如果你不衡量自己,你就无法提高

到目前为止,我们一直在疯狂地研究,以使结果适用于指导我们的一组特定的小例子。到目前为止,我已经有了一堆关于如何进一步改善结果、使代码对任意的手机方向保持健壮等等的想法。

但是我在开发周期中要做的第一件事不会是修改我们的蹲式计数器的代码。现在我们有了第一个工作版本,要做的事情是计算我们做得有多好,并确保我们所做的后续代码更改使这个数字朝着正确的方向移动。

幸运的是,我们的问题被很好地定义了,所以我们可以衡量自己!对于我做的每一次录音,我都认真地记下了深蹲的次数。当我们从 Moonsense 获取会话数据时,这个标签是可用的。因此,在下一章中,我们将添加一段代码来捕获我们的平均误差,然后开始进行更改,以降低我们的误差指标。

我们也将尝试看看我们是否能解决量化蹲姿质量水平的想法——也许用“一致性”来定义质量。或者可以提取一些描述性的统计数据,比如峰值加速度,然后看看这些数字如何与基于同一时段视频的专家对下蹲质量的评估相匹配。我们甚至可以为每一次会议贴上下蹲质量专家评估的标签,并训练一个机器学习模型,根据我们提取的数字特征预测专家评估。这将使我们的应用成为一个潜在的有趣和有用的产品。

关闭循环,使之成为一个活生生的应用程序

Moonsense 有一个简洁的小特性,叫做“数据消费者”,在这里你可以定义一个函数来处理新数据,只要它变得可用。这允许近乎实时的行为,比如当用户做了蹲起动作时,就向用户发送推送通知。一旦我们有了一个像样的下蹲质量评估器,我们就可以立即给用户反馈他们的下蹲做得如何。

你可以在这个回购中找到完整的代码示例

从笔记本电脑到企业

原文:https://towardsdatascience.com/from-the-laptop-to-the-enterprise-4a4234e961f5?source=collection_archive---------37-----------------------

当你从周末数据科学战士变成企业数据科学家时,要考虑三件事

图片由 www_slon_pics 来自 Pixabay

在线学习数据科学的免费内容多得简直荒谬。关于数据科学的媒体教程、Youtube 视频、MOOC 内容(例如 Coursera)和个人博客都创建了一个巨大而廉价的生态系统,只需你的笔记本电脑就可以学习数据科学。

没有什么比关注一篇半生不熟的博客文章,调试提供的代码以满足您自己的数据需求,并看着新技能诞生更令人兴奋的了。就在我们眼前出生。在我们的笔记本电脑上。太神奇了!

事实上,正是能够成功地浏览无数的在线资源,并将我所学的内容翻译到我的笔记本电脑上(当然是按工作顺序),让我一开始就有信心进入数据科学领域。

但在笔记本电脑上学习数据科学是一回事,了解如何将所学知识应用于大型企业通常会带来新的挑战,而大多数免费在线材料对此没有帮助。

你说我需要访问那个数据库是什么意思?我是数据科学家?访问数据不是我职位的要求吗?

当我离开学术岗位,在一家大型企业开始我的第一份数据科学工作时,我就面临着这样的问题。我在笔记本电脑上取得的所有成功并不是毫无意义的,但我仍然有很多东西要学习,以确保我可以继续将我最近获得的数据科学技能应用于大型企业问题。

这些问题是如此有力,以至于这不是我第一次在这里写关于的话题。

在本文中,我基于我之前对企业数据科学家面临的问题的见解,研究了所有年轻数据科学家在大型企业向数据科学角色过渡时需要考虑的 5 件事。我们开始吧!

第一件事:服务器架构

数据科学教育通常只关注让代码工作,这通常意味着创建固定的数据集(例如预先设计的数据集),利用笔记本电脑安装的 IDE 环境(例如 Anaconda、VS-Code)或预先配置的云管理笔记本环境(例如 Google CoLab、AWS Sagemaker、Azure DataBricks),并确保一切都已正确连接。

为了对这一过程进行抽象,数据科学家需要数据、处理该数据的计算环境以及连接到数据存储位置的方法。在企业环境中,这些服务被组织在一个服务器网络中,这些服务器之间的连接程度各不相同。因此,了解如何连接到这些服务器对于数据科学家在他们的岗位上最有效地工作是至关重要的。

当然,先进企业可能有工程团队,他们可以帮助新的数据科学家访问常用的数据资产,但是数据科学家因识别不常用的数据源来帮助他们的开发而臭名昭著。因此,通常需要对服务器架构有足够的了解,以帮助工程师、IT 专业人员和安全团队了解如何将数据科学工作台与这些资产联系起来。即使有基本的了解,也有助于确保在数据科学和 IT 支持团队之间建立信任,这是确保数据科学家尽可能对企业产生影响的关键因素。

等等,什么是数据科学工作台?

在现代企业中,数据科学工作台通常是运行软件的单个服务器或服务器集群,允许数据科学家连接到数据以执行不同的数据科学任务。这些服务器可以是内部软件解决方案(如 Dataiku 或 Alteryx)或托管云服务(DataBricks、AWS Sagemaker、GCP 数据实验室)。在这两种情况下,开发人员都是通过 web 浏览器来访问服务的。

这些环境中的大多数允许数据科学家访问数据科学中常用的 Python 和 Python 库(例如 pandas、scikit)。在某些情况下,企业还可能允许这些服务器连接到 Python 包索引,以便能够访问新的和不断发展的库。

这似乎很简单,数据科学家还需要什么?

在许多情况下,访问常见的企业数据资产不足以满足特定业务问题的需求。因此,数据科学家通常需要能够访问非传统数据源,例如来自应用程序数据库的应用程序级数据、存储在共享文件系统上的数字文档,或者通过 API 调用来自第三方的数据源。

要记住的核心概念:服务器之间的通信有几种不同的方式,其中一些协议或 API 取决于服务器或服务器上的软件要执行的功能(例如,数据库服务器与 web 服务器)。大多数连接机制利用了 TCP/IP 协议,该协议要求知道至少两件关于服务器的事情;他们的 IP 地址和端口号。

IP 地址是赋予服务器的名称,这样在网络上传输的信息就知道去哪里找这些信息。这些 IP 地址可以是人类可读的,这需要域名系统(DNS)将人类可读的服务器名称映射到其数字 IP 地址,但这不是必须的。服务器上的端口只是唯一标识网络上事务的数字。端口有助于区分不同类型的网络服务,例如 web 服务(HTTP)、文件服务(FTP)或邮件服务(SMTP)等等。

连接到通用服务器

通用服务器本质上是一台远程计算机。在企业中,可以构建和供应这些服务器,以允许开发人员访问计算资源,满足本地笔记本电脑或数据科学工作台不容易满足的要求。例如,数据科学开发人员可能需要访问开源光学字符识别(OCR)工具,如 Tesseract,以便从图像中提取文本。在这种开发环境中,在独立服务器上安装像 Tesseract 这样的工具可能是最容易的。

为了连接到这些服务器,我们通常使用安全 shell 或 SSH 协议。像 PuTTY 或 WinSCP 这样的客户端应用程序允许我们使用笔记本电脑与远程服务器建立 SSH 连接。为了建立这些连接,我们需要知道服务器的名称或 IP 地址,并且可能需要一个公钥-私钥对。在大多数企业中,这些密钥对是不必要的,因为您的用户名(如员工 ID 等)可能与一个目录相关联,该目录会告诉网络中的任何服务器谁可以访问该服务器。

当需要密钥对时,公钥存储在服务器上,私钥存储在客户端(例如您的笔记本电脑)。为了使用 PuTTY 连接到服务器,我们输入服务器的名称或 IP 地址、端口(对于 SSH 通常是 22),然后在我们的客户机环境中提供私钥的位置。

作者图片

连接后,您可以使用命令行脚本来使用服务器的资源,这些脚本允许您执行不同的任务。具体的命令行语法将取决于服务器使用的操作系统(例如 Windows 与 Linux)。

连接数据库

数据库服务器只是运行各种数据库软件的服务器,为存储某些类型的信息而优化。为了访问这些数据库中的数据,大多数数据库(如 SQLServer、PostgreSQL 或 MySQL)都有允许访问的特殊 API。这些 API 是 Java 数据库连接(JDBC)或开放式数据库连接(ODBC)规范。

Python、R、SAS 和 Java 都有帮助建立到这些数据库的连接的库。至少,我们需要了解以下内容才能进行连接:

服务器名称

数据库名称

用户名

密码

一旦连接到数据库,您就可以使用适当的数据库语法(如 SQL for SQL databases)从数据库中提取数据。

连接到共享文件系统(如 Windows 目录、AWS 弹性文件系统)

如前所述,数据科学家经常面临数据在企业数据库中不可用的情况。相反,所需的数据可能存储在共享文件系统中。这些文件系统只是用来存储各种文件类型(包括文档、图像或声音文件)的目录。因为这些文件类型不容易存储在数据库解决方案中,所以我们将它们存储在文件系统中。

有几种不同的方法可以访问这些文件系统,以便数据科学工作台可以使用这些数据。一种方法是将文件系统目录装载到 data science workbench 服务器上,以便这些目录中的文件变得可用,就像它们是根文件结构的一部分一样。如何挂载文件系统取决于操作系统,对服务器有一定的管理权限,并知道远程服务器的 IP 地址。因此,这项任务通常由服务器架构师来执行。

访问共享文件系统中的文件的另一种方法是将文件移动到 data science workbench 可访问的位置。根据我的经验,将文件复制到可访问的位置是最安全的,尤其是在开发期间,这进一步强调了作为数据科学生态系统的一部分,访问小型开发服务器的价值。

使用 API

最后,在数据科学中,可能需要从应用程序编程接口或 API 获取数据。为客户提供服务的第三方供应商可能会通过 API 向客户公开他们的服务收集的一些数据。例如,我的一个团队被要求从使用 Qualtrics 调查平台构建和托管的调查中获取数据。为了完成这项任务,我们利用 Qualtrics API 为我们的公司调查请求数据。

今天,大多数 API 利用 URL 和 HTTP 协议来提供对信息的访问。对于数据科学家来说,连接到这些 API 需要向 API 发出请求,并传递指向正确 URL 的参数。如果处理得当,URL 会以 JSON 格式响应所需的信息。

要使用 API,您可能需要一个 API 密钥(也称为令牌),在许多情况下,这些密钥在过期之前只持续一定的时间。在代码中,目标是构建传递适当参数和身份验证令牌的 URL,以获取所需的数据。这里的是使用 Python 入门 API 的绝佳资源。

第二件事:关于安全、身份和访问管理(IAM)的更多信息

构成现代企业 IT 生态系统的所有这些服务器都需要严格的安全协议,这可能会影响数据科学家的工作方式。基本思想是确保只有那些有授权的人被允许访问信息。如今,这主要是通过基于角色的访问控制(RBAC)来处理的,在这种情况下,角色被创建并被授予执行各种操作(如访问数据库或服务器)的权限。

然后,用户被分配到被分配了角色的组,从而给予用户访问该角色所允许的操作的权限。因此,对于数据科学家来说,了解如何请求访问不同的角色以执行不同的工作职能至关重要。

例如,一名数据科学家想要访问一个企业应用程序正在使用的 MongoDB 数据库,因为它包含由用户(企业的客户)编写的自由格式文本数据。为了获得访问权限,数据科学家需要识别组“MongoDB Production”,然后选择分配给该组的适当角色“Application Schema User Read”,以便能够为她的用户获得成功连接和读取数据库的权限。

第三件事:了解计算发生在哪里

在所有这些服务器中,每台服务器都有自己的身份和访问权限,当数据科学家在工作时,很容易忘记哪些系统的负担最重。在大多数数据科学教育中,我们只知道我们用来执行工作(如争论数据和训练模型)的系统的计算限制。那些讨厌的记忆错误一定要提醒我们。

但是,了解计算发生在哪里可以帮助年轻的数据科学家开发更好的代码,利用跨服务器资源的本地计算,从而减少令人讨厌的内存错误的可能性。

事实上,训练模型需要我们的数据科学工作台能够访问强大的计算(例如 GPU 和/或集群)。然而,鉴于我们 60%以上的工作都花在争论数据上,并且大多数数据库服务器都配备了非常强大的计算环境,了解如何利用这些环境可以带来一些显著的好处。让我们看一个简单的例子。

通常需要数据科学家访问数据库,连接几个表,并将数据转换成机器学习格式。完成这些任务的一种方法是利用 data science workbench,使用 Python 的 pyodbc 库访问数据库,查询每个表,将结果作为两个数据帧输入 data science workbench 的 pandas 库,连接这些表,并处理它们。

在这个场景中,我们使用支持数据科学工作台的服务器上可用的计算来执行所有数据科学任务。作为这一过程的替代,我们可以选择利用数据库服务器来执行其中的一些任务。以下是我们的流程可能会发生的变化。

我们可以编写 SQL 来连接数据库中的表,而不是使用 pyodbc 分别从每个表中返回数据并使用 pandas 来连接它们。此外,我们可以将该表作为临时表返回给数据库,或者在对连接的数据执行争论功能的单个语句中包含额外的 SQL。然后,这些 SQL 查询的结果可以放入我们的数据科学工作台上的单个数据框架中。

第二个过程的一些好处包括降低对数据科学工作台上计算的要求。提高了性能,因为许多数据库软件解决方案针对 SQL 操作进行了优化。以及处理大型数据集的能力,因为数据库服务器通常包含高度的计算资源。

最后,我分享了一些在我刚开始学习企业数据科学时给我留下深刻印象的概念。我希望这些能帮助你有一个良好的开端,至少能让你在企业环境中更自信地驾驭数据科学。

比如参与学习数据科学、职业发展或糟糕的商业决策?加入我。

用熊猫魔法从跟踪数据到时间序列

原文:https://towardsdatascience.com/from-trace-data-to-time-series-with-panda-magic-8efe0fa4ea82?source=collection_archive---------23-----------------------

伊洛娜·弗罗利希在 Unsplash 上的照片

本文将指导您使用强大的 Pandas 将数百万行跟踪数据快速转换成宽格式的时间序列表。

数据

在这次演示中,我将使用来自开放大学的 OULAD 数据集。完整的数据集,以及一个可爱的数据描述,可在上面的链接。这是一个关于在线课程中虚拟学习环境下学生活动的数据集。它涵盖了 7 个模块中每一个模块的 2 年和 4 个队列。

我以前写过这个数据集,因为它是我的最爱之一。你可以在我的文章中阅读我以前的一些工作,使用这些数据建立预测模型,通过学生如何与他们的学习环境互动来预测学生的成绩。

今天,我们将探索压缩集合中的 student_vle.csv 文件。该文件包含学生与学习环境中可访问的在线活动交互的跟踪数据。每行代表学生完成的一项活动,包括他们在该活动中的点击次数。

目标

在我之前对这个数据集的研究中,我使用这些跟踪数据的集合来预测学生是否能通过这门课。我使用学生点击的总次数。

但是现在我每天都用学生的行为来做我的预测。这意味着使用时间序列数据来描述学生的参与度如何随着时间的推移而变化。对于本文,我将只记录学生每天点击的次数,尽管对于我的实际模型,我使用了更多的变量,并将课程每天的多个列作为输入变量。

因为我想要每个学生的时间序列数据,所以我将从个人活动交互观察中创建一个宽格式的时间序列表。每一行将是给定课程的给定群组中的单个学生。每一列都描述了当天学生在学习环境中点击活动的次数。

这些日期与该群组的开始日期相关。一些学生在课程开始前 25 天就开始工作,课程长达 270 天。因此,我们的最终表将有 295 列。

这是我们想要的样子:

作者图片

流程概述

第一次尝试将数据从跟踪日志转换到宽形式的时间序列表时,我尝试使用嵌套的 for 循环来读取跟踪日志中的每个条目,并将其放在新表上的正确位置。不要这样。我用一个计数器观察了一下这个过程,并做了一些快速计算。对于略多于 1000 万行的跟踪数据,这将花费我超过 5 天的运行时间来完成。有一种说法是,“如果你对熊猫使用嵌套的 for 循环,可能有更好的方法。”

相反,我使用布尔掩码来创建 Pandas 文档中所谓的“视图”,或者在不破坏原始数据的情况下过滤数据。为此,我分别过滤了每天的数据,并将该视图的结果按照时间顺序合并到一个新的 dataframe 中。

流程细节

跟踪数据启动了一个活动交互列表,其中包含描述活动、模块、群组、学生和点击次数的变量。我将模块、群组和学生合并到一个“注册”栏中,以便于索引。

作者图片

如您所见,每个学生每天都有多个条目,甚至每个活动都有多个条目,因为每个条目都是与单个活动的单个交互。学生似乎经常在同一天多次参与同一个活动。我们需要做的第一件事,为了获得每天点击的数据,是对数据进行分组。要了解更多关于如何使用 Pandas Groupby 函数的信息,你可以阅读我的关于主题的文章。

我们可以使用以下代码按学生和日期对该表进行分组:

按学生和日期分组

def group_by_day(student_vle): #group by registration and dayvle_group = student_vle.groupby(by = [‘registration’, ‘date’]) #sum up the clicks for each day for each studentsum_clicks = vle_group.sum().reset_index()sum_clicks = sum_clicks.drop(columns=['id_site']) #sort by student and daysum_clicks = sum_clicks.sort_values(by=[‘registration’,’date’]) return sum_clicks

函数group_by_day()使用df.groupby() Pandas 方法按学生和日期对数据进行分组,并使用df.sum()聚合方法生成一个新的数据框架,其中汇总了每个学生每天的点击量。

我还做了一个完全不必要的排序,因为看到按学生和日期排序的数据很好,可以对它有一个简要的了解,但这对于接下来的步骤是完全不需要的。如果您正在处理一个更大的数据集,或者将代码投入生产,一定要跳过这一步。

此代码返回下表:

作者图片

我们现在每个学生每天只有一个条目。他们每项活动的点击数总和被加在一起,以表示他们全天的点击数总和,而不是每项活动交互实例的点击数总和。

由于我需要秩序,条目是按学生和日期组织的。我认为在模块的日子里看到每个学生的工作流程是很好的。

现在,我们可以开始一天一天地分割这张表,然后用下面的代码将这些部分并排放在一起:

过滤并合并

def create_time_series(sum_clicks): #Create a new dataframe to hold our timeseries data.time_series = pd.DataFrame() #Create one row for each student registrationtime_series['registration'] = sum_clicks['registration'].unique() start_date = sum_clicks['date'].min()end_date = sum_clicks['date'].max()date_range = range(start_date, end_date) counter = len(date_range) #Iterate through the days of the course: for date in date_range: #create a views of the data, one day at a time. single_date_df = sum_clicks[sum_clicks['date'] == date]single_date_df = single_date_df.drop(columns=['date']) #rename columns to describe date and data.new_cols = ['registration'] +   [f'clicks_on_day_{date}'] single_date_df.columns = new_cols #merge into the time series dataframe. time_series = time_series.merge(single_date_df,how='left',on='registration',validate = '1:m') print('Days remaining to be processed: ', counter)clear_output(wait=True)counter -= 1 #Missing data represents no clicks that day, so fill with 0. time_series = time_series.fillna(0) time_series = time_series.set_index('registration', drop=True) return time_series

过滤器

上面的函数遍历模块中的每一天,并使用一个布尔数组(Trues 和 Falses 数组)来过滤当天的数据。它检查每一行的“date”变量,并只返回其日期与该迭代的当前日期相匹配的行。

例如:

sum_clicks['date'] == 0将返回一个与 sum_clicks 长度相同的序列,但是为数据变量为‘0’的每一行填充 True,为其余的行填充 False。

sum_clicks[sum_clicks['date'] == 0]将只返回布尔数组包含 True 的行的视图。

当我们将上述过滤器应用于 sum_clicks 表时,我们得到:

作者图片

请注意,我们只有每个学生在课程第 0 天或第一天的点击量总和。你可能还会意识到,大多数学生可能不会每天都在虚拟学习环境中学习。因此每个每日视图不会包含每个学生。下一步中的左连接将有助于解决这个问题。

上述函数的下一部分将每天的视图合并到一个我们已经准备好的 dataframe 上,该 data frame 为每个学生注册记录一行,但没有数据。

合并

time_series = time_series.merge(single_date_df,how=’left’,on=’registration’,validate = ‘1:m’)

df.merge()是将一个数据帧合并到另一个数据帧的一种方法。这相当于在 SQL 中加入表的另一种数据管理工具。这种方法的神奇之处在于合并。我准备了名为“time_series”的空数据帧,专门用来按时间顺序连接这些视图。该数据帧有一个名为“注册”的列,表示数据中存在的唯一注册。每个学生注册一排,不多不少。这很重要。

当我在 for 循环中合并每个每日视图时,我使用“registration”作为键。这确保了正确的数据进入正确的行,即使这些行在“时间序列”和我们正在合并的每日视图中的顺序不同。当我们像这样转换数据时,我们还需要考虑我们的数据完整性。用键合并是确保行之间的值不会混淆的最好方法。

how='left'告诉 Pandas 保留左侧数据帧的记录,在本例中为“时间序列”。不要丢弃任何一个,不要添加任何一个,不要重新排列它们。只需获取正确数据帧中的行,在本例中为“single_date_df”,并附加匹配的行。放弃任何不喜欢的。我们希望确保每天每个注册都有一条记录。

告诉 Pandas 使用该列作为键来匹配每个数据帧的行。否则它不知道 single_date_df 数据帧中的哪些行在合并时去了哪里!最后,validate='m:1'的意思是‘多对一’。这告诉 Pandas 检查每天的正确数据帧中是否只有一个值。还有一种方法可以确保我们的数据不会被弄乱。如果右边的数据帧“single_day_df”中没有与左边“time_series”中的注册相匹配的记录,Pandas 将用 np.nan 或“无数据”填充该值。

一旦这个循环结束,dataframe 将有每个学生每天的所有点击计数,按时间顺序从左到右排列。在某一天没有发现学生点击的任何地方都将有一个名词性名词。我们将使用time_series = time_series.fillna(0)将这些名词性名词替换为零。毕竟那个 np.nan 真正的意思就是:那个学生那天什么都没点。

我还将“注册”设置为索引,因为 Pandas 让我可以快速完成,这就是那个列的内容,学生注册的索引。我之前没有这样做,因为它稍微简化了合并语法,将它作为自己的列。

这是我们的决赛桌。很稀疏。

作者图片

奖励:稀疏化!

就因为我爱你们大家,我想再给你们看一个魔术。我们上面创建的时间序列数据帧大部分都是零。这在商业中被称为“稀疏数据框架”。这一个只是有点稀疏,但是我们可能使用的其他数据帧都充满了零。如果我们像这样保存它们,单独记录每个零会浪费很多空间。再一次,熊猫来救援了!

我们可以压缩数据帧,方法是从本质上删除零,同时跟踪它们的位置:

sparse_time_series = time_series.astype(pd.SparseDtype('int', 0))

上述代码通过删除零,将时间序列数据帧压缩了大约 1/3。在代码的(pd.SparseDtype('int', 0)部分,我们告诉 Pandas,产生的稀疏数据帧将具有‘int’或 integer 类型的值,并且零是我们想要压缩的。

在其他应用程序中,尤其是自然语言处理,使用这种方法可以将数据压缩到原来的许多倍。

摘要

您了解了如何将跟踪数据记录(可能是用户交互、物联网 pings 或任何定期返回值的东西)转换为按选定时间段(在本例中是按天)聚合的广泛形式的时间序列数据帧。您了解了如何使用df.groupby聚合数据,将布尔掩码传递给数据帧,比如用df[df['date'] == 0]]在一列中创建您想要的数据的视图,以及用df.merge()迭代地将每个时间段的数据附加到前一个时间段,以创建宽格式的时间序列数据帧。

另外,您还学习了一种压缩方法,可以更有效地描述稀疏数据帧。当您想要使用非常大、非常稀疏的数据集进行建模时,这变得非常重要。许多标准的机器学习工具可以有效地处理稀疏数据帧。

在上面的例子中,这些策略将处理时间从 5 天减少到 1 到 2 分钟,这取决于你的机器。

完整代码:

下面是 Github 的完整代码要点,它将下载、解压缩和转换这个特定的数据集。请随意复制它,并将其用作您自己项目的模板。

参考资料:

Kuzilek J .、Hlosta M .、Zdrahal Z. 开放大学学习分析数据集 Sci。数据 4:170171 doi:10.1038/sdata . 2017.171(2017)。

从单词到向量

原文:https://towardsdatascience.com/from-words-to-vectors-e24f0977193e?source=collection_archive---------7-----------------------

自然语言处理中文本表示的直观介绍

格伦·卡丽在 Unsplash 拍摄的照片

你可能会使用数据来建立机器学习模型,以解决特定的任务,如预测客户是否会流失或估计股票价格。在所有这些例子中,数据通常包含数字特征,如果任何特征以文本格式表示(例如分类特征,则应用各种编码技术将其转换为数字,因为机器学习算法被设计为仅与数字一起工作。在这里,我们实际上遇到了将单词转换成数字的基本尝试,但是在这种情况下,我们的目的仅仅是捕获关于文本 特征的信息,而不是文本本身。这对于上面提到的任务来说当然是完全没问题的,在这些任务中,目标不是理解单词,而是捕捉这些单词所包含的知识。

另一方面,像确定客户评论的情绪或预测不完整句子中的下一个单词这样的任务需要某种形式的理解给定文本中的单词。毕竟,当我们试图手动解决这些任务时,这就是我们所做的,但是我们如何教会计算机为我们做这些呢?这就是自然语言处理(NLP),人工智能(AI)的一个分支,在其他涉及分析和理解人类语言的任务中所关注的。然而,在自然语言处理的核心,存在着一个基本的挑战:文本表示。换句话说,我们如何将给定的文本转换成 NLP 算法可以处理并用来解决现实世界任务的数字形式?在本文中,我将概述一些基本的和高级的方法来应对这个基本的挑战。

基本方法

基本编号

现在,解决这个问题的最基本和最简单的方法是什么?当你思考的时候,让我建议一个。只需给字典中的每个单词分配一个唯一的数字,然后就可以收工了!

word    | number
_________________
a       |  1
able    |  2...
book    |  325...
paper   |  1024...
zoology |  5067...

这是一个很好且简单的表示,但是它有一个主要的缺点。除了这些数字没有捕捉到单词的任何含义之外,另一方面,它们给单词强加了一种隐含的和不必要的语义排序。事实上,没有任何理由让论文的编号大于图书的编号,而小于动物学的编号。 ML 算法对数据分布非常敏感,这种表示可能会误导算法认为论文在某种程度上是比更好(或更差)的候选。看来我们的第一次尝试悲惨地失败了。下一步是什么?

字符编码

在我们的第一次尝试中,我们给单词分配了任意的数字,也许这就是问题所在。也许我们应该在如何选择这些数字上变得聪明一点,并开始考虑与单词有某种联系的数字。事实上,这里可能想到的一个直接想法是字符编码。单词是由字符组成的,并且在单词和它在计算机中的字符编码表示之间已经存在一对一的映射。那么,如果我们将每个单词映射到代表其 ASCII 或 Unicode 编码的数字,而不是任意数字,会怎么样呢?啊哈!起初听起来非常简单有趣,但是如果你仔细观察,你会发现这只是告诉你单词是什么,不是单词的意思。换句话说(没有双关的意思),97 112 112 108 101 可能是字符序列的编码 a p p l e ( 的确如此),然而,它远不是单词 apple 的有意义的表示,因为仅仅是字母的组合并不携带它们所组成的单词的任何固有含义。这种表示也有类似于基本编号的语义排序问题。

一键编码

因此,看起来我们是在正确的轨道上,但是我们应该考虑其他方法来克服与编号相关的内在语义排序问题,而不是搜索信息性的编号分配。这就是向量出现的地方。让我们回到我们的基本编号方法,并扩展它以避免排序问题。因此,我们仍将为每个单词分配一个唯一的整数,但不是将数字保持为十进制形式,而是将数字编码为大小为|V|的二进制向量(0 和 1 的向量),其中 V 是给定文本中单词的词汇。这个向量在任何地方都是 0,除了在对应于我们分配给单词的数字的索引处,我们将在那里放置 1。让我们看一个简单的文本示例来说明这一点:

I think therefore I am.

给定这篇课文,我们的词汇由 4 个单词组成:V ={ I,think,因此,am }。我们从 1:

I   think   therefore   am
1     2        3        4

因此,我们的新单词向量将如下所示:

 **1  2  3  4** I          [**1**, 0, 0, 0]
think      [0, **1**, 0, 0]
therefore  [0, 0, **1**, 0]
am         [0, 0, 0, **1**]

正如你所看到的,在这些向量中没有隐含排序的概念,所以我们实现了一个更有效而简单的单词表示。唷!

然而,由于其自身的以下主要限制,该方案在实践中很少使用:

  • 虽然我们的玩具示例很短,但是在现实世界中,您需要处理大量的文本和大量的词汇。因为我们的独热编码单词向量的维数与词汇表的大小成正比,所以我们最终会得到大的稀疏向量,其中大多数条目都是零,这在计算上是低效的。稀疏也容易造成过拟合。
  • 每个单词被视为一个独立的单元,并且在这种表示中没有单词之间关系的概念,例如相似性。例如,如果我们取任意两个向量的欧几里得距离或余弦相似度,不管单词之间的潜在关系如何,我们都会得到相同的结果。换句话说,这种表示不能捕捉单词相对于其他单词的语义。
  • 如果不重新训练和扩大词汇量,就没有办法表示我们的词汇中以前没有见过的新单词(又称 out of vocabulary words )。

袋字

安妮·斯普拉特在 Unsplash 上的照片

让我们试着遵循我们的传统,逐步克服一种方法的缺点,希望产生一种更好的表示方法。一键编码的主要缺点之一是明显缺乏对建立单词间语义关系的支持。让我们看看是否可以通过利用我们关于语义的知识来解决这个限制。两个单词什么时候语义相似?这实际上是一个很难的问题,我们将在本文的后面回到这个问题。让我们考虑一个不同的、相对简单的问题。两段文本什么时候语义相似?一个直观而直接的答案是,当这些文本共享大量相同的单词时。因此,让我们尝试提出一种表示方法,通过将文本片段(也称为文档)而不是单个单词转换为基于其组成单词的向量来编码这一事实。与我们之前的方法类似,我们为每个单词分配一个唯一的编号,但是我们不是用这些编号来表示单词,而是使用它们和相应的词频来构造给定文档的有用表示。

更具体地说,我们将每个文档转换成一个维为|V|的向量,其中 V 是我们的词汇表,索引 i 处的元素只是对应于数字 i 的单词在文档中出现的次数。让我们看几个例子来更好地理解这个概念:

Document 1: I think therefore I am
Document 2: I love dogs
Document 3: I love cats

我们的词汇是 V = {我,想,因此,我,爱,狗,猫}让我们像以前一样分配唯一的数字:

I   think   therefore   am   love   dogs   cats
1     2         3       4      5     6       7

那么我们的文档向量将是:

 I  think  therefore  am  love  dogs  cats
Document 1: [ **2**,   **1**,      **1**,      **1**,    0,   0,    0 ]
Document 2: [ **1**,   0,      0,      0,    **1**,   **1**,    0 ]
Document 3: [ **1**,   0,      0,      0,    **1**,   0,    **1** ]

这些向量本质上把相应的文档表示为单词的包(集合),而不考虑上下文和单词的顺序。如果你注意到了,文档 1 和文档 3 的向量在向量空间中彼此非常接近,这反映出它们有许多共同的单词。实际上,这些文档之间的欧几里德距离远小于例如文档 1 和文档 2 之间的距离。因此,这种表示允许我们测量文档的语义相似性,而不是一次性编码,但是如果你更深入地观察,你会意识到这种表示离一次性编码不远,事实上可以通过简单地将文档中单词的一次性编码向量相加来实现。这里真正的区别是,我们是根据文件而不是文字来操作的。

虽然这种方法似乎提供了更丰富、更简单的表示,并且事实上在实践中被普遍使用,特别是对于文本分类,但是它有几个主要缺点:

  • 我们的新文档向量的大小仍然由词汇大小决定,这意味着高维度和稀疏性问题仍然存在。
  • 新的语义相似性特性非常严格,严重依赖于共享单词之间的字面词典匹配。例如,文档“我游泳”、“我游泳”和“我走路”的向量在向量空间中彼此距离相等,即使前两个句子在意义上非常接近。
  • 句子中的顺序可以极大地改变意思,因此将句子视为没有顺序和上下文的单词集合会导致像“狗吃了食物”和“食物吃了狗”这样的文档用相同的向量表示。
  • OOV 问题仍然没有解决。

一袋 n 元硬币

像往常一样,让我们再次尝试补救前一种方法的一些问题,看看我们在哪里着陆。单词袋方法的一个主要问题似乎是缺乏顺序和上下文。你能想出一个简单的方法来抓住这些概念吗?让我们后退一步,找出问题的根源。单词袋方法缺乏上下文的原因是因为它将单词视为独立的原子单位。另一方面,上下文通常不能从一个单词中确定,而是在单词序列出现时出现。因此,与其将文档表示为一个由单个单词组成的包,不如将其视为一个由一些固定大小的连续单词序列(也称为n-grams)组成的包,从而捕获一些上下文。然后,我们的词汇表将由 n 元语法组成,像以前一样,我们将为每个词汇表条目分配一个唯一的数字,并用向量来表示文档,这些向量对这些条目在文档中出现的频率进行编码。让我们将这个概念应用到上面提到的文档中。如果我们将每个文档分成由两个相邻单词组成的块(即 2-gram 或 bigram),我们会得到以下词汇表:

V = {我思故我思,故我在,我爱爱狗爱猫}

然后我们给每个词汇成员分配一个唯一的数字:

I think:         1
think therefore: 2
therefore I:     3
I am:            4
I love:          5
love dogs:       6
love cats:       7

现在我们可以为每个文档构造二元模型向量:

 **1  2  3  4  5  6  7**
Document 1: [ **1**, **1**, **1**, **1**, 0, 0, 0 ]
Document 2: [ 0, 0, 0, 0, **1**, **1**, 0 ]
Document 3: [ 0, 0, 0, 0, **1**, 0, **1** ]

如果你注意到,我们之前的单词包方法只是 n 元单词包的的一个特例,其中 n=1。我们还看了这种方法最常用的一种情况,叫做 二元模型 表示法。另一个流行的案例被称为毫不奇怪的 三元模型 其中 n=3。正如您所看到的,扩展我们对文档中语义含义的更好代表的概念有助于我们捕捉更多的上下文。事实上, n 的值越大,包含的上下文就越多,但是会产生更稀疏的向量。一般来说,n=2,3 的 n-grams 的方法由于其上下文优势而优于单词包方法,但其他问题,如高向量维数、稀疏性和缺乏对 OOV(词汇外)单词的支持,仍然使其在实际应用中不太有效。

TF-IDF

在进入更高级的方法之前,我们先来看看最后一种基本的矢量化方法。这一次,让我们考虑一个文档中单词的不同方面,以通知我们的向量表示。我们仍然在寻找文档的有意义的表示,问题是文档还有什么特征?好吧,想象一下,给你一篇像这篇文章这样的文章,让你用几个关键词来总结它。你会怎么做?你会简单地报告前 5 个最常用的词吗?可能不会,因为你很可能会以类似于 am,are,is,like,the,this,that (又名停用词)的词语结束。所以,你会去寻找对文档来说总体上更加重要的单词,对吗?例如,文本表示单词矢量化将是表示这篇文章的良好候选。这是我们下一个表示方法背后的核心思想。我们希望将文档中的每个单词与某种重要性或相关性分数相关联,并用这些分数的向量来表示文档,而不是分配任意的数字。现在问题变成了如何计算这些分数?在进入公式之前,让我们理解它们背后的直觉。我们的目的是设计一个公式,让文档中重要的单词(也称为术语)比不太重要的单词获得更高的分数。我们知道,对于某些文档来说重要的单词可能会在该文档中频繁出现(虽然大多数情况下很少出现),但是几乎总是比停用词少得多。这意味着项频率(TF) 不足以简单地表示重要性,事实上,大多数时候是错误的。然而,这是我们用来计算最终分数的必要信息。因此,让我们根据我们的目的来调整这个值。我们实际上需要将这个 TF 分数乘以另一个分数,这个分数对于停用词要低得多,对于重要术语要高得多。并且这个新的乘数被称为逆文档频率(IDF) 分数,其本质上依赖于停用词不仅在一个文档中频繁出现而且在所有文档中频繁出现的简单实现。因此,如果我们简单地取一个单词出现在文档中的频率的倒数,那么对于重要的单词,这个值应该更高,因为它们最有可能只出现在它们的相关文档中(因此文档更少)。因此,我们得到下面的公式来计算给定文档 d: 中每个术语 t 的得分

来源:作者

其中每个功能定义如下:

来源:作者

来源:作者

如果你注意到了,这里我们取倒频的对数,这样做的原因是为了惩罚非常大的值,这些值是我们从极其罕见的术语(如拼写错误的单词)中得到的。

现在我们已经为我们的表示提出了评分方法,让我们将它应用到我们的一个文档(文档 2 )中,看看它在实践中的表现。请注意,我们有 3 个文档,文档 2 总共有 3 个术语。

**word   TF score     IDF score          TF-IDF score**
I      1/3 = 0.33   log(3/3) = 0       0.33 * 0 = 0
love   1/3 = 0.33   log(3/2) = 0.18    0.33 * 0.18 = 0.059     
dogs   1/3 = 0.33   log(3/1) = 0.48    0.33 * 0.48 = 0.158 I   think   therefore   am   love   dogs   cats
Document 2 vector: [0     0        0        0    0.059  0.158    0]

正如您所看到的,我们最终得到了单词 I 的最低值,它对所考虑的文档并不重要,而更高的值被授予更相关的单词。这意味着 TF-IDF 表示还允许我们测量文档之间的语义相似性,虽然它通常用于 NLP 应用,如文本分类和信息检索,但它仍然存在一些基本缺点,如高维度、稀疏性和无法处理 OOV 词。

高级方法

单词嵌入

来源:developers.google.com

我们在寻找单词的有意义的表示方面已经走了很长的路,并且我们已经看到了一些有趣的基础方法,但是我们仍然无法逃脱高维度和稀疏性的诅咒。以前的表述似乎也不能概括单词的真正语义。我们能做得更好吗?让我们重温一下我们提出的、但在本文前面被方便地回避的难题:什么时候两个词在语义上相似?让我们稍微分离一下语义相似性的概念。我们如何确定两个单词是否相似?比如这两个词相似吗?当然是的,因为两者都指人类。啊哈!所以,在人类的语境中,这些词是 语义相近的 以此类推,类似于国王、王后、男孩、女孩的其他词语在同一语境中也是同等相关的。但是如果我们转换上下文,比方说,从性的角度来说,那么突然之间,这些术语似乎没有了相同程度的相似性。显然,在这种情况下,男人女人更类似于男孩,女人本身比男人更类似于女孩。那么,从这个观察中我们能得出什么结论呢?那就是语境在确定语义相似度中起着举足轻重的作用。因此,按照这种推理,如果我们能够以某种方式将这些上下文编码成一个数字向量,那么产生的向量将比我们迄今所看到的更能代表它们相应的单词。让我举个例子来说明一下。我将基于以下上下文为上面提到的每个单词(加上一些额外的单词)构建一些虚拟向量:

  1. 是人吗?
  2. 是男的吗?
  3. 是女的吗?
  4. 是国家统治者吗?
  5. 是无生命的吗?
**word/context   1\.    2\.    3\.     4\.    5.**
king         [ 0.9   1     0      1     0 ]
queen        [ 0.9   0     1      1     0 ]
man          [ 1     1     0      0.5   0 ]
woman        [ 1     0     1      0.5   0 ]
boy          [ 1     1     0      0.5   0 ]
girl         [ 1     0     1      0.5   0 ]
book         [ 0     0     0      0     1 ]
paper        [ 0     0     0      0     1 ]

这里,每个维度中的值代表了我们对单词与所考虑的上下文的相关性的信任程度。正如您所看到的,在某些上下文中语义相似的单词在与相同上下文相关联的维度上的向量空间中也是彼此接近的。现在注意这个向量的根本不同之处。它的维度不再与我们的词汇大小相关,而是与通常小得多的上下文(特征)的数量相关,这意味着我们可以用低维、密集的向量来表示单词,同时提供了检测语义相似性的关键好处。但是利益实际上并没有到此为止。这种表示也允许我们回答其他关于语言模式的有趣问题。例如,我们可以问男人之于国王就像女人之于什么?语言学上的答案是女王,实际上,你可以通过对向量进行如下操作来得出这个答案:

这也从直觉上讲是有道理的,如果你从国王、身上去掉男子气概,你应该只剩下纯粹的皇室概念,给这个结果加上女人味应该会给你一个王后。宾果!

所以,现在我们有了一个巧妙的方法,用紧凑的向量以一种更加语义直观的方式来表示单词(又名单词嵌入),问题变成了我们实际上如何得到这些向量?我们查看了一个带有几个上下文的小样本语料库,但是在庞大词汇的现实世界中,手动生成这些向量几乎是不可能的。同样,对于向量维数,我们应该考虑多少上下文也不清楚。在 2013 年,Mikolov 等人[1]的一项革命性工作表明,基于神经网络的表示模型“word2vec”可以实现上述示例中所示的结果。该模型基于大量文本学习给定维度(超参数)的单词嵌入,然而,所学习的向量不像示例中使用的向量那样可解释,因为从向量来看,每个维度代表什么类型的上下文并不十分清楚。我不会深入模型如何工作的细节(也许在未来的文章中),但是 paper 提出的模型架构背后的核心思想也依赖于上下文的重要性。他们的“连续单词包”方法本质上是试图预测句子中的单词,给定它周围的单词作为上下文,而“SkipGram”方法则相反,并推断给定单词的上下文。

虽然单词嵌入表示解决了基本方法的大多数关键问题,但是一个问题即处理 OOV 单词的能力仍然没有被覆盖。为了解决这个问题,一种称为“fastText”的流行技术[6]通过使用关于单词部分的信息,例如形态属性(例如前缀、后缀等),对单词嵌入训练进行了有趣的修改。).这种方法背后的关键思想是通过单词的组成字符 n 元文法来表示单词,并一起学习单词和字符 n 元文法的嵌入。为了生成一个我们从未见过的单词的嵌入,比方说,parocial,我们将它分解成它的字符 n-grams,如 par,aro,roc,och,…,ial ,并组合这些 n-grams 的嵌入来生成单词parocial 的嵌入。

单词嵌入方法已被证明是 NLP 的基础构件,并从那时起启发了更复杂的文本表示方案。其中一个称为“doc 2 vec”[2]扩展了“word2vec”方法,直接学习任意长度文本的表示。在过去几年中,已经引入了更多的全局(GloVe [3])和上下文单词表示(ELMo [4],BERT [5])来解决与简单单词嵌入相关联的单词歧义问题(即,表示在不同上下文中表示不同事物的单词,例如同音异义词)。这些表示非常复杂,需要有自己独立的博客帖子。

结论

在本文中,我试图阐明 NLP 中文本表示的一些基本和高级矢量化方法背后的动机和直觉。我讨论了各种技术的优缺点以及它们之间的联系。神经文本表示仍然是 NLP 的一个不断发展的领域,其艺术状态变化很快,然而,所有这些进步的核心是本文讨论的基本思想。

参考文献

[1] 托马斯·米科洛夫,程凯,格雷戈·科拉多,杰弗里·迪恩,向量空间中单词表征的高效估计 (2013)

[2] 郭诉勒、托马斯·米科洛夫、分发陈述的句子和文件 (2014)

[3]杰弗里·潘宁顿、理查德·索切尔和克里斯托弗·曼宁。2014.手套:单词表示的全局向量。

[4] 马修·e·彼得斯,马克·诺伊曼,莫希特·伊耶,马特·加德纳,克里斯多佛·克拉克,肯顿·李,卢克·泽特勒莫耶,深层语境化的话语表征

[5] 雅各布·德夫林,张明蔚,肯顿·李,克里斯蒂娜·图塔诺娃,伯特:语言理解深度双向变形金刚前期训练

[6] 皮奥特·博亚诺夫斯基,爱德华·格雷夫,阿曼德·茹林,托马斯·米科洛夫,用子词信息丰富词向量

使用 FRONNI 计算具有置信区间的机器学习模型性能度量

原文:https://towardsdatascience.com/fronni-a-python-library-for-quickly-calculating-machine-learning-model-performance-metrics-with-3baf28eaa5c0?source=collection_archive---------31-----------------------

一个 Python 库,用于快速计算和显示带有置信区间的机器学习模型性能指标

FRONNI 这个名字来源于统计学家 Bradley Efron 的姓氏,Bradley Efron 是 bootstrap 重采样技术的发明者,John Ioannidis 是广受好评的文章《 为什么大多数发表的研究结果都是假的 》的作者。照片由 Minh Tran 在 Unsplash 拍摄

数据科学家花费大量时间评估他们的机器学习模型的性能。这样做的一种常见方法是针对分类问题的分类报告,例如内置在 scikit-learn 库中的报告(在 Github 上被引用超过 440,000 次)。类似地,对于回归问题,人们使用 r2 得分、 MSE 或 MAE 。

依赖这些的问题是,当我们的测试样本中有不平衡的和/或小的数据集时,构成每个点估计的数据量可能非常小。因此,无论对评估指标有什么样的估计,都不可能真正代表现实世界中发生的事情。相反,向读者呈现一系列置信区间的值会好得多。

例如,我们可以通过使用 bootstrap 技术从原始数据集(替换)创建数百个样本,然后丢弃最极端的 5%的值以获得 95%的置信区间,从而轻松创建任何感兴趣的指标的置信区间。

然而,当数据集很大时,如上所述运行引导程序会变成计算量很大的计算。即使是相对较小的 100 万行样本,当重采样 1000 次时,也会变成 10 亿行数据集,并导致计算花费接近一分钟的时间。当离线进行这些计算时,这不是问题,但是工程师经常在 Jupyter 笔记本上交互工作,并且希望快速得到答案。出于这个原因, Meta (又名脸书)决定为常见的机器学习指标创建一些这些计算的快速实现,例如使用 numba 库的 precision & recall,它提供了比常规 Python 并行处理代码大约 23 倍的加速。

让我们用分类问题的例子来证明这一点。考虑标准的手写数字数据集,我们正在构建一个 ML 模型来识别数字。

到目前为止,这是标准的东西。现在,我们可以使用 FRONNI 来获得精确度、召回率、f1 分数和相关的置信区间。PyPi 中有这个库,要安装 FRONNI 只需运行 pip install。

pip 安装 fronni

现在运行 FRONNI 分类报告,以获得每个类别的精确度、召回率和 f1 分数及其置信区间。您可以使用参数 n 控制自举样本的数量。

瞧啊。,它给出了每个类的精确度、召回率和 f1 分数的上限和下限。

数字分类器的 FRONNI 分类报告输出示例。

类似地,FRONNI 回归模块给出了 RMSE、r2 评分和 MAE 的置信区间。完整的文档请参考 GitHub 库。

完整的深度学习组合项目第 1 部分

原文:https://towardsdatascience.com/full-deep-learning-portfolio-project-part-1-78df161214aa?source=collection_archive---------14-----------------------

系统地寻找鸟类图像分类任务的最佳训练策略

托马斯·列斐伏尔在 Unsplash 上的照片

介绍

想从事机器学习工程师的工作,但从未实际从事过机器学习项目?然后找工作真的不容易。大多数公司都在寻找有经验的机器学习工程师。我所说的经验并不是指你参加过机器学习在线课程。不要误解我的意思:参加机器学习在线课程以获得更多关于该主题的知识总是很棒的!然而,对于一个雇主来说,正确地评估一门在线课程是非常困难的。有些很容易,有些很有挑战性。然而,雇主能评估好的是自己的项目。在那里,他可以直接看到你如何处理某些话题,以及你已经从项目中获得了什么经验。

然而,在这些项目中,你不应该只关注机器学习部分,这主要是在 Jupyter 笔记本上完成的,但你也应该考虑部署。因为现在训练深度学习模型不再具有挑战性。像 Keras 这样的库允许你在几行代码内创建和训练一个深度学习模型。然而,如果你能够开发一个成熟的应用程序,那么你肯定会更有趣。此外,如果你已经开发了一个网页,并可以在那里展示你训练有素的模型,而不是让他浏览你的 Jupyter 笔记本,在那里只能看到代码和打印输出,那么你可以更好地说服一个没有技术背景的招聘人员。

为此,我创作了两篇文章,其中系统地发现并应用了深度学习训练策略,并通过网站部署了训练好的模型。

在这个系列的第一部分,我想向你展示一个如何为图像分类任务找到一个好模型的系统方法。作为数据集,我决定使用来自 Kaggle 的开源鸟类物种数据集,你可以在这里找到。代码和所有文档都可以在我的 Github 页面这里找到。代码是用 Python 写的。

在本系列的第二部分,我将向您展示如何使用 html 和 Flask 开发一个完整的 web 应用程序,包括前端和后端。你可以在这里找到文章。

如果你对我如何使用 Docker 和 Github Actions 将完整的 web 应用程序部署到 AWS Elastic Beanstalk 感兴趣,那么我可以推荐你阅读我的这篇文章。

内容

在第一部分中,我介绍了数据集,并已经对输入数据进行了一些预处理。在第二部分,我将向您展示我如何使用 Tensorflow 创建输入管道,以及它的代码是什么样子。方法部分描述了我为找到最佳训练策略而进行的各种评估。每当要训练 CNN 时,可以使用这些评估。结果部分显示了最终培训策略的培训结果。结论部分总结了这个项目的结果,而展望部分提供了本系列第二篇文章的参考。

探索性数据分析和预处理

作为第一步,我将提供的“Bird_Species.csv”文件加载到 pandas 数据框中(图 1)。

图 1:初始加载的数据帧头。

数据集的创建者还提供了第二个 csv 文件,包含图像的类和一些元数据。我还将这个 csv 文件加载到 pandas 数据框中(图 2)。

图 2:包含类和图像形状的数据帧的头部。

然后,我使用第二个数据框快速检查了该数据集中不同类的数量,并将其与“Bird_Species.csv”文件(代码 1)中唯一标签的数量进行了比较。

代码 1:读入数据文件并检查所有的类是否都存在于完整的数据集中。

有趣的是,根据“class_dict.csv”文件,鸟类有 300 个不同的类别,但在整个数据集中,只有 285 个不同的类别。因此,我检查了哪些类没有出现在数据集中,并查看了文件夹,以确定它们是真的没有出现,还是只是在“Bird_Species.csv”文件中丢失了。确实有缺失班级的图片。这意味着现有的 csv 文件不正确。所以我首先创建了一个干净的 csv 文件,保存它并在这个项目的其余部分使用它。这一步的代码可以在“Make_Clean_Dataset.ipynb”笔记本这里找到。

既然数据集是干净的,我开始进一步研究它。我从绘制数据集的一些随机示例图像开始,以便对图像的外观有所了解。图 3 显示了两个示例鸟图像。

图 3:鸟类数据集的两个示例图像。左图是一只非洲冠鹤,右图是一只冈比亚鹌鹑。

作为下一步,我绘制了已经由作者创建的训练和测试集的分布图(图 4 和图 5)。这对于检查数据集是否不平衡以及确保测试分布和训练分布大致相同非常重要。

图 4:从数据集作者创建的训练集的分布。

图 5:从数据集作者创建的测试集的分布。

可以看出,训练集是不平衡的,而测试集是完全平衡的。这清楚地表明测试集来自不同于训练集的分布。这可能会导致模型在测试集上表现良好,但在真实世界数据上表现不佳,因为测试分布没有反映“真实”分布。因此,我决定使用 Scikit-Learn 的分层混洗技术创建自己的训练、验证和测试集。但是在分割数据之前,我还对标签进行了一次性编码,以匹配 CNN 所需的输入格式。代码 2 显示了这些步骤的代码,包括清理后的数据集 csv 文件的初始加载。

代码 2:用于通过执行分层混洗分割来创建训练、验证和测试集的代码。

图 6 和图 7 显示了分层洗牌拆分后训练集和测试集的分布。这两个发行版现在来自同一个发行版。

图 6:使用分层洗牌拆分后的训练集分布。

图 7:使用分层洗牌拆分后测试集的分布。

训练数据集有点不平衡,这应该不是问题。但是让我们稍后检查过采样是否可以提高这个数据集的性能。

这里没有添加验证集的数字,但是它与测试集和训练集具有相同的分布。

创建输入管道

对于训练深度学习模型来说,拥有一个好的输入管道总是很重要的。Tensorflow 通过其 ImageDataGenerator 类为您提供了很好的支持。这个类允许您指定一些预处理,让您从一些数据扩充中选择,并允许您在训练期间批量加载图像。这一点尤其重要,因为对于大型数据集,如果在训练之前必须先加载一次所有图像,将会占用大量 RAM。

对于鸟类分类,我创建了以下输入管道步骤:

  1. 应用一些随机选择的数据扩充,这样大约 10%的数据没有被扩充。
  2. 归一化图像像素值,使它们在(0,1)的范围内。

我使用了一些来自 imgaug Python 库的基本数据扩充,以增加数据集中的变化。这个库非常有用,因为它实现了几乎所有你能想到的扩充。本项目使用的数据扩充是通过对示例图像应用扩充并评估图像是否仍然有意义来手动选择的。在上面提到的 Github 存储库中,可以在 Jupyter 笔记本中看到不同应用增强的评估结果,称为“Check Augmentations.ipynb”。一般来说,可以使用这些增强,并且可以一次用一个额外的增强来训练模型,并且将其性能与没有任何增强的基线模型进行比较。但是为了这个项目,我决定不做这个评估,因为我假设每一个增强都会导致与基线模型相比的改进。

我使用了以下扩展(图 8):

  1. 左右翻转图像。
  2. 将像素值乘以偏移量。
  3. 盐和胡椒。
  4. 伽玛对比度变化。
  5. 向像素值添加偏移量。
  6. 添加附加高斯噪声。
  7. 应用运动模糊。
  8. 应用仿射变换。
  9. 旋转图像。
  10. 应用弹性变换。

增强“添加”和“伽玛对比度”从不同时使用,因为这可能导致不真实的图像。

图 8:应用增强的概述(图片由作者提供)。

代码 3 展示了创建输入管道的完整 Python 代码,同时使用了 Tensorflow 的“flow_from_dataframe”选项。这允许在训练期间分批加载图像。您只需要一个 csv 文件,其中第一列包含图像的名称,其他列包含该图像的标签。为了首先找到最佳的 CNN 架构,我决定使用 8 的批量大小,并将图像的大小固定为(224,224)。

代码 3:使用 Tensorflow 和 ImageDataGenerator 类创建输入管道的代码。

方法学

输入管道已创建。现在是时候找到最适合的训练策略了。首先,比较了一些最先进的 CNN 架构,并选择性能最佳的架构作为本项目剩余部分的架构。其次,比较不同的图像尺寸,以便找到最佳的图像尺寸。第三步,尝试过采样来处理稍微不平衡的数据集。最后一步,使用贝叶斯超参数搜索来搜索最优超参数。

方法部分的代码没有包含在本文中,因为它太长了。请随意检查我的 Github Jupyter 笔记本,查看并复制我创建的代码。我只包含了对数据帧进行过采样的代码,因为这可能是更有趣的代码部分。

CNN 架构比较

有许多不同的 CNN 架构可用于鸟类分类器。在本项目中,选择了六种不同的 CNN 架构(表 2)并进行相互比较。每种架构都用于训练具有表 1 中给出的超参数的鸟分类器。最后,最佳验证 f1 分数被存储并用于找到最佳 CNN 架构。这里,仅使用最佳验证 f1 分数,并且忽略了这一点,即每个体系结构具有不同的训练复杂性,并且可能一个体系结构仅导致稍差的验证 f1 分数,但是具有比达到更高验证 f1 分数的模型少得多的参数。但是对于未来的优化,也可以考虑训练复杂度,并且可以将其包括在决定中,将哪个编码器架构用于最终的鸟分类器。表 2 还显示了最终结果。可以看出,DenseNet121 实现了最佳的 f1 验证分数,因此被用作鸟类分类器的最终编码器架构,也用于该项目的其他评估。图 5 显示了不同编码器在训练过程中的 f1 分数,图 4 显示了训练过程中的损失值。

表 1:用于 CNN 架构比较的超参数。

图 4:不同编码器架构的训练过程中的损耗值。使用分类交叉熵作为损失函数。

图 5:F1-不同编码器架构训练过程中的得分。

表 2:在训练过程中使用的 CNN 架构和它们的最好成绩。

图像大小比较

在通往最佳训练策略的道路上,接下来应该找到最佳图像尺寸。将评估和比较四个不同的选项。使用表 1 中的超参数为四种图像尺寸中的每一种训练 DenseNet。结果可以在表 3 中找到,其中再次将最佳验证 f1 分数作为决策的衡量标准。图 6 和 7 显示了在不同图像尺寸的训练过程中 f1 分数和损失值的结果。

正如人们所猜测的:图像越大,模型的性能越好。然而,从图像大小 192x192 到 224x224,最佳验证 f1 分数仅增加 0.4%。因此,我决定使用 192x192 作为图像大小,以便减少可训练参数的数量,并稍微加快训练过程。

图 6:F1-在用不同图像尺寸训练 DenseNet 的训练过程中的分数。

图 7:用不同图像尺寸训练 DenseNet 的训练过程中的损失值。使用分类交叉熵作为损失函数。

表 3:最佳验证 f1-用不同图像尺寸训练 DenseNet 的得分和准确度。

过采样

如前所述,数据集略有不平衡。因此,可以使用过采样来更好地平衡数据集,并避免模型更偏向多数类而预测少数类不太准确的风险(图 8,代码 4)。

代码 4:获取数据帧并对其进行过采样以获得完全平衡的数据帧的代码。过采样是通过对少数类更频繁地重用图像来实现的。

然后使用过采样数据集和来自表 1 的超参数来训练 DenseNet121,除了时期的数量减少到 20 个时期。这是由于过采样,因此是模型应该学习得更快的原因,因为相同的图像在一个训练时期内不止一次可用。过采样模型的最佳验证 f1 分数为 95.4%,这与没有应用过采样的情况几乎相同。因此,过采样不用于训练最终的鸟类分类器,因为它也需要更多的训练时间,并且通常更容易过拟合。

图 8:应用过采样后的训练数据集。训练集现在完全平衡,这是通过复制少数类的相同图像来实现的,只要每个类具有相同数量的样本。

贝叶斯超参数搜索

作为找到最佳训练策略的最后一步,使用贝叶斯超参数搜索来优化超参数。贝叶斯搜索的优点在于,它在寻找最优超参数方面比随机搜索更有效,并且比网格搜索需要更少的迭代。κ为 3 的高斯过程被用作优化策略。手动提供四个初始点,这将有助于将优化过程引向最佳方向。贝叶斯优化被执行 12 次迭代。使用称为“置信下限”的获取函数,并且它获得最佳验证 f1 分数作为要优化的度量。置信下限试图最小化其优化度量。因此,使用负的最佳验证 f1 分数。表 4 显示了超参数使用的搜索空间,而表 5 显示了最佳参数。衰减率指定学习率在每个衰减步骤时期应该减少多少。

图 9 显示了贝叶斯超参数搜索的收敛图。可以看出,最佳参数是在最后一次迭代中找到的。这是由于贝叶斯优化的性质。在开始阶段,存在大量的不确定性,Bayes 模型在非最优区域采样较多。但是最后,模型在最佳区域中采样更多,因此找到越来越好的参数。

表 4:贝叶斯超参数优化的优化超参数及其搜索空间。

表 5:通过贝叶斯超参数搜索找到的最佳超参数。

图 9:贝叶斯优化的收敛图。该图显示了迭代次数和获得的最佳 f1 分数。

结果

使用在方法部分中找到的所有发现来训练鸟类分类器。鸟类分类器现在已经训练了 30 个时期,根据验证 f1 分数的最佳模型被存储为 Tensorflow 模型(图 10)。之后,加载验证 f1 分数为 96.2%的最佳模型,并在保留测试集上进行评估,以检查最终 birds 分类器在真实世界数据上的性能。最佳模型在保留测试集上获得了几乎 96%的 f1 分数,这与在训练过程中获得的最佳验证 f1 分数几乎相同。这表明,该模型在真实世界数据上表现得非常好,并且该模型在训练和验证数据上没有过度拟合。

图 10:用于训练最终鸟类分类器的训练指标。

结论

最终的鸟类分类器在保留测试集上实现了几乎 96%的 f1 分数。由于其良好的性能,DenseNet121 被用作 CNN 的底层架构。作为目标图像尺寸,使用 192x192 像素的尺寸。训练集不是过采样的,因为在过采样的训练集上训练的模型与在非过采样的训练集上训练的模型获得了近似相同的验证 f1 分数。利用贝叶斯超参数搜索优化了一些超参数。

观点

在本系列的第二部分中,我开发了一个 API,前端用 HTML 编写,后端应用程序使用 Python 库 Flask。如果你对它的工作原理感兴趣,请阅读第二篇文章。你可以在这里找到第二篇。总的来说,我总是建议您将最终的机器学习应用程序嵌入到可部署的应用程序中,因为这是机器学习工程师在一天结束时需要考虑的问题。

谢谢你把我的文章看完!我希望你喜欢这篇文章和我参与的项目。如果你想在未来阅读更多类似的文章,请关注我,保持更新。

完整的深度学习组合项目第 2 部分

原文:https://towardsdatascience.com/full-deep-learning-portfolio-project-part-2-e37d09a451fa?source=collection_archive---------31-----------------------

用 Flask 和 HTML 创建可部署的 Web 应用程序

沙哈达特·拉赫曼在 Unsplash 上拍摄的照片

介绍

本文是系列文章的第二部分。在这里,我着重于构建使用在第一篇文章中开发的 birds 分类器的 web 应用程序。正如我在第一部分提到的,成为一名机器学习工程师不仅意味着在 Jupyter 笔记本上训练模型,还意味着能够创建一个可以由最终用户直接部署和使用的应用程序。此外,这对你的投资组合也很有帮助,因为你现在有了一份可以展示给招聘人员的申请。这非常有帮助,因为他们通常没有技术背景,因此不想通过 Jupyter 笔记本来了解您在这个项目中开发了什么。

在本文的第一部分,我想引导您使用 html 创建前端部分。在第二部分,我将向您展示如何使用 Python 库 Flask 开发后端。

你可以在我的 Github 资源库中找到与这个项目相关的所有代码。图 1 展示了运行中的最终应用程序。

图 1:开发的 web 应用程序使用情况的 GIF

创建前端

每个应用程序都需要一个前端。前端部分非常重要,因为这是用户将要与之交互的部分。这个项目的前端是使用 html 开发的。html 代码在代码笔中创建。Code Pen 是一个网页,用户可以在交互式环境中在线创建和可视化他们的 html 代码。这非常适合快速制作网页原型!

这里重要的部分是从第 37 行到第 62 行。在这里,一个 base64 图像被创建并可视化,以防用户点击“选择文件”按钮。然后,base64 字符串被格式化,以便稍后可以发送到后端应用程序。当用户按下“预测”按钮时,用 POST 命令调用托管网页的预测端点。然后,预测端点对输入图像进行预处理,并将其提供给鸟类分类器模型。这将在下一节中进一步解释。

predict.html 文件存储在一个名为“模板”的文件夹中。这是以后烧瓶应用所需要的。

如果你不熟悉开发 html 代码,我真的可以向你推荐这个关于 html 编码的 Youtube 速成班。

代码 1:创建前端应用程序的 Html 代码。

创建后端

后端应用程序负责后台发生的“魔术”。birds 分类器的后端应用程序是使用 Python 库 Flask 开发的,这是一个易于使用的 web 框架。代码 2 展示了后端应用程序的完整 Python 代码。在第 19 行,应用程序本身被创建。

第 21 行是 Python 修饰符,定义了默认路由。该功能在应用程序启动时执行。在“我的表单”功能中,前端 html 文件链接到这个应用程序。

“get_model”函数加载经过训练的 Keras 模型,并将其存储在全局模型变量中。此外,还提供了预处理功能。此功能预处理输入图像,使其具有网络预期的输入格式。“load_classes”函数仅用于在以后将预测的标签链接到相应的类名。

在第 49 行,定义了预测路线。当前端应用程序中的预测按钮被调用时,这个路由被调用。在这里,图像被提取、预处理并馈送到网络。然后网络进行预测。预测的类别标签和输出分数然后被发送回前端应用程序,使得它可以在网站上显示。

main 函数加载模型和类,并在端口 5000 启动应用程序。

启动 Python 应用程序后,您可以在浏览器中打开链接 http://127.0.0.1 :5000 下的网站。

代码 2:用于创建后端应用程序的 Python 代码。

结论

所以现在已经开发了一个成熟的机器学习应用。在本系列的第一篇文章中,找到了最佳的训练策略,并训练了最终的模型。本文开发了相应的 web 应用程序。这个应用程序现在可以部署到像 AWS 这样的云提供商。当你想阅读我如何创建一个 AWS Elastic Beanstalk 的持续部署管道,这样每个人都可以访问创建的 web 应用程序,那么我可以推荐你阅读我的媒体文章。

谢谢你把我的文章看完!我希望你喜欢这篇文章和我参与的项目。如果你想在未来阅读更多类似的文章,请关注我,保持更新。

在服务器上全面部署 Jupyter 笔记本电脑,包括 TLS/SSL 和加密功能

原文:https://towardsdatascience.com/full-deployment-of-jupyter-notebooks-on-a-server-including-tls-ssl-with-lets-encrypt-b30cc758881e?source=collection_archive---------8-----------------------

在服务器或云上完成 Jupyter 笔记本电脑或 JupyterLab 的设置和安装

图片来自维基共享资源

Jupyter Notebook 是一个强大的工具,但是你如何在服务器上使用它呢?在本教程中,你将看到如何在服务器上设置 Jupyter notebook,如数字海洋、海兹纳、 AWS 或其他大多数可用的主机提供商。此外,您将看到如何通过 SSH 隧道或 TLS/SSL 使用 Jupyter notebooks 和让我们加密。本文原载此处。

Jupyter 是一个开源的 web 应用程序,支持从浏览器进行交互式计算。您可以创建包含实时代码的文档、带有 Markdown 的文档、等式、可视化甚至小部件和其他有趣的功能。Jupyter 来自支持的三种核心语言:Julia、Python 和 r。Jupyter 连接到使用特定语言的内核,最常见的是 IPython 内核。它支持各种各样的内核,你应该能找到你需要的大多数语言。本教程写于 JupyterLab ,Jupyter 笔记本的下一步发展:

在本教程中,我们将使用 Ubuntu 18.04/20.04 服务器,但大多数步骤应该与 Debian 9/10 发行版相当相似。我们将首先创建 SSH 密钥,在服务器上添加一个新用户,并使用 Anaconda 安装 Python 和 Jupyter。接下来,您将设置 Jupyter 在服务器上运行。最后,你可以选择在 SSH 隧道上运行 Jupyter 笔记本,或者在 SSL 上运行让我们加密。

创建 SSH 密钥

我们从一个全新的服务器开始,为了在访问您的服务器时增加更多的安全性,您应该考虑使用 SSH 密钥对。这些密钥对由上传到服务器的公钥和保存在机器上的私钥组成。一些主机提供商要求您在创建服务器实例之前上传公钥。要创建新的 SSH 密钥,您可以使用 ssh-keygen 工具。要创建密钥对,您只需键入以下命令:

ssh-keygen

如果您愿意,这将提示您添加文件路径和密码。还有其他选项参数可供选择,如公钥算法或文件名。你可以在这里找到一个非常好的教程关于如何用 ssh-keygen 为 Linux 或 macOS 创建一个新的 SSH 密钥。如果您使用的是 Windows,您可以使用 PuTTYgen 创建 SSH-keys,如这里的所述。如果您的主机提供商在创建前不需要公钥,您可以使用 ssh-copy-id 工具复制公钥:

ssh-copy-id -i ~/.ssh/jupyter-cloud-key user@host

最后,您可以通过以下方式连接到您的服务器:

ssh -i ~/.ssh/id_rsa root@host

其中~/.ssh/id_rsa是您的 ssh 私有密钥的路径,而host是您的服务器实例的主机地址或 IP 地址。

添加新用户

在一些服务器中,您是作为根用户开始的。直接使用根用户被认为是一种不好的做法,因为它有很多特权,如果某些命令是意外执行的,这些特权可能是破坏性的。如果您已经有用户,可以跳过这一部分。请注意,您可以将以下所有命令中的cloud-user替换为您想要的用户名。首先创建一个新用户:

adduser cloud-user

这个命令会问你几个问题,包括密码。接下来,您需要向该用户授予管理权限。您可以通过键入以下命令来完成此操作:

usermod -aG sudo cloud-user

现在你可以用su cloud-user切换到新用户,或者用ssh cloud-user@host连接到你的服务器。或者,您可以将 root 用户的 SSH 密钥添加到新用户中,以提高安全性。否则,您可以跳到下一节如何安装 Anaconda。现在,如果您有根用户的现有 SSH 密钥,您可以将公钥从根主文件夹复制到用户主文件夹,如下所示:

mkdir /home/cloud-user/.ssh
cp /root/.ssh/authorized_keys /home/cloud-user/.ssh/

接下来,您需要更改文件夹和公钥的权限:

cd /home/user/
chmod 700 .ssh/
chmod 600 .ssh/authorized_keys

如果您正在为您的用户使用密码,您需要更新/etc/ssh/sshd_config:

nano /etc/ssh/sshd_config

在这里,您希望找到行PasswordAuthentication no,并将no更改为yes,以允许密码验证。最后,您希望通过键入service ssh restart来重启 SSH 服务。对于其他发行版,请看一下这个指南,在那里你也会看到如何设置防火墙。

安装 Anaconda

Anaconda 是 Python(和 R)的开源发行版,用于科学计算,包括包管理和部署。有了它,你就有了你需要的大部分工具,包括 Jupyter。要安装 Anaconda,请转到 linux 的下载,并复制最新 Python 3.x 版本的 Linux 安装程序链接。然后你可以用wget下载安装程序:

wget [https://repo.anaconda.com/archive/Anaconda3-5.2.0-Linux-x86_64.sh](https://repo.anaconda.com/archive/Anaconda3-5.2.0-Linux-x86_64.sh)

接下来,您可以使用bash安装 Anaconda,如下所示:

bash Anaconda3-5.2.0-Linux-x86_64.sh

在安装过程中,当安装过程中出现以下提示时,键入yes非常重要:

Do you wish the installer to prepend the Anaconda3 install location
to PATH in your /home/user/.bashrc ? [yes|no]

安装完成后,您希望通过 Anaconda 用以下命令初始化conda命令行工具和包管理器:

source .bashrc 
conda update conda

这两个命令在您的服务器上设置 Anaconda。如果您已经用 sudo 运行了 Anaconda bash 文件,您将得到一个Permission denied错误。你可以通过输入sudo chown -R $$USER:$$USER /home/user/anaconda3来解决这个问题所示的问题。这将使用 chown 命令将该文件夹的所有者更改为当前用户。

正在启动 Jupyter 笔记本服务器

Jupyter 与 Anaconda 一起安装,但是我们需要做一些配置以便在服务器上运行它。首先,您需要为 Jupyter 笔记本创建一个密码。您可以通过用ipython启动 IPython shell 并生成一个密码散列来实现这一点:

from IPython.lib import passwd
passwd()

暂时保存这个结果散列,我们稍后会用到它。接下来,您想要生成一个配置文件,您可以通过键入。

jupyter-notebook --generate-config

现在用sudo nano ~/.jupyter/jupyter_notebook_config.py打开配置文件,将下面的代码复制到文件中,并用您之前生成的代码替换这个代码片段中的散列:

c = get_config()  # get the config object
# do not open a browser window by default when using notebooks
c.NotebookApp.open_browser = False
# this is the password hash that we generated earlier.
c.NotebookApp.password = 'sha1:073bb9acaa67:b367308802ab66cb1d7654b6684eafefbd61d004'

现在你应该设置好了。接下来,您可以决定是使用 SSH 隧道还是使用 SSL 加密并通过您自己的域名访问您的 jupyter 笔记本。

Linux 或 MacOS 上的 SSH 隧道

您可以通过在负责端口转发的ssh命令中添加-L参数来隧道连接到您的服务器。第一个8888是您将在本地机器上访问的端口(如果您已经为另一个 juypter 实例使用了这个端口,那么您可以使用端口 8889 或不同的开放端口)。你可以用localhost:8888在你的浏览器上访问它。第二部分localhost:8888指定从服务器访问的跳转服务器地址。因为我们希望在服务器上本地运行笔记本,所以这也是 localhost。这意味着我们从服务器通过端口转发到我们机器上的localhost:8888来访问localhost:8888。下面是该命令的样子:

ssh -L 8888:localhost:8888 cloud-user@host

如果您的本地机器上已经运行了另一个 Jupyter 笔记本,您可以将端口更改为8889,这将导致命令:

ssh -L 8889:localhost:8888 cloud-user@host

现在,您可以在服务器上为您的项目创建一个笔记本文件夹,并在其中运行 Jupyter notebook:

mkdir notebook
cd notebook/
jupyter-notebook

你也可以使用 JupyterLab 来代替,这是一个更强大的接口,它也预装了 Anaconda。你可以通过输入jupyter-lab而不是juypter-notebook来启动它。

让我们加密的 SSL 加密

也可以对你的 jupyter 笔记本使用 SSL 加密。这使您能够通过互联网访问您的 Jupyter 笔记本,从而方便地与您的同事分享结果。要做到这一点,您可以使用让我们加密,这是一个免费的认证中心(CA) ,它为 TLS/SSL 证书提供了一种简单的方法。这可以用他们的 certbot 工具全自动完成。要找到您系统的安装指南,请查看此列表。对于 Ubuntu 18.04,安装如下所示:

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python-certbot-apache

现在,您可以为您拥有的域运行 certbot:

sudo certbot certonly -d example.com

完成提示后,您应该会看到以下输出:

IMPORTANT NOTES:- Congratulations! Your certificate and chain have been saved at:/etc/letsencrypt/live/example.com/fullchain.pemYour key file has been saved at:/etc/letsencrypt/live/example.com/privkey.pemYour cert will expire on 2019-05-09\. To obtain a new or tweakedversion of this certificate in the future, simply run certbot againwith the "certonly" option. To non-interactively renew *all* ofyour certificates, run "certbot renew"- If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donateDonating to EFF:                    [https://eff.org/donate-le](https://eff.org/donate-le)

太好了!您已经准备好了证书和密钥文件。现在,您可以使用 jupyter 笔记本配置文件中的证书和密钥文件。在此之前,您需要更改证书和密钥文件的所有者(用您自己的用户名更改user):

sudo chown user /usr/local/etc/letsencrypt/live
sudo chown user /usr/local/etc/letsencrypt/archive

接下来,您可以将以下代码添加到~/.jupyter/jupyter_notebook_config.py配置文件中:

# Path to the certificate 
c.NotebookApp.certfile = '/etc/letsencrypt/live/example.com/fullchain.pem' 
# Path to the certificate key we generated
c.NotebookApp.keyfile = '/etc/letsencrypt/live/example.com/privkey.pem' 
# Serve the notebooks for all IP addresses
c.NotebookApp.ip = '0.0.0.0'

最后,你可以通过https://example.com:8888安全地访问 Jupyter 笔记本。只是确保使用https://而不是http://。如果您犯了任何错误,您可以用sudo certbot deletesudo certbot delete --cert-name example.com删除 certbot 证书。如果您使用的是防火墙,请确保端口8888是打开的。这里有一个关于使用简单防火墙(UFW) 防火墙的很好的指南。

结论

您已经从头到尾学习了如何为服务器设置 Jupyter。随着您设置的每一台服务器,这项任务变得越来越容易。请务必深入研究 Linux 服务器管理的相关主题,因为一开始使用服务器可能会令人生畏。使用 Jupyter,您可以访问各种各样的内核,这些内核使您能够使用其他语言。所有可用内核的列表可以在这里找到。我希望这是有帮助的,如果你有任何进一步的问题或意见,请在下面的评论中分享。

我在之前的教程中提到了如何在 Jupyter 笔记本中使用虚拟环境。还有一个将 Jupyter 作为 Docker 容器运行的选项。例如,您可以使用jupyter/data science-notebook容器。你可以在本指南的中阅读更多关于如何使用 Jupyter 和 Docker 的信息。关于进一步的安全考虑,请看一下 Jupyter 笔记本服务器中的安全性。以下是我从中学到的更多链接,可能对你也有用:

  • 初始服务器设置
  • 运行笔记本服务器
  • 如何为 Python 3 设置 Jupyter 笔记本
  • 如何使用 Certbot 独立模式检索加密 SSL 证书
  • UFW 基础:通用防火墙规则和命令
  • 在 Jupyter 笔记本和 Python 中使用虚拟环境
  • 用 Jupyter 笔记本制作幻灯片

更多参考

  • 如何在 Jupyter 和 IPython 中使用 letsencrypt 证书
  • 向 Jupyter Hub 添加 SSL 和域名

梯度下降的完全实现

原文:https://towardsdatascience.com/full-implementation-of-gradient-descent-no-holding-back-86e688f36064?source=collection_archive---------38-----------------------

深入研究梯度下降算法的数学。

这篇文章推导了实现梯度下降的算法。它又脏又丑又乏味!自己推导它是一个有趣的练习,但最终,它只是识别模式。不要让这个页面让你脑袋爆炸,让你放弃 AI!仅仅知道如何使用算法是最重要的(即使这样也可以认为你可以只使用 Keras),但是为什么不自己尝试一下并从中获得一些乐趣呢!我在这里包括推导,只是因为我知道当我学习人工智能时,我会喜欢看它。

我们现在知道,我们必须找到误差函数相对于每个权重的梯度,以最小化我们的误差(如果你不知道我刚才说了什么,请学习/复习如何训练神经网络这里)。这很好,但是我们如何用代码来实现呢?你可以想象,如果我们有一个 5、6 层或更多层的神经网络,每层都有数百或数千个神经元,找到梯度会有多困难。

我们知道要找什么(梯度),现在我们只需要弄清楚如何找到它。

我们可以用导数的定义。仔细检查每一个重量,并稍微增加一点,然后将误差的变化除以这个微小的量。这将给出这个特定重量的∂E/∂W。如果我们对所有的重量都这样做,我们就会得到梯度。

但是客观地看,我训练用来玩雅达利游戏的神经网络有 1,685,667 个权重,我必须更新它们大约 1000 万次。对于这样的网络来说,使用导数的定义太费时间了。

由于神经网络具有非常高的重复率,看起来我们可以找到一种算法,以一种有效的方式为我们找到梯度。为了尝试创建这种算法,我们将首先手动写出一个相对较小但较深的神经网络的前进和更新阶段。然后,我们将在这个过程中寻找模式,尽可能地简化它。

这是我们将用来推导梯度下降算法的神经网络:

这一次我们实施的是偏向。请注意,只要我们将偏置“输入”保持为 1,上述实现与仅将偏置添加到每个神经元的加权和上完全相同。偏向是蓝色的,任何与偏向相关的东西在这个页面上都是蓝色的。*****图片作者***

正向阶段

首先,非常重要的是要记住,我们绘制神经网络作为这个计算图,是为了帮助我们可视化正在发生的事情。但是,如果我们要找到我们的梯度下降算法,我们将需要写出完成的计算。嗯,我们这里有很多参数!我们真的为丑陋的索引做了大量的参数!

让我写出这个神经网络中所有的参数。然后让你了解我的索引惯例。

图片作者

上面的 Xbar 是每一层的【输入】列表。注意,Xbar 中每个列表的大小对应于每层中神经元的数量。Xbar[0]是带有偏差的初始输入数据,Xbar[1]是带有级联偏差的 X[0]的激活加权和,Xbar[2]是带有级联偏差的 X[1]的激活加权和,依此类推。

Wbar 是连接每一层的所有权重的列表。每个列表都应该有大小:

(不包括偏差的下一层神经元的数量,包括偏差的当前层神经元的数量)。

例如,第一个权重列表有 3 行,因为在下一层中有 3 个神经元(不包括偏差)。该列表有 3 列,因为有 2 个输入和 1 个偏差。

现在,左上角的索引显示了特定元素所在的层。右上角的指数告诉我们正在谈论的层中的输入神经元,右下角的指数告诉我们将要输入什么。

X 是层的输入,w 是层的权重,z 是通过激活函数之前的加权和。*****图片作者***

现在我们在记谱法上达成了一致。这是神经网络的前向阶段。从左到右,从上到下,写出计算结果:

a(z)是我们应用于 z 的激活函数。退一步,看看在高层次上发生了什么。不要让你的脑袋爆炸,试图同时意识到每个细节!*****图片作者***

最上面一行计算将我们从第一层输入带到第二层输入。第二行将我们从第二层输入带到第三层输入,依此类推,直到我们到达一个输出。

反向相位

好了,现在让我把我们要找的东西写出来;

图片作者

我们将试图找到足够的第三和第二个导数列表来确定一个模式。利用链式法则,以及大量盯着的问题,我们可以证明这些导数等于下列;

我突出显示了我认识的任何模式,这将有助于简化。第二梯度矩阵只是部分完成。我们只需要足够的证据来确定模式。图片作者

如果上面的照片有点模糊,建议你下载一份,研究一段时间。我首先计算导数,然后突出矩阵中的相似之处。模式识别是这个游戏的名字。

这可能很难理解你自己。经常回头看看前进阶段的照片。如果你从这个错误开始,然后用链式法则让你自己回到你试图找到的重量,你会发现这很简单,但是很乏味。

现在,我们试图找到一种更简单的方法来表达上述方程。如果你记得你的线性代数,你会发现上面的方程可以简化为:

那个里面有 X 的圆圈表示我们正在对行进行乘法运算。矩阵之间的点表示我们正在应用点积。图片作者

看多漂亮!你可以注意到所有红色的东西都和上面一行中高亮显示的一样。这意味着我们可以从最后一层开始,初始化一个术语,称之为ψ,就是绿色的。然后,当我们回到之前的层时,我们可以用该层中的绿色来更新ψ(红色的就是ψ的当前值)。现在,要找到该层的梯度,我们只需将ψ乘以∂Z/∂w 行。当你插入数值时,这是非常漂亮的,下面我假设均方误差函数和 sigmoid 激活函数。

图片作者

现在,我们将更新打包成一个非常简单的 for 循环:

图片作者

摘要

好吧,我知道你在想什么。刚刚发生了什么事!?我所做的只是识别模式!没有比链式法则更复杂的东西被用到,我只是用了很多。如果你只是相信我的结果,而不是自己推导出来的,我不会怪你。在实践中,我们无论如何都将使用 Keras 来实现,但是现在您已经知道如何自己做了,您不必为这样做而感到内疚。

一如既往,我们还没有真正理解这一点!直到我们应用它,我们才会理解它。我在这里用 python 实现了一个简单的实现,在这个链接中我还构建了一个有用的 python 类,我们稍后会用它来识别手写数字。

感谢您的阅读!如果这篇文章在某种程度上帮助了你,或者你有什么意见或问题,请在下面留下回复,让我知道!此外,如果你注意到我在某个地方犯了错误,或者我可以解释得更清楚一些,那么如果你能通过回复让我知道,我会很感激。

这是一系列文章的继续,这些文章从头开始对神经网络进行了直观的解释。其他文章请参见下面的链接:

第 1 部分:什么是人工神经网络

第二部分:如何从零开始训练神经网络

第 3 部分:梯度下降的完全实现

第四部分:梯度下降的实现(一个例子)

第 5 部分:如何在 python 中对手写数字进行分类

满秩联合分析

原文:https://towardsdatascience.com/full-rank-conjoint-analysis-af5ced77070b?source=collection_archive---------20-----------------------

用于洞察消费者偏好的技术

由吉纳·戈麦斯
与格雷戈·佩奇

我们为这个练习建立了数据集,通过模拟一项调查,要求回答者对一系列 24 个独立的手机月套餐进行排序,1 是最好的,24 是最差的。在向 1000 名受访者展示调查后,每组选项都会根据其在所有受访者中的平均排名获得一个排名。

这些计划包括互联网数据的两个选项、通话时间的三个选项、音乐的两个选项和社交网络接入的两个选项。这些功能基于一家哥伦比亚电信公司提供的真实电话套餐。价格大致基于实际功能价格,从哥伦比亚比索兑换回美元。

数据集有 7 个变量,变量的规格见下表:

bundleID: 数据集每一行的 ID。

千兆字节:在互联网上导航的千兆字节数。选项是 4 和 10。

分钟:人们必须拨打电话的分钟数。选项 100、200 和 400。

音乐:计划是否包含免费获取音乐(“是”或“否”值)。

social_networks: 计划是否包括无限制访问社交网络(“是”或“否”值)。

价格:计划在哥伦比亚的价格,以美元表示。

排名:根据近 1000 名受访者的调查答案,对 1 至 24 个首选预付费计划进行排名。

flip 恶作剧:每个捆绑包的“翻转”等级,呈现为受青睐的捆绑包采用较高的值,而不是较低的值。这将使线性回归系数更容易解释。

当受访者评估捆绑包时,他们会考虑成本—否则,我们可以预期受访者会简单地选择“最佳”或功能最多的选项。这里显示了增加的功能成本:

通过添加上表中的功能,可以找到任何特定捆绑包的成本。例如,一个 10gb 的套餐,400 分钟的通话时间,没有音乐,可以访问社交网络,价格为 2.50 美元+3.35 美元+0.00 美元+1.55 美元,或 7.40 美元。一个 4.5 的套餐,有 200 分钟的通话时间,可以访问音乐,但不能访问社交网络,价格为 1.50 美元+2.95 美元+1.60 美元+ 0.00 美元,即 6.05 美元。

为了运行线性回归并能够更容易地读取结果,我们修改了 rank 变量,将#1 包的 CorrectedRank 值设为 24,将#2 包的 CorrectedRank 值设为 23,将#3 包的 CorrectedRank 值设为 22,依此类推。

为什么要使用完整的排名系统?

在之前的一篇文章中,我们写了一个基于评级的联合分析系统,在这个系统中,调查受访者考虑游乐园乘坐的功能,从 1 到 10 对各种功能组合进行评级。

虽然这种系统非常适合线性建模,但它有一个明显的缺陷——当要求在 1-10 的范围内赋值时,并非所有受访者都使用相同的评级“基线”。例如,一个电影评论者可能会给出 7.2 分(满分 10 分),而另一个看过同一组电影的评论者给出的平均分接近 5.0 分。

有了完整的排名系统,基线问题就解决了,因为所有回答者都被简单地要求确定每个选项的相对吸引力。然而,这种系统的一个可能的缺点是调查疲劳的风险——如果有太多的捆绑包需要排序,受访者可能会不知所措。随着更多功能和更多级别的添加,对包总数的影响是倍增的。在这里,只有 2 个数据选项、3 个通话时间选项、2 个音乐选项和 2 个社交网络选项,我们已经有了 24 个组合(2 x 3 x 2 x 2)。

满秩场景的线性建模

如上所述,为了提高线性回归建模的适用性,我们“翻转”了排名,以便更高的值将与更受青睐的包相关联。这使得线性回归系数的解释变得更容易——正值现在与更好的选项相关联,而负值与更差的选项相关联。

下面您可以看到在环境中读取的干净数据集:

在运行这样一个模型之前,所有的输入特性都应该被虚拟化,包括数据计划和每月通话分钟数等数值。这样,模型结果会将每个特征选项显示为一个离散的选项。这样做意味着我们可以给每一个选项附加一个精确的系数值,而不是用一个单一的数字系数来试图表达整个连续的可能选项范围内的偏好。

pandas 的 get_dummies()函数帮助我们为线性建模准备变量:

然后,使用 scikit-learn 的 LinearRegression 模块,以 fli 恶作剧作为结果变量,以千兆字节、分钟、音乐和社交网络的虚拟化水平作为输入,构建线性模型:

至于使用普通最小二乘线性回归的适用性,有几个问题值得注意。

首先,这个数据集中的结果值是均匀分布的,范围是 1 到 24。如果我们将这个模型用于预测目的,这个范围约束可能会出现问题(我们如何解释小于 1 或大于 24 的值?),但这并不妨碍我们出于解释的目的使用该模型。我们的目标只是更好地理解功能选项和客户偏好之间的关系,我们可以在这里完成。

其次,考虑到响应变量的非正态分布,异方差的风险可能会增加。我们使用回归诊断图来检查这一点,并在模型结果中没有发现异方差的证据。

解读结果

模型系数揭示了一些有价值的模式:

例如,他们向我们表明,调查受访者非常强烈地支持社交网络接入和 10gb 的数据计划。

较大的通话分钟数和音乐选项的负值不一定意味着客户根本不想要这些选项。相反,它可能表明消费者不希望支付与这些功能相关的增量成本。电信运营商可能希望在未来的调查中修改这些选项——如果相关成本降低,受访者可能会更倾向于这些选项。

或者,对这些特征缺乏兴趣可能表明消费者口味的其他方面。也许这个群体中的消费者习惯于通过其他格式听音乐,并且根本不打算每月使用超过 100 分钟的通话时间。通过功能和定价选项的不断迭代,以及对实际用户数据的分析,电信公司可以不断努力为其消费者群找到一组理想的选择。

福克斯尔斯,摄影师。(2019 年 11 月 5 日)。拿着手机的人。从 Pexels 检索。

在 Docker 上使用 Node.js 和 ElasticSearch 进行全文搜索

原文:https://towardsdatascience.com/full-text-search-with-node-js-and-elasticsearch-on-docker-edcea23612fd?source=collection_archive---------4-----------------------

让我们基于 Node.js、ElasticSearch 和 Docker 构建一个真实世界的应用程序

照片由张诗钟·维诺在 Unsplash 上拍摄

全文搜索既令人害怕又令人兴奋。一些流行的数据库,如 MySql 和 Postgres,是存储数据的惊人解决方案…但当谈到全文搜索性能时,没有与 ElasticSearch 竞争。

对于那些不知道的人来说, ElasticSearch 是一个建立在 Lucene 之上的搜索引擎服务器,具有惊人的分布式架构支持。根据 db-engines.com 的说法,它是目前使用最多的搜索引擎。

在这篇文章中,我们将构建一个简单的 REST 应用程序,称为报价数据库,它将允许我们存储和搜索尽可能多的报价!

我准备了一个 JSON 文件,其中包含 5000 多条作者引用;我们将用它作为填充 ElasticSearch 的初始数据。

您可以在这里找到这个项目的资源库。

设置 Docker

首先,我们不想在我们的机器上安装 ElasticSearch。我们将使用 Docker 在一个容器上编排 Node.js 服务器和 ES 实例,这将允许我们部署一个生产就绪的应用程序以及它需要的所有依赖项!

让我们在项目根文件夹中创建一个Dockerfile:

如你所见,我们告诉 Docker 我们将运行 Node.js 10.15.3-alpine 运行时。我们还将在/usr/src/app下创建一个新的工作目录,在那里我们将复制package.jsonpackage-lock.json文件。这样,Docker 将能够在我们的WORKDIR中运行npm install,安装我们需要的依赖项。

我们还将通过运行RUN npm install -g pm2在全球范围内安装 PM2 。Node.js 运行时是单线程的,因此如果一个进程崩溃,整个应用程序都需要重启...PM2 检查 Node.js 进程状态,并在应用程序因任何原因关闭时重新启动它。

安装 PM2 后,我们将在我们的WORKDIR ( COPY . ./)中复制我们的代码库,我们告诉 Docker 公开两个端口:3000,这将公开我们的 RESTful 服务,和9200,这将公开 ElasticSearch 服务(EXPOSE 3000EXPOSE 9200)。

最后,我们告诉 Docker 哪个命令将启动 Node.js 应用程序:npm run start

设置 docker 撰写

现在你可能在想,“太好了,我明白了!但是我如何在 Docker 中处理 ElasticSearch 实例呢?我在我的文档里找不到!_“…你说得对!这就是 docker-compose 派上用场的地方。它允许我们编排多个 Docker 容器,并在它们之间创建连接。因此,让我们写下docker-compose.yml文件,它将存储在我们的项目根目录中:

这比我们的 docker 文件要复杂一些,但是让我们来分析一下:

  • 我们声明我们使用的是哪个版本的文件(3.6)
  • 我们声明我们的服务:api这是我们的 Node.js 应用程序。就像在我们的 docker 文件中一样,它需要node:10.15.3-alpine图像。我们还为这个容器指定了一个名字:tqd-node,在这里,我们使用build .命令调用之前创建的 Dockerfile。然后,我们需要公开3000端口:如您所见,我们将这些语句编写如下:3000:3000。这意味着我们从端口3000(在我们的容器内)映射到端口3000(可以从我们的机器访问)。然后我们将设置一些环境变量。值elasticsearch是一个变量,它引用我们的docker-compose.yml文件中的elasticsearch服务。我们还想挂载一个卷:/usr/src/app/quotes。这样,一旦我们重启我们的容器,我们将维护我们的数据而不丢失它。我们再次告诉 Docker,一旦容器启动,我们需要执行哪个命令,然后我们设置一个到elasticsearch服务的链接。我们还告诉 Docker 在elasticsearch服务启动后启动api服务(使用depends_on指令)。最后,我们告诉 Docker 在esnet网络下连接api服务。这是因为每个容器都有自己的网络:这样,我们说apielasticsearch服务共享同一个网络,所以它们将能够用相同的端口相互调用。这是(你可能已经猜到了)我们的 ES 服务。它的配置与api服务非常相似。我们将把logging指令设置为driver: none来删除它的详细日志。
  • 我们声明存储 es 数据的卷
  • 我们宣布我们的网络,esnet

引导 Node.js 应用程序

现在我们需要创建 Node.js 应用程序,所以让我们开始设置我们的package.json文件:

npm init -y

现在我们需要安装一些依赖项:

npm i -s @elastic/elasticsearch body-parser cors dotenv express

太好了!我们的package.json文件应该是这样的:

让我们在 Node.js 中实现我们的 ElasticSearch 连接器。首先,我们需要创建一个新的/src/elastic.js文件:

如你所见,这里我们设置了一些非常有用的常量。首先,我们使用其官方 Node.js SDK 创建一个到 ElasticSearch 的新连接;然后,我们定义一个索引("quotes")和一个索引类型("quotes"),我们稍后会看到它们的含义。

现在我们需要在 ElasticSearch 上创建一个索引。您可以将“索引”视为 SQL“数据库”的等价物。ElasticSearch 是一个 NoSQL 数据库,这意味着它没有表——它只存储 JSON 文档。索引是映射到一个或多个主碎片的逻辑名称空间,可以有零个或多个副本碎片。你可以在这里阅读更多关于弹性搜索指数的信息。

现在让我们定义一个创建索引的函数:

现在我们需要另一个函数来为我们的报价创建映射。映射定义了我们文档的模式和类型:

如您所见,我们正在为文档定义模式,并将它插入到我们的index中。

现在让我们考虑一下,ElasticSearch 是一个庞大的系统,可能需要几秒钟才能启动。在 ES 准备好之前,我们无法连接到 ES,因此我们需要一个函数来检查 ES 服务器何时准备好:

如你所见,我们正在回报一个承诺。这是因为通过使用,async/await,我们能够停止整个 Node.js 进程,直到这个承诺得到解决,并且它不会这样做,直到它连接到 es。这样,我们强制 Node.js 在启动前等待 ES。

我们已经完成了 ElasticSearch!现在,让我们导出我们的函数:

太好了!让我们看看整个elastic.js档案:

用报价填充弹性搜索

现在我们需要用我们的报价填充我们的 ES 实例。这听起来很容易,但是相信我,这可能是我们应用程序中很棘手的一部分!

让我们在/src/data/index.js中创建新文件:

正如您所看到的,我们正在导入刚刚创建的elastic模块和来自存储在/src/data/quotes.json中的 JSON 文件的报价。我们还创建了一个名为esAction的对象,一旦我们插入一个文档,它将告诉 ES 如何索引它。

现在我们需要一个脚本来填充我们的数据库。我们还需要创建一个具有以下结构的对象数组:

如您所见,对于我们将要插入的每个报价,我们需要将其映射设置为 ElasticSeaech。这就是我们要做的:

太好了!现在让我们创建我们的主文件/src/main.js,看看我们将如何组织我们到目前为止所写的所有内容:

我们来分析一下上面的代码。我们创建一个自动执行的 main 函数来检查 ES 连接。在 ES 连接之前,代码不会执行。当 ES 准备好时,我们将检查quotes索引是否存在:如果不存在,我们将创建它,我们将设置它的映射,并将填充数据库。显然,我们只有在第一次启动服务器时才会这样做!

创建 RESTful API

现在我们需要创建 RESTful 服务器。我们将使用 Express.js,它是构建服务器最流行的 Node.js 框架。

我们将从/src/server/index.js文件开始:

如你所见,它只是一个标准的 Express.js 服务器;我们不会在那上面花太多时间。让我们看看我们的/src/server/routes/index.js档案:

我们创建两个端点:

  • GET /将返回与我们的查询字符串参数匹配的报价列表。
  • POST /new/将允许我们发布一个新的报价存储在弹性搜索。

现在让我们看看我们的/src/server/controllers/index.js文件:

这里我们基本上定义了两个函数:

  • getQuotes,需要至少一个查询字符串参数:text
  • addQuote,需要两个参数:authorquote

ElasticSearch 接口委托给我们的/src/server/models/index.js。这种结构有助于我们维护一个类似 MVC 的架构。让我们看看我们的模型:

如您所见,我们通过选择包含给定单词或短语的每个报价来构建我们的 ElasticSearch 查询。然后,我们生成查询,设置pagelimit值:我们可以在查询字符串中传递它们,例如:http://localhost:3000/quotes?text=love&page=1&limit=100。如果这些值没有通过查询字符串传递,我们将使用它们的默认值。

ElasticSearch 返回大量数据,但我们需要四样东西:

  • 报价 ID
  • 引用本身
  • 引用作者
  • 得分

分数代表报价与我们的搜索词的接近程度;一旦我们有了这些值,我们就将它们和总结果数一起返回,这在前端对结果进行分页时可能会很有用。

现在我们需要为模型创建最后一个函数:insertNewQuote:

这个函数很简单:我们将引文和作者发布到我们的索引中,并将查询结果返回给控制器。现在,完整的/src/server/models/index.js文件应该如下所示:

我们完事了。我们需要从里到外设置我们的启动脚本package.json文件,我们已经准备好了:

一旦连接了 ElasticSearch,我们还需要更新我们的/src/main.js脚本来启动我们的 Express.js 服务器:

启动应用程序

我们现在准备使用 docker-compose 启动我们的应用程序!只需运行以下命令:

$ docker-compose up

您需要等到 Docker 下载了 ElasticSearch 和 Node.js 图像,然后它将启动您的服务器,您就可以对 REST 端点进行查询了!

让我们用几个 cURL 调用进行测试:

$ curl localhost:3000/quotes?text=love&limit=3{"success": true,"data": {"results": 716,"values": [{"id": "JDE3kGwBuLHMiUvv1itT","quote": "There is only one happiness in life, to love and be loved.","author": "George Sand","score": 6.7102118},{"id": "JjE3kGwBuLHMiUvv1itT","quote": "Live through feeling and you will live through love. For feeling is the language of the soul, and feeling is truth.","author": "Matt Zotti","score": 6.2868223},{"id": "NTE3kGwBuLHMiUvv1iFO","quote": "Genuine love should first be directed at oneself if we do not love ourselves, how can we love others?","author": "Dalai Lama","score": 5.236455}]}
}

如你所见,我们决定将结果限制在3,但是还有其他 713 个引用!我们可以通过调用以下命令轻松获得接下来的三个报价:

$ curl localhost:3000/quotes?text=love&limit=3&page=2{"success": true,"data": {"results": 716,"values": [{"id": "SsyHkGwBrOFNsaVmePwE","quote": "Forgiveness is choosing to love. It is the first skill of self-giving love.","author": "Mohandas Gandhi","score": 4.93597},{"id": "rDE3kGwBuLHMiUvv1idS","quote": "Neither a lofty degree of intelligence nor imagination nor both together go to the making of genius. Love, love, love, that is the soul of genius.","author": "Wolfgang Amadeus Mozart","score": 4.7821507},{"id": "TjE3kGwBuLHMiUvv1h9K","quote": "Speak low, if you speak love.","author": "William Shakespeare","score": 4.6697206}]}
}

如果您需要插入新的报价呢?就叫/quotes/new端点吧!

$ curl --request POST \--url http://localhost:3000/quotes/new \--header 'content-type: application/json' \--data '{"author": "Michele Riva","quote": "Using Docker and ElasticSearch is challenging, but totally worth it."
}'

答案会是:

{"success": true,"data": {"id": "is2QkGwBrOFNsaVmFAi8","author": "Michele Riva","quote": "Using Docker and ElasticSearch is challenging, but totally worth it."}
}

结论

Docker 使得管理我们的依赖项和它们的部署变得非常容易。从那时起,我们可以轻松地在 Heroku 、 AWS ECS 、 Google Cloud Container 或任何其他基于 Docker 的服务上托管我们的应用程序,而无需费力地用它们的超级复杂的配置来设置我们的服务器。

下一步?

  • 了解如何使用 Kubernetes 来扩展您的容器并编排更多的弹性搜索实例!
  • 创建一个允许您更新现有报价的新端点。错误是会发生的!
  • 那么删除一个报价呢?您将如何实现该端点?
  • 用标签保存你的引语会很棒(例如,关于爱情、健康、艺术的引语)…试着更新你的quotes索引!

软件开发很有趣。有了 Docker,Node,和 ElasticSearch,就更好了!

使用 AWS CI/CD 工具完全自动化您的 ML 管道

原文:https://towardsdatascience.com/fully-automating-your-ml-pipelines-with-the-aws-ci-cd-tools-bfc337aa77c3?source=collection_archive---------18-----------------------

利用可信的 DevOps 工具集构建自动化 MLOps 管道的指南。

在 Unsplash 上科学高清拍摄的照片

在过去的几年里,由于谷歌和脸书等公司的进步,以及开源社区的贡献,机器学习(ML)的受欢迎程度呈指数级增长。由于它可以应用于非常广泛的用例,几乎世界上的每个公司都开始利用 ML 并将其集成到其流程中。

这种大规模采用 ML 最初缺少一个关键部分:自动化。即使 ML 系统基本上是软件系统,它们之间的细微差别,例如 ML 本质上是实验性的,使得一些最初的采用者在构建他们的 ML 系统时放弃了 DevOps 原则——即使 DevOps 已经是其他软件系统的标准。

这为人工智能平台向其客户提供 MLOps 功能创造了空间,允许他们通过应用 CI/CD 原则来自动化其 ML 管道。在本文中,我们的目标是展示如何通过依赖大多数云提供商提供的工具,将我们在 DevOps 管道中日常使用的 CI/CD 原则应用到 ML 管道中。我们将在本文中讨论 AWS 工具,但大多数其他云提供商也提供类似的功能。

首先:把代码放在一个地方

是的,ML 本质上是实验性的,所以应用源代码控制可能不像对其他软件系统那样简单。但是,一旦你开始将你的 ML 代码库的不同组件(从预处理、训练或后处理脚本,到你的实验笔记本)集中在一个主要服务中,你将开始收获好处:协作将变得更加无缝,并且你将确保代码质量。

与其他软件系统不同,对 ML 来说,对代码进行版本控制只是工作的一半,因为管道也依赖于数据集。理想情况下,你不希望通过你的源代码控制服务来版本化你的数据集,所以你可以利用S3提供的版本化功能。这样,无论何时新的数据集到达,您都可以确定您将在管道中使用它,同时还可以跟踪数据的确切版本。至于笔记本,你可以使用像 Jupytext 这样的工具,让它们更容易在你的版本控制服务上工作。

这一步还将允许您定义最适合您的项目的分支策略,以及您决定如何组织它们。无论您决定使用 AWS CodeCommit 还是其他提供者,如 GitHub 或 GitLab,都不会真正影响管道的其余部分,因为我们将要讨论的工具提供了大多数主流源代码控制服务的连接器。

管道的当前版本:版本化代码和数据集

AWS 代码管道:更大的图景

构建我们的 MLOps 管道的最佳起点实际上是定义管道本身,即使不同的组件仍然没有准备好。AWS CodePipeline 是 AWS 持续交付产品中经常被忽视的核心部分,有了它,您将能够构建一个实际的 MLOps 管道,在不同的 AWS 服务上运行和编排步骤。

除了与大多数 AWS 服务(包括我们将为该管道利用的所有工具)集成之外,CodePipeline 还提供了与大多数源代码控制服务的连接器,这意味着您可以配置一个 webhook,允许它在推送到主分支之后或合并拉请求时(取决于您希望管道运行的频率)检索项目的新版本。

既然我们可以基于适合用例的事件来触发管道,我们就已经可以定义管道的不同步骤了:

  1. 当有我们想要触发管道的事件时,从我们的源代码控制服务中检索代码(这已经由 CodePipeline 在一个专用的源代码步骤中处理了)。
  2. 对数据运行预处理脚本(这是可选的,可以独立于此管道发生)。
  3. 使用最新版本的训练脚本来训练 ML 模型。
  4. 评估我们的新模型并测试其性能。
  5. 如果模型在性能方面满足一定的标准,则部署该模型。

在这个阶段,我们已经定义了 CodePipeline 中的不同步骤,现在让我们看看如何实现它们。

管道的当前版本:通过 AWS 代码管道定义的步骤,初始源步骤包括检索代码和数据

AWS 代码构建:您的瑞士军刀

我们模型的训练、评估和部署需要在一个包含所有必要包(无论是开源库还是定制的内部包)的环境中进行,这样我们不同的脚本就可以运行而不会出现任何问题或意外。

使用容器是对这种需求的直接回答,它允许我们为管道中的不同步骤高效地构建可预测的环境。幸运的是,AWS 提供了 CodeBuild,这是一种持续集成服务,我们可以利用它为我们的三个主要步骤中的每一个步骤推送 Docker 容器。

这种设计为我们的不同步骤提供了极大的灵活性,因为我们可以指定每个容器的包列表以及我们希望如何执行我们的脚本。CodeBuild 需要做的唯一额外工作是为每个作业提供一个 [buildspec](https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html) 脚本,其中我们指定了构建 Docker 映像要执行的命令。在buildspec脚本中,我们还将图像推送到 ECR ,AWS 容器注册表。

现在,对于我们的三个主要步骤中的每一个,我们都有一个容器映像来表示执行该步骤的合适环境——但是我们可以在哪里运行这些容器呢?

管道的当前版本:CodeBuild 允许我们为管道的每一步构建一个专用的 Docker 映像

AWS SageMaker:奇迹发生的地方

SageMaker,Amazon 的通用 ML 平台,允许我们在 ML 优化的实例上运行不同的容器。SageMaker 还为我们的不同步骤提供专用组件:

  • SageMaker 培训任务:它们允许我们无缝运行培训任务并生成模型。
  • SageMaker 加工作业:非常适合模型评估任务。例如,我们可以使用测试数据集评估模型,然后在我们的跟踪工具上记录一组指标。
  • SageMaker 端点:它们允许我们轻松地部署我们的服务模型。

多亏了这些工具,我们现在可以运行我们专用的容器映像来训练模型、评估它,然后部署它来提供服务。我们的 ML 难题中唯一剩下的部分是增加从 CodePipeline 触发这些不同的 SageMaker 组件的能力。

管道的当前版本:我们运行培训作业、模型评估,然后在 SageMaker 上部署

AWS Lambda:将点连接起来

Lambda 函数是 AWS 上使用最广泛的服务之一。这主要归功于它们的多功能性、简单性以及作为无服务器计算服务提供的便利性。

对于我们的 MLOps 管道,可以有效地利用 Lambda 函数来触发不同的 SageMaker 作业,在必要时执行附加操作,并在管道内将参数从一个步骤传递到另一个步骤。

例如,在评估步骤中,我们可以使用 Lambda 函数来执行以下操作:

  • 检索由训练步骤产生的模型的位置(在 S3 上)。
  • 为我们的评估环境检索完整的 Docker 图像名称和标签(图像将由 SageMaker 从 ECR 中提取)。
  • 通过传递所有必要的参数,触发 SageMaker 处理作业来运行评估。

为了将变量从一个步骤传递到另一个步骤,我们可以通过 CodePipeline 本身定义想要传递的元数据,然后我们可以从不同的 Lambda 函数中检索变量。

最终的管道:我们使用 Lambda 函数来触发不同的 SageMaker 组件,依赖于通过 CodePipeline 传递的变量

结论

建立一个自动化的 MLOps 管道是工业化 ML 工作流程和确保模型及时到达生产的必要条件。在本文中,我们展示了 AWS 提供的 CI/CD 工具是构建这种管道的合适选择。

与开箱即用的解决方案相比,这种方法所需的额外工作是为极度灵活性(因为管道可以轻松修改或更新)和与其他 AWS 服务的自然集成(例如,我们可以在几分钟内通过 SNS 添加通知)所付出的代价。

流水线本身也应该通过 IaC(作为代码的基础设施)自动化,以确保可再现性和效率。文章中提到的所有资源都可以通过 Terraform 或 CloudFormation 创建。

最后,以下资源提供了关于该设计不同组件的更多见解:

  • MLOps:机器学习中的连续交付和自动化管道
  • AWS re:Invent 2018:使用 CI/CD 技术工业化机器学习
  • 在 SageMaker 短暂实例上调度 Jupyter 笔记本
  • 机器学习团队在生产中使用 CI/CD 的 4 种方式

要了解更多数据工程内容,您可以订阅我的双周刊时事通讯 Data Espresso,我将在其中讨论与数据工程和技术相关的各种主题:

https://dataespresso.substack.com/

Python 中的函数装饰器

原文:https://towardsdatascience.com/function-decorators-in-python-a17958b9d618?source=collection_archive---------6-----------------------

为什么您可能需要它们以及如何实现一个定制的

约翰·安维克在 Unsplash上的照片

装饰者在第一次与它们打交道时可能会显得有点神秘,但毫无疑问,这是增强功能行为的一个很好的工具。

事实上,Python 中有两种类型的装饰器——类装饰器和函数装饰器——但我在这里将重点介绍函数装饰器。

在我们进入基本装饰器如何工作以及如何实现你自己的装饰器的有趣细节之前,让我们先看看为什么我们需要它们。在一些情况下,装饰者会有很大的帮助。

他们可以添加日志记录或工具代码,并以封装的方式从应用程序组件中提取各种指标,例如计时。

Decorators 可能是验证输入的完美机制,这在使用像 Python 这样的动态类型的语言时尤其重要。

内置装饰器在 Python 库中被广泛使用。典型的例子包括 web 框架中用于路由和授权的 decorator,例如, Flask 中的[@route()](https://flask.palletsprojects.com/en/2.0.x/api/#flask.Flask.route) decorator。

既然我们看到了学习编写和应用装饰器是一个好主意,那么让我们弄清楚什么是装饰器,以及如果需要的话,如何实现自定义装饰器。

为了使用 decorators,你需要知道的基本知识是,函数也是 Python 中的对象,它们可以作为参数传递给其他函数,就像其他对象一样,比如字符串。所以 Python 中的函数是一级对象

以其他函数为自变量返回一个函数的函数是 高阶函数 。这就是 Python decorators 的情况。

一个函数可以在另一个函数中定义。在这种情况下,它被称为嵌套函数。另一个与嵌套函数直接相关并且你需要理解的概念是 闭包——一个“记住”数据的函数对象,例如来自其封闭范围的变量及其值。这将是我们稍后将看到的装饰器示例中的wrapper()函数。

装饰器通常被定义为一个修改另一个函数行为的函数。最常见的情况是,装饰者给参数函数的行为添加了一些东西。重要的是要记住,装饰器只是在一定程度上改变被装饰函数的行为,而不是永久地或完全地改变它。这就是为什么有时人们更喜欢将装饰器定义为一个函数,这个函数扩展了另一个更准确的函数的行为。

接下来,让我们看一个装饰函数的例子。假设我们有一个简单的函数,它返回两个整数的和:

def sum_up(n, m):return n + m

那么我们可以这样运行它:

print(sum_up(3, 7))

输出:

10

现在,假设我们想要记录代码库的这一部分发生了什么——为了便于练习,我们将简单地把它打印到控制台上。我们可以为此编写一个装饰器:

现在我们需要将装饰器添加到代码库中的函数中:

[@log_computation](http://twitter.com/log_computation)
def sum_up(n, m):return n + m

因此,当我们在代码中调用此函数时,我们将在控制台中看到以下输出:

Adding up 3 and 7\. The result equals to 10.

让我们一行一行地分解它,以理解装饰器中发生了什么。

在第 1 行,decorator 方法的签名显示它接受一个函数作为参数。在第 2 行,我们定义了一个嵌套的包装函数,它将调用修饰函数并在第 6 行返回它的输出。在第 3 行,我们获得了修饰函数的输出。在第 4 行和第 5 行,装饰者的修改行为开始生效:在这里,它使输出更加冗长。在第 7 行,装饰者返回包装器。

如果我们不知道修饰函数的参数的很多细节怎么办?如果我们想概括装饰者呢?

我们可以使用 *[args](https://docs.python.org/3.7/glossary.html?highlight=kwarg#term-parameter)和/或**[kwargs](https://docs.python.org/3.7/glossary.html?highlight=kwarg#term-parameter)来实现:

def log_computation(func):def wrapper(*args):numbers = argsres = func(*args)print('Adding up the following numbers:\n''{}\n''The result equals to {}.'.format(numbers, res))return resreturn wrapper

因此,如果将sum_up()函数推广到累加任意数量的整数,我们的装饰器仍然可以工作:

sum_up(3, 7, 11, 50)

输出:

Adding up the following numbers:
(3, 7, 11, 50)
The result equals to 71.

这是一个自定义装饰的基本模板。自定义装饰器可能要复杂得多。嵌套函数可以不接受参数,也可以接受位置参数、关键字参数或两者都接受。他们可以在调用 main 函数之前完成一些步骤,以确保它可以被安全地调用,或者在调用之后完成(就像我们的例子一样),或者两者都完成(例如,在记录函数的执行或计时时)。我们也可以对一个函数应用多个装饰器——这被称为链接装饰器。

Decorators 是使您的代码更健壮(特别是如果您将它们用于验证目的的话)并且更简单、更通用的好帮手。

如果你对使用 decorators 来跟踪你的 Python 代码的性能感兴趣,可以随意查看我关于代码优化和并发和并行的帖子。

人脑的功能连接和相似性分析(下)

原文:https://towardsdatascience.com/functional-connectivity-and-similarity-analysis-of-human-brain-part-iii-c427c88ca5bb?source=collection_archive---------28-----------------------

人脑的空间分析

来源:https://nilearn . github . io/auto _ examples/03 _ connectivity/plot _ multi _ subject _ connectome . html # sphx-glr-auto-examples-03-connectivity-plot-multi-subject-connectome-py

材料

这是该系列的第三篇文章,即“腹侧颞叶皮层时空功能磁共振成像的认知计算模型”。如果你想了解整个系列,请点击下面的链接。

https://github.com/cankocagil/Cognitive-Computational-Modelling-for-Spatio-Temporal-fMRI-in-Ventral-Temporal-Cortex

我将介绍功能连接和相似性分析的主题,它们在大脑解码研究中的用例。让我们开始吧。

所有相关资料都放在我的 GitHub 页面上。别忘了去看看。如果你是一个纸质爱好者,你可以阅读这一系列文章的纸质版,也可以在我的回购中找到。

https://github.com/cankocagil/Cognitive-Computational-Modelling-for-Spatio-Temporal-fMRI-in-Ventral-Temporal-Cortex

在深入分析和编码之前,让我们稍微操作一下 Haxby 数据集,并应用腹侧时间掩模从人脑的感兴趣区域提取信号。安装和导入部分在前一篇文章中已经完成。如果你没有看我以前的文章,我想就此打住,快速浏览一下。但是,不用担心。所有部分“几乎”相互独立。开始编码吧。

在这里,我们获取 Haxby 数据集。接下来,我们将理解数据结构,并将其转换为 NumPy 数组,以便进一步处理。

正如我们所看到的,有 8 个类别。(我们将忽略“rest”类别,因为它没有提供额外的信息。)

让我们删除“休息”条件数据,并探索数据的形状如下。

因此,有 864 个样本在时间上相连,即时间序列数据。固定时间的 fMRI 数据具有 40×64×64 的维度,其中 40 是指 3-D 图像的深度,64 是指空间维度。因此,我们是四维时间序列图像数据。回想一下,实验中有 6 名受试者,让我们按如下方式查看所有受试者。

所以,所有受试者都有 864 个时间序列数据。有关数据集的详细描述,请参考第一部分。

然后,让我们执行掩蔽来提取感兴趣的区域,以降低 fMRI 的维度。掩蔽的 fMRI 样本代表神经活动可能发生的区域。

是的,这个脚本使我们能够

  1. 获取 fMRI 数据并将其转换为 NumPy 矩阵
  2. 创建并应用时空掩膜来提取感兴趣区域
  3. 准备监督(目标/标签)

那么,让我们运行这个函数并获取数据。

是啊!最后,我们准备了数据集。现在,我们可以进行任何我们想要的分析。在本文中,我们将对人脑进行功能连接和相似性分析。

功能连接和相似性分析

功能连接性被定义为解剖学上分离的大脑区域的神经元激活模式的时间依赖性,在过去的几年中,越来越多的神经成像研究开始通过测量大脑区域之间静息状态 fMRI 时间序列的共激活水平来探索功能连接性[23]。这些功能联系对于建立大脑区域的统计联系非常重要。可以通过估计来自分解的不同大脑区域的信号的协方差(或相关性)矩阵来获得功能连接,例如在静息状态或自然刺激数据集上。这里,我们基于相关性、精确度和部分相关性进行了功能连接性分析。然后,进行基于余弦、闵可夫斯基和欧几里德距离的相似性分析,以进一步扩展掩蔽的 fMRI 数据中的统计发现。

功能连接:关联

对受试者 1 进行基于皮尔逊相关性的功能连接。我们可以看到,在受试者 1 的腹侧颞叶皮层中,当呈现面孔的刺激时,存在很强的相关性。

相关矩阵(图片由作者提供)

功能连接:精度

如文献[20,24]所示,使用逆协方差矩阵,即精度矩阵更有意义。它只给出区域之间的直接联系,因为它包含部分协方差,即两个区域之间的协方差取决于所有其他区域。此外,我们基于精确评分进行了功能性连接组,以提取受试者 1 的 RoI 信号。这里,随着连接性测量的改变,我们看到受试者 1 的腹侧皮层中空间相关性的直接变化。通过精确测量,我们进一步了解了大脑组织和大脑网络。

精度矩阵(图片由作者提供)

功能连接:部分相关

在一系列网络建模方法中,偏相关在准确检测真实的大脑网络连接方面显示出巨大的前景[25]。因此,我们基于偏相关进行了功能连接性分析。RoI fMRI 数据中的部分相关性的可视化表明受试者 1 的腹侧颞叶皮层没有太多相关性。

部分相关矩阵(图片由作者提供)

相似性分析:余弦距离

为了便于在大脑中统计连接的背景下进行测地线理解,我们对受试者 1 进行了余弦相似性分析,并将获得的矩阵可视化。结果表明,当视觉刺激出现时,在神经活动方面存在高度重叠的区域。

余弦矩阵(图片作者提供)

相似性分析:闵可夫斯基距离

为了试验不同的相似性度量,我们利用了闵可夫斯基距离,它是欧几里得距离和曼哈顿距离的推广。因此,它在 fMRI 时间相似性分析中是有用的。

闵可夫斯基矩阵(图片作者提供)

相似性分析:欧几里德距离

最后,我们基于经典的欧氏距离进行相似性分析。这是一个非常经典的使用勾股定理[13]根据点的笛卡尔坐标测量距离的方法。从功能连接和相似性分析所揭示的统计和结构模式中,我们可以得出结论,在人脑腹侧颞叶皮层诱发的神经活动是高度重叠和分布的。

欧几里德矩阵(图片由作者提供)

耶!本文到此为止。我深入讨论了 fMRI 数据的功能连接和相似性分析技术。

恭喜你!您已经完成了第三篇文章,并通过认知计算方法对人脑解码迈出了一步。

在下一篇文章中,我们将执行无监督表示学习,以提取人脑中的潜伏期。

文章链接

  1. 发表文章

https://cankocagil.medium.com/introduction-to-cognitive-computational-modelling-of-human-brain-part-i-90c61e0e24c9

https://cankocagil.medium.com/discovery-neuroimaging-analysis-part-ii-b2cdbdc6e6c3

https://cankocagil.medium.com/functional-connectivity-and-similarity-analysis-of-human-brain-part-iii-c427c88ca5bb

https://cankocagil.medium.com/unsupervised-representation-learning-on-distributed-regions-in-the-human-brain-part-iv-55fecf4e1b6f

2.在路上(即将到来…)

  1. 第五部分的占位符

进一步阅读

  • 【https://www.hindawi.com/journals/cmmm/2012/961257/

我在机器学习和神经科学方面的研究中使用了以下参考文献列表。我强烈建议复制粘贴参考资料,并简要回顾一下。

参考

[1]巴、基罗斯和辛顿。图层归一化,2016。

[2] L. Buitinck,G. Louppe,M. Blondel,F. Pedregosa,A. Mueller,O. Grisel,V. Niculae,P. Prettenhofer,A. Gramfort,J. Grobler,R. Layton,J. VanderPlas,a .乔利,B. Holt,10 和 G. Varoquaux。机器学习软件的 API 设计:scikit-learn 项目的经验。在 ECML PKDD 研讨会:数据挖掘和机器学习的语言,第 108–122 页,2013。

[3]褚,田,王,张,任,魏,夏,沈。双胞胎:重新审视《视觉变形金刚》中空间注意力的设计,2021。

[4] K .克拉默、o .德克、j .凯舍特、s .沙莱夫-施瓦兹和 y .辛格。在线被动攻击算法。2006.

[5] K. J .弗里斯顿。统计参数映射。1994.

[6]格罗斯、罗查-米兰达和本德。猕猴下颞皮质神经元的视觉特性。神经生理学杂志,35(1):96–111,1972。

[7] S. J .汉森、t .松坂和 J. V .哈克斯比。用于物体识别的腹侧颞叶组合编码。

[8]哈克斯比、戈比尼、富里、伊沙伊、斯豪滕和彼得里尼。《视觉物体识别》,2018。

[9]赫克曼、哈伊纳尔、贾巴尔、吕克特和哈默斯。结合标记传播和决策融合的自动解剖脑 mri 分割。神经影像,33(1):115–126,2006。

10d .亨德里克斯和 k .金佩尔。高斯误差线性单位(gelus),2020。

[11]黄少华,邵文伟,王明林,张德庆.人脑活动视觉信息的功能解码:简要综述。国际自动化和计算杂志,第 1-15 页,2021。

[12] R. Koster、M. J. Chadwick、Y. Chen、D. Berron、A. Banino、E. Duzel、D. Hassabis 和 D. Kumaran。海马系统内的大循环复发支持跨发作的信息整合。神经元,99(6):1342–1354,2018。

[13]马奥尔。勾股定理:4000 年的历史。普林斯顿大学出版社,2019。

[14] K. A. Norman、S. M. Polyn、G. J. Detre 和 J. V. Haxby 超越读心术:功能磁共振成像数据的多体素模式分析。认知科学趋势,10(9):424–430,2006。

[15]奥图尔、江、阿卜迪和哈克斯比。腹侧颞叶皮层中物体和面孔的部分分布表征。认知神经科学杂志,17(4):580–590,2005。

[16] F .佩德雷戈萨、g .瓦洛夸、a .格拉姆福特、v .米歇尔、b .蒂里翁、o .格里塞尔、m .布隆德尔、p .普雷登霍弗、r .魏斯、v .杜伯格、j .范德普拉斯、a .帕索斯、d .库尔纳波、m .布鲁彻、m .佩罗特和 e .杜切斯内。sci kit-learn:Python 中的机器学习。机器学习研究杂志,12:2825–2830,2011。

17 r . a .波尔德拉克。功能磁共振成像的感兴趣区域分析。社会认知和情感神经科学,2(1):67–70,2007。

[18] M. Poustchi-Amin、S. A. Mirowitz、J. J. Brown、R. C. McKinstry 和 T. Li。回波平面成像的原理和应用:普通放射科医师回顾。放射学,21(3):767–779,2001。

[19] R. P. Reddy,A. R. Mathulla 和 J. Rajeswaran。心理健康专家的观点采择和情绪传染的初步研究:移情的玻璃脑观点。印度心理医学杂志,0253717620973380,2021 页。

[20]史密斯、米勒、萨利米-科尔希迪、韦伯斯特、贝克曼、尼科尔斯、拉姆齐和伍尔利奇。功能磁共振成像的网络建模方法。神经影像,54(2):875–891,2011。

21 田中先生。下颞叶皮层和物体视觉。神经科学年度评论,19(1):109–139,1996。

[22] M. S .特雷德。Mvpa-light:一个多维数据的分类和回归工具箱。神经科学前沿,14:289,2020。

[23] M. P .范登赫维尔和 H. E .波尔。探索大脑网络:静息态功能磁共振成像功能连接综述。欧洲神经精神药理学,20(8):519–534,2010。

[24] G. Varoquaux,A. Gramfort,J. B. Poline 和 B. Thirion。大脑协方差选择:使用群体先验的更好的个体功能连接模型。arXiv 预印本 arXiv:1008.5071,2010。

[25] Y. Wang,J. Kang,P. B. Kemmer 和 Y. Guo。一种利用偏相关估计大规模脑网络功能连接的有效可靠的统计方法。神经科学前沿,10:123,2016。

26s . Wold、K. Esbensen 和 P. Geladi。主成分分析。化学计量学和智能实验室系统,2(1–3):37–52,1987。

27s . Wold、K. Esbensen 和 P. Geladi。主成分分析。化学计量学和智能实验室系统,2(1–3):37–52,1987。

功能“控制流”——编写没有循环的程序

原文:https://towardsdatascience.com/functional-control-flow-writing-programs-without-loops-ce07e6137bba?source=collection_archive---------25-----------------------

小窍门

控制流的函数式编程特性概述—没有循环和 if-else

概述

在我上一篇关于函数式编程的关键原则的文章中,我解释了函数式编程范例与命令式编程的不同之处,并讨论了幂等性和避免副作用的概念是如何与函数式编程中支持等式推理的引用透明性联系起来的。

在我们深入了解函数式编程的一些特性之前,让我们从我写 Scala 代码的前三个月的个人轶事开始。

函数代码中没有“如果-否则”

我正在为一个定制的 Spark UDF 编写一个纯 Scala 函数,它基于一个用 JSON 字符串表示的定制分级调整来计算收入调整。当我试图用纯功能代码来表达业务逻辑时(因为这是团队的编码风格),我对我感觉到的生产力下降感到非常沮丧,以至于我在代码中引入了“if-else”逻辑,试图“完成工作”。

这么说吧,我在对那个特定的合并请求进行代码审查的过程中学到了一个非常艰难的教训。

“函数代码中没有 if-else,这不是命令式编程… 没有 if,就没有 else。

没有“if-else”,我们如何在函数式编程中写出“控制流”?

简答:功能构成

最长的答案是:函数组合和函数数据结构的结合。

由于对每个功能设计模式的深入探究可能相当冗长,本文的重点是提供一个函数组合的概述,以及它如何实现一个更直观的方法来设计数据管道。

函数合成简介

功能构成(图片由作者提供)

在数学中,函数合成是将两个函数 fg 依次取值,形成一个复合函数 h ,使得h(x)= g(f(x)】—函数 g 应用于将函数 f 应用于一个泛型输入 x 的结果。在数学上,该操作可以表示为:

f : X → Y,g:y→z⟹g♀f:x→z

其中g♀f是复合函数。

直观地说,对于域 X 中的所有值,复合函数将域 Z 中的XX 映射到域 g(f(x))

用一个有用的类比来说明函数组合的概念,就是用一片面包和冷黄油在烤箱里做黄油吐司。有两种可能的操作:

  1. 在烤箱中烘烤(操作 f)
  2. 将黄油涂在最宽的表面上(操作 g)

如果我们先在烤箱里烤面包,然后把冷黄油涂在从烤箱里出来的面包的最宽表面上,我们会得到一片涂有冷黄油的烤面包。

如果我们先将冷黄油涂在面包最宽的表面上,然后在烤箱中烘烤涂有冷黄油的面包,我们会得到一片涂有热黄油的烤面包(f♀g)。而且我们知道“冷黄油涂抹”!= "温黄油涂抹"

从这些例子中,我们可以直观地推断出函数应用的顺序在函数合成中很重要。(g♀f≠f♀g)

类似地,在设计数据管道时,我们经常通过将函数应用于其他函数的结果来编写数据转换。组合函数的能力鼓励将重复的代码段重构成函数,以实现可维护性可重用性

充当一级对象

函数式编程中的核心思想是:函数就是值

这个特征意味着一个函数可以是[2,3]:

  1. 赋给变量
  2. 作为参数传递给其他函数
  3. 作为其他函数的值返回

为此,函数必须是运行时环境中的一级对象(并存储在数据结构中)——就像数字、字符串和数组一样。包括 Scala 在内的所有函数式语言以及 Python 等一些解释型语言都支持一级函数。

高阶函数

函数作为一级对象的概念所产生的一个关键含义是,函数组合可以自然地表达为一个高阶函数。

高阶函数至少具有下列特性之一:

  1. 接受函数作为参数
  2. 将函数作为值返回

高阶函数的一个例子是map

当我们查看 Python 内置函数map的文档时,发现map函数接受另一个函数和一个 iterable 作为输入参数,并返回一个产生结果的迭代器[4]。

在 Scala 中,包scala.collections中的每个集合类及其子集都包含由 ScalaDoc [5]上的以下函数签名定义的map方法:

*def map[B](f: (A) => B): Iterable[B]    // for collection classes
def map[B](f: (A) => B): Iterator[B]    // for iterators that access elements of a collection*

函数签名的意思是map接受一个函数输入参数f,而f将一个A类型的通用输入转换成一个B类型的结果值。

为了对整数集合中的每个值求平方,迭代方法是遍历集合中的每个元素,对元素求平方,并将结果附加到随着每次迭代而长度扩展的结果集合中。

  • 在 Python 中:
*def square(x):return x * xdef main(args): collection = [1,2,3,4,5]# initialize list to hold resultssquared_collection = []# loop till the end of the collectionfor num in collection:# square the current number squared = square(num)# add the result to listsquared_collection.append(squared) print(squared_collection)*

在迭代方法中,循环中的每次迭代都会发生两种状态变化:

  1. 保存从square函数返回的结果的squared变量;和
  2. 保存 square 函数结果的集合。

为了使用函数方法执行相同的操作(即不使用可变变量),可以使用map函数将集合中的每个元素“映射”到一个新集合,该新集合具有与输入集合相同数量的元素——通过对每个元素应用平方运算并将结果收集到新集合中。

  • 在 Python 中:
*def square(x):return x * xdef main(args):collection = [1,2,3,4,5]squared = list(map(square, collection))print(squared)*
  • 在 Scala 中:
*object MapSquare {def square(x: Int): Int = {x * x}def main(args: Array[String]) {val collection = List[1,2,3,4,5]val squared = collection.map(square)println(squared)}
}*

在这两个实现中,map函数接受应用于值集合中每个元素的输入函数,并返回包含结果的新集合。由于map具有接受另一个函数作为参数的属性,所以它是一个高阶函数。

关于 Python 和 Scala 实现之间的差异,有一些简短的补充说明:

  • Python map vs Scala map:需要一个像list这样的可迭代函数将 Python map函数返回的迭代器转换成可迭代函数。在 Scala 中,不需要将来自map函数的结果显式转换为 iterable,因为Iterable trait 中的所有方法都是根据抽象方法iterator定义的,抽象方法iterator返回Iterator trait 的一个实例,该实例一个接一个地产生集合的元素[6]。
  • 如何从函数中返回值:虽然在 Python 中使用了return关键字来返回函数结果,但是在 Scala 中很少使用return关键字。相反,在 Scala 中定义函数时,会计算函数声明中的最后一行,并返回结果值。事实上,在 Scala 中使用return关键字对于函数式编程来说并不是一个好的实践,因为它放弃了当前的计算,并且不是引用透明的[7-8]。

匿名函数

当使用高阶函数时,能够用函数文字或匿名函数调用输入函数参数通常是方便的,而不必在它们可以在高阶函数中使用之前将其定义为命名函数对象。

在 Python 中,匿名函数也称为 lambda 表达式,因为它们源于 lambda 演算。一个匿名函数是用关键字lambda创建的,它不使用关键字defreturn包装一个表达式。例如,Python 中前面示例中的square函数可以表示为map函数中的匿名函数,其中 lambda 表达式lambda x: x * x用作map的函数输入参数:

*def main(args):collection = [1,2,3,4,5]squared = map(lambda x: x * x, collection)print(squared)*

在 Scala 中,匿名函数是按照=>符号定义的——其中函数参数定义在=>箭头的左边,函数表达式定义在=>箭头的右边。例如,Scala 中前面示例中的square函数可以用(x: Int) => x * x语法表示为匿名函数,并用作map的函数输入参数:

*object MapSquareAnonymous {def main(args: Array[String]) {val collection = List[1,2,3,4,5]val squared = collection.map((x: Int) => x * x)println(squared) }
}*

在高阶函数中使用匿名函数的一个关键好处是,单次使用的单表达式函数不需要显式包装在命名函数定义中,因此优化了代码行提高了代码的可维护性

递归作为“函数迭代”的一种形式

递归是自引用函数组合*的一种形式——递归函数获取自身(较小实例)的结果,并将它们作为自身另一个实例的输入。为了防止递归调用的无限循环,需要一个基本用例作为终止条件,以便在不使用递归的情况下返回结果。*

递归的一个经典例子是阶乘函数,它被定义为所有小于或等于整数 n 的正整数的乘积:

n!= n ⋅ (n-1) ⋅ (n-2)⋅⋯⋅3⋅2⋅1

实现阶乘函数有两种可能的迭代方法:使用for循环和使用while循环。

  • 在 Python 中:
*def factorial_for(n):# initialize variable to hold factorialfact = 1# loop from n to 1 in decrements of 1for num in range(n, 1, -1):# multiply current number with the current productfact = fact * numreturn factdef factorial_while(n):# initialize variable to hold factorialfact = 1# loop till n reaches 1while n >= 1:# multiply current number with the current productfact = fact * n# subtract the number by 1n = n - 1return fact*

在阶乘函数的两种迭代实现中,循环中的每次迭代都会发生两种状态变化:

  1. 存储当前产品的阶乘变量;和
  2. 被相乘的数字。

为了使用函数方法实现阶乘函数,递归在将问题分成相同类型的子问题时非常有用——在本例中,子问题是 n(n-1)的乘积!

阶乘函数的基本递归方法如下所示:

  • 在 Python 中:
*def factorial(n):# base case to return valueif n <= 0: return 1# recursive function call with another set of inputsreturn n * factorial(n-1)*
  • 在 Scala 中:
*def factorial(n: Int): Long = {if (n <= 0) 1 else n * factorial(n-1)
}*

对于基本递归方法,5 的阶乘按以下方式计算:

*factorial(5)
if (5 <= 0) 1 else 5 * factorial(5 - 1)
5 * factorial(4)    // factorial(5) is added to call stack
5 * (4 * factorial(3))  // factorial(4) is added to call stack
5 * (4 * (3 * factorial(2)))    // factorial(3) is added to call stack
5 * (4 * (3 * (2 * factorial(1))))  // factorial(2) is added to call stack
5 * (4 * (3 * (2 * (1 * factorial(0)))))    // factorial(1) is added to call stack
5 * (4 * (3 * (2 * (1 * 1)))) // factorial(0) returns 1 to factorial(1)
5 * (4 * (3 * (2 * 1))) // factorial(1) return 1 * factorial(0) = 1 to factorial(2)
5 * (4 * (3 * 2))   // factorial(2) return 2 * factorial(1) = 2 to factorial(3)
5 * (4 * 6) // factorial(3) return 3 * factorial(2) = 6 to factorial(4)
5 * 24  // factorial(4) returns 4 * factorial(3) = 24 to factorial(5)
120 // factorial(5) returns 5 * factorial(4) = 120 to global execution context*

对于 n = 5 ,阶乘函数的评估涉及对阶乘函数的 6 次递归调用,包括基本情况。

虽然与迭代方法相比,基本递归方法更接近于阶乘函数的定义(也更自然地)来表达阶乘函数,但它也使用更多的内存,因为每个函数调用都作为堆栈帧被推送到调用堆栈,并在函数调用返回值时从调用堆栈中弹出。

对于更大的 n 值,递归会随着对自身的更多函数调用而变得更深,并且更多的空间必须分配给调用栈。当存储函数调用所需的空间超过调用堆栈的容量时,就会发生堆栈溢出

尾部递归和尾部调用优化

为了防止无限递归导致堆栈溢出和程序崩溃,必须对递归函数进行一些优化,以减少调用堆栈中堆栈帧的消耗。优化递归函数的一种可能方法是将其重写为一个尾递归函数。

尾部递归函数递归调用自身,并且在递归调用返回后不执行任何计算。当一个函数调用除了返回函数调用的值之外什么也不做时,它就是一个尾调用

在 Scala 等函数式编程语言中,尾调用优化通常包含在编译器中,以识别尾调用,并将递归编译为迭代循环,每次迭代都不会消耗堆栈帧。事实上,堆栈帧可以被递归函数和递归函数中被调用的函数重用[1]。

通过这种优化,递归函数的空间性能可以从 O(N) 减少到O(1)——从每次调用一个堆栈帧减少到所有调用一个堆栈帧[8]。在某种程度上,尾部递归函数是“函数迭代”的一种形式,其性能与循环相当。

例如,阶乘函数可以在 Scala 中以尾部递归的形式表示:

*def factorialTailRec(n: Int): Long = {def fact(n: Int, product: Long): Long = {if (n <= 0) productelse fact(n-1, n * product)}fact(n, 1)
}*

虽然在 Scala 中尾调用优化是在编译期间自动执行的,但 Python 却不是这样。此外,Python 中有一个递归限制(缺省值为 1000),作为防止 CPython 实现的 C 调用堆栈溢出的措施。

接下来是什么:高阶函数

在本帖中,我们将了解:

  1. 功能组成
  2. 高阶函数是函数式编程的关键含义
  3. 递归作为“函数迭代”的一种形式

我们找到“如果-否则”的替代词了吗?不完全是,但是我们现在知道如何使用高阶函数和尾部递归在函数式编程中编写“循环”。

在下一篇文章中,我将更多地探讨高阶函数,以及如何将它们用于设计函数式数据管道。

想要更多关于我作为数据专业人员的学习历程的幕后文章吗?查看我的网站 https://ongchinhwee.me !

参考

[1]保罗·丘萨诺和罗纳·比雅纳松,Scala 中的函数式编程 (2014)

[2]阿尔文·亚历山大,《函数也是变量》 (2018),函数式编程简化版

[3] Steven F. Lott,函数式 Python 编程(第二版 ) (2018)

[4] 内置函数— Python 3.9.6 文档

[5] Scala 标准库 2 . 13 . 6—Scala . collections . iterable

[6]Trait Iterable | Collections | Scala 文档

[7]tpolecat——不归之点

【8】Scala 中不使用 Return?—问题— Scala 用户

[9] Michael R. Clarkson,尾部递归 (2021),OCaml 中的函数式编程

原载于 2021 年 7 月 4 日https://ongchinhwee . me

Python 中的功能建模和定量系统分析

原文:https://towardsdatascience.com/functional-modeling-and-quantitative-system-analysis-in-python-22b90bf0b9b5?source=collection_archive---------25-----------------------

实践教程

使系统框图可执行的编码模式

本文介绍了一种实用的编码模式来对系统进行建模和分析。这由一个的现实例子来说明。该示例是完整开发的,包括完整代码清单。这旨在成为系统架构师和工程师快速入门指南。

介绍

功能建模是一种建立工程系统模型的技术。模型化的系统被视为一组相互关联的功能。
每个功能都将输入转换为输出,其行为可能取决于参数。在图形上,这通常由功能框图来描述。

为了定量分析这种功能框图,需要一种可执行的数学表示。Python 非常适合这项任务。不仅仅是编码和执行数学模型,而是实际执行分析,绘制结果,并通过可复制的计算环境共享工作。本文介绍了 Python 中的一种编码模式,以简明地对功能框图建模,作为定量系统分析的一部分。编码模式应用于简单的工程分析环境中:信号转换链中的误差源分析。

功能链的示例

我们仅限于没有反馈回路的单向功能链的情况。反馈循环引入了需要扩展模式的动态效果——这将在后续文章中讨论。考虑下面说明性的功能框图。

说明性功能框图(图片由作者提供)。

它显示了从极坐标( θi,A )到笛卡尔坐标 (u,v) 以及反过来的变换链。需要注意的是,这个链中有一些错误源,用红色突出显示。为了举例,假设分析旨在量化由各种误差源产生的最终角度误差。这个例子的灵感来自于作者作为磁传感器架构师的职业经历[1]。基本原则是通用的。

假设极坐标到笛卡尔坐标的变换存在偏移。这些是一次分析运行的固定参数。进一步假设笛卡尔坐标被噪声污染,随机样本从具有给定标准偏差(另一个固定参数)的正态分布中抽取。最后一个功能块简单地用 2 参数反正切值重新计算输出角度(Numpy 中的 np.atan2 )。直观上,如果偏移和噪声相对于振幅 A 相对较小,则角度误差 θe 应该较小。

Python 中的函数定义

对于每个功能块,我们定义一个将输出与输入相关联的数学函数: Y= f(X,P)。通常,输入或输出可能是多维变量,因此使用大写符号。在功能输入中,我们区分在块之间流动的变量信号 X ,以及由设计或环境条件设置的具有固定值的参数 P 。对于给定的分析运行,这些参数是恒定的。Python 中有偏移误差的极坐标到笛卡尔坐标变换的直接对应函数定义如下:

def f(A, theta_i, offset_u, offset_v):return (A * np.array([np.cos(theta_i), np.sin(thetat_i)]) + np.array([offset_u, offset_v])) 

注意,上面的定义没有区分可变输入和固定参数。它还返回匿名输出:这两个输出被简单地分组在一个数组中,没有标记。这种编码方案是一个很好的起点,但缺乏模块化。

为了模块化,我们希望能够链接功能块,而不管它们的功能签名。为了获得统一的函数签名并允许链接,我们引入以下编码模式。

  • 首先,我们将所有固定参数分组到一个公共数据字典[1] dd 中。这使得确定用于分析运行的确切参数集变得更加容易。为了方便起见,我们将这个数据字典打包成一个 Pandas 系列,以允许使用更短的点符号快速访问底层元素: dd.parameter_1 (与 Python 中更冗长的 dd['parameter_1'] 相比)。
  • 其次,我们还将变量输入分组到另一个系列 X
  • 最后,输出也用命名标签分组。

按照这种约定,函数签名的形式总是:Y = f(X,dd)。这与输入和输出的数量无关。以下是 polar2cart 的改编定义:

dd=pd.Series({'offset_u' : 0.01, 'offset_v' : 0.0,'noise_std': 0.01,
})def polar2cart(X, dd):return ({'u': X.A * np.cos(X.theta_i) + dd.offset_u,'v': X.A * np.sin(X.theta_i) + dd.offset_v,})

可以按如下方式调用:

polar2cart(pd.Series({'A': 1, 'theta_i': 0}), dd=dd)

在现阶段,人们可能想知道上述公约有什么好处。好像挺啰嗦的。

所提出的模式的主要优点是易于扩展到表格数据集,在 Pandas 中称为数据框架。数据帧是用离散时间变化信号进行的完整模拟运行的简明表示,其中一行表示在给定时刻所有信号值的一个快照。

编码信号波形的数据帧(图片由作者提供)。

让我们从主要输入(模拟的刺激)开始:输入角度 θi 和振幅 A 。让我们针对两个幅度 A =1 和 A =2,生成对应于完整角度扫描(从 0 到 2π)的数据帧。

import itertools
itertools.product([1,2], [3])
df = pd.DataFrame(itertools.product(np.arange(0,2*np.pi,np.pi/100),[1,2]),columns=['theta_i', 'A'])
display(df)

我们现在可以包装我们之前的函数(在 Python 中这被称为“修饰”函数),这样它就可以处理数据框输入和输出。
这可以通过将函数应用于每一行,并连接输出和输入数据帧来实现。使用这种编码模式,在输入变量的表格数据集上执行任何函数 f 只需调用: df=f(df,dd)

下面是 polar2cart 函数的定义,这次它被包装成数据帧友好的,并调用它。

def apply_func_df(func):def wrapper(df, dd):Y = df.apply(func, dd=dd, axis=1, result_type='expand')return df.drop(columns=Y.columns, errors='ignore').join(Y)wrapper.__wrapped__ = funcreturn wrapper[@apply_func_df](http://twitter.com/apply_func_df)
def polar2cart(X, dd):return {'u': X.A * np.cos(X.theta_i) + dd.offset_u,'v': X.A * np.sin(X.theta_i) + dd.offset_v,}df=polar2cart(df, dd)
display(df)

对数据帧的操作

由于所有变量都在一个数据框中,我们可以利用 Pandas 库的广泛功能进行快速内联操作。例如,可以很容易地应用移动平均:

df[['u_avg', 'v_avg']]=df[['u', 'v']].rolling(2, center=True).mean()

像这样的简单操作可以直接在完整的数据帧上执行,而不需要调用我们的装饰器。这是因为 Pandas 内置的广播机制,默认情况下,它将算术运算扩展到整列。例如,要添加噪声,我们可以定义下面的函数,绕过我们的装饰器:

def add_noise(df, dd):df[['u', 'v']] += np.random.randn(len(df),2)*dd.noise_stdreturn dfdf=add_noise(df, dd)

对于复杂的操作(例如,控制逻辑,或者不同的输出),我们提出的编码模式仍然有效:定义一个初等函数并用我们的装饰器包装它。

对链条的其余部分进行建模

回到功能链,我们仍然需要对角度计算块进行建模。我们还可以计算考虑相位缠绕的角度误差(-π = +π,以角度表示)。使用我们的编码模式,我们将两个额外的函数 calc_anglecalc_angle_err 定义如下:

[@apply_func_df](http://twitter.com/apply_func_df)
def calc_angle(X, dd):return {'theta_o': np.arctan2(X.v, X.u)}[@apply_func_df](http://twitter.com/apply_func_df)
def calc_angle_err(X, dd):e = X.theta_o — X.theta_i# account for phase wrappingif e > np.pi:e-=2*np.pielif e < -np.pi:e+=2*np.pireturn {'theta_err': e}

最后的修饰操作可能是将弧度转换为角度,以便更容易地解释绘图。因为这是单个 Numpy 操作,所以我们可以直接对数据框列进行操作。我们在名称包含 *theta_* 的所有列上就地操作。

def convert_to_deg(df, dd):
df[df.filter(like='theta_').columns]=np.degrees(
df[df.filter(like='theta_').columns])
return df


# 完整管道所有功能块的功能都已定义,并在需要时进行包装,以使它们都与数据帧兼容。我们现在可以使用 pipe [3]操作符将所有操作链接起来,如下所示:

df=(df
.pipe(f1, dd)
.pipe(f2, dd))


完整的工作流程如下图所示。*   (a)我们从单向信号流的功能模型开始。
*   (b)我们用 python 函数 *Y=f(X,dd)* 对每个功能块建模。如果需要的话,我们包装了这个函数,这样包装的函数就可以直接在数据帧上操作。
*   (c)我们用主要输出填充数据框。
*   (d)我们按照与信号流相同的顺序依次调用管道中的每个函数。这将逐步扩展数据帧。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c26653d2834fa09ee3654dd035540d13.png)Python 中函数建模的工作流(图片由作者提供)。汇总统计也很容易计算,因为我们在单个数据帧中有所有信号值。下面我们展示了如何通过提取两个不同振幅的均方根(RMS)误差,在数据透视表中轻松总结结果。我们最后通过调用 *df.plot(…)* 或 *df.hvplot* 来绘制关键曲线,这是一个带有 Holoviews 的交互版本【4】。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2c4f4d24534a1ec1d155cadbea662b18.png)总结分析的交互式绘图和表格(图片由作者提供)。附录中提供了生成上述图的完整代码清单。# 结论我们提出了一个通用的编码模式,适合于用 Python 实现一个单向框图的可执行模型。该模式基于初等函数,这些初等函数直接作用于表格数据集,如 Pandas 数据框。然后简单地通过从刺激开始链接这些操作来调用端到端模拟。我们在定量系统分析中演示了这种编码模式,以说明其优势。主要优势是:1.  我们利用 Pandas 内置的大量数据框操作(切片、过滤、查询、数据透视表、绘图……)。
2.  我们获得了可直接追溯到框图的模块化可执行模型。# 参考[1] N. Dupré、Y. Bidaux、O. Dubrulle 和 G. Close,“具有 1%精度的杂散磁场免疫磁位移传感器”,IEEE Sens. J,2020 年 5 月。可用:[https://doi.org/10.1109/JSEN.2020.2998289](https://doi.org/10.1109/JSEN.2020.2998289)[2] Mathworks,“什么是数据字典?”。Mathworks 帮助中心。可用:[https://ch . mathworks . com/help/Simulink/ug/what-is-a-data-dictionary . html](https://ch.mathworks.com/help/simulink/ug/what-is-a-data-dictionary.html)。访问日期:2021 年 1 月 24 日。[3] B. Chen,“使用 Pandas 方法链接提高代码可读性”,走向数据科学,2020 年 8 月。可用:[https://towards data science . com/using-pandas-method-chaining-to-improve-code-readability-d 8517 c 5626 AC](/using-pandas-method-chaining-to-improve-code-readability-d8517c5626ac)[4] A. Rilley,“使用全息视图在 Python 中实现高级数据可视化”,走向数据科学,2020 年 6 月。可用:[https://towards data science . com/advanced-data-visualization-with-holo views-e 7263 ad 202 e](/advanced-data-visualization-with-holoviews-e7263ad202e)# 附录:完整的代码清单完整的代码笔记本可以在[那里](https://gist.github.com/gael-close/3dd0ef09a22def02ec97246543d9d4ae)找到,还有一个可执行版本的链接。# 函数主成分分析和函数数据> 原文:<https://towardsdatascience.com/functional-principal-component-analysis-and-functional-data-91d21261ab7f?source=collection_archive---------7----------------------->## [实践教程](https://towardsdatascience.com/tagged/hands-on-tutorials)## 简要介绍函数数据,尤其是函数主成分分析。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/839edd2e7f92c2056cd143b023d9e4a3.png)功能数据的典型示例(图片由作者提供)# 功能数据功能数据到底是什么?假设您连续多年每天都在测量家乡的温度。如果你接着查看累积的数据,你可能会得出结论,温度在一年内的表现有些相似。嗯,这很明显,我们毕竟是按照这种模式生活的。天气受时间控制。事实上,有人可以说,有一个潜在的时间函数,导致了你的测量。现在在函数数据分析中,我们不把我们的测量数据解释为一个观察序列,而是一个单一的函数或曲线。这比传统的时间序列视图有多方面的优势。1.  一个函数通常可以在任何时间点进行求值。
2.  我们可以分析函数的导数。
3.  功能可以很容易地注册到一个共同的时间表。
4.  函数可以为我们的数据提供更加自然和直观的视图。
5.  不必在相同的时间点进行测量才能进行比较。第五点其实是一个普遍的问题。经常发生的情况是,您想要比较时间序列,但是它们的测量值不是同时进行的,或者一个测量值比另一个测量值多。比较这些会有问题。如果我们把数据看作函数,比较就容易多了。# 我们是不是忘了什么?函数是连续的,测量是不连续的。是的,事实上测量是不连续的。但是我们可以估计数据的基本函数。通过这种方式,我们还能够进行平滑处理,这对于降低噪声来说是理想的。你可能会问,如何做到这一点?一种常见的方法是使用基展开。这里,我们将通过基函数的线性组合来表示我们的测量值。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4047bf84d62f97b0f87068d415ddd521.png)(图片由作者提供)常见的基函数是 B 样条、小波或傅立叶基。我们使用的基函数越多,我们得到的平滑就越多。这可能是为了减少噪音。在上面的图中,我使用了 20 个 B 样条来估计我的数据的基本函数。现在你知道了什么是函数数据,以及我们如何从我们的离散测量中估计出潜在的函数。你现在是某种专家了。# 功能主成分分析主成分分析的老大哥。有大量的技术来分析功能数据。其中许多都有一个非功能性的对应物,您可能已经使用过了。FPCA 是基于主成分分析,一种著名的降维技术。为了理解 FPCA,我们至少应该简要地谈谈 PCA。## 主成分分析函数主成分分析的小兄弟。PCA 解决了数据分析中的一个常见问题。很多时候,我们必须降低大型数据集的维度。这是很有问题的,因为每个维度都存储着信息,如果我们忽视它们,我们就会丢失这些信息。也就是说,我们需要在降低维度的同时测量信息。在 PCA 的情况下,这个度量是我们的数据内的变化。哪里有变异,哪里就有信息。PCA 找到所谓的主成分(向量),其沿着它们的方向最大化数据的方差。每个主成分解释了数据中总方差的一部分。他们建立了一个标准正交基,这意味着每个数据点是我们的主成分的线性组合。现在,我们可以通过使用 PC 的子集来表示数据点,从而降低数据的维数。例如,我们将选择最小数量的 PC,它们的总方差超过 95%。这样,我们减少了数据集的维度,但仍然保留了大部分信息。如果您不熟悉 PCA,我鼓励您阅读这篇文章,以便更好地了解这项技术。</a-one-stop-shop-for-principal-component-analysis-5582fb7e0a9c>  ## 真正的交易FPCA 本质上与 PCA 做完全相同的事情,但是有一些小的不同。在 PCA 中,我们处理向量,而在 FPCA 中,我们处理函数。这意味着我们的主要组成部分也是函数,或曲线。在下文中,我们称它们为功能主成分(fPC)。现在我们如何找到这些 fPC?![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/06820077f48a8887f4fafd1d62fe096c.png)给定 n 条曲线,通过最大化第一个 fPC 分数的方差来找到第一个 fPC。我们将第一个 fPC 限制为一个,因为我们可以通过增加第一个 fPC 来无限地最大化。这样我们可以找到最大化的明确答案。第一个 fPC 是我们数据变化的主要来源。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4bbbed6d70a11fc0432a28bb19bae7ab.png)现在,与第一个 fPC 相同的过程适用于第二个 fPC(以及以下所有 fPC)。只是这次我们有了一个额外的约束。也就是说,第二 fPC 与第一 fPC 正交。事实上,所有 fPC 都必须相互垂直。现在,每条曲线都可以表示为 fPC 的线性组合。fPC 分数告诉我们一条曲线在多大程度上由它各自的函数主成分组成。现在你也知道了功能主成分背后的理论,但是如何应用这种技术呢?# 一个典型的用例也是一个相当温和的人。可以探索性地使用 FPCA 来更深入地了解您的数据。现在我想给你们举个例子。我们想要分析的数据是过去 200 年来法国男性的对数死亡率。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7fe7cd53d12f2826c1f172985b25a02f.png)(图片由作者提供)首先,我们估计数据的基本函数。如前所述,我们使用 B 样条基展开来实现这一点。这额外导致平滑,这是伟大的,因为我们减少噪音。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4c4aa29eae4bc37f6b69ff7a21104a0b.png)(图片由作者提供)现在我们运行功能主成分分析,看看前两个功能主成分。这两个解释了我们数据中大约 97%的变化。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/523682a53c75c6e42e06a8c5fb8b0ee0.png)(图片由作者提供)这些功能性主成分的解释可能相当困难,因为在数据中可能没有明显的对应物。在我们的例子中,这种解释幸运地非常直观。第一个 fPC 似乎是我们数据的均值函数的变化。这种变化会随着时间的推移而减少。也可以说,我们越老,我们的死亡就越确定。这个 fPC 解释了我们数据中 94%的变化。第二个 fPC 似乎与 20-40 岁的人有关。这暗示了在我们的数据中,这个年龄组的死亡率与其他年龄组有很大的不同。我立即想到的是两次大战,它们造成了如此多年轻人不必要的死亡。还记得我们说过如何找到函数的主成分吗?当时,我们了解到数据中的每条曲线都可以表示为 fPC 的线性组合,其中每个 fPC 分数决定了曲线在多大程度上由哪个成分解释。我们现在可以做的是将每条曲线缩减为一个二维点,由前两个 fPC 分数组成。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/adc1735d31db318065acaee577a2d12a.png)(图片由作者提供)这很有趣。通过颜色编码,我们可以看到战争年代的曲线在很大程度上是由第二 fPC 解释的。这是一个好消息,因为我们的解释是正确的。我们也可以很清楚地看到,死亡率在 1950 年左右有一个很大的转变。这在原始数据中并不清楚。我们不仅深入了解了数据,还在不丢失太多信息的情况下降低了数据的(高维)维度。我们现在能够进一步使用这种表示并应用传统的聚类算法。最后我想提一下,我从[2]中获得了这个分析的灵感。如果你对 FPCA 更深入的解释和示范性的使用感兴趣,我鼓励你去看看。在[3]中还可以找到 scikit-fda python 包的文档。它为多功能分析工具提供了许多易于理解的例子。[1] *人类死亡率数据库*。加州大学伯克利分校(美国)和马克斯·普朗克人口研究所(德国)。可在 www.mortality.org 的[或](http://www.mortality.org) [www.humanmortality.de](http://www.humanmortality.de) 获得(数据于【01.06.2021】下载)。[2]尚,H.."功能主成分分析综述."AStA 统计分析进展 98(2014):121–142。[[3]https://FDA . readthe docs . io/en/latest/auto _ examples/index . html](https://fda.readthedocs.io/en/latest/auto_examples/index.html)# 功能时间序列> 原文:<https://towardsdatascience.com/functional-time-series-83b717cca12?source=collection_archive---------12----------------------->## [实践教程](https://towardsdatascience.com/tagged/hands-on-tutorials)## 当我们更频繁地测量数据时,我们如何才能最好地分析它?功能数据分析(FDA)可以大大简化分析。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/357119f4747a382d32b4b05ca91469ec.png)由[罗斯蒂斯拉夫·萨维钦](https://unsplash.com/@ross_savchyn?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片随着内存空间的增长,存储数据变得越来越便宜,这反过来意味着存储越来越多的数据。在时间序列的情况下,这意味着更频繁地收集数据。然而,还不清楚如何对以(非常)高的频率记录的时间序列建模,尤其是当涉及(多个)季节性时。我们应该把数据看作一元时间序列还是高维的多元时间序列?在许多情况下,最好将观察值视为时间的函数,并分析这一函数时间序列本身。例如,我们可以将股票的日内价格划分为每日观察值,我们观察每天的价格随时间的变化。(听起来很专业,但是我们后面会看到一个例子!)当函数数据是连续的时,后一种方法特别有用,因为它意味着比高维向量更多的结构(对于连续函数,如果 *x* 接近 *y* , *f(x)* 接近*f(y)*; *x(i)* 对于一个向量 *(x(1),…,x(d))* ,不需要靠近 *x(i+1)* 。功能数据在不同的环境中自然出现,如医学(脑电图数据)、金融(股票价格)或气象学(温度)。在这篇博文中,我们将通过例子来尝试对函数时间序列有一个直观的理解。此外,假设检验的独立性和平稳性的假设函数时间序列介绍。注:自始至终,我们都假定你熟悉时间序列分析的基本概念。如果想刷新一下知识或者入门题目,可以查看我的 [*以前的博文*](/time-series-analysis-part-i-3be41995d9ad) *。*# 介绍先说个例子。假设我们在一段时间内测量了特定位置的温度,并且每天收集一个观测值,那么对于年份 *t* 和日期 *i* 我们有观测值 *X(t,i)* ,其中 *i ∈ {1,…,d},t ∈ {1,…,n}* 和 *d = 365* (每年的天数),如图 1 所示。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8455d3986f19b2a4a7c66f373d14c524.png)图 1:2013-2017 年悉尼每日气温;x 轴:时间,y 轴:摄氏温度;作者图片现在我们有不同的选择来处理数据。首先,我们可以将其视为一个单变量时间序列,并简单地按时间顺序连接数据,因此在技术上 *Y(t) = X(j,i)* 其中 *t = (j-1) d + i* 。在这种情况下,我们有季节性,这使得分析更加困难。我们还可以将时间序列建模为一个多变量时间序列,其维数与每年的观测值一样多,这样时间序列的每个观测值都对应于全年收集的数据: *Y(t) = ( X(t,1),…,X(t,d) )* 。现在不用考虑季节性,但是维度很高(准确的说是 365 维)。当然,我们可以通过降低观测频率来降低维数。然而,在这种情况下,我们丢失了信息,并且不清楚如何选择频率(每周还是每月?).最后一种方法是将数据视为函数时间序列 *Y(t,x)* ,其中我们有一个函数 *Y(。,x)* 为每年 *t* 用 *Y(t,i/d) = X(t,i)* 。在这种情况下,年温度被视为时间的函数,每个观测值对应于一个描述年温度的函数。在图 2 中,来自图 1 的数据被视为函数时间序列。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4d198f9d17cf8a69e9867c6e1cf5e327.png)图 2:悉尼不同年份的气温;x 轴:时间,y 轴:摄氏温度;作者图片数据的功能视角具有重要的优势。在这个例子中,全年的平均温度显然不是常数。然而,夏季的平均温度高于冬季的平均温度。因此,当建模为函数时间序列时,非平稳单变量时间序列可能是平稳的,因为我们比较的数据是合理的(例如,将 2016 年 1 月的温度与 2017 年 1 月而不是 2016 年 7 月的温度进行比较)。此外,将数据建模为函数时间序列通常比使用高维时间序列更自然,因为它增加了额外的结构。例如,如果我们观察连续函数,如温度或股票价格,两个相近时刻的值是相似的,而这种结构对于任意多元时间序列是不存在的。这在精神上类似于卷积神经网络。由于其特定的体系结构,CNN 的使用更多地局限于一组特定的问题,然而对于这组问题,它们工作得非常好。功能数据分析(FDA)是一个活跃的研究领域,可用于各种应用。在下文中,我们将重点关注一种特定类型的函数数据,即函数时间序列。然而,请注意,许多来自统计的经典结果被推广到功能数据,例如比较不同组的期望值的 t 检验。# 功能时间序列—基础知识好的,我提到了函数时间序列,我们看到了一个例子,但是数学上什么是函数时间序列呢?它与单变量时间序列有什么不同?数学上,只有很小的差别。单变量实时序列是由时间索引的真实数据的集合(见[此处](/time-series-analysis-part-i-3be41995d9ad))。所以对于时刻 *1,2,…,n* ,我们观察实值数据 *Y(1),Y(2),…,Y(n)* ,比如特定地点的温度或者某个股票的价格。一个*泛函时间序列*基本相同,只是我们观察的是函数而不是实值数据。在这种情况下, *Y(1),Y(2),…,Y(n)* 是函数,可以写成 *x* 中的函数,即 *Y(1)(x),Y(2)(x),…,Y(n)(x)* 。为了简单起见,我们经常假设函数定义在区间*【0,1】*上,必要时重新调整区间(如果 *f(x)* 定义在区间*【0,T】*, *g(x)=f(xT)* 定义在区间*【0,1】*)。*技术说明:我们在一个函数空间而不是实数空间中工作,不清楚如何为函数数据定义诸如期望值或协方差之类的量。幸运的是,在大多数情况下,均值和协方差可以逐点定义,因此等式 E[Y(i)](x) = E[Y(i)(x)]和 Cov(Y(i)(x),Y(j)(z)) = Cov(Y(i),Y(j))(x,z)成立。
根据观察值的连续性或 L-可积性等假设,我们可能有额外的结构(连续函数的空间是 Banach 空间,L-空间是 Hilbert 空间),在这些情况下,逐点定义是合理的。*# 平稳性和独立性测试至于单变量时间序列,平稳性和独立性的概念大大简化了任何进一步的分析,所以我们想知道它们是否是合理的假设。在概念层面上,想法与单变量的情况相同:如果概率因子分解,两个函数观察是独立的;如果时间序列的分布在一段时间内保持不变,则时间序列是稳定的(参见[这篇博客文章](/time-series-analysis-part-i-3be41995d9ad)的严格定义)。在[这篇博文](/time-series-analysis-part-ii-ii-bece7ecc9647)中,我们已经看到了如何验证单变量时间序列的两个假设。对于函数数据,我们可以做完全相同的事情,即使用累积和统计量来确定时间序列是否是(弱)平稳的,并使用组合测试来验证(或拒绝)独立性的零假设。## 弱平稳性测试当处理时间序列时,我们想知道它们是否是平稳的,因为在这种情况下,我们不需要考虑时间的变化。然而,平稳性是难以衡量的,我们经常使用时间序列的时刻作为代理。直观上,如果矩不随时间变化,我们可以忽略潜在分布的时间变化。因此,我们想测试给定时间序列的均值和(自)协方差是否是时不变的,而不是测试平稳性。对于一个函数时间序列 *Y(1)(x),Y(2)(x),…,Y(n)(x)* ,这转化为假设![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a4dd07e3df6d60fe19224d49263279b6.png)对于某些 *i ∈ { 2,…,n }* 和![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/74ec25b3f04305d7564c611d81593ea8.png)对于某些 *i ∈ { 2,…,n-h}* 。如果零假设对任意正整数 *h* 有效,则时间序列 *Y(i)* 是弱平稳的。注意 *Y(i)* 的一阶和二阶矩本身就是函数。所以两个函数相等依赖于函数空间。在连续函数空间中,比如两个函数 *f* 和 *g* 在任意一点 *x* 相等,那么如果 *f(x)=g(x)* 。相反,在平方可积函数空间 *L* 中,两个函数相等,如果它们几乎在每个点都重合(w.r.t .勒贝格测度)。我们通常将注意力限制在第一个 *H* 滞后上(对于所有 *1 ≤ h ≤ H* 的 *h* ),而不是对所有滞后 *h* 测试后面的假设,因为它们从根本上决定了分布的行为。在下文中,我们将只测试 *H₀* ,因为我们可以类似地测试关于二阶矩的零假设。此外,我们假设数据是平方可积的,因此它属于范数由 *||表示的空间 *L ([0,1])* 。||* 。在这种情况下,( 1)中的测试问题等价于![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/dcb48e3a7ab1bacf4b042410c68169cb.png)在单变量方案中,我们可以使用累积和统计量,它基本上将第一个观测值的平均值与其余观测值的平均值进行比较。(函数)累积和统计量定义为![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a5262d10d0ac6584d1b5bf5fda17ec1f.png)在零假设(和弱假设)下, *√n C(u,x)* 弱收敛于空间中协方差函数未知的一个中心高斯过程 *B(u,x)**L([0,1])**| |。||₂* 。反之, *√n C(u,x)* 在选择下偏向 *+∞* 或 *-∞* 。所以如果 *√n C(u,x)* 偏离其极限 *B(u,x)* 太多,我们可以拒绝 *H₀* 。不幸的是,我们不知道 *B(u,x)* 的分布,因为我们不知道协方差,需要估计它。有不同的方法可以做到这一点,时间序列分析中的一种常见方法是使用块乘数自举近似,这基本上是一种考虑时间相关性的重采样方案。如果 *q(α)* 表示 *||B||₂* 的 *α* 分位数(例如,通过 bootstrap 过程或协方差的直接估计获得),我们可以拒绝 *H₀* 每当 **√n ||C||₂ > q(1-α)** 。这为 *H₀* 定义了一个渐近一致水平α测试。## 组合式测验与平稳性类似,随机独立性很难测量,我们使用时间序列(自)协方差结构作为代理来评估其依赖程度。为简单起见,我们假设时间序列是平稳的和居中的,即 *E[Y(i)]=0* (这个假设可以用类似于给出的过程来检验)。同样,我们主要对小滞后的自协方差感兴趣。根据经典的组合测试,我们考虑假设![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/343ed55cf9b4f4badf5504474f508505.png)像以前一样,函数时间序列的二阶矩本身就是函数,所以我们根据它们的范数来制定假设。为了避免多重测试问题,我们同时比较所有的矩,而不是通过考虑它们的最大值来单独测试它们。作为检验统计量,我们可以使用(最大的)经验矩![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0c238f400fc7f7509d5b4e0c87ad86c9.png)估计器 *Mₙ(h)* 以概率收敛于*e[y(1)y(1+h)】*,滞后时的自协方差 *h* 。因此,我们可以拒绝零假设,如果 *Mₙ(h)* 明显偏离其极限。在零假设下,对于某个居中的高斯变量 *B(h)* ,认为 *√n ||Mₙ(h)||₂* 弱收敛于 *||B(h)||₂* ,而在选择下发散到无穷。同样, *B(h)* 的协方差结构是未知的,它的分布可以用 bootstrap 程序来近似,就像在平稳性测试的情况下一样。如果 *q(α)* 表示*最大{||B(h)||₂: 1 ≤ h ≤ H}* 的(近似) *α* 分位数,我们可以随时拒绝 *H₀*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5043c5d8408280d4fbf27eaeac1c082d.png)其为 h₀*定义了渐近一致水平α测试。*# 用 Python 实现对于实施,我们使用来自澳大利亚的气候数据。更具体的说是澳大利亚政府气象局[提供的悉尼(站号 066062)1859-2017 年的日最低气温。](http://www.bom.gov.au/climate/data/)首先,我们需要加载所需的包并准备数据:## 均值平稳性的检验为了测试均值的平稳性,我们定义了三个辅助函数来计算累积和统计量、 *L -* 范数和 bootstrap 复制来逼近分位数。

Test Statistic: 2.11
Approximated quantile: 1.84
The null hypothesis can be rejected


输出表明,我们可以拒绝常数均值函数的零假设。因此,从 1859 年到 2017 年,悉尼的温度不太可能是稳定的,这表明气候发生了变化。## 非相关性测试对于前面介绍的组合体类型测试,我们定义了两个辅助函数。第一个函数计算(函数)观测值的乘积,这些乘积稍后将用于更有效地计算经验矩。第二个函数生成 bootstrap 复制来逼近分位数。*请注意,计算可能需要一些时间,因为分位数近似值的计算开销很大。**还要注意的是,为了简单起见,我们假设时间序列是居中的和平稳的。在给定的例子中,这两个假设显然都不满足。通过减去估计的(局部)平均值,我们可以将该方法推广到非中心时间序列,但它将是不稳定的,如前面的测试所示。无论如何,我们可以用这些数据来说明这种方法。*

Test Statistic: 2587.612
Approximated quantile: 67.463
The null hypothesis can be rejected


结果表明,不相关的零假设可以被拒绝。如前所述,这一结果是不可解释的,因为它既不合理假设时间序列的中心性也不平稳。# 结论函数数据分析比单变量数据分析更具技术性,但具有一些重要的优势,可用于许多应用。在概念层面上,这两种方法是相似的,我们可以使用(几乎)相同的思想和技术。除了功能时间序列,FDA 还有许多其他重要的应用——它甚至可以用于维度缩减,这乍一看似乎违反直觉——这是我们作为数据科学家应该知道的一个话题。*如果你对时间序列分析监控机器学习模型的应用感兴趣,这篇文章可能适合你:*</monitoring-ml-models-in-production-768b6a74ee51>  *如果你对单变量时间序列感兴趣,可以看看这两篇入门帖子:*</time-series-analysis-part-i-3be41995d9ad>  </time-series-analysis-part-ii-ii-bece7ecc9647> # 在 Pandas 中生成多重索引的函数以及如何删除级别> 原文:<https://towardsdatascience.com/functions-that-generate-a-multiindex-in-pandas-and-how-to-remove-the-levels-7aa15ac7ca95?source=collection_archive---------6----------------------->## groupby 和 unstack 操作如何创建多重索引,以及如何在不损害数据完整性的情况下删除多重索引![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d3e6d4d38605c21e51d884c888a0e9a3.png)由[凯利·西克玛](https://unsplash.com/@kellysikkema?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片**简介**在本文中,我们将了解什么是多重索引,何时何地使用它,生成多重索引的函数,以及如何将它折叠成一个单一的索引。但是首先,让我们弄清楚一些基本的定义。**索引**是数据帧中“唯一”标识每行的一列。可以把它想象成行标签。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d7fea23625cbf36447cdc4209c94a57b.png)作者图片**多指标**是指有一个以上的指标。其他名称有*多重指标*和*分级指标*。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ae84f0cb41ba8e0a60c1156fd41634f1.png)作者图片Multiindex 也可以指**多个标题级别**,或者当你有一个列名的层次结构时。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9cf547ebbb9797a3bc29140f59e2dfe0.png)作者图片**多指标的优势***   用于保存包含层次结构或级别的高维数据。
*   以表格形式直观显示层次结构级别,非常有用。
*   它允许使用诸如 [df.xs()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.xs.html) 和 [df.unstack()](https://pandas.pydata.org/docs/user_guide/reshaping.html#reshaping-by-stacking-and-unstacking) 之类的函数有效地选择和操作层次数据。**多指标的缺点***   这种格式不允许直接绘制图表。
*   使用 multiindex 没有性能优势。我们将使用来自 [seaborn](https://seaborn.pydata.org/) 的 [diamonds 数据集](https://github.com/mwaskom/seaborn-data/blob/master/diamonds.csv)来演示导致多索引情况的各种场景,以及如何将多索引折叠回单个索引数据框架。

import pandas as pd
import seaborn as snsdiamonds = sns.load_dataset('diamonds')


那么,我们如何得到多个指数呢?## 第一部分:生成多重指数## A.行的多索引**A1。使用** `**df.set_index(col_list)**`下面的代码手动将索引设置为两列(`cut`和`clarity`)。

sorted_df = diamonds.sort_values([ 'cut’, ’clarity’])multiind_df = sorted_df.set_index([ 'cut','clarity'])multiind_df


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/246366630fd8dce74e6ac11ff2aabae8.png)按作者分类的多索引数据框架需要注意的事项:*   层次结构按预期显示。如果没有,记得对这些列的数据帧进行排序。
*   得到的数据帧的行数不变,而是重新排列数据帧,使得层次结构可见。

diamonds.shape###Results
(53940, 10)multiind_df.shape###Results
(53940, 8)


*   结果列的数量现在少了两个,因为索引丢失了一些列(参见上面的`df.shape`的结果)。
*   该索引现在是多索引。运行`df.index`显示一个多索引列表,其中每个元素都是一个[元组](/ultimate-guide-to-lists-tuples-arrays-and-dictionaries-for-beginners-8d1497f9777c)。

multiind_df.index


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c57e4321e6ede32c878abc1b5197fa41.png)作者图片*   默认情况下,先前的索引已被删除。当我们将索引设置为新数据帧中的另一列时,请看下面发生的情况。

multiind_df.set_index('carat')


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/09b461625ffb5656fbca8c83a98eb525.png)作者图片如果您想保留以前的索引,首先使用`df.reset_index()`使索引成为现有列的一部分,然后使用`df.set_index(col_list)`。**A2。由多列**的 `**groupby**` **产生的多索引**`[df.groupby](https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html)`根据所选列的类别汇总列(特征)。例如,我们可以通过`cut` 和`color`对菱形进行分组,以查看其他特性在这些类别中的分布情况。我们使用`max()`作为[聚合函数](https://cmdlinetips.com/2019/10/pandas-groupby-13-functions-to-aggregate/)。

grouped_df = diamonds.groupby([’cut’, 'color’]).max()grouped_df


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4fe8d16913c010b34c2f1ab2b51fbe61.png)按作者分组图片需要注意的事项:*   行数将大大减少。这是因为只显示唯一的索引(这里是唯一的`cut`和`color` 组合)。指定的聚合函数(`max`)将这些组中的其他值组合成一个值。

diamonds.shape###Results
(53940, 10)grouped_df.shape###Results
(35, 7)


*   列数也减少到 7 列,因为现在有两列作为索引,而`clarity`被删除,因为聚合函数`max` 不能处理非数字特性。## B.列的多索引(多个标题级别)现在让我们来演示一下我们是如何得到多个标题级别的。**B1。** `**Groupby**` **超过两列则** `**unstack**`我们将继续使用上一节的代码。我们用`cut`和`color.`进行分组现在让我们将它分解,这样`‘cut’`类别就显示为列标题。这是通过将它们从行索引翻转到列标题来实现的。

grouped_df = diamonds.groupby(['cut','color']).max()unstacked_df = grouped_df.unstack('cut')unstacked_df


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/78c91d77b6580429f109d0224e1efa6f.png)作者未堆叠 df 的图像我们现在在原来的标题下面有了一个新的标题级别— `carat`、`depth`、`price,`等等。B2。 `**Groupby**` **使用几个聚合函数**在我们之前的分组中,我们只使用了 `max()`作为[聚合函数](https://cmdlinetips.com/2019/10/pandas-groupby-13-functions-to-aggregate/)。但是,我们可以包含几个聚合函数,它们的名称将保持在一个新的级别。下面的代码将数据按一列分组— `cut` —但是使用了 3 个聚合函数— `median`、`max`和`mean`。

diamonds.groupby( 'cut').agg( ['median','max','mean'] )


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/860feb3dfe3004906db72ff7e154f290.png)作者图片B3。使用 `**pivot_table**` **将行转换成列**一个`pivot_table`提供了一种方便的方法来将列的值重新整形为列标题,就像我们上面使用的 unstack 方法一样。在这里,我们将关注我们的原始钻石数据集。

diamonds.pivot_table(
values = 'price',
index = 'color',
columns = ['clarity','cut'],
aggfunc='median')


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9b370cdd8922f39c9a3b1d34f4ce400b.png)作者数据透视表 _ 表格**B4。熊猫交叉标签**`pandas.crosstab`功能允许我们创建数据频率表。在下面的代码中,我们希望找到每个`color`的`clarity`和`cut`的分布。我们使用`normalize=’columns’`来显示每列的百分比分布。

pd.crosstab(
index = diamonds[’color’],
columns = [diamonds[’clarity’],
diamonds[’cut’]],
normalize = 'columns’)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d8fa9935f1b44b03949e5f4f357d61c4.png)作者的交叉表插图## 第二部分:删除多重索引## **C .删除多行索引(每行多个索引)****C1。使用** `**df.reset_index()**``df.reset_index()`通过将现有索引转换为普通列来重置索引。生成一个[范围索引](https://pandas.pydata.org/docs/reference/api/pandas.RangeIndex.html)作为新的索引。

grouped_df.reset_index()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/38156bb08e8b0c2be58deee869671bc0.png)作者图片在多索引的情况下,我们可以通过包含`level=n`来选择要重置的索引的名称(或位置)。

grouped_df.reset_index(
level='cut')


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a2832245ea033c1afdebad48e3f7f1c6.png)作者图片我们还可以重置索引,并仍然保持多个标题级别。

df = diamonds.groupby(
'cut’).agg(
[’median’,’max’,’mean’])df.reset_index()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5b3322e7ef9c52ae6d58eae0968e74b0.png)作者图片**C2。使用** `**df.droplevel(level = level_to_drop, axis=0)**`删除多索引当您想要完全删除一个索引时,可以使用这种方法。使用前面生成的`grouped_df`,让我们删除`color`索引。注意,我们既可以用`level=index_name`也可以用`level=position`(从 0 开始计数为最外层)。该方法返回修改后的数据帧。

grouped_df.droplevel(
level = 1,
axis=0)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0a86bb7b7555ef35014283c40b4d2a89.png)作者图片**C3。使用** `**df.index.droplevel(level = level_to_drop)**`删除多索引该函数从索引中删除指定的级别,并返回剩余的索引列表。下一步是将这个列表指定为数据帧的索引。

grouped_df.index = grouped_df.index.droplevel('color')


打印数据帧,显示与上一节中的图像相同的结果。## D.删除列标题中的多索引**D1。合并每列的级别名称**合并标题级别是一种常见的解决方案,因为两个级别都可能有用,并且在这里不可能重置索引。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2df8479340d5b176c5c7a8d11292840b.png)多个标题级别![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/428d13431ec85502f5ff96213729ee55.png)按作者列出的列名元组列表***方法 1:使用*** `***map***` ***和*** `***join***` ***功能***函数使用给定的函数修改列表中的每个元素。这里,我们为每个列名准备了一个元组列表。地图用途[。连接](https://www.jquery-az.com/3-ways-convert-python-list-string-join-map-str/)将元组合并成一个用下划线分隔的名称。

df.columns.map('_'.join)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0b27b61f4db3eae6eed3871d77e6afae.png)上面的代码返回一个索引对象。我们需要将它分配给列名,然后打印出数据帧。

df.columns = df.columns.map('_'.join)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/fb1836fa439ec6b056ae55b6307164b6.png)按作者合并标题级别***方法二:利用列表理解***一个[列表理解](https://realpython.com/list-comprehension-python/#using-list-comprehensions)也接受一个列表,通过一些操作修改每个元素,并返回一个新的列表。我们使用。join 使用不同的连接符号(|)将每个元组合并为一个名称。

df.columns = ['|'.join(s) for s in df.columns]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7ffe4e17b5d203a4c48304e0332f371e.png)作者图片另一个列表理解示例使用了 [f 字符串格式](https://zetcode.com/python/fstring/)。这有助于在合并后更改名称的顺序。在下面的代码中,低级别的名称排在最前面。

df.columns = [f'{j}#{i}' for i,j in df.columns]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/52ea8e270d1de7edcfc74ac9b59d322a.png)按作者合并后反转名称**D2。使用** `**df.droplevel(level, axis=1)**`删除每列的多索引如果标题级别对标识列没有用,您可以选择删除它。我们使用`axis=1`(或`axis= ’columns’`)来表示列标题级别。让我们来演示一下。首先,我们通过`cut`对数据集进行*分组,并使用**四个**聚合函数。然后我们使用`df.xs()`只选择`price`列。*

df = diamonds.groupby(
'cut').agg(
['max', 'median', 'min','mean'])df.xs(
key='price',
axis=1,
level=0,
drop_level=False)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/71534a84c82fa7447d2a4e10ae623dba.png)作者图片现在我们可以放弃顶层`‘price’`,因为我们已经知道所有的值都代表价格。

df_price.droplevel(
level=0,
axis=1)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b69fa68a4070931c83b1b21e4f49cb36.png)作者图片**D3。** `**df.columns.droplevel(level_to_drop)**`我们还可以删除一个标题级别,并以列表形式返回所需的级别。(这与前面的`df.index.droplevel`类似,但用*列*代替*索引*)。然后,我们将这个列表分配给列名。

df.columns = df.columns.droplevel(0)display(df)


打印数据帧,显示与上一节中的图像相同的结果。D4。 `**df.columns.get_level_values(level_to_return)**`该函数返回所需的级别并删除其余的级别。下面的代码产生的结果与上一节中的图像相同。

df.columns = df.columns.get_level_values(1)df


## 结论在本文中,我们探讨了生成多索引的各种函数,以及如何将它折叠回只有一个索引的基本数据框架。从头开始创建多索引数据框架还有其他方式和几种复杂的方式[访问和选择数据](https://stackoverflow.com/questions/18835077/selecting-from-multi-index-pandas)。我鼓励您使用包含许多显著分类特征的多维数据进行实验和实践,并尝试使用多索引。在这里找到这篇博文[中使用的代码](https://github.com/suemnjeri/medium-articles/blob/main/multiindex/Multiindex%20notebook.ipynb)。如果你喜欢这个内容,并希望得到更多类似的通知,请在这里订阅。如果你还不是一个中等会员,在这里加入。感谢您的阅读。## 参考1.[熊猫多指数教程](http://zaxrosenberg.com/pandas-multiindex-tutorial/)作者 [Zax Rosenberg,CFA](https://zaxrosenberg.com/)2.[访问熊猫多索引数据框架](/accessing-data-in-a-multiindex-dataframe-in-pandas-569e8767201d)中的数据 [B. Chen](https://medium.com/u/563d09da62a?source=post_page-----7aa15ac7ca95--------------------------------)3.[层次索引](https://jakevdp.github.io/PythonDataScienceHandbook/03.05-hierarchical-indexing.html#The-Better-Way:-Pandas-MultiIndex)摘自杰克·范德普拉斯的 [Python 数据科学手册](http://shop.oreilly.com/product/0636920034919.do)# FuncTools:一个被低估的 Python 包> 原文:<https://towardsdatascience.com/functools-an-underrated-python-package-405bbef2dd46?source=collection_archive---------4----------------------->## 使用 functools 将您的 Python 函数提升到一个新的水平![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2407bd5130bb6bd820571d72ff123d07.png)([https://unsplash.com/photos/gnyA8vd3Otc](https://unsplash.com/photos/gnyA8vd3Otc)# 介绍上个月,我写了一篇关于 Python 标准库中一些模块的文章,我发现这些模块在我的编程和数据科学生涯中非常有用。这篇文章获得了高质量的反馈,因此我决定再写一篇文章,讨论相同的主题,使用大家都应该熟悉的更多标准库工具。事实证明,Python 编程语言的基础实际上是相当包容的,包括了许多应对各种编程挑战的优秀工具。如果你想读这些文章中的任何一篇,你可以在这里查阅:</10-surprisingly-useful-base-python-functions-822d86972a23>  </15-more-surprisingly-useful-python-base-modules-6ff1ee89b018>  当浏览这些工具时,似乎有些工具应该有一整篇文章专门介绍它们,而不仅仅是对它所提供的大多数其他模块的概述。我认为最能体现我这种想法的工具是 functools 模块。这是一个非常强大的模块,通过使用简单和经典的方法,可以用来改进 Python 中的几乎任何功能,例如利用处理器速度上的堆栈。虽然在某些情况下,我可以看到这是一个很大的负面影响,但当然也有例外。> [笔记本](https://github.com/emmettgb/Emmetts-DS-NoteBooks/blob/master/Python3/Functools%20examples.ipynb)# 隐藏物functools 模块提供的最酷的东西可能是能够在内存中缓存某些计算,而不是为了以后重新计算而丢弃它们。这是节省处理时间的一个很好的方法,特别是如果您发现自己处于 Python3 超时的情况下,您的代码无法被解释。虽然这伴随着使用更多内存的代价,但是在许多不同的情况下使用它肯定是有意义的。Python 编程语言本身是相当声明性的,通常解释器为我们处理所有的内存管理。虽然这是一种效率较低的编程方法,但它也消除了许多分配内存和类似事情的麻烦。使用 functools,我们可以通过决定什么在堆栈中,什么将被重新计算来改变这一点。functools 提供的缓存的好处在于,它既易于使用,又允许用户更好地控制代码下的解释器。利用这一令人敬畏的特性就像在函数上方调用它一样简单。这里有一个关于阶乘计算的例子,我真的认为它很好地利用了这一点:

def factorial(n):
return n * factorial(n-1) if n else 1


为了在这个函数中使用缓存,我们将从 functools 中导入 lru_cache,并在我们的函数之前调用它:

@lru_cache
def factorial(n):
return n * factorial(n-1) if n else 1


现在,让我们评估一下,仅仅通过做这个简单的加法,我们可能已经获得的性能优势。让我们看看没有它阶乘函数计算阶乘有多快:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6ad8ecae3585afe721ae26afbdfb0855.png)现在,我将运行重新启动内核,以确保没有奇怪的内存问题发生,并运行我们使用 lru_cache 的新函数。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b65af91c297eeb034a82a350e27c3133.png)从这个例子中,我们可以看到使用这种缓存技术的巨大好处。众所周知,阶乘很难用计算机计算。在大多数情况下,这是因为阶乘是递归的自然数学示例。结果,二项分布的累积分布函数(CDF)让我做噩梦。这种计算非常密集,以至于编程语言的基本阶乘函数通常会使用查找表,而不是计算数字。也就是说,如果你打算像这样使用递归,开始熟悉 functools 可能是个好主意。这个标准的库工具可以大大加快 Python 通常很难解决的问题的解决速度。在某种程度上,它真的把我带回了 Numba Python 编译器,在那里一个简单的调用就能让你的代码变得更快。如果你想看我不久前写的一篇文章,你可以在这里看看:</numba-jit-compilation-but-for-python-373fc2f848d6>  # 关键功能有没有这样的时候,你真的想使用一些非常旧的 Python 代码中的函数,但是这个函数被编译成了一个比较函数?在现代 Python 3 中,这些类型的函数不再得到很好的支持,甚至不再被使用,并且将一种函数类型转换成另一种函数类型可能非常困难。也就是说,functools 可以通过另一个简单的方法调用轻松解决这个问题:

newfn = cmp_to_key(myfunction)


# 部分的partial 函数将返回一个新的 partial 对象,稍后可以使用完全相同的参数调用该对象,并且它的行为将与我们之前的 func 完全一样。代码中的函数最终看起来有点像这样:

def partial(func, /, args, **keywords):
def newfunc(
fargs, fkeywords):
newkeywords = {
keywords, **fkeywords}
return func(*args, *fargs, **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc


我们可以在之前使用阶乘函数创建一个分部:

from functools import partial
fact = partial(factorial)
fact(10)


partial()用于部分函数应用程序,它“冻结”函数参数和/或关键字的某个部分,从而产生具有简化签名的新对象。这样做的结果是,通过创建一个包装在全新对象中的函数的简化版本,可以轻松地节省内存和提高速度。# 减少reduce 函数将通过累积迭代应用两个参数的函数。记住这一点,我们需要我们的论点是可重复的。在这个例子中,我将使用一个生成器,range。这将使我们非常容易地构造出我们想要的任意长度的列表数据类型。

from functools import reduce
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])


这有什么用?这将把可迭代式简化成它的最简形式。reduce 的名字来自于它的数学等价物。这可以方便地节省运行时性能,并且像这个列表中的许多其他调用一样,没有一个好的借口不使用!# 派遣> 好吧——这真的真的很酷。我博客的读者可能会注意到我是 Julia 编程语言的超级粉丝。这不仅是因为 Julia 是一种令人敬畏的高性能科学编程语言,还因为我对多重调度有着特殊的吸引力。当这个概念不在的时候,我真的很怀念它,它让编程感觉更自然。在某种程度上,让函数更加基于类型,而不是仅仅通过不同的调用来处理不同的情况,这很好。Python 的 functools 模块实际上提供了一种方法,可以有效地将 Python 变成一种具有多重调度的编程语言。最重要的是,它像以前一样简单,只需添加一个装饰器。为了做到这一点,我们将首先用 singledispatch 修饰器来修饰一个函数,它不需要任何参数的特定类型:

@singledispatch
def fun(arg, verbose=False):
if verbose:
print("Let me just say,", end=" ")
print(arg)


现在我们将使用我们的 function.register 来注册新类型的调度:

@fun.register
def _(arg: int, verbose=False):
if verbose:
print("Strength in numbers, eh?", end=" ")
print(arg)
@fun.register
def _(arg: list, verbose=False):
if verbose:
print("Enumerate this:")
for i, elem in enumerate(arg):
print(i, elem)


# 结论Functools 是一个非常棒的软件包!此外,我认为这个包对于任何 Python 程序员来说都非常方便。这个包允许你用最少的努力来简化你的代码和数学。此外,更深入地了解语言及其缓存也相对容易,这对于提高某些方面的性能非常方便。几乎任何你想做的有趣的函数都可以用这个模块来完成,这太棒了!# func tools——Python 中高阶函数的威力> 原文:<https://towardsdatascience.com/functools-the-power-of-higher-order-functions-in-python-8e6e61c6e4e4?source=collection_archive---------9----------------------->## 浏览 Python 的 functools 模块,了解如何使用它的高阶函数来实现缓存、重载等等![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5bf0d481b827e09c9793ab94d8a5686d.png)Joel Filipe 在 [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄的照片Python 标准库包括许多伟大的模块,可以帮助你使你的代码更干净、更简单,而`functools`绝对是其中之一。这个模块提供了许多有用的高阶函数,这些函数作用于或返回其他函数,我们可以利用这些函数来实现函数缓存、重载、创建装饰器,并在总体上使我们的代码更具功能性,所以让我们浏览一下它,看看它能提供的所有东西...# 贮藏让我们从`functools`模块最简单却非常强大的功能开始。这些是缓存函数(也是装饰器)- `lru_cache`,`cache`和`cached_property`。其中第一个- `lru_cache`提供*最近最少使用的*函数结果缓存,或者换句话说- *结果存储*:在这个例子中,我们使用`@lru_cache` decorator 获取请求并缓存它们的结果(最多 32 个缓存结果)。为了查看缓存是否真正工作,我们可以使用`cache_info`方法检查函数的缓存信息,它显示缓存命中和未命中的数量。装饰器还提供了`clear_cache`和`cache_parameters`方法,分别用于使缓存的结果无效和检查参数。如果你想有一个更细粒度的缓存,那么你也可以包含可选的`typed=true`参数,这样不同类型的参数可以分别缓存。`functools`中的另一个缓存装饰器是一个简单称为`cache`的函数。它是在`lru_cache`之上的一个简单的包装器,省略了`max_size`参数,使它更小,因为它不需要驱逐旧值。还有一个装饰器可以用于缓存,它叫做`cached_property`。这个——正如您可能猜到的——用于缓存类属性的结果。如果你有一个计算起来很昂贵同时又是不可变的属性,这是非常有用的。这个简单的例子展示了我们如何使用缓存属性来缓存呈现的 HTML 页面,这些页面会一遍又一遍地返回给用户。对于某些数据库查询或长时间的数学计算也是如此。`cached_property`的好处是它只在查找时运行,因此允许我们修改属性。修改属性后,将不使用以前缓存的值,而是计算并缓存新值。也可以清除缓存,我们需要做的就是删除属性。在本节的最后,我要对上述所有装饰器提出警告——如果您的函数有任何副作用或者每次调用都会创建可变对象,请不要使用它们,因为这些不是您想要缓存的函数类型。# 比较和排序你可能已经知道在 Python 中可以使用`__lt__`、`__gt__`或`__eq__`实现比较操作符,比如`<`、`>=`或`==`。尽管实现`__eq__`、`__lt__`、`__le__`、`__gt__`或`__ge__`中的每一个都很烦人。幸运的是,`functools`模块包含了`@total_ordering`装饰器,可以帮助我们完成这个任务——我们需要做的就是实现`__eq__`,剩下的方法和 rest 将由装饰器自动提供:上面显示了即使我们只实现了`__eq__`和`__lt__`我们也能够使用所有丰富的比较操作。这样做最明显的好处是不必编写所有额外的神奇方法,但更重要的可能是减少了代码并提高了可读性。# 过载可能我们都被告知函数重载在 Python 中是不可能的,但是实际上有一个简单的方法来实现它,使用 `functools`模块中的两个函数- `singledispatch`和/或`singledispatchmethod`。这些函数帮助我们实现我们所谓的*多重分派*算法,这是 Python 等动态类型编程语言在运行时区分类型的一种方式。考虑到函数重载本身就是一个很大的话题,我专门为 Python 的`singledispatch`和`singledispatchmethod`写了一篇文章,所以如果你想了解更多,你可以在这里阅读更多:</the-correct-way-to-overload-functions-in-python-b11b50ca7336> [## Python 中重载函数的正确方法towardsdatascience.com](/the-correct-way-to-overload-functions-in-python-b11b50ca7336) # 部分的我们都使用各种外部库或框架,其中许多提供了需要我们传入回调函数的函数和接口——例如用于异步操作或事件监听器。这没什么新鲜的,但是如果我们还需要在回调函数中传递一些参数呢?这就是`functools.partial`派上用场的地方- `partial`可以用来*冻结*函数的一些(或全部)参数,用简化的函数签名创建新对象。迷惑?让我们看一些实际的例子:上面的代码片段演示了我们如何使用`partial`来传递函数(`output_result`)及其参数(`log=logger`)作为回调函数。在这种情况下,我们使用`multiprocessing.apply_async`,它异步计算提供的函数(`concat`)的结果,并将其结果返回给回调函数。然而,`apply_async`总是将结果作为第一个参数传递,如果我们想要包含任何额外的参数,就像在本例中的`log=logger`一样,我们必须使用`partial`。这是一个相当高级的用例,所以一个更基本的例子可能是简单地创建打印到`stderr`而不是`stdout`的函数:通过这个简单的技巧,我们创建了一个新的 callable(函数),它总是将`file=sys.stderr`关键字参数传递给`print`,这样我们就不必每次都指定关键字参数,从而简化了代码。最后一个好的衡量标准的例子。我们还可以使用`partial`来利用`iter`函数鲜为人知的特性——可以通过向`iter`传递 callable 和 sentinel 值来创建一个迭代器,这在下面的应用程序中很有用:通常,当读取一个文件时,我们希望遍历所有行,但是对于二进制数据,我们可能希望遍历固定大小的记录。这可以通过使用读取指定数据块的`partial`创建 callable 并将其传递给`iter`来完成,然后由后者创建迭代器。这个迭代器然后调用`read`函数,直到到达文件末尾,总是只取指定的数据块(`RECORD_SIZE`)。最后,当到达文件结尾时*返回标记值* ( `b''`),迭代停止。# 装修工我们已经在前面的章节中讨论了一些装饰者,但是没有讨论创造更多装饰者的装饰者。一个这样的装饰器是`functools.wraps`,为了理解我们为什么需要它,让我们首先看一下下面的例子:这个例子展示了如何实现一个简单的装饰器——我们用外部的`decorator`函数包装执行实际任务的函数(`actual_func`),外部的`decorator`函数成为我们可以附加到其他函数的装饰器——例如这里的`greet`函数。当`greet`函数被调用时,你会看到它打印了来自`actual_func`的消息以及它自己的消息。一切看起来都很好,这里没有问题,对不对?但是,如果我们尝试以下方法会怎么样:当我们检查修饰函数的 name 和 docstring 时,我们发现它被 decorator 函数内部的值替换了。这并不好——我们不能在每次使用 decorator 时覆盖所有的函数名和文档。那么,我们如何解决这个问题呢?—带`functools.wraps`:`wraps`函数唯一的工作就是复制名称、文档字符串、参数列表等。以防止它们被覆盖。考虑到`wraps`也是一个装饰者,我们可以把它放到我们的`actual_func`上,问题就解决了!# 减少在`functools`模块中最后但同样重要的是`reduce`。你可能从其他语言中知道它是`fold` (Haskell)。这个函数的作用是获取一个 iterable,然后*将*(或折叠)它的所有值变成一个值。这有许多不同的应用,以下是其中一些:从上面的代码中可以看出,`reduce`可以简化并经常将代码压缩成单行,否则代码会很长。也就是说,仅仅为了缩短代码、使*【聪明】*或使*更实用*而过度使用这个函数通常是个坏主意,因为它会很快变得难看和不可读,所以在我看来——少用它。此外,考虑到使用`reduce`通常会产生一行程序,它是`partial`的理想候选:最后,如果你不仅需要最终的*简化的*结果,还需要中间结果,那么你可以使用`accumulate`来代替——来自另一个伟大模块`itertools`的函数。这就是你如何使用它来计算运行最大值:# 结束语正如你在这里看到的,`functools`提供了许多有用的函数和装饰器,可以让你的生活更轻松,但是这个模块只是冰山一角。正如我在开始时提到的,Python 标准库包括许多可以帮助你构建更好代码的模块,所以除了我们在这里探索的`functools`,你可能还想检查其他模块,比如`operator`或`itertools`(我也写过关于这个的文章👇)或者直接进入 [Python 模块索引](https://docs.python.org/3/py-modindex.html),点击任何引起你注意的东西,我相信你会在那里找到有用的东西。*本文最初发布于*[*martinheinz . dev*](https://martinheinz.dev/blog/52?utm_source=medium&utm_medium=referral&utm_campaign=blog_post_52)</tour-of-python-itertools-2af84db18a5e>  </making-python-programs-blazingly-fast-c1cd79bd1b32>  </ultimate-guide-to-python-debugging-854dea731e1b> # 生成艺术的基本要素> 原文:<https://towardsdatascience.com/fundamental-elements-of-generative-art-11175f4741e5?source=collection_archive---------42----------------------->## [入门](https://towardsdatascience.com/tagged/getting-started)## 计算机生成视觉艺术的基本构成方法探索。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ddf7e3bda9b240922bfb0bf4699da9c1.png)*作者图片*[生成型](https://www.invaluable.com/blog/generative-art/)艺术家倾向于有条不紊,并意识到他们作品的抽象结构,这仅仅是因为用代码定义一件艺术品需要这种高水平的想象力。他们使用的一些结构和构图方法是如此的基础(也是编程媒介特别鼓励的),以至于当你在你看到的艺术品中遇到它们时,能够认出它们,并能够自己使用它们是很有帮助的。它不仅会使你自己的受孕过程变得清晰,还会帮助你识别哪些世代过程已经结束,哪些还相对新颖。下面我将描述我遇到的一些基本方法。当然,这不是一份详尽的清单。既然我们在谈论艺术,就没有穷尽。这只是我在欣赏和自己对生成艺术的尝试中认识到的一些工具。我将把重点放在经典的 2D 抽象生成艺术上。同样的原则适用于 3D,但如果我们着眼于基于 [AI](http://www.aiartonline.com/) - [的](https://aiartists.org/ai-generated-art-tools)艺术或自然图像处理,可能就不适用了。所以让我们来看看基本面…![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0b107294b3482f135aef34c1a3277c76.png)重复***重复*** 是计算机擅长的,而人类要么不擅长,要么很慢,所以这种创作工具被生成艺术家用来将自己与更传统的艺术区分开来是很自然的。重复本身可以给人一种平静和可预测的感觉。它可以用来设置你的图像的大规模组成或给你的图像一个细粒度的纹理。你经常会看到生殖艺术作品一遍又一遍地重复相同的形状或主题。大量的重复已经给艺术品带来了一些质感和复杂性,并将你的作品推向了传统艺术未曾涉足的领域。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/99634bfb1fe9de6fbb7fab2cd33f03f8.png)随机性***随机性*** 是计算机擅长的另一个领域。我相信这真的是很多生成性艺术的生命线。随机性给艺术带来独特性,可以应用于你艺术的任何方面:颜色、旋转、大小、几何、运动等等没有随机性的重复往往看起来平淡无味。但是将重复与随机性结合起来已经可以成为一件有趣艺术品的基础。随机性也可以用来模仿自然纹理——如果你把它看做一片草地,它基本上是一遍又一遍重复的相同对象,在大小、方向、缺陷等方面有随机变化随机性当然是一个广泛的概念,为了真正理解图像中发生的事情,我们至少应该考虑 3 种不同的概率分布作为随机性的基础:*   [均匀分布](https://en.wikipedia.org/wiki/Continuous_uniform_distribution):每个值都有相同的概率。这种分布可能有点无聊,但确实会导致“统一”的结果,但如果使用得当,它可能是生成型艺术家的主要分布。
*   [高斯分布](https://en.wikipedia.org/wiki/Normal_distribution):也许是所有概率分布中最受欢迎的。它倾向于均值附近的值,概率向两边对称下降。也许多亏了中心极限定理,高斯分布在自然界中很常见,能给你的随机性一种自然的感觉。有时采用截断的版本是有用的。
*   [泊松分布](https://en.wikipedia.org/wiki/Poisson_distribution):稀有事件的分布。最常用于使大部分值变小,但少数值突出。选择正确的发行版可以成就或毁灭艺术品。[这里的](https://tylerxhobbs.com/essays/2015/creating-soft-textures-generatively)是一个使用概率分布的设计过程的例子。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/467d669071b21bc790e2e9f6880c3550.png)分解***分解*** 是您可能经常看到的工具之一,因为它是一种简单的技术,可以通过编程轻松实现,例如通过递归,但可以给出有趣的结果。基本上,你把一个大的形状细分成更小的区域。最常见的是,一个几何形状(如三角形,圆形,…)被[细分成三角形](https://www.reddit.com/r/generative/comments/kkapuo/which_is_your_favourite/),再细分成三角形,再细分成三角形,…同样,[随机性可以帮助](https://tylerxhobbs.com/essays/2017/aesthetically-pleasing-triangle-subdivision)使结果在视觉上更加赏心悦目。当然,分解并不局限于三角形,实验例如弯曲的细分可能是富有成效的。我怀疑选择三角形是因为它们是可以细分任何基于顶点的几何图形的最简单的形状。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5d17feda7a904b1743c4abd6eb31486b.png)建筑如果分解是自上而下的方法,那么 ***构造*** 就是自下而上的。通常你定义一些迭代规则,每次应用时[通过每次迭代中的新元素增长你的形状](https://inconvergent.net/generative/hyphae/)。同样,递归可以用来给你的作品增加深度。也许最基本的例子是像 Mandelbrot 集合和 L 系统这样的分形。即使非常简单的规则也可能导致复杂的结构。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b513701abb6e4842cca8fef50a7da06d.png)模式打破例如通过任何前述技术建立的模式仍然会感觉太完美或死气沉沉。 ***打破模式*** ,通过添加瑕疵、省略部分等。可以使艺术品生动起来,整体上更有趣。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/611e39cb4c4cfc534b448d03debac29e.png)互动***交互*** 一个是也许不那么显而易见的一个方法。其思想是,在生成过程中,一些对象(线条、形状等)及其(可能随机影响的)属性会对周围的其他对象产生影响,例如,在空间上,通过相互吸引或排斥。这种交互可以是顺序的:每个对象都是根据以前的对象生成的。或者它可以是迭代的:生成对象,经过多次迭代,所有对象影响所有其他对象。inconvergent 的 Linetrace 是这种方法的一个非常简单但视觉上令人愉悦的例子。# 结束语还有更多的东西需要考虑,比如调色板、纹理、运动等等。但是上面的类别是一些(我相信)基本的技术,如果你特别关注生成视觉艺术的话,你会遇到的。我希望这篇文章对如何分析以编程方式生成的图像的生成过程有所启发,并对您自己的实验有所启发。希望你学到了有用的东西!# 软件系统可伸缩性的基础> 原文:<https://towardsdatascience.com/fundamentals-aboutscalability-of-software-systems-752ddbf889c4?source=collection_archive---------36----------------------->## 为可扩展系统设计建立直觉的指南![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5c8f92c733680954b902101f80a8e01f.png)萨姆·穆卡达姆在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片T4:我猜想你是一家杂货店的老板。您有一个计费柜台。顾客来到你的商店,挑选商品,然后在收银台排队付款。你有一个叫约翰的员工,在柜台后面接待顾客。约翰是一个无忧无虑的人,他微笑着欢迎每一位顾客,并在结账时与他们进行简短的交谈。当商店里的顾客人数较少时,约翰就从容不迫了。排队时不太匆忙,也没有人抱怨。然而,在高峰时段,约翰会缩短谈话时间,加快脚步,努力管理顾客。很快,你的杂货店就在镇上出名了,你会看到大批顾客涌入商店。这对企业非常有利。然而,现在你面临一个问题。您只有一名员工 John 和一个计费柜台。约翰正在尽最大努力处理客户负载,但他所能付出的努力是有体力限制的。毕竟他也是人。还有另一个问题。约翰有时身体不舒服,或者不得不休假。在这种情况下,你不得不关闭商店,因为你大部分时间都在外地工作。在这样的日子里,商店是不营业的。> 你必须“扩展”来解决这些问题你决定雇用另一名员工 Sam,并开设第二个结算柜台。这减轻了约翰身上的*【负载】*。有两个队列。一些顾客去找萨姆,而另一些去找约翰。你开心,约翰开心,你的顾客也开心。这也解决了第二个问题(在一定程度上)。当你的一个员工不在的时候,另一个可以试着接待顾客。当然,他的负担会更多,但至少你不需要在那天关门。它仍将是“可用的”。最终,客户数量不断增加,你决定开设第三个结算柜台并雇佣第三名员工。你知道,这个策略很有效。你的商店总是爆满,顾客现在排成 3 队。然而,有时会出现这样的情况,一个计费柜台上的线路比其他柜台上的线路长。顾客随机决定站在任何一个柜台前,结果可能是一个员工非常忙,而另外两个相对空闲。为了克服这种情况,你雇佣了第四名员工。他的工作是站在所有 3 个柜台的中心,通过查看哪个柜台是免费的等等来指引顾客去哪里。他在某种程度上“平衡”了工作负荷,使其或多或少地平均分配给你的员工。=====================================这与软件应用程序有什么关系?几乎每一点都是。在很高的层次上,软件 web 应用程序将由一个托管应用程序的 web 服务器和一个维护数据的数据库服务器组成。在上面的故事中-> 用“软件应用程序”替换“杂货店”
> 
> 用维护该应用程序的 web 服务器/数据库服务器代替 John。
> 
> 用应用程序的“用户”替换客户。该设置的架构如下所示。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/42e28f7ca0cf7f94e8d1ba42c1410301.png)作者图片用户(或客户)通过 URL (www.myapplication.com)访问您的应用程序。HTTP 请求被发送到 web 服务器。web 服务器返回 HTML 页面。想象一个 web 服务器/数据库服务器,就好像 John 正在处理来自客户的请求。随着客户数量的增加,您的系统(例如 John)的负载也会增加。由于您的 webserver/DB 服务器繁忙,客户将开始体验到较慢的响应,或者他们中的一些人可能得不到响应。你是做什么的?你得**【秤】**## **垂直缩放**垂直扩展,也称为“纵向扩展”,意味着您可以为您的服务器增加更多功能。例如,添加更多的 CPU 或 RAM,以便它能够处理更多的负载。这相当于说约翰开始使用更多的精力,减少闲聊,行动迅速。我知道这是一个非常糟糕的类比,但你会明白的。垂直缩放有一个限制。你不能只给一台服务器增加无限的内存或无限的 CPU。这就像说约翰只能以他的身体极限行动。没有更多的。同样,在这种情况下,如果服务器停机(John 休假),您的应用程序也会停机。它将“不可用”。## 水平缩放水平扩展或“向外扩展”意味着向您的设置中添加更多的服务器。这就像你在商店里雇佣额外的员工和开设更多的收银台。这种方法更适合有大量用户和大量数据处理需求的大型应用程序。实际上,您可以将多少台服务器添加到您的系统中是没有限制的。因此您的应用程序可以处理尽可能多的负载。当您的设置有很多服务器时,您可以使用一个 ***【负载均衡器】*** 将传入的流量平均分配到您的服务器上(记住,在我们的杂货店故事中,我们雇佣了第四名员工,他的工作是将顾客引导到不同的计费柜台)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/934f286f3f8e138699e46e41c857d0ab.png)作者图片这也解决了问题——当一台服务器停机时,另一台服务器仍然可以继续运行,您的应用程序不会变得“不可用”。这个概念也被称为*【高可用性】*。## 数据库复制在上面的系统设计中(是的…你可以称之为系统设计或者软件架构),我们已经搞定了 web 服务器。数据库服务器呢?我们还可以横向扩展数据库服务器。这被称为数据库复制。这个想法很简单。您有一个主数据库和这个主数据库的几个副本(称为从数据库)。所有插入/更新/删除都将在主数据库上完成,而从数据库将用作只读数据存储。这也确保了数据库的高可用性。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/963ccb5183790b4d93cce5b006b9659e.png)作者图片> 简单地说,如果您考虑可伸缩性,或者当您说您的软件应用程序或系统设计或软件架构是可伸缩的时,这仅仅意味着您的系统可以在可接受的响应时间限制内处理负载或请求。web 服务器和数据库服务器的水平扩展是实现这一目标的一个很好的方式。但是,我们还能做些什么来改善加载/响应时间呢?## 贮藏当您的应用程序被使用时,本质上存在对数据库的请求,这些请求被处理并提供给用户。一些这样的请求可能是相同的和重复的。如果我们将对应于这些请求的数据存储在比数据库更快的临时存储中,这将是有意义的。“缓存”就是这样一种存储。您可以将缓存添加到应用程序架构中。收到请求后,web 服务器将首先检查数据是否在缓存中。如果是,它将从缓存中获取数据并发送给客户端。否则,它将查询数据库,将数据存储在缓存中,并将其发送给客户端。我希望这篇文章为您提供了一种考虑可伸缩性的方法。还有许多其他的补充技术来设计和构建可伸缩的系统。我将尝试在后续文章中介绍它们。# 数据科学家的数据仓库基础> 原文:<https://towardsdatascience.com/fundamentals-of-data-warehouses-for-data-scientists-5314a94d5749?source=collection_archive---------20----------------------->## 数据科学## 或者说做好数据仓库有哪些维度设计原则?![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f42e6319636c376fe3fbd0be6126692e.png)在 [Unsplash](https://unsplash.com/s/photos/silo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上由 [Waldemar Brandt](https://unsplash.com/@waldemarbrandt67w?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 拍照对于数据科学家来说,机器学习模型和可视化包是必不可少的工具。但更重要的是,数据科学家依赖数据和数据基础设施来进行分析和建模。没有数据和数据库,所有开发的分析工具和技术都是无用的。许多数据科学家从几个信息源获得原始格式的数据。但是,对于许多数据科学家和业务决策者来说,尤其是在大型企业中,信息的主要来源是企业数据仓库。数据仓库是公司中所有可用数据(理想情况下)的结构化组织。使用数据仓库,数据科学家可以回答重要的业务问题并分析业务绩效。通常,数据科学家不关心数据仓库背后的过程和方法,他们只使用这些资源来完成他们的分析工作。通常,关于供应、创建和维护数据仓库的任务属于数据工程师的职责范围。但是,了解数据仓库的基础知识有助于数据科学家和业务决策者更有效地与数据工程师沟通。这篇短文涵盖了数据仓库及其设计的基础知识,称为维度设计。本文中的大部分概念都是从克里斯托弗·阿达姆松的一本名为《星型模式完全参考》的优秀著作中借用的<https://www.amazon.com/gp/product/B003Y8YWAE/ref=dbs_a_def_rwt_bibl_vppi_i0>  # 信息系统的类型在深入研究数据仓库之前,让我们快速回顾一下信息系统的两个主要类别(或者简单地说是数据库)。信息系统分为两大类:1.  交易/运营系统(OLTP)
2.  分析系统公司(OLAP)这里我们快速回顾一下这两个系统。## 交易/运营系统这些信息系统支持业务流程的执行。这些系统有时被称为“在线事务处理”(OLTP)系统,主要涉及数据库交互,如插入、更新和删除。例如,考虑一个社交媒体网站用户的数据库。这个数据库必须照顾用户注册,登录,张贴活动等。为了保持业务运行,事务/操作信息系统应该不断地读写数据库。它必须添加用户,更新他们的密码(如果他们要求的话),将他们的帖子添加到数据库,记录其他用户与他们的帖子的交互,等等。这个系统在处理数据库事务时必须非常高效。## 分析系统这些系统支持业务流程的分析。这些系统也被称为“在线分析处理”(OLAP)系统或数据仓库。分析系统主要通过查询和检索聚合数据来与数据库进行交互。举个例子,让我们回到我们的社交媒体业务。为了更好地了解我们的业务,我们需要回顾和理解我们的数据,并衡量我们的业务表现。例如,我们需要知道每月有多少人注册。最近有多少人发帖?简而言之,我们需要数据来洞察我们的业务表现。处理这些类型任务的信息系统和数据库不同于事务系统。这些类型的系统需要一个使查询简单、准确和高效的体系结构。# 什么是维度设计?维度设计是一套技术、原则和规则,用于设计适合分析系统的信息系统和数据库。请记住,分析系统的目标不同于交易系统。由于我们通常在交易系统中记录数据,为了将它用于分析系统,我们必须转换其架构和设计。维度设计帮助我们为我们的分析系统(即数据仓库)找到最佳的架构和设计。当我们找到最佳设计时,然后通过一个称为 ETL(提取、转换和加载)的过程,我们可以将数据和信息从交易/运营系统中获取到分析系统中。## 维度设计的中心:事实与维度维度设计中最重要的概念是理解数据库中的任何类型的数据都属于这些组之一:1.  事实
2.  规模事实是我们想要监控并从中获得答案的度量。例如,如果您想知道 2020 年每月注册的用户数量,您想要的事实(您正在寻找的事实)是“用户数量”。大多数时候,你是在某些语境中寻找事实。比如我之前的问题(即“2020 年每月注册用户数是多少?”),我在寻找基于“注册月数”的用户数量因此,注册的月份为我的事实提供了一些背景(例如,注册用户的数量)。维度为事实提供了语境,没有维度,事实几乎毫无意义。有时候很容易找到事实和维度;有时候,这很难。一旦可以将事实和维度分开,就可以为事实建立一个表。对于你的维度,你必须做更多的工作,并根据你的分析目的将它们分成几个主要的组。但是请记住,您不希望像大多数人对事务系统所做的那样,为您的维度数据创建许多表。现在,新的维度表可以链接到事实表。现在,如果你看看你的数据库设计,你看到了什么?你的答案见下一节。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f460ea63fbb3318fd94b3d9c86ac7039.png)## 星形模式一个分析系统的最简单的视图是一个事实表被几个维度表包围,或多或少像一个星形。这就是为什么我们称之为星型模式。星型模式是简单关系数据库的维度模型。换句话说,将维度设计的原则应用于简单的关系数据库会产生一个类似星形的数据库模型,称为星型模式。星型模式提供了一种高效而准确的方法来查询数据库(尤其是大型数据库)以进行分析。请记住,星型模式是维度设计的一部分,而不是整个概念。# 数据仓库架构的类型尽管数据仓库的体系结构各不相同,但它们通常归入以下三类:1.  独立数据集市架构
2.  企业信息工厂架构(比尔·恩门)
3.  多维数据仓库架构(Ralph Kimball)在解释每个体系结构之前,让我快速地向您介绍一下“数据集市”的概念数据集市是为特定主题领域或业务需求而构建的小型(有时经过过滤和聚合)数据库。例如,我们可以构建一个数据集市来分析客户行为,或者构建一个数据集市来分析我们的库存问题。所有这三种体系结构通常都以数据集市的形式向数据科学家和决策者提供数据(在下图中显示为用户)。在某些体系结构中,数据集市是直接从事务/操作数据库构建的。在其他一些情况下,它们是由中央数据仓库生成的。通过了解数据集市的概念,让我们来回顾一下这三种数据仓库架构。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f3391d90f3b4ab232779dbbda3a81f95.png)独立数据集市架构的摘要(图片来自作者)。独立的数据集市是最简单的数据仓库架构。在这种体系结构中,对于特定的业务需求或主题领域,您可以从您的事务/操作数据库中创建一个集中的数据集市。这一过程简单、直接且成本低廉。但是,您应该为另一个主题领域从头开始创建一个单独的数据集市。如您所见,如果您只需要构建有限数量的数据集市,这种方法非常有效。构建和维护大量独立数据集市的过程变得非常困难,因此,许多大型组织都避免使用这种方法。与独立的数据集市架构不同,另外两种架构建议首先创建一个中央数据仓库,然后从中央数据仓库创建主题领域数据集市。因此,您不需要在每次想要构建数据集市时重复从事务/操作数据库中提取和转换数据的过程。此外,这种方法使您能够更容易、更准确地维护和更新数据集市,因为它们连接到单一的信息源。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/430a8658c3865a8c8d552cb5ddd91c0f.png)Inmon 的企业信息工厂架构摘要(图片由作者提供)。在比尔·恩门开发的企业信息工厂架构中,首先,我们建立一个中心数据仓库,称为*企业数据仓库*。正如您所猜测的,企业数据仓库从事务/操作系统中获取信息。用技术术语来说,企业数据仓库是一个标准化格式的原子数据的集成存储库。原子特性表明,在这个中央数据仓库中,数据处于其最低级别(没有聚合)。此外,我们有标准化格式的数据,类似于操作系统(无维度设计)。最后,从这个中央数据仓库中为不同的业务分析目的创建数据集市。值得一提的是,在这个体系结构中,维度设计的原则并不应用于中央数据仓库(即企业数据仓库),而是应用于数据集市。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/98f05dd7f2199e83475336b627f608cf.png)Kimball 的维度数据仓库架构摘要(图片由作者提供)。最后,我们有主要由 Ralph Kimball 开发的多维数据仓库架构。像前面的架构一样,这里我们有一个名为*多维数据仓库*的中央数据仓库,它从事务/运营系统获取信息。这个中央数据仓库为数据科学家和业务决策者用于分析的多个数据集市提供数据。你可能会想,这个架构和之前的有什么区别?主要的区别在于我们将维度设计的原则应用到我们的建筑中的步骤。在维度数据仓库架构中,我们将维度设计原则应用于中央数据仓库(即维度数据仓库)。在企业信息工厂架构中,我们没有将维度设计原则应用于中央数据仓库(即企业数据仓库)。然而,公司数据工厂架构应用维度设计原则来构建数据集市。这两种体系结构之间另一个有趣的区别是数据集市概念的不同。在企业信息工厂架构中,数据集市是与中央数据仓库分离的物理实体。但是在多维数据仓库架构中,数据集市是物理上存在于我们的中央数据仓库中的逻辑实体。# 摘要分析系统不同于交易/运营系统。它们的不同性质需要不同的设计和架构。在本文中,我们讨论了三种主要类型的数据仓库架构。我们还了解了维度设计,以及它是如何应用在这些主要建筑中的。# 机器学习的线性回归基础> 原文:<https://towardsdatascience.com/fundamentals-of-linear-regression-for-machine-learning-87d684007dee?source=collection_archive---------34----------------------->## 探索最古老和最常见的统计和机器学习模型![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f4baf3a7ba392c8666beeb34573aaee0.png)图片由[彼得 H](https://pixabay.com/users/tama66-1032521/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2439189) 来自[皮克斯拜](https://pixabay.com/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2439189)回归是预测连续变量的技术,连续变量是在任意两个值之间具有无限个值的数值变量。线性回归是最重要和最广泛使用的回归模型之一,主要是因为它的简单性和易于解释。其他流行的回归模型包括多项式、岭、套索、弹性网、主成分回归、支持向量回归、泊松和许多其他模型。线性回归是一种统计模型,它假设输入/独立(x)要素和目标/预测(y)要素之间存在线性关系,并根据 x 和 y 之间的关系通过数据拟合直线。在有许多输入要素的情况下,x = (x₁,x₂,… xₙ),其中 *n* 是预测要素的数量。这被称为**多元线性回归。**简单线性回归是指只有一个输入(x)特征。线性回归通常只需要一个要预测/估计的目标特征 y。`ŷ=β₀+β₁x`是简单的线性回归模型公式。*ŷ* 是对于给定的 *x 的 *y* 的预测值*这是我们试图估计或预测的特征。所有的 *ŷ* 值都落在线性回归线上。β₀和β₁是回归系数。*   β₀称之为**拦截**。这是直线*与 y 轴*相交的地方,相当于 *x* =0 时 *y* 的预测值
*   β₁是输入特征 *x* 的**系数**,是直线的斜率。它表示 x 对 y 的影响。因此,线性回归模型假设如果 x 增加 1,y 增加β₁(这仅在 x 和 y 具有完美的线性关系时成立,这种情况很少发生)
*   β₀和β₁都是模型从数据集中学习到的*。**因此,当您*拟合*一个线性回归模型时,该模型的工作是根据您的数据集估计β₀和β₁的最佳值。**`ŷ=β₀+β₁x₁+β₂x₂+…+βₙxₙ`是有多个输入特征时的公式。 *ŷ* 是给定 *x 的 *y* 的预测值。* β₀、β₁、β₂和βₙ是回归系数,其中 *n* 是输入特征的个数。**一个线性回归模型(一个 *x* 和一个 *y* 特征)产生一个**二维线图**,易于显示。一个多元回归模型(几个 x 特征和一个 y 特征)产生一个更高维的线,称为 [**超平面**](https://datacadamia.com/data_mining/multiple_regression#equation_function) 。**线性回归模型也包括误差,称为残差。这些是 y 的真实值和 y 的预测值之间的*差*,或`y-ŷ.`**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/75457b578493232ffe73166ee1556fdd.png)**作者图片**线性回归模型通过找到“最佳拟合线”或这些误差最小的线来最小化这些误差。想一条最接近所有点的线。这涉及到最小化**误差平方和(SSE)** ,也称为**残差平方和(RSS)** ,一种称为[**普通最小二乘法**](https://en.wikipedia.org/wiki/Ordinary_least_squares) **的技术。**这项技术旨在最小化 RSS,这意味着当我们有一条穿过数据的线性回归线时,计算每个数据点到该线的距离,对其求平方,并将所有平方误差加在一起。最佳拟合线的 RSS 最小。**另一种在机器学习中常见的计算“最佳拟合线”的技术是 [**梯度下降**](https://www.geeksforgeeks.org/gradient-descent-in-linear-regression/) 。这包括通过从系数的随机值开始优化系数,然后在使误差平方和最小化的方向上逐渐更新它们。*## *使用 scikit-learn 在 Python 中实现线性回归**现在让我们来看看使用 [scikit-learn 数据集](https://scikit-learn.org/stable/datasets/toy_dataset.html#toy-datasets)的多元线性回归模型。你可以从[这个](https://github.com/suemnjeri/medium-articles/blob/main/Linear%20regression%20fundamentals/Linear%20Regression%20using%20boston%20dataset.ipynb) Github 链接下载代码并跟随。**Scikit-learn 附带了一些小的标准数据集,不需要您从一些外部网站下载任何文件。使用[波士顿房价数据集](https://scikit-learn.org/stable/datasets/toy_dataset.html#boston-house-prices-dataset),我们将实现一个多元线性回归模型,并通过计算 r 得分和均方误差来测量其性能,同时显示输入要素的截距(β₀)和β系数。您可以通过运行`print(df[‘DESCR’])`来查看波士顿住房数据集的描述。**如果您的机器上没有安装 python,请按照[这些](https://docs.anaconda.com/anaconda/install/)步骤下载并安装 **anaconda,**这是一个 python 环境平台。安装完成后,使用[这些](https://jupyter-notebook-beginner-guide.readthedocs.io/en/latest/execute.html)步骤打开一个新的 Jupyter 笔记本,我们将从这里运行我们的代码。**首先是导入您需要的库。其中包括常用的`pandas`、`numpy`、`matplotlib,`、`seaborn`。另外,从我们将要加载数据集的地方导入`linear regression`类和`datasets`类。*

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('darkgrid')from sklearn.linear_model import LinearRegression
from sklearn import datasets


*下一步是加载数据集。*

data = datasets.load_boston()


*预设特征名称将是我们的预测值,我们将把它存储在一个名为`features`的数据帧中,预测(目标)特征将是预设目标‘MEDV’,我们将把它存储在一个名为`target`的数据帧中。*

*features = pd.DataFrame(data.data, columns=data.feature_names)
target = pd.DataFrame(data.target, columns=["MEDV"])features.shape

Results

(506, 13)target.shape

Results

(506, 1)*


*下一步是*初始化*线性回归模型的实例,然后*使用`model.fit(features,target)`使*模型实例符合数据,也称为训练模型。这是得出β₀和β₁最佳估计值的一步。最后,我们将使用`model.predict(features).`进行预测:注意:我使用了所有 13 个特征来拟合模型并进行预测,但是如果您执行探索性数据分析(EDA)并总结出几个有用的特征,您可以使用更少的特征。请阅读我关于[基本 EDA 代码块](/11-simple-code-blocks-for-complete-exploratory-data-analysis-eda-67c2817f56cd?gi=4dd3ddfc57ae&source=collection_category---4------2-----------------------)的文章以获得指导。*

model = LinearRegression()
model.fit(features, target)
preds = model.predict(features)


*观察目标列“MEDV”的前 5 个值和前 5 个预测。**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/10774641267fbe3f1f1feee047cdc37e.png)**Sklearn 具有内置的函数,可以返回分数(r 分数)、系数(β₁,..,βₙ),和拦截(β₀).**`model.score(features,target)`返回模型的 R 分数,即模型预测的解释方差的百分比。它将当前模型与恒定基线进行比较,该基线是通过取数据的平均值并在平均值处画一条水平线来选择的。r 分数总是小于或等于 1,并且优选更高的值。高 R 也可能是由于过拟合,在这种情况下,可以计算出[调整后的 R](https://www.statisticshowto.com/adjusted-r2/) 。更多关于衍生的 R 分数[在这里。](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html#sklearn.linear_model.LinearRegression.score)*

model.score(features, target)###Results
0.7406426641094095


*我们还将计算均方差(MSE),它是实际目标值( *y* )和预测值( *ŷ)* 或`1/n(y-*ŷ)*²`)之间的*平方差*的*平均值*。这是一个很好的性能指标,因为对差异求平方会导致对较大误差的更大强调,从而表明模型的好坏。较小的 MSE 是优选的。为了计算 MSE,我们使用从`sklearn.metrics.`导入的`mean_squared_error`类*

from sklearn.metrics import mean_squared_error
print('MSE', mean_squared_error(target, preds))### Results
MSE 21.894831181729202


*我们可以使用`model.intercept_.`显示 y 截距(β₀),我们模型的 y 截距是 36.45948839,这是 x=0 时 y 的值。*

print(model.intercept_)### Results
[36.45948839]


*`model.coef_`显示各种输入特征的模型估计系数。它们是由模型在训练期间导出的。*

print(model.coef_)### Results
[[-1.08011358e-01 4.64204584e-02 2.05586264e-02 2.68673382e+00
-1.77666112e+01 3.80986521e+00 6.92224640e-04 -1.47556685e+00
3.06049479e-01 -1.23345939e-02 -9.52747232e-01 9.31168327e-03
-5.24758378e-01]]


***线性回归假设****线性回归在数据中做出假设,如果不符合假设,可能会导致模型不准确,预测不准确。这些是一些假设。**   *独立/预测变量是无误差的,不是随机变量。我们在上面讨论过,误差来自预测值 *ŷ* ,我们称之为残差。`e = y-ŷ.`然而,线性回归假设我们不期望单个输入/预测特征有任何误差。*
*   *线性。假设 x 和 y 特征具有线性关系,意味着当 x 增加(或减少)时,y 增加(或减少)。*
*   *特征呈正态分布。假设要素具有正态分布,高度倾斜的要素或具有显著异常值的要素会扭曲关系并导致模型不准确。*
*   *线性回归假设误差的大小与其他误差无关。*
*   *该模型假设不存在多重共线性,并且没有任何要素与其他要素存在冗余。*## *结论**在本文中,我们介绍了线性回归,这是使用输入特征 x₁,…,xₙ.预测响应特征 y 的常用回归模型之一我们研究了线性回归的基础知识,并使用 sklearn 的玩具数据集之一实现了一个多元线性回归模型。[这里的](https://github.com/suemnjeri/medium-articles/blob/main/Linear%20regression%20fundamentals/Linear%20Regression%20using%20boston%20dataset.ipynb)是 Github 上的完整代码。在实践中,重要的是将数据集分成训练集和测试集,并标准化/规范化特征以防止过度拟合。这是对 EDA、清理数据集、特征工程等其他数据准备最佳实践的补充。****参考文献****机器学习掌握—[https://machineellingmastery . com/linear-regression-for-machine-learning/](https://machinelearningmastery.com/linear-regression-for-machine-learning/)**Youtube: GeostatsGuy 讲座—[https://www.youtube.com/watch?v=0fzbyhWiP84](https://www.youtube.com/watch?v=0fzbyhWiP84)*# SQLite 中关系和连接的基础> 原文:<https://towardsdatascience.com/fundamentals-of-relationships-and-joins-in-sqlite-82ab47806d00?source=collection_archive---------32----------------------->## 使用 World 数据库的内、左、右和全外连接示例![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/91f975e6df6b777b069edd99e66e433e.png)在 [Unsplash](https://unsplash.com/s/photos/swans?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上由 [Belinda Fewings](https://unsplash.com/@bel2000a?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 拍摄的照片## 介绍结构化查询语言(SQL)是与关系数据库通信的标准编程语言,关系数据库以表格的形式组织相关数据。理解关系和连接的基础知识对于使用任何关系数据库管理系统都是必要的。本文使用[世界数据库](https://dev.mysql.com/doc/index-other.html)和 [SQLiteStudio](https://sqlitestudio.pl/) ,介绍 SQLite 中不同类型的关系和连接 SQLite 支持标准 SQL 的许多特性,但内存需求较低。世界数据库包含 3 个表:“城市”、“国家”和“国家语言”这些表都通过一个共享的国家代码变量相互关联,这允许跨三个表的数据被连接。让我们看看它是怎么做的!## 内部联接内部联接只返回查询中两个表都满足指定条件的数据。以下查询连接了 world 数据库中城市和国家表的数据。从城市表(别名为“ci”)中,我们选择名称列(重命名为“City”)和人口列(重命名为“City Pop”)。从 Country 表(别名为“co”)中,我们选择 Name 列(重命名为“Country”)。如果不重命名第一行中的列,我们将在返回的表中得到两个“Name”列和一个不明确的“Population”列,这可能会在涉及更多列的情况下造成混乱。为 SQL 查询中的每个不同列指定不同的名称是一个好习惯。“ON”子句指定两个表应该在哪些列上联接。在这种情况下,城市表中的“国家代码”值对应于国家表中的“代码”值。返回两列中具有匹配值的行。这是一个**多对一关系**的例子,它描述了一个表中的多行与另一个表中的一行匹配的情况。有多个城市与每个国家/地区相关联:例如,在下表中,孟买和德里这两个城市都与国家/地区表中的印度相关联。查询最后一行中的“WHERE”子句将行进一步限制为只包括人口值超过 600 万的城市。在返回的行中,我们有前 20 个人口最稠密的城市、它们的人口值和它们的国家:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/054582fdd862cf6caefd6cb0b360f367.png)按作者分类的表格## 左连接左连接返回左表中的所有行和右表中具有匹配值的行。为了可读性,查询通常被分成一系列的行,所以左边的表可能并不总是出现在右边的表的左边。例如,在下面的查询中,左边的表是 County,右边的表是 CountryLanguage。我们知道 Country 是左边的表,因为如果这个查询被安排在一行中,Country 将被放置在“JOIN”的左边。默认情况下,' ORDER BY '子句按预期寿命以升序对行进行排序。将“DESC”添加到第五行的末尾将会首先显示预期寿命最高的行。这里使用“LIMIT”关键字将结果限制为仅 20 行,使用“OFFSET”关键字删除原本会出现在结果中的前 15 行。如果所选列中的行数允许,这些关键字后面可以跟任何其他数字。以下是上述查询的结果:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cc9fd9ac917712f54b95c029367dbeee.png)按作者分类的表格我在查询中包含了 Code 和 CountryCode 列,以说明左连接的效果。请注意一些 CountryCode 值是'*NULL ';*这表示该列没有值。在内部联接中,CountryCode 和 Code 列没有匹配值的行将被排除。“LEFT”关键字确保返回左表(国家)中的所有值,即使右表(国家语言)中没有匹配的值。这是一个**一对一关系**的例子:Country 表中的每一行只与 CountryLanguage 表中的另一行相关联。## 右连接右连接返回右表中的所有行和左表中具有匹配值的所有行。SQLite 不支持' RIGHT JOIN '子句,但是通过更改查询中表的顺序,可以将任何右连接更改为左连接。例如,考虑下面的右连接:在 SQLite 中,使用左连接可以实现该查询中所需的相同效果:请注意,join 语句“左侧”的表已经更改为 CountryLanguage,而 Country 表现在出现在它的后面。切换表顺序是将右连接转换为左连接的全部步骤。最后一行使用' LIKE '关键字和一个通配符(' % ')来选择任何以字符串'君主制'结尾的值。在下面的输出行片段中,我们可以看到君主制和立宪君主制都被选中了:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f83a7d48c9d5690fdbb3933519f99e84.png)按作者分类的表格## 完全外部连接完全外部联接是左联接和右联接的组合。它包括从左表和右表中选择的所有行,并在没有匹配值的行中返回“NULL”值。SQLite 也不支持完全联接,但是可以使用“LEFT JOIN”和“UNION ALL”来重现它们的行为,如以下查询所示:该查询将第一个和第二个“SELECT”语句的结果与“UNION ALL”组合在一起假设外部连接是左连接和右连接的组合,并且 SQLite 不支持右连接,我们只需在第二个选择中颠倒表的顺序。该查询只选择人口值小于 1000 的小城市,并按洲按字母升序排列行。结果如下:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/64acbad9da13098c2cdb6857486b0e57.png)按作者分类的表格## 结论本文介绍了 SQLite 中一些基本连接和关系类型的例子,但是还有更多!查看 [SQLite 文档](https://www.sqlite.org/keyword_index.html)获取更多信息和资源。# 数据科学家和分析师的统计学基础> 原文:<https://towardsdatascience.com/fundamentals-of-statistics-for-data-scientists-and-data-analysts-69d93a05aae7?source=collection_archive---------0----------------------->## 数据科学或数据分析之旅的关键统计概念![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3d837e28f741cef15e30cf335d054a33.png)图片来源:[佩克斯/安娜·涅克拉舍维奇](https://www.pexels.com/photo/marketing-businessman-person-hands-6801647/)正如英国数学家卡尔·皮尔逊曾经说过的那样,**统计学**是科学的语法,尤其适用于计算机和信息科学、物理科学和生物科学。当你开始你的**数据科学**或**数据分析**之旅时,拥有统计知识将帮助你更好地利用数据洞察力。> "统计学是科学的语法。"**卡尔·皮尔逊**统计学在数据科学和数据分析中的重要性不可低估。统计学提供了工具和方法来发现结构并给出更深层次的数据见解。统计学和数学都热爱事实,讨厌猜测。了解这两个重要主题的基础知识将允许您进行批判性思考,并在使用数据解决业务问题和做出数据驱动的决策时具有创造性。在本文中,我将介绍数据科学和数据分析的以下统计主题:

**- Random variables

  • Probability distribution functions (PDFs)
  • Mean, Variance, Standard Deviation
  • Covariance and Correlation
  • Bayes Theorem
  • Linear Regression and Ordinary Least Squares (OLS)
  • Gauss-Markov Theorem
  • Parameter properties (Bias, Consistency, Efficiency)
  • Confidence intervals
  • Hypothesis testing
  • Statistical significance
  • Type I & Type II Errors
  • Statistical tests (Student's t-test, F-test)
  • p-value and its limitations
  • Inferential Statistics
  • Central Limit Theorem & Law of Large Numbers
  • Dimensionality reduction techniques (PCA, FA)**

如果你以前没有统计学知识,你想从头开始识别和学习基本的统计学概念,为你的工作面试做准备,那么这篇文章就是为你准备的。这篇文章也是任何想更新他/她的统计知识的人的好读物。# 随机变量随机变量的概念构成了许多统计概念的基石。可能很难理解其正式的数学定义,但简单地说,**随机变量**是一种将随机过程的结果映射到数字的方法,例如抛硬币或掷骰子。例如,我们可以用随机变量 X 来定义抛硬币的随机过程,如果结果是*正面*则取值 1,如果结果是*反面则取值 0。*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/60fb33982e6ce0725cdfda9a41c42722.png)在这个例子中,我们有一个抛硬币的随机过程,这个实验可以产生 ***两个*** ***可能的结果*** : {0,1}。这组所有可能的结果称为实验的 ***样本空间*** 。每次重复随机过程时,称为一个 ***事件。*** 在这个例子中,抛硬币得到一条尾巴作为结果是一个事件。这一事件以特定结果发生的几率或可能性称为该事件的 ***概率*** 。事件的概率是随机变量取 x 的特定值的可能性,可以用 P(x)来描述。在抛硬币的例子中,获得正面或反面的可能性是相同的,即 0.5%或 50%。因此,我们有以下设置:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f787fa37199930c834dd91a96bc68474.png)在本例中,事件的概率只能取[0,1]范围内的值。> 统计学在数据科学和数据分析中的重要性不可低估。统计学提供了工具和方法来发现结构并给出更深层次的数据见解。# 均值、方差、标准差为了理解均值、方差和许多其他统计主题的概念,学习 ***人口*** 和 ***样本*的概念是很重要的。*****总体*** 是所有观察值(个体、对象、事件或程序)的集合,通常非常大且多样,而 ***样本*** 是总体中观察值的子集,理想情况下是总体的真实代表。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/797118cbf3ae8a240f806077144db6fe.png)图片来源:作者鉴于对整个人群进行实验要么是不可能的,要么就是太昂贵,研究人员或分析师在他们的实验或试验中使用样本而不是整个人群。为了确保实验结果可靠并适用于整个群体,样本需要真实地代表总体。也就是说,样本需要是无偏的。为此,可以使用统计抽样技术,如[随机抽样、系统抽样、整群抽样、加权抽样和分层抽样。](https://github.com/TatevKaren/mathematics-statistics-for-data-science/tree/main/Sampling%20Techniques)## 平均均值,也称为平均值,是一组有限数字的中心值。让我们假设数据中的随机变量 X 具有以下值:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a5e8cec1a593947980f7c8f066f3decf.png)其中 N 是样本集中观察值或数据点的数量,或简称为数据频率。那么 ***样本均值*** 由 **μ** 定义,这非常常用于近似 ***总体均值*** *,*可表示如下:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1ad2e99479fc81f6152d7b92cbd4af4f.png)平均值也称为 ***期望*** ,通常由 **E** ()或顶部带横杠的随机变量定义。例如,随机变量 X 和 Y 的期望,即分别为 **E** (X)和 **E** (Y),可以表示如下:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4db687755f2022f31d622a20151f1242.png)

import numpy as np
import mathx = np.array([1,3,5,6])
mean_x = np.mean(x)# in case the data contains Nan values
x_nan = np.array([1,3,5,6, math.nan])
mean_x_nan = np.nanmean(x_nan)


## 差异方差测量数据点与平均值*、*相差多远,等于数据值与平均值(平均值)之差的平方和。再者, ***人口方差****可以表示如下:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8cc4e3d99c2bf70ebcf49b55486deaaa.png)*

x = np.array([1,3,5,6])
variance_x = np.var(x) # here you need to specify the degrees of freedom (df) max number of logically independent data points that have freedom to varyx_nan = np.array([1,3,5,6, math.nan])
mean_x_nan = np.nanvar(x_nan, ddof = 1)


*要获得不同流行概率分布函数的期望和方差,[查看 Github repo](https://github.com/TatevKaren/mathematics-statistics-for-data-science/tree/main/Deriving%20Expectation%20and%20Variances%20of%20Densities) 。*## *标准偏差**标准差就是方差的平方根,衡量数据偏离均值的程度。***∑****定义的标准偏差可以表示如下:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6e3bbe33757f9a5364f60c93e009ea2b.png)****标准差通常优于方差,因为它与数据点具有相同的单位,这意味着您可以更容易地解释它。**

**x = np.array([1,3,5,6])
variance_x = np.std(x)

x_nan = np.array([1,3,5,6, math.nan])
mean_x_nan = np.nanstd(x_nan, ddof = 1)**


## **协方差****协方差是两个随机变量的联合可变性的度量,描述了这两个变量之间的关系。它被定义为两个随机变量与其均值的偏差乘积的期望值。两个随机变量 X 和 Z 之间的协方差可以用下面的表达式来描述,其中 **E** (X)和 **E** (Z)分别代表 X 和 Z 的均值。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/56312fb811e722d4380a24750859402d.png)****协方差可以取负值或正值,也可以取值 0。协方差的正值表示两个随机变量趋向于同向变化,而负值表示这些变量反向变化。最后,值 0 意味着它们不一起变化。**

x = np.array([1,3,5,6])
y = np.array([-2,-4,-5,-6])#this will return the covariance matrix of x,y containing x_variance, y_variance on diagonal elements and covariance of x,y
cov_xy = np.cov(x,y)


## **相互关系****相关性也是对关系的度量,它度量两个变量之间线性关系的强度和方向。如果检测到相关性,则意味着在两个目标变量的值之间存在关系或模式。两个随机变量 X 和 Z 之间的相关性等于这两个变量之间的协方差除以这些变量的标准偏差的乘积,这可以由下面的表达式来描述。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0b3f005b5d2c6eae337c05af6492a7e7.png)****相关系数的值介于-1 和 1 之间。请记住,变量与其自身的相关性始终为 1,即 **Cor(X,X) = 1** 。在解释相关性时要记住的另一件事是不要将其与 ***因果关系*** 混淆,因为相关性不是因果关系。即使两个变量之间存在相关性,你也不能断定一个变量会引起另一个变量的变化。这种关系可能是巧合,或者第三个因素可能导致这两个变量发生变化。**

x = np.array([1,3,5,6])
y = np.array([-2,-4,-5,-6])corr = np.corrcoef(x,y)


# ****概率分布函数******描述所有可能值、样本空间和随机变量在给定范围内可能取的相应概率的函数,介于最小和最大可能值之间,称为 ***概率分布函数(pdf)*** 或概率密度。每个 pdf 都需要满足以下两个标准:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ea31b532ed33858bca4969673ef749e5.png)****其中第一个标准规定所有的概率应该是在[0,1]范围内的数字,第二个标准规定所有可能的概率之和应该等于 1。****概率函数通常分为两类: ***离散*** 和 ***连续*** 。离散分布函数用 ***可数*** 样本空间描述随机过程,就像在抛硬币的例子中,只有两种可能的结果。连续分布函数描述了随机过程与*连续的样本空间。离散分布函数的例子有[伯努利](https://en.wikipedia.org/wiki/Bernoulli_distribution)、[二项式](https://en.wikipedia.org/wiki/Binomial_distribution)、[泊松](https://en.wikipedia.org/wiki/Poisson_distribution)、[离散均匀](https://en.wikipedia.org/wiki/Discrete_uniform_distribution)。连续分布函数的例子有[正态](https://en.wikipedia.org/wiki/Normal_distribution)、[连续均匀](https://en.wikipedia.org/wiki/Continuous_uniform_distribution)、[柯西](https://en.wikipedia.org/wiki/Cauchy_distribution)。***## ***二项分布******[二项分布](https://brilliant.org/wiki/binomial-distribution/)是一系列 **n 个**独立实验中成功次数的离散概率分布,每个实验的结果为布尔值:*(概率为 **p** )或 ***失败*** (概率为**q**= 1p)。假设随机变量 X 遵循二项分布,那么在 n 次独立试验中观察到***k*** 成功的概率可以由下面的概率密度函数表示:******![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e193daa6333c73c1eaebb8fe4dda42d3.png)****当分析重复独立实验的结果时,二项式分布是有用的,特别是如果人们对在给定特定错误率的情况下满足特定阈值的概率感兴趣。******二项分布均值&方差******![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ab458651b75e2bb483a6d5e51bd75760.png)****下图显示了一个二项式分布的例子,其中独立试验的数量等于 8,每次试验的成功概率等于 16%。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ac4bfcede854d1ba125c9855a2a2fa24.png)****图片来源:作者**

# Random Generation of 1000 independent Binomial samples
import numpy as np
n = 8
p = 0.16
N = 1000
X = np.random.binomial(n,p,N)# Histogram of Binomial distribution
import matplotlib.pyplot as plt
counts, bins, ignored = plt.hist(X, 20, density = True, rwidth = 0.7, color = 'purple')
plt.title("Binomial distribution with p = 0.16 n = 8")
plt.xlabel("Number of successes")
plt.ylabel("Probability")
plt.show()


## **泊松分布****[泊松分布](https://brilliant.org/wiki/poisson-distribution/)是特定时间段内发生的事件数量的离散概率分布,给定该时间段内事件发生的平均次数。假设随机变量 X 服从泊松分布,那么在一段时间内观察到***k*** 事件的概率可以用下面的概率函数表示:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2119ef3873e68c2082ff4268106a1d7e.png)****其中 ***e*** 为 [***欧拉数***](https://brilliant.org/wiki/eulers-number/) 和***λ***λ, ***到达率参数*** 为*x 的期望值。泊松分布函数因其在对给定时间间隔内发生的可数事件建模中的用途而非常流行。********泊松分布均值&方差********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/552e43a1afc23e649337bce0ddd8728b.png)******例如,泊松分布可用于模拟晚上 7 点到 10 点之间到达商店的顾客数量,或者晚上 11 点到 12 点之间到达急诊室的患者数量。下图显示了泊松分布的一个示例,其中我们计算了到达网站的 Web 访问者的数量,到达率λ假定等于 7 分钟。******![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0172b3a36df54a0c82300cf02a20669a.png)******图片来源:作者***

***# Random Generation of 1000 independent Poisson samples
import numpy as np
lambda_ = 7
N = 1000
X = np.random.poisson(lambda_,N)

Histogram of Poisson distribution

import matplotlib.pyplot as plt
counts, bins, ignored = plt.hist(X, 50, density = True, color = 'purple')
plt.title("Randomly generating from Poisson Distribution with lambda = 7")
plt.xlabel("Number of visitors")
plt.ylabel("Probability")
plt.show()***


## ***正态分布******[正态概率分布](https://brilliant.org/wiki/normal-distribution/)是实值随机变量的连续概率分布。正态分布,也称为 ***高斯分布*** 可以说是社会科学和自然科学中最常用的分布函数之一,用于建模,例如,它用于对人的身高或考试成绩进行建模。假设随机变量 X 服从正态分布,那么它的概率密度函数可以表示如下。*****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cb39019b83d98ec302eaffeae47f0858.png)****其中参数**μ**(μ)**是分布的平均值,也称为 ***位置参数*** ,参数 **σ** (sigma) 是分布的标准偏差,也称为*比例参数*。数字 [**π**](https://www.mathsisfun.com/numbers/pi.html) (pi)是一个数学常数,大约等于 3.14。**********正态分布均值&方差**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a46f0def0098d23f90879136c09aca1f.png)********下图显示了一个均值为 0 ( **μ = 0** )标准差为 1 ( **σ = 1** )的正态分布示例,这被称为 ***标准正态*** 分布,它是*对称的。*********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/13e2dec2bcd12ae3059bd94225e54afa.png)********图片来源:作者****

****# Random Generation of 1000 independent Normal samples
import numpy as np
mu = 0
sigma = 1
N = 1000
X = np.random.normal(mu,sigma,N)

Population distribution

from scipy.stats import norm
x_values = np.arange(-5,5,0.01)
y_values = norm.pdf(x_values)#Sample histogram with Population distribution
import matplotlib.pyplot as plt
counts, bins, ignored = plt.hist(X, 30, density = True,color = 'purple',label = 'Sampling Distribution')
plt.plot(x_values,y_values, color = 'y',linewidth = 2.5,label = 'Population Distribution')
plt.title("Randomly generating 1000 obs from Normal distribution mu = 0 sigma = 1")
plt.ylabel("Probability")
plt.legend()
plt.show()****


# ******贝叶斯定理**********贝叶斯定理或通常称为 ***贝叶斯定律*** 可以说是概率统计中最强大的规则,以著名的英国统计学家和哲学家托马斯·贝叶斯的名字命名。********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ecf099fa99478160ae60f470fbabb5d0.png)********图片来源:[维基百科](https://en.wikipedia.org/wiki/Thomas_Bayes)********贝叶斯定理是一个强大的概率定律,它将 ***主观性*** 的概念带入了一切都与事实有关的统计和数学世界。它描述了一个事件发生的概率,基于可能与该事件相关的 ***条件*** 的先验信息。例如,如果已知患冠状病毒或新冠肺炎的风险会随着年龄的增长而增加,那么贝叶斯定理允许通过将年龄作为条件来更准确地确定已知年龄的个体的风险,而不是简单地假设该个体是整个人口中的常见个体。***********条件概率*,**的概念在贝叶斯理论中起着核心作用,它是一个事件发生的概率的度量,假设另一个事件已经发生。贝叶斯定理可以由下面的表达式描述,其中 X 和 Y 分别代表事件 X 和 Y:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9d5cea618a072361ae7c165a5034e1c5.png)*****   ****Pr (X|Y):给定事件或条件 Y 已经发生或为真,事件 X 发生的概率****
*   ****Pr (Y|X):给定事件或条件 X 已经发生或为真,事件 Y 发生的概率****
*   *****Pr*(X)&*Pr*(Y):分别为观察事件 X 和 Y 的概率********在前面的例子中,以在某个年龄为条件的获得冠状病毒(事件 X)的概率是 *Pr* (X|Y),它等于给定一个人在某个年龄获得冠状病毒的概率, *Pr* (Y|X),乘以获得冠状病毒的概率, *Pr* (X),除以在某个年龄的概率。, *Pr* (Y)。****# ****线性回归********早些时候,变量之间的因果关系的概念被引入,这发生在一个变量对另一个变量有直接影响的时候。当两个变量之间的关系是线性时,那么线性回归是一种统计方法,可以帮助建模一个变量中单位变化的影响,****自变量*** , ***因变量*** 。*********因变量常被称为 ***反应变量*** 或 ***解释变量****而自变量常被称为 ***回归变量*** 或 ***解释变量*** 。当线性回归模型基于单个自变量时,则该模型称为 ***简单线性回归*** ,当模型基于多个自变量时,则称为 ***多元线性回归*。**简单的线性回归可以用下面的表达式来描述:*********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/afe697f64175be3da20e56b1120ee977.png)********其中 **Y** 为因变量, **X** 为自变量,为数据的一部分, **β0** 为未知常数的截距, **β1** 为斜率或未知常数的变量 X 对应的参数。最后, **u** 是模型在估计 Y 值时产生的误差项。线性回归背后的主要思想是通过一组成对的(X,Y)数据找到最拟合的直线, ***回归线,*** 。线性回归应用的一个例子是模拟*鳍状肢长度*对企鹅*体重*的影响,如下图所示。********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2cb648d6af35f0b4dbd3c6eba39d83e8.png)********图片来源:作者****

# R code for the graph
install.packages("ggplot2")
install.packages("palmerpenguins")
library(palmerpenguins)
library(ggplot2)View(data(penguins))ggplot(data = penguins, aes(x = flipper_length_mm,y = body_mass_g))+
geom_smooth(method = "lm", se = FALSE, color = 'purple')+
geom_point()+
labs(x="Flipper Length (mm)",y="Body Mass (g)")


****具有三个独立变量的多元线性回归可由以下表达式描述:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/980bd41a342eddfb4000979d94db7d48.png)****## ****普通最小二乘法********普通最小二乘法(OLS)是一种估计线性回归模型中β0 和β1 等未知参数的方法。该模型基于 ***最小二乘*** 的原理,即使观察到的因变量与其由自变量的线性函数预测的值之差的平方和最小化,通常称为 ***【拟合值】*** 。因变量 Y 的实际值和预测值之间的差异被称为 ***残差*** ,OLS 所做的是最小化残差平方和。这个优化问题导致未知参数β0 和β1 的以下 OLS 估计,也称为 ***系数估计*** 。********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/999c493c5db71d57bf481243e7171c42.png)********一旦简单线性回归模型的这些参数被估计,响应变量的 ***拟合值*** 可以计算如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6fd1bc42b02d5ba485b8cff3d4c523ed.png)****## ****标准误差***********残差*** 或估计误差项可确定如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6df001944c63c263ca6b9a0efc02a891.png)********记住误差项和残差之间的区别很重要。误差项永远不会被观察到,而残差是从数据中计算出来的。OLS 估计每个观测值的误差项,但不是实际的误差项。因此,真正的误差方差仍然未知。此外,这些估计受抽样不确定性的影响。这意味着我们将永远无法从经验应用的样本数据中确定这些参数的准确估计值和真实值。但是我们可以通过计算 ***样本*** ***残差方差*** 来估计,使用的残差如下。********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4ce93be44d95d6f8506fa080bbfb2162.png)********样本残差方差的这种估计有助于估计估计参数的方差,估计参数的方差通常表示如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7289dd3f6d1bac1148fc8c6817077c60.png)********这个方差项的平方根被称为**估计值的标准误差**,这是评估参数估计值准确性的关键部分。它用于计算测试统计和置信区间。标准误差可以表示如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5232b62aa312d75c7c673ceba1e8bac4.png)****> ****记住误差项和残差之间的区别很重要。误差项永远不会被观察到,而残差是从数据中计算出来的。****## ****OLS 假设********OLS 估计法作出如下假设,需要满足这些假设才能得到可靠的预测结果:**********A1:线性**假设模型的参数是线性的。**********A2:** **随机** **样本**假设样本中的所有观测值都是随机选取的。**********A3:外生性**假设独立变量与误差项不相关。**********A4:同方差**假设所有误差项的方差为常数。**********A5:没有完美的多重共线性**假设没有一个自变量是恒定的,自变量之间没有精确的线性关系。****

**def runOLS(Y,X):

OLS esyimation Y = Xb + e --> beta_hat = (X'X)^-1(X'Y)

beta_hat = np.dot(np.linalg.inv(np.dot(np.transpose(X), X)), np.dot(np.transpose(X), Y))

OLS prediction

Y_hat = np.dot(X,beta_hat)
residuals = Y-Y_hat
RSS = np.sum(np.square(residuals))
sigma_squared_hat = RSS/(N-2)
TSS = np.sum(np.square(Y-np.repeat(Y.mean(),len(Y))))
MSE = sigma_squared_hat
RMSE = np.sqrt(MSE)
R_squared = (TSS-RSS)/TSS

Standard error of estimates:square root of estimate's variance

var_beta_hat = np.linalg.inv(np.dot(np.transpose(X),X))*sigma_squared_hat

SE = []
t_stats = []
p_values = []
CI_s = []

for i in range(len(beta)):
#standard errors
SE_i = np.sqrt(var_beta_hat[i,i])
SE.append(np.round(SE_i,3))

    #t-statisticst_stat = np.round(beta_hat[i,0]/SE_i,3)t_stats.append(t_stat)#p-value of t-stat p[|t_stat| >= t-treshhold two sided] p_value = t.sf(np.abs(t_stat),N-2) * 2p_values.append(np.round(p_value,3))#Confidence intervals = beta_hat -+ margin_of_errort_critical = t.ppf(q =1-0.05/2, df = N-2)margin_of_error = t_critical*SE_iCI = [np.round(beta_hat[i,0]-margin_of_error,3), np.round(beta_hat[i,0]+margin_of_error,3)]CI_s.append(CI) return(beta_hat, SE, t_stats, p_values,CI_s, MSE, RMSE, R_squared)**

# ****参数属性****> ****在满足 OLS 准则 A1 — A5 的假设下,系数β0 和β1 的 OLS 估计量为**蓝色**和**一致**。****
> 
> ******高斯-马尔可夫定理**********这个定理突出了 OLS 估计的性质,其中术语*代表 ***最佳线性无偏估计量*** 。*****## ******偏差**********估计量的**偏差**是其期望值和被估计参数的真实值之间的差值,可以表示如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8409a7b205ff9698fc1b499bb51cd383.png)********当我们声明估计量是 ***无偏的*** 时,我们的意思是偏倚等于零,这就暗示了估计量的期望值等于真实参数值,即:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3dd86e83777d49238dd680cc860a1124.png)********无偏性不能保证任何特定样本的估计值等于或接近β。这意味着,如果一个 ***重复*** 从总体中抽取随机样本,然后每次都计算估计值,那么这些估计值的平均值将等于或非常接近β。****## ****效率********高斯-马尔可夫定理中的术语*与估计量的方差有关,称为 ***效率*** *。*一个参数可以有多个估计值,但是方差最小的那个被称为有效的**。*******## ****一致性********术语一致性与术语 ***样本量*** 和 ***收敛*** 密切相关。如果当样本量变得很大时,估计量收敛于真实参数,则称该估计量是一致的,即:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c49e28207d2893ddbd4c663d2941120f.png)****> ****在满足 OLS 准则 A1 — A5 的假设下,系数β0 和β1 的 OLS 估计量是**蓝色**和**一致**。****
> 
> ******高斯-马尔科夫定理**********所有这些性质都适用于 OLS 估计,正如高斯-马尔可夫定理所总结的那样。换句话说,OLS 估计具有最小的方差,它们是无偏的,参数是线性的,并且是一致的。这些性质可以通过使用先前的 OLS 假设在数学上得到证明。****# ****置信区间********置信区间是包含具有某个预先指定的概率的真实总体参数的范围,称为实验的**,它是利用样本结果和 ***误差*** 得到的。******## ******误差幅度**********误差幅度是样本结果之间的差异,基于如果使用整个人口的结果。****## ****可信度********置信水平描述了实验结果的确定性水平。例如,95%的置信水平意味着,如果一个人重复进行 100 次相同的实验,那么这 100 次实验中的 95 次会产生相似的结果。请注意,置信水平是在实验开始之前定义的,因为它会影响实验结束时的误差幅度。****## ****OLS 估计的置信区间********如前所述,简单线性回归的 OLS 估计值、截距β0 和斜率β1 的估计值会受到采样不确定性的影响。但是,我们可以为这些参数构建 CI 的,它将包含所有样本中 95%的这些参数的真实值。也就是说,β的 95%置信区间可以解释如下:*****   ****置信区间是假设检验不能被拒绝到 5%水平的一组值。****
*   ****置信区间有 95%的机会包含β的真值。********OLS 估计值的 95%置信区间可构建如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/37c7c5c1afde362538eb597d1d775711.png)********其基于参数估计、该估计的标准误差以及表示对应于 5%拒绝规则的误差容限的值 1.96。该值使用[正态分布表](https://www.google.com/url?sa=i&url=https%3A%2F%2Ffreakonometrics.hypotheses.org%2F9404&psig=AOvVaw2IcJrhGrWbt9504WTCWBwW&ust=1618940099743000&source=images&cd=vfe&ved=0CAIQjRxqFwoTCOjR4v7rivACFQAAAAAdAAAAABAI)确定,这将在本文后面讨论。同时,下图说明了 95% CI 的概念:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/88c14e2699226ebd2e020153e5368627.png)********图片来源:[维基百科](https://en.wikipedia.org/wiki/Standard_deviation#/media/File:Standard_deviation_diagram.svg)********请注意,置信区间也取决于样本大小,因为它是使用基于样本大小的标准误差计算的。****> ****置信水平是在实验开始之前定义的,因为它会影响实验结束时的误差幅度有多大。****# ****统计假设检验********检验统计学中的假设是检验实验或调查结果的一种方法,以确定这些结果有多大意义。基本上,一个是通过计算结果偶然发生的几率来测试获得的结果是否有效。如果是信,那么结果不可靠,实验也不可靠。假设检验是 ***统计推断*** 的一部分。****## ****无效假设和替代假设********首先,你需要确定你想要测试的论题,然后你需要制定 ***零假设*** 和 ***替代假设*。**测试可能有两种结果,根据统计结果,您可以拒绝或接受所述假设。根据经验,统计学家倾向于将假设的版本或表述放在需要拒绝的无效假设**下,而可接受的和期望的版本则放在替代假设*下。*******## ****统计显著性********让我们看看前面提到的例子,线性回归模型被用来调查企鹅的*鳍长*(自变量)是否对*(因变量*的体重有影响。我们可以用下面的统计表达式来建立这个模型:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3387a9e5c1bd6cf765cc8ea03f8a479b.png)********然后,一旦估计了系数的 OLS 估计,我们可以制定以下无效和替代假设来测试鳍状肢长度是否对身体质量具有 ***统计显著性*** 影响:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d080b0c627ab84d771dd7b4e16984394.png)********其中 H0 和 H1 分别代表零假设和备择假设。拒绝零假设意味着*鳍状肢长度*增加一个单位会对*体重*产生直接影响。假设β1 的参数估计值描述了自变量*脚蹼长度*对因变量*身体质量的影响。*这个假设可以重新表述如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/faa865b19653066ebaea3d5498776d04.png)********其中 H0 陈述β1 的参数估计等于 0,即*鳍长*对*体质量*的影响 ***统计上不显著*** 而H0 陈述β1 的参数估计不等于 0,暗示*鳍长*对*体质量*的影响 ***统计上显著*** *。*****## ****第一类和第二类错误********在进行统计假设检验时,需要考虑两种概念上的错误:第一类错误和第二类错误。当零假设被错误地拒绝时,出现类型 I 错误,而当零假设没有被错误地拒绝时,出现类型 II 错误。混淆矩阵有助于清楚地显示这两种错误的严重程度。****> ****根据经验,统计学家倾向于将假设版本放在需要拒绝的***无效假设下,而可接受的和期望的版本放在*备选假设下。********# *****统计测试**********一旦陈述了无效假设和替代假设,并定义了测试假设,下一步就是确定哪个统计测试是合适的,并计算***测试统计量*** 。通过将测试统计量与 ***临界值*进行比较,可以确定是否拒绝空值。**该比较显示观察到的测试统计值是否比定义的临界值更极端,它可能有两种结果:******   *****检验统计量比临界值更极端→可以拒绝零假设*****
*   *****检验统计量不像临界值那样极端→不能拒绝零假设**********临界值基于预先指定的 ***显著性水平* α** (通常选择等于 5%)和检验统计遵循的概率分布类型。临界值将该概率分布曲线下的面积分为 ***拒绝区域*** 和 ***非拒绝区域*** 。有许多统计测试用来测试各种假设。统计检验的例子有[学生 t 检验](https://en.wikipedia.org/wiki/Student%27s_t-test)、 [F 检验](https://en.wikipedia.org/wiki/F-test)、[卡方检验](https://en.wikipedia.org/wiki/Chi-squared_test)、[德宾-豪斯曼-吴内生性检验](https://www.stata.com/support/faqs/statistics/durbin-wu-hausman-test/)、W [海特异方差检验](https://en.wikipedia.org/wiki/White_test#:~:text=In%20statistics%2C%20the%20White%20test,by%20Halbert%20White%20in%201980.)。在本文中,我们将研究其中的两个统计测试。*****> *****当零假设被错误地拒绝时,出现类型 I 错误,而当零假设没有被错误地拒绝时,出现类型 II 错误。*****## *****“学生”t 检验**********最简单也是最受欢迎的统计测试之一是学生的 t 检验。其可用于测试各种假设,尤其是在处理主要关注领域是寻找单变量**的统计显著效果的证据的假设时。*t 检验的检验统计量遵循 [***学生的 t 分布***](https://en.wikipedia.org/wiki/Student%27s_t-distribution) ,可以确定如下:***********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/dea30078bcd99a1b341a1be943860de1.png)**********其中,指定器中的 h0 是参数估计值的测试值。因此,t 检验统计量等于参数估计值减去假设值除以系数估计值的标准误差。在早先陈述的假设中,我们想测试鳍状肢的长度是否对体重有统计学上的显著影响。该测试可以使用 t-test 来执行,并且在这种情况下,h0 等于 0,因为斜率估计是针对值 0 来测试的。**********t 检验有两个版本:一个 ***双边 t 检验*** 和一个 ***单边 t 检验*** 。你是需要前一个版本的测试还是后一个版本的测试,完全取决于你想要测试的假设。**********双边或*双尾 t 检验* 可用于假设检验无效和替代假设下*等于*与*不等于*的关系,类似于下例:**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b7dc5995f73648d77cdba8e6564a6681.png)**********双边 t 检验有两个拒绝区域*,如下图所示:************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ca46e98ed0aabadcea7280edbbefea1e.png)************图片来源: [*Hartmann,k .,Krois,j .,Waske,b .(2018):SOGA 电子学习项目:统计和地理空间数据分析。柏林自由大学地球科学系*](https://www.geo.fu-berlin.de/en/v/soga/Basics-of-statistics/Hypothesis-Tests/Introduction-to-Hypothesis-Testing/Critical-Value-and-the-p-Value-Approach/index.html)***********在这个版本的 t-检验中,如果计算的 t-统计量太小或太大,则拒绝空值。**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7d63cfe3bf7c5181e8d87de237fcca7e.png)**********这里,根据样本大小和选定的显著性水平,将测试统计数据与临界值进行比较。为了确定分界点的精确值,可以使用双边 t 分布表。**********当假设在检验零假设和备选假设下的*正/负*对*负/正*关系时,可以使用单侧或 ***单尾 t 检验*** ,类似于下面的例子:**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2962c24e85789d35c3d5f97b42fe9a57.png)**********单侧 t 检验有一个 ***单个*** ***拒绝区域*** 和依赖在假设侧,拒绝区域要么在左侧,要么在右侧,如下图所示:**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0561ae3cb3e0a4d25bbddddc0a2ed0d5.png)**********图片来源: [*Hartmann,k .,Krois,j .,Waske,b .(2018):SOGA 电子学习项目:统计和地理空间数据分析。柏林自由大学地球科学系*](https://www.geo.fu-berlin.de/en/v/soga/Basics-of-statistics/Hypothesis-Tests/Introduction-to-Hypothesis-Testing/Critical-Value-and-the-p-Value-Approach/index.html)**********在这个版本的 t 检验中,如果计算出的 t 统计值小于/大于临界值,则拒绝空值。**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2bbd24116f8ef68e2c9e24ff8c5c8e2b.png)*****## *****f 检验**********f 检验是另一种非常流行的统计检验,常用于检验假设检验****多个变量的联合统计显著性*** *。*当您想要测试多个自变量是否对因变量有显著的统计影响时,就是这种情况。下面是一个可以使用 f 检验进行检验的统计假设示例:***********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b21fafa03ae13e6c95eb1befd8e8a999.png)**********其中零表示对应于这些系数的三个变量在统计上联合不显著,而备选项表示这三个变量在统计上联合显著。f 检验的检验统计量遵循 [F 分布](https://en.wikipedia.org/wiki/F-distribution),可确定如下:**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8dd52ce0a63393ed1ef3d2aa2e3442b2.png)**********其中,SSRunrestricted 为*******受限* *模型*** 的残差平方和,该模型与从数据中排除了在空值*下声明为无关紧要的目标变量的模型相同,SSRunrestricted 为****模型**** *的残差平方和 q 代表在空值下联合检验显著性的变量数量,N 是样本大小,k 是无限制模型中的变量总数。 运行 OLS 回归后,在参数估计值旁边提供 SSR 值,这同样适用于 F 统计。以下是 MLR 模型输出的示例,其中标记了 SSR 和 F 统计值。***************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/75ba2cadb5d53da36a50f4c884df6923.png)********图片来源:[股票和 Whatson](https://www.uio.no/studier/emner/sv/oekonomi/ECON4150/v18/lecture7_ols_multiple_regressors_hypothesis_tests.pdf)********f 检验有**一个单一剔除区域**,如下图所示:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/eb4f13bb1e5ae619b8ff7cc142a76581.png)********图片来源: [*密歇根大学*](https://www.statisticshowto.com/probability-and-statistics/f-statistic-value-test/)********如果计算出的 F-统计量大于临界值,则可以剔除空值,这表明独立变量共同具有统计显著性。拒绝规则可以表示如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/28f758c0a65e4ee5ef04b93799e68c5e.png)****# ****p 值********另一种快速确定是拒绝还是支持零假设的方法是使用 ***p 值*** 。p 值是零发生条件下的概率。换句话说,假设零假设为真,p 值是观察到至少与检验统计量一样极端的结果的概率。p 值越小,反对零假设的证据越强,表明它可以被拒绝。********对 *p* 值的解释取决于所选的显著性水平。通常,1%、5%或 10%的显著性水平用于解释 p 值。因此,这些检验统计的 p 值可以用来检验相同的假设,而不是使用 t-检验和 F-检验。********下图显示了具有两个独立变量的 OLS 回归的输出示例。在此表中,t 检验的 p 值(测试 *class_size* 变量参数估计的统计显著性)和 F 检验的 p 值(测试 *class_size、*和 *el_pct* 变量参数估计的联合统计显著性)带有下划线。********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0d01ee97736e887433bd996022ee5007.png)********图片来源:[股票和 Whatson](https://www.uio.no/studier/emner/sv/oekonomi/ECON4150/v18/lecture7_ols_multiple_regressors_hypothesis_tests.pdf)********对应于 *class_size* 变量的 p 值为 0.011,当将该值与 1%或 0.01、5%或 0.05、10%或 0.1 的显著性水平进行比较时,可以得出以下结论:*****   ****0.011 > 0.01 →在 1%的显著性水平上不能拒绝 t 检验的空值****
*   ****0.011 < 0.05 → Null of the t-test can be rejected at 5% significance level****
*   ****0.011 < 0.10 →Null of the t-test can be rejected at 10% significance level********So, this p-value suggests that the coefficient of the *class_size* 变量在 5%和 10%的显著性水平上具有统计显著性。对应于 f 检验的 p 值为 0.0000,因为 0 小于所有三个截止值;0.01,0.05,0.10,我们可以得出结论,在所有三种情况下都可以拒绝 f 检验的零。这表明 *class_size* 和 *el_pct* 变量的系数在 1%、5%和 10%的显著性水平上共同具有统计显著性。****## ****p 值的限制********虽然使用 p 值有很多好处,但它也有局限性**。**也就是说,p 值取决于关联的大小和样本量。如果影响的幅度很小并且在统计上不显著,p 值可能仍然显示出 ***显著影响*** ,因为大样本量很大。也可能出现相反的情况,影响可能很大,但如果样本量很小,则无法满足 p < 0.01、0.05 或 0.10 的标准。****# ****推断统计学********推断统计学使用样本数据对样本数据来源的总体做出合理的判断。它用于调查样本中变量之间的关系,并预测这些变量将如何与更大的总体相关。***********大数定律(LLN)*** 和 ***中心极限定理(CLM)*** 在推断统计学中都有重要作用,因为它们表明,当数据足够大时,无论原始人口分布是什么形状,实验结果都成立。收集的数据越多,统计推断就变得越准确,因此,产生的参数估计就越准确。****## ******大数定律(LLN)**********假设 **X1,X2,。。。,Xn** 都是具有相同基础分布的独立随机变量,也称为独立同分布或 i.i.d .,其中所有 X 都具有相同的均值 **μ** 和标准差 **σ** 。随着样本量的增加,所有 X 的平均值等于均值μ的概率等于 1。大数定律可以总结如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/36f7e0fe1d8a288efd7d3c226c68bbcd.png)****## ****中心极限定理(CLM)********假设 **X1,X2,。。。,Xn** 都是具有相同基础分布的独立随机变量,也称为独立同分布或 i.i.d .,其中所有 X 都具有相同的均值 **μ** 和标准差 **σ** 。随着样本量的增长,X ***的概率分布收敛于均值 **μ** 和方差 **σ-** 平方的正态分布*** 。中心极限定理可以概括如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e7fe092d5b6a2e5f033d6255f78e1990.png)********换句话说,当您有一个具有均值μ和标准差σ的总体,并且您从该总体中选取足够大的随机样本进行替换时,样本均值的分布将近似为正态分布。****# ******降维技术**********降维是将数据从一个 ***高维空间*** 转换到一个 ***低维空间*** ,使得数据的这种低维表示仍然尽可能地包含原始数据的有意义的属性。********随着大数据越来越受欢迎,对这些降维技术(减少不必要的数据和特征的数量)的需求也在增加。流行的降维技术的例子有[主成分分析](https://builtin.com/data-science/step-step-explanation-principal-component-analysis)、[因子分析](https://en.wikipedia.org/wiki/Factor_analysis)、[典型相关](https://en.wikipedia.org/wiki/Canonical_correlation)、[随机森林](/understanding-random-forest-58381e0602d2)。****## ******主成分分析**********主成分分析(PCA)是一种降维技术,通常用于降低大型数据集的维数,方法是将一组大型变量转换为一个较小的集合,该集合仍然包含原始大型数据集中的大部分信息或变化。********假设我们有一个有 p 个变量的数据 X;X1,X2,…、Xp 带 ***特征向量*** e1、…、ep、 ***特征值*** λ1、…、λp 特征值表示总方差中某一特定数据字段所解释的方差 PCA 背后的思想是创建新的(独立的)变量,称为主成分,是现有变量的线性组合。第 i *个*主分量可以表示如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7c38d61662af7df63410a8ac10c4cf9b.png)********然后使用**肘规则**或[或**凯泽规则**或](https://docs.displayr.com/wiki/Kaiser_Rule)就可以确定最优概括数据的主成分个数而不会丢失太多信息。还要看***【PRTV】***每一个主成分所解释的总变异的比例来决定是包含还是排除它是有益的。第 i *个*主分量的 PRTV 可以使用特征值计算如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b2ae7144e60f8ebf2eba7287a75e5339.png)****## ****肘尺********肘规则或肘方法是一种启发式方法,用于从 PCA 结果中确定最佳主成分的数量。这种方法背后的思想是将所解释的变化绘制为组件数量的函数*,并选择曲线的拐点作为最佳主组件的数量。以下是此类散点图的示例,其中 PRTV (Y 轴)绘制在主成分数(X 轴)上。肘对应于 X 轴值 2,这表明最佳主成分的数量是 2。*********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1d87a7bb5174bbceb05514a8493e6df7.png)********图片来源:[多元统计 Github](https://raw.githubusercontent.com/TatevKaren/Multivariate-Statistics/main/Elbow_rule_%25varc_explained.png)****## ******因子分析**********因子分析是另一种降维的统计方法。这是最常用的相互依赖技术之一,当相关变量集显示系统的相互依赖时使用,目标是找出产生共性的潜在因素。假设我们有一个有 p 个变量的数据 X;X1,X2,…,Xp。FA 模型可以表示如下:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1ecbabe06fe6ca61dd23776001651515.png)********其中 X 是 p 个变量和 N 个观察值的[p x N]矩阵,是[p x N]总体均值矩阵,A 是[p x k]公共 ***因子加载矩阵*** ,F [k x N]是公共因子矩阵,u [pxN]是特定因子矩阵。因此,换句话说,因子模型是一系列的多元回归,从不可观察的公共因子 fi 的值预测每个变量 Xi:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2bcb27214fcb107313ee08f36c8c9070.png)********每个变量都有 k 个自己的公因子,这些公因子通过因子加载矩阵与单个观察值相关联,如下:在因子分析中,计算 ***因子*** 以使 ***最大化* *组间方差*** 而 ***最小化组内方差*** *e* 。它们之所以是因素,是因为它们将潜在的变量组合在一起。与 PCA 不同,FA 中的数据需要归一化,因为 FA 假设数据集遵循正态分布。****# ****额外资源********<https://github.com/TatevKaren>  **Github 仓库进行 A/B 测试:** [此处](https://github.com/TatevKaren/data-science-popular-algorithms/tree/main/AB_Testing)**** # ****如果你喜欢这篇文章,这里有一些你可能喜欢的其他文章:********<https://tatev-aslanyan.medium.com/bias-variance-trade-off-in-machine-learning-7f885355e847>  <https://tatev-aslanyan.medium.com/data-sampling-methods-in-python-a4400628ea1b>  </simple-and-complet-guide-to-a-b-testing-c34154d0ce5a>  </monte-carlo-simulation-and-variants-with-python-43e3e7c59e1f>  <https://medium.com/analytics-vidhya/pyspark-cheat-sheet-big-data-analytics-161a8e1f6185>  <https://medium.com/mlearning-ai/using-customer-and-product-features-in-recommender-systems-2734258873cf>  # 调查:完美的数据科学课程对你来说是什么样的?*你是否也注意到,作为数据科学家,我们很难浏览多个博客和课程,即使在这种情况下,也没有一个地方涵盖所有主题。所以,我愿意为您打造这个* ***【一站式数据科学店】*** *课程。**为了为您定制本课程,我很想了解您的意见,以了解“完美的数据科学课程对您来说是什么样的?”。**因此,我想请您回答几个问题来完成这个* [***简短调查***](https://docs.google.com/forms/d/e/1FAIpQLSeRxugd3ACiD1wsC8H3y8Y29L4sk2fdysw1lxzGNedL5sPqUw/viewform)**,一旦课程开始,您将是第一个收到通知的人。也请* [***与你认为会对此课程感兴趣的人分享***](https://docs.google.com/forms/d/e/1FAIpQLSeRxugd3ACiD1wsC8H3y8Y29L4sk2fdysw1lxzGNedL5sPqUw/viewform) *?***预先感谢您,非常感谢您的参与!*****为调查链接:*** [***点击此处***](https://docs.google.com/forms/d/e/1FAIpQLSeRxugd3ACiD1wsC8H3y8Y29L4sk2fdysw1lxzGNedL5sPqUw/viewform)*****感谢阅读******我鼓励你* [***加入 Medium today***](https://tatev-aslanyan.medium.com/membership) *以拥有* *完整访问所有跨媒体发布的伟大锁定内容,并在我的 feed 上发布关于各种数据科学、机器学习和深度学习主题的内容。****关注我* [***中***](https://medium.com/@tatev-aslanyan)**阅读更多关于各种数据科学和数据分析主题的文章。更多机器学习的动手应用,数学和统计概念查看我的*[***Github***](https://github.com/TatevKaren)**账号。
我欢迎反馈,可以联系*[***LinkedIn***](https://www.linkedin.com/in/tatev-karen-aslanyan/)*。*********快乐学习!*********# 使用 SQL: MATCH_RECOGNIZE()对雪花进行漏斗分析> 原文:<https://towardsdatascience.com/funnel-analytics-with-sql-match-recognize-on-snowflake-8bd576d9b7b1?source=collection_archive---------4----------------------->## SQL 是一个很棒的工具,但是它不能做所有的事情。例如,找出一种用 SQL 分析漏斗和会话的方法确实很困难——直到现在。让我们通过用雪花分析一个 Google Analytics 电子商务漏斗来发现 MATCH_RECOGNIZE()的强大之处。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/17a18fd641a46e612bc4e93bd18d82f1.png)图片: [Pixabay](https://pixabay.com/photos/architecture-buildings-cars-city-1837176/)当 TJ 墨菲发现雪花现在支持`MATCH_RECOGNIZE`时,看看他的反应:# 样本用例:带有雪花的谷歌分析电子商务漏斗## **你会如何用 SQL:** 回答这个漏斗问题> “我们有一个电子商务商店。我们需要识别从任意推荐人(Instagram、脸书等)进入网站并最终购买了某些东西的会话。这些用户买东西经历了多少步,尝试了多少次支付才成功?”用普通的 SQL 回答这个问题并不容易。但是`MATCH_RECOGNIZE`最终给了我们一种优雅的方式来寻找像这样问题的答案。使用`MATCH_RECOGNIZE`,我们可以简单地定义我们想要在一系列事件中找到的步骤,然后我们可以为这些步骤定义任何模式——然后`MATCH_RECOGNIZE`完成剩下的工作。在这个例子中,我们将使用来自电子商务商店的 Google Analytics 360 数据集。没有什么比真实数据更能证明我们工具的威力了。## 步骤 1:将谷歌分析数据加载到雪花中将数据从 BigQuery 取出放入 Snowflake 很容易。您可能需要工具来构建可靠的管道,但基本步骤很简单:*   从 BigQuery 导出到 GCS:您可以使用自己的 GA 数据,或者一个包含来自 Google 商品商店的数据的[样本数据集](https://support.google.com/analytics/answer/7586738?hl=en)。
*   [将 GA 数据加载到雪花中](https://stackoverflow.com/a/64168195/132438):这很简单。雪花会很乐意从 GCS 摄取文件,即使你的雪花账户住在 AWS。加载 JSON 也像变魔术一样。您可能希望设置身份验证和权限以获得最大的安全性,而对于示例数据,我只使用了一个 public bucket。

create or replace table ga_demo2(src variant);copy into ga_demo2
from 'gcs://fhoffa/ga360/ga_sessions000000000000'
file_format=(type='JSON');


*   雪花中的查询:注意上面我们将 JSON 行加载到了一个`variant`类型中。雪花使处理半结构化数据成为一种乐趣;你可以很容易地浏览谷歌分析模式。我们还可以在基本查询之外创建一个视图,以便更容易地执行以下所有步骤:

create or replace view ga360_parsed
as
select src:visitStartTime::timestamp ts
, hit.value:hitNumber::int hit
, src:visitId::string visit
, hit.value:eCommerceAction.action_type::int action_t
, hit.value:eCommerceAction.step::int action_s
, hit.value:eCommerceAction.option::string action_o
, hit.value:page.pagePath::string path
, hit.value:referer::string referer
, src:fullVisitorId::string visitor
, src:totals.transactions::int total_transactions
from ga_demo2, lateral flatten(input => src:hits) hit


## 第二步:查询漏斗很有趣这个“简单明了”的查询回答了我们想要回答的问题:

select count() visits
, avg(steps) avg_steps
, avg(payment_attempts) avg_pay_attempts
, max(payment_attempts) max_pay_attempts
from ga360_parsed
match_recognize(
partition by visit
order by hit
measures count(
) steps, count(payment.) payment_attempts
one row per match
pattern(from_plex (payment | anything)
completed)
define
from_plex as referer = 'https://mall.googleplex.com/'
, completed as path like '/ordercompleted.html'
, payment as action_o = 'Payment'
);


结果有 21 次访问是从那个特定的推荐人登陆到我们的网站,并最终购买了一些东西。平均来说,他们要走 35.6 步,尝试支付 1.7 次——至少有一个会话在成功前尝试支付 9 次。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9648b6e3b21ef1dffef05d9ac0d24766.png)漏斗问题的结果# 了解匹配识别你可以跟随[官方文档](https://docs.snowflake.com/en/user-guide/match-recognize-introduction.html)去发现`MATCH_RECOGNIZE`的所有能力——这里我们将看看上面查询的基础。## 规定让我们从`define`部分开始,它用于定义用户漏斗中的步骤:

define
from_plex as referer = 'https://mall.googleplex.com/'
, completed as path like '/ordercompleted.html'
, payment as action_o = 'Payment


你可以看到我们给每一步取了一个任意的名字,条件可以是你想要的任何条件。我们的一个步骤查看`referer`,另一个步骤查看用户登陆特定的`path`,支付步骤由 Google Analytics 存储的`action`变量标识。## 模式`pattern`部分基本上是漏斗步骤的正则表达式:

pattern(from_plex (payment | anything)* completed)


这表示"*查找以* `*from_plex*` *步骤开始的会话,随后是任意数量的* `*payment*` *或* `*anything*` *步骤,并以* `*completed*` *状态结束。*## 匹配 _ 识别随着`define`和`pattern`的建立,我们可以进行一个基本的`match_recognize`查询:

select classified_as, hit, visit, action_o, referer ref, path
from ga360_parsed
match_recognize(
partition by visit
order by hit
measures classifier() as classified_as
all rows per match
pattern(from_plex (payment | anything)* completed)
define
from_plex as referer = 'https://mall.googleplex.com/'
, completed as path like '/ordercompleted.html'
, payment as action_o = 'Payment'
);


我们向该查询添加了 3 个构造。首先,如何拆分和排序我们的会话:`partition by visit order by hit`。然后添加一列,显示每行在我们的漏斗中是如何分类的:`measures classifier()`。然后我们希望看到每个漏斗的所有行,而不仅仅是一行摘要:`all rows per match`。这使我们可以看到以下结果,其中突出显示了分类为“付款”的步骤:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/24835720b3d505395995b0a27f34a044.png)显示每个匹配的所有行## 回答漏斗问题确定每个漏斗步骤后,我们就可以回答开头的问题了。我们可以不选择所有的行,而是要求每个漏斗有一个摘要:`one row per match`。我们添加我们感兴趣的度量:`measures count(*) steps, count(payment.*) payment_attempts`。`MATCH_RECOGNIZE`完成剩下的工作,我们可以回到我们通常的 SQL 方式来获得计数、平均值和其他指标。# 后续步骤漏斗分析只是一个例子。想想工具箱里有`MATCH_RECOGNIZE`的所有可能性:威胁检测、在天气和股票价格趋势线中寻找趋势,等等。让我们在未来的帖子中探讨这些话题,并分享您的最佳想法和结果。# 阅读更多*   官方雪花`MATCH_RECOGNIZE()`文档。# 想要更多吗?我是 Felipe Hoffa,雪花的数据云倡导者。谢谢你和我一起冒险。你可以[在 Twitter](https://twitter.com/felipehoffa) 上关注我,并查看[reddit.com/r/snowflake](https://www.reddit.com/r/snowflake/)最有趣的雪花新闻。<https://github.com/Snowflake-Labs/awesome-snowflake> # 融合图形神经网络和语义推理以产生互补预测> 原文:<https://towardsdatascience.com/fuse-graph-neural-networks-with-semantic-reasoning-to-produce-complimentary-predictions-33a238d555c0?source=collection_archive---------34----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f425574fac1e95ceaca30cfbcc355a66.png)Maxime VALCARCE 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片***组织可以将 GNN 推理能力与知识图中的经典语义推理相结合,以达到下一个级别的人工智能,并在规模上基于上下文预测任何商业事件。***机器的推理能力——不仅仅是识别海量数据中的模式,而是根据特定领域的知识做出基于规则或逻辑的推理——是人工智能的基础。围绕[神经符号人工智能](https://research.ibm.com/blog/ai-neurosymbolic-common-sense)的增长势头和[对图形分析的日益依赖](https://solutionsreview.com/data-management/key-takeaways-the-2021-gartner-market-guide-for-graph-database-management-solutions/)证明了这些发展对企业的重要性。将人工智能的符号知识处理与其统计分支(以机器学习为代表)相结合,可以产生最佳的规范性结果,提供全面的人工智能,并迅速成为处理关键任务流程的企业规模应用的必要条件,如预测设备故障、优化医疗保健治疗和最大化客户关系。图形神经网络(GNN)体现了机器学习和人工智能推理的融合。它们的底层图形功能非常适合将机器学习的高级模式识别应用于对其他机器学习类型来说过于复杂的高维、非欧几里德数据集。通过将关系预测、实体分类和图聚类的 GNN 推理能力与知识图中可用的经典语义推理相融合,组织可以在一个框架中获得两种形式的推理。自动混合和匹配这两种类型的推理是下一级人工智能,是基于大规模上下文预测任何商业事件的基础。**从知识中创造知识**语义推理和[图形神经网络](/the-next-step-in-machine-learnings-evolution-graph-neural-networks-fdf16b8df85a)提供的推理是互补的,因为它对于不同的应用具有相似的功能。尽管语义知识图支持这两者,但是它们为语义推理提供了本地支持。这种强大的功能有效地允许组织从关于其数据的现有事实中获取新知识。例如,如果事实表明 Bill 是人类,人类是哺乳动物的一个类型(子类),而哺乳动物是动物的类型,那么对所有动物的查询将在结果*中显示 Bill,而不会明确告诉系统 Bill 是动物*。系统会将这个事实添加到它的其他知识中。虽然这个例子很简单,但是从现有知识中推断额外知识的能力对于理解、确定企业知识或医疗保健中关键数据(如患者就诊、诊断类型、治疗选项、账单和其他医疗保健问题)的分类的关系并将其置于上下文中是至关重要的。**推断关系,实体**图形神经网络的智能推理极大地提高了用语义推理扩充查询的能力。这种组合发布了惊人准确的预测,否则不可能在规模和特异性上改变一切,从下一个最佳客户互动到优化患者结果,这已变得比以往任何时候都更重要。图形神经网络处理高维数据集,这些数据集避开了典型矢量化方法的模式检测。他们根据发现智能地对实体进行分类,预测数据之间的关系(特别是通过查明知识图中[节点之间缺失或额外的链接),并在精细的知识图中分离子图。他们利用图形感知分析来完成这些统计任务。这种图形神经网络功能的分类为收集关于高度情境化数据集的预测或处方提供了无与伦比的结果,如评估社交网络以辨别客户、产品或国防工业利益中的影响者。](https://www2.deloitte.com/content/dam/Deloitte/de/Documents/operations/knowledge-graphs-pov.pdf)**一前一后**当用户在单个语义图框架中将语义推理和图形神经网络的推理配对时,会出现最佳结果。医疗行业只是众多能够从符号人工智能和人工智能统计基础的统一中极大受益的垂直行业之一。例如,有了适当的分类法,从业者就可以用它来确定花粉热患者将会出现的最常见的其他疾病。他们还可以更进一步,检查任何个体的统计和分类学关系,以预测这样的患者最有可能患的下一组疾病——通过他或她的医疗史洞察他或她的医疗未来。积极的下游效果包括从业者可以为患者实施的所有预防措施,以及将这些知识扩展到知识图中,以更好地通知未来的查询和预测。**智能推理**组织只需准备合适的分类法、本体论和逻辑规则来应用语义推理,并为他们选择的业务问题增加图形神经网络的推理能力。这种方法对于用例至关重要,例如预测飞机中各种类型的零件、工艺和 IT 系统的零件故障。反过来,这种知识对于通过预防性维护补救任何发现的问题是不可或缺的。图形神经网络通过利用人工智能漫长历史的两个方面——它的统计和知识基础,打开了组织可以实现的可能性范围。最重要的是,这些推理方法增加了组织对其特定领域问题的知识,传播了他们分析、了解和处理这些问题的能力,形成了一个良性循环,表明了人工智能在整个数据领域的影响。# 融合效率 Net & YoloV5 —高级对象检测 2 阶段管道教程> 原文:<https://towardsdatascience.com/fusing-efficientnet-yolov5-advanced-object-detection-2-stage-pipeline-tutorial-da3a77b118d1?source=collection_archive---------14----------------------->## 通过将 YoloV5 与 EfficientNet 集成,将对象检测性能提高约 20%![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1cfeeb40b3dd8f3e662d094e141544e9.png)[格蕾塔·法内迪](https://unsplash.com/@gretafarnedi?utm_source=medium&utm_medium=referral)在[号航天飞机](https://unsplash.com?utm_source=medium&utm_medium=referral)上的照片在本文中,我将解释一个我称之为“2 类过滤器”的概念。这是一种用于对象检测和分类模型的集成技术,在过去几周我一直在进行的一场 Kaggle 竞赛中大量使用。这项技术已经被几乎每个参加比赛的人所使用,它似乎能提高 5-25%左右的成绩,这是相当有用的。## 物体检测 YoloV5我们首先在数据集上训练一个 YoloV5 模型,同时使用加权盒融合(WBF)进行后处理/预处理,如果您想了解更多信息,我建议查看以下两篇文章:</advanced-yolov5-tutorial-enhancing-yolov5-with-weighted-boxes-fusion-3bead5b71688>  </wbf-optimizing-object-detection-fusing-filtering-predicted-boxes-7dc5c02ca6d3>  我不想再详述和 WBF 一起训练约洛娃的细节。但是,实际上您需要做的就是使用 WBF 消除重复的方框,然后对数据进行预处理,在上面运行 YoloV5。YoloV5 需要一个特定的层次结构,以便数据集能够开始培训和评估。## 分类-效率网接下来要做的是在数据集上训练一个分类网络。但是,有趣的是,尽管在 14 个不同的类别(13 种不同类型的疾病和 1 种无疾病类别)上训练了对象检测模型,但是我们将仅在 2 个类别(疾病和无疾病)上训练分类网络。您可以将其视为简化我们的数据科学问题的建模技巧,因为对一个网络分类 2 类比分类 14 类要容易得多,当我们融合这 2 个网络时,我们并不真正需要每种疾病的细节,我们只需要这 2 类中的一种。当然,对于您的问题来说,这可能有点不同,所以您可能需要尝试不同的设置,但是希望您可以从本文中获得一个或两个想法。目前最先进的分类网络之一是高效网。对于这个数据集,我们将使用经过 Keras (TensorFlow)培训的 B6 效率网,以及以下增强功能:

(
rescale=1.0 / 255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode="nearest",
)


如果你想看完整个教程,我建议你看看这个:</an-in-depth-efficientnet-tutorial-using-tensorflow-how-to-use-efficientnet-on-a-custom-dataset-1cab0997f65c>  ## 组装这就是 2 类滤波器提高性能的地方,也是本文真正要讨论的内容。我不想谈论太多关于培训 YoloV5 和 EfficientNet 的内容,因为有很多关于它们的资源。我想强调的主要思想是,虽然 Yolo 的分类预测非常好,但如果你可以将它们与另一个更强大的网络的分类混合,你可以获得相当不错的性能提升。让我们看看这是如何实现的。这里使用的想法是设置一个高阈值和一个低阈值。然后我们会检查每个分类预测。如果概率小于低阈值,我们将任何预测设置为“无疾病”。回想一下,我们最初的问题是对 14 种疾病中的一种或“无疾病”进行分类。这个低阈值可以是 0 到 1 之间的任何值,但是很可能是 0 到 0.1 之间的某个值。此外,如果分类预测在低阈值和高阈值之间,我们**添加**一个“无疾病”预测,该预测具有 **EfficientNet 的**置信度(不是 Yolo 的),因为在这种情况下有更高的几率患任何疾病。最后,如果分类预测高于高阈值,我们什么也不做,因为这意味着网络高度可信。这可以通过以下方式实现:

low_thr = 0.08
high_thr = 0.95def filter_2cls(row, low_thr=low_thr, high_thr=high_thr):
prob = row['target']
if prob<low_thr:
## Less chance of having any disease
row['PredictionString'] = '14 1 0 0 1 1'
elif low_thr<=prob<high_thr:
## More chance of having any disease
row['PredictionString']+=f' 14 {prob} 0 0 1 1'
elif high_thr<=prob:
## Good chance of having any disease so believe in object detection model
row['PredictionString'] = row['PredictionString']
else:
raise ValueError('Prediction must be from [0-1]')
return row


来源:[卡格尔](https://www.kaggle.com/awsaf49/vinbigdata-2-class-filter)**最终想法**我在比赛期间在各种不同的场景和模型上试验了这种 2 级过滤器,它似乎总是能够将性能提高多达 25%,这令人惊讶。我认为如果你想把它应用到你的自定义场景中,你需要考虑在什么情况下分类网络预测可以帮助你的对象检测模型。这并不完全是交换预测信心,而是以一种聪明的方式“融合”它们。# 面向未来的数据分区> 原文:<https://towardsdatascience.com/future-proof-your-data-partitions-d2047de9ead2?source=collection_archive---------32----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9f2b4e892e21dabd464b110ed90566ee.png)照片由 [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上的 [Ijaz Rafi](https://unsplash.com/@ijazrafi?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 拍摄## ***数据分区和机器中的幽灵***将数据分成训练分区和测试分区是改进我们预测的重要一步。对一些数据进行建模,并通过对剩余样本的预测来测试该模型,这就是我们如何理解和补偿偏差和方差,这是机器学习的一个中心困境。使用 Python 拆分数据非常容易,scikit-learn 中有 train_test_split 函数。除了指定训练样本(或测试样本)的大小,如果这是一个分类问题,是否对响应变量进行分层是您最需要的。剩下的工作就是设置 random_state 值,该值以随机的方式决定哪些行进行训练,哪些行进行测试。过去,对于随机种子值,我使用:1.  42(向道格拉斯·亚当斯致敬)
2.  451(雷·布雷德伯里)
3.  2001 年、2010 年和 2061 年(亚瑟·C·克拉克)
4.  314159(仅在圆周率日)
5.  我最常见的随机种子= 1这个想法是,无论随机种子输入如何,分割数据都会导致训练和测试之间的值的类似分布,但我已经错误地这样做了相当长一段时间。我们的机器(学习)里有个鬼,叫方差。***偏差&方差***但在我们带上捉鬼敢死队的质子包来对付这个幽灵之前,让我们先来看看偏差和方差的数学基础,找出前进的道路。对于随机变量 X 的给定值,测试数据的预期残值(通常表示为均方误差)可以分解为三个要素:1)方差,2)偏差的平方,以及 3)残差的方差(James,Witten,Hastie,& Tibshirani,2013)。更多细节见图 1。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f3ed381ac2e55ceb645c1fcb7c38db3e.png)图 1:均方误差分解方差本身是一个随机函数,无论学习算法如何,它都会给每个预测模型增加一定程度的不确定性,我们可以利用这种随机性来构建更稳健的模型。为了实现这一飞跃,让我们考察一个解释方差的不同方程(Abu-Mostafa,Magdon-Ismail,& Lin,2012)。更多详情请参见图 2:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/abcf09fa4c30a44a66e77ddc7a6312c1.png)图 2:方差还原在这种概念化中,学习模型“g”作用于无限数量的数据集上的随机变量 X 的预期残差值需要从所有估计值的平均值中减去估计预测值,这就是我们的解决方案!如果我们可以根据方差的平均值分割数据集,这既是数据也是特定于模型的,我们就可以提高模型对未来数据必然包含的偏差的稳健性。**类似方差均值的训练和测试分区可以降低方差本身的整体效应**。但这主要是一个概念工具,因为它意味着通过在无限数量的数据集上重复估计学习函数来收集预期残差,并且对于每个随机 x。**但还有另一种方法来使用这一概念,即通过模拟同一数据集的随机偏差的许多数据集。**通过构建测试准确度/训练准确度比率作为度量,并迭代训练/测试分裂的随机种子值,我们可以可视化学习模型的不稳定性(Abu-Mostafa 等人,2012 年),因为它们与特定数据集相关;这是检验方差的一种局部方法。一个纯理论的概念可以成为业务分析建模模板中重要的新步骤。***求方差均值***方差是特定于模型的,包含可减少和不可减少的误差,因此任何可视化这种随机函数的尝试都应该使用预期的建模算法。图 3 展示了 IBM HR Analytics 员工流失和绩效二进制分类数据集 200 次迭代的方差均值和曲线图,该数据集采用了交叉验证的逻辑回归模型,您可以看到均值分割如何减少方差的振幅波动,以及如何缩小不同时间的偏差范围。数据预处理是最少的(丢弃低信息变量和一次性编码分类变量),并且不需要调整,因为我们不寻求准确性,而是所有预测模型中存在的不稳定性,所以使用默认的超参数设置是预期的。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c53f6f88a8670cc9031aa25c30a301f0.png)图 3:方差图和平均值计算代码块 1 和 2 显示了如何使用 f1_score 作为精度度量来实现二进制分类。200 个模型的使用是任意的;选择它是为了在运行时和捕获全范围的方差之间取得平衡,其中最大的峰值出现在这个数据集+模型的 random_state = 125 以上。

Code Block 1from sklearn.linear_model import LogisticRegressionCVmodel = LogisticRegressionCV(random_state=1, max_iter=5000)

size = 0.5


Code Block 2import numpy as np

from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score, balanced_accuracy_score, precision_score, recall_score
import matplotlib.pyplot as pltVar = []for i in range(1, 200):
train_X, test_X, train_y, test_y = train_test_split(X, y,
test_size = size, stratify=y, random_state = i)
model.fit(train_X, train_y)
train_pred = model.predict(train_X)
test_pred = model.predict(test_X)
train_error = f1_score(train_y, train_pred)
test_error = f1_score(test_y, test_pred)
variance = test_error/train_error
Var.append(variance)

rs_value = np.average(Var)def find_nearest(array, value):
array = np.asarray(array)
idx = (np.abs(array - value)).argmin()
return array[idx]nearest = find_nearest(Var, rs_value)print('random_state = ', Var.index(nearest))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9993cb320d71ec490c5b59dc206182db.png)方差均值分割的随机种子值

Code Block 3 for plotting the variance graphplt.figure(figsize=(10,8))plt.plot(range(1, 200), Var, color='royalblue', label="Variance")

plt.plot([0, 200], [rs_value, rs_value], color='darkorange', linewidth=3)
plt.text(0,rs_value, rs_value, fontsize=15, color='black')plt.legend(loc='lower center', shadow=True, fontsize='medium')
plt.show()


为回归模型更改此代码是一个简单的转换:从数据分区中删除“分层=y ”,并更改误差度量(例如,均方误差、平均绝对误差等。).代码块 1 设置建模算法和测试大小,而代码块 2 收集方差信息,计算其均值,并找到与方差均值最接近的随机状态值,以对训练/测试分割进行编程。代码块 3 绘制了方差及其均值。关于这种方法是否会导致信息泄露还有一个问题,但是我们没有使用测试预测的性能来改变模型拟合。相反,我们使用来自多个模型的元数据来发现方差均值,并根据该值调整初始数据分区。尽管如此,这是一个讨论的话题。最后,尽管需要更多的一次性计算资源,但根据方差的平均值分割数据应该会产生更强大的模型,在新的未来数据到来时,这些模型将保持更好的准确性。**参考文献**Abu-Mostafa,Y. S .、Magdon-Ismail,m .、和 Lin,H.-T. (2012 年)。*从数据中学习*(第四卷)。美国纽约 AMLBook:詹姆斯,g .,威滕,d .,哈斯蒂,t .,,蒂布拉尼,R. (2013)。*统计学习概论*(第 112 卷)。斯普林格。# 用 Python 实现模糊 C 均值聚类> 原文:<https://towardsdatascience.com/fuzzy-c-means-clustering-with-python-f4908c714081?source=collection_archive---------4----------------------->## 无监督学习## 在这篇文章中,我简要介绍了无监督学习方法的概念,模糊 C 均值聚类,以及它在 Python 中的实现。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8802cad16a198dd9534af983613e9354.png)亚历山大·Cvetanovic 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片F uzzy C-means 聚类算法是一种无监督学习方法。在了解细节之前,我先来解密一下它的花里胡哨的名字。所以,“模糊”在这里的意思是“不确定”,表示这是一种**软聚类**方法。“C-means”的意思是 C 个聚类中心,只是把“K-means”中的“K”换成了一个“C”,让它看起来不一样。在一个聚类算法中,如果一个数据点属于一个聚类的概率只能取值 1 或 0,这就是**硬聚类**。硬聚类方法中的聚类的边界可以被可视化为清晰的边界。相反,在软聚类方法中,一个数据点属于一个聚类的概率可以取 0 到 1 之间的任何值,例如 75%,为此,聚类的边界可以被可视化为模糊边界。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/bffd8ac30b7791e0ef29187fb3811cf2.png)硬聚类和软聚类。每个点代表一个数据点,每个点中的数字是它属于类 1 的概率,黑色圆圈代表类 1 的类边界。(图片由作者提供)好了,在了解了软聚类方法的概念之后,我们可以直观地认识到可能驱动聚类的几个重要参数。首先,当然是集群中心。第二,一个点属于特定聚类的概率。## 了解参数在*模糊 c 均值* ( **FCM** )聚类方法中,我们有两个参数, ***μ_ij*** 和 ***c_i*** 和一个超参数, ***m*** 。***【μ_ ij】****隶属值* ***,*** 是第*个*个数据点属于第*个*聚类的概率,约束为每个数据点 *j* 的 ***μ_ij*** 与 *C* 聚类中心之和为 **1** ***c_i*** 是*与*簇的中心(与 ***X*** 同维)。而 ***m*** 是*模糊化器*,控制聚类边界应该模糊到什么程度。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c523fec52c7211490ec02e1d456d18a0.png)参数示例。(图片由作者提供)在上面的示例图中,我们正在查看第 5 个数据点 *X_5* ,并且假设我们知道只有两个聚类,并且当前聚类中心是*C1*和*C2*。 ***μ*** _25 是第 5 个数据点属于第 2 类的概率, ***μ*** _15 是第 5 个数据点属于第 1 类的概率。然后,我们看到第 5 个数据点比 C1 更靠近 C2,所以 ***μ*** _25 (0.6)大于 ***μ*** _15 (0.4)。并且它们满足每个数据点的 ***μ*** 之和为 1 的约束,其中***μ***_ 15+***μ***_ 25 = 1。上面的例子只是为了说明 FCM 中的参数,但是实际的值并不一定是那样的。## 目标函数![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2f019f3fa58ae1e575127c3d4566e70e.png)FCM 的目标函数。(图片由作者提供)我选择在引入参数后显示目标函数,因为它在这里看起来更清晰。你可以把目标函数理解为数据点( *X_j* )和聚类中心( *C_i* )之间距离的加权和。“距离”项是上式中的 *L2 范数*,在上面的示例(第 5 个数据点)中,它正好是箭头的长度。如果 *m = 1* ,那么目标函数就是数据点和聚类中心之间距离的概率加权和。这是什么意思?这意味着靠近聚类中心的数据点被赋予较高的权重。在上面的例子中,第 5 个数据点和第 2 聚类中心之间的距离比第 5 个数据点和第 1 聚类中心之间的距离对目标函数的贡献更大,因为 ***μ*** _25 = 0.6 和 ***μ*** _15 = 0.4。记住,我们希望最小化目标函数,因此对于那些长距离(数据点和聚类中心之间),使用小的 ***μ*** 是很好的。如果 m =2,3,…会怎么样?然后距离的贡献差越来越小,如下图所示( ***μ*** _15 和 ***μ*** _25),都接近于 0。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/deb99ddca818b2ec6b1303cc429c8c4d.png)重量衰减曲线。红色曲线为 ***μ*** _25,蓝色曲线为 ***μ*** _15。(图片由作者提供)因此,对于**一个非常大的 m** ,聚类**中心**倾向于位于与所有数据点的**距离**几乎相等的地方,因为每个点到中心的距离对目标函数的贡献 ***相等*** 。那么,聚类中心在哪里呢?是的,所有数据点的中心。如果 m 超级大,所有聚类中心都位于所有数据点的质心,那么聚类就会超级“ ***模糊*** ”因为根本不聚类!![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4c1ccf53e2079c951477b98023885e05.png)FCM 中非常大的 m 的例子。(图片由作者提供)因此,为了进行有意义的聚类,我们在大多数情况下使用 m = 2。## 寻找最小化目标函数的参数受约束的参数优化可以使用拉格朗日函数手动解决,但我们不会在这篇文章中讨论它。相反,我现在列出的是计算 ***c_i*** 和 ***μ_ij 的最终方程。***![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1e8f7da069ad255c6c28aeda981f46c4.png)更新 FCM 方程(图片由作者提供)求解 ***c_i*** 的方程相对简单,其中它表示 X 到簇中心 *i* 的加权平均值。为什么一定要除以(***μ_ ij***)*^m*之和?那是因为只有当 ***m=1*** 时,权重之和才等于 1(这种情况下我们可以去掉整个分母)。当 *m > 1* 时,权重之和为聚类中心加权和计算的定标器。但是 ***μ_ij*** 的方程看起来没那么好理解吧?如果我们把它转换成下面这个,应该就容易解读多了。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2180677adedf891763844cc92e33b949.png)u_ij 的另一种看法(图片由作者提供)假设 *m=2* ,那么分子部分就是第*个第*个数据点到第*个第*个聚类中心的 ***距离*** 的倒数(上图中箭头的长度)。如前所述,较大的距离应对应较小的 ***μ_ij*** ,这也反映在这个等式中。等式的分母是从 *x_j* 到每个聚类中心的距离的倒数之和。## 该算法完整的 FCM 算法可以在下图中描述。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/079de77e49e18ad4c5fc9a7ad56b9cde.png)FCM(作者图片)算法该过程实际上与 **EM** 算法相同。如果你有兴趣了解 EM,可以去下面的帖子。</gaussian-mixture-models-with-python-36dabed6212a>  ## 实施 FCM模糊 c 均值聚类在 Python 中的实现非常简单。安装程序如下所示,

import numpy as np
from fcmeans import FCMmy_model = FCM(n_clusters=2) # we use two cluster as an example
my_model.fit(X) ## X, numpy array. rows:samples columns:features


从聚类模型中提取信息,

centers = my_model.centers
labels = my_model.predict(X)


就是这样!希望文章有用。<https://jianan-lin.medium.com/membership> # 模糊数据结构——诅咒还是祝福?> 原文:<https://towardsdatascience.com/fuzzy-data-structures-curse-or-blessing-5ee34ff39cd7?source=collection_archive---------37----------------------->## 从工业应用的角度看挑战和解决方案![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d8621030fa6dde51475057e44ffed418.png)约书亚·索蒂诺在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片# 介绍前段时间发现一篇有意思的文章[【1】](#_ftn1),对比了 SQL 和 NoSQL 通过 Python 进行数据处理,指出了 SQL 的一些弊端。SQL 的一个突出的弱点是在一个简单的属性中缺少存储复杂的对象结构(例如 Python 字典),这违反了第一范式(1NF)[【2】](#_ftn2)。在这种情况下,作者简要讨论了模糊数据格式的情况,这在 MongoDB 中是技术上可行的。虽然在那篇文章中没有进一步指出这个问题,但是我想知道 MongoDB 的这个特性到底是优点还是缺点,特别是在我专业所在的工业应用程序环境中。因为我找不到一篇文章全面地讨论了这个问题,所以我想分析和讨论这个问题,并分享我的发现!在这个简短的介绍之后,我们将简要讨论不同数据库技术的特征。然后,我们将基于 MongoDB 中的两个简单集合评估使用模糊数据结构时的挑战。接下来,我们将把简化示例中的发现转移到半导体行业的实际工业应用中。最后,我们将进一步了解克服这些挑战的工具和方法。# 技术首先,必须理解 MongoDB 的数据存储原理。MongoDB 通常被归类为 NoSQL 数据库概念[【3】](#_ftn3)。然而,NoSQL 是多种技术的总称,这些技术不仅不同于 RDBMS,而且彼此之间也有很大的不同。众所周知的 NoSQL 数据库技术类型有键值存储(如 Amazon Dynamo)、宽列存储(如 Cassandra)、图形数据库(如 Nio4j)和文档存储,MongoDB 属于这些类型。与 SQL 相比,面向文档的数据库的一大优势在于,数据结构可以以与处理这些数据的软件代码相同的格式持久化和查询。数据格式遵循类似 JSON 的半结构化和层次化格式。据 AWS 称,它符合目录、用户配置文件和内容管理系统的要求,每个文件都可以有一个独特的格式。面向文档的数据库提供了灵活的索引、高性能的特别查询和对集合的分析[【4】](#_ftn4)。MongoDB 和 MySQL 之间的性能比较得出的结果是,MongoDB 的写性能明显更高,尤其是对于较大的数据集,而 SQL 执行更快的查询[【5】](#_ftn5)。因此,这意味着文档存储的应用对于需要频繁插入或更新数据和/或处理较大数据的场景是有用的。这种用例也存在于工业环境中:例如,从生产设备中收集遥测数据需要非常频繁的插入,并且根据机器的复杂性,可能包含涉及特定传感器的多个变量。# 挑战为了评估这些挑战,创建了一个示例 MongoDB 数据库。第一个场景使用由三个文档组成的集合,如图 1 所示:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/38137eb2092f1c6077c390ba7893388f.png)图 1:带有文档的样本集合文档引用人并存储他们的一些属性,如姓名、年龄、城市和爱好;“_id”属性是文档的默认标识符。乍一看,它看起来像一个简单的数据结构。不过还是把重点放在“爱好”这个属性上吧。如图所示,我们看到每个文档都有这个属性。然而,该属性的数据类型在文档之间明显不同:(1)数组,(2)对象和(3)字符串。这种模糊性实际上是关系数据库的一个不同之处,在关系数据库中,表属性的数据类型是为所有记录严格定义的。因此,我们看到我们可以创建灵活的——或者更负面地说——不确定的数据结构。让我们直接关注一个相关的主要挑战:MongoDB 不提供像数据结构那样灵活的查询功能。这在实践中意味着什么?让我们仔细看看三个文档的“爱好”属性值。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d0bbb85160dad8e79d80839227e1c897.png)图 2:兴趣爱好的更详细视图如果我们希望找到所有将“足球”作为业余爱好的人,我们作为人类可以简单地看到在我们的集合中有两个相关的人。然而,想象我们在社交媒体平台上有数千或数百万这样的文档,我们宁愿应用数据库查询来搜索类似“所有爱好足球的人”的内容。然而,对于这种类型的模糊数据结构,这在技术上是不可能的,因为 MongoDB 需要一个唯一的路径来应用过滤器。虽然通配符搜索是可能的,并且也适用于对象中的嵌套字段,但是这个搜索工具不能处理不同的数据结构[【6】](#_ftn6)。这实际上意味着我们可以在文档层次结构的任何级别上对包含短语“爱好”的字段执行搜索——但是该搜索不考虑我们的嵌套数组或对象,因为内部字段名称不同于“爱好”。此外,我们可以说这样的搜索在语义上也是没有用的,因为这就像是在大海捞针。因此,我们可以说,当我们想要存储内容相似但结构不同的数据时,MongoDB 提供了广泛的灵活性,但是一旦我们想要查询或分析这些数据,我们就会受到这种模糊数据结构的限制。当然,我们可以将查询逻辑放在外部代码中,例如用 Python,并构建一个函数来连续搜索字符串形式的爱好、数组形式的爱好和对象形式的爱好,然后返回合并的结果。但是这是一个静态的解决方案,只要我们不“关闭”其他结构变体的大门,我们就不能确保查询不会错过相关的结果。**第二个场景**涉及模糊数据结构,与包含不同属性文档的集合相关。在我们的例子中,有一组由不同信息描述的人。我们现在正在努力解决这样一个问题:亚当是通过他的头发颜色来描述的,而布莱恩和夏娃是通过他们的眼睛颜色来描述的。更糟糕的是,属性“眼睛颜色”在两个文档中使用了不同的拼写。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b1dbc665c944d1ebf0f333cd2157e684.png)图 3:具有不同属性的文档集合虽然我们现在能够始终如一地根据爱好进行筛选,但我们无法直接搜索具有特定头发或眼睛颜色的人。同样,我们的查询可能会忽略语义上符合过滤标准的文档。此外,我们的分析能力有限,因为我们无法确保所有文档都有相同的可用信息。当然,如果表中的字段没有配置为强制的,这个问题也可能存在于 SQL 数据库中,但是至少我们可以依赖一组固定的属性。但是,使用 MongoDB,如果不断插入新文档,同一集合中的文档之间使用的各种属性可能是无穷无尽的。因此,数据分析师甚至无法确定可以使用哪些属性。# 研究成果转化为工业应用我们在上一节中基于非常简单的例子讨论了几个挑战。但是这些是理论上的构想还是工业应用中的现实问题?为了回答这个问题,让我们仔细看看前面提到的从机器上收集遥测数据的用例。图 4 显示了从 E1 到 E3 的三台机器,它们属于两种不同的类型 T1 和 T2。此外,我们看到两种类型的接口定义 ID1 和 ID2。通过这些接口,设备遥测数据被传输到中央 CIM 数据库。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/bb8669f88aff8ae21f775b48602060a6.png)图 4:设备数据集成示意图在半导体行业,我们通常使用一种称为“SECS/GEM”的接口标准。基于这个标准的事件消息有一个类似于 JSON 的类似对象的字符。然而,与 JSON 或 XML 相比,SECS/GEM 的一个好处是减少了数据开销,从而减少了网络流量,加快了数据处理[【7】](#_ftn7)。无论如何,原始事件消息不符合关系表,因为它包含违反 1NF 的非原子信息。因此,将设备事件存储到 SQL 数据库总是需要 ETL 过程。但是,事件消息可以作为文档直接存储到 MongoDB。由于 SECS/GEM 消息体的结构是由该标准定义的,因此场景 1 中讨论的风险在该应用中较低,只要所有设备接口都遵循该标准(例如 E3 和 E1)。而且半导体设备可能会受到最初不支持任何数据集成的遗留设备的影响。升级到 SECS/GEM 可能需要制造商的支持,并且成本更高。然而,也有经济高效的替代方案来实现传统设备的数据集成,如智能传感器、改装套件和边缘网关[【8】](#_ftn8)。由于有不同的接口定义,我们有不同数据结构的潜在风险,只要不遵循 SECS/GEM 消息格式,或者数据在存储前没有被转换。因此,从工业应用的角度来看,场景 1 中提到的挑战在我们描述的用例中理论上是可能的,但如果有经验的工程师预见到它们,是可以避免的。在这个实际用例中,以不同格式存储相同信息的能力并没有被视为一种优势。让我们转到场景 2:在半导体行业,我们通常使用不同设备制造商提供的不同机器类型(参见 E1 和 E2 与 E3)。这些机器大多有内部软件和内置传感器。最有可能的是,可用的传感器以及类似传感器的内部技术名称在机器和制造商之间有所不同,即使它们指的是相同类型的信息,例如压力或温度。如果设备接口之间没有数据协调,这种情况将导致场景 2 中描述的问题陈述:a)如果单台机器不提供该信息,我们不能一致地过滤或分析机器园区内的传感器值;b)我们必须处理引用相同信息但具有不同拼写的传感器名称。因此,我们可以得出结论,这些风险对于我们的工业用例是有效的。然而,我们也可以暗示 MongoDB 的能力适合于存储不同消息内容和灵活添加新实现的传感器的数据的需求。# 如何应对这些挑战幸运的是,有多种技术可以克服前面讨论的挑战。可能有更多的方法,我并不声称下面的列表是完整的,但我想提供一个从反应一致性验证到真正的预防措施的技术带宽的概述。**1)** **检查字段存在**作为数据分析人员,您可能希望检查特定字段是否如您所料存在于集合中。这可以防止无效的筛选器或聚合。MongoDB 提供了“$exists”操作符,可以在查询中使用该操作符只返回包含特定字段或缺少特定字段的文档[【9】](#_ftn9)。获得两个过滤器的结果表明,该领域必须小心享受。**2)** **从集合中检索所有字段**如果您想要应用系统的或者甚至定期的比较来识别缺失的字段,那么像前面讨论的那样检查字段的存在可能不是正确的方法。您更希望提取存在于您的集合中的字段列表。这可以通过使用“map reduce”方法来实现。下面的 Python 代码展示了一个使用 pymongo API 的示例实现。

import pymongo
from bson.code import Code

conn = "mongodb://localhost:27017"
client = pymongo.MongoClient(conn)

db = client.mytestDB

map = Code("function () {"
" for (var k in this) { emit(k, null); }"
"}")

reduce = Code("function(k, s) { return null; }")

result = db.diffAttributes.map_reduce(map, reduce, "r")
for d in result.find():
for k, v in d.items():
if k == "_id":
print(v)


通过执行这段代码,我们从被评估的集合中接收到以下打印的唯一字段列表,在本例中称为“diffAttributes”。当然,我们可以将列表转移并持久存储到文档或数据库中,或者直接在 Python 代码中实现进一步的检查。

name
_id
eye colour
eye color
hobbies
hair color


**3)**检查模式如果使用 MongoDB Compass 进行数据库管理,可以简单地分析数据库模式,考虑集合中的所有文档。使用图 5 所示的结果,您可以很容易地评估集合中字段的形状。例如,我们看到字段“爱好”使用了三种数据类型。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/98f1b864f2aeef6dd9fab117f90874f4.png)图 5:使用 MongoDB Compass 进行模式分析的结果**4)**强制一个模式标准从本文的讨论中,人们可能会有这样的印象:MongoDB 是建立在无政府状态之上的。情况显然不是这样。尽管有多种方法可以灵活地存储复杂的数据结构,但我们可以降低这种灵活性,使我们的集合内容是可确定的。就像 SQL 数据库一样,您可以定义验证规则,例如,哪些字段是强制性的,必须遵守哪些数据类型,或者允许哪些值[【10】](#_ftn10)。例如,如图 6 所示,我们可以声明我们的“爱好”属性只允许字符串值。通过执行这个验证规则,MongoDB Compass 显示了哪个文档是有效的或无效的。此外,我们可以配置拒绝违反此规则的新插入文档。因此,我们可以从头开始保持我们的集合的一致性。唯一的限制是,如果 MongoDB Compass 连接到一个数据湖,这个特性就不可用。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/834e65d2231f3daaa1be295c6b7dd2ec.png)图 6:验证规则**5)** **提供用户界面**如果您希望存储在 MongoDB 中的数据直接来自用户条目,您可以通过构建一个成熟的 UI 来减少数据结构的模糊性。这类似于具有自动生成数据的标准化设备接口的方法。您可以配置下拉框来强制允许的值,使文本框成为强制性的,甚至提供工作流来按一定的顺序收集数据。因此,我们确保只向数据库提交符合允许的数据格式的数据。6) **应用数据治理(DG)**这听起来很琐碎:但是要知道您的数据是否一致,首先需要定义规则,并在利益相关者之间针对特定的数据对象保持一致。如果从来没有决定“爱好”应该是一个数组,或者“眼睛颜色”必须遵循哪个拼写,那么从技术上来说,你不能在你的集合中解决这个问题。DG 就位了。通过明确数据的责任和决策流程,您可以获得多种好处,例如加快 IT 项目实施速度、提高数据质量和增加数据价值[【11】](#_ftn11)。如果所有 IT 实施活动都遵循 DG 的决策,我们将通过设计确保数据的一致性。# 结论在本文中,我们评估了在文档存储中允许模糊数据结构时可能出现的挑战和风险。我们基于在 MongoDB 中实现的两个简化场景对它们进行了分析和评估,并将结果转移到一个选定的行业用例中。我们暗示了在工业应用程序中,MongoDB 的灵活性可能是有用的,但也可能存在缺点。最后,我们讨论了克服这些挑战的技术,其中我们看到了相当被动的方法(例如现场存在检查)以及预防措施(例如数据治理)。**参考文献**[1] M. Sosna,SQL 与 NoSQL 数据库在 Python 中的实践演示-用 SQLAlchemy 和 PyMongo (2021)打动你的朋友,[https://towardsdatascience . com/A-Hands-On-Demo-of-SQL-vs-no SQL-Databases-in-Python-eeb 955 bb a4 aa](/a-hands-on-demo-of-sql-vs-nosql-databases-in-python-eeb955bba4aa)[2]维基百科,第一范式(n.d .),https://en.wikipedia.org/wiki/First_normal_form[3]谢弗,什么是 NoSQL?(未标明)[https://www.mongodb.com/nosql-explained](https://www.mongodb.com/nosql-explained)[4]亚马逊,它是一家银行吗?(未注明)[https://aws.amazon.com/de/nosql/document/](https://aws.amazon.com/de/nosql/document/)[5] M. Shah,MongoDB vs MySQL:关于数据库的比较研究(2017),[https://www . sim form . com/MongoDB-vs-MySQL-Databases/#:~:text = MongoDB % 20 vs % 20 MySQL % 3A % 20 性能% 20% 26% 20 速度,is % 20more %敏感% 20 to % 20 工作负载](https://www.simform.com/mongodb-vs-mysql-databases/#:~:text=MongoDB%20vs%20MySQL%3A%20Performance%20%26%20Speed,is%20more%20sensitive%20to%20workload)[6] MongoDB,路径构造(n.d .),[https://docs . atlas . MongoDB . com/reference/atlas-search/Path-Construction/# STD-label-ref-Path](https://docs.atlas.mongodb.com/reference/atlas-search/path-construction/#std-label-ref-path)[7] B .格雷,SECS/GEM 系列:协议层(2018),[https://www . cimetrix . com/blog/secs-GEM-series-Protocol-Layer](https://www.cimetrix.com/blog/secs-gem-series-protocol-layer)[8] I. Lamont,将传统制造设备带入物联网时代的 4 种方法(2019),[https://www . hpe . com/us/en/insights/articles/4-ways-to-bring-legacy-manufacturing-equipment-into-the-IoT-age-1903 . html](https://www.hpe.com/us/en/insights/articles/4-ways-to-bring-legacy-manufacturing-equipment-into-the-iot-age-1903.html)[9] MongoDB,查询空字段或缺失字段(n.d .),[https://docs . MongoDB . com/manual/tutorial/Query-for-Null-Fields/](https://docs.mongodb.com/manual/tutorial/query-for-null-fields/)[10]MongoDB,为你的模式设置验证规则(n.d .),【https://docs.mongodb.com/compass/current/validation/ [11]数据治理(n.d .),https://www.cc-cdq.ch/data-governance# 模糊积分:深入研究数据融合> 原文:<https://towardsdatascience.com/fuzzy-integral-a-deep-dive-into-data-fusion-b544e90e9c7b?source=collection_archive---------8----------------------->## 模糊积分——一种鲜为人知的计算智能方法模糊积分是一种强大的、鲜为人知的数据融合技术。我花了七年时间研究它的许多特性。这篇文章介绍并探索了模糊积分的基本原理,为研究它的各种特性打下了基础。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a701efb9701d5e6684ee074a440f2e95.png)丹尼尔·利维斯·佩鲁西在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片# 动机/设置我们可以将计算智能分割成许多不同的部分——[分支](/tired-of-ai-lets-talk-about-ci-eb54f7a2d393),主题,算法,底层数学,等等。也许没有“正确”的方法来做这件事,但是我想让你知道这篇文章会给你自己带来什么。今天的帖子是:*分支* : **模糊系统**
*主题* : **数据融合**
*数学* : **模糊积分**
*算法* : **将模糊积分**
*编程语言* : **Python**# **数据融合**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b98f2cbc80db3a3c51dc94198c2cf100.png)弗兰基·洛佩兹在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片随着我们收集和处理更好数据的能力越来越成熟,数据融合算法也在不断变化。在高层次上,数据融合是将多个输入(或源)集合在一起并组合成单个输出的过程。数据融合是一个重要的人工智能问题,因为我们经常有来自不同来源的信息,我们必须筛选噪音以找到最合适的组合。作为人类,我们经常毫不费力地混合互补的、多余的、甚至是冲突的信息。我们将杂乱的数据整合成单一结论的能力很难在算法中复制。例如,我的手机上有三个不同的天气应用程序。我可以随时登录,每次都会给出不同的天气预报。有了这些信息,我们可能会问:“天气会怎么样?”;一个数据融合算法可以解答。但是怎么做呢?在这篇文章的剩余部分,我将分解一个特定的数据融合算法——模糊积分。# **模糊积分**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/aab70c92bb93f31a3c7a890c58511767.png)杰斯温·托马斯在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片一旦我们抛开行话,模糊积分(又名 Choquet 积分)可以说是一个非常简单的概念。我花了很长时间才意识到这个算法是三个简单的运算——加法、减法和乘法。当然,魔鬼就在细节中,随着我们的深入,它的功能变得越来越复杂。然而,只要我们回到基本原则,我们可以增加更多的复杂性。首先,让我们在一个较高的层次上完成这些步骤(使用我们的天气示例),然后我们将检查这个等式。## 1.从每个天气应用程序接收预测值[3 个值]## 2.根据大小对值进行排序## 3.减去适当的参数来计算权重## 4.将权重乘以适当的输入## 5.添加到目前为止的总重量## 6.从步骤 3 开始重复,直到所有值合并我们可以用下面的等式来表示这些步骤:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b2616106bed0dec7c4c0c965f19f46cb.png)图片作者。我有相当不错的数学背景,当我第一次看到这个等式时,我仍然感到害怕。看一眼就理解这个符号被证明是复杂的。让我们将这些参数与我们的天气示例联系起来。**适马**是标准的数学符号。它表示多个项目的总和。我认为这是一个“for”循环,其中“j”是当前索引,“N”是总迭代次数。在我们的例子中,我们将迭代每个天气应用程序的预测值。**pi(几项的下标)**是 Choquet 积分非线性特征的原因。积分要求我们在应用等式之前对每个样本的输入值进行排序。 **pi** 表示该参数与特定的排序相关。*因此,天气应用程序预测下雨的概率为 84%,应用程序 2 预测为 57%,应用程序 3 预测为 97%。排序应该是 app。3,app。1,app。2.***mu (A_{pi(j)})** 是定义系统的参数值。当我们从它前面的值中减去**mu(A _ { pi(j)}****【mu**】**(A _ { pi(j-1)})】**时,我们产生特定输入的权重。因此,通过遵循这个等式(或上面列出的步骤),我们将有效地将 Choquet 积分应用于新样本。然而,这一过程还有其他一些特点。我提到了排序,我还没有掌握在高层次上解释排序的必要性——我将谈到它的含义。排序允许积分是非线性函数,这是很重要的,因为它产生了更复杂的决策边界。在[1]中,我们创造了术语“行走”,指的是个体排序。如果我们独立地观察每一步,我们会注意到每一步都是一个线性方程。为什么这很重要?我们可以明确地将每个权重和/或来源的影响与特定的结果联系起来。这一特性对其 XAI 有着巨大的影响,但这超出了本文的范围。此外,该方法有两个约束条件——边界条件和单调性。这实质上意味着权重介于 0 和 1 之间,并且参数(用于计算权重)必须大于它们之前的值。好吧,但这意味着什么?让我们在这个例子中放一些数字。我们可以用点阵直观地表示 Choquet 积分。从底部开始,到顶部的每条路径都是一次遍历,每个节点都是用于计算特定。在非线性函数中,积分可以学习最大值运算。为此,我们将每个参数设置为 1。下面的例子说明了为什么会出现这种情况。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/63698240a4b38586030e10aa038d8d6b.png)作者图片无论我们走哪一条路,第一个源头就是我们所考虑的一切。这个例子回避了我们如何定义参数的问题?嗯,有很多方法可以实现这一点,但我们最喜欢的是二次规划。二次程序利用了积分是一组线性方程的事实。使用这种技术,我们能够学习一组参数来快速优化权重。我们还可以用许多其他方式利用行走特性。例如,如果我们知道训练数据,我们可以追踪每种排序在训练过程中影响的权重。这意味着,可以为每个参数和整个系统计算信任值。这个概念是巨大的。它是如此巨大,以至于我可以利用它来写我的论文。在接下来的几周里,我们将深入探讨如何利用它来提高我们对来源、数据和模型的理解。# **代码(基础知识)**我想在这篇文章中提供一些实用的东西,所以我想分享一些使用这个算法的基本代码。这些代码都是用 python 编写的,它使用了几个不同的包。我会推荐安装 conda(外面有很多 conda 教程)。我是在刚接触 python 时写的这篇文章,所以请原谅任何糟糕的约定。在这个例子中,我们将使用合成数据来感受这个算法。如果我们使用一个技巧来生成标签,我们可以控制我们的输出。在这个例子中,我希望算法证明它可以在适当的时候学习*Max*运算。首先,创建 25 个样本,每个样本有三个特征,然后,将标签设置为每个样本值的最大值。

data = np.random.rand(3, 25)
labels = np.amax(data, 0)


在我们创建数据之后,我们可以通过几个步骤来训练算法。以下代码行初始化一个 Choquet Integral 对象。

chi = ChoquetIntegral()


然后,我们通过将数据传递给训练函数,用二次程序进行训练。

chi.train_chi(data, labels)


基于 Choquet 积分的基本数学,你知道学习的权重应该是多少吗?要查看它们是什么,请运行下面一行。

print(chi.fm)


该算法为每个学习到的重量生成一个 1,这正是我们所期望的。我们可以用最小运算代替最大运算重复同样的练习。然而,我们将为权重学习什么值呢?全是 0。这里的回购是[这里的](https://github.com/B-Mur/choquet-integral)。# 结论模糊积分是一种鲜为人知的数据融合算法,已经在模糊社区的许多不同应用中使用。它伴随着一套深厚扎实的数学理论。也就是说,这不是解决你所有问题的完美方案。具体来说,它在试图融合多个源时会很困难;我从未融合超过 10 个。但是,如果你有需要融合的资源,并且正在寻找可以学习复杂决策边界和大量解释机会的东西,那就去看看吧!# 参考[1]https://ieeexplore.ieee.org/document/8491501# 模糊匹配人名> 原文:<https://towardsdatascience.com/fuzzy-matching-people-names-6e738d6b8fe?source=collection_archive---------7----------------------->## [实践教程](https://towardsdatascience.com/tagged/hands-on-tutorials)## 使用 Python 和线性编程对十亿 Git 提交签名等进行数据驱动算法设计。我最近不得不解决一个有趣的问题:给定两个含有真实姓名的无序列表,匹配它们之间的身份。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/db0153c35a3a492c8f6b2ec3929b09e8.png)两个姓名匹配的列表。图片作者。看起来很简单,对吧?对两个列表进行排序,就大功告成了。唉,我的问题是关于两个独立的名单,名单上的人来自不同的独立信息来源——准确地说,是来自同一个组织的 GitHub 和 JIRA 用户。我必须处理以下复杂情况:*   不存在完美的匹配。第一个列表中的名字属于第二个列表中不存在的人,反之亦然。
*   列表有不同的长度。
*   名称的格式是任意的。比如“V. MARKOVTSEV”或者“Vadim”而不是“Vadim MARKOVTSEV”(Vadim 是我的名字)。
*   虽然这些名字是用拉丁字母写的,但是所有可能的 Unicode 怪癖都有不同的规范化、变音符号等等在等着我。
*   列表项可以包含多个名称。这些是相应人员在信息资源上使用的独特签名。例如,GitHub 用户可能在工作和家用电脑上以不同的方式提交。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f078839d27501aafab09575493b46f74.png)一些匹配的复杂情况。图片作者。在花了一些时间进行实验后,我用 Python 想出了一个“足够好”的解算器,并发表在 GitHub 上:[名称匹配器](https://github.com/athenianco/names-matcher)。文章的其余部分是关于实现的模糊匹配算法。# 资料组拥有一个好的数据集来评估想法是所有好的解决方案的内在要素。我收集了两个:一个私人的和一个公共的。私人数据集包含大约 10 个雅典客户组织的个人信息:他们在 GitHub 和 JIRA 上的全名([雅典](https://athenian.co)是我工作的公司)。因此,我不能透露数据。公共数据集是一个半人工数据集,每个人都可以按照我的指示或[直接下载档案](https://drive.google.com/file/d/1R8MgffDNuOUcEeGF4c9Hi9McfnaBpIxY)进行复制。如何构建公共数据集的想法源于我之前在 [source{d}](http://web.archive.org/web/20191225160328/https://sourced.tech/) 的经历:从 GitHub 存储库的公共可用元数据中榨取最大的汁液。我利用了两个来源:[2016 年 Google BigQuery 上的 GitHub 快照](https://cloud.google.com/blog/products/gcp/github-on-bigquery-analyze-all-the-open-source-code)和 [GHTorrent](https://ghtorrent.org/) 。前者在 Git 提交签名中提供真实的人名,而后者提供这些提交的真实身份。以下 BigQuery SQL 提取相关大小的 GitHub 帐户:

SELECT SUBSTR(repo_name, 0, STRPOS(repo_name, '/') - 1), COUNT()
FROM bigquery-public-data.github_repos.languages
GROUP BY SUBSTR(repo_name, 0, STRPOS(repo_name, '/') - 1)
HAVING COUNT(
) > 50;


当然,五年后,拥有超过 50 个存储库的账户会更多;然而,我的目标不是列出一份详尽的清单。该查询产生了 500 多个属于组织和个人用户的帐户名称。我在顶部过滤了大约 20 个条目,排除了太多样化和太单一作者的条目,如`google`、`JuliaPackageMirrors`或`sindresorhus`。然后,我启动一个更重的查询来获取剩余存储库中提交的 Git 签名中的名称:

SELECT DISTINCT SUBSTR(repo, 0, STRPOS(repo, '/') - 1),
commit,
author.name,
committer.name
FROM bigquery-public-data.github_repos.commits,
UNNEST(repo_name) AS repo
WHERE SUBSTR(repo, 0, STRPOS(repo, '/') - 1) IN ('openstack', 'octoblu', ...);


现在我有了一个提交散列、相应的作者和提交者姓名以及 GitHub 帐户名。其中 13.7 亿人。不幸的是,BigQuery 没有告诉我们哪些用户与每个记录相关联。我们要挖掘第二个数据源,GHTorrent 的 MySQL dump。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3731eac0473f633440d12830e5d0546c.png)GHTorrent 的 MySQL 数据库的模式。我们需要带有标识的“提交”表。资料来源:GHTorrent.org。GHTorrent 也过期了——更新在 2019 年停止了,但这没什么,因为我们真正需要的是 BigQuery 数据集发布后的转储。读者可能想知道为什么我们需要 BigQuery。答案是因为 MySQL 模式不包含人名。它们确实存在于 MongoDB 转储中,但是根据我的经验,它们是增量的,并且更难处理。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/13b6dc1cc6c826b9d02d24b52ba6ed0d.png)GHTorrent 的提交表不包含任何个人信息。资料来源:GHTorrent.org。这就是如何下载转储文件并提取包含提交散列和相应用户 id 的文件,而不存储其余部分:

wget -O - http://ghtorrent-downloads.ewi.tudelft.nl/mysql/mysql-2016-09-05.tar.gz | tar -xzvO mysql-2016-09-05/commits.csv | gzip > commits.csv.gz


下一步是将 BigQuery 中的每个 Git 提交签名与 GHTorrent 中的一个用户 ID 相关联,前提是提交哈希相同。是时候让 Python 大放异彩了。这个长脚本生成了两个字典:`people`包含从用户 ID 到他们的名字集的映射,而`acc_membership`包含从帐户 ID 到上述用户 ID 的映射。这还不是我们想要的:我们如何过渡到我们的两个列表?通过随机分裂。在可能的情况下,我们将每个人的名字随机分成大小相等的两组。我们最终得到 338 对有名字的列表。总对数为 20882 对。对 GitHub 登录有一定程度的偏见,因为许多人在 Git 中输入它们的全名。此外,每对中的列表长度相等。然而,该数据集足以测试不同的模糊姓名匹配方法。示例(我替换了真实名称,保留了独特的属性):

["Dynatrace-VadimMarkovtsev"] - ["Vadim Markovtsev"]
["Vadim Markovtsev"] - ["DYNATRACE\vadim.markovtsev", "VadimM"]
["Vadim M."] - ["vmarkovtsev-dt"]
["Vadim Markovtsev"] - ["Dynatrace-Vadim-Markovtsev"]
["vadimmarkovtsev"] - ["Vadim Markovtsev"]
["Vadim Markovtsev", "Headless", "Vadim"] - ["mrkv-headless", "Markovtsev", "mrkv"]
["Vałim Mórkovtsev"] - ["Valim Morkovtsev"]


# 算法我最初的灵感来自这两篇博文: [Python 教程:模糊姓名匹配算法](/python-tutorial-fuzzy-name-matching-algorithms-7a6f43322cc5)和 [Python 教程:模糊姓名数据集的姓名查找表](/python-tutorial-a-name-lookup-table-for-fuzzy-name-data-sets-2580e4eca6e7)作者 [Felix Kuestahler](https://medium.com/u/15626f27740c?source=post_page-----6e738d6b8fe--------------------------------) 。它们是对这个主题的很好的介绍,也是数据驱动算法开发的一个很好的例子。为了总结他的帖子,Felix 提出了以下模糊姓名匹配计划:1.  规范化名称:处理 Unicode 异常,转换成小写,删除不相关的符号,折叠空格。用空格分割结果字符串,并将每个字符串转换成一个[双变音](http://aspell.net/metaphone/)。
2.  将名字的指纹定义为所有可能的变音组合。如果两个名字的指纹集有交集,则将它们之间的距离设置为零,否则设置为 1。
3.  贪婪地匹配配对:我们忽略可能的多个匹配。我将这些步骤概括为:1.  名称规范化。
2.  距离度量聚合。
3.  距离矩阵上的匹配。我建议在每个步骤中使用不同的方法和改进,并评估我的公共数据集的最终准确性。每个下一步越强大,它就越能掩盖每个上一步的缺点,所以我们应该独立地对它们进行基准测试。## 名称规范化有一个很棒的 Python 库可以规范化 Unicode 字符串,名为 [Unidecode](https://pypi.org/project/Unidecode/) 。我很自然地选择它来删除重音符号、元音变音、罕见字母和非典型的 Unicode 规范化。我们评估下面编码的三个选项。第一个函数完成了最简单的工作:删除任何不是字母、数字或空格的字符,并将几个空格合并成一个。第二个另外适用`unidecode`。第三个函数用空格分割第二个函数的结果,将每个部分转换成一个变音位,然后将它们连接起来。一个人有几个名字怎么办?我删除重复的,排序并把剩下的连接在一起。## 距离度量聚合同样,还有另一个伟大的 Python 库来计算两个字符串之间的相似性: [FuzzyWuzzy](https://github.com/seatgeek/fuzzywuzzy) 。它提供了几种算法,这些算法的不同之处在于它们的激进程度,即它们的精度与召回权衡值。*   `ratio`是传统的 [Levenshtein 距离](https://en.wikipedia.org/wiki/Levenshtein_distance)。
*   `token_sort_ratio`按空格分割,对部分排序,再连接起来,然后计算`ratio`。
*   `token_set_ratio`按空白分割,构建两组部分,找到交集和对称差,串联三个导数集合中每个集合的排序元素,将差字符串追加到交集字符串,选择最大值成对`ratio` ( [代码](https://github.com/seatgeek/fuzzywuzzy/blob/2188520502b86375cf2610b5100a56935417671f/fuzzywuzzy/fuzz.py#L135))。我们评估了五种距离计算方法。以下函数假设`s1`和`s2`源自归一化步骤。FuzzyWuzzy 返回从 0 到 100 的相似性度量,所以我必须从 100 中减去它,以假装我们计算了一个距离度量。我“假装”是因为距离度量有某些明确定义的标准,而三角形不等式并不总是成立的。幸运的是,这对我们的问题一点也不重要。`distance_join_ratio`在计算`ratio`之前清除所有空白字符。正如我后面要展示的,这很重要。`distance_max_ratio`详细阐述了`token_set_ratio`的思想:我取最少两个距离:令牌集比率和`distance_ratio_join`。## 距离矩阵上的匹配将第一个列表中的每个名字与第二个列表中的每个名字进行比较后,我们得到了一个距离矩阵。我们必须解决一个经典的[线性分配问题](https://en.wikipedia.org/wiki/Assignment_problem)(圈):> 问题实例有许多*代理*和许多*任务*。任何代理都可以被分配来执行任何任务,从而产生一些*成本*,这些成本可能因代理任务分配而异。要求执行尽可能多的任务,每个任务最多分配一个代理,每个代理最多分配一个任务,这样分配的*总成本*最小。几年前我写过一篇关于 LAP 的[博文,甚至在 GitHub](http://web.archive.org/web/20180611012448/https://blog.sourced.tech/post/lapjv//) 上发表了一个[开源 LAP 求解器(核心算法由 Jonker 和 Volgenant 提供)。所以没错,*又有一个很棒的 Python 库可以解决线性赋值问题。*](https://github.com/src-d/lapjv)我们评估两种距离矩阵匹配解决方案,贪婪选择和 LAP。贪婪求解器不需要明确的距离矩阵。`names1`和`names2`是规范化步骤的输出:两个列表中的规范化名称。`compare`是距离度量聚合步骤中的函数之一。重要提示:求解一个精确的圈在矩阵大小上具有立方复杂度。大约 10,000 后,经过的时间变得不切实际。# 估价让我们把所有的东西都放在一起。我提出了 3 个不同的归一化函数、5 个距离计算器和 2 个矩阵匹配器。它们总共有 3*5*2=30 种组合,我在第一部分的公共数据集上对这些组合进行了评估。代码如下:我计算准确度:有多少匹配的身份是正确的。我将进一步在私有数据集上设置一个置信度阈值,以召回换取精度。目前,下面的 3D 图表总结了 30 种组合,并有助于选择最佳组合:`unidecode`归一化、`max_ratio`距离,当然还有精度为 0.78 的`lap`解算器峰值。模糊名称匹配的准确性取决于规范化、距离和求解器类型。由 [@Miau_DB](https://twitter.com/Miau_DB) 可视化。令人惊讶的是,变音符号严重降低了准确性。变音排除了元音,结果丢弃了对下游匹配器有价值的信息。`unidecode`与`simple`相比并没有很大优势,但仍然是有益的。`max_ratio`距离胜出,这要归功于无序的部件集合和有序的部件连接序列的聚合,让人想起原始的集合。规格化和解算器相等,`distance_join_ratio`比`distance_set_ratio`更强大。贪婪的解决方案总是比单圈差,不出所料。我们必须选择第四个元参数——距离阈值。如果两个身份之间的估计距离大于该值,则该算法断定没有匹配,从而降低了召回率但提高了精确度。私人数据集是 10 对不同的人的身份列表,每个身份一个或多个名字。我修复了`unidecode`归一化、`distance_max_ratio`和 LAP solver,执行了匹配,并请我们在雅典的产品负责人 [Waren Long](https://medium.com/u/d535a1493d28?source=post_page-----6e738d6b8fe--------------------------------) 用他丰富的领域知识来评估结果。Waren 仔细检查了每一场比赛,并带回了一份令人信服的平均 F1 图。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4cad253942e53b1ec0e7ab5e8f8c63d2.png)F1 表示精确度和召回率之间的折衷。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0c28e42011a765f95dda6457d8550577.png)F1 取决于置信度阈值,由 [Waren Long](https://medium.com/u/d535a1493d28?source=post_page-----6e738d6b8fe--------------------------------) 评估。图片作者。该图表允许我选择 **0.5** 作为最佳距离阈值。我在整个组织中平均实现了 0.93 的精确度和 0.95 的召回率。# 名称匹配器我们来总结一下前面几节。1.  我定义了两个列表之间模糊人名匹配的问题,并强调了难点。
2.  我收集了两个数据集:一个来自 2016 年 GitHub 数据的公共数据集,一个来自[雅典](https://www.athenian.co/)的客户数据的私有数据集。
3.  我将模糊名称匹配算法定义为三个低级过程的序列:规范化、距离计算和分配问题解决方案。
4.  关于如何执行每一步,我考虑了几种选择。
5.  我在公共数据集上评估准确性,以选择最好的。
6.  我评估了私有数据集上的 F1 分数,以选择距离阈值来换取一些额外的精确度。我们雅典人在我们的作品中使用所描述的算法。我将开源核心提取到一个名为 [**的 Python 包中——matcher**](https://github.com/athenianco/names-matcher)。**名字匹配者**自诩对这篇博文中的主要观点做了一些额外的调整。也就是说,标准化步骤变得更加复杂;例如,我删除了由其他部分拼接而成的部分。此外,我删除了一些在私有数据集上“训练”的停用词。用户可以选择自己的停用词表。这些调整使我在公共数据集上的准确率进一步提高了+0.5%。我认为**名称匹配器**还可以进一步改进。请不要犹豫,把你的想法写在[期](https://github.com/athenianco/names-matcher/issues)里!如果你希望得到我下一篇文章的通知,请在 Twitter 上订阅 [@vadimlearning](https://twitter.com/vadimlearning) 。我借此机会感谢整个雅典团队帮助我创作,并感谢 Guillem Duran 的 3D 视觉效果。# 模糊字符串匹配算法> 原文:<https://towardsdatascience.com/fuzzy-string-matching-algorithms-e0d483c2a9ea?source=collection_archive---------3----------------------->## Levenshtein,语音![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/92e263db5b7c441c5b987dbf6bada84f.png)来自 Pixabay通常,相同的实体可以表示为不同的字符串。例如,同一个人的名字的似是而非的表达。比如*凯西*和*凯西*。或者是*乔纳森*和*乔纳森*。匹配和推断两个字符串是同一实体的似是而非的表达式有几个用例。例如在网络搜索和实体的去重复数据库中。形式上,模糊匹配问题是输入两个字符串并返回一个分数,该分数量化它们是同一实体的表达式的可能性。所以(*约翰*、*乔恩*)应该拿高分而不是(*约翰*、*简*)。几十年来,出现了各种模糊字符串匹配算法。他们有不同的长处和短处。这些分为两大类:词汇匹配和语音匹配。词法匹配算法基于某种错误模型来匹配两个字符串。通常,它们用于匹配因拼写或键入错误而不同的字符串。考虑*乔娜****th***T22an*乔娜***ht**T30an。词汇匹配算法将挑选出 ***ht*** 是***th*** 的换位。这种换位错误很常见。考虑到这一点,以及两个字符串的其余部分完全匹配并且足够长,我们应该给这个匹配打高分。语音匹配算法根据发音的相似程度来匹配字符串。考虑一下*凯西*和*凯西*。它们听起来非常相似,一个人可能拼成凯西,另一个拼成凯西。在这种情况下,一个不一定是另一个的拼写错误。只是听起来差不多。**词法匹配****动态编程算法**这个空间中的规范算法就是所谓的 Levenshtein 算法。首先,我们需要两个字符串之间*编辑距离*的概念。这是将一个字符串转换为另一个字符串所需的操作次数。允许的操作通常是*单字符替换、单字符插入*、*单字符删除*或相邻字符的*换位*。与其定义这些,不如让我们用例子来说明它们。

act → aet, act → actg, act → at, act → cat


第一个例子是替换,c → e,第二个例子是插入,g 在 t 之后,第三个例子是删除,c,第四个例子是转座 ac → ca。更精细的操作是可能的,尽管这会使计算编辑距离的算法变得复杂。在这篇文章中,我们将坚持使用这些方法。*举例*:考虑一下琴弦*大车*和 *crad* 。它们的编辑距离是 2,从下面可以看出。

cart → card → crad (E1)


**计算编辑距离**正如你可能从我们的例子(E1)中猜到的,计算编辑距离涉及一个重要的算法。我们必须以某种方式计算出将一个字符串转换成另一个字符串所需的最少的运算次数。Levenshtein 算法使用一种称为动态编程的算法技术。让我们来说明这个想法。如下。考虑两根弦*大车*和*小车*。它们的编辑距离是三(记住,我们放弃了换位操作)。我们将从左到右构建两个字符串,进行动态操作。(越少越好。)考虑在此过程中最后完成的操作。有三种可能。

1. We are at (car, crad) and append t to the former (this entails
one insertion).2. We are at (cart, cra) and append d to the latter (this entails
one insertion).3. We are at (car, cra) and append t to the former and a to the
latter (this entails one substitution because t and a are
different characters).


此外,这是唯一的三种可能性,直到插入和删除是对称的(我们不会详细说明这一点)。从 1-3 来看,(*小车*、*小车*)的编辑距离是一加上(*小车*、*小车*)、(*小车*、*小车*、*小车*、*小车*)的编辑距离中的最小值。(“一加”是因为在每种情况下,我们都要多做一次运算。)太好了。因此,现在我们可以计算两个字符串的前缀的编辑距离,并从中导出扩展字符串的编辑距离。长度为 *m* 和 *n* 的两个字符串的成对前缀的数量顺序为 *m* * *n* 。所以这些计算是必要的。对于较大的 *m* 或 *n* 有点慢。不过,还不错。**增强功能**几十年来,已经开发了各种增强功能。讨论它们,将有助于正式描述我们的设置。让 X 和 Y 表示我们试图计算其编辑距离的两个字符串。Levenshtein 算法的本质体现在下面的递归关系中。

D(i,j) = min(D(i, j-1) + 1, D(i-1, j) + 1, D(i-1, j-1) + S(X[i],Y[j])) (ED1


这里 D( *i* , *j* )分别是 X 的第一个 *i* 字母和 Y 的第一个 *j* 字母组成的字符串的编辑距离。X[ *i* 是 x 的第 *i* 个字符,如果 *a* 等于*b*S(*a*, *b* )等于 0,否则等于 1。把 S( *a* , *b* )看成是 *a* 和 *b* 之间的距离。考虑增强 S( *a* , *b* )。基于 *a* 是否等于 *b* ,我们可以分配一个数值距离来反映 *a* 被 *b* 取代的可能性,反之亦然。我们究竟如何确定 S( *a* , *b* )取决于用例。考虑对在计算机键盘上打字产生的替代错误进行建模。附近的键更有可能输入错误。因此,替换距离 S( *a* 、 *b* )与 *a* 和 *b* 的键盘距离成比例是有意义的,这是适当定义的。事实上,等式(ED1)允许 S( *a* , *b* )也是非对称的。接下来考虑等式(ED1)中的插入成本,当前设置为 1。考虑下面的增强版(ED1。

D(i,j) = min(D(i, j-1) + I(j), D(i-1, j) + I(i), D(i-1, j-1) + S(X[i],Y[j])) (ED2


等式(2)允许在位置 j 插入字符的成本,表示为 I( *j* ),不仅取决于位置 *j* ,还取决于被插入的值 X[ *j* ]。在蛋白质序列分析的一些用例中,这个特性非常有用[5]。**语音匹配**语音匹配方法通常为每个字符串生成一个语音关键字。一个字符串的键试图捕捉其发音的本质。具有相同关键字的两个字符串被视为匹配。这些算法在构造语音键的细节上有所不同。**Soundex**这个经典算法可以追溯到一百年前。它确实有很高的误报率,这意味着它可以将同一个键分配给不相关的字符串。然而,它被广泛使用,特别是在修剪模糊搜索问题的搜索空间时,对于这种问题,足够快且具有高召回率的适度假阳性率是可接受的。该算法生成的密钥由给定字符串的第一个字母组成,后面跟着 3 个数字,这些数字表示其发音的重要方面。在高水平上,元音之间的区别是模糊的(除了在第一个位置时)。就像在同一语境中发音相似的辅音之间的区别一样。让我们看一些例子。这些都是在[1]中尝试的。下面的对具有相同的密钥,如下所列。这些都不错。

Jack, Jach → J200, Joseph, Josef → J210, John, Jon → J500


杰克的钥匙也是 J200。这是相对于*插孔*的误报。*凯茜*和*凯茜*的钥匙不同,分别是 C300 和 K300。不理想。简和珍妮特分别有钥匙 J500 和 J530。很好,他们是不同的。另一方面,这也揭示了*乔恩*和*简*拥有同一个 key,J500,这是一个误报。**变音**这是一个比 Soundex 更新、更先进的算法。这有三种风格:基本(变音),更高级(双变音),甚至更高级(变音 3)。在这篇文章中,我们将我们的范围限制在变音。对其他口味感兴趣的读者可以参考[3]。让我们从看一些例子的变音键开始。这些都是通过在线服务[2]运行的。首先,让我们遍历那些我们期望它们的键是相同的对。

Steven, Stephen → STFN, John, Jon → JN, Cathy, Kathy → K0


很好。都工作了。还要注意,它捕捉到了 Soundex 错过的最后一对。另一方面,*杰克*和*杰克*拥有相同的密钥 JK。像 Soundex 一样,这是一个假阳性。让我们试试*简*和*珍妮特*。它们分别有键 JN 和 JNT。很好,他们不一样。也就是说, *John* 和 *Jane* 再次拥有相同的 key,JN,一个误报。有几点:1.  Metaphone 的音调肯定比 Soundex 的更容易解释,因为它们揭示了发音相似的辅音。在 Soundex 中,这些作为数字变得模糊不清。
2.  变音音的键有不同的长度。较长的单词往往有较长的键。让我们深入了解更多。想想史密森尼博物馆这个词。它的变音键是 SM0SNN。相比之下,它的 Soundex 键是 S532。*史密森*的 Soundex 键相同,即 S532。相比之下,*史密森*的变音键是 SM0SN,与史密森尼的不同。2)我们的研究表明,在长单词上,Metaphone 比 Soundex 更准确。**内部运作一瞥**下面我们将看看 Metaphone 中的一些规则,并尝试理解它们。他们揭示了明智的非平凡的选择。我们的列表不具有代表性,只是说明性的。让我们从

CK → K, PH → F


这些规则已经揭示了上下文的使用。比如 *PH* 换成 *F* 。当 *H* 前面没有 *P* 时,此规则不适用。这是变音音中另一个有趣的规则

If the string begins with KN, GN, PN, AE, or WR drop the first letter.


这是有道理的。在每一种情况下,第一个字母是不发音的。也就是说,当用来开始一个字符串时, *KN* 、 *GN* 、 *PN* 听起来像 *N* 、 *AE* 听起来像 *E* 、 *WR* 听起来像 *R* 。最后,考虑一下 Metaphone 中的这条规则。

If D is followed by GE, replace it by J.


这可以这样理解。 *DGE* 中的 *D* 听起来像 *J* 。如在*中做* ***dge*** 。**总结**在这篇文章中,我们介绍了一些近似匹配字符串的算法,即模糊匹配。我们主要关注两种方法:基于动态编程的方法和基于语音匹配的方法。**延伸阅读**1.  [在线测试 soundex—PHP 字符串函数](https://www.functions-online.com/soundex.html)
2.  toolpage.org[变音发生器](https://en.toolpage.org/tool/metaphone)
3.  [变音——维基百科](https://en.wikipedia.org/wiki/Metaphone)
4.  [Levenshtein distance —维基百科](https://en.wikipedia.org/wiki/Levenshtein_distance)
5.  [https://en . Wikipedia . org/wiki/Smith % E2 % 80% 93 waterman _ algorithm](https://en.wikipedia.org/wiki/Smith%E2%80%93Waterman_algorithm)# 使用 Python 进行模糊字符串匹配> 原文:<https://towardsdatascience.com/fuzzy-string-matching-using-python-e0d1ff142dd0?source=collection_archive---------34----------------------->## 在本文中,我们将探索如何使用 Python 执行模糊字符串匹配。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/163dfe338ab583a36b601b0d83fde721.png)在 [Unsplash](https://unsplash.com/s/photos/matching-colors?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上由[S O C I A L C U T](https://unsplash.com/@socialcut?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)拍摄**目录***   介绍
*   莱文斯坦距离
*   简单模糊字符串匹配
*   部分模糊字符串匹配
*   无序模糊字符串匹配
*   结论# 介绍当处理字符串匹配或文本分析时,我们经常希望在一些变量或文本中找到匹配的部分。我们自己看文字就知道*多伦多机场*和*多伦多机场*指的是同一个东西,而 *Torotno* 只是拼错了*多伦多*。但是我们如何通过编程解决这个问题,并让 Python 识别这些情况呢?我们使用模糊字符串匹配!为了继续学习本教程,我们需要以下 Python 库:fuzzywuzzy 和 python-Levenshtein。如果您没有安装它,请打开“命令提示符”(在 Windows 上)并使用以下代码安装它:

pip install fuzzywuzzy
pip install python-Levenshtein


# 莱文斯坦距离为了理解字符串匹配背后的底层计算,让我们讨论一下 Levenshtein 距离。在计算机科学中,Levenshtein 距离是两个序列(在我们的例子中是字符串)之间相似性的度量。它通常被称为“编辑距离”。为什么简单地说,它计算两个字符串之间应该发生的最小编辑次数,以使它们相同。现在,需要编辑的次数越少,两个字符串就越相似。要了解关于 Levenshtein 距离及其计算的更多信息,请查看本文。# 简单模糊字符串匹配fuzzywuzzy 库中的简单比率方法计算两个字符串之间的标准 Levenshtein 距离相似性比率,这是使用 Python 进行模糊字符串匹配的过程。假设我们有两个非常相似的单词(有些拼写错误): *Airport* 和 *Airprot* 。仅仅看这些,我们就能知道除了拼写错误之外,它们可能是一样的。现在,让我们尝试使用简单的比率字符串匹配来量化相似性:我们得到了:

86


因此,计算出的两个单词之间的相似度是 86%,对于一个拼写错误的单词来说,这是相当不错的。这种方法适用于短字符串和长度相对相似的字符串,但不适用于不同长度的字符串。例如,您认为*机场*和*多伦多机场*的相似之处会是什么?实际上比你想象的要低:我们得到了:

64


这里发生的是,绳子长度的差异起了作用。幸运的是,fuzzywuzzy 图书馆有一个解决方案:**。【partial _ ratio()方法。**# 部分模糊字符串匹配回想一下上一节,当比较*机场*和*多伦多机场*时,我们通过简单的字符串匹配只得到 64%的相似度。事实上,在这两种情况下,我们指的是一个机场,这也是我们作为读者将会看到的。由于字符串的长度差异很大,我们应该进行部分字符串匹配。我们感兴趣的是一个较短的字符串和一个较长的字符串的最佳匹配。逻辑上是怎么运作的?考虑两串:*机场*和*多伦多机场*。我们可以马上看出第一个字符串是第二个字符串的子字符串,即 *Airport* 是 *Toronto Airport* 的子字符串,这是一个完美的匹配:我们得到了:

100


# 无序模糊字符串匹配我们在处理字符串时可能会遇到的一个常见问题是单词的顺序。例如,您认为多伦多*机场*与多伦多*机场*有多相似?100%?使用上述部分的技术,我们发现结果低得惊人:我们得到了:

47
48


这可能比你预期的要低得多?只有 47%-48%。我们发现不仅子串的相似度很重要,它们的顺序也很重要。# 相同长度的字符串对于这种情况,fuzzywuzzy 库有一个解决方案:**。token_sort_ratio()** 方法。它所做的是将字符串标记化,然后按字母顺序对标记进行排序,然后进行字符串匹配。在我们的例子中,标记*多伦多机场*将保持同样的方式,但是标记*多伦多机场*将按字母顺序排列子字符串以得到*多伦多机场*。现在我们正在比较*多伦多机场*和*多伦多机场*,你可以猜测我们可能会得到 100%的相似性:我们得到了:

100


# 不同长度的字符串对于这种情况,fuzzywuzzy 库有一个解决方案:**。token_set_ratio()** 方法。它所做的是将字符串标记化,然后分成[交集]和[余数],然后按字母顺序对每个组中的字符串进行排序,然后进行字符串匹配。考虑两串:*多伦多机场*和*多伦多机场关闭*。在这种情况下,[交叉点]组将是*机场*,第一串的[剩余部分]将是空的,第二串的[剩余部分]将是*关闭的*。从逻辑上讲,我们可以看到,具有较大[交集]组的字符串对的得分会更高,因为将会有完美的匹配,并且可变性来自[剩余]组的比较:我们得到了:

100


# 结论在本文中,我们探讨了如何使用 Python 执行模糊字符串匹配。我也鼓励你看看我关于 [Python 编程](https://pyshark.com/category/python-programming/)的其他帖子。如果你有任何问题或者对编辑有任何建议,请在下面留下你的评论。*原载于 2021 年 2 月 6 日 https://pyshark.com*<https://pyshark.com/fuzzy-string-matching-using-python/>**。**# 模糊系统:生活在 1 和 0 之间> 原文:<https://towardsdatascience.com/fuzzy-systems-life-between-the-1s-and-0s-949de445f58e?source=collection_archive---------14----------------------->## AI 可以模糊,我们来看三种方式模糊系统是计算智能的一个分支,希望表现模糊、不确定世界的不确定性。模糊系统在人类语言的不精确性中找到了灵感。模糊系统因模糊逻辑而广为人知,在本文中,我们将深入探讨模糊规则库、模糊控制和模糊积分。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3a12e2849c93e05c0c66ea4c1fac7699.png)[Gradienta](https://unsplash.com/@gradienta?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片# 动机计算智能汇集了三个分支的主题——进化计算、神经网络和模糊系统。在以前的文章中,我已经讨论了前两个,但是在这篇文章中,我将介绍模糊系统的三个不同领域。在标准数学中,我们只能将项目表示为完全属于一个组(或集合)。“是还是不是”的问题完美的凸显了这个概念。在许多情况下,我们可以在一个框架中表示世界,在这个框架中,元素完全属于一个组。动物提供了另一个例子——有些东西不能同时既是马又是牛。不幸的是,在一个不总是非黑即白的世界里,这个框架是不够的。模糊系统提供了一套替代的数学方法来处理具有许多不同颜色的许多不同阴影的宇宙中的灰色。这篇文章将强调计算智能的模糊分支中的三个特定主题——模糊规则库、模糊控制和模糊积分。# 模糊规则库![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/64ea26b9473f68ff907be9df7f9a0a64.png)照片由[乔尔·穆尼斯](https://unsplash.com/@jmuniz?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄模糊规则库是模糊规则的集合。最基本的描述是,模糊规则是一个 if-then 语句,它包含一组导致结果的前提条件。在研究了术语之后,我发现模糊规则类似于我每天做决定的方式。如果我问你这个问题,“你高吗?”在你回答之前,你必须对“高”的定义有所了解。你可能会考虑你相对于特定人群的身高。例如,我比蹒跚学步的孩子高,但比 NBA 球员矮。当我们试图用数学来表示“高”的时候,这就产生了一个问题。传统数学通过定义任何高于 5 英尺 11 英寸的东西为高,任何低于 5 英尺 11 英寸的东西为矮来划分界限。然而,我们可以用模糊隶属值更好地表示这种类型的数据。模糊隶属值允许元素部分地属于一个组。隶属度(或特征)函数定义一个项目“有多少”属于一个集合,其中值在 0(无隶属度)和 1(完全隶属度)之间。考虑下图。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/37b33297187edc98f10dffb07accf239.png)隶属函数示例。图片作者。在 x 轴上,我们有某人身高的原始值,在 y 轴上,我们有我们的成员值(或者他们属于高个子人群的程度)。所以,当我们的高度为 5 '时,我们的隶属值为 0.2。如果我们的身高是 5 英尺 8 英寸,那么我们的隶属值就是 1。既然我们理解了一个隶属值,我们就可以讨论它对模糊规则的影响了。模糊规则与传统的 if-then 规则没有太大区别;然而,有一个重要的区别。前因(或导致结果的条件)是模糊值。之前的逻辑适用于离散的情况,比如“如果动物是熊,那就跑。”这种动物不能同时既是熊又不是熊。但是,如果我们说,“如果天冷,那就穿件外套”,这种传统逻辑就站不住脚了冷的概念不容易定义,所以我们需要用光谱来表示它(就像我们之前的隶属函数图像)。将这种想法扩展到考虑模糊规则库是非常简单的。模糊规则库是模糊规则的集合。如果这个概念看起来很容易掌握,很好!模糊逻辑应该是直观的,因为它更好地代表了我们的模糊世界。当我们定义隶属函数时,它变得很复杂(或者来自专家,数据驱动的方法,或者两者的结合)。然而,我发现这个框架在将数据翻译给对数据的低级解释不感兴趣的人时非常有效——它们使我的数据工作更容易被最终用户访问。# 模糊控制![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/04a3ae4837f5e5b3b9c7ad83afaee720.png)照片由[斯潘塞·阿奎迈德斯](https://unsplash.com/@spencerarquimedes?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄我将在本节开始时说明,我不是控制理论或模糊控制方面的专家,但是,从高层次来看,它似乎并不太复杂。控制理论处理系统(例如,机器人)的某些方面的自动化过程,以确保它在正确的时间处于正确的状态。控制器驱动系统以确保一切正常。本质上,控制器是一种应用系统规则的算法。在我家,我通常充当控制者(告诉 Alexa 做什么)。“Alexa,打开客厅灯”,灯就亮了。这个理论的二元性限制了它在模糊空间中的适用性。例如,用这种简化的控制理论框架来调暗灯光是不可能的。现在我们已经理解了模糊规则(从上一节开始),我们可以看到将这个框架应用于控制理论是多么简单。注意——可能有许多方法来处理这种类型的控制问题,但我强调模糊理论,因为这是一个关于模糊系统的帖子。模糊控制在多种应用中找到了归宿,不难想象为什么。我们可以直接将模糊规则注入控制器,以创建一个由模糊规则控制的系统。你通常什么时候开关空调或加热器?天气热或冷的时候。这些词听起来像模糊的词,我们可以建立隶属函数来定义它们。“热”打开空调或关闭加热器。根据一年中的不同时间,我们可能有不同的隶属函数来定义“热”这个词你能想到你会使用模糊控制器的其他领域吗?# 模糊积分类似于我在 [EC](/a-hidden-gem-of-ci-evolutionary-computation-ef8d5e815344) 和 [NNs](/neural-networks-more-than-deep-learning-a0c9e1629781) 上的帖子,我们不能将 CI 分支简化为一组三个算法。相反,我突出了那些我觉得有趣或有价值的。最后一部分解释了模糊积分——这是我花了 5 年多时间专门研究的一个领域。在一篇典型的学术论文[1,2,3]中,我会这样开头:“模糊积分是一个强大的非线性聚集算子。”但是,我们将跳过底层术语,直接进入它如何工作以及为什么它如此强大的核心部分。模糊积分(也称为 Choquet 积分)算法学习一组权重来融合一组输入,以获得单个输出。我们通常在分类和回归算法中使用它。我通常通过将模糊积分(又名 Choquet 积分)描绘成一个格子来直观地解释它(如下图所示)。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/92a1dc9989ec307af0dc1fd2a97d6527.png)作者图片我们从网格的底部开始,在那里我们看到三个输入(X1、X2 和 X3)。我们从单个输入开始,随着我们沿着网格向上走,我们在每个节点积累源(或输入)。值得注意的是,我们每层只考虑一个节点,因为网格上的每个组合代表不同的融合。我已经突出显示了一个沿网格向上的单个行走(蓝色),但它是每个想象我们可以触摸的节点的各种组合。你应该问自己,“我们怎么知道该走哪条路?”这是基础数学的一个关键特征。该算法在评估之前对输入进行排序,它们的排序顺序决定了它们的行走。我们强加在这个算法上的约束允许多种程度的解释。我们使用了 Shapley 值(在它们击中 NN 包之前)和相互作用指数。更重要的是,Choquet 积分是可解释的(将输入直接映射到输出),因此我们可以在许多层面上做出解释。我计划深入研究这个主题(通过代码),展示我们如何融合七个深度卷积神经网络来产生更好的分类精度(敬请关注),并提供解释。但是,我要举一个更简单的例子——我遛狗。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0baf183332d354a4edb0d2c430da8d38.png)图片作者。想想海蒂(金色)、汉克(黑色)和我(人类)的形象;) ).他们最喜欢的活动之一是去散步。我们可以回答这个问题,当汉克走 1 英里,海蒂走 10 英里,我走 3 英里时,这三个人走得有多快?为了融合这些数据点,我们可以为每个节点分配一个权重。我们不仅可以得到每个速度组合的输出,还可以使用 XAI 技术来提取信息,以确定每个来源的重要性。Choquet 积分对输入的互补性和冗余性进行建模,因此这个例子非常适用(因为 Heidi 和 Hank 不擅长走路)。我已经手动定义了权重,但是有许多方法可以从数据中学习这些值(参见其中一个参考文献)。# 结论我写过一篇关于[神经网络](/neural-networks-more-than-deep-learning-a0c9e1629781)、[进化计算](/a-hidden-gem-of-ci-evolutionary-computation-ef8d5e815344)的帖子,现在是模糊系统。我认为有一些事情要说,这个主题是多么简单,以高水平来写。很难解释神经网络的基础数学是由它们利用链式法则通过反向传播来学习数百万个权重的能力来驱动的。很拗口。虽然比较不是苹果与苹果之间的比较,但我发现模糊系统更容易讨论,因为它们确实实现了(在某种程度上)我在日常生活中经历的推理。我已经说服自己,我的大部分行为只是在考虑许多模糊的规则。我的内部对话框通常是这样的:> “我会加油吗?”
> 
> “我快空了。”
> 
> “我会得到多少?”
> 
> "我的账户里有足够的钱。"
> 
> “我会一路加满。”当然,人类可以基于上下文动态地改变底层的隶属函数。尽管如此,我还是忍不住认为模糊系统是我们“人工智能”更深层推理的发射台。但是,我们如何动态地学习这些隶属函数呢?也许是神经网络?也许“CI”终究是真正的“AI”。# 参考[1]https://ieeexplore.ieee.org/document/9149954/[2][https://ieeexplore.ieee.org/document/8491501](https://ieeexplore.ieee.org/document/8491501)[https://ieeexplore.ieee.org/document/9494563](https://ieeexplore.ieee.org/document/9494563)# Fuzzywuzzy:合并不同转录名称的数据集> 原文:<https://towardsdatascience.com/fuzzywuzzy-basica-and-merging-datasets-on-names-with-different-transcriptions-e2bb6e179fbf?source=collection_archive---------13----------------------->## 使用词向量距离比较字符串相似度的模糊匹配![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2dc61d22f00ceb573b636fdf3158dad3.png)安娜斯塔西娅·切平斯卡在 Unsplash 上拍摄的照片我最近做了一个项目,涉及到合并同一个人的姓名的数据集,这些姓名的转录略有不同。一些名字拼写错误,包括昵称、中间名或后缀,它们在数据集之间不匹配。在本例中,我使用了一个字符串匹配包 [Fuzzywuzzy](https://pypi.org/project/fuzzywuzzy/) 来合并正确的名称。为了省去你很多我在合并前做的额外工作,我想解释一下你可以使用的 [**Fuzzywuzzy**](https://pypi.org/project/fuzzywuzzy/) 的模块、方法和用途。# 模糊的距离计算Fuzzywuzzy 使用 Levenshtein distance 来计算距离,简单来说,它决定了需要对字符串中的每个字符进行多少次更改才能找到另一个单词。例如,“dog”和“dogs”需要一个变化:添加“s”。而“dog”和“dig”也需要一个变化:替换一个字母。而将“start”改为“tarp”将会有两处改动:删除“s”并用“t”代替“p”。在实现 one names 的计算时需要注意的一点是,在词根发生变化的情况下,将名字与昵称进行比较时会有困难。例如,“Bobby”和“Robert”需要大量的更改,可能会导致其他不相关的名称出现为更好的匹配。# **模糊不清的模块和方法**Fuzzywuzzy 有两个模块:`process`和`fuzz`。## 绒毛返回字符串的相似率,在 0-100 之间,最基本、最精确的方法是`fuzz.ratio()`。1.  `fuzz.partial_ratio()`将一个字符串与较长字符串中长度相等的子字符串进行比较。例如:`**fuzz.partial_ratio(‘Dogs’, ‘Dog’)**`会有一个 **100 的部分 _ 比率**,但只会有一个 **86** 与`**fuzz.ratio()**`。2.`fuzz.token_sort_ratio()`不考虑顺序测量字符串,您可以从包含单词 **sort** 中猜到这一点。这在比较不同顺序的姓名时很有用,例如,比较**姓**、**名**与**名**、姓。3.`token_set_ratio()`,你可以从`.token_sort_ratio`中猜到,把每一个令牌做一套来比较。重复的话不会影响比例。如果我们在歌名列表中查找歌曲,其中一首歌曲名为**谁放出了狗**,而我们想要匹配的歌曲名为**谁放出了狗,谁,谁,谁**,我们将获得 **100 的比率分数。**## 过程基于比率抓取最相似的单词。1.  `process.extract()`和`process.extractOne()`将从字符串列表中取出最相似的(extractOne)或 n 个最相似的(extract(limit = n))单词与你给定的字符串进行比较。# 与 Fuzzywuzzy 的过程融合在我的合并过程中的这一点上,我已经将我的一个数据集中的名称重新排序为与我的第二个数据集相同的顺序,所以我在我的过程中没有使用`fuzz`。现在我们知道,在未来的尝试中,我们不必这样做。首先,安装您正在使用的软件包和模块。

# pip install fuzzywuzzy from fuzzywuzzy import process


为了合并名称,我在要合并的数据帧中创建了一组名称,称为`names`,并在第二个数据帧中创建了一组要比较的名称:`member_names`。然后我做了一个字典,里面有与`names`最接近的两个匹配项,这样我就可以手动检查分数,看名字匹配是否正确。

make a dictionary of closest matches to names keys = {}for name in names: #names in smaller dataset to compare and match**#get closest match of name compared to larger data member_nameskeys[name] = ((process.extract(name, member_names, limit=2)))#you can limit to 1 with extractOne to take less time but I wanted to check if names were returning as correct.


下面是`keys`返回的前 5 行。

Robert J. Wittman [('J Cox', 86), ('Rob Wittman', 86)]
James R. Langevin [('James Risch', 86), ('James Comer', 86)]
Gerald E. Connolly [('Gerry Connolly', 75), ('J Cox', 54)]
Kathy Manning [('Kay Granger', 58), ('Kathy Castor', 56)]
Michael K. Simpson [('Mike Simpson', 86), ('Michael Waltz', 66)]


正如您所看到的,最匹配的名字并不完美,所以从这一点上,我过滤并检查了不匹配的名字。我查了比率低于或等于 86%的名字。

#checking names that might not match correctlyfor name in keys:
if keys[name][0][1] <= 86: * #this gives the second value in the first tuple, which is the score of the first name*

print(name, keys[name])

此时,您可以将您的限制扩展到 2 个以上,因为我的一些匹配项的比率较低。找到正确的参数后,您可以为没有匹配项的名称创建一个列表,在不同的索引处有匹配项,并迭代字典值以创建一个合并关键字过滤列表中的名称,如果需要的话:

no_match = ['Michael Enzi', 'Kathy Manning', 'John Hickenlooper', 'William Hagerty', 'cott Franklin', 'Victoria Spartz',
'Marjorie Taylor Greene', 'Marie Newman', 'eter Meijer', 'David Cheston Rouzer', 'Robert "Bobby" Scott']

second_match = ['Mitchell Mcconnell, Jr.', 'Harold Dallas Rogers', 'Neal Patrick Dunn MD, FACS']


下面,我提供了匹配代码的简化版本来生成 merge_keys:

getting list of the matches from the bigger dataset to the smaller one as keys to merge onmerge_key = [keys[name][1][0] if

                  name **in** second_match \**else** **None** **if** name **in** no_match **else**keys[name][0][0] **for** name **in \** df['name']]df[‘merge_key’] = merge_keydf.merge(second_df, how = ‘left’, left_on = ‘merge_key’, right_on=’member_names’)

现在你知道了!如果愿意,您可以覆盖任一数据集中的原始列,但是我希望保留原始数据集中的原始名称,以及我希望用于合并第二个数据集中的名称。感谢阅读,我希望它是有帮助的!你可以阅读更多关于 fuzzywuzzy 的内容,或者在这里下载。# 模糊不清——之前和之后> 原文:<https://towardsdatascience.com/fuzzywuzzy-the-before-and-after-c3661ea62ef8?source=collection_archive---------45----------------------->## 关于数据预处理,选择适当的模糊函数,并处理结果![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/140fa642e958fa725bb5d737bd5d8232.png)娜塔莉·格兰杰在 [unsplash](http://www.unsplash.com) 上拍摄的图片在之前的[文章](https://medium.com/naomikriger/string-comparison-is-easy-with-fuzzywuzzy-library-611cc1888d97)中,我介绍了 FuzzyWuzzy 库,它为一对字符串计算 0-100 的匹配分数。不同的模糊不清的功能使我们能够选择一个最符合我们需要的。然而,进行一个成功的项目不仅仅是计算分数。我们需要在开始处理数据之前清理数据,选择计算分数的最佳方法,学习如何不仅处理一对字符串,还处理数据表,并最终知道如何使用我们收到的分数来充分利用我们的结果。所以,事不宜迟,让我们深入了解一些我们应该熟悉的最佳实践。## 使用包含熊猫的表格来比较多个字符串如前所述,FuzzyWuzzy 函数计算两个字符串的匹配分数。但是当处理“真实生活”的数据时,我们可能需要比较至少两组字符串。这意味着使用表格,或者用熊猫的术语来说——使用数据框架。一个好的表格应该是这样的:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/526c77c05e7b23cad0af3e377eb645b7.png)上表包含两个比较列,每个列都有一个相关的标题,其中要比较的字符串位于平行的行中。给定这样一个数据集,我们可以使用相关函数将表读入数据帧。下面的例子直接从 CSV 读取,但是如果您对使用其他格式感兴趣,您可以查看下面的[文档](https://pandas.pydata.org/pandas-docs/stable/reference/io.html)。

my_data_frame = pd.read_csv("my_folder/my_file_name.csv")


## 数据预处理—在分析前清理数据在我们选择 FuzzyWuzzy 函数并开始比较字符串之前,我们希望清理数据以确保我们的结果尽可能准确。清理数据意味着删除不相关的字符串,从而提高函数的性能。例如,假设我们比较两个地址的字符串,其中一个地址是“Joe Boulevard”,另一个是“Jule Boulevard”。匹配分数会相对较高,但大多是因为两个字符串中都存在“Boulevard”。删除它并重新计算将导致低得多的匹配分数:

fuzz.ratio("Joe Boulevard", "Jule Boulevard")
89
fuzz.ratio("Joe", "Jule")
57


数据所需的清理类型取决于您的域。我们看到了一个地址清理的例子。类似地,在比较电话号码时,我们可能会想要删除没有附加值的括号和破折号。还建议将所有字符串规范化为小写,因为一些 FuzzyWuzzy 函数将大写字母不同的字母视为不同的字符串。
所以,看看你的数据,决定什么应该被修改,以使其干净并准备好处理。## 数据预处理——让我们来看看技术现在,让我们用相关逻辑定义一个函数,并在数据帧中的每个相关列上迭代运行它。**为了解释清楚,下面的示例已经过简化。为了获得最佳结果,建议使用正则表达式(regex ),这超出了本文的范围。请注意,当前形式的 *strings_to_remove* 可能会导致清理后的结果不完美。

strings_to_remove = [" ave ", " ave. ", "avenue", " lane ",
" ln ", "blvd", "boulevard", " rd. ", "road", "street", " st. ",
" str ", " dr. ", "drive", " apt ", "apartment", "valley", "city", ".", ","]

comparison_table =
comparison_table.astype(str).apply(lambda x: x.str.lower())>>> for current_string in strings_to_remove:
comparison_table = comparison_table.astype(str).apply(
lambda x: x.str.replace(current_string, ' '))

comparison_table = comparison_table.astype(str).apply(
lambda x: x.str.replace(' +', ' '))


然后——瞧!![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ad73effbdbf64d7c32adde5511f2656e.png)## 添加分数栏并进行比较现在剩下的就是向数据帧添加一个名为“score”的空列,使用我们选择的 FuzzyWuzzy 函数
计算匹配的分数,并用这些分数填充数据帧。这是一个如何做到这一点的例子

comparison_table["score"] = "">>> comparison_table['score'] =
comparison_table.apply(lambda row:
fuzz.token_set_ratio(row['col_a_addresses'], row['col_b_addresses']),axis=1)


让我们将结果与我们在未处理的数据帧上运行 FuzzyWuzzy 函数所得到的结果进行比较:清洁前-![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/26bc3b6b1482352cf4006f97a3912d27.png)清洁后-![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0fae071bb493a92b31a258b84886ad4a.png)***那么,清洗完数据后,实际发生了什么?*** 匹配分数变得更加准确——根据清洗情况增加或减少。*   *让我们看看清洁后得分下降的第 3 行。*在这种情况下——清理前两个地址都出现的单词“Lane”错误地增加了匹配分数。但是删除之后,我们发现地址并不相似。
*   *让我们看看第 9 行,清洁后得分增加了。*而“巷”和“巷”有相同的意思,它们是大小写不同的不同字符串。清除噪声后,我们能够获得更好的分数,更准确地反映这些字符串之间的相似性水平。
*   有趣的是,第 9 行中清理过的字符串并不相同。“85”只出现在 *col_b_addresses* 中,但匹配分数是 100。为什么?因为字符串“足够接近”而被算法确定为完全匹配。如果由人类来做,这个决定可能也是一样的。## 简而言之,选择一个模糊的函数选择最佳 FuzzyWuzzy 函数的一种方法是基于不同函数的逻辑/目的,并确定哪个函数似乎与您的目的最相关。但是,如果您不能决定哪个函数可以检索最准确的结果,您可以进行一个小的研究来确定使用什么。我推荐使用的方法是对数据集进行采样,并对其运行每个相关的函数。然后,对于每个结果,手动决定每行中的值是真阳性/假阳性/真阴性/假阴性。完成后,您可以选择 TP/FP 率最令人满意的地方,或者继续计算准确度*和灵敏度*,并使用这些值做出决定。对于每个项目,我们的目标可能不同,我们愿意接受的假阳性/真阴性率也不同。*准确性和敏感性都用于数据科学,超出了本文的范围。这些公式都可以在网上找到。## 选择阈值分数—简而言之我的一对字符串返回了 82 的匹配分数。好吃吗?很糟糕吗?答案取决于我们的目标,并且有许多相关的问题要问,例如:我们是对彼此非常相似的字符串感兴趣,还是对不同的字符串感兴趣?我们愿意接受的最大假阳性率是多少?我们想要的最小真阳性率是多少?对于同一组字符串,我们可以得出两个不同的阈值分数——相似字符串的最低分数(例如 85),不同字符串的最高分数(例如 72)。
这些阈值分数之间可能存在一个完整的范围,这将注定是“不确定的”。有不同的方法来定义阈值分数,我们不会在本文中深入探讨它们。然而,我要提到的是,选择阈值分数将需要一些手动工作,类似于上面提到的关于如何选择最佳 FuzzyWuzzy 函数的工作——获取一组具有最终分数的样本字符串,确定结果的真阳性和假阳性,并最终决定我们的阈值。使用 FuzzyWuzzy 进行字符串比较,以及预处理数据,并最终分析结果是一项令人着迷的工作。总是有更多的事情要做,并且有不同的方法来改进这个过程。在本文中,我们探索了一些让这个过程变得有用和舒适的实践。我希望本系列对您有所帮助和启发,并且现在您已经为下一个面向数据的项目准备了更好的工具。# R 中用蒙特卡罗方法模拟 Gacha> 原文:<https://towardsdatascience.com/gacha-simulation-using-monte-carlo-method-in-r-3897ce611458?source=collection_archive---------28----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2c3b7f78a421cacbf37b9ce4583c3826.png)[C M](https://unsplash.com/@ubahnverleih?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍照## 不是运气。概率就是这样的。## 动机蒙特卡罗模拟方法是模拟理论中最流行的方法之一,它依靠重复随机抽样来获得期望的数值结果。这种方法有很多应用,如 A/B 检验、从贝叶斯推断的后验分布中模拟随机样本、期权定价、风险分析等等。另一方面,手机游戏近年来变得越来越受欢迎,其中一个主要功能是向玩家提供兑换某种稀有物品或角色的能力。这个特征通常被称为*嘎查*。在这篇文章中,我将解释如何应用蒙特卡罗方法来模拟你将使用 r 得到的 gacha。## 概念:蒙特卡罗模拟法蒙特卡洛方法的思想是利用随机性来解决通常(原则上)是确定性的问题。具体来说,在进行模拟时,蒙特卡罗方法的过程可以解释如下。1.  定义可能输入的域和每个输入的频率,
2.  根据输入计算概率密度函数(PDF ),
3.  从 pdf 中计算累积密度函数(CDF),
4.  生成均匀分布在(0,1)中的随机数,
5.  基于 CDF 将随机数值指定为输入之一,
6.  重复步骤 4 和 5,直到达到所需数量的模拟结果。为了在实践中更好地理解这种方法,这里我将实现蒙特卡罗方法来模拟您将得到的 gacha。我将在这里使用的编程语言是 r。## 履行假设我们想要模拟的 gacha 系统遵循这些规则:1.  可用物品稀有度为 3、4 和 5 级(通常分别表示为 3 星、4 星和 5 星)。我们将使用它们作为我们可能输入的域。
2.  对于 3 级、4 级和 5 级稀有物品,该物品在一次投掷中获得的概率分别为 0.945、0.05 和 0.005。
3.  如果在连续 9 次掷骰中,玩家还没有获得 4 级稀有物品,那么第 10 次掷骰将保证玩家获得 4 级稀有物品。这个卷通常被称为**怜悯卷**。
4.  如果在连续 89 次掷骰中,玩家还没有获得 5 级稀有物品,那么第 90 次掷骰将保证玩家获得 5 级稀有物品。根据上面的规则,我们可以如下创建每个卷的 PDF。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/330e665beecb95fe789f7fe16987f67e.png)其中 x 表示该物品的稀有程度。从上面的 PDF 中,我们可以创建逆 CDF 来将均匀分布在(0,1)中的随机数分配给每个稀有级别,如下所示。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/87d6d9c2cdc6f6c47aee71af920e6d27.png)其中 u 表示均匀分布在(0,1)中的生成的随机数。请记住,上面的逆 CDF 不包括 4 级和 5 级稀有物品的同情骰,因为它只计算一次。然后,我们用这几行代码编写函数来模拟 gacha 过程。蒙特卡洛模拟嘎查,代码由作者编写让我们通过运行 50 次 gacha roll 模拟来尝试上面的代码。结果如下(**注意,每次运行模拟**的结果可能不同)。

x=runif(50)
rarity=3:5
PDF=c(0.945,0.05,0.005)
sim=mc.sim(x,rarity,PDF)
Gacha Simulation Table
rarity PDF CDF
1 3 0.945 0.945
2 4 0.050 0.995
3 5 0.005 1.000The 1 th roll produces : 3 star rarity item.
The 2 th roll produces : 3 star rarity item.
The 3 th roll produces : 3 star rarity item.
The 4 th roll produces : 3 star rarity item.
The 5 th roll produces : 3 star rarity item.
...
The 46 th roll produces : 3 star rarity item.
The 47 th roll produces : 3 star rarity item.
The 48 th roll produces : 3 star rarity item.
The 49 th roll produces : 4 star rarity item.
The 50 th roll produces : 3 star rarity item.
table(sim)
sim
3 4
44 6


从上面的模拟中我们可以看到,我们获得了 6 个 4 星稀有项目,对于 gacha 游戏的初学者来说还不错!让我们把它增加到 70 次模拟,看看有什么不同。

x=runif(70)
rarity=3:5
PDF=c(0.945,0.05,0.005)
sim=mc.sim(x,rarity,PDF)
Gacha Simulation Table
rarity PDF CDF
1 3 0.945 0.945
2 4 0.050 0.995
3 5 0.005 1.000The 1 th roll produces : 4 star rarity item.
The 2 th roll produces : 3 star rarity item.
The 3 th roll produces : 3 star rarity item.
The 4 th roll produces : 3 star rarity item.
The 5 th roll produces : 3 star rarity item.
...
The 16 th roll produces : 3 star rarity item.
The 17 th roll produces : 5 star rarity item.
The 18 th roll produces : 3 star rarity item.
...
The 66 th roll produces : 3 star rarity item.
The 67 th roll produces : 3 star rarity item.
The 68 th roll produces : 3 star rarity item.
The 69 th roll produces : 3 star rarity item.
The 70 th roll produces : 3 star rarity item.
table(sim)
sim
3 4 5
61 8 1


伟大的结果!1 件五星级稀有品和 8 件四星级稀有品,这就是我们所说的好嘎查!## 结论我们到了。本文解释了蒙特卡罗方法在模拟理论中的许多实现之一,您可以在其他领域中实现它,如风险度量、期权定价等等。像往常一样,如果您有任何问题,请随时提问和/或讨论!我的下一篇文章再见!保持安全,保持健康!![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5bc2c59b4facde9bbd852fc56a1a2df2.png)可能发生在你读完这篇文章之后(图片来自 [Imgflip](https://imgflip.com/i/59fhrf)## 作者的联系人领英:[拉登·奥勒留和希卡·维亚迪努格罗霍](https://www.linkedin.com/in/raden-aurelius-andhika-viadinugroho-b84b19163/)中:[https://medium.com/@radenaurelius](https://medium.com/@radenaurelius)## 参考[1] Enrico,Z. (2013 年)。 [*系统可靠性与风险分析的蒙特卡罗模拟方法*](https://link.springer.com/book/10.1007/978-1-4471-4588-2) 。可靠性工程中的斯普林格级数。伦敦:斯普林格。[2][https://book down . org/S3 dabeck 1984/book down-demo-master/Monte-Carlo-simulations . html](https://bookdown.org/s3dabeck1984/bookdown-demo-master/monte-carlo-simulations.html)[3]罗伯特,C. P .和卡塞拉,G. (2010 年)。 [*用 R 介绍蒙特卡罗方法*](https://link.springer.com/book/10.1007/978-1-4419-1576-4) 。用 R!。伦敦:斯普林格。[4]s . m .罗斯(2013 年)。 [*模拟,第五版*](https://www.sciencedirect.com/book/9780124158252/simulation) 。爱思唯尔。# GAIA-X:向欧洲推销?> 原文:<https://towardsdatascience.com/gaia-x-a-pitch-towards-europe-6c0e7fa36370?source=collection_archive---------34----------------------->## 欧洲雄心勃勃的数据和云基础设施项目会信守承诺吗?![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4f829ab070c494f81fd463fa0bd63c8f.png)用 GAIA-X 克服数据湖孤岛?(图片由滑翔伞运动员金·雷伯格提供)目前,只有少数超大规模云提供商主导着市场:谷歌云平台、亚马逊网络服务、IBM 云、微软 Azure 和阿里云,仅举几个最著名的例子。他们都没有欧洲血统。生活在欧洲,如果你想在云中存储和分析数据,你很可能会选择一家美国供应商,它隶属于**云法案**。你很可能会发现自己被这些全球科技巨头锁定为**。欧洲的数字基础设施和分析依赖于提供全球可扩展云基础设施的非欧洲企业集团。如果锁定作为一个选项被添加到这一事实中,这可能意味着在欧洲范围内进一步增值是不可能的。在这一点上,在进入进一步的细节之前,请让我强调,我不是危言耸听。就其本身而言,这些全球科技公司绝对没有任何问题。像我们这样处理数据的人一定会对他们令人印象深刻的服务着迷。就我个人而言,我是他们每个人的超级粉丝。此外,这篇文章不是批评全球主义。依我拙见,全球主义比保护主义提供了更多的机会,在我看来,保护主义不是解决当今问题的可持续答案。但是这并不意味着我们应该在没有任何规则的情况下玩这个游戏。这个帖子主要是想引发一些关于数据**主权的思考。我们走吧。****# ****GAIA-X 的目标是什么?******盖亚是希腊语的原始神之一,起源于混沌( [1](https://en.wikipedia.org/wiki/Gaia) )。我不会说当前的云状态是混乱的,但只有未来才会真正告诉我们 GAIA-X 中的 X 代表什么,我估计(或者也许我只是完全误解了该项目的名称)。不管你是否喜欢以神的名字命名一个云项目,这只是一个名字,所以让我们来看看它背后的主要思想。对 GAIA-X 最大的误解之一是它应该是一项云服务。但是 GAIA-X 是**而不是**旨在成为**欧洲云替代方案**,它更好地被描述为一个非营利导向的**云倡议**。如果有的话,GAIA-X 作为一个数字**生态系统**努力为**安全**(欧洲)云服务设定**规则**和**标准**,这满足了**欧洲数据**和**知识产权。**就像之前提到的,这篇文章不会选择一条关于云的国有化道路,但是因为我们已经提到了美国、中国和欧洲很多,也许现在是一个假设性问题的好时机:****数据有国籍吗?****理想情况下,**互联网**旨在超越国界,将这个星球上的每个人联系起来。自由交换数据。一切平等交易。****云平台是建立在互联网上的,它们的所有者是收入触发的。这些供应商遵守他们祖国的法律和秩序,也必须遵守他们提供服务的国家的法律和秩序。例如,我是一名德国公民,使用谷歌云平台,并向其提供我的个人数据。谷歌也可以使用我的数据吗?当我使用谷歌的人类标签服务来完成机器学习任务时,这些工人受到哪些社会标准的保护?哪个国家的社会标准?我应该在乎吗?由于这个话题超出了本文的范围,我们将把它留给下一个话题。****许多人同意,数据必须受到国家机构的透明保护,而不能对私营公司不透明。这种观点认为,在民主国家,法律更可能符合公众利益,而不是公司的商业利益。如果不能,就要靠人民投票来改变。那么 GAIA-X 的方法看起来怎么样呢?****作为一个云计划,GAIA-X 的目标不是拥有一个巨大的服务器,而是许多小型(如欧洲)和大型提供商(如中国和美国)的能力,这些能力将在需要时通过统一的接口连接起来。GAIA-X 是一种**云网**。在这个网络中,GAIA-X 主要有两个目标[ [3](https://www.bmwi.de/Redaktion/EN/Dossier/gaia-x.html) ]:***   **为了数据驱动的价值链,公司应该在欧洲安全地交换数据(而不是让他们的数据通过大西洋流失)。**
*   **通过服务合作加强较小的云供应商的地位,这样他们可以建立一个联合的平衡力量来对抗现有的大型云玩家的统治地位。******在公司之间共享**数据以从中获取更多价值(这对每个相关合作伙伴来说都是双赢),使用**安全**基础设施确实是一个令人兴奋的想法。在日常生活中,我们可能不太担心云数据的物理安全。但是 OVHcloud(一家来自法国的大型云提供商)的一些客户非常清楚地记得,即使是云也不是天堂般的安全区域,但它们也容易发生像火灾这样的人间灾难。OVHcloud 位于斯特拉斯堡的一些服务器在 2021 年 3 月 10 日晚不幸烧毁( [2](https://www.faz.net/aktuell/wirtschaft/digitec/frankreich-feuer-bei-groesstem-cloud-anbieter-europas-ausgebrochen-17237695.html) )。当然没有任何恶意的喜悦,这应该再次提醒我们所有人,安全网是多么的重要。云也不例外。但是,尽管有这种明显的安全声明,GAIA-X 观点中的安全更多地是针对**数据保护**,非常类似于“**通用数据保护条例”** (GDPR,或在德国称为 Datenschutz-Grundverordnung DSGVO)。**# **GAIA-X 是如何努力实现目标的?**## **政策规则****必须有规范,你可以审计,以确保欧洲的价值观是真正遵守有关数据保护和他们的知识产权。根据定义,使用云意味着您的数据将存储在外部服务器上。美国提供商受美国云法案的约束。这一云法案与任何欧洲对欧洲数据主权的企图背道而驰。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c80d4877d2a9f3dee743a1f7bd602cbb.png)****来自我的[网站的声明](https://www.dar-analytics.de/indexEN.html)****更准确地说,**数据主权**是关键!您需要控制并能够访问数据,以努力实现数据驱动的创新,例如“现成的”数据**生态系统**。全球化经济需要的是公平透明的竞争规则,只有健康的依赖关系。**## ****互操作性(** Liberté,用法语说)****这些规则之一是互操作性。这意味着提供商必须确保他们的客户能够轻松地将他们的数据从一个云提供商切换到另一个云提供商,而不会丢失任何数据。GAIA-X 还希望为他们的客户提供不同供应商的**服务**的相互使用,例如分析。希望通过使用相互的 GAIA-X **参考体系结构**实现互操作性,从而实现业务模型的协作和扩展。这与目前大玩家的锁定效应完全相反。如今,通过使用例如 AWS,亚马逊正在努力为您这个客户也利用亚马逊的其他服务。作为客户,留在亚马逊的原因可能在于方便(向其他供应商传输数据是可能的,但需要努力)。老实说,留在亚马逊的另一个原因(谷歌、微软等也是如此)很可能是因为他们的服务已经在技术上满足了你的需求。每个云提供商都将能够提供云存储来保存您的数据。这不是一个大挑战。但是,这些供应商是否也能够提供与 IBM 的 Watson 自然语言处理、谷歌的 Vision API、微软的 Azure 机器学习服务、阿里巴巴的 Quick BI 或亚马逊的增强人工智能相当的有竞争力的云服务呢?与这些极高的高低杠竞争,我相信它们实际上是不可超越的。但是盖亚-X 的决定性王牌是它的透明度方法。**## **透明度****或许对科技巨头来说,更根本的是对透明度的要求。非常欢迎每一个愿意达到盖亚-X 标准的人加入。从法律角度来看,针对云提供商所依据的监管问题:***   **美国**云法案******或者尊重***   **欧洲**一般数据保护条例**(与美国《云法案》相矛盾)****GAIA-X 希望成为符合欧洲透明度和互操作性标准的云主机市场。欢迎所有云提供商让他们的服务通过 GAIA-X 标准的认证。美国东道主屈从于《云法案》。《云法案》与欧洲云标准形成鲜明对比。理论上,云法案要求美国供应商在特殊情况下允许美国机构访问其服务器上的数据(甚至法律专家仍在争论这到底意味着什么)。虽然观察 GAIA-X 是否会吸引任何非欧洲客户会很有趣,但我确实希望一些欧洲公司对这种欧洲云质量标签市场有浓厚的兴趣。**# **展望:欧洲的数据经济****GAIA-X 的应用程序希望确保数据可以在安全的环境中在公司和国家之间交换。这些云基础设施网络是在工业 4.0、健康、金融等许多不同应用领域创建数据驱动生态系统的基础。GAIA-X 的生态系统应该给我们一个从数据中赚钱的市场机会。例如,人工智能可以用数据池进行训练,这些数据池可以提供给其他行业的公司(这在以前是不可能的)。这个想法是从原始数据中创建二级数据。辅助数据的保护需求低于主数据。特定于域的批准和接受被认为是作为元数据保存在主数据中的。如果一个公司为 GAIA-X 开发库,他们将会收到所有必要的信息,如认证协议等。这些库是开发者的财产,作为“知识产权”(IP)投放市场。与**欧洲数据战略**类似,GAIA-X 旨在创建数字生态系统,尤其是在以下领域[ [3](https://www.bmwi.de/Redaktion/EN/Dossier/gaia-x.html) ]:***   **产业的**
*   **欧洲绿色交易**
*   **流动性**
*   **健康**
*   **金融**
*   **农业**
*   **行政部门**## **数据聚类****例如,**金融数据集群**保持了连接数据的承诺,以便更有效地打击洗钱和市场滥用。欧洲央行和其他银行的数据池与人工智能相结合,可能会导致更高的命中率。如果这不是使用云分析的理想目标,那该怎么办?**## **GAIA-X 只会吸引欧洲商家吗?****在 GDPR(General Data Protection Regulation)**之初,许多人(包括我自己)都对这种方法是否真的能保护数据隐私持怀疑态度。我不得不承认,我预计 GDPR 会让事情变得更糟,在没有给数据保护带来重大好处的情况下,摧毁的欧洲就业岗位比它创造的还要多。我的假设是多么错误。今天,GDPR 不仅在欧洲广为人知,甚至还出口到中国、南美和日本等国家。********一个目前被广泛讨论的概念是,大型科技公司也可以自由加入 GAIA-X 项目。例如,法国 OVH 云提供商正在与谷歌合作。谷歌应该在尊重欧洲主权原则的同时,以开源兼容技术交付他们的软件和应用。这项技术将由欧洲人在位于欧洲的服务器上实践,因此预计不会有数据离开欧洲。正如本文开头所提到的,GAIA-X 不想自己创建一个云和云应用程序。欧洲足够现实地估计,如果没有在这项技术上投入了数十亿美元的老牌大玩家的专业知识,就没有解决方案。********直到今天,还没有一个具体的 GAIA-X 服务可以让我们得到。我非常兴奋地看到 GAIA-X 是否会成为一个高飞的新云标准或者只是一个理论上的 Gedankenexperiment(德语为思想实验)。********在此之前,非常感谢您的阅读!希望这篇文章对你有帮助。请随时在 [LinkedIn](https://de.linkedin.com/in/jesko-rehberg-40653883) 、 [Twitter](https://twitter.com/DAR_Analytics) 或[工作室](https://jesko-rehberg.medium.com/virtual-reality-vr-for-education-a532aa5b6272)与我联系。********<https://jesko-rehberg.medium.com/membership>  最初发表在我的网站 [DAR-Analytics](http://dar-analytics.com/) 。参考:[1]维基百科上的盖娅:[https://en.wikipedia.org/wiki/Gaia](https://en.wikipedia.org/wiki/Gaia)[2] FAZ 网,Flammen wüten beim gr esten Cloud-Anbieter Europas:[https://www . FAZ . Net/aktuell/wirtschaft/digitec/frank Reich-feuer-Bei-groesstem-Cloud-Anbieter-Europas-ausgebrochen-17237695 . html](https://www.faz.net/aktuell/wirtschaft/digitec/frankreich-feuer-bei-groesstem-cloud-anbieter-europas-ausgebrochen-17237695.html)[3]联邦经济事务和能源部,欧洲 GAIA-XA 联邦数据基础设施:[https://www.bmwi.de/Redaktion/EN/Dossier/gaia-x.html](https://www.bmwi.de/Redaktion/EN/Dossier/gaia-x.html)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/167384baca02feb1a3f14f7124228e4f.png)GAIA-X:一个高飞的新云标准还是一个理论上的实验?(图片由滑翔伞运动员金·雷伯格提供)****# 通过解决负责任的人工智能差距获得信任> 原文:<https://towardsdatascience.com/gain-trust-by-addressing-the-responsible-ai-gaps-eeb5ee685bf1?source=collection_archive---------39----------------------->## 全球负责任人工智能调查的结果![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2631df8b2251f0006ad254bba5da81bb.png)布雷特·乔丹在 [Unsplash](https://unsplash.com/s/photos/mind-the-gap?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上的照片在过去的几年里,人工智能的风险和人工智能的伦理考虑正成为人们关注的焦点。随着人工智能在疫情期间越来越多地用于接触追踪、劳动力安全和规划、需求预测和供应链中断,出现了许多围绕人工智能模型的隐私、偏见、安全、鲁棒性和可解释性的风险。人工智能风险识别、评估和缓解因人工智能成熟度、公司规模、行业部门和居住国而异。普华永道在 2020 年 11 月对 1000 多名首席执行官进行的全球负责任的人工智能调查揭示了许多见解,因为它与人工智能的风险以及公司如何评估、管理和减轻这些风险有关。接受调查的公司来自多个行业,包括金融服务、技术、能源、公用事业和医疗卫生。这些公司的规模各不相同,有年收入不足 5 亿美元的小公司,有年收入在 5 亿至 10 亿美元之间的中型公司,也有年收入超过 10 亿美元的大型公司。近 49%是大公司,29%是中型公司,其余是小公司。我们还根据这些公司的人工智能成熟度(由部署的企业范围人工智能应用程序的数量决定)对它们进行了细分。这导致了三个集群——**人工智能领导者(**或完全拥抱人工智能 **)** (26%),**人工智能实验者**(或实现的早期阶段)(58%),以及**人工智能落后者(**或未实现 **)** (16%)。毫不奇怪,大公司(年收入 10 亿美元)占人工智能领导者的近 65%。# **人工智能伦理仍未在相当多公司的视野中出现**近 33%的受访者不考虑道德因素(4%)或仅在有限程度上考虑道德因素(29%)。这一比例在人工智能实验者中上升到 37%,在人工智能落后者中上升到 44%。在日本,人工智能实验者的这一比例上升至 58%。小公司(营收 5 亿美元或更低)往往很少或根本不关注道德考虑——46%的人工智能实验者和 52%的人工智能落后者属于这一类别。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/42674cfdab6af48d0212d5e59eb99720.png)图 1:成熟度等级对人工智能伦理的关注度(来源:普华永道责任人工智能调查)# **人工智能的偏倚、安全性和可解释性仍然排名靠前**算法偏差仍然是许多组织主要关心的问题。这是 36%的受访者的主要关注点,56%的受访者充分考虑了这一点。随着公司在人工智能采用方面的成熟,他们将算法偏见作为主要关注点——近 60%的人工智能领导者将它作为主要关注点。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6ac28643aad556f208fe3b6ff853ae31.png)图 2:关注成熟度水平的偏差(来源:普华永道责任人工智能调查)人工智能系统的安全性是 28%的受访者的主要担忧,37%的受访者非常担忧,31%的受访者有点担忧。然而,随着公司的成熟,安全变得更加令人担忧——50%的人工智能领导者将安全视为非常重要的问题。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d215d79648dc995e89118cb106c103d1.png)图 3:按成熟度划分的安全关注度(来源:普华永道责任人工智能调查)在我们的调查中,27%的公司绝对有能力解释或证明模型所做的决定,41%的公司能够很好地解释,30%的公司能够在一定程度上解释。人工智能领导者在这方面更精通——48%的人肯定有能力解释这些决定。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/329137687ad21958d92a203e86620249.png)图 4:关注成熟度级别的可解释性(来源:普华永道责任人工智能调查)# **公司正在使用各种方法来评估和管理人工智能风险**在调查受访者中,近 52%的人没有道德的人工智能框架,也没有将道德原则纳入日常运营。对于 AI 落后者,这个数字上升到 68%,对于收入低于 5000 万美元的公司,这个数字上升到 66%。人工智能行为准则(63%的受访者)、人工智能影响评估(52%)、人工智能道德委员会(43%)和人工智能道德培训(37%)是公司一直用来处理人工智能风险的一些机制。虽然这些百分比在所有国家都相对一致,但英国的人工智能道德委员会(32%)和人工智能道德培训(28%)的数量似乎较少。随着公司在人工智能采用方面的成熟,他们似乎接受了更多的道德培训,也使用了道德委员会。60%的人工智能领导者拥有人工智能道德委员会(整体比例为 43%),47%的人工智能领导者接受过道德培训(整体比例为 37%)。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/51b0e3976b0a835a7226596c5370b1f7.png)图 5:按成熟度管理人工智能风险的方法(来源:普华永道责任人工智能调查)# **人工智能风险识别和问责尚处于起步阶段**只有 12%的公司将其人工智能风险管理和内部控制完全嵌入和自动化;26%的公司拥有已经标准化和沟通的企业方法;其余的公司在人工智能风险管理方面采取了孤立的或非标准化的方法。对于人工智能领导者,我们看到近 29%的领导者拥有完全嵌入式和自动化的风险管理和控制,38%的领导者拥有企业范围的标准化方法。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1513384e018c70a6d3382e934859ce81.png)图 6:按成熟度划分的人工智能风险识别(来源:普华永道责任人工智能调查)当谈到透明度和问责制时,只有 19%的公司有一个正式的和记录在案的过程,并向所有利益相关者报告;29%的公司只有在发生特定事件时才有正式流程;其余的只有一个非正式的过程或者根本没有明确定义的过程。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b0320f9d6df42df59ca7e05e028367c4.png)图 7:按成熟度划分的人工智能责任(来源:普华永道责任人工智能调查)从上述调查结果可以清楚地看出,在以下方面,人工智能领先者和人工智能落后者之间仍有很大差距*   他们对偏见、安全性和可解释性等问题的关注;
*   他们使用人工智能行为准则、人工智能伦理委员会、培训和人工智能影响评估来管理人工智能风险的方法;和
*   他们识别人工智能风险并让人们承担责任的能力。我们称之为 ***负责任的 AI 差距。*** 公司需要弥合这一鸿沟,以获得客户、员工和其他利益相关者的信任。如果做不到这一点,很可能会影响他们的投资回报率(ROI ),并且无法从人工智能计划中获得预期的收益或价值。# 相关文章1.  [AI 领导人充分利用新冠肺炎危机来增加 AI 的作用](/ai-leaders-make-the-most-of-the-covid-19-crisis-to-increase-the-role-of-ai-ce885e39dcb9)# 基于 LeNet-5 的星系多影像分类> 原文:<https://towardsdatascience.com/galaxy-multi-image-classification-with-lenet-5-1bc2f66d3cfc?source=collection_archive---------19----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1e8309e0ebca24fd30b66011f78bb04e.png)Guillermo Ferla 在 Unsplash 上拍摄的照片。## 用梯度下降魔法探索空间星系的美丽从未停止征服我。思考星系是令人难以置信的基础,它们是重塑视角的有力工具。不久前,当我在互联网上搜索我的下一次机器学习冒险时,我偶然发现了[这个](https://astronn.readthedocs.io/en/latest/galaxy10.html)机器,我知道我必须试一试。不过,在训练机器对图像进行分类之前,我很好奇, *I* 能把它们分类得多好?简短的回答是不太好。其中一些非常明显,我可以很容易地把它们挑选出来,归类为一个特定的标签。其他人我会很有信心,但当我发现我错了的时候,我的信心就破灭了。考虑到这一点,我现在很好奇。一台机器能做得多好?因此,我对这个问题进行了测试,并构建了一个卷积神经网络——到底是哪一个呢?心爱的 LeNet-5!在本文中,我将从头到尾介绍如何建立一个对星系进行分类的机器学习模型!只对代码感兴趣?没关系,我不太生气。我将为您省去通读整篇文章的麻烦,因为说实话,当我只需要某个特定部分时,我不太喜欢费力地阅读大量信息。这里是 [Kaggle](https://www.kaggle.com/tenzinmigmar/classifying-iris-flower-types-with-k-means) 笔记本的链接。## 导入依赖关系在构建任何机器学习模型时,要做的第一件事是下载我们需要的依赖关系。

! pip install astroNN
import tensorflow as tf
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import numpy as np
from tensorflow import keras

from keras.models import Sequential
from keras.layers import Conv2D, AveragePooling2D, Flatten, Dense, Dropout
from keras.callbacks import ReduceLROnPlateau
from keras.optimizers import Adam

import sklearn
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report,confusion_matrix
from tensorflow.keras import utils

from astroNN.datasets import galaxy10
from astroNN.datasets.galaxy10 import galaxy10cls_lookup


完成后,我们现在有了开始构建模型所需的工具。## 关于数据集如果你读过我的其他机器学习文章,你就会知道我对数据的评价有多高。数据点是我们日常决策的北极星。你知道你的同事总是在上午 10 点霸占着咖啡机吗?你可以把喝咖啡的时间改到 9:30。因为你的老师喜欢用突击测验给你惊喜而不断受挫?你将开始每天学习,为第二天他们可能扔给你的任何东西做好准备。数据是机器学习的核心。如果人工智能有一个口号,我会说是“只添加数据”。话虽如此,我还是给大家简单介绍一下今天节目的明星:galaxy10!galaxy10 数据集包含 21785 个 69x69 像素的彩色星系图像,分为 10 个不同的类别。该数据集的图像来自斯隆数字巡天,标签来自银河动物园。数据集内的每个图像被分类为 10 个类别中的一个,然而,在分配给来自人类志愿者的某些图像的类别中存在差异,所述人类志愿者的任务是标记图像,其作为经验证据,表明在类别之间的图像中存在高水平的相似性。为了缓解这个问题,Galaxy10 数据集不包括没有最终决定的图像。(55%的人类志愿者投票支持一个类别)您现在已经熟悉了数据集!我们继续吧。## 数据探索现在,我们不能探索尚未加载的数据。

images, labels = galaxy10.load_data()

x_train, x_test, y_train, y_test = train_test_split(images, labels, test_size=0.2)

features = ['Disk, Face-on, No Spiral', 'Smooth, Completely round', 'Smooth, in-between round', 'Smooth, Cigar shaped', 'Disk, Edge-on, Rounded Bulge', 'Disk, Edge-on, Boxy Bulge',
'Disk, Edge-on, No Bulge','Disk, Face-on, Tight Spiral', 'Disk, Face-on, Medium Spiral', 'Disk, Face-on, Loose Spiral']

x_train = x_train / 255.0
x_test = x_test / 255.0


那更好。现在,让我们试着更好地理解这些数据。

x_train.shape, x_test.shape# This prints ((17428, 69, 69, 3), (4357, 69, 69, 3))


现在,我们对数据集有了更多的了解。这里,我们有 17248 个尺寸为 69×69 的彩色训练图像和 4357 个尺寸为 69×69 的彩色测试图像的数据集。让我们来看看数据集中随机选择的图像。

fig = plt.figure(figsize=(20,20))

for i in range(25):
plt.subplot(5,5,i+1)
plt.imshow(x_train[i])
plt.title(features[y_train[i]])
fig.tight_layout(pad=3.0)

plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/65bf3749ff545f3098e01d1b26af91fd.png)从数据集中选择星系图像。来自 galaxy10 数据集的图像。令人敬畏不是吗?让我们看看这个数据集还能揭示什么。

# Check class distribution

df = pd.DataFrame(data=labels)

counts = df.value_counts().sort_index()
print(counts)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b2f938bf4c7f544da3f9750195a2643b.png)上面代码的输出。图片由作者提供。

def class_distribution(x, y, labels):
fig, ax = plt.subplots()
ax.bar(x, y)
ax.set_xticklabels(labels, rotation=90)
plt.show()

class_distribution(features, counts, features)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/61d47e56433884ee533dd73b682b164e.png)上面代码的输出。图片由作者提供。## 不平衡数据:准确性悖论这里,我们有一个相当不平衡的数据集。每个类别中的图像数量范围从类别 5 中的 17(最小)到类别 1 中的 6997(最大)。具有偏斜类别分布的数据的问题在于,准确度不再是正确反映机器学习模型对图像进行分类的能力的评估度量。这也被称为**准确性悖论**,即具有较高准确性的模型可能比具有较低准确性的模型具有更少的预测能力。总结一下:准确性可能并不总是评估你的模型的最佳指标。因此,如果我们使用其他评估指标,如精确度或召回率,这将是一个更公平的分析。**精度**:精度=真阳性(TP) /真阳性(TP) +假阳性(FP)**召回**:召回=真阳性(TP) /真阳性(TP) +假阴性(FN)**补充说明:**精度和召回指标已被移除,因此我们将使用精度作为指标来训练卷积网络,但稍后将使用 Scikit Learn 的分类报告来更好地了解我们模型的精度、召回和 f1 分数。## 训练基线模型

model = Sequential()

# Baseline model to compare to LeNet-5
model.add(Flatten(input_shape=(69, 69, 3)))
model.add(Dense(128, activation='relu'))
model.add(Dense(10, activation='softmax'))

model_optimizer = Adam(lr=0.001)

model.compile(optimizer=model_optimizer, loss='sparse_categorical_crossentropy', metrics=["accuracy"])
reduceLR = ReduceLROnPlateau(monitor='accuracy', factor=.001, patience=1, min_delta=0.01, mode="auto")
lol = model.fit(x_train, y_train, epochs=10, callbacks=[reduceLR])


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e8bb05bdf343f2048e916b2785b52a42.png)上面代码的输出。图片由作者提供。还不错。最终准确率为 70%。让我们看看 LeNet-5 在比较中表现如何,但在此之前,我先向您介绍一下 LeNet-5 的背景。## LeNet-5 架构LeNet-5 是一种古老而经典的卷积神经网络架构,由 Yann Andre LeCun、Leon Bottou、Yoshua Bengio 和 Patrick Haffner 于 1998 年开发。最初开发时,它是为手写 MNIST 数字识别而设计的,后来成为了 AlexNet 和 VGG 等未来架构的基础。第一个卷积块由两个卷积和平均池层组成,其后是一个平坦层,然后是 3 个密集层。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/172e13f86781ac763010a24d776bd772.png)LeNet-5 架构。图可以在[原文中找到。](http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf)让我们开始构建 LeNet-5 模型吧!

model2 = Sequential()

# LeNet-5 conv-net architecture
model2.add(Conv2D(filters=6, kernel_size=(5,5), strides=(1,1), activation='tanh', input_shape=(69,69,3)))
model2.add(AveragePooling2D(pool_size=(2,2), strides=(2,2)))
model2.add(Conv2D(filters=16, kernel_size=(5,5), strides=(1,1), activation='tanh'))
model2.add(AveragePooling2D(pool_size=(2,2), strides=(2,2)))

model2.add(Flatten())
model2.add(Dense(units=120, activation='tanh'))
model2.add(Dense(units=84, activation='tanh'))
model2.add(Dense(units=10, activation='softmax'))

model_optimizer = Adam(lr=0.001)

reduceLR = ReduceLROnPlateau(monitor='accuracy', factor=.001, patience=1, min_delta=0.01, mode="auto")

model2.compile(optimizer=model_optimizer, loss='sparse_categorical_crossentropy', metrics=["accuracy"])
model2.fit(x_train, y_train, epochs=10, callbacks=[reduceLR])


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/51d197a2af6852c093430d904b1dc028.png)上面代码的输出。图片由作者提供。90%的准确率!这不完全是机器学习的圣杯,但也是一个相当不错的分数。现在,让我们看看 LeNet-5 模型的预测。

predict = model2.predict(x_test).argmax(axis=1)

for i in range(10):
print("Actual:", features[y_test[i]])
print("Prediction:", features[np.argmax(predict[i])])
print("-----")
print()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f72da0954329ac2845043dc4584dd1d8.png)上面代码的输出。图片由作者提供。看起来一些星系等级被其他的混淆了。即使是人类也很难正确地对每一类图像进行分类。为了更好地理解所犯的错误,使用混淆矩阵是有帮助的。我们还会在这里看一下分类报告。

classification_report(y_test, predict)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5f6a81094597816d0abe4f27bedbda3e.png)上面代码的输出。图片由作者提供。从这个报告中,我们可以看出,我们的模型对于分类 0、1、2、4(特别是 1 和 2)具有很高的精度和召回率。请注意,类 1 和类 2 也有最多的训练和测试样本。另一方面,对于只有 6 个测试样本的类别 5,该模型具有非常低的精度和召回率(0)。绘制混淆矩阵将进一步明确这 6 个测试样本的预测结果。

matrix = confusion_matrix(y_test, predict)
sns.heatmap(matrix, annot=True)
plt.title('Galaxy Confusion Matrix')
plt.xlabel('Predicted class')
plt.ylabel('True class')


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/00ea889a3ced621da777ac2361203e8c.png)该模型很好地预测了 1 类和 2 类图像!这并不奇怪,因为它们是样本最多的类。0 和 4 也做得不算太差。我们的模型一贯混淆类别 0 和类别 7 (76 个样本),类别 1 和类别 2 也经常被预测为类别 0。此外,该模型在分类第 8 类时存在问题,经常将其误认为第 0 类和第 7 类。让我们调查一下。8 类是盘面,正面,中螺旋,0 类是盘面,正面,无螺旋,7 类是盘面,正面,紧螺旋。看看上面的图像,很容易看出为什么这些图像看起来非常相似。## 结论这是一个有趣的数据集!当我找到它并检查图像时,作为一个人,我很难辨别不同星系类别之间的差异,因为它们具有高度相似的特征,所以我很想看看机器学习模型与人类相比表现如何。我做的一些最初的假设是正确的:我相信这个模型在螺旋上有最大的困难,其他的有点偏离。我曾认为该模型会更频繁地混淆类别 1 和类别 2(平滑、完全圆形和平滑、圆形之间),因为这些类别在一些图像中看起来也非常相似。经过训练后,我认为模型能够很好地区分两个类别,是因为每个类别都有大量的图像可供训练。其他要注意的事情:准确性并不总是评估你的模型的最佳指标,也是 LeNet-5 的一个旁注;LeNet-5 虽然它的体系结构可能相对较老,但它在这个数据集上的表现并不太差。# 伽辽金变压器:NeurIPS 2021 上的一次性实验> 原文:<https://towardsdatascience.com/galerkin-transformer-a-one-shot-experiment-at-neurips-2021-96efcbaefd3e?source=collection_archive---------28----------------------->## [思想和理论](https://towardsdatascience.com/tagged/thoughts-and-theory)## 一个业余计算数学家关于注意力机制的数学理论和应用的旅程。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e500abf4817fc5e17c446fb3747e2831.png)一个基于注意力的算子学习器直接从参数中推断出解。图片作者。# 警罗罗格最近,我写了我的第一篇关于机器学习的论文,这是一个有趣但具有挑战性的兼职项目,同时还有一个包含代码的开源库:【https://github.com/scaomath/fourier-transformer。作为一个完全的新手和这个领域的独立研究者,我疯狂而愚蠢地向 NeurIPS 2021 提交了这篇论文……感谢[我的导师](https://github.com/lyc102/ifem)的鼓励。我认为这个标题很吸引人,因为搜索“伽辽金变形金刚”会在顶部找到这篇论文的 arXiv 链接。作为一名业余数学家,这个标题表明这更像是一篇“享受乐趣,而不是为了发表”类型的论文。然后,我看到了一些其他“明显的”NeurIPS 使用 LaTeX 模板提交的内容,标题类似于[“反 Koopmanism”](https://arxiv.org/abs/2106.00106),[“Max-Margin 已死,Max-Margin 万岁!”](https://arxiv.org/abs/2105.15069)、[“你永远不会独自群集”](https://arxiv.org/abs/2106.01908)。毫无疑问,这些 CS 人对此是认真的。论文本身是半理论半实验的。我觉得即使每个人都在使用变形金刚,因为 ***注意力是你所需要的全部*** ,即使对于 CV 任务,说“注意力机制背后的数学不是很好理解”甚至有点轻描淡写。几乎没有任何严格的理论基础来解释为什么注意力会以如此神奇的方式在数学上起作用。因此,在这篇博文的剩余部分,我将以一种随意的方式,带着一些半严肃的数学知识,介绍我们用一些我熟悉的严肃数学知识重新思考变形金刚的小小尝试:> **首次尝试从希尔伯特空间的逼近理论出发,用伽辽金方法解释注意机制的逼近能力。**[1]:曹,S. (2021)。选择一个变换器:傅立叶或伽辽金。在 [*arXiv 预印本 arXiv:2105.14995*](https://arxiv.org/abs/2105.14995) 。[2]:瓦斯瓦尼,a .,沙泽尔,n .,帕尔马,n .,乌兹科雷特,j .,琼斯,l .,戈麦斯,A.N .,凯泽,l .,波洛苏欣,I .,2017。你需要的只是关注。 [*arXiv 预印本 arXiv:1706.03762*](https://arxiv.org/abs/1706.03762) 。# 背景自我关注算子的数学定义如下:𝐲 ∈ ℝⁿ × ℝᵈ是输入潜在表示,查询 *Q* ,键 *K* ,值 *V* ,以及投影矩阵 *W^Q、W^K、W^V*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/39a18bd7bf5964ca7f5afd3619d94a7c.png)使用[编码](http://www.codecogs.com/)创建的方程式。缩放后的点积关注度为:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f0e999bf9777a553893d1723127c1171.png)使用[编码](http://www.codecogs.com/)创建的方程式。全部注意力是:对于 g(⋅)一个逐点通用逼近器(在这种情况下是前馈神经网络)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7447f71a1de9acf6fb1b8d6c385f4dbe.png)**(A)** :标准的注意机制。使用[编码](http://www.codecogs.com/)创建的方程式。在许多关于*中自我注意机制的解释的论文中,注意是你所需要的全部*,包括最近的一些尝试,用“内核解释”进行类比,或者说将 Softmax *(QKᵀ)V* 链接为可学习的内核图是一种常见的做法。Softmax( *QKᵀ* )被描述为每个位置的特征向量(标记的学习嵌入)与每个其他位置的特征向量的相似性度量。softmax 归一化变压器的一些值得注意的线性化利用了这种解释。我想,如果没有 softmax,生活会变得简单得多,我们将解释从行方式的**改为列方式的**。所以让我们做吧!# 改进基于数学直觉的注意机制的尝试现在假设 *Q,k,V* 的第 *j* 列为在物理位置 xᵢ ∈ ℝᵐ采样的(单独的)函数 qⱼ(⋅),i=1,…,n ,连同 zⱼ(⋅)表示缩放的点积的输出。然后, *(QKᵀ)V* 加上一些关于跳过连接的警告,没有 softmax 的注意力变成了第二类弗雷德霍姆方程[:](https://mathworld.wolfram.com/FredholmIntegralEquationoftheSecondKind.html)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/61c046b1d4a12f9a5fcfe6ef0383f4f7.png)使用[代码生成的方程式](http://www.codecogs.com/)。与κ(x,ξ):=ζ_q(x)⋅ϕₖ(ξ)对于特征地图:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/46e672444649f7e00703908a2b37c6d2.png)使用[代码生成的方程式](http://www.codecogs.com/)。将注意力机制解释为积分并不新鲜,例如在 LieTransformer 中已经开发了对[组](https://en.wikipedia.org/wiki/Group_(mathematics))的积分。尽管如此,将**积分**引入到图片中会为没有 softmax 的线性变量带来更有趣的解释: *Q(KᵀV)* 可以被视为彼得罗夫-伽辽金投影(如果我们将 *Q,k,V* 的列视为独立函数):![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/dcdd5e2bb203c658b6088c581e7bcc58.png)**(P-G)** :重写没有 softmax 的线性注意。使用[编码](http://www.codecogs.com/)创建的方程式。其中𝔟(⋅,⋅)是在 ***无限维希尔伯特空间*** 上定义的双线性形式,但在行动中被评估为离散近似。为了帮助我们理解,我们可以参考下面的两个数字,看看没有 softmax,生活是如何变得容易得多的。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7ad9cd7d7290ab1c3dc46f8c7d00f80c.png)没有 softmax 的线性注意力的图示。图片作者。现在,为了将上面关于没有 softmax 的线性注意力的表达式与我们熟悉的东西联系起来,我们可以进一步考虑 *QR* 因式分解,或者甚至是在一组 *d* 正交基函数{ *qⱼ(⋅)* }ⱼ₌₁ᵈ:中的投影![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/160abebb653dc1c7c047135431c9dded.png)使用[编码](http://www.codecogs.com/)创建的方程式。毫不奇怪,解决方案是一个类似于线性回归解的显式表达式的投影:如果我们假设{ *qⱼ(⋅)* }ⱼ₌₁ᵈ通过其内积诱导范数进一步规范化(想想具有进一步 *1/√n* 权重的实例规范化)。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5d7b450d006cd0bd580233d285f9e576.png)**(F)** :正交基的潜在扩展。使用[代码生成的方程式](http://www.codecogs.com/)。来看一个具体的例子:设*ω*=【*0,2π* 】和 *qⱼ(x)* = sin( *jx* )和 cos( *jx* ),那么上面的等式只是 [**傅里叶级数部分和逼近***【x】*和**中的一个特例(p-p)**](https://encyclopediaofmath.org/wiki/Partial_Fourier_sum)受这种解释的启发,提出了下面的伽辽金型简单注意算子:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/481993c56a4eec91f8a2ecbd14d1a840.png)**(G)** :伽辽金注意力,一种尺度保持的注意力算子。使用[代码生成的方程式](http://www.codecogs.com/)。一点也没有。在进行点积之前,对潜在表示进行层归一化,就像傅立叶基可以被视为具有预内积归一化一样,![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d7295ce80b40ea4a4a6f80073c7af2b2.png)使用[代码编码](http://www.codecogs.com/)创建的方程式。[3]:哈钦森,m .,兰,C. L .,扎伊迪,s .,杜邦,e .,德,Y. W .,,金,H. (2020)。LieTransformer:李群的等变自注意。 *arXiv 预印本 arXiv:2012.10885* 。# 操作员学习现在一种新的注意力被构想出来了,问题是:> 我们在哪里为这位新的注意力操作员搭建舞台?即使一些初始原型表明使用`fairseq`(例如,更快的训练)在 IWSLT14 (En-De)上的 BLEU 评估基准上有希望的结果,对我自己来说,与[偏微分方程](https://en.wikipedia.org/wiki/Partial_differential_equation)相关的操作员学习问题将是自然的选择。如果选择一个大而艰巨的自然语言处理(NLP)问题,作为一个独立的研究人员,原型-调试-改进的周期对我来说太长了。去年,我的导师给我发了一篇[博客文章](https://www.jiqizhixin.com/articles/2020-10-23-7)关于加州理工学院 ML 小组使用所谓的傅立叶神经算子(FNO)⁴学习偏微分方程解算子)实现了一个最先进的性能。在仔细阅读、剖析代码并自己重新实现之后,我完全[屈服于这种令人敬畏的方法的脚下](https://en.wikipedia.org/wiki/Pran%C4%81ma),因为它在数量级上击败了以前的方法。此外,这个实现让我确信,注意力中的一般`Q/K/V`方法变成了`FFT->conv->iFFT`。这种变化是注意力机制的一种特殊而有效的线性变化,投影矩阵是不可训练的。因为快速傅立叶变换(FFT)或其逆变换都可以被视为通过乘以范德蒙矩阵的不可训练的基变换。在实际的注意机制中,基底的(非线性)变化的权重都是可训练的。最重要的是,FNO 的实践表明了一件事> 对待潜在表示的**列**而不是**行**(位置的特征向量)施加操作,是一种有前途的方法。直到最近(截至 2021 年 5 月),ML 社区开始重视这一方向,例如在[5]和[6]。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ea1632aecf783defdc51a13e336a41e3.png)随机界面的扩散系数。图片作者。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/99f5e4faebe79925ab779694a3106bc4.png)含 10%噪声的偏微分方程解。图片作者。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ac14cbd8bf292f4adb57112d1ad02570.png)来自溶液的噪声测量的重构系数。图片作者。那么,结果是什么呢?注意力和 FNO 的结合非常好,基于伽辽金注意力的转换器也可以解决困难的反系数识别问题(见上图)。在相同的参数配额下,在伯格斯方程基准中,4 个伽辽金注意层+2 个 FNO 层的模型在相同的实验室条件下(相同学习速率的`[1cycle](https://arxiv.org/abs/1708.07120)` [调度器](https://arxiv.org/abs/1708.07120),100 个历元)优于 4 个 FNO 层的模型 4 倍,优于原始的具有`Batchnorm`的模型 10 倍。在 *L* -norm 中平均评价相对误差的常用范围为`1e-3`,最大值为`1.7e-3`。达西流中的基准,连同其逆版本,在评估准确性方面也已经废黜了国王(FNO)。伽辽金变换器的训练比 FNO 慢,尽管理论上具有相同的复杂度。除了加州理工学院集团提出的神经算子结构化网络,下一个接近的竞争对手 [DeepONets](https://arxiv.org/pdf/2103.10974.pdf) 要差得多……(参见[第 14 页](https://arxiv.org/pdf/2103.10974.pdf),图 10 中有`3e-2`相对误差的单个实例)。由于 DeepONets 中的网络类似于[神经图灵机(NMT)](https://arxiv.org/abs/1410.5401) 中的附加注意力,可以预见的是,尽管 DeepOnets 具有启发式地符合数学的结构,但由于多个“困难的”非线性(如双曲正切和 Sigmoids)的组合,deep onets 更难训练。[4]:李,z .,科瓦奇基,n .,阿齐扎德内谢利,k .,刘,b .,巴塔查里亚,k .,斯图尔特,a .,&阿南德库马尔,A. (2020)。参数偏微分方程的傅立叶神经算子。 *arXiv 预印本 arXiv:2010.08895* 。[5]:托尔斯泰欣、霍尔斯比、科列斯尼科夫、拜尔、李、翟、安特辛纳、杨、凯泽斯、乌兹科雷特、卢契奇和多索维茨基,2021 年。Mlp 混合器:用于视觉的全 mlp 架构。 *arXiv 预印本 arXiv:2105.01601* 。[6]:李-索普,j .,安斯利,j .,埃克斯坦,I .,&翁塔农,S. (2021)。FNet:用傅立叶变换混合记号。 *arXiv 预印本 arXiv:2105.03824* 。## 注意:下面的最后一部分有一些半严肃的数学。# 我们能证明什么?彼得罗夫-伽辽金投影注意算子或其线性变体,就其输入和可训练参数而言,是一个 ***非线性*** 算子。我们如何把它连接到像伽辽金或者彼得罗夫-伽辽金投影这样的线性投影上呢?答案很简单:> 我们尝试在希尔伯特框架下,在以下意义下证明 ***近似容量*** 。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3072ffb4a4b0e4a520be023e41e5af13.png)**(M)** :线性投影度量的非线性映射的逼近能力。使用[编码](http://www.codecogs.com/)创建的方程式。这转化为:g_θ,建立在伽辽金注意力上的近似器,其近似能力等同于到近似子空间 *𝕍ₕ* ⊂ ℋ的伽辽金投影,其中ℋ是希尔伯特空间,并且我们想要在它的子集上模拟操作者的行为。这个子空间 *𝕍ₕ* 是基于潜在表示的当前子空间,并且在优化期间,是动态变化的。然而,在固定的潜在表征的静态视图中,注意机制有能力在当前的近似空间中提供最佳近似器,即伽辽金型投影。## 难点:用线性投影桥接非线性映射有人可能会问:这不是小事吗?嗯,有几分像 **(F)** 正是*𝕍ₕ*:= span {*vⱼ(⋅)*}的情况。然而,仔细观察后,用数学方法把这个结果清晰地表达出来可能并不那么容易。困难如下:*   与伽辽金投影中的空间设置不同,`Q/K/V`所代表的近似子空间是不同的。
*   如何将 *Q* 的列线性组合得到 **(P-G)** 中输出 **z** 的每一列取决于乘积 *KᵀV* 的每一列。然而,并不完全清楚的是, *KᵀV* 的某一列是否足以给出系数,以产生任意函数*f*∈ℋ.**的伽辽金或彼得罗夫-伽辽金投影原因是因为既不能保证`Q/K/V`满秩,也不能保证非线性内积的满射性。**## 一个简单的例子来说明困难在注意力的任何线性变化的上下文中:> q 代表值,K 代表查询,V 代表键。让我们考虑一个简单的例子,其中*ω*=(*-1,1* ),由*−1=x₁<x₂<⋯<xₙ=1*离散化。*q****列的近似空间*** 由前两个[切比雪夫多项式](https://en.wikipedia.org/wiki/Chebyshev_polynomials) { *1,x* }构成, *K* 和 *V* 的列的近似空间分别为{ *a,bx* 和{ *c,dx* }对于 *a,b,b 实际的列是由这些函数在 *xᵢ* 的评估产生的,对于一个样本,网格点数 *n* 是固定的。我们注意到序列长度 *n* 可以在操作者学习管道中改变。*现在,对于一个 *f* ∈ ℋ,*l*-*f*到 *ℚₕ* := span{ *1,x* }的投影为:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ecd6b969282e83a874d51f9de13dc4fb.png)**(L)** :线性多项式空间中对 f 的最佳逼近。使用[代码生成的方程式](http://www.codecogs.com/)。当将 *K/V* 的列解释为网格采样的函数时, *KᵀV/n* **的点积成为积分**的近似值,并且易于验证:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/331af8a7df539fc53287bfae747ea2b2.png)使用[代码生成的方程式](http://www.codecogs.com/)。在这种情况下,通过进一步的简单检查,我们可以看到 *KᵀV/n* 能够复制 **(L)** 中投影的系数,只需乘以矢量 *(f₁,f₂)ᵀ* )。但是,如果把 *K* 和 *V* 的列改成网格点处的{ *a,bx* }和{ *cx,dx* }的求值呢?![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/67083575358943e3e0642843cc9eccc3.png)使用[代码生成的方程式](http://www.codecogs.com/)。突然,**复制(L)中系数的能力没有了!**因为这个矩阵乘以 *Q* 后: *Q(KᵀV)* 的列所代表的子空间在里面没有常数函数!欢迎感兴趣的读者验证一下。当然,这是一种过度简化,因为:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e5721cd182aeac3eae3e4d2895c0577d.png)使用[代码生成的方程式](http://www.codecogs.com/)。但是你明白了。## 证明:希尔伯特空间中的一个鞍点问题通过我自己的专业技术(混合有限元),我们可以证明 *Q(KᵀV)* 具有**能力**来实现彼得罗夫-伽辽金投影所能近似的结果,前提是以下条件成立:> **存在从关键空间(线性注意中的 V)到值空间(线性注意中的 Q)的满射映射。**在泛函分析中,这也可以被视为在逼近算子方程的情况下的[近距离定理](https://en.wikipedia.org/wiki/Closed_range_theorem)或[Ladyzhenskaya–Babu ka–Brezzi 条件](https://en.wikipedia.org/wiki/Ladyzhenskaya%E2%80%93Babu%C5%A1ka%E2%80%93Brezzi_condition)的条件。如果我们的一些读者对细节感兴趣,请参考论文中的[附录 D。](https://arxiv.org/abs/2105.14995)用通俗易懂的语言来翻译这个线性注意证明的数学意义,它是:> **对于值空间中的最佳逼近器(Petrov-Galerkin 投影),至少存在一个键来匹配传入的查询以传递该最佳逼近器。**写成一个不等式的形式:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/04c1a7f43167b32b65ff32e98e6089a3.png)变压器的序列长度独立逼近。使用[编码](http://www.codecogs.com/)创建的方程式。其中 *c* 是离散近似空间上 Ladyzhenskaya-Babu ka-br ezzi 条件中的常数。如果 *c* 可以被证明是序列长度无关的,那么伽辽金变换器的近似功率,或者变换器的任何线性变量的近似功率,是 ***独立于序列长度*** ,数学证明。相反,近似能力取决于`d_model`,即我们愿意支付多少基函数来近似一个子集上的操作者的响应。算子理论和(线性)注意力机制之间的完美桥梁,没有 softmax。由于我自己已经完成了这个小项目,并在不久的将来返回到我自己的领域(可能会在多级转换器上再做一个工作,利用注意力机制中残差的子空间校正性质),如果 ML 社区发现这个证明的重要性,利用 ***键到值映射*** 的满射性,这并不奇怪,在 1 或 2 年内,将会出现像“Sobolev 注意力”、“微分注意力”、“Chebyshev 注意力”、使用其他积分变换的注意力之类的东西。## 连续中的连续,离散中的稳定对于不熟悉希尔伯特背景下算子方程近似的人来说,按照本文的思路,最大的困惑可能是:> 使用双线性形式定义键到值的映射。这种双线性形式定义在两个**无限维希尔伯特空间**上,但为什么论文只给出了它在**有限维** **离散近似空间**上的下界?答案很长。在写这篇论文之前,我读了关于第一篇论文[的评论](https://arxiv.org/abs/2106.01506) ⁷试图使用 [Mercer 核](https://en.wikipedia.org/wiki/Mercer%27s_theorem)以数学严谨的方式解释近似容量。他们的证明主要是将早期开创性工作中的一个移植到巴拿赫·spaces⁸.的背景中从他们提交 arXiv 的时间来看,可以有把握地假设他们也向 NeurIPS 2021 提交了他们的工作(尽管没有使用 LaTeX 模板)。在他们提交的 ICLR 2021 年申请的公开审查页面中,审查者 1 提出了这个关键的有见地的问题:> 论点中的另一个弱点是,核随着随机梯度下降的每一步而变化。也就是说,参数 W^Q 和 W^K 被更新,这改变了核函数。结果,变压器的训练不在单个再生核 Banach 空间中操作。这是 Mercer kernel 论文的作者没有用明确的论据直接回答的主要问题之一。事实上,在操作员学习的背景下,答案很简单:> 即使 Transformer 提供了序列长度不变的性能,例如,在 n=512 上训练的模型可以在 n=512 或 n=2048 上提供相同的评估误差;对于单个样本,提供的近似是通过具有 n 个网格点的离散空间。因此,该理论可以用**动态变化的有限维近似空间** **来表述,但只有一个无限维的潜在希尔伯特(或巴拿赫)空间**。例如,在ω的 *n* 个网格点采样的连续分段线性函数的空间,无论那个 *n* 有多大,都是*L(ω)*的子空间。每个单个样本的近似是在离散水平上完成的。近似空间通过优化动态更新,但底层无限维希尔伯特空间( *L* 、 *H* 等,甚至像 *Lᵖ* 这样的巴拿赫空间)没有变化!我觉得对于 Mercer kernel 论文来说,这是一个错失的机会,因为近似理论是建立在无限维的背景上的。Transformer 架构的近似能力仍然受限于有限维子空间,受限于`d_model`,这是在我们的“面向列”解释中支付的基函数的数量。[7]:赖特,硕士,冈萨雷斯,J. E. (2021)。变形金刚是深度无限维的非 Mercer 二进制内核机器。arXiv 预印本 arXiv:2106.01506 。[8]:奥野,a .,哈达,t .,&下代拉,H. (2018,7 月)。基于神经网络的多视角特征学习概率框架。在*机器学习国际会议*(第 3888–3897 页)。PMLR。# 收场白NeurIPS 2021 委员会决定将[清单](https://neuripsconf.medium.com/introducing-the-neurips-2021-paper-checklist-3220d6df500b)放在提交模板的末尾:> NeurIPS 论文清单旨在鼓励负责任的机器学习研究的最佳实践,解决可重复性、透明度、研究道德和社会影响等问题。我个人非常喜欢这个清单。它指导我,一个在这个领域完全是新手的人,通过准备论文,并教会我在 ML 研究中的以下良好实践:*   承认别人的资产(代码、数据集);
*   用可再生/可复制的代码和指令展示 ML 研究;
*   报告关于不同种子的误差条/带。受到这份清单以及 LieTransformer 论文中致谢的启发,我[感谢在这个小项目过程中启发我的每个人](https://github.com/scaomath/fourier-transformer#acknowledgement),即使这只是在一次偶然的随意交谈中的一句俏皮话。*原载于 2021 年 6 月 6 日*[*https://scao math . github . io*](https://scaomath.github.io/blog/galerkin-transformer-neurips)*。*# Gallia:数据转换库> 原文:<https://towardsdatascience.com/gallia-a-library-for-data-transformation-3fafaaa2d8b9?source=collection_archive---------27----------------------->## 用于实际数据转换的模式感知 Scala 库:ETL、特性工程、HTTP 响应等![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c757eb59e9c37060da944f1b2627661a.png)由[约书亚·索蒂诺](https://unsplash.com/@sortino?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片[Gallia](https://github.com/galliaproject/gallia-core/blob/master/README.md) 是一个用于通用数据转换的 Scala 库,重点关注**实用性**、**可读性**和**可伸缩性**(如果需要的话)。这是一个个人项目,是我在对现有工具失望多年后开始的。它旨在帮助数据工程师完成工作,而不必在需要时放弃可伸缩性。它还旨在填补像 *pandas* 这样的库(对于那些重视 Scala 这样的强大类型系统的人)和 *Spark SQL* 这样的库(对于那些发现 SQL 很难理解特定查询复杂性的人)之间的空白。更一般地说,它是为应用程序中的大多数或所有数据转换需求提供一站式范例而创建的。它的执行发生在**两个阶段**,每个阶段遍历一个专用的执行[有向无环图(DAG)](https://en.wikipedia.org/wiki/Directed_acyclic_graph) :1.  初始的**元**阶段完全忽略数据,并确保转换步骤是一致的(模式方面)。
2.  随后的**数据**阶段,在此阶段数据被实际处理。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/707ab08769a6b88387c240e4b25ec1a5.png)图片通过 LogoGround 授权给 Anthony Cros。# 微不足道的例子下面是一个非常基本的用法示例:这样就会成功打印: *{"* ***姓名*** *":"托尼】,* ***年龄*** *":40}*但是,由于 Gallia 支持模式,因此在实际处理任何数据之前,以下操作将会失败:因为递增字符串(通常)是无意义的,初始的“元”阶段将返回一个错误,抱怨字符串不能递增。注意事项:*   *JSON* 因其作为对象符号无处不在而被用于所有示例,然而 Gallia 并不是 *JSON* 特定的数据序列化或内存表示(见 [JSON 缺陷](http://github.com/galliaproject/gallia-docs/blob/master/json.md)
*   这里实际上推断出了模式,这更简洁,但通常并不理想(参见[改为提供模式](https://github.com/galliaproject/gallia-core/blob/master/README.md#schema-metadata))# 更复杂的例子让我们来看一个更复杂的用法例子。您的老板比尔向您提供了以下电子表格(优雅地被甩为 TSV):雇员项目问题他希望您为公司( *Initech* )的每位员工创建一份报告,并基于以下模板对“W2K”和“W3K”进行项目设计:# 代码和数据您可以使用 Gallia 和以下代码实现上述结果:这个例子的可运行代码可以在 github 上找到[。存储库还包含输入和输出数据,以及所有中间顶级模式/数据对的转储,这将有助于澄清任何不明确之处。例如,如果我们考虑上面的第 31 行(生成 *is_manager* 字段),我们可以找到所有的中间体文件,如下所示:](https://github.com/galliaproject/gallia-medium-article)*   **输入**模式:[。/data/intermediate/30 . meta . txt](https://github.com/galliaproject/gallia-medium-article/blob/master/data/intermediate/30.meta.txt)
*   **输入**数据:[。/data/intermediate/30 . data . JSON](https://github.com/galliaproject/gallia-medium-article/blob/master/data/intermediate/30.data.json)
*   **输出**模式:[。/data/intermediate/31 . meta . txt](https://github.com/galliaproject/gallia-medium-article/blob/master/data/intermediate/31.meta.txt)
*   **输出**数据:[。/data/intermediate/31 . data . JSON](https://github.com/galliaproject/gallia-medium-article/blob/master/data/intermediate/31.data.json)请注意,这不是一个标准的 Gallia 特性,只是为了本文的方便而提供的。还要注意,每个步骤只提供第一个数据实体。**EDIT:** 我还增加了一个[手动对应物](https://github.com/galliaproject/gallia-medium-article/blob/master/src/main/scala/galliamedium/initech/InitechManual.scala),可以很容易的和 [Gallia 加工](https://github.com/galliaproject/gallia-medium-article/blob/master/src/main/scala/galliamedium/initech/InitechGallia.scala)相比。手动对应物专门使用标准库。# 游戏攻略上面的转换步骤尽可能不言自明。例如,`.remove(“Employee ID”)`就是这个意思:“雇员 ID”字段将不再存在。相反,我们将在下面详述一些更复杂的操作。## 嵌套操作第一个嵌套操作很简单:

.nest(“first”, “middle”, “last”).under(“name”)


它基本上把一个实体:*{****【第一个*** *”:【彼得】、* ***中间*** *:【罗恩】、* ***最后*** *:【长臂猿】、…}*到…里面*{****姓名****:{***【彼得】,* ***中间*** *【罗恩】,* ***最后*** *【长臂猿】},… }***然而,第二个嵌套操作(有意地)更加复杂:*

.renest{ .filterKeys(.startsWith(“Address”)) }.usingSeparator(“ “)


*它利用了两种机制:**   *通过谓词选择一个键的子集,即这里的`startsWith(“Address”)`*
*   *使用一个普通的分隔符重新嵌套,即这里的空格字符**目标选择集中在仅有的四个带有“地址”前缀的字段上。同时,重定机制使用提供的分隔符来重建隐含的嵌套:**因此我们从:*

{
...
"Address number": 9,
"Address street": "Channel Street",
"Address city" : "Houston",
"Address zip" : 77001,
...
}


*收件人:*

{
...
"Address": {
"number": 9,
"street": "Channel Street",
"city" : "Houston",
"zip" : 77001
},
...
}


*请注意,这是处理已被“展平”以适合矩形格式的数据的典型方式。**更多关于 Gallia 重新嵌套的细节可以在[这里](https://github.com/galliaproject/gallia-core/blob/master/README.md#renesting-tables)找到*## *进行操作*

issues.bring(projects, target = "Name", via = "Project ID" <~> "ID")


*该语句可以用简单的英语理解为“通过匹配字段将字段*名称*从*项目*带入*问题*”。这里,我们必须显式地命名匹配的字段,因为它们的键不同(*"项目 ID"* vs *"ID"* ),否则它们可能会被猜到。**"*▲*"是一种特殊类型的左连接。当一个人只想用来自另一个数据源的几个字段来扩充数据时,可以方便地使用它。这与以下情况形成对比:**   *Gallia *join,*对应于同名的 *SQL* 操作,因此意味着潜在的反规范化。*
*   *A Gallia *co-group* ,对应于同名的 *Spark* 操作:没有反规格化,但是分组的边分别嵌套在 *_left* 和 *_right* 字段下。*## *透视操作(嵌套)*

.transformObjects(“issues”).using {
_ .countBy(“Status”) // defaults to “_count”
.pivot(_count).column(“Status”)
.asNewKeys(“OPEN”, "IN_PROGRESS", “RESOLVED”) }


*这里要注意的第一件事是,我们将转换应用于嵌套元素,而不是每个实体根处的数据元素。下划线在 Scala 中有特殊的含义,因此对应于嵌套在 *issues* 字段下的每个实体(在前面的 group-by Employee ID 操作中,参见[中间元数据](https://github.com/galliaproject/gallia-medium-article/blob/master/data/intermediate/50.meta.txt)和[数据](https://github.com/galliaproject/gallia-medium-article/blob/master/data/intermediate/50.data.json))。**从这里开始,对于所有这样的“发布”实体,我们按状态进行计数(*打开*、*进行中*或*已解决*),然后对该计数进行透视。也就是说,如果这些是给定受让人的问题:**那么计数操作导致:**该支点导致:**应该注意的是,`.asNewKeys(“OPEN”, “IN_PROGRESS”, “RESOLVED”`部分是必需的,因为——非常重要 Gallia 在整个转换过程中维护一个模式。在目前的情况下,*状态*的值只能在查看整个数据集后**才能知道,因此必须提前提供。关于这个问题的更多细节也可以在文档的[模式](https://github.com/galliaproject/gallia-core/blob/master/README.md#schema-metadata)和【T21(DAG)】标题部分找到。***# *未来文章**在以后的文章中,我想讨论使用替代技术实现相同结果的方法,如 *SQL、Spark sql、pandas、*等(与[这个想法](https://github.com/galliaproject/gallia-docs/blob/master/bounties.md)相关)**我还想讨论如何使用内置 Gallia 的 *Spark RDDs* 扩展上述转换(参见[文档](https://github.com/galliaproject/gallia-core/blob/master/README.md#spark))。上面的例子是有意忽略的,但是如果数据包含数十亿行,代码将不能像现在这样处理它。*# *结论**对于现实生活中更复杂的例子,[参见这个](https://github.com/galliaproject/gallia-dbnsfp)知识库。另请参见[示例的完整列表](https://github.com/galliaproject/gallia-core/blob/master/README.md#examples)。**Gallia 的主要**优势**可以总结如下:**   *提供最常见/有用的数据操作,或者至少[预定](https://github.com/galliaproject/gallia-docs/blob/master/tasks.md)。*
*   *领域专家至少应该能够部分理解的可读 DSL。*
*   *扩展不是事后的想法,需要时可以利用*Spark rdd*。*
*   *元感知,意味着不一致的转换会尽可能地被拒绝(例如,不能使用已经被移除的字段)。*
*   *可以处理单个实体,而不仅仅是其集合;也就是说,没有必要创建一个实体的“虚拟”集合来操作那个实体。*
*   *可以以自然的方式处理任何多重性的嵌套实体。*
*   *宏[可用于](https://github.com/galliaproject/gallia-macros)与 case 类层次的平滑集成。*
*   *提供灵活的目标选择,即作用于哪个(哪些)字段,范围从显式引用到实际查询,包括涉及嵌套时。*
*   *执行 DAG 是充分抽象的,它的优化是一个很好分离的关注点(例如谓词下推、剪枝等);但是请注意,目前很少有这样的优化。**Gallia 仍然是一个相当新的项目,因此我期待着它的任何反馈!主存储库可以在 github 上找到[,而](https://github.com/galliaproject/gallia-core)[父组织](https://github.com/galliaproject)包含了所有相关的存储库。**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/707ab08769a6b88387c240e4b25ec1a5.png)***根据 Anthony Cros 的许可,图片来自 LogoGround。**# *脚注**[1]:如果提供了类之间的关系(例如通过*隐含*),则不会出现这种情况,参见两个相关任务:**   *[提供关系( *t210426094707* )](https://github.com/galliaproject/gallia-docs/blob/master/tasks.md#t210426094707)*
*   *更一般的:[语义( *t210124100546* )](https://github.com/galliaproject/gallia-docs/blob/master/tasks.md#t210124100546)**还要注意的是,*带来* / *加入* / *协同组*对多个按键的操作还不可用:参见任务[多个按键( *t210304115501* )](https://github.com/galliaproject/gallia-docs/blob/master/tasks.md#t210304115501) 。解决方法是生成一个临时字段。**[2]: *左连接*和*左连接*功能相同,如果右侧没有多个匹配的话。**[3]:如果该字段被显式设置为一个*枚举,*就可以避免这种情况,因为我们使用了模式推断。Gallia 将来也可能提供“不透明物体”:参见相应的[任务( *t210202172304* )](https://github.com/galliaproject/gallia-docs/blob/master/tasks.md#t210202172304)*# 权力的游戏和编程语言#第二部分> 原文:<https://towardsdatascience.com/game-of-throne-and-programming-language-7606f4da8027?source=collection_archive---------36----------------------->## 数据科学## r,SQL,Python,Ruby。作为一名数据科学家,如果《权力的游戏》角色是编程语言会怎样?![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/53b4b8005c8a51837766e04caa1b74da.png)[Kylo](https://unsplash.com/@kylo8?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片*首先,我要感谢你。第一篇文章在 Medium 和 Twitter 上一飞冲天(超过 15000 次浏览和 350 次鼓掌)。我对此心存感激。我要感谢大家的支持。正如我所承诺的,这是第二部分。*让我们回顾一下到目前为止我们所看到的。在开始之前,我建议你阅读发表在 [TDS](https://medium.com/u/7e12c71dfa81?source=post_page-----7606f4da8027--------------------------------) 上的第一部分,以获得第一个角色的第一个概述,因为本文中的不同角色将引用它:</what-if-programming-languages-were-game-of-thrones-characters-as-a-data-scientist-c3a9ae523273>  在这篇文章中,我们将探索戴维·贝尼奥夫和乔治·马丁的剩余角色,并作为一名数据科学家,从编程语言丛林的历史和复杂性中获取更多信息。探索以下房屋后:*   严肃的;R1SE 何洛洛
*   坦格利安
*   兰尼斯特
*   拜拉席恩在本文中,我们将介绍其余的关键人物,并想象世界各地的数据科学家每天都会使用哪些工具。本文涉及的人物有山姆威尔·塔利、梅丽珊卓、瓦里斯勋爵、波隆、玛格丽·提利尔和拉姆齐·波顿。我希望你喜欢这个故事。让我们从一门你每天都必须使用并且总是在幕后的编程语言开始:SQL。# 瓦里斯勋爵— SQL比如 SQL,**瓦里斯勋爵总是在幕后**。你可以为银行、汽车行业甚至建筑商工作,SQL 或者瓦里斯勋爵将会提供你需要的所有信息。Gif 来自 Giphy.com通过发送他的“小鸟”(瓦里斯抚养的孩子,帮助他获得所有的秘密)对不起…小查询,瓦里斯勋爵不停地收集维斯特洛的每一个人和每一件事的数据,再次抱歉…在你的公司。等待您的管理特权,您将无法访问相同的信息,拥有它将始终是一个至关重要的附加值。而且,说到底,唯一知道维斯特洛/你们公司每个人的一切的人就是瓦里斯大人/SQL。此外,他被设计成能够轻松地与多个角色(兰尼斯特、坦格利安、史塔克……)合作。在这个系列中,当 SQL(又名瓦里斯勋爵)与强大的编程语言 Python ( [提利昂·兰尼斯特](/what-if-programming-languages-were-game-of-thrones-characters-as-a-data-scientist-c3a9ae523273))结合在一起时,一切都变了。两者的结合帮助数据科学征服了世界。# 山姆威尔·塔利河山姆威尔·塔利是维斯特洛的学者。**总是好的一面,人人都爱 R 和山姆威尔·塔利**。即使他不是最重要的 GOT 字符,他仍然是健壮的,并有助于获得关于您存储的数据的见解。如山姆威尔·塔利,R 很少探究企业环境。但它是学者、理学硕士和博士生使用的主要编码语言之一。Gif 来自 Giphy.com与 R 类似,山姆威尔·塔利非常适合阅读许多旧书,这些旧书会对你的数据提供有益的见解。如果您想在数据集内运行预测或时间序列分析,R 非常适合导入额外的库,如机器学习和统计库。# 波隆——坚固波隆维斯特洛的另一个主角。**波隆,如雷贯耳,可以佩服他处理合同的能力**。因为他们不忠于任何一方,看起来都像雇佣兵,但如果你想在双方之间达成一个透明干净的协议,他们都是必不可少的。> 研究如何编写智能合同…这相当于在早期互联网时代学习 HTML 和 Java。威廉·穆加耶Solidity 正在使用区块链编辑越来越有名的**“智能合同”。**比如波隆在第三季到第六季之间,波隆填补了提利昂·兰尼斯特和他妹妹之间的桥梁。与稳健类似,随着时间的推移,波隆赢得了信誉和影响力。在早期阶段,稳健和它处理货币合同的方式变得越来越重要,对不起…随着时间的推移。# 梅丽珊卓-鲁比Gif 来自 Giphy.com不仅红色是梅丽珊卓和红宝石的共同点④。比如梅丽珊卓, **Ruby 可以让任何应用在一夜之间看起来年轻清新**(即使,如果你以为它永远死了)。即使 Ruby 不是一种年轻的语言,但由于 Ruby 的 web 框架,它在年轻的创业公司中越来越有名,使他们的应用程序看起来新鲜。如果你还没有用过,可以肯定的是,**以后还会遇到**:)。下一个角色,如果玛格丽·提利尔是一种编程语言呢?# 玛格丽·提利尔——斯威夫特有人记得我们是如何开始忘记目标 C 的吗,抱歉,是君临的珊莎·史塔克?像 Swift 这样的编程工具已经被创造出来,用一种更加用户友好的编程语言取代 Objective C。可以问每个 Python 开发者;大家更喜欢斯威夫特。Swift 是一种通用的开源编程语言,由 Apple 开发,用于取代 Objective-C。它受 Python 的影响很大,因此速度快,非常容易学习。今天,许多程序员已经做出了改变。像斯威夫特这样的玛格丽特·提利尔用她的热情、简单、礼貌和对开发者的友好吸引了君临的人们。但是**不要小看珊莎·史塔克,她在网络中还有强大的盟友**,抱歉……维斯特洛和现实世界中的很多公司还在和客观 c 打交道第二部分将以整个系列中最糟糕的角色结束,让我们来谈谈属于最古怪的编程语言中最令人毛骨悚然的角色。# 拉姆齐·博尔顿——brain f * CK我相信没有什么可说的了——名字本身就说明了一切。对于记得他的人来说,拉姆齐·波顿是整个维斯特洛最残忍的角色。Brainfuck(3)是一种深奥的编程语言,仅由八个简单的命令组成。如 Ramsay Bolton,它的设计不是为了实用,而是为了挑战开发者,给他们造成痛苦。Brainf*ck 在创建几年后就去世了,没有人会后悔。Giphy.com gif这是这个列表的最后一个字符。我让你自由地分享你关于其他字符和编程语言的想法。如果你想更多地了解其他角色,如瑟曦·兰尼斯特、奈德·史塔克或丹妮莉丝·坦格利安,以及哪些角色属于 Python、C++和 Javascript,我强烈推荐你阅读《T4》第一部。特别感谢[安德里亚斯·穆勒](https://medium.com/u/95e023f81efd?source=post_page-----7606f4da8027--------------------------------)、[希亚拉·奥尔森](https://medium.com/u/ecf80228b29e?source=post_page-----7606f4da8027--------------------------------) & [塞尔吉·叶夫图申科](https://medium.com/u/910badbeb75c?source=post_page-----7606f4da8027--------------------------------)分享他们的创作思想。我希望你喜欢这篇文章,即使它没有通常那么专业,但仍然与数据科学有关。如果你想了解更多关于编程语言的知识,你可以在下面找到一些资源。感谢您的关注快乐编码# 成为提利昂·兰尼斯特:正如个人数据科学家提示,如果你想从零开始学习 Python,了解更多算法交易,成为下一个提利昂·兰尼斯特,我强烈推荐这门课程:<https://www.udemy.com/course/learn-algorithmic-trading-in-one-day/?couponCode=TDSCIENCE>  # 来源:(1)迈向数据科学#第 1 部分:</what-if-programming-languages-were-game-of-thrones-characters-as-a-data-scientist-c3a9ae523273>  (2)大纲— Brainfck:<https://theoutline.com/post/825/brainfuck-coding-languages?zd=1&zi=zwoxtyke>  (3)维基百科— Ruby:<https://en.wikipedia.org/wiki/Ruby_%28programming_language%29> # 博弈论、Python 和晚餐> 原文:<https://towardsdatascience.com/game-theory-python-and-dinners-4732ff59bdbb?source=collection_archive---------43----------------------->## 博弈论和纳什均衡的直观介绍2020 年的大部分时间我们都在房子里,但一旦封锁放松,我和我的朋友们就会大约一个月见一次面,一起吃顿饭或喝喝咖啡。在哪里见面一直是一个众所周知的问题。其他两个朋友都在重要部门工作,所以他们不得不去他们的办公室,而我是被“授予”计划部分的人(我不太喜欢)。考虑到他们对美食的偏好以及他们在城市中最喜欢去的地方,我通常会以一种我必须去的地方最少的方式提出选择(邪恶的笑声😈)他们都住在城市的北部,所以在北部见面对他们来说是最合适的。我在中部的某个地方,更喜欢那里。此外,鉴于我们生活在一个大城市,在这个城市的任何地方都不缺乏好吃的地方,但供应他们最喜欢的菜肴的餐馆位于这个城市的不同地方。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b99b8c6c1e78f762825dfe9f97605aec.png)食物大战(来源: [Pixabay](https://pixabay.com/photos/pizza-food-italian-baked-cheese-3007395/)> 要问的问题:给定某一天的地点和美食的倾向,我的朋友们会选择什么地方作为不联系对方而一致见面吃饭的地方?# 一点背景简而言之,博弈论是对描述理性决策者( ***我这里的朋友*** )之间互动( ***选择在哪里见面*** )的数学模型的研究。很公平!游戏的结果——预测游戏结果的一种方法是确定每个玩家的优势策略。优势策略是对给定玩家来说最好的策略,而不管其他玩家的选择如何( ***【无论哪里适合我的朋友***)——所以不管朋友#2 做什么,朋友#1 的优势策略就是朋友#1 的最优策略。玩家(*)选择的一组占优策略( ***地点见*** )称为**纳什均衡。这被称为均衡,因为任何一方都不会因为改变他/她的选择而获得额外的利益。***> *简单来说,纳什均衡是一条法律,即使没有警察,也没有人想打破这条法律。违法对个人没有任何好处,他们不会获得任何额外的东西。人们观察交通信号并根据灯的颜色停车/前行就是这样一种现象。*# *让我们调查一下**我们将首先为我的朋友们关于见面地点的各种选择创建一个**收益/困惑矩阵**。**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/933faa5f69ec8812b33aa0f3dc2467c5.png)**选择去城市哪个部分的收益矩阵(图片由作者提供)**阅读上面的矩阵相当简单;如果朋友 1 选择“北部”,朋友 2 选择“中部”,那么回报将是 1,5(第 2 行,第 1 列),这将使朋友 2 与朋友 1 相比处于有利位置。**我们想找到每个朋友的优势策略。在这种情况下,我们可以观察到,对于这两个朋友,优势策略是到达中心部分(第一行,第一列)。如果朋友 1 的策略从中部变为北部,那么他的收益会从 2 变为 1,这是不可取的,如果朋友 2 从中部变为北部,那么她的收益也会从 2 变为 1。**所以,两个朋友都选择来到城市的中心。去北部是一个 ***理想*** 结局,但*理想*不一定是 ***最优*** 。*# *Python 实现**让我们看看能否用 python 得出上面的结论(选择(2,2)即两者都选择中心部分)。要使用的库是 Nashpy,使用 pip 非常容易安装*

pip install nashpy


*根据上面描述的支付矩阵为每个朋友创建一个单独的支付矩阵。**Nashpy 很容易地将矩阵转换成游戏。我会把这个游戏叫做“*location _ war _ inter _ friends*”。**它产生了一个双矩阵博弈,收益矩阵如下**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/499cd439ea6e566f6059ff0219842a0e.png)**这些收益矩阵将用于计算纳什均衡,这在本库中非常简单。**纳什均衡很重要,因为它让我们对复杂系统中的突现行为有了初步的了解。在这种情况下,平衡达到于:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a32894b989bd609535fffb9b8def4496.png)**它由两个向量组成,表示每个朋友的动作:friend_1 [1,0 ]和 friend_2 [1,0]。第一个位置的 1 表示他们都将选择' ***【中央*** ',并举例说明和具体化我们上面的假设。**你可以在这里查阅 [GitHub repo 中相当简单的代码。](https://github.com/Prashantmdgl9/Game_Theory_Food_War/blob/main/Nashpy.ipynb)*# ***结论*******我们看到,尽管北方是最佳地点,但根据强大的博弈论,他们最终选择了中央,而我必须走的路最少*** 😀**这仅仅是我们在日常生活中玩的游戏的一个例子,却没有意识到。在现实世界中,由于社会条件和外部因素,我们总是最终做出妥协,最终选择不是最优的选项。这是一个有趣的观察结果,因为我们看到了我们周围的世界,例如,我们知道减少碳足迹对所有国家都是必要的,但大多数国家最终选择了次优路线。*# ***参考文献**:*1.  *[https://nashpy . readthedocs . io/en/latest/tutorial/index . html # creating-a-game](https://nashpy.readthedocs.io/en/latest/tutorial/index.html#creating-a-game)*
2.  *[https://simplicable.com/new/game-theory](https://simplicable.com/new/game-theory)*
3.  *[https://www . science direct . com/topics/neuroscience/game-theory](https://www.sciencedirect.com/topics/neuroscience/game-theory)*## *进一步阅读**我翻阅了威廉·斯巴涅尔的《博弈论 101》,发现这是一本令人愉快的书。它是根据他的 YouTube 系列[改编的。](https://www.youtube.com/playlist?list=PLKI1h_nAkaQoDzI4xDIXzx6U2ergFmedo)*# 机器人游戏> 原文:<https://towardsdatascience.com/games-for-bots-7a73ad2c70?source=collection_archive---------33----------------------->## 人工智能很难## 使用 NLP 列出多组事物![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/42bc72cb16dd762faa9100db68d40b6c.png)图片由 [GraphicMama-team](https://pixabay.com/users/graphicmama-team-2641041/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=1417208) 从 [Pixabay](https://pixabay.com/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=1417208) 在[这个地址](https://pixabay.com/vectors/dog-animal-corgi-beagle-bolonka-1417208/)拍摄。在这篇文章中,我们将深入研究在一个计算机化的系统中由人类[参与者](https://en.wikipedia.org/wiki/Actor_(UML)#:~:text=An%20actor%20in%20the%20Unified,is%20external%20to%20the%20subject.%22)执行的任务的自动化。在 2020 年的一次关闭期间,我为我的孩子创造了一个简单的记忆游戏,让他们在睡觉前玩。记忆游戏是这样的:1.  选择一个主题(例如,食物)
2.  轮流说出适合该主题的事物的名称(如黄瓜、西红柿)。我们后来添加了一个规则,你只能给未加工的东西命名,因为我们得到了近似的复制品(例如,芝麻面包、洋葱面包、肉桂面包、十字面包等)。).
3.  你命名的每一个事物都被隐藏起来,这样你就能记住哪些事物已经被命名了。如果你连续玩了几个游戏,记得听到了一个名字,但不记得是这个游戏还是之前的游戏,那就更难了。
4.  如果你在游戏中说了别人已经说过的话,你就出局了,不能再轮流上场。孩子们被鼓励编造答案以推迟就寝时间。这是游戏的代码:是的,10 行。这就是你所需要的。它在 jupyter 笔记本上运行。下面是游戏运行的一个简单例子:

Player 1: Cucumber
Player 2: Lettuce
Player 1: Banana
Player 2: Celery
Player 1: Apple
Player 2: Cucumber
Computer: Cucumber was on the list! You are OUT!


然后一号玩家赢了。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/94e96542c0d5adf7318d24a1d2d3437e.png)在 Collab 笔记本上运行的记忆游戏示例。图片由作者提供。我们最终增加了第二个游戏,它更注重词汇而不是记忆,你必须猜一个单词是真是假。真词来自一个大列表,假词来自另一个大列表。下面是第二个游戏的代码:像第一个游戏一样,每个人在开始时轮流,越来越少的玩家幸存下来,直到只剩下一个玩家(赢家)。今年,我对自己说,这些游戏可以作为一个机器学习项目的试验场。第二个游戏可以用字典或其他一些基于记忆的方法来解决。然而,关于第一个游戏(记忆游戏),你注意到的第一件事是,在代码中没有关于选择什么是好单词的规则。这只是我在我们玩的时候强调我认为有意义的新词。## 自动化记忆游戏我们需要做的第一件事是为更结构化的实现准备内存游戏。话题选择(如食物)不在规范范围内。在与人对战的电脑版本中,我们需要明确主题选择。我们可以在游戏开始时从主题中挑选 5 个单词来定义主题,而不是列出每个可能的主题和主题中的单词。这在学术文献中被称为 [**种子集**](https://arxiv.org/abs/1808.08953) 。这方面的研究工作还有很多例子,比如[这个](https://dl.acm.org/doi/abs/10.1145/3331184.3331359)和[这个](https://dl.acm.org/doi/abs/10.1145/3366423.3380284)。为了使我们的代码能够玩游戏,我们需要让我们的计算机游戏玩家在它还没有看到的主题中选择单词。您可能想知道这项任务有什么新内容。为什么不简单地使用嵌入向量相似性,并获得与某个起始单词相似的单词集?例如,word2vec 和 fasttext 具有相似的单词方法:

word_vectors.most_similar in gensim
model.get_nearest_neighbors in fasttext


答案是,词语语境相似不代表话题相似。在找和‘本田’同话题的词时,我们不要‘可靠’这个词。相反,我们想要“丰田”和“特斯拉”这样的词。尽管语义的相似性正在把我们带到我们想要去的地方,但是仅仅是相似的上下文还不足以从我们的主题词种子集中产生一个主题。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c7e8cbee69119482c15c222e196c4efd.png)在“Word2Vec All”数据集中嵌入单词“Toyota”的投影结果。我们可以在列表中看到飞机、发动机和车辆,它们与单词“Toyota”相关,但不在我们要表达的汽车名称的主题中。图片由作者提供。最近的工作叫做 FUSE,有一个很好的 MIT 许可,在这里[可以得到](https://github.com/WanzhengZhu/FUSE.git),来自论文“ [FUSE:通过 Skip-grams 的相干聚类进行多面集合扩展](https://arxiv.org/pdf/1910.04345.pdf)”。虽然他们不提供数据集,但我们可以尝试使用我们自己的维基百科数据集或类似的开源文本数据集。我们首先按照保险丝安装说明中的指示,为 gloVe 和 BERT 抓取预训练模型。这个冒险的完整代码可以在 [**这里**](https://github.com/dcshapiro/seriously-a-repo-just-to-upload-one-file-for-an-article/blob/main/Games_for_Bots.ipynb) **:** 找到<https://github.com/dcshapiro/seriously-a-repo-just-to-upload-one-file-for-an-article/blob/main/Games_for_Bots.ipynb>  **我的第一次尝试**是使用[提供的 45471 个句子的数据集](https://github.com/WanzhengZhu/FUSE/tree/master/data)来训练集合扩展模型。它太小了,因此,正如[在代码说明](https://github.com/WanzhengZhu/FUSE#Data)中指出的,它无法生成簇。聚类代码删除小的聚类。我没有试图联系提到的第三方以访问他们的数据集,这似乎是一个私人数据集。对于我的第二次尝试,我将 NLTK 数据库 gutenberg、就职、brown 和 webtext 合并成一个 186,670 个句子的语料库。FUSE 集群代码仍然会删除小的集群,所以我删除了集群删除代码。结果很差。例如,给定种子词' apple ',' orange '和' grape ',返回的扩展集是['music ',' black ',' musical ','葡萄',' white ',' gold ',' live ','名人',' green ',' red ',' royal ',' star ',' best ',' rock ',' new ',' commercial ',' radio ',' country ',' tv ',' national']。所以,我计划尝试一个更大的数据集。对于**我的第三次尝试**,我打算在更大的 [c4 数据集](https://huggingface.co/datasets/allenai/c4)上进行训练,但后来我意识到我可以尝试[另一个预训练库](https://github.com/IntelLabs/nlp-architect),这一次是来自以色列[英特尔实验室](https://intellabs.github.io/nlp-architect/term_set_expansion.html)。实际上,我把[和](https://arxiv.org/abs/1808.08953)联系到了上面的研究中,但是先尝试了 FUSE。我想那只是我的运气。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8fd58375cc84145f4326a9d13ba8857a.png)英特尔 set 扩展预训练模型的输出示例。图片由作者提供。英特尔集合扩展解决方案在第一次尝试中就成功了。他们的演示包中还有一个服务器版本和一个用户界面。以下是我最初实验的一些有趣结果:1.  **种子词:**'苹果','橘子','葡萄'。**扩展列表:**‘梨’,‘杏’,‘桃’,‘榛子’,‘石榴’,‘樱桃’,‘草莓’,‘李子’,‘薰衣草’,‘杏仁’
2.  **种子词:**'兔','马','鸭'。**扩展列表:**'野兔','狐狸','野猪','鹿肉','狗','鹧鸪','鸸鹋','猪','鸽子','鹰'
3.  **种子词:'**椅子','桌子','书桌'。**扩展列表:**‘书桌’,‘桌子’,‘椅子’,‘书桌’,‘梳妆台’,‘木板’,‘沙发’,‘椅子’,‘小桌子’,‘抽屉’。我们现在可以看到,该模型没有认识到一个对象的单数和复数形式是同一事物(例如,“书桌”与“书桌”)。该模型还没有删除停用词(例如,“书桌”与“书桌”以及“椅子”与“椅子”)。这可以通过简单的后处理步骤来解决。
4.  **种子词:**本田、福特、奔驰。**扩展列表:**'山','谷','盎格鲁-撒克逊词','古斯堪的纳维亚语','设防的地方','福特','格伦','凯尔特词','福特','摩尔人'。我们可以看到这个案子非常失败。“本田”和“梅赛德斯”这两个词不在车型词汇表中。这表明该模型区分大小写。由于只剩下单词“ford ”,该模型找到了在单词“ford”附近带有向量的单词。如果我们改为利用汽车品牌名称,我们会得到更好的结果。**种子词:'**本田','福特','奔驰'。**扩展列表:**'丰田','日产','法拉利','宝马','保时捷','雷诺','捷豹','马自达','迈凯轮','梅赛德斯-奔驰'注意,汽车名称不像 word2vec 结果那样包含与汽车相关的其他内容。这太棒了!## 结论我们现在可以看到,人们玩的某些文字游戏也可以被电脑玩。要做到这一点,需要训练计算机理解主题中包含的单词,集合扩展是实现这一能力的一种很好的方式。这些模型可以微调,也可以从头开始训练。这篇文章的代码是[,可以在这里找到](https://github.com/dcshapiro/seriously-a-repo-just-to-upload-one-file-for-an-article/blob/main/Games_for_Bots.ipynb)。如果你喜欢这篇文章,那么看看我过去最常读的一些文章,比如“[如何给人工智能项目定价](https://medium.com/towards-data-science/how-to-price-an-ai-project-f7270cb630a4)”和“[如何聘请人工智能顾问](https://medium.com/towards-data-science/why-hire-an-ai-consultant-50e155e17b39)”还有嘿,[加入快讯](http://eepurl.com/gdKMVv)!下次见!——丹尼尔
linkedin.com/in/dcshapiroT21
丹尼尔@lemay.ai# 甘沃——抽象修复> 原文:<https://towardsdatascience.com/gan-vogh-abstract-inpainting-63ab5da53b89?source=collection_archive---------39----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a32077494b4911570f2aa91174464838.png)图 1:左:[约翰·克莱伯格](https://www.wikiart.org/de/albrecht-durer/bildnis-johann-kleeberger-1526)(阿尔布雷特·丢勒)的肖像——右:作者的图片。时尚数据培训网络。## 人工艺术合成I npainting 是一种根据原始内容以逼真的方式填充缺失像素来重建不完整图像的方法。目前,这个问题通常用深度卷积神经网络来解决。一种常见的解决方案是利用两种鉴别器架构来实现全局和局部一致性。全局鉴别器查看发生器的全部输出,局部鉴别器仅查看丢失像素的区域。但是我们能做的不仅仅是猜测原文内容吗?为了生成艺术上有趣的图像,我们希望修复比原来更多的细节和抽象特征。虽然内容和风格确实可以完全不同,但是新生成的补丁和它周围的上下文之间的过渡仍然应该是平滑的。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/79527816f9eece2965ad35e30df3b879.png)图二。图片作者。在这个实验中,我只使用正方形(瓷砖)作为随机放置在图像中的缺失区域。通常,学习修补和现有内容之间的平滑过渡可以通过空间折扣遮罩来实现。通过使用合适的损失函数,例如 L1 范数,比较屏蔽的输出和屏蔽的背景真相,屏蔽仅约束丢失面片边界处的像素。接下来,我们看一下内容表示。我们的生成器架构应该生成与原始内容不完全匹配的内容。事实上,排除全局鉴别器正是我们想要的解决方案。在大多数情况下,本地鉴别器本身就足以为发生器提供有意义的梯度。令人惊讶的是,在剪贴画和卡通等非常简单的情况下,本地鉴别器会指导生成器重建逼真的图像补丁。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ee2a8591ad7a29e1c4bbc94a90098f58.png)图 3:左:[站着的男性形象](https://www.wikiart.org/de/edward-wadsworth/male-figure-standing-1911)(爱德华·沃兹沃斯)——右:作者图片。网络训练分形和重复艺术。这一想法是由于与大规模图像合成相关的过高计算要求而产生的。在我的实验中,每个数据集包含大约 2000 张 512x512 像素的图像,图像块大小为 256x256 像素。我在一个 8GB 的混合精度 GPU 上对每个数据集进行了大约 4 天的训练。一般来说,没有全局鉴别器,该体系结构需要较少的资源。GANs 适用于小图像,因此简单的架构就足够了。此外,随机改变输入图像中的瓦片位置对应于数据扩充过程,允许小得多的数据集足以用于训练。**推论**与机器学习中的最佳实践相反,用训练数据生成抽象图像会导致最有趣和一致的结果。应用到完全不同的图像内容仍然有效,但是,每个图块的边界在最终结果中可能是可见的(图 3)。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1e00f9d95ae05a5c6f6df76c6c23e805.png)图 4。作者图片在推理时,我的脚本从左上角开始递归地修补所有的瓷砖。为了给生成器提供所需的上下文,从整个图像中裁剪出一个较大的正方形部分,如果图块与图像边界相邻,则使用反射填充进行扩展。在处理下一个补丁之前,新创建的补丁将被插入到图像中。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0fe1257ba78d9ec070c175b39f2febe3.png)图 3:左:[柏树和两个女人](https://commons.wikimedia.org/wiki/File:Van_Gogh_-_Zypressen_und_zwei_Frauen.jpeg)(文森特·梵高)——右:作者的图片。网络培训海绵宝宝。独立于训练数据,全局内容仍然在输出图像中表示。适合图像的补丁越多,单个补丁覆盖的信息就越少,从而可以重建更多的内容。细节被训练集的风格和内容所取代。如果网络训练得不够好,或者输入图像远离训练域,则输出会变得非常嘈杂,图像上可能会出现补片边界。在某些情况下,网络会产生高度冗余的模式,类似于模式崩溃。总之,我已经证明了抽象修复可以使用有限的资源产生具有精细细节的大型艺术品。它构成了一个有趣的和娱乐性的方法,应该进一步探讨!![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/936a38ae736a8463f138fcc8dcc06cf8.png)图 4:谁住在海底的菠萝里?图片作者。# 加尼拉——幻想增强版> 原文:<https://towardsdatascience.com/ganilla-fantasy-enhanced-d4918681820c?source=collection_archive---------22----------------------->## 当人工智能和出色的插图画家携手点燃我们的想象力***由*** [***李奥达甘***](https://medium.com/@liork.dagan)*[***李龙索夫***](https://medium.com/@lironsoffer)*[***达芙娜******。***](https://medium.com/@dafna.mordechai)****在儿童故事中,世界充满了奇迹,疯狂的事情每天都在发生,你发现自己坐在人行道上靠近精灵或仙女也并不罕见。这种魔力在儿童书籍中栩栩如生,伴随着故事可以找到精彩的插图。但是如果机器可以为我们创造这种魔力呢?GANILLA 就是这样一个神经网络,在这篇博文中,我们将向你展示如何做到这一点!**## **什么是加尼拉?****GANILLA 是 GAN ( **生成对抗网络**)的一种,它解决了儿童书籍插图领域的**图像到图像的翻译问题**。在实践中,当你提供一张照片给一个训练有素的 GANILLA 模型时,它会根据特定插图画家的风格输出输入图像的插图。
在下图中,您可以在左侧看到一个输入图像,以及十个不同的输出图像——这是将输入图像输入到十个经过训练的模型的结果,每个模型都使用不同 illustrator 的数据进行训练。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4f570afc34e37bbdaf2d0b7219b44df0.png)****行动中的加尼拉:一个输入图像,十个不同的输出结果,模仿不同的插图艺术家(图像来源:加尼拉的论文: [arXiv:2002.05638v2](https://arxiv.org/abs/2002.05638v2) )****虽然在加尼拉之前就有其他伟大的图像到图像的翻译模型,但这项工作有两个主要的创新点。虽然当前最先进的图像到图像翻译模型成功地传递了风格或内容,但是它们有时不能同时传递两者。在下面的图片中,你可以看到一个例子,其中 GANILLA 保留了原始输入照片的内容和所需插画师的风格。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7b83307fc8974392de5c178d05249a10.png)****与 CycleGAN 和 DualGan 相比,GANILLA 的两个输出示例(图片来源:GANILLA 的论文: [arXiv:2002.05638v2](https://arxiv.org/abs/2002.05638v2) )****除了模型本身,本文还介绍了一种新的定量方法来评估图像到插图的模型。他们不是主观地评估图像,而是通过使用单独的分类器定义考虑内容和风格的指标来制定评估过程。**# **用于不成对图像到图像翻译的数据集****当处理图像到图像的翻译问题时,我们的数据可以是两种类型之一:成对图像或不成对图像。配对数据集是一个集合,其中每个输入图像都有一个预定义的输出图像。这是一种标记数据的形式。 [pix2pix 数据集](https://www.kaggle.com/vikramtiwari/pix2pix-dataset)就是成对数据的一个例子。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0b2a2f8eba87f1844adec527e38d00c9.png)****来自 [pix2pix 数据集](https://www.kaggle.com/vikramtiwari/pix2pix-dataset)的图像对示例****不成对的数据集由来自两个不同域的两个图像池组成,它们之间没有标记,也没有预定义的相关性。领域之间的映射是一个无监督的学习问题。输入域是自然照片,预期输出域是儿童书籍插图。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/09bb2abd8321bc75cc629c654f047d1e.png)****一个不成对的数据集:风景照片(第一排)和宫崎骏**(第二排)的插图****# ****架构概述****## ****加尼拉发电机********模型的核心是发电机。训练时,它将用于推理,即生成器将接收风景照片作为输入,并返回插图图像作为输出。
发电机有两部分;下采样(编码)阶段基于 ResNet,负责从原始图像中提取特征(输入图像内容)。上采样(解码)阶段是特征金字塔网络(FPN),并且负责从先前提取的信息中创建输出图示(输出图像风格)。
在 GANILLA [中实现的另一个概念是跳过连接](https://theaisummer.com/skip-connections/)。它在下图中用蓝线表示,顾名思义,它连接模型的各个部分,但不是以直接的方式,而是通过跳过一些层,并在模型中不连续的层之间传输信息。********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/81e3660825e78ddcd65e54e271b4770f.png)********加尼拉的发电机架构(图片来源:加尼拉的论文: [arXiv:2002.05638v2](https://arxiv.org/abs/2002.05638v2) )****## ****加尼拉的 D **是首席法官**********与 GAN 模型一样,训练过程需要一个**鉴别器**来评估发电机输出的质量。从技术上来说,鉴别器是一种分类器,用于评估生成的图像是“真”还是“假”。
随着发生器和鉴别器一起接受训练,两者的作用变得更好、更准确,发生器产生更高质量的图像,而鉴别器在区分真假图像方面变得更好。********加尼拉的鉴别器实现了 **PatchGAN,**一种在 [pix2pix](https://arxiv.org/pdf/1611.07004v3.pdf) 论文中介绍的方法。PatchGAN 鉴别器或马尔可夫鉴别器不将整个图像分类为真实或伪造,而是将图像分成 NxN 个片段,并分别对它们进行分类。鉴别器在图像上卷积运行,平均所有响应以提供结果。与对整个图像进行分类相比,PatchGAN 鉴别器具有更少的参数,运行速度更快,同时实施更多的约束,以促进生成的图像中清晰的高频细节。********下图比较了不同 n 值的结果。发现 70x70 面片产生的结果最清晰,人眼可看到的拖尾伪影较少,但代价是空间和光谱维度(细节和色彩)的准确性较低。********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/bc6e02e3de1f3961e7294c338f113fa0.png)********PatchGAN 对于不同 N 值的结果(图片来源:pix 2 pix paper:[arXiv:1611.07004 v3](https://arxiv.org/abs/1611.07004v3))****## ****无监督对偶学习********为了从两个域的两组未标记图像中进行训练,GANILLA 使用了在 [DualGAN](https://arxiv.org/pdf/1704.02510.pdf) 论文中介绍的方法。受自然语言翻译双重学习的启发,该方法在训练过程中使用两对生成器和鉴别器。
第一个也是主要的一个,G,是将用于推理的生成器。次要生成器 F 学习相反方向的映射:从目的域(Y,插图)到源域(X,风景照片)。用于训练的损失函数类似于 [CycleGAN](https://arxiv.org/pdf/1703.10593.pdf) 纸上的损失函数。****## ****损失函数与循环一致性和恒等性********加尼拉的损失函数是几个值的和。其中两个是两台发电机的最小最大损耗(BCE)。********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0479773dfbdd65d1cd521031961262a4.png)********将辅助生成器 F: Y → X 训练成主生成器 G: X → Y 的反函数。这将通过两个损失函数来完成:*****   ******循环一致性损失:** F(G(x)) ~ x 和 G(F(Y)) ~ Y 由 L1 距离强制。****
*   ******身份丢失:** G(Y) = Y,F(X) = X 也受 L1 距离的影响。********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e961cbd60387017f0290a1ac78c9175f.png)********F(G(X)) ~ X 的循环一致性性质的说明同样适用于 G(F(Y)) ~Y********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b04f72095aeb1c2ca610e9eae42487f6.png)********恒等性质的说明:G(Y) = Y,F(X) = X****# ****轮到我们了!********在阅读了加尼拉的论文并理解了架构之后,**我们已经从头开始实现了它**,并得到了我们的结果。我们使用相同的景观图像作为我们的源域。对于目的地领域,我们选择了宫崎骏<https://en.wikipedia.org/wiki/Hayao_Miyazaki>**的作品,那是我们从网上刮下来的。我们的代码可以在这里找到,这里是我们的一些结果:************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/41409cf21e147d99c45851951ccd4276.png)************我们实现加尼拉模型的例子。上面的图像是原始照片,下面的是模型输出的插图图像******# ******轮到你了!************想开始自己的深度学习副业?不确定从哪里开始?
[这篇博文只为你!](https://medium.com/@liork.dagan/how-deep-is-your-love-or-how-to-choose-your-first-deep-learning-side-project-524f3700813d)******## ******想从 GANILLA 开始吗?************以下是一些有用的网址:*******   ******[加尼拉纸](https://arxiv.org/abs/2002.05638)。******
*   ******YouTube 频道“[两分钟论文](https://www.youtube.com/watch?v=-IbNmc2mTz4)中关于它的概述。******
*   ******加尼拉[数据集](https://github.com/giddyyupp/ganilla/blob/master/docs/datasets.md)******
*   ******我们实现论文的 [GitHub](https://github.com/liorkdagan-dev/ganilla) 资源库。******
*   ******最初的 [GitHub](https://github.com/giddyyupp/ganilla/) 文件库。******# 从零开始> 原文:<https://towardsdatascience.com/gans-from-scratch-19e917edf3ea?source=collection_archive---------31----------------------->## 决斗神经网络神经网络不仅限于学习数据;他们也可以学习创造它。其中一篇经典的机器学习论文是伊恩·j·古德费勒(Ian J. Goodfellow)、让·普盖-阿巴迪(Jean Pouget-Abadie)、迈赫迪·米尔扎(Mehdi Mirza)等人撰写的 [*生成对抗网络*](https://arxiv.org/abs/1406.2661) (GANs) (2014)。gan 采用两个对立的神经网络的形式,一个学习生成假样本,而另一个试图将真样本与假样本分开。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/28209922a3226806fc5165f991843b89.png)VQGAN 根据来自 Flickr 的数据训练生成的风景。这些图像都不是真实的。[来源](https://compvis.github.io/taming-transformers/)复杂的 GAN 模型,如 VQGAN 和其他模型,可以生成任何东西,包括假的风景、人脸,甚至是[《我的世界》](https://arxiv.org/abs/2106.10155v1)世界。这些是我对第一次介绍 GANs 的经典论文的笔记。# 设置gan 基本上是由两个神经网络模型组成的两部分二元分类问题。第一个被称为**生成器**的模型接受仅由噪声组成的输入,并创建与它正在学习伪造的数据形状相同的输出。另一个模型是**鉴别器**,它接受真实和生成的输入,并输出数据是真实还是虚假的预测。# 失败理解生成器和鉴别器之间博弈的关键是价值函数和**二进制交叉熵** (BCE)损失之间的联系。论文中的等式解释了两者的目标。暂时忽略最小值/最大值部分,等式的其余部分描述了**值函数、** *V(D,G)* 。值函数是鉴频器输出的对数的期望值, *D(x)* ,其中 *x* 取自真实数据加上对数的期望值 1 减去作用于所产生输出的鉴频器输出, *D(G(z))* ,其中发生器的输入, *z* 取自噪声。现在,再次查看最小值/最大值部分,生成器的目标是最小化值函数,而鉴别器的目标是最大化值函数。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2c4ca4ea104c0fb1450afe364d8cbb1a.png)但是价值函数和 BCE 有什么关系呢?下面是 BCE 损失的等式,其中 *y* 是真实标签,ŷ是模型预测。因此,如果真数据的标签是 1,假数据的标签是 0,则价值函数变成假数据损失的总和( *y=0* 和*ŷ=d(g(z)*)和真数据损失的总和( *y=1* 和 *ŷ=D(x)* )。等式的一半抵消了每次损失。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f44e1ed0717aa78ef66133137d8e61e0.png)基于最小值/最大值约定,减号消失。下面绘制的价值函数说明了这一点。生成器的目标是让鉴别器将假数据误分类为真实数据,将真实数据误分类为假数据,对应于下面蓝色和金色曲线的低(最小)值。鉴别器的目标是正确地对每一个样本进行分类,这两个样本在两条曲线上都具有零值函数(最大值)。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/491d4ae299fbf9752bcc7519306db257.png)GAN 值函数,发生器工作以最小化这些曲线上的值,而鉴别器试图最大化它们# 培养这两个模型一起训练。下面的代码展示了 TensorFlow 中的一个例子。首先,通过绘制一批噪声和一批真实数据来训练鉴别器。鉴频器损耗如前所述进行计算,并更新其权重。接下来,通过绘制另一批随机噪声并使其通过生成器来训练生成器。鉴别器对生成的数据进行分类,并根据生成器欺骗鉴别器的程度对其进行评分。基于该梯度更新发生器权重,并且重复该过程。随着两个模型的训练,生成数据的分布(绿线)变得看起来像真实数据的分布(黑色虚线),直到鉴别器预测(蓝色虚线)不再能够区分,并预测真实和虚假输入的概率为 50%。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/71d0b655c4f090715cd2dc5fb1de65cb.png)变速发电机输出分配和分类([来源](https://arxiv.org/abs/1406.2661)以下是在不同训练阶段的一些生成器输出示例。我使用 MNIST 数数据集来构建 GAN。随着时间的推移,随着生成器开始产生看起来像训练集的图像,鉴别器对其预测哪个样本是真的哪个样本是假的越来越没有信心。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/de8bac1cd736e2b69a153242c0e05754.png)不同时期的发电机输出甘人很难训练。例如,在这个使用来自 MNIST 的单个示例的测试案例中,生成器在几百个步骤之后很快学会了复制示例 5。然而,随着训练的继续,发电机输出迅速偏离。发电机也可以发散回学习率过高的噪声。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7b5a9266667fe0a44e0f070967c25516.png)不良培训设置导致的示例。发电机培训出现分歧。管理两个网络之间的平衡也很困难。如果鉴别器太好,可能会导致训练问题,因此可能需要调整训练设置中的参数。最先进的 GANs 在生成现实内容方面非常强大,可以用于善意和恶意。希望这些笔记有助于理解它们的基本工作原理。你可以在这里找到我用来学习甘斯[的笔记本](https://github.com/tims457/ml_notebooks/blob/main/gans/gans.ipynb)。# 参考*   [甘纸](https://arxiv.org/abs/1406.2661)
*   [伊恩·古德菲勒谈莱克斯·弗里德曼](https://www.youtube.com/watch?v=Z6rxFNMGdn0)# 甘斯卡皮斯:用人工智能创造新的印象派绘画> 原文:<https://towardsdatascience.com/ganscapes-using-ai-to-create-new-impressionist-paintings-d6af1cf94c56?source=collection_archive---------11----------------------->## [实践教程](https://towardsdatascience.com/tagged/hands-on-tutorials)## 我如何在公共领域用 5000 幅印象派风景画训练 StyleGAN2 ADA![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/961a8d4bf6fd295e8ed3a6e1caae8e76.png)**甘斯卡皮斯样本输出**,图片由作者提供这是我的第三篇关于尝试用生成性对抗网络(GANs)来创作美术的文章。前两篇文章关注的是[通过](/machineray-using-ai-to-create-abstract-art-39829438076a)[使用图像增强](/creating-abstract-art-with-stylegan2-ada-ea3676396ffb)来创作抽象艺术,但这篇文章关注的是创作印象派风景画。我把 GANscapes 的所有[源代码](https://github.com/robgon-art/GANscapes)贴在 GitHub 上,把原画贴在 Kaggle 上。你可以在这里使用[谷歌实验室](https://colab.research.google.com/github/robgon-art/GANscapes/blob/main/GANscapes_Image_Generation_with_CLIP_Filter.ipynb)创作新的风景画。# 先前的工作已经有几个项目和论文展示了如何使用 GANs 来创作风景画。昆士兰科技大学的 Drew Flaherty 的硕士论文题为“机器学习的艺术方法”,他在论文中使用了原始的 StyleGAN [1]。爱丽丝·薛(Alice Xue)在她的论文“使用生成性对抗网络进行端到端的中国山水画创作”中描述了 SAPGAN[2]。和刘等人在他们的论文中创造了一种轻量级 GAN,“实现更快和稳定的 GAN 训练以实现高保真少量拍摄图像合成”[3]。下面是 StyleGAN、SAPGAN、Lightweight GAN 和 GANscapes 的绘画样本。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7b5fa6fdd8f0fce9bdb53d926906e79b.png)**甘山水样本,**自上而下,**德鲁·弗莱厄蒂训练的风格甘**、爱丽丝·薛的**萨甘**、刘等人的**轻灵甘**、作者的**甘山水**# GANscapes 概述GANscapes 是一个利用人工智能的最新进展创造新的印象派风景画的系统。这张图显示了主要的系统组件。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0c2c91501575da6c1d645510d8cf5bf7.png)**GANscapes 系统组件,**作者提供的图表## 组件概述以下是对 GANscapes 中使用的组件的简要概述。我将在本文后面讨论每个组件的细节。我从 WikiArt.org 收集了印象派风景画的图片,并对这些图片进行处理以调整长宽比。然后,我使用 OpenAI 的剪辑模型[5]来过滤图像,以保留“好的”我用这些图像来训练 NVidia 的 StyleGAN2 ADA [6],它有一个生成器和鉴别器网络。生成器从形式和风格的随机“潜在”向量开始创建新图像,并试图欺骗鉴别器,使其认为输出的图像是真实的。在将真实图像和生成的图像输入鉴别器之前,会使用自适应鉴别器增强(ADA)模块对其进行轻微修改,从而在图片中创建视觉多样性。我再次使用 CLIP 根据用户提供的文本查询过滤输出图像。我再次使用生成器来创建一个混合了用户选择的样式和形式的图像。最后一步,我对最终图像进行后处理,以调整宽高比。请务必查看文章末尾附录中的图片集,以查看更多结果。## 收集图像![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/05a11ce3b8150b458eeb1649b0f2989e.png)**阿让特伊塞纳河上的克洛德·莫内和他的秋天,**来源 WikiArt.org我开始在[实验室](https://colab.research.google.com/github/robgon-art/GANscapes/blob/main/1_GANscapes_Gather_Images.ipynb)用自定义的 python 脚本抓取 WikiArt.org 的风景画。该脚本按字母顺序遍历网站上的每个艺术家。它检查艺术家是否被标记为“印象主义”艺术运动的一部分,以及他们是否生于 1800 年之后,死于 1950 年之前。然后,脚本遍历所有艺术家的画作,寻找公共领域中可用的“风景”类型的作品。然后,脚本使用艺术家和绘画名称作为文件名下载每个符合条件的图像,即 Claude-Monet _ landscape-at-giver ny-1 . jpg。系统找到了大约 5,300 幅符合这些标准的绘画。这是一幅 WikiArt.org 印象派绘画的样本。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5b4196d2c602d1546362b8e537147dda.png)**印象派风景画**,来源 WikiArt.org## 调整训练图像的纵横比你会从上面的绘画样本中注意到,它们有不同的长宽比,例如,一些图像比其他图像宽很多。由于 GAN 系统在处理完美的正方形图像时效率更高,因此需要调整源图像的纵横比。通常使用三种技术来进行调整,各有利弊。我将以德加的瓦莱里索姆河湾*景观为例,展示不同的方法。*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/99403c1f39781ab3536e683984d5021c.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3b377460d1b9c5cace1677d528e60439.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6905690f499104f316593a24f0bc48a2.png)**信箱、中心切割和压缩格式**,图片由德加制作,由作者格式化上面第一幅图像中的“信箱”格式保持了图像的不剪切和不挤压,但在上下添加了黑条,使图像具有方形形状。信箱格式的问题是,整个图像被有效地缩小了尺寸,失去了分辨率,黑色部分在 GAN 训练中被“浪费”了。第二个图像是“中心剪切”格式,它被剪切以保持图像的正方形中心。中心切割格式的问题是左右两边的图像明显丢失。第三个图像被水平挤压成正方形。压缩格式的问题是绘画中的对象被扭曲了。例如,在这张图片中,风车变得更薄了。而且每幅画都会被挤压不同的量,这取决于原始的长宽比。对于这个项目,我想出了一个混合技术,这似乎是一个很好的妥协。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4b1866a9b86ef9a34334c6917a2b9164.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e823923297e5d83385e9490b4ef865ae.png)**1.27:1 矩形切割和 1.27:1 挤压格式**,图片由德加制作,作者格式化我的混合解决方案需要首先确定所有原画的平均长宽比,对于数据集来说是 1.27:1。接下来,我将每张图片裁剪成 1.27:1 的纵横比,拉出一个中心矩形。然后,我将裁剪后的图像水平压缩成分辨率为 1024 x 1024 像素的正方形格式,并将结果图像用于我的训练数据集。当 GAN 产生方形输出图像时,我将其缩放回 1.27:1,以匹配原始格式。这个过程的结果将是无失真的合成生成的图像。这种“中心矩形”格式似乎是中心切割和挤压格式之间的一个很好的妥协,特别是因为原始的风景画是风景格式。然而,这种方法不能很好地处理横向和纵向混合格式的图像,因为它倾向于中心切割格式。源代码在[的实验室里](https://colab.research.google.com/github/robgon-art/GANscapes/blob/main/2_GANscapes_Process_Images.ipynb)。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2e105c5dc31a3de1b86226e8ba3b8c48.png)**Durand-Ruel 画廊的主展厅**,Charles-Fran ois Daubigny 的蚀刻作品,来源[https://www.pubhist.com/w30198](https://www.pubhist.com/w30198)## 使用剪辑判断训练图像仅仅因为一幅画在 WikiArt 上被标记为印象派画家的风景画,并不意味着它是这样一幅画的好代表。在我之前用 GAN 生成抽象艺术的项目中,我“手动选择”了源图像,这相当耗时(并且让我觉得有点“武断”)。对于这个项目,我使用了一个新的开源人工智能系统,名为 CLIP from OpenAI [5]来进行图像过滤。OpenAI 设计了两个模型,一个图像编码器和一个文本编码器。他们在带有相应短语的图像数据集上训练这两个模型。模型的目标是使编码图像与编码短语相匹配。一旦经过训练,图像编码器系统将图像转换为嵌入,即捕获图像一般特征的 512 个浮点数的列表。文本编码器将文本短语转换为类似的嵌入,该嵌入可以与图像嵌入进行比较以进行语义搜索。对于 GANscapes,我将短语“印象派风景画”中的嵌入内容与 5300 幅画中的嵌入内容进行比较,以找到最符合该短语的图像。源代码在[栏的](https://colab.research.google.com/github/robgon-art/GANscapes/blob/main/3_GANscapes_Filter_Images.ipynb)这里。根据 CLIP 的说法,以下是符合短语“印象派风景画”的前 24 幅图像。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/39705961c2498f87cd31057fd1198fcf.png)**顶级印象派风景画据剪辑**,图片由作者提供,来源 WikiArt.org还不错!对树和水的描绘似乎很多,但画风各异。下面是根据剪辑的底部 24 个图像。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cb505d2a556b3403598e6d51dfce64db.png)【WikiArt.org】底印象派风景画据剪辑,图片由作者提供,来源好吧,我明白为什么 CLIP 认为这些图像不符合“印象派风景画”这个短语了除了左边的两张灰度图像,大部分都是人物、建筑、抽象画等。我看了一下 5000 大关附近的图像,似乎还过得去。所以在这 5314 张图片中,我把最下面的 314 张移到了一个名为“拒绝沙龙”的文件夹中,并把它们排除在训练之外。## **生成对抗网络**2014 年,蒙特利尔大学的 Ian Goodfellow 和他的合著者提交了一篇关于 GANs 的论文[7]。他们想出了一种方法来训练两个相互竞争的人工神经网络(ann)来创建逼真的图像。正如我在本文开始时解释的那样,第一个 ANN 称为生成器,第二个称为鉴别器。发生器尝试创建真实的输出。鉴别器试图从来自生成器的假图像中辨别来自训练集的真实图像。在训练过程中,两个 ann 都逐渐提高,效果出奇的好。去年,我创建了一个名为 [MachineRay](/machineray-using-ai-to-create-abstract-art-39829438076a) 的项目,使用 Nvidia 的 StyleGAN2 在公共领域创作基于 20 世纪绘画的抽象艺术品。此后,Nvidia 发布了新版本的人工智能模型 StyleGAN2 ADA,旨在从有限的数据集生成图像时产生更好的结果。StyleGAN2 ADA 的一个重大改进是在训练过程中动态改变图像增强的数量。早在 2020 年 1 月,我就写过这方面的改进。</creating-abstract-art-with-stylegan2-ada-ea3676396ffb>  ## 培训风格 GAN2 ADA我在 Google Colab Pro 上对 GAN 进行了大约三周的培训。因为 Colab 每 24 小时超时一次,所以我把结果保存在我的 Google Drive 上,从它停止的地方继续。下面是我用来开始训练的命令:

!python stylegan2-ada/train.py --aug=ada --mirror=1
--metrics=none --snap=1 --gpus=1
--data=/content/drive/MyDrive/GANscapes/dataset_1024
--outdir=/content/drive/MyDrive/GANscapes/models_1024


我注意到 ADA 变量 *p* 的一个问题,它决定了在训练中使用多少图像增强。因为 *p* 值总是从零开始,系统每天需要一段时间才能回升到 0.2 左右。我在[我的 StyleGAN2 ADA](https://github.com/robgon-art/stylegan2-ada) 的 fork 中修复了这个问题,允许在增强设置为 ADA 时设置 *p* (如果在使用 ADA 时设置了 *p* ,NVidia 的 repo 中的实现将会抛出一个错误。)下面是我在随后的重启中使用的命令。

!python stylegan2-ada/train.py --aug=ada --p 0.186 --mirror=1
--metrics=none --snap=1 --gpus=1
--data=/content/drive/MyDrive/GANscapes/dataset_1024
--outdir=/content/drive/MyDrive/GANscapes/models_1024
--resume=/content/drive/MyDrive/GANscapes/models_1024/00020-dataset_1024-mirror-auto1-ada-p0.183-resumecustom/network-snapshot-000396.pkl


我用最后使用的 *p* 值和之前保存的模型的*恢复*路径替换了 0.186。这是一些来自训练有素的 GANscapes 系统的样本。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a6b358b4e0c687e8d9c611eb578cace3.png)不错!一些生成的绘画看起来比其他的更抽象,但总体来说,质量似乎很好。该系统倾向于很好地描绘自然项目,如树、水、云等。然而,它似乎正在与建筑物、船只和其他人造物体进行斗争。## 使用剪辑来过滤输出图像我再次使用剪辑模型来过滤输出图像。该系统生成 1000 幅图像,并输入 CLIP 以获得图像嵌入。用户可以输入一个提示,比如“秋天树林的印象派绘画”,它会被转换成一个嵌入的剪辑文本。系统将图像嵌入与文本嵌入进行比较,并找到最佳匹配。以下是符合“秋日树林”提示的前 6 幅画。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/70844a84689f9602cc35a07937980522.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e995d030aa5d288be4d399b86fc01b8c.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/92e6f774359992935012adb98efffbed.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ceac8d2acdf8f7252d1095e81b90537c.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f3e08b7d380733638de9f26bcecdfe51.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/dbbe9669167b2c226117706679043e9b.png)**甘斯卡皮斯秋林系列**,图片由作者提供系统不仅为提示找到了合适的匹配,而且整体质量似乎也有所提高。这是因为剪辑系统有效地根据这些画与短语“秋天树林的印象派绘画”的匹配程度来对它们进行评级剪辑将过滤掉任何“时髦”的图像。## 风格混合你有没有想过 NVidia 为什么把他们的模型命名为 StyleGAN?为什么名字里有“风格”二字?答案在架构中。该模型不仅学习如何基于一组训练图像创建新图像,还学习如何基于训练数据集创建具有不同风格的图像。您可以有效地从一个图像中复制“样式”并将其粘贴到第二个图像中,创建第三个图像,该图像保留第一个图像的形式,但采用第二个图像的样式。这叫做**风格混合**。我构建了一个 Google Colab,演示了 GANscapes 的风格混合。它基于 NVidia 的 style_mixing.py 脚本。Colab 为它们的形式渲染了七幅风景,为它们的风格渲染了三幅风景。然后它展示了一个由 21 幅风景组成的网格,将每种形式与每种风格混合在一起。请注意,缩略图被水平放大到 1:127 的纵横比。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e571dd979c01db5381cc1d4611aea471.png)**GANscapes 风格混合**,图片作者如您所见,表单图像从左到右显示在顶部,标记为 F1 到 F7。样式图像从上到下显示在左侧,标记为从 S1 到 S3。7x3 网格中的图像是表单和样式图像的混合。你可以看到这些树是如何被放置在七种形式的图像中大致相同的位置,并且以不同风格渲染的绘画使用相同的调色板,看起来好像它们是在一年中的不同时间绘制的。## 图像后处理我执行了两个后处理步骤,一个温和的对比度调整和图像大小调整,以恢复原始的纵横比。这是代码。

import numpy as np
import PIL# convert the image to use floating point
img_fp = images[generation_indices[0]].astype(np.float32)# stretch the red channel by 0.1% at each end
r_min = np.percentile(img_fp[:,:,0:1], 0.1)
r_max = np.percentile(img_fp[:,:,0:1], 99.9)
img_fp[:,:,0:1] = (img_fp[:,:,0:1]-r_min) * 255.0 / (r_max-r_min)# stretch the green channel by 0.1% at each end
g_min = np.percentile(img_fp[:,:,1:2], 0.1)
g_max = np.percentile(img_fp[:,:,1:2], 99.9)
img_fp[:,:,1:2] = (img_fp[:,:,1:2]-g_min) * 255.0 / (g_max-g_min)# stretch the blue channel by 0.1% at each end
b_min = np.percentile(img_fp[:,:,2:3], 0.1)
b_max = np.percentile(img_fp[:,:,2:3], 99.9)
img_fp[:,:,2:3] = (img_fp[:,:,2:3]-b_min) * 255.0 / (b_max-b_min)# convert the image back to integer, after rounding and clipping
img_int = np.clip(np.round(img_fp), 0, 255).astype(np.uint8)# convert to the image to PIL and resize to fix the aspect ratio
img_pil=PIL.Image.fromarray(img_int)
img_pil=img_pil.resize((1024, int(1024/1.2718)))


代码的第一部分将图像转换为浮点型,找到每个通道的 0.1%最小值和 0.99%最大值,并放大对比度。这类似于 Photoshop 中的调整色阶功能。代码的第二部分将图像转换回整数,并将其大小调整为 1.27 比 1 的纵横比。这里有三幅风格混合的画,分别是后期处理前后的。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e527f3abe63c537dd773602315203660.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ef8105e7a03861c183d5cb5e3650a47c.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/76b7659ea941036bcb3f8c68d34b0ae5.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d484316d53b6a662e8469a6ca5981029.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2702f0e0601804d7246a2cc9d0e2c771.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/968d78d392499dd473e298b22e07e5f0.png)**甘斯卡皮斯 F4S1,F7S2,F1S3** ,图片由作者提供你可以点击每张图片仔细查看。# 讨论GANscapes 创作的风景画的质量可以归功于 StyleGAN2 ADA 和 CLIP 模型。通过设计,StyleGAN2 ADA 可以在有限的数据集上进行训练,以产生出色的结果。请注意,GANs 生成的图像在图像间连续流动。除非输入图像被标记为分类,否则结果之间没有硬中断。如果输入的潜在向量改变一点,结果图像也会改变一点。如果矢量变化很大,图像也会变化很大。这意味着系统有效地从一个场景变形到所有可能的邻居。有时,这些“中间”图像会有奇怪的伪像,就像一棵树部分溶解在云里。这就是 CLIP 的用武之地。因为它根据图像与文本查询(即“印象派风景画”)的匹配程度对图像进行评级,所以它倾向于挑选没有奇怪伪像的完整图像。CLIP 模型有效地解决了未标记 gan 的部分变形问题。# 未来的工作有几种不同的方法来改进和扩展这个项目。首先,绘画的质量可以通过一种叫做学习转移的技术来提高。这可以通过首先在风景照片上训练甘,然后继续在风景画上训练来完成。我可以通过多次迭代 StyleGAN → CLIP → StyleGAN → CLIP 等来改进文本到图像的生成。这可以通过像 CLIPGLaSS [9]中的遗传算法或者梯度下降和反向传播来实现。这与 Victor Perez 在 Medium [10]的文章中描述的训练人工神经网络的方法相同。最后,最近关于不可替换令牌(NFT)如何被用来验证数字文件所有者的新闻让我想到了一个可能的 NFTs 甘混合体。潜在的收藏者可以出价购买一系列潜在向量,而不是购买单个 JPEG 文件的所有权,这些潜在向量在经过训练的 GAN 中生成图像和/或风格的变化。嘿,你们先在这里读吧,伙计们!# 源代码我收集的 5000 幅抽象画可以在 [Kaggle 这里](https://www.kaggle.com/robgonsalves/impressionistlandscapespaintings)找到。这个项目的所有[源代码](https://github.com/robgon-art/GANscapes)都可以在 GitHub 上获得。Kaggle 上绘画的图像和源代码在 [CC BY-SA 许可](https://creativecommons.org/licenses/by-sa/4.0/)下发布。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2668f344f4170d0e90563d6dc208e439.png)归属共享相似# 感谢我要感谢詹尼弗·林和奥利弗·斯特瑞普对本文的帮助。# 参考[1] D. Flaherty,“机器学习的艺术方法”,2020 年 5 月 22 日,昆士兰科技大学,硕士论文,[https://eprints . qut . edu . au/200191/1/Drew _ Flaherty _ Thesis . pdf](https://eprints.qut.edu.au/200191/1/Drew_Flaherty_Thesis.pdf)[2] A .徐,《端到端的中国山水画创作运用
生成性对抗网络》,2020 年 11 月 11 日,[https://open access . the CVF . com/content/WACV 2021/papers/Xue _ End-to-End _ Chinese _ Landscape _ Painting _ Creation _ Using _ Generative _ Adversarial _ Networks _ WACV _ 2021 _ paper . pdf](https://openaccess.thecvf.com/content/WACV2021/papers/Xue_End-to-End_Chinese_Landscape_Painting_Creation_Using_Generative_Adversarial_Networks_WACV_2021_paper.pdf)[3] B .刘,Y .朱,k .宋,A. Elgammal,“实现高保真少镜头图像合成的更快和更稳定的 GAN 训练”,2021 年 1 月 12 日,[4]维基百科,2008 年 12 月 26 日,[https://www.wikiart.org](https://www.wikiart.org/)[5] A .拉德福德,J. W .金,c .哈勒西,a .拉梅什,g .高,s .阿加瓦尔,g .萨斯特里,a .阿斯克尔,p .米什金,j .克拉克等人,《从自然语言监督中学习可转移的视觉模型》,2021 年 1 月 5 日,[https://cdn . open ai . com/papers/Learning _ Transferable _ Visual _ Models _ From _ Natural _ Language _ Supervision . pdf](https://cdn.openai.com/papers/Learning_Transferable_Visual_Models_From_Natural_Language_Supervision.pdf)[6] T. Karras,M. Aittala,J. Hellsten,S. Laine,J. Lehtinen 和 T. Aila,“用有限数据训练生成性对抗网络”,2020 年 10 月 7 日,【https://arxiv.org/pdf/2006.06676.pdf [7] I .古德费勒,j .普热-阿巴迪,m .米尔扎,b .徐,D .沃德-法利,s .奥泽尔,a .库维尔,y .本吉奥,《生成性对抗性网络》,2014 年 6 月 10 日,【https://arxiv.org/pdf/1406.2661.pdf】[8] S. Bozinovskim 和 A. Fulgosi,“模式相似性和迁移学习对基本感知机 B2 训练的影响。”信息研讨会会议录,1976 年第 3-121-5 期[9] F. Galatolo,M.G.C.A. Cimino 和 G. Vaglini,“通过剪辑引导的生成潜在空间搜索从字幕生成图像,反之亦然”,2021 年 2 月 26 日,[https://arxiv.org/pdf/2102.01645.pdf](https://arxiv.org/pdf/2102.01645.pdf)[10] V. Perez,“使用 CLIP 和 StyleGAN 从提示生成图像”,2021 年 2 月 6 日,[https://towardsdatascience . com/Generating-Images-from-Prompts-using-CLIP-and-style gan-1 F9 ed 495 ddda](/generating-images-from-prompts-using-clip-and-stylegan-1f9ed495ddda)# 附录—甘斯卡皮斯画廊这是一组已完成的画。请注意,您可以单击放大任何图像。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/52d6d9b1becdcabcf6a8c244bea35459.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/83f49772d4af8f8a24176819218a8a52.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d754721ec5efd646b5ead6d19af6e6b9.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/97ad83d4f807ca7fe78afe8381017c49.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6b9259ff40a7f545b1c6b9523ea4e8ae.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/df2655ed155b29499445b61ce26cb63b.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c67f9586cc92103ded57e1aaead428cf.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2be524152d2e203e1c95915e1f94ef08.png)为了无限制地访问 Medium 上的所有文章,[成为会员](https://robgon.medium.com/membership),每月支付 5 美元。非会员每月只能看三个锁定的故事。# 甘沙尔:用人工智能创造和管理艺术,以获取乐趣和利润> 原文:<https://towardsdatascience.com/ganshare-creating-and-curating-art-with-ai-for-fun-and-profit-1b3b4dcd7376?source=collection_archive---------1----------------------->## 使用 CLIP 和 VQGAN 模型生成 ChromaScapes,即在 OpenSea 上作为 NFT 出售的高质量数字绘画![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/42d82a01feea5ab425115d94a9c7e15f.png)**由 GANshare One 创建的色彩场景样本,**作者提供的图片2020 年 8 月,我第一次写了关于使用生成性对抗网络(GANs)来创造视觉艺术的文章。为了那个项目, [MachineRay](/machineray-using-ai-to-create-abstract-art-39829438076a?source=user_profile---------13----------------------------) ,我用公共领域的抽象画来训练 NVidia 的 style gan 2【1】创作新的作品。从那以后,我又写了几篇关于使用 GANs 制作艺术作品的文章[。从我收到的反馈中,我可以看出一些读者想学习如何制作数字艺术作品,作为不可替代的代币(NFT)在一个新兴的市场中出售。](https://robgon.medium.com/list/creating-fine-art-with-gans-73476c209de3)如果你不熟悉加密货币和 NFTs,这里有一个简单的类比。> 加密货币之于贵金属,就像 NFT 之于宝石一样。每盎司纯金的价值都是一样的,但每颗钻石都是独一无二的,因此价值也不同。为了这个项目,我一头扎进了 NFTs 的世界。我不仅创作并出售新创作的数字艺术作品,还出售受过训练的甘的“股份”,让其他艺术家制作他们自己的数字艺术作品,作为非数字艺术作品出售。我把这个概念叫做“GANshare”,我的第一个人工智能模型叫做 GANshare One。# GANshare One 组件这是系统的高级示意图,其中简要描述了组件。再往下,你可以找到每个部分的细节。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/18e23003dda79b12d0a5ee7494f8655e.png)**GANshare 组件图,**作者图片我开始在公共领域收集来自 WikiArt.org 的 50,000 多幅画。然后我训练了一个新的人工智能模型,名为 VQGAN [2],是在德国海德堡大学开发的。VQGAN 有一个图像编码器、转换器和解码器,用于创建新图像,还有一个鉴别器,用于检测生成的图像部分是真实的还是生成的。我使用 VQGAN 根据文本提示创建新的绘画。我从文本文件中自动生成提示,这些文本文件包含绘画风格、几何形状、地理位置的列表,以及大量颜色名称的列表。我使用 OpenAI 的 CLIP model [3]来控制 VQGAN 解码器,使用 Pytorch 库中的 Adam optimizer [4]生成一幅数字绘画来匹配提示。我使用 ISR 超分辨率 Resizer [5]将图像放大到 1024x1024,并发布到 OpenSea 上作为 NFT 出售。你可以在这里查看艺术品的样品:[https://opensea.io/collection/chromascapes](https://opensea.io/collection/chromascapes)# GANshare One 系统详情本节将更详细地讨论我用来构建 GANshare One 系统的组件。## 收集图像类似于我为我的[磁铁](/magnet-modern-art-generator-using-deep-neural-networks-57537457bb7)项目所做的,我使用一个定制的 python 脚本从 WikiArt.org 收集绘画作为训练数据。剧本按字母顺序浏览了网站上的每个艺术家。它检查了这些艺术家是否生于 1800 年之后,死于 1950 年之前。然后,它检查每个艺术家的画,以确保它们是在公共领域,然后将它们复制到我的谷歌驱动器的文件夹中。它找到了 52,288 张符合我标准的图片。这里有一些我用来训练 GANshare One 的原画,来自康定斯基、梵高和毕加索等艺术家。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a8114d91f740e116395c8cad98de6175.png)**训练图片**,来源 WikiArt.org## VQGANEsser 等人的矢量量化生成对抗网络(VQGAN)模型是一种用于生成高质量图像的混合 GAN/Transformer 模型[2]。在他们题为“驯服高分辨率图像合成的变形金刚”的论文中,作者声明他们的方法学习…> …由上下文丰富的可视部分组成的码本,其组成随后用自回归转换器架构建模。离散码本提供了这些架构之间的接口,基于补丁的鉴别器支持强压缩,同时保持高感知质量。该方法将卷积方法的效率引入到基于变换的高分辨率图像合成中。帕特里克·埃塞尔、罗宾·龙巴赫和比约恩·奥默这是他们的 VQGAN 架构图。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f821de490d42c0a2c04cc82e9c0a8a10.png)**VQGAN 架构**,来自 Esser 等人的[驯服变压器用于高分辨率图像合成](https://compvis.github.io/taming-transformers/paper/paper.pdf)。在我收集了我的训练图像之后,我使用我的 Google Colab Pro [7]帐户使用这个命令来训练 VQGAN:

!python main.py -b configs/custom_vqgan.yaml --train True --gpus 0,


因为 VQGAN 是一个混合变压器模型,它在训练期间向您显示原始和编码的样本。下面是一组示例图像。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6895631599d5e8b9cb70ced3a2f713ba.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a628ebe6932557d73c491e7b3df418b7.png)**使用 VQGAN 的原始和重新编码图像**,(左)WikiArt.org,(右)作者你可以看到模型在重建原始图像方面做得很好,但它似乎对一些面部特征做了自己的事情,如眼睛和嘴巴。总的来说,我发现 VQGAN 工作得很好。下表比较了经典 GAN 和 VQGAN 的一些特性。

Feature Classic GAN VQGAN Discriminator: All-or-nothing Sub-image
Output Image Size: Fixed Size Variable Size
Reverse Encoding: Iterative Process Trained Encoder
Image Generation: New Images Look Good Images Need Steering


对于 VQGAN,训练很快,因为图像的每个部分都由鉴别器检查,而传统的 GAN 使用全有或全无的方法进行训练。换句话说,VQGAN 中的鉴别器查看 4x4 网格中的 16 个子图像,并对每个部分给发生器一个向上或向下的大拇指作为改进的反馈。经典 GAN 中的鉴别器为整个图像向发生器提供单个拇指向上或向下。对于经典的 GANs,输出图像总是固定大小。因为它与“代码本”一起工作,VQGAN 可以输出不同大小的图像。例如,我用 256x256 输入图像训练 VQGAN,并用它产生 512x512 输出图像。例如,以下是以 256x256 和 512x512 渲染的提示“起伏的农田”的生成图像。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b419fff1b3ffb3f0cb9891e6e8176b96.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2edc541985fba7542cda128ed123e11f.png)起伏的农田,渲染尺寸为(左)256x256 和(右)512x512,图片由作者提供请注意 512x512 图像中的更多功能。这是因为 VQGANs 码本中的特征是以 256x256 的比例学习的,并被渲染为对更大画面的较小贡献。512x512 图像的输出类似于将多个晕影合并在一起。经典的 GANs 没有用于反向编码的内置模型,反向编码是一种在给定任意真实图像的情况下寻找最接近的生成图像的过程。对于经典 GAN 来说,这必须通过迭代方法来完成,并且它并不总是工作得很好。然而,反向编码对于 VQGAN 模型来说很容易,因为它实际上是一种编解码器。它有一个将图像编码成嵌入的模型和一个将嵌入解码成图像的相应模型。前三点都是 VQGAN 的优势。然而,第四点是很容易从经典的 GANs 产生输出图像。只要给它一些随机数,它就会生成一个好看的图片。但是 VQGAN 没有制作新图像的简单方法。如果给解码器一些随机数,输出的图像就不连贯了。VQGAN 需要由一些其他过程来控制,比如使用剪辑模型生成可识别图像的文本提示。## OpenAI 的剪辑模型OpenAI 设计并训练了一个名为 CLIP 的人工智能系统,代表对比语言-图像预训练[3]。CLIP 系统有一个图像和文本编码器,它可以用来执行跨模态语义搜索,例如,你可以使用单词来搜索图像,正如我在我的 [MAGnet](/magnet-modern-art-generator-using-deep-neural-networks-57537457bb7) 项目中所做的那样。OpenAI 在带有相应短语的图像数据集上训练编码器。训练的目标是使编码图像与编码单词相匹配。一旦经过训练,图像编码器系统将图像转换为嵌入,即捕获图像一般特征的 512 个浮点数的列表。文本编码器将文本短语转换为相似的嵌入,该嵌入可以与图像嵌入进行比较以进行语义搜索。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2a4e37de00d03e9b2dabd277bb65058e.png)**对比语言-图像预训练(剪辑)**,OpenAI 图像例如,如果您有一个图像数据库,您可以通过图像编码器运行每个图像,以获得图像嵌入的列表。如果您随后通过文本编码器运行短语“绿色草坪上的小狗”,您可以找到与该短语最匹配的图像。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b088af21d4d839f16352a906ce0f76ab.png)**待办事项清单**,作者图片说明,基于莱克西·詹尼在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的一张照片## 生成提示如上所述,GANshare 系统使用文本提示创建由 CLIP 控制的图像。比如说,如果你告诉 VQGAN+CLIP 创建一幅“橙色圆圈的抽象画”,它就会创建一幅。为了画出大量的画,我生成了包含三个不同部分的提示:风格、主题和颜色。经过试验,我发现这九种风格相当不错:抽象、立体主义、表现主义、野兽派、未来主义、几何、印象派、后现代和超现实主义。对于主题,我从三个类别中选择:几何形状、地理特征和物体。我从伊万·马洛平斯基的[单词表](https://github.com/imsky/wordlists/tree/master/nouns)开始,为我的形状和地理特征列表做了一些调整。对于我的物品列表,我组合了由 [COCO](https://cocodataset.org/#home) 和 [CIFAR 100](https://www.cs.toronto.edu/~kriz/cifar.html) 检测系统识别的物品列表,得到 181 个物品的列表。我从维基百科[中抓取了一份颜色名称的详细列表,并稍微编辑了一下,得到了 805 种独特的颜色。](https://en.wikipedia.org/wiki/List_of_colors:_A%E2%80%93F)这是四个列表中的前七个条目。

shapes.txt places.txt things.txt colors.csv angles an archipelago an airplane absolute zero
blobs an atoll an apple acid green
circles a beach apples aero
cones a bay an aquarium fish aero blue
cubes a butte a baby african violet
curves a canal a backpack alabaster
cylinders a canyon a banana alice blue
... ... ... ...


这里有一个[链接](https://gist.github.com/robgon-art/8bdaf6593ae4c1d7ed4037064969e818)到 Python 代码,它通过随机选择样式、主题和颜色来生成提示。下面是代码生成的一些提示。

Futurist Painting of a City in Vivid Burgundy Brown
Abstract Painting with Diagonals in Beige Pink
Impressionist Painting with Prisms in Carolina Blue


现在我们有了一些有趣的提示,接下来我们将看看如何引导 VQGAN 生成相应的图像。## 带夹子的转向 VQGAN在我的 [MAGnet 项目](/magnet-modern-art-generator-using-deep-neural-networks-57537457bb7)中,我使用了一个定制的生成算法,让 CLIP 操纵 StlyeGAN2 的一个变体,根据文本提示创建图像。在这个项目中,我使用了凯瑟琳·克劳森设计的算法,她是一位人工智能/生殖艺术家,在 Twitter 上以 [RiversHaveWings](https://twitter.com/RiversHaveWings) 的身份发布帖子。为了使用 CLIP 控制 VQGAN,她使用 Pytorch 库中的优化器 Adam,Adam 代表自适应矩估计[4]。下面是算法的示意图。请注意,这里有两个嵌入空间。CLIP 系统使用 512 个数的平面嵌入(表示为 *I* 和 *T* ),其中 VQGAN 使用 256x16x16 个数的三维嵌入,表示为 *Z* 。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ff7367277099e0a360764bbf96f73934.png)**优化算法**,图片作者优化算法的目标是产生与文本查询紧密匹配的输出图像。系统首先通过剪辑文本编码器运行文本查询,以获得目标 *T* 。Adam 优化器从初始 VQGAN 向量 *Zi* 开始。它修改向量 *Zn* 以产生一个嵌入了剪辑 *I* 的图像,该图像试图匹配原始目标 *T* 。随着 *I* 接近 *T* ,输出图像将更好地匹配文本查询。让我们看看该算法与上一节中的提示配合得如何。对于每个提示,我运行系统 200 次迭代。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a768dd017a98992db9e2464c82e776c6.png)未来主义者用鲜艳的勃艮第棕色画了一座城市![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1403ba891cc47b2ca75ee683896d173d.png)**米色粉色斜线抽象画**,图片由 GANshare One 提供![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/eb90f594365392f1949fa406a6f1ede4.png)**印象派画家用卡罗莱纳蓝棱镜作画**,图片由 GANshare One 提供果然,系统创建的图像似乎与提示相符。请注意优化算法是如何即兴发挥的。例如,不清楚第三张图片本身是否包含任何棱镜。但它确实在调色板中显示了一些彩虹色,暗示了光线通过棱镜的效果。# 结果在生成了数百幅数字绘画后,我注意到它们并不都是赢家。从形状类别中的提示生成的图像似乎具有最好的产量,即,大约 33%可以被认为是合理的。但地点和事物类别中的图片效果不佳,只有大约 20%的人保留。下面是我判断的一些样品。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/934f66df23c7e53633d75b30d149df0f.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ab5af4e80d528c23d543b9599cdb6909.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7984c1b8cfefae1ca95c8b84c1e61da9.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/663f3246ebc1c095257d6997b820be84.png)**音速银棕色的对角线几何画**(左)**樱花粉色的城市几何画**(中)**台盼蓝的女孩几何画**(右),图片由甘沙尔一![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5f4598633f3c11fb22176d9b00208238.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cdd6caf75dc4d6d5c0df2e76a96f8a94.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3cde8df4cf38d130bc86023908a881ca.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cb0472ac4a042f466fb980522395e871.png)**野兽派的宝石红色池塘画**(左)**薰衣草粉色吹风机抽象画**(中)**松绿色臭鼬抽象画**(右),图片由甘沙尔一![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3d33aac981bbd177a80d87f83bfdbbe1.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/802acce4dedad9f6a4ac8d2d32c0e565.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d8690cf3421e14696a18b55f57a6dfc1.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b9fe36fd48975b8f58bbe1d43728c33e.png)**芦笋棕色松鼠的后现代绘画**(左)**最大紫色岛屿的抽象画**(中)**白粉色野兽派自行车的绘画**(右),图片由 GANshare One 提供你可以在这里看到更多结果[。](https://opensea.io/collection/chromascapes)# 在 OpenSea 上销售 NFT![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/80f11ddaa0025a4a79d0ffcdd97a3831.png)***每一天*** ***—前 5000 天*作者:毕普**,来源:[beeple-crap.com](https://www.beeple-crap.com/)自从 2021 年 3 月被称为 Beeple 的数字艺术家以 6900 万美元的价格出售了一份 JPG 文件以来,人们对使用区块链出售数字艺术产生了浓厚的兴趣> 皮普尔的拼贴 JPG 是在二月份作为一种“不可伪造的象征”或 NFT 制作或“铸造”的。一个由计算机系统组成的安全网络将销售记录在一个被称为“区块链”的数字账本上,为买家提供真实性和所有权的证明。大多数人用以太坊加密货币支付。“Everydays”是佳士得售出的第一件纯数字 NFT,它提出接受以太坊付款,这对这家有 255 年历史的拍卖行来说是第一次。——**斯科特·雷伯恩,** [《纽约时报》](https://www.nytimes.com/2021/03/11/arts/design/nft-auction-christies-beeple.html)我考虑以 NFTs 的形式出售我的数字艺术,在进行了一点研究后,我发现使用多边形区块链[10]的 OpenSea 市场是一个很好的选择。这是出于成本和环境影响的原因。OpenSea 允许创作者在以太坊区块链或多边形区块链(也称为 MATIC)上发布待售商品。下表显示了以太坊和多边形区块链之间的一些差异。

Feature Ethereum Polygon Account initializing: ~US$50 Free
Selling cost: 2.5% 2.5%
Selling items in bundles: Yes No
Blockchain validation: Proof of work Proof of stake
Environmental impact: Huge* Minimal*expected to change in Q1/Q2 2022


从表中可以看出,在 OpenSea 上建立一个帐户来销售多边形区块链是免费的,在这里使用以太坊区块链大约需要 50 美元。OpenSea 将从区块链的销售额中抽取 2.5%的销售价格。此外,在多边形区块链上不支持捆绑销售项目。## NFTs 的环境影响两个区块链之间的另一个巨大差异是工作证明(PoW)与利益证明(PoS)验证的环境影响。> 能量消耗是两种共识机制之间的一个主要区别。因为利害关系证明区块链不要求矿工在重复的过程中花费电力(竞争解决相同的难题),利害关系证明允许网络以低得多的资源消耗运行。—[coinbase.com](https://www.coinbase.com/learn/crypto-basics/what-is-proof-of-work-or-proof-of-stake)根据多边形…> …最大的电力公司区块链每年可消耗 35-140 太瓦时的电力,持续消耗 3-15 吉瓦的电力。如果区块链是一个国家,它的年能源消耗将排在第 27 位,高于瑞典、越南和阿根廷。…相比之下,Polygon 的验证器每年大约消耗 0.00079TWh 的电力,大约持续汲取 0.00009GW 的电力,比主要的 PoW 区块链网络的能耗低几个数量级。— [多边形技术](https://blog.polygon.technology/polygon-the-eco-friendly-blockchain-scaling-ethereum-bbdd52201ad/)经营区块链以太坊的人们清楚地意识到他们对环境的严重影响。他们计划在 2022 年中期转向利益证明验证。> …[ 2022 年]的升级代表着正式转向利益相关共识。这消除了对能源密集型采矿的需求,取而代之的是使用支撑以太网来保护网络。实现 Eth2 愿景的真正激动人心的一步——更高的可扩展性、安全性和可持续性。——【ethereum.org ## 建立一个 OpenSea 账户建立以 NFTs 形式销售数字艺术的平台很容易(而且使用多边形区块链是免费的)。我跟随 OpenSea 的简单指示[来到这里](https://support.opensea.io/hc/en-us/articles/4404029357587-How-do-I-create-and-sell-NFTs-on-Polygon-)。一旦我建立了我的账户,我就把我的数码作品上传到这里,在这里出售,[https://opensea.io/collection/chromascapes](https://opensea.io/collection/chromascapes)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/df5c60c2ec0c86054a68bc0cabf2c735.png)**色彩景观**,作者图片OpenSea 的一个很酷的特性是能够为待售商品添加属性。购物者可以使用这些属性来定义他们希望看到的商品。对于我的例子,我为生成的绘画添加了以下属性。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/864a39d98b9a65b73803f96b06cfa103.png)**NFT 房产**,图片作者如果你有半打左右的项目,用户界面是可以的。但是如果你想卖 100 样东西,直接从 OpenSea 上传并列出要卖的东西是不容易的。## 使用脚本批量上传项目尽管 OpenSea 确实有一个 [API](https://docs.opensea.io/reference/api-overview) 来自动完成特定的任务,但是他们的 API 没有自动上传和在他们的市场上销售商品的功能。这是不幸的,因为上传数百个文件将是一个真正的痛苦。在阅读了 Jim Dees 关于[使用宏程序](https://medium.com/web-design-web-developer-magazine/how-to-post-giant-10-000-sets-of-nfts-on-opensea-2a8efd4c836e)发布 NFT 的文章后,我开始用我喜欢的语言 Python 来做这件事。正确设置后,我发现[的 Selenium WebDriver](https://www.selenium.dev/documentation/webdriver/) 与我本地笔记本电脑上运行的 Chrome 浏览器配合得很好。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/fb1bfda81b7226ffccab6a8c19e39781.png)**使用 Selenium 和 Chrome 上传和销售 NFTs** ,作者配图首先,我在一个文本文件中捕获了 NFTs 的所有元数据。它包括每幅画的文件名、标题和属性。然后,我的脚本使用 MetaMask wallet 登录到我在 OpenSea 上的帐户,并运行列表中的每个项目,执行以下任务:

1. Create a new item in my OpenSea collection
2. Upload the image file
3. Enter the name of the item
4. Enter the description
5. Enter the properties (i.e. color, style, etc.)
6. Save the item
7. Go to sell the item
8. Enter the price
9. Post the item for sale


这需要一点调整,但我让脚本运行得足够好,可以上传 1,000 个 NFT。# 甘沙尔除了以的身份出售好的形象,我还把训练有素的甘的“股份”卖给其他希望创造新形象的艺术家。我为自己保留一股,并在这里卖出另外三股。OpenSea 在销售 NFT 时允许“锁定内容”。购买 GANshare 后,这些内容将使新的所有者能够创建新的图像,并上传到 OpenSea 或任何其他 NFT 市场进行销售。# 后续步骤我在上面提到过,“好的”生成图像的产量只有大约 20%到 33%。运行优化算法超过 200 次迭代可能会改善结果,特别是对于地点和事物类别。此外,可以将剪辑编码器用作自动艺术评论家。查看图像嵌入与“美丽的绘画”这样的短语有多接近,可以提供一种更容易的方法来区分小麦和谷壳。这可以很好地工作,除非你喜欢绿色臭鼬的邋遢画😀。我还从我的一位评论者奥利弗·斯特瑞普那里得到了一个很好的建议。他问我是否可以训练一个基于语言的人工智能系统来生成高质量的提示,这可能会使它成为一个全自动的艺术生成系统。好主意!# 源代码一个用于试验 VQGAN 和 Clip 的 Google Colab 是[这里](https://colab.research.google.com/github/robgon-art/GANshare/blob/main/GANshare_One.ipynb)。# 感谢我要感谢詹尼弗·林和奥利弗·斯特瑞普对这个项目的帮助。# 参考[1]由 T. Karras、S. Laine、M. Aittala、J. Hellsten、J. Lehtinen 和 T. Aila 编写的 StyleGAN2,(2020)[2]p . Esser、R. Rombach 和 B. Ommer 的 VQGAN,[驯服高分辨率图像合成的变形金刚](https://arxiv.org/pdf/2012.09841.pdf) (2020 年)[3]a .拉德福德等人的剪辑,[从自然语言监督中学习可转移的视觉模型](https://cdn.openai.com/papers/Learning_Transferable_Visual_Models_From_Natural_Language_Supervision.pdf) (2021)[4]d . Kingma 和 J. Ba 的 Adam Optimizer,A [dam:一种随机优化方法](https://arxiv.org/pdf/1412.6980.pdf) (2017)[5]卡迪纳尔等人的 ISR, [ISR 超分辨率 Resizer](https://idealo.github.io/image-super-resolution/) (2018)为了无限制地访问 Medium 上的所有文章,[成为会员](https://robgon.medium.com/membership),每月支付 5 美元。非会员每月只能看三个锁定的故事。# 用 Python 的 Matplotlib 制作甘特图> 原文:<https://towardsdatascience.com/gantt-charts-with-pythons-matplotlib-395b7af72d72?source=collection_archive---------2----------------------->## 用 Python 可视化项目进度指南![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b7375b8aafd48bad1a35d55742223795.png)作者图片这种可视化已经有 100 多年的历史,对于项目管理来说仍然非常有用。亨利·甘特最初创建了用于分析已完成项目的图表。更具体地说,他设计了这种可视化方法来衡量生产率和识别表现不佳的员工。随着时间的推移,它变成了一个计划和跟踪的工具,一旦项目结束,它就被抛弃了。不可否认的是,自最初设计以来,甘特图已经发生了很大的变化。分析师引入了许多编码来显示部门、任务完成度、依赖性、截止日期等之间的区别。本文将探讨如何使用 Python、Pandas 和 Matplotlib 创建甘特图。## 亲自动手

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np


对于这个例子,我们需要一些虚拟数据;我们将使用的数据集包含任务名称、部门、开始和结束日期以及完成时间等列。

df = pd.read_excel('../data/plan.xlsx')
df


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cee0a7135d5e222a7212b46b37f34425.png)作者图片为了使我们的绘图更容易,我们需要获得一些措施。我们将从项目开始日期的变量开始。然后,我们将添加一列从项目开始到每个任务开始的天数;这将有助于在 x 轴上定位条形。任务结束时也是如此;这有助于计算完成任务所需的总天数、条形图的长度,并有助于稍后定位文本。

project start date

proj_start = df.Start.min()# number of days from project start to task start
df['start_num'] = (df.Start-proj_start).dt.days# number of days from project start to end of tasks
df['end_num'] = (df.End-proj_start).dt.days# days between start and end of each task
df['days_start_to_end'] = df.end_num - df.start_num


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b1dd188609c68d73b36e36ce1c9978b1.png)作者图片现在我们可以绘制一个条形图。y 将是任务名称,宽度是任务开始和结束之间的天数,左边是项目开始到任务开始之间的天数。

fig, ax = plt.subplots(1, figsize=(16,6))ax.barh(df.Task, df.days_start_to_end, left=df.start_num)plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/410902c49f1281a87b137ec8141fcd48.png)作者图片酷,我们有最简单的甘特图。我们可以添加许多细节来使我们的图表更有洞察力。我们将从最基本的开始,一个带有日期和颜色的适当的 x 轴来区分各个部门。

create a column with the color for each department

def color(row):
c_dict = {'MKT':'#E64646', 'FIN':'#E69646', 'ENG':'#34D05C', 'PROD':'#34D0C3', 'IT':'#3475D0'}
return c_dict[row['Department']]df['color'] = df.apply(color, axis=1)


对于 x 轴,我们将每三天添加一个标签,我们还将为每一天添加一个小刻度。

from matplotlib.patches import Patchfig, ax = plt.subplots(1, figsize=(16,6))ax.barh(df.Task, df.days_start_to_end, left=df.start_num, color=df.color)##### LEGENDS #####
c_dict = {'MKT':'#E64646', 'FIN':'#E69646', 'ENG':'#34D05C',
'PROD':'#34D0C3', 'IT':'#3475D0'}
legend_elements = [Patch(facecolor=c_dict[i], label=i) for i in c_dict]plt.legend(handles=legend_elements)##### TICKS #####
xticks = np.arange(0, df.end_num.max()+1, 3)
xticks_labels = pd.date_range(proj_start, end=df.End.max()).strftime("%m/%d")
xticks_minor = np.arange(0, df.end_num.max()+1, 1)ax.set_xticks(xticks)
ax.set_xticks(xticks_minor, minor=True)
ax.set_xticklabels(xticks_labels[::3])plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/57768e0f173a905f23db23c85d4542e7.png)作者图片太好了!这张图表比我们之前的版本更有洞察力。现在让我们将项目的完整性编码到我们的可视化中。

days between start and current progression of each task

df['current_num'] = (df.days_start_to_end * df.Completion)


我们将向我们的绘图添加另一个条形,并使用我们刚刚创建的度量作为宽度。为了提高精确度,我们将在条形的末尾写下完整度的百分比。为了区分完成的和未完成的,我们可以使用条形的 alpha 参数。

from matplotlib.patches import Patchfig, ax = plt.subplots(1, figsize=(16,6))# bars
ax.barh(df.Task, df.current_num, left=df.start_num, color=df.color)
ax.barh(df.Task, df.days_start_to_end, left=df.start_num, color=df.color, alpha=0.5)# texts
for idx, row in df.iterrows():
ax.text(row.end_num+0.1, idx,
f"{int(row.Completion*100)}%",
va='center', alpha=0.8)
##### LEGENDS #####
c_dict = {'MKT':'#E64646', 'FIN':'#E69646', 'ENG':'#34D05C', 'PROD':'#34D0C3', 'IT':'#3475D0'}
legend_elements = [Patch(facecolor=c_dict[i], label=i) for i in c_dict]
plt.legend(handles=legend_elements)##### TICKS #####
xticks = np.arange(0, df.end_num.max()+1, 3)
xticks_labels = pd.date_range(proj_start, end=df.End.max()).strftime("%m/%d")
xticks_minor = np.arange(0, df.end_num.max()+1, 1)ax.set_xticks(xticks)
ax.set_xticks(xticks_minor, minor=True)
ax.set_xticklabels(xticks_labels[::3])plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4c43345c81263886eaed437046290e47.png)作者图片就是这样!我们可以改进这种可视化,使其更具吸引力,用另一个轴添加更多信息,绘制网格线,添加标题,等等。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0a4fd49b34fc6a861ab7ef973b68f746.png)[代号](https://gist.github.com/Thiagobc23/ad0f228dd8a6b1c9a9e148f17de5b4b0) —图片由作者提供![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/548e533011a80101a4c1237dcd59a188.png)[代号](https://gist.github.com/Thiagobc23/fc12c3c69fbb90ac64b594f2c3641fcf) —图片由作者提供## 结论总的来说,这是可视化项目的一种极好的方式,尽管它可能不适合大多数当前的项目管理方法。甘特图在某种意义上是灵活的,它们可以有许多功能。您可以分解任务、跟踪绩效指标、依赖性、里程碑、截止日期等等。通过更多的编码、工具提示、向下钻取和文本,可以很容易地向甘特图添加更多的信息。所有这些信息很容易使我们的图表难以理解,甚至更难维护。使用敏捷方法,计划是不断变化的。花那么多时间收集和维护这些信息来跟进一个项目需要太多的资源,而且往往会适得其反。综上所述,它们擅长可视化已完成的项目,比流程图、表格或看板/ Scrum 板更有洞察力,尤其是在审查单个过程或项目时。感谢阅读我的文章!— [在这里](https://linktr.ee/thiagobc23)你可以找到更多 Python dataviz 教程。# MySQL 的差距和孤岛问题> 原文:<https://towardsdatascience.com/gaps-and-islands-with-mysql-b407040d133d?source=collection_archive---------6----------------------->## 如何用 SQL 分析序列和时间序列,或者如何操作 SQL 语言使其对时间序列更加友好![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8eb95ceaa3ba6005fc8b6b5592109bdf.png)信用:[朱利叶斯·西尔弗](https://pixabay.com/users/julius_silver-4371822/)随着世界变得越来越互联,物联网设备在我们的日常生活中占据越来越大的部分,我们周围有如此多的设备和传感器,特别是当其中一些设备和传感器位于并负责敏感功能时,我们必须知道如何监控它们。监控这些设备的一个重要方面是分析来自传感器数据的统计指标。这些数据通常以具有单一指标的时间序列格式存储,可以是二进制或连续数据,在本文中,我将展示如何使用 SQL 分析这两种选项。用 MySQL 分析时间序列可能具有挑战性,因为它不是处理这种数据的理想方法。在下面呈现的查询中,有许多子查询会降低查询的效率,因为子查询丢失了原始数据索引。虽然有更好的方法来处理时间序列数据流,但在许多情况下,来自生产环境的原始数据是使用 MySQL 数据库存储的,因此使用这种方法可以避免漫长而昂贵的 ETL 管道,从而节省时间和金钱。> 老实说,直到我写这篇文章的参考,我不知道这个问题有一个名字,这是一个已知的问题——差距和岛屿问题。岛的意思是“正常的”序列(在我们的例子中是 1 ),而缺口是成为没有错误和中断的完美序列的障碍。所以我们正在解决一个已知的问题,在我看来,理解了问题就等于解决了一半。## 二元序列给定一组数据序列,例如:传感器数据为 0 和 1,1 表示连接,0 表示断开,您希望确定停机时间并更好地了解传感器的行为。信息包括:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9f80d551a16342891d8afdfc8723873c.png)序列数据![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8fb4191678a8fc823d87570edfa0a902.png)传感器超时1.  设备的总停机时间是多少?2.如何求不间断 1 值序列的最大长度?3.传感器在两者之间切换多少次?4.最长的停机/正常运行时间是多久?5.平均停机时间是多少?我们可以看到传感器几乎每分钟都在报告。要回答第一个问题“设备停机的总时间是多少?”我们可以估计值为 0 的行数,并乘以 60 秒。汇总这个数量可以为我们提供传感器的总停机时间,但这只是一个估计,如果探测之间存在延迟,并且每两个数据包之间的速率将上升到 70 秒甚至更长,该怎么办?目前计算这一停机时间的方法是将每个零序列分组,找出第一个和最后一个包之间的时间差,然后汇总这些差异。这可以通过使用 MySQL 的 4 个简单步骤来解决:第一步![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3b70f32aa0f7a454f63d059c45c4bcc8.png)第一步的结果在第一步中,我们使用了两个窗口函数,第一个函数 ROW_NUMBER()按时间对数据点进行编号,而第二个函数 ROW_NUMBER()按值对数据点分区进行编号,这意味着第二个函数为每个值提供连续计数(分隔 0 和 1 的序列)。在第 2 步中,我们将计算*continues _ seq-*seq _ by _ value,并获得每个序列的唯一编号!![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/676d0c68a135a296eaf97fdf6438d42d.png)现在,我们从传感器获得的数据中的每个序列都有一个唯一的 id!从这里开始,可以很容易地从这些数据中查询统计数据,因为我们对每个停机时间都有一个唯一的名称。基于这种操作,我们可以使用基于值为 0 的 seq _ ids 的`GROUP BY`来回答第一个问题,并将其与我们对`number_row_0 * 60`的估计进行比较![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/bf0c4b8fe8b4e40fd141406d3b72d58f.png)每个序列具有唯一 id 的数据在上面显示的具体案例中,我们得到了预计停机时间的`number_row_0 * 60 = 9120 secounds`和准确停机时间的`sum(time_diff_s) = 5104 seconds`!为了回答最大停机时间、平均停机时间等其他问题,我们可以使用以下查询:## 连续序列我们的下一个例子展示了带有累积数据的时间序列数据,其中的值可以表示任何累积的指标。例如,传输的数据、自最近一次重启以来的时间、或者从零开始并一直上升的任何度量。(无季节性)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/bfae968a8c1eba77aac67613b11640f8.png)累积值数据集![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/40f9892eb747e27e284de6c41240caac.png)原始数据超时在这种情况下,我们可以问自己几个新问题:1.  计数器重新开始了多少次?
2.  每个序列中的最大值是多少?
3.  每个序列的平均周期是多少?对于这类数据,我们将使用窗口函数*LEAD*和*LAG*,在我们的第一部分之后,这将更加直观和简单![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/71d432b1e9e3d88b68e4fe54bc9f531f.png)窗口函数在步骤 1 中,我们使用了 LEAD window 函数,该函数用于提供当前行之后的行中的值,利用该功能,我们可以计算每个值与下一个值之间的差异——在我们的示例中,这些值是累积的,因此我们希望每个值都比前一个值高。在第一步之后,我们可以很容易地识别每个序列的开始时间和结束时间,并定义每个序列的行为,只需从`diff_min` [LAG()]中选择负值,从`diff_plus` [LEAD()]中选择正值,然后找到其最大值。为了计算计数器重新开始的次数,我们只需要从`diff_min`开始计算负值。**总结**在这篇文章中,我展示了如何使用 SQL 分析类似序列的数据。第一部分重点介绍离散和二进制数据集,它们仅代表值为 1 和 0 的信号。我展示了如何使用 *ROW_NUMBER* () window 函数为每个 0 / 1 序列提供一个惟一的 id,这使得分析和统计计算更加简单。第二章集中于连续的数据集,其中的值随着时间的推移而增加。我展示了如何使用 LAG()和 LEAD()窗口函数,并分析这种时间序列数据流。我希望您发现这个用例的这些解决方案(使用 MySQL 来分析时间序列数据集)有趣且有用,就像我在日常工作中所做的那样。## 额外阅读1.  [https://dev . MySQL . com/doc/ref man/8.0/en/window-function-descriptions . html](https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html)
2.  【https://www.mysqltutorial.org/mysql-window-functions/ 
3.  [https://stack overflow . com/questions/58472798/MySQL-how-to-find-the-maximum-length-of-an-uncontinued-sequence-of-a-determined-a-va](https://stackoverflow.com/questions/58472798/mysql-how-to-find-the-maximum-length-of-an-uninterrupted-sequence-of-certain-va)
4.  [https://www . red-gate . com/simple-talk/SQL/t-SQL-programming/The-SQL-of-gap-and-islands-in-sequences/#:~:text = The % 20 word % 20 ' gap ' % 20in % 20th,between % 20 them % 20in % 20a % 20 column](https://www.red-gate.com/simple-talk/sql/t-sql-programming/the-sql-of-gaps-and-islands-in-sequences/#:~:text=The%20word%20'Gaps'%20in%20the,between%20them%20in%20a%20column)。# 垃圾进,垃圾出> 原文:<https://towardsdatascience.com/garbage-in-garbage-out-721b5b299bc1?source=collection_archive---------13----------------------->## 拯救世界只是解决这个普遍问题的一个好理由![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/de461ea2c66314f58859ed7ecd0ca032.png)克拉克·古在 Unsplash 上的照片*垃圾进,垃圾出*可能是初露头角的数据科学家们对他们即将到来的分析努力所学到的第一课。虽然 GIGO 的精神早在 19 世纪 60 年代就很明显,但实际的短语似乎是由一位名叫 George Fuechsel 的 IBM 程序员在 1962 年创造出来的(Stenson,2016)。他的意思就是它所说的:如果我们把不好的信息放入我们的计算机模型,我们将从它们那里得到不好的信息。预计会有争议、糟糕的见解、糟糕的决策和糟糕的政策接踵而至。在这篇文章中,我将在机器学习模型的背景下定义垃圾,这些模型被用来解决当今令人烦恼的问题。我们将研究不同类型的垃圾,它们会产生不同大小和意义的问题。我们将从课堂上以及数据科学和统计教科书中提到的基础知识开始。然后,我们将考虑更微妙和更重要的垃圾来源和例子,这些垃圾使解决新冠肺炎疫情或处理许多其他公共卫生、政治、社会、商业或经济问题所需的许多决策和方法变得复杂。我们将描述一些解决 GIGO 问题的方法,并提供一些关于如何将这些方法应用到生活中的想法。***垃圾到底是什么?***如果 GI 产量没有了,垃圾会是什么?这个问题的部分答案很简单:坏数据。我指的是以下数据:错了,与众不同的是,太像其余的,或者失踪了。第一点背后的逻辑很简单。*错误数据*是错误获得或记录的事实上不正确的值,从而歪曲了分析师想要测量的任何结构。*与其余数据*差异很大的数据(例如,其值位于均值的两个或两个以上标准偏差处,在任一方向上)通常被称为异常值。有几种方法来定义异常值,但本质上它们有异常高或异常低或其他非典型的值(NIST,2010;麻省理工学院关键数据,2016)。因此,异常值并不常见,但仍然具有影响力,因为这些数据点的极值可能会扭曲分析结果。例如,对一些州和国家的新冠肺炎病例和死亡率的早期预测被发现严重夸大,因为周末的检测和死亡率结果被错误地与下周的检测结果相结合。夸张的下周报告将住院、重症监护病房停留和死亡的时间序列预测拉得太高,导致后来未实现的可怕预测(Ioannidis 等人,2020)。异常值的识别并不总是简单明了的,尤其是在非正态分布的数据中。调查中出现的例子包括非典型事件,如医院获得性感染或其他医疗保健相关感染的成本分析。这些往往非常昂贵,使整体成本分布向高端倾斜。然而,对异常值的补救并不总是简单地排除、减少或替换它们。尽管异常值很少且很大,但一些异常值可能确实是底层数据生成过程的真实反映,因此排除、替换或缩减异常值可能会产生不正确的推断。麻省理工学院关键数据团队(2016)对电子健康记录分析中的异常值进行了很好的讨论。一般来说,通过进行多次分析(有异常值和无异常值)可以获得更深刻的见解,从而了解包含少量仍然非常有影响力的观察结果的影响。*与其余数据*过于相似的数据通常被标记为高度相关或共线。当两个或多个变量高度共线时(即,倾向于以大约相同的速率向相同的方向移动),它们可能测量相同或非常相似的基本概念。当这样的变量被输入到我们的模型中时(引发了垃圾问题),我们的模型会遭受多重共线性。这个问题会使模型不稳定,混淆从这些模型中得到的推论,从而产生垃圾。Belsley、Kuh 和 Welsch (1980)发表了描述多重共线性的起源和解决方案的开创性文本。他们的诊断和补救过程至今仍被频繁使用。在我们的回归模型中,我和我的同事经常测试多重共线性,发现即使是轻微的共线性也会导致有问题的不稳定性,这意味着来自共线变量的系数具有奇怪的高值或低值以及高标准误差。删除一个或多个有问题的变量通常会减少或补救这个问题。其他解决方案,如从共线变量生成主成分或因子得分,也可以在许多应用中使用。还有其他解决方案也有帮助,如套索或岭回归或在分析前将变量居中(Cox,2021)。但是,在删除变量或应用套索或岭回归时要小心,要确保系数减少或删除的变量不会被不当处理。其中一些可能仍然是理论上或概念上正确的因果推理所需要的。建议测试共线性,并通过改变模型规格来调查模型性能,即使尚未(或几乎)达到公认的共线性阈值。在许多机器学习问题中,一个被广泛接受的表示共线性的阈值被标注为大于 30 的 X’X 矩阵条件索引值。然而,Belsley,Kuh 和 Welsch 反对使用标准的截止值作为条件指数,我和我的同事经常在更低的值(例如,甚至低于 20)发现有问题的共线性。使用其他共线性诊断(如方差膨胀因子(VIFs ))时也发现了类似的模式,因此测试模型对高度共线的输入要素列表中的微小变化的敏感性可能很有启发性。*缺失数据*如果缺失值的百分比很高,就会出现问题,降低从我们的分析中找到重要结果的能力。如果缺失的模式不是随机的,那么缺失的数据尤其成问题。缺失数据的系统模式意味着剩余数据是系统存在的,这种方式可以从统计分析中产生有偏见的见解(Kalton 和 Kasprzyk,1986)。例如,从 2020 年 3 月开始的几个月里,密歇根州停止向联邦政府报告阴性新冠肺炎测试的数量,从而无法估计阳性测试的比例(Livengood,2020)。阳性结果的比例是用于跟踪和预测病毒感染的流行病学模型的一个关键特征,因此不正确或缺失的值会导致对病毒传播以及随后的住院和死亡率的错误估计。不幸的是,所有 50 个州的私人检测公司仍然没有被要求向联邦政府报告阴性结果,而且在许多州也没有。这使得制定抗击疫情的最佳政策所需的洞察力生成过程变得更加复杂(Schulte,2020)。Little 和 Rubin (1987)撰写了关于如何处理缺失数据以及这样做的潜在偏见和优势的开创性文本。十几年后,我发表了一篇关于退伍军人调查数据的多重插补法的应用,以解决他们对等待住院治疗的观点,在一个调查数据集中有几个缺失的观察值(Ozminkowski,1998)。我的多重插补方法试图反映数据的可变性,避免低估标准误差。麻省理工学院关键数据团队(2016)提供了处理缺失数据的最新进展。***垃圾以多种形式出现***GIGO 不仅仅指坏数据;这也是对错误思维和/或对偏见反应迟钝的一种暗示。Brian Christian (2020)在他的名为*对齐问题*的书中很好地阐述了这个问题。他指出,人工智能模型中的偏见可能是由于对正在建模的问题缺乏理解。此外,他说,这种偏见很难被发现,发现的时间越长,这种偏见持续的时间越长,范围越广。因此,偏见未被发现的时间越长,这些偏见可能会变得越大越严重,因为它们会伤害更多的人。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ba59d93a830e7e051aff3dc646ff8492.png)照片由 Michal Matlon 在 Unsplash 上拍摄*其他垃圾来源**不正确的理论或概念模型*用作建模的基础,这可能导致建模错误或错误地解释模型结果。例子包括阴谋论和政治或其他干扰,它们要么产生不正确的概念模型,要么阻碍数据收集和科学进程,产生误导或危险的结果。*对因果关系和因果推理方法的理解有限*,这也导致了糟糕的建模选择、错误的结果解释以及糟糕的社会或经济政策(Maziarz,2020)。*文档记录不良或无文档记录的代码*,这导致其他开发人员或程序员在模型更新或部署到下游时错过重要细节并犯错误。*糟糕的研究操作*导致分析师曲解客户需求、应用不正确的理论或概念模型、收集错误或不完整的数据、测试错误的假设、使用不正确的方法或曲解结果。例子包括测试新药物或装置的不正确剂量,导致有偏见的结果(Gillian 等人,2016)。*未能纳入代表性观点*,导致不完整的概念模型、不能充分代表感兴趣人群的数据、要测试的不完整或不准确的假设和/或对结果的不正确解释(Obermeyer 等人,2020)。*忽略没有免费的午餐定理*,这可能会导致使用次优模型来生成洞察,如果研究其他模型,这些洞察可能会更加准确、敏感或具体。*忽略正确使用统计模型所依据的假设*,导致结果不正确。*构建不良的传播/部署流程*,通常由建模师和工程师之间的误解引起,导致传播或部署不正确或次优的模型。*一个不适定的问题*(一个有许多不同答案的问题),导致对目标的误解和可能不想要的结果。一种被称为逆向强化学习的技术可能有助于通过解读研究人员的意图来解决不适定的问题,然后可以指导寻找解决方案。克里斯蒂安(2020,第 255–259 页)描述了吴恩达在这一领域的工作。通过在下述 CRISP-DM 流程的理解业务需求部分花费更多时间,人类也可以更好地解读意图。*使用错误的统计测试*,例如那些未能控制混杂因素或通过调节打开竞争因果路径的变量而过度控制的测试。Pearl 和 MacKenzie (2018)详细讨论了这个问题及其解决方案。*高置信度下做出的错误判断*就是垃圾剔除的例子。不过,有时人类的直觉可以解决计算机产生的错误判断。克里斯蒂安(2020 年,第 279 页)描述了一个潜在的引发战争的案例,当时苏联模型错误地预测了美国向苏联领土发射导弹的核发射。幸运的是,一名训练有素的值班军官 Stanislav Petrov 利用他的直觉和训练避免了可能导致 WWIII 的报复!这个故事说明了机器加人类可以比机器单独强很多。对人+机器过程的正式研究被称为合作机器学习。Christian (2020,第 266 页)引用了 Stuart Russell 在这方面的工作。道德不确定性可能是一种垃圾。如果我们不能就什么是好的或正确的达成一致,我们如何知道相关的政策是否没有垃圾,或者其中可能有多少垃圾?(《基督教》,2020 年,第 305 页)。另一方面,一些不确定性可能是可取的,因为它可以激发更多的调查和多角度的考虑。这可能有助于澄清伦理问题,并为更好(或至少更完整)的分析指明方向。克里斯蒂安(2002 年,第 304-308 页)描述了威尔·麦卡斯基尔在这一领域的工作。*数据标注不当*是垃圾的来源。如果我们预测模型中的标签是不正确的,那么我们的洞察力将会是错误的。(《基督教》,2020 年,第 315 页)。*模型假设偏差*(即,对现实中不存在的事物建模)也是一种垃圾。Maziarz (2020)在他的《经济决策的因果推理》一书中描述了几个这样的例子。克里斯蒂安(2020)在他的书的第 324 页也提到了这一点。*走得快,打破常规*如果我们走得太快,错过了上面提到的任何一个问题,就可能成为垃圾的来源。***解决方案***为了指导寻找 GIGO 问题的解决方案,考虑一下数据科学的跨行业标准流程。CRISP-DM 是由一个国际财团在 20 世纪 90 年代开发的,并由 Chapman 等人在 1999 年进行了总结。图片上看起来是这样的:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e0833cc3781d6d51b880f7b83cee9a85.png)图 1:https://en . Wikipedia . org/wiki/Cross-industry _ standard _ process _ for _ data _ miningCRISP-DM 是科学过程的计算机科学渲染。这与高质量的物理和社会科学方法中使用的过程非常相似。一个是从业务理解任务开始,如果做得好,会对客户希望通过分析解决的问题产生坚实的理解。这个迭代任务驱动图中显示的所有后续阶段,其中一些阶段相互加强。该图是不言自明的,因此显而易见的是,任何步骤中的问题(即垃圾)输入都会混淆所有未来或相关的步骤,并导致垃圾输出。因此,解决方案是在每一步都避免错误或其他垃圾。CRISP-DM 流程已经随着时间的推移而不断完善。一个特别引人注目的修订是由微软的 Jen Stirrup 做出的,并作为“数据科学生命周期”发表(strap,2017)。她的版本和下面的非常相似,这是我根据她的版本创作的,并经许可使用。主要区别如下:我的版本侧重于健康服务的研究和部署过程。这反映了我的培训和经验,也反映了最近对健康的社会决定因素(SDOH)的关注,包括我们出生、成长、学习、生活、工作、玩耍、崇拜、衰老和以其他方式度过时间的环境的各个方面(美国卫生与人类服务部,健康人 2030)。这些影响了我们的健康,获得医疗保健服务,如 COVID 测试和疫苗,癌症治疗等。SDOHs 也影响医疗服务的质量和治疗的结果。与 SDOH 相关的偏见在我们的模型中制造了垃圾,这可能会导致这些模型产生垃圾。“数据”不是微软修订版的中心,我开发的精细数据科学生命周期将人作为分析工作的中心焦点。这符合以人为中心的设计原则(IDEO.org,2015)。此外,我添加了标记为公平和多样性、异质性分析和可归纳数据的框,以指出这些焦点如何帮助避免偏见,并提高对细化的生命周期的理解和洞察力。我还移动了 box 3,使更多的 box 成为双向的,以记录它们对生命周期其他部分的影响。为了反映上述内容,我更改了该图的标题,添加了短语“从 SDOH 和公平的角度”从 GIGO 的角度来看,这个图表的要点是,对细化生命周期的每一步给予更多的思考可以减少垃圾输入错误,从而减少垃圾从我们的分析中出来的可能性。每一步都应该反映和融合各种文化、理论、概念和其他关于人的观点,以及我们如何努力改善每个人的生活。这将有助于我们识别和避免认知偏见、种族主义、年龄歧视、性别歧视和其他不公平现象,否则这些现象可能会渗透到我们的研究设计中,并在我们的分析中引发来自生命周期每一步的偏见。识别和避免这些类型的垃圾将有助于避免糟糕的政策、歧视和糟糕的生活质量。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ee4b632af864cf4fcda0f0491b6e1fb4.png)图 2:作者修改的数据科学生命周期图像,以反映健康的社会决定因素(SDOH)和公平观点***实施方案***虽然遵循数据科学的生命周期似乎很简单,但一些评论可以帮助指导这一过程。首先,业务理解任务是最重要的部分。这里的错误会在整个过程中级联,并且肯定会在剩余的过程中产生垃圾。如果不加以纠正,这种垃圾将在部署期间和生命周期的后续迭代中传播。为了避免这种情况,我和同事们完成的许多研究和报告项目都涉及一系列预定的正式会议,至少每季度面对面一次,至少每两周通过电话进行一次。当出现意想不到的问题或疑问时,还会有非正式的电话、短信、即时消息或电子邮件。如果需要,Zoom 及其同类产品可以取代基于电话的会议。在几十年的研究生涯中,我还没有经历过一个更好的方法来识别和解决分析工作中的问题。这个过程可能看起来会增加研究过程的时间和净成本,但我们的经历正好相反。通过经常看到和听到我们的同事,我们建立了更好的关系,能够看到和听到客户和利益相关者在想什么,我们能够更快地解决冲突或回答问题。人们开始习惯问一些直接的问题来推动项目的进展。这节省了时间和金钱,如果没有足够的对话,这些时间和金钱将会花费在迭代解决方案上。客户更开心了。其他经验告诉我,在业务理解过程中偷懒是一个非常糟糕的主意。正确地做可以避免前端的垃圾,这些垃圾会导致(有时确实会导致)以后的重大问题。如果您与多个团队合作,例如业务开发、战略团队、产品开发、临床医生、社会服务提供商、工程和营销团队,将每个团队的代表召集在一起是很困难的。然而,如果做不到这一点,可能会导致严重的痛苦和客户不满,损失时间,并造成数十万甚至数百万美元的额外损失。这些人应该从始至终在整个项目中合作。只与这些人中的一些人开会,排除其他人,会增加误解和错误的可能性,这在以后可能是非常昂贵的。业务理解过程也是努力理解如何避免或解决其他问题的地方。这是应该考虑坚实理论的地方,也是应该进行相关文献回顾的地方,以帮助指导分析过程。不同年龄组、不同性别、不同收入、不同教育、不同文化背景和不同地点的人,如果直接经历了分析要解决的问题,也应该在这个阶段进行咨询。他们的意见应通过上述会议/电话/缩放/电子邮件或文本流程定期获得。这些业务理解活动有助于识别因果机制和要测试的反事实场景。它们还可以帮助识别可能经历不同因果途径和完全不同结果的亚人群。除了分析整个人群的经历,分析这些亚人群的经历将有助于避免偏见并产生更好的见解。卡内基梅隆大学数据科学和公共政策团队(2018)构建的 Aequitas 开源机器学习审计工具显示了如何解决不同年龄、性别表达、教育水平和收入的人的观点。Spurlock 等人(2020 年)对加州疗养院新冠肺炎患病率的研究说明了亚人群结果如何不同,以及模型结果如何随时间变化。数据获取和数据理解过程,以及图 2 中提到的建模/测试/评估过程,在很大程度上相互依赖,并且依赖于业务理解任务。这些过程中的错误通过收集错误的数据、不充分或不正确地分析数据,以及未能应用彻底的模型测试和评估过程而注入或产生垃圾。在医疗保健应用中,对健康的社会决定因素或公平的其他相关因素的关注将对这些过程产生重大影响。数据元素的概况、数据质量报告、分析过程和分析结果应与客户和重要亚人群的代表一起审查。如何清理和分析数据的例子比比皆是,在任何优秀的数据科学文本中都可以找到。麻省理工学院关键数据团队(2016)在临床分析领域提供了一个很好的例子。在这些阶段也应该应用 Aequitas 或其他方法来发现和解决偏见。使用敏感性分析来测试群体差异和个体差异,然后在必要时修正数据和/或模型,将会产生更好的结果(Hall 等人,2021,第 46–49 页;麻省理工学院关键数据团队,2016)。数据科学生命周期的第四个主要阶段是部署,这通常被认为是流程中的最后一步。这是否正确取决于客户、竞争对手和其他利益相关者对生命周期输出的反应。大多数分析模型会随着时间的推移而衰退,这意味着随着新的和不同的数据进入模型,它们的准确性和其他性能指标会下降。退化可能是由于从新群体或亚群体获得数据,或者是由于人类行为的自然进化。Ilro Lee (2021)指出了学习组织心理学的价值,以了解认知偏差和数据科学家可以避免的其他问题。数据科学家制作的许多分析模型旨在预测或解释人类行为,因此理解行为心理学或行为经济学可以帮助减少 GIGO 问题。由于人类的经验和视角会随着时间而改变,部署应该是后续工作的推动者,而不是建模过程的真正结束。数据科学的生命周期是迭代的,来自客户、竞争对手和其他利益相关方的见解应该激励未来的迭代。这些将引导创新,创造更多有用的见解,减少垃圾的输入和输出。最后,Obermeyer 等人的算法偏差剧本(2020 年,第 4 页)提供了一个非常有用的 4 步过程,以识别和避免在我们的模型中插入垃圾的系统性偏差。这些包括(我引用一下):步骤 1:库存算法第二步:筛选偏见第三步:重新训练有偏见的算法(或者抛弃它们)第四步:建立防止未来偏见的结构。作者详细描述了这些步骤和每个步骤中的子步骤。他们的指南没有行话,并且提供了常识性的解决方案,这使得它简单易懂。绝对值得花时间去了解和遵循他们的系统。***局限性***我在这篇文章中的目标只是指出几个可能在我们的模型中产生垃圾的问题,以及如何解决这些问题以避免产生垃圾的一些想法。GIGO 问题的范围很广,人们无法在一篇短文中完整地描述这些问题或它们的解决方案。微软(2021)的研究小组提供了有关数据质量测试和补救工作的更多信息。这里提供的参考资料也会有所帮助。对于更细微的问题,随着偏见检测和负责任的机器学习的应用继续应用,将会学到更多。还应该注意的是,这里没有提到的许多其他问题可能会产生这样或那样的垃圾。我的同事 Mahil Senathirajah 提到的例子包括以旨在得出特定结论的研究形式出现的故意偏见、科学家或新闻界对结果的不准确或故意的错误报道,以及由于不利的结论而禁止发表研究。在我看来,同行评审期刊中经常出现的避免发表不具有统计学意义的结果的偏见可能也是另一种形式的压制和垃圾。好的研究并不总是揭示统计上的显著关系。***结论***GIGO 的精神简单且广为接受,但它的现实只有在我们认识到好的和坏的数据和分析过程之间的区别时才能得到承认。尽管我们尽了最大努力来解决上述问题,但每个数据集和分析方法都包含一些垃圾,没有一个是完美的。分析师尽最大努力发现并解决问题,但他们无法独自完成这项工作。那些设计研究、创建行为理论、创建和/或收集数据的人,以及那些设计、进行和解释分析的人,也扮演着重要的回避工作的角色。简单地删除垃圾并不总能解决 GIGO 问题。如果垃圾以在模型中产生偏差的变量的形式出现,如果与偏差诱导变量高度相关的其他变量可能拾取那些偏差诱导变量的一些影响,则一些偏差可能会保留。Christian (2020 年,第 57-65 页)用模型说明了这一点,这些模型导致在高犯罪率地区也就是高少数族裔地区加强警察监控。过了一段时间,少数民族种族和犯罪之间的联系被联系在一起,然而种族本身并不是诱发犯罪的因素。Hall 等人(2021)描述了“负责任的机器学习”的许多原则和应用,可以更好地解决 GIGO 问题。再加上对融合了公平和 SDOH 观点的最新数据科学生命周期的关注,并通过实施算法偏差剧本,我们可以产生分析见解,然后应用这些见解来改善全球数百万人的生活。***回执***我要感谢 Mahil Senathirajah 对本文早期草稿的有益评论。他的见解帮助我改进了它。任何遗留的错误都是我的。***参考文献***D.A. Belsley、E. Kuh 和 R.E. Welsch,《回归诊断:识别共线性的有影响的数据和来源》( 1980 年),纽约 John Wiley & Sons 公司页(page 的缩写)Chapman,J. Clinton 和 R Kerber 等人,CRISP-DM 1.0:逐步数据挖掘指南(1999 年),关于[https://www.the-modeling-agency.com/crisp-dm.pdf](https://www.the-modeling-agency.com/crisp-dm.pdf)B.克里斯蒂安,《对齐问题》( 2020 年),诺顿公司,纽约州纽约市J.考克斯,《回归分析中的多重共线性:问题、检测和解决方案》(2021 年),载于[https://statisticsbyjim . com/Regression/multiple 共线性-in-regression-analysis/](https://statisticsbyjim.com/regression/multicollinearity-in-regression-analysis/)卡内基梅隆大学的数据科学和公共政策团队, *Aequitas:一个用于机器学习的开源偏见审计工具包* (2018),在[http://www . datasciencepublicpolicy . org/our-work/tools-guides/Aequitas/](http://www.datasciencepublicpolicy.org/our-work/tools-guides/aequitas/)G.L. Fell,A. O'Loughlin,P. Nandivada 等人,减少研究性胃肠外药物临床试验中用药错误的方法,(2016),当代临床试验通讯 4(15):64–67页(page 的缩写)Hall,N. Gill 和 B. Cox,《负责任的机器学习》( 2021 年),波士顿,MA: O'Reilly Media 公司。IDEO.org,《以人为本的设计实地指南》( 2015 年), designkit.orgJ.P.A .约安尼迪斯、s .克里普斯、M.A .坦纳,《对新冠肺炎的预测已经失败》(2020 年 6 月 11 日),国际预测机构G.Kalton 和 D. Kasprzrk D,《缺失调查数据的处理》( 1986 年),调查方法 12;1–16I. Lee,每个数据科学家都应该学习组织心理学的 4 个理由(2021),走向数据科学,在[https://Towards Data Science . com/4-Reasons-Why-Every-Data-Scientist-Should-Study-organization-Psychology-a 9411 FD 6030 b](/4-reasons-why-every-data-scientist-should-study-organizational-psychology-a9411fd6030b)R.J.A. Little 和 D. Rubin,《缺失数据的统计分析》( 1987 年),纽约约翰威利父子公司C.Livengood,为什么密歇根州不再报告阴性新冠肺炎测试?很复杂*、*(2020 年 3 月 19 日)*克莱恩斯底特律商务*。米(meter 的缩写))Maziarz,《经济学中的因果哲学:因果推论和政策建议》( 2020 年), Routledge Taylor 和 Francis 集团,纽约麻省理工学院关键数据,电子健康记录的二次分析,(2016),施普林格国际出版公司,瑞士湛美国国家标准与技术研究所,数据中有哪些异常值?工程统计手册(2010 年),位于[https://www . ITL . NIST . gov/div 898/Handbook/PRC/section 1/PRC 16 . htm](https://www.itl.nist.gov/div898/handbook/prc/section1/prc16.htm)Z.Obermeyer,R. Nissan,M. Stern 等人,《算法偏差剧本》(2020 年),芝加哥布斯:应用人工智能中心。同样在[https://www . FTC . gov/system/files/documents/public _ events/1582978/algorithm-bias-playbook . pdf](https://www.ftc.gov/system/files/documents/public_events/1582978/algorithmic-bias-playbook.pdf)R.Ozminkowski,等待住院治疗:在退伍军人医院的经历(1998 年),*健康服务管理研究 11:228*–237J.Pearl 和 D. MacKenzie,《为什么之书:因果的新科学》( 2018 年),纽约基础图书公司微软研究小组实验平台,数据质量:可信 A/B 测试分析的基础构建模块(2021 年 11 月 9 日)在[https://www . Microsoft . com/en-us/research/Group/Experimentation-Platform-exp/articles/Data-Quality-Fundamental-Building-Blocks-for-trust-A-B-Testing-Analysis/](https://www.microsoft.com/en-us/research/group/experimentation-platform-exp/articles/data-quality-fundamental-building-blocks-for-trustworthy-a-b-testing-analysis/)F.舒尔特,一些州报告了不完整的新冠肺炎结果,模糊了全貌,(2020 年 3 月 25 日),凯撒健康新闻B.Spurlock、C. Harrington、M. Senathirajan 等人(2020 年),《加州疗养院中的新冠肺炎:与病例和死亡相关的因素》,载于[https://www . chcf . org/publication/新冠肺炎-加州-疗养院-因素-病例-死亡/#建议](https://www.chcf.org/publication/covid-19-californias-nursing-homes-factors-cases-deaths/#recommendations)R.史丹森,这是第一次有人印“垃圾进,垃圾出”吗?(2016 年 3 月 14 日)Atlas Obscura,在[https://www . atlasobscura . com/articles/is-this-the-first-time-any one-printed-garbage-in-garbage-out](https://www.atlasobscura.com/articles/is-this-the-first-time-anyone-printed-garbage-in-garbage-out)J.马镫,CRISP-DM 怎么了,有替代方案吗?(2017),上*[https://jen staple . com/2017/07/01/whats-error-with-crisp-DM-and-is-there-an-alternative/](https://jenstirrup.com/2017/07/01/whats-wrong-with-crisp-dm-and-is-there-an-alternative/.%C2%A0)**美国卫生与公众服务部健康促进与疾病预防办公室。健康人 2030:健康的社会决定因素,载于[https://Health . gov/Health ypeople/objectives-and-data/Social-determinators-Health](https://health.gov/healthypeople/objectives-and-data/social-determinants-health)*# 使用 PyTorch 进行垃圾分类> 原文:<https://towardsdatascience.com/garbage-segregation-using-pytorch-6f2a8a67f92c?source=collection_archive---------35----------------------->## PyTorch 中卷积神经网络的 RESNET 方法人类每天产生数百万吨垃圾。众所周知,这些垃圾在被带出家门之前需要被分类。这个过程对于社区的运作和地球母亲的维系是必不可少的,但却是乏味的!![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c9f3c88925ca0a903bc9d382bf669add.png)分离你的想法|照片由[paweczerwi ski](https://unsplash.com/@pawel_czerwinski)在 [Unsplash](http://unsplash.com/) 拍摄我们都曾在某个时候想象过有一个机器人私人助理来为我们做所有的家务,包括垃圾分类。我是说,我们在骗谁呢?我们不喜欢手里拿着一个汽水罐,盯着 6 个垃圾桶,想知道它去了哪里。这个梦想不是遥不可及的想法,而是由于深度学习的进步而成为现实。今天我们将使用 PyTorch 构建一个这样的图像分类模型。PyTorch 是一个 Python 库,具有各种各样的函数和操作,主要用于深度学习。我们将通过使用属于 6 个不同垃圾箱的 2527 个图像的 Kaggle 数据集来训练这个模型。那些是-1.  不真实的
2.  玻璃
3.  金属
4.  纸
5.  塑料的
6.  废物数据集从 [Kaggle](https://www.kaggle.com/asdasdasasdas/garbage-classification) 获得。我们将使用`opendatasets`库来下载数据集。在下载数据集时,您将被要求提供您的 Kaggle 用户名和凭证,您可以使用 Kaggle 上您的帐户页面上的“创建新的 API 令牌”按钮来获得这些信息。使用“文件”选项卡上传`kaggle.json`笔记本,或在出现提示时手动输入用户名和密钥。现在我们将导入必要的库。# 探索数据我们已经下载了数据。现在我们来看一下图像,看看数据是如何存储的。正如我们所看到的,我们将图像分为以上 6 个不同的类别,或者在我们的例子中,是垃圾箱。# 应用转换在我们将这些图像用于我们的模型之前,我们必须应用一些变换。其中之一是将图像转换成张量。张量是数字、向量、矩阵或任何 n 维数组。当我们将图像转换成张量时,PyTorch 能够对其应用不同的函数和变换。在我们将图像转换为张量之前,我们将调整它们的大小或缩小为 64 * 64 像素的图像。这是为了减少训练时间,不让我们的 GPU 超负荷运转。可以使用`transforms.Compose` 链接变换,如下所示## 检查图像在定义我们的模型之前,让我们看一下我们正在处理的数据。我们将定义一个助手函数,它将显示图像和与之对应的标签。我们将使用 matplotlib,这是一个用于数据可视化的 python 库。如我们所见,我们正在处理存储在单个数据集中的 64 * 64 像素图像。让我们检查数据集包含多少样本## 分割数据集我们分离垃圾的下一步是将数据集分成:1.  训练数据集-模型将在其上进行训练。
2.  测试数据集—出于预测目的随机选择的数据集部分。理想情况下,还会创建一个验证数据集来检查模型的准确性,但由于我们的图像数量有限,我们将使用测试数据集作为验证数据集来提高模型的准确性。我们使用了 random_split 函数,它将数据集随机分成几部分。## 创建数据加载器现在我们将创建数据加载器。这些数据加载器将数据批量加载到我们的模型中。通过这样做,数据将以 18 幅图像为一批输入到模型中。为了可视化一批数据,我们可以如下创建一个助手函数。正如我们看到的,一批包含随机选择的图像。## 使用 GPUGPU 使用 CUDA 核心来加速我们的训练过程。因此,最好将我们的数据和模型转移到 GPU。我们将为此创建助手函数。这里我们定义了几个函数来检查 GPU 是否可用。如果 GPU 可用,数据将传输到 GPU 以进行更快的处理。数据加载器和模型也被移到 GPU 中。我们现在可以使用 DeviceDataLoader 来包装我们的训练和验证数据加载器,以便自动将数据批量传输到 GPU(如果可用的话)。## 定义模型现在是时候定义我们的模型了。我们将扩展包含训练函数的 **nn.module** 类。我们将在 **ImageClassificationBase** 类中定义可用于任何图像分类类的函数。*   **精度**功能将帮助我们计算每个历元后模型的精度。
*   **training_step** 将在训练数据集上批量训练我们的模型,并计算损失。
*   **validation_step** 将通过在验证数据集上应用我们的模型来计算验证损失。
*   **validation_epoch_end** 和 **epoch_end** 用于显示每个历元后的损失和精度。## 创建一个 RESNET CNN我们现在已经定义了基类,它包含了训练模型所必需的函数。我们仍然没有定义我们的模型架构。我们将使用的模型被称为卷积神经网络。它不是对张量的每个元素都应用权重,而是从一个核开始,它只是一个权重的小矩阵。这个内核在 2D 输入数据上“滑动”,对它当前所在的输入部分执行元素级乘法,然后将结果相加到单个输出像素中。[ [来源](/intuitively-understanding-convolutions-for-deep-learning-1f6f42faee1)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/746ad250ddc3ad38944d6908b1f2242d.png)来源:[https://towards data science . com/直观理解-卷积用于深度学习-1f6f42faee1](/intuitively-understanding-convolutions-for-deep-learning-1f6f42faee1)使用卷积神经网络的优势是—*   **更少的参数**:使用一小组参数(内核)来计算整个图像的输出,因此与完全连接的层相比,该模型的参数要少得多。
*   **连接的稀疏性**:在每一层中,每个输出元素只依赖于少量的输入元素,这使得向前和向后的传递更加高效。
*   **参数共享和空间不变性**:由图像的一部分中的内核学习的特征可以用于检测另一图像的不同部分中的类似模式。对于我们的卷积模型,我们还将添加一个**残差块**。该块将原始输入添加回通过将输入传递通过一个或多个卷积层而获得的输出特征图。我们不能改变残差块中的输出通道,因为那样的话输入和输出形状会改变,从而不可能将两者相加。上面是一个简单的剩余块的例子。这里,卷积层之后是 **ReLU** ,它是一个非线性激活函数,保留正值并将负值设置为零。ReLU 之后是另一个卷积层。我们可以将输入添加回该层的输出,然后应用 ReLU,反之亦然。现在我们准备定义我们的模型。这里我们定义了一个有 3 层的卷积块。将输入通道数转换为输出通道数的卷积层、[批量归一化](https://machinelearningmastery.com/batch-normalization-for-training-of-deep-neural-networks/#:~:text=Batch%20normalization%20is%20a%20technique,required%20to%20train%20deep%20networks.)层和 ReLU 层。如果 pool 设置为 *True,* [Max Pooling](https://computersciencewiki.org/index.php/Max-pooling_/_Pooling#:~:text=Max%20pooling%20is%20a%20sample,in%20the%20sub%2Dregions%20binned.) 将在前 3 层之后应用。我们已经扩展了 ImageClassificationBase 类来定义我们的架构。如您所见,我们有 2 个卷积块,后跟一个残差块。这是重复 2 次以上。由于每个卷积块将使我们的图像的维度减半,通道的数量加倍,所以在我们的最终残差层之后,我们的 3 * 64 * 64 图像将被转换为 1024 * 4 * 4。然后,我们应用了一个分类器块,该分类器块将信道的数量转换成 6 个值,这 6 个值表示属于每个垃圾箱的概率。我们现在可以将我们的模型移动到 GPU。## 训练模型现在我们可以定义函数来训练我们的模型。*   **evaluate** 函数将调用 validation_step()并返回验证损失。
*   我们使用了一些技术来改进我们的模型,包括**学习速率调度**、**权重衰减**和**梯度裁剪**。关于这些的更多信息可以在[这里](https://www.notion.so/Data-Augmentation-Regularization-and-Res-Nets-b30e613133b345a3846f724c897ca2dc#6aa005432297462190d9c0436f2ffc41)找到。让我们检查一下我们的初始精度和损失。由于模型尚未训练,损失相当高,而准确性非常低。我们现在准备训练我们的模型。我们已经用 0.001 的最大学习率训练了我们的模型 10 个时期。我们已经达到了 80%的准确率。让我们以较低的学习率再训练 5 个时期的模型。精确度在 80%左右反弹,这表明除非我们改变我们的模型结构,引入新技术,增加图像尺寸或微调超参数,否则我们不会达到更高的精确度。## 评估模型性能我们现在知道我们的模型大约有 80%的准确性。这还不是结束,重要的是要多了解为什么会这样。我们现在将绘制一些图表来更好地理解我们的模型。1.  **精确度与纪元:**可以观察到,在第一个历元中精度增加了最大余量,随后,曲线变得平滑。2.**训练和验证损失与时期:**从趋势来看很明显,我们的模型并没有过度拟合训练数据,因为两条曲线都下降了。尝试逐个移除数据扩充层和剩余层,以研究它们对过度拟合的影响。3.**学习率与时期:**请记住,我们对模型进行了两次训练。在这两种情况下,学习率在大约 30%的时期增加,然后开始下降。这就是学习率调度器的作用。让我们尝试预测一些样本图像的标签。## 生成测试预测我们现在可以对测试数据集进行预测。在上面的例子中,我们的模型已经猜对了。但是我们的模型并不是 100%准确。下面是我们的模型出错的图像的例子。正如我们所见,该模型有时会给出错误的结果。## 保存工作Jovian 让我们保存笔记本并记录超参数以备将来参考。## 结论计算正在发展,深度学习是计算可以给我们的最新和最伟大的东西。垃圾分离,尽管这个过程很乏味,但我们在现实中不仅是垃圾分离,而且几乎任何乏味,复杂和不人道的过程都可以通过人工智能实现自动化。我们肯定离有意识的机器人帮助人类世界还有很长的路要走,但毫无疑问,这是朝着正确方向迈出的一步。## **学分:**1.  这个博客是[深度学习项目的一部分:PyTorch : Zero to GANs](http://zerotogans.com) ,这是一个由 [Jovian](http://jovian.ai) 提供的广泛、丰富且非常有趣的免费认证课程。特别感谢 Aakash N.S .和整个木星团队。
2.  数据集提供:[https://www.kaggle.com/asdasdasasdas/garbage-classification](https://www.kaggle.com/asdasdasasdas/garbage-classification)
3.  PyTorch 文档:[https://pytorch.org/](https://pytorch.org/)
4.  一个可执行的 Jupyter 笔记本可以在[这里](https://jovian.ai/aditya-pat10/garbage-segregation)找到。# 高斯、冒名顶替者和创造空间> 原文:<https://towardsdatascience.com/gauss-imposters-and-making-room-for-creativity-ad01daabacae?source=collection_archive---------40----------------------->“实用”对你意味着什么?在 TDS,我们尽量保持宽松的定义。我们每天与你分享的文章必须提供独特的价值:你可以在日常生活中利用的东西。但是一个高层次的理论解释或者一个关于工作和身份的个人反思也同样有用——甚至同样实用!—作为一个执行良好的教程。本周的变数就是一个很好的例子。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f79cd32d22c345514d293049202a5cd6.png)照片由 [June Wong](https://unsplash.com/@junio_006?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄我们从 [Ryan Sander](https://medium.com/u/dca93f60cd11?source=post_page-----ad01daabacae--------------------------------) 的一篇帖子开始:高斯过程回归 (GPR)的[第一原理介绍,这是一类强大的机器学习算法,数据科学家在各种各样的项目中都会用到它。从那里去一个非常好的地方?Maxim Ziatdinov](/gaussian-process-regression-from-first-principles-833f4aa5f842) 的[全景展示了旋转不变变分自动编码器](/how-we-learnt-to-love-the-rotationally-invariant-variational-autoencoders-rvae-and-almost-562aa164c59f) (rVAE)及其在那些以分析成像数据为生的人中的优势。它提供了历史和背景,以及几个可供考虑的实例。我们阅读上面两篇文章是为了学习和成长,但有时——比许多人想象的更频繁——即使是博览群书、经验丰富的数据科学家也会经历骗子综合症。 [Dale Markowitz](https://medium.com/u/1b81dbdfe1ea?source=post_page-----ad01daabacae--------------------------------) 分享了[她从个人经历](/how-i-one-humble-engineer-deal-with-imposter-syndrome-6075ee2b10a8)中获得的关于这一系列感受的见解,并为读者提供了一些有用的导航工具。戴尔提出的观点之一是,我们偶然发现自己的知识缺口不仅仅是好的,而是不可避免的。在机器学习中尤其如此,在机器学习中,模型部署过程依赖于许多可能出错的小步骤。我们对帮助填补这些特定类型的、范围明确的空白的帖子情有独钟。如果你也这样做,你会欣赏瓦莱丽·凯里的[对特征选择](/feature-choice-and-fairness-less-may-be-more-7809ec11772e)的尝试及其对模型公平性的影响,以及[雅格布·塔利亚布埃](https://medium.com/u/bffd30619c10?source=post_page-----ad01daabacae--------------------------------)对自动为机器学习管道生成文档的[工具的演练。你也不会想错过](/dag-card-is-the-new-model-card-70754847a111)[Sohini Roychowdhury](https://medium.com/u/28d2cbcd292f?source=post_page-----ad01daabacae--------------------------------)博士的基于 U-net 的[关于多类图像分割的迁移学习教程](/a-machine-learning-engineers-tutorial-to-transfer-learning-for-multi-class-image-segmentation-b34818caec6b)。完成本周的编辑推荐阵容?伦敦专题: [Philip Wilkinson](https://medium.com/u/ec0e018f30da?source=post_page-----ad01daabacae--------------------------------) 关于空间聚类的帖子使用犯罪数据作为城市的几个简洁可视化的基础。(如果你在读完之后有了重新观看《夏洛克》的灵感,我们不会责怪你。)## 联系的艺术和实践这是一个常见的比喻,表明数据科学家需要成为强有力的故事讲述者。很少有人谈到这样一个事实,即这些故事通常作为一篇文章存在——无论是幻灯片、学术文章,还是——为什么不呢?—一篇 TDS 帖子([想写一篇](/questions-96667b06af5)?).编辑 [Elliot Gunn](https://medium.com/u/aad1101621dd?source=post_page-----ad01daabacae--------------------------------) 收集了一些我们[的最佳资源来帮助技术专家写出可靠的作品](/the-all-time-best-guides-to-data-science-writing-tues-b6fec391e9d9),虽然他们提供了许多不同的观点,但他们分享了一个重要的事实:“写作可能比编码更难。”研究数据科学家和 TDS 编辑助理 [Lowri Williams](https://medium.com/u/e98db206e1b3?source=post_page-----ad01daabacae--------------------------------) [在我们最近的 Q & A](/lowri-williams-on-how-to-connect-your-academic-training-to-real-world-challenges-bc43ef3cdfed) 中同意这种观点:“我也不会说写一篇博客文章更容易。要清晰、连贯地写作有时很有挑战性!”但是好处很值得;[阅读我们对话的其余部分](/lowri-williams-on-how-to-connect-your-academic-training-to-real-world-challenges-bc43ef3cdfed)听听 Lowri 关于她的职业道路和当前工作的更多信息,她充分利用自己的学术专长来帮助中小型企业主。交流的关键作用以及围绕人工智能建立和引导安全感的需要也是我们最近的播客嘉宾 [Ethan Perez](https://medium.com/u/bbd762c9dcf1?source=post_page-----ad01daabacae--------------------------------) 首先想到的。[听听他与主持人](/making-ai-safe-through-debate-935fe8a0ec5) [Jeremie Harris](https://medium.com/u/59564831d1eb?source=post_page-----ad01daabacae--------------------------------) 的对话,了解更多关于他在基于辩论的人工智能策略方面的工作(以及更多!).时间从来都不宝贵;在一周内,当我们中的许多人把一个小时还给时钟变化时,情况更是如此。因此,我们特别感谢您选择与我们和我们的作者一起在 TDS 上花费大量时间,并感谢您实践的其他形式的支持——从[成为媒体成员](https://medium.com/membership)到与您的网络分享我们的工作,再到向我们提供反馈。直到下一个变量,
TDS 编辑器## 我们策划主题的最新内容:## 入门指南*   [数据科学家破解商业案例面试的终极指南:第一部分](/the-ultimate-guide-to-cracking-business-case-interviews-for-data-scientists-part-1-cb768c37edf4)作者[艾玛·丁](https://medium.com/u/1b25d5393c4f?source=post_page-----ad01daabacae--------------------------------)
*   [为什么 Python 中的装饰者是纯粹的天才](/why-decorators-in-python-are-pure-genius-1e812949a81e)作者 [Rhea Moutafis](https://medium.com/u/593908e0206?source=post_page-----ad01daabacae--------------------------------)
*   [git lab 入门:绝对初学者指南](/getting-started-with-gitlab-the-absolute-beginners-guide-ea9e5cadac8b)作者 [Marie Lefevre](https://medium.com/u/2a04bf49928f?source=post_page-----ad01daabacae--------------------------------)## 实践教程*   [Pascal Janetzky](/custom-audio-classification-with-tensorflow-af8c16c38689)[用 TensorFlow](https://medium.com/u/672b95fdf976?source=post_page-----ad01daabacae--------------------------------) 定制音频分类
*   [数据科学访谈中你应该知道的十个高级 SQL 概念](/ten-advanced-sql-concepts-you-should-know-for-data-science-interviews-4d7015ec74b0)作者 [Terence Shin](https://medium.com/u/360a9d4d19ab?source=post_page-----ad01daabacae--------------------------------)
*   [如何将变形金刚应用于任何长度的文本](/how-to-apply-transformers-to-any-length-of-text-a5601410af7f)## 深潜*   [通过](/selecting-hyperparameter-values-with-sequential-human-in-the-loop-search-space-modification-766d272ed061) [Hai Rozencwajg](https://medium.com/u/5921283ee0f1?source=post_page-----ad01daabacae--------------------------------) 使用顺序、人在回路、搜索空间修改选择超参数值
*   [(深度)豪斯:制作人工智能生成的豪斯音乐](/deep-house-making-ai-generated-house-music-e1447b06b53d)作者[塔加特·邦汉](https://medium.com/u/2e2b1936481f?source=post_page-----ad01daabacae--------------------------------)
*   [在模糊逻辑](/classifying-simple-color-matching-outfits-with-the-help-of-fuzzy-logic-fc9733ce8346)的帮助下对简单的配色服装进行分类 [Fernando Carrillo](https://medium.com/u/4f90b3fb8449?source=post_page-----ad01daabacae--------------------------------)## 思想和理论*   [固定效应回归](/fixed-effect-regression-simply-explained-ab690bd885cf) —简单解释[陈路静](https://medium.com/u/cfd57c91fe70?source=post_page-----ad01daabacae--------------------------------)
*   [改善图像数据类别不平衡的 4 种方法](/4-ways-to-improve-class-imbalance-for-image-data-9adec8f390f1)作者 [Emily Potyraj (Watkins)](https://medium.com/u/ff882220c17d?source=post_page-----ad01daabacae--------------------------------)
*   [Dmitry Obukhov](/breakthroughs-in-speech-recognition-achieved-with-the-use-of-transformers-6aa7c5f8cb02)[利用变形金刚](https://medium.com/u/1a0c11528869?source=post_page-----ad01daabacae--------------------------------)实现语音识别的突破# 用于聚类的高斯混合模型> 原文:<https://towardsdatascience.com/gaussian-mixture-models-for-clustering-3f62d0da675?source=collection_archive---------11----------------------->## 扩展 K-Means 以外的聚类知识的初学者指南。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/efee1123b89eb76b2e5249d13c8297f4.png)纳蕾塔·马丁在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片# 介绍最近,我在一个项目中使用 K-Means,并决定看看聚类算法还有什么其他选择。我总是觉得埋头拓展我的数据科学技能是一件令人愉快的事情。我决定写这篇文章来分享我在探索拓宽我的聚类知识以包括使用高斯混合模型的过程中所发现的经验。# 高斯混合模型综述当听说这种技术时,您可能会想到高斯分布(也称为正态分布)。这正是这种聚类技术的基础。它假设数据点来自多维高斯分布,这些分布可能具有不同的协方差、均值和密度参数。高斯混合模型基于一种叫做期望最大化或 EM 的算法工作。当给定高斯混合模型的聚类数时,EM 算法试图通过两个基本步骤计算出这些高斯分布的参数。*   **E-step 根据可用数据对参数进行猜测。**数据点被分配到一个高斯聚类,并计算它们属于该聚类的概率。
*   **M 步骤根据 E 步骤的计算结果更新聚类参数。**根据 E 步骤中的数据点计算聚类的均值、协方差和密度。
*   重复该过程,继续更新计算值,直到达到收敛。如果你熟悉 K-Means,这个过程在高层次上确实是一样的。类似的流程是进行猜测、计算值,然后重新调整直到收敛。# 拟合高斯混合聚类模型对高斯混合的工作原理有了基本的了解后,有趣的部分是开始编码和实验。使用 Python 和 Scikit-Learn,只需几行代码就可以实现一个集群模型。我鼓励你看看高斯混合类的 Scikit-Learn 文档页面。

from sklearn.mixture import GaussianMixturegm = GaussianMixture(n_components=n, random_state=123, n_init=10)
preds = gm.fit_predict(X)


`n_components`参数是您指定集群数量的地方。`n_init`参数允许您控制算法初始化的次数。聚类在开始时所处的初始位置可以设置算法来挑选坏的聚类参数。通过多次初始化,您减少了仅仅因为初始放置运气不好而聚集在坏簇上的机会。最后,拟合和预测可以在一个步骤中完成,只需对示例中表示为 X 的数据调用`fit_predict()`方法。# 有多少个集群?但是我的数据中有多少聚类呢?您可能已经注意到,为了将模型应用于您的数据,您必须为分类数选择一个值。您如何知道哪个集群编号最能代表您的数据?你有几个选择,我会过一遍。## 反复试验通常,找到合适的分类编号的最佳方法是尝试不同的分类编号,看看哪一个更适合您的数据。为拟合高斯混合模型挑选聚类数的两个最流行的评估指标是 BIC 和 AIC。BIC 代表贝叶斯信息准则,AIC 代表阿凯克信息准则。计算这两个指标的直觉是,它们倾向于最大化模型似然函数的最简单模型。计算 AIC 和 BIC 很容易,因为它们是 Scikit-Learn 高斯混合类的内置方法。通过设置一个循环来尝试不同的集群编号并计算 AIC 和 BIC,您可以将这些指标绘制在一起以选择您的集群编号。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/978137b435c5677a293d8f3028e8e089.png)BIC 和 AIC 情节(图片由作者提供)你可以看到 AIC 和 BIC 非常相似。 **BIC 和 AIC 意味着** **最小化**所以选择图表中的低点。这两种方法通常会选择相同的聚类数,但如果它们不同,那么就知道 BIC 比 AIC 更倾向于简单模型,但 AIC 模型往往更好地拟合数据。在本例中,我将选择 5 作为数据的最合适的聚类数,因为在此之后图表将真正趋于平稳。## 贝叶斯高斯混合模型我遇到的另一种选择聚类数的方法是使用 Scikit-Learn 中的[贝叶斯高斯混合模型类。当您符合此模型时,它有一个属性来返回错误聚类的权重,错误聚类的权重等于或接近于零,并且基本上会自动移除这些聚类。同样,您只需要几行代码就可以适应这个模型。](https://scikit-learn.org/stable/modules/generated/sklearn.mixture.BayesianGaussianMixture.html)

from sklearn.mixture import BayesianGaussianMixture
import numpy as npbgm = BayesianGaussianMixture(n_components=10, n_init=10)
bgm.fit(X)
np.round(bgm.weights_, 2)


模型创建完毕,与之前一样拟合,但现在我们可以返回一个聚类权重数组。我自己的实验返回了这个数组:数组([0.09,0.25,0.16,0.07,0.06,0.24,0.13,0。, 0., 0.])这让我看到模型基本上已经自动挑选了适当数量的集群,因为不需要的集群被加权为 0。# 利弊这些模型的一个优点是它们可以处理更多种类的形状,主要是形成省略号形状的集群。像 K-Means 这样的东西实际上只擅长于近似球形的聚类。有一个`covariance_type`参数允许调整不同形状的簇。然而,对于高斯混合模型来说,类似月牙形的簇仍然难以准确识别。另一个积极的方面是,这些模型允许软分类。K-Means 是一个硬分类模型,其中每个数据点被分配到一个单独的聚类。然而,高斯混合方法计算属于聚类的数据点的概率。这些概率可以在拟合模型后使用`predict_proba()`方法获得。我在玩高斯混合模型时发现的一个警告是,它们比 K-Means 模型需要更长的时间来运行,因为它们需要更长的时间来收敛。请注意您使用的数据量以及涉及的要素数量。当特别试验贝叶斯高斯混合类时,它经常给出关于如何不能达到收敛的错误。当这种情况发生时,你可以增加`max_iter`参数,但这也意味着运行时间会更长。请记住,这也可能意味着您的数据不太适合高斯混合聚类风格。# 结论这种类型的集群还有很多值得探索的地方。我试图让这成为一个指南,用简单的英语解释概念,让你开始,但我鼓励你查找公式,挖掘正在发生的事情背后的数学。 [Scikit-Learn 集群用户指南](https://scikit-learn.org/stable/modules/clustering)是一个很好的起点。# 基于 Python 的高斯混合模型> 原文:<https://towardsdatascience.com/gaussian-mixture-models-with-python-36dabed6212a?source=collection_archive---------2----------------------->## 无监督学习## 在这篇文章中,我简要介绍了无监督学习方法的概念,高斯混合模型,以及它在 Python 中的实现。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f416164362654c8dd92513ca99fe5d0e.png)由 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的 [Edge2Edge 媒体](https://unsplash.com/@edge2edgemedia?utm_source=medium&utm_medium=referral)拍摄T 何**高斯混合模型** ( ***GMM*** )作为一种**无监督**学习算法用于聚类是众所周知的。这里,“*高斯*是指高斯分布,用均值和方差来描述;*混合*指一个以上高斯分布的混合。这个想法很简单。假设我们知道一组数据点来自多个不同的高斯模型(对于 *1-d* 数据,高斯模型由均值标量和方差标量描述,对于 *N-d* 数据,由均值向量和方差矩阵描述),如果我们知道它们的密度函数,我们可以知道每个数据点属于 2 个高斯模型之一的概率(如下例所示)。然后,我们能够将数据点分配给高斯混合中概率最高的一个特定模型。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/64d8b6f88e78e8b2a727443617b12d6e.png)2 高斯分布的高斯混合密度(图片由作者提供)。从上面描述的程序,相信你已经注意到了,高斯混合模型中有**两个最重要的**东西。一个是 ***估计高斯混合中每个高斯分量的参数*** (如上图右侧所列),另一个是 ***确定一个数据点属于哪个高斯分量*** 。这就是为什么聚类只是高斯混合模型最重要的应用之一,但高斯混合模型的核心是密度估计。为了估计描述高斯混合模型中每个高斯分量的参数,我们必须了解一种叫做 [**期望最大化** ( ***EM*** )算法](https://en.wikipedia.org/wiki/Expectation%E2%80%93maximization_algorithm)的方法。当模型依赖于一些不可观测的潜在变量时,EM 算法被广泛用于参数估计。高斯混合模型中的潜在变量是描述数据点属于哪个高斯分量的变量。由于我们只观察了数据点,这个变量是一个未观察到的潜在变量。在这篇文章中,我简要描述了**使用 EM 算法**构建高斯混合模型的思想,以及**如何用 Python** 实现该模型。我在学习 EM 的时候,最大的问题是对方程的理解,所以在这篇帖子里我会尽量解释没有很多方程的算法。## EM 算法在 GMM 中到底做了什么?简而言之, **EM 算法**是针对高斯参数估计的。为了更好地理解概念,我们从头开始。显然,在理解高斯混合分布之前,我们必须先理解单个高斯分布。假设我们有一个数据点序列,每个数据点只有一个特征( *1-D* 数据集)。我们可以沿着该特征的轴绘制这些数据点的密度。例如,我们想通过测量苹果的直径来描述一桶 *Gala* 苹果的大小。我们不想只知道苹果的平均直径,而是想知道苹果大小的整体分布。因此,我们将分布绘制如下。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/beffcb6557d548325e75a922e2f660ff.png)苹果大小的高斯分布(图片由作者提供)上面的密度图也可以由下面的等式描述,![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1118cfc95d254d084074835c469b9ef2.png)高斯分布密度函数(图片来自作者)其中,μ是均值,σ是标准差。通常,我们用**均值**和**方差**来描述一个高斯分布。很简单,对吧?接下来,假设我们不小心把一桶*嘎拉*和一桶*富士*苹果混在了一起。我们这里没有水果专家,所以周围没有人能区分水果和藤茶。我们所能做的仍然是测量苹果的大小。我们还能把它们分开吗?理论上讲,是的,如果*星系*与*藤球*在大小上有真正的差异。注意,由于我们现在只能测量大小,我们应该祈祷这个唯一的特征能够足够好地分离苹果。上面描述的情况是可以应用 ***高斯混合模型*** 聚类的现实问题。如果苹果的直径遵循如下所示的两种不同的高斯分布,我们会非常高兴,![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3d735d14fb199a1ac7d584c83365fc93.png)两种截然不同的高斯分布(图片由作者提供)在这种情况下,我们可以简单地应用硬截止来分离这两种苹果。例如,较大的(直径超过 2 英寸)是富士牌的🍎,更小的(直径小于 2 英寸)是嘎拉🍏。然而,在大多数情况下,我们将观察到如下所示的混合分布。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6da20651aad0ae4b4f25dc33367b0dda.png)加拉和富士苹果大小的混合分布(图片来自作者)在上面的图中,顶部的 ***黑色曲线*** 是我们观察到的苹果大小的*,它代表了我们看不到的两个基本高斯分布。我们来思考一下如何用最直观的方式解决问题。****(1)** 如果我们知道两个分布的密度函数参数(均值和方差),对于每一个苹果,我们可以很容易的得到它属于*富士*的概率,也可以得到它属于*嘎拉*的概率。如果成为*富士*的概率大于成为*春晚*的概率,那么就是*富士*,反之亦然。然而,我们不知道密度函数参数。**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f2cdecebf1404d6473e8b49ac40e42c0.png)**贴着贴纸的苹果(图片由作者提供)****(2)** 如果我们突然发现每个苹果上其实已经有贴纸了,我们可以直接估算出*富士*和*嘎拉*的密度函数参数。但是等等,如果我们已经有了贴纸,为什么我们还要费心去做所有的事情呢?然而,真实的情况是,我们没有正确的贴纸,因为水果店老板的儿子玩苹果,把贴纸弄乱了。**我在说什么?你以为我疯了是因为上面的点 *(1)* 和点 *(2)* 其实是循环题?我们必须知道其中一个才能解决另一个。**实际上,我只是在描述 **EM 算法**的一次迭代。别急,请让我详细解释一下。*## *EM 算法的思想****EM 算法**具有两个主要过程的迭代序列,即 **E 步骤**和 **M 步骤**。 ***E-Step*** 估算潜变量,即每个苹果成为*富士*或 *Gala* 的概率。这个潜在变量影响数据,但不可观察。 ***M 步*** 通过最大化给定数据的似然性来估计分布的参数。似然性描述了一组参数与给定数据的匹配程度,我们希望得到它的**最大**值(与给定数据最匹配,也称为 ***最大似然估计*** )。**所以,EM 算法的真正过程应该是这样的,****EM EM EM EM EM EM EM EM…****让我们回到我们正在讨论的具体问题上来。**水果店老板的儿子帮我们完成了 EM 算法的 ***初始化步骤*** ,即**随机**给数据点(苹果)分配标签(贴纸)。这个想法是,因为我们不能直接分离数据点,我们只是给一个初始化的猜测。从现在起,我们应该让这个小男孩远离苹果。**好了,现在我们来执行 EM 算法中的 ***E 步*** 。由于我们直接来自 ***初始化步骤*** ,我们已经有了每个苹果成为*富士*或者 *Gala* 的概率。对于一个贴有*富士*贴纸的苹果,它成为*富士*的概率等于 1,成为*嘎拉*的概率等于 0。**但是,如果我们来自于之前的一个 ***M 步*** ,我们就需要用两个高斯的密度函数(从之前的 M 步估计)重新计算成为*富士*或者*加拉*的概率。如果之前贴有*富士*的苹果碰巧成为*嘎拉*的概率大于成为*富士*的概率,那么我们就用新的*嘎拉*贴纸替换当前的贴纸。如果之前的标签和当前的概率没有不一致,我们就保持标签不变。**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/514e718f9d18f97edb292af1f9efc59c.png)**估计概率,必要时更换标签。(图片由作者提供)**好了,现在我们来执行 EM 算法中的 ***M 步*** 。不管是哪个迭代,我们已经在苹果上有了初始/更新的标签(贴纸)。我们可以用给定的标签直接估计出*富士*和*加拉*分布的高斯参数。基本上,我们只根据贴有“*富士*的苹果来估计*富士*高斯参数,然后根据贴有“*嘎拉*的苹果来估计*嘎拉*高斯参数。从理论上讲,我们找到了在给定苹果贴纸的情况下使可能性最大化的参数集。**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c72ae9e7d0cd636d6e60e89970dca4d5.png)**给定当前标签,最大化可能性。(图片由作者提供)**然后,我们反复重复上述两个步骤,直到苹果的分配**不再变化**(严格来说,直到**可能性**函数中的**变化**非常**小**)。**这就是 EM 算法在现实问题中的完整过程。你觉得苹果分离任务中的 EM 算法怎么样?很难吗?我用了很多方程式吗?不是真的,对吧?*## *提高执行力的技巧**如果你真的思考苹果分离任务,你会意识到里面有很多现实问题。**例如,商店老板的小儿子只是随机地发起苹果贴纸**而不记得他做了什么。那么,我的苹果分离任务会因为不同的苹果贴纸初始分配而有很大的不同吗?另外,只看大小应该很难区分*嘎拉*和*富士*吧?****第一个问题的答案肯定是肯定的。理论上,对于*的 ***EM 算法*** ,并不能保证每次随机初始化都会导致相同的最终结果。为了解决这个问题,从一些不那么随机的“初始化”开始可能是一个好的选择。如果这个小男孩只是玩了 1/4 的苹果,而不是把所有的苹果贴纸都弄乱了,现在的开始可能会导致一个稳定得多的分离。****对于第二个问题,当然最好有更多的功能。例如,小男孩不仅玩苹果的贴纸,还咬每个苹果(假设他能够以定量的方式记录每个苹果的味道)。然后,对于每个苹果,我们都有大小和味道,这可能会导致更好的分离。****具有二维数据的高斯分布可以被可视化为特征空间中的椭圆。下面的 GIF 显示了具有三个高斯分量的高斯混合模型的 EM 算法的过程。你可以把它想象成一项任务,根据每个苹果的已知大小和味道,将*富士*、*旮旯*和*甜脆*苹果分开。****GMM 上 EM 算法的过程 GIF(免费 GIF 来自 Tenor[https://Tenor . com/view/Gaussian-mixture-models-EM-method-math-gauss-computer-science-nerd-GIF-15288262](https://tenor.com/view/gaussian-mixture-models-em-method-math-gauss-computer-science-nerd-gif-15288262))****上面 GIF 中的 *X 轴*和 *Y 轴*可以分别是标准化的大小和标准化的味道。可以看到初始化的三个组件是如何逐渐移动到特定的 apple 集群的。**## **如何用 Python 实现?****相对于理解 GMM 中 EM 算法的概念,Python 中的实现非常简单(感谢强大的包 scikit-learn)。**

import numpy as np
from sklearn.mixture import GaussianMixture# Suppose Data X is a 2-D Numpy array (One apple has two features, size and flavor)GMM = GaussianMixture(n_components=3, random_state=0).fit(X)


*****Gaussian mixture***是函数, ***n_components*** 是底层高斯分布的个数, ***random_state*** 是初始化的随机种子, ***X*** 是我们的数据。这里的 ***X*** 是一个 ***二维*** *NumPy* 数组,其中每个数据点有两个特征。****拟合数据后,我们可以检查任何具有这两个特征的数据点(苹果)的预测聚类。**

GMM.predict([[0.5, 3], [1.2, 3.5]])


**有时,高斯分量的数量并不明显。我们可以通过使用 [AIC](https://en.wikipedia.org/wiki/Akaike_information_criterion) 或 [BIC](https://en.wikipedia.org/wiki/Bayesian_information_criterion) 作为标准来调整它(可能会在未来的帖子中进一步解释)。**

aic(X)
bic(X)


**就是这样!**的概念与实现 *GMM* 中的**Python*中的***。希望有帮助。******如果你觉得文章过于简单笼统,又偏爱更多的方程和数学,可以参考以下优秀帖子,这里</gaussian-mixture-models-explained-6986aaf5a95>*[*这里*](https://www.mygreatlearning.com/blog/gaussian-mixture-model/) ,这里<https://stephens999.github.io/fiveMinuteStats/intro_to_em.html>*。****## ***参考资料:******<https://scikit-learn.org/stable/modules/generated/sklearn.mixture.GaussianMixture.html#sklearn.mixture.GaussianMixture>  <https://en.wikipedia.org/wiki/Expectation%E2%80%93maximization_algorithm>  <https://machinelearningmastery.com/expectation-maximization-em-algorithm/>  </gaussian-mixture-models-explained-6986aaf5a95>  ![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/dfe03db5fb385468f0f718a426fd1a39.png)Christine Jou 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片***# (高斯)朴素贝叶斯> 原文:<https://towardsdatascience.com/gaussian-naive-bayes-4d2895d139a?source=collection_archive---------9----------------------->## (高斯)朴素贝叶斯模型介绍,包括理论和 Python 实现![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7db7757593916d70c73e2a4da065e7c3.png)(高斯)朴素贝叶斯模型的决策边界图解。图片作者。# 内容这篇文章是我将要发表的一系列文章的一部分。你可以通过点击[这里](https://cookieblues.github.io/guides/2021/04/01/bsmalea-notes-3b/)在我的个人博客上阅读这篇文章的更详细版本。下面你可以看到该系列的概述。## 1.机器学习导论*   [(一)什么是机器学习?](/what-is-machine-learning-91040db474f9)
*   [(b)机器学习中的模型选择](/model-selection-in-machine-learning-813fe2e63ec6)
*   [(c)维度的诅咒](/the-curse-of-dimensionality-5673118fe6d2)
*   [(d)什么是贝叶斯推理?](/what-is-bayesian-inference-4eda9f9e20a6)## 2.回归*   [(a)线性回归的实际工作原理](/how-linear-regression-actually-works-theory-and-implementation-8d8dcae3222c)
*   [(b)如何使用基函数和正则化改进您的线性回归](/how-to-improve-your-linear-regression-with-basis-functions-and-regularization-8a6fcebdc11c)## 3.分类*   [(a)分类器概述](/overview-of-classifiers-d0a0d3eecfd1)
*   [(b)二次判别分析(QDA)](/quadratic-discriminant-analysis-ae55d8a8148a)
*   [(c)线性判别分析](/linear-discriminant-analysis-1894bbf04359)
*   **(d)(高斯)朴素贝叶斯**# 设置和目标我们已经了解了二次判别分析(QDA)和线性判别分析(LDA ),前者假设特定于类的协方差矩阵,后者假设类之间共享协方差矩阵,现在我们将了解(高斯)朴素贝叶斯,它也略有不同。如果你没有看过我在 QDA 上的帖子,我强烈推荐它,因为 Naives Bayes 的推导是相同的。朴素贝叶斯假设特征是独立的。这意味着**我们仍然假设特定类别的协方差矩阵(如在 QDA),但是协方差矩阵是对角矩阵**。这是因为假设特征是独立的。因此,给定一个具有相应目标变量 *t* 的 *N* 输入变量 **x** 的训练数据集,(高斯)朴素贝叶斯假设**类条件密度**是正态分布的![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/152fe7860d9297f6232823ee207109e0.png)其中 ***μ*** 是**类特定均值向量**,而**σ**是**类特定协方差矩阵**。利用贝叶斯定理,我们现在可以计算后验概率![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/35b4ad99045d0364c5e9b68f6f2a7e5e.png)然后我们将把 x 分类到类中![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e72ab5f9f343eabff439e2416f672e13.png)# 衍生和培训这种推导实际上与从 QDA 推导特定类别的先验矩阵、均值矩阵和协方差矩阵是一样的。你可以在我之前关于 QDA 的文章[这里](/quadratic-discriminant-analysis-ae55d8a8148a)找到出处。唯一的区别是,我们必须将特定于类的协方差矩阵中除对角线以外的所有内容都设置为 0。因此,我们得到以下结果![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ba570564816faf430cabc3a0105925e9.png)其中 diag 表示我们将不在对角线上的每个值都设置为 0。# Python 实现下面的代码是我们刚刚讨论过的(高斯)朴素贝叶斯的简单实现。下面是一个图表,其中包含数据点(颜色编码以匹配其各自的类)、我们的(高斯)朴素贝叶斯模型找到的类分布,以及由各自的类分布生成的决策边界。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7557f1425a8d6578e5ec78413d3f4631.png)数据点的图表,其各自的类别用颜色编码,通过我们的(高斯)朴素贝叶斯模型找到的类别分布,以及从类别分布得到的决策边界。图片作者。注意,虽然在 LDA 的情况下判定边界不是线性的,但是类别分布是完全圆形高斯分布,因为协方差矩阵是对角矩阵。# 摘要*   朴素贝叶斯是一个**生成**模型。
*   (高斯)朴素贝叶斯假设**每个类遵循高斯分布**。
*   QDA 和(高斯)朴素贝叶斯的区别在于**朴素贝叶斯假设特征**的独立性,这意味着**协方差矩阵是对角矩阵**。
*   记住,LDA 有一个共享的协方差矩阵,其中**朴素贝叶斯有特定于类的协方差矩阵**。# 高斯过程:物理主动学习的第一步> 原文:<https://towardsdatascience.com/gaussian-process-first-step-towards-active-learning-in-physics-239a8b260579?source=collection_archive---------21----------------------->马克西姆·齐亚丁诺夫&谢尔盖·加里宁*美国田纳西州橡树岭橡树岭国家实验室纳米材料科学和计算科学与工程中心*尽管在研究对象和研究方法上存在极大的差异,但一些任务在多个科学领域是共同的。其中一项任务就是插值。想象一下,测量一些感兴趣的属性,比如温度(如果你是气象学家)或土壤成分,或者某个地区有用矿石的存在(如果你是地质学家)。在(通常很少)数量的测量点之间插入这些数字以获得适合人眼的 2D 图是非常有用的。这可以使用多种方法来实现,包括样条、核密度近似、神经网络拟合和许多其他方法。然而,当这样做时,第二个自然的问题是这些插值的不确定性,或者它们在多大程度上是可信的。在进行测量的位置,不确定性明显最小,但是当远离测量点时,不确定性会增加。最后,第三个也可能是最有趣的问题是,我们能否利用插值函数及其不确定性的知识来指导我们的搜索策略。换句话说,给定在几个位置的感兴趣的财产的测量,我们能选择测量的下一个点吗——基于预期的奖赏或得到一个的概率。所有这些问题都可以使用高斯过程(GP)和基于 GP 的贝叶斯优化以有原则的方式来解决。类似的问题,尽管定义在不同的参数空间,出现在多个其他科学领域。寻找具有有趣和有用性质的材料通常意味着探索二元、三元和四元相图,即 1D、2D 和 3D 组成空间。调整显微镜以获得最佳分辨率意味着调整几个控制参数,例如尖端偏压和隧道电流(对于扫描隧道显微镜)或驱动偏压和设定点(对于压电响应力显微镜)。即使在理论/模拟中,我们也经常希望通过调整少量交换参数来探索特定哈密顿量的相图。显然,所有这些问题都可以通过网格搜索来解决,即评估我们的系统或运行显微镜,或为每个参数组合合成一个材料样本。同样明显的是,这是极其不切实际的。例如,对于材料合成,如果我们想要研究每 1%浓度的成分,我们将需要 100 个二元体系的样品、三元体系的 10⁴样品和四元体系的 10⁶样品。那需要一段时间!在物理科学中,这些问题通常使用直觉、近似方法和实验/模拟的组合来解决。例如,为了将伊辛哈密顿量的相图定义为温度的函数,可以使用近似方法来获得非常高和非常低的温度下的系统行为。类似地,可以分析系统的普适类及其在相变附近的行为。剩下的任务是找到相关的转变温度和临界指数,来描述系统在其附近的行为。在实验科学中(例如,调整显微镜),当参数改变时,通常对系统的行为有很好的预期。最后,材料科学家使用热力学理论和测量的结合来探索少量迭代内的相图。然而,这些方法是非常异构和特定于领域的。数据科学家会怎么做?解决这些问题的方法是高斯过程。这种方法的正式定义和讨论可以在许多优秀的公开出版物和教科书中找到,特别是由 [Rasmussen 和 Williams](http://www.gaussianprocess.org/gpml/) 编写的。在这里,我们想提供一个稍微不寻常的方法来描述 GP,集中在实验如何提高我们对世界的理解,以及这些知识如何编码在正式的数学结构中。想象在低维参数空间上定义一个标量函数(或感兴趣的属性)。这可以是全球范围内的温度、三相图中的材料硬度或磁性,或者显微镜图像中的对比度。在任何测量(或计算)之前,我们都不知道函数的可能值,也就是说,一切皆有可能。在测量了几个位置上的函数值后,严格地说,我们只知道这些位置上的值,别的什么都不知道。然而,假设我们感兴趣的函数值在整个参数空间中以某种方式相关是合理的。在物理学中,我们经常寻找一些特定的函数形式,要么是现象学的,要么是由基本物理定律规定的。但是,从数据科学的角度来看,我们假设相邻位置的函数值之间的关系是由一个核函数定义的,例如 exp(-(*xᵢ*-*xⱼ*)/2*l*)。后者被称为径向基函数,是 GP 中最常见的核函数之一。参数 *l* 定义了过程的特征长度尺度,通常从数据中推断出来。更正式地,给定数据集 *D* ={ *xᵢ* , *yᵢ* }, *i* =1,…, *N,*其中 *x* 和 *y* 是输入特征和输出目标,高斯过程可以由以下概率模型定义:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/000381a84c5b4f9081a26dd2e50affe3.png)其中 *MVN* 是多元正态分布, **m** 是先验均值函数(通常选择某个常数), **K** 是我们的核函数,具有(超)参数 *σ* 和 *l* ,我们为其选择了弱信息对数正态先验。我们还假设存在正态分布的观测噪声, **ϵ** ~ *正态* (0,*s*t30】I,这样 **y** ₙₒᵢₛᵧ **=y + ϵ.**实际上,我们把它吸收到核函数的计算中。建立模型和先验分布后,下一步是获得新的/未知数据的预测后验概率。这里,我们从 NumPyro 的概率编程库中使用哈密顿蒙特卡罗(HMC)算法获得 GP 模型参数的后验样本。然后,我们在提供的新输入点 Xₙₑᵥᵥ:从模型输出的多元正态后验样本中进行采样![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/fa2a38c4e8a0578f8dc10203335f301a.png)其中 ***θ*** *ⁱ* 是包含核超参数和模型噪声的单个 HMC 后验样本。让我们看看它是如何工作的,对于一个简单的 1D 函数,我们得到一些稀疏的噪声观测。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3cf524629ca35fbc41cb7d689ba05fa8.png)图一。周期函数 sin(10 *x* )的噪声观测。作者图。给定图 1 中观察到的数据,我们对等式(1)中定义的模型运行 HMC,以获得模型参数的后验样本。然后,我们根据等式(2)在-1 和 1 之间的点的密集均匀网格上计算后验预测分布。结果如下所示:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6c150f5ddf6786c29d2296e12e145707.png)图二。在等式 2a 中,GP 预测从多元正态后验样本中取样。还显示了取样平均值的质量中心(等式 2b)。作者图。请注意,与许多其他插值方法相比,GP 的一个独特之处在于它提供了关于预期函数值和每个预测点的不确定性的信息。后者只是抽样预测中的方差(或标准差)。对于图 2 中的数据,我们将得到-0.75 到-0.25 之间的较大不确定性,因为在该区域没有观测值。请注意,GP 模型在预测该区域的平均函数值方面仍然做得很好。在继续讨论如何使用不确定性来导航参数空间之前,让我们快速看看如果我们改变一个核函数会发生什么。具体来说,我们将用 exp(-2 sin(*π*(*xᵢ*-*xⱼ*)/*p*/*l*)形式的周期核替换我们的 RBF 核,在周期*p*~*uniform*(0.1,1.0)上具有均匀的先验。然后,我们重新运行 HMC,并重新计算我们的后验预测分布。周期性内核的结果如下所示。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/57f65902d0a5173fda4729f3f9f0a92d.png)图 3。基于周期核的 GP 预测。作者图。显然,现在的预测要好得多(而且模型对它们也更有把握了!).这表明适当的 GP 核的选择可以由问题的物理学来指导。GP 预测的平均函数值和相关的不确定性可以用于导出所谓的采集函数,用于在参数空间中选择下一个测量点。一种常用的获取函数被称为置信上限(UCB ),本质上是预测平均值和不确定性的线性组合,![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5dda9e3efaa584e64012765a14283d9d.png)其中*k*0 用于最小化问题,而*k*0 用于最大化问题。下面我们用一个简单的 1D 例子来说明采集功能是如何工作的。假设我们想要最小化某个黑盒函数,我们有大约 16 个噪声观测值(图 4)。如果不考虑不确定性,我们的下一个测量点将在 0.15 左右,这似乎是基于可用观测值和 GP 重建的函数的最小值。然而,在 0.4 和 0.6 之间有相对较高的不确定性,以及在~0.65 以上,所以可能还有另一个更深的最小值藏在那里。UCB 采集功能将这种不确定性考虑在内,并输出下一个测量点(约 0.5°)。然后,我们在该点执行测量,更新我们的观察值,并且(如果必要的话)“重新训练”我们的 GP 模型,以导出另一个获取函数来获得下一个测量点。利用已测量点附近的区域和探索“未知”之间的平衡(或权衡)是贝叶斯优化的核心。当然,还有许多其他更复杂的获取函数,我们建议感兴趣的读者参考 Nando de Freitas 的[关于贝叶斯优化的综述](https://www.cs.ox.ac.uk/people/nando.defreitas/publications/BayesOptLoop.pdf)。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1fba8fb10ab6945c9a40ea6b7cbd8def.png)图 4。对于 *k* = -2(右),未知目标函数的 GP 预测(左)和导出的 UCB 采集函数(见等式 3)。作者图。为了说明真实物理系统的贝叶斯优化过程,我们探索伊辛模型的相图,正如在我们最近的论文中详细描述的那样。这里,我们使用基于 GP 的贝叶斯优化和 UCB 获取函数来有效探索晶格哈密顿量的参数空间,并绘制特定宏观功能最大化的区域。在下面的图 5 中,我们通过单独的快照展示了在次近邻伊辛模型中发现热容量最大化的参数空间区域的例子。可以看到,该算法在感兴趣的区域上快速归零,允许以有效的(与常规网格搜索相比)方式发现具有最高热容量的区域。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7205b06bf777a3a78beb95f8e09f44ee.png)图 5。伊辛模型中基于 GP 的热容量贝叶斯优化。显示的是 GP 在步骤 100、200、300、400 和 600 发现的所有点,以及全网格模拟(“地面实况”)。作者图。总之,这里我们介绍高斯过程和贝叶斯优化方法,并举例说明它们的实现和实际物理问题的应用。除了对伊辛模型的分析,GP 还被用于研究铁电体中的[磁滞回线](https://doi.org/10.1063/5.0011917),[在自动合成中探索混合钙钛矿的成分空间](https://doi.org/10.1021/acsenergylett.0c01749),[在扫描探针、电子显微镜和光谱学中实现超分辨率](https://doi.org/10.1063/5.0013847),甚至[控制操作显微镜](https://pubs.acs.org/doi/abs/10.1021/acsnano.0c10239)探索铁电薄膜中的极化动力学。然而,尽管 GP 功能强大,这里讨论的一个简单实现还是有许多明显的局限性。第一个也是最明显的一个是,GP 运行的参数空间往往是相当低维的,最佳性能通常限于< 6 D 空间。第二个限制是相关性的结构是由核函数定义的,尽管已经提出了大量的核函数,包括各向异性的和周期的,但是这些核函数中的大多数本质上都是唯象的。最后,它往往是计算密集型的。然而,在许多情况下,基本的 GP 方法可以很容易地扩展到其他方向。例如,深度神经网络和高斯过程的结合产生了一系列[深度内核学习](https://arxiv.org/abs/1511.02222)方法,这些方法结合了深度学习的表达能力和 GP 的灵活性。也可以通过用预期系统行为的概率模型替换 GP 的常数均值函数来直接注入先验物理知识。袖手旁观为未来的博客文章关于 DKL 和 sGP 在物理科学中的应用!也请查看我们的 [GPim](https://github.com/ziatdinovmax/GPim) 和 [gpax](https://github.com/ziatdinovmax/gpax) 软件包,将 GPs 应用于科学数据,重点是成像和光谱学。最后,在科学界,我们感谢资助这项研究的赞助商。这项工作在橡树岭国家实验室纳米材料科学中心(CNMS)进行并得到支持,该中心是美国能源部科学用户设施办公室。您可以使用[此链接](https://my.matterport.com/show/?m=MT819FqAwbT)进行虚拟漫游,如果您想了解更多,请告诉我们。可执行的 Google Colab notebook 带有文中讨论的基本 GP 示例,可从这里[获得](https://colab.research.google.com/github/ziatdinovmax/notebooks_for_medium/blob/main/GP_for_medium.ipynb)。# 高斯过程模型> 原文:<https://towardsdatascience.com/gaussian-process-models-7ebce1feb83d?source=collection_archive---------2----------------------->## 能够模拟复杂行为的简单机器学习模型[高斯过程](https://en.wikipedia.org/wiki/Gaussian_process)模型与更受欢迎的机器学习算法如[线性回归模型](https://en.wikipedia.org/wiki/Linear_regression)、[基于树的模型](https://en.wikipedia.org/wiki/Decision_tree)或[基于感知器的模型](https://en.wikipedia.org/wiki/Perceptron)相比,可能是不太为人所知的机器学习算法之一。这是不幸的,因为高斯过程模型是少数几个可以解析求解同时仍然能够对相对复杂的系统建模的机器学习模型之一。尽管目前在更广泛的机器学习和数据科学社区中相对缺乏人气,但高斯过程模型已经在一些领域中找到了各种用途,例如[地质统计学](https://en.wikipedia.org/wiki/Kriging)和[昂贵评估函数的优化](https://en.wikipedia.org/wiki/Bayesian_optimization),例如深度学习神经网络的超参数搜索,或[激光优化](https://arxiv.org/pdf/1909.05963.pdf)。今天,我将向您展示高斯过程模型是如何工作的,并教您如何使用 Python 创建自己的高斯过程回归模型!![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/64a486c12088c55cb49b42acd3d1748e.png)亚利桑那国家公园。Andrew Coelho 在 [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄的照片。# 高斯过程高斯过程模型假设观察目标 *yₙ* 的值具有以下形式:*yₙ*=*f*(**x**t26】ₙ)+*eₙ*,其中*f*(**x**ₙ)是产生被观察目标的某个函数,**x**t8】ₙ是一组 *φ* 输入中的第 *n* 行**x**=**x**₁、 **x** ₂、**x**ᵩ观察到 *yₙ* 给定*f*(**x**t32】ₙ)的条件概率为正态分布:*p*(*yₙ*|*f*(**x**ₙ)=*n*(*yₙ*|*f*(**x***ₙ*), *σ* ),其中 *σ* 为 *eₙ* 的标准差。由于假设噪声对于每个样本都是独立的,因此以**(**x【75】)的φ*** 值为条件, *φ* 观测目标值**y**=【*y*₁、 *y* ₂、……y*ᵩ*]ᵀ的联合概率分布***p*(**y**|**|*f***(**x**)=*N*(**y**|**|*f***(**x**), **σ** ),**其中**σ=***σ***I**是大小为 *φ* × *φ的对角矩阵。***为了对 **y** 做出预测,我们需要确定边际概率分布***p*(**y**)。这个概率分布可以通过使用积分将条件分布*p*(**y**|**|*f***(**x**))边缘化于分布*p*(***f***(**x**)来获得:*******p*(**y**)=∫*p*(**y**|***f***(**x**)*p*(***f***(**x**)d***f***(**x**)。******分布*p*(***f***(**x**))定义为均值为 **0** 且协方差核矩阵 **K** 大小为 *φ* × *φ* 的高斯分布:*******p*(***f***(**x**)=*N*(***f***(**x**)|**, **K** )。**********协方差矩阵 **K** 由 **x** 中两行之间的距离组成,并假设相似的输入应在 **y** 中产生相似的目标值。矩阵 **K** 中的每个元素计算如下:************K** [ *n* ,*m*=*k*(**x**t82】ₙ,**x**t86】ₘ),**********其中 *k* 是稍后定义的函数。使用上面的*p*(***f***(**x**))的等式,我们可以执行 *p* ( **y** )中涉及的积分来获得解:***********p*(**y**)=∫*p*(**y**|***f***(**x**)*p*(***f***(**x**)d **σ**)*N*(***f***(**x**)|**0**,**K**d***f***(**x**)**********其中得到的协方差矩阵具有以下形式:**C**=**K**+**σ**=**K**+*σ***I**。因此, **C** 中的各个元素可以写成: **C** [ *n* ,*m*=*k*(**x***ₙ*,**x***ₘ*+*σδₙₘ*。*****# *****二次指数核**********可以使用用于*k*(**x**t38】ₙ,**x**t42】ₘ)的各种协方差核函数,例如顾名思义基本上是常数的[常数核](https://scikit-learn.org/stable/modules/generated/sklearn.gaussian_process.kernels.ConstantKernel.html#sklearn.gaussian_process.kernels.ConstantKernel),广泛使用的二次指数核(也称为[径向基函数(RBF)](https://en.wikipedia.org/wiki/Radial_basis_function) ,或者通常用于对周期性数据建模的[周期性核](https://scikit-learn.org/stable/modules/generated/sklearn.gaussian_process.kernels.ExpSineSquared.html)。**********在本文的其余部分,我们将使用二次指数核。这个内核是由成对的样本(**x**t52】ₙ,**x**ₘ)在 **x** 中计算出来的:***********k*(**x***ₙ*,**x***ₘ*)= exp(-| |**x***ₙ*-**x***ₘ*| |/2*l【t79)、***********其中 *L* 是一个内核超参数,为了方便起见,我们将其设置为 1。*****# *****新观测值的概率分布**********对于目标的 *φ* 观测值**y**=【*y*₁、 *y* ₂、……y*ᵩ*]ᵀ对应一组 *φ* 输入值**x**=【**x**₁、 **x** ₂、… **x** *ᵩ* ]ᵀ这一步需要我们确定概率分布*p*(*yᵩ*₊₁|**y**)的参数(即均值和协方差)。**********为了确定*p*(*yᵩ*₊₁|**y**)的参数,我们从分布 *p* ( **y** '),其中 **y** ' = [ *y* ₁, *y* ₂,… y *ᵩ* , *yᵩ* ₊₁]ᵀ是一个长度为的向量从上面的 *p* ( **y** )的解,我们得到*p*(**y**’)的相应解:***********p*(**y**')=*N*(**y '**|**0**, **C'** ),**********其中大小为 *φ* +1× *φ* +1 的新协方差矩阵**C’**具有以下结构:************C'** = [[ **C** , **k** ,
..…….[ **k** ᵀ, *c* ]] **,************其中**c**=**k**+*σ***I**是来自上面的原始 *φ* × *φ* 协方差矩阵, **k** 是长度为 *φ* 的向量,其元素由:**k***n*给出 而 *c* 是包含 **x** *ᵩ* ₊₁与自身的协方差的标量:*c*=*k*(**x***ᵩ*₊₁,**x***ᵩ*₊₁)+*σ*。*****# *****高斯过程预测**********如前所述,高斯过程是少数几个具有从[条件概率](https://en.wikipedia.org/wiki/Conditional_probability)获得的解析解的机器学习模型之一,如下所示。**********如果我们有一些正态分布的*n*(**r**|***μ***,**σ**)随机变量的向量 **r** ,分割成两个任意长度的子向量:**r**=【**r***ᵤ*, **r** *ᵥ* , 然后对于条件分布**p*(**r***ᵤ*|**r**|*ᵥ*)均值***μ***(**r***ᵤ*|**r*ᵥ*和协方差**σ*****************μ***(**r***ᵤ*|**r***ᵥ*)=***μ****ᵤ*+**σ***ᵤᵥ***σ************σ**(**r**t100】ᵤ|**r**t104】ᵥ)=**σ***ᵤᵤ*-**σ***ᵤᵥ***σ***ᵥᵥ*⁻**σ【t119**********其中***μ****ᵤ*/***μ****ᵥ*是包含**r***ᵤ*/**r***ᵥ*和**σ**元素均值的向量********对于我们的情况,**r**ᵤ对应于新的观测值,而**r**ᵥ对应于旧的一组 *φ* 观测值。因此新旧观测值之间的协方差**σ**ᵥᵤ是带有元素的向量**k**k*n**= k*(**x**t24】ₙ、**x**ᵩ₊₁),旧观测值的协方差**σ** *m*=*k*(**x***ₙ*,**x***ₘ*)+*σδₙₘ*新观测值的协方差***ᵤᵤ*是标量***c*=*k*( 根据我们上面的定义***μ****ᵤ=****μ****ᵥ=***0**。**************把一切放在一起,条件概率分布*p*(*yᵩ*₊₁|**y**)是一个均值为的高斯分布:*************μ*=**k**ᵀ**c**⁻**y**,************和方差:*************s*=*c*-**k**ᵀ**c**⁻**k**。******# ******在 Python 中实现高斯模型************上面的分析解决方案可以很容易地用 Python 实现!首先,我们创建一个函数来计算输入特征*φ*x=【**x**₁、 **x** ₂、… **x** *ᵩ* ]ᵀ:的二次指数核矩阵**************K** [ *n* ,*m*]=*k*(**x***ₙ*,**x***ₘ*)= exp(-|**x***ₙ*-**************此外,为了简化起见,我们假设 *σ* = 0,使得 **C** = **K.**********

import numpy as npdef RBF_kernel(xn, xm, l = 1):
"""
Inputs:
xn: row n of x
xm: row m of x
l: kernel hyperparameter, set to 1 by default
Outputs:
K: kernel matrix element: K[n, m] = k(xn, xm)
"""
K = np.exp(-np.linalg.norm(xn - xm)
2 / (2 * l
2))
return Kdef make_RBF_kernel(X, l = 1, sigma = 0):
"""
Inputs:
X: set of φ rows of inputs
l: kernel hyperparameter, set to 1 by default
sigma: Gaussian noise std dev, set to 0 by default
Outputs:
K: Covariance matrix
"""
K = np.zeros([len(X), len(X)])
for i in range(len(X)):
for j in range(len(X)):
K[i, j] = RBF_kernel(X[i], X[j], l)
return K + sigma * np.eye(len(K))
****


******新的预测平均值*μ*=**k**ᵀ**c**⁻**y**和协方差*s*=*c*-**k**ᵀ**c**⁻**k**可使用以下函数计算得出。******

def gaussian_process_predict_mean(X, y, X_new):
"""
Inputs:
X: set of φ rows of inputs
y: set of φ observations
X_new: new input
Outputs:
y_new: predicted target corresponding to X_new
"""
rbf_kernel = make_RBF_kernel(np.vstack([X, X_new]))
K = rbf_kernel[:len(X), :len(X)]
k = rbf_kernel[:len(X), -1]
return np.dot(np.dot(k, np.linalg.inv(K)), y)def gaussian_process_predict_std(X, X_new):
"""
Inputs:
X: set of φ rows of inputs
X_new: new input
Outputs:
y_std: std dev. corresponding to X_new
"""
rbf_kernel = make_RBF_kernel(np.vstack([X, X_new]))
K = rbf_kernel[:len(X), :len(X)]
k = rbf_kernel[:len(X), -1]
return rbf_kernel[-1,-1] - np.dot(np.dot(k,np.linalg.inv(K)),k)


# ******用高斯过程模型进行预测************现在我们需要做的就是用一些数据来测试这个算法!我们使用一个简单的公式*y =*(*x*-5)*得到 5 个数据点:`[1, 3, 5, 7, 9]`。对于`5.5`的新输入值,我们预测 *y* 的值。*******

def f(x):
return (x-5) ** 2# Training data x and y:
X = np.array([1.0, 3.0, 5.0, 7.0, 9.0])
y = f(X)
X = X.reshape(-1, 1)# New input to predict:
X_new = np.array([5.5])# Calculate and print the new predicted value of y:
mean_pred = gaussian_process_predict_mean(X, y, X_new)
print("mean predict :{}".format(mean_pred))# Calculate and print the corresponding standard deviation:
sigma_pred = np.sqrt(gaussian_process_predict_std(X, X_new))
print("std predict :{}".format(sigma_pred))mean predict :0.277673949912025
std predict :0.4150417380004999


******我们也可以检查高斯过程模型中使用的 **K** 的值。******

for i in make_RBF_kernel(X):
for j in i:
print("{:.3f}".format(j), end = ", ")
print()1.000, 0.135, 0.000, 0.000, 0.000,
0.135, 1.000, 0.135, 0.000, 0.000,
0.000, 0.135, 1.000, 0.135, 0.000,
0.000, 0.000, 0.135, 1.000, 0.135,
0.000, 0.000, 0.000, 0.135, 1.000,


******作为明智的检查,我们可以使用`sklearn`中的`GaussianProcessRegressor`来检查我们的算法是否有效!******

from sklearn.gaussian_process import GaussianProcessRegressorgpr = GaussianProcessRegressor()
gpr.fit(X, y)gpr_mean, gpr_std = gpr.predict(X_new.reshape(-1, 1),
return_std = True)print("sklearn pred: {}".format(gpr_mean))
print("sklearn std: {}".format(gpr_std))sklearn pred: [0.27767395]
sklearn std: [0.41504174]


******同样,我们也可以检查`sklearn`使用的核矩阵的值。注意`sklearn`使用原始核矩阵的 [Cholesky 分解](https://en.wikipedia.org/wiki/Cholesky_decomposition),以便使用以下公式优化计算: **K** = **LL** ᵀ.******

for i in np.dot(gpr.L_, gpr.L_.T):
for j in i:
print("{:.3f}".format(j), end = ", ")
print()1.000, 0.135, 0.000, 0.000, 0.000,
0.135, 1.000, 0.135, 0.000, 0.000,
0.000, 0.135, 1.000, 0.135, 0.000,
0.000, 0.000, 0.135, 1.000, 0.135,
0.000, 0.000, 0.000, 0.135, 1.000,


******我们的模型和`sklearn`的模型对于新输入`x = 5.5`都有相同的`0.278` 预测和`0.415`标准差!核矩阵也是一样的!******# ******在训练数据之外进行预测************现在让我们看看如果我们在训练数据范围外使用`x`的值会发生什么。例如:如果`x = 15`发生了什么?******

X_new = np.array([15])mean_pred = gaussian_process_predict_mean(X, y, X_new)
print("mean predict :{}".format(mean_pred))sigma_pred = np.sqrt(gaussian_process_predict_std(X, X_new))
print("std predict :{}".format(sigma_pred))mean predict :2.396794716305008e-07
std predict :0.9999999999999999


******我们发现现在预测的标准差要大得多,预测值几乎是 0。虽然高斯过程模型非常擅长在训练集的范围内插值数据,但是它们不擅长在该范围外外推。******# ******绘制模型的 95%置信区间************使用预测平均值和相应的标准差,我们可以为整个输入值范围 *x* 创建并绘制模型的 95%置信区间。******

******import matplotlib.pyplot as plt# Range of x to obtain the confidence intervals.
x = np.linspace(0, 10, 1000)# Obtain the corresponding mean and standard deviations.
y_pred = []
y_std = []for i in range(len(x)):
X_new = np.array([x[i]])
y_pred.append(gaussian_process_predict_mean(X, y, X_new))
y_std.append(np.sqrt(gaussian_process_predict_std(X, X_new)))

y_pred = np.array(y_pred)
y_std = np.array(y_std)plt.figure(figsize = (15, 5))
plt.plot(x, f(x), "r")
plt.plot(X, y, "ro")
plt.plot(x, y_pred, "b-")
plt.fill(np.hstack([x, x[::-1]]),
np.hstack([y_pred - 1.9600 * y_std,
(y_pred + 1.9600 * y_std)[::-1]]),
alpha = 0.5, fc = "b")
plt.xlabel("\(x\)", fontsize = 14)
plt.ylabel("\(f(x)\)", fontsize = 14)
plt.legend(["\(y = x^2\)", "Observations", "Predictions", "95% Confidence Interval"], fontsize = 14)
plt.grid(True)
plt.xticks(fontsize = 14)
plt.yticks(fontsize = 14)
plt.show()******


******![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/24744d930d87c8c9d9fa338f91c1e62c.png)************高斯过程模型的 95%置信区间。************不用单独检查每个新输入的标准偏差,使用这样的图形可以让我们很容易地查看模型对其预测最有信心和最没有信心的地方!******# ******更高级的协方差核************在本文中,我们使用二次指数核来计算我们的协方差核矩阵 **K** 。然而,还有许多其他的内核函数,它们可能会为某些类型的数据带来更好的性能。例如,存在一个周期内核,它对于周期数据表现得非常好!如果你想了解更多关于这些更先进的内核,请阅读我关于[高斯过程内核](/gaussian-process-kernels-96bafb4dd63e)的文章!******# ********闭幕词**************今天在这篇文章中,我们探索了高斯过程是如何工作的,并使用 Python 创建了我们自己的高斯过程回归模型!高斯过程模型非常强大,在学术界和工业界都被广泛使用。作为一个工业应用的例子,在以后的文章中,我将向您展示如何使用基于高斯过程的优化器来确定最佳激光参数,以获得特定的激光功率输出!******# ******参考************[1] C. M. Bishop (2006), [*模式识别与机器学习*](https://www.microsoft.com/en-us/research/uploads/prod/2006/01/Bishop-Pattern-Recognition-and-Machine-Learning-2006.pdf) ,Springer。
【2】[https://sci kit-learn . org/stable/modules/Gaussian _ process . html](https://scikit-learn.org/stable/modules/gaussian_process.html)
【3】[https://sci kit-learn . org/stable/modules/generated/sk learn . Gaussian _ process。GaussianProcessRegressor.html](https://scikit-learn.org/stable/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html)******# 基于第一原理的高斯过程回归> 原文:<https://towardsdatascience.com/gaussian-process-regression-from-first-principles-833f4aa5f842?source=collection_archive---------5----------------------->## [思想和理论](https://towardsdatascience.com/tagged/thoughts-and-theory)## 高斯过程回归是一类非常强大的机器学习算法。在这里,我们从基本原理开始介绍。***高斯过程回归*** (GPR)是一类非常强大的机器学习算法,与当今许多最先进的机器学习模型相比,它依赖很少的参数来进行预测。因为 GPR 是(几乎) ***非参数*** ,所以它可以有效地应用于解决各种各样的监督学习问题,即使在数据很少的情况下。借助 PyTorch 和 TensorFlow 等最先进的自动微分框架,学习 GPR 并将其应用于大量复杂的监督学习任务变得前所未有的简单。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/db902121e99e79478d3e5b1ddfb4e250.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/df8a19b2f3222b9d0700f988c7e5c153.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e4c7d2e1a12985979d93d40f5c17d157.png)从左到右:(a)在训练点(显示为绿色)上训练的 GPR 模型的预测均值(蓝色线)和置信区间(浅蓝色区间),(b)在 Ackley 测试函数上训练的 GPR 模型的预测均值,(c)在正弦训练数据上训练的 GPR 模型的预测均值。图片来源:作者。在本文中,我们将从**第一原理**开始讨论高斯过程回归(GPR),使用来自机器学习、最优化和贝叶斯推理的数学概念。我们将从高斯过程开始,用它来形式化如何用 GPR 模型进行预测,然后讨论 GPR 模型的两个关键因素:协方差函数和超参数优化。最后,我们将在下面的数学推导的基础上,讨论一些直观的方法来查看 GPR。如果你也想看到这些想法以学术风格的论文呈现,请点击这里的链接<https://drive.google.com/file/d/1KkmOahqH7bFVoezHCaarPlqPn0o8Kcvl/view?usp=sharing>**。我们开始吧!**# **什么是高斯过程?****在讨论 GPR 之前,我们先来探讨一下什么是高斯过程。高斯过程属于随机/随机过程类别,它定义了在空间和/或时间中演化的随机变量的实现。****严格地说, ***高斯过程***(***GP***)是随机变量的集合,使得这些变量的任何子集都是联合高斯的[1]。为了将 ***d*** 随机变量的集合表示为联合高斯,我们可以通过将它们表示为:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/89d60403596faf12bcd40b2230cc069f.png)****其中 ***d*** 是子集中随机变量的个数, ***μ*** 是均值的向量,**σ**是这些随机变量之间的协方差矩阵。写成高斯密度,随机变量的一组实现 **x = (xi,…,xj)** 联合高斯意味着:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/30779ff0e54f813bf930b321f5b35cbd.png)*******GP*** 的一个概念化是,它定义了函数*【1】上的***分布:给定一个完全由均值和协方差函数指定的高斯过程,我们可以根据下式从高斯过程中在点 **x** 处对函数进行采样:*********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/884a76d3952016f28dd24db0c82f28a3.png)******其中 f()是我们从 ***GP*** 中采样的函数,m()是均值函数,k(,)是协方差函数,是核函数的子类。这被称为 GPs 的功能空间视图[1]。******将数据集表示为 ***GP*** 在机器学习[1]、信号处理[3]和概率推理中有多种应用。******现在我们已经介绍了什么是高斯过程,我们准备开始讨论如何将这个概率随机过程框架用于回归!***# ***高斯过程回归******高斯过程的一个应用是通过监督学习来执行回归,因此被命名为高斯过程回归。这种回归可以概念化为核化贝叶斯线性回归,其中核参数化由协方差/核函数的选择以及用于进行预测的数据来确定[1]。这就是 GPR 的“重量-空间观点”[1]。******高斯过程回归也可以在前述的函数空间视图中概念化,其中学习者通过学习在 **x** 处实现*的**均值**和**协方差**函数来学习函数[1]的分布,由 f( **x** 表示。********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e7ff872152b0f385e2a3983b095a2768.png)********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/03f869e49912a2abc5456705dd4c3728.png)********f( **x** )给定的一个 ***GP*** 的实现对应一个 ***随机变量*** 。指定这些功能后,可以根据以下公式从 ***GP*** 中对 f( **x** )进行采样:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/884a76d3952016f28dd24db0c82f28a3.png)********这是对取决于位置 **x** 的随机变量 f( **x** )进行采样的形式化(对于空间应用;对于时间序列应用,f( **x** )可能取决于时间 t)。********f( **x** )的平均值的估计值作为观察目标值 y 的**线性组合产生。用于产生这些均值估计的加权系数是独立于目标值** 的 ***,将高斯过程回归模型放入*线性平滑器*【1】的类别中。**********给定由 ***N*** 个观察值组成的**训练**数据集:******![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d5ae16ab5e6d12bdafdfbd1760a5c1a7.png)******以及由***N’***点组成的**测试**数据集:******![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2d1853f826213032c92a8bd44c31372b.png)******GPR 预测目标 在测试点**X**∫上的 ***后验高斯分布,方法是在给定观测训练数据的情况下计算该高斯分布的参数。我们可以把这种预测看作是对每个测试点的高斯分布的准确预测。*********我们将首先考虑无*噪声预测的情况,然后用这种情况来概括模型中对于 ***噪声的观测目标值*************请注意以下衍生的定义:******1.  ******m()代表一个均值函数******
2.  ******k(,)是一个核/协方差函数******
3.  ********X** 是训练特征的(N,d)矩阵******
4.  ********X**∫**是测试点的(N’,d)矩阵********
5.  **********y** 是训练目标的(N,1)向量********
6.  ********f** 是高斯过程在训练特征 **X** 上的实现的(N,1)向量******
7.  ********f**∫**是高斯过程在测试点**X**∑上的实现的(N’,1)向量********
8.  ******Cov()是一个协方差运算符******
9.  ******σ是正的超参数,表示高斯过程的协方差噪声。************我们现在准备好推导 GPR 的预测了!******## ******无噪声预测************在我们开始之前,让我们回忆一下我们的目标:**预测测试点 X∫**处目标 f∫的高斯分布。************在无噪声的情况下,观察到的训练目标***y**和高斯过程 **f** 的*实现函数值相等。换句话说,我们直接观察高斯过程在点 **X** 的采样函数。**************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c4835efbe54c975f343326a6fd2d562e.png)************给定上面定义的训练和测试数据集,高斯过程函数在训练和测试数据集上的联合分布(分别为 **f** 和**f**∫)由[1]给出:************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e971ec40c327d404c8fd6d24744ff844.png)************其中右边的协方差矩阵是核相似性矩阵的块矩阵。************虽然联合分布给出了关于**f**∫如何与 **f** 相关的一些见解,但是在这一点上还没有对预测**f**∫进行推断。我们感兴趣的不是这种联合分布,而是测试点**X**∫处预测 GP 实现**f**∫的 ***后验分布*** 。这就是贝叶斯推理的概念发挥作用的地方:我们将 ***限定*** 我们在训练数据上的测试点的先验分布,以便改进我们对测试点的高斯均值和方差参数的估计。************该后验分布可以通过在训练数据集 **f** 的已实现目标上的测试点**f**∫处调节高斯过程的预测实现来计算。除了调节 **f** 之外,我们还调节训练输入 **X** 和测试输入**X***。************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e48469b0123d853ab42a2bef872542fa.png)************因此,我们可以将测试点**X**∫处的**均值**和**协方差**预测写成:************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/283af453864c8d082c9d274ab60ed0d1.png)************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e0931dae8948e4931898a2b69697b61b.png)************这些估算说明了什么?******1.  ********预测均值**:这是作为训练集 **f** 上高斯过程的实现的*线性组合来估计的。这个线性组合的系数由 ***距离*** 确定,在 ***内核空间*** 中,在测试点**X**∫和训练点 **X** 之间。直观地说,这意味着在内核空间中更接近于**X**∫的训练样本在预测均值中具有更强的“发言权”。这些系数也通过训练集 **X** 中的输入之间的逆核相似性 ***缩放*** 。*******
2.  ********预测协方差**:这被估计为测试点之间的核距离**X**∫减去训练输入 **X** 前后的逆 ***核距离*** 的二次形式乘以训练和测试输入之间的 ***核距离*** 。************在某些应用中,均值函数不必为零,可以写成广义 m()。在这种情况下,使用非零均值函数,测试点的预测**均值**和**协方差**估计值变为:************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1279d793e58bf5cc0e0a99640aaed3b8.png)************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e0931dae8948e4931898a2b69697b61b.png)******## ******在有噪声的情况下进行预测************在高斯过程回归的许多应用中,通常将训练目标 **y** 建模为高斯过程**f**【1】的*噪声实现*,其中噪声由零均值高斯参数化,正噪声协方差值由σ给出。************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3fb6ef68632a4b2fcaabc4500911f0db.png)************这个σ是一个可以优化的超参数(参见下面的超参数优化部分)。************使用上面的预测方程以及我们对噪声目标值 **y** 的定义,我们可以表达观测到的训练目标 **y** 的联合分布,以及在测试点**X**∫的高斯过程**f**∫的预测实现:************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6ba7e110a91ad1b00f495df5df852f5d.png)************使用与上述相同的条件直觉和过程,我们可以将预测的高斯过程实现的条件分布**f**∫以观察到的训练目标 **y** 为条件表示为:************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c0b22959f5d020f5d66b74a730f23e63.png)************这是一个很大的解构,但预测均值和协方差的公式与之前基本相同,只是在反向训练核相似性项中添加了对角噪声。************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f20a274a0437cd5e8e6a62105d2a32d1.png)************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ce8736d4be736d69f6380278985951e6.png)************添加协方差噪声的一个实际考虑是,它可以确保括号中的矩阵在 GPR 超参数优化期间保持半正定,这进而允许括号中的矩阵是可逆的。************上述推导描述了 GPR 如何进行预测的精确分析框架。然而,这些方程的一些元素仍然是相当黑盒子,如核/协方差矩阵和协方差噪声。在下面的章节中,我们将讨论 GPR 的这些重要元素。******## ******协方差函数************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9348e50708ba606781dd4b0de33aadb9.png)************考虑协方差函数的一种方式是,它们通过双线性映射测量空间中的点有多接近。照片由 [Siora 摄影](https://unsplash.com/@siora18?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄************协方差函数是 GPR 模型的重要组成部分,因为***这些函数根据观测训练点 **X** 和测试点 **X** 之间的 ***核距离*** 来衡量训练点*** 对预测测试目标的贡献。回想一下上一节,将 GPR 预测概念化的一种方法是作为一种*线性平滑*机制:预测的**意味着在测试点**X***实际上可以表示为:***********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/91d441284e9486b6dc5d2e2efdd5a8dd.png)******因此,**预测均值**是观测目标值 y 的**线性组合,具有由测试点和训练点之间的*核距离确定的*,训练点的平均贡献被考虑。************以下是 GPR 文献中经常使用的一些协方差函数示例[1]:*****1.  *******平方指数(SE) /径向基函数(RBF)核**与**自动相关性判定(ARD)**【4】。ARD 能够为每个输入维度学习单独的长度尺度,因此适合于在每个维度中具有可变尺度和输出灵敏度的高维输入空间。该协方差函数由下式给出(其中**θ**是长度标度的对角矩阵):**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/18859aae419ebad125ccd98a2e202353.png)**********2.**具有 ARD 的有理二次(RQ)核:**RQ 核可以被概念化为 **SE** 核的无限混合,其中混合权重由正超参数α [1]控制。**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7f93e7e319234c7f608b12da084568aa.png)**********3.**带 ARD 的 Matérn 内核:**在某些条件下,这种内核允许完美的插值[1]。请注意,ν是一个超参数,用于确定插值中允许的不连续程度,K 是二阶贝塞尔函数,γ()是伽马函数。**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4bd774e6edbaebf045d57ecd6f8c818f.png)*****## *****高斯过程回归模型是完全非参数的吗?**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7c3328e9d675307994a8161f423e44a1.png)**********为了优化我们的 GPR 模型的超参数,我们可以使用**梯度上升**优化方法。照片由[迪奥戈·塔瓦雷斯](https://unsplash.com/@diogotavares?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄**********尽管高斯过程回归模型被认为是*非参数*,但其超参数,如长度尺度【1】,会显著影响其预测能力,因此应进行优化,以最大化*预测样本外性能*。幸运的是,像许多其他监督学习模型一样,这些超参数可以使用 ***梯度方法***【1】进行优化。*********优化 GPR 模型超参数的目标是*【1】。然而,由于这种边际似然性具有指数项,因此通常通过最大化边际对数似然性来执行这种优化,以便导出解析梯度更新[1]。由于边际对数似然函数是边际似然函数的严格单调变换,最大化边际对数似然的超参数集也将最大化边际似然。**********由一组超参数 **θ** 参数化的边际对数似然由下式给出(当对观察目标中的噪声建模时):**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0a8c6c1e82a27b484a121b03f1d86955.png)**********如上所述,为了优化 GPR 模型的超参数,计算关于 **θ** [1]的边际对数似然的导数:**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1fb7c235337342ec42b58b9419e7f6a3.png)**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0aff360bfedc2c053cca4d2c2cc35b7f.png)**********然后,使用 ***梯度上升*** 方法(如 Adam【5】)将这些导数用于更新 GPR 模型的超参数。这会导致表格的渐变更新:*********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ce7ebc2d6ba92ebef35bc72a2c92333e.png)********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3cecfb6b4bea79e0fac1e15a0a885623.png)********在 GPR 的超参数已经在观察的训练数据集( **X** , **y** )上被优化之后,GPR 模型准备在测试数据集**X**∑上执行 ***后验推断*。******## ****回顾********到目前为止,我们已经讨论了:(I)GPR 模型如何进行预测,(ii)GPR 的协方差函数,以及这些函数在确定点之间的相似性/距离方面发挥的关键作用,以及(iii)我们如何优化 GPR 模型的超参数以提高其样本外性能。********接下来,为了加强我们的直觉,我们来讨论一下 GPR 的其他一些解释。****# ****我们还可以从哪些方面思考 GPR?********与其他机器学习技术和算法一样,高斯过程回归(GPR)有许多解释。这里有几个与我们上面讨论的相关。GPR 是一种算法,它:****1.  ****计算联合多元高斯*分布的一个 ***测试集*** 给定一个 ***训练集*。**这被形式化为从高斯过程中采样一个函数。*****
2.  ****将 d 维输入( ***特征*** )空间中的点插值到 m 维输出( ***目标*** )空间中。在一定条件下,这些(测试)预测插值点是现有(训练)点的*线性组合*!****
3.  ****给定过去和现在,预测未来的平均值和标准差。****
4.  ****在由协方差函数(半正定核)参数化的高维特征空间中执行回归。********让我们用直觉和应用上面的数学推导来讨论每一个。****## ******1。联合多元高斯后验**********也许这就是高斯过程回归中“高斯”的由来。这种机器学习技术将数据建模为源自高斯过程。回想一下,高斯过程是被认为是联合高斯的 ***N*** 个随机变量的集合。********“后”在这里是什么意思?嗯,像其他监督机器学习模型一样,GPR 依赖于同时拥有 ***训练*** 和 ***测试*** 数据。该模型与训练数据拟合, ***预测*** ,以****分布*** 的形式(在本例中,高斯后验分布)被定义为对 ***测试*** 集的预测的条件分布,条件是来自*集的观测值)。*************2。插值************![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6ea77d4d5b19ae3d78396f4f9333fdb6.png)**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c46e7fb4bb985c03f991a516f0d06ca0.png)**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/02db0af8da1faf058f787fd437e02148.png)**********插值/克里金法[2]是高斯过程回归的最早应用之一[2]!插值代表了 GPR 的一个主要用例,因为我们可以使用现有的点来插值新点的均值和协方差。**********GPR 也可以作为非参数插值方法!这在空间统计字段[2]中也被称为**克里金法**,它允许从一维和多维**输入**中内插一维和多维**输出**。**********这里,当计算预测平均值时,使用与上面相同的思想来执行插值:通过取最近的训练点的组合来估计插值点,并且通过它们的核距离(“相似性”)来加权它们。与“较远”的点相比,“较近”的点对新点的预测贡献更多的输出。************3。利用过去和现在预测未来************GPR 是时间序列预测的常用工具,因为它能够捕捉时间行为,允许自动测量和加权两个时刻的“接近”程度。**********回想一下,由于我们预测的是高斯后验分布,并且高斯分布完全由其均值和方差参数确定,因此从 GPR 进行预测所需的全部工作就是预测未来时间的均值和方差。**********预测这些量实际上是非常强大的-从中可以提取置信区间(均值+/ sqrt(方差)),以及感兴趣的量随时间的预测平均值/期望值。**********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4076eb6d791e638439cd08712e4fa80b.png)**********时间序列**均值**和**方差**预测使用高斯过程回归的一个例子。图片来源:作者。*****## *****4.用协方差函数度量高维特征空间中的“接近度”**********GPR 的最后一个令人兴奋的解释是,它是有效的贝叶斯回归,其特征空间由一组可能无限维的基函数组成!**********这个结果是 ***默塞尔定理*** *的一个推论。*该定理的部分陈述如下:*********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/038949bd15d434f399e3dcd28a60a5da.png)********函数φ( **x** )及其共轭φ*(**x’**)是核(在我们的例子中是协方差)函数k( **x** ,**x**’)的**本征函数**。这些本征函数是特殊的,因为在一个度量上对它们进行积分,例如概率密度 p( **x** 或勒贝格度量[1] **,**导致本征函数本身,由一个称为**本征值的数来缩放,**在这里由λ来表示。我们可以把上面的这个表达式看作是我们的核[1]的一个*广义傅立叶级数*表示。请注意,这意味着我们可以有无限数量的基函数**来将我们的输入转换成特征。这和**内核诡计**原理相似。**********将该结果与上述线性平滑函数结果相结合,我们可以将潜在预测的表达式重写为特征值-特征函数组合的加权和:********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8351b19643b928c2dca4ff4aa70abd4c.png)********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b9ba2b2934d47413783e52d1636ce575.png)********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/07e73f82b13ba1d504dba1dee5d8e0f7.png)********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/dee4403cdc4b80ea1cd9ade92f5c60d6.png)********![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2f7e7ed8c4f2d0c0c01766935d607c58.png)********上面的结果有什么关系?我们已经表明,用于形成预测的输出的线性组合由在训练和测试点应用的协方差函数的 ***本征函数*** 和 ***本征函数*** 确定。除了选择协方差函数和协方差噪声,**这里的预测完全由数据本身决定**!这说明了为什么高斯过程回归被认为是 ***非参数*** 。********即使特征函数分析不是你真正喜欢的,这里也有一个重要的要点: ***GPR 通过协方差函数*** 将我们的标准贝叶斯回归设置转换成一个无限维的特征空间!根据协方差函数的选择,这可以承认****无限的表现力*** 为我们的 GPR 模型。这是 GPRs 如此强大和通用的一部分,适用于广泛的监督机器学习任务。*****# ****我怎样才能学到更多?********下面是一些(非常有帮助的)资源,可以帮助你开始。这个清单当然不是详尽无遗的:****1.  ****[**机器学习的高斯过程**](http://www.gaussianprocess.org/gpml/chapters/RW.pdf)**【1】**:一本数学上严谨的高斯过程教科书。这本书着重于 GPR 背后的概率和几何理论,如核,协方差函数,测量,估计和再生核希尔伯特空间(RKHSs)。****
2.  ****[**内核指南**](https://www.cs.toronto.edu/~duvenaud/cookbook/) :这是一本很好的 GPR 学习指南,你可以问自己:“我应该使用什么 GPR 协方差函数?”本指南结合了直觉和数学的严谨性。****
3.  ****[**自动相关性确定**](https://link.springer.com/content/pdf/10.1007%2F978-1-4471-0847-4.pdf)**【ARD】**:如协方差函数部分所介绍的,ARD 对于具有可变特征尺度和跨输入维度的输出敏感度的 GPR 问题特别有用。****# ****总结和回顾********在本文中,我们介绍了高斯过程(GPs)和高斯过程回归(GPR)模型,以及它们的一些理论和直观基础。********在我们下一篇关于 GPR 的文章中,我将回顾一些 GPR 模型的**应用**和**实现资源**。********要查看更多关于强化学习、计算机视觉、机器人和机器学习的内容,请关注我。感谢您的阅读!****# ****感谢********感谢 [CODECOGS](https://codecogs.com/) 提供了极其有用的[内联方程渲染工具](https://codecogs.com/latex/eqneditor.php),也感谢 Carl Edward Rasmussen 开源了机器学习的教材*高斯过程*。****# ****参考********[1]卡尔·爱德华·拉斯姆森和克里斯托弗 K. I .威廉姆斯。2005.机器学习的高斯过程(自适应计算和机器学习)。麻省理工学院出版社。********[2]奥利弗,玛格丽特和理查德·韦伯斯特。"克里金法:地理信息系统的一种插值方法."《国际地理信息系统杂志》4.3(1990):313–332。********[3]奥本海姆、艾伦五世和乔治·c·韦尔盖塞。*信号,系统&推理*。哈洛:皮尔森,2017。打印。********[4]胡斯迈尔 D. (1999)自动相关性确定(ARD)。条件概率估计的神经网络。神经计算的前景。伦敦斯普林格。[https://doi.org/10.1007/978-1-4471-0847-4_15](https://doi.org/10.1007/978-1-4471-0847-4_15)********[5]金玛、迪德里克 p .和吉米巴。"亚当:随机最优化的方法."arXiv 预印本 arXiv:1412.6980 (2014)。****# 时间序列数据的高斯平滑> 原文:<https://towardsdatascience.com/gaussian-smoothing-in-time-series-data-c6801f8a4dc3?source=collection_archive---------4----------------------->## 用 Python 学习时间序列数据中高斯平滑的内部工作原理# 时序数据顾名思义,时间序列数据是时间索引数据。数据点是在不同的时间戳收集的。通常,我们会在 x 轴上显示小时、天或年等时间变量,在 y 轴上显示我们正在收集的数据。时间序列数据的一个例子是相对于天数的新新冠肺炎病例数。## 观察数据与真实数据观察数据是我们观察到的数据点。它们是数据生成/报告过程的结果。另一方面,真实的数据是真相,是世界上正在发生的事情的真实价值。让我用新冠肺炎新案例的例子来区分一下。每天出现的新病例是*报告的*新病例。它们可能不等于真正的新病例数。这是因为一些新案例可能没有被报告,一些积压的案例可能已经被添加到今天的新案例中。下面,我们看到*尼*的新增病例*的时序图。我们注意到少数地方突然出现峰值和下降,这可能是报告不足和/或报告积压的结果。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cf824553bcfbcff4a158dd1736460c84.png)因此,在处理这些数据时,减少噪音是有帮助的。通过将数据点与其相邻数据点进行平均来减少此类时间序列数据中的噪声的过程称为平滑。有许多技术可以降低噪声,如简单移动平均、加权移动平均、核平滑器等。我们将学习并应用*高斯核平滑器*进行平滑或去噪。# 高斯核核定义了用于取相邻点平均值的函数的形状。高斯核具有高斯曲线的形状。高斯曲线具有以下形状:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ec449157ee87a5db0fc1e291b4744acb.png)来源:维基共享资源正如在高斯曲线中看到的,近点(在上面的曲线中大约为 0)将被赋予更高的权重,而远点将被赋予更低的权重。高斯核的数学表达式如下所示:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f690fae35c99c0fe772ad0e0d79a4cbe.png)来源:[维基百科](https://en.wikipedia.org/wiki/Kernel_smoother)其中, *b* 定义内核的宽度。# 平滑过程为了进行平滑,我们逐点处理数据。对于每个点,我们计算核函数值,并计算由核函数值加权的数据点的加权平均值。这里用一个例子来理解一下。我们采用之前显示的尼泊尔 COVID 新病例数据。2020 年*10 月 27 日*新增病例数为 *570 例*,而前一天新增病例数为 *1741 例*,后一天新增病例数为 1954 例。570 不太可能是当天新增病例的真实数字。让我们尝试使用高斯核平滑器来平滑新的案例数。首先,我们来计算基于*2020 年 10 月 27 日*的高斯核值。我们这里任意取了 *b* = *2* 。我们认为+2/-2 天的高斯核宽度占用了很大比例的邻居数据。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0d761776b28a01cf955930776261c014.png)上图显示了与日期相关的高斯核值。精确日期和邻近日期被赋予最高权重(接近 1),而较远的日期被赋予接近 0 的权重值。我们将核值标准化,这样我们就不会增加新的案例数量。我们通过将高斯核值除以所有高斯核值的总和来实现。然后,我们将*新案例*列与*高斯核值*列进行逐元素相乘,并将它们相加,以获得*平滑后的*案例数。我们得到平滑后的病例数: *2036* 。当日报告病例数为 *570* 。我们预计平滑会增加当天的病例数,事实也确实如此。这样,我们可以减少数据中存在的噪声,使其看起来更加平滑。让我们对所有的数据点进行平滑处理。我们完成了将*高斯核平滑*应用于新病例的数量。让我们看看新的平滑后的新案例数与以前的新案例数相比如何。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/79c12c4bf3199a0c41b04f136de62a8c.png)我们可以在上面的图中看到平滑的线几乎没有噪音。平滑减弱了急剧下降和峰值。因此,我们使用高斯核平滑器实现了我们想要做的。选择 *b* 对我们得到的平滑程度有影响。如果我们将 *b* 增加到 *4* ,我们会得到更平滑的数据。然而,我们应该小心选择更高的 *b* 值,因为重要的尖峰、下降可能会丢失。让我们看看 *b* 的值等于 *4* 的平滑图。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/24be4dd047faaa08e9a108f1a5bf455e.png)正如所料,我们得到了一个更平滑的图形。我们理解了高斯内核平滑器的内部工作原理,甚至看到了它在 Python 中的实现。我们在平滑的时候调整了超参数 *b* 并且看到了它的效果。我们了解到超参数 *b* 应该仔细选择。如果您正在尝试对时间序列数据进行建模,平滑可能是您想要尝试的第一件事,因为它可以减少噪音并可能使您的模型更好。继续平滑,继续建模!此外,在新冠肺炎期间保持距离,并采取预防措施以保持安全。:)**尼泊尔的 COVID 数据取自数据* *中的* [*我们的世界。*](https://ourworldindata.org/covid-vaccinations)# 使用 macOS Big Sur 在 Python 中进行数据科学项目的一般设置> 原文:<https://towardsdatascience.com/general-setup-for-data-science-projects-in-python-with-macos-big-sur-65784fc20231?source=collection_archive---------23----------------------->## 为初学者安装 CLT、Xcode、Hombrew、Python 和 Pip![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b3d3951d9004bb71e99f1bf1373aa255.png)图片由来自 [Pixabay](https://pixabay.com/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=5091352) 的 [Aaron Olson](https://pixabay.com/users/aaronjolson-4628445/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=5091352) 拍摄## **一.你好 Python**Python 2.7.7 将开箱安装在您的 Mac 上。它应该在一个名为**/System/Library/framework/Python . framework**的文件夹中,与操作系统所需的其他几个 Python 2 版本放在一起。帮自己一个忙,不要修改该文件夹中的任何内容,因为后台进程可能会依赖于它们,这可能会导致系统崩溃。要在项目中使用 Python,您需要下载 Python 的新版本。导航至**[**python.org**](https://www.python.org/)**>下载> Mac OS X** 并下载当前版本(3.9.5,截至 2021 年 5 月)。如果你愿意,你可以使用图形化的安装程序。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e5b4ab2a8945ab20b6cf1dd0d6f6458c.png)****[https://www.python.org/downloads/](https://www.python.org/downloads/)****软件包下载完成后,安装程序应该会立即启动。安装完成后,您将可以使用最新版本的 Python。**## ****二。迎接终端******前往**发射台>其他>终端。******![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4a625fe4bca4b1e7a89fc32a3b9d9748.png)****Mac OS Big Sur 上的 Launchpad >其他屏幕****为了让您的生活更轻松,您可以将终端放在您的 dock 中,以便经常使用。****还有一些其他方法可以访问“终端”。要从桌面打开终端,可以使用快捷键 **command +空格键**到打开 Spotlight Search,然后在搜索栏中输入“终端”并点击 return。如果您希望在“终端”中打开更多的终端窗口,您可以使用 **command +T** 打开一个新标签,使用 **command + N** 打开一个新的终端窗口。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d59ab5b81969a5512177aa3cfc380ef8.png)****Mac OS 中的终端**## ****三世。安装 CLT 和 Xcode******现在,需要安装命令行工具和 Xcode 才能在 Mac 上使用 Homebrew 和其他工具。在终端中输入以下内容:**

% xcode-select — install


**下载所有内容可能需要一点时间。如果沿途出现任何提示,请按照它们的指示进行操作。**## ****四。安装自制软件******家酿称自己为“macOS(或 Linux)缺失的软件包管理器”在这种情况下,家酿正在实践它的主张,因为我们需要继续我们的安装。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6a408b9adc669a785b3321d9b991835f.png)****[https://brew.sh/截图](https://brew.sh/)****通过在终端中输入以下内容来安装 Homebrew:**

% mkdir homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz — strip 1 -C homebrew


**这将自动在你的**/usr/本地目录**中安装自制软件。**## ****用自制软件安装 Python(和 Pip)******家酿已经安装,现在是时候确保家酿有自己的 Python 了。**

% brew install python@3.9


**家酿将安装自己的最新版本的 Python。Pip 是下载 Python 时附带的一个包管理器。接下来,我们将使用 Homebrew 和 Pip 来安装 Python 数据科学项目所需的其他包。******六。我们做了什么?**
1。安装了最新版本的 Python。
2。向终端介绍我们自己。
3。已安装 Xcode 和命令行工具。
4。安装自制软件。
5。安装了一个专门为家酿的 Python 版本,用的是家酿。现在我们还有匹普。****这是你需要开始用 [Pyenv](https://pypi.org/project/pyenv/) 管理你的 Python 版本和用 [Virtualenv](https://pypi.org/project/virtualenv/) 管理你的虚拟环境的基础。查看下一个教程,[使用 Pyenv 和 Virtualenv](https://christineegan42.medium.com/virtual-environments-for-python-data-science-projects-on-mac-os-big-sur-with-pyenv-and-virtualenv-60db5516bf06) 在 macOS Big Sur 上进行 Python 数据科学项目的虚拟环境,了解如何操作。**# 什么是广义加性模型?> 原文:<https://towardsdatascience.com/generalised-additive-models-6dfbedf1350a?source=collection_archive---------1----------------------->## 以及您为什么需要了解它…![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6da8d73880df159133dabad28036c8ec.png)使用线性模型与 GAM 的效果。图片作者。# 介绍线性模型被认为是模型的瑞士军刀。我们可以进行许多调整,以使模型在各种条件和数据类型下表现良好。广义加性模型(gam)是一种适应,它允许我们在保持可解释性的同时对非线性数据建模。# 目录*   [什么是 GAM?](#c407)
*   [数据集](#4a2c)
*   [用线性回归估计非线性函数](#232f)
*   [GAMs 是如何工作的?](#fb90)
*   [将 GAMs 应用于自行车数据集](#64f7)
*   [游戏玩家如何工作第二部分](#6dcc)
*   [使用 PyGAM 实现线性 GAM](#6b0a)
*   [结论](#a505)# 什么是 GAM?GAM 是一个线性模型,与广义线性模型(如线性回归)相比有一个关键的区别。允许游戏者学习非线性特征。> gam 放宽了关系必须是简单加权和的限制,而是假设结果可以通过每个特征的任意函数的和来建模。为此,我们简单地用一个允许非线性关系的灵活函数替换线性回归的β系数(我们将在后面研究数学)。这种灵活的功能称为**花键**。样条是复杂的函数,允许我们为每个特征建立非线性关系模型。许多样条的总和形成一个 GAM。结果是一个高度灵活的模型,仍然具有线性回归的一些解释能力。让我们了解一下如何在没有 gam 的情况下对非线性特征建模。# 资料组这篇文章将使用经典的自行车共享数据集,可以从 [Kaggle](https://www.kaggle.com/c/bike-sharing-demand) 下载。该数据集跟踪华盛顿特区的自行车租赁数据这篇文章的笔记本在这里:<https://github.com/AdamShafi92/GAM>  # 用线性回归估计非线性函数**世界不是线性的。这意味着线性回归并不总是代表我们在现实中看到的。有时线性关系是足够好的估计,但通常不是。**让我们来看看一天中每小时**的**自行车租金中位数正如所料,这不是线性的。那么如果我们拟合一个简单的线性回归会发生什么呢?还是那句话,不出所料,这行没有太大意义。它没有抓住我们的关系,我们不能真正使用这个模型。值得注意的是,我确实做了一点小手脚,我没有对小时进行编码,这意味着模型将每个值都视为递增,然而我认为我的观点仍然有效..让我们试着把这模拟成一种非线性关系。为此,我们使用*小时*变量创建多项式特征,例如小时、小时等。随着多项式的**阶**变得更高,我们使用更多的变量,因此对于 5 阶,我们使用 x,x,x ,x⁴和 x⁵.![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b1fa005f54dc6cab6627b282ee065fb4.png)多项式特征。图片作者。在本例中,我让**在**小时 0-21**和**预测小时 22-23 训练**模型。**我们可以看到,x 模型比线性模型做得更好,高阶模型能够很好地模拟我们的关系,挑选出早上和下午的峰值。然而,如果我们看看预测点(22 小时和 23 小时)……灾难!我们曾经遇到过 [**龙格效应**](https://en.wikipedia.org/wiki/Runge%27s_phenomenon) **。**> 龙格现象发现,当我们使用高阶多项式时,函数的边缘可能会振荡到极值,这意味着具有多项式特征的模型并不总是会产生更好的值。如果我们看看我们的 x ⁰模型,我们可以看到,一旦它预测到什么,橙色线就会射向平流层。**这不好。它不仅不准确,还凸显出我们不知道这个模型会对看不见的数据做什么。如果我们想要部署这个模型,并让这个简单的模型变得几乎完全不可理解,这是一个巨大的风险。**那么我们如何用一个简单的模型来模拟这种非线性关系呢?**进入 GAM。**# GAM 的作品是怎么做的?## 从直线到样条曲线让我们暂时回到我们的线性回归。该方程由变量的**线性组合之和定义。每个变量被赋予一个权重β并相加。**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/54b4458ed2bbaff5802fdcb633815336.png)线性回归方程。图片作者。在 GAMs 中,我们放弃了可以使用变量的线性组合来计算我们的目标的假设,只是简单地说我们可以使用变量的非线性组合,用 *s、*表示“**平滑函数**”。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f83cd74133a06d7856528920ce967e1f.png)广义加性模型(GAM)方程。s 是一个光滑函数。作者图片但是这是什么呢?我们用下面的等式定义它,这里我们看到β回来了,它表示同样的东西;一个砝码。我们的另一个术语, *b* 是在*基础上的扩展*。基展开就是我们之前对多项式所做的,取 x⁰,x,x 等。还有其他的基函数,它们可以是多维的。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/23b73523dc02ac1c9ab9e152e7f018d4.png)光滑函数方程。图片作者。最棒的是,我们可以在方程中为每个变量设置权重和函数。这比我们的线性回归灵活得多,线性程度也低得多。这个**平滑函数**也被称为**样条。**不幸的是,样条真的很难定义,它们本质上是覆盖小范围的多项式函数。如果我们将样条可视化,它们会更容易理解。这里有一个 4 条样条线的例子,来自 GAM,我们将很快拟合!![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b3650173a28541c611dfd8c4b282f4fa.png)从自行车数据集中的 GAM 拟合中随机选择 4 条样条曲线。图片作者。如你所见,这些都是小范围的平滑函数。它们在外观上可以变化,甚至可以是线性的。让我们将 GAM 应用于我们的问题,并尝试理解样条函数,而不是通过更多的理论。> “定义这些样条函数的方法多得令人困惑。如果您有兴趣了解更多有关定义样条曲线的所有方法,我祝您旅途愉快”
> 
> - *Christoph Molnar,可解释机器学习*[点击这里查看克里斯托弗的书](https://christophm.github.io/interpretable-ml-book/extend-lm.html)# 将 gam 应用于自行车数据集让我们继续用一个游戏来解决前面的问题如你所见,GAM 在评估我们的函数方面做得更好。它遵循曲线,在我们预测的点上(22 小时和 23 小时),没有龙格现象的迹象。那么这是如何工作的呢?我们使用了 12 个**花键。**还记得我们上面看到的 4 条样条线吗?我们可以查看整个特征空间中的所有 12 个。这看起来不像与我们的曲线相关,这是因为每个样条函数**也有一个权重**。我们可以将函数输出乘以系数,以了解模型在 24 小时内的表现。现在这看起来更像我们的曲线!希望这是直观的原因。**曲线只是我们个人样条的总和**!不要忘记顶部绿色的截距术语。这是单个变量的问题,但是 GAM 可以很容易地应用于多个变量。我们甚至可以选择每个变量的样条**数量——我们不需要每个变量都有相同的数量。我们也可以手动编程变量之间的交互。**# GAM 理解第二部分关于游戏还有很多需要理解的地方,我将在以后的文章中讨论。这里我们只看了一个变量。GAM 的工作对很多人来说都很好,但是我们以后再看这个。以下是主要概念的概述## 摇摆波动就是我们的线有多波动。这是描述这个的正确术语!我们包含的样条越多,我们的线相对于我们的特征就越扭曲。这样做的问题是,它将开始过度适应我们的数据。我们需要找到正确数量的样条曲线,这样模型就可以学习问题,并很好地概括。## 防止过度拟合幸运的是,我们不仅仅需要猜测样条的数量。我们有另一个参数叫做*λ,λ。*这不利于我们的样条曲线。λ越高,我们的线就越不摆动,直到它变成一条直线。在下图中,我们可以看到使用大量的样条和低 *λ* 导致一个非常**摆动**线。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4e6995707c99eeba290a3cc70181c3d9.png)样条和λ值的比较。图片作者。一般的经验法则是使用大量的**样条**并使用**λ**(λ)值的交叉验证来找到最通用的模型。记住,我们可以为模型中的每个变量设置不同的**样条**和**λ**值。## 链接功能很像常规的广义线性模型,链接函数可以用于不同的分布;用于分类问题的 *Logit* 函数或用于对数转换的 *Log* 。## 分布我们还可以选择不同的分布,如泊松分布、二项式分布、正态分布。## 张量积我们可以在游戏中设计互动。这被称为张量积。这样我们就可以模拟变量之间的相互作用,而不是孤立地考虑每个变量。# 使用 PyGAM 实现线性 GAM根据我的研究,似乎 R 中的 [*mgcv* 包最适合 GAMs。但是,我更喜欢 Python 两个最好的选择是](https://cran.r-project.org/web/packages/mgcv/mgcv.pdf) [Statsmodels](https://www.statsmodels.org/stable/gam.html) 和 [PyGAM](https://pygam.readthedocs.io/en/latest/index.html) 。以下是如何使用 PyGAM 来适应 GAM。这是假设您的数据已经过清理和预处理,可以进行建模,并且您的数据已经拆分为训练数据集和测试数据集。

import numpy as np
import pandas as pdfrom pygam import GAM, LinearGAM, s, f, te# your training and test datasets should be split as X_train, X_test, y_train, y_testn_features = 1 # number of features used in the model
lams = np.logspace(-5,5,20) * n_features
splines = 12 # number of splines we will use# linear GAM for Regressiongam = LinearGAM(
s(0,n_splines=splines))
.gridsearch(
X_train.values,
y_train.values,
lam=lams)
gam.summary()print(gam.score(X_test,y_test))


PyGAM 有更多的深度,因为它提供了多种游戏类型。查看 PyGAM 文档,了解其他类型的 GAM(例如用于分类)和不同的可用地块类型。<https://pygam.readthedocs.io/en/latest/notebooks/tour_of_pygam.html>  # 结论这是一次短暂的 GAMs 之旅!希望你现在知道什么是**样条**,以及我们如何使用它们来建模**非线性数据**。因为我们可以理解我们的模型将如何对看不见的数据做出反应,我们必须明确地包括交互,游戏被认为是相对**可解释的**。> 当我们需要非线性数据的可解释模型时,gam 是最好的。在我的下一篇关于 GAMs 的文章中,我们将通过一个更复杂的分类问题的视角来看待波动、过度拟合、分布、连接函数和张量积。## 了解更多信息</5-project-ideas-91da0da17b31>  ## 将我的内容直接发送到您的收件箱!<https://adamsh.substack.com/p/coming-soon> # 广义优势估计:数学与代码> 原文:<https://towardsdatascience.com/generalized-advantage-estimate-maths-and-code-b5d5bd3ce737?source=collection_archive---------6----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/bbee9cec5e1a8d3095fbb4077fad1e99.png)由 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的 [Edge2Edge 媒体](https://unsplash.com/@edge2edgemedia?utm_source=medium&utm_medium=referral)拍摄在我的文章实现 [**阶段策略梯度(PPG)算法**](/phasic-policy-gradient-ppg-part-2-c93afeaf37d4) 中,我有一个关于广义优势估计(GAE)的问题,所以我想我应该在这里跟进一些额外的细节😊[**这里是原文**](https://arxiv.org/abs/1506.02438) 。我将更直观地描述这个理论,并解释如何用代码实现它。如果你想尝试这个和其他 RL 技术,请查看我的开源库, [**Pearl**](https://github.com/LondonNode/Pearl) 。总之,这种方法允许我们估计强化学习中的优势和价值函数,并且容易控制偏差方差权衡。让我们开始吧!# 设置场景我们正在尝试教一些代理解决一个环境(例如,一个游戏)。为了做到这一点,代理人必须了解其行动的预期结果。在这里,我们将正式方程,将给予代理这一信息。## 轨道当代理浏览环境状态时,它收集奖励,告诉它刚刚采取的行动是好是坏。随着时间的推移,一个代理人遇到的行动、状态和奖励的序列被称为轨迹,我们在这里用符号 **τ** 来定义它。## 返回在一个轨迹的终点,我们可以回头看,看到轨迹中每一步的未来回报的贴现总和,也称为**回报**。更正式地说,回报是这样定义的:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7769bdfa26b470bb8fde8aa3f3614ded.png)作者图片:轨迹的回归**γ** 术语引入的折扣是一个介于 0 和 1 之间的数字。我们想这么做有几个原因:1.  从数学上来说,奖励的无穷大可能不会收敛到一个有限值,并且很难用等式来处理。折扣因素对此有所帮助。
2.  更直观地说,未来的奖励不会带来直接的好处。我们更喜欢即时的满足感;其实我们在给股票和衍生品定价的时候也是这么做的!## 价值函数价值函数 **V** 定义为一个状态的预期收益:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1f5c8461be768cfaab04eecae3a80f7e.png)作者图片:价值函数代理应该偏好具有较高值的状态,因为这些状态具有与其相关联的较高的预期总轨迹回报。几乎每个强化学习算法都会用到这一点。## 优势函数优势函数 **A** ,是从状态中给定动作的期望回报中减去状态(值)的期望回报。更直观地说,它告诉我们所采取的行动与总体预期回报相比有多好或多差:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/aabdaae45e48d6d3e4d57ffd5ff87400.png)作者图片:优势功能为什么我们用这个,而不仅仅是在一个状态下给定一个动作的预期收益(第一项)?直观地说,该指标在蒙特卡洛运行中具有较低的方差,因为减去确定性值函数通常会导致较小的量值。# 偏差方差权衡首先,让我们开始一些定义:*   **偏差**:有偏差的估计量不能很好地代表/符合原始度量。从形式上讲,如果估计量的期望值等于原始度量,则估计量是无偏的。
*   **方差**:方差较大的估计量,其值的分布范围较大。理想情况下,无偏估计量应该具有较低的方差,以便始终如一地匹配输入的原始度量。在形式上,这是衡量相同的方差的任何随机变量的衡量。不幸的是,我们通常没有价值函数或优势函数的精确形式。让我们使用神经网络来模拟价值函数,因为这仅需要状态输入而不是状态动作输入。鉴于此,**我们如何用一个不完美的价值函数估计器来估计优势函数?**首先,注意:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/13f672f44fbcccf3df6eff4b67913f7e.png)作者图片也就是说,一个状态下给定一个动作的预期收益,等于动作状态对的回报(这里假设是确定性的)加上下一个状态的贴现预期收益。因此,优势可以估计为:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c6836d48aff7ba36699c1a5a70039724.png)作者图片:优势函数的时间差异(TD)估计注意,这个估计量高度依赖于价值函数估计量。如果这个有高偏差,那么 TD 估计也会有高偏差!![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/82cdbfb92c5348fcdf6b0f020a063c51.png)图片作者:如果价值函数估计有偏差,则 TD 估计有偏差理想情况下,我们希望尝试绕过这个问题。在强化学习设置中,我们通常在每次更新的环境中采取 **n** 个步骤。因此,延长额外时间步长的 TD 估计值相当容易:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f1894aa508c3cdc6aa17831e96050283.png)作者图片:超过 **n** 步的扩展优势评估这样做减少了偏差,因为我们增加了来自完全优势函数的不依赖于价值函数估计的项的比例,并且我们将第 n 个状态的价值估计的幅度缩放了小得多的数。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a6a730be883d7ab75b8dcad8408ec01c.png)作者图片:回报期望项与原始优势函数相匹配然而,这样做也有不利的一面。随着许多额外项的加入,新的估计量具有增加的方差。总之,扩展 TD 估计以包括更多的奖励步骤以增加方差为代价减少了估计量的偏差。我们可以在 1 和 n 之间选择任意一个数字,来放入扩展的优势估计, **A^{(i)}(s,a)。**问题是,我们如何挑选这个数字?# GAE 方程一个很好的解决方案是只取 1 和 n 之间的一个指数平均值作为扩展优势估计器的输入。让我们直接从纸上看最终的形式,其中 **δ_t** 是时间步长 **t** 的 TD 优势估计。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/77bf72fe53aad38509a4093bae34d586.png)[1]广义优势估计这里, **λ** 是指数权重折扣。重要的是,**这是控制偏差方差权衡的杠杆!**注意,如果我们将其设置为 0,那么我们将得到 TD 优势估计(高偏差、低方差),如果我们将其设置为 1,这相当于选择 **i = n** 作为扩展优势估计(低偏差、高方差)。# 密码GAE 在 Python 中的实现如下所示:是我的错觉还是事情出奇的简单?这就是指数平均的美妙之处!它可以容易地实现,并且在计算上是线性的😁诀窍是从末尾开始,然后往回算,这样我们就不会一遍又一遍地计算相同的量。让我们用一个 **n** 步进轨迹来更清楚地展示这一点:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/834687b3bd42a166d9e7d909e4a9eb7c.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/13aa03c986a1500091157c5c154100fa.png)作者图片因此:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/db5a7d67000f3051ad0eb281a6050396.png)作者图片此外,请注意此处添加了“完成”标志,表示一集是否已经结束(0 =完成,1 =未完成)。包括这一点很重要,这样我们在计算当前剧集中某一步的优势时就不会考虑未来剧集的奖励。唷!坚持到了最后🎉🎉如果您觉得这篇文章有用,请考虑:*   跟踪我🙌
*   [**订阅我的邮件通知**](https://medium.com/subscribe/@rohan.tangri) 永不错过上传📧
*   使用我的媒介 [**推荐链接**](https://medium.com/@rohan.tangri/membership) 直接支持我并获得无限量的优质文章🤗促销的方式,让我知道你对这个话题的想法和快乐学习!!# 参考[1]使用广义优势估计的高维连续控制,作者:约翰·舒尔曼、菲利普·莫里茨、谢尔盖·莱文、迈克尔·乔丹、彼得·阿比尔:[https://arxiv.org/abs/1506.02438](https://arxiv.org/abs/1506.02438)# 广义注意机制:大鸟的理论基础和一般变形金刚模型> 原文:<https://towardsdatascience.com/generalized-attention-mechanism-bigbirds-theoretical-foundation-and-general-transformers-models-9fb87bdac3b2?source=collection_archive---------11----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f8f8355a58a490ad1339a64f391fee7d.png)美国宇航局在 [Unsplash](https://unsplash.com/s/photos/network?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 拍摄的照片作为一个小背景, [**BigBird**](https://arxiv.org/abs/2007.14062) 是 [Google Research](https://research.google/pubs/pub49533/) 最近发布的一个模型,它可以处理比以前可能的更长的文本序列。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/fc8f4f3453dd6d9a7ffa755bf1fe4f3b.png)BigBird 在处理了一整天的长文本序列后([BigBird](https://www.flickr.com/photos/62424772@N08/11504478233)BY[J . Fei nberg](https://www.flickr.com/photos/62424772@N08)CC BY 2.0)以下是这种模式值得大肆宣传的几个原因。我喜欢这些属性甚至不是自然语言处理中出现的常见主题,但它显示了它的潜力:1.  正是[图灵完成](https://en.wikipedia.org/wiki/Turing_completeness)。
2.  它在基因组学研究方面取得了最先进的成果。
3.  它在使用变形金刚处理长文本序列方面击败了其他 SotA 模型,比如曾经主宰场景的 [Longformer](https://arxiv.org/abs/2004.05150) 。但是除了它的能力有多深远之外,这篇论文本身读起来非常有趣。作者深入研究了该模型的数学基础,以证明该设计的合理性,以及他们如何解释该模型的优越性能。在本文中没有得到足够讨论的一个概念是 ***广义注意机制*** 。## 变形金刚通常是如何解释的这个概念本身只不过是观看变形金刚模型的另一种方式。通常,当我们谈论变形金刚模型和它们的**注意力机制**时,它们被想象成这样:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7be317d6bb75521e50d49e76a1f06fdd.png)作者使用 [BertViz](https://github.com/jessevig/bertviz) 进行可视化变形金刚从标题为 [***注意*** *的论文开始,这就是你所需要的全部*](https://papers.nips.cc/paper/2017/file/3f5ee243547dee91fbd053c1c4a845aa-Paper.pdf) ,这可能是今天 NLP 中引用最多的一篇论文。中心思想是这样的: ***对一个句子中的一个标记的分析包括查看其他标记的整个集合*** *,*,除了对每个标记进行基于注意力的加权。你很难找到变形金刚模型的其他可视化形式。有一整套像 [**BertViz**](https://github.com/jessevig/bertviz) 这样的工具和库,可以让你像这样制作变形金刚模型的可视化。但是,如果我告诉你,这些可视化并没有公正的变形金刚的真实本性呢?这些流行的可视化方法忽略了关于注意力机制本质的核心属性。这篇论文建议我们,思考变形金刚如何处理序列的正确方式是把它看作 ***图形运算*** 。# 广义注意机制***广义注意机制*** 背后的思想是,我们应该把序列上的注意机制看作图形操作。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5a433bb3678092a6c0ca1228e7a80634.png)来自 Avinava Dubey 的谷歌人工智能博客 BigBird[***关注是你所需要的全部***](https://proceedings.neurips.cc/paper/2017/file/3f5ee243547dee91fbd053c1c4a845aa-Paper.pdf) 背后的中心思想是,模型在处理每个令牌的同时,关注序列中的每一个其他令牌。那么,如果我们把记号看作图上的节点,注意每一个其他的记号意味着该节点与图中的每一个其他节点相连。换句话说,传统的变形金刚模型可以另外表示为一个 ***全连通图*** 。事实上,它们是 ***加权的*** 全连通图,其中权重是我们大肆宣传的关注分数。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/008211165916e887d5c778a67c16f3d9.png)这篇[论文](https://www.researchgate.net/figure/a-Undirected-fully-connected-weighted-Graph-G-b-Adjacency-Matrix-of-G_fig1_320116922)中的加权全连通图示例。这种替代方案,*用图论的方法来观察变压器如何处理序列中的记号是非常强大的,因为我们可以直接应用数学家们已经开发了几个世纪的图论中的强大工具。**这是大鸟设计的核心指导思想。*# *全连通图有多痛苦**BigBird 是出于处理长文本序列的需要。如果你以前用过变形金刚模型,这可能是 NLP 中的一个明显的问题。您会直接知道即使模型有数十亿个参数,最多也只有 1024 个标记。**我对变形金刚形象化的另一个问题是:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7be317d6bb75521e50d49e76a1f06fdd.png)**作者使用 [BertViz](https://github.com/jessevig/bertviz) 进行可视化**或者这些:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3eb8bf89f566fc2fd033d0a8d68f4ad6.png)**出自原来的[伯特论文](https://arxiv.org/pdf/1810.04805.pdf)。**是 ***他们*** ***没有恰当地捕捉到变形金刚模型背后的*** 处理有多激烈。**一旦你把它们想成是完全连通的图,这就变得更加清楚了。**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/69d7e6695234223448f1f77c97ef6180.png)**[汤姆·鲁恩](https://upload.wikimedia.org/wikipedia/commons/d/dd/20-simplex_graph.png),公共领域,通过维基共享**这是一个只有 20 个节点的完整图!你能想象 1024 个节点的完整图形会是什么样子吗,更不用说 BigBird 能够处理 4000 多个令牌了?**上图中的每条边代表一个计算,上图中所有计算的集合只针对一层。*# *利用图论:图稀疏化**幸运的是,在计算机科学和数学的其他领域,这是一个古老的问题。BigBird 建议做的事情本质上是利用这些工具,当涉及到具有大量节点的图形时,我们看到这些工具正在其他领域中使用。*> *这种将自我关注视为完全连通图的观点允许我们利用现有的图论来帮助降低其复杂性。降低自我关注的二次复杂度的问题现在可以被看作是一个**图稀疏化问题**——来自 [BigBird 论文](https://arxiv.org/pdf/2007.14062.pdf)。**以下是对 BigBird 使用的方法的综合介绍:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/38074642074ad7baa269451e1663f65c.png)**来自 Avinava Dubey 的谷歌人工智能博客文章**下面的矩阵是**邻接矩阵**。它们是将图形数据结构表示为具有数值的矩阵的有用方式,其中每个位置的正值表示两个节点之间的连接。**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/20a5b798aa3ec392d981fe339aaddea8.png)**邻接矩阵的例子,来自 nl.wikipedia 的 [Yepke,](https://upload.wikimedia.org/wikipedia/commons/3/3b/AdjacencyMatrix.png) [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0) ,通过维基共享**我们现在知道 BigBird 的指导原则是**稀疏化变形金刚**模型的计算图,这样处理更长的序列是一个更现实的目标。**我们需要一个比原始全连通图简单得多的图的设计,它仍然保留了节点之间有意义的连接。**以下是设计此最佳图表的步骤。*## ***1。鄂尔多斯-雷尼模型:最简单的随机图****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/81d61ba8d5813eaae5501e5336af4129.png)**来自 [ResearchGate](https://www.researchgate.net/figure/Erdoes-Renyi-model-of-random-graph-evolution_fig10_313854183) 的一个帖子**这只是随机和独立地挑选连接节点的边的概念。如果问题是我们有太多的连接,那么这就是随机丢弃大多数连接的方法。**这种方法实际上比预期的更有效**,因为两个变得不连接的令牌仍然可能共享信号**,因为它们可能具有它们都连接到的其他节点。由于变压器需要多层处理,这些连接可以复合足够多的令牌,以充分地相互连接。*> *因此,**这样的随机图在光谱上接近完整图**,并且它的第二特征值(邻接矩阵的)离第一特征值相当远。这一特性导致图中随机游走的快速混合时间,这非正式地表明信息可以在任意一对节点之间快速流动——来自论文。*## *2.瓦特和斯特罗加兹模型:参照的局部性**一般来说,单词之间的接近度是自然语言处理中的一个重要因素。直观地说,一个给定标记的大部分信息都可以被它周围的人找到。**一个简单的随机图错过了这种结构,因为它固有地在整个图中产生相等的稀疏度——紧邻一个标记的单词被认为是数千个标记之外的单词的概率相等。**因此,解决方案是考虑一种“滑动窗口”方法:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cc0d4295ede556a291c79ab912cb7dc1.png)**来自[龙前纸业。](https://arxiv.org/pdf/2004.05150v2.pdf)**因为我们知道单词周围的记号在分析单词时肯定会很重要,**我们简单地保证对每个记号的 n 个最近的记号的全部关注。这实际上是以前在为长文档应用变形时提出的,尤其是在 [Longformer](https://arxiv.org/pdf/2004.05150v2.pdf) 中。****虽然这不是一个完美的类比,但我认为可以将其比作网络中的集线器:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/954959299a8db430d60f2c3dd9dd5f0a.png)**来自[马克西姆](https://commons.wikimedia.org/wiki/File:Scale-free_network_sample.png)、 [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0) 的本地枢纽示例,通过维基共享**通过这些窗口,我们围绕每个令牌创建了**注意力**集群。结合简单的随机图方法,这些注意力的**“本地中枢”**被随机连接到整个文档中的一些标记。这使我们既能实现图的稀疏化,又能在分析中保持一定的局部性。**然而,作者指出,简单的随机图和滑动窗口图的组合不足以让该模型显示 BERT 级性能。**毫不奇怪,这种方法很难赶上 BERT 的性能,因为稀疏图包含的分析量本质上比全连通图少。但下面的最后一个组件显然是核心组件,至少在经验上,它允许 BigBird 显示出类似于 BERT 的性能,尽管它很稀疏。*## *3.全局令牌**之前我们注意到:*> *…[**]两个未连接的节点** ]仍然可能共享信号,因为它们可能都连接到其他节点。…这些连接可以复合到足以使令牌彼此**充分连接**。*
> 
> *“因此,**这种随机图在光谱上接近完整图**……这非正式地表明信息可以在任何一对节点之间快速流动”**我们打了一个比方,滑动注意力窗口创造了局部注意力中心。**对于全局令牌,我们指定一个令牌列表,让**处理文档中的所有令牌**。虽然 BERT 被设计成每个令牌照顾其他令牌,但是 BigBird 被设计成只有少数指定数量的令牌这样做。**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e76ea07ae2909df4e85563e3439ee8f6.png)**完整的大鸟来自 [HuggingFace 的博客](https://huggingface.co/blog/big-bird)**这是有用的,有几个原因,其中一些作者没有明确指出:*1.  *全局记号(类似于 BERT 中的[CLS]记号)通常非常有用,因为虽然它们只是序列的另一个记号,但是它们本身能够表示完整的输入序列。如果没有全局标记,就很难生成一个表示整个文档的向量。*
2.  *虽然作者没有明确提到这一点,但我相信这是另一个非常重要的结果。关于未连接的令牌(由于随机图的构造)仍然通过跳过相互邻居来共享信号的想法, ***全局令牌保证这是真的*** 。在添加全局令牌之前,对彼此非常重要的两个令牌实际上可能是断开的,并且只能共享由于跳过太多节点而显著减弱的信号。**现在有了全局令牌,它们被保证最多相距两跳**,因为全局令牌被保证是图中的共同节点。**最后,下面是作者提供的最终图表,它很好地总结了这一点:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c843c1e75ffe88377d2fe4ca64e33552.png)**出自[大鸟论文](https://arxiv.org/pdf/2007.14062.pdf)。**单纯看 BigBird 注意力的最后一张图,即使有很多空连接,直观上也不会让我们觉得太在意它们——好像没有它们处理就完全没问题了。这有点像原始全连通图的信息最大化缩减。**但随着这种减少,BigBird 能够处理的序列远远超过以前的 1024 个限制,甚至达到 4096 个,而不会像完全连接的同行那样损失太多性能。**我想很多读者可能也会看最后一张图,并想知道他们如何能够在 GPU 中表示这样的计算图。这是一个完全不同的话题,作者利用了非常聪明的方法“阻断稀疏注意力”来做到这一点。这是另一个话题,一个彻底的解释(用代码!)可以在一篇 [Huggingface 的博文](https://huggingface.co/blog/big-bird)中找到。**感谢阅读!*# 火炬视觉目标检测的广义 IoU 损失> 原文:<https://towardsdatascience.com/generalized-iou-loss-for-object-detection-with-torchvision-9534029d1a89?source=collection_archive---------11----------------------->## 关于如何在 Torchvision 对象检测中使用 GIoU 自定义损失函数的教程![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d251b5df101cabb38a3e5ac33fc4fcd1.png)使用 GIoU 损失函数后目标检测的改进([来源](https://images.unsplash.com/photo-1598896130238-5606c05ec207?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80)在对象检测任务中,最常见的评估度量是 IoU,这促使我们在训练中最小化这样的度量,看看我们是否取得了一些进展。Hamid Rezatofighi 和他的同事表明,使用广义 IoU ( ***GIoU*** )损失函数优于使用其他标准损失函数的最先进的对象检测方法。我不想浪费你的时间解释什么是***IoU******GIoU***。如果你在这里,你可能对这些功能很熟悉。你可以在这里找到完整的描述。在[火炬视觉](https://github.com/pytorch/vision)物体检测模型中,RCNN 家族中的默认损失函数是[平滑 L1 损失函数](https://pytorch.org/docs/stable/generated/torch.nn.SmoothL1Loss.html)。模型中没有改变损失函数的选项,但是如果您对使用平滑 L1 损失不感兴趣,可以简单地定义您的自定义损失并将其替换为平滑损失。# GIoU 损失函数我们计划计算以下 GIoU:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2137b6912a7e726fe811eb494f7bda2f.png)IoU 和 GIoU(查看更多详情[此处](https://giou.stanford.edu/GIoU.pdf))Torchvision 提供了边界框的交集和并集计算,这使得计算 GIoU 变得非常容易。我们可以通过从`torchvision.ops.boxes`导入`_box_inter_union`来直接计算盒子的交集和并集。为了计算包围盒子的最小凸形的面积,首先我们找到 ***C:*** 的坐标![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b1d75d61b2c7b1917d9402e435323c29.png)然后,我们计算它的面积(下面代码的第 17 行)。**GIoU 损失为: *1- GIoU*** *。*物体检测的 GIoU 损失函数(类似于 [fvcore](https://github.com/facebookresearch/fvcore/blob/master/fvcore/nn/giou_loss.py) )# 火炬视觉中的自定义损失函数主 RCNN 框架在`[roi_heads.py](https://github.com/pytorch/vision/blob/main/torchvision/models/detection/roi_heads.py)`中完成,FastRCNN 和 MaskRCNN 损失函数位于此处。因此,要使用您的自定义损失函数,您需要从`roi_heads`导入它并用您的自定义函数替换它,正如我在下面代码的第 22 行中所做的:FastRCNN 的自定义损失函数# 摘要在这篇短文中,您可以找到使用 GIoU loss 函数通过 Torchvision 进行物体检测所需的全部内容。**参考文献:**[1] [并集上的广义交集:包围盒回归的度量和损失](https://giou.stanford.edu/GIoU.pdf)<https://sciencenotes.medium.com/membership>  杰瑞米·哈里斯,[拉胡尔·阿加瓦尔](https://medium.com/u/e8cce06956c9?source=post_page-----9534029d1a89--------------------------------),[大卫·麦克](https://medium.com/u/1d81a71197ab?source=post_page-----9534029d1a89--------------------------------),[库马尔·什里达尔](https://medium.com/u/c7ad13abfbb7?source=post_page-----9534029d1a89--------------------------------)# 用 GPBoost 实现 R 和 Python 中的广义线性混合效果模型> 原文:<https://towardsdatascience.com/generalized-linear-mixed-effects-models-in-r-and-python-with-gpboost-89297622820c?source=collection_archive---------5----------------------->## [思想和理论](https://towardsdatascience.com/tagged/thoughts-and-theory)## “lme4”和“statsmodels”的介绍和比较![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/43b7d84bfa787b318550085bb3554180.png)图 gpboost、lme4 和 stats 模型的比较:**估计时间和单水平随机效应模型的系数和方差参数的均方误差(MSE)** 对于**变化的样本数**[**GPBoost**](https://github.com/fabsig/GPBoost) **是一个最近发布的 C++软件库,它允许在 R 和 Python 中拟合广义线性混合效果模型**。本文展示了如何使用相应的 [R](https://github.com/fabsig/GPBoost/tree/master/R-package) 和 [Python](https://github.com/fabsig/GPBoost/tree/master/python-package) `**gpboost**`包来实现这一点。此外,我们对`lme4` R 包和`statsmodels` Python 包进行了比较。**在模拟实验中,我们发现** `**gpboost**` **比** `**lme4**` **R 包****快很多(有些情况下快 100 倍以上)。令人不安的是,** `**statsmodels**` **Python 包经常错误地估计模型。**# 简介:广义线性混合效应模型[广义线性混合效应模型(GLMMs)](https://en.wikipedia.org/wiki/Generalized_linear_mixed_model) 假设响应变量 *y* 遵循已知的参数分布 *p(y|mu)* ,并且该分布的参数 *mu* (通常是平均值)与所谓的固定效应 *Xb* 和随机效应 *Zu* 的总和相关:> y ~ p(y |μ)
> 
> mu = f( Xb + Zu)*   *y* 是响应变量(又名标签,因变量)
*   *Xb* 是固定效应, *X* 是具有预测变量(又名特征、协变量)的矩阵, *b* 是系数
*   *Zu* 是随机效应,其中 *u* 假设遵循多元正态分布,而 *Z* 是将 *u* 与样本相关联的矩阵
*   *f()* 是一个链接函数,确保 *mu = f( Xb + Zu )* 在适当的范围内(例如,对于二进制数据,平均值必须在 0 和 1 之间)GLMM 与广义线性模型(GLM)的区别在于随机效应的存在。例如,随机效果可以由具有潜在嵌套或交叉分组结构的分组(又名群集)随机效果组成。因此,[随机效应也可以被看作是一种建模高基数分类变量](https://arxiv.org/abs/2105.08966)的方法。此外,随机效应可以包括例如用于对空间数据建模的高斯过程。与仅使用固定效应相比,随机效应的优势在于,当例如组或类别的数量相对于样本大小较大时,可以更有效地估计模型。[线性混合效应模型(LMEs](https://en.wikipedia.org/wiki/Mixed_model) )是 GLMMs 的一个特例,其中 *p(y|mu)* 是高斯的, *f()* 仅仅是恒等式。# **使用 GPBoost 在 R 和 Python 中建模 glm ms**我们简要地展示了 R 和 Python `gpboost`包如何通过 GLMMs 用于推断和预测。更多细节,我们参考 [GitHub 页面](https://github.com/fabsig/GPBoost),特别是 [R](https://github.com/fabsig/GPBoost/blob/master/R-package/demo/generalized_linear_Gaussian_process_mixed_effects_models.R) 和 [Python](https://github.com/fabsig/GPBoost/blob/master/examples/python-guide/generalized_linear_Gaussian_process_mixed_effects_models.py) GLMM 的例子。## 装置CRAN 和 PyPI 上有`gpboost` R 和 Python 包,可以按如下方式安装**:****Python:****R:**## 模型估计由于可能性(应该最大化的数量)不能以封闭的形式写下来,因此 GLMMs 的估计是一项重要的任务。GPBoost(版本 0.6.3)的当前实现基于拉普拉斯近似。Python 和 R 中的模型估计可以如下进行:**Python**

gp_model = gpb.GPModel(group_data=group_data, likelihood="binary")
gp_model.fit(y=y, X=X)
gp_model.summary()


**R**

gp_model <- fitGPModel(group_data=group_data, likelihood="binary",
y=y, X=X)
summary(gp_model)


在哪里*   `group_data`是具有分类分组变量的矩阵或向量,指定随机效应结构。如果有多个(交叉或嵌套)随机效应,相应的分组变量应该在`group_data`的列中
*   `y`是一个带有响应变量数据的向量
*   `X`是一个具有固定效应的矩阵协变量数据
*   `likelihood`表示响应变量的分布(例如,似然性=“二元”表示具有概率单位链接函数的伯努利分布)估计后,`summary()`函数显示随机效应和固定效应系数 *b* 的估计方差和协方差参数。## 固定效应系数的近似 p 值获取 GLMMs 中固定效应系数的 p 值是一项有些模糊的工作。由于不可能首先精确地计算出可能性,人们不得不依赖于多重渐近论证。即,p 值可以是(非常)近似的,应持保留态度。然而,由于`lme4`和`statsmodels`包允许计算近似标准偏差和 p 值,我们还展示了如何使用`gpboost`依靠与`lme4`相同的方法来实现这一点。简而言之,必须启用`"std_dev": True` / `std_dev=TRUE`,以在拟合模型时计算近似标准差,然后使用如下所示的近似 Wald 测试。**Python**

gp_model = gpb.GPModel(group_data=group, likelihood="binary")
gp_model.fit(y=y, X=X, params={“std_dev”: True})
coefs = gp_model.get_coef()
z_values = coefs[0] / coefs[1]
p_values = 2 * stats.norm.cdf(-np.abs(z_values))
print(p_values) # show p-values


**R**

gp_model <- fitGPModel(group_data=group_data, likelihood="binary",
y=y, X=X, params=list(std_dev=TRUE))
coefs <- gp_model$get_coef()
z_values <- coefs[1,] / coefs[2,]
p_values <- 2 * exp(pnorm(-abs(z_values), log.p=TRUE))
coefs_summary <- rbind(coefs, z_values, p_values)
print(signif(coefs_summary, digits=4)) # show p-values


## 预言;预测;预告可以通过调用如下所示的`predict()`函数来获得预测。**Python**

pred = gp_model.predict(X_pred=X_test, group_data_pred=group_test,
predict_var=True, predict_response=False)
print(pred['mu']) # predicted latent mean
print(pred['var']) # predicted latent variance


**R**

pred <- predict(gp_model, X_pred=X_test,
group_data_pred=group_test,
predict_var=TRUE, predict_response=FALSE)
pred\(mu # predicted latent mean pred\)var # predicted latent variance


在哪里*   `group_data_pred`是带有分类分组变量的矩阵或向量,用于进行预测
*   `X_pred`是对其进行预测的具有固定效应协变量数据的矩阵
*   `predict_var`(布尔型)表示除平均值外,是否还应计算预测方差
*   `predict_response`(布尔型)表示是否应预测响应 *y* 或潜在 *Xb + Zu* 。即随机效应部分也被预测。如果`group_data_pred`包含新的、未观察到的类别,相应的随机效应预测将为 0。# 与`lme4`和`statsmodels`的对比下面,我们做一个模拟研究来比较`gpboost`(版本 0.6.3)与`lme4`(版本 1.1–27)和`statsmodels`(版本 0.12.2)。重现完整模拟研究的代码可在[这里](https://github.com/fabsig/Comparison_GLMM_Packages)找到。我们对所有包都使用默认选项。特别是,所有软件包都使用拉普拉斯近似来近似(边际)似然性。**我们评估了计算时间和方差参数的准确性,以及根据均方根误差(RMSE)测量的固定效应系数估计值。**关于后者,我们预计只会看到微小的差异,因为理论上,所有软件包都依赖于相同的统计方法,只是在具体的软件实现上有所不同。## 模拟设置作为基线设置,我们使用以下模型来模拟数据:1.  n=1000 个样本
2.  每组 10 个样本(即 100 个不同的组)
3.  10 个固定效应协变量加上一个截距项
4.  单水平分组随机效应模型
5.  具有概率单位连接函数的二元伯努利似然当改变这些选择中的每一个而保持所有其他选择不变时,我们煽动结果如何变化。具体来说,我们如下改变这些选择:(1 .)样本数:100,200,500,1000,2000,(2。)组数:2,5,10,20,50,100,200,500,(3。)协变量个数:1,2,5,10,20,(4。)嵌套和交叉随机效应模型,以及(5。)泊松概率而不是二进制概率。方差 1 用于随机效应。协变量 *X* 从均值为 0 的正态分布中取样,选择方差,使固定效应和随机效应之间的信噪比为 1,除截距为 0 外,真实回归系数均为 1。对于上述模型选择的每个组合,我们模拟 100 次数据,并使用三个不同的软件包估计相应的模型。参见[此处](https://github.com/fabsig/Comparison_GLMM_Packages)了解模拟研究的更多细节。所有计算都在一台配备 2.9 GHz 四核处理器的笔记本电脑上运行。## 结果结果用下面的五个数字表示。注意,我们在对数标度上绘制结果,因为例如`lme4`和`gpboost`之间的计算时间差异非常大。我们观察到以下发现。首先,`statsmodels`给出了 RMSEs 非常大的参数估计,即非常不准确的估计。这是令人不安的,因为从理论上讲,所有三个软件包应该做“同样的事情”。此外,`gpboost`比`lme4`快得多,随机效应的维度越高,固定效应协变量的数量越多,差异就越大。例如,对于具有 100 组、1000 个样本和 20 个协变量的二元单级随机效应模型,`gpboost`平均比`lme4`快大约 600 倍。正如所料,`gpboost`和`lme4`具有几乎相同的 RMSEs,因为两个包使用相同的方法。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/43b7d84bfa787b318550085bb3554180.png)**不同数量的样本 n**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/bb9dc154b0edf499e9f33f7dfe104304.png)**改变组数**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/03f952679ef3bcafd5c9eeb5bd456a4c.png)**改变协变量的数量**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d79cb315b24c2bd73ecd8513f9ca0c60.png)**不同的随机效果模型**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/85863318ee320f6354dd286e4b5708b0.png)**泊松可能性和样本数量的变化***注意:* `*gpboost*` *对于可以并行化的操作,使用 C++中的 OpenMP 并行化。但是主要的计算瓶颈是 Cholesky 分解的计算,并且该操作不能并行化。即* `*lme4*` *和* `*gpboost*` *计算时间的巨大差异不是并行化*的结果。# **结论**[GPBoost](https://github.com/fabsig/GPBoost) 是一个最近发布的 C++软件库,它允许在 R 和 Python 中拟合广义线性混合效果模型。如上图所示,`gpboost`比`lme4` R 包快很多。令人不安的是,`statsmodels` Python 包经常导致非常不准确的估计。除了本文中考虑的分组随机效应,GPBoost 还允许对高斯过程建模,例如空间或时间随机效应,以及组合的分组随机效应和高斯过程模型。此外,GPBoost 支持随机系数,例如随机斜率或空间变化系数。最后,除了 LMMs 和 GLMMs,GPBoost 还允许学习非线性模型,而无需使用[树提升](https://en.wikipedia.org/wiki/Gradient_boosting)对固定效果采取任何函数形式;详见这两篇关于将树提升与[分组随机效果](/tree-boosted-mixed-effects-models-4df610b624cb)和[高斯过程](/tree-boosting-for-spatial-data-789145d6d97d)或 [Sigrist (2020)](https://arxiv.org/abs/2004.02653) 和 [Sigrist (2021)](https://arxiv.org/abs/2105.08966) 结合的博文。# GLMs 第一部分:严格的数学公式> 原文:<https://towardsdatascience.com/generalized-linear-models-a-rigorous-mathematical-formulation-58ac2ec7d9ea?source=collection_archive---------12----------------------->## 用标准和非标准形式的导数统一 GLMs 理论的直觉![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f6521557020a967269e966d1173b6c08.png)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的 [ThisisEngineering RAEng](https://unsplash.com/@thisisengineering?utm_source=medium&utm_medium=referral)# 1:背景和动机广义线性模型(GLMs)在包括统计学、数据科学、机器学习和其他计算科学在内的领域中起着关键作用。这类模型是对某些响应变量类型的普通线性回归的推广,具有非正态分布的误差分布模型。让我们回忆一下普通的线性回归:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4dd352a4734e75ff3509b03f4777943f.png)作者图片*(对于线性回归的彻底推导,具体来说就是普通最小二乘法和 BLUE(最佳线性无偏估计量),* [*请参见我之前关于这个主题的文章*](/ols-linear-regression-gauss-markov-blue-and-understanding-the-math-453d7cc630a5) *。)*但是如果我们的随机变量 ***Y*** 不是正态分布呢?另外,如果给定******Y***X***的条件分布不支持整个实值线呢?或许 ***Y*** 是泊松分布而***E【Y | X】***只在正实线上有支撑?又或许 ***Y*** 是伯努利分布而***E【Y | X】***只有支集[0,1】?我们仍然有兴趣构建一个“线性模型”作为 ***X*** 和β的函数,但是用条件分布 ***Y*** 的均值给定*,即***E【Y | X】***,无偏估计并有界在适当的支持范围内。**在统计建模技术的发展历史中,开发了不同的方法来处理具有不同条件分布的线性模型 ***Y*** 给定 ***X*** 。其中包括:**   *伯努利或二项分布的逻辑回归 ***Y****
*   *泊松回归为泊松分布 ***Y****
*   *指数回归为指数分布 ***Y*****1972 年,统计学家约翰·内尔德和罗伯特·威德伯恩证明了上述线性建模技术可以统一到一个模型家族中。提到的分布,以及其他几个分布,都可以被参数化为属于**指数分布族**。结合线性预测器和有效的链接函数(我们将在本文中介绍),我们将这一系列模型称为**广义线性模型**。通过将这些建模技术统一到单个系列中,我们可以将这些看似不同的模型视为解决相同“味道”的问题。从计算的角度来看,这些技术在 GLM 理论下的统一有着重要的意义,尤其是在 20 世纪 70 年代,当时科学计算还处于起步阶段。**这篇文章以规范和非规范的形式提供了普通 GLMs 的一个彻底的数学概述(有证明)。在下一篇文章中,我们将全面回顾为使 GLMs“适合”数据而开发的迭代数值程序*(牛顿-拉夫森法、费希尔评分法、迭代加权最小二乘法和梯度下降法)*,并进一步展示为什么将这些不同的建模技术统一到一个共同的问题类别中是如此方便。**这篇文章的目录如下:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7e8adde860e1898e7618282f5a3be423.png)**作者图片*# *2: GLM 概述*## *2.1:GLMs 的三个模型组件**所有 GLMs 都有三个主要组成部分:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/88c9757fd928abf9636c267323583eab.png)**作者图片*## *2.2:规范和非规范形式**现在,让我们以规范和非规范的形式,检查指数离差分布族的概率密度函数(PDF)的参数化:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4c3cca4515a860a4e03bd19731d431be.png)**作者图片*## *2.3:审查费希尔信息**让我们回忆一下 Fisher 信息的推导,这对理解规范 GLMs 的期望值和方差 ***Y*** 很重要**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4cbd2f508466e6121330bf89068759a9.png)**作者图片**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e52409393762a7645abf1ab3c5dfb2d6.png)**作者图片**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9414493fe0ebd6a7af609d0e89250891.png)**作者图片*## *2.4:规范 GLMs 的期望值和方差**使用我们在第 *2.3 节*中对得分函数的期望值和 Fisher 信息的推导,我们可以推导出规范 GLMs 的期望值和方差:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e6bff776ed09dc926a15c8caaf13af52.png)**作者图片**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/88a86340631ca13850367c4347ff869f.png)**作者图片*# *3:范例规范 GLMs**使用第 *2* 节中的推导,我们可以开始证明某些常见的回归建模技术都可以统一为规范的 GLMs。*## *3.1:线性回归**对于线性回归,我们假设结果*是正态分布的。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1a59eec26b68751984bbb4660b55607c.png)****作者图片****我们来推导这样一个随机变量 ***Y*** 的期望值和方差:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0c64b5cef4bf85fed530e9487290a04b.png)****作者图片****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/dd015c78f01d5b3cfe029cea8748b11b.png)****作者图片****让我们定义链接函数,并展示如何将问题参数化为非规范 GLM:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/395767a74c0a3b5f76caba3b8f6c874b.png)****作者图片****…并展示如何将其进一步简化为标准形式:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5e4b4a8d3a1a64be662f75978ed90498.png)****作者图片**## **3.2:逻辑回归****对于逻辑回归,我们假设结果 ***Y*** 是二项分布。注意,伯努利分布是二项式的一个特例。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0ad9fec40f050072e4f17bef82e68952.png)****作者图片****我们来推导这样一个随机变量**的期望值和方差 *Y*** :****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a5784de533373f2ed7c8b96c711c4a34.png)****作者图片****让我们定义链接函数,并展示如何将问题参数化为非规范 GLM:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/fb183955f8fec319df357decf1d431e3.png)****作者图片****…并展示如何将其进一步简化为标准形式:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5aa6b001b5c85c2aa790acc9f2516297.png)****作者图片****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5aff59bc1a4838d235c3962e044fc2ba.png)****作者图片**## **3.3:泊松回归****对于泊松回归,我们假设结果 ***Y*** 是泊松分布的。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2f96a9cfd89485844e702ae6e2b9b829.png)****作者图片****我们来推导这样一个随机变量 ***Y*** 的期望值和方差:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1513404d6aa7c15c28def54ccb35a438.png)****作者图片****让我们定义链接函数,并展示如何将问题参数化为非规范 GLM:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/08543d932f9ffa5554b7ac2108e7a6cf.png)****作者图片****…并展示如何将其进一步简化为标准形式:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/204906118f3122d17cdfe61997c06d8d.png)****作者图片**## **3.4:负二项式回归****对于负二项回归,我们假设结果 ***Y*** 是负二项分布。我们假设参数 *k* 已知。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/969db3457062736347cacad2994cf7d5.png)****作者图片****我们来推导这样一个随机变量 ***Y*** 的期望值和方差:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4dad3e5968ca31d8e070fab0962cd720.png)****作者图片****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/58e168dd8f91536faec69eed3ee694ba.png)****作者图片****让我们定义链接函数,并展示如何将问题参数化为非规范 GLM:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/dcc5714a31c476192925d724b3f55678.png)****作者图片****…并展示如何将其进一步简化为标准形式:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a9e3c49192d56cd1b683e7f448a45146.png)****作者图片****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a40b88f9b707dfa99c54ec5e07d76cb1.png)****作者图片**## **3.5:伽玛回归****对于伽玛回归,我们假设结果 ***Y*** 是伽玛分布的。我们还假设参数*α*是已知的。还要注意,指数分布、卡方分布和厄兰分布都是伽玛分布的特例。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e945580351d82c073046039f072f5800.png)****作者图片****我们来推导这样一个随机变量 ***Y*** 的期望值和方差:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/023b124149e5b9a18c049fab78878ad0.png)****作者图片****让我们定义链接函数,并展示如何将问题参数化为非规范 GLM:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/eae71506836da4942c080e14553c14ab.png)****作者图片****…并展示如何将其进一步简化为标准形式:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/67e23982395a1f963118857702e45705.png)****作者图片****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/225b4d18d3e48c033ea97e6955bd59f7.png)****作者图片**# **4:示例非规范 GLMs****我们将研究 Probit 回归,这是一种广泛使用的回归模型,是一种 GLM,但不能以规范形式参数化。**## **4.1:概率单位回归****类似于逻辑回归,对于概率单位回归,我们假设结果 ***Y*** 为二项分布:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/daa58a2f0eeb022e70f39a58221424f1.png)****作者图片****然而,概率单位回归利用了与逻辑回归不同的链接函数。概率单位回归没有使用对数优势关联函数,而是将标准正态累积分布函数(CDF)指定为关联函数。****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d5137c41ef918f36ed7fb3bf6d6d9f32.png)****作者图片****概率单位回归不能以标准形式参数化的事实对于选择用于恢复模型参数的经验估计的迭代数值拟合过程(即牛顿-拉夫森对费希尔评分)具有重要意义。在以后的文章中,我们将全面介绍 GLMs 的迭代数值拟合过程。**# **5:总结和结论****在这篇文章中,我们提供了常见的规范和非规范 GLMs 的严格数学概述。有关简要总结,请参见下表:****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f3f18c7a3e074acd44df16a00971d802.png)****作者图片****在未来的文章中,我们将涵盖 GLMs 的迭代数值拟合过程,以及通过多级递归 GLM 模型的镜头对神经网络进行严格的数学推导。****希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在 [**LinkedIn**](http://www.linkedin.com/in/andrew-rothman-49739630) 上与我联系,并在 Medium 上 [**关注我的更新!**](https://anr248.medium.com/)**# 广义线性模型解释清楚> 原文:<https://towardsdatascience.com/generalized-linear-models-clearly-explained-5c51993e41a4?source=collection_archive---------8----------------------->## [实践教程](https://towardsdatascience.com/tagged/hands-on-tutorials)## 是什么造就了 GML·GML?![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/45109a8da70edb5b734cc807ac41a4fd.png)GLMs(作者图片)广义线性模型是一组具有一些共同属性的模型。这些共同的属性是:1.  给定输入 x,响应变量(即标签)的分布是指数分布族的一员。
2.  指数族分布的自然参数是θ(即模型参数)和输入数据的线性组合。
3.  在预测时,给定 x 的模型输出是该 x 的分布的期望值。如果一个模型具有这三个特征,它就是广义线性模型。在深入研究之前,本文假设您知道什么是线性回归和逻辑回归。现在,来看看这三个特征的含义。## I .给定 x 的响应变量的分布是指数分布族的一员。当进行线性回归或逻辑回归时,我们假设响应变量的分布属于一个指数族。这意味着给定一组特征(x),结果是某个值(y)。该值(y)的概率遵循指数族分布。在线性回归的情况下,我们假设给定 x 的 y 的分布是具有一些均值μ和方差σ的高斯分布。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/abc7602194d6fbc04b1a0f789f5b1367.png)在线性回归中,响应变量 y 的分布是正态分布正如我们马上会看到的,高斯分布是指数分布族的一部分。如需进一步阅读,请查看我关于线性回归的[概率解释](/probabilistic-interpretation-of-linear-regression-clearly-explained-d3b9ba26823b)的文章。</probabilistic-interpretation-of-linear-regression-clearly-explained-d3b9ba26823b>  **什么是指数分布族?**如果分布的概率密度函数(PDF)可以写成以下形式,则该分布属于指数族:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/feeec12a50cf003d321ad2b6dd817d11.png)PDF 集成到 1。在上面的 PDF 方程中,eta (η)被称为分布的自然参数。高斯(或正态)分布属于指数族。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/13f3cdbdbef687a2b8b1eaf1fa42dbf6.png)高斯分布(图片来自[维基百科](https://en.wikipedia.org/wiki/Normal_distribution#/media/File:Standard_deviation_diagram.svg))方差为 1 的高斯分布的 PDF 为:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9c38495ef5c9a1f2fb53f819a5e66ca9.png)方差为 1 的高斯分布希腊字母μ是分布的平均值。这里,μ称为分布的**正则参数**。我们将在下面看到平均值μ是如何与自然参数η相联系的。从上面的等式,经过一些代数排列,我们得到:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d53d09fdc304aa7531beb88cb1cd3cb8.png)因此,高斯分布具有指数族所需的形式。对于高斯分布,正则参数μ等于自然参数η。伯努利分布也属于指数族。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2e8cbffe4743cc9602fe6a91b0e3e87f.png)伯努利分布(图片来自[维基百科](https://en.wikipedia.org/wiki/Bernoulli_distribution)伯努利分布的 PDF 为:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8e76ab85c1d2f338d10723c759d51688.png)这里,正则参数φ(φ)是 y 为 1 的概率。我们现在需要把这个 PDF 写成指数族的形式:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ecc34f0ae82beb4a0608d5f376fce7d0.png)对于伯努利分布,自然参数 eta 就是所谓的“对数优势”。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ceeb24164ab3d5283a1db7ff8fc36f9c.png)规范参数和自然参数之间的联系自然参数可以表示为正则参数的函数。这个函数称为规范链接函数。类似地,正则参数可以表示为自然参数的函数。这个函数称为规范响应函数。我们稍后将看到自然参数和规范参数在线性和逻辑回归中的作用。现在,看第二个属性。## 二。指数族分布的自然参数是θ和输入数据的线性组合这条线基本上意味着 eta 可以表示为θ乘以输入数据。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/24317151ceddeb4e2126b2f3e2968021.png)当进行线性或逻辑回归时,我们正在训练一个模型,以找到给定一组数据的“最佳”θ。这意味着,为了使 GLM 成为一种有用的学习算法,我们希望输入数据和该数据结果分布的自然参数之间存在线性关系。## 三。在预测时,给定 x 的模型输出是该 x 的分布的期望值当进行线性或逻辑回归时,我们训练一个模型来预测给定数据的结果。在线性回归的情况下,我们训练一个模型来预测给定 x 的高斯分布的平均值。高斯分布的平均值是高斯分布的期望值。因此,对于给定的 x,模型的输出是该 x 的分布的期望值。在逻辑回归的情况下,数据点 x 的预期结果是一个概率。这个概率就是伯努利分布的期望值。**我们可以用自然参数来求一个分布的期望值。**在线性回归的情况下:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5ca60d51ca6b23ee05b922c337ec4b97.png)线性回归模型在逻辑回归的情况下:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/65f0e9ae28c77e060aee53a4e1df5e06.png)逻辑回归模型广义线性模型就是具有上述 3 个属性的模型。“线性”部分来自于自然参数(η)是模型参数(θ)和输入数据的线性组合。## 为什么 GLM 有用在指数分布的家庭中有额外的好处。1.  损失函数是凸的。换句话说,有一个全局最小值(而不是几个局部最小值)。因此,梯度下降将收敛到全局最小值。
2.  所有 glm 使用相同的公式来更新梯度下降中的θ。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b637249059785b26b74056b2c2e24a2a.png)所有 glm 的梯度下降规则只要插上右边的 h(x)就可以做梯度下降了。我们前面已经看到,h(x)是自然参数的函数,自然参数是θ乘以 x。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b68d10309b34da1fadaca7b4423080d6.png)GLM 在其核心# 通过 3 个简单的步骤生成一个独立的可运行 JAR 文件(没有 Eclipse IDE、CMD/Shell 终端命令)> 原文:<https://towardsdatascience.com/generate-a-standalone-runnable-jar-file-in-3-simple-steps-no-eclipse-ide-cmd-shell-terminal-cf87b6cf0e20?source=collection_archive---------13----------------------->## 便携式 Java 应用程序和特定数据提取工具的理想选择作为我上一篇关于用 Java 从 Excel 和 Outlook 文件中提取数据的文章[的后续,我分享了我在工作场所实施 Java](/extracting-data-from-excel-and-outlook-files-with-java-7979eb64edff) [内部数据提取工具](https://github.com/incubated-geek-cc/data-extraction-with-Java)时所面临的情景约束,其中❝ **40%的用户无法打开他们的 Windows CMD/Shell 终端/PowerShell 终端** ❞,因此发现用以下命令运行任何 Java 应用程序都是一个挑战:

java -jar


由于使应用程序尽可能容易执行是至关重要的(理想情况下只需双击鼠标🖱️),我想我应该分享一种从 JAR 文件生成 runnable JAR 的简单方法。这种方法既不依赖于 [Eclipse IDE](https://www.codejava.net/coding/how-to-create-executable-jar-file-with-resources-and-dependencies-using-maven-in-eclipse) 的导出功能,也不需要包装实用程序,如 [Launch-4j](http://launch4j.sourceforge.net/) 。*请注意,本文假设您的 Java 应用程序是用 GUI 构建的,并且有要打包的外部 JAR 库。*# 简单来说,JAR 文件和可运行 JAR 之间的区别在于,JAR 文件是一个需要命令行才能运行的 Java 应用程序,而可运行 JAR 文件可以通过双击直接执行。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6eec4eb0daa1b7c41db336b63d4a0cc0.png)[达里奥·门德斯](https://unsplash.com/@dariomen?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片对于初学者来说,注意 JAR 文件本质上是另一种类型的[归档文件格式(其他更广为人知的归档文件格式有 Zip、7z、Rar 等)是很有用的。)](https://www.sysinfotools.com/blog/different-types-archive-files-format/)。考虑到这一点,在我创建的一个简单的基于 UI 的应用程序(可以在我的 [GitHub](https://github.com/incubated-geek-cc/Runnable-JAR-Generator) 上找到)中,实现了下面的 Java 代码片段:作者代码片段|一个实用函数,用于将 JAR 文件中的目录、子目录和文件提取到外部文件夹中作者代码片段|将应用程序 JAR 和外部 JAR 依赖项中的内容提取到一个文件夹中,并配置清单。MF 通过指定可运行 JAR 输出的目标入口点,即应用程序的主类。**注:**完整的源代码可以在[这里](https://github.com/incubated-geek-cc/Runnable-JAR-Generator/tree/main/src/executablejargenerator)找到。请随意使用它,调整它/改进它以供您自己使用,☺# **最后,输出可运行 JAR 的 3 个步骤如下:**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ec6c2dea06dbac9ca9daafc9ede7c19f.png)作者图片|在[应用程序上运行的 3 个步骤的图示](https://github.com/incubated-geek-cc/Runnable-JAR-Generator/blob/main/RunnableJARGenerator.jar) | **(1)** 输入 JAR 文件(通常通过 NetBeans IDE 等其他方式输出和构建); **(2)** 正确指定主类(极其重要!); **(3)** 选择所有外部 JAR 库,这些库将被打包为最终输出可运行 JAR 中的依赖项此后,*“创建可运行 JAR>>”*被选中,**请注意,这可能需要几分钟的时间(取决于您的应用程序的大小和您上传的外部 JAR 依赖项的数量)**。最后,当输入被成功处理以生成所需的 runnable JAR 时,用户将得到通知:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/80919bbbfb90b693ec40030af7645784.png)Image by Author | Runnable JAR 已经根据用户的输入成功生成。选择❛Ok❜后,应自动显示包含最终输出的文件夹。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/69fc2cb90b8f4aa2e2ad2cb1166e3cec.png)作者图片|应用程序在标题为“extracted _*<timestamp>*”的文件夹中输出可运行的 JAR 文件。要测试 JAR 是否正确生成,继续双击,您应该能够看到您的应用程序按预期运行。仅供参考:用于演示上述内容的示例文件位于[演示文件夹](https://github.com/incubated-geek-cc/Runnable-JAR-Generator/tree/main/demo),而示例输出位于[extracted _ 19 _ Aug _ 2021 _ 1118am](https://github.com/incubated-geek-cc/Runnable-JAR-Generator/tree/main/extracted_19_Aug_2021_1118AM)。# 这就对了!没有”。jar …”命令或包装类/库需要将所有依赖项与应用程序生成的类打包在一起。只需提取、合并和更新清单。MF 文件,就是这样!# 非常感谢你的阅读,希望有人觉得这有用!❤<https://geek-cc.medium.com/membership> # 用 Python 从照片生成铅笔草图> 原文:<https://towardsdatascience.com/generate-pencil-sketch-from-photo-in-python-7c56802d8acb?source=collection_archive---------2----------------------->## 使用 OpenCV 的图像处理教程,带代码## 导入库[*OpenCV*](https://docs.opencv.org/master/index.html) 是项目需要的唯一库。
我们也将使用 [*matplotlib*](https://matplotlib.org/) 库进行一些可视化,这将在后面中[讨论。](#8970)

import cv2
import matplotlib.pyplot as plt


## 阅读照片以下命令可用于使用 OpenCV 读取图像。

img=cv2.imread("photo.jpg")


该命令读取当前文件夹中的文件*photo.jpg*,并在内存中存储为 *img* 。## 使用 OpenCV 显示图像使用 OpenCV 显示图像不是很直接。以下命令可用于显示照片。

cv2.imshow(‘original image’,img)
cv2.waitKey(0)
cv2.destroyAllWindows()


执行此命令时,下面的照片将在一个新窗口中打开,标题为“原始图像”![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6e99ddf1ac7c385c7ff959f191f72990.png)[拉明卡](https://unsplash.com/@raaminka?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍照# 使用 Matplotlib 显示当每次必须显示图像时打开新窗口,并且为了进一步执行代码必须删除新窗口时,这不是很方便。为了避免这些麻烦,我们可以使用 *matplotlib* 库的 *pyplot* 模块来显示 *Jupyter* 笔记本本身中的图像。以下命令可用于使用 matplotlib 显示 cv2 图像。

plt.imshow(img)
plt.axis(False)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/204560865362420409c44c07e6303850.png)Matplotlib 的输出## Matplotlib 与 OpenCV我们可以观察到使用 matplotlib 显示的图像与原始图像不一致。这是因为 OpenCV 使用 BGR 配色方案,而 matplotlib 使用 RGB 配色方案。我们可以使用以下任何一种方法将 BGR 图像转换成 RGB。## 将 BGR 转换为 RGB:方法 1

plt.imshow(img[:,:,::-1])
plt.axis(False)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a0cb49d1475282e70f21171aea047ad4.png)matplotlib 的输出## 将 BGR 转换为 RGB:方法 1使用 *OpenCV* 的 *cvtColor* 方法。

RGB_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(RGB_img)
plt.axis(False)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a0cb49d1475282e70f21171aea047ad4.png)matplotlib 的输出# 将图像转换为铅笔草图将照片转换为铅笔草图包括以下步骤:## 步骤 1:转换为灰色图像使用 OpenCV 的 cvtColor 函数。

grey_img=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)


## 步骤 2:反转图像可以通过以下两种方法之一反转图像

invert_img=cv2.bitwise_not(grey_img)

invert_img=255-grey_img


## 第三步:模糊图像对图像应用*高斯模糊*。函数的第二个参数是内核大小,如果应该是一对奇数。
内核越大,图像越模糊,会失去其细微的特征。
为了创建草图,我们只需要图像中的突出特征(对比边缘)。
对于小图像,*内核大小*(3,3),(5,5)等。就足够了,而对于较大的图像,较小的内核大小不会产生任何影响。
可以通过试错法选择合适的内核大小。

blur_img=cv2.GaussianBlur(invert_img, (111,111),0)


## 步骤 4:反转模糊图像重复步骤 2

invblur_img=cv2.bitwise_not(blur_img)

invblur_img=255-blur_img


## 第五步:素描可以通过在灰度图像和反模糊图像之间执行逐位分割来获得草图。

sketch_img=cv2.divide(grey_img,invblur_img, scale=256.0)


详细解释逐位划分超出了本文的范围。
你可以在这里获得[更多关于图像算法的信息。](http://Refer this page for more information on image arithmetic.)## 步骤 6:保存草图

cv2.imwrite(‘sketch.png’, sketch_img)


## 步骤 7:显示草图

cv2.imshow(‘sketch image’,sketch_img)
cv2.waitKey(0)
cv2.destroyAllWindows()


## 原始图像与草图我们可以把原图和草图并排展示出来进行对比。

plt.figure(figsize=(14,8))plt.subplot(1,2,1)
plt.title('Original image', size=18)
plt.imshow(RGB_img)
plt.axis('off')plt.subplot(1,2,2)
plt.title('Sketch', size=18)
rgb_sketch=cv2.cvtColor(sketch_img, cv2.COLOR_BGR2RGB)
plt.imshow(rgb_sketch)
plt.axis('off')
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4280ae3931240165ec421a93ce30fc3e.png)原始图像与生成的草图# 创建草图功能我们可以将所有东西放在一起创建一个草图功能:来自 GitHub Gist 的 img2sketch 功能代码## 资源:本教程的代码可以从我的 [GitHub Repo](https://github.com/hashABCD/Publications/tree/main/Medium/imagetr_opencv) 中获得。如果你喜欢视频格式的内容,你可以看看这个 YouTube 教程。如何从照片生成草图的视频教程## 成为会员我希望你喜欢这篇文章,我强烈推荐 [**注册*中级会员***](https://abhijithchandradas.medium.com/membership) 来阅读更多我写的文章或成千上万其他作者写的各种主题的故事。
[你的会员费直接支持我和你看的其他作家。你也可以在媒体](https://abhijithchandradas.medium.com/membership)上看到所有的故事。## 相关文章:</create-and-read-qr-code-using-python-9fc73376a8f9>  ![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/63a987506737d09de4bf4583894ef948.png)由 [Raamin ka](https://unsplash.com/@raaminka?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的原始照片以及计算机生成的草图# 用 Python 中的逆变换方法生成随机变量> 原文:<https://towardsdatascience.com/generate-random-variable-using-inverse-transform-method-in-python-8e5392f170a3?source=collection_archive---------7----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5722b7baed80f4b3d66e51c9d9d5d5ad.png)由 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的 [Edge2Edge 媒体](https://unsplash.com/@edge2edgemedia?utm_source=medium&utm_medium=referral)拍摄## “从均匀到任何随机变量”,这是个神奇的词。**动机**在仿真理论中,生成随机变量成为最重要的“积木块”之一,其中这些随机变量大多是由均匀分布的随机变量生成的。可以用来产生随机变量的方法之一是逆变换方法。在本文中,我将向您展示如何使用 Python 中的**逆变换**方法生成随机变量(离散和连续的情况)。**概念**给定随机变量 U 其中 U 均匀分布在(0,1)中。假设我们想要生成随机变量 X,其中累积分布函数(CDF)为![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9618c881d030c2e2eafb79127bb5e62e.png)逆变换方法的思想是通过使用其逆 CDF 从任何概率分布生成随机数,如下所示。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a3a2fab3651ab79bae236edd8e54c8f3.png)**对于离散型随机变量,步骤略有不同。**假设我们想要生成一个离散随机变量 X 的值,该变量具有一个概率质量函数(PMF)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/32b7ba813d1db66a1214b6581b4ed2f6.png)要生成 X 的值,生成一个随机变量 U,其中 U 均匀分布在(0,1)中,并设置![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/dd89e512967adaf451188a10242724da.png)根据上面的步骤,我们可以创建如下的逆变换方法的算法。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7b746ea75e3552c9b2a907fc25fc7371.png)逆变换方法的算法(图片由作者提供)**实施:连续 r.v .案例**首先,我们实现了这种生成连续随机变量的方法。假设我们要模拟一个服从均值为λ的指数分布的随机变量 X(即 X~EXP(λ))。我们知道指数分布的概率分布函数是![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/fed5225f64ca0795ce3bd3b5e0baa969.png)CDF 如下所示。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/906b569ea823a285dc80a19f1f5a720f.png)然后,我们可以把逆向 CDF 写成如下。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/969a97d1a7d978e5da08d44a36c96235.png)在 Python 中,我们可以通过编写如下代码来简单地实现它。

Generate exponential distributed random variables given the mean

and number of random variables

def exponential_inverse_trans(n=1,mean=1):
U=uniform.rvs(size=n)
X=-mean*np.log(1-U)
actual=expon.rvs(size=n,scale=mean)

plt.figure(figsize=(12,9))
plt.hist(X, bins=50, alpha=0.5, label="Generated r.v.")
plt.hist(actual, bins=50, alpha=0.5, label="Actual r.v.")
plt.title("Generated vs Actual %i Exponential Random Variables" %n)
plt.legend()
plt.show()
return X

我们可以通过运行下面的一些例子来尝试上面的代码。**请注意,由于我们要生成随机变量,结果可能会有所不同。**

cont_example1=exponential_inverse_trans(n=100,mean=4)
cont_example2=exponential_inverse_trans(n=500,mean=4)
cont_example3=exponential_inverse_trans(n=1000,mean=4)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/64b87f01806723a152a7c9a2eb12fe39.png)生成的与实际的 100 个指数随机变量(图片由作者提供)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/98154ffbd1de5f1cf896e794dc8ccccc.png)生成的与实际的 500 个指数随机变量(图片由作者提供)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a0ba42f9801a69a3e1ff7e6e1ab91481.png)生成的与实际的 1000 个指数随机变量(图片由作者提供)看起来很有趣。我们可以看到,产生的随机变量有一个非常相似的结果,如果我们比较它与实际的。你可以调整均值(**请注意,我为 expon.rvs()函数定义的均值是指数分布**中的一个比例参数和/或生成的随机变量的数量,以查看不同的结果。**执行:离散 r.v .案**对于离散随机变量情况,假设我们想要模拟一个离散随机变量情况 X,它遵循以下分布![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0e5ce8aeff48e9502913e293e6bf0835.png)用于示例的离散随机变量分布的 PMF(图片由作者提供)首先,我们用这几行代码编写函数,为一个样本生成离散随机变量。

Generate arbitary discrete distributed random variables given

the probability vector

def discrete_inverse_trans(prob_vec):
U=uniform.rvs(size=1)
if U<=prob_vec[0]:
return 1
else:
for i in range(1,len(prob_vec)+1):
if sum(prob_vec[0:i])<U and sum(prob_vec[0:i+1])>U:
return i+1


然后,我们用这些代码行创建一个函数来生成许多随机变量样本。

def discrete_samples(prob_vec,n=1):
sample=[]
for i in range(0,n):
sample.append(discrete_inverse_trans(prob_vec))
return np.array(sample)


最后,我们通过这几行代码创建一个函数来模拟结果,并与实际结果进行比较。

def discrete_simulate(prob_vec,numbers,n=1):
sample_disc=discrete_samples(prob_vec,n)
unique, counts=np.unique(sample_disc,return_counts=True)

fig=plt.figure()
ax=fig.add_axes([0,0,1,1])
prob=counts/n
ax.bar(numbers,prob)
ax.set_title("Simulation of Generating %i Discrete Random Variables" %n)
plt.show()data={'X':unique,'Number of samples':counts,'Empirical Probability':prob,'Actual Probability':prob_vec}
df=pd.DataFrame(data=data)
return df

我们可以运行下面的一些例子来看看结果。**同样,注意结果可能会不同,因为我们想要生成随机变量。**

prob_vec=np.array([0.1,0.3,0.5,0.05,0.05])
numbers=np.array([1,2,3,4,5])dis_example1=discrete_simulate(prob_vec, numbers, n=100)
dis_example2=discrete_simulate(prob_vec, numbers, n=500)
dis_example3=discrete_simulate(prob_vec, numbers, n=1000)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/210379354af983a1834de320380c68c9.png)生成的与实际的 100 个离散随机变量(图片由作者提供)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/fad395c6e390eaa323e97bc74313d5a0.png)生成的与实际的 500 个离散随机变量(图片由作者提供)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/91fd9e810a5e85a0a15e16ac1296cd21.png)生成的与实际的 1000 个离散随机变量(图片由作者提供)

In[11]: dis_example1
Out[11]:
X Number of samples Empirical Probability Actual Probability
0 1 8 0.08 0.10
1 2 35 0.35 0.30
2 3 50 0.50 0.50
3 4 5 0.05 0.05
4 5 2 0.02 0.05In[12]: dis_example2
Out[12]:
X Number of samples Empirical Probability Actual Probability
0 1 53 0.106 0.10
1 2 159 0.318 0.30
2 3 234 0.468 0.50
3 4 30 0.060 0.05
4 5 24 0.048 0.05In[13]: dis_example3
Out[13]:
X Number of samples Empirical Probability Actual Probability
0 1 108 0.108 0.10
1 2 290 0.290 0.30
2 3 491 0.491 0.50
3 4 51 0.051 0.05
4 5 60 0.060 0.05


结果有意思!我们可以看到,随着随机变量样本数量的增加,经验概率越来越接近实际概率。尝试使用不同数量的样本和/或不同的分布进行实验,以查看不同的结果。**结论**就是这样!这种逆变换方法是统计学中非常重要的工具,特别是在模拟理论中,我们希望在给定均匀分布在(0,1)中的随机变量的情况下生成随机变量。研究案例本身非常广泛,从生成经验 CDF 到预测分析,您都可以使用这种方法。下期帖子再见!**作者联系方式**领英:[拉登·奥勒留和希卡·维亚迪努格罗霍](https://www.linkedin.com/in/raden-aurelius-andhika-viadinugroho-b84b19163/)**参考文献**[1]谢尔登·m·罗斯,[模拟,第 5 版](https://www.sciencedirect.com/book/9780124158252/simulation) (2013),爱思唯尔[2]谢尔登·m·罗斯,[工程师和科学家概率统计导论,第 5 版](https://www.sciencedirect.com/book/9780123948113/introduction-to-probability-and-statistics-for-engineers-and-scientists) (2014),爱思唯尔[3][https://Stephens 999 . github . io/five minute stats/Inverse _ transform _ sampling . html #:~:text = Inverse % 20 transform % 20 sampling % 20 is % 20a,P(X%E2%89%A4x)。](https://stephens999.github.io/fiveMinuteStats/inverse_transform_sampling.html#:~:text=Inverse%20transform%20sampling%20is%20a,P(X%E2%89%A4x).)# 为 R 中的线性模型生成模拟数据集> 原文:<https://towardsdatascience.com/generate-simulated-dataset-for-linear-model-in-r-469a5e2f4c2e?source=collection_archive---------5----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/44e922b180681edef8256cee5e9c6683.png)由 [CHUTTERSNAP](https://unsplash.com/@chuttersnap?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片## 当真实数据集很难找到时,模拟一下。## 动机近年来,随着计算能力的增加,关于机器学习(ML)的研究也在增加。因此,在一些 ML 模型中有了很大的发展——如果不是发明一个新的模型的话——表现得比传统模型更好。研究人员在尝试实现所提出的模型时通常会遇到的一个主要问题是缺乏符合模型假设的正确的真实世界数据集。或者在另一种情况下,真实世界的数据集是存在的,但是数据集本身非常昂贵并且难以收集。为了克服这些问题,研究人员通常会生成一个遵循模型假设的模拟数据集。该模拟数据集可用作建模过程中模型或真实数据集替换的基准,其中模拟数据集比真实数据集更具成本效益。本文将解释如何使用 r 为线性模型生成模拟数据集。## 这个概念生成模拟数据集的过程可以解释如下。首先,我们指定想要模拟的模型。接下来,我们确定每个自变量的系数,然后模拟遵循概率分布的自变量和误差。最后,根据模拟的自变量(及其预定系数)和误差计算因变量。为了在实践中更好地理解这个过程,这里我将给出一些使用 r 为线性模型生成模拟数据集的实现。## 实施:线性回归对于第一个示例,假设我们想要模拟以下线性回归模型![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7f3fedf0a6999c5e7fb3b2df00ece368.png)其中 x_1 遵循均值为 50、方差为 9 的正态分布,x_2 遵循均值为 200、方差为 64 的正态分布,误差遵循均值为 0、方差为 16 的正态分布。也假设 b0、b1 和 b2 分别是 150、-4 和 2.5。我们可以通过编写如下代码来模拟它**(注意不同的种子,结果可能不同)**。

summary(m1)Call:
lm(formula = y1 ~ x1 + x2)Residuals:
Min 1Q Median 3Q Max
-41.782 -12.913 -0.179 10.802 53.316Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 154.23621 10.71954 14.39 <2e-16 ***
x1 -3.98515 0.19636 -20.30 <2e-16 ***
x2 2.47327 0.02714 91.14 <2e-16 ***


Signif. codes: 0 ‘’ 0.001 ‘’ 0.01 ‘’ 0.05 ‘.’ 0.1 ‘ ’ 1Residual standard error: 17.96 on 97 degrees of freedom
Multiple R-squared: 0.9885, Adjusted R-squared: 0.9883
F-statistic: 4179 on 2 and 97 DF, p-value: < 2.2e-16


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/111981d458355962b3ce8df1930153c6.png)使用模拟数据集对第一个示例模型进行诊断检查(图片由作者提供)从模型`m1`可以看出,模型是显著的(基于总体检验的 p 值),每个自变量(x1 和 x2)和常数都是显著的(基于每个变量中的 p 值)。我们还可以看到,估计的系数非常接近每个系数的预定值。## 实施:带分类自变量的线性回归现在,对于第二个示例,假设我们想要模拟以下线性回归模型![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b52a422c15e6fb43f13b791edd6b5344.png)其中 x_1 和 x_2(及其系数)、error 和 b0 与第一个示例相同,但 x_3 是一个二进制分类变量,遵循二项式分布,成功概率(在 R 中表示为 1)为 0.7,b3 为 5。使用与之前相同的种子,我们可以通过编写如下代码行来模拟它。

summary(m2)Call:
lm(formula = y2 ~ x1 + x2 + x3)Residuals:
Min 1Q Median 3Q Max
-41.914 -12.804 -0.065 10.671 53.178Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 153.84275 11.32094 13.589 <2e-16 ***
x1 -3.98432 0.19751 -20.173 <2e-16 ***
x2 2.47330 0.02728 90.671 <2e-16 ***
x3 5.46641 4.11890 1.327 0.188


Signif. codes: 0 ‘’ 0.001 ‘’ 0.01 ‘’ 0.05 ‘.’ 0.1 ‘ ’ 1Residual standard error: 18.05 on 96 degrees of freedom
Multiple R-squared: 0.9885, Adjusted R-squared: 0.9882
F-statistic: 2758 on 3 and 96 DF, p-value: < 2.2e-16


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4203339f932c235a77db36b566fe46a7.png)从模型`m2`可以看出,模型是显著的,每个自变量(除了 x_3)和常数都是显著的(基于每个变量中的 p 值)。## 实施:计数回归对于最后一个例子,假设我们想要模拟下面的计数线性模型(具体来说是泊松回归模型)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/937541c1278088b2ad5003029655db92.png)其中 x_1 服从均值为 2、方差为 1 的正态分布,x_2 服从均值为 1、方差为 1 的正态分布,b0、b1、b2 分别为 5、-4、2.5。与前两个示例的不同之处在于,我们需要首先使用上面的等式计算λ的对数,并对其求幂以计算因变量。我们可以通过编写如下代码来模拟它。

summary(m3)Call:
glm(formula = y3 ~ x1 + x2, family = poisson(link = "log"))Deviance Residuals:
Min 1Q Median 3Q Max
-1.99481 -0.58807 -0.14819 0.00079 2.08933Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 5.02212 0.03389 148.2 <2e-16 ***
x1 -3.96326 0.02871 -138.0 <2e-16 ***
x2 2.48380 0.02950 84.2 <2e-16 ***


Signif. codes: 0 ‘’ 0.001 ‘’ 0.01 ‘’ 0.05 ‘.’ 0.1 ‘ ’ 1(Dispersion parameter for poisson family taken to be 1)Null deviance: 90503.729 on 99 degrees of freedom
Residual deviance: 69.329 on 97 degrees of freedom
AIC: 283.21Number of Fisher Scoring iterations: 4


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cd94d7c82fc69b4e1540ead3b6dc77a1.png)从模型`m3`中,我们可以看到变量和模型常数是重要的,并且我们可以看到估计的系数与每个系数的预定值相比也非常接近。## 结论就是这样!您已经学习了如何在 r 中为线性模型生成模拟数据集。本文中的示例只是如何进行模拟数据集生成过程的一些简单实现。在实际应用中,您可以生成更复杂的模拟数据集,并将其用于一些具有交互效果的线性模型或一些高级 ML 模型。像往常一样,如果您有任何问题,请随时提问和/或讨论!我的下一篇文章再见!## 作者的联系人领英:[拉登·奥勒留和希卡·维亚迪努格罗霍](https://www.linkedin.com/in/raden-aurelius-andhika-viadinugroho-b84b19163/)中:【https://medium.com/@radenaurelius】T4## 参考[1]s . m .罗斯(2013 年)。 [*模拟,第 5 版*](https://www.sciencedirect.com/book/9780124158252/simulation) 。爱思唯尔。[2][https://book down . org/rd Peng/rprogdatascience/simulation . html # simulating-a-linear-model](https://bookdown.org/rdpeng/rprogdatascience/simulation.html#simulating-a-linear-model)[3]巴拉尔迪,p .,曼吉利,f .,和齐奥,E. (2013 年)。[使用模拟数据调查基于模型和数据驱动的预测方法的不确定性处理能力](https://www.sciencedirect.com/science/article/pii/S0951832012002591?casa_token=VIZMOmD3vBwAAAAA:miZcBKZp_5HIzzVw1UcVQfsbrgvWv59piCov8XtcrtGgA-TMdcYfVI9tab0ioZ3PexsflwXY)。*可靠性工程&系统安全*,第 112 卷,第 94–108 页。[4]奥尔蒂斯-巴里奥斯,硕士,伦德斯特伦,法官,辛诺特,法官,热尔佩和圣安娜(2020 年)。[用模拟数据补充真实数据集:基于回归的方法](https://link.springer.com/article/10.1007/s11042-019-08368-5)。*多媒体工具和应用*,第 79 卷,第 34301–34324 页。# 使用马尔可夫链生成披头士歌词> 原文:<https://towardsdatascience.com/generate-unedited-beatles-lyrics-using-markov-chain-b7968c49584f?source=collection_archive---------26----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1fb6009552bed5cf37dba4d9b75c169c.png)[费多尔](https://unsplash.com/@fmdevice)在 [Unsplash](https://unsplash.com) 上拍照我非常喜欢披头士。我希望他们写更多的歌词…但是等等,我是一个程序员,我可以根据他们的唱片目录生成新的歌词!让我们看看怎么做。*🎤昨天……我所有的烦恼都显得那么遥远。*哦,等等,这是一篇文章,你听不到我唱歌!(幸好😄)我们将创建一个程序,将许多歌词作为输入,并在每次执行时产生一个新的歌词。非常熟练的数据科学家和程序员最终会用 **TensorFlow** 或类似的东西创建一个**AI**…但是我们想让它变得简单!我们将使用一种叫做**马尔可夫链**的算法。# 为什么使用马尔可夫链算法?很高兴你问了!
维基百科将**马尔可夫链**描述为:*“描述一系列可能事件的随机模型,其中每个事件的概率仅取决于前一事件达到的状态”*寥寥数语,让我们来看看以下披头士的歌词:*“爱是古老的;爱是新的,爱是一切,爱是你。*让我们把上面的句子分解成单词。现在回答以下问题:1.  “爱”这个词在上面的句子中重复了多少次?
2.  哪些词紧挨着“爱”这个词?
3.  “是”这个词重复了多少次?
4.  哪些词紧挨着“是”这个词?在我们回答了这些问题之后,我们可以清楚地想象下面的图表:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/178cce5fbd16ffee3e9462b52545046d.png)因此,根据上面的图表,我们可以知道:1.  在“爱”这个词之后,有 100%的可能性会遇到“是”这个词
2.  在单词“是”之后,有 25%的可能性会遇到下列单词之一:“旧的”、“新的”、“所有的”、“你”现在,想象对一首更复杂的歌曲做同样的研究,比如 **Hey Jude** :*“嘿,裘德,不要让它变坏
唱一首悲伤的歌,让它变好
记得让她进入你的心里
然后你就可以开始让它变好*嘿,裘德,不要害怕从你让她进入你的皮肤的那一刻起,你就被迫走出去得到她*无论何时你感到痛苦
嘿,裘德,不要把世界扛在肩上* 因为你知道,通过让自己的世界变得更冷来装酷的人是傻瓜*娜娜娜娜……**嘿,裘德,不要让我失望
她已经找到你,现在去得到她
记得让她进入你的心
然后你可以开始让它变得更好**尽情释放,尽情投入
嘿,裘德,开始
你在等人和你一起表演
难道你不知道只有你自己
嘿,裘德,你会做
你需要的动作就在你的肩膀上
啦,啦,啦,啦……**嘿,裘德,不要让它变坏
选一首悲伤的歌,让它变得更好
一旦你让她进入你的心
那么你就可以开始让它变得更好**娜娜娜……”*一位 Reddit 用户贴了一张关于这首歌的有趣的流程图,这将节省我很多工作:![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/682a0fe9c8e0b64ba6fcec73beadd0fc.png)[Reddit](https://www.reddit.com/r/ProgrammerHumor/comments/f27xpu/flowchart_hey_jude/) 上的流程图“嘿,裘德”你能看到我要去哪里吗?我们想要估计每个单词出现在另一个单词旁边的概率。给定这个值,我们将能够根据一个给定单词在另一个给定单词之后出现的概率来组成新的句子。# 构建马尔可夫链我们将在**类型脚本**中构建马尔可夫链,以便在编译阶段之后在我们的浏览器中运行。如果您不习惯 TypeScript 语法,不要担心!理解起来会毫不费力。我们将从定义马尔可夫链接口开始:我们的类将有三个公共方法:1.  `add`:它会让我们给自己的模型添加越来越多的歌词。
2.  `train`:它会训练我们的模型。一个模型基本上是一个对象,它保存了一个给定单词和它旁边的所有单词之间的所有关系。
3.  `generate`:它会根据我们的模型返回给定长度的新歌词。现在我们可以开始构建我们的`MarkovChain`类了:如你所见,在我们的类中,我们还想指定两个私有变量。第一个是`data`。它会将我们添加的所有歌词存储为一个唯一的字符串。第二个是`model`。这个对象应该是这样的:(如果你想知道为什么`'new'`要加引号,那是因为它是 JS 中的保留关键字)。正如您可能已经猜到的那样,`model`存储了`data`中的每个单词,以及它们后面的所有单词。让我们开始实现`add`方法:通过这种方法,我们希望将输入字符串附加到`data`变量上。请注意,我们还在`txt`变量后添加了一个空格,以连接给定歌词的最后一个词和下一个词的第一个词。现在继续使用`train`方法。
首先,我们要确保在开始培训之前已经插入了一些数据。然后,我们想从我们的`data`中删除所有的特殊字符(不包括单引号)。这样,下面的输入字符串:`'hey there! I\'m trying the Markov Chain for the first time!!!'`将被转换成:`['hey', 'there', 'i\'m', 'trying', 'the', 'markov', 'chain', 'for', 'the', 'first', 'time']`。现在我们要训练我们的模型,所以我们基本上要循环每个令牌。如果给定的令牌在我们的模型中还不存在,我们将添加它(并添加一个空数组作为值)。否则,我们将把下一个令牌作为一个值放入当前模型数组中。厉害!现在我们可以训练我们的模型了。
现在我们需要添加`generate`方法。我们还将添加一个名为`getRandomElement`的私有 helper 函数,它将从给定的数组中返回一个随机元素。如您所见,这些方法非常简单。
首先,我们要检查用户是否已经对模型进行了训练。
之后,我们开始从模型中获取一个随机单词。
然后我们想要循环`x`次,其中`x`是我们想要创建的最终歌词的长度。在每一个循环中,我们都希望得到前面实例化的`newWord`变量旁边的一个单词。然后,我们将这个单词连接到`result`字符串。然后我们要检查这个词在我们的模型中是否有它自己的后继词。
如果是,我们用后继者重新实例化`randomWord`变量;否则,我们随机取一个新词。一旦循环结束,我们返回结果字符串,就这样!下面是完整的实现:# 玩我们的新玩具现在我们的类已经准备好了,我们可以如下使用它:你也可以从 [GitHub](https://github.com/Hackdoor-io/articles-codebase/tree/master/articles/generate-inedited-beatles-lyrics-using-markov-chains) 下载代码!
尽情享受!# 用 Python 生成你想要的任何东西> 原文:<https://towardsdatascience.com/generate-whatever-you-want-in-python-3db8dea7bdd4?source=collection_archive---------24----------------------->![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ee8bc84ad22b63d48c0180888d12fcdc.png)照片由 [Pixabay](https://pixabay.com/photos/tulips-flowers-tulip-field-5097405/) 上的[迈克尔 _ 卢嫩](https://pixabay.com/users/michael_luenen-2998623/)拍摄## 随机库—从基础到高级无论您使用 Python 做什么,您都可能需要生成一些随机数据,比如数字和字符串。如果您是数据科学家或数据分析师,这一点尤为重要。事实上,不仅是随机的,而且是我们想要的特定形状。在本文中,我将重点介绍 Python 内置库——random。等等,不要不扫描就关闭这一页。我知道你们大多数人都知道如何使用随机图书馆。但是,我几乎保证,会有你可能不知道的高级。它们有时会非常方便和有用。本文将从三个方面介绍随机库的主要特性——随机整数、随机选择和从某些发行版中随机选择。此外,本文中的所有代码都基于随机库中的所有函数都已被导入,如下所示。

from random import *


# 随机整数![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/988046182b9098106ccdd0956af9b3a6.png)图片由 [adriano7492](https://pixabay.com/users/adriano7492-6485549/) 在 [Pixabay](https://pixabay.com/photos/dice-game-role-playing-game-2788986/) 上拍摄## 基本用法随机库最常见的用法肯定是生成随机整数。我们可以很容易地在如下范围内生成一个随机整数。

randint(start, end)


“开始”和“结束”的数字都包括在内。我们可以通过如下循环 10 次来测试这个函数。

[randint(1, 3) for i in range(10)]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/940d3c9f9d801206e4d1cdfa480a5588.png)上面的代码从范围[1,3]中生成了 10 个整数。这是`randint()`的基本用法。## 使用步长从范围生成大多数开发人员似乎不会过多地使用函数`randrange()`。这里有一个要解决的样本问题。> 生成 20 个介于 1 和 9 之间的奇数。你会怎么做?或许生成一个包含所有可能数字的列表,然后随机选择?嗯,这是可行的,但肯定有更好的方法来做到这一点。那就是使用`randrange()`功能。我很确定你会知道如何使用`range()`函数,这是 Python 中的内置函数之一。我刚刚在 for 循环中用它作为计数器。如果我们想用它来生成一个奇数列表,我们可以这样做。

range(1, 10, 2)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ec72ae15ff39e6b8282999a289c88d9a.png)这只是一个例子,因为功能`range()`和`randrange()`的用法和参数完全相同。因此,要解决我们在本节开始时遇到的问题,我们可以执行以下操作。

[randrange(1, 10, 2) for i in range(20)]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f425000fb1c479856edf50c4c7badb12.png)# 随机选择![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e10c09e5c845af0d37200f00427fb09a.png)由 [Pixabay](https://pixabay.com/photos/girl-crossroads-choice-way-2573111/) 上的[pix source](https://pixabay.com/users/pixource-3867243/)拍摄的照片## 基本用法随机选择是随机库中另一个基本而重要的功能。我们用它从列表中随机选择一个项目。例如,我们有如下列表。

my_list = ['a', 'b', 'c']


要从中随机选择一个项目,只需调用`choice()`函数。

choice(my_list)


如果我们想这样做 10 次,当然,只要循环它。

[choice(my_list) for i in range(10)]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e1b76bf7d63ba0bb2b901429de7edaab.png)然而,最佳实践是使用`choices()`函数。注意它是复数。通过传递参数“k”,我们不必重新发明轮子。

choices(my_list, k=10)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e839270e976d967019aecce099351b75.png)## 带权重的随机选择如果我们想做一些有偏见的选择呢?这有时是必要的。使用`choices()`函数,我们可以通过`weights`参数很容易地做到这一点。

choices(my_list, weights=[1, 0, 0], k=10)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c8c30b844d68c43db9941773d4942b28.png)请注意,“权重”必须是一个与“我的列表”长度完全相同的列表。在第一个例子中,我将项目“a”的权重设置为 1,而其他两个项目的权重都为 0。因此,“b”项和“c”项根本没有机会被选中。在第二个例子中,我给项目“a”的权重为 10,“b”的权重为 1,“c”的权重为 0。所以“a”比“b”有 10 倍的机会被选中,而“c”没有机会。老实说,我不得不多次随机选择,以得到一个包含 10 个包含“b”的条目的列表## 打乱名单随机库还有另一个有用的特性。考虑以下两个问题> 1.我们有一个按一定顺序排列的集合,但我们不希望它被排序。
> 2。我们想在“我的列表”上随机选择 3 次,但不想要重复的值。以上两个问题,我们其实都需要洗牌。随机库中的`shuffle()`函数可以打乱列表。

shuffle(my_list)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/31d33b2728d495a4fa0ccc185c29e109.png)## 列表中的样本然后,考虑上一节的第二个问题。我们想在“我的列表”上执行几次随机选择(小于它的长度)。我们仍然不希望有任何重复的值。这相当于使用“my_list”作为人口,并对其进行随机抽样。随机库中有一个函数`sample()`可以帮我们做到这一点。

sample(my_list, k=2)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cb3712e0faca536526f7093c1d2f8c2a.png)因此,在上面的代码中,我们从原始列表中抽取了 2 个项目。# 具有特定分布的随机![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/199ab7d2ef0314adab509274cd242879.png)[6689062](https://pixabay.com/users/6689062-6689062/) 在 [Pixabay](https://pixabay.com/photos/financial-analytics-blur-business-2860753/) 上拍摄的照片现在,让我们做一些更高级和定制的随机数生成。为了测量我们生成的数字的分布,让我导入 Matplotlib 来绘制直方图中生成的数字。让我们首先使用基本函数`random()`在一个列表中生成 10000 个数字。请注意,该函数将生成一个介于 0 和 1 之间的浮点数。

r1 = [random() for i in range(10000)]


然后,让我们画出数字。

plt.hist(r1, bins=20)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/44af76b3a019f3f9a5c514e95a95ed02.png)我们可以看到直方图显示这些数字分布非常均匀。这是默认设置。事实上,要显式生成均匀分布形状的数字,我们可以使用`uniform()`函数。

r2 = [uniform(1,100) for i in range(10000)]plt.hist(r2, bins=20)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5f1fefe45a0dc6a2fba16fa11f4fbe64.png)上面的代码生成了 10,000 个 1 到 100 之间的均匀分布的浮点数。还有什么?每个人都喜欢正态分布。或者,我们也可以说是高斯分布。让我们在这个形状中生成 10,000 个数字。

r5 = [gauss(1, 1) for i in range(10000)]plt.hist(r5, bins=100)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/088093d5d45c5615a081b46133208f47.png)函数`gauss(mu, sigma)`有两个参数,代表我们想要的正态分布的均值和标准差。然后,我们可以把其他事情交给它。最后,我还想介绍一下三角分布。这在我们的日常生活中确实不太常见。它不像随处可见的正态分布。但是,如果我们想要生成一个偏态分布,这是非常方便的。`triangular()`功能的基本用法如下。

r3 = [triangular(1, 100) for i in range(10000)]plt.hist(r3, bins=50)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4b6cb936a4ca59873e389a05732bef93.png)上面的代码生成 10,000 个 1 到 100 之间的三角形分布的数字。正如我提到的,如果我想要一个偏态分布呢?比如我们希望顶点在 80 左右?我们可以将第三个参数传递给函数,如下所示。

r4 = [triangular(1, 100, 80) for i in range(10000)]plt.hist(r4, bins=50)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e25f7749e75c2e90a3ef945a3b764ba7.png)# 摘要![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f0810230721b627835bc43c50dafba34.png)照片由[吉尔·威林顿](https://pixabay.com/users/jillwellington-334088/)在 [Pixabay](https://pixabay.com/photos/pears-lemons-apples-fruit-tea-6101067/) 上拍摄在本文中,我介绍了如何使用 Python 中的内置随机库来获得我们想要的任何东西,比如随机整数、从列表中随机选择以及某种分布中的随机数。而不是把重点放在基础知识上,一些高级的用法比如一气呵成的随机选择,加权,洗牌,抽样。希望你喜欢阅读。<https://medium.com/@qiuyujx/membership>  如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/72610.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

TowardsDataScience-博客中文翻译-2021-七十七-

TowardsDataScience 博客中文翻译 2021(七十七)原文:TowardsDataScience Blog 协议:CC BY-NC-SA 4.0使用数据科学节省资金原文:https://towardsdatascience.com/saving-money-using-data-science-f7f6d229dd90?source=collection_archive---------44--------------------…

TowardsDataScience-博客中文翻译-2021-七十二-

TowardsDataScience 博客中文翻译 2021(七十二)原文:TowardsDataScience Blog 协议:CC BY-NC-SA 4.0图片中的概率公理原文:https://towardsdatascience.com/probability-axioms-in-pictures-2de96880c868?source=collection_archive---------32-----------------------通…

116、SAP导出表结构并保存到Excel,方便写代码时复制粘贴

01. 在SE38模块,创建一个程序 02.ABAP代码如下:*&---------------------------------------------------------------------* *& Report Z_TIANPAN_20190716_HELLO *&---------------------------------------------------------------------* *& *&----…

『玩转Streamlit』--环境配置

尽管Streamlit的使用非常直观,但正确的环境配置对于充分发挥其潜力仍然至关重要。 本篇将介绍如何从头开始配置Streamlit环境,以及Streamlit开发过程中常用的几个命令。 最后通过一个简单的示例演示开发Streamlit应用的过程。 1. 安装 Streamlit是纯Python的框架,只依赖Pyth…

DTL698电表数据 转 profinet IO协议项目案例

VFBOX协议转换网关支持PLC,modbus,EthernetIP,Profinet,CCLink,EtherCAT,IEC61850,IEC104,bacnet,DLT645,HJ212,opc ua,opc da,DNP3。目录 1 案例说明 1 2 VFBOX网关工作原理 1 3 准备工作 2 4 配置VFBOX网关 2 5 用PROFINET IO协议转发数据 4 6 其他说明 6 7 案例…

win11网络修改篡改bug自动修改dns没有网络问题

1.问题描述 没有网络,dns一直是自动获取的,但是在重启或连接vpp后,会被设置成某个固定值 正常情况:莫名其妙的 篡改: 2.解决办法 1.首先,删除所有网络的手动dns配置,控制中心那个dns管理没有用,在设置中删除网络,不然问题还会出现 - 2.然后,进入注册表\HKEY_LOCAL_MACHI…

sqlsever 将字符串格式转换成日期格式

SELECT CONVERT(DATETIME, 20241009, 112) AS ConvertedDate;SELECT CAST(20241009 AS DATETIME) AS ConvertedDate;