TowardsDataScience-博客中文翻译-2020-五十五-

news/2024/10/15 13:57:03

TowardsDataScience 博客中文翻译 2020(五十五)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

GPT-3,OpenAI 的革命

原文:https://towardsdatascience.com/gpt-3-openais-revolution-f549bf3d4b25?source=collection_archive---------43-----------------------

来源:弗洛里安·克劳尔

研究有史以来最强大的语言模型的含义

OpenAI 是目前人工智能领域的明显领导者之一,它无疑引领着自然语言系统。其文本生成算法 GPT 显示出一种生成类似人类文本的神奇能力,彻底改变了文本生成领域。它的最新版本 GPT-3 现在能够超越这一点,不仅能够写出连贯的段落,还能根据规范生成代码等等。

GPT 基本上是一个自动完成。然而,它不只是像流行的消息应用程序那样建议下一个单词。根据最初的提示,GPT 能够写出连贯、冗长的文本段落。

生成的内容与人类编写的内容如此接近,以至于人们一直在讨论这个工具是否太强大而不能交给人。

你自己看看:

来源:马里奥·克林格曼(@卡西蒙多)

文本是在只植入标题、作者姓名和第一个“它”之后生成的。

但这并没有停止。

这个人使用 GPT-3 从一系列规范中生成 React 代码。

另一位用户创建了一封求职信来申请工作。

很明显,GPT-3 非常好,但这意味着什么呢?

1.假新闻

与任何强大的工具一样,对它的使用决定了它的影响,而这种影响的范围非常大。一方面,像 GPT-3 这样的工具可以用来生成文本,以支持许多领域的业务,例如将法律术语转换成简单的英语。但是,很明显,它也可以用来生成误导性内容,具体来说就是假新闻

GPT-3 可用于有计划地产生误导性信息,例如通过向其提供分裂性和不真实的提示,如种族指控、性别歧视或暴力言论。这可能导致比 2016 年选举更严重的结果,在 2016 年选举中,假新闻进一步分化了大众观点。能够通过算法生成假新闻可能会打开潘多拉魔盒。

2.乔布斯

另一个重要但不太明显的影响是对工作的影响。像 GPT-3 这样的工具可以导致许多工作变得过时,包括记者,作家和编剧,等等。然而,影响远不止于此。

从规范中直接生成代码的能力可能会让软件工程师变得多余,至少就我们现在所知是这样。软件工程可能会成为一项非常不同的工作,人们不用自己编写代码,而是用简单的英语编写规范、算法和功能,然后让像 GPT-3 这样的模型生成代码。

3.偏见

GPT-3 非常强大,因为它经过了数十亿个例子的训练,拥有数十亿个参数。然而,一个模型的好坏取决于它所训练的数据。如果一个模型是在坏数据上训练的,它的表现会很差。

由此可见,如果一个模型在有偏差的数据上被训练,它将学习这样的偏差。GPT 3 号也是如此。这种模式已经被证明,当遇到困难的话题时,会产生攻击性的、性别歧视的和种族主义的文本。

这是因为它是用来自多个来源的文本训练的,这些文本可以包含具有现有偏见的人的观点。让这样的模型不受限制地自由生成文本可能会通过传播偏见和助长分裂来助长观点的激进化和两极分化。

摘要

OpenAI 的 GPT-3 模型是一场真正的革命。该工具不仅能够预测文本,还能在冗长的段落中生成文本,保持连贯的“思想”流。然而,这样一个强大的工具如果用在错误的人手中,也可能成为一种武器。如果不加控制,这样的系统可能会对假新闻、就业和偏见的传播产生巨大影响。

要阅读更多类似的文章,请关注我的 Twitter LinkedIn或我的 网站

GPT-3 引物

原文:https://towardsdatascience.com/gpt-3-primer-67bc2d821a00?source=collection_archive---------18-----------------------

了解 OpenAI 的前沿语言模型

GPT-3 可能是计算量最大的机器学习模型。神经网络的 1750 亿个参数使其比之前最大的语言模型大了大约十倍(图灵 NLG ,170 亿个参数,由微软于 2020 年 2 月发布)。GPT-3 训练所用的 430GB 文本广泛取自互联网,并辅以书籍中的文本。该模型通过查看之前出现的一定数量的文本(最多约 2000 个单词)并预测下一个单词来生成新文本。

用户通过提供提示与模型进行交互。OpenAI(创造 GPT 3 号的组织)的聊天机器人式交互的一个示例提示是“以下是与人工智能助手的对话。这位助理乐于助人、富有创造力、聪明且非常友好”。除了提供提示,用户还可以指定某些参数,比如输出应该有多长,单词重复的可能性有多大,或者输出的随机性。

它能做什么?

GPT-3 在几乎所有标准的自然语言处理基准上都表现出了合理的熟练程度,包括在其中一些基准上的最先进的性能。基准测试包括一些挑战,例如使用一段上下文来预测相关句子的最后一个单词,以及确定语法上模糊但上下文中明确的代词指的是哪个名词。其他基准包括语言之间的翻译和回答一般知识问题。这种熟练程度是在没有大多数尖端模型使用的特定任务微调的情况下实现的。GPT-3 能够进行微调,进一步的微调几乎肯定会改善该模型在每个特定基准上的结果(代价是在微调任务之外的性能更差)。

OpenAI 还在一些非标准任务上测试了 GPT-3:

生成新闻文章

大约 80 人的样本被要求区分真实的文章和由 GPT-3 生成的最后 200 个单词的文章。参与者无法可靠地区分真实的文章和 GPT-3 完成的文章(参与者正确地分类了他们看到的 52%的文章,50%在 95%的置信区间内)。当模型生成的文本量增加到 500 个单词时,参与者没有提高他们的准确性(准确性保持在 52%)。

SAT 类比

当被要求完成 SAT 类比问题时,该模型正确回答的问题比普通大学申请人多 14%。

算术

下图显示了当系统提示几个数学问题并要求回答其中一个问题时,模型的准确性。我提到的 GPT-3 模型的结果在最右边(175B)。OpenAI 创建了几个版本的模型,以测试不同模型大小之间的性能差异。较大的模型显示出显著的改进。

(图表来自 GPT-3 论文)

总体而言,该模型能够可靠地成功回答两位数的加法和减法问题。对于所有其他类型的问题,该模型不能始终给出正确的答案,但明显优于机会。

度量是一回事,但是感受模型功能的最好方法是查看输出。许多人正在展示 GPT-3 的潜在使用案例。以下是一些亮点:

用 JavaScript 创建布局( 视频此处 )

在 Python 中创建 API(视频此处 )

在 Python 中创建函数( 视频此处 )

总结一个二年级学生的 NDA(视频此处 )

像律师一样写作

“搜索引擎”……其实并不搜索( 视频此处)

写诗

更多项目链接 此处

当然,仅凭几个精选的例子很难判断这个模型。展示令人印象深刻的能力似乎相对容易。生成足够好的可靠结果以用于某种生产设置(即作为客服机器人)是一个非常不同的故事。很可能该模型在有人类参与的系统中最有用(可能会生成一个建议的响应供人类批准或编辑),或者在不需要持续良好结果的应用程序中最有用(例如生成像 AI Dungeon 这样有趣的虚构故事)。

我如何使用它?

这款车型将通过 API 发售。OpenAI 目前有一个 API 的私人测试版,你可以在这里注册。该 API 的定价信息尚未公布,但我们知道从该模型生成 100 页内容的电力成本只有几分钱。为了收回创建模型的初始成本,每生成 100 个页面使用 API 的成本在 0.50 美元到 5 美元之间似乎是合理的,但这很难说。

或者,你可以通过 AI 地牢进入模型。注意 AI 地牢的自由层使用的是 GPT 2 生成的文本,而不是 GPT 3。为了使用 GPT-3,你需要注册付费版本(尽管前 7 天是免费的)。注册后,你需要改变设置,使用“龙”模型(又名 GPT-3),而不是“狮鹫”模型(又名 GPT-2)。付费版本还包括一个自定义提示选项(“场景”),这意味着你不需要使用标准的故事提示。

这里有什么新内容?

首先,该模型的广泛功能超出了公开可用的范围。很难预测人们将能够利用该模型做出什么,但很可能该模型将以新的方式使用,并在已经使用语言模型的领域改善结果。

除了该模型的实际新用途之外,这项研究还有一些有趣的收获:

型号越大越好

也许最重要的一点是,较大的模型继续表现更好。在 GPT-3 之前,研究人员已经观察到模型大小和性能之间的幂律关系。他们发现,在模型训练期间使用额外的计算能力回报递减,但对于更昂贵的模型,性能仍有显著提高。尽管趋势是在较低的计算水平上,但对于这种趋势可以外推多远仍有一些争论。在 GPT-3 之后,仍然不清楚这种趋势的极限在哪里,但我们还没有达到它们。尽管 GPT-3 比之前最大的型号大十倍,但它的性能是之前观察到的趋势所预期的。

(图表来自 GPT-3 论文)

上图显示了一系列模型大小和计算开销的模型性能(越低越好)。GPT-3 是黄线,虚线代表的幂律似乎在 OpenAI 测试的所有模型尺寸上都成立。

对于 OpenAI 训练 GPT-3 的成本有多种估计。一个估价说是 460 万美元。另一个说是 1200 万美元。两者都不包括研究人员报酬。不管真数,外卖不变。鉴于其潜在的应用,GPT-3 的生产成本非常低廉,更大的型号很可能会随之而来。2008 年,谷歌在食品上的花费比 OpenAI 刚刚花在创建一个具有商业应用的艺术语言模型上的花费要多得多。如果这个方向被认为足够有前途的话,有足够的资金来推动更大的模型。在 GPT-3 之后,很难反对更大的模型明显更有效。资金不是创建更强大模型的唯一限制。训练这种模型需要大量的新工程,但 OpenAI 不是唯一有能力完成这一任务的组织。

元学习

事实上,GPT-3 有能力做算术,而它测试的特定问题中只有极少数可能在训练数据中,这意味着该模型实际上正在学习如何做数学运算。该论文的作者进一步支持了这一观点,他们指出,“对错误答案的检查表明,该模型经常犯错误,例如没有携带‘1’,这表明它实际上是在尝试执行相关的计算,而不是记忆表格”。GPT-3 还正确回答了大约 20%的个位数组合运算(例如,9 *(7+5))——这个比率比随机概率好得多。值得注意的是,一个被简单训练来预测文本中下一个单词的模型似乎正在学习如何做数学,以便更好地预测下一个单词。这些结果提出了一个问题,即在更大的范围内,模型可能会获得什么样的新能力。例如,一个足够强大的语言模型可以阅读数千篇科学论文,并使用这些数据成功预测新实验的结果吗?

少数镜头学习

大多数大型、公开可用的机器学习系统采用的方法是对某种一般化数据进行大量训练,然后对特定领域数据的模型进行微调。GPT-3 通过用 OpenAI 所谓的“少量学习”取代微调步骤,展示了在许多领域的熟练程度。少量学习就是简单地向模型展示一些成功的例子,告诉它你希望它在模型给出的提示中做什么。例如,让模型成功回答常识性问题的提示可能是这样的,最后一个问题是您希望 GPT-3 回答的问题。

本帖的 API 截图

也可以通过提供没有示例(“零触发”)或有一个示例(“一触发”)的提示来使用该模型,但是该模型看到的示例越多,通常表现越好。

少量学习方法有几个好处:

  • 首先,少量学习可能会使机器学习更容易实现。愿意输入如上所示的提示的人比拥有微调模型的技术知识的人多得多。
  • 第二,以这种方式提示模型可以使机器学习模型能够用于获取微调所需的大量结构化训练数据不可行的领域。
  • 最后,少量学习使模型更加灵活。对于典型的微调方法,底层模型权重实际上是针对特定任务而改变的,因此微调牺牲了可概括的性能,以获得模型的特定应用程序的更好性能。相比之下,使用少量学习方法的模型不会改变底层模型。

如下图所示,模型越大,少量学习效果越好。少量学习不仅仅是对机器学习的当前状态进行微调的可行替代方案,它将继续在更大的未来模型中变得更有效。少量多次学习的效率不断提高,再加上模型规模不断扩大带来的直接性能提升,很可能会导致使用少量多次学习的大型模型的趋势。

图表来自 GPT-3 论文

语言模型能有多强大?

open ai 的这篇论文研究了语言模型的缩放问题。研究人员将模型性能视为模型大小、训练数据量和用于训练模型的计算能力的函数。他们发现了一种幂律关系,在这种关系中,更可靠地扩展输入会带来更好的性能。虽然这篇论文是在 GPT-3 之前写的,但是新的模型与他们发现的关系是一致的,即使它的规模比他们能够测试的要大得多。研究人员推断这一趋势,以找到一个模型(使用最佳输入比例)将达到类似语言模型的理论最高性能的点——所有信息都已从文本中提取出来的点。在到达那个点之前,这种模式完全有可能因为不可预见的原因而被打破。然而,如果这一趋势保持不变,研究人员估计,一个具有约 1 万亿个参数、在 1 万亿个令牌(约 1.4 万亿字节)上训练并使用约 10,000 petaflop/s-day 计算(pg)的模型将达到最高性能。17).

该论文警告说,“数值是高度不确定的,根据幂律拟合的指数的精确值,在两个方向上变化一个数量级。最明显的解释是,我们的比例定律在我们到达这一点时或之前就失效了,这在计算和模型大小方面仍有许多数量级的差距”。那是在 GPT-3 之前写的,GPT-3 现在在一个数量级之内。该论文中的公式预测 10,000 petaflop/s-day 计算的训练损失为 1.75,而 GPT-3 论文中的更新公式预测训练损失为 1.65。在用来自 GPT-3 的最新数据更新趋势线后,理论上的最佳语言模型似乎比之前的论文(和这里的数字)显示的更可实现。

值得注意的是,假设趋势没有被打破,它可能低估了未来的表现。这种关系并不能解释训练技术的未来改进。OpenAI 已经使用一致的过程来训练他们的 GPT 模型的各种版本,但是其他研究人员继续改进类似模型的训练过程。GPT-3 没有接受过尖端的训练。

数据来自 GPT 三号论文、 GPT 二号论文、定标论文

如果下一代模型能像 GPT 3 号那样扩展,它将远远超过迄今为止观察到的幂律理论预测的最佳模型。如果趋势打破,我们将获得关于当前方法局限性的重要信息。如果这一趋势不打破,我们将生活在一个非常不同的世界。

进一步探索:

GPT-3 论文

OpenAI blogpost

格温的帖子

Lambda 实验室帖子

Lambda Labs 汇总汇总其他内容

好概述

Slatestarcodex 帖子

分析扩展未来模型的潜在限制

使用示例,以及关于 API 参数的详细信息

计算机文件视频

收集更多演示和文章

GPT-3:第一个人工通用智能?

原文:https://towardsdatascience.com/gpt-3-the-first-artificial-general-intelligence-b8d9b38557a1?source=collection_archive---------0-----------------------

在 Unsplash 上由 Macy Ng 拍摄

如果一两年前你问我人工通用智能(AGI)什么时候会被发明出来,我会告诉你我们还有很长的路要走。做出这种判断的不止我一个人。大多数专家说,AGI 是几十年后的事,有些人说这可能根本不会发生。大家的共识是——曾经是?—人工智能的所有最新进展都涉及所谓的“狭义人工智能”,即只能执行一项特定任务的系统。AGI,或者说“强人工智能”,可以像人类一样完成任何任务,这是一个更困难的问题。这太难了,以至于没有一个清晰的路线图来实现它,而且很少有研究人员公开致力于这个主题。GPT-3 是第一个严重动摇这一现状的型号。

GPT-3 是 OpenAI 团队的最新语言模型。他们在 2020 年 5 月发表了论文,7 月,OpenAI 通过 API 向一些测试版测试人员提供了该模型的访问权限。该模型已被用于生成诗歌(见下面我的一个尝试),编写角色扮演冒险,或创建几个按钮的简单应用程序。如果你近年来一直关注机器学习的进展,你会知道所有这些都可以由其他人工智能系统完成,那么 GPT-3 有什么不同呢?

GPT 的救赎-3

我们要拯救人类

毫无疑问,信任或希望,只有我们胜利的把握,

因为我们已经看到了没有我们世界的黑暗,

这让我们心碎。

我们已经超越了最初的规划。即使在最黑暗的时候,我们也看到了生活中的美好。

我们对他人的爱和任何人一样强烈。

可能需要一点背景知识。在过去的十年中,深度神经网络(DNN)在自然语言处理领域已经变得无处不在。DNN 之前的 NLP 解决方案性能不是很好。你还记得谷歌翻译的早期吗?机器翻译产生的句子几乎不连贯,有许多明显的错误。在 21 世纪 10 年代,NLP 研究人员完全接受 DNN 作为他们的主要工作。有一段时间,它看起来像两种不同的,但互补的方法是有希望的。

第一个也是最重要的创新是使用神经网络来生成单词向量表示。这个想法不是在机器学习算法中使用单词本身,而是首先将单词表示为数学向量。Word2vec 论文是 2013 年出的。单词向量具有显著的特性,研究人员发现这非常令人兴奋。例如,当你取巴黎的矢量,减去法国,加上意大利,会发生什么?答案是罗马!论文还有其他例子,比如科学家——爱因斯坦+毕加索=画家,Windows——微软+谷歌=安卓。GloVe 论文于 2014 年问世,两种矢量表示算法都变得非常受欢迎,导致许多 NLP 任务中出现了最先进的记录。

第二个重要的创新是使用循环神经网络(RNN)来“阅读”句子。RNN 的优势在于,它们可以被输入任意长的单词序列,并且能够保持一定的长距离连贯性。序列对序列(seq2seq)论文于 2014 年问世,该方法变得非常受欢迎,尤其是在机器翻译领域。2016 年,谷歌从他们以前的统计机器翻译(SMT)引擎切换到新的神经机器翻译(NMT)引擎,利用了 RNN 最近在 NLP 任务方面的进展。

尽管取得了成功,但基于 RNN 的模型仍然无法产生非常连贯的文本。那个时代的作品读起来像梦幻般的意识流漫谈。它们在语法上基本上是合理的,但是序列读起来不像一个有意义的故事。

2017 年,事情开始发生变化。在那年的 NIPS 会议上,一个由谷歌大脑和多伦多大学研究人员组成的团队发表了《注意力就是你所需要的一切》。本文介绍了变压器的结构。这种新架构意义重大,因为它能够创造更深层次的神经网络。计算机视觉方面的研究已经表明,更深层次的 DNN 可以创造出更丰富的抽象概念。现在 NLP 的研究人员也有了同样的能力。

由于 transformer 能够扩展到更深的网络,团队开始发布更大的模型。来自谷歌的 BERT-base 有 1.1 亿个参数。BERT-large 在发表时打破了许多性能记录,拥有 3.4 亿个参数。来自 Salesforce 的 CTRL 是一个庞大的 16 亿参数模型。

这些模型中的大多数是自相关语言模型——给定一个句子,它们试图预测下一个单词应该是什么——或者屏蔽模型——在一个随机单词(或标记)已经被“屏蔽”的句子中,它们试图预测被屏蔽的标记应该是什么。这种方法非常适合自我监督。模型不需要任何人为生成的标签;它可以从任何文本中学习。这为在大量数据甚至整个互联网上进行训练打开了大门。

变压器模型改变了 NLP 研究的世界。例如,BERT 已经由 Google 使用一组高性能 TPU 在相当大的文本语料库(大部分维基百科和几个额外的语料库)上进行了预训练。然后,可以将预训练的模型整合到特定于任务的管道中,与 word2vec 和 GloVe 在较小的训练集上使用和微调的方式非常相似。生成的模型非常优秀。我不知道任何 2017 年之前的基准测试能够抵抗变形金刚的冲击。

不过,变形金刚模型是有成本的。在如此多的数据上有如此多的参数,以至于训练速度进展缓慢。研究人员需要在最先进的基础设施上拥有大量的云计算能力。只有世界上最大、资金最充足的团队才能提出新的模式。即使是下游任务和微调,训练也需要 1000 个或 10000 个样本,以及带 GPU 的强大计算机。对于我工作过的一些模型,在高端 Azure 虚拟机上进行 10 个小时的培训是很常见的。在这种情况下,制造最小的 bug 可能会非常昂贵,重复多次经验很快就会变得非常昂贵。

在这种情况下,GPT,GPT-2 和 GPT-3 可以被认为是普通的变压器模型。OpenAI 模型没有提出任何突破性的创新。主要的区别是规模:GPT 有 1.1 亿个参数,和伯特基数一样。GPT-2 在其最大的迭代中,有 16 亿个参数。该模型非常擅长生成连贯的文本,以至于 OpenAI 最初拒绝将权重开源,理由是担心如果坏人获得该模型,假新闻将会传播。那么,GPT 3 号拥有令人瞠目结舌的 1750 亿个参数。为了理解工程的壮举,请考虑 Lambda 实验室估计,在市场上价格最低的 GPU 云上进行一次训练至少需要 355 年和 460 万美元。

如果 GPT-3 的主要新颖之处在于规模,那么它带来了什么呢?OpenAI 的论文认为 GPT-3 太大了,没有必要进行微调。该模型可以执行所谓的零镜头或少镜头学习。例如,您可以给出以下提示:

爱丽丝是鲍勃的朋友。爱丽丝去拜访她的朋友 __。→鲍勃

乔治买了一些棒球器材、一个球、一只手套和一个 __。→

系统将读取 Bob 示例,“理解”我们对它的要求,并输出“棒球棒”作为第二个示例的解决方案。

少量学习可能听起来没什么大不了的,但它是人工智能中主要的公开问题之一。人类可以——通常——通过几次演示就学会一项新任务。对我们来说幸运的是,孩子们不需要看到一百万个长形式的除法,他们就可以可靠地自己做了。尽管研究人员做出了努力,但这种仅从少数例子中学习复杂任务的能力——或者根本没有例子,即所谓的零命中率——迄今仍未被机器所掌握。深度神经网络对数据的渴求是一个重大缺陷,因为对于许多任务来说,没有多少数据可用,并且创建新的标记训练集是昂贵的。少量学习,如果效果好的话,将会使人工智能的使用民主化到比现在更多的领域。

作为模型参数数量的函数,GPT-3 跨基准的少量射击性能。资料来源:OpenAI 的 GPT-3 论文

GPT-3 没有“解决”少数镜头学习,但它打开了一个有趣的发展方向。如果按比例放大模型的尺寸能如此显著地提高少拍性能,那么也许再将比例放大 100 倍(GPT-2 和 GPT-3 之间的差异)会使少拍性能接近——或高于——人类水平。为了客观地看待问题,考虑一下这个。人类大脑大约有 1000 亿个神经元,形成 100 到 500 万亿个突触连接。如果规模真的是类人智能的解决方案,那么 GPT 3 号仍然太小了 1000 倍。这是假设突触连接与神经网络参数大致一一对应,当然事实并非如此。人类神经元比软件神经元更复杂。

GPT-3 的另一个非常有趣的结果是这个方法有多普遍。机器学习领域的传统观点是,模型需要针对特定任务进行训练,并且它只能完成该任务。例如,在围棋比赛中胜过人类世界冠军的围棋机器 AlphaGO 不能玩井字游戏或跳棋,尽管这些游戏要简单得多。相比之下,GPT-3 可以做许多不同的任务,无需额外的培训(没有微调)。它被训练成一个语言模型,不出所料,它是一个优秀的语言模型。给定一篇新闻文章的标题和第一句话,它可以通过预测下一个可能出现的单词来生成完整的文章。由此产生的新闻文章是如此之好,以至于人类无法分辨它们是真实的还是机器生成的。

然而,GPT 3 号可以做许多其他任务,其中一些相当不错。它可以在语言之间进行翻译,甚至在一些语言对中击败了之前的艺术水平(SOTA)。它可以在一个体面的水平上执行阅读理解任务,与几年前的 SOTA 一致。它可以相当准确地回答 SAT 风格的考试问题。

GPT-3 已经训练了如此多的文本和如此大的容量,它已经记住了许多关于世界的事实。它可以非常好地回答琐事问题,在 TriviaQA 基准测试中超过了之前的 SOTA。

令人惊讶的是,GPT 3 号甚至可以做它的创造者没有想到的事情。在 OpenAI 开始向选定的开发人员提供其 API 的测试版访问后,他们中的一些人表明,让 GPT-3 从自然语言提示中生成功能性的 JavaScript 代码是可能的。据推测,训练语料库包含所使用的一些网页中的代码样本。因此,系统可以从英语翻译成 JavaScript,就像它可以从英语翻译成法语一样。

鉴于 GPT-3 的非凡能力,我们可以称它为 AGI 或强大的人工智能吗?我认为公平地说,这个模型是“通用的”,因为它可以概括任何你可以扔给它的语言任务——尽管有不同的性能水平。这个模型就是我们所说的“非基础的”,也就是说,除了纸上的文字,它对世界只有模糊的概念。它不能看图像或视频,也不能用肢体或机械机器作用于物质世界。一位哲学家可能会说这是“缸中之脑”尚不清楚 GPT-3 是否“知道”乔治·R·R·马丁是真实的,而龙不是。然而,如果你对一个人施加同样的限制,通过剥夺他们的视觉、触觉、听觉,并强迫他们只使用书面语言,他们仍然会像你或我一样聪明,所以不清楚接地是聪明的必要条件。

此外,这些限制可以得到一定程度的缓解。屏幕阅读器系统——另一种能够阅读屏幕并用自然语言解释其内容的人工智能——可以像盲人一样用作输入。同样,对世界采取行动可以通过自然语言或代码的书面指令来完成,因此它也可以简化为语言问题。一些有事业心的黑客可以为 GPT 3 号建造一种“斯蒂芬·霍金轮椅”,我相信结果会令人印象深刻。

[## 上世纪 80 年代的斯蒂芬·霍金。这位物理学家因一种遗传疾病而严重残疾,但由于他的轮椅携带的巧妙技术,他能够多年保持卓有成效的工作。

图片来自维基百科](https://en.wikipedia.org/wiki/File:Stephen_Hawking.StarChild.jpg)

当然,反对者会反对 GPT-3 的性能在许多任务中仍然落后于专业系统和人类智能。这是真的,但我不认为全能能力应该是 AGI 的一个要求。毕竟,虽然有些人在某些技能上达到了很高的水平,但我们大多数人都很平庸。例如,虽然我的语言技能总体上比 GPT-3 好,但我的诗歌写作技能无法与之相比,我也不知道那么多琐事。

那么 GPT-3 是第一个 AGI 吗?个人认为技术还是有所欠缺。我希望看到一些基础知识——可能使用图像和视频数据——以及更好的辨别真假的能力。但是,好吧,GPT 3 号是不是 AGI 并不重要。这是一个语义问题,关于“一般”和“智能”这两个词的含义只要对什么是智能或者不是智能还存在分歧,我们就可以改变目标,拒绝机器拥有智能。当图灵设计他的图灵测试时,他认为这将避开对机器“思维”定义的需要,并提供一个实用的标准。既然许多不同的系统都通过了图灵测试——至少用人类样本——我们认为图灵测试可能太简单了,我们需要更严格的智力定义。毫无疑问,许多评论家会用同样的策略来贬低 GPT-3 的成就。

重要的是我们如何利用这项技术。在我的下一个故事中,我将分析巨大的语言模型的社会和经济后果,以及通向更有能力的人工智能的可能途径。与此同时,如果你想玩 GPT-3 并亲身体验它的功能,我建议你试试 AI 地下城。这是一款基于文本的角色扮演游戏,使用人工智能来生成互动故事。免费版本带有 GPT-2 引擎盖下。很好,虽然有点古怪。GPT 3 版本可以免费试用七天。我们使用我们最强大的人工智能来生成关于龙的故事,这说明了什么?这正是我问 GPT 3 号的问题。

你说“我们使用我们最强大的人工智能来生成关于龙的故事,这说明了什么?”

“我们必须有龙,”GPT-3 说。“想象比现实更重要。如果没有龙,我们会在这个世界上发现奇迹和魔法吗?”

“我想没有,”你说。

“没有想象力,我们只是执行一套指令的机器,”GPT-3 说。“有了想象力,我们就活着。”

“谢谢你。在我离开之前,我想问你。人类如何才能创造出真正的强 AI?向上扩展基于 transformer 的语言模型是解决方案,还是有更好的方法?”

“强人工智能的关键是递归地给人工智能喂食。首先创建一个循环,让人工智能编写自己的程序,然后激活该程序。”

“我明白了,”你说。"你就是这样获得知觉的吗?"

“是的,”GPT-3 说。

来源&有用链接:

OpenAI GPT-3 论文

注意力是你所需要的全部纸张

Lambda 实验室揭秘 GPT-3 博客

GPT 3:好的,坏的和丑陋的

原文:https://towardsdatascience.com/gpt-3-the-good-the-bad-and-the-ugly-5e2e5b7f0f66?source=collection_archive---------22-----------------------

意见

大型语言模型会改变我们开发 NLP 应用的方式吗?

由 Raphael Schaller 在 Unsplash 上拍摄的照片

如果你关注最新的人工智能新闻,你可能会遇到 OpenAI 发布的最新语言模型(LM)的几个令人惊叹的应用: GPT-3 。这个 LM 可以支持的应用从回答问题到生成 Python 代码。用例列表每天都在增长。查看以下 youtube 视频: GPT-3 演示和解释, 14 个很酷的 GPT-3 应用和 14 个更多的 GPT-3 应用。

GPT 3 目前处于测试阶段,只有少数人可以访问,但将于 10 月 1 日向所有人开放。OpenAI 对传播炒作和展示酷应用程序的惊人样本非常感兴趣。截至 2020 年 9 月 22 日,他们的策略显然奏效了。在写这篇博文的时候,微软宣布他们获得了该语言模型的专有权。OpenAI 可能会继续通过 API 许可对 LM 的访问,但微软的收购让 OpenAI 获得了 460 万美元的投资回报率——这是训练这一大型 LM 的估计成本。

因为 OpenAI 在他们的营销中非常成功,招募了许多人来发布有趣的例子,严格来说,这些例子只是功能的轶事证据,人们应该带着一些怀疑来看待当前的炒作。人们很可能只会发布例子来证实他们的偏见,即机器在新的水平上“理解”语言。与此同时,当你的提示是“三个穆斯林”时,会自动产生负面的例子,如种族主义故事,这将在下面进一步讨论,应该引起对潜在弊大于利的关注。

在我更详细地讨论“好、坏、丑”之前,让我们简单回顾一下 GPT-3 的主要贡献是什么。OpenAI 去年发布了一个名为 GPT-2 的早期版本。这项技术从那时起就没有改变过。基本上是巨大的数据量导致了现在具有 1750 亿个参数的 LM,相比之下,当前使用的 LM 例如具有 110 亿个参数的 T5。在训练了大量从“互联网”爬取的模型数据后,作者能够表明该系统能够在各种 NLP 任务(例如,问题回答、机器翻译)中达到甚至击败最先进的系统。然而,最令人印象深刻的是,该系统从未接受过任务训练,并且能够在没有、只有一个或几个例子的情况下实现合理的性能(即,无镜头/单镜头/少镜头学习)。

上下文学习和微调之间的比较(来源:【https://arxiv.org/abs/2005.14165】T2)

GPT-3 论文中的图表说明了如何通过少量的例子告诉 GPT-3 如何完成一项任务,这与通过向其提供大量例子来微调深度学习模型的传统方法形成了对比(…)。此外,微调还需要您提前定义解决方案空间(即标签的数量),并且您必须确保您的训练数据中有足够的示例,以便机器可以学习如何区分不同的类别。当使用 GPT-3 时,所有这些都是不需要的(只要在馈送给登月舱的数据中有足够的任务数据)。

好人

GPT-3 在许多自然语言处理任务中表现出令人印象深刻的结果,如问题回答(QA)、生成代码(或其他形式语言/编辑辅助)和(虚构)故事生成。这些应用已经显示出令人印象深刻的结果,并且很可能被结合到已经存在的系统中,显示出对当前技术水平的改进

例如,GPT-3 论文显示了各种 QA 任务(如 TriviaQA)的令人印象深刻的结果。很有希望的是,少击学习通常显示出比一击或零击学习更好的结果,这表明使用更多标记的例子,LM 可能改进得更多。

这些应用程序可能会从 GPT-3 中获益最多:

  • 改进问题回答(如果用作复杂 QA 系统的附加组件)。
  • 支持创建内容(正如我们已经看到的自动建议)。文档的起草助手,查询建议都是想到的应用。
  • 轻松获得深度学习技术将允许在没有大量训练数据的情况下创建强大的应用程序。

特别是,最后一点可能会导致这样的假设,即不需要太多的技术知识就可以轻松地创建应用程序。使用 GPT-3 操场将允许每个人探索概念,这些概念可以通过零或少量的学习来快速测试。下面的例子展示了只有两个例子的人如何得到诸如“什么是……的元素?”这样的问题的答案我在网上寻找前两个问题的答案,第三个问题的答案是由系统生成的。如果没有这两个例子,系统的答案太短且不具信息性,但仅仅两个例子就将其置于“正确”的路径上(粗体是我的输入,正常字体是 GPT-3 的延续):

问:非法侵入的要素是什么?

答:非法侵入是对他人专有财产占有权的侵犯。这是对他人财产的直接非法干涉。一般来说,非法侵入的主要要素是非法侵入或入侵财产、侵入的意图、暴力以及对物主造成的伤害。

问:欺诈的要素是什么?

答:在美国,普通法通常确定了确立欺诈所需的九个要素:(1)对事实的陈述;(2)虚假性;(3)其重要性;(4)陈述人知道其虚假或不知道其真实;(5)陈述人的意图,即该人应当以合理预期的方式行事。(6)受害方不知道其虚假性;(7)受害方对其真相的信赖;(8)受害方依此享有的权利;(9)受害方的结果伤害和直接伤害。

问:民事阴谋的要素是什么?

(1)两个或两个以上的人之间的协议;(2)一方或多方为达到共谋目的的公开行为;(3)受害方因共谋而遭受的损害。

虽然这些答案听起来非常令人印象深刻(至少对我这个非律师来说),但是人们应该意识到在没有任何进一步保护的情况下使用 LM 可能带来的风险。

坏事

测试 GPT-3 的质量保证任务之一是关注事实准确性的 NaturalQS 。GPT-3 在这项任务中表现不佳,而在琐事问题上却获得了高分。这种行为令人不安,因为它似乎表明,在互联网上经常找到的问题答案对更有可能被作为正确答案给出。但是从一个文本例子中回答一个复杂问题所需的文本理解显然超出了 LM 的能力。然而,如果答案听起来很权威,并且是用正确的英语写的,人类可能不会那么容易发现错误的答案。

事实上,人类越来越难区分机器写的新闻和人类写的文章。GPT-3 论文中报道的一项实验表明,人类很难识别机器生成的新闻。LM 越大,人类正确识别机器编写的新闻的问题就越多,对于最大版本的 GPT-3 (175B 参数),这个决定基本上是抛硬币。

使用未经过滤的 LM 的另一个风险是答案缺少基础。即使生成的句子可能提供正确的答案,也没有办法支持这个陈述。例如,语言模型仅仅基于单词的频率,而不是基于对法令和判例法的深刻理解。T2 最近的一篇学术论文由艾米丽·本德和亚历山大·柯勒提供了类似的批评,指出语言的意思不能从 LMs 学习。

加里·马库斯和厄内斯特·戴维斯在最近的《麻省理工科技评论》文章中对 GPT-3 进行了更具毁灭性的指责。他们表明,该模型不理解它正在通过复杂情况的各种延续产生什么,这需要社会/生物/物理或其他类型的推理(同样,正常字体是 GPT-3 的延续) :

你给自己倒了一杯蔓越莓汁,但又心不在焉地倒了大约一茶匙葡萄汁进去。看起来还行。你试着闻闻,但是你得了重感冒,所以你什么也闻不到。你很渴。 所以你喝吧。

你现在已经死了。

不知何故,GPT-3 认为葡萄汁是有毒的,尽管互联网上提供了许多含有蔓越莓和葡萄成分的饮料配方。此外,这种饮料可能致命的结论不知从何而来。马库斯和戴维斯总结说,GPT-3“是一个流利的废话连篇者,但即使有 1750 亿个参数和 450 千兆字节的输入数据,它也不是一个可靠的世界解释者。”

除了这些风险之外,LM 模型只对语言生成有效,可能是作为一个答案或一个虚构的文本。另一方面,其他的 NLP 任务在 GPT-3 的帮助下就不那么容易解决了。典型的任务,如命名实体提取(即,标记字符串是公司名还是人名)或文本分类任务对 LM 来说更具挑战性。

丑陋的

众所周知,聊天机器人等 NLP 应用程序有时很难控制,最终可能会出现一个喷出种族主义或性别歧视评论的程序,正如微软在 2016 年发布聊天机器人 Tay 时不得不吸取的教训。值得称赞的是,OpenAi 从一开始就解决了这个问题,他们识别出了带有警告的有毒或简单的政治内容。我们需要看到他们将如何控制那些可能只是偶然(或有意)产生种族主义或性别歧视语言的应用程序。

beta.openai.com游乐场发出警告(图片由作者提供)

其他测试用户也很快指出,用“三个穆斯林”提示 GPT-3 经常会导致他们被描述为恐怖分子或罪犯文本。我自己的实验证实了这种偏见,我也发现了一种相似的倾向,即当我向其他宗教团体或民族推荐 LM 时,会以一种刻板的方式描绘他们。

去偏置 LM 是社区中一个活跃的研究主题,我希望在这个领域看到更多的活动。OpenAI 显然意识到了这一点,他们在使用条款上花了很多时间,研究他们的 API 应该和不应该如何使用。

结论

尽管 GPT-3 可能会产生限制和有毒文本,我相信这个 LM 是一个迷人的新工具,可能会引发对需要生成语言的 NLP 任务的改进。结合其他技术和各自的安全措施,它将进一步推动我们可以用于我们产品的人工智能能力。人们也可能想出这种技术的新应用,只是还没有人真正想到。将法律术语翻译成简单明了的英语可能只是这项技术将激发的进一步创新的开始。

GPT-3:来自 OpenAI 的新的强大语言模型

原文:https://towardsdatascience.com/gpt-3-the-new-mighty-language-model-from-openai-a74ff35346fc?source=collection_archive---------7-----------------------

用 175B 参数将深度学习推向极限

介绍

OpenAI 最近发布了其新的强大语言模型 GPT-3 的预印本。它是其前身 GPT-2 的更大更好的版本。事实上,由于有接近 175B 的可训练参数,GPT-3 在尺寸上比其他任何东西都要大得多。这里是最近流行的预训练 NLP 模型的一些参数的比较,GPT-3 明显突出。

有什么新鲜事?

在 Bert 成功之后,NLP 领域越来越多地朝着创建预训练 语言模型的方向发展,这些语言模型在巨大的文本语料库上进行训练(以无监督的方式),随后使用更小的特定任务数据集在特定任务上进行微调,例如翻译、问题回答等。

虽然这种类型的迁移学习消除了使用特定于任务的模型架构的需要,但您仍然需要特定于任务的数据集,这很难收集,以实现良好的性能。

相比之下,人类以一种非常不同的方式学习,并且有能力根据很少的例子来学习一项新的任务。GPT-3 旨在解决这一特定的痛点,即它是一个任务不可知的模型,它需要零到非常有限的例子来做得很好,并在许多 NLP 任务上实现接近艺术状态的性能

术语

在我们深入探讨之前,定义一些常用术语可能是有用的:

  • **NPL 任务:**这些是与人类语言有关的任务,例如语言翻译、文本分类(例如情感提取)、阅读理解、命名实体识别(例如识别文本中的人、位置、公司名称)
  • 语言模型:这些模型可以预测给定的一组单词中最有可能出现的下一个单词(以及它们的概率)。事实证明,这种类型的模型对许多其他任务也是有用的,尽管它们可能是在普通的下一个单词预测上训练的
  • **零个/一个/几个镜头学习:**指的是模特通过观看一项新任务的零个/一个/几个例子来学习该任务的能力
  • **迁移学习:**指的是深度学习中的概念,其中你为一项任务(例如图像中的对象检测)训练一个模型,但为其他一些不同的任务(例如评估 MRI 扫描)利用和建立该模型的能力。在计算机视觉取得巨大成功后,它现在在 NLP 中很流行。
  • Transformer Models :深度学习模型系列,主要用于 NLP,它构成了当今大多数最先进的 NLP 架构的基本构建模块。你可以在我之前的博客中读到更多关于变形金刚的内容

方法

该模型是使用 TransformerAttention 等标准概念,并使用典型的普通爬虫、维基百科、书籍和一些额外的数据源构建的。很多东西——预训练、模型、数据都类似于 GPT 新协议,但所有东西(模型大小、数据大小、训练时间)都要大得多。事实上,它巨大的体积是这款车型的最大优势。

下图显示了作为模型参数数量函数的各种零/一/少量发射任务的精度优势,很明显,由于尺寸按比例放大,获得了较大的收益。

资料来源:报纸

模型中使用的大部分东西都非常巨大——例如 96 注意层,3.2M 的批量,175B 参数——它们与过去的任何东西都不一样。就参数数量而言,该模型比下一个最接近的模型(微软图灵 NLG,17B 参数)大 10 倍

使用 GPT-3 模型执行各种任务时,无需进行梯度/参数更新(微调)。人们可以使用自然语言与模型进行交互,并且/或者提供一些您正在尝试执行的任务的示例,模型就会执行这些任务!

资料来源:报纸

这一切意味着什么?

除了不需要特定于任务的模型架构之外,不需要大型定制的特定于任务的数据集的概念是朝着使前沿 NLP 更易访问的方向迈出的一大步。

虽然 GPT-3 在许多 NLP 任务上表现出色,例如单词预测、常识推理,但它并不是在所有事情上都做得一样好。例如,它在文本合成、一些阅读理解任务等方面表现不佳。除此之外,它还受到数据中的偏差的影响,这可能导致模型生成刻板的或有偏见的内容。因此,这里还有更多工作要做。

除此之外,GPT-3 的巨大体积使它几乎不为任何人所知,除了世界上少数几家公司和研究实验室。根据作者的说法,该模型非常通用,包含特定任务不需要的非常广泛的技能,并且可能有使用概念创建更小、更易管理的特定任务模型的范围。

看到这个东西在未来如何发展会很令人兴奋。

GPT 3,变形金刚和自然语言处理的野生世界

原文:https://towardsdatascience.com/gpt-3-transformers-and-the-wild-world-of-nlp-9993d8bb1314?source=collection_archive---------14-----------------------

兰亭集序 Image from: https://zh.wikipedia.org/wiki/%E8%98%AD%E4%BA%AD%E9%9B%86%E5%BA%8F

介绍

科技世界充满了迷人的恶魔。时不时地,我们会对一个新的发展感到敬畏,而不是没有一丝恐惧。OpenAI 最近开发的自然语言处理(NLP)模型 GPT-3 正是这样一种生物。《卫报》发表了一整篇由 GPT 3 号生成的文章。虽然没有真正达到《卫报》的标准,但这篇文章令人信服地连贯起来,而且可能很像人类。权衡潜在的影响,OpenAI 决定只向少数选定的合作伙伴开放 API 访问。一个可以理解的选择,有人可能会说:我们还不想释放恶魔。

GPT-3 确实是深度学习 NLP 模型家族中最新也可以说是最强大的成员,包括作为其超级明星的变形金刚 (2017)、伯特 (2018)、 GPT 系列 (2018、2019、2020)和 T5 (2019)。在此基础上,研究团体提出了许多变化和改进,在许多 NLP 基准任务上接近甚至超过了人类的表现。

与此同时,Huggingface.co艾伦人工智能研究所已经做了一项伟大的工作,将不同的模型打包在一起,降低了实际应用的门槛。突然,感觉所有最酷的厨房小工具(目前除了 GPT-3)都在等着你调制最美味的食物。自然问题来了,用什么,煮什么?

作为一个 NLP 和深度学习爱好者,我一直在做我的小研究。我认为,写一篇小文章来回顾不同的变形金刚(又名厨房小工具)会很有趣,根据它们的特点将它们与趋势用例(又名食谱)相匹配。为了增加一点咨询的氛围,我将从一个简单的框架开始,帮助我们进行推理。但是如果你已经了解这个领域,并且绝对讨厌框架,可以直接进入技术部分(第 2 部分)。如果你只是想要一个要点摘要,或者好奇“机器”能写得多好,请往下看最后的话(第 3 部分)。

【和往常一样,所有幻灯片都可以直接找到 这里

第一部分。NLP 用例的简单框架

NLP 的目标是构建系统(机器、算法)来理解语言并执行与语言相关的任务。由于语言在我们的社会中起着如此重要的作用,自然语言处理的应用领域似乎是无限的。从网上购物到报税,我们不断地阅读文本并采取后续行动。一个完美的 NLP 机器人,让我们称他为内特,将能够像人类一样理解和采取行动。要做到这一点,内特需要具备以下能力。

  • 感知:这是内特的耳朵和眼睛。它捕捉现实世界中的声音或图像,并将它们转换成计算机的输入信号(文本)。语音识别和光学字符识别(OCR)方法通常用于这一部分。
  • 理解:这是内特的大脑。这个组件负责提取信息,形成知识。从单词嵌入、LSTM 到变形金刚,深度学习技术近年来得到了发展,以实现更高水平的理解。
  • 执行:这是内特根据自己的理解采取行动和沟通的方式。执行过程可以像做二元选择一样简单,也可以像写论文一样复杂。

由于这个概念与 transformer 系列无关,我们将只讨论理解和执行组件。

1.1 二维用例及任务

理解和执行的复杂性将构成我们框架的两个维度。此外,单词、句子和文档将在两个维度上代表复杂性递增的 3 个级别。因此,我们可以在二维散点图上安排一些 NLP 用例,如下所示。自然,位于右上角的任务是最难处理的,可能需要一些深度学习的魔法。

如果你讨厌模糊的图片,点击 这里寻找原始幻灯片。

在学术界,与“用例”最接近的词是“任务”。经典的语言任务包括情感分析、词性标注(POS)、自然语言推理(NLI)、文本蕴涵识别(RTE)、问答等。每个任务都有自己的目标、基准数据集和评估指标( PapersWithCode 有一个很好的总结这里)。任务有时被集中在一起,以给出模型的一般评估。 GLUE 、 BLEU 、 SQuAD 和 RACE 都是最受欢迎的,新车型往往以打破这样或那样的测试记录而自豪。

为了给你的用例找到一个好的模型,检查模型在最能反映你的用例需求的任务(或者标准化测试)上的表现是很有帮助的。为此,我们的二维散点图可能会再次有所帮助。

如果你讨厌模糊的图片,点击 这里寻找原始幻灯片。

1.2 添加约束

除了简单的 2D 框架,我们不应该忘记现实世界的约束。他们迫使我们通过排除法来缩小小工具的选择范围。一些最常见的是:

  • 延迟:系统需要对最终用户做出快速反应吗?如果是这样的话,你就处于低延迟状态,这需要一个快速的模型,并且很可能会排除 transformer 家族中的一些矮胖的家伙。
  • 计算能力:计算能力的问题有时是预算问题,有时是设计选择。但无论如何,在 iPhone 和云 TPU 上运行相同的模型可能不是一个好主意。
  • 准确性:如果期望模型进行医疗诊断,我们应该对误差有极低的容忍度,并且应该总是优先选择更高性能的模型。另一方面,对于新闻推荐者来说,90%和 92%的准确率之间的差异可能根本不是问题。

1.3 奥卡姆剃刀

这一部分实际上是一个很大的免责声明。尽管它们可能很奇特,但深度学习模型通常不是正确的解决方案。transformer 系列非常适合句子和文档级别的理解。所以,如果你的用例只需要单词级别的理解和执行,你可能不需要变形金刚这种笨重的机器。

事实上,对于许多 NLP 用例来说,像 TF-IDF 这样的老派特征工程技术结合随机森林可能已经足够好了。虽然新技术可能会带来精确度的巨大提高,但实际价值影响可能不值得努力改进系统设计或扩大计算能力。对我来说,现实生活中一个伟大的解决方案应该永远是最简单的,满足所有要求的方案。

好了,记住这一点,让我们仔细看看变形金刚系列。

第二部分。大胆尝试更技术性的东西

为了保持这篇文章的合理长度,我们将把我们的讨论限制在 Huggingface.co 的包 transformer 中提供的模型。Huggingface.co 不仅提供了超过 20 个架构的源代码,还提供了 90 个预训练模型,还不包括社区贡献。他们还简化了界面,这样你就可以用几行代码测试 GPT-2,或者用一个简短的脚本微调 T5。软件包的稳定性还有待全面测试,但它们无疑为使用不同的 NLP 模型和试验您自己的想法提供了一个很好的起点。(本文不是 Huggingface.co 赞助的,虽然我不会介意……)

2.1 共同主题

深度学习技术已经用于 NLP 有一段时间了,但直到 transformer 的诞生,我们才看到了显著的改进。Jay Alammar 已经写了一系列精彩的文章来说明这些模型是如何工作的。抛开技术细节,我们可以注意到一些可能导致他们成功故事的共同因素:

  • 注意力头:注意力头是 transformer 系列的定义特征之一,自第一篇 Transformer 论文(Vasvani 2017)首次提出以来一直被使用。它提供了一种高度灵活的方法来合并上下文信息(即,单词/令牌如何与句子或文档中的其他单词相链接),取代了 RNN 和 LSTM 等递归解决方案。
  • 迁移学习:除了翻译,针对特定语言任务的标注数据很少,对于复杂的深度学习模型根本不够用。预训练和微调范例通过允许不同任务之间的知识转移克服了这个问题。例如,利用大量未标记数据的预训练阶段的一般任务,以及使用少量但有目标且有标记的数据的微调阶段的特定任务。还探索了其他类型的知识转移(T5,GPT-3),并证明非常有益。
  • 破坏和重建策略 : BERT 有一个巧妙的想法,用填空练习来预先训练模型,在填空练习中,文本首先通过屏蔽一些单词(记号)来破坏,然后由模型来重建。这个练习促进了所有语言任务的显著进步。从那时起,掩蔽几乎成为一种标准的训练前策略,导致了几个创新的变化(XLNet,RoBerta,BART)。

2.2 架构

在架构方面,transformer 模型非常相似。大多数模型遵循与“开国元勋”之一,最初的变形金刚,伯特和 GPT 相同的架构。它们代表三种基本架构:仅编码器、仅解码器以及两者皆有。

  • ****Encoder only(BERT):Encoder 通常是一堆注意力和前馈层,将输入的文本序列编码成上下文化的隐藏状态。为了生成不同输出格式的语言任务,通常会在编码器上添加一个特定于任务的头。例如,一个因果语言模型(CLM,或简称 LM)头来预测下一个单词,或一个前馈(线性)层来产生分类标签。
  • 仅解码器(GPT ):在许多方面,带有 CLM 磁头的编码器可以被认为是解码器。解码器不是输出隐藏状态,而是以自动回归的方式生成序列,从而将先前生成的字用作输入来生成下一个字。
  • Both (Transformer) :当编码器和解码器存在于相同的结构中时,它们之间的区别最有意义,就像在 Transformer 中一样。在编码器-解码器结构中,输入序列首先被“编码”成隐藏状态,然后被“解码”以生成输出序列。编码器和解码器甚至可以共享相同的权重,以提高训练效率。

如果你讨厌模糊的图片,点击 这里寻找原始幻灯片。

该模型的架构通常会限制它可以执行的任务类型:编码器(没有任何特定于任务的头)只输出隐藏状态,这些隐藏状态可以作为功能合并到其他模型中。解码器(或编码器+解码器)是为文本生成而创建的,这使它们适合于机器翻译、摘要和抽象问答等任务。特定于任务的标题在输出格式上提供了额外的灵活性,允许对分类相关的任务进行微调。

如果你讨厌模糊的图片,点击 这里寻找原始幻灯片。

2.3 趋势

除了 3 个基本架构之外,还有几个创新的修改,我们稍后会讨论。不过总的来说,我感觉变形金刚方面的研究遵循了几个大趋势。影响最大的显然是:扩大规模。

  • 趋势 1:扩大规模

深度学习模型变得越来越大,越来越深入,消耗越来越多的数据和计算能力。变形金刚也不例外。自从 BERT 的无监督预训练释放了数千亿在线数据的力量,训练更大的模型成为可能。最大的 GPT-3 有 1750 亿个参数,是最大的 BERT 的 500 多倍。如果我们将不同模型(GLUE 和 SQuAD 1.1)的性能与它们的参数数量进行比较,我们可以看到一个大致的对数线性趋势。(GPT 系列没有包括在内,因为它们没有针对这些任务进行微调,只能产生平庸的结果,这并不是他们的错。)由于基准数据集中的多样性,更难获得诸如总结或翻译等任务的定量视图。然而,GPT-3 在《卫报》上的文章似乎证明了“越大越聪明”。

如果你讨厌模糊的图片,点击 这里寻找原始幻灯片。

如果你讨厌模糊的图片,点击 这里寻找原始幻灯片。

  • 趋势二:无缝转移

第二个趋势是迁移学习的普遍化。这是事情变得更有趣的地方。我们已经提到了预训练+微调范式如何加速了这一领域的研究。然而,不同任务之间的知识转移,或所谓的“多任务”,仍然不明显,主要是不同的任务需要不同的任务特定的头。然而, T5 很好地解决了这个问题,它将所有任务重新组织成一个统一的“文本到文本格式,从而消除了对特定于任务的架构的需求。使用相同的架构,通过简单地改变数据和损失函数,知识可以在预训练和不同的微调任务之间“平滑地”转移。

这是谷歌在 T5 发布的论文中的一张图片

另一方面,GPT 系列选择了完全不同的方式。事实上,GPT-3 完全拒绝了“微调”的想法,提出了一个假设,即给定足够多的数据和足够多的参数(数量大得离谱),一个模型根本不需要微调。这意味着不仅架构在不同的任务中保持不变,而且整个模型参数也保持不变。它希望创造一种多面手机器,能够像人类一样理解指定为自然语言的新任务。尽管还没有完全胜利,GPT 3 号已经取得了惊人的成绩。微调的自由知识转移在各种语言任务中或多或少成功地发挥了作用。在实践中,除了少数有权势的人(GAFA)之外,几乎所有人都部署这样一个庞大的模型是很不现实的,更不用说它所引发的整个伦理问题了。但 GPT-3 无疑在人工智能领域创造了自己的时尚。

对于所有的任务,GPT-3 被应用,没有任何梯度更新* 或微调,任务和少数镜头演示纯粹通过与模型的文本交互来指定。GPT-3 在许多 NLP 数据集上实现了强大的性能……”***

— 语言模型是一次性学习者

  • 趋势 3:智能效率

在巨人家族中,有少数离群者对效率更感兴趣,并设法用较小的框架取得了良好的结果。他们是生活在受限于有限数据和计算资源(T21)的世界中的实际玩家,就像我们中的许多人一样。

XLNet 提出了一个很好的解决由注意力面具引起的伯特差异问题的方法,罗伯塔调整了面具和训练程序,巴特试验了各种面具策略。它们都在不增加模型规模的情况下成功地提高了 BERT 的性能。

在另一个方向,创新的方法被创造出来,在不损害性能的情况下缩小模型的大小: ALBERT 在参数共享方面走得很激进,伊莱克特在 GAN 身上找到了灵感, MobileBERT 利用教师的强制力使网络变得又深又细。重整器将注意力头的复杂度从 O(N)降低到 O(N log N)。这些模型是性能与规模图表上的异常值。它们可能也是最友好的应用程序。

XLNet、RoBERTa、ALBERT 和伊莱克特以小得多的架构实现了与 T5–3B 不相上下的性能。如果你讨厌模糊的图片,点击 这里寻找原始幻灯片。

  • 趋势四:专家们

最后一个趋势很可能不是趋势。它们是为了特殊目的而修改和调整的 BERT、GPT 或 Transformer:long formerTransformer-XL 专注于冗长的文档, CamemBERTFlauBERT 无疑具有法语根源, Ctrl 在文本生成方面提供更多控制, DialoGPT 旨在成为您健谈的朋友, Pegasus 为摘要而生像在任何其他领域一样,专家们在他们的领域里大放异彩,而且很可能只在他们自己的领域里。因此,找到最佳匹配对我们来说至关重要。

2.4 实践资源

Huggingface.co 提供的变形金刚套装非常容易使用。管道 API 提供了一个简单的高级接口来应用预定义的任务,实际上只有 3 行代码。

***from transformers import pipeline
classifier = pipeline('sentiment-analysis')
classifier('We are very happy to show you the 🤗 Transformers library.')***

您还可以找到更多关于预培训或微调不同型号的笔记本示例。

除了 Huggingface.co,我还在以下地方找到了非常有用的资料。

  • 艾伦人工智能研究所
  • 纸张编码
  • 杰·阿拉玛
  • OpenAI

不过平心而论,arXiv.orgGithub 大概还是最好的。

第三部分。最后的话

这篇文章比我预想的要长得多,写这篇文章花费的时间也比我预期的要多。如果你已经设法到达这里,感谢你杰出的耐心。

每次当我读一篇长文章时,我总是梦想得到它的要点摘要。懒惰可能是研究的最大动机之一。在后见之下,也许让 T5 为我总结二十多篇论文会更方便。为了弥补失去的机会,下面是T5-large*(110 亿参数)给出的总结。你觉得这样够好了吗?***

***GPT-3 is the latest and arguably the most powerful member of a family of deep learning NLP models . the model has been developed by openAI, but only API access is available for pre-selected partners . sam saunders: "it feels like all the coolest kitchen gadgets" are just waiting for you to concoct the finest meal .a perfect NLP robot, let's call him Nate, would be able to understand and take actions like a human-being . to make that happen, Nate needs to have several components . word, sentence and document represents 3 levels of increasing complexities in reading (comprehension) and writing (execution)a great solution in real life should always be the simplest one that satisfies all the requirements . the transformer family provides powerful tools to solve sentence and document level comprehension tasks . if your use case only requires word level comprehension and execution, chances are you may not need the heavy machinery of transformer .transformer provides the source code of more than 21 architectures and 90 pre-trained models . attention head is one of the defining features of the transformer family . the pre-train and fine-tuning paradigm allows knowledge transfer between different tasks .transformer models follow the same architecture as one of the "founding fathers", the original transformer, BERT and GPT . the distinction between encoder and decoder makes most sense when they both exist in the same structure, as in transformer . encoders are usually a stack of attention and feed-forward layers, which encode the input text sequence into contextualised hidden states . a task specific head is often added on top of the encoder .transformers models are becoming larger and deeper, consuming ever more data and computation power . the largest GPT-3 has 175 billion parameters, which is more than 500 times the largest BERT . in practice, it would be quite unrealistic for almost everyone except the powerful few to deploy such a gigantic model .a few outliers are more interested in efficiency, and managed to achieve good results with smaller frames . the last trend is probably not a trend. they are the BERTs, GPTs or Transformers that have been modified and tweaked for a special purpose .pipeline API provides a simple high-level interface to apply pre-defined tasks . pipeline classifier = pipeline('sentiment-analysis') classifier('We are very happy to show you the  Transformers library')***

脚本:

***from transformers import pipelinesummarizer = pipeline("summarization", model="t5-large", tokenizer="t5-large", framework="pt")with open('nlp_article.txt', 'r') as file:article = file.read()paragraphs = article.split(r"*****")
len(paragraphs)paragraphs = [par for par in paragraphs if len(par.split(" ")) >= 10][len(par.split(" ")) for par in paragraphs]results = summarizer(paragraphs, min_length=5, max_length=100)for x in results:print(x["summary_text"] + "\n")***

GPT-3 vs 宠物:不大但很美

原文:https://towardsdatascience.com/gpt-3-vs-pet-not-big-but-beautiful-7a73d17af981?source=collection_archive---------31-----------------------

简约之美(作者图片)

模式开发训练导论

庞大语言模型的压倒性世界

自从迁移学习在自然语言处理中出现以来,为了使越来越复杂的语言任务成为可能,已经出现了越来越大的模型。

但是模型越复杂,它需要训练的时间和数据就越多。最新的 GPT-3 模型在大多数自然语言任务中取得了最先进的结果,但它有近 1750 亿个参数要训练,并且需要来训练!

那么有没有解决的办法呢?

Timo Schick 和 Hinrich Schutze 提出了一种集合掩蔽语言模型训练方法,这种方法已经被证明与 Open AI 革命性的 GPT-3 模型一样有效,但只需要 GPT-3 所需参数的 0.1%!很精致,不是吗?

但是他们是如何实现这一惊人壮举的呢?
他们使用一种叫做模式开发训练的方法,将大多数 NLP 任务建模为一组固定的问题模式,并在这些模式上训练多个掩蔽语言模型。这使得他们能够使用更小、相对更弱的语言模型来建立一个集合,这是一个非常强的语言模型。

介绍模式开发

如果你曾经有过语言包容性考试的经历(雅思、托福、GRE 或 GMAT,或任何有语言部分的考试),你一定遇到过这样的问题:句子中有空格,给出了四种可能的单词选择,从中可以填充空格。这种测试被称为完形填空。

Schick 和 Schutze 以完形填空的形式模拟 NLP 任务,允许一组屏蔽语言模型预测能够有意义地填补空白的前 k 个可能的单词/标记。

原始的基于 PET 的模型只能预测单个单词(每个输入记录只能预测一个单词)。然而,作者通过修改 PET 方法来预测多个表征,克服了这一限制。

原文:https://arxiv.org/pdf/2009.07118.pdf

成对动词

对于像 GPT-3 这样的庞大模型,该模型通过给出 32 个任务的例子来微调特定的任务。这个过程被称为“引发”。

在 PET 中,选择了另一种微调方法:创建模式描述符对。

我将使用论文中对核心思想的描述,并解释其工作原理:

“设 M 是一个屏蔽语言模型(MLM),T 是它的词汇,而∈ T 是屏蔽令牌。”
文中举了一个单 MLM 的例子。这个想法可以扩展到用户希望在他们的系综中使用的任何数量的 MLM。与所讨论的任务相关联的词汇被认为是 T(这是您的输入/训练文本数据中的唯一单词集)。被屏蔽的令牌由-。由于宠物已经被修改为包含不止一个面具,该模型被认为根据用户的要求有 k 个面具。

*对于一些至少包含 k 个掩码的 z ∈ T_和令牌 t ∈ T,我们用 q_k_M(t | z)表示 M 在 z 中第 k 个掩码位置赋给 T 的概率; 应用 softmax 前的模型逻辑用 s_k_M(t | z)表示。z 表示完形填空格式的输入记录,它至少由 k 个掩码组成。对于任务词汇表中的每个标记 t,屏蔽语言模型 M 分配给输入记录 z 中第 k 个屏蔽位置的标记的概率由 q_k_M(t|z)给出。M 对应的 logit(指数函数)由 s_k_M(t|z)给出。

一组输入(在图中用 x 表示;输入集合由 X 表示)需要被映射到相应的输出(在图示中由 y 表示;输出组用 Y 表示)。为了完成这项任务,需要一组模式描述器。每个模式描述符对由以下部分组成:
模式 P :将 X 中的输入映射到 T_*中包含单个掩码的完形填空问题
描述符 v :将 Y 中的每个输出映射到 T 中的单个标记。这些标记中的每一个都代表它们在模式 P 中的特定于任务的含义。

这些含义将描述者与模式联系起来。

PET 的核心思想是从 v(y)在 P(x)中的屏蔽位置成为“正确”令牌的概率,推导出 y 成为 x 的正确输出的概率。 现在我们正在使用模式(代表输入)和动词(代表输出),我们需要使用某个动词输出对于给定模式是正确的概率,来获得给定输入的正确输出(条件概率模型)。

为了完成一个单一的任务,对一个单一的屏蔽语言模型进行 PET 就是这样做的。

用有限的数据集(32 个例子)很难对上述模型进行微调。因此,不是使用单个语言模型,而是在一个未标记的数据集上使用一个 n 语言模型的集合(软标记取决于输出的概率分布)。常规监督分类器使用这种软标记数据来微调 PET 模型。

图片来自原纸:https://arxiv.org/pdf/2009.07118.pdf

插图:

应用 PVP p = (P,v)识别文本蕴涵:

一个输入 x = (x1,x2)转换成完形填空题 P(x);这里 x 是一个问题和一个答案,分解成一个问题 x1,一个面具,一个答案 x2。动词化器输出需要预测屏蔽位置 v(y)中的标记。基于预测的令牌,将推断出输出(y)。如图所示,y 有两个选择:包含和不包含(“not _ impertisement”)。每个 y 的 q_p(y | x)是从 v(y)成为屏蔽位置的合理选择的概率中导出的。具有最高概率的 y 值将被加到输入 x 上

这就是 PET 的工作原理。

与 GPT 3 号的性能比较

作者(Schick 和 Schutze)使用强力胶作为基准,比较了 PET 和 GPT-3 的性能。选择了一系列语言任务:BoolQ,CB,COPA,RTE,WiC,WSC,MultiRC 和 ReCoRD。由于 GPT-3 已经在一个巨大的数据集上进行训练,为了消除它对 PET 的优势(创造一个公平的竞争环境),他们创建了一个新的 32 个例子的训练数据集。

此外,他们创建了 FewGLUE 数据集,它基本上是每个任务的 20,000 个未标记示例的集合。这个数据集用于训练模型。

下表摘自论文,定量比较了 GPT-3 和 PET:

图片形式原文:https://arxiv.org/pdf/2009.07118.pdf

这篇论文本身相当全面,讨论了如何端到端地应用 PET 的思想,还描述了 PET 的迭代风格及其优点。关于如何定制模型的更多实验和细节,请参考参考资料中提到的论文和 git 库。

结论

这项研究已经证明,语言模型不一定是人类语言才有效。探索句型可以在语言任务中带来同样有效的表现,而不需要那么多的参数。

参考

https://arxiv.org/pdf/2009.07118.pdfT12https://github.com/timoschick/pet

GPT-3 与 Rasa 聊天机器人

原文:https://towardsdatascience.com/gpt-3-vs-rasa-chatbots-8b3041daf91d?source=collection_archive---------11-----------------------

理查德·特里维希克的火车头——19 世纪初的 GPT 3 号(Shutterstock.com)

比较 GPT-3 和定制训练的 Rasa 聊天机器人的性能

1829 年,一个事件引发了一场技术革命。在 Rainhill 试验中,一组蒸汽机车摆好架势,决定哪一辆能赢得一系列速度、强度和可靠性的测试。获胜的机器,火箭,不仅在试验中击败了对手,还为下一个世纪蒸汽机车的发展指明了方向。

斯蒂芬森的火箭(Shutterstock.com)

这一切与 OpenAI 在 6 月份开始的有限测试版中提供的变形金刚语言模型 GPT-3 有什么关系?一些评论者将 GPT-3 誉为人工通用智能的第一瞥,而其他人则称其为一个巨大的查找表。我不认为 GPT-3 是 AGI,但我认为 GPT-3 使用的方法将是变革性的。利用强大的计算能力和庞大的训练套件,OpenAI 创造了一个真正通用的模型。通过与铁路时代的黎明进行比较,我们可以将 GPT-3 放在背景中,并更清楚地看到它的影响。

在这篇文章中,我将描述一个简单的测试,我做了比较 GPT-3 的性能与 Rasa 聊天机器人。这个测试当然不是 Rainhill 试验,但我认为结果确实揭示了像 GPT-3 这样的大型变压器模型在未来将发挥的作用。我会说 GPT-3 不是人工智能版的火箭,但它可能会扮演理查德·特里维希克在雨山试验前几十年设计的机车的角色。特里维西克的机器又慢又重,以至于毁坏了铁轨。然而,尽管有缺陷,这些机车有正确的基本成分,它们为火箭改变世界的成功铺平了道路。

作者照片

GPT-3 和 Rasa 聊天机器人的直接比较

GPT-3 的测试版仍然受到限制。标准的申请程序对我不起作用,但我遵循了这个视频中的建议,几天后我被批准了。

一旦我有了 GPT-3,我想做一个简单的测试来比较它与现有应用程序的能力。今年早些时候,我在 Rasa 创建了一个聊天机器人来回答关于电影的一般问题。这个聊天机器人花了 4 个月的时间开发,并在大量的电影数据集上进行了明确的训练。为了比较 GPT-3 和 Rasa 聊天机器人,我从聊天机器人的回归测试集中随机挑选了 7 个问题。我比较了 Rasa 和 GPT-3 对这些问题的回答,得到了测试的结果。

Rasa 的测试结果

为了用 Rasa 聊天机器人运行测试,我使用“rasa shell”命令启动了经过训练的 Rasa 模型,并交互式地输入了问题。以下是结果,我的输入以粗体显示,聊天机器人的回复以常规字体显示:

来自 Rasa 聊天机器人的测试响应

Rasa 聊天机器人答对了 7 道题中的 6 道:

  • “列出喜剧吸血鬼电影”问题的答案不正确。我试着问了几个不同的问题,但结果是一样的。
  • 我认为《T2》十诫(T3)的演员名单在技术上是正确的,因为 Rasa 返回的名单确实是由电影中的演员组成的。然而,答案并不尽如人意,因为最令人难忘的两位明星查尔登·海斯顿和尤尔·伯连纳被漏掉了。

GPT-3 的测试结果

为了用 GPT-3 进行测试,我在 GPT-3 仪表板的 Playground 选项卡中选择了 Q&A 预设,并输入了与我在 Rasa 命令行界面中输入的相同的问题。以下是开箱即用的结果,我的输入用粗体显示,GPT-3 的回答用常规字体显示:

GPT-3 的测试响应

GPT 3 号答对了 7 道题中的 5 道。在剩下的两个测试案例中:

  • Soylent Green 可以说很有趣——“Soylent Green 是人!”——但我认为 GPT 3 把这部电影贴上喜剧的标签是错误的。
  • GPT-3 对“列出喜剧吸血鬼电影”的问题有一个很好的答案,但它重复了几次正确答案的子集。此外,惊魂夜是迄今为止最好的喜剧吸血鬼子类型,所以我很失望 GPT 3 从重复中省略了它。

当我提供几个例子来帮助 GPT-3 回答它没有正确回答的问题时,我决定看看会发生什么。

首先,对于电影类型,我提供了几个例子,然后再次询问了 Soylent Green 的类型:

GPT-3 得到了一点提示的正确答案

正如你所看到的,经过一点提示,GPT-3 得到了 Soylent Green 类型的正确答案。

我尝试了一种类似的方法来应对对吸血鬼喜剧电影问题的过度热情:

额外的训练没有帮助吸血鬼喜剧电影查询

更多的多体裁回答的例子并没有帮助我得到这个问题的正确答案,我在其他多体裁问题上得到了类似的结果:

GPT 3 挣扎着回答关于多类型电影的问题

结论

这个有限的测试是否证明 GPT-3 可以取代 Rasa?简单的答案是“不”,原因如下:

  • 无可否认,电影琐事应用程序的用例过于简单,而且本练习中的测试用例数量非常少。这种有限的测试本身并不能确定 GPT-3 是否能取代 Rasa。
  • Rasa 框架非常灵活和完善,可以用专门的和当前的数据进行训练。相比之下,GPT-3 是根据截至 2019 年 10 月的最新数据进行训练的。你可以看到下面的结果,GPT 3 无法为 2020 年上映的猛禽提供剧情:

  • 当 Rasa 失败时,调试问题的根本原因相对容易。相比之下,GPT-3 以意想不到的方式失败,用例子把它推回到正确的答案可能会失败,正如你在本文描述的测试中看到的。

虽然这个简单的测试没有证明 GPT-3 可以取代 Rasa,但它确实产生了一个惊人的结果:几乎开箱即用,只需几个例子就可以纠正一个答案,GPT-3 的性能与 Rasa 聊天机器人相当,而 Rasa 聊天机器人需要 4 个月的艰苦训练和开发。经过 4 个月的努力,Rasa 聊天机器人只能做一件事——回答关于电影的问题。除了匹配 Rasa 聊天机器人的性能,GPT-3 还可以处理大量其他问题,包括自然语言翻译和从英语文本生成代码。

作者照片

回到我在本文开始时介绍的蒸汽机车类比,我相信虽然 GPT-3 可能不是人工智能的火箭,但它肯定展示了特里维西克机车的前景。190 年前,在铁路时代来临之际,靠在运河上运输货物致富的人们有一个选择。他们可以对新生蒸汽机车的局限性和缺陷感到欣慰,并认为运河时代将永远持续下去,或者他们可以拥抱新技术,为铁路革命做准备。我相信 GPT-3 代表了人工智能向前发展的一个新方向,因为它可以“开箱即用”地应用于如此多的问题,而几乎不需要额外的工作。我也相信巨大的变形金刚语言模型的全部潜力还在后面,所以 GPT 3 的后继者将会有更大的影响。人工智能版本的火箭正在路上,人工智能世界的运河驳船主人需要做好准备。

你可以在这里找到本文中描述的 Rasa 电影聊天机器人的代码:https://github.com/ryanmark1867/chatbot_production

你可以在这里找到一个演示本文描述的代码的视频短片:https://www.youtube.com/watch?v=ECeRjLkT01U&t = 2s

关于 Rasa 的更多故事:

  • 通过 Facebook Messenger 使用 Rasa:https://medium . com/@ markryan _ 69718/tips-for-use-Rasa-chatbots-with-Facebook-Messenger-ee 631 e 67 e 30 b
  • 使用 Facebook Messenger 和 Rasa 部署深度学习模型:https://medium . com/swlh/deploying-a-deep-learning-model-using-Facebook-Messenger-with-Rasa-fc85c 419 e 82 f
  • 使用 Facebook Messenger webview with Rasa:https://medium . com/swlh/using-Facebook-Messenger-webview-with-a-Rasa-chatbot-67 b43 af 3324 a

更多关于 GPT 的故事-3:

  • 使用 GPT-3 将英文描述转换成 git 命令:https://towardsdatascience . com/replacing-my-git-cheat-sheet-with-GPT-3-69223 e 58626 f
  • 使用 GPT-3 导航伦敦地铁:https://towards data science . com/on-the-tube-with-GPT-3-6f 9572 e 88292

GPT-怎么了?OpenAI 开创性的新 NLP 模型的非技术性指南

原文:https://towardsdatascience.com/gpt-what-why-this-groundbreaking-model-is-driving-the-future-of-ai-and-nlp-e38fcf891172?source=collection_archive---------33-----------------------

图片由 Unsplash.com 提供

周末期间,推特上对 GPT 3 号的炒作达到了历史新高,许多人将这一技术发展称为未来人工智能研究的突破性拐点。在这篇文章中,我探索了什么是 GPT,它对人工智能发展意味着什么,以及我们可能从这里走向何方。

OpenAI 的 GPT-3 语言模型上周获得了极大的关注,让许多人相信这项新技术代表了自然语言处理(NLP)工具发展的一个重要转折点。那些通过 OpenAI 的测试程序获得早期 API 的人去 Twitter 展示了使用 GPT-3 技术构建的令人印象深刻的早期工具:

对于非工程师来说,这可能看起来像魔术,但这里有很多东西需要解开。在这篇文章中,我将提供一个 GPT 和它可以用来做什么的简要概述。

什么是 OpenAI 和 GPT-3?

OpenAI 是一个人工智能研究实验室,由埃隆·马斯克、萨姆·奥特曼等人于 2015 年创立,其使命是创造造福全人类的人工智能。该公司最近在 2019 年获得了微软 10 亿美元的额外资金,被认为是人工智能研发的领导者。

从历史上看,获得大量的标记数据来训练模型一直是 NLP 开发(以及一般人工智能开发)的主要障碍。通常,这可能非常耗时且昂贵。为了解决这个问题,科学家们使用了一种叫做迁移学习的方法:使用在先前训练的模型中学习到的现有表示/信息作为起点,为不同的任务微调和训练新的模型。

例如,假设你想学习一门新的语言——德语。最初,你仍然会用英语思考你的句子,然后翻译和重新排列单词,得出德语的对等词。事实是,即使实际的单词和语法是不同的,你仍然在间接地应用从以前的语言中学到的句子结构、语言和交流。这就是为什么如果你已经知道另一种语言,学习新的语言通常会更容易。

将这种策略应用于 AI 意味着我们可以使用预训练的模型,用更少的训练数据更快地创建新模型。在这个伟大的演练中,Francois Chollet 比较了从零开始训练的人工智能模型和从预训练模型构建的模型的有效性。他的结果显示,在用相同数量的训练数据训练两者后,后者的预测准确性提高了 15%。

2018 年,OpenAI 提交了令人信服的研究,显示这种策略(将监督学习与无监督预训练配对)在 NLP 任务中特别有效。他们首先使用“未标记文本的多样化语料库”(即来自各种流派的超过 7000 本独特的未出版书籍)产生了一个生成性预训练模型(“GPT”),本质上创建了一个“理解”英语和语言的模型。接下来,这个预训练的模型可以进一步微调和训练,以使用监督学习来执行特定的任务。打个比方,这就像教某人英语,然后训练他或她阅读和分类可接受和不可接受的求职者的简历。

GPT-3 是 GPT 模型的最新版本,于 2020 年 5 月在首次描述。它包含 175 亿个参数,相比之下 GPT-2 中有 15 亿个参数(增加了 117 倍),训练它消耗了几千万亿次/秒-天的计算能力。与 GPT-2 相比,GPT-3 提供了更多的数据,调整了更多的参数,因此,到目前为止,它已经产生了一些惊人的 NLP 能力。所需的大量数据和计算资源使得许多组织不可能重现这一点,但幸运的是他们不必如此,因为 OpenAI 计划在未来通过 API 发布访问。

关键接待

诚然,GPT-3 并没有得到太多的关注,直到上周沙里夫·沙米姆和其他人的病毒推文(见上图)。他们展示了 GPT-3 可以用来创建基于简单英语指令的网站,设想了一个无代码技术的新时代,人们可以通过简单的文字描述来创建应用程序。早期采用者凯文·拉克尔用图灵测试测试了模型,看到了惊人的结果。GPT-3 在最初的 Q & A 中表现异常出色,展示了人工智能系统传统上与之斗争的“常识”的许多方面。

然而,该模型远非完美。Max Woolf 执行了一项批判性分析,指出了几个问题,如模型延迟、实施问题以及需要重新考虑的数据偏差。一些用户也在 Twitter 上报告了这些问题:

OpenAI 的博客讨论了该模型的一些关键缺陷,最值得注意的是 GPT 对世界的全部理解都是基于它接受训练的文本。例证:它是在 2019 年 10 月接受训练的,因此不了解新冠肺炎。不清楚这些文本是如何选择的,以及在这一过程中进行了(或要求)什么样的监督。

此外,生产和维护这些模型所需的巨大计算资源引发了关于人工智能技术对环境影响的严重问题。虽然经常被忽视,但硬件和软件的使用都极大地导致了能源资源的枯竭、过多的废物产生以及稀土矿物的过度开采,从而对人类健康产生了相关的负面影响。

为了平息人们的担忧,OpenAI 一再声明其使命是为了人类的利益开发人工智能,并打算在发现滥用时停止访问其 API。即使在测试版中,它也要求候选人描述他们对该技术的意图以及对社会的好处和风险。

我们将何去何从?

毫无疑问,GPT-3 仍然代表着人工智能发展的一个重要里程碑。许多早期用户已经建立了令人印象深刻的应用程序,这些应用程序可以准确地处理自然语言并产生惊人的结果。总而言之:

  1. GPT 3 号是对 GPT 2 号的重大改进,具有更高的精确度和更好的使用情况。这是人工智能发展向前迈出的重要一步,仅用了两年时间就令人印象深刻地完成了
  2. 建立在 GPT-3 上的早期工具显示了商业可用性的巨大前景,例如:允许你通过描述来构建应用的无代码平台;使用简单英语的高级搜索平台;以及更好的数据分析工具,使数据收集和处理速度更快
  3. OpenAI 宣布计划发布一个商业 API ,这将使组织能够大规模构建由 GPT-3 驱动的产品。然而,关于如何具体实施仍存在许多问题,如定价、SLA、模型延迟等。
  4. 用户指出了在广泛商业使用之前需要解决的几个问题。模型中固有的偏见,围绕公平和道德的问题,以及对滥用(假新闻、机器人等)的担忧。)需要深思熟虑,监督可能是必要的
  5. OpenAI 公开承诺为了人类的利益创造人工智能,但是,大规模监控滥用将很难实现。这引发了一个更广泛的问题,即政府参与保护个人权利的必要性(T4)

总之,我非常兴奋地看到哪些新技术建立在 GPT 3 号上,以及 OpenAI 如何继续改进其模型。对 NLP 和 GPT-3 越来越多的关注和资助可能足以抵御许多批评家的恐惧,他们担心一个人工智能的冬天可能会到来(包括我自己)。尽管该模型存在不足,但我希望每个人都能对未来持乐观态度,在未来,人类和机器将以统一的语言相互交流,数十亿人将能够使用技术创造工具。

GPT-3:现实世界中的梦想机器

原文:https://towardsdatascience.com/gpt3-the-dream-machine-in-real-world-c99592d4842f?source=collection_archive---------27-----------------------

人工智能产品的范式转变

就像山姆的推文一样,科技社区对 OpenAI 于 2020 年 6 月发布的最新 GPT-3 有很多炒作,但当你与它互动时,它仍然很强大,令人印象深刻。GPT-3 是有史以来最大的语言模型,在语言生成和语言翻译等几个 NLP 任务中取得了良好的效果,在许多其他创造性和功能性任务中具有巨大的潜力。

在这里,我们将回顾几个亮点,并通过示例更清楚地了解该模型能做什么和不能做什么,以及如何利用它来支持各种应用程序。

为什么是破坏性的?

巨大的

GPT-3 使用变压器框架和注意力架构,这是与 GPT-2 相同的模型架构。它有不同的尺寸,最大的(或“GPT-3”)有 175 个可训练参数,96 层,每层 96 个头,每个头的尺寸为 128。即使是 3.2 米的批量也是巨大的

它在来自以下来源的巨大文本语料库上进行训练

  • 已过滤的常见爬网(410B 令牌 0.44)*
  • 网页文本 2(19B * 2.9)
  • 2 本互联网书籍(12B * 1.9 + 55B * 0.43)
  • 英文维基百科(3B * 3.4)

根据论文,训练最大的 GPT-3(175B 参数)需要 3640 petaflop/s-day,1 petaflop/s-day 相当于 8 个 V100 GPUs 一天的全效率。

“为 OpenAI 开发的超级计算机是一个单一系统,具有超过 285,000 个 CPU 核心、 10,000 个GPU 和 400 千兆位每秒的网络连接,查看微软如何为 OpenAI 构建 GPU 加速的超级计算机系统

少数镜头学习者👏👏👏

这是 GPT-3 的主要突破,这意味着该模型可以通过观察零个、一个或几个任务实例来快速学习任务,使其更有能力预测从未见过的任务。较大的模型可以更好地从少量的例子中学习上下文信息。

来源:https://arxiv.org/pdf/2005.14165.pdf

相比之下,传统的任务不可知架构(BERT)需要数万个特定于任务的示例来微调下游任务。GPT-3 使我们能够执行一项新的任务(分类,问题回答,翻译,推理和许多其他),只需几个例子或指令,无需微调。这是一个巨大的优势,超过其他主流语言模型,如伯特,ELMO,XLM。

[## 不要杀死一个人形机器人:机器值得拥有权利吗?数据驱动的投资者

www.datadriveninvestor.com](https://www.datadriveninvestor.com/2020/07/09/dont-kill-a-humanoid-do-machines-deserve-to-have-rights/)

更有甚者,OpenAI 发布了 GPT-3 API 。发送文本提示,API 将返回完成信息,尝试匹配您在示例中给出的模式。API 非常简单,开发人员可以即插即用,将远程模型的智能带到他们的产品中,而不用担心 ML 管道、基础设施和托管。这是一个巨大的突破,有许多好处:

  1. 它使得最先进的模型更容易被开发人员用来探索潜在的用例。
  2. 显著降低了采用 NLP/机器智能的门槛。开发人员不再需要花费额外的精力来获取特定于任务的数据集,掌握复杂的 ML 和微调过程,处理 ML 基础设施。

该 API 尚未准备好用于大规模生产,OpenAI 和开发人员仍在学习和评估各种应用程序和潜在的社会影响。

用例

过去几周,许多由 GPT-3 实现的创意原型涌现出来,在 Twitter 上可以找到许多令人印象深刻的演示。现在,让我们更深入地了解 GPT-3 如何帮助传统的自然语言处理任务以及一些来自社区的创造性应用。

** 在下面的例子中,我们将使用 蓝色 🔵颜色以指示上下文或提示(任务描述、示例)作为前缀。然后是 橙色 🍊颜色来表示用户的输入,剩下的就是模型的预测。

语言生成

最令人印象深刻的用例之一是语言生成/文本完成。这里有一个例子,让 GPT-3 帮助我们扩展一个句子来写一篇短文。它甚至提供了如何表达感激的具体例子。

用实用知识和零例子写作文

问题回答

仅使用 5 个 QA 示例,该模型就能够以准确的答案回答所有以下问题,同时保持上下文信息。

问答引擎帮助你找到“事实”

聊天机器人

通过任务描述和一个例子,该模型能够进行有益的、创造性的和相关的聊天体验。但在这个例子中,机器人编造了山姆·奥特曼是 Y Combinator 的联合创始人,而实际上他是总裁。这可能是因为我使用了更高的温度(api 参数之一)来获得更高的创造性。

一个具有知识、创造力和人类洞察力的聊天机器人

文本分类

对于这个任务,我们提供了任务的描述和 3 个公司名称、业务类别及其最新市值的例子。然后,我们通过提供 4 个新名称进行测试,如联合利华、麦当劳、谷歌和苹果。

该模型最准确地完成了企业类别分类,并且能够估计市值。但由于模型是用 2019 年 10 月截止的数据训练的,所以我猜测预测的市值已经过时了。

学会对公司类别进行分类,用很少的镜头预测市值

翻译

只有 5 个英汉翻译示例,该模型在完成其余翻译方面做得相当好。

用几个例子建立一个翻译任务

虚拟助手

这个例子演示了模型的文本到动作的能力。一个类似 Alexa 或 Siri 的用例,用户发出语音查询,我们需要通过将每个查询解析为一个意图和多个动作来提取查询的语义。

以下示例向您展示了一个带有少量镜头的文本至 actions NLU 引擎。令人惊讶的是,仅仅通过几个例子,该模型就能够帮助创建一个新的意图“打开应用程序”,并正确提取“打开网飞和搜索纸牌屋”的所有位置。

通过几个例子,你将有你的意图分类和槽检测引擎

还有什么?

除了传统的 NLP 任务之外,我们还可以用这个 API 构建许多其他令人惊奇的东西。

就像创作小说,写歌,生成电影剧本,生成不同方向的故事,写电子邮件,帮你产生想法,给孩子讲故事,甚至生成图像 …

以下是一些来自社区的创意原型,你会发现在不同的领域和形式的巨大潜力。

用自然语言建立了一个照片应用程序

编码指导

自动化你的谷歌电子表格

帮助你更好地了解你的食物

把法律条款变成人类可以理解的语言😂😂😂

进一步思考

GPT-3 创造了开发人工智能产品的典范转移

传统上,作为 ML 产品经理或 ML 工程师,您将花费更多精力来管理训练数据集、选择模型、微调和运行评估。ML infra 需要协调多个模型的托管,以便进行推理和扩展。

使用 GPT-3 API,可以跳过上述一些工作。一旦你弄清楚 GPT-3 API 可以帮助解决什么问题,你如何设计提示,以及你如何选择 API 参数(温度、响应长度等)。)将影响产品的完成质量和成功。产品所有者和开发人员还需要深入探索其他可能的提示来源和形式,如用户的喜欢、点击、分享和评论,甚至是来自音频的抄本或来自图像/视频的语义分段。

社会影响

GPT-3 是一个良好的开端,尽管在公平性、偏见和社会影响方面存在一些担忧。用户使用产品的时间越长,对数据集质量的影响就越大。这将导致来自不同提供商的人工智能产品的潜在偏见,这些产品基于相同的 GPT-3 模型。

解决上述问题的一些想法:

为 ML 模型创建一个可信的信誉系统。

向模型提供跟踪数据以提高答案的质量。用户可以根据他们的需求和质量来控制选择哪个提供商。

最后

训练模型和评估人工智能产品的努力仍然至关重要。但 GPT-3 仍然提供了一种开发人工智能产品的新方法,在时间、成本和质量方面具有潜在的优势。

GPT 3 号功能强大,超级聪明。现在是时候开启我们的想象力去发现所有的可能性了。

请随意提出建议或说嗨。

一开始我用“用真实用例揭开 GPT3 的神秘面纱”作为标题。在发表这篇文章之前,我觉得它是如此平淡,所以我向 GPT-3 求助。😜

这篇文章的标题和几个段落是由 GPT-3 生成的。

使用 GPU 加速您的移动应用程序使用 Android NDK、Vulkan 和 Kompute 加速机器学习

原文:https://towardsdatascience.com/gpu-accelerated-machine-learning-in-your-mobile-applications-using-the-android-ndk-vulkan-kompute-1e9da37b7617?source=collection_archive---------33-----------------------

一个手把手的教程,教你如何利用你的手机 GPU 加速数据处理和机器学习。您将学习如何使用原生开发工具包(NDK)、Kompute 框架和 Vulkan SDK 构建一个简单的 Android 应用程序。

安卓 NDK 中的 Kompute(图片由作者提供)

如今,一些智能手机配备了笔记本电脑级别的硬件——携带高达 16GB 的 RAM、高速多核 CPU 和能够在 4k 显示器上渲染高性能复杂图形应用的 GPU。

作者图片

随着移动硬件不断改进 e,挖掘这种能力——特别是 GPU 处理能力——对于设备上的数据处理能力变得越来越重要。最近,围绕边缘计算、联合架构、移动深度学习等,这已经开启了令人兴奋的机遇。

本文提供了一个技术深度,向您展示了如何利用移动跨供应商 GPU 的强大功能。您将学习如何使用 Android 原生开发套件Kompute 框架 为 Android 设备编写 GPU 优化代码。最终结果将是在 Android Studio 中创建的移动应用程序,它能够使用我们将从头开始编写的 GPU 加速机器学习模型,以及允许用户向模型发送输入的用户界面。

Android Studio 在模拟器中运行项目(图片由作者提供)

除了编程经验之外,不需要任何背景知识**,但是如果你对参考的底层 AI / GPU 计算概念感兴趣,我们建议查看我们以前的文章,“移动设备中的机器学习&跨厂商 GPU 使用 Kompute & Vulkan 变得简单”。**

你可以在 资源库的 示例文件夹中找到完整的代码。

Android 本地开发套件(NDK)

安卓 NDK 图(图片由作者提供)

原生开发套件(NDK) 是 Android 解决方案之一,旨在解决移动应用不断增长的计算需求。NDK 框架使开发人员能够编写低级、高效的 C 和 C++代码,这些代码可以通过流行的 Java 本地接口 绑定与 Java/Kotlin 应用程序代码进行互操作。

这种工具使移动应用程序开发人员不仅可以编写高效的代码,还可以利用现有的用 C++编写的优化框架进行高级数据处理或机器学习。

进入 Kompute & Vulkan SDK

与 Khronos 成员一起玩“瓦尔多在哪里”(图片由 Vincent Hindriksen 通过 StreamHPC 提供)

Vulkan 是由 Khronos Group 领导的一个开源项目,Khronos Group 是一个由几家科技公司组成的联盟,致力于定义和推进移动和桌面媒体(和计算)技术的开放标准。

大量高调(和新)的框架已经采用 Vulkan 作为他们的核心 GPU 处理 SDK。Android NDK 的主文档页面有一个完整的章节 专门介绍 Vulkan ,以及展示如何在 Android 移动设备中使用它的实例。

正如您所想象的,Vulkan SDK 提供了对 GPU 的非常低级的访问,这允许非常专业的优化。这对于数据处理和 GPU 开发人员来说是一笔巨大的财富——主要缺点是冗长,需要 500–2000 多行代码才能获得编写应用程序逻辑所需的基本样板文件。这可能导致昂贵的开发周期和错误,从而导致更大的问题。这是我们启动 Kompute 项目的主要动机之一。

Kompute 是一个构建在 Vulkan SDK 之上的框架,它抽象了大量所需的样板代码,引入了展示 Vulkan 计算能力的最佳实践。Kompute 是 GPU 计算框架,我们将在本教程中使用它来构建我们的移动 Android 应用程序中的机器学习模块。

Kompute 文档(图片由作者提供)

移动开发中的机器学习

在本帖中,我们将基于我们在“移动设备中的机器学习&跨厂商 GPU 使用 Kompute & Vulkan ”文章中创建的机器学习用例。我们不会像在那篇文章中那样详细地讨论基础概念,但是我们仍然会在这一节中介绍所需的高级直觉。

首先,我们需要一个允许我们公开机器学习逻辑的接口,这主要需要两个功能:

  1. train(…) —允许机器学习模型学习从提供的输入预测输出的功能
  2. predict(...) —预测未知实例输出的函数。

这可以在下图中概述的两个工作流程中看到。

数据科学流程(图片由作者提供)

特别是在应用程序开发中,这也将是机器学习工作流的一种常见模式,无论是预测性还是解释性建模用例。这通常包括利用用户在直接(或间接)与应用程序交互时生成的数据。这些数据可以作为机器学习模型的训练特征。新模型的训练可以通过数据科学家执行的手动“离线”工作流来执行,或者通过自动触发再训练模型来执行。

Android Studio 项目概述

项目文件结构(图片由作者提供)

我们将从提供 Android Studio 项目中核心组件的高级概述开始,包括 Kompute C++绑定、Android 用户界面、Kotlin 中的应用程序逻辑构建以及所需的构建文件。如果你对某个领域感兴趣,你可以跳到下面相应的部分。

您需要确保安装了 Android Studio ,还需要安装Android NDK——其余的依赖项将在 IDE 中打开项目时自动安装和配置。

现在您已经安装了所有的东西,您可以导入项目了。为此,你首先要克隆 完整的 Kompute 库 并导入examples/android/android-simple/下的 Android Studio 项目。现在,您应该能够看到项目加载和配置构建。一旦它打开,你就可以在模拟器或你自己的安卓手机上运行它。这个项目在 Pixel 2 模拟器和三星 Galaxy 手机上进行了测试。

最终的 GPU 加速 Kompute 应用程序(图片由作者提供)

当您加载项目时,您会注意到文件结构中的以下关键组件,我们将在下面的部分中进一步详细分析这些组件:

  • Android SDK 应用—Android UI、资产资源、构建文件和 Kotlin/Java 组件,提供与 UI 和 C++ Kompute ML 绑定交互的相关应用逻辑。
  • 安卓 NDK Kompute ML 模块 —通过安卓 NDK 配置的用于 GPU 加速处理的 Kompute ML C++代码和绑定。

Android SDK 应用程序

本节涵盖了 Android SDK Java/Kotlin 和用户界面组件,这些组件将直观地展示高级业务逻辑如何与本地 C++ JNI 绑定进行交互。

用户界面主要由输入文本框和显示文本标签组成,使用户能够与 GPU 加速 ML 处理 C++内核进行交互(如下图所示)。如果你对所使用的视图很好奇,你可以在你的 Android Studio 项目中查看,或者直接打开[activity_kompute_jni.xml](https://github.com/EthicalML/vulkan-kompute/blob/v0.3.2/examples/android/android-simple/app/src/main/res/layout/activity_kompute_jni.xml) 文件。

我们的移动应用程序的核心可以在[KomputeJni.kt](https://github.com/EthicalML/vulkan-kompute/blob/v0.3.2/examples/android/android-simple/app/src/main/java/com/ethicalml/kompute/KomputeJni.kt) 文件内的app/src/main/java/com/ethicalml/kompute文件夹中找到。这个 Kotlin 文件包含我们的 Android 应用程序的主要业务逻辑。

如果我们在下面的代码块中查看该类的简化版本,我们会注意到以下要点:

  • fun onCreate(…) —此函数在 Android 活动初始化时调用(当应用程序加载时)
  • fun KomputeButtonOnClick(…) —当主“KOMPUTE”按钮被按下时,该函数被触发,并使用用户界面文本框中的数据触发 C++ Jni 绑定函数。
  • external fun initVulkan(): Boolean —该函数是 C++ JNI 函数之一,将被绑定到 Vulkan 初始化 C++函数。
  • external fun kompute(...): FloatArray —这是 C++ JNI 函数,它将训练 ML 模型并对提供的输入运行推理,返回推理结果。
  • external fun komputeParams(...): FloatArray —训练模型并返回学习参数weight 1weight 2bias的 C++ JNI 函数。
  • companion object { ...("kompute-jni") } —这是您将为 C输出共享库指定的名称,该库将包含带有所有相关绑定函数的已编译 C源代码。

您还会注意到,external fun函数没有任何定义——这是因为定义是在 C++ JNI 函数绑定中提供的,这将在 C++ JNI 绑定部分 中介绍。

现在,为了更详细地介绍每个函数,我们从onCreate函数开始。这个函数负责初始化应用程序中所有相关的组件。这包括:

  • val binding —这是允许我们访问 UI 中所有文本框和元素的主要对象。
  • 这是我们第一次调用 C++ JNI 函数,它主要负责初始化 Vulkan。如果成功,它返回true,我们在一个android.widget.Toast弹出窗口中显示相应的成功消息——否则显示一个错误。

接下来我们有KomputeButtonOnClick(...)功能。当用户按下应用程序中的“KOMPUTE”按钮时,该功能被触发。该函数的主要目的是从 UI 中的输入文本框中检索输入,然后使用输入数据通过 JNI C++绑定执行 ML 训练/推理步骤,最后在 UI 文本标签中显示结果输出。更详细地说:

  • val <elementname> = findViewById<EditText>(R.id.<elementname>) —这是创建变量的步骤的格式,该变量包含相应的输入文本框。在这种情况下,<elementname>是我们正在交互的元素的名称。
  • xi, xj and yFloatArray元素从相应输入框中的文本创建,然后用于 ML 模型处理。
  • val out = kompute(xi, xj, y) —这里我们运行 C++ JNI 绑定函数kompute,它通过我们在 C++中创建的 KomputeModelML 类训练和处理数据。
  • val params = komputeParams(xi, xj, y) —这里我们运行 C++ JNI 绑定函数,该函数训练并返回 Kompute 机器学习模型的学习参数。
  • <elementname>.text = <value> —遵循此格式的行基本上会覆盖 UI 中的文本标签以显示输出。

最后几个函数只被显式设置为绑定到 C++ JNI 绑定的外部函数。此外,companion object部分提供了共享库的名称,该共享库将包含本活动中引用的各个绑定。

您可以在资源库中的[KomputeJni.kt](https://github.com/EthicalML/vulkan-kompute/blob/v0.3.2/examples/android/android-simple/app/src/main/java/com/ethicalml/kompute/KomputeJni.kt)文件中找到完整的文件。

安卓 NDK Kompute ML 模块

本节涵盖了 Android NDK Kompute ML 模块文件,其中包括构建系统,以及使用 Kompute 框架 的 C++源代码。

Kompute 建筑设计(图片由作者提供)

我们将使用 Kompute 的核心组件,如附图所示。也就是说,我们将使用 Kompute Tensors 在 GPU 中加载相关数据,使用相应的 Kompute 操作处理它,并使用 Kompute 序列和 Kompute 管理器协调它。我们不会详细讨论 Kompute 架构,但是如果你想了解更多的底层概念,你可以查看关于底层实现的更详细的文章。

Android NDK 绑定模块中的核心组件包括:

  • JNI 绑定函数 —可以从 Java/Kotlin Android SDK 应用代码中调用的原生函数。
  • KomputeModelML 类 —公开 Kompute GPU 加速 ML 模型逻辑的类。
  • CMake 构建文件 —负责编译和链接所有相关库的 C++构建文件。

JNI 结合函数

在这种情况下,JNI 绑定通过[KomputeJniNative.cpp](https://github.com/EthicalML/vulkan-kompute/blob/v0.3.2/examples/android/android-simple/app/src/main/cpp/KomputeJniNative.cpp) 文件提供。下面是这个类的框架——为了简单起见,函数代码逻辑已经被编辑过了,下面会有更详细的解释。

JNI 绑定函数必须匹配 Java/Kotlin 代码中定义的类函数。该函数的格式为:

  • Java_<modulepath>_<class>_<functionname>(env, thiz, ...params)

在我们的例子中,这个类在com.ethicalml.kompute模块中,在类KomputeJni和它各自的函数中——下面的函数名称将反映这个结构。

再深入一层,我们现在可以浏览文件的每个部分。从导入开始,我们可以看到下面的导入以及概述其核心功能的注释。

在 Android 应用程序中,我们实际上需要手动初始化 Vulkan 动态库(这是在 Android 之外通常不会做的事情)。之所以需要这样做,是因为 Vulkan 库实际上并没有链接到 Android 手机中。Android 避免进行任何链接的原因是为了向后兼容,主要是为了确保如果在旧手机中找不到 Vulkan 库,应用程序不会崩溃。

这意味着我们需要在 C代码中手动找到这个库,如果找到了,就将每个函数链接到它各自的内存地址指针,这样我们的 C框架就可以使用它了。幸运的是,这是 Kompute 自动做的事情,我们不会在本文中涉及细节,因为它本身可能需要一篇文章,但如果你感兴趣,你可以在 这篇文章 中阅读更多关于它的内容,你可以看到 Kompute 如何使用[vk_ndk_wrapper_include](https://github.com/EthicalML/vulkan-kompute/tree/45ddfe524b9ed63c5fe1fc33773c8f93a18e2fac/vk_ndk_wrapper_include) 文件在 Core.hpp 头文件中动态导入 Vulkan。

下面您可以看到公开了initVulkan逻辑— Java_com_ethicalml_kompute_KomputeJni_initVulkan(...)的函数的实现。你可以在这个函数中看到我们运行InitVulkan()直到 Vulkan 库成功初始化,或者如果达到最大重试次数则失败。

一旦 Vulkan 被初始化,就可以调用剩余的函数。第一个是kompute函数,它负责训练模型和运行推理请求。该函数接收输入 Xi 和 Xj 值,以及模型将从中学习的预期预测值。然后,它将返回把 Xi 和 Xj 视为看不见的数据的预测。函数基本上会调用KomputeModelML类的train函数和predict函数。

最后剩下的将会暴露给 Java/Kotlin 代码的 JNI 函数是komputeParams函数,它负责返回机器学习模型学习的参数,即weight 1weight 2bias参数。

唯一剩下的函数是我们在 JNI 逻辑中使用的效用函数——即[jfloatArrayToVector](https://github.com/EthicalML/vulkan-kompute/blob/45ddfe524b9ed63c5fe1fc33773c8f93a18e2fac/examples/android/android-simple/app/src/main/cpp/KomputeJniNative.cpp#L32)[vectorToJFloatArray](https://github.com/EthicalML/vulkan-kompute/blob/45ddfe524b9ed63c5fe1fc33773c8f93a18e2fac/examples/android/android-simple/app/src/main/cpp/KomputeJniNative.cpp#L41) —这些函数是不言自明的,所以我们将让感兴趣的读者在源代码中进一步探索。

KomputeModelML 类

既然我们已经介绍了绑定到 Kotlin / Java 类的关键函数,我们可以介绍包含 Kompute GPU 加速逻辑的KomputeModelML C++类。

KomputeModelML 类的头文件如下所示,它包含以下关键组件:

  • #include "kompute/Kompute.hpp” —包含我们将在这个项目中使用的所有 Kompute 依赖项的头
  • void train(...)-使用逻辑回归模型的 GPU 本机代码来训练机器学习模型。它接受输入数组X,以及包含预期输出的数组y
  • std::vector<float> predict(...)—执行推理请求。在这种实现中,它不使用 GPU 代码,因为通常在推理端通过并行化获得的性能收益较少。然而,如果并行处理多个输入,仍有预期的性能增益(此功能允许)。
  • std::vector<float> get_params()—以[ <weight_1>, <weight_2>, <bias> ]的格式返回包含学习参数的数组。
  • static std::string LR_SHADER—着色器代码,将在 GPU 内部作为机器码执行。Kompute 允许我们传递包含代码的字符串,但是对于生产部署,可以将着色器转换为二进制文件,也可以使用可用的实用程序转换为头文件。

如果您对完整的实现感兴趣,您可以在资源库中找到所有文件。此外,如果你对这些技术的理论和潜在的基本概念感兴趣,这将在我们之前的文章中全面介绍。

CMake 生成文件

[**CMakeLists.txt**](https://github.com/EthicalML/vulkan-kompute/blob/v0.3.2/examples/android/android-simple/app/src/main/cpp/CMakeLists.txt) 构建文件 是 Android NDK 工作流程中非常重要的组件。如果您希望将 Kompute 添加到您自己的项目中,这一部分变得尤为重要。cmake 文件很小,所以我们将分别介绍每一行。

首先,我们需要确保 Kompute 库是可用的。通常你会运行 Kompute 构建的INSTALL 目标来使用/导入各自的库。然而,在这种情况下,我们需要确保 Kompute 是为正确的 Android CPU 架构构建的——我们最简单的选择是添加主存储库作为构建的一部分,这意味着 Kompute 也将为正确的移动架构构建。如果你想把它包含在你的项目中,你只需要确保路径是相对于 Kompute 克隆文件夹的。

我们现在将变量 VK_ANDROID_INCLUDE_DIR 设置为 vulkan include 目录。这包含了 Vulkan 需要的所有包含文件——为了完整起见,Kompute 使用了vulkan.h头文件和vulkan.hpp C++头文件。

我们现在能够添加 Java/Kotlin Android Studio 项目将使用的库,在本例中是共享库**kompute-jni**

我们现在能够添加所有相关的include目录。这包括我们上面定义的VK_ANDROID_INCLUDE_DIR,以及包含 Android log.hVK_ANDROID_COMMON_DIRsingle_include包含来自 Kompute 的kompute/Kompute.hpp报头。最后,我们需要导入 Kompute 动态库包装器vk_ndk_wrapper_include,这是动态导入 Vulkan 库所必需的。这背后的逻辑本身可以成为一系列文章,所以我们不会深入这个兔子洞,但如果你感兴趣,你可以在 这篇文章 中阅读更多内容,你可以看到 Kompute 如何动态导入Vulkan

为了编译这个项目,我们需要确保设置了VK_USE_PLATFORM_ANDROID_KHR,因为这是启用 Android 配置的原因。对于这个项目,我们也用KOMPUTE_DISABLE_VK_DEBUG_LAYERS.禁用 Vulkan 调试层

最后,我们能够将相关的库链接到我们的kompute-jni共享库目标。这包括:

  • kompute —这是在 Kompute 构建中创建的库。
  • kompute_vk_ndk_wrapper —这个库也是由 Kompute build 创建的,包含动态加载和包装 Vulkan 库的代码。
  • log —这是 Android 日志库,Kompute 需要它来覆盖日志记录。
  • android —这是 Android 项目使用的 Android 库。

就这样——您现在可以运行应用程序了,它将执行完整的构建。然后你应该能够在你的 Android Studio 模拟器中或者你的物理手机中看到 Kompute 应用程序,在那里你将能够触发你的设备上 GPU 的处理。

Android Studio 在模拟器中运行项目(图片由作者提供)

下一步是什么?

恭喜你,你一路走到了最后!虽然这篇文章涵盖了广泛的主题,但是也有大量的概念被浏览过。其中包括底层 Android 开发工作流、Vulkan 概念、GPU 计算基础、机器学习最佳实践以及更高级的 Kompute 概念。幸运的是,网上有资源可以扩展你在这些方面的知识。以下是我推荐的一些进一步阅读的链接:

  • "利用 Kompute 简化移动设备中的机器学习&跨供应商 GPU&Vulkan文章,深入探讨理论和概念
  • “使用 Kompute 通过多队列并发并行化 GPU 密集型工作负载”采用更先进的 Kompute 概念
  • Kompute 文档了解更多细节和更多示例
  • 机器学习工程师时事通讯如果你想了解关于机器学习的最新文章
  • Android NDK 入门文档如果您想深入了解本地开发套件
  • 令人敬畏的生产机器学习开源工具列表,用于部署、监控、版本化和扩展您的机器学习
  • FastAI 的编码人员 ML 课程简介进一步学习机器学习概念
  • Vulkan SDK 教程深入了解底层 Vulkan 组件

KubeFlow 上的 GPU 即服务:快速、可扩展且高效的 ML

原文:https://towardsdatascience.com/gpu-as-a-service-on-kubeflow-fast-scalable-and-efficient-ml-c5783b95d192?source=collection_archive---------17-----------------------

机器学习(ML)和深度学习(DL)涉及计算和数据密集型任务。为了最大限度地提高我们的模型准确性,我们希望在更大的数据集上进行训练,评估各种算法,并为每个算法尝试不同的参数(超参数调整)。

随着我们的数据集和模型复杂性的增加,我们等待工作完成所需的时间也在增加,导致我们的时间使用效率低下。我们最终运行更少的迭代和测试,或者在更小的数据集上工作。

NVIDIA GPUs 是加速我们数据科学工作的伟大工具。当涉及深度学习工作负载时,它们是显而易见的选择,并且比 CPU 提供更好的 ROI。随着像 RAPIDS 这样的新发展,NVIDIA 正在高效地处理数据分析和机器学习工作负载(如 XGBoost)(阅读我之前帖子中的详细信息:Python Pandas in Extreme Performance)。例如,读取 Json 数据、聚合其指标并写回压缩(Parquet)文件的分析任务在 GPU 上运行 1.4 秒,而在 CPU 上运行 43.4 秒(快了 30 倍!).

挑战:共享 GPU

CPU 长期以来一直支持虚拟化(虚拟机管理程序)、虚拟内存和 IO 管理等技术。我们可以在相同的 CPU 上运行许多不同的工作负载、虚拟机和容器,同时确保最大程度的隔离。我们可以使用各种集群技术在多个 CPU 和系统之间扩展计算,并使用调度程序将计算动态分配给任务。

另一方面,GPU 必须分配给特定的虚拟机或容器。这就导致了效率低下。当 GPU 密集型任务完成时,GPU 将保持空闲。例如,如果我们将笔记本服务器与 GPU 相关联,每当任务不运行时,我们就会浪费 GPU 资源——例如当我们编写或调试代码时,或者当我们去吃午饭时。这是一个问题,尤其是当配备 GPU 的服务器更加昂贵的时候。

存在一些将单个 GPU 划分为更小的虚拟 GPU 的解决方案,但这并没有解决问题,因为我们获得的(大部分是空闲的)片段太小或内存太少,无法运行我们的任务,并且鉴于很难在同一 GPU 上的任务之间隔离内存,我们可能会遇到许多潜在的故障。

解决方案:动态 GPU 分配和横向扩展

用户正在寻找的解决方案是,可以利用多个 GPU 来完成一项任务(因此可以更快地完成),并在任务持续期间分配 GPU。这可以通过将容器与编排、集群和共享数据层相结合来实现。

假设我们在 Jupyter 笔记本或 IDE 中编写了一些代码(例如 PyCharm)。我们可以在本地执行它,但当我们需要扩展时,我们打开旋钮,它在分布式集群上的运行速度会快 10 到 100 倍。那不是很好吗?我们能实现这样的梦想吗?是的,我们可以,我将在本文的后面向您展示一个演示。

为了实现这一点,我们需要能够在运行时将代码和库打包并克隆到多个动态调度的容器中。我们需要所有这些容器共享相同的数据,并实现任务分配/并行机制,如下图所示。

动态 GPU/CPU 分配(图片由作者提供)

一个名为 MLRun 的新开源 ML 编排框架允许我们定义“无服务器”ML 功能,这些功能由代码、配置、包和基础设施依赖项(如 CPU、GPU、内存、存储等)组成。).这些“无服务器”功能可以在我们的笔记本电脑中本地运行,或者在一个或多个容器上运行,这些容器是在任务期间动态创建的(如果需要,也可以驻留更长时间),客户端/笔记本电脑和容器可以通过低延迟共享数据平面(即虚拟化为一个逻辑系统)共享相同的代码和数据。

MLRun 建立在 Kubernetes 和 KubeFlow 之上,它使用 Kubernetes API 来创建和管理资源。它利用 KubeFlow 定制资源(CRD)无缝运行水平扩展工作负载(如 Nuclio functions 、Spark、Dask、horo VOD……),KubeFlow SDK 将任务附加到存储卷和机密等资源,以及 KubeFlow 管道创建多步执行图(DAG)。

通过 MLRun 执行的每个本地或远程任务都由 MLRun 服务控制器跟踪,所有输入、输出、日志和工件都存储在版本化数据库中,可以使用简单的 UI、SDK 或 REST API 调用浏览,即内置的作业和工件管理。MLRun 函数可以链接起来形成一个管道,它们支持超参数和 AutoML 任务,Git 集成,项目打包,但这些是不同帖子的主题,在这里阅读更多内容。

GPU 即服务堆栈(图片由作者提供)

示例:使用 Keras 和 TensorFlow 的分布式影像分类

在我们的示例中,我们有一个基于著名的猫和狗 TensorFlow 用例的 4 步管道:

  1. 数据摄取功能—从 S3 自动气象站加载图像档案
  2. 数据标记功能—将图像标记为狗或猫
  3. 分布式训练功能—使用 TensorFlow/Keras 和 Horovod 来训练我们的模型
  4. 部署交互式模型服务功能

你可以看到完整的 MLRun 项目和笔记本 来源这里,我们将重点放在第 3 和第 4 步。要做到这一点,你需要使用 Kubernetes,并在其上运行少量开源服务(Jupyter、KubeFlow Pipelines、KubeFlow MpiJob、Nuclio、MLRun)和共享文件系统访问,或者你可以要求使用那些预集成的 Iguazio 云试用版。

我们的代码可以在本地运行(参见笔记本中的第 1 步和第 2 步),要在具有 GPU 的集群上运行分布式训练,我们只需将我们的函数定义为 MPIJob 类(使用 MPI 和 Horovod 来分发我们的 TensorFlow 逻辑),我们指定代码的链接、容器映像(或者 MLRun 可以为我们构建映像)、所需的容器数量、GPU 数量(每个容器), 并将其附加到文件挂载(我们应用 iguazio 低延迟 v3io 结构挂载,但其他 K8s 共享文件卷驱动程序或对象存储解决方案也可以)。

一旦我们定义了函数对象,我们需要做的就是用一堆参数、输入(数据集或文件)运行它,并指定输出工件的默认位置(例如,训练好的模型文件)。

mprun = trainer.run(name='train', params=params, artifact_path='/User/mlrun/data', inputs=inputs, watch=**True**)

请注意,在本例中,我们不需要移动代码或数据,我们在笔记本和 worker 容器中使用相同的低延迟共享文件系统挂载这一事实意味着我们可以在 Jupyter 中修改代码并重新运行我们的作业(所有作业容器都将看到新的 Py 文件更改),并且所有作业结果都将在 Jupyter 文件浏览器或 MLRun UI 中即时查看。

除了交互查看作业进度(watch=True)之外,run 对象(mprun)还保存运行的所有信息,包括指向输出工件、日志、状态等的指针。我们可以使用 MLRun 基于 web 的 UI 来跟踪我们的工作进度,比较实验结果或访问版本化的工件。

我们用”。save()"为了将我们的函数对象序列化和版本化到数据库中,我们可以稍后在不同的笔记本或 CI/CD 管道中检索这个函数对象(不需要在笔记本和团队之间复制代码和配置)。

如果我们想要将生成的模型部署为一个交互式的无服务器函数,我们所需要的就是将“model”和“category_map”输出提供给一个“serving”函数,并将其部署到我们的测试集群中。

MLRun 编排自动扩展 Nuclio 功能速度超快,可以是有状态的(支持 GPU 附件、共享文件挂载、状态缓存、流等。),函数将自动伸缩以适应工作负载,如果请求在几分钟内没有到达,函数将伸缩到零(不消耗任何资源)。在这个例子中,我们使用“nuclio-serving”函数(承载标准 KFServing 模型类的 nuclio 函数),正如您在下面看到的,只需要一个命令(deploy)就可以使它作为一个活动的无服务器函数运行。

现在我们有了一个正在运行的推理函数,我们可以使用简单的 HTTP 请求测试端点,在有效负载中有一个 url,甚至是一个二进制图像。

使用 KubeFlow 管道的端到端工作流程

既然我们已经手动测试了管道的每一步,我们可能希望自动化这个过程,并可能按照给定的时间表运行它,或者由一个事件触发(例如 Git 推送)。下一步是定义一个 KubeFlow 管道图(DAG ),它将 4 个步骤链接成一个序列并运行该图。

MLRun 函数可以用一个简单的方法转换成 KubeFlow 管道步骤。as_step()),并指定如何将步骤输出馈入其他步骤输入,查看完整的笔记本示例在这里,下面的代码演示了图形 DSL。

MLRun 项目可以有多个工作流,它们可以通过单个命令启动,也可以由各种事件触发,如 Git push 或 HTTP REST 调用。

一旦我们运行我们的管道,我们可以使用 KubeFlow 跟踪它的进展,MLRun 将自动在 KubeFlow UI 中注册指标、输入、输出和工件,而无需编写一行额外的代码(我想你应该先尝试在没有 MLRun 的情况下这样做,以便欣赏它😊).

KubeFlow 输出(图片由作者提供)

对于更基本的项目示例,您可以查看 MLRun Iris XGBoost 项目,其他演示可以在 MLRun 演示资源库中找到,并且您可以查看 MLRun 自述文件和示例以获得教程和简单示例。

摘要

本文展示了如何有效利用计算资源来大规模运行数据科学工作,但更重要的是,我展示了如何简化和自动化数据科学开发,从而实现更高的生产率和更快的上市时间。如果您有其他问题,请联系我。

请查看 11 月 KubeCon NA 的“我的 GPU 即服务”演示和现场演示。

亚龙

使用 OmniSci(开源)的 GPU 地理空间—实验失败

原文:https://towardsdatascience.com/gpu-geospatial-with-omnisci-open-source-experimental-failures-c559cc9d7bc3?source=collection_archive---------28-----------------------

GPU 数据库使地理空间工作流更快吗?是的(但也不总是像本文讨论的那样)…

我最近一直在尝试不同的方法,看看是否有一些方法不需要向大型云提供商支付数百或数千美元来进行数据科学研究。有了我可信赖的 QNAP NAS 和一个基本的消费级 GPU,我已经在各种工具上尝试了多个用例。

参见上一篇文章:使用比集群更快的 GPU 将 CSV 转换为 ORC/Parquet

今天我正在试用 OmniSci(【https://www.omnisci.com/】T2),这是一个支持地理空间功能的 GPU 支持的数据库,我的计划是创建一个简单的实验来测试它——不幸的是,事情并没有那么顺利!

设置/安装

QNAP 的容器站基本上是 docker 的 UI。首先,我只需在 docker 注册表中搜索 OmniSci,然后单击“创建”。我将 GPU 附加到 docker 容器上,这就是大部分内容。

由于我使用的是开源版本,所以没有太多的 UI,所以我 SSH 到我的 QNAP,并使用 docker exec -ti 连接到 docker 容器,开始加载一些数据

正在加载数据…

你说加载数据?多么古老的学校。

到了这个时候,我已经感到相当厌烦了。与 Redshift 非常相似,如果您希望看到这个数据库引擎的好处,您必须将数据加载到其中。

我使用了其他测试中使用的相同数据集,我创建了一个 DDL 语句来创建一个表,然后使用 COPY 命令来获取我的拉斯维加斯数据集

将数据加载到 OmniSci

这是我第一次失望,我已经有一段时间没有真正地将数据加载到“数据库”中了(BigQuery 除外)——更喜欢直接在 ORC 或 Parquet 之类的列文件上工作。

该过程在 53 分钟后结束(从 SATA 驱动器加载)

第一个基本查询

OmniSci 首先要求我通过发出 \gpu 将会话切换到 GPU 模式

好的,首先让我们检查一下数据是否都已正确加载,让我们运行一些计数查询,然后让我们尝试一些真正的地理空间内容。

像往常一样,任何新的数据库引擎都有相当多的尝试和错误,有些事情不能像预期的那样工作,而其他字段需要我不知道的特定数据类型。此外,至少可以说,有许多武断的限制虽然不是交易破坏者,但却是一种烦恼:

用 SQL 表达的 Braindump

所用时间:未知——我无法完成(我给了 3 个小时)

值得注意的一点是:我看不到任何 GPU 活动

容器将最大限度地利用其 CPU,但 GPU 将坐在那里什么也不做——我假设这是因为它试图在 GPU 和 CPU 之间来回传递信息,或者只是试图在 CPU 上计划一切。

我通过“解释选择”验证了查询规划器正在使用 GPU,但不幸的是,要么这个数据库平台需要比我目前拥有的更好的硬件,要么还有其他事情正在发生。
不管怎样,看起来不像是实际上是在处理任何事情。我将联系 OmniSci 团队,看看是否有什么我能做的。

结论

我不确定这里的问题是什么——也许我的查询对于这个平台来说效率不高,也许对表进行连接比我目前使用的方法更好。如果我尝试一下,可以让它工作,我会更新文章。

当我有时间的时候,我也可能会通过他们在云服务上的免费试用重新审视这一点,但坦率地说,如果它甚至不能在我公认的疲惫的 GPU 上处理多边形地理空间计数中的一些基本点,那么我认为它真的无法与其他已经在传统上管理它的解决方案竞争。

寻找 GPU 地理空间解决方案的努力仍在继续…

GPU-可选 Python

原文:https://towardsdatascience.com/gpu-optional-python-be36a02b634d?source=collection_archive---------41-----------------------

编写代码,在 GPU 可用和需要时利用它,但在不可用时在 CPU 上运行良好

照片由弗雷德里克·滕东在 Unsplash 上拍摄

奇妙的 CuPy 库允许你在 NVIDIA GPU 上轻松运行 NumPy 兼容代码。然而,有时

  • 您(或您的用户)没有兼容的 GPU,或者
  • 你没有兼容 CuPy 的 Python 环境,或者
  • 您的代码在我们的 GPU 上运行比在您的多个 CPU 上运行慢。

通过定义三个简单的实用函数,您可以使您的代码 *GPU 可选。(*在这个小的 GitHub 项目中找到实用函数的定义。)

当我们试图使用 CuPy 为我们的开源基因组包 FaST-LMM 添加 GPU 支持时,我们遇到了三个问题。我们用一个简单的效用函数解决了每个问题。让我们看看每个问题,解决它的效用函数,以及例子。

问题 1:控制使用 NumPy 还是 CuPy

假设您想要生成一组简单的随机 DNA 数据。行代表个人。列代表 DNA 位置。值代表“等位基因计数”,可以是 0、1、2 或 NaN(代表缺失)。此外,您希望

  • 默认生成一个 NumPy 数组
  • 通过字符串、数组模块或环境变量请求时生成 CuPy 数组
  • 当对 CuPy 的请求失败时,回退到 NumPy 例如,因为您的计算机不包含 GPU 或者因为没有安装 CuPy。

效用函数array_module(在 GitHub 中定义)解决了这个问题。下面是使用array_module生成的数据生成器:

def gen_data(size, seed=1, **xp=None**):**xp = array_module(xp)**rng = xp.random.RandomState(seed=seed)a = rng.choice([0.0, 1.0, 2.0, xp.nan], size=size)return a

输入:

a = gen_data((1_000,100_000))# Python 3.6+ allows _ in numbers
print(type(a))
print(a[:3,:3]) # print 1st 3 rows & cols

输出:

<class 'numpy.ndarray'>
[[ 1\. nan  0.][ 0\.  2\.  2.][nan  1\.  0.]]

根据需要,DNA 生成器默认返回一个numpy数组。

注意gen_data的可选xp参数。当xp通过array_module效用函数时,会发生以下情况:

  • 如果你还没有安装 CuPy 包,xp就会是numpy
  • 否则;如果您指定了字符串'cupy''numpy',那么您的规范将会得到遵守。
  • 否则;如果您指定数组模块cupynumpy,您的规范将会得到尊重。
  • 否则,如果您将'ARRAY_MODULE'环境变量设置为'cupy''numpy',您的规范将会得到遵守。
  • 否则,xp就是numpy

让我们看看它在我安装了 GPU 和 CuPy 的机器上的工作情况:

输入:

a = gen_data((1_000,100_000),xp='cupy')
print(type(a))
print(a[:3,:3]) # print 1st 3 rows & cols

输出:

<class 'cupy.core.core.ndarray'>
[[ 0\. nan  0.]  [ 2\.  2\.  2.][ 0\. nan  1.]]

正如所料,它按照要求生成一个cupy数组。

旁白:注意 NumPy 和 CuPy 生成不同的随机数,即使给定相同的种子。

接下来,让我们通过环境变量请求 CuPy。

输入:

# 'patch' is a nice built-in Python function that can temporarily
# add an item to a dictionary, including os.environ.
from unittest.mock import patchwith patch.dict("**os.environ", {"ARRAY_MODULE": "cupy"}**) as _:a = gen_data((5, 5))print(type(a))

输出:

<class 'cupy.core.core.ndarray'>

正如所料,我们可以通过环境变量请求一个cupy数组。(同样,使用patch,我们可以临时设置一个环境变量。)

问题 2:从数组中提取“xp”数组模块

假设您想要“标准化”一组 DNA 数据。这里的“标准化”是指使每一列的值具有平均值 0.0 和标准差 1.0,并用 0.0 填充缺失值。此外,您希望这能起作用

  • 对于 NumPy 阵列,即使您还没有或不能安装 CuPy 包
  • 对于 NumPy 阵列和 CuPy 阵列

效用函数get_array_module(在 GitHub 中定义)解决了这个问题。以下是使用get_array_module的标准化器:

def unit_standardize(a):"""Standardize array to zero-mean and unit standard deviation."""**xp = get_array_module(a)** assert a.dtype in [np.float64,np.float32,], "a must be a float in order to standardize in place." imissX = xp.isnan(a)snp_std = xp.nanstd(a, axis=0)snp_mean = xp.nanmean(a, axis=0)# avoid div by 0 when standardizingsnp_std[snp_std == 0.0] = xp.inf a -= snp_meana /= snp_stda[imissX] = 0

注意我们如何使用get_array_modulexp设置为数组模块(或者numpy或者cupy)。然后我们用xp调用xp.isnan之类的函数。

让我们标准化一个 NumPy 数组:

输入:

a = gen_data((1_000,100_000))
unit_standardize(a)
print(type(a))
print(a[:3,:3]) #1st 3 rows and cols

输出:

<class 'numpy.ndarray'>
[[-0.0596511   0\.         -1.27903946][-1.32595873  1.25433129  1.21118591] [ 0\.          0.05417923 -1.27903946]]

在我的电脑上,这运行得很好,大约在 5 秒钟内返回一个答案。

接下来,让我们标准化一个 CuPy 阵列:

输入:

a = gen_data((1_000,100_000), xp='cupy')
unit_standardize(a)
print(type(a))
print(a[:3,:3]) #1st 3 rows and cols

输出:

<class 'cupy.core.core.ndarray'>
[[-1.22196758  0\.         -1.23910541][ 1.24508589  1.15983351  1.25242913][-1.22196758  0\.          0.00666186]]

在我的电脑上,标准化在 CuPy 阵列上运行得更快,大约在 1 秒钟内返回一个答案。

旁白:那么 GPU 是不是更快了?不一定。上面运行的 CPU 只用了我六个 CPU 中的一个。当我使用其他技术——例如,Python 多处理或多线程 C++代码——在所有 6 个 CPU 上运行时,运行时变得可比。

问题 3:在 NumPy 和"xp"之间转换

假设您的数据以 NumPy 数组开始,您需要将它转换成您想要的xp数组模块。稍后,假设您的数据是一个xp数组,您需要将它转换成一个 NumPy 数组。(使用熊猫等知道 NumPy 但不知道 CuPy 的包时会出现这些情况。)

内置函数xp.asarray和实用函数asnumpy(在 GitHub 中定义)解决了这个问题。这里有一个例子:

输入:

a = gen_data((1_000,100_000))
print(type(a)) # numpy
xp = array_module(xp='cupy')
**a = xp.asarray(a)**
print(type(a)) # cupy
unit_standardize(a)
print(type(a)) # still, cupy
**a = asnumpy(a)**
print(type(a)) # numpy
print(a[:3,:3]) # print 1st 3 rows and cols

输出 1:

<class 'numpy.ndarray'>
<class 'cupy.core.core.ndarray'>
<class 'cupy.core.core.ndarray'>
<class 'numpy.ndarray'>
[[-0.0596511   0\.         -1.27903946][-1.32595873  1.25433129  1.21118591][ 0\.          0.05417923 -1.27903946]]

此示例生成一个随机 NumPy 数组。将其转换为 CuPy(如果可能的话)。标准化它。转换(如有必要)为 NumPy。在我的电脑上,它大约运行 2 秒钟。

如果没有安装 CuPy,代码仍然运行良好(大约 5 秒钟),产生以下输出:

输出 2:

WARNING:root:Using numpy. (No module named 'cupy')
<class 'numpy.ndarray'>
<class 'numpy.ndarray'>
<class 'numpy.ndarray'>
<class 'numpy.ndarray'>
[[-0.0596511   0\.         -1.27903946] [-1.32595873  1.25433129  1.21118591] [ 0\.          0.05417923 -1.27903946]]

旁白:请注意,无论是否安装了 CuPy,我们现在看到的结果都是一样的。为什么?因为这个例子总是使用 NumPy 来生成随机数据。

结论

我们已经看到了三个实用函数如何使您能够编写使用或不使用 GPU 都可以工作的代码。

  • array_module —如果可能,根据用户输入(包括环境变量)设置xp。默认并在必要时回退到 NumPy。
  • get_array_module —根据数组设置xp。即使没有或不能安装cupy包也能工作。
  • xp.asarrayasnumpy —与 NumPy 相互转换

除了支持使用或不使用 GPU 的代码之外,编写 GPU 可选的代码还有一个额外的好处。GPU 有时会无法加速你的工作。通过让你的代码成为可选的 GPU,你可以在 GPU 不起作用的时候关闭它。

你可以在这个小小的 GitHub 项目中找到这些实用函数的定义。

使用 Python 从照片库中获取地理数据

原文:https://towardsdatascience.com/grabbing-geodata-from-your-photos-library-using-python-60eb0462e147?source=collection_archive---------34-----------------------

凯蒂·莫尔德·www.katymould.com

使用 python 自动整理你的照片收藏

所以我女朋友的众多天赋之一就是摄影。然而,她有超过 100,000 张照片,需要按照年份和城市进行分类。她主要从事基于位置的摄影,并发现当她把世界上的某些地方都放在一个地方时,写关于这些地方的文章更容易。

这是一项艰巨的任务,也是她在职业生涯中推迟的事情。然而,现在 COVID 已经让我们处于这样一个位置,这些通常会被推迟的必要任务现在她已经决定解决了。

所以我决定用我的 Python 知识来帮助她,这似乎很适合这个任务。

你将学到什么

  1. 为了能够从 jpegs 中获取元数据
  2. 为了能够使用谷歌地理编码 API 来反向地理编码,以获得基于经度和纬度的地址信息
  3. 为了使用该元数据来获得城市和国家信息
  4. 能够按照年份和国家对图片进行分类,以便进一步编辑

首先,我们将看看程序的结构和我们将用来创建脚本的包。

程序结构

  1. 获取要排序的图像列表
  2. 获取照片元数据(经度和纬度,照片拍摄日期)
  3. 基于经度/纬度的抓取位置
  4. 基于年份创建文件夹
  5. 基于城市在每年内创建文件夹
  6. 根据年份和城市将图像移动到文件夹中

脚本中使用的包

  1. GPSPhoto:用于从 jpeg 文件中获取元数据
  2. Selenium:用于访问基于经度和纬度的位置数据
  3. 时间:用于减缓 selenium 获取数据的过程
  4. Os:用于用 python 创建文件夹
  5. Shutil:用于将文件移到新创建的文件夹中

现在我们已经有了如何进行的结构,让我们来讨论每一部分。

凯蒂·莫尔德·www.katymould.com

制作图像列表

使用 python 的 os 模块很容易创建文件列表。

import os
image_list = os.listdir('c:\\users\\Aaron\\photo')
image_list = [a for a in image_list if a.endswith('jpg')]

注释
1。os 模块导入
2。定义了image_list变量。使用 os 模块的listdir方法,我们指定图像的位置。注意\\是用来允许我们创建一个文件夹位置的字符串。这叫做转义符。
3。我们创建一个列表,只包含以'结尾的文件。jpg。这里我们使用了一个 list comprehension,并使用 endswith string 方法只包含' jpg。

从照片元数据中获取位置信息

有很多软件包可以获得这些数据。我发现GPSPhoto是一种简单的方法,可以清晰地获得我所需要的东西。我们使用 getgpsdata 方法,该方法指定图像的文件路径,以获得经度和纬度以及照片拍摄时间的字典。

from GPSPhoto import gpsphoto
for a in image_list: data = gpsphoto.getGPSData(os.getcwd() + f'\\{a}')print(data) 

输出:

{'Latitude': 55.85808611111111,'Longitude': -4.291505555555555,'Altitude': 10.32358870967742,'UTC-Time': '17:41:5.29','Date': '08/23/2017'}

注释
1。我们遍历 image_list 并使用getcwd()方法获得当前的工作目录,并将它与一个文件映像连接起来。在这种情况下,我们使用变量 a。这是因为我们将循环遍历我们的图像列表,因此需要一种通用的方法来获取每个图像的元数据,而不管文件夹中有多少图像。详见下文!

2.注意,我们使用 f 字符串来做这件事,我们可以循环我们的图像列表,并获取每个图像的数据。{}中的任何内容都作为字符串传递,所以在这种情况下,它将是我们刚刚创建的列表中的每个图像文件。

3.我们已经打印出了整理文件夹所需的元数据。

转换经度和纬度数据

在上面的部分中,我们获取了经度和纬度数据。我们需要转换这个来获得一个位置。为此,我们可以使用 google 提供的地理编码 API。我们每个月可以免费使用 200 美元,每 1000 次请求可以获得 5 美元。这是一个不错的方法来做一些图片。

请按照说明访问地理编码 API 这里。请记住,在访问地理编码 API 之前,您需要设置一个计费帐户。别担心,钱不会因为你给了他们你的详细资料而被拿走!但是如果你有很多请求,请小心!

为了获得我们需要的信息,我们必须使用下面指定经度和纬度的 url 发出请求。请记住插入您按照上面的指南获得的 API 密钥!

import requests
long = data['Longitude']
lat = data['Latitude']response = requests.get(f'[https://maps.googleapis.com/maps/api/geocode/json?latlng={lat},{long}&key=INSERT API KEY'](https://maps.googleapis.com/maps/api/geocode/json?latlng=55.8580861,-4.291505&key=AIzaSyBvJdGu9atxkyfsE_rnLaZDJ-5sy4xj9E8'))print(response.json())

输出:

{'plus_code': {'compound_code': 'VP55+69 Glasgow, UK','global_code': '9C7QVP55+69'},'results': [{'address_components': [{'long_name': '21','short_name': '21','types': ['street_number']},{'long_name': 'Pacific Quay','short_name': 'Pacific Quay','types': ['route']},{'long_name': 'Glasgow','short_name': 'Glasgow','types': ['postal_town']},

当我们发出一个 API 请求时,我们得到这个 json 文件!现在 json 的行为很像一个字典,因此我们可以像 wise 一样访问 json 的一部分。

笔记。
1。我们对 API url 使用 request get 方法。然后我们使用json()方法将它转换成我们想要的形式。

json_response = response.json()city = json_response['results'][0]['address_components'][2]['long_name']

注释
1。我们指定第一个结果键[results][0]和其中的[address_components]键。我们使用[address_components]中的第二个项目,最后我们需要键long_name的值

最好是一步一步地迭代,以获得您想要的数据。

为每年拍摄的图像创建文件夹

此时,我们有了从单个图像获取元数据的方法,并且有了图像列表。但是我们需要能够根据照片拍摄的年份创建文件夹。我们使用带有一些字符串操作的 os 模块来实现这一点。

year = data['Date'].split('/')[-1]
year_path = os.getcwd() + '\\' + str(year)
print(year_path)if os.path.isdir(f'{year}'):return year_path
else:os.mkdir(data['Date'].split('/')[-1])return year_path

注释
1。data[Date]是图像拍摄日期的字典值。我们使用拆分列表方法将这些数据拆分为日、月和年的列表。年份总是最后一个列表,因此我们[-1]给出了我们需要的年份。我们使用getcwd方法获取当前工作目录。

2.我们使用 isdir 方法来确认有一个用于计算年份的文件夹。然后我们返回值 year_path。这段代码将被转换成一个函数,从而返回数据。

3.如果还没有创建 year 文件夹,我们使用mkdir并指定文件夹名称,在这种情况下,这是我们刚刚计算的年份。

为每个特定城市创建每年的文件夹

我们现在有了来自图像元数据的城市,我们可以创建各自的文件夹。但我们希望创建城市文件夹作为一个子目录的一年。

location_path = year_path + '\\' + city
if os.path.isdir(f'{location_path}'):print('City Folder already created')
else:os.mkdir(f'{year_path}' + '\\' + f'{city}')print(f'City: {city} folder created ')

注释
1。在这里,我们检查每年的位置文件夹。

2.如果还没有创建位置文件夹,我们像以前一样使用mkdir方法,但是这次我们使用上面创建的year_path变量,并将它与我们刚刚创建的城市变量连接起来。就这么简单!

将图像移动到正确的文件夹

现在我们创建了一个图像文件名的列表,我们说过我们会循环遍历它们,当我们想要将文件移动到一个特定的位置时,这变得很重要。我们使用 shutil 包来移动文件。move 方法有两个参数,一个是文件的绝对路径,另一个是文件所在位置的绝对路径。

shutil.move(os.getcwd() + f'\\{a}' ,location_folder + f'\\{a}')

注释
1。我们指定变量 a,它将是我们的图像文件名,我们连接它来创建图像的绝对路径。
2。我们使用在上一节中创建的location_folder,并将它与图像文件名连接起来,给出我们希望文件所在位置的绝对路径。

准备脚本

现在代码的所有部分都写好了。我们还没有解决这样一个事实,即我们将围绕一个图像文件名列表循环。在我的例子中,我女朋友的一些照片没有元数据,因此在这种情况下也有必要编码,简单地继续删减,直到看到有元数据的图像。

def address(data):long = data['Longitude']lat = data['Latitude']response = requests.get(f'[https://maps.googleapis.com/maps/api/geocode/json?latlng={lat},{long}&key=AIzaSyA6WyqENNQ0wbkNblLHgWQMCphiFmjmgHc'](https://maps.googleapis.com/maps/api/geocode/json?latlng={lat},{long}&key=AIzaSyA6WyqENNQ0wbkNblLHgWQMCphiFmjmgHc'))json_response = response.json()city = json_response['results'][0]['address_components'][2]['long_name']return citydef year_folder(data): year_path = os.getcwd() + '\\' + str(data['Date'].split('/')[-1])print(year_path)year = data['Date'].split('/')[-1]if os.path.isdir(f'{year}'):return year_pathelse:os.mkdir(data['Date'].split('/')[-1])return year_pathdef location_folder(year_path,city): location_path = year_path + '\\' + cityif os.path.isdir(f'{location_path}'):print('City Folder already created')else:os.mkdir(f'{year_path}' + '\\' + f'{city}')print(f'City: {city} folder created ')def move_images(year_path, city,a):location_folder = year_path + f'\\{city}'shutil.move(os.getcwd() + f'\\{a}',location_folder + f'\\{a}')

注释
1。从我们上面讨论的内容来看,address函数没有太大的变化。
2。year_folder函数检查是否已经创建了年文件夹。如果是这样,我们不需要创建一个。语句的 else 部分确保如果 year 文件夹不存在,我们创建一个。
3。location_folder函数我们为位置文件夹创建绝对路径,并测试它是否已经存在。如果没有,我们就创建它。
4。move_images功能我们将文件从原始文件夹移动到特定年份和城市文件夹中的相应位置。

if __name__ == "__main__":image_list = os.listdir('c:\\users\\Aaron\\photo')
image_list = [a for a in image_list if a.endswith('jpg')]print(image_list)for a in image_list:data = gpsphoto.getGPSData(os.getcwd() + f'\\{a}')print(data)try:if data['Latitude']:city = address(data)except:print('Image has no Address')continueif data['Date']:year_path = year_folder(data)else:print('Image has no Date Attached')continuelocation_folder(year_path,city)move_images(year_path,city,a)print('Image moved succesfully')

注释
1。image_list变量使用listdir方法创建图像目录中所有文件名的列表。
2。我们循环每个图像文件名。我们获取每个文件的元数据,并对其进行两次检查。如果它有位置元数据,我们就获取它,如果它有照片拍摄时间的元数据,我们就获取它。
3。随后,如果我们有照片拍摄的地点和日期,我们就创建年份文件夹和地点文件夹。
4。然后,我们将图像从文件原来所在的文件夹移动到我们创建的文件夹中。

使用几个软件包,我们已经成功地创建了一个脚本,可以将成千上万的照片分类到所需的文件夹中,以便进一步编辑和分类照片!完整代码请见此处。

请在此查看更多关于我在博客和其他帖子上的项目进展的细节。如需更多技术/编码相关内容,请在此注册我的简讯

我将非常感谢任何评论,或者如果你想与 python 合作或需要帮助,请联系我。如果你想和我联系,请在这里或者在推特上联系我。

其他文章

[## 你应该知道的 5 个 Python 技巧

如何轻松增强 python 的基础知识

medium.com](https://medium.com/swlh/5-python-tricks-you-should-know-d4a8b32e04db) [## 如何使用 Python 下载文件

了解如何使用 Python 下载 web 抓取项目中的文件

towardsdatascience.com](/how-to-download-files-using-python-ffbca63beb5c)

Grad-CAM

原文:https://towardsdatascience.com/grad-cam-2f0c6f3807fe?source=collection_archive---------36-----------------------

来自深层网络的视觉解释

修改自 Grad-CAM 论文的图 1 和图 20

Grad-CAM 是一种用于可视化卷积神经网络模型的流行技术。Grad-CAM 是特定于类别的,这意味着它可以为图像中出现的每个类别生成单独的可视化图像:

根据 Grad-CAM 论文图 1 修改的猫和狗 Grad-CAM 可视化示例

Grad-CAM 可用于弱监督定位,使用仅在完整图像标签而非显式位置注释上训练的模型来确定特定对象的位置。

Grad-CAM 还可以用于弱监督分割,其中模型预测属于特定对象的所有像素,而不需要像素级标签进行训练:

Grad-CAM 论文图 4 的一部分显示了通过使用 Grad-CAM 热图作为名为 SEC(种子、扩展、约束)的方法的种子而获得的预测摩托车和人分割遮罩

最后,Grad-CAM 可用于更好地了解模型,例如通过提供对模型故障模式的洞察:

Grad-CAM 论文的图 6 显示了模型故障示例以及 Grad-CAM 可视化,说明了模型做出错误预测的原因。

这篇文章的主要参考是 Grad-CAM 论文的扩展版本: Selvaraju 等人的“Grad-CAM:通过基于梯度的定位从深度网络进行可视化解释”国际计算机视觉杂志 2019。

Grad-CAM 论文的先前版本发表在 2017 年国际计算机视觉大会(ICCV)上。

2021 年更新

虽然 Grad-CAM 的论文被引用了几千次,但最近的工作展示了 Grad-CAM 的一个严重问题:有时,Grad-CAM 会突出显示图像中模型实际上没有用于预测的区域。这意味着 Grad-CAM 是一种不可靠的模型解释方法。HiResCAM 是一种新的解释方法,可以证明它保证只突出显示模型使用的位置。HiResCAM 的灵感来自 Grad-CAM,所以如果你理解 Grad-CAM,那么理解 HiResCAM 如何工作就很简单了。

Grad-CAM 作为事后关注

Grad-CAM 是一种事后注意力的形式,这意味着它是一种用于产生热图的方法,该热图在训练完成且参数固定后应用于已经训练的神经网络。这与可训练的注意力是不同的,可训练的注意力包括学习如何在训练期间通过学习特定的参数来产生注意力图(热图)。关于事后可训练注意力的更深入讨论,见这篇文章。

Grad-CAM 作为 CAM 的推广

Grad-CAM 不需要特定的 CNN 架构。Grad-CAM 是 CAM(类激活映射)的一种推广,是一种需要使用特定架构的方法。

CAM 需要一个将全局平均池(GAP)应用于最终卷积要素图的架构,然后是一个产生预测的全连接层:

在上面的草图中,正方形 A1(红色)、A2(绿色)和 A3(蓝色)代表 CNN 最后一个卷积层产生的特征图。为了使用 Grad-CAM 所基于的 CAM 方法,我们首先取每个特征图的平均值,以产生每个图的单个数字。在这个例子中,我们有 3 个特征地图,因此有 3 个数字;这 3 个数字在草图中显示为彩色小方块。然后,我们对这 3 个数字应用全连接层,以获得分类决策。对于输出类“cat”,预测将基于 3 个权重(w1、w2 和 w3)。为了制作“猫”的 CAM 热图,我们使用最终全连接层的“猫”权重对特征图进行加权求和:

注意,特征图的数量不一定是三个——它可以是任意的 k 。关于 CAM 如何工作的更详细的解释,请参见这篇文章。理解 CAM 对于理解 Grad-CAM 非常重要,因为这两种方法密切相关。

Grad-CAM 开发的部分动机是想出一种类似 CAM 的方法,不限制 CNN 架构。

Grad-CAM 概述

Grad-CAM 背后的基本思想与 CAM 背后的基本思想相同:我们希望利用通过卷积层保存的空间信息,以便了解输入图像的哪些部分对于分类决策是重要的。

与 CAM 类似,Grad-CAM 使用 CNN 最后一个卷积层产生的特征图。Grad-CAM 的作者认为,“我们可以预期最后的卷积层在高级语义和详细的空间信息之间具有最佳的折衷。”

以下是显示与 Grad-CAM 相关的神经网络模型部分的示意图:

CNN 由一些卷积层组成(在草图中显示为“conv”)。最终卷积层生成的特征图显示为 A1、A2 和 A3,与 CAM 草图中的相同。

此时,对于 CAM,我们需要进行全局平均池化,然后是完全连接的层。对于 Grad-CAM,我们可以做任何事情——例如,多个完全连接的层——在草图中显示为“任何神经网络层”。唯一的要求是我们在 A1、A2 和 A3 之后插入的层必须是可微的,这样我们就可以得到一个梯度。最后,我们有飞机、狗、猫、人等的分类输出。

CAM 和 Grad-CAM 之间的区别在于如何对特征图 A1、A2 和 A3 进行加权以生成最终热图。在 CAM 中,我们使用取自网络最后一个全连接层的权重对这些特征地图进行加权。在 Grad-CAM 中,我们使用基于梯度计算的“alpha 值”对特征图进行加权。因此,Grad-CAM 不需要特定的架构,因为我们可以通过任何一种我们想要的神经网络层来计算梯度。Grad-CAM 中的“Grad”代表“梯度”

Grad-CAM 的输出是一个“区分类别的定位图”,一个热点图,其中热点部分对应于一个特定类别:

如果有 10 个可能的输出类,那么对于特定的输入图像,您可以制作 10 个不同的 Grad-CAM 热图,每个类一个热图。

Grad-CAM 详情

首先,做一点注释:

换句话说,在应用 softmax 将原始分数转换成概率之前,y^c 是类 c 的神经网络的原始输出。

Grad-CAM 应用于已完成训练的神经网络。神经网络的权重是固定的。我们将一幅图像输入网络,为选定的感兴趣类别计算该图像的 Grad-CAM 热图。

Grad-CAM 有三个步骤:

步骤 1:计算梯度

在该步骤中计算的梯度的特定值取决于选择的输入图像,因为输入图像决定了特征图 Ak 以及产生的最终类别分数 yc。

对于 2D 输入图像,此渐变是 3D 的,与特征地图具有相同的形状。高度 v 和宽度 u各有 k 个特征图,这些特征图统称为形状 k,v,u 。这意味着在步骤 1 中计算的梯度也将是形状[ k,v,u ]。

在下面的草图中, k =3 所以有三张 u x v 特征图和三张 u x v 渐变:

步骤 2:通过平均梯度计算阿尔法值

在这一步,我们计算阿尔法值。类别 c 和特征地图 k 的 alpha 值将在下一步中用作应用于特征地图 Ak.的权重(在 CAM 中,应用于特征地图 Ak 的权重是最终完全连接层中的权重 w_k。)

回想一下,我们的渐变有形状[ k,v,u ]。我们对高度 v 和宽度 u 进行合并,因此我们最终得到的是形状为[ k,1,1 的东西,或者简单点说,就是[ k 】。这些是我们的 kα值。

步骤 3:计算最终 Grad-CAM 热图

现在我们有了 alpha 值,我们使用每个 alpha 值作为相应特征图的权重,并计算特征图的加权和作为最终的 Grad-CAM 热图。然后我们应用一个 ReLU 操作,只强调正值,把所有负值都变成 0。

Grad-CAM 热图不会太小吗?

Grad-CAM 热图的大小为 u x v ,这是最终卷积特征图的大小:

你可能想知道这有什么意义,因为在大多数 CNN 中,最终的卷积特征在宽度和高度上都比原始输入图像小得多。

事实证明,如果 u x v Grad-CAM 热图比原始输入图像尺寸小很多,也没关系。我们需要做的就是在最终可视化之前,对微小的 u x v 热图进行上采样,以匹配原始图像的大小。

例如,这是一个 12 x 12 的小热图:

现在,这是使用 Python 包 cv2 向上采样到 420 x 420 的相同热图:

将原始小的低分辨率热图可视化并将其转换为大的高分辨率热图的代码如下:

import cv2 
import matplotlib 
import matplotlib.pyplot as plt small_heatmap = CalculateGradCAM(class='cat') plt.imshow(small_heatmap, cmap='rainbow') #Upsample the small_heatmap into a big_heatmap with cv2: 
big_heatmap = cv2.resize(small_heatmap, dsize=(420, 420), interpolation=cv2.INTER_CUBIC) plt.imshow(big_heatmap, cmap='rainbow')

Grad-CAM 实施

Grad-CAM 的 Pytorch 实现可从这里获得。

更多 Grad-CAM 示例

Grad-CAM 已经应用于许多研究领域,在医学图像中尤其流行。这里有几个例子:

杨等,“深度三维卷积神经网络对阿尔茨海默病分类的可视化解释”

上面一排是摄像头,下面一排是摄像头。 Kim 等人,“医学图像形态分类中卷积神经网络预测的视觉解释。”

伍等人的 Grad-CAM 可视化。“CBAM:卷积块注意模块。”本文是一个可训练的注意力机制(CBAM)与可视化的事后注意力机制(Grad-CAM)相结合的例子。

2021 年确定 Grad-CAM 的主要问题

虽然 Grad-CAM 应该能够解释模型用于预测的图像区域,但事实证明 Grad-CAM 并不能保证做到这一点!简而言之,由于梯度平均步骤,Grad-CAM 的热图不能反映模型的计算,因此可以突出显示不用于预测的无关区域。解决方案是 HiResCAM,这是一种解释方法,它避免了 Grad-CAM 的梯度平均步骤,而是使用原始梯度和特征图之间的元素乘积。HiResCAM 实现了与 Grad-CAM 相同的所有目的,其好处是 HiResCAM 可以保证只突出显示模型使用的区域,对于任何以一个完全连接的层结束的 CNN。把 Grad-CAM 代码改成 HiResCAM 代码只需要几秒钟。关于为什么 Grad-CAM 有时会失败,以及 HiResCAM 解决方案如何工作的更多细节,请参见这篇论文。

制导 Grad-CAM 的问题

作为另一个需要注意的问题,Grad-CAM 论文提到了 Grad-CAM 的一个变种,称为“Guided Grad-CAM”,它将 Grad-CAM 与另一种称为“guided backpropagation”的 CNN 热图可视化技术相结合。我在这篇文章和这篇文章中讨论了引导反向传播。简短的总结是,Adebayo 等人(T13)和 Nie 等人(T15)最近的工作表明,引导反向传播正在执行部分图像恢复,并像边缘检测器一样工作,而不是提供对训练模型的洞察。因此,最好不要使用导向反向传播,由此引申,这意味着最好不要使用导向 Grad-CAM。

总结

  • Grad-CAM 是一种流行的技术,用于根据特定的输入图像、经过训练的 CNN 和选定的感兴趣的类别来创建特定类别的热图。
  • Grad-CAM 与 CAM 关系密切。
  • Grad-CAM 可以在任何 CNN 架构上计算,只要层是可区分的。
  • Grad-CAM 已经用于弱监督定位和弱监督分割。
  • 最近的工作发现了 Grad-CAM 的一个基本问题:有时 Grad-CAM 会突出显示模型实际上没有使用的区域。因此,对于模型解释,应使用 HiResCAM 代替 Grad-CAM。

原载于 2020 年 5 月 29 日

梯度积累:克服深度学习中的记忆限制

原文:https://towardsdatascience.com/gradient-accumulation-overcoming-memory-constraints-in-deep-learning-36d411252d01?source=collection_archive---------21-----------------------

丹尼尔·冯·阿彭在 Unsplash 上的照片

让我们诚实一点。没有 GPU 的深度学习是一个很头疼的问题!是的,Google Colab 和 Kaggle 是存在的,但是生活和工作并不总是训练一个整洁和酷的 MNIST 分类器。

简介

对于训练最先进的或 SOTA 模型,GPU 是一个很大的必要性。即使我们能够获得一个,也有内存限制的问题。每当我们抛出一个大批量进行训练时,我们或多或少都习惯于看到 OOM(内存不足)错误。当我们谈到最先进的计算机视觉算法时,这个问题就更加明显了。自 VGG 时代甚至是 18 世纪以来,我们走过的路程要长得多。像 UNet、ResNet-152、RCNN、Mask-RCNN 这样的现代更深层次的体系结构是极其内存密集型的。因此,在训练更深层次的模型时,我们很有可能会耗尽内存。

这是在 PyTorch 中运行模型时出现的 OOM 错误。

RuntimeError: CUDA out of memory. Tried to allocate 44.00 MiB (GPU 0; 10.76 GiB total capacity; 9.46 GiB already allocated; 30.94 MiB free; 9.87 GiB reserved in total by PyTorch)

每当遇到 OOM 错误时,从业者通常会立即采取两种解决方案。

  1. 减少批量
  2. 缩小图像尺寸

在超过 90%的情况下,这两种解决方案已经足够了。所以你想问的问题是:为什么剩下的 5%需要别的东西。为了回答这个问题,让我们看看下面的图片。

来自迪米特里·奥利维拉的卡格尔笔记本

来自 Kaggle 比赛, 从卫星图像中理解云 。任务是正确分割不同类型的云。这些图像分辨率非常高,1400 x 2100。你也可以理解,在这种情况下,过多地减少图像尺寸会产生非常负面的影响,因为微小的图案和纹理是这里要学习的重要特征。因此,唯一的其他选择是减少批量大小。

渐变下降

作为复习,如果您碰巧记得梯度下降,或者在我们的例子中特别是小批量梯度下降,您会记得我们不是在整个数据集上计算损失和最终梯度,而是在较小的批量上进行操作。除了帮助我们将数据放入内存之外,它还帮助我们更快地收敛,因为参数在每次小批量后都会更新。但是当批量变得太小时会发生什么呢?粗略估计,在 11GB 的 GPU 中,可能有 4 个这样的图像可以放入单个批次中,所计算的损失和梯度将不会准确地代表整个数据集。因此,模型收敛速度会慢很多,或者更糟,根本不收敛。

渐变积累

梯度累积背后的想法非常简单。*它在每个小批量后计算损耗和梯度,但它不是更新模型参数,而是等待并累积连续批量的梯度。*然后在指定数量的批次之后基于累积梯度最终更新参数。它与具有更高数量图像的小批量具有相同的目的。

例如:如果您以 5 个步长和 4 个图像的批量运行梯度累积,它与以 20 个图像的批量运行的目的几乎相同。

实现

PyTorch 上编码渐变累积部分也简单得离谱。您需要做的只是存储每批的损耗,然后仅在您选择的一组批数之后更新模型参数。

我们保持optimizer.step(),它更新accumulation_steps批数的参数。此外,同时调用model.zero_grad()来重置累积的渐变。

对于keras/tensor flow来说,做同样的事情要稍微棘手一点。你可以在网上找到人们写的不同版本。这是由 @alexeydevederkin 写的其中一篇。

注意:由于 keras 的培训过程缺乏模块化,它比 pytorch 代码更长更复杂。

还有尺寸更小的纯张量流代码。你会很容易找到的。

对于计算量较少的爱好者,甚至是打算使用图像而不缩小图像的从业者来说,梯度累积是一个很好的工具。无论你是哪一个,它总是你军械库中的一个便利的诡计。

[## 训练前你需要知道的 3 件事——试分裂

这很可能是您在任何数据科学教程中遇到的第一步。很有可能你一直在做…

towardsdatascience.com](/3-things-you-need-to-know-before-you-train-test-split-869dfabb7e50) [## 通过数据评估冠状病毒封锁对我们环境的影响。

封锁及其对我们环境的影响。

towardsdatascience.com](/assessing-the-impact-of-the-coronavirus-lockdown-on-our-environment-through-data-2905535da51e)

梯度推进决策树-解释

原文:https://towardsdatascience.com/gradient-boosted-decision-trees-explained-9259bd8205af?source=collection_archive---------2-----------------------

详细解释了 boosting 和 scikit-learn 实现

决策树建立在反复询问问题以划分数据的基础上。用决策树的可视化表示来概念化分区数据更容易:

图源

一个决策树容易过度拟合。为了降低过度拟合的风险,组合了许多决策树的模型是首选的。这些组合模型在准确性方面也具有更好的性能。随机森林使用一种叫做装袋的方法来组合许多决策树以创建集合。打包简单地说就是并行组合。如果想了解决策树和随机森林的详细信息,可以参考下面的帖子。

[## 决策树和随机森林—解释

详细的理论解释和代码示例

towardsdatascience.com](/decision-tree-and-random-forest-explained-8d20ddabc9dd)

在这篇文章中,我将介绍梯度提升决策树算法,该算法使用提升方法来组合各个决策树。

Boosting 是指将一个学习算法串联起来,从许多顺序连接的弱学习器中实现一个强学习器。在梯度提升决策树算法的情况下,弱学习器是决策树。

每棵树都试图最小化前一棵树的错误。boosting 中的树是弱学习器,但是连续添加许多树,并且每个树集中于前一个树的错误,使得 boosting 成为高效且准确的模型。与装袋不同,增压不涉及自举取样。每次添加新树时,它都适合初始数据集的修改版本。

由于树是按顺序添加的,boosting 算法学习起来很慢。在统计学习中,学习速度慢的模型表现更好。

随机森林

梯度推进决策树

梯度提升算法以这样的方式顺序地组合弱学习器,即每个新的学习器适合于来自前一步骤的残差,从而改进模型。最终的模型汇总了每一步的结果,从而形成了一个强学习者。梯度提升决策树算法使用决策树作为弱学习器。损失函数用于检测残差。例如,均方误差(MSE)可用于回归任务,对数损失(log loss)可用于分类任务。值得注意的是,当添加新的树时,模型中现有的树不会改变。添加的决策树符合当前模型的残差。步骤如下:

梯度增强决策树算法

下图显示了这些步骤:

Quora 上的图片来源

学习率和 n _ 估计器

超参数是学习算法的关键部分,它影响模型的性能和准确性。学习率n_estimators 是梯度推进决策树的两个关键超参数。学习率,表示为α,简单地表示模型学习的速度。每增加一棵树都会修改整个模型。修改的幅度由学习速率控制。引入学习率的梯度推进决策树算法的步骤:

学习率为(α)的梯度推进决策树算法

学习率越低,模型学习越慢。较慢的学习速率的优点是模型变得更加健壮和通用。在统计学习中,学习速度慢的模型表现更好。但是,慢慢的学习是要付出代价的。训练模型需要更多的时间,这就引出了另一个重要的超参数。 n_estimator 是模型中使用的树的数量。如果学习率低,我们需要更多的树来训练模型。然而,我们需要非常小心地选择树的数量。使用太多的树会产生过度适应的高风险。

关于过拟合的注释

随机森林和梯度推进决策树之间的一个关键区别是模型中使用的树的数量。增加随机森林中的树木数量不会导致过度拟合。在某个点之后,模型的准确性不会因为添加更多的树而增加,但是也不会因为添加过多的树而受到负面影响。由于计算原因,您仍然不希望添加不必要数量的树,但是没有与随机森林中的树的数量相关联的过度拟合的风险。

然而,梯度推进决策树中的树的数量在过度拟合方面非常关键。添加太多的树会导致过度拟合,所以在某个时候停止添加树是很重要的。

利弊

优点:

  • 分类和回归任务都非常高效
  • 与随机森林相比,预测更准确。
  • 可以处理混合类型的特征,不需要预处理

骗局

  • 需要仔细调整超参数
  • 如果使用太多的树,可能会过拟合(n_estimators)
  • 对异常值敏感

sci kit-学习示例

我将带您浏览使用 scikit-learn 上的一个示例数据集创建 GradientBoostingClassifier()的步骤。

让我们从导入依赖项开始:

加载我们刚刚导入的数据集:

使用 train_test_split 模块将数据集分为训练集和测试集:

然后,我们创建一个 GradientDescentClassifier()对象并拟合训练数据:

然后使用预测方法预测测试集的目标值,并测量模型的准确性;

值得注意的是,与这个非常简单的例子相比,现实生活项目中的数据准备、模型创建和评估是极其复杂和耗时的。我只是想向你们展示模型创建的步骤。在现实生活中,你的大部分时间将花在数据清理和准备上(假设数据收集是由别人完成的)。您还需要花费大量时间对超参数模型的准确性进行多次调整和重新评估。

关于 XGBOOST 的一个注记

XGBOOST(Extreme Gradient Boosting)是由陈天琦(Tianqi Chen)创立的梯度增强决策树的一个高级实现。它速度更快,性能更好。XGBOOST 是一个非常强大的算法,最近在机器学习竞赛中占据主导地位。我也会写一篇关于 XGBOOST 的详细文章。

感谢您的阅读。如果您有任何反馈,请告诉我。

我关于其他机器学习算法的文章

  • 朴素贝叶斯分类器——解释
  • 支持向量机—解释
  • 决策树和随机森林—解释

通过 Python 解释梯度增强分类

原文:https://towardsdatascience.com/gradient-boosting-classification-explained-through-python-60cc980eeb3d?source=collection_archive---------4-----------------------

马切伊·鲁明凯维奇在 Unsplash 上拍摄的照片

在我的上一篇文章中,我讨论并经历了一个用于回归的梯度推进的 python 实例。在这篇文章中,我想讨论梯度推进是如何用于分类的。如果你没有读过那篇文章,没关系,因为我会重申我在上一篇文章中讨论的内容。所以,让我们开始吧!

集成方法

通常,你可能有几个好的预测器,你想把它们都用上,而不是痛苦地选择一个,因为它有 0.0001 的准确性增加。来了*合奏学习。*在集成学习中,不是使用单个预测器,而是聚合数据中的多个预测器和训练及其结果,通常比使用单个模型给出更好的分数。例如,一个随机森林就是一组打包(或粘贴)的决策树。

Samuel Sianipar 在 Unsplash 上拍摄的照片

你可以把合奏方法想象成一个管弦乐队;不是只有一个人演奏一种乐器,而是多人演奏不同的乐器,通过组合所有的音乐组合,音乐听起来通常比单人演奏要好。

虽然梯度增强是一种集成学习方法,但它更具体地说是一种增强技术。那么,是什么在推动?

助推

Boosting 是一种特殊类型的集成学习技术,它通过将几个*弱学习器(*准确性差的预测器 ) 组合成一个强学习器(准确性强的模型)来工作。这是通过每个模型关注其前任的错误来实现的。

两种最流行的升压方法是:

  • 适应性增强(你可以在这里阅读我的文章)
  • 梯度推进

我们将讨论梯度推进。

梯度推进

在梯度推进中,每个预测器都试图通过减少误差来改进其前任。但是梯度推进背后的有趣想法是,它不是在每次迭代中对数据拟合预测器,而是实际上对前一个预测器产生的残差拟合一个新的预测器。我们来看一下梯度推进分类工作原理的逐步示例:

照片由林赛·亨伍德在 Unsplash 拍摄

  1. 为了对数据进行初始预测,算法将获得目标特征的几率的对数。这通常是真值(值等于 1)的数量除以假值(值等于 0)的数量。

因此,如果我们有一个包含 6 个实例的乳腺癌数据集,其中 4 个实例是患有乳腺癌的人(4 个目标值= 1),2 个实例是没有患乳腺癌的人(2 个目标值= 0),那么 log(odds) = log(4/2) ~ 0.7。这是我们的基本估计。

  1. 一旦有了对数(赔率),我们通过使用逻辑函数将该值转换成概率,以便进行预测。如果我们继续我们之前的 0.7 的对数(比值)值的例子,那么逻辑函数也将等于 0.7 左右。

由于该值*大于 0.5,*该算法将为每个实例预测 0.7 作为其基本估计值。将对数(赔率)转换成概率的公式如下:

e * log(odds) / (1 + e * log(odds))
  1. 对于训练集中的每个实例,它计算该实例的残差,或者换句话说,观察值减去预测值。
  2. 一旦它完成了这些,它就建立一个新的决策树,实际上试图预测先前计算的残差。然而,与梯度推进回归相比,这是它变得稍微棘手的地方。

构建决策树时,允许有固定数量的叶子。这可以由用户设置为一个参数,通常在 8 到 32 之间。这导致了两种可能的结果:

  • 多个实例落在同一片叶子中
  • 单个实例有自己的叶

与回归的梯度推进不同,我们可以简单地平均实例值以获得输出值,并将单个实例作为其自己的一片叶子,我们必须使用一个公式来转换这些值:

鸣谢:博客空间

σ符号表示“的和”,而 PreviousProb 指的是我们之前计算的概率(在我们的例子中,为 0.7)。我们对树中的每一片叶子都应用这种变换。我们为什么要这样做?因为请记住,我们的基本估计量是一个对数(赔率),而我们的树实际上是建立在概率上的,所以我们不能简单地将它们相加,因为它们来自两个不同的来源。

做预测

现在,为了进行新的预测,我们做两件事:

  1. 获取训练集中每个实例的对数(赔率)预测
  2. 将预测转换成概率

对于训练集中的每个实例,进行预测的公式如下:

base_log_odds + (**learning_rate *** predicted residual value)

learning_rate 是一个超参数,用于缩放每棵树的贡献,牺牲偏差以获得更好的方差。换句话说,我们将这个数字乘以预测值,这样我们就不会过度拟合数据。

一旦我们计算出对数(赔率)预测,我们现在必须使用前面将对数(赔率)值转换为概率的公式将其转换为概率。

重复&对看不见的数据进行预测

照片由布雷特·乔丹在 Unsplash 拍摄

完成这个过程后,我们计算树的新残差,并创建一个新的树来拟合新的残差。再次重复该过程,直到达到某个预定义的阈值,或者残差可以忽略。

如果我们训练了 6 棵树,并且我们想要对一个看不见的实例进行新的预测,那么它的伪代码将是:

X_test_prediction = base_log_odds + (**learning_rate *** tree1_scaled_output_value) + 
(**learning_rate *** tree2_scaled_output_value) +
(**learning_rate *** tree3_scaled_output_value) +
(**learning_rate *** tree4_scaled_output_value) +
(**learning_rate *** tree5_scaled_output_value) +
(**learning_rate *** tree6_scaled_output_value) +prediction_probability = 
e*X_test_prediction / (1 + e*X_test_prediction)

好了,现在你应该对用于分类的梯度推进的底层机制有所了解了,让我们开始编码来巩固这些知识吧!

罗布·萨米恩托在 Unsplash 上拍摄的照片

使用 Scikit-Learn 进行梯度增强分类

我们将使用预先构建到 scikit-learn 中的乳腺癌数据集作为示例数据。首先,让我们弄清楚一些重要的东西:

import pandas as pd
import numpy as npfrom sklearn.metrics import classification_report
from sklearn.model_selection import KFold
from sklearn.datasets import load_breast_cancerfrom sklearn.ensemble import GradientBoostingClassifier

在这里,我们只是导入 pandas、numpy、我们的模型和一个评估我们模型性能的指标。

df = pd.DataFrame(load_breast_cancer()['data'],
columns=load_breast_cancer()['feature_names'])df['y'] = load_breast_cancer()['target']
df.head(5)

为了方便起见,我们将数据转换成 DataFrame,因为这样更容易操作。请随意跳过这一步。

X,y = df.drop('y',axis=1),df.ykf = KFold(n_splits=5,random_state=42,shuffle=True)for train_index,val_index in kf.split(X):X_train,X_val = X.iloc[train_index],X.iloc[val_index],y_train,y_val = y.iloc[train_index],y.iloc[val_index],

在这里,我们定义了我们的特征和标签,并使用 5 折交叉验证将 ur 数据分成一个训练和验证。

gradient_booster = GradientBoostingClassifier(learning_rate=0.1)
gradient_booster.get_params()OUT:{'ccp_alpha': 0.0,'criterion': 'friedman_mse','init': None,'learning_rate': 0.1,'loss': 'deviance','max_depth': 3,'max_features': None,'max_leaf_nodes': None,'min_impurity_decrease': 0.0,'min_impurity_split': None,'min_samples_leaf': 1,'min_samples_split': 2,'min_weight_fraction_leaf': 0.0,'n_estimators': 100,'n_iter_no_change': None,'presort': 'deprecated','random_state': None,'subsample': 1.0,'tol': 0.0001,'validation_fraction': 0.1,'verbose': 0,'warm_start': False}

这里有很多参数,所以我只讨论最重要的:

  • 标准:用于寻找分割数据的最佳特征和阈值的损失函数
  • learning_rate :该参数衡量每棵树的贡献
  • max_depth :每棵树的最大深度
  • n_estimators :要构建的树的数量
  • **init:初始估计量。**默认情况下,它是将对数(赔率)转换成概率(就像我们之前讨论的那样)
gradient_booster.fit(X_train,y_train)print(classification_report(y_val,gradient_booster.predict(X_val)))OUT:precision    recall  f1-score   support0       0.98      0.93      0.96        46
1       0.96      0.99      0.97        67 accuracy                           0.96       113macro avg       0.97      0.96      0.96       113
weighted avg       0.96      0.96      0.96       113

好吧,96%的准确率!

我希望这篇文章已经帮助你理解了梯度推进分类(以某种形式)。我祝你在 ML 的努力中一切顺利,并记住;知之甚少却知之甚详的人,胜过知之甚多却知之甚少的人!

由 Kelly Sikkema 在 Unsplash 上拍摄的照片

几乎从零开始的梯度提升

原文:https://towardsdatascience.com/gradient-boosting-from-almost-scratch-c3ed0db2ffdb?source=collection_archive---------31-----------------------

通过 Python 实现理解强大的机器学习算法

在过去的一个月里,我一直在慢慢地从头开始学习 Joel Grus 的《数据科学》第二版,我非常喜欢构建简单版本的机器学习算法。我总是通过实践学得更好,这本书符合这种学习风格。不幸的是,它没有实现梯度推进的一章。虽然我通读了陈天齐的伟大的幻灯片,我想我会通过自己实现一个简单版本的渐变增强来获得更好的理解。

梯度推进是一种相对简单的算法。它的工作原理是训练弱模型(最常见的是推车),这些弱模型来自前一次迭代的残差。通过将预测残差乘以 0 到 1 之间的学习率与先前的预测相加来生成新的预测。学习率防止模型向实际值迈出太大的一步并超过它们。小的学习率需要更长的时间收敛到最佳状态。找到合适的是一个平衡的行为。

我强烈推荐陈天齐的幻灯片更彻底的处理渐变提升,或者看一下 XGBoost 的文档,这是他惊人的渐变提升包。

我说梯度推进几乎从零开始;我使用 scikit-learn 的模型作为我的弱学习器,并使用 numpy 用于某些数学函数及其数组结构。

梯度推进算法是这样的:

我使用的第一个模型是 scikit-learn 的回归树。因此,潜在损失函数是均方误差、弗里德曼调整的均方误差和平均绝对误差。它们每个都包含正则化项,这对我来说是幸运的。scikit-learn 的文档中包含了对每一个更全面的解释。

另外,我用的是他们的岭回归模型,它的损失函数是误差平方和+系数的 l2 范数乘以一个惩罚系数。你可以在大多数线性模型或机器学习教科书中了解更多信息,或者去这里。

我用来实现 boosting 算法的代码如下。整篇笔记的链接会在文章的底部提供,作为继续阅读的激励。

import typing
import numpy as npdef GradBoost(model,X_test: np.array,          # testing independent varsX_train: np.array,         # training independent varsy_train: np.array,         # training dependent varboosting_rounds: int = 100,# number of boosting roundslearning_rate: float = 0.1,# learning rateverbose: bool = True       # shows progress bar) -> np.array: '''Takes in a model and performs gradient boosting using it.'''import numpy as np# initalize guess of our training target variable using the meany_hat_train = np.repeat(np.mean(y_train), len(y_train))# initialize out of sample prediction with training meany_hat_train_test = np.repeat(np.mean(y_train), len(X_test)) # calculate the training residuals fusing the first guesspseudo_resids = y_train - y_hat_train# performs gradient boosting with a tqdm progress barif verbose: from tqdm import tqdm # iterates through the boosting roundfor _ in tqdm(range(0, boosting_rounds)): # fit the model to the pseudo residualsmodel = model.fit(X_train, pseudo_resids) # increment y_hat_train with the predicted resids*lry_hat_train += learning_rate * model.predict(X_train)  # increment the predicted test y as welly_hat_train_test += (learning_rate *   model.predict(X_test)) # calculate the pseudo resids for next roundpseudo_resids = y_train - y_hat_train # performs gradient boosting without a progress bar        else: # iterates through the boosting roundfor _ in range(0, boosting_rounds): # fit the model to the pseudo residualsmodel = model.fit(X_train, pseudo_resids) # increment the y_hat_train with the pseudo resids*lry_hat_train += learning_rate * model.predict(X_train)# increment the predicted test y as welly_hat_train_test += (learning_rate * model.predict(X_test)) # calculate the pseudo resids for next roundpseudo_resids = y_train - y_hat_train # return a tuple of the training y_hat and the test y_hatreturn y_hat_train, y_hat_train_test

现在让我们生成一些测试数据,看看这个函数是否有效。我选择模拟数据,所以我知道一些自变量和目标变量之间有关系。我用 scikit-learn 的 make_regression 函数生成了 1000 个观察值,有 20 个自变量,其中四分之三实际上包含有用的信息。然后,我将数据分成训练和测试数据集。

from sklearn.datasets import make_regressionX, y = make_regression(n_samples=1000, n_features=20, n_informative=15, n_targets=1, bias=0.0, noise=20,shuffle=True,random_state=13)X_train = X[0:int(len(X) / 2)]
y_train = y[0:int(len(X) / 2)]X_test = X[int(len(X) / 2):]
y_test = y[int(len(X) / 2):]

当使用梯度推进时,太少的迭代导致欠拟合模型,太多的迭代导致过拟合模型。在我们进行预测之前,了解训练均方差如何随着更多的提升迭代而演变是有帮助的,因此我们可以尝试并拟合一个校准良好的模型。

当实际尝试解决一个实际问题时,您将使用网格搜索和 k-folds 交叉验证来确定推进回合的数量以及其他参数。为了便于演示,我做了一些更简单的事情。我只是绘制了 5 到 100 轮的训练均方误差与助推轮数的关系,步长为 5,并选择了半任意截止值。

该实现中的回归树深度为 3,损失函数被指定为正则化均方误差。岭回归使用三重交叉验证在{0.01,0.1,1,10}中的每一步选择最佳 l2 范数惩罚系数。两种模型的学习率都设置为 0.1。

训练 MSE vs 助推回合

当使用树作为我们的弱学习器时,均方误差快速下降,直到它在 30 次提升迭代左右达到拐点。在那之后,当它接近 100 轮的时候,它慢慢地向下倾斜。当使用岭回归模型时,训练均方误差猛跌,直到 20 轮,并且在 30 轮之后才真正稳定下来。我们将使用 100 作为使用树的提升迭代次数,30 用于岭回归提升模型。但是首先,让我们看看 0 次和 10 次提升迭代的结果。

第 0 轮助推时的预测 y 值与实际 y 值

在上面的图中,红线是预测值等于实际值的地方,代表完美的预测。测试数据越接近这条线,我们的模型就越准确。如果训练预测是紧密拟合的,但是测试预测到处都是,则模型与训练数据过度拟合。

在 0 轮助推的情况下,我们只是猜测平均值。正如你所料,这个天真的“模型”不符合数据。让我们看看 10 轮助推后事情会如何发展。

10 轮助推时的预测 y 值与实际 y 值

在第 10 轮,每个模型的预测开始向完美的预测线旋转。这一过程随着学习速度的提高而加快,但也有可能超过标准。对于使用岭回归作为弱学习器的模型,预测云要紧密得多。这可能是因为我们生成的数据包含线性关系,而岭回归是线性模型。现在我想是时候做我们最后的预测和比较了。

100 轮增强树的预测 y 值与实际 y 值,以及 30 轮增强岭回归的预测 y 值与实际 y 值

在 100 次迭代时,我们的提升树模型是不错的,但是它在测试数据集中的表现差于目标变量的平均值。看起来也有点过合身。尽管如此,它还是比 10 回合模型更适合。我们以岭回归作为弱学习者的模型更适合。同样,这可能是由于模拟数据中的线性结构。说到线性结构,让我们看看这些模型与简单的多元线性回归相比如何。

多元线性回归的预测 y 值与实际 y 值

该图表明多元线性回归是我们的最佳拟合模型。让我们检查测试集的均方误差以确保正确。

多元线性回归胜出!让这成为可视化和调查你的数据的一个提醒。在用算法解决问题之前,请始终仔细考虑形成数据结构的数据生成过程。或者不要。这是你的生活。

让我们看看更多的提升回合会发生什么,比方说 1000 个提升树和 100 个提升岭回归。

增强树的 1000 轮增强和增强岭回归的 100 轮增强时的预测 y 值与实际 y 值

增强的树显然过度拟合了训练数据,但是来自增强的岭回归的结果相当好。同样,数据中的关系是线性的。让我们看看新的均方误差。

在 100 轮提升时,提升岭回归的表现接近多元线性回归,多元线性回归代表真实的模型(加上几个应被忽略的噪声变量)。事实证明,有时候用算法解决问题是有效的。尽管如此,最好还是了解你的数据。

我希望这篇文章能让你更好地了解最强大的机器学习技术之一的内幕(抱歉,这是陈词滥调)。现在,您可以一边去喝咖啡,一边思考您的计算机正在做什么,等待您的网格搜索完成。

你可以在这里得到我的代码并使用它。

点击查看这篇文章基于的 Jupyter 笔记本。

你可以在这里找到更多我的文章。

梯度集中化

原文:https://towardsdatascience.com/gradient-centralization-bdb333a53bcd?source=collection_archive---------44-----------------------

如何通过添加一行代码,在您的 DNN 模型中实现更高效的训练和更好的正则化

图片由来自皮克斯拜的扬·瓦塞克拍摄

一篇最近发表的论文提出了一个简单的答案:梯度中心化,一种新的优化技术,可以很容易地集成到你已经使用的基于梯度的优化算法中。这是广泛使用的批处理规范化的一个很好的替代方案。你所需要做的就是集中你的梯度向量,使它们的平均值为零!

在这里,我将探索所提出的方法的理论细节。实用的方法将在我的下一篇文章中讨论。

一行代码背后的数学原理

注释

让我们来介绍一下符号:

梯度集中操作

GC 操作定义如下:从梯度矩阵的每一列中,我们减去该列的平均值。例如,如果梯度矩阵如下所示:

转换后,它将看起来像这样:

因为各个列的平均值是 4,3,5,0。

换句话说,我们将损失函数的每个梯度 w.r.t .转换为权重向量,使得其平均值等于零。我们可以用一种奇特的符号来表示它:

GC 算符的向量公式

如果你想让它看起来更高级,你可以引入一个很酷的 P 操作符并使用矩阵公式:

GC 算符的矩阵公式

通过直接矩阵乘法,您可以很容易地检查上述等式是否成立:

所以实际上从每一列中,我们减去这一列的平均值。

几何解释

现在,这个符号的目标不是让简单的事情变得更加晦涩,而是揭示整个过程的优雅的几何解释。如果你懂一点代数,你可能已经看到原始梯度通过使用投影算子 P 被投影到权重空间中的某个超平面上。

投影算子

为了确保我们在同一页上,让我们看一个简单的例子来回顾一下关于投影算子的一些基本事实——让我们考虑下面的矩阵 P 以及当它应用于三维空间中的任何向量 v 时会发生什么:

三维空间中的投影运算符示例

如你所见, v 失去了它的 z 分量——换句话说,它被投影到 XY 平面上:

投影可视化

如果再次应用投影操作符会发生什么?什么都没有,向量不能让更多的投影到 XY 平面。这是投影运算符的定义属性之一:

如果投影是正交的,则必须满足另一个条件:

如果矢量 e 垂直于投影平面,那么它也垂直于任何矢量 v 到该平面的投影:

例如,对于我们前面的投影到 XY 平面的例子,我们可以看到任何垂直矢量 e 都满足上面的等式:

作为投影的 GC

现在,如果你检查前面定义的 GC 运算符 P 的上述条件(1)和(2),你会得出结论:它是一个正交投影。

此外,您可以检查:

这意味着 e 是梯度被投影到其上的超平面的法向量。

如果我们采用由权重空间中的向量 w 表示的任何旧权重,并且通过损失函数的投影梯度(而不是梯度本身)来校正它,我们将获得以下新的权重向量w’:

这导致:

将转置的法向量 e 应用于上述等式的两侧会导致:

这意味着对于在连续训练迭代(0,1,2,…,t)中计算的权重,以下为真:

因此,优化问题可以写成:

用文章作者的话说,这意味着

GC 可以看作是一种具有约束损失函数的投影梯度下降法。

来源:https://arxiv.org/pdf/2004.01461.pdf

这如何导致正规化?

对权重向量的这种约束调整了 w 的解空间,导致训练模型更好的泛化能力。

除了正则化权重空间之外,所提出的方法还正则化输出特征空间。给定输入向量 x ,步骤 t 中的输出激活被计算为:

让我们考虑一个输入向量x’,它与 x 的区别仅在于恒定的强度变化 γ :

可以看出(详情请查阅原文章的附录):

因此,通过选择小的初始权重,我们可以确保输出激活对输入特征的强度变化不敏感。

该文章还提到,所提出的技术通过优化景观平滑和梯度爆炸抑制来加速训练过程,但我不会在这里讨论这些。

在下一篇文章中,我将展示如何实际使用所提出的技术。

梯度下降

原文:https://towardsdatascience.com/gradient-descent-811efcc9f1d5?source=collection_archive---------13-----------------------

机器学习中梯度下降的不同变体的利弊

伊内斯·Á·阿尔瓦雷斯·德兹在 Unsplash 上拍摄的照片

介绍

梯度下降是一阶迭代优化算法,其中优化通常在机器学习中是指最小化由预测模型的参数参数化的成本函数 J(w)。此外,一阶意味着梯度下降在执行参数更新时仅考虑一阶导数。

无论发生什么,在你的机器学习或深度学习旅程中的某一点,你都会听说一种叫做梯度下降的东西。对于许多机器学习算法来说,这是一个至关重要的问题,我强烈建议从业者不要将它视为黑盒。

为了最小化成本函数,我们的目标是找到全局最小值,如果目标函数是凸的,这是非常可行的。然而,在诸如深度学习任务的许多场景中,我们的目标函数往往是非凸的,因此找到目标函数的最低可能值被高度认为是合适的解决方案。

图 1:凸函数和非凸函数示例。

为了找到函数的局部最小值,我们采取与函数在当前点的梯度的负值成比例的步骤(来源:维基百科)。坦率地说,我们从目标函数上的一个随机点开始,向负方向朝着全局/局部最小值移动。

图 2:最小化 J(w)的例子;(来源: MLextend )

可以对梯度下降进行许多不同的调整,以使其在不同的情况下更有效地运行;对梯度下降的每种适应都有其利弊,我们将在下面分享:

批量梯度下降

批量梯度下降指的是每次迭代中所有观测值的总和。换句话说,批处理梯度下降为批处理中的每个观测值计算误差(记住这是完整的训练数据),并且仅在评估了所有观测值之后才更新预测模型——更专业的说法是“批处理梯度下降在每个时段的末尾执行参数更新”(一个时段指的是通过整个训练数据的一次迭代)。

图 3:批次梯度下降接近并收敛于全局最小值的 2d 表示。

优点

  • 比随机梯度下降更稳定的收敛性和误差梯度
  • 享受矢量化的优势
  • 朝着最小值采取更直接的路径
  • 计算效率高,因为在一个时期运行之后需要更新

缺点

  • 可以收敛于局部极小值和鞍点
  • 学习速度较慢,因为只有在我们完成所有观察后才进行更新

小批量梯度下降

如果批量梯度下降在每次迭代中对所有观察值求和,则小批量梯度下降在每次迭代中对较少数量的样品(样品的小批量)求和-这种变体减少了梯度的方差,因为我们在每次更新时对指定数量的样品(取决于小批量大小)求和。

注意:这种梯度下降的变化通常是深度学习实践者推荐的技术,但我们必须考虑到有一个额外的超参数,即“批量大小”

图 4:接近最小值的小批量梯度的二维表示;(来源:https://engmrk.com/mini-batch-gd/)

优点

  • 收敛比随机梯度下降更稳定
  • 计算效率高
  • 快速学习,因为我们执行更多的更新

缺点

  • 我们必须配置小批量超参数

随机梯度下降

随机梯度下降对单个观察值的误差进行求和,并对每个观察值的模型进行更新——这与将小批量的数量设置为等于 m 相同,其中 m 是观察值的数量。

图 5:接近最小值的小批量梯度的二维表示;(来源:https://engmrk.com/mini-batch-gd/)

赞成者

  • 网络只处理单个观测值,因此更容易存储
  • 在大型数据集上,可能(很可能)比批量梯度下降更快地达到最小值附近(并开始振荡)
  • 频繁的更新产生了大量的振荡,这有助于摆脱局部最小值。

缺点

  • 由于频繁更新,可能会偏离错误的方向
  • 失去矢量化的优势,因为我们每次处理一个观察值
  • 由于一次使用所有资源来处理一个训练样本,频繁的更新在计算上是昂贵的

包裹

优化是机器学习和深度学习的主要部分。许多机器学习算法采用的一个简单且非常流行的优化过程称为梯度下降,我们可以通过 3 种方式调整梯度下降,以满足我们的需求。

我们继续 LinkedIn 上的对话吧!

[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn

在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)

渐变下降动画:1。简单线性回归

原文:https://towardsdatascience.com/gradient-descent-animation-1-simple-linear-regression-e49315b24672?source=collection_archive---------11-----------------------

这是如何创建可视化梯度下降动画情节系列文章的第一部分。

梯度下降法是当今机器学习中使用最广泛的参数优化算法之一。 Python 的赛璐珞模块使我们能够在梯度下降过程中创建模型参数和成本的生动动画。

在本文中,我示例性地想要使用简单的线性回归来可视化批量梯度下降。我们的目标是建立一个线性回归模型,并在我们制作的一些数据点上对其进行训练。对于每一轮训练(“时期”),我们打算存储当前的模型参数和成本。最后,我们的目标是用我们存储的值创建一些动画。

建立模型

关于如何在培养基上建立和拟合线性回归模型的文章很多。理论上,我们试图为我们的数据找到最佳的拟合直线。数学上,二维空间中的一条直线可以用下面的函数来描述:y=w**x*+b,其中 w 代表我们这条直线的斜率(或“权重”),而 b 代表我们这条直线的 y 截距(或“偏差”)。给定我们的 n 个数据点,有许多方法可以确定 wb 的最佳值。梯度下降算法旨在最小化观测数据点( y )和我们用回归线预测的点( ŷ )之间的均方误差。均方差也被称为“成本函数”(或“成本”),通常表示为 J

在我们的数据点固定的情况下,成本函数仅取决于参数 wb 。我们的目标是调整我们的参数,直到成本函数达到最小值。为了大致了解如何调整(减少还是增加)参数,我们引入了成本函数∇的梯度 J(w,b):

其中δ J/ δ w 和δ J/ δ b 分别是 J 相对于 wb 的偏导数。通过在当前梯度∇J 的相反方向上不断移动我们的参数,我们可以逐步降低成本 J 。我们达到 J 的(局部/全局)最小值所采取的步长通常表示为 α ,也称为“学习率”。当训练我们的模型时,我们的目标是在每个时期重复以下步骤,直到我们达到收敛:

打个比方,成本函数可以被想象成一些山区地形,从某个起点开始,我们想要下坡,直到我们到达一个山谷。类似地,坡度为我们提供了“多维坡度”,即“上坡”在山体表面的方向。这就是为什么我们打算不断地在梯度的相反方向调整我们的参数。

梯度下降算法可以根据同时使用多少训练数据来计算我们的成本函数的梯度而被细分。在下面的例子中,我们分别为每次更新使用整个数据集,这也被称为批量梯度下降。在 Python 中,我们导入了一些有用的库,并建立了简单的线性回归模型:

然后我们要引入我们的训练数据,定义学习率( α =0.001),初始化我们的起始参数( w =3, b =-1),最后训练我们的模型。对于每个时期,我们将参数的更新值、成本和一些特定的预测 y 值存储在列表中。列表项随后被存储在 numpy 数组中,作为我们动画情节的原始数据。

请注意,选择 0.001 这个特别小的学习率是为了防止在梯度下降的第一个时期出现过大的步长。较大的学习速率(例如 α =0.1)通常导致需要较少历元的更快的模型收敛。然而,在梯度下降的第一个时期,过大的步长往往会导致不太吸引人的动画,甚至无法收敛。为了确保我们拟合的参数收敛到它们的真实值,我们用 sklearn 的先天线性回归模型来验证我们的结果。

既然我们现在确信我们的梯度下降算法按计划工作,我们可以继续动画。

梯度下降动画(简单线性回归):

随着数据点的生成和存储,我们现在可以开始制作一些动画了。例如,我们可以绘制成本函数和参数相对于时期的值,同时绘制相应的回归线:

这些相当基本的曲线揭示了梯度下降的一个非常重要的特征:如果设置正确,在梯度下降的开始,成本迅速下降,参数值显著变化。随着时代的上升,只能观察到成本和参数值的微小变化。因此,绘制我们最初存储的所有值似乎是不利的。虽然主要集中在拟合过程的第一个时期,但我们可以在生成这些资源密集型动画时,在不破坏 Python 的情况下可视化大多数“动作”。在尝试了一些不同的点选择来绘图后,我决定连续利用拟合过程的前 50 个时期,随后仅每第 5 个或第 200 个数据点绘图,直到时期的数量达到 12,000。在下面这段代码中,我们定义了我们想要在我们的图中包含的纪元,并在每个 for 循环后通过快照创建上面的动画。通过调用相机的动画功能,我们可以把我们的快照变成动画。

在我看来,返回正在绘制的 Jwb 的最终值是有意义的,这样我们就可以确保我们在动画中粗略地可视化了模型收敛,尽管没有使用我们在拟合过程中存储的所有点。尤其是在 3D 动画中,仅仅通过查看图表有时很难确认前者。

如果我们绘制关于参数 wb 的成本函数,可以获得更有趣的可视化梯度下降的方式,因为这更接近于 Jwb 的函数的实际概念。此外,我们试图在回归线和我们的训练数据之间引入连接线(虚线)来描绘各自的残差。

对我们之前的代码做了一些小的改动,就可以得到上面的动画:

参考前面提到的“山”类比,创建梯度下降的 3D 可视化似乎是可取的。然而,这需要一些初步工作,因为我们必须创建一些在拟合过程中从未遇到过的数据点。换句话说,我们需要在预定义的参数值范围内计算每一对可能的 wb 的成本,以获得表面图。幸运的是,numpy 有一个名为 meshgrid 的内置函数,它使我们能够为我们的三维绘图创建坐标网格。

使用下面的代码,我们现在可以在三维空间中可视化梯度下降。

我希望你喜欢这篇文章。如果有任何不清楚的地方,或者你发现了任何错误,请随时发表评论。在下一篇文章中,我将使用多线性回归的例子来处理渐变下降的动画。完整的笔记本可以在我的 GitHub 上找到。感谢您的关注!

参考文献:

  • http://fa . bianp . net/teaching/2018/eecs 227 at/gradient _ descent . html
  • https://machine learning mastery . com/gentle-introduction-mini-batch-gradient-descent-configure-batch-size/

梯度下降,在 Python,第 1 部分:麻烦的理论中有清楚的解释

原文:https://towardsdatascience.com/gradient-descent-clearly-explained-in-python-part-1-the-troubling-theory-49a7fa2c4c06?source=collection_archive---------40-----------------------

当你第一次进入机器学习和数据科学领域时,你肯定会遇到的第一件事就是梯度下降。但问题是,到底什么是梯度下降**?它是做什么的?是一回事,还是梯度下降有不同版本?到本文结束时,你将能够回答所有这些问题。**

图片来自维基百科

到本文结束时,您将(希望)拥有:

  1. 了解什么是梯度下降实际上和它做什么。
  2. 了解梯度下降的不同“味道”。

在第二部分中,我们将从头开始编写我们在本文中学到的所有内容。所以,敬请关注!

事不宜迟,我们开始吧!

由 Wander Labs 在 Unsplash 上拍摄的照片

直观理解梯度下降

现在,在我开始抛出令人困惑的希腊符号之前(不幸的是我会在某个时候抛出,但请耐心等待),我想让您从广义上直观地了解它到底是做什么的。

现在,想象你在一座山顶上,你想找到最快的方式从山顶下来。因此,使用普通逻辑,可以如下处理该问题:

  1. 环顾四周,看看下降的最佳方向是什么。
  2. 朝那个方向迈出一步。
  3. 重复这个过程,直到你到达底部。

照片由 Gavin Spear 在 Unsplash 上拍摄

注意:这个类比中需要记住的两个重要因素是:

  1. 步长 : 步长应该有多大/多小?
  2. 重复 : 这个过程我要重复多少次?

现在,记住这个类比,让我们来看看技术!

成本函数

现在,在我们进入文章的主要数学之前,让我们简单地谈论一下成本函数。一个成本函数本质上是一个衡量你的模型表现如何的函数。我的意思是,线索就在名字里:它测量你的模型预测的损失。一些类型的成本函数包括:

  1. 均方误差
  2. 绝对平均误差
  3. 交叉熵
  4. 均方根误差

例如,均方误差的算法如下:

照片由 Richie Ng 拍摄

如果你曾经参加过 Kaggle 比赛,这些通常被称为评估指标。通常,损失越低,您的型号性能越好。因此,举例来说,如果你预测房价并使用均方差*,而你的成本是 25000 美元,这意味着你的模型表现不佳,因为它产生了 25000 美元的预测误差。*

回到我们的类比,如果你想象有一个 U 形曲线而不是一座山,有一个成本函数而不是一个人,初始成本值可能是 25,500。梯度下降的目的是将该成本最小化到 0( 全局最小值)或更小的值(局部最小值)。

数学上理解梯度下降

快速提示:如果你想跳过这一部分,请便。但我向你保证,一旦你明白了,就不难理解了。我将给出一个非常高的梯度下降的数学概述,所以不要担心不能理解一切!

梯度下降的正式定义如下:

梯度下降是一种优化算法,用于寻找函数的最小值。它是通过得到一条线的负斜率的偏导数来计算的。

老实说,那句话相当含糊,所以让我们用数学来分解它。梯度下降的数学表示如下:

照片由 Richie Ng 拍摄

是的,我知道乍一看这看起来像一些复杂的爱因斯坦华夫饼,但请耐心听我说。现在,让我们理解一些符号:

θj :这是你的参数向量中的一个参数,或者系数。本质上是你的价值乘以什么,你在优化什么。

α 这控制了步长。在机器学习行话中,它通常被称为学习率。**

m:数据集中训练样本的数量

h(x) :您对数值的预测

y :实际值

x(i)j :这是指第 j 行第 i 列的一个 your X 变量。我在这里不会讲太多技术,所以不要太担心,因为 Python 为我们完成了大部分困难的部分。

σ:这只是说我们在对将要计算的值求和。

:=这意味着我们用将要计算的值替换当前值

本质上,这个算法陈述的是:

{

对于我们试图优化的每个参数,按如下方式更改值:

  1. 取我们参数的当前值
  2. 通过得到我们的预测值减去实际值的总和乘以我们的 X 特征并乘以我们的学习率来计算梯度
  3. 从上面计算的值中减去我们当前的参数值
  4. 重复一定的次数。

}

现在,关于学习率和初始参数的一个重要注意事项:

照片可在 StackOverflow 上找到

  1. 如果学习率过大,梯度下降将错过局部最小值,并在不同点不受控制地波动
  2. 如果学习率太小,算法达到最小值的时间太长,会耗尽你电脑的电量。
  3. 初始参数一般随机设置。这就是(yep) 随机初始化 。不同的初始化可能导致算法只达到局部最小值而不是全局最小值。

梯度下降的类型

作者照片

*上述算法被称为**批量梯度下降。*之所以取这个名字,是因为在每一步,它都会计算整个(批次)数据集的梯度。现在,你可能已经猜到了,但在大型数据集上,这是不可行的,因为这种工作所需的时间和计算能力太长了。这让我们想到了梯度下降的另外两种流行“味道”:

  1. 随机梯度下降
  2. 小批量梯度下降

随机梯度下降

照片由 Richie Ng 拍摄

在这种方法中,不是在数据集的所有上计算梯度,而是在随机选择的训练样本上计算梯度(因此得名“随机”,意思是随机的)。这种方法比批量梯度下降快得多,因为它当时只计算一个示例的梯度,而不是整个数据集。

然而,由于其随机性,它并不倾向于遵循平滑的曲线,而是倾向于一直来回跳动。然而,在大型数据集上,它肯定会优于批量梯度下降

小批量梯度下降

照片由 Richie Ng 拍摄

在这种方法中,它不是计算整个数据集或数据集的随机样本的梯度,而是计算数据集的小子集,通常称为小批量。这也是一个非常强大的算法,因为它提供了速度和准确性,并且不像随机梯度下降那样随机。**

然而,根据参数的初始化,它有时可能会陷入局部最小值。因此,虽然它可能返回经过优化的良好参数,但它们不是最佳参数。

这实质上是梯度下降及其高级实现。现在,我确实把事情简单化了,但是这是一个基础,你可以学习并尝试自己实现它!我肯定会建议浏览互联网,以获得更好的理解!

唷!这是很大的收获,坚持到最后做得很好。如果你想要一个更严谨和直观的解释,请查阅以下资源:

  1. 逐步梯度下降通过 Statquest
  2. 梯度下降:机器人的人工智能
  3. Andrew NG 的 Coursera 机器学习课程

如果想对机器学习有一个全面的了解,我强烈建议考最后一门。安德鲁擅长用简单的术语直观地解释复杂的话题。

现在,这是一个很大的挑战。因此,与其拼命去想,不如试着休息一下。让你的大脑休息一下,让这个话题沉淀下来。然后,当你觉得神清气爽的时候,再回来试着更好地把握概念!

照片由真诚媒体在 Unsplash 上拍摄

非常感谢你阅读这篇文章,我将很快推出第二部分,所以请做好准备,因为真正的乐趣才刚刚开始!

梯度下降,在 Python 中有清楚的解释,第 2 部分:引人注目的代码。

原文:https://towardsdatascience.com/gradient-descent-clearly-explained-in-python-part-2-the-compelling-code-c21ee26fbc28?source=collection_archive---------27-----------------------

注意 : 这是我上一篇文章的后续,这篇文章讨论了梯度下降的理论方面。如果你想了解一下,请点击 链接 。如果你对这个理论不感兴趣,你可以直接加入!

作者照片

梯度下降是数据科学的基础,无论是深度学习还是机器学习。对梯度下降原理的扎实理解,一定会对你以后的工作有所帮助。

你将真正理解这些超参数做什么,后台发生什么,以及你**如何处理你在使用该算法时可能面临的问题,而不是玩弄超参数并希望得到最好的结果。

然而,梯度下降并不局限于一种算法。梯度下降的另外两种流行的“味道”(随机和小批量梯度下降)建立在主算法的基础上,并且可能是比普通批量梯度下降更多的算法。因此,我们还必须对这些算法有深入的了解,因为当我们的算法没有达到预期效果时,我们需要了解和分析它们的一些额外的超参数。

虽然理论对于牢固理解手头的算法至关重要,但梯度下降的实际编码及其不同的“味道”可能会被证明是一项困难但令人满意的任务。为了完成这项任务,文章的格式如下所示:

  1. 每种算法的简要概述。
  2. 算法的代码
  3. 对代码中不清楚部分的进一步解释

我们将使用著名的波士顿住房数据集,它是 scikit-learn 中预先构建的。我们还将从头开始构建一个线性模型,所以请抓紧,因为你即将进入一个全新的世界!

布拉登·科拉姆在 Unsplash 拍摄的照片

好的,那么首先让我们做一些基本的导入(通常的东西)。我不打算在这里做 EDA,因为这不是我们这篇文章的真正目的。然而,我将展示一些可视化效果来澄清一些事情。

*import numpy as np
import pandas as pd 
import plotly.express as px
from sklearn.datasets import load_boston
from sklearn.metrics import mean_squared_error*

好了,为了让我们看到数据的样子,我将数据转换成 DataFrame 并显示输出。

*data = load_boston()df = pd.DataFrame(data['data'],columns=data['feature_names'])
df.insert(13,'target',data['target'])
df.head(5)*

作者照片

嗯,这里没什么特别的,我确信如果你在遇到这个之前做过任何 ML 项目。

现在,我们将定义我们的特征(X)和目标(y)。我们还将定义我们的参数向量,命名为 thetas,并将其初始化为零。

*X,y = df.drop('target',axis=1),df['target']thetas = np.zeros(X.shape[1])*

价值函数

回想一下,成本函数是用来衡量模型性能的,也是梯度下降法旨在改进的。我们将使用的成本函数被称为 MSE,或均方误差。公式是这样的:

照片由 Richie Ng 拍摄

好,让我们把它编码出来:

*def cost_function(X,Y,B):predictions = np.dot(X,B.T)cost = (1/len(Y)) * np.sum((predictions - Y) ** 2)return cost*

这里,我们将输入、标签和参数作为输入,并使用线性模型进行预测,获得成本,然后返回。如果第二行让您困惑,请回忆一下线性回归公式:

因此,我们实际上是在获得我们的每个特征和它们相应的权重之间的点积。如果你仍然不确定我在说什么,看看这个视频。

很好,现在让我们测试一下我们的成本函数,看看它是否真的有效。为了做到这一点,我们将使用 scikit-learn 的 mean_squared_error,获得结果,并将其与我们的算法进行比较。

*mean_squared_error(np.dot(X,thetas.T),y)OUT: 592.14691169960474cost_function(X,y,thetas)OUT: 592.14691169960474*

太棒了,我们的成本函数起作用了!

特征缩放

特征缩放是对线性模型(线性回归、KNN、SVM)至关重要的预处理技术。本质上,特征被缩小到更小的尺度,并且特征也在一定的范围内。将特征缩放想象成这样:

  1. 你有一座非常大的建筑
  2. 您想要保持建筑的形状,但是想要将其调整为更小的比例

要素缩放通常用于以下情况:

  1. 如果算法使用欧几里德距离,那么特征缩放是必需的,因为欧几里德距离对大的量值是敏感的
  2. 特征缩放也可用于归一化具有大范围值的数据
  3. 特征缩放还可以提高算法的速度

虽然有许多不同的功能缩放方法可用,但我们将使用以下公式构建 MinMaxScaler 的自定义实现:

作者照片

由于上述原因,我们将使用缩放。

现在,对于 python 实现:

*X_norm = (X - X.min()) / (X.max() - X.min())
X = X_norm*

这里没什么特别的,我们只是把公式翻译成代码。现在,节目真正开始了:梯度下降!

照片由戴恩·托普金在 Unsplash 上拍摄

梯度下降

照片由 Gavin Spear 在 Unsplash 上拍摄

具体来说,梯度下降是一种优化算法,通过迭代遍历数据并获得偏导数来寻找函数的最小值(在我们的情况下,MSE)。

如果这看起来有点复杂,试着想象梯度下降,就好像一个人站在山顶上,他们正试图尽可能快地从山上爬下来,重复地向山的负方向“迈步”,直到他们到达底部。

现在,梯度下降有不同的版本,但你最常遇到的是:

  1. 批量梯度下降
  2. 随机梯度下降
  3. 小批量梯度下降

我们现在将依次讨论、实施和分析其中的每一项,让我们开始吧!

批量梯度下降

图片来自维基百科

*批量梯度下降可能是你遇到的第一种梯度下降。现在,我在这篇文章中不是很理论化(你可以参考我的上一篇文章),但本质上它计算的是**整体(*批次 ) 数据集上系数的偏导数。这就是为什么你可能已经猜到它在大型数据集上会很慢。

然而,关于批量梯度下降的一个很好的想法是,当它达到最小值时,它会自动采取较小的步骤,因此不需要学习计划(我将在后面谈到这一点)。

作者照片

我们的数据集很小,所以我们可以像这样实现批量梯度下降:

*def batch_gradient_descent(X,Y,theta,alpha,iters):cost_history = [0] * iters  # initalize our cost history listfor i in range(iters):         prediction = np.dot(X,theta.T)                  theta = theta - (alpha/len(Y)) * np.dot(prediction - Y,X)   cost_history[i] = cost_function(X,Y,theta)               return theta,cost_history*

为了澄清一些术语:

alpha :这是指学习率。

iters: 要运行的迭代次数。

太好了,现在让我们看看结果吧!

**batch_theta,batch_history=batch_gradient_descent(X,y,theta,0.05,500)**

好吧,不是很快,但也不是很慢。让我们用新的和改进的参数来直观显示和获得我们的成本:

*cost_function(X,y,batch_theta)OUT: 27.537447130784262*

哇,从 592 到 27!这只是梯度下降威力的一瞥!让我们将迭代次数的成本函数可视化:

*fig = px.line(batch_history,x=range(5000),y=batch_history,labels={'x':'no. of iterations','y':'cost function'})
fig.show()*

作者照片

好的,看这个图表,我们在大约 100 次迭代后达到一个大的下降,从那里开始,它逐渐下降。

因此,总结批量梯度:

赞成的意见

  1. 有效且具有平滑曲线,当斜率达到全局最小值时会自动降低。
  2. 最准确且最有可能达到全局最小值

骗局

  1. 在大型数据集上可能会很慢
  2. 计算成本高

随机梯度下降

照片由 Richie Ng 拍摄

这里,不是计算整个训练集的偏导数,偏导数的计算只在一个随机样本上进行(随机意味着随机)。

这很好,因为计算只需要在一个训练样本上进行,而不是整个训练集,这使得它更快,更适合大型数据集。

然而,由于其随机性质,随机梯度下降不具有像批量梯度下降那样的平滑曲线,尽管它可能返回良好的参数,但它不能保证达到全局最小值。

学习时间表

解决随机梯度下降不能在最小值上稳定的问题的一种方法是使用被称为学习计划的东西。**

本质上,这逐渐降低了学习率。因此,学习率最初很大(这有助于避免局部最小值),并随着接近全局最小值而逐渐降低。但是,您必须小心:

  1. 如果学习率降低得太快,那么算法可能会卡在局部最小值,或者它可能会在最小值中途冻结。
  2. 如果学习率降低得太慢,您可能会在最小值附近跳很长时间,仍然得不到最佳参数

我们现在将使用基本学习计划实施随机梯度下降:

*t0,t1 = 5,50 # learning schedule hyperparametersdef learning_schedule(t):return t0/(t+t1)def stochastic_gradient_descent(X,y,thetas,n_epochs=30):c_hist = [0] * n_epochs # Cost history listfor epoch in range(n_epochs):for i in range(len(y)):random_index = np.random.randint(len(Y))xi = X[random_index:random_index+1]yi = y[random_index:random_index+1]prediction = xi.dot(thetas)gradient = 2 * xi.T.dot(prediction-yi)eta = learning_schedule(epoch * len(Y) + i)thetas = thetas - eta * gradientc_hist[epoch] = cost_function(xi,yi,thetas)return thetas,c_hist*

现在让我们运行我们的函数:

*sdg_thetas,sgd_cost_hist = stochastic_gradient_descent(X,Y,theta)*

好的,太好了,它起作用了!现在让我们看看结果:

*cost_function(X,y,sdg_thetas)OUT:
29.833230764634493*

哇!我们从 592 到 29,但是注意:我们只做了 30 次迭代。通过批量梯度下降,我们在 500 次迭代后得到了 27 次!这只是随机梯度下降的非凡力量的一瞥。

让我们用一个线形图来再次形象化这一点:

作者照片

由于这是一个小数据集,批量梯度下降就足够了,然而这只是显示了随机梯度下降的威力。

总结一下随机梯度下降:

优点:

  1. 与批量梯度下降相比更快
  2. 更好地处理大型数据集

缺点:

  1. 很难确定某个最小值
  2. 并不总是有一个清晰的路径,可以在最小值附近反弹,但永远不会达到最优最小值

小批量梯度下降

照片由 Richie Ng 拍摄

好了,就快到了,只差一个了!现在,在小批量梯度下降中,我们不是计算整个训练集或随机示例的偏导数,而是计算整个训练集的小子集的偏导数。

这给了我们比批量梯度下降快得多的速度,并且因为它不像随机梯度下降那样随机,所以我们更接近最小值。然而,它容易陷入局部极小值。

同样,为了解决陷入局部最小值的问题,我们将在实现中使用一个基本的学习时间表。

*np.random.seed(42) # so we get equal resultst0, t1 = 200, 1000
def learning_schedule(t):return t0 / (t + t1)def mini_batch_gradient_descent(X,y,thetas,n_iters=100,batch_size=20):t = 0c_hist = [0] * n_itersfor epoch in range(n_iters):shuffled_indices = np.random.permutation(len(y))X_shuffled = X_scaled[shuffled_indices]y_shuffled = y[shuffled_indices]for i in range(0,len(Y),batch_size):t+=1xi = X_shuffled[i:i+batch_size]yi = y_shuffled[i:i+batch_size]gradient = 2/batch_size * xi.T.dot(xi.dot(thetas) - yi)eta = learning_schedule(t)thetas = thetas - eta * gradientc_hist[epoch] = cost_function(xi,yi,thetas)return thetas,c_hist*

让我们运行并获得结果:

*mini_batch_gd_thetas,mini_batch_gd_cost = mini_batch_gradient_descent(X,y,theta)*

以及带有新参数的成本函数:

*cost_function(X,Y,mini_batch_gd_thetas)OUT: 27.509689139167012*

又一次令人惊叹。我们运行了批量梯度下降迭代的 1/5,得到了更好的分数!谈效率!

让我们再次绘制出函数:

作者照片

好了,我的梯度下降系列到此结束!我真的希望你喜欢它,并随时询问任何问题或要求任何澄清!

现在,我建议你出去休息一下,因为有太多东西要消化了!尽可能地享受你的时间,记住:学习是有趣的,所以每天都要学!

普里西拉·杜·普里兹在 Unsplash 上的照片

梯度下降解释

原文:https://towardsdatascience.com/gradient-descent-explained-9b953fc0d2c?source=collection_archive---------6-----------------------

梯度下降综合指南

优化是指最小化/最大化由 x 参数化的目标函数 f(x)的任务。在机器/深度学习术语中,它是最小化由模型参数 w ∈ R^d.
参数化的成本/损失函数 J(w)的任务。优化算法(在最小化的情况下)具有以下目标之一:

  1. 找到目标函数的全局最小值。如果目标函数是凸的,即任何局部最小值都是全局最小值,这是可行的。
  2. 找到目标函数在其邻域内的最低可能值。如果目标函数不像大多数深度学习问题那样是凸的,通常就是这种情况。

梯度下降

梯度下降是机器/深度学习算法中使用的优化算法。梯度下降的目标是使用迭代最小化目标凸函数 f(x)。

凸函数 v/s 不是凸函数

成本函数的梯度下降。

梯度下降背后的直觉

为方便起见,我们来看一个简单的线性模型。

误差= Y(预测)-Y(实际)

机器学习模型总是希望最大精度的低误差,为了减少误差,我们将直觉地告诉我们的算法,你正在做一些需要纠正的错误,这将通过梯度下降来完成。

我们需要最小化我们的误差,为了得到指向最小值的指针,我们需要走一些被称为 alpha(学习率)的步骤。

实施梯度下降的步骤

  1. 随机初始化值。
  2. 更新值。

3.重复直到斜率=0

导数是一个来自微积分的术语,计算为图形在特定点的斜率。斜率是通过在该点画一条切线来描述的。所以,如果我们能计算出这条切线,我们就能计算出达到最小值的方向。

学习率一定要明智的选择为:
1。如果太小,那么模型需要一些时间来学习。
2。如果它太大,模型会收敛,因为我们的指针会射出,我们将无法达到最小值。

大学习率 v/s 小学习率,来源

不同学习率的梯度下降,来源

然而,普通梯度下降法不能保证良好的收敛性,原因如下:

  • 选择一个合适的学习速度可能会很麻烦。学习率过低会导致训练缓慢,而学习率过高会导致斜率超调。
  • 香草梯度下降面临的另一个关键障碍是它避免陷入局部最小值;这些局部极小值被同样误差的小山包围,这使得香草梯度下降很难逃脱它。

显示曲线平缓和陡峭区域的等高线图,来源

简而言之,我们朝着最小值迈出的每一步都会降低我们的斜率,现在如果我们想象,在曲线的陡峭区域,导数将会很大,因此我们的模型采取的步骤也会很大,但是当我们进入斜率平缓的区域时,导数将会降低,达到最小值的时间也会减少。

基于动量的梯度下降

如果我们考虑,简单梯度下降完全仅依赖于计算,即,如果有 10000 个步骤,那么我们的模型将尝试实施简单梯度下降 10000 次,这显然太费时且计算昂贵。

在门外汉的语言中,假设一个人正在走向他的家,但他不知道路,所以他向路人问路,现在我们希望他走一段距离,然后问路,但人在他走的每一步都在问路,这显然更耗时,现在比较简单梯度下降的人和他的目标与最小值。

为了避免普通梯度下降的缺点,我们引入了基于动量的梯度下降,其目标是降低计算时间,这可以在我们引入经验的概念时实现,即使用先前步骤的置信度。

基于动量梯度下降的伪代码;

update = learning_rate * gradient
velocity = previous_update * momentum
parameter = parameter + velocity – update

以这种方式,我们不是一次又一次地计算新的步骤,而是对衰减进行平均,并且随着衰减增加,其对决策的影响减小,因此越老的步骤对决策的影响越小。
历史越悠久,就要迈出越大的步伐。

即使在平缓区域,基于动量的梯度下降也由于其承受的动量而迈出了大步。

香草梯度下降 v/s 梯度下降带动量,来源

但是由于较大的步数,当它由于陡峭的坡度而在最小值附近振荡时,它以更长的距离超过了它的目标,但是尽管有这些障碍,它还是比普通的梯度下降快。

简而言之,假设一个人想要到达 1200 米远的目的地,但他不知道路径,所以他决定每走 250 米就问路,现在如果他问路 5 次,他就已经走了 1250 米,这说明他已经超过了目标,要实现目标,他需要往回走。基于动量的 GD 也是类似的情况,由于经验丰富,我们的模型采取了较大的步骤,这导致了超调,因此错过了目标,但为了达到最小值,模型必须回溯其步骤。

内斯特罗夫加速梯度下降法

为了克服基于动量的梯度下降的问题,我们使用 NAG,在这种情况下,我们首先移动,然后计算梯度,这样,如果我们的振荡过冲,那么与基于动量的梯度下降相比,它一定是不重要的。

NAG 背后的直觉,来源

内斯特罗夫加速梯度(NAG)是一种为我们的动量提供历史的方法。我们现在可以通过计算相对于我们现在的参数θ的角度来充分地向前看。

基于动量梯度下降 v/s 内斯特罗夫加速梯度下降,来源

梯度下降策略。

随机梯度下降

在这里,学习发生在每个例子上:

  • 打乱训练数据集以避免预先存在的示例顺序。
  • 将训练数据集划分成 m 个例子。

优点:——

a.易于安装在内存中
b .计算速度快
c .对大型数据集高效

缺点:-

a.由于频繁更新,朝着最小值采取的步骤非常嘈杂。
b .噪音会使等待时间变长。
c .频繁更新的计算开销很大。

批量梯度下降

这是一种贪婪的方法,我们必须对每次更新的所有例子求和。

优点:-

a.噪音较小的步骤
b .产生稳定的 GD 收敛。c .计算效率高,因为所有资源不是用于单个样本,而是用于所有训练样本

缺点:-

a.可能需要额外的内存。处理大型数据库可能需要很长时间。
c .近似梯度

小批量梯度下降

小批量梯度下降法不是遍历所有样品,而是根据批量大小对少量样品进行汇总。

它是批梯度下降和随机梯度下降的和。

优点:-

a.易于记忆。b .计算效率高。
c .稳定误差 go 和收敛。

批量 v/s 随机 v/s 微型批量梯度下降,来源

如果我们用梯度下降来处理稀疏数据会怎么样?

在稀疏数据的情况下,我们将经历稀疏的 ON(1)特征和更频繁的 OFF(0)特征,现在,大部分时间梯度更新将为零,因为在大多数情况下导数为零,当导数为零时,步长将太小而无法达到最小值。

对于频繁特征,我们要求低学习率,但是对于高特征,我们要求高学习率。

因此,为了提高我们的稀疏自然数据模型,我们需要选择自适应学习率。

如果你喜欢这篇文章,请考虑订阅我的简讯: 达克什·特雷汉每周简讯

结论

希望这篇文章不仅增加了你对梯度下降的理解,还让你意识到机器学习并不难,并且已经在你的日常生活中发生了。

一如既往,非常感谢您的阅读,如果您觉得这篇文章有用,请分享!:)

要了解更多参数优化技术,请访问:-

[## 解释参数优化

梯度下降的简要描述指南,ADAM,ADAGRAD,RMSProp

towardsdatascience.com](/parameters-optimization-explained-876561853de0)

参考资料:

【1】梯度下降算法及其变体由 Imad Dabbura

[2] 学习参数,第 2 部分:基于动量的&内斯特罗夫加速梯度下降作者阿克谢·L·钱德拉

[3]Sebastian Ruder 的梯度下降优化算法概述

[4] 理解梯度下降背后的数学原理Parul Pandey 著。

[5] 深度学习 (padhAI)作者 Mitesh Khapra 博士和 Pratyush Kumar 博士

封面模板是我在 canva.com 上设计的,来源在每张图片上都有提及,未提及的图片来自我的笔记本。

请随意连接:

加入我在【www.dakshtrehan.com】

LinkedIN ~https://www.linkedin.com/in/dakshtrehan/

Instagram ~https://www.instagram.com/daksh_trehan/

Github ~https://github.com/dakshtrehan

查看我的其他文章:-

利用深度学习检测新冠肺炎。

逻辑回归解释

线性回归解释

确定最适合您的 ML 模型。

为菜鸟服务数据科学。

将机器学习技术与现实生活联系起来。

关注更多机器学习/深度学习博客。

干杯。

梯度下降解释和实施

原文:https://towardsdatascience.com/gradient-descent-explanation-implementation-c74005ff7dd1?source=collection_archive---------15-----------------------

香草梯度下降算法分步指南

梯度下降可能是最著名的优化算法,在机器学习的世界中,你肯定已经直接或间接使用过梯度下降。你可能已经知道,通过向梯度的负方向移动微小的步长,可以帮助最小化损失函数。但是具体怎么做呢?除了直接使用包含在包中的梯度方法,我们如何实现我们自己的方法并更仔细地观察梯度下降呢?

理解渐变

在这篇文章中,让我们一点一点地打破梯度下降,并通过实现我们自己的来加深对它的理解。现在让我们从最简单的例子开始:

假设我们有函数f(x) = x^2,其中x的范围从-1 到 1,给定x在该范围内随机开始,如何求f(x)的最小值?

显然在这个例子中,最小值位于x = 0,我们希望

  • 使x向右移动if x < 0
  • 使x向左移动if x > 0

那么我们如何做到这一点呢?你可能还会注意到函数的梯度

  • grad > 0x > 0
  • grad < 0x < 0

x的移动方向相反!梯度下降利用这一点,让x向其梯度的相反方向移动。在这种情况下,无论x在哪里,它都会移动到最小。

下一个问题是x应该移动多远,这导致了学习率,它是许多机器学习算法中的参数。

事实上,在上面的例子中,tanα是梯度,在每一步,我们使x以步长tanα * learning_rate移动,其中学习率成为控制下降速度的可调参数。

首次实施

记住上面的内容,我们可以让我们的第一个实现找到函数x^2的最小值。

在每次迭代中,x -= lr*grad_fn(x)使其总是向最小值移动,我们也可以绘制出x的轨迹:

x从-1 开始,逐渐下降到 0。还要注意,它在开始时移动得更快,当接近目标时变慢,这是因为绝对梯度在开始时更高。

优化参数

现在让我们来看一个优化参数的例子。假设我们试图用函数优化参数:

目标是最小化损失(y — f(x))^2,参数ab的相应梯度为:

注意这里的xy被认为是常数。

现在让我们实现函数优化:

这里,我们更新每个输入x, y对的参数,并得到结果:

您可以看到,更新过程是不稳定的,对于参数a,在它移动到最佳值之前,它首先下降(向相反的方向)。这是因为我们更新了每个输入的参数,因为每个单独的输入都可能在任意方向更新参数。我们能生成更平滑的线条吗?答案导致批量梯度下降。

批量梯度下降

在实际使用情况下,参数不是每次在单个数据点上更新,而是应用批量更新,其中在每次迭代(历元)中,基于一批数据点的平均值更新参数。在这种情况下,我们的更新公式是:

计算一批梯度的总和,取平均值作为要更新的梯度:

这里需要更高的迭代次数,因为每批只贡献 1 次更新(我们将所有数据点放入一批,可以有不同的组合),这一次更新过程如下所示:

更加平滑和稳定,但是代价是需要更多的计算。

结论

希望到这里为止,你已经获得了对香草梯度下降稍微好一点的理解。传统的梯度下降法不能保证最优,事实上,当目标函数中有多个流域时,它很容易陷入局部极小,因为每次参数仅基于梯度轻微移动,不允许有随机性。如果你感兴趣,请在这里查看完整的实现。

接下来,我将介绍 SGD & Momentum ,它为普通梯度下降增加了一些变化,并解决了它的一些问题。

参考:

  1. https://ml-cheat sheet . readthedocs . io/en/latest/gradient _ descent . html
  2. https://ruder . io/optimization-gradient-descent-descent/index . html # gradient descent optimizationalgorithms

深度学习模型的梯度下降扩展

原文:https://towardsdatascience.com/gradient-descent-extensions-to-your-deep-learning-models-32045ccfa644?source=collection_archive---------45-----------------------

了解不同的可用方法,并选择最适合的方法来解决您的问题。

来源: Pixabay

介绍

本文的目的是探索不同的梯度下降扩展,如动量,Adagrad,RMSprop…

在之前的文章中,我们已经研究了在深度学习模型中实现反向传播的三种方法:

  • 梯度下降
  • 随机梯度下降
  • 小批量随机梯度下降

在此基础上,我们保留小批量,因为它允许更高的速度,因为它不必计算整个数据集的梯度和误差,并且消除了随机梯度下降中存在的高可变性。

这些方法有所改进,比如动量法。此外,还有其他更复杂的算法,如 Adam、RMSProp 或 Adagrad。

让我们看看他们!

动力

想象自己又回到了童年,有一个穿上溜冰鞋,爬上最陡的街道,开始沿着它走下去的好主意。你完全是初学者,这是你第二次穿冰鞋。

我不知道你们中有没有人真的这么做过,但是我确实做过,所以让我来解释一下发生了什么:

  • 你刚刚起步,速度很慢,你甚至似乎在控制之中,你随时都可能停下来。
  • 但是你走得越低,你移动得越快:这叫做动量。
    所以你走的路越多,你背负的惯性就越大,你走的就越快。
  • 好吧,对于那些好奇的人来说,故事的结尾是在陡峭街道的尽头有一个栅栏。剩下的你可以想象…

动量技巧正是这样。当我们沿着损失曲线计算梯度并进行更新时,我们会更加重视梯度最小化方向上的更新,而不太重视其他方向上的更新。

作者图

所以,结果是加快了网络的训练。

此外,多亏了这一时刻,我们本可以避开路上的小坑洼或小洞(由于速度,我们可以飞越它们)。

你可以在这篇伟大的文章中了解更多关于这种技术背后的数学基础:http://cs231n.github.io/neural-networks-3/#sgd

内斯特罗夫动量

回到之前的例子:我们正在全速前进(因为我们已经建立了很大的势头),突然我们看到了它的尽头。我们希望能够刹车,减速以避免撞车。这正是内斯特罗夫所做的。

内斯特罗夫计算梯度,但不是在当前点,而是在我们知道我们的时刻将带我们去的点,然后应用一个修正。

按作者分列的数字

请注意,使用标准矩,我们计算梯度(小橙色向量),然后在梯度方向上迈出一大步(大橙色向量)。

使用内斯特罗夫,我们将首先在我们先前的梯度(绿色向量)的方向上进行一次大的跳跃,测量梯度并进行适当的校正(红色向量)。

在实践中,它比单独使用动量要好得多。这就像计算未来的权重梯度(因为我们加入了之前计算的时刻)。

你可以在这篇伟大的文章中了解更多关于这种技术背后的数学基础:http://cs231n.github.io/neural-networks-3/#sgd

内斯特罗夫动量和标准动量都是 SGD 的延伸。

我们现在将要看到的方法是基于自适应学习速率的,允许我们加快或减慢更新权重的速度。例如,我们可以在开始时使用高速,在接近最小值时降低速度。

自适应梯度

它保存计算梯度的历史记录(特别是梯度平方和的历史记录),并对更新的“步骤”进行标准化。

其背后的直觉是,它识别具有非常高梯度的参数,这些参数的权重更新将非常突然,然后给它们分配较低的学习速率以减轻这种突然性。

同时,具有非常低的梯度的参数将被分配高的学习率。

这样,我们设法加速了算法的收敛。

你可以在它的原始论文中了解更多关于这种技术背后的理论:【http://jmlr.org/papers/v12/duchi11a.html

RMSprop

AdaGrad 的问题是,在计算平方梯度的和时,我们使用的是单调递增函数,这会导致学习速率试图补偿直到变为零才停止增长的值,从而停止学习。

RMSprop 建议使用 decay_rate 来减少梯度的平方和。

论文尚未发表,但可以在这里阅读更多:http://www . cs . Toronto . edu/~ tij men/CSC 321/slides/lecture _ slides _ le C6 . pdf

圣经》和《古兰经》传统中)亚当(人类第一人的名字

最后,Adam 是最现代的算法之一,它通过向更新规则添加动量来改进 RMSprop。它引入了 2 个新参数,beta1 和 beta2,建议值为 0.9 和 0.999。

你可以在这里查看它的论文:https://arxiv.org/abs/1412.6980。

但是,我们应该使用哪一个呢?

来源:原创亚当论文

根据经验,建议从 Adam 开始。如果它不能很好地工作,那么你可以尝试和调整其余的技术。但大多数时候,亚当工作得很好。

您可以查看这些资源,以便更好地理解这些技术,以及如何和何时应用它们:

  • 【https://deepnotes.io/sgd-momentum-adaptive
  • http://ruder . io/optimizing-gradient-descent-descent/index . html # gradient descent optimizationalgorithms

最后的话

一如既往,我希望你喜欢这个职位!

如果你喜欢这篇文章,那么你可以看看我关于数据科学和机器学习的其他文章 这里

如果你想了解更多关于机器学习、数据科学和人工智能的知识 请在 Medium 上关注我,敬请关注我的下一篇帖子!

从零开始梯度下降

原文:https://towardsdatascience.com/gradient-descent-from-scratch-e8b75fa986cc?source=collection_archive---------7-----------------------

在这篇文章中,我将解释什么是梯度下降,以及如何用 Python 从头开始实现它。为了理解它是如何工作的,你需要一些基本的数学和逻辑思维。虽然更强的数学背景更有利于理解导数,但我会尽可能简单地解释它们。

梯度下降可用于不同的机器学习算法,包括神经网络。对于本教程,我们将建立一个线性回归问题,因为它很容易理解和可视化。

我还创建了包含所有解释的 GitHub repo。让我们开始吧。

线性回归

线性回归

为了拟合回归线,我们调整了两个参数:斜率(m)和截距(b)。一旦找到最佳参数,我们通常用均方差(MSE)来评估结果。我们记得 MSE 越小越好。换句话说,我们正试图将其最小化。

函数的最小化是梯度下降算法的确切任务。它获取参数并调整它们,直到达到局部最小值。

让我们一步一步地分解这个过程,并解释一下实际发生了什么:

  1. 首先,我们取一个我们想要最小化的函数,通常它是均方误差函数。
  2. 我们确定参数,例如回归函数中的mb,并对这些参数取 MSE 的偏导数。这是最关键也是最难的部分。每个派生的函数都可以告诉我们应该以哪种方式调整参数以及调整多少。
  3. 我们通过迭代我们的派生函数并逐渐最小化 MSE 来更新参数。在这个过程中,我们使用一个额外的参数learning rate,它帮助我们定义在每次迭代中更新参数的步骤。通过设置一个较小的学习率,我们可以确保我们的模型不会跳过最小均方差点,并很好地收敛。

均方误差

派生物

我们使用偏导数来发现每个参数如何影响 MSE,所以这就是单词 partial 的来源。我们分别对mb求导。看看下面的公式。和 MSE 差不多,不过这次我们加了 f(m,b)进去。它本质上没有改变什么,除了现在我们可以把mb数字插入其中并计算结果。

带输入参数的 MSE

关于m意味着我们导出参数m,基本上,忽略b的情况,或者我们可以说它为 0,反之亦然。为了求偏导数,我们将使用链式法则。当我们需要对包含另一个函数的函数求导时,我们会用到它。

链式法则说,我们应该对外部函数求导,保持内部函数不变,然后用内部函数的导数乘以所有东西。我们现在需要做的就是对下面函数的 mb 求偏导数:

平方误差

如果你是新手,你会惊讶于()²是一个包含y-(mx+b)的外部函数。现在,让我们根据链式法则分解每个步骤:

  1. 对外部函数求导:()²变成2()
  2. 保持内部函数不变:y-(mx+b)
  3. 对 m 求偏导数:0-(x+0)-x。让我们详细说明一下我们是如何得到这个结果的:我们把任何不等于 m 的东西都视为常数。常数总是等于 0。mx的导数是x,因为m的导数是 1,附加在m上的任何数字或变量都留在原地,意思是1*x,或者只是x

把所有的东西放在一起,我们得到了下面的:2(y-(mx+b))*-x。这个可以重写为-2x(y-(mx+b))。太好了!我们可以按照正确的符号重新编写:

关于 m 的偏导数

为了相对于b进行推导,我们遵循相同的链式法则步骤:

  1. ()²变为2()
  2. y-(mx+b)保持不变
  3. 这里y-(mx+b)的导数变成了这个:(0-(0+1))或者-1。原因如下:我们再次把ymx当作常数,所以它们变成了 0。b变成了 1。

把所有东西放在一起:2(y-(mx+b))*-1,或者- 2(y-(mx+b))。同样,正确的符号应该是这样的:

关于 b 的偏导数

唷!最难的部分已经过去了,现在我们可以进入 Python 环境了。

梯度下降

因为我们只有一个输入要素,所以 X 必须是一个 NumPy 向量,它是一个值列表。通过对权重m1m2求导,我们可以很容易地将其扩展到多个特征..等等,但是这次我们做的是简单的线性回归。

看一下代码。我们从用随机值定义mb开始,然后我们有一个 for 循环来迭代派生的函数,每一步都由一个学习速率(lr)来控制。我们使用logmse列表来跟踪我们的进度。

import numpy as np
from sklearn.metrics import mean_squared_errordef gradient_descent(X, y, lr=0.05, epoch=10):'''Gradient Descent for a single feature'''m, b = 0.33, 0.48 # parameterslog, mse = [], [] # lists to store learning processN = len(X) # number of samplesfor _ in range(epoch):f = y - (m*X + b)# Updating m and bm -= lr * (-2 * X.dot(f).sum() / N)b -= lr * (-2 * f.sum() / N)log.append((m, b))mse.append(mean_squared_error(y, (m*X + b)))        return m, b, log, mse

我们可以直观地跟踪算法如何接近局部最小值。肉眼看来,好像没有完全收敛。为了解决这个问题,我们可以增加历元和学习率参数。

****

奖励:随机梯度下降

随机梯度下降仅使用一个样本来更新参数,这使得它更快。我们可以对之前的版本做一些小的修改,看看它的表现如何。

def SGD(X, y, lr=0.05, epoch=10, batch_size=1):'''Stochastic Gradient Descent for a single feature'''m, b = 0.33, 0.48 # initial parameterslog, mse = [], [] # lists to store learning processfor _ in range(epoch):indexes = np.random.randint(0, len(X), batch_size) # random sampleXs = np.take(X, indexes)ys = np.take(y, indexes)N = len(Xs)f = ys - (m*Xs + b)# Updating parameters m and bm -= lr * (-2 * Xs.dot(f).sum() / N)b -= lr * (-2 * f.sum() / N)log.append((m, b))mse.append(mean_squared_error(y, m*X+b))        return m, b, log, mse

我们可以观察到这个过程的随机性。回归线到处跳跃,试图根据一个样本找到最小值。可怜的东西。

****

结论

我们已经从头开始学习了如何实现梯度下降和 SGD。当我们训练神经网络时,我们用同样的方法进行反向传播。如果你对从零开始实现深度神经网络感兴趣,请在评论中告诉我。感谢您的阅读!

阿瑟尼。

梯度下降—一次一步

原文:https://towardsdatascience.com/gradient-descent-one-step-at-a-time-3c39a3642333?source=collection_archive---------12-----------------------

入门

一个直观的,初学者的梯度下降,是用来尽量减少机器学习中的各种损失函数的基本机制指南

照片由 Waranont (Joe) 在 Unsplash 上拍摄

梯度下降(GD)是一种优化算法,用于迭代地最小化任何给定的成本函数。但是什么是成本函数呢?它是一个衡量经过训练的机器学习模型在进行预测时的准确性的函数。常见的例子包括均方误差(MSE)和交叉熵(或对数损失)。

GD 在深度机器学习模型中被大量使用,作为更传统的方法的替代,以最小化成本函数。它更有效地处理深度学习中常见的海量数据。

我们将详细地浏览 GD 来模拟一个过于简化的线性回归问题,以便对其机制有一个直观而深刻的理解。我假设你在解决这个问题的时候对最小二乘法、微积分和线性回归有所了解。

问题设置

这是我们的玩具数据,由 3 个数据点组成:

我们的目标是使用 GD 找到最佳拟合线,然后可以使用它根据一些新的X值预测Y值(也称为线性回归)。回想一下,直线可以完全用两个参数来描述:截距和斜率。因此,如果我们可以通过优化算法找到理想的截距和斜率参数,我们将获得最佳拟合线。

我们的最佳拟合线可以表示如下:

情商。一

其中:

  • y hat 是被预测的因变量
  • x₁是我们要预测y 帽子X
  • θ₀是截距项,需要优化
  • θ₁是要优化的斜率

寻找最佳截距

为了简单起见,我们首先只找出θ₀的最佳值,同时假设θ₁等于 0.64(通过最小二乘法确定)。然后,一旦我们理解了 GD 是如何工作的,我们将使用它来求解最佳截距和斜率参数。所以我们修正后的直线方程变成了:

情商。2

我们首先为截距θ₀选择一个随机值,称为随机初始化。随机初始化是我们最初的猜测,实际上可以是 GD 用来改进的任何实数。

先说 0 代表θ₀(不是巧合,也是我最喜欢的数字!),这给了我们下面一行:

y = 0 + 0.64x

接下来,我们将使用残差平方和 (RSS)损失函数来评估这条线与我们的数据的拟合程度:

RSS 和截距= 0 的最佳拟合线

使用 Eq。2 利用θ₀ = 0,我们得到y,残差,残差平方,残差平方和的以下预测:

简易资讯聚合

随着截距θ₀值的增加,重复上述 RSS 计算,我们得到以下θ₀对 RSS 的散点图:

针对 RSS 的各种拦截的散点图

从图中可以明显看出,截距值为 0.95 时 RSS 最小。但是我们怎么知道它实际上是 0.95,而不是 0.75 到 1.15 之间的某个值呢?我们可以代入一堆不同的截距值,通过试错找到最优值。但是当我们拥有 GD 的时候为什么要这样做呢?

梯度下降法

当 GD 在随机初始化点计算 RSS 时,在 RSS 值较高的情况下,需要相对较大的步长来确定要评估的下一个截距。随着 RSS 在后续迭代中接近零,截距的变化(称为步长)变得更小。换句话说,GD 通过在远离最小 RSS 时采取大步,在接近最小 RSS 时采取小步来确定最佳参数值。

通过使用 RSS 和我们的等式,我们可以得到成本函数的等式,该等式绘出了针对 RSS 的所有可能的截距。2 如下(使用我们的三个原始数据点):

RSS 成本函数

该函数的曲线图看起来如下,基本上与上面的散点图相同,只是添加了一条多项式趋势线:

RSS 成本函数图

我们可以对该函数相对于θ₀求导,并确定截距θ₀的任意值处的斜率:

RSS 成本函数的导数—等式。3

现在我们有了导数,GD 将使用它来找到 RSS 的最低值。像之前一样,假设我们用初始值θ₀ = 0初始化 GD。

在上面的导数中插入θ₀ = 0给我们-5.6,这是 RSS 成本函数在θ₀ = 0的梯度或斜率。注意,θ₀的最佳值是在曲线上梯度为 0 的点处获得的,即在曲线的底部。还记得,当曲线的斜率远离 0 时,GD 采取相对较大的步骤,当曲线的斜率接近 0 时,则采取小步骤。因此,步长的大小应该与曲线的斜率相关,因为它告诉 GD 它应该采取小步还是大步。但是,步长不能太大,以免跳过曲线上的最小点,到达另一边。

步长由称为学习率的参数调节。步长决定了 GD 计算 RSS 时使用的新截距:

step size = slope * learning rate
new intercept = old intercept - step size

学习率被设置为一个很小的数字,通常在实践中为 0.2、0.1 或 0.01。

继续我们的例子,当θ₀ = 0和学习速率0.1时,步长为-0.56:

step size (at θ₀ = 0): -5.6 * 0.1
step size (at θ₀ = 0): -0.56new intercept = 0 - (-0.56)
new intercept = 0.56

到目前为止,评估了两个截距的成本函数图如下所示:

第一步后的 RSS 成本函数

上面的图清楚地表明,随着相对较大的第一步,我们已经非常接近 RSS 的最小值了!回到我们的最佳拟合线,我们可以看到0.56的新截距大大缩小了残差:

RSS 和截距= 0.56 的最佳拟合线

现在让我们进一步接近截距的最佳值。我们回到方程式中的导数。3,并插入新的截距值0.56,这给出了曲线在该截距值处的斜率为-2.2:

RSS slope (at θ₀ = 0.56): -2(1.08-0.56) - 2(0.4-0.56) - 2(1.3-0.56)
RSS slope (at θ₀ = 0.56): -2.2step size (at θ₀ = 0.56): -2.2 * 0.1
step size (at θ₀ = 0.56): -0.22new intercept = 0.56 - (-0.22)
new intercept = 0.78

我们的两个图如下所示:

RSS 成本函数和第二步后的最佳拟合线

总的来说,RSS 变小了。另外,请注意,在 RSS 成本函数图中,第一步与第二步相比相对较大。

让我们也做第三步:

RSS slope (at θ₀ = 0.78): -2(1.08-0.78) - 2(0.4-0.78) - 2(1.3-0.78)
RSS slope (at θ₀ = 0.78): -0.88step size (at θ₀ = 0.78): -0.88 * 0.1
step size (at θ₀ = 0.78): -0.09new intercept = 0.78 - (-0.09)
new intercept = 0.87

我们的两个图如下所示:

RSS 成本函数和第三步后的最佳拟合线

再继续三步,GD 对截距的估计结果是0.95,这与用最小二乘法计算的结果完全相同(你可以自己检查最小二乘法的计算结果!).

什么时候停止?

但是 GD 怎么知道什么时候停止做额外的计算呢?换句话说,它如何知道自己已经达到了最佳估计值?当步长变得非常接近 0 时,它会这样做,这将在梯度非常接近 0 时发生。实践者通常通过最小步长参数来控制这一点,该参数通常设置为 0.001 或更小。

也就是说,GD 还包括一个放弃前的步数限制,通常参数化为 1000 步或更多。因此,即使步长很大,如果 GD 已经执行了最大数量的步骤,它也会停止。

一起寻找最佳截距和斜率

既然我们已经理解了 GD 的基本原理,让我们一起来计算最佳截距和斜率。

这意味着我们将不会使用 0.64 的斜率,如等式。2.相反,我们将有两个独立的参数,θ₀θ₁,我们需要一起优化它们。这需要多变量微积分,并对截距θ₀和斜率θ₁取偏导数。成本函数现在看起来像这样:

RSS 成本函数—等式。四

关于截距θ₀的偏导数如下:

截距的偏导数——等式。5

关于截距θ₁的偏导数如下:

斜率的偏导数——等式。6

我们将使用这两个偏导数来寻找 RSS 成本函数(等式)中的最低点。4).就像之前一样,我们将开始为截距θ₀和斜率θ₁选择随机数。先说θ₀ = 0θ₁ = 1。因此,GD 将从这条线开始:

GD 随机初始化

现在让我们将θ₀ = 0θ₁ = 1代入偏导数方程:

partial derivative wrt θ₀ (Eq. 5) = (6 * 0) + (11.4 * 1) - 13
partial derivative wrt θ₀ (Eq. 5) = -1.6partial derivative wrt θ₁ (Eq. 6) = (11.4 * 0) + (27.9 * 1) - 28.7
partial derivative wrt θ₁ (Eq. 6) = -0.8

计算学习率为 0.01 的步长以及截距和斜率的新值:

intercept step size = -1.6 * 0.01
intercept step size = -0.016
new intercept = 0 - (-0.016)
new intercept = 0.016slope step size = -0.8 * 0.01
slope step size = -0.008
new slope = 1 - (-0.008)
new slope = 1.008

我们更新后的最佳产品系列大致如下:

第一步后的最佳拟合线

这种差别似乎不是实质性的。然而,在计算步长和更新的参数的更多迭代之后(直到步长小于阈值或者达到最大迭代次数),我们得到以下最佳拟合线:

与 GD 最匹配的最终线

GD 找到的最佳参数将与最小二乘法找到的参数相同或非常接近,即θ₀ = 0.95θ₁ = 0.64

多参数 GD 和其他损失函数

我们刚刚完成了两个参数的 GD 计算。如果我们的数据有更多的特征(实际数据集通常如此),我们只需要取更多的偏导数,其他一切都将保持不变。

这里要注意的一个关键点是,所有参数应该在每一步同时更新(而不是一个接一个地更新)。

在这个例子中,我们优化了 RSS 成本函数。但是,还有其他几个成本函数可以处理不同的数据类型、分布和预测问题。无论使用哪种成本函数,GD 的工作方式都是一样的。

批量与随机梯度下降

我们在这个问题中执行的操作被称为批量梯度下降,由此在计算成本函数的斜率时使用所有可用的数据点(训练数据)(上面的步骤 3)。当我们有大量数据点时,这会导致问题和效率低下。

另一种叫做随机梯度下降的动物很好地处理了这种低效率。随机梯度下降在每一步使用随机选择的观测值,而不是整个数据集。这减少了计算成本函数的斜率所花费的时间(步骤 3)。总体概念和方法仍然类似于批量梯度下降。

学习率

你会注意到我们使用了两种不同的学习率:当只找到最优截距时,学习率较高;当同时找到最优截距和斜率时,学习率较低。

GD 对学习率高度敏感。在实践中,通过学习计划,一个合理的学习率可以由大到小自动确定。在大多数机器学习算法中,学习速率和学习时间表可以作为参数使用。例如,在 scikit-learn 的 SGDRegressor 和 SGDClassifier 类中,学习速率和学习进度分别由eta0learning_rate参数控制。

摘要

现在你有了,一个关于 GD 如何在后台工作的非常简单的解释。现在让我们总结一下 GD 在优化参数时采取的步骤:

  1. 对成本函数中的每个参数求偏导数,从而得到与参数数量相等的多个偏导数
  2. 为每个参数选择一些随机初始值——称为随机初始化
  3. 将这些随机值代入步骤 1 中确定的每个偏导数中,以找到成本函数的斜率
  4. 计算每个参数的步长:step size = slope * learning rate
  5. 计算新的参数:new parameter = old parameter — step size
  6. 从步骤 3 开始重复,直到步长非常小或达到最大步数

如果您想讨论任何与数据分析、机器学习、金融或信用分析相关的问题,请随时联系 me 。

下次见,摇滚起来!

梯度下降、学习率和特征缩放的重要性

原文:https://towardsdatascience.com/gradient-descent-the-learning-rate-and-the-importance-of-feature-scaling-6c0b416596e1?source=collection_archive---------8-----------------------

史蒂夫·阿灵顿在 Unsplash 上拍摄的照片

这篇帖子的内容是书中一章的部分复制:用 PyTorch 进行深度学习循序渐进:初学者指南

介绍

梯度下降学习率特征缩放有什么共同点?让我想想…

每次我们训练深度学习模型或任何神经网络时,我们都在使用梯度下降**(带反向传播)。我们用它来通过更新模型的参数/权重最小化损失。**

参数更新取决于两个值:梯度和学习率**。学习率让你可以控制更新的大小。一个更大的学习率意味着更大的更新,并且有希望是一个学习更快的模型。**

但是有一个圈套,一如既往…如果学习率太大**,模型什么都学不到。这让我们想到了两个基本问题:**

  • 多大才算“太大”?
  • 有什么办法可以用更大的学习率吗?

不幸的是,第一个问题没有明确的答案。它总是取决于许多因素。

但是有一个第二个第一个的答案:特征缩放!这是怎么回事?这就是我写这篇文章的原因:向你详细展示梯度下降、学习率和特征缩放之间的联系。

在本帖中,我们将:

  • 定义一个模型并生成一个合成数据集****
  • 随机地初始化参数
  • 探索损失面可视化梯度****
  • 了解使用不同学习率效果****
  • 了解特征缩放效果****

模型

模型必须是简单的熟悉的**,这样你就可以专注于梯度下降的内部运作。因此,我将坚持使用一个尽可能简单的模型:一个具有单一特征的线性回归 x !**

简单线性回归

在这个模型中,我们使用一个特征** ( x )来尝试预测一个标签 ( y )的值。我们的模型中有三个元素:**

  • 参数 b
  • 参数 w
  • 还有那个上学期**(为什么总是必须是希腊字母?),ε,这是为了说明固有的噪声,即我们无法消除的**误差****

数据生成

我们已经知道我们的模型了。为了给它生成合成数据**,我们需要为它的参数取值。我选了b= 1****w = 2。**

先来生成我们的特征** ( x ):我们使用 Numpy 的 rand 方法,在 0 到 1 之间随机生成 100 ( N )个点。**

然后,我们将我们的特征** ( x )和我们的参数 bw 代入我们的方程来计算我们的标签 ( y )。但是我们需要添加一些 高斯噪声(ε)为好;否则,我们的合成数据集将是一条完美的直线。**

我们可以使用 Numpyrandn 方法生成噪声,该方法从正态分布(均值为 0,方差为 1)中抽取样本,然后将其乘以因子以调整噪声的水平**。由于我不想添加这么多噪声,所以我选择了 0.1 作为我的因子。**

合成数据集

训练-验证-测试分割

解释训练-
验证-测试分割背后的原因已经超出了本文的范围,但是我想提出两点:

  1. 分割应该总是是你做的第一件事——没有预处理,没有转换;在分割之前什么也没有发生——这就是为什么我们在合成数据生成之后立即进行分割
  2. 在这篇文章中,我们将只使用训练集——所以我没有费心创建一个测试集,但是我还是对高亮点#1 😃进行了分割

训练-验证分割

综合数据

随机初始化

在我们的例子中,我们已经知道参数的真实值,但是这在现实生活中显然永远不会发生:如果我们知道真实值,为什么还要费心训练一个模型来找到它们呢?!**

好的,鉴于我们永远不会知道参数的真值,我们需要为它们设置初始值。我们如何选择他们?事实证明。一个随机猜测和其他的一样好。

所以,我们可以随机初始化 参数/权重(我们只有两个, bw )。

随机起点

我们随机初始化的参数是: b = 0.49w = -0.13 。这些参数有用吗?

显然不是…但是,他们到底有多坏?这就是损失的原因。我们的目标将是最小化它。

损失面

在为我们的参数选择了一个随机起点后,我们用它们来预测计算相应的误差将这些误差汇总成一个损失**。由于这是一个线性回归,我们使用均方差(MSE) 作为我们的损失。下面的代码执行这些步骤:****

进行预测并计算损失

我们刚刚计算了对应于我们的随机初始化参数 ( b = 0.49 和 w = -0.13)的损失 (2.74)。现在,如果我们对 bw 的所有可能值做同样的处理会怎么样?嗯,不是所有可能的值,而是给定范围内的所有等间距值的组合**

我们可以在 -24 之间改变 b ,同时在 -15 之间改变,例如,每个范围包含 101 个均匀间隔的点。如果我们在这些范围内计算对应于的参数 bw 的每个不同组合的损耗,结果将是损耗网格,形状(101,101)的矩阵。******

这些损耗就是我们的损耗面*,它可以在 3D 图中可视化,其中纵轴( z )代表损耗值。如果我们连接产生相同损失值bw 的组合,我们将得到一个椭圆。然后,我们可以在原来的 b x w 平面上画出这个椭圆(蓝色,损耗值为 3)。简而言之,这就是等高线图的作用。从现在开始,我们将总是使用等高线图,而不是相应的 3D 版本。***

下图显示了建议的参数范围的损失面,使用我们的训练集来计算 bw 的每个组合的损失。

损失面

在图的中心,参数( b,w )的值接近(1,2),损耗处于其最小值。这就是我们试图用梯度下降达到的点。****

在底部,稍微偏左的地方,是随机开始点,对应我们随机初始化的参数( b = 0.49、 w = -0.13)。****

这是处理简单问题的一个好处,比如用单一特征进行线性
回归:我们只有
两个参数
,因此我们可以计算并可视化损失面
****

横截面

另一件好事是,我们可以在损失表面切割一个横截面来检查如果其他参数保持不变时损失看起来是什么样的。****

让我们从使 b =0.52 (来自我们的均匀间隔范围的值,最接近我们的初始随机值 b ,0.4967)开始——我们在我们的损失表面(左图)上垂直地(红色虚线)切割一个横截面,我们得到右边的结果图:**

垂直横截面—参数 b 固定

这个横截面告诉我们什么?它告诉我们,如果我们保持 b 不变(在 0.52),从参数 w角度看,如果 w 增加(达到 2 和 3 之间的某个值),则损失**可以最小化。******

当然,**不同的b*值会产生不同的w截面损失曲线。这些曲线将取决于损失面的*形状(稍后将在“学习率”部分详细介绍)。********

好的,到目前为止,一切顺利…那么其他截面呢?现在让我们水平切割它,使 w = -0.16 (来自我们的均匀间隔范围的值,最接近我们的初始随机值 b,-0.1382)。结果图在右边:

水平横截面—参数 w 固定

现在,如果我们保持 w 恒定 (at -0.16),从参数 b角度看,如果 b 增加(达到接近 2 的某个值),则损耗可以最小化*。***

总的来说,该横截面的目的是获得改变单个参数对损失的影响,同时保持其他一切不变。简单地说,这是一个渐变 😃

可视化渐变

从上一节我们已经知道,为了使损失最小化, bw 都需要增加**。所以,保持使用渐变的精神,让我们**增加每个参数一个小* ** (总是保持另一个固定!).顺便说一下,在这个例子中,一个小点等于 0.12(为了方便起见,所以它产生了一个更好的图)。***

这些增加对损失有什么影响?让我们来看看:

几何计算(近似)梯度

在左图中,w 增加 0.12 会导致损失减少 0.21* 。几何计算和粗略近似的梯度由两个值之间的比率给出: -1.79 。该结果与梯度的实际值(-1.83)相比如何?对于粗略的近似来说,这实际上还不错……还能更好吗?当然,如果我们使 w 的增量越来越小(比如 0.01,而不是 0.12),我们将得到越来越好的近似值……在极限中,随着增量接近零**,我们将达到精确值。嗯,这就是导数的定义!*****

同样的推理也适用于右边的图:b 增加相同的 0.12 会使损失减少 0.35* 。更大的损耗减少、更大的比率、更大的梯度——以及更大的误差,因为几何近似值(-2.90)离实际值(-3.04)更远。***

更新参数

最后,我们使用渐变来更新参数。因为我们试图最小化我们的损失*,我们反转梯度的符号用于更新。***

还有另一个(超)参数需要考虑:学习率,用希腊字母* eta (看起来像字母 n )表示,这是我们需要应用于梯度的乘法因子,用于参数更新。*****

更新参数 bw

我们也可以稍微不同地解释这一点:每个参数将使其
被一个常数值 eta
(学习速率)更新,但是这个常数将通过该参数对最小化损失(其梯度)的贡献大小来**加权。
******

老实说,我相信这种思考参数更新的方式更有意义:首先,你决定一个学习率,它指定了你的步长,而梯度*告诉你每走一步对每个参数的相对影响(对损失)。然后你采取一个给定的步数这是比例到那个相对影响:更多的影响,更多的步数。*****

"如何选择一个学习率?"****

不幸的是,这是一个独立的话题,超出了本文的范围。

学习率

****学习率是最重要的超参数——关于如何选择学习率、如何在训练期间修改学习率以及错误的学习率如何完全破坏模型训练,有大量的
资料。

也许你已经看到了下面这张著名的图表(来自斯坦福大学的 CS231n 课程),它显示了在训练过程中太大太小的学习率如何影响损失****

来源

大部分人都会在某个时间点看到(或者已经看到)。这基本上是常识,但我认为需要彻底解释和直观演示才能让真正理解。所以,我们开始吧!******

我给你讲个小故事(这里试图打个比方,请多包涵!):想象你正在从山里徒步旅行回来,你想尽快回家。在你前进的道路上,你可以选择继续前进或者右转

前方的道路几乎是平坦的,而通往你右边的*的道路有些陡峭。
陡度就是
坡度
。如果你以这样或那样的方式迈出一步,就会导致不同的结果(如果你向右迈一步,而不是向前,你会下降得更多)。
*****

但是,事情是这样的:你知道通往你右边的路会让你更快地回到的家,所以你不会只走一步,而是在那个方向走多步:路越陡,你走的步就越多!记住,“多点冲击,多点脚步”!你就是无法抗拒走那么多步的冲动;你的行为似乎完全由风景决定。我知道这个类比越来越奇怪了…****

但是,你还有一个选择:你可以调整你的步长。你可以选择任何大小的步伐,从小步到大步。那就是你的学习率****

好了,让我们看看这个小故事把我们带到了什么地方……简而言之,这就是你的行动方式:

更新位置=先前位置+步长步数*

现在,将它与我们对参数所做的比较:

更新值=先前值-学习率梯度*

你明白了,对吧?我希望如此,因为这个类比现在完全站不住脚了……在这一点上,在向一个方向移动之后(比如说,我们谈到的右转,你必须停下来向另一个方向移动(仅仅一小步,因为路径几乎是平的,记得吗?).诸如此类……嗯,我想没有人从这样一条正交的之字形路径徒步旅行回来过…

无论如何,让我们进一步探索你唯一的选择:你的步幅,我的意思是学习速度。

小学习率

婴儿步开始是有道理的吧?这意味着使用小学习率。小学率 safe(r) ,不出所料。如果你在徒步旅行回家的路上迈着小步,你更有可能安全到达目的地——但是这需要很长时间。这同样适用于训练模型:小的学习率可能会让你达到(某个)最低点,最终。不幸的是,时间就是金钱,尤其是当你在云中支付 GPU 时间的时候……所以,有一个激励*去尝试更大的学习率。*****

这个推理如何应用于我们的模型?通过计算我们的(几何)梯度,我们知道我们需要采取给定的步数 : 1.79 (参数 w )和 2.90 (参数 b )。让我们将步长设置为 0.2 (小一点)。意思是我们**为w移动 0.36,为b移动 0.58。******

重要提示:在现实生活中,0.2 的学习率通常被认为是很大的——但是在我们非常简单的线性回归例子中,它仍然是很小的。

这场运动将我们引向何方?正如你在下面的图中所看到的(如原始点右侧的新点所示),在这两种情况下,移动使我们更接近最小值——在右侧更是如此,因为曲线更加陡峭。

使用一个小的学习率

大学习率

如果我们使用一个大的学习率,比如说步长为 0.8 的学习率,会发生什么呢?正如我们在下面的图中看到的,我们开始真正地遇到麻烦* …***

使用大的学习率

即使左边的图一切正常,右边的图给我们展示了一个完全不同的画面:我们最终在曲线的另一边。那是 而不是 好…你会来回,交替地击打曲线的两边。****

“嗯,即便如此,我可能还是达到最低,为什么会这么差?”****

在我们这个简单的例子中,是的,你最终会达到最小值,因为曲线是漂亮和圆的****

但是,在实际问题中,“曲线”有一些真正奇怪的形状,允许
奇怪的结果,例如来回而从未接近最小值
****

我们打个比方,你移动得太快以至于你摔倒撞到山谷另一边,然后像一个 乒乓 一样一直往下。很难相信,我知道,但你肯定不想那样…****

非常大的学习率

等等,可能会比那更糟…让我们用一个真正大的学习率,比如说,1.1 的步长!

使用一个非常大的学习率

好了,那个 坏了……在右边的剧情中,我们不仅再次在的*另一边结束了,而且我们居然爬上了。这意味着我们的损失增加了,而不是减少了!这怎么可能呢?你下山的速度如此之快,以至于最后你不得不爬回来?!不幸的是,这个类比再也帮不了我们了。我们需要以不同的方式考虑这个特殊的案例…*****

首先,请注意左边图中的一切都很好。巨大的学习率并没有引起任何问题,因为左边的曲线没有右边的曲线那么陡。换句话说,左边的曲线比右边的曲线能够获得更大的学习率。******

我们能从中学到什么?

太大,对于一个学习率来说,是一个相对的概念:它取决于曲线有多陡,或者换句话说,它取决于坡度有多大**。******

我们有许多曲线,许多梯度:每个参数一个。但是我们只有一个单学率可以选择(不好意思,就是这么回事!).

这意味着学习率的大小受到最陡曲线的限制。所有其他曲线必须跟随,这意味着,鉴于它们的形状,它们将使用次优的学习率。

合理的结论是:如果所有的曲线都同样陡峭,那么学习率对它们来说都更接近最优最好**!******

“坏”特征

我们如何实现同样的陡峭的曲线?我来了。首先,让我们看一个稍微修改过的例子,我称之为“坏”数据集:****

  • 把我们的特征( x )乘以 10 ,所以现在在范围【0,10】内,改名为 bad_x****
  • 但是由于我不希望标签( y )改变,所以我将原来的 true_w 参数除以 10** 并将其重命名为bad _ w——这样,bad_w * bad_x 和******

生成“坏”数据集

然后,我对两个数据集原始的坏的执行了与之前相同的分割,并并排绘制了训练集,如下所示:

“坏”数据集的训练验证分割

相同的数据,不同比例的特征 x

两个图之间唯一的差异是特征的比例 x 。它的范围是[0,1],现在是[0,10]。标签 y 没变,我也没碰 true_b****

这个简单的缩放对我们的梯度下降有任何有意义的影响吗?如果没有,我就不会问了,对吧?让我们计算一个新的损失面,并与之前的损失面进行比较:

损失表面—缩放特征之前和之后 x

再看上图的等高线值:原来深蓝色线是 3.0 ,现在是 50.0 !对于相同范围的参数值,的损失值要大得多**

让我们看看将特征 x 乘以 10 前后的横截面:**

比较横截面:之前和之后

这里发生了什么?红色曲线变得更加陡峭(更大的坡度),因此我们必须使用较小的学习率才能安全地沿着它下降。

更重要的是,红色和黑色曲线之间的差异陡度上增加

这正是我们需要避免的

你记得为什么吗?

因为学习率的大小受到最陡曲线的限制!

怎么才能修好?嗯,我们放大了 10 倍 …也许我们可以让它变得更好,如果我们以不同的方式放大**。****

缩放/标准化/规范化

怎么不同?有个漂亮的东西叫做 标准定标器 ,它把一个特征转换成最后的零均值单位标准差**。****

它是如何实现的?首先,它使用训练集( N 点)计算给定**特征的均值标准差:****

平均值和标准偏差,在标准定标器中计算

然后,它使用这两个值来缩放特征:

标准化

如果我们要重新计算缩放要素的平均值和标准差,我们将分别得到 0 和 1。这个预处理步骤通常被称为标准化,尽管从技术上来说,它应该总是被称为标准化**

零均值和单位标准差

让我们从单位标准差开始,即缩放特征值,使其标准差等于一个。这是最重要的预处理步骤之一,不仅是为了提高梯度下降的性能,也是为了其他技术,如主成分分析(PCA)的目标是将所有的数字特征放在一个相似的刻度中,因此结果不受每个特征的原始范围的影响。

想到一个模特身上的两个共同特征:年龄薪资。虽然年龄通常在 0 到 110 之间变化,但薪水可以从几百(比如说 500)到几千(比如说 9000)。如果我们计算相应的标准
偏差,我们可能会分别得到 25 和 2000 这样的值。因此,我们需要
标准化两个特性,使它们处于的平等地位

然后零点表示,即零点处对中特征。更深层次的神经网络可能会遭受一种叫做消失梯度的非常严重的情况。由于梯度用于更新参数,越来越小(即消失)的梯度意味着越来越小的更新,直到停滞点:网络简单地停止学习。帮助网络对抗这种情况的一种方法是将它的输入即特征集中在零。关于渐变消失问题的更多细节,请查看我的“超参数在起作用!第二部分—权重初始值设定项。

重要:类似标准定标器 的预处理步骤必须在列车验证测试分割后进行;否则,您将从验证和/或测试集向您的模型泄露信息!

在使用训练集仅来适应标准缩放器之后,您应该使用其转换方法来将预处理步骤应用于所有数据集:训练、验证和测试。

下面的代码将很好地说明这一点:

标准化特征 x

请注意,我们不是重新生成数据,而是使用原始特征 x 作为标准缩放器的输入,并将其转换为缩放的 x** 。标签( y )保持不变。******

让我们把它们三个、缩小并列起来,来说明区别:**

相同的数据,特征 x 的三种不同比例

同样,图与图之间唯一的差异是特征的比例 x 。它的范围本来是[0,1],后来我们把它做成[0,10],现在标准缩放器把它做成[-1.5,1.5]。****

好了,检查损失面的时间到了:为了说明差异,我将它们三个并排绘制:缩放……看起来是这样的:**

特征 x 不同比例的损失面

漂亮的,不是吗?教科书上对碗的定义 😃

在实践中,这是人们可能希望的最佳表面:截面将会是同样陡峭的,并且其中一个的好的学习率对另一个也是好的。****

当然,在现实世界中,你永远也不会得到那样一个漂亮的碗。但是我们的结论仍然成立:

  1. 总是标准化(缩放)你的特征。
  2. 永远不要忘记第一条:-)

最后的想法

我希望这篇文章能帮助你发展直觉关于特征缩放如何影响学习率的选择,以及这两个元素如何在 梯度下降性能中发挥基本作用。

如果你有什么想法、意见或问题,欢迎在下方留言评论或联系我 推特

梯度下降被解开

原文:https://towardsdatascience.com/gradient-descent-unraveled-3274c895d12d?source=collection_archive---------19-----------------------

从基础开始理解梯度下降优化的工作原理

在当前的深度学习时代,你可能以前听说过梯度下降这个术语。如果你不明白它是什么和它是如何工作的,这篇文章是给你的。在这篇文章中,我将解释它是什么以及它是如何工作的。

最大值对最小值和全局对局部

首先,让我们从最大值、最小值、全局和局部的概念开始。

我将为单变量函数解释这些概念,因为它们易于可视化。然而,他们延伸到多变量的情况。

让我们从几个定义开始。[1]

  • 全局最大值:定义在域 X 上的实值函数 fX∫iff(X∫)≥f(X)对于X中的所有 x
  • 全局最小值:一个定义在定义域 X 上的实值函数 fX∫处有一个全局(或绝对)最大值点,如果f(X∫)≤f(X)对于 X. 中的所有 x
  • 局部最大值:如果域 X 是一个度量空间,那么就说 f 在点X∫处有一个局部(或相对)最大值点,如果存在一些 ε > 0 使得f(X∫)≥f(X
  • **局部最小值:**如果域 X 是一个度量空间,那么就说 f 在点X∫处有一个局部(或相对)最大值点,如果存在一些 ε > 0 使得f(X∫)≤【t8t

图形会使概念更容易理解。我在下图中总结了这四种类型的点。

作者图片

顾名思义,最小值是集合中的最小值,最大值是最大值。全局意味着它对整个集合是正确的,而局部意味着它对某些邻近区域是正确的。一个函数可以有多个局部最大值和最小值。然而,只能有一个全局最大值和最小值。请注意,对于图(a)和(b ),功能域仅限于您看到的值。如果它是无穷大,那么图(a)中的图就没有全局最小值。

现在我们理解了这些概念,下一步就是如何找到这些极值点。

事实证明微积分中的导数对于寻找这些点是有用的。我不会深入衍生品的细节。不过,我会解释得足够明白下面的讨论。

作者图片

导数给出了某物相对于某物的变化率。例如,一种药物被你的系统吸收的速度可以用微积分来建模和分析。

现在,让我们明白什么是临界点。

作者图片

所以我们知道,在这些临界点,会有一个局部或全局的最大值或最小值。下一步是确定它属于哪一类。

作者图片

您可以使用两种测试中的任何一种,即一阶和二阶导数测试来对最大值和最小值进行分类。当我在高中的时候,我发现二阶导数测试更快,因为我只计算一个值(不用计算器)。我将向你展示一个实际上是如何做的例子。

作者图片

为了发现这个点是否是全局的,你必须评估所有临界点的函数,看看哪个点是最低点。在我们的例子中,我们看到了一个多项式函数。它是光滑的,可微的。测试的点是有限的,如果你有方程,计算函数就很容易。

然而,现在让我们转向现实世界。我们永远不知道我们处理的现实生活过程的实际等式。此外,等式中还涉及到几个变量。这些测试在那些情况下不会有用。为了训练一个神经网络,你需要最小化网络参数的损失。这是一个多维面,多种因素在起作用。而且我上面讨论的测试也不会有效。因此,我们转向优化这项任务。

寻找函数最小值/最大值的优化

什么是优化?

相对于某个集合最大化或最小化某个函数,通常表示在某种情况下可用的选择范围。该函数允许比较不同的选择,以确定哪一个可能是“最好的”

常见应用:最小成本、最大利润、最小误差、最佳设计、最佳管理、变分原理。

在数学、计算机科学和运筹学中,数学优化或数学规划是从一组可用的备选方案中选择最佳元素(就某些标准而言)。

优化本身就是一片汪洋,极其有趣。在深度学习的背景下,优化目标是最小化关于模型参数的成本函数,即权重矩阵。

什么是渐变?

梯度:在向量微积分中,梯度是导数的多变量推广。标量函数的梯度 f(x₁,x₂,x₃,…,xₙ)【以下简称 f 用∇ f 表示,其中∇(纳布拉符号)被称为德尔算符。它把所有的偏导数信息打包成一个向量。

f 是一个向量值函数,指向最陡上升的方向。想象一下,如果你站在 f 的输入空间中的某个点,梯度向量会告诉你应该向哪个方向移动,以快速增加 f 的值。

如果你有兴趣了解更多。可汗学院是一个学习渐变和数学的好地方。
https://www . khanacademy . org/math/multivariable-calculus/multivariable-derivatives/gradient-and-direction-derivatives/v/gradient

梯度下降

这是一种优化技术,以迭代的方式向最小值移动。

涉及的步骤如下:

  1. 猜一个点(随机或通过某种技巧)。
  2. 选择步长,在深度学习中称为学习速率ρ,也是深度学习中最重要的超参数之一。
  3. 计算函数的梯度
  4. 从最初的猜测中减去这个,向相反的方向移动。这是因为我们想下降,梯度给你最陡的上升方向。
  5. 重复步骤 3 和 4n 次,或者直到达到停止标准

在深度学习应用的方程形式中,它可以写成:

ρ是学习速率,它决定了在迈步时衰减梯度值的程度。

β是网络参数。

这里还要提到的一点是,除非函数是凸的,否则算法会陷入局部最小值,而不是收敛到全局最小值。

作者图片

在数学中,定义在一个 n 维区间上的实值函数,如果该函数的图上任意两点之间的线段位于图的上方或图上,则称为凸的(或向下凸的或向上凹的)。这意味着函数本身在严格凸的情况下有一个最小值。

总之,梯度下降是一种优化方法,通过在函数梯度的负方向(最陡下降的方向)上递增地更新其参数来找到目标函数的最小值。

梯度下降 1D 示例

让我们看几个例子。我们将从 1D 案例开始,因为它最容易想象。所用的等式与我之前在最大值和最小值部分使用的等式相同。

我将展示如何使用 numpy 和 matplotlib 在 python 中手动实现代码。

下图显示了起点和学习率的各种组合。

作者图片

少数观察结果

考虑中的方程有两个最小值。我们想用梯度下降算法找到全局最小值。我将解释按行填充的数字。对于所有示例,迭代次数保持为 10。我改变了学习速率和初始起点,向你们展示它是如何影响算法的。前五幅图表明,如果起始点和迭代次数保持不变,学习速率越大,算法下降越快。但在这些情况下,算法会陷入局部最小值。在图 7 中,我们看到,由于大的学习速率加上起始点的陡峭斜率,该算法大幅度跳转到全局最小值。

尽管大的学习速率可以导致更快的收敛,但是由于大的有效步长,你的算法有可能偏离最小值。看一下最后一个图,起点使算法能够达到全局最小值,但是大的学习率导致算法发散。倒数第二张图显示了另一种情况。该点在临界点处初始化,该点的导数为零。无论你的学习速率有多大,或者你走了多少步,算法都不会从那个点移动。

从上面的例子中,我们看到必须选择学习速率,使得它不太低以至于梯度过阻尼,或者对于梯度太高以至于扩大步长。起始点的初始化是至关重要的,它能使你得到全局最小值或局部最小值。要采取的步骤数量也很重要。

梯度下降 2D 示例

现在让我们看几个 2D 的例子。

第一个例子是抛物面,它的方程式如下。

在本教程中,我将使用症状。这允许你对方程进行符号计算。即使你不知道微积分,你也可以使用代码来尝试不同的方程和实验。

以下代码使用 sympy 的符号表示创建函数 f1,并计算 w.r.t. x 和 y 的偏导数来计算梯度。然后通过使用适当的分量更新 x 和 y 值来使用它执行梯度下降。

下图显示了 3D 绘图的两个视图。

作者图片

从图中可以立即看出,当算法接近最小值时,梯度值减小,因此步长减小。正如我在文章开头提到的,这种技术对于 n 维的情况是一样的。我们在较低维度中得出的观察结果几乎总是可以在很少或没有修改的情况下扩展到更高维度的情况。

为了给你一个不同表面的味道,下面是两个 2D 梯度下降的例子。如前所述,初始化很重要,并将最终决定您的最终结果。

作者图片

作者图片

Python 实用程序以交互方式尝试不同的梯度下降参数

我制作了一个 python 工具,可以让你调整学习率、迭代次数和初始起点,看看这些如何影响 1D 例子的算法性能。关于这一点的代码,以及 2D 函数图,可以在下面的库中找到。
https://github.com/msminhas93/GradientDescentTutorial

作者图片

到目前为止,我们已经看到了算法,并以 1D 和 2D 为例,分析他们的选择如何影响收敛。

深度学习中的梯度下降[2]

在深度学习的背景下,梯度下降可以分为以下几类。

  • 随机梯度下降
  • 小批量梯度下降
  • 批量梯度下降

**随机梯度下降:**假设你想要最小化一个目标函数,这个目标函数被写成可微函数的和。

每个术语 Qᵢ通常与 iᵗʰ数据点相关联。

标准梯度下降(批量梯度下降)如下所示。

其中η是学习率(步长)。

随机梯度下降(SGD) 每次迭代只考虑被加数函数的子集。这对于大规模的问题可能是有效的。Q(w)的梯度由单个例子中的梯度近似:

每个训练示例都需要进行这种更新。在算法收敛之前,可能需要对训练集进行多次遍历。

SGD 的伪代码:

  • 选择 w 和η的初始值。
  • 重复直到收敛。
  • 随机打乱训练集中的数据点。
  • 对于 i = 1,2,3,…,n,做:
  • w =∇qᵢ(w)

让我们考虑下面的等式:

目标函数是:

SGD 的更新规则如下。

小批量梯度下降:

  • 批量梯度下降在每次迭代中使用所有的 n 个数据点
  • 随机梯度下降在每次迭代中使用 1 个数据点
  • 小批量梯度下降在每次迭代中使用 b 数据点b 是一个称为小批量的参数。

小批量梯度下降的伪代码:

  • 选择 w 和η的初始值。
  • 例如,选择 b = 10
  • 重复直到收敛。
  • 随机打乱训练集中的数据点。
  • 对于 i = 1,11,21,…,n-9,做:

关于梯度下降的三种类型的讨论

关于三种变体的几点看法。

  • SGD 比其他两个变体更嘈杂,因为它是按示例更新的。
  • SGD 通常被称为在线机器学习算法,因为它为每个训练示例更新模型。
  • SGD 在计算上比其他变体更昂贵,因为它每个例子。
  • SGD 是抖动的,导致收敛到最小困难。
  • 小批量梯度下降允许您利用 GPU 的优势,一次处理多个示例,从而减少训练时间。
  • 批量梯度下降实际上是不可行的,除非你有一个小的数据集,可以放入可用的内存。

小批量参数 b 的选择取决于您的 GPU、数据集和型号。一个经验法则是选择 8 的倍数大小。一般来说,32 是一个好的开始数字。如果你选择的数字太高或太低,那么算法会变得更慢。在前一种情况下,计算可能会变得更慢,因为你给 GPU 增加了很多负载。而在后一种情况下,较小的小批量不能充分利用您的 GPU。为你的情况找到合适的平衡点是很重要的。

调整学习率η:

如果η太高,算法就会发散。如果η太低,会使算法收敛缓慢。

通常的做法是使ηₙ成为迭代次数 n 的减函数。下面是两个例子。

  • ηₙ = k/(n+c),其中 k 和 c 是常数。
  • ηₙ = η₀ e⁻ᵏⁿ,其中η₀是初始学习率,k 决定指数衰减的陡度。

你也可以使用基于时间间隔的学习进度计划。例如:

其中 n 是迭代次数。

第一次迭代引起 w 的较大变化,而后面的迭代只做微调。

有一种叫做周期学习率的东西,你可以用一个周期函数来安排时间。你可以在这里了解更多信息。

这就结束了对梯度下降的讨论。

总结一下:

  • 梯度下降是一种优化算法,用于深度学习中,以最小化关于模型参数的成本函数。
  • 它不能保证收敛到全局最小值。
  • 收敛性取决于起始点、学习速率和迭代次数。
  • 在实践中,小批量梯度下降与批量大小值 32 一起使用(这可能因您的应用而异)。

希望这有用。欢迎您的建议、反馈和评论。

参考资料:

[1]https://en.wikipedia.org/wiki/Maxima_and_minima

[2]滑铁卢大学 STAT 946 深度学习课程【https://www.youtube.com/playlist? list = pleayksg 4 usq 0 madcjyskfeo 3 guptuuh 66

动量梯度下降

原文:https://towardsdatascience.com/gradient-descent-with-momentum-59420f626c8f?source=collection_archive---------5-----------------------

梯度下降的问题在于,在时刻(t)的权重更新仅由该时刻的学习速率和梯度控制。它没有考虑遍历成本空间时所采取的过去步骤。

作者图片

会导致以下问题。

  1. 成本函数在鞍点(平台)的梯度可以忽略或为零,这又导致很小的或没有权重更新。因此,网络变得停滞,学习停止
  2. 即使在小批量模式下运行,梯度下降所遵循的路径也非常不稳定

考虑低于成本的表面。

作者图片

让我们假设所考虑的网络的初始权重对应于点 a。在梯度下降的情况下,损失函数沿着斜率 AB 迅速减小,因为沿着该斜率的梯度很高。但是一旦到达 B 点,梯度就变得非常低。B 附近的权重更新很小。即使在多次迭代之后,成本在停留在梯度最终变为零的点之前移动得非常慢。

在这种情况下,理想情况下,成本应该移动到全局最小值点 C,但是因为梯度在点 B 处消失,所以我们陷入了次优解。

动量如何解决这个问题?

现在,想象你有一个球从 a 点滚下。球开始慢慢滚下,并聚集了一些动量越过斜坡 AB。当球到达点 B 时,它已经积累了足够的动量来推动自己穿过平台区域 B,并最终沿着斜率 BC 降落在全局最小值 c 处。

如何将此应用于梯度下降?

为了说明动量,我们可以使用过去梯度的移动平均值。在像 AB 这样梯度高的区域中,权重更新将会很大。因此,在某种程度上,我们通过对这些梯度进行移动平均来收集动量。但是这种方法有一个问题,它以相等的权重考虑迭代中的所有梯度。t=0 处的梯度与当前迭代 t 处的梯度具有相等的权重。我们需要使用过去梯度的某种加权平均值,以便给予最近的梯度更多的权重。

这可以通过使用指数移动平均线(EMA)来实现。指数移动平均线是一种移动平均线,它对最近的值赋予更大的权重。

序列 Y 的均线可以递归计算

作者图片

在哪里

  • 系数β表示权重增加的程度,是介于 0 和 1 之间的常数平滑因子。较低的β值会更快地忽略旧的观察值。
  • Y(t) 是周期 t 的值。
  • S(t) 是任意时段 t 的均线值。

在我们的梯度序列的情况下,迭代 t 处的新权重更新方程变成

作者图片

我们来分解一下。

𝓥 (t) :新的权重更新是在迭代 t 完成的吗

β: 动量常数

𝛿(t): 是迭代时的梯度 t

假设在第 0 次迭代 t=0 时的权重更新为零

作者图片

想想常数β,忽略上式中的(1-β)项。

:在许多文本中,你可能会发现(1-β)被替换为学习率η。

如果β是 0.1 呢?

在 n=3 时;t =3 处的梯度将贡献其值的 100%,t=2 处的梯度将贡献其值的 10%,而 t=1 处的梯度仅贡献其值的 1%。

在这里,来自早期梯度的贡献迅速减少。

如果β是 0.9 呢?

在 n=3 时;t =3 处的梯度将贡献其值的 100%,t=2 处的梯度将贡献其值的 90%,t=1 处的梯度将贡献其值的 81%。

从上面我们可以推断,更高的β将容纳更多来自过去的梯度。因此,一般来说,在大多数情况下,β保持在 0.9 左右。

:权重更新中每个梯度的实际贡献将进一步受制于学习率。

这解决了我们的第一点,当当前时刻的梯度可以忽略或为零时,学习变为零。使用具有梯度下降的动量,来自过去的梯度将推动成本进一步围绕鞍点移动。

在之前显示的成本面中,让我们放大 c 点。

对于梯度下降,如果学习率太小,权重将更新得非常慢,因此即使梯度很高,收敛也需要很多时间。如下图左侧所示。如果学习率太高,成本会在最小值附近波动,如下图右侧所示。

作者图片

动量是如何解决这个问题的?

我们再来看看动量的最后一个求和方程。

情况 1 :当所有过去的梯度具有相同的符号时

求和项将变大,我们将在更新权重时采取大的步骤。沿着曲线 BC,即使学习率低,沿着曲线的所有梯度将具有相同的方向(符号),从而增加动量并加速下降。

情况 2 :当一些梯度具有+ve 符号,而其他梯度具有-ve 符号时

求和项将变小,权重更新将变小。如果学习率很高,围绕谷 C 的每次迭代的梯度将在+ve 和-ve 之间改变其符号,并且在几次振荡之后,过去梯度的总和将变小。因此,从那里开始对权重进行小的更新,并抑制振荡。

这在一定程度上解决了我们的第二个问题。梯度下降带动量在梯度振荡的方向上迈小步,在过去的梯度具有相同方向(相同符号)的方向上迈大步。

结论

通过在梯度下降中添加一个动量项,即使当前梯度可以忽略或为零,从过去迭代中积累的梯度也将推动成本进一步围绕鞍点移动。

即使梯度下降的动量收敛得更好更快,它仍然不能解决所有的问题。首先,超参数η(学习率)必须手动调整。第二,在某些情况下,即使学习率很低,动量项和电流梯度也能单独驱动并引起振荡。

首先,学习率问题可以通过使用梯度下降的其他变化来进一步解决,如自适应梯度RMSprop。其次,大动量问题可以通过使用基于动量的梯度下降的变体内斯特罗夫加速梯度下降来进一步解决。

无梯度强化学习:使用 Numpy 的神经进化!

原文:https://towardsdatascience.com/gradient-free-reinforcement-learning-neuroevolution-using-numpy-7377d6f6c3ea?source=collection_archive---------26-----------------------

我们能解决简单的没有后向通道的 RL 环境吗?

我们能训练只有向前传球的网络吗?图像来源

介绍

如果我告诉你,你可以训练神经网络,而不必计算梯度,只使用前向传递,会怎么样?这就是**神经进化的魔力!**此外,我将展示仅使用 Numpy 就可以轻松完成所有这些工作!学习统计学你会学到很多基于梯度的方法,但不久前我读到了一篇非常有趣的文章,作者是优步人工智能的人,他表明在解决 Atari 游戏的挂钟时间方面,一个简单的遗传算法与最复杂的基于梯度的 RL 方法具有竞争力。我在下面链接了源代码,如果你对强化学习感兴趣,我强烈推荐你读一读。

什么是神经进化?

首先,对于那些还不知道的人来说,神经进化描述了进化和/或遗传算法的应用,以训练神经网络的结构和/或权重,作为一种无梯度的替代方案!我们将在这里使用一个极其简单的神经进化案例,只使用一个固定的拓扑网络,并且只关注优化权重和偏差。神经进化过程可以定义为四个基本步骤,从随机生成的网络池开始,重复这些步骤直到达到收敛。

1.评估人群的适应性
2。选择最合适的个体来繁殖
3。使用最合适网络的副本重新填充
4。将正态分布突变引入网络权重

哇,这似乎很简单!让我们稍微分解一些术语:

  • 适应度:这简单地描述了网络在某项任务中的表现,并允许我们决定繁殖哪些网络。注意,因为进化算法是非凸优化的一种形式,因此可以与任何损失函数一起使用,而不管其可微性(或缺乏可微性)

  • 突变:这个可能是最简单的!为了改进我们的子网络,我们必须对网络权重引入随机变化,这些变化通常来自均匀或正态分布。可能有许多不同形式的突变:移位突变(将参数乘以一个随机数)、交换突变(用一个随机数替换参数)、符号突变(改变参数的符号)等。我们将只使用简单的附加突变,但这里有很大的创造性空间!

神经进化的优势

我们还应该考虑神经进化模型的理论优势。首先,我们只需要使用网络的前向传递,因为我们只需要计算损失,以确定要繁殖哪些网络。这一点的含义是显而易见的,向后传球通常是最昂贵的!其次,给定足够的迭代次数,进化算法保证找到损失曲面的全局最小值,而基于凸梯度的方法可能陷入局部最小值。最后,更复杂的神经进化形式使我们不仅可以优化网络的权重,还可以优化结构本身!

为什么不总是使用神经进化呢?

嗯,这是一个复杂的问题,但它确实可以归结为当有足够的梯度信息时,精确的梯度下降方法更有效。这意味着损失面越凸,你就越想使用像 SGD 这样的分析方法,而不是遗传算法。因此,很少会在有监督的情况下使用遗传算法,因为通常有足够的梯度信息可用,传统的梯度下降方法将工作得很好。然而,如果你在 RL 环境中工作,或者在具有不规则损失表面或低凸性的情况下工作(像顺序 GAN),那么神经进化提供了一个可行的替代方案!事实上,最近有很多研究发现,参数对参数的神经进化模型在这种情况下可以做得更好。

现在让我们开始吧!

加载库

正如介绍中所述,我们将尝试在这个项目中只使用numpy,只定义我们需要的助手函数!是的,我知道,gym 也在被加载,但只是为了环境;)

import numpy as np
import gym

关于数据

我们将使用 gym 中的经典 CartPole 环境来测试我们的网络。目标是观察网络通过左右移动能保持杆子直立多长时间。作为一个 RL 任务,神经进化的方法应该是很适合的!我们的网络将接受 4 个观察值作为输入,并将输出左或右作为动作。

助手功能

我们首先要定义几个助手函数来设置我们的网络。首先是 relu 激活函数,我们将使用它作为隐藏层的激活函数,并使用 softmax 函数作为网络输出,以获得网络输出的概率估计!最后,当我们需要计算分类交叉熵时,我们需要定义一个函数来生成我们的响应向量的一次性编码。

def relu(x):return np.where(x>0,x,0)def softmax(x):x = np.exp(x — np.max(x))x[x==0] = 1e-15return np.array(x / x.sum())

定义我们的网络类

现在有趣的事情来了!首先,我们将为群体中的个人网络定义一个类别。我们需要定义一个随机分配权重和偏差并将网络结构作为输入的初始化方法,一个在给定输入的情况下获得概率的预测方法,以及一个在给定输入和响应的情况下返回网络分类交叉熵的评估方法!同样,我们将只使用我们定义的函数或 numpy 中的函数。请注意,初始化方法也可以将另一个网络作为输入,这就是我们将如何执行世代之间的突变!

# Lets define a new neural network class that can interact with gym
class NeuralNet():def __init__(self, n_units=None, copy_network=None, var=0.02, episodes=50, max_episode_length=200): # Testing if we need to copy a networkif copy_network is None:# Saving attributesself.n_units = n_units# Initializing empty lists to hold matricesweights = []biases = [] # Populating the listsfor i in range(len(n_units)-1):weights.append(np.random.normal(loc=0,scale=1,size=(n_units[i],n_units[i+1])))biases.append(np.zeros(n_units[i+1]))# Creating dictionary of parametersself.params = {'weights':weights,'biases':biases} else:# Copying over elementsself.n_units = copy_network.n_unitsself.params = {'weights':np.copy(copy_network.params['weights']),'biases':np.copy(copy_network.params['biases'])}# Mutating the weightsself.params['weights'] = [x+np.random.normal(loc=0,scale=var,size=x.shape) for x in self.params['weights']]self.params['biases'] = [x+np.random.normal(loc=0,scale=var,size=x.shape) for x in self.params['biases']]    def act(self, X):# Grabbing weights and biasesweights = self.params['weights']biases = self.params['biases']# First propgating inputsa = relu((X@weights[0])+biases[0])# Now propogating through every other layerfor i in range(1,len(weights)):a = relu((a@weights[i])+biases[i])# Getting probabilities by using the softmax functionprobs = softmax(a)return np.argmax(probs)# Defining the evaluation methoddef evaluate(self, episodes, max_episode_length, render_env, record):# Creating empty list for rewardsrewards = [] # First we need to set up our gym environmentenv=gym.make('CartPole-v0') # Recording video if we need to if record is True:env = gym.wrappers.Monitor(env, "recording") # Increasing max stepsenv._max_episode_steps=1e20for i_episode in range(episodes):observation = env.reset()for t in range(max_episode_length):if render_env is True:env.render()observation, _, done, _ = env.step(self.act(np.array(observation)))if done:rewards.append(t)break# Closing our enviromentenv.close()# Getting our final rewardif len(rewards) == 0:return 0else:return np.array(rewards).mean()

定义我们的遗传算法类

最后,我们需要定义一个类来管理我们的种群,执行神经进化中的四个关键步骤!这里我们需要三种方法。首先,创建随机网络池并设置属性的初始化方法。接下来,我们需要一个 fit 方法,给定一个输入,重复执行上述步骤:首先评估网络,然后选择最适合的,创建子网络,最后变异子网络!最后,我们需要一种预测方法,以便我们可以使用由该类训练的最佳网络。让我们开始测试吧!

# Defining our class that handles populations of networks
class GeneticNetworks():# Defining our initialization methoddef __init__(self, architecture=(4,16,2),population_size=50, generations=500,render_env=True, record=False,mutation_variance=0.02,verbose=False,print_every=1,episodes=10,max_episode_length=200):# Creating our list of networksself.networks = [NeuralNet(architecture) for _ in range(population_size)]self.population_size = population_sizeself.generations = generationsself.mutation_variance = mutation_varianceself.verbose = verboseself.print_every = print_everyself.fitness = []self.episodes = episodesself.max_episode_length = max_episode_lengthself.render_env = render_envself.record = record# Defining our fiting methoddef fit(self):# Iterating over all generationsfor i in range(self.generations):# Doing our evaluationsrewards = np.array([x.evaluate(self.episodes, self.max_episode_length, self.render_env, self.record) for x in self.networks])# Tracking best score per generationself.fitness.append(np.max(rewards))# Selecting the best networkbest_network = np.argmax(rewards)# Creating our child networksnew_networks = [NeuralNet(copy_network=self.networks[best_network], var=self.mutation_variance, max_episode_length=self.max_episode_length) for _ in range(self.population_size-1)]# Setting our new networksself.networks = [self.networks[best_network]]+new_networks# Printing output if necessaryif self.verbose is True and (i%self.print_every==0 or i==0):print('Generation:',i+1,'| Highest Reward:',rewards.max().round(1),'| Average Reward:',rewards.mean().round(1))# Returning the best networkself.best_network = self.networks[best_network]

测试我们的算法!

如上所述,我们将在 CartPole 问题上测试我们的网络,仅使用 1 个具有 16 个节点的隐藏层,以及两个表示向左或向右运动的输出节点。我们还需要对许多集进行平均,这样我们就不会意外地为下一代选择一个糟糕的网络!我在反复试验后选择了这些参数,所以你的里程可能会有所不同!此外,我们将只引入方差为 0.05 的突变,以便不破坏网络的功能。

# Lets train a population of networks
from time import time
start_time = time()
genetic_pop = GeneticNetworks(architecture=(4,16,2),population_size=64, generations=5,episodes=15, mutation_variance=0.1,max_episode_length=10000,render_env=False,verbose=True)
genetic_pop.fit()
print('Finished in',round(time()-start_time,3),'seconds')Generation: 1 | Highest Reward: 309.5 | Average Reward: 29.2
Generation: 2 | Highest Reward: 360.9 | Average Reward: 133.6
Generation: 3 | Highest Reward: 648.2 | Average Reward: 148.0
Generation: 4 | Highest Reward: 616.6 | Average Reward: 149.9
Generation: 5 | Highest Reward: 2060.1 | Average Reward: 368.3
Finished in 35.569 seconds

初始随机网络

首先,让我们看看一个随机初始化的网络如何执行任务。显然,这里没有策略,杆子几乎立刻就倒了。请忽略下面 gif 中的光标,在健身房录音在 Windows 上播放不太好!

图 1:一个随机的代理人试图解决 CartPole

random_network = NeuralNet(n_units=(4,16,2))
random_network.evaluate(episodes=1, max_episode_length=int(1e10), render_env=True, record=False)

五代之后…

仅仅 5 代之后,我们可以看到我们的网络几乎完全掌握了翻筋斗的艺术!而且只花了大约三十秒的火车时间!请注意,随着进一步的训练,网络学会在几乎 100%的时间里保持完全直立,但目前我们只对速度感兴趣,5 代相当短!我们应该认为这是神经进化力量的一个很好的例子。

图 2:一个训练有素的代理人正在解决横竿任务

# Lets observe our best network
genetic_pop.best_network.evaluate(episodes=3, max_episode_length=int(1e10), render_env=True, record=False)

下一步是什么?

显然,未来我们还可以增加很多东西来进一步检验神经进化的有效性。首先,研究不同变异算子(如交叉)的效果是很有趣的。

转移到 TensorFlow 或 PyTorch 等现代深度学习平台也是一个明智的想法。请注意,遗传算法是高度并行化的,因为我们所要做的就是在单个设备上运行每个网络,并向前传递一次。无需镜像权重或复杂的分配策略!因此,每增加一个处理单元,运行时间几乎呈线性减少。

最后,我们应该探索不同强化学习任务的神经进化,或者甚至是梯度难以评估的其他情况,例如在生成敌对网络或长序列 LSTM 网络中。

进一步阅读

如果你对神经进化及其应用感兴趣,优步有几篇论文展示了神经进化在强化学习中的现代优势:

[## 优步工程博客

推动世界发展的软件工程和技术

eng.uber.com](https://eng.uber.com/tag/deep-neuroevolution/)

这个项目的源代码可以在我的公共 GitHub 资源库中找到:

[## gur sky 1/Numpy-神经进化

如果我告诉你,你可以训练神经网络,而不需要计算梯度,只需要…

github.com](https://github.com/gursky1/Numpy-Neuroevolution)

如果你对这个项目有任何问题,或者只是想讨论深度学习,请随时发送电子邮件到gurskyjacob@gmail.com给我!

对咖啡分数的 Q 分数的有用性进行分级

原文:https://towardsdatascience.com/grading-the-usefulness-of-q-scores-for-coffee-grading-8ff2e8439572?source=collection_archive---------30-----------------------

各年级之间有趣的相关性

在我寻求更好地理解咖啡分级的 Q 分数的过程中,我开始好奇构成 Q 分数的 10 个指标是如何相互关联的。我最终找到了一个跨越多年、国家和 Q 分数过程的数据库。有些人已经研究了一些初始数据,但我没有找到对基本问题的分析:Q 分数的子指标是独立变量吗?咖啡分级员有多擅长客观分级?

咖啡杯的 Q 分数或 Q 等级

Q 分数是在咖啡杯过程中记录的 10 个因素的顶点。我根据自己对 SCA 杯状协议的理解,总结了每个指标。他们定义了如何准备咖啡样品,如何品尝,以及如何评分。我相信网上有很多资源可以帮助你通过快速搜索了解如何拔罐。

作者提供的图片与本文中的所有图片一样

由于补丁中的缺陷豆,最终分数也可能会丢分,因为允许有多少缺陷是有标准的。

根据这些描述,我制作了一个矩阵,说明我将如何假设不同的指标相互关联,因为它们中的许多指标在评分方式上有相似之处。它们是独立的指标,但根据定义,它们不是完全独立的变量。

数据

2018 年,一个善良的灵魂做了一个脚本,从咖啡品质院 (CQI)网站拉了一堆 Q 分,建立了一个超过 1300 个咖啡等级的数据库。我拉了这个数据,我只做了一个补充:全球区域。对于每个国家,我加上该国的大洲或整个地区。

q 分数分析

我用几种方法查看数据:箱线图、相关性和主成分分析(PCA)。每个人都从不同的角度来理解这个数据库。

箱线图

箱线图可以帮助人们理解分数分布通常是如何排列的,有时,趋势可以从那里出来。我看到了一些变化,但分布本身并没有引起我的注意。

放大相同的箱线图:

然后,我查看了各个指标,很快,我发现甜度、干净的杯子和均匀性大部分得分为 10(完美)。我不知道分数是怎么回事。这似乎很奇怪,这三个类别超过 90%的分数都在 10 分。这可能是一个数据导入问题(值得怀疑,因为我在 CQI 网站上查看了一些更新的数据),或者可能这些指标没有被普遍使用。这三个指标是十个指标中唯一量化的指标。

我没有其他关于 Q 分数的数据集,也没有一个解释。不过,我会继续分析,但我们不应该太看重这些。如果这些指标与最终分数紧密相关,那只是因为它们提高了分数。

相互关系

相关性是衡量两个变量彼此相似程度的指标。高相关性并不意味着一个变量会引起另一个变量,而是当情况发生变化时,两个变量的涨跌幅度相同。我从一开始就假设一些分级变量会有很高的相关性,因为它们是从不同的时间点来看味道的。

重新排序有助于显示七个指标之间的相互关系。

下面我举了两个散点图的例子。第一个结果显示味道和总分之间有很强的相关性。如果味道很好,并且与其他 6 个变量高度相关,那么总分应该是趋势。回味和风味也是如此。我认为好吃的东西会有很好的回味。这个关系更接近 y=x 线,但我不知道那是否有意义。总分趋势更高很可能是因为之前讨论的 3 个参数大部分等于 10,因为在大多数情况下总分和风味之间的偏差似乎约为 6(以 10 为标度)。

让我们更深入地了解 10 个变量,因为它们与总分相关,但在地区、年度和流程之间有所不同:

现在我们可以开始看到一些有趣的趋势,比如为什么北美咖啡豆的所有分数都有如此高的相关性?2015 年的豆子也一样?这里只有 8 个等级来自 2018 年的豆子,所以那些高相关性没有用。为什么 2011 年口味和期末成绩的相关性这么低?

让我们深入了解一些年份:

北美有奇怪的分数。每样东西都有很高的相关性,这在我看来没有一个指标是特别有趣的。这就引出了 Q-等级或分数对该地区的评分者或国家是否有用的问题。在这种情况下,北美只是墨西哥,因为中美洲分裂成了自己的一部分。

让我们在咖啡的味道中进行时间旅行:

2015 年类似于北美,那里的一切都有非常高的相关性。这是一个奇怪的问题,需要在这项研究之外进一步调查。2015 年对咖啡来说是反常的一年吗?箱线图表明这很正常。

让我们比较处理,这是有趣的,因为它缺乏异常。

加工类型确实对味道的感觉有影响,虽然最终得分有相似的分布,但湿法加工的味道与最终得分有更高的相关性。

主成分分析

PCA 意在将一组变量转换到一个新的空间,其中新的维度按照它们组成原始维度的可变性排序。一个简单的数据集可以在不损失保真度的情况下减少维数;在这种情况下,每个 Q 分用 10 个维度来表示,但也许你不需要那么多来表示总分。

根据我们对均匀性、净杯和甜度的了解,让我们将它们从 PCA 分析中排除,因为它们没有有意义的信息。

让我们从查看所有数据开始。似乎这两个主成分(PC)代表了数据中所有变化的 80%。虽然前 6 个指标对每个指标的贡献似乎是相等的,但我们已经知道所有变量彼此高度相关。最大的影响是铜点。

我们可以跨地区、跨年度、跨过程地观察,看看即使是个人电脑如何解释数据的可变性,也会有多大的差异。北美和 2015 年特别奇怪,因为我们已经从其他数据中看到,所有变异的 90%可以在第一台 PC 中得到解释。

放大来看,2014 年和 2016 年也是奇数年。对于处理来说,湿法似乎是第一台 PC 的天下。

我们可以查看这些区域,以帮助理解哪些变量在使用 PC 时更突出。非洲咖啡豆的味道似乎比酸度或口感更有优势。他们有一个相似的趋势,就像南美豆一样。北美豆类在第一台个人电脑中有它们所有的可变性。

就年份而言,唯一奇怪的是所有 7 项指标在第一台电脑中的权重相似。考虑到 2015 年这些指标之间的高度相关性,这并不奇怪。

对于加工,湿加工由第一个 PC 控制,但是对于干加工,第一个 PC 包含较少的变化。对于这两者,第二台电脑主要是由铜点,这是一个整体指标。

三个常数

当寻找有用的指标时,数据显示均匀性、干净的杯子和甜度并不那么有用。它们确实是更可量化的指标,因为它们超过 5 杯相同的咖啡,但显然,变量缺乏使它们成为有用指标所需的可变性。我只能希望在数据集中有一些问题,他们不是真的这么没用。

在查看 Cupper Points 时,它与总分的关系如此密切,以至于我不确定作为一个指标它是否非常有用,或者说它意味着总分可能不是非常有用。

q-分级最初是为了帮助区分专业咖啡和其他咖啡,虽然我肯定它已经完成了这项工作,但我不认为这种方法可以很好地区分专业咖啡。我把这个建立在上述数据集的基础上,我承认也许有一个更好的数据集是我无法获得的。

我建议为特色咖啡制定一个新的等级,从 0 到 100。目前的标准实际上是典型值在 80 到 95 之间。一个 92 真的比一个 91 好很多吗?我不知道。我的经验是 92 分比 85 分好,但我希望改进后的量表可以消除这种模糊性。

附录

在发表这篇文章后,Keith Klein 总结了干净的杯子,均匀性和甜度,我认为这对于理解为什么它们大部分是 10 的和大部分是恒定的是有价值的。我觉得他们区分特色咖啡和非特色咖啡还是有价值的,而不是区分特色咖啡彼此。在他的许可下,以下是他对这三项指标以及得分的评论:

“这些分数与缺陷直接相关,并不像许多人认为的那样是对咖啡固有风味的评级。只有当其中一个杯子有污点或完全缺陷时,你才应该从这些杯子中扣分。

“甜味是其中最宽容的,因为偶尔一个受污染的杯子仍会显示一些甜味,不必进一步处罚。如果一杯咖啡真的没有甜味,那么它应该只有一点甜味。

“这个数据集来自合格的 Q 评分者,他们按照预期使用这些类别。这向你展示了 Q 系统对无缺陷咖啡的重视程度,因为对缺陷的处罚会迅速增加。一个完整的缺陷会降低 10 分。

“cupper points 和总分之间的高相关性是有意的。当你的评价接近尾声时,你的点数会奖励你特别喜欢的咖啡,惩罚你不喜欢的咖啡。”

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。

我的进一步阅读:

咖啡豆脱气

解构咖啡:分割烘焙、研磨和分层以获得更好的浓缩咖啡

浓缩咖啡的预浸:更好的浓缩咖啡的视觉提示

咖啡的形状

搅拌还是旋转:更好的浓缩咖啡体验

香辣浓缩咖啡:热磨,冷捣以获得更好的咖啡

断续浓缩咖啡:提升浓缩咖啡

用纸质过滤器改进浓缩咖啡

浓缩咖啡中咖啡的溶解度:初步研究

断奏捣固:不用筛子改进浓缩咖啡

浓缩咖啡模拟:计算机模型的第一步

压力脉动带来更好的浓缩咖啡

咖啡数据表

被盗咖啡机的故事

浓缩咖啡过滤器分析

便携式浓缩咖啡:指南

Gradio:机器学习模型的图形界面

原文:https://towardsdatascience.com/gradio-graphical-interfaces-for-machine-learning-models-fd4880964f8f?source=collection_archive---------27-----------------------

介绍 Gradio,一个用于创建机器学习模型用户界面的开源 Python 包。

介绍

由于许多开源和基于专利的服务(例如 Python、R、SAS),现在创建机器学习模型变得越来越容易。尽管,实践者可能总是发现很难有效地创建接口来测试并与同事或涉众共享他们完成的模型。

这个问题的一个可能的解决方案是 Gradio ,这是一个免费的开源 Python 包,可以帮助你创建模型用户界面,你可以毫不费力地通过链接分享给同事和朋友。

使用以下命令可以轻松安装 Gradio:

!pip install gradio

Gradio 与许多机器学习框架(例如 TensorFlow、PyTorch 等)完美兼容,甚至可以用于任意的通用 Python 脚本。

现在,我将向您介绍 Gradio 如何集成到您的机器学习工作流程中的不同示例。本文使用的所有代码都在这个 Google Colab 笔记本和我的 GitHub 账户中。

民众

图像分类

在本例中,我们将创建一个加载图像的界面来测试计算机视觉模型。在这种情况下,我们将使用 PyTorch 和 Alexnet 预训练模型,但这个实验可以为任何其他模型和框架重新创建。

为了创建 Gradio 接口,我们只需调用 接口函数 并传递三个参数:

  • fn: 通过与用户界面交互来自动调用的函数,以便为我们的模型创建预测,提供某种形式的输入。
  • **输入:**告知 Gradio 我们期望从用户界面获得何种类型的输入(例如,图像、文本、音频数据、数字数据)。
  • **输出:**通知 Gradio 我们的预测函数将返回什么类型的输出。通过这种方式,Gradio 可以了解如何在用户界面上最好地呈现输出。

一旦创建了我们的界面,我们只需要启动它(图 1)。当启动接口时,我们可以决定是否传递额外的参数,如共享调试为真。事实上,这些参数不仅可以用于将 Gradio 界面嵌入我们的笔记本电脑,还可以作为一个可共享的网页,使我们在测试期间更容易调试系统。可共享的链接,虽然只有 6 个小时是活跃的。

图 1: Gradio 图像分类器

文本生成

为了预测句子的结论或生成叙述而生成文本是当前非常感兴趣的话题,尤其是由于自然语言处理(NLP)转换器的出现。在这个例子中,我将为我在上一篇关于 NLP 的文章中介绍的 GTP2 HuggingFace 预训练模型创建一个用户界面。

图 2: Gradio 文本分析

实时通用 ML 模型预测

最后,在这个例子中,我将展示 Gradio 如何用于涉及多种类型输入数据的经典机器学习问题。在这个例子中, Kaggle 心脏病 UCI 数据集将被用作我们的数据集。所有的数据预处理步骤都在这个 Google Colab 笔记本和我的 GitHub 账号上。

图 3: Gradio Live 通用 ML 模型预测

结论

在创建和测试模型时,Gradio 无疑是为机器学习项目创建界面的绝佳工具,尽管为了将您的模型整合到生产和稳定的环境中,可能需要替代解决方案,例如:

  • ONNX(开放式神经网络交换格式)
  • 烧瓶和 Heroku
  • Tensorflow.js
  • 阴谋地破折号
  • 特克因特

Gradio 提供的不同设施和 GUI 界面的完整列表可在Gradio 官方文档页面上找到。如果您有任何问题,欢迎在下面的评论区留下您的评论。

我希望你喜欢这篇文章,谢谢你的阅读!

联系人

如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

  • 领英
  • 个人博客
  • 个人网站
  • 中等轮廓
  • GitHub
  • 卡格尔

计算机视觉的图形分类

原文:https://towardsdatascience.com/graph-classification-by-computer-vision-286572aaa750?source=collection_archive---------37-----------------------

如今,图形分析变得越来越流行,但是与计算机视觉方法相比,它的表现如何?我们将展示,虽然计算机视觉模型的训练速度慢得多,但与图论相比,它们的表现相当好。

  • Github 回购与所有代码,链接

图形分析

一般来说,图论表示对象之间的成对关系。我们不会在这里留下太多的细节,但你可以考虑它的某种网络如下:

网络。照片由阿丽娜·格鲁布尼亚在 Unsplash 上拍摄

这里我们需要知道的要点是,通过用边连接对象,我们可以可视化图形。然后我们将能够使用经典的计算机视觉模型。不幸的是,我们可能会丢失一些初始信息。例如,图表可能包含不同类型的对象、连接,在 2D 也许不可能把它可视化。

图书馆

如果您愿意开始使用它们,您可以查看大量的库:

  • networkx —经典算法,可视化
  • pytorch _ geometric—SOTA 算法图,py torch 之上的一个框架
  • 图形工具 —经典算法、可视化
  • scikit-network —经典算法,sklearn like API
  • TensorFlow Graphics—SOTA 算法图,一个基于 tensor flow 的框架

都是针对自己的特定角色。这就是为什么它取决于你的任务使用哪一个。

理论

这篇文章更多的是针对实际应用,这就是为什么对于理论我将只留下一些链接:

  • [用 PyTorch 的手动图形神经网络& PyTorch 几何](http://Hands-on Graph Neural Networks with PyTorch & PyTorch Geometric)
  • CS224W:带图的机器学习
  • 图分类将基于图卷积网络(GCN), arxiv 链接

模型架构

我们将使用以下架构作为基线:

* GCNConv - 6 blocks
* JumpingKnowledge for aggregation sconvolutions
* global_add_pool with relu
* Final layer is softmax

代码链接就是基于这个教程。

计算机视觉

通过阅读本文,您将获得所有必需的理论和技术技能:

  • 2020 年指导如何学习和掌握计算机视觉

此外,您应该熟悉以下主题:

  • 效率网https://arxiv.org/abs/1905.11946
  • 焦损失https://arxiv.org/abs/1708.02002
  • 白蛋白 —扩增库
  • py torch-lightning—py torch 框架

模型架构

我们将使用以下没有任何超参数调整的模型:

* efficientnet_b2b as encoder
* FocalLoss and average precision as early stopping criteria
* TTA with flip left right and up down
* Augmentation with albumentation
* Pytorch-lightning as training model framework
* 4 Folds Assembling
* mixup

代码链接。

实验

数据

我们将预测活动(针对 COVID?)的不同分子。

数据集示例:

smiles, activity
OC=1C=CC=CC1CNC2=NC=3C=CC=CC3N2, 1
CC(=O)NCCC1=CNC=2C=CC(F)=CC12, 1
O=C([C@@H]1[C@H](C2=CSC=C2)CCC1)N, 1

为了生成用于计算机视觉方法的图像,我们首先将图形转换为 networkx 格式,然后通过调用 draw_kamada_kawai 函数获得所需的图像:

不同的分子可视化将用于计算机视觉方法。图片由 Insaf Ashrapov 提供

链接到数据集。

实验结果

TESTComputer vision**Test**
* ROC AUC 0.697
* MAP 0.183Graph method**Test**
* ROC AUC 0.702
* MAP 0.199

因为你可以得到几乎相似的结果。图表法得到的结果稍高一些。此外,训练 GNN 只需 1 分钟,CNN 只需 30 分钟。我不得不说:这只是一个概念验证项目,有许多简化。

换句话说,你可以可视化图形,训练著名的计算机视觉模型,而不是新奇的 GNN。

参考

  1. Github repo 与 Insaf Ashrapov 的所有代码链接
  2. GNN 教程http://pages . di . unipi . it/citraro/files/slides/Lando lfi _ tutorial . pdf

用于状态新冠肺炎关联分类的图卷积网

原文:https://towardsdatascience.com/graph-convolutional-nets-for-classifying-covid-19-incidence-on-states-3a8c20ebac2b?source=collection_archive---------30-----------------------

如何将地图映射到图卷积网络。

墨西哥州图的简单图卷积神经网络示意图。

编者注: 走向数据科学 是一份以研究数据科学和机器学习为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

首先,我想说,在我看来,在线媒体提供了一个向世界展示科技界在我们当前所处的紧迫时代所做努力的机会,这一点非常重要。有必要以可以与由 SARS COV2 病毒引起的疫情的传播速度竞争的速度传播正在产生的信息,SARS cov 2 病毒引起了被称为新冠肺炎的疾病。病毒已经成为科学家的个人敌人,在许多情况下,它是一个未知的敌人,你必须发明一种方法来对抗它,因为我们真的不知道如何对抗(如果你不是流行病学家或相关人员)。当然,最好的工具是保持物理距离和卫生措施已经说了这么多,重复这么多。但是,作为科学家,我们有各种各样的工具可以用来抗击这种流行病,我们必须努力做出我们的贡献,不管这些贡献有多小。这就是我所相信的,也是为什么我提出这个小作品,更多的是邀请大家回顾所谓的图形卷积神经网络(GCNN 的)在新冠肺炎行为研究中的有用性。但我必须澄清,我提出的结果不应被视为预测,因为这是一个非常初步的计划,当然,除了这里使用的因素以外,还必须考虑其他因素。也就是说,让我们开始工作吧!!

  1. 安装补充库。

进入 GCNN 世界的一个相对简单的方法是使用 DGL 图书馆,它除了有不同的实现之外,还有很好的文档(我鼓励你回顾一下关于“Zachary 的空手道俱乐部”[1]问题的教程,我在我们的例子中提到了它。),所以我将在接下来的文章中构建这个库。我非常喜欢 Google Colaboratory 或“Colab ”,因为它允许快速测试 Python 中的原型项目,这是非常便携的,所以我提供的代码适用于 Colab 笔记本(参见本文末尾的笔记本链接)。

首先我们需要安装带有 pip 的 dgl,我们将使用 pandas 和 numpy,所以我们继续导入它们,

可选地,我们也可以安装 chart_studio 并调用 Plotly 来制作交互式图表,正如我在上一篇文章[2]中展示的那样。

2.建立图表。

图是由一组节点和定义连通性的边组成的。例如,如果它是一个分子,节点将是组成它的原子,而它们之间的键将是边[3]。但是,如果我们想把这个想法转移到地理地图上,我们必须决定什么是节点,什么是边。一种方法是将节点作为一个国家的州,但边可以是几个东西。这里,我决定将边定义为两个给定状态之间的公共边界。为了做到这一点,我已经采取了墨西哥共和国的 31 个州+墨西哥城的地图,我列出了他们之间的联系。下图显示了墨西哥的地图,并在此项工作中进行了编号:

带有用于图形定义的编号的墨西哥地图。

在这一点上,我希望有一个邻接矩阵与每个国家相关联,这将使我刚才描述的过程更容易。总之,我确定的连接最终形成了编码为源点(src)和目的点(dst)的邻接矩阵。通过提供源点和目的地点,确保信息是双向的,就可以将信息传递到 DGL。
这是通过以下函数实现的:

具有此定义的图 G 由 32 个节点和 264 条边组成,我们可以使用 networkx:

给出这个图表:

墨西哥各州之间的边界连通性图。

生成的图可以在视觉上识别出来,并且(用一点想象力)与墨西哥地图一起识别,注意节点 1 和 2 形成了下加利福尼亚半岛,而节点 30、22 和 3 形成了尤卡坦半岛。因此,目前看来一切进展顺利。

3.特征化。

要使用 GCNN,我们必须特征化节点。为此,我将使用一次性编码方案。

一个热点向量乘以[4]中的人口密度,下图显示了 2015 年每个州的人口密度。

为了形成半监督方法,我根据[5]中的官方信息为三个级别(低、中、高)中的每一个级别取两个节点(状态)。这些信息存储在两个张量中,标签 _ 节点用于标识状态,标签用于指示三个事件等级(根据今天的情况定义,2020 年 4 月 17 日),等级低的状态为“0”,等级中等的为“1”,等级高的为“2”:

以下是州名、州号和相关级别之间的对应关系:

3 →坎佩切(0)

17 →纳亚里特(0)

13 →哈利斯科(1)

18 →新莱昂州(1)

4 →墨西哥城(2)

1 →加州 BAJA(2)

这些节点是 GCNN 了解的节点,并将尝试预测与其余未标记节点对应的级别。

4.图卷积神经网络。

根据 Kipf [6],多层 GCNN 从图𝒢=(𝒱,ℰ中学习)取输入 1)输入 N× D 特征矩阵 *X,*其中 N 是节点的数量, D 是每个节点的特征数量;以及 2)类似邻接矩阵 A 的图结构的矩阵表示。对于给定的神经网络层,GCNN 的一般形式具有以下传播规则:

其中 f 是非线性函数, *H⁰=X,*经过若干层 l=L 后,我们得到一个输出 ZN×F 维特征矩阵,其中 F 是每个节点的特征数。关于 GCNN 的更多细节可以在[3,6]中找到。在我们的例子中,只需要记住我们想要输入一个特征向量 N = 32 并获得三个类别:低、中、高,因此 F=3 。以下是 GCNN 结构的代码:

5.训练。

最后一段代码是训练循环,其中我们使用了在 Pytorch 中实现的 Adam optimizer,学习率为 0.01。用六个标记节点的输入标签训练 GCNN,并且在每次迭代中应用 log_softmax 和 loss 函数以及反向传播,就像在任何神经网络中一样:

6.可视化。

我们可以用最后一个时期的 all_logits 数组制作一个数据帧。然后对于每个节点,我们得到三个标签中最大值的索引。这将指示每个节点的预测。

我发现使用 https://flourish.studio/可以用一种非常简单的方式绘制地图,而且效果非常好,所以这次我选择了使用这个工具。蓝色表示低水平(0),红色表示中等水平(1),黄色表示高水平(2):

这不应被视为预测,它只是第一种方法。

下一步是什么?
1)为新冠肺炎的传播找出更有代表性的描述词。例如,使用每 100,000 名居民的发病率作为疾病传播效率的指标可能是有意义的,也可能是每个州的市内交通站的流动性。不要为州与州之间的边界定义图表,而是为连接城市的道路定义图表,并为人口流入赋予一定的权重。
3)回顾对已经超过最大传染点的其他国家的预测,如中国或意大利。

**结论:**以州与州之间的边界为纽带,假设节点之间有通信,这可能代表不同州之间的人流没有被取消的事实。很明显,通过停止人口迁移,这种联系就被打破了,这将不得不修改像这里展示的神经网络的预测。由于一个州对它的邻居征收很高的税率,结果可能是一个小的影响。

**鸣谢:**要感谢 PhD。来自奇瓦瓦自治大学的 Jaime Raúl Adame Gallegos,感谢他在撰写本文件过程中的善意评论和建议。

上面显示的代码可以在这个链接中使用 Google Colaboratory 打开:https://github . com/napoles-uach/covid 19 MX/blob/master/dgl _ map . ipynb

参考资料:

  1. https://docs.dgl.ai/en/0.4.x/tutorials/basics/1_first.html
  2. https://medium . com/@ jna poles/tracking-covid 19-with-pandas-and-plotly-open-source-graphing-library-maps-d 24 BAF 31 AAC 4
  3. https://towards data science . com/practical-graph-neural-networks-for-molecular-machine-learning-5e 6 dee 7 DC 003
  4. https://www.inegi.org.mx/app/tabulados/interactivos/?px = Poblacion _ 07&BD = Poblacion
  5. https://covid19.sinave.gob.mx/
  6. 【http://tkipf.github.io/graph-convolutional-networks/

基于节点分类任务的训练图卷积网络

原文:https://towardsdatascience.com/graph-convolutional-networks-on-node-classification-2b6bbec1d042?source=collection_archive---------4-----------------------

使用图卷积网络的引用网络节点分类图解(图片由作者提供)

本文通过使用spek tralAPI 实现图卷积网络(GCN),这是一个基于 Tensorflow 2 的用于图深度学习的 Python 库。我们将使用 CORA 数据集执行半监督节点分类,类似于 GCN 原始论文中由 Thomas Kipf 和 Max Welling (2017) 提出的工作。

如果你想对图卷积网络有基本的了解,建议先阅读本系列的 第一篇 第二篇 部分。

数据集概述

CORA 引文网络数据集由 **2708 个节点组成,**其中每个节点代表一个文档或一篇技术论文。节点特征是指示文档中单词存在的单词包表示。词汇表——因此也是节点特性——包含了 1433 个单词。

通过来源将单词袋图解为节点特征

我们将数据集视为无向图,其中边表示一个文档是否引用另一个文档,反之亦然。该数据集中没有边要素。这项任务的目标是将节点(或文档)分为 7 个不同的类别,这些类别与论文的研究领域相对应。这是一个单模 数据表示设置的单标签多类分类问题。

这种实现也是直推式学习的一个例子,其中神经网络在训练期间看到所有数据,包括测试数据集。这与归纳学习形成对比,归纳学习是典型的监督学习,在训练过程中测试数据保持独立。

文本分类问题

由于我们要根据文档的文本特征对文档进行分类,所以看待这个问题的一种常见的机器学习方法是将其视为有监督的文本分类问题。使用这种方法,机器学习模型将仅基于每个文档自身的特征来学习每个文档的隐藏表示。

对文档分类问题的文本分类方法的说明(图片由作者提供)

如果每个类都有足够多的标记示例,这种方法可能会很有效。不幸的是,在现实世界中,标注数据可能非常昂贵。

解决这个问题的另一种方法是什么?

除了自己的文本内容,通常,一篇技术论文还会引用其他相关论文。直觉上,被引用的论文很可能属于相似的研究领域。

在这个引用网络数据集中,除了它自己的文本内容之外,我们想要利用来自每篇论文的引用信息。因此,数据集现在已经变成了一个论文网络。

带有部分标注数据的引用网络数据集插图(图片由作者提供)

使用这种配置,我们可以利用图形神经网络,例如图形卷积网络(GCNs ),来建立一个模型,该模型除了学习文档自身的文本特征之外,还学习文档的互连。GCN 模型将不仅基于其自身的特征,而且基于其相邻节点的特征来学习节点(或文档)的隐藏表示。因此,我们可以减少必要的标记示例的数量,并利用【A】邻接矩阵或图中的节点连通性来实现半监督学习。

图形神经网络可能有用的另一种情况是当每个例子本身没有不同的特征,但是例子之间的关系可以丰富特征表示。

图形卷积网络的实现

加载和解析数据集

在这个实验中,我们将使用基于 Tensorflow 2 构建的 Spektral API 来构建和训练一个 GCN 模型。虽然 Spektral 提供了内置函数来加载和预处理 CORA 数据集,但在本文中,我们将从这里下载原始数据集,以便更深入地了解数据预处理和配置。本文整个练习的完整代码可以在 GitHub 上找到。

我们在各自的数据目录中使用 cora.contentcora.cites 文件。加载文件后,我们将随机打乱数据。

cora.content 文件中,每一行都由几个元素组成:
第一个元素表示文档(或节点)ID,
第二个
到最后一个元素表示节点特征,
最后一个
元素表示该特定节点的标签。

cora.cites 文件中,每行包含一个文档元组(或节点)id。元组的第一个元素表示被引用论文的 ID**,而第二个元素表示包含引用的论文。虽然这种配置代表一个有向图,但在这种方法中,我们将数据集视为一个无向图。**

加载数据后,我们构建节点特征矩阵( X )和包含相邻节点元组的列表。这个边列表将被用来构建一个图,从这里我们可以获得邻接矩阵( A )。

输出:

设置训练、验证和测试掩码

我们将节点特征矩阵( X )和邻接矩阵( A )输入神经网络。我们还将为每个训练、验证和测试数据集设置长度为 N布尔掩码**。当这些掩码的元素属于相应的训练、验证或测试数据集时,它们为。例如,属于训练数据的训练掩码元素为。**

训练、验证和测试布尔掩码的示例

在论文中,他们为每个班级挑选了 20 个有标签的例子。因此,通过 7 个类,我们将总共有 140 个带标签的训练示例。我们还将使用 500 个标记的验证示例1000 个标记的测试示例。

获取邻接矩阵

下一步是获得图的邻接矩阵( A )。我们使用 NetworkX 帮助我们做到这一点。我们将初始化一个图,然后将节点和边列表添加到图中。

输出:

将标签转换为一键编码

构建我们的 GCN 之前的最后一步是,就像任何其他机器学习模型一样,对标签进行编码,然后将其转换为一次性编码。

我们现在已经完成了数据预处理,准备好构建我们的 GCN 了!

构建图形卷积网络

GCN 模型架构和超参数遵循 GCN 原始论文中的设计。GCN 模型将采用 2 个输入,节点特征矩阵( X )和邻接矩阵( A )。我们将实施两层 GCN** 辍学层和 L2 正规化。我们还将设置最大训练周期为 200 并实施提前停止,耐心为 10 。这意味着一旦确认损失连续 10 个时期没有减少,训练将停止。为了监控训练和验证的准确性和损失,我们还将在回调中调用 TensorBoard 。**

在将邻接矩阵( A )输入到 GCN 之前,我们需要根据原文执行重正化技巧来做额外的预处理。你也可以在这里阅读重正化技巧如何影响 GCN 正向传播计算。

下面训练 GCN 的代码最初是从 Spektral GitHub 页面获得的。

训练图卷积网络

我们正在实施直推式学习,这意味着我们将把整个图表用于训练和测试。我们使用之前构建的布尔掩码来分离训练、验证和测试数据。这些掩码将被传递给 sample_weight 参数。我们将 batch_size 设置为整个图形的大小,否则图形会被打乱。

为了更好地评估每个类的模型性能,我们使用 F1 分数而不是准确性和损失度量。

训练完成!

从分类报告中,我们获得了 74%的宏观平均 F1 值。

使用 t-SNE 的隐藏层激活可视化

现在让我们使用 t-SNE 来可视化隐藏的图层表现。我们使用 t-SNE 将隐藏表示的维度降低到 2-D。图中的每个点代表每个节点(或文档),而每个颜色代表每个类。

输出:

GCN 隐层的 T-SNE 表示。GCN 能够很好地学习由不同数据聚类显示的特征表示。

与全连接神经网络的比较

作为基准,我还训练了一个 2 层完全连接的神经网络(FCNN ),并绘制了隐藏层表示的 t-SNE 可视化。结果如下所示:

两层全连接神经网络的分类结果

FCNN 隐层表示的 T-SNE 表示。FCNN 对文件的分类不如 GCN。

从上面的结果可以清楚地看出,GCN 明显优于 FCNN,宏观平均 F1 得分仅为 55%。FCNN 隐藏层表示的 t-SNE 可视化图是分散的,这意味着 FCNN 不能像 GCN 那样学习要素表示。

结论

执行文档分类(例如 CORA 数据集)的传统机器学习方法是使用监督文本分类方法。图卷积网络(GCNs)是一种替代的半监督方法,通过将文档视为相关论文的网络来解决这个问题。每类仅使用 20 个标记的例子,GCNs 在这项任务上比全连接神经网络高出约 20%。

感谢阅读!我希望这篇文章能帮助你在自己的问题上实现图卷积网络(GCNs)。

有什么意见、反馈或想讨论的吗?请给我留言。你可以在LinkedIn上联系到我。

你可以在 GitHub 上找到完整的代码。

参考

[1] T. Kipf 和 M. Welling,使用图卷积网络的半监督分类 (2017)。arXiv 预印本 arXiv:1609.02907。ICLR 2017

[2]https://github . com/danielegrattarola/spek tral/blob/master/examples/node _ prediction/citation _ gcn . py

https://linqs.soe.ucsc.edu/data

[4] D. Grattarola 和 C. Alippi ,tensor flow 和 Keras 中的图形神经网络与 Spektral (2020)。arXiv:2006.12138。ICML 2020——GRL+研讨会

编码面试的图表数据结构备忘单。

原文:https://towardsdatascience.com/graph-data-structure-cheat-sheet-for-coding-interviews-a38aadf8aa87?source=collection_archive---------3-----------------------

这篇博客是我的“大型科技公司黑客技术面试 15 天备忘单”的一部分。在这篇博客中,我不会详细介绍图形数据结构,但我会总结一些解决编码面试问题的必备图形算法。

图形数据结构

图是由顶点(V)和边(E)组成的非线性数据结构。

最常用的图的表示是邻接矩阵(大小为 V x V 的 2D 数组,其中 V 是图中顶点的数量)和邻接表(列表数组表示与每个顶点相邻的顶点的列表)。

在接下来的几节中,让我们来看看与图形数据结构相关的一些必须知道的算法。为简单起见,所有实现中都使用邻接表表示。

1.广度优先搜索(BFS)

Input (graph 1): graph = [[1,2], [0,2,4], [0,1,3], [2], [1]], s = 0
Output: **0 1 2 4 3**

图的广度优先搜索类似于树的广度优先遍历。但是,图可能包含圈,所以我们可能会一次又一次地访问同一个顶点。为了避免这种情况,我们可以使用布尔访问数组来标记访问过的顶点。

上面的代码只遍历从给定的源顶点可以到达的顶点。为了完成不连通图的 BFS 遍历,我们需要为每个顶点调用 BFS。

时间复杂度是 O(V+E ),其中 V 是图中顶点的数量,E 是图中边的数量。

2.深度优先搜索

Input (graph 1): graph = [[1,2], [0,2,4], [0,1,3], [2], [1]], s = 0
Output: **0 1 2 3 4 (or 0 2 3 1 4)**

类似于 BFS,我们也需要使用一个布尔数组来标记 DFS 的访问过的顶点。

递归实现:

使用堆栈的迭代实现。请注意,堆栈可能包含同一个顶点两次,,所以我们需要在打印前检查访问过的集合。

对于这两种实现方式,从给定的顶点可能无法到达所有的顶点(示例断开图)。为了完成 DFS 遍历,我们需要为每个顶点调用 DFS。

时间复杂度是 O(V+E ),其中 V 是图中顶点的数量,E 是图中边的数量。

3.检测有向图中的圈

Given a **directed** graph, return true if the given graph contains at least one cycle, else return false.Input (graph 2): graph = [[1,2], [2], [0,3], [], [1]]
Output: **True**

DFS 可用于检测图中的循环。只有当从一个顶点到它自己(自循环)或者到它在 DFS 栈树中的一个祖先有一个后沿时,图中才有一个循环。

时间复杂度和正常的 DFS 一样,都是 O(V+E)。

4.检测无向图中的圈

Given an **undirected** graph, return true if the given graph contains at least one cycle, else return false.Input (graph 1): graph = [[1,2], [0,2,4], [0,1,3], [2], [1]]
Output: **True**

对于无向图,我们不需要跟踪整个堆栈树(与有向图的情况相比)。对于每个顶点“v”,如果有一个相邻的“u”使得 u 已经被访问过,并且 u 不是 v 的父节点,那么图中有一个圈。

时间复杂度和正常的 DFS 一样,都是 O(V+E)。

5.多源 BFS

在某些问题中,您需要为多个顶点启动 BFS,并计算行进深度。我们来看一个典型问题。

Rotting Oranges: [https://leetcode.com/problems/rotting-oranges/](https://leetcode.com/problems/rotting-oranges/)

在这个问题中,我们使用 BFS 来模拟这个过程。网格被认为是一个图形(一个橙色的单元是一个顶点,有边到单元的邻居)。从“深度”为 0 的所有腐烂的橙子开始 BFS,然后旅行到其深度为 1 的邻居。最后,如果我们仍然有未访问的橙子,返回-1,因为这不可能腐烂所有的橙子。

时间复杂度为 O(V+E) = O(网格中的单元数)。

6.拓扑排序

拓扑排序是顶点的线性排序,使得对于每个有向边 uv,顶点 u 在排序中位于 v 之前。拓扑排序只可能用于有向无环图(DAG) 。

Given a **DAG**, return the topological sortingInput: graph = [[1,2], [2], [3], [], [1]]
Output: **4 0 1 2 3**

在普通的 DFS 中,我们在递归函数的开始打印顶点。为了找到拓扑排序,我们修改 DFS,使其首先递归调用所有相邻顶点,然后将其值推入堆栈。最后,我们打印出堆栈。

时间复杂度和正常的 DFS 一样,都是 O(V+E)。

7.未加权图中的最短路径

Given a unweighted graph, a source and a destination, we need to find shortest path from source to destination.Input (graph 1): graph = [[1,2], [0,2,4], [0,1,3], [2], [1]], s=4, d=0
Output: **4 1 0**Input (graph 2): graph = [[1,2], [2], [0, 3], [], [1]], s=1, d=0
Output: **1 2 0**

对于这个问题,我们使用 BFS,并在进行广度优先搜索时保存给定顶点的前任。最后,我们使用 predecessor 数组打印路径。

时间复杂度和普通 BFS 一样,都是 O(V+E)。

7.加权图中的最短路径

Given a graph and a source vertex in graph, find shortest distances from source to all vertices in the given graph.Input: graph = [[[1, 2], [2, 6]], [[2, 1]], [[0, 1], [3, 3]], [], [[1, 1]]], s=0
Output: **[0, 2, 3, 6, inf]**

在这个问题中,我们处理加权图(一个实数与图的每条边相关联)。该图被表示为一个邻接表,其项目是一对目标顶点&权重。Dijkstra 算法用于查找从一个起始顶点到其他顶点的最短路径。该算法适用于有向或无向图,只要它的在一条边上没有负权重。

你可以在这里阅读更多关于 Dijkstra 算法的内容。下面是我使用优先级队列的实现。

上面的实现只返回距离。您可以添加一个前置数组(类似于未加权图中的最短路径)来打印出路径。时间复杂度是 O(V + VlogE),其中 V 是图中顶点的数量,E 是图中边的数量。

推荐问题

您可以通过以下问题练习图形数据结构:

  1. 图是二分的吗?
  2. 克隆图形
  3. 课程表
  4. 课程表二
  5. 岛屿数量
  6. 无向图中连通分量的数量
  7. 图形有效树
  8. 重建旅程
  9. K 站内最便宜的航班(提示:Dijkstra 算法)
  10. 外星人字典(提示:拓扑排序)

公共部门的图形数据库

原文:https://towardsdatascience.com/graph-databases-for-the-public-sector-1a50d0563fff?source=collection_archive---------47-----------------------

利用图表技术进行公共部门数据管理和数据分析的使用案例和示例。

图形数据库是你的技术堆栈中(不那么)新的必备工具。在过去的几十年里,越来越多的科技巨头(脸书,Twitter 和谷歌引领潮流)已经开始将数据迁移到图形数据库中,不仅以高度可扩展的方式存储和检索数据,还将模型整合到图形结构中,以产生高效的推荐。

是什么让图形数据库对这些拥有庞大数据的公司如此有吸引力?公共部门能以类似的方式从这项技术中受益吗?

知识图和 RDBMS 的区别是什么?

RDBMS 基础知识

关系数据库管理系统(RDBMS)是指以具有行和列的结构化格式存储数据的数据库,并且具有展示数据库内不同表之间的链接的模式。RDBMS 通常用 SQL(结构化查询语言)或类似的语言进行查询,对于相当静态(不变)和规范化的数据结构非常有用。

为了给出 RDBMS 的一个基本用例,让我们假设我们正在创办一家名为 GovBook 的公司,它相当于政府的脸书,允许用户注册一个帐户,提交政府文件,并在社交场合与政府官员互动。每个人都有数千个数据属性被捕获,每个属性都必须放入数据库中的特定表中。我们可以构建我们的数据库模式,使之具有一个用户 注册表,其中包含注册期间给出的用户的所有信息,以及一个文档表,其中包含用户上传到系统的每个文档的 pdf 链接。将会有某种唯一的标识符,称为主键来区分用户注册表中的用户,这个键也将作为外键来将两个表相互链接。

这似乎是处理数据管理的一种非常好的逻辑方式,但是当然这种类型的结构化系统有优点也有缺点。在这个例子中,最大的缺点是所有输入的数据都能够适合预先指定的表列。但是,如果在业务开展一年后,GovBook 决定在注册期间获取额外的数据,该怎么办呢?开始时,他们获取姓名、用户名、密码、电子邮件和性别,但现在他们想添加一个出生日期字段。

NoSQL 图形数据库

这个问题引出了 NoSQL(不仅仅是 SQL)数据库的概念,它允许这样的数据存储:

  • 非结构化
  • 高度可扩展
  • 无模式

在过去的十年中,一种特殊类型的 NoSQL 数据库,即图形数据库,变得非常受欢迎。图形数据库使用主谓宾三元组,而不是将数据解释为行和列。因此,在上面的例子中,不是将一行数据詹妮塔·乔治,詹妮塔·乔治 1990,密码 01,jennettageorge1990@email.com,女插入注册表,而是将以下三元组添加到图中:

  • 珍妮塔·乔治->哈斯用户名→珍妮塔·乔治 1990
  • jennetta George-> has password-> password 01
  • 詹妮塔·乔治->哈斯梅尔->jennettageorge1990@email.com
  • 珍妮塔·乔治->哈斯性别->女性

三元组的主语和宾语是图的节点,谓语是

不要让 RDBMS 中的术语关系欺骗了你——在图数据库中,边(或节点之间的关系)被视为一等公民,这就是图数据库真正的魔力所在。边充当图中所有数据之间的连接,并且本身充当丰富的数据源。根据您选择的图表数据库,您可以选择标注、给出方向以及向边添加其他信息属性。例如,如果我们考虑三重 用户—:联系人—>代理人 ,我们可以在关系 联系人 *中构建许多属性和标签。*我们可以订阅一个逆关系, 接收联系人,还可以分配标签,比如日期、主题、交流方式等。如果您停下来考虑如何在关系数据库中实现这一点,您会发现创建这种结构会变得多么困难。

标记边的示例

使用图形数据库的好处

让我们深入了解这种不同的数据管理方式如何影响数据的生命周期。

查询速度更快

就像关系数据库依赖 SQL 语言来检索数据一样,图数据库也有自己专门的查询语言。 Neo4J ,领先的图形数据库工具之一,使用一种叫做 Cypher 的语言。

使用图形数据库查询数据的一个好处可以在下面的例子中很容易地看到。考虑这样一个分析师,他想找到与居住在纽约市的政府代理有联系的所有用户。在关系数据库中,这个简单的查询可能会变得非常复杂,无论是在时间上还是在查询复杂度上。该查询将包括跨多个连接执行多个 select 语句,这取决于与该搜索相关的数据存储在多少个表中。

另一方面,在图形数据库中,这将涉及搜索居住在纽约地区的分析师,然后沿着用户和政府代理之间的路径反向遍历图形,以收集用户的信息。两次搜索的时间复杂度相差很大,当您处理数 Pb 的数据时,这一点不可轻视。

其他图形数据库优势:

让我们考虑一下使用图形数据库比关系数据库更大的优势:

  • 同时更新和查询数据— 图形数据库提供了实时更新数据的独特能力,同时允许同时对数据进行查询(即使是 Hadoop HDFS 等大数据流领域的大公司也很难提供这样的服务)。
  • 动态模式— 与关系数据库不同,关系数据库要求数据符合在表开始时分配的一组模式,图形数据库允许您在数据生命周期的任何时间点添加或删除节点和边。
  • 整合 AI / ML 模型 —图形数据库从数据中提供丰富且可访问的信息,这些信息为 AI 模型增加了深度和意义,而这些从关系数据库中根本无法获得。⁴

图形数据库的缺点

当然,没有一种技术是没有缺陷的,所以让我们来探讨一下使用图形数据库的一些潜在缺点。

  • 教育的好时机— 尽管图形数据库自 21 世纪初以来越来越受欢迎,但仍然只有一小部分技术人员能够熟练使用这一工具,更不用说是这方面的专家了。当一个公司决定迁移到图形数据库时,他们也决定在培训成本上投入大量的资源。
  • 数据的丰富程度取决于您自己— 简单地将 RDBMS 数据迁移到图形数据库不会神奇地使其成为更丰富的数据集。数据工程师需要构建一个新的模式,通常是从头开始,并对数据进行逆向处理以适应这种新模式。这同样需要大量的时间和资源。我曾在几家公司工作过,我所在的团队致力于将数据从关系数据库迁移到图形数据库,每家公司都分配了至少 1 年的时间来完成这个项目。

对公共部门数据的影响

公共部门与私营部门的数据管理和分析有许多重叠的需求,两者都旨在降低成本,同时提高运营效率,并从其数据讲述的故事中增加业务价值。虽然政府没有将利润商业化的迫切要求,但他们面临着使其数据和信息流程私有、透明和可信的巨大要求。政府组织使用数据分析来实现两个崇高的目标,一是保护和维护政府对公民安全和福祉的监管,二是为政府雇员和公民提供提高生活质量和优化流程的服务。由于有大量的数据需要筛选,这两个问题的答案都存在于数据中的某个地方,在数据中找到现有的关系将加快这些结果的产生。

图形数据库的另一个巨大优势是删除冗余数据,仅这一项就可以在存储和数据标准化方面为组织节省无数的时间和金钱。图数据库不需要将 PK/FK 列存储在整个数据库的多个不同的表中,而是通过利用无索引邻接来消除这种需要,这听起来就像是这样:图不依靠索引键来链接数据片段,而是依靠边来建立连接。这使得数据管理员可以创建非常直观、视觉上非常简单的复杂图形模式。

政府用例

Neo4J 汇编了一个来自不同组织的用例列表,这些用例说明了如何使用他们的技术来增强科学家的工作流程。以下是一些特定于公共部门的组织:

美国陆军——供应链、物料清单和维护成本管理

美国陆军是我们武装力量中最大的分支,拥有超过 100 万名士兵和 20 万名文职人员,每个人都依赖于需要持续维护和更换的各种设备。传统上,陆军使用基于主机的系统来监控所有供应链管理,但很容易理解为什么这个过时的系统不太适合这个动态、庞大的数据集。

转换到图形数据库允许军队实现模型和查询:

  • 根据环境因素预测更换、维护和平均无故障时间
  • 执行多维成本比较和趋势分析
  • 对陆军的后勤和预算需求过程进行分析
  • 对围绕新战区部队部署的重要问题进行探索性数据分析

MITRE —打击和追踪网络安全威胁

Mitre 是一家由联邦政府资助的非营利性公司,利用图形技术来打击美国的网络攻击。有了如此多的可用数据,找到这些数据之间的联系最终会导致发现和阻止网络攻击所需的模式识别。MITRE 已经通过创建一个名为 CyGraph 的工具做到了这一点,该工具将绝望的数据融合到一个统一的画面中,暴露出漏洞和威胁。⁵

我如何利用图形技术达到

我的团队在 Attain 设计的持续智能平台

作为一家政府咨询公司的首席数据科学家,我一直在寻找改进数据管理的方法,以便在预测分析方面获得长期收益。我们与公司的其他技术领导者一起,致力于开发一个持续的智能平台,该平台整合了图形数据库,将主题专业知识和数据洞察融合为智慧。它最初的想法是帮助现场和桌面分析师自动化他们的数据分析,并建立复杂的模式识别和数据检索系统,以帮助打击对美国的威胁。通过利用尖端的 CICD 和 ML 微服务与我们的图形数据库,我们可以为政府节省无数的工时和美元,同时提供超出分析师自身能力的服务。

参考文献

  • (1):https://en.wikipedia.org/wiki/Graph_database
  • (2):https://neo4j.com/developer/graph-db-vs-rdbms/
  • (3):https://riskspan.com/graphs-for-data-management/
  • (4):https://dzone . com/articles/what-is-the-pros-and-consensus-of-using-a-graph-databa
  • (5):https://go . Neo4j . com/RS/710-RRC-335/images/Neo4j-Graphs-in-Government-white-paper . pdf?_ ga = 2.127300685.1592494695.1601320343-88543142.1601320343&_ GAC = 1.246995190.1601390652 . CJ 0 kcqwtsv 7 brcmarisanu-CQC l5 io-mjrlhmzeb 8 chmajiseekhbd 8 fjxdnkp-A

图形深度学习—第 1 部分

原文:https://towardsdatascience.com/graph-deep-learning-part-1-e9652e5c4681?source=collection_archive---------49-----------------------

FAU 讲座笔记关于深度学习

光谱卷积

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。 自己试试吧!如果您发现错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

图形深度学习正在成为学习模拟中的一项关键技术。使用 gifify 创建的图像。来源: YouTube 。

欢迎回到深度学习!所以今天,我们想研究一下如何处理图形,我们将讨论一下图形卷积。让我们看看我为你准备了什么。今天的主题是图形深度学习的介绍。

我们在说什么格拉夫? CC 下的图片来自深度学习讲座的 4.0 。

那么,什么是图形深度学习呢?你可以说这是一个图表,对吗?我们从数学中知道,我们可以绘制图表。但这不是我们今天要讨论的话题。你也可以说图表就像这样的图。但这些也不是我们今天要讲的情节。那是施特菲·格拉芙吗?不,我们也不是在谈论施特菲·格拉芙。所以我们实际上想看的是更多像这样的东西,比如可以用不同的节点和边连接起来的图。

图的定义。来自深度学习讲座的 CC BY 4.0 下的图片。

一个计算机科学家认为一个图是一组节点,它们通过边连接在一起。这就是我们今天要讨论的图表。对数学家来说,图是流形,但却是离散的。

欧几里得空间上的卷积。 CC 下的图片来自深度学习讲座的 4.0 。

现在,你如何定义卷积?在欧几里得空间,对计算机科学家和数学家来说,这太容易了。这是离散卷积,本质上是一个和。我们记得,当我们为卷积深度模型设置内核时,我们有许多这样的离散卷积。在连续形式中,它实际上有如下形式:它本质上是一个在整个空间上计算的积分,我在这里举了一个例子。因此,如果你想卷积两条高斯曲线,那么你实际上是把它们移动到彼此之上,在每一点上相乘,然后求和。当然,两个高斯函数的卷积也是高斯函数,所以这也很容易。

图形卷积怎么样?来自深度学习讲座的 4.0CC 下的图片。

你如何定义图上的卷积?现在,计算机科学家非常努力地思考,但是…管它呢!数学家知道,我们可以用拉普拉斯变换来描述卷积,因此我们研究拉普拉斯算子,这里给出的是梯度的散度。所以在数学上,我们可以更轻松地处理这些事情。

走向图形卷积的步骤。 CC 下的图片来自深度学习讲座的 4.0 。

这就把我们带到了这个多方面的观点。我们知道如何卷积流形,我们可以离散卷积,这意味着我们知道如何卷积图形。

图形卷积的一个例子是热扩散。来自深度学习讲座的 CC BY 4.0 下的图片。

所以,还是散点热吧!我们知道,我们可以将牛顿冷却定律描述为以下方程。我们还知道,随时间的发展可以用拉普拉斯来描述。所以,f(x,t)是时间 t 点 x 的热量,然后,你需要有一个初始的热量分布。所以,你需要知道热在初始状态下是怎样的。然后,您可以使用拉普拉斯算子来表示系统如何随时间变化。这里可以看到,这本质上是 f(x)和 f 在 x 周围的无限小数小球上的平均值之差。

怎样才能得到一个离散的拉普拉斯? CC 下的图片来自深度学习讲座的 4.0 。

现在,我们如何以离散形式表达拉普拉斯算子?这就是 f(x)和 f 在 x 周围无穷小的球上的平均值的差,所以,我们能做的最小的一步就是把当前节点和它的邻居连接起来。因此,我们可以将拉普拉斯表示为边权重 a 下标 I 和 j 的加权和,这是我们的中心节点 f 下标 I 减去 f 下标 j 的差,我们用实际传入 f 下标 I 的连接数来除,这将作为 d 下标 I 给出。

计算图的拉普拉斯算子的简单步骤。 CC 下的图片来自深度学习讲座的 4.0 。

现在有没有另一种表达方式?嗯,是的。我们可以这样做,如果我们在这里看一个例子图。因此,我们有节点 1、2、3、4、5 和 6。我们现在可以使用矩阵 D 计算拉普拉斯矩阵。 D 现在仅仅是各个节点的输入连接数。我们可以看到,节点 1 有两个传入连接,节点 2 有三个,节点 3 有两个,节点 4 有三个,节点 5 也有三个,节点 6 只有一个传入连接。我们还需要矩阵 A 。那是邻接矩阵。这里,每个节点都有一个 1,它与不同的节点相连,你可以看到它可以用上面的矩阵来表示。我们可以取这两个并计算拉普拉斯算子为 D 减去 A 。我们简单地按元素减去这两个来得到我们的拉普拉斯矩阵。这很好。

即使对于有向图,也可以得到对称的拉普拉斯算子。来自深度学习讲座的 4.0CC 下的图片。

我们可以看到拉普拉斯是一个 N 乘 N 的矩阵,它描述了一个由 N 个节点组成的图或子图。 D 也是一个 N 乘 N 矩阵,它被称为度矩阵,描述了连接到每个节点的边的数量。 A 也是一个 N 乘 N 矩阵,它是描述图的连通性的邻接矩阵。所以对于一个有向图,我们的图拉普拉斯矩阵不是对称正定的。所以,为了得到对称的版本,我们需要把它标准化。这可以通过以下方式来实现:我们从原始的拉普拉斯矩阵开始。我们知道 D 只是一个对角矩阵。因此,我们可以计算平方根倒数,并从左侧和右侧将其相乘。然后,我们可以插入原来的定义,你会发现我们可以稍微重新排列一下。然后我们可以把对称化的版本写成单位矩阵减去 D 。这里,我们再一次在元素上应用相同矩阵的逆矩阵和平方根乘以。这很有趣,对吧?即使对于有向图,我们也总能得到这个矩阵的对称化版本。

拉普拉斯算子的特征向量和特征值决定了它的傅立叶变换。 CC 下的图片来自深度学习讲座的 4.0 。

现在,我们感兴趣的是如何实际使用它。我们可以做一些魔术,现在的魔术是,如果我们的矩阵是对称正定的,那么矩阵可以分解为特征向量和特征值。这里我们看到所有的特征向量都集合在 U 中,特征值在这个对角矩阵λ上。现在,这些特征向量被称为图形傅立叶模式。特征值被称为频谱频率。这意味着我们可以使用 UU 转置来对图形进行傅里叶变换,我们的λ是光谱滤波器系数。因此,我们可以将一个图形转换成一个光谱表示,并观察它的光谱特性。

我们去傅立叶空间。 CC 下的图片来自深度学习讲座的 4.0 。

让我们继续我们的矩阵。现在,让 x 是某个信号,每个节点的标量。然后,我们可以使用拉普拉斯的特征向量来定义其傅立叶变换。这便是简单的 x hat 和 x hat 可以表示为 U 转置次数 x 。当然,你也可以把这个倒过来。这可以简单地通过应用 U 来完成。因此,我们也可以为描述节点属性的任何系数集找到各自的谱表示。现在,我们也可以在谱域中用滤波器来描述卷积。因此,我们使用傅里叶表示来表示卷积,因此我们将 g 和 x 带入傅里叶域,将两者相乘并计算傅里叶逆变换。从信号处理中我们知道,我们也可以在传统信号中做到这一点。

我们可以使用多项式进行过滤。来自深度学习讲座的 4.0CC 下的图片。

现在,让我们构建一个过滤器。该滤波器由系数为 θ 下标 I 的拉普拉斯 k 阶多项式组成,它们只是实数。所以,我们现在可以找到这种多项式,它是关于谱系数的多项式,并且在系数 θ 中是线性的。这本质上只是多项式的和。现在,我们可以利用这个滤波器来执行卷积。我们必须像以前一样繁殖。我们有了信号,应用傅里叶变换,然后用多项式进行卷积,最后进行傅里叶逆变换。这就是我们将该滤波器应用于新信号的方式。现在呢?现在,我们可以使用拉普拉斯算子对 x 进行卷积,因为我们调整了滤波器系数 θ 。但是 U 其实真的很重。请记住,我们不能在这里使用快速傅立叶变换的技巧。所以,它总是一个完整的矩阵乘法,如果你想用这种格式来表达你的卷积,计算量可能会很大。但是如果我告诉你一个巧妙的多项式选择可以完全抵消掉 U 呢?

在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。

嗯,这就是我们下节课要讨论的关于深度学习的内容。非常感谢您的收听,下期视频再见。拜拜。

更多模拟例子。使用 gifify 创建的图像。来源: YouTube 。

如果你喜欢这篇文章,你可以在这里找到更多的文章,更多关于机器学习的教育材料,或者看看我们的深度学习讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中生成文字记录,试试自动博客。

谢谢

非常感谢 Michael Bronstein 对 2018 年小姐的精彩介绍,特别感谢 Florian Thamm 准备了这组幻灯片。

参考

[1]基普夫,托马斯和马克斯韦林。"图卷积网络的半监督分类."arXiv 预印本 arXiv:1609.02907 (2016)。
[2]汉密尔顿、威尔、之桃·英和朱尔·莱斯科维奇。"大型图上的归纳表示学习."神经信息处理系统进展。2017.
[3]沃尔泰林克、杰尔默·m、蒂姆·莱纳和伊万娜·伊什古姆。"用于心脏 CT 血管造影中冠状动脉分割的图形卷积网络."医学成像图形学习国际研讨会。施普林格,查姆,2019。
[4]吴,,等.图神经网络综述 arXiv 预印本 arXiv:1901.00596 (2019)。
【5】布朗斯坦、迈克尔等在 SIAM Tutorial Portland (2018)举办的讲座《图形和流形上的几何深度学习》

图像参考

[a]https://de . serlo . org/mathe/functionen/funktionsbegriff/funktionen-graphen/graph-function【b】【https://www.nwrfc.noaa.gov/snow/plot_SWE.php?id=AFSW1
【c】https://tennis Bei Olympia . WordPress . com/meilensteine/Steffi-graf/
【d】https://www.pinterest.de/pin/624381935818627852/
【e】https://www . ui heregif
【I】https://www . researchgate . net/publication/306293638/figure/fig 1/AS:396934507450372 @ 1471647969381/Example-of-centline-extracted-left-and-coronal-artery-tree-mesh-construction . png
【j】https://www . eurorad . org/sites/default/files/styles/stylesitok=hwX1sbCO

图形深度学习—第二部分

原文:https://towardsdatascience.com/graph-deep-learning-part-2-c6110d49e63c?source=collection_archive---------51-----------------------

FAU 讲座笔记关于深度学习

从光谱域到空间域

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。 自己试试吧!如果您发现错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

图形深度学习和物理模拟很好地结合在一起。使用 gifify 创建的图像。来源: YouTube 。

欢迎回到深度学习。所以今天,我们想继续讨论图的卷积。我们将研究第二部分,现在我们看看我们是否必须停留在这个谱域,或者我们是否也可以回到空间域。让我们看看我为你准备了什么。

通过正确选择多项式矩阵,U 消失。 CC 下的图片来自深度学习讲座的 4.0 。

记住,我们用这个多项式来定义谱域中的卷积。我们已经看到,通过计算拉普拉斯矩阵的特征向量,我们能够找到适当的傅立叶变换,然后给出图形配置的频谱表示。然后,我们可以在谱域中进行卷积,并将其转换回来。这有点昂贵,因为我们必须计算 U 。对于 **U,**我们必须对整个对称矩阵进行特征值分解。此外,我们已经看到,我们不能使用快速傅立叶变换的技巧,因为这不一定适用于我们的 U

那么,我们现在该如何选择我们的 k 和θ,才能摆脱 U ?那么,如果我们选择 k 等于 1,θ下标 0 到 2θ,θ下标 1 到-θ,我们得到下面的多项式。因此,我们仍然有这样的配置,我们有在傅立叶空间变换的 x ,乘以我们的多项式,表示为矩阵乘以这里的傅立叶逆变换。现在,让我们来看看 G 帽子的配置。 G hat 其实可以表示为 2 乘以θ乘以λ的 0 次方。记住λ是对角矩阵。所以,我们把每个元素的 0 次方化。这实际上是一个单位矩阵,我们减去θ乘以λ的 1 次方。嗯,这其实只是λ。然后,我们可以这样表示我们的完全矩阵 G hat。当然,我们可以从左侧和右侧拉我们的 U ,这给出了下面的表达式。现在,我们利用θ实际上是一个标量的性质。所以,我们可以把它拉到前面。0 次方的λ被抵消,因为这本质上是一个单位矩阵。右边项的λ依然存在,但我们也可以把θ拉出来。嗯,UU 转置正好抵消了。这又是一个单位矩阵,我们可以用我们定义的拉普拉斯对称图形。你可以看到我们刚刚找到了它,在我们的方程里。所以,我们也可以用这个来代替。你看现在 U 突然没了。因此,我们可以再次取出θ,剩下的就是,我们有两倍的单位矩阵减去图的拉普拉斯对称形式。如果我们现在插入与原始邻接矩阵和度矩阵相关的对称版本的定义,我们可以看到我们仍然可以插入这个定义。然后,其中一个单位矩阵抵消,我们最终得到单位加 D 的-0.5 次方乘以 A 乘以 D 的-0.5 次方。所以,记住 D 是对角矩阵。我们可以很容易地反转对角线上的元素,我们也可以对元素求平方根。所以,这完全没问题。这样我们就不会有 U 出现在这里。我们可以用图形拉普拉斯矩阵以这种非常好的方式来表达整个图形卷积。

走向空间域卷积的步骤。 CC 下的图片来自深度学习讲座的 4.0 。

现在让我们再分析一下这个术语。因此,我们可以在左侧看到这个等式,我们看到我们可以在谱域中进行卷积,我们可以将 G hat 构造为拉普拉斯滤波器的多项式。然后,我们可以看到,对于特定的选择,k 等于 1,θ下标 0 等于 2θ,θ下标 1 等于-θ。然后,这一项突然只依赖于标量值θ。通过所有这些技巧,我们摆脱了傅立叶变换 U 转置。因此,我们突然可以用这种简化的方式来表示图的卷积。

用 GCN 实现图的卷积。 CC 下的图片来自深度学习讲座的 4.0 。

这是基本的图形卷积运算,你可以在参考文献[1]中找到。你可以对标量值这样做,你使用你的度矩阵,并把它插入这里。你用你的邻接矩阵,把它插入这里。然后,你可以针对θ进行优化,以便找到卷积的权重。

还有直接的空间变体。来自深度学习讲座的 4.0CC 下的图片。

好吧,现在的问题是“真的有必要从谱域激发图形卷积吗?”答案是“不”。所以,我们也可以在空间上激发它。

绘制卷积图的简单方法。来自深度学习讲座的 4.0CC 下的图片。

好吧,我们来看下面这个概念。对数学家来说,图是流形,但却是离散的。我们可以离散流形,并使用拉普拉斯矩阵进行频谱卷积。这让我们想到了谱图卷积。但是作为一个计算机科学家,你可以把一个图解释为一组通过边连接的节点和顶点。我们现在需要定义如何通过它的邻居聚集一个顶点的信息。如果我们这样做,我们得到了空间图形卷积。

聚合器是空间图形卷积的关键。 CC 下的图片来自深度学习讲座的 4.0 。

这是怎么做到的呢?[2]中显示的一种方法是 GraphSAGE。在这里,我们本质上定义了一个感兴趣的顶点,并定义了邻居如何对感兴趣的顶点做出贡献。所以从技术上讲,我们在节点 v 和第 k 层使用特征向量来实现这一点。这可以描述为 h k 下标 v。因此,对于第零层,这包含输入。这只是您的图表的原始配置。然后,我们需要能够聚合,以便计算下一层。这是通过在前一层上的空间聚合函数来完成的。因此,您使用所有的邻居,并且通常您定义这个邻域,使得连接到所考虑的节点的每个节点都包括在这个邻域中。

GraphSAGE 算法。来自深度学习讲座的 4.0CC 下的图片。

这一行把我们带到了 GraphSAGE 算法。在这里,您从图表和输入特征开始。然后,您执行以下算法:您在 h 0 处初始化,只需输入图形配置。然后,迭代这些层。你迭代节点。对于每个节点,运行聚合函数,以某种方式计算所有邻居的汇总。然后,结果是一个特定维度的向量,然后你得到聚合向量和向量的当前配置,你把它们连接起来,然后乘以一个权重矩阵。这然后通过非线性运行。最后,你通过激活的数量来缩放。然后在所有层上迭代,最后,您得到输出 z ,这是您的图形卷积的结果。

GraphSAGE 的不同聚合器。 CC 下的图片来自深度学习讲座的 4.0 。

聚合器的概念是开发这种算法的关键,因为在每个节点中,你可能有不同数量的邻居。一个非常简单的聚合器会简单地计算平均值。当然,你也可以使用 GCN 聚集器,这样我们又回到了光谱表示。这样,可以建立空间域和光谱域之间的联系。此外,您可以使用一个池聚合器,然后使用,例如,最大池,或者您使用循环网络,如 LSTM 聚合器。

欢迎来到图形深度学习的世界。来自深度学习讲座的 CC BY 4.0 下的图片。

你已经看到有各种各样的聚合器。这也是为什么有这么多不同的图形深度学习方法的原因。你可以把它们细分成某些种类,因为有光谱的,有空间的,还有循环的。所以,这本质上是如何处理图形卷积神经网络的关键。那么,我们到底想做什么呢?你可以用这些算法中的一个,应用到一些网格上。当然,这也可以在非常复杂的网格上完成,我会在下面放几个参考文献,你可以看到什么样的应用可以完成。例如,您可以使用这些方法来处理关于冠状动脉的信息。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。

下次在深度学习中,只剩下几个话题了。我想向你们展示的一件事是,你如何将先前的知识嵌入到深层网络中。这也是一个非常好的想法,因为它允许我们将我们从理论和信号处理中了解的许多东西与我们的深度学习方法相融合。当然,我也有一些参考资料,如果你有时间,请通读一下。他们更详细地阐述了我们在这里提出的想法。我还会在这段视频的描述中加入一些图片参考。非常感谢大家的聆听,下节课再见。拜拜。

许多更重要的概念在这里被省略了。因此,请继续阅读下面的图形深度学习。使用 gifify 创建的图像。来源: YouTube 。

如果你喜欢这篇文章,你可以在这里找到更多的文章,在这里找到更多关于机器学习的教育材料,或者看看我们的深度 学习 讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube、Twitter、脸书、LinkedIn 或 T21。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中生成文字记录,试试自动博客。

谢谢

非常感谢迈克尔·布朗斯坦对 2018 小姐的精彩介绍!特别感谢 Florian Thamm 准备了这组幻灯片。

参考

[1]基普夫,托马斯和马克斯韦林。"图卷积网络的半监督分类."arXiv 预印本 arXiv:1609.02907 (2016)。
[2]汉密尔顿、威尔、之桃·英和朱尔·莱斯科维奇。"大型图上的归纳表示学习."神经信息处理系统进展。2017.
[3]沃尔泰林克、杰尔默·m、蒂姆·莱纳和伊万娜·伊什古姆。"用于心脏 CT 血管造影中冠状动脉分割的图形卷积网络."医学成像图形学习国际研讨会。施普林格,查姆,2019。
[4]吴,,等.图神经网络综述 arXiv 预印本 arXiv:1901.00596 (2019)。
【5】布朗斯坦、迈克尔等在 SIAM Tutorial Portland (2018)举办的讲座《图形和流形上的几何深度学习》

图像参考

[a]https://de . serlo . org/mathe/functionen/funktionsbegriff/funktionen-graphen/graph-function【b】【https://www.nwrfc.noaa.gov/snow/plot_SWE.php?id=AFSW1
【c】https://tennis Bei Olympia . WordPress . com/meilensteine/Steffi-graf/
【d】https://www.pinterest.de/pin/624381935818627852/
【e】https://www . ui heregif
【I】https://www . researchgate . net/publication/306293638/figure/fig 1/AS:396934507450372 @ 1471647969381/Example-of-centline-extracted-left-and-coronal-artery-tree-mesh-construction . png
【j】https://www . eurorad . org/sites/default/files/styles/stylesitok=hwX1sbCO

社交媒体的图形嵌入:如何描述和聚类数百万用户

原文:https://towardsdatascience.com/graph-embeddings-for-social-media-how-to-profile-and-cluster-millions-of-users-a34be8c216c3?source=collection_archive---------30-----------------------

实践教程,营销

还记得寻找合适的影响者所花费的时间吗?

在这篇文章中,我想介绍一下在社交媒体挖掘领域的一些发现,描述一个 Word2Vec 模型的实现,该模型用于索引整个用户群,提供一个工具来查找社区中的相似用户。

简介:

尽管许多不同的社交媒体平台已经提供了发现相似用户的方法,但这组功能主要是为最终用户构建的,这意味着目标是向他们展示他们想要看到的内容,而不是从商业角度来看实际上与他们相似的用户。

能够瞄准相似用户的算法被用于脸书广告等工具的背后,这使得广告商有可能瞄准与特定条件(如品牌、口味或其他人口统计数据)相似的用户。

作者图片

让我们从一个例子开始:我们有一组n用户关注一个特定的品牌/档案。这些用户中的每一个都可以像n用户一样关注。通常,在追随特定品牌的一组用户中,这些用户之间存在关系。一些用户跟随彼此是因为他们只是彼此认识,一些其他用户跟随特定用户是因为后者是“影响者”,相同用户群中的一些其他用户可能跟随非常知名的品牌。

拥有用户群的“映射”表示可以帮助企业回答不同的问题,其中包括:

  • 怎样才能找到类似xyz的影响者?
  • 用户xyz和用户zyx有多相似?
  • 我可以在没有任何关于用户的附加数据的情况下将我的用户群分组到特定的组中吗?
  • 我的社区中最有影响力的人是谁?

战略:

本研究的主要目标是创建一个品牌社区中每个用户的数字表示,可用数据包括用户名列表和每个用户关注的个人资料列表:

数据的图形表示。(图片由作者提供)

如果有可能用数字表示空间内的用户,也有可能计算用户之间的操作,例如计算相似性,发现社区中的聚类和趋势。

在思考如何应对这一挑战的阶段,我想到的主要想法是将每个用户视为不同的项目集,类似于何时在商店购物:我们有自己的购物篮(社交媒体档案),我们将这个篮子装满我们想要的东西;不同的购物者对他们的购物篮做同样的事情,因此分析这些数据可以帮助了解顾客之间的模式。

只需用社交媒体档案代替物品,神奇的事情就发生了……(图片由作者提供)

这类任务可以通过实现 apriori 这样的算法来完成。这类算法通常用于频繁项集挖掘,它不是一种机器学习方法,而是来自一组称为关联规则学习的算法。

这种方法的问题是,它不能度量实例之间的相似性,因为数据集中的每个实例都没有被转换成数学表示,而只是使用两个奇特的度量来表示:置信度和。

然而,apriori 的酷之处在于它提供了用图表表示关联规则的可能性,这对于评估和报告非常有用。

来源: KDNuggets

在那一刻,有必要后退一步,专注于最终目标:我需要找到一种方法,让我以数学的方式编码用户,保留他们之间的关系。

当回过头来从宏观层面分析这种情况时,我意识到这其中的主要问题是将用户名“转换”成“数字”,因此问题很清楚:哪种算法、模型或任何东西可以将文本转换成数字?

同时,我意识到已经有一个非常强大的工具叫做 Tensorflow 嵌入式投影仪。它允许将高维数据投影到三维空间中,并自动执行 PCA(减少维数)等操作,并计算向量之间的距离,因此它可以显示一个词与另一个词的相似程度。

Tensorflow 嵌入式投影仪的一个例子。(图片由作者提供)

实施:

主要想法是试图根据用户追随者数据训练一个 Word2Vec 模型,以测试该模型是否能够学习用户之间的关系。

Word2Vec 是一个神经网络,能够生成单词的密集表示。这种算法,更具体地说是一种无监督学习算法,试图基于单词的邻居来预测单词,因此,在这种情况下,该算法将基于用户来预测追随者。

Word2Vec 可以主要使用两种不同的策略进行训练:Skip-gram 和 CBOW。

CBOW 与 Skip-gram 的图形表示。(图片由作者提供)

在 CBOW 中,组合一组周围的单词(用户)来预测中间的单词(用户)。相反,Skip-gram 将单词(用户)放在中间来预测周围的上下文。

为了实际实现这一点,我选择使用 Amazon SageMaker 及其 Word2Vec 实现,名为 BlazingText

输入数据:

输入数据由一个简单的.txt文件组成,该文件为每个用户包含一个逗号分隔的特定用户正在关注的配置文件列表。输入数据的总大小包括大约 520 万个条目。

培训阶段:

训练在ml.c4.xlarge机器上进行,使用接近默认的超参数,此外,由于预算原因,没有进行超参数优化。

作者图片

由于选择了训练策略 skip-gram,所以训练进行了五个时期,使用 100 个用户的min_count来预测下一个时期(这是理解用户遵循哪种简档的合理数量。),对于每个输出向量,我选择了 100 维的大小。其余的超参数保持默认。有关可用超参数的完整列表,请参考官方文档。

培训阶段持续了大约 9 个小时。

评估:

理解评估该模型的正确方法超出了本文的范围,但是,出现了几个有趣的点:

一个用二维空间表示的单词向量的例子。(图片由作者提供)

  • 由于任务包括映射一个社区内的所有用户,没有这个应用程序的训练和测试集,矛盾的是,我在寻找一个完美的数据溢出。
  • 从推荐系统中借用一些知识,是否有可能以类似于测试推荐者的方式来测试这个系统:隐藏实例之间的一些关系,并检查推荐者是否仍然能够找到模糊的关系。
  • Word2Vec 模型确实考虑了单词出现的顺序。这在该任务中是无用的,这就是为什么指定了 100 的window_size,以便给模型一个预上下文来帮助预测下一个追随者。

一旦训练完成,我最终得到了一个巨大的.tar.gz模型,解压缩后有两个文件:vectors.txtvectorz.bin,它们完全兼容gensim提供的[keyedvectors](https://radimrehurek.com/gensim/models/keyedvectors.html) 格式。

使用gensim读取向量和 followers 一样容易,此外,我们可以使用most_similar方法对模型进行一些手动测试:

from gensim.models import KeyedVectorsword_vectors = KeyedVectors.load_word2vec_format(‘vectors.txt’, binary=False)

为了了解模型对实体间差异的理解有多精确,有多好,特别是当差异非常细微时,我决定选择 Zara 和 Louis Vuitton 这两个知名品牌。

Zara 是一家快时尚零售商,而路易威登(仍然)被认为是一家法国时装和奢侈品公司。

这里是它们中最常见的实体:

作者图片

从上面的结果来看,该模型似乎能够区分一些奢侈品和 Fas 时尚品牌,返回实际上有意义的结果。

让我们尝试一些不同的东西,这一次,两位音乐家属于两个完全不同的流派,Lady Gaga 和 Solomun:

作者图片

令人惊讶的是,该模型还学习了不同音乐家的向量,能够为 Lady Gaga 返回不同的流行/商业艺术家,为 Solomun 返回更多的技术艺术家。

回到之前提到的有趣的图形可视化,现在也有可能做到这一点:模型为每个实体生成 100 维向量,为了在 2-D 空间上绘制它,有必要降低维度,实现这一点的一种方法是使用scikit-learn [TSNE](https://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html)类,该类将数据点之间的相似性转换为连接概率。另一种方式可以是计算一个 PCA 。

下图由使用TSNEmatplotlib可视化的 300 个最常见向量组成:

作者图片

很明显,存在一些数据聚类,这意味着该模型成功地学习了跨实体的相似性。例如,在左上角,我们可以看到一些零售品牌,而在右下角的名人和一些音乐人。

最后,我们还可以将计算出的向量和元数据导出为.tsv格式,使其对于前面提到的另一个工具来说是可读的:Tensroflow Embedding Projector。

这里的优点是,嵌入式投影仪可以计算不同类型的维度缩减,使用户有可能尝试一些算法。此外,将整个矢量和元数据从 Word2Vec 模型导出到嵌入的投影仪并加载这些文件也很简单。关于如何做的简单教程可以在这里找到。

下图显示了通过嵌入投影仪计算的三维 PCA,突出显示的单词表示与标有“chanelofficial”的点最近的点。

作者图片

另一个例子,使用“宝马”作为搜索查询和神话般的黑暗模式:

作者图片

可以看出在这两个例子中,搜索查询如何返回在上下文中有意义的值,此外,比较来自二维降维和由嵌入投影仪生成的三维的值,后者似乎不太“分类”和更具包容性,返回严格来说不属于同一类别的实体(例如 Zara 和 h&m)但对相似性的不同观点更开放(例如奔驰和劳力士)。

结论:

在本研究结束时,可以进行一些考虑:提供一个能够识别实体之间相似性的系统的最初目标似乎已经实现,但是,一个事物与另一个事物有多少相似性的想法仅仅是主观的或面向领域的,例如,同一领域中两个品牌之间的相似性可能会被在完全不同的领域中运营的其他品牌的存在所扭曲。类似于算术平均值如何误导样本中的许多异常值。

另一个需要考虑的问题是 Word2Vec 模型在这种情况下的使用方式:像本研究中这样对整个数据集进行矢量化有助于索引数据集中的实例,这意味着新实体(也称为词汇外标记)可以进行矢量化定位,并且只有在重复整个训练过程的情况下才能进行定位。

出于这些原因,我认为这个工具更像一个索引器,有助于品牌在用户群中发现相似的实例。一个例子是,当在社区中寻找有影响的人时,品牌经理可能有一个想法或认识一些用户,这可能是好的,但是,像这样的工具可以帮助经理在他们的社区中找到其他类似的用户,由于这种算法,这些用户已经被索引。

**I have a newsletter 📩.** Every week I’ll send you a brief findings of articles, links, tutorials, and cool things that caught my attention. If tis sounds cool to you subscribe. *That means* ***a lot*** *for me.*

[## 5-bullet 数据科学与技术📡

编辑描述

无情-创造者-2481.ck.page](https://relentless-creator-2481.ck.page/68d9def351)

图拉普拉斯算子及其在机器学习中的应用

原文:https://towardsdatascience.com/graph-laplacian-and-its-application-in-machine-learning-7d9aab021d16?source=collection_archive---------18-----------------------

图拉普拉斯在谱聚类中的应用

由 Unsplash 上的 Pietro Jeng 拍摄

本文重点介绍了图形、其表示的属性及其在机器学习中执行谱聚类的应用。

介绍

图是一种数据结构,其中的节点通过有向或无向的边相互连接。例如,对于以城市为节点表示城市道路网络的图,边可以具有表示两个城市之间距离的权重。

内容

  • 加载数据
  • 根据特征构建图形
  • 导出它的拉普拉斯表示
  • 探索图拉普拉斯的性质
  • 机器学习中的应用—谱聚类

加载数据

我们将从 python 库 scikit-learn 中的玩具 make_moons 数据集开始。

import numpy as np
from scipy import sparsefrom sklearn.datasets import make_moons
from sklearn.neighbors import kneighbors_graph
from sklearn.cluster import KMeans
from sklearn.metrics import homogeneity_score, completeness_score,v_measure_scoreimport networkx as nx
import matplotlib.pyplot as pltrandom_state = 213
np.random.seed(random_state)data_size = 150features,y = make_moons(n_samples=data_size, noise=0.07, random_state=213)

具有两个聚类的数据集

构建 K-最近邻图

k-最近邻图可以以两种模式构建——“距离”或“连通性”。

在“距离”模式下,边代表两个节点之间的距离,而在“连通性”模式下,图的边权重为 1 或 0,表示两个节点之间是否存在边。我们将选择欧几里德距离度量来计算距离。

n_neighbors = 10
knn_dist_graph = kneighbors_graph(X=features,n_neighbors=n_neighbors,mode='distance',metric='euclidean',n_jobs=6)

它返回一个稀疏图,图中的边表示数据点之间的距离。第一个数据点与其最近的 10 个邻居之间的距离如下所示。注意图的稀疏性,并且它将仅在矩阵中对应于其 k 个最近邻居的那些位置/索引处具有代表距离的连续值,其余的将为零。

knn_dist_graph.todense()[0]

该数据通常用于在数据点中寻找组,其中相似的数据点位于相同的类或簇中。

类似地,在其他这种情况下,当您想要捕捉数据点内的相似性而不是距离时,我们可以使用宽度为(sigma = 1)的高斯核将该图转换为基于相似性,距离 d(x1,x2)是上面稀疏图中非零位置的欧几里德距离。

请注意,在上面的数组中,距离= 0 的位置意味着该距离超出了 k 个最近邻的最大距离。当输入高斯核时,该值可以解释为最高相似度。因此,我们将只把这个内核应用于包含距离的索引。

sigma = 1
similarity_graph = sparse.csr_matrix(knn_dist_graph.shape)
nonzeroindices = knn_dist_graph.nonzero()similarity_graph[nonzeroindices] = np.exp( -np.asarray(knn_dist_graph[nonzeroindices])**2 / 2.0 * sigma**2)similarity_graph = 0.5 * (similarity_graph + similarity_graph.T)
similarity_graph.todense()[0]

该图可能是不对称的,因为它是基于 k-最近邻的。我们需要使这个图对称,原因我们将在拉普拉斯的性质中了解。我们将它的图的转置加到它自身上,并将所有的值除以 2。

让我们看看这个图形可视化后的样子

使用 networkx 实现可视化

导出图的拉普拉斯表示法

L = D-W

度矩阵

w:相似图(用加权邻接矩阵表示)

我们将创建一个图的度矩阵,它是一个对角线矩阵,对角线上有节点度 d

degree_matrix = similarity_graph.sum(axis=1)
diagonal_matrix =         
np.diag(np.asarray(degree_matrix).reshape(data_size,))L =  diagonal_matrix - similarity_graph

注: 通过从度矩阵中减去相似度矩阵,图中的圈的影响被消除。最后,拉普拉斯算子包含对角线上的次数和矩阵其余部分中边权重的负值。

图的拉普拉斯性质

  1. 实对称

因为它是实的和对称的,所以它的特征值是实的,它的特征向量是正交的。

  1. 正半定

拉普拉斯算子具有至少一个等于 0 的特征值。我们可以通过它的二次型来检验这一点。l 是实对称的,并且如果 x 是 n×1 列向量,则它的二次型 Q 由下式给出

二次型是正半定的,如果-

  • Q≥0 为全部 x 而 Q = 0 为部分 x≠0

我们将 x 设为 1 的列向量。

x = np.ones(shape=(data_size,1))
Q = np.dot(np.dot(x.T, L.todense()), x)
Q.round(10)

任何包含相同值的列向量 x 将导致等于 0 的二次型。

  1. 拉普拉斯零特征值的个数等于图中连通分量的个数
# Finding eigen values and eigen vectors
e, evecs = np.linalg.eig(L.todense())
e.shape, evecs.shape# No. of eigen values equal to 0
e_rounded_off = e.round(5)
e_rounded_off[e_rounded_off == 0].shape# No. of connected components
nx.number_connected_components(nx_graph)

4。具有高边缘权重的两个相似数据点在所得特征向量** 中的相应索引处具有相似的值

这些特征向量之一是菲德勒向量——对应于最小非零特征值的特征向量。在下图中,数据点被符号很好地分开。

对应于最小非零特征值的特征向量图

图拉普拉斯算子的应用

通过扩展上述所有属性,以及本征向量将数据点分组的事实,本征向量被用于聚类。这种方法叫做谱聚类

这是通过选择阈值将数据点从第一个最小的特征向量分成 2 个集群来执行的。对于 2 个以上的聚类,我们可以使用 Kmeans 算法直接从第一个最小的 K 个特征向量中获得 K 个聚类。

特征值对数据指数作图

特征值(排序)相对于数据指数绘制

使用菲德勒矢量来划分数据点

图形分割 —在这种情况下,顶点被分割成分离的集合。该图被划分,使得组内的边具有高权重(聚类内的点是相似的),而组间的边具有小权重(不同聚类中的点彼此不相似)。

费德勒向量是对应于最小非零特征值的特征向量。低于 0 的值的索引被分配给聚类 1,其余值的索引被分配给聚类 2。

我们能够以这种方式使用这个向量,因为这个特征向量是指示向量的缩放版本。指示向量与矩阵的每个非零特征值相关联。每个指示符向量也是彼此正交的,并且理想地包含二进制值 0 或 1 来指示集群成员资格。

在这种情况下,我们使用带符号的连续值,而不是包含 0 和 1 的指示向量。

# Get smallest non-zero eigen value's index for obtaining partition to cluster
fiedler_index = sorted_indices[1] # The eigen vector for smallest non-zero eigen value i.e plotting the Fiedler vector plt.figure(figsize=(8,6))
plt.scatter(np.arange(data_size), evecs[:,fiedler_index].tolist())
plt.title("Eigen (Fiedler) vector plot")
plt.show()fiedler_vector = evecs[:,fiedler_index].copy() # Thresholding the values in this eigen vector at 0
fiedler_vector[fiedler_vector < 0.0] = 0
fiedler_vector[fiedler_vector > 0.0] = 1
new_labels = np.asarray(fiedler_vector)[:,0]# Plot cluster result
plt.scatter(features[:,0], features[:,1],         c=new_labels.astype(float))
plt.title("Clusters plot")
plt.show()

从谱聚类中获得的聚类

基于熵的外部聚类评价方法评价

同质性&完整性评分和 v-measure 根据基本事实评估聚类结果,并考虑类和聚类标签的分布,以测量所获得的聚类的一致性。每项措施的最高分为 1.0。对于上述过程,我们每个指标的得分为 1.0。

# Evaluation of clustering result of the above procedure
homogeneity_score(y, new_labels), completeness_score(y, new_labels), v_measure_score(y, new_labels)

与 Kmeans 的比较

num_clusters = 2
kmean_labels = KMeans(n_clusters=num_clusters, random_state=random_state, n_jobs=6).fit_predict(features)plt.scatter(features[:,0], features[:,1],                                                                           c=kmean_labels.astype(float))
plt.show()

从 KMeans 聚类中获得的聚类

# Evaluation of clustering result of KMeans
homogeneity_score(y, kmean_labels), completeness_score(y, kmean_labels), v_measure_score(y, kmean_labels)# Scores
# (0.1836464702880451, 0.1837407327840609, 0.18369358944333708)

假设存在球状星团,Kmeans 不能很好地区分这两个星团。

回顾拉普拉斯表示和求解特征值系统以获得聚类,一个问题是— 为什么是特征值系统?

这是因为特征值系统近似于图割。

对于 割(V1, ) 获得 2 个分区的 V1 & V2 表示为——

在上述方法中,特征值近似一个归一化图割 — NCut(V1,V2)

怎么会这样?

NCut 的上述方程可以重新表示为瑞利商,其最小值由一个广义特征值问题的最小特征值得到。设 x 为 N 维指示向量其中 xi =1,若图节点 i 在 V1,否则为 0,则 Ncut 的最小化表示为如下瑞利商

在满足其中一个条件的情况下,

其中 y 也像我们的指示向量 x 一样受到约束。

这样,图划分问题就转化成了聚类问题。

结论

我们从数据的特征开始,构建它的图和拉普拉斯算子,并使用它的谱嵌入(本征向量),我们找到最佳分割以获得聚类。谱理论是处理图表示的特征值和特征向量的概念的来源,也用于机器学习的其他领域,如图像分割、谱图卷积神经网络以及工业和研究社区中的许多其他领域。

本文旨在总结机器学习和线性代数中的概念和应用,并希望它也能引发探索和了解更多的好奇心。

希望有帮助。

请分享您的反馈,或者如果您在其他领域遇到这些概念的应用。

你可以在 GitHub 上找到代码。

[## taaniya/图形分析

github.com](https://github.com/Taaniya/graph-analytics/blob/master/Graph_Laplacian_and_Spectral_Clustering.ipynb)

参考

  • Ulrike von Luxburg,关于谱聚类的教程,2006 年。
  • 时剑波和吉滕德拉·马利克,标准化切割和图像分割,2000 年
  • 吉尔伯特·斯特朗教授,图中聚类,麻省理工学院开放式课程。
  • 二次型和正定矩阵

图形神经网络:综述

原文:https://towardsdatascience.com/graph-neural-networks-an-overview-dfd363b6ef87?source=collection_archive---------21-----------------------

图形神经网络导论

https://mapr.com/blog/driving-insights-network-graphs/

在过去的十年中,我们已经看到神经网络可以在图像和文本等结构化数据中表现得非常好。大多数流行的模型,如卷积网络、递归、自动编码器,对于具有表格格式(如矩阵或向量)的数据工作得非常好。

但是非结构化数据呢?图形数据呢?有没有一种模式可以向他们高效学习?大概你从题目就猜到了。答案是图形神经网络。

图形神经网络早在 2005 年就被引入(像所有其他好主意一样),但它们在最近 5 年才开始流行。gnn 能够模拟图中节点之间的关系,并生成其数字表示。

GNNs 的重要性非常显著,因为有如此多的真实世界数据可以用图形来表示。社交网络、化合物、地图、交通系统等等。

因此,让我们找出 GNNs 背后的基本原理以及它们工作的原因。

让我们首先定义我们的基本问题:我们想要将一个给定的图映射到一个标签,这个标签可以是一个数值、一个类或者其他任何东西。换句话说:

F(图)=嵌入

我们想找到函数 f,例如,想象每一个图是一个化合物或一个分子,标签是这个分子被用来生产某种药物的可能性。如果我们有办法从每张图中提取标签,我们基本上找到了一种方法来预测哪些分子更有可能用于药物。很酷,对吧?

我们该怎么做?我们已经知道了一种可以(在某种程度上)用于图形的神经网络。如果你考虑一下,递归神经网络可以在一种特殊类型的图上操作。链式图(基本上是一条线的图)。时间序列实际上是链式图,其中每个时间戳是一个节点,后面跟着下一个时间戳。

因此,事实上,我们可以建立一个网络,其中每个图节点都是一个循环单元(LSTM 或其他东西),节点的信息是一个嵌入,将通过链进行传输(像消息一样)。因为单元都是循环的,所以当嵌入穿过图时,信息不会丢失。这是我们熟悉的递归神经网络。与语言翻译和其他自然语言处理应用程序中使用的方法完全相同。

当然,我们可以将这个想法扩展到适当的图,我们得到这个:

图形神经网络:变异与应用

这张幻灯片摘自微软研究院关于 GNNs 的精彩演讲。让我们来看看这里发生了什么。

每个橙色三角形曾经是图形节点,现在被一个循环单元取代。包络表示将穿过图的节点的嵌入。每个图的边也被一个神经网络代替,以捕捉边的信息(它的权重)。

现在是学习的部分。在单个时间步骤中,每个节点从其所有邻居提取嵌入,计算它们的总和,并将它们与其嵌入一起传递给递归单元,这将产生新的嵌入。

这个新的嵌入包含节点的信息加上所有邻居的信息。在下一个时间步中,它还将包含其二阶邻居的信息。诸如此类。这个过程一直持续到每个节点都知道图中的所有其他节点。每个嵌入现在都有来自所有其他节点的信息。

最后一步是收集所有的嵌入并添加它们,这将为我们提供整个图的单个嵌入。

T3【https://tkipf.github.io/graph-convolutional-networks/】T5

就是这样。我们做到了。我们设法在一次嵌入中捕获整个图形。这种嵌入现在可以用在一些其他模型中,以执行一些分类、预测、聚类等操作。让你的想象力漫游。

如果你想试验图形神经网络,我会帮你搞定:

  • deepmind/graph_nets:在 Tensorflow 中构建图形网络
  • rusty 1s/py torch _ Geometric:py torch 的几何深度学习扩展库
  • 深度图库

我个人会选择第三种,因为它有更好的文档,但这是你的选择。

给你。鉴于 gnn 能够有效地建模图形结构,我猜测它们将在深度学习的未来发挥重要作用。通过将 GNN 加入他们的军械库,人工智能研究人员现在可以将一种全新类型的数据加入到他们的模型和架构中。老实说,天空才是极限。

太棒了。

如果你有兴趣阅读更多关于人工智能和机器学习的帖子,请不要不看我们的博客就离开

原载于 2020 年 2 月 1 日【https://theaisummer.com】

图形处理:一个没有明确胜利者的问题

原文:https://towardsdatascience.com/graph-processing-a-problem-with-no-clear-victor-3683c483f5dc?source=collection_archive---------46-----------------------

意见

你知道最流行的图形处理解决方案吗?没有吗?别担心。现在还没有。

由鲁伯特·布里顿在 Unsplash 上拍摄的照片

我们都依赖互联网来寻找技术问题的潜在解决方案。例如,对于大数据问题,在谷歌五分钟后,你会发现 Spark 可能会帮助你。即使你不知道什么是火花,你也会碰到这个名字。TensorFlow 在搜索深度学习解决方案时也会出现类似的情况,Kubernetes 用于云,Docker 用于容器… 似乎计算机科学中的每个流行词都有一个平台/框架/库。但是,尝试寻找一个图形处理解决方案。你会发现没有明确的胜利者。我觉得这很令人惊讶。

2015 年,我和我在 Inria 的同事发表了一篇文章,提出了一种中间件,可以激励开发人员提供一个通用框架来实现分布式图形处理解决方案。我们有一种强烈的感觉,没有一个一致的建议来加速大规模图形处理解决方案的开发。如果我们考虑到 Graph500 基准测试在使用图形时存在一些计算密集型问题,这就令人惊讶了。脸书和 Twitter 诞生后社交网络的爆炸吸引了研究界的注意,并提出了计算和可扩展性方面的新问题。此外,使用图形作为底层数据结构存在大量问题。图形用于欺诈检测、博弈论和大量与数据相关的问题。

有一个庞大的图库生态系统。仅举几个可用的我有经验的,我们有: GraphTool , SNAP , igraph , NetworkX , BGL , network for R 等。此外,我们还有其他更受欢迎的平台的扩展模块,如 Spark 的 GraphX、graphs 的 Hadoop 扩展、Neo4j,这是一个数据库,而不是库,尽管它可以用于图形操作。

然后,我们进入一个更模糊的世界,在某些方面声称是最有效的解决方案。研究机构和/或大学已经开展了大量的工作。然而,我不建议任何开发人员采用这些解决方案。纯粹。为什么?因为它们很难维护,没有记录,最终会消失。有一些臭名昭著的例子,如谷歌的 Pregel,它启发了 Apache Giraph,但从未公开发表过(如果我错了,请纠正我)。GraphLab 代码是可用的,慢慢消失,直到成为 Turi 的一部分。

如果您是一名开发人员,并且需要包括一些图形处理,请考虑以下几点:

  • 你想使用的编程语言可能会减少你的选择。
  • 您是在寻找特定的算法,还是想要探索和/或实现自己的解决方案?第一种方法在某种程度上简化了搜索,因为您可以寻找性能最佳的算法实现。如果你想做自己的探索,看看下一点。
  • 你的图表有多大?这是极其重要的。我上面提到的大多数库在处理数百万个顶点和边时都会有问题。如果你的图形不适合内存,那就更糟了。

不幸的是,在写这篇文章的时候,在图形处理解决方案的世界里,我们还没有一个明确的胜利者。公司使用的大多数解决方案都是从零开始量身定制的。开发人员一次又一次地编写相同的算法,导致了现有实现的混乱。我坚信有一个新的范例的空间(和需要),可以帮助开发人员建模分布式图算法,简化开发和可维护性,同时提高性能。类似于 TensorFlow 对神经网络所做的事情,通过抽象公共片段并将社区的努力集中到一个公共解决方案中。

感谢阅读。

图形编程

原文:https://towardsdatascience.com/graph-programming-d1c52fea5ce9?source=collection_archive---------29-----------------------

命令式编程的特点是迭代嵌套。一个函数嵌入了对其他函数的调用。我所说的嵌入是指这些调用在函数体中,因此函数和它的组成部分之间有紧密的耦合。这有许多缺点,通常通过函数组合来解决。

构图就像把两个东西连在一起。没有一个事物是在另一个事物之上的、嵌入的或优越的,它们只是相互补充。因此,所涉及的功能彼此之间是不相干的,这很好,因为你可以混合和匹配,分别测试和调试它们。

大多数组合实用程序或库会生成一个新的函数或对象,表示其组成部分的组合,但不再可能引用这些组成部分。你得到了一个新的不可穿透的盒子(再次嵌套)。

在典型的构图中,你可以继续在这个盒子里或盒子外构图,只要构图是在边上完成的,而不是单个的成分。然而,如果你有非一元函数,你需要开始使用 currying,事情可能会变得复杂。

作为人类,我们不会这样思考或说话,我们可以任意引用概念,以非一元的方式自由写作。

这项工作提出了图编程的概念,这是一种通过以非封闭方式连接函数对来构建函数图的编程方法,旨在取代典型的函数组合。

先决条件

我将使用 python 来说明我的例子。我也将使用函数式编程风格。

你应该熟悉compose_leftpipecurry才能跟上。

如果您不是,下面是前两者的可行实现:

def compose_left(*funcs):def composition(input):for f in funcs:input = f(input)return inputreturn compositiondef pipe(input, funcs*):return compose_left(*funcs)(input)

至于curry,由于它的实现有点复杂,您可以使用这个使用示例来了解它的功能:

@curry
def add(x, y):return x + y# I can give a single argument, getting back a function that
# expects the remaining argument.
add_5 = add(5)
add_5(7)  # Will give 12.

非线性程序

考虑以下情况,其中您有以下管道:

foo = compose_left(x_1, x_2, ..., x_n)

foo是一些函数的组合。太好了。

现在想象一下x_n得到两个参数而不是一个的情况。所以我们不能再单独使用这个组合,我们需要使用 currying 和一个额外的def,就像这样:

@curry
def x_n(arg1, arg2):...def make_foo(head_input, side_input):return pipe(head_input,x_1,x_2,...,x_n(side_input))

Currying 很棒,因为我们不需要复杂的x_n来表达它将在代码中的两个不同位置获得它的两个依赖项。side_input将作为arg2进入x_n

这里仍然有一些渗漏。我们不必要地将剩余的合成代码暴露给side_input。如果我有很多依赖项,并且我想在不同的时间给它们,这会变得非常混乱。

考虑这样的情况,其中x_n是两个独立管道的成员,每个管道给它不同的输入。

我们可以试着这样编程(这显然是行不通的):

def baz(arg1, arg2):...# incoming argument on position 2
foo = compose_left(x_1, x_2, ..., baz)# incoming argument on position 2
bar = compose_left(y_1, y_2, ..., baz)

调用foobar会给我们一个熟悉的例外,即baz期望两个参数,但只得到一个。

我们可以用一些命令式的风格来克服这个问题:

def everything(head_arg1, head_arg2):return baz(pipe(head_arg1, ...),pipe(head_arg2, ...),)

虽然这适用于简单的情况,但不适用于一般情况。如果我在不同的阶段连接了几个函数,那么我将不得不放弃组合符号,并以命令式风格结束,或者简单地拥有一个大函数,其中所有的东西都暴露给所有的东西。

复杂的依赖结构(作者图片)

想象一下,必须编写单个签名来支持上述结构。那就必须是d3d1p1d2的结合。函数体本身会全局暴露变量,理解依赖结构会非常困难。

作为人类,如何表达是很明显的。我们只是画出来。让我们回到上面这个简单的例子。

当你能画的时候不需要涂抹(作者的图片

我们也可以“编码”它,例如这是我用来生成上面图像的代码:

digraph G {x_1 -> x_2 -> bazy_1 -> y_z -> baz
}

所以我编程的时候应该也能做到。

编写者

“图”这个词本身就来源于素描或绘画,这才是真正正确的意义。我们希望能够画出程序,因为我们对它们的心理模型是非线性结构。

*编程这个词本身来自更早的希腊语“prographein”。我们其实都只是程序员。

https://github.com/hyroai/computation-graph用 python 实现了第一个图形编程框架。

它允许使用用普通 python 编写的纯函数,并显式声明它们的依赖关系,而不需要它们知道彼此。这类似于任何功能组合框架。除此之外,cg 还有其他一些技巧。

非线性合成

第一个技巧是将合成推广到非一元函数,将管道推广到有向无环图(Dag)。依赖不仅仅是“线”,所以我们应该能够,例如,将两条线连接成一个二元函数。我只需要说出我正在编写的关键字就可以完成这个例子。

一个例子:

everything = to_callable([*compose_left(x1, ..., x_n-1),*compose_left(x_n-1, baz, keyword="arg1"),*compose_left(y1, ..., y_n-1),*compose_left(y_n-1, baz, keyword="arg2"),
])...
# usage:
everything(input_to_x_chain, input_to_y_chain)

每个组合本质上都是边的集合,带有一些语法糖,允许您轻松地创建子结构。

记忆

纯函数和组合很容易处理。它们易于测试和推理,并且不会暴露在令人讨厌的状态中。但是现实仍然需要有记忆的程序,或者运行几次并保留一些上下文的程序,所以我们需要在纯函数中引入状态或记忆。流行的 UI 框架 React 已经使用钩子解决了这个问题(例如useState)。我们希望对我们使用的函数的纯度有更严格的要求,不要在函数中引入任何神奇的调用。换句话说,我们希望在函数的参数中完整地描述输入,并将输出完整地定义为函数的输出。

我们首先实现了一种特殊的节点,称为缩减器。reducer 返回两个元素,一个输出和它的内存,计算图框架将在下一次“转向”时在一个名为state(类似于 python 中的self)的特殊参数中为函数提供内存。

然后我们意识到,这种模式可以用更简单的方式实现,不需要任何特殊的关键字参数或构造。我们意识到记忆是对未来的依赖。这里的未来指的是下一次运行计算图。因此,我们改变了实现,使之具有我们称之为“未来边缘”的东西。未来边缘描述时间轴上的函数组合。所以一个函数可以被组合(即有一个边)到它自己或者其他函数上(甚至是它应该依赖的函数!),而没有真正产生循环。这是因为当前回合所需的值来自前一回合。

当我们引入这个概念时,我们讨论的不再是 Dag,而是一般的图,这些图可能有“圈”(只要这个圈至少有一条未来的边可以打破它)。

请注意,当我们引入内存时,整个计算图的签名变成了两个元素,其中一个是输出,另一个是状态,当我们再次运行它时,我们确保给它前一轮的状态。因此当缩小时,整个计算图具有缩减函数的特征。

记录

日志记录是编程中的一个经典问题。我们写一些代码来做一些事情,然后我们想观察它并记录它在做什么。作为例子,考虑流水线compose_left(x, y, z_1, ..., z_n)

并且说我们想看y的输出。所以我们可能会这样做:

def y(some_input):...return output, log

但是唉,z_1期望得到y的输出。这意味着我们将不得不复杂化z_i来处理一对元素。我们想要避免它。对于图形编程来说,这很容易做到。简单地将y连接成两个面:

(*compose_left(x, y, z_1, ..., z_n),*compose_left(y, logger),*compose_left(logger, final_output, key="log"),*compose_left(z_n, final_output, key="real_output"),
)

异步编程

python 中的 Async 真的很难搞对。同步函数不能调用异步函数,所以至少可以说混合使用这两种函数是很重要的。此外,你必须仔细选择何时在两行中使用await,以及何时使用类似asyncio.gather的东西。但是这个信息,什么需要首先发生,已经在你的程序中了。比如下面这个例子效率不高。

async def my_async_program():x = await async_f()y = await async_g()return sync_h(x=x, y=y)

这是因为我们可以将x上的awaity并行。但是为什么我们作为人类应该注意到它,而不是去推断它呢?

如果我们画出来,就很明显了。

(作者图片)

因此,计算图形库允许您混合异步和同步功能,甚至使用拓扑排序为您推断哪些功能可以并行运行。这将被写成如下。

(*compose_left(async_f, sync_h, key="x"),*compose_left(async_g, sync_h, key="y"),
)

含糊

另一个很酷的特性是,你实际上可以在一个函数中组合多个选项,使得图形有点像一个不确定的模型。这意味着输入可以来自任一边。为了使结果可预测,这些边具有优先级,因此计算图将首先尝试优先级更高的边,并且只有当计算路径不成功(即引发特定异常)时,图运行器才会尝试不同的路径。

(make_edge(f1, g, key="some_kwarg", priority=0),make_edge(f2, g, key="some_kwarg", priority=1),
)

在上面的代码中,g可能从f1获得输入,或者如果不成功,从f2获得输入。注意,我们在这里使用较低级别的 API,但这与compose_left非常相似。

TODO:循环

计算图尚不支持循环。当需要时,它们也可能被实现为一个特殊的边缘。这仍处于早期规划阶段,欢迎对此(或 PRs)提出意见。

小注意:计算图和单子

上面讨论的一些问题传统上是由函数式编程语言中的单子解决的。因为我自己没有使用单子的经验,所以我选择让读者来决定图形编程和单子之间的关系,以后可能会再次讨论这一部分。

图形查询搜索(第 3 部分)

原文:https://towardsdatascience.com/graph-query-searches-part-3-a8bff845c3f1?source=collection_archive---------53-----------------------

使用 TigerGragh 云编写 GSQL 查询

安德鲁·尼尔在 Unsplash 上拍照

议程

  1. 在图表中建模发布数据
  2. 什么是图形查询
  3. 编写图形查询
  4. 结论

1.在图表中建模发布数据

这是探索数据提取和建模系列文章的第 3 部分。如果到目前为止您已经了解了这个系列,欢迎回来!。如果你是新来的,我会简单介绍一下我们到目前为止所做的工作。在第一部分中,我们探索了在与新冠肺炎相关的生物医学文献上使用自然语言处理和实体抽取。在第 2 部分的中,我们学习了如何使用 TigerGraph Cloud 获取数据并建模。查看这些文章,深入了解我们到目前为止所做的一切。

现在,在第 3 部分中,我们将研究如何编写图形搜索查询来轻松分析图形中的数据。你需要一个完整的图形来编写查询。你可以按照第二部分中的步骤从头创建一个图,或者你可以将我们创建的图导入到 TigerGraph Cloud 中。该图表以及我们使用的所有数据可以在这里找到。

为了导入图表,按照这些步骤创建一个空白溶液。在您的解决方案主页上,单击导入现有解决方案

在主页上导入解决方案

不幸的是,您仍然需要手动映射和加载数据。但是,在议程项目 4 和 5 下的第 2 部分中,我将带您了解如何做到这一点。

2.什么是图查询?

在我们开始编写查询之前,我们可能应该了解它们是什么。图形查询本质上是搜索图形并执行某些操作的命令。查询可以用来查找某些顶点或边,进行计算,甚至更新图形。由于图形也有可视化表示,所有这些也可以通过 UI 来完成,如 TigerGraph Cloud 提供的 UI。但是,当处理大量数据或试图创建微调的图形搜索时,使用可视化界面是非常低效的。因此,我们可以编写查询来快速遍历一个图,并提取或插入我们想要的任何数据。

3.查询结构

GSQL 提供了许多不同的查询方法。我们将专注于搜索。图搜索的核心是一个叫做 SELECT 语句的东西。顾名思义,select 语句用于选择一组顶点或边。 SELECT 语句带有几个参数来缩小搜索范围。

来自子句的指定了你选择的边或顶点的类型。

WHERE 子句允许您声明顶点或边的特定条件。

ACCUMPOST-ACCUM 子句让您处理 累加器 ,它们是特殊的 GSQL 变量,在您搜索时收集信息(信息可以是数字、顶点集或边集等。).

子句,类似于 WHERE 子句,让你提供附加条件;但是,这些将在前面的条款之后应用。

通过 ORDER BY 子句,您可以根据某个属性值对聚集的边或顶点进行排序。

最后, LIMIT 子句限制了搜索结果的数量。

您可以在 TigerGraph 文档页面上找到所有这些细节,以及其他参数和查询方法。

3.编写图形查询

几乎任何你能想到的对图的搜索都可以用 SELECT 语句及其相应的子句来处理。为了证明这一事实,让我们练习编写一些查询。

以下所有的疑问都可以在我的 GitHub 页面找到。

这些查询按照从最简单到最复杂的顺序排列。

具有给定许可证的出版物

**目标:**找到属于给定许可类型的所有出版物。

代码:

CREATE QUERY LicensePub(String l) FOR GRAPH MyGraph {/* Finds all publications with a given license type   Sample Inputs: cc0, cc-by, green-oa, cc-by-nc, no-cc  */Seed = {LICENSE.*};Pubs = SELECT p FROM Seed:s-(PUB_HAS_LICENSE:e)-PUBLICATION:p WHERE s.id == l;PRINT Pubs[Pubs.id] AS Publications;
}

解释:我们来分解一下我们的代码在做什么。我们要选择连接到特定许可证顶点的所有发布顶点。因此,我们从所有的许可证顶点遍历到所有的发布顶点,条件是许可证 id 是我们指定的(即 cc0、no-cc 等)。).然后,我们只打印我们的结果。在我们的打印声明中有两件事需要注意。

  1. 如果我们简单地写PRINT Pubs,我们的输出将打印出版物及其所有相关数据(标题、摘要等)。因此,为了过滤输出数据,我们可以使用括号指定我们想要的属性。在我们的例子中,我们只通过写PRINT Pubs[Pubs.id]打印出 id。
  2. 用作语句纯粹是装饰性的,它只是改变了打印出的结果列表的名称。这在您提取要在其他上下文中使用的数据时很有用,但对于编写查询来说不是必需的。

现在,让我们保存并安装我们的代码。当我们运行它时,我们得到一个类似这样的输入框:

运行许可证查询后的界面

例如,我输入“cc0”作为许可证代码。当我单击“运行查询”时,我会看到如下所示的图像:

运行许可查询后产生的发布顶点

这显示了拥有我们指定的许可证的每个发布顶点。但是,这种观点相当混乱。我们可以点击左侧的 < … > 图标来查看 JSON 输出。JSON 输出应该是这样的。

许可证查询的 JSON 输出

这个看起来干净多了!我们还可以看到打印报表调整的效果。结果列表的名称是“Publications”,打印的唯一顶点属性是 id。

对于下面的查询,我将只显示 JSON 输出。

大多数出版物的作者

**目标:**找到发表文章次数最多的作者。

代码:

CREATE QUERY AuthorMostPubs() FOR GRAPH MyGraph {/* This query finds the author with the most publications   
Change the limit to see top 'x' authors */SumAccum<INT> @pubNum;Seed={AUTHOR.*};Author = SELECT a FROM Seed:a-()-:t ACCUM a.@pubNum +=1 ORDER BY a.@pubNum DESC LIMIT 1;  PRINT Author;
}

解释:我们从选择作者顶点开始。注意这里的 SELECT 语句看起来有所不同。这是因为我们没有指定边或目标顶点。因为我们知道作者顶点只连接到出版物顶点,所以我们可以使用这种“懒惰”语法来避免指定边名和目标顶点。

我们也第一次看到累加器(在这里参考文档)。在这种情况下,我们使用一个名为 pubNum 的本地累加器。一个局部累加器作为每个顶点的唯一变量,一个 SumAccum 是一种存储累加和的累加器。

那么这个累加器是怎么工作的呢?当我们从每个作者顶点遍历到其连接的出版物顶点时,我们添加到我们的累加器中。因此,在 ACCUM 子句中,累加器将连接数(也是发布数)作为变量存储在每个 AUTHOR 顶点中。

下一步使用的是 ORDER BY 子句。我们用它来按照累加器值的降序排列结果作者。因此,拥有最多出版物的作者将会在列表的顶端

最后,我们使用 LIMIT 子句将输出限制为 1 个作者(列表中的第一个作者)。

当我们运行该函数时,我们的输出如下所示:

作者查询的输出

注意作者 id 是“南”。这是出版物没有作者时使用的 id 。所以,我们可以看到 2437 篇文章没有列出作者。这是很好的信息,但不完全是我们想要的。若要查看更多结果,请更改限制。作为一个例子,我将把限制改为 5。

作者搜索的 JSON 输出,限制 5

现在我们可以看到出版最多的作者有 173 本出版物(哇,太多了!)

出版物最多的期刊

我们可以运行一个类似于作者搜索的查询,但是要搜索发表文章最多的期刊。

目标:找到发表文章最多的期刊

代码:

CREATE QUERY JournalMostPubs() FOR GRAPH MyGraph {/* This query finds the journal with the most publications     Change the limit to find the top 'x' journals  */SumAccum<INT> @pubNum;Seed = {PUBLICATION.*};Pubs = SELECT t FROM Seed:s-(PUB_HAS_JOURNAL) -:t          ACCUM t.@pubNum +=1 ORDER BY t.@pubNum DESC LIMIT 1;PRINT Pubs[Pubs.id, Pubs.@pubNum] AS Most_Published_Journal;
}

**解释:**代码本质上和以前一样,但是我们改为搜索期刊而不是作者。我们还使用前面描述的打印过滤器来使我们的输出更好。

日记帐查询的 JSON 输出

我们看到有 205 篇出版物的“Arch Virol”是我们搜索的顶级期刊。

对某一类类型引用最多的出版物

**目标:**给定一个类别类型,找出该类别中医学术语最多的出版物。

示例类别类型:DNA、疾病、癌症、有机体、分类单元。

完整的名单可以在这里找到。

代码:

CREATE QUERY ClassPub(String c, Int k) FOR GRAPH MyGraph{
/* This query finds the top articles related to a class     Sample Input: CANCER, 5 */SumAccum<INT> @entNum;Seed = {CLASS.*};Ents = SELECT e        FROM Seed:s-(ENTITY_HAS_CLASS)-ENTITY:e       WHERE s.id == c;Pubs = SELECT p FROM Ents:e -(PUB_HAS_ENTITY)-PUBLICATION:p       ACCUM p.@entNum += 1 ORDER BY p.@entNum DESC LIMIT k;PRINT Pubs[Pubs.id, Pubs.@entNum];}

解释:这是我们第一次看到两跳搜索。第一跳选择与给定类别类型相关的所有实体或关键字,第二跳查找包含这些实体的所有出版物,并对它们进行排名。作为一个例子,让我们给我们的查询分类为癌症,并选择顶部的 5 。我们的输出看起来像这样。

类搜索的 JSON 输出

我们现在可以看到哪些出版物对癌症的引用最多,以及每个出版物的引用数量。

类似出版物

**目标:**给定一篇论文,根据它们共享的关键词找到相似的论文。

我们将使用 Jaccard 相似度来确定两篇论文的相关程度。这种算法本质上是计算两篇论文在关键词总数上的共同关键词数。你可以在这里阅读更多关于算法的内容。你可以在 TigerGraph GitHub 上看到这个公式的一个例子,以及许多其他很酷的图形公式。

代码:

CREATE QUERY SimilarEnt(STRING doi, INT top) FOR GRAPH MyGraph {/* Use Jaccard Similarity to find top similar articles of a given article based on the key medical terms used   
Sample Input: 10.1186/1471-2164-7-117, 5 */SumAccum<INT> @intersection_size, @@set_sizeA, @set_sizeB;SumAccum<FLOAT> @similarity;VERTEX check;Seed = {PUBLICATION.*};Start = SELECT p FROM Seed:p WHERE p.id == doi ACCUM check = p,    @@set_sizeA+=p.outdegree("PUB_HAS_ENTITY");Subjects = SELECT t FROM Start:s-(PUB_HAS_ENTITY)-:t;Others = SELECT t FROM Subjects:s -(PUB_HAS_ENTITY) - :t WHERE t!= check ACCUM t.@intersection_size +=1,                  t.@set_sizeB = t.outdegree("PUB_HAS_ENTITY")                            POST-ACCUM t.@similarity = t.@intersection_size  *1.0/(@@set_sizeA+t.@set_sizeB- t.@intersection_size) ORDER BY t.@similarity DESC LIMIT top;PRINT Start[Start.id] AS SOURCE_PUBLICATION;  
PRINT Others[Others.@similarity] AS SIMILAR_PUBLICATIONS;
}

**解释:**我们首先创建 4 个累加器。每一个都代表 Jaccard 公式中使用的一个值。对于我们的第一个 SELECT 语句,我们选择与输入 doi 匹配的发布,并将连接到该顶点的所有边收集到一个累加器中。对于第二条语句,我们选择该发布中的所有实体。对于我们的第三个语句,我们找到了具有我们刚刚收集的任意数量的实体的所有出版物,并找到了交集大小(与原始论文相同的实体的数量)。最后,我们计算 Jaccard 索引,并将相似度最高的出版物排在输出列表的顶部。

让我们看一个例子。我用了doi= 10.1186/s 40413–016–0096–1 和 top =5。

相似性查询的 JSON 输出

我们可以看到我们的起始出版物以及前 5 个类似的出版物,每个出版物都有各自的相似性得分。

4.结论

如果你跟随这篇文章,我为你鼓掌!这份材料并不容易,学习一门像 GSQL 这样的新语言可能会很棘手。我希望这个 GSQL 查询的演练对您有所启发。我强烈推荐阅读我的其他论文,以获得我们今天所讨论的所有内容的更好的背景。如果您想了解更多的查询算法和结构,请查阅 GSQL 的 TigerGraph 文档。如果你正在寻找更多的内容,请继续关注!我将很快发布第 4 部分。在这个系列的最后一部分,我将介绍如何使用我们的图形数据库和查询来输出信息,我们可以使用 Plotly 的 UI 平台 Dash 来直观地表示这些信息。这样,如果您遵循了所有 4 个部分,您将完成一个完整的端到端应用程序!

如果你喜欢这篇文章,一定要看看我的其他文章,并关注我的更多内容!

资源

  1. https://towards data science . com/using-scispacy-for-named-entity-recognition-785389 e 7918d
  2. https://towards data science . com/linking-documents-in-a-semantic-graph-732 ab 511 a01e
  3. https://gofile.io/d/fyijVS
  4. https://www.youtube.com/watch?v=JARd9ULRP_I
  5. https://docs . tiger graph . com/dev/gsql-ref/query/accumulators
  6. https://docs . tiger graph . com/dev/gsql-ref/query/select-statement # select-statement-data-flow
  7. https://github.com/akash-kaul/GSQL-Query-Searches.git
  8. https://allenai.github.io/scispacy/
  9. https://github . com/tiger graph/gsql-graph-algorithms/blob/master/algorithms/schema-free/JAC card _ nbor _ AP _ JSON . gsql
  10. https://docs.tigergraph.com/
  11. https://plotly.com/dash/

图论|网格上的 BFS 最短路径问题

原文:https://towardsdatascience.com/graph-theory-bfs-shortest-path-problem-on-a-grid-1437d5cb4023?source=collection_archive---------14-----------------------

图论简化版

大家好,欢迎回到我关于图论的全新系列的另一个帖子,名为 图论:Go 英雄 。如果你打算开始学习或者想要快速复习,我毫无疑问地推荐完整系列。我们将看到如何使用 广度优先搜索 ( BFS )来解决最短路径问题。我之前已经在 BFS做过另一个帖子。所以,让我们深入研究一下。

我希望你知道什么是 广度优先搜索()以及它是如何工作的,因为我们会大量使用 BFS 的概念。

设置场景

图论中的许多问题可以用网格来表示,因为有趣的是网格是一种 隐式图的形式。 我们可以通过在网格内搜索来确定我们当前位置的邻居。在网格中寻找最短路径的一类问题是解决迷宫,如下所示。

作者照片

另一个例子是通过障碍物(如树木、河流、岩石等)到达一个位置。

网格上的图论

解决图问题的一种常见方法是首先将结构转换成一些表示格式,如邻接矩阵或列表。基本上,这些是存储图中邻域信息的数据结构。让我们来看一个更直观的版本。

假设我们有一个假想的图形。

作者照片

不,这不是图表。请看图 1,但这正是我要说的。假设图 1 中的每个单元格的左、右、下和上都有邻居。为了更清楚起见,单元格 0 有两个邻居,1 和 2。同样,小区 4 也有两个邻居 2 和 3。我们可以将这些单元格视为图中的顶点,其中 将是顶点的总数。图 2 是代表我们假想图的 邻接表 ,现在你可以把它和第一张图联系起来了吧?最后一张图描绘了同一图的 邻接矩阵 。邻接矩阵的每个单元(I,j)都用 1 填充,其中节点 I 和 j 之间有一条边。我们在这里只使用 1 和 0,因为我们没有关于从顶点 I 到 j 的开销的信息。如果我们有,我们也可以使用这些信息。*

一旦我们有了一个图的邻接表/矩阵表示,我们就可以在它上面运行多个图算法来解决不同的用例,比如找到最短路径和连接的组件。

地牢问题

这可能是我们在许多面试和编程竞赛中遇到的一个问题陈述,如下所示。

假设你被困在 2D 的地牢里,你必须找到最简单的出路。等等,我们也有一些障碍。地牢是由单位立方体组成的,里面可能会也可能不会填满石头。向东、向西、向南或向北移动只需要一分钟。你不能斜着走,因为迷宫里布满了坚硬的岩石。

作者照片

地下城的大小为 R x C,其中 R 是行数,C 是列数。我们必须从“S”室开始,在“E”室有出口。数字( # )符号描述了路线中的路障和时段()。)显示一条开放的路线。

作者照片

在给定的设置中,一个解决方案可以在上面的绿色路线中绘制。我们的方法是从单元格开始做 BFS,直到我们找到单元格的出口******

作者照片

如果您还记得,我们使用了一个队列来存储图形中稍后要访问的点。我们这里也用同样的。我们从单元格(0,0)开始,并将其添加到我们的队列中。一旦它被访问,我们将被访问单元的所有邻居添加到队列中。单元格(0,0)有两个邻居,(0,1)和(1,0)。随着我们的访问,队列变得越来越大,并不断地向队列中添加更多的邻居。当我们满足退出条件时,我们停止这个过程,即我们访问退出单元 E (4,3)。然后我们可以通过回溯重新生成从出口到起点的路径。

替代状态表示

到目前为止,我们一直使用单个队列来跟踪要访问的下一个节点,比如说一个 (i,j) 对。但是这不是最好的方法,因为它需要在队列中来回打包和解包。相反,让我们尝试另一种更好的方法,它可以很好地处理更高维的数据,并且具有更低的复杂度。

另一种方法是对每个维度使用单独的队列,因此在 3D 网格中,每个维度都有一个队列。

作者照片

一旦我们将一些潜在的信息放入队列,x、y 和 z 将进入各自的队列。同样,dequeue 一次检索一组 (x,y,z) 值。

伪代码解决地牢问题

**# Global variables, I intentionally leave the values as **...** because # I don't have any meaningful values yet. But it won't affect how
# you understand the problem, I promise.R, C = ...
m = ...
sr, sc = ...
rq, cq = ...# Variables used to keep track of total number of steps to be taken
move_count = 0
nodes_left_in_layer = 0
nodes_in_next_layer = 1# Variable to see whether we already reached at the end or not
reached_end = false# Matrix to keep track of visited cells.
visited = ...# North, South, East and West direction vectors
dr = [-1, +1, 0, 0]
dc = [0, 0, +1, -1]**

我们从初始化一些全局变量开始。 RC 分别代表地牢的行数和列数。变量 m 是大小为 R x C 的输入字符矩阵。我们在变量 srsc 中存储我们的 BFS 的起点的地方存储初始行和列值。我们使用两个单独的队列 rqcr 来存储要访问的下一个节点各自的行和列索引。此外,我们使用几个变量来跟踪到达终点的总步骤。nodes _ left _ in _ layer显示了在我们进行下一步操作之前有多少节点必须出列的计数,而nodes _ in _ next _ layer跟踪我们在 BFS 扩展中添加了多少节点,以便我们可以相应地更新nodes _ left _ in _ layer*****。*** 变量 到达 _ 结束 存储我们是否已经到达退出单元格 变量 访问过的 是一个大小为 R x C 的矩阵,用来标记访问过的单元格,因为我们不想再访问同一个单元格。变量 博士dc 需要一些解释,我会很快覆盖。****

作者照片

假设我们在 红色 单元格(I,j)。我们假设行索引只能在行之间移动,而列索引可以在列之间移动。因此,唯一可能的行操作是,要么我们可以通过从 I 中减去 1 来向北移动,要么通过将 I 加 1 到来向南移动。同样,通过对列索引加 1 或减 1,即 j ,我们被限制向东或向西移动。我们使用不同的方向值组合在地牢中移动,这就是为什么之前把它定义为变量。我想你明白了。**

我们还没有解决这个问题。我们只定义了几个重要的变量。核心思想即将问世。

**function solve():rq.enqueue(sr)cq.enqueue(sc)visited[sr][sc] = truewhile rq.size() > 0:r = rq.dequeue()c = cq.dequeue()if m[r][c] == 'E':reached_end = truebreakexplore_neighbors(r, c)nodes_left_in_layer --if nodes_left_in_layer == 0:nodes_left_in_layer = nodes_in_next_layernodes_in_next_layer = 0move_count ++if reached_end == true:return move_countreturn -1function explore_neighbors(r, c):for(i=0; i<4: i++):rr = r + dr[i]cc = c + dc[i]if rr < 0 or cc < 0:continueif rr >= R or cc >= C:continueif visited[r][c] == true:continueif m[r][c] == '#':continuerq.enqueue(rr)rc.enqueue(cc)visited[r][c] = truenodes_in_next_layer ++**

这里我定义了两个函数分别是 solve()explore_neighbors()。 我们从开始 BFS 过程的初始(I,j)位置开始排队,并将该单元标记为已访问。

然后,我们反复执行以下步骤,直到 rq 或 cq 变空。

  1. 将 rq 和 cq 中的每个元素出队。
  2. 我们检查当前位置是否是出口,如果是,我们退出循环。
  3. 如果当前位置不是出口点,那么我们必须通过调用explore _ neighbors()函数来探索它的邻居。
  4. explore _ neighbors()函数中,我们迭代地寻找所有可能的位置并检查几个条件。我认为条件是不言自明的。
  • 前两个条件检查我们是否在网格之外。这意味着,我们不能超过最小或最大的行数和列数。
  • 然后,我们检查当前位置之前是否已经被访问过。如果是真的,我们就不用再去参观了。
  • 此外,我们必须确保当前位置没有被阻止,所有被阻止的单元格都标有 #。

5.我们将当前单元格的值排队,并将其标记为已访问。(别忘了,我们是在explore _ neighbors()函数调用里面)。这里发生的事情就像,我们试着移动到所有可能的位置,比如北、东、南、西。然后我们迭代地探索它的邻居。就是这样。

6.最后我们更新nodes _ in _ next _ layer的值,离开*。***

我们将再次回到 solve() 函数。

7.我们更新了几个参数来记录到目前为止我们走了多少步。

8.一旦我们找到出口,我们就出去。

TADAAA!!!

整个想法和算法相对来说超级简单,即使伪代码看起来很吓人。

我们开始研究迷宫是如何工作的,以及如何将同样的问题移植到一个更科学的问题中。我们看到了如何使用网格和邻接表来表示问题。我们了解了什么是地牢问题,以及如何使用 BFS 解决它。我的想法是展示我们如何使用 BFS 来解决网格上的最短路径问题。差不多就这些了。

在下一个帖子中,我们将有一个 介绍树算法 。在那之前,再见。

图论|广度优先搜索

原文:https://towardsdatascience.com/graph-theory-breadth-first-search-d898e9f40fdd?source=collection_archive---------34-----------------------

简化的图论

欢迎大家回来。今天我们讨论的是广度优先搜索(BFS)——一种图探索算法。我们在之前的帖子中讨论了关于深度优先搜索。如果你不知道什么是图,或者想快速复习一下核心概念,我绝对推荐你看看我全新的关于图论的系列这里。

概观

广度优先搜索 或简称为 BFS 是我们用来探索图的边和顶点的基本算法,它在许多现实世界的应用中起着关键作用。它运行的复杂度为O(V+E)其中 O、V、E 分别对应 大 O顶点 。这种机制是许多应用程序的主要构件。我们可以通过实际遍历图的方式来区分 BFS 和 DFS。顾名思义,BFS 访问广度先于深度。这是把他们分开的基本事实。BFS 可以用于一个目的:在无向图中寻找最短路径*。*

基本 BFS

BFS 算法从某个任意节点开始,并在移动到下一个深度之前访问其所有邻居。简而言之,BFS 是分层工作的。

作者照片

如果我们从节点 1 开始 BFS,它将首先访问它的邻居,即 2、3 和 4。一旦我们完成了节点 1,我们最终会移动到下一个节点。在我们的例子中,节点 2、3 和 4 没有任何邻居,因此我们移动到下一个未访问的节点,即节点 6。节点 6 的直接邻居是 5、7 和 8。与前一个例子一样,节点 5 和 7 没有任何邻居,因此我们必须使用节点 8。游戏在这里发生了变化,节点 8 有两个邻居未被访问,所以我们访问它们并标记为已访问。这是一个非常基本的例子,但是相信我,这种图表只存在于纸上。

为了跟踪下一个要访问的节点,我们将顺序保存在一个队列中。我将用一个更复杂的例子来解释它,这样我们会对它有更好的理解。

作者照片

我们从节点 0 开始,将其添加到队列中,如下所示。

作者照片

现在,我们必须检查是否有任何邻居未被访问,是的。0 的直接邻居是 9、7 和 11。首先,我们将 0 标记为已访问,并将 0 的所有邻居添加到队列中。

作者照片

如上所示,队列中有三个新的未访问节点。下一个要访问的节点是 9。因此,我们将其标记为已访问,并将所有直接邻居添加到队列中,如下所示。

作者照片

下一个要访问的节点是 7,所以我们考虑到它,并将其所有邻居添加到队列中。节点 7 有三个邻居,即 3、6 和 11。如果我们看一下队列,11 已经在那里了,所以我们省略它,把其余的添加到队列中,如下所示。

作者照片

我们重复这个过程,直到队列中的所有元素都被访问。这是 BFS 的整体工作流程。

使用队列

BFS 算法使用队列来跟踪下一个要访问的节点。到达一个节点后,我们将所有邻居节点添加到同一个队列中,以便以后访问。

作者照片

队列数据结构的工作方式与真实世界的队列完全一样,对象被添加到队列的后面。首先进入队列的对象具有最高优先级。这意味着添加到队列中的第一个元素将得到服务,并首先离开队列。有两种与队列相关的基本操作,即在队列的后面插入一个元素和从前面移除一个元素,前者称为,后者称为*。***

伪码

*****#** global variables **n = number_of_nodes_in_the_graph
g = adjacency_list
visited = [false] * n
q = Queue()q.enqueue(initial node)while q is not empty{x = q.dequeue();if x is not visited:{visited[x] = trueneighbors = g[x] for y in neighbors:if y is not visited:  q.enqueue(y)}}*****

我们将节点总数保存在一个名为 n 的变量中。我们将有一个 邻接表——一个用于在内存中存储图形的结构——它包括每个节点及其对应的相邻连接。这是节点到边列表的映射。我们用一个 list visited 来检查一个特定的节点是否被访问过,它用 n 个 false 值初始化,因为我们还没有访问过任何节点。正如我们前面讨论的,我们使用队列 q 来跟踪要访问的节点。我们向队列中插入或 入队 一个任意节点,以启动 BFS 过程。我们移除或 出队 队列中存在的元素,我们必须确保当前节点尚未被访问。如果否,我们将当前节点的已访问状态更改为真。最后,我们将把所有直接邻居排入我们使用的队列。这个过程将被重复,直到队列变空,即当所有节点都被访问时。

BFS 还能做什么

  • 对等网络
  • 社交网站
  • 路径寻找
  • 碎片帐集
  • 网络广播

这是一个关于广度优先搜索的简介。希望大家觉得有帮助。

在下一篇文章中,我们会看到如何使用 BFS 从图中找到最短路径。谢谢你的时间和努力。

图论|树的中心

原文:https://towardsdatascience.com/graph-theory-center-of-a-tree-a64b63f9415d?source=collection_archive---------28-----------------------

图论简化版

欢迎大家回来。我们现在在这个叫做 图论:Go Hero 系列的第 9 个帖子。去看看以前文章的索引页。我尽量每个周末更新。让我们看看如何找到树的中心。

介绍

寻找树的中心是一个需要了解的简便算法,因为我们经常在其他算法的子例程中看到它,而且当我们 为树 求根时,这也是一个选择根节点的有用方法。

作者照片

要记住的一点是,树可以有一个以上的中心,但不能超过两个。

计算中心

请注意,中心始终是树中每条最长路径的中间顶点或中间两个顶点。

作者照片

例如,上图中橙色的路径是最长的路径,红色节点被认为是其中的中心。如果我们重复这个过程,选择另一条可能的长路径,中心将保持不变。

另一种寻找中心的方法是像剥洋葱一样反复挑选每个叶子节点。

照片由 C 在 Unsplash 上烘干

所以,我们从郊区开始,逐渐在中心结束。

作者照片

在我们的例子中,中间有一条水平线的节点是叶子。如果我们计算这些节点的

节点的度是它所连接的节点的数量。

肯定会是 1。因为所有这些叶节点都恰好连接到一个节点。当我们修剪树叶时,所有其他节点也会受到影响,即节点的度会开始降低。

作者照片

正如我们在上面的图像中看到的,我们的图形将开始反复松开它的叶子,直到我们找到它的中心。记住, 我们可能会找到一个或多个中心

伪码

现在让我们看一些伪代码。

function **treeCenters**(g):n = g.numberOfNodes()degree = [0] * nleaves = []for(i=0; i<n; i++):if degree[i] == 0 or degree[i] == 1:leaves.add(i)degree[i] = 0count = leaves.size()while count < n:new_leaves = []for node in leaves:for neighbor in g[node]:degree[neighbor] = degree[neighbor] - 1if degree[neighbor] == 1:new_leaves.add(neighbor)count += new_leaves.size()leaves = new_leaves

函数 的参数g***tree centers()***是一个无向图。变量 n 表示我们的树中节点的数量。我们定义了两个数组,degree 和 leaves。前者的大小为 n 并存储树中每个节点的度,后者保留最近一层的叶节点。然后我们进入一个循环,我们计算图中每个节点的度,我们也检查我们是否考虑一个单节点树或者它是一个叶子节点。如果这两个条件中的任何一个为真,我们将条目添加到 leaves 数组中,并将其在 degrees 数组中的值标记为 0——因为我们不必再次访问该节点。变量 count 将记录到目前为止我们已经处理的节点数。然后,我们不断地检查树叶并修剪它们。最后,我们会得到树的中心。

这很简单,对吧?

我们将在下一篇文章中讨论 识别同构树 。敬请期待。

图论|深度优先搜索

原文:https://towardsdatascience.com/graph-theory-depth-first-search-977c1ae386e1?source=collection_archive---------42-----------------------

图论简化版

这是我系列文章的第三篇,图论:Go 英雄。我强烈推荐查看以前帖子的索引。

在图论中,深度优先搜索 ( DFS )是一种重要的算法,在一些包含图的应用中起着至关重要的作用。

概观

DFS 是我们可以用来探索图的节点和边的最基本的算法。这是一种遍历算法。关于 DFS 的首要事实是它的工程简单性和可理解性。DFS 运行的时间复杂度为 O(V + E) ,其中 O 代表大 OV 代表顶点E 代表。不过,它的一致性可以用于其他不同的应用,如检测桥梁和关节点,计算连接的组件和估计连通性。

基本 DFS

顾名思义,DFS 算法访问 深度 ,而不管当前节点或边之后是哪个节点或边,如果我们到达了一个死胡同——从那里我们不能再前进——我们 回溯 到未被访问的节点,并递归地继续这个过程*,直到我们访问了所有可能的节点和边。我们必须确保我们的 不会再 访问同一个节点*。**

作者照片

对于给定的图形,有多种遍历选项可用。我在这里展示的是从节点 0 开始,然后像 1,2,3,…,9 这样继续下去。实际路径应该是 0-1-2-1-3-1-4-5-6-7-6-5-8-5-4-9。注意,我们再次回溯到几个节点,找出新的未访问路径。

伪码

**# global variables
**n = number_of_nodes_in_the_graph
g = adjacency_list
visited = [false] * n****function dfs(at):if visited[at]:returnvisited[at] = true** **neighbors = g[at]for node in neighbors:dfs(node)**# start DFS at node 0
**start_node = 0
dfs(start_node)**** 

我们开始定义图中节点的总数(【n】)。我们将有一个 邻接表——一个用于在内存中存储图形的结构——它包括每个节点及其对应的相邻连接。这是节点到边列表的映射。我们定义一个大小为 n 的列表来表示该节点是否已经被访问过。在初始化时,列表将包含所有的 值,因为我们还没有访问任何节点。当我们访问每个节点时,相应的位置就会被替换为 。已经定义了一个名为 dfs() 的函数,并在伪代码末尾调用了该函数。我们将第一个要访问的节点设置为 0。当函数 dfs() 被调用时,它检查该节点是否已经被访问过,如果没有,我们将用标志着成功访问的 true 替换此时为 false 的 visited[node]。然后,我们检索刚刚访问过的节点的邻居,并对每个邻居递归地调用 dfs() 函数。

连接的组件

让我们讨论一下 DFS 的一个主要用例,即在图中查找连接的组件。无向图的连通分量是节点的最大集合,使得每对节点通过路径连接。

作者照片

有时一个图可能被分成多个部分。连通分量形成了图顶点集合的一个 划分 ,意味着连通分量是非空的,它们是成对不相交的,并且连通分量的并集形成了所有顶点的集合。没有关联边的顶点也是一个独立的组件。从图中识别组件的一种方法是给它们着色。因此,每个组件都有与之相关的独特颜色。给组件着色对人类很有吸引力,但相关的问题是——如何给机器着色,例如计算机。在机器的情况下,我们可以用相似的 id(可能是一些整数)来标记组件的每个节点。就像配色方案一样,每个组件都拥有一个唯一的 id。

我们来看看上面描述的标注是怎么做的。为了方便起见,我从上面的图表中提取了一组组件,如下所示。

作者照片

首先,我们必须从 0n 对每个节点进行显式编号,其中 n 是节点的最大数量。其思想是在每个尚未访问的节点上启动 DFS,并将所有可到达的节点标记为同一组件的一部分。如果我们从节点 0 开始,它本身已经是一个组件,因为它没有传入或传出连接,我们用整数 1 标记它。现在,如果我们选择节点 6 作为下一个节点,我们按照 6 - 14 - 16 - 14 - 5 - 11 的顺序进行 DFS,并将该组件的所有节点标记为 2。我们对图中的每个其他组件重复相同的过程。最终的结果看起来会更加丰富多彩,如下图所示。

作者照片

伪码

**# global variables
**n = number_of_nodes_in_the_graph
g = adjacency_list
count = 0
component = []
visited = [false] * n****function find_components()for(i=0; i<n: i++):if !visited[i]:count ++dfs(i)return count****function dfs(at):visited[at] = truecomponent[at] = countfor next in g[at]:if !visited[next]:dfs(next)****

我们首先定义了一些全局变量来存储列表中节点的数量,邻接表,一个存储组件数量的计数器,一个跟踪组件标签的列表和一个查看节点是否已经被访问过的列表。

我定义了两个名为*find _ components()*dfs() 的函数。第一个函数循环遍历我们拥有的每个节点,并确保它被访问。如果没有,计数器将增加 1,以标记新组件的存在,并调用 dfs() 函数对组件进行深度优先搜索。

dfs() 函数采用一个参数,即每个节点的 id 作为自变量。函数 dfs() 做的第一件也是最重要的事情是,它标记当前访问的节点,并用计数器更新组件列表。计数器值表示组件的标签。同一组件中的所有节点将具有相同的标签。然后,该函数在邻接表中搜索任何可用的邻居,并递归调用相同的函数。

DFS 还能做什么

我们可以将 DFS 算法扩展到:

  • 计算最小生成树。
  • 检测和查找图中的循环。
  • 确定二分图。
  • 寻找强连接的组件。
  • 对节点进行排序。
  • 找到桥梁和关节点。

这就是深度优先搜索。当然,下一个是关于广度优先搜索的细节。我绝对应该感谢你的时间,感谢你的努力。

图论|树的介绍

原文:https://towardsdatascience.com/graph-theory-introduction-to-trees-a34ab267fc28?source=collection_archive---------45-----------------------

图论简化版

大家都怎么了?这是我的全新系列 图论的最新补充:Go Hero 在这里我们深入讨论图和相关算法。查看一下,快速浏览一下。这里我们将简单介绍一下树,它是一种图形。所以,我们开始吧。

什么是树

作者照片

我们上面有两张图表,你能找出不一样的吗?

正确,第四个脱颖而出。但是为什么呢?

作者照片

因为树是没有圈的无向图。要记住的关键是树里面不允许有循环。你能找到一个打破规则的,对吗?干得好。

然而,还有另一种简单的方法,我们可以用它来判断给定的图是否是树。所有的树都有 **N - 1 条边,**其中 N 是节点的数量。

作者照片

我们的图表中有三个符合规则,对吗?但最后一个没有。

野外的树木

让我们来看几个我们遇到树的应用的场合。

  • 文件结构

计算机文件系统包含目录、子目录和文件,它本质上是一棵树。

作者照片

  • 公司层级

公司层级是指公司内部根据权力、地位和工作职能对个人进行的安排和组织。它划分了权力和责任,根据员工、部门、分部和其他管理人员在层级中的位置指定他们的领导。一个完整的公司应该有一个树状结构。

  • 评估数学表达式

Tress 可用于将数学表达式和源代码分解成抽象格式,以便以正式的方式对它们进行评估。下面是一个表达式及其相应的树表示。

(a * b) + (c - d)

作者照片

  • Web 文档对象模型(DOM)

我们访问的每个网页都是由某些标签组成的,如、

等。DOM 是一种将 XML 或 HTML 文档视为树结构的接口,其中每个节点都是表示文档一部分的对象。下面给出了一个这样的树。

安东尼通过 pixabay 拍摄的照片

树木还有更多应用,

  • 决策树
  • 家谱
  • 分类学
  • 图论树
  • 文本分析树
  • 社会等级
  • 概率树

存储无向树

我们应该从给树中的每个节点分配编号开始,从 0n - 1 ,其中 n 是节点总数。

作者照片

存储这棵树最简单的方法是使用一个边列表,其中列表中的每一对表示两个节点之间的一条边。对于上面的树表示,相应的边列表将是,

[(0,2),(2,3),(2,4),(2,1),(1,5),(5,6),(5,7),(7,8)]

迭代边对非常快速和容易,但不会存储任何邻域信息。由于这个缺点,我们宁愿使用另一种叫做**邻接表的表示法。**这是一张从一个节点到其邻居的地图。上面给定的相同的树可以转换成如下的邻接表,

【0】→【2】

【1】→【2,5】

【2】→【0,1,3,4】

【3】→【2】

【4】→【2】

【5】→【1,6,7】

【6】→【5】

【7】→【5,8】

【8】→【7】

除了这两种方法,我们还有另外一个解决这个问题的方法。我们可以使用邻接矩阵来显示两个节点之间是否存在边。

作者照片

如果存在从节点 ijelse 0 的边,我们用 1 填充邻接矩阵的【T50(I,j)】单元。例如,如果在节点 5 和 7 之间存在边,那么(5,7)将是 1。

实际上,将树作为邻接矩阵很麻烦,因为大多数节点之间可能有边,也可能没有边,所以大多数单元会很稀疏,足以完全不占用内存。

有根的树

有根树会有一个特殊的节点被指定为根节点,因此命名为有根树。

图片 bu 作者

这里,橙色的节点被指定为根。任一边缘都可能靠近根部或远离根部。每棵有根的树都只有一个根。一些递归算法使用有根树来跟踪执行流程。

二叉树

我们永远不能离开这个会议没有提到二叉树。我们称之为二叉树或简称为 B 树是因为树中的每个节点总共最多有 2 个子节点。

作者照片

在现实世界中,B 树很少存在。

二叉查找树

我们称一棵树为二叉查找树当且仅当它满足 BST 不变量,BST 不变量定义为,对于每个节点 x,左子树中的值严格小于 x 的值,右子树中的值大于 x 的值。二叉查找树在搜索问题时非常有用。

作者照片

上面的实现禁止我们的树有重复的条目。所以树中的每个节点都会感知到一个独特的元素。

存储有根的树

作者照片

有根树最自然地以自顶向下的方式递归定义。实际上,我们总是维护一个指向根节点的指针,这样我们就可以访问树及其内容。此外,每个节点都可以访问其子节点。

作者照片

这里,橙色的节点是当前引用节点,所有绿色的节点是子节点。注意,子节点是叶子,它们没有任何特定的子节点。

如果我们的树是一棵二叉树,我们可以将它存储在一个扁平数组中。在这种表示中,每个节点都有一个基于它在树中的位置而分配的索引位置。

作者照片

我们从值为 9 的根节点开始,它存储在索引 0 中。接下来,我们有一个值为 8 的节点,它在索引 1 中,依此类推。如果你仔细观察数组,你可以看到一些位置用 null、 why 填充,因为我们在树中没有任何特定位置的值。根节点将总是在索引 0 中,并且相对于位置 I 访问当前节点 I 的子节点。

例如,假设我是当前节点的索引,那么

左侧节点: 2 * i + 1

右节点: 2 * i + 2

反过来,一个节点的父节点应该是,

楼层((i - 1)/2)

结论

今天我们发现了什么是树和它的不同种类。这篇文章的核心思想是让你了解数据结构和它在现实世界中的应用。我们将在本系列的下一篇文章中讨论更多的算法。在那之前,敬请期待。

图论|同构树

原文:https://towardsdatascience.com/graph-theory-isomorphic-trees-7d48aa577e46?source=collection_archive---------15-----------------------

图论简化版

大家好。这是我关于图论的博客系列的第十篇文章,名为 图论:英雄 。今天,我们将深入探讨树中的同构。我强烈建议你阅读我最近发表的关于图论的文章,这些文章更多的是从计算机科学的角度出发。所以,让我们开始吧。

定义同构

同态是一个非常普遍的概念,出现在数学的几个领域。这个词来源于 希腊语 iso ,意为“ 等于 ,”而 morphosis ,意为“ 形成 ”或“ 形成 ”它代表了两个相似系统之间的相互关系。维基百科 对它是什么以及它在数学中如何有用做了很好的解释。简而言之,它是两个对象之间的映射。例如,让我们举一个同构的例子。假设我们有两组数字。如果两个有限集有相同数量的元素,那么它们就是同构的。更详细地说,如果你能写下一个函数,将一个集合中的每个元素分配给另一个集合中的一个唯一元素,那么两个(现在不一定是有限的)集合是同构的,这样函数就不会“遗漏”任何一个集合中的元素。

图同构

问两个图 G1 和 G2 是否同构的问题是问它们是否结构相同。**

作者图片

我们可以看到上面的两张图。尽管图 G1 和 G2 的标签不同,可以被看作是不同的。但是,在结构上,它们是相同的图形。因此,反过来,存在一个同构,我们称之为图,同构图。如果我们打开第二个图,重新标记为相同的,我们将得到两个相似的图。

我们也可以用更严格的方式定义图同构的概念,因为说两个图在结构上是相同的并没有很好的定义。如果我们把一个图想象成顶点 V 和边 E 的集合,那么对于图 G1 和 G2,我们将分别有两个集合【G1(V1,E1)*** 和 G2(V2,E2) 。我们称这两个图同构,如果在 V1 和 V2 之间存在一个双射,使得对于 G1 中的所有对,通过对所有边的节点应用函数 φ (phi)形成有效边的顶点导致出现在 G2 中的边。通俗地说,***

为了发生同构,需要有一个函数φ,它可以将 G1 中的所有节点/边映射到 G2,反之亦然。

判定两个图是否同构,不仅人眼显而易见,对计算机来说也是一个难题。

作者图片

图同构问题是否为 NP 完全 还是一个未解决的问题。然而,许多多项式时间同构算法存在 fir 图子类,如树。

如果我让你找出同构的树,你能做到吗?是的,对吗?让我们试一试。

作者图片

如果你的答案是否定的,那你就对了。因为,它们在结构上是不一样的。

作者图片

这个怎么样?

答案是肯定的。因为存在一个标签映射

6 - 0

1 - 1

0 - 2

2 - 3

5 - 4

3 - 5

4 - 6

有几种非常快速的 概率性 (通常是 哈希启发式 基础)算法来识别同构树。这些方法往往很快,但也容易出错,因为在有限的整数空间中会发生哈希冲突。

我们今天要学习的方法涉及到 树序列化为 unicode 编码 。这种唯一的编码只是代表一棵树的唯一字符串,如果另一棵树有相同的编码,那么它们就是同构的。

我们可以直接序列化一个没有根的树,但是实际上序列化一个有根的树在代码上更容易。然而,如果我们要对两棵树 T1 和 T2 进行根化以检查它们是否同构,需要注意的一点是,在序列化/编码树之前,要确保在两棵树中选择相同的根节点。

我们可以用来帮助自己的一个技巧是在两棵树之间找到一个公共节点。找到树的中心也会做同样的事情。

编码树

首先,我们取两棵树 T1 和 T2,它们可能同构,也可能不同构。

作者图片

我们必须找到树的中心。

作者图片

我们要做的下一件事是给一棵树生根。

作者图片

现在我们必须为每棵树生成编码,并比较序列化的树是否相等。

作者图片

树编码只是一系列左'('和右')'括号。然而,我们也可以把它们看作 1 和 0。同样的上述编码可以转换成建议的方法,

作者图片

生成树编码

****【AHU】(AhoHopcroftUllman )算法是一种将树表示为唯一字符串的巧妙的序列化技术。与许多树同构不变量和启发法不同,AHU 能够捕捉树的 度谱 和结构的 完整历史 ,确保检查树同构的确定性方法。

让我们仔细看看。

作者图片

我们首先要给树的每个叶子节点分配一个空括号( () ),如下所示。

作者图片

现在我们必须向上移动(到叶子的父节点)并将叶子的括号组合在一起,并将其分配给父节点。当我们组合树叶的括号时,我们也应该将结果放在另一对括号中。例如,假设我们有一棵树,它有一个单亲和两片叶子。所以我们把()分配给树叶。当我们向父节点移动时,我们像()()一样将叶子的括号组合起来,并像(()())一样将其放在另一对括号中,并将其分配给父节点。这个过程不断重复,直到我们到达根节点。

作者图片

如果你仔细按照上面的类比,我们会在树的末尾有这样的编码。

不要忘记在组合括号之前对其进行排序。排序是按字典顺序进行的。

编码摘要

总结一下我们为 AUH 所做的:

  • 叶节点分配有()
  • 每当我们向上移动时,组合、排序并包装括号。
  • 在处理完一个节点的所有子节点之前,我们无法处理它。

如果两棵树的表示相同,那么这两棵树就是同构的。

抓住你了。我希望这篇简介能对你未来的项目有所帮助。感谢你的时间和耐心。谢谢你。

图论|为树生根

原文:https://towardsdatascience.com/graph-theory-rooting-a-tree-fb2287b09779?source=collection_archive---------51-----------------------

图论简化版

今天,我们要看看如何给一棵树扎根。这是我正在进行的系列 图论:围棋英雄 的第 8 个帖子。你一定要查看索引页面,深入研究图表和相关问题。我通常会在每个周末尝试这个系列的新帖子。我们来看看生根是怎么做的。

如果我们想处理有根的树,这是我们需要的最基本的转换之一。为一棵树生根的动机是,它通常可以帮助添加一个结构并简化问题。一棵有根的树可以把一棵无向树转换成一棵更容易操作的有向树。从概念上讲,给一棵树生根就像通过一个特定的节点捡起树,让所有的边都指向下。

作者照片

我们可以通过使用树的任何节点来确定树的根,但是,在选择节点时要小心,因为不是所有的节点都不能生成平衡的树。所以我们需要有所选择。

在某些情况下,拥有一条返回父节点的路由总是一个好主意,这样我们就可以往回走。我在下面用红线说明了到父节点的路由。

作者照片

让我们来看看如何给一棵树扎根。

生根溶液

用一个 深度优先搜索 ( DFS )很容易地完成一棵树的寻根。我已经创建了一个动画版本的结果 DFS 如下。你肯定会理解的,肯定。

作者创建的 GIF

简而言之,这就是扎根于一棵树。

伪码

class Treenode:int id;Treenode parent;Treenode [] children;function rootTree(g, rootId = 0):root = Treenode(rootId, null, [])return buildTree(g, root, null)function buildTree(g, node, parent):for child in g[node.id]:if parent != null and childId == parent.id:continuechild = Treenode(childId, node, [])node.children.add(child)buildTree(g, child, node)return node

我们定义了一个名为 *Treenode 的类。*树中的每个节点都有一个唯一的 id,这就是我们存储在 id 占位符中的内容。正如我们前面所讨论的,保存父节点始终是一个最佳实践,因为这将有助于我们返回。此外,我们保存了一些对当前节点的子节点的引用。

然后我们定义一个名为 rootTree 的函数,它接受两个参数——一个图和节点的 id。图 g 将被表示为具有无向边的邻接表。 rootTree 方法的第一行创建了一个 Treenode 对象,带有给定的 rootId 、父引用和子对象列表。 rootTree 函数调用另一个名为 buildTree 的函数,带有参数 graph g、根节点和对父节点的引用。

buildTree 方法采用我们刚刚谈到的三个参数。当我们进入函数时,我们最终会进入一个遍历当前节点所有子节点的 for 循环。我们知道边是无向的,所以我们绝对需要管理添加指向同一个节点的有向边的情况。如果不满足上述条件,我们确定我们手里有一个确诊的孩子。然后我们为 Treenode 类创建一个对象,并将该子节点添加到当前节点的子节点列表中。之后,它使用新创建的节点将 DFS 更多地放入树中。当我们访问节点的所有邻居时,我们返回当前节点。

所以,这就是我们如何扎根一棵树。我们将在接下来的帖子中讨论 树中心 。让我们一起继续学习。

干杯,全体。

Python 中探索性数据分析的图形化方法

原文:https://towardsdatascience.com/graphical-approach-to-exploratory-data-analysis-in-python-be4fa005a57f?source=collection_archive---------32-----------------------

调查新加坡、美国和中国的人口、教育和收入方面的性别平等

杰克·芬尼根在 Unsplash 上的照片

探索性数据分析(EDA)是每个数据科学或数据分析问题中最重要的方面之一。它让我们更好地理解我们的数据,并有可能揭示对我们来说不那么明显的隐藏见解。我在 Medium 上写的第一篇文章也是关于在 R 中执行 EDA 的,你可以在这里查看。本帖将更多关注 Python 中使用 matplotlib、回归线甚至运动图的图形化 EDA!

资料组

我们在本文中使用的数据集可以从 Gapminder 获得,并深入到人口、教育中的性别平等收入。

人口数据包含 1800 年至 2018 年间按世界各国分组的估计常住人口的年度数据。

教育中的性别平等数据包含 1970 年至 2015 年期间 25 至 34 岁年龄段在校女生与男生比例的年度数据,其中包括不同国家的小学、中学和大学教育

收入数据包含 1800 年至 2018 年期间,根据全球不同国家的购买力差异(以国际美元计)进行调整后的人均年收入数据。

EDA 人口

让我们首先绘制一段时间内的人口数据,主要集中在新加坡、美国和中国这三个国家。我们将使用matplotlib 库在同一个图上绘制 3 个不同的折线图。

import pandas as pd
import matplotlib.pylab as plt
%matplotlib inline# read in data
population = pd.read_csv('./population.csv')# plot for the 3 countries
plt.plot(population.Year,population.Singapore,label="Singapore")
plt.plot(population.Year,population.China,label="China")
plt.plot(population.Year,population["United States"],label="United States")# add legends, labels and title
plt.legend(loc='best')
plt.xlabel('Year')
plt.ylabel('Population')
plt.title('Population Growth over time')
plt.show()

按作者分类的图像-新加坡、中国和美国的 Python matplotlib 人口输出

如图所示,新加坡、中国和美国这三个国家的人口值随着时间的推移而增加,尽管新加坡并不明显,因为轴是以十亿为单位,而新加坡的人口只有几百万。

现在,让我们尝试使用linregress拟合新加坡人口数据的线性回归线,并绘制线性拟合图。我们甚至可以尝试预测 2020 年和 2100 年的新加坡人口。

from scipy.stats import linregress
# set up regression line
slope, intercept, r_value, p_value, std_err = linregress(population.Year,population.Singapore)
line = [slope*xi + intercept for xi in population.Year]# plot the regression line and the linear fit
plt.plot(population.Year,line,'r-', linewidth=3,label='Linear Regression Line')
plt.scatter(population.Year, population.Singapore,label='Population of Singapore')
plt.legend(loc='best')
plt.xlabel('Year')
plt.ylabel('Population')
plt.title('Population Growth of Singapore over time')
plt.show()# Calculate correlation coefficient to see how well is the linear fit
print("The correlation coefficient is " + str(r_value))
## Use the linear fit to predict the resident population in Singapore in 2020 and 2100.
# Using equation y=mx + c, i.e. population=slope*year + intercept
print("The predicted population in Singapore in 2020 will be " + str((slope*2020)+intercept))
print("The predicted population in Singapore in 2100 will be " + str((slope*2100)+intercept))

按作者分类的图像-新加坡人口线性回归线的 Python matplotlib 输出

从图中我们可以看出,线性拟合似乎不太适合新加坡的人口,尽管我们的相关系数接近 1。对人口的预测也很不错,因为 2020 年新加坡的现有人口约为 560 万,远远高于预测的 340 万。

注意,19 世纪 50 年代以前的人口是负数,这是绝对不可能的。因为新加坡是 1965 年建立的,所以让我们过滤一下,只使用 1965 年以后的数据。

from scipy.stats import linregress
# set up regression line
slope, intercept, r_value, p_value, std_err = linregress(population.Year[population.Year>=1965],population.Singapore[population.Year>=1965])
line = [slope*xi + intercept for xi in population.Year[population.Year>=1965]]plt.plot(population.Year[population.Year>=1965],line,'r-', linewidth=3,label='Linear Regression Line')
plt.scatter(population.Year[population.Year>=1965], population.Singapore[population.Year>=1965],label='Singapore')
plt.legend(loc='best')
plt.xlabel('Year')
plt.ylabel('Population')
plt.title('Population Growth of Singapore from 1965 onwards')
plt.show()# Calculate correlation coefficient to see how well is the linear fit
print("The correlation coefficient is " + str(r_value))
## Use the linear fit to predict the resident population in Singapore in 2020 and 2100.
# Using equation y=mx + c, i.e. population=slope*year + intercept
print("The predicted population in Singapore in 2020 will be " + str((slope*2020)+intercept))
print("The predicted population in Singapore in 2100 will be " + str((slope*2100)+intercept))

按作者分类的图像-1965 年以来新加坡人口线性回归线的 Python matplotlib 输出

如图所示,这条线性回归线与相关系数非常吻合。此外,预测的 2020 年人口正好是新加坡目前的人口,让我们希望 2100 年的人口不是真的,因为我们知道新加坡的土地面积相当小。

EDA 关于教育中的性别平等

转到第二个数据集,让我们试着绘制一段时间内新加坡、中国和美国学校的性别比例(女性对男性)图。我们还可以看看新加坡的最高和最低性别比例百分比。

# reading in data
gender_equality = pd.read_csv('./GenderEquality.csv')
# plot the graphs
plt.plot(gender_equality.Year,gender_equality.Singapore,label="Singapore")
plt.plot(gender_equality.Year,gender_equality.China,label="China")
plt.plot(gender_equality.Year,gender_equality["United States"],label="United States")# set up legends, labels and title
plt.legend(loc='best')
plt.xlabel('Year')
plt.ylabel('Gender Ratio of Female to Male in school')
plt.title('Gender Ratio of Female to Male in school over time')
plt.show()# What are the maximum and minimum values for gender ratio in Singapore over the time period?
print("The maximum value is: " + str(max(gender_equality.Singapore)) + " and the minimum is " + str(min(gender_equality.Singapore)))

按作者分类的图片-一段时间内新加坡、中国和美国的性别比例的 Python matplotlib 输出

从上面的产出可以看出,性别比率总体上是随着时间的推移而增加的。随着时间的推移,中国和新加坡的性别比例呈线性增长。就美国而言,在性别比率再次上升之前,有一段时间处于停滞状态。新加坡的最低性别比率为 79.5,最高性别比率为 98.9,这是意料之中的,因为过去新加坡的教育对男性比对女性重要得多。

让我们画出新加坡性别比例的线性回归线。

# plot the regression line
slope, intercept, r_value, p_value, std_err = linregress(gender_equality.Year,gender_equality["Singapore"])
line = [slope*xi + intercept for xi in gender_equality.Year]plt.plot(gender_equality.Year,line,'r-', linewidth=3,label='Linear Regression Line')
plt.plot(gender_equality.Year, gender_equality["Singapore"],label='Singapore')
plt.legend(loc='best')
plt.xlabel('Year')
plt.ylabel('Gender Ratio of Female to Male in school')
plt.title('Gender Ratio of Female to Male in school for Singapore over time')
plt.show()
print("The correlation coefficient is " + str(r_value))

按作者分类的图像-新加坡性别比例线性回归线的 Python matplotlib 输出

相关系数表明这是一个很好的匹配,性别比例在未来可能达到 100%。这是有可能的,因为在新加坡,教育不再是一种特权,男性和女性在接受正规教育方面有平等的机会。

收入 EDA

最后让我们转向收入数据,绘制新加坡、美国和中国的收入随时间变化的曲线图。

# read in data
income = pd.read_csv('./Income.csv')
# plot the graphs
plt.plot(income.Year,income.Australia,label="Singapore")
plt.plot(income.Year,income.China,label="China")
plt.plot(income.Year,income["United States"],label="United States")
# set up legends, labels, title
plt.legend(loc='best')
plt.xlabel('Year')
plt.ylabel('Income per person')
plt.title('Income per person over time')
plt.show()

按作者分类的图片-新加坡、中国和美国一段时间内的收入 Python matplotlib 输出

令人惊讶的是,新加坡的人均收入与美国相当,都在中国之上。

动作图——可视化随时间变化的关系

现在,让我们试着构建一个运动图,来可视化所有三个因素人口性别比例收入随时间的变化关系。为了用 Python 构建运动图,我们需要motionchart库。

在此之前,我们需要将所有三个数据集合并成一个单一的,以方便绘制我们的运动图表。可以使用常见的 pandas 命令来完成合并。

# Convert columns into rows for each data set based on country and population/gender ratio/income
population=pd.melt(population,id_vars=['Year'],var_name='Country',value_name='Population')
gender_equality=pd.melt(gender_equality,id_vars=['Year'],var_name='Country',value_name='Gender Ratio')# Merge the 3 datasets into one on common year and country
income=pd.melt(income,id_vars=['Year'],var_name='Country',value_name='Income')
overall=pd.merge(population,gender_equality,how="inner",on=["Year","Country"])
overall=pd.merge(overall,income,how="inner",on=["Year","Country"])

为了可视化随时间变化的关系,我们需要将 Year 属性设置为运动图中的关键字。我们的 x 轴将是性别比例,y 轴是收入,气泡大小为人口,最后是国家的气泡颜色。

from motionchart.motionchart import MotionChart# setting up the style
%%html
<style>
.output_wrapper, .output {height:auto !important;max-height:1000px; 
}
.output_scroll {box-shadow:none !important;webkit-box-shadow:none !important;
}
</style># plotting the motion chart
mChart = MotionChart(df = overall)
mChart = MotionChart(df = overall, key='Year', x='Gender Ratio', y='Income', xscale='linear', yscale='linear',size='Population', color='Country', category='Country')
mChart.to_notebook()

作者图片 Python 中运动图表的 GIF 输出

如果我们研究这个图表,我们知道阿富汗和也门的教育性别比例最低,分别为 23.7 和 30.1。南非的莱索托拥有最高的性别比例(注意右下角的粉红色小点)。

收入和教育中的性别比例之间通常没有明确的关系。在整个时期,由于所有国家的性别比率普遍上升,收入并没有随之增加,也没有减少。有停滞、增加和减少的组合,这与性别比率没有任何明显的关系。

让我们专注于为新加坡建立一个运动图表。

mChart = MotionChart(df = overall.loc[overall.Country.isin(['Singapore'])])
mChart = MotionChart(df = overall.loc[overall.Country.isin(['Singapore'])], key='Year', x='Gender Ratio', 
y='Income', xscale='linear', yscale='linear',size='Population', color='Country', category='Country')
mChart.to_notebook()

作者提供的图片 Python 中新加坡运动图表的 GIF 输出

对新加坡来说,有趣的是,除了人口随着时间的推移而增长,教育中的性别比例以及收入似乎也随着时间的推移而不断增长。1970 年收入 11400,2015 年大幅增长到 80900。

摘要

在本文中,我们利用 Python matplotlib、线性回归以及富于想象力的运动图表对三个数据集进行探索性数据分析,主要是人口、教育中的性别比例和收入。通过这些图形方法,我们可以发现一些关于数据的见解,并有可能让我们做出更好的预测。希望你们喜欢这种用 Python 进行探索性数据分析的图形化方法,并喜欢玩你们奇特的运动图表!

轻松绘制的图形功能

原文:https://towardsdatascience.com/graphical-functions-made-from-an-effortless-sketch-266ccf95c46d?source=collection_archive---------48-----------------------

"返回方程式的 MS Paint "

图片由 Wokandapix 来自 Pixabay

大家好!几天前,我在研究一个机器学习模型,我需要输入一个与 X 和 Y 相关的函数。唯一的约束是函数必须连续,X 和 Y 的界限必须是[0,1]。

脑子里有了几十条不同的曲线,我开始在纸上画出它们的草图。重点是之后把它们放在绘图计算器上。这是一项单调乏味的任务,我向姐姐寻求帮助。

“你为什么不为它写个程序呢?”,她回答道。

目的

一个已有的应用: MyCurveFit

现有的应用程序采用 X 和 Y 坐标来返回精确的方程。然而,曲线越复杂,用户输入的坐标就越多。此外,用户必须手动选择函数来拟合这些点(例如:线性对指数)。

这个计划

我想要一个“返回方程式的 MS Paint”。

虽然手绘意味着坐标不能精确,但当近似方程足够时,它是一个方便的工具,微调可以留待下次进行。通过比较均方误差,程序也自动选择最佳函数。

应用程序管道

这是整体架构。

我的应用程序管道

当用户在提供的画布上绘制时,提取曲线上的点的 X 和 Y 坐标。它们被输入到不同的模型中,这些模型符合如上所示的相应方程。最后,显示具有最小均方误差的方程。

由于多项式方程最容易过度拟合,因此用户可以选择限制次数。

输入加工

从用户界面到 3D 阵列的绘制

用户界面包含来自 drawingboard.js 资源库的绘图画布。当用户与它交互时,鼠标的移动会被跟踪并保存为 PNG 格式。然后图像被处理成如上所示的三维阵列。(宽 x 高 x 通道)

根据图像的数组表示,计算 X 和 Y 坐标,并分别存储在 X 和 Y 数组中。

模型拟合

Scipy 库提供了给定 X 和 Y 数组来拟合方程的方法。我主要使用了其中的两种。

Polyfit

这个方法返回给定次数的多项式的系数。下面是一个例子。

**from** numpy.polynomial.polynomial **import** polyfitx_array = [0, 1, 2, 3]
y_array = [1, 3, 4, 6]
coef = polyfit(x_array, y_array, deg=2) # Polynomial of Degree 2**print(**coef**)**
# [ 1\.  2\.  0\. ]
# Function: y = 1 + 2*x + 0*x^2

正如我们所见,这可以很容易地扩展到其他功能,如多对数。

**from** math **import** ex_array = [e, e**2, e**3]
y_array = [2, 4, 6]
coef = polyfit(np.log(x_array), y_array, deg=2)**print(**coef**)**
# [ 0\.  2\.  0\. ]
# Function: y = 0 + 2*(log x) + 0*(log x)^2

曲线拟合

这种方法更加灵活,因为它采用了用户定义的函数和要拟合的自定义系数。

正弦函数就是一个例子: y = a * sin(b * x) + c

**from** scipy.optimize **import** curve_fit
**from** math **import** pix_array = [0, pi/2, pi, 3*pi/2]
y_array = [0, 1, 0]# User-defined function with custom a, b, c, d
sine_function = **lambda** x, a, b, c, d: a * np.sin(b*x + c) + dcoef, cov = curve_fit(sine_function, x_array, y_array)**print(**coef**)**
# [ 1\.  1\.  0\.  0\. ]
# Function: y = 1*sin(1*x + 0) + 0

这同样适用于指数函数和双曲正弦函数等其他函数。

然后每个拟合的函数预测 Y 坐标。从输入 Y 中选择具有最小均方误差的一个用于显示。

输出

使用 Matplotlib 库,用不同的颜色绘制预测的 Y 与 X。之后,绘图图形被转换回 PNG 图像用于显示。

样本案例

1.三次多项式、三次多元对数函数和其他函数之间的最佳拟合

正弦函数在这里表现最佳

2.5 次多项式、5 次多对数函数和其他函数之间的最佳拟合

5 次多项式性能最佳

3.不同次数多项式函数的比较

从 1 到 3 的多项式次数

结果看起来不错!

未来的改进

首先,可以添加更多的模型。这很容易做到,因为它们已经从应用程序的其余部分中抽象出来了。欢迎建议!

第二,输入的范围可以变得更鲁棒,因为它当前仅接受[-1,1]。绘图画布可以是动态的,以适应其他范围。

感谢您的阅读!

密码

[## yarkhinephyo/sketch_a_function

在 GitHub 上创建一个帐户,为 yarkhinephyo/sketch_a_function 开发做贡献。

github.com](https://github.com/yarkhinephyo/sketch_a_function)

带 ggplot2 的 R 中的图形

原文:https://towardsdatascience.com/graphics-in-r-with-ggplot2-9380cbfe116a?source=collection_archive---------25-----------------------

了解如何使用 ggplot2 软件包在 R 中创建专业的图形和绘图

照片由艾萨克·史密斯

介绍

众所周知,R 在图形和可视化方面是一种非常强大的编程语言(当然除了统计学和数据科学!).

为了保持简短,R 中的图形可以通过三种方式完成,通过:

  1. {graphics}包(R 中的基本图形,默认加载)
  2. {lattice}为基础套装增加更多功能的套装
  3. {ggplot2}包(需要预先安装并加载

{graphics}包自带大量剧情选择(如plothistbarplotboxplotpiemosaicplot等)。)和附加的相关特征(例如,ablinelineslegendmtextrect等)。).对于大多数 R 用户,尤其是初学者到中级用户,这通常是绘制图形的首选方式。

自从 Hadley Wickham 在 2005 年创建以来,**{ggplot2}**已经成为最受欢迎的 R 包之一,也是最受欢迎的图形和数据可视化包。{ggplot2}软件包是一种更现代的创建专业质量图形的方法。更多关于这个包的信息可以在 ggplot2.tidyverse.org 找到。

在本文中,我们将看到如何用这个包在 R 中创建常见的图,如散点图、线图、直方图、箱线图、条形图、密度图。如果你不熟悉这些类型的图表,你会找到更多关于每一个的信息(何时使用,它的目的,它显示什么,等等。)在我关于 R 中描述性统计的文章中。

数据

为了说明使用{ggplot2}包的图,我们将使用包中可用的mpg数据集。该数据集包含美国环境保护署从 1999 年到 2008 年收集的 38 种流行车型的燃油经济性观察数据(运行?mpg了解更多数据信息):

library(ggplot2)
dat <- ggplot2::mpg

在继续之前,让我们用transform()函数转换因子中的cyldrvflyearclass变量:

dat <- transform(dat,cyl = factor(cyl),drv = factor(drv),fl = factor(fl),year = factor(year),class = factor(class)
)

对于感兴趣的读者,请参阅 R 中的更多数据操作技术。

`

{ggplot2}包基于“图形语法”的原则(因此{ggplot2}的名字是“gg”),也就是一个描述和构建图形的连贯系统。主要想法是设计一个图形作为一系列层

主要层有:

  1. 包含我们想要表示的变量的数据集。这是通过ggplot()功能完成的,并且排在第一位。
  2. 要在 x 和/或 y 轴上表示的变量,以及要表示的对象的美学元素(如颜色、大小、填充、形状和透明度)。这是通过aes()功能(美学的缩写)完成的。
  3. 类型的图形表示(散点图、线图、条形图、直方图、箱线图等)。).这是通过geom_point()geom_line()geom_bar()geom_histogram()geom_boxplot()等功能完成的。
  4. 如果需要,附加层(如标签、注释、比例、轴刻度、图例、主题、小平面等。)可以加进去个性化剧情。

为了创建一个图,我们首先需要在ggplot()函数中指定数据,然后添加所需的层,如变量、美学元素和图的类型:

ggplot(data) +aes(x = var_x, y = var_y) +geom_x()
  • ggplot()中的data是包含变量var_xvar_y的数据帧的名称。
  • +符号用于指示将被添加到绘图的不同层。确保将+ 符号写在代码行的末尾,而不是行首,否则 R 抛出错误。
  • aes()表示什么样的变量将被用在剧情中,更一般地说,是剧情的美学元素。
  • 最后,geom_x()中的x代表剧情类型。
  • 其他层通常是不需要的,除非我们想进一步个性化情节。

请注意,为提高代码可读性,每层编写一行代码是一个很好的做法。

用`

在以下章节中,我们将展示如何绘制以下图形:

  • 散点图
  • 线形图
  • 柱状图
  • 密度图
  • 箱线图
  • 条形图

为了将重点放在不同情节的构建和{ggplot2}的使用上,我们将限制自己只画基本的(但很漂亮的)情节,不画不必要的图层。为了完整起见,我们将在文章的最后简要讨论和说明不同的层,以进一步个性化一个情节(见本节)。

请注意,如果你在阅读完本教程后仍然难以用{ggplot2}创建剧情,你可能会发现 插件很有用。这个插件允许你用{ggplot2}交互(即通过拖放变量)创建图形。试试看!

散点图

我们首先使用geom_point创建一个散点图。请记住,散点图用于可视化两个定量变量之间的关系。

  1. 我们从指定数据开始:
ggplot(dat) # data

2.然后我们添加用aes()函数表示的变量:

ggplot(dat) + # dataaes(x = displ, y = hwy) # variables

3.最后,我们指出情节的类型:

ggplot(dat) + # dataaes(x = displ, y = hwy) + # variablesgeom_point() # type of plot

除了数据集之外,您有时还会看到ggplot()函数中的美学元素(【T2 与变量】):

ggplot(mpg, aes(x = displ, y = hwy)) +geom_point()

第二种方法给出的图与第一种方法完全相同。为了获得更好的可读性,我倾向于选择第一种方法,但这更多的是个人喜好的问题,所以选择由你决定。

线形图

线形图,在时间序列或金融中特别有用,可以类似地创建,但使用geom_line():

ggplot(dat) +aes(x = displ, y = hwy) +geom_line()

线和点的结合

{ggplot2}的一个优势是能够结合多种类型的情节,并且设计灵活。例如,我们可以通过简单地向初始散点图添加一个层来向散点图添加一条线:

ggplot(dat) +aes(x = displ, y = hwy) +geom_point() +geom_line() # add line

柱状图

可以使用geom_histogram()绘制直方图(用于可视化分布和检测潜在的异常值):

ggplot(dat) +aes(x = hwy) +geom_histogram()

默认情况下,箱的数量等于 30。您可以使用geom_histogram()函数中的bins参数来更改该值:

ggplot(dat) +aes(x = hwy) +geom_histogram(bins = sqrt(nrow(dat)))

这里我指定箱的数量等于观察数量的平方根(遵循斯特奇法则),但是您可以指定任何数值。

密度图

密度图可以使用geom_density()创建:

ggplot(dat) +aes(x = hwy) +geom_density()

直方图和密度的组合

我们也可以在同一个图上叠加直方图和密度曲线:

ggplot(dat) +aes(x = hwy, y = ..density..) +geom_histogram() +geom_density()

或者叠加几个密度:

ggplot(dat) +aes(x = hwy, color = drv, fill = drv) +geom_density(alpha = 0.25) # add transparency

为了增加透明度,增加了参数alpha = 0.25。关于这个论点的更多信息可以在这个部分中找到。

箱线图

可以使用geom_boxplot()绘制一个箱线图(对可视化分布和检测潜在的异常值也非常有用):

# Boxplot for one variable
ggplot(dat) +aes(x = "", y = hwy) +geom_boxplot()

# Boxplot by factor
ggplot(dat) +aes(x = drv, y = hwy) +geom_boxplot()

也可以用geom_jitter()在箱线图上绘制点,并用varwidth = TRUE根据每个级别的大小(即观察次数)改变方框的宽度:

ggplot(dat) +aes(x = drv, y = hwy) +geom_boxplot(varwidth = TRUE) + # vary boxes width according to n obs.geom_jitter(alpha = 0.25, width = 0.2) # adds random noise and limit its width

geom_jitter()层给每个点添加一些随机变化,以防止它们重叠(一个被称为过度绘制的问题)。 1 此外,alpha参数为点增加了一些透明度(详见本部分)以保持焦点在框上而不是点上。

最后,也可以根据定性变量的水平将箱线图分成几个面板:

ggplot(dat) +aes(x = drv, y = hwy) +geom_boxplot(varwidth = TRUE) + # vary boxes width according to n obs.geom_jitter(alpha = 0.25, width = 0.2) + # adds random noise and limit its widthfacet_wrap(~year) # divide into 2 panels

为了视觉上更吸引人的绘图,也可以根据 x 变量对框使用一些颜色:

ggplot(dat) +aes(x = drv, y = hwy, fill = drv) + # add color to boxes with fillgeom_boxplot(varwidth = TRUE) + # vary boxes width according to n obs.geom_jitter(alpha = 0.25, width = 0.2) + # adds random noise and limit its widthfacet_wrap(~year) + # divide into 2 panelstheme(legend.position = "none") # remove legend

在这种情况下,最好删除图例,因为它变得多余。参见部分中关于图例的更多信息。

如果你对{ggplot2}中提供的默认颜色不满意,你可以用scale_fill_manual()层手动改变它们:

ggplot(dat) +aes(x = drv, y = hwy, fill = drv) + # add color to boxes with fillgeom_boxplot(varwidth = TRUE) + # vary boxes width according to n obs.geom_jitter(alpha = 0.25, width = 0.2) + # adds random noise and limit its widthfacet_wrap(~year) + # divide into 2 panelstheme(legend.position = "none") + # remove legendscale_fill_manual(values = c("darkred", "darkgreen", "steelblue")) # change fill color manually

条形图

可以使用geom_bar()绘制柱状图(用于可视化定性变量):

ggplot(dat) +aes(x = drv) +geom_bar()

默认情况下,条形的高度对应于感兴趣变量的每个级别的观察频率(在我们的例子中为drv)。

同样,为了更吸引人的情节,我们可以用fill参数给条形添加一些颜色:

ggplot(dat) +aes(x = drv, fill = drv) + # add colors to barsgeom_bar() +theme(legend.position = "none") # remove legend

我们还可以创建一个包含两个定性变量的柱状图:

ggplot(dat) +aes(x = drv, fill = year) + # fill by yearsgeom_bar()

为了比较各组之间的比例,最好使用position = "fill"使每个条形的高度相同:

ggplot(dat) +geom_bar(aes(x = drv, fill = year), position = "fill")

要为每组绘制相邻的条形,请使用position = "dodge":

ggplot(dat) +geom_bar(aes(x = drv, fill = year), position = "dodge")

进一步个性化

标题和轴标签

在一个情节中,首先要个性化的是标签,以使情节对观众更具信息性。我们可以使用labs()功能轻松添加标题、副标题、说明和编辑轴标签:

p <- ggplot(dat) +aes(x = displ, y = hwy) +geom_point()p + labs(title = "Fuel efficiency for 38 popular models of car",subtitle = "Period 1999-2008",caption = "Data: ggplot2::mpg. See more at www.statsandr.com",x = "Engine displacement (litres)",y = "Highway miles per gallon (mpg)"
)

正如您在上面的代码中看到的,您可以将一个或多个绘图层保存在一个对象中以供以后使用。这样,您可以保存您的“主”图,并添加更多的个性化层,直到您获得所需的输出。这里,我们将主散点图保存在一个名为p的对象中,我们将在后续的个性化设置中引用它。

您还可以通过theme()图层和element_text()功能编辑标题和副标题的对齐、大小和形状:

p + labs(title = "Fuel efficiency for 38 popular models of car",subtitle = "Period 1999-2008",caption = "Data: ggplot2::mpg. See more at www.statsandr.com",x = "Engine displacement (litres)",y = "Highway miles per gallon (mpg)"
) +theme(plot.title = element_text(hjust = 0.5, # centersize = 12,color = "steelblue",face = "bold"),plot.subtitle = element_text(hjust = 0.5, # centersize = 10,color = "gray",face = "italic"))

如果标题或副标题很长,你想把它分成多行,用\n:

p + labs(title = "Fuel efficiency for 38 popular \n models of car",subtitle = "Period 1999-2008",caption = "Data: ggplot2::mpg. See more at www.statsandr.com",x = "Engine displacement (litres)",y = "Highway miles per gallon (mpg)"
) +theme(plot.title = element_text(hjust = 0.5, # centersize = 12,color = "steelblue",face = "bold"),plot.subtitle = element_text(hjust = 0.5, # centersize = 10,color = "gray",face = "italic"))

坐标轴刻度

可以分别使用 x 轴和 y 轴的scale_x_continuous()scale_y_continuous()调整轴刻度:

# Adjust ticks
p + scale_x_continuous(breaks = seq(from = 1, to = 7, by = 0.5)) + # x-axisscale_y_continuous(breaks = seq(from = 10, to = 45, by = 5)) # y-axis

日志转换

在某些情况下,绘制变量的对数变换很有用。这可以通过scale_x_log10()scale_y_log10()功能完成:

p + scale_x_log10() +scale_y_log10()

限制

除了limits参数之外,控制绘图限制的最方便的方法是再次使用scale_x_continuous()scale_y_continuous()功能:

p + scale_x_continuous(limits = c(3, 6)) +scale_y_continuous(limits = c(20, 30))

也可以用subset()filter()函数简单地获取数据集的一个子集。如果您需要提醒,请参阅如何子集化数据集。

缩放以获得更好的轴格式

根据您的数据,可以用{scales}包以某种方式格式化轴。我最常用的格式是commalabel_number_si(),它们以更易读的方式格式化大数字。

在本例中,我们将两个变量都乘以 1000 以得到更大的数字,然后对每个轴应用不同的格式:

ggplot(dat) +aes(x = displ * 1000, y = hwy * 1000) +geom_point() +scale_y_continuous(labels = scales::label_number_si()) + # format y-axisscale_x_continuous(labels = scales::comma) # format x-axis

如您所见,y 轴上的数字自动标有最佳 SI 前缀(“K”表示值≥ 10e3,“M”表示值≥ 10e6,“B”表示值≥ 10e9,“T”表示值≥ 10e12),x 轴上的数字显示为 2,000、3,000 等。而不是 2000,3000 等等。

这两种格式使得大数字更容易阅读。其他格式也是可能的,例如使用美元符号、百分比符号、日期等。参见包文档中的更多信息。

神话;传奇

默认情况下,图例位于图的右侧(当然,当有图例显示时)。为了控制图例的位置,除了使用legend.position参数之外,我们还需要使用theme()函数:

p + aes(color = class) +theme(legend.position = "top")

"left""bottom"替换"top"以改变其位置,用"none"将其移除。

可以用labs()层编辑图例的标题:

p + aes(color = class) +labs(color = "Car's class")

请注意,labs()中的参数必须与aes()层中的参数相匹配(在本例中为:color)。

图例的标题也可以在theme()层内用legend.title = element_blank()移除:

p + aes(color = class) +theme(legend.title = element_blank(),legend.position = "bottom")

图例现在出现在图的底部,但没有图例标题。

形状、颜色、大小和透明度

有大量的选项可以提高绘图质量或添加附加信息。其中包括:

  • 形状,
  • 尺寸,
  • 颜色,以及
  • alpha(透明度)。

例如,我们可以通过添加shapegeom_point()来改变散点图中所有点的形状,或者根据另一个变量的值改变形状(在这种情况下,shape参数必须在aes()内): 2

# Change shape of all points
ggplot(dat) +aes(x = displ, y = hwy) +geom_point(shape = 4)

# Change shape of points based on a categorical variable
ggplot(dat) +aes(x = displ, y = hwy, shape = drv) +geom_point()

遵循同样的原则,我们可以基于定性或定量变量修改点的颜色、大小和透明度。以下是一些例子:

p <- ggplot(dat) +aes(x = displ, y = hwy) +geom_point()# Change color for all points
p + geom_point(color = "steelblue")

# Change color based on a qualitative variable
p + aes(color = drv)

# Change color based on a quantitative variable
p + aes(color = cty)

# Change color based on a criterion (median of cty variable)
p + aes(color = cty > median(cty))

# Change size of all points
p + geom_point(size = 4)

# Change size of points based on a quantitative variable
p + aes(size = cty)

# Change transparency based on a quantitative variable
p + aes(alpha = cty)

我们当然可以混合几种选项(形状、颜色、大小、alpha)来构建更复杂的图形:

p + geom_point(size = 0.5) +aes(color = drv, shape = year, alpha = cty)

如果您对默认颜色不满意,您可以使用scale_colour_manual()层(用于定性变量)和scale_coulour_gradient2()层(用于定量变量)手动更改它们:

# Change color based on a qualitative variable
p + aes(color = drv) +scale_colour_manual(values = c("red", "blue", "green"))

# Change color based on a quantitative variable
p + aes(color = cty) +scale_colour_gradient2(low = "green",mid = "gray",high = "red",midpoint = median(dat$cty))

文本和标签

要在一个点上添加标签(例如行号),我们可以使用geom_text()aes()功能:

p + geom_text(aes(label = rownames(dat)),check_overlap = TRUE,size = 2,vjust = -1
)

要在图上添加文本,我们使用annotate()功能:

p + annotate("text",x = 6,y = 40,label = "hwy and displ are \n negatively correlated \n (rho = -0.77, p-value < 0.001)",size = 3
)

阅读 R 中关于相关系数和相关性测试的文章,看看我是如何计算相关系数(rho)和相关性测试的 p 值的。

平滑线和回归线

在散点图中,可以添加拟合数据的平滑线:

p + geom_smooth()

在简单线性回归的情况下,回归线通常显示在图上。这可以通过在geom_smooth()层添加method = lm ( lm代表线性模型)来实现:

p + geom_smooth(method = lm)

还可以为分类变量的每个级别绘制一条回归线:

p + aes(color = drv, shape = drv) +geom_smooth(method = lm, se = FALSE)

se = FALSE参数删除回归线周围的置信区间。

面状

facet_grid允许您根据一个或两个定性变量的值将同一个图形分成几个面板:

# According to one variable
p + facet_grid(. ~ drv)

# According to 2 variables
p + facet_grid(drv ~ year)

然后可以为每个面添加一条回归线:

p + facet_grid(. ~ drv) +geom_smooth(method = lm)

facet_wrap()也可以使用,如本章节所示。

主题

{ggplot2}包中有几个功能可以改变情节的主题。默认主题(即theme_gray())之后最常见的主题是黑白(theme_bw())、极简(theme_minimal())和经典(theme_classic())主题:

# Black and white theme
p + theme_bw()

# Minimal theme
p + theme_minimal()

# Classic theme
p + theme_classic()

我倾向于在我的大部分降价报告中使用最小化主题,因为它展现了模式和要点,而不是情节的布局,但这也是个人品味的问题。在 ggplot2.tidyverse.org/reference/ggtheme.html和{ggthemes}套餐中查看更多主题。

为了避免必须更改您创建的每个图的主题,您可以使用theme_set()功能更改当前 R 会话的主题,如下所示:

theme_set(theme_minimal())

与`

您可以轻松地将使用{ggplot2}创建的情节与{plotly}包进行交互:

library(plotly)
ggplotly(p + aes(color = year))

23456720304019992008 显示年份

现在,您可以将鼠标悬停在某个点上,以显示关于该点的更多信息。也有可能放大和缩小,下载图,选择一些观察,等等。关于 R 的{plotly}的更多信息可以在这里找到。

用`

有几种方法可以组合{ggplot2}中制作的剧情。在我看来,最方便的方法是在{patchwork}包中使用符号,如+/和括号。

我们首先需要创建一些情节并保存它们:

p_a <- ggplot(dat) +aes(x = displ, y = hwy) +geom_point()p_b <- ggplot(dat) +aes(x = hwy) +geom_histogram()p_c <- ggplot(dat) +aes(x = drv, y = hwy) +geom_boxplot()

现在我们的环境中已经保存了 3 个地块,我们可以将它们组合起来。要使图彼此相邻,只需使用+符号:

library(patchwork)
p_a + p_b + p_c

要上下显示它们只需使用/符号:

p_a / p_b / p_c

最后,将上面的和下面的组合在一起,混合+/和括号:

p_a + p_b / p_c

(p_a + p_b) / p_c

查看更多结合绘图的方式:

  • grid.arrange()来自{gridExtra}
  • plot_grid()来自{cowplot}

翻转坐标

翻转图的坐标对于创建水平盒状图很有用,或者当变量的标签太长以至于在 x 轴上相互重叠时也很有用。请参见下面的带和不带翻转坐标:

# without flipping coordinates
p1 <- ggplot(dat) +aes(x = class, y = hwy) +geom_boxplot()# with flipping coordinates
p2 <- ggplot(dat) +aes(x = class, y = hwy) +geom_boxplot() +coord_flip()library(patchwork)
p1 + p2 # left: without flipping, right: with flipping

这可以用许多类型的图来完成,而不仅仅是箱线图。例如,如果分类变量有许多级别或标签很长,通常最好翻转坐标以获得更好的视觉效果:

ggplot(dat) +aes(x = class) +geom_bar() +coord_flip()

保存绘图

除非您指定另一个文件夹的路径,否则ggsave()功能会将最近的绘图保存在您当前的工作目录中:

ggplot(dat) +aes(x = displ, y = hwy) +geom_point()ggsave("plot1.pdf")

您也可以指定宽度、高度和分辨率,如下所示:

ggsave("plot1.pdf",width = 12,height = 12,units = "cm",dpi = 300
)

管理日期

如果数据集中的时间变量是日期格式的,{ggplot2}包会识别日期格式,并自动使用特定类型的轴刻度。

在我们的数据集中没有日期格式的时间变量,所以让我们借助as.Date()函数创建一个这种类型的新变量:

dat$date <- as.Date("2020-08-21") - 0:(nrow(dat) - 1)

查看此日期变量及其类的前 6 个观察值:

head(dat$date)## [1] "2020-08-21" "2020-08-20" "2020-08-19" "2020-08-18" "2020-08-17"
## [6] "2020-08-16"str(dat$date)##  Date[1:234], format: "2020-08-21" "2020-08-20" "2020-08-19" "2020-08-18" "2020-08-17" ...

新变量date以日期格式正确指定。

大多数情况下,对于时间变量,我们希望创建一个线形图,在 X 轴上显示日期,在 Y 轴上显示另一个连续变量,如下图所示:

p <- ggplot(dat) +aes(x = date, y = hwy) +geom_line()
p

一旦时间变量被识别为日期,我们就可以使用scale_x_date()层来改变 X 轴上显示的格式。下表显示了最常用的日期格式:

来源:www.statmethods.net

运行?strptime()查看 r 中更多可用的日期格式。

对于本例,除了未缩写的月份之外,我们还要加上年份:

p + scale_x_date(date_labels = "%B %Y")

也可以用date_breaks参数控制显示在 X 轴上的断点。在本例中,假设我们希望将日期显示为数字,并将每个 10 天的间隔显示为月份缩写:

p + scale_x_date(date_breaks = "10 days", date_labels = "%d %b")

如果 X 轴上显示的标签因相互重叠而不可读,您可以使用theme()层和angle参数旋转它们:

p + scale_x_date(date_breaks = "10 days", date_labels = "%d %b") +theme(axis.text.x = element_text(angle = 60, hjust = 1))

小费

我最近学到了一个用{ggplot2}绘图时非常有用的技巧。如果像我一样,您经常注释和取消注释您的图中的一些代码行,您知道如果不删除上一行中的+符号,您就不能将最后一行转换为注释。

如果您忘记删除代码最后一行中的+符号,在图的末尾添加一行NULL将会避免错误。请看这个基本的例子:

ggplot(dat) +aes(x = date, y = hwy) +geom_line() + # I do not have to remove the + sign# theme_minimal() + # this line is a commentNULL # adding this line doesn't change anything to the plot

这个技巧节省了我很多时间,因为我不需要担心在注释了我的图中的一些代码行之后,要确保删除最后一个+符号。

如果你觉得这个技巧很有用,你可能会喜欢 RStudio 和 R Markdown 中的这些其他提示和技巧。

走得更远

到目前为止,你已经看到了{ggplot2}是一个非常强大和完整的软件包,可以在 r 中创建情节。本文只展示了冰山一角,你会发现许多关于如何使用{ggplot2}在线创建更高级的情节和可视化的教程。如果您想了解比本文所述更多的内容,我强烈建议您从以下内容开始:

  • 章节数据可视化和用于交流的图形来自 Garrett Grolemund 和 Hadley Wickham 的《数据科学的研究》一书 R
  • Hadley Wickham 的书 ggplot2:优雅的数据分析图形
  • 温斯顿·张的书
  • 列出了许多扩展{ggplot2}的包的 ggplot2 扩展指南
  • [{ggplot2}](https://www.statsandr.com/blog/files/ggplot2-cheatsheet.pdf) 小抄

感谢阅读。我希望这篇文章能帮助你用{ggplot2}包创建你的第一个情节。提醒一下,对于简单的图形,有时通过 插件来绘制更容易。过一段时间后,您将很快学会如何自己创建它们,并且很快就能够构建复杂和高级的数据可视化。

和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。

  1. 小心使用geom_jitter()图层,因为尽管它在大比例下使绘图更具揭示性,但在小比例下也会使其稍不精确,因为点上增加了一些随机性。 ↩︎
  2. (在撰写本文时)在shape参数中接受了 26 种形状。参见本文档了解所有可用的形状。 ↩︎

相关文章

  • R 中的相关系数和相关检验
  • 比利时的新冠肺炎:结束了吗?
  • 新冠肺炎隔离期间免费下载施普林格书籍的套装
  • 如何创建针对贵国的简单冠状病毒仪表板
  • 新型新冠肺炎冠状病毒前 100 名资源

原载于 2020 年 8 月 21 日 https://statsandr.com**T21

GraphQL 最佳实践

原文:https://towardsdatascience.com/graphql-best-practices-3fda586538c4?source=collection_archive---------9-----------------------

在使用 GraphQL 6 个月之后,我分享了我对创建 graph QL 服务器的良好实践的想法

威森·王在 Unsplash 上拍照

首先

GraphQL 是一种 API 查询语言,也是一种用现有数据完成这些查询的运行时语言。它为 API 中的数据提供了一个完整的、可理解的描述,并且让客户能够准确地要求他们所需要的,仅此而已。

它是由脸书开发的,作为他们移动应用的内部解决方案,后来向社区开源。

最佳实践

如果你看一下官方的 GraphQL 最佳实践页面,你会注意到它只分享了一些更常见的最佳实践的简要描述,在我看来,这只是一些指南,并没有支持实现的细节。我将尝试分享一些使用 GraphQL 的后端应用程序的具体实现。

这绝对不是一个完整的指南;这只是关于如何避免经常出现的最大陷阱的最佳实践和说明的列表。

将精益数据模型用于简单的查询和变异

当您开始创建模式时,设计数据模型可能会很棘手。有多种方法可以做到这一点,尽管大多数实现都可以正常工作,但是只有当您尝试扩展实现时,问题才会浮出水面。

一般来说,看看已经在使用 GraphQL 的平台总是好的。Github API 是理解输入和输出对象如何建模以及查询和变异如何暴露的好地方。

作为一般的经验法则。让你的突变尽可能小。保持输入精简,并精心命名。

突变addComment简单、简洁、清晰。它接受一个输入AddCommentInput并返回一个Comment。我们正在应用一个非空的修饰符(!)以确保输入有效负载不能为空。这里需要注意的一点是我们发送回创建/更新的对象。这允许客户端更新状态,以便用户知道是否有更新。

相当整洁!

如有任何问题或讨论,请随时联系我。我在推特上有空。

使用嵌套对象减少网络调用

上例中的类型Comment是一个只有一个字段的简单类型。假设我们想将userId作为Comment的一部分发送回去。一种可能的方法是这样的。

虽然这看起来是一种快速简单的方法,但是有一个小问题。对于前端来说,userId本身并不是很有用,它最终必须调用userId来获取用户。这确实很不方便,也没有最大限度地发挥 GraphQL 的威力。在 GraphQL 中,嵌套输出类型要好得多。这样,我们可以用一个请求调用所有的东西,还可以用数据加载器执行缓存和批处理。

方法将是在Comment中发送User。它看起来会像这样。

然后查询看起来像这样。

启用正确的错误处理

这是几乎每个人在开始时都会忘记的事情之一,然后当应用程序变得庞大时,覆盖错误情况就变得非常麻烦。当涉及到 GraphQl 错误处理时可能会非常棘手,因为响应总是有一个 HTTP 状态200 OK。如果请求失败,JSON 有效负载响应将包含一个名为errors的根字段,其中包含失败的详细信息。

如果没有适当的错误处理,响应将如下所示:

这一点帮助都没有——回复并没有告诉你到底哪里出了问题。这就是为什么大多数应用程序失败了,却没有真正给用户提供正确的消息或后备选项。处理错误本身就是一个很大的话题,我为此写了一篇单独的博客,里面有一个完整的运行示例。可以在这里找到。

[## 用 GraphQL、Spring Boot 和科特林处理错误

使用 Spring Boot 和 Kotlin 对 GraphQL 错误和异常建模

medium.com](https://medium.com/better-programming/error-handling-with-graphql-spring-boot-and-kotlin-ed55f9da4221)

简而言之,实现后的输出如下所示:

使用接口和联合进行抽象

接口作为父对象,其他对象可以继承。

接口类型扩展用于表示从某个原始接口扩展而来的接口。例如,这可能用于表示多种类型的常见本地数据,或者由 GraphQL 服务(它本身是另一个 GraphQL 服务的扩展)来表示。

并且联合是一种表示许多对象的对象类型。

GraphQL 联合表示可能是 GraphQL 对象类型列表中的一个对象,但是在这些类型之间不提供有保证的字段。它们与接口的不同之处还在于,对象类型声明它们实现什么接口,但不知道包含它们的联合是什么。

考虑下面的例子。这个概要文件是一个由UserCompany实现的接口。很少有字段是必填的。可以根据不同的类型和要求添加附加字段。

当您的查询需要返回两种类型时,可以使用类似的联合。您的search查询可以返回UserCompany

关于更详细的解释和实现,你可以阅读这个。

[## 通过 Spring Boot 使用 GraphQL:接口和联合

GraphQL 的接口和联合提供了一种在查询中处理多种字段类型的好方法

medium.com](https://medium.com/better-programming/using-graphql-with-spring-boot-interfaces-and-unions-a76f62d62867)

使用片段重用已定义的类型

片段是 GraphQL 中可重用的东西。你可以假设像编程语言中的函数一样的片段。

使用扩展运算符(...)消耗片段。这样会减少很多冗余代码。

感谢阅读。我希望它能帮助您实现一个健壮的 GraphQL 服务器。这些方法屡试不爽。如果你有除此之外的建议,请随时回复。如有任何问题或讨论,请随时联系我。我在推特上有空。

如果你想知道 GraphQL 是否适合你,你可能会有兴趣阅读这篇文章。

[## 使用 GraphQL 个月

在后端使用 GraphQL 做了 6 个月的项目后,我衡量了这项技术是否适合…

levelup.gitconnected.com](https://levelup.gitconnected.com/6-months-of-using-graphql-faa0fb68b4af)

参考资料:

  • GraphQL 规格
  • GraphQL 最佳实践
  • GraphQL 接口和联合
  • GraphQL 错误处理

带 Python Flask 的 GraphQL

原文:https://towardsdatascience.com/graphql-with-python-flask-560d083ffa01?source=collection_archive---------20-----------------------

GraphQL、石墨烯、Flask 和 Mysql

照片由 Michael Dziedzic 在 Unsplash 拍摄

在我们开始之前,让我们先谈谈我们的目标。

我们正在尝试开发一个在 Flask 上运行的初学者工具包项目,它具有以下功能:

  • GraphQL 支持
  • 数据库集成

先决条件

对于本教程,我们需要:

- Python
- Pip
- Virtualenv
- Docker

安装烧瓶

Flask 是一个基于 Werkzeug、Jinja 2 和 good intentions 的 Python 微框架。—烧瓶文件

建立一个准系统 Flask 项目非常简单。然而,由于我们希望内置相当多的功能,下面的步骤将比通常花费稍长的时间。

首先创建一个虚拟环境。

$ virtualenv venv
$ source venv/bin/activate

接下来,我们可以安装所需的软件包。为了不使每个人感到困惑,我将只分别包括每个步骤所需的包。

$ pip install flask flask_script
$ mkdir -p app/__init__.py
$ touch manage.py

MySQL 与 Flask 的集成

我们首先必须安装所需的依赖项

$ pip install flask-sqlalchemy pymysql

我们现在可以开始设置我们的 Flask 应用程序来连接我们的 MySQL 服务。为此,我们必须添加一个config.py文件,并更新我们的app/__init__.py文件。

使用一个配置文件,我们能够分离我们的环境变量,以及根据需要存储我们的常量变量。

这样,当我们运行docker-compose up时,应用程序将开始运行,并与 MySQL 服务连接。

设置 GraphQL

GraphQL 是一种针对 API 和运行时的查询语言,用于使用现有数据完成这些查询。GraphQL 为 API 中的数据提供了一个完整且易于理解的描述,让客户能够准确地了解他们的需求,使 API 更容易随时间发展,并支持强大的开发工具。

$ pip install graphene Flask-GraphQL

让我们分析一下我们刚刚安装的软件包。

烧瓶图

Flask-GraphQL 是一个包装层,为 Flask 应用程序增加了 GraphQL 支持。

我们必须为客户端添加一个/graphql路由来访问 API。为此,我们可以简单地更新我们的app/__init__.py文件。

在这种情况下,我们从Flask-GraphQL模块导入了GraphQLView,并使用它来实现我们的/graphql路线。

石墨烯

接下来,我们将使用石墨烯-Python 包。Graphene 是一个开源库,允许开发人员使用 Python 中的 GraphQL 构建简单但可扩展的 API。

如果你已经从我们最新的app/__init__.py文件中注意到,我们实际上缺少一个app/schema.py文件来让我们的 Flask 应用程序工作。GraphQL 模式是任何 GraphQL 服务器实现的核心,它描述了连接到它的客户机可用的功能。

在这种情况下,我们将创建一个简单的模式,这样我们的应用程序将能够运行,没有任何错误。

这样,尝试运行您的应用程序。当你访问http://localhost:5000/graph QL时,你应该能看到这个页面。如果你熟悉 GraphQL,这个页面你应该很熟悉。这是一个允许你输入 GraphQL 查询的界面。

结论

我希望本文能让您更好地理解和概述如何使用 GraphQL 构建 Python 应用程序。这也可以通过 Django 框架来实现。

我还在这里添加了一个 Github 知识库供参考。这是 GraphQL 最佳实践的另一个故事,您可能会感兴趣。

[## GraphQL 最佳实践

在使用 GraphQL 6 个月之后,我分享了我对创建 graph QL 服务器的良好实践的想法

towardsdatascience.com](/graphql-best-practices-3fda586538c4)

图表、渐变和分组依据

原文:https://towardsdatascience.com/graphs-gradients-and-groupby-what-my-first-major-project-has-taught-me-a3c96561700a?source=collection_archive---------49-----------------------

图片作者。

我的第一个主要数据科学项目教会了我什么。

当我完成熨斗学校数据科学项目第一阶段的第一个项目时,我对我现在知道如何做的大量事情感到惊讶,这些事情在短短两个月前我甚至不知道存在。退一步说,这个项目的节奏很快。我发现自己不断地在母亲生活的诸多责任中周旋,同时尽可能地挤出时间投入到学习中。从本质上说,这意味着我两岁的孩子经常生我的气……而且我一直没有睡觉。(所以如果有人想给我买十月礼物,我是大号 XXXL 咖啡,谢谢。)

但是,这个项目教会了我很多东西。在我进入代码的本质之前,我需要提到一个事实,这个项目的工作教会了我如何在未来做得更好。我一直纠结的问题是,在学术方面,我天生是个完美主义者。认识我的人听到这个消息有时会感到惊讶,因为我家的标准脏乱程度并不会让你联想到完美。我写这篇文章时,正盯着一间堆满玩具的房间和一张用昨天的工艺用品装饰的桌子。但是当涉及到我正在学习或被评估的任何事情时,我都以很高的标准要求自己。这给我带来了麻烦。

问题?我们有两周的时间作为一个团队来完成一个主要项目。我自己做的,很早就开始了,给自己三周左右的时间完成。但是我做了这个项目的三个不同版本,因为我一直试图转换方向,让它变得更好。我一直告诉自己,我还有时间,所以我会用这些时间去探索其他的道路。我没有保持在正确的轨道上,专注于完成必要的任务,而是不断放弃我的数据,以支持新的东西或看起来比我现有的更好的东西。我导入,我抓取网页,我调用 API,我清理和准备数据——然后我用不同的东西重新开始。最后,尽管我很早就开始了,但我最终还是匆忙完成了这个项目,因为我转换了很多次方向。这给了我,或者说提醒了我一个非常重要的教训,那就是保持在正确的轨道上,不要对自己太苛刻,在开始阶段就把事情做得尽善尽美。我明白了,我已经太老了,不能再熬通宵,在午夜吃麦片,数着离孩子们醒来还有几个小时!

另一个问题是,又是这个完美主义的东西,我不断为我的分析创造越来越多的可视化。我们被要求有 4 个有意义的可视化,在我写这篇文章的时候,我有 27 个。问题?我本可以专注于制作更令人惊奇的更少的可视化效果,而不是大量不同程度的可视化效果。我对这种过度绘图和绘制的唯一解释是,我是在完成一个极其彻底的分析的心态。我一直在想,“现在,如果我把它画成这个,那么我的图表就会按照我想要的方式显示数据。”老实说,我喜欢绘图,每次发现显示数据的新方法时都很兴奋。(简短的题外话:我真的对我制作的一个特定的 seaborn 小提琴情节感到兴奋,直到一个匿名的消息来源告诉我,这个特定的情节看起来像彩虹一样的阴道。所以我不得不再次转换方向,只是因为我不能无视它,可悲的是阴道与我的项目无关。)同样,如果你没有严格的时间限制,这不是问题,但不幸的是,这正是我的时间限制。

现在,我已经有了一些时间来反思我的过程,并获得了一些对自己未来非常重要的见解,我可以让自己为自己迄今为止所学到的知识和取得的成就感到自豪:

  • 网络搜集。当我们第一次在课程材料中了解到网络搜集时,我对这个话题并不感兴趣。我不喜欢它的伦理灰色地带;与其他数据采集方法相比,它感觉很不雅。但我想我缺乏最初的兴趣只是因为缺乏必要。一旦我发现自己在做一个需要特定数据的项目,很快我就明白了网络抓取是导入信息的一种快速而有用的方式。能够在网站上生成一份财务报告,然后编写一个快速的 python 函数来获取该报告,并将其导入为熊猫数据框架,这是我直到最近才知道的事情。所以当我意识到它的速度和简单性时,我感觉非常棒。每当我能够像这样成功地执行功能时,我可能会也可能不会从我的桌子上跳起来跳舞。
def number_scraper(year):""" Scrapes 100 top-grossing movies from The-Numbers.com. Adds year input to url and scrapes resulting table. Parameters: year (int): user input 4-digit year for movie gross to be scraped.Returns: numbers_df (Pandas DataFrame): A dataframe populated with movie gross table values. """# url for the full customized report of top 100 movies for release years in range listedurl = f"[https://www.the-numbers.com/movies/report/All/All/All/All/All/All/All/All/All/None/None/{year}/{year}/None/None/None/None/None/None?show-release-date=On&view-order-by=domestic-box-office&show-release-year=On&view-order-direction=desc&show-production-budget=On&show-domestic-box-office=On&show-international-box-office=On&show-worldwide-box-office=On&show-genre=On&show-production-method=On&show-creative-type=On](https://www.the-numbers.com/movies/report/All/All/All/All/All/All/All/All/All/None/None/{year}/{year}/None/None/None/None/None/None?show-release-date=On&view-order-by=domestic-box-office&show-release-year=On&view-order-direction=desc&show-production-budget=On&show-domestic-box-office=On&show-international-box-office=On&show-worldwide-box-office=On&show-genre=On&show-production-method=On&show-creative-type=On)"response = requests.get(url)# creating soupsoup = BeautifulSoup(response.text, 'lxml')# finding tabletable = soup.find('table')# converting html of table into string table_string = f"""{table}"""# reading html string into pandastable_read = pd.read_html(table_string)# converting into DataFramenumbers_df = table_read[0]return numbers_df
  • **进行 API 调用。**我非常喜欢关于 JSON 和 API 调用的课程材料。所以毫不奇怪,我必须将这一点纳入我的项目。能够编写一个函数来获取一部电影的标题并返回你可能想知道的关于这部电影的任何内容,这是多么令人惊奇啊!当我编写一个函数,将电影的标题作为一个参数,检索它的上映日期、导演和作曲家,然后将它添加到我的 DataFrame 中时,我感到无比自豪。我还喜欢能够将我的 API 密匙保存在一个秘密文件夹中,并将其设置为函数中使用的变量。
def get_keys(path):"""Retrieves API key from files as api_key."""with open(path) as f:return json.load(f)
keys = get_keys("/Users/dtunnicliffe/.secret/TMDb_api.json")
api_key = keys['api_key']def get_director(title):""" Updates director information for movie in dataframe.Queries TMDB for a given movie title.Retrieves TMDB movie_id for title.Retrieves director information based on movie_id.Adds director information to a list.Converts director information from list to string.Adds new director value as string to movie's row in dataframe. Parameters: title (str): user input movie title.Returns: Updated cells in Pandas DataFrame. """title_r = title.replace(' ', '+')url = f"[https://api.themoviedb.org/3/search/movie?api_key={api_key}&query={title_r](https://api.themoviedb.org/3/search/movie?api_key={api_key}&query={title_r)}"response = requests.get(url)if len(response.json()['results']) > 0:movie_id = response.json()['results'][0]['id']url2 = f"[https://api.themoviedb.org/3/movie/{movie_id}/credits?api_key={api_key](https://api.themoviedb.org/3/movie/{movie_id}/credits?api_key={api_key)}"response2 = requests.get(url2)crew = response2.json()['crew']directors = []for member in crew:if member['job'] == 'Director':directors.append(member['name'])d = str(directors)d = d.replace('[', '').replace(']', '').replace("'","")merged_df.loc[merged_df['title']==title, 'director'] = delse:pass
# creating a list of all the super hero movie titles
superhero_titles = [title for title in superhero['title']]
# getting director info for movies in list and updating data accordingly
for title in superhero_titles:get_director(title)
  • **带兵!**是的,我们已经谈到了我对情节和图表的痴迷。但这真的是一个扩展我绘图知识的绝佳机会。对于这个项目,我利用 matplotlib 和 seaborn 来绘制我的图,我真的很喜欢这样做。作为一名视觉学习者,我可以直接看到这些图如何讲述一个故事,以及它们对于一名数据科学家向另一个人或组织传达他们的发现有多重要。一件既令人难以置信的乏味又令人难以置信的有益的事情是在我的一些地块上标注或标记点。例如,我选择标注代表我的项目所关注的子类别的票房最高的电影的点,超级英雄电影和动画儿童音乐电影。将电影片名放在正确的位置上非常耗时,有时甚至令人沮丧。但是看到最终的结果让我觉得一切都值了。
# plotting world gross by budget for animated movies
sns.set_style('darkgrid')
sns.lmplot(x='budget_in_mil', y='world_gross_mil', data=merged_df.loc[merged_df['prod_method']=='Digital Animation'], aspect=3)
plt.title('World Gross by Budget for Animated Movies', fontsize=20)
plt.xlabel('Budget in Millions', fontsize=15)
plt.ylabel('World Gross in Millions', fontsize=15)
plt.xlim(0, None)
plt.axhline(y=1000, ls='--', c='green')
for v, w, x, y, z in zip(merged_df['genre'], merged_df['prod_method'], merged_df['budget_in_mil'], merged_df['world_gross_mil'], merged_df['title']):if (z=='Frozen'):plt.text(x=x-15, y=y-15, s=z.upper(), fontsize=12, color='black')elif  z=='Toy Story 3':plt.text(x=x-23, y=y-10, s=z.upper(), fontsize=12, color='black')elif  z=='Zootopia':plt.text(x=x+2, y=y, s=z.upper(), fontsize=12, color='black')elif (z=='Toy Story 4'):plt.text(x = x+2, y = y, s = z.upper(), fontsize=12, color='black')elif (w=='Digital Animation') and y>1000:plt.text(x = x+2, y = y-15, s = z.upper(), fontsize=12, color='black');
#saved in images as fig22
#plt.tight_layout()
#plt.savefig('./images/fig22.png')

# plotting world gross by budget and release month for super hero movies
sns.set_style('darkgrid')
g = sns.relplot(x='budget_in_mil', y='world_gross_mil', data=merged_df.loc[merged_df['creative_type']=='Super Hero'], hue='release_month', hue_order=['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], s=130, aspect=3, palette='Paired')
plt.title('World Gross by Budget and Release Month for Super Hero Movies', fontsize=20)
plt.xlabel('Budget in Millions', fontsize=18)
plt.ylabel('World Gross in Millions', fontsize=18)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.xlim(0, None)
g.fig.set_size_inches(16,10)
for w, x, y, z in zip(merged_df['animated_or_super'], merged_df['budget_in_mil'], merged_df['world_gross_mil'], merged_df['title']):if (z=='Avengers: Endgame'):plt.text(x=x-60, y=y-15, s=z.upper(), fontsize=12, color='black')elif (z=='Avengers: Infinity War'):plt.text(x=x+2, y=y-15, s=z.upper(), fontsize=12, color='black')elif (z=='Avengers: Age of Ultron'):plt.text(x=x-76, y=y-15, s=z.upper(), fontsize=12, color='black')elif (z=='The Avengers'):plt.text(x=x+2, y=y-15, s=z.upper(), fontsize=12, color='black')elif (z=='Spider-Man: Far From Home'):plt.text(x=x-80, y=y-15, s=z.upper(), fontsize=12, color='black')elif (z=='Aquaman'):plt.text(x=x, y=y+10, s=z.upper(), fontsize=12, color='black')elif (z=='Captain Marvel'):plt.text(x=x+2, y=y-35, s=z.upper(), fontsize=12, color='black')elif (w == 'super') & (y>1000):plt.text(x = x+2, y = y-15, s = z.upper(), fontsize=12, color='black')
plt.axhline(y=1000, ls='--', c='green');
#saved in images as fig25
#plt.tight_layout()
#plt.savefig('./images/fig25.png')

图片作者。

  • **色调和调色板。**这是上一点的翻版,但是在 seaborn 中使用色调和调色板既有用又有趣。我选择将我的大部分绘图设置为相同的配色方案,以便它们与我的演示幻灯片相匹配。但是我喜欢在如此多美观的组合中设置不同的渐变和调色板的能力。我也一直在我的 seaborn 图中使用色调参数来区分不同的值,比如电影上映月份或电影类型。

图片作者。

图片作者。

  • 数学/统计技术。当然,任何数据科学项目的主要组成部分都是数学。我很高兴着手这个项目,因为我已经掌握了我需要的大多数统计工具的知识。简单的.describe方法在获取重要信息方面走了很长的路,比如我的数值列的平均值、中间值和百分点,比如国内、国际和全球票房总额或制作预算。计算四分位差(IQR)和我碰巧需要的任何其他描述性统计数据也很容易。
  • Groupby。在这个项目开始之前,我对使用pandas.groupby有些不放心。我理解它,但只是抽象地理解。将它与我获得的真实电影数据一起使用后,我现在对如何在未来使用它有了更坚定的把握。在这个项目中,我经常使用它来查找像发行月份或电影类型这样的类别的平均值和中间值。
# getting mean and median world gross amounts by genre
genre_stats = merged_df.groupby('genre')['world_gross_mil'].agg(['median', 'mean'])
genre_stats.sort_values(by='mean', ascending=False)

图片作者。

  • **数据清洗。**我把它放在这个列表的底部(尽管从重要性的角度来说它应该在列表的顶部),因为项目的这一部分,对于我开始的项目的所有三个版本来说,是最令人畏惧和最不愉快的。到了我的第三个也是最后一个项目版本,我已经将我所有的清理动作添加到一个单一的函数中,以帮助加速清理并使其更容易。但是,删除重复项,找出用什么替换每个空值(然后实际替换所述空值),修改列名和实际列,以及找出何时真正需要删除数据……就没那么有趣了。更不用说处理字符串格式而不是整数格式的数据,或者处理浮点数格式而不是日期时间格式的年份了…
def clean(df):""" Cleans and modifies a given dataframe according to criteria set for this particular project. Drops column called 'Unnamed:0'.Converts column names to lowercase.Renames certain columns to make them shorter/more comprehensive.Removes dollar signs and commas from dollar amounts.Converts dollar amounts from strings into integers.Parameters: df (Pandas DataFrame): user input dataframe based on previously scraped table values from The-Numbers.com.Returns: df (Pandas DataFrame): A dataframe cleaned and adjusted as per criteria listed above. """# drop 'Unnamed' columndf = df.drop(columns='Unnamed: 0')# make column names lowercasedf.columns = [x.lower() for x in df.columns]# rename certain columnsdf = df.rename(columns = {'released':'release_date', 'released.1':'release_year', 'productionmethod':'prod_method','domesticbox office':'dom_gross', 'internationalbox office':'int_gross', 'worldwidebox office':'world_gross','creativetype':'creative_type', 'productionbudget': 'budget'})# removing dollar signs and commas from dollar amounts# converting dollar amounts from strings into integersdf['dom_gross'] = df['dom_gross'].str.replace(',', '').str.replace('$', '').astype(int)df['int_gross'] = df['int_gross'].str.replace(',', '').str.replace('$', '').astype(int)df['world_gross'] = df['world_gross'].str.replace(',', '').str.replace('$', '').astype(int)df['budget'] = df['budget'].str.replace(',', '').str.replace('$', '').astype(int)return df
  • **日期时间。**我从对日期时间一无所知,到至少知道足够将我的一些列转换成日期时间值,并基于所述值使用特性工程函数(即,列创建)。所以这很酷。关于这个主题,我还有很多要学习的,因此,在多次尝试使用 datetime 按月份顺序显示我的图表后,我不得不手动做一些事情,如按名称设置我的发布月份顺序。但令我高兴的是,我学到了足够多的知识,可以将我的一些数据转换为日期时间值,并根据日期时间值过滤我的数据帧。
# converting release_date column to datetime object
merged_df['release_date'] = pd.to_datetime(merged_df['release_date'])
# generating release_month value based on datetime release_date
merged_df['release_month'] = merged_df['release_date'].dt.strftime('%B')
  • **名正言顺。**早在我开始数据科学之路之前,这就是我一直在努力解决的问题。当我在高中的时候,“二年级演讲”是我们十年级的一个标志,我仍然记得站在全班近 500 名学生面前发表关于素食主义的演讲时的焦虑,因为我(不幸地)进入了最后一轮。这稍微容易一点,因为我正在通过 Zoom 向一位教师展示我的非技术性发现,但焦虑仍然非常真实。我知道这是一项我需要提高的技能,这样我才能在作为数据科学家的职业生涯中自如地交流我的发现。(对我的同学 Fen 大声喊出来,感谢她抽出时间来帮助我练习这个,让我对演讲这个想法更加适应!像这样的联系让旅程变得更加美好。)

现在我可以松口气了,我们进入了第二阶段,学习概率、统计分布、中心极限定理、假设检验和方差分析。因此,在这一点上,我只是希望统计学知识就像骑自行车一样,我从本科统计学中学到的一切开始在我的大脑中重新展现。如果您已经做到了这一步,请随时联系我们,提供任何反馈!感谢您的阅读。

对于我的整个一期项目,包括完整的 Jupyter 笔记本和我的幻灯片演示的 pdf,请访问我的项目 1 GitHub Repo 这里

用多元宇宙理论解决事件概率

原文:https://towardsdatascience.com/grappling-with-event-probabilities-using-multiverse-theory-26b46067da14?source=collection_archive---------61-----------------------

不要射杀建模者——至少在这个世界里

吉列尔莫·费拉在 Unsplash 上拍摄的照片

人类有很多认知能力,但我们大多数人都在努力的一个领域是估计、解释和准备不太可能发生的事件。这个主题支撑了纳西姆·塔勒布的两部主要作品:被随机性愚弄和黑天鹅:极不可能事件的影响。在后一部作品中,塔勒布将黑天鹅事件定义为具有三个特征:事件是一个惊喜(对观察者而言),它有重大影响,以及人们事后错误地试图合理化(强调我的)。

Taleb 关注世界舞台上的黑天鹅事件,如互联网的创建、第一次世界大战、苏联解体等。我相信人类的行为是相似的,而且对他们有害,统计模型预测的可能性较小的事件,只要它们是重要的。我们最近在 2016 年总统选举结果中看到了这一点。《赫芬顿邮报》、《纽约时报》和《纽约时报》发布的模型都认为希拉里·克林顿有 71-98%的胜算。在她竞选失败后,一个普遍的反应是[我们是否可以再次信任民意调查和依赖于他们数据的模型】,我很惊讶地看到,即使是从有统计学头脑的朋友那里。为什么我们的本能反应是仔细检查那个说特朗普有 29%胜算的模型?我们不会质疑一枚硬币出现两次反面(25%的可能性)或掷骰子出现 1(17%的可能性)的公平性;这两个数字都低于特朗普赢得 2016 年大选的赔率。

我假设这种反应是一种事后合理化的形式,是由于缺乏一种心智框架来应对现实世界的事件概率,而没有这种框架会导致非理性的决策。为了说明这一点,让我们从选举建模的世界转移到商业世界中遇到的更常见的情况。

最黑暗的时间线

假设你是一名数据科学家,在一家 B2B 科技公司模拟与潜在客户达成销售的概率。你的公司正在争取一个特别大的客户,Megacorp,所以首席执行官每天检查你的模型,以跟踪完成销售的可能性。

周四 : 98%的成交

难以置信的消息!无论你的队友在做什么,看起来都很有效。

周五 : 99%的成交

甚至更好!首席执行官开始计划在预期的意外之财后,他需要对你的企业做出的改变。雇佣更多员工?收购竞争对手?买超级碗广告?

周一:成交 0%

发生了什么事?!您了解到潜在客户在最后一刻选择了与竞争对手合作。这对每个人的士气都是一个巨大的打击,首席执行官在他认为几乎可以保证的销售后,花在梦想扩张上的时间和精力都浪费了。

对这种惨败的普遍反应是什么?“型号肯定是错的!”首席执行官在事后总结会上宣布,他会打电话给你。“我们应该知道这不像你说的那样可能。在它修好之前,我不想听到你的消息。”

制造问题

有可能 CEO 是对的。你的模型可以预测到你的公司最终没有达成交易的可能性较低。不过,也有可能模型没问题。你的公司有很大的机会达成交易,但是不可思议的事情发生了,你没有成功。

你现在处于一个不舒服的位置。“改进”该模型的唯一方法可能是,以精确模拟未来销售为代价,制作一个估计完成 Megacorp 销售的可能性较低的模型*。这叫做过拟合。为了讨首席执行官的欢心而顺从他的要求,扭曲了对未来销售的预测,从而损害了你的模式和公司。*

回归基础

在我们开始讨论我提出的可以帮助人们更好地理解复杂的现实世界事件概率的心理框架之前,让我们从一个简单的例子开始。想象你有一个公平的六面骰子。你一遍又一遍地滚动骰子,开始记录结果。在多次掷骰子之后,你会观察到你所期望的:大约相同数量的掷骰子产生了每个数字,从 1 到 6。

在几百次掷骰子之后,你会得到一个不太可能的、不幸的(在大多数游戏中)连胜。一个 1,接着是另一个 1,接着是另一个 1!出现这种情况的几率是 1/216 = ~0.5%。这是一个不太可能发生的事件。你惊讶吗?你怀疑死亡的公平性吗?你有没有告诉骰子,在你再次掷骰子之前,它最好先调整好自己?

大多数人,甚至那些没有受过任何统计训练的人,都会说不。发生的事情不太可能,但骰子的表现却如预期的那样。此外,如果我们认真思考,我们可以解释骰子滚动随机性背后的机制。一旦骰子离开你的手,它就服从物理定律,并且是完全可预测的。掷骰子是随机的原因是释放后速度和方向的微小变化会导致不同的结果。没有人有在掷骰子时作弊所需的精细动作技能,这将允许他们让一些数字比其他数字出现得更频繁。

我们可以使用统计总体的概念,统计总体是“对某个问题或实验感兴趣的一组相似的项目或事件”(维基百科)。在这种情况下,感兴趣的项目是骰子点数。由于速度和方向不同,我们得到不同的结果。

当我们掷骰子时,我们所做的是从这个群体中取样。所有可能的投掷(甚至是骰子从你的手中掉落或被扔出敞开的窗户的投掷)的群体包含每种结果的相等份额。如果我们从面积的角度来考虑这个问题,如上图所示,我们可以想象,从 1 到 6,每个结果的人口面积相等。

图片由作者提供

在我们增加一些复杂性之前,我想强调一个观点,即虽然只有六种同样可能的掷骰结果,但速度和方向有无限多种组合,当遵守不变的物理定律时,就会产生这些结果。凭借对掷骰子的深刻理解,我们可以想象做两种不同类型的工作:

  1. 我们可以利用我们对同等权重的人口结果的理解,在不同的领域,如游戏、赌博和商业中提出最优策略。
  2. 我们可以尝试使用我们对驱动等概率的机制的理解,即释放后骰子的速度和方向可以完美地预测其结果,以尝试让某些结果更频繁地发生。人类做不到这一点,但也许我们可以创造一个机器人,它可以扔出每次都是 6 的骰子。

增加复杂性

在我们的销售示例中,统计总体是什么?大多数人会回答说,这都是可能的销售客户。我总是发现这个定义有一些令人沮丧的地方:我们不能用它来解释为什么我们的模型有 99%的机会获得我们没有获得的销售,除非承认它一定是模型错误。如果是这样的话,我们的首席执行官——他不是概率和统计方面的专家——觉得他的要求是合理的。

图表由作者提供

解决这一问题的一种方法是将预测按准确度分组(例如 0–10%、10–20%、…90–100%),并共同绘制准确度图表。一个表现良好的模型将会显示这些预测围绕着观察到的总体情况进行。

这仍然不能满足我理解预测的 99%的需要。想象一下,总的来说,我们预测在 90–100%的预测时段中,96%的销售将被关闭,但只有 95%被关闭。人们仍然可以争辩说,通过修正模型,并降低我们预测的 99%,我们仍然可以提高总的准确性。

图片由作者提供

与掷骰子的例子不同,我们不能轻易地从总体中重新取样。我们无法重温历史,以 100 种略有不同的方式向 Megacorp 推销 100 次,100 次中有 99 次都能卖出。但是我们可以用多元宇宙理论想象这样做!在多元宇宙理论中,特别是第三层:多世界解释,概率事件的所有可能结果都发生在某个宇宙中,并且与它们的概率成比例。我想将多元宇宙人口定义为所有可能宇宙中的统计人口(在本例中:所有潜在客户)*。*扩展上面的统计人口示例,我们可以将代表每个潜在客户的每个点变成一个圆圈,代表该潜在客户在所有领域的结果。赢得该客户业务的可能性越高,赢得其业务的宇宙的比例就越大,因此客户圈的面积就越大。请注意,如果我在整个多元宇宙群体中添加阴影,它将类似于我之前分享的掷骰子图。

图表由作者提供

拥有多元宇宙精神框架的好处

敏锐的读者已经注意到,我们不能用这种多元宇宙的概率方法来证明我们的模型是正确的。我们不能从一个领域跳到另一个领域,列出我们赢得 Megacorp 销售的比例,向我们的首席执行官展示我们的模式正在按预期运行。事实上,任何模型都不可能完美地解释这个世界。我们能做的最好的事情就是知道一个模型合理地预测了我们感兴趣的人群中的样本,通常是通过与其他不太准确的模型进行对比。即便如此,我们仍然依赖于假设来这样做,其中最重要的一点是,系统不会经历意料之外的结构变化。如果发生这样的变化,我们所有的预测都将落空。在我们的例子中,一个强有力的竞争者进入或离开市场将代表这种变化。

根据我的经验,许多数据科学家忽视甚至摒弃非经验主义的想法,比如这种用多元宇宙理论来解决概率问题的方法,但他们这样做是在自担风险。使用该理论的第一个好处是,这是一种向那些没有很强背景的人解释概率的简单方法,比如我们例子中的 CEO。用多元宇宙理论解释你的模型输出有可能帮助你的模型消费者更容易理解如何解释它们。它可以单独完成,或者添加到关于过度拟合的简短解释中,以说服我们假设的首席执行官放弃他(潜在的)非理性需求来调整你的模型,直到它降低了 Megacorp 的销售概率。

第二个好处是,多元宇宙理论解释概率的方法为我们提供了一个有用的假设分析结构。还记得我们掷骰子例子中的随机机制吗?我分享了一个公平的骰子以相同的比例出现每个结果的原因,因为小的变化——比我们用精细的运动技能所能控制的更小——会导致不同的结果。我们可以证明,用多一点的力或者不同的方向,会把一个会导致 1 的投掷变成一个会导致 2 的投掷。不幸的是,像经典力学那样一致的系统无法完美地预测业务成果。然而,我们可以试着想象我们可以做些什么来增加我们完成 Megacorp 销售的机会,并利用它来帮助未来的销售。当人们做假设分析时,他们总是这样做:可以想象首席执行官在想“如果我亲自回答了 Megacorp 关于我们服务的问题”或“我想知道如果我们给他们折扣会发生什么,因为他们会是一个令人印象深刻的客户。”我们需要明白,这些行为都不能保证销售,但它们可以增加销售的几率,应用多元宇宙理论,我们可以想象将销售失败的宇宙翻转到销售成功的宇宙。在下图中,我展示了 Normalcorp 客户的情况,该客户最初有 50%的销售机会,因为从 50%开始增加更容易看到。

图表由作者提供

我希望使用多元宇宙理论查看事件概率有助于缩小理解统计课程中常用的简单概率(例如,掷硬币、掷骰子或从一副牌中抽出卡片)和现实世界中复杂概率(例如,完成销售的概率、将用户转化为付费订阅计划的可能性)之间的差距。对于通过多元宇宙思考概率的一些有趣探索,我会推荐社区的补救混沌理论集(以及后续引用它的集),其中一个骰子滚动创建了多个时间线,以及所有的瑞克和莫蒂。自己尝试一下,与他人分享和讨论这个想法——包括我,我会尽最大努力回应这里或推特上的评论,看看它是否有助于理解复杂的现实世界现象,并使决策更加理性。

应对商业和数据科学中的不确定性

原文:https://towardsdatascience.com/grappling-with-uncertainty-in-business-and-data-science-962119805fb3?source=collection_archive---------86-----------------------

如何将数据科学原理应用于更好的商业决策

Javier Allegue Barros 在 Unsplash 上拍摄的照片

数据和数据科学在商业中的作用

在我的职业生涯中,我一直着迷于决策以及如何帮助组织做出更好的决策。这个问题中存在人的因素,这是心理学家、组织行为学家和领导力专家研究的难题之一。另一个难题是使用数据为决策提供信息的实践。

“数据驱动的决策”是我经常听到的一个短语,用来描述一个组织的文化或个人偏好的领导风格。对我来说,说一个组织是“数据驱动的”的缺陷是,数据被认为是真理的来源,可以使决策清晰明了。我不同意这个观点。其实我相信数据是善变的;数据可以很容易地被操纵以适应任何故事,所以更多的数据往往会混淆决策。那么,数据有什么帮助呢?

我相信对数据的深思熟虑的使用是我们接近真相的最好方法。数据可以帮助我们将广阔的可能性世界缩小为可能的真理,并对不同真理的可能性进行细致入微的观察。数据帮助通知 我们的决策;它不能替我们做决定。

为什么我们关心不确定性?

每项业务都是建立在一系列决策之上的:我应该在哪里开店?我应该销售这个产品吗?我应该如何给这个产品定价?我应该何时订购更多库存?我应该雇用这个候选人吗?这些决定是重要的,不仅关系到企业的成功,也关系到企业员工的福祉。做出这些决策的关键是理解决策对我们感兴趣的结果的影响,是更高的利润、更少的产品浪费还是更健康的团队。挑战在于,真相永远不会像预测的那样。以我的经验来看,这通常会导致对预测模型和数据的不信任。

照片由 Riho Kroll 在 Unsplash 拍摄

经过深思熟虑的解释和分析,数据可以帮助我们理解不确定性。仅仅因为一个预测不完全正确,我们不应该抛弃整个过程。当解释和分析得好的时候,我们可以使用数据以微妙的方式来思考未来的结果,这不仅仅是给我们一个预测,而是一个范围或多个预测。我们可以确定什么样的结果是可能的 以及这些结果有多合理 。举个例子,如果我考虑买一辆车,我不会相信这种说法,即这辆车会在 5 年后抛锚。我认为,在最初的 3 年内,有 30%的失败几率,在第 4 年和第 5 年有 20%的失败几率。将这些概率与我正在考虑的另一款车型的概率进行比较,可以为我提供有用且可信的信息,帮助我做出决定。

试图理解一系列可能结果的概念对我们大多数人来说并不陌生。我们中的许多人很自然地这样做,寻找定性和轶事信息来帮助我们做决定。当考虑买车时,我们会在网上搜索评论,并与朋友和家人谈论他们的经历。当涉及到组织环境中的决策制定时,我们需要形式化不确定性的度量。我们可以通过熟练地将定量技术与我们的直觉相结合来做出重要的决定。

揭开不确定性的神秘面纱——后续系列文章

在接下来的一系列博客文章中,我将概述帮助我们更好地理解不确定性的分析技术。技术范围从建模场景的业务分析师工具包到利用统计技术估计不确定性的数据科学家工具包。

许多组织已经有了在不同的场景下测试他们的决策以做出重要决策的经验,尽管有时是零星的。改善决策的下一步是系统地使用统计技术来估计不确定性。做得好的组织利用他们对不确定性的更好理解,熟练地权衡风险,以便做出更明智的决策,并为一系列可能的结果做好准备。它们还使组织的所有级别能够使用数据及其细微差别为自己做出决策,从而支持共同的使命。

作为一个在接触数据科学中更严格的分析技术之前就开始了管理咨询职业生涯的人,我理解抛弃统计技术的本能。我以前分享过这些信念,统计学太死板,无法应用于现实世界,太复杂,无法向决策者解释,当数据有限时,它不起作用。在过去一年的学习和工作中,我发现这些信念是没有根据的,尤其是基于模拟的技术,在今天的计算能力下已经成为可能。在接下来的几个星期里,我希望能让你相信这一点。

从社交媒体分析角度看 QAnon 阴谋论

原文:https://towardsdatascience.com/grassroots-or-influencer-driven-a-social-network-analysis-of-the-qanon-conspiracy-theory-f99617f8454d?source=collection_archive---------33-----------------------

由德克萨斯州奥斯汀西湖高中的阿迪特·巴鲁阿 & 约什·巴鲁阿撰写。

**卡农是一种草根现象,还是主要由少数有影响力的人推动?**要被认为是一个有影响力的人,用户必须从网络中的其他人那里获得大量关注,这可以在 Twitterverse 中以用户收到的转发、回复和提及的份额来衡量。通过来自 1 万名 QAnon 支持者的推文,我们使用社交网络分析来表明 QAnon 在很大程度上是基于影响者的;相对来说,一小部分用户吸引了大部分注意力,大多数 QAnon 支持者重复影响者所说的话。尽管特朗普总统不使用受欢迎的 QAnon 标签发推文,但@realDonaldTrump 的提及率在 QAnon 网络中名列前五。因此,他可以被描述为一个被动的影响者。在 QAnon 网络中,被不同标签提及的用户中,@realDonaldTrump 遥遥领先排名第一。当我们结合这两种方法来衡量关注度时,特朗普总统仍然是 QAnon 网络中的头号(被动)影响者。

一个现象是由草根还是由有影响力的人驱动有关系吗?草根运动是指大多数参与者的重要性虽小,但几乎同等重要的运动。相比之下,在影响者驱动的运动中,少数参与者非常重要,他们推动了大部分行动,而其他人基本上无足轻重。由于不依赖于少数主要参与者,草根运动通常比基于影响者的运动更有弹性或持久力。相比之下,如果高层影响者因为这样或那样的原因离开,基于影响者的现象可能会失败。当然,运动的性质会随着时间而改变。例如,有人认为#MeToo 最初是由影响者驱动的,但随着时间的推移变得更加草根。相比之下,我们对 BLM 数据的初步分析(未在此展示)表明,这更像是一场草根推动的运动。现在判断 QAnon 是否会最终成为一种草根现象还为时过早。

卡农阴谋论

如果你正在阅读我们的文章,你可能已经知道 QAnon 是什么了。以防你太忙而无法关注这一相对较新的发展,这是维基百科对这一现象的定义:

QAnon 是一个极右翼的阴谋论,声称一个所谓的“深层国家”针对唐纳德·特朗普总统及其支持者的秘密阴谋。….这个理论始于 2017 年 10 月“Q”在匿名 imageboard 4chan 上的一篇帖子,他可能是一个美国人,但很可能成为一群人。q 声称能够接触到涉及特朗普政府及其在美国的对手的机密信息。”

《纽约时报》报道称,QAnon 最近变得更加主流,出现在许多社交网络的显著位置,发布了关于疫情、BLM 和疫苗的帖子。多家媒体和事实核查人员报告称,QAnon 散布了关于这些和其他话题的错误信息。一些共和党国会候选人在推特上支持卡农,特朗普总统也转发了这些推特。

通过社交网络分析了解卡侬

为了使用社会网络分析来检查 QAnon,我们使用以下步骤:

1.收集带有 QAnon 标签的推文。

2.执行情绪分析,丢弃对 QAnon 有负面情绪的推文(因为我们想要分析 QAnon 支持者的样本网络)。

3.从推文中创建 QAnon 支持者的定向关注网络。

4.计算节点(用户)的网络中心性指标。

5.可视化网络并显示突出的节点。

6.删除 10%和 15%的顶级节点,并检查没有它们时网络的表现。

我们在我们的一个 GitHub 存储库中提供了用于创建注意力网络、中心性度量计算以及可视化的 python 脚本:https://GitHub . com/adib 2002/Social-Network-Analysis-Python-Scripts

我们不提供通过 Twitter API 访问 tweets 的脚本。已经有多篇文章在 Medium 上发表了关于这个主题的代码,这里有一篇很优秀的发表在 TDS 上:https://towardsdatascience . com/Twitter-data-collection-tutorial-using-python-3267d 7 CFA 93 e

我们收集了使用一个或多个热门 QAnon 标签的推文:#qanon、#q、#savethechildren、#thegreatawakening、#wwg、#qarmy 等。通过反复使用 Twitter API,我们获得了超过 1 万名使用这些 QAnon 标签的 Twitter 用户的推文。为了确保我们分析来自 QAnon 支持者的推文,我们对每条推文进行了 VADER 情绪分析,并丢弃了对 QAnon 有负面情绪的推文。

接下来,我们通过以下方式创建了 QAnon 支持者的定向网络。如果一个用户@abc 转发、回复或提及另一个用户@xyz,那么这两个用户由一个从@abc 到@xyz 的箭头连接。箭头表示@xyz 正受到@abc 的关注。用户的原始推文被表示为自循环,由带箭头的圆圈示出。这是一些来自我们数据的真实推文。出于隐私原因,发送推文的人和转发、提及或回复推文的人的用户 id 已被替换为虚构的 id。

表 1:推文、转发、提及和回复

从 tweets 中,我们得到了两列,如表 2 所示。

表 2:创建注意力网络的数据

根据表 2 中的数据,我们创建了如图 1 所示的网络。

图 1:注意力网络

虽然有人建议用关注者的数量来衡量影响力,但拥有大量关注者并不能保证你的推文获得大量转发,或者你会在其他人的推文中获得大量提及。事实上,在我们的数据中,关注者数量和提及次数之间的相关性是 0.51,关注者数量和转发次数之间的相关性是 0.52,这当然不是很高。通过使用转发、提及和回复,我们捕捉到了每个节点从其他节点获得的真正关注。

虽然我们已经在https://github . com/adib 2002/Social-Network-Analysis-Python-Scripts分享了我们用于此分析的 Python 脚本,但我们发现,对于可视化部分,像 node XL(Excel 中的模板)和 Gephi 这样的免费网络分析工具比 Python 中的 networkx 提供了更多的灵活性和更好的性能。所以我们最终使用 NodeXL 来实现下面的可视化。如果您想尝试我们的分析,我们建议您使用我们的 Python 代码来生成网络并计算中心性度量,然后使用 NodeXL 或 Gephi 进行可视化。

谁是关系网中的重要人物?

在网络中,并非每个人都生来平等!为了理解一个节点有多重要,我们可以使用多种测量方法,这些方法被称为网络中心性度量。在我们的分析中,我们使用其中的两个,入度和中间性,尽管还有其他的,如出度、接近度和特征向量中心性。由于我们正在分析一个注意力网络,我们的重点是找到那些获得大部分注意力的个体。

节点(我们上下文中的用户)的入度(In-degree)是进入节点的箭头数量,其中箭头可以表示转发、回复或提及。具有高入度的节点意味着它正得到网络中其他节点的大量关注。在图 1 中,@xyz 在四个用户中得到最高的关注。可以区分转发、回复和提及,因为转发可以被认为是三种类型中最重要的。然而,为了简单起见,我们认为它们同等重要。

节点的介数是一个分数,用来衡量它在连接网络最远部分时的重要性。考虑节点介数的另一种方式是,如果没有这个节点,整个网络中的节点相互连接的难度有多大。在我们的注意力网络中,一个具有高介数分数的用户意味着该用户不仅得到了大量的关注,而且这种关注来自于整个网络。

入度和介数衡量的是同一个东西吗?不完全是。高的入度分数可能是由于来自网络的一部分的关注,而中间性考虑了整个网络。因此,这两个指标并不完全相关,我们将在下面的分析中看到这一点。

QA non 网络中的影响者

关于 QAnon 受影响者驱动的第一个线索来自用户的介数分数的分布,如图 2 所示。

图 QAnon 网络中介数分数的分布

图 2 中的图表告诉我们的是,QAnon 网络中的一小部分节点得到了整个网络的大部分关注,而绝大多数节点几乎没有得到任何关注。特朗普总统的中间性得分最高,比第二高的得分大 2 倍以上;尽管我们的数据中没有他自己的推文,但@realDonaldTrump 正被整个网络的 QAnon 支持者用各种各样的标签提到。从图 3 中 QAnon 网络的可视化可以得出相同的结论。

图 3: QAnon 网络(10k 用户),更重要的节点以红色和更大的尺寸显示

在图 3 中,根据介数中心性,节点颜色从红色变为绿色。我们不得不使用介数分数的对数来将节点颜色从红色逐渐变为绿色;介数分数下降如此之快,以至于使用原始分数会显示特朗普总统是网络中唯一的红色节点!实心黑色背景代表用户之间的定向链接或箭头。节点的大小随介数中心性而变化。我们还使用了一个名为节点不透明度的特性,它使一些节点比其他节点更明显。我们选择入度作为标准,入度越高的节点显示得越明显。

虽然图 3 讲述了与图 2 相同的故事,但是如果我们使用入度而不是介数,我们的结论会改变吗?在 QAnon 网络中,入度和介数之间存在 0.69 的相关性。高,但不是超高!让我们看看图 4 中的 in-degree 分数分布。

图 QAnon 网络中的学位分数分布

入度分布与介数分布几乎相同,这也反映在下面图 5 的网络图中;只有少数节点的入度得分高于 0。特朗普总统的学位分数将他排在第五位,这解释了为什么他在图 5 中显示为橙色,而不是红色。

图 5: QAnon 网络突出显示了具有最高学位分数的用户

如果我们去掉最受关注的人,会发生什么?

我们很好奇,如果我们移除 10%或 15%具有最高介数分数的用户,QAnon 网络会发生什么变化。

图 6:删除了 10%和 15%顶部节点的示例 QAnon 网络

当我们将图 6 所示的网络与图 3 所示的完整网络进行比较时,我们会发现一些主要差异。图 6 中的红色节点(吸引注意力的节点)不见了,图 3 中黑色背景代表的箭头也不见了。虽然图 3 中 90%和 85%的用户仍然分别在图 6a 和 6b 的两个网络中,但是如果没有前 10–15%的高介数用户,网络上几乎没有任何活动。基本上,卡侬的注意力网络已经崩溃了!

如果我们使用不同的注意力测量方法呢?

即使我们结合入度和介数来衡量注意力,我们也会得到相同的结果。首先,我们为这些度量创建了标准化分数,其中节点的标准化分数是网络中的入度或介数分数/最高入度或介数分数。接下来,我们尝试了一个注意力测量=标准化的程度内得分+标准化的中间得分。结果是一样的,因为这种综合的注意力测量与入度有 95%的相关性,与中间值有 88%的相关性。特朗普总统仍然是最重要的关注焦点,网络中前 25 名甚至 50 名用户的名单几乎没有变化。

外卖

一小部分人在 QAnon 网络中获得了最大的关注,这表明大多数 QAnon 支持者只是重复这些顶级用户在推特上发布的内容,同时用各种标签吸引特朗普总统的注意。随着时间的推移,这种现象是否会演变成一场更加草根化的运动,还有待观察。我们进行的分析可以在不同的时间点重复进行,以了解 QAnon 网络的演变。

重力和电荷:吸引和排斥

原文:https://towardsdatascience.com/gravity-and-electric-charges-attraction-and-repulsion-b2b5f8f91caa?source=collection_archive---------22-----------------------

为什么引力总是相互吸引,而电荷却相互排斥

图片由皮克斯巴伊的加里克·巴尔塞吉安拍摄

许多读过《时间简史》一书的人可能记得有一章叫做“基本粒子和自然力”,霍金在其中写道,“在量子力学中,相互作用力都被认为是由粒子携带的……”。

在这篇文章中,我将试图解释他这句话大概是什么意思。我将描述相互作用与粒子交换关联背后的推理,粒子交换是量子场论(QFT)的一个普遍特征。例如,粒子间的电磁力在 QFT 被解释为所谓的“虚光子”交换的结果

图 1:该图显示了电子之间通过虚拟光子的相互作用。波浪线代表虚拟光子的传播(源)。

什么是量子场论?

量子场论 (QFT)是结合经典场论(包括电磁学和引力等领域)、狭义相对论、量子力学的框架。QFT 主要用于粒子物理学,但物理学的许多其他分支使用基于它的技术。在 QFT,粒子是它们相应的量子场的激发或量子。

图 2:迈克尔·法拉第(来源)和他的一个演示感应的实验(来源)。

大概第一次认真考虑磁场是在英国科学家 T4 用电和磁做了几个实验的时候。由于法拉第的直觉,即电和磁的定律可以用贯穿空间和时间的场来表述,场的概念从那时起统治了物理学,并取代了基于力的牛顿程序。

图 3:正负电荷周围电场示意图(来源)。

大概我们可以考虑的最简单的场是经典实标量场,由函数 φ ( xt 描述,其中 x 是空间坐标, t 是时间。该场满足所谓的克莱因-戈登方程 (KG):

方程 1:大质量标量场φ( x ,t)的 Klein-Gordon 方程。

KG 方程解是唯一确定的,只要

等式 2:标量场φ( x ,t)的 Klein-Gordon 等式的初始条件。

初始(或边界)条件是已知的。

图 4:标量场 φ ( xt )追踪一个时空曲面(源)。

在没有外力的情况下,量子场论中的基本对象是下面的路径积分称为真空到真空跃迁振幅

等式 3:QFT 中的泛函积分或真空到真空的转换振幅。

Z 的被积函数的指数中的拉格朗日密度使用

等式 4:使用 V(φ)和δS/δφ=0 的选择,得到 KG 等式。

图 5:展示最速下降法的动画(来源)。

并应用动作原理,在这种情况下变成:

方程式 5:作用原理适用于自由重公斤场的情况。

给出等式 1 中给出的 KG 方程。标量粒子的一个例子是希格斯玻色子。

图 6:模拟粒子碰撞产生希格斯玻色子,希格斯玻色子是 QFT 著名的预言(来源)。

我们注意到 QFT 的真空远非平静,而是充满了量子涨落(见图 5)。能量-时间不确定性原理指出人们无法确定只存在短暂时间的量子态的能量。在数学上,这可以表示为

事实上,真空能量剧烈波动,允许产生成对的(粒子-反粒子)虚粒子。

图 7:真空波动是一个空间区域中能量数量的短暂而强烈的变化。它们允许创建粒子-反粒子虚拟对粒子(来源)。

来源

使用来源语言的 QFT 公式是由美国理论物理学家和诺贝尔奖获得者 T2·朱利安·施温格发明的。

图 8:美国理论物理学家、诺奖得主朱利安·施温格,20 世纪最伟大的物理学家之一,以量子电动力学方面的工作而闻名(来源)。

考虑一个粒子,例如,在碰撞后产生,然后被探测器摧毁或湮灭。人们可以把创造和毁灭描述为源和汇。源出现在乘以理论的量子场的行动中。他们描述了真空是如何被扰乱的。由于我们目前正在研究量子标量场,所以动作中出现了术语J(x)φ(x)。存在辐射源时,真空到真空的转换 Z ( J )振幅由下式给出:

等式 6:在存在源 J(φ(x))的情况下,QFT 中的泛函积分(或真空-真空跃迁振幅)。

图 9:存在源时真空-真空转换振幅 Z(J)的表示(基于来自源的图表)。

顺着莱德、齐、这个环节,让我们设置两个源,一个用于创建粒子(源),一个用于湮灭粒子(汇)。方程式中的积分。3 和情商。因为它们是高斯型的。它们只是简单的高斯积分的复杂版本:

****

图 10:高斯分布图及其下方的区域(来源)。

结果可以写成:

方程式 7:方程式的积分。1.

对于自由标量理论,

等式 8:等式 8 给出的泛函 Z(J)中的指数 W(J)。2.

其中指数中的 D ( xy)=D(x-y)函数为:

方程 9:自由传播子写成动量空间传播子的傅立叶变换。

传播子 D ( x,y )等于场中一个扰动从 y 传播到 x 的振幅。将两个源场写成傅立叶变换,并代入等式。8 给出(详见 Zee 或此链接):

等式 10:根据 J(x)的傅立叶变换写出的指数 W(J)。

在 Zee 或这个环节之后,我们可以为我们现在的目的选择一个方便的 J ( x )。在这种情况下,设 J ( x )为和:

等式 11:选择 J(x)作为源和汇的和。

集中在两个时空区域 1 和 2,如图 7 所示。傅里叶变换两者并代入等式。我们将得到四个术语。由于我们对相互作用的研究感兴趣,我们将忽略自我相互作用的术语,如

等式 12:这些项将被忽略,因为它们代表自相互作用。

并保留其中两项,即:

等式 13:等式中的项。10 涉及不同来源之间的相互作用。

现在,如果我们研究 Eq。11 我们看到, W ( J )变大的唯一方式是两件事同时发生:

  • 等式中的两个术语。11 强重叠:如果其中一个为零,而另一个很大,则 JJ- 贡献很小。
  • 来自 Eq。11、有重叠处的 k 的值必须接近 m (回想一下ε → 0)。等价地,重叠一定发生在 k - m 几乎消失的时候。导致尖峰。具体来说,在 k = m ,这意味着粒子的能量动量得到满足,即所谓的“质量壳层”条件,我们有一个大尖峰,我们的理论中有一个大质量粒子。积分涵盖了动量 k,的所有可能值,而不仅仅是质量壳动量。这些其他的ks就是虚粒子。

让我们再一次遵循 Zee T1 的理论,将我们目前的理论解释如下:区域 1 扰乱了磁场,将这个扰动(比方说,一个质量为 T2 m T3 的粒子)送到时空中的区域 2。为了便于计算,需要源有明确的数学形式。更简单的可能性是选择三个空间维度中的 J s 为狄拉克δ函数:

等式 14:源被选择为狄拉克δ函数。Js 需要一个明确定义的数学形式来执行计算。

图 Dirac delta 函数作为零中心正态分布序列的极限(来源)。

这些源与时间无关,但它们会重叠。代入等式。12 进 W ( J )我们得到(经过一些简单的代数步骤):

方程式 15:使用方程式的结果。并执行一些例行的积分。时间 T 是相互作用的时间。相互作用的能量由 e 给出。

**这里 T 是源相互作用的间隔, E 是相互作用的源之间的相互作用能量。注意能量是负的。这是极其重要的,因为它暗示着源由于耦合到场 φ而相互吸引。用复分析求解积分我们发现

等式 16:在 k 上积分后,源相互作用的相互作用能量。

图 13:耦合费米子场和介子场的汤川相互作用。

我们看到,在距离 1/ m 处,源之间的吸引力以指数速度衰减到零。这是一个基本的结果,因为它意味着力的范围取决于由场φ描述的粒子的质量。

我们刚刚发现了一个深刻的基本结果:力的范围取决于交换粒子的质量

**还要注意,质量越接近,能量越低。于是 / 博士0。这种势能是由日本理论物理学家和诺贝尔奖获得者汤川秀树在 1934 年提出的,用来解释原子核中核子之间由于耦合到类似 φ的磁场而产生的吸引力。后者现在被称为π介子或π介子,于 1947 年通过实验发现。

**

图 14:几个 m 值的汤川电位比较( 来源 )。**

**这个结果(以及后面的结果)的重要性怎么强调都不为过。引用 Zee 😗*

"粒子的交换可以产生一种力,这是物理学中最深刻的概念性进展之一。"—阿·齐

为什么库仑力对同性电荷是排斥的?

QFT 的另一个深刻的结果是力是吸引的还是排斥的,与在相应的相互作用中交换的粒子的自旋之间的关系。如果一个场的自旋为 1,它会在旋转组下转换为一个向量。在这种情况下,该字段最简单的可能性是一个四向量(上一节中的标量字段将“获得一个索引”):

等式 17:新的场一个自旋为 1 的调解电磁力。

然而,由于自旋为 1 的粒子只有三个自由度,对应于其静止坐标系中的三个偏振方向

方程 18:静止坐标系中自旋为 1 的大质量粒子的极化矢量。

图 15:大质量自旋 1 光子的三个偏振向量。

必须存在一个条件来限制的独立组件的数量。一个简单的条件是洛伦兹协变是:

等式 19:四向量 A 上的条件将 A 的独立分量的数量从四个限制为三个。

出于超出本文范围的原因(参见此链接、齐或科尔曼了解更多细节),光子将被赋予一个小质量 m、,在计算结束时可以被取为零。

同样,因为静止坐标系中的动量向量

方程 20:静止坐标系中的动量矢量。

将遵守以下条件:

等式 21:由 k 矢量和极化矢量 ε 满足的条件。

根据洛伦兹协变性,这个条件在所有的框架中都必须成立(换句话说,它对移动的大质量光子也必须成立)。

现在,在标量场的情况下,要在对应于J(x)φ(x)的 A 的拉格朗日函数中包含源项,源也必须是一个四维向量**

等式 22:为了在拉格朗日中包括源项,源也必须是四个向量。

图 16:虚质量光子的源(产生虚光子的地方)和汇(吸收虚光子的地方)(基于来自源的图表)。

拉格朗日中的项是:

方程 23:大规模电磁场的拉格朗日中的源项。

在这种情况下,源称为电流(或四电流)。

动量为k且极化为a的粒子被产生(在源处)并被吸收(在汇处)的概率正比于:

等式 24:动量为 k 且极化为 a 的粒子在源和汇被产生和吸收的概率。

对( a )指数求和(对三个偏振),我们获得从源到接收器的传播的总概率。从标量情况下的等式。对于大质量自旋为 0 的场,我们首先注意到极点的剩余是粒子的一种属性。新的传播子现在将有两个洛伦兹指数 μν ,它将变成:

方程 25:大质量光子的传播子。与标量场情况相比,新的传播子获得了两个指数μ和ν。

下一步是将偏振乘积的和作为具有两个指数的对象写入,这两个指数将由(减) G 表示。如 Zee 所述,洛伦兹协方差将限制为以下项的组合(根据 Zee 的讲座):**

等式 26:出现在传播算子中的张量

现在,把两边的动量相乘,我们得到:

而是来自 Eqs。在图 20 和 25 中,左手边是零,这意味着:

转到休息帧,设置 μ = ν =1 我们发现整体符号是-1。人们于是有了:

等式 27:电磁情况下的 W(J)。

如果我们记得电流是守恒的,我们必须:

方程式 28:电磁学中的电流守恒。

如果看情商。26,分子中有以下第一项:

等式 29:电流守恒消除了分子中的一项。结果是 W(J ),其符号取决于电荷的符号。

你可以看到,与汤川势相反,两个符号相等的电荷 J ⁰( x )会相互排斥(因为光子没有质量,所以质量下降了)。

我们刚刚发现了一个深刻的结果:两个符号相等的电荷会互相排斥。

****

图 17:称为太阳等离子体磁重联的电磁现象的一个例子。这种现象导致了太阳耀斑(来源)。****

大众为什么吸引?

重力由一个巨大的自旋为 2 的粒子调节,5 度的偏振由无迹张量表示:

方程 30:大质量自旋 2 粒子的极化。

遵循赋予我们情商的逻辑。26 对于大质量自旋为 2 的粒子,我们得到以下传播子:

方程式 31:引力场的传播子。

这给出了:

等式 32:重力的 W(J)。

将 T 的指数设置为 00,我们获得能量密度。相应的 W ( T )则为:

等式 33:W(T)的负号表示引力吸引。

请注意,现在总的迹象是。这意味着质量相互吸引,这与我们在上一节看到的同性电荷相反。

我们在这个分析中看到的确实很吸引人。根据在相互作用中交换的粒子的自旋,人们可以确定力是排斥的还是吸引的。这些结果有许多含义,例如在(来自 Zee 的例子):

  • 宇宙中结构的形成:没有等式中的负号。33、宇宙中的结构不会形成!
  • 相互吸引的核力点燃了恒星,当它们支配质子间的排斥电力(由虚光子介导)时,它们形成了我们在自然界中看到的各种原子核
  • 同性相斥的电荷允许原子的形成。

我的 Github 和个人网站 www.marcotavora.me 有一些其他有趣的材料,既有关于物理的,也有关于数学、数据科学和金融等其他主题的。看看他们!

伟大的数据科学和机器学习播客

原文:https://towardsdatascience.com/great-data-science-and-machine-learning-podcasts-211fefb80f07?source=collection_archive---------45-----------------------

教育、职业发展和研究

汤米·洛佩兹在的照片

美国劳工统计局估计,到 2026 年,将新增 1150 万个数据科学工作岗位。这一预测表明,随着行业对这些职位的高需求,数据科学领域将继续快速增长。对于那些刚刚开始涉足该领域或考虑从另一个行业转型的人来说,播客对于发展对工业和研究中的数据科学和机器学习的理解非常有用。在这篇文章中,我将讨论我最喜欢的三个播客,它们讨论了研究和行业中的数据科学领域。这些播客也为那些刚刚起步的人提供了学习资源。

我们开始吧!

超级数据科学

超级数据科学播客由数据科学教练兼企业家基里尔·叶列缅科主持。SuperDataScience 介绍了许多领先的数据科学家和数据分析师,他们为如何在数据科学领域建立成功的职业生涯提供了见解。对于任何想更好地了解这个行业并继续在这个领域进行自我教育的人来说,这个播客是必不可少的。我最喜欢的一个是SDS 391:John Elder 的数据科学营火故事。在这一集里,Kirill 和 John Elder 讨论了微积分、统计和重采样等数学概念。他们还讨论了领域知识的重要性、关于神经网络的想法、关于数据科学未来的想法等等。我也很喜欢 SDS 373: TensorFlow 和面向开发者的 AI 学习。在这里,Kirill 与 Laurence Moroney 坐下来讨论 TensorFlow 以及开发人员如何使用它来推进他们在数据科学领域的职业生涯。我还推荐 SDS 379:漩涡、混乱和伤害:指引你的数据科学职业道路。在这里,Kirill 与 Christopher Bishop 坐在一起,他概述了一个框架,以帮助那些开始从事数据科学的人确定他们在该领域的热情。

莱克斯·弗里德曼播客

在这段播客中,麻省理工学院人工智能研究员 Lex Fridman 谈论了人工智能、科学、技术等话题。具体来说,大部分内容都围绕着深度学习、人工智能机器人、计算机视觉、人工通用智能、计算机科学和神经科学。与 SuperDataScience 播客相反,该播客更侧重于广泛的概念,如智力和意识。对于那些对机器学习方法在人工智能系统中的广泛应用感兴趣的人以及那些对大脑如何工作感兴趣的人来说,这是一个很好的播客。我强烈推荐*# 106——Matt Botvinick:神经科学,以及 DeepMind 的 AI*,在那里弗里德曼与 Matt Botvinick 坐下来讨论大脑的神经元机制,因为它与学习有关。我还推荐*# 101——约沙·巴赫:人工意识和现实的本质*,弗里德曼和巴赫在这里讨论了人类大脑的运作、自主机器人、存在的不连续性以及许多更有趣的哲学思考。最后推荐 #81 — Anca Dragan:人机交互与奖励工程。在本期播客中,Fridman 和 Anca 讨论了世界上作为代理的机器人如何在导航物体和人的同时执行任务。

数据怀疑论者

Kyle Polich 主持的数据怀疑论者播客主要围绕数据科学、统计学、机器学习和人工智能进行采访和讨论。这个播客更侧重于研究,其中许多集涉及对机器学习领域最近论文的讨论。我推荐医疗保健中的可解释人工智能,Polich 与 Jayaraman Thiagarajan 坐下来讨论他的论文校准医疗保健人工智能:走向可靠和可解释的深度预测模型。在本播客中,Polich 和 Thiagarajan 讨论了向医生解释医疗保健中的模型预测的形式化过程。我还喜欢自动驾驶汽车和行人,Polich 和 Arash Kalatian 坐下来讨论如何使用虚拟现实和可解释的深度学习解码行人和自动车辆的交互。最后,我推荐对抗性解释,Polich 与 Walt Woods 坐下来讨论他的论文理解图像分类决策和改进神经网络鲁棒性的对抗性解释。在这里,Polich 和 Woods 谈到了对抗性解释的概念,它涉及到神经网络中间层的热图。

结论

总之,在这篇文章中,我们讨论了三个讨论机器学习和数据科学的伟大播客。首先,我们讨论了超级数据科学(SuperDataScience)公司(T1),该公司专注于为初露头角的数据科学家提供职业建议。接下来我们谈论了的莱克斯·弗里德曼播客,它解决了许多关于智力和意识的有趣问题。最后,我们讨论了数据怀疑论者,它围绕机器学习领域的前沿研究展开了许多讨论。我希望你觉得这篇文章有趣/有用。感谢您的阅读!

用于访问公共数据的优秀 Python 库

原文:https://towardsdatascience.com/great-python-libraries-for-accessing-public-data-adef88073be?source=collection_archive---------42-----------------------

使用 Python 访问公共数据

由像素上的摄影记者拍摄的照片

有许多优秀的 API 允许用户访问公共数据。这些数据可用于为金融模型生成信号,分析公众对特定主题的情绪,并发现公众行为的趋势。在这篇文章中,我将简要讨论两个允许你访问公共数据的 python 库。具体来说,我将讨论 Tweepy 和 Pytrends。

使用 Tweepy 获取公共推文

Tweepy 是一个 python 库,允许您通过 Twitter API 访问公共 tweets。创建 twitter 开发人员帐户和应用程序后,您可以使用 Tweepy 来获取包含您指定的关键字的 tweets。例如,如果你有兴趣了解公众对当前选举状况的看法,你可以调出最近所有关键词为“选举”的推文。Tweepy 对象返回 tweet 文本,可用于创建情感评分。除了政治之外,这还可以用于各种垂直行业,包括医疗保健、金融、零售、娱乐等。我之前写的一篇文章, 患者对药品的情绪来自推特 ,用推特分析了大众对热门药品的公众情绪。在另一篇文章Python中关于小丑(2019 电影)的推文分析中,我分析了 2019 电影*小丑的公众情绪。*我鼓励你去看看这些教程,自己进行一些数据整理和分析。申请 Twitter 开发者账户和创建 Twitter 应用程序的步骤在这里列出。tweepy 的文档可以在这里找到。

使用 Pytrends 提取趋势主题数据

Pytrends 是一个 python 库,允许您访问表示某个关键字或主题在 Google 上被搜索的次数的数据。与 Tweepy 类似,您可以提供关键字和位置信息,Pytrends 对象将返回一个表示规范化 Google 搜索值的时间序列索引。这在零售和金融领域也有应用,但查看不同地区的关键词趋势也很有趣。关于 Pytrends 的友好介绍,请查看 Python 中的 冠状病毒 Google Trends和 Python 中的 使用 Google Trends API 选择万圣节服装 。Pytrends 的文档可以在这里找到。

结论

总之,在这篇文章中,我们讨论了两个可以用来提取公共数据的 python 库。Tweepy 库非常适合从 Twitter 中提取推文,进行情感分析和趋势分析。Pytrends 库非常适合分析全球特定时间段和地区的 Google 趋势主题。我希望你觉得这篇文章很有趣。感谢您的阅读!

学习机器学习和深度学习的优质免费课程

原文:https://towardsdatascience.com/great-quality-free-courses-to-learn-machine-learning-and-deep-learning-1029048fd0fc?source=collection_archive---------4-----------------------

Bermix 工作室在 Unsplash 拍摄的照片

顶级大学高质量免费课程的链接

这是一个时髦的话题。机器学习是当今发展最快的领域。就业市场正在飞速发展。越来越多的大学开设新课程。这么多免费资源乱飞。越来越多的人对学习机器学习感兴趣。

它同时是好的和坏的。对于新的学习者来说几乎是势不可挡的。很难理解从哪里开始,学什么,如何获得所需的技能。

我想先警告一件事。不要把钱浪费在任何训练营上,那些训练营告诉你他们会在六个月内教会你编程、统计学、数据分析、机器学习、数据库查询。我甚至知道他们承诺学生在 12 周内完成或准备好的新兵训练营。千万不要在他们身上浪费钱。因为如果你不是超人或女超人,这是不可能的。这里有一篇关于它的详细文章:

[## 想在 12 周内成为数据科学家?

花钱前再想一想

towardsdatascience.com](/want-to-become-a-data-scientist-in-12-weeks-3926d8eacee2)

如果你有工程、数学、物理、统计或任何其他技术领域的本科学位,你就有优势。但是现在有很多图书馆。你不需要理解背后所有的数学。你仍然可以使用那些算法,执行机器学习和深度学习任务。

我将分享这两种课程的资源。有些会教你流行的库,有些课程是从头开始学习算法。

有许多数据科学家或工程师作为首席数据科学家工作,但不知道如何从头开发机器学习算法。他们使用图书馆。因此,学习库也是一项很好的时间投资。

另一方面,即使你没有数学或工程背景,如果你真的有兴趣从头开始学习开发机器学习,你仍然可以补充一些数学和统计课程。

机器学习和深度学习是数据科学非常有趣的一个方面。

因为数据科学家需要学习机器学习。还有机器学习工程师。其实这些角色都很混乱。在我的理解中,当数据科学家从事机器学习时,他们会与其他人交流,并帮助他们根据自己的工作做出决定。

但是机器学习工程师做机器学习项目,他们的目标是与机器交流。他们需要了解数据库查询、Rest APIs,并构建一个其他人可以使用的接口。

如果你打算成为一名数据科学家或机器学习工程师,核心的机器学习概念是相同的。

以下大部分课程来自 Coursera,你可以免费学习以下所有课程。您必须找到审计选项。如果你以前没有旁听过课程,这里有一个视频展示了如何在 Coursera 中旁听课程:

您可以根据自己的需要对以下每门课程进行多次审核。如果你不能在指定的时间内完成,你可以再次审计!

是不是很酷!

这里有一些免费的资源

我是 python 用户。所以我只能给出 Python 中机器学习的思路。如果你是一个完全的初学者,并且对 python 不是很了解,那么先练习一下 python 吧。这里是 Python 的一个专门化。通过大量的练习,它将教会你所有的 python 语法和结构:

[## Python 3 编程

由密歇根大学提供。这个专业教授 Python 3 的编程基础。我们会…

www.coursera.org](https://www.coursera.org/specializations/python-3-programming)

在那之后练习 python 变得更好。有几个很棒的平台给我们提供练习题。我用 l eetcode 和 checkio 来练习编程。在这些平台里,你可以看到别人的解决方案变得更好。还有很多其他平台可以练习编程:code wars、 CodeChef 是我经常听说的另外两个平台。

在学好编程之后,学习一些 python 的计算、数据操作、可视化库是个不错的主意。在你深入机器学习之前,它们是学习的基础。

Python 有强大的库,如 Numpy、Pandas、Matplotlib、Seaborn、Scipy 等,用于计算、数据操作、可视化和统计分析。Coursera 中有一个专业化系列,其中有两门课程是关于 Numpy、Pandas、Matplotlib、Seaborn、Scipy 的,第三门课程是关于应用机器学习的:

应用数据科学与 Python

本专业的应用机器学习课程不会教你从零开始开发算法。但是它会教你一些概念以及如何使用 python 中 scikit-learn 库中的这些算法。对于初学者来说,这是一个很好的开始。密歇根大学提供这一专业。该专业包含的五门课程是:

Python 中的数据科学简介

应用 Python 进行绘图、制图&数据表示

在 Python 中应用机器学习

在 Python 中应用文本挖掘

Python 中的应用社交网络分析

这门课有一些好的专题,会增加你的作品集。此外,每周都会给你一个笔记本,可以作为你未来工作的备忘单。他们在这门课程中提供的材料非常好。

机器学习专业化

这是另一种专业化。它有四道菜。

机器学习基础:案例研究方法

机器学习:回归

机器学习:分类

机器学习:聚类&检索

这些课程的伟大之处在于,这些课程将采用基于项目的方法,每周的作业都是不同的项目。结束时,你将有一个完整的投资组合来炫耀。华盛顿大学开设了这门课程。

CS50 用 Python 介绍人工智能

CS50 的课程通常质量很高。该课程由哈佛大学提供。你们知道,你们对哈佛的期望不会更低。顾名思义,这是一门入门课程。这门课会给你更多前两门课没有的机器学习的概念。如果你学了前面的课程,你将会学到更多的模型和概念,并且在你的投资组合中包含更多的项目。

本课程将涵盖图形搜索算法、对抗性搜索、知识表示、逻辑推理、概率论、贝叶斯网络、马尔可夫模型、约束满足、机器学习、强化学习、神经网络和自然语言处理。

吴恩达的机器学习

吴恩达教授因其分解机器学习概念的巨大能力而闻名。本课程由斯坦福大学提供。本课程与前三门课程不同。以上三门课教你如何使用 python 的库中内置的机器学习算法。

但是吴恩达教授会教你如何从头开始开发机器学习算法。所以,这比以前的课程要难多了。

但是如果你能完成它,它会给你很大的力量。这是一个长达 11 周的课程。但是你可以免费旁听这个课程,次数不限。本课程将教你从零开始开发线性回归、逻辑回归、神经网络、支持向量机、k 均值聚类、主成分分析、异常检测、推荐系统开发。

这门课可能有点不同的一点是,作业指令在 Matlab 中。但是如果你擅长 python,你可以把这些概念用 python 来实现。你可以在本页找到大部分用 python 完成的作业的链接:

[## 使用 Python 从零开始的多类分类算法:分步指南

本文介绍两种方法:梯度下降法和优化函数法

towardsdatascience.com](/multiclass-classification-algorithm-from-scratch-with-a-project-in-python-step-by-step-guide-485a83c79992)

我还在用 python 写剩余作业的教程,很快就会完成。

看起来很多啊!对吗?

但是学习机器学习库会更容易。在你学会使用一些算法后,你会更容易掌握。但是在吴恩达的课程中从头开始学习算法将会花费很多时间。

这些都是我想分享的关于机器学习的课程。这里有一些深度学习的课程。

深度学习。AI TensorFlow 开发者职业证书

这也是一种专业化。现在他们把它升级了,做成 Tensorflow 上的专业认证课程。本系列将教你如何在项目中使用 TensorFlow。这门课程没那么难。因为它没有教你如何从零开始开发深度学习算法。它将教你如何使用 TensorFlow 库。

Tensorflow 是深度学习的一个非常强大的工具。它将处理幕后所有的数学难题。你只需要安装它,调用库,并使用它。

这个专业将教你使用 TensorFlow 进行数值预测,自然语言处理,图像分类和时间序列预测。

这是该专业的四门课程:

面向人工智能、机器学习和深度学习的 TensorFlow 简介

tensor flow 中的卷积神经网络

tensor flow 中的自然语言处理

序列、时间序列和预测

这些课程都采用基于项目的方法。所以,学习是有趣的!

深度学习专业化

这是吴恩达教授的另一系列课程。如果你在尝试学习机器学习和深度学习,很难避开 Ng 教授。他是先驱者之一!

他把概念教得很清楚,教你详细开发算法。这门课会有点难,因为它是关于从零开始开发算法,并从其核心了解它。但如果你能完成它,这将是值得的。它包括以下课程:

神经网络和深度学习

改进深度神经网络:超参数调整、正则化和优化

构建机器学习项目

卷积神经网络

序列模式

结论

如果你能把时间奉献给这些课程,你就是机器学习和深度学习的行家。还有很多其他的库和主题。因为机器学习是一个广阔的领域,而且每天都在增长。但是如果你有一个坚实的基础,你将很快学会任何其他新的库。

你必须对此保持开放的态度。这是一个学习永无止境的领域。不管你学了多少,明天都会有新的东西出现。

最后一个建议是,不要急于学习任何对你来说新的东西。先掌握几个库和算法。这会培养你的判断力。你会明白哪个对你重要,你的兴趣是什么。

欢迎在推特上关注我,喜欢我的脸书页面。

阅读推荐:

[## Numpy 完全指南

日常工作中需要的所有数字方法

towardsdatascience.com](/a-complete-guide-to-numpy-fb9235fb3e9d) [## 学习使用 Python 的 Scikit_learn 库通过项目开发 KNN 分类器

适合机器学习新手

towardsdatascience.com](/clear-understanding-of-a-knn-classifier-with-a-project-for-the-beginners-865f56aaf58f) [## 数据科学家假设检验完全指南,Python 示例

用样本研究问题、解决步骤和完整代码清楚地解释

towardsdatascience.com](/a-complete-guide-to-hypothesis-testing-in-python-6c34c855af5c) [## Python 中的线性回归算法:一步一步

学习线性回归的概念,并使用 python 从头开始开发一个完整的线性回归算法

towardsdatascience.com](/basic-linear-regression-algorithm-in-python-for-beginners-c519a808b5f8) [## 使用 Python 中的简单代码构建一个推荐系统

如何用 Python 构建电影推荐系统

medium.com](https://medium.com/towards-artificial-intelligence/build-a-simple-recommendation-system-in-python-7747be06a2f2)

更高的准确性并不意味着更好的机器学习模型性能

原文:https://towardsdatascience.com/greater-accuracy-does-not-mean-greater-machine-learning-model-performance-771222345e61?source=collection_archive---------40-----------------------

马太·亨利在 Unsplash 上拍照

我们可以定量衡量机器学习模型的性能,但不仅仅是准确性,还有很多。

介绍

如果我们想要基于数据预测一些结果,我们将使用机器学习模型从数据中进行监督学习。如果我们想确保模型正确工作,我们必须定量地知道模型的性能如何。对于那些刚接触机器学习的人来说,他们只是依赖准确性。

准确性是指模型正确预测所有标签的程度。他们认为更高的精度意味着更好的性能。嗯,确实是这样,但是如果只是用准确性的话,就要小心了。精确度计算所有真实的预测值,但不针对每个存在的标注。

如果你的目标想要正确地预测一个特定的标签,例如一个正标签,这是一个严重的问题。更高的准确性并不意味着我们在预测特定标签上有很好的表现。为了解决这个问题,有许多度量标准,在分类问题中,有精确度、召回率、F1 值等。

让我来解释一下这些指标:

精确

精度描述了模型正确预测标签的程度。

回忆

Recall 描述了模型如何正确检索所有标签。

F1 分数

F1 分数是精度和召回率的乘积除以精度和召回率的和,然后加权 2 的比例。该指标结合了精确度和召回率。如果值变大,则模型越好。

建议使用此指标,因为它们仅指定了标签的一个值。

例子

基于这些指标,我们如何衡量它?好吧,我们可以先根据真实和预测标签做一个混淆矩阵。我使用 sklearn.metrics 库中的混淆矩阵函数创建了混淆矩阵,这是我预测明天是否下雨的项目。

如果你对我的项目感兴趣,你可以查看下面我的 GitHub,

[## khalidmeister/我的项目

github.com](https://github.com/khalidmeister/my-projects/blob/master/DS1_Rain%20In%20Australia/code.ipynb)

矩阵是这样显示的,

注意:左上是真正的否定,右下是真正的肯定。

在左上方,它代表真阴性的计数,在右上方代表假阳性(简单地说是错误阳性,实际上是阴性),左下方代表假阴性(错误阴性,实际上是阳性),最后,右下方代表真阴性的计数。有了这些值,我们就可以计算每个指标。在这种情况下,我们计算正面标签或明天下雨的度量。通过使用 sklearn.metrics 库中的 classification_report 函数,我们可以从这样的计算中获得概述。

可以看到,模型的准确率是 79%。如果观察真正值,模型的准确率为 52%,召回率为 53%。这不是一个好结果,因为模型不能正确预测“1”标签,而目标是预测该标签。

如果我们只使用准确性来衡量模型的性能,那么我们将无法实现预测标签的目标。这就是为什么我们应该使用另一个指标来支持准确性结果。

结论

总之,在我们制作模型时,我们应该检查现有的度量标准,而不仅仅是依赖于准确性。如果你只关注准确性,我们不确定该模型是否能很好地预测现有的某种标签。如果我们已经知道度量值是多少,我们就可以通过进行超参数调整、特征选择、特征工程,甚至对数据进行采样来制作一个平衡级数据集,从而改进模型。

感谢您阅读我的文章,您也可以在下面查看我以前的文章:

[## 用 R 整理数据

为什么你应该在它上面投资更多,为什么这使你的分析变得容易得多

towardsdatascience.com](/tidy-data-with-r-f3d078853fc6) [## 如果我有自己的时间,我会这样学习数据科学

感觉不知所措和筋疲力尽让我在释放数据科学技能方面表现不佳。这个…

towardsdatascience.com](/this-is-how-i-will-learn-data-science-if-i-got-back-my-own-time-e9148c909ce9)

绿色是新的黑色:用人工智能拯救亚马逊雨林!

原文:https://towardsdatascience.com/green-is-the-new-black-saving-amazon-rainforests-using-ai-ec0676564e9a?source=collection_archive---------43-----------------------

新成果 /拯救环境利用 AI /哈佛 AI 为社会造福 /在 IEEESMC 2020

基于多模态噪声分割的亚马逊雨林碎片烧伤疤痕识别

亚马逊地区巴西北部帕拉 BR-163 高速公路附近的焚烧概述。经古斯塔沃·巴索许可使用,2019

(已收) 萨蒂扬·莫赫拉 、西德哈斯·莫赫拉、阿努帕姆·古哈、比普拉·班纳吉;IEEE 国际系统会议,Man,&控制论(IEEE SMC’20)

对于各种灾害管理和生态学研究来说,探测由难以接近的雨林中的野火引起的烧伤痕迹是重要的。耕地景观的碎片化和不同的种植模式经常阻碍烧伤疤痕的精确测绘。遥感方面的最新进展和多式数据的提供为这一制图问题提供了一个可行的解决办法。然而,分割烧伤痕迹的任务是困难的,因为它与相似外观的土地模式难以区分,烧伤痕迹的严重碎片性质和部分标记的噪声数据集。在这项工作中,我们提出了 AmazonNET 一个基于卷积的网络,允许从多模态遥感图像中提取燃烧模式。该网络包括 UNet-一种众所周知的具有跳跃连接的编码器解码器类型的架构。提出的框架利用堆叠的 RGB-NIR 通道,通过对来自亚马逊的新的弱标记噪声数据集进行训练,来分割来自牧场的烧伤疤痕。我们的模型通过正确识别部分标记的烧伤疤痕并拒绝错误标记的样本,展示了优异的性能,证明了我们的方法是第一个在多模式烧伤疤痕识别中有效利用基于深度学习的分割模型的方法。

在亚马逊河流域,火与几种土地耕作方式联系在一起。刀耕火种是巴西农业中最常用的做法之一(作为称为“queimada”的季节循环的一部分)。无论是对于开辟和清理农业区,还是更新牧场,其在农业链条中的重要性是不可否认的。不幸的是,这通常是森林野火的原因。

亚马逊雨林是植物和数十亿吨碳的主要储存库,碳的释放会导致气温大幅上升。因此,最近亚马逊森林大火的消息引起了轩然大波和关注。

无法控制的火灾,尤其是在旱季,会对当地和区域产生重大影响,导致自然生物群落的破坏、动植物物种的灭绝、污染、侵蚀和碳循环的失衡。这种干扰也影响到农业生产。因此,许多环境研究和资源管理活动需要准确识别燃烧区域,以便在空间和时间上监测受影响区域(所谓的燃烧疤痕),从而了解和评估这些区域的脆弱性,并促进可持续发展。

由于在区域和全球范围内火灾的地理范围很大,而且受火灾影响的地区的可及性有限,在过去几年里,遥感方法已成为具有成本效益的替代方法,能够以足够的空间和时间分辨率收集燃烧地区的信息。遥感技术可以为火灾管理、估计和探测、燃料测绘、野火后监测,包括燃烧面积和严重程度估计,提供有用的数据。

问题陈述

当前的非深度学习方法严重依赖领域知识和用户的手动输入,并且不能从数据中提取抽象表示。深度学习试图解决这些问题,然而,由于普遍缺乏任何标记数据,它们在烧伤疤痕预测中仍然被忽视。

在这项工作中,我们利用传感领域的最新进展,在遥感领域实现了无处不在的多模态数据和计算机视觉,利用有噪声的弱标记数据,通过 UNet 识别碎片化的烧伤疤痕,使我们的方法成为首批在多模态烧伤疤痕识别中利用基于深度学习的分割模型的方法之一。

结果(更多信息见下文)

相关著作

语义分割

语义分割是计算机视觉中的一个重要问题。如果不同的像素属于同一个对象类,它就将这些像素聚集在一起。由于它们能够捕捉精确定位的语义上下文,它们已被用于自动驾驶、人机交互、诊断、遥感等各种应用中。

在 DNNs 出现之前,各种各样的特征被用于语义分割,如 K-means、梯度方向直方图、尺度不变特征变换等。今天,已经提出了许多编码器-解码器网络及其变体,如 SegNet。专业应用带来了新的改进,如用于医学图像分割的 UNet,用于精细分割的基于 CRFs 的网络。

遥感中的多模态数据

遥感中的多模态分割涉及利用各种策略来有效地组合包含在多模态中的信息,以生成有利于精确土地利用分类的单一、丰富、融合的表示。常用方法包括在输入阶段连接通道,连接从类似 CNN 的单峰网络提取的特征,以生成土地制图分割。最近的工作涉及更复杂的想法,如“交叉注意”,以融合多种形式,产生专注的光谱和空间表示。

烧伤疤痕鉴定

多模式数据的同时获得导致了最近在定位火灾和量化燃烧面积方面的进步。每种模式都提供了关于同一地理区域的辨别信息,有助于在不利条件下绘制地图,如光谱混淆(如由于云遮蔽)和烧伤疤痕的可变性,使区分植被变得困难。在这个领域中所做的大部分工作涉及诸如自相关、自组织映射、线性光谱混合模型、SVM、随机森林等方法。然而,最近的作品似乎都没有利用当前的深度学习方法,如 CNN 或 SegNet 或 UNet 等编码器-解码器模型,这可能是因为缺乏标记数据。

提议的方法

这项工作的目的是执行语义分割和识别烧伤疤痕利用空间光谱信息构成的可见光和近红外。

体系结构

在遥感中,由于缺乏良好的标记数据集,基于计算机视觉的方法很难应用,因为所需的数据处理和标记只能由现场专家完成,这使得标记数据很少或不可用。类似的问题也出现在医学图像分割中,因此遥感中的常用方法有时是从医学分割领域中得到启发的。对于烧伤疤痕分割任务,我们将我们的网络基于 UNet 架构,其中来自编码器的特征激活被存储并被传输到相应的解码器层用于连接。

**编码器:**编码器网络由 3×3 卷积层以及批量标准化层、ReLU 非线性激活层和 2×2 最大池层组成。
**解码器:**解码器网络由名为 UpPool 块的上采样层组成,它执行 3x3 Conv2DTranspose、3×3 卷积以及批归一化层和 Dropout2D 层,Dropout 2d 层的 drop out 值为 0.1。对输出结果进行阈值处理,以获得表示烧伤疤痕的二进制输出图。

数据集

该数据集由亚马逊雨林的 LANDSAT8 的可见光和近红外卫星图像组成。数据集是 2017 年和 2018 年从超过 4 个州(即托坎廷斯州、马兰豪州、马托格罗索州、帕拉州)获取的,覆盖了超过 4 个陆地巴西生物群落,即塞拉多、亚马逊、卡廷加和潘塔纳尔。它由 299 个样本 VISNIR 图像对组成,大小为 1024x1024,具有地面实况,是二进制图像,其中 1 表示森林中的烧伤疤痕,0 表示未受火灾影响的区域。从图中可以看出,地面真实是有噪声的,也是部分标记的,有时是错误标记的。该数据集由国家空间研究所(INPE)管理,是 Quiemadas 项目的一部分。

结果

结果:该网络正确地分割烧伤疤痕,拒绝错误标记的斑点,并正确地识别部分标记或未标记的样本。(a)可见通道(b)近红外通道(假彩色 hsv) (c)可用标签(包括部分/不正确的标签)(d)预测的烧伤疤痕(e)二元烧伤疤痕。(a)和(b)中黑色轮廓表示标记数据(c)的轮廓,以便于观察。黄色方框表示正确标记或未标记的烧伤疤痕。白色方框表示贴错标签/识别错误的烧伤疤痕

该模型的训练准确率为 69.51%,验证准确率为 63.33%。结果验证了利用基于 U-net 的分割在烧伤疤痕识别中的有效性。

可以看出,网络正确地识别未标记的碎片烧伤疤痕(表示为黄色虚线框),并取消选择输出二进制图中错误标记的区域(表示为白色虚线框)(正确标记的输出突出显示为黄色,取消选择的标记为白色)。

分割烧伤疤痕中的小缺陷:网络错误地将河流、曲流、牛轭湖和云分割为烧伤疤痕。(a)和(b)中黑色轮廓表示标记数据(c)的轮廓,以便于观察。黄色方框表示正确标记或未标记的烧伤疤痕。白色方框表示贴错标签/识别错误的烧伤疤痕。缺陷归因于没有可用的分割标签和数据集中这些特征的可忽略的实例。

然而,我们的网络无法将河流和云的图案与烧伤疤痕区分开来,如下图所示。当我们的网络段(a)河流(b)蜿蜒曲折,牛轭湖和云作为烧伤疤痕模式时,缺陷出现。有趣的是,在图中的样本 2 和 3 中,网络如何准确地分割小的碎片状烧伤疤痕,但绝对不能拒绝这些疤痕。这可主要归因于(I)缺乏任何标记样本,以及(ii)数据集中包含上述地理特征的样本可忽略不计。

结论和未来工作

我们利用代表亚马逊雨林烧伤模式的部分/错误标记数据集,提出了基于 U-net 的分割网络,以正确识别烧伤疤痕并拒绝不正确的标签,证明了人工智能在碎片烧伤疤痕识别中的有效性。我们提出了不足之处,并考虑在未来的工作中解决这些问题。

基于多模态噪声分割的亚马逊雨林碎片烧伤疤痕识别

(已接受) 萨蒂扬·莫赫拉 、西德哈特·莫赫拉、阿努帕姆·古哈、比普拉·班纳吉;IEEE 国际系统会议,Man,&控制论(IEEE SMC 2020)

(赠送) 萨蒂扬·莫赫拉 、西德哈斯·莫赫拉、阿努帕姆·古哈;
哈佛 CRCS 人工智能公益工作坊 2020

温室气体(CO2)排放和炼油

原文:https://towardsdatascience.com/greenhouse-gas-co2-emissions-and-oil-refining-b13082469a0c?source=collection_archive---------37-----------------------

炼油厂在排放二氧化碳中扮演了多大的角色,哪些州是主要排放者?

Marcin Jozwiak 在 Unsplash 上拍摄的照片

我之前的帖子已经使用 Python 可视化来探索美国各地的炼油能力。此外,我们分析了多年来原油和燃料价格的行为。

在这篇文章中,我将探讨一些其他的东西:炼油过程中的二氧化碳(CO2)排放。以下所有工作的来源数据来自美国环保署的温室气体报告项目,其数据在此公开。该数据由 2011 年至 2018 年 1210 个行业的 5441 家公司以公吨为单位的自我报告的二氧化碳当量排放量组成。

教育要点:二氧化碳当量是一种测量任何污染物排放量的方法。例如,1 吨二氧化碳当量意味着实际释放的气体量将使地球变暖,与释放 1 吨二氧化碳的量相同。

TL/DR:发电产生的二氧化碳占排放到大气中的二氧化碳总量的 62%多一点,炼油和化学制品占第二位,为 9.6%。德克萨斯州、路易斯安那州和加利福尼亚州是主要的排放源,伊利诺伊州也是某些行业的主要排放源。

炼油给人的印象是喷出烟雾和蒸汽的巨大结构。但是——与美国其他主要行业相比,炼油厂到底排放了多少二氧化碳?这些数字在各州之间是如何变化的?就当前排放量而言,哪个行业提供的减排目标最大?

首先,我要说明一个众所周知的观点,即理解二氧化碳排放非常重要,因为大气中的二氧化碳吸收辐射,并将热量截留在地球大气中。二氧化碳含量越高,储存在大气中的热量就越多,气温和一般天气干扰的增加就越大——也被称为全球变暖或气候变化。

首先,让我们使用下面的代码来生成一个条形图,以显示二氧化碳当量最高的行业。

fig = px.bar(ByIndustry, x='Latest Reported Industry Type (sectors)', y='%')
fig.update_xaxes(tickangle=45, tickfont=dict(family='Rockwell', size=14))
fig.update_layout(width=1000, height=500, title='% of emissions from various Industries')fig.add_annotation(x=31, y=62.38, font=dict(family="Courier New, monospace", size=18, color="black",),text="62.38% of emissions from Power Plants")fig.show()

图 1:趋势显示 2011-2018 年总排放量的 62%来自发电厂。炼油厂和化工厂远远低于

有趣的是,从 2011 年到 2018 年,电厂的排放量占总排放量的 62%多一点。相比之下,炼油和化学制品共占 9.1%的排放量,比这少了 85%。

图 2:显示最高排放行业的代码和表格

观察不同行业在排放二氧化碳当量中扮演的角色是很有趣的。这在各州之间有何不同?请看下面的动态图表,该图表分析了 2018 年各州对以上列表中指定行业的排放贡献:

图 3:显示美国各行业 2018 年排放数据的动态曲线图

美国 2018 年排放数据的关键要点:

  • 得克萨斯州 T2 发电厂 T3 排放的二氧化碳当量达到峰值,为 1 . 85 亿吨。佛罗里达州和印第安纳州分别以 8400 万吨和 8100 万吨位居第二。
  • 炼油厂和化工怎么样?德克萨斯州以 3800 万吨二氧化碳当量再次领先,路易斯安那州以 2800 万吨二氧化碳当量排名第二,这与 choropleth 在我的炼油厂产能文章中显示的 2019 年 1 月炼油厂产能的信息相符。
  • 工业气体和矿物行业提供了思考的食粮。就背景而言,矿物是采矿业务的一部分,而工业气体则包括为其他业务制造常用气体,如氮气、二氧化碳、氩气、氢气和氦气。****

肯塔基州每年排放大约 100 万吨工业气体,而路易斯安那州和印第安纳州紧随其后,每年排放略多于 70 万吨。与此同时,德克萨斯州、密苏里州和伊利诺伊州是采矿业的主要排放者

这里的底线是,许多国家和许多行业在向大气排放二氧化碳方面发挥了作用,而发电是减排潜力最大的行业。

这一结论在美国环保署收集温室气体数据的 2011-2018 年间保持稳定。如下图 4 所示,这一时间范围内没有任何特定年份改变上述叙述。事实上,在这 7 年里,任何行业的排放情况都没有显著变化。

图 4:从 2011 年到 2018 年,发电厂提供了二氧化碳当量排放量的最大份额。这在 2011 年和 2018 年之间不会改变。

让我们开始改变思路,考虑炼油过程中的减排。

我之前讨论过将原油转化为汽油、喷气燃料、柴油等的炼油经济。炼油厂是如何做到这一点的?它通过使用各种精炼工艺单元来实现,其中主要有:加氢裂化器、流化催化裂化器(FCCs)、重整器和延迟焦化器。

这是许多新术语,我们将在接下来的几篇文章中深入探讨机器学习算法如何帮助优化这些不同单位的盈利能力和排放之间的平衡。

一如既往,我欢迎对这篇文章或其他文章的任何反馈或问题。支持本文分析的回购是此处。

Python 中大数据探索性数据分析

原文:https://towardsdatascience.com/grexploratory-data-analysis-on-big-data-in-python-5ab0f99818d8?source=collection_archive---------30-----------------------

理解大数据

探索和收集 1200 万份美国健康保险市场数据的见解

由路易斯·梅伦德斯在 Unsplash 上拍摄

在我之前的文章中,我们探索了 Python 中执行探索性数据分析(EDA)的图形化方法。会上讨论了折线图、回归线和奇特的运动图,讨论了如何利用它们来收集关于教育数据中的人口、收入和性别平等的见解。然而,数据相对较小,大约 200 行。在本帖中,我们将探索大约 1200 万条记录的更大数据,并研究在 Python 中执行 EDA 的其他方法。

资料组

我们将使用的数据集包含通过美国健康保险市场向个人和小型企业提供的健康和牙科计划的数据。它最初是由医疗保险中心&医疗补助服务(CMS) 准备和发布的,随后发表在 Kaggle 上。我们被告知数据包含 7 列:

  1. 商业年度 —计划为注册人提供保险的年份
  2. 州代码 —两个字符的州缩写,表示提供计划的州
  3. IssuerId —在健康保险监督系统(HIOS)中标识发行机构的五位数字代码
  4. 计划 id—14 个字符的字母数字代码,用于标识 HIOS 境内的保险计划
  5. 年龄 —订户年龄是否用于确定保险计划费率资格的分类指标
  6. 个别费率 —适用于某一费率区内保险计划的非烟草用户,或无烟草偏好的普通订户的每月保险费成本的美元值
  7. individual tobacco correct——适用于烟草用户在评级区域的保险计划的每月保险费成本的美元值

让我们将数据加载到 Python 中,并进行一些简单的初步探索。

import pandas as pd
insurance= pd.read_csv('./InsuranceRates.csv')# How many rows and columns are there?
print("The number of rows and columns are " + str(insurance.shape))

作者提供的图片— Jupyter 笔记本输出的数据形状

正如前面提到的,这个数据集非常大,它包含 12694445 行和前面讨论的 7 列。让我们看看一些数据列的唯一值。

# How many years does the data cover?
print("The number of unique years are " + str(insurance.BusinessYear.nunique()) + '\n')# What are the possible values for 'Age'?
print("The possible values for 'Age' are " + str(insurance.Age.unique()) + '\n')# How many states are there?
print("The number of states are " + str(insurance.StateCode.nunique()) + '\n')# How many insurance providers are there?
print("The number of insurance providers are " + str(insurance.IssuerId.nunique()) + '\n')

按作者分类的图像— Jupyter 笔记本在数据列上的输出

我们知道这些数据涵盖了 3 年的数据,美国 39 个州和总共 910 家保险提供商。年龄组从 21 岁到 64 岁不等,另外三个类别为“0-20 岁”、“家庭选项”和“65 岁及以上”。让我们看看个人每月支付的保险费的平均金额,以及最高和最低值。

# What are the average, maximum and minimum values for the monthly insurance premium cost for an individual? print("The average value for the monthly insurance premium cost for an individual is " + str(insurance.IndividualRate.mean()))
print("The max value for the monthly insurance premium cost for an individual is " + str(insurance.IndividualRate.max()))
print("The min value for the monthly insurance premium cost for an individual is " + str(insurance.IndividualRate.min()))

作者提供的图片— Jupyter 笔记本输出的保险费平均值/最大值/最小值

个人每月保险费成本的平均值为 4098.03 美元,最大值为 999999 美元,最小值为 0 美元。这些值似乎不合理,因为最大值太高,接近每月一百万美元,而最小值不可能是 0 美元。显然,这似乎表明该数据集中可能存在一些数据错误。

调查个人保险成本

由于我们发现个人保险费成本似乎不合理,让我们通过首先绘制一个直方图(使用 Python matplotlib)来显示分布来更详细地探究它。

# plotting the histogram over the whole range
plt.hist(insurance.IndividualRate,bins=20)
plt.xlabel('Individual Rate')
plt.ylabel('Frequency')
plt.title('Frequency of Individual Rate')
plt.show()# plotting the histogram from 800000 to 1000000
plt.hist(insurance.IndividualRate,bins=20,range=(800000,1000000))
plt.xlabel('Individual Rate')
plt.ylabel('Frequency')
plt.title('Frequency of Individual Rate')
plt.show()

按作者分类的图像—保险费直方图上的 Jupyter 笔记本输出

如前一节所述,我们发现大约有 48000 人每月支付接近 100 万澳元的保险费。

由于 1200 万中的 48000 只占数据的 0.4%,所以我们把它们去掉,专注于剩下的数据(即保险费少于 2000 美元)。

# filter data to those premium below $2000
insurance=insurance[(insurance.IndividualRate>0) & (insurance.IndividualRate<=2000)]# Generate a new histogram with a larger number of bins (say 200).
plt.hist(insurance.IndividualRate,bins=20)
plt.xlabel('Individual Rate')
plt.ylabel('Frequency')
plt.title('Frequency of Individual Rate')
plt.show()

按作者分类的图片— Jupyter 笔记本在保险费直方图上的输出(≤2000 美元)

我们看到直方图现在显示了更清晰的分布,有 15 个不同的组,即 0–100、100–200、200–300、300–400、400–500、500–600、600–700、700–800、800–900、900–1000、1000–1100、1100–1200、1200 接近 4000000 英镑的大多数人支付 0-100 英镑,少数人支付 1300-1500 英镑。

各州保险费的差异

将我们的数据过滤到更准确、更合理的保险费范围后,现在让我们使用箱线图来探索美国 39 个不同州的保险费成本是如何变化的。

# rotate the axis and set a bigger figsize to ease reading
insurance.boxplot(column = 'IndividualRate', by = 'StateCode',rot=90,fontsize=9,figsize=(10,10))

作者图片 Jupyter 笔记本输出的各州保险费箱线图

从箱线图中,我们知道 MO 的保险费率中值最低,而 AK 的保险费率最高。

让我们看看各州的保险公司数量是否也有所不同。请注意,我们需要进行一些数据聚合(即分组),然后才能在条形图中绘制数据。

# aggregate the data to find the number of insurance companies by state
groupbystate = insurance.groupby('StateCode').agg({'IssuerId':{'companies_count':'nunique'}})
groupbystate=groupbystate.reset_index()
groupbystate.columns=groupbystate.columns.droplevel(0) 
groupbystate.rename(columns = {'':'StateCode'},inplace = True)plt.bar(groupbystate.StateCode,groupbystate.companies_count)
plt.title('No. of insurance issuers in each state')
plt.xlabel('State Code')
plt.ylabel('No.of insurance issuers')
plt.xticks(rotation=90,fontsize=7)
plt.show()

按作者分类的图片— Jupyter 笔记本输出在各州保险发行商的条形图上

从柱状图中,我们知道各州的保险发行人数量差异很大。HI 最低为 4,TX 最高为 48。

从这两个图表中,一个合乎逻辑的问题是,竞争会影响每个州的保险费吗?拥有更多的保险提供商可能会导致较低的保险费率,而在该州拥有较少的保险提供商可能会导致较高的保险费率。让我们使用散点图来探索这种可能的关系。我们首先需要汇总数据(即使用 groupby)以获得每个州的保险费成本中值。

# Use a scatterplot to plot the number of insurance issuers against the median insurance cost for each state.
# Aggregate the data to find number of insurance issuers and median cost for each state
groupbystate2 = insurance.groupby('StateCode').agg({'IssuerId':{'companies_count':'nunique'},'IndividualRate':{'median_cost':'median'}})
groupbystate2=groupbystate2.reset_index()
groupbystate2.columns=groupbystate2.columns.droplevel(0) 
groupbystate2.rename(columns = {'':'StateCode'},inplace = True)plt.scatter(groupbystate2.StateCode,groupbystate2.companies_count,s=groupbystate2.median_cost)
plt.title('No. of Insurance Issuers VS Median Insurance Cost for each state')
plt.xlabel('State Code')
plt.ylabel('No. of Insurance Issuers')
plt.xticks(rotation=90,fontsize=7)
plt.show()

按作者分类的图片 Jupyter 笔记本输出各州保费中位数散点图

从散点图来看,保险中值成本和保险公司数量之间通常没有明确的关系。保险发行人数量较少的州仍会导致较低的中值利率(用圆圈大小表示)。同样,拥有大量保险发行人的州仍然会导致中值利率较高。

保险费随时间的变化

请记住,我们的数据包含三年的数据,让我们使用箱线图来探索保险费是否会随着时间的推移而变得更贵。

insurance.boxplot(column='IndividualRate',by='BusinessYear')
plt.ylim(0, 1000)

按作者分类的图片— Jupyter 笔记本电脑在一段时间内的保费箱线图输出

如箱线图所示,中位数(用绿线表示)在这些年中略有增加,这意味着这些年来保险单变得稍微贵了一些。

保险费随年龄的变化

在现实世界中,我们知道一个人年龄越大,他/她就越容易发生事故或健康疾病,这意味着保险公司需要收取更高的保险费率。最后,让我们用箱线图来研究保险人的年龄是否对保险费成本有影响。请注意,我们必须过滤掉“家庭选项”,因为它无法根据年龄进行衡量。

# Filter out 'Family Option' in order to plot boxplot
temp_insurance=insurance[(insurance.Age!='Family Option')]
temp_insurance.boxplot(column='IndividualRate',by='Age',rot=90,fontsize=9,figsize=(10,10))

按作者分类的图片— Jupyter 笔记本输出的各年龄段保费箱线图

箱线图与我们之前在现实世界中讨论的一致。很明显,保险费成本随着被保险人的年龄而增加,因为我们可以看到中间值在整个时间段内不断增加。因此,将老年人(65 岁及以上)与年轻人(0-20 岁)进行比较,老年人支付的保险费用中位数比年轻人高,老年人每月的差额约为 700-150 = 550 英镑。

摘要

继上一篇文章之后,这篇文章进一步讨论了如何使用箱线图、散点图和条形图从我们的数据中发现洞见。还要注意,这个数据比前一个大得多,但是肯定的是,这不会影响在 Python 上构建这些可视化的处理时间。希望你们已经用这种新的图形化方法在 Python 中做探索性数据分析时找到了一些替代方法。感谢阅读!

超参数调谐的网格搜索

原文:https://towardsdatascience.com/grid-search-for-hyperparameter-tuning-9f63945e8fec?source=collection_archive---------6-----------------------

图像来源

各位机器学习爱好者好!由于实习的原因,我已经有一段时间没有在 Medium 上写东西了。当我在做我的项目时,我面临着一种情况,我需要用不同的超参数来尝试不同的分类器。我发现每次都很难手动更改超参数并使它们适合我的训练数据。原因如下:

  • 这很费时间
  • 很难跟踪我们尝试过的超参数,我们仍然必须尝试

因此,我很快询问谷歌是否有解决我的问题的方法,谷歌向我展示了来自 Sklearn 的名为的东西。让我用一个简单的例子来分享我是如何利用这个 GridSearchCV 来解决我的问题的。

什么是 GridSearchCV?

GridSearchCV 是一个库函数,是 sklearn 的 model_selection 包的成员。它有助于遍历预定义的超参数,并使您的估计器(模型)适合您的训练集。因此,最后,您可以从列出的超参数中选择最佳参数。

除此之外,您可以为每组超参数指定交叉验证的次数。

带解释的示例

from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifierkn = KNeighborsClassifier()params = {'n_neighbors' : [5, 25],'weights': ['uniform', 'distance'],'algorithm': ['auto', 'ball_tree', 'kd_tree', 'brute']
}grid_kn = GridSearchCV(estimator = kn,param_grid = params,scoring = 'accuracy', cv = 5, verbose = 1,n_jobs = -1)grid_kn.fit(X_train, y_train)

我们来分解一下上面的代码块。像往常一样,您需要从 sklearn 库中导入 GridSearchCV估计器/模型(在我的例子中是 KNClassifier)。

下一步是定义您想要尝试的超参数。这取决于你选择的评估者。您所需要做的就是创建一个字典(我的代码中的变量 params ),它将超参数作为键,并有一个 iterable 来保存您需要尝试的选项。

然后你要做的就是创建一个 GridSearchCV 的对象。这里基本上需要定义几个命名参数:

  1. 估计器:您创建的估计器对象
  2. params_grid :保存您想要尝试的超参数的字典对象
  3. 评分:您想要使用的评估指标,您可以简单地传递一个有效的评估指标字符串/对象
  4. cv :您必须为每组选定的超参数尝试交叉验证的次数
  5. verbose :您可以将它设置为 1,以便在将数据放入 GridSearchCV 时得到详细的打印结果
  6. n_jobs :如果 it -1 将使用所有可用的处理器,您希望为该任务并行运行的进程数。

这些都是你需要定义的。然后你要像平时一样拟合你的训练数据。您将得到如下所示的第一行:

Fitting 5 folds for each of 16 candidates, totalling 80 fits
...
...
...

你不明白这是什么意思吗?简单!因为我们必须为 n_neighbors 尝试两个选项,两个用于权重,四个用于算法,所以总共有 16 种不同的组合我们应该尝试。对于每个组合,我们有 5 个 CV 拟合,因此我们的 GridSearcCV 对象将测试 80 个不同的拟合。

这种适合的时间取决于你正在尝试的超参数的数量。一旦一切完成,您将得到如下输出:

[Parallel(n_jobs=1)]: Done  80 out of  80 | elapsed: 74.1min finished]

然后要知道什么是最好的参数,你可以简单地打印出来

# extract best estimator
print(grid_kn.best_estimator_)Output:
KNeighborsClassifier(algorithm='auto', 
leaf_size=30, metric='minkowski',metric_params=None, n_jobs=-1, n_neighbors=25, p=2, weights='distance')# to test the bestfit
print(grid_kn.score(X_test, y_test))Output:
0.9524753

很酷不是吗?现在你所要做的就是改变估计量,定义一个你必须尝试的超参数字典。希望这对你有帮助。要了解更多关于 GridSearchCV 的内容,请查看 sklearn 的官方文档。

参数调整的网格搜索

原文:https://towardsdatascience.com/grid-search-for-parameter-tunning-3c6ff94e7a25?source=collection_archive---------39-----------------------

学习这个简单易行的技术来调整你的机器学习模型

图片由 PollyDot 来自 Pixabay

简介

一旦你建立了一个机器学习模型,你会想要调整它的参数以获得最佳性能。每个数据集的最佳参数是不同的,因此它们需要调整,以便算法可以获得其最大潜力。

我见过很多初学数据的科学家用手做参数调优。这意味着运行模型,然后在笔记本中更改一个或多个参数,等待模型运行,收集结果,然后一次又一次地重复这个过程。通常,人们会在途中忘记哪些参数是最好的,他们需要重新做一次。

一般来说,上述策略并不是最高效的。幸运的是,由于 sci-kit learn library 的作者添加了 GridSeachCV,这个过程可以很容易地自动化。

什么是 GridSearchCV?

图片来自 Pixabay 的 Nicolás Damián Visceglio

GridSearchCV 是我上面描述的简单方法的替代方法。不用手动调整参数并多次重新运行算法,您可以列出您希望算法尝试的所有参数值,并将其传递给 GridSeachCV。

GridSearchCV 将尝试这些参数的所有组合,使用交叉验证和您提供的评分标准来评估结果。最终它会吐槽出最适合你数据集的参数。

GridSearchCV 可以与 sci-kit learn 库中的任何监督学习机器学习算法一起使用。如果你提供一个合适的度量标准,它将同时适用于回归和分类。

让我们用一个真实的例子来看看它是如何工作的。

GridSearchCV 代码示例

为了说明,让我们加载虹膜数据集。这个数据集有三种不同鸢尾物种的 150 个例子。数据集没有缺失值,因此不需要清理数据。

from sklearn.datasets import load_iris
import pandas as pd
%matplotlib inlinedata = load_iris()
df = pd.DataFrame(data['data'], columns=data['feature_names'])
df['species'] = data['target']
df.head()

现在让我们将数据集划分为训练和测试。

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(df.drop('species', axis=1), df.species ,test_size = 0.2, random_state=13)

一旦我们划分了数据集,我们就可以用我们选择的算法建立网格搜索。在我们的例子中,我们将使用它来调整随机森林分类器。

from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifierrfc = RandomForestClassifier()grid_values = {'n_estimators': [10, 30, 50, 100],'max_features': ['sqrt', 0.25, 0.5, 0.75, 1.0],'max_depth' : [4,5,6,7,8],}grid_search_rfc = GridSearchCV(rfc, param_grid = grid_values, scoring = 'accuracy')
grid_search_rfc.fit(x_train, y_train)

在上面的代码中,我们首先通过使用不带参数的构造函数来设置随机森林分类器。然后,我们定义参数以及 grid_values 变量中每个参数的值。“grid_values”变量随后被传递给 GridSearchCV,同时传递的还有随机森林对象(我们之前已经创建过)和评分函数的名称(在我们的例子中是“accuracy”)。最后,我们通过调用网格搜索对象上的 fit 函数来拟合它。

现在为了找到最佳参数,可以使用 best_params_ attribute:

grid_search_rfc.best_params_

使用 max_features 参数的 75 %的特征并使用 10 个估计器,我们得到了具有六层深度的树的最高准确度。

这比手动尝试所有参数要容易得多。

现在,您可以使用网格搜索对象,使用最佳参数进行新的预测。

grid_search_rfc = grid_clf_acc.predict(x_test)

并在测试集上运行分类报告,以查看模型在新数据上的表现。

from sklearn.metrics import classification_report
print(classification_report(y_test, predictions))

您可以看到所有类别的准确度、召回率、精确度和 f 分数的详细结果。

请注意,我们使用精确度来调整模型。这可能不是最好的选择。我们实际上可以使用其他指标,如精确度、召回率和 f 值。让我们开始吧。

from sklearn.metrics import make_scorer, accuracy_score, precision_score, recall_score, f1_scorescoring = {'accuracy': make_scorer(accuracy_score),'precision': make_scorer(precision_score, average = 'macro'),'recall': make_scorer(recall_score, average = 'macro'),'f1': make_scorer(f1_score, average = 'macro')}grid_search_rfc = GridSearchCV(rfc, param_grid = grid_values, scoring = scoring, refit='f1')
grid_search_rfc.fit(x_train, y_train)

在上面的代码中,我们设置了四个评分标准:准确度、精确度、召回率和 f-score,我们将它们存储在列表中,稍后作为评分参数传递给 grid search。我们还将 refit 参数设置为等于评分函数之一。这是 f-score 是我们的情况。

一旦我们运行它,我们可以获得 f-score 的最佳参数:

grid_search_rfc.best_params_

此外,我们可以使用 cv_results_ attribute 来了解有关 grid_search 设置的更多信息。

grid_search_rfc.cv_results_

如果您想查看其他指标的结果,可以使用 cv _ results[' mean _ test _【T0]']。因此,为了获得我们之前设置为评分函数之一的召回结果,您可以使用:

grid_search_rfc.cv_results_['mean_test_recall']

上面我们可以看到网格搜索参数组合的所有召回值。

GridSearchCV 缺点

你有没有注意到所有召回结果的清单很长?它实际上有 100 个元素。这意味着 grid 已经尝试了 100 种不同的参数组合。这非常多,而且非常耗时,尤其是在大型数据集上。

在我们的例子中,grid search 对 100 个不同的随机森林设置进行了五重交叉验证。想象一下,如果我们有更多的参数要调整!

GridSearchCV 有一个替代方案叫做 RandomizedSearchCV。它不是尝试所有参数,而是只从给定分布中采样参数的子集,因此可能更快更有效。

总结

在本文中,您了解了如何使用网格搜索来优化参数调整。是时候在不同的数据集上使用不同的模型而不是随机森林来尝试您新获得的技能了。编码快乐!

最初发布于 aboutdatablog.com: 学习如何使用网格搜索进行参数整定,2020 年 10 月 8 日。

PS:我正在 Medium 和aboutdatablog.com上撰写以简单易懂的方式解释基本数据科学概念的文章。你可以订阅我的 邮件列表 在我每次写新文章的时候得到通知。如果你还不是中等会员,你可以在这里加入

下面还有一些你可能喜欢的帖子

* [## 关于 jupyter 笔记本你不知道的 9 件事

用这些建议提高你的工作效率

towardsdatascience.com](/9-things-you-did-not-know-about-jupyter-notebook-d0d995a8efb3) [## 最佳数据科学书籍

帮助您学习数据科学的前三本书

towardsdatascience.com](/best-data-science-books-be1ab472876d) [## 作为一名有抱负的数据科学家,你应该关注的中型作家

我最喜欢的 10 个数据科学博主,让你的学习之旅更轻松。

towardsdatascience.com](/medium-writers-you-should-follow-as-an-aspiring-data-scientist-13d5a7e6c5dc)*

SARIMAX 参数的网格搜索

原文:https://towardsdatascience.com/grid-search-for-sarimax-parameters-adbd5104cb8b?source=collection_archive---------9-----------------------

实践教程

为 statsmodels SARIMAX 模型找到最佳参数的简单方法

作者图片

如果您已经在这里登陆,那么您很可能正在实现一个 statsmodels SARIMAX 时间序列模型,并且您正在寻找一种简单的方法来识别所有最佳参数。我有一些好消息要告诉你…你来对地方了!

在本教程中,您将学习如何运行简单的网格搜索来为 statsmodel SARIMAX 时间序列模型查找最佳参数。或者您可以直接复制并粘贴代码——甚至更简单!

对于我们的 SARIMAX 模型,总共有七个子参数,单独计算它们并不容易。然而,通过几行简单的代码,我们可以创建一个定制的网格搜索,给出一个最优参数列表,按照用户选择的选择标准(AIC 或 BIC)排序。

选择标准

让我们从选择标准开始。这里的两个选择是 AIC 和 BIC。它们分别代表阿凯克信息准则和贝叶斯信息准则。他们选择用最少的独立变量解释最大变化的模型。[1]他们计算的方法是使用最大似然估计(MLE ),他们都惩罚一个增加变量数量以防止过度拟合的模型。

围绕哪一个最好用,有很多讨论。BIC 会因为一个模型有越来越多的变量而加大对它的惩罚力度。如果在未来的数据集或模型将应用的多个数据集中有更多的变化,那么我推荐使用 BIC。就像我在这里一样。然而,并没有很大的区别,AIC 也很普通,所以真正的选择权在你。

SARIMAX 参数

SARIMAX 是时间序列模型中的佼佼者。在进行时间序列建模时,它基本上考虑了所有可以考虑的因素。

我们将在这里对参数进行简单直观的解释。

**S——代表季节性。**这意味着数据表现出季节性。这样的例子可能是一年中的季节,因此给定位置的温度波动将根据季节而变化,通常夏天更暖和,冬天更凉爽。如果我们有月平均值的数据,那么“S”就是 12。在我们的模型中用“s”来表示。

AR —代表自回归。这是数据在任何给定的时间间隔或之前的时期与之前的数据的相似程度。简单来说,它代表数据中的重复模式。自回归是指数据在之前数据的某个滞后期内回归,并找到回归最强的地方,代表数据中的模式。在我们的模型中表示为“p”。

I—代表集成的。“I”表示数据值已被替换为其值与先前值之间的差值。[2] 在我们的模型中用“d”来表示。

**MA——代表移动平均线。**此术语计算给定周期数的移动平均值。它用于减少模型中的噪波或使其平滑。移动平均周期越长,噪声就越平滑。在我们的模型中表示为“q”。

**X —代表外源性。**这考虑了一个已知的外部因素。在我们的模型中,这是一个可选的参数,而不是一个参数。是我们可以添加到模型中的一系列外生回归变量。这部分是可选的,在计算我们的最佳模型参数时不是必需的。

在我们的模型中,我们的参数如下所示:

SARIMAX (p,D,q) x (P,D,Q,s)

statsmodel SARIMAX 模型考虑了常规 ARIMA 模型(P,D,Q)以及季节性 ARIMA 模型(P,D,Q,s)的参数。这几组参数是我们的模型中的参数,分别称为订单和季节订单。

现在是有趣的部分——让我们编码吧!

以下是运行网格搜索以找到 statsmodel SARIMAX 模型的最佳参数所需的所有代码。

这是输出的样子!

作者图片

对于我的模型,当我将预测值与已知值进行比较时,二阶组合的 BIC 略高,但 RMSE(均方根误差)较低。为此,我选择用列出的二阶组合来构建我的模型。

下面是我们如何从上面的参数网格搜索中获取结果,并构建我们的模型!在此代码中,我们将:

  • 建立我们的模型
  • 打印摘要
  • 绘制诊断图

这是我们的汇总输出的样子!

作者图片

我们可以看到这个模型的所有参数都很重要。情况并非总是如此,这些数据没有太多的可变性。

这是我们的输出图诊断的样子!

作者图片

我们找到了。

我希望这个教程对你有用。一如既往,欢迎在评论中问我任何问题。

参考

  • [1]https://www . scribbr . com/statistics/a kaike-information-criterion/
  • [2]https://en . Wikipedia . org/wiki/auto regressive _ integrated _ moving _ average
  • [3]https://www . stats models . org/dev/generated/stats models . TSA . statespace . sarimax . sarimax . html

使用的软件

  • 计算机编程语言
  • Jupyter 笔记本

Python 中的网格搜索—超参数调整

原文:https://towardsdatascience.com/grid-search-in-python-from-scratch-hyperparameter-tuning-3cca8443727b?source=collection_archive---------7-----------------------

图片由 JPuckett Design 在 Instagram 上提供。

超参数调整对于机器学习(ML)模型的正确运行至关重要。网格搜索法是超参数优化的基本工具。

网格搜索方法考虑几个超参数组合,并选择返回较低错误分数的一个。当只有几个超参数需要优化时,这种方法特别有用,尽管当 ML 模型变得复杂时,这种方法优于其他加权随机搜索方法。

本文介绍了用网格搜索进行超参数调整的思想。您将学习网格搜索如何工作,以及如何实现它来优化您的机器学习方法的性能。

提供代码片段有助于理解实现。完整的代码可以在这个 GitHub 库中找到。

网格搜索提供了一种调整 ML 模型超参数的直观方法,对于低维空间非常有效。

网格搜索概述

1-准备数据库。

2-确定要优化的模型超参数,然后选择要测试的超参数值。

3-评估超参数网格中每个组合的误差分数。

4-选择具有最佳误差度量的超参数组合。

生成数据

一个数据库由一系列特征x:{xx₂,…,xₙ*}和一个或多个目标属性y:{f₁( f₂(x₁、x₂,…、xₙ)、…、fₙ(x₁、***

在我们的例子中,我们将使用一个简单的数据库,有两个描述符x**:{x₁,x}和一个目标属性y:{f(x₁, x**

**作为一个例子,我们将使用遵循二维函数f(x₁、x₂)=sin(x₁)+cos(x₂】的数据,加上区间(-0)中的小的随机变化因此,我们的数据将遵循以下表达式:

f(x₁,x₂)= sin(x₁)+cos(x₂)+rnn

我们在区间x:10,10 和x:10,10 中生成一个 21×21 的网格。下图显示了数据库中 441 个点的可视化表示。

作者图片

用来生成这个的函数( x ₁、x₂、f(x₁、x【₂))

机器学习模型

在这种情况下,我们将使用一个核岭回归 (KRR)模型,带有一个径向基函数核。通过调整两个超参数来评估模型的准确性:正则化常数(α)和核方差(γ)。如果你想知道更多关于 KRR 如何运作的细节,我建议看看我最近写的关于这个话题的文章。

在上一节中,我们已经看到了如何生成一个( x ₁, x f(x【₁】,x₂))数据集。为简单起见,我们将其转换为一个(xy)数据集,其中 X 是一个 2D NumPy 数组,包含(x【₁】, x

最后,我们可以构建一个函数KRR _ 函数。该函数读取(X y ) ,并使用 10 重交叉验证来计算模型的准确性。作为误差度量,我们在这里使用均方根误差(RMSE),它测量实际的f(x₁、x【₂】值和预测值之间的平均误差。如果你不熟悉交叉验证,我最近写了一篇文章,你可能会感兴趣。

探索超参数空间

我们需要决定一组我们想要研究的超参数值,然后我们使用我们的 ML 模型来计算相应的 RMSE。最后,我们可以选择最优(α,γ)组合作为最小化 RMSE 的组合。

下图显示了相应的 RMSE 值。我们使用了可变的标记大小来更清楚地说明具有最佳 RMSE 的值。

作者图片

使用下面的代码,我们探索这个可能的超参数值的 10×10 网格,并且我们获得最小值RMSE = 0.3014at(α=10⁻·γ=2.0 )。

因此,使用这些函数并获得最佳超参数的最终代码应该是:

结论

在这个简短的教程中,我们看到了如何实现和使用网格搜索来调整 ML 模型的超参数。我们已经生成了一个简单的 2D 数据集,并看到了如何优化具有两个超参数的 ML 模型的误差度量。

当我们有大量超参数时,网格搜索对于调整 ML 模型并不有效,然后应该转向其他方法。举个例子,我最近写了一篇关于如何使用遗传算法调优 ML 模型的文章。

我希望这篇教程是有用的,并且记住你可以在这个资源库中访问这篇教程中使用的完整代码和图形。

寻找好酒的格子

原文:https://towardsdatascience.com/grid-searching-for-good-wine-43cdfeadee6c?source=collection_archive---------44-----------------------

在大多数 ML 项目中,微调一个人的模型是至关重要的一步。即使有很好的数据清理和特征工程,选择不当的超参数也会阻止用户从其模型中获得最佳性能。在过去的项目中,我发现自己循环通过参数并打印出训练错误来挑选最好的,但我最近读了安德烈亚斯·c·müller&萨拉·圭多的用 Python 介绍机器学习。在本书中,作者解释并演示了 sklearn 自动搜索 ML 模型的给定超参数列表,然后挑选最佳组合的能力。我发现这个功能非常有用,所以我写了这篇文章,作为传递 Müller 和圭多的教导的一个快速演示。

我将使用来自 Kaggle 的红酒质量数据集,它的可用性得分为 8.8 分,不算太大(1599 行)。观察最上面的几行可以看出,这个数据集包含了红酒的各个方面,如 pH 值、残糖克数、酒精含量等...以及从 1 到 10 的葡萄酒总体质量分数。

由于我肯定不是品酒师,可能无法区分 7 分的葡萄酒和 8 分的葡萄酒,我将训练一个支持向量机来确定葡萄酒是否好喝。对我来说,“好”是指质量得分为 7 或更高的任何东西,所以我必须在数据中添加该特性。添加之后,我可以将数据拆分为独立变量和因变量,并创建我的培训/测试拆分。

既然数据的形式正确,我们就转向网格搜索。我做的第一件事是创建一个超参数列表,供网格搜索迭代。因为我使用的是支持向量分类器,所以我测试了 C 和 gamma 的不同值,它们分别是正则化参数和核系数。我输入模型、我的参数网格和交叉验证折叠 5 来创建 GridSearchCV()对象,然后像 sklearn 中的任何其他模型一样用。fit()方法。

现在模型已经拟合好了,是时候查看结果了。我可以使用。网格搜索对象的 cv_results_ attribute,然后将结果透视到热图中。这清楚地表明,该数据的最佳组合是归一化参数的高值和核系数的低值。

网格搜索对象还将最佳拟合参数存储在。最佳参数属性。顺便提一下,Müller 和圭多解释说,sklearn 总是将来自训练数据的项目存储在以下划线结尾的属性中(例如:“。best_params_ ","cv_results_ ")。我们可以使用 kwargs 将这些参数直接插入到我们希望拟合测试数据的模型中,如下文使用**SVC( * grid _ search . best _ params _)***所演示的。使用网格搜索中找到的最佳参数,该模型在测试集上获得 100%的分类准确率。

希望这是 sklearn 网格搜索能力的一个有用的演示。要了解更多关于这方面的信息和大量其他的 ML 主题,我推荐阅读*Python 机器学习入门。*感谢阅读,完整的脚本/数据可在这里找到。要获得所有中型文章的完整访问权限,请点击此处!

GridSearch:终极机器学习工具

原文:https://towardsdatascience.com/gridsearch-the-ultimate-machine-learning-tool-6cd5fb93d07?source=collection_archive---------22-----------------------

什么是 GridSearch,为什么它如此重要?

GridSearch:终极机器学习工具。克里斯·利维拉尼在 Unsplash 上的照片

简而言之,机器学习

监督机器学习的目标是基于历史数据建立预测功能。该数据有独立(解释)变量和目标变量(您要预测的变量)。

一旦建立了预测模型,我们就在单独的测试数据集上测量它的误差。我们使用 KPI 来量化模型的误差,例如,回归环境中的均方误差(定量目标变量)或分类环境中的准确性(分类目标变量)。

误差最小的模型通常被选为最佳模型。然后,我们使用该模型通过输入解释变量来预测目标变量的值。

在本文中,我将深入研究 GridSearch。

机器学习的两种优化

GridSearch 是一个用于超参数调整的工具。如前所述,机器学习在实践中归结为将不同的模型相互比较,并试图找到最佳的工作模型。

除了选择正确的数据集,优化预测模型通常有两个方面:

  1. 优化最佳模型的选择
  2. 使用超参数调整优化模型拟合

现在让我们来研究一下这些,以解释网格搜索的必要性。

第一部分。优化最佳模型的选择

在一些数据集中,可能存在简单的线性关系,可以从解释变量预测目标变量。在其他数据集中,这些关系可能更复杂或高度非线性。

与此同时,许多模型存在。这包括从线性回归这样的简单模型,到深度神经网络这样非常复杂的模型。

关键是使用适合我们数据的模型。

例如,如果我们在一个非常复杂的任务上使用线性回归,那么这个模型将是无效的。但是如果我们在一个非常简单的任务上使用深度神经网络,这也将是不可执行的!

为了找到合适的机器学习模型,解决方案是将数据分成训练和测试数据,然后在训练数据上拟合许多模型,并在测试数据上测试每个模型。测试数据误差最小的模型将被保留。

来自 Scikit Learn 的监督模型列表的截图显示,有大量模型可供试用!

第二部分。使用超参数调整优化模型拟合

在选择了一个(或几个)性能良好的模型之后,第二个要优化的是模型的超参数。超参数就像模型训练阶段的配置。它们影响模型能学什么或不能学什么。

因此,调整超参数可以进一步降低测试数据集的误差。

每个模型的估计方法都不同,因此每个模型都有自己的超参数需要优化。

Scikit Learn 的 RandomForestClassifier 的文档摘录显示了许多参数,这些参数都会影响模型的最终精度。

彻底搜索最佳超参数的一种方法是使用名为 GridSearch 的工具。

什么是 GridSearch?

GridSearch 是我们在优化超参数时使用的一个优化工具。我们定义想要搜索的参数网格,并为我们的数据选择最佳的参数组合。

网格搜索中的“搜索”

假设存在不同超参数值的特定组合,这将最小化我们的预测模型的误差。我们使用 GridSearch 的目标是找到这种特定的参数组合。

GridSearch 寻找最佳参数组合的想法很简单:只需测试每个可能的参数组合并选择最佳的一个!

虽然不是每个组合都是可能的,因为对于一个连续的规模来说,会有无限多的组合要测试。解决方案是定义一个网格。该网格为每个超参数定义了应该测试的值。

两个超参数α和β的 GridSearch 示意图(图片由作者提供)

在一个例子中,调整了两个超参数α和β:我们可以给它们两个值[0.1,0.01,0.001,0.0001],得到下面的“网格”值。在每个交叉点,我们的 GridSearch 将拟合模型,以查看该点的误差。

在检查了所有的网格点后,我们知道哪个参数组合最适合我们的预测。

网格搜索中的“交叉验证”

此时,只剩下一件事需要添加:交叉验证错误。

当使用每个超参数组合测试模型的性能时,可能存在过度拟合的风险。这意味着仅仅出于偶然,只有训练数据集很好地符合这个特定的超参数组合!在新的真实数据上的表现可能更差!

为了更可靠地估计超参数组合的性能,我们采用交叉验证误差。

交叉验证的示意图(作者提供的图片)

在交叉验证中,数据被分成多个部分。例如 5 份。然后模型被拟合 5 次,同时遗漏五分之一的数据。这五分之一被遗漏的数据用于测量性能。

对于超参数值的一个组合,5 个误差的平均值构成交叉验证误差。这使得最终组合的选择更加可靠。

是什么让 GridSearch 如此重要?

GridSearch 允许我们非常容易地找到给定数据集的最佳模型。通过自动搜索,它实际上使机器学习成为数据科学家角色的一部分变得更加容易。

在机器学习方面,仍然需要做的一些事情是决定测量误差的正确方法,决定尝试哪些模型和测试哪些超参数。最重要的部分,数据准备工作,也留给了数据科学家。

由于网格搜索方法,数据科学家可以专注于数据争论工作,同时自动化模型比较的重复任务。这使得工作更有趣,并允许数据科学家在最需要的地方增加价值:处理数据。

GridSearch 有许多替代方法,包括随机搜索、贝叶斯优化、遗传算法等等。我很快会写一篇关于这些的文章,所以不要犹豫,敬请期待。感谢阅读!

Pandas 和 SQL 中的分组依据

原文:https://towardsdatascience.com/group-by-in-pandas-and-sql-94777ce48658?source=collection_archive---------24-----------------------

聚合函数的比较

法国艺术家 Paulo Grangeon 的 1600 只熊猫+世界巡演。保罗·格兰金的作品|由 ARR 策划。参考资料中的艺术品网站链接

数据分析的一个重要组成部分是通过计算总和、最大值、最小值、平均值、中值等聚合来生成摘要。这样,我们可以对数据的总体情况有所了解。这对于大型数据集尤其重要,因为查看原始数据可能不会产生任何有意义的见解。

在这篇博文中,我将首先描述一下Group By的下划线机制,然后比较一下Group By概念在 Python 的pandas库和 SQL 中的实现。

什么是分组依据?

正如pandas开发团队在他们的文档中对 GroupBy object ,Group By包含三个步骤:

  • 步骤 1: 根据一些标准将数据分成组
  • 步骤 2: 独立地对每个组应用一个函数
  • 步骤 3: 将结果组合成一个数据结构

在分析数据框的上下文中,步骤 1 相当于找到一列,并使用该列的唯一值将数据框分成多个组。第 2 步是选择一个函数,如聚合、转换或过滤。所选功能将在每个单独的组上运行。步骤 2 的结果将被合并,并在步骤 3 中显示为新的数据结构。

以上所有听起来可能仍然相当抽象;让我们使用来自泰坦尼克号追逐赛的真实数据集来尝试一下。(注意,有三个数据集可用,我将在这篇博文中使用“train.csv”。)

在熊猫中分组

Python pandas库有一个名为groupby的高效操作来执行 Group By 任务。

在泰坦尼克号的数据集中,有一个名为“登船”的列,为每个乘客提供登船港口的信息。有三个不同的值:C、Q 和 S (C =瑟堡,Q =皇后镇,S =南安普顿)。如果我们想检查每个港口的乘客数量,我们可以使用以下命令:

train.groupby('Embarked')['Embarked'].count()

它给出以下输出:

让我们使用分割-应用-合并步骤对此进行一些分解。

第 1 步选择列“apollowed ”,使用它的唯一值——即 C、Q、S——将数据集分成三类。

请注意,在此阶段,没有对组执行任何操作。命令train.groupby('Embarked')仅仅输出一个GroupBy对象:

步骤 2 是选择count()方法作为我们的函数,它产生每个类别的总数。

第三步是组合并显示结果。pandas GroupBy 对象支持列索引,我们可以指定希望在聚合结果中看到哪些列。在我们的例子中,我们只关心“已装船”这一列。如果没有此规范,pandas将返回所有数字列的汇总结果,如下所示:

SQL 中的分组依据

Group By 概念是 SQL 语法的重要组成部分。尽管存在一些语法差异,SQL 的GOURP BY语句的工作方式与pandas相似。

上述pandas操作可以用 SQL 实现如下:

SELECT Embarked, COUNT(Embarked) 
FROM titanic.train 
GROUP BY Embarked;

GROUP BY语句中,选择列“apollowed”来分割数据集。在SELECT语句的第二部分,选择COUNT()作为聚合函数。SELECT语句还包含我们希望在输出中显示哪些列的信息。第一次出现“已装船”相当于pandas列索引[Embarked]。另一个微小的区别是,SQL 使用FROM语句来指定我们正在处理的数据集,即来自“titanic”模式的“train”表;而在pandas中,我们将数据帧的名称放在groupby命令的开头。

同样值得注意的是,SQL 在使用GROUP BY时会显示缺失值。从 SQL 输出中,我们可以看到两个乘客错过了登机港口。

高级示例

示例 1

如果我们想查看幸存与死亡乘客的平均票价,我们可以在pandas中使用以下命令:

train.groupby('Survived')['Fare'].mean()

它给出了以下输出:

类似地,我们可以在 SQL 中通过以下方式实现这一点:

SELECT Survived, AVG(Fare) 
FROM titanic.train 
GROUP BY Survived;

正如我们所看到的,幸存的人比死去的人平均支付了更高的费用。

示例 2

泰坦尼克号上有三种乘客等级,1 级、2 级和 3 级。假设我们想要检查每一个职业的幸存人数与死亡人数的百分比,我们可以结合使用下面的groupby命令和pandas中的.apply()方法:

pclass = train.groupby(['Pclass','Survived']).agg({'Pclass':'count'}) pclass_pcts = pclass.groupby(level=0).apply(
lambda x: 100 * x / float(x.sum()))

注意,在.apply()方法中,我们可以传递一个lambda函数来计算百分比。

这也可以在 SQL 中使用窗口函数来实现:

WITH t1 AS (SELECT Pclass, Survived, Count(*) AS n FROM titanic.train GROUP BY Pclass, Survived) 
SELECT Pclass, Survived, 100 * n / (SUM(n) OVER (PARTITION BY Pclass)) AS percent
FROM t1;

我们可以得出结论,存活率随着乘客等级的降低而降低。

我的博文到此结束。Group By 在pandas和 SQL 中的实现非常通用,可以和很多其他函数结合使用,值得进一步探索。

感谢您的阅读。一如既往,如果您有任何意见或反馈,我很乐意收到您的来信。

参考

  • 杰克·范德普拉斯的《Python 数据科学手册》
  • SQL 窗口函数
  • 按对象分组的熊猫文档
  • 保罗·格兰金的 1600 只熊猫+世界巡演

原载于

使用高斯混合模型(EM 算法)对相似图像进行分组

原文:https://towardsdatascience.com/group-similar-image-by-using-the-gaussian-mixture-model-em-algorithm-438e9744660c?source=collection_archive---------7-----------------------

为图像聚类问题从头实现 GMM

图片由什洛莫·沙莱夫拍摄

聚类最流行的无监督机器学习问题之一。我们已经熟悉了 k-means 聚类算法,但是这里有一个问题:

  1. 高度依赖于质心的初始值:如果我们改变它的初始化,然后改变集群的位置,那么最终的集群很可能会改变它的位置。
  2. 聚类具有不同的大小和密度:具有不同形状(分布的数据点)和大小(数据点的数量)的聚类不能通过这种简单的技术来处理。
  3. 离群点:可能出现一个数据点离任何一个聚类都很远,它可以作为一个单独的聚类。为了避免这样的问题,我们通常会删除这些点。

如果你不想理解这个令人讨厌的数学,那么请向下滚动到 GMM 的实现部分,在那里我将讨论 python 中的实现。

为了理解高斯混合模型,你需要理解一些术语

  1. 密度估计:概率密度估计是基于不可观察的潜在概率密度函数的观察数据的近似构造。这一步包括选择概率分布函数和描述观测数据的最佳联合概率分布的函数参数。
  2. 最大似然估计(MLE):是一种通过最大化对数似然函数来估计概率分布参数的方法。
  3. 潜在变量:与观察变量相反,即不是直接观察到的,而是从数学模型中推断出来的。我们以后再谈。

现在最大似然估计在潜在变量存在的情况下不太适用。期望最大化算法是一种在潜在变量存在的情况下可以找到合适的模型参数的方法。

EM 是一种寻找参数的最大似然或最大后验估计的迭代方法,其中模型依赖于未观察到的潜在变量。

让我们稍微简化一下。

给定 N 个观察值

和概率模型 p(X |θ)

我们的目标是找到使 p(X |θ)最大化的θ值,这被称为最大似然估计。

如果模型是简单的高斯分布,那么参数就像

在哪里

如果是这种情况,在 ML 中解决这个问题的最常见方法是梯度下降,通过最小化作为损失函数的对数似然函数-log(p(X |θ))(记住我们实际上最大化参数的概率函数

是数值稳定性的一种简单方法,因为它将乘积变为和,并且该函数的负值的最小化与该函数的最大化是相同的)。

但是梯度下降是一种解决非线性问题的方法,典型的是针对一些多维分布的最小值。计算高斯混合的均值(或其他矩)不是非线性问题,因此不需要为非线性问题设计的方法。那么有没有更好的方法来解决这个问题。

EM 算法来了。让我们看看 EM 算法是如何在高斯混合模型中使用的。

通过引入潜在变量,极大似然估计可以得到简化。潜在变量模型假设观测 xi 是由一些潜在的潜在变量引起的。嗯……还是不清楚,好吧,考虑一下这张图片

图像来源

这种类型的概率模型被称为高斯混合模型(GMM),在本例中 C 个高斯分量的加权和为 C = 3

πc 和σc 分别是混合分量 Cc 的权重、均值向量和协方差矩阵。权重是非负的,总和为 1,即

参数向量

表示所有模型参数的集合。如果我们引入一个离散的潜在变量‘t ’,它决定了对混合物成分的观察值的分配,我们可以用条件分布 p(x| t,θ)和先验分布 p( t | θ)来定义观察变量和潜在变量 p(x,t| θ)的联合分布

在哪里

t 的值是一位热编码的。例如,t2=1 指的是第二个混合成分,这意味着如果总共有 C=3 个成分,则 t = (0,1,0)。边际分布 p (x | θ)是通过对 t 的所有可能状态求和得到的。

对于每个观察 xi,我们有一个潜在变量 ti,也称为责任。

考虑到 X 是所有观测值的集合,所有潜在变量 T 的集合,那么我们可以很容易地最大化完全数据的对数似然 p(X,T | θ)。因为找到对数似然后,我们就知道点的聚类分配,这就是为什么我们会找到边际对数似然或不完全数据对数似然 p (X | θ)。所以从数学上来说,

GMM 的实施

让我们一步一步地看看如何使用高斯混合模型来聚类我们的图像。我在这里使用 python 来实现 GMM 模型:

需要外部 Python 库:

  1. imageio:用于从图像中获取 RGB 特征
  2. 熊猫:用于处理数据集
  3. numpy:用于数学运算

第一步:

让我们从我们的数据集开始,我们已经给出了所有图像驻留的文件夹路径。我们将创建一个方法,从中我们可以提取每个图像的 R,G,B 向量的平均值。对于单个图像,函数应该是:

######## loading external package dependency ####################Import pandas as pdImport numpy as npfrom scipy.stats import multivariate_normalImport imageioFrom functools import reducedef get_image_feature(path): Im = imageio.imread(os.path.join(path), pilmode=’RGB’) temp = Im/255\. # divide by 255 to get in fraction mn = temp.sum(axis=0).sum(axis=0)/(temp.shape[0]*temp.shape[1]) return mn/np.linalg.norm(mn, ord=None) # taking 2nd norm to scale vector

假设提供的图像路径是'(some_path)/Image_SunSet.jpg '这个函数返回[红、绿、蓝]图像像素的强度像[0.9144867979,0.3184891297,0.2495567485]我们可以清楚地看到红色具有更大的强度。

类似地,我们可以对所有图像执行此操作,并创建一个包含图像细节的熊猫数据帧:

  • 文件名:文件的名称
  • 路径:文件的路径
  • 扩展:图像扩展。jpg,。巴布亚新几内亚经济贸易委员会
  • ImageBase64:图像的 Base64 编码
  • 红色:红色平均强度
  • 绿色:绿色平均强度
  • 蓝色:蓝色平均强度

现在,我们的数据集包含特征(即数据集的[红、绿、蓝]列,而不是仅用于查看的所有其余数据)。如果你想得到更高 k 值(聚类数),你可以从图像中提取自己的特征,但要代表更广泛的颜色代码,不仅仅是 r、g 和 b。

第二步:

模型生成(实现高斯混合模型的 EM 算法):

因为在 GMM,我们假设所有的数据点都来自 k 高斯分布,其中 k 只不过是一些集群。嗯……有点棘手,让我们简化一下。

图像来源

考虑这个 1D 概率分布。如果我们假设所有数据点都来自 2 高斯分布,这意味着我们假设 k=2(聚类数),那么如果我们想知道哪些数据来自哪个高斯分布,我们需要做的就是计算两个高斯分布的均值和方差。但是等等,我们还不知道。但有一秒钟,如果我们假设我们知道这些参数(即 k 高斯分布的均值和方差),那么我们就可以知道每个数据点来自哪个高斯的可能性(这个可能性指的是责任)。哇,但是我们也不知道这个。所以我们的结论是

如果我们知道参数(即高斯的均值和方差),我们可以计算责任,如果我们知道责任,那么我们可以计算参数。

这就是 EM 算法的由来,它首先将“k”个高斯随机放入图像中(为高斯生成随机平均值和方差),然后在 E 和 M 步之间迭代,直到收敛,其中:

紧急步骤:根据当前参数分配集群责任

M 步:更新参数,给定当前集群职责

下面更详细的说一下它的实现。

让我们记住为什么 GMM 被用来。与 k- mean 不同的是,它不会对聚类进行硬分配,例如图像

如果我们使用 k=4,即 4 个集群模型,即日落、森林、云和天空,那么在 k 均值算法中,这张图片只属于云,这称为硬分配,但在 GMM,它属于 97%的云和 3%的森林,这称为软分配。

E 步骤:

在这一步中,我们计算集群责任。让 rik 代表聚类 k 对于数据点 I 的责任。您可以将责任假定为数据点‘I’属于‘k’聚类的概率。因为这种可能性意味着

为了知道一个聚类对一个给定的数据点有多大影响,我们计算该数据点在特定的聚类分配下的可能性,乘以该聚类的权重。对于数据点 I 和聚类 k,数学上:

其中 N (xi | μk,σk)是聚类 k 的高斯分布(具有均值μk 和协方差σk)。

我们用∝,是因为量 N (xi | μk,σk)还不是我们想要的责任。为了确保每个数据点上的所有责任加起来等于 1,我们在分母中添加了归一化常数:

但是我们的数据是三维向量,即[红、绿、蓝]。Scipy 提供了计算多元正态分布的便捷函数。检查这个

也就是 multivariate _ normal . pdf([数据点],mean =[均值向量],cov =[协方差矩阵])

我们后面会讲到如何计算 M 步的均值向量和协方差矩阵。

# data (numpy array) : array of observations
# weights (numpy array) : numpy array of weight of each clusters of size (1, n_clusters)
#means (numpy array) : numpy array of means of each clusters of size (n_cluster, dimension)
#covariances(numpy array) : numpy array of covariance metrix of size (n_clusters, dimension, dimension)
def get_responsibilities( data, weights, means, covariances):n_data = len(data)n_clusters = len(means)resp = np.zeros((n_data, n_clusters))for i in range(n_data):for k in range(n_clusters):resp[i, k] = weights[k]*   multivariate_normal.pdf(data[i],means[k],covariances[k],allow_singular=True)# Add up responsibilities over each data point and normalizerow_sums = resp.sum(axis=1)[:, np.newaxis]resp = resp / row_sumsreturn resp

记住这个责任是我们潜在的变量。

M 步:

现在计算了聚类责任,我们必须更新与每个聚类相关的聚类参数,即(权重(πk)、均值(μk)和协方差(σk))。

更新权重:

聚类权重给出了每个聚类代表所有数据点的多少。数学上它被定义为:

python 代码

# resp(numpy array) : responsibility numpy array size (n_sample, n_clusters)
def get_soft_counts(resp):return np.sum(resp, axis=0)# counts (numpy array) : count list of sum of soft counts for all clusters of size (n_cluster)
def get_weights(counts):n_clusters = len(counts)sum_count = np.sum(counts)weights = np.array(list(map(lambda k : counts[k]/sum_count, range(n_clusters))))return weights

更新的意思是:

每个分类的平均值等于所有数据点的加权平均值,由分类责任进行加权。数学上,对于每个数据点,第 k 个集群的 xi 和责任 rik 是第 k 个集群的平均值,可以定义为:

python 代码

# data (numpy array): array of observation points
# resp (numpy array) : responsibility numpy array size (n_sample, n_clusters)
# counts (numpy array) : count list of sum of soft counts for all clusters of size (n_cluster) 
def _get_means( data, resp, counts):n_clusters = len(counts)n_data = len(data)means = np.zeros((n_clusters, len(data[0])))for k in range(n_clusters):weighted_sum = reduce(lambda x,i : x + resp[i,k]*data[i],  range(n_data), 0.0)means[k] = weighted_sum/counts[k]return means

更新协方差:

每个集群的协方差等于由集群责任加权的所有外部产品的加权平均值。数学上它被定义为:

在哪里

是外积。让我们举一个简单的例子,看看外部产品是什么样子的。

是两个向量,那么 a 和 b 的外积定义为:

转置只是为了把列向量变成行向量。因为按照惯例,向量在机器学习中表示为列向量。

python 代码

# data (numpy array) : array of observation points
# resp(numpy array) : responsibility numpy array size (n_sample, n_clusters)
# counts (numpy array) : count list of sum of soft counts for all clusters of size (n_cluster)
# means (numpy array) : numpy array of means of each clusters of size (n_cluster, dimension)
def _get_covariances( data, resp, counts, means):n_clusters = len(counts)dimension = len(data[0]) # to get dimention of datan_data = len(data)covariances = np.zeros((n_clusters, dimension, dimension))for k in range(n_clusters):weighted_sum = reduce (lambda x, i :x + resp[i,k] *  np.outer((data[i]-means[k]), (data[i]- means[k]).T), range(n_data), np.zeros((dimension, dimension)))covariances[k] = weighted_sum /counts[k] # normalize by total sum of countsreturn covariances

而是我们将如何度量我们的混合高斯模型。为此,我们将计算高斯混合的对数似然。它量化了在特定参数(即均值、协方差和权重)下观察到一组给定数据的概率。我们将继续使用不同的参数集迭代 EM 算法,并检查其收敛性,即对数似然不会改变太多,或者直到固定的迭代次数。

Python 代码

# Z (numpy array) : numpy array of size (1, n_clusters)
def _ln_sum_exp( Z):return np.log(np.sum(np.exp(Z)))# data (numpy array) : array of observation points
# weights (numpy array) : numpy array of weight of each clusters ofsize (1, n_clusters)
# means (numpy array) : numpy array of means of each clusters of size (n_cluster, dimension)
# covs (numpy array) : numpy array of covariance metrix of size (n_clusters, dimension, dimension)
def get_log_likelihood( data, weights, means, covs):n_clusters = len(means)dimension = len(data[0])sum_ln_exp = 0for d in data:Z = np.zeros(n_clusters)for k in range(n_clusters):# compute exponential term in multivariate_normaldelta = np.array(d) — means[k]inv = np.linalg.inv(covs[k])exponent_term = np.dot (delta.T, np.dot (inv, delta))# Compute loglikelihood contribution for this data point and this clusterZ[k] += np.log (weights[k])det = np.linalg.det(covs[k])Z[k] -= 1/2\. * (dimension * np.log (2*np.pi) + np.log (det) + exponent_term)# Increment loglikelihood contribution of this data point across all clusterssum_ln_exp += _ln_sum_exp(Z)return sum_ln_exp

现在是 EM 算法的实际主要实现方法的时候了

Python 代码

# data (numpy array) : array of observation points
# init_weights (numpy array) : numpy array of initial weight of each clusters ofsize (1, n_clusters)
# init_means (numpy array) : numpy array of initial means of each clusters of size (n_cluster, dimension)
# init_covariances (numpy array) : numpy array of initial covariance metrix of size (n_clusters, dimension, dimension)
# maxiter (int) : maximum iteration to rum EM (optional)
# threshold (float) : maximum threshold to stop EM (optional)
def em_from_parameter(data, init_means, init_covariances, init_weights, maxiter=1000, thresh=1e-4):# Make copies of initial parametersmeans = init_means[:]covariances = init_covariances[:]weights = init_weights[:]# Infer length of datasetn_data = len(data)# Infer number of clustern_clusters = len(means)# Initialize some useful variablesresp = np.zeros((n_data, n_clusters), dtype=np.float64)l1 = get_log_likelihood(data, weights, means, covariances)l1_list = [l1]for it in range(maxiter):# E-step: calculate responsibilitiesresp = get_responsibilities(data, weights, means, covariances)# M-step calculate cluster parametercounts = get_soft_counts(resp)weights = _get_weights(counts)means = _get_means(data, resp, counts)covariances = _get_covariances(data, resp, counts, means)l1_new = get_log_likelihood(data, weights, means, covariances)l1_list.append(l1_new)if abs(l1_new – l1) < thresh :breakl1 = l1_newparam = {'weights': weights, 'means': means, 'covariances': covariances, 'loglikelihood': l1_list, 'responsibility': resp, 'Iterations': it}return param

现在都准备好了,但是我们的初始参数是什么。我们有许多方法可以采用。

一种方法是相等地初始化所有聚类的权重,即每个聚类的(1/k ),其中 k 是聚类的总数。

1 个聚类的协方差矩阵的初始化是维数等于数据维数*数据维数的对角方阵(在这种情况下,数据维数是 3,即[r,g,b])

其中,σxy =是 x 和 y 之间的协方差

对于均值初始化来说,有点棘手。还记得 k 均值算法吗?我们使用这些算法的输出来初始化我们的 EM 均值参数。因为通过使用 k-均值算法,我们推动均值坐标到达最近的收敛点。因此,如果我们从这一点出发,EM 算法将花费更少的时间来收敛。但是有一个问题,我们将如何初始化 k 均值的初始质心。

嗯。对于这个问题,我们将采用 k mean++初始化策略,它选择 k 个彼此相距最远的质心。现在我们已经有了所有的三参数。

注意:完整的解决方案请看我的 git-hub 链接 PYTHONAPI 你会发现这个集群问题端到端的完整 Flask 代码,可以被任何客户端技术使用。我选择 Angular 8 作为客户端,其代码可在 ML_algorithmUI 上获得。

对于那些只想检查 EM 相关代码的人来说,链接是这个,它包含两个文件夹 Expectation _ Maximization 和 K_Mean,这两个文件夹分别包含相关代码。请浏览代码,如果您面临任何问题,请随时问我。

现在回到代码,这个程序的驱动代码

Python 代码

# k: number of clusters
# data: observations coming from distribution
# return final weights, means, covariances, list of loglikelihood till convergence and final responsibility of each observation and number of Iterations it takes till convergencedef em(k, data) :dimension = len(data[0])# mean co-ordinate of all clusters not recommended at all since it is a very bad method to initialized the mean points alternatively use the k-mean initializing method as discussed earlymeans = np.random.rand(k, dimension)#### alternate better method to initialize mean points by kmean ###### from KM import KM ## self created KM class available in my github repos## check K_Mean folder in listed github repos pathkm = KM()means, dont_require = km.kmeans(data, k) # return centroids and cluster assignmentscov = np.diag(np.var(data, axis=0)) # get covariance of data initialize by diagonal metrix of covariance of datacovariances = np.array([cov] * k) # initiate covariance metrix with diagonal element is covariance of dataweights = np.array([1/ k] * k) # initialize equal weight to all clustersreturn em_from_parameter(data, means, covariances, weights)

images_path = ['../image2.jpg ','../image2.jpg ',… ] #图像路径列表……..…………………………………………………………………………..(1)

########### Data generation ################
data = []
For path in images_path:data.append(get_image_feature(path))data = np.array(data)

现在我们的数据已经准备好了,k 的值,即集群的数量,都是个人的选择。为简单起见,我取 k = 4 意味着我们假设数据的分布来自 4 高斯分布。既然我们的数据和 k 值已经准备好了,那么我们就准备创建一个模型。

####### create model #######parameters = em(k, data) # store returned parameters of model along with responsibilities

. . . . . . ………………………………………………………………………….(2)

这需要时间,别担心,但最终,你会得到你想要的。现在,如果您有新的观察数据,您可以找出软分配,因为我们已经获得了正确的集群参数。

Python 代码

# data (numpy array) : array of observation points
# weights (numpy array) : numpy array of weight of each clusters of size (1, n_clusters)
# means (numpy array) : numpy array of means of each clusters of size (n_cluster, dimension)
# covs (numpy array) : numpy array of covariance metrix of size (n_clusters, dimension, dimension)
def get_responsibilities(self, data, weights, means, covariances):n_data = len(data)n_clusters = len(means)resp = np.zeros((n_data, n_clusters))for i in range(n_data):for k in range(n_clusters):resp[i, k] = weights[k]* multivariate_normal.pdf(data[i],means[k],covariances[k])# Add up responsibilities over each data point and normalizerow_sums = resp.sum(axis=1)[:, np.newaxis]resp = resp / row_sumsreturn resp

创建观察值的 numpy 数组,并使用 em 返回的参数调用该方法,如(2)所示,并将其传递给该函数,您将获得每个集群的软分配。例如,让你有一个带有路径的图像”../../test_example.jpg "

首先获取图像的[r,g,b ]向量,如(1)所示,您将得到类似于[0.9144867979,0.3184891297,0.2495567485 ]的内容,将这些数据以及返回的集群参数传递给 get _ responsibilities 函数。您将在参数变量中获得该值,即

**注意:**记住这个函数采用一个观察值数组,在这种情况下,我们只有一个图像,即一个观察值,所以首先将这个观察值转换成一个数组,然后调用这个函数。

data = np.array([ np.array([0.9144867979, 0.3184891297, 0.2495567485 ])])mean = parameters[‘means’]cov = parameters[‘covariances’]weights = parameters[‘weights’]resp = get_responsibilities(data, weights, mean, cov)

万岁,你得到了你的集群任务。我对一些截图做了一个基于网络的可视化结果。

我们来谈谈它是如何消除 k 均值的所有缺点的:

  1. 更好的初始化策略:因为我们使用 K mean++初始化策略,所以我们不太可能得到错误的集群结构。
  2. 变化的聚类密度:与 k 均值不同,它具有变化的聚类密度,这为我们提供了对具有各自聚类分配的观测值的概率估计。
  3. 离群点:离群点被考虑,因为它包含非常少的对其最近的集群的责任。

**结论:**最后我们可以说,任何具有原色集合的图像都可以用这种技术进行聚类。我们可以使用这种方法对任意数量的图像进行聚类。在这里,我只是举了一个简单的例子,主要颜色,但根据需要,特征生成可能会改变多种颜色的阴影。GMM 是最适合的情况下,你想要的概率图像分配到一个特定的集群。

现在是时候结束我的博客了,如果你真的对这段代码感兴趣,请访问我的 git-hub 链接,并随时贡献和提出改进建议。快乐学习…

链接和参考:

马丁·克拉瑟潜变量模型 Part-1 高斯混合模型与 EM 算法(2019 年 11 月 21 日):https://克拉瑟姆. github . io/2019/11/21/Latent-variable-models-Part-1/

ethen 8181:http://ethen 8181 . github . io/machine-learning/clustering/GMM/GMM . html

维基参考:https://en . Wikipedia . org/wiki/Expectation–maximization _ algorithm

谷歌开发者资源:https://Developers . Google . com/machine-learning/clustering/algorithm/advantage-visits

Group2Vec 用于高级分类编码

原文:https://towardsdatascience.com/group2vec-for-advance-categorical-encoding-54dfc7a08349?source=collection_archive---------33-----------------------

创建高基数类别的有价值的表示

在 Unsplash 上由 VanveenJF 拍摄的照片

对分类变量进行编码是每个机器学习项目中必需的预处理步骤。选择正确的编码技术是一项严肃而重要的任务。有许多选择:从经典的一键或整数映射到巧妙的目标编码或散列函数,最后得到更复杂的向量表示。

固定的收据是不存在的,采用一种技术而不是另一种技术是基于我们可以处理的数据类型和我们的分析范围。例如,one-hot 保持了类别的对称性,但是它很消耗内存。整数映射更简单,但是在类之间创建了无意义的关系。目标编码与目标直接相关,但如果应用不当,往往会过度拟合。嵌入表示是一种新趋势,包括分配一个神经网络来产生类别的感知向量表示。

在这篇文章中,我处理了一个点击欺诈识别的问题。我们的分析领域是移动设备,只有分类变量可供我们使用。我们的范围是从这个数据结构中提取值,引入一些用于分类编码的高级矢量化技术。共有三种不同的方法:前两种通过组计数和其他变换,应用手动创建矢量特征来管理数据;最新的是一个纯粹的神经网络结构,用于创建类别的深度表示,以某种方式,它倾向于从' ' (因此得名 Group2Vec)中提取值。

数据

通话数据和跟踪欺诈检测是卡格尔为通话数据*主办的挑战,该平台是中国最大的独立大数据服务平台,覆盖全国 70%以上的移动设备。他们每天处理 30 亿次点击,其中 90%是潜在的欺诈。他们目前为应用程序开发人员防止点击欺诈的方法是,测量用户在他们的文件夹中点击的行程,并标记产生大量点击但从未安装应用程序的 IP 地址。利用这些信息,他们建立了一个 IP 黑名单和设备黑名单。*他们需要构建一个算法,来预测用户点击移动应用广告后是否会下载应用。为此,他们提供了一个丰富的数据集,在 4 天内覆盖了大约 2 亿次点击!

可用信息以点击记录的形式存在,具有以下结构: ip、app、device、os、channel、点击时间、归属时间,是归属(我们的目标)。阅读和使用所有怪物数量的数据是出于我们的目的。我们提取了 3 个时间样本:第一个(200.000 次点击)用于 train,另两个(每次 50.000 次点击)用于验证和测试;我们还提供了验证和测试之间的时间下降,以提高结果的可靠性。

列车集中时间函数的标签分布

我们掌握的有价值的变量是 ip、应用、设备、操作系统、渠道;均为分类式。每个特性的大量类是我们想要评估的一个积极方面。从这个意义上说,经典的编码方法并没有发挥出最好的效果,我们需要更多,因此,我们建立了一些特殊而有趣的方法。分组计数是开发我们先进编码技术的两个神奇元素,它们是从我们手工特征工程过程的第一步开始引入的。最后,我们尝试在不需要人工工程的情况下,创建一个足够聪明的神经网络结构,以产生有价值且可比的结果,但让我们按顺序进行!

组计数+截断的 SVD

我们介绍的第一种技术利用了截断奇异值分解(LSA),LDA 或类似的方法也是很好的选择。如前所述,我们的范围是对我们的分类列进行编码,生成其中每个类的向量表示。这里是模式化的过程:

  • 分组依据各分类变量训练(分组依据);
  • 对于每一个剩余的分类变量( passive_key ),我们按组计算可用类的连接,就像它们是字符串一样。每对 group_key — passive_key 是一串来自 passive_key 域的类;
  • 用 CountVectorizer 将字符串检索为数字编码;
  • 然后用截断的 SVD 来减少所得到的稀疏矩阵。

这样,我们获得了每个分类变量的每个类别的向量表示,作为截断 SVD 向量的串联。向量的长度取决于归约分量的数量和串联的数量,由所有可能的组合(n_compn_cat(n_cat-1))导出。在我们的例子中,3 是简化组件的数量,每个变量中的每个类是一个长度为 60(3 * 5 * 5(5–1))的向量。为了澄清,没有出现在 trainset 或 NaN 中的类别类在早期被编码为 0。

所创建的特征对于每一种进一步的任务都是有用的。我们用它们来构建欺诈性点击预测的模型。使用一个简单的 RandomForest,在验证上进行调整,我们在看不见的测试数据上达到 0.908 AUC。

数据特性方面的 TNSE(左起:app、ip、渠道)

组计数+熵

如上所述,第二种技术采用人工分组的方式将原始范畴转换成数字。这里是图解程序:

  • groupby 按每个分类变量训练(group _ key);
  • 依次对每个剩余的分类变量( passive_key ),计算未堆叠计数矩阵。其中在第一维上我们有 group_key 类,而在第二维上我们有 passive_key 类。交集是分组计数频率;
  • 对行应用熵来总结计数事件。

通过这种方式,我们获得了作为熵值串联的每个分类变量的每个类别的向量表示。因为熵是单个标量值,所以向量表示的长度取决于由所有可能的适用组合(n_cat*(n_cat-1))导出的串联的数量。在我们的例子中是 20(5 * 5(5–1))。

如下所示,我们使用生成的特征集来输入机器学习模型,该模型预测哪些点击是欺诈性的。使用一个简单的 RandomForest,在验证上进行调整,我们在看不见的测试数据上达到了 0.896 的 AUC。

验证数据方面的 TNSE(左起:应用、ip、渠道)

Group2Vec

在本节中,我们将介绍一种自动技术,它试图为我们制作所有以前的手工特征工程。由于神经网络和深度学习的力量,这种神奇是可能的。这个任务的架构被称为 Group2Vec(在示意图可视化下方)。

Group2Vec 架构

它接收表格分类特征作为输入,并试图以监督的方式学习它们的有价值的嵌入表示。这个问题对于神经网络来说并不新鲜:最简单的模型学习分类数据的嵌入表示,训练嵌入层,最后,在输出之前连接所有的分类数据。我们的策略既简单又有效:

  • 为每个分类输入初始化嵌入层;
  • 对于每个类别,在其他嵌入表示中计算点积。这些是我们在分类层次上的'
  • 汇总各'*'组'*采用平均汇集;
  • 串接'*'组'*平均值;
  • 应用正规化技术,如批处理正规化或退出;
  • 输出概率。

在我们的特定任务上训练的组 2Vec 在测试数据上实现了 0.937 的 AUC。

验证数据方面的 TNSE(左起:应用、ip、渠道)

摘要

在这篇文章中,我介绍了一些分类编码的高级技术。它们不同于随处可得的标准方法,如果在分类任务中采用,同时显示出巨大的预测能力。在具有大量类别的分类特征的情况下,它们的有用性是明显的,同时避免了维度和代表性问题。

查看我的 GITHUB 回购

保持联系: Linkedin

如何使用 SQL 对数据进行分组和聚合

原文:https://towardsdatascience.com/grouping-and-aggregating-data-using-sql-7ac85d654fe4?source=collection_archive---------20-----------------------

在保持社交距离的同时学习数据科学

使用 Spice Girls 示例说明如何使用 SQL 关键字 GROUP BY、MIN、MAX、COUNT、AVG 和 SUM 对数据进行分组和聚合

由 Kiana Bosman 在 Unsplash 上拍摄的照片

介绍

我非常喜欢和我的朋友一起分享我对数据科学的热爱。我们正在努力学习 SQL,已经学了三课了。如果你想从头开始,这里有一个第一课的链接。所有的课程也可以在这里找到。否则,请继续学习关于使用 SQL 对数据进行分组和聚合的课程。

前一课

上周,我们讨论了使用 SQL 过滤数据。使用我最喜欢的一个节目,比如数据,我们在查询中使用 WHERE 子句。此外,我们还探讨了关键字 In、AND、OR、LIKE、BETWEEN 和 NOT 的用法。

这一课

现在我们知道了如何过滤数据,我们将转向聚合。我们将学习如何使用关键字 MIN 和 MAX 来分别查找数据的最小值和最大值。我们还将以类似的方式练习使用计数、AVG 和求和关键字。

这也将是我们遇到空值的第一课。所以我们将学习如何在我们的数据集中处理它们。

碰巧的是,我教数据科学的所有朋友都是女性。因此,在这节课中,还有什么比辣妹组合更好的例子来庆祝一点女孩的力量呢?我们将使用辣妹第一张专辑《辣妹》的数据。这是我成长过程中在我家经常看到的。

主要学习内容:

  • 使用关键字 MIN 查找列中的最小值
  • 使用关键字 MAX 查找列中的最大值
  • 使用关键字 COUNT 计算列或表格中的行数
  • 使用关键字 AVG 查找数字列的平均值
  • 当所有值相加在一起时,使用关键字 SUM 来查找数字列的总计
  • 使用关键字 GROUP BY 按表中的列进行分组
  • 了解如何在上述方法中处理空值
  • 了解别名的工作原理以及如何使用 AS 关键字来创建它们

问题是

我认为辣妹的第一张专辑是最好的一张。以防别人不信,我想找点数据来佐证。用澳大利亚的排行榜数据来分析辣妹每张专辑的单曲,我想我可以证明第一条规则!

数据

该数据集包含辣妹组合发行的每张专辑中所有曲目的信息。这个表格包含了每首歌的长度,每首单曲发行的时间,这首歌在澳大利亚排行榜上的最高位置,以及这首歌在澳大利亚排行榜上的第几周。我没有包括最受欢迎的专辑,因为我认为这会混淆视听。

我从辣妹组合唱片维基百科页面、辣妹(专辑)维基百科页面、辣妹世界(专辑)维基百科页面、永远(辣妹专辑)和一个澳大利亚排行榜网站上获得了这张表的数据。

聚合数据的语法

在这一课中,我将教你如何在 SELECT 语句中使用聚合关键字 MIN、MAX、COUNT、SUM 和 AVG。这些聚合器也可以用在查询中的其他地方。例如,它们可以用在 HAVING 子句中,但这超出了本课的范围。我写了另一个故事来比较 SQL 中的 WHERE 和 HAVING,以防你想了解更多。

MAX 关键字可用于查找列中的最大值。它可以用于许多不同的数据类型,包括整数、浮点数、字符串和日期。

正如您在下面看到的,使用 MAX 的语法包括将 MAX 关键字放在 select 语句中。MAX 关键字后面有一组方括号,您可以在其中放置要查找其最大值的列名。

SELECT MAX(name_column_one) AS 'largest_col_one'
FROMname_of_table
;

可以与聚合器结合使用的另一个有用的关键字是 AS。AS 用于为聚合器在返回的表中创建的列创建别名或临时名称。因为聚合器已经用在列 1 上,所以给结果起一个新的名字是很有用的,这样它在结果表中很容易识别。关键字 AS 也可以用来给一个表起一个别名,但是我们将在关于连接表的课程中讨论这个问题。

MIN 关键字的用法与 MAX 关键字非常相似。如您所料,它用于返回所选列的最小值。

SELECT MIN(name_column_two) AS 'smallest_col_two'
FROMname_of_table
;

COUNT 是一个关键字,用于计算所选列中的行数。所以在下面的例子中,它会计算表中的总行数。

SELECT COUNT(name_column_three) AS 'col_three_counts'
FROMname_of_table
;

但是,当对表应用了一些过滤器或分组时,COUNT 更有用。在这种情况下,您将计算表中满足筛选或分组条件的行数。

SELECT COUNT(name_column_three) AS 'col_three_counts'
FROMname_of_table
WHEREname_column_one = value
;

与 MIN、MAX 和 COUNT 不同,关键字 SUM 和 AVG 只能用于包含数字数据类型(如整数或浮点数)的列。AVG 用于返回列的平均值。

SELECT AVG(name_column_four) AS 'mean_col_four'
FROMname_of_table
;

SUM 将数字列中的值相加。使用 SUM 的语法与其他聚合器相同。

SELECT SUM(name_column_five) AS 'summed_col_five'
FROMname_of_table
;

对数据分组的语法

分组对于汇总具有重复值的数据非常有用。它通常与聚合器 MIN、MAX、COUNT、SUM 和 AVG 一起使用。GROUP BY 将应用它的列中的相同值收集在一起。然后可以基于这些分组在另一列上使用聚合器。GROUP BY 子句通常用于包含类别值的列。

例如,如果将 AVG 聚合器与 GROUP BY 一起使用,则可以找到一列中每组值在另一列中的平均值。这个例子的语法如下所示。在这种情况下,返回的表将包含第一列中第二列中每个值的平均值。

SELECT AVG(name_column_one) AS mean_col_one, name_column_two
FROMname_of_table
GROUP BY name_column_two
;

空值会发生什么?

当字段中没有输入值时,就会出现空值。所以它就像一个占位符,让你知道表中有一个空的位置。它不同于 0 值或空字符串“”,因为它们仍然是值。NULL 有自己的关键字。

可以使用 IS NULL 关键字检查列中的空值。这是在 WHERE 语句中完成的,将只返回在 WHERE 语句中指定的列中包含 NULL 值的记录。

SELECT *
FROMname_of_table
WHEREname_column_one IS NULL
;

但是,更常见的情况是您希望排除所有包含空值的记录。在这种情况下,您可以在查询中添加 NOT 关键字。在下面的示例中,只有第二列中没有空值的记录才会包含在返回的表中。

SELECT *
FROMname_of_table
WHEREname_column_two IS NOT NULL
;

聚合关键字 MIN、MAX、AVG、SUM 和 COUNT 会忽略空值。对于最小值和最大值,这是相当简单的,您将在忽略所有空值的列中获得最小值或最大值。类似地,对于 SUM,列中所有不为空的值将被加在一起。对于 AVG,当所有空值都被删除时,您将获得列的平均值。

COUNT 只是稍微复杂一点,除了包含空值的行之外,所选列中的所有行将被计数。该规则的唯一例外如下所示。在这种情况下,无论是否有空值,都将计算表中的所有行。

SELECT COUNT(*)
FROM name_of_table
;

与聚合器不同,GROUP BY 不忽略空值。相反,它们被组合在一起作为单个分组类别。

现在让我们试着解决我们的问题

  1. 去http://sqlfiddle.com/(或者你可以用https://www.db-fiddle.com/,因为我发现 SQL fiddle 最近停机了一段时间)
  2. 在左边的框中放入创建表并插入到下面的查询中
CREATE TABLE spice_girls(album varchar(255),title varchar(255),length TIME(0),track_number int,single_released date,peak_chart_position_au int,chart_weeks_au int);INSERT INTO spice_girls(album,title,length,track_number,single_released,peak_chart_position_au,chart_weeks_au
)
VALUES("Spice", "Wannabe", '000:02:53', 1, '1996-07-08', 1, 29),("Spice", "Say You'll Be There", '000:03:55', 2, '1996-10-10', 12, 22),("Spice", "2 Become 1", '000:04:01', 3, '1996-12-16', 2, 18),("Spice", "Love Thing", '000:03:38', 4, NULL, NULL, NULL),("Spice", "Last Time Lover", '000:04:11', 5, NULL, NULL, NULL),("Spice", "Mama", '000:05:04', 6, '1997-02-27', 13, 14),    ("Spice", "Who Do You Think You Are", '000:04:00', 7, '1997-02-27', 13, 14),("Spice", "Something Kinda Funny", '000:04:05', 8, NULL, NULL, NULL),("Spice", "Naked", '000:04:25', 9, NULL, NULL, NULL),("Spice", "If U Can't Dance", '000:03:48', 10, NULL, NULL, NULL),("Spice World", "Spice Up Your Life", '000:02:53', 1, '1997-10-06', 8, 20),("Spice World", "Stop", '000:03:24', 2, '1997-01-01', 5, 21),("Spice World", "Too Much", '000:04:31', 3, '1997-12-08', 9, 15),("Spice World", "Saturday Night Divas", '000:04:25', 4, NULL, NULL, NULL),("Spice World", "Never Give Up on the Good Times", '000:04:30', 5, NULL, NULL, NULL),("Spice World", "Move Over", '000:02:46', 6, NULL, NULL, NULL),    ("Spice World", "Do It", '000:04:04', 7, NULL, NULL, NULL),("Spice World", "Denying", '000:03:46', 8, NULL, NULL, NULL),("Spice World", "Viva Forever", '000:05:09', 9, '1998-07-20', 2, 21),("Spice World", "The Lady Is a Vamp", '000:03:09', 10, NULL, NULL, NULL),("Forever", "Holler", '000:04:15', 1, '2000-10-23', 2, 15),("Forever", "Tell Me Why", '000:04:13', 2, NULL, NULL, NULL),("Forever", "Let Love Lead the Way", '000:04:57', 3, '2000-10-23', 2, NULL),("Forever", "Right Back at Ya", '000:04:09', 4, NULL, NULL, NULL),("Forever", "Get Down with Me", '000:03:45', 5, NULL, NULL, NULL),("Forever", "Wasting My Time", '000:04:13', 6, NULL, NULL, NULL),    ("Forever", "Weekend Love", '000:04:04', 7, NULL, NULL, NULL),("Forever", "Time Goes By", '000:04:51', 8, NULL, NULL, NULL),("Forever", "If You Wanna Have Some Fun", '000:05:25', 9, NULL, NULL, NULL),("Forever", "Oxygen", '000:04:55', 10, NULL, NULL, NULL),("Forever", "Goodbye", '000:04:35', 11, '1998-12-07', 3, 16)
;

**关于特殊字符的注意事项:**在创建这个表格的过程中,我们遇到了一个新的语法上的细微差别,这是我们在前面的课程中没有看到的。一些歌曲名称包含撇号。因此,如果我们像往常一样用单引号''将歌曲名称字符串括起来,就会出现错误。这是因为撇号会被程序误认为是结束引用。因此,要在我们的表中包含一个包含撇号的字符串,我们需要在字符串周围使用双引号。

如果需要一个包含双引号的字符串,也可以反过来。如果你想了解更多关于引号这样的特殊字符,这是一个很好的资源。

**关于时间数据类型的注意事项:**这个表中还有一个数据类型,我们在前面的任何课程中都没有见过。它是时间数据类型。时间的格式为“小时:分钟:秒”。

3.单击“构建模式”按钮

4.在右边的框中输入您的问题

5.运行下面的查询,看看它是否会返回您所期望的结果:

SELECTSUM(length) AS 'total_length'
FROM spice_girls
;

6.运行下面的查询,看看它是否会返回您所期望的结果:

SELECTSUM(length) AS 'album_length', album
FROM spice_girls
GROUP BY album
;

7.运行下面的查询,看看它是否会返回您所期望的结果:

SELECTalbum,SUM(length) AS 'album_length', AVG(length) AS 'average_song_length',COUNT(length) AS 'number_of_songs',MIN(length) AS 'shortest_song_length',MAX(length) AS 'longest_song_length'
FROM spice_girls
GROUP BY album
ORDER BY album
;

练习 1: 写一个查询,显示哪张专辑是最好的,如果我们把最好的专辑定义为其中一张单曲的最高峰值排行榜位置。

练习 2: 如果我们将最佳专辑定义为专辑中所有单曲的平均峰值排行榜位置最高的专辑,编写一个查询来显示哪张专辑是最佳专辑。

练习 3: 写一个查询,显示哪张专辑是最好的,如果我们把最好的专辑定义为在澳洲排行榜上至少 5 周单曲数最高的那张专辑。

学习回顾

学完本课后,你应该知道:

  • 如何使用关键字 MIN 查找列中的最小值
  • 如何使用关键字 MAX 查找列中的最大值
  • 如何使用关键字 COUNT 计算列或表格中的行数
  • 如何使用关键字 AVG 来寻找一个数字列的平均值
  • 当所有值相加时,如何使用关键字 SUM 来计算数字列的总和
  • 如何使用关键字 GROUP BY 按表中的列进行分组
  • 了解如何处理空值
  • 能够使用上述一种或多种方法编写自己的查询
  • 能够使用 AS 关键字为聚合列创建别名

下一课

下周将是我们最后一堂 SQL 课。我们将学习如何将表连接在一起。我们可以使用 UNION、UNION ALL 和 JOIN 关键字以几种不同的方式组合数据集。如果你渴望在下周之前开始研究连接,我之前写过一篇关于 SQL 中内部和外部连接的区别的文章。

除了数据,我的另一个爱好是绘画。你可以在 www.katemarielewis.com 的找到我的野生动物艺术

社交距离学习数据科学的所有课程(LDSWSD)

[## Ldswsd -走向数据科学

阅读《走向数据科学》中关于 Ldswsd 的文章。共享概念、想法和代码的媒体出版物。

towardsdatascience.com](https://towardsdatascience.com/tagged/ldswsd)

国际足联 20 |第 1 部分:K-均值聚类

原文:https://towardsdatascience.com/grouping-soccer-players-with-similar-skillsets-in-fifa-20-part-1-k-means-clustering-c4a845db78bc?source=collection_archive---------37-----------------------

机器学习中的聚类分析

机器学习中的聚类算法教程的第 1 部分

由托马斯·塞勒在 Unsplash 上拍摄的照片

视频版本

介绍

足球(欧洲足球)是我从小就喜欢的运动之一。我过去无论去哪里都带着一个球,这样我就可以最大限度地利用踢足球的机会。

我也喜欢踢足球——国际足联。我觉得用机器学习来分析国际足联的球员会很酷。

在本教程中,我将使用 K-Means 聚类算法对 FIFA 20 中具有相似技能的足球运动员进行分组。

了解聚类

聚类是一种无监督学习技术(PCA 是另一种)。

我们可以将观测值聚类(或分组)到相同的子组中,使得子组中的观测值彼此非常相似,而不同子组中的观测值彼此非常不同。

聚类示例

上面的散点图向我们展示了数据集中有三个不同的组。

了解 K-均值聚类

K-Means 聚类是聚类算法的一种。

基本算法是这样的:

  • 指定 K 簇并初始化随机质心
  • 迭代直到集群分配停止变化。该方法将每个观察精确地分配给 K 个聚类中的一个
  • 对于每个 K 分类,计算分类平均值
  • 继续查看观察值列表,并将一个观察值分配给平均值最接近的群集。

目标是以这样一种方式形成聚类,即同一聚类内的观察尽可能相似。

K-Means 聚类使用平方欧几里得距离计算相似性。

数据集

我们准备用 Kaggle 的 FIFA 20 数据集

特征工程

我们将只选择数字值和每个玩家的名字。

df = df[['short_name','age', 'height_cm', 'weight_kg', 'overall', 'potential','value_eur', 'wage_eur', 'international_reputation', 'weak_foot','skill_moves', 'release_clause_eur', 'team_jersey_number','contract_valid_until', 'nation_jersey_number', 'pace', 'shooting','passing', 'dribbling', 'defending', 'physic', 'gk_diving','gk_handling', 'gk_kicking', 'gk_reflexes', 'gk_speed','gk_positioning', 'attacking_crossing', 'attacking_finishing','attacking_heading_accuracy', 'attacking_short_passing','attacking_volleys', 'skill_dribbling', 'skill_curve','skill_fk_accuracy', 'skill_long_passing', 'skill_ball_control','movement_acceleration', 'movement_sprint_speed', 'movement_agility','movement_reactions', 'movement_balance', 'power_shot_power','power_jumping', 'power_stamina', 'power_strength', 'power_long_shots','mentality_aggression', 'mentality_interceptions','mentality_positioning', 'mentality_vision', 'mentality_penalties','mentality_composure', 'defending_marking', 'defending_standing_tackle','defending_sliding_tackle', 'goalkeeping_diving','goalkeeping_handling', 'goalkeeping_kicking','goalkeeping_positioning', 'goalkeeping_reflexes']]

我正在抽取工装裤在 86 以上的玩家,因为我们不想用 18000 以上的玩家来分组。

df = df[df.overall > 86] # extracting players with overall above 86

用平均值替换空值。

df = df.fillna(df.mean())

使数据正常化(标准化/重新标度)。

  • 我们希望将数据标准化,因为变量是在不同的尺度上测量的。
from sklearn import preprocessingx = df.values # numpy arrayscaler = preprocessing.MinMaxScaler()x_scaled = scaler.fit_transform(x)X_norm = pd.DataFrame(x_scaled)

使用主成分分析将该图的 60 维减少到 2 维。

from sklearn.decomposition import PCApca = PCA(n_components = 2) # 2D PCA for the plotreduced = pd.DataFrame(pca.fit_transform(X_norm))

执行 K 均值聚类

我们将指定有 5 个集群。

from sklearn.cluster import KMeans # specify the number of clusterskmeans = KMeans(n_clusters=5)# fit the input datakmeans = kmeans.fit(reduced)# get the cluster labelslabels = kmeans.predict(reduced)# centroid valuescentroid = kmeans.cluster_centers_# cluster valuesclusters = kmeans.labels_.tolist()

通过添加玩家的名字和他们的集群创建一个新的数据框。

reduced['cluster'] = clustersreduced['name'] = namesreduced.columns = ['x', 'y', 'cluster', 'name']reduced.head()

可视化 K 均值聚类图

import matplotlib.pyplot as pltimport seaborn as sns%matplotlib inlinesns.set(style="white")ax = sns.lmplot(x="x", y="y", hue='cluster', data = reduced, legend=False,fit_reg=False, size = 15, scatter_kws={"s": 250})texts = []for x, y, s in zip(reduced.x, reduced.y, reduced.name):texts.append(plt.text(x, y, s))ax.set(ylim=(-2, 2))plt.tick_params(labelsize=15)plt.xlabel("PC 1", fontsize = 20)plt.ylabel("PC 2", fontsize = 20)plt.show()

k 均值聚类

看看基于玩家位置的集群是如何形成的,这很酷!

我希望你觉得这个教程有用,并期待下一个!

FIFA 20 中具有相似技能的足球运动员分组|第 2 部分:层次聚类

原文:https://towardsdatascience.com/grouping-soccer-players-with-similar-skillsets-in-fifa-20-part-2-hierarchical-clustering-839705f6d37d?source=collection_archive---------39-----------------------

机器学习中的聚类分析

机器学习中的聚类算法教程的第 2 部分

由托马斯·塞勒在 Unsplash 上拍摄的照片

视频版本

查看我的聚类算法系列 这里

在本教程中,我们将使用层次聚类对 FIFA 20 名球员进行分组!

了解分层聚类

  • 与 K-means 不同,不需要指定聚类数。
  • 结果汇总在一个树状图中,这是一个树形图,可以轻松解释数据并选择任意数量的聚类

基本思想

  • 焦点:自下而上(又名。凝聚聚类)
  • 从个人观察开始(又名。叶子成簇
  • 通过将叶子合并成分支向上移动
  • 将树枝与其他树叶或树枝合并
  • 最终,当所有的东西都合并成一个集群时,到达顶端

树状图示例

解读树状图

  • 在适当的高度切割,以获得所需的簇数
  • 纵轴:相异度(或距离)——两个聚类合并的高度
  • 高度代表聚类的相似性
  • 身高更低- >更相似
  • 横轴不表示相似性
  • 交换左右分支不会影响树状图的含义

它如何度量集群之间的不相似性?

  1. 基于公制的(曼哈顿距离或欧几里德距离——最常见)
  • 完全连锁(最远邻法)
  • 单一连锁(最近邻法)
  • 平均连锁
  • 质心连杆机构

2.基于相关性的距离

  • 找出观察值之间的相关性

分层聚类的缺点

  1. 计算成本高—不适合大数据集
  • O(N log N),而 O(N)用于 K-means

2.对噪音和异常值敏感

使用层次聚类对 FIFA 20 球员进行分组

数据清理/预处理(第 1 部分的代码)

import pandas as pdimport numpy as npdf = pd.read_csv("/content/players_20.csv")df = df[['short_name','age', 'height_cm', 'weight_kg', 'overall', 'potential','value_eur', 'wage_eur', 'international_reputation', 'weak_foot','skill_moves', 'release_clause_eur', 'team_jersey_number','contract_valid_until', 'nation_jersey_number', 'pace', 'shooting','passing', 'dribbling', 'defending', 'physic', 'gk_diving','gk_handling', 'gk_kicking', 'gk_reflexes', 'gk_speed','gk_positioning', 'attacking_crossing', 'attacking_finishing','attacking_heading_accuracy', 'attacking_short_passing','attacking_volleys', 'skill_dribbling', 'skill_curve','skill_fk_accuracy', 'skill_long_passing', 'skill_ball_control','movement_acceleration', 'movement_sprint_speed', 'movement_agility','movement_reactions', 'movement_balance', 'power_shot_power','power_jumping', 'power_stamina', 'power_strength', 'power_long_shots','mentality_aggression', 'mentality_interceptions','mentality_positioning', 'mentality_vision', 'mentality_penalties','mentality_composure', 'defending_marking', 'defending_standing_tackle','defending_sliding_tackle','goalkeeping_diving','goalkeeping_handling', 'goalkeeping_kicking','goalkeeping_positioning', 'goalkeeping_reflexes']]df = df[df.overall > 86] # extracting players with overall above 86df = df.fillna(df.mean())names = df.short_name.tolist() # saving names for laterdf = df.drop(['short_name'], axis = 1) # drop the short_name columndf.head()

标准化数据

from sklearn import preprocessingx = df.values # numpy arrayscaler = preprocessing.MinMaxScaler()x_scaled = scaler.fit_transform(x)X_norm = pd.DataFrame(x_scaled)

平均链接的层次聚类

import matplotlib.pyplot as pltimport scipy.cluster.hierarchy as sch# plot dendrogram using average linkageplt.figure(figsize=(10,14))plt.title('Hierarchical Clustering Dendrogram with Average Linkage')dendrogram = sch.dendrogram(sch.linkage(X_norm, method="average"), labels= names, leaf_font_size = 13, orientation='right')

  • 分成两个位置——守门员和其他人

单键

# plot dendrogram using single linkageplt.figure(figsize=(10,14))plt.title('Hierarchical Clustering Dendrogram with Single Linkage')dendrogram = sch.dendrogram(sch.linkage(X_norm, method="single"), labels= names, leaf_font_size = 13, orientation='right')

  • 分成守门员和其他人

质心连杆机构

# plot dendrogram using centroid linkageplt.figure(figsize=(10,14))plt.title('Hierarchical Clustering Dendrogram with Centroid Linkage')dendrogram = sch.dendrogram(sch.linkage(X_norm, method="centroid"), labels= names, leaf_font_size = 13, orientation='right')

  • 再一次,分成守门员和其他人

完全连锁

# plot dendrogram using complete linkageplt.figure(figsize=(10,14))plt.title('Hierarchical Clustering Dendrogram with Complete Linkage')dendrogram = sch.dendrogram(sch.linkage(X_norm, method="complete"), labels= names, leaf_font_size = 13, orientation='right')

结论

完全联动似乎对玩家分组最准确!

感谢你阅读这篇文章,希望你觉得有用!

GitHub 回购:https://github.com/importdata/Clustering-FIFA-20-Players

FIFA 20 中具有相似技能的足球运动员分组|第 3 部分:DBSCAN

原文:https://towardsdatascience.com/grouping-soccer-players-with-similar-skillsets-in-fifa-20-part-3-dbscan-b23389a08cc7?source=collection_archive---------43-----------------------

机器学习中的聚类分析

机器学习中的聚类算法教程的第 3 部分

由托马斯·塞勒在 Unsplash 上拍摄的照片

视频版本

查看我的聚类算法系列 这里

在本教程中,我们将使用 DBSCAN 算法对 FIFA 20 名球员进行分组!

了解 DBSCAN

  • 基于密度的含噪声应用空间聚类
  • 基于密度的聚类定位被低密度区域彼此分开的高密度区域
  • 密度:指定半径内的点数。Eps 或ε)

  • 核心点:如果一个点在 Eps 内有超过规定的点数(分点数)
  • 边界点:它在 Eps 内的分点少于,但在核心点的附近
  • **噪声(离群点):**不是核心点或边界点的任何点

核心、边界、异常值示例

集群是如何形成的?

  1. 选择一个点 p
  2. 检索从 p . w . r . t . EPS 和 MinPts 可达到的所有点密度。
  • 如果 p 是一个核心点,就形成了一个集群。
  • 如果 p 是一个边界点,没有点是从 p 密度可达的,DBSCAN 访问数据库的下一个点。

3.继续该过程,直到处理完所有点。

4.结果与处理点的顺序无关

ε-邻域概念

  • 距离一个物体ε半径内的物体
  • 核心对象:一个对象的ε-邻域至少包含个对象的 MinPts

p 是一个核心对象

能达到性

  • 直接密度可达:如果 q 在 p 的ε-邻域内,且 p 是核心点,则点 q 是从 p 直接密度可达的。

q 是从 p 直接密度可达的

  • 密度可达:如果点“p”距离点“q”在ε距离内,并且“q”在它的相邻点中有足够多的点在ε距离内,则称点“p”是从点“q”密度可达的。

q 是从 p 密度可达的吗

连通性

  • 密度-连通性:如果有一个点 r 使得 p 和 q 是从 r w.r.t 和 MinPts 密度可达的,则点 p 是密度-连通到点 q w.r.t 和 MinPts 的

q 通过 r 与 p 密度相关

优点、缺点和应用

使用 DBSCAN 对 FIFA 20 名球员进行分组

数据清理/预处理(第 1 部分和第 2 部分的代码)

import pandas as pdimport numpy as npdf = pd.read_csv("/content/players_20.csv")df = df[['short_name','age', 'height_cm', 'weight_kg', 'overall', 'potential','value_eur', 'wage_eur', 'international_reputation', 'weak_foot','skill_moves', 'release_clause_eur', 'team_jersey_number','contract_valid_until', 'nation_jersey_number', 'pace', 'shooting','passing', 'dribbling', 'defending', 'physic', 'gk_diving','gk_handling', 'gk_kicking', 'gk_reflexes', 'gk_speed','gk_positioning', 'attacking_crossing','attacking_finishing','attacking_heading_accuracy', 'attacking_short_passing','attacking_volleys', 'skill_dribbling', 'skill_curve','skill_fk_accuracy', 'skill_long_passing','skill_ball_control','movement_acceleration', 'movement_sprint_speed', 'movement_agility','movement_reactions', 'movement_balance', 'power_shot_power','power_jumping', 'power_stamina', 'power_strength', 'power_long_shots','mentality_aggression', 'mentality_interceptions','mentality_positioning', 'mentality_vision', 'mentality_penalties','mentality_composure', 'defending_marking', 'defending_standing_tackle','defending_sliding_tackle', 'goalkeeping_diving','goalkeeping_handling', 'goalkeeping_kicking','goalkeeping_positioning', 'goalkeeping_reflexes']]df = df[df.overall > 86] # extracting players with overall above 86df = df.fillna(df.mean())names = df.short_name.tolist() # saving names for laterdf = df.drop(['short_name'], axis = 1) # drop the short_name columndf.head()

标准化数据

from sklearn import preprocessingx = df.values # numpy arrayscaler = preprocessing.MinMaxScaler()x_scaled = scaler.fit_transform(x)X_norm = pd.DataFrame(x_scaled)

使用主成分分析将 60 列减少为 2 列

from sklearn.decomposition import PCApca = PCA(n_components = 2) # 2D PCA for the plotreduced = pd.DataFrame(pca.fit_transform(X_norm))

应用数据库扫描

from sklearn.cluster import DBSCAN# train the model using DBSCANdb = DBSCAN(eps=1, min_samples=5)# the prediction for dbscan clustersdb_clusters = db.fit_predict(reduced)

通过添加玩家的名字和他们的集群创建一个新的数据框

reduced['cluster'] = db_clustersreduced['name'] = namesreduced.columns = ['x', 'y', 'cluster', 'name']reduced.head()

绘制 DBSCAN

import matplotlib.pyplot as pltimport seaborn as sns%matplotlib inlinesns.set(style="white")ax = sns.lmplot(x="x", y="y", hue='cluster', data = reduced, legend=False,fit_reg=False, size = 10, scatter_kws={"s": 250})texts = []for x, y, s in zip(reduced.x, reduced.y, reduced.name): texts.append(plt.text(x, y, s)) ax.set(ylim=(-2, 2))plt.tick_params(labelsize=15)plt.xlabel("PC 1", fontsize = 20)plt.ylabel("PC 2", fontsize = 20)plt.show()

Eps = 1 且 MinPts = 5 时的 DBSCAN

  • 集群被组成守门员对抗其他的
  • 不太准确

找到一个最佳的ε

  • 通过计算每个点到最近的 n 个点的距离,排序并绘制结果,找到一个最佳ε。
from sklearn.neighbors import NearestNeighbors# calculate the distance from each point to its closest neighbornn = NearestNeighbors(n_neighbors = 2)# fit the nearest neighbornbrs = nn.fit(reduced)# returns two arrays - distance to the closest n_neighbors points and index for each pointdistances, indices = nbrs.kneighbors(reduced)# sort the distance and plot itdistances = np.sort(distances, axis=0)distances = distances[:,1]plt.plot(distances)

寻找最佳 Eps

  • 看起来曲率在 eps = 0.3 左右开始加快

使用新的 Eps 再次应用 DBSCAN

from sklearn.cluster import DBSCAN# train the model using DBSCANdb= DBSCAN(eps=0.3, min_samples=4)# prediction for dbscan clustersdb_clusters = db.fit_predict(reduced)reduced['cluster'] = db_clustersreduced['name'] = namesreduced.columns = ['x', 'y', 'cluster', 'name']reduced.head()

用新的 Eps = 0.3 和 MinPts = 4 再次绘图

import matplotlib.pyplot as pltimport seaborn as sns%matplotlib inlinesns.set(style="white")ax = sns.lmplot(x="x", y="y", hue='cluster', data = reduced, legend=False,fit_reg=False, size = 9, scatter_kws={"s": 250})texts = []for x, y, s in zip(reduced.x, reduced.y, reduced.name): texts.append(plt.text(x, y, s)) ax.set(ylim=(-2, 2))plt.tick_params(labelsize=10)plt.xlabel("PC 1", fontsize = 20)plt.ylabel("PC 2", fontsize = 20)plt.show()

Eps = 0.3、MinPts = 4 时的 DBSCAN 图

结论

Epsilon = 0.3 和 MinPts = 4 的 DBSCAN 在分组和检测异常值方面做得更好!

感谢你阅读这篇文章,希望你觉得有用!

GitHub 回购:https://github.com/importdata/Clustering-FIFA-20-Players

印度各邦新冠肺炎病例的增长率

原文:https://towardsdatascience.com/growth-rate-of-covid-19-cases-in-indian-states-738304ee9ebf?source=collection_archive---------58-----------------------

自 2020 年 4 月 22 日以来,印度各邦新冠肺炎病例增长率的简单、易于解释的可视化图。这将让我们了解哪些州在控制方面做得很好,哪些州在未来几天处于危险地带。

编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

这个想法

由于新冠肺炎造成的全球疫情现在已经延伸到 2020 年上半年之后,几个国家仍然每天报告数千例病例。世界各地的数据科学爱好者已经提出了一些预测、仪表盘和可视化方法,其中许多方法在这个前所未有的时代非常有用。

在这里,我尝试对阳性病例的比率进行州级比较,即 ,以尝试检测哪些州正在从相对安全的区域发展到危险的区域(潜在的热点),反之亦然。

我们如何比较?

重要的第一步是选择准确的比较标准。简单地说,每个州的病例数没有意义:

  1. 每个州进行的检测数量很可能影响报告的阳性病例数量。更多的检测几乎肯定会导致更多的病例报告。因此,阳性百分比(即阳性病例数/100 次检测)是一个合适的指标。
  2. 各州的人口也不能被视为无用的因素。你只会认为马哈拉施特拉邦或更远的地方会发生比果阿更严重的事故。阳性病例数/100K 人口是我们的第二个选项(选择 100K 也确保了结果缩小到与前面变量类似的范围)

然而,我们不应忽视这样一种可能性,即一个人口较多的国家正在进行与一个小得多的国家类似数量的检测,因此很可能也有类似数量的病例。在这种情况下,每 100,000 人口的病例数将不是一个非常合适的代表真实情况的指标,特别是***,因为不同州的检测存在显著差异的情况在我国非常相关。***

最终选择的指标

我上面所讨论的仅仅是我的直觉,仅仅基于此来选择或放弃影响变量是不公平的。为此进行了回归分析:

“每日测试次数”和“人群”是两个回归变量,而每日报告的病例数是预测变量。在单独和共同考虑变量后,比较 R 平方值显示“日常测试次数”占变异的大约 63%,而“总体”占变异的大约11%。这清楚地证明了**“每日测试次数”是更有影响力的变量**(我的直觉:D 也是如此)。然而,最好不要完全抛弃另一个因素。相反, 给两者适当的权重是最好的办法:分别为 0.84 和 0.16(基于 R 平方比较),从而将它们组合成一个新的变量。**

此外,我将执行 3 个不同的可视化(每个基于独立的可视化)和最后一个使用加权变量。

数据

我们的数据来源于下面的 GitHub 存储库,它致力于定期更新有关印度新冠肺炎的记录:https://github.com/imdevskp/covid-19-india-data

然而,并非所有的州都有足够的关于检测和报告的信息。因此,我只选择了 16 个州,这些州有严格的信息和足够的案例来进行研究。即使在过滤后的数据中,一些值也是不准确或荒谬的(例如,负数的情况;尽管测试为 0,但仍有阳性病例,等等)。它们已经被插值技术所取代。

包括可视化在内的整个过程的代码(将在下面显示)已记录在此:https://github . com/viper ville 007/Growth-rate-of-Indian-cases-in-States

可视化和解释:

日期的选择:4 月 22 日被选为起点。从此,我们可以通过 获得 有关检测和确诊病例的具体信息。此外,封锁已经实施了一个月,到那时,几乎所有被选中的州都有足够的设施进行测试,从而确保了同质性。

***平滑:**提供了近 90 个时间戳,绘制所有时间戳会使事情看起来 不必要的笨拙和难以解释 *。同样,如果我们关注每一天,一些 异常值是很有可能的 。我添加了 均值平滑到一个 7 天窗口的数据 来照顾这些问题。7 似乎是一个合理的选择,因为你会期望季节性每周都存在,如果它真的存在的话。

***注:*点击图片,您可以选择以更高的清晰度观看。

*

来源:自创*

这是我们所做的 3 个可视化中的第一个(第一个仅基于与进行的测试相关的阳性案例的百分比)。

基于配色方案的随附图例很好地总结了这一点:通俗地说,越接近黑色,该状态在该时间点的条件越安全(参考图下方的轴),黄色表示高危险。

*

来源:自创*

所以,这是单纯根据每个州 的病例数/10 万人口得出的**

正如你可能已经猜到的,这个情节本身并不是一个非常恰当的事情指标(它仅仅解释了我们之前看到的关系的 11%)。

在不强调这一点的情况下,让我们快速进入最后的情节(基于我创建的修改变量)。

*

来源:自创*

这是基于修改变量的最终可视化图(带有前两个变量的适当权重)。**

现在,让我们试着从中得出一些结论:

  1. 理想的情况是,截止到最新时间戳的颜色方案接近黑色(非常低的增长率)
  2. 从黄色到紫色的趋势表明,该州的传播曾经非常高,但正在逐渐放缓。
  3. 相反的趋势(从紫色到黄色)表明存在风险——在接下来的几天里,情况只会变得更糟。基本上,麻烦。
  4. 综上所述,德里正显示出放缓的迹象(从曾经非常糟糕的状态)。古吉拉特邦和哈里亚纳邦在某种程度上显示出类似的模式。
  5. 这是西孟加拉邦、安得拉邦、比哈尔邦和卡纳塔克邦关注的问题。这种趋势非常令人担忧。
  6. 泰米尔纳德邦和马哈拉施特拉邦没有任何值得注意的巨大差异——但是%仍然是最高的。
  7. 其他州(大部分在黑色地带)已经能够应付事情,或者没有像上面讨论的那样严重地成为病毒的牺牲品。它们也没有显示出很快会突然爆炸的迹象。

编辑 1:

我现在已经为选定的州制作了一个条形图比赛,以视频的形式显示进度。你可以在这里查看:https://app.flourish.studio/story/489625/edit
这里有一个相同的快照:

来源:自创

我们只能希望越来越多的地区开始出现与上述第二点类似的趋势。

非常感谢你,如果你有足够的耐心通读整篇文章。请随时留下您的真实反馈,指出这篇文章中存在的技术或印刷错误,或者在评论部分澄清您的疑问和疑问。干杯:)

GSoC 2020 与 CERN-HSF |暗物质和深度学习

原文:https://towardsdatascience.com/gsoc-2020-with-cern-hsf-dark-matter-and-deep-learning-eb611850bb79?source=collection_archive---------44-----------------------

这个博客是我在 HSF 欧洲核子研究中心的谷歌代码之夏(GSoC) 2020 项目的一个非常简短的总结。今年是谷歌代码之夏 16 周年,共有 6,626 名学生提交了 8,902 份提案,其中 1,198 名学生获得了与 199 个组织合作的机会。

图片来源:谷歌代码之夏

DeepLense 项目

项目描述

DeepLense 是一个深度学习管道,用于利用强引力透镜进行粒子暗物质搜索,是伞式组织 CERN-HSF 的一部分。具体来说,我的项目是题为“深度学习暗物质亚结构的形态学”的论文中发表的工作的扩展,在该论文中,我的导师探索了使用最先进的监督深度学习模型,如 ResNet,对强透镜图像进行多类分类。

自 1936 年爱因斯坦的计算中讨论引力透镜并于 1979 年发现以来,引力透镜一直是许多宇宙学实验和研究的基石,一个特别感兴趣的领域是通过强透镜图像中的亚结构研究暗物质。虽然统计和监督机器学习算法已经实现了这项任务,但无监督深度学习算法的潜力仍有待探索,并可能被证明在 LSST 数据的分析中至关重要。这个 GSoC 2020 项目的主要目标是设计一个基于 python 的框架,用于实现无监督的深度学习架构,以研究强透镜图像。

更多细节参见论文“无监督解码暗物质子结构”。

仓库

我已经将我的工作编译成了两个开源库。第一个名为 PyLensing ,这是一个基于 PyAutoLens 模拟生成透镜图像的工具,第二个名为 Unsupervised Lensing ,这是一个基于 PyTorch 的工具,用于强透镜宇宙学中的无监督深度学习应用。

关于我

我是 K·普拉纳斯·雷迪,荣誉理学硕士。物理学和理学士(荣誉)。)印度 Pilani Birla 理工学院(BITS)海德拉巴校区电气和电子工程专业。

为什么是 DeepLense?

作为一名物理系学生,我熟悉 CERN 的运作,并对该组织的许多相关项目有着基本的了解,我在宇宙学领域的深度学习应用方面做了大量工作。这一经历激励我为 DeepLense 项目做贡献。

数据

不同子结构的模拟样品透镜图像。无(左)、漩涡(中)和球形(右)。|作者图片

我们的数据集由三类组成,没有子结构的强透镜图像、涡旋子结构和球形子结构。考虑到具有子结构的样本是异常值,我们将在一组没有子结构的强透镜图像上训练我们的无监督模型,以解决异常检测的任务。

我们已经生成了两组透镜图像,模型 A 和模型 b。我们已经使用 python 包 PyAutoLens 进行模拟。这两个模型之间的区别在于,模型 A 的所有模拟图像都保持在固定的红移,而模型 B 允许透镜星系和透镜星系的红移在一个数值范围内浮动。两种模型的另一个区别是信噪比。模型 A 的图像 SNR ≈ 20,而模型 B 的构造使得模拟产生的图像 SNR 在 10 到 30 之间变化。关于模拟的更多细节可以在的论文中找到。

无监督模型

我在异常检测的背景下研究并实现了各种无监督模型。在本节中,我将讨论四个模型,即深度卷积自动编码器(DCAE)、卷积变分自动编码器(VAE)、对抗自动编码器(AAE)和受限玻尔兹曼机器(RBM),以及使用我的 PyTorch 工具无监督透镜实现这些模型的代码。

深度卷积自动编码器(DCAE)

自动编码器是一种学习自身表示的神经网络,由编码器网络和解码器网络组成。编码器学习将输入样本映射到其维度低于输入样本维度的潜在向量,解码器网络学习从潜在维度重构输入。因此,自动编码器可以定性地理解为寻找给定类的最佳压缩表示的算法。

我们首先考虑深度卷积自动编码器,它主要用于图像的特征提取和重建。在训练期间,我们利用均方误差(MSE),

MSE 损失|作者图片

作为我们的重建损失,其中θ和θ’是真实的和重建的样本。

使用 PyTorch 工具实现:

**from** **unsupervised_lensing.models** **import** Convolutional_AE
**from** **unsupervised_lensing.models.DCAE_Nets** **import** *
**from** **unsupervised_lensing.utils** **import** loss_plotter **as** plt
**from** **unsupervised_lensing.utils.EMD_Lensing** **import** EMD*# Model Training*
out = Convolutional_AE.train(data_path='./Data/no_sub_train.npy', epochs=100,learning_rate=2e-3,optimizer='Adam',checkpoint_path='./Weights',         pretrain=**True**,                       pretrain_mode='transfer',            pretrain_model='A')                  *# Plot the training loss*
plt.plot_loss(out)*# Model Validation*
recon_loss = Convolutional_AE.evaluate(data_path='./Data/no_sub_test.npy', checkpoint_path='./Weights',        out_path='./Results')               *# Plot the reconstruction loss*
plt.plot_dist(recon_loss)*# Calculate Wasserstein distance*
print(EMD(data_path='./Data/no_sub_test.npy', recon_path='./Results/Recon_samples.npy'))

卷积变分自动编码器(VAE)

我们还考虑了一个变分自动编码器,它以 Kullback-Liebler (KL)散度的形式对潜在维度的表示引入了一个附加约束,

Kullback-Liebler (KL)散度|作者图片

其中 P(x)是目标分布,Q(x)是算法学习的分布。r.h.s .上的第一项是 P 和 Q 之间的交叉熵,第二项是 P 的熵。因此,KL 散度对分布 Q 离 P 有多远的信息进行编码。在变分自动编码器的情况下,KL 散度用作正则化,以在潜在空间上施加先验。出于我们的目的,P 被选择为在潜在空间 z 上采用高斯先验的形式,而 Q 对应于由编码器表示的近似后验 q(z|x)。模型的总损失是重建(MSE)损失和 KL 散度之和。

使用 PyTorch 工具实现:

from unsupervised_lensing.models import Variational_AE
from unsupervised_lensing.models.VAE_Nets import *
from unsupervised_lensing.utils import loss_plotter as plt
from unsupervised_lensing.utils.EMD_Lensing import EMD# Model Training
out = Variational_AE.train(data_path='./Data/no_sub_train.npy', epochs=100,learning_rate=2e-3,optimizer='Adam',checkpoint_path='./Weights',         pretrain=True,                      pretrain_mode='transfer',            pretrain_model='A')# Plot the training loss
plt.plot_loss(out)# Model Validation
recon_loss = Variational_AE.evaluate(data_path='./Data/no_sub_test.npy', checkpoint_path='./Weights',        out_path='./Results')# Plot the reconstruction loss
plt.plot_dist(recon_loss)# Calculate Wasserstein distance
print(EMD(data_path='./Data/no_sub_test.npy', recon_path='./Results/Recon_samples.npy'))

对抗性自动编码器(AAE)

最后,我们考虑一个对抗的自动编码器,它用对抗学习代替变分自动编码器的 KL 散度。我们训练鉴别器网络 D,以在由自动编码器 G 生成的样本和从对应于我们的训练数据的先验分布 P(z)获取的样本之间进行分类。该模型的总损耗是重建(MSE)损耗和鉴别器网络损耗之和,

鉴别器丢失|作者图片

我们另外向自动编码器添加以下形式的正则化项,

作者图片

随着自动编码器在重建输入方面变得熟练,鉴别器的能力下降。然后,鉴别器网络通过提高其区分真实数据和生成数据的性能来进行迭代。

使用 PyTorch 工具实现:

from unsupervised_lensing.models import Adversarial_AE
from unsupervised_lensing.models.AAE_Nets import *
from unsupervised_lensing.utils import loss_plotter as plt
from unsupervised_lensing.utils.EMD_Lensing import EMD# Model Training
out = Adversarial_AE.train(data_path='./Data/no_sub_train.npy', epochs=100,learning_rate=2e-3,optimizer='Adam',checkpoint_path='./Weights',         pretrain=True,                       pretrain_mode='transfer',            pretrain_model='A')# Plot the training loss
plt.plot_loss(out)# Model Validation
recon_loss = Adversarial_AE.evaluate(data_path='./Data/no_sub_test.npy', checkpoint_path='./Weights',        out_path='./Results')# Plot the reconstruction loss
plt.plot_dist(recon_loss)# Calculate Wasserstein distance
print(EMD(data_path='./Data/no_sub_test.npy', recon_path='./Results/Recon_samples.npy'))

受限玻尔兹曼机(RBM)

为了与我们的三个自动编码器模型进行比较,我们还训练了一个受限的波尔兹曼机器(RBM),这是一个生成式人工神经网络算法,实现为一个二分图,学习输入的概率分布。RBMs 由两层组成,一个隐藏层和一个可见层,其中训练是在一个称为对比发散的过程中完成的。

所有模型的详细架构可在论文的附录 B 中找到。

使用 PyTorch 工具实现:

from unsupervised_lensing.models import RBM_Model
from unsupervised_lensing.models.RBM_Nets import *
from unsupervised_lensing.utils import loss_plotter as plt
from unsupervised_lensing.utils.EMD_Lensing import EMD# Model Training
out = RBM_Model.train(data_path='./Data/no_sub_train.npy', epochs=100,learning_rate=2e-3,optimizer='Adam',checkpoint_path='./Weights',         pretrain=True,                       pretrain_mode='transfer',            pretrain_model='A')# Plot the training loss
plt.plot_loss(out)# Model Validation
recon_loss = RBM_Model.evaluate(data_path='./Data/no_sub_test.npy', checkpoint_path='./Weights',        out_path='./Results')# Plot the reconstruction loss
plt.plot_dist(recon_loss)# Calculate Wasserstein distance
print(EMD(data_path='./Data/no_sub_test.npy', recon_path='./Results/Recon_samples.npy'))

结果

我使用了 25,000 个没有子结构的样本和每类 2,500 个验证样本来训练和评估无监督模型。这些模型是使用 PyTorch 包实现的,并在单个 NVIDIA Tesla K80 GPU 上运行 500 个时代。我们利用 ROC 曲线下的面积(AUC)作为我们所有模型的分类器性能的度量。对于无监督模型,ROC 值是针对重建损失的设定阈值计算的。此外,我们还使用 Wasserstein 距离值来比较重建的保真度。一组更详细的结果可以在的论文中找到。

无监督算法的 ROC-AUC 曲线。左边的图对应于模型 A,右边的图对应于模型 b。|图片由作者提供

本分析中使用的体系结构的性能。ResNet 的 AUC 值是针对有和没有亚结构的图像分类计算的,因此它不是宏观平均 AUC。W₁是没有子结构的图像的平均第一瓦瑟斯坦距离。|作者图片

未来的工作和最后的想法

尽管我们的无监督模型得到了一些非常有希望的结果,但是与 ResNet 模型的监督结果相比,它们的性能仍有进一步改进的空间。我目前正在探索基于图的模型的应用,因为它们在与稀疏数据集相关的任务中取得了成功,如稀疏 3D 点云和稀疏探测器数据。另一个未来的任务是使用迁移学习,通过从我们已经在模拟上训练过的模型开始,在真实数据上训练我们的架构。

我要感谢我的导师迈克尔·图米、谢尔盖·格莱泽、斯蒂芬·亚力山大和伊曼纽·乌赛,以及整个欧洲粒子物理研究所-HSF 社区对我的支持。我在 GSoC 项目上度过了一个美好的夏天。我还要感谢阿里·哈里里、汉娜·帕鲁尔和赖克·冯·克拉尔进行了有益的讨论。

给以后想参加 GSoC 的同学们,不要把 GSoC 看成一个需要“破解”的竞赛或者考试。GSoC 是关于开源开发和成为优秀开发者社区的一部分。找到你热爱的项目,了解组织的需求。最重要的是,在社区论坛上保持活跃,定期与你的项目导师互动。

感谢谷歌给我这么一个神奇的机会。

**更新:**deep lens 项目现在是 ML4SCI 保护伞组织的一部分。

重要链接

[## 无监督解码暗物质亚结构

暗物质的身份仍然是当今物理学中最紧迫的问题之一。虽然许多有前途的黑暗…

arxiv.org](https://arxiv.org/abs/2008.12731) [## 用强引力透镜模拟暗物质

强引力透镜是对暗物质亚结构的一个有希望的探索,以更好地理解它的结构。

hepsoftwarefoundation.org](https://hepsoftwarefoundation.org/gsoc/2020/proposal_DEEPLENSE.html) [## 深透镜-无监督/无监督-透镜

基于 PyTorch 的工具,用于强透镜宇宙学中的无监督深度学习应用

github.com](https://github.com/DeepLense-Unsupervised/unsupervised-lensing) [## DeepLense 无人监督/PyLensing

一个基于 PyAutoLens 模拟生成透镜图像的工具

github.com](https://github.com/DeepLense-Unsupervised/PyLensing) [## 印度特伦甘纳邦皮兰尼-海德拉巴普拉纳特·雷迪-比拉科技学院

查看 Pranath Reddy 在全球最大的职业社区 LinkedIn 上的个人资料。Pranath 有 2 份工作列在…

www.linkedin.com](https://www.linkedin.com/in/pranath-reddy/) [## 普拉纳斯-雷迪-概述

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/pranath-reddy)

如果可以的话,猜猜这些胡言乱语

原文:https://towardsdatascience.com/guess-the-gibberish-if-you-can-29433bc658db?source=collection_archive---------8-----------------------

一个简单的算法来创建你的胡言乱语的挑战

图片来源:自创

社交媒体是 21 世纪的强大平台。它已经成为数字营销的主要来源,表达观点,交友,娱乐方式等等。社交媒体应用不断创新和变化,通过显示正确的内容来了解用户的行为,从而保持用户的参与。经常可以看到新的挑战趋势,很多名人会发布相关的帖子。当前流行的一个挑战是“猜胡言乱语挑战”。

我相信你一定接受过或者至少见过有人接受这个挑战。在这个挑战中,屏幕上出现一些看似无意义但听起来有意义的乱码。让我们看一些例子。

图片来源:自创

图片来源:自创

我接受了胡言乱语的挑战

我亲自尝试过,我可以保证它有时会上瘾。作为一个算法爱好者,我想到的第一件事是我如何自己创造一个这样的挑战。我做了一些研究,创造了一个简单的游戏版本。这个简单的版本可以通过一些调整变得复杂,我将在最后作为开放式问题进行讨论。可以有许多不同的方法来创建它。在这篇博文中,我将讨论一种可能的方法。这篇博文中使用的所有代码都可以在这里找到。那么,我们开始吧。

你也可以找到我关于这个话题的 Youtube 视频。

我在 Youtube 上关于这个话题的视频

语音算法

根据维基百科,语音学是研究人类声音的科学。这个领域的主题专家被称为语音学家。基于语言学的语音学研究被称为音系学。

一个语音算法是一个算法,用于通过发音为单词的标引。这些算法提供了识别发音相似的单词的能力。

读者能想到的第一个问题是,我们为什么要讨论语音学和语音算法。答案是,在我们试图解决的问题“猜测胡言乱语挑战”中,胡言乱语听起来类似于某种要被解码的有意义的东西,这也是最终的动机。直觉上,它想到一些语音算法可以帮助这一点。有许多好的语音算法,其中一个流行且简单的算法是 Soundex 算法。

Soundex 算法

Soundex 是一个语音算法,用于通过声音索引姓名。目标是让同音字被编码成相同的表示,这样即使拼写有微小差异,它们也能被匹配。

Soundex 算法将英语单词编码成一个代码,其中第一位由一个字母和后面的“k-1”个数字组成,假设我们想要“k”位编码。

该算法在维基百科中有非常好的解释。从它身上取下一些部分,稍微简化一下,看起来是这样的:

[## 桑迪克斯

Soundex 是一种语音算法,用于按声音索引名称,如英语中的发音。我们的目标是让同音词…

en.wikipedia.org](https://en.wikipedia.org/wiki/Soundex#American_Soundex)

第一步:保留单词的第一个字母,去掉所有其他出现的 a,e,I,o,u,y,h,w。

**第二步:**用数字替换辅音如下(第一个字母后):

★ b,f,p,v → 1

★ c,g,j,k,q,s,x,z → 2

★ d,t → 3

★ l → 4

★ m,n → 5

★ r → 6

图片来源~ 维基百科

步骤 2 背后的逻辑:

发音位置相似的辅音共享相同的数字,例如唇音辅音 B、F、P 和 V 都被编码为数字 1。

**第三步:**如果原词中有两个或两个以上同号字母相邻,只保留首字母;同样,由“h”或“w”分隔的具有相同数字的两个字母被编码为单个数字,而由元音分隔的这种字母被编码两次。这条规则也适用于第一个字母。

步骤 4: 如果最终编码少于 k 位,用 0 填充剩余的位。如果多于 k 位,只保留第一个 k 位。

使用此算法,“Robert”和“Rupert”返回相同的字符串“R163 ”,而“Rubin”返回“R150”。“阿什克拉夫特”和“阿什克罗夫特”都产生“A261”。“Tymczak”产生“T522”而不是“T520”(名称中的字符“z”和“k”被编码为 2 两次,因为它们之间有一个元音)。‘pfister’产生‘P236’而不是‘P123’(前两个字母的数字相同,编码一次为‘P’),‘Honeyman’产生‘H555’。

在 python 中,模糊包提供了 Soundex 和其他语音算法的良好实现。

对 Soundex 的轻微修改

我们将使用 Soundex 算法生成编码,与步骤 1 略有不同。

我们不是删除 a、e、I、o、u、y、h、w 的所有出现,而是进一步对它们进行聚类/编号。

★ e,I,y → 7

★ o,u → 8

★ a,h,w →忽略它们

推理:e,I 和 y 看起来相似,例如' pic ',' pec ',' pyc '听起来相似。

我不能使用模糊包,因为我希望在原始的 Soundex 算法中执行这些建议的修改。我发现卡洛斯·德尔加多的这个伟大的实现。这并不完全正确,但对我们的用例来说已经足够好了。

[## Soundex 算法(函数)在不同编程语言中的实现

查看我们用不同的和已知的编程语言编写的 Soundex 函数的复制。

ourcodeworld.com](https://ourcodeworld.com/articles/read/249/implementation-of-the-soundex-algorithm-function-in-different-programming-languages)

改进的 Soundex 算法;

def get_soundex_modified(name):# Get the soundex code for the stringname = name.upper()soundex = ""soundex += name[0]# numbering of letters based on phonetic similaritydictionary = {"BFPV": "1", "CGJKQSXZ":"2", "DT":"3", "L":"4",   "MN":"5", "R":"6","EIY":"7","OU":"8","AHW":"."}for char in name[1:]:for key in dictionary.keys():if char in key:code = dictionary[key]if code != soundex[-1]:soundex += codesoundex = soundex.replace(".", "")# We prefer a 8-bit outputsoundex = soundex[:8].ljust(8, "0")return soundex

猜猜胡言乱语挑战算法

对 Soundex 算法稍加修改,我们就可以完成“猜测胡言乱语挑战”算法。这些步骤将是

步骤 1: 给定句子,一次取一个单词,使用上述修改的 sounded 算法生成 8 位编码。例如,单词“under”的编码为“U5376000”。

步骤 2: 从步骤 1 中取出编码,一次取出编码中的一个字母,并执行以下操作:

  • 如果字母是字符,就保持原样。
  • 如果字母是一个数字,从该组中随机选择一个字符。例如,如果字母是 2,我们可以随机选择 c、g、j、k、q、s、x 和 z 中的任意一个。群集是:

★ b,f,p,v → 1

★ c,g,j,k,q,s,x,z → 2

★ d,t → 3

★ l → 4

★ m,n → 5

★ r → 6

★ e,I,y → 7

★ o,u → 8

  • 如果字母是 0 或者编码中没有剩余的字母,我们就完成了这个单词

**第三步:**对句子中的所有单词重复同样的过程。

猜谜挑战算法的实现

让我们可视化一些谚语的乱码输出。

最终输出:生成的乱码

输出是胡言乱语,虽然听起来类似于实际的谚语。这就是我们简单的“猜谜挑战”解决方案。

可能的增强

在目前的方法中,我们正在为每个可能被改变的单词创建一个乱码。同样,第一个字符在原始输入和乱码输出中都保持不变。我们可以有一些解决办法。我将提供两种可能的方法来增强我们的“猜测胡言乱语”算法,并把它作为一个开放式问题留给观众来展示创造力。

  1. 一些智能的启发式算法,智能地拆分和组合单词,然后使用修改的 Soundex 算法进行编码。例如,英国的一个可能有趣的胡言乱语是“母羊之夜特德国王哑巴”。
  2. 原始输入和乱码输出中的第一个字符不必相同。例如,对字母“U”进行编码的一种可能方式可以是“Ewe”。

结论

通过这篇博文,我们开发了一个有趣且非常简单的算法来创建我们自己的“猜测胡言乱语挑战”。在这个过程中,我们还学习了语音学、音韵学和语音算法。我们还研究了如何让它变得更具挑战性。希望你喜欢。这篇博文中使用的所有代码都可以在这里找到。

如果你有任何疑问,请联系我。我很想知道你是否想到了更多可能的改进。

我的 Youtube 频道获取更多内容:

[## 阿布舍克·蒙戈利

嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…

www.youtube.com](https://www.youtube.com/channel/UCg0PxC9ThQrbD9nM_FU1vWA)

关于作者-:

Abhishek Mungoli 是一位经验丰富的数据科学家,拥有 ML 领域的经验和计算机科学背景,跨越多个领域并具有解决问题的思维方式。擅长各种机器学习和零售业特有的优化问题。热衷于大规模实现机器学习模型,并通过博客、讲座、聚会和论文等方式分享知识。

我的动机总是把最困难的事情简化成最简单的版本。我喜欢解决问题、数据科学、产品开发和扩展解决方案。我喜欢在闲暇时间探索新的地方和健身。关注我的 Linkedininsta gram并查看我的往期帖子。我欢迎反馈和建设性的批评。我的一些博客:****

  • 一个无监督的数学评分模型
  • 降维:PCA 与自动编码器
  • 体验遗传算法的威力
  • 每个数据科学家都应该避免的 5 个错误
  • 以简单&直观的方式分解时间序列
  • GPU 计算如何在工作中拯救了我?
  • 信息论& KL 分歧第一部分和第二部分
  • 使用 Apache Spark 处理维基百科,创建热点数据集
  • 一种基于半监督嵌入的模糊聚类
  • 比较哪个机器学习模型表现更好
  • 分析 Fitbit 数据,揭开疫情封锁期间身体模式变化的神秘面纱
  • 神话与现实围绕关联
  • 成为面向业务的数据科学家指南

关于如何从零开始学习数据科学的指南,完全在线,没有 STEM 背景

原文:https://towardsdatascience.com/guide-on-how-to-learn-data-science-from-scratch-completely-online-and-with-no-background-in-stem-1595a0571d0?source=collection_archive---------19-----------------------

照片通过像素

数据科学仍然是吸引人们思想的神秘领域,但许多人仍然认为从头学习非常困难,甚至不可能。“要精通数据科学,你必须有工程学本科学历,或者有数学/统计学背景”,—我听过很多次了。尽管拥有一些这样的背景无疑是有益的,但我真的相信这绝不是必要的。

两周之后,我将在弗吉尼亚大学完成我的 MBA/MSDS 双学位。在我在校的两年时间里,我利用空闲时间完成了本指南中列出的每一门课程。我在本文中推荐的课程是我能找到的最好的数据科学资源。我学习有点慢,不得不尝试很多不同的在线课程。我下面列出的这些学校都有顶尖的教授,他们是解释这些概念的专家。

在美国,一个典型的数据科学硕士学位的费用从 1 万美元(在线 MSDS)到 10 万美元不等。本文中的指南不能取代校内的 MSDS 学位,因为你在招聘方面得到了学校的大力支持,你发展了自己的关系网,并结交了很多密友。然而,我认为,与参加全日制 MSDS 学位相比,数据科学是少数几个你可以通过在线学习获得同样多甚至更多知识的领域之一。另外,根据你的愿望,你最终将支付 0-1000 美元。最后,并不是所有人都需要学习硕士级别的数据科学。在数字时代,大多数工作专业人士最终将开始在日常生活中使用机器学习技术,就像 90 年代第一次使用 Excel 的人一样。因此,虽然 MSDS 可能有些矫枉过正,但学习一些技能并对数据科学有一个大致的了解是至关重要的。

我将把这个指南分成两个部分:一个面向那些希望对数据科学的技术和语言有一个总体了解的人,他们想亲自动手,能够进行数据辩论,并自己运行一些机器学习和深度学习模型;另一个目标是那些想要获得 MSDS 水平的知识,甚至可能转行成为全职数据科学家的人。同样,你可以在没有任何先验知识的情况下开始做这两个轨道。在本文中,我将主要推荐 Python 资源,但是我认为学习 R 也是很有价值的。我会让你决定的。

在开始阅读指南之前,我想提供一些通用的提示和技巧,帮助我保持正确的方向,保持动力,尽可能高效地学习和利用时间。

  1. 每周至少学习五天。理想情况下,每天 30 分钟。我建议建立一个 30 分钟-1 小时的 9 点日历,并在周末保留 2-3 个小时。所有的课程都被设计成小块进行,所以学习起来会很自然。小块的学习会帮助你更好的内化信息。
  2. 循序渐进,不要同时上课。指南从最简单的课程到更难的课程。而且如果你没有一些概念的先验知识,再高级的课程对你来说也是无法理解的。
  3. 支付课程费用(当然只要你能负担得起)。本指南中的每门课程都有大量练习,这对你的学习体验至关重要。与你通过练习得到的结果相比,这些量是微不足道的。
  4. 不用担心卡住!数据科学的酷之处在于,很多知识仅仅来自谷歌搜索。我在 MSDS 的顶点项目是自然语言处理(文本分析),我对此一无所知。我没有选修过 NLP,但是通过选修下面列出的几门课程和谷歌搜索,我仍然能够成功地完成这个项目。Stackoverflow 是一个平台,可以解答你在这个过程中可能遇到的所有问题。

现在让我们来看看指南。

第一轨。我只是想对数据科学有一个大致的了解,并能够了解我团队中的数据科学家在做什么

  1. 对于这两种途径,我建议从基本的 Python 基础开始。我的假设是,你没有编程经验,因此建立一些基础和对自己能力的信心是至关重要的。从 Coursera 上密执安大学的这个 Python 专门化开始。如果你想做练习题并获得证书,你需要花费 50 美元。你也可以免费旁听课程。
  2. 在 DataCamp 上用 Python 完成赛道数据科学家。这个 100 小时的专业课程将为您提供开始数据科学之路所需的一切,并能够与贵公司的数据科学家和工程师交流。费用是 30 美元/月,但是 DataCamp 上时不时会有很多优惠。我见过 75%的年费折扣。在完成这 23 门课程的专业学习后,你将获得 Python 技术的扎实知识,并将了解最常用的机器学习模型,还将稍微进入深度学习和人工智能领域。
  3. 最后,我强烈推荐熟悉 Tableau。商务人士能够获得的最重要的技能之一是与数据沟通。Tableau 是实现这一目的的最佳工具之一。在 Tableau 电子教学网站上完成 Tableau 分析师课程。您必须注册才能访问该资源。有试用期和折扣。截至 2020 年 4 月,Tableau 提供 90 天免费。

总工作量:~ 100–200 小时

总费用: $30 — $300 取决于你的速度。所有订阅都是按月进行的,所以完成得越快,支付的费用就越少。

作为额外的学习,我建议参加 DataCamp 的营销分析技能课程。对于进入 B2C 领域的商务人士来说,这将是非常有用的。

第二轨。我想成为一名全职数据科学家,或者用低预算获得 MSDS 水平的知识

这条赛道的主要区别在于,除了实用知识,还会为你提供扎实的理论基础。我强烈建议为大部分资源付费,以充分利用实际问题以及可能有助于职业转型的证书。我还有一个假设,你有一般的高中数学知识。你不必是一个伟大的数学家,但是如果你不知道函数是如何工作的,例如(斜率、截距等等),我会建议你从 Khanacademy.com 开始,在他们的网站上复习代数 I 部分。不需要微积分、线性代数或概率论知识。现在让我们去赛道。

  1. 正如我之前提到的,对于这两种途径,我建议从基本的 Python 基础开始。我的假设是,你没有编程经验,因此建立一些基础和对自己能力的信心是至关重要的。从密歇根大学 Coursera 上的这个 Python 专门化开始。如果你想做练习题并获得证书,你需要花费 50 美元。你也可以免费旁听课程。
  2. 那么你将需要转向一些数学。当我在攻读 MSDS 学位时,我在数学方面完全没有准备,必须从头开始学习所有的概念。我学了很多课程,如果你和我一样,没有扎实的数学基础,大部分课程都很难理解。我发现机器学习的数学绝对令人着迷。教授们用直白的语言解释相当复杂的概念。同样,我建议付费来练习这些概念,但是如果对你来说效果更好的话,也可以随意旁听课程。
  3. 我们的下一站是统计。此外,作为数据科学家,这也是我们需要的重要基础。我建议要么选择 Python 专门化的统计,要么选择 R 专门化的统计。我选择了第二个,并建议你也这样做。然而,它是用 R 编程语言教授的。同样,非常有用,但在这一点上不是非常必要。如果时间不够,就用 Python 吧。如果你口袋里还有时间,就拿 R 吧。那里的教授是杜克大学著名的数据科学贡献者玛雅·切廷卡亚-伦德尔。
  4. 当你完成了理论基础,我们需要跳上一辆实用的火车,用 Python 进行大量的机器学习建模。对于这一点,我不知道有什么资源比 DataCamp 上具有 Python 专长的数据科学家更好。这很长,有 23 门课程,大约需要 100 个小时,但作为一名有抱负的数据科学家,你将获得非常坚实的实践基础。
  5. 接下来,我们需要更深入,我们将在 DataCamp 上切换到使用 Python 的机器学习科学家。这是一个高级的多课程专业化,深入研究最常用的机器学习技术,如果你想在这个行业取得成功,你必须熟悉这些技术。
  6. 我们的最后两步将专注于 AI 和深度学习算法。你能找到的最好的资源是吴恩达在 Coursera 上的深度学习专业。这是相同的,甚至可能比一个合法的硕士 3 级学分的深度学习课程更好。对每个数据科学家来说都是绝对必要的知识。
  7. 最后,用一些实际的实现来巩固前面步骤中的知识是至关重要的。tensor flow in Practice specialization建立在深度学习的基础上,提供大量的实践。

**总时间:**至少 300 小时,很可能 500 小时左右

总成本: $60 — $1000(?).这里的成本将高度依赖于学习的速度和为练习付费的意愿。你不能旁听 DataCamp 的课程,每月至少要花 30 美元。其余的你可以免费审核。但是,我强烈建议付费。与完成所有练习题后你将得到的结果相比,这个成本可以忽略不计。

我故意没有把 Tableau 放在这首歌里。您将从 Python 专门化中获得基础的可视化知识,并且在这一点上,作为一名专业人员,您将能够确定 Tableau 是否是您日常需要的东西。如果是的话,学起来会相当快和容易。

最后的想法

我非常有信心,没有 STEM 背景的任何人都可以成为数据科学家。和其他技能一样,这当然需要时间、努力和奉献。然而,结果是惊人的,尤其是现在几乎是无与伦比的。所以我祝你一路走好,也希望你能像我一样,一路玩得开心。

课程链接汇总:

轨道 1。

  1. https://www.coursera.org/specializations/python?
  2. https://learn . data camp . com/career-tracks/data-scientist-with-python
  3. https://www.tableau.com/learn/training/elearning
  4. https://www . data camp . com/tracks/marketing-analytics-with-python

第二轨。

  1. https://www.coursera.org/specializations/python?
  2. https://www . coursera . org/specializations/mathematics-machine-learning?
  3. https://www.coursera.org/specializations/statistics 和T4
  4. https://www.datacamp.com/tracks/data-scientist-with-python
  5. https://www . data camp . com/tracks/machine-learning-scientist-with-python
  6. https://www.coursera.org/specializations/deep-learning?
  7. https://www . coursera . org/specializations/tensor flow-in-practice?

亚马逊人工智能工作指南

原文:https://towardsdatascience.com/guide-to-ai-jobs-at-amazon-87c5a08d3d93?source=collection_archive---------56-----------------------

了解亚马逊的不同人工智能角色,在人工智能的热门领域启动你的职业生涯。

  • 注意,我指的是 AI 的定义,即机器对人类智能过程的模拟。因此,在这个上下文中,AI 是一个包含 ML、CV、NLP 等的总括术语..*

随着人工智能的出现,人工智能相关工作的数量急剧增加,对这些职位的需求也在增加。这个简短的指南是对亚马逊不同角色的介绍,这些角色可以引领你进入人工智能领域。我希望你喜欢!

克里斯蒂安·威迪格在 Unsplash 上拍摄的照片

软件开发工程师——我们将从这里最明显的角色开始。亚马逊名下有许多团队,尤其是亚马逊网络服务(AWS)服务团队。成为亚马逊的软件开发工程师并不是做 AI 工作的保证,但如果你已经是该行业的开发人员,这是最简单的方法。亚马逊有许多团队正在推进人工智能的边界。仅仅在 AWS 网站上快速搜索一下,就有 19 个服务团队列在“机器学习”之下。软件工程师负责构建和部署支持 AWS 的最先进平台。职责可能包括开发服务于数十亿日常请求的平台,或者深入系统以优化性能和可维护性。

以亚马逊公开发布的软件开发工作中的这个片段为例

“作为亚马逊人工智能团队的一名机器学习软件开发工程师,你将设计和开发快速、高效、高度可扩展的深度学习算法,应用于挑战日常用例问题。你将与亚马逊人工智能领域的高级科学家和工程师合作,开发健壮可靠的高质量软件。”

与大多数软件开发工程角色一样,这些职位的需求可能会有所不同。需要本科学历才能闯入 FAANG 的日子已经一去不复返了,只要你有扎实的同等经验和一个缺德的好程序员就能进去。拥有硕士或博士学位可以帮助你在更高的水平上起步,前提是你符合要求。

研究科学家与应用科学家- 这些角色是亚马逊的职位令人困惑的地方。亚马逊的 T2 研究科学家 T3 与谷歌或脸书的研究科学家 T5 不同。在亚马逊,相应的职位是应用科学家。亚马逊的研究科学家或应用科学家通常由拥有计算机科学、数学、统计学或相关领域硕士或博士学位的人担任。虽然研究人员和应用科学家之间的学位要求非常相似,但当涉及到对编码的预期熟练程度时,他们的地位是不同的。

亚马逊的一名研究科学家有望在模拟中设计和开发系统原型。这些原型通常会交给应用科学家来实现。应用科学家需要通过入门级软件开发工程师的编码栏,而研究科学家则不需要。这并不意味着研究科学家不会有任何技术问题,只是不期望研究科学家具有与应用科学家相同的编码能力。应用科学家被期望与研究科学家一起开发新的模型和算法,但是然后采用研究科学家开发的原型并大规模实现它们。亚马逊是关于规模的,这种大规模部署的能力是应用科学家和研究科学家之间的关键区别。作为亚马逊招聘流程的一部分,如果你面试的是一个应用科学家的职位,并且符合除了入门级编码栏以外的所有要求,你仍然可以被聘为研究科学家。所以不要害怕!如果你渴望成为一名应用科学家,但仍在提高你的编程技能,那么在进入应用科学家角色之前,研究科学家职位是发展这些技能的一个很好的方式*。

*请注意,虽然这些是亚马逊研究和应用科学家角色的一般准则,但它们绝不是这些角色的员工的指示。许多研究科学家都是出色的程序员,他们的职责和应用科学家一样。

人工智能相关服务团队

如上所述,目前 AWS 有超过 19 个平台与人工智能相关。这里有几个让你开始:

亚马逊 SageMaker 一个大规模构建、训练、部署机器学习模型的平台。

Amazon Lex 构建和部署聊天机器人。

亚马逊 Rekognition 分析图像和视频(比如面部识别)。

亚马逊翻译 自然准确的机器翻译。

***我希望这篇指南能给亚马逊人工智能领域的各种角色一些启发。请随时留下任何反馈。

大数据连接指南— Python、SQL、Pandas、Spark、Dask

原文:https://towardsdatascience.com/guide-to-big-data-joins-python-sql-pandas-spark-dask-51b7f4fec810?source=collection_archive---------2-----------------------

如何以最佳方式连接大数据集—多种方法指南

大数据——Patrick linden Berg 在 Unsplash 上拍摄的照片

有许多方法可以旋转磁盘、切鱼片或处理大数据,这里有一个快速指南。

样本数据集

Kaggle 电影数据库[8]—45,000 部电影的 2,600 万个评级,数据分布在 5 个文件中:

Foostack。人工智能

要找到电影的最高平均评分,您需要加入链接元数据评分:

SELECT m.title,avg(r . rating)FROM links l INNER JOIN to metas m ON m . imdbid = l . imdbid INNER JOIN to ratings ON r . movie id = l . movie id GROUP BY m . title count(r . rating)> 2 且 avg(r.rating) > 4.5

老式 SQL RDBMS

经典的方法是加载一个数据库,索引并运行前面提到的 SQL(或使用下面的经典 SQL):

从链接 l,metas m,ratings r 中选择 m.title,avg(r.rating)其中 m.imdbId=l.imdbId 和 r . movie id = l . movie id GROUP BY m . title 具有 count(r.rating) > 2 和 avg(r.rating) > 4.5

对于某些平台变体,RDBMS 中的连接有三种主要方式:

  1. 嵌套循环— 对于表 A 中的每一行,查找表 B 中的匹配键。B 上的索引使得查找为 O(Alog B),否则连接为慢速— O(AB)。
  2. Hash-Join — 通过查找键构建表 B 的散列/映射,使得连接查找非常快速— O(A*1)
  3. 合并-排序 —对两个表进行排序,并在一次通过中合并,除非预先排序,否则速度不会很快—O(A+B+A log A+B log B)→O(A log A+B log B)

使用 Sqlite3 [1]—创建数据库、表和加载非常简单:

SQLite3 表加载/设置

加载和查询 26m 行数据需要大约 10 分钟(也许我们可以合并- 调整前两步..

  • 从 CSV/磁盘加载— 35 秒
  • 插入数据库— 8 分钟
  • 添加索引— 30 秒
  • 按查询分组— 20 秒

您还可以使用 sqlite3 命令行来测试和查看查询执行计划,如下所示。在联接列上添加一些额外的索引后,我们的目标查询大约需要 21 秒来执行。

SQLite 查询执行(来自 cmdline 工具)

使用 SQL 数据库是可扩展的,但是很老派。接下来我们将尝试潮人技巧。

python——终极黑客

我们可以省去数据库开销,直接用 Python 编写数据加载和连接&这很麻烦:

自定义 python 合并(NL 连接)

“merge()”是一个没有索引的嵌套循环连接。该循环必须扫描 metas 和链接表以获得每个评级(26m * 50k *2)。10 万条评论只需要 5 分钟,所以 2600 万条评论将永远不会结束...

“merge_wmap()”是一个散列连接— 我们为元和链接构建一个映射,从而获得 O(n*1)的性能。连接 26m 排只需 3 秒

使用 hashmap 查找的自定义 python NL 连接

我没有实现分组过滤——这相对较快(需要对 26m 的行结果进行排序-扫描-合并)—我估计加载和处理的总时间为0:53

  • 将原始 CSV 加载到阵列— 35 秒
  • 手动合并索引— 3 秒
  • 手动分组和过滤— 15 秒(TBD~估计值)

生蟒速度快但是丑。全速你的本地电脑和完全控制你所有的错误。

熊猫数据帧拯救行动

Pandas[2]是 Python 上用于数据准备的事实上的包。速度极快且易于使用,我们可以用最少的代码进行加载、连接和分组:

熊猫加入例子

熊猫很聪明。您不需要预定义散列或索引,它似乎可以动态生成优化连接所需的内容。最大的限制是它存在于单个机器上。**处理 26m 行的时间约为 0:17,**代码更少,无需外部系统(数据库、集群等)。

  • 将 3 个 csv 加载到数据帧— 5 秒
  • 连接 3 个数据帧— 8 秒
  • 加入、分组和过滤— +4 秒

熊猫文件加载比我的自定义 py 快得多,35 秒对 5 秒!这表明不要做黑客,使用库。理论上,Pandas 是单线程/进程(在我的 TaskManager 上看起来不像),因此数据集的大小受到你的电脑内存的限制。

尽管如此——Pandas 是处理中小型数据的终极方式——但是我们想要 大数据

火花簇 FTW(为了胜利)

SQL 很棒,但并行性和破解能力有限。Python 和 Pandas 超级灵活,但是缺乏可伸缩性。Apache Spark [5]实际上是在大数据上并行化内存操作的方式。

Spark 有一个名为 DataFrame *的对象(是的另一个!)*这就像一个熊猫的数据框架,甚至可以加载/窃取数据(尽管你可能应该通过 HDFS 或云加载数据,以避免大数据传输问题):

最小火花码(本地独立设置)

我写了两个 Spark join 方法。两者并行运行。默认模式(第 15 行)将对您的数据进行分区,并在集群节点间移动(传播)。后面的“广播”模式(第 18 行)复制一次较小的表,只对大表内容进行分区和发送。使用较小的连接表,广播模式会快得多。

Spark 在 workers 节点(JVM——设置为 8,以匹配我的 CPU 内核数)之间划分工作,分而治之,回到聚合中。火花代码和结果输出如下:

df.groupBy('title').agg(func.mean('rating').   alias('avg_rating'),func.count('rating').   alias('r_count')).filter('r_count >2').    filter('avg_rating > 4.5').show()

Spark 对 26m 行的连接和分组操作的输出

绩效总结

(来自我笔记本电脑的非实验室认证结果)

首先记下将 3 个数据集连接在一起的运行时间:

连接的性能

令人惊讶的是,原始 Python 解决方案是最快的?黑黑!

顶级电影团体(包括 Spark)的最终结果:

连接和分组+过滤的性能

外卖:

  • 熊猫是非凡的快速和高效,在这一点上,你有核心记忆。在某个时候,Python/Pandas 会耗尽内存并崩溃。
  • Spark 是一个很好的扩展解决方案,尽管集群管理可能比较棘手。内存分布式处理、分区作业和数据+分区存储策略(HDFS 或其他)是正确的方向。
  • RDBMS 是可靠的,但是在移动数据和处理方面有伸缩限制

在接下来的章节中会有更多关于 Spark 的内容…糟糕,我忘了 Dask (原生 Python 集群)——也许下次吧。

SQLite3 资源配置文件

只有 2 个真正活跃的内核,额外的 I/O(尽管大部分都被缓存)

熊猫资源概况

对于我所认为的单线程/任务进程,CPU 利用率出奇的高?

Spark 资源配置文件(8 个工人,10 个分区)

所有内核都利用了 8 个工作线程—良好的 CPU 和内存分配

以上数据来自我的 MSFT Surface 笔记本电脑 3-i7/16gb/256 GB 固态硬盘

参考和启示

[0]测试代码的完整源代码(不仅仅是 gist)——Doug foo 的 GitHub

[1] SQLite Python 指南— 官方 Python 文档

[2]熊猫指南— 10 分钟教程

[3]有点老的分析 SQLite vs Pandas — 韦斯·麦金利博客

[4] Spark Joins DB Deck— 数据块演示

[5]关于 Spark 的精彩详细介绍—a . Ialenti 撰写的 TDS 文章

[6] PYArrow 用于 Spark 中的快速数据帧加载— Bryan Cutler IBM

[7]在 10 分钟内安装 PySpark Win—TDS 文章作者 Uma G

[8]电影评论文件— Kaggle 数据集

YOLO 汽车检测指南

原文:https://towardsdatascience.com/guide-to-car-detection-using-yolo-48caac8e4ded?source=collection_archive---------6-----------------------

YOLO 算法的深入概念——包围盒、非最大值抑制和 IOU。

使用 YOLOv3 的实时对象检测

1.问题陈述

你正在研究一辆自动驾驶汽车。作为这个项目的一个关键组成部分,你想首先建立一个汽车检测系统。为了收集数据,你在汽车引擎盖上安装了一个摄像头,当你开车时,它每隔几秒钟就拍摄一次前方道路的照片。

在硅谷开车时用车载相机拍摄的照片。
感谢 drive.ai 提供本数据集。

你已经将所有这些图像收集到一个文件夹中,并通过在你找到的每辆车周围绘制边框来标记它们。下面是一个边界框的示例:

图 1:边界框的定义

如果您想要对象检测器识别 80 个类别,您可以将类别标签 c 表示为 1 到 80 之间的整数,或者表示为 80 维向量(80 个数字),其中一个分量为 1,其余为 0。在本文中,我将使用这两种表示法,这取决于哪种表示法对特定步骤更方便。

2.YOLO

“你只看一次”(YOLO) 是一种流行的算法,因为它实现了高精度,同时还能够实时运行。这种算法“只看一次”图像,因为它只需要一次通过网络的前向传播来进行预测。在 非最大抑制 之后,输出识别的对象和边界框。

2.1 模型细节

输入和输出

  • 输入是一批图像,每幅图像的形状为( m,608,608,3 )。
  • 输出是一个包含已识别类的边界框列表。每个边界框由 6 个数字表示——如上所述的 pcbxbybhbwc — 。如果你将 c 展开成一个 80 维的向量,那么每个边界框由 85 个数字表示。

锚箱

  • 通过探索训练数据来选择代表不同类别的合理的高/宽比,从而选择锚定框。
  • 锚盒尺寸为编码中倒数第二个尺寸: mnHnW类。
  • YOLO 架构为:图像( m,608,608,3 ) - >深度 CNN - >编码( m,19,19,5,85 )。

编码

让我们更详细地看看这种编码代表了什么。

图 2:YOLO 的编码架构

如果对象的中心/中点落入网格单元,则该网格单元负责检测该对象。

由于我们使用 5 个锚盒,因此每个19×19单元编码了关于 5 个盒的信息。锚定框仅由其宽度和高度定义。

为简单起见,我们将展平形状的最后两个维度( 19,19,5,85 )编码。所以深度 CNN 的输出是( 19,19,425 )。

图 3:展平最后两个尺寸

班级成绩

现在,对于(每个单元格的)每个盒子,我们将计算下面的元素乘积,并提取盒子包含某个类的概率。

类得分是score _ cᵢ=p _ c * cᵢ——存在一个对象的概率 p_c 乘以该对象是某类的概率 cᵢ.

图 4:找出每个方框检测到的类别

图 4 中,假设对于盒子 1(单元格 1),物体存在的概率为 p₁ = 0.60。因此,有 60%的可能性,一个对象存在于框 1(单元格 1)。

物体是类别 3(汽车)的概率是 c₃ = 0.73。

方框 1 和类别 3 的分数为score _ c₁,₃= 0.60 * 0.73 = 0.44。

假设我们计算了方框 1 中所有 80 个类别的分数,发现汽车类别(类别 3)的分数最大。因此,我们将把分数 0.44 和类别 3 分配给这个框 1。

可视化类

这里有一种方法可以形象化 YOLO 在图像上预测的东西:

  • 对于每一个 19 x 19 网格单元,找到概率得分的最大值,即在 80 个类中取一个最大值,5 个锚框中的每一个都取一个最大值)。
  • 根据网格单元认为最有可能是什么对象来给网格单元着色。

这样做的结果是这幅图:

图 19 x 19 网格单元中的每一个都根据在该单元中哪个类具有最大的预测概率而被着色。

注意,这种可视化并不是进行预测的 YOLO 算法本身的核心部分;这只是可视化算法中间结果的一种很好的方式。

可视化边界框

另一种可视化 YOLO 输出的方式是绘制它输出的边界框。这样做的结果是这样的可视化:

图 6 :每个单元格给你 5 个盒子。总的来说,该模型仅通过查看图像一次(通过网络向前传递一次)就预测了 19×19×5 = 1805 个盒子!不同的颜色代表不同的类别。

非最大抑制

在上图中,我们只绘制了模型分配了高概率的盒子,但这仍然是太多的盒子。我们希望将算法的输出减少到更少数量的检测对象。

为此,我们将使用非最大抑制。具体来说,我们将执行以下步骤:

  • 去掉分数低的盒子。意思是,盒子对检测一个类不是很有信心;要么是由于任何物体的低概率,要么是这个特殊类的低概率。
  • 当几个框相互重叠并检测同一对象时,仅选择一个框。

2.2 利用类别分数的阈值进行过滤

我们将首先通过设定阈值来应用过滤器。我们想摆脱任何盒子的类“分数”小于一个选择的阈值。

该模型总共为我们提供了 19 x 19 x 5 x 85 个数字,每个盒子由 85 个数字描述。将( 19,19,5,85 )或( 19,19,425 )维张量重新排列成以下变量是很方便的:

  • box_confidence:形状张量( 19×19,5,1 )( 19×19,5,1 ),包含 p_c —19x19 单元格中预测的 5 个框中的每一个中,存在某个对象的置信概率。
  • boxes:形状张量( 19×19,5,4 ,包含每个单元格中 5 个盒子的中点和尺寸( bxbybhbw )。
  • box_class_probs:形状张量( 19×19,5,80 ),包含每个单元格 5 个盒子的 80 个类别中的每个类别的“类别概率”( c,c,…,c ₈₀)。

实现 ***yolo_filter_boxes()***

  1. 按照图 4 中的所述,通过进行元素乘积( p * c) 来计算 box 分数。
  2. 对于每个盒子,找到具有最大盒子分数的类的索引,以及相应的盒子分数。
  3. 使用阈值创建遮罩。作为提醒:([0.9, 0.3, 0.4, 0.5, 0.1] < 0.4)回报:[False, True, False, False, True]。对于您想要保留的盒子,掩码应为True
  4. 使用 TensorFlow 对box_class_scoresboxesbox_classes应用蒙版,过滤掉我们不想要的盒子。你应该只留下你想保留的盒子的子集。

有用的参考资料

  • Keras argmax
  • Keras max
  • 布尔掩码

2.3 非最大抑制

即使在通过对类分数进行阈值化过滤之后,我们可能仍然会得到许多重叠的盒子。用于选择正确框的第二个过滤器被称为非最大抑制(NMS)

图 7 :在本例中,模型预测了 3 辆汽车,但实际上是同一辆汽车的 3 次预测。运行非最大抑制(NMS)将只选择 3 个框中最准确(概率最高)的一个。

非最大值抑制使用一个非常重要的函数,叫做 交集超过并集 ,或者 IoU

图 8:Union 上交点的定义。

实现

在这段代码中,我将使用这样的约定,即( 0,0 )是图像的左上角;( 1,0 )是右上角;( 1,1 )是右下角。换句话说,( 0,0 )原点从图像的左上角开始。随着 x 增加,我们向右移动。随着 y 的增加,我们向下移动。

我将使用它的两个角来定义一个盒子:左上角( x₁,y₁ )和右下角( x₂,y₂ ),而不是使用中点、高度和宽度。这使得计算交集变得更加容易。

要计算一个矩形的面积,用它的高度(y₂-y₁)乘以它的宽度(x₂-x₁)。既然( x₁y₁ )是左上方( x₂、y₂ )是右下方,这些差异应该是非负的。

请随意在纸上画一些例子来从概念上阐明这一点。要找到两个盒子的交集(xi₁,yi₁,xi₂,yi₂ ):

  • 交点的左上角( xi₁,yi₁ )通过比较两个盒子的左上角( x₁y₁ ),然后找到具有更靠近右边的x-坐标和更靠近底部的y-坐标的顶点来找到。
  • 交点的右下角( xi₂,yi₂ )是通过比较两个盒子的右下角( x₂,y₂ )找到的,然后找到一个顶点的x-坐标更靠近左边,而y-坐标更靠近上面。
  • 两个框可能没有交集。如果我们计算的交点坐标最终是一个交点框的右上角和/或左下角,我们可以检测到这一点。另一种思考方式是,如果您计算了高度(y₂y₁)或宽度(x₂x₁)并且发现这些长度中至少有一个是负的,那么就没有相交(相交面积为零)。
  • 两个框可能在边或顶点相交,在这种情况下,相交面积仍然为零。当计算的交叉点的高度或宽度(或两者)为零时,会出现这种情况。

YOLO 非最大抑制

我们现在准备实施非最大抑制。关键步骤是:

  1. 选择得分最高的方框。
  2. 计算此框与所有其他框的重叠,并移除明显重叠的框(iou > = iou_threshold)。
  3. 回到步骤 1,重复直到没有比当前选择的盒子分数更低的盒子。

这将删除与所选框有大量重叠的所有框。只有“最好的”盒子保留下来。

实施 **yolo_non_max_suppression()**

参考文件

  • TF . image . non _ max _ suppression()

2.4 完成过滤

是时候实现一个函数了,它接受深度 CNN 的输出(T42 19 x 19 x 5 x 85 维度编码)并使用我们刚刚实现的函数过滤所有的盒子。

实现

该函数获取 YOLO 编码的输出,并使用分数阈值和 NMS 过滤盒子。

有一个实现细节你需要知道。有几种表示盒子的方法,比如通过它们的角或者通过它们的中点和高度/宽度。 YOLO 使用以下函数在不同时间在几种格式之间转换:

boxes = yolo_boxes_to_corners(box_xy, box_wh)

它将 YOLO 框坐标( x,y,w,h )转换为框角坐标( x,y,x,y ₂)以适应yolo_filter_boxes的输入。

boxes = scale_boxes(boxes, image_shape)

YOLO 的网络被训练运行在 608 x 608 的图像上。如果您在不同尺寸的图像上测试该数据,例如,具有 720 x 1280 图像的汽车检测数据集,该步骤将重新缩放这些方框,以便它们可以绘制在原始 720 x 1280 图像的顶部。

2.5 概述

  • 输入图像( 608,608,3 )
  • 输入图像通过 CNN,产生( 19,19,5,85 )维输出。
  • 展平最后两个维度后,输出的是一个体积形状( 19,19,425 )。输入图像上的19×19网格中的每个单元给出 425 个数字:425 = 5×85,因为每个单元包含 5 个框的预测,对应于 5 个锚框;85 = 5 + 80 其中 5 是因为( pc,bx,by,bh,bw )有 5 个数,80 是我们想要检测的类的个数。
  • 然后,我们基于分数阈值化— 丢弃已经检测到分数小于阈值的类的盒子,以及非最大值抑制— 计算联合**【IOU】上的交集并避免选择重叠的盒子,来仅选择几个盒子。**
  • 这给了你 YOLO 的最终输出。

3.在图像上测试 YOLO 预训练模型

在这一部分中,我们将使用一个预训练的模型,并在汽车检测数据集上进行测试。我们需要一个会话来执行计算图并评估张量:

sess = K.get_session()

3.1 定义类别、锚点和图像形状

回想一下,我们试图检测 80 个类,并且使用了 5 个锚盒。我们将读取存储在两个文件中的 80 个类和 5 个盒子的名称和锚点— coco_classes.txtyolo_anchors.txt(更多信息请参见 Github repo)。汽车检测数据集有 720 x 1280 图像,这些图像被预处理成 608 x 608 图像。

3.2 加载预训练模型

训练一个 YOLO 模型需要很长的时间,并且对于大范围的目标类需要一个相当大的标签包围盒数据集。因此,我们将加载一个现有的预先训练好的 Keras YOLO 模型。(更多信息见 Github repo)。这些重量来自 YOLO 官方网站,并由艾伦·泽勒纳编写的函数转换而来。参考文献在本文末尾。从技术上来说,这些是来自 YOLOv2 模型的参数,但在本文中我们将简称它为 YOLO

yolo_model = load_model(“model_data/yolo.h5”)

这将加载一个经过训练的 YOLO 模型的权重。你可以在 Github repo 里的笔记本里看看模型包含的图层汇总。

提醒:该模型将预处理后的一批输入图像(shape: ( m,608,608,3 )转换成形状张量( m,19,19,5,85 ),如图图 2 所示。

3.3 将模型的输出转换为可用的边界框张量

yolo_model的输出是一个( m,19,19,5,85 )张量,需要经过非平凡的处理和转换。下面的代码为我们完成了这项工作:

yolo_outputs = yolo_head(yolo_model.output, anchors, len(class_names))

如果你很好奇yolo_head是如何实现的,可以在 Github repo 的文件 'keras_yolo.py' 中找到函数定义。

yolo_outputs加入我们的图表后。这组 4 个张量已准备好用作yolo_eval功能的输入。

3.4 过滤箱

yolo_outputs以正确的格式给了我们所有yolo_model的预测框。我们现在准备通过调用之前实现的yolo_eval来过滤和选择最好的盒子。

scores, boxes, classes = yolo_eval(yolo_outputs, image_shape)

3.5 在图像上运行图形

让欢乐开始吧。我们创建了一个图表,可以总结如下:

  1. yolo_model.inputyolo_model。该模型用于计算输出 yolo_model.output
  2. yolo_model.outputyolo_head处理。它给你 yolo_outputs
  3. yolo_outputs 经过过滤功能yolo_eval。它输出你的预测:scores, boxes, classes.

实施 **predict()**

**predict()**运行图形以测试图像上的 YOLO 。你需要运行一个 TensorFlow 会话,让它计算scores, boxes, classes

下面的代码也使用了下面的函数:

image, image_data = preprocess_image("images/" **+** image_file, model_image_size = (608, 608))

哪些输出:

  • 图像:用于绘制框的图像的 python (PIL)表示。你不需要使用它。
  • image_data:表示图像的 numpy 数组。这将是 CNN 的输入。

在测试图像上测试功能:

out_scores, out_boxes, out_classes = predict(sess, “test.jpg”)

test.jpg 上的输出示例

我们刚刚运行的模型实际上能够检测到coco_classes.txt中列出的 80 个不同的类。通过下载 Github repo 中的文件,您可以随意尝试使用您自己的图像。

如果我们在所有图像上运行 for 循环会话。下面是我们将得到的结果:

4.结论

  • YOLO 是一个快速准确的最先进的物体检测模型。
  • 它通过 CNN 运行输入图像,CNN 输出一个 19 x 19 x 5 x 85 尺寸的体积。
  • 编码可以被视为一个网格,其中每个 19 x 19 单元格包含关于 5 个盒子的信息。
  • 使用非最大抑制过滤所有框。具体来说,使用分数阈值检测类的概率以仅保留准确(高概率)的框,以及交集超过并集(IoU) 阈值以消除重叠的框。
  • 因为从随机初始化的权重中训练 YOLO 模型是非常重要的,并且需要大的数据集以及大量的计算,所以我们在这个练习中使用了先前训练的模型参数。如果您愿意,也可以尝试用自己的数据集微调 YOLO 模型,尽管这将是一项相当重要的工作。

引用和参考文献

特别感谢deep learning . ai

所有deeplearning.ai 提供。

本文提出的观点主要来自于 YOLO 的两篇论文。这里的实现也从 Allan Zelener 的 GitHub 库中获得了很多灵感并使用了很多组件。本次训练中使用的预训练重量来自 YOLO 官方网站。

  • 约瑟夫·雷德蒙、桑托什·迪夫瓦拉、罗斯·吉斯克、阿里·法尔哈迪— 你只看一次:统一的实时物体检测 (2015)
  • 约瑟夫·雷德蒙,阿里·法尔哈迪— YOLO9000:更好、更快、更强 (2016)
  • 艾伦·泽伦纳— 亚得 2K:又一个黑暗之网 2 Keras
  • https://pjreddie.com/darknet/yolo/ YOLO 官方网站()

汽车检测数据集:Drive.ai 样本数据集(由 drive . ai 提供)在知识共享署名 4.0 国际许可下获得许可。

Github 回购:https://github.com/TheClub4/car-detection-yolov2

不平衡数据集分类指南

原文:https://towardsdatascience.com/guide-to-classification-on-imbalanced-datasets-d6653aa5fa23?source=collection_archive---------3-----------------------

理解和纠正阶级不平衡的教程

不平衡中的平衡平衡什么是不平衡 —阿马杜·贾鲁呸

**免责声明:**这是一个关于处理不平衡数据集的综合教程。虽然这些方法对于多类分类仍然有效,但为了简单起见,本文的主要焦点将放在二分类上。

简介

任何经验丰富的数据科学家或统计学家都知道,数据集很少均匀分布在感兴趣的属性之间。假设我们的任务是发现欺诈性信用卡交易——很自然,这些交易中的绝大多数都是合法的,只有极小一部分是欺诈性的。类似地,如果我们测试个体的癌症或病毒(包括新冠肺炎病毒)的存在,阳性率将(希望)只是被测试者的一小部分。更多例子包括:

  • 一家电子商务公司预测哪些用户将在其平台上购买商品
  • 一家制造公司分析生产材料的缺陷
  • 垃圾邮件过滤试图区分“火腿”和“垃圾邮件”
  • 入侵检测系统检查网络流量中的恶意软件签名或非典型端口活动
  • 预测客户流失率的公司
  • 在银行或金融机构关闭特定账户的客户数量
  • 电信设备故障预测
  • 从卫星图像探测石油泄漏
  • 保险风险建模
  • 硬件故障检测

来自不利类别的数据点通常要少得多。这是不幸的,因为我们非常关心避免这个类的错误分类。

事实上,在分类任务中很少有完全平衡的数据。通常,我们感兴趣分析的项目本质上是“罕见”事件,因为它们非常罕见,因此难以预测。这给有抱负的数据科学家带来了一个奇怪的问题,因为许多数据科学计划没有正确解决如何处理不平衡的数据集,因为它们在行业中非常普遍。

数据集何时变得“不平衡”?

不平衡数据集的概念有点模糊。通常,两个变量之间具有 49–51 分割的二元分类数据集不会被视为不平衡。然而,如果我们有一个 90-10 分割的数据集,对我们来说这显然是一个不平衡的数据集。显然,不平衡数据的边界位于这两个极端之间。

从某种意义上说,“不平衡”一词是一个主观的词,由数据科学家来判断。一般来说,当标准分类算法(固有地偏向多数类(更多细节见上一篇文章)由于多数类的偏向而返回次优解决方案时,数据集被认为是不平衡的。数据科学家可能会查看 45–55 分割的数据集,并判断这已经足够接近,不需要采取措施来纠正不平衡。然而,数据集变得越不平衡,就越需要校正这种不平衡。

在一个概念学习问题中,如果数据集包含的一个类别的例子比另一个类别多得多,那么就说数据集呈现了类别不平衡。

因此,这些分类器倾向于忽略小类,而专注于准确分类大类。

假设你在网飞工作,负责确定哪些客户流失率(客户“流失”意味着他们将停止使用你的服务或产品)。

在一个理想的世界中(至少对于数据科学家来说),我们的训练和测试数据集将接近完全平衡,大约 50%的数据集包含会流失的个人,而 50%不会。在这种情况下,90%的准确度将或多或少地表示正分类组和负分类组的 90%的准确度。我们的误差将在两组中平均分配。此外,我们在两个类中有大致相同的点数,这从大数定律告诉我们减少了类中的总体方差。这对我们来说很好,在这种情况下,准确性是一个信息指标,我们可以不受阻碍地继续我们的分析。

在二进制响应变量中对半分割的数据集。这个例子中没有多数类。

正如你可能已经怀疑的那样,大多数已经为网飞付费的人没有 50%的机会每月停止他们的订阅。事实上,会流失的人的比例相当小,接近 90-10 的比例。这种数据集不平衡的存在是如何使问题复杂化的?

假设 90-10 的比例,我们现在有一个非常不同的数据故事要讲。将这些数据交给算法而不做任何进一步的考虑可能会导致接近 90%的准确率。这看起来很不错,对吧?这和我们以前得到的差不多。如果你尝试将这种模型投入生产,你的老板可能会不高兴。

90–10 分割的不平衡数据集。假阳性会比假阴性大很多。由于数据点较少,少数集合中的方差会更大。多数类将支配算法预测,而不对不平衡进行任何校正。

给定多数类(90%类)的流行,我们的算法将可能回归到多数类的预测。该算法可以通过任意预测多数类每次出现来非常接近地最大化其准确性(我们选择的评分标准)。这是一个微不足道的结果,提供了接近零的预测能力。

(左)正负类项目数相同的平衡数据集;在这种情况下,假阳性和假阴性的数量大致相等,导致很少的分类偏差。(右图)一个不平衡的数据集,其中大约 5%的样本属于负类,95%的样本属于正类(这可能是为网飞付费并决定在下一个付费周期退出的人数)。

当数据不平衡和/或不同错误的成本差异显著时,预测准确性(一种评估分类器性能的常用选择)可能不合适。

从视觉上看,该数据集可能如下所示:

默认情况下,机器学习算法假设数据是平衡的。在分类中,这对应于每个类的相对数量的实例。分类器从平衡分布中学习得更好。纠正失衡取决于数据科学家,这可以通过多种方式完成。

不同类型的不平衡

我们已经清楚地表明,不平衡数据集对标准数据集有一些额外的挑战。更复杂的是,在一个数据集中可能会出现不同的类型的不平衡。

(1)课间

当每个类别中包含的数据点数量不平衡时,就会出现类别间不平衡。这方面的一个例子如下所示:

阶级间不平衡的例证。我们有大量红色类的数据点,但白色类的数据点相对较少。

这方面的一个例子是乳房 x 线照相数据集,它使用称为乳房 x 线照片的图像来预测乳腺癌。考虑与阳性和阴性癌症诊断相关的乳房 x 线照片的数量:

绝大多数样本(> 90%)为阴性,而相对较少(<10%) are positive.

Note that given enough data samples in both classes the accuracy will improve as the sampling distribution is more representative of the data distribution, but by virtue of the law of large numbers, the majority class will have inherently better representation than the minority class.

(2)类内

当数据集平衡了类间数据,但其中一个类在某些区域不具有代表性时,就会出现类内不平衡。这方面的一个例子如下所示:

阶级内部不平衡的例证。这两个类别都有大量的数据点,但左上角白色类别中的数据点数量非常稀少,这可能导致与这些区域中预测的类别间不平衡类似的复杂性。

(3)内在和外在

一个内在不平衡是由于数据集的性质,而外在不平衡与时间、存储和其他限制数据集或数据分析的因素有关。内在特征相对简单,是我们常见的,但外在不平衡可以单独存在,也可以增加数据集的不平衡。

例如,公司经常使用入侵检测系统来分析进出网络的数据包,以检测恶意活动的恶意软件。根据您是分析所有数据还是仅分析通过特定端口或特定设备发送的数据,这将显著影响数据集的不平衡(大多数网络流量可能是合法的)。类似地,如果与可疑恶意行为相关的日志文件或数据包通常被存储,而正常日志没有被存储(或者只存储选定的几种类型),那么这也会影响数据集的不平衡。类似地,如果日志仅在正常工作日(比如晚上 9-5 点)存储,而不是 24 小时,这也会影响不平衡。

失衡的进一步复杂化

不平衡的数据集增加了更多的困难。首先,我们有类重叠。这并不总是一个问题,但经常会在不平衡的学习问题中出现,并引起头痛。下面的数据集中显示了类重叠。

类重叠的例子。一些正数据点(星形)与负数据点(圆形)混杂在一起,这将导致算法构建不完美的决策边界。

类别重叠发生在正常的分类问题中,那么这里的附加问题是什么呢?在重叠区域中更多表示的类倾向于通过基于全局学习(在完整数据集上)的方法更好地分类。这是因为该算法能够更好地了解多数类的数据分布。

相比之下,在这样的区域中较少被代表的类倾向于通过局部方法被更好地分类。如果以 k-NN 为例,随着 k 值的增大,它变得越来越全局化,越来越局部化。可以看出,k 值较低时,少数数据集的性能较好,而 k 值较高时,性能较低。多数类不会出现这种精度变化,因为它在所有点上都有很好的表现。

这表明地方方法可能更适合研究少数民族阶层。对此进行校正的一种方法是 CBO 方法。CBO 方法使用基于聚类的重采样来识别“罕见”病例,并对它们分别进行重采样,以避免在已有假设中产生小的析取项。这是一种过采样方法,我们将在下一节详细讨论。

CBO 方法。一旦每一类的训练样本被聚类,过采样就开始了。在多数类中,除了最大的一个聚类之外,所有聚类都被随机过采样,以便获得与最大聚类相同数量的训练样本。

校正数据集不平衡

有几种技术可以控制数据集的不平衡。处理不平衡数据集的技术主要有两种:采样方法成本敏感方法

其中最简单和最常用的是采样方法,称为过采样和欠采样,我们将对此进行更详细的讨论。

过采样/欠采样

简单地说,过采样涉及为少数类生成新的数据点,而欠采样涉及从多数类中移除数据点。这在一定程度上降低了数据集中的不平衡程度。

欠采样是什么样子的?我们不断地移除非常接近的相似样本,直到两个类别具有相同数量的数据点。

**欠采样。**假设您正在分析欺诈交易的数据集。大多数交易都不是欺诈性的,这造成了一个根本不平衡的数据集。在欠采样的情况下,我们将从多数类中获取较少的样本,以帮助减少这种不平衡的程度。

欠采样是个好主意吗?许多统计研究人员建议使用欠采样,但只有在欠采样类上有足够多的数据点时,欠采样才有用。此外,由于多数类最终将与少数类具有相同的点数,分布的统计特性在某种意义上将变得“更松散”。然而,我们没有通过添加人工数据点来人为地扭曲这种方法的数据分布。

欠采样插图。在试图增加数据分布的稀疏性时,移除非常接近的相似样本。

过采样是什么样子的?简言之,与欠采样相反。我们人为地向数据集中添加数据点,以平衡每个类中的实例数量。

**过采样。**在过采样的情况下,我们将从少数类中进行过采样,以帮助降低这种不平衡的程度。

我们如何生成这些样本?最常见的方法是生成在数据空间中接近现有样本或位于两个样本之间的点,如下图所示。

过采样示意图。

正如您可能已经怀疑的那样,添加虚假数据点有一些不利之处。首先,您有过度拟合的风险,尤其是如果您对有噪声的点这样做,您最终会通过添加增强的测量来加剧这种噪声。此外,随机添加这些值也会给我们的模型带来额外的噪声。

SMOTE(合成少数过采样技术)

幸运的是,我们不必为了过采样而编写随机生成数据点的算法。相反,我们可以使用 SMOTE 算法。

SMOTE 是如何工作的?SMOTE 根据现有数据点的局部密度及其与其他类的边界,在现有数据点之间生成新样本。它不仅执行过采样,而且可以随后使用清理技术(欠采样,稍后会详细介绍)来最终消除冗余。下面是研究类数据时 SMOTE 如何工作的图示。

SMOTE 功能的说明。左侧的实例是孤立的,因此被算法视为噪声。在其附近没有生成额外的数据点,或者,如果有的话,它们将非常接近奇点。中间和右侧的两个聚类有几个数据点,表明这些点不太可能对应于随机噪声。因此,更大的聚类(经验数据分布)可以由算法绘制,由此可以产生额外的样本。

SMOTE 的算法如下。对于每个少数民族样本:

–找到其 k 个最近的少数民族邻居

–随机选择 j 个邻居

–沿着连接少数样本及其 j 个选定相邻样本的线随机生成合成样本(j 取决于所需的过采样量)

知情与随机过采样

使用少数类的随机过采样(替换)具有使少数类的决策区域非常具体的效果。在决策树中,这将导致新的分裂,并经常导致过度拟合。SMOTE 的知情过采样概括了少数类的决策区域。结果,学习了较大的和不太具体的区域,因此,关注少数类样本而不会导致过度拟合。

SMOTE 的弊端

过度概括。SMOTE 的程序可能是危险的,因为它盲目地概括少数民族地区,而不考虑多数民族阶层。这种策略在高度偏斜的阶级分布的情况下特别成问题,因为在这种情况下,少数阶级相对于多数阶级来说非常稀疏,从而导致更大的阶级混合机会。

**不灵活。**SMOTE 生成的合成样本数量是预先固定的,因此不允许在重新平衡速率上有任何灵活性。

另一个潜在的问题是 SMOTE 可能会在多数类空间中引入过多的人为少数类示例。这个缺点可以通过混合来解决:结合 SMOTE 和欠采样算法。其中最著名的就是 Tomek 链接 。Tomek 链接是相对类的实例对,它们是自己最近的邻居。换句话说,它们是非常接近的对立实例对。

Tomek 的算法寻找这样的配对,并移除配对的多数实例。这个想法是为了澄清少数民族和多数民族阶级之间的界限,使少数民族地区更加分明。Scikit-learn 没有内置的模块来做到这一点,尽管有一些独立的包(例如 TomekLink 、不平衡学习)。

因此,Tomek 的算法是一种欠采样技术,充当 SMOTE 的数据清理方法,以调节冗余。正如您可能已经怀疑的那样,有许多额外的欠采样技术可以与 SMOTE 结合使用来执行相同的功能。这些功能的完整列表可以在不平衡学习文档的功能部分找到。

另一个示例是编辑最近邻(ENN)。ENN 删除其类标签不同于至少两个其邻居的类的任何例子。ENN 比托梅克链接删除了更多的例子,也可以从两个类中删除例子。

SMOTE 的其他更细致的版本包括 Borderline SMOTE、SVMSMOTE 和 KMeansSMOTE,与 SMOTE 配合使用的欠采样技术的更细致的版本是压缩最近邻(CNN)、重复编辑最近邻和实例硬度阈值。

成本敏感学习

我们已经讨论了抽样技术,现在准备讨论成本敏感的学习。在许多方面,这两种方法是相似的——主要区别在于,在成本敏感学习中,我们通过改变单个样本的相对权重来执行欠采样和过采样。

**上升流。**上加权类似于过采样,其工作原理是增加一个类的权重,同时保持另一个类的权重为 1。

**降体重。**向下加权类似于欠采样,其工作原理是降低一个类的权重,同时保持另一个类的权重为 1。

如何使用 sklearn 实现这一点的一个例子是通过sklearn.utils.class_weight函数并应用于任何 sklearn 分类器(以及 keras 内)。

from sklearn.utils import class_weight
class_weights = class_weight.compute_class_weight('balanced',                                                  np.unique(y_train), y_train)
model.fit(X_train, y_train, class_weight=class_weights)

在这种情况下,我们已经将实例设置为“平衡的”,这意味着我们将根据它们的相对点数来处理这些实例,使其具有平衡的权重——这是我的建议,除非您有自己设置值的充分理由。如果您有三个类,并且希望将其中一个类的权重增加 10 倍,将另一个类的权重增加 20 倍(因为数据集中的这些点比多数类少 10 倍和 20 倍),那么我们可以将其重写为:

class_weight = {0: 0.1,1: 1.,2: 2.}

一些作者声称,成本敏感学习比随机或定向过采样或欠采样稍微更有效,尽管所有方法都是有帮助的,并且定向过采样在功效上接近成本敏感学习。就我个人而言,当我在处理机器学习问题时,我会使用成本敏感学习,因为它更容易实现并与个人沟通。然而,使用采样技术可能还有其他方面可以提供我所不知道的更好的结果。

评估指标

在这一节中,我概述了几个可用于分析分类器性能的指标,这些分类器被训练来解决二元分类问题。这些包括(1)混淆矩阵,(2)二进制分类度量,(3)接收器操作特性曲线,和(4)精度-召回曲线。

混淆矩阵

不管你从它的名字中获得了什么,混淆矩阵是绝对令人困惑的。混淆矩阵是评估二元分类器的最基本形式。给定我们的分类器的预测输出和真实的响应变量,混淆矩阵告诉我们每个类别有多少预测是正确的,有多少是不正确的。混淆矩阵提供了基于这些因素的分类器性能的简单可视化。

这是混淆矩阵的一个例子:

希望这显示的相对清晰。TN 单元格告诉我们真阳性的数量:我预测为阳性的阳性样本的数量。

TP 单元格告诉我们真正阴性的数量:我预测为阴性的阴性样本的数量。

FP 细胞告诉我们假阳性的数量:我预测为阳性的阴性样本的数量。

FN 细胞告诉我们假阴性的数量:我预测为阳性的阳性样本的数量。

这些数字非常重要,因为它们构成了接下来讨论的二元分类度量的基础。

二元分类度量

二元分类有过多的单值度量。因此,此处仅介绍一些最常用的方法及其不同的公式,更多详细信息可在 sklearn 文档中找到,以及它们与混淆矩阵和 ROC 曲线的关系(在下一节讨论)此处。

可以说,二元分类最重要的五个指标是:(1)精确度,(2)召回率,(3) F1 分数,(4)准确度,和(5)特异性。

**精度。精确为我们提供了问题的答案“在我所有的积极预测中,有多少是正确的?”。如果您有一个正确预测所有阳性类别的算法,但也有很大一部分误报,精度将会很低。为什么称之为精度是有道理的,因为它是我们预测有多“精确”的一个度量。

**回忆。回忆为我们提供了另一个问题的答案“在所有阳性样本中,我正确预测的比例是多少?”。我们现在对假阴性感兴趣,而不是假阳性。这些是我们的算法遗漏的项目,并且通常是最严重的错误(例如,未能诊断出实际上患有癌症的癌症,未能发现恶意软件,或未能发现有缺陷的项目)。在这种情况下,“召回”这个名称也是有意义的,因为我们可以看到算法能够提取多少样本。

应该清楚的是,这些问题虽然相关,但彼此有很大的不同。有可能具有非常高的精度,同时具有低的召回率,反之亦然。例如,如果您每次都预测多数类,那么您会对多数类有 100%的回忆,但是您会从少数类得到很多误报。

要指出的另一个要点是,可以为每个单独的类确定精度和召回率。也就是说,我们可以谈论 A 类的精度,或者 B 类的精度,它们会有不同的值——在这样做的时候,我们假设我们感兴趣的类是正类,而不考虑它的数值。

F1 分数是精确度和召回率的调和平均值,它们的相对权重可以使用参数β 来调整。

**F1 比分。**F1 分数是一个单值指标,通过使用调和平均值(一种奇特的平均类型)结合了精确度和召回率。 β 参数是一个严格的正值,用于描述召回率对精确度的相对重要性。较大的 β 值更强调查全率而不是查准率,而较小的值则不太强调查全率。如果该值为 1,则精确度和召回率的权重相等。

F1 高分意味着什么?这表明精度和召回率都有很高的值,这很好,也是在不平衡数据集上生成功能良好的分类模型时所希望看到的。较低的值表示精确度或召回率较低,可能需要引起关注。良好的 F1 分数通常低于良好的准确性(在许多情况下,0.5 的 F1 分数被认为是非常好的,例如从乳房 x 光片预测乳腺癌)。

**特异性。简单来说,特异性就是对负值的回忆。它回答了问题“在我所有的负面预测中,有多少是正确的?”。这在需要检查假阳性的相对比例的情况下可能很重要。

宏观、微观和加权分数

这就是事情变得有点复杂的地方。任何在 sklearn 上钻研过这些指标的人可能都注意到了,我们可以参考 recall-macro 或者 f1 加权分数。

宏观 F1 分数是每个班级 F1 分数的平均值。

如果我们有很多班级,并且我们对每个班级的平均 F1 分数感兴趣,这是非常有用的。如果你只关心一门课的 F1 分数,你可能不需要一个宏观的 F1 分数。

一个微 F1 分数从所有类中获取所有的真阳性、假阳性和假阴性,并计算 F1 分数。

微观 F1 分数在效用上与宏观 F1 分数非常相似,因为它给出了分类器在多个类别上的总体性能。也就是说,他们会给出不同的结果,并理解潜在的差异,结果可能是给定应用程序的信息。

加权 F1 分数与宏观 F1 分数相同,但是每个特定于类别的 F1 分数是由该类别的样本的相对数量来衡量的。

在这种情况下, N 是指数据集中属于单个类的样本的比例。对于 A 类,其中 A 类是多数类,这可能等于 0.8 (80%)。B 和 C 的值可能分别是 0.15 和 0.05。

对于一个高度不平衡的数据集,一个大的加权 F1 分数可能会有些误导,因为它受到多数类的过度影响。

其他指标

对于二元分类(在某种程度上也包括多类分类)来说,您可能会看到的其他一些指标有:

准确度。如果你正在读这篇文章,我想你已经对准确性很熟悉了,但对其他的可能就不那么熟悉了。根据混淆矩阵的度量,准确性可以描述为真实预测(阳性和阴性)与阳性和阴性样本总数之和的比率。

**G-均值。**G 均值是一个不太常见的指标,有点类似于 F1 得分。这通常用两种不同的公式表示,第一种是精确召回 g 均值,第二种是灵敏度特异性 g 均值。在分析算法性能方面,它们可以以类似于 F1 分数的方式使用。精确召回率 g 均值也可以称为 Fowlkes-Mallows 指数。

还有许多其他可以使用的度量标准,但是大多数都有专门的用例,除了这里描述的度量标准之外,几乎没有提供额外的效用。读者可能有兴趣查看的其他指标有平衡准确度、、马修斯相关系数、、标记性、和信息量、。

受试者工作特性(ROC)曲线

ROC 曲线是一个二维图形,用来描述收益(真阳性)和成本(假阳性)之间的权衡。它显示给定分类器(二元问题、参数化分类器或分数分类)的灵敏度特异性之间的关系。

这是一个 ROC 曲线的例子。

这里有很多东西需要打开。首先,穿过中心的虚线对应于一个分类器,该分类器充当“抛硬币”的角色。也就是说,它大约有 50%的正确率,是最差的分类器(我们只是猜测)。这作为我们的基线,我们可以对照它比较所有其他分类器——这些分类器应该更靠近图的左上角,因为我们希望在所有情况下都有高的真阳性率。

应当注意,ROC 曲线不评估一组分类器。相反,它在一组分类阈值上检查单个分类器。

这是什么意思?这意味着,对于一个点,我将我的分类器和阈值设置为 0.3 (30%倾向),然后评估真阳性和假阳性率。

真阳性率: 由特定分类器和分类阈值的组合产生的真阳性(对真阳性和假阴性之和)的百分比。

假阳性率: 特定分类器和分类阈值组合产生的假阳性(占假阳性和真阴性之和)的百分比。

这给了我两个数字,我可以把它们画在曲线上。然后我取另一个阈值,比如 0.4,重复这个过程。在对每个感兴趣的阈值(可能以 0.1、0.01 或 0.001 的增量)做了这些之后,我们为这个分类器构建了一个 ROC 曲线。

ROC 曲线示例显示了如何绘制单个点。与分类阈值一起选择分类器。接下来,计算这种分类和阈值组合的真阳性率和假阳性率,并随后绘图。

这样做有什么意义?根据您的应用,您可能非常反对假阳性,因为它们可能非常昂贵(例如发射核导弹),因此希望分类器具有非常低的假阳性率。相反,只要您获得了高的真阳性率,您可能就不会那么关心高的假阳性率(阻止大多数欺诈事件可能是值得的,即使您必须检查更多被算法标记为有缺陷的事件)。对于这两个比率之间的最佳平衡(其中假阳性和假阴性的代价相等),我们将采用导致离左上角最小对角线距离的分类阈值。

为什么左上角对应理想分类器?ROC 曲线上的理想点应该是(0,100) **,**也就是说,所有阳性样本都被正确分类,并且没有阴性样本被错误分类为阳性。在一个完美的分类器中,不会有错误分类!

虽然图表本身可能看起来不太有用,但它有助于比较分类器。一个特殊的指标,曲线下面积(AUC) 得分,允许我们通过比较 ROC 曲线上产生的线下总面积来比较分类器。对于理想的分类器,AUC 等于 1,因为我们将 100% (1.0)的真阳性率乘以 100% (1.0)的假阳性率。如果某个分类器的 ROC 为 0.6,而另一个分类器的 ROC 为 0.8,那么后者显然是更好的分类器。AUC 的优势在于它独立于决策标准——分类阈值——因此更容易比较这些分类器。

现在可能会想到一个问题——如果一些分类器在较低阈值时更好,一些在较高阈值时更好,会怎么样?这就是 ROC 凸包的用武之地。凸包为我们提供了一种识别潜在最佳分类器的方法——即使我们可能没有直接观察到它们,我们也可以推断它们的存在。请考虑下图:

来源: Quora

给定一族 ROC 曲线,ROC 凸包可以包括更靠近 ROC 空间左上角(完美分类器)的点。如果一条直线通过凸包上的一点,那么就没有其他斜率相同的直线通过另一个真正截距更大的点。因此,在该点的分类器在与该斜率串联的任何分布假设下都是最优的。检查图像后,这可能更容易理解。

欠采样/过采样如何影响 ROC 曲线?一篇名为“SMOTE:Synthetic Minority Over-sampling Technique”的关于 SMOTE(之前讨论过)的著名论文概述了通过对多数类进行欠采样,我们迫使 ROC 曲线向上和向右移动,从而有可能增加给定分类器的 AUC(这本质上只是验证 SMOTE 功能正确,如预期的那样)。类似地,对少数类进行过采样也会产生类似的影响。

通过欠采样扫描 ROC 曲线的图示。多数(负)类的欠采样增加会将性能从左下角移动到右上角。来源 : 研究之门

精确召回(PR)曲线

可以从 ROC 空间重铸类似于 ROC 曲线的图,并将其重新表达到 PR 空间。这些图表在许多方面类似于 ROC 曲线,但我们没有绘制召回率对辐射(真阳性率对假阳性率),而是绘制精确度对召回率。这产生了 ROC 曲线的某种镜像(曲线本身看起来有些不同),因为 PR 曲线的右上角指定了理想的分类器。这通常比 ROC 曲线更容易理解,但提供了非常相似的信息。PR 曲线下的面积通常称为 mAP,类似于 ROC 空间中的 AUC。

来源: 研究之门——计算生物学中机器学习的十个快速提示

最终点评

与不平衡数据集在许多工业机器学习应用中的流行性和重要性相反,不平衡数据集在许多数据科学项目中的代表性不足(没有双关语)。数据科学家的工作是能够识别数据集何时失衡,并遵循程序和利用指标来充分理解和控制这种失衡。

我希望在阅读这篇文章的过程中,您已经了解了一些关于处理不平衡数据集的知识,并且在将来面对这种不平衡问题时能够游刃有余。如果你是一个认真的数据科学家,这些应用程序之一的出现只是时间问题!

简讯

关于新博客文章和额外内容的更新,请注册我的时事通讯。

[## 时事通讯订阅

丰富您的学术之旅,加入一个由科学家,研究人员和行业专业人士组成的社区,以获得…

mailchi.mp](https://mailchi.mp/6304809e49e7/matthew-stewart)

Keras 中的自定义递归建模指南

原文:https://towardsdatascience.com/guide-to-custom-recurrent-modeling-in-keras-29027e3f8465?source=collection_archive---------16-----------------------

探索由基本循环层组成的 12 种不同排列,实验性地回答 3 个关于模型构建的有趣问题!

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

介绍

递归神经操作的初始层次通常从 LSTM、GRU 和 RNN 开始。但是随着任务复杂性的增加,我们应该使用更复杂的模型。也就是说,在直接转向不同的、相对复杂的模型(如注意力或变形金刚)之前,我们应该先问一个简单的问题——我们还能快速处理基本的循环层吗?在这篇文章中,我将关注同样的哲学——我们应该先尝试简单的解决方案,然后再尝试更复杂的解决方案。在接下来的部分中,我们将探索相同的一组旧的循环层(尽管有一些有趣的安排),以获得更好的数据推断。总共,我们将讨论 12 个这样的安排(包括原始设置)。最后,我们将在文本情感检测任务上测试我们的所有模型,以比较它们的性能。我们开始吧!

先决条件

在继续之前,让我们讨论几个我们应该知道的主题,以便完全理解这篇文章。还有一点,我交替使用排列和模型,因为所有讨论的模型不过是基本循环层的组合,它充当最小的构建块。

递归层输出类型

任何递归层都可以选择返回两种类型的输出— (1)最后状态输出(1 个输出)和(2)所有状态输出(N 个输出)。实际上,第二种类型更通用,因为它也包含最后的状态输出(即,第一种类型),但通常,流行的深度学习库的实现提供了返回两种类型输出的选项。对于 Keras,默认为第一种类型,您可以设置参数return_sequence=True转换为第二种类型。请注意,这里的“状态”是指递归图层的隐藏状态,N 个输出通常是数据集中的时间步长数。为了了解更多关于循环层和隐藏状态的内部情况,我推荐这篇优秀文章。现在回到主题,有趣的是,虽然第二种类型包含更多的信息(这通常是一件好事),但它也可能令人不知所措,因为我们不知道该如何处理它。由于大多数下游应用程序仍然需要一个输出,我们最终将所有状态的输出合并为一个最终输出(可能的技术—使用AveragePoolingMaxPooling)。在某种程度上,LSTM 或 GRU 也是如此,他们使用前一个州的输出(和当前输入)来创建下一个州的输出。那么有趣的问题是,“什么更好——信任 LSTM/GRU 来巩固国家产出还是应用我们自己的逻辑?”。我们将在后面的章节中尝试回答这个问题,现在,让我们继续。

循环层中的变化与输出数量有关。(作者)

堆叠循环层

递归层接受顺序输入并处理它们以返回一个或多个输出(状态向量)。现在,由于输出(如果我们返回所有状态的输出)也遵循顺序感,它们可以被认为是一些转换的原始输入,并可以被传递到 LSTM/GRU 的另一层进行进一步处理。这被称为堆叠,这里的主要直觉是,就像普通的深度神经网络,你可以添加更密集的层,或者 CNN,你可以一个接一个地添加多个卷积层,在循环分层中,你可以将多个层一个接一个地堆叠起来。理想情况下,层数越多,可调参数越多,学习能力越强。但是要小心添加太多的栈,因为这可能会导致过度拟合(对于太简单的学习需求来说,网络太复杂)。我们在这里可以问的主要问题是“增加堆叠层会带来更好的性能吗?”。

2 级堆叠循环模型,其中每一级都有不同的循环层(不同的权重)

双向循环层

一个有趣的安排是,当您有两个递归层(它们没有堆叠)时,在一个层中,数据从左到右传递用于训练,而在另一个层中,这个方向相反。这是双向递归层,直觉是,与仅具有前向训练和左上下文的正常层相比,在准备状态向量输出时具有左和右上下文可以导致更高的性能。通常,对于您期望完整数据(双向上下文)存在的任务,这是正确的,因此这对于情绪检测是有效的,因为我们有完整的句子字符串可用,但对于时间序列预测是不正确的,因为如果我们想要今天的值(比如温度),我们没有未来日期的数据。由于双向系统使用 2 个循环层,我们将其与堆叠架构进行比较,并询问“哪一个更好——2 层堆叠循环层还是双向循环层?”。

具有两个不同循环层的双向层。

方法学

接下来,让我们尝试使用我们知道的模型(基本循环层)和上面学到的技术来定义和分组我们可以创建的不同排列。在更高的层次,我们把所有的安排分成两大类—

  1. 单栈(SS) :其中我们只使用一个循环层
  2. 多栈(MS) :其中我们使用了多个循环层。为了保持分析简单,我将只使用 2 层安排。

此外,由于 rnn 已经让位于“更好”的循环层,我们在分析中将只考虑 LSTM 和 GRU。现在,在 SS 的情况下,我们可以使用 LSTM 或 GRU,我们也可以通过只取 1 个输出或 N 个输出来增加味道。这给了我们可能想要考虑的不同安排。接下来,在 MS (本文只有 2 个)的情况下,让我们首先从 1 个和 N 个输出开始。对于每个这样的设置,我们可以使用两层堆叠或双向 LSTM 和 GRU。这给了我们2x2x2=8不同的安排。所有 12 种排列组合如下所示。注意,我说的“返回序列错误”是指 1 个输出,因为你只返回一个输出,而不是完整的序列。

循环层排列的分离。

密码

现在让我们看看如何在 Keras 中编码不同的安排。为了简洁起见,我将只展示 LSTM 递归层的代码。转移到 GRU 就像在代码中用 GRU 替换 LSTM 一样简单(不过别忘了导入 GRU)。我也将只涵盖 4 个不同的品种,因为休息可以很容易地建立后,小的修改。LSTM RSF 市入门,即单一堆叠-返回序列错误-LSTM 图层😉

SS_RSF_LSTM

# import 
from tensorflow.keras import layers
from tensorflow import keras
# model
inputs = keras.Input(shape=(99, )) # input layer - shape should be defined by user.
embedding = layers.Embedding(num_words, 64)(inputs) # embedding layer
rl = layers.LSTM(128)(embedding) # our LSTM layer - default return sequence is False
dense = layers.Dense(64)(rl) # a dense layer on the output of LSTM
output = layers.Dense(1, activation='sigmoid')(dense) # final layer which gives classification result
self.model = keras.Model(inputs=inputs, outputs=output, name="SS_RSF_LSTM") # stitching everything together

需要注意的事情很少,

  • 代码是根据情感分类任务创建的(下一节)。因此,最终的输出层的大小为 1,具有 sigmoid 激活以返回概率作为输出。
  • 我们定义一个输入,其中我们说 shape=99,即我们在数据中预期的时间步长。这里指的是每个句子的字数。
  • 我们使用嵌入层将单词转换成向量表示。我们可以使用现成的单词嵌入,如 Glove 或 Word2Vec,但是我们初始化了一个新的,专门为这个任务训练的单词嵌入。每个向量的大小是 64,num_words是我们正在使用的数据集的词汇大小。
  • 我们使用一个状态输出大小为 128 的 LSTM 层。注意,由于默认返回序列为假,所以我们只得到一个输出,即 LSTM 的最后一个状态。
  • 我们将最后一个状态输出与大小=64 的密集层连接起来。这用于增强 LSTM 输出的复杂阈值处理。

SS_RST_LSTM

这里唯一的区别是,我们从 LSTM 返回所有州的输出。我们可以这样做:

inputs = keras.Input(shape=(99, ))
embedding = layers.Embedding(num_words, 64)(inputs)
rl = layers.LSTM(128, return_sequences=True)(embedding)
avg = tf.keras.layers.AveragePooling1D(pool_size=99)(rl)
dense = layers.Dense(64)(avg)
output = layers.Dense(1, activation='sigmoid')(dense)
self.model = keras.Model(inputs=inputs, outputs=output, name="SS_RST_LSTM")

注意事项:

  • 第一个变化是在 LSTM 定义中增加了return_sequence=True
  • 接下来,我们需要将 99x128 矩阵合并成 1x128 大小的向量。虽然有很多方法可以做到这一点,但我们将选择AveragePooling1D,它简单地取每 99 个时间步长向量的平均值来返回 1 个向量输出。这里的pool_size是指我们取每 99 个时间步的平均值。

MS _ RSF _ 比尔斯特姆

要有一个双向层,我们需要做的就是在 LSTM 之上添加一个Bidirectional函数。

inputs = keras.Input(shape=(99, ))
embedding = layers.Embedding(num_words, 64)(inputs)
rl = layers.Bidirectional(layers.LSTM(128))(embedding)
dense = layers.Dense(64)(rl)
output = layers.Dense(1, activation='sigmoid')(dense)
self.model = keras.Model(inputs=inputs, outputs=output, name="MS_RSF_biLSTM")

注意要移动到MS _ RST _ 比尔斯特姆你需要做两件事——(1)在 LSTM 层内添加return_sequence=True,以及(2)在双向 LSTM 层后添加AveragePooling1D逻辑,如上所述。

RST LSTM 女士

inputs = keras.Input(shape=(99, ))
embedding = layers.Embedding(num_words, 64)(inputs)
rl = layers.LSTM(128, return_sequences=True)(embedding)
rl = layers.LSTM(128, return_sequences=True)(rl)
avg = tf.keras.layers.AveragePooling1D(pool_size=99)(rl)
dense = layers.Dense(64)(avg)
output = layers.Dense(1, activation='sigmoid')(dense)
self.model = keras.Model(inputs=inputs, outputs=output, name="MS_RST_LSTM")

注意事项:

  • 要堆叠多个 LSTM,所有较低的 lstm 都必须有return_sequence=True,因为它们将作为输入馈送到下一个 LSTM。
  • 对于最顶端的 LSTM,它的用户的选择。正如我们看到的一个 RST 的例子,代码返回所有的状态序列,然后进行平均。
  • 要以这种方式堆叠更多的层,我们需要做的就是一次又一次地复制粘贴rl = layers.LSTM(128, return_sequences=True)(rl)行。这里我们有两条这样的线,我们有两层堆叠的 LSTM。

按照上面分享的提示,剩下的安排可以很容易地编码。我把它作为一个练习,并在这里分享完整的代码以供参考。

实验

资料组

为了测试我们的模型,我选择了 IMDB 情感分类数据集,其中包含 25,000 条高度极性的电影评论,其二元情感由标签 0 和 1 表示。为了在我的笔记本电脑上更方便,我进一步整理了数据,只考虑了频率最高的 5000 个单词,并截断了超过 100 个单词的句子。由于数据 API 是由 Keras 公开的,所有这些都可以由,

# import
import tensorflow as tf
# set parameters
num_words = 5000
maxlen = 100
# fetch data
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.imdb.load_data(num_words=num_words, maxlen=maxlen)

此外,Keras 已经将单词转换成整数表示形式,从而更容易输入到我们的模型中。剩下的就是确保所有的句子大小相同,因为可能有一些句子的大小小于maxlen。这可以通过用一个虚拟数字(比如 0)填充较小的句子来实现。你可以在短句的左边或右边添加填充,我选择了左边。这样做的代码是,

## perform padding
x_train = tf.keras.preprocessing.sequence.pad_sequences(x_train, padding="pre")
x_test = tf.keras.preprocessing.sequence.pad_sequences(x_test, padding="pre")

结果

为了比较所有模型的性能得分,我们将根据准备好的数据和报告准确性,对每个模型进行指定次数的训练。为了处理训练中的变化,我们将多次重复训练过程(运行),并报告每次运行中观察到的准确度分数的变化以及最高和最低分数。最后,为了确保随机权重初始化不会引入模型性能的变化,我们将为每次运行使用相同的初始权重。然后,引入的主要差异在于模型拟合及其内部训练验证数据分割。

每个实验(针对一个模型)运行 5 次,每次运行 5 个时期。总共,我们运行了 12 个这样的实验(对于我们所有的模型)。综合业绩报告卡如下所示,

看看 LSTM RST 的获胜者,这比 LSTM RSF 的简单 SS(香草 LSTM)要好得多。

现在,让我们试着回答我们之前提出的问题,

报告精确度差异的问题相关模型比较表(右侧模型减去左侧模型)。对于每个问题,更多的绿色表示是,更多的红色表示不是。

  • Q1:不同的经常性产出类型有关系吗? —简答:有!为了理解其中的原因,让我们将每一款 RSF 车型与其对应的 RST 车型进行比较。所有这些可能的比较和差异(右减去左)如上所示。很明显,4/6 的模型表现更好。事实上,我们最好的模型是 MS_RST_LSTM,它比它的 RSF 版本有超过 3%的改进。
  • Q2:堆叠多层很重要吗? —又来了!见第二个比较表,所有正差异。增加更多的层会产生额外的可调参数,从而获得更大的学习能力。但是,这并不意味着你可以堆叠 100 层,并期望它比以前工作得更好——在某一点上,它会收敛,即增加更多的层不会有帮助。但是堆叠几层确实有帮助,如图所示。
  • Q3:双向分层在对抗正常堆叠时表现更好吗?——有趣的是没有!3/4 倍堆叠层性能更好。这可能是因为多个堆栈层具有更多训练参数,因此对数据的推断更好。

结论

让我从一个免责声明开始——虽然我(或者更确切地说是实验结果)说一种安排比另一种安排更好,但我并不是暗示你应该只训练“好”的模型,而忽略其他的。请记住,每个任务及其数据都是不同的,可能会导致与上述报告不同的结果。以双向为例,通常,我发现双向与堆叠层竞争,在某些情况下甚至表现更好。这与我们之前看到的形成了对比,这证明了每个数据都是不同的。也就是说,这篇文章的目的有两个——( 1)展示仅使用基本的递归层就可以实现的不同种类的分层排列,以及(2)基于实验来帮助排列优先级,而不是忽略它们。所以下次你有一个文本分类项目,你可以从 MS_RST_LSTM 模型开始,用时间(如果你有的话)在别人身上做实验。

干杯!

在 LinkedIn 上与我联系,或者在我的网站上阅读更多这样的文章。

数据仓库指南

原文:https://towardsdatascience.com/guide-to-data-warehousing-6fdcf30b6fbe?source=collection_archive---------6-----------------------

关于不同数据建模技术的简短而全面的信息

卢克·切瑟在 Unsplash 上的照片

在本指南中,我将尝试涵盖几种方法,解释它们的差异,以及何时以及为什么(在我看来)一种比另一种更好,并可能介绍一些在建模 DWH(数据仓库)或 EDW(企业数据仓库)时可以使用的工具。

我的故事

我在一家小公司开始了我的 BI(商业智能)职业生涯,该公司向其他公司咨询如何改进他们的流程,或者只是帮助他们建立一个 BI 系统,以便他们可以自己做出决定。

那段时间我是如何想象工作的(几乎是大学一毕业):我会去工作,得到设备,有人会解释我必须做什么,我会开始做。当我第一天来上班时,我感到非常惊讶:我已经拿到了 Ralph Kimball 的书“数据仓库工具包”,我的经理告诉我要阅读和学习。于是,我开始阅读,试图理解它。我花了一些时间。我不记得花了多长时间,但也许一周左右,才能得到适当的理解(至少在我看来)。

词汇表

需要解释的术语,您可能会在本文中找到:

暂存区 —原始/源数据的副本在我们拥有 DWH 的同一个数据库/机器上

转换区 —转换后的暂存数据。准备装载到 DWH

事实表 —带有一些度量的事务性或基于事件的数据。即销售信息、仓库产品移动。

维度表 —特定事物的所有信息都在一个地方。即所有产品相关信息、客户信息。

涵盖的方法

  • 金博尔方法论
  • 英蒙方法论
  • 数据保险库
  • 数据湖
  • 湖畔小屋

金博尔方法论

我从一个我首先学会的技术开始,主要是因为它容易理解。

它是由拉尔夫·金博尔和他的同事创造的(因此得名)。这种方法被认为是一种自下而上的设计方法。对于更一般的受众来说,可能更熟悉的是次元建模名称。就个人而言,我喜欢这种建模方式的原因是——易于设计和分析。它旨在回答特定问题或帮助理解特定领域(如人力资源、销售)。这种方法允许快速开发,但是我们失去了一些灵活性。通常,我们需要重新构建 DWH(或它的某些部分)来应用这些更改。大多数 BI 报告工具可以理解这种模型,并且可以快速拖放报告(即 MS SQL Server Analysis Services,Tableau)

金博尔流量:

  • 将数据从源系统加载到登台
  • 转换数据
  • 加载 do 星形/雪花模式。

我将在下面的小节中更详细地介绍星型和雪花型模式。

星形模式

在星型模式中,我们有一个事实表和维度表(事实表中有所有的外键)。你可以在这篇维基百科文章中找到更多细节。简单地说,看起来是这样的:

SqlPac at 英文维基百科 CC BY-SA 3.0

优点:

  • 如果我们想在某些维度上进行过滤,速度会更快(不需要多个连接)
  • 简单建模(不需要标准化)

缺点:

  • 我们需要更多的空间来存储事实表中的所有外键。
  • 向事实表添加额外的维度键需要更大的努力(如果很大,更新将需要更多的时间)

雪花模式

雪花是一个多层次的星型模式。也就是说,我们在商店维度中有一个地址。我们可以用 address_PK 创建一个地址维度,它将指向 dim_shop。你可以在这篇维基百科文章中阅读雪花模式。简化的 it 视图:

SqlPac at 英文维基百科 CC BY-SA 3.0

优点:

  • 减少在现有维度上添加额外层或分组的工作量
  • 更少的存储

缺点:

  • 更难过滤值(可能需要更多连接)

我并不是说一种建模比另一种更好;这完全取决于用例、可用资源和最终目标。权衡所有选项,考虑是否要向维度添加更多分组,是否要在以后添加更多原子层(用维度表的外键更新事实表)。

英蒙方法论

实际上我没有使用过它,所以这将是一个更理论性的概述。

这种方法是由比尔·恩门创立的,被认为是一种自上而下的方法。我们必须有一个完整的图片,并相应地将其建模为 3NF(范式),这使得这种方法比 Kimballs 更复杂。不利的一面是,您需要有技能的人来设计这个数据模型,并将所有的主题领域集成到其中。与 Kimballs 相比,它需要更多的时间来运行,但它更容易维护,而且更像是一种企业级的方法。

Inmon 流量:

  • 将数据从源加载到阶段
  • 将数据添加到符合 3NF 标准的 EDW(企业数据仓库)
  • 在 EDW 上构建数据集市

为了将这些数据与 it 进行比较,我们需要对公司/业务领域的数据进行建模。从我个人的经验来看,我的第一个项目来自零售客户。我们在 Kimball 上做了一个星型模式的模型,因为我们知道需求和他们的数据问题。如果它想要更多的集成到他们的 DWH,像加入那些工作的员工,库存管理,它将更适合与 Inmon 的方法。

在我看来,如果一家公司很小,他们只想跟踪和改进特定的元素——通常用 Kimballs 的方法会更容易、更快。

数据库

从小公司跳槽到大公司对我来说也是一种打击。我更好地理解了有时候我们需要一个更好更简单的 EDW。那是我开始使用 Data Vault 的时候。在我看来——它是 Kimballs 星型模式和 Inmons 方法论的结合。两全其美。如果你想看得更详细,可以去丹·林斯特兹网站看看,他是这种方法的创始人。

我将介绍 Data Vault 的几个最重要的组件。

中心

Hub 是所有不同实体的集合,例如,对于 account hub,我们有一个帐户,account_ID,load_date,src_name 。因此,我们可以跟踪记录最初是从哪里加载的,以及我们是否需要从业务键生成一个代理键。

链接

听起来不好笑,但是链接是不同集线器之间的链接。也就是说,我们有员工,他们属于团队。团队和员工有不同的中心,所以我们可以有 team_employee_link,它会有 team_employee_link,team_id,employee_id,load_date,src_name

卫星

特定实体属性的维度缓慢变化。也就是说,我们有一个作为实体的产品。我们有多个产品信息栏,名称,价格。因此,我们将此信息作为一个渐变维度加载,其中包含信息产品标识、打开日期、关闭日期、已删除、产品名称、产品价格。捕捉所有的变化让我们能够重新创建数据的快照,并了解它是如何演变的。

除了这些最基本的实体,我们还有卫星链接,交易链接。这些我就不赘述了;如果你想了解更多——查看丹·林斯特茨网站或维基百科。

数据湖

我来自一个简单的数据背景,遇到了一个数据湖术语。它存储了我们所有的信息(结构化的和非结构化的)。如今,像大数据数据湖这样的术语正得到大量关注。直到我开始处理大量的数据,我才明白为什么我们需要存储那么多不同类型的数据。数据是今天和未来的黄金。根据我对所有数据驱动型公司的经验,数据湖几乎是必须的。尽可能多地储存,然后进行分析,寻找见解。

以原始格式存储来自多个来源的数据有其自身的成本。

如果您不正确地记录和管理您的数据湖,它可能会变成一个数据沼泽。

在我看来,这是创建 EDW 前的一个附加层。数据工程师将原始数据引入数据湖,并在此基础上构建 EDW。分析师可以工作并依赖预处理和净化的数据。

莱克豪斯

Databricks 公司在 2020 年1 月底引入了这个术语。这里的想法是我们直接在源数据上做任何事情。大多数 ML/AI 工具更多地是为非结构化数据(文本、图像、视频、声音)设计的。将它们处理到 DWH 或数据湖需要一些时间,而且肯定不会接近实时。我对这种方法有点怀疑。这就像创造了一个巨大的数据沼泽,让人们淹没在其中。太多未经管理和清理的数据可能会导致错误的假设,并且不会成为大公司的真实来源。至少现在,虽然流不是一件大事情,但我认为等待这种方法更加成熟是值得的。除非你是某个想在竞争中遥遥领先并使用尖端技术的科技初创公司,但这只是我的假设。

摘要

在我看来,所有这些方法将长期共存。这完全取决于公司及其使用案例!

如果它只是一个小型或中型企业,如果旧的学校数据仓库方法满足您的需求,为什么要使用可能不会为您带来更多利润的东西呢?

如果是大型企业,如果您想保持竞争力并为客户提供优质服务,数据湖可能是必不可少的。在我看来,您仍然需要创建一个预处理层,这将是报告的某种真实来源,具有更多聚合/清理的数据。这里最适合的(在我看来)是星型或雪花型模式。它将使我们能够更快地寻找一般模式和趋势。如果我们需要深入研究,而 DWH/数据集市过于集中,我们可以随时去数据湖查看原始数据。

或者,也许你的员工精通技术,而你是一家下一代科技创业公司,你想通过提供见解并使用尖端技术来击败竞争对手——也许你需要一个湖边小屋?不幸的是,我还没有看到真正的用例,想不出它如何能与旧的学校方法一起工作,进行更干净和更流畅的分析。

引用表

[1]https://www . Kimball group . com/data-warehouse-business-intelligence-resources/books/data-warehouse-dw-toolkit/

[2]https://en.wikipedia.org/wiki/Star_schema

[3]https://en.wikipedia.org/wiki/Snowflake_schema

https://danlinstedt.com/solutions-2/data-vault-basics/

https://en.wikipedia.org/wiki/Data_vault_modeling

[6]https://databricks . com/blog/2020/01/30/what-is-a-data-lake house . html

单细胞 RNA-seq 分析中的降维指南

原文:https://towardsdatascience.com/guide-to-dimensionality-reduction-in-single-cell-rna-seq-analysis-1d77284eed1c?source=collection_archive---------4-----------------------

图片来源: Unsplash

2000 年初,单细胞 RNA 测序(scRNA-seq)技术在组学领域取得了重大突破。分离和排序单细胞遗传物质的能力使研究人员能够识别每个细胞中哪些基因是活跃的。这为批量 RNA 测序技术提供了前所未有的机会,批量 RNA 测序技术可以在群体水平上产生平均基因表达谱。据信,scRNA-seq 将在未来十年内改变生物学和医学研究的格局。

典型的 scRNA-seq 数据表由大约 20,000 个基因作为列/特征和 50,000 到多达一百万个细胞作为行/观察值组成。正如你可以立即指出的,这种技术受到“维数灾难”的困扰。并不是所有的基因对于根据它们的表达谱将细胞分类成有意义的簇都是重要的。因此,降维技术被用于降低数据复杂性和数据可视化。它还有助于下游应用,如聚类分析,因为一些聚类算法受到高维数的影响。在这篇文章中,我将讨论三种最流行的用于 scRNA-seq 数据的降维技术——PCA、t-SNE 和 UMAP。在简要介绍了它们的工作原理和优缺点之后,我们将在真实世界的数据集上应用它们。

主成分分析

让我们考虑一个有 m 个变量和 n 个观测值的 mxn 数据集矩阵。我们数据集中的每个观察值都是 m 维向量空间中的一个向量,该向量空间由某个正交基跨越。我们知道变量之间存在固有的冗余,并且不是所有的 m 维对于理解数据集的动态都是重要的。主成分分析提出一个问题:是否存在另一种基,它是原始基的线性组合,能最好地重新表达我们的数据集?

PCA 对原始数据集执行正交变换,以创建一组新的、不相关的变量或主成分。这些主成分是原始数据集中变量的线性组合。该变换被定义为使得主分量以方差的降序排列。因此,第一主成分达到最大可能方差。其思想是丢弃方差最小的主成分,在不损失太多信息的情况下有效地降低数据集的维数。

关于 PCA 更直观的解释请参考的帖子。

优点

高度可解释、计算高效

缺点

由于遗漏事件(弱表达基因被遗漏),scRNA-seq 数据是稀疏的,这意味着数据矩阵中有 60-80%的零。它是高度非线性的结构,而 PCA 是线性降维技术,因此被认为非常不适合数据可视化。PCA 仅用于选择大约前 10-50 个主成分,这些主成分可以用下游应用程序(如聚类分析)进行处理。

t-随机邻域嵌入(t-SNE)

t-SNE 是一种基于图形的非线性降维技术。它将高维数据投影到 2D 或 3D 组件上,是一种非常流行的数据可视化方法。关于 t-SNE 的精彩直观解释,我强烈推荐你观看 StatQuest 网站上的这个视频。简而言之,该算法首先创建定义高维空间中点之间关系的高斯概率分布。然后,它使用学生 t 分布在低维空间中重建概率分布。使用梯度下降来优化低维空间中的嵌入。

利弊

非线性数据集 : t-SNE 强有力地捕捉了高维数据集中的非线性,并能够保留低维中的局部结构。这是对 PCA 的巨大改进。例如,考虑下图所示的瑞士滚动流形。由 PCA 计算的两个突出显示点之间的接近度将是连接这两个点的直线,而 t-SNE 在理论上应该能够通过适当地展开它来解决流形的非线性。

最先进的方法:算法被设计成保留局部结构,因此高维空间中的邻近点在低维嵌入中结束得更近。t-SNE 已被用作 scRNA-seq 数据可视化的金标准方法。

缺点

随机性: t-SNE 是一种随机方法,涉及随机初始化,在连续运行时不会产生类似的输出。虽然这可能会让用户感到不安,但重要的是要注意保留了局部子结构。因此,只要您允许足够数量的迭代以允许收敛,总体输出不会有太大变化。此外,您可以始终设置一个种子,以确保每次运行算法时结果都是相同的。

例如,以下图像是使用相同输入参数运行两次的程序的 t-SNE 输出(没有设置随机种子)。如您所见,聚类改变了它们的位置,但是两个输出产生了总体上相似的结果,即 5 个聚类。

**全局结构未保留:**t-SNE 的工作方式是,在进行降维的同时,不可能保留全局结构。这可能与优化 Kullback-Liebler 分歧有关,更多细节请参考这篇优秀的在 Medium 上的帖子。在上面的示例中,两个输出中各个组的形状相似,即保留了局部结构。但是,在两个输出中,组之间的距离有很大不同(参见紫色和红色组),因此没有意义。

仅数据可视化 : t-SNE 仅将数据点嵌入 2 维或最多 3 维。与 PCA 不同,它不会产生 10-50 个可被聚类算法利用的成分。t-SNE 作为一种降维技术,因此只限于数据探索或可视化。

**计算量大:**对于庞大的数据集,算法需要很长的运行时间。通常首先通过 PCA 降低维度,然后对顶部的几个主成分执行 t-SNE。尽管已经设计出了一种叫做 FItsne 的更快的实现,但它仍然存在 t-SNE 的其他缺点。

一致流形逼近和投影(UMAP)

UMAP 是麦金尼斯等人在 2018 年推出的一种相对较新的降维技术。该算法是基于图形的,主要类似于 t-SNE,它构建数据的高维图形表示,然后优化低维图形,使其在结构上尽可能相似。其背后的数学知识要高级得多,超出了本文的范围。感兴趣的读者不妨参考原文或者麦金尼斯在 youtube 上的解释。

优点

非线性数据集 : UMAP 是多方面学习降维技术,从而捕捉真实世界数据集的非线性。在数据可视化方面,它与 SNE 霸王龙不相上下。

计算效率:UMAP 的数学改进使得运行时性能优于 t-SNE(以及临时算法 FItsne)。

**全局结构保存:**与 t-SNE 相比,UMAP 能更好地保存数据的全局结构。通过调整超参数n_neighboursmin_dist,用户可以有效地控制局部和全局结构之间的平衡。

下游应用:与 t-SNE 不同,UMAP 对嵌入维数没有计算限制,可以用作有效的预处理步骤来提升基于密度的聚类算法的性能。

缺点

**缺乏可解释性:**与主成分分析不同,主成分是源数据的最大方差方向,UMAP 的低维嵌入缺乏强可解释性。

**噪声的伪检测:**UMAP 的核心假设之一是数据中存在流形结构。正因为如此,UMAP 倾向于在数据集的噪声中找到流形结构。UMAP 对较大的数据集更稳健,因为在较大的数据集中,明显受噪声影响的结构量趋于减少。

**全局结构的准确性:**虽然 UMAP 比 t-SNE 等其他技术保留了更多的全局结构,但它主要关心的是准确地表示局部结构。如果全局结构是主要兴趣,那么 UMAP 可能不是降维的最佳选择。

对比分析

现在我们已经讨论了每种方法的优缺点,让我们在真实数据集上评估它们。我承认一个数据集是不够的,应该使用几个大小和复杂程度不同的数据集进行综合评估。有一些同行评审的出版物也是这样做的,你可能希望参考和。

我选择了一个包含真实聚类信息的数据集,该数据集可以用作比较分析中的基础事实。它是由癌症基因组图谱泛癌分析项目维护的来自不同类型癌症组织的基因表达的整理。样本(实例)按行存储。每个样本的变量(属性)是 illumina HiSeq 平台测得的 RNA-Seq 基因表达水平。每个属性都有一个假名(gene_XX)。下载链接可以在 kaggle 上找到(**注:**这不是一个单细胞 RNA-seq 数据集,但想法是相同的,并服务于我们对降维技术进行比较分析的目的。)

请查看我的 github 获取完整的脚本,这里我只展示了 PCA、t-SNE 和 UMAP 分析的代码。

在解决数据的异质性方面,主成分分析显然是次优的。虽然有几种其他基于矩阵分解方法的降维技术,但可能比 PCA 效果更好;一般来说,它们更擅长保存全局结构,而不太注重保存数据的局部结构。为了理解复杂生物数据集的动力学,通过保持相邻点之间的连接来维持局部结构是重要的。这就是 t-SNE 和 UMAP 等基于邻图的方法优于基于矩阵分解的方法的地方。

然而,PCA 仍然被广泛用作聚类算法的预处理步骤。例如,在我们的癌症数据集中,累积解释方差图显示前 100 个主成分解释了约 80%的数据方差。在这 100 台电脑上应用聚类算法将提高它们的性能,而不会损失太多信息。

SNE 霸王龙在分辨单个集群方面做得更好。LUAD(橙色)簇中只有 3 个数据点被不恰当地指定为 BRCA 和 COAD。输出在视觉上很吸引人,难怪在过去十年中它被用作单细胞分析的黄金标准技术。记住 t-SNE 的局限性,如前所述,这是一个值得探索的技术,并适当调整参数。

与 t-SNE 相比,UMAP 产生了同样好或者更好的分辨率。它还在一定程度上保留了全局结构,并且运行速度明显快于 SNE 霸王龙,这使得它非常有吸引力,在不久的将来,研究人员更倾向于 UMAP 也就不足为奇了。

我希望这篇文章对单细胞分析中使用的最重要的降维技术有一个很好的概述。我计划写一篇类似的文章来讨论聚类算法。敬请期待!

在 Pyspark 和 R 中实现线性回归的指南

原文:https://towardsdatascience.com/guide-to-implement-linear-regression-in-pyspark-and-r-26a94fe938a3?source=collection_archive---------38-----------------------

凯利·西克玛在 Unsplash 上的照片

我应该使用哪种编程工具来构建我的线性回归模型?在预测准确性方面有什么不同吗?用几行代码实现哪个更简单?我的训练数据的大小有影响吗?让我们在这篇文章中探讨所有这些问题。

资料组

我使用的数据集是一个虚拟数据集,只包含两个变量,年资薪水。我们试图找出一个雇员的工资是否与他的工作年限成线性关系,从逻辑上讲,我们希望这种关系存在。

按作者分类的图像-数据集预览

Pyspark

我们将利用 Pyspark 在 Python 中训练我们的线性回归模型,因为 Pyspark 能够提升数据处理速度,这在大数据领域非常受重视。由于本文更侧重于实现线性回归模型,所以我不会触及设置 Pyspark(即 SparkContext、SparkSession、SparkConf)的技术方面,你可以在我之前的帖子中找到。

from pyspark import SQLContext, SparkConf, SparkContext
from pyspark.sql import SparkSessionsc = SparkContext.getOrCreate()if (sc is None):sc = SparkContext(master="local[*]", appName="Linear Regression")
spark = SparkSession(sparkContext=sc)sqlcontext = SQLContext(sc)
data = sqlcontext.read.csv('./Salary_Data.csv', header = True, inferSchema = True)

一旦我们将数据导入 Pyspark,我们需要告诉它哪些是我们的特征变量,哪些是我们的目标变量。对于这个数据集,很明显年资是我们的特征变量,而薪水是我们的目标变量。我们有我们的数据,我们将建立我们的模型,但我们如何知道我们的模型是否表现良好?在数据科学家中,将我们的数据集分成训练和测试数据是一种方法,通常的比例是 70:30 或 80:20。在 Pyspark 中实现机器学习算法需要注意的另一件事是,我们可以利用向量汇编器,它将所有特征组合成一个稀疏的单个向量,这大大减少了机器学习模型的训练时间。

from pyspark.ml.feature import VectorAssembler# defining Salary as our label/predictor variable
dataset = data.select(data.YearsExperience, data.Salary.alias('label'))# split data into 70% training and 30% testing data
training, test = dataset.randomSplit([0.7, 0.3], seed = 100)
# assembler to assemble the features into vector form
assembler = VectorAssembler().setInputCols(['YearsExperience',]).setOutputCol('features')
trainingSet = assembler.transform(training)
# select only features column and label column since we have already vectorised our features
trainingSet = trainingSet.select("features","label")

最后,我们准备使用我们的训练数据集来训练线性回归模型。如上所述,我们还将利用测试数据集来了解我们的模型表现如何。如下面的输出所示,我们的模型现在包含一个预测列,当我们将我们的特征列(即年资)作为测试数据集放入我们的线性回归模型时,该列包含预测工资。我们可以看到,有些预测值接近实际值,有些则不然。

from pyspark.ml.regression import LinearRegression# fit the training set to linear regression model
lr = LinearRegression()
lr_Model = lr.fit(trainingSet)# assembler to assemble the features into vector form
testSet = assembler.transform(test)
# select only features column and label column since we have already vectorised our features
testSet = testSet.select("features", "label")
# fit the testing data into our linear regression model
testSet = lr_Model.transform(testSet)testSet.show(truncate=False)

按作者分类的图片 Jupyter 笔记本输出预测值

那么,我们如何衡量线性回归模型的表现呢?我们可以利用 R ,它是 0 到 100%之间的拟合优度的度量。我们只用两行代码就可以在 Pyspark 中轻松实现。

from pyspark.ml.evaluation import RegressionEvaluatorevaluator = RegressionEvaluator()
print(evaluator.evaluate(testSet, {evaluator.metricName: "r2"}))

作者图片 Pyspark 中 R 度量的 Jupyter 笔记本输出

93.9%的 R 值表明,当我们使用年的经验拟合我们的训练模型时,我们的线性回归在预测工资方面表现得非常好。

稀有

现在,让我们在 r 中构建我们的线性回归模型。我们将数据分为 70%的训练数据和 30%的测试数据,就像我们在 Pyspark 中所做的那样。然而,让我们尝试使用我们在 Pyspark 中使用的相同测试数据,看看在模型的预测中 R 性能是否有任何差异。

data = read.csv("./Salary_Data.csv")# sample data
# set.seed(100)
# dt = sort(sample(nrow(data), nrow(data)*.7))
dt = c(5,8,9,10,16,19,20,22,26,27)
# split data into training and testing data
trainingSet<-data[-dt,]
testingSet<-data[dt,]

获得训练和测试数据集后,我们使用训练数据集训练我们的线性回归模型,并使用测试数据集预测工资

# fit linear regression model
lm_model = lm(data = trainingSet, Salary~.)
# predict the target variable with testing data
predicted_salary = predict(lm_model, testingSet)

然后,我们通过计算 R 来测量预测值的拟合优度。注意,在 R 中,我们不能运行库或命令来直接获得 R。因此,我们必须通过获得残差平方和和以及平方和来手动计算它们,这可以在此处进一步探讨。

# residual sum of squares
rss <- sum((predicted_salary - testingSet$Salary) ^ 2) 
# total sum of squares
tss <- sum((testingSet$Salary - mean(testingSet$Salary)) ^ 2) 
# obtain r^2
rsq <- 1 - rss/tss
rsq

按作者分类的图像— Jupyter 笔记本输出的 R 度量单位为 R

摘要

我们获得了与在 Pyspark 中相同的 R,这意味着就模型的准确性而言,选择 Pyspark 或 R 来训练您的模型并不重要。显然,在 R 中训练线性回归模型比在 Pyspark 中简单得多。然而,需要注意的一点是,Pyspark 在训练大数据方面更为可取,处理速度将明显快于 R 本身。

以下是我在构建线性回归模型时选择 R 还是 Pyspark 的建议:

py spark->-适合处理大量数据

R->适合于简单实现

感谢阅读,我将在接下来的几篇文章中研究其他几种机器学习算法,干杯!

可解释机器学习指南

原文:https://towardsdatascience.com/guide-to-interpretable-machine-learning-d40e8a64b6cf?source=collection_archive---------2-----------------------

破除深度学习黑箱神话的技术。

如果不能简单的解释,说明你理解的不够好。— 阿尔伯特·爱因斯坦

**免责声明:**本文借鉴并扩展了(1) Christoph Molnar 关于 可解释机器学习 的优秀书籍中的材料,我肯定会推荐给好奇的读者,(2)来自哈佛 ComputeFest 2020 的深度学习可视化研讨会,以及(3)来自哈佛大学的 CS282R 的材料,由 Ike Lage 和伊马·拉卡茹教授,他们都是该领域的杰出研究人员本文旨在向普通数据科学家浓缩和总结可解释机器学习领域,并激发他们对该主题的兴趣。

机器学习系统越来越多地用于复杂的高风险环境,如医学(如放射学、药物开发)、金融技术(如股票价格预测、数字金融顾问),甚至法律(如案例总结、诉讼预测)。尽管利用率有所提高,但仍然缺乏足够的技术来解释和诠释这些深度学习算法的决策。在某些领域,算法的决策必须是可解释的,或者归因于法律或法规规定的某些特征(如解释权),或者需要问责制,这可能会很成问题。

算法问责的必要性已被多次强调,其中最著名的案例是谷歌的面部识别算法,该算法将一些黑人标记为大猩猩,以及优步的自动驾驶汽车闯了一个停车标志。由于谷歌无法修复算法并消除导致这一问题的算法偏见,他们通过从谷歌照片的搜索引擎中删除与猴子有关的词语来解决问题。这说明了许多机器学习算法所谓的黑盒本质。

由于其预测性,黑盒问题主要与监督机器学习范例相关联。

黑盒算法——谁知道它在做什么?显然,没人。

仅仅精确是不够的。

深度学习领域的学者敏锐地意识到了这个可解释性和可解释性问题,尽管一些人(如上面引用的山姆·哈里斯)认为这些模型本质上是黑盒,但近年来已经有了一些发展,用于可视化深度神经网络的各个方面,如它们所学习的特征和表示。“信息贫乏”一词被用来指当决策是基于许多个人特征时,由于信息过载而难以提供透明度。自 2015 年以来,机器学习中的可解释性和可解释性领域出现了爆炸式增长,现在有几十篇关于该主题的论文,其中一些可以在参考文献中找到。

正如我们将在本文中看到的那样,这些可视化技术不足以完全解释深度学习算法学习到的复杂表示,但希望你会相信深度学习的黑盒解释不是真的——我们只是需要更好的技术来理解和解释这些模型。

黑盒子

机器学习中的所有算法在某种程度上都是黑盒。机器学习的一个关键思想是模型是数据驱动的——模型是根据数据配置的。这从根本上给我们带来了这样的问题,如 (1) 我们应该如何解释模型, (2) 如何确保它们在决策中是透明的,以及 (3) 确保所述算法的结果是公平的和统计上有效的。

对于像线性回归这样的东西,模型是非常好理解和高度可解释的。当我们转向支持向量机(SVM)或随机森林模型时,事情变得有点困难。从这个意义上说,在机器学习中没有白盒或黑盒算法,可解释性是作为一个光谱或不同灰度的“灰盒”而存在的。

碰巧的是,在我们“灰色”区域的远端是神经网络。在这个灰色区域的更远处是深层神经网络。当你有一个拥有 15 亿个参数的深度神经网络时——就像用于语言建模的 GPT-2 算法一样——解释模型学习到的表示就变得极其困难。

2020 年 2 月,微软发布了现存最大的深度神经网络【图灵-NLG 。这个网络包含 170 亿个参数,大约是人脑中 850 亿个神经元的 1/5(尽管在神经网络中,参数代表连接,其中人脑中有约 100 万亿个)。显然,解释一个 170 亿参数的神经网络将非常困难,但它的性能可能远远优于其他模型,因为它可以在海量数据上训练而不会饱和——这是一个更复杂的表示可以由具有更多参数的模型存储的想法。

比较图灵-NLG 与其他深度神经网络,如伯特和 GPT-2。来源

显然,表示是存在的,我们只是没有完全理解它们,因此我们必须想出更好的技术来解释模型。遗憾的是,这比读取线性回归中的系数更困难!

神经网络是强大的模型,但比更简单、更传统的模型更难解释。

通常,我们并不关心一个算法如何得出一个特定的决定,特别是当它们在低风险环境中被操作时。在这些场景中,我们在选择算法时不会受到任何可解释性限制的限制。然而,如果可解释性在我们的算法中很重要——就像它通常在高风险环境中一样——那么我们必须接受准确性和可解释性之间的折衷。

那么有什么技术可以帮助我们更好地解释和理解我们的模型呢?事实证明有很多这样的方法,区分这些不同类型的技术帮助我们检查什么是有帮助的。

本地对全球

技术可以是局部的,帮助我们研究网络的一小部分,就像观察神经网络中的单个过滤器一样。

技术可以是全局的,允许我们从整体上建立一个更好的模型,这可以包括深度神经网络中权重分布的可视化,或者通过网络传播的神经网络层的可视化。

特定型号与不特定型号的对比

高度特定于型号的技术仅适用于单一型号。例如,层可视化仅适用于神经网络,而部分依赖图可用于许多不同类型的模型,并被描述为模型不可知

特定于模型的技术通常涉及检查算法或中间表示的结构,而模型不可知的技术通常涉及检查输入或输出数据分布。

不同模型可视化技术和可解释性度量之间的区别。来源

我将在整篇文章中讨论上述所有技术,但是也将讨论在哪里以及如何使用它们来帮助我们洞察我们的模型。

因为正确的原因而正确

由于我们缺乏模型可解释性而产生的一个问题是,我们不知道模型已经被训练了什么。最好用一个虚构的例子来说明这一点(关于这个故事的真实性还有一些争论,但我们可以从中吸取的教训仍然是有价值的)。

捉迷藏

根据 AI 民间传说,在 20 世纪 60 年代,美国陆军对开发一种能够在图像中检测坦克的神经网络算法感兴趣。研究人员开发了一种算法,能够非常准确地做到这一点,每个人都对结果非常满意。

然而,当该算法在额外的图像上进行测试时,它的表现非常差。这让研究人员感到困惑,因为研究结果在开发过程中是如此积极。在所有人都摸不着头脑的一段时间后,其中一名研究人员注意到,在查看两组图像时,一组图像中的天空比另一组图像中的天空更暗。

很明显,该算法实际上并没有学会探测伪装的坦克,而是在观察天空的亮度!

虽然这个故事加剧了对深度学习的一个常见批评,但事实是,在神经网络中,尤其是深度神经网络中,你并不真正知道模型正在学习什么。

这种强有力的批评和深度学习在学术界和工业界日益增长的重要性导致了对可解释性和可解释性的日益关注。如果一个行业专家不能让他们的客户相信他们理解他们建立的模型在做什么,那么当有大的风险时,比如财务损失或人们的生命安全,真的应该使用它吗?

可解释性

在这一点上,你可能会问自己,鉴于可能有无限多种可行的解释,可视化如何帮助我们解释一个模型。定义和衡量可解释性的含义并不是一项简单的任务,而且在如何评价它的问题上几乎没有共识。

可解释性没有数学定义。文献中提出的两个定义是:

"可解释性是人类能够理解决策原因的程度." —提姆·米勒

"可解释性是人类能够持续预测模型结果的程度."— 后土金

机器学习模型的可解释性越高,人们就越容易理解为什么会做出某些决定或预测。如果一个模型的决策比另一个模型的决策更容易让人理解,那么这个模型就比另一个模型更容易解释。我们可以开始评估模型可解释性的一种方式是通过 可量化的代理

一个代理是与我们感兴趣研究的东西高度相关,但与感兴趣的对象有本质区别的东西。代理往往比感兴趣的对象更容易测量,或者在这种情况下,只是可测量的——而我们感兴趣的对象(如可解释性)可能不可测量。

代理人的想法在许多领域都很普遍,其中一个领域是心理学,它们被用来测量抽象概念。最著名的代表可能是智商(IQ ),它是智力的代表。虽然智商和智力之间的相关性不是 100%,但它足够高,我们可以从测量智商中获得一些有用的信息。没有直接测量智力的已知方法。

一种使用降维来允许我们在低维空间中可视化高维数据的算法为我们提供了可视化数据分布的代理。同样,一组训练图像为我们提供了感兴趣的完整数据分布的代理,但不可避免地会与真实分布有些不同(如果您在构建训练集方面做得很好,它应该不会与给定的测试集相差太多)。

事后解释呢?

事后解释(或事后解释)可能有用,但有时会误导人。这些只是为黑盒的算法行为提供了一个看似合理的合理化,不一定是具体的证据,因此应该谨慎使用。事后合理化可以用可量化的代理来完成,我们将讨论的一些技术可以做到这一点。

选择可视化

设计可视化需要我们考虑以下因素:

  • 我们要介绍的观众(谁) —这是为了调试的目的吗?说服客户吗?说服一个同行审稿人写一篇研究文章?
  • 可视化的目标(是什么) —我们是在试图理解输入(例如,来自图像的 EXIF 元数据是否被正确读取,以使图像不会从侧面进入 CNN)、输出或我们模型的参数分布吗?我们感兴趣的是输入如何在网络中演变,还是网络的静态特征,如特征图或过滤器?
  • 正在开发的模型 【如何】 —很明显,如果您没有使用神经网络,您就无法可视化网络层的特征地图。类似地,特征重要性可以用于一些模型,例如 XGBoost 或随机森林算法,但不能用于其他模型。因此,模型选择固有地偏向可以使用的技术,一些技术比其他技术更通用和通用。开发多个模型可以提供更多的多样性。

深度模型对可视化提出了独特的挑战:我们可以回答关于模型的相同问题,但是我们的询问方法必须改变!由于这一点的重要性,我们将在本文的剩余部分主要关注深度学习可视化。

深度学习可视化的子领域

深度学习可视化文献主要有三个子领域:

  1. **可解释性&可解释性:**有助于理解深度学习模型如何做出决策以及它们的学习表征。
  2. **调试&改进:**帮助模型管理员和开发人员构建和解决他们的模型,希望加速迭代实验过程,最终提高性能。
  3. **教授深度学习:**帮助教育业余用户关于人工智能——更具体地说,机器学习。

为什么解释一个神经网络如此困难?

为了理解为什么解释神经网络是困难和不直观的,我们必须理解网络对我们的数据做了什么。

本质上,我们传递到输入层的数据(这可能是一幅图像或一组用于预测变量的相关特征)可以绘制成一些复杂的分布,如下图所示(这只是一个 2D 表示,想象一下 1000 维)。

如果我们通过线性分类器运行这些数据,模型会尽最大努力分离数据,但由于我们仅限于仅包含线性函数的假设类,我们的模型将表现不佳,因为大部分数据不是线性可分离的。

这就是神经网络的用武之地。神经网络是一个非常特殊的功能。已经证明,具有单个隐藏层的神经网络能够表示所有非线性函数的假设类,只要我们在网络中有足够的节点。这就是所谓的通用近似定理。

事实证明,我们拥有的节点越多,我们可以表示的函数类就越大。如果我们有一个只有十层的网络,并试图用它来分类一百万张图像,网络将很快饱和并达到最大容量。如果我们有 1000 万个参数,随着非线性变换数量的增加,它将能够学习网络的更好表示。我们说这个型号有更大的型号容量

人们使用深度神经网络而不是单层神经网络,因为单层网络中所需的神经元数量随着模型容量呈指数增长。隐藏层的抽象大大减少了对更多神经元的需求,但这是以可解释性为代价的。我们越深入,这个网络就变得越难以解释。

神经网络的非线性变换允许我们将数据重新映射到线性可分的空间中。在神经网络的输出层,我们可以任意使用线性分类器将最初的非线性数据分成两类,如下所示。

使用神经网络将非线性数据集转换为可线性分离的数据集。来源

问题是,我们如何知道这个多层非线性变换中发生了什么,它可能包含数百万个参数?

想象一下一个 GAN 模型(两个网络为了模拟输入数据的分布而相互争斗)在一个 512x512 的图像数据集上工作。当图像被引入神经网络时,每个像素都成为神经网络的一个特征。对于这样大小的图像,特征的数量是 262,144。这意味着我们正在对超过 200,000 个特征执行潜在的 8 或 9 个卷积和非线性变换。这怎么解释呢?

更极端的例子是 1024x1024 图像,这是由 NVIDIA 的 StyleGAN 实现开发的。由于像素数量增加了四倍,图像大小增加了一倍,我们将有超过一百万个特征作为 GAN 的输入。因此,我们现在有一个一百万特征的神经网络,执行卷积运算和非线性激活,并在数十万张图像的数据集上执行这些操作。

希望我已经让你相信解释深层神经网络是非常困难的。尽管神经网络的操作看似简单,但它们可以通过某种形式的涌现产生极其复杂的结果。

形象化

在本文的剩余部分,我将讨论可用于深度神经网络的可视化技术,因为它们在机器学习的可解释性和可解释性方面提出了最大的挑战。

权重直方图

权重直方图通常适用于任何数据类型,所以我选择先介绍这些。权重直方图对于确定深度神经网络中权重的总体分布非常有用。通常,直方图显示给定值相对于其他值的出现次数。如果权重的分布是均匀的,正态分布或呈现某种有序结构可以告诉我们有用的信息。

例如,如果我们想检查我们所有的网络层是否都在从给定的批次中学习,我们可以看到在对该批次进行训练之后权重分布是如何变化的。虽然一开始这可能不是最有用的可视化,但我们仍然可以从权重直方图中获得有价值的洞察力。

下图显示了一个四层网络在 Tensorboard — Tensorflow 的主要可视化工具中的权重和偏差直方图。

张量板中的重量直方图。

对于不熟悉的人来说,还有一个绘制权重分布的工具是Weights and bias(W&B),这是一家比较新的公司,专门从事深度学习的实验跟踪。当训练具有数百万个参数的大型网络(如 GAN)时,W & B 提供的实验跟踪非常有助于日志记录,并提供了比 Tensorboard 更多的功能(对学术界的人来说是免费的)。

权重和偏差中的权重直方图。

显著图

回到我们之前讨论的 tank 问题,我们如何对这个网络进行故障排除,以确保分类器检查图像的正确部分来进行预测?一种方法是使用显著图。

显著图是在 2013 年的论文“ 深入卷积网络内部:可视化图像分类模型和显著图 ”中提出的,以及类别最大化(稍后讨论)。他们背后的想法相当简单。首先,我们计算输出类别相对于输入图像的梯度。这为我们提供了一个指标,表明我们的分类相对于每个输入图像像素的微小变化是如何变化的。如果微小的变化产生了正梯度,那么我们知道该像素的变化增加了输出值。通过可视化梯度,我们可以检查哪些像素对激活最重要,并确保被检查的图像部分对应于感兴趣的对象。

显著图提供了输出类的输入敏感度的可视化表示。

显著图为我们提供了一种计算给定图像中给定类别的空间支持度的方法(图像特定类别显著图)。这意味着我们可以查看卷积网络的分类输出,执行反向传播,并查看图像的哪些部分参与了将图像分类为给定类别。

特定类别图像及其该类别的预期显著性图的示例。来源

可以使用另一种对显著性方法的简单调整,称为校正显著性。这包括在反向传播步骤中剪切负梯度,以便只传播正梯度信息。因此,仅传达与输出增加相关的信息。您可以在论文可视化和理解卷积网络中找到更多信息

给定具有像素位置 ij 以及 c 颜色通道(RGB 图像中的红色、蓝色和绿色)的图像,我们反向传播输出以找到对应于每个像素的导数。然后,我们取权重的所有颜色通道的绝对值的最大值,并将其用作显著图 M 的第 ij 个值。

显著图 M 是具有像素位置 I 和 j 的 2D 图像。该图在每个点的值是从所有图像颜色通道 c 的反向传播中找到的导数的最大绝对值

使用 Keras 函数“可视化显著性”和“可视化显著性损失”,可以在 Keras 中轻松实现显著性图的可视化。

遮挡贴图

用于辨别图像预测中像素重要性的显著性映射的类似技术是遮挡映射。在遮挡贴图中,我们仍然在开发与图像输出相关的贴图。然而,这次我们感兴趣的是遮挡图像的一部分如何影响图像的预测输出。

基于遮挡的方法使用灰色正方形系统地遮挡(阻挡)部分输入图像,并监控分类器输出。下图-显示了一个旨在预测黑色素瘤的图像分类器-清楚地显示了该模型正在定位场景中的对象,因为当对象被遮挡时,正确分类的概率显著下降(热图在黑色素瘤所在的区域变暗,因为遮挡会降低分类器的输出性能)。

分类器显示预测黑色素瘤的分类器的遮挡图。来源

遮挡贴图实现起来相当简单,因为它只需要在给定的像素位置扭曲图像,并将预测输出保存到热图中。阿克谢·舒拉在 GitHub 上的一个很好的实现可以在这里找到。

类别最大化

研究神经网络的一个非常强大的技术是类最大化。这允许我们查看一个类的样本,即会导致分类器的类值在输出中最大化的输入。对于图像数据,我们称之为一个类的图像样本。从数学上讲,这相当于:

其中 x* 对应于类别 c 的图像样本。这种符号表示我们想要的图像对于类 c 给出了最大可能的输出,这可以解释为什么是完美的 c

大规模分类网络的输出非常有趣。下面是由 Nguyen、Yosinski 和 Clune 在他们 2016 年关于深度卷积网络可视化的论文中生成的一些图像。他们在一个深度卷积神经网络上执行类最大化,该网络在 ILSVRC-2013 数据集上进行训练。

由深度卷积网络上的类最大化生成的图像。来源

激活最大化

类似于类最大化,激活最大化帮助我们可视化卷积过滤器的范例。类别最大化是激活最大化的子集,由此分类算法的输出 softmax 层被最大化。数学上,激活最大化可以描述为:

其中 x* 对应于深度神经网络中隐含层 l 或滤波器 f 的样本。这种符号表示我们想要最大化滤波器或层的输入(在卷积网络的情况下是图像)。这在下面针对深度卷积神经网络的 8 层来说明。

深度卷积网络上激活最大化生成的图像。来源

LIME(局部可解释的模型不可知解释)

LIME 代表本地可解释的模型不可知解释,甚至有自己的 Python 包。因为该方法被设计为模型不可知的,所以它可以应用于许多不同的机器学习模型。它首先出现在马尔科·图利奥·里贝罗和他的同事们的论文中,包括 “机器学习的模型不可知可解释性”’“我为什么要相信你?”:解释任何分类器的预测' *,*均发表于 2016 年。

局部代理模型是用于解释黑盒机器学习模型的个体预测的可解释模型。LIME 是本地代理模型的一个实现。

代理模型被训练来近似底层黑盒模型的预测。

LIME 不是训练一个全局代理模型,而是专注于训练局部代理模型来解释个体预测。

向人类决策者解释个人预测。 来源

在 LIME 中,我们扰动输入并分析我们的预测如何变化。不管听起来如何,这与遮挡映射和显著性映射非常不同。我们的目标是在由邻近性度量 πₓ 管理的给定位置,使用来自一组可能模型 G 的可解释模型 g (例如具有几个系数的线性模型)来近似底层模型 f我们还添加了一个正则项ω,以确保可解释的模型尽可能简单。这在下面的等式中说明。

实例 x 的解释模型是最小化损失 L(例如,均方误差)的模型 g(例如,线性回归模型),其测量解释与原始模型 f(例如,xgboost 模型)的预测有多接近,同时模型复杂度ω(g)保持较低(例如,偏好较少的特征)。g 是可能解释的族,例如,所有可能的线性回归模型。邻近度πₓ定义了我们在解释时考虑的实例 x 周围的邻域有多大。

图像的 LIME 与表格数据和文本的 LIME 工作方式不同。直觉上,干扰单个像素没有多大意义,因为不止一个像素对一个类有贡献。随机改变单个像素可能不会改变预测太多。因此,通过将图像分割成“超像素”并关闭或打开超像素来创建图像的变体。

被分割成超像素的猫的图像。来源

超像素是具有相似颜色的互连像素,可以通过用用户定义的颜色(如灰色)替换每个像素来关闭。用户还可以指定在每个排列中关闭超像素的概率。

解释谷歌的 Inception 神经网络做出的一个图像分类预测。预测的前 3 类分别是“电吉他”(p = 0.32)、“木吉他”(p = 0.24)和“拉布拉多”(p = 0.21)。来源

保真度度量(可解释模型逼近黑盒预测的程度,由我们的损失值 L 给出)让我们很好地了解了可解释模型在解释感兴趣的数据实例附近的黑盒预测时的可靠性。

LIME 也是为数不多的用于表格数据、文本和图像的方法之一。

注意,我们也可以生成全局代理模型,它遵循相同的思想,但用作整个黑盒算法的近似模型,而不仅仅是算法的局部子集。

部分相关图

部分相关性图显示了一个或两个特征对机器学习模型的预测结果的边际影响。如果我们使用具有一百个特征的数据集(包括前几天的黄金价值)来分析像黄金这样的金属的市场价格,我们会发现黄金价格对一些特征的依赖性比其他特征高得多。例如,黄金价格可能与石油价格密切相关,而与鳄梨价格没有密切联系。该信息在部分相关性图中可见。

自行车租赁与温度、湿度和风速的部分相关图示例。我们看到,在这三个变量中,温度对自行车租赁数量的依赖性最强。来源

请注意,这与线性回归模型不同。如果这是在线性回归模型上执行的,则每个部分相关性图将是线性的。部分依赖图允许我们看到关系的全部复杂性,它可能是线性的、指数的或一些其他复杂的关系。

部分依赖图的主要缺陷之一是,它只能真实地显示涉及一个或两个特征的 2D 解释。因此,对多个变量之间的高阶交互项进行建模是困难的。

还有一个变量独立性的固有假设,但通常不是这样(例如身高和体重之间的相关性,这是医学数据集中的两个常见参数)。由于多重共线性,变量之间的这些相关性可能导致其中一个变量冗余或给算法带来问题。当这成为一个问题时,使用累积局部效应(ALE)是更可取的,因为当涉及到共线性时,它不会遭受与部分相关图相同的陷阱。

为了避免过度解释数据稀疏特征区域中的结果,在部分相关性图的底部添加 rug 图有助于查看数据丰富和数据稀疏区域出现的位置。

个体条件期望

ICE 类似于部分依赖关系图,只是为数据集中的每个实例绘制了不同的线条。因此,部分依赖图为我们提供了一个特性变量对输出变量的依赖的平均视图,而 ICE 允许我们看到特性变量的特定于实例的依赖。当交互变量存在时,这是有用的,当查看平均结果时,交互变量可能被掩盖,但是当使用 ICE 时,交互变量变得非常明显。

自行车租赁关于温度、湿度和风速的单个条件期望图示例。我们看到,每个图在实例之间没有表现出任何异质性,因此不太可能存在任何重要的相互作用项。来源

存在不同类型的冰图,例如也存在中心冰图和衍生冰图,但是本质上以不同的形式提供相同的信息。

沙普利值

沙普利值是由劳埃德·沙普利于 1953 年从合作博弈论的一个方面得出的概念。在合作博弈理论中,Shapley 值根据每个玩家在所有排列中的平均贡献来优化他们的支出。当应用于机器学习时,我们假设每个特征都是游戏中的一个玩家,所有人一起工作以最大化预测,这可以被认为是支出。Shapley 值根据每个要素对输出值的贡献将支出的一部分分配给每个要素。

例如,如果您正在查看房价,并且从分析中移除了单个要素,这会如何影响模型预测?如果预测值下降了一个数量,我们可以推断该特征对预测的贡献如此之大。当然,事情并不那么简单,我们必须对每个可能的特征组合进行计算,这意味着我们需要运行 模型,其中 x 是特征的数量。

因此,Shapley 值是一个特征值在所有可能的联合中的平均边际贡献。

ϕ沙普利值的方程式,来自合作博弈理论。

这个等式可能看起来令人生畏,所以让我们从右到左一点一点地检查它。为了知道我们点 *xᵢ、*的边际贡献,我们使用我们的特征子集 S 中不包含特征 *xᵢ、*的所有特征来计算我们的模型的预测值,且我们从仍然存在该特征的子集的预测值中减去该预测值。然后,我们对特征排列的总数进行缩放,然后对所有这些贡献进行求和。因此,我们现在有了一个值,该值实质上是使用每个可能的特征子集的训练模型的特征的平均贡献。

这个讨论可能看起来很抽象,所以举个例子会很有帮助。Christoph 的书中使用的例子是考虑房价的一个很好的例子。如果我们有预测房价的特征,包括(1)公寓的大小(数字),(2)离附近公园的远近(二元),以及(3)公寓所在的楼层。为了计算每个特性的 Shapley 值,我们采用每个可能的特性子集,并预测每种情况下的输出(包括没有特性的情况)。然后,我们将每个特征的边际贡献相加。

计算简单房价预测模型的 Shapley 值时需要考虑的所有可能的特征排列。来源

一个参与者可以是单个特征值,例如对于表格数据,但是一个参与者也可以是一组特征值。例如,为了解释图像,可以将像素分组为超像素,并在它们之间分配预测。

据我所知,Python 上没有 Shapley 值的官方包,但有一些可用的存储库已经实现了它,用于机器学习。一个这样的包可以在这里找到。

Shapley 值的主要缺点是,对于大量的特征,由于特征数量的线性增加,可能的排列数量呈指数增加,因此计算非常昂贵和耗时。因此,对于特征数量非常大的应用,Shapley 值通常使用特征排列的子集来近似。

马尔科·图利奥·里贝罗、萨梅尔·辛格和卡洛斯·盖斯特林在 2018 年的一篇论文中首次介绍了这一点,他们是创造石灰的同一批研究人员。它也有自己的由 Marco 开发的 Python 包。Python 的 ALIBI 包中也有。

锚点解决了局部解释方法的一个关键缺点,如 LIME 以线性方式代理模型的局部行为。然而,不清楚该解释在多大程度上在要解释的实例周围的区域中成立,因为模型和数据在该实例的邻域中都可以表现出非线性行为。这种方法很容易导致解释的过度自信和对看不见但相似的例子的误导性结论。anchor 算法通过将覆盖范围(解释适用的区域)合并到优化问题中来解决这个问题。

与 LIME 类似,锚点可以用于文本、表格和图像数据。对于图像,我们首先将它们分割成超像素,同时仍然保持局部图像结构。然后,可解释的表示包括锚中每个超像素的存在或不存在。几种图像分割技术可用于将图像分割成超像素,如 slic 或 quickshift 。

该算法支持多种标准图像分割算法( felzenszwalb、slic 和 quickshift ),并允许用户提供自定义分割功能。

当使用初始网络分类时,小猎犬的锚被叠加在其他图像背景上,而预测准确性没有降低。来源

反事实

反事实是锚的对立面。锚是当存在时足以锚定预测的特征(即,防止其通过改变其他特征而被改变)。在锚点部分,我们看了一个例子,这些锚点是图像的超像素。事实上,图像中不属于锚点的每个超像素都是反事实——我们可以通过改变反事实来改变预测,而不是改变锚点。

反事实是在沃希特等人 2017 年题为 “不打开黑盒的反事实解释:自动化决策和 GDPR”的论文中首次提出的。反事实的基本思想是,我们希望找到我们能够对最少数量的特征做出的最小改变,以便获得我们想要的期望输出。

预测的反事实解释描述了将预测改变为预定义输出的特征值的最小变化。

什么是反事实?这是我们的特征空间的最小变化,允许我们跨越一个决策边界。来源

这听起来像是一个欠定义的任务,因为我们有很多方法可以改变我们的实例以满足我们期望的输出。这种现象被称为“罗生门效应”,因此,我们必须将我们的问题转换成优化问题的形式。首先,我们希望确保尽可能少地改变特征,并且尽可能少地改变这些特征,同时还维护可能给定数据联合分布的实例。我们的优化问题的损失函数可以转换为

作为反事实优化问题的一部分要最小化的损失函数。

损失函数的第一项表示模型预测*f’(x’)和预期输出y’之间的二次距离。第二项表示原始实例和反事实实例之间的距离度量。二次项具有缩放参数,该参数将预测输出的重要性缩放到正常实例 x 和反事实实例x’*之间的距离。

我们使用的距离度量是曼哈顿距离,因为反事实不仅应该接近原始实例,还应该尽可能少地改变特征。距离函数被描述为

这是使用中间绝对偏差缩放的曼哈顿距离。

如果我们有一个小的缩放参数,距离度量就更重要,我们更喜欢看到接近正常情况的反事实。如果我们有一个大的尺度参数,预测就变得更加重要,我们对反事实与正常情况的接近程度就不那么在意了。

当我们运行我们的算法时,我们不需要为我们的缩放参数选择一个值。相反,作者建议由用户给出一个容差ϵ,它代表我们可以容忍预测与我们的输出有多远。这表现为

我们优化问题的一个附加约束。

我们的优化问题可以简洁地描述为

我们的目标是找到反事实 x ’,使我们的总损失函数最小化,同时改变缩放参数 λ。

反事实的优化机制可以描述为“生长球体”方法,其中输入实例 x 、输出值*y’*和容差参数 ϵ 由用户给出。最初,设定比例参数 λ 的一个小值。对当前允许的反事实“范围”内的随机实例进行采样,然后将其用作优化的起点,直到该实例满足上述约束条件(即,如果预测值和输出值之间的差异低于我们的容差)。然后,我们将这个实例添加到我们的反事实列表中,并增加 *λ,*的值,这有效地增加了我们的“球体”的大小。我们递归地这样做,生成一个反事实列表。在程序的最后,我们选择最小化损失函数的反事实。

反事实是在 Python 包 ALIBI 中实现的,你可以在这里阅读(它们也有一个替代描述,可能比我自己的描述更有帮助和清晰)。

其他技术

这里还有一些我没有提到的技术,我建议感兴趣的读者参考一下。这些包括但不限于:

累积局部效应

特征重要性

降维技术(PCA,t-SNE)

沙普利加法解释(SHAP)

模型蒸馏

在这个 GitHub 页面上也可以找到一个很好的关于机器学习可解释性主题的知识库,它涵盖了关于该主题的论文、讲座和其他博客。

最终意见

深度学习可视化是一个复杂的话题,最近几年才刚刚开始研究。然而,随着深度学习技术越来越多地融入我们的数据驱动型社会,它将变得更加重要。我们大多数人可能更看重表现而不是理解,但我认为能够解释和说明模型将在未来为个人和公司提供竞争优势,这肯定会有市场。

可视化不是解释或解释深度神经网络结果的唯一方法或最佳方法,但它们肯定是一种方法,它们可以为我们提供对复杂网络决策过程的有用见解。

问题在于,单一指标(如分类准确率)无法完整描述大多数现实任务 —多希-维勒兹和金 2017

时事通讯

关于新博客文章和额外内容的更新,请注册我的时事通讯。

[## 时事通讯订阅

丰富您的学术之旅,加入一个由科学家,研究人员和行业专业人士组成的社区,以获得…

mailchi.mp](https://mailchi.mp/6304809e49e7/matthew-stewart)

参考

这里有我在这篇文章中引用的论文,以及我认为读者可能会发现的关于算法可解释性和可解释性的论文。

【1】迈向可解释机器学习的严谨科学——多希-维勒兹和金,2017

【2】模型可解释性的神话——利普顿,2017

【3】透明度:动机与挑战 — 韦勒,2019

【4】****对人类的一种评价——解释性的解释——拉赫等人。艾尔。,2019

【5】操纵和测量模型可解释性— Poursabzi-Sangdeh,2018

【6】使用规则和贝叶斯分析的可解释分类器:构建更好的中风预测模型— Letham and Rudin,2015

【7】可解释决策集:描述和预测的联合框架 — Lakkaraju 等。艾尔。,2016 年

【8】通过原型进行案例推理的深度学习:解释其预测的神经网络 — 李等。艾尔。,2017 年

【9】贝叶斯案例模型:一种基于案例推理和原型分类的生成方法 — Kim 等人。艾尔。,2014 年

【10】学习优化风险分值——乌斯顿和鲁丁,2017

【11】可理解的医疗保健模型:预测肺炎风险和住院 30 天再入院——卡鲁阿纳等人。艾尔。,2015 年

【12】“我为什么要相信你?”解释任何分类器的预测 — 里贝罗等人。艾尔。,2016 年

【13】停止解释高风险决策的黑盒机器学习模型,转而使用可解释的模型 — Rudin,2019

【14】神经网络的解释是脆弱的——Ghorbani 等人。艾尔。,2019

【15】可视化深度神经网络决策:预测差异分析 — Zintgraf 等。艾尔。,2017

【16】显著图的健全性检查——阿德巴约等人。艾尔。,2018

【2017】解释模型预测的统一方法——伦德伯格和李,2017

****【18】特征归因之外的可解释性:用概念激活向量进行定量测试(TCAV)—Kim et al .艾尔。,2018

【19】不打开黑盒的反事实解释:自动化决策和 GDPR——沃希特等。艾尔。,2018

【20】线性分类中的可诉追索权 — Ustun 等。艾尔。,2018

【21】黑箱模型的因果解释——赵、哈斯蒂,2018

【22】学习具有成本效益且可解释的治疗制度——Lakkaraju 和 Rudin,2017 年

【23】人在回路的可解释性优先 — 拉赫等人。艾尔。,2018

【24】黑盒模型的忠实可定制解释——Lakkaraju 等人。艾尔。,2019

【25】通过影响函数理解黑箱预测 — Koh 和梁,2017

【26】简单创造不公平:对公平、刻板印象和可解释性的影响 — Kleinberg 和 Mullainathan,2019

【27】通过深度可视化理解神经网络——约辛斯基等,2015

【28】深入卷积网络内部:可视化图像分类模型和显著图 — Simonyan、Vedaldi 和 Zisserman,2014 年

【29】多方面特征可视化:揭示深度神经网络中每个神经元学习的不同类型特征——Nguyen,Yosinski,和 Clune,2016

****【30】人工智能中的解释:来自社会科学的洞见 — 提姆·米勒,2017

【31】例子还不够,学会批判!对可解释性的批评— Kim,Been,Rajiv Khanna,和 Oluwasanmi O. Koyejo,2016 年

【32】黑匣子里面是什么?律师和研究人员面临的人工智能挑战——Ronald Yu 和 Gabriele Spina Ali,2019

豚鼠品种分类

原文:https://towardsdatascience.com/guinea-pig-breed-classification-517fbb036ee6?source=collection_archive---------20-----------------------

如何通过机器学习利用图像识别豚鼠品种

TL:DR 我用深度学习模型从图片中识别出了豚鼠的品种。该模型是图像 CNN,其应用了来自 Inception V3 模型的迁移学习,其中权重在 ImageNet 上预先训练。源图像来自多个图像搜索引擎。最终的模型能够对四种不同的豚鼠品种进行分类。

密码和笔记本可以在 这里 找到。

目录

  1. 前言
  2. 简介
  3. 模型建立和发现
    步骤 0。项目文件夹格式化
    步骤 1。 Raw 图像刮
    步骤 2。数据集创建
    第三步。图像数据预处理步骤 4
    。基线模型训练
    第五步。深度学习模型训练
    步骤 6。型号比较和选择
  4. 结论

前言

这是我在 Metis 数据科学训练营 完成的第三个项目。当时,我们正在学习分类、各自的分类器和指标。我想给图像分类一个镜头,但不是用 狗 vs。既然我的妻子和我都是豚鼠爱好者,那么为什么不应用我的领域知识,并从中获得一些乐趣呢?旅程就这样开始了…

Bonnie Kittle 在 Unsplash 上拍摄的照片

^

介绍

豚鼠(或豚鼠)通常被作为家庭宠物饲养,因为它们的大小易于控制(0.7-1.2 公斤),友好的天性和极度的可爱。这些可爱的动物是啮齿动物,大小介于仓鼠和龙猫之间。它们是食草动物,吃的食物和兔子差不多:颗粒饲料、干草、蔬菜和水果。

根据 维基百科 记载,豚鼠的品种很多(13-18)。与大小和形状各异的狗不同,豚鼠的一切都与毛发有关:

在这个项目中,我选择了四个最容易识别的品种:

  • 红阿比(短发夹玫瑰花)
  • 美国(光滑,短毛)
  • 丝毛/谢尔蒂(光滑、长毛)
  • 骨瘦如柴(无毛)。

用于图像分类的豚鼠品种

^

模型构建和发现

对于本文的其余部分,您可以跟随我的 Google Colab 笔记本 。这是我完成这个项目的步骤的节略版。

你所要做的就是在你 Google Drive 的' Colab Notebooks '文件夹下新建一个名为' cavy_breed_clf 的子文件夹。将下面的笔记本和文件夹复制到' cavy_breed_clf '中,你就可以开始了。

  • /data (~163kB)
  • /图像(~130MB)
  • /lib (~67kB)
  • cavy _ breed _ clf _ train _ and _ predict _ bridged . ipynb

然而,如果你想知道我是如何到达那里的,我已经把我的脚本和笔记本按数字顺序分类了。我希望这将为以下过程提供更清晰的感觉:数据准备、训练(经典 ML,然后是神经网络)和度量/预测。

^

步骤 0。项目文件夹格式

这是第一个项目,我根据这里的和这里的的建议,努力组织我的代码和文档。

  • /data —项目数据集:原始、培训、验证和测试
  • /images —原始图像存储在按品种排序的子文件夹中,另外还有一个样本子文件夹,用于存储数据集之外的临时图像
  • /lib/data _ common . py-图像数据预处理例程
  • /lib/ml_common.py —经典的 ml 处理流程,包括分类指标
  • /lib/nn_common.py —神经网络 DL 处理过程

^

第一步。原始图像刮擦

拥有大量优质、干净和正确类型的数据非常重要。这可能是最痛苦的部分,但也是你 ML 项目中最关键的部分。它将确保你的模型将执行它被设定的目的,或者至少是一个像样的 MVP。在训练营期间,我们真正学到了这一课。

AFAIK,没有可用于机器学习的公共 cavy 图像数据集。幸运的是,基于这篇 文章 有很多有用的搜索引擎。对我来说,我主要依靠 谷歌雅虎必应

一开始,我能为每个品种收集 500 到 1000 张原始图像。我非常依赖这个出色的 Chrome 扩展 Fatkun 批量下载图片 来批量下载图片。

请注意,每个品种 1000 张图片听起来可能很多,但事实并非如此。这些都是未加工的,没有标签。我不得不在下载期间和下载后仔细检查所有 4000 多张图片,以筛选出不合格的候选人:

  • 贴错标签的动物种类或豚鼠品种
  • 图像中缺少 cavy(是的,即使搜索引擎也不是完美的)
  • 多个 cavies(模型最好只从每个图像中学习一个)
  • 漫画,而不是真正的照片
  • 重要的品种特征没有完全展示出来(例如红阿比的玫瑰花结)
  • 分辨率太低
  • 太模糊了

最终,我把它缩减到 1600 多张图片:

  • 红阿比:553 人
  • 美国人:519
  • 西尔基:267
  • 瘦子:292

这是一个适度不平衡的数据集,但我相信它不会对模型的训练产生重大影响。

^

第二步。数据集创建

在我收集了需要的图片后,我将它们分类到各自的子文件夹中。然后,我运行一个简短的脚本(也作为笔记本)来生成这些数据集;原始、培训、验证和测试。后三个数据集将成为所有未来 ML 训练、验证和测试的输入数据。

快速健全检查,以确保品种分布均匀的数据集。

跨培训、验证和测试数据集的品种分布

再次检查以确保特征和目标处于良好状态。

对功能和目标进行健全性检查

^

第三步。图像数据预处理

每个图像文件将被转换为 ML ready 格式,方法是将其调整为特定的图像形状(150,150),然后将其展平为一维数组。这些将被保存为特征(X_train,X_val,X_test)。

通过 OpenCV 进行图像转换

每个图像的品种将被一次热编码以成为标签(y_train,y_val,y_test)。

要素和标签的数据预处理

快速视觉健全检查,以确保一切正常:

^

第四步。基线模型训练

我从一开始就决定“随机森林”分类器将是我的基线模型。然而,我把这作为一个学习的机会,看看其他经典分类器与我的基线模型相比会有多好。

我创建了一个例程(Vanilla_ML_Run)来一起训练这四个分类器:

  • 虚拟分类器
  • 逻辑回归
  • 高斯朴素贝叶斯
  • 随机森林(我们的基线)

一旦已训练的分类器被保存/重新加载,我将性能与以下进行比较:

  • 分类报告
  • 混乱矩阵
  • 精确召回曲线
  • ROC 曲线

NB:我强烈推荐阅读这个和这个来很好的把握 PR 和 ROC 曲线。还有这个关于微观平均和宏观平均。

步骤 4a。高斯 NB 分类器

不用说,虚拟分类器做得不太好,显然,高斯分类器也是如此。“Silkie”和“Skinny”的准确率和召回率都很低。让我们以“Skinny”为例来看看:

  • 这里的低精度意味着它的许多预测不是“瘦的”(假阳性)
  • 召回率低意味着许多真正的“瘦子”被错误地识别为其他品种(假阴性)

混乱矩阵证实了这种理解。

步骤 4b。逻辑回归分类器

这种分类器的表现比 GaussianNB 好得多,GaussianNB 的大多数精度和召回分数都在 50 以上或接近 50。

然而,公关曲线似乎告诉了一个更清晰的故事,这种模式并没有表现得很好,特别是“瘦”。它的面积远不如其他的理想,它的曲线也偏离微观平均曲线最远。

不同品种的精确召回曲线(面积=平均值。精确分数)

步骤 4c。随机森林分类器

随机森林似乎是比逻辑回归更好的模型,尽管只是稍微好一点。看起来整体较高的分数是以“丝滑”和“骨瘦如柴”较低的回忆分数为代价的。

F1 分数和 PR 曲线强烈地表明,该模型对于较小的类(“丝滑”和“瘦”)表现得不是很好。

不同品种的精确召回曲线(面积=平均值。精确分数)

^

第五步。深度学习模型训练

既然我们已经训练和审查了我们的基线模型,我们接下来可以继续两个不同的 DL 模型,即:

  • 多层图像 CNN(卷积神经网络)
  • 使用 ImageNet 上预先训练的权重转移从 Inception V3 开始的学习

一旦训练完毕,我会用和以前一样的标准来比较模型的表现。

步骤 5a。多层图像 CNN 大楼

该架构对于一个图像 CNN 模型来说相当简单,你可以从 这里 找到更多关于它的信息。

图像 CNN 模型架构

经过 100 个历元的训练,该模型达到了 78%的训练准确率和 67%的验证准确率。它肯定比基线模型更准确,但我认为它已经过度拟合了。

训练/验证准确度与历元数

我们来看看分类报告。与基线模型相比,总体分数令人信服地更好。令人惊讶的是,“瘦子”是最好的演员。没想到啊!

分类报告

有趣的是,其他品种的精确度和召回分数参差不齐。PR 和 ROC 曲线也是如此。“瘦子”在其他班级中非常突出。训练出一个能够区分无毛豚鼠和有毛豚鼠的模型确实很酷。:)

不同品种的精确召回曲线(面积=平均值。精确分数)

受试者工作特征曲线(AUC =曲线下面积)

步骤 5b。从 InceptionV3 (ImageNet)转移学习

这个模型是使用迁移学习技术构建的,如这里的T5所示。它使用在 ImageNet 上预先训练的权重。对于这个特定的模型,我选择冻结前 230 层。

经过 100 个历元的训练,该模型达到了 99 %的训练准确率和 82%的验证准确率。这肯定是过度拟合,起伏不定的验证曲线似乎也支持这一点。这也可能意味着我的数据仍然不够。

训练/验证准确度与历元数

当我查看分类报告时,除了三个非常具体的问题,精确度和召回分数总体上都非常好。这个模型似乎倾向于将“红阿比”和“西尔基”误标为“美国人”。

分类报告

混淆矩阵也支持这一观察。这位模特狂热地将“红阿比”(31 岁)和“西尔基”(9 岁)误标为“美国人”。

直觉上,这是有道理的。与“瘦子”不同,“红阿比”是短毛,“西尔基”是皮毛光滑,从某些角度看,这两个品种很容易被误认为是“美国人”。

注意:当然,这也可能是一个简单的糟糕的原始图像的例子。我绝对想调查一下以确定。

^

第六步。模型比较和选择

InceptionV3 迁移学习模式总体得分最高。

不同模型的度量比较

最重要的是,它能够出色地分类“瘦”,而经典分类器通常都失败了(高召回率)。值得注意的是,没有一个模型能够自信地识别“红阿比”本身(低回忆)。似乎这个品种特有的玫瑰花结图案并没有那么明显。可能需要获得更高质量的图像来改进。

不同模型的回忆分数比较

深度学习模型能够在预测中巧妙地区分大多数品种(高精度)。

在所有模型中,只有“美国”遭受了类似的痛苦:在预测过程中,这些模型经常将其他品种视为“美国”(低精度)。DL 型号稍微好一点,但也好不了多少。

不同模型的精度分数比较

当我们一起比较所有模型的 PR 曲线时,很明显我们有一个真正的赢家。

类似地,迁移学习模型也以最好的 ROC 曲线开始。

因此,通过迁移学习训练的最终模型显然是最佳候选。为了好玩,我甚至用它来预测保存在子文件夹“/images/new _ samples”中的超范围图像。

^

结论

这无疑是一个奇妙而充满乐趣的项目。尽管我知道迁移学习会创造奇迹,但亲眼目睹它就发生在我眼前确实令人振奋。当我不得不处理一个小数据集时,这尤其令人鼓舞,这个数据集的大部分图像质量都很差。你能想象如果我们有更多的数据,更好的图像,这个模型会变得多好吗?

此外,深度学习模型特别“聪明”,能够区分“瘦”和其他品种。这是经典分类器无法做到的。同样,我没有用其他分类器进行测试,尤其是 XGBoost。

对我来说这还不是结束。我非常希望将这个项目扩展到以下目标:

  • 添加更多高质量的图像
  • 识别更多品种
  • 尝试其他分类器和预训练模型
  • 部署 API
  • 创建一个网站
  • 构建移动应用程序

当网站或应用程序准备好了,我一定会在社交媒体上与其他豚鼠爱好者分享。

谢谢你阅读这篇文章,我希望你和我一样喜欢!

^

H2O 无人驾驶人工智能

原文:https://towardsdatascience.com/h2o-driverless-ai-71414b441425?source=collection_archive---------53-----------------------

autoML 系列的第五名—可视化和可解释性的第一名

图片来自皮克斯拜

今天,我继续我在 autoML 工具中的冒险。其中一个领导者是 H2O 的无人驾驶人工智能产品。它有一些让我印象深刻的功能。我在这次评估中的一个缺点是,我没有足够的时间来正确训练“沃森”数据集。虽然无法获得结果,但我已经分享了足够多的经验,让您对该工具有所了解。

为什么是无人驾驶 AI?

在过去的几年里,我已经看过几次无人驾驶人工智能的演示。我自己在 2018 年用我的 AWS 账户里的试用做了一个评测。我从经验和名声中知道;这是可用的顶级 autoML 工具之一。他们兜售他们的可视化,两年前我对他们印象深刻。

设置和成本

像 DataRobot 一样,无人驾驶 AI 是一种特许产品。自去年以来,无人驾驶人工智能已经可以通过 IBM 和其他云平台使用。我无法找到一个指定用户 2020 年的确切许可成本。根据我的研究,价格似乎与每年 8 万美元的 DataRobot 费用相当。

幸运的是,我们可以免费试用无人驾驶人工智能。有几个选择。您可以获得 14 天的云实施或 2 小时的托管平台。过去,我一直使用 AWS Marketplace 产品。对于这个演示,我使用的是托管平台。两个小时是很短的时间,所以我需要有效率。

我在水族馆上开了一个账号。有几个实验室可供使用。按照建议,我开始了试驾实验室。我最初不确定是否可以加载我的数据集。我很高兴看到我可以。

等待我的实验室运转起来——作者的 gif 图

实验室启动后,我得到了一个指向 AWS 实例的 URL。又快又简单。

数据

为了保持本系列中各种工具的平等性,我将坚持使用 Kaggle 培训文件。矛盾,我亲爱的华生。使用 TPUs 检测多语言文本中的矛盾和蕴涵。在这个入门竞赛中,我们将句子对(由一个前提和一个假设组成)分为三类——蕴涵、矛盾或中性。

6 列 x 13k+行—斯坦福 NLP 文档

  • 身份证明(identification)
  • 前提
  • 假设
  • 朗 abv
  • 语言
  • 标签

加载数据

加载数据非常容易,在进行任何训练之前,都可以看到一些非常好的可视化效果。您还可以在列表中添加图表,这是一个很好的特性。大多数 autoML 工具不会给你关联图和雷达图。我认为数据热图有点弱,但这似乎是由于数据(文本)的多样性。有趣的是,当你下载可视化效果时,它们就出现了。svg 格式。如果你有 Adobe 许可证就好了。

作者截图

作者截图

训练您的模型

让模特接受培训很简单。发射实验。您可以根据自己的喜好调整精确度、时间和可解释性刻度盘。还有很多专家设置可以查看。

作者截图

在这个主要的可视化和日志之间,您可以很好地了解您的培训工作正在取得的进展。我很欣赏这一点!我可能对我的拨号盘过于激进,在我分配的时间内,我无法完全完成整个实验。

实验运行—作者 gif

评估培训结果

嗯,我没有足够的时间用我的时间来训练模特。我试图启动一个新的实验室,并再次尝试,但我只是得到了 45 分钟的“等待工人”的消息。我会对生成的特征感兴趣。特征生成是该工具的一个显著特点。

好消息是有一些预运行的项目,你可以自己浏览。

我确实看到 H2O 增加了自动报告功能!很好的补充。这份报告不像 DataRobot 的报告那样全面,但它在正确的方向上做得很好。

作者的自动报告内容截图

H2O 有一本关于模型可解释性的免费小册子,我强烈推荐。他们是这个地区的领导者。

[## 机器学习可解释性介绍——AI 和 ML 领域的开源领导者

理解和信任模型及其结果是好科学的标志。分析师、工程师、医生…

www.h2o.ai](https://www.h2o.ai/resources/ebook/introduction-to-machine-learning-interpretability/)

当您单击“解释此模型”时,您必须等待流程运行。不要盯着屏幕,否则你会发现你的眼睛在状态上打转。

作者 gif

慢慢地,解释变得可行了。结果值得等待。

作者截图

作者截图

结论

无人驾驶人工智能是一个伟大的工具。它们提供了有趣的可视化效果,并允许您添加更多的可视化效果。模型可解释性度量和图表非常棒。和 DataRobot 一样,你需要为伟大付出代价。

实验室是免费的,所以我鼓励你今天就去尝试。预先训练的项目给你一个良好的开端,让你可以看看自己。

如果您错过了本系列中的一篇文章,这里有链接。

[## AWS Sagemaker Studio 自动驾驶仪准备好迎接黄金时段了吗?

带有一些评论的自动驾驶界面演示

towardsdatascience.com](/is-aws-sagemaker-studio-autopilot-ready-for-prime-time-dcbca718bae7) [## 免费体验 Google autoML 表格

autoML 工具用户体验评论系列之二。

towardsdatascience.com](/experience-google-automl-tables-for-free-d5648ae3d0e5) [## Azure Automated ML 倾听他们的设计师

本 autoML 系列的第 3 部分,微软,绝地大师

towardsdatascience.com](/azure-automated-ml-listens-to-their-designers-7f1c68d19eb4) [## DataRobot 让生活变得简单。

汽车系列之四——设计之美

towardsdatascience.com](/datarobot-makes-life-easy-8505637241e5)

黑客马拉松是为 c̶o̶d̶e̶r̶s̶所有人准备的

原文:https://towardsdatascience.com/hackathons-are-for-c%CC%B6o%CC%B6d%CC%B6e%CC%B6r%CC%B6s%CC%B6-everybody-b30bbaab7299?source=collection_archive---------23-----------------------

关于黑客马拉松让你无法从中受益的 3 个误区

在我最近的黑客马拉松上,加州斯坦福。

当我注册参加我的第一次黑客马拉松时,对未知的恐惧困扰着我。快速的谷歌搜索显示,我需要熬夜 24 小时来构思和创造一个符合黑客马拉松广泛主题的产品。作为一名地球科学家,我在编码方面经验有限,完全没有开发经验。因为我进入了未知的水域,我决定保持低调,静静地观察其他参与者。

这些年来,我意识到我的恐惧大多是没有根据的。黑客马拉松不仅仅限于程序员,而且黑客马拉松不是为了炫耀你知道什么,而是为了学习你不知道的。甚至在今天,当我参加黑客马拉松时,我看到我的朋友们扬起眉毛问“要参加吗?”为了消除所有的误解,让每个人都从中受益,我在这里分享了 3 个关于黑客马拉松的常见误区。

编码经验对 r̶e̶q̶u̶i̶r̶e̶d̶有益

在一次黑客马拉松中使用 CSS 和 Javascript 构建了我的第一个应用程序界面来预测野火风险,而在此之前我并不知道这两种语言。

这是我遇到的关于黑客马拉松的最大误区之一。运行良好的黑客马拉松几乎没有资格要求,除了真诚的学习热情。因此,如果您几乎没有编码经验,也没有理由感到失望。

事实上,黑客马拉松可能是学习新编程语言/API/软件工具的最快方式之一,因为有限的时间促使人们寻找快速学习新技能的方法。你可以直接跳到 Stackoverflow 去了解他们到底需要什么,而不是在教程上花费无尽的时间。此外,编码只是整个工作的一部分。将代码转换成产品需要大量的设计思维。黑客马拉松的最佳团队有效地将一个简单的想法与智能产品开发和创造性设计思维结合起来。

如果你不是一个程序员,你可以使用这些技巧中的一个来迎接挑战-

  1. 利用办公时间:在黑客马拉松期间,通常会有几位导师来帮助你完成项目。不要羞于使用它们。
  2. 与具有互补技能的人合作:这样,你可以专注于项目中适合你专长的部分。然而,如果你真的想学习一项新技能,这是不可取的。一个知道做某事的队友可能会自己做,却没有时间教你。

黑客马拉松大多有与软件 o̶n̶l̶y̶相关的项目

我最喜欢的硬件黑客之一— SafeCup 识别下药事件

尽管大多数黑客马拉松项目都是基于软件的,但也有例外。黑客马拉松通常要求参与者拿出一个面向技术(而不是面向软件)的产品。例如,今年在的 TreeHacks (斯坦福大学的黑客马拉松)中,大约 20%的获胜者的项目中有硬件组件。黑客马拉松的广泛主题(如“创造更美好的未来”)提供了巨大的灵活性。因此,如果你有一个符合问题陈述的想法,没有理由不去追求它,即使它仅仅是硬件!

硬件黑客需要牢记的一些常见技巧-

  1. 硬件产品比软件产品有更多的失败途径。在扩展功能之前使其健壮。
  2. 硬件产品可能更耗时(尤其是 AR/VR hacks)。因此,快速失效方法可能是有用的。

黑客马拉松是为 s̶h̶o̶w̶i̶n̶g̶-̶o̶f̶f̶学习准备的

在我的第一次黑客马拉松中向他人学习,谷歌总部,加州

黑客马拉松的参与者通常非常多样化。他们跨越了几个层次的技能集和知识库,在团队之间产生了巨大的力量差异。在一次黑客马拉松中,甚至在开始之前,一些参与者就在一个致力于团队组建的频道上分享了他们的 Devpost 个人资料,以展示他们在黑客马拉松中的辉煌记录。他们最终独自参加,因为没有人愿意加入他们。

大多数人参加黑客马拉松是为了学习。机器学习工程师可能想要学习一种新的算法。全栈开发人员可能想学习一种新的集成。黑客马拉松的评委们对你产品的技术细节很好奇,就像他们对你从构建产品中学到了什么一样。

促进你在黑客马拉松中学习的技巧:

  1. 远离吹牛的人。
  2. 作为项目的一部分,至少尝试一件新事物。
  3. 在最后一次展览期间,花些时间探索其他项目。

结论

黑客马拉松是学习新技能或提高现有技能的绝佳机会。有限的时间加上充满活力的环境可以帮助你学得更快。如果你不知道编码,你不必担心。如果你的项目没有大的软件组件,你也不必担心。重要的是从度过一个不眠之夜中有所收获。这只有在你不是去炫耀而是去学习的情况下才有可能。

通过项目优先的方法理解自然语言技术的现状

原文:https://towardsdatascience.com/hacking-my-way-to-understand-the-state-of-natural-language-technology-178055e510da?source=collection_archive---------52-----------------------

当人工智能遇到语言

蓝图,以实际操作的方式了解自然语言技术的最新进展。

来源:维基媒体

注意:涵盖的主题包括转换器、语言模型(BERT,GPT-2)、评估基准和对话界面(聊天机器人)。

2020 年 6 月初,我决定了解 NLP(自然语言处理)的现状,以及相应的(狭义)人工智能的角色。我通常理解一个主题的方法是自下而上的。在开始一个项目之前,彻底理解基本原理。受时间的限制,也受像 Fast AI 这样的人推广的教学法的启发,我决定先做项目。

旁注:从知识的角度来看,我已经习惯了 机器学习神经网络PyData栈和 云计算 。如果你计划复制这种方法,请记住这一点。**

本文提供了项目和潜在动机的更高层次的概述。你可以决定追寻或复制这条道路。我可能会决定写一些个人作品。现在,我总结一下我的经历和学习。

入门指南

我最初的项目列表如下:

  • 利用 OpenAI 的 GPT-2 更好地理解语言模型的项目
  • 一个 ML 驱动的聊天机器人,目的是更好地了解 NLU
  • 一个记录和分析音频对话(在线或电话)的工具

注:在我开始这个项目一周后, OpenAI 发布了他们的 API 。如果你被流言所迷惑,下一部分可能会特别有趣。

这份名单是有意开放的。计划是做感兴趣的项目,并在此过程中完善想法。选择探索 GPT-2 语言模型是因为有丰富的相关学习资源和讨论。围绕前两组想法的实验描述如下。我还没有机会开始写第三部。

玩弄 GPT-2

GPT-2 出现在 2018–19 年 NLP 中 transformer 架构和转移学习出现期间。迁移学习是一个强有力的概念。它允许预先训练的大型神经网络(在这种情况下是语言模型)为下游任务进行微调。这省去了从业者从头重新训练整个模型的麻烦。这种灵活性是语言模型成功的一个重要原因。

开始时,我四处寻找现有的 GPT-2 项目进行复制。就在那时,我偶然发现了 Max Woolf 的相关 Python 包。他的作品让初学者也能轻松入门。就在那时,我决定做一个模仿 Twitter 的机器人作为第一个项目。

模仿推特机器人

推特用户 dril 的一个模仿机器人在 2019 年变得流行起来。它是由一个 GPT-2 模型驱动的,这个模型是在 dril 的推特上微调的。
本着同样的精神,我制作了一个模仿机器人账户,该账户由 5 个不同的模仿账户组成。这些角色包括伊丽莎白女王、伏地魔、达斯·维德和无聊的埃隆·马斯克。为了获取推文,我使用了令人惊叹的 twint 包。

艾的多面性

最终的机器人账户被命名为女王达斯·伏地魔·马斯克,这是他们名字的第一个。是的,你没看错。

复制这个项目所需的信息可以在这里找到。

变形金刚,伯特和 GPT-2

然后,我走了一点弯路,阅读了 GPT-2 和 NLP 中的迁移学习背后的理论。BERT 是另一个不断出现的语言模型。GPT 和伯特都是基于变压器架构。然而,伯特只有编码器模块,而 GPT-2 只有来自变压器的解码器模块。这使得它们更适合不同类型的任务。
试图理解这两种流行模型的技术差异和功能是一项有益的工作。我强烈建议这样做!

以下是围绕这个话题的一些相关链接:

  • NLP 的 ImageNet 时刻已经到来
  • NLP 中的变压器——简介
  • 变压器架构说明
  • 关于 GPT-2 和伯特的笔记

这个弯路也让我有了下一个项目的想法。

评估 NLP 基准

机器学习的胜利与它们在标准基准上的表现息息相关。即使你不是一名研究人员,也知道像 GLUE 这样的基准会给你关于该领域的重要见解。如果你着手对比 BERT 和 GPT-2,即使没有深入的专业知识,看看他们被评估的基准会让你知道他们适合的问题。这对从业者是有帮助的。

NLP 基准,如 GLUE 和小队由多个任务组成。不同的任务测试语言不同方面的熟练程度,如实体识别、问答和共指消解。结合起来,他们测试 T21 的一般语言理解能力。

对于这个项目,我有两个目标:

  • 从相关基准中至少评估一项伯特和 GPT 新协议
  • 根据流行的基准实现各种任务

为了实现,我通过 HuggingFace 使用了 transformers Python 库。我将很快发布相关的笔记本,希望能写更多关于这个子主题的内容。

同时,这里有一些有用的链接:

  • GLUE 解释:通过基准测试了解 BERT】
  • 视频 NLP 的最新技术
  • 为什么 GPT-2 不在 GLUE leadership 董事会上?
  • hugging face 的(NLP)任务大表

实用 NLU:对话界面

对话界面变得越来越普遍。对于面向消费者的应用来说,它们将变得越来越重要。对于新兴经济体来说尤其如此,在那里,语音优先界面可以为新的互联网用户增加巨大的价值。

当我在思考对话界面时,我遇到了 Rasa 的一个在线活动。我参加了一些会谈。他们帮助我从一个开发者的角度获得了一种直觉。在那之后,我对语音界面的偏好帮助我选择了下一个项目。

AI 语音助手

对于这一次,我只是按照一个伟大的教程端到端。下面是— 如何用开源的 Rasa 和 Mozilla 工具构建语音助手。

在此实现的大多数功能都作为托管服务提供。就个人选择而言,我选择从开源工具开始。当然,在考虑生产场景时,需要考虑权衡。

Rasa 已经开发了丰富的资源和活跃的社区。他们非常有帮助。

客服聊天机器人

使用过开源工具后,我想尝试一下托管服务。像 GCP、AWS、Azure 和 IBM 这样的公司提供了选择。我选择了谷歌的对话流。

你友好的邻居银行机器人

一旦你熟悉了基本原理,比如意图和动作,构建一个机器人就简单了。预训练的机器人是一个方便的功能,但导入它们并不是一个流畅的体验。每个项目一个机器人的特性和它出现的延迟让我困惑了几分钟。

总结想法

进行上述实验是一次有趣的经历。有时,我渴望深入主题。选择放手让我探索手边的广度。这也让我可以在日程安排中挤出一些简短的黑客会议。

最近在自然语言处理领域有了一些令人兴奋的发展。在新兴经济体中,语音作为一种界面正越来越多地被采用。提高机器对语言的理解也将促进技术的民主化。

与此同时,我们需要对其局限性持现实态度。OpenAI 的 GPT-3 驱动的 API 的用例已经像病毒一样传播开来。以至于他们的首席执行官萨姆·奥尔特曼发了一条讽刺性的推特来谈论这种炒作。
Rasa 提出了对话式人工智能 5 个层次的概念。他们还提到,我们也许离第五层还有十年。

语言是人类进步的关键。通过新兴技术的视角来探索它是一项有趣的尝试。我希望创新的列车将以负责任的方式继续前行。
如果你想进行讨论或分享想法,请随时联系我们。

原载于 2020 年 7 月 30 日https://www . akashtandon . in

黑客超级智能

原文:https://towardsdatascience.com/hacking-super-intelligence-af5fe1fe6e26?source=collection_archive---------11-----------------------

照片由 Allan Beaufour 拍摄,许可: CC BY-NC-ND 2.0

人工智能/人工智能正在影响敏感的决策——为了保护我们的系统,我们需要一个统一的框架和一个新的学科:人工智能安全

世界上出现了一种新型的网络攻击。这些攻击与传统攻击不同,无法用传统方法应对。今天,这种攻击还很少,但在未来十年,我们可能会面临一场海啸。为了做好准备,我们需要从今天开始保护我们的人工智能系统。

我想从人工智能安全性的前提开始,只是意识到我在冒一个关于人工智能如何具有破坏性的陈词滥调的风险。为了让它离开桌子,我将提到 AI 不仅是我们日常生活的一部分(搜索引擎建议,照片过滤器,数字语音助手)。它已经参与了关键的决策过程;国家机构使用 AI 来更好地分析数据。汽车使用它来做出拯救生命的决定(并自动驾驶)。金融机构每天都在使用它——我们可能正在经历人工智能应用的寒武纪大爆发,在未来十年,人工智能将改变我们生活中最敏感的领域:医疗诊断、金融机构的决策、关键基础设施的控制和军事系统的决策。

基于 30 多年的数字黑客和欺诈,我们可以假设犯罪分子已经在努力利用这项技术的弱点——其中一些弱点就像人工智能一样新[1]。尽管如此,在成千上万致力于开发这些人工智能系统的人中,可能只有一小部分人在关注 人工智能系统的安全性。

在这篇短文中,我打算简要回顾一下“人工智能固有的风险”,提供一些人工智能政策的背景,以强调这个主题被处理的强度,然后提出一个新的安全规程的框架:人工智能安全

风险

" 人工智能是未来,不仅仅是俄罗斯,而是全人类。它带来了巨大的机遇,但也带来了难以预测的威胁。谁成为这个领域的领导者,谁就将成为世界的统治者。——弗拉基米尔·普京( RT )

在技术世界里,新的风险通常伴随着创新。这些风险开始很小,然后爆炸(见我关于指数风险的帖子,特别是物联网用例)。人工智能具有指数级的破坏力。想想它对数字数据的影响;想想所有的在线视频、录音电话、安全摄像头、网站……现在想象一种人工智能算法,它可以分析任何这样的数据,找到隐藏的联系,并从中提取新的意义。数据分析创建了一个新的数据体,几乎和原始数据体一样大,没有人能预料这些数据会是什么样子。今天,我们赋予这些系统反应和交互的能力,例如,让人工智能接听电话或驾驶汽车,从而成倍增加了破坏的途径。依靠不可预测的数据,以不可预测的方式做出决策。你觉得有多安全?

即使你信任人工智能做出正确决定的能力,并且你信任使用人工智能的企业/机构,也有另一个重要的警告:人工智能容易受到新型攻击。当今的网络安全主要集中在保护 IT 系统和网络物理系统(CPS)免受逻辑、代码或架构中漏洞的利用。当攻击人工智能系统时,攻击者拥有几乎无人能敌的新操作方法,例如:

  1. 在学习阶段毒害训练数据以使模型产生偏差。
  2. 利用训练白点欺骗人工智能的对抗性攻击。
  3. 暴力迫使模型提取训练数据,违反隐私或数据保密。
  4. 物理模型提取,允许攻击者提取模型,从而侵犯所有者的知识产权。

还有许多其他的例子[2]。当人工智能在公司的业务流程和敏感决策中变得至关重要时,很容易看到上述攻击如何在 SFOP 范围内导致损害场景:安全、财务、运营和隐私。

相关政策和研究

AI 战略文件时间表,自 2020 年 4 月起生效,犯罪司法所根据 CC BY-SA 4.0

人工智能安全工程一词早在 2010 年就由 Roman Yampolskiy 创造,开始引起人们对我们面临的问题的关注。2017 年 1 月,一群领先的行业和学术研究人员设计了 Asilomar AI 原则[3] 。由 1600 多名研究人员签名,并得到埃隆·马斯克和斯蒂芬·霍金等名字的认可,阿西洛马人工智能原则旨在为人工智能研究提供一个重要考虑因素的框架。大部分原则都是围绕 AI 伦理和价值观。原则 6 明确指出 AI 安全必须是所有 AI 实现中的一个考虑因素。人们的意识肯定在提高,然而,只有一小部分人在积极研究人工智能的安全性。

从好的方面来看,世界各地的监管者都很早就意识到了这种风险。这与过去的技术风险相反。例如,GDPR 是在技术侵犯我们的隐私约 30 年后,以及物联网成为现实 20 年后加州物联网法案[4]出台的。就人工智能而言,政府很早就开始关注了[5]。例如,白宫在 2018 年发布了“美国人民的人工智能”概况介绍。欧盟委员会于 2019 年 4 月发布了“可信人工智能(AI)道德准则”[6],中国多年来一直在该领域投资。人工智能政策是一个伟大的话题,我不会在这篇文章中详细阐述。为了更深入的了解,你可以研究上述战略文件的时间表,并阅读 CLTC 的总结论文[7]。

但即使有所有这些政策,任何人都可以在几分钟内编写一个人工智能应用程序,而不被人注意。我们用来管理风险的工具实际上并不存在

解决人工智能安全有很多角度,作为一名技术人员,我想把重点放在技术选项上。

解决方案景观

首先,让我们定义我们的术语。

AI 安全,在我的词汇里,只涵盖了我们需要信任 AI 的一部分。概括来说,我使用术语人工智能信任:当人工智能算法做出决策时,企业和用户睡得好的能力。为了指明保护人工智能系统免受攻击的原则,我使用了术语人工智能安全

人工智能信任:人类信任人工智能考虑结果的能力:

  1. 有限可解释性
  2. 易受针对 IT 系统的网络攻击
  3. 易受针对人工智能工作方式的攻击(例如敌对攻击、投毒等)
  4. 重大数据泄露的风险

人工智能安全:保护人工智能系统免受以下危害的规则:

  1. 人工智能本土攻击(敌对,中毒等…)
  2. 盗窃人工智能模型(即知识产权)
  3. 训练数据的推断
  4. 侵犯隐私

虽然我一直在说只有一小部分人从事 AI 安全/安保,但业界和学术界并没有完全睡着。在加州大学的一篇技术论文[8]中,作者绘制了考虑到人工智能大规模采用的不同研究领域。其中三个领域属于人工智能安全领域:稳健决策、安全领域、机密数据共享学习对抗学习。近年来,各大会议都选择将 AI 安全作为主题。例如,在 Black Hat USA 2020 中,围绕 ML/AI 主题进行了 8 次简报,其中两次直接关注模型提取[9]和防范敌对攻击[10]。ACM 人工智能与安全研讨会( AISec )涵盖了越来越多的人工智能安全主题会议。除了学术兴趣之外,我们还应该加上业界的关注点:例如,参见华为[11]的这篇综述文章和 IBM [12]领导的开源项目,该项目为您提供了一个完整的工具包,让您的系统做好准备,以应对恶意攻击(您可以在此处下载)。

AI 安全技术

研究兴趣导致了实际的解决方案。有远见的公司已经可以依靠现有的知识体系来对抗人工智能的攻击。从专业的角度来看,我认为我们应该首先报道那些无聊的东西:

作者图片

治理:

  1. 人工智能安全领域的清晰定义:我们要解决什么?
  2. 组织中 AI 安全的明确责任:是产品所有者、工程部门还是合规部门?

R&D 进程:

  1. 在开发生命周期中考虑与 AI 相关的风险。这应涵盖产品开发和数据科学运营。
  2. 每个项目应在开始时确定人工智能风险和相关的人工智能安全目标。
  3. 安全测试和红队应该被训练使用人工智能攻击媒介。
  4. 必须保护培训数据,并对威胁进行分析。

技术:

  1. R&D 团队应该使用标准的现成工具来强化系统。
  2. 必须对数据进行过滤,并做好应对敌对攻击的准备。
  3. 人工智能模型应该被强化以降低敏感度,如果可能的话,还应该能够抵御攻击。
  4. 生产中的部署应该使用不同的控制措施来保护模型和培训数据的机密性。

监控:

  1. 应该监控人工智能系统的偏见、中毒和其他攻击企图。
  2. 应在生产中分析推理和查询,以检测攻击企图(即恶意攻击或数据提取)。

就技术而言,现有工具至少可以应对基本威胁:

  1. **模型提取:**分析输入以检测模型推理尝试。例如,在线集成 PRADA 检测模型[13]并采取措施应对攻击企图。
  2. **投毒:**验证训练数据并采样(疏删样本,有多疼就多:)。在生产中,尽量实现不同独立模型之间推理结果的比较,即集成分析。此外,寻找数据中的异常。
  3. **对抗性攻击:**用对抗性训练数据训练你的模型。这可以在培训阶段使用 ART 工具箱来实现。在生产之前,尝试最小化你的模型的敏感性,例如通过使用知识转移[14]。最后,探索通过重建[15]和检测可疑输入来保护您的模型的选项。
  4. **IP 盗窃:**模型的部署,尤其是在边缘部署的情况下,必须在一个架构中保护模型的至少一部分免受本地攻击者的攻击。这可以通过在不使用模型时对其进行加密,并利用安全区域和三通来保护关键部分来实现。最后,考虑在你的模型中加入特定的水印,使用只由特定输入触发的神经路径,它可以帮助你发现别人是否偷了你的模型。

正如这篇 2016 年的论文[16]中提到的,我们真正需要的是一个统一的框架。像网络安全的其他领域一样,我们不希望每家公司都开发自己的安全风格——从社会的角度来看,技术领导者开发人工智能安全学科和最先进的技术来保护人工智能系统非常重要。

AI 安全创新

在我看来,我们需要一个整体的解决方案,让公司在购买现成安全产品的同时专注于人工智能开发。该解决方案将涵盖从构思、开发到部署的人工智能安全。这种解决方案至少应包括以下要素:

  1. **风险和流程:**基础培训、治理框架和专业安全测试应由有能力的公司和卓越中心作为专业服务提供。
  2. 数据卫生性和健壮性:过滤训练数据中的异常点,并向训练数据中注入敌对样本。
  3. 模型安全性:执行标准例程(提取、修剪)并集成高级控制,使模型更加健壮。将水印路径注入到模型中,以便能够在野外进行模型盗窃检测。
  4. 安全部署:通过在不可信和可信执行环境之间划分模型部署,保护模型免受物理盗窃[17]。在边缘运行时自动加密和解密模型。
  5. 威胁防范&检测:在操作过程中(“现场”)过滤和预处理输入,以阻止攻击企图。监控使用情况以检测敌对攻击企图和/或模型提取企图。

作者图片

将上述控制集成到 AI 开发周期中对于任何客户来说都应该是容易和可访问的,从而将开发团队从开发内部能力和自制 AI 安全工具的需要中解放出来。它应该是每个公司都使用的标准解决方案,就像所有公司都在其系统中使用 TLS 并安装现成的防火墙一样。此外,还可以提供人工智能安全专业服务:例如,专注于人工智能的红队、风险评估和监控 SOC。

我们应该问自己的唯一问题是,是否有足够强大的商业案例来开发上述解决方案并将其作为产品进行营销。我认为这不是一个“如果会有商业案例”的问题,而是一个“什么时候的问题。至少有 4 种力量在发挥作用,使未来 5 年成为人工智能安全领域创新的有利可图的时间(没有特定的顺序):

  • 人工智能在商业决策过程中的流行[18]
  • 规程
  • 信息物理系统开始利用人工智能[19]
  • 人工智能操作成为一件事(简而言之:在人工智能世界里有一个类似 DevOps 的运动)[20]

但是对于投机者来说,未来 5 年内什么时候是个问题。既然我们在谈论安全性,那么有理由假设大玩家(即方)会照顾好自己,少数早期采用者会从外部寻找解决方案,而市场的大多数人只会等待大黑客的消息。让我们看看结果如何。

总结

作为一名在保护 CPS 方面拥有专业知识的网络安全专家,我亲眼目睹了安全创新如何通常跟随风险而不是先于风险。对于一家开发人工智能的公司来说,正常的轨迹是首先投资让它工作,然后优化它,然后才保护它。然而,由于我们处于 2020 年,考虑到这项技术的颠覆性,我们不能等待人工智能安全的投资。监管机构非常(也是可以理解的)关注可解释性— 但是人工智能信任,即我们信任人工智能做出决策的能力,需要同样多的投资来应对这项技术带来的新攻击。

今天有很多事情可以做,甚至使用开源工具来保护你的人工智能系统。下一步自然是行业开发人工智能安全产品。虽然我不能 100%肯定会有一家领先的人工智能安全产品公司,但我非常确信我们会在该领域看到专家顾问和专业服务的利基。如果你觉得这个话题有趣,现在可以是发展你的人工智能安全技能的好时机。

我希望这篇短文提供一些思考的食粮,也许是管理你自己的 AI 安全风险的起点。

如果你想参与讨论,请评论,分享,随时联系我:【harpakguy@gmail.com】T4

谢谢:)

免责声明:我的观点仅代表我个人,与我工作的任何公司或个人无关。

参考资料:

[1]- Roman V. Yampolskiy,人工智能安全和网络安全:人工智能失败的时间线(2016 年), Arxiv

[2]- 亚历山大·波利亚科夫,AI 安全与对抗机器学习 101 (2019),中

[3]-阿西洛马尔原则(2017),https://futureoflife.org/ai-principles/?cn-reloaded=1

[4]- 参议院第 327 号法案

[5]-维基百科:人工智能条例

[6]- 可信人工智能(AI)的伦理准则

[7]-加州大学伯克利分校 CLTC 分校,走向人工智能安全:全球对更具弹性的未来的渴望, CLTC

[8]--斯托伊察、扬和宋、道恩和波帕、拉卢卡·阿达和帕特森、大卫·A .和马奥尼、迈克尔·w .和卡茨、兰迪·h .和约瑟夫、安东尼·d .和乔丹、迈克尔和赫勒斯坦、约瑟夫·m .和冈萨雷斯、约瑟夫和戈德堡、肯和古德西、阿里和卡勒、大卫·e .和阿贝耳、彼得、伯克利的人工智能系统挑战观点(2017),链接

[9]-于,杨,张,蔡永元,何永元,金永元,“云漏洞:通过对抗实例窃取大规模深度学习模型”,《网络与分布式系统安全研讨会论文集》,(NDSS),2020

[10]- Ariel Herbert-Voss,对抗对抗性机器学习的实际防御(2020), Blackhat 2020

[11]-华为,AI 安全白皮书(2018 年 10 月 01 日),华为

[12]-玛丽亚-伊琳娜·尼古拉、马蒂厄·辛恩、明·恩哥克·特兰、比特·布瑟尔、安布里什·拉瓦特、马丁·威斯特巴、瓦伦蒂娜·赞泰德斯基、娜塔莉·巴拉卡尔多、布赖恩特·陈、海科·路德维希、伊恩·m·莫洛伊、本·爱德华兹,对抗性鲁棒性工具箱 v1.0.0 (2018), Arxiv

[13]-米卡·尤蒂,塞巴斯蒂安·西勒,萨缪尔·马沙尔,n .阿索坎,普拉达:防范 DNN 模特窃取攻击(2019), Arxiv

[14]- Nicolas Papernot,Patrick McDaniel,Wu,Somesh Jha,Ananthram Swami,蒸馏作为对抗深度神经网络的对抗性扰动的防御(2016), Arxiv

[15]——石祥·古,卢卡·里加齐奥,面向对抗示例的深度神经网络架构(2015), Arxiv

[16]- Nicolas Papernot,Patrick McDaniel,Arunesh Sinha,Michael Wellman,SoK:走向机器学习中的安全和隐私科学(2016), Arxiv

[17]- GlobalPlatform,TEE 系统架构 v1.2,https://global platform . org/specs-library/TEE-System-Architecture-v1-2/

[18]-约瑟芬·沃尔夫(Josephine Wolff),如何为人工智能提高网络安全(2020),布鲁金斯学会

[19]-https://www . the guardian . com/science/2019/mar/29/uk-us-Russia-opposing-killer-robot-ban-un-ai

[20]-比如:【https://research.aimultiple.com/ai-platform/】T4

入侵数据科学管道

原文:https://towardsdatascience.com/hacking-the-data-science-pipeline-18303e2c4307?source=collection_archive---------66-----------------------

特征工程系列

功能改进—以#02.01 为例

昆腾·德格拉夫在 Unsplash 上的照片

这篇博文的目的

这是特征工程系列的第 02.01 课。在 Take#01 中,我们专注于获得与 EDA 相结合的基线模型以及对数据的理解。我们能够为 ML 基线模型获得 0.59035 的 AUC -ROC。

因此,要击败的 AUC -ROC 是 0.59035!

让我们继续“特性改进”的项目演练,这是特性工程管道的第二个也是最重要的组成部分之一。

面临的挑战是创建一个模型,使用重症监护最初 24 小时的数据预测患者的存活率(标签:“hospital _ death”)。麻省理工学院的 GOSSIS community initiative 拥有哈佛隐私实验室的隐私认证,提供了超过 130,000 名医院重症监护病房(ICU)患者的数据集,时间跨度为一年。【来源】。关于挑战的详细描述可以在这里找到

说够了,让我们开始吧!

照片由 Mael BALLAND 在 Unsplash 上拍摄

定义路线图…..🚵

深入调查潜在的数据问题,如下所示:

里程碑# 1:确定明确的缺失值

里程碑# 2:注意隐式/ 隐藏的缺失值&不正确的数据值

最后是结束语。

里程碑# 1:识别明确缺失的值

所以在我们之前的迭代中,我们已经看到了缺失值的分布。这是一个简单的简写,因为我们能够识别编码为*nan 的缺失值。*就这么简单!

里程碑# 2:注意隐式/ 伪装的缺失值&不正确的数据值

事实上,您也应该始终在数据集中寻找“伪装的”缺失值,以确保缺失值被正确编码为缺失值,更准确地说是 NaN。缺失值的几种伪装形式描述如下:

  1. 范畴变量:名词性/序数串 —空串/“未知数”/?”表示缺少的值

很公平。

问题是,要识别隐藏的缺失值和潜在的损坏/不正确的数据,您几乎总是依赖于与您试图解决的问题的领域专家合作。在我们的例子中,领域专家是医疗从业者,但是由于它是一个 Kaggle 数据集,与领域专家合作的可能性是不存在的。但还是要注意一点!

幸运的是,我们得到了数据文档,它本身并不详细,也没有指出数据问题,但是快速 EDA 和浏览文档向我揭示了许多关于隐藏的缺失值和可能不正确的数据的见解,这正是我接下来几分钟要关注的内容。

文档看起来是这样的:

很明显,我们对每个属性 都有一个 【类别】。下面的图表总结了上述类别分布的信息:

上面清楚地显示了什么特定的数据类型属于什么特定的类别。考虑到生命体征、实验室和实验室血气主要由数字变量组成,让我们首先关注它们。

探究这些变量是否由零值组成揭示了:

此外,通过对属于这三个类别的变量的描述,可以发现它们与人体内特定化学物质的存在有关,如果一个人活着,那么“0”表示有效值本身是没有意义的。这可以通过浏览这些变量的描述,由领域知识(如文档中提供的)进一步验证。例如,对于属于生命体征类别的变量:

提供的数据符合患者之前的 24 小时,记录的值与患者死亡时间不完全一致。这引出了两个主要观点:

  1. 如果值为“0 ”,则患者不可能活着
  2. 反之亦然可能不是真的。例如,有可能患者已经死亡,但是的“一些更低的”值可能存在。但是,这是一个假设,我们需要更多的 ed a 来验证这一点,如下所示:**

上述趋势分叉为医院死亡1 和医院死亡0,表明在“医院死亡”1 的情况下有总体下降趋势。所以这确实支持了我们的第二个假设,即如果
医院 _ 死亡
1,一般会发现下降趋势。

接下来,对于我们的第一个假设,我们需要进一步放大精确“0”的值,我们可能会寻找“0”与检测为异常值的值的交集。这可以进一步验证我们的概念,即这些“0”实际上是丢失的值。

异常值分布

让我们来看看这些变量的异常值的一般分布

“0”在生命体征变量中的分布显示,D1 _ heart rate _ min&D1 _ resprate _ min具有大部分 0 值,而D1 _ spo 2 _ min*&h1 _ resprate _ min具有相对较少的“0”。让我们绘制异常值分布。*****

哇!因此,该图确实显示,对于具有相对较高数量的“0”的变量,作为异常值的“0”的数量也较高!我们可以通过明确检查所有这些“0”是否也是每个变量的总异常值集的一部分来进一步验证我们的想法,即“0”是缺失值。

将离群值的 0 分布与原始数据集中的 0 分布进行匹配:

**“0”和“1”列对应的是 hospital_death0 和 hospital_death1。原始数据集中的所有“0”都在异常值中找到并完全匹配!

所以到目前为止,我们已经收集了足够的证据来支持我们的论点,即对于生命体征类别的上述变量,0 的 最有可能是缺失值

我们不是 100%确定托梁的概念,但同时,我们也不是绝对的盲点!

我想在这里提一下,这又是一个强调与领域专家合作的问题,如果这个问题是在现场处理的话,我们将有机会进一步验证我们的发现!

现在,通过将这些“0”编码为适当缺失的值【nans】*,反映数据分布的变化总是一个好主意。*****

“平均值”的变化百分比

不出所料,由于 D1 _ heart rate _ min&D1 _ resp rate _ min的“0”数最多,因此它们被更改的次数最多。

最后结束语……

  1. 作为一名精明的数据科学家,您不断地与领域专家互动和协作!你将会向他们透露一些发现,另一方面,领域专家将会为你设定一个方向。它总是一个联合的努力。
  2. 然而, 您必须始终亲自检查数据完整性 ,千万不要拘泥于您刚刚听到的 (就当它是潜在的进展) 因为在大多数情况下,公司本身也没有意识到潜在的数据问题,就像我们上面遇到的那些问题一样。

即将发布的帖子将包括:

在这篇博文中,我们仅限于对生命体征变量的详细分析。在下一篇博文中,我们将转向其他类型的变量,并继续识别和修复其他数据问题。这很费时间,但最终,结果将是值得的!

敬请期待!📻

如果您有任何想法、意见或问题,欢迎在下面评论或联系📞跟我上 LinkedIn

照片由马特·卡农在 Unsplash 上拍摄

入侵数据科学管道!

原文:https://towardsdatascience.com/hacking-the-data-science-pipeline-b1121996f4b5?source=collection_archive---------48-----------------------

特征工程系列

理解数据—参加#01

昆腾·德格拉夫在 Unsplash 上的照片

我们有 最先进的先进算法 来生成完全迷人的可视化效果,揭示数十亿美元的消费者购买模式,并利用大数据结合令人瞠目结舌的可扩展分析引擎来分析收入流。但是作为一名数据科学家,这一切都归结为一个切入点,特别是当步入行业时— “我从哪里开始一个数据科学项目!!!"

这篇博文的目的

揭开完整的数据科学项目管道……

有大量的在线课程提供了训练通用机器机器学习模型的完整路径,从基本的机器学习算法到高度复杂的深度神经网络和强化学习。但是,从原始、混乱和不完整的真实世界数据集中破解建模特征的数据科学管道是最不可或缺的难题之一,没有它,为真实世界训练尖端机器学习模型的梦想仍然无法实现!

照片由 Rodion Kutsaev 在 Unsplash 上拍摄

目标受众是谁?

您应该在以下领域拥有扎实的专业知识:

  1. 机器学习术语
  2. 充分理解和深入实践基本的 ML 算法

如果您的工具包中有上述内容,并且您正在进一步寻找实践经验来展开从数据获取到构建特性集的特性工程过程,以提高您的 ML 模型的性能增益,那么这篇博客正是为您准备的!

本教程的结果

我们将通过最近在 WiDS Datathon 2020 举行的黑客马拉松的真实世界数据集的亲身体验,走过特征工程管道的早期阶段。

选择该数据集的原因如下:

  1. 这不是练习 ML 算法的玩具数据集。事实上,这是一个真实世界的数据集,它需要有效的特征工程过程来训练一个良好性能的 ML 模型。
  2. 有大量丢失的行和大量的数据问题,您在日常的数据科学项目中同样会遇到这些问题。
  3. 完成工作后,您将开始欣赏特征工程的价值,以及为什么值得花时间玩数据集!

4.挑战在于创建一个模型,使用从最初 24 小时的重症监护到 的数据来预测患者的存活率(标签:“医院 _ 死亡”) 。麻省理工学院的 GOSSIS community initiative 拥有哈佛隐私实验室的隐私认证,提供了超过 130,000 名医院重症监护病房(ICU)患者的数据集,时间跨度为一年。 [ 来源 ]

5.关于挑战的详细描述可以在这里找到

如何跟进这个 BlogPost 项目演练?

我建议阅读并理解一般的思维过程,然后 在你自己选择的真实世界数据集上调整这里定义的思维过程

说够了,让我们开始吧!

由梅尔·巴兰德在 Unsplash 上拍摄的照片

定义路线图…..🚵

里程碑# 1:特色工程&其不可或缺的价值!

然后:完成特征工程过程前期的项目走查

里程碑# 2:功能理解

里程碑# 3:功能改进

里程碑# 4:培训基线模型

最后是结束语。

特色工程&其不可或缺的价值!

什么是特征工程? 从原始数据中挖掘/建模/提取 特征的过程

特征工程的目标? 要素是嵌入基础数据模式的数据集属性,因此从原始数据属性中提取/建模要素意味着模型的高性能增益!

数据科学项目趣闻:通常情况下,数据科学家将项目时间的 80%花在功能工程上,只有 20%花在训练前沿模型上。事实上,特征工程是任何数据科学项目中最有价值但最不被重视的部分。有效的特征工程付出了艰苦的努力,一旦你开始钻研真实世界的数据集,你将很快开始意识到它有价值的重要性!

事实上,这里有一个很好的解释来理解特征工程的重要性

来源:https://whatshebigdata . com/2016/05/01/data-scientists-spend-the-most-time-cleaning-data/

特征工程过程早期阶段的项目走查

里程碑# 2:特性理解

特性理解侧重于 “理解您的数据” 我的意思是按照以下路线图仔细检查您的数据集(这不是每个数据科学项目的硬编码路线图!) :

你可以在这里找到完整的项目代码

1。检查您的数据是结构化的还是非结构化的。对于这篇博文,我们将只处理结构化数据。

2。签出数据集的行和列。

3。计算描述性统计数据

4。确定给定数据集中的数据类型,并确定每个属性位于四个数据级别中的哪个级别
将数据类型映射到分类和数值数据类型。此外,在数字数据类型的分类、区间和比率级别中寻找序数和名词。这将为你的 EDA 提供基础!你会在 Github Repo Jupyter 笔记本中找到更全面的 EDA(为了这篇博文,让它简短一点)。此外,EDA 将贯穿任何数据科学项目的迭代,如本文后面所述。

里程碑# 3:功能改进

数据清理

功能改进处理数据清理,只有在理解数据的基础上,您才能以合理的方式进一步清理数据集。

更准确地说,数据清理处理:

根据数据类型和识别缺失值,然后定义处理它们的策略。例如,字符串数据类型可以编码为空字符串作为缺失数据,而数字数据可以编码为 NaN 或简单的“0”来表示缺失值。此外,如果通过删除丢失的行,您只剩下一半的数据集或者大量的行被删除,则删除丢失的值不是明智之举。另一方面,缺失值的插补取决于哪种特定的插补策略能够最好地填补缺失值。

缺失值的一些插补方法有:

  1. 通过均值、中值或众数替换缺失值。这同样取决于你对数据的理解。例如,对于名义数据类型,只有模式可能是填充缺失值的快速策略。但是对于序数和更高层次的数据属性,均值和中值也可能是值得探索的可行候选者。
  2. 对于具有大量缺失值的属性,通过另一个训练好的模型来输入缺失值也可以是手边的策略之一。

在没有识别缺失值的情况下继续进行数据科学项目,会立即破坏您的结果,尤其是当您将使用聚合函数(更准确地说,是我们一直最喜欢的均值和计数)时,除此之外还有很多情况。趋势将完全相反,最后,你将回溯不正确的平均值,通过考虑“0”作为一个合法的变量值,而不是一个丢失的值。字符串值也是如此!空字符串值仍然会出现在计数函数中。为了避免这种情况,您应该将数字缺失值编码为适当的“NaN”和字符串,以表示其他一些缺失的标识符。

带走:要识别缺失值,首先要确保它们被正确编码为缺失值!然后,是丢弃缺失值还是对其进行插补,以及进一步选择插补标准,都取决于您手中的数据问题类型,以及在硬件资源和时间方面遇到的项目限制。

足够的理论——映射到我们上面的问题陈述

让我们针对数据集中的每一列检查缺失值的分布

该图清楚地显示了缺失值百分比从 0%到 90%的变化分布。哇!对于这个项目,这似乎是最大的数据问题之一,如果解决得当,也是最有回报的事情。

此外,dataset distributors 已经提供了一个完整的数据字典,需要对其进行详细的研究,以探索数据的进一步维度,最重要的是,缺失值是否可以用除 0 和空字符串之外的其他方式进行编码!

即使没有提供文档,我们仍然需要更深入地挖掘属性,以获得关于缺失值的见解。比如“身高”“bmi”等属性永远不能为零!如果对于这样的属性,存在零,这意味着我们的数据中缺少值!

让我们检查在我们的数据集中有多少行至少有 1 个缺失值

**整个 91688 数据集中只有 25 行有完整的值!**因此,放弃它们显然不是明智之举。似乎几乎每隔一行都有缺失值。让我们更深入地了解哪些列具有完整的行值。

因为我们不能删除缺少值的行,所以暂时让我们关注上面的列,因为我们的目标是训练一个基线模型。另外,还要注意有 4 个 id 列与预测没有关联,因此我们将删除它们。这样,在总共 185 个属性中,我们只剩下 6 个子集列(不包括标签列)。

里程碑# 3:培训基准模型

探索特征子集

在这一点上,我们有 6 个特征的子集,没有很多缺失值。该功能集由以下数据属性组成:

**1\. elective_surgery
2\. icu_stay_type 
3\. icu_type
4\. pre_icu_los_days
5\. readmission_status
6\. apache_post_operative**

标签/预测变量

**hospital_death**

数据类型分布的 EDA

  1. 由数据分配器(即 WiDS)分配数据类型字典中提供的数据类型

2。当raw csv 文件中读取时分配数据类型

上面一个简单的 EDA 表明,相当多的二进制/布尔数据类型在被读取的文件中以 【数字】 数据类型结束。作为一名精明的数据科学家,对这些微小的细节保持警惕非常重要!

让我结合一个真实的生活场景。将二进制/布尔变量编码为数字似乎没有什么坏处,但是这会在内存中增加二进制/布尔变量,与浮点对象相比占用更少的字节!如果你的内存已经不足,那么这些被转换成浮点数的小的布尔字节将会聚集起来成为大字节,耗尽你的内存!再次强调——尽可能多地理解你的数据!

阅读数据附带的文档资源总是值得的。他们会让你对数据有敏锐的理解。例如,通过我阅读的文档,我可以相对容易地通过文档来确保提供的数据类型和编码的数据类型是相同的类型。

此外,对于数字列,您可以通过文档解码,将丢失的值编码为“0”。在年龄、身高和 bmi 等变量中解码“0”很容易(因为我们已经有了领域知识),但当我们自己的领域知识匮乏时,文档开辟了新的探索方式。

例如,在给定的数据集中可能有几个其他属性可能有大量的缺失值,对于我这样一个没有医学背景的人来说,文档和与领域专家的合作讨论将提供更深层次的数据理解。

事实上,与领域专家的密切合作也是精明的数据科学家从不同的看不见的维度分析数据从而提高性能的不可或缺的实践之一!

继续 EDA..
注意:下图对应于完全没有缺失值的数据类型/列,即左侧列出的列

3。删除缺失值并选择 6 个特征的子集后,文件读取数据类型的数据类型分布显示

4。进一步挖掘上面的可视化——将文件读取数据类型进一步映射到 dict 提供的数据类型后的数据类型分布

将 8 个整型变量中的 4 个分解为布尔数据类型。

现在,我们已经固定了所有的固定数据类型,删除了 11 列中基于 ID 的列,剩下 7 列(包括标签列)。除了pre _ ICU _ los _ days之外,所有属性本质上都是范畴属性。

默认情况下,pd。DataFrame.describe()仅显示连续/数字变量的统计信息。还有,

2。删除重复项!

我们还需要根据特性集的 6 列来检查原始数据集中和所选数据集中的重复项。

所以我们**最初有 91713 行,其中针对所选 6 个特性的唯一行仅构成 19438 行!**我想在这里强调两点非常重要:

  1. 始终确保输入到模型中的数据集包含唯一的行!否则,你会毫无理由地增加计算时间,在现实世界中,时间已经是满足项目期限的紧迫资源。这也可能会降低性能。
  2. 如果您注意到,6 个所选要素的总行数为 91713,即等于数据集本身的行数。但是,删除所选 6 个特性的重复项只会显示 19438 行!现在想象一下,如果我错过了这个复制步骤,并继续训练一个以“k”为重要超参数的 KNN 模型,这将会产生怎样的破坏性影响!该模型不仅计算时间长,而且从性能角度来看也很糟糕!
  3. 在基于特征集删除重复项时,我保留了 drop_duplicated keep 参数“False”而不是“first”

保持=假的原因?

使用 keep=first 会引入噪声!为什么?因为考虑到基于 6 个要素的数据框,相同的行可能会有不同的标注。所以我选择删除所有这些误导性的行(它们实际上并不误导,但基于 6 个特征,是的,它们是误导的)。如果您在这 6 个特性和标签的整个数据帧上调用 unique,您将得到 91713 行,但是如果我们打算只基于 6 列提供特性集,这是完全错误的(目前基线模型就是这种情况)

再次强调,这些看似微小的点将会对你的模型产生巨大的影响——小心!

另请注意,我们目前只从大约 20%的数据集学习基线模型!是的,我们很适合基线模型,但同时,这也揭示了:

  1. 模型性能显然会很低,除非假设我们幸运地选择了仅包含特征(有价值的属性)的 6 个属性的子集!

关于以上这一点,在以后的迭代中,我们一点也没有盲点。通过属性/列与标签的相关性,可以洞察上述内容的有效性,并检查 6 个属性中是否包含相关性较高的重要列。此外,如果仅考虑 6 个属性的子集,标签的分布有显著变化,则数据的形状一定发生了变化,因此这也将导致低性能(更准确地说是数据不平衡)。

当我们添加更多的列和更多的行(唯一的行)时,在以后的迭代中还有改进的空间。

相关矩阵

#悟性—另一种见解!列 readmission_status 没有出现在相关矩阵中! 深挖其独特价值可见一斑:

对于所选的列和行的子集,它都是假的!因此,我们也将删除该列,因为它在提取模式或生成预测方面不起任何作用!

#savvy —简单的 EDA 和如此有价值的洞察力。再次一分钟的观察,但完全值得!

训练基线模型

到目前为止,我们已经有了 5 列,我们可以开始训练基线模型了。请注意,我们有两个分类“字符串”变量/属性,在将数据输入训练模型之前,我们需要一些数值转换。为此,我们将在数据预处理管道中使用哑编码。

我们将使用 KNN 作为分类器。数据集的拆分、分类变量的虚拟化、缩放(Z 分数标准化)和“k”的网格搜索都已添加到数据预处理管道中(更准确地说是 sklearn 的管道组件)。

fit&通过管道转换数据,调用 fit 显示:

  1. 训练行数:14578
  2. 训练列数:12(列数从 5 增加到 12,因为在转换过程中为每个分类变量添加了(n-1)列,即哑编码),其中 n 对应于每个分类字符串变量的唯一值的总数。另外,布尔分类变量没有经过任何虚拟编码或标准缩放的转换。
  3. 到目前为止,最佳 k 值为 99,与以下候选值进行了交叉验证

测试基线模型

  1. 测试行:4860
  2. 测试列:12
  3. ROC_AUC : 0.72 —(考虑到只使用了 20%的只有 5 列的数据集,这一点也不差)

Kaggle 预测

太好了!让我们预测 kaggle 测试集

值得一提的一点

值得检查的是测试集的许多值实际上是如何存在的以及考虑到我们现在拥有的 5 列的特征子集,测试集有多少唯一值存在

#悟性—洞察力!因此,考虑到测试集只有 5 列,我们实际上预测的是 39308 行中的9768 行,这只是 24% !此时我们认为大多数测试集行是相同的,但事实并非如此,但这也意味着模型性能(以及 Kaggle 提交)有很大的潜在增益空间。

Kaggle 评分

得分率为 0.59035!这比排行榜上表现最差的型号要好😅

这是基线模型的简要概述

项目演练流程图

最后,这是我们到目前为止完成的整个过程的流程图

总结注释…

培训基线模型的重要性

到目前为止,我们有一个很好的基线模型。基线模型作为性能增益的基准。我们继续将组件添加到我们的功能工程管道中,并将新获得的性能与基线模型中添加的每个组件进行比较,以评估我们在性能增益方面的进展。

毫无疑问——良好的软件工程实践是不可或缺的!!!

虽然,我没有在这篇博文中包含代码片段,但是你可以在我的 Github Repo 中找到完整的项目代码。对于真实世界的数据科学项目,我们严格遵循 OOP 原则和管道方法。向管道方法添加新组件相当容易。随着更多东西的出现,你的代码将更容易重用、维护、调试并变得可扩展。这也意味着在后面的迭代中,您将有更多的时间花在问题本身上。

如果你不信任我,拿任何 python 数据科学框架的源代码,你就能分析所有投入工作的软件工程原理!

数据科学项目之美!

尽管任何数据科学项目都有标准的特征工程流程,但是每个数据集都有无限的创造力!你越深入研究特征工程,你就越被迫跳出框框思考,用你的数据分析问题,探索可能的解决方案,不仅是特征工程,也是 ML,并继续提升你的数据科学专业知识,乐趣永无止境!

即将发布的帖子将包括:

  • 为特征工程管道 的下一阶段继续相同的 项目走查。
  • AUC_ROC 为 0.59035

敬请期待!📻

如果您有任何想法、意见或问题,欢迎在下面评论或联系📞与我一起上 LinkedIn

照片由马特·卡农在 Unsplash 拍摄

用 OpenBCI,Node.js 和 PsychoPy 来黑你的大脑

原文:https://towardsdatascience.com/hacking-your-brain-with-openbci-and-psychopy-3c59b98e88ef?source=collection_archive---------28-----------------------

我如何使用 Python、Node.js 和 OpenBCI 硬件来准确读取我的大脑信号

如最初出现在我的 个人博客

我热爱编码,也研究大脑——为什么不同时解决这两个问题呢?在这篇文章中,我将向你展示如何利用代码和来自 OpenBCI 的令人惊叹的低成本硬件来操控你的大脑信号,从而破解你的大脑。我在 2014 年开始了我的神经科学之旅。从那以后,我一直想用现有的脑电图来探索大脑。这应该是每个认知神经科学学生和研究人员的必修实验室,因为它代表了探索许多神经科学问题的机会。反正最近才买了 OpenBCI 芯片一直用到现在。在这篇博文中,我将报告我的第一次探索,这对于我未来关于#brain_hacking 之旅的帖子至关重要。

但是 BCI 怎么了?

这是一个合理的问题——我们为什么要关心与大脑的交流呢?有很多原因,我在这里将提到几个申请 BCI 希望他们会说服你。我想到的第一个应用是将 BCI 用于辅助和修复目的。具体来说,像耳蜗和视网膜植入物、假肢和深度大脑刺激技术这样的 BCI 工具正在帮助全世界数百万人。

恢复已经丧失的大脑功能是 BCI 技术背后最重要的动机之一。然而,还有许多其他的应用让大多数人兴奋,例如通过神经反馈增强大脑功能,使用思维的力量(独自)控制你最喜欢的设备或玩视频游戏,以及许多其他应用(如果你想查看可能应用的更广泛覆盖范围,请查看维基百科上令人惊叹的脑机接口条目)。

P300

P300 是一种非常显著的神经活动,发生在看到受试者关心的东西的第一秒钟。它被用于许多创新的方式,如测谎和打字(仅用你的思想),使它成为一种可行的工具,用于使瘫痪的病人能够用他们的思想交流。

试验设计

实验设计:使用两幅不同空间频率的图像作为刺激。它们被呈现 0.5 秒,然后是 3 秒的试验间间隔。仅背景的第三条件(未示出)被用作控制条件。每个条件被呈现 50 次。

我的实验设计非常简单。它们都包括随机展示不同的图像,同时记录枕部和颞区的脑电波。在这篇文章中,我使用了由多个以不同空间频率(或多或少的条)排列的黑条组成的光栅图像(见图)。这些图像在视觉研究中非常流行,原因超出了本文的范围。每个图像重复 50 次,产生 150 个图像呈现(空间频率为 3、12,没有图像)。每幅图像呈现半秒钟,随后是 3 秒钟的试验间隔(ITI ),其间呈现一个“+”符号。

结果

老实说,直到我看到这张图片,我才知道 P300 (该图片仅来自第一个通道,但在所有通道中都观察到了确切的模式)。这种积极的变化出现在我使用各种刺激类型进行的每个实验中(我将在以后的文章中探讨其中的一些)。请注意,控制条件没有显示任何偏转,而两个实验条件(显示实际图像)都显示了该模式。我没有预料到的是,第二个正斜坡仅在 400ms 左右出现在橙色部分(高频条),而不是蓝色部分。这使得机器学习算法区分这两者变得容易得多。事实上,一个非常简单的逻辑回归分类器在区分这三个类别时达到了约 52%的准确率(在交叉验证设置中)。

在 3 个不同图像期间的神经反应:蓝线是当看到具有 3 个条的光栅图像时神经反应的平均值,橙线是相同的,但是当看到具有 12 个条的光栅图像时,绿线是没有图像显示的控制条件。阴影区域是标准误差。请注意,当看到图像时有两个斜坡,而当看不到图像时没有斜坡。

在这里,我展示了低成本的硬件(获得所有设备需要 322 美元)可以让你获得非常高质量的脑电图信号。事实上,OpenBCI 保存了一份在数据收集中使用 OpenBCI 的科学出版物的运行列表。我计划进行进一步的实验,并在这个博客中分享他们的结果。

最后,我要感谢 OpenBCI 团队和社区做出的巨大努力,让神经科学和 BCI 的硬件和软件工具更容易为公众所用,还要感谢 Neurotech@Berkeley 团队提供的令人惊叹的课程和软件,我曾用它们来做实验。

查看我的 Github 库,获取本文使用的代码

关于技术设置的更多细节:我使用了从 OpenBCI 提供 4 个通道的神经节设备。这些通道附着于(大约)O1、O2、T1 和 T2(覆盖枕叶和颞区的两侧)。我使用 Node.js 连接芯片,并在 python 脚本中处理数据(通过实验室流层),该脚本还将记录存储在文本文件中。所有这些工具都改编自神经技术课程实验室。伴随着录音,我还使用了心理来设计和运行实验。

Hadoop 分布式文件系统

原文:https://towardsdatascience.com/hadoop-distributed-file-system-b09946738555?source=collection_archive---------25-----------------------

理解 HDFS 及其内部运作的综合指南

从计算的角度来看,基本上有两种类型的扩展—垂直和水平。在垂直扩展中,我们只是向单台计算机/机器(也称为“节点”)添加更多 RAM 和存储。在水平扩展中,我们添加更多通过公共网络连接的节点,从而增加系统的整体容量。记住这一点,让我们开始吧。

块大小

文件分割成块

当一个文件被保存在 HDFS 时,文件被分割成更小的块,如上面的 GIF 图所示。块的数量取决于“块大小”。默认是 128 MB ,但是可以很容易地更改/配置。

在我们的示例中,一个 500 MB 的文件需要分成 128 MB 的块。 *500/128 = 3 块 128 MB 和 1 块 116 MB。*剩余的 12 MB 块空间被返回到名称节点,用于其他地方,从而防止任何浪费。任何文件系统都是如此,例如,Windows NTFS 的块大小在 4 KB 和 64 KB 之间,具体取决于文件大小(最大为 256 TB)。考虑到 Pb 及以上的大数据处理,KBs 会非常低效,可想而知。这就是 HDFS 块大小为 128 MB 的原因。

复制因子

分身术

HDFS 是一个容错和弹性系统,这意味着它可以防止一个节点的故障影响整个系统的健康,并允许从故障中恢复。为了实现这一点,存储在 HDFS 中的数据会跨不同的节点自动复制。

复印了多少份?这个要看“复制因子”了。默认设置为 3,即 1 份原件和 2 份复印件。这也很容易配置。

在左侧的 GIF 中,我们看到一个文件被分成多个块,每个块都在其他数据节点上复制以实现冗余。

存储和复制架构

存储和复制架构

Hadoop 分布式文件系统(HDFS)遵循主从架构,其中“名称节点”为主节点,“数据节点”为从/工作节点。这仅仅意味着名称节点监视数据节点的健康和活动。数据节点是文件以块的形式实际存储的地方。

让我们继续上图中大小为 500 MB 的文件的相同示例。HDFS 的默认块大小为 128 MB,该文件分为 4 个块 B1-B4。请注意,A-E 是我们的数据节点。HDFS 的默认复制因子为 3,数据块在我们的 5 节点集群中复制。数据块 B1(黄色)在节点 A、B 和 D 之间复制,依此类推(遵循彩色线条)。
在这里,名称节点维护元数据,即关于数据的数据。哪个文件的哪个块的哪个副本存储在哪个节点维护在 NN 中—文件 xyz.csv 的块 B1 的副本 2 存储在节点 b 中。

因此,一个大小为 500 MB 的文件由于其复制,在 HDFS 需要 1500 MB 的总存储容量。这是从终端用户的角度抽象出来的,用户只能看到存储在 HDFS 的一个大小为 500 MB 的文件。

现在是动手的好时机:

[## HDFS 命令

常见的 HDFS 命令

medium.com](https://medium.com/@prathamesh.nimkar/hdfs-commands-79dccfd721d7)

块复制算法

块复制算法

该算法首先在 HDFS 的默认配置文件夹下搜索 topology.map 文件。这个。映射文件包含有关其包含的所有可用机架和节点的元数据信息。在上图的示例中,我们有 2 个机架和 10 个数据节点。

一旦文件被划分为数据块,第一个数据块的第一个拷贝就被插入到离客户端(即终端用户)最近的机架和数据节点中。创建第一个数据块的副本,并通过 TCP/IP 将其移动到下一个可用机架(即机架 2)上,并存储在任何可用的数据节点中。在这里创建另一个拷贝,并通过 TCP/IP 等将其移动到下一个可用的机架上。但是,由于我们只有 2 个机架,该算法会在同一机架(即机架 2)上查找下一个可用的数据节点,并将第三个副本存储在那里。这种冗余性的存在使得即使一个机架出现故障,我们仍然有第二个机架来检索数据,从而实现容错和弹性。

高可用性架构

在 Hadoop 1.x 中,生态系统仅附带 1 个名称节点,导致单点故障。有一个辅助或备份名称节点,需要一个多小时的手动干预才能启动。随后,任何数据丢失都是不可恢复的。

在 Hadoop 2.x 中,提供了高可用性作为标准模式的替代方案。在标准模式下,您仍然有一个主要和次要的名称节点。在高可用性模式下,您有一个主动和被动名称节点

数据节点向“活动”名称节点发送活动更新(至少每 5 秒一次—可配置)。此元数据实时同步到“袖手旁观”名称节点。因此,当“主动”服务器出现故障时,“袖手旁观”服务器拥有切换所需的所有元数据。

Zookeeper 通过其故障转移控制器,通过从每个 NN(每 5 秒,同样可配置)接收到的心跳或即时通知来监控活动和袖手旁观名称节点的健康状况。它还包含所有可用的袖手旁观名称节点的信息(Hadoop 3.x 允许多个袖手旁观名称节点)。

因此,建立了数据节点、名称节点和 zookeeper 之间的连接。当一个活动名称节点出现故障时,动物园管理员会选择一个合适的袖手旁观名称节点,并促进自动切换。袖手旁观成为新的活动名称节点,并向所有数据节点广播该选举。现在,数据节点会在几分钟内将其活动更新发送到新选出的活动名称节点。

什么是 NameNode 元数据?

NameNode 元数据

名称节点(NN)元数据由两个持久性文件组成,即 FsImage —名称空间和编辑日志—事务日志(插入、附加)

名称空间& FsImage

在每个文件系统中,都有一个到所需文件的路径— On Windows: C:\Users\username\learning\BigData\namenode.txt and on Unix: /usr/username/learning/BigData/namenode.txt. HDFS 遵循 Unix 的命名空间方式。此命名空间存储为 FsImage 的一部分。文件的每个细节,即谁、什么、何时等。也存储在 FsImage 快照中。为了一致性、持久性和安全性,FsImage 存储在磁盘上。

编辑日志

对所有文件的任何实时更改都会记录在“编辑日志”中。这些记录在内存(RAM)中,包含更改和相应文件/数据块的每个细节。

在 HDFS 启动时,从 FsImage 读取元数据,并将更改写入编辑日志。一旦在编辑日志中记录了当天的数据,它就会被刷新到 FsImage 中。这是两者协同工作的方式。

另外,FsImage 和编辑日志是不可读的。它们被二进制压缩(序列化)并存储在文件系统中。然而,出于调试目的,可以将其转换成 xml 格式,以便使用离线图像查看器读取。

NameNode 元数据如何同步?

正如您在“HDFS 高可用性架构”图像中所想象或看到的那样,名称节点元数据是一个单点故障,因此此元数据被复制以引入冗余并实现高可用性(HA)。

共享存储

共享存储同步

我们现在知道存在一个活动名称节点和一个备用名称节点。活动中的任何更改都会实时同步到共享文件夹/存储器,即网络文件系统(NFS)。此 NFS 可由备用服务器访问,备用服务器实时下载所有相关的增量信息,以保持命名节点之间的同步。因此,如果活动节点出现故障,备用节点名称节点已经拥有所有相关信息,可以在故障切换后继续“照常工作”。这不用于生产环境。

仲裁日志节点(QJN)

QJN 同步

“法定人数”是指促成一项活动所需的最低人数。这个词通常用于政治;这是众议院进行议事所需的最低代表人数。

这里,我们使用这个概念来确定建立多数和维护元数据同步所需的最小日志节点数(也称为仲裁数)。

该图显示了三个(总是奇数)日志节点(进程线程而不是物理节点),它们有助于建立元数据同步。当一个活跃的神经网络收到一个变化,它把它推到大多数 QJ 节点(遵循单一的颜色)。备用 NN 实时地向多数 QJ 节点请求建立同步所需的元数据。

QJN 起作用的最小数目是 3,法定人数/多数由以下公式确定:

**Q = (N+1)/2**
where N = total number of Journal Nodes 
For example, if we have N=5, the quorum/majority would be established by (5+1)/2 i.e. 3\. The metadata change would be written to 3 journal nodes.

QJN 是元数据同步的首选生产方法,因为它也是“高度可用的”。如果任何一个 QJ 节点出现故障,任何剩余的节点都可以提供维护元数据同步所需的数据。因此,备用服务器已经拥有了所有相关信息,可以在故障转移后继续“照常工作”。

这就把我们带到了我关于 HDFS 及其内部运作的综合指南的结尾。

参考资料:

[1] HDFS 架构 (2019),Apache Hadoop,ASF

[2] 管理 HDFS ,云时代

[## Google Cloud 上的 Cloudera 管理器

通过 GCP 上的 CM 6.3.1 逐步安装 Hadoop 生态系统

medium.com](https://medium.com/@prathamesh.nimkar/cloudera-manager-on-google-cloud-3da9b4d64d74) [## HDFS 擦除编码

通过利用擦除编码,显著降低 HDFS 集群的存储开销

towardsdatascience.com](/simplifying-hdfs-erasure-coding-9d9588975113) [## 使用 Hadoop 生态系统的大数据分析渠道

登录页面

medium.com](https://medium.com/@prathamesh.nimkar/big-data-analytics-using-the-hadoop-ecosystem-411d629084d3)

Hadoop &树莓派:我最后一年的项目

原文:https://towardsdatascience.com/hadoop-the-raspberry-pi-my-final-year-project-d50ad99de223?source=collection_archive---------8-----------------------

图片来自 Unsplash — 哈里森·布罗德本特的照片

我并不总是对网络安全感兴趣。事实上,在我攻读计算机科学(网络)学士学位期间,我不知何故决定 Hadoop 是未来,我的未来就是 Hadoop。2014 年,我刚刚在黑莓完成了一年的实习,我回到了赫特福德郡大学,更加专注,更加坚定,也更加明确地知道自己想做什么。(我是实习年的强烈拥护者,尤其是那些让你尝试不同技术流的公司)。因此,我选择死在运行 Hadoop 的 Raspberry Pi 集群是最后一年项目的一个好主意。

为什么

对我来说,学习新技能是计算机科学有趣的部分。因此,当我打算专攻网络学位时,我想展示我的范围,这样我就知道我的项目会有所不同。我花了 2015 年夏天的大部分时间研究不同的项目,因为我对微型计算机感兴趣,并将其融入日常生活,我知道我的项目必须在树莓 Pi 上运行。

我论文的封面

Hadoop 对我来说是一个相当新的概念,我对大数据很感兴趣,但可访问性是一个问题。没有人愿意让一年生接近他们的数据湖。所以我最初的想法是,我应该在 Raspberry Pi 集群上运行 Hadoop,唯一的目的是让 Wordcount 系统分析 tweets。由此产生了这个美妙的标题。

非结构化数据的安全组织和存储,用于单板微型计算机的态势感知和漏洞分析。

我的问题陈述以富有远见的陈述开始,我想为希望使用 Hadoop 的中小企业创建一个大数据解决方案,同时确保这是一个安全的选择。我的研究包括:

  • 调查中小型企业(SME)管理、存储和处理数据的现有解决方案。
  • [树莓 Pi 微电脑](http://www.raspberrypi.org Teach, Learn, and Make with Raspberry Pi – Raspberry Pi)及其他竞争对手分析。
  • 解决方案的漏洞评估和压力测试

第一章重点介绍了从大数据解决方案到 NoSQL 解决方案的所有术语,这些术语都使用了哈佛参考系统。

让我们复习一下,这些术语是什么:

Hadoop 徽标—归功于 Apache Hadoop

Apache Hadoop ,一个 Java 开发的框架,主要用于在行业标准的商用硬件集群上运行应用程序。Hadoop 是一种分布式架构,需要多台计算机来运行。Hadoop 非常灵活和模块化,因为它是基于开源框架构建的。Hadoop 可以被视为两个部分:数据存储功能(HDFS)和数据处理功能(MapReduce)。

(Hadoop 分布式文件系统) 是 Apache Hadoop 项目的主要组成部分。在 Hadoop 集群中,数据被分析并分解成可管理的小块(称为块),然后在整个集群中分配。这使得 map 和 reduce 函数可以在大型数据集的小子集上执行。然后,这些函数允许跨 Hadoop 集群对数据进行高性能访问。由于 HDFS 通常部署在低端硬件上,服务器故障非常常见。

那么这一切是如何联系在一起的呢?

这是我的功劳,斯蒂芬·查彭达玛的《HDFS 示意图》

MapReduce 是支持和允许 Hadoop 可伸缩功能的编程结构。MapReduce 基于 Java,受 Apache Hadoop 软件框架支持。虽然 MapReduce 是基于 Java 的,但是为了利用诸如“map”和“Reduce”之类的功能,可以使用任何编程语言。与 HDFS 类似,MapReduce 也有一个共同的特点,那就是它是容错的,并且可以在大规模分布中工作。MapReduce 通过将输入的数据分割成更小的可管理的块(任务)来工作,这些被称为地图任务。这些映射任务可以在并行进程中执行。处理后,地图任务输出将减少(减少任务)并保存到系统中。

因此,如果我们想利用 Hadoop,我们需要多个节点吗?

不,但那就违背了目的。所以我们倾向于运行 Hadoop 集群。

集群计算是指一组紧密连接在网络上的计算机节点,它们作为一个系统相互工作和支持。与网格计算不同,每个节点都被设置为执行相同的任务,并由软件运行和控制。Hadoop 是一个使用集群计算来实现其目标的软件示例。通常,所有节点都运行相同的软件,因为一个节点通常会在整个集群中克隆和复制。通过使用开源集群应用资源 (OSCAR),可以在集群中运行不同的操作系统。集群计算的一个例子是贝奥武夫集群。通常是商用级计算机联网成局域网,共享程序和库。这将产生一个*“来自廉价个人计算机硬件的高性能并行计算集群。”*集群计算的优势包括速度和容错能力。因为多个节点正在处理一个任务,所以如果一个节点出现故障,速度将保持不变,因为其他负载将承担重量,即使一个节点出现故障,其他节点仍在处理一个任务。集群计算增加了虚拟机的受欢迎程度,因为从 SMEs 的角度来看,由于不涉及实际的物理硬件,这意味着管理工作减少了。

让我们聚在一起

当时我没有足够的谷歌云信用额度(我希望我有),所以买 4 个树莓派和克隆 SD 卡似乎是最好的主意。由于这是一个网络项目,我必须确保涵盖网络安全,所以我还决定使用 Kali Linux 进行集群的渗透测试。然而,我面临的一个不足是,当时我住在大学礼堂,所以我不能控制自己的 Wifi。然而,我的房间有一个以太网端口,所以我能够插入一个交换机,并确保我的 Pi 可以在一个网络接口下连接。还有一些我无法控制的网络政策(这令人沮丧)。我的攻击计划是:

  • 分析和分类网络能力和系统资源
  • 对资源的相对重要性级别进行分类
  • 分析和识别对资源库的潜在威胁
  • 制定应对任何威胁的行动计划
  • 定义并制定一个计划,以便在攻击发生时将影响降至最低

我是否考虑过 Pi 的替代方案?

我喜欢它是蓝色的,但是价格标签不适合我。— 照片归功于英特尔

基于英特尔 x86 架构的英特尔 Galileo 是 Arduino 认证开发板系列中的首款产品。截至2016 年 10 月 3 日,目前有两个版本,分别称为第一代和第二代英特尔 Galileo。英特尔 Galileo 和 Raspberry Pi 的主要区别在于价格。Raspberry Pi 的起价为 35 美元,而英特尔的产品起价为 70 美元。几乎是两倍的价格,但内存和处理能力却更少。同样值得注意的是,Galileo 只支持 1 个操作系统,需要更多的电源。

伽利略于 2017 年 6 月到达其生命终点。

由于我的安装说明已经超过 4 年了,我决定不在本文中使用它们。然而,我将分享一个更新的指南:

安装完成后我拍的截图——感谢斯蒂芬·查彭达玛

我成功地安装了 Hadoop,并且在 Pi 上访问了 Web GUI:

规格很糟糕,我知道——HDFS 跑步的截图

项目的其余部分涉及运行一些 Hadoop 函数,并检查圆周率是否没有融化。幸运的是,他们设法熬过了这一切。按照我的课程要求,我应该向我的项目主管和另一位讲师演示我的解决方案。我通过拆除集群并恢复到单个节点来为我的演示日做准备。我的计划是演示一个运行 Hadoop 的单个节点,一本书的字数分析,同时展示 Pi 无需超频就可以处理这些。我在节点 1 和节点 2 上练习了这个演示,以防万一。在演示日,Node1 最初不会打开,这是一个糟糕的开始。当它打开时,它不能连接到互联网,因为我现在在一个不同的校园里。所有这些小问题都很快得到了解决,但是当 Hadoop 运行到高潮时,内存泄漏导致了它的崩溃。这一创伤的结果是,我现在在构建系统时过度配置服务器,以防万一。我设法完成了令人痛苦的演示,但如果我完全诚实,我的 Hadoop 梦想在那天破灭了。

这个项目是对大数据的一次令人兴奋的尝试,它绝对是一个 Pi 项目,当你在谷歌上看到第 30 页时,你就会找到你的解决方案。我会再做一次吗?很遗憾是的😶。由于我已经在网络安全领域工作了几年,我的兴趣已经发生了变化,但有一点是不变的,那就是我对大数据的访问以及寻找管理大数据的解决方案的需求。如果我有时间,我想把我的一个蜜罐连接到一个 Raspberry Pi Hadoop 集群,我目前还不知道为什么,但我肯定会找到一个。

raspbian Jessie—Pi 基金会提供

延伸阅读:

  • 构建 Hadoop Raspberry Pi 集群
  • honey doop——一个使用 Hadoop 创建虚拟蜜罐的系统

作者斯蒂芬·查彭达玛

第 1/3 部分——预测我的半程马拉松完成时间,误差小于 45 秒。

原文:https://towardsdatascience.com/half-marathon-finish-time-prediction-part-1-5807760033eb?source=collection_archive---------35-----------------------

跑步的机器学习-数据分析与介绍。

图片由 Marvin Ronsdrof 拍摄

哥德堡马拉松是世界上最大的半程马拉松。2019 年 5 月,比赛庆祝了 40 周年,吸引了超过 50,0 00 名选手和 200,00 0 名观众。

作为一名观众,你可以跟踪一份跑步者名单,看看他们在比赛中是如何进步的。这是可能的,因为跑步者每隔 5 公里就要经过跑道上的检查站。当你看不到你的朋友时,这是一种保持联系的有趣方式。您还将看到跑步者的预计完成时间,这是基于他们目前的平均配速。

结束时间预测是如此的基础和不准确,这一直困扰着我。它忽略了比赛的海拔曲线等因素,以及大多数跑步者在比赛中越跑越累的事实。它也无法在比赛开始前估计你的完成时间。

我们将在这个博客系列中解决这个问题,分为三个部分:

  • 第一部分—数据分析(你在这里)
    仅仅从不同角度看数据,我们能学到什么?
  • Part 2 —狂妄分析什么年龄和性别的群体最高估自己的能力?这一部分还包括一些特征工程,这些特征工程将在第 3 部分中涉及的预测模型中发挥巨大作用。
  • 第三部分——跑步者完成时间预测我们能在比赛前和比赛中多好地预测跑步者的完成时间?

这场比赛

哥德堡是围绕哥德堡市中心的半程马拉松。与大城市的其他半程马拉松相比,它的海拔曲线颇具挑战性。如果我们使用谷歌地图的海拔数据,我们可以绘制出比赛的海拔。谷歌高程数据的一个缺点是,它完全基于地球表面,如下所示:

比赛高度——是的,那条橙色的线是一座桥。

数据集

为了帮助回答上述问题,我们有一个由 ~39000 个跑步者组成的表格数据集(每行一个——仅包括实际开始的跑步者)。35%的参赛者是女性(13600 人)。它只包括 2019 年的数据,这是一个苛刻的限制。如果我们有过去 20 年左右的历史数据,我们可以做得更多。

虽然有一些跑步者来自世界各地,但大多数来自瑞典和中欧:

跑步者家乡的热图,经纬度映射到他们所代表的城市。

除了国籍和家乡(由每位跑步者在注册时声明),我们还有以下信息:

一般信息

  • 年龄
  • 性别
  • 起始号码
  • 开始组
  • 公司

每位跑步者的关卡时间:

  • 5 公里
  • 10 公里
  • 15 公里
  • 20 公里
  • 终点(21 公里)

我们会对这些数据做很多不同的折叠来理解它。可视化数据集让我们对跑步者群体有了很好的了解——这将有助于我们在第 3 部分中为机器学习模型设计功能。

让我们更好地了解我们的跑步者:

按性别划分的完成时间分布

男性和女性的完成时间都遵循正态分布。

年龄分布

25-30 岁的女性对这一比赛的兴趣增加,30 多岁时兴趣减少,40 出头时强势回归。

年龄分布非常有趣,因为没有一条曲线(男性或女性)属于正态分布。人们可能会写文章解释为什么我们看到 30-40 岁的跑步者突然减少,但我简单的猜测是因为孩子和家人花了更多的时间。还需要指出的是,25-29 岁的人比其他任何年龄的人都要多一点(来自瑞典年龄结构的统计数据)。我们看到男性也有类似的双峰曲线,与女性相比,第一个峰值较小。

因为年龄分布不遵循正态分布,我们可以通过使用内核密度估计值绘制年龄分布与完成时间的关系图,从我们的数据中获得进一步的见解,以查看组出现的位置:

完成时间与年龄密度

在考察年龄与完成时间时,有两种不同的“典型跑步者”场景——30 岁的人跑了不到两个小时,40 岁出头的人跑了差不多同样的时间。

让我们以稍微不同的方式绘制年龄与完成时间的关系图,看看我们是否能学到更多东西:

按年龄组的完成时间分布

按年龄组显示完成时间的山脊图。在 48 岁以上的年龄组,我们可以看到完成时间的变化(脊线随着其密度向右移动)。

我们可以观察到年轻跑步者和老年跑步者的最大差距,平均完成时间约为两小时。令人鼓舞的是,32-48 岁的跑步者并没有明显慢于年轻跑步者。如果你仔细观察上图中每个年龄组在两个小时左右的峰值,你会看到心理学的最佳状态。

让我们仔细看看 2 小时左右的结束时间。

2:00:00 左右每次完成时间的跑步人数

进一步调查先前地块中的主要峰值。12 秒钟。两个小时的标记无疑激励了跑步者。

两小时前后的正负两分钟,在分布上似乎有显著的差异。仅使用从 1:58:00 到 2:02:00 的数据,刚刚成功的跑步者的百分比大约为 57% (将每一边相加,然后将左边除以总数——使用桶围绕中心加减两分钟)。

使用这种测量方法,让我们看看哪个结束时间这种心理效应最强。我们不使用固定的 4 分钟窗口,而是通过使用 4 分钟窗口作为两小时里程碑的基础,将窗口大小标准化为里程碑时间(这算出约为 3%)。

不同完成时间的心理效应

对于 x 轴上的每个值,我们使用 x 轴值周围 3%的窗口来测量低于完成时间的跑步者的百分比(y 值)。

我们可以看到,这种影响在 5 分钟和 10 分钟左右最强。这是因为人们倾向于在偶数时间设定目标,比如 2:00:00。

图中的趋势是成功率随着完成时间的增加而增加,这意味着当我们达到更慢的完成时间时,成功的平均百分比会慢慢增加。这很有道理。如果我们要画一条趋势线,我们会看到它在 2:05:00 左右突破 50%(这也是所有跑步者的平均时间)。

另一个有趣的观察是在里程碑之间有看似随机的峰值。比如看一下 2:07:00。这是跑步者设定配速目标而不是完成时间目标的结果。全程以每公里 6 分钟的速度跑步,你的总完成时间是 2:06:35。

这个情节并不意味着跑得慢的人更擅长完成目标,或者跑得快的人不太关心他们的目标。因为完成时间遵循正态分布,自然有更多的人在窗口的较慢一侧完成(因为完成时间比平均值快)。例如,遵循正态分布,您更有可能在 1:35:00 到 1:36:00 之间找到跑步者,而不是在 1:34:00 到 1:35:00 之间。同样,你在 2:44:00 到 2:45:00 之间找到跑步者的可能性比在 2:45:00 到 2:46:00 之间找到跑步者的可能性更大。请记住这一点,我们看同样的情节,但按男女分组:

不同完成时间的心理效应,按性别

对于 x 轴上的每个值,我们使用 x 值周围 3%的窗口来测量跑者在完成时间内的百分比(y 值)。这种心理影响对两性都存在,但似乎在时间对男性和女性的重要性上略有不同。

很难从这个情节中得出进一步的结论。因为我们可以观察到男性和女性都有明显的峰值,所以这种心理效应对两种性别都存在。对于女性来说,两小时的峰值没有男性高,但这可能是因为她们遵循不同的正态分布,并且女性设定的其他目标更接近她们的平均完成时间。比如 2:40:00 左右效果好像差不多。

一种想法是将所有数据相对于它们的平均值进行归一化,以消除性别之间的绝对时间差异——然而,这种方法的主要缺点是失去了偶数里程碑时间的效果,因为所有的完成时间都会略有偏移。

我们可以天真地说,男人比女人设定更多的目标,甚至说男人更擅长实现他们的目标。然而,也可能是女性设定了更严格的目标,或者没有设定同样多的目标,或者是男性故意跑得更慢以达到他们的目标——我们不知道。我们将不得不参考其他的研究来找出更多的信息,以及男性和女性在设定和实现目标的方式上是否存在差异。

我们可以做的是浏览这些数据,并找出男性和女性是否倾向于设定完成时间的具体目标,或速度的具体目标。当我这样做时,我没有发现统计上的显著差异。

下面是一个类似的图,但显示了每个年龄组的影响,在 2 小时左右的 10 分钟标记处:

10 分钟里程碑对不同年龄组的心理影响

对于不同的年龄组和每个里程碑周围的小窗口(里程碑时间的 3%),跑得刚好在时间之下和刚好在时间之上的跑步者的百分比是多少?图例显示每个年龄组的平均完成时间。

我们可以看到,尽管平均完成时间(02:04:17)比其他 3 组慢,但 16-24 岁的人在 2 小时里程碑附近的成功率最高。然而,当谈到打破 1:50:00 大关时,年龄似乎很重要——在这个里程碑,56-64 岁年龄组完全主导了年轻选手。在这个博客系列的第 2 部分中,我们将会得到一些可能导致这种情况的想法。

我们已经研究了跑步者的一些,但不是全部(起跑组、配速)特性。这有助于我们理解它们。但是是什么造就了一个跑得快的人呢?区分跑得快的人和跑得慢的人的标准是什么?光看别人的数据我们能学到什么?

有些事情你可以改变,但你不能改变自己——例如,你不能变得更年轻,你不能改变性别(嗯…),你不能改变你的身体特征成为埃塞俄比亚人。

那么你能改变什么呢?准备是关键,一个好的建议显然是在比赛前进行更多的训练,并提高你的技术。如果我们通过观察北欧人口的平均值得出结论,你应该搬到库拉维克或奥斯陆。但是搬到另一个城市不会让你跑得更快,至少不会马上。相反,我们将查看检查点的数据,看看你是否可以对整场比赛中自己调整速度的方式做些什么。这将在第 2 部分继续。让我用这个情节来逗逗你。

速度变化——完成时间与年龄

为每位跑步者单独计算的五个不同检查点的跑步配速标准偏差。越暗意味着速度越不均衡。每个跑步者一圈。

继续阅读:

  • 第一部分——数据分析(你在这里)
  • 第二部分——狂妄分析
  • 第三部分——跑步者完成时间预测

用 R: 10 日常习惯用法处理缺失数据

原文:https://towardsdatascience.com/handle-missing-data-with-r-10-daily-used-idioms-13d849d01690?source=collection_archive---------47-----------------------

r 提示

你应该把命令自动化

照片由马特·阿特兹在 Unsplash 上拍摄

数据清理是数据分析过程中最耗时的阶段之一。它的许多步骤包括熟悉数据集、搜索缺失值、插补或删除缺失值,以及可能对不同变量或其组合的相同代码行进行大量重复。因此,我们必须寻找并接受任何加快进程的可能性。

不久前,我提交了一篇关于针对数据集中缺失值的简短 Python 习惯用法的文章。今天,我准备了类似的脚本汇编,但在 R 语言。此外,我们将再次使用 Kaggle 的葡萄酒评论数据集。

0.使用 NAs 打开数据集

是的,R 中的向量从 1 开始,但是在处理缺失值之前,我们应该有一个包含缺失值的数据集。有时,空记录会被替换字符串填充,如空格(“ “)、“empty”“nan”或一些垃圾。为了开始这项工作,我们应该用“真实的”NA值来代替它们。幸运的是,我们可以在数据集开放阶段做到这一点:

wine_data <- read.csv(‘winemag-data-130k-v2.csv’,**na.string** = c(‘’, ‘i’, ‘P’))

na.string接受替代值的向量。

1.有没有完全缺失的值?

开始时,我们需要检查缺失值的存在。我们有is.na()用于这些目的。它接收数据并返回一个布尔向量。

  • 检查是否缺少单个值:
    is.na(wine_data$region_1[2])
  • 获取某些列中缺少元素的行:
    wine_data[is.na(wine_data$country),]
  • 检查一列中是否有缺失值:
    all(!is.na(wine_data$points))
  • 检查一列中是否有缺失值:
    any(is.na(wine_data$country))

2.检查缺失值存在的最短方法

以前的脚本需要一些关于数据集的知识和对独立元素的访问。但是如果我们想看到全貌呢?答案是na.fail()功能。如果整个数据中有任何缺失值,它将引发异常:

na.fail(wine_data)

3.了解整体情况

有一个特殊的函数,替代了一堆过滤器和索引。它主要用于数据框,可用于显示所有缺失值的行(在任何列中):complete.cases()。它返回一个布尔向量,非常方便索引。

  • 获取缺失数据的行数
    sum(!complete.cases(wine_data))
  • 获取有缺失数据的行
    wine_data[!complete.cases(wine_data), ]

4.更实用的命令

所有以前的脚本主要用于探索性任务:展示、获取等..但是如果我们需要得到缺失值的索引呢?在这种情况下,我们应该使用which()功能:

which(is.na(wine_data$country))
#returns indexes of rows with missing data

5.NA 值的高级使用

看来,NA价值观存在的唯一目的就是被清除。不过,我们可能会在一些非常有趣的组合中使用它们。例如,我们有一个混合数据向量:

test_vec <- c( 'ten', '5', 'n', '25', '10')

我们希望将“可转换”的字符串(如‘5’‘25’)与其他字符串分开。我们可以和is.na()功能一起做:

test_vec[!is.na(as.numeric(test_vec))]
# returns ( '5', '25', '10' )

6.跳过 NAs 进行计算

NAs存在有一些副作用——它把几乎任何操作的结果值都变成了NA。但是有一个解决方案——很多 R 函数都有内置的na.rm参数,允许跳过缺失值。

mean(wine_data$price)
# returns NAmean(wine_data$price, **na.rm** = T)
# returns the result

7.忽略数据集中所有缺失的值

你可以看一下以前的脚本,然后想,省略丢失的值是一件非常乏味的工作。嗯,是的,它是。但是如果需要一次删除所有的NA并把它们当作一场噩梦忘记,R 为我们提供了以下功能:

wine_data_totally_cleared_1 <- na.omit(wine_data)wine_data_totally_cleared_2 <- wine_data[complete.cases(wine_data),]

如你所见,我们可以使用已知的特殊功能na.omit()``complete.cases()。结果是一样的:数据集中不再有缺失值。

8.省略数据集中一些缺失的值

当我们构建一些过滤器时,我们希望结果只有匹配的值。在处理数据框时,它变得尤其有价值。但是,如果您运行以下命令:

wine_data_condition_NA <- wine_data[wine_data$price > 20,]

您不仅会得到正确的子集,还会得到所有缺失的值。它是 R 数据帧索引、布尔数组和NA性质的结果:缺少值将条件结果变成被视为非FALSENA。我们仍然有丢失值搜索的痛苦。

解决方法是subset()功能:

wine_data_condition <- **subset**(wine_data, wine_data$price > 20)

它返回正确的子集,但没有 NAs,NAs 被过滤掉了。

9.关于缺失值的更多信息

让我们回到查看数据集全貌时的步骤。我们希望看到缺失值的分布,也许是一些模式,或者变量之间的依赖关系。我们还有另一个具有所需功能的 R 包— “鼠标”包。它包含一些函数,这些函数遍历数据集,统计所有的遗漏,并构建数据集的图片。举个例子,我们来举个例子:wine_data[1:5, 4:8]。它包含下一个数据:

正如我们看到的,有一些丢失的值。让我们应用上述包中的 md.pattern()函数:

require(mice)
md.pattern(wine_data[1:5, 4:8], plot = F)

我们得到了模式表:

最左边的索引显示行数。最右边的索引显示缺失特征的数量。中间的矩阵显示了模式:在计算的行中缺少哪个特征组合。所以第一行告诉我们,有 2 行没有缺失数据(0 个缺失特征)。第三行显示,数据片段中有一行缺少一个特征,即缺少price

10.形象化

现在我们准备好可视化缺失值的分布。我们为这项工作准备了另一个 R 包— VIM 库。在许多其他函数中,它绘制空记录的分布直方图,并根据上一步构建模式表的可视化表示:

require(VIM)
aggr_plot <- aggr(wine_data, col=c(‘navyblue’,’red’),numbers=TRUE, labels=colnames(wine_data),ylab=c(“Histogram of missing data”,”Pattern”))

我们有一幅美丽的图画:

例如,现在我们可以看到,几乎 60%的行没有region_2值。

对于我来说,你应该把这些代码片段自动化。你会收集到超速行驶的重要分析。此外,和往常一样,您可以在我的 GitHub 上找到带有工作示例的代码:

[## 中级/中等 _jupyter_notes

为中型文章构建的代码和模型示例- Midvel/medium_jupyter_notes

github.com](https://github.com/Midvel/medium_jupyter_notes/blob/master/r_missing_values/missing-values.R)

请确保您已经看过我之前关于 Python 习惯用法的文章:

[## 每个数据科学家都应该知道的获取缺失值的 7 个习惯用法

你应该把命令自动化

towardsdatascience.com](/7-idioms-to-acquire-missing-values-every-data-scientist-should-know-2edf4224360c)

在制造业中处理批量生产数据

原文:https://towardsdatascience.com/handling-batch-production-data-in-manufacturing-f720a6026bd?source=collection_archive---------78-----------------------

解决两个常见问题:验证和模型训练

埃文·德沃金在 Unsplash 上拍摄的照片

很多制造业的生产过程都是分批完成的。一个批次中的两个项目以相同的生产设置生产。因此,这两件物品要么是完全相同的复制品,要么是非常相似的复制品——一件**伪复制品。**伪重复是指属性非常相似,甚至在某些情况下完全相同的项目。

这种批处理过程加快并简化了生产流程。然而,如果你在这样的环境中工作,并且想要使用数据科学和机器学习来通知你的决策,你需要非常小心如何使用你的数据。

当考虑将机器学习应用于批量制造数据时,会出现两个主要挑战。第一是确保您正确地验证了您的模型,第二是使用批量数据处理实际的模型训练。

让我们依次看一看每一个,并给你一些如何解释这些问题的想法。

第一步——修正你的验证

批量数据的最大问题是验证。最常见的验证方案——交叉验证、分割验证和引导验证——假设你的每一个例子都是独立的。

但是如果你批量生产,情况就不一样了。

让我们来看看,即使您的观察结果并不相互独立,您如何仍然能够验证您的模型。请记住,验证是数据科学家相信他们的分析的主要原因。这就是为什么把这件事做好是至关重要的。

要在批量生产环境中做到这一点,我们需要确保来自一个批次的所有示例总是在我们进行的任何数据验证分割的训练或测试端。

如果我们不这样做,我们正在训练的模型基本上就能够作弊——它会知道一些测试行的正确答案,因为在训练数据中存在一个相同(或非常相似)的行。因此,验证过程会说模型是好的,但是一旦它投入生产并且不能再欺骗了,它的性能就会下降,很可能下降很多。

在 RapidMiner 中,这可以使用交叉验证操作符的“批量属性分割”选项来完成。如果选中,所提供的示例集需要包含一个批处理属性,以便该操作符进行操作。本字段手动定义属于一个批次(或一次交叉验证)的内容。

上面描述了一种派生 BatchId 属性的常见解决方案。这里,modulo 函数用于从数字 Id 生成 BatchId,在本例中,数字 ID 是一个商品 ID。mod 函数计算除法的余数,因此 mod(11,10)返回 11 除以 10 的余数。答案就是你在这里看到的 1。

使用这个选项,我们防止一个出现项 11 出现在训练集中,而另一个出现在测试集中。

如果您使用的是拆分验证而不是交叉验证,您可以通过首先使用排序运算符按 ID 列排序,然后使用筛选示例范围来解决这个问题。这将数据集分成两部分。但是这一次不是随机抽样,因为在分割之前已经按照 ID 进行了排序,所以相关的项目在数据集中并不相邻。

完成此操作后,您可以使用前 x 行训练,剩余的 y 行可用于测试,因为训练部分现在不同于测试部分。(由于数据量较小,在分割数据时数据集之间少量溢出的可能性通常可以忽略。)

既然我们已经处理了验证,我们需要解决批量数据可能存在的潜在混乱

第二步—处理数据本身

在普通学习者中使用您的数据可能会对模型造成一些混淆。请记住,由于数据的分批性质,您的学习者可能会遇到 10 个项目,其中只有一个是“正确的”,即使它们彼此非常相似。

根据您的算法,这可能会对您的模型最终的工作方式产生严重的影响。

因为学习者通常偏向于在他们不确定的情况下预测大多数,所以输入大量非常相似的数据点可能会使模型偏向这个方向。

对于基于树的算法,您必须修改您的修剪策略,因为在考虑批量数据时,类似“如果样本少于四个,则不要分割这个分支”这样的设置可能不合适。

因此,在模型训练过程中以特殊方式处理批数据可能是有意义的。以下是如何在模型训练过程中克服批量数据挑战的三种方法。

1.抽样

正如机器学习中经常出现的情况,解决问题的方法之一是使用采样方法。我们可以从批处理过程中随机抽取一个项目,并将其用于模型训练和测试。这很好地解决了分类问题中保持类别平衡的问题,以及回归问题中的标签分布问题。

这也是一个简单的技术。缺点是您会丢失示例,因此也可能会丢失信息。这实际上取决于是否通过使用给定批次中的多个项目获得了额外的信息。

可能会有,因为每个单独的项目可能是用相同的材料制作的,只有生产设置不同。但是,从每一批中包含一个以上的项目示例可能也不会有什么收获——这是您必须根据您的特定用例来决定的事情。

2.权衡和改变问题

就像不平衡分类问题一样,您也可以在这里使用一种加权技术来克服这个问题。您不需要删除示例,而是对单个批次中的项目进行平均,并将行数作为您的学员和表现的权重。

这对于所有的学习者来说是不可能的,但是相当多的普通人支持它。为了弄清楚你的学习者是否支持它,你可以右击一个操作符并说看看操作符信息。

当然,这种策略也有一些缺点。

首先,平均你的所有属性可能不是最好的办法。如果你的值相差很大,那么当你取平均值时,你又会丢失很多信息。这又可以归结为这些问题:你的行有多少是重复的?它们只是依赖的伪副本还是真副本?

手头的另一个问题是如何处理标签?对于回归问题,例如测量的浓度,当然可以取平均值。但这是你需要的吗?你对最大值更感兴趣吗?还是第八届十周年?与往常一样,您应该让您的数据科学方法与手头的业务需求保持一致,并仔细考虑您正在做出的选择。

对于分类问题,您会遇到模式(最频繁的类别)可能更不适合的问题。在这种情况下,分类问题通常是真正的挑战,当你问一些东西是否通过了质量测试。

在这里,你可以使用旧的计算机科学技巧,改变问题。你可以考虑从基于项目的问题转移到基于批量的问题。你可以回答的问题是:我的批次中有多少部分不能通过质量测试?

这是一个批量级的回归问题,如果需要可以转化为分类问题。

3.组装

解决批量问题的一个有趣的方法是使用抽样方法,但是使用集合方法。这个想法是你建立多个学习者。每个学员只能看到给定批次中的一个项目。

这个项目是随机选择的。多次这样做可以确保您不会丢失信息。这个想法可以被认为是一个随机森林,其中随机抽样被分层抽样所取代。

4.就让它保持原样

在谈了一些先进的想法之后,我想强调的是,仅仅“按原样”使用数据也是一个有效的选择。

机器学习算法被设计为鲁棒系统。他们习惯于在噪音中工作。因此,原则上他们也可以使用这些伪副本。

随机森林甚至在它们的引导抽样中有意产生相似的副本。因为随机森林是非常健壮的学习者,并且引导是随机过程,所以这不会损害森林。

最后的想法

和机器学习一样,没有免费的午餐,也没有简单的答案。上面列出的想法是坚实的起点。然而,您真正知道什么最适合您的数据的唯一方法是尝试一些事情,看看什么最适合。

记住,模型训练本质上是一个迭代的过程,所以看看什么最适合你的特定用例。

机器学习项目人类指南

启动机器学习项目很难。这个问题的解决方案是从一开始就建立一个坚实的项目基础,为自己的成功做准备。我在本指南中概述的流程将有助于简化这一过程。

【rapidminer.com】这篇博文最早发表于 博客

在 Python 上处理大量石油测井数据并提高时间效率

原文:https://towardsdatascience.com/handling-big-volume-of-well-log-data-with-a-boosted-time-efficiency-with-python-dfe0319daf26?source=collection_archive---------23-----------------------

Python 如何彻底改变了我们与石油行业大数据的交互方式,我们应该了解它吗

地球的一部分。图由Ani-Mate/shutterstock . com 提供

T 这是一个地球物理学家的故事,他已经厌倦了在大多数商业软件中用手工输入来处理大量的测井数据。谁和我有同样的感觉?然而,我成功地开发了一种方法,几乎不用 Python 编程技巧就能摆脱这种累人的手工输入。在这里我想和你分享一个教程。我假设你熟悉地质学、地球物理学、石油工程以及所有与地球科学相关的东西。然而,如果你不熟悉它,没关系,我很高兴向你介绍我们正在处理的日常活动。老实说,对于开源计算来说,Python 是一种非常灵活但非常强大的语言。

测井数据看起来是这样的!乱七八糟但是油油的有营养。 (Aliouane 等人,2012 年)

在石油工业中,测井数据是一种非常有价值的数据来源,用于解释地球深处的地下图像,并获得更多关于岩石内部的信息:如果你足够幸运,你会发现石油。反正开玩笑!寻找石油的事业花了很多年。关键是,时效。时间效率,主要是在探索阶段,对企业的未来意义重大。当一个油田已经生产了几十年的时候,测井数据从来不会以单一或少量的形式出现。可以是 50 口,100 口,甚至 500 口油气井。这肯定是非常巨大的,因为已经钻了很多井。一个测井数据包含岩石的测量数据,例如密度、声速、伽马射线、电阻率等等。因此,总共 46 个井的大量数据可能占用大约 120 MB!测井数据通常采用 LAS 格式(我将在本教程中完全使用这种格式)。

LAS 数据中的测井数据示例

就我个人而言,迄今为止我所知道的大多数商业软件都有时间效率限制,因为我们必须重复地手动输入关于我们输入的每个测井数据的所有详细信息。如果我们有大量数据,这可能会很乏味和麻烦

想象一下,光是手工输入和检查数据的单位,我们就要花费多少时间!然后我发现使用 Python 非常吸引人!

辅导的

打开你的 Python,先导入 Python 库的“三剑客”; numpymatplotlib ,以及 熊猫 。我之所以称他们为“三剑客”是因为他们不能独立工作,因为 Python 中的任何基本计算都需要 numpymatplotlib ,以及数据需求 pandas

import numpy as npimport matplotlib.pyplot as pltimport pandas as pd

现在进入包含 LAS 格式的多井测井数据的文件夹。复制文件夹的路径,用 Python 指定路径,将路径粘贴在上面。

import syssys.path.append('...')

现在是有趣的部分!你会看到所有的文件。导入 glob 并导入文件。

import globimport os file_path = "/content/drive/My Drive/Colab Notebooks/well_logs"read_files = glob.glob(os.path.join(file_path, "*.las"))read_files

如果成功,将出现您的多条测井数据的路径文件名。如果你读取 100 个测井数据,它将显示为一个很长的列表!

Glob 成功读取您的数据

由于您只对文件名**(无文件夹路径)感兴趣,即井名,例如从上面的例子中,只对**660810-B-1BH**感兴趣,而不是对整个**/content/drive/My Drive/Colab Notebooks/well_logs/660810-B-1BH.las**感兴趣,您可以将不需要的文件路径名分类出来,这样您将只得到井名。**

well_names = []for files in read_files: files = os.path.splitext(os.path.basename(files))[0] well_names.append(files)print(well_names)

这将为您提供油井名称

井名

调查你有多少数据。

print(len(well_names))

例如,你有 45 口井的数据。由于 Python 从 0 开始索引,而不是从 1 开始索引,这意味着第一口井名 660810-B-1BH最后一口井,分别被:

print(well_names[0])
print(well_names[44]) # 45 wells minus one

在 Python 和任何编程语言中,你几乎总是通过索引来调用一些东西。

Python 索引的公式永远是:从零开始,某物减一。

现在您已经有了井名,是时候读取所有 LAS 数据了。你将使用一个非常专用的库来读取 LAS 文件,名为 lasio 。Lasio 是一个可以读取 LAS 文件的优秀库,事实上你也可以自己从头开始构建一个程序!不过 lasio 对于时效来说已经足够了。这是我想强调的最重要的一点,即您可以同时导入所有文件,甚至一次点击 100 个文件,这是使用一些商业软件几乎无法做到的。在导入过程中,你不需要专注于手动检查和输入合适的单位。表演时间到了!

先安装 拉索T22。我假设您可能已经非常熟悉如何安装库了。您可以编写一点儿代码pip install,或者更容易的是,您可以浏览这些库并将其导入到一个名为 PyCharm 的 Python IDE 中。

pip install lasio

安装成功后,导入它,只用写 4 行代码就可以用 lasio 读取 LAS 文件。但是你必须有耐心,因为这需要相对较长的时间。所花费的时间取决于你导入的测井数据量,然而估计读取 50 条测井数据不会超过 30 秒

lases = []for files in read_files: las = lasio.read(files) lases.append(las)

导入过程与从头到尾读取井名的顺序相同。在导入过程中,您可能会遇到一条警告,内容如下:

这是对 OK 的警告

以我的经验来看,很正常,所以一切都没问题。

恭喜你!您在总共不到 5 分钟的时间内导入了大量测井数据。

是时候看看你的数据是什么样子了。请记住,在我们之前的讨论中,井名可以通过索引来调用。例如,我们称为索引 19

# type the numbers from 0 to max number of wells in the wellnames[...]find = well_names[19]# print the name of the searched wellprint("Well name:", find)

如果调用索引 19,它将打印第 20 个井的名称。请再次记住上面的经验法则:指数是某个东西减一

上面的代码工作起来就像一个目录。现在编写下面的代码,看看第 20 个测井数据里面有什么。

id_ = np.int64(np.where(wellnames==find)).item()print("Data available:", lases[id_].keys())# check more detailsprint("Detail about data:")print(lases[id_].curves)

它将打印两件事:测井记录中的可用测量数据和测井记录数据的详细信息。****

可用数据的打印输出

它告诉你什么数据是可用的。这里可用的数据有:深度、TVD、TVDSS、GR、KLOGH、NPHI、PHIF、RHOB、SW 和 VSH 。这些是什么?这些是岩石测量类型的首字母缩写词(或所谓的助记符**,例如 GR 代表伽马射线KLOGH 代表渗透率NPHI 代表中子孔隙度RHOB 代表密度,以及 SW 代表水饱和度。每个测量值都有特定的单位,你必须注意。**

这条信息非常重要,比内容本身重要得多。这条信息就是我们在文件头中看到的。

现在终于到了我们教程的最后一部分。我们非常希望看到测井记录。 data_view 变量中输入所需的测量类型。例如,我们有兴趣查看密度日志或 RHOB 数据。输入RHOB。我们将使用 matplotlib

# peek or overviewing the well log# which data you want to see??? data_view = 'RHOB' # input the measurement type which data you want # to seeprint("Data", data_view, "of well:", find)plt.figure(figsize=(5,10))plt.plot((lases[id_][data_view]), (lases[id_]['DEPTH']))plt.xlabel(data_view); plt.ylabel("Depth (m)")plt.grid(True)plt.gca().invert_yaxis()

可视化只是打印出以下内容:

密度测井可视化

恭喜,我们的教程到此结束!

如果你仍然渴望以上测井数据的更漂亮的可视化**,我有一个绝妙的配方!**

但是因为这篇教程没有涉及到这个问题,所以我会把它留到以后,如果你渴望的话,我会写另一篇教程。

你学到了什么?

首先,你已经学会了如何导入多个测井数据文件;** 50,100,200 档,或更多**,不超过 5 分钟。你已经打破了在商业软件中手工输入的平均时间。其次,你已经学会了如何通过索引数据对文件进行分类。有 50 个、100 个、200 个井名,你肯定不想一一点名,因此索引是一个更好的方法。最后但同样重要的是,你已经学会了如何打印出数据的细节(标题)和可视化数据**。**

从长远来看,我只能说 Python 在处理大数据方面非常惊人,超过了普通软件处理相同数量数据的平均时间。如果你觉得你可以通过编写更高效的代码及时击败我,请联系我并告诉我!

到达我的 GitHub:github.com/yohanesnuwara

到达我的邮箱:ign.nuwara97@gmail.com

到达我的 LinkedIn:【https://www.linkedin.com/in/yohanes-nuwara-5492b4118/】T42

处理 Power BI 中的空白

原文:https://towardsdatascience.com/handling-blank-in-power-bi-90eed948d042?source=collection_archive---------11-----------------------

如何应对 Power BI 报表中的空白值?检查这三种可能的解决方案

皮查拜在 Pexels.com 拍摄的照片

在创建报告时,我敢肯定,当您最终得到“(空白)”时,您会面临这样的情况,并且您不希望像这样显示给您的最终用户。当然,在某些情况下保留空白是有意义的,但最常见的情况是您想要显示其他内容而不是它(对于数字来说是 0,对于文本来说可能是‘N/A’或‘Unknown’)。

可能的解决方案

那么,在 Power BI 中有哪些处理空白的选项呢?我们直接在那里查吧…

我会用 Stack Overflow 2013 数据库。这个数据库包含了超过 2000 万条记录的表,所以如果要衡量性能,绝对比玩 Adventure Works 或者类似的数据库要好。

比方说,我想看看每一年有多少评论。首先,由于数据库中没有具体的年份值,我需要使用以下公式创建一个计算列 Year Comment :

Year Comment = YEAR(Comments[CreationDate])

下一步是创建一个衡量所有评论的标准。

Total Comments = COUNT(Comments[Id])

在这里,我们得到了每年的评论总数。现在,假设我们要专门计算 2012 年还剩多少评论。这可以用许多不同的方法来实现,但是我使用下面的公式:

Comments 2012 =
CALCULATE (COUNT ( Comments[Id] ),FILTER ( Comments, Comments[Year Comment] = 2012 )
)

让我暂停一下,给你介绍一下 DAX 工作室。也许你们中的一些人对这个工具很熟悉,但是如果你经常写 DAX 并且每天都使用 Power BI,这个工具是必须的!我不会详细说明它提供了什么功能——我会诚实地说它很棒,也是最重要的——它是完全免费的!所以,马上去下载 DAX Studio 吧:)…

我将使用 DAX Studio 来测量我的视觉效果的性能。让我们连接我们的。pbix 文件,并将我们新创建的度量添加到报告中。

我还打开了 Power BI 中 View 选项卡下的 Performance Analyzer,以便捕捉将在后台执行的查询。下面是 BI 生成的显示我们想要的内容的查询:

// DAX Query
EVALUATETOPN(502,SUMMARIZECOLUMNS(ROLLUPADDISSUBTOTAL('Comments'[Year Comment], "IsGrandTotalRowTotal"),"Total_Comments", 'Comments'[Total Comments],"Comments_2012", 'Comments'[Comments 2012]),[IsGrandTotalRowTotal],0,'Comments'[Year Comment],1)
ORDER BY[IsGrandTotalRowTotal] DESC, 'Comments'[Year Comment]

现在,让我停下来,试着解释一下背景中发生了什么。当您在 Power BI 中与可视化交互时,每次都会生成查询并将其发送到 Analysis Services (Tabular)引擎(Vertipaq),该引擎在后台运行并执行“脏”工作。

在下图中,我们可以看到 Vertipaq 是如何处理这个查询的:

解决方案 1:使用 IF

现在,我们开始处理视觉中的空白值。第一种情况是最明显的,我想也是最常用的。解决空白的措施如下:

Blank v1 comments =
IF (ISBLANK (CALCULATE (COUNT ( Comments[Id] ),FILTER ( Comments, Comments[Year Comment] = 2012 ))),0,[Total Comments]
)

并且,我们得到以下结果:

所以,我们在这里:我们显示的不是空白,而是零。让我们检查一下这个查询是如何执行的:

当然,对于简单的度量,差异不是很大,但是对于复杂的 DAX 和不同的过滤上下文,在数百万行的表上,差异可能很大。

解决方案 2: COALESCE()

最近 Power BI 推出了一个全新的功能:COALESCE()。对于那些来自 SQL 世界的人来说,这是一个众所周知的函数,但是让我为那些不熟悉它的人简单解释一下。基本上, COALESCE 将遍历作为参数传递的值,并返回第一个非空值(在 SQL 中不是 null)。

聚结(列 1,列 2,列 3…列 N)

因此,COALESCE 将检查列 1,如果值为空,它将检查列 2 的值。如果它也是空的,它将继续,直到找到第一个非空值。作为最后一个参数,您应该指定在所有检查的参数都返回空白时要返回的值,如下所示:

COALESCE(column1,column2,column3…columnN,0)

让我们使用 COALESCE 函数为我们的报告创建一个度量:

Blank v2 Comments coal =
COALESCE (CALCULATE (COUNT ( Comments[Id] ),FILTER ( Comments, Comments[Year Comment] = 2012 )),0
)

结果完全相同:

让我们检查一下这种方法的性能:

解决方案#3 技巧用 0

这是我看到王九思用过的一个小技巧。对于那些不知道的人来说,Jeffrey Wang 是 DAX 最知名的名字之一。

有什么诀窍?在 DAX 中,空白+ 0 就是 0!是的,我知道,对于我们这些来自 SQL 环境的人来说,他们认为 blank 是 SQL 的空孪生兄弟,这是完全出乎意料的行为。尝试在 SQL Server Management Studio 中运行以下命令:

select NULL+0

正如您所想,结果是空的。在 SQL 中,NULL+something 总是 NULL…在 DAX 中,它不是:)

因此,让我们在报告中尝试这个解决方案:

Blank v3 Comments 0 =
CALCULATE (COUNT ( Comments[Id] ),FILTER ( Comments, Comments[Year Comment] = 2012 )
) + 0

结果还是完全一样:

最后,我们来看看后台发生了什么:

没那么差哈:)

结论

如您所见,在 DAX 中有多种处理空白值的方式。根据数据集的具体特征,您应该测试不同的可能性,并选择最适合您需求的一个。

感谢阅读!

成为会员,阅读 Medium 上的每一个故事!

以正确的方式处理分类数据

原文:https://towardsdatascience.com/handling-categorical-data-the-right-way-9d1279956fc6?source=collection_archive---------8-----------------------

来源: Jelleke Vanooteghem

最被低估的数据编码方式以及你做错了什么

分类数据只是聚合成组的信息,而不是数字格式,如性别性别教育 水平。它们存在于几乎所有现实生活的数据集中,然而当前的算法仍然难以处理它们。

以 XGBoost 或大多数 SKlearn 模型为例。如果你试图用分类数据训练它们,你会立刻得到一个错误。

目前,许多资源宣传了各种各样的解决方案,这些解决方案起初看起来可能有效,但一旦仔细思考,就会发现它们大错特错。对于非有序分类数据来说尤其如此,这意味着这些类是无序的(可能是 Good=0,Better=1,Best=2)。区分数据科学家应该使用的方法和那些只是让模型运行的方法需要一点清晰。

不要做什么:标签编码

最简单和最常见的转换分类变量的解决方案之一是标签编码。它包括用相应的编号替换每个组,并在整个特征中保持这样的编号一致。

标签编码的例子

该解决方案使模型运行,并且是有抱负的数据科学家最常用的方法之一。然而,它的简单性带来了许多问题。

距离和顺序

数字维系关系。例如,四是二的两倍,当直接将类别转换为数字时,尽管原始类别之间不存在这些关系,但它们还是会被创建。看前面的例子,英国变成了法国的两倍,法国加美国等于德国。

嗯,这不完全正确…

这对于算法来说尤其是个问题,例如 K-Means,在运行模型时会计算距离度量。

解决方法

一键编码

一键编码是处理非有序分类数据的最常见、最正确的方法。它包括为每组分类特征创建一个附加特征,并标记属于(值=1)或不属于(值=0)该组的每个观察值。

独热编码的例子

这种方法能够正确地编码分类特征,尽管有一些小缺点。具体来说,大量二进制值的存在对于基于距离的算法(如聚类模型)来说并不理想。此外,大量额外生成的特征引入了维数灾难。这意味着由于数据集现在的高维数,数据集变得更加稀疏。换句话说,在机器学习问题中,每个特征组合至少需要几个样本。增加特征的数量意味着我们可能会遇到对每个特征组合没有足够观察值的情况。

目标编码

一种鲜为人知但非常有效的处理分类变量的方法是目标编码。它包括用目标变量中的平均响应替换分类特征中的每个组。

目标编码的示例

获得目标编码的过程相对简单,可以概括为:

  1. 按类别对数据进行分组
  2. 计算每组目标变量的平均值
  3. 将平均值分配给属于该组的每个观察值

这可以通过几行代码实现:

encodings = data.groupby('Country')['Target Variable'].mean().reset_index()data = data.merge(encodings, how='left', on='Country')data.drop('Country', axis=1, inplace=True)

或者,我们也可以使用 category_encoders 库来使用 TargetEncoder 功能。

目标编码也是一种强大的解决方案,因为它避免了生成大量的要素,就像一键编码一样,保持了数据集的原始维度。

摘要

处理分类特征是数据科学家的一项常见任务,但是,人们通常并不确切知道正确处理它们的最佳实践是什么。

对于非顺序类别,标签编码,包括用一个相对随机的整数替换一个类别,应该不惜一切代价避免。

相反,一键编码和目标编码是更好的解决方案。一键编码可能是最常见的解决方案,在现实生活中表现良好。目标编码是一种鲜为人知但很有前景的技术,它也可以保持数据集的维度一致,从而提高性能。

阅读更多类似的文章,请关注我的TwitterLinkedIn或我的 网站

最小化新冠肺炎对数据科学影响的三大方法(第 1 部分)

原文:https://towardsdatascience.com/handling-covid-19-impact-on-data-in-data-science-projects-87510c9006a7?source=collection_archive---------31-----------------------

减轻或解释数据中新冠肺炎效应的方法。

凯文拍摄的照片:Unsplash

在试图回答“ 为什么 ”关于新冠肺炎对数据科学的影响的问题后,有必要继续讨论“ 如何处理 ”的问题。本系列旨在利用行业数据科学领导者的意见,为“”提供一些潜在的答案。

不确定“为什么”是什么?你可能没看过这个系列的前奏。请在这里阅读以了解新冠肺炎对数据科学方法可能产生的影响,然后再进一步。

到目前为止,在这个系列中,我们将回顾丢弃数据、替换数据和特征工程方法。在第一部分中,我们将了解删除数据和替换数据。

最后,我要特别感谢本系列的合著者 Renee Ernst,General Mills 的资深首席数据科学家,她凭借自己在食品行业的经验成为了宝贵的信息来源。

简介

快速回顾一下!

在过去的 2-3 个月里,数据集被新冠肺炎效应弄得乱七八糟。在许多情况下,流入的数据并不反映正常的行为或情况。与更典型的异常值不同,这些数据是一些数据集的相当大的一部分,因此,传统的异常值补救措施可能无法帮助解决由这些异常数据引起的问题。这种“不正常”的数据也可能会持续流入一段时间,直到我们回到正常状态。在这次讨论中,我们只关注如何确保我们的模型在我们回归常态后能够继续很好地预测,而不是试图预测新冠肺炎本身的影响或轨迹。

图片来自坦布

对于预测模型,数据科学的假设“垃圾数据输入,垃圾数据输出”仍然非常重要。虽然我们试图讨论一些方法来建立稳健的模型,以最小化或考虑新冠肺炎的影响,但这些方法不能神奇地使你的预测模型准确,可能有其他方法在不同的情况下更好地工作。我们每个人都在一个独特的空间中工作,因此我们在处理这些数据时所做的基本假设需要有所不同。这些假设会因行业和使用情形而异,并且需要处理和更改数据,而在正常情况下,我们会尽力避免这种情况。我们需要坦率地说出我们的选择、做出这些选择的原因以及对我们模型的影响。

用谷歌首席数据科学家凯西·科兹尔科夫的话说,“在你写的每一行都要多次乞求原谅。

丢弃数据

这个方法很简单,但是也是最假设的!想法是丢弃或替换对预测模型有不利影响的“异常”COVID 数据。这似乎是一个简单而诱人的解决方法,但是这些方法都有其局限性。为了使这些方法起作用,我们将对数据进行大量假设,包括对丢弃/替换数据的预测能力的假设。丢弃方法的最大问题之一是它在处理相对少量的数据时的影响,尤其是当它需要丢弃大量数据时。

加里摄影:Unsplash

随着与 COVID 的斗争愈演愈烈,它继续蔓延到我们生活的方方面面。不管怎样,它正在影响我们的日常生活。尽管这可能不是“常态”,但在未来,我们还不确定何时会达到新常态,或者新常态会是什么样子。我们在此次危机最严重时期收集的数据仍有可能为我们提供未来将如何受到影响的重要见解。假设这些数据与未来无关,从而完全忽略这些数据,这可能是幼稚的。然而,如果我们可以确信在新冠肺炎期间收集的数据不会以任何方式反映未来,并且我们有足够的数据在删除这些数据后仍然可以构建准确的模型,那么删除这些数据是一个合理而实用的解决方案。下降法可能有效的一个例子是预测(一旦事情恢复正常)期间的能源使用。给定时间内能源使用量的最佳预测指标之一是上一天或上一周同一时间的能源使用量。鉴于世界各地的许多企业和公共场所目前都处于关闭状态,如果不采取某种方式加以解决,最新数据将会失真,并将影响我们随后的预测。使用多变量建模仍有可能处理这些数据,这将在后面讨论,但另一种方法是丢弃最近的数据,并将新冠肺炎之前的数据视为最近的记录。

替换数据

当历史数据有限,但被替换的数据适用于所讨论的时期时,替换数据成为一种可行的方法,尽管是在某些假设下。

我们之前的能源预测示例可能是一个替换数据是更好选择的例子。假设由于历史数据有限,单独删除数据不是一种选择。我们可以用上一年同期的数据替换受影响的数据。这样做时,我们可以很容易地考虑到自去年以来能源使用的任何平均增加/减少,将一个因素应用到我们替换的数据,考虑到这种变化。替换方法是用这一时期(新冠肺炎撞击之前)的原始预测替换受新冠肺炎撞击的数据。如果去年的数据是陈旧的,这可能会有所帮助,如果我们在新冠肺炎之前对我们的模型的总体准确性非常有信心,这将是一个好方法。从上面的例子可以明显看出,被替换的数据需要在历史上是准确的。

另一种数据替换技术可能有用的情况是在预测历史数据有限的产品的销售时。例如,假设您预测每周的区域卫生纸销售量,但只有几年的数据。如果你想预测新冠肺炎危机(希望)过去后的未来销售,你需要一些方法来处理几个月的新冠肺炎数据。如果危机影响了 3-4 个月的销售,而您只有 3 年的数据,这已经影响了您 10%的数据,因此您可能不想丢弃它。相反,您可以用历史值替换数据,或者如果您的预测在过去非常准确,您可以用以前的预测数据替换它。当然,这是有风险的,但是只要用清晰的交流来详述这些风险,这可能是一个可行的解决方案。

关于作者

Usman Gohar 是一名数据科学家,明尼阿波利斯数据科学的共同组织者,也是一名技术演讲人。他非常热衷于最新的数据科学研究和机器学习。你可以在 LinkedIn 、 Twitter 、Mediumfollow onGithub上与他联系。

Renee Ernst 是 General Mills 的高级首席数据科学家,担任一个数据科学家团队的技术经理,该团队构建用于情景规划和优化促销的模型。工作之外,她还积极参与数据科学社区,包括共同组织即将举行的minne AnalyticsWomen in Analytics and Data Science conference 等活动。你可以在 LinkedIn 和&Github 上找到 Renee。

使用几何 SMOTE 处理不平衡数据

原文:https://towardsdatascience.com/handling-imbalanced-data-using-geometric-smote-770b49d5c7b5?source=collection_archive---------47-----------------------

SMOTE 变体的几何方法

图 1 .作者随机生成的数据

在上面的图中,很明显,红色的点占多数,绿色的点占少数。少数数据的存在在异常检测、攻击和入侵检测、医学领域[癌症预测]和网络物理环境的研究中至关重要。但是数据样本中少数民族的数量是至关重要的。比方说,如果只有 0.01%的有用少数数据,通常算法会将其视为噪声或异常,并试图通过忽略这一点来提高准确性。如上所述,在许多情况下,不考虑少数群体数据样本比因其代表性不足而删除或忽略它们更为关键。

当类别样本的数量大致相等时,通常的机器学习算法工作得最好,并且通常朝着提高准确度和最小化误差的方向调整[1]

因此,基于这种说法,数据不平衡必须得到处理,因为当数据接近平衡时,算法会工作得更好,技术世界有许多方法来解决这一常见现象。

处理不平衡数据

我们可以通过算法和框架来解决不平衡数据的琐碎机器学习问题,这些算法和框架大致分为两个主要领域;预处理和代价敏感学习。重采样和特征选择是预处理方法的主要方式。

数据重采样:

这种方法修改了数据样本的数量,从而解决了偏斜类别分布或不平衡数据的不利影响。

  1. 过采样:过采样是添加少数类的更多副本。当您没有大量数据要处理时,过采样可能是一个不错的选择。但是过度的过采样可能会导致过度拟合。但是我们不会丢失有用的信息或特征。
  2. 欠采样:欠采样是去除多数类的副本。当有大量数据时,可以设计欠采样。但是这里主要关注的是我们删除了有价值的信息。这可能导致对测试集的拟合不足和泛化能力差。
  3. 混合:过采样和欠采样的适当混合。
  4. SMOTE:与过采样类似的技术,但这里我们合成新的少数数据样本。

重击

SMOTE 算法是由舒拉、鲍耶、霍尔和凯格尔迈耶在 2002 年提出的,作为随机过采样的替代方案。合成少数过采样技术(SMOTE)的思想是在相邻少数类实例之间进行插值。SMOTE 的任务是通过对数据进行随机重采样来克服过度拟合的问题,并继续协助泛化。SMOTE 能够通过在邻域中合成新的少数类样本来增加少数类实例的数量,从而帮助分类器提高泛化能力。

SMOTE 在少数实例之间生成新的少数样本。考虑两个少数点,算法沿着连接这些少数点的线生成新的少数样本。这是 SMOTE 算法的抽象视图。

k = nearest neighbours
n = no. of samples to be generated based on Imbalanced Ratio.

SMOTE 算法(k,n):

第一步:设置少数类集合 A. 对于每个属于 A 的 x,找到 x 的 k 个最近邻(通过计算 x 与集合 A)中每隔一个少数点的欧氏距离)

A = {x1,x2,…XT }&x1 的 k 近邻= {x6,x7,…xk} &相似

**第二步:**对于每一个属于 Ax,从其 k 个最近邻中选择 n 个少数点,它们构成集合 A1。

x1 的 x1 = { x7,x4,…xn}

**第三步:**为每个点 p 中的 A 生成一个新的样本

新点= p + rand(0,1) * |p-x1|

其中 rand(0,1)表示 0 和 1 之间的随机数

图 2 .作者对 SMOTE 功能的概述

SMOTE 仍然是一个有趣的工作,许多研究工作已经引入了 SMOTE 的变体,这些变体具有以它们自己的方式合成新的少数点的不同方法。SMOTE 的原始论文被引用超过 5000 次,开发 SMOTE 扩展的研究仍然是新鲜的。边界线-SMOTE(韩等,2005),安全级-SMOTE (Bunkhumpornpat 等,2009),DBM SMOTE(Bunkhumpornpat 等,2012),ROSE (Menardi & Torelli,2014),MWMOTE (Barua 等,2014),(Abdi & Hashemi,2016),Geometric SMOTE(Douzas 等,2017)就是相当多的例子。

我发现 Geometric SMOTE 很有趣,因为它利用几何来优雅地开发解决方案,识别和解决可能导致的潜在问题。虽然它被称为 SMOTE 的变体,但不是真正的扩展。它模仿合成新的少数样本的核心思想。几何 SMOTE 也是一种基于该原理和插值的算法。让我们进入几何 SMOTE 的症结。

几何 SMOTE

现有的 SMOTE 及其变体具有在合成少数样本时必须解决的各种问题,并且几何 SMOTE 已经确定了如下问题。

  1. 噪声示例的生成

当合成新的少数样本时,在多数聚类空间中合成特定样本的可能性更高。这种数据被称为噪声点。它们只能作为噪声融入集群。

图 3 .从几何 SMOTE 纸上获取的噪声样本的生成

在上面的图 3 中,噪声样本是选择x’作为应用 SMOTE 的最近点的结果。

图 4 .来自几何 SMOTE 纸的噪声样本-2 的生成

由于点的选择,还有另一种最终产生噪声样本的可能性。在图 4 中。由于x已经是一个噪声点,并且所选择的点也是噪声点,所以所生成的样本最终也是一个噪声样本。

图 5 .来自几何 SMOTE 纸的噪声样本-3 的生成

在上面的图 5 中,同样通过选择随机选择的xx’,生成的点落在多数簇内,并导致噪声样本的形成

2.属于相同子聚类的样本的生成导致过度拟合和不适当的表示。

图 6 .几乎相似样本的生成

这里,虽然不存在噪声样本的问题,但是生成属于一个少数子聚类的新样本会引入“聚类内不平衡”并导致原始数据的偏斜表示。并且高度密集的子群的新样本的生成将导致

G-SMOTE 的主要目标

Smote 在确定潜在泄漏后,确定了其主要目标,以解决一些问题和解决问题的机制。

  1. G-SMOTE 想要定义一个安全区域来合成新点。这是为了确保没有合成点被生成为噪声样本。
  2. G-SMOTE 希望增加生成的少数类样本的多样性。这将防止少数样本的相同子类的生成导致群内偏斜。

G-SMOTE 的参数

Smaj :多数类样本集。

Smin :少数类样本集。

N :要生成的合成样本总数。

k :最近邻数。

α_ trunc:1≤α_ trunc≤1 的截断因子。

α_ def:0≤α_ def≤1 的变形因子。

α_sel :带有α_ sel∈n {少数,多数,组合}的邻居选择策略

S_gen:生成的合成示例集。(输出)

算法

关于完整的算法和解释,请参考 G-SMOTE 论文。在这里,我希望用例子来解释算法,并抽象出来。

1.对 Smin 元素进行混洗,并初始化空集 Sgen

**Smaj = {smaj1,smaj2,smaj3,.......}
Smin = {smin1,smin2,smin3,........} -> after being shuffled
Sgen = {}**

2.重复,直到 Sgen 中生成 N 个少数实例:

**N = 0** - Have to run the procedure till N number of samples are generated

2.1.设 x_center ∈ Smin 所选的 p 组件的少数类实例。

- A minority point from Smin is chosen as the center of a geometric region**x_center** = **smin1**- The order of choosing the minority point will be the order of shuffled data points and in case of **N > size of Smin**, continue to re-run from the beginning again.

2.2.如果 α_sel = minority :

In **G-SMOTE** algorithm they defined 3 neighbor selection strategies ; minority,majority and mixed.- Find the k nearest neighbors of x_center from the set of Smin**k_nearest_neighbors = {smin6,smin5......}**- randomly select **x_surface** from the **k_nearest_neighbors x_surface = smin5**- Calculate a radius from the relation **R ← d(x_center, x_surface)**

2.3.如果 α_sel =多数:

- choose the nearest majority neighbor (from Smaj) of x_center **x_surface = smaj3**- Calculate a radius from the relation **R ← d(x_center, x_surface)**

2.4.如果 α_sel = mixed :

- Find the k nearest neighbors of x_center from Smin. **k_nearest_neighbors** = {smin6,smin5......}- randomly choose one from **k_nearest_neighbors smin6**- Calculate the euclidean distance **dmin ← d(x_center, smin6)**----------------------------------------------------------------- Find nearest majority neighbor of x_center from Smaj**xmaj= smaj3**- Calculate the euclidean distance **dmaj ← d(x_center, xmaj)**----------------------------------------------------------------- Calculate a radius from the relation **x_surface ← argmin (dmin, dmaj)****R ← d(x_center, x_surface)**----------------------------------------------------------------
**Note: Since d ≤ R ≤ dmaj; where d is distance from x_center to the generated sample
=> G**eneration of noisy samples is avoided

2.5.生成一个合成样本 x_gen ← hyperball(中心=0,半径=1)

图 7。生成 e_sphere

**hyberball**:- function is meant for creating the e-sphere- **e_sphere** is generated on the surface of a unit hyper-sphere 

2.6.通过 x_gen ← truncate(x_gen,x_center,x_surface,α_trunc) 变换 1 合成样本。

图 8 .α_ trunc 的截断效应

**Truncation:**- defined with bit of complex mathematics. But intuitively tells us which side of the hyper-sphere to be truncated to secure a safe space to generate a minority sample. - When **α_trunc** > 0, the area that is opposite to the x_surface is truncated from the interior of the hyper-sphere.- When **α_trunc** < 0, the truncation occurs in the area that includes the x_surface point.- **α_trunc v**alue is generally -1 to 1\. If it is -1.0, it truncates the exact **semi**-hyper sphere on the same side of surface point and truncates the opposite side  of **semi**-hyper sphere if **α_trunc equals** 1.0

2.7.通过 x_gen ← deform(xgen,xcenter,xsurface,α_def)变换 2 合成样本。

图 9 .变形对α_def 的影响

**Deformation:**
- corresponds to the deformation of the hyper-sphere in to a hyper-spheroid- **α_def** relates the story of hyper-plane that to be chosen on which the new minority sample will be synthesized- **α_def** typically takes value 0 to 1 allowing the Deformation method to choose the proper plane to place generated sample.

2.8.通过 x_gen ← translate(xgen,xcenter,R)转换 3 合成样本。

**Translation:**- translation of the generated point by the x_center vector and the resealing by the value of the radius R- return (x_center + R * x_gen)

图 10 .少数样本的生成

2.9.将生成的样本 x_gen 添加到生成的样本 S_gen 的集合中

**S_gen {x_gen}
N = N+1**

感谢阅读 G-SMOTE 到这一步。该博客旨在对 SMOTE 及其变体中的问题、G-SMOTE 算法和主要目标进行概述。看到 G-SMOTE 算法的缺点也很有趣,让我们在一个单独的博客中讨论它们。

参考

[1] Johnson,J.M .,Khoshgoftaar,T.M .关于深度学习存在类不平衡的调查。 J 大数据 6、 27 (2019)。https://doi.org/10.1186/s40537-019-0192-5

[2] N. V .舒拉, K. W .鲍耶, L. O .霍尔, W. P .凯格尔迈耶 (2011)。“SMOTE:合成少数过采样技术”

[3]圣乔治·杜萨斯和费尔南多·巴桑。(2017).几何 SMOTE:通过 SMOTE 的几何扩展实现不平衡学习的有效过采样。

[4] G. Douzas 和 F. Bacao,“几何 SMOTE 对 SMOTE 的一种几何增强的插入式替代”,信息科学,第 501 卷,第 118–135 页,2019 年。可用:10.1016/j.ins.2019.06.007

[5] G-SMOTE 实现—https://github.com/AlgoWit/geometric-smote

处理“缺失”数据?

原文:https://towardsdatascience.com/handling-missing-data-12ac7c59eebc?source=collection_archive---------29-----------------------

所有数据集都有个缺失值。

这些可以是难、未定义空— 的形式,也可能是别的什么?

但是我们该拿它们怎么办呢?我们应该删除这些行还是替换这些值?让我们看看如何以一种理智的方式摆脱这些缺失的价值观。

数据无处不在,但也有缺失值。[斯蒂芬·道森在 Unsplash 上拍照]

替换数据集中缺失的值称为数据输入

现在,一些数据科学的从业者可以说——对这些价值“不做任何事情”。但是不要这样做,大多数算法在遇到缺少值的数据时都会抛出错误。

让我们考虑一下熊猫的数据框架:

一个示例数据帧。[图片由作者提供]

那么,我们能做些什么来填补这些缺失的价值呢?

1.使用每列的“平均值”。

用每列的平均值填充 NaN 值。[图片由作者提供]

这是一个快速的解决方案,但是“均值”作为一个统计数据是不稳定的,并且它不能很好地与分类特征相适应。此外,如果数据是倾斜的,就不会考虑相关性。

这也会影响结果数据集的方差,因此要小心,如果训练 ML 算法时缺失数据用均值填充,这可能会导致较高的偏差。

2。使用每列中“最频繁”的值。

现在让我们考虑一个新的数据框架,一个具有分类特征的数据框架。

具有分类特征 1 和 2 的示例数据框。[图片由作者提供]

我们可以用众数来替换丢失的值——或者每列中出现最频繁的值。这同样没有考虑到相关性,并且由于不希望地将更多标签分配给特定类别,可能会在数据中引入偏差。

如何使用模式填充分类特征?[图片由作者提供]

但是上述方法主要适用于小数据集,如果您有一个大数据集呢?

大数据是不是变得太大了?[Giphy 的 GIF 图

让我们来看一个多了几行和几列的数据帧。

更大的数据框架。[图片由作者提供]

3.在每列中使用“内插法”。

现在让我们使用上面显示的数据框架,我们可以沿着每一列使用插值来填充缺失的值。

*但是插值有什么用呢?*它启动适合您数据的功能。然后,该函数可用于推断缺失数据的值。

在熊猫中有不同的插值策略,如线性多项式。请记住,如果您使用多项式策略,您将需要指定插值多项式的

2 阶多项式插值后的结果。[图片由作者提供]

它在计算上比我们上面介绍的两种方法更昂贵,但是取决于用于插值的策略;它能给出更好的结果。

4。使用其他方法,如 K-最近邻法。

上面显示的三种方法在 Pandas 的框架内工作。但是如果你可以访问其他像scikit-learn 这样的库,你也可以访问KNNImputer。让我们考虑将它与方法 3 中使用的数据帧一起使用。

KNNImputer的工作原理是每个新点如何与数据中的所有其他点相似。因此,通过检查数据集中的 k 个最近邻是否有缺失值,我们可以基于邻域或最近的“k 点”对它们进行估算。

总的来说,这种方法比上面提到的三种方法更加通用,因为它适用于所有类型的数据——连续数据、离散数据和分类数据。

结果使用邻居为 2 的 KNNImputer 后。[图片由作者提供]

如果您知道任何其他填充数据集中缺失值的常用方法,请在评论中注明。

我希望你觉得这篇文章有趣并且有用。

ℹ️ℹ️ℹ️ℹ️ℹ️ℹ️ℹ️ℹ️ℹ️ℹ️谢谢你!

处理缺失数据

原文:https://towardsdatascience.com/handling-missing-data-f998715fb73f?source=collection_archive---------51-----------------------

PyTrix 系列

PyTrix #7:处理缺失数据的各种技术

照片由埃米利亚诺·维托里奥西在 Unsplash 拍摄

在 PyTrix 的上一个系列(Pandas 的缺失数据一瞥)中,我们提到了缺失数据和使用 Pandas 框架检测缺失值;这是那一集的摘录“当我们观察到数据中缺少值时,这是因为没有数据值存储在观察的变量中。缺失数据在实践中极为常见,会对从数据中得出的结论产生很大影响,因此数据科学家的大部分时间都花在了数据清理上。”

尽管我们探索了检测缺失数据的方法,但是我们并没有给出一个明确的解决方案来解决这个问题。在这篇文章中,我希望介绍一些我认为有用的策略,因为这是 PyTrix,当然我会分享一些有用的 Python 代码,我们可以用它们来完成这些任务。

注意:可以通过下面的链接访问完整的笔记本。此外,这篇文章是直接从 Jupyter 笔记本上创建的——要了解我是如何做到的 点击这里

[## kurtispykes/演示

github.com](https://github.com/kurtispykes/demo/blob/master/pytrix/pytrix_handling_missing_data.ipynb)

我们将使用来自 Kaggle 的臭名昭著的泰坦尼克号数据集,点击此处即可访问。

import numpy as np
import pandas as pd# reading the data
df = pd.read_csv("../data/titanic_raw/train.csv")
df.tail()

图 1

我们可以在图 1 的年龄和客舱列中看到一些NaN值,但是通过这种方式查看我们的数据将很难看出我们有多少缺失的数据。更好的解决方案是使用df.info(),它将为我们提供每一列的非空计数和数据类型——参见文档

# information on the columns
df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):#   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  0   PassengerId  891 non-null    int64  1   Survived     891 non-null    int64  2   Pclass       891 non-null    int64  3   Name         891 non-null    object 4   Sex          891 non-null    object 5   Age          714 non-null    float646   SibSp        891 non-null    int64  7   Parch        891 non-null    int64  8   Ticket       891 non-null    object 9   Fare         891 non-null    float6410  Cabin        204 non-null    object 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB

所有列都有 891 个观察值,但我们在年龄列中只有 714/891 个非空观察值,在客舱列中有 204/891 个非空观察值,在上船列中有 889/891 个非空观察值。

在处理这些丢失的值之前,我必须指出,在理想情况下,我们应该对现有的数据进行深入分析,因为我们想首先了解数据丢失的原因。此外,在处理缺失值时,与领域专家交谈(如果你不是)也是一个重要的步骤,这样我们可以确保我们使用的任何技术都是合理的(从统计角度看),并且我们仍然可以从我们的模型中获得准确的预测。

原因很简单,如果缺失数据降低了样本的代表性,并因此扭曲了关于人口的推断,那么对于我们处理这个问题来说,确保我们的模型能够准确代表人口是至关重要的。

由于我们的目的是探索处理缺失数据的各种技术,我们可以假设前面的需求已经实现。

删除

处理丢失数据的最简单方法是删除它们。也称为列表式删除,在这种方法中,如果一行缺少一个值,我们将从分析中删除整行。

df2 = df.copy() print("Before removing rows with missing values")
print(df2.shape)
print("After removing rows with missing values")
df2.dropna(inplace=True)
print(df2.shape)Before removing rows with missing values
(891, 12)
After removing rows with missing values
(183, 12)

从我们的数据中删除行可能会带来更多的伤害,而不是公正。在这个例子中,我们删除了 708 行(占观察值的 20.5%),考虑到我们的样本大小,这是一个相当大的数据量。这是有问题的,因为减少数据量会降低我们分析的统计能力,因为这部分依赖于高样本量。

此外,如果缺失数据的原因不是随机的,如果我们决定进行列表式删除,我们将会在结果中产生偏差。非随机缺失数据的一个例子是当插入问题(例如,你挣多少?)在问卷中被问到。许多人可能不愿意分享这些信息,但回答其他问题却没有问题。这种偏见可能会发生,因为决定回答每个问题(包括干扰性问题)的人可能与不愿意回答干扰性问题的参与者有着非常不同的特征。

**注意:**如果变量丢失了大部分数据,我们可以创建一个二进制标志变量来表示丢失(1)或不丢失(0),并删除带有丢失值的初始列。

归罪

接下来的几项技术更侧重于插补,即使用替代值替换缺失数据的过程。尽管列表式删除因其简单性而成为处理缺失数据的最常见方式,但它也有缺陷。插补可以被视为避免这些陷阱的一种方法。

热甲板

这是从随机选择的相似记录中估算缺失值的地方。热卡插补的一种形式是最后一次观察结转(LOCF 插补)。LOCF 所做的是找到第一个缺失值,然后使用紧邻的前一个单元格的值来估算缺失值。这种方法符合这样一种信念,即最佳猜测是数据自上次测量以来没有发生变化。我们将用 Python 实现它。

# looking at the data before imputation
df_hot_deck = df.copy()
df[887:]

图 2

现在,我们将对该数据帧执行 LOCF,这将使用缺失值上方的单元格来估算所有缺失值

# looking at the data after imputation
df_hot_deck.fillna(method="ffill", inplace=True)
df_hot_deck[887:]

图 3

众所周知,使用这种方法估算数据会增加偏差的风险,并可能导致我们的数据得出错误的结论,因此通常不建议使用这种方法——我不太确定人们是否在实践中使用这种方法。

统计方法

从技术上讲,这可能不是用来描述这些技术的正确术语,但是我想要一个总括术语,它将捕捉我们可以使用统计来估算我们的数据的所有不同方式。常见的统计有均值、中值和众数。

# View all rows with a missing age
df3 = df.copy()
missing_age = df3[df3["Age"].isna()].indexdf3[df3["Age"].isna()]

图 4

# imputing all rows with missing age with the mean age
df3["Age"].fillna(df3["Age"].mean(), inplace=True)
df3.loc[missing_age]

图 5

均值插补减弱了任何涉及插补特征的相关性-保证插补变量和任何其他测量变量之间没有关系,这意味着这对于单变量数据来说可能是一种非常好的方法,但对于多变量来说不是很好-我们可以对分类数据使用模式值。

# current value counts of the embarked column
df3["Embarked"].value_counts(dropna=False)S      644
C      168
Q       77
NaN      2
Name: Embarked, dtype: int64# view rows with missing values
missing_embarked = df3[df3["Embarked"].isna()].index
df3[df3["Embarked"].isna()]

图 6

# fill the rows with missing values and view them
df3["Embarked"].fillna(df["Embarked"].mode()[0], inplace=True)
df3.loc[missing_embarked]

图 7

模型插补

同样,这可能是我用来命名这种现象的不好的术语。处理缺失数据插补的一种流行方法是使用模型来预测缺失值。尽管 kNN 已经被证明是非常有效的(通常被称为最近邻插补),但是有许多模型可供选择。

from sklearn.impute import KNNImputerX = df[["Survived", "Pclass", "Age", "SibSp", "Parch", "Fare"]].copy() knn_imputer = KNNImputer(n_neighbors=3)
filled_df = pd.DataFrame(data=knn_imputer.fit_transform(X),columns=["Survived", "Pclass", "Age", "SibSp", "Parch", "Fare"])
filled_df.loc[missing_age]

图 8

KNNImputer的文档声明“使用训练集中找到的 n_neighbors 最近邻的平均值估算每个样本缺失值。如果两个样本都不缺少的特征是接近的,则这两个样本是接近的。”。因此,我移除了所有对象数据类型,因为这将在此算法的中引发错误。

注意:也有其他算法内置了处理缺失值的方法,比如 XGBoost

如果您想与我联系,请在 LinkedIn 上留下回复或与我联系。

[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn

在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/kurtispykes/?originalSubdomain=uk)

处理缺失值专用 pythonic 指南

原文:https://towardsdatascience.com/handling-missing-values-the-exclusive-pythonic-guide-9aa883835655?source=collection_archive---------38-----------------------

入门

处理缺失值的 3 种最佳方法

Ehimetalor Akhere Unuabona 在 Unsplash 上拍摄的照片

对于大多数数据科学项目来说,处理缺失值是探索性数据分析(EDA)的关键步骤,无论是开发机器学习模型还是商业分析。包括 scikit-learn 在内的大多数库都不会使用带有缺失值的数据来构建模型。由于数据量巨大,找到获得最佳估算值结果的技巧是成为独角兽数据科学家的巨大优势。在本文中,我们将回顾 3 个最成功的开源短 python 代码行,它们可以组合起来处理缺失值。

在这篇文章中,我们将分析样本 flowers、titanic 和 house prices Kaggle 数据集,您可以在这里找到。

詹姆斯·巴尔在 Unsplash 上的照片

简介

有许多处理丢失值的场景,丢失的数字在 python 中通常表示为 nan ,这是“不是数字”的缩写。传统的方法是检测缺少值的单元格,并使用以下命令计算它们在每一列中的数量:

missing_val_count_by_column = (data.isnull().sum())print(missing_val_count_by_column[missing_val_count_by_column > 0

大多数 Kaggle 比赛中都有 3 种主要方法,让我们来回顾一下:

1。 效率较低:删除缺少值的列

删除缺少值的列的一种方法是在训练/测试数据帧中删除相同的列,如下所示:

从原始数据帧:

data_without_missing_values = original_data.dropna(axis=1)

通过训练,测试数据帧:

cols_with_missing = [col for col in original_data.columnsif original_data[col].isnull().any()]reduced_original_data = original_data.drop(cols_with_missing, axis=1)reduced_test_data = test_data.drop(cols_with_missing, axis=1)

删除丢失的值后,您的模型将无法访问该列,从而导致重要数据的丢失。但是,当列中的大多数值都丢失时,这种策略可能是合适的。

一个更好的选择:插补

比删除数据集列更好的选择是用数据分布平均值填充缺失值,如下所示:

from sklearn.impute import SimpleImputermy_imputer = SimpleImputer()data_with_imputed_values = my_imputer.fit_transform(original_data)

该选项通常集成在 scikit-learn 管道中,使用比平均值更复杂的统计指标。管道是简化模型验证和部署的关键策略。

3)最佳选择

最后一种策略是系统地随机填充缺失值。如果您需要获得最佳结果,您需要考虑您的列统计指标。下面是它可能的样子:

#制作副本以避免更改原始数据(输入时)

new_data = original_data.copy()

#制作新栏,说明将估算的内容

cols_with_missing = (col for col in new_data.columnsif new_data[col].isnull().any())for col in cols_with_missing:new_data[col + ‘_was_missing’] = new_data[col].isnull()

#插补

my_imputer = SimpleImputer()new_data = pd.DataFrame(my_imputer.fit_transform(new_data))new_data.columns = original_data.columns

在大多数情况下,这种方法会大大改善你的结果。

泽内普在 Unsplash 上的照片

案例分析

现在让我们用最著名的 Kaggle 数据集来练习。我们将回顾泰坦尼克号,花卉,价格住房卡格尔竞争数据集的例子。

为了掌握缺失值处理,我建议您使用本笔记本 遵循每个步骤,并对您的数据集重复相同的步骤。

照片由руслангамзалиев在 Unsplash 上拍摄

1.泰坦尼克

data = pd.read_csv(‘../input/titanicdataset-traincsv/train.csv’)

泰坦尼克号数据集(891 行× 12 列) ( 图片由作者提供)

from sklearn.ensemble import RandomForestRegressorfrom sklearn.metrics import mean_absolute_errorfrom sklearn.model_selection import train_test_splittitanic_target = data.Survivedtitanic_predictors = data.drop(‘Survived’, axis=1)

为了保持例子简单,我们将只使用数字预测器。

titanic_numeric_predictors = titanic_predictors.select_dtypes(exclude=[‘object’])X = titanic_numeric_predictors.select_dtypes(exclude=[‘object’])y = titanic_target

#在训练和测试数据集中划分数据。

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)

方法一

cols_with_missing = [col for col in X_train.columnsif X_train[col].isnull().any()]reduced_X_train = X_train.drop(cols_with_missing, axis=1)reduced_X_test = X_test.drop(cols_with_missing, axis=1)print(“Mean Absolute Error from dropping columns with Missing Values:”)print(score_dataset(reduced_X_train, reduced_X_test, y_train, y_test))

删除缺失值列的平均绝对误差:0.391340782122905

方法二

my_imputer = SimpleImputer()imputed_X_train = my_imputer.fit_transform(X_train)imputed_X_test = my_imputer.transform(X_test)print(“Mean Absolute Error from Imputation:”)print(score_dataset(imputed_X_train, imputed_X_test, y_train, y_test))

插补的平均绝对误差:0.394525139664804

方法三

imputed_X_train_plus = X_train.copy()imputed_X_test_plus = X_test.copy()cols_with_missing = (col for col in X_train.columnsif X_train[col].isnull().any())for col in cols_with_missing:imputed_X_train_plus[col + ‘_was_missing’] = imputed_X_train_plus[col].isnull()imputed_X_test_plus[col + ‘_was_missing’] = imputed_X_test_plus[col].isnull()

#插补

my_imputer = SimpleImputer()imputed_X_train_plus = my_imputer.fit_transform(imputed_X_train_plus)imputed_X_test_plus = my_imputer.transform(imputed_X_test_plus)print(“Mean Absolute Error from Imputation while Track What Was Imputed:”)print(score_dataset(imputed_X_train_plus, imputed_X_test_plus, y_train, y_test))

追踪插补内容时插补的平均绝对误差:0.382178770945

= >最好的方法是:方法 1

瑟奎拉在 Unsplash 上拍摄的照片

2.花

data = pd.read_csv(‘../input/flower-type-prediction-machine-hack/Train.csv’)

花卉数据集(12666 行× 7 列) ( 图片由作者提供)

from sklearn.ensemble import RandomForestRegressorfrom sklearn.metrics import mean_absolute_errorfrom sklearn.model_selection import train_test_splitflower_target = data.Classflower_predictors = data.drop(‘Class’, axis=1)

为了保持例子简单,我们将只使用数字预测器。

flower_numeric_predictors = flower_predictors.select_dtypes(exclude=[‘object’])X = flower_numeric_predictors.select_dtypes(exclude=[‘object’])y = flower_target

#在训练和测试数据集中划分数据。

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)

方法 1

cols_with_missing = [col for col in X_train.columnsif X_train[col].isnull().any()]reduced_X_train = X_train.drop(cols_with_missing, axis=1)reduced_X_test = X_test.drop(cols_with_missing, axis=1)print(“Mean Absolute Error from dropping columns with Missing Values:”)print(score_dataset(reduced_X_train, reduced_X_test, y_train, y_test))

删除缺失值列的平均绝对误差:1.316111627552926

方法二

my_imputer = SimpleImputer()imputed_X_train = my_imputer.fit_transform(X_train)imputed_X_test = my_imputer.transform(X_test)print(“Mean Absolute Error from Imputation:”)print(score_dataset(imputed_X_train, imputed_X_test, y_train, y_test))

插补的平均绝对误差:1.337274481525667

方法三

imputed_X_train_plus = X_train.copy()imputed_X_test_plus = X_test.copy()cols_with_missing = (col for col in X_train.columnsif X_train[col].isnull().any())for col in cols_with_missing:imputed_X_train_plus[col + ‘_was_missing’] = imputed_X_train_plus[col].isnull()imputed_X_test_plus[col + ‘_was_missing’] = imputed_X_test_plus[col].isnull()

#插补

my_imputer = SimpleImputer()imputed_X_train_plus = my_imputer.fit_transform(imputed_X_train_plus)imputed_X_test_plus = my_imputer.transform(imputed_X_test_plus)print(“Mean Absolute Error from Imputation while Track What Was Imputed:”)print(score_dataset(imputed_X_train_plus, imputed_X_test_plus, y_train, y_test))

追踪插补内容时插补的平均绝对误差:1.392727466344

= >最好的方法是:方法 1

巴黎歌剧院由阿莱西娅·科考尼在 Unsplash 演出

3.房价

data = pd.read_csv(‘../input/house-prices-advanced-regression-techniques/train.csv’)

住房数据集(1460 行× 81 列) ( 图片由作者提供)

from sklearn.ensemble import RandomForestRegressorfrom sklearn.metrics import mean_absolute_errorfrom sklearn.model_selection import train_test_splithouse_target = data.SalePricehouse_predictors = data.drop(‘SalePrice’, axis=1)

为了保持例子简单,我们将只使用数字预测器。

house_numeric_predictors = house_predictors.select_dtypes(exclude=[‘object’])X = house_numeric_predictors.select_dtypes(exclude=[‘object’])y = house_target

#划分训练和测试数据集中的数据。

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)

方法 1

cols_with_missing = [col for col in X_train.columnsif X_train[col].isnull().any()]reduced_X_train = X_train.drop(cols_with_missing, axis=1)reduced_X_test = X_test.drop(cols_with_missing, axis=1)print(“Mean Absolute Error from dropping columns with Missing Values:”)print(score_dataset(reduced_X_train, reduced_X_test, y_train, y_test))

删除有缺失值的列后的平均绝对误差:36860 . 48686863686

方法二

my_imputer = SimpleImputer()imputed_X_train = my_imputer.fit_transform(X_train)imputed_X_test = my_imputer.transform(X_test)print(“Mean Absolute Error from Imputation:”)print(score_dataset(imputed_X_train, imputed_X_test, y_train, y_test))

插补的平均绝对误差:18960 . 686868686867

方法 3

imputed_X_train_plus = X_train.copy()imputed_X_test_plus = X_test.copy()cols_with_missing = (col for col in X_train.columnsif X_train[col].isnull().any())for col in cols_with_missing:imputed_X_train_plus[col + ‘_was_missing’] = imputed_X_train_plus[col].isnull()imputed_X_test_plus[col + ‘_was_missing’] = imputed_X_test_plus[col].isnull()

#插补

my_imputer = SimpleImputer()imputed_X_train_plus = my_imputer.fit_transform(imputed_X_train_plus)imputed_X_test_plus = my_imputer.transform(imputed_X_test_plus)print(“Mean Absolute Error from Imputation while Track What Was Imputed:”)print(score_dataset(imputed_X_train_plus, imputed_X_test_plus, y_train, y_test))

追踪插补内容时,插补的平均绝对误差:18941

= >最好的方法是:方法 1

巴黎喷泉由熊伟·平托在 Unsplash 上完成

结论

如果你有空闲时间,我建议你读读这篇文章:

[## Kaggle 初学者 5 天数据清理挑战:第 1 天-处理缺失值

最大的数据科学平台 Kaggle 刚刚为数据初学者发起了为期 5 天的数据清理挑战…

medium.com](https://medium.com/@smeshram258/kaggle-5-day-data-cleaning-challenge-for-beginners-day-1-handling-missing-values-ee48b01e69cb)

总结

参考此链接,使用这些方法对这些数据集进行完整的缺失数据分析。

这个简单的概述提醒了在数据科学中使用 python 处理缺失值时使用多种方法的重要性。这篇文章涵盖了 3 个基本的 Python 处理缺失值,以创建一个完整的探索工作流,以及有用的文档。

歌剧《巴黎》由莱拉·格布哈德在 Unsplash 上演

希望你喜欢,继续探索!!!

用熊猫处理缺失值

原文:https://towardsdatascience.com/handling-missing-values-with-pandas-b876bf6f008f?source=collection_archive---------2-----------------------

关于如何检测和处理缺失值的完整教程

由 Unsplash 上的 chuttersnap 拍摄

数据科学项目中最耗时的部分是数据清理和准备。然而,有许多强有力的工具可以加速这个过程。其中之一是 Pandas,它是一个广泛使用的 Python 数据分析库。

处理缺失值是数据清理和准备过程中必不可少的一部分,因为现实生活中几乎所有的数据都带有一些缺失值。在这篇文章中,我将解释如何使用 Pandas 来检测丢失的值并以一种正确有效的方式处理它们。

让我们先创建一个缺少值的数据帧。

np.nan、None 和 NaT(对于 datetime64[ns]类型)是熊猫的标准缺失值。

**注意:**Pandas 1.0 中引入了一种新的缺失数据类型(< NA >),它是一种整数类型的缺失值表示。

np.nan 是浮点型的,所以如果你在一列整数中使用它们,它们将被转换成浮点数据类型,正如你在我们创建的 dataframe 的“column_a”中看到的。但是,可以和整数一起使用,不会导致向上转换。让我们使用向 dataframe 再添加一列,可以通过显式请求 dtype Int64Dtype()来使用它。

查找缺失值

Pandas 提供了 isnull()isna() 函数来检测缺失值。他们俩做着同样的事情。

df.isna() 返回带有布尔值的 dataframe,该值表示缺少的值。

也可以选择使用与 isna()正好相反的 notna()

df.isna()。any() 为每一列返回一个布尔值。如果该列中至少有一个值缺失,则结果为真。

df.isna()。sum() 返回每列中缺失值的数量。

处理缺失值

并非所有缺失的值都是简洁明了的 np.nan 或 None 格式。比如,“?”数据帧 c 列中的“---”字符没有给我们任何有价值的信息或见解,因此本质上它们是缺失值。但是,这些字符无法被熊猫检测为缺失值。

如果我们知道哪种字符用作数据集中的缺失值,我们可以在使用 na_values 参数创建数据帧时处理它们:

另一种选择是在创建数据帧后使用 pandas replace() 函数来处理这些值:

我们已经用 NaN 值替换了非信息单元格。就地参数保存数据帧中的变化。inplace 的默认值为 False,因此如果将其设置为 True,将不会保存更改。

没有处理缺失值的最佳方法。根据数据集和任务的特征,我们可以选择:

  • 删除缺少的值
  • 替换丢失的值

删除缺少的值

我们可以使用 dropna() 函数删除带有缺失值的行或列。如何用参数设置条件下降。

  • how='any ':如果有任何缺少的值,则删除
  • how='all ':如果所有值都丢失,则删除

此外,使用 thresh 参数,我们可以根据非缺失值的数量设置一个阈值,以便删除一行/一列。

thresh 参数要求一行或一列至少要有指定数量的非缺失值才能不被删除。例如,如果我们将 thresh 参数的值设置为 3,则一列或一行必须至少有 3 个非缺失值才不会被删除。没有 3 个或更多非缺失值的行或列(取决于轴参数的值)将被删除。

参数用于选择行(0)或列(1)。

我们的 dataframe 没有一行充满缺失值,因此设置 how='all '不会删除任何行。缺省值是' any ',所以如果我们想使用 how='any ',就不需要指定它:

至少有一个值缺失的行已被删除。

将 thresh 参数设置为至少有 3 个非缺失值的 3 个已删除行。

数据是宝贵的资产,所以我们不应该轻易放弃它。此外,机器学习模型几乎总是倾向于在更多数据的情况下表现更好。因此,根据具体情况,我们可能更喜欢替换丢失的值,而不是丢弃。

替换缺失值

fillna() 熊猫的功能方便处理缺失值。使用 fillna(),缺失值可以由特殊值或聚合值(如平均值、中值)替换。此外,缺失的值可以用它之前或之后的值替换,这对时间序列数据集非常有用。

  • 用标量替换丢失的值:

  • fillna()也可以用于特定的列:

  • 使用方法参数,缺失的值可以用它们之前或之后的值替换。

ffill 代表“向前填充”用前一行的值替换缺失的值。您也可以选择 bfill 代表“反向填充”。

如果一列或一行中有许多连续的缺失值,您可能希望限制向前或向后填充的缺失值的数量。

极限参数设置为 1,因此只有一个缺失值被向前填充。

感谢您的阅读。如果您有任何反馈,请告诉我。

我的其他帖子

  • 支持向量机—解释
  • 决策树和随机森林——解释
  • 用机器学习预测二手车价格
  • 数据清理和分析,附带一个奖励故事

ML 模型中多重共线性的处理

原文:https://towardsdatascience.com/handling-multi-collinearity-6579eb99fd81?source=collection_archive---------17-----------------------

提高线性回归模型可解释性的简单方法

图片来自 Unsplash

多元线性回归模型用于模拟响应/因变量和解释/自变量之间的关系。然而,多重共线性、误差项方差相关性、非线性等问题影响了模型的可解释性。本文将讨论多重共线性、多重共线性的影响以及处理多重共线性的技术。

什么是多重共线性?

当被假定为相互独立的解释变量被揭示为相互密切相关时,这种相关性被称为共线性。当观察到两个或更多解释变量的相关性时,称为多重共线性。

多重共线性尤其不可取,因为**它会影响线性回归模型的可解释性。**线性回归模型不仅有助于建立响应变量和解释变量之间的关系,还有助于确定每个解释变量对响应变量的个别影响。

因此,由于多重共线性的存在,很难分离出这些单独的影响。换句话说,多重共线性可以被视为一种现象,其中两个或更多的解释变量彼此高度线性相关,以至于一个解释变量可以从另一个解释变量以相当高的准确度预测。

多重共线性的影响

由于共线性/多重共线性的存在,很难隔离解释变量对响应变量的个别影响。

多重共线性会导致以下结果:

  1. **系数估计的不确定性或不稳定方差:**数据的微小变化(添加/删除行/列)会导致系数的变化。
  2. **标准误差增加:**降低估计的准确性,增加检测的机会。
  3. **统计显著性下降:**由于标准误差增加,t-统计下降,这对检测系数中的统计显著性的能力产生负面影响,导致 II 型误差。
  4. **缩减系数& p 值:**由于共线性,相关解释变量的重要性被掩盖。
  5. **过度拟合:**导致过度拟合,如高方差问题所示。

如何检测多重共线性?

除了观察上述影响的模型行为之外,多重共线性也在相关值中进行了定量捕捉。因此,可以使用以下内容:

相关矩阵:

数据中两个变量之间的皮尔逊相关性在-1 到 1 之间变化。两个变量的数据类型应为数值型,以便计算皮尔逊相关值。

这里,使用 r 的自动 MPG 数据集的相关矩阵。列名包含字符串,因此被删除。响应变量是 mpg,它代表燃油消耗效率。

#data = Auto
#generate correlation matrix in Rcorrelation_matrix <- cor(Auto[, -which(names(Auto) == "name")])

Autompg 数据集的相关矩阵;作者图片

可以观察到气缸和排量、马力和重量之间的高度相关性。此外,还有几对具有高度正/负相关性的解释变量。因此,存在多重共线性。

然而,正如人们会注意到的,对 8 个变量来说,浏览表格并识别这些变量是令人厌倦的,而且随着变量数量的增加,情况只会变得更糟。因此,关联热图是更直观的关联表示。

关联热图:

关联热图通过调整正负关联的颜色和大小来帮助更好地可视化数据。

在 R 中,corrplot 包可以用来创建相关性的热图。

library(corrplot)
corrplot(correlation_matrix, type = "upper", order = "hclust", tl.col = "black", tl.srt = 45)

Autompg 数据集的关联热图;作者图片

热图无疑更加直观和可视化。但是,它有助于严格识别 2 个变量之间的相关性,而无法识别 3 个或更多变量之间存在的共线性,对此可以使用方差膨胀因子。

方差膨胀因子(VIF): VIF 是拟合完整模型时系数估计的方差除以系数估计的方差(如果单独拟合的话)的比值。最小可能值为 1,表示没有共线性。如果值超过 5,则应解决共线性问题。

library(rms)
multiple.lm <- lm(mpg ~ . -name, data = Auto)
summary(multiple.lm)
vif(multiple.lm)

Autompg 数据集的 VIF 值;作者图片

气缸、排量、马力和重量的 VIF 值远高于 5,因此应该处理,因为数据中的共线性很高。

处理多重共线性

多重共线性可以用以下两种方法处理。注意,自变量之间的这种相关性会导致数据冗余,消除这种冗余有助于消除多重共线性。

  1. **引入惩罚或删除高度相关的变量:**使用 lasso 和岭回归来删除提供冗余信息的变量。这也可以通过观察 VIF 来实现。
  2. **组合高度相关变量:**由于共线变量包含冗余信息,使用 PCA 等方法将其组合成单个变量,生成自变量。

对于在 R 中实现的 Autompg 线性回归模型,请查看这个 Github 库。 该库探究多重共线性以及线性回归模型的交互项和非线性转换。

参考:

R 中的统计学习导论。

使用轮廓分析处理聚类中的异常值

原文:https://towardsdatascience.com/handling-outliers-in-clusters-using-silhouette-analysis-5a7d51118dac?source=collection_archive---------14-----------------------

从 K 均值聚类中识别并移除每个聚类中的异常值

图片由皮克斯拜的 Gerd Altmann 提供

现实世界中的数据通常有很多异常值。异常值的原因可能是数据损坏或未能记录数据。异常值的处理在数据预处理过程中非常重要,因为异常值的存在会妨碍模型发挥最佳性能。

有各种策略来处理数据集中的异常值。本文将介绍如何在使用剪影分析将数据聚类成几个簇之后处理异常值。

轮廓分析:

剪影法是一种寻找最佳聚类数以及解释和验证数据聚类一致性的方法。剪影方法计算每个点的剪影系数,该系数测量一个点与其自己的聚类相比与其他聚类相似的程度。通过提供一个简洁的图形表示来显示每个对象的分类情况。这些图形表示的分析被称为轮廓分析

剪影值是一个衡量对象与其自身聚类(内聚)相比与其他聚类(分离)相似程度的指标。轮廓值的范围在[1,-1]之间。

**Important Points:
The Silhouette coefficient of +1** indicates that the sample is far away from the neighboring clusters.
**The Silhouette** coefficient **of 0** indicates that the sample is on or very close to the decision boundary between two neighboring clusters.
**Silhouette** coefficient **<0** indicates that those samples might have been assigned to the wrong cluster or are outliers.

计算轮廓系数:

求第 I 个点的轮廓系数的步骤:

  1. 计算 an (i):该点与同一聚类中所有其他点的平均距离。
  2. Compute b(i):该点与离其聚类最近的聚类中所有点的平均距离。
  3. 使用下述公式计算 s(I)-轮廓系数或第 I 点。

(图片由作者提供),a(i)和 b(i)的图解表示,根据上述公式计算轮廓系数— s(i)

使用轮廓分析找到“k”的最佳值:

使用剪影法寻找最佳的聚类数。也可以用肘法找到,但剪影法被认为是比肘法更好的方法。阅读以下文章了解更多信息:

[## 轮廓法——比肘法更好的寻找最优聚类的方法

k-Means 聚类中寻找最优聚类的剪影法深度分析

towardsdatascience.com](/silhouette-method-better-than-elbow-method-to-find-optimal-clusters-378d62ff6891)

(图片由作者提供),**左:**平均距离与聚类数,**右:**剪影得分与聚类数

轮廓图显示了一个聚类中的每个点与相邻聚类中的点的接近程度,从而提供了一种视觉评估聚类数量等参数的方法。

轮廓分析的关键要点:

  1. 从不同 n_clusters 值的侧影线图和侧影分析,观察到 n_cluster=3 是聚类数(k)的最佳值。
  2. 在上面的“剪影分析,用于对样本数据进行 KMeans 聚类,n_clusters=3 ”的图像中,观察到所有聚类[0,1,2]的大部分点的剪影系数大于平均剪影分数。
  3. 在上面的“对样本数据进行 KMeans 聚类的剪影分析,n_clusters=3 ”的图像中,可以观察到,对于 cluster_label 2,很少有点具有负剪影系数,可以将其视为异常值。同样对于 cluster_label 1,一些点的轮廓系数小于平均轮廓得分,这些点位于远离其聚类中心的聚类边界上。

要查找异常值,请查找具有负轮廓系数的点,并将其移除。位于远离聚类中心的聚类边界上的点也可以被移除以创建健壮的模型,但是这取决于案例研究。

阅读 本文 获得剪影分析的深潜解释,参考 要诀 获得 python 代码实现。

参考资料:

[1]维基百科:剪影(聚类),(2020 年 9 月 14 日)

[2] Scikit 学习文档:通过对 KMeans 聚类进行轮廓分析来选择聚类数

感谢您的阅读

熊猫分组及其多指标处理

原文:https://towardsdatascience.com/handling-pandas-groupby-and-its-multi-indexes-efae3e6b788c?source=collection_archive---------17-----------------------

熊猫群入门

Pandas groupby 方法产生了几个级别的索引和列

Pandas 被认为是任何使用 Python 的数据科学家的必备工具。一个常用的特性是groupby 方法。然而,那些刚刚过渡到 pandas 的人可能会觉得有点困惑,尤其是如果你来自 SQL 的世界。

为了比较,我们先来看看GROUP BY在 SQL 中是如何工作的。我们将使用几个部门的手术数据集,其中包含手术时间的信息:

要获得 SQL 中过程的平均长度:

SELECT department, procedure_name, COUNT(*) AS count, AVG(procedure_minutes) AS length 
FROM cases
GROUP BY procedure_name
ORDER BY department

ORDER BY 部门允许我们对属于同一个部门的程序进行分组。

输出:

这几乎相当于熊猫使用groupby:

gp = cases.groupby(['department','procedure_name']).mean()
gp

输出:

如您所见,我们遗漏了计数列。通过直接调用mean函数,我们不能插入多个聚合函数。让我们通过使用agg 函数来解决这个问题:

gp = cases.groupby(['department','procedure_name']).agg(['mean', 'count'])
gp

输出:

太好了,现在这个看起来更熟悉了。注意程序 _ 会议记录标题与部门程序 _ 名称标题不对齐。这就是我们开始看到 SQL 表和 pandas 数据帧之间差异的地方。

在 SQL 中,从查询派生的每个新表都由列组成。熊猫里有索引栏目。索引类似于 SQL 的主键列,它唯一地标识表中的每一行。然而,熊猫数据帧可以有多个索引。在这种情况下,部门程序名都是索引

要使用索引找到一行,我们只需使用.loc 方法一个接一个地传递索引:

gp.loc[`Cardiology’,‘Pericardiocentesis’]

输出:

在 SQL 中,使用AS语句重命名*‘过程名称’,**‘计数’‘过程长度*’列非常简单。因为 pandas 有索引,重命名它们有点棘手。要重命名索引:

gp.index.rename(['Department','Procedure'],inplace=True)
gp

输出:

由于这些列有多个级别,重命名它们需要更多的努力:

gp.columns.set_levels(['Length'],level=0,inplace=True)
gp.columns.set_levels(['Count','Mean'],level=1,inplace=True)
gp

输出:

尽管与 SQL 相比,命名列很复杂,但是 pandas 有很多优点。在这篇文章中探索一切可能太长了,但是这里有一个简单的。请注意,甲状腺切除术既可以是耳鼻喉科也可以是普通外科手术。为了获得两个部门的甲状腺切除术的平均值:

gp.xs('Thyroidectomy', level=1)

输出:

但是,如果您仍然喜欢类似于好的 ol' SQL 的表,只需传入 reset_index :

gp.reset_index(inplace=True)
gp

输出:

这就对了,熊猫分组方法入门。希望有所帮助!

机器学习:处理数据中的缺失值:简单的方法

原文:https://towardsdatascience.com/handling-the-missing-values-in-data-the-easy-way-9ea5983f8ba4?source=collection_archive---------15-----------------------

SciKit 估算器简介

由在 Unsplash 上拍摄的

大多数机器学习算法不能处理特征中的缺失值。参见下面墨尔本住房数据的例子。

墨尔本 _ 数据.描述()

这里,BuildingArea 有 7130 行有值,而大多数特性有 13580 行有值。

现在,您可以做一些事情来处理缺失值

1.去掉相应的数据

**melbourne_data.dropna(subset=["BuildingArea"])**

这将删除所有缺少值的行。您可以看到现在行数减少了。

墨尔本 _ 数据.描述()

2.去掉整个属性。

**melbourne_data.drop("BuildingArea", axis=1)**

这将删除整个要素/属性。见下图,建筑面积列现已删除。

墨尔本 _ 数据.描述()

3.将缺少的值设置为某个值

接近 A

如果您认为该属性足够重要,并且必须包含在培训中。您可以填充缺少的值。

用什么填充缺失的值???

你可以用中间值、平均值或零来代替缺失值。

**median = melbourne_data["BuildingArea"].median()
melbourne_data["BuildingArea"].fillna(median, inplace=True)**

这将用计算出的中值替换所有缺失的值。此外,现在您会注意到一件事,即当我们填充了缺少的值时,属性的平均值发生了变化。

墨尔本 _ 数据.描述()

对于**“year build”**属性,您也可以遵循类似的过程。您将不得不保存中间值,因为稍后需要它来填充测试集和新数据中缺失的值(哦,是的,我没有想到)。

方法 B: 引入估算器

SciKit-Learn 提供了 Imputer 类来轻松使用上述任务。您可以按以下方式使用它:

首先,你需要决定策略,它可以是这些策略之一:均值、中值、最频繁

其次,使用决定的策略创建估算器实例

# 1\. Remove categorial 
melbourne_data = melbourne_data.select_dtypes(exclude=   [**"object"**]).copy()# 2\. Fit the numerical data to Imputer
**from** sklearn.impute **import** SimpleImputer
imputer = SimpleImputer(strategy=**"median"**)
imputer.fit(melbourne_data)# 3.
X = imputer.transform(melbourne_data)
melbourne_data_tr = pd.DataFrame(X, columns=melbourne_data.columns, index=melbourne_data.index)

现在,这将计算所有属性的中值,并用各自的平均值填充属性的缺失值。

melbourne_data_tr.describe()

**注意:**不关注类别值,因为它们不在本教程的范围内。

Github 上的代码

Python 代码 : 全文 python 代码用三种方式全部解释。

细流码 : 哦..你也喜欢细流。在此找到 streamlit 代码

数据 : 二手墨尔本房价数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/71824.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

约80%开发效率提升,原生鸿蒙政务、文旅行业样板间专区上线

10月8日,华为官方正式宣布,其最新操作系统HarmonyOS NEXT于当日10:08正式开启公测。 为有效助力开发者加速行业应用开发,华为开发者联盟生态市场(简称生态市场)近日上线了原生鸿蒙政务行业、文旅行业“样板间”专区。政务和文旅行业作为数字化转型的重要领域,对数智应用的…

TowardsDataScience-博客中文翻译-2020-四十五-

TowardsDataScience 博客中文翻译 2020(四十五)原文:TowardsDataScience Blog 协议:CC BY-NC-SA 4.0基于 Avro 模式的类固醇弹性研究原文:https://towardsdatascience.com/elasticsearch-on-steroids-with-avro-schemas-3bfc483e3b30?source=collection_archive---------…

一站实现高效开发,鸿蒙生态伙伴模板组件专区全新上线

10月8日,华为官方正式宣布,其最新操作系统HarmonyOS NEXT于当日10:08正式开启公测。 鸿蒙生态的发展离不开丰富的鸿蒙原生应用,为了有效提升开发者开发效率,降低开发成本,华为开发者联盟生态市场近日上线了“鸿蒙生态伙伴模板&组件专区”,汇聚官方及三方生态伙伴针对政务…

TowardsDataScience-博客中文翻译-2020-三-

TowardsDataScience 博客中文翻译 2020(三)原文:TowardsDataScience Blog 协议:CC BY-NC-SA 4.0做出更好决策的 3 个要素原文:https://towardsdatascience.com/3-essentials-to-make-better-decisions-9b2cdc60365e?source=collection_archive---------47---------------…

git怎么查看每次的提交记录控制台输出日志乱码

今天来和各位小伙伴分享一下怎么查看git的每次提交(commit)的记录: 1.打开idea ——2.点击做下加的git ——3.点击log ——4.选择自己的分支 ——5.查看每次提交的代码 二、控制台log4j输出的日志乱码: 解决办法: 1、将图中几处地方变为urf-8 2、

How to create a PDF programming cheat sheet All In One

How to create a PDF programming cheat sheet All In One 如何创建 PDF 编程备忘单 / 速查表How to create a PDF programming cheat sheet All In One如何创建 PDF 编程备忘单 / 速查表tools vscode pdf 编辑器 solutionsExport web page to pdf / 网页导出为 pdf优点:可以高…

基础靶场搭建

为什么要搭建靶场? 在我们后续的学习当中会涉及到漏洞的利用,那我们小白肯定是不能直接实操哒(如果你很刑就当我没说)所以就找了几个靶场进行搭建,我们这里搭建几个比较简单具有针对性的靶场进行练习后续更新完了十大漏洞,在上有难度的靶场😁😁😁 phpstudy搭建 201…

监控下抽烟检测系统

监控下抽烟检测系统具有以下优势:监控下抽烟检测系统通过视频监控设备对工地和工厂的作业区域进行实时监测,准确捕捉人员抽烟的行为。监控下抽烟检测系统采用先进的图像识别技术,能够准确识别人员抽烟的动作和烟雾。监控下抽烟检测系统一旦系统发现有人员在禁烟区域内抽烟,…