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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

如果你没有发现任何新的东西,你就没有做好 EDA

原文:https://towardsdatascience.com/if-you-dont-find-anything-new-you-don-t-do-eda-right-d356f9995098?source=collection_archive---------72-----------------------

更好的 EDA 指南

进行探索性数据分析或 EDA 的目的是在数据中发现新信息。从业者可能没有意识到的对 EDA 的理解是,EDA 使用直观检查的数据集来理解和总结数据集的主要特征,而无需事先假设或依赖统计模型。

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

照片由 Unsplash 上的 Aswathy N 拍摄

EDA 是制定新假设之前的关键步骤,然后可以使用后续分析对新数据集进行测试。做 EDA 的最大好处只有当它从数据集中检测到预期的并发现意外的时候才能实现。

最有趣的问题是如何解释可视化中的有趣模式,这些模式可以是图表、图形或地图的形式,并描述是什么导致了您观察到的模式。

考虑名为“对抗 20 世纪传染病:疫苗的影响的互动图片:

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

照片由华尔街日报

首先,我们马上注意到的是配色方案。只要看看颜色和写着疫苗引入的线,就已经提供了疫苗起作用的证据。

这就是我们在 EDA 阶段对可视化的期望,它是对数据的表示、探索和呈现,以促进理解。使一个 EDA 与另一个不同的是,它产生的可视化可以使理解变得容易。

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

照片由伯纳德·赫尔曼Unsplash 上拍摄

就像我说过的,可视化只是 EDA 的产物。更好的可视化形式是交互式的。单个可视化一次只能表示一个方面。在包含多个交互式可视化的仪表板中,用户可以使用多个表示来工作和指导、选择、筛选。只需点击链接,就可以使用简单的指示板进行操作,该指示板允许您交互式地播放各种时间方面的记录。

为什么想出有效的 EDA 这么难?你可以说,好吧,让我们导入一些库,然后画些东西。

能有多难?

因为数据有无数种可能的可视化表示。你的目标应该是创建有效的可视化效果,让用户无需更多解释就能真正理解。

制定 EDA 战略

制定 EDA 策略的方法有很多,取决于你的创造力水平。然而,良好的开端是检查您的数据并理解组成数据集的不同数据类型。

那么,到底是什么数据类型呢?它可以解释为以结构化的方式解释数据的方式。这里的数据类型不是指我们从编程中知道的数据类型的定义。

其次是任务抽象。让我给你一个例子来解释“任务”在可视化中意味着什么,以及为什么要抽象。“任务”做的第一件事是,当我们执行 EDA 时,它证明了使用可视化的合理性。有些人可能认为,当它勾选了指南中出现的所有检查清单时,就创建了一个完美的可视化,但是如果它没有提供洞察力并回答用户最初提出的问题,那么无论它有多漂亮,它对用户都没有多大用处。

这就是用户的“任务”的重要性。当用户想要分析数据时,考虑用户来自的领域,确定用户如何思考

我希望你能从这篇文章中学到一些新东西。

感谢您的阅读。对于任何想法或反馈,请随时通过给我的 Linkedin 发送消息来与我分享!

https://www.linkedin.com/in/faizfablillah/➡️

如果你认为 GPT-3 让编码员过时了,你可能就不会写代码了

原文:https://towardsdatascience.com/if-you-think-gpt-3-makes-coders-obsolete-you-probably-do-not-write-code-25fbc6461362?source=collection_archive---------14-----------------------

意见

反驳数据科学家和开发人员过时

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

来自 Pexels 的 Andrea Piacquadio 的照片

这是一篇观点文章。我很想在下面的评论中听到你的反驳。

乍一看,GPT 3 号可能是人类编写代码的终结。

虽然具有开创性,但得出软件工程师已经过时的结论还为时过早。

但是那些以写代码为生的人已经知道这一点了。

以下是开发人员留下来的几个原因。

开发人员写代码没有报酬

我们解决问题是有报酬的。

代码是解决问题的一种手段,但它也是一种繁重的工作和不可避免的罪恶。

代码不是解决方案,它是解决方案的实现

编写代码是开发人员最容易的部分。鉴于多层次的限制,澄清和解决一个问题要困难得多。

这就是写代码和写软件的区别。

GPT-3 太复杂,无法扩展

GPT-3 需要大量的专业知识,对个人和小企业来说运行起来太昂贵了。

API 底层的模型非常庞大,需要大量专业知识来开发和部署,并且运行起来非常昂贵。这使得除了大公司之外的任何人都很难从底层技术中受益。

OpenAI 给出了这个模型只能通过 API 获得而不能开源的三个原因之一。

它是巨大的。在1750 亿个参数,GPT-3 让“只有”15 亿个参数的 GPT-2 相形见绌。

鉴于穆雷斯定律的死亡,在不久的将来,我们不会看到这样的模型在个人电脑上运行。

也就是说,我认为这是一个暂时的问题。模型只能变得如此之大,但仍然具有成本效益。在某种程度上,我们将不得不开发更小/更智能的模型,即使这需要完全不同的硬件。

我们还不信任人工智能

银行或军事技术中的错误代码显然是有问题的。

但是你的普通网络应用程序中的安全漏洞也可能是灾难性的(比如 T4 的 Equifax T5)。

正如我们在自动驾驶汽车上看到的那样,在我们信任人工智能之前,它必须比最好的人类更好。

围绕自动驾驶汽车的最大问题之一不是技术问题,而是哲学问题:有多安全才算足够安全?

人类通常将这种约束应用于高风险领域。但是考虑到 2020 年代码会渗透到大部分技术中,有很大的下降空间。

从技术上讲,我们可以通过审查 AI 的代码来克服这一点。但是当人类再也看不懂代码的时候会发生什么呢?

没有“软件工程师”,所有技术都是黑箱

如果不再有人编码,我们能理解 AI 写的代码吗?

有了 AI 写软件,我们就不会投入擅长它所需的数千小时。如果不擅长,怎么复习。

在这个知识丢失的场景中,所有技术本质上都变成了一个黑盒。

作为一个社会,我们是否愿意走到这一步?

在一个不太遥远的场景中,第三方拥有的人工智能和人类无法维护的代码的组合感觉像是一个巨大的商业风险。

GPT-3 创建了无代码编码的文本接口

GPT 三号创建了一个布局生成器

虽然在无监督学习的背景下令人印象深刻,但通过文本放置按钮的能力感觉像是人工智能编写代码的一个非常小的胜利。

  1. 自 90 年代以来,我们就有了产生 HTML 和 CSS 的拖放式 web 编辑器。
  2. 代码自动化自从软件出现以来,代码就一直存在并不断发展。

甚至像 Ruby on Rails 这样的框架也是为了节省时间而设计的,它们在应用程序开发过程中尽可能多地构建通用代码。

因此,虽然我怀疑 GPT 3 号很快会有更复杂的用例,但我们目前看到的并不完全是软件工程师的工作。

结论

首先,撇开反驳不谈,GPT-3 是不可思议的。如果我们没有不断提高标准,我们可能已经认为这是“真正的人工智能”了。

其次,虽然我相信写代码会一直存在,但是花更少的时间写代码是一件很棒的事情。

不像盖房子,有无限多的代码要写,有无限多的问题要用技术来解决。

将编码委托给人工智能的能力给了工程师处理更多问题的带宽。

如果您的 Python 代码抛出错误,请先检查这些内容

原文:https://towardsdatascience.com/if-your-python-code-throws-errors-check-these-things-first-a93d8a9036f1?source=collection_archive---------26-----------------------

忘记关闭大括号或添加缩进?许多错误都有一个简单的修复方法

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

Python 不需要成为你的敌人。作者图片

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 F 快失败,早失败——我们都听说过这句格言。尽管如此,当你写了一段漂亮的代码,却发现它并不像你预期的那样工作时,还是会很沮丧。

这就是单元测试的用武之地。检查你的每一段代码有助于你定位和修复你的错误。

但并非所有的缺陷都是一样的。有些 bug 是意想不到的,根本看不出来,即使是有经验的开发人员也很难修复。这些更有可能发生在大型复杂的项目中,尽早发现它们可以为您节省大量的时间。

其他错误是微不足道的,比如当你忘记了一个右括号或者弄乱了一些缩进。它们很容易修复,但是很难发现,特别是当你已经在代码上工作了一段时间或者在深夜的时候。

一旦你发现了这样一个 bug,这就有点像掌脸时刻了。你可能会因为没有早点发现这一点而自责不已——并且你会想当初为什么会犯下如此愚蠢的错误。他们也不是你希望你的同事在你之前发现的那种错误。

[## Python 初学者应该避免的 4 个常见错误

我很艰难地学会了,但你不需要

towardsdatascience.com](/4-common-mistakes-python-beginners-should-avoid-89bcebd2c628)

首先要检查的愚蠢但常见的错误

我不能说这个列表涵盖了你可能会犯的所有愚蠢的错误。然而,定期使用它至少可以帮助您消除最常见的错误。

忘记右括号了吗?

每个人都会遇到这种情况——你快乐地编码,在编码的过程中,你忘记了关闭数组、参数列表或任何你正在处理的东西。

一些开发人员一打开右大括号就键入右大括号,然后填充中间的空格。大多数现代 IDE 也自动关闭牙套——因此,如果忘记牙套是你的一种慢性病,你可能会考虑放弃你的旧 IDE。

你的结肠呢?

嘿,我们每个人都会遇到这种事。您正在构造一个新的类,由于它很复杂,您在键入代码时已经在考虑类的内容了。哎呀,你忘了结尾的冒号:

class SillyMistake():
    def AvoidThis():
        print("Don't do silly mistakes!")

一个很好的经验是,如果你要增加一行的缩进量,你需要在它前面的那一行加一个冒号。

你是否混淆了等式和赋值运算符?

什么时候用=,什么时候用==?根据经验,如果你正在检查或比较两个值,你将使用==。另一方面,如果你给一个变量赋值,你将使用=

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

在你对错误感到恐慌之前,检查一下那些微不足道的错误。作者图片

你是否混淆了易变的表达式?

看看这个:

def NotRecommendedCode(item, new=[]):
    new.append(item)

这本身没有错,但是如果你不小心的话,你会遇到麻烦的。将参数列表中的数组[]定义为可变的意味着它将被修改以用于将来的调用

但是你可能每次都想从一个空数组开始。这更好:

def RecommendedCode(item, new=None):
    if new is None:
        new **=** []
    new.append(item)

Python 是区分大小写的,记得吗?

这是非常琐碎的事情,但却经常发生。假设您已经定义了变量CamelBucket,稍后在代码中调用camelbucket

没用,是吧?很有可能,您非常清楚 Python 是区分大小写的,但是您只是忘记了按 shift 键。

大多数现代的 ide 可以通过提出聪明的建议来帮助你避免这个错误。因此,如果你容易打字错误,你可以考虑升级你的文本编辑器。

[## 为什么开发人员会爱上函数式编程

从 Python 到 Haskell,这种趋势不会很快消失

towardsdatascience.com](/why-developers-are-falling-in-love-with-functional-programming-13514df4048e)

你在迭代列表的时候修改列表了吗?

这可能发生在每个初级开发人员身上:你已经建立了一个列表,现在你想改变一些事情。没什么大不了的,对吧?

不对。考虑一下这个:

mylist = [i for i in range(10)]
for i in range(len(mylist)):
    if i%2==0: del mylist[i]

剧透:这抛出了一个错误,因为你最终迭代了一个不再存在的列表中的条目。与其从现有列表中删除,不如考虑写入一个新列表。

你有循环模块依赖吗?

这是如此琐碎,但也是常见的:在一个文件中,比如说bug.py,你写import anotherbug。在另一个文件anotherbug.py中,你写import bug

这是行不通的——计算机怎么知道哪个文件包含在哪个文件中呢?你可能知道这一点,但这样做是偶然的。没关系,但是尽快修理它!

你还没有像 Python 的标准库那样命名你的模块,对吧?

关于模块的另一件事:Python 附带了大量惊人的库模块。但是如果你需要创建你自己的,一定要给他们一个原始的名字。

例如,定义一个名为numpy.py的模块会导致混乱。如果您不确定可以使用哪些名称,这里有 Python 标准库的完整列表

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

一天一个好习惯,代码医生远离我。作者图片

如何避免愚蠢的错误

你从错误中学习。作为一名初级开发人员,您可能每天都在犯这样的错误。但是随着时间的推移,它们变得越来越少。

你也可以更进一步,养成一些健康的习惯,这样你就不会犯小错误了。这些只是许多技巧中的一小部分,但是它们可以帮助你避免许多错误。

总是初始化变量

如果你定义了一个变量并且直到后来才赋值,Python 代码可以完美地工作。因此,每次在定义时初始化它们似乎很麻烦。

但是不要忘记你也是人,因此你很容易忘记哪个变量被赋值了,哪个没有。此外,初始化变量迫使您考虑您正在处理的变量的类型,这可能会防止以后出现错误。

这就是为什么许多经验丰富的开发人员用默认值初始化每个变量,如0None[]""等等。

当然,如果你只是想绑定一个小的独立脚本,而不是在一个庞大的项目上工作,你可以允许自己快速草率地做事。但是当事情变得复杂时,记得要勤奋。

用大括号调用函数,避免麻烦

又是牙套。不知何故,它们与人类大脑的迟钝不相容。

在 Python 中,你总是需要像这样调用函数:callingthisfunction(),而不是像这样:notcallingthisfunction,不管有没有参数。听起来微不足道,但并不总是如此!

例如,如果您有一个名为file的文件,并且您想用 Python 关闭它,那么您将编写file.close()。但是,如果您编写file.close,代码将运行而不会抛出错误——除了它不会关闭文件。试着在一个有数千行代码的项目中找出这样的错误…

经过几天的练习,它变得相当自动,所以从今天开始:函数总是用括号调用!

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

虫子可能会令人生畏,但随着时间的推移,你会学会避开它们。作者图片

导入模块时不要使用扩展

同样,这是相当琐碎的,但经常被初学者忘记。如果你正在调用一个模块,你将永远不会使用一个扩展,不管它是来自 Python 标准库还是其他地方。

因此,请注意类似这样的语句:

import numpy.py         *# don't do that!!!*

删除那个.py扩展名,并像避开臭味一样避开它。扩展和导入不能一起工作。

一致缩进

同样,您可能知道自己需要在整个文件中以同样的方式建立索引。但是,当你与他人合作或在深夜时,这仍然是一个常见的陷阱。

在开始编码之前,决定是使用制表符还是空格,以及使用多少空格。最常见的约定是四个空格,但是您可以做任何最适合您的事情——只要您在整个文档中保持它。

另一方面,如果您在一行中使用空格,在另一行中使用制表符,有时 Python 不会像您预期的那样处理它。我知道这看起来像是一个愚蠢的工作,但是尽你所能努力去做。

[## 面向对象编程已经死了。等等,真的吗?

函数式编程的鼓吹者们,你们把枪口对准了错误的敌人

towardsdatascience.com](/object-oriented-programming-is-dead-wait-really-db1f1f05cc44)

底线:为你自己和你的同事避免面部表情

快速失败,尽早失败——但不要愚蠢地失败。每个人都会犯错误,但还是要避免那些愚蠢的错误,或者至少快速改正它们。

不仅仅是为了进步。这也是为了避免 face palm-时刻,你会因为没有早点发现错误而自责。

这也是为了不失去你的名声——谁愿意带着一个看似复杂的问题跑去找同事或经理,却发现这个问题其实很容易解决?

很有可能你已经犯了我在过去提到的一些错误。冷静,伙计,我也有——我们是人。

关键是,如果您的代码以意想不到的方式运行,您将希望首先检查琐碎的事情。然后,如果您的代码仍然不能正常工作,您可以随时 ping 您的同事。

如果你对 GPT-3 编写代码感到兴奋,那你一定没听说过 NAS

原文:https://towardsdatascience.com/if-youre-hyped-about-gpt-3-writing-code-you-haven-t-heard-of-nas-19c8c30fcc8a?source=collection_archive---------15-----------------------

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

来源: Unsplash

自动化人工智能发现和研究

GPT-3 最近因展示人类语言代码翻译的病毒视频而成为机器学习社区的头条新闻。该模型可用于自动化许多冗余和重复的编码,例如在 HTML/CSS 中或在简单神经网络的构造中。正如许多其他人所指出的,GPT-3 只是一个工具,并且受到其训练数据的限制。

开发人员想做的许多更复杂的事情——例如,给网站添加一些特定的基于动量的动画——GPT-3 都做不到,因为它 a)不够先进,b)没有足够的训练数据,c)毫无疑问不是“创造性的”。GPT-3 可能会成为一个有用的工具,帮助开发人员花更少的时间重新输入旧命令,花更多的时间集思广益创造性的基础设施设计和调试复杂的跨系统错误,但它绝不是对程序员生计的威胁。

特别令人感兴趣的是一个演示,其中 GPT-3 在流行的高级深度学习库 Keras 中为一个神经网络编写了代码,给定一个自然文本输入,如“我有一个 60 乘 60 像素图像的数据集,想将它们分为 10 类”。然后,GPT-3 会吐出默认代码来构建一个基本的模板卷积神经网络。

GPT-3 为神经网络“编写代码”很像一个初学者试图打出他们从教程中记住的样本代码:它不关心它的性能或使它的架构适合数据集,它只是试图根据它早先在训练数据集中看到的内容来预测下一个最有可能的字符。尽管这是一种直白的说法,但使用 GPT-3 编写代码就像在 StackOverflow 上自动搜索简单的代码片段一样。也许它会在代码自动完成中获得商业上的成功。

然而,这个想法,人工智能学习创造人工智能,并不新鲜,在 2002 年就有了第一个正式的概念。虽然 GPT-3 将以前在广泛的代码处方中看到的代码回流,但神经架构搜索(简称 NAS)通过实际搜索数据集的最佳神经网络,将这一想法推向了一个新的水平。机器学习工程师的大部分工作都依赖于基于直觉和经验测试一些万亿级的潜在神经网络结构,而 NAS 可以大大降低这一成本。

NAS 通过智能搜索人类从未想到的潜在结构,利用 AI 创造更好的新 AI。不是概括,是发现。

通常,NAS 的实施有三个组件:

  • 一个搜索空间。这是神经结构搜索可以探索潜在结构的空间。该空间由作者定义的一组可能的层(回旋、汇集、密集、下降等)界定。)以及它们如何连接(跳过、层大小等。).搜索空间的轮廓需要一些人类经验。
  • **一种搜索算法。**NAS 算法首先对几个候选网络架构进行采样,并根据这些“子模型”的性能,通过准确性或延迟(运行时间)等指标,获得奖励或惩罚。人类可以指定哪些度量更重要;例如,如果需要一个小而轻的模型,即使以精度为代价,更小的尺寸和更好的延迟可能会获得更高的回报。
  • 一种进化策略。NAS 必须测量和预测许多提议的子模型的性能,以获得反馈供其学习。这可以通过训练每个子模型来完成,但是这显然是非常昂贵的,并且已经提出了新的方法来节省计算和时间资源。

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

作者创建的图像。

从这个意义上说,NAS 类似于一个人解决搜索问题的典型 RL 方法,但是做了一些修改以适应其任务。

首先,神经网络结构有许多潜在的表现形式。由于 NAS 围绕着这种复杂结构的选择和进化,所以找到一种合适的方法来呈现它是非常重要的。因为将神经网络表示为实际的、物理的神经网络是非常低效的,所以已经有许多对架构的描述,这些架构额外支持更容易的进化。

一种方法是基于细胞的方法,受现代图像识别模型(如 Inception)的设计启发,在该方法中,人类决定堆叠两种类型细胞的一般架构:正常细胞(输入和输出具有相同的维度)和缩减细胞(输出是输入的 1/2)。在网络框架(细胞序列,可能是多个背靠背的同一个细胞)设置好之后,NAS 创建这两个细胞的结构。

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

来源: Zoph 等人 2018 ,图片免费分享。

该模型具有高度的可移植性,因为架构不是特定于数据集的,可以用其他实现来实现,并且在训练时速度更快。然而,基于细胞的表示高度依赖于良好的人类细胞构造。

另一种方法是将神经网络表示为计算图或“主题”。1 级操作——原始的 1x1 卷积或汇集,可以组装成 2 级主题,并递归到更高级别的网络结构上。这种方法类似于基于单元的结构,因为它聚合了几个更小的结构,但它允许更大的复杂性。

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

来源: 刘等人 2017 ,图片免费分享。

这种表示方法可以被认为更“自然”,因为神经网络本质上是单向图。此外,它可以产生有趣的非对称神经网络。然而,这种表示的存储和操作成本很高。

对于已建立的神经网络表示,仍然存在许多算法来(有时)创建和选择架构。令人惊讶的是,随机搜索——从空间中随机选择一个网络——是设计良好的搜索空间难以超越的基准。

强化学习常用于 NAS 方法。基于强化学习的“控制器”生成/建议要评估的子模型架构。这个控制器是一个递归神经网络,它学习生成潜在神经网络的基于令牌的顺序表示。RNN 随着潜在架构的性能而更新,并被训练以输出更好且性能更好的网络。

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

来源:Zoph&Le 2017,图片免费分享。

这至少在概念上类似于 GPT 3 号正在做的事情:模拟一个序列。然而,在 NAS 中,RNN 连接到强化学习系统,因此它根据数据集学习生成性能良好的网络。可以认为是自动化人类研究人员所做的事情——利用已知的现有想法并探索新想法。

另一种搜索算法是基于进化的,其中架构被表示为“基因”。突变包括单独添加连接和节点;来自父体系结构的两个体系结构可以“配对”或“交叉”以形成子结构。通过巧妙的方法来减少搜索空间并控制种群数量,如淘汰旧模型,NAS 的进化方法已被证明是相对有效的,尽管比 RL 方法更昂贵。

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

来源: 斯坦利&米库莱宁 。图片免费分享。

虽然 NAS 仍处于早期,其沉重的计算成本限制了广泛的访问,但人工智能指导的人工智能研究很可能会变得更加流行。尤其是像上面讨论的基于主题(图形)的流体表示,AI 可能会在 LSTMs 或 Dropout 这样的聪明机制中找到新的发现。另一个有趣的思想实验是考虑如果 NAS 系统的发现被用来改进发现它的系统会发生什么。

此外,神经架构搜索正在扩展到深度无监督学习,由于标签和监督学习的成本,这是非常重要的。此外,在神经网络的框架之外, Auto-ML Zero 将 NAS 扩展到发现新的机器学习算法,如 SVM 或决策树,使用简单的数学运算作为构建模块和老化进化策略。

NAS 不会是机器学习研究人员的棺材上的钉子,就像 GPT-3 不会是开发人员工作的死刑判决一样。当自动计算器被发明时,人类计算器开始使用计算器来提高他们在金融机构和会计的新工作中的效率,人类总是会有所贡献。同样,技术发展的道路将继续向前,突破是帮助进一步增长的工具。

人工智能发现的自动化令人难以置信地有前途,并有可能使机器学习的能力远远超出人类思维的限制。

点燃火花!

原文:https://towardsdatascience.com/ignite-the-spark-68f3f988f642?source=collection_archive---------7-----------------------

使用 PySpark 在 Kubernetes 上运行 Apache Spark

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

来源:免费图片来自 Pixabay

简介

在这本初级读本中,您将首先了解一些 Apache Spark 的集群管理器是如何工作的,然后了解如何在现有的 Kubernetes (k8s)集群上以交互方式在 Jupyter 笔记本中运行 PySpark。

完成本文后,您应该能够自信地在任何 Kubernetes 集群上开发 Spark 应用程序,并对两者之间的联系有更深的理解。

这都是关于环境的

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

来源:Apache 文档

Spark 是一个快速通用的集群计算系统 ,这意味着根据定义,计算是以分布式方式在许多互连的节点上共享的。

但是 Spark 实际上是如何在集群中分配给定的工作负载的呢?

Spark 采用主/从方式,其中一个驱动程序(“主”)创建一个 SparkContext 对象,该对象连接到一个集群管理器

创建的 SparkContext(由您喜欢的语言绑定以编程方式创建,或者在您提交作业时以您的名义创建)将集群抽象为一个大型计算节点,您的应用程序使用它来执行工作。

另一方面,集群管理器负责生成和管理大量工作节点(“从节点”),每个节点代表 SparkContext 运行一个执行器进程来完成实际工作。

当 Spark 应用程序操作弹性分布式数据帧(RDD) 形式的数据时,RDD 被分割成多个分区,分布在这些工作节点/执行器组合上进行处理。最终结果在节点间汇总并发送回驱动程序。

选择一个管理器,任何集群管理器

这种设计的一个主要优点是集群管理器与应用程序是分离的,因此可以互换。

传统上,Spark 支持三种类型的集群管理器:

  • 独立
  • 阿帕奇 Mesos
  • Hadoop YARN

独立集群管理器是默认的集群管理器,随 Spark 的每个版本一起提供。这是一个没有虚饰,有能力的经理,这意味着让你尽快启动和运行。

Apache Mesos 本身就是一种集群技术,旨在将集群的所有资源抽象化,就像一台大型计算机一样。Mesos 附带了一个集群管理器,您可以在 Spark 中利用它。

Hadoop YARN (“又一个资源谈判者”)是作为 Apache Hadoop 项目的副产品开发的,主要专注于分发 MapReduce 工作负载。因此,它也是 Spark 可以与之进行本地对话的集群管理器。

进入 Kubernetes

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

来源:Apache 文档

从 2.3.0 开始,Spark 现在支持直接使用 Kubernetes 作为集群管理器。

但是那个到底是什么意思呢?

这取决于你想如何在 Kubernetes 上运行 Spark。

集群模式中,在您使用 spark-submit 提交应用程序之后,代表您的应用程序创建的 SparkContext 将要求 kube-apiserver 设置一个驱动程序节点和一些相应的工作节点(Pods ),并在它们之上运行您的工作负载。

一旦所有数据处理完成,在拆除时,临时工作节点窗格将自动终止,但驱动程序节点窗格将保留,以便您可以在手动删除它之前检查任何日志。

客户端模式中,您创建 Spark driver 节点作为 Pod,然后在最终提交工作之前,使用您最喜欢的语言的 API 绑定创建 SparkContext。

出于几个原因,本初级读本将着重于配置客户端模式:

  • web 上的大多数文档都是以集群模式提供的
  • 使用 spark-submit 提交应用程序的步骤与使用现有的集群管理器没有什么不同
  • 大多数 Spark 开发人员都希望使用客户机模式,这样他们就可以开发新的应用程序并交互式地探索数据

先决条件

以下说明假设如下:

  • 您对 Kubernetes 集群或该集群中的专用名称空间拥有管理权限

我正在运行一个小型的 1.17.2 八节点集群,它是使用 kubeadm 工具安装的。我相信任何集群 1.15+都应该工作得很好。

如果你没有集群,我强烈建议在你的桌面上安装 MiniKube 作为一种跟进方式。

  • 您对 Kubernetes 的核心概念有些熟悉,比如 pod、部署和服务
  • 您已经安装了 Docker,理解了容器背后的概念,并且能够轻松地使用 Docker 文件构建自定义映像
  • 您可以访问内部、云中或外部的 Docker 注册中心,如 Docker Hub
  • 在撰写本文时,您使用的是 Spark 的最新稳定版本 v2.4.4

集群设置

在我们开始构建映像和部署 Pods 之前,让我们设置一个专用的名称空间,我们的 combo Jupyter notebook/Spark driver 节点以及所有对应的 worker 节点都将部署在这个名称空间中。

$ kubectl create namespace spark
namespace/spark created

为了让你的驱动程序 Pod 从集群中请求资源,它必须使用某种类型的服务帐户,该帐户拥有正确的角色基础访问控制(RBAC)

Spark 文档建议创建一个角色绑定集群角色绑定来完成这个任务。选择实现哪种方法完全取决于集群的安全策略。

对于本例,我们将在 spark 名称空间 中创建一个名为 spark 的 ServiceAccount,并使用 ClusterRoleBinding 赋予该帐户适当的权限:

$ kubectl create serviceaccount spark -n spark
serviceaccount/spark created$ kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=spark:spark --namespace=spark
clusterrolebinding.rbac.authorization.k8s.io/spark-role created

Docker 设置

如上所述,由于每个 worker 节点实际上只是我们集群中的一个 Pod,所以我们需要一个 docker 映像和正确的 Spark 运行时。

幸运的是,Spark 团队提供了一组 Dockerfiles 和一个工具( docker-image-tool.sh )来创建映像,这些映像可以部署在任何 Kubernetes 集群上。

每个 docker 文件都要与 Spark 支持的三种主要语言绑定一起使用——Scala、Python 和 r。

让我们构建默认图像,这样我们至少有一些基础图像可以使用:

$ wget -qO- [http://mirrors.gigenet.com/apache/spark/spark-2.4.4/spark-2.4.4-bin-hadoop2.7.tgz](http://mirrors.gigenet.com/apache/spark/spark-2.4.4/spark-2.4.4-bin-hadoop2.7.tgz) | tar -xzf -$ cd spark-2.4.4-bin-hadoop2.7 && bin/docker-image-tool.sh build
Sending build context to Docker daemon  262.2MB
...
Successfully built 02fb36ac3ee0
Successfully tagged spark:latest
Sending build context to Docker daemon  262.2MB
...
Successfully built 0d33be47d094
Successfully tagged spark-py:latest
Sending build context to Docker daemon  262.2MB
...
Successfully built dc911ac3678e
Successfully tagged spark-r:latest

docker-image-tool.sh 脚本完成后,您应该有三个新的映像准备好部署在 Kubernetes 集群上:

$ docker images spark:latest
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
spark               latest              02fb36ac3ee0        7 days ago          344MB$ docker images spark-py:latest
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
spark-py            latest              0d33be47d094        7 days ago          432MB$ $ docker images spark-r:latest
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
spark-r             latest              dc911ac3678e        7 days ago          539MB

由于本教程将集中使用 PySpark,我们将为我们的 worker Pod 使用 spark-py 图像。通常,您只需将这些映像推送到集群使用的任何 docker 注册表中。但是,我们将创建它们的自定义版本,以便解决一个 bug。

通信故障

在撰写本文时,由于最近修补了一个安全 CVE,在较新的集群上使用现有的 Spark v2.4.4 Kubernetes 客户端 jar 文件存在问题。

你可以在这里和这里阅读更多关于这个问题的信息。

解决方法是构建一个启用 Spark 的 docker 映像,但是其中包含较新的客户机 jar 文件。

让我们使用我们刚刚构建的基础映像来实现这一点。因为我们关注的是使用 PySpark,所以我们将只重建 spark-py 映像,但是相同的步骤适用于所有映像。

$ mkdir my-spark-py && cd my-spark-py$ wget -qO- [http://apache.mirrors.hoobly.com/spark/spark-3.0.0-preview2/spark-3.0.0-preview2-bin-hadoop2.7.tgz](http://apache.mirrors.hoobly.com/spark/spark-3.0.0-preview2/spark-3.0.0-preview2-bin-hadoop2.7.tgz) | tar -xzf -$ cp spark-3.0.0-preview2-bin-hadoop2.7/jars/kubernetes*jar . && rm -f [spark-3.0.0-preview2/spark-3.0.0-preview2-bin-hadoop2.7.tgz](http://apache.mirrors.hoobly.com/spark/spark-3.0.0-preview2/spark-3.0.0-preview2-bin-hadoop2.7.tgz)$ cat << EOF > Dockerfile
FROM spark-py:v2.4.4COPY *.jar /opt/spark/jars/
RUN rm /opt/spark/jars/kubernetes-*-4.1.2.jar
EOF$ docker build --rm -t my-spark-py:v2.4.4 .
...
Successfully built 29abceec5cb2
Successfully tagged my-spark-py:v2.4.4

所以现在 my-spark-py:v2.4.4 包含了相同的官方 spark 运行时,但是更新了来自 v3.0.0-preview2 版本的 Kubernetes 客户端 jar 文件。

每当我们生成 SparkContext 时,Kubernetes 会根据需要创建一个 worker Pod,并提取该图像。

创建“驱动程序”窗格图像

因为我们的最终目标是在 Jupyter 笔记本中的 Kubernetes 上交互开发 PySpark 应用程序,所以这个 Pod 也将充当我们的“驱动程序”节点。

因此,您有两种选择:

PySpark docker 官方图片是一个很好的起点,我强烈推荐它。

我创建了一个自定义的 docker 图片,你可以点击上面的链接找到它。我把这张图片叫做我的笔记本:最新的

您应该构建、标记和推送您最终选择的任何映像到您的集群使用的 docker 注册表。

设置您的部署

正如 Kubernetes 的所有事情一样,我们需要编写一个 YAML 文件来部署我们的驱动程序 Pod,它将用于登录 Jupyter 并创建一个 SparkContext。

以下是我的部署情况:

apiVersion: apps/v1
kind: Deployment
metadata:
 **namespace: spark**
  name: my-notebook-deployment
  labels:
    app: my-notebook
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-notebook
  template:
    metadata:
      labels:
        app: my-notebook
    spec:
      **serviceAccountName: spark**
      containers:
      - name: my-notebook
        image: pidocker-docker-registry.default.svc.cluster.local:5000/my-notebook:latest
        ports:
          - containerPort: 8888
        volumeMounts:
          - mountPath: /root/data
            name: my-notebook-pv
        workingDir: /root
        resources:
          limits:
            memory: 2Gi
      volumes:
        - name: my-notebook-pv
          persistentVolumeClaim:
            claimName: my-notebook-pvc
---
apiVersion: v1
kind: Service
metadata:
  namespace: spark
  name: my-notebook-deployment
spec:
  selector:
    app: my-notebook
  **ports:
    - protocol: TCP
      port: 29413
  clusterIP: None**

突出显示的文本是您应该注意的指令:

  • 我们希望我们的部署存在于 spark 名称空间中
  • 我们希望将这个部署的 ServiceAccount 设置为 spark ,它具有我们在上面创建的 ClusterRoleBindingspark-role
  • 根据 Spark 客户端模式文档,我们希望通过将服务的 ClusterIP 设置为 None 来将我们的部署公开为一个无头服务。这允许工人舱通过端口 29413 与司机舱通信。您选择的端口号可以是任何有效的未使用的端口,但是我在这个例子中选择 29413 作为对这个有用帖子的敬意。

创建部署

当您对部署感到满意时,通过以下方式创建它:

$ kubectl create -f k8s/deploy.yaml
deployment.apps/my-notebook-deployment created
service/my-notebook-deployment created

检查您的部署是否正在运行:

$ kubectl get all -n spark
NAME                                          READY   STATUS    RESTARTS   AGE
pod/my-notebook-deployment-7bf574447c-pdn2q   1/1     Running   0          19sNAME                             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
service/my-notebook-deployment   ClusterIP   None         <none>        29413/TCP   19sNAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-notebook-deployment   1/1     1            1           19sNAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/my-notebook-deployment-7bf574447c   1         1         1       19s

现在将端口转发到 8888,这样您就可以登录 Jupyter:

$ kubectl port-forward -n spark deployment.apps/my-notebook-deployment 8888:8888
Forwarding from 127.0.0.1:8888 -> 8888
Forwarding from [::1]:8888 -> 8888

现在,您应该能够将您最喜欢的浏览器指向 http://localhost:8888 并登录 Jupyter(如果您使用我的图像作为参考,密码是**‘Jupyter’**,否则您将需要复制/粘贴在容器的日志文件中显示的生成的 auth token)。

点燃它!

启动一个新的 Python3 笔记本,并在单元格中键入以下内容:

import osfrom pyspark import SparkContext, SparkConf
from pyspark.sql import SparkSession# Create Spark config for our Kubernetes based cluster manager
sparkConf = SparkConf()
sparkConf.setMaster("**k8s://**[**https://kubernetes.default.svc.cluster.local:443**](https://kubernetes.default.svc.cluster.local:443)**"**)
sparkConf.setAppName(**"spark"**)
sparkConf.set(**"spark.kubernetes.container.image", "pidocker-docker-registry.default.svc.cluster.local:5000/my-spark-py:v2.4.4"**)
sparkConf.set(**"spark.kubernetes.namespace", "spark"**)
sparkConf.set(**"spark.executor.instances", "7"**)
sparkConf.set("spark.executor.cores", "2")
sparkConf.set("spark.driver.memory", "512m")
sparkConf.set("spark.executor.memory", "512m")
sparkConf.set("spark.kubernetes.pyspark.pythonVersion", "3")
sparkConf.set(**"spark.kubernetes.authenticate.driver.serviceAccountName", "spark"**)
sparkConf.set(**"spark.kubernetes.authenticate.serviceAccountName", "spark"**)
sparkConf.set(**"spark.driver.port", "29413**")
sparkConf.set(**"spark.driver.host", "my-notebook-deployment.spark.svc.cluster.local**")# Initialize our Spark cluster, this will actually
# generate the worker nodes.
spark = SparkSession.builder.config(conf=sparkConf).getOrCreate()
sc = spark.sparkContext

让我们来分解一下上面的 Spark 配置:

  • 我们将主 URL 设置为"k8s://https://Kubernetes . default . SVC . cluster . local:443",这告诉 Spark 我们的集群管理器是 Kubernetes (k8s)并且在哪里可以找到请求资源的 kube-apiserver
  • 我们将应用程序名称设置为**“spark”**,它将被添加到 worker Pod 名称的前面。你可以随意使用任何你认为合适的名字
  • 我们将 worker Pods 使用的容器映像设置为我们在上面构建的自定义映像,其中包含更新的 Kubernetes 客户端 jar 文件
  • 我们指定希望所有工作节点都创建在 spark 名称空间中
  • 我将工作节点的数量设置为**“7”**,因为我在八个节点上(一个节点是主节点,七个可用于工作)。您需要选择一个对您的集群有意义的数字。
  • 我们将驱动程序和工人的服务帐户名称设置为我们在上面创建的服务帐户(“spark”)
  • 最后,我们将端口号设置为 29413 ,并将集群内服务的完全限定域名指定给工作节点,以便联系驱动节点。

在执行这个单元之后,您应该会看到 spark 名称空间中产生了许多 worker Pods。

让我们检查一下:

$ kubectl get pods -n spark
NAME                                      READY   STATUS    RESTARTS   AGE
my-notebook-deployment-7bf574447c-pdn2q   1/1     Running   0          5m6s
spark-1581043649282-exec-1                1/1     Running   0          76s
spark-1581043651262-exec-2                1/1     Running   0          75s
spark-1581043651392-exec-3                1/1     Running   0          75s
spark-1581043651510-exec-4                1/1     Running   0          75s
spark-1581043651623-exec-5                1/1     Running   0          75s
spark-1581043656753-exec-6                1/1     Running   0          70s
spark-1581043656875-exec-7                1/1     Running   0          70s

您现在有一个运行在 Kubernetes 上的 Spark 集群等待工作!

按照传统,让我们在新的单元格中使用我们的集群来计算数字 Pi:

from random import random
from operator import addpartitions = 7
n = 10000000 * partitionsdef f(_):
    x = random() * 2 - 1
    y = random() * 2 - 1

    return 1 if x ** 2 + y ** 2 <= 1 else 0count = sc.parallelize(range(1, n + 1), partitions).map(f).reduce(add)
print("Pi is roughly %f" % (4.0 * count / n))

您的输出应该是:

Pi is roughly 3.141397

熄灭火花

完成开发后,只需执行以下命令就可以关闭 Spark 集群:

sc.stop()

这将指示您的 SparkContext 通过 kube-apiserver 拆除上面创建的 worker Pods。

要验证:

$ kubectl get pods -n spark
NAME                                      READY   STATUS        RESTARTS   AGE
my-notebook-deployment-7bf574447c-pdn2q   1/1     Running       0          20m
spark-1581043649282-exec-1                0/1     Terminating   0          16m
spark-1581043651262-exec-2                1/1     Terminating   0          16m
spark-1581043651392-exec-3                1/1     Terminating   0          16m
spark-1581043651510-exec-4                0/1     Terminating   0          16m
spark-1581043651623-exec-5                0/1     Terminating   0          16m
spark-1581043656753-exec-6                0/1     Terminating   0          16m
spark-1581043656875-exec-7                0/1     Terminating   0          16m

现在您只剩下 spark 名称空间中的部署/驱动程序 Pod。

结论

我希望您现在更有信心使用 PySpark 在 Kubernetes 上创建 Spark 集群,并欣赏其背后的架构。

我知道在我早期的 Spark 开发工作中,大部分时间我都是在独立模式下运行的,但是现在有了 Kubernetes 的支持,它要么集群,要么破产!

欢迎在下面发表任何问题、更正或担忧,祝您愉快!

“我会在半路上遇见你”——使用数据科学来揭露你的朋友告诉你的谎言

原文:https://towardsdatascience.com/ill-meet-you-halfway-using-data-science-to-expose-the-lies-your-friends-are-telling-you-c028b4262091?source=collection_archive---------60-----------------------

使用 API 和空间分析来优化和规划你的“新常态”社交生活

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

马克·克劳斯Unsplash 上拍照

一款应用程序,使用 API 和空间分析来优化与朋友见面时的旅行

回到 2019 年,我开发了一个应用程序,它很快给了我和我的朋友们一个“最好的”见面地点的列表。这包括了地点的类型,每个人的旅行时间,评论,价格等等。虽然当时我把它作为“一点乐趣”和在空间分析中更深入地使用 API 的有用尝试,但我希望随着我们进入“新常态”,它可能会比以往任何时候都更有用,作为一种减少每个人旅行并找到新的和不那么拥挤的见面地点的手段。

这是我在 Alteryx 的开发过程中写的,作为我如何构建应用程序的指南,这是在一个预先锁定的世界里……所以,让我们回到 2019 年,一个更好的时间,那时我们可以出去,感觉安全地去见朋友。

(虽然重读了一些,但我当时似乎还是那么消极。直到失去了,你才真正懂得珍惜你所拥有的…)

【2019 年 11 月

我很恼火;我已经在一个破旧的伦敦酒吧里独自等了 15 分钟,这时我收到一条短信说,“对不起,伙计,我要走了……给我拿杯酒,我一分钟就回来”。我仍然很恼火,但不再是因为他迟到了;也不是说酒吧很糟糕;我甚至不用请他喝一杯。我很恼火,因为我们选择见面的地方显然就在他家附近,尽管离我家有几英里远。这可能会让你觉得我是一个很难相处的人。你绝对是对的。无论如何,这是我认为这种问题将来可以解决的方法…

像任何理性分析师一样,我和我的(同样脏兮兮的)同伴喝完一品脱酒后,离开了这个脏兮兮的酒吧,开始思考如何解决这个问题。在处理手头的挑战之前,我想了解具体的问题是什么,以及定义它的可能约束。我把它们总结为:

问题:两个(或更多)人需要决定他们想在哪里见面

约束:

  • 双方都必须有可能在每个人规定的旅行时间内到达这个地方(显然我的同伴的最大旅行时间是 1 分钟,我应该明白这一点)
  • 每个人都可以选择开车、步行、骑自行车或乘坐公共交通工具到达目的地
  • 这个地方应该在平均旅行时间和场地质量之间取得平衡
  • 场所类型可以预先定义(咖啡馆、酒吧、餐馆等)。)
  • 在你去之前,你应该能看到这个地方和评论

这是一个位置问题,尽管我知道我需要位置信息来解决它——而不是预先选择数千个地点,我想要一种方法来动态访问任何位置的大量位置数据,无论应用程序何时运行。

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

维克多·罗德里格兹在 Unsplash 上的照片

所以——除了我明显的个性问题(有些事情即使复杂的算法也无法解决)——很明显这是一个空间和 API 的两难问题,我可以使用 Alteryx 来解决。

本博客的其余部分致力于应用程序的用户界面;从技术角度看它是如何构建的;以及我接下来的步骤。我在这篇文章的底部添加了 Alteryx 社区上的应用程序链接。请随意下载并亲自尝试,或者只是评论反馈—链接在本文的底部。欢迎所有反馈。

如何使用该应用程序

像许多 API 一样,您需要生成一个访问令牌来使用 Google API。你可以在这里注册。

请务必检查路线和地点:

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

我选择将一张卡与我的 API 相关联(因为这样做可以让你免费打很多电话),但是请务必通读这里的所有文档。

该应用的用户界面分为三个选项卡:

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

Alteryx 设计器中 UI 的第一次迭代

结果

结果在报告中提供,显示:您的旅行多边形重叠的地方,该景点中排名最高的地方,以及其他一些有趣的点和图像…

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

它是如何工作的?

有几个关键工具是该应用程序不可或缺的。在调试模式下运行应用程序可以让你确切地看到这些工具在做什么。

  • 在应用程序开始时,您在地图上放置了两个(或更多)大头针;这些大头针需要转换成空间对象,这样我们就可以对每个人的位置进行空间分析。这是使用“创建点”工具,通过 XY 坐标和附加一个空间对象来完成的。
  • 丢弃的点被馈送到 Route 360 API 宏中;该 API 利用步骤 1 中创建的空间点,在每个人周围创建一个多边形,显示他们在选择的交通类型和时间内可以到达的区域。(请注意,当您远离时,斑点的大小会减小;公共交通经常出现这种情况,其中每个斑点(在这种情况下)是一个地铁站,围绕它们的圆环是人们在剩下的分配时间内可以从每个车站走多远)

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

  • 上面的步骤 2 是为每个人单独运行的,但我们真正想要的是将这两个多边形结合起来,看看这两个旅程是否可以重叠(你将去参加舞会)。“空间处理”工具允许您创建显示重叠区域的多边形,如下所示:

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

  • 如果——如上所述,我们有多个重叠的区域呢?为了最大限度地找到一个好的地点(并最大限度地减少我们必须在下游进行的 API 调用的数量),我们可以使用“空间信息”工具来计算这四个多边形的面积,并只选择面积最大的一个进行地点分析。

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

  • 现在我们有了“完美的会合点”(或者有中心点的多边形),但是我们仍然需要在其中搜索符合我们标准的地方(在这个例子中,是一个酒吧)。您在应用程序开始时定义的搜索半径在这里发挥作用,在我们的谷歌地图 API 调用中充当“距离”中心点的角色。
  • 这些信息,以及中心点和地点类型的 X 和 Y,使我们能够构建一个搜索 URL,如下所示:
[https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=518746104,-0.110362243&radius=500&keyword=Bar&key=**yourGoogleAPIkey**](https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=518746104,-0.110362243&radius=500&keyword=Bar&key=yourGoogleAPIkey)
  • 这个网址实际上是你在谷歌地图中搜索过的。我们需要 Alteryx 预先做好工作,以便在稍后找到完美的会议,但是,通过 Alteryx 这样做,我们可以返回比我们在 Google 中直接看到的更多的结果,更不用说看到关于每个地方的更多信息。
  • 我们可以将新构建的 URL 输入到“下载”工具中,该工具与“JSON parse”一起允许我们以结构化的方式查看所有数据:

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

  • 额外的报告和 blob 转换工具允许我们为用户构建标签,点击通过谷歌评级排序的地点列表,查看显示其位置的地图,并查看一些示例图片:

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

  • 然后使用报告工具生成您在最终输出中看到的地图和表格:

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

后续步骤

最近,除了“中间”之外,我拒绝在任何地方与任何人见面,并且被封锁,这意味着我有很多空闲时间来测试、改进和添加功能。我在锁定期间添加的几个功能包括但不限于:

  • 用户关键字搜索。例如,您可能想要一家餐馆,但是添加到 google URL 的自由文本字段也允许您声明该餐馆提供“鱼和薯条”
  • 每个人的实际旅行时间;google maps API 允许您返回以分钟和英里为单位的旅行时间,还可以返回一步一步的路线
  • 多人(> 2 人)功能。显然,有些人有不止一个朋友,所以我添加了在 UI 中声明多人位置的功能
  • 评论排名理论上是好的,但实际上很差。如果我要会见工作中的朋友(假设每个人都在市中心工作),应用程序通常会建议在里兹酒店(Ritz)见面喝杯啤酒……所以我创建了一个指数,将所有这些变量都考虑在内,包括价格
  • UI 的一般整理:例如,最初,在下拉选择中,你可以看到谷歌将为你搜索的一系列商业类型;很自然,这非常适合酒吧和餐馆:

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

…我认为(也希望)没有人会想用这个来寻找他们之间评价最高的牙医或动物园。但我有什么资格评判?

更新后的新应用程序用户界面如下所示,可以在任何设备上通过浏览器运行:

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

Alteryx 服务器中的新应用程序 UI

…输出包括更多细节,包括:

  • 每个人到达每个目的地需要多长时间(见下面的安迪、克里斯和戴夫专栏)
  • 行程时间的均值和标准差(保证公平!)
  • 价格、评级、评级数量
  • 一个排名指数,基于我创建的评分系统,加权并结合了上述所有指标

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

如果我和两个(虚构的)朋友想在一个高档酒吧见面

最后订单

我发现,尽管用例最初是用来学习 Google APIs 并继续使用 Alteryx 中的空间分析工具,但从 2020 年开始,我们相遇的地方以及我们如何到达那里,是一个比以往任何时候都更相关的问题。

正如你所看到的,即使是现在这也是一项正在进行的工作;我欢迎对这个应用程序的任何反馈,或者如果你想在这个或类似的事情上合作,请听听你的意见。我很乐意在附近的动物园见面,假设它符合我的评分高于 4.7 和旅行时间少于 27 分钟的标准。

我欢迎任何反馈或想法!

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

威尔·斯图尔特在 Unsplash 上拍摄的照片

干杯

伊利诺伊州——你为什么不把曲线变平?

原文:https://towardsdatascience.com/illinois-why-arent-you-flattening-the-curve-9e19b71ab453?source=collection_archive---------47-----------------------

还是你?让我们看看数据

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

索耶·本特森在 Unsplash 上的照片

编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

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

图片作者。查看伊利诺伊州新冠肺炎仪表盘上的实时图像。

伊利诺伊州的“呆在家里”命令,相当于该州的就地避难所,于 3 月 21 日生效,并持续到今天。但是尽管隔离,伊利诺伊州的新冠肺炎病例似乎仍在加速。这与旧金山湾区的明显成功形成鲜明对比。

确诊病例总数

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

图片作者。查看伊利诺伊州新冠肺炎仪表盘上的实时图像。

关于伊利诺伊州,首先要注意的是,总病例数继续呈上升趋势。这对于大多数州来说是真实的,并不意味着他们没有拉平曲线。问题是,病例总数的增长速度有多快?

增长曲线—每日新病例

每天新增病例的数量是决定一个州是否在拉平曲线的最重要的统计数据。它代表了感染的加速。

生长曲线的快速解释

为了便于说明,让我们用一个假设的例子来说明一周的时间跨度。

如果一个州的新病例数每两天翻一番,这意味着周一有 400 个新病例,周三有 800 个新病例,周五有 1600 个新病例,周日有 3200 个新病例,这意味着一周总共有 6000 个新病例。这很糟糕,表明感染率在上升。

相比之下,如果增长曲线是平坦的,则他们可能会在周一显示 40 个新病例,周三显示大约 40 个新病例,周五显示大约 40 个新病例,周日显示 40 个新病例——这几周总共有 160 个新病例。

前一种情况是那种可以迅速压垮医疗系统的增长曲线。后一种情况是曲线变平后的样子。仍然有新的病例,但是每天的新病例数量没有增长。因此,病例总数并没有增加。

伊利诺伊州的增长曲线

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

图片作者。查看伊利诺伊州新冠肺炎仪表盘上的实时图像。

从这张图表中我们可以看出,伊利诺伊州的增长曲线似乎没有变平。每天都有一些变化,但如果你看一下 7 天移动平均线(绿线),你会发现每天的新病例数量仍呈上升趋势。这是怎么回事?

库克县有绝大多数的病例

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

图片作者。在伊利诺斯州新冠肺炎仪表盘上查看实时可视化。

这张图表中最突出的一点是,伊利诺伊州的绝大多数病例都发生在库克县。库克县是芝加哥的所在地,芝加哥是该州最大的都会区,也是人口密度最大的地区。

但是等等,他们在进行更多的测试吗?

我们需要考虑的一点是,确诊新增病例的数量可能并不总是代表实际新增病例的数量。检测激增会导致确诊新病例激增。

因此,伊利诺伊州(甚至芝加哥)每天都在做越来越多的测试,这是理所当然的,他们会显示每天的病例数在增加,即使实际病例数持平。我们来看看测试数据。

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

现在看这个图表,叙述开始改变。在这里,我们看到 4 月 24 日进行的测试大幅增加。如果我们回到每日新增病例图表,我们也看到 4 月 24 日确诊病例大幅增加。

测试曲线解释了增长曲线中所有的增长吗?看起来没有,没有。但它确实消除了一些更令人担忧的峰值,并且在报道伊利诺伊州就地安置的有效性时需要额外的谨慎。

数据源和参考

这篇文章的所有数据和可视化来自 Knowi 冠状病毒数据中心。那里使用的数据来自约翰·霍普斯金,世卫组织,疾病控制中心。在这里查看他们的数据来源列表。

可以在这里找到各州的测试数据。

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

图片作者。伊利诺伊州的新冠肺炎仪表盘。

暹罗网络图解指南

原文:https://towardsdatascience.com/illustrated-guide-to-siamese-network-3939da1b0c9d?source=collection_archive---------25-----------------------

使用三重损失进行一次性学习

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

马尔科·祖彭在 Unsplash 上的照片

建立一个准确的机器学习模型通常需要大量的训练数据,这仍然可能导致训练数据过度拟合,或者只适用于有限数量的训练数据类别。但是,如果一台机器能够“学会学习,例如,如果我们向我们的机器展示一只鹦鹉的单一图像,它可以通过理解它与作为参考展示的鹦鹉的图像如何相似来准确地识别另一只鹦鹉的图像。这个设计一个可以“学会学习”的机器的问题叫做元学习

在本文中,我们将关注一个著名的元学习模型——暹罗网络。如何运作,如何实施?

Siamese,顾名思义,来自“Siamese Twins”,其中我们使用两个或更多的网络(这里,在图像的情况下是 CNN),该网络使用共享的权重来学习图像之间的相似性和不相似性。网络输出 n 维嵌入,其中每个方向代表图像的一些视觉模式。

了解嵌入

假设,我们使用 n 维空间来映射我们的图像,其中每个维度对应于特定特征/或模式的值。每个维度描述了输入图像的独特视觉特征。查看 Jay alam mar的这篇令人惊叹的文章以获得更好的嵌入直觉**。**例如,在不同动物图像的情况下,输出嵌入可能如下所示(颜色强度表示其值在 0 到 1 之间)—

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

作者图片

狗的前两个图像输出相似的嵌入,而猫和美洲驼的第三和第四输出嵌入与狗非常不同,因为它们具有非常不同的视觉特征包。

在本文中,我们将使用 Omniglot 数据集。该数据集包含世界各地不同语言中使用的各种字母的字符图像。

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

Ominglot 数据集

工作

美国有线新闻网;卷积神经网络

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

CNN 架构的灵感来自这篇论文

我们的 CNN 输出一个期望嵌入大小的一维数组。我们可以看到最后一层执行 L2 归一化 ,这将归一化输出向量并将其映射到半径为 1 的 n 维超球的表面。这样做是为了确保可以通过计算两个嵌入之间的距离来比较图像之间的相似性值,因为所有的嵌入都将位于将给出更好结果的表面上。我们的模型有三个这样的 CNN,所有的重量都一样。这将帮助我们的模型学习每个样本中的一个相似性和一个不相似性。每个样本将包含三个组成锚*、阳性阴性的样本图像。稍后会有更多的介绍。*

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

最终连体网络架构

损失函数

现在是构建这个网络最重要的部分。在这里,我们将编写它如何比较输出嵌入的定义,并理解它们之间的相似性/不相似性,从而完成元学习的任务。

由于我们使用之前讨论的 L2 归一化将输出嵌入映射到表面上,我们可以使用 L2 距离或余弦相似度。使用三重损失将允许我们的模型映射两个彼此接近的相似图像,并且远离不相似的样本图像。这种方法通过供给三个一组来实现,包括:

1。锚点图像 —这是一个样本图像。

2。正面形象——这只是主播形象的另一种变体。这有助于模型学习两个图像之间的相似性。

3。负像 —这是与上面两幅相似图像不同的图像。这有助于我们的模型学习锚图像的不同之处。

为了增加相似和不相似输出向量之间的距离,并进一步映射彼此接近的相似图像,我们引入了另一个术语,称为边距。这增加了相似和不相似向量之间的分离,也消除了任何平凡解的输出。由于人类很难想象一个嵌入映射到 N 维球体上,从而理解这种损失是如何工作的,我做了下面的渲染来建立对 N=3(我们非常熟悉的 3D)这种东西如何工作的直觉。

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

此图描述了我们的模型在训练后的输出。标记为绿色点的相似图像相互靠近映射,标记为红色映射的不相似图像相距较远,边距大小的最小距离显示为黄色。在训练后的理想情况下,不应在锚图像的黄色区域中映射任何点。然而,由于表面上的空间非常有限,点往往会有重叠区域。稍后将对此进行更多讨论。

我们的模型使用了在论文中使用的 0.2 的边距大小。

这种相似性/不相似性由使用 L2 距离和余弦距离的两个向量之间的距离来定义。

所以我们的损失定义如下—

loss(a,p,n) = max(0,d(a,p) -d(a,n)+余量)

余弦三重损失

L2 三重损失

履行

实现这个网络的棘手部分是定义损失函数。我们通过对所需批量的三元组进行采样来生成输入数据,并定义网络和我们的损失函数,然后进行训练!!!完整的实现可以在 这里找到

结果和观察

在用不同的超参数和损失函数训练网络,并在 n 路一次分类(即网络从未见过的不同类别的“n”个单个图像)上测试网络准确度之后。可以观察到—

  1. 对于较小的嵌入,余弦损失往往表现良好。
  2. 增加嵌入的大小可以提高精确度,因为更多的维度现在可以表示图像的更多独特特征。
  3. 随着 n 向一次发射中的“n”增加,模型精度略微降低,因为网络难以在超球体上映射更多数量的相距较远的嵌入。

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

不同大小的输出向量之间的精确度比较

后续的文章可以阅读,使用对比损失使暹罗网络仅学习相似性,使用一个角色的两个不同图像。毫无疑问,它确实表现不佳,往往在训练中过度适应,而三连音缺失根本不会过度适应。基于对比损失的连体网络的准确性随着 nway 一次性分类的增加而急剧下降。

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

不同大小输出向量下对比损失和三重损失的准确性比较

应用

这个网络用来比对指纹,检测签名伪造人脸识别。这可以应用于任何相似和相异分数有用的地方。

参考

[1]https://www.cs.cmu.edu/~rsalakhu/papers/oneshot1.pdf

[2]https://en.wikipedia.org/wiki/Siamese_neural_network

https://jalammar.github.io/illustrated-word2vec/

[3]https://towards data science . com/one-shot-learning-with-siamese-networks-using-keras-17 f 34 e 75 bb 3d

[4]https://Neptune . ai/blog/content-based-image-retrieval-with-siamese-networks

变压器图解指南

原文:https://towardsdatascience.com/illustrated-guide-to-transformer-cf6969ffa067?source=collection_archive---------20-----------------------

逐个组件的细分分析

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

变压器模型是编码器-解码器架构的演变,在论文中提出注意力是你所需要的一切。虽然编码器-解码器架构一直依赖递归神经网络(RNNs)来提取序列信息,但转换器不使用 RNN。基于变压器的模型已主要取代了 LSTM,并已被证明在许多序列间问题的质量优越。

Transformer 完全依赖注意力机制,通过并行化来提高速度。它在机器翻译方面产生了最先进的性能。除了语言翻译方面的重大改进之外,它还提供了一种新的体系结构来解决许多其他任务,如文本摘要、图像字幕和语音识别。

在 Transformer 模型之前,递归神经网络(RNNs)一直是顺序数据的首选方法,其中输入数据具有定义的顺序。RNNs 的工作方式就像一个前馈神经网络,将输入一个接一个地展开。

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

展开递归神经网络[ 来源

展开输入中每个符号的过程由编码器完成,其目的是从顺序输入中提取数据,并将其编码为一个向量,即输入的表示。

顺序输入数据的例子是产品评论中的单词(或字符),其中 RNN 将顺序提取每个单词,形成一个句子表示。这种表示将被用作分类器输出固定长度向量的特征,例如指示正面/负面的情感标签,或者在 5 分尺度上。

在机器翻译和图像字幕中,我们可以用解码器代替输出固定长度向量的分类器。如同编码器单独消耗输入中的每个符号一样,解码器在几个时间步长上产生每个输出符号。

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

使用编码器-解码器结构的机器翻译。

例如,在机器翻译中,输入是英语句子,输出是法语翻译。编码器将按顺序展开每个单词,并形成输入英语句子的固定长度向量表示。然后,解码会以定长向量表示为输入,一个接一个地产生每个法语单词,形成翻译后的英语句子。

基于 RNN 的编码器-解码器的问题

然而,RNN 模型有一些问题,它们训练缓慢,并且它们不能处理长序列。

输入数据需要一个接一个地顺序处理。这种循环过程没有利用现代图形处理单元(GPU ),它是为并行计算而设计的。rnn 非常慢,以至于引入了截断反向传播来限制反向传递中的时间步长数——估计梯度来更新权重,而不是完全反向传播。即使采用截短的反向传播,rnn 的训练仍然很慢。

其次,RNNs 也不能很好地处理长序列,因为如果输入序列太长,我们会得到消失和爆炸梯度。一般在训练过程中会在损耗中看到 NaN(不是一个数字)。这些也被称为 RNNs 中的长期依赖性问题。

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

如果输入序列太长,则渐变消失。

1997 年,hoch Reiter&schmid Huber引入了长短期记忆(LSTM)网络,这种网络被明确设计用来避免长期依赖问题。每个 LSTM 单元允许过去的信息跳过当前单元的所有处理并移动到下一个单元;这允许存储器保留更长时间,并且将使数据不变地随其流动。LSTM 由一个决定存储什么新信息的输入门和一个决定删除什么信息的遗忘门组成。

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

长短期记忆[ 来源

当然,LSTMs 比 rnn 有更好的记忆,能够处理更长的序列。然而,LSTM 网络更复杂,速度更慢。

基于 RNN 的编码器-解码器架构的另一个缺点是固定长度的向量。使用固定长度的向量来表示输入序列以解码一个全新的句子是困难的。如果输入序列很大,上下文向量不能存储所有信息。此外,区分单词相似但意思不同的句子是一项挑战。

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

使用固定长度的向量来表示输入序列。

想象一下,选择上面的一段话(输入)并记忆它(定长向量)。然后,翻译整个段落(输出),不要参考它。这很难,我们不是这样做的。相反,当我们把一个句子从一种语言翻译成另一种语言时,我们一部分一部分地看这个句子,每次都注意这个句子中的一个特定短语。

Bahdanau 提出了一种在编码器-解码器模型中搜索与预测目标单词相关的源句子部分的方法。这就是注意力机制的美妙之处;我们可以使用注意力翻译相对较长的句子,而不会影响它的表现。比如翻译成“noir”(法语是“黑”的意思),注意机制会把注意力集中在“black”这个词上,可能还有“cat”,而忽略句子中的其他词。

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

测试集上生成的翻译相对于句子长度的 BLEU 分数。[ 来源

注意机制提高了编码器-解码器网络的性能,但是速度的瓶颈仍然是由于 RNN 必须一个字一个字地顺序处理。对于序列数据,我们能去掉 RNN 吗?

我们如何对顺序数据使用并行化?

是啊!你需要的只是关注。变压器架构于 2017 年推出。就像编码器-解码器架构一样,输入序列被送入编码器,解码器将逐个预测每个字。该转换器通过消除 RNN 和利用注意机制来改善其时间复杂度和性能。

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

RNN 一个一个地打开每个单词。变压器并行处理输入。

考虑把一个句子从英语翻译成法语。在 RNN,每个隐藏状态都依赖于前面单词的隐藏状态。因此,当前步骤的嵌入一次生成一个时间步骤。在 Transformer 中,没有时间步长的概念;输入序列可以并行传递到编码器。

变压器

假设我们正在训练一个将英语句子翻译成法语的模型。转换器架构有两部分,编码器(左)和解码器(右)。让我们来看看变压器架构。

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

变压器模型架构。[ 来源

在编码器中,它输入一个英语句子,输出将是每个单词的一组编码向量。将输入的英语句子中的每个单词转换成嵌入来表示意思。然后我们添加一个位置向量来添加单词在句子中的上下文。这些单词向量被馈送到编码器注意块,编码器注意块计算每个单词的注意向量。这些注意力向量通过前馈网络并行传递,输出将是每个单词的一组编码向量。

解码器接收法语单词的输入和整个英语句子的注意力向量,以生成下一个法语单词。它用嵌入层编码每个单词的意思。然后添加位置向量来表示单词在句子中的上下文。这些单词向量被送入第一个注意块,即掩蔽注意块。掩蔽注意块计算当前和先前单词的注意向量。来自编码器和解码器的注意力向量被馈送到下一个注意力块,该注意力块为每个英语和法语单词生成注意力映射向量。这些向量被传递到前馈层线性层和 softmax 层,以预测下一个法语单词。我们重复这个过程来生成下一个单词,直到生成“句子结束”标记。

这是变压器如何工作的高级细节。让我们更深入地研究一下每个组件。

嵌入

因为计算机不像我们一样理解单词——它的意思以及单词之间的关系;我们需要用向量代替单词。单词向量(或嵌入)允许每个单词被映射到高维嵌入空间中,其中具有相似含义的单词彼此更接近。

尽管我们可以用向量来引用和表示每个单词的含义,但单词的真正含义取决于句子中的上下文,因为不同句子中的同一个单词可能有不同的含义。由于 RNN 被设计用来捕获序列信息,没有 RNN,转换器如何处理词序?我们需要位置编码器。

位置编码器

位置编码器从输入嵌入层接收输入,并应用相对位置信息。这一层输出带有位置信息的单词向量;这就是单词的意思和它在句子中的上下文。

考虑下面的句子,“狗咬了约翰尼”和“约翰尼咬了狗。”如果没有上下文信息,两个句子会有几乎相同的嵌入。但我们知道这不是真的,对约翰尼来说肯定不是真的。

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

单词嵌入和位置编码产生带有上下文的单词向量。

作者建议使用多个正弦和余弦函数来生成位置向量。这样,我们可以使用这个位置编码器来处理任何长度的句子。波的频率和偏移对于每个维度是不同的,代表每个位置,值在-1 和 1 之间。

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

使用多个正弦和余弦函数的位置编码。

这种二进制编码方法还允许我们确定两个单词是否彼此接近。例如,通过参考低频正弦波,如果一个单词具有“高”,而另一个单词具有“低”,我们知道它们相距更远,一个位于开头,另一个位于结尾。

编码器的多头注意力

注意力的主要目的是回答“我应该关注输入的哪一部分?”如果我们对一个英语句子进行编码,我们想要回答的问题是,“英语句子中的一个单词与同一个句子中的其他单词有多相关?”这表现在注意力向量中。对于每个单词,我们可以生成一个注意力向量来捕捉句子中单词之间的上下文关系。例如,对于单词“黑色”,注意力机制集中在“黑色”和“猫”上

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

多个注意力向量正常化。

由于我们对不同单词之间的交互感兴趣,每个单词的注意力向量可能对自己的权重过高。因此,我们需要一种方法来规范化向量。注意模块接受输入 V、K 和 Q——这些是提取输入单词不同成分的抽象向量。我们用这些来计算每个单词的注意力向量。

为什么叫“多头关注”?这是因为我们对每个单词使用多个注意力向量,并采用加权平均来计算每个单词的最终注意力向量。

编码器的前馈

由于多头注意块输出多个注意向量,我们需要将这些向量转换成每个单词的单个注意向量。

该前馈层接收来自多头注意力的注意力向量。我们应用标准化将它转换成一个单一的注意力向量。因此,我们得到可被下一个编码器块或解码器块消化的单个向量。在该论文中,作者在输出到解码器模块之前堆叠了六个编码器模块。

解码器的输出嵌入和位置编码器

因为我们是从英语翻译成法语,我们输入法语单词到解码器。我们用单词嵌入替换单词,然后添加位置向量来获得单词在句子中的上下文概念。我们可以将这些包含单词含义及其在句子中的上下文的向量输入解码器模块。

解码器的掩蔽多头注意

类似于编码器模块中的多头注意力。注意块为法语句子中的每个单词生成注意向量,以表示每个单词与同一个输出句子中的每个单词的相关程度。

与接收英语句子中每个单词的编码器中的注意块不同,只有法语句子中的前几个单词被输入到解码器的注意块中。因此,我们使用向量屏蔽稍后出现的单词,并用零表示,这样注意力网络在执行矩阵运算时就无法使用它们。

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

多个注意力向量被屏蔽。

解码器的多头注意力

这个注意块充当编码器-解码器,它从编码器的多头注意和解码器的掩蔽多头注意接收向量。这个注意块将决定每个单词向量彼此之间的相关程度,这就是从英语单词到法语单词的映射发生的地方。这个模块的输出是英语和法语句子中每个单词的注意力向量,其中每个向量代表两种语言中与其他单词的关系。

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

将注意力向量输入到解码器的多头注意力中

解码器的前馈

像编码器的前馈层一样,该层将由多个向量组成的每个词归一化为下一个解码器块或线性层的单个注意力向量。在本文中,作者在输出到线性层之前堆叠了六个解码器块。

解码器的线性层和 softmax

由于解码器的目的是预测下一个单词,所以这个前馈层的输出大小是词汇表中法语单词的数量。Softmax 将输出转换为概率分布,输出与下一个单词的最高概率相对应的单词。

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

把英语翻译成法语,解码器预测下一个单词。

对于每一个生成的单词,我们重复这个过程,包括法语单词,并用它来生成下一个直到句子结束的令牌。

开始

TensorFlowPyTorch 都有一个循序渐进的教程,可以帮助你理解和训练一个使用 Transformer 的序列到序列模型。如果你需要快速制作的东西,可能最受欢迎的选择是通过拥抱脸

张量流教程:

[## 用于语言理解的转换器模型| TensorFlow 核心

本教程训练一个 Transformer 模型将葡萄牙语翻译成英语。这是一个高级示例,假设…

www.tensorflow.org](https://www.tensorflow.org/tutorials/text/transformer)

PyTorch 教程:

[## 基于神经网络的序列间建模。变压器和火炬文本- PyTorch 教程 1.5.0…

PyTorch 1.2 版本包含了一个标准的 transformer 模块,该模块基于一篇名为“你只需要关注”的文章。的…

pytorch.org](https://pytorch.org/tutorials/beginner/transformer_tutorial.html)

PyTorch 中的变压器架构:

生产包装:

[## 快速入门-变压器 2.10.0 文档

Transformers 是一个为寻求使用/研究/扩展大型变压器的 NLP 研究人员而构建的自以为是的库…

huggingface.co](https://huggingface.co/transformers/quickstart.html) [## 深度学习神经网络中卷积层是如何工作的?

理解卷积及其参数的生动方式

towardsdatascience.com](/how-convolutional-layers-work-in-deep-learning-neural-networks-2913af333b72) 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

变压器图解指南-逐步解释

原文:https://towardsdatascience.com/illustrated-guide-to-transformers-step-by-step-explanation-f74876522bc0?source=collection_archive---------0-----------------------

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

变形金刚正在席卷自然语言处理世界。这些令人难以置信的模型打破了多项 NLP 记录,推动了技术的发展。它们被用于许多应用程序,如机器语言翻译、会话聊天机器人,甚至是更好的搜索引擎。变形金刚是当今深度学习的热门,但它们是如何工作的呢?为什么它们胜过了之前的序列问题之王,比如递归神经网络、GRU 和 LSTM?你可能听说过不同的著名变形金刚模型,如伯特、GPT 和 GPT2。在本帖中,我们将重点关注引发这一切的一篇文章,“你所需要的是注意力”。

如果你想看视频版本,请点击下面的链接。

注意机制

为了理解变形金刚,我们首先必须理解注意力机制。注意机制使变形金刚具有极长的记忆。转换器模型可以“关注”或“关注”所有先前已经生成的令牌。

让我们看一个例子。比方说我们要用生成式变形金刚写一篇短篇科幻小说。使用的拥抱脸用变形金刚写的应用程序,我们就可以做到这一点。我们将用我们的输入来填充模型,模型将生成其余的。

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

我们的输入: “随着外星人进入我们的星球”。

变形金刚输出: “开始殖民地球,某一群外星人开始操纵我们的社会,通过他们对一定数量精英的影响来保持对平民的铁腕控制。”

好吧,这个故事有点黑暗,但有趣的是这个模型是如何产生它的。当模型逐字生成文本时,它可以“注意”或“关注”与生成的单词相关的单词。知道参加什么单词的能力也是通过反向传播在训练中学会的。

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

在一个接一个地生成单词时关注不同标记的注意机制

递归神经网络(RNN)也能够查看以前的输入。但是注意力机制的力量在于它不会受到短期记忆的影响。RNN 的参考窗口更短,所以当故事变长时,RNN 不能访问序列中更早生成的单词。对于门控循环单位(GRU 氏)和长短期记忆(LSTM 氏)网络来说仍然如此,尽管它们实现长期记忆的能力更大,因此具有更长的参考窗口。从理论上讲,注意机制在给定足够的计算资源的情况下,具有无限的参考窗口,因此能够在生成文本时使用故事的整个上下文。

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

假设的注意参照窗,RNN 的,GRU 的和 LSTM 的

注意力是你所需要的-一步一步的演练

在论文“注意力是你所需要的全部”中展示了注意力机制的力量,其中作者介绍了一种新的新型神经网络,称为变压器,这是一种基于注意力的编码器-解码器类型的架构。

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

变压器模型

在高层次上,编码器将输入序列映射到抽象的连续表示中,该表示保存该输入的所有学习信息。然后,解码器获取该连续表示,并逐步生成单个输出,同时还被馈送先前的输出。

让我们看一个例子。本文将变压器模型应用于神经机器翻译问题。在本帖中,我们将展示它如何适用于对话聊天机器人。

我们的输入: 【嗨你好】

变压器输出: 【我很好】

输入嵌入

第一步是将输入输出到单词嵌入层。单词嵌入层可以被认为是获取每个单词的学习矢量表示的查找表。神经网络通过数字进行学习,因此每个单词都映射到一个具有连续值的向量来表示该单词。

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

将单词转换为输入嵌入

位置编码

下一步是在嵌入中注入位置信息。因为变换器编码器不像递归神经网络那样具有递归性,所以我们必须将一些关于位置的信息添加到输入嵌入中。这是使用位置编码完成的。作者想出了一个使用正弦和余弦函数的聪明绝招。

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

我们不会深入位置编码的数学细节,但这里有一些基础知识。对于输入向量的每个奇数索引,使用 cos 函数创建一个向量。对于每个偶数索引,使用 sin 函数创建一个向量。然后将这些向量添加到它们相应的输入嵌入中。这成功地给出了关于每个矢量位置的网络信息。选择正弦和余弦函数是因为它们具有线性属性,模型可以很容易地学会处理。

编码器层

现在我们有了编码器层。编码器层的工作是将所有输入序列映射到一个抽象的连续表示中,该表示保存整个序列的学习信息。它包含 2 个子模块,多头关注,其次是一个完全连接的网络。在两个子图层的每一个周围还有剩余连接,随后是图层归一化。

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

编码器层子模块

要分解这一点,我们先来看看多头注意力模块。

多头注意力

编码器中的多头注意力应用了一种称为自我注意力的特定注意力机制。自我注意允许模型将输入中的每个单词与其他单词联系起来。所以在我们的例子中,有可能我们的模型可以学会将单词“你”,与“怎么样”和“是”联系起来。也有可能模型知道以这种模式构建的单词通常是一个问题,因此做出适当的响应。

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

编码器自关注操作。参考下面的插图。

查询、键和值向量

为了实现自我关注,我们将输入提供给 3 个不同的完全连接的层,以创建查询、键和值向量。

这些向量到底是什么?我在栈交换上找到了一个很好的解释。

“查询关键字和值概念来自检索系统。例如,当你键入一个查询来搜索 Youtube 上的一些视频时,搜索引擎会将你的 查询 映射到一组 (视频标题、描述等)。)与数据库中的候选视频相关联,然后呈现给你最匹配的视频( )。

查询和关键字的点积

在通过线性层馈送查询、关键字和值向量之后,查询和关键字经历点积矩阵乘法以产生得分矩阵。

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

查询和密钥的点积乘法

得分矩阵决定了一个单词在其他单词上的关注程度。因此每个单词都有一个与时间步长中的其他单词相对应的分数。分数越高,注意力越集中。这就是查询映射到键的方式。

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

点积的注意力分数。

降低注意力分数

然后,分数通过除以查询和键的维度的平方根而缩小。这是为了获得更稳定的渐变,因为倍增值可能会产生爆炸效果。

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

降低注意力分数

标度分数的最大值

下一步,你取标度分数的 softmax 来得到注意力权重,它给你 0 到 1 之间的概率值。通过做 softmax,高分得到提高,低分受到抑制。这允许模型对哪些单词也要参加更有信心。

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

取标度分数的软最大值以获得概率值

将 Softmax 输出乘以值向量

然后你把注意力权重乘以你的价值向量,得到一个输出向量。softmax 分数越高,模型学习的单词值就越重要。较低的分数会淹没无关的单词。然后你把它的输出输入到一个线性层进行处理。

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

计算多头注意力

要使这成为多头注意力计算,您需要在应用自我注意力之前将查询、键和值分成 N 个向量。分裂的向量然后单独经历自我注意过程。每一个自我关注的过程被称为一个头。每个头产生一个输出向量,在通过最终的线性层之前,该向量被连接成一个向量。理论上,每个头将学习不同的东西,因此给编码器模型更多的表示能力。

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

在应用自我关注之前,分裂 Q,K,V,N 次

总而言之,多头注意力是 transformer 网络中的一个模块,它计算输入的注意力权重,并产生一个输出向量,其中包含关于每个单词应该如何关注序列中所有其他单词的编码信息。

剩余连接、层标准化和前馈网络

多头注意力输出向量被添加到原始位置输入嵌入中。这被称为剩余连接。剩余连接的输出经过层标准化。

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

位置输入嵌入与多头注意输出的剩余连接

归一化残差输出通过逐点前馈网络进行投影,以便进一步处理。点式前馈网络是一对线性层,中间有一个 ReLU 激活。然后,其输出再次添加到逐点前馈网络的输入,并进一步归一化。

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

逐点前馈层的输入和输出的剩余连接。

剩余连接通过允许梯度直接流过网络来帮助网络训练。使用层标准化来稳定网络,从而大大减少所需的训练时间。逐点前馈层用于投射注意力输出,潜在地给予它更丰富的表示。

编码器总结

这就完成了编码器层。所有这些操作都是将输入编码成具有注意力信息的连续表示。这将有助于解码器在解码过程中关注输入中的适当单词。您可以将编码器堆叠 N 次,以进一步对信息进行编码,其中每一层都有机会学习不同的注意力表示,因此有可能提高 transformer 网络的预测能力。

解码器层

解码器的工作是生成文本序列。解码器具有与编码器相似的子层。它有两个多头注意力层,一个逐点前馈层,和残差连接,以及每个子层之后的层归一化。这些子层的行为类似于编码器中的层,但是每个多头注意力层有不同的工作。解码器以线性层作为分类器,以 softmax 获得单词概率。

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

解码器层。阅读时参考这张图表。

解码器是自回归的,它以一个开始标记开始,并接受一个先前输出的列表作为输入,以及包含来自输入的注意信息的编码器输出。解码器在生成令牌作为输出时停止解码。

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

解码器是自回归的,因为它在先前的输出中被馈送时一次生成一个令牌 1。

让我们来看一下解码步骤。

解码器输入嵌入和位置编码

解码器的开始与编码器非常相似。输入经过嵌入层和位置编码层以获得位置嵌入。位置嵌入被送入第一个多头注意力层,该层计算解码器输入的注意力分数。

解码器第一多头关注

这个多头注意力层的运作方式略有不同。由于解码器是自回归的,并且一个字一个字地生成序列,所以需要防止它适应未来的标记。例如,当计算单词“am”的注意力分数时,您不应该访问单词“fine ”,因为该单词是在之后生成的未来单词。单词“am”应该只能访问它自己和它前面的单词。这对于所有其他的词都是如此,在那里他们只能注意前面的词。

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

对解码器的第一个多头注意力标度注意力分数的描述。“am”这个词,不应该为“fine”这个词取任何值。其他所有单词都是如此。

我们需要一种方法来防止计算未来单词的注意力分数。这种方法叫做掩蔽。为了防止解码器查看将来的令牌,您可以应用一个先行掩码。在计算 softmax 之前和缩放分数之后添加掩码。让我们来看看这是如何工作的。

前瞻掩模

掩码是一个矩阵,其大小与填充有 0 值和负无穷大值的注意力分数相同。当你把面具加到缩放的注意力分数上时,你会得到一个分数矩阵,右上角的三角形填充了否定的无穷大。

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

向缩放后的分数添加前瞻掩码

屏蔽的原因是因为一旦你取屏蔽分数的软最大值,负的无穷大被清零,为未来的标记留下零注意分数。正如您在下图中所看到的,“am”的关注度得分本身及其之前的所有单词都有值,但单词“fine”的关注度得分为零。这实际上是告诉模型不要关注这些单词。

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

这种屏蔽是在第一个多头注意力层中如何计算注意力分数的唯一区别。这一层仍然有多个头部,蒙版被应用,然后连接并通过一个线性层进行进一步处理。第一多头注意力的输出是带有关于模型应该如何关注解码器输入的信息的屏蔽输出向量。

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

带掩蔽的多头注意力

解码器二次多头关注,逐点前馈层

第二个多头关注层。对于这一层,编码器的输出是查询和键,第一个多头关注层的输出是值。这个过程将编码器的输入与解码器的输入相匹配,允许解码器决定关注哪个编码器输入。第二多头注意力的输出通过逐点前馈层进行进一步处理。

输出概率的线性分类器和最终 Softmax

最终的逐点前馈层的输出通过最终的线性层,该线性层充当分类器。分类器和你拥有的类的数量一样大。例如,如果您有 10,000 个包含 10,000 个单词的类,则该分类器的输出大小为 10,000。分类器的输出然后被输入到 softmax 层,该层将产生 0 到 1 之间的概率分数。我们取最高概率分数的索引,它等于我们预测的单词。

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

使用 Softmax 获得输出概率的线性分类器

然后,解码器获取输出,将其添加到解码器输入列表中,并再次继续解码,直到预测到令牌。对于我们的情况,最高概率预测是分配给结束令牌的最后一个类。

解码器也可以堆叠 N 层,每层接收来自编码器及其前几层的输入。通过堆叠这些层,该模型可以学习从其注意力头部提取并关注不同的注意力组合,从而潜在地提高其预测能力。

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

堆叠编码器和解码器

就是这样!

就是这样!这就是变形金刚的机制。变形金刚利用注意力机制的力量做出更好的预测。递归神经网络试图实现类似的事情,但因为它们患有短期记忆。如果您想要编码或生成长序列,转换器可能会更好。因为有了 transformer 架构,自然语言处理行业才能取得前所未有的成果。

查看michaelphi.com了解更多类似的内容。

✍🏽想要更多内容?在 https://www.michaelphi.com 查看我的博客

📺喜欢看基于项目的视频?看看我的 Youtube

🥇注册我的 电子邮件简讯 ,了解最新文章和视频!

💡示出了重整器

原文:https://towardsdatascience.com/illustrating-the-reformer-393575ac6ba0?source=collection_archive---------11-----------------------

🚊高效变压器️

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

参见:🇫🇷 法文 的翻译

🎥如果你一直在开发用于处理顺序数据的机器学习算法——如语言处理中的文本、语音信号或视频——你可能听说过或使用过Transformermodel,你可能知道它与 twitter 认为的不同:

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

图一。破冰者,摘自克里斯·曼宁教授的推特

🔊🗞最近,谷歌推出了 重整器 架构,这是一个转换器模型,旨在高效处理超长序列的数据(例如一种语言处理多达 100 万个单词)。Reformer 的执行需要低得多的内存消耗,即使只在一个 GPU 上运行也能获得令人印象深刻的性能。论文改革者:高效的变革者 r 将于 2020 年在 ICLR 亮相(并在评论中获得近乎完美的分数)。改革家模型有望通过超越语言应用(如音乐、语音、图像和视频生成)对该领域产生重大影响。

💡在本帖中,我们将尝试深入到 重整器模型 中,并尝试用一些视觉向导来理解它。准备好了吗?💪

为什么是变形金刚?

🎬NLP 中的一类任务(如机器翻译、文本生成、问题回答)可以公式化为序列到序列学习问题。长短期记忆(LSTM)神经网络,后来配备了一个[注意力机制](http://Neural machine translation by jointly learning to align and translate.),是一个用于建立此类问题预测模型的突出架构——例如在谷歌的神经机器翻译系统。然而,LSTMs 中递归固有的顺序性质是对数据序列进行并行计算的最大障碍(就速度和消失梯度而言),因此,这些架构无法利用长序列的上下文。

🚀最近的变压器型号——在论文中介绍的“注意力就是你所需要的全部”——通过消除递归并引入多头自我注意力机制,在许多任务中实现了最先进的性能。transformer 的主要新颖之处在于它的并行处理能力,这使得能够处理长序列(具有数千个单词的上下文窗口),从而以更少的训练时间产生卓越的模型,如著名的 Open AI 的 GPT2 语言模型。🤗Huggingface 的变形金刚库——拥有 100 多种语言的超过 32 个预训练模型以及 TensorFlow 和 PyTorch 之间的互操作性——是构建最先进的 NLP 系统的一项出色的开源工作。🎮用变形金刚写作与变形金刚对话是一些有趣的演示。这个转换器已经被用于文本之外的应用,例如生成音乐图像

变形金刚少了什么?

🚦在深入研究重整器之前,让我们回顾一下 transformer 模型的挑战性。这需要对 transformer 体系结构本身有所了解,这一点我们在本文中无法详述。然而,如果你还不知道,Jay Alamar 的The Illustrated Transformer帖子是迄今为止最伟大的视觉解释,我强烈建议在阅读这篇帖子的其余部分之前阅读他的帖子。

🤔虽然 transformer 模型在越来越长的序列上使用时产生了很好的结果,例如(Liu 等人,2018 年)中的 11K 长的文本示例,但许多这样的大型模型只能在大型工业计算平台上训练,甚至不能在单个 GPU 上进行微调,即使是针对单个训练步骤也是如此,因为它们需要内存。例如,完整的 GPT-2 模型包含大约 1.5 亿个参数。(Shazeer 等人,2018 年)中报告的最大配置中的参数数量超过每层 0.5B,而层的数量高达 64(Al-Rfou 等人,2018 年)。

💡让我们看一下变压器模型的简化概述:

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

图 2:标准变压器模型的简化总结[图片灵感来自‘图解变压器’]

😕如果这个模型看起来不熟悉或似乎难以理解,我敦促你在这里停下来,并审查➡️ 的插图变压器职位。

你可能会注意到有一些👓在图表中用三种不同的颜色。每个都是独一无二的👓s 代表了 Transformer 模型的一部分,Reformer 作者将其视为计算和内存问题的来源:

👀问题 1(红色👓):注意力计算

计算长度为 L 的序列上的注意力是 O(L )(时间和内存都有)。想象一下,如果我们有一个长度为 64K 的序列,会发生什么。

👀问题 2(黑色👓):大量的层

具有 N 层的模型消耗的内存是单层模型的 N 倍,因为每一层中的激活都需要存储用于反向传播。

👀问题 3(绿色👓):前馈层的深度

中间前馈层的深度通常比注意激活的深度大得多。

重整器模型解决了上述转换器中内存消耗的三个主要来源,并对它们进行了改进,使得重整器模型可以处理高达100 万字的上下文窗口,所有这些都在单个加速器上,并且仅使用 16GB 内存。

简而言之,重整器模型结合了两种技术来解决注意力和内存分配的问题:位置敏感哈希 (LSH)来降低处理长序列的复杂性,以及可逆剩余层来更有效地使用可用内存。

下面我们将进一步探讨细节。

💥 1.区分位置哈希(LSH)注意

💭注意和最近的邻居

深度学习中的注意力是一种机制,它使网络能够根据上下文的不同部分与当前时间步长的相对性,专注于上下文的不同部分。变压器模型中存在以下三种类型的注意机制:

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

图 3:变形金刚模型中的三种注意力

变压器中使用的标准注意力是缩放的点积,公式如下:

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

**从上式和下图可以看出,乘法 QKᵀ (形状为[ L,L )的计算和内存开销都在 O(L),这是主要的内存瓶颈。

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

图 4:(左):点积注意力的主要计算,(右)一个标记(‘它’)注意序列中其他标记的子集(‘the’,‘animal’,‘street’,‘it’,’.’)

❓But 是否有必要计算和存储全矩阵 QKᵀ ?答案是不,因为我们只对 softmax ( QKᵀ )感兴趣,它由典型稀疏矩阵中的最大元素支配。因此,正如你在上面的例子中看到的,对于每个查询 q ,我们只需要注意最接近 q 的键 k 。例如,如果 K 的长度为 64K,对于每个 q ,我们只能考虑 32 或 64 个最接近的键的一个小子集。因此,注意力机制找到了查询的最近邻关键字,但是效率很低。💡这是否让你想起了最近邻搜索

重整器的第一个新颖之处来自于用局部敏感散列(LSH) 代替点积关注,将复杂度从 O ( L )变为 O( L log L )。

最近邻搜索的🗒 LSH

LSH 是在高维数据集中最近邻搜索的一种高效近似方式的著名算法。LSH 背后的主要思想是选择散列函数,使得对于两点’ p’ 和’ q’ ,如果’ q’ 接近’ p’ ,那么以足够好的概率我们得到’ hash(q) == hash§'。

实现这一点的最简单的方法是通过随机超平面保持切割空间,并附加 sign(pᵀH) 作为每个点的散列码。让我们看下面的例子:

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

图 5:用于最近邻居搜索的位置敏感散列的简化动画

*一旦我们找到所需长度的哈希码,我们就根据它们的哈希码将这些点划分到桶中——在上面的例子中,*‘a’‘b’属于同一个桶,因为 hash(a) == hash(b) 。现在,用于查找每个点的最近邻居的搜索空间从整个数据集到其所属的桶中急剧减少。

🗒角度 LSH: 普通 LSH 算法的一种变体,称为角度 LSH,将点投影到单位球上,该单位球已被分成预定义的区域,每个区域具有不同的代码。然后,点的一系列随机旋转定义了点所属的桶。让我们通过一个简化的 2D 例子来说明这一点,这个例子摘自《改革家》一文:

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

图 6:最近邻搜索的角度 LSH 的简化动画:两个点是分开的[基于论文中的例子创建的动画]

这里我们有两个点被投影到一个单位圆上,并以不同的角度随机旋转 3 次。我们可以观察到它们不太可能共享同一个哈希桶。然而,在下一个示例中,我们看到彼此非常接近的两个点将在 3 次随机旋转后共享相同的哈希桶:

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

图 7:最近邻居搜索的角度 LSH 的简化动画:两个点接近[基于论文中的例子创建的动画]

🚀LSH 注意了

现在 LSH 关注背后的基本想法如下。回过头来看上面的标准注意力公式,不是计算 QK 矩阵中所有向量的注意力,而是进行以下操作:

  • 找到矩阵 QK 的 LSH 散列。
  • 仅为相同哈希桶内的 kq 向量计算标准注意力。

****多轮 LSH 注意:重复上述步骤几次,以增加相似物品不落入不同桶中的概率。

下面的动画根据论文中的图片展示了简化版的 LSH 注意力。

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

图 6:LSH 注意力机制的简化示意图[根据论文中的例子制作的动画]

💥 2.可逆变压器和组块

现在我们准备解决变压器中的第二和第三个问题,即大量( N )编码器和解码器层以及前馈层的深度。

🗒可逆残差网络

密切关注图 2 中的编码器和解码器块,我们意识到每个关注层和前馈层都被包装到一个残差块(类似于我们在图 6(左)中看到的)。残差网络(ResNets)——在这篇论文中介绍——是 NN 架构中使用的强大组件,用于帮助解决深度网络(具有许多层)中的消失梯度问题。然而,ResNets 中的内存消耗是一个瓶颈,因为需要将每层中的激活存储在内存中,以便在反向传播期间计算梯度。存储成本与网络中单元的数量成正比。

为了解决这个问题,由一系列可逆模块组成的可逆残差网络(RevNet )。在 Revnet 中,每一层的激活都可以从后续层的激活中精确重建,这使我们能够执行反向传播,而无需将激活存储在内存中。图 6。说明了残差块和可逆残差块。请注意,我们如何从模块的输出( Y₁,Y₂ )计算模块的输入( X₁,X₂ )。

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

图 6:残差网络块(左)和可逆残差块(右)示意图

🚀可逆变压器

回到我们的第二个问题,这个问题是处理 N 层变压器网络的内存需求——N 可能相当大。

Reformer 通过将 RevNet 块内的注意前馈层结合起来,将 RevNet 思想应用于变压器。在图 6 中,现在 F 成为关注层, G 成为前馈层:

y₁=x₁+attention(x₂)
y₂= x₂+feedforward(y₁)

🎉现在使用可逆残差层代替标准残差使得在训练过程中只存储一次激活而不是 N 次T42。

🚀组块

重整器中效率改进的最后一部分处理第三个问题,即前馈层的高维中间向量,其可以达到 4K 或更高维。

由于前馈层中的计算独立于序列中的各个位置,因此前向和后向传递的计算以及反向计算都可以分成块。例如,对于向前传球,我们将有:

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

前向传递计算中的分块[图片取自 Reformer 论文]

🚀实验结果

作者对两个任务进行了实验:图像生成任务 imagenet64 (序列长度为 12K)和文本任务 enwik8 (序列长度为 64K),并评估了可逆变换和 LSH 哈希对内存、准确性和速度的影响。

🎉可逆变压器匹配基线:他们的实验结果表明,可逆变压器节省内存而不牺牲准确性:

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

可逆性对 enwik8 和 imagenet64 训练表现的影响[图片和说明取自 Reformer 论文]。

🎉LSH 关注度与基线相符:📔注意,由于 LSH 注意力是完全注意力的近似,其准确性随着哈希值的增加而提高。当哈希值为 8 时,LSH 注意力几乎等同于完全注意力:

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

LSH 注意力在 imagenet64 上作为散列回合的函数的效果[图像和说明取自 Reformer 论文]。

🎉他们还证明,随着序列长度的增加,常规注意力会变慢,而 LSH 注意力速度保持稳定,它在 8GB GPUs 上以通常的速度运行于长度约为 100K 的序列上:

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

注意力评估的速度是完全注意力和 LSH 注意力输入长度的函数。

与变压器模型相比,最终的重整器模型表现类似,但是在长序列上显示出更高的存储效率和更快的速度。

💻Trax:代码和示例

🤖重整器的代码已经作为新的 Trax 库的一部分发布。Trax 是一个模块化的深度学习训练和推理库,旨在让您从头开始理解深度学习。重整器代码包括几个例子,您可以在图像生成文本生成任务中训练和推断。

🙏承认

我要感谢祖卡斯·凯泽生动地介绍了改革者并提供了补充材料。我还要感谢 Abraham Kang 的深刻回顾和建设性反馈。

📚参考资料和相关链接:

** [## 改革家:高效的变压器

理解连续数据——如语言、音乐或视频——是一项具有挑战性的任务,尤其是当有…

ai.googleblog.com](https://ai.googleblog.com/2020/01/reformer-efficient-transformer.html) [## Transformer:一种用于语言理解的新型神经网络结构

神经网络,特别是递归神经网络(RNNs),现在处于领先方法的核心…

ai.googleblog.com](https://ai.googleblog.com/2017/08/transformer-novel-neural-network.html)

我要去(数据)冒险了!—霍比特文本分析

原文:https://towardsdatascience.com/im-going-on-a-data-adventure-hobbit-text-analysis-a0a5cb116ed1?source=collection_archive---------50-----------------------

解释自然语言处理技术的整本书的数据分析。

在这篇文章中,我分析了 J. R. R .托尔金的书《霍比特人》的全文。我主要关注的是提取关于书籍情感的信息,以及熟悉 NLP 的技术之一——文本分块。我们将回答谁是这本书的主角,情绪如何随着每一章而变化,以及-哪一对矮人在一起出现的次数最多!

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

《霍比特人:意外之旅》

探索性分析

快速浏览一下数据总是应该的。它有助于了解我们在处理什么,验证数据质量,但也允许一些初步的见解。通过对句子进行分词,我得到它们的总数是 4915。它们分为 18 章。

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

每章的句子数量变化很大。最短的一章有 150 个句子长,最长的一章有三倍多。我们可以看到,当章节从第三章到第十章变得更长时,“情节变得越来越复杂”。然后,随着两个急剧的变化,它们的长度逐渐变短。从句子长度来看,稳定性要高得多。最低平均句子长度和最高平均句子长度的最大差异在 30%左右(句子最短的章节平均在 45 左右,最长的在 60 字左右)。如果我们仔细观察,细微的差别显示了一个类似的章节长度模式——最长的句子在第八章到第十章。最短的——第三、第十一、第十四和最后一个。我对散文的句子长度做了一个小小的研究,建议(例如这里的)平均长度应该在 15-20 个单词之间。如果我们把这作为一个参考,托尔金的写作风格是明显不同的。

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

情感分析

我开始为文本中的每一个句子获得一个情感分数。为了这个目的,我使用了一种叫做 VADER 的方法,它可以在 nltk . perspective 包中找到。通过调用sentimentintensitiyanalysizer上的 polarity_scores ,我们得到 4 个分数:复合、正、负和新。复合分数是一个一维的标准化句子分数,基于词典中单词的等级。它的取值范围是-1 到 1。根据标准,一个句子被认为是中性的,复合得分在-0.05 到 0.05 之间——高于 0.05 的都是积极的,低于 0.05 的都是消极的。Pos、neg 和 neu 是可以被分配到每个类别中的文本的比例,并且总和为 1。

出于这个分析的目的,我将使用复合分数,但在分析之前,让我们看看它在 Hobbit 文本上是如何工作的(这四个数字分别是:复合分数、正分数、负分数和新分数):

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

《霍比特人》中最多的肯定句和否定句

我觉得下面的配乐很搞笑:

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

句子及其复合词、词性、否定词和 neu 分值。

我完全支持,每个人都应该有选择。但另一方面,它显示了这种方法的缺陷。似乎因为这个句子太短,所以它受到了“不”的严重影响,而句子本身是一个完全中立的陈述。知道这些句子平均至少有 40 个单词长,我有足够的信心在分析中使用这种方法。

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

看上面的情节,我们可以看到小说以积极的情绪开始,可能是对开始旅程的兴奋。然后,它大部分保持在中性范围内,只达到一次负分,然后再次以正数结束。

让我们更详细地看看每一章和句子的百分比。一般来说,肯定句占所有句子的 25%到 40%,否定句占 30%左右。虽然每一个情绪组按章节划分的比例没有强烈的波动,但我在肯定句的百分比中发现了一个有趣的模式。除了一个例外,每一次增加都伴随着肯定句百分比的下降,反之亦然。会不会是整本书不断变化的氛围在戏弄读者?这是一个很长的镜头,但情节讲述了一个很好的故事。

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

文本分块

根据定义,组块需要多音序列来分割和标记它们。这个想法变得简单时,显示了一个例子。

1.命名实体

在第一次尝试中,我们将以自动方式从文本中提取命名实体——我知道书中的人物,并且可以列出他们,但是很容易错过一些重要的东西。这个任务变得更加简单,因为在库中提供了一个 nltk.ne_chunk() 函数来实现这个目的。

对于输入,我们需要准备一个句子,其中每个单词都转化为一个单词及其词性标签的元组,例如:

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

多音标记句

当把句子的每个单词输入到 nltk.ne_chunk() 时,我们得到一个 nltk。树对象,它以清晰的图形方式显示了哪个部分匹配块标准。在这个例子中,这意味着成为一个 NNP——单数专有名词,由“Oin”和“Gloin”满足。

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

nltk。树对象

我发现 nltk.ne_chunk 能够很好地处理我的数据。尽管还需要做更多的工作。许多常用词被认为是命名实体,因为它们是用大写字母书写的,例如“Hill”。我限制列表的想法是删除英语单词语料库中包含的所有以小写字母书写的单词词条。

为此我使用了nltk . corpus . words . words()。这仍然有点棘手,需要一些领域知识(当然是阅读这本书),例如,这种方法会将比尔博从命名实体中排除。

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

当时只有几个词,我决定手动删除,例如:“Tralalalally”和“Blimey”。整本书中前 15 个命名实体的结果列表(基于它们的出现次数)如下所示。

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

《霍比特人》中的 15 大命名实体

我们可以更进一步,按章节分析出现次数最多的主要人物。三个主要角色——比尔博、索林和甘道夫,毫无疑问,贯穿了整个故事。虽然在第一章中甘道夫的出现肯定更多。咕鲁是一个独一无二的角色。另一方面,史矛革在书的结尾得到了最多的关注,我们仍然可以看到他已经在第一章被宣布了。

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

我们还可以将提取的命名实体与前面分析部分的句子情感得分进行匹配,并查看某些字符是否在肯定句中出现的次数多于否定句。

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

除了埃尔隆德,情绪的分布在人物之间没有很大的不同。从前面的情节中,我们知道埃尔隆德在书中出现的次数相对较少,所以他的结果可能会有偏差。

事实证明,这并不一定意味着性格是好是坏。这也是有意义的,因为情感分数是根据角色自己说的话以及他被描述的时候来计算的。一个快乐的坏人可能不会在这样的情节中浮出水面。不过我们确实知道,没有一个霍比特人的角色仅仅被放在好/坏的环境中。

2.命名实体之间的关系

出于学习的目的,我想定义我自己的组块规则。在第一次尝试中,它是由已经存在的函数 nltk.ne_chunks 自动完成的,但是我们可以选择任何配置的任何词性标签集来从文本中提取。

下面的语法由 4 个 nnp 组成——单数专有名词。中间的两个是必需的,剩下的两个是可选的,用“?”表示。它们都由可选的 CC(并列连词)、TO、VBD(动词、过去式)或 IN(介词或从属连词)连接。

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

我的目标是让任何一组实体通过动词“talked to”以及简单的“and”连接起来。实际上,它导致从下面的句子中提取这样的 4 个组块:

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

列表中提取的块

很快,德瓦林躺在巴林旁边,菲利和基利躺在一起,多丽、诺里和奥里躺在一起,欧因、格洛因、比弗、博弗和邦布尔不舒服地堆在火边。

“lay”在词性方面被认为是一个 NN,这就是为什么 Dwalin 不幸被这个逻辑遗漏的原因。我计算了这些命名实体块一起出现的数量。

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

命名实体对及其出现次数

我们现在知道哪对矮人在一起出现的次数最多了——是基利和菲利,没有接近的亚军!我们也看到只有一组矮人和非矮人角色——比尔博和巴林。同样的角色也有成对的名和姓(例如比尔博·巴金斯),这是因为在我上面的定义中,名词之间的任何单词都是可选的。

摘要

借助一些工具,我们可以对整本书有一个有趣的了解。虽然它们可能不太准确——我认为用数据分析来总结艺术是非常困难的——但这是学习新技术的一个好方法。

分析的代码可以在这里找到。

这篇文章主要发表在数据部维基上。

如何提高数据科学家的工作效率

原文:https://towardsdatascience.com/im-how-to-be-more-productive-as-a-data-scientist-d6f75163527f?source=collection_archive---------16-----------------------

如果你想获得报酬并改变世界,为什么你应该掌握不性感的技能

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

喷火摄影在 Unsplash 上拍摄的照片

数据科学家操纵数据

如果你的数据没有良好的结构,你就无法建立有效的机器学习管道。如果您的数据状态不佳,您就无法构建一个像样的可视化。如果您的数据一片混乱,您就无法交付太多东西。

数据科学绝对是一个很酷的工作领域。这个领域正在发生惊人的进步,它正在改变世界。我们经常听到 ML、AI 和 NLP 等热门缩写词。这些先进的技术确实令人敬畏,但我们世界的现实是,数据科学家工作的很大一部分是用来清理和处理数据的。

在你可以创建一个很酷的可交付产品之前,你需要收集数据,整理数据,清理垃圾。正如迷因所说:就像冰山一样,大部分进入可交付物的工作并不是你的客户或用户所看到的。

根据一些调查,数据科学家多达 60%的时间都花在清理和组织数据上需要明确的是,许多数据科学家所做的大部分工作都是操纵数据,这对于初级角色来说尤其如此。

数据科学不仅仅是 ML 和高级分析,数据科学是处理数据的科学。建模技术和洞察力很重要,解释直方图或散点图的能力也很重要,要知道你应该警惕从小样本中得出结论……这些都很重要,是我们工作的价值得以实现的地方,但为了分析数据,它必须处于可用状态。

面对这一事实,你可以采取一些心态。一是真正的工作是进行机器学习和高级分析,我们必须进行枯燥的数据处理才能得到结果。另一个观点(也是我推荐的观点)是,数据操作是我们交易的基础,我们应该致力于掌握它。我认为这不仅从态度的角度来看是好的,从经济的角度来看也是好的。掌握数据操作和清理从根本上来说是有价值的,并且将在早期推动你的职业发展。

生产力和价值

下一节将深入探讨一点基础经济学,并提供一个关于就业的市场驱动视角。我认为这既有趣又是求职者的宝贵视角。

工作就是你为了钱出卖你的技能/时间。雇主付给你薪水不是因为他们想让你过上好日子,而是因为他们需要你为他们工作。

在一个完全信息的自由市场中,没有一个理性的利己主义的市场参与者会为一件商品或服务支付比他们所获得的价值更高的价格。考虑到现实世界的问题,需要做一些说明。市场是受管制的,所以它们不是完全自由的。雇主在招聘时肯定没有完整的信息,所以他们可能会判断失误,支付过高的工资。以我的经验来看,自利和理性的部分通常适用于雇主和雇员之间的互动,这一点通常会变得更加真实,公司越大,公司越小,所有者的同理心就越能发挥作用。

这种交易观的重要结果是,你的生产率是你报酬的上限。也就是说,从长远来看,你得到的报酬不会超过你能为雇主创造的价值。

你越有效率,你的时间就越有价值。因此,你的生产力越高,你得到的报酬就越多。如果你在一个工作稀缺的竞争市场中,最有生产力的人将得到这份工作(或者在不完全信息的情况下被认为是最有生产力的人)。

不幸的是,你可能不会得到你时间的全部价值。你的公司会想从你的劳动中获利,也就是说,他们愿意付给你的报酬会少于或等于你提供给他们的价值。谈判和供求关系会让你的薪水降到这个水平以下。生产力只是设定了上限,但却极其重要。幸运的是,对于 2020 年的数据科学家来说,存在巨大的技能短缺,因此我们能够获取大量的劳动力价值。

这种生产力观念是你应该专业化的原因之一。擅长某事需要时间。你的时间有限,所以你应该把精力集中在某个特定领域,这样你卖给雇主的时间就更有价值。

专业化的另一个主要原因是减少竞争。更少的供应意味着你可以在谈判阶段获得更多的价值。这种生产力的想法也是为什么一个公司会投资工具,但这是另一个时间的讨论。

这种手工经济学的关键要点是:如果你想得到更多的报酬,考虑一下你的生产率。

对于那些没有经济动机的人来说,生产力对于项目的成功也很重要。如果你在有限的时间内完成一个项目,你完成工作的速度越快,就越有可能实现你的目标。

作为一名数据科学家,如何提高工作效率?

到目前为止,我概述了两点:

  1. 数据科学家花费大量时间处理数据
  2. 提高你的生产力符合你的利益

如果您的大部分时间都花在操作数据上,并且您想要提高您的生产率,那么提高您操作数据的能力是有意义的。

据我所知,提高生产率最有效的方法是提高你的技能。根据我的经验,处理数据的主要工具和技巧是:

  • 结构化查询语言
  • 操作系统和外壳
  • Python / R
  • 电子表格
  • 文本编辑器
  • 正则表达式

我还介绍了其他一些基本技能,这些技能与数据处理没有直接关系,但对数据科学家的工作效率也很重要。

  • 搜索引擎和研究技巧
  • 写作和文件
  • 测试和检查您的工作

数据处理技能

结构化查询语言

SQL 是用于操作数据库中数据的工具。这是数据科学家的基本技能。大多数结构化数据保存在数据库中。如果你想分析数据库中的数据,你需要擅长 SQL。

示例:

想象你在一家营销公司工作。你有一个客户来找你,他想要一个仪表盘来显示他们最近活动的效果。如果幸运的话,您需要的所有数据都在一个数据库中,可能存储在多个表中。

您可能需要为您的仪表板创建一些图表来显示:按天销售、按地区销售、销售来源。您需要能够计算出您的可视化套件的数据需要什么样的结构,然后尽快将数据从数据库中取出。

您可能需要使用一些公共表表达式(cte)、一些连接,并使用一些函数来转换数据。这只是一个简单的查询,这些查询可能很复杂,需要数百行 SQL。这是这项工作的基本部分之一。您越快整理好您的数据,您就能越早开始构建您的仪表板。几乎所有的数据科学任务都需要这些技能,因此掌握这些技能是必不可少的,也是很有价值的。

根据我的经验,许多数据分析师认为 SQL 是核心技能**。Python 和 R 等语言被视为数据科学家的专业工具。如果你是一名学生,读到这里,你可能会想“但我想成为一名数据科学家!”。现实情况是,成为数据科学家和从事机器学习等高级课题工作的最快、最赚钱的途径可能是从一家尚未完全接受现代数据科学的公司的数据分析师开始。**

如果你擅长 SQL,你可以得到这份工作,然后一旦你适应了自己的角色,你就可以开始介绍你的 Python 技能,给你的老板留下深刻印象,也许你会有机会参与任何出现的高级分析项目。否则,经过几年的工作和一点业余学习,你将拥有令人敬畏的 SQL 技能,学会基本的 ML 技能,并能够获得一份扎实的数据科学工作,从事你想做的高级工作。

你真的需要精通 SQL。

操作系统和外壳

操作系统为完成工作提供了一套强大的工具。使用鼠标完成的单调而耗时的任务可以通过几个命令在 shell 中编写脚本。任务可以通过计划任务或 cron 作业实现自动化。可以使用 choco(windows 上)、home brew(MAC OS)和 apt(Ubuntu)等软件包管理器来安装和更新程序。操作系统中有许多功能,虽然作为数据科学家您不需要掌握这些工具,但您应该很熟悉。

Shell 脚本语言值得多解释一下。Bash、windows cmd 和 PowerShell 是 Shell 脚本环境的一些例子。它们非常强大,您应该熟悉这些工具。除此之外,你可以用它们来重命名、移动和编辑大量的文件,只需要几行文字。

一个简单的 shell 脚本如何帮助您完成工作的例子是,如果您在多个目录中有 1000 个相似的文件,您希望将它们合并到一个文件中。您可以编写一个脚本来读取所有文件的内容,将输出合并成一个文档,然后将其写回磁盘。显然,这比手工操作要好得多。

你可以用像 Python 或 R 这样的语言来完成很多这样的任务,但是外壳将一直存在,因为它是操作系统。

Python / R

这些语言非常适合内存中的数据操作、处理 API 和 web 抓取,以及。csv 格式,可用于在操作系统上操作文件。

这些语言是魔法发生的地方,互联网上对训练机器学习等时尚话题给予了很多关注,所以我不打算在这里讨论这些。为了完成工作,您应该熟悉许多数据操作任务。

数据帧操作—这与 SQL 中的操作相同,您需要能够快速重塑数据并构建新列来显示数据的特征—深入研究这一点

数据不仅仅存储在平面文件和数据库中,还有其他数据格式,比如 XML 和 JSON,您应该能够处理它们。能够反序列化和序列化 JSON 对于处理 API 非常重要。

互联网上有很多来自 twitter 等服务的 API 形式的数据。这些 API 允许您通过互联网查询数据集。数据通常以 JSON 等结构化格式返回给您,然后您需要将其转换成数据帧进行分析。库的存在是为了处理流行的 API,但是你应该熟悉使用没有包的 API。

除了可以在 shell 中进行简单的文本操作之外,这些语言对于脚本编写非常有用,我处理过的一个例子是:我们收到了一个包含 1000 个电子表格的文件夹,每个表格都有一台机器上的一份单独的日报告。我们需要将这些放在一个文件中进行分析,使用 R I 编写了一个脚本来导入各个电子表格,然后遍历文件夹,将所有文件读入一个列表,然后组合各个数据帧。

电子表格

适用于小型数据集和数据输入。有利于跟踪工作。非数据科学家使用它,所以你需要知道它。大多数商务人士可以使用电子表格,它们非常便携。Excel 只能容纳一百万行数据,因此它是有限的。电子表格操作不像编写好的代码那样可重用,而且很难通过编写工具来提高生产率。

你需要擅长电子表格,因为其他人知道如何使用电子表格。对于大多数人来说,数据分析意味着电子表格,所以如果你与非数据科学家互动,你很可能不得不使用电子表格作为交流的媒介。人们会给你电子表格,你需要了解他们做了什么。你需要能够清楚地展示你的工作,因为客户和经理可能希望看到计算是如何进行的。

电子表格也是你解决问题的好工具。例如,假设您有一个包含姓名和年龄列表的电子表格,您必须将其添加到数据库中。您应该能够快速地将这些姓名和年龄转换成正确格式的列(例如,(‘name’,‘age’),以便您可以将其复制到 SQL insert 查询中的 values 语句中。

你应该擅长使用 excel,但你不应该生活在 excel 中,电子表格是你工具箱中的强大工具,但数据科学家主要生活在代码中。

文本编辑器

文本编辑器是一个强大的东西。它们是你用来检查原始数据文件的工具,是操纵这些原始数据文件的方法。文本编辑器是处理数据任务的重要工具。

我上面的电子表格例子很好地使用了文本编辑器。您可以在 excel 中创建格式为(‘姓名’,‘年龄’)的列,但是如果您将它直接复制到文本文件或 SQL 编辑器中,它将复制“(‘姓名’,‘年龄’)”,因为它是一个字符串。使用文本编辑器,您需要能够使用类似 find 的工具删除外部的双引号,并用空白替换双引号,或者垂直选择双引号并手动删除它们。

有许多文本编辑器,你真的需要熟悉一个。windows 默认记事本并不是一个好的选择,因为它非常有限,但许多 ide,如 VS Code 和 RStudio,都有很好的文本编辑功能。对于下一级的文本操作,看看 vim 和 emacs,它们在终端中可用,许多图形文本编辑器支持这些程序提供的一些功能。

正则表达式

这里特别提到了 Regex。它们本身并不是一套独立的工具,但是它们非常有用,你应该知道它们的基本知识。

正则表达式基本上允许你以一种通用的方式描述字符串,允许你指示计算机给你带来一个字符串的变体。

正则表达式有用的一个简单例子是替换. csv 文件中的日期。假设您有一个日期格式为 yyyy-MM-dd hh:mm:ss 的平面文件,例如 2020–01–25 20:13:00,并且您想要将日期更改为 1 月 28 日,您可以对[0–9]{ 4 }-[0–9]{ 2 }-[0–9]{ 2 }执行正则表达式匹配,并将其替换为您的日期。也就是 4 位数,然后是“-”,然后是 2 位数,然后是“-”然后是 2 位数。这是一个简单的例子,但它应该展示 regex 的强大功能,以及为什么您应该花一些时间学习基础知识。

关于自动化的一个注记

工具是自动化。您可能会想,这项工作将会自动化,而且会的,有了更好的工具。例如,在 VBA,我们过去必须为数据分析编写循环,现在有了 pandas 和 dplyr 这样的包,我们可以编写列表达式并调用 mutate()。

这些工具将不断进步,变得更加强大,关键是你必须学会如何使用它们。把这些工具想象成神奇的语言,你在告诉计算机你想做什么,你做得越好,你就越容易表达你的愿望。

变得更好需要练习和对学习的承诺。在编程中,您经常会面临一个选择,要么编写复杂而强大的东西,要么手动重复任务,随着时间的推移,您将更擅长编写复杂的东西,这将是优雅的,但您经常会发现,在编写优雅的脚本和用电子表格、文本编辑器和一点编程拼凑一个数据处理解决方案之间有一个权衡。

其他重要技能

搜索引擎和研究技巧

“如果你给一个饥饿的人一条鱼,你可以喂他一天,如果你教他如何捕鱼,你可以喂他一辈子,如果你教他如何谷歌,他可以学会如何喂饱他的整个村庄,给他衣服和房子。”—欧文·弗拉纳根,2020[有问题的引用]

你需要擅长使用搜索引擎。大多数编码问题都可以通过正确表达您的问题来解决,这种表达方式会给您带来文档、论坛帖子和堆栈溢出响应。为了做到这一点,您需要了解术语并练习阅读技术文档。从更广泛的意义上来说,这也涵盖了学术研究和 google scholar。

写作和文件

作为一名数据科学家,你需要写作。你需要写电子邮件,你需要解释你自己和你所做的工作。基本上,你需要能够写出人们能读懂的句子,并且能够组织一个段落。这是任何职业的基本技能,需要练习。你写得越好,你要做的工作就越少,如果你给你的同事、经理或客户发的是没有上下文的冗长混乱的电子邮件,你将不得不写更多来解释这一点。你应该善于提炼你试图传达的关键点,然后围绕它们来组织你的文章。

除了优秀写作的基本要素之外,围绕文档的良好习惯还有一个生产力的争论。向人们解释事情需要时间;如果你记录下获得结果的步骤,你可以与需要知道的人分享,而不是单独解释。这对加入你团队的人尤其重要;如果你有很好的文档,当一个新人加入时,你可以给他们看文档,并给他们一些关于流程的培训,之后他们应该能够查阅文档,了解他们在你的培训中记不起的任何事情。

投资于好的文档可以节省您的时间。从长远来看,培养记录过程的习惯和技能将会节省时间。这一点也适用于代码中的注释。

“文档是你写给未来自己的情书”——达米安·康威

测试和检查您的工作

数据科学家承担着重要的工作。我们必须提供见解来帮助决策者确定最佳前进道路,我们建立机器学习模型来做出预测,这些预测可以帮助决定人们是被雇佣还是让从监狱获释。甚至像数据输入和配置数据库中的东西这样的小任务也留给我们来检查。测试和检查你的工作是工作的一大部分。

出错可能会很严重,如果你在为销售团队制作仪表板,你可能会让人们困惑或紧张,直到问题出现。如果你向一位 CEO 展示数字,让他做出紧急决策,那么数百万美元可能会丢失。如果你正在制造无人驾驶汽车,人们可能会死亡。

在现实世界中,除了你和你的团队,没有人检查事情是否做得正确。检查你的工作可能是工作中最重要的部分,交付糟糕的工作会导致严重的伤害和损害你的声誉。虽然这是枯燥乏味的,但应该尽最大努力注意细节。

当我们谈论生产力时,把事情做好将是重中之重。

结论

我们听到很多关于对数据科学家的巨大需求,我们看到很多课程教人们成为数据科学家。这些课程中有很多侧重于高级技术,任何数据科学新手都可能认为工作主要是构建和优化模型。当他们听说未来几年存在巨大的技能赤字并且需要数百万数据科学家时,他们认为这意味着数百万人需要培训和部署机器学习模型并推进该领域。

我会认为,这个世界不需要数百万人工智能研究人员,这个世界需要数百万能够让数据变得有用的人。这就是这些技能的意义所在,让数据变得有用。在交付任何项目之前,需要做大量的工作来使数据处于良好的状态。很多工作都是单调乏味的,但是没有这些工作,我们就无法取得任何成果。对于有抱负的数据科学家来说,事情并不是这样描述的,我知道这不是我刚开始涉足该领域时所想的。

通过投入时间掌握操纵数据所需的技能,你可以完成更多的工作,增加你的价值。这就是机会所在,也是人们受雇要做的事情。数据处理得越快,就有越多的时间来构建酷的东西。然而在另一个层面上,许多工具都是基于语言的,所以更多的技能意味着使用更优雅更周到的解决方案,这意味着工作更有趣。

作为一名数据科学家,无论你从事什么工作,这些技能总是有用的。我的观点不仅仅是善于使用这些工具会帮助你更好地完成工作,而且我们的态度应该是大声宣传处理数据的好方法。我们应该大声宣传测试和检查你工作的好方法。我们应该大声疾呼将文档集成到我们的工作流程中的好方法。我们应该大声疾呼,让这些技能得到应有的尊重,让我们都能变得更有效率。

我没有图层了——如何定制 TensorFlow 2 图层。

原文:https://towardsdatascience.com/im-out-of-the-layers-how-to-make-a-custom-tensorflow-2-layer-9921942c88fc?source=collection_archive---------17-----------------------

有时需要编写自己的神经网络层,接受非标准数据或以不寻常的方式处理它们。

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

TensorFlow 2 使机器学习框架更容易使用,但仍保留了构建模型的灵活性。它的一个新特性是通过集成的 Keras API 构建新的层,并使用 eager-execution 轻松调试这个 API。

在本文中,您将学习如何在 TensorFlow 2 框架中构建自定义神经网络层。撰写本文时,我假设您对 Python 3 中的面向对象编程有基本的了解。最好是在阅读本文之前先回顾一下__init____call__、类继承和方法重写。

用于构建图层的模板

让我们从一个模板开始,基于它你将建立你的大部分层。

新 TensorFlow 2 层的模板,根据需要使用它。

如你所见,结构很简单。该模板由两个方法组成,__init__和 call。第一个方法是一个类的标准 Python 3 构造函数,我们在其中初始化所有对象和字段。因此,在层的情况下,您在这里初始化将在训练中使用的所有变量。还要记住通过调用super(YourClassName, self).__init__()来调用图层类的__init__方法,否则图层类的构造函数不会被初始化。方法调用是基于给定的输入和变量定义所有向前和向后的地方。你唯一要做的就是定义正向传播步骤,反向传播步骤由 TF2 自动执行。

此外,还有两个强制参数—一个是x_input,另一个是training。输入可以是任何类型,如果需要,还可以添加更多的输入参数。然而,必须至少有一个输入,否则正向和反向传播步骤是不可能的。此外,还有训练增强,我将它设置为默认的False(测试期间默认没有False)。它用于某些层,在测试和训练阶段的行为是不同的。比如 dropout 就是这样一个层,用在这里是因为它只在训练阶段丢弃神经元。

如果你很好奇为什么用call而不是 pythonic 式的__call__,那么看看文章的最后。

自定义层的示例

让我们定义一个更复杂的层,这一次它将执行一个非常复杂的操作,那就是……两个实数的乘法

允许两个标量数相乘的层

这一次,这些层由call方法中的两个输入和一个将两个数相乘的tf.math.multiply方法组成。要使用该层,您只需定义创建多层对象,并通过向其传递值来调用它,如下所示:

一个如何使用我们创建的多层的例子。

先自己试试,再往前跑。下一个更复杂,这次我不玩文字游戏了。但你会熬过去的,相信我。

用 TF2 建立残差层神经网络

让我们假设,你想要创建一个神经网络来预测几个类。为此,您将在流行的 CIFAR-10 数据集上训练网络,该数据集有 10 个不同的类。为了解决这个问题,你选择了残差神经网络(简称 ResNet),但它要求你建立自己的层,因为它们不是在 TF2 实现的,或者你想玩不同的架构。ResNet 由剩余块构成,这些块具有跳跃连接,抵消了消失梯度问题。

ResNet 块

这里有两种类型的块,一种保持输入形状(因此输出形状与输入形状相同),另一种改变。ResNet 块具有如下所示的体系结构,其中最重要的是跳过连接(有时称为快捷连接)。跳过连接只不过是复制输入并将其添加到输出的末尾,这并不神秘,但它工作得很好。

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

ResNet 块的一般视图

将 ResNet 定义为 TF2 的自定义图层

让我们现在尝试建立一个剩余块。我不会根据一些架构来创建层,而是根据一些直觉。此外,我会尽量让事情简单,但它会占用更多的空间(不必要的重复),我会预约如何做得更好。

有了构建 TF2 层的基础,让我们尝试一下构建 ResNet 的新技能,在 CIFAR10 基准数据集中把自己放在靠前的位置。在这里,您可以找到一个带有相应文件的排行榜:

[## CIFAR-10 排行榜|带代码的论文

CIFAR-10 目前的最新水平是 BiT-L (ResNet)。查看 91 篇论文与代码的完整对比。

paperswithcode.com](https://paperswithcode.com/sota/image-classification-on-cifar-10)

让我们首先画出我们的标识块,我们将使用它来构建我们的自定义层(即 ResNet 块)。
首先,我们将构建一个身份块,我称之为ResidualLayer在代码中,这一层由两条路径和三个卷积块以及一条快捷路径组成(见下图)。在训练过程中,宽度通常会提高准确性[1]。随意修改路径的数量,并检查它如何影响结果的准确性,训练时间和其他参数。值得注意的是,两条路径应该有不同的超参数集,以学习如何提取不同的特征集。

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

在我们的例子中使用的剩余块,代码如下。快捷方式块表示前面提到的跳过连接。

第二个残差块不保留输入形状,因此跳过连接必须重新缩放输入。这是用卷积层完成的。其余的几乎与前面显示的剩余块相同。该层将在代码中以与上一个类似的方式调用,但使用 Scal 后缀,所以ResidualLayerScal

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

快捷路径上带有缩放层的剩余块。

残余块的代码

剩余块的代码在这里,用于ResidualLayerResidualLayerScal。代码有点长,所以你不能在中型网页上看到它的全部。你必须点击它,直接进入要点。

保留输入形状的剩余图层

不保留输入形状的剩余图层

注意评论和training=False

使用剩余层

所有的代码看起来都很复杂,但是大部分代码都是某种模式的重复。大部分代码可以(甚至是)通过一个或两个 for 循环重复(一个用于控制深度,另一个用于控制宽度)。但是为了使代码更简单,我认为最好不要在这里使用它。

要创建这样一个层并使用它,您只需以与MultiplyLayer相同的方式创建该类的一个实例。

请随意修改这些参数以获得更好的结果。

将其分组为块

从“纸”入手,总比没有任何计划就匆忙投入工作要好。因此,让我们制作一个块的模式,块将由五个剩余层组成,如下图所示,并被进一步称为…猜怎么着,一个剩余块!

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

一个由 5 个定制剩余层组成的剩余块。

在这样的块中有两种类型的层,一层不保留输入形状— ResidualLayerScal,四层保留— ResidualLayer。定义好模块后,让我们构建一个模型并测试这些层。

建立模型

整个模型的模式不会更复杂,它是四个剩余块的重复,在开始时具有批量标准化、激活函数和卷积层,在结束时具有密集输出的另一个批量标准化。

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

整个模型的模式,看起来很简单,你不觉得吗?

该模型将通过创建一个继承自tf.keras.Model类的类来实现。姑且称模型类为FunnyResNet(听起来一点都不好笑)。代码来了:

这个模型实现了前面展示的模式,它是如何工作的你可以在我的另一个故事中了解到。

[## 如何从头开始创建 TensorFlow 2 模型——一个“无用”的例子。

想象一下,您想要构建一个可以在项目中使用的模型。你选择做张量流 2…

towardsdatascience.com](/creating-a-trashy-model-from-scratch-with-tensorflow-2-an-example-with-an-anomaly-detection-27f0d1d7bd00)

培训和评估

定义好你的模型后,你需要做的一件事就是用model.compile()定义它,用model.fit()训练模型。这里展示的整体 Resnet 模型你可以在我的知识库中找到,还有图像标准化、规范化和增强。

在编译之前将两幅图像传递给模型的目的是初始化权重形状。这是在 TF2 自动完成的,基于第一次出现的输入。

在这里,您可以找到一个 Jupyter 笔记本,上面有所有代码:

[## 丹尼尔维奇/搞笑网

TowardDataScience-DanielWicz/funny resnet 上的教程示例

github.com](https://github.com/DanielWicz/FunnyResNet)

或者直接在谷歌的 colab:

[## DanielWicz/FunnyResNet 谷歌联合实验室

TowardDataScience 教程的 resnet 示例](https://colab.research.google.com/github/DanielWicz/FunnyResNet/blob/master/SimpleResNet.ipynb)

摘要

在 TF2 创建图层并不是一件难事,您需要记住以下几点:

  • 它将复杂的结构简化成一个可用的“块”,可以很容易地重复多次。
  • 该层必须从tf.keras.Layer继承才能工作。
  • 您必须定义两种方法,__init__call
  • __init__方法中,你定义了所有将在调用方法中进一步使用的变量,如对象(如层)、常量。
  • call中,您定义了应用于数据的所有操作,如分层、乘法、加法、蒙版、转置等。
  • 记得在call中传递training参数,否则,dropout 和 batch normalization 不起作用。

此外,记得使用专用的张量流函数

总是在层中使用 TF 函数,否则你将不能用model.fit()来编译它们或者用@tf.function语句来使用它们(这意味着低得多的性能)。在 TF2,你需要的几乎每一个 pythonic 函数都有替代品。例如,在一个层中执行一个 For 循环,你将使用for i in tf.range(N)或者使用你使用的数组tf.TensorArray

说明

  • 定义了call方法而不是__call__,因为__call__ 在调用call之前会调用一些额外的东西。这些东西包括初始化权重的方法,以及确保该层正常工作的所有其他东西。这是一个与Model相似的案例,你可以在我的故事中读到。

附加阅读

  • 谷歌自定义图层指南:此处
  • TF2 图层类文档:此处

参考资料:

[1]s . Zagoruyko 和 n . Komodakis(2016 年)。广泛的剩余网络。 arXiv 预印本 arXiv:1605.07146

图像增强掌握:15+技术和 Python 代码的有用功能

原文:https://towardsdatascience.com/image-augmentation-mastering-15-techniques-and-useful-functions-with-python-codes-44c3f8c1ea1f?source=collection_archive---------32-----------------------

平滑的 python 代码可自行扩充您的影像数据集。

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

无论我们是在享受 Keras 还是 Pytorch 我们都可以使用美妙的图书馆来有效地提升我们的形象。但是那些特例呢,其中:

  • 我们的数据集不具有平凡的结构(例如,3 个输入图像和 1-2 个分段输出)。
  • 在我们所做的事情上,我们想要完全的自由和透明。
  • 我们希望增加这些库没有提供的功能。

对于所有这些情况和许多其他情况,我们必须能够掌握我们的图像增强。此外,我每次都使用自己的函数,而且我不是唯一一个这样做的人(我想)。因此,在这篇文章中,我将向您介绍并我的功能来执行图像增强。

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

举个例子,我会用一个朋友的照片来提醒我在加拿大度过的美好时光。我希望你喜欢这张照片,因为这是你在这篇文章中看到的唯一一张照片…🍁👼🍁

我将分段它,以便有一个实际案例使用我们的图像和目标函数。这会让你对将要向你描述的方法的灵活性有一个概念:

  • 翻转
  • 农作物
  • 内核过滤和锐化
  • 虚化
  • 旋转、平移、剪切、缩放
  • 断流器
  • 色彩空间
  • 聪明
  • 对比
  • 均匀和高斯噪声注入
  • 渐晕
  • 透镜畸变

⚠️:这篇文章的目的是不是证明增强技术是如何设计的,而是如何理解使用它们。⚠️

一些有用的功能

在我开始之前,我想解释一下的常见结构 每个方法都会有。它实际上将是一个对象来初始化。这个对象将用我们的样本作为参数被调用,并将返回我们的扩充样本**。就这些吗?是的,就这些!那么,在我们的增强功能之前,让我们先从一些有用的功能开始。**

调整大小

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

第一个有用的函数允许我们用(width, height)形状来调整图像的大小。这个允许我们看到所有其他的类将如何被初始化。我们用上游参数化的实例化一个大小的对象。在我们的例子中,所有的样本(图像和目标)都将以这个相同的尺寸返回。有了这种类型的功能,我们可以轻松地同时以我们想要的方式处理我们的图像和目标。

夹子

剪辑功能是一个非常有用的功能,尤其是当你需要从一个色彩空间切换到另一个色彩空间或者在 0 和 1 或者 0 和 255 之间重置图像时。

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

默认情况下,如果只指定了一个阈值,最小阈值为 0。

使正常化或标准化

在传递模型中的输入之前,我们通常希望标准化标准化我们的数据。当然,这些操作可以在特定的上完成。

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

默认情况下,对整个图像执行规范化和标准化。

托特索尔

最后,如果你使用的是 Pytorch,你需要将你的图片转换成 T1。唯一需要注意的一点是,使用 Pytorch,我们的图像是先通道后通道,而不是最后一个通道。最后,我们还可以留下选择张量的输出类型的可能性。

怎么用?

也许在这一点上,你没有看到的设置有多简单。然而它是。我们所要做的就是定义一个我们想要在样本上做的转换列表,就这样。之后我们不碰任何其他东西。注意转换的顺序有其重要性。由你决定。

我们现在可以深入文章的目的,看看图像增强技术。

翻转

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

第一种,也是中最简单的一种,由随机在图像的水平垂直轴上执行翻转组成。换句话说,有 50/50 的机会进行垂直翻转,有 50/50 的机会进行水平翻转。

农作物

为了进行图像增强,通常的做法是随机裁剪图像。换句话说,我们裁剪一部分随机 大小的图像,并覆盖一个随机 区域

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

裁剪图像的尺寸可以从尺寸(height, width)比率中选择**。如果没有指定裁剪的比例最大尺寸,那么我们将默认认为它是图像的尺寸。**

内核过滤器

一般情况

我们将开始一些更有趣的事情。滤镜是伟大的经典作品,但我认为能够轻松创建我们自己的卷积滤镜是很重要的。如果您不知道滤波器的工作原理,请参考我关于 Conv2d 的文章。

[## Conv2d:终于明白了向前传球会发生什么

2D 卷积层及其参数的视觉和数学解释

towardsdatascience.com](/conv2d-to-finally-understand-what-happens-in-the-forward-pass-1bbaafb0b148)

所以我想做一个通用的函数来使用我们自己的过滤器。

尖锐

就过滤器而言,通过选择上游的过滤器并应用随机加权,可以走得更远。例如,我向你介绍用于锐化我们图像的滤镜。

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

value of center从 0 到 65。

虚化

为了完成过滤器,最流行的是用来随机模糊我们的图像。有很多方法可以模糊我们的形象。最著名的是平均、中值、高斯或双边滤波器

平均模糊度

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

内核大小从 1 到 35

关于平均滤波器。顾名思义:它允许我们对给定中心的值进行平均。这是由一个内核做出的。它的大小可以指定或多或少的模糊。为了用平均过滤器增加我们的图像,我们只需要用随机大小的内核来过滤我们的输入图像。

高斯模糊

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

内核大小从 1 到 35

最后,以同样的方式平均模糊。高斯模糊不使用平均滤波器,而是使用滤波器,因此值对应于中心的高斯曲线。注意,内核维度必须只包含奇数**。**

视角转换

到目前为止应用最广泛的图像增强技术是透视变换。有旋转**、平移剪切、缩放。这些转换可以在一个 3D 维度中执行。通常,他们只在 2D 使用,这是一个遗憾。让我们利用我们所拥有的一切,对吗?**

旋转

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

翻译

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

剪羊毛

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

缩放比例

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

结合一切

我不会在 2D 图像的 3D 变换上花更多的时间,因为我写了一整篇文章。所以我选择了本文末尾的函数。如果你想了解更多关于齐次坐标三维变换矩阵的信息,我邀请你去看一下。

** [## 如何将 2D 图像转换成三维空间?

用 python 执行变换矩阵。数学和视觉解释视频游戏和深…

towardsdatascience.com](/how-to-transform-a-2d-image-into-a-3d-space-5fc2306e3d36)

应该注意的是,这个函数允许我们根据 4 个建议的矩阵随机执行转换。秩序有它的重要性。这里有剪切,然后是旋转,然后是缩放,最后是平移。注意,平移是通过图像尺寸的比例来完成的。****

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

结合随机旋转平移剪切和缩放

断流器

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

剪切块替换为 0,在整个输入上同时裁剪目标

断流漂亮直观。它包括随机移除输入图像的区域。它在中的工作方式与我们之前谈到的裁剪相同。但是我们没有返回相关的区域,而是删除了它们。因此,我们可以再次允许用户提供要删除的区域的每比例的最小和最大尺寸**,区域的最大数量**,以便同时或不同时从目标中剪切区域,我们可以对每个通道执行此剪切,并且还可以选择已删除区域的默认替换值。****

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

剪切替换为 1,输入通道尺寸,不裁剪目标

色彩空间

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

现在我们到了我觉得最有趣的部分。很很少考虑的一部分**。如果我们知道色彩空间,我们可以利用它们的特性来增强我们的图像。给你一个简单的例子,有了 HSV 颜色空间,我们可以尽情地提取叶子,感谢它的颜色和根据我们的愿望随机改变它的颜色。这是一件非常酷的事情!我们理解拥有自己的图像增强功能的好处。当然,这需要多一点创造力。因此了解我们的色彩空间以充分利用它们是很重要的。特别是因为它们在我们的(深度)机器学习模型的预处理中可能是至关重要的。**

** [## 了解并可视化色彩空间,以改进您的机器学习和深度学习模型

解释、分析和实验 14 种流行的颜色空间以及它们对我们模型的准确性的影响。

towardsdatascience.com](/understand-and-visualize-color-spaces-to-improve-your-machine-learning-and-deep-learning-models-4ece80108526)

聪明

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

亮度从-100 到 100

让我们再坚持一会儿。图像增强的一个伟大经典就是能够玩亮度。有几种方法可以做到这一点最简单的是简单地添加一个随机偏差

对比

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

对比度从-100 到 100

同理,玩对比也很简单。这也可以随机进行。

噪声注入

最后一种相当常见的图像增强技术是噪声注入。实际上,我们只添加了一个与输入大小相同的矩阵。该矩阵由随机分布的个元素组成。可以从任何随机分布中进行噪声注入。实际上,我们只看到其中的两个。但是可以随意走得更远😃

制服

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

高斯的

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

渐晕

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

最后,用得少但不是没用。有些相机有渐晕效果。想想我们如何通过随机模仿这种现象来增加我们的形象也是很有趣的。我们也将尝试给予用户灵活性。我们将能够决定从效果可以随机开始的最小距离,决定它的强度,甚至决定它是一个走向黑色还是走向白色的效果

透镜畸变

最后最好的最后。我很惊讶它没有被更多地使用。但是它可以模仿相机镜头的扭曲。就像透过圆玻璃看一样。我们看到的是扭曲的,因为镜片(玻璃)是圆的。所以,如果我们的图像是从一个有镜头的相机中拍摄的,为什么我们不模拟它们呢?这应该是默认用于图像 s 的,至少我是这么认为的。

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

因此,我建议在最后一个函数中,通过利用径向系数k1, k2, k3切向系数p1, p2来随机模拟我们的镜头失真。在该方法中,系数的顺序如下:k1, k2, p1, p2, k3。我邀请你看一看关于这个主题的 OpenCV 文档。

[## 使用 OpenCV 进行摄像机校准——OpenCV 2.4.13.7 文档

照相机已经存在很长时间了。然而,随着 20 世纪 90 年代后期廉价针孔摄像机的出现…

docs.opencv.org](https://docs.opencv.org/2.4/doc/tutorials/calib3d/camera_calibration/camera_calibration.html) 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

知识就是分享。
支持我,获取访问 中我所有文章的点击此处

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

来源和参考

一切都是自制免费使用(包括图片和 gif)

特别感谢 Elise 授权使用此图片👋****

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值