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

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

我的第一次人工智能黑客马拉松

原文:https://towardsdatascience.com/my-first-ai-hackathon-4e67cf988dd2?source=collection_archive---------11-----------------------

我学到的一切,以及你如何赢得你的第一次黑客马拉松

我涂鸦的尝试

退出。好奇。焦虑。就像任何第一次参加黑客马拉松的人一样,我脑海中闪过许多想法。这是我成为传奇 CS 之神的第一步。尽管面临艰巨的挑战,但前方道路的每个转弯处都会有意想不到的回报。在接下来的 5 分钟左右的时间里,请允许我带你去神秘化,我会分享更多关于我的经历,让你在注册你的第一次黑客马拉松时有一个更好的了解。

背景

大约半年前,我和几个朋友参加了一个应用程序设计比赛。它的结构相当简单。比赛前的几天,由外部供应商和专家举办的可选培训研讨会占满了时间。虽然我们没有通过第一轮,但它让我对黑客马拉松的进行有了一个简单的了解。几个月过去了,我设法让一些朋友加入了我们的第一次人工智能黑客马拉松。我们中的几个人是未来的计算机科学学生,具有非常基本的编程知识。我们还对人工智能和一些方便的工具有了初步的了解(非常感谢在线课程)。差不多就是这样。完全不知道我们为自己注册了什么,我们一头扎进了黑客马拉松。

黑客马拉松结构

首先,这是一个很大的遗憾,但是黑客马拉松是百分之百虚拟的,符合所有的健康指南(世界仍然被新冠肺炎震撼)。它持续了 3 周,真正的黑客马拉松在最后才举行。前两周基本上是“培训阶段”,参与者被关于人工智能和流行的机器学习*台 google colab 的速成讲座轰炸。在此期间,我们安排了几次 AMA 会议,在会上我们可以澄清我们的任何疑问,但考虑到长时间尴尬的沉默,结果证明这是徒劳的。

问题陈述

首先,我们给出了一个虚构的场景。在不远的将来,通过控制论的增强,动物被广泛用作监视船,参与者的任务是开发人工智能模型,以识别和识别动物图像和音频文件。比赛分为 6 个不同难度的计算机视觉(CV)和语音分类(SC)挑战。这些以训练和测试数据集的形式出现,以判断参与者模型的准确性和性能。第一个 CV 和 SC 挑战数据集在活动开始时发布,我们有大约两周的时间来微调我们从讲座中学到的关于这两个挑战的基线模型。此后,第三和第四个挑战在黑客马拉松第一天发布,最后两个挑战在黑客马拉松第二天发布。只有成功达到最低及格标准的队伍才能参加随后的挑战。

黑客马拉松前准备

正如一些成功人士曾经说过的,“如果你没有做好准备,你就是在为失败做准备。”虽然我们的参与主要是为了更多地了解当地的黑客马拉松场景,并获得宝贵的经验点,但我们不会不战而退。经过一些深入的研究,我指的是几个小时的谷歌搜索,我能够提取一些关于过去黑客马拉松的有价值的信息。尽管问题陈述和结构可能(并且很可能应该)有很大的不同,但是强烈建议任何希望更清楚地了解预期情况的人采取这一步骤。幸运的是,我们发现了一个 2 年前参加过同样活动的选手写的博客。与本文类似,它包含了一份冗长的第一手资料,描述了发生的一切,以及一些示例代码。

是的,虽然我确实提到了问题陈述的变化,但我怎么强调访问这些样本代码的重要性都不为过。数据集、人工智能模型和函数可能略有不同,但当我们最终构建和编写我们的机器学习模型时,整体框架是至关重要的。一些团队包含了他们使用的各种 ML 技术,这些都是值得深入研究的有趣领域。

培训,学习,再培训,再学习

为了启动我们的培训和学习,每个人都完成了一个快速 python 速成课程,以刷新我们的记忆,加速我们的神经引擎。组织团队还提供了 30 多个由 IBM 人工智能讲师录制的讲座视频。这时,我们先前的人工智能知识派上了用场。由于主题的深度,仅仅在几周内给出对 AI 的全面理解几乎是不可能的。许多重要的关键想法被轻松地通过,更多的时间花在解释 Google Colab 中的代码实现上。即便如此,这些解释还是让人觉得仓促且不充分。我们不得不依靠我们最好的朋友谷歌来获得更多的答案。与它看起来的相反,能够搜索信息和在线帮助是计算机科学和软件工程中的一项关键技能。即使是世界上顶尖的程序员也经常在网上寻找解决问题的灵感,见鬼,他们甚至应该在大型技术编码面试中加入这一点。

克林特·帕特森拍摄的 Unsplash 图像

掌握一件事的最好方法是教它。感谢我最喜欢的物理学家,伟大的理查德·费曼,我们能够更好更快地掌握概念。轮流分解概念,互相教导,好像对方完全没有先验知识,这有助于暴露我们概念上的缺陷。这也让我们能够补充我们的学习。我们纠正了彼此的错误,并确保每个人都对我们的神经网络模型有一个完整的(或至少有能力的)理解。

在不深入探讨技术领域的情况下,我将试图解释我们工作的关键。所有团队都在 Google Colab 中获得了一个基线 ML 模型,在这个模型中,我们将解析给定的训练和测试数据集,以查看我们的模型执行得有多好。与从头开始,一层一层地学习构建模型的基本结构不同,基线代码采用了迁移学习。想象一个博士研究项目,其中研究人员不是从零开始,而是在最新的相关研究论文的帮助下研究当前信息。从一个预先写好的模型开始,我们的团队不得不对代码进行逆向工程,以完全理解每一行代码在做什么。虽然这大大提高了我们对迁移学习和各种神经网络模型的理解,但它推迟了我们在黑客马拉松中的进度。

图像识别人工智能模型通过对特定的标记数据集进行训练来工作。训练集通常由一幅图像(例如一只猫)和一个标签(“猫”)组成。类似于给孩子看图片卡,我们“教”人工智能正确地识别一只猫的图像,而不是任何其他动物。有不同的方法来实现这一点,例如特征提取等。然后,对于经过训练的模型,下一步将是使用模型从未见过的新图像的测试数据集来测试训练的好坏,并评估它可以识别图像的准确程度。这相当于一个人类孩子参加一个小型考试来验证他的学习。AI 正确识别的图像越多,精确度和性能就越高。

现在,有多种方法可以提高这种性能。虽然模型调整确实改善了结果,但数据扩充通常被证明对准确性有更大的提升。这一步包括在将训练数据集传递给我们的 AI 进行学习之前,对其进行清理和细化。首先,检查标签错误的数据总是有用的。毕竟,你不会想给你的孩子一张大象的照片,然后告诉他们那是一只长颈鹿。移除或重新标记此类数据可能会很繁琐,但可以通过自动化来增强。

鸭肉还是披萨?memegenerator 生成的图像

接下来,我们希望我们的人工智能能够准确一致地识别图像,即使在条件不理想的情况下。当我们指着一只鸭子的蹼足时,我们希望我们的孩子能认出它是一只鸭子,而不是橙色的披萨片!通过数据扩充,我们可以通过水*或垂直翻转图像、旋转、剪切、裁剪、添加模糊或雨水滤镜来模拟恶劣的天气条件、添加高斯噪声、更改色调饱和度亮度等方式,向训练数据中引入随机变化。这些只是各种技术来模拟我们的人工智能可能被‘测试’的独特变化。

作者图片

最初,在黑客马拉松的早期阶段,测试数据集相当一致和简单。然而,随着挑战的进行,数据集中出现了更多的变化。一些照片更模糊,甚至光线不好,雨滴遮住了主体。这就是我们的数据增强帮助扭转了局面。结果,我们的人工智能经过了充分和相关的训练,能够在雨中看到一只恐龙的照片,并识别出它是一只恐龙,而不是一团灰色。

结论

就像生活中的任何冒险一样,在开始旅程之前设定一个目标总是有益的。设定一个可实现的目标对于突出团队的重点,确保每个人在整个比赛期间都遵守纪律是至关重要的。你们中可能有很多人考虑参加黑客马拉松只是为了曝光,只是为了涉猎一点,获得一些经验。设定一个目标,可以是前 10 名甚至前 3 名登上领奖台,任何目标都会极大地提升整体体验。团队将更积极地参与并开发一个可行的解决方案。如果你没有达到任何一个最初的目标,那也没什么。我可以有把握地说,我的团队玩得很开心,结果从这次经历中收获了很多。

这基本上概括了我的第一次人工智能黑客马拉松。希望这能激励你鞭策自己,报名参加下一次黑客马拉松!最重要的是,记得玩得开心,一路上结交新朋友!祝大家黑客快乐。

我在 Kaggle 的第一枚金牌:NLP 竞赛的技巧和诀窍

原文:https://towardsdatascience.com/my-first-gold-in-kaggle-tips-and-tricks-for-an-nlp-competition-cec48dda5895?source=collection_archive---------25-----------------------

或者如何用拥抱脸模型解决回归问题

马克斯·哈林金在 Unsplash 上的照片

自然语言处理是深度学习中最令人兴奋的领域之一。在计算机视觉领域,我们使用迁移学习已经有几年了,并且有非常强大的预训练模型,如 VGG、Resnet 或 EfficientNet。随着著名的注意就是你需要的全部论文的发表,自然语言处理领域也有了突破。Huggingface 上有数千个预先训练好的 NLP 任务模型,使我们能够用比以往更少的数据创建最先进的模型。

关于比赛

比赛的主持人是 CommonLit ,一个非盈利教育科技组织。他们提供免费的数字阅读和写作课程。在教育中,给学生适合他们阅读水*的课文是很重要的。老师不应该直接给一个 10 岁的孩子读歌德的《浮士德》,然而课文仍然应该具有挑战性。

这就是 CommonLit 经常要求教师和学者根据可读性对某些文本进行排名的原因:

目标值是布拉德利-特里(Bradley-Terry)对 111,000 多个摘录进行成对比较后得出的结果。3-12 年级的教师(大多数在 6-10 年级授课)是这些比较的评分者。—斯科特·克罗斯利,竞赛主持人之一

结果是从-4 到+2 的等级,数字越大表示可读性越好。每个节选一次由几个人评价。然后将*均值作为最终得分。在挑战中,有一个包含文本和相应分数的训练数据集。该模型应该学习分数,然后预测新文本的分数。

共同的方法

预先训练的拥抱脸模型已经变得非常流行,用于任何类型的 NLP 任务:分类、回归、摘要、文本生成等等。在竞争的早期就很明显,transformer 架构的性能明显优于传统的机器学习方法或 LSTM 架构。因此,很大一部分参与者关注于变压器的微调。由于生成带标签的训练数据的资源密集型过程,可用的示例相对较少,大约 2800 个示例。大多数人最初使用 Roberta-base,一个有 12 层、12 个头和 1.25 亿个参数的变压器,它已经给出了很好的结果,无需太多的微调。但是,我们确定了几个可以显著提高性能的字段,我将在后面简要说明:

  • 大型模型架构
  • 辨别学习率
  • 定制头
  • 装袋和堆放
  • 伪标记
  • 基础设施

大型模型架构

从其他比赛中得知,预训练模型的较大版本通常表现更好。某些架构通常有小型、基础和大型版本(例如 RoBERTa)。这些区别主要在于隐藏层的数量、隐藏状态的大小和头的数量。

罗伯塔基地对罗伯塔大

这种联系具有直观的意义:更多的参数允许更好的模式映射,即模型可以学习更多和更深。较大的型号在这次比赛中也表现得更好。然而,由于数据有限,或者他们只是在训练数据上过度拟合模型,许多团队未能使模型收敛。我们的突破是实施了区别学习率和自定义头。

辨别学习率

众所周知,在迁移学习中,以相同的学习速度训练所有层并不总是有意义的。有时所有嵌入层都被冻结,头部以较大的学习速率被训练,然后所有层以较低的学习速率被再次训练。

这个想法是神经网络的第一层学习一般概念,然后每层学习越来越多的特定任务信息。

由于这个原因,我们不得不调整第一层小于,例如,新的头部,它仍然包含初始化时完全随机化的权重。因此,我们实现了一个定制的优化器。我们对 RoBERTa 主干使用线性递增的学习速率,对头部使用 1e-3 或 2e-4 的固定学习速率(取决于预先训练的模型)。递增的学习速率从第一层的 1e-5 开始,到最后一个嵌入层的 5e-5 结束。

定制头

我个人一开始觉得这个话题有点混乱。当您微调预训练模型时,通常会删除神经网络的最后一层(例如分类头)并用新的神经网络替换它。变压器通常输出最后隐藏状态。这包含相应序列的所有标记的所有最后隐藏状态。在开始时,总是有特殊的 CLS 令牌,根据 BERT 论文的作者,该令牌可用于下游任务(并且在没有进一步微调的情况下也用于分类)。这个想法是,这个令牌已经是整个序列的表示。这个令牌在这场比赛中经常被用作回归头。另一种可能性是额外输出池状态。这包含 CLS 令牌的最后隐藏状态,由线性层和 Tanh 激活函数进一步处理。这些输出也可以用作回归头的输入。还有无数更多的可能性和一个非常全面的总结可以在这里找到。
我们尝试了不同的表达方式。最后,我们还使用了 CLS 代币和一种注意力集中的形式。BERT 论文的作者在他们的一项测试中显示,连接多个层比只使用最后一层可以产生更好的结果。

Jay Alammar 在他的博客中写道:哪种载体作为情境化嵌入效果最好?

背后的想法是不同的层包含不同的信息。因此,我们已经连接了最后 4 层的 CLS 令牌。此外,我们为最后 4 层生成了注意力权重。然后我们连接结果,并通过最后一个线性层传递它们。下面是实现过程:

装袋和堆放

如前所述,我们在这场比赛中没有太多的训练数据。超过 2 个时代的训练导致排行榜和我们的交叉验证分数之间的过度拟合和巨大差距。我们使用 5 个折叠来训练数据,并为每个折叠创建一个模型。我们创建了一个评估调度程序,以便随着分数的提高(根据较低的 RMSE)更频繁地进行评估。在 2 个时期内具有最佳验证分数的模型被保存。我们设法得到了与排行榜的密切关联:我们的简历越低,我们的 lb 分数越好。这是每个挑战中最重要的事情之一:

如果可能的话,你应该努力缩小本地简历和排行榜之间的差距。否则,您无法以有意义的方式进行本地测试。

伪标记

如前所述,训练数据集非常小。我们使用新的、未标记的文本,如维基百科文章(可通过 api 免费获得),并根据我们的训练示例的长度调整文本的长度。然后,我们使用现有的集成预测新数据的得分,并使用新数据和旧数据来重新训练模型。

一个重要的发现是,用更好的集合重新计算伪标签并没有提高多少分数。聚合更多的数据总是比提高伪标签的质量更重要。

基础设施

我们将 Kaggle 基础设施(内核、数据存储)和 Google drive 与 Google Colab 结合使用。我们更加灵活,因为我们可以在多个实例上进行训练,并且在 Colab 上每个帐户可以访问多达 3 个 GPU。一个结构良好的工作空间有助于组织和跟踪实验。通过使用 Kaggle api,可以非常容易地将数据从 Colab 推送到 Kaggle 或从 Kaggle 拉回来。我们还使用了一个 slack 频道来讨论我们的想法和跟踪我们的实验。

不可思议的队友

我的队友尤金与社区分享了令人难以置信的有用的笔记本,编写了自定义标题并创建了训练程序。他的方法被广泛使用,他还出版了第一本真正有效的RoBERTa——大型培训笔记本。祝贺他在第一场比赛中获得第一枚金牌。

结论

HuggingFace 是一个用于各种 NLP 任务的优秀*台,并提供了大量预训练模型的选择。然而,在这场竞赛中,如何进一步调整模型以获得更好的结果变得很清楚。如果没有预先训练的模型,结果会更糟,同时仍有优化的潜力。Kaggle 的参与者表明,从模型架构到优化器到训练程序,所有领域都有改进的空间。这些方法也可以转移到其他任务中。我希望 CommonLit 可以利用结果,使教师在未来更容易为学生提供正确的文本。

感谢您的阅读,祝您愉快!

进一步阅读

  1. 培训用完整笔记本:https://www . ka ggle . com/chame call/clrp-fine tune-Roberta-large
  2. HuggingFace 上的预训练模型概述:https://huggingface.co/transformers/pretrained_models.html
  3. 组装方法:https://towards data science . com/ensemble-methods-bagging-boosting-and-stacking-c 9214 a10a 205
  4. 伯特微调教程:https://mccormickml.com/2019/07/22/BERT-fine-tuning/

如果你对数据科学感兴趣并且还没有注册,请随时使用我的推荐链接加入这个社区。

我的第一次黑客马拉松

原文:https://towardsdatascience.com/my-first-hackathon-3f6d5fbf7d91?source=collection_archive---------18-----------------------

为什么你一定要参与其中,如果可以的话!

考尔·克里斯詹在 Unsplash 上拍摄的照片

这个周末,我参加了我的第一次黑客马拉松,Hex Cambridge。很久以来,我一直想参加一个,但是每当我感兴趣的一个出现时,我总是找到借口不参加,不可否认,主要是因为我害怕我不够好,或者我不喜欢它。公*地说,我应该更快地参与进来,我肯定会建议任何想做一个的人去做吧!

那么什么是黑客马拉松呢?简而言之,这本质上是一个短期的编码挑战,在 24/36 或 48 小时内,你就能想出一个技术解决方案或产品。在某些情况下,这些解决方案或产品必须解决一个明确定义的挑战,而在其他情况下,有一个总的主题,你可以自由地创造。它包括作为一个团队一起工作,通常与你以前没有见过的人一起工作,深夜编码和比萨饼/外卖食品,产生一个由你的同事和评判小组评判的工作成果。

这次黑客马拉松有几个挑战,包括来自贝莱德、华为和 Optiver 的挑战,都集中在一个特定的任务上。然而,我们决定把重点放在 Marshall Wace 整体挑战赛上,该挑战赛旨在开发一个社会公益应用程序,这给了我们很大的权限。

我们的想法是什么?鉴于当前疫情突出的无家可归问题,对无家可归者有害的做法是敌意建筑。这种做法在长凳上很明显,长凳上有明确的座位,这样某人就不能躺下,或者地板上有钉子,睡在上面不舒服,灯整夜亮着,甚至播放很大的声音。这些做法迫使无家可归者离开他们可以获得资源的市中心,并试图将他们藏起来,而没有实际解决问题或帮助那些有需要的人。因此,我们认为强调这种做法是很重要的,这样我们就可以让人们远离它,并希望尝试解决它所带来的一些问题。

为此,我们认为一个应用程序将允许外出或甚至在家的个人能够标记这种敌对的架构,并最终提醒公众和决策者这种做法的流行。有两种方法可以做到这一点,首先是那些在现实世界中四处走动的人,如果他们发现了敌对的建筑,他们可以拍一张照片并提交到网站上。这张照片将包含元数据,如拍摄时间和地点,然后可以通过这些提交的照片创建的活动 twitter feed 和网站上标识这些照片拍摄地点的交互式地图进行可视化。另一个选择是让用户利用谷歌街景,或者让我们自己建造一个机器人,从他们自己的家出发到世界各地去识别敌对的建筑,这也会出现在地图和 twitter 上。这当然都是通过图像分类算法来实现的,该算法能够识别提交的图片是否是恶意建筑。

就我们的技术栈而言,我们的计划是使用 cassandra 数据库来存储照片元数据,使用 google cloud bucket 来存储实际照片,使用 HTML、css 和 javascript 前端,使用 fast.ai 机器学习算法来对图像进行分类,使用 flask 后端将所有这些结合在一起,以便能够在 google cloud 上托管。

我是怎么适应这个的?鉴于这是我的第一次黑客马拉松,我真的不知道我到底能在哪里提供帮助,我有机会在机器学习方面或后端方面提供帮助。最后,我和另一个以前使用过 Flask 的团队成员合作,主要在后端工作。我的主要任务是让谷歌云架构正确运行应用程序,并帮助一些 Flask 基础设施。这当然是非常棘手的,因为我基本上是从零开始,但我设法快速刷起来,让网站工作。我在这么短的时间内学习了 google 云应用程序开发、flask 构建、cassandra 数据库集成和模型部署,尽管还有很多东西需要学习!

我们的结果是什么?嗯,我们设法在 hacktheurban.space 上建立了一个部分运行的网站,它设法满足了我们的一些目标,但不是全部。嗯,我们让 wesbite 自己在 hacktheurban.space 上启动并运行,托管在谷歌云*台上,如下图所示:

作者图片

作者图片

作者图片

在这个系统中,网站连接到数据库,因此任何图像都可以被上传、发送到数据库,并且元数据将被存储,包括位置和图片本身。嵌入的 twitter feed 也出现了,从最后的三张照片中可以看到。我们还可以实现街景步行,你可以输入不同的纬度和经度值来环游世界,就像在伦敦桥上看到的一样:

作者图片

然而,我们在开发地图方面有所欠缺,twitter 集成也没有用于谷歌云,图像分类的实际模型也无法嵌入(尽管后两者我们最终设法在完全集成的本地机器上工作)。

最终,我们获得了基于 cassandra 框架的 DataStax Astra 数据库最佳使用奖,当然,我们对此非常自豪(只是在最后 30 分钟内才设法让它工作)!虽然最终的应用程序现在由于缺乏功能而被删除,但如果你想四处看看,可以在这里找到代码库!

那么,我学到了什么?:

  1. 黑客马拉松对于快速学习新技术或者强化你已经掌握的技能来说是非常棒的。对我来说,这是学习如何使用 flask,以及如何将其与谷歌云*台集成。
  2. 任何大型项目早期的技术集成都是关键。在这里,大多数问题都是关于将 Flask 后端集成到谷歌云*台上,因为我们最初努力连接数据库,加载模型和集成 twitter,只能在一个小时内克服数据库连接,其他两个问题在谷歌云*台上根本不存在。
  3. 有时候,最好的办法就是卡住,看看什么管用,什么不管用。在如此短的时间内举办一次黑客马拉松,你通常不得不继续进行,而不是犹豫使用什么,尤其是如果你以前没有使用过的话。边做边学是关键,即使不总是成功,你最终还是会在过程中学习。

除此之外,这次黑客马拉松还有许多很棒的提交材料,可以在这里找到:【https://hex-cambridge.devpost.com/project-gallery。其中包括一些令人惊叹的决赛选手,他们的工作主题包括在线教室中的情绪检测、手机在飞行模式下的信息传输以及计算机之间的安全数据传输。看到所有这些,并与从事这些工作的一些人交谈,真是太棒了。

总的来说,这是一次很棒的经历。未来我会关注更多的黑客马拉松吗?是的,肯定的!我玩得很开心,和了不起的人一起工作,学到了很多东西。虽然我们的解决方案最终没有完全按照我们想要的方式工作,我们也没有赢得任何主要奖项,但我肯定可以带走很多东西,并希望将我的学习应用到下一个项目和我的博士学位中!现在,该睡觉了!

[## scikit-learn 决策树分类器简介

towardsdatascience.com](/introduction-to-decision-tree-classifiers-from-scikit-learn-32cd5d23f4d)

我的第一个 NLP 管道

原文:https://towardsdatascience.com/my-first-nlp-pipeline-99d24aafb773?source=collection_archive---------12-----------------------

照片由西格蒙德Unsplash 上拍摄

为有监督的文本分类问题创建 NLP 管道

这篇文章基于由阿迪·沙莱夫和我为 2021code fest创建的一个工作室。

在数据科学领域,特别是在 NLP 领域迈出第一步时,我们经常会遇到一组全新的术语和短语;“契合”、“转换”、“推论”、“度量”等等很多。虽然可用的信息源允许理解这些术语,但并不总是清楚这些不同的工具如何最终结合在一起,以形成我们能够用于新数据的基于生产机器学习的系统。

从标记数据集到创建可应用于新样本的分类器(也称为监督机器学习分类)应该经历的有序阶段集被称为 NLP 管道。

在本帖中,我们将为一个监督分类问题创建这样一个管道:根据电影的描述对电影是否是剧情电影进行分类。完整的代码可以在这里找到。

监督机器学习分类的 NLP 管道——到底是什么?

我们从数据集开始我们的旅程,数据集是一个分类已知的文本记录表。我们的数据就像一股水流,我们想用它来创造我们的产品。为此,我们将创建一个管道:一个多级系统,其中每一级都从上一级获得输入,并将其输出作为输入转发给下一级。

我们的管道将由以下阶段组成:

作者图片

虽然我们构建每个阶段的方式会因问题而异,但是每个阶段在我们的最终产品中都有一个角色,一个闪亮的文本分类器!

数据

我们将使用的数据基于来自 Kaggle 的电影数据集。我们将使用这些数据来确定一部给定电影的类型是不是剧情片——是还是不是,这是一个二元分类问题。我们的数据是一个 pandas 数据帧,有 45466 条记录,删除空条目后有 44512 条。

1。探索数据

每当我们开始处理一个新的数据集时,在我们继续进行设计决策和创建模型之前,我们必须了解我们的数据。让我们回答一些关于数据集的问题:

  • 概视图是什么样的?

因为我们希望使用概述来确定电影是否是剧情电影,所以让我们来看一些概述。

  • 概观有多长?最长的概述?最简短的概述?

  • 我们有多少戏剧电影?

  • 概述中出现频率最高的词是什么?在特定类型的概述中?

探索数据的阶段对于接下来的阶段很重要,因为它允许我们获得在接下来的步骤中做出决策所需的信息。

  • 任何有助于我们更好地了解数据集的信息!

2。清洗&预处理数据

现在我们对手中的数据有了更好的理解,我们可以继续清理数据了。这一阶段的目标是在使用数据创建模型之前,删除数据中不相关的部分。“不相关部分”的定义因问题和数据集而异,在现实世界中,可以对问题进行实验以找到最佳方式。

  • 删除短于 10 的条目

在数据探索过程中,我们注意到我们的一些概述篇幅较短。因为我们希望使用描述来对流派进行分类,所以我们可以删除长度小于 15 的记录,因为包含如此少字符的概观可能不具信息性。

  • 删除标点符号

因为我们想捕捉描述戏剧电影和描述其他电影的词语之间的区别,我们可以去掉标点符号。

  • 词汇化

词汇化用于将一个单词的不同屈折形式组合在一起,这样它们就可以作为一个项目进行分析。让我们看一个例子:

我们现在可以对我们的数据应用术语化:

在清理和预处理之后,我们的文本就可以转换成特征了。

3.列车测试分离

在创建模型之前,我们应该将数据分为训练集和测试集。训练集将用于“教授”模型,测试集将由我们用来评估我们的模型有多好。在现实世界的场景中,我们也经常分割一个验证集,在其中我们可以使用 hyper 参数调整。

下面的代码会拆分。更多示例可在[这里](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html)找到。

4。特色工程

在构建管道的这一点上,我们已经熟悉了我们的文本数据,它是“干净的”并经过预处理的。尽管如此,它仍然是文本。由于我们的最终目标是为我们的数据训练一个分类器,是时候将我们的文本转换为机器学习算法可以处理和学习的格式,这种格式也被称为“vectors”

将文本数据编码成向量的方法有很多种:从基本的、直观的方法到基于神经网络的最新方法。让我们来看看其中的一些:

计数向量

将文本描述为一个向量,在这个向量中,我们保存了词汇表中每个单词的出现次数。我们可以选择向量的长度,这也是我们词汇量的大小。

你可以阅读更多关于计数向量和创建它们时使用的不同参数这里

TF-IDF 矢量

使用 TF-IDF 向量,我们可以解决使用计数向量时遇到的一个问题:在文本数据中多次出现的无意义的单词。在创建 TFIDF 向量时,我们将词汇表中每个单词的出现次数乘以一个因子,该因子标记该单词在语料库中的其他文档中的出现频率。这样,出现在我们的语料库中的许多文档中的单词将在我们的特征向量中获得更小的值。

你可以在这里阅读更多关于 TF-IDF 矢量和创建它们时使用的不同参数

5。建模

使用矢量器后,我们的电影概述不再用文本表示,而是用矢量表示,这允许我们使用我们的数据来训练模型。

我们现在可以使用我们的训练集来训练一个模型。这里我们训练多项朴素贝叶斯,但是 Scikit-Learn 中可用的许多其他算法可以类似地应用,并且当解决一个新问题时,我们通常会检查不止一个算法。

6。评估

在训练一个模型之后,我们想要评估它在新数据上的表现如何。为此,我们对数据进行了划分,并留出了一个测试集。我们现在将使用我们的模型为测试集做出的预测来评估我们的模型。

我们将根据正确答案和我们的模型所犯的错误创建一个混淆矩阵

二元分类的混淆矩阵

我们现在可以使用混淆矩阵产生的值来计算一些其他指标:

通常,我们建立模型的第一次尝试不会有惊人的指标。这是一个很好的时间回到早期的阶段,尝试做一些不同的事情。

7。推论——对新样本使用我们的模型

在使用我们的数据创建一个模型来解决我们根据电影的概述来分类电影是否是戏剧电影的问题并评估我们的模型之后,我们可以使用它来确定新的样本- 戏剧还是非戏剧?

由于我们的原始概览在用于训练/评估我们的模型之前已经经历了一段旅程,我们需要以同样的方式处理新样本:

我们现在可以使用我们的模型来预测新样本的类型:

我们的预测是正确的!

总结

在这篇文章中,我们为一个有监督的文本分类问题创建了一个管道。我们的管道由几个相互链接的部分组成(就像一个真实的管道!).我们希望这篇文章能帮助你理解这个过程的每一部分在创建最终产品——文本分类器中的作用。

我作为数据科学家的头六个月

原文:https://towardsdatascience.com/my-first-six-months-as-a-data-scientist-69f6697c9ec3?source=collection_archive---------1-----------------------

办公时间

我学到的技术和非技术课程

奈杰尔·塔迪亚恩多在 Unsplash 上的照片

科学很酷,但我不认为 2000 年或更早的孩子长大后会梦想这样做。对我来说,我首先想成为一名兽医,然后是公园管理员、训狗师、作家,最后是经济学家。我仍然有点想获得最后两个工作角色,就像一些孩子梦想成为律师-医生-宇航员一样(或者律师-医生-美人鱼,但让我们现实一点,美人鱼太棒了,无法学习像法律这样枯燥的东西)。

当然,目标会随着时间的推移而改变,今年 5 月,我获得了弗吉尼亚大学的 was 数据科学硕士学位。毕业几个月后,我获得了第一份全职工作,成为一名数据科学家。我欣喜若狂,因为我能够运用我的技能,向我的新同事证明我自己。在我开始工作的 135 天里,我也有过 426 次感觉力不从心。

这是我从课堂跳到数据科学领域以来学到的技术和非技术课程的清单。作为免责声明,这当然只是我的经验,每个人的会有一点不同。

1.你会用到在✂️学校学到的不到 20%的工具

我真的很喜欢 r 语言编程。如果有选择的话,我甚至参加了上述 it 工作的编码面试。尽管如此,我在工作中 95%的时间使用 Python 和终端(在 VS 代码中),大约 5%的时间使用 SQL,而从我开始使用以来 R 正好是 0%。结果,我在 R 语言中所学的课程(大约是课程的一半)对我来说比在 Python 中所学的课程有用得多。很多作业——比如网络抓取、NLP、Apache Spark 或 Tableau——我根本就没用过。这是意料之中的事,因为很难猜测你在这份工作中会做些什么。

如果你是一个真正致力于用特定语言编码的人,我建议尽早询问你的招聘人员团队使用什么。即使你可以“技术上”用你选择的语言编码,如果团队使用其他的语言,这将使代码审查和集成更加困难。对我来说,我真的很享受在 Python 上变得更好,但是如果是在 Scala 之类的东西上,我不认为我会喜欢它。

2.AWS (&云服务)是王道👑

当我开始的时候,AWS 和我并不像握手那样熟悉,但是现在我每天都在使用它。众所周知,AWS 的产品种类繁多,让人很难知道对于给定的任务,你需要什么样的服务。更糟糕的是,在 AWS 中搜索如何做某事通常会指向 5 个听起来基本相同的服务。

为了解决这个问题,我一直在使用 ExamPro 为 AWS 云从业者认证做准备。要学的东西实在太多了,但在我学习的过程中,我发现自己在建立联系,学习可能对我未来的工作有用的服务。最终我也会参加考试,这也有望成为一个很好的简历助推器。我不认为我会成为一名 AWS 巫师,但是如果我能成为一名相对称职的 AWS 圣骑士,我会接受的。

AWS 被我加冕。GIF by GIPHY

像谷歌云和 Azure 这样的服务也很受欢迎,但如果你不知道你可能会使用哪一个,我还是会诚实地推荐 AWSTechJury.net 发现,2020 年,AWS 在新企业云采用中占有 76%的份额。尽管如此,大多数公司在某种程度上使用云服务,了解他们如何工作以及他们提供什么是有好处的。

3.了解硬件对于有效排除软件故障非常重要💻

在学校里,我们经常被给予干净的、玩具般的例子,以便专注于一个特定的高层次问题。在拥有较小数据科学团队的公司,你经常会自己处理真实、混乱、丑陋的数据。如果是大数据,试图让它在您的管道中运行就像试图让犀牛穿上舞会礼服。

了解你的电脑在幕后做什么将会有很大的不同。对于处理有问题的数据,我使用watch -d -n 0.5 nvidia-smihtop等命令来跟踪 GPU/CPU 的使用和内存,使用df -h来监控给定目录中文件的大小,以防空间溢出。我还使用 tmux 会话,以便同时打开多个终端窗口,并防止我的工作在 ssh 登录到远程机器时中断。最后,当我找到一个可行的解决方案时,我仍然会在网上寻找具有更好复杂度的替代方案,这可以在处理大数据集时节省几分钟到几天的处理时间。

这些只是我对抗测试我的机器上限的数据的几种方法——我很想听听你自己的提示和技巧!

4.无时无刻不在谷歌搜索一切🔍

作为一名数据科学新手,学习曲线是持续不断的。你将被要求做的任务在很多时候会感觉完全脱离了领域,这意味着你正在匆忙地找出一个解决方案,解决你甚至不知道存在的错误。你将学会在日常生活中驾驭最随机事物的内在复杂性,虽然你不再需要映射 A → C → Q,但你开始变得更擅长编程,代码库将随着每次迭代变得更有意义。

总而言之,“数据科学家”、“问题解决者”和“职业谷歌人”几乎是一回事。至少对我来说,我觉得我在第一份工作中学到的东西至少和我在大学时一样多,这有点令人惊讶(毕竟,我是在付钱给某人在那里教我东西)。

使用流行的数据科学编程语言的公司是伟大的,因为大量使用的语言也方便地拥有最好的堆栈溢出帖子(这在无数场合下救了我的命)。

5.你的坏习惯不会随着学校的结束而突然消失🍜

这不是数据科学特有的,但我在学校时给自己施加了很多压力,没有像我的同龄人那样经常放松(虽然我住在兄弟会街,所以这也可能是为什么🤔).在期中考试前,我会学习整整一周(有时是一个月——微积分很难),除了打印更多的练习题或续杯,我几乎不离开房间。在非期中考试周,我会强迫自己学习到早上很晚,然后把自己推醒,穿上运动裤、凉鞋和一件旧套头衫,匆匆忙忙地熬到那天早上 8 点或 9 点。从我没有出去的数量来看,我很惊讶我没有在毕业典礼上看起来像一个瘦长、苍白的吸血鬼而吓到每个人。

我一直以为一旦拿到学位,我就会像正常人一样生活。在我想象的这个完美的世界里,我终于可以每天健康地写日记、阅读、冥想、锻炼和饮食。此外,工作不会感觉像工作,因为我喜欢编程,因此我生活中的一切都会一直很棒。

是啊,所以…那没有发生。

虽然工作确实增加了一些额外的结构,但我有一些坏消息;如果你在大学里是一个工作狂,你很可能是一个工作狂…..工作中的。如果你远程工作(像我一样)并且没有太多的会议,那么运动裤、破旧的运动衫和睡发在大多数时候都是不错的选择。所以基本上大学…没有朋友或 darties 在你的窗外大放厥词。

GIF by GIPHY

总的来说,你可能有更多的可支配收入,但是当你工作到凌晨 1 点时,除了“我想我快要解决这个问题了”之外,没有任何其他原因,你会感觉像是生活在阴阳魔界,却在第二天开会前几分钟醒来,再次重复这个循环。善待自己——精疲力尽是不好的,*衡是关键,这一点我仍在学习。

6.在改变世界的同时好好生活🌎

我不同意那些认为数据科学将在 10 年内消亡的反对者,因为公司总是希望信息(即数据)增加利润,并希望人们对其进行定量分析,即数据科学家(或工程师,或分析师,名称并不重要)。在我的工作中,我已经能够直接影响大型计划,并通过我的数据科学产生积极的影响,在我离开后,这些项目将继续存在许多年。

我也非常有理财头脑,我希望我能开始自己的事业,或者如果我选择提前退休的话。有了数据科学,做有影响力的事情和经济富裕之间不再有典型的权衡;你可以两全其美。结合编程有趣的事实,数据科学真的是完美的三连胜。

结论❄️

显然我有点偏见,但我很高兴成为一名数据科学家,并且仍然相信,为了大局,我的不足和自我怀疑是值得的。对于那些在大学里的人来说,在成为专业人士方面,你最紧张的是什么?对于那些现在工作的人来说,当你自己进行转变时,你最大的文化冲击是什么?

一如既往的感谢阅读!失陪了,我要去做兼职了,为一些寄居蟹咨询 ML 算法。

照片由娜佳·贝尔托尔特·詹森Unsplash 拍摄

https://amawest.medium.com/membership

我的 Google Foobar 之旅

原文:https://towardsdatascience.com/my-google-foobar-journey-2d02e8150158?source=collection_archive---------5-----------------------

走查

第 1 级—获得邀请。

FooBar 完成截图(图片作者: Pratick Roy )

索引

  1. 我的 Google FooBar 之旅:第 1 级-获得邀请。(这个)
  2. 我的 Google FooBar 之旅:2.1 级——电梯维护
  3. 我的 Google FooBar 之旅:2.2 级— 整装待发

怎么开始的

时间是 2016 年至 2017 年左右。我是一名年轻的计算机科学大学生,非常想成为一名开发人员。我喜欢编码和构建东西,我同样讨厌做 mcq(选择题)。

我对 MCQs 是恨之入骨,工程应该是 。要想在 MCQs 中取得好成绩,你必须记住一千个捷径公式,学会应用技巧而不是应用概念,并虔诚地避免试图回答难题,这一切都是为了在尽可能短的时间内回答尽可能多的简单问题。

现在我还在上学,但从逻辑上来说,

作为一名工程师,我的工作描述是拿一个足够大、困难和模糊的问题,学习、忘记和重新学习概念,以便将它分解成更小更简单的问题,随着时间的推移赋予它越来越多的形状,直到我对问题的核心概念及其周围的许多边缘情况有一个好的干净的解决方案。

事后回想起来,我认为年轻时的自己在这个分析上是正确的。

然而,所有的大学就业面试总是以 MCQ 回合开始,所以我想你可以很好地衡量我的偏执,不要带着工作机会走出大学。

然后有一天,当我正在摆弄一些代码块时,我可能出现了一些错误,或者需要查找一些语法,当我谷歌搜索时,浏览器扭曲显示了这条消息

FooBar 邀请(图片作者: Pratick Roy )

现在,作为一个为了乐趣而编码的人,我想玩,但是当屏幕动画出现时,我已经点击了第一个堆栈溢出链接。我热情地按下了后退键,但没有成功。

我心烦意乱。我意识到我刚刚犯的错误的严重性。我从之前的 reddit 帖子中了解到这个挑战是关于什么的。这是谷歌足球挑战赛。我刚刚收到一份邀请,我设法浪费了它。

现在,如果你不知道这个挑战是关于什么的,简单地说就是谷歌只邀请秘密招聘程序。一旦被邀请,你就可以解决编码挑战,如果你完成了,你就有机会直接面试谷歌。此外,可笑的严格时间限制和无法使用互联网的标准障碍,是大多数在线编码挑战和面试过程的专利,并不适用。你有大量的时间去阅读、理解、研究、修改和解决问题。

如果这还不明显的话,这正是我渴望的那种挑战。我错过了抓住它的唯一机会。然而,作为一个坚忍的人,我设法很快站起来,笑自己是多么笨拙。

就这样,生活照常进行,然后,在运气和努力的共同作用下,我设法获得了亚马逊的实习机会,给了我 6 个月的时间来证明我在现实世界软件开发环境中的勇气。又一次尝试玩我喜欢的游戏。

我知道这里说的可能有点生存偏见,但是塞内卡曾经说过,

运气是当准备遇到机会时发生的事情。2

而且这次我是有备而来,没有犯什么愚蠢的错误。从那以后,我就成了亚马逊人,并为此超级自豪,那场侥幸逃脱的挑战的记忆也开始慢慢从记忆中淡化。

它是如何结束的

大约几个月前,也就是那次致命的误点击发生* 4 年后,当我再次陷入一些代码中,并希望利用在我之前解决问题的开发人员的智慧时,我的浏览器再次扭曲,向我显示一条熟悉的消息。

FooBar 邀请(图片作者: Pratick Roy )

这一次,我没有重复失礼。这一次风险降低了,我不再需要工作面试,但我想要挑战。我说我想玩,我就加入了。

这就把我带到了上个周末,当时我提交了最后一个问题的代码。曾经逃脱的挑战终于完成了。

现在开始旅程

你有没有进行过一次你计划了很久的旅行,在你的脑海中建立了它,但当你最终到达那里时却感到失望。这是而不是的旅程之一。

我们是一种说书人,fooBar 让你成为渗透并摧毁 Lambda 指挥官的邪恶组织的故事中的主角,在那里你所拥有的只是你的智慧来拯救你的兔子同志。

在这个过程中,你会边走边学。从马尔可夫链到细胞自动机,这个挑战让我接触到了很多有趣的想法和概念。

如果你收到邀请,并且你喜欢编程和挑战,我强烈建议你接受 FooBar 的邀请。

需要注意的另一点是,如果你熟悉 python,那么使用它可能很有意义,因为标准库将为你提供许多有用的函数。我个人使用 Java,因为我对它更熟悉,坦率地说,我不是 Python 的忠实粉丝。也许有一天我会写一篇关于厌恶 python 的帖子。如果是的话,我会把它链接到这里。

这篇文章现在对我来说太大了,所以在接下来的几篇文章中,我将一个接一个地讨论这些挑战,强调我从这次挑战中获得的知识和见解。

但是在结束之前,让我们解决第 1 级的问题 1。

一级

问题 1:重新识别

奴才队伍中有一些不安定因素:ID 号码像“1”、“42”和其他“好”号码的奴才们一直对那些被更无聊的 ID 卡住的可怜奴才们颐指气使。为了*息骚乱,Lambda 指挥官让你根据一个完全万无一失的方案给每个人重新分配新的随机 id。

Lambda 指挥官将质数串联成一个长串:“2357111317192329……”。现在每个仆人必须从帽子里抽出一个号码。该数字是素数串中的起始索引,并且 minion 的新 ID 号将是该串中接下来的五个数字。所以如果一个奴才抽到了“3”,他们的身份证号就会是“71113”。

通过编写一个函数 solution(n)来帮助指挥官分配这些 id,该函数接受 Lambda 的所有素数的字符串的起始索引 n,并返回该字符串中的下五位数字。Lambda 司令有很多爪牙,所以 n 的值永远在 0 到 10000 之间。

—测试用例—
输入:
解决方案.解决方案(0)
输出:
23571

输入:
解决方案.解决方案(3)
输出:
71113

其核心是,这里的挑战是计算一长串素数。每当你面对这个挑战,你的 goto 算法应该是厄拉多塞[3] 的筛子。我很确定 Sieve 会成功,但是我已经忘记了它是如何工作的,所以我在 Youtube 上放了一个视频来复习。现在,让我们来构建解决方案。

重新识别解决方案

因此,一旦筛选功能就绪,我们需要做的就是

  • 稍微修改一下 Sieve 函数,产生一个素数的串联列表。
  • 计算这个列表中从 index 到 index + 5 的子串,因为本质上这将从 index 之后的素数串中给出接下来的 5 个数字。这正是 Lambda 指挥官想要的输出 ID。
  • 此外,考虑到约束条件,该列表需要至少 10000 + 5 个数字长。因此,通过一点强力检查,找出 206412 之前的所有素数,对于我们的用例来说已经足够好了。

仅此而已。如果你对我如何解决其他挑战感兴趣,看看我的回购。

https://github.com/pratickRoy/foobar

在以后的帖子中,我将回顾我解决的其他问题的解决方案的关键见解/经验。我在这里把它们联系起来。要获得相同的通知,请考虑在 medium 上关注我,订阅一封相同的电子邮件,直接发送到您的收件箱!😊

来源、脚注和进一步阅读链接

我的 Google Foobar 之旅

原文:https://towardsdatascience.com/my-google-foobar-journey-a6488df029cf?source=collection_archive---------17-----------------------

走查

2.1 级—电梯维护

FooBar 完成截图(图片作者: Pratick Roy )

索引

  1. 我的 Google FooBar 之旅:第一关——获得邀请
  2. 我的 Google FooBar 之旅:2.1 级——电梯维护。(这个)
  3. 我的 Google FooBar 之旅:2.2 级— 整装待发

故事到此为止

你在 Lambda 指挥官的组织里活了一个星期,你甚至设法让自己升职了。万岁!不过,你的党羽还是没有那种安全权限来拿下 Lambda 指挥官,所以你最好继续工作。快快快。

所以现在我有了 2 级权限,但是要打败 Lambda 指挥官还有很长的路要走。在我寻求释放我的兔子兄弟的过程中,我的下一个障碍,我前进的下一个关键,是一个相当有趣的挑战。

电梯维修

粗略地看,这确实是一个非常简单的问题;魔鬼藏在边缘的箱子里。我一开始用一种非常不干净的方法来强迫自己通过,并且在很大程度上成功了。然而,我就是无法破解一些测试用例,不管我引入了多少黑客。

所以我深吸一口气,睡了个好觉。第二天早上,我起床,喝了点咖啡,重构了代码。它一次性通过了所有的测试用例。

好代码的一个小切线

在我开始写代码之前,我想强调一点,总是试图写干净的代码。我知道这在一个竞争激烈的编码环境中并不真正必要,事实上,有时它会对事业不利。在未来的等级中,我已经采取了许多我在生产环境中永远不会写的捷径,并且永远不会让任何一个我正在审查其代码的人来写。它们让我的生活变得更容易,代码运行得更快,所以我跟着它,你也应该在你的 fooBar 之旅中这样做,但重要的一点是,你应该对这样做感到内疚。

如果你能写出工作正常但不干净的代码,而不用担心上面的伟人[1],那么你可能是一个伟大的程序员,但你将是一个糟糕的开发者。

如果你不同意这一点,我强烈建议你读一读我不久前写的一篇文章,即使读完之后,如果你不同意,请随时给我留言/评论,我们可以进一步讨论这个问题。

现在回到手头的问题

你被分配了繁重的电梯维修任务——唉!除了所有的电梯文档已经在文件柜的底部杂乱无章的堆了好几年,而且你甚至不知道你将要工作的电梯版本号,这不会太糟糕。

电梯版本由一系列数字表示,分为主要、次要和修订整数。电梯的新版本增加了主要编号,例如 1、2、3 等等。当新的特征被添加到电梯中而不是一个完整的新版本时,名为“次要”的第二个数字可以用于表示那些新添加的特征,例如 1.0、1.1、1.2 等。小的修复或维护工作可以用第三个数字“修订”来表示,例如 1.1.1、1.1.2、1.2.0 等等。数字 0 可用作
电梯预发布版本的主要版本,例如 0.1、0.5、0.9.2 等(Lambda 指挥官总是小心翼翼地测试她的新技术,以她的忠实追随者为对象!).

给定一个以字符串表示的电梯版本列表,编写一个函数解(l ),返回按主版本号、次版本号和修订号升序排序的相同列表,以便您可以识别当前的电梯版本。列表 l 中的版本将总是包含主要版本号,但是次要版本号和修订版本号是可选的。如果版本包含修订号,那么它也将有一个次版本号。

例如,给定列表 l 为["1.1.2 "," 1.0 "," 1.3.3 "," 1.0.12 "," 1.0.2"],函数解(l)将返回列表["1.0 "," 1.0.2 "," 1.0.12 "," 1.1.2 "," 1.3.3"]。如果两个或多个版本相同,但其中一个版本包含的数字比其他版本多,则这些版本必须根据它们拥有的数字数量按
升序排序,例如[“1”、“1.0”、“1 . 0 . 0”]。列表 l 中的元素数量至少为 1,不会超过 100。

—测试用例—
输入:
Solution.solution({"1.11 "," 2.0.0 "," 1.2 "," 2 "," 0.1 "," 1.2.1 "," 1.1.1 "," 2.0"})
输出:
0.1,1.1.1,1.2,1.2.1,1.11,2,2.0,2.0

输入:
Solution.solution({"1.1.2 "," 1.0 "," 1.3.3 "," 1.0.12 "," 1.0.2"})
输出:
1.0,1.0.2,1.0.12,1.1.2,1.3.3

问题陈述相当直接。给定一个版本列表,按照优先顺序升序排序:主要>次要>修订。这很简单,让我们来看看边缘案例。

  • 次要版本号和修订号是可选的
  • 如果两个或两个以上的版本是相同的,但是其中一个版本包含的数字比其他版本多,那么这些版本必须根据它们包含的数字的多少按升序排序。

在解决这些问题之前,让我们先看看解决方案代码

电梯维护解决方案

在运行代码之前,让我们首先讨论一个常见的编码结构。

比较器2

简单地说,比较器总是采用以下形式:

比较器框架

现在,如果你观察,这里我们没有使用任何 if 语句来进行比较,而是简单地减去两个散列码。

这种减法实际上是实现这一点的一种简单而常见的惯例。例如,考虑两个 int,a 和 b,那么

a — b < 0, if a is smaller
a — b == 0, if a and b is same
a — b > 0, if a is larger

这正是我们想要的输出。

这对于排序非常有用,因为 Java 标准库提供了排序函数,可以根据比较器对任何对象集合进行排序。在我们的代码中,我们将不止一次而是两次使用这个概念。

代码缩减

所以没有比较器。让我们精简代码,并涵盖上述边缘情况

  • 首先,我们根据自定义的比较器对数组进行排序。
  • 在我们的比较器中,我们首先将版本划分为主要、次要和修订类型。
  • 同样,我们编写了另一个比较器(这次没有继承的华丽,但基本上它做同样的事情),用于比较特定的版本类型。
  • 我们按照主要版本>次要版本>修订版本的优先顺序来比较版本类型。如果在任何阶段,两者不相等,我们简单地返回内部比较器的输出。如果是,我们就进入下一种类型。如果最后没有区别(边缘情况 2),我们基于版本子类型计数进行排序。
  • 在我们的内部比较器中,我们首先检查特定版本子部分是否在任一版本中存在(边缘情况 1)。如果不是,我们默认它为 0,否则我们选择它,然后像在任何整数比较器中一样进行比较。

一个重要的外卖

在上面的部分中,我给出了代码的概要,以帮助初学者理解核心概念,但是对于那些已经花了相当长时间在 IDE 前涉猎的人来说,我需要这样做吗?

代码正在做的事情非常清楚,不需要任何文档。当然,它甚至可以更好,我们可以添加枚举来使版本类型更加清晰,并使用正确命名的私有方法来使边缘情况的处理更加直观。但是我们在这里应该理解的是,遵循干净的代码原则,边缘情况的处理不再是中断思想流动的丑陋的异常值,而是它的自然延伸。

现在我意识到我没有把它打扫得尽可能干净,这让我感到非常内疚。所以让我们忏悔吧。

清洁电梯维护解决方案

我不会在这里给出一个纲要,因为坦率地说,这是不必要的。此外,我鼓励你只看解决方法,看看你是否能理解流程,而不需要看版本和版本类型的实现,这就是为什么我把它们放在底部。如果你只需要阅读 1/4 的代码就能理解代码在做什么,那么我的工作就完成了!

在我的下一篇文章中,我将进入第二关的第二个挑战:准备毁灭。当我找到时,我会在这里链接它。要获得相同的通知,请考虑在 medium 上关注我,订阅一封相同的电子邮件,直接发送到您的收件箱!

来源、脚注和进一步阅读链接

我奶奶的室友是个机器人

原文:https://towardsdatascience.com/my-gradmas-flatmate-is-a-robot-f083ecb933a?source=collection_archive---------58-----------------------

人工智能如何帮助我们的老年人在自己的家中

张家瑜Unsplash 上拍照

众所周知,如今人们的寿命更长了,大多数政府都面临着提供更多机构护理的压力。但这种护理非常昂贵,而且在大多数情况下,需求远远高于供给,从而使弱势人群得不到充分的监督。许多人担心,因为他们的父母已经到了不能独立生活的阶段,但另一方面,没有可供他们负担得起的机构护理的空间。此外,我们都知道,人们更愿意继续生活在自己的社区,而不是被连根拔起,安置在一个陌生的环境中。他们需要亲人的安慰,需要邻居的闲聊,需要友好面孔的偶尔造访。有各种纵向研究表明,拥有令人满意的人际关系的人更快乐,健康问题更少,寿命更长。

但是一个人的家也可能包含死亡陷阱。老年人面临的一个重大风险是意外跌倒。研究估计,大约三分之一生活在社区中的老年人每年至少经历一次跌倒(因为意识丧失、癫痫发作、中风或其他情况),其中 30%的 65 岁或以上的人每年经历一次跌倒。在有人注意到事故或恢复意识之前,无论一个人躺在哪里,跌倒之前或之后失去意识都会产生问题。如果相关人员受伤并且无法移动,这种情况可能会导致进一步的并发症。因此,呼救或试图站起来可能是至关重要的。

照片由扬·安东宁·科拉尔Unsplash 上拍摄

养老院中的环境辅助生活(AAL)服务可以解决这个问题。这些技术通过帮助清洁、提供支持和监控来帮助老年人独立生活。基于传感器、麦克风和视觉系统,已经设计和开发了几种设备,结果非常有希望。这些产品包括温度控制器、智能手表、机器人和许多其他产品。它们在安全的环境中为老年人或弱势群体提供更好的生活方式。

这些技术的奇妙之处在于,它们使用非侵入性的廉价传感器来监控人的运动和行为。由人工智能系统监控的标准摄像头能够跟踪一个人的整个家。他们可以执行骨骼检测(估计人的骨骼),并通过它来推断这个人在做什么。因此,如果系统在夜间检测到有人躺在地板上,它将首先尝试通过语音与他进行互动。如果这个人不回答,它将向他的*亲或有关当局发出警报。整个过程由人工智能自动执行,没有人类参与,因此保护了个人的隐私。

蒂亚戈·穆拉罗在 Unsplash 上的照片

但是这样一个系统是如何运作的呢?首先,用户需要安装一些必要的传感器,如摄像头、麦克风和扬声器。一个人工智能系统连接到它们,管理不同的设备以及与用户的所有交互。让我们想象一下一个叫露西的老人的情况,她独立生活。

早上,人工智能会在所需的时间唤醒她,方法是拉起窗帘,打开有 wifi 功能的水壶。咖啡的香味轻轻地涌入她的鼻孔,她最喜欢的音乐开始在最*的扬声器上播放。当露西起床时,人工智能祝她早上好,并提醒她吃药。该系统还向她所爱的人发送短信,通知他们露西已经醒来,身体健康。随着时间的推移,人工智能为露西提供各种服务,如阅读最新新闻,提醒她可能有约会,将她与她的在线朋友联系起来,并建议一个可爱的食谱。有时露西会迷失方向,因为她有轻微的老年痴呆症症状,并试图在没有任何帮助的情况下走出家门。系统注意到这种尝试,试图通过呼叫她来吸引她的注意力,同时通知她所爱的人。幸运的是,露西冷静下来,回到了她的日常生活中。当她坐在沙发上看她最喜欢的电视节目时,系统会指示机器人清洁工开始打扫房间。然后,它注意到露西睡着了,并调整恒温器来保持这个地方温暖。当她睡了一个长时间的午觉醒来后,她需要使用浴室,但她绊了一下,摔倒在地板上。系统注意到这一点,并与她交谈。听到没有回应,它立即通知她的亲人,并要求救护车。幸运的是,露西没有受什么重伤,很快就回家了。

托尼·里德在 Unsplash 上的照片

正如我们刚刚看到的,AAL 系统有各种好处。它可以帮助弱势群体完成最*凡的任务和更严肃的事情。在某些情况下,它可以保护它们免受房子周围各种陷阱的伤害,从而成为救生员。入门的费用不高,而且大多数人都可以负担得起。此外,我们还必须考虑将这些人制度化所节省的成本,以及将他们从社区中剥离的情感代价。总的来说,AAL 显然是最实用的方法。通过在他们的私人家中安装这项技术,我们可以保证我们年迈的亲属有一个光明的未来,我们也可以保证我们的亲人在安全的数字手中度过一些宁静的夜晚。

如果你喜欢这篇文章,并想与我联系,请这样做🐦 碎碎念 ,🔗LinkedIn,📷insta gram或者😊 脸书

https://medium.com/dataseries/from-paris-to-london-in-a-handful-of-minutes-7657d978152

阿列克谢·丁力教授 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他已经出版了几本同行评审的出版物,并成为马耳他的一员。由马耳他政府成立的人工智能特别工作组,旨在使马耳他成为世界上人工智能水*最高的国家之一。

我从化学工程师到数据工程师的旅程

原文:https://towardsdatascience.com/my-journey-from-chemical-engineer-to-data-engineer-908cca5c1989?source=collection_archive---------22-----------------------

我在两个看似无关的领域之间的转换

伊恩·施耐德在 Unsplash 上拍摄的照片

数据工程的独特领域

数据工程的独特之处在于它没有正式的教育要求。你可以有物理学博士学位,或者根本没有高等教育。技能和经验决定了你能否成为一名成功的数据工程师。我本人有化学工程学位。在担任第一个数据工程职位之前,我没有接触过传统的数据工程。然而,通过自学(加上一点运气),我成为了一名数据工程师,并找到了一份我非常喜欢的职业。

我采取的步骤

正如我上面提到的,每个人的数据工程之旅都是独一无二的。进入这个领域并没有一套规定的步骤。然而,我所采取的步骤足够通用,任何有抱负的数据工程师都可以采取类似的步骤,并根据自己的喜好修改它们。

我拥抱世俗 数据无处不在。公司越来越依赖数据来推动增长和/或利润。作为制造部门的化学工程师,我参与了与流程改进相关的项目。幸运的是,我有大量的数据要处理:传感器数据、财务数据、生产力数据等等。虽然我们通常将数据检索和存储解决方案外包给我们的 IT 部门,但作为一名有抱负的数据工程师,我请求成为工程部门和 IT 部门之间的联络人,以便我可以参与数据处理。最初分配的任务很普通:我为表添加二级索引,为报告查询表,等等。然而,这是我第一次涉足数据工程领域。我学习了 SQL 的基础知识,一旦我证明了自己,我就被分配了越来越复杂的任务。通过充当两个部门之间的粘合剂,我拓宽了我的数据工程经验。

我求云认证 。认证是一个有争议的话题。有些人坚信它们的必要性,而有些人则完全不相信它们。我倾向于前者,但我不认为认证是一项要求。证书是对数月辛勤工作的奖励。作为一名化学工程师,我选择学习云认证,特别是 AWS。我认为选择哪种云环境并不重要,因为它们都提供类似的服务。对我来说,我想学习各种公司和行业使用的数据工具。不幸的是,我的雇主没有利用任何种类的云解决方案,所以我需要一个包括云产品的学习路径:因此,认证。事实证明,为每一项认证而学习会产生有价值的知识,而且作为一个额外的好处,它给了我一个借口来建立多个我可以在面试时谈论的副业项目。

我看的书和文章 。我认为学习需要大量阅读是不足为奇的。我阅读书籍、文章、研究论文等。任何与数据工程领域的现状相关的东西都在我的阅读清单上。我保留了一切吗?绝对不行。我觉得一切都有趣吗?没有。然而,通过广泛的阅读,它让我了解了这个领域当前发生的事情。我让自己熟悉了数据工程术语,并记下了每个我不知道的术语。不久,我能够与数据工程师和数据专业人员进行智能对话。

我练过编码……很多 。如果你想在数据工程领域开始职业生涯,这是一项必要的任务。数据工程师实际上只是专门研究数据的软件工程师。因此,每个面试循环都需要某种算法问题的解决。数据工程师的面试循环往往包括一个简单/中等的算法问题和一个中等/困难的 SQL 问题。因此,我花了大量时间复习数据结构、算法和 SQL 查询。在去面试一个数据工程师的职位之前,我每天都在练习。练习编码问题的额外好处是它直接有利于学习编程。我练习得越多,使用文档进行简单操作的次数就越少。

我给大大小小的观众做演讲 这可能不是每个人都需要的,但以清晰、简洁的方式交流技术概念对我来说一直是个挑战。我很难将技术概念传达给非技术受众。但是,作为一名数据工程师,您可能会处理属于整个公司各个部门的数据。我认识到能够将业务需求转化为技术需求的重要性。为了实践这个薄弱领域,我经常主动向任何愿意倾听的部门展示项目发现。我抓住一切机会练习交流复杂的想法。随着时间的推移,我改进了我的沟通方式,我找到了一种适合我的沟通方式。

我找到了导师 。作为一名有抱负的数据工程师,导师对我的成长极其重要。互联网上有很多信息。我发现很难区分什么是最新的,什么是过时的。一位导师帮助我将精力集中在对数据工程师角色至关重要的主题上。我在阅读各种资料时遇到的任何歧义都通过与我的导师的简短交谈而立即消除了。我不认为导师是成为数据工程师的必要条件;然而,它对我和我的旅程来说非常有价值。

结束语

数据工程是一个如此伟大的领域,因为进入的障碍不是你的学历;你可以通过努力工作和对该领域的奉献获得经验和技能。我可以证明,仅仅因为你现在不知道如何处理数据,并不意味着你不会在数据工程领域取得成功。努力工作,致力于学习基础知识,如果运气好的话,你也会在数据工程领域找到一席之地。

Kaggle BIPOC 赠款计划-我的经验

原文:https://towardsdatascience.com/my-journey-of-getting-started-with-kaggle-competitions-fdd4a059f329?source=collection_archive---------17-----------------------

费德里科·朗塞洛蒂在 Unsplash 上的照片

一个好的导师和 Kaggle 如何帮助我利用我的数据科学技能

今年, Kaggle 启动了一个名为 BIPOC(黑人、土著、有色人种)资助计划的新项目。它旨在为代表性不足的数据科学家提供支持,以促进他们的职业发展和抱负。我很感激自己是参与这个精彩项目的少数人之一。所有参与该项目的学生都被分配了一名导师。在成为这个项目的一部分之前,我已经做了一些基本的项目。我试着自己学习,但我参加这个项目的原因之一是获得一个合适的导师。我的导师,Usha Rengaraju,帮助我开始了 Kaggle 竞赛。

照片由克莱门斯·范·雷在 Unsplash 上拍摄

我的旅程

我和我的导师合作,在 3 个月的时间里参加了 5 场比赛。然而,一开始这一切都让人不知所措(数据量和方法),那么,我是如何开始的呢?我的导师提出了以下建议

  • 浏览数据集中的每个文件,阅读数据描述,并记下我观察到的一切。
  • 浏览前几年的成功解决方案——帮助我为我可能使用的各种技术打下基础
  • 浏览公共笔记本——有助于更好地理解数据的结构
  • 浏览讨论线索——让我进一步了解哪些模型可能过度拟合,或者是否有任何数据泄漏或我可以使用的额外数据集

这有助于我学习新的方法和技巧,然后用在我自己的笔记本上。我希望这些建议能对任何想开始 Kaggle 比赛的人有所帮助。我们参加了以下比赛

三月机器学习狂潮 2021- NCAAM 三月机器学习狂潮 2021- NCAAW :- 在这场比赛中,目的是预测一支队伍在 NCAA 2021 年男女比赛中战胜另一支队伍的概率。虽然我们参赛晚了一点,但我们还是在男子比赛中获得了一枚铜牌。通过这次比赛,我学到了一些新的东西,如单变量样条模型和 如何进行 Kaggle 比赛 ,因为这是我的第一次比赛。关于我的方法的更多细节可以在本次比赛的 讨论部分 中找到。这是我为这两个比赛写的笔记本。:-

https://www.kaggle.com/muskan2006/ncaam-feature-engineering-and-xgboost https://www.kaggle.com/muskan2006/ncaaw-feature-engineering-and-xgboost

室内定位导航:-在这个比赛中,需要根据实时传感器数据预测智能手机的室内位置。该数据由室内定位技术公司 XYZ10 与微软研究院合作提供。不幸的是,由于新冠肺炎,我生病了。所以我们只能工作四天,但我确实学到了一些新东西,比如后处理的重要性以及用于后处理的各种技术(网格捕捉、成本最小化等)。).此外,可视化数据在这场比赛中是一个挑战,但有很多很棒的公共笔记本在这方面帮助了我。关于我的方法的更多细节可以在本次竞赛的 讨论部分 中找到。

https://www.kaggle.com/c/indoor-location-navigation

表格游乐场系列-2021 年 5 月 :-这是一个为任何希望开始 Kaggle 比赛的人准备的比赛系列。它旨在提供一个任何人都可以接*的表格数据集。通过这次比赛,我了解了去噪自动编码器(DAE)、自动机器学习模型(AutoML)、Google Research 的 TabNet 库。关于我的方法的更多细节可以在本次比赛的 讨论部分 中找到。

https://www.kaggle.com/c/tabular-playground-series-may-2021

植物病理学 2021-fgvc 8:-T竞赛的主要目标是开发基于机器学习的模型,将测试数据集中给定的叶片图像准确分类到特定的疾病类别,并从单个叶片图像上的多个疾病症状中识别出单个疾病。这是我第一次参加与图像检测相关的 Kaggle 比赛。我以前从事过手写数字识别,但这次比赛涉及彩色图像,并且关于各种颜色(RGB)分布的知识是 EDA 的重要部分。使用的模型可以从 CNN 到 DenseNet、EfficientNet 等。关于我的方法的更多细节可以在本次比赛的 讨论部分 中找到。

我还做过 SESHAT 的社会复杂性数据集 。在这里,我处理了非结构化数据,并致力于分析多年来社会复杂性演变的各种趋势,以及可能在社会复杂性演变中发挥重要作用的各种因素。这是我写的笔记本

https://www.kaggle.com/muskan2006/evolution-of-social-complexity-a-data-analysis

我最终成为了 Kaggle 笔记本电脑专家!除了赠款,Kaggle 还提供了一些 Coursera 专业和 GCP 学分,以帮助学员开始使用谷歌云。他们还发出了令人惊叹的好东西,并向每个人传达了美好的信息,耶!

这是一次很棒的经历,鉴于这是第一批 BIPOC 受资助者,整个 Kaggle 团队都付出了很大的努力,让这次经历变得有价值和有趣。作为项目的总结,受资助者应该在其他学员、导师和 Kaggle 团队成员(包括 Kaggle 首席执行官 Anthony Goldbloom)在场的情况下进行最终展示。

总结思路

一开始,开始做任何事情似乎都令人生畏,尤其是在 Kaggle 比赛的情况下,因为数据集非常大。弄清楚数据本身可能会变得很困难,但是你不需要自己做所有的事情。慢慢来,正确地浏览数据描述。记下您对数据的所有理解,每个文件与另一个文件的关系,每个列的描述,或者提到的关于数据集的任何独特的东西,或者您能够找到的东西。如果你试图理解什么有困难,浏览讨论区和公共笔记本。很多时候,讨论线程包含有助于理解数据的公共笔记本列表。如果您无法理解公共笔记本中的内容,请尝试运行代码并探索每一步的数据。它不仅能帮助你理解数据,还能帮助你开始写自己的笔记本。此外,这些笔记本将让您了解可以用来形成基线的各种模型。您可以使用这些模型,并使用各种技术来提高分数,如集合最佳分数或后处理或调整模型本身的参数。作为初学者,重点应该放在学习上,所以,记录下你从每次比赛中学到的新东西,从长远来看会对你有帮助(我也在上面的讨论帖中总结了我在每次比赛中学到的一切)。从别人的旅程中获得灵感,开创一条属于自己的旅程:)

我希望我的文章能启发和帮助任何想开始使用 Kaggle 的人。如果您有任何进一步的疑问或需要帮助,请随时通过 LinkedIn 联系我!

[1] Kaggle-室内定位和导航。(https://www.kaggle.com/c/indoor-location-navigation)

2 【卡格-表格游乐场系列(【https://www.kaggle.com/c/tabular-playground-series-may-2021】T2)

[3] Kaggle: 植物病理学 2021—fgvc 8(https://borda.github.io/kaggle_plant-pathology/)

我的 UCL 计算机科学之旅——最艰难的计算机科学学位之一

原文:https://towardsdatascience.com/my-journey-through-ucl-computer-science-one-of-the-toughest-cs-degrees-977a1d1e0bea?source=collection_archive---------36-----------------------

从我在伦敦大学学院 3 年的计算机科学学习中

内森·杜姆劳在 Unsplash 上的照片

如果你不熟悉伦敦大学学院,它是世界上排名第十的大学(根据 QS 排名)。我在那里的三年旅程相当坎坷,但我很高兴去年夏天以一级荣誉毕业。

在这个故事中,我将为大学生提供全面的建议和细节,告诉他们如何避免犯和我一样的错误。这将为你节省很多时间,我认为这些建议甚至可以在大学之外使用。

也许不是每个人都同意,但是我确信如果你问人们他们在 UCL 大学计算机科学学士学位的时间,他们会同意这有点困难,特别是如果他们试图获得一级荣誉的话。

我将谈论这三年中的每一年,不是因为我想提出一个无聊的时间表,而是我认为每一年都有一些不同的挑战,我想分别解决。

大一的时候

尽管这所大学是从零开始的,但是学习材料的速度非常快。我记得在我工作的前几周,有人要求我用 Dijkstra 算法、Prim 算法、动态编程算法和其他算法编写 python 代码来解决图形问题。不要误会我的意思,我知道这些是计算机科学课程的标准,但通常在几个月后,当你开始掌握计算机科学时。

所以我给即将获得计算机科学学士学位的人的第一个建议是:

在开始上大学之前,尽可能做好准备

这包括学习编程语言的基础知识(如 Python、HTML 等),学习计算机科学的基础知识,并复习数学。这对你第一年的学习大有帮助。此外,在开始之前,试着在网上查找第一年的内容。

我的第二个建议是:

阅读有效的时间管理策略

我不打算详细讨论这个问题,因为网上有很多这方面的资源。从我的经验来看,大多数大学生在第一年遭受痛苦的原因是他们的时间管理太糟糕了。例如,虽然我的第三年课程比第一年难多了,但我能够以更好的方式处理它,因为我更好地管理了我的时间。

最终提示:

总是研究你的任务,一旦收到任务就制定一个完成任务的计划

生活有时会妨碍你,有时推迟完成任务也没关系。然而,你必须有一个完成它们的计划。我之前已经推迟了几个我认为需要几个小时才能完成的任务,结果它们只花了几天,因为我没有意识到它们的复杂性。一旦你收到作业,花 30 分钟研究一下,你就可以避免这种情况。

倒数第二年

达米安·扎莱斯基Unsplash 上拍摄

我一直认为第二年会轻松一点,因为我会从第一年学到很多东西。就大学模块而言,这稍微容易一点,但是,因为你几乎必须在毕业前获得实习机会,所以第二年相当困难。

当然,我预料到第二年会比第一年更困难,我只是没想到获得实习机会有多难。

对此,我的第一条建议是:

从你的第一年开始准备,参加招聘会(这真的很重要),开始写你的简历,和你大学的学长交谈。

如果你对我的实习经历感兴趣,我将很快发布一个全面的指南。

最后一年

预计这将是你最艰难的一年。Covid 无疑让今年变得比预期的更加艰难。但是无论如何,成功毕业的主要挑战之一是做好你的论文。

大三前的暑假,我开始研究各种论文题目。我认为这是我做的最好的一步。我不仅选择了一个独特的论文主题,而且我学到了很多关于机器学习的知识(因为它是那个主题的一部分),这帮助我通过了几个最后一年的模块。

你的论文可以非常乏味,也可以非常有趣。我和我的朋友们见过这两个极端。对我来说,这是相当愉快的,我建议你看看这里:

此外,最后一年的主要挑战之一是找到一份研究生工作。如果你在倒数第二年后有一个暑期实习,这可能对你来说不是问题。然而,如果你没有,我强烈建议你从九月开始申请研究生工作。

最后的想法

我想我的最后一条建议,也可能是最重要的一条是冷静下来!老实说,我过去常常因为到处丢了几个分数而感到压力很大,这不值得。我最终获得了一等荣誉,我本可以享受更多的旅程。你的大学时光可能会是你一生中最美好的时光之一,我相信很多读者都会同意这一点。

我将 MariaDB 连接到 MySQL Workbench 的旅程

原文:https://towardsdatascience.com/my-journey-to-connect-mariadb-to-mysql-workbench-2d7e599a8a26?source=collection_archive---------8-----------------------

数据库ˌ资料库

我的老板向我要一个保存在 MariaDB 中的模式的 ER 图。

希尔德·德梅斯特在 Unsplash 上的照片

我碰巧必须从 SQL 模式中提取实体关系图。我通常使用 XAMPP 来处理 SQL,所以我告诉自己尝试使用 PhpMyAdmin 提供的设计工具。事实上,结果并不好。我的数据库有超过 20 个表格,设计者显示它们一个接一个。此外,PhpMyAdmin 设计器是一个非常基础的工具,它不允许您自动对齐表格以提高可读性。

然而,由于我的老板要求我制作这个受祝福的 er 图,并且不希望手动地在图中一个接一个地移动表格,我考虑使用 MySQL Workbench 。我记得在很久以前的回忆中,MySQL Workbench 为将 SQL 模式自动转换成 ER 图提供了一个非常强大的工具。这个工具叫做逆向工程

问题就出现了。让 Maria db(XAMPP 新版本提供的数据库)与 MySQL Workbench 对话不是一个非常简单的操作。但我想最终成功。

我想告诉你我是如何成功的。

首先,我已经在我的电脑(Mac OS)上预装了 XAMPP 的最新版本(在我写这篇文章的时候是 7.3.33),所以我不想像 StackOverflow 上的一些帖子所说的那样,降级到以前安装了 MySQL DB 的版本。

第一次尝试😱

我下载了最新版本的 MySQL Workbench (写这篇文章的时候是 8.0.27)并安装了它。

我的第一次尝试是让 MariaDB 直接与 MySQL Workbench 对话。我从 XAMPP 的控制面板启动了 MariaDB:

作者图片

当服务器处于活动状态时,其名称旁边的指示灯会变成绿色。然后我启动 MySQL Workbench 并点击+号来创建一个新的连接:

作者图片

我添加了连接参数,但是当我试图按下 Connect 按钮时,不幸的是连接失败了,因为这需要配置 SSL。

第二次尝试😢

所以我搜索了一下,找到了如何在 Maria DB 中配置 SSL。我发现本文中描述了一个相当复杂的过程。但是说实话,我有点害怕。所以我放弃了。

然而,在浏览 MySQL Workbench 的连接配置选项卡时,我发现存在一个向导(在 SSL 选项卡下),它允许您自动生成密钥和证书。

作者图片

通过遵循向导过程,可以生成各种证书。我已经在“使用默认参数”项中打上了勾号。

该过程完成后,您可以通过单击向导按钮正下方的“文件”按钮来访问文件。我将文件复制到我的本地文件夹,然后转移到 Maria DB 服务器配置。

从 XAMPP 菜单中,我选择了 MySQL 服务器,然后单击配置,然后单击打开配置文件,在底部,我粘贴了与证书一起生成的my.conf.sample文件中的文本。有问题的文本是这样的:

[client]
ssl-ca=<directory>/ca-cert.pem
ssl-cert=<directory>/client-cert.pem
ssl-key=<directory>/client-key.pem[mysqld]
ssl-ca=<directory>/ca-cert.pem
ssl-cert=<directory>/server-cert.pem
ssl-key=<directory>/server-key.pem

我用我的目录的路径替换了<directory>。我重启了 SQL server,它安静地启动了。

然后我回到 MySQL Workbench 并创建了一个新的连接。这一次,我已经在 SSL 选项卡中的适当位置配置了所有必需的 SSL 参数。

这一次我尝试连接 MySQL 工作台给了我一个警告(见侧面)。我还是点击了继续,一切似乎都很好。

看起来的确如此。

我可以看到存储在我的 SQL server 上的所有数据库,但是当我试图访问单个表时,它告诉我无法加载它们:

无法获取表—加载模式内容时出错

唉,连第二次尝试,都不幸悲惨失败…

第三次尝试😌

但是我不灰心。我再次尝试谷歌。这次我发现另一个 StackOverflow 线程奇怪地说 MySQL 需要更新。

没有什么可失去的,并且总是想着我的老板不惜一切代价想要那个 ER 图,我打开一个终端并运行这个命令,希望它不会破坏一切:

sudo /Applications/XAMPP/bin/mysql_upgrade

有东西在动。看起来像是在安装什么东西。好了,完成了。我重启了 SQL 服务器,一切正常。然后,我回到 MySQL 工作台,重新连接到 SQL server,现在,我终于可以看到这些表了!哇!我很开心!

我只要启动逆向工程就行了!
但是不行,系统崩溃了。

不要。它看起来像一个古老的奥德赛。但是我不放弃,我能做到。我不得不做。

我总是在想我必须带给我老板的那个 ER 图。
事实上,我有点泄气了……也许,我对自己说,我可以重用 PhpMyAdmin 设计器。

然后,然而,我想象自己用手移动所有的桌子…不-不。我试着再找一遍。

第四次尝试😄

我不停地在谷歌上搜索,直到我看到这篇 StackOverflow 文章,文章中说逆向工程崩溃问题是最新版本 MySQL Workbench 在 Mac OS 上的一个已知错误。所以如果你安装一个老版本,最晚 8.0.21,问题应该就解决了。

那我试试。卸载最新版本,下载 8.0.21,安装。我尝试逆向工程,一切正常!这些桌子都完美地排列在一起,不需要任何手工操作😎

那都是乡亲们!

声明一下,这里制作的 ER 图我不能放截图,出于隐私考虑。相反,我放了一个简单的 ER 图的截图,它产生了我的逆向工程:

作者图片

摘要

在本文中,我描述了我尝试将 Maria DB 与 MySQL Workbench 连接起来的经历,以利用 MySQL Workbench 提供的逆向工程工具。

这是一个漫长的过程,但我最终设法产生我的 ER 图。但是这个问题仍然存在:

花时间让自动工具工作是否值得,还是进行手动操作更好?

老实说,我几乎总是喜欢花一些时间让自动程序工作。你看呢?如果你愿意,请随意发表评论。

如果你已经走了这么远来阅读,对我来说今天已经很多了。谢谢!你可以在这篇文章中读到更多关于我的信息。

相关文章

https://alod83.medium.com/how-to-import-and-export-a-dataset-in-phpmyadmin-b108288a3ca3 https://alod83.medium.com/how-to-install-xampp-bcb43fb11912

我 14 岁的卡格尔大师之旅

原文:https://towardsdatascience.com/my-journey-to-kaggle-master-at-the-age-of-14-e2c42b19c6f7?source=collection_archive---------1-----------------------

作者的 Kaggle 简介

有些人可能会觉得“数据科学”和“机器学习”这两个术语令人生畏,认为它们需要专业技能才能成功。初看数据科学和机器学习领域,可能会不知所措,盯着无尽的代码行和技术术语,不知道从哪里开始。

卡格尔是许多人开始旅行的地方之一。对于其他人来说,Kaggle 是他们竞争、赢得声誉和深入机器学习领域的地方。

在这篇文章中,我将带你了解我是如何在 14 岁时成为最年轻的 Kaggle 竞赛大师之一的。

关于我自己

我是 Andy Wang,一名高一学生,对数学、人工智能和计算机科学有着浓厚的兴趣。我在 Kaggle 上比赛以学习和提高我的技能,获得了 2 枚银牌和 1 枚金牌。

作者图片

早期经历

几年前,我对数学产生了兴趣,并开始自学比学校里教的更高级的课题。不久之后,我开始研究编程,因为我从小就对计算机科学着迷。我搜索在线课程,找到了几门教授 Python 和基本编码概念的课程。不久,我开始自己编程,用回溯算法做一些小项目,比如数独解算器。

我的数独生成器的代码片段。图片作者。

在这一点上,我有点怀疑以我手中掌握的知识,我该何去何从。直到有一天,我的朋友向我介绍了机器学习和数据科学领域,我对它的力量感到非常惊讶。然后我找到了 Kaggle,这是一个网站,它扩展了我对当前计算和人工智能技术的可能性的了解。

我是如何进步和学习的

我的编程知识和机器学习概念很大程度上来源于互联网。当你有疑问时,互联网是你最好的老师。没有学校教授数据科学或神经网络,如果我要在 Kaggle 上取得成功,我只能靠自己。

数据科学和机器学习对许多人来说是一项艰巨的任务。面对如此多的资源和科目,人们不知道从哪里开始,也不知道如何学习。因为有如此多的领域与术语“数据科学”和“机器学习”相关联,精通每一个类别几乎是不可能的。ML 和 DS 的力量令人着迷。对于像我这样的初学者来说,你需要找到你感兴趣的东西,并充分发掘它所能实现的潜力。

机器学习的不同领域。作者在 LucidSpark 上创建的图像。

学习 ML 和 DS 对许多人来说是不同的,基于他们先前的知识,这里是我选择的道路,我在其中找到了成功。

  1. 我知道数学是未来一切的基础。线性代数微积分是机器学习中使用的两个最重要的数学概念。几乎所有的机器学习算法都以这样或那样的方式与这两个领域相关。数据以向量和矩阵的形式表示和处理。因此,需要了解矩阵的基本运算。机器学习中微积分最常见的用法之一是 梯度下降 。这是一种算法,旨在通过使用函数的梯度迭代地逐步达到全局最小值来最小化目标函数。
  2. 统计也不能被遗漏。顾名思义,数据科学就是关于数据的。虽然计算机可以预测数据的某些趋势,但人类是唯一可以分析它们,计算某些属性,并最终得出数据结论的人。数据的预处理和特征工程严重依赖于统计学。我零零碎碎的学了统计学,刮了网上的文章,找了合适的网上课程。
  3. 了解了基础知识后,我开始着手编写代码。有了面向对象编程 (OOP)和 Python 的基础知识,我找到了在线课程,这些课程教会了我所有机器学习中常用的库。与简单地遵循代码和复制粘贴相反,我确保我理解了所写内容背后的数学原理。如果你不了解事物的内部运作,就不可能充分利用它。我从简单的算法开始,如线性回归,直到更复杂的算法,如梯度推进神经网络。

学习点点滴滴,一步一个脚印,你从一开始获得的知识可以在未来轻松地积累成复杂的东西。

加入 Kaggle

在这一点上,我想利用我在 Kaggle 竞赛方面的知识。我参加了一个利用回归技术预测房价的初级竞赛。我发现我学到的远远不够。我最怀念的是经历最好的学习方式是通过失败和尝试新事物。我熟悉了 Kaggle 的环境,浏览讨论和笔记本,寻找关于这个问题的解释。不久之后,我觉得我已经为我的第一次真正的比赛做好了准备。我和朋友 Andre Ye 一起参加了机关动作大赛

我们的第一场比赛,莫阿。来源

当时我们都是竞赛的新手。论坛上那些看起来很专业的代码和技术讨论让我们目瞪口呆。我决定从头开始,而不是分叉一个入门笔记本。在讨论帖子的帮助下,我能够在短时间内建立一个基线。创新对于在竞争中取得成功至关重要。我翻遍了关于这个问题的论文和文章,然后将它们与论坛上介绍的方法结合起来,将我们的解决方案排在前 4%。后来,随着更多的经验,我们又参加了两项比赛,获得了另一枚银牌和我们的第一枚金牌。结果对我来说是一个真正的惊喜,我无法感谢 Kaggle 社区引导我度过了。以下是我在参加比赛时观察和学到的一些技巧和诀窍。

我的高尔夫比赛总流程

从我参加的比赛来看,有一个我遵循的通用流程,它不仅能组织工作,还能有效地产生有意义的结果。

  1. 仔细阅读数据描述和概述。如果可能的话,温和地探索领域知识。
  2. 在阅读任何论文、讨论或笔记本之前,试着自己建立一个基线。这有助于在你锁定别人所说的之前产生全新的想法。
  3. 制定可行的交叉验证策略,并提交至排行榜。确保你的简历策略也适用于 LB,这一点很重要。
  4. 读,读,学!充分发掘与主题相关的论文,在论坛和笔记本上寻找灵感。
  5. 开始调整基线,无论是模型方面还是特性方面。一次只调整一件事,这样你就知道是什么导致模型改善/表现变差。
  6. 探索尽可能多的新方法,不要停留在那些行不通的事情上。
  7. 合奏!如果其他方法都失败了,组装或堆叠是我发现的最稳定的改进方法。
  8. 只选择简历分数好的提交(并确保自己知道为什么表现好)。

我所学到和利用的

随着我参加越来越多的比赛,我对一些解决方案的复杂性感到惊讶,从特征工程到神经网络的结构。

来自 RANZCR 竞赛的惊人的第一名解决方案

一般来说,机器学习算法可以很好地学习,只从信息数据中学习。在某些情况下,能够利用与预期稍有不同的算法会有所帮助。例如,使用主成分分析(PCA) 来减少数据的维度然后将减少的特征连接回原始特征在不止一种情况下帮助了我。

特征工程带来了特征选择。移除不重要的要素有助于减少数据中的噪音。在行动竞赛机制中,论坛和讨论帖中的方法对我们设计的模型没有帮助。在这种情况下,不要害怕深入研究和阅读论文。由于我正在处理的多标签分类案例并不常见,所以我找不到任何简单的教程。我发现了一篇旨在使用问题转换比较多标签特征选择的论文。

阅读研究论文似乎令人生畏,但是能够快速浏览并从长长的技术术语中抓住关键词是一项至关重要的技能。对我这样的初学者来说,试图理解你遇到的每一篇论文的每一个细节是不可能的。只有当我降落在我需要和将要使用的纸上时,我才试着去理解文中的每一个词和参考文献。

在建模期间,我学到的最大的一课是创造力。不仅仅是在模型结构中,还要跳出框框思考模型如何在不同类型的数据上工作。

  • 调整模型,使其具有非线性拓扑或为表格数据构建类似 ResNet 的结构化网络,不仅在 MoA 比赛中,而且在接下来的 Jane Street Market Prediction 比赛中,我们在 4.2k 个团队中排名第 16 位,取得了一些惊人的成绩。
  • 探索不同类型的自动编码器,如去噪变分稀疏编码器可以给你的数据带来令人惊讶的变化,而不是简单的特征工程和选择所能实现的。
  • 合奏。组合不同模型的结果增加了您的解决方案的多样性,从而使它更加健壮和稳定。无论什么样的建模技巧奏效与否,在比赛中,组装总是我的“最后手段”。
  • 时刻关注新的论文,探索论坛中没有提到的东西。调整一些小事情,比如激活函数(尝试 swish 而不是 ReLU),以及优化器(尝试 AdaBelief 而不是 Adam,等等。)可能会从模型中挤出一些性能。
  • 跳出框框思考!使用 1D CNN 对表格数据进行特征提取。或者使用 DeepInsight ,将表格数据转化为图像,利用 CNN 的优势。

图片来自 Kaggle

最后,在一场比赛中奏效的策略不一定会在另一场比赛中改善你的解决方案。在简街市场预测挑战中,我发现特征工程对结果一点帮助都没有。相反,我发现了建模的魔力。要记住的一般经验法则是:

在这种情况下,不要停留在“以前工作过”或“为他人工作过”的事情上,继续前进,花更多的时间探索能带来进步的新事物。

参加 Kaggle 比赛并获得奖牌不是一件容易的事,但是通过正确的学习方法和工具,这个过程可以变得更容易。

  • 查看讨论帖子和阅读公共笔记本非常有帮助。每天都有新的想法出现,我通过论坛中提到的论文和笔记本中使用的库了解了一些最新的、令人着迷的模型和工具。其中之一是 TabNet ,这是一种通过使用顺序注意将特征选择纳入模型来对表格数据建模的新方法。这个模型让我在 MoA 比赛中获得银牌。
  • 最后,拥有稳定而强劲的渠道是在最终私人排行榜上取得优异表现的最关键因素。为了在公共排行榜上获得额外的 0.0001 而浪费时间过度拟合是没有意义的。始终相信您的本地交叉验证分数,因为训练数据的数量大于公共排行榜。

尽管有很多技巧和诀窍,但我成功的最重要部分是我始终如一的建模渠道和稳定的简历。

对于一个强有力的,稳健的 CV…

设置本地交叉验证方案时。我谨记以下几点:

  1. 折数> 3。对于较小的折叠数,训练分裂不足以代表全部数据。
  2. 确保数据没有泄露。特别是在时间序列预测等情况下,常规交叉验证会导致未来数据泄露,应使用某种形式的时间序列分割。
  3. 当目标不*衡时使用分层折叠。分层折叠方法试图在折叠中*均分割目标。
  4. 确保你知道某事为什么会改善。 这非常重要,因为结果可能会受到随机种子和其他未知因素的影响。这可能会导致看不见的数据中的重大不确定性(私人排行榜)。

仅仅按下复制粘贴对学习或赢得比赛没有任何帮助。我在 Kaggle 最重要的座右铭是永远不要抄袭别人的作品,我可以从他们的想法中获得灵感,甚至使用他们的建模方法,但我从不提交别人的作品作为我的解决方案。当接触新的事物时,我养成了一种习惯,去查阅一切我不懂的东西,直到我能自信地向别人解释这个主题。

最后…

这篇文章可能不会帮助你赢得竞争,但是我向你保证,他们会引导你在 ML 和 DS 的旅程中少失败。

我的第一份数据科学工作之旅

原文:https://towardsdatascience.com/my-journey-to-landing-my-first-data-science-job-8a64907f7343?source=collection_archive---------8-----------------------

野外的数据科学和机器学习

以及我一路走来学到的 10 个教训

史蒂夫·哈维Unsplash 上拍照

介绍

众所周知,数据科学工作的竞争非常激烈。你可能正在填写你的第一份申请,也可能已经有 100 份申请了。不管怎样,我想和你分享我的故事,希望它能激励你继续前进。我热爱我作为首席数据科学家的工作,但这并不容易。我面临持续的拒绝和失望;有一段时间,我准备接受一份我讨厌的职业。我没有放弃,你也不应该放弃。这是我的故事。

我一直是一个好奇的人,这让我的父母和周围的人很烦恼。我喜欢理解“为什么?”发现我参与哲学辩论或谈论想法并不罕见,这是许多数据科学家的共同特征(我相信)。无意冒犯,但我认为这条职业道路选择了我。当我还是个孩子的时候,并没有真正意义上的“数据科学家”这种工作。我知道有些人在逻辑、数学和科学方面做了很酷的事情……我想成为他们中的一员,不管是什么。

教育

追随我的梦想,我攻读了过程工程学位。建造大型炼油厂,设计可再生能源发电站,这很酷吧?我会产生巨大的影响,至少我是这么想的。我很快发现这根本不适合我。我坚持完成了学业,并以一个*庸的工程学士学位毕业。我把这归咎于我缺乏兴趣、派对生活方式和不成熟。

即使在我糟糕的大学经历之后,我仍然有这种渴望。我知道我想以某种方式产生影响,我仍然相信我的能力。我申请了运筹学、应用统计学和风险的硕士课程。这太棒了!班级规模很小,我学习了(一点)编码,我第一次感觉到我在学习真正有影响力的东西。我们讨论了图形网络、信用卡、时间序列预测、优化算法等等。当时,这种东西看起来像是最先进的分析技术,它会很好地为我的第一份职业工作做准备。我也很幸运地得到了一份关于零售和消费价格指数的实习工作。

早期职业生涯

我的第一份职业是在一家非常大的银行从事风险分析。最初这很棒,我接触到了所有的信贷准备金模型。在最初的几个月里,我会把它们分开,试图理解它们是如何工作的。当时所有的模型都是用 SAS 编写的,并且有一个 excel 前端。出于好奇,我找到了改进模型的方法,但作为一个天真的孩子,我无法向我的高级利益相关者推销我的想法。我很快就变得灰心丧气,只能听天由命地输入数据和遵循流程。我对这一经历不再抱有幻想,进入了轻度抑郁状态。

我知道我必须离开。在接下来的 5 年里,我会在不同的公司和不同的工作间穿梭,试图为自己找到一个位置。这是一段艰难的旅程,我很矛盾。我知道我很幸运,但同时我对工作不满意,完全没有成就感。提供给我的工作类型大同小异,我无法胜任我想要的工作。

投资我自己

最让我难以接受的是,自从我完成硕士学位后,这个世界已经变了。当时的“最先进”现在看来已经过时了。新一批毕业生现在可以构建深度学习模型,闭着眼睛编码,并创建强化学习模型,可以在国际象棋上打败我。好吧,我夸大其词了,但重点是世界已经变了,我的技能已经过时了。我知道在这个时候,如果我想朝着正确的方向前进,我必须投资我的职业生涯。我抽不出时间去完成另一个硕士项目。“我能怎么办?”,我问自己。

我认为 MOOCs 是一个好的开始。我热切地报名参加了尽可能多的活动,并努力完成了所有的活动。从在 sci-kit learn 中构建基本的 ML 模型到发现谷歌云*台的来龙去脉,我学到了一切。这太棒了,它极大地满足了我的好奇心,我终于觉得我要去某个地方了。

我尽可能多地接触书籍,我想尽可能地了解算法、统计、计算、机器学习、深度学习等等。

我真正的书架上有我在旅途中读过的书

我花时间构建机器学习模型,也写了一些关于它们的文章。除了头衔,我开始觉得自己什么都像数据科学家。

这里是我写的一些文章,可能会对你的人生有所帮助……

找到我的第一份工作

在此之后,我开始申请工作。起初,我试探性地认为我没有合适的经历,直到一个朋友说服我要么做大,要么回家。他是对的,我绝对没有什么可失去的。仅仅申请了几份,我就成功获得了谷歌、脸书和 Spotify 等科技和金融公司的面试机会。这很令人兴奋,我觉得自己离成为数据科学家的目标越来越*了。

对我来说,所有的面试都很难。我接受了无数带回家的挑战,被编码能力问题轰炸,有时连续 7 个小时被拷问,有时三个问题同时被拷问。

我做得很好,但发现我在最后一轮面试中一直表现不佳。我总是被比我多一点经验的候选人击败。几个月来,我接连收到拒绝信,有时根本没有回音。在努力工作了大约一年后,我在情感上和精神上都筋疲力尽了。

我最终找到了我的第一份工作,成为一名正式的数据科学家,并被提升为领导一个数据科学家团队。我必须说这超出了我申请时的预期。我想给你留下我在旅途中学到的十件事。

我在旅途中学到的十课

1.你的过去并不能定义你。即使你的背景不够好,你也有能力改变它。

2.追随你的激情。生命太短暂了,不要困在你讨厌的事情上。

3.投资职业发展总是值得的。即使这需要一些钱,和你的雇主谈谈,看看是否有资金来源,或者如果资金太难的话,自学。

4.指导你的学习。我花了很多时间学习多余的东西,如果我能回到过去,我会选择一个专业来指导我的研究。这可能是一件困难的事情,因为你可能不知道你想去哪里。

5.尽快申请工作。许多人发现面试令人生畏,所以他们用学习、MOOCs 或任何他们能告诉自己还没准备好面试的事情来拖延时间。根据我的经验,你可以从面试中学到很多东西。你开始弄清楚外面有什么,雇主在找什么,你在面试中也会变得更好。

6.以拒绝为教训。不要掉入变苦的陷阱。每一次拒绝都有一个教训。从每次面试中寻求反馈,并以此来指导你的学习。如果没有反馈,这本身就是一个教训。

7.庆祝小胜。通过一轮又一轮的面试并不容易。当你庆祝的时候,提醒自己庆祝,这会让你精神振奋。提醒自己你已经走了多远,许多人甚至没有申请到。

8.该休息的时候休息。如果你感到筋疲力尽,放下书本或者暂停一会儿面试。你的大脑工作能力有限,它需要时间休息。如果你发现你的工作越来越马虎,面试变得越来越费力,那可能是时候休息一下了。

9.向机遇敞开大门。我受邀参加研讨会、播客和社交活动。敞开心扉去参加。让自己走出舒适区,你永远不知道那里会出现什么机会。

10.别放弃。在这条路上你会遇到许多障碍,你的工作就是去克服。作为数据科学的从业者,工作中也是如此。一旦你被雇佣了,事情就不会变得容易了。当你开始真正的事情时,把这看作是条件反射。

奖金 ⭐️: 学习永不停止。这个领域不会停滞不前,继续学习和发展你的技能。我将在明年年初开设一门开放式银行和人工智能课程。你需要保持这种内在的知识。

我祝你一路顺风。记住外面有很多工作机会!

https://www.linkedin.com/in/john-adeojo/

我的机器学习模型是完美的

原文:https://towardsdatascience.com/my-machine-learning-model-is-perfect-9a7928e0f604?source=collection_archive---------34-----------------------

但我能闻到。

Unsplash 上@ youxventures@ tade KL@ Mario Gogh的照片

需要重构的代码

奇怪和难以阅读的代码是引发重构(重写)的常见原因。想象一下没有大量文档的非结构化意大利面条式代码——或者相反——文档太多,你再也看不到森林了。这种代码问题被称为“代码味道”。这个术语在 1999 年马丁·福勒的书“重构:改进现有代码的设计”出版后被广泛采用。其本质,重构是应用一系列小的行为保持转换,其累积效果是“降低引入错误的风险”。

有些气味很容易被发现,有些气味比其他气味更微妙、更阴险。虽然这些问题和迹象本身可能并不有害,但它们值得仔细观察。你可能以前见过其中一些:

  • 不必要的复杂性(也就是炫耀)。
  • 带有太多参数的函数,表明“上帝函数”没有划分成辅助函数。
  • 屏幕上的函数长度失控,难以阅读。
  • 过多的注释使得很难区分代码和非代码。
  • 重复代码——这就是“不要重复自己”原则的来源。

看看代码气味的完整列表及其在维基百科上的描述,以及 Anupam Chugh 在他的 TowardsDataScience 帖子中讨论的内容。

突围:谁有最臭的代码?

在写这篇文章的时候,华盛顿州的谷歌搜索用户对代码气味最感兴趣,或者至少排名很高。立即查看谷歌趋势。他们的代码是所有代码中最臭的吗?兴趣可能与一个状态中的编码者的数量相关,并且不可避免地会有有问题的代码被发现。

粘土银行Unsplash 拍摄的照片

机器学习闻起来是什么味道?

几乎所有的机器学习都需要有人编写代码。这意味着已知的问题或气味可能来自代码库——不管是我们写的还是其他人放入黑盒中让我们调用的。机器学习模型是传统的函数,但在数学上遵循不同的范式:一个将样本值 X 与某个目标值 y 相关联的函数。虽然 PyTorch、TensorFlow 和 Scikit-learn 等全面的 ML/DL 库的所有函数都有望得到优化,并且没有代码味道,但一个项目涉及的不仅仅是在单个函数中调用的单个算法。根据我们项目的需求调用函数库功能的工作流是一个“元模型”,有其自身的设计复杂性。

那么,在我们的预测工具中,哪些“ML 气味”可能会提醒我们更深层次的问题呢?

【Matt Hall 博士于 2020 年 10 月在 Twitter 和地质机器学习社区 Software Underground 中提出了以下问题:

🐽ML 气味很可能不是一个东西,但也许应该是。一个# machine learning项目中潜在更深层次问题的表面迹象是什么?——马特·霍尔(@ kwinkunks)2020 年 10 月 7 日

Matt 众包了一些优秀的回答:

  • 像 AutoML 这样的暗箱服务。
  • 违反直觉的模型权重 - >已知影响具有低特征重要性。(里斯·霍普金斯,安克雷奇)
  • 不可复制、不确定的代码 - >不设置随机种子。(里斯·霍普金斯,安克雷奇)
  • 无列车价值测试分割描述/理由。训练数据和盲数据之间的泄漏很容易随着空间相关数据中的随机分裂而引入。(贾斯汀·戈斯,休斯顿)
  • 无评估指标讨论 - >如何选择或设计(Dan Buscombe,Flagstaff)
  • 无事实根据的讨论以及目标标签如何与之相关。(贾斯汀·戈斯,休斯顿)
  • 过高的超参数精度 - >可能意味着过度调整。(克里斯丁宁,珀斯)
  • 未考虑精度-召回权衡 - >,尤其是在二分类任务中。(丹·巴斯科姆,弗拉格斯塔夫)
  • 强烈的阶级不*衡并且没有明确提到如何处理。(丹·巴斯科姆,弗拉格斯塔夫)
  • 一个或两个特征的偏斜特征重要性可能暗示特征泄漏。(约翰·拉米,奥斯汀)
  • 找借口 - >“我们需要更多数据”“标签不好”等。(哈尔格里姆·拉德维森,斯塔万格)
  • 花在清理数据上的时间太少 - >不到准备数据工作的 80–90%。(迈克尔·皮尔茨,奥斯汀)
  • 非常高的精度,例如,对于新任务上的复杂模型为 0.99。(Ari Hartikainen,赫尔辛基 Lukas Mosser,雅典)。在大多数真实世界的场景中,接* 0.7 的精确度是非常好的,任何 0.8 的精确度都表明发生了一些不寻常的事情。

这是一个很长的列表,但还有更多。

最有可能的是,我们有自己的偏见和倾向来产生一些气味,因为我们没有意识到,没有更好的了解,或者没有其他选择。在这种情况下,同行评审提供了第二(或第三、或第四……)双眼睛,这是至关重要的,所有的气味都被清除了。

你怎么想呢?

你的 ML 代码有多完美?你看到了什么样的表面现象可能表明 ML 项目中更深层次的问题?

也许是时候有人正式创造一个新的术语叫做“ML 气味”了…..

感谢马特·霍尔,他的问题激发了我写这篇文章的灵感!

关于

Christian 拥有Marine Science的博士学位,Geoscience的理学硕士学位,有很强的计算机编程背景。他精通我们这个时代最热门的课题之一:Data Science,并开发Machine Learning模型。查看更多...

原载于 2021 年 1 月 16 日https://www . Christian Haller . me

我在数据科学领域的指导经验:经验和教训

原文:https://towardsdatascience.com/my-mentoring-experience-in-data-science-lessons-taught-and-learned-e7df0317f44c?source=collection_archive---------18-----------------------

我对工作内外的人进行正式和非正式指导的经历

乔恩·泰森在 Unsplash 上的照片

什么是师徒制?怎么才能找到导师?像这样的问题经常在论坛、社交媒体和社区中被问到。当一个有经验的人分享见解并无偿指导学员走向成功时,师徒关系应该是一个令人兴奋的局面。有人建议在工作中找一个导师;还有人说,你可以在任何地方找到潜在的导师。

但是从导师的角度来看事情是如何进行的呢?也许有一天,一个人只是决定是时候指导别人了,并开始帮助别人?就我而言,它是逐渐开始的。

很长一段时间,我认为我只是在帮助人们向我伸出援手。但是后来,在一份工作中,我开始正式指导人们。项目结束后,我回头看,意识到我已经指导了很多人。以前我认为师徒关系是一个重要而正式的承诺,但现在我知道这并不总是正确的,师徒关系可以是完全非正式和有趣的。

2020 年,我获得了 ods.ai 颁发的导师奖,现在我认为是时候谈谈导师了。

在这篇博文中,我想分享我的指导经验,我对它的想法,对导师的好处,以及潜在的困难。

什么是指导

指导有许多定义,侧重于不同的方面。维基百科提供了以下一条:

辅导是一个非正式传递知识、社会资本和接受者认为与工作、职业或专业发展相关的心理社会支持的过程;指导需要非正式的沟通,通常是面对面的,持续一段时间,在被认为拥有更多相关知识、智慧或经验的人(导师)和被认为拥有较少相关知识、智慧或经验的人(被保护人)之间进行。

我基本同意,并想强调最重要的几点:

  • 导师在学员感兴趣的领域更有经验。这是不言自明的,但也意味着学员在其他领域可能更有经验。例如,学员正在转行或学习新的兴趣领域;
  • 学员有一个具体的目标(例如,获得一份更好的工作)。如果被辅导者不知道他们想要什么,导师将无法提供帮助;
  • 通常,指导是在两个人之间进行的,而不是在小组中进行。唯一的例外是,导师同时帮助几个学员处理类似的话题,例如,指导新同事。但是尽管如此,这些小组会议应该比更多的个人指导更少;
  • 与其他形式的知识共享相比,指导更个性化,更不正式。例如,教练仅限于商业话题,在教学的情况下,学生通常没有太多的选择自由,教师也不太容易分享个人想法;
  • 指导的开始通常不是正式的。其实给我写信“成为我的导师”的只有几个人,我一般都是拒绝的(我在这篇博文的最后说说我的理由);
  • 导师交流可以面对面进行,但我更喜欢短信或电话。
  • 指导可以偶尔进行,但必须至少进行几次。一次性建议不是完全的指导,尽管它仍然是有益的;

导师本身有多种形式:导师可能会给出模糊的建议或帮助解决技术问题,提供一个新的视角,激励,支持和激励,并以许多其他方式提供帮助。导师风格取决于导师的偏好、学员的目标和背景(例如,是否在工作)。

我的指导经历

我生成的模因

首先,我想分享一下我在开始 DS 职业生涯时的经历:大学毕业后,我作为 ERP 系统实施领域的分析师/顾问工作了大约 4 年。在那段时间里,我在精益六适马获得了绿带。

由于从事咨询工作,我学到了很多东西,特别是与客户交谈,讨论他们的需求并将其形式化,向程序员解释任务,测试结果,组织项目和许多其他技能。

然后就离开了这个职业,经过 8 个月的自学,开始了大三 DS 是银行的工作。在那里工作期间,我已经完成了两门课程,并做了一个自己喜欢的项目。这个热门项目包括收集数据、训练模型、部署模型,以及制作一个与模型交互的 web 界面。还有就是我在 ods.ai 社区里问答。

结果,尽管我是一个大三的 DS,但我成功地将我的职业生涯转向了数据科学,拥有了各种技能和知识,以及一个已完成项目的经验(尽管是在工作之外)。这意味着我已经可以帮助别人了,事实上,我在做 DS 的第一份工作时就已经开始指导了。

非正式指导

我将把正式的(工作中的)和非正式的(工作之外的)指导分开,因为它们非常不同:它们有不同的承诺水*、不同的参与者动机、不同的期望等。详细描述我所有的指导经历太长了,所以我想只描述我正式的指导经历。对于非正式的指导,我将介绍更高层次的信息。

第一次指导经历

我产生的迷因

正如我已经提到的,我在从事我的第一份 DS 工作时就开始了指导。ods.ai 社区的一名成员向我提出了关于转行的问题,我分享了我的经验并给出了建议。

然后我们继续交流,我帮助他解决技术和理论问题,对各种项目提出建议。其中一个是关于制作网站和部署模型的,这和我上面提到的宠物项目很相似。

在帮助寻找这些问题的答案的同时,我自己也学到了很多有用的信息。

我们的交流持续了 6-12 个月。

卡格尔

如你所知,我是 Kaggle 竞赛大师和笔记本电脑大师(我甚至保持了 1 年的排名第一)。

我在 Kaggle 上活跃的时候(目前不太活跃),经常在 Kaggle 论坛上回答问题。许多人写信给我,通过社交媒体、电子邮件和其他媒介提出问题。在某些情况下,我们的交流持续了很长时间。最显著的例子是两个人成为 Kaggle 笔记本电脑大师;这是其中之一:

我分享了我写和推广笔记本的经验,对他们的工作提供了反馈,给出了想法和建议——而且效果很好!

短期和长期指导

我不仅在 Kaggle 上很活跃——我在几个社区回答问题,发表演讲,并参加许多其他活动。结果,很多人向我求助。

他们中的一些人就某个特定的主题提出了问题,或者在解决某个技术问题时需要帮助(例如,询问客户流失预测的方法或者解决某个特定的医疗 CV 任务)。其他人想要关于职业的建议或一般指导。通常,它是通过文本,有时使用语音。

在大多数情况下,一次会议就足够了,所以我不愿意称之为“指导”,但无论如何我可以帮助这些人,这很好。

但在某些情况下,我们的交流持续了很长时间。有时我们经常互相发信息,有时我们可以几个月没有任何联系。

正式辅导

我在一份工作中是正式的导师。指导是我职责的一部分,但当你是一名技术主管时,有时很难将指导与其他工作活动区分开来。因此,以下几点纯粹是关于指导的;其他的将是关于管理团队或其他工作的事情。

该项目是关于使用深度学习模型开发一种产品。这项工作在我加入公司之前很久就开始了,但公司的一些变化让我成为了这个项目 NLP 部分的技术主管。

在我开始领导技术的时候,我的团队只有一个人,但是我很快就雇佣了 3 个人。因此,我必须指导有经验和没有经验的同事。还有一个额外的问题——这正好与新冠肺炎疫情和锁定的开始相吻合,所以一切都很遥远,这带来了不同的挑战,因为我不习惯。

入职

我生成的模因

入职培训是一种特殊类型的指导——它帮助新人成为项目、团队和公司的一部分。

它主要是关于日常的事情——帮助更多地了解队友,描述过程和非正式的规则。

在理想世界中,没有必要教授任何特定于项目的技术内容——它们在文档和内部 wiki 中有描述,但这在现实中很少。最好的情况——有一些有用的文档,但是它们有点过时了。

在我的案例中,我认为现有的文档是不够的,所以我和每个新人打了 2-3 个小时的电话。我从高层次和低层次的细节讲述了这个项目,展示了代码,演示了它是如何工作的,解释了我们的开发实践,等等。然后,我们更新了文档并试图维护它。

初始教学

我的团队中有些人有着不同的经历,他们中的一些人比其他人需要学习的东西更多。

从一开始,我就声明任何问题都是受欢迎的。如果有人在一个纯粹的技术问题上花了一个多小时——寻求帮助比在这上面花太多时间要好。所以我们经常在一周内互相发信息或打电话。

有时我组织现场编码会议,在那里我展示了我将如何解决一个特殊的问题。

顺便说一句,我认为指导最有价值的好处之一是看到导师的思维过程。发送解决方案/文章/课程的链接就可以了;给予暗示也是好的。但是当你展示你的思考过程时,这对学员来说真的很有价值。

培养主人翁精神

由于项目的结构,将功能的不同部分交给不同的人是可能的。它的代码大部分已经写好了,但是还有很多尝试新事物的机会。我设置了一些必要的任务,当然,也鼓励人们尝试他们的想法。有些想法失败了,有些超出了我的预期。

当然,这并不总是容易的。例如,有时人们追求先进的方法而没有尝试更简单的方法,这损害了项目的进展。解决办法是设定具体的最小的事情,应该尝试,然后任何人都可以做任何事情。

一对一

我产生的迷因

我不会说这是我的失败,但事后看来,我本可以做得更好。

我是如何做到的:每个月初,我都会给我团队中的人写信(当然是单独的),询问反馈、问题、担忧以及其他他们想告诉我的事情。然后,我们讨论它们,如果出现问题,我会尽力解决。

我应该怎么做:我认为视频通话(或者至少是音频)会更好——看到或听到另一个人比短信提供更多的信息和线索。此外,我应该从我的角度给出更多的反馈(我给出了反馈,但并不总是这样)。

每周电话

在团队成立和最初的问题得到解决后,我意识到我需要两样东西:

  • 某种定期的非正式会议。敏捷/scrum 会议不算数——它们主要是关于工作的,而且还有太多其他人。但有机会互相交谈是至关重要的,特别是考虑到我们完全处于偏远地区,彼此之间的联系比在办公室里更少。
  • 向整个团队而不是单独向每个人教授同样的东西。

我的解决方案是每周打电话(通常是音频,但有时也有视频),持续 1-2 小时,由两部分组成:

  • 起初,有人(通常是我,但过了一段时间也有人)就某个话题做了一次演讲/研讨会。通常,它是一些实际的东西:可以是分享功能的进展,一些一般性的问题,或者一个特定技术问题的解决方案
  • 关于工作、生活和其他任何事情的非正式谈话

我认为效果非常好。

  • 我们从介绍性的话题开始,逐渐转向更高级的概念;一些问题是:从头开始用 Pytorch 编写训练神经网络的代码,NER 建模,使用通气管、Docker、ONNX
  • 我鼓励我的团队成员在这些每周电话会议上至少做一次演讲。这有助于他们发展或提高公开演讲技巧;
  • 我们能够更好地了解彼此,即使在项目结束后也能保持沟通;

领导团队的一般原则

艾萨克·史密斯在 Unsplash 上拍摄的照片

很难描述我所做的一切,但我想说出主要的想法和原则:

  • 试图在团队中培养良好的环境/文化,旨在互相帮助和提高技能;
  • 正如我前面说过的,我鼓励人们提问,尤其是当他们被卡住的时候。我试图帮助解决理论和技术问题;
  • 不仅提供单独完成任务的机会,还提供结对完成任务的机会;
  • 我教授了编写好代码的实践:设置预提交挂钩、使用 ci/cd 进行风格检查、代码审查和其他事情;
  • 帮助提高软技能,给出前进的一般建议;
  • 推动改进我们的技术解决方案——改进小事情,尽可能自动化,使用更好的现代方法;
  • 尝试给予很多积极的反馈,因为以前我经历过很多我完成的事情没有得到表扬/认可的情况;
  • 还有一点——我很幸运,其中一位同事也想指导我,他从我这里接过了一部分责任,并帮助了经验较少的队友;

导师的观点

现在我已经详细描述了指导,让我们来谈谈指导的更高层次。

指导对导师的益处

我产生的迷因

既然我已经描述了我的指导经历,你可能会问——为什么导师还要这么做?我的时间和努力换来的是什么?嗯,有些指导纯粹是像志愿者一样完成的,但也有很多好处,导师可以得到。这是合理的——因为导师在他们的学员身上花费了大量的时间和精力。有段时间,我每周花大约 5 个小时进行辅导。我将从指导的更理想化的理由开始,逐渐转向更实际的理由。

  • 指导是回报社区的方式之一。我在 ods.ai、kaggle 论坛和其他地方得到了很多帮助,我想回报这些帮助
  • 我在以前的工作中没有得到足够的指导,所以当我在工作中有这样的机会时,我想把事情做得“正确”
  • 通常,这是毫不费力的,尤其是在短期或不经常辅导的情况下。你可以直接回答或者改变方向。这花费了导师几分钟的时间,但可以为学员节省几个小时
  • 此外,看到你的学员如何进步并取得成功也是令人满意的
  • 我认为最常见的动机之一就是渴望分享经验。人们写博客,发表演讲,制作视频来分享他们的知识,以帮助人们避免错误。当然,告诉人们他们有多棒,但这不太适用于指导
  • 人们常说,理解某事的最好方法是把它教给别人。指导给了我们一个绝佳的机会。它有助于构建和系统化知识,提高和完善基本技能。如果很多人问类似的问题,你可以在以后与公众分享这些专业知识
  • 指导和任何讨论一样,允许从不同的角度看待一些问题。通常一个新的观点会带来新的更好的解决方案,你可以在未来使用
  • 指导也帮助我学到了很多新东西。有时人们会问我一些超出我专业范围的问题。但是由于我的知识和经验,我可以很快学会这些东西并帮助解决问题。还有,有时候我有想法但是没有时间或者机会去尝试;我可以向学员提供这些想法,并看到结果
  • 指导还能提高沟通和其他软技能
  • 指导增加了你的社交网络。你永远不知道你的学员会取得什么成就。他们很可能会在未来帮助你
  • 最后,你可以写一篇关于你的经历的博文😉

当导师不指导时

有必要再次重申,不同的导师有不同的风格、技能和偏好。这意味着有时导师可以拒绝指导请求,因为他们不能或不想满足学员的期望。

我已经提到我过去拒绝成为一名导师。我想分享我做出这些决定的一些理由。

  • 我害怕承诺。是的,就这么简单。我害怕成为一名完全的导师,让我未来的学员失望,所以我拒绝了。
  • 我不想教基础的东西(在工作中教是个例外)。如果有人要求解释逻辑回归是如何工作的,我会给出好文章的链接,就这样。原因之一是这些话题已经有足够多的优质资源。另一方面,很有可能我多年没有刷过这些话题,所以可能要花很多时间才能记住。
  • 我们并不总是有足够的空闲时间。有许多 DS 活动、爱好和生活本身——有时你没有足够的时间教其他人。
  • 有些人想被填鸭式喂养。他们不想接受暗示或建议——他们期待直接的答案和现成的解决方案。有些人希望我能解决他们的问题,并把完整的工作代码发给他们,而他们自己却什么也没做。
  • 他们想在我不感兴趣的话题上得到指导。

你需要指导吗?

我产生的迷因

这是一个好问题。

我想说,指导的主要优势是比没有它更快地得到结果。

想象一下当你需要完成一项你并不完全熟悉的任务时的情况。你可以在论坛、社交媒体、社区上寻求建议。你可以搜索论文、博客文章、视频和课程。在这之后,你会得到一堆材料,许多建议(其中一些可能是相互矛盾的),以及许多可以尝试的东西。当然,你可以自己完成所有的工作,或者使用最新和最流行的资源推荐。但是导师可以帮助你避免典型的错误,并指出哪些在实践中有效,这将节省你很多时间。更重要的是,导师可以分享一些基于经验的想法,这是你想都没想过的。

另一方面,如果你现在没有导师,找到他们可能需要更长的时间,所以自己解决问题可能会更快。

我想有导师吗?

这可能很讽刺,但我很少有机会有导师。

我从论坛、社区、会议和工作中学到了很多东西。有些人,我可以称之为导师,但通常是短期的。过去有(现在仍然有)我们与之交谈并分享经验的人。但是我想我从来没有请过任何人做我的导师。

一部分是因为缺乏自信和自我怀疑,一部分是因为我习惯了自学,一部分是因为我对很多事情感兴趣,参加了很多活动,因此不知道半年后我会做什么。

我想有一个导师吗?当然了。但首先,我需要找到这个问题的答案,“我想被教导什么,我想实现什么”。

如何获得导师

我生成的模因

让我们回到这篇博文提出的第一个问题。寻找导师很有挑战性;通常,人们不知道从导师那里能期待什么,不知道他们能提供什么作为交换,也没有目标。我将分享几个想法:

  • 最重要的是——学员和导师应该和谐相处。他们可能有不同的心态,不同的表达方式,其他更喜欢的教学/学习方法——有时指导不起作用;
  • 你需要有一个具体的要求,而不是泛泛而谈。如果你写“帮助我成为 DS”,你很可能会收到一个普通的回复或者一篇博客的链接;
  • 如果你没有尝试自己做任何事情,不要指望导师会为一个技术问题写出完整的解决方案;
  • 一些导师要求潜在的学员通过特定的测试,因为他们不想从头开始教授一切;
  • 也有导师在社交媒体上发布他们正在接受学员的情况——这可能是找到导师的理想选择;
  • 多了解导师,问相关的事情。如果指导者从未接触过音频,不要要求音频处理方面的指导;
  • 如果你想有更高的成功几率,那就试着在初次接触时参考导师活动中的一些东西。例如,说你对他们的一次谈话感兴趣,并询问更多细节;
  • 这取决于导师的性格,但有些导师愿意接受指导请求;有些人喜欢简单地回答问题。对不同的人尝试不同的方法;
  • 如果可能的话——提供一些东西作为指导的交换。例如,如果你想让一位导师帮助你参加 ML 竞赛,给他们在团队中提供一个位置以换取指导(尽管你没有提交任何参赛作品,但这种方法可能会失败)。只有当导师以提供有偿指导而闻名时,才提供金钱补偿;否则,它可能会导致拒绝;
  • 如果你的公司提供导师项目,这可能是最好的选择;

结论

这就是我的指导经验和我的想法。我希望我的博客文章能更清楚地说明从导师的角度来看,指导是怎样的,以及它的困难和优势。不是每个人都需要一个导师,尤其是如果有可能从在线社区获得支持的话,但是获得一个好的导师可能会给你的技能和职业生涯带来巨大的推动。

页(page 的缩写)这篇博文最初发表于这里

我的 ML 模型失败了。为什么?是数据吗?

原文:https://towardsdatascience.com/my-ml-model-fails-why-is-it-the-data-d8fbfc50c254?source=collection_archive---------23-----------------------

了解模型表现不佳是因为错误的模型选择,还是因为训练数据中的噪声,并提供一个真实的示例。

图片:拉斐尔 1509 年创作的《雅典学院》

介绍

当你建立和训练一个模型并检查其准确性时,机器学习中最常见的问题之一是"我能从数据中获得的准确性最好吗或者 a 能找到更好的模型吗?"。

此外,一旦您的模型被部署,下一个常见的问题是“为什么模型失败了”。有时这两个问题都无法回答,但有时我们可以通过研究模型误差的统计分布来发现预处理误差、模型偏差以及数据泄漏。

在本教程中,我们将解释和演示如何对模型结果进行统计研究,以在示例中发现错误的原因。

商业案例

在本例中,我们将使用来自驱动的数据竞赛的数据,从一组社会经济变量中预测一个人是否生活在贫困状态。

该商业案例的价值不仅在于能够利用机器学习模型预测贫困状况,还在于了解衡量贫困的社会经济变量的预测性,并从特征上分析其原因。

模特培训

数据由一组九个描述性变量组成,其中四个是分类变量,另外五个是数字变量(但是其中一个似乎是 id,所以我们将丢弃它)。

import pandas as pd

pd.set_option('display.max_columns', None)
train = pd.read_csv('train.csv', index_col='id')
print(train)

它返回

 Unnamed: 0 kjkrfgld bpowgknt raksnhjf vwpsxrgk  omtioxzz  yfmzwkru
id                                                                          
29252  2225    KfoTG    zPfZR    DtMvg      NaN      12.0      -3.0   
98286  1598    ljBjd    THHLT    DtMvg    esAQH      21.0      -2.0   
49040  7896    Lsuai    zPfZR    zeYAm    ZCIYy      12.0      -3.0   
35261  1458    KfoTG    mDadf    zeYAm    ZCIYy      12.0      -1.0   
98833  1817    KfoTG    THHLT    DtMvg    ARuYG      21.0      -4.0   

       tiwrsloh  weioazcf   poor  
id                                
29252      -1.0       0.5  False  
98286      -5.0      -9.5   True  
49040      -5.0      -9.5   True  
35261      -5.0      -9.5  False  
98833      -5.0      -9.5   True 

这里可以看到数据分布

按作者分类的图像:数据集中用目标着色的所有要素的成对绘图。黄色表示差=假,紫色表示差=真。

在一些预处理(NaN 值插补、缩放、分类编码等)之后,我们将训练一个 SVM 模型(它通常在来自一键编码的高维数据中工作良好)

支持向量机

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import RobustScaler
from sklearn.neighbors import KNeighborsClassifier

model = Pipeline(steps=preprocess+[
                 ('scaler', RobustScaler()),
                 ('estimator', KNeighborsClassifier(n_neighbors=5))])

model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(classification_report(y_test,y_pred))

它返回

precision    recall  f1-score   support

       False       0.73      0.77      0.75       891
        True       0.70      0.66      0.68       750

    accuracy                           0.72      1641
   macro avg       0.72      0.71      0.71      1641
weighted avg       0.72      0.72      0.72      1641

从二进制分类问题来看,0.72 的精度不是非常好的精度。相比之下,查全率和查准率似乎是*衡的,这使我们认为该模型不是偏向于任何一个类别。

测试其他模型

尝试改进模型的下一步是尝试其他 ML 模型和超参数,看看我们是否找到任何提高性能的配置(或者甚至只是检查性能是否在*稳状态下保持不变)。

我们将使用来自不同系列函数的两个其他模型。KNN 模型是学习局部模式影响的一个很好的选择,梯度增强树也是具有最高能力的 ML 模型之一

K-最*邻

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import RobustScaler
from sklearn.neighbors import KNeighborsClassifier

model = Pipeline(steps=preprocess+[
                 ('scaler', RobustScaler()),
                 ('estimator', KNeighborsClassifier(n_neighbors=5))])

model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(classification_report(y_test,y_pred))

它返回

precision    recall  f1-score   support

       False       0.71      0.74      0.72       891
        True       0.67      0.63      0.65       750

    accuracy                           0.69      1641
   macro avg       0.69      0.69      0.69      1641
weighted avg       0.69      0.69      0.69      1641

梯度推进

from sklearn.pipeline import Pipeline
from sklearn.ensemble import GradientBoostingClassifier

model = Pipeline(steps=preprocess+[
                 ('estimator', 
                  GradientBoostingClassifier(max_depth=5,
                                             n_estimators=100))])

model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(classification_report(y_test,y_pred))

它返回

precision    recall  f1-score   support

       False       0.76      0.78      0.77       891
        True       0.73      0.70      0.72       750

    accuracy                           0.74      1641
   macro avg       0.74      0.74      0.74      1641
weighted avg       0.74      0.74      0.74      1641

我们可以看到,其他两个模型的表现似乎非常相似。这提出了以下问题:

这是我们用 ML 模型所能预测的最好结果吗?

模型预测分布

除了检查性能的一般指标之外,分析模型输出分布也很重要。我们不仅要检查测试数据集中的分布,还要检查训练数据集中的分布。原因是因为我们不想看到我们的模型表现如何,而是是否也学会了如何分割训练数据

import matplotlib.pyplot as pltpd.DataFrame(model.predict_proba(X_train))[1].hist()
plt.show()

按作者排序的图片:在训练集上评估的模型输出分布

pd.DataFrame(model.predict_proba(X_test))[1].hist()
plt.show()

作者图片:测试集上评估的模型输出分布

我们可以看到,在 0 的预测数量中有一个高峰,这表明有一个数据子集,该模型非常确定其标签为 0。除此之外,分布似乎相当均匀。

如果模型已经知道肯定区分两个标签,则分布将具有两个峰值,一个在 0 附*,另一个在 1 附*。因此,我们可以看到我们的模型没有正确地学习模式来区分数据。

偏差分布

我们已经看到,该模型还没有学会清楚地区分这两个类别,但我们还没有看到它是否即使不自信也能猜出预测,或者它只是一直失败。

此外,检查模型是否更偏向于某一类别也很重要。为了检查这两个方面,我们可以画出预测值与目标值的偏差分布图

train_proba = model.predict_proba(X_train)[:,1]
pd.DataFrame(train_proba-y_train.astype(int)).hist(bins=50)
plt.show()

作者图片:模型置信度输出与在训练集上评估的基础真实值的偏差

test_proba = model.predict_proba(X_test)[:,1]
pd.DataFrame(test_proba-y_test.astype(int)).hist(bins=50)
plt.show()

作者图片:模型置信度输出与测试集上评估的基础事实的偏差

从这两幅图中我们可以看到,偏差分布似乎是对称的,以零为中心。差距正好为零,因为模型从不返回 0 和 1 的精确值,我们不必担心这一点。

如果模型误差来自训练数据的统计/测量噪声误差,而不是偏差误差,我们预计偏差分布遵循高斯分布

我们的分布类似于在 0 中具有更高峰值的高斯分布,但是该峰值可能是由于模型预测的更大数目的 0(即,模型已经学习了一种模式来区分 0 的子集和 1 的类别)。

正规性检验

由于训练数据中的统计噪声,在考虑模型预测偏差是否合理之前,我们必须确保它们遵循高斯分布。

import scipy

scipy.stats.normaltest(train_proba-y_train.astype(int))

带退货

NormaltestResult(statistic=15.602215177113427, pvalue=0.00040928141243470884)

在 p 值=0.0004 的情况下,我们可以假设预测与目标的偏差遵循高斯分布,这使得模型误差来自训练数据中的噪声的理论看似合理。

模型可解释性

正如我们之前提到的,这个商业案例的目标不仅仅是一个可以预测为什么会发生以及与之相关的社会经济变量的模型。

可解释模型不仅能对未知数据进行预测,还能提供特征如何影响模型的信息(全局可解释性),以及为什么某个预测是这样的(局部可解释性)。

然而,一个模型的可解释性越少,也就越有助于理解它为什么能做出预测以及为什么会失败。从梯度推进模型中,我们可以如下提取全局可解释性:

cols = X_train.columns
vals= dict(model.steps)['estimator'].feature_importances_

plt.figure()
plt.bar(cols, vals)
plt.show()

作者图片:梯度增强特征重要性

现在,我们将进行相同的特征重要性分析,但只是在数据子集内进行训练。具体来说,我们将只使用零类别的明显为零的数据(之前模型明确预测为零的数据)来训练模型。

zero_mask = model.predict_proba(X_train)[:,1]<=0.1
one_mask = y_train==1
mask = np.logical_or(zero_mask,one_mask)
X_train = X_train.loc[mask,:]
y_train = y_train.loc[mask]
model.fit(X_train,y_train)

现在特征的重要性是

作者图片:在模型表现最佳的训练集的子样本上训练的梯度增强要素重要性

我们可以看到,现在, tiwrsloh,yfmzwkru 的重要性增加了,而 vwpsxrgk 的值减少了。这意味着人口中有一个子集明显不属于贫困人口(0 类),可以用贫困变量中的这两个变量来表征,并且 vwpsxrgk 在许多情况下可能很重要,但并不具有决定性

如果我们绘制这两个特征的过滤值,我们会看到:

按作者分类的图像:分割并描述模型明确检测到非贫困的特征区域。

对于这两个特征,模型已经学会区分两个类别,同时对于这些变量的其他值,对于整个数据集,零类别和一类别是混合的,因此不能清楚地区分。

我们也可以从前面的图表中将非贫困人口的一个明确子集描述为那些具有 tiwrsloh < 0 和 yfmzwkru < -2 的人。

结论

  • 我们分析了在给定数据集中检测贫困的问题,并分析了给定社会经济数据的贫困原因,发现贫困不容易预测,但是,我们可以定义一些明确确定人们贫困状况的区域:tiwrsloh0 和 yfmzwkru < -2。
  • 我们已经尝试了许多不同的型号和配置,性能稳定在 0.75。根据这一点以及模型预测和误差偏差分布的统计性质,我们可以得出结论,问题在于缺乏从训练数据预测目标的预测能力。所以不可能建立一个更好的模型。
  • 数据预测性不足的原因可能是因为噪音,但也因为除了我们的数据集中的社会经济特征之外,缺乏一些预测贫困的预测特征。

我们学到了什么?

我们已经用一个真实的例子解决了模型没有得到足够好的结果的问题。这种情况下的目标是试图理解模型未能理解的地方,如果问题是在数据或模型中。

回答这个问题的过程是:

1 —尝试不同的系列函数模型和超参数,并确认所有的性能都处于*稳状态。

2-对于可解释的最好的一个,计算目标的模型输出分布和偏差分布。如果数据有问题,输出必须一致,偏差必须遵循高斯分布

3-尽管数据是问题所在,但尝试从模型输出和偏差分布中找出模型表现良好的区域。尝试分割和描述这个区域,例如,用这个子集重新训练模型,并提取它的可解释性。

4 —此外,在描述某些子集的特征时,我们可以尝试从业务知识的角度考虑问题是来自数据的统计/测量噪声,还是缺少预测因变量所需的某些特征值。

我的路径变量一团糟

原文:https://towardsdatascience.com/my-path-variable-is-a-mess-e52f22bfa520?source=collection_archive---------12-----------------------

如何清理你在 macOS/Linux 中的路径

莉莉·波普Unsplash 上拍摄的照片

介绍

当你安装一个程序时,它经常要求你添加一个路径到你的 shell 配置文件。我盲目地想,“这个工具很酷。我现在就想用!”过了一段时间后,你发现你的路径变量一团糟。许多重复或三重的路径。是时候清理了。

检查你的路径

以下命令用新行替换冒号,排序,计算唯一路径出现的次数,并显示:

$ echo $PATH | sed 's/:/\n/g' | sort | uniq -c

我从 echo $PATH | sed 的/😕\ n/g ' | sort | uniq-c . Image by Author 输出的部分。

你有不止一次的经历吗?如果是这样,请继续阅读!

macOS 用户

macOS 有path_helper命令。path_helper是构造 PATH 环境变量的助手。

man path_helper:

man path_helper 的输出。图片作者。

默认路径和 MANPATH 值在/etc/paths/etc/manpaths中。并且path-helper 还读取etc/paths.d/etc/manpaths.d目录中的文件。

让我们检查一下/etc/paths的内容:

$ cat /etc/paths
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

这些是 macOS 上的默认路径。如果您的 shell 配置文件中有这些,它将在路径输出中重复它们。

现在让我们检查一下/etc/manpaths的内容:

$ cat /etc/manpaths
/usr/share/man
/usr/local/share/man

当您使用man命令时,它将在上述路径中搜索手册页。

您可以输出 PATH 和 MANPATH 变量:

$ /usr/libexec/path_helper

/usr/libexec/path_helper 的我的输出。注意第一行的/Library/Apple/usr/bin。图片作者。

您可以查看etc/paths.d/etc/manpaths.d中有哪些文件。

$ ls /etc/paths.d
100-rvictl$ cat /etc/paths.d/100-rvictl
/Library/Apple/usr/bin$ ls /Library/Apple/usr/bin
rvictl

它加载了100-rvictl并具有/Library/Apple/urs/bin。我的/usr/libexec/path_helper第一行有/Library/Apple/usr/bin

Ubuntu 用户

Ubuntu 使用/etc/environment进行系统范围的配置,您可以在这个文件中找到默认路径。

ubuntu@shin-instance:/$ cat /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"

/etc/environment 中的 Ubuntu 输出。图片作者。

ZSH 用户

如果您是 ZSH 用户,并且在您的~/.zshrc文件中有太多的路径,您可以在您的~/.zshrc的末尾添加以下内容:

# .zshrc
typeset -U PATH

这可以防止路径变量重复。

添加路径和路径顺序

在 UNIX 上,您可以使用冒号添加多个路径:

PATH="/path1/to/file:/path2/to/file:/path3/to/file:$PATH"

如果您想要前添加一个路径(在默认路径之前),请使用:

PATH="/path/to/file:$PATH"

如果你想追加一个路径(在默认路径之后)使用:

PATH="$PATH:/path/to/file"

例如,如果要添加/usr/local/sbin路径:

export PATH="/usr/local/sbin:$PATH"

如果您的 Bash 脚本在~/bin目录中,并且您想将它放在前面:

export PATH="$HOME/bin:$PATH"

不要在要添加的路径前后添加$PATH

如何在中共享路径。zshrc,。bashrc,。bash_profile

您可能希望在 ZSH 和 Bash shell 中共享相同的路径。一种方法是在您的~/.zshrc文件中获取~/.bashrc

# In the ~/.zshrc, sourcing ~/.bashrc 
. ~/.bashrc

如果您使用 iTerm2 ,iTerm2 在 Preference>Profiles>General>命令下有“登录 Shell”。它会在~/.bashrc之前寻找~/.bash_profile

iTerm2 使用登录 Shell。图片作者。

这意味着您需要在~/bash_profile中获取~/.bashrc:

# In ~/.bash_profile
. ~/.bashrc

然后在~/.bashrc中,添加您想要在 ZSH 和 Bash shell 中使用的路径。添加路径或包含路径的源文件。

# I have all the GNU/Linux PATH in [~/.macgnu](https://github.com/shinokada/macgnu/blob/main/.macgnu) file
. ~/.macgnu
export PATH="/path/to/file1:$PATH"# Terminal color
export PS1="\[\033[01;32m\]\w:$ \[\033[00m\]"# not display errors when using apropos and whatis
alias apropos="apropos 2>/dev/null"
alias whatis="whatis 2>/dev/null"
...

如果您正在寻找其他路径文件,这可能会导致路径重复。您需要仔细检查您是否正在寻找相同的路径。注意不要在不同的 shell 配置文件中添加相同的路径。

结论

如果你声明了一个没有附加或前置的路径变量,你没有从/etc/paths加载路径。从长远来看,这将是问题的一个原因。你总是在你的配置文件中为$PATH变量添加新的路径,比如~/.zshrc~/bashrc等等。我建议偶尔进行路径检查,以获得健康的外壳寿命。在~/.bashrc中编写公共因子并在~/.zshrc中获取是个好主意,但是要小心路径的重复。如果使用 ZSH,添加typeset -U PATH可以防止路径变量重复。

通过 成为 会员,可以完全访问媒体上的每一个故事。

https://blog.codewithshin.com/subscribe

我的电脑与 Azure ML 计算—开始!

原文:https://towardsdatascience.com/my-pc-vs-azure-ml-compute-go-98a6e33e816c?source=collection_archive---------44-----------------------

ML Studio 计算速度更快吗?

照片由蒂姆·高Unsplash 拍摄

几周前,我在 YouTube 上制作了一个视频,内容是将微软 Visual Studio 代码连接到运行在 Azure 计算资源上的 Jupyter 笔记本(通过 Azure ML Studio)。当我制作视频时,我一直在想那个远程服务器到底有多快。

所以我决定测试一下。

这是 Jupyter 设置的视频:

作者提供的视频

设置

我不会让您费力地完成我的探索性数据分析,甚至加载我的数据。这与我的目的没有密切关系,我的目的只是向您展示在我的个人电脑上运行一段重要代码与在 Azure 上进行比较之间的区别。

正如我在 Jupyter 视频中所说的,如果你想跟进,你还需要一个 Azure 帐户,并创建一个 Azure ML Studio 资源。这里有一段视频向你展示如何做到这一切。

作者提供的视频

代码

代码运行的是 GridSearchCV,它不仅运行交叉验证,还进行一些相对重要的超参数调优。我选择这个场景是因为它需要一些时间在我的电脑上运行,并且代表了远程计算的常见情况。

你可以看到代码通过 5 个交叉折叠经历了许多KNeighborsRegressor选项。最后总共是 360 度。根据您的需要,为任何估计器/调整/ CV 选项修改这段代码并不困难。

我还添加了自己的计时器,只是为了获得整个代码的完整运行时间。

我的电脑结果

我的电脑是微软 Surface,配有 i7–8650 u CPU 和 16 GB 内存。我运行的是 Windows 10。即使没有 GPU,它通常也很快。

为了运行所有 360 fits,我的电脑总共用了 4287 秒,即 71.4 分钟或 1 小时 11 分钟 27 秒左右。不可怕,但更能说明问题的是在这段时间里我的电脑发生了什么。

作者图片

我的 CPU 完全被运行的代码消耗了。我认为这是占用所有 CPU 的工作室代码,但它(逻辑上)实际上是 Python:

作者图片

看看所有这些 Python 进程!整个 1:11.27 的 CPU 利用率超过 90%。虽然在我的电脑上做其他事情在技术上是可能的,但实际上是不可能的。一个多小时了。在一个简单的模型上。做一件事。

Azure 计算结果

在 Azure 中,我创建了一个很好的 CPU(对于一个免费帐户来说,这是我能做到的最好的了)——它不是 GPU。标准 DS12 V2 计算机拥有 4 个内核和 28 GB 内存。默认情况下,Azure ML Studio Compute 运行在 Linux 上。

它肯定比我的电脑更强大。而且是 30 美分一小时

作者图片

在连接到 Azure 的 Jupyter 笔记本上运行完全相同的代码需要 1621.6 秒,也就是 27 分钟零 2 秒(27.02)。云计算运行速度提高了 62%。但更重要的结果是:

作者图片

Python 是空闲的,我的 CPU 利用率下降到了 12% ( < 3% was Studio Code). This mean while those 360 fits were running, I can do anything I want on my PC!

Not bad for a free account and about 30 minutes of setup (total). Imagine what that could be with a GPU or better yet, a GPU cluster (I can’t create either of those with the free account or I would have).

Some Conclusions and Wild Financial Speculation

I’m not going to try and convince anyone about the value of cloud. But there are some facts worth noting:

  • I can get the latest and greatest CPU/GPU (if I have a real subscription) with almost no effort
  • I need to do 很少管理那个服务器
  • 当我不用它的时候,我不付钱(只要我用完它的时候记得关机
  • 我没有在上面安装任何软件(正如我在 Azure 安装视频中演示的那样,添加 Python 包超级容易)
  • 在代码运行时,让我的计算机可用对我来说是无价的;我不需要等待,可以同时处理很多这样的情况

我决定模拟(胡乱猜测)这在财务上可能是什么样子。我的电脑买的时候大约是 1800 美元。如果我是一家公司,有一个 3 年的折旧计划,那么每年就是 600 美元。

假设我运行了 1000 次像我的例子一样的代码。也就是 1000 * 71 分钟,也就是 71000 分钟,也就是 1183 个小时。我的电脑每小时的费用大约是 600 美元(每年的成本)除以 1,800(我每年工作的小时数……是的,没错)。这大约是每小时 33 美分(比我预期的更接* Azure)。这相当于每年 394 美元。

在 Azure 上运行这个工作负载是 1000 * 27 分钟或 27000 分钟(450 小时,快 62%)。450 * .30 = $135.少了 259 美元,或者说便宜 66%。更不用说,当代码在 Azure 中运行时,我可以在我的电脑上做任何其他事情,而当我在电脑上运行工作负载时就不是这样了。

我知道,这是一个非常粗略的财务草图(充其量),但当数字改变时,价值不会改变(只是或多或少)。

在我看来,Azure 在各方面都赢了。虽然自从我有了 Surface,微软输了吗?(因为我买了 Surface,而且我也在写关于 Azure 的东西,所以我猜不会。)

云计算快乐!

我最*在谷歌的面试经历

原文:https://towardsdatascience.com/my-recent-interview-experience-with-google-c7e8e1206260?source=collection_archive---------14-----------------------

从写技术文章到谷歌(差不多)

Firmbee.comUnsplash 上拍照

个人故事。

介绍

如果你想让自己在新技术主题上保持最新,尤其是在数据科学和机器学习领域,写技术文章是实现这一目标的最佳方式之一。

例如,我喜欢从头开始创建机器学习应用程序和 python 程序,并通过记录步骤和做笔记来跟踪开发过程。这次实践教会了我很多。

写我已经完成的项目就像向自己展示我是如何完成的。过了一段时间,我发现我这样学得更好。我就是这样体会到写作和教学的力量的。我认为教学是长期学习的最佳途径,即使你是在自学。

作为一个软件工程出身的人,我可以说技术写作对我来说并不有趣。但是写的越来越多之后,我觉得用起来更舒服了。这也是我申请谷歌技术写作职位的动机。

在这篇文章中,我将分享我在谷歌的申请过程,以及它如何帮助我更好地了解自己。整个申请过程花了我不到一个月的时间。事情是这样的。

第 1 步,共 4 步

星期一,申请了这个职位。软件工程技术作家。

周三,招聘人员发来一封邮件。得到快速回复,我超级兴奋。

使用日历链接安排的电话呼叫。

周五,与招聘人员进行 30 分钟的电话交谈。进行得太顺利了。善良友好的人。我真的很喜欢这次聊天。

我已经走到第二步了。分享我的一些作品。

第二步,共四步

一周后。

我想保持列表的多样性。所以,我从三个不同的主题中挑选了文章:语音识别,人脸识别和语音情感识别。

周五,我和招聘人员分享了我的三份技术写作样本。

周末,很高兴得到反馈。

下周。

周一,招聘人员回复。对书写样本进行了审查。我被下一步录取了。耶!

周二,一封来自招聘协调员的邮件。下周安排一次面试。

很棒的电子邮件,解释了面试过程的一切。谷歌会议链接。以及更多关于这一过程的有用指南的链接。

第三步,共四步

下周。

星期一,大日子!采访技术作家。他已经在谷歌工作了 5 年多。很知性的人!我真的很喜欢这次谈话。这是一次 45 龙敏的采访。

我们检查了写作样本,他问了一些技术问题。

最后,我也有机会问了许多问题。整个面试进行得很快很顺利。

第 0 步,共 4 步

同一周。

周三,我收到了招聘人员发来的一封电话聊天的邮件。得知自己的表现,我非常兴奋。

反馈:需要更多经验。

我被拒绝了。我有点震惊。我很难过。

经过一周的消化一切;我不再感到悲伤,尽管我为自己感到骄傲。让我告诉你为什么。

一点背景

我喜欢做创造性的事情。而写作绝对是其中之一。自由写作。在自己的时间用自己的声音写作。

去年在一级防范禁闭期间,我开始编写动手编程教程。我已经有了一个小的个人博客,我经常在那里写东西。当我有机会呆在家里一段时间时,我决定试一试,把我的博客带到一个新的高度。就在那时,我决定加入媒体伙伴计划,与世界分享我的文章。

经过 18 个月的写作经历后,我来到了这里。有超过 2000 名追随者,我不知道有多少人观看。是的,有点多。(我不喜欢分享号码,所以我会保守这个秘密。)

我喜欢我在这里做的事情。与大家分享动手编程教程和项目。与出色的出版物和编辑合作。与来自世界各地的读者和作家没有任何界限的联系。

那么,为什么我对被拒感到高兴呢

  • 我了解到“技术写作者”的职位并不适合我。至少在我人生的这个阶段。
  • 我了解到我在这里做的事情和在一家高科技公司成为一名技术作家有点不同。技术作家大部分时间都在写文档,我更喜欢博客风格。
  • 我发现我的年龄还不足以胜任技术写作的职位。在美国,技术作家的*均年龄是 46 岁。我现在还 20 多岁。
  • 我了解到面试对双方来说都是很棒的经历。在进行下一步之前,你可以随意问他们你想知道的任何问题。
  • 我很高兴我申请并通过了整个过程。我一路走到了第三步,对此我非常自豪。
  • 谷歌的面试过程是如此的顺利和中肯。我在路上遇到的每个人都很好,很善良。我一点也不觉得有压力。我会保持联系,为未来不同的机会。

我的计划是什么?

对我来说,写作是铅笔,而不是最终产品。比起写作,我更喜欢创造新事物的过程。

  • 我将更加专注于软件开发。
  • 我会继续在 Medium 和我的个人博客上分享动手编程教程。
  • 我将继续联系我的读者,帮助他们解决编码问题。
  • 我将更加努力在我的行业获得更多的经验。
  • 我会提出一些项目想法,这些想法可能会成为未来个人公司的种子。如果事情没有按计划进行,早点开始将有助于我有更多的时间再次尝试。

最后的想法

拒绝给了我时间 重新思考提问 我的目的地就分在这人生的旅途中。这是值得的。

感谢您花时间阅读我的简短采访之旅。这是一个个人故事,但我希望它能给你一些启发和灵感。我写这篇文章的目的是安慰我自己和任何可能需要勇气来处理生活中这种拒绝的人。请随时通过我的博客联系我。

我是 贝希克·居文 ,喜欢分享编程、教育、生活方面的故事。 订阅 给我的内容留下灵感。Ty,

如果你想知道我写什么样的文章,这里有一些:

我的屋顶项目——卫星图像和计算机视觉的例子

原文:https://towardsdatascience.com/my-rooftop-project-a-satellite-imagery-computer-vision-example-e45a296129a0?source=collection_archive---------11-----------------------

让深度技术和遥感为对抗全球变暖服务

凯文·杨在 Unsplash 上的照片

我们都越来越关注全球变暖。随着时间的推移,世界上又一场自然灾害发生了。如果你在这个线程上,你可能想做点什么。如果你能用你所有的知识,你所有的背景来建立一个系统来对抗它,让我们的生活更可持续会怎么样?作为一名机械和航空航天工程的双学位毕业生,我发现热岛的一个方面可以通过计算机视觉技术和数据挖掘来有效地解决。在这篇文章中,我将向您介绍一个简单而全面的解决方案,这是我在参加欧空局举办的哥白尼大师赛 2021 期间开发的。这次黑客马拉松通过征集对抗气候变化的概念来促进卫星图像的利用。在影像上使用著名的 Mask-RCNN 时,该解决方案可以定位助长热岛现象的深色屋顶建筑物。

1.热问题:黑暗是热的

未来几年城市地区的主要问题之一将是热岛现象。城市中心通常使用的建筑材料,如混凝土、柏油路面和钢铁,限制和储存入射的太阳能,使大白天的温度大幅上升至 40°c。另一方面,众所周知,在没有这些材料的地方,如农田或农村,即使在热浪期间,温度也不会上升太多。显然,解决办法是消除这些材料和太阳能之间的相互作用,但是说起来容易做起来难!在这种情况下,空调通常用于将热量从建筑中带走,但它只是将热量转移,而不是将热量带出城市(热量最终会重新进入被冷却的建筑,参见傅立叶定律)。所以问题依然存在。

城市热岛示意图(资料来源:莫里斯和西蒙兹,2000 年)

我对建造屋顶感兴趣,因为它们是问题的核心。它们直接面对太阳,因此它们直接接收入射的太阳能并与之相互作用。当屋顶隔热层用深色涂层制成时,它会明显地储存太阳能,因为众所周知深色会积聚热量。这导致车内温度大幅上升,因此将使用更多的空调。它会使电费更加膨胀。它还会导致周围的大气通过对流变热,然后出现热岛现象。但是你能做什么呢?希腊长期以来所做的是用一种非常反光的白色油漆来粉刷建筑物的侧面。这种颜色会大大增加反射太阳能的部分,因此屋顶吸收的太阳能部分会大大减少。热量不太可能进入建筑物,室内温度不太可能升高,因此空调消耗较少。此外,随着更多的太阳能直接返回太空,周围的大气不太可能变热,热岛现象大大减弱。

图片来自作者

正如你在非常迷人的希腊城市圣托里尼所看到的,白色绘画已经进行了几个世纪,但这一过程在西方国家仍处于萌芽状态。这个项目的目标是使人们能够方便地进入受益于屋顶白色油漆的建筑位置。当地的决策者、政府甚至公司将很容易找到联系人来推动当地的进程。让我向您介绍一个我认为可以完成这项工作的管道概念。

2.管道:计算机视觉和大数据

该管道由 3 个不同的系统组成,这些系统放在一起可以形成一个地址、建筑业主联系方式和屋顶表面的数据库。管道最终对它所处理的任务来说“相当”简单。你可以在下面的幻灯片中看到我在 2021 年夏季哥白尼大师赛上展示的管道。

图片来自作者

  • 空间供应商提供的非常高分辨率的卫星图像随时可用,即每一个大气校正都已经应用。在培训期间,我主要使用美国地质调查局通过国家地图服务公开发布的美国城市图像(芝加哥、奥斯汀、旧金山)。美国地质调查局、国家地理空间计划提供的地图服务和数据。这项服务是开源的,所以你可以对数据做任何你想做的事情!😉

  • 然后对图像进行预处理和格式化,以便正确地输入掩模 RCNN 算法。更具体地说,图像分辨率降低到 0.6 地面米/像素,并被削减到只有 1024 像素边的正方形图像。每一步都使用 GDAL 库来保存嵌入在数据集中的地理空间元数据。tiff 文件。

  • 预处理和分割成训练/val/测试子集的数据然后被馈送到掩模 RCNN Matterport 算法。我选择它是因为,目前,它是对象检测/实例分割领域中最有效的算法之一。这种计算机视觉算法能够检测(单独识别)图片的特定元素,并将它们所属的像素与这些元素相关联。使用图像地理空间信息,可以计算每个屋顶的全球 GPS 坐标,并用经度和纬度来标识。稍后,它将能够估计屋顶表面被刷成白色。

  • 每一对(经度,纬度)被发送到 Google Maps API,使用反向地理编码功能转换成地址。API 发回的信息随后被处理并存储在一个基本的 csv 数据库中(我正在处理 PostGIS 数据库,以获得一个健壮而灵活的工具)。其他 API 功能可用于获取更多关于建筑物的详细信息,如联系信息。

使用 12GB GPU 在 Google Colab 会话上执行训练。迄今为止,我已经能够在一些看不见的图像上测试管道,第一批结果相当令人鼓舞。即使在 0.37 公里的瓦片上仍然没有检测到一些建筑物,主要的建筑物屋顶也能被人工智能正确识别,并被谷歌地图 API 精确定位。与黑客马拉松幻灯片相反,TRL 目前是 6 比 5,因为所有渠道开始表现良好。对于你们当中的数据科学家,我将继续通过改进 mAP 和 mAR 来注释 tiles 以提高管道性能。你可以在我的 Github repo 中找到与这个项目相关的代码。

结论

这个管道项目表明,对抗气候变化的伟大系统可以用每个人都可以获得的技术来建造。如果每一块砖都包含一种专门的技术,那么将它们组合在一起就会形成一条强大的管道。

让我们在我的 LinkedIn 和 T2 Github 上保持联系,了解更多的深度技术项目😉。在 UpWork 上为你的计算机视觉自由工作找到我。#爱芝加哥

我在寻找更好的 Spotify 播放列表,以便在锻炼中使用

原文:https://towardsdatascience.com/my-search-for-a-better-spotify-playlist-to-use-for-workouts-ed8d4a191074?source=collection_archive---------39-----------------------

我如何使用“spotifyr”创建新的健身播放列表,该列表基于我当前健身播放列表中确定的特定音频功能

介绍

照片由德鲁·格拉汉姆Unsplash 拍摄

如果你像我一样,那么你对健身和锻炼的享受将与你对音乐的热爱紧密相连。我相信孔子曾经说过“音乐产生一种人类自然不能没有的快乐”,鉴于我在激烈运动时经常经历的真正的不适,我经常需要音乐的独特快乐来淹没消极的精神沉思,这种沉思反复鼓励我放弃运动,过一种更安静和闲散的生活。

不要误解我,我确实喜欢锻炼和训练(尤其是在最后),然而,我有时会想,如果我听不到我的音乐,感受不到令人愉快的旋律或引人入胜的低音线带来的温暖保证,我是否会同样喜欢我的锻炼。我不会考虑不带耳机和一个足够有条理的播放列表去跑步,我也不会考虑在没有响亮的音乐和访问我的 Spotify 帐户的情况下锻炼。音乐是我锻炼的阳之于阴。

现在你明白了我的锻炼强度和动机是如何与我听的音乐紧密相关的,你可能会更好地理解我这个项目的动机;因为,尽管 Spotify 在应用程序和网络播放器中提供了合理的搜索功能,但我目前不知道有什么功能可以让我根据特定的音频特征(如速度和能量)精确地过滤歌曲。

我知道 Spotify(和其他公司)为锻炼和其他情况提供特色播放列表,但是,因为我没有读过任何关于用于确定这些播放列表中有哪些曲目的具体标准的文档,所以我想我会通过分析我当前锻炼播放列表的音频功能来定义我自己的新锻炼播放列表的标准,来尝试一下。

在这篇文章中,我描述了我如何通过遵循数据驱动的方法和使用 Charlie Thompson 的神奇的spotifyr包来创建一个特定的声音播放列表库。该软件包允许您深入研究您的 Spotify 收听习惯,并提供与您最喜爱的歌曲和艺术家相关的详细信息。我发表这篇文章,希望我分享的任何信息都可能对那些新手、spotifyr的其他用户以及英国音乐的支持者有所帮助。

这篇文章的结构如下:

  1. 在 R/RStudio 中设置spotifyr包;
  2. 我如何分析我当前的健身程序播放列表,以确定我理想的健身程序播放列表所需的曲目数据和音频特征;
  3. 使用spotifyr在 Spotify 中搜索并过滤音频特征符合我所选锻炼标准的歌曲;
  4. 我是如何创建多个锻炼播放列表并上传到我的 Spotify 库中的;和
  5. 我对新锻炼播放列表的最初感受和反应。

初始设置

亚历克斯·格鲁伯在 Unsplash 上的照片

为了避免网上重复的内容,我将避免简单地重复设置和初始化spotifyr的最基本方面的操作方法。对于如何安装和设置spotifyr的概述,Charlie Thompson(软件包的开发者)有一个特定的网页,详细说明了安装和认证软件包所需的步骤,位于这里

除了查理的spotifyr网页,我还发现以下网站有助于设置和初始灵感:

在开始这个项目之前,我用下面的代码初始化了需要的 R 包:

library(spotifyr)
library(tidyverse)
library(scales)

分析我当前的最佳锻炼播放列表

诺贝特·布杜茨基在 Unsplash 上的照片

我首先需要了解 Spotify 音频功能,这些功能定义了我目前认为的剧烈或高强度锻炼的最佳聆听体验。幸运的是,我有一个代表性的播放列表来分析(“我的最佳播放列表”),由 26 首曲目组成,当我需要一致的高节奏节奏和响亮的低音时,我会默认使用它们。

查找我的最佳播放列表的 Spotify ID

我使用函数get_my_playlists(limit = 50)来检索我的库中的前 50 个播放列表。从产生的数据帧中,我能够定位我的最佳播放列表的id,我将其命名为my_optimum_gym_playlist_id。如果您的媒体库包含超过 50 个播放列表,您还需要包含offset = 50来检索您的媒体库中的下 50 个播放列表。

了解我的最佳音频特性

现在我有了最佳播放列表的相关 Spotify ID,我使用函数get_playlist_audio_features()来检索播放列表中每个曲目的流行度和音频特征的数据帧。对于我的初步分析,我只是想了解播放列表中的每个曲目在典型的价/能量情绪象限模型中的排名,其中:

  • 低能/低价歌曲被认为是“悲伤的”或“压抑的”;
  • 低价/高能歌曲被认为是“愤怒的”或“动荡的”;
  • 高价/低能歌曲被认为是“*和的”或“冷的”;和
  • 高价/高能歌曲被认为是“快乐的”或“欢乐的”。

使用上面的代码,我能够直观地看到我的最佳播放列表中的每首歌曲在情感上的排名:

正如我们从上面的散点图中看到的,我的最佳播放列表不包含令人沮丧或冰冷的歌曲,所有歌曲(除了一首)的“能量”值都在 0.50 以上。正如我所料,我的最佳播放列表包含高能轨道。Spotify 表示“充满活力的歌曲感觉起来很快、很响、很吵”,这是一种解脱,因为这个特定的播放列表应该代表我在高节奏和高强度训练中选择的歌曲。

在使用情绪象限模型对我的最佳播放列表中的每个曲目进行可视化后,我想了解该播放列表是否有其他突出的特征,可以用作基准来创建我的理想锻炼播放列表库。

通过使用上面的代码,我能够将原始的my_optimum_gym_playlist_audio_features数据帧转换成长格式,然后我可以用它来创建密度图和总结音频特征数据的表格。

在查看了图表和汇总表后,我注意到了我的最佳播放列表中的以下特征:

  • 音轨的速度在 89 bpm 以上;
  • 响度低于-3 分贝;
  • 仪器化程度小于 0.0062;
  • Key 是一个从 1 到 11 的整数值;
  • 轨道模式为 1 或 0;
  • 音轨的声音、舞蹈性、能量、活性、语速和效价范围从 0 到 1;和
  • 26 首曲目中有 2 首是 2018 年之前发布的。

虽然密度图提供了数值分布的良好视觉效果,但我也为每个音频特性创建了一个箱线图,这样我就可以更好地显示与我的最佳播放列表中每个音轨相关的数值。给定不同音频特征的值的变化和范围,为了显示我的初始箱线图可视化,我排除了“速度”、“音量”、“键”、“模式”、“乐器性”和“音轨持续时间 _ 毫秒”。

我使用上面的代码创建了以下六个选定音频特征的箱线图:

有关每个音频功能代表什么的更多信息,请访问 Spotify 开发者页面 此处

然后,上面的代码用于创建其他六个音频特征的第二个箱线图可视化:

我更喜欢哪种类型?

既然我已经分析了我的最佳播放列表的 Spotify 音频特性,我还需要了解分配给播放列表中每个艺术家的流派。

使用上面的代码,我能够总结并创建一个条形图,显示我的最佳播放列表中分配给每个艺术家的流派:

看着上面的图表,任何认识我的人都不会对这个结果感到惊讶,因为尽管我喜欢美国嘻哈音乐,但我目前更喜欢高强度锻炼时英国嘻哈音乐和 grime 音乐的声音。套用伟大的鲍勃·马利的话,当音乐击中我时,我感觉不到痛苦!只是有一些关于英国曲调和他们的节拍。

通过分析我当前的 Spotify 锻炼播放列表获得的初步见解

现在我已经分析了我的最佳播放列表的音频特征,这个过程的下一部分是决定适当的阈值(最小/最大)。

在查看了各种图表、表格和数据框后,我决定为新的锻炼轨迹选择以下最佳标准:

  • 能量> 0.67;
  • 可跳舞性> 0.64;
  • 节奏> 100 bpm
  • 曲目发布日期> 2017–12–31;
  • 仪器性< 0.0062;
  • 活性< 0.20;
  • 语速< 0.33;
  • 120000 毫秒
  • -11 分贝

我已经分析了我的代表性锻炼播放列表,并定义了 Spotify 音频功能,以将哪种类型的歌曲包含在我的新锻炼播放列表中,现在我必须在 Spotify 中搜索并过滤符合我的最佳标准的英国嘻哈、grime 和英国备选嘻哈歌曲。

在 Spotify 中搜索新的训练曲目

内森·杜姆劳Unsplash 拍摄的照片

在开始这个潜在的耗时的 Spotify 兔子洞之旅之前,我在网上搜索了旨在解决这个 Spotify 过滤难题的相关网站、内容或应用程序。我偶然发现了 Nelson ,一个网站/应用程序,被 Engadget 描述为“一个内部项目,感觉更像是一个玩具,而不是一个确切的工具或适当的功能”,在测试了几次应用程序后,我不得不同意 Engadget 的观点,尽管这个网站很有趣“瞎玩……有时结果有点令人困惑。”此外,流派过滤器排除了英国 hip hop、grime 和英国另类 hip hop,这进一步证实了我将不得不潜入 Spotify 的庞大图书馆寻找我想要的歌曲。

检索艺术家信息和曲目数据

使用上面的代码,我能够检索 Spotify 的“uk_hip_hop”流派中所有艺术家的数据。在执行代码时,我收到了以下警告消息(这似乎不会妨碍我的分析):

In stri_detect_regex(string, pattern, negate = negate, opts_regex = opts(pattern)): argument is not an atomic vector; coercing

您会注意到,在我的代码末尾,我包含了以下内容:

dplyr::filter(!str_detect(genres, "ukrainian"))

我包含了过滤器,因为我注意到最初的数据帧以c("ukrainian hip hop", "ukrainian pop")等“流派”为特色。Spotify 似乎也认为“uk_hip_hop”是“ukrainian_hip_hop”的简称?!

在收集了英国嘻哈艺术家的 Spotify 信息后,我接着对“grime”和“uk_alternative_hip_hop”艺术家进行了类似的练习。

按照上面的代码,我添加了另一个过滤器,以排除属于不想要的流派的艺术家,如“grime brasileiro”、“funk ostentacao”和“fluxwork”(我认为这是 grime 音乐的南美衍生物)。

我使用上面的代码组合了三个数据框,创建了一个包含来自三个流派的 771 位相关艺术家的数据框。

下一步是询问 Spotify 与数据帧中每个艺术家的每个曲目(专辑或单曲)相关的音频特征数据。

使用上面的代码,我可以下载 771 位艺术家的所有专辑和单曲数据。我必须包含insistently(artist_tracks, my_rate)possibly(artist_tracks_insistently, otherwsie = NA)以允许对 Spotify API 的重复调用,并确保错误将默认为 NA。关于insistently()的更多信息,请访问这里,关于possibly()请访问这里

您应该注意到,下载数据确实需要一些时间,所以如果您计划复制这个项目,您可能需要在这个过程的这一部分找到一些事情来占用您的时间。

过滤符合我的最佳锻炼标准的轨迹

现在,我已经从 Spotify 获得了 49,309 首英国 hip hop、grime 和英国 alternative hip hop 曲目的相关曲目信息和音频特征数据,我只需要过滤数据帧中符合最佳标准的曲目。

使用上述代码过滤原始数据帧将磁道数量减少了 96%以上,从 49,309 减少到 1,734。

然后,我使用上面的代码过滤重复的曲目,这样我只保留了每个重复曲目的“explicit”和“album”版本。此外,我还只过滤了英国市场上的歌曲。

在筛选出想要的曲目后,我现在有了一个包含 1,270 首曲目的代表性健身程序库,这些曲目符合我的最佳标准。我将使用这个新的库来创建我的新的最佳锻炼播放列表。

音频功能对比(新旧对比)

使用上面的代码,我能够比较我的新的最佳播放列表库和我的初始 26 轨最佳播放列表的音频特性箱线图。

除了箱线图,我还计算了音频特征*均值的差异和百分比变化。

我使用上面的代码创建了一个汇总表和柱状图,显示了每个音频特性*均值的变化和百分比变化。

虽然该图表似乎描述了我的新的最佳播放列表库的*均乐器性、音调、活跃度、模式和语音的相对较大的变化,但是快速回顾我的原始最佳播放列表表明,*均乐器性、活跃度和语音的相对较大的百分比变化是由这些音频特征的低初始值引起的。此外,key 和 mode 的变化是由它们的深奥性质引起的:key 是从 0 到 11 的整数值,而 mode 只有两个值(0 或 1)。

现在,我已经根据我选择的标准创建了一个最佳锻炼库,我需要将我的 1270 首曲目库分成更小、更易于管理的播放列表,上传到我的 Spotify 帐户。

向我的 Spotify 资料库添加新的体育锻炼播放列表

照片由 Erin SongUnsplash 拍摄

此过程的最后一步是将较大的最佳播放列表库分割成较小的、更易于管理的健身程序播放列表。

我使用上面的代码创建了 26 个随机播放列表,每个列表包含大约 49 首歌曲,都是从我的 1,270 首歌曲的最佳锻炼库中采样的。然后,我可以使用功能add_tracks_to_playlist()将新的播放列表上传到我的 Spotify 账户。

我实现了我的目标!根据对当前锻炼播放列表的音频特征的分析,我创建了 26 个新的锻炼播放列表。

结论

凯文·麦卡琴在 Unsplash 上的照片

在将这 26 个新的锻炼播放列表上传到我的 Spotify 图书馆后,我显然想知道这些播放列表是否不错,或者我是否设法上传了只包含古典音乐曲目和摇滚民谣的播放列表。

在我第一次播放“新最佳播放列表 1”时,我感到惊喜!新的播放列表主要由我没有听说过的歌曲组成,在我最初听的 43 首歌曲中,只有 3 首歌曲似乎没有达到我一直在寻找的锻炼强度或“声音”。从那以后,我又听了另外 40 多首来自其他新的锻炼播放列表的歌曲,我很高兴地告诉大家,大多数歌曲都有我一直在寻找的能量和声音。

这让我开始思考。尽管我已经花了时间来分析和定义我的最佳音频功能的标准,但我仍然在某种程度上受 Spotify 内部测量和分类系统的支配。如果 Spotify 对一系列歌曲进行了错误的测量或错误的分类会怎么样?例如,虽然 Spotify 将可跳舞性描述为基于“音乐元素的组合,包括速度、节奏稳定性、节拍强度和整体规律性”,但我不清楚 Spotify 如何从其描述中详细描述的属性中具体计算可跳舞性。此外,仅仅因为我喜欢锻炼中的某些音频功能,这并不一定意味着我会喜欢符合这些音频功能的每一首歌曲。

唉,就像生活中的大多数事情一样,没有什么是完美的;然而,如果我偶然发现一首不吸引人的歌曲,我可以简单地把它从播放列表中删除。在接下来的几个月里,我将一边锻炼一边使用我的 26 个新的播放列表;希望我不会花太多时间删除歌曲,而不是健身?!

沉默之后,最接*表达不可表达的东西是音乐。

结束

感谢您通读。我希望你喜欢我的分析和写作。如果您有任何问题或意见,请联系我们。谁知道呢…如果有足够多的人感兴趣,我甚至会公开一些播放列表…或者创建一个网站,这样其他人也可以做类似的事情?!

我写一篇成功的数据科学博客的秘密

原文:https://towardsdatascience.com/my-secrets-to-writing-a-successful-data-science-blog-b2597b2553c6?source=collection_archive---------9-----------------------

我是如何在短短一年多的时间里拥有 20,000 名粉丝的

约书亚·厄尔在 Unsplash 上的照片

在 2020 年初,我只是将 Medium 作为一种“媒介”,用于每周记录我对数据科学的学习。当时我甚至不知道什么是媒介——我真的认为它是 WordPress 的替代品。

快进到今天,我现在有将* 25,000 名粉丝,* 4,000,000 篇文章。同样,现在中等收入几乎占我每年总收入的 25%。

在这篇文章中,我想分享我是如何建立我的数据科学博客和我的追随者基础到今天的秘密。请记住,这些技巧不是黑客或欺骗系统的方法——建立一个博客需要大量的工作。然而,这些建议会帮助你思考一些你以前可能从未想过的事情。

说了这么多,让我们开始吧!

提示 1:找到你擅长写的东西、你喜欢写的东西和人们喜欢读的东西的交集。

作者创建的图像

这是我给有抱负的作家的第一个建议。理想情况下,你想找到一个满足这三个条件的利基市场。

如果你发现你擅长写的东西,你也喜欢写它,但人们不喜欢阅读它,那么你就不会建立一个粉丝群(假设你在乎这个)。

如果你发现一个你擅长写的话题,人们喜欢读它,但你不喜欢写它,那么你不会持续很久,因为你会失去兴趣。

最后,如果你发现一个你喜欢写的话题,人们喜欢读它,但你不擅长写它(例如,因为你没有足够的专业知识),那么你可能不会得到任何牵引。

所以,在你旅程的开始,找出你的定位。我将在技巧 3 中详细阐述这一点。

技巧 2:理解你正在编写的*台的机制。

无论你是使用 Medium,Substack,Patreon,还是其他的博客*台,确保你花时间去理解这个*台是如何工作的。

我不能透露太多细节,但理解诸如收益是如何计算的,*台如何帮助你做广告,以及诸如此类的事情是值得思考的。

通过理解媒体的机制和它是如何工作的,我能够最大限度地拓展我的范围,并最终更快地扩大我的追随者基础。

下一个技巧将帮助你实现技巧 1 和 2:

技巧 3:在创建内容时,考虑“开发与探索”的概念。

为了找到技巧 1 中三件事的交集,并理解你正在编写的*台的机制,考虑一下开发与探索的概念。

这个想法来自于一个叫做“多臂土匪问题的统计问题我不会说得太详细,但“探索和利用”背后的主要思想是决定是探索并发现新的潜在想法,还是利用你已经知道有效的想法。

在你写作/博客生涯的开始,探索和尝试尽可能多的想法,看看什么最适合你,这对你最有利。这意味着写不同的主题,在不同的出版物上发表(在媒体上),并可能尝试新的写作风格。

随着你在写作风格和偏好上变得更加成熟,你可能会偶然发现一个让你在写作中持续成功的“秘诀”。这是你可以开始利用这一突破,加倍你的秘密公式。

总而言之,在旅程的早期尽可能多地探索,当你开始定义自己并找到成功时,开始利用那些让你成功的见解和想法。

提示 4:及时了解人们感兴趣的阅读内容。

这可能取决于你写的主题,但由于我写的是数据科学,我必须始终跟上人们有兴趣了解的内容,因为总是在变化

我该怎么做?

这没什么稀奇的,但我只是有一个网站和 YouTube 频道的列表,我会定期浏览这些网站和频道,以提出新的想法。比如看到一个学习 SQL 的速成班,就想着写一个 52 周的速成班,学习包括统计学、Python、SQL、Pandas 等数据科学技能

通过了解人们感兴趣的最新信息,并花时间思考新的想法,你将能够建立一个内容管道,永远不会缺乏可写的想法!😃

秘诀 5:保持一致的时间表。

这个听起来很明显,但是我真的相信遵循这个建议是我成功的支柱。

去年,我承诺在 52 周内每周学习和写作数据科学,这样做让我能够建立一个有效的系统,在一致的基础上撰写文章,而不会筋疲力尽。此外,通过保持一致,你无疑会推出更多的内容,最终让你的博客发展得更快。

所以找一个适合你的写作时间表,不管是一周一篇还是一个月一篇,坚持下去!

感谢阅读!

我希望这对你有所帮助!这和我*时写的有些不同,但是如果你想看到更多这样的文章,请留下评论。

一如既往,我祝你学习一切顺利。😃

不确定接下来要读什么?我为你挑选了另一篇文章:

[## 我如何利用数据科学在一年内将收入翻倍

towardsdatascience.com](/how-i-used-data-science-to-double-my-income-in-one-year-c8ba8c28ce8f)

又一个!

特伦斯·申

  • 如果你喜欢这个, 跟我上媒 了解更多
  • 有兴趣合作吗?让我们连线上LinkedIn
  • 报名我的邮箱列表 这里

我开始接触数据科学

原文:https://towardsdatascience.com/my-start-to-data-science-9ff46431996?source=collection_archive---------37-----------------------

我的数据科学本科学位之旅

詹姆斯·彭纳在 Unsplash 上的照片

2020 年 5 月 23 日是我完成数据科学本科学位的日子。

在过去的四年里,我挣扎了很多,但是我得到了将会伴随我一生的朋友和知识。尽管我还是觉得很奇怪。感觉就像是昨天我拥抱着我的父母告别,开始了我大一的第一天。然而,回忆我的过去不会成为一篇非常引人注目的文章,所以我想带你踏上我在数据科学中寻找激情的旅程。

我想和你谈谈我的一些数据科学课程,以及它是否对我未来的数据科学有所帮助。我也想和你分享一些我帮助其他学生的方法和有效的学习方法。

我还想指出,大学并不便宜。网上有丰富的信息,所以无论是金钱、家庭还是距离,四年制课程并不是每个人的最佳选择。然而,与其他有抱负的数据科学家一起学习和成长的经历对我来说是无价的。

我的大学之旅

Avinash MurugappanUnsplash 拍摄

和一些人一样,我实际上并不是从数据科学家开始的。我进入大学的第一个学期实际上是作为一个计算机工程专业(CPE)。我一直以为我会被一家大公司雇用,成为一名承包商。然而,我正在做的工作让我感到不满足。

2017 年春天,在与一位朋友交谈后,他告诉我大学里一个更新的项目,名为计算数据科学(CDS)。这听起来很有趣,我联系了本科生导师以获得更多信息。他是一位年长的绅士,年轻时在地里干活。他给我看了一些数据科学研究生正在做的研究项目,从那以后,我知道我迷上了数据。

“数据科学家有点像新文艺复兴时期的人,因为数据科学本质上是多学科的。”

John 领班

2017 年秋天,我正式从 CPE 转到 CDS。我在该专业的前几堂课涉及计算思维和 Python 及 r 编程。渐渐地,我开始接触班上的其他学生并与之互动。起初,我们只是谈论一般的课程,但最终我们会一起吃午饭,分享不同的项目,在线课程和资源。这是一个很好的环境,帮助我专注于我的学习。所以我强烈建议,尤其是如果你是这个领域的新手,在课堂之外与你的同龄人互动。

到 2018 年秋天,我已经完成了 CDS 课程的一半,并认识了许多新同事。我当时的课程主要集中在数据可视化、数据库和数据挖掘技术上。我也努力在我的系里保持形象,和教授们谈论他们在这个领域的经历。最终,我和其他学生想出了创办一个数据科学俱乐部来推广该领域的想法,到下学期,我们已经完全投入使用了。在我们在一起的时候,我们互相帮助提出关于个人项目的想法,将在线资源正规化,并组成了一个紧密团结的团队。

“你可以有没有信息的数据,但你不能有没有数据的信息”——丹尼尔·凯斯·莫兰

到 2019 年秋季,我的大多数课程都专注于高级数据建模、机器学习、处理非结构化数据和模拟。通过一名前俱乐部成员,我得以获得一个为学校做一些数据科学工作的机会。这个角色教会了我很多如何成为一名成功的数据科学家,但那是以后的事了。当我设法在当地一家公司找到实习机会时,情况开始好转,我真的很想拿到学位毕业。

2020 年春季将会是一个非常难忘的学期。我不知道我们都将经历一场全球性的疫情,在我知道之前,每个人都不得不呆在家里。像许多其他人一样,没有人知道会发生什么,不幸的是,我曾经的实习被取消了。尽管压力很大,但在几个月内,我完成了本科的一天。

数据科学课程

耶稣·希拉里奥·h .在 Unsplash 上的照片

以下是我对数据科学项目的一些想法

  • 建模与仿真 I:这门课主要教授 Python 的基础知识和算法思维技能的发展。它介绍了基本的软件概念,如测试、调试和数据类型。
  • 建模与仿真 II:在对各种科学应用建模的同时,更加关注 Python 中的高级技术。这个课程确实帮助我熟悉了非结构化数据类型(图像、声音、文本)。
  • 基于代理的建模和仿真简介:本课程主要提供基于代理的建模的背景知识。学习了很多不同的模型,教授也很棒,但是在我的数据工作中不要真的使用 Netlogo。
  • 计算和数据科学介绍:这门课主要关注用 r 进行数据分析。我对使用 RMarkdown 非常熟悉,我们对 Rshiny 也有一个简短的介绍。了解一些数据科学的历史背景也很不错。
  • 数据可视化:本课程主要关注数据可视化的最佳实践。我们讨论了诸如配色方案、完形原理、用户控制等主题。我们可以自由选择任何我们认为效果最好的可视化软件,但课程主要集中在 Tableau 上。
  • 数据库:我们学习了 SQL 的基础知识,同时学习了数据库系统的基础知识。我们主要练习开发复杂的查询和建立数据库。
  • 科学数据挖掘/机器学习:这实际上是两个课程。我把他们分在了一起,因为他们是由同一个教授教授的,基本上是按系列教授的。这堂课真的很酷,因为我们深入探讨了让我对数据科学感到兴奋的话题。这些包括监督学习,非监督学习,强化学习,推荐系统,神经网络,并谈到了很多历史。这位教授刚从视频游戏行业的数据科学领域出来,所以他给课堂带来了很多有趣的话题。
  • 数学和统计:最后,程序调用了单变量和多变量统计以及 Calc (I,II,III)和线性代数。主要用作职业生涯的基础课。

结论

这就是我四年的大学生活,总结成一篇文章!当然,除了无数个小时的在线学习、工作和学习新资源之外,这只是一个简短的概要。所以我就回到之前的问题,“拿个数据科学的本科学位值得吗?”我的答案是,老实说,这取决于你如何学习,以及一个项目提供了哪些资源来满足你的具体目标。

如果你的项目需要你参与很多实践项目,并且是一个既定的项目,那么我会说去做吧。除了得到一张证明你合格的纸之外,我看到的最大好处是在一个以数据为导向的环境中与有相似目标的人在一起。这帮助我发展了更多的软技能,并获得了分享不同想法和在该领域发挥创造力的信心。

总的来说,我对本科阶段所教的课程感到满意。我目前正在研究生院读第一年,我一定会让每个人都知道将来会发生什么!

特别感谢我的同学 Jordan,他让我进入了数据科学领域,感谢我的室友和女朋友,感谢他们不断的鼓励,最后感谢我的导师 Joe,他让我走过了我的旅程!

感谢您的阅读!

库珀·巴雷特生存指南毕业 GIF

我和 UNV 在新冠肺炎数据项目中作为在线志愿者的故事

原文:https://towardsdatascience.com/my-story-as-an-online-united-nations-volunteer-on-covid-19-data-projects-17a5d159980a?source=collection_archive---------34-----------------------

变更数据

#社会影响数据:对公开数据和众包的思考

联合国开发计划署亚太地区区域创新中心 UNV 在线志愿服务在线志愿者邓华。

Unsplash雷桑加库苏马的照片

新冠肺炎,2020 年最重要的话题,已经俘获了每个人的心,我也不例外。作为一名拥有数据科学专业知识的研究生,尽管我渴望为这场全球抗击疫情的斗争做出贡献,但我不知道如何才能参与进来。幸运的是,通过在线联合国志愿服务的机会,我加入了联合国开发计划署曼谷区域中心的区域创新中心,为东南亚的新冠肺炎数据分析提供支持。

我想知道是否也有像我一样的学生或专业人士,他们愿意自愿为社会公益贡献他们在数据科学方面的专业知识,但发现很难获得机会。

当我在寻找机会的时候,我确实找到了一些。比如在公益组织做实习;加入学术研究; DrivenData ,举办社会影响领域的数据科学竞赛; DataKind ,以项目为基础提供志愿服务机会。但总的来说,仍然没有足够的机会,或者接*这些机会的方法并不广为人知。

为什么?

如果没有既定的数据治理系统,数据共享肯定是一个问题。在这种情况下,使用开放数据的项目,或者从收集数据开始的项目会引起较少的关注。例如,根据《每日电讯报》的报道,印度尼西亚政府的国家新冠肺炎特别工作组发言人维库·阿迪萨斯米托说,印度尼西亚政府“赞赏”来自独立党派的报告,如“T2 报告新冠肺炎”的报告,这是一项由公民主导的数据科学活动,要求公民报告疑似新冠肺炎死亡病例,并在此基础上进行分析。

此外,非营利组织可能缺乏为拥有数据科学专业知识和奉献时间热情的人组织这种“为好的数据”机会的经验。他们可能很少看到过去让志愿者参与数据科学项目的案例,因此很少或根本不知道可以做什么以及如何安排。这促使我写这篇博客来分享我作为数据导向项目志愿者的经历,以及我对“数据为善”项目核心步骤的思考。你可以在这里找到关于我的项目的博客,在这里找到 tableau 仪表盘

思考 1——如何确定数据项目的范围?

马库斯·温克勒在 Unsplash 上拍摄的照片

老实说,我们花了很长时间来确定项目范围。我们一开始非常灵活,没有必须做的事情,因为这个项目本质上是探索性的。结果,我们花了很多时间决定做什么,在多个潜在的提议中摇摆不定,而不是实际去做。

我们最终决定制作一个交互式仪表盘,显示我们对东南亚隔离政策的分析。我们相信仪表板可以是一个放大器,可以激发更多的工作,我们的分析可以是一个演示或火花。此外,考虑到我们的潜在受众,我们认为数据可视化是最广泛接受的形式。

反思我的经验——当数据项目的范围不明确时,首先确定以下任何方面都是有帮助的:问题、数据源和分析类别。然后,评估可访问性并相应地调整计划将是一个迭代过程。

首先,一个好的数据项目始于一个好的问题,尤其是工作中出现的问题。确定一个明确的“问题所有者”效果最好,或者至少了解你的听众和他们关心的话题。第二,如果团队中有人熟悉可用的数据源,这将节省搜索时间,并帮助您快速评估您的提议的可行性。第三,我们应该认识到问题属于哪一类分析——描述性的、诊断性的、预测性的还是规定性的。这四个类别分别回答了以下问题:过去发生了什么,为什么会发生,未来可能会发生什么,以及应该采取什么行动来影响结果。问题的本质已经在很大程度上决定了要采取的方法和可交付成果的形式。

有时,问题没有明确定义,因为客户或利益相关者可能没有特定的问题,他们可能不知道数据分析可以帮助什么。在这种情况下,项目可以从理解上下文、目标和现有项目开始。需要深入的交流来激发灵感并制定可行的建议。

反思# 2——如何有效且高效地搜索开放数据?

Nathana rebou asUnsplash 上拍摄

当输入“新冠肺炎开放数据”时,人们可能会感到兴奋,然后被数据来源的数量所淹没。它不像学术出版,学术出版已经是一个非常成熟的过程,因此发表的论文是有据可查的,可以很容易地搜索到。到目前为止,数据发布仍然非常分散,没有被广泛接受的标准。开放的数据源分散在互联网上,你必须找到它们并逐例理解它们。我真诚地希望会有好的做法出现,这样我们就可以少受一些通过“煮海”来寻找数据的痛苦。

以下是高效搜索开放数据的五个技巧。

  • 有针对性的关键词搜索——使用有针对性的关键词来获取满足您需求的资源,而不是泛泛而谈。比如“新冠肺炎数据”+话题+其他说明。
  • 收集库 —当你没有一个明确的目标时,寻找一个库或数据门户,在那里你将立即接触到丰富的来源。挑战在于如何在众多选择中找到适合您项目的源代码。一些例子包括#数据 4 提供 19我们数据中的世界AMiner 等。
  • 链接和引用 —你也可以通过追踪参考文献找到好的数据来源。通常,图表、分析博客和论文的作者都会引用数据来源。一些数据所有者也在他们的网站上推荐其他好的数据源。
  • 相关机构 —如果你具体知道你想要什么数据,谁可能是它的第一手采集者,你可以直接去他们的网站上找。主要的提供者类型包括政府、非政府组织、私营部门公司和学术机构。了解他们通常提供什么类型的数据会很有帮助,如果你考虑他们的数据来自哪里,这是非常直观的。
  • 社交网络——我没想到这会有所帮助,直到我们在那里找到了一些好的资源。然后我意识到,这些数据所有者也需要一个渠道来宣传他们的数据,以获得更好的影响,特别是那些来自私营部门公司的“数据换好”项目,来自学术机构的项目,以及致力于促进开放数据使用的非政府组织。一旦你关注了这些机构或代表,就很容易获得新的、创新的数据来源的更新,以及基于它们的好项目。

反思# 3——如何进行差异化分析?

照片由斯科特·格雷厄姆Unsplash 上拍摄

新冠肺炎是一场全球性危机,国际社会正在共同努力抗击整个疫情。为了防止重复工作,检查已经做了什么和还需要做什么是很重要的。这里有一些方面你可以从它们开始。

1。组合不同的数据源。

数据发布者通常为他们的数据提供简单的可视化或报告,但很少将他们自己的数据与其他数据源相关联。如果你能发现不同数据源之间的关联,很可能你会发现别人以前没有想到的角度。

2。不同粒度级别的下钻或上钻。

基于分析的上下文,可能有不同的粒度级别被证明是合适的。例如,在我们的项目中,在国家一级查看菲律宾的流动性指数是不太合适的,因为菲律宾在次区域、省和城市一级执行其隔离政策是不同的。

3。缩小范围进行有意义的比较。

许多数据源非常全面,这为不同的分析目的提供了灵活性。事实上,没有必要使用所有可用的数据。相反,缩小范围可以清除噪音,使模式变得明显。基于深思熟虑的判断进行有意义的比较是很重要的。

4。介绍背景信息和跨学科领域知识。

这是我从我们的项目中学到的最重要的一课。数据信息量很大,但也有局限性。有些见解只有通过深入理解上下文和领域知识才能获得。它们是提示和线索,有助于组织你对数据的探索并理解结果。例如,在我们的项目中,如果不了解菲律宾的隔离政策,我们永远无法解释流动趋势。进行可靠的分析依赖于严格的定量评估和深刻的定性判断。

感谢您的阅读!我们希望这个博客能够让人们学习我们利用开放数据的经验,并鼓励更多的人加入社区,致力于数据对社会的影响。可以在这里 找到之前关于项目 的博客,在这里 找到 tableau dashboard

我的系统设计面试清单

原文:https://towardsdatascience.com/my-system-design-interview-checklist-86b64b5ac5e2?source=collection_archive---------14-----------------------

系统设计面试必备知识

图像通过 Unsplash

可怕的系统设计面试。我记得我被问到的第一个系统设计问题。“设计 WhatsApp”,他说。我不知道从哪里开始!我是新生。我只知道数据结构和算法。我相信你能猜到面试进行得如何。然后经过充分的研究,我给自己做了一个各种组件的清单,来引导我通过下一次系统设计面试!

所以我就不闲聊了,直接进入正题吧!

用户界面

首先,用户如何与你的系统交互?是通过手机应用程序,还是通过笔记本电脑或智能电视?这给了我们一个我们正在处理的限制和隐藏需求的指示。例如,在移动用户的情况下,我们可能必须处理波动的网络,对于智能电视和笔记本电脑用户,我们可能必须支持不同的文件格式和不同的分辨率和纵横比。

负载*衡器

没有负载*衡器,就无法设计分布式系统。负载*衡是指在分布式系统的各个节点之间分配请求,以减少响应时间和提高资源利用率。通过在各个节点之间分配负载,我们排除了出现单点故障的可能性,并且还确保了在另一个服务器空闲时,单个节点不会过载。

Web 套接字

或者更具体地说 web socket 处理器web socket 管理器。我知道,这些不是标准条款。但这是我最*在 youtube 视频上看到的,完全有道理。一个 Web Socket 处理器基本上是一个服务器,它与所有活动的用户设备保持开放的 Web Socket 连接。来自用户的任何请求都将通过 web 套接字处理程序进入系统,对用户的任何通知或响应也将通过 web 套接字处理程序发送。现在,如果我们正在开发一个大规模的应用程序,用户分布在不同的位置,我们将需要分布在不同地理位置的 web 套接字处理程序。认为低延迟。现在,用户也可以在各种 web 套接字处理程序之间切换,原因是网络波动,或者仅仅是因为他们现在在物理上更接*另一个 web 套接字处理程序。在这种情况下,我们需要一个中央存储库来跟踪哪个用户连接到哪个 web 套接字处理程序。这是由网络套接字管理器完成的。

数据库ˌ资料库

不仅仅是数据库,还有一般的存储解决方案。如果我们需要保存图像或文件,我们将需要像亚马逊 blob 存储,如果我们存储支付记录,我们需要它遵循 ACID 属性,在这种情况下需要一个关系数据库。如果我们在 Amazon 这样的*台上存储产品相关的信息,我们可能需要一个像 Mongo DB 这样的文档数据库。如果我们正在构建 Twitter 或脸书,没有像 Redis 这样的缓存解决方案,我们就无法设计我们的系统。在决定使用哪种存储解决方案时,我们需要考虑很多事情!这是我在准备->CodeKarle 的系统设计访谈中遇到的最好的文章之一。

加拿大

同样,如果我们的用户分布在不同的地理位置,那么将频繁访问的数据的副本保存在离用户位置更*的数据中心是有意义的。例如,网飞上“恐怖游戏”的大量流量可能来自印度。因此,将数据保存在靠*印度的数据中心以减少延迟并改善用户体验是有意义的。下面是 Akamai 的一个短片,简要解释了 CDN 到底做什么-> 什么是 CDN

分析组件

记住,无论你正在创建什么样的系统,总有分析的空间。这是那些在需求收集过程中从来不会被提出,但是总是被要求的事情之一。这就是我们使用 Kafka 这样的流处理软件的时候。无论系统中发生了什么,用户登录或退出,挂断电话,取消订单,取消付款,任何事情!对我们来说都是有用的信息!每当有事件发生,都要写给卡夫卡。在 Kafka 上,我们可以运行一些简单的 spark 流作业进行实时处理。或者我们可以简单地将数据转储到 Hadoop 集群中,然后运行一些复杂的机器学习算法进行详细的分析。

可插拔组件

如果我们正在设计 Twitter,帖子长度是我们需要处理的限制之一。但是如果用户想要分享一个链接呢?那会占据一半的职位!这就是为什么我们需要一个 URL 缩短服务。无论您构建什么系统,总会有这样或那样的事情需要通知用户。这就是你可能需要一个通知服务的地方。通知服务实际上是理解可插拔性需求的一个好方法。如果按照我们的要求,如果一个朋友喜欢脸书上的个人资料图片,我们需要发送应用内通知。所以我们把它建立在我们的系统中。现在出现了一个新的要求,向超过 3 天没有访问应用程序的用户发送电子邮件通知。我们无法添加另一项服务来处理电子邮件通知。这就是我们的通知服务需要可插拔的原因,这样我们就可以随时添加处理程序,并轻松支持新的通知方法。

另一个作为独立组件使用的独立服务的例子是资产交付服务。如果您正在构建类似网飞的东西,我们需要一个系统来根据传入流量将视频内容加载到 cdn,管理需要发送给哪个用户的分辨率和宽高比数据,负责将主文件转码为所有其他支持的文件格式,等等。我将附上我提到的一个视频的链接,以了解资产交付系统可能如何工作。

监控和警报

你达到里程碑了吗?满足截止日期?您的系统是否按预期工作?无论是什么应用程序,无论计划或设计得多好,总有出错的可能。第三方依赖可能会崩溃,服务器可能会停机,可能一台服务器的 CPU 利用率非常高,而另一台服务器未得到充分利用,可能系统在黑色星期五销售期间无法进行足够的扩展!事先知道这些事情不是很好吗?

但是怎么做呢?当然是通过监控你的系统!和警报。任何表现出乎意料或达到极限的事情,都必须在失控之前被大声指出。这是另一个在构建系统时,最初没有被提到但非常重要的事情。这里的是一个你如何做到这一点的例子。

印象分

一旦你想出了一个满足需求收集阶段所有要求的解决方案,那就是你从其他申请者中脱颖而出的时候了。这是当你考虑人们在面试中通常不会考虑的边缘情况时。比如谷歌如何在谷歌地图中处理像印巴中边界这样的争议地区?或者你可以展示如何扩展你的解决方案来支持比预期大得多的规模。比如你的视频会议系统可以扩展到现场直播吗?

你可能想看的资源

什么是负载均衡器?->https://medium . com/@ itIsMadhavan/what-is-load-balancer-and-how-it-works-f 7796 a 230034

如何在系统设计面试中选择最佳存储解决方案?->https://www . codekarle . com/system-design/Database-system-design . html

CDN 到底是什么?——>https://youtu.be/l6X_IxyGHHU

如何用 Redis 扩展你的系统->https://youtu.be/CtV-QymAeIc

资产交付系统如何工作(以网飞为例)——>https://youtu.be/lYoSd2WCJTo

下面是我写的另一篇关于为系统设计面试选择最佳 DB 的中型文章->https://towardsdatascience . com/choosing-the-right-database-in-a-a-system-design-interview-b 8 af 9 c 6 DC 525?source = friends _ link&sk = d 78 ef 7 e 0 b 0 f 4071636 c 57681 b 9 FCE 1c 8

破解下一个系统设计的综合指南采访由 CodeKarle->https://www.codekarle.com/】

**系统设计面试常见问题->https://www.youtube.com/watch?v=EpASu_1dUdE&list = plhgw 50 vuymyckxl 3d 1 lxo VL 94 wknjfuc

我希望这能帮助你想出一个你自己的清单,在你下一次系统设计面试时参考。觉得我错过了重要的一步?请在评论中告诉我!

我最喜欢的 3 种机器学习算法

原文:https://towardsdatascience.com/my-top-3-machine-learning-algorithms-7eaa19d9bb36?source=collection_archive---------44-----------------------

意见

数据科学家现在和 2021 年最喜欢的算法

戴维·冯迪马尔在Unsplash【1】上拍摄的照片。

目录

  1. 介绍
  2. 随机森林
  3. XGBoost
  4. CatBoost
  5. 摘要
  6. 参考

介绍

随着 2021 年的到来,我想讨论一下我最喜欢的三种机器学习算法的更新列表以及原因。在过去的一年里,我在业余时间通过自己研究和使用不同的算法获得了更多的专业经验和实践经验。新的用例、Kaggle 示例、视频和其他文章让我关注我最喜欢的三种算法,包括 Random Forest、XGBoost 和 CatBoost。这三者都有好处,你当然可以用这三者产生令人印象深刻的结果。虽然一个是老的和可靠的,另一个是强大的和有竞争力的,最后一个是新的和令人印象深刻的,这三个算法在我的列表中名列前茅,看看哪三个在你的列表中名列前茅将是有趣的。如果你想了解这三种著名的机器学习算法的更多信息,请继续阅读下面的内容。

随机森林

Sebastian UnrauUnsplash【2】上拍摄的照片。

一种经过检验的真正的机器学习算法是随机森林【3】算法。它已被证明在各种情况和用例中表现良好。这个库的一个独特的好处是,因为它比较老,所以它比 XGBoost 和 CatBoost 拥有更多的文档和更多的例子。随机森林工作的一般方法是在子样本上拟合一些决策树,然后对它们进行*均。这有助于提高精度和防止过度拟合。当我第一次调查我的数据,执行特征工程,并希望有一个总体的准确性时,我倾向于使用这种算法。即使您使用随机森林作为最终数据科学模型的一部分,您仍然会看到一些令人印象深刻的结果,并且 XGBoost 或 CatBoost 实现可能没有必要。当然,您可以随时对所有三种算法进行测试,以查看哪种算法最适合您、您的数据和您的用例。

我特别喜欢用随机森林做分类问题,也叫监督学习。这种类型的学习是当你的数据上有标签。标签的一个例子是商店或电子商务*台的特定类型的服装(,例如,裤子、t 恤、毛衣)。你可以使用特征(袖长、可能的尺寸、颜色等。)描述服装,最终对新装进行训练和分类。在预测时,很容易使用predict_proba函数,该函数很容易显示某事物对其分类的可能性。

以下是随机森林的一些好处:

  • 通用(回归和分类)
  • 处理不*衡的数据
  • 适用于异常值
  • 并行处理(n_jobs = -1)
  • 易于使用
  • 学习、练习和理解算法的几种方法

总的来说,随机森林是数据科学和机器学习过程的一个很好的起点,也可能是一个很好的终点。但是,下面可能会有其他某些算法对于其他某些情况更好,或者出于其他原因(基于你的限制)。

XGBoost

罗马法师Unsplash【4】上拍摄的照片。

卡格尔赢家。

我不会深究这个问题,因为它比下一个算法讨论得更广泛。

XG boost【5】经常被用在比赛中,在这些比赛中,最微小的精确度都是至关重要的。然而,这种强大的机器学习算法也可以在学校,在你的时间练习,或在工作中使用。这是一个梯度增强库,已被证明是非常准确和快速的。XGBoost 可能比 Random Forest 需要更长的时间,但是在我所看到的情况下,它在大多数时候都更准确。

以下是 XGBoost 的一些优点:

  • 正规化
  • 缺失值处理
  • 交叉验证
  • 并行处理
  • 质量很好
  • 特征重要性

CatBoost

照片由迪米特里·科艾曼斯在Unsplash【6】上拍摄

CatBoost 机器学习算法是由Yandex【7】创建的,它在决策树上使用梯度推进。该算法是最新的算法之一,如果不是最新的算法的话。它强大、健壮、准确,总体来说令人印象深刻。组成这个算法的主要类包括分类器和回归器,分别是CatBoostClassiferCatBoostRegreessor。当然,CatBoost 的主要区别在于它强调分类变量的重要性。它使用一种目标编码的形式,其他包或算法也包括这种形式;然而,这种特定类型的目标编码要健壮得多。使用这种转换的好处是不仅可以加快训练和预测数据所需的时间,还可以获得更准确和有益的值。例如,使用 CatBoost,您不需要采用一次热编码,也不需要担心数百个稀疏列,而是可以专注于一个编码特性,该特性也可以防止目标泄漏。

我发现对 CatBoost 有用的两个主要特性重要性类型是PredictionValuesChangeLossFunctionChange类型。对于排名指标,您需要坚持使用 LossFunctionChange 方法。您还可以使用非常流行且易于使用的 SHAP 库来直观地解释特性的重要性。

以下是 CatBoost 的优势:

  1. 更快的计算
  2. 快速预测
  3. 防止过度拟合
  4. 防止目标泄漏
  5. 最适用于分类特征
  6. 提高培训质量
  7. 减少参数调整的时间
  8. 更多关于可解释性的时间
  9. 不同类型的特征重要性
  10. 也利用 SHAP 价值观
  11. 嵌入了大量有益且令人印象深刻的情节

CatBoost 本身讨论的主要特性是无需参数调整的高质量、分类特性支持、快速和可扩展的 GPU 版本、提高的准确性和快速预测。他们还提到了它在搜索、推荐系统、天气预报等方面的广泛应用。到目前为止,我真的相信这个机器学习算法是最好的。看看一年或几年后会出现什么来与强大而准确的机器学习算法 CatBoost 竞争,这将是一件有趣的事情。

摘要

总的来说,有几个机器学习算法提供了很大的好处。它们都比较容易实现,同时还能产生有竞争力和高质量的结果。我知道这些算法中的一些可能对你来说并不陌生,所以我希望我还是增加了对至少一种算法的认识。虽然 Random Forest 是最老的,但 XGBoost 一直在主导 Kaggle 竞争,我相信 CatBoost 是最好的——对于分类数据科学用例来说。

以下是我现在和 2021 年最喜欢的三种机器学习算法:

*Random ForestXGBoostCatBoost*

我希望你觉得这篇文章既有用又有趣,请随时讨论你使用的机器学习算法。哪些是你最喜欢的?你同意还是不同意我的观点?为什么或为什么不?

感谢您的阅读!

请随意查看我在'The Top 5 Machine Learning Algorthims ' [8]中的另一篇文章,这篇文章深入探讨了这些算法中的两个以及其他三个算法的用例:

*

参考

[1]照片由 David von DiemarUnsplash(2019)上拍摄

2Sebastian Unrau 在 Unsplash 上拍摄的照片,(2015)

[3] scikit-learn 开发者,随机森林,(2007-2020)

4罗马法师在 Unsplash 上拍摄的照片

[5] xgboost 开发商, XGBoost ,(2020)

6Dimitry Kooijmans 在 Unsplash 上拍摄的照片,(2017)

[7] Yandex, CatBoost ,(2021)

[8 ] M.Przybyla,五大机器学习算法,(2020)*

我的四大 GeoPandas 功能:一个实用的故事

原文:https://towardsdatascience.com/my-top-4-geopandas-functions-a-practical-story-ed375b76c686?source=collection_archive---------21-----------------------

六月在 Unsplash 拍摄的

在过去的几个月里,我一直在研究 GeoPandas,它很快成为我最喜欢的 Python 包之一。就个人而言,我对数据科学如何应用于城市规划、地理空间信息和技术等领域很感兴趣。对于这些,GeoPandas 特别有用,因为它允许用户操作地理数据并从中提取有价值的信息。在这个故事中,我将根据我的学习经验,用一个实际的例子向您展示我在 GeoPandas 中的 4 个顶级函数。

1.获取可用数据集

首先,如果您刚刚开始使用 GeoPandas,您将需要一些易于访问的数据集。这可以通过使用“.“可用”功能如下:

这会产生以下结果,每个结果都是一个数据集:

2.来自 xy 的点

如果您发现自己正在处理地理空间数据,它可能并不总是适合您立即开始处理的格式。一个这样的例子是当您的数据包含在纬度和经度列中,并且您需要它们在点几何中。幸运的是,GeoPandas 提供了一个函数来快速将这些数据转换为点格式。这个函数叫做“points_from_xy”。让我们来看看它的实际应用:

使用城市的数据集,让我们分解 x 和 y 坐标中的点几何列,然后将它们作为列添加到数据框中:

这是新的数据框架:

现在,我们可以使用“points_from_xy”函数将纬度和经度转换回点几何:

结果如下:

3.制作地图

使用地理空间数据的很大一部分是能够在地图中有效地可视化它们。GeoPandas 允许对用户表示地图数据的方式进行大量细化,包括添加不同的地图图层和处理缺失数据。在这一部分,我们来看看如何制作一个多层地图。首先,我们需要创建一个基础层。假设我们将着眼于仅位于南半球的城市。让我们过滤掉这些数据,然后使用 geopandas.plot 绘制它:

现在,让我们用一张世界地图覆盖这些城市,该地图在 GeoPandas 可用数据集中提供。我们将调整国家边界的颜色,这些国家的填充,以及城市点的颜色和大小:

现在,我们有了一张分层地图,可以看到世界南部的一些城市和国家的边界。

4.计算面积

对于第四个也是最后一个函数,我选择了“area”函数。这个函数顾名思义就是计算多边形和多重多边形等形状的面积。这在处理几何数据时非常有用,我们将在下面看到。

对于这个例子,让我们使用“nybb”数据集,它包含关于纽约行政区的信息。如下图所示,数据框包括代表纽约每个区域形状的多重多边形:

从这里开始,计算每个多边形的面积非常简单:

以下是输出:

让我们使用此结果,并使用 GeoPandas 绘图功能绘制行政区,使用图例按区域对其进行着色:

现在,我们已经完成了 4 个函数,我希望您也受到启发,开始使用 GeoPandas 并进一步探索它。感谢您的阅读,如有任何问题,请联系我!

我的顶级数据科学读物和资源,2021 年 6 月版。

原文:https://towardsdatascience.com/my-top-data-science-reads-resources-june-2021-edition-2c2f3a1e7643?source=collection_archive---------22-----------------------

SQL 技巧,世界级的实验,等等。

照片由 Scott GoodwillUnsplash 上拍摄

你好!欢迎来到我这个月遇到的第一个月度顶级数据科学资源展览。我想在做一些像时事通讯一样的事情,但不要太激烈,要能产生直接价值的。

每个月,我都会与您分享我遇到的一些最佳读物,并按主题/话题对它们进行分组—本月,我想与您分享一些关于 SQL 技巧和提示的文章、世界级的实验*台以及一个免费资源,其中包含超过 15 个关于各种统计话题的研究生课程。

也就是说,我希望你喜欢,如果这是你有兴趣每月关注的事情,请留下评论!

SQL 技巧和提示

SQL 中更危险的微妙连接

https://alexpetralia.com/posts/2017/7/19/more-dangerous-subtleties-of-joins-in-sql

无论你是初学者还是专家,我都强烈建议你读一下这篇文章。本文讨论了 SQL 连接中一个微小但深刻的细微差别,实际上直到去年我才意识到这一点。如果你没有意识到这个微妙之处,这个小错误会给你的公司带来巨大的成本和影响。

我不想完全破坏这篇文章,但是对于 SQL 连接如何工作有一个常见的误解—例如,许多人认为左连接将在左表中返回相同数量的行。事实并非如此。左连接给了至少和左表一样多的行。

BigQuery:数据分片与数据分区

https://mark-mccracken.medium.com/bigquery-date-sharding-vs-date-partitioning-cee3754f7900

如果您是数据分析师、数据科学家、数据工程师、数据架构师,或者基本上是任何编写数据管道和创建表视图的人,那么接下来的两篇文章是非常有价值的。

分片分区是两个概念,它们将帮助您编写查询并创建更具可伸缩性和效率的表——这意味着运行查询的时间更少,每次查询的费用更少!

学习如何创建分片/分区表将使您与众不同,因此我强烈建议您阅读一下这篇文章。

BigQuery 分区&聚类

https://medium.com/analytics-vidhya/bigquery-partitioning-clustering-9f84fc201e61

类似地,还有另一个叫做集群的概念,它的作用类似于分区。如果你觉得上一篇文章很有价值,强烈建议你也读一读这篇文章。

世界级的实验*台

随着我职业生涯的深入,我越来越意识到实验的重要性。实验远远超出了假设检验和 A/B 检验背后的理论。下面的两篇文章展示了所有公司在进行实验时都应该努力争取的理想结果。

Airbnb 的实验

https://medium.com/airbnb-engineering/experiments-at-airbnb-e2db3abf39e7 [## Airbnb 的实验

medium.com](https://medium.com/airbnb-engineering/experiments-at-airbnb-e2db3abf39e7)

这篇文章很好地介绍了实验。它不太关注 Airbnb 已经建立的*台,而是更关注 Airbnb 在其一生中积累的经验和教训。

我喜欢这篇文章的原因是,它向您展示了在进行实验时,您必须了解和考虑的所有细微差别和复杂性。

优步实验*台的引擎盖下

https://eng.uber.com/xp/

这篇文章有如此多的有价值的信息,我不能相信它是免费的,可以让其他人看到。优步在这篇文章中谈到了几件事:

  • 它们涵盖了他们日常使用的所有实验方法
  • 他们简要介绍了他们的统计引擎和实验*台
  • 它们还涵盖了他们在进行实验时需要注意的几个条件和因素。

超过 15 门免费的统计学研究生课程

https://online.stat.psu.edu/statprogram/graduate-programs

人人都爱免费课程。

这是一个拥有超过 15 门免费统计学研究生课程的网站。

这是我在学习过程中利用的一个很好的资源,我想把这个留给你们,以防你们觉得有必要学习更多的统计学。

以下是他们提供的一些课程:

  • 方差分析和实验设计
  • 应用数据挖掘和统计学习
  • 应用时间序列分析
  • 抽样理论和方法
  • 还有更多…

感谢阅读!

我希望你喜欢这个精选的阅读和资源列表!如果你喜欢这个,请给这个一些掌声,并留下评论,你希望在未来几个月看到什么主题!

一如既往,我祝你学习一切顺利。

不确定接下来要读什么?我为你挑选了另一篇文章:

又一个!

</10-statistical-concepts-you-should-know-for-data-science-interviews-373f417e7d11>

特伦斯·申

  • 如果你喜欢这个, 跟我上媒 了解更多
  • 有兴趣合作吗?让我们连线上LinkedIn

我的 TubeStats 应用程序(英尺。阿里·阿卜杜勒)

原文:https://towardsdatascience.com/my-tubestats-app-ft-ali-abdaal-48dfc982c7ed?source=collection_archive---------44-----------------------

在 YouTube 频道中寻找一致性

照片由绍博·维克多Unsplash 上拍摄

拥有超过 1 亿的浏览量和 100 万的订阅者,Ali Abdaal 绝对是一个建议建立一个成功的 YouTube 频道的人。除了给有抱负的 YouTuber 今天就开始的建议之外,他还鼓吹一致性。

这就是这个应用程序的动机所在。问题是:阿里·阿布达尔的 YouTube 频道有多稳定?那其他 YouTube 频道呢?

我们将看到使用 TubeStats 来回答这个问题。我们还将介绍它是如何工作的。我还会提供我的个人倾向以及我未来的计划。

app 链接:https://www . tubestats . app

github:https://www.github.com/shivans93/tubestats

作者的动画 gif

TubeStats 做什么?

该应用程序接受用户输入。这可以是:

  • 频道 ID(例如UCoOae5nYA7VqaXzerajD0lg),
  • 链接到通道(如[https://www.youtube.com/channel/UCoOae5nYA7VqaXzerajD0lg](https://www.youtube.com/channel/UCoOae5nYA7VqaXzerajD0lg,)
  • 链接到感兴趣频道的视频(如https://www.youtube.com/watch?v=epF2SYpWtos,或
  • 视频 ID(例如epF2SYpWtos)。

几分钟后,它将生成该频道的汇总统计数据。示例包括总视频计数和总观看时间,如下所示。

作者图片

这里,我们还有渠道头像图像以及渠道上提供的描述。

接下来,我们有一个图表,总结了频道中的所有视频。

作者图片

该图涉及发布时间对查看次数的自然对数。y 轴有对数刻度,因为数据偏向尾部。这是由于视频的“病毒”性质。如果我们使用线性访问,那么大多数视频将在底部附*,只有少数在顶部附*。

圆圈的颜色代表视频的喜欢-不喜欢比率。圆圈的大小与其绝对视图数有关。

日期范围可以更改。在这个例子中,我改变了日期范围,因为 Ali Abdaal 在 2017 年 7 月开始更加认真地对待他的渠道。

另一个图表显示了视频之间的天数。例如,在上面选择的日期中,“我最喜欢的 iPad Pro 应用程序”视频的最长不活动时间不到 22 天。从视频的日期来看,这是在节日期间。

作者图片

*均来说,Ali Abdaal 能够每 3 天发布一个视频,其中大多数(75%)在 5 天内发布。

最后,TubeStats 提供了一个在频道中观看次数最多的视频列表,以及喜欢/不喜欢比率最低的视频列表。

TubeStats 是如何工作的?

主要工作部件:

  1. YouTube 数据 API
  2. pandas
  3. streamlit
  4. 赫罗库

我还把这分成了几个障碍,并提供了克服它们的解决方案。

障碍#1:我如何设置我的开发环境?

我用的是 Linux。建立我们的开发环境对于我们编码的生产力是必不可少的。

我们从创建目录开始。接下来,我们创建一个虚拟环境来管理我们的包,而不会干扰其他项目。最后,我们初始化 git 来跟踪变化,并允许与世界共享我们的代码。

$ mkdir tubestats
$ cd tubestats$ python3 -m venv venv
$ source venv/bin/activate
$ (venv)$ git init

障碍 2:我们如何访问视频信息?

我们可以为了观看次数、评论次数等而放弃每一个视频。这需要很长时间。幸运的是,我们可以使用 YouTube 数据 API 。这提供了对 YouTube 视频和频道的统计数据的简单访问。要访问这个,我们必须设置我们的谷歌云控制台*台

由此,我们创建了一个“新项目”。我们激活 YouTube 数据 API v3 应用程序。最后,我们创建凭证(单击此处了解更多信息)。这些步骤将提供访问 YouTube 数据 API 的关键。

障碍 3:我们如何存储密码和 API 密匙?

我们想分享我们的代码,但不是我们的密码和 API 密匙。我们如何做到这一点?

我们可以用一个第三方包: [python-dotenv](https://pypi.org/project/python-dotenv/)

这很重要,这样我们就可以在本地访问数据。我们将会看到,当我们使用 Heroku 推进网络服务时,我们必须使用不同的方法。

我们可以将密钥存储在一个.env文件中,并且我们可以将这个文件添加到.gitignore中,这样它就不会被共享。

.env file
 APIKey=xxxAPIKEYherexxx

我们安装了允许访问 YouTube API 的模块。我们在激活虚拟环境的同时,使用 pip 来实现这一点。

$ (venv) pip install google-api-python-client

障碍 4:我们如何获得视频统计数据?

如果我们有一个频道 ID,我们可以用它来获得一个播放列表,其中包含从该频道上传的所有视频的 ID。然后我们可以调用视频 ID,然后获得我们感兴趣的统计数据。

def get_video_data(self) -> pd.core.frame.DataFrame: ... while True:                     
            # obtaining video ID + titles                       
            playlist_request = self.youtube.playlistItems().list(                    
                    part='snippet,contentDetails',                 
                    maxResults=50, # API Limit is 50                  
                    pageToken=next_page_token,                    
                    playlistId=upload_playlist_ID,                
                    )                 
            playlist_response = playlist_request.
            # isolating video ID
            vid_subset = [ vid_ID['contentDetails']['videoId'] for vid_ID in playlist_response['items']
            # retrieving video ID
            vid_info_subset_request = self.youtube.videos().
                part='snippet,contentDetails,
                id=vid_subset
                )       

            vid_info_subset_response = vid_info_subset_request.    
            video_response.append(    
            # obtaining page     
            next_page_token = playlist_response.get('nextPageToken') 
            # get method used because token may not exist
            if next_page_token is 
                break
        df = pd.json_normalize(video_response, 'items')       
        return df

这里我们调用 API,但是一次只能获得 50 个视频 id。这要归功于分页。每次调用时,如果超过 50 个视频,则提供一个页面令牌。页面标记指向下一页。如果页面令牌是返回None,这意味着所有的 id 已经用尽。我们使用 while 循环来获取视频 id。一旦我们不再有页面标记,while 循环就会停止。

我们将这个输出附加到一个 python 列表中,这是一个 JSON 格式的字符串列表。我们将这些信息存储在一个pandas DataFrame中。我们能够做到这一点要感谢一个内置函数json_normalize()。由此,我们有了数据框架。

障碍 5:如何组织代码?

既然我们的代码已经开始腾飞,将所有这些代码放入一个文件变得越来越困难。这是我们为组织使用不同文件和目录的地方。

├── data
 │   ├── channel_data.pkl
 │   └── video_data.pkl
 ├── LICENSE
 ├── Procfile
 ├── README.MD
 ├── requirements.txt
 ├── setup.sh
 ├── tests
 │   ├── **__init__**.py
 │   ├── test_settings.py
 │   ├── test_youtube_api.py
 │   ├── test_youtube_data.py
 │   └── test_youtube_parser.py
 ├── tubestats
 │   ├── __init__.py
 │   ├── youtube_api.py
 │   ├── youtube_data.py
 │   └── youtube_parser.py
 └── youtube_presenter.py

需要注意的主要子目录是tubestats,它包含访问 API 的 python 源代码,处理数据,并生成底层图形来呈现数据。tests包含用于测试tubestats模块的测试代码。

最后,youtube_presenter.py是呈现代码的东西。我们看到了一些其他的文件,我们将在后面处理。

障碍 6:如何测试代码?

确保我们的代码工作是很重要的。在这种情况下,我使用pytest。下面是测试上述get_video_data()功能的一个例子。

from tubestats.youtube_api import create_api, YouTubeAPI
 from tests.test_settings import set_channel_ID_test_case from pathlib import Path import pytest import googleapiclient
 import pandas def test_create_api():
     youtube = create_api()
     assert isinstance(youtube, googleapiclient.discovery.Resource) @pytest.fixture()
 def youtubeapi():
     channel_ID = set_channel_ID_test_case()
     yt = YouTubeAPI(channel_ID)
     return yt def test_get_video_data(youtubeapi):
     df = youtubeapi.get_video_data()
     assert isinstance(df, pandas.core.frame.DataFrame)

     # saving video data to save API calls for later test 
     BASE_DIR = Path(**file**).parent.parent
     df.to_pickle(BASE_DIR / 'data' / 'video_data.pkl')

在这种情况下,我们导入源代码,以及相关的模块。我们使用pytest.fixture()装饰器。这允许我们重用我们在测试用例中提取的数据的结果。我们“腌制”数据,这样我们就可以使用它,而不是为其他测试进行更多的 API 调用。

我可能比isinstance做得更好,但这也是必须的。

如果我们在终端中运行pytest,这将测试我们代码的功能。

障碍#7:如何显示这些数据以供他人交互?

这是通过altair的组合来完成的,它为我们提供了交互式的图形。此外,我们使用streamlit来显示这些图形并允许交互。

以下代码创建了一个图表,显示一段时间内的所有视频。

import altair as alt
 def scatter_all_videos(self, df: pd.core.frame.DataFrame) -> alt.vegalite.v4.Chart:
df_views = df
         c = alt.Chart(df_views, title='Plot of videos over time').mark_point().encode(
                 x=alt.X('snippet.publishedAt_REFORMATED:T', axis=alt.Axis(title='Date Published')),
                 y=alt.Y('statistics.viewCount_NLOG:Q', axis=alt.Axis(title='Natural Log of Views')),
                 color=alt.Color('statistics.like-dislike-ratio:Q', scale=alt.Scale(scheme='turbo'), legend=None),
                 tooltip=['snippet.title:N', 'statistics.viewCount:Q', 'statistics.like-dislike-ratio:Q'],
                 size=alt.Size('statistics.viewCount:Q', legend=None)
         )
         return c

接下来,我们可以显示这个图表,并能够编辑日期。

import streamlit as st def date_slider(date_end=datetime.today()):
         date_start, date_end = st.slider(
                 'Select date range to include:',
                 min_value=first_video_date, # first video
                 max_value=last_video_date, #value for date_end
                 value=(first_video_date , last_video_date), #same as min value
                 step=timedelta(days=2),
                 format='YYYY-MM-DD',
                 key=999)
         return date_start, date_end date_start, date_end = date_slider()
     transformed_df = youtuber_data.transform_dataframe(date_start=date_start, date_end=date_end) 
     c = youtuber_data.scatter_all_videos(transformed_df)
     st.altair_chart(c, use_container_width=True)

这是我们在本地运行程序时看到的,streamlit run youtube_presenter.py:

障碍 7:我如何炫耀?

坐在我们的电脑上没有任何意义。我们需要与世界分享这一点。Github 可以用来共享代码,但是我们当中的非技术人员呢?

解决办法是用 Heroku 来主持

首先,我们要做的是在 Heroku 上创建一个帐户。一个免费账户就够了。

我们已经确保代码工作,我们可以把它推到 GitHub 上。接下来,我们创建一个requirements.txtsetup.shProcfile

requirements.txt文件将包含外部库。我们可以使用命令:

$ (venv) pip freeze > requirements.txt

创建了setup.sh文件:

mkdir -p ~/.streamlit/echo "\\
[server]\\n\\
headless = true\\n\\
port = $PORT\\n\\
enableCORS = false\\n\\
\\n\\
" > ~/.streamlit/config.toml

然后Procfile告诉 Heroku 这是一个 web 应用程序。它还指示setup.py运行文件以及使用streamlit运行我们的代码。

web: sh setup.sh && streamlit run app.py

接下来,我们安装 Heroku 命令行接口。

然后,我们可以将代码推送到 Heroku,就像我们对 GitHub 库所做的那样。

$ heroku login
$ heroku create tubestats$ git push heroku main

这就是我们的最终产品。

我们还可以附加一个域来定制应用程序。

障碍 8:如果输入了一个视频 ID 怎么办?

到目前为止,这仅适用于通道 ID 输入。视频 ID 呢?一个网址?这是我们需要解析输入的地方。

我们结合使用正则表达式和检查长度。

例如,频道 ID 正好是 24 个字符长,视频 ID 是 11 个字符长。

如果提供了链接,我们可以使用正则表达式(regex,使用re模块)来提取视频 ID 或频道 ID。有很多网站可以帮助使用 regex。这里有一个。

下面是一个应用正则表达式的例子。

import reLINK_MATCH = r'(^.*youtu)(\\.be|be\\.com)(\\/watch\\?v\\=|\\/)([a-zA-Z0-9_-]+)(\\/)?([a-zA-Z0-9_-]+)?'
m = re.search(LINK_MATCH, for_parse)
video_id = m.group(4) # video ID
if video_id == 'channel':
    return m.group(6) # Channel ID
elif video_id == 'user':
    channel_username = m.group(6) # Channel Username

我从 TubeStats 中学到了什么?

从这个项目中可以学到很多东西。

项目可以帮助学习,让你保持兴趣。没有什么比提出问题并回答它更有帮助的了。这意味着你所有的研究和你学到的东西都是相关的,并且可能会坚持下去。

此外,达到“最低可行产品”也很重要。如果一个项目是压倒性的,把它分解成一个简单的层次,得到一些刚刚工作。然后,专注于使代码有性能,干净等等。

我将来能做什么?

错误。没有办法捕捉错误。将打印的是代码本身提供的错误。

更好的性能。可能有很多地方可以让代码运行得更好。不过,我可以稍后再谈这个。

结论

发布视频的一致性是 YouTube 频道成功的一个重要因素。这个应用程序就是这样测量的。或者至少尝试过。

该项目实现了 YouTube 数据 API 以及pandasstreamlit,并推送到 Heroku 进行托管。一个重要的教训是建立一个项目到一个最低限度可行的阶段。以后集中精力完善它。

我从这个项目中学到了很多,也有更多我可以做的。

参考

  1. 一个阿卜达尔,阿里阿卜达尔 (2021),https://aliabdaal.com/
  2. 谷歌, Youtube 数据 API (2021),https://developers.google.com/youtube/v3/
  3. 熊猫开发团队,熊猫文档 (2021),https://pandas.pydata.org/
  4. H Krekel,pytest-dev 团队, pytest:帮助您编写更好的程序— pytest 文档 (2021),https://docs.pytest.org/en/6.2.x/
  5. 牛郎星开发者,牛郎星:Python 中的声明式可视化——牛郎星 4.10 文档 (2021),https://altair-viz.github.io/
  6. 细流公司,细流公司 (2021),https://streamlit.io/
  7. 赫罗库,赫罗库 (2021),【https://www.heroku.com】T2
  8. 名词(noun 的缩写)Mashinchi,一个关于如何将你的 Streamlit 应用程序部署到 Heroku 的快速教程。 (2017),走向数据科学

我在大多数人都能使用的计算资源上的不公*优势

原文:https://towardsdatascience.com/my-unfair-advantage-in-computing-resources-that-are-accessible-to-most-people-5bb95932f247?source=collection_archive---------26-----------------------

如何将 Google Colab 推向极限

照片由帕特里克·福尔Unsplash 拍摄

我在参加研究生机器学习课程时,开始使用谷歌协作实验室(Colab),这是一个附带免费计算资源的 python 笔记本。

在最初的一两个月里,这是相当毁灭性的,因为相当比例的学生可以从他们的实验室或系里访问计算资源。试图通过免费 GPU 获得更高结果的学生看到并感受到了这种差异。

起初我也在其中,但幸运的是,有从前的学生传下来的提示和技巧,或在同龄人之间分享,大多数人都愿意帮助。我也开发了一些我自己的技术,为泳池做出了贡献。

最终 Colab 成了我手中越来越强大的工具,我也能过得去了。我甚至幸运地在我们的几个 Kaggle 比赛中连续几天名列第一。

知道你在做什么图形处理器

您可以通过运行!nvidia-smi来实现这一点。举个下面的例子,我正在用一辆特斯拉 K80。

跑步!尼维迪亚-斯米

在撰写本文时,Colab 提供了 4 种类型的 GPU,下面按照一般性能从高到低列出了它们。

  1. V100
  2. T4
  3. P100
  4. K80

GPU 会在每次会话时重新启动,并且通过单击左上角工具栏上的运行时>恢复出厂设置运行时来重新启动会话。

并非所有时段都生来*等

人们发现,获得更好的 GPU 和更长的运行时间的可能性并不固定。从我和我周围的人分享的经验来看,一些客户享受更长的会话,长达 3 到 9 个小时,而其他人在达到略高于 1 个小时后就停止了。

通过跨不同帐户的测试,我发现允许的运行时间与两个因素最相关。

1.哪个谷歌账号在用 Colab

查看了 20 多个谷歌账户和 100 多次运行,发现谷歌对每个账户使用该服务的时间有不同的标准。

我没有找到任何可靠的预测一个帐户的持久性。起初,人们很容易认为活跃了一段时间的账户比新创建的实体更持久,教育账户也比免费的谷歌账户更持久。令人惊讶是,这些假设没有一个被证明是正确的,我经常看到类似的客户资料以非常不同的方式处理。

基于它的不可预测性,我会说,最好的方法来找出一个帐户是否是好的,将得到你的手脏,只是测试自己。通过比较不同的账户,你应该能够决定哪个账户是你的深度学习项目的最佳选择。

2.客户多久使用一次 Colab

谷歌似乎也采用了一种“冷静”的政策:最*在 Colab 中使用较多的账户通常比最*被滥用的账户训练时间更长。

请注意,前一点仍然适用,每个帐户在冷却之前使用 GPU 的起始配额是不同的。一些帐户在最初的几次会议后就被禁止了,而其他人则喜欢默认分配到 T4 GPU,可以训练 8 或 9 个小时进行多次跑步。

简而言之,如果你在 Colab 上遇到了使用问题,考虑改变使用帐户,这可能会有所帮助。

用一点编码保存训练进度

在默认设置中,会话中发生的一切,包括训练参数或检查点,都只是临时存储在 colab 上,会话结束后就会消失。以下是一些防止悲剧发生的措施。

在 Google drive 上安装您的内容

在 Colab 的左侧,点击“文件”>“安装驱动器”,并按照说明将文件保存或加载到您的 google drive。

文件>安装驱动器

装载驱动器提示

使用%cd content/drive/MyDrive/the_name_of_folder在你的驱动器中移动目录。

完成后,会话期间创建的所有文件都将自动保存到帐户的 Google drive 中,并且不会在会话结束后立即消失。

客户对客户的培训

只需在 Colab 上登录不同的 Google 帐户,就可以持续不断地进行培训,但要安装在同一个帐户的 Google drive 上。

然而,这是假设你熟悉如何保存训练检查点,从我的角度来看,这对初学者来说并不容易。我建议从 Pytorch 的指南开始。

我最喜欢的订阅:Colab Pro

Colab 为更快的 GPU 和更长的运行时间提供每月 9.99 美元的订阅计划,这通常是一笔相当不错的交易,除非你遇到问题。

简而言之,您选择升级订阅的帐户对您将获得的体验至关重要。

我是吃了苦头才知道的。一听到这个计划,我立即掏出我的卡,骑了上去。令人发指的是,用了不到 1 个小时,我的会话就被切断了,连不上 GPU。

冷却一段时间后,我仍然可以使用它,但我在使用 1 小时左右后被切断。(与免费计划中的 3-9 小时相比)

另外,我甚至没有得到最好的图形处理器。虽然通常分配给 T4,但 Colab Pro 的默认分配是 P100。

话虽如此,我还是想训练我的神经网络。我决定用一个不同的帐户再次订阅 Pro,结果是体验好得多。在这个帐户下,我可以用以下好处进行训练。

使用 V100 加快训练速度

V100 很好。虽然很难量化有多好,但在我的一些 NLP 项目中,我可以看到它比 T4 快 10 倍。

快速不仅节省时间,有时还能发挥很大作用。有一次,我的最后期限是 23 小时,但通常需要 24 小时才能完成培训。我几乎要放弃了,但在最后的 10 个小时里,我上了 V100,按时完成了。

通宵训练

只有在使用正确的帐号登录 Pro 后,我才能在训练过程中睡足 8 个小时。

不稳定互联网下的训练

这也很难量化,但是当我的互联网被切断时,培训仍在继续,这在我的印象中与我们在免费计划中获得的不同。

打开多个会话

在免费版中,你一次只能训练一个笔记本,而在付费版中,你有时可以训练多达三个标签。这同样不适用于每个账户,在我看来,这增加了被 GPU 禁止的几率。因此,我通常做一两个标签,它工作得很好。

柯基和凯蒂

最后,Colab 附带了这个可爱的功能,除了让你保持愉快的心情工作更长时间之外,它什么也没做,我认为这是一个优势。你可以在设置>杂项中找到它,然后点击 Corgi 模式/Kitty 模式。

最后的话

Colab 让我的数据科学之旅变得有趣和可能,我希望你也会喜欢你的旅程。

中级会员资格使我有可能学到足够的知识,并为数据科学写作。用我的个人链接报名,然后在下面评论,我会给你发一个分享我全程的 pdf。

作为一名生物医学领域的学术研究者,我为开放和可复制科学的工作流程

原文:https://towardsdatascience.com/my-workflow-for-open-and-reproducible-science-as-an-academic-researcher-in-biomedicine-b41eaabcd420?source=collection_archive---------28-----------------------

夕阳下我们的实验室。

行业笔记

目标受众:完成一门或几门编程课程的硕士生或博士生。

这篇文章的目的是提供一个资源的概述,这些资源可以用来使生物医学科学和数据分析更具可重复性,我个人认为是有用的。它并不意味着全面或解释太多细节。如果你有问题或补充,请在评论中留下。

到目前为止,我在博士期间做得最好的一件事是在我刚刚起步的时候学习编程。它节省了我无数的时间,并帮助我在更深的层次上理解科学。我在 2018 年初写了这个,在我关于编程和生物信息学的速成课程中。现在,三年多过去了,是时候更新一下我作为一名学术研究者如何在日常工作中整合编码和生物信息学了。

首先,我认为很重要的一点是,无论如何,我仍然不是一名高级程序员——我最多认为自己是一名中上程序员。我花了整整两年时间才明白编程是实现目标的一种手段,而不是目标本身。换句话说,从“我希望能够使用 R 和 Python”到“我希望能够使用 R 和 Python 从我的数据中获得有意义的见解”,用了 2 年时间。在那之后,它再次花费了大量的时间来发展到“我希望能够使用 R 和 Python 从我的数据中获得有意义的见解,这样其他人就可以完全复制我是如何获得这些见解的”。

我说 R 和 Python 是因为这是我最常用的两种语言。我使用 Python 编写必须在计算集群/HPC 上运行的脚本。然后,我将 Python 的输出下载到我的计算机上,并使用 R 进行下一部分的数据分析(可视化、注释),其中交互性(例如,改变图形的外观)更重要。

虽然学习额外的编程语言既有趣又有挑战性,但一天也就那么几个小时。最后,你必须自己决定你想把时间投入到什么事情上。我个人有一瞬间想尝试 Java 或者 Julia 语言。我感觉自己处于 R 和 Python 的*台期:停滞不前,因为我没有开始时提高得那么快,学习一门新语言会有所帮助。但是在对了解 Julia 和 Java 可能带来的好处进行批判性评估之后,我不确定这是否会提高我的生产率。相反,我专注于提高我已经掌握的技能,而不是学习新的东西。

开放和可复制的科学

不可复制的科学更像科幻小说而不是科学。通常这种缺乏再现性并不是因为不良意图,而是因为固有的难以再现的不良实践。通过在 Excel 表中单击来清理数据。或者改变表中的值,几周或几个月后忘记为什么这些变量被改变了。认为完美的再现性存在是天真的,但是通过一些工具你可以非常接*。伴随着可再现性,通常会有一个代价,那就是需要更多的时间来配置所有的东西,但是从长远来看,这些时间是可以赚回来的。

我的工作流程草图

制蛇

工作流管理器的目标是使数据分析(1)可重复,(2)可扩展。工作流管理器有很多,其中最受欢迎的是 Nextflowsnakemake 。我选择使用 snakemake 是因为它的直观语法,以及它与 Python 和我们大学的 HPC 基础设施的完美集成——但 Nextflow 可能是满足您需求的同样好或更好的替代方案。官方的 snakemake 教程非常好,如果你刚刚开始,我强烈推荐它。

什么时候我使用 snakemake 而不是简单的 python 或 bash 脚本?自动化总是在投入的时间和节省的时间之间取得*衡。由于 snakemake 的用户友好性,当我注意到必须在两个或更多文件上运行一行代码时,我会快速编写一个 snakemake 管道。这样,我就不必在 shell/python 脚本中修改和删除变量,而且通过使用 snakefile,代码可以在一个或一千个输入文件上运行。

用 snakemake 制作的 bcl2fastq 片段。即使您不熟悉 snakemake,也应该清楚这段代码是做什么的。

Git 和 GitHub

Git 是另一个可重复数据分析的重要工具。这是一种版本控制的形式,这意味着您可以轻松地回到不同版本的代码,比较版本,并在不同的设备上同步您的代码。我推荐这个关于数据营的教程。

我经常遇到这样的情况,我的代码必须在集群/HPC 上运行。我在笔记本电脑上编写代码,将其推送到 Github,并在 HPC 上提取存储库。为了避免合并冲突,我将这个目录设为只读目录。虽然我可以通过 SSH 连接 Visual Studio 代码,直接在 HPC 上编写代码,但是这个额外的步骤允许对每个修改进行完全跟踪,并且如果出现问题,我可以很容易地返回到早期版本。

我什么时候做一个 Github 库?每当我开始一个新项目时,我都会将其连接到我们的 Github Enterprise。如果我的电脑、time machine backup 和 Dropbox 都出现故障,它还可以作为额外的备份。

Github 上相同脚本的两个版本之间的差异

RMarkdown 和 R 项目

snakemake 的输出通常不是结束,而是生成表格或文件,为 r 的进一步处理做好准备。当开始一个新项目时,我首先创建一个新的*Rproj,并像这样构建我的文件夹:

$ cd ~/tutorial
$ treetutorial
├── .git
│   └── HEAD
├── .gitignore
├── code
│   ├── processRaw.snakefile
│   └── config.yaml
├── Markdowns
│   ├── annotation.csv
│   ├── tutorial.Rmd
│   └── tutorial.html
├── raw_data # this can be a remote folder to save space
├── processed_data
│   ├── datafile1.csv
│   └── datafile2.csv
├── plots
│   └── figure.png
└── tutorial.Rproj

我的哲学是,如果我的电脑现在坏了,我不得不重新安装,那么重新配置的时间应该越短越好。换句话说,记住不同计算机和操作系统之间的可移植性,因为如果你和其他人一起工作(其他人可以包括手稿的审阅者或读者),这将导致很多挫折。

当您使用 RStudio 打开 Rproj 文件时,工作目录会自动分配给 Rproj 的目录。如果您在另一台计算机上工作,并且将目录与 Onedrive 或 Dropbox 同步,那么如果您使用相对路径,一切应该仍然正常:

library(tidyverse)df <- read_csv("./data/datafile1.csv")
df$SampleID <- "datafile1"

这让我想到了另一个重要的提示。我曾经尽可能多地给文件名添加注释(类似于sample1_DNA_plasma_72hincubation.csv),但这很容易出错(在重命名过程中出错),别人也不总是清楚。我现在创建包含所有元数据的注释文件。

annotation <- read_csv("./Markdowns/annotation.csv")
annotation
    SampleID    biomaterial    incubation_time_hours
    datafile1   plasma         72
df_annotated <- merge(df, annotation, on = "SampleID")

RMarkdown 有很多定制选项,请参阅 Yan Holtz 的指南了解更多信息。

我什么时候用 RMarkdown 而不用 R?也总是如此——除非在极少数情况下,我编写一个脚本在集群上运行。如果你更习惯使用 Python,你可以用 Jupyter 笔记本代替 RMarkdown 文件。

关于 Docker

如果没有提到 Docker 的使用,一篇关于可再现数据分析的文章是不完整的。简而言之,Docker 允许您使用和编写的任何软件在计算机之间(甚至在 macOS 和 Windows 之间)完全可移植。我在 Docker 上学习过教程,但是到目前为止我还没有使用过它。为什么不呢?我们的集群使用 easybuild ,每当我们想要使用一个软件包(比如说 FastQC)时,我们必须用ml FastQC/0.11.9_Java-11显式地加载它,它也加载它所有的依赖项。这在某种程度上使 Docker 对我来说是多余的,但在任何其他情况下,我都建议查看 Docker。

出版可复制的科学

让你的数据分析对你未来的自己来说是可理解和可复制的是一回事,但让它对整个科学界来说是可复制的是另一回事。即使对你来说一切都很清楚,清理你的代码和数据并将其公之于众也是一项巨大的时间投资。发布可重复的研究有三个主要组成部分:原始数据、处理过的数据和脚本/代码(第四部分:编写文档和提供元数据)。

原始数据

在我的生物医学和基因组学领域,原始数据通常是测序数据,可能会占用大量存储空间,并且可能是机密的。测序数据可以通过欧洲基因组-现象档案提供给社区。但是根据数据的大小和性质,原始数据也可以作为补充数据添加到手稿中。

处理过的数据

经过处理的数据可以采取多种形式。也可以选择将处理后的数据发布到公共存储库中(例如 ArrayExpress ),将其作为补充数据文件添加到发布中,或者将其托管在 Github 存储库中,您将在那里添加代码。避免由你自己或你的大学托管,因为这在几年内更容易出现 404“未找到”错误。

剧本

这些脚本要么将原始数据转化为经过处理的数据,要么将经过处理的数据转化为手稿中呈现的图形和结论。从原始数据和经过处理的数据中复制手稿的代码可以在 Github 上获得。如果您使用如上所述的文件夹结构进行数据分析,就像上传文件夹一样容易(如果文件太大,不需要原始/处理过的数据,将这些数据添加到。gitignore)。许多杂志也接受你从编织你的博客中得到的 html 文件。此外,您可以将 html 文件作为网页发布在 Github 页面上。

https://gfycat.com/sillythirstybangeltiger

对于这些 Github 库来说,编写文档通常是最具挑战性的。当我发布我的代码时,我并不打算每次都发布一个适用于所有人的现成软件包。对于熟悉 R 和/或 Python 的用户来说,我更多地将这些脚本视为扩展的数据分析部分。我试着给出每个脚本做了什么的简要总结,并以一种清晰的方式评论我的 Python 代码或 RMarkdowns。

工具

我下面列出的工具通过使用提高我的生产率的扩展的组合来帮助加速我的编码过程。一个很好的经验法则是,如果你在编程过程中遇到一些困难,并且认为“这可以更有效地完成”,那么很有可能有人已经做得更有效了。

文本编辑器:Visual Studio 代码

Visual Studio 代码

除了 RMarkdown 之外,我对所有东西都使用 Visual Studio 代码(对此我使用 RStudio)。我的(有限的)扩展列表是:

终端:iTerm2

我仍然在 tmux 中使用 iTerm2,正如我在关于使用 Nord 调色板编程的速成班中所写的。

定制你的.bashrc.zprofile也可以节省你大量的打字时间。我最重要的别名是给 ls 的输出上色,但是还有很多其他的小技巧

cat ~/.bashrc
    # Color for grep and ls
    alias ls="ls --color=auto"
    alias grep='grep --color=auto'

iTerm2 和 tmux

其他工具

RStudio 用于编写 RMarkdown —除了 Nord 调色板之外,我对 RStudio 没有任何定制。对于可视化,我总是使用 ggplot2。

背页— 在线 LaTeX 作者同步到 GitHub,我完全用 LaTeX 写了我的博士论文,这是一次非常愉快的经历,避免了我在 Word 中可能遇到的许多挫折。

最后的想法

分享你的代码可能会令人害怕,尤其是如果你刚刚开始。试着从目标是做好科学和做出有效结论的角度来看。一个开放和透明的工作流程使其他研究人员能够进一步发展和改进您的工作。如果他们发现了一个错误,那么你会学到一些新的东西,在某些情况下,这可能会对你的数据产生新的见解。最后,要意识到每个人都会犯错误,科学研究是一个终身学习的过程。开放的、可复制的科学和其他任何东西一样是一种技能,你做得越多,你就会做得越好(当你犯更多的错误时,你就会知道要注意什么)。

如果没有我从转化肿瘤组学和生物信息学(TOBI)实验室和OncoRNAlab的计算博士生、博士后和生物信息学家那里获得的灵感,这篇文章是不可能完成的,特别是 Pieter-Jan Volders、Celine Everaert、Jasper Anckaert、Annelien Morlion 和 Francisco Avila Cobos。

关于作者:

我是 Ruben Van Paemel 博士,2017 年从医学院毕业后,我开始在根特大学(医学遗传学中心)担任儿科肿瘤学的博士研究员。我得到了弗兰德斯研究基金会的资助。我也是根特大学医院的儿科住院医师。可以在推特上关注我:@ RubenVanPaemel

Python 中的缅甸语自然语言处理

原文:https://towardsdatascience.com/myanmar-language-natural-language-processing-in-python-30489b5de2ca?source=collection_archive---------23-----------------------

语言检测、Zawgyi-Unicode 转换和标记化

照片由 Unsplash 上看到 Wunna

今天的主题是一个面向缅甸语言的开源免费 NLP 工具包,名为 pyidaungsu 。根据官方文件,pyiduangsu 是一个

…缅甸语 Python 库。在缅甸语言的自然语言处理和文本预处理中很有用。

在撰写本文时,它支持:

  • 语言检测(通用缅甸语、扎吉语、克伦语、孟语、掸语)
  • Zawgyi 和 Unicode 文本之间的转换
  • 基于音节或单词的标记化

设置

建议在继续安装之前创建一个新的虚拟环境。

Pip 安装

激活它并运行以下安装命令:

pip install pyidaungsu

语言检测

导入

在文件顶部添加以下导入语句:

import pyidaungsu as pds

然后,您可以调用detect函数并传入您想要的文本:

pds.detect("ထမင်းစားပြီးပြီလား")
# "mm_uni"

它将返回一个指示检测到的缅甸语言的字符串。例如,看看下面的例子和结果:

pds.detect("ထမင္းစားၿပီးၿပီလား")
# "mm_zg"
pds.detect("တၢ်သိၣ်လိတၢ်ဖးလံာ် ကွဲးလံာ်အိၣ်လၢ မ့ရ့ၣ်အစုပူၤလီၤ.")
# "karen"
pds.detect("ဇၟာပ်မၞိဟ်ဂှ် ကတဵုဒှ်ကၠုင် ပ္ဍဲကဵုဂကောံမွဲ ဖအိုတ်ရ၊၊")
# "mon"
pds.detect("ၼႂ်းဢိူင်ႇမိူင်းၽူင်း ၸႄႈဝဵင်းတႃႈၶီႈလဵၵ်း ၾႆးမႆႈႁိူၼ်း ၵူၼ်းဝၢၼ်ႈ လင်ၼိုင်ႈ")
# "shan"

在撰写本文时,它支持以下输出:

  • mm_uni
  • mm_zg
  • 凯伦
  • 孟族人
  • 掸族

Zawgyi-Unicode 转换

这个包提供了两个方便的函数供你在 Zawgyi 和 Unicode 之间转换。

Unicode 到 Zawgyi

对于从 Unicode 到 Zawgyi 的转换,请使用以下函数:

pds.cvt2zgi("ထမင်းစားပြီးပြီလား")
# "ထမင္းစားၿပီးၿပီလား"

Zawgyi 到 Unicode

至于 Zawgyi 转 Unicode,可以这样调用:

pds.cvt2uni("ထမင္းစားၿပီးၿပီလား")
# "ထမင်းစားပြီးပြီလား"

标记化

这个包的主要核心特性之一是标记缅甸语文本的能力。在撰写本文时,它支持:

  • 音节级标记化(缅甸语、克伦族、掸族、孟族)
  • 单词级标记化(缅甸语)

音节级标记化

这种标记化基于正则表达式(regex)。它支持缅甸语,克伦族,掸族和孟族语言。叫它如下:

它将返回一个记号列表(记号化的单词)。

单词级标记化

另一方面,单词级标记化只支持缅甸语。它基于条件随机场(CRF)预测。照常调用 tokenize 函数,并将form参数指定给word

根据输入的文本,输出与音节标签略有不同。在包含英语单词的第二个例子中,注意单词标记化将Alan Turing组合成一个单词。

未来的工作

虽然这个包相当新,目前提供的功能有限,但作者在官方库中概述了以下路线图:

  • 支持新的标记化方法(BPE,文字块等)。)
  • 缅甸语的词性标注
  • 缅甸语命名实体识别(NER)分类器
  • 适当的文件

如果您对其他亚洲语言的语言分析感兴趣,请随意查看以下文章:

结论

让我们回顾一下你今天所学的内容。

本文首先简要介绍了这个包提供的特性。

然后,它通过pip install进入安装过程。

它继续深入解释了语言检测、Zawgyi-Unicode 转换以及标记化。此外,标记化分为音节级和词级。

感谢你阅读这篇文章。祝你有美好的一天!

参考

  1. Github — pyidaungsu

适用于数据仓库解决方案的 MySQL 数据连接器

原文:https://towardsdatascience.com/mysql-data-connector-for-your-data-warehouse-solution-db0d338b782d?source=collection_archive---------26-----------------------

如何构建一个数据库,并以块的形式导出数百万行,流式传输,捕获实时数据更改或提取数据并将其保存到云中

丽塔·塞内卡Unsplash 拍摄的照片

为您的数据仓库构建 MySQL 数据连接器

假设您是一名数据工程师,您的任务是从您的 MySQL 数据库实例和您的 数据仓库 中同步数据。这是一个非常常见的场景,其中您需要连接最流行的数据源和您的数据仓库解决方案,即雪花、红移或 BigQuery。

这篇文章详细总结了如何在不使用任何第三方应用程序的情况下从关系数据库(MySQL)中提取和保存数据。是用 AWS Lambda 函数构建的node . jsserver less应用的详细教程。这个微服务将从 MySQL 数据库中提取数据,并可以在您的机器上本地运行或/和按计划从 AWS 帐户运行。同样的应用程序还有一个更高级的例子,它创建了节点。JS streams从 MySQL 提取数据并保存到你的 AWS S3 数据湖

概述

你将学习如何:

  • AWS Lambda 创建一个简单的 Node.js app。
  • 使用 Node.js streams 来优化内存消耗。
  • 提取数据并以 CSV 和 JSON 格式保存在本地。
  • 导出到云存储中。
  • 使用yaml config 进行查询。
  • 部署和安排它。

*$ npm run test* 命令会将一亿行数据批量导出到云存储中。

作者图片💡迈克·沙克霍米罗夫

本教程可能对数据工程师和所有使用 MySQL 数据库或想学习如何连接各种任意数据源和数据仓库解决方案的人有用。

先决条件、库和设置

工具

  • 已安装 Node.js 和节点包管理器
  • 对云计算(Amazon Web Services 帐户)、AWS CLI 和 AWS SDK 有基本的了解
  • Google Cloud Platform 或 AWS 帐户,具体取决于您使用的云存储。
  • Shell(命令行界面)命令和脚本(高级)。

技巧

  • 良好的节点知识。JS(中级)。您将创建一个 Lambda 函数。
  • 你必须了解 Node。JS 基本概念,即异步函数、节点包和代码如何工作。
  • 基本调试(控制台、打印报表)
  • 循环:即用于
  • 分支:if、if/else、开关
  • Shell 命令和脚本,就像您希望从命令行使用 AWS CLI 部署 Lambda 并能够在本地测试它一样。

如何使用 MySQL 原生特性导出数据

您可能希望使用[SELECT * INTO 'file.csv'](https://dev.mysql.com/doc/refman/5.7/en/select-into.html)来实现这一点:

稍加调整和改变,你就会获得想要的结果。

但是,这是手动操作…

请记住,您可能希望使用索引列来限制where子句中的范围。否则,您的数据库将会遇到困难。

带有节点的非常基本的 MySQL 数据连接器。射流研究…

跳过 这部分如果你是在用 node.js streaming、数据转换和S3 upload等更高级的例子之后。

  • 为你的 Lamda 微服务新建一个文件夹:
    $ mkdir mysql-connector
    $ cd mysql-connector $ npm init

  • 使用npm为其安装 mysql 包:
    $npm i mysql2@2.0.0

  • 安装 run-local-lambda 包。我们将使用它在本地触发和测试 Lambda:
    $ npm i run-local-lambda@1.1.1

  • 在您的 Lambda 根目录中创建一个config文件来定义要使用的管道配置和表:

  • 在主应用程序文件./app.js中创建一个async函数,从./config.json文件运行 SQL 查询

你的应用程序文件夹现在应该是这样的:

您的主应用程序文件 **./app.js** 应该是这样的:

这是如何以编程方式从 MySQL 导出数据的要点。很简单。

在命令行中运行$ npm run test,这将从 MySQL 数据库中导出数据。请确保您的凭据和数据库主机地址正确无误。

现在您可以在您的./config.json文件中更改 SQL 查询,并以编程方式运行它。

如何使用 Node.js stream并从 MySQL 导出数据

首先,为什么要用 node . jsstream

如果你的数据集超过了你的内存,那么你应该像我们在步骤 1 中所做的那样分块提取数据。那stream是干什么用的。它可以帮助你优化应用程序的内存并导出数据,而无需将所有行加载到内存中。

如果你使用 AWS Lambda 或 GCP 云功能,这有助于节省资金,并且不会过度配置内存资源。

通常,128 Mb 的分配内存足以导出几百万行。

所以有了 Node.js *stream* 你可以更高效的把 MySQL 连接到你的数据仓库。

它的要旨

假设您想从 MySQL 中逐行提取数据,并在本地保存为 CSV 格式。以下示例适用于 npm 包mysql2csv-stringify

尝试创建一个函数,并用 lambda 的npm run test命令运行它。

如何用stream高效地从 MySQL 导出数据并在本地保存为 CSV

你所需要的只是一个queryDbAndSave()函数。尝试将下面的async示例添加到您的processEvent()函数中。

把这个加到你的 **processEvent()** 函数里,就像这样:

下一个在你的命令行运行:$ npm run test

有想法了?酷毙了。让我们继续举更多的例子。

如何将数据从 MySQL 导出,并通过管道stream传输到 GCP 的云存储或 AWS S3

这个例子将把你的 SQL 查询结果保存到 AWS S3 或者 GCP 云存储中,不需要过度配置内存资源。

在我的场景中,我希望将结果查询到我的 S3 数据湖桶 ,并将 JSON 转换为 ndJSON

这样,当文件在云存储中被创建时,我可以很容易地用其他的服务 进一步触发 数据摄取 。如果你想学习如何做,请查看我的教程如何处理数据加载到你的数据仓库

对于stream-save查询结果,您可能想要向您的queryDbAndSave()函数添加一个新的分支:

此示例适用于相同的模块,但您可能也想包括这些模块:

  • npm i aws-sdk@2.1001.0撰写本文时,AWS Lambda 环境中使用的。检查当前环境这里的,这样您就可以简单地将其从部署工件中排除。
  • through2@4.0.2"一个更容易构建的包装库streams

所以现在如果再添加一个 MySQL 管道 到你的./config.json:

在你的命令行运行 *$ npm run test*

它将从 MySQL 中导出数据,并以 *stream* 模式将其 保存为一个文件 到您的云存储中。

如何将数据导出为一个stream并将其分块保存到云存储中

您可能还想将数据保存在本地或保存到 AWS S3 中,即保存在 批处理模式 中。下面的片段解释了如何做到这一点。

您可能希望在./app.js : const BATCH_SIZE = process.env.BATCH_SIZE || 3000;的顶部声明输出文件的批量大小

那么您可能想要评估 SQL 查询的大小。您可以为此使用另一个异步函数:

向您的queryDbAndSave()函数添加另一个分支,并在每次检查是否到了结束时间时分块导出数据:

最终解决方案为**./app.js****processEvent()**功能:别忘了运行$npm i moment./app.js将使用构造文件的键来保存对象。

如何使用 yaml 配置

最终的解决方案可以在这个仓库中找到,为你的 MySQL 管道使用npm configyaml定义。

我更喜欢使用 *yaml* 只是因为当你添加那些长的 SQL 查询时更容易阅读。

样品./config/staging.yaml通常会看起来:

在我看来,当你需要区分livestaging环境时,这也更直观。在你的命令行运行$ npm i config。所以你最终的应用程序文件夹用./config/代替./config.json看起来会像这样:

如何部署解决方案

有三种方法可以做到。

  1. 初学者可能会选择使用 web UI,要么将解决方案部署为 AWS LambdaGCP 云功能
  2. 更高级的用户可能想要创建一个部署 shell 脚本./deploy.sh,如下所示。在命令行中运行$ ./deploy.sh,它将部署 Lambda:

3.使用 Tarraform 或 AWS Cloudformation 部署代码为的基础设施。方便的 AWS Cloudformation 模板可以在 github 上的这个项目的资源库中找到。

在部署期间,确保您正确配置了所有访问角色安全组。例如,当您的 MySQL 数据库在 AWS 中时,您的 Lambda 函数必须部署在同一个 VPC 中才能访问它。一旦你在 Lambda 中启用了 VPC 支持,你的函数就不能再访问 VPC 之外的任何东西,包括 S3。具体到 S3,你可以使用[VPC 端点][15]来解决这个问题。

结论

这是一个简单可靠的 数据导出 解决方案,允许你以低内存使用的方式从 MySQL 数据库中提取数据。这样你就可以创建一个快速可靠的 MySQL 数据连接器 并拥有一些令人敬畏的特性:

  • 通过从命令行运行$npm run test以编程方式提取 MySQL 数据。
  • 使用yaml定义来描述你的 MySQL 管道
  • 执行dryRun来评估 SQL 大小。
  • 使用Node.js streams导出数据,以避免内存过度配置。
  • 在本地设备上保存数据导出。
  • 将数据作为一个文件或成块保存到中。
  • 基础设施为代码的一键式部署和调度

查看 Github 库了解更多信息。

一些实时集成可能会很昂贵,而且通常依赖于你拥有的数据量。想象一下,插入到 MySQL 中的每一行都会触发 Lambda 导出并插入到您的数据仓库中。有一种更好的方法来像这样监视和控制数据摄取。

就在几天前,我用它从 MySQL 中导出了 5600 万行。然后我将它们分块保存到 AWS S3 的数据湖中。例如,我有一个数据加载管理器,每次文件进入数据湖时,它都会将数据发送到我的 BigQuery 数据仓库。

因此,导出我的 MySQL 数据并将其加载到我的数据仓库既快又容易。

资源

[1]:https://towardsdatascience . com/how-to-handle-data-loading-in-big query-with-server less-ingest-manager-and-node-js-4f 99 FBA 92436

[3]:https://docs . AWS . Amazon . com/Amazon rds/latest/aurora user guide/aurora MySQL。Integrating.SaveIntoS3.html

【5】:【https://nodejs.org/api/stream.html

[7]:https://docs . AWS . Amazon . com/lambda/latest/DG/lambda-runtimes . html

[8]:https://AWS . Amazon . com/blogs/database/captureing-data-changes-in-Amazon-aurora-using-AWS-lambda/

[9]:https://stack overflow . com/questions/12333260/export-a-MySQL-table-with-亿万记录分块

[10]:https://stack overflow . com/questions/1119312/MySQL-export-into-outfile-CSV-escaping-chars/1197023

[11]:https://joshuaotwell . com/select-into-outfile-examples-in-MySQL/

[13]:https://AWS . Amazon . com/blogs/database/best-practices-for-export-and-import-data-from-Amazon-aurora-MySQL-to-Amazon-S3/

[14]:https://blog . rising stack . com/node-js-MySQL-example-handling-Bai-gigabytes-of-data/

原载于https://mydataschool.com

MySQL 与 Access

原文:https://towardsdatascience.com/mysql-vs-access-5db036bcdf4d?source=collection_archive---------10-----------------------

开源和专有的冲突

Unsplash 上由 Rodion Kutsaev 拍照

正如你可能从标题中猜到的,我们正在做 MySQL 对比系列的另一篇文章。数据库再次引起了我的兴趣,还有一个数据库我们还没有谈到。Microsoft Access 数据库。我们甚至不必开始深入研究,你可能已经知道访问将会有多么不同。但这正是我认为挖掘更多信息会很有趣的地方。有那么多明显的不同,但是当我们去挖掘的时候,又有多少相似之处呢?也有一些明显的相似之处,但是那么又有多少不同呢?

正如你所猜测的,我刚刚发现这是一个有趣的话题。根据我在几堂课上的经验,我们没有把 Access 作为一个完整的数据库来使用。但是在我女朋友的一堂课上,她做到了。那么,让我们深入了解 MySQL 和 Microsoft Access 之间的差异。在这一点上,我们将更多地关注两者之间的差异,而不是积极/消极的方面。在我看来,你已经看到 MySQL 是我最喜欢在家里使用的开源数据库之一,而我从来没有真正提到过 Access。所以,今天我们只看 MySQL 和 Access 的区别。

什么是微软 Access

首先要注意的是,Access 不仅仅是一个数据库管理系统(DBMS)。Access 合并了 Jet 数据库引擎和图形用户界面(GUI)。它还增加了软件开发工具。传统上,Access 使用关系数据库管理系统(RDBMS)。但是,Access 也可以简单地作为 DBMS 运行。

虽然 Jet 数据库引擎是默认的,但是您也可以选择 Access 支持的其他常用数据库,如 SQL Server、Oracle、DB2,或者查找对开放式数据库连接(ODBC)标准的支持。Access 还允许您从电子表格、文字处理文件或数据库文件中导出或导入数据。您还可以导入甚至直接链接到存储在其他数据库或应用程序中的数据。Access 还可以理解各种各样的数据格式。

当然,访问点是能够访问各种资源。这可能意味着它访问的文件,或者它可以读取的不同数据格式。但它也适用于访问数据的方式。例如,Access 可以处理来自其他来源、其他 SQL 数据库、流行的 PC 数据库程序、服务器、小型机、大型机的数据,甚至可以处理 Internet 或 intranet web 服务器上的数据。关于访问已经说得够多了,让我们开始比较一些不同之处。

开源与不开源

正如我们之前多次讨论过的,MySQL 是一个开源的 RDBMS,大部分可以免费使用。MySQL 只涉及一些专有代码。当然,这是你不能只看到的代码,也是你要付费的领域。对于 MySQL,你有更多的争议。所以,Access 是微软 Office 自带的应用程序之一。但是可以肯定的是,这些并不是完全免费的。你必须有办公室才能免费进入那里。你可以获得微软 365 应用的 30 天免费试用,但也有免费的 Access 运行时版本可供你使用。现在,应该有免费使用 Access 的方法,但当然,这并不等同于 MySQL 是开源的,因为 Access 使用的是商业许可证。

管理

说到分区,我们已经讨论了 MySQL 如何使用水*分区,或者使用 MySQL Cluster 或 MySQL Fabric 进行分片。另一方面,Access 不支持分区。复制也是如此。MySQL 支持多源或源副本复制,而 Access 不支持复制。

对于用户概念,MySQL 使用了细粒度的用户授权概念。然而,Access 并不包含用户概念,尽管在 Access 2003 之前有简单的用户级内置安全性。

MySQL 和 Access 都是为了经久耐用而构建的。它们都支持数据的持久性。但是,Access 不包括用于事务日志记录的文件。MySQL 和 Access 也是 ACID 兼容的,但是 Access 没有用于事务日志的文件。

我们还应该提到操作系统。MySQL 可以在 Linux、Windows、Solaris、OS X 和 FreeBSD 上运行。但是,Access 只能在 Windows 上运行。这是因为它不是真正的数据库服务器。它只是通过使用 dll(动态链接库)来发挥作用。也许没那么重要,MySQL 是用 C++和 C 写的,而 Access 只用 C++写的。

服务器端脚本也可能是一个考虑因素,这取决于您使用的版本。例如,MySQL 只有专有版本的服务器端脚本。对于 Access,仅当您将 Access 2010 或更高版本与 ACE 引擎一起使用时。Access 中的触发器也是如此。它们仅在带有 ACE 引擎的 Access 2010 或更高版本中可用,而触发器在 MySQL 中始终可用。

就安全性而言,访问权限要有限得多。您可能已经听说过,MySQL 有不同类型的安全性,并且可以配置 SSL 支持。为了安全起见,Access 仅支持用户名/密码。

既然我们已经了解了这些差异,那么让我们快速了解一下 Access 的优点和缺点。

访问的好处

Access 易于导航,因为它使用经典的 Microsoft UI(用户界面)。它也是微软办公套件的一部分。

访问不仅仅是针对表。如果你需要你的图表都绘制出来,没有必要在纸上做。Access 使得为表或模拟布局创建实体关系图变得很容易。

Access 还支持标准的 SQL 语法/脚本,因此您不必花时间学习一门新语言来使用它。

访问的缺点

虽然有对访问的支持,但它并不总是有用的。就教程而言,它们有时会受限于所涵盖的材料。这使得“帮助信息”并不总是有用的。

虽然有更新,但没有太多大的变化。这可能是好事,但也可能是坏事。没有太多的变化也意味着他们会落后。

很难展示未使用的表格、报告、表格、文档等等。虽然开始时这可能不是很重要,但由于内存有限,您需要找到哪些对象可以删除,而不会损害任何底层查询或报告。

另一个挑剔的问题,但是对话框并不总是可调整大小的,所以长名字可能会被删掉。这不会是太大的问题,除非您有类似的命名约定。在这种情况下很难分辨出哪个是哪个。

结论

在本文中,我们研究了 MySQL 和 Microsoft Access 之间的区别。总而言之,这两者之间有很多相似之处,但都具有标准的 SQL 特性。至于更技术性的方法,主要是底层结构,有更多的差异。在我看来,这是对数据库的一次有趣的探索。我认为有比我认为的更多的相似之处,但也许差异是重要的决定因素,比如付费或开源。最后,我希望您发现这是对 MySQL 和 Access 的一次有趣的探索。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

看看我最*的一些文章:

https://python.plainenglish.io/how-fast-are-sqlalchemy-relationships-5b6787dc9276 https://medium.com/codex/libreoffice-on-docker-1a64245468c

参考资料:

https://dba.stackexchange.com/questions/62851/mysql-vs-microsoft-access https://db-engines.com/en/system/Microsoft+Access%3BMySQL https://www.toolbox.com/tech/devops/question/difference-between-microsoft-access-and-mysql-061011/ https://www.tutorialspoint.com/ms_access/ms_access_overview.htm

MySQL vs Cassandra DB

原文:https://towardsdatascience.com/mysql-vs-cassandra-db-49bc518e1b8f?source=collection_archive---------7-----------------------

另一个 RDBMS 和 NoSQL 摊牌…

丹尼尔·库切列夫在 Unsplash 上拍摄的照片

在我上一篇 MySQL vs 的文章中,我谈到了 Redis,这是一个我以前没有听说过的数据库。这一次,我想谈谈一个我听说过但没有时间试用的数据库。Cassandra DB 是另一个 NoSQL 数据库,我没有机会尝试,但经常在黑客马拉松这样的活动中听说它。除了是一个 NoSQL 数据库,Cassandra 也是开源的,它遵循我通常选择写的文章。但除此之外,我没有其他关于它的背景知识。

因此,对于另一篇 MySQL vs 文章,让我们更深入地了解一下 Cassandra DB 是什么。就像我们在以前的文章中所做的那样,它主要是管理性的,不包括语法。但是我们也要看看卡桑德拉的一些利弊。我们也可以比较一下 MySQL 的优缺点,但它们将与我们对 Cassandra 的了解直接相关,因为我们已经在本系列中讨论了很多关于 MySQL 的内容。所以,不再耽搁,让我们来学习一下什么是 Cassandra DB。

什么是卡珊德拉

Cassandra 是 Apache 的一个开源数据库。这是 NoSQL,所以也很轻。Cassandra 也是一个分布式数据库。分布式数据库运行在多台机器上,但是对于用户来说,它看起来就像只有一台机器,因为他们是一个统一的整体。这通过多个节点发生,每个节点代表 Cassandra 的一个实例。从那里,节点相互通信以分配工作负载,从而改进功能。如果这个节点逻辑听起来很熟悉,那是因为 Cassandra 被设计成易于组织成一个集群。在那里,如果您愿意,您可以拥有多个数据中心。

Cassandra 在可伸缩性方面也很灵活。因为 Cassandra 是如此动态,您可以根据需要增加或缩小数据库。但这不像 MySQL,MySQL 有很长的停机时间,最终会再次达到上限。相反,Cassandra 允许更多的动态扩展,这意味着您需要做的只是添加更多的节点来增加大小、容量,甚至 CPU 能力或相关的 RAM。这意味着需要很少甚至没有停机时间,如果您过度,您可以轻松地缩减。

开源数据库

正如我们过去讨论过的,MySQL 和 Cassandra 都是开源的。关于 MySQL,前几篇文章我们讨论了 MySQL 提供的专有软件。这当然是一种付费服务,具有额外的支持和功能。对于 Cassandra,我在他们的开源文档中找到了信息,但我找不到任何关于它有付费功能或专有代码的信息。如果这是不正确的,请让我在评论中知道,但从我所看到的,卡珊德拉是真正的开源。

数据库功能

所以,首先,让我们谈谈数据库的结构。如你所知,MySQL 是一个 RDBMS(关系数据库管理系统)。然而,卡珊德拉是一个 NoSQL 数据库。这意味着 MySQL 将更多地遵循主/工人架构,而 Cassandra 则遵循对等架构。

我们已经知道 MySQL 支持 ACID(原子性、一致性、可靠性和持久性)事务。然而,Cassandra 不会自动跟踪 ACID 交易。这并不意味着这是不可能的。虽然最初没有提供,但是您可以调整 Cassandra 的特性来支持 ACID 属性。例如,调整 Cassandra 的复制和容错功能可以确保可靠性。另一个例子是调整一致性。Cassandra 是一个 AP (Available Partition-tolerant)数据库,但是您可以将一致性配置为基于每个查询。

当我们考虑可伸缩性时,MySQL 更普遍地支持垂直伸缩。通过复制或分片,水*扩展也是可能的。另一方面,Cassandra 支持水*和垂直可伸缩性。虽然这个更具体一点,但是我们也来看看 Read 事务的性能。但是首先,我们需要查看连接来理解逻辑。如您所知,MySQL 或任何 RDBMS 都支持查询中多个表之间的连接。另一方面,卡桑德拉不鼓励加入。相反,它更喜欢每次查询只从一个表中选择。因此,因为在一次 MySQL 读取中可以连接多个表,所以性能为 O(log(n))。一次只读取一个表,Cassandra 的性能是 O(1)。当查看 Write 语句时,MySQL 的性能可能会降低,因为在写入之前执行了搜索。Cassandra 不使用搜索,而是使用 append 模型,这在编写时提供了更高的性能。

行政

可能是给定的,但是 MySQL,因为它是 RDBMS,支持参照完整性,并且有外键。因为 Cassandra 是一个 NoSQL 数据库,它不实施参照完整性,因此没有外键。

为了确保分布式系统中的一致性,MySQL 提供了即时一致性方法,但这是唯一提供的类型。Cassandra 允许即时一致性方法和最终一致性方法。

就操作系统而言,MySQL 用于 FreeBSD、Linux、OS X、Solaris 和 Windows。然而,Cassandra 只在 BSD、Linux、OS X 和 Windows 上受支持。正如我们所知,MySQL 也是用 C 和 C++语言编写的。另一方面,Cassandra 只使用 Java 编写。MySQL 也是 Oracle 开发的,其中 Cassandra 是 Apache 软件开发的。

卡珊德拉的优势

正如我们在描述 Cassandra 时谈到的,它的可伸缩性是一个很大的优势。这是因为它可以在不停机的情况下快速完成,因为您不必关闭数据库来进行扩展。水*和垂直可伸缩性都是一个选项,因为 Cassandra 使用线性模型来获得更快的响应。

除了可伸缩性,数据存储也很灵活。因为它是一个 NoSQL 数据库,所以可以处理结构化、非结构化或半结构化数据。同样的,数据分布也很灵活。可以使用几个不同的数据中心,这使得分发数据更加容易。

性能是我们讨论的另一个因素。我们将在这里讨论的好处是它如何处理同时读写语句。即使是多个写请求也能得到快速处理,不会影响读请求。

使用 Cassandra 的另一个好处是简单的语言,CQL (Cassandra 查询语言),它是作为一个替代 SQL 提供的。卡珊德拉也有权力下放的好处。这意味着,由于节点的结构,不会有单点故障。如果一个节点发生故障,另一个节点可以检索相同的数据,因此数据仍然可用。

卡珊德拉的缺点

Cassandra 的一个缺点是,因为它是 NoSQL,没有结构化的 SQL 语法,所以会有一系列 Cassandra 没有的功能。例如,没有实施参照完整性、子查询(GROUP BY、ORDER BY 等。),甚至是加入。Cassandra 的查询能力有限,也不支持聚合。此外,读取请求可能运行缓慢。我们提到写请求可以运行得很快,但是多个读请求会延迟结果并且运行得更慢。

使用预测查询在 Cassandra 中对数据建模。这意味着存在重复数据的可能性。尤其是卡桑德拉是 NoSQL,你可能必须处理重复的数据,因为它不会像 MySQL 或其他 SQL 语言那样被自动拒绝。

与 Cassandra 相比,MySQL 的优势

与 Cassandra 相比,MySQL 的最大优势在于它是一个 RDBMS。首先,我们讨论的是连接、聚合和其他功能,比如实施参照完整性。还有更灵活的查询,您可以创建任何组合来产生不同的结果。然而,MySQL 比其他一些 SQL 系统更灵活,因此对 SQL 标准的遵从是有限的。

MySQL 也试图防止重复记录,而 Cassandra 没有。不仅如此,MySQL 还兼容 ACID,这可能是您数据库需要的额外结构。

MySQL 的缺点

与 Cassandra 相比,第一个主要缺点是伸缩时的灵活性。虽然 MySQL 可以扩展,但是会有停机时间,即使这样,您仍然会遇到瓶颈。但是,由于查询中的所有潜在组合,查询速度也会变慢。例如,如果您正在连接多个表,无论是读请求还是写请求,都可能会降低结果的速度。

MySQL 也只是部分开源。使用付费版本时,涉及到专有代码和额外的支持。

结论

在今天的 MySQL 对比系列中,我们看了 NoSQL 数据库 Cassandra。Cassandra 是另一个轻量级、开源、高度可伸缩的数据库,越来越受欢迎。它是一个 Apache 软件,设计为在一系列节点之间作为分布式数据库运行。这意味着可以有多个数据中心,如果您想要扩展,只需添加或删除节点。尽管 Cassandra 灵活而有用,但它也不遵循标准的 SQL 实践,例如强制引用完整性,并且它鼓励用户编写单独的查询,而不是不支持的连接。

如果你对卡珊德拉有更多的了解,或者想分享你的经历,请随时发表评论。我希望这些信息对你有用,或者至少是一篇有趣的文章。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

看看我最*的一些文章:

https://medium.com/codex/libreoffice-on-docker-1a64245468c https://python.plainenglish.io/searching-for-text-in-those-annoying-pdfs-d95b6dc7a055

参考资料:

https://cassandra.apache.org/_/cassandra-basics.html https://www.educba.com/cassandra-vs-mysql/ https://www.geeksforgeeks.org/difference-between-cassandra-and-mysql/ https://cloudinfrastructureservices.co.uk/cassandra-vs-mongodb-vs-redis-vs-mysql-vs-postgresql-pros-and-cons/

MySQL vs. MariaDB

原文:https://towardsdatascience.com/mysql-vs-mariadb-6dda1649de44?source=collection_archive---------28-----------------------

比较两个非常相似但完全不同的 Rational 数据库管理系统

Unsplash沙丘拍摄的照片

最*一直在想多了解一下 MariaDB。我对 MariaDB 没有太多的了解,但我也很久没有为我的 MySQL 系列写文章了,所以我想这将是一个学习更多知识的好机会,但也可以与类似的东西进行比较。关于 MariaDB,除了它如何寻求成为 MySQL 的可比较的替代者之外,没有什么背景知识,让我们先来看看 MariaDB 的一些基础知识,然后再进行比较。

什么是 MariaDB?

MariaDB 是一个关系数据库管理系统(RDBMS ),旨在替代 MySQL。它是开源软件,在 GNU 通用公共许可证下也可以免费使用。MariaDB 的一大重点是它的全能速度。但是,并没有牺牲性能和动力。众所周知,MariaDB 还具有高度的可伸缩性。监督 MariaDB 的团队非常关注安全性,这意味着他们会尽快发布更新来修补这些漏洞。MariaDB 还努力在网络、云端甚至移动设备上快速工作。它也是耐酸的。

现在我们已经了解了一些关于 MariaDB 的背景知识,让我们来看看 MySQL 和 MariaDB 的异同。

性能

当我们谈论性能时,我们将更多地关注功能而不是实际速度,因为两者非常具有可比性。MySQL 和 MariaDB 都使用分区,这尤其有助于提高可伸缩性。扩展时,性能变得更加重要。为了获得更快的性能,您还需要充分利用分配给您的空间。MySQL 和 MariaDB 都使用行压缩。

MariaDB 也使用线程池。如果您从未听说过线程池,请考虑尝试链接到数据库的连接。该连接将获取一个线程来查询数据库。使用线程池,有一系列开放的线程被池化在一起,并且没有被使用。当一个连接需要这些线程中的一个时,它可以直接获取它并使用它来查询数据库,然后在完成后再次丢弃它。这样,就不会在每次打开连接时都创建线程。现在,MySQL 确实有了线程池的能力。但是,它仅在企业级可用。这意味着免费使用的社区版本不包括线程池。

因为 MariaDB 试图建立在 MySQL 的基础上,所以许多其他特性加快了 MariaDB 的性能。其中一个功能是查询结果缓存。另一个是并行查询和读/写拆分。还有很多,但这只是少数。

真正的开源

所以,MySQL 和 MariaDB 都是开源的。但是,MySQL 归甲骨文所有。这意味着,是的,在他们的社区版中有一些开源代码。但是,也有专有代码。该代码并不是对每个人都可用,因为它只是作为企业级的特性而可用。对于 MariaDB,它是真正的开源,这意味着随着他们的更新,他们甚至接受外部的贡献来建立更多的特性和功能。

数据库功能

MySQL 和 MariaDB 的通用选项非常具有可比性,这也是它们如此相似的原因。然而,MariaDB 在 MySQL 的基础上增加了几项改进。例如,MariaDB 有一个内存存储引擎,可以加快缓存和索引的速度。这意味着 INSERT 语句的完成速度比 MySQL INSERT 快 24%。

如前所述,MariaDB 可以处理线程池。然而,让 MariaDB 与众不同的是,当适当扩展时,它可以处理 200,000 个或更多的开放连接。复制过程也比 MySQL 更安全、更快速。更新也可以比使用 MySQL 更新更快。

MariaDB 除了其他特性之外,还有其他的扩展和语句。比如可以处理 JSON 之类的扩展。对于语句,MariaDB 可以执行各种语句,如 WITH 或 KILL 语句。其中一些特性是 MariaDB 的新特性,因此 MySQL 没有提供。

MySQL 在企业版中提供了专有代码。在它提供的特性中,有一些是 MariaDB 没有的。为了解决缺失的功能,MariaDB 允许开源插件作为替代。

虽然 MariaDB 试图成为 MySQL 的改进版,但是有一些重要的特性是 MariaDB 所不具备的。例如,MySQL 允许动态列,而 MariaDB 不允许。

安全与行政

MariaDB 和 MySQL 都实现了重要的安全特性,如加密、密码过期、角色、特权和试听。两者似乎都允许数据屏蔽。对于高级数据库和数据保护,Maria DB 还增加了查询限制和查询结果限制。

另一个重要因素是灾难恢复计划。MariaDB 和 MySQL 支持使用备份和恢复工具以及二进制日志来前滚事务的时间点恢复。然而,MariaDB 更进一步。它支持时间点回滚,使数据库管理员能够在很少甚至没有停机的情况下回滚数据库。

MariaDB 和 MySQL 都将多主集群与提供连续可用性的数据库代理或路由器相结合。为了进一步提高其高可用性,MariaDB 还增加了事务重放、会话恢复功能和连接迁移。这允许对应用程序隐藏故障。

结论

当与 MySQL 比较时,MariaDB 试图成为一个可比较的资源。正因为如此,MariaDB 拥有 MySQL 拥有的许多功能。然而,它试图通过添加 MySQL 所没有的各种特性来更进一步。MariaDB 也更关注开源,他们的团队甚至在添加什么功能和如何改进方面接受意见。MariaDB 速度更快,并试图将重点放在安全性和性能上。然而,MariaDB 也努力实现高度可伸缩性。

当试图决定使用什么数据库时,您当然应该始终考虑您的项目需求。说到细节对比,MariaDB 和 MySQL 非常相似。没有太多方面是一方缺少另一方拥有的东西。当然,这条规则也有例外,但在大多数情况下,MariaDB 试图成为 MySQL 的改进版本。正因为如此,我认为应该给 MariaDB 一个机会。如果你正在寻找一些非常熟悉和成熟的东西,我建议你坚持使用 MySQL 的根。然而,如果您正在寻找一个新的、强大的、具有同样多有用特性的数据库,我建议尝试一下 MariaDB。

在了解了更多关于 MariaDB 的信息后,我更有兴趣尝试一下。也许我以后甚至会写一篇如何使用 MariaDB 的教程。但是现在,我希望这个比较是有帮助的和有趣的。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

看看我最*的一些文章:

https://miketechgame.medium.com/after-nearly-five-years-i-left-my-job-a2e76f0dc0b4 https://python.plainenglish.io/what-is-typer-9a9220d80306 https://python.plainenglish.io/sending-error-emails-and-text-messages-in-python-b8e9a48e00ae

参考资料:

https://mariadb.com/database-topics/mariadb-vs-mysql/ https://www.guru99.com/mariadb-vs-mysql.html https://hackr.io/blog/mariadb-vs-mysql https://blog.panoply.io/a-comparative-vmariadb-vs-mysql

MySQL 与 Oracle SQL

原文:https://towardsdatascience.com/mysql-vs-oracle-sql-a97a7659f992?source=collection_archive---------2-----------------------

比较两个 Oracle 拥有的关系数据库管理系统

达里尔·洛在 Unsplash 上的照片

在我上一篇关于 MySQL 的文章中,我简单的提到了 MySQL 是由 Oracle 拥有的。但这让我想到,为什么不比较 MySQL 和 Oracle SQL 呢?它们都属于同一家公司,但在使用时,它们看起来非常不同。理论上,不同管理系统支持的每种 SQL 语言都应该至少有些不同。但是这两个 RDBMSs 的区别不仅仅是语法。这就是我们将在本文中探讨的内容。和其他人一样,我们将首先简要概述 Oracle SQL。只是简单描述一下它是什么,以及我们稍后需要参考的一些细节。最后,我们将比较 MySQL 和 Oracle SQL 之间的一些差异。像其他 MySQL 与…的文章一样,它不会包罗万象。但是我们至少会看到一些主要的区别。

Oracle SQL 概述

当提到 Oracle SQL 时,我们指的是 Oracle 数据库。它是一个使用商业许可的关系数据库管理系统(RDBMS)。Oracle SQL 是一个跨*台的管理系统,这意味着它可以在多种操作系统上运行。这个数据库管理系统是第一个为处理数据库中的记录而开发的关系系统。Oracle SQL 还具有可伸缩性、可移植性和易编程性。

Oracle SQL 旨在处理大量数据。它甚至有恢复管理工具。另一个主要目标是数据的可靠性,并确保维护数据的完整性。它通过遵循 ACID(原子性、一致性、隔离性和持久性)来保持完整性。

开源数据库

众所周知,MySQL 是一个开源数据库。然而,相比之下,Oracle SQL 是为商业开发的。这意味着没有许可证,您将无法使用 Oracle SQL。Oracle SQL 有一个免费的快速附加功能,但只推荐学生使用。

数据库功能

就可伸缩性而言,MySQL 可用于小型和大型企业。Oracle SQL 被设计成大规模的,可以支持大量数据。

MySQL 不支持数据分区,只支持静态系统。然而,Oracle SQL 支持数据分区。它还可以与静态和动态系统一起工作。然而,MySQL 支持一些 Oracle SQL 不支持的类型。例如,MySQL 支持空值。Oracle SQL 不支持空值。

MySQL 支持 SQL 语言。但是,Oracle SQL 同时支持 SQL 和 PL/SQL。

与 MySQL 相比,Oracle SQL 不支持那么多操作系统。例如,Oracle SQL 支持 Windows、Mac OS X、Linux、Unix 和 z/OS。除了 BSD、Symbian 和 AmigaOS 之外,MySQL 还支持所有这些。

直到版本 5,MySQL 都不支持存储过程。相比之下,Oracle SQL 支持嵌入在数据库中的存储过程。它们可以由事件执行或触发。

无法定制 Oracle SQL,因为它是一个封闭的源。相比之下,MySQL 是可以修改的。因为它是开源的,所以可以根据您的任何需求,针对不同的环境修改代码。

安全和管理

MySQL 和 Oracle SQL 都有用户名和密码等安全性。然而,两者之间有一些小的不同。例如,在 MySQL 中,需要标识一个主机。但是有了主机、用户名和密码,用户就可以访问数据库。使用 Oracle SQL,登录时需要用户名和口令,但是还需要验证概要文件。这意味着如果没有设置配置文件,用户就不能访问它。这也有助于定义用户角色。

因为 Oracle 同时拥有 Oracle SQL 和 MySQL,所以它们都有支持和文档。Oracle SQL 使用社区支持以及针对付费产品的各种支持选项。对于 MySQL,我们提供全天候的技术支持服务。主要是,那些支持工程师在寻找漏洞的修复,定期维护,并推出安全补丁。

甲骨文的优势

如果需要高度的可伸缩性,并且预计数据会更大,那么 Oracle SQL 将是更好的选择。如果大型数据库也需要托管,那么选择 Oracle SQL。当交易控制需要灵活性时,也应该选择它。当数据库需要独立于*台时,Oracle SQL 也是更好的选择。因为 Oracle SQL 是为更大的数据库和更高的交互而设置的,所以它比 MySQL 支持更大的并发池。尽管 Oracle SQL 是付费的,但由于它的支持和功能,它被设计成企业的最佳选择,尤其是它是为企业扩展而构建的。

甲骨文的缺点

Oracle SQL 的企业版是唯一的免费版本,因为它主要被许可用于商业用途。这意味着除非付费,只有少数人可以访问和学习它。因为是付费的,所以不是开源的。这意味着任何更新和修复,甚至价格,都是由 Oracle 制定的。这意味着产品的透明度降低。这也意味着更少的定制和灵活性,因为它是一个成品。与 MySQL 相比,最后一个缺点是语法。与 MySQL 相比,学习曲线有点陡峭。Oracle SQL 并不是很难学,只是没有 MySQL 那么简单。

MySQL 的优势

MySQL 在一些情况下是更好的选择。一个这样的例子是当数据库不需要大规模扩展时。另一种情况是网站或 web 应用程序需要只读数据库。如果不需要更高程度的复制,MySQL 将是更好的选择。因为 MySQL 确实有一个 GNU 许可下的免费开放版本,预算也是选择 MySQL 的一个很好的理由。选择 MySQL 而不是 Oracle SQL 的最后一个原因是当并发率较低,或者只需要简单的查询时。

MySQL 的缺点

因为 MySQL 属于 Oracle,所以与其他开源关系数据库管理系统相比,它有许多限制。尽管它对小型和大型企业都很灵活,但它不是为 Oracle SQL 这样的大规模数据而构建的。MySQL 也不支持与其他客户端应用程序的集成。它还允许使用触发器。尽管这些对数据非常有用,但它们也会给数据库服务器带来很高的负载。与 Oracle SQL 相比,MySQL 速度较慢,存储选项也较少。它也不支持大型线程池,但这是因为与 Oracle 相比,内存存储容量较小。正如我们在上一篇 MySQL 对比文章中提到的,MySQL 并不是完全开源的。相反,它在企业版中有一些专有代码。

结论

MySQL 和 Oracle SQL 都是 Oracle 公司的关系数据库管理系统。MySQL 主要是免费和开源的,而 Oracle 主要是商业和付费的。MySQL 也比 Oracle 更加可定制,因为 Oracle 是一个成品。两种管理系统都提供社区和技术支持。尽管这两个数据库都属于同一家公司,但是它们有很大的不同,特别是在比较一些功能时,比如并发线程或数据分区。这两个数据库都是非常好的选择。

当您决定需要哪个数据库时,您应该考虑项目的规模和预算。尽管 Oracle 确实有免费版本,但它主要是为学生设计的,不像 MySQL 那样开放给每个人使用。MySQL 确实有一个付费版本,可以帮助解决免费版本中缺少的许多功能,但是对于大多数项目来说,您只需要在家里使用免费版本。最终,两者都是数据库管理系统的好选择,但是如果你在家工作,你可能想要选择 MySQL 来保持预算友好。但是,如果您创建了自己的业务,随着业务的扩展和数据的增加,您可以考虑选择 Oracle SQL 来扩展您的业务。无论你做什么决定,你最了解你的项目。希望本文能为您提供每个数据库的更多细节,以及是什么让它们如此不同。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

看看我最*的一些文章:

https://python.plainenglish.io/making-python-read-my-emails-9e3b3a48887c https://medium.com/codex/a-simpler-introduction-to-oauth-3533e53a4589 https://miketechgame.medium.com/after-nearly-five-years-i-left-my-job-a2e76f0dc0b4

参考资料:

https://www.geeksforgeeks.org/difference-between-oracle-and-mysql/ https://www.educba.com/mysql-vs-oracle/ https://hevodata.com/learn/mysql-vs-oracle/ https://www.janbasktraining.com/blog/oracle-vs-sql-server-vs-mysql/

MySQL vs PostgreSQL

原文:https://towardsdatascience.com/mysql-vs-postgresql-3d48891452a?source=collection_archive---------5-----------------------

关系数据库管理系统与对象关系数据库管理系统的比较

妮可·梅森在 Unsplash 上的照片

不久前,我比较了 MySQL 和 SQLite。这既是我喜欢写的东西,也是我觉得有趣的东西。我想将它发扬光大,并将其作为深入研究其他数据库管理系统的工具。我决定学习更多关于 Postgres 的知识,并认为这种比较将有助于澄清困惑的领域。此外,通过比较,除了语法之外,似乎还有更深入的方面。

让我们开始看看 Postgres 是什么,它与 MySQL 有何不同,不要再拖延了。

什么是 PostgreSQL?

PostgreSQL 也称为 Postgres,是一个免费和开源的对象关系数据库管理系统。它可以在所有主要的操作系统上运行,并且是 ACID(原子性、一致性、隔离性、持久性)兼容的。Postgres 不仅具有各种各样的特性,还具有定制的灵活性。语法也更容易学习和初学者友好。

现在我们对 Postgres 有了一个简单的背景,让我们看看 MySQL 和 Postgres 的区别。

RDBMS vs ORDBMS

MySQL 是关系数据库管理系统(RDBMS ),而 Postgres 是对象关系数据库管理系统(ORDBMS)。在关系数据库管理系统中,数据库是基于关系模型的。这意味着所有表与另一个表至少有一个关系,没有一个表没有关系。对象关系数据库管理系统兼有 RDBMS 和面向对象关系数据库管理系统的特点。这意味着不仅表是相关和链接的,而且还有面向对象管理系统的元素,这意味着它支持诸如对象、类和继承等特性。

数据类型

除了传统的数据类型,MySQL 还支持字符串、字符、日期和时间、小数、大文本、布尔值,甚至 BLOB 类型。BLOB 是一种可以存储二进制数据的类型。另一方面,Postgres 支持上面列出的所有数据类型,甚至更多。它可以存储枚举类型、JSON 或 XML 等非结构化类型、几何类型,甚至网络类型。还支持空间数据类型。

数据库功能

当考虑将用于每一个的 GUI 时,MySQL 有 MySQL Workbench。对于 Postgres,可以使用 PgAdmin。Postgres 也使用单个存储引擎,而 MySQL 有多个。MySQL 更像是一个产品,而 Postgres 更像是一个项目。

就 SQL 功能而言,存在一些差异。一旦临时表出现这种差异。虽然两者都可以用“CREATE temporary TABLE”来创建临时表,但是只有 MySQL 在 DROP 语句中有关键字 TEMPORARY。这意味着您必须更加小心您的命名约定,因为临时表可能与常规表同名,并且因为您没有在 DROP 语句中指定“temp ”,您可能会无意中丢失数据。

在删除或截断表时,也有很大的不同。对于 Postgres,删除的表支持级联选项。这意味着它也将删除依赖于该表的任何内容。MySQL 不支持 CASCADE。类似地,对于截断表,MySQL 不支持任何级联选项。使用 Postgres,截断允许级联,重新启动 IDENTITY 将 ID 放回起始值,就像以前的数据从未存在过一样,或者继续 IDENTITY,这更像 MySQL 所做的,即使数据已不存在,ID 仍保留在同一位置。对于标识,Postgres 支持标识,而在 MySQL 中,等价的标识是一个 AUTO_INCREMENT 整数。

对于存储过程,MySQL 要求该过程用 SQL 语法编写。在 Postgres 中,过程是基于函数的,函数可以用其他语言编写,如 SQL、Python、Perl、JavaScript 或其他语言。

对于索引,只有 Postgres 提供了不同的类型,比如部分索引甚至位图索引。与 MySQL 相比,Postgres 中的触发器对于更广泛的能力也更加灵活。然而,分区在 Postgres 中更受限制,只允许范围或列表。在 MySQL 中,分区有范围、列表、散列、键甚至复合分区选项。

MySQL 不区分大小写,但 Postgres 区分大小写。这意味着如果没有适当地设置,查询可能会失败。此外,MySQL 允许 IF 和 IFNULL 语句,而 Postgres 不允许。相反,应该使用 CASE 语句。

可扩展性

当添加新的连接时,与 MySQL 的每个连接都是一个线程,而 Postgres 中的一个连接是一个进程。谈到并发性,Postgres 使用多版本并发控制(MVCC)。这是为了支持多个用户,减少锁定的机会。这是因为它实现了并行查询计划。

因为在 Postgres 中每个连接都有额外的进程,所以每个连接都需要少量的内存(大约 10 MB)。然而,Postgres 不限制数据库的大小,这使得它成为大型数据库管理的一个好选择。至于复杂性,Postgres 也更复杂,因为它允许函数、继承等等。MySQL 专注于速度和可靠性。

一个有趣的现象是,在其他方面,差距正在缩小。这很大程度上是由于 Postgres 和 MySQL 在最*的更新中解决了用户需求。事实证明,这些更新作为用户需求的标准更受期待。由于这些更新,数据库确实有相似之处,而不仅仅是不同之处。这使得决定使用哪一个有点困难。或者,这表明两个数据库都致力于解决长期存在的问题,满足需求,并且最终都是您的项目非常合适的选择。

结论

如果您正在寻找一个简单、快速、流行、可靠且易于理解的数据库,MySQL 可能是更好的选择。但是如果您正在寻找一个更大的数据库或者更多的特性和复杂性,PostgreSQL 可能是更好的选择。也许您的决定归结为支持,在这种情况下,您需要数据库提供更好的帮助。也可能你的决定是基于更多的标准或者工作预期。无论如何,这两个数据库管理系统似乎是一个公*的选择。

对于你的项目,我已经说过一百次了,这真的取决于你。你可以选择任何你需要的技术来满足你自己的需求,我的观点可能不会像他们对我的观点一样符合你的项目的目标。无论哪种选择,你比任何人都更了解你的项目,所以试着用你对两者的了解来做决定,而不是简单地了解别人的决定。

从各方面来看,我希望这个分析对你的决策有所帮助。这两种数据库管理系统似乎都有优点和缺点,所以希望您已经学到了足够的知识来选择是使用 MySQL 还是 PostgreSQL,或者甚至被鼓励去学习更多关于这两者的知识。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

查看我最*的文章:

https://medium.com/codex/graphql-vs-rest-c0e14c9f9f1 [## GraphQL 与 REST

medium.com](https://medium.com/codex/graphql-vs-rest-c0e14c9f9f1) https://python.plainenglish.io/build-your-own-plex-client-using-python-11cf2e566262 https://python.plainenglish.io/giving-django-another-shot-3e6f786b13f3 https://python.plainenglish.io/renpy-a-simple-solution-to-building-visual-novel-games-32d6179a7840

参考资料:

https://www.xplenty.com/blog/postgresql-vs-mysql-which-one-is-better-for-your-use-case/ https://developer.okta.com/blog/2019/07/19/mysql-vs-postgres https://www.postgresqltutorial.com/postgresql-vs-mysql/ https://www.enterprisedb.com/blog/postgresql-vs-mysql-360-degree-comparison-syntax-performance-scalability-and-features https://www.postgresql.org/docs/11/datatype.html https://www.postgresql.org/about/ https://pediaa.com/what-is-the-difference-between-rdbms-and-ordbms/#:~:text=The main difference between RDBMS,store and manage data efficiently.&text=ORDBMS has features of both RDBMS and OODBMS

MySQL vs Redis

原文:https://towardsdatascience.com/mysql-vs-redis-def3287de41?source=collection_archive---------12-----------------------

DBMS 与内存中数据存储的比较

照片由王思然·哈德森Unsplash 上拍摄

需要改变一下节奏,我决定回到 MySQL 系列。我已经将 MySQL 与许多其他流行的数据库进行了比较,但是看看前十名,我仍然没有涉及 Redis。不可否认,Redis 是另一个我以前没有听说过的资源。好吧,不完全正确。我听说过此事,但只是路过。只有名字和一些基本信息。例如,我对 Redis 唯一真正的背景知识是它是一个 NoSQL 数据库。但是我很想了解更多的细节,或者至少在 Redis 上获得更多的知识。目前,Redis 将是我们了解更多数据库。

因此,在我们典型的 MySQL vs 格式中,让我们先来看看 Redis 是什么,以及它的一个小背景。然后,我们可以比较 MySQL 和 Redis 之间的一些总体差异。

什么是 Redis?

Redis 是一种数据结构存储,可以用作数据库、缓存甚至消息代理。存储结构是开源的和内存中的。它的总部也在 NoSQL。这意味着它允许像字符串、散列、列表、集合、数据集排序、位图等数据结构。它具有 NoSQL 数据库的优势和能力。Redis 也有事务、不同级别的磁盘持久性和内置复制。

Redis 还允许您运行原子操作,比如增加散列中的值,甚至推送列表中的元素。它也是根据 BSD 许可的。因为 Redis 在内存中,所以您必须考虑是否要备份或“持久化”数据。如果您选择不这样做,您仍将拥有联网的内存缓存。但是,如果您选择备份数据,您将决定是将数据集转储到磁盘,还是将命令追加到基于磁盘的日志。但是关于背景已经足够了,让我们看看 Redis 和 MySQL 之间的区别,这样我们可以更好地理解数据库。

数据库功能

首先,让我们看看每一个都是用什么语言写的,作为一般背景。正如我们之前可能谈到的,MySQL 是用 C 和 C++编写的。然而,Redis 是用 ANSI 和 C 语言编写的。但是我们将讨论的最重要的区别是数据库的类型。我们知道,MySQL 是一个关系数据库。Redis 是一个 NoSQL 数据库,它是一个键值存储。在键值数据库中,数据像 JSON 对象一样存储。有一个键,这个键对应一个值。与其说是一份记录,不如说是一份文件。最大的区别在于,您不必像在关系数据库中那样关联表。相反,可以有大量灵活的文档集合或多个集合,它们不需要有任何公共链接。这意味着您不需要传递外键来使数据库工作。这也意味着 MySQL 实施参照完整性,而 Redis 没有。

在 MySQL 数据库中,它遵循一个定义好的模式。这是一个固定的模式。在 Redis 数据库中,数据模式是免费的。Redis 也不支持触发器,而 MySQL 允许触发器。MySQL 支持 XML 数据格式,而 Redis 不支持。当涉及到索引时,两者都允许它们。然而,MySQL 支持二级索引,没有任何限制,而 Redis 只支持带有 RediSearch 模块的二级索引。

管理

在本节中,我们将比较如何保持数据的完整性以及如何备份数据。

对于分区,MySQL 使用 MySQL 集群或 MySQL Fabric 的水*分区或分片。在 Redis 中,只允许分片,可以是自动的基于散列的分片,也可以是手动的使用散列标签的分片。对于复制,MySQL 可以使用多源或源副本复制。Redis 还支持源副本复制,并允许链式复制。对于 Redis 中的多源复制,它仅在 Redis Enterprise Pack 中可用,这是一个付费包。

MapReduce 是一种允许 API 用户定义 map/reduce 方法的功能。它不是 MySQL 中使用的特性,但是 Redis 允许通过 RedisGears 使用它。两者都有某种类型的并发性。在 MySQL 中,是通过表锁还是行锁,这取决于使用的是哪种存储引擎。对于 Redis,并发性是由服务器序列化的数据访问定义的。

就每个数据库的持久性而言,我们正在寻找使数据持久的支持。MySQL 支持这一努力。因为 Redis 在内存中,所以它的持久性看起来有点不同。Redis 不是简单地允许数据持久化,而是允许通过操作日志甚至快照来配置提供数据持久化的机制。

关于交易后数据的完整性,我们知道 MySQL 是 ACID(原子的、一致的、隔离的、持久的)兼容的。然而,Redis 只是部分符合 ACID 标准。正如我们之前谈到的,它是耐用的。Redis 也有脚本和命令块的原子执行,但是使用乐观锁定。

连接

我们将讨论的第一个连接是您可以用来连接数据库的方法。MySQL 使用 ADO.NET、JDBC 和专有的本地 API。Redis 使用 RESP,这是 Redis 序列化协议。

对于用户访问,我们知道 MySQL 有用户授权。在 Redis 中,有基于密码的身份验证、访问控制列表(ACL)、LDAP 和基于角色的访问控制(RBAC )(如果使用 Redis Enterprise)以及相互 TLS 身份验证。

结论

Redis 是一种数据结构存储,可以用作 NoSQL 数据库。一个很大的优点是键值结构,它允许存储不需要在多个表或集合之间实施引用完整性的文档。但是,因为它位于内存中,所以存储空间有限,这并不适合扩展。如果你需要一个流行的 NoSQL 数据库,Redis 可能是一个很好的选择。但是,如果您需要一个模式结构的数据库来实现引用完整性,或者至少是 ACID 兼容的,MySQL 可能是您更好的选择。

现在,我希望您觉得这个比较有用。欢迎对您使用过 Redis 数据库的任何项目发表评论。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

看看我最*的一些文章:

https://python.plainenglish.io/searching-for-text-in-those-annoying-pdfs-d95b6dc7a055 https://miketechgame.medium.com/one-year-of-writing-on-medium-d4d73366e297 https://python.plainenglish.io/web-scraping-with-beautiful-soup-1d524e8ef32

参考资料:

https://db-engines.com/en/system/MySQL%3BRedis https://redis.io/

MySQL 与 SQLite

原文:https://towardsdatascience.com/mysql-vs-sqlite-ba40997d88c5?source=collection_archive---------7-----------------------

探索两个流行数据库之间的差异。

照片由贾瓦德Unsplash 上拍摄

作为改变,我决定回到数据库。不过这一次,我想做一点比较,而不是另一个教程风格的帖子。回想我在大学的时候,我记得有一节课我们讨论了使用 MySQL 还是 SQLite。最后,由于可移植性的原因,我们使用了 SQLite,但这让我开始思考。对话暗示 MySQL 和 SQLite 非常相似,然而,我知道事实并非如此。那么它们有什么不同呢?它们有什么相似的地方吗?所以在这篇文章中,我们将讨论这一点。MySQL 和 SQLite 有多大区别?对于您的项目,使用哪一种更好?

快速浏览对比

MySQL 和 SQLite 都是关系数据库管理系统(RDBMS)的形式。这些是基于结构化查询语言(SQL)的。此外,每一个的语法可以是相似的,并且,在我看来,一个接一个地学习并不太难。话虽如此,尽管这听起来像是非常相似的背景,但这是我们相似之处的终点。

一看背景细节

首先,作为开始,我们应该看看每一个的背景代码。对于 MySQL 和 SQLite,都使用 C 作为开发语言。也就是说,只有 MySQL 也是用 C++开发的。两者都是开源的。虽然 MySQL 是由 Oracle 管理的,但是 SQLite 的代码可以在公共领域中用于个人和商业用途。

接下来,我们可以看看它是如何运行的,或者它是靠什么运行的。MySQL 使用数据库服务器在网络上运行,然后客户端可以访问它。然而,SQLite 是所谓的嵌入式数据库。这意味着该结构存储在应用程序本身上。通过存储在应用程序上,SQLite 是可移植的并且易于移动,因为所有的表信息都位于文件中。也就是说,这也意味着网络上没有其他应用程序可以访问数据库。

SQLite 是可移植的,因此它也必须是非常轻量级的。事实上,尽管取决于系统,所需的空间可以小于 600 KiB。SQLite 也不需要预先安装或设置。此外,它还是完全独立的,因此没有外部依赖性。SQLite 有时也被称为“开箱即用的”RDBMS,因为它不需要启动或停止程序之类的配置。另一方面,MySQL 确实需要安装。它也跑得更重。运行所需的空间约为 600 Mb。也就是说,MySQL 也支持复制和可伸缩性。

但是数据类型呢?

支持的数据类型是 MySQL 和 SQLite 的一大区别。MySQL 支持多种数据类型,包括不同的数字类型、日期和时间类型以及字符串类型。如果选择得当,这允许大多数数据安全地存储在正确的类型中。另一方面,SQLite 不支持那么多类型。事实上,SQLite 只支持 NULL、integer、real、text 和 blob。如您所见,数据可能并不总是最适合这些类型之一。这样的挫折是保持 SQLite 对初学者友好和轻量级所必需的。

可扩展性和其他重要特性

正如前面已经提到的,网络中的连通性是 MySQL 和 SQLite 的一个区别。与 MySQL 不同,SQLite 是独立的,网络上的其他客户端无法访问数据库。这也扩展到多用户能力。MySQL 能够同时处理许多连接。然而,SQLite 只能处理一个连接。此外,在 MySQL 中,不同的用户可能被创建为具有一系列不同的权限,而在 SQLite 中,用户管理不是一项功能,因此不受支持。

就可伸缩性而言,有几个不同的因素需要考虑。首先,MySQL 能够处理大量数据。这可能是因为有大量不同的表,也可能是因为每个表都有许多条目。对于 SQLite,它是为运行轻量级和小型而构建的,因此存储的数据越多,效率越低,性能越差。MySQL 包含的 SQLite 没有的一个小特性是支持 XML 格式。另一个非常重要的因素是认证问题。使用 MySQL,可以创建具有权限的用户,这意味着这些用户需要经过身份验证。用户名和密码就是这样一种形式。这是为了防止外部用户能够更改或访问数据库中的任何信息。然而,在 SQLite 中,没有受支持的内置身份验证。这意味着不仅任何人都可以访问数据库,而且任何人都可以添加、更新或删除条目甚至整个表。

尽管 SQLite 可能不支持多用户可访问性,但是并发性非常有限。这意味着多个进程能够同时访问数据库,但是不支持同时进行更改。然而,MySQL 的并发性更有可能。也就是说,同时进行更改仍然会产生问题,这将使 RDBMS 中的这些问题变得相似。

安全性是 MySQL 的一个重要的特性。因为它是服务器端的,所以 MySQL 有内置的特性来防止不受欢迎的人轻易访问数据。尽管并不完美,但与 SQLite 相比,它提供了一个完全不同的世界。这是因为 SQLite 是嵌入式的,因此不具备 MySQL 作为服务器端数据库所具备的 bug 预防和其他重要的安全特性。

如何以及何时选择

总的来说,MySQL 在交易比较频繁的时候使用。它通常用于 web 和桌面应用程序。如果网络功能是必须的,也应该选择 MySQL。如果需要多个用户,如果需要更强的安全性,或者如果涉及身份验证,这也是一种选择。如果需要存储大量数据,MySQL 也是合适的选择。

当数据被预定义并在移动等应用程序上使用时,SQLite 更常用。对于这样的应用,被限制在设备的文件中不是问题,并且不需要网络。也就是说,有时候可能会选择 SQLite。如果剩余少量空间,或者如果应用程序需要存储少量数据,而该应用程序只需要最低限度地访问数据库,并且不需要大量计算,那么就会出现这种情况。我知道当我在大学做小项目时,SQLite 是快速创建数据库的好方法。这些小型独立应用程序可能不需要用户,甚至不需要应用程序以外的功能来访问数据库,这就是 SQLite 可能适合您的原因。

总的来说,这实际上取决于你使用起来是否舒服,以及你认为哪个更合适。毕竟没有人会像你一样了解你的项目。

结论

作为一种改变,我认为比较两种不同的 RDBMS,MySQL 和 SQLite,是一种有趣的尝试。它不仅给出了每一个的一点背景,而且更多的是对每一个是如何工作的理解。我们还研究了两者之间的一些主要差异,它们实际上并不像你可能会相信的那样相似。最后,我们简要地看了一下什么时候您可能想使用一个而不是另一个,尽管这更多地取决于用户和您的特定项目。我希望您能从中学到一些东西,并且发现这些信息是有用的。我知道我觉得很有趣。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

查看我最*的文章:

https://miketechgame.medium.com/giving-django-another-shot-3e6f786b13f3 https://python.plainenglish.io/renpy-a-simple-solution-to-building-visual-novel-games-32d6179a7840 https://python.plainenglish.io/organizing-my-pictures-with-mysql-and-python-ca5dee8fe02f https://medium.com/codex/all-along-ive-been-using-a-sql-antipattern-50f9a6232f89

参考资料:

https://www.digitalocean.com/community/tutorials/sqlite-vs-mysql-vs-postgresql-a-comparison-of-relational-database-management-systems https://www.educba.com/mysql-vs-sqlite/

流言终结者:古老的 SQL 数据库和今天的实时分析

原文:https://towardsdatascience.com/mythbusting-the-venerable-sql-database-and-todays-real-time-analytics-a6abfa35728e?source=collection_archive---------20-----------------------

不是你父亲的甲骨文集群,但更好。

图片作者。

我们都知道软件创新的闪电般的速度。

给我看一个已经存在十年的技术或*台,我会给你看一个过时的遗迹,它已经被更快、更高效的竞争对手超越了。因此,我不会责怪你抵制我的信息,即在 80 年代成熟的 SQL 数据库今天仍然在将数据驱动的公司从批量分析转向实时分析方面发挥着关键作用。

这可能会令人吃惊。在许多技术领域,SQL 数据库仍然是 Oracle 或 DB2 等传统本地数据库的同义词。许多组织已经放弃了 SQL 数据库,认为它们不可能满足现代数据应用程序的苛刻要求。但是没有什么比这更偏离事实了。

在本文中,我们将探讨一些关于 SQL 数据库的常见误解。希望我们能够理解 SQL 数据库如何不必受过去的限制所束缚,使它们在实时分析的时代仍然非常重要。

来自 Pixabay拉姆德隆的照片

SQL 数据库简史

SQL 最初是由 IBM 的研究人员在 1974 年开发的,用于其开创性的关系数据库 System R。System R 只能在 IBM 的大型机中运行,这些大型机在当时非常强大,而且非常昂贵,除了 NASAs 和 NOAAs(国家海洋和大气管理局,负责国家气象局)之外,任何人都无法使用。

SQL 真正腾飞是在 20 世纪 80 年代,当时 Oracle 公司推出了基于 SQL 的数据库,可以在更便宜的小型计算机和服务器上运行。其他竞争对手如微软(SQL Server)和 Teradata 也紧随其后。随着时间的推移,不同风格的 SQL 数据库被添加进来。数据仓库出现在 20 世纪 90 年代,开源数据库,如 MySQL 和 PostgreSQL,在 90 年代末和 21 世纪初开始使用。

我们不要掩盖这样一个事实:SQL 作为一种语言,仍然非常流行,是数据世界的通用语言。根据 2020 年栈溢出调查,它在所有编程语言中排名第三,54.7%的开发者使用

鉴于他们丰富的遗产,您可能会认为工程团队会倾向于尽可能多地构建 SQL 数据库。然而,当我与首席技术官和工程副总裁交谈时,我不断听到关于 SQL 数据库不可能很好地支持实时分析的三个神话。让我们逐一解决这些神话。

误解 1: SQL 数据库不支持大的流写速率

在实时分析成为梦想之前,第一批 SQL 数据库是在单台机器上运行的。随着数据库规模的增长,供应商对它们进行了重写,以便在服务器集群上运行。但这也意味着数据必须分布在多个服务器上。面向列的数据库将按列进行分区,每列存储在特定的服务器上。虽然这使得从列的子集检索数据变得高效,但是写入一条记录将需要写入多个服务器。面向行的数据库可以进行范围分区,并将所有记录保存在一台服务器上。然而,一旦使用了由不同键划分的辅助索引,我们将再次面临这样的问题,即必须向存储主表和辅助索引的不同服务器写入单个记录。

因为单个数据记录被发送到许多机器上进行写入,所以这些分布式数据库,无论是面向行还是面向列的,都必须确保数据在多个服务器上以正确的顺序得到更新,以便较早的更新不会覆盖较晚的更新。这通过两种技术之一来保证:分布式锁或两阶段锁和提交。虽然它确保了数据完整性,但分布式两阶段锁给 SQL 数据库写入带来了巨大的延迟——如此之大,以至于激发了针对快速数据写入进行优化的 NoSQL 数据库的兴起,如 HBase、Couchbase 和 Cassandra。

较新的 SQL 数据库以不同的方式构建。它们针对实时分析进行了优化,通过使用一种称为文档分片的替代存储技术,避免了 SQL 数据库过去的问题。当一个新的文档被接收时,一个文档分片的数据库会立刻将整个文档写到最*的可用机器上,而不是将其分割开来,然后将不同的字段发送到不同的服务器上。文档的所有二级索引都本地驻留在同一服务器上。这使得存储和写入数据非常快。当一份新文件到达系统时,该文件的所有字段和该文件的所有二级索引都存储在一台服务器上。不需要为每次更新进行分布式跨服务器事务。

这也让我想起了亚马逊如何以最快的速度在仓库中存储物品。不是把所有的笔记本电脑放在一个过道里,把所有的吸尘器放在另一个过道里,而是把大多数物品存放在最*的随机位置,与不相关的物品相邻,尽管会被亚马逊的库存软件跟踪。

除了文档分片,新的实时 SQL 数据库支持超快的数据写入速度,因为它们可以使用 NoSQL 数据库中首次出现的日志结构化合并()树结构,而不是以前的 SQL 数据库使用的高度结构化的 B 树。我将跳过 LSM 和 B 树数据库如何工作的细节。可以说,在 B 树数据库中,数据是以存储页面的形式组织的,存储页面以 B 树的形式组织,更新会对相关的 B 树页面进行读-修改-写操作。这会在写入阶段产生额外的 I/O 开销。

相比之下,基于 LSM 的数据库可以立即将数据写入任何空闲位置—不需要先进行读取-修改-写入 I/O 循环。LSM 还有其他功能,如压缩(通过删除不使用的部分来压缩数据库),但它能够灵活地立即写入数据,从而实现极高的速度。这里有一篇研究论文,展示了 RocksDB LSM 引擎相对于基于 B 树的 InnoDB 存储引擎的更高写入速率。

通过使用文档分片和 LSM 树,基于 SQL 的实时数据库可以接收和存储大量数据,并在几秒钟内使其可用。

误解 2: SQL 数据库无法处理不断变化的流数据模式

这个神话也是基于对 SQL 数据库的过时认知。

确实,所有的 SQL 数据库都要求数据结构化,或者以模式的形式组织。过去,SQL 数据库要求预先定义这些模式。任何摄取的数据都必须完全符合模式,因此需要 ETL(提取、转换、加载)步骤。

然而,流数据通常以 JSON、Avro 或 Protobuf 的形式原始和半结构化地到达。这些流还不断地传递可能与现有模式不兼容的新字段和数据列。这就是为什么传统的僵化的 SQL 数据库不能接收原始数据流的原因。

但是一些较新的 SQL 数据库可以通过实时检查数据来接收流数据。它们检查半结构化数据本身,并自动从中构建模式,不管数据是如何嵌套的。

数据类型化似乎是流数据和 SQL 数据库的另一个障碍。作为对模式承诺的一部分,SQL 要求数据是强类型的——每个值必须被分配一个数据类型,例如整数、文本字符串等。强数据类型有助于防止在查询中混合不兼容的数据类型并生成不好的结果。

传统的 SQL 数据库在创建时为数据表/模式中的每一列分配一种数据类型。像模式的其余部分一样,数据类型是静态的,永远不会改变。这似乎排除了原始数据馈送,在原始数据馈送中,由于其动态特性,数据类型会不断变化。

然而,一些实时 SQL 数据库支持一种更新的方法,叫做 【强动态类型化】这些数据库仍然为所有数据分配一种数据类型,只不过现在它们可以在极细的级别上进行分配。可以为单个列中的每个单独的值分配它自己的数据类型,而不仅仅是为整个数据列分配相同的数据类型。仅仅因为 SQL 是强类型的并不意味着数据库必须是静态类型的。编程语言(PL)已经表明,强动态类型是可能的,而且是强大的。PL 编译器和运行时的许多最新进展证明它们也可以非常高效;看看 V8 Javascript 引擎这几年的性能提升就知道了!

并非所有较新的 SQL 数据库都支持半结构化实时数据。一些数据仓库可以提取 JSON 文档数据,并将其分配给不同的列。但是,如果检测到一个空值,操作就会失败,迫使数据仓库将文档的其余部分转储到一个单一通用‘Other’数据类型中,这种数据类型很慢,不便于查询。其他数据库甚至不会尝试模式化半结构化数据流,而是将整个摄取的文档转储到具有一种数据类型的单个 blob 字段中。这也使得它们运行缓慢,难以查询。

误解 3: SQL 数据库无法在不影响查询的情况下扩展写入

这又是一个过时的神话,对新的实时 SQL 数据库是不真实的。传统的内部 SQL 数据库将用于接收和查询数据的资源紧密耦合在一起。这意味着,每当一个数据库同时增加读取和写入时,就会产生争用,从而导致两个功能都受到影响。解决方案是过度配置您的硬件,但这既昂贵又浪费。

因此,许多人转向基于 NoSQL 的系统,如键值存储、图形数据库和其他大数据工作负载,NoSQL 数据库因其在处理大规模数据集方面的性能而闻名。事实上,NoSQL 数据库也面临着与传统 SQL 数据库相同的争用问题。用户只是没有遇到它,因为大数据和机器学习往往是面向批处理的工作负载,数据集在实际查询之前就被摄取了。事实证明,当 NoSQL 数据库集群试图同时读写大量数据时,它们也容易变慢。

新的云原生 SQL 数据库服务通过将用于接收的资源与用于查询的资源分离,完全避免了这一问题,因此公司可以同时享受快速读写速度和复杂分析查询的能力。最新的提供商明确地将他们的系统设计为将接收和查询功能分开。这完全避免了资源争用问题,并使读取或写入速度在另一个扩展时不受影响。

结论

SQL 数据库已经走过了漫长的道路。最新版本融合了 SQL 久经考验的能力和效率、NoSQL 的大规模功能以及云原生技术的灵活可扩展性。先进的 SQL 数据库可以使用最新数据提供实时分析。您可以同时运行许多复杂的查询,并且仍然可以立即获得结果。也许最被低估的功能是:SQL 在数据工程师和开发人员中的持久流行使其成为贵公司最务实的选择,因为它实现了从批处理到实时分析的飞跃。

如果这篇博文有助于打破您长期以来对 SQL 的误解,那么也许是时候重新审视一下 SQL 数据库能够为您的用例带来的好处和能力了。

建模的神话:数据说话

原文:https://towardsdatascience.com/myths-of-modelling-data-speak-358805890baa?source=collection_archive---------47-----------------------

Cryteria,CC 由 3.0<https://creativecommons.org/licenses/by/3.0>,通过维基共享

数据让我们保持诚实,但它们不会说话;它们不是客观的,也从未摆脱理论的污染。

神话

说话数据的神话有很多相关的形式

  • 数据是调查和分析的自然起点,人们应该用纯洁的头脑处理数据,清除所有理论的污点
  • 数据是客观的,或者至少在某种程度上比模型更客观,没有数据的模型只是带有强烈观点气味的故事。
  • 我们通过公正地收集数据并让数据“说话”来确保模型的客观性。
  • 数据客观地指导我们构建公正的模型,只受“事实”的驱使

这是数据至上和诚实的神话。

神话的起源

莫里茨·施利克,哲学家,物理学家,逻辑实证主义的创始人。照片由西奥多·鲍尔拍摄(公共领域)

这个神话深深植根于逻辑实证主义贫瘠的哲学土壤中,这是一场围绕着 30 年代一个名为维也纳圈的排他性思想家俱乐部的哲学运动。逻辑实证主义者相信经验观察的首要地位,以至于任何陈述,如果它本身不是一个经验数据或通过对应原则与一个数据紧密联系,就会被宣布为无意义的。只有数据和逻辑,分析关系是值得讨论的,后者只有通过他们与前者的对应。

逻辑实证主义的哲学基础在第二次世界大战后遭到致命的破坏,首先是奎因对数据和分析话语之间的区别的分解,然后是波普尔对无理论观察的毁灭性驳斥,最后是库恩对科学范式在科学理解演变中的作用的描述。到 1960 年,这场运动“就像一场哲学运动一样死去了”。

但是,尽管从未打算作为对科学实践的哲学检查(更确切地说,作为对哲学实践的科学检查),科学实践者已经深深地从实证主义的毒泉中汲取了养分。具有讽刺意味的是,冲刷实证主义(奎因、库恩和社会建构主义)支柱的哲学运动巩固了实证主义作为良好科学实践典范的地位(至少在那些从未读过波普尔、奎因或库恩的科学实践者中)。

关于逻辑实证主义死亡的报道被严重夸大了。事实上,逻辑实证主义仍然存在,并且活跃在全球高中和大学的工程和物理教科书中。

为什么我们继续坚持这个神话

大多数建模神话都是由一种认真的、善意的努力伪造和助长的,这种努力是为了保护我们自己免受虚假、欺骗和自欺的伤害,数据至上和诚实的神话也不例外。

这个神话试图防范波普尔所谓的理论偏差,但最*被称为 T2 确认偏差。波普来了

…如果我们不加批判,我们总会找到我们想要的:我们会寻找,并找到证实,我们会远离,而不是看到,任何可能对我们钟爱的理论有危险的东西。用这种方法,很容易获得压倒性的证据来支持一个理论,如果批判性地对待这个理论,这个理论就会被驳倒。

我们很有理由害怕明智地选择和扭曲经验数据,为自己钟爱的理论或隐藏的议程服务,或者为了延续现有理论的主导地位并压制勇敢的挑战者。

不幸的是,我们并没有通过否认理论在数据的发现、选择和呈现中的重要作用来修正我们的理论不可避免的主观性和我们选择模型时不可避免的利己主义。

为什么这是一个神话

关于数据的首要性和真实性的神话的第一个问题是,如果没有承诺或至少愿意接受一个理论或模型,我们根本不知道观察什么或如何观察任何东西。

数据的存在要求有人发现、收集并在某种程度上处理和呈现这些数据。但是为什么是这些数据呢?如果我们真的清除了理论的污点,我们如何决定什么可能是相关的?在没有一些理论概念的情况下,我们如何处理和呈现这些数据,这些理论概念是什么,以及它们如何与手头的问题相关联?

第二个问题是,我们无法知道所有与理解和解决手头问题相关的数据对我们来说都是现成的,如果没有一些理论或模型来指导我们的搜索,我们就无法去寻找它们。

因此,没有理论,我们有太多的数据和太少的数据,但还有更多。

逻辑实证主义的根本失败不是哲学上的,而是实践上的。无论是实证主义者还是他们的科学实践辩护者都无法给出一个客观、透明的过程,更不用说一个演绎过程,通过数据的积累产生一个理论或假设。数据不会说话。如果不借助于一些理论背景,我们甚至无法解释数据。如果构建假说的手沾染了观点和理论偏见,那么清洗理论数据就毫无意义。

为什么这是个问题

当我们认为我们可以从理论承诺中独立地获取数据时,欺骗自己有什么关系吗?

我认为这很重要,原因有三。首先,理论偏差的问题仍然没有解决。最好的情况是,我们和以前一样有偏见,但是——确信我们自己有良好的数据卫生——我们说服自己没有偏见;最糟糕的情况是,我们学会了在收集数据和产生假设的过程中玩游戏,我们在一个秘密的、欺骗性的奴役中以中立和不偏不倚的方式呈现这个过程,以隐藏议程和宠物理论。

其次,这是驱动有缺陷的实践。例如,流行的“无模型”统计实践源于通过盲目坚持完全根据数据和实验进行推理来争取客观性。许多非数学学科(医学、公共卫生和经济学,仅举几个例子)的常用数学方法是统计测试,旨在揭示因果关系,而不会因致力于因果模型而污染其数据的假定纯度。

问题是,所有这些测试实际上都是建立在简单且通常非常不恰当的因果模型上的,但断然否认这一点会妨碍我们评估这些模型的适用性,并阻止我们将它们与我们的专业知识和理解相结合。

最后,这个神话阻止我们去做真正有效的事情:构建多重(最好是因果)模型,解决我们面临的问题,与我们拥有的数据保持一致,最重要的是,激发新数据和新见解的发现,从而加强我们的理解和干预。

我们应该做什么

这又是波普尔,来自他的书《客观知识:进化方法》。

每当一个理论对你来说似乎是唯一可能的,把它当作一个信号,表明你既没有理解这个理论,也没有理解它要解决的问题。

确保客观性的关键是将客观性的审查从数据的获取转移到多种理论或模型之间的竞争。

数据必然是我们的理论与世界相交的节点。它们对于理论之间的裁决是必不可少的,我们必须尽我们所能确保它们不被故意扭曲或压制。但是,通过将我们追求客观性、公正性和现实世界一致性的重点转移到多种理论之间的竞争,我们将数据从独立的幻觉中解放出来,并在理论和启发并规范它们的数据之间建立更丰富、更富有成效的关系。

图数据库中的 n 元关系

原文:https://towardsdatascience.com/n-ary-relationships-in-graph-databases-81ca596dac48?source=collection_archive---------23-----------------------

为什么超图数据库有优势

属性图模式中隐含的三元关系。图片作者。

有向图进行操作的专用图数据库处理三进制或更多(n 进制)关系非常糟糕,即使 n 进制关系在许多严肃的数据建模练习中表现出来。以上图为例,其中每个库存商品代表仓库中某个仓位的一部分。三元关系是由一系列三个二元关系(如有向图)暗示的,如 库存项目是针对 零件的。

为了有助于形象化场景,想象一个仓库,其中存放着仓库管理员必须打包和挑选的物品(零件),如下所示:

一名仓库保管员在仓库的箱子里寻找零件。图片经由Dreamstime.com授权给维克多摩根特。ID 102810076 七十四张图片| Dreamstime.com

我们的仓库管理员正在取某个仓库中被称为的零件。注意每个箱子都有一个数字。我们的数据模型涵盖了一个假设的情况,即一家公司有多个仓库,一个零件编号为“123”的零件可能存储在不同仓库的不同编号的箱子中…从而在我们的数据模型/属性图模式中形成了一个称为 StockedItem 的三元唯一关系。

如果我们将属性添加到 StockedItem,我们的图形模式就变成了属性图形,如下所示:

属性图架构。图片作者。

一个典型的图形数据库并不复杂,因为如果你知道一个 StockedItem 的 Part_Nr 你并不知道它是否支持一个关系, StockedItem 是用于 Part 的,即使它被模式的可视化所暗示。事实上,许多图形数据库甚至没有提供查看模式的工具。这是因为典型图形数据库的内部管道( 元模型 )不够复杂,不足以映射属性和关系之间的关系,和/或图形数据库被吹捧为无模式…这基本上意味着您可以对数据库做您想做的事情,并且没有强制实施许多规则来确保您的数据是一致的,并且对数据范围内的一些常见模式有意义。

这是典型图形数据库的一个已知问题,迫使人们寻找变通方法来弥补元模型中的不足。

例如,当您想要将数据插入数据库时,问题就出现了。如果你想说“123”零件在“H1”仓库中,在“悉尼”仓库中,你不能只说 与 Part_Nr 有关系(图表)【123】表示“123”零件在“Part_Nr”仓库中,以此类推,因为 StockedItem 在“T6”仓库中,而 StockedItem 在仓库 中,而没有太大的区别

我觉得在这里展示如何用典型的图形查询语言将三进制/多进制关系导入典型的图形数据库是没有意义的,因为典型的图形数据库已经过了它们的宣传周期高峰。本文提供了一个更适合数据建模者的解决方案。

全世界对图形数据库的兴趣正在下降,并在 2017 年达到顶峰。来源谷歌趋势,“图形数据库”。

超图数据库具有优势…

超图是这样一种图,其中图中的边/关系的概念被扩展,使得每条边可以连接两个以上的节点/顶点,并且边可以连接其他边。我在《走向数据科学》的中写了这些

例如,概念建模语言对象-角色建模 (ORM),可以被概念化为超图建模语言。我们在 ORM 中的 StockedItem 模型看起来像…

仓库中箱柜零件的对象-角色模型。图片作者。

请注意,StockedItem 不仅是图中一个表面上的节点,而且还是一个超边,它连接着源自真正边的关系。我们 ORM 图中的 StockedItem 是对象化的事实类型,虚线事实类型是链接事实类型。在语言学中,我们说仓库中的关系部分在 Bin 中已经被具体化StockedItem

也就是说,对象-角色建模和具有映射到对象-角色模型的元模型的数据库,具有将图的属性链接到它们各自的关系所需的所有丰满度。比如说,“123”在 Bin,“H1”,在 Warehouse,“悉尼”,自动映射到超图中相应的关系/边。

那么…我们的超图数据库在哪里?

你已经以这样或那样的方式使用它们很多年了……它们被称为 关系数据库 。关系数据库是为连接的数据而制造的,因为在关系数据库中关系是一等公民……关系属性与它们的关系联系在一起。关系数据库是关系重要的地方。

在之前的一篇文章中,我解释过关系数据库和图形数据库在概念上几乎是一样的……在概念层次上,同态接*同构。如果我们在这种情况下看我们的例子,我们得到这个原则的形象化…

对象-角色模型、实体关系图和属性图模式之间的同态。图片作者。

一种方便的图形查询/操作语言…

当您将关系数据库概念化为图形数据库时,非凡的事情是可能的。如果您可以在关系数据库上进行图形查询,那么专用图形数据库的优势就会有所减弱。

让我们看一些例子。我们把对象-角色建模超图数据库作为一个两层实现,在关系数据库上有一个对象-角色模型知识图。

当您想要将数据插入到对象-角色模型超图数据库中的 n 元关系中时,它应该不比在专用图数据库中插入属性信息更困难。例如,要确定一个零件 123 在一个名为“悉尼”的仓库中的“H1”箱柜中,应该很容易:

基于对象角色建模的超图数据库中的插入语句。图片作者。

因为关系是 hypergraph 数据库中的一等公民,所以我们应该能够立即通过节点和关系查询数据库,如下所示:

基于对象-角色建模的超图数据库的图查询。图片作者。

同样,如果我们想知道零件 123 在悉尼仓库的哪个箱子里(返回箱子,“H1”):

使用对象-角色模型知识图覆盖对关系数据库进行基于图的查询。图片作者。

因为我们的数据库将关系与属性联系在一起,所以我们可以通过引用关系来插入相同的 StockedItem 数据。

基于对象角色建模的超图数据库中 n 元关系的替换插入语法。图片作者。

也就是说,在对象角色建模 hypergraph 数据库中,您可以选择如何引用数据和关系。典型的图形数据库不提供这种选择。

图数据库中的 n 元关系

本文不是诱饵和开关,而是旨在表达一些关于图形数据库的事情:

  1. 典型的图数据库可以存储 n 元关系(边和属性),但是如果对 n 元关系使用边和属性的组合,典型的图数据库的元模型不会将属性链接到它们各自的边/关系。
  2. 关系数据库可以被概念化和查询,就像它们是一个图形数据库一样。如果您做了本文之外的功课,您会发现一些证据表明,一些关系数据库的图形查询速度比典型的图形数据库更快;
  3. 超图数据库 图数据库,顾名思义,当涉及到 n 元关系时,它们以一种超高效的方式做到这一点;
  4. 因为任何关系数据库都可以被概念化为对象-角色模型,并且因为对象-角色模型是有效的超图…你可以(再次)将任何关系数据库可视化为超图/图形数据库。

那么典型的图形数据库和 n 元关系在哪里呢?

没有什么可以阻止图形数据库供应商支持将属性链接到关系…他们可以做到这一点。在某种程度上,它改变了他们的底层数据模型,他们可能最终得到一个混合的关系/图形数据库…如果你愿意的话,一个图形数据库,或者更普遍地称为多模型数据库。然而,我们在这里看到的是,实际上任何数据库都可以被概念化为多模型数据库…但是缺少一个更复杂的元模型和图形查询/定义语言。

非常感谢阅读。如果时间允许,我会写更多关于图形数据库、对象角色建模、超图数据库和多模型数据库的文章。

  • 对于感兴趣的人来说,本文中的所有查询和数据定义都是在 SQLite 关系数据库上进行的,在元模型级别上有一个对象-角色建模超图覆盖。

朴素贝叶斯用 Python 解释课程评分预测实例

原文:https://towardsdatascience.com/naïve-bayes-explained-with-course-ratings-prediction-example-in-python-cb7d46f5ffca?source=collection_archive---------41-----------------------

Americana 使用 Canva 创建的图像

朴素贝叶斯简介

贝叶斯定理

图片截图由 Americana

贝叶斯定理是一个数学公式,它允许我们计算“反向”条件概率。当我们对一个事件发生的概率有一些先验的信念,并且想要结合这些信息来计算一个结果的条件概率时,通常会用到它。我们可以将术语定义如下:

  • P(A|B)被称为后验概率
  • P(A)是先验概率
  • P(B|A)是可能性
  • P(B)就是证据。
  • 然后,我们可以将公式重新表述为:

后验=可能性*先验/证据

朴素贝叶斯

  • 给定一组数据
  • y 取从 1 到 k 的一组有限的离散值(类别)

朴素贝叶斯应用贝叶斯定理的概念来计算 P(yi=1|xi),P(yi=2|xi) …。P(yi=k|xi)的值 P(xi|yi=1),P(xi|yi=2)…。P(xi|yi=k)和 P(x) & P(y=1)…P(y=k)

我们的预测仅仅是给出所有 P(yi=1|xi),P(yi=2|xi) …中最大值的 y 值。P(yi=k|xi)。

当处理所有这些符号时,它可能会变得混乱,将它放入分类示例将使计算更清晰。

想象一下,我们有一个经典的垃圾邮件分类问题,我们收到一封写着“购买免费食物”的邮件。与可能出现的单词列表相比,我们将 x 向量化为行向量,其中 1 出现在对应于“购买”、“免费”和“食物”的位置,否则为 0。

美国人陈使用 Canva 创建的图像

当使用贝叶斯定理时,我们可以简单地使用我们的样本估计 P(垃圾邮件)、P(购买)和 P(购买|垃圾邮件):

  • p(垃圾邮件)=样本中垃圾邮件的数量/样本邮件的总数
  • p(购买)=样本中出现“购买”的电子邮件总数/样本电子邮件总数
  • P(Buy|Spam) = P(Buy 和 Spam) / P( Spam) = 包含“Buy”一词的垃圾邮件数量/样本中的垃圾邮件总数

最后,我们取每个个体后验概率的乘积,这将给出给定电子邮件内容的特定电子邮件是垃圾邮件的概率。注意,这是模型“幼稚”的地方,它假设每个后验概率是独立的。在这种情况下,我们假设我们知道“购买”出现在电子邮件中的事实并没有给我们任何关于“免费”是否也会出现在电子邮件中的额外信息。

凭直觉思考,这个假设可能不成立。事实上,如果我们知道电子邮件包含“购买”、“食物”,我们可能会本能地将其与“销售”、“免费”、“折扣”等词联系起来。所以当我们使用这个模型时,我们需要意识到它的假设的不完美性。

使用 python 进行课程评分预测的示例

我们在这个例子中使用的数据集是 Kaggle 的“Coursera 课程回顾”数据集,可以通过下面的链接访问:

https://www.kaggle.com/imuhammad/course-reviews-on-coursera/notebooks?datasetId=915988&sortBy=dateRun&tab=profile

在我们决定如何处理这个问题之前,看看我们的数据并了解它的总体结构总是很有帮助的。上传者提供的数据集描述表明,它由学生和参与者在 Coursera(最大的在线课程提供商之一)上发布的 145 万条课程评论组成。考虑到我们有一个很大的数据集,删除缺少条目的行不太可能导致有很大偏差的结果。在删除丢失的值后,我们的数据集最终有 1,454,571 行 5 列。

为了预测课程的用户评分,我们将重点使用“评论”列作为预测器,使用“评分”列作为目标,但首先让我们探索我们的预测适合多少类别。下面的代码简单地告诉我们,数据集涵盖了 604 门课程,有 5 种可能的评级。

Sklearn 对于初学者来说非常友好,可以处理这种机器学习任务。只需使用几行代码,我们就可以轻松地构建一个模型,使用我们的训练数据对其进行训练,并根据测试数据进行预测。

首先,我们需要使用计数矢量器将评论转换成稀疏的行向量,对于没有出现在特定评论中的单词,其值为 0,如果出现在评论中,则值为 1。在这种情况下, x 变成了一个 1*108508 的稀疏矩阵,以压缩的稀疏行格式存储了 30 个元素,这为我们节省了一些内存。

然后,我们将 Xs(记录每个评论中单词出现的稀疏矩阵)和 Ys(评分)分成训练集和测试集。

最后,我们使用 MutinomialNB 来拟合我们的训练数据,并返回测试数据的分数。该模型的准确性为 81% ,乍一看可能不太令人信服,但考虑到我们本质上是使用简短的评论进行情感分析,并且人们对课程表达积极或消极态度的方式存在很大差异,这个简单算法达到的 81%是非常令人信服的。

观察分类的分布,我们可以看到大多数评级被预测在 4 和 5 左右,这是合理的,人们倾向于给予更多的正面评级而不是负面评级。

你也可以试着写一些注释的例子,测试算法是否能正确预测它!这是一个明显的 5 星评级,但如果我们加入更多模糊的词,如“令人困惑”、“干燥”,结果可能会有所不同。

我们可以通过使用 stop_words= 'english ',来尝试改进我们的模型,它删除了常用的单词,如' the ',' a ',' an ',使我们能够专注于那些实际上可以传达意思的单词。然而,最终的准确率只有 80.6%。对此的一个可能的解释是,因为大多数评级在 4 & 5 左右,在测试集注释中频繁遇到这些停用词可能会导致最终结果中有偏见的预测。因此,如果我们只是因为有相似的停用词而盲目猜测 4 或 5,那么很容易获得更高的准确性。使用 stop_word 降低准确性的事实揭示了我们原始模型中的问题。

我们可以指定的另一个试图提高模型性能的参数是 min_df,这意味着这个词只有在所有评论中出现至少 30 次时才会被考虑。这可能会使模型更具普遍性,并且避免受到错别字、俚语或特例的影响。

原来这也降低了我们模型的精度!

在这种情况下,提高模型性能的最佳方法就是查看我们在哪里分类错误,以及我们离正确答案有多远:

仔细观察前 100 个样本中的错误分类的具体情况,我们可以看到,在有些情况下,用户的评论确实非常模糊,甚至对于人来说也很难预测准确的评级,例如:

评论:考试中的一些语法错误让我看了两遍,但总的来说还不错。

预测:[3]

实际:4

该模型可能会预测较低的评级,因为它认识到了工作错误和糟糕的负面情绪内涵。

评论:很好的课程,提供的培训非常详细,易于掌握。

预测:[5]

实际:4

这个评论传达了强烈的积极情绪,我相信人类也会将其解释为五星评级。

另一方面,也存在模型预测与实际评级相差甚远的情况:

备注:ProctorU.com 系统花了两倍于本课程 3 天时间的时间才完成。在我 20 多年的 It 生涯中,这是我用过的最糟糕的生产用户系统。你应该换一个供应商。

预测:[1]

实际:5

对于人类来说,这显然是一个负面评价,但模型实际上预测它是 5 星!

总而言之,学习过程并不是一件困难的任务,几行代码就能为我们完成这项工作。更具挑战性的部分和数据科学家的工作是评估模型,查看错误分类的具体情况,找出句子的哪一部分可能会产生误导,并仔细调整我们的模型,以适应不确定性。

关注我/连接到:

领英:美国陈

insta gram:@ africccana

NAACL-HLT 2021:不容错过的六个教程

原文:https://towardsdatascience.com/naacl-hlt-2021-six-tutorials-you-cant-afford-to-miss-36bfe4908e?source=collection_archive---------43-----------------------

计算语言学协会(NAACL-HLT)北美分会拥有 2000 名与会者、50 多名知名研究员和 22%的论文接受率,是一支不可忽视的科学力量。

Manuel ArroyoUnsplash 上拍摄的照片

自 1998 年成立以来,NAACL-HLT 一直处于当代计算语言学的前沿,促进了全球科学家和专业协会之间的研究和信息交流。今年的 NAACL-HLT 定于 6 月 6 日至 11 日在墨西哥城举行。

教程时间表截图。来源:https://2021.naacl.org/program/tutorials/#t1

六个备受期待的 NLP(自然语言处理)教程已经提上日程,让我们简单看看每一个都提供了什么:

文本排序的预训练变形器:BERT 和 Beyond

❓Content.本教程将概述使用神经网络架构的文本排序,即 BERT(来自变压器的双向编码器表示)。排序的目的是从语料库中生成一个有序的文本列表,BERT 和自我监督的预训练为 NLP 提供了许多可能性。具体来说,演讲者将着眼于多阶段和直接文本排名架构,重点是处理长文档的技术,以及解决有效性与效率之间的权衡。

💡关键见解。排序问题是信息检索和问题回答的基础。由于基于 Transformer 的表示在各种 NLP 任务中表现出令人印象深刻的结果,因此应用预训练 BERT 进行排序以及减少模型参数的数量可能会很有趣。

深度 NLP 模型中的细粒度解释和原因分析

❓Content.深度神经网络(DNNs)在许多自然语言处理任务中起着至关重要的作用,其中包括机器翻译、问题回答和摘要。在本教程中,演讲者将从两个角度研究如何解释神经网络模型的组件:1 .内在分析(关于期望的语言任务);第二。因果关系分析(关于模型做出的决策)。我们将讨论模型预测的可解释性以及有助于精细解释的相关工具包。

💡关键见解。dnn 学习自然语言现象的隐式表示,这需要付出巨大努力才能在性能分析期间正确解释。该研究领域在black Xbox NLP 研讨会系列中进行调查。通过分析神经网络中的单个神经元冗余,有可能揭示神经元中各种语言属性的有意义分布。

NLP 中的深度学习和图形神经网络

❓Content.图形神经网络(GNNs)为许多 NLP 问题提供了受欢迎的解决方案;然而,将原始文本序列数据转换成图结构数据仍然存在一系列障碍。本教程将向您展示如何使用 Graph4NLP,一个最*开发的开源库,通过基于 GNN 的高级模型来克服这些 NLP 挑战。这种方法有助于在机器翻译、NLG(自然语言生成)和语义分析等领域取得进展。

💡关键见解。最*,图形神经网络受到了机器学习社区的极大关注,而 NLP 领域则专注于基于转换器的表示。类似于 TextGraphs workshop 系列,本教程提供了一个不同的观点,通过使用语言图和网络中的结构化信息以及现成的开源库来增强您的模型。

自然语言生成中的自动评估指标

❓Content.有了 DL(深度学习),对 NLG 的研究大大加速;然而,促进 DL 研究改进的 AEMs(自动评估指标)需要调整。在本教程中,演讲者将研究 AEMs 的演变以及最新的新兴趋势,并试图回答最紧迫的问题,包括:如何将 AEMs 组织成一个连贯的分类法;现有 AEMs 的缺点是什么;有什么可能的新的改善途径?

💡关键见解。评估非结构化领域中的对话代理并不简单,因为模型需要与人类的判断相匹配。幸运的是,有像 ADEMAQG 这样的方法来处理这个问题。如果你开发了一个对话系统,本教程将为改善对话流程提供可行的见解。

自然语言处理中的长序列处理

❓Content.处理长序列文档的能力对于许多自然语言处理任务至关重要,其中包括文档分类、摘要、问题回答和共指消解。同时,许多变压器(BERT 型)型号对于此目的来说太贵了。在这个带编码练习的实践教程中,演讲者将评估长序列处理和文档级表示学习的分层、基于图和基于检索的方法;概述不同的转换器和内存节省方法;并深入研究该领域正在出现的新研究。

💡关键见解。基于变压器的表示显示了大量 NLP 基准和下游应用的最新结果。然而,这些模型的训练和推理都很昂贵,考虑其他强有力的信号是有帮助的,如 SciBERTSPECTER 等。

大规模众包自然语言数据

❓Content.在基于 Toloka 六年行业经验的本教程中,我们的团队将关注使用公共众包市场的数据标记,重点关注任务设计和分解、质量控制技术和注释者选择。相关的数学背景以及许多有用的行业技巧将被揭示,随后是动手制作任务,在此期间,观众成员将能够在最大的众包*台之一上启动他们的标签收集项目,并相互分享他们的注释想法。

💡关键见解。由于机器学习方法需要越来越多的标记数据,我们需要使用大规模产生这种数据的方法。流行的评估数据集,如小队多民族和其他已经使用众包建立了——这是一个值得考虑的选择。构建众包管道是一项特殊的技能,需要练习任务分解和质量控制。动手练习给了你提高这一技能的机会。

多么棒的一套教程。还有很多东西需要探索。你呢?你对大会最期待的是什么?欢迎在评论中分享一些建议👇

参考

[1]文本排名的预训练变形金刚:伯特和超越,林志颖等 2020。

2 PARADE:面向文档重排序的段落表征聚合,李灿佳等,2020 .

[3]沙漠中的一粒沙是什么?在深度 NLP 模型中分析单个神经元,Dalvi 等人,2019 年。

4分析预训练变压器模型中的冗余,Dalvi 等人,2020 年。

[5]图神经网络综述,吴等. 2020 .

6重新评估 ADEM:更深入地了解对话回应评分,Sai 等人,2019 年。

[7] 迈向评估问题生成系统的更好指标Nema 和 Khapra 2018。

[8] SciBERT:科学文本的预训练语言模型,Beltagy et al. 2019。

[9] SPECTER:使用引用通知转换器的文档级表示学习,Cohan 等人,2020。

用我的金锤钉荷兰猪

原文:https://towardsdatascience.com/nailing-dutch-hogs-with-my-golden-hammer-f01dc86cb92d?source=collection_archive---------32-----------------------

AutoDiff 的乐趣

我偶然发现了三个荷兰人的难题。对自动微分和梯度下降有点熟悉,这立即给了我一个想法。这当然不容易,但能有多难呢?

感谢 VK 博士向我介绍了这个有趣的三个荷兰人的谜题。

拼图中不同角色和猪的插图。图片由作者提供。

关于

这篇文章描述了使用梯度下降解决三个荷兰人难题的一种方法。这不是最有效的解决方法。这只是为了好玩:)文章后面的一个应用程序可以让你使用不同的优化器来处理这个问题。

我们不会深究自动微分或梯度下降的细节,而是用它们来解决数学难题。它展示了一种在机器学习之外使用梯度下降的愚蠢方法。

荷兰人和他们的猪

谜题中的人物(排名不分先后):亨德里克、克拉斯、卡特琳、吉尔特鲁伊、科尼利厄斯和安娜。图片由作者提供。

荷兰人是一个数学难题。下面是一个简短的版本:

有三对已婚夫妇。他们是:
-丈夫:亨德里克、克拉斯和科尼利厄斯 -妻子:吉尔特鲁伊、卡特琳和安娜

你不知道这些夫妇的配对,但这里有一些提示:亨德里克买了 23 头猪,比卡特琳多

问:谁和谁结婚了?

我们将通过使用自动微分和梯度下降来解决这个问题,类似于神经网络的训练。我们将需要以下内容:

  1. 当给每个人一组猪数时,测量它离答案有多远/多*:一个误差函数
  2. 从误差函数中找出每头猪的数量如何影响误差:自动微分
  3. 一种修改输入猪数的方法,知道它们对误差的影响:梯度下降算法,优化器

本文中嵌入的应用程序包含了所有这些内容。你可以在帖子后面试试。

黄金分化锤

闪亮的金锤。图片由作者提供。

自动微分,或简称为 autodiff ,是一种计算函数导数的算法[1]。给定一个具有一组输入变量和结果输出值的可微分函数,它可以计算输出相对于每个输入的偏导数,这样做不需要任何手动推导代码。我喜欢把这些导数值看作是每个输入如何影响输出的度量。

在我看来,自学是一把巨大的锤子。它在许多领域都发挥着重要的作用。你可能熟悉它在训练神经网络时计算导数的应用。当有一个以上的值时,我们也可以称梯度的导数值为4

在我们的例子中,给定每个人的猪数,我们需要找出:

  1. 误差有多大?
  2. 最重要的是,每个人的猪数是如何影响误差的?

结合自动识别功能的合理误差函数可以回答这两个问题。我们的误差函数的框架可以这样定义:

误差函数的结构。

这个误差函数中的计算可以是所有提示的实现。正如我们将看到的,我们还可以添加更多适合这个问题的规则。

闪亮的下降指甲

图片由作者提供。

Autodiff 为每个输入值计算一个导数值,统称为梯度。它告诉我们每个输入变量对主计算的最终输出的影响,在我们的例子中,是误差函数的误差值。就其本身而言,它什么也不做。我们需要以某种方式将其应用于输入猪计数。

有许多不同的算法将梯度应用于输入变量[5]。这些算法或优化器的一个共同主题是,它们以小步骤迭代工作,每次都微小地改变输入变量。如果处理得当,误差会随着时间的推移而减小。下面是一个简单的优化/训练循环的例子:

简单训练/优化循环的例子。

我们将尝试三种不同的优化器。分别是带动量的梯度下降,RMSProp,Adam,各有特点。关于优化器的讨论超出了本文的范围,但是您可以在应用程序中尝试一下。你可能对每一个都有感觉,至少和这个谜题有关。

多维误差海洋

水中的一艘船。波高可以代表误差量,而 x,y 坐标可以代表两个独立变量,比如这个拼图中妻子和丈夫的猪数。

我们的问题由六个变量组成,每个人一只猪(暂时忽略夫妇的配对)。假设我们有一个六维空间。每个计数都可以映射到这个超空间中它自己的轴上。这个空间中的一个点将代表一组可能的 hog 值。在每个点上应用误差函数给我们一个超空间,其中每个位置的值代表给定的猪数集合的误差量。

当使用梯度下降时,我们可以把这个空间看作一个多维的误差海洋。我们随机选择一个点来放置我们想象中的船。自动挖掘的坡度用于转向。它具有这种独特的属性,可以将我们从当前位置指向误差更小的水域。我们向上冲浪,但大部分时间是在错误的多维波浪、山丘和山谷中冲浪。希望我们会在误差的小宇宙中找到一个最低值。

自动挖掘和梯度下降可以训练具有数千甚至数百万个变量的神经网络。这些微不足道的六个变量不应该是这些终极技术的对手,对吗?

给第一个想法钉钉子

我的第一个破主意。图片由作者提供。

丈夫和妻子之间的关系是答案的重要组成部分。我试图用 softmax 值来建模,这样每个丈夫最终都会有一个唯一“正确”的妻子。在优化过程中找到正确的配对很有挑战性,我无法让它工作。我们将跳过这一失败的尝试,以保持这篇博文更短。

相反,我们将通过硬连线所有可能的关系,以更直接的方式对问题建模。

正在逼*那些猪

三只雄性和三只雌性,总共有六种可能的配对:

这个谜题的所有潜在丈夫和妻子配对列表。

我们应该通过求解上述所有选项来找到正确的配对。所有六个配对选项都将被优化,但我们将只关注第五个**,因为它是来自已知解决方案【7】的正确配对。其他的配对不会汇聚成一个解决方案,但是如果你感兴趣的话,本文后面的嵌入式应用程序允许你研究它们。

让我们再次回顾一下这些提示:

1) 亨德里克买了 23 头猪多了卡特琳多了
2) 克拉斯买了 11 头猪多了格尔崔伊
3)shillingsPaidByPerson(hogs boundt byperson)= hogs boundt byperson
4)各夫

前三个提示都是一样的,不管是哪对情侣。这种关系只影响最后一个暗示"每个男人比他的妻子多付 21×3 先令

误差函数由所有可能配对的误差*方和表示。每种配对可能性都基于所有四种提示计算误差:

错误函数的伪代码。

如果我们的输入猪数和夫妻关系是正确的,误差函数将输出零,否则输出正值。

躲避的猪

一只幸运的猪。图片由作者提供。

现在我们已经有了误差计算,我们可以编写训练/优化循环:

优化循环的伪代码。

第一次训练一个模型总是令人兴奋的,这很少奏效。我持谨慎乐观的态度。结果如下:

用我们的第一个误差函数优化的动画。它接*解决方案,但从来没有达到正确的数字。

动画显示了真实解配对的误差图。误差接*于零,但从未完全达到零(标签只显示两位小数)。每对夫妇都在他们各自的误差地图中显示出来。x 轴和 y 轴分别代表丈夫和妻子的猪数。通过使用坐标作为对的猪计数来计算误差值,每个地图被着色。其他对在当前迭代中保持不变。颜色是不是普通误差而是视野中的最小误差。换句话说,黑色是所示区域内的最小误差(我们稍后将在这些地图中移动)。绿色小方块显示每对夫妇已知的正确答案。

理想情况下,我们应该看一个六维误差图。尽管如此,我希望这些 3 x 2d 地图能给我们提供一些有帮助的情况。

不用说,它不起作用。我尝试了不同的优化器,也改变了它们的参数。我找不到解决办法。你可以自己试试:

(移动用户:使用 0.5x/0.25x 按钮缩小。使用鼠标以获得最佳体验)用于优化第一个错误函数的实时应用程序,该函数未能找到正确的猪数。

通过放大,我们可以看到这个:

放大每对已婚夫妇的动画。显示值被卡住的区域。(结尾的像素化很可能是由 javascript 中十进制数的精度引起的。)

如前所述,真正的问题在于一个六维空间。因此,查看三张 2d 地图并不完全正确,但是我们可以尝试使用它们来理解问题。似乎所有三对夫妇都发现自己处于“局部最小值”6。我的假设是:夫妇在一个低误差值的口袋里。没有地方可以将它们从当前位置移开,从而进一步减小误差。我和解决方案都卡住了。

更好地瞄准猪

我们的猪数不再趋向于一个解决方案。这可能是因为我们的误差函数不能充分区分真实答案和第一个结果。我们需要误差函数中的附加要求。

我们知道最小猪数必须有一些特定的值才有效,付款也是如此。考虑到这一点,我们可以添加一个新的需求。当成本低于有效阈值时,它将强制成本与提示一致。第四个提示,“丈夫比妻子多支付 63”,分别具有(丈夫,妻子)的最小有效猪数(8,1),这导致一对夫妇的价格值为(64,1),给我们 63 的请求差。

改进的误差函数:

改进的误差函数的伪代码。当值太低时,它的目标是使每对的支付达到有效的最小值。

钉猪

是的,钉死了他们,没有血。图片由作者提供。

使用修改后的误差函数进行优化,如下所示:

修正错误函数后的优化动画。

*最后,我们得到了解决方案:

  • (32,31)猪换(亨德里克,安娜)
  • (12,9)猪换(班,卡特林)
  • (8,1)猪换(科尼利厄斯,吉尔特鲁伊)*

所有优化者都设法找到答案,有些人比其他人更快。与训练神经网络不同,亚当是收敛最快的优化器之一,这里我们有最快的标准动量梯度下降。很可能是我没有为优化器找到合适的参数(或者可能在我的代码中引入了错误)。尽管带动量的梯度下降在这里更快,但它需要仔细选择其参数(学习速率和动量)。Adam 和 RMSProp 对它们的参数都不太敏感。

尝试自己寻找解决方案:

(移动用户:用 0.5x/0.25x 按钮缩小。使用鼠标获得最佳体验)使用修复错误功能的实时应用程序优化应用程序。

余波

当所有钉着钉子的猪都被运走,市场清理干净后,我们终于有了答案。使用梯度下降来解决这个难题可能是不传统的,有点复杂,特别是当我们使用现代工具,甚至可以使用移动设备来暴力破解它的时候。更好的方法无疑是运用一些分析技巧。

但不管它是否复杂,人们可能会将这个问题视为一系列方程和一个误差函数。这告诉我,有机会通过优化找到答案。这并不容易,至少对于像我这样的业余自学爱好者来说是这样:)有趣的是,它最终成功了。每当你只是在找乐子的时候,使用你闪亮的金锤是完全可以接受的。

关于实现

自动微分需要每个变量和值的额外数据。在类似【a+b】的计算中,我们需要用附加信息来标记两个变量。实现是通过将这些变量建模为对象来实现的。

正文中的所有伪代码都显示了使用常规数学运算符的计算。实现是在 javascript 中完成的,它不支持运算符重载,因此 "y = a + b" 必须这样编程:

实际实现中的计算必须使用自定义函数,而不是常规的数学运算符。

如果您检查(代码)笔中的代码,请记住这一点。

自动区分的代码可以从笔的资源中查看。这是一个简单的实现,只支持标量值。你可以在这里读到它:

*

额外收获:用蛮力解决

我提到,用今天的设备,答案可以是蛮力的。

暴力搜索的动画效果。在我的小米米 A1 移动设备上拍摄的。

一个简单的程序可以检查每个人所有可能的猪数,并对所有六个可能的配对选项进行检查。下面的应用程序正是这样做的。一个附加条件是提前停止;如果已经得到的少数几个值(比如只有两个参与者的值)违反了要求,代码将停止尝试其余的排列。否则,这是一个简单的实现。

尝试一下点击按钮和观看进度条的快感:

使用蛮力方法解决难题的现场应用程序。

抱歉无聊的应用程序。也许它可以作为一个粗略的性能基准?😃

我想知道这个 1739 年的谜题的创造者会对这个谜题在几秒钟内被人用从我们口袋里取出的装置强行破解作何反应。我们生活在一个神奇的时代。*

[1]https://en.wikipedia.org/wiki/Automatic_differentiation

http://www.autodiff.org/?module=Applications

[3]https://www.jmlr.org/papers/volume18/17-468/17-468.pdf

[4]https://www . khanacademy . org/math/multivariable-calculus/multivariable-derivatives/partial-derivatives-and-gradient-articles/a/the-gradient

[5]https://ruder.io/optimizing-gradient-descent

6https://en.wikipedia.org/wiki/Local_optimum

[7]https://www.cantorsparadise.com/three-dutchmen-f9f08ac19d73

朴素贝叶斯分类算法

原文:https://towardsdatascience.com/naive-bayes-algorithm-for-classification-bc5e98bff4d7?source=collection_archive---------9-----------------------

多项式朴素贝叶斯模型及其 Python 实现

来源

分类是最常用的预测形式之一,其目标是预测记录的类别。对于二元分类,我们的目标是预测记录是 1 还是 0,如垃圾邮件/非垃圾邮件或流失/非流失,对于多类分类,我们的目标是预测记录的类别,如将邮件分类为主要/社交/促销等。

除了大部分时间预测我们记录的类别,我们还想知道属于感兴趣类别的预测概率。这些概率值也被称为倾向得分。我们可以为感兴趣的类别设置截止概率,对于倾向分数低于该值的记录,我们认为该记录属于该类别,反之亦然。

对于分类问题,这是一种监督学习的形式,我们从记录类别已知的标记数据开始,我们使用该数据训练我们的模型,然后将该模型应用于类别未知的新数据。

在本文中,我们将通过在 Python 中实现来了解如何使用朴素贝叶斯算法来解决多类分类问题。

我鼓励任何人查看我的 GitHub 上的 Jupyter 笔记本以获得完整的分析和代码。

贝叶斯定理

贝叶斯定理提供了一种在已知先验知识的情况下计算假设的概率的方法。

作者图片

先验概率是在收集新数据之前事件的概率,即 P(垃圾邮件)是在看到任何新邮件之前垃圾邮件的概率。

边际可能性也称为证据是证据事件发生的概率,即 P(money)是邮件文本中包含“money”的概率。

可能性是假设事件为真,证据发生的概率,即 P(money|spam)是假设邮件是垃圾邮件,邮件包含“money”的概率。

后验概率是在证据信息已经被合并之后的结果的概率,即 P(垃圾邮件|金钱)是给定邮件在文本中包括“金钱”的情况下邮件是垃圾邮件的概率。

我们可以看到,我们是用 P(金钱)和 P(金钱|垃圾邮件)从先验概率 P(垃圾邮件)计算后验概率 P(垃圾邮件|金钱)。

最大后验概率(MAP) 是后验概率最高的假设。在计算了几个假设的后验概率后,我们选择概率最高的假设。

例如:如果 P(spam|money) > P(not spam|money)那么我们可以说该邮件可以归类为垃圾邮件。这是最大可能的假设。

如何在分类中使用贝叶斯定理?

答案是天真的解决方案

精确的贝叶斯分类在技术上是不切实际的,因为我们的数据集中有许多证据变量(预测值)。当预测值的数量增加时,我们想要分类的许多记录将不会有精确的匹配。

上述等式仅显示了我们有 3 个证据变量的情况,即使只有 3 个,也不容易找到精确匹配。

天真的假设介绍了给定类变量是独立的。所以我们可以计算条件概率如下:

天真的假设

朴素贝叶斯定理

通过假设变量之间的条件独立性,我们可以将贝叶斯方程转换成一个更简单和朴素的方程。即使假设变量之间的独立性听起来很肤浅,朴素贝叶斯算法在许多分类任务中表现得相当好。

让我们看一个例子👀

来源

多项式模型的 1️⃣朴素贝叶斯分类器

多项式朴素贝叶斯分类器适用于具有离散特征的分类,例如用于文本分类的字数。它需要整数特征计数,例如应用于文本的词袋或 tf-idf 特征提取。

对于这个例子,我将使用名为“Twenty news groups”的数据集,它是大约 20,000 个新闻组文档的集合,*均分布在 20 个不同的新闻组中。

**from** sklearn.datasets **import** fetch_20newsgroups# import dataset
data = fetch_20newsgroups()
data.target_names

为了简化我们的示例,我将选择一些类别来过滤数据集。

# Selected categories
categories = [**'talk.politics.misc'**, **'talk.religion.misc'**, **'sci.med'**, **'sci.space'**, **'rec.autos']**# Create train and test dataset 
train = fetch_20newsgroups(subset=**'train'**, categories=categories)
test = fetch_20newsgroups(subset=**'test'**, categories=categories)

让我们来看一个数据例子:

**print**(train.data[5])>>>
From: rts@nwu.edu (Ted Schreiber)
Subject: Opinions on recent Alfa Spiders
Nntp-Posting-Host: mac178.mech.nwu.edu
Organization: Mechanical Engineering
Lines: 15

Anyone have any opinions on fairly recent model Alfa Spiders (86-> ) 

Reliablilty for what their class ( I'm not talking Alfa vs. Toyota corrola which is more relaible ) 

As far as I can discern, in recent years, there are 3 levels with all basically the same mechanical aspects.

Please email any responses 

Ted Schreiber
Mechanical Enginering 
Northwestern University
Tel: 708.491.5386 FAX 708.491.3915 Email: rts@nwu.edu

为了将文本数据用于任何机器学习任务,我们需要将每个字符串转换为数字向量。这一步被称为特征工程,一种方法是使用 tf-idf 矢量器。我们可以创建一个将 tf-idf 向量附加到多项式朴素贝叶斯分类器的管道。

**from** sklearn.feature_extraction.text **import** TfidfVectorizer
**from** sklearn.naive_bayes **import** MultinomialNB
**from** sklearn.pipeline **import** make_pipeline# Create a pipelinemodel = make_pipeline(TfidfVectorizer(), MultinomialNB(alpha=1))

📢多项式中的 alpha 表示加法*滑参数。如果是 0,那么就没有*滑。

⚡为什么要磨*?*滑解决了朴素贝叶斯算法中的零概率问题,即给测试集中每一个数据点分配概率等于零的问题。

# Fit the model with training set
model.fit(train.data, train.target)#Predict labels for the test set
labels = model.predict(test.data)

在用训练集拟合模型并预测测试集的标签之后,我们可以绘制混淆矩阵来评估我们的模型。

**from** sklearn.metrics **import** confusion_matrix
**import** seaborn **as** sns
**import** matplotlib.pyplot **as** plt# Create the confusion matrix
conf_mat = confusion_matrix(test.target, labels, normalize=**"true"**)# Plot the confusion matrix
sns.heatmap(conf_mat.T, annot=**True**, fmt=**".0%"**, cmap=**"cividis"**, xticklabels=train.target_names, yticklabels=train.target_names)
plt.xlabel(**"True label"**)
plt.ylabel(**"Predicted label"**)

在列上标准化的混淆矩阵(真值)

从混淆矩阵中,我们看到朴素贝叶斯分类器对于一些新闻类别表现得相当好,例如汽车、医学和空间,其中正确预测真实标签的时间为 98%、95%和 97%。然而,正如你所想象的,它在政治和宗教类别中取得了较低的结果..

如果你对文本分类感兴趣,你可以阅读我下面的文章,我展示了文本挖掘技术,并使用逻辑回归对亚马逊的美食评论数据集进行了分类。

https://medium.com/analytics-vidhya/applying-text-classification-using-logistic-regression-a-comparison-between-bow-and-tf-idf-1f1ed1b83640

结论

朴素贝叶斯分类器通常适用于初始基线分类。它们速度快,易于实现和解释。话虽如此,但它们在复杂模型中表现不佳,比如没有很好的分类。

尽管朴素贝叶斯是一个简单的分类器,但它被用于许多基于文本数据的应用中,如文本分类(如我们在示例中所做的)、情感分析(即理解一个人是正面还是负面思考)和推荐系统(即在协作过滤中,不管客户是否对特定的产品组感兴趣)。

总而言之,我们可以列出朴素贝叶斯的几个优点和缺点。

✅快速训练和预测

✅易于实现,只有几个可调参数,如α

✅很容易解释,因为他们提供了一个概率预测

❌天真地假设所有预测者都是独立的,在现实生活中并不成立

当*滑技术使用不当时,❌零概率问题会引入错误的结果。

❌:它会产生高度偏颇的估计。

我希望您喜欢阅读这篇文章并了解朴素贝叶斯算法。

如果你喜欢这篇文章,你可以在这里阅读我的其他文章 关注我上媒如果您有任何问题或建议,请告诉我。✨**

喜欢这篇文章吗? 成为更多会员!

朴素贝叶斯分类器——如何在 Python 中成功使用?

原文:https://towardsdatascience.com/naive-bayes-classifier-how-to-successfully-use-it-in-python-ecf76a995069?source=collection_archive---------2-----------------------

机器学习

算法背后的理论的详细解释,以及 6 个 Python 例子

朴素贝叶斯模型决策边界。图片由作者提供。(参见第 5 节,了解该图表是如何制作的)。

前言

只是让你知道你正在进入什么,这是一个 长故事 包含了 6 个不同的 Python 例子的朴素贝叶斯分类器的数学解释。请查看 下方的 主题列表,并随意跳转到您最感兴趣的部分。

简介

机器学习正在取得巨大的进步,越来越多的算法使我们能够解决复杂的现实世界问题。

这个故事是解释机器学习算法机制的深度系列的一部分。除了让您了解 ML 算法如何工作,它还为您提供了构建自己的 ML 模型的 Python 示例。

本故事涵盖以下主题:

  • 朴素贝叶斯分类器所属的算法
  • 关于朴素贝叶斯分类器如何工作的解释
  • Python 示例如何构建朴素贝叶斯分类模型,包括:
    1 .高斯 NB 带 2 个自变量
    2。具有 3 个类别标签和 2 个自变量
    3 的高斯 NB。分类 NB 带 2 个自变量
    4。伯努利 NB 带 1 个自变量
    5。混合 NB (高斯+分类)方法 1 —通过宁滨将连续变量转化为分类变量,然后训练一个分类模型
    6 .混合 NB (高斯+分类)方法 2 —使用连续和分类变量训练两个独立的模型,然后根据前两个模型的预测训练最终模型

朴素贝叶斯分类器属于哪一类算法?

朴素贝叶斯分类器基于贝叶斯定理,适用于不同的机器学习问题。其中包括分类聚类网络分析。这个故事将解释朴素贝叶斯如何用于机器学习树的监督分支下的分类问题。

谈到监督学习,快速提醒一下回归和分类之间的区别:

  • 回归旨在预测连续目标变量的值(例如,房屋价格)
  • 分类旨在预测分类目标变量的类别标签(例如,垃圾邮件/非垃圾邮件)

下图是交互式的,所以请确保点击不同的类别以放大并展示更多的👇。

机器学习算法分类。由作者创建的互动图表。

如果你喜欢数据科学和机器学习 ,请 订阅 每当我发布一个新故事时,你都会收到一封电子邮件。

朴素贝叶斯分类器是如何工作的?

我们先从回答下面这个问题开始。

为什么朴素贝叶斯是朴素的?

朴素贝叶斯的基本假设是预测值(属性/独立变量)彼此独立。这是一个很大的假设,因为它很容易表明,在现实生活中,变量之间往往至少存在某种相关性。正是这种独立性假设使得贝叶斯分类显得“幼稚”

尽管如此,朴素贝叶斯算法已经一次又一次地被证明在分类问题中表现得非常好,尽管假设是独立的。同时,这是一种快速算法,因为它很容易扩展到包括许多预测器,而不必处理多维相关性。

条件概率

要理解朴素贝叶斯,我们首先需要理解条件概率。为此,让我们使用下面的例子。

假设我们有一个装满红色和黑色球的桶。总共有 15 个球:7 个红色和 8 个黑色。

黑色和红色球桶。图片由作者提供。

从桶里随机挑出一个红球的概率是 7/15。可以写成P(red) = 7/15.

如果我们一次抽一个球而不替换它们,在第一次抽一个红球后,第二次抽一个黑球的概率是多少?

你可以看到上面这个问题的措辞是给我们提供了第二次尝试之前需要先满足的条件。条件是在第一次尝试中必须抽出一个红球。

如前所述,第一次尝试得到红球的概率(P(red))为 7/15。桶里还有 14 个球,6 个红色,8 个黑色。因此,下一次得到黑球的概率是 8/14 = 4/7。

We can write this as a **conditional probability**:
**P(black|red) = 4/7\.** *(read: probability of black given red)*We can also see that 
P(red and black) = P(red) * P(black|red) = 7/15 * 8/14 = 4/15.Similarly,
P(black and red) = P(black) * P(red|black) = 8/15 * 7/14 = 4/15.

贝叶斯定理

当我们知道一个反向事件的可能性时,贝叶斯定理帮助我们计算一个事件的条件概率。使用上面的例子,我们可以这样写:

如果你想检查这个的正确性,你可以把上面例子中的数字代入条件概率,你会发现两边都等于 4/7。

朴素贝叶斯分类器

现在让我们来看看上面的等式,并改变符号,使其与分类问题更加相关。

其中:

  • P(C|x) 是给定预测因子 x(属性/自变量)的 C 类(目标变量)的后验概率;
  • P(C) 是 C 类的先验概率;
  • P(x|C) 是似然,是给定 C 类的预测器 x 的概率;
  • P(x) 是预测值 x 的先验概率;
  • 小 k 只是区分不同类别的符号,因为在分类场景中至少有两个独立的类别(例如,垃圾邮件/非垃圾邮件,红球/黑球)。

实际上,只对上述等式的分子感兴趣,因为分母不依赖于 c。此外,因为属性 x 的所有值都是已知的,所以分母实际上是一个常数。

因此,将上述内容与独立性假设相结合,并考虑多个预测因素,分类方程变为:

Note, the class label predicted by the model is the one with the highest probability. E.g., if P(Class_red|X) = 0.6 and P(Class_black|X) = 0.4 then the predicted class label is 'red' since 0.6 > 0.4.

高斯朴素贝叶斯—连续属性的适应

处理连续数据时,一个典型的假设是每个类的连续值都按照正态分布(也称为高斯分布)分布。

虽然我们可以使用频率来计算分类属性的出现概率,但我们不能对连续属性使用相同的方法。相反,我们首先需要计算每个类中 x 的*均值和方差,然后使用以下公式计算 P(x|C ):

伯努利朴素贝叶斯—布尔属性的适应

如果您有二进制值属性(伯努利、布尔),那么您可以使用伯努利 NB 模型,该模型利用以下公式来计算 P(x|C):

注意属性 x 只能取值 1 或 0(真或假)。因此,根据 x 是 0 还是 1,上述条件概率结果是 P(i|C)或 1-P(i|C)。

朴素贝叶斯用法

我们已经列出了很多方程,在这一点上可能显得有些力不从心。不过,别担心。您仍然可以成功地构建朴素贝叶斯模型,而无需记住算法中使用的确切公式。

重要的部分是根据你所拥有的属性类型(独立变量),确定使用哪种朴素贝叶斯变异。这将在下一节中介绍。

如何用 Python 建立朴素贝叶斯模型?

把理论放在后面,让我们用 Python 建立一些模型。在我们进入分类和伯努利之前,我们将从高斯开始。但是首先,让我们导入数据和库。

设置

我们将使用以下内容:

让我们导入所有的库:

然后我们从 Kaggle 获得象棋游戏的数据,你可以通过这个链接下载:https://www.kaggle.com/datasnaek/chess

将数据保存到机器上后,使用以下代码接收数据:

来自 Kaggle 的国际象棋数据集的数据片段。图片由作者提供。

由于我们希望对因变量(目标变量)使用“赢家”字段,因此让我们检查它的分布情况:

象棋比赛数据赢家分布。图片由作者提供。

我们可以看到白棋和黑棋的胜率相当均衡。然而,抽奖发生的频率要低得多,这使得模型更难预测。

然而,让我们通过创建几个新字段来准备数据,以便稍后在模型中使用。

三个新派生的列被添加到 DataFrame 中。图片由作者提供。

在我们构建模型之前,最后要做的一件事是定义一个处理样本分割、模型拟合和结果报告打印的函数。调用这个函数将使我们避免重复相同的代码,因为我们将在下面的例子中构建多个模型。

1。具有 2 个独立变量的高斯 NB

让我们从一个简单的高斯朴素贝叶斯模型开始。为此,我们将使用“rating_difference”和“turns”字段作为我们的独立变量(属性/预测值),并将“white_win”标志作为我们的目标。

请注意,我们在这里有点作弊,因为总移动次数只有在比赛后才知道。因此,如果我们要在比赛开始前做出预测,我们就无法获得“回合”。然而,这仅仅是为了说明的目的,所以我们将继续使用它。

在选择了要使用的字段之后,我们将数据和算法名称传递给我们之前定义的“mfunc”函数。然后,我们打印模型性能结果以供评估。

模拟性能指标。图片作者作者

绩效指标的快速回顾:

  • 准确度 =正确预测/总预测
  • 精度 =真阳性/(真阳性+假阳性);精度越低意味着假阳性的数量越多
  • 回忆 =真阳性/(真阳性+假阴性);低召回率意味着该模型包含许多假阴性,即,它不能正确地识别大部分类别成员。
  • F1-得分 =精确度和召回率之间的*均值(对于特定用例,如果一个指标比另一个更重要,则可以应用权重)
  • 支持 =该类中实际观测的数量

对测试样本的验证告诉我们,使用该模型,我们可以在 66%的情况下正确预测白棋是否获胜,这比随机猜测要好(有 50%的机会猜对)。然而,如前所述,我们使用“回合”作为预测因素之一,实际上,在比赛结束之前,我们无法使用它。

因为我们只使用了 2 个独立变量(预测值),所以我们可以使用下面的代码创建一个图形来轻松地可视化决策边界。

朴素贝叶斯分类模型的决策边界图。图片由作者提供。

这是一张漂亮的图表,显示了以下内容:

  • 不同的颜色代表“白色胜利”(class=1)的不同概率
  • 圆点代表实际结果,蓝色代表‘白方赢’(class = 1),红色代表‘白方没赢’(class = 0)。
  • x 轴是“评级差异”,y 轴是“圈数”。

如你所见,离中心越远,预测越准确。这是意料之中的,因为排名的显著差异代表了技能水*的巨大差异。同时,围绕决策边界(prob=0.5)的预测不太准确,因为玩家势均力敌,并且有相似的获胜机会。

2。具有 3 个类别标签和 2 个独立变量的高斯 NB

接下来,让我们使用相同的自变量,但将目标改为“match_outcome”,它有三个类:

  • -1:黑方获胜
  • 0:绘制
  • 1:白方获胜

模拟性能指标。图片作者作者

正如预期的那样,该模型在预测 class=0 (draw)时遇到了一些困难,因为该类别的可用观测值数量少得多(测试样本中只有 175 个)。因此,准确率和召回率都非常低,分别为 0.18 和 0.07。

处理不*衡数据有多种方法,其中一种方法是对少数类进行过采样(在本例中,class=0)。这里就不赘述了。然而,如果你对过采样感兴趣,你可以在我之前关于逻辑回归的文章中找到一节:

3。具有两个独立变量的分类 NB

接下来是使用分类独立变量建立一个模型。我们将使用‘opening _ eco’和‘white _ id’,前者告诉我们比赛的开局棋步,后者是玩白棋的玩家的 ID。

构建分类 NB 模型与构建高斯 NB 模型非常相似,但有一个例外。Sklearn 的包要求变量为数值格式;因此,我们需要一个额外的步骤来将 type='string '的变量编码为' numeric '使用 sklearn 的顺序编码器只用几行代码就完成了。

快速注意,顺序编码器通常用于编码具有特定顺序的数据。然而,当使用 CategoricalNB 时,sklearn 中的朴素贝叶斯分类器不假定独立变量的值的顺序。因此,我们可以在这里使用顺序编码器。否则,必须使用替代编码器(例如,“OneHotencoder”)。

模拟性能指标。图片由作者提供。

我们得到了一个精度为 0.6 的模型,这比我们之前建立的高斯模型要差一些。然而,我们可以通过将连续变量和分类变量合并到一个模型中来改进它。

4。带 1 个独立变量的伯努利 NB

当我们有二元预测变量时,我们希望使用伯努利 NB 模型。对于这个例子,我们将采用一个名为“rated”的字段,它告诉我们匹配是否被评级。它是一个布尔型字段,取值为“真”或“假”

模拟性能指标。图片由作者提供。

如你所见,比赛是否被评分并不影响比赛结果。该模型的准确度和精确度都在 0.5,这意味着该模型与随机猜测一样好。

5。混合 NB(高斯+分类)方法 1

在这个例子中,我们将通过宁滨把连续变量转换成分类变量。然后,我们将根据所有这些特征训练一个分类模型。

除了使用 Pandas‘qcut’方法将连续变量绑定到 20%分位数的额外步骤之外,代码保持非常相似。

模拟性能指标。图片由作者提供。

使用这种方法将连续变量和分类变量结合起来,我们设法建立了迄今为止准确率为 65%的最佳模型。

6。混合 NB(高斯+分类)方法 2

这种方法需要更多的工作,因为我们将使用连续和分类自变量训练两个独立的模型。然后,我们将从这两个模型中获取预测概率,并使用它们来训练我们的最终模型。

由于这种方法中有几个步骤是不同的,我们将不使用我们先前定义的“mfunc”函数。这将导致代码稍微长一点。

模拟性能指标。图片由作者提供。

虽然模型结果不如前一个好,但这种方法工作得相对较好,准确率为 63.5%。我建议在构建模型时尝试这两种方法,并选择最适合您的数据的方法。

最后

朴素贝叶斯分类算法非常灵活和快速,尽管它有“朴素”的假设,但它在许多情况下确实工作得很好。这绝对是你决策科学“工具箱”里的好东西。

请随意将这个故事中的代码和其他材料用于您自己的项目。我希望我传达了朴素贝叶斯的精髓。如果没有,请让我知道如何为其他读者改进这个故事。

干杯!👏
索尔·多比拉斯

如果你已经花光了这个月的学习预算,下次请记得我。 我的个性化链接加入媒介是:

https://solclover.com/membership

你可能喜欢的相关故事:

用于文本分类的朴素贝叶斯分类器

原文:https://towardsdatascience.com/naive-bayes-classifiers-for-text-classification-be0d133d35ba?source=collection_archive---------17-----------------------

不同文本处理情况下的朴素贝叶斯分类器类型

(来源)

文本分类可以被描述为自然语言处理领域的主要分支之一。基于文本的数据集由非结构化格式化内容组成。这种本性导致他们很难提取有意义的片段。为了能够处理这项任务,选择相应的技术是至关重要的。为此,朴素贝叶斯分类器方法可以通过考虑算法的结构类型来执行。

贝叶斯定理的一般公式可以简单地强调如下。

**P (X|Y) = ( P(Y|X) * P(X) ) / P(Y)**

通过观察公式,X 和 Y 可以被接受为事件,假设 X 正在出现,而 Y 已经发生。借助于这种方法,可以提出一个事件的单个占用不影响另一个事件的推论,也称为朴素方法。

本文接下来的部分包括三种不同的方法,如多项式、伯努利、高斯朴素贝叶斯

1.多项式朴素贝叶斯

在确认特定单词在文本文档中的频率的情况下,多项式朴素贝叶斯可以被接受为分类文档的概率方法。

术语“单词包”[1]被广泛用作在朴素贝叶斯的上下文中要处理的所选文档,同时通过允许多次出现,将文档本身描述为一个包,并将纹理中的每个词汇描述为包中的项目。

为了能够正确地分类,应该预先知道该词在给定文本中的存在。这个分类器在文档中找到的单词数量的离散类型上实现得很好。这种方法的使用领域的一个例子可以是借助于在文档中分配的单词的出现来预测文档的匹配类别。

该算法的输出产生由单词集的整数频率值组成的向量。

**P(M|N) = ( P(M) * P(N|M) ) / P(N)**

2.伯努利朴素贝叶斯

伯努利或“多元伯努利” [ 2 ]朴素贝叶斯可被表达为通过利用期望文本的存在在布尔基础上生成输出的统计方法。该分类器从具有离散性质的伯努利分布 [ 3 中获取信息。

**P(M) = *1-p for M = 0, 
       p   for M = 1*****P(Mi|N)= P(i|N) * Mi + ( 1 - P(i|N) ) * (1 - Mi)**

当在给定的文档中想要检测不想要的单词或者想要标记特定类型的单词时,这种朴素贝叶斯分类器是有用的。此外,它通过生成二进制输出1–0、真-假或是-否来区别于多项式方法。

3.高斯朴素贝叶斯

对文本格式的数据进行分类的概念更倾向于使用分类类型。除了离散数据,朴素贝叶斯也可以应用于连续类型。

高斯朴素贝叶斯可用于应用于真实连续 - 数据集,而非分类离散值特征。

在公式中,带下划线的概率密度函数通过生成任何附加输入单词的概率计算而属于高斯分布。

**Probability Density Function (x, mean, stdDev) = 
(1 / (sqrt(2 * PI) * stdDev)) * exp(-((x-(mean^2))/(2*(stdDev^2))))**

原因是通过考虑一个高斯分布 [ 4 ]来实现相应的分类。

高斯/正态分布(归作者所有)

对于使用区域,具有对应连续值的单词的数据集,如高度或宽度的数据集,适合于执行高斯朴素贝叶斯算法。**

结论

朴素贝叶斯分类器在文本上下文[ 5 ]中的 检测情感垃圾邮件 领域提供了有见地的结果。对于不同的领域,对分类器的需求也有所不同,因为算法背后的数学是变化的。为了能够准确地产生正确的词类和类别,定义问题的类型是非常必要的。

非常感谢您的阅读!

参考

  1. 利用朴素贝叶斯进行文本分类
  2. 多元伯努利分布
  3. 伯努利分布
  4. 高斯分布函数
  5. 朴素贝叶斯和情感分类

朴素贝叶斯-在 Tableau 上从头开始预测客户流失

原文:https://towardsdatascience.com/naive-bayes-customer-churn-predictor-from-scratch-on-tableau-bb74d2fc8418?source=collection_archive---------29-----------------------

概念和编程语言,哪个更重要?

Jorge Franganillo 在 Unsplash 上的照片

人们争论 R、python 和 Julia 哪种语言更适合统计建模。但是如果你知道自己在做什么,那么任何语言或者软件都只是一个工具。任何语言的流利程度都不如概念本身重要。下面是朴素贝叶斯学习解释清楚,并实现了 Tableau 从零开始与数据使用- 预测银行客户流失

朴素贝叶斯是一种概率模型,通过计算变量的个体概率来分配事件的概率。

P(a|b): A 是 B 发生时客户的流失预测,其中 B 是我们数据集中的变量,如任期、年龄、信用评分。
例如,如果客户年龄为 30 岁,信用评分为 350 分,任期为 2 年,则会发生客户流失。

P(a|b) :基于个人概率计算,这就是为什么它被称为天真,因为它假设每个变量独立于其他变量。

P(b|a): 是 A 已经发生的情况下事件 B 的概率(例如,如果客户 18 岁,我们有一个已经离开银行的老客户数据集,我们可以创建一个概率,反映客户 18 岁时客户流失的概率)。这适用于所有变量,如任期,信用,分数等。

P(A) :客户流失的概率:如果我们知道 1000 个客户中有 100 个会离开银行,那么概率就是 100/1000。

P(B): 变量本身发生的概率。例如,与所有其他客户相比,某个客户 18 岁的概率是多少?

我们需要以同样的方式计算流失和保留的概率 P(a/b ),然后将两个数字归一化。所以数字较大的概率就是答案。如果规格化 P(a|b)(流失)>规格化 P(a|b)(留存)那么客户会放弃银行。

此外,我们可以修改 Tableau 上更简单的实现公式。

1-P(B)是分母,对所有变量都是相同的常数,所以我们不必计算它,因为它不会影响分析。
2-乘以多个概率(例如,P(年龄|流失)P(任期|流失)P(a)将得到一个很小的数字,并且需要大量的计算能力。一种解决方案可能是使用数学技巧,通过使用对数函数来加法而不是乘法:

Churn: LOG(P age|churn) +LOG((P tenure|churn)+LOG(P churn) Retained:LOG(P age|retained) +LOG((P tenure|retained)+LOG(P retained)

Tableau 上的实现

1 数据探索和特征工程:第一步是探索数据,找到客户流失的相关信息,并根据“偏差方差权衡”使用这些变量。因此,我们不希望使用太多变量,这会增加方差和过度拟合模型,我们也不希望基于单个变量建立一个愚蠢的模型,这会增加偏差和欠拟合。
根据我的结果,我使用了这些变量:

Income to Debt={FIXED [Credit Score],[Tenure] :sum([Estimated Salary])} Credit Score by Age= [Credit Score]/[Age]

2 我们的目标是最大限度地减少假阳性和增加真阴性,或者最大限度地减少假阴性和增加真阳性,这取决于我们希望通过分析实现的目标。
我的模型得到 5889 + 383 个不会离开银行的人,其中 5889 代表准确的预测,389 代表不正确的预测,1239+489 也是如此,其中 1239 是正确的预测,489 是不正确的预测。

表格上的逐步计算-

  1. **Churn**- if [Exited]=1 then 1 ELSE 0 END
  2. **Retained**-if [Exited]=0 then 1 ELSE 0 END
  3. **Income to Debt**={FIXED [Credit Score],[Tenure] :sum ( [ Estimated Salary])}
  4. **Credit Score by Age**= [Credit Score]/[Age]
  5. **P Churn (P(A))=**{SUM([Churn])}/{COUNT([Customer Id])}
  6. **P Retained (P(A))**={SUM([Retained])}/{COUNT([Customer Id])}
  7. **P(Income to Debt|Churn)**={ FIXED [Income to debt]:SUM([Churn])}/{SUM([Churn])}
  8. **P(Income to Debt|Retained)**={ FIXED [Income to debt]:SUM([Retained])}/{SUM([Retained])}
  9. Repear step 7 and 8 for all the selected variables,in my case**(Income to Debt and Credit score by age)**
  10. **Naive Bayes Churn**=LOG(P(Income to Debt|Churn))+LOG(P(Credit score by age|Churn))
  11. **Naive Bayes Retained**=LOG(P(Income to Debt|Retained))+LOG(P(Credit score by age|Retained))
  12. **Normalize Naive bayes Churn**=[Naive Bayes Churn]/[Naive Bayes Churn ]+[Naive Bayes Retained]
  13. **Normalize Naive bayes Retained**=[Naive Bayes Retained]/[Naive Bayes Churn ]+[Naive Bayes Retained]
  14. **Predizione**=IF [Normalize Naive bayes Churn]>[Normalize Naive bayes Retained ] THEN 1 ELSE 0 END

模型准确性检查

运行公式后,我们可以计算模型精度:

Retained Prediction=if [Prediction]=0 then 1 ELSE 0 END Churn Prediction=if [Prediction]=1 then 1 ELSE 0 END

1- 假阳性:模型预测的客户不会离开银行,但实际上确实离开了。

if { FIXED [Customer Id]:sum([Retained])} < {FIXED [Customer Id]:SUM([Retained Prediction])} THEN 1 ELSE 0 END

2- 假阴性:模型预测会离开银行,但实际上没有离开的客户。

if { INCLUDE [Customer Id],[Exited]:sum([Retained])}=1 AND zn({include [Customer Id],[Prediction]:SUM([Retained Prediction])})=0 THEN 1 ELSE 0 END

3- 真阳性:模型正确识别的未离开银行的客户数量;

if {INCLUDE [Customer Id],[Exited]:sum([Retained])}=1 AND {include [Customer Id],[Prediction]:SUM([Retained Predictor ])}=1 THEN 1 ELSE 0 END

4- 真负值 =模型正确识别的离开银行的客户数量。

if {INCLUDE [Customer Id],[Exited]:sum([Churn])}=1 AND {INCLUDE [Customer Id],[Prediction]:SUM([Churn prediction])}=1 THEN 1 ELSE 0 END

在*衡误报和漏报并根据我们的业务需求获得最佳模型后,我们可以创建一个仪表板,通过创建参数进行预测,用户可以在其中输入要使用的变量(如年龄、任期、信用评分),模型将为输入的数据计算 P(A/B)

参数变量的计算--

  1. **Income to Debt**={ FIXED [Parameters].[Credit Score]=[Credit Score],[Parameters].[Tenure]=[Tenure]:sum([Estimated Salary])}
  2. **Credit Score by Age**= { FIXED [Parameters].[Credit Score]=[Credit Score],[Parameters].[Age]=[Age]:sum([Credit Score])/sum([Age])}

所以最后,我们应该知道我们在做什么,关于模型制作和模型调整的概念应该由数学直觉支持,那么编程语言趋势的任何进步或变化都没有意义。在我看来,数据科学家的工作是使用任何可用的工具来研究和实现概念。

原文由我用意大利语发布在这里->https://www . theinformationlab . it/2021/02/25/naive-Bayes-classifier-customer-churn-predictions-da-scratch-sul-tableau/

命名实体识别的简易指南

原文:https://towardsdatascience.com/named-entity-recognition-5324503d70da?source=collection_archive---------28-----------------------

如何使用自然语言处理从文本中自动识别适当的实体

鲍勃·鲍伊在 Unsplash 上的照片

什么是命名实体识别?

命名实体识别或 NER 是一种对文本中的命名实体进行识别和分类的技术。这些实体是在词性标注名词短语分块之上的一个级别,其中代替识别语法部分;它将单词识别和分类为它们真正的实体。公认的主要类别有:

PERSON:      People, including fictional.
NORP:        Nationalities or religious or political groups.
FAC:         Buildings, airports, highways, bridges, etc.
ORG:         Companies, agencies, institutions, etc.
GPE:         Countries, cities, states.
LOC:         Non-GPE locations, mountain ranges, bodies of water.
PRODUCT:     Objects, vehicles, foods, etc. (Not services.)
EVENT:       Named hurricanes, battles, wars, sports events, etc.
WORK_OF_ART: Titles of books, songs, etc.
LAW:         Named documents made into laws.
LANGUAGE:    Any named language.
DATE:        Absolute or relative dates or periods.
TIME:        Times smaller than a day.
PERCENT:     Percentage, including ”%“.
MONEY:       Monetary values, including unit.
QUANTITY:    Measurements, as of weight or distance.
ORDINAL:     “first”, “second”, etc.
CARDINAL:    Numerals that do not fall under another type.

有很多库可以选择;这些天我选择的工具是 SpaCy。它强大的 API 和模型只需几行代码就可以使用,正如我们将在后面看到的,我们可以用它来训练我们的模型。为了展示它的威力,让我们来看看它的运行情况。

有空间的 NER

我们先从一篇 Teslarati 文章中的一段开始:特斯拉可能从纽约市获得价值 1236 万美元的 Model 3 订单

import spacy
from spacy import displacy
nlp = spacy.load("en_core_web_sm")

text = "IN THE MATTER OF a proposed contract between the Department of Citywide Administrative Services of the City of New York and Tesla, Inc., located at 3500 Deer Creek Rd., Palo Alto, CA 94304, for procuring Tesla Model 3 All-Electric Sedans. The contract is in the amount of $12,360,000.00\. The term of the contract shall be five years from date of Notice of Award. The proposed contractor has been selected by Sole Source Procurement Method, pursuant to Section 3-05 of the Procurement Policy Board Rules. If the plan does go through, the $12.36 million could effectively purchase about 274 units of the base Model 3 Rear-Wheel-Drive, which cost $44,990 under Tesla's current pricing structure."

doc = nlp(text)
displacy.render(doc, style="ent")

Spacy 有一个奇妙的能力来渲染 NER 标签与文本一致,这是一个奇妙的方式来查看在原始文章的上下文中被识别的内容。

作者图片

培训自定义实体

如果你是一名在 DC 报道华府的记者,训练有素的 NER 模特是非常棒的。然而,我们大多数人都不是。如果你在一个产品团队中,你想更新模型,以包含新的实体来映射你的业务,那该怎么办?幸运的是,这可以通过空间实现。我将使用一个开发人员在 StackOverflow 上的帖子来说明这个过程,他正在使用我公司的一个 API。在重新训练模型之前,让我们看看输出。

以前

作者图片

训练模型

从头开始训练一个新的模型或者更新现有的模型是可能的。以下示例将向您展示如何使用新实体和新现有实体下的新单词更新现有模型。我所在的行业,像许多其他行业一样,有许多特定的语言需要被涵盖,以给 NER 提供适当的背景。产品名称、新组织,对我来说,我甚至要教它什么是 API。

我们需要建立一个训练集,它可以由你创建的句子构成,或者你可以从数据集中提取它们。您可以为您想要培训的每个新实体添加一个两个示例。我还构建了一个实用函数,它简化了 Spacy 所需的tuple格式的创建。

def built_spacy_ner(text, target, type):
    start = str.find(text, target)
    end = start + len(target)

    return (text, {"entities": [(start, end, type)]})

我们可以用上面的函数传入texttargettype来获得正确格式化的元组。结果是一个列表。

TRAIN_DATA = []
TRAIN_DATA.append(
  built_spacy_ner("I work for Autodesk.", "Autodesk", "ORG")
  )

最终的格式是一个带有原始stringtuple和一个带有实体的startend位置的dictionarystring及其type中。下面是我在例子中使用的全套训练数据。我们可以看到添加了新的实体类型APISERVICEFORMAT,现有的实体ORGPRODUCT有了新的条目。

[('Model Derivative API provides translation', 
  {'entities': [(0, 20, 'API')]}),
 ('I want to create a cloud-based service to Revit Server.',
  {'entities': [(61, 73, 'PRODUCT')]}),
 ("I'm new to the Forge API unsure where a design parameter is",
  {'entities': [(15, 24, 'API')]}),
 ('I would like to automate Revit with the Design Automation API',
  {'entities': [(40, 61, 'API')]}),
 ("I've uploaded a Revit model to my OSS bucket.",
  {'entities': [(34, 37, 'SERVICE')]}),
 ('Autodesk Forge is my Platform of choice',
  {'entities': [(0, 14, 'PRODUCT')]}),
 ('The native file format for Revit is RVT.',
  {'entities': [(36, 39, 'FORMAT')]}),
 ('I work for Autodesk.', 
  {'entities': [(11, 19, 'ORG')]}),
 ('The Model Derivative API used in conjunction with the Viewer',
  {'entities': [(4, 24, 'API')]}),
 ('Changes are sent to a central BIM 360 server.',
  {'entities': [(30, 37, 'PRODUCT')]}),
 ('All of this is possible on IFC.', 
  {'entities': [(27, 30, 'FORMAT')]})]

注:我经历(和阅读)的一件事是,如果你提供了太多的文本示例,它会过拟合,最终除了你训练过的示例之外,什么也认不出来。我开始尝试训练整个DataFrame,但是它基本上消除了预先训练的实体。

有了训练数据后,我们需要用新的实体更新可用的实体。

# adding a named entity label
ner = nlp.get_pipe('ner')

# Iterate through training data and add new entitle labels.
for _, annotations in TRAIN_DATA:
  for ent in annotations.get("entities"):
    ner.add_label(ent[2])

接下来,我们需要训练模型。我们首先要确保我们只通过选择与ner相关的pipe_names来更新 NER 型号。然后,我们遍历训练数据,利用Example函数,并用每个新实体更新 NER 模型。

# creating an optimizer and selecting a list of pipes NOT to train
optimizer = nlp.create_optimizer()
other_pipes = [pipe for pipe in nlp.pipe_names if pipe != 'ner']

with nlp.disable_pipes(*other_pipes):
    for itn in range(10):
        random.shuffle(TRAIN_DATA)
        losses = {}

        # batch the examples and iterate over them
        for batch in spacy.util.minibatch(TRAIN_DATA, size=2):
            for text, annotations in batch:
                doc = nlp.make_doc(text)
                example = Example.from_dict(doc, annotations)
                nlp.update([example], drop=0.35, sgd=optimizer, losses=losses)

print("Final loss: ", losses)

这是它的基础。在为您的生产全面训练模型时,您应该阅读 Spacy 文档,以了解如何将其部署到生产环境中。

在...之后

最后,让我们尝试使用新模型再次处理我们的文本。

doc = nlp(text)
displacy.render(doc, style="ent", jupyter=True)

作者图片

我们可以看到更新后的结果正确地标记了APIs,它现在正确地捕捉了 Autodesk ForgeRevitPRODUCTS,最后, IFC 被列为ORG,这应该是基于训练的。这些结果显示了调整 NER 模型以满足你的短期实验的特定需求的前景。

NER 与 NLTK

自然语言工具包 (NLTK)也提供了 NER 功能。让我们看看上面的原始段落,并通过 NLTK 的 NER 运行它。

for sent in sent_tokenize(text):
   for chunk in ne_chunk(pos_tag(word_tokenize(sent))):
      if hasattr(chunk, 'label'):
         print(chunk.label(), ' '.join(c[0] for c in chunk))
ORGANIZATION Department
ORGANIZATION Citywide Administrative Services
ORGANIZATION City
GPE New York
PERSON Tesla
PERSON Palo Alto
PERSON Tesla Model
PERSON Award
PERSON Sole Source
ORGANIZATION Procurement Policy Board Rules
PERSON Tesla

NLTK 似乎没有为这个特定的文本标记项目以及空间。几个区别只有三种类型的标签被识别,其中 spacy 有cardinaldatemoneylaw都从相同的文本中被识别。此外,帕洛阿尔托特斯拉被错误地识别为人和其他几个被错误标记的物品。我的经验是,虽然 NLTK 肯定功能齐全,但 Spacy总体表现更好。

结论

我希望您喜欢这个快速浏览,尤其是用不同的实体来训练 NER 模型的能力,这些实体为您的用例改进了 NER。本文中使用的完整源代码可以在 GitHub 上获得。

如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑报名成为一名媒体成员。一个月 5 美元,让你可以无限制地访问成千上万篇文章。如果你使用我的链接注册,我会赚一小笔佣金,不需要你额外付费。

IEEE 文摘的命名实体识别

原文:https://towardsdatascience.com/named-entity-recognition-of-ieee-abstracts-be57d5e881d7?source=collection_archive---------30-----------------------

实践教程

哈佛 IACS 顶点报告

作者: 宝琳娜·托罗·伊萨约翰·阿林,吴悠,贾斯汀·克拉克

顾问:克里斯托弗·坦纳教授,艾萨克·斯拉维特

https://www.capstone.iacs.seas.harvard.edu/

海报展示链接:https://drive . Google . com/file/d/1d 9 D1 omeamahf 6 qhdlsqjuzps 6 kxdgxfr/view?usp =共享

问题陈述

电气和电子工程师协会(IEEE)在电气和电子工程、电信、计算机工程和相关学科方面出版了世界上令人震惊的 30%的文献。这些出版物往往包含有特色的实体,如科学概念、技术产品和研究机构的名称。提取这些实体可以为其大型文本语料库提供高水*的概述,这将使研究人员能够快速发现具有高度相关或相似内容的论文,并允许商业利益相关者检测出版趋势。

我们的项目旨在解决两个任务:

命名实体识别

我们将使用命名实体识别(NER)自然语言处理任务来识别 IEEE Xplore 摘要中的命名实体。三个感兴趣的实体类型是:方法产品组织。图 1 展示了随机抽取的抽象上的任务。

图一。标有方法、产品和组织实体的示例文本(作者提供照片)

共指消解

我们将通过共指解析从上面发现的实体中提取唯一的实体,共指解析是一种 NLP 技术,它将引用同一实体的表达式聚集在一起。

探索性数据分析

IEEE Xplore 是 IEEE 的数字白皮书存储库,包含大约 500 万份出版物。这些论文分布在许多研究领域,从计算机科学到病毒学。对于这个项目,我们只看这些出版物的摘要。我们通过托管在关系数据库实例上的 Microsoft Academic Graph (MAG)的快照来获取摘要。MAG 是一个包含出版物元数据的学术出版物异构图形数据库。MAG 上总共有 478 万份 IEEE 摘要。我们还收到了 1,300 份摘要,上面标有方法、产品和组织。在本文的其余部分,我们将把它称为继承数据集。

对数据集的探索性分析表明,IEEE 出版物在研究领域(如计算机科学、政治学)方面严重倾斜。超过 94%的 IEEE 论文涉及计算机科学、工程、材料科学和物理学。图 2 和图 3 比较了在 MAG 数据库和继承数据集中 IEEE 出版物按研究领域的分布情况。继承的数据集从工程领域过度采样,从不太常见的领域(如艺术、历史和哲学)采样不足。

图二。继承摘要与所有 IEEE 摘要中前 5 个领域的比例(作者照片)

图三。继承摘要与所有 IEEE 摘要中剩余字段的比例(作者照片)

我们将继承数据集中的标记摘要映射到它们的出版研究领域(例如,计算机科学、医学),并绘制每个领域中标记实体的数量。图 4 显示了每个实体类的出现在不同学科之间有显著差异的证据。例如,注释者倾向于选择数学、生物学或地质学摘要中的方法,而产品更可能出现在计算机科学或化学摘要中。

图 4 。每个研究领域摘要中的*均注释实体(作者照片)

图 5 显示了从 1879 年到 2019 年每年的 IEEE 摘要数量。自 2000 年以来,出版物的数量急剧增加,而且这一趋势没有减缓。科学研究领域的快速发展意味着旧论文中的技术术语和语言使用会很快过时。为了具有前瞻性,我们的目标是在数据库中更新的摘要上训练我们的模型。

图 5 。每年 IEEE 出版物数量(1879–2019)(作者照片)

我们的探索性数据分析使我们确信,1,300 个继承的摘要并不构成 IEEE 数据库的代表性样本。更大的研究领域被过度采样,我们发现证据表明实体并不是均匀分布在各个领域。这激发了创建具有出版领域代表性的样本的需求。我们还希望将我们的分析集中在更新的抽象上,这是继承的数据集所不具备的。此外,在查看了带注释的数据集并与 IEEE 讨论后,我们发现标记方案不一致,并且不完全可重复。因此,IACS 团队决定创建一组新的标记数据。

新 IACS 标注数据集

我们标记的数据集有两个目标:

  1. 在研究领域代表 IEEE 摘要
  2. 具有可重复的一致标签方案

对于第一个目标,我们确保从数据库中取样,使得研究领域的样本分布遵循实际分布。

表 1 。每个研究领域提取样本的百分比(作者照片)

我们还希望将我们的分析集中在较新的摘要上,同时仍然考虑较旧的摘要。

表二。每个时间段提取的样本百分比(作者照片)

对于第二个目标,我们与 IEEE 密切合作来定义实体类,并创建了一套注释指南。然而,正如我们将在后面讨论的,这是一项具有挑战性的任务,对模型性能有着重大的影响。

IACS 数据集总共有 1050 个由 4 个标注者标注的摘要。

命名实体识别

建模方法

对于命名实体识别(NER)任务,我们采用了基于 BERT 的模型。BERT(来自变压器的双向编码器表示)[1],顾名思义,是一个基于变压器的语言模型,利用双向训练。该模型是根据对大量文本的自我监督训练开发的,特别是来自图书语料库的 8 亿个单词和来自英语维基百科的 2500 万个单词。它接受了掩蔽语言模型(MLM)和下一句话预测(NSP)任务的训练,在训练过程结束时,BERT 具有语言处理能力,可以实现下游监督学习任务,如 NER。

转换器包含两种机制:一种是读取文本输入的编码器,另一种是为任务做出预测的解码器。BERT 仅使用编码器机制来生成单词之间的上下文关系。一系列单词(记号)被传递到模型中,嵌入到向量中,并在神经网络中进行处理。输出是一个向量序列,每个向量对应一个令牌。双向训练指的是与从左到右顺序读取输入文本的定向转换器相反,BERT 读取输入文本的左右上下文。(图 6)

图 6 。左至右转换器的预训练架构(左)与 BERT(右)。在所有层中,BERT 表示由左右上下文共同决定。1

对于 MLM 任务的训练,伯特屏蔽了输入中 15%的单词来进行预测。由于用于评估损失函数的输入百分比如此之小,因此与其他方法相比,BERT 趋于收敛得更慢。BERT 还通过将两个句子配对在一起来训练下一句预测,50%的时间是后续句子,50%的时间是随机配对。这允许模型学习句子连续性。

我们评估了两个模型:(1)根据来自书籍语料库和英语维基百科的通用文本进行预训练的 BERT,以及(2)根据来自语义学者的科学文本进行预训练的 SciBERT 2。18%的数据集来自计算机科学领域,82%的数据集来自广泛的生物医学领域。在基于 BERT 的词汇和 SciBERT 词汇之间有 42%的重叠,说明了科学和一般领域文本之间在常用词方面的实质性差异。

多类别到多标签场景

对于我们的 NER 任务,我们在预训练的 BERT 模型之上添加了一个令牌级分类器。分类器为每个单词标记预测一个实体类(方法、产品、组织或无)。我们从一个多类 NER 任务开始,但是后来意识到我们的问题是一个多标签的问题。也就是说,我们应该能够将一个单词标记分为多个类别。例如,“IEEE Xplore”中的“IEEE”应同时标注为组织(因为它是组织的名称)和产品(因为它是正式产品名称的一部分)。我们重新注释了数据集,并对原始的多类模型做了一些修改。我们现在预测一组类,而不是为每个单词标记预测一个单独的类。数组中的每个元素都是一个二进制标志,表示该类中的成员。我们还将损失函数从交叉熵损失改为二元交叉熵损失。

结果

对于 BERT-Base 和 SciBERT 模型,我们将 60%的标记数据用于训练,20%用于验证,20%用于测试。我们使用 Optuna 来调整训练集和验证集上的模型超参数,并使用最佳超参数集来评估测试集上的模型。图 7 绘出了训练步骤中的二元交叉熵损失。

7 。BERT-Base(左)和 SciBERT(右)在训练步骤中的损失(作者拍摄)

表 3 报告了每个实体类别的 F1 分数。我们在包含 200 个测试样本的 IACS 多标签数据集上报告了 BERT-Base 和 SciBERT 模型的 10 倍交叉验证 F1 分数。

T2 3。每个实体类的 BERT-Base 和 SciBERT 模型的 F1 分数。报道了超过 10 倍的*均值和标准偏差。(作者供图)

表 3 中的交叉验证结果表明,我们的模型性能在运行中通常是一致的,尽管 BERT-Base 模型在组织类的性能方面有较大的差异。

共指消解

建模方法

共指解析是指对同一实体的引用的解析。这些参考资料有多种形式。对于这个项目,我们感兴趣的是通过名称或缩写来引用同一个实体,例如"麻省理工学院"和"麻省理工学院"或" k-最*邻"和" kNN "。

在回顾 IEEE 摘要时,很明显这些缩写中的许多至少在文本中定义过一次。定义几乎都是“我们使用 k-nearest neighbors (kNN)来对我们的记录进行聚类”的形式,其中缩写在它缩写的短语后面的括号中。在我们的注释指南中,我们决定当这些缩写出现时,应该选择它们作为实体的一部分。这意味着在我们带注释的摘要中识别这种模式并解析出缩写和完整形式是一项相当容易的任务。我们在 Method 类的 3,074 个标签中发现了 339 个这种形式的实例。

对于每个实体类,我们然后获取所有标记的实体加上这些解析的实体,并成对地进行比较,以找到彼此相似的实体和缩写。我们需要执行的比较的数量大致与实体标签的数量成二次方关系,所以我们需要一个非常高效的方法。我们考虑了一种对位置敏感的散列方法,例如 datasketch ,但是最终使用了一种更快更精确的解决方案【3】,就像在 Python 包 SetSimilaritySearch 中实现的那样。这个实现要求每个实体标签被表示为一个无序的集合,我们选择通过向下压缩和基于字符的 2-瓦片区来构造它。比如“马尔可夫”就变成了(“ma”、“ar”、“rk”、“ko”、“ov”)。然后我们使用上面的包找到所有 Jaccard 相似度大于 0.85 的对。为了将所有这些成对比较转化为聚类,我们创建了实体标签的网络图,并将每个发现的对添加为边。为了提取聚类,我们简单地提取了图的连通分量。

。我们的共指解决程序的图解(由作者拍摄)

结果

为了评估性能,我们检查了为每个实体类创建的所有分类,并识别了错误分类的实体标签。作为错误聚类的一个例子,考虑这种方法聚类:“SA”、“模拟退火”、“模拟退火(SA)”、“球面像差”和“球面像差(SA)”。很明显,“模拟退火”和“球面像差”不是指同一个过程,但我们的方法将它们聚集在一起,因为它们都缩写为“SA”。对于每个实体类,只有不到 4%的实体被错误聚类,我们认为这是很好的性能。详情参见表 4。

表 4。共指消解的聚类性能(作者图片)

讨论

回顾伯特模型预测

我们回顾了基于 BERT 的模型对人类标签的预测。图 9 显示了我们的模型做出的良好预测的示例。BERT-Base 和 SciBERT 都成功地将相同的实体及其对应的类识别为人类注释器。

图九。BERT 和 SciBERT 预测准确的样本摘要(作者提供照片)

当我们查看模型的故障模式时,我们注意到 BERT 和 SciBERT 都特别容易在标点符号(例如破折号或括号)和结尾的“s”处出错。很可能这些术语在文本中出现得更频繁,因此它们在模型的失败中出现得更频繁。也有可能模型在解析实体的边缘时有困难。图 10 显示了模型造成的一些错误。

图 10。BERT 和 SciBERT 错误的样本摘要(作者照片)

在第一个例子中,BERT-Base 和 SciBERT 都只捕获了实体的一部分。在第二个样本中,人类没有在这个摘要中标记任何东西,但是 BERT-Base 和 SciBERT 都选择了“信息中心网络(ICN) ”,这可能是一个实体。

基于 BERT 的研究领域预测

探索性分析的一个发现是,不同的研究领域(如计算机科学、历史)在词汇、语境和语言使用上有所不同。出于这个原因,我们确保我们的标记数据集包括人文科学、社会科学和科学的例子,以确保该模型可以适用于提交给 IEEE 的任何论文。

图 11。验证集研究领域的 F1 分数(作者照片)

上面的图 11 显示了该模型在不同的研究领域中的不同表现。我们看到,对于历史和政治科学这两个研究领域,没有方法实体,因此 F1 值为 0。在训练场上也是如此。这表明,如果我们希望更好地评估模型的特定领域性能,我们需要增加此类领域的训练样本数量。

我们也看到了依赖于注释者团队专业知识的趋势。方法实体的最高 F1 分倾向于注释团队具有丰富专业知识的领域:数学、工程和计算机科学。(哲学和地质学是离群值。)这表明注释者的专业知识对模型性能有影响。

因为像计算机科学、工程、数学和材料科学这样的领域构成了所有 IEEE 摘要以及所有训练和验证样本的大约 85%,所以这些领域对模型性能和度量具有最大的影响。method 的总体 F1 分数为 0.64,计算机科学、工程和数学的 F1 分数分别为 0.65、0.65 和 0.68。同时,材料科学的 F1 分数为 0.47。

内部标注者协议

即使在用 IEEE 定义了实体类并创建了注释指南之后,团队仍然发现很难标记摘要。有歧义(指导方针并不涵盖所有情况)和难懂的术语,团队都在努力解决。为了量化这些困难,我们测量了注释者对 50 个摘要的注释达成一致的程度。

为了使我们的注释者间协议(IAA)度量与我们的模型性能度量相当,我们将实体标签与来自我们模型的标记器的标记边界对齐。这使得我们可以将一个人类注释者与另一个人类注释者进行比较,就像我们将模型的输出与人类注释者进行比较一样。在4之后,我们查看了四个注释器的所有六个可能的对。对于每一对,我们任意选择一个注释器作为“基础事实”,并根据这个基础事实计算每个实体类的第二个注释器的 F1 值。(选择注释者作为基础事实并不重要——无论哪种方式,得到的 F1 分数都是一样的。)这个 F1 分数可以解释为第二个注释者在恢复第一个注释者的标签的任务中的表现。这实际上是模型正在执行的相同任务。

这个过程为每个实体类产生了六个 F1 值——每对标注器一个。在图 12 中,我们将这六个 F1 分数与我们最佳模型的 F1 分数进行了比较。我们可以看到,对于 Organization 和 Method 类,我们的模型比一些注释器对执行得更好,但比其他的差。None 类比其他类大得多,每个人做的都差不多。对于 Product 类,我们的模型的性能比最不一致的那对标注器稍差。从表 3 的标准偏差中可以看出,该模型的一些运行表现得比产品类别的最不一致的人对更好,尽管该模型对其他类别的表现稍差。

图 12 说明了我们的模型与人类表现相当。对于产品类来说,可能会有一些小的性能提升,但是我们已经达到了数据质量所强加的性能上限。为了进一步发展这个模型,任务和类的定义很可能需要显著的改进。

图 12。 BERT 模型 F1 性能相对于注释者对之间的 F1 协议(由作者拍摄)

参考

[1] J. Devlin,M.-W. Chang,K. Lee,K. Toutanova,“BERT:用于语言理解的深度双向转换器的预训练”,arXiv:1810.04805【cs】,2018 年 10 月,访问日期:2021 年 03 月 04 日。【在线】。可用:【http://arxiv.org/abs/1810.04805】T4。

2 I. Beltagy,K. Lo,A. Cohan,“SciBERT:一种用于科学文本的预训练语言模型”,arXiv:1903.10676【cs】,2019 年 9 月,访问日期:2021 年 3 月 04 日。【在线】。可用:http://arxiv.org/abs/1903.10676.

[3] R. J. Bayardo、Y. Ma 和 R. Srikant,“扩大所有配对的相似性搜索”,载于第 16 届国际万维网会议论文集WWW ' 07,加拿大阿尔伯达省班夫,2007 年,第 131 页,doi:10.1145/1242572.1242591

4 G. Hripcsak 和 A. S. Rothschild,“信息检索中的协议、F-Measure 和可靠性”,美国医学信息学协会杂志,第 12 卷,第 3 期,第 296-298 页,2005 年 5 月,doi: 10.1197/jamia。M1733

[5] J. Huang ,《少镜头命名实体识别:综合研究》,arXiv:2012.14978【cs】,2020 年 12 月,访问时间:2021 年 03 月 04 日。【在线】。可用:【http://arxiv.org/abs/2012.14978】T4。

6 M. Joshi,D. Chen,Y. Liu,D. S. Weld,L. Zettlemoyer,O. Levy,“SpanBERT:通过表示和预测跨度来改进预训练”,《计算语言学协会汇刊》,第 8 卷,第 64–77 页,2020 年 12 月,doi:10.1162/tacl _ a _ 00300

[7] H. Lee、Y. Peirsman、A. Chang、N. Chambers、M. Surdeanu 和 D. Jurafsky,“斯坦福大学在 CoNLL-2011 共享任务中的多遍筛选共指消解系统”,访问日期:2021 年 3 月 4 日。【在线】。可用:https://nlp.stanford.edu/pubs/conllst2011-coref.pdf

[8] J. Lee ,“BioBERT:一种用于生物医学文本挖掘的预训练生物医学语言表示模型”,生物信息学,第 36 卷第 4 期,第 1234–1240 页,2020 年 2 月,doi:10.1093/bio informatics/btz 682

[9] V. Stoyanov 和 J. Eisner,“简易优先共指消解”,载于 2012 年印度孟买的COLING 会议录,2012 年 12 月,第 2519-2534 页,访问日期:2021 年 3 月 4 日。【在线】。可用:https://www.aclweb.org/anthology/C12-1154

[10] R. B. Tchoua 等人,“用最小的人类 Effort 为科学命名实体识别创建训练数据”,访问日期:2021 年 3 月 4 日。【在线】。可用:https://tsapps.nist.gov/publication/get_pdf.cfm?pub_id=926228

NaN、None 和实验 NA

原文:https://towardsdatascience.com/nan-none-and-experimental-na-d1f799308dd5?source=collection_archive---------21-----------------------

熊猫价值观缺失的图解指南

现代技术创新经常涉及处理和分析带有缺失值的数据集。而且,为了有效地处理这些数据集,不同的库选择以不同的方式表示缺失的值。鉴于它们的重要性和频繁出现,我们将从当前的艺术状态开始,讨论它们的属性,然后按时间顺序说明在熊猫中使用的可用缺失值惯例。

图片由作者制作,使用

为了让表示缺失值,我们看到有两种方法,它们通常应用于表格或数据帧中的数据。第一种方法包含一个掩码来指出缺失值,而第二种方法使用特定于数据类型的标记值来表示缺失值。

屏蔽时,屏蔽可以是全局屏蔽,也可以是局部屏蔽。全局掩码由每个数据数组的一个单独的布尔数组组成(图 1),而局部掩码利用元素的逐位表示中的一位。例如,一个有符号整数也保留了一个单独的位,用作本地掩码来指示整数的正/负符号

图 1:全局布尔掩码方法。请注意,MV 表示缺失值。图片由作者使用制作。

另一方面,在标记方法中,定义了特定于数据类型的标记值。这可以是基于最佳实践的典型值,也可以是唯一定义的逐位表示。对于浮点类型的缺失值,库通常会选择标准的 IEEE 754 浮点表示,称为 NaN (不是数字),例如,参见图 2。类似地,有些库也为其他数据类型定义了独特的位模式,例如 R

图 2:说明了一个逐位的 IEEE 754 单精度(32 位)NaN 表示。根据维基百科,IEEE 754nan 编码为指数字段填充 1(类似于无穷大值表示),有效位字段中有一些非零数字“x”(“x”等于零表示无穷大)。这允许多个不同的 NaN 值,具体取决于有效位域中设置了哪些位,但也取决于前导符号位“s”的值。似乎IEEE 754 标准将 16,777,214 ( ⁴-2)浮点值定义为 NaNs,或所有可能值的 0.4%。减去的两个值是正无穷大和负无穷大。另请注意,x 的第一位用于确定 NaN 的类型:“安静 NaN”或“发信号 NaN”。其余位用于编码有效载荷(在应用中最常被忽略)。图片由作者提供,使用制作。

尽管上述屏蔽和哨兵方法被广泛采用,但它们也有各自的权衡。单独的全局布尔掩码在存储和计算方面增加了额外的负担;然而,位样式的标记限制了可能丢失条目的有效值的范围。除此之外,用于标记的类型特定的逐位模式也需要实现附加的逻辑来执行比特级操作。

由于 pandas 是基于 NumPy 构建的,所以它只是将 IEEE 标准 NaN 值合并为浮点数据类型的 sentinel 值。然而,NumPy 没有针对非浮点数据类型的内置标记。因此,这意味着熊猫可以利用掩码或者哨兵来处理非浮点类型。也就是说, pandas 既可以有一个全局布尔掩码,也可以在元素的逐位表示中本地保留一位,或者有唯一的特定类型的逐位表示,比如 IEEE 的 NaN

然而,如前所述,上述三种可能性[ 布尔掩码、位级掩码和哨兵码 ( 位模式 )]中的每一种都是有代价的。说到利用全局布尔掩码,熊猫可以基于 NumPy 的掩码数组 ( ma )模块。但是,所需的代码库维护、内存分配和计算工作量使其不太实用。类似地,在本地级别上, pandas 也可以在其元素的每个位表示中保留一个位。但话说回来,对于较小的 8 位数据单元,丢失一位用作本地掩码将显著减少它可以存储的值的范围。因此,认为全局和局部屏蔽是不利的。也就是说,这让我们想到了第三个选项,即特定类型的 sentinels 。虽然这是一个可能的解决方案,但是熊猫对 NumPy 的依赖使得特定类型的哨兵变得不可行。例如,该包支持 14 种不同的整数类型,包括精度、字符顺序和有符号性。因此,如果要为 NumPy 支持的所有不同数据类型指定和维护独特的类似 IEEE 的标准位表示,那么 pandas 将再次面临艰巨的开发任务。

由于上述实际考虑,并且作为计算效率和维护之间的良好折衷, 熊猫利用两个现有的 Python 哨兵来表示空。分别是 IEEE 的标准浮点值 NaN (可用作为 numpy.nan ),Python 的singletonobjectNone(如 Python 代码中所用)。

然而,从 v1.0 开始,在【2020 年 1 月 熊猫标量缺失值引入了一个内部 实验 NA 值(单例对象)🎉根据文档,这个新的目标是熊猫。NA singleton 提供了一个通用的“缺失值”指示器,可以在所有数据类型中一致使用。也就是用熊猫。那总的来说不是跳来跳去的numpy nanNone熊猫。NaT ,这是特定于类型的。注意熊猫。NaT 用于表示 datetime 缺失值。

说到 NaNNonepandas 就是为了在这两个哨兵之间方便地切换(转换),在需要的时候。例如,在下图中,我们从包含一个缺失值的浮点值的列表中构造了一个简单的数据帧,我们用 numpy.nanNone、来表示

图 3:说明了一个简单的单列数据帧,它由一个包含一个缺失值的浮点值列表构成。注意,默认情况下,pandas 将浮点值推断为 float64。图片由作者提供,使用

虽然我们知道浮点缺失值将使用 numpy.nan 来表示,但是为了方便起见,我们也可以使用 None 来表示缺失值。在这种情况下,如上图所示, pandas 隐式地从 None 切换到 NaN 值。

类似地,让我们考虑另一个例子,其中我们从一列整数中构造一个数据帧,只缺少一个值,见下文。

图 4:说明了一个简单数据帧中隐含的 int 到 float 类型转换现象,该数据帧由一个包含缺失值的整数列表构成。图片由作者提供,使用图表

上图中有两件事需要注意。首先,在使用 numpy.nan熊猫表示整数型缺失值时,将整数型数据(默认推断为 int64 )类型强制转换为浮点型数据(默认为 float64 )。其次, pandas 再次允许我们利用两个哨兵中的任何一个来表示整数类型的缺失值。也就是说,当 None 用于表示缺失值时,它会隐式地将其转换为浮点值 NaN ,参见上面的结果数据帧。然而,将整数自动类型转换为浮点值并不总是很方便。尤其是当我们希望整数保持为整数的时候。因为有时整数也作为标识符用于索引目的。别担心😉因为熊猫已经解决了这个问题😎

再次截止到 2020 年 1 月发布的 v1.0 中,所有熊猫【现有的可空整数dtype,如(https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.UInt64Dtype.html)int 64,使用新的实验用熊猫。NA* 作为缺失值指示器,代替 NaN 值。这太棒了😃因为通过使用任何 pandas 的扩展 integer 类型,我们可以在需要时避免整型到浮点型的类型转换。请注意,为了区别于 NumPy 的整数类型,例如“int64”,extension-dtypes 的字符串别名中的第一个字母是大写的,例如“Int64”。因此,作为一个例子,让我们使用扩展类型 Int64 和包含缺失值的一列整数来构造一个简单的数据帧,见下文*

图 5:展示了一个单列数据帧,它由包含缺失值的整数列表构成,使用 Int64 扩展类型作为推断的数据类型。注意,您也可以将 dtype 别名“Int64”指定为 pd。Int64Dtype()。此外,您还可以使用更小的位大小变量,如 Int16 或 Int8。图片由作者提供,使用图表

如上图所示,当 Int64 被指定为 dtype 时, pandas 不会将整数类型转换为浮点数据,它使用新的实验 NA 值来表示所有标量缺失值,而不是 NaN

1.0版本还为我们提供了两种新的实验性扩展类型,类似于整数<位长> Dtype* 。这些是完全专用于字符串和布尔数据的字符串可空布尔数据类型。新的 Dtype 可用作string typeBooleanDtype 以及它们相应的别名“string”和“boolean”。作为一个例子,下面我们举例说明一个简单的数据帧,该数据帧是使用新的实验扩展类型string type以及一列带有缺失值的字符串构建的,*

图 6:展示了一个使用 pd 从包含缺失值的字符串列表构建的单列数据帧。string type()扩展数据类型别名“string”。图片由作者使用制作。

即使对于新的扩展字符串类型,当我们使用 numpy.nanNone 来表示一个缺失值时, pandas 会隐式地将其转换为结果数据帧中新的实验 NA 标量值。是从 v1.1 开始,在2020 年 7 月* 发布,这里所有的 Dtype 都可以转换成string type。*

类似地,如图 6 所示,我们也可以使用新的扩展类型BooleanDtype从一列 bool 和缺失值中构造一个 dataframe,如下所示**

图 7:展示了一个使用新扩展 pd 从一列 bool 和缺失值构建的单列数据帧。BooleanDtype() dtype 别名“boolean”。图片由作者使用制作。

并且,截至【2020 年 12 月随着发布v1.2pandas 支持两个额外的实验性float 32d type/float 64d type扩展数据类型,它们完全专用于浮点数据。两种可空浮动类型都可以容纳实验用的熊猫。NA 值。虽然 NumPy 的 float 使用 NaN 值来表示一个缺失值,但是这些新的扩展dtype现在与已经存在的可空整数布尔dtype 内联。下面的例子展示了工作中的可空 floatd typefloat 64

图 8:说明了使用 pd 的数据帧结构。Float64Dtype()别名 Float64,它是 NumPy 的 float64 数据类型的扩展,支持 pd。不单身。注意,作为一种选择,只有一种更小的位尺寸变体可用,即 Float32。图片由作者提供,使用图表

除了上面提到的扩展数据类型,即可空整数、布尔、浮点字符串 dtype、熊猫也带有它们对应的扩展数组数据类型。这些是 IntegerArray (自 v0.24 起可用,更新于 v1.0 ),string array(v 1.0),boolean array(v 1.0),以及 FloatingArray ()因此,当 dtype 被指定为“boolean”时,所有 BooleanDtype 数据都存储在一个 BooleanArray 中。类似地,当要推断的 dtype 被指定为“Int64”时,它将所有的 Integer64Dtype 数据存储在一个 IntegerArray 中。

仔细观察,使用扩展数据类型作为其推断的 dtype 构造的 dataframe 实际上使用相应的扩展数组数据类型来存储(系列)数据。实际上,这些扩展数组数据类型由两个 NumPy 数组表示,见图 1。第一个用于存储数据,而第二个用作全局布尔掩码,指示第一个数组中缺失的值(布尔值表示缺失)。但是,请注意, StringArray 只存储string type对象,没有第二个 NumPy 数组用作布尔掩码。另一方面,请注意,当扩展数组数据类型不用于构建数据帧时,默认情况下,所有带有缺失值的类似数组的数据都使用默认 NumPy float -或 object -dtype NumPy 数组进行存储。这些数组使用 NaNNone 来表示缺失的值。因此,下面我们列出了熊猫中所有缺失的价值观惯例,

表 1:熊猫缺失的价值观。请注意,可空和字符串 dtype 是一种扩展数据类型。字符串通常存储在 object-dtype NumPy 数组中,这里读。然而,随着 string dtype 的引入,它们现在可以存储在 StringArray 中,参见这里的。图片由作者提供,使用制作。

这就是我们的结局。希望上面的讨论和插图系统地展示了熊猫中常规的和实验性的缺失值表示。虽然新的熊猫。NA 标量值被标记为实验性的,最*发布的特性和增强确实显示了库的驱动力和制造熊猫的意图。NA 通用缺失值指示器。谢谢,继续和熊猫们玩得开心😃 🙏

构建数据帧的另一种方式

我们也可以使用传统的 pandas.arrays() 来构建数据帧,而不是使用缺失值的数据列表和指定的特定(扩展)数据类型来进行推断。从 v1.0pandas . arrays()开始,默认情况下,为整数、布尔值、字符串、浮点数等类似数组的输入推断扩展 dtype,参见这里的

进一步阅读

“纳米 YOLO”——对简化 YOLO v1 多部分损失函数的见解

原文:https://towardsdatascience.com/nano-yolo-insights-on-the-multi-part-loss-function-of-a-simplified-yolo-v1-5104bdee7ff1?source=collection_archive---------41-----------------------

实践教程

当开始实验物体检测时,我们想知道什么

(图片作者)

在本文中,我们将描述我们训练简化的 YOLO v1 模型(我们称之为“纳米”)来检测物体的方法和学习。我们这样做的主要驱动力是“好奇心”——我们想看看我们是否能够成功地深入到对象检测中,利用我们自己的数据建立和训练我们自己的模型。
我们使用 Tensorflow 2.3.0 建立和训练模型。

因为我们想学习和尝试一些东西,所以每当我们不能完全理解最初的 YOLO v1 论文的目的时,我们就选择自己做决定。我们选择 112×112 像素的输入尺寸来训练模型(YOLO v1 使用 448×448),我们使模型架构适应变化的尺寸,并且我们改变损失函数的部分。我们的目标是检测桌子上的三个简单物体——一辆玩具车、一个卷笔刀和一套工具。

在以下部分中,我们将描述如何

  • 生成了用于训练和验证的数据集,包括自动标记,
  • 建立了模型并实现了损失函数,
  • 训练模型以达到我们期望的精度。

通过我们的“纳米 YOLO”模型,我们能够在一个恒定的*面背景(我们的公寓地板)上检测三个不同的物体(玩具车、卷笔刀和工具集),精确度为 0.81 (VOC2007 mAP@.80)。这并不多,但对我们来说——这让我们对物体检测的工作原理有了大量的见解和理解,我们想与尚未迈出这一步的人分享这一点。

YOLO v1 上的一些话(如果你以前没听过)

YOLO v1 试图通过单次向前穿过模型来检测图像中的对象。预测图像中的对象类别、中心位置及其边界。

这是通过将整个图像分解成网格单元(通常为 7×7)来完成的,并且为这些网格单元中的每一个回答它持有哪个对象类,以及(从该单元的角度来看)该对象在该单元内居中并且跨越整个图像的最佳猜测。由于许多网格单元可能要求更大的图像,因此需要后处理来抑制声称检测到对象但与其他相比不是最佳对象的网格单元。

导致图像内物体的相当好的检测。

创建训练集

我们创建了自己的训练集,包括物体的图片(玩具车、工具集和卷笔刀)和不同的背景图片(公寓地板)。因为我们想使用最少的一组图像,所以我们使用数据生成将相同的对象放置在背景上的随机位置,以创建一组 6000 张图像。

为了实现这一点,我们使用 OpenCV 方法(不是本文的一部分)剪切对象,选择背景图片的随机部分,并将对象放置在该图片的随机位置。对象位置、放置的对象类型和边界框的信息存储在一个文本文件中,以便稍后用作我们的标签。

此外,我们增强了创建的图像,以增加训练模型的鲁棒性。我们使用了 imgaug 库,它有一个非常好的文档,显示了不同类型的增强的效果。注意不要以使创建的标签过时的方式增加,例如透视变换。或者生成在模型的预期用途中永远不会出现的图像,例如,因为我们的玩具车不会粘在天花板上而上下翻转。

我们使用了以下增强功能:

  • 将对象从左向右翻转(放在背景上之前)
  • 运动模糊将运动效果应用到图像
  • 亮度稍微改变颜色,使其出现在不同的光线设置中
  • 锐化对象的边缘。

下图显示了创建的原始图像和增强模糊,颜色,锐化

图像:原始、运动模糊、色彩亮度和锐化(作者的图像)

每个增强以一定的概率应用于每个图像。每个生成的图像都很有可能是唯一的。

对于我们的示例训练,我们使用了 4 幅原始图像——一幅公寓地板的图像,一幅每个对象的图像。为了实现高质量的图像生成,图像以 448×448 像素生成,然后缩小到所需的 112×112 的图像尺寸。

模型设置

我们大致按照最初的 YOLO v1 论文(链接)中描述的那样实现了模型架构——尽管我们应用了一些更改:

  1. 我们减少了图像的输入尺寸,并相应地调整了层数和最大池数,从 112x112(图像尺寸)到 7x7(网格尺寸)
  2. 我们为“empty”添加了一个类来描绘没有任何对象的背景,并相应地改变了损失函数
  3. 我们移除了损失函数中的大部分超参数,并用基于当前批次统计数据计算出的参数替换了这些超参数

下面,我们将详细描述我们如何建立模型,以及我们如何理解和实现损失函数。

模型架构

我们建立了两个模型:

  • “分类”,用于分类预处理
  • “检测”,用于检测物体

两个模型共享一个“公共基础”模型,这构成了图表的最大部分。而用于分类或检测的头部只是添加到公共基础模型中(注意:生成模型输出的“头部”通常显示在所绘制的模型图的底部,或者如果该图是水*绘制的,则显示在右侧)。

用于分类和检测的“公共基础”模型(作者图片)

我们的公共基础模型在卷积中使用步长 1,然后使用最大池来减少矩阵。这是在最初的 YOLO v1 论文中使用的简化技术。也可以通过使用步长 2 卷积来实现这种减少。

添加分类头

对于分类模型,我们展*了公共基础模型的输出,并在使用激活的 softmax 完成密集的 4 层(我们的类“无”、“玩具车”、“削笔器”、“工具集”)之前应用了 0.5 的 dropout。

softmax 是可行的,因为我们不会生成包含多个对象的图像。

最初的 YOLO v1 论文为头部添加了一个额外的密集层和一个*均池层,这是我们首先尝试但跳过的——在我们的数据集上训练期间,我们没有看到这些额外层的任何好处或改进。

添加探测头

对于检测模型,我们向基本模型添加了以下层:

  1. 两个卷积层,具有泄漏 relu 激活函数、权重衰减和滤波器大小 512 和 128
  2. 0.6 的展*和下降
  3. 具有 tanh 激活功能的尺寸为 1024 的密集层(完全连接)
  4. 大小为 686 的密集层(这是 7 个垂直网格单元* 7 个水*网格单元*每个网格 4 个热编码每类单元+ 2 个具有 1 个置信度和 4 个框尺寸的框)
  5. 自定义重塑图层以输出具有不同值范围的类、盒和盒置信度(具有 softmax 的类、具有 sigmoid 的盒和盒置信度)

卷积层需要学习用于基于公共基础模型的特征进行检测的特征。这种学习必须有一定的空间,这些额外的回旋将完成这个任务。
密集层将所有数据收集在一起,并提供学习预测所需检测输出的能力。

损失函数

现在,我们来看看损失函数。对于基于 YOLO v1 的物体检测,预测将首先远非完美,并且将以三种不同的方式产生误差:

  1. 对象类的错误预测
  2. 对象的位置和边界框的错误预测
  3. 错误的置信度哪个内部盒子表示是对象的正确表示

每个错误都需要用一个损失来惩罚,以训练模型,因此总损失由这三部分组成,即所谓的多部分损失函数。

在每个训练步骤中,计算该损失,并且计算模型函数的梯度(朝向最优的方向)。现在,在梯度方向上前进一步会减少损失。

在构建我们的“纳米 YOLO”时,我们深入研究的一件事是这三个部分的损失函数的组成以及这些部分如何相互作用。事实证明,为 YOLO v1 描述的大多数超参数只是将这三个部分混合成单个损失值的加权。

可视化损失函数的各个部分

由于训练历史中的典型“损失”值将仅显示多部分损失函数的组合损失,我们添加了额外的数据写入器来记录这些部分损失。

在我们保存实际损失函数“yolo_loss”的类中,我们添加了一个属性“self.lastClassLoss ”,该属性在实际损失函数“yolo_loss”的末尾将该损失与所有其他部分损失相加之前获取类损失的最后一个值。

class YOLOLossFunction ():
   def __init__(self, …):
      ...
      self.lastClassLoss = 0
      ... def yolo_loss(self, groundtruth, prediction):
      ...
      self.lastClassLoss = class_loss
      ...
      return (classloss + … )

为了能够在训练时将这个“lastClassLoss”写入历史,我们需要一个简单的函数,将标签和预测作为输入,并只返回这个属性:

class YOLOLossFunction ():
   ... def classLoss(self, y_true, y_pred):
      return self.lastClassLoss ...

在编译模型时,我们只需将此函数添加到我们的度量参数中,以便在每个训练步骤中将返回值写入历史:

yololoss = YOLOLossFunction(...)detmodel.compile(
  ...,
  metrics=[..., yololoss.classLoss, ...]
)

我们对多部分损失函数的每一部分都这样做了。

多部分损失函数各部分的验证损失图(作者图片)

有了这些信息,您可以清楚地看到多部分损失函数是如何工作的——哪个部分首先被优化,哪个部分根本不移动。当优化器努力寻找最简单的方法来降低损失时,如果不进行均衡,某些部分的数量可能会超过其他部分。有了这些见解,您可以根据您的特定数据集的需要来操纵超参数,并控制应该首先优化的内容。在我们的损失函数中,我们设法在移动到中心位置之前开始优化类预测,然后是盒子及其置信度(置信度在我们的例子中仍然不能正确工作,但可能是因为没有必要像在最初的 YOLO v1 论文中提到的那样,在不同类的网格单元中“专门化”两个盒子)。

阶级损失

损失函数首先优化的是类损失,这是最容易的部分,因为所有特征在公共基础模型中已经可用,新的头只需要学习这些特征的一些新的“路线”。我们试图塑造我们的数据集,通过在数据集中几乎没有太大变化的几乎统一的背景来使这变得更加容易。这使我们能够引入一个空类来描述没有对象的背景。

我们也有数据集中没有任何对象的图像。

我们实现了类预测,包括在最后一层激活 softmax 的空类,而不是 YOLO v1 论文中描述的 sigmoid 或线性。

由于图片的大部分包含空的网格单元(在我们的训练数据中只有一个网格单元是热的),我们不想让模型猜测所有单元都是“空的”以最小化损失。因此,我们计算了一个物体和“空”之间的超参数。我们通过将“空”类预测损失除以空网格单元的数量,并将任何其他类的类损失除以负责对象(包含其中心)的网格单元的数量来实现这一点,当然是针对一批中的所有项目。

盒子损失

提醒一下,框损失描述了找到的对象中心有多好,以及预测的边界框覆盖对象有多好。第二部分让我们想起了 IoU(并集上的交集)和中心点之间欧几里德距离的第一部分——这正是我们实现它的方式。只有 IoU 不能完成这项工作,因为在训练开始时可能根本没有重叠,所以最小化距离将导致随后可以优化的重叠。

在训练中,您可以看到如何首先最小化距离损失,在学习边界框的高度和宽度之前估计对象的正确中心。导致结果更喜欢正确的中心位置而不是正确的边界框。同样,我们通过只计算该批中确实包含对象的图像来衡量损失。

信心丧失

置信度表示算法对估计的确信程度。在 YOLO v1 中,这用于编码网格单元中的盒子是否包含物体。我们已经用“空”类的概念代替了它,所以置信度将只指示每个网格单元的两个框中的哪一个应该最后被评估。

如前所述,YOLO v1 的论文认为,这也使细胞能够“专门化”某些类别。我们已经看到了这样的例子(看看另一个框的值),而我们的总体结果显示,大多数时候这个框的置信度只是回答一个“你选择哪个框都没关系,因为两个都很好”。

我们再次用一批中的对象数量来加权该参数。

根据图像/对象中的对象对部分损失进行加权

在对我们的模型和数据集进行实验时,我们发现不*衡的对象数量(图像上的存在、类的类型)会导致不*衡的损失。因此,我们添加了(我们称之为)“数据组合丢失标准化”的概念,这确实改善了我们的结果,而且更重要的是,对于我们来说,理解模型试图了解的内容是很自然的:由于在一个图像中有许多空网格单元,甚至在整批图像中有更多的空网格单元(可能包含完全空的图像),因此预测某些内容为“空”是没有意义的,因此需要根据图像中小对象的单次出现来权衡。大大增加了发生在这些小物体上的损耗。

将零件合计为每批一个损耗

最后,损失函数总结了三个损失值——预测类别标签的损失、预测对象位置和大小的损失(盒损失)和预测盒置信度值的损失。

培养

用我们自己的数据从头开始训练“纳米 YOLO”是一个两步走的方法——首先,我们训练分类模型来对不同的对象进行分类(“无”、“玩具车”、“卷笔刀”、“工具集”),然后我们继续进行检测(对象位置和大小)。

预训练分类器

我们使用“ADAM”优化器和 Tensorflow 预定义的稀疏分类交叉熵损失函数来训练分类器。我们将 ADAM optimizer 的配置设置保留为默认值,这意味着学习率为 0.001,第一动量的指数衰减率为 0.9,第二动量的指数衰减率为 0.999,数值稳定性常数ε为 1e-07。我们没有使用优化器的 AMSGrad 变体。

经过 6 个时期(6000 张图像,批次大小为 64) —我们达到了 0.99 的验证精度。该模型可以对相似但看不见的图像进行分类。

这个结果看起来令人印象深刻,但必须谨慎对待,因为我们是从很少的实际图像中生成数据集的。

“纳米 YOLO”——检测

我们保留了训练好的“共基”模型,并增加了探测头来训练我们的“纳米 YOLO”。

我们用随机梯度下降(SGD)优化器和前面解释的损失函数来训练该模型。对于所有的训练时期,我们使用具有初始设置值的优化器——动量为 0.6,学习率为 0.003。所有其他设置都保留默认值。

经过 250 个时期,一批 32 个和 6000 个图像,我们达到了 0.81 的精度(VOC 2007mAP @ 0.80= 0.81)。

为了达到这个训练结果,我们尝试了从 0.001 到 0.01 的几个学习率以及从 0.3 到 0.8 的动量。此外,我们还尝试使用 ADAM 优化器对学习率进行类似的调整。我们经历了 ADAM 优化器在开始时相当不稳定,并且——一旦损失很小并且接*最佳值——损失值随机地突然爆炸(“爆炸梯度”的问题是众所周知的并且被描述了,但是我们还没有深入研究它,并且想要继续我们的对象检测方法)。

结果

对象检测工作得很好,尽管工具集和玩具车的分类可以更准确和鲁棒。尤其是使用“真实世界”的图像,上面有一个以上的对象。例如,下面的结果图像是用不同的闪电设置以及一个图像中的三个对象拍摄的,这是模型在训练期间没有看到的。在这张图片中,模型可以正确地检测和分类“sharper”和“toolset”——尽管玩具车的分类是“toolset”。

在训练期间从未见过的图像上检测到边界框(作者的图像)

汽车的视角完全不同于其他图像上所有先前训练的汽车视角。尽管这个盒子仍然很准确。

为了测量我们的 Nano Yolo 模型的准确性,我们将 VOC challenge(2007 年)的*均精度作为张量流度量(矢量化计算)来实施,考虑到我们的特殊情况,即每个图像只有一个对象。

根据这一指标,我们的纳米 YOLO 版本具有 0.81 的精度,最低 IoU 阈值要求为 0.8(VOC 2007mAP @ 0.80= 0.81)。该图显示了*均精度如何根据 IoU 的不同选定阈值在所有类别中以 0.1 为步长变化。我们没有像通常在文章和论文中看到的那样,对每个阈值的精确值绘制不同的召回。

为 0 到 1 之间的几个 IoU 阈值绘制的*均精度(图片由作者提供)

学习

“已为特定数据集/挑战选择了描述的超参数—估计您自己的参数或动态计算它们。”

对于我们的数据集,超参数取决于每批中所选的图像,并且需要根据批中对象和“无对象”的数量来采用。此外,物体对图像的覆盖也很重要——与我们的小物体相比,VOC2007 的图像覆盖范围更大。我们尝试了 Yolo v1 论文中的原始超参数,但在我们的数据集上没有得到好的结果。

"如果背景一直是空的,那么“空”类会使事情变得更容易."

对于我们的数据集和方法,它简化了使用空类的事情。

在其他数据集(如 VOC2007 数据集)上,不同的背景将不符合我们的空类概念。在这里,使用 sigmoid 激活的原始 YOLO v1 行为可能会更好-允许所有类预测接*零的置信度,以指示在图像单元中无法识别任何已知对象。

"从一个小模型开始快速实验."

我们的整体方法——用一个小模型处理一个小数据集——帮助我们深入了解对象检测的概念,并学习编写自定义损失函数的技巧。特别是,它使我们能够尝试不同的优化器、学习率以及快速采用超参数和模型层。一个带有小图像的小模型帮助我们在几分钟内完成了大多数实验,并且在不到一小时的时间内在我们自己的机器上完成了一个完整的训练。

“你得试试。”

我们一停止复制就开始学习,开始自己开发东西。我们鼓励每个人也这样做。尝试愉快。

Apache Spark 中的本机会话化

原文:https://towardsdatascience.com/native-sessionization-in-apache-spark-624883a8a9e2?source=collection_archive---------10-----------------------

在 Spark 3.2.0 的下一个版本中,在许多新特性中,有一个将使我们在使用 Spark 结构化流解决会话化问题时变得更加容易。

在进入细节之前,让我们澄清一些流概念,如窗口。

照片由卢卡·布拉沃Unsplash 拍摄

当你向窗外看时,你只能看到陆地的一部分,而不能看到全部。这里是一样的🤓

在流式传输中,由于数据流是无限的,所以我们不能尝试使用批处理方法对数据进行分组,这也没有意义。

那么,你是如何分组的呢?

窗口、窗口和窗口。

Windows 将数据流分成有限大小的“块”,我们可以在这些块上进行计算。如前所述,没有他们,这是不可能的。

最常见的窗口类型是翻转窗口、滑动窗口、会话窗口。

你可以想象,在这篇文章中,我们将讨论后者。

会话窗口

会话窗口捕获数据中的一段活动时间,该时间因非活动间隙而终止。与翻滚滑动窗口相反,它们没有重叠,也没有固定的开始和结束时间。

非活动间隙将用于关闭当前会话,并且以下事件将被分配给新会话。

作为会话的一个例子,考虑在您最喜欢的音乐提供商那里听音乐。

一旦您播放了第一首歌曲,将为您的用户创建一个会话窗口,这个会话将在一段时间(比如 10 分钟)不活动后结束。

这意味着,如果你只听一首歌,窗口将在 10 分钟后关闭,但如果你继续听更多的歌曲,窗口不会关闭,直到达到不活动的时期。

当研究用户在特定时间段内参与某项活动时,它们在数据分析中特别有用。

如何在 Spark< 3.2.0

This would be too long to cover 😩, and there are great posts about it, as a hint search for flatMapGroupsWithState 中创建会话窗口?

如何在 Spark ≥3.2.0 中创建会话窗口

这正是你在这里的原因,今天是你的幸运日,因为它们比以前简单多了,简单多了🎉。

你需要定义的只是你的时间列(必须是 TimestampType) 和不活动的间隙。

def session_window(timeColumn: Column, gapDuration: String)

让我们举个简单的例子。

输入数据:

{"time":"2021-10-03 19:39:34", "user_id":"a"} - first event
{"time":"2021-10-03 19:39:41", "user_id":"a"} - gap < 10 seconds
{"time":"2021-10-03 19:39:42", "user_id":"a"} - gap < 10 seconds
{"time":"2021-10-03 19:39:49", "user_id":"a"} - gap < 10 seconds
{"time":"2021-10-03 19:40:03", "user_id":"a"} - **gap > 10 seconds**

让我们使用会话窗口对这些数据进行分组:

val sessionDF = df
    .groupBy(*session_window*('time, "10 seconds"), 'user_id)
    .count

简单对吗?😭

输出:

+------------------------------------------+-------+-----+
|session_window                            |user_id|count|
+------------------------------------------+-------+-----+
|{2021-10-03 19:39:34, 2021-10-03 19:39:59}|a      |4    |
+------------------------------------------+-------+-----+

如您所见,我们有 4 个事件落在第一个会话窗口中,因为非活动期始终小于 10 秒。第五个事件将出现在该用户的下一个会话窗口中,因为活动间隔大于 10 秒。

结论

Spark 发展很快,以前不可能的事情现在可能会发生,跟上时代总是好的,不仅是 Spark,而是每项技术。

自然语言生成第 2 部分:GPT2 和 Huggingface

原文:https://towardsdatascience.com/natural-language-generation-part-2-gpt-2-and-huggingface-f3acb35bc86a?source=collection_archive---------7-----------------------

学习使用 Huggingface 和 GPT-2 来训练语言模型以用于 Tensorflow

照片由 Aliis SinisaluUnsplash

距离我的上一篇文章已经有一段时间了,很抱歉。工作,然后疫情抛出了一个扳手在很多事情上,所以我想我会回来一个小教程,对文本生成与 GPT-2 使用拥抱脸框架。这将是一个 Tensorflow 重点教程,因为我在谷歌上发现的大多数内容都倾向于 Pytorch 重点,或围绕 Tensorflow 使用它的细节。如果你不想看完我的整篇帖子,只是看看它是如何工作的,我有下面的 Colab 笔记本作为大纲,供人们参考这里。这篇文章基本上会回顾笔记本上的内容,所以应该很容易来回参考。

在我的上一个教程中,我使用马尔可夫链从总统演讲中学习 n-gram 概率,并使用这些概率生成类似的文本输出。现在,我们将更进一步,利用更先进的架构来创建更准确、更真实的文本输出。如果你还没有听说过 GPT-2 ,它是一个来自 OpenAI 的语言模型,使用一种叫做转换器的架构对来自网络的大量数据进行训练。这里是 GPT-2 使用的变压器架构的一个很好的视觉概述,这应该有助于给你关于它如何工作的直觉。GPT-2 不是开放人工智能语言模型的最高级版本,但与较新的 GPT-3 模型相比,它有许多参考实现和框架可供使用。它也是可以在 Colab 上运行的模型的一个版本,安装起来相当简单,希望在本教程之后更加容易:)

我们来说说数据

对于我们的任务,我们将创建一个生成金融文章标题的模型。如果我们从零开始训练语言模型的任务,我们将需要很多很多的例子(GPT-2 在 800 万个网页上被训练)。从预先训练的模型进行微调意味着我们不需要使用几乎相同的数量来获得我们特定任务的体面结果。

计划是获取大量的样本,几十万个,然后将它们分成训练集和评估集。我决定从 Kaggle 的 /r/investing subreddit 中的 reddit 标题和从 美国财经新闻文章 数据集中提取标题来获取数据。来自联合数据集中的一些示例不仅仅与金融相关,因为许多金融新闻网站也报道非金融事件,并且 subreddit 数据混合了投资建议和问题。

从 reddit 提交的内容中提取的标题约为 100k,从 Kaggle 数据集提取的标题约为 179k。这应该是足够的例子,以便不过度适合我们的任务,并给我们一个丰富的可能文本集,以便从“金融”领域中生成。

数据格式

数据的格式似乎决定了我所发现的这些模型的训练和输出。对于 GPT-2,如果你想生成一大堆文本,比如一本书或文章,你可以把所有的例子放在一个文档中,例子之间没有特殊的标记。但是,如果您想要生成遵循特定模式或提示的输出,您应该向数据集中添加特殊标记,以便更清楚 GPT-2 应该尝试学习什么模式来输出。下面是标题生成任务数据集中一个示例的基本格式。

<|title|>Some title about finances or other things<|endoftext|>

然后,将每个示例连接成一个长字符串。我们不需要为训练添加一个开始标记,因为 GPT-2 只需要''标记来拆分示例,但是有了这个前导标记,我们就可以让模型在每次运行时生成新的随机输出,这时我们首先用''来提示它。您可以将开始标记设置为您真正想要的任何内容,或者根本没有,但我发现,将这些标记设置为不太可能在数据的词汇中显示的内容会更容易生成连贯的文本,并且您也不太可能陷入重复的循环。

上面的要点显示了用于创建我们的训练和评估集的单元步骤。正如你所看到的,当我们一行一行地读入数据集,然后将标记附加到输入中,然后用重新连接,并写回到它们各自的文件中。现在我们已经将这两个文件写回到 Colab 环境中,我们可以使用 Huggingface 训练脚本来微调我们任务的模型。

如何微调 GPT-2

为了微调 GPT-2,我们将使用 Huggingface,并将使用提供的脚本 run_clm.py 找到这里。我试图找到一种直接通过 TF 模型调用来微调模型的方法,但是很难让它容易地工作,所以默认使用提供的脚本。像分类器这样的东西可以通过标准的 TF api 调用直接训练,但是当我开始这项工作时,语言模型似乎还没有得到完全的支持。其可能的新版 Huggingface 将支持这一点。

python run_clm.py \
--model_type gpt2-medium \
--model_name_or_path gpt2-medium \
--train_file "train_tmp.txt" \
--do_train \
--validation_file "eval_tmp.txt" \
--do_eval \
--per_gpu_train_batch_size 1 \
--save_steps -1 \
--num_train_epochs 5 \
--fp16 \
--output_dir=<directory of saved model>

上面的脚本将使用中型的 GPT-2 模型运行微调过程,尽管如果您使用标准的 Colab,由于虚拟机上的资源限制,您可能只能运行小型的 GPT-2 模型。对我自己来说,我使用的是 Colab Pro,它让我可以访问更强大的基本机器和 GPU。根据您的使用情况,常规的 Colab 可能就足够了,或者如果您确实需要长时间访问更强大的 GPU 实例,您可以使用 GCP。由于其架构,Transformer 模型在计算上非常昂贵,因此当在 GPU 上训练时,使用足够大的数据集很容易花费几个小时或几天。

对于 investing title 数据集,p100 上的 5 个时期需要 3-4 个小时,而 v100 只需要 1.5-2 个小时,具体取决于我使用的设置。当你启动 Colab 实例时,你在哪个 GPU 上运行似乎取决于一些运气。我发现我通常能够在几个小时的训练后每隔一天服用一次 v100。在上面的脚本调用中需要指出的一点是,我在模型训练中使用了混合精度和— fp16 参数。在我们的数据上,与单一精度训练模型相比,使用混合精度节省了大约 30 分钟的训练时间,而模型性能没有明显下降。

在模型训练的最后,会有一个评估步骤,告诉我们模型的困惑。正如你所看到的,我们的新一代 GPT-2 模型给我们带来了大约 10.6 的困惑分数,考虑到它只运行了 5 个时代,这个分数还不错。

现在我们已经训练了新的语言模型来生成金融新闻标题,让我们试一试吧!我们将使用脚本输出模型文件的目录的路径,并加载它,看看它是否会为我们输出一些新的金融文章/ reddit 标题!

要加载到 TF 中,我们需要导入 TFGPT2LMHeadModel,然后从 _pretrained 调用,确保将 from_pt 标志设置为 True。这样它将把 Pytorch 模型加载到 TF 兼容的张量中。我们还将使用预训练的 GPT-2 标记器来创建模型的输入序列。

预训练的标记器将获取输入字符串,并为我们的模型进行编码。使用记号赋予器时,还要确保设置 return_tensors="tf "。如果我们使用默认的 Pytorch,我们不需要设置它。有了这两样东西,我们就可以设置模型的输入,并开始获取文本输出。

创建输入后,我们调用模型生成函数。Huggingface 有一个很棒的博客,详细介绍了生成文本的不同参数以及它们是如何协同工作的这里。我建议通读一遍,以获得更深入的理解。下面的参数是我发现在给定数据集的情况下工作良好的参数,这些参数是我在多轮生成输出中反复试验得出的。语言模型的一个问题是,您必须尝试许多不同的参数选项才能开始看到一些好的输出,即使这样,有时也需要运行许多次才能得到适合您的任务的输出,所以如果最初的结果不太理想,也不要感到惊讶。

下面是我们的投资所有权模型生成的一些输出,给出了“”标记作为提示。

0: <|title|>Tesla's stock jumps 9% after Musk tweets it will hit $1,000 per share

1: <|title|>Avis Budget Group to Announce Fourth Quarter and Full Year 2017 Financial Results on February 27, 2018

2: <|title|>BRIEF-India's Bajaj Finance Dec Qtr Profit Falls

3: <|title|>BRIEF-Dunkin' Brands Reports Q4 Adjusted Earnings Per Share $0.06

4: <|title|>BRIEF-‍UAE's National Investment Posts FY Profit Before Tax Of RMB8.2 Mln

5: <|title|>BRIEF-Cogint Announces $8 Mln Bought Deal Financing

6: <|title|>Question about stock splits.

从上面生成的例子来看,它们看起来像可信的文章和 reddit 标题。有时运行时,您会得到一些有趣的输出,如下所示。

<|title|>Noob

好吧,这篇文章可能有点长,但是希望你发现它对学习如何使用 Huggingface 微调语言模型和使用 Tensorflow 后端生成一些文本是有用的。现在有了这些技巧,你可以开始为自己的工作/兴趣想出不同的任务和模式。例如,在建立了这个标题模型之后,我决定看看是否可以生成一个标题,并使用该标题生成某种文章,并获得不同程度的成功。尝试为自己做实验,看看你能想出什么!

感谢阅读!

链接到 colab gist:https://gist . github . com/georgeditmar/5c 57a 35332 B2 b 5818 e 51618 af 7953351

自然语言生成(实用指南)

原文:https://towardsdatascience.com/natural-language-generation-practical-guide-9dc03df6bffd?source=collection_archive---------34-----------------------

如何用马尔可夫链制作自己的标题

Unsplash 上的absolute vision拍摄

自然语言生成(NLG) 是一种能够从结构化数据中生成人类语言的人工智能。它与自然语言处理(NLP)密切相关,但有明显的区别。

简单来说, NLP 允许计算机读,NLG。这是一个快速发展的领域,它可以让计算机理解我们的交流方式。目前,它被用于编写建议,如电子邮件的自动完成,甚至在没有任何人工干预的情况下产生人类可读的文本。

在本文中,您将在实践中了解这一过程是如何工作的,以及如何用几行代码生成人工新闻标题,这些标题与真实标题没有区别。

马尔可夫链

(图片由作者提供)

我们将在这个任务中使用马尔可夫链,所以首先让我们了解它们是什么,以及我们为什么要使用它们。

马尔可夫链是一个使用随机、无记忆过程在状态间转换的系统。你可能在过去的数学课程中学习过它们,但是可能没有看到应用它们的实际方法。

让我们看一个例子。米隆是个婴儿,他只做三件事:吃、睡、哭。我们称它们为,Miron 可以处于的所有态称为态空间

马尔可夫链向我们展示了这些状态之间所有可能的转变,以及每一种转变发生的可能性。

让我们看看上面的图像,以便更好地理解其背后的理论。从睡眠状态,米隆可以过渡到哭泣、进食或回到睡眠状态,每一种状态都有一定的概率。

通过观察米隆,随着时间的推移,我们能够根据他的正常行为找出这些概率。这是马尔可夫链背后的基本思想,但是我们为什么要把它们用于 NLG 呢?

答案相当简单。我们构造句子的方式可以很容易地用马尔可夫链来模拟。所以,每个单词都是一种状态,一个句子就是每种状态之间的一系列转换。这个事实允许我们构建一个类似于上面的链。

通过观察许多不同的句子,我们可以看到人们通常是如何造句的,以及单词应该出现的顺序。在看到足够多的句子后,我们实际上可以开发一个模型,它可以生成与人类相似的句子。

既然计算机如此擅长计算,我们仅仅通过状态和概率就能充分利用它们。计算机将根据概率列表选择转移到哪里,这将允许我们在示例中生成新闻标题。这种技术可以应用于任何类型的文本,因此我鼓励您使用您构建的模型来生成其他文本,例如,某个名人的推文。

数据集和模块

丹妮卡·坦尤科在 Unsplash 上拍摄的照片

对于这个小项目,我们将利用 Markovify ,这是一个方便 Python 使用的马尔可夫链生成器。它通常用于建立大型文本语料库的马尔可夫模型,并从中生成随机句子。不过它的应用并没有限制,可以在 Markovify GitHub 页面随意查看它的真实应用。

我们还将使用来自 Kaggle 的“一百万条新闻标题”数据集来训练我们的模型。它包括大量美国广播公司新闻发布的文章的标题。

你不需要任何编程经验来完成这个项目,所以不要担心。对于 Python,你可以直接进入 Kaggle,在笔记本部分创建你自己的笔记本。在这个文件中,您可以执行所有进一步的步骤。

模型结构

马库斯·斯皮斯克Unsplash 上拍摄

加载包

我们将使用熊猫来构建标题数据。它对于数据分析和操作也很有用。马尔可夫链需要的模型是马尔可夫链。

import pandas as pd
import markovify
import random

读取输入文件

如果您使用 Kaggle 笔记本,只需使用下面的行来加载数据集。如果您想在您的计算机上运行代码,请下载数据集并将它的路径放在括号中。

input = pd.read_csv('../input/abcnews-date-text.csv')

input.head(10)

标题示例

下面的代码将从前 100 个标题中随机输出 10 个标题,这样我们可以看看数据是什么样子的。

input.headline_text[random.sample(range(100), 10)]

建立模型

这里我们使用输入数据来建立我们的马尔可夫模型。sate_size 变量允许我们选择模型在生成新句子时要查看的单词数。

例如,state_size 为 2 将检查前面的 2 个单词,并决定下一个单词是哪个。这个变量越大,模型就越复杂。然而,如果它太大,我们将无法生成许多句子,因为我们的数据集中没有足够的数据。

model = markovify.NewlineText(input.headline_text, state_size = 2)

生成标题

现在,这是有趣的部分,因为下面的代码将为我们生成 10 个标题。每次都会不一样,所以可以反复运行代码。

for i **in** range(10):
    print(model.make_sentence())

一些例子:

  • 塔斯马尼亚花费 1600 万英镑用于运动
  • 牛奶价格不会影响亚马逊
  • 商业环境和洪水
  • 首相对领导权守口如瓶

不同的州规模

这里我们有不同的州大小,这将使标题更符合逻辑,实际上看起来像真的一样。

model1 = markovify.NewlineText(input.headline_text, state_size = 3)
model2 = markovify.NewlineText(input.headline_text, state_size = 4)

状态大小 3:

for i **in** range(5):
    print(model1.make_sentence())

一些例子:

  • 搜寻在丹麦失踪的名为杰克·梅里特的男子的工作仍在继续
  • 猕猴桃为新工厂做好准备
  • 黎巴嫩军队加强对亚齐的控制引发新的冲突

状态大小 4(注意:我们这里要检查 4 个之前的单词,所以有些句子可能没有那么多。这就是为什么我们需要检查生成的句子是否不是 None):

for i **in** range(10):
    temp = model2.make_sentence()
    if temp **is** **not** None: 
        print(temp)

一些例子:

  • 六年后吉朗星捕鱼禁令解除
  • 特朗普能在 2020 年赢得第二个任期吗

集合模型

我们也可以将两个或多个模型结合在一起,看看结果是否会有所改善。

model11 = markovify.NewlineText(input.headline_text, state_size = 2)
model12 = markovify.NewlineText(input.headline_text, state_size = 2)
model_combo = markovify.combine([ model11, model12 ], [ 1.5, 1 ])

for i **in** range(5):
    print(model_combo.make_sentence())

一些例子:

  • 工业捍卫数百万人的安全;毕晓普说她会旅行
  • 天然气中心可能会在自行车比赛中放松
  • 议员推测亨德拉病毒马运动

结论

您现在已经学习了马尔可夫链的实际应用,以及如何开始学习 NLG。这个过程相当简单,上面的代码基本上可以应用于任何其他的生成任务。

来源:

[1]库尔卡尼河(未标明)。一百万个新闻标题。检索于 2021 年 1 月 18 日,来自https://www.kaggle.com/therohk/million-headlines

2辛格-维恩,法学博士(未注明)。马克维奇。检索于 2021 年 1 月 18 日,发自 https://github.com/jsvine/markovify

自然语言处理——依存句法分析

原文:https://towardsdatascience.com/natural-language-processing-dependency-parsing-cf094bbbe3f7?source=collection_archive---------3-----------------------

实践教程

使用 spaCy、NLTK 和 Stanford CoreNLP 和 Stanza 进行依赖解析的不同方法

照片由 Siora 摄影Unsplash 拍摄

什么是依存解析?

依存句法分析是分析句子的语法结构,找出相关词以及它们之间的关系类型的过程。

每种关系:

  1. 有一个 和一个修改从属
  2. 根据被从属之间的从属性质进行标注。这些标签可以在通用依赖关系中找到。

两个词之间的简单依存关系

在上图中,之间存在关系,因为修饰了的含义。这里,充当头的从属。这里关系的本质是 amod ,代表“形容词修饰语”。它是修饰名词的形容词或形容词短语。

履行

在 Python 中实现依赖解析有不同的方法。在本文中,我们将研究三种方法。

方法 1:使用空间

spaCy 是一个用于自然语言处理的开源 Python 库。

要开始,首先安装 spaCy 并加载所需的语言模型。

pip install -U pip setuptools wheel
pip install -U spacy
python -m spacy download en_core_web_sm

en_core_web_sm 是 spaCy 现有最小的英文型号,大小为 12MB。参考 spaCy 英国型号查看其他可用型号。

使用空间进行依存解析

spaCy 还提供了一个名为 displaCy 的内置依赖可视化工具,可以用来生成句子的依赖图。

displacy.render()功能将生成句子的可视化。

注意:如果运行的是 Jupyter Notebook 或者 Google Colab 中的代码,使用render()函数中的jupyter = True

依赖关系可视化的输出

方法 2:将 NLTK 与斯坦福 CoreNLP 一起使用

由斯坦福 NLP 小组创建的 CoreNLP 提供了 Java 语言的 NLP 工具。这个 Java 库可以和 NLTK 一起使用来解析 Python 中的依赖关系。

第一步,从 CoreNLP 网站下载斯坦福 CoreNLP zip 文件和斯坦福 CoreNLP 模型 jar 文件。

运行这三个命令将下载所需的库并解压缩 zip 文件。

wget [https://nlp.stanford.edu/software/stanford-corenlp-4.2.2.zip](https://nlp.stanford.edu/software/stanford-corenlp-4.2.2.zip)
wget [https://nlp.stanford.edu/software/stanford-corenlp-4.2.2-models-english.jar](https://nlp.stanford.edu/software/stanford-corenlp-4.2.2-models-english.jar)
unzip /content/stanford-corenlp-4.2.2.zip

一旦下载了这些库,我们就可以从 NLTK 导入 StanfordDependencyParser。

from nltk.parse.stanford import StanfordDependencyParser

使用 NLTK 和 Stanford CoreNLP 进行依存解析

为了可视化 CoreNLP 生成的依赖关系,我们可以使用dependency.nx_graph()函数提取一个有标签和有方向的 NetworkX 图形对象,或者使用dependency.to_dot()函数在图形描述语言中生成一个点定义。使用 GraphViz 可以将点定义可视化为图形。

使用 NetworkX 可视化

# importing networkx
import networkx as nx
import matplotlib.pyplot as plt# Using reverse() to reverse the direction of edges as nx_graph() returns inverted edges
G = dependency.nx_graph().reverse()# nx_graph() returns numeric node labels starting from 1
# Create a dictionary to map numeric nodes and words in the sentence
words = sentence.split(" ")
labels = {index + 1: words[index] for index in range(len(words))}nx.draw(G, with_labels=True, labels=labels, node_size=2500, node_color='#B5EAD7', font_size=10)

从 NetworkX 对象创建的依赖关系图

使用点定义可视化

!pip install graphvizfrom graphviz import Source
dot_def = dependency.to_dot()'''
The below lines require graphviz executables to be installed to your system. If that does not work, print the dot_def object and paste the output on http://graphs.grevian.org/graph/
'''
source = Source(dot_def, filename="dependency_graph", format="png")
source.view()

从点定义创建的依赖关系图

方法 3:使用节

斯坦福大学 NLP 小组也开发了 Stanza。它提供了一个可以定制的神经网络 NLP 管道和一个基于 Stanford CoreNLP 包的 Python 包装器,使得在不下载 jar 文件的情况下使用 CoreNLP 特性变得更加容易。

要开始,请安装 Stanza

pip install stanza

下一步是导入 stanza 并下载所需的语言模型。您可以在此查看所有可用型号

import stanza
stanza.download('en')

使用stanza.Pipeline()函数初始化神经管道。第一个参数是要使用的语言。可以传递一个可选参数processors,该参数可以是一个字典或逗号分隔的字符串,以配置处理器在流水线中使用。

nlp = stanza.Pipeline('en',
                     processors = 'tokenize,mwt,pos,lemma,depparse')

您可以找到管道上所有处理器和处理器的列表。有些处理器可能需要在流水线中的其他处理器之前,否则它们将无法工作。例如,pos处理器需要tokenizemwt处理器,所以如果我们想使用pos处理器,也需要在流水线中使用这两个处理器。

我们现在将通过管道传递我们的句子,并将所有结果存储在doc变量中。

doc = nlp(sentence)

如果我们打印doc.sentences,我们将看到通过管道传递的每个句子的列表。每个列表包含所有标记信息和语言特征的结果。

例如,列表中的每一项都是一个对象,具有表示词条通用词性树库专有词性形态特征中心词索引在句子中的位置等属性。

{
    "id": 1,   -----> index of word in the sentence, starting from 1
    "text": "Deemed", -----> actual word
    "lemma": "Deem",  -----> lemma of the word
    "upos": "VERB", -----> universal POS
    "xpos": "VBN", -----> treebank specific POS
    "feats": "Tense=Past|VerbForm=Part",-----> morphological feature
    "head": 2, -----> index of the head
    "deprel": "amod", -----> dependency relationship nature
    "start_char": 0, -----> start index of word in the sentence
    "end_char": 6  -----> end index of word in the sentence
}

对于doc对象中的所有句子,我们可以调用print_dependencies()函数。这个函数将打印具有三个值的元组——令牌、头部的索引和关系性质。

注意:在我们的例子中,因为我们只有一个句子,所以我们使用doc.sentences[0]直接访问它

print_dependencies()函数的输出

使用 Stanza 进行依赖解析

因此,在本文中,我们看到了用 Python 实现文本依赖解析的三种方法。感谢您的阅读!:)如果对实现有疑问,可以在 LinkedIn 上联系我。

参考

  1. 空间依赖解析器—https://spacy.io/usage/linguistic-features#dependency-parse
  2. 斯坦福·科伦普—https://stanfordnlp.github.io/CoreNLP/index.html
  3. 小节依赖解析器—https://stanfordnlp.github.io/stanza/depparse.html

自然语言处理:从一个热点向量到十亿参数模型

原文:https://towardsdatascience.com/natural-language-processing-from-one-hot-vectors-to-billion-parameter-models-302c7d9058c6?source=collection_archive---------20-----------------------

实际上,它有万亿个参数。

人类的语言是模糊的。在说(或写)的时候,我们传达单个的单词、语气、幽默、隐喻和许多其他语言特征。对于计算机来说,这样的属性首先很难检测到,其次更难理解。为应对这些挑战,出现了几项任务:

  • 分类:该任务旨在将文本分类到几个预定义的类别中的一个或多个类别中
  • 语音识别和语音转文本:这些任务处理检测音频信号中的语音并将其转录成文本形式
  • 情感分析:在这个任务中,文本的情感被确定
  • 自然语言生成:这个任务处理自然(即人类)语言的生成

这份清单绝非详尽无遗;其中包括词性标注、(命名的)实体识别以及其他任务。然而,在所有列出的项目中,自然语言生成(NLG)领域最*受到了最多的关注。

想想最*的语言模型。例如,GPT-2(和 3)可以生成本身连贯的高质量文本数据。这样的能力开启了许多可能性;出于好的和坏的目的。无论如何,这种能力已经出现了很长时间;早期的方法使用一键向量将单词映射成整数;最*的成功依赖于注意力机制。

纳迪·博罗迪纳在 Unsplash 上拍摄的照片

建模文本

使用任何文本数据作为神经网络的输入都需要一个数字表示。一个简单的方法是用一包单词(BoW)表示法。按照这种方法,人们只考虑单词和它们的频率,而不考虑顺序:只是一袋单词。

举个例子,就拿“敏捷的棕色狐狸跳过篱笆”这句话来说吧。对应的弓是

["The:2 "," quick:1 "," brown:1 "," fox:1 "," jumps:1 "," over:1 "," fence:1"]。

为了将这个多集合(数学上是什么)转换成向量表示,我们用一个整数来表示每个单词。术语“The”被转换为 2,这是示例中“the”的计数。同样,“快”翻译成 1。有了这些信息,得到的矢量就是

[2, 1, 1, 1, 1, 1, 1]

第一个位置是句子中“The”的计数,第二个位置是文档中“quick”的计数,其余的索引也是如此。如果我们有几个句子,向量就会增长;总是只要词汇量大。例如,当我们有了第二句话,“狗和猫都是动物”,我们的词汇量就会增加五个单词。这种变化反映在所有矢量中;我们最初的例子变成了

[2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]

附加的零代表更新的词汇。由于这些词在第一句中不存在,所以它们没有数量。

单词包方法工作良好,但有一个明显的缺点:我们使用词序。失去了排序,我们引入了歧义。例如,句子“A 和 not B”和“B 和 not A”都映射到向量表示[1,1,1,1]。此外,语言特征也丢失了。从最初的例子“快速的棕色狐狸跳过篱笆”,我们可以推断动词“跳”指的是狐狸和篱笆。这种上下文信息会丢失。为了对这两个提到的特征建模,我们需要词序和上下文信息。

代表单词

传统上,单词被认为是离散的符号。如果我们总共有 20 个唯一的单词,每个单词由一个长度为 20 的向量表示。只有一个索引设置为 1;所有其他的都为零。这种表示被称为独热向量。使用这种技术,我们例句中的单词就变成了

[1,0,0,0,0,…]表示“the”

[0,1,0,0,0,…]表示“快”

作为一个旁注,总结这些向量,我们得到了弓的表现。

两个问题很快出现:给定一个相当大的词汇表,向量变得非常长而且非常稀疏。事实上,只有一个索引是活动的。第二个问题与单词之间的相似性有关。例如,一对“猫”和“狗”比“猫”和“鹰”更相似像这样的关系不会反映在一键表示中。通常,人们使用相似性度量(或反距离度量)来计算两个向量之间的相似性。一个常见的相似性是 余弦相似性 。回到我们的例子对“猫”和“狗”,我们可能有(任意的)向量

猫的[0,0,0,0,0,1,0,0,0]

狗的[0,1,0,0,0,0,0,0,0,0]

这些向量之间的余弦相似度为零。对“猫”和“鹰”来说,也是零。因此,两个结果没有反映第一对的更高相似性。为了解决这个问题,我们使用了嵌入。

嵌入

嵌入背后的核心思想:一个词的意义是由经常出现在附*的词创造的。为了推导出这个意思,人们使用单词的上下文,即在一个范围内出现的一组单词。对许多这样的上下文进行*均,可以得到这个词的相当准确的表示。以我们为例

"那只敏捷的棕色狐狸跳过了栅栏."

对于大小为 1 的上下文窗口,“fox”具有上下文单词(附*的单词)“brown”和“jumps”对于尺寸为 2 的窗口,将添加“快速”和“结束”。在我们的短句中,我们将很快用完上下文单词,并且只有一个“fox”的外观显而易见,需要大量的文本来创建实体的有意义的表示。我们通常想要尽可能多的上下文信息,这对于较大的语料库来说是自然的。

假设我们有足够的文本数据,我们如何创建一个嵌入?首先,嵌入是大小为 d 的密集向量。第二,意义接*的单词具有相似的嵌入向量,这解决了上面介绍的信息相似性度量的问题。第三,有一些算法可以创建单词嵌入; Word2Vec 就是其中之一。

所有嵌入计算算法的一般思想是为令牌创建有价值的嵌入向量。word2vec 算法以词为基本单位,侧重于局部关系。为了创建一个嵌入向量,我们可以——利用这个框架——集中精力从上下文预测中心词,或者从中心词预测上下文。第一种方法称为连续单词包(CBOW),第二种方法称为跳格法。我将在下一节简要介绍跳格法:

为了获得任何单词的嵌入向量,我们使用神经网络。下图取自[1],显示了该过程的示意图:

修改后的 Word2Vec 跳格法示意图。图片来自[1]。

为了获得任意单词的嵌入,我们使用它的一键表示。这个向量是网络的输入,如左图所示。在下一步中,向量被投影到它的嵌入表示中,如中间所示。通常,这是通过将其乘以一个矩阵来实现的,在图中标记为 E 。换句话说,这是网络中的正向传递。得到的(隐藏的)表示被优化以预测显示在右侧的上下文单词。

因此,网络的输出不是嵌入而是上下文单词。为了预测它们,我们使用另一个权重, C 。当我们将隐藏的内部表示乘以 C 时,我们得到一个长度为 d 的向量,其中 d 是我们的词汇量。这个结果向量可以被解释为每个单词在上下文中出现的非标准化概率。因此,在训练我们的网络时,我们最大化实际上下文单词的概率,最小化非上下文单词的概率。概括来说,向量流是:

Wᵢₙₚᵤₜ × E = e |对于一个热点与 e 的乘法运算

out = e × C |用于内部表示与 C 相乘

为了最终获得嵌入,我们提取内部表示。这里会涉及更多内容,比如目标函数(负对数似然)。请参考该文件以了解更多信息。

为了评估嵌入的有用性,请使用 TensorFlow 的投影工具。它让你探索不同的嵌入;在我们的例子中,“Word2Vec 10k”数据集是合适的。点击“A”启用标签。您现在可以直观地看到相关单词之间的相似性。在下面的例子中,我搜索了单词机器。最*的邻居被突出显示:

高维嵌入的可视化。我搜索了单词“ machine”,它的邻居(即最相似的嵌入)被高亮显示。你可以拿着它到处玩 这里 。图片由作者提供。

如上所述,Word2Vec 算法有两种选择:

首先,它抓住了当地的关系。其次,它把词作为基本单位。其他算法采取其他选择。例如, GloVe 算法,是GlobalVectors 的缩写,它基于全局关系创建嵌入,并使用单词作为基本单元。第三种算法是 FastText (参见论文参考文献此处),它使用子词信息作为基本单位(例如“this”—>“th”和“is”)。

不管算法选择如何,都存在一些挑战:如何处理标点符号?如何处理复数单词?不同的单词形式?这种修改是预处理的一部分,通常包括词干分析和词汇化。词干化把一个单词简化成它的词干。这种技术很有效,但是会产生人为的词干。词汇化试图将一个单词简化为它的基本形式,这通常是在大型数据库中实现的。

随着现代端到端方法的进步,预处理的重要性稍微变得不那么重要了。只有标记化仍然相关,比如字节对编码。在我们到达那里之前,我们必须看一下 n-grams。

(现代)n-格兰姆斯

为了开始整合词序,我们可以使用所谓的 n 元语法方法。以前,当创建 BoW 表示时,我们将句子分成单个单词。相反,我们也可以把它分成两个连续的单词、三个连续的单词等等。一行的字数是中的nn-克。如果 n 为 1,解析模型称为unigram;若 n 为二,则称为 bi 克。

举个例子,让我们用二元模型来解析“快速的棕色狐狸跳过栅栏”:

[《快手》、《快手布朗》、《棕色狐狸》、《狐狸跳》、…]

正如我们在这个例子中看到的,我们在文本上滑动一个窗口,大小为 n ,步幅为 1。一的跨距使得前一摘录的最后一个单词成为后一摘录的第一个单词。使用这种方法,我们部分地保持了单词之间的关系。

该表示是静态的。如果 n 参数改变,数据集必须再次预处理。根据大小,这可能需要一段时间。然而,我们可以将 n -gram 算法整合到神经网络中,让它们进行“预处理”这种方法可以看作是现代 n-grams

从嵌入步骤开始,我们对每个单词使用所获得的密集且信息丰富的表示向量。为了合并词序,我们必须稍微改变网络输入。给定一个长度为 l 的句子和大小为 e 的嵌入,输入现在是一个具有形状的矩阵:

l x e

这个矩阵可以解释为一个奇怪的图像。在与图像相关的任务中,卷积神经网络非常有效,但它们并不局限于这个领域。对输入文本矩阵的卷积运算可以解释为创建 n 个图。当内核大小设置为 2,步幅设置为 1 时,这实际上创建了一个二元模型表示。保持步幅,但是将内核的大小增加到 3,我们获得了三元模型。

卷积运算有一些有益的特性。其中之一就是位置不变性。可以在输入的每个位置应用核。如果一个这样的内核关注形容词-名词组合,它将在任何地方检测它们。此外,卷积运算自然会共享它们的权重,并且具有比密集图层少得多的参数。

n -grams 的缺点是它们只能捕捉有限范围内的关系。例如,N-grams 不能表达一个句子的第一个词和最后一个词之间的联系。将参数 n 设置为句子的长度是可行的,但是需要为每个不同长度的句子设置一个单独的 n 。有一种更好的方法来处理大跨度的关系,那就是注意力机制。这项技术是为机器翻译任务而引入的。

机器翻译

机器翻译(MT)任务处理将文本从源语言翻译成目标语言。例如,“这是水的毒药吗?”(法语)会被翻译成“鱼会接触水吗?”

早期的机器翻译研究是在冷战期间进行的,目的是将俄语翻译成英语。正在使用的系统主要基于规则和必要的字典。在下一步中,更正了词序。

从 20 世纪 90 年代开始,统计机器翻译成为焦点。核心思想是学习一个概率模型。强调翻译任务,这意味着:给定源语言中的一个句子,我们需要找到目标语言中最合适的句子——即最佳翻译。

数学上,这是用 y* = argmax_y P(y|x)来表示的。y*表示概率最高的翻译。

根据贝叶斯规则,这个描述可以分解为两个独立的部分:y* = argmax_y P(x|y) P(y)。第一个组件 P(x|y)对 x 是 y 的*移的概率进行建模,这部分称为*移模型。第二部分,语言模型,给出 y 在目标语言中的概率。

换句话说,第一部分量化源序列的概率,第二部分量化目标序列的概率。翻译模型是利用源语言和目标语言中的大型文本数据集来学习的。

深度神经网络的发展也影响了机器翻译的任务。递归神经网络是一个很好的选择,因为输入和输出都是序列。输入是要翻译的句子;输出是翻译。使用单个 RNN 会出现两个问题:首先,源句子和目标句子的长度可能不同。这一事实在最初的示例翻译中显而易见。输入包含八个标记,输出只有五个标记(取决于您如何计算标点符号,但问题是一样的)。其次,词序可以改变,使得单个一进一出的 RNN 不可用。

这两个问题的解决方案是在所谓的序列到序列(Seq2Seq)布局中使用两个递归网络[2,3]。第一个网络名为 encoder,接受输入并产生内部表示。称为解码器的第二个网络使用这种内部表示来生成目标序列,例如翻译。

简短说明:内部表示可以模拟任何关于输入句子的知识,包括单词关系。因此,长期依赖的问题被最小化。

单个 RNN 读取输入的逐标记解析,并立即返回翻译。在 Seq2Seq 布局中,编码器首先读取完整的输入序列,以创建内部表示。只有这时,这种通常是向量的表示才被传递到解码器网络。

这种设置是经过训练的文本对,生成目标序列的概率被视为损失。在训练期间,该模型是编码器和解码器的组合,最大化适当翻译的概率。

这是处理 Seq2Seq 任务所需的全部设置。然而,像往常一样,人们可以做一些改进,其中包括注意机制。

注意力

在普通的序列到序列布局中,编码器将关于输入句子的所有信息压缩到一个向量中。这个向量被恰当地称为瓶颈层,因为它导致了信息瓶颈。尽管能够解析无穷无尽的序列,但是随着新信息的加入,来自早期步骤的信息会慢慢消失。

这个瓶颈的解决方案是使所有隐藏的编码器状态都是可访问的。在普通设置中,编码器只传递它的最后一个状态,这成为了瓶颈。可以修改这种方法,以便在网络解析新令牌后保存所有中间状态。因此,编码器可以存储每一步的信息,而不再将所有知识压缩到一个向量中。

在编码步骤中,编码器网络可以访问所有每步向量。因此,它现在可以关注最重要的隐藏状态。我将简要回顾一下实现这一点的机制【4】。

编码器保存所有隐藏状态(解析新令牌后的向量)。然后,我们获取编码器的当前状态,并计算它和隐藏状态之间的点积。该操作为每个隐藏状态返回一个标量数,我们可以将其表示为一个新的向量:

[甲、乙、丙、丁、戊],

其中字符表示具有相应隐藏状态的点积的结果(例如,a 是具有第一隐藏状态的点积的结果)。然后将 softmax 操作应用于该向量,产生注意力权重。这些权重表示每个隐藏状态的重要性,用概率表示。在最后一步中,我们将隐藏状态与它们的注意力分数相乘,并将向量相加。这为我们提供了当前状态的上下文向量,它被传递给编码器(不完全正确,但对这个目的来说很好)。在每个编码器步骤之后,重复这个过程。

这个过程可以在这个动画中看到,它取自谷歌的 seq2seq 知识库:

序列到序列过程的动画。粗线表示对特定编码器状态的关注。来自谷歌 seq2seq 知识库的动画。

注意力机制的动画。来自谷歌的 seq2seq

注意过程使编码器能够存储每一步的信息,并让解码器决定注意哪些隐藏状态。这些修改极大地提高了文本翻译的质量,如4所示。

一般来说,递归网络,尤其是序列到序列方法的一个普遍缺点是低并行性。回想一下,步骤 k+1 的输出依赖于步骤k;因此,我们必须首先解析前面的所有步骤。因此,我们在这里不能并行运行太多——除非我们改变底层网络架构。这个想法让我们想到了变形金刚。

变形金刚(电影名)

转换器【5】是一种利用注意力机制的神经网络架构。在引擎盖下,它仍然使用编码器-解码器结构,但取代了循环网络。相反,编码器由具有自关注和常规前馈网络的 n 个相同层来建模。编码器模块使用相同的结构,并添加了另一个注意层,它接收编码器的输出。下图取自[5],显示了所描述的设置:

变压器架构示意图。左边是编码器堆栈,右边是解码器堆栈。图片来自[5]。

第二个改进是注意程序的修改。在传统的序列到序列方法中,解码器的隐藏状态计算所有编码器隐藏状态的点积。在称为多头自关注的改进机制中,这些操作被建模为矩阵乘法。

自我关注将输入转化为内部表征,即自身时间步长的加权和。这种方法可以捕捉序列中的长期依赖性。输入被转换成三种不同的表示,即查询,以对这些关系进行建模。这些表示是通过将输入乘以三个权重获得的: Wₖ (对于键) Wᵥ (值),以及 Wq (查询)。计算流程如下图所示[5]:

注意力机制的详细视图。q、K 和 V 是同一输入的不同表示。图片来自[5]。

q 和 K 进行矩阵相乘、缩放、选择性屏蔽,然后进行软最大化。最后,将结果与 v 进行矩阵相乘,这可以用以下公式进行数学表达:

将注意力机制表示为一个等式。图片来自[5]

最后,有多个这样的“流”,被称为注意力头。每个头部使用不同的注意力权重集 Wₖ、Wᵥ和 Wq。这些权重为同一输入产生多个内部表示。然后将单个注意头的结果连接起来,如下图所示[5]:

多头注意力机制的可视化示意图。各个向量在被送入线性层之前被连接在一起。图片来自[5]。

这些计算在编码器和解码器模块中完成,并且可以并行运行。这种并行化是 Transformer 方法比普通 RNN 模型更快的原因之一。此外,转换器使用字节对编码,使他能够归纳出看不见的单词。生僻字是一个常见的问题,有复合词的语言也是如此。想想德国那些疯狂的名词比如“Baumhausprüfgesellschaft”(检查树屋的社会)。我非常怀疑这种组合是否存在于典型的训练数据中。因此,我们的想法是使用子词标记,即前面提到的字节对编码:我们从训练数据中提取最常见的子词,如“th”和“ng”有了这样的词汇表,我们就可以将一个(未知的)单词建模为字节对的组合。

为了建立单词关系的模型,我们必须保留关于输入顺序的信息。简单的想法是修改令牌的嵌入向量。我们在每个嵌入中添加一个信号来模拟向量之间的距离,即步进信息。

更多的细节可以在这里讨论,但是这会偏离这篇文章的主题。如果你感兴趣,我推荐杰伊·阿拉玛的描述,“图解变形金刚”

经过目前为止的进展,人们可能会有这样的印象,自然语言现在可以很容易地解析。事实并非如此。一些问题依然存在。回到单词嵌入,我们现在可以使用注意机制来模拟单词关系。然而,考虑一下“他开了一家银行”这句话。从上下文中可以清楚地看出,“银行”就是金融机构。现在考虑“她坐在岸上。”同样,上下文信息解释了“银行”是用来坐的东西。

Word2Vec 或类似的框架只为每个令牌创建一个向量。然而,正如我们已经注意到的,一个词的意思是由其上下文决定的。并且频繁上下文可能在训练数据(用于获得嵌入)和测试数据之间变化。那么我们该如何解决这个问题呢?通过使用迁移学习。

迁移学习、语言模型和 ELMo

在计算机视觉任务中,迁移学习是一个标准过程。首先,学习任务 A 的模型,然后使用任务 B 的权重。通常,任务 A 和任务 B 已经在相同的数据类型上进行了训练。此外,正在解决的问题(对象检测、分类、翻译)足够相似。这个概念可以扩展到 NLP 领域。

我们在一个大数据集上预训练一个模型,修改这个模型,并在我们的任务中重用它。在预训练步骤中,模型已经学习了语言特征,例如句法或语义。优点是减少了新任务对数据的需求。

标准的预训练任务是语言建模。当我们训练一个语言模型时,我们会根据之前的单词来预测即将到来的单词。对于这个任务,ELMo 6变得相关。ELMo 是语言模型嵌入的缩写,由 LSTM 层组成。这些层中的几层被堆叠和训练以预测即将到来的单词。此外,该模型更进了一步:它是一个双向语言模型。序列被双向解析。为了获得嵌入向量,我们将隐藏层连接起来,并对它们求和(简化),如图所示,摘自 Jay Alammar 对 BERT and co. 的介绍:

计算嵌入的 ELMo 过程的示意图。图片来自 Jay Alammar 对 BERT 和 co 的介绍。

一旦我们有了一个完全训练好的模型,我们就可以通过用我们的句子查询模型来获得我们的嵌入。这如何帮助我们获得上下文?ELMo 已经在许多数据上进行了训练,它必须预测下一个单词。这项任务要求它学习上下文。例如,“他坐在[银行]”和“他去了[银行]”都以“银行”结尾,模型必须学习同一个单词的不同含义。

从这种模型中获得的向量包含了这种上下文信息——它们是上下文化的嵌入。因此,对于前面的“银行”示例,我们得到了两个不同的向量,这取决于“银行”的上下文然后,在我们的主任务中使用这些嵌入;ELMo 模型用作特征提取器。但是它很慢;我们不能进行表查找,但必须加载(潜在的巨大)模型。它依赖于循环网络。这就引出了伯特。

伯特

从传统的、基于 RNN 的序列对序列方法发展而来的成功经验同样适用于 ELMo 模型。我们可以用一堆编码器模块来代替 LSTM 层,这是我们从《变形金刚》中了解到的。这些修改为我们提供了 BERT [7]模型,这是变压器双向编码表示的缩写。输入序列的一部分被屏蔽,这使得它成为一个屏蔽语言模型。我们通过随机屏蔽令牌(默认值:15 %)来实现双向;我们不需要在两个方向上解析序列。

BERT 的输出是维度为 hidden_size 的层,在基本模型中设置为 768(堆叠 12 个编码器块)。这些输出向量是我们的嵌入,它们再次被语境化。与 ELMo 的嵌入一样,我们可以将它们用于我们的特定任务。或者我们可以用伯特。它在很多任务上都非常有效。我们可以将其用于情感分析、问题回答、命名实体识别(例如,将标记标记为名词)。基本型有 1.1 亿个参数,大型型有 3.4 亿个参数,您可以做几件事情。但是我们还没有达到 10 亿。进入 GPT-2。

GPT-2

GPT-2 [8]背后的想法与 BERT 的想法很接*:在大规模文本语料库上训练一个大型语言模型。GPT 是生成性预训练的缩写,2 表示这是第二次迭代。第一次迭代被称为 OpenAI Transformer [9]和堆叠式 Transformer 解码器层。伯特后来继承了这种架构。回到 GPT-2,该模型有 1.17 亿到 15.42 亿个参数——1.5 万亿个参数。因为它是一个语言模型,所以它可以执行的每个任务都被建模为一个完成任务。假设你想把英语翻译成拉丁语。首先,模型被训练成一个翻译系统,在推理过程中,你给它一个提示,比如

“政府已经发放了最新一轮的奖学金。="

“=”表示模型必须完成(即翻译)句子。在训练过程中,它看到了成对的“ = ,从而学会了“=”提示符的属性。翻译任务不是唯一的任务;GPT -2 也擅长总结和回答问题。

与 BERT 模型不同,GPT-2 没有对目标任务进行微调。在 BERT 在基础文本语料库上被训练之后,它针对个别问题被微调。这一步对于 GPT-2 来说是过时的,使其成为零射击设置。换句话说,它是一个通用模型,能够执行多种未经直接训练的任务。此外,它生成连贯文本的能力,通常相当于人类的工作,导致伦理上的考虑。例如,通过访问大型 GPT-2 模型,人们可以制造假新闻、假冒他人或制造大量高质量的垃圾邮件。

因此,GPT 网络背后的组织 OpenAI 最初决定不发布整个模型。相反,只公布了 1.17 亿和 3.45 亿个参数模型的训练权重。然而,在 2019 年底,研究人员还提供了大型模型,让任何精通 15 亿参数模型的人都有足够的权限。

即使我们现在已经达到了超过十亿个参数,仍然有更大的模型。十亿参数范围内有几种架构,万亿+参数有两种。

开关变压器

有几个架构有数十亿个参数。下图摘自 Nvidia 的博客,显示了语言模型的增长:

语言模型中的参数数量增长非常快。开关变压器(未示出)具有 1.5 万亿个参数。图片来自 Nvidia 的博客

由于我们已经达到了十亿参数阈值,我将介绍一个万亿参数模型,开关变压器[10]。该架构使用的关键变化是专家混合(MoE)方法。通常,模型对所有输入使用相同的参数。无论输入是猫还是狗的图像,所使用的权重都是相同的。在 MoE 设置中,模型为每个输入选择不同的参数(思考路线)。这种方法对应于稀疏神经网络,其中仅同时使用权重的子集。下图清楚地说明了这一点(摘自[10]):

如前所述,该图示出了修改后的变压器编码器模块。在这个原始块中,信息流是由块的布局预先定义的。相比之下,开关变压器模块维护几个前馈神经网络(而不是单个)。然后,路由器层选择将当前输入转发到这些网络(称为专家网络)中的哪一个。这种方法有效地最大化了变压器的参数数量。而且因为只咨询了一个专家,所以在计算上还是可行的。

有几个其他的技巧可以支持这么多的参数。其中包括并行化策略。在纯数据并行中,工作人员处理独立的数据分割,每个工作人员使用相同的权重。在模型并行性中,模型的层被划分给不同的工作者。一旦激活变得太大而不适合单个设备,这种策略就很有用。开关变压器结合了这两种技术。还有很多细节在用。然而,讨论它们超出了本文的范围,所以我鼓励你自己去研究。我特别推荐讨论和未来研究方向部分。

随着开关变压器拥有超过一万亿个参数,我们已经到达了旅程的终点。但肯定不是所有的 NLP 问题都解决了。例如,目前的研究集中在使大模型变小(蒸馏)和减少偏差。我们可以从即将出版的书中期待很多。

摘要

自然语言处理有了巨大的发展。从一个热点向量来表示标记开始,它已经发展到嵌入来更精确地捕捉含义。慢慢地,这些向量不再从 Word2Vec 或类似的框架中获得,而是从语言模型中提取(ELMo,BERT)。这些模型从 1 亿到 3 亿个参数开始。很快,越多的参数获得越好的分数就变得越明显,因此研究人员不断扩大权重的数量。GPT-2 模型随后突破了十亿参数阈值,被更大的模型所取代。训练如此多的参数具有挑战性,如果没有大规模增加的计算,这是不可能的。由 TPUs 供电,开关变压器达到了超过一万亿个参数。而这仅仅是开始。

参考

[1] Mikolov 等人,利用语言间的相似性进行机器翻译,2013,arXiv

2 Sutskever 等人,神经网络的序列对序列学习,2014,神经信息处理系统(NIPS)进展

[3] Cho 等,利用统计机器翻译的 RNN 编解码器学习短语表示,2014,arXiv

4 Bahdanau 等,联合学习对齐和翻译的神经机器翻译,2015,ICLR

[5]瓦斯瓦尼等人,注意力是你所需要的全部,2017,NIPS

6 Peters 等人,深度语境化的词语表征,2018,arXiv ( 幻灯片)

[7] Devlin 等人, BERT:用于语言理解的深度双向变压器的预训练,2018,arXiv ( 幻灯片)

[8]拉德福德等人,语言模型是无监督的多任务学习器,2019,OpenAI 博客

[9]拉德福德等,通过生成性预训练提高语言理解,2018,OpenAI 博客

[10] Fedus 等人,开关变压器:利用简单有效的稀疏性缩放至万亿参数模型,2021 年,arXiv

自然语言处理:III

原文:https://towardsdatascience.com/natural-language-processing-iii-b067c5d0e89c?source=collection_archive---------36-----------------------

HMM & LDA 的一瞥

我已经在这个系列的第一部分和第二部分中解释了 NLP 的基本知识。可能会让你吃惊的一件事是,没有一个文本预处理没有解释单词之间的任何隐藏关系。这个博客会让你对 NLP 可用的数学工具有所了解。我们来了解一下。

马尔科夫模型:

马尔可夫的性质告诉我们

在一组事件中,任何事件都依赖于它的前一个事件。

版权所有 somesh

以上是已经发生的一系列事件。所以根据马尔可夫的属性事件,2 将依赖于事件 2,事件 3 将依赖于事件 2。这意味着明天天气的概率取决于今天,而今天天气的概率取决于昨天。

一些术语:

1。有多少个状态被考虑用于概率的计算是状态空间。

2。遵循马尔可夫性质的事件集合将形成马尔可夫链。

3。事件发生概率的矩阵称为传递矩阵。

版权所有 Somesh

1。天气热的时候天气会有雾有雾的概率有多大?

状态空间= {多雾,炎热}

初始概率= {0.7,0.1}

Q = {热,多雾,多雾}

P(多雾,多雾|热)= P(多雾|热)* P(多雾|多雾)

向右复制一些

所以结果是 0.7*0.3=0.21

Q = {热,多雾,多雾,热,多雾}

可以用 P(Hot)* P(F | H)* P(F | F)* P(H | F)* P(F | H)来计算

它仅仅是事件跃迁概率的产物!

隐马尔可夫模型:一种改进的马尔可夫模型

版权所有 Somesh

隐马尔可夫模型 由一个普通的马科夫链&的一组观察变量组成。

上图代表天气和相应的心情。天气是一种隐藏状态,情绪是依赖于隐藏状态的观察变量。简单地说,当天气多云时,心情愉快的概率是 0.65,概率是 0.75。

版权所有 Somesh

隐藏状态的概率矩阵是一个转移矩阵,其中观察变量的概率是一个发射矩阵

以下情况发生的概率有多大?

版权所有 Somesh

用数学术语来说,我们可以把它写成,

版权所有 Somesh

这可以使用 P(多云)、P(快乐|多云)、P(多雾|多云)、P(悲伤|多雾)、P(多云|多雾)、P(快乐|多云)的乘积来计算

我们可以从跃迁和发射矩阵中找到除 P(多云)以外的所有值。P(多云)的值可以使用马尔可夫链的*稳分布来计算。重复矩阵乘法和归一化左特征向量来计算分布。

但是,与特定的情绪序列相对应的最可能的天气序列是什么呢?

你可以用每个节点的概率来计算。那么概率较大的隐藏状态将是答案。从数学上讲,我们可以计算出这个公式。

版权所有 Somesh

利用贝叶斯定理,arg max P(Y|X)*p(X) / P(Y)

P(Y |X) = P(Y1 | X1)*P(Y2|X2)……。P(Yn|Xn)

进一步可以写成πP(Yi | Xi)&利用马尔可夫的性质,

P(X)=πP(Xi | Xi-1)。对于 Xo,你可以使用马尔可夫链的*稳分布来计算。所以最终等式会变成—

arg maxπP(YI| XI)* P(XI| XI-1)。就这些了嗯!

你可以在生物信息学、自然语言处理、语音识别等领域实现它。

LDA-潜在狄利克雷分配

LDA 对于在给定文档中找到相当准确的各种主题非常有用。当你处理主题建模时,这是很方便的。考虑下面的几个例子。

1.我喜欢蜂蜜和浆果。

2.熊也喜欢蜂蜜。

3.熊和熊猫很可爱。

如果你理解了上面的句子,你会得到食物和动物的主题,第二句话将是两个句子的组合。在决定主题的时候,你必须明白一些事情。LDA 有两个方面:1 .文件中的文字——这是已知的。2.你需要计算才能知道你所学单词的主题。

每个文档都是主题的概率分布,每个主题都是单词的概率分布。换句话说,文档是主题的混合物,主题是单词的混合物。

像- is,am,are,has,have 等这样的词你必须去掉,因为它们不携带信息。

在你开始找题目之前,你必须决定你想要多少题目。这基本上表示为 K.

除了你目前拥有的单词以外的所有题目都可以考虑。

LDA 是如何工作的?

  1. 选择你认为语料库中存在的主题数量。

2.仔细阅读每个文档中的每个单词及其主题。

3.查找该主题在文档中的出现情况,其次是该主题的整体出现情况。在此基础上,指定一个词作为新的主题。

4.执行多次迭代,直到获得合适的主题。

同样,最后一步是您作为人的工作,通过改变文档术语矩阵中的参数、主题数量和迭代次数来解释主题,并在达到目标时停止!

还有其他的主题建模技术,比如潜在语义索引和负矩阵分解。

希望你能理解,并请在评论区写下你的想法。我会为 NLP 系列带来更多有趣的话题。在 关注我,或者订阅我的博客了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @ RoutraySomesh&Gmail联系

自然语言处理和社会科学

原文:https://towardsdatascience.com/natural-language-processing-social-sciences-94a35a8a7c78?source=collection_archive---------21-----------------------

这篇文章解释了自然语言处理(NLP)模型在社会科学中的应用。

Madhur ChadhaUnsplash 上拍摄的照片

这是一篇解释自然语言处理(NLP)模型如何应用于社会科学的文章。此外,将使用由 OpenAI 开发的 GPT-3 NLP 模型给出几个例子。

目录

描述

其核心是,自然语言处理工具将预测在处理输入文本后应该输出什么文本。通常,会使用复杂类型的神经网络,这是一种机器学习构造。

可能性

使用 NLP 模型处理文本的常用方法包括:

文本延续:这是自然语言处理模型可以给出的最基本的任务类型。基于概率,它将继续输入文本,只是长度受限于模型允许运行的周期数。您可以输入句子:“吸烟是”,其中模型可能首先吐出单词“不好”,但如果再运行几个周期,这可能“对您的健康有害”。

回答问题:同样,基于给定的约束,模型将返回给定问题的答案,开放式或是或否。你甚至可以要求 NLP 模型就给定的主题写文章,尽管当被问及精确的科学时,它们的表现相当差;真正的理解还不存在。根据所使用的定义,你可能会认为语言模型目前也不理解其他主题。只是对于社会科学相关的问题,更容易预测一个接一个的正确单词。这可能是部分原因,因为社会科学在本质上相对更基于论证,而有形的社会科学相关的论证通常遵循类似的模式。当你进入数学直觉的领域,事情往往会变得更加抽象、多变和复杂。注意,所有接下来的例子都可以被认为是这个例子的子集,但是额外的细节是出于信息的原因给出的。

摘要:给出一段文本作为输入,并返回一个符合先前指定约束的摘要作为输出。一些复杂的 NLP 模型甚至能够输出摘要,就好像是给二年级学生看的一样。通常,这些模型相当善于挑选应该包括在摘要中的内容,这可能是因为上一个例子中给出的相同推理路线:写摘要通常需要查看类似的短语,这些短语表明文本中的重要性,并且一些语法“理解”似乎存在于这些模型中。这种理解的概念是值得思考的。这些模型估计了某段文本在最后一段之后出现的可能性,但是我们在哪些方面与之不同呢?这样的问题怎么回答就不那么清楚了。这并不意味着我们在某种程度上与这些模型相似的可能性很高,这种可能性确实存在。

在正文中寻找答案:这是一个与上一个例子有些关联的例子。这里,所提供的文本连同与所提供的文本相关的问题一起被给予模型。与摘要一样,对于这些模型来说,这通常是一项简单的任务,但是一旦模型被要求从文本中给出的信息中进行抽象,它就很难有效地内插或外推这些想法。

文本分类:这也与前面的例子相关。一个例子是要求模型将给定文本分类为包含积极、中立或消极情绪。这对于分析与某个主题相关的大量社交媒体帖子的情绪非常方便。

编写代码:为了恢复,模型本质上是对下一个文本的预测(准确地说,通常模型一次预测一个'标记)。这些模型是在有标签或无标签的数据上训练的,前者是在某些指定的 NLP 任务的流线被指定时选择的,而后者是在使用模型时需要更多的自由度时选择的。标记数据的一个例子是一段带有相应摘要的文本,并相应地进行标记。当涉及到代码时,这些数据通常包含基本的示例,由于其学习性质,该模型通常不擅长预测边缘情况下返回什么,或者如何根据其“知识”进行推断以解决不同的编码问题。因此,模型能够很好预测的代码通常与标准的、已知的编码问题相关联。

取自 OpenAI 网站的一个例子的输入: Use list comprehension to convert this into one line of JavaScript: dogs.forEach((dog) => { car.push(dog); }); JavaScript one line version:

带有 GPT-3 返回的输出: dogs.forEach(dog => car.push(dog))

除非您的特定问题与某些数据条目有许多相似之处,例如,只是执行顺序不同,否则您的特定问题输入将不会得到满意的回答。

关联

基于上面给出的例子,我们可以提炼出自然语言处理在社会科学中的三个应用领域:

1。教育工具:对于给出的所有示例,它认为模型能够根据提供给模型的数据返回输出。鉴于输入的是我们已经知道的东西,而模型在这些知识上的构建能力还没有以不同方式回忆信息的能力那么复杂,NLP 模型可以被视为工具,既可以以更小的片段再现我们已经知道的东西,也可以执行我们自己也可以完成的基本任务,如总结或情感分析。尽管模型可能只“知道”人类也知道的事情,但这并不意味着模型可能“知道”的所有事情也为任何给定的个人所知。因此,在某种程度上,该模型类似于我们钟爱的搜索引擎 Google,根据手头的用例,可能更具延展性,并配备了额外的功能,如摘要技能。

有一个例子很好地说明了这些工具如何应用于教育:

2。研究中的辅助任务工具:与前面的观点重叠,人们可以将他们的知识扩充到 NLP 模型在某种程度上已经训练过的数据中嵌入的知识。此外,用例的一些想法包括根据一些标签集对其他研究人员的论文进行分类,从而建立一个易于访问的知识库。然后,可以提出问题在这些论文的正文中查找。还可以向模特提出快速的一次性问题,以查找必要的一般信息。然而,谷歌也许能够更可靠地做同样的事情。此外,将草稿转换成写得很好的语言是可能的,但是成功执行这样的命令需要相当多的逻辑,所以这可能会给模型带来困难。同样的道理也适用于将书面文本转换成领域外的人能够理解的更清晰的语言。对你写的东西进行快速总结并发给研究合作者也是可能的。就目前而言,自己写摘要或研究论文似乎更可靠(如果你的研究超出了模型训练数据中嵌入的“知识”的界限)。不过,看看 NLP 模型如何总结你的工作也无妨。最后,编写代码可以帮助简化作为最终项目组成部分的标准算法的实现过程。

3.用于研究的数据收集:特别是对于政治研究项目,使用社交媒体的数据收集针对某些相关话题的情感分析可以在瞬间产生大量可信的数据。以类似的方式,它可以用来观察思想如何在社交媒体上传播,金融新闻如何在网上处理和在公众中谈论,并最终影响我们的经济。可能有更多的可能性可以探索,但命名的似乎是最简单的。

示例性实现

在写这篇文章之前,我也尝试过使用社会科学的 NLP 模型,准确地说,是 OpenAI 的 GPT-3,我被授予了 beta 访问权限。我的基本计划是创建一个辅助的和鼓舞人心的工具,在那里简短的问题将得到简短的回答。其核心是,我开发了两种不同的提示,用户可以通过这两种提示询问一些决定某种现象的因素,或者用有限的句子解释是什么导致了一个事件的发生。在对每个不同问题的参数做了一些调整后,通常,这个模型会发挥作用。对于因素列表提示,出现的不准确性比解释提示更多,这可能是因为描述事件更像是一种回忆行为,而不是命名某种现象的因素,后者更经常需要从训练的数据中建立。换句话说,如果你能说出一些特殊的历史事件,你也能说出是什么导致了它。由于 OpenAI 的 GPT-3 基本上是在互联网上训练的,所以它是在互联网上注册的事件上训练的,因此它也知道导致最详细记录的事件的原因,因为这些原因通常包含在命名它们的文章中。某些特定现象的因素通常不太好记录,有时需要对数据进行更多的外推或插值,有人认为这些 NLP 模型并不擅长。

使用该工具的一个例子:

提交工具的因子提示

结论

自然语言处理已经走过了漫长的道路,并产生了令人惊讶的结果。通常,在某些模型发布后的媒体*台上,这些模型能够做什么的最惊人的例子会被挑选出来,例如一个采访,在采访中向模型提出精心设计的问题,以确保它能给出有趣的答案(本文包含为什么这些问题对模型来说很容易回答的解释)。在现实中,当这些模型暴露于甚至需要最基本的问题解决的中等复杂的问题时,它们就崩溃了。然而,NLP 模型有许多用途,并且随着其能力的不断发展,自然语言处理模型在不久的将来将会发挥相当大的作用是很有可能的。

自然语言处理任务

原文:https://towardsdatascience.com/natural-language-processing-tasks-3278907702f3?source=collection_archive---------21-----------------------

NLP 是一组操作,主要是通过各种活动处理文本数据。在这些计算机活动的帮助下,将非结构化的信息转换成明确的数据或从信息中生成文本是可能的。在这篇文章中,我给你列出了这些不同的任务。

照片由 Unsplash 上的 Dmitry Ratushny 拍摄

介绍

我们与生俱来的对话能力,是从我们的家庭、老师、同事那里获得的……我们在学校学习,在我们的一生中,掌握着写作和说话的词汇和语法。自然语言与计算机语言相反,因为它缺乏明确的逻辑结构、丰富性以及管理它的规则(通常复杂而模糊)。由于计算机还不能自然地理解我们的语言,一系列的活动已经被创造出来来连接两个世界:人类和机器。

信息通常以三种形式提供:

  • 一种结构化的表示方法,带有与表格相关的信息的明确标记,以数据库表格或图形的形式呈现。
  • 这是一种半结构化表示,具有明确的高级上下文信息,如发票或订单数据,这些数据将始终包含相同的信息。
  • 非结构化表示将需要这里指出的提取工作,以将信息转换成显式数据。这些数据具有不同的编辑质量,混合了不同类型的信息,如人名、地名、日期等。主要目的是检测文本元素的结构,识别这些元素的属性以及将它们链接在一起的关系。

语言分析在两个层次上进行:词汇分析,它基于对单个单位的处理,例如字素(记录一个音素的字母或字母组,例如“ewe”、“eau”或“eu”)、音素(音段,例如音/o/),以及语素(单词的段,例如前缀或后缀);以及语义分析,侧重于单词和句子的整体意义。

长期以来基于显式规则,NLP 现在充分利用了机器学习提供的自动规则学习功能。这种学习是由语言或相关业务领域的专家进行的标记工作提供的。现在让我们详细说明主要的 NLP 过程。

注意:NLP 任务的这种组织是个人的。

NLP 任务:主要类别(作者的图表)

NLP 任务:基本语言特征(作者的图表)

NLP 任务:增强的语言特性(作者的图表)

NLP 任务:语音管理和光学识别(作者的图表)

NLP 任务:文本分类(作者的图表)

NLP 任务:语言生成(作者的图表)

NLP 任务:其他任务(作者的图表)

基本语言特征

第一类包括“基本”处理任务,例如:

  • 语言识别在于检测文本中使用的语言。它允许定义用于执行其他活动的模型。
  • 分句(也叫句界消歧)、,或者组词。许多 NLP 任务需要在句子或单词级别上工作,因此这种处理非常重要。因此,这一活动在文本处理链中至关重要。
  • 词干词汇化。词干提取包括提取单词的词根。引理化允许将一个单词简化为它的标准形式(引理)。它也被称为“字典”形式。
  • 单词嵌入和句子嵌入,通过对段落和文档的扩展,将元素转化为数字的向量。矢量化目前是执行相似性搜索、聚类、分类等的基本操作。

高级语言特征

第二类包括语义处理任务,例如:

  • 识别命名实体 (NER)。一些单词或词组可以被分组到称为实体的类别中。没有这样的标准,但我们通常会找到组织、地点(地址、城市等。),以及人[ENAMEX];货币和百分比[NUMEX];时间和日期[TIMEX];vehicle…一般来说,特定于被治疗领域的类别被添加到预定义的类别中。确定实体的关系在于将唯一标识符与实体相关联。关系抽取是预测句子中实体的属性和关系的任务。也有可能找到其他类别的提取:特征提取,关键词提取,概念提取…
  • 词性 (POS)也叫语法标注。这项活动包括关联语法信息(名词、动词、冠词、形容词、代词、副词等。)与句子中的单词。
  • 分块,也是浅层解析,识别连续的记号间隔,这些记号形成与被处理的领域中的概念相对应的句法单元。这项活动首先识别句子的组成部分(名词、动词、形容词、副词等)。)然后将它们与具有明显语法意义的高阶单位(名词组、动词组等)联系起来。)
  • 统计解析包括生成解析树(也称为派生树),包含句子词汇单元的结构、依赖性和分类。根树根据上下文无关语法表示句子的结构。
  • 语义关系抽取是预测句子中实体和词组的属性和关系的任务。*年来,人们对链接语法的兴趣有所增加,导致了提取质量的提高,从而对这种技术产生了新的兴趣。如今存在许多类型的依赖,这使得理解哪些活动被链接以及使用哪棵树变得不容易:句法、语义、形态、韵律…
  • 单词的词义消歧在于确定单词在句子上下文中的含义。
  • 共指消解涉及确定与一个或多个表达式相关的事物或人。这种确定可以在句子、段落或文档的上下文中进行。
  • 否定检测旨在识别文本中的否定暗示。

语音处理

语音处理在语言处理领域有着特殊的地位,因为书面语言和使用声音频率来表达语音之间有着更大的差异。

语音处理涵盖许多活动:

  • 所讲语言的标识。这项活动包括识别说话者使用的语言。这是选择语言模型的先决条件。
  • 自动语音识别 (ASR)在于将声音转换成文本或意图。这种处理包括几种语言处理。
  • 语音中的情感识别在于识别语音中的情感,而与语义内容无关。
  • 说话人识别就是从声音的特征来识别一个人。它包括回答这个问题:“谁在说话?”
  • 说话人验证包括检查说话人是否是预期的人。它在于回答这个问题:“是 X 在说话吗?
  • 声音克隆包括复制一个声音,以允许生成任何句子。
  • 对话中的语音分离包括分离在单个麦克风中同时说话的几个语音。
  • 语音合成是从文本中生成语音。下面是我关于语音合成技术的文章的链接。

光学识别

光学识别包括检测图像中的书写并将信息转换成文本。这种书写可以来自印刷字符或手写。

  • 光学字符识别 (OCR)是将包含印刷或键入信息的图像转换为文本的过程。
  • 手写识别 (HWR)在于检测书写文本的模式并将其转换成计算机文本。

文本分类

这些活动的目标是成功地检测句子或文档的主题、领域。

  • 句子或文档的分类寻求识别与其相关联的一个或多个类别。
  • 主题建模在于找到一篇文章、一篇文章或者一个或几个文档的主题。
  • 讽刺讽刺的检测。
  • 感觉/情绪分析。这是为了确定一个文本是否包含感觉或情绪。下面是我关于情绪/情感分析的文章的链接。
  • 意见提取类似于情感检测,但是在于检测意见的主题。
  • 语义聚类包括在没有监督的情况下生成具有相同语义的单词、句子的集合/组。

语言生成

这一类别包括大量允许从可用信息中产生文本的服务。最*,随着具有数十亿个参数的统计模型的产生,这些活动得到了强调,并在接*万亿字节的语料库上进行了训练。

  • 语言建模 (LM)包括创建一个统计模型,对语言中单词序列的分布进行建模。这种模型可用于预测文档中的下一个单词或字符。这种语言建模用于其他语言生成任务。
  • 自然语言生成 (NLG)。这些多学科包括从内容中生成正确格式的文本。在此活动中,我们发现从令牌(例如实体)或表生成数据描述;面向任务或目标的对话的生成,甚至是自始至终的整个对话的生成;故事、文章的产生。释义是从一个句子创造新句子的操作。这种技术可以用来扩充现有的语料库。计算机代码的生成也是工作的一个重要轴心。
  • 文本校正包括添加标点符号(例如,在语音到文本转换的末尾)如逗号或句号,或者校正拼写或变化错误。
  • 增加、替代和减少。文本扩充是通过添加元素或用其他类似元素替换元素来转换句子。缩减是为了给定的目的删除不必要的信息。文本规范化是将数字、日期、首字母缩写词和缩略语转换成普通文本的过程。
  • 自动文本摘要通过提取最具代表性的句子或通过抽象生成新文本,将文本压缩成一组精简的句子。
  • 自动机器翻译使用一套技术将文本或语音从一种语言翻译成另一种语言。
  • 问答有很多子活动。有开放领域(通常是维基百科)或闭卷问答系统;从知识图中自动提取答案;从答案生成问题(即 Jeopardy 游戏);问题质量评价;自然语言推理在于从一个“前提”中确定一个“假设”是真(蕴涵)、假(矛盾)还是未确定(中性)。

其他任务

存在许多其他活动,但是不太普遍,应用起来更复杂,或者甚至更机密,因为它们在 NLP *台中不太常见。

例如:

  • 回指解析是将一个回指与其关联的单词连接起来的任务。
  • 常识包括使用“常识”模式或对世界的了解来做出推论。
  • 维度缩减用于将单词向量或句子向量的大小缩减为信息的精简版本。
  • 域适应使用不需要标记的目标域数据的无监督神经域适应技术。
  • 问题质量评估旨在开发主观问题回答算法,以验证问题是否是高质量的,或者是否应该修改或标记。
  • 屏蔽语言建模(MLM)是自编码语言建模的一个示例,其中句子中的一个或多个单词被屏蔽,模型根据句子中的其他单词预测这些单词。
  • 缺失成分分析旨在确定文本中缺失的成分。这些元素是一组现象,它们与预期的事物相关,但在文本中没有明确提到。省略、连接回指等缺失成分有不同的类型。
  • 语义角色标注就是给句子中的词赋予语义(一种“意义”),比如把值赋予名词组,把谓词赋予动词组。语义分析通常在句法和形态句法分析之后进行。
  • 篇章蕴涵旨在确定两个句子是否矛盾。
  • 句子的词汇链接、下一句的预测等。

观点

NLP 由许多自动语言处理任务组成,允许从非结构化内容中探索和提取信息。*年来,机器学习技术的贡献推动了该领域的发展,使其有可能达到有时优于人类的质量水*。这是几项任务的集合,将使我们能够取得非凡的成果。

上面没有提到一个活动,因为严格地说,它不是 NLP 任务。该活动涵盖所有活动,因为它包括执行结果的验证/比较活动。它包括通过专用于要执行的任务的语料库来检查算法的性能。这种验证是基本的,因为它将允许我们通过使用一个共同的参考框架来评估治疗而获得一个分数。然而,这一活动受到以下事实的质疑,即算法因此被优化以在被选作参考的语料库上获得最佳可能得分,并且难以概括。

使用 SQL 导航时间序列

原文:https://towardsdatascience.com/navigating-time-series-with-sql-39068018ba7e?source=collection_archive---------6-----------------------

通过分析顺序数据巩固您的 SQL 知识

照片由来自 PexelsLorenzo 拍摄

从 SQL 开始,我最大的错误之一是我试图通过概念化来学习一切。

我的意思是,如果你有编程背景,只要理解 SQL 关键字和函数背后的逻辑应该就没问题了吧?

不对。

仅仅通过学习语法来学习编写 SQL 就像通过阅读字典来学习说英语一样;这简直是疯了。

一旦你认为你已经达到了某个里程碑,你的时间会更好地用在项目中。

也就是说,我发现许多人因为只为他们的项目选择相对简单的数据集而搬起石头砸自己的脚。对于更简单的数据集,您只能使用更基本的 SQL 关键字和函数。

这是一个很好的起点,但是它剥夺了您应用更高级技术的机会,比如 cte 和窗口函数。

明白真实的数据是杂乱无章的;它不像你在教程中看到的素数和适当的表那样友好。

因此,如果你想展示你的分析能力和 SQL 知识,最好是采用展示这些特征的数据集。

使用 SQL 的时间序列

出于多种原因,使用时间序列数据集有助于您学习 SQL。

时序数据本质上存储的记录并不是相互独立的。分析此类数据需要在列与列之间进行更复杂的计算。

这将要求您展示您对简单和高级 SQL 技术的理解。

因此,我强烈建议对那些希望巩固对 SQL 原理的理解的人进行时间序列分析。

个案研究

让我们试着为显示每个国家的疫苗接种时间序列的数据集编写一个 SQL 脚本。

将用于这次演示的数据集可以在这里访问(无版权)。疫苗接种表显示每天收集的不同国家的各种疫苗接种统计数据。

为了缩小分析的范围,让我们将我们的研究限制在 3 个特征上:国家、日期和每天接种疫苗的次数。

注意:下面的代码片段是在 SQL server 中运行的,所以语法可能与您最熟悉的 SQL 方言略有不同。

代码输出预览(由作者创建)

如果我们对如此大量的信息或如此精细的粒度不感兴趣,那会怎样?

假设我们只对按月观察每个国家的疫苗接种感兴趣。

此外,不考虑世界上的每个国家,我们只对英国(即英格兰、苏格兰、威尔士和北爱尔兰)的疫苗接种感兴趣。

我们可以过滤掉不需要的记录,并使用以下查询将每日疫苗接种记录转换为每月记录。

代码输出预览(由作者创建)

对英国每月一次的疫苗接种的任何分析都需要使用这个生成的表,所以为了方便起见,让我们将这个数据存储到一个名为“# Monthly _ Vaccinations”的临时表中。

有了这个临时表,我们可以开始从数据中提取见解,以了解每个国家的疫苗接种计划的更多信息。

每个国家疫苗接种的 3 个月移动*均值是多少?

移动*均经常用于时间序列分析,因为它通过限制观察变量的不稳定变化的影响来帮助减少噪声。

要计算 3 个月移动*均线,我们需要:

  1. 查找当月和前两个月的疫苗接种值。
  2. 找出每行在 3 个月内接种疫苗的*均次数。

幸运的是,我们可以使用窗口函数在一行代码中完成所有这些。

代码输出预览(由作者创建)

每个国家每月接种疫苗的百分比变化是多少?

另一个需要考虑的重要变量是疫苗接种的百分比变化。毕竟,疫苗接种的任何急剧上升或下降都会引起公共卫生官员的兴趣。

要找出每月疫苗接种的百分比变化,我们需要:

  1. 查找每行上个月的疫苗接种数量
  2. 给定当前和以前的疫苗接种值,计算每行的疫苗接种百分比变化

我们可以用 LAG 函数找到每条记录以前的疫苗接种值。请注意,第一行的先前疫苗接种值为 0。

代码输出预览(由作者创建)

该表提供了我们计算每行疫苗接种百分比变化所需的所有信息。将它存储在 CTE 中后,我们可以计算每个国家每个月接种疫苗的百分比变化。

代码输出预览(由作者创建)

每个国家哪个月的疫苗接种率最低?

要确定每个国家表现最差的月份,我们需要:

  1. 根据接种疫苗的数量对记录进行排序(从低到高)
  2. 选择等级最高的行(即等级=1)

我们可以使用 RANK 函数根据接种记录的数量对每个国家的记录进行排序。

代码输出预览(由作者创建)

用 CTE 存储这些数据后,我们可以继续查询,选择每个国家中排名最高的记录。

代码输出(由作者创建)

所有四个国家在第 9 个月(9 月)登记的疫苗接种数量最少。

RANK 函数允许我们对表现最差的月份进行更深入的搜索。

例如,如果我们想找出每个国家最差的 3 个月,我们只需要修改 WHERE 语句。

代码输出(由作者创建)

哪个国家目前在管理疫苗方面最成功?

直接比较国家的一个好方法是找出每个国家接种疫苗总数与人口的比率。

考虑这些国家的人口是合乎逻辑的。直接比较每个国家的疫苗接种总量是不公*的,因为这些国家在人口规模上有很大差异。

为了找到疫苗接种与人口比例最佳的国家,我们需要:

  1. 查找每个国家接种的疫苗总数(累计)
  2. 找出每个国家的人口
  3. 计算每个记录的疫苗接种与人口的比率
  4. 只保留最*一个月的记录

首先,我们需要知道每个国家总共注射了多少疫苗。目前,我们只能获得每月注射的疫苗数量。

要找到累计疫苗接种数,需要计算累计总数。这可以通过窗口功能来实现。

代码输出预览(由作者创建)

接下来,我们需要知道每个国家的人口。

让我们创建一个包含这些信息的表。

代码输出(由作者创建)

让我们使用每 10 万人接种疫苗的数量作为我们选择的评估指标。

我们可以通过一个连接合并名为“running_total”的 CTE 和人口表,然后计算每 10 万人的疫苗接种数量,从而直接比较这些国家。

代码输出预览(由作者创建)

最后一步是用第二个 CTE 存储这些信息,并过滤掉不需要的记录。结果将显示每个国家最*一个月的疫苗接种总数。

代码输出(由作者创建)

根据评估标准,苏格兰在为人民接种疫苗方面做得最好(到目前为止)。

结论

照片由 Unsplash 上的 Prateek Katyal 拍摄

现在,您已经对如何将 SQL 关键术语和函数应用于时间序列数据有了一些了解。

也就是说,即使你从这个演示中学到了很多,如果你自己进行类似的分析,你会取得更大的进步。

本案例研究仅包括英国的国家。我邀请你利用这个数据集,对其他国家进行类似的分析。

我祝你在数据科学的努力中好运!

参考

Preda,G. (2021)。新冠肺炎世界疫苗接种进展,第 221 版。2021 年 11 月 27 日检索自 https://www . ka ggle . com/gp reda/covid-world-vaccine-progress。

Tableau 导航设计

原文:https://towardsdatascience.com/navigation-designs-in-tableau-e1ba7e35cf7?source=collection_archive---------12-----------------------

深入分析

设置引人注目的导航结构的指南

玛丽安·博斯Unsplash 上拍摄的照片(由作者编辑)

在使用商业智能(BI)工具进行数据分析的领域,我们很少使用专用的独立仪表板。通常在组织中,我们需要将多个仪表板编织在一起,有时还需要外部资源来创建和理解更大的画面。在这方面,我们需要将用户导航集成到其他仪表板或外部来源。拥有一个好的导航结构是至关重要的,因为它为最终用户提供了一种类似网站的感觉,并允许他们与您的仪表板无缝交互。

在这篇文章中,我将通过用例来说明如何在 Tableau (2021.3)中创建这样一个导航结构的不同可能性。在本演练中,我们将使用 Sample - Superstore 工作簿,它有六个仪表板概述、产品、客户和发货(默认)以及绩效和预测(另外从默认内置视图中创建)。

按钮导航

用例:以文本按钮的形式在两个仪表板产品和客户之间创建来回的用户导航。

因为在这个用例场景中,仪表板产品和客户都在同一个工作簿中,所以我们可以使用导航对象,它将充当导航按钮。

为此,将导航对象从对象窗格拖放到仪表板中,并设置其属性。请记住,我们将需要两个导航对象,一个用于产品,另一个用于每个仪表板上的客户。您可以根据自己的选择进一步自定义格式选项。但是请记住关于选项背景颜色,当前激活的仪表板需要是明亮的,而非激活的仪表板需要是浅色的。这可以很容易地通过使用相同的基色并调整其不透明度来实现。这将最终为您提供主动/被动效果。默认情况下,Tableau 提供了直观的工具提示,但是如果您需要定制它,请继续。

导航对象及其属性(来源:图片由作者提供)

按钮导航(来源:图片由作者提供)

类似工作表的按钮导航

使用案例:在概览控制面板上以文本按钮的形式添加外部 OneDrive URL 存储库链接。

由于在这个用例场景中,我们需要将一个外部链接附加到一个文本按钮来进行导航,并且由于上面的带有按钮的导航的设计不支持这个场景,我们需要创建一个工作表按钮来模拟一个 Tableau 导航对象。

为此,创建一个新的工作表,命名为储存库,带有空白计算字段,并将其添加到文本卡。此外,格式化工作表背景颜色,编辑并添加按钮名称,此处为文本的储存库,并将其对齐为中间居中。此外,格式化工具提示说明,类似于在第一个设计导航中观察到的按钮,此处导航到“OneDrive 团队存储库”

存储库工作表及其属性(来源:图片由作者提供)

继续将此储存库工作表添加到您的概览仪表板,并对齐&位置,使其看起来像一个按钮。最后,通过仪表板菜单- >操作… 添加一个指向外部 OneDrive 存储库链接的 URL 操作,并在 Select 上执行到该工作表。

存储库工作表 URL 操作(来源:作者提供的图片)

类似工作表的按钮导航(来源:作者图片)

图像导航

用例:向每个仪表板添加公司徽标,并将其链接到公司网站。

在这个用例场景中,我们将利用图像对象进行导航,并将我们公司的网站链接附加到它上面。

为此,将图像对象从对象窗格拖放到每个仪表板中,并设置其属性。在我们的例子中,我们有 Tableau 徽标,同样,您可以从本地存储或指向该图像的 URL 链接中插入贵公司徽标的图像文件。在待打开的 URL中,添加您公司的网站链接,点击即可显示。

图像对象及其属性(来源:作者提供的图像)

用图片导航(来源:作者图片)

使用形状导航

用例:为每个仪表板创建一个 back image 按钮,在鼠标悬停时,该按钮将用户导航回外部主/主仪表板。

在这个用例场景中,我们将把我们的外部主仪表板看作是作为 Tableau 解决方案库的一部分在 Tableau 服务器上发布的超市概览仪表板;因此,这将是一个外部 URL 链接。

为此,创建一个新的工作表,命名为背面,带有空白计算字段,并将其添加到标记卡上的颜色形状。此外,从形状选项板中选择所需的形状(或者,您也可以通过将图像文件保存在本地 Tableau 存储库中的文件夹 Shapes 中来使用您自己的自定义形状),相应地格式化其颜色、大小和工具提示。添加与第一个设计按钮导航类似格式的工具提示说明,此处为导航至“概述”。

后台工作表及其属性(来源:图片由作者提供)

返回工作表添加到每个仪表板后,添加仪表板 URL 操作 ( 仪表板菜单- >操作……->添加操作- >转到 URL……),在 Tableau 服务器上发布仪表板的 URL 并在鼠标悬停时执行(在我们的示例中为超市概览)。然后概览仪表盘将打开,无需点击鼠标。

返回工作表 URL 操作(来源:图片由作者提供)

用形状导航(来源:图片由作者提供)

同样,也要以这样一种格式设计您的外部主/主页仪表板,它还提供了返回到每个单独仪表板的导航。

菜单导航

用例:在产品仪表板上创建一个下钻菜单,以查看所选产品的性能和预测仪表板。

因为在这个用例场景中,所有的仪表板都在同一个工作簿中,所以我们可以使用仪表板过滤动作来创建下钻菜单。

为此,在产品仪表板上,在工作表产品视图上创建两个过滤器操作(仪表板菜单- >操作…- >添加操作- >过滤器)。一个用于衡量产品性能,另一个用于查看产品预测。您可以对所有选定字段执行过滤,也可以隐藏仪表板的内容,直到通过排除所有值 做出选择(这将有助于更好的仪表板性能)。此外,仔细选择名称,因为它将作为菜单选项出现。此外,我还添加了一个后退按钮,以便从两个菜单仪表板中的每一个导航回主产品仪表板。

产品性能的过滤动作及其属性(来源:图片由作者提供)

产品预测的筛选操作及其属性(来源:图片由作者提供)

带菜单的导航(来源:作者图片)

最后,一些额外的提示来丰富最终用户的导航体验,添加参数?:link target = _ self&:embed = yes在 URL 操作中的每个 URL 的末尾,将您的仪表板发布到 Tableau Server/Public,不使用选项将工作表显示为选项卡,并使用参数与用户共享初始或主/主页仪表板链接?:link target = _ self&:embed = yes附在最后。这将强制视图加载到同一个浏览器选项卡中,而不是打开多个视图。

总的来说,Tableau 提供了很多功能,有了一个好的设计概念,你就可以创建一个引人注目的工作流程。

参考

[1]https://www.tableau.com/support/knowledgebase

[2]https://kb . tableau . com/articles/issue/URL-actions-open-a-new-browser-tab-inst-of-the-same-tab

赫尔辛基地区大数据集的最*邻分析

原文:https://towardsdatascience.com/nearest-neighbor-analysis-for-large-datasets-in-helsinki-79ebc7288c91?source=collection_archive---------26-----------------------

用于高效距离分析的 BallTree 函数:公交车站和餐馆

图片由作者提供。离每个从 OSM 回来的餐馆(黄色)最*的公共汽车站(粉红色)。演示

在过去的几个月里,我作为一名研究助理参加了赫尔辛基大学著名的 自动化 GIS 课程。在给学生们讲解 GIS 自动化流程的过程中,我的经验非常丰富。我很高兴看到地理学家是如何用 python 语言编程接管 GIS 自动化的,我仍然对材料的高质量感到惊讶。在课程开始时,课程会就 python 的用法和 GIS 中常用对象的基本概念给出建议。然后,这些类变成了深入和高级的分析,在广泛的应用中非常有用。

我将永远记住的一课是最*邻分析。这是一种来自 shapely 库的算法,可以从选定的点中检索最*的点。在此过程中,它使用一元并集函数,这会消耗内存并降低操作速度。因此,在本教程中,我们将使用 BallTree 函数,而不是一元并集,这样可以加快进程并消耗更少的内存。

最终网络地图:演示
仓库代码:回购

对于这个示例,我将使用赫尔辛基作为研究案例,并查找该城市中距离餐馆最*的所有公交车站。在此过程中,从 Geoff Boeing 开发的 python 库 OSMnx 中获取餐馆,从赫尔辛基地区的 GTFS 数据集(最新数据集)中获取公交车站。我们开始吧

数据集

本文中使用的数据集和所用材料的许可证的简要描述。

  • 赫尔辛基地区的 GTFS 数据集。根据知识共享协议 CC0 获得许可。这个数据集是通过 OpenMobilitydata 收集的,OpenMobilitydata 是一个为交通数据、应用开发者、网络开发者和交通机构提供的免费服务。
  • 打开街道地图数据。根据开放数据共享开放数据库许可证(ODbl) 或归属许可证获得许可。用户可以自由地复制、分发、传输和改编这些数据,只要这些数据是像 OpenStreetMap 贡献者这样的作者所拥有的。
  • 自动化 GIS 教学材料。根据知识共享署名-相似分享 4.0 国际许可证获得许可。用户可以在归属下自由分享和改编。课程是公开分享的,在使用资料后,建议也公开分享资料。

编码实践

从最重要的开始。导入所需的库。

**import** geopandas **as** gpd
**import** pandas **as** pd
**import** osmnx **as** ox
**import** matplotlib.pyplot **as** plt
**from** shapely.geometry **import** Point, LineString

让我们用 OSMnx 获取感兴趣的区域。赫尔辛基

**# Specify the name that is used to seach for the data** place_name = “Helsinki, Finland”**# Fetch OSM street network from the location** graph = ox.graph_from_place(place_name)**# Plot the streets** fig, ax = ox.plot_graph(graph)**# Get place boundary related to the place name as a geodataframe** area = ox.geocode_to_gdf(place_name)

图片由作者提供。图形对象的绘图

现在,让我们从 OSMnx 获取并安排餐馆

**# List key-value pairs for tags such as restaurants** tags = {‘amenity’: ‘restaurant’}**# Retrieve restaurants** restaurants = ox.geometries_from_place(place_name, tags)**# getting centroids from restaurants to avoid polygon geometric objects** restaurants[‘geometry’] = [geom.centroid for geom in restaurants[‘geometry’]]**# reset index** restaurants = restaurants.reset_index(drop=True)

现在,餐馆已在格式化的地理数据框架中,我们将从赫尔辛基地区的 GTFS 数据集中读取停靠点文件,并创建另一个地理数据框架

**# read the stops** stops = pd.read_csv(r’gtfs/stops.txt’, sep=’,’)**# creating geodataframe of stops** stops[‘geometry’] = Nonestops_gdf = gpd.GeoDataFrame(stops, geometry = ‘geometry’, crs=4326)stops_gdf[‘geometry’] = [Point(lon, lat) for lon, lat in zip(stops_gdf[‘stop_lon’], stops_gdf[‘stop_lat’])]**# Clip stops from the area of interest** stops_mask = gpd.clip(stops_gdf, area)

让我们画一个图,看看到目前为止它看起来怎么样

图片由作者提供。公共汽车站(蓝色)和餐馆(红色)

现在我们有了我们需要的东西,我们将定义几个函数来帮助找到最*的邻居

**from** sklearn.neighbors **import** BallTree
**import** numpy **as** np

第一个功能。

**def** get_nearest(src_points, candidates, k_neighbors=1):
 '''
**Find nearest neighbors for all source points from a set of candidate points**
'''**# Create tree from the candidate points
** tree = BallTree(candidates, leaf_size=15, metric=’haversine’)**# Find closest points and distances
** distances, indices = tree.query(src_points, k=k_neighbors)**# Transpose to get distances and indices into arrays
** distances = distances.transpose()
 indices = indices.transpose()**# Get closest indices and distances (i.e. array at index 0)
 # note: for the second closest points, you would take index 1, etc.
** closest = indices[0]
 closest_dist = distances[0]**# Return indices and distances
** **return** (closest, closest_dist)

第二个功能。

**def** nearest_neighbor(left_gdf, right_gdf, return_dist=False):
'''
 **For each point in left_gdf, find closest point in right GeoDataFrame and return them.

 NOTICE: Assumes that the input Points are in WGS84 projection (lat/lon).**
'''

 left_geom_col = left_gdf.geometry.name
 right_geom_col = right_gdf.geometry.name

 **# Ensure that index in right gdf is formed of sequential numbers** right = right_gdf.copy().reset_index(drop=True)

 **# Parse coordinates from points and insert them into a numpy array as RADIANS
 # Notice: should be in Lat/Lon format** left_radians = np.array(left_gdf[left_geom_col].apply(lambda geom: (geom.y * np.pi / 180, geom.x * np.pi / 180)).to_list())
 right_radians = np.array(right[right_geom_col].apply(lambda geom: (geom.y * np.pi / 180, geom.x * np.pi / 180)).to_list())

 **# Find the nearest points** **# — — — — — — — — — — — -
 # closest ==> index in right_gdf that corresponds to the closest point
 # dist ==> distance between the nearest neighbors (in meters)
** 
 closest, dist = get_nearest(src_points=left_radians, candidates=right_radians)**# Return points from right GeoDataFrame that are closest to points in left GeoDataFrame
** closest_points = right.loc[closest]

 **# Ensure that the index corresponds the one in left_gdf** closest_points = closest_points.reset_index(drop=True)

 **# Add distance if requested** if return_dist:
 **# Convert to meters from radians** earth_radius = 6371000 # meters
 closest_points[‘distance’] = dist * earth_radius

 **return** closest_points

让我们应用这些函数

**# Find closest public transport stop for each building and get also the distance based on haversine distance 
# Note: haversine distance which is implemented here is a bit slower than using e.g. ‘euclidean’ metric 
# but useful as we get the distance between points in meters**closest_stops = nearest_neighbor(restaurants, stops_mask, return_dist=True)

此时,相同数量的餐馆将会是相同数量的最*停靠点。这里我们总共有 1.111 个链接。

现在,我们将合并餐馆和公共汽车站。这样,我们就可以在每一行中找到离公交车站最*的餐馆,我们可以创建一个线串作为链接。

**# Rename the geometry of closest stops gdf so that we can easily identify it** closest_stops_geom = closest_stops.rename(columns={‘geometry’: ‘closest_stop_geom’})**# Merge the datasets by index (for this, it is good to use ‘.join()’ -function)** restaurants = restaurants.join(closest_stops_geom)

我们可以在此具有距离属性的地理数据框架中应用描述性统计,我们可以看到从餐馆到公交车站的*均距离为 114 米,记录的最大距离为 4813 米。你会在最终地图中注意到一些餐馆位于群岛上:)

让我们继续创建链接。

**# Create a link (LineString) between building and stop points** restaurants[‘link’] = restaurants.apply(lambda row: LineString([row[‘geometry’], row[‘closest_stop_geom’]]), axis=1)**# Set link as the active geometry** restaurants_links = restaurants.copy()
restaurants_links = restaurants_links.set_geometry(‘link’)

最后,如果我们对我们的元素进行绘图。它看起来会像这样:

**# Plot the connecting links between buildings and stops and color them based on distance** ax = restaurants_links.plot(column=’distance’, cmap=’Greens’, scheme=’quantiles’, k=4, alpha=0.8, lw=0.7, figsize=(13, 10))
ax = restaurants.plot(ax=ax, color=’yellow’, markersize=4, alpha=0.7)
ax = closest_stops.plot(ax=ax, markersize=8, marker=’o’, color=’red’, alpha=0.7, zorder=3)**# Zoom closer** ax.set_xlim([24.924, 24.95])
ax.set_ylim([60.16, 60.1740])**# Set map background color to black, which helps with contrast** ax.set_facecolor(‘black’)

图片由作者提供。餐馆(黄色)和最*的公交车站(红色)之间的链接(绿色)

现在,它完成了。如果你想的话,你可以下载这些数据,并像我一样按照你自己的喜好进行格式化。

图片由作者提供。最终地图。

结论

BallTree 是一种有效的功能,有助于加速几何元素之间的距离分析过程。自己测试一下,你会发现它是如何快速工作的,避免了额外的计算机内存开销。此外,通过研究与最*邻居的距离,可以创建移动性报告。在这个例子中,公共汽车站和餐馆之间的*均距离是 114 米,步行不到 5 分钟。在这种情况下,您分析的是餐馆之外的其他元素,*均值太高,到达时间较长,显然存在可访问性问题。

仅此而已。良好的编码实践和对未来的良好分析。你可以在我的网络地图中支持我的工作,或者在我的 LinkedIn 上找到我。

使用 SQL 和 Python 的最*邻

原文:https://towardsdatascience.com/nearest-neighbour-with-sql-and-python-78a1937d15b8?source=collection_archive---------27-----------------------

一个简单的算法来解决最*邻问题与任何语言和 SQL 和 Python 中的例子

最*邻问题是空间分析中经常出现的问题之一。它是如此普遍,知道如何简单有效地解决它是根本。本文介绍了 SQL 和 Python 中的问题和解决方案。

问题是

这个问题很容易定义:给定空间中的两组物体,集合 A 和集合 B,对于 A(原点集合)中的每一个物体,在 B(目的集合)中寻找最*的物体。

假设 A 组代表图书馆,B 组代表休闲中心,你想知道哪个休闲中心离每个图书馆最*。

该算法

这个问题的解决方案如下(图 1):

  • 组合集合 A 和 B 中的对象
  • 测量每个组合的距离
  • 首先按(原点)中的对象,然后按距离对组合进行排序。
  • 对于中的每个对象,选择应该是最短距离的第一个组合

图 1:最*邻算法。图片作者。

请注意,一个集合必须是起点,另一个集合必须是终点。这是因为原始集合中不应该有重复值,但是目标集合可以有重复值。B 中的相同对象可能是 a 中不同对象的最*对象。以图书馆和休闲中心为例,两个图书馆可以拥有相同的休闲中心作为它们的最*对象(图 2)。

图 2:两个起点共享一个目的地作为它们的最*点。图片作者。

该算法可以被修改以产生唯一的关系。换句话说,如果一个目的地是一个起点,那么算法可以为你提供下一个最*的起点。

数据

我们在这篇文章中使用了两个数据集:一个是特拉福德的图书馆,一个是特拉福德数据实验室(2021)的休闲中心。您可以通过以下方式下载它们:

wget h[ttps://www.trafforddatalab.io/council_open_data/assets/leisure_centres/leisure_centres.geojson](https://www.trafforddatalab.io/council_open_data/assets/leisure_centres/leisure_centres.geojson) ; wget [https://www.trafforddatalab.io/council_open_data/assets/libraries/libraries.geojson](https://www.trafforddatalab.io/council_open_data/assets/libraries/libraries.geojson)

SQL 示例 1:仅最*邻

本文中的所有 SQL 示例都适用于 postgreSQL (Postgresql.org,2019)数据库和 PostGIS (PostGIS Developers,2020)。这些表名为“休闲中心”和“图书馆”,都存储在名为“trafford”的模式中,都有一个“id”列、“name”列和“geom”列。

假设我们想知道每个图书馆最*的休闲中心,算法实现如下:

代码片段 SQL 中的最*邻查询

让我们分析一下查询的不同部分:

  • 我们使用“选择”来选择我们想要的列
  • 使用“DISTINCT ON”,我们指定不希望在表“A”的“id”列中出现重复的元素;它通过选择定义为“ORDER BY”的第一行来工作
  • 我们指定数据将来自两个表,即模式“trafford”中的“libraries”和“leisure_centres ”,并对这两个表应用别名,以避免在每一列前面重复表名
  • 没有连接表的“WHERE”条件会迫使 SQL 规划器组合两个表的元素
  • 然后,我们使用“ORDER BY”对值进行排序,这允许“DISTINCT ON”过滤掉最*的邻居

表 1 和图 3 显示了图书馆和最*的休闲中心之间的一些联系。

表 1:使用 SQL 的离图书馆最*的休闲中心(未显示全部)

图 3:离图书馆最*的休闲中心(未全部显示)。图片作者。

可以通过在 QGis 中运行前面查询的一个小修改来生成链接:

代码片段 2:以链接作为几何图形的 SQL 中的最*邻查询

这个例子*均运行 67 毫秒,我将把它与 Python 版本进行比较。

SQL 示例 2: K 个最*邻居

在某些情况下,我们不仅对最*的邻居感兴趣,而且对一组最*的邻居感兴趣。我们可以通过简单修改代码来实现这一点。例如,如果我们对每个图书馆最*的两个休闲中心感兴趣,您可以使用:

代码片段 3:用 SQL 查询 K 个最*邻居

表 2 显示了输出。

表 2:使用 SQL 查询离图书馆最*的两个休闲中心(未全部显示)

该示例*均运行时间为 108 毫秒。

Python 示例 1:仅使用 Geopandas 的最*邻

目标是使用 Geopandas 复制 SQL 示例 1 的输出( Jordahl et al,2020)。算法是相同的,我们结合所有,计算距离,排序的价值,并选择最*的。

首先让我们导入库并读取数据:

代码片段 4:将数据导入 Geopandas

重要的部分是下一个函数,我们遵循算法的所有步骤:

代码片段 Python 中的最*邻函数

现在我们必须做两件事:首先,应用函数,这样我们就可以获得最*几何图形的标识符列表。其次,我们获取这些标识符的值。

该函数被编写为总是返回源和目的地的标识符,这样更安全,因为所有数据帧都有索引,但不是所有数据帧的列都有相同的名称。代码的第二部分将这些标识符转换成值:

代码片段 6:最*邻函数的实现

输出类似于 SQL 示例 1:

表 3:离使用 Geopandas 的图书馆最*的休闲中心(未全部显示)

*均运行时间为 5 毫秒,这与 SQL 相比快得惊人。在这篇文章的最后,我将用一个更大的数据集进行比较。

Python 示例 2:具有 Geopandas 的 K 个最*邻

现在,让我们尝试使用 Geopandas 来查找 K 个最*的邻居,就像我们在 SQL 示例 2 中所做的那样。和以前一样,算法不变,只有实现。我们修改了函数,现在接受第三个变量 k,它代表所需的最*邻数量:

代码片段 Python 中的 K *邻函数

我们调用该函数并获得输出(表 4):

代码片段 8:K *邻函数的实现

表 4:离使用 Geopandas 的图书馆最*的两个休闲中心(未全部显示)

这个例子*均运行 7 毫秒。

更大数据的性能

到目前为止,所有的例子都是使用一对相当小的数据集完成的。一个是 13 行长,另一个是 17 行长。我将使用操作系统打开 UPRN 和代码点打开 UPRN 作为原点,重复练习 1。

这两个数据集都可以从 https://osdatahub.os.uk/downloads/open(2021)下载。

我将表格简化为白马谷区域内的几何图形。这给了我们 80347 个 UPRNs 和 4074 个代码点。这些仍然是小数据集,我想说一个更真实的练习将涉及有数百万行或至少数十万行的表。不过,我将保持简单,只是为了演示性能上的差异。

在 PostgreSQL 中,有许多方面会影响 Geopandas 与 SQL 的性能:

  • Geopandas 将数据存储在内存中,而 PostgreSQL 必须从磁盘中读取数据。这可以让熊猫更快,只要你有足够的内存,你愿意等待数据读入内存。
  • PostgreSQL 有一个计划器,它会尝试以最好的方式实现查询,这可能是相对于 Python 的一个优势。
  • 根据版本的不同,PostgreSQL 可以对同一个查询使用多个 CPU,而 Pandas 则仅限于单个 CPU。
  • 通常 PostgreSQL 运行在一个比普通计算机有更多 RAM 和 CPU 的服务器上,但是你也可以在服务器上运行 Geopandas,所以这完全取决于你的情况。
  • PostgreSQL 和 Geopandas 都使用索引来加快查询速度,但我发现 PostgreSQL 索引更加通用和强大。
  • PostgreSQL 的配置很重要,默认情况下,它会限制给查询的内存量。

在这种情况下,SQL 和 Python 都在同一台笔记本电脑上运行,该笔记本电脑有 16GB RAM 和 8 个 2.30 Ghz 的 CPU(对于数据库服务器来说不是很好)。

我们需要做一些调整,以确保查询和函数不会被大型任务所阻塞。对于 SQL,我们需要:

  • 为两个表创建空间索引
  • 为要在“DISTINCT ON”中使用的列创建索引
  • 建立一个距离限制来减少组合的数量

如果没有索引,SQL 查询将需要很长时间。我使用的限制是 5 公里,因此距离超过 5 公里的所有组合都会被删除。

让我们创建索引,并用距离限制修改查询:

代码片段 9:最*邻查询的表索引

代码片段 10:使用 SQL 的大型数据集的最*邻

注意,我没有调用输出,而是重定向到一个新表。输出可能很大,您肯定不希望第二次运行一个很长的查询。这个查询需要 3 分 28 秒。

对于 Geopandas,我们需要重写代码,以便从索引中获益。我们导入数据,定义新函数,并像这样实现它:

代码片段 11:使用 Python 的大型数据集的最*邻

该查询运行时间为 35 分 42 秒。

如您所见,在这种情况下,Geopandas 并不比 SQL 运行得更快。

还有另一种选择:由于两个表都是点,我们可以将几何图形表示为坐标,然后使用 scikit-learn (Pedregosa 等人,2011 年)计算最*邻。这仅用了 106 毫秒。这种方法的唯一缺点是不能使用不同于点的几何图形:

代码片段 13:使用 sklearn 和 geopandas 的最*邻

所有执行速度如表 5 所示:

表 5:性能比较

结论

最*邻问题是空间分析中的基本问题之一,它可以有一个简单的解决方案,但需要一个计算密集型的解决方案。

我已经展示了使用 SQL 和 Python 的选项。更准确地说,我展示了 PostGIS、Geopandas 和 Scikit-learn 的选项。

很明显,当任务很小时,Geopandas 是很棒的。当任务较大时,PostGIS 做得更好,尤其是在服务器良好的情况下。Scikit-learn 速度超快,但仅限于点数。

性能不仅受您使用的语言的影响,还受硬件、配置、索引等整个环境的影响。

我希望你喜欢这篇文章,但如果你有改进算法或代码的建议,请不要忘记评论。

参考

凯尔西·乔达尔、乔里斯·范登博舍、马丁·弗莱施曼、雅各布·乏色曼、詹姆斯·麦克布莱德、杰弗里·杰拉德……弗朗索瓦·勒布朗。(2020 年 7 月 15 日)。geo pandas/geo pandas:v 0 . 8 . 1(v 0 . 8 . 1 版)。芝诺多。可用时间:http://doi.org/10.5281/zenodo.3946761

osdatahub.os.uk. (2021)。 OS 数据中枢。[在线]可从https://osdatahub.os.uk/.获得

Pedregosa,f .,Varoquaux,g .,Gramfort,a .,Michel,v .,Thirion,b .,Grisel,o .,Blondel,m .,Prettenhofer,p .,Weiss,r .,Dubourg,v .,Vanderplas,j .,Passos,a .,Cournapeau,d .,Brucher,m .,佩罗特,m .和 Duchesnay,e .(2011).sci kit-learn:Python 中的机器学习。机器学习研究杂志,【在线】12(85),第 2825–2830 页。可在:https://jmlr.csail.mit.edu/papers/v12/pedregosa11a.html

后 GIS 开发者(2020)。PostGIS—PostgreSQL 的空间和地理对象。[在线]Postgis.net。可在:https://postgis.net/.

‌Postgresql.org。(2019). PostgreSQL:全球最先进的开源数据库。[在线]可在 https://www.postgresql.org/.找到

Trafforddatalab.io. 2021。特拉福德数据实验室。【在线】可在:https://www.trafforddatalab.io/获得。

需要数据?为什么不用你的邮箱地址呢?

原文:https://towardsdatascience.com/need-data-why-not-use-your-email-address-2936e9894a4c?source=collection_archive---------45-----------------------

我如何设置我的电子邮件帐户来分析右翼媒体信息

皮沙贝

尽管在过去的几年中,我们已经看到消息应用和聊天选项的流行程度显著上升,但电子邮件仍然是最主要的数字通信形式之一。今天,据估计有超过 40 亿人使用电子邮件;这个数字预计在可预见的未来还会增长。

此外,电子邮件简讯的打开率大约为 22% ,这使得社交媒体业务参与度大打折扣。简而言之,电子邮件仍然很重要,有很多公司、团体和组织都渴望让你注册他们的电子邮件营销简讯。

但是数据科学家如何处理这些信息呢?;)

年轻的数据科学家今天面临的最大问题之一是在构建企业级数据科学解决方案的过程中真正理解数据工程的价值。无论是访问数据、了解如何处理杂乱的数据,还是为下游培训进行特征工程,年轻的数据科学家通常不会接触这些主题,因为课程、博客和在线教程通常提供“罐装”数据集,这些数据集已经过审查并清除了它们的原始形式。

进入电子邮件,你自己的数据收集机器,它有助于让你接触数据科学中肮脏的、较少被谈论的、当然也没有被美化的方面,同时也打开了无数商业用途的大门。以下是使用电子邮件收集、分析和模拟数据的一些业务用例:

1.通过订阅他们的电子邮件时事通讯来了解你的竞争对手在做什么

2.监控社会运动及其对信息的使用,以发现新趋势

3.从客户那里收集反馈,感觉不像是另一项调查

好吧,酷,但我该怎么做?

在本文的剩余部分,我将提供一个过程和一些代码,向您展示我如何设置一个电子邮件帐户来收集来自右翼团体的数据,以监控极端主义消息,并使用一些自然语言处理工具来分析这些数据以获得洞察力。如果你正在挠头,想知道为什么这个话题如此狭窄,这个项目是与 RivalAnalytics 合作的。Ai ,一个竞争情报数据科学小组,有兴趣建立像这样的监控项目。

高级项目看起来像这样:

1.设置一个 Gmail 帐户并启用程序化访问

2.使用新的电子邮件地址注册目标时事通讯

3.等待我的收件箱填满…

4.利用 Python 访问电子邮件并提取日期、主题和正文

5.清理数据

6.使用关键词、情感和相关性分析数据

7.考虑一下其中的含义

开始了…

步骤 1:设置电子邮件帐户

希望我不需要向每个人展示如何设置一个 Gmail 帐户,更有用的是展示如何启用该帐户进行编程访问。创建 Gmail 帐户后,进入 Gmail 收件箱,单击“齿轮”图标进入设置,然后单击“查看所有设置”(见图中的黑色箭头)。

从那里点击“转发和 POP/IMAP”标签和“IMAP 访问”部分的“启用 IMAP”(见图中红色箭头)。选择后,滚动到底部并单击“保存更改”以启用帐户上的选择。

最后,点击左上角你的 Gmail 账户的圆圈图标(我用的是 Chrome BTW),然后点击“管理你的谷歌账户”(见绿色箭头)。转到“安全”部分,点按以打开“不太安全的应用程序访问”(见黑色箭头)。搞定了。现在,您的电子邮件配置为编程访问。前进!

步骤 2 和 3:注册并等待

对于这个实验中的第 2 步和第 3 步,我选择注册 Gab 时事通讯。Gab 是一个右翼社交媒体网站,也是右翼极端组织的知名*台。

…等待…等待…仍在等待…

随着我的耐心越来越少,我终于决定拔掉插头,看看我在大约 2 个月内积累的数据。在仅仅两个月的时间里,并且只关注一个时事通讯来源,我积累了 28 封电子邮件。无论如何都不是“大数据”,但你可以想象如何扩大范围以包括更多的来源,并允许多一点时间来获取数据,可以大大扩展足迹。

步骤 4:使用 Python 访问数据

为了以编程方式访问数据,我在 Windows 10 笔记本电脑上使用了 Python 3.7。首先,我们需要安装允许我们访问电子邮件服务器的库:

第二,我们从我们的时事通讯提供商那里搜索电子邮件,并提取日期、主题和正文。请注意,代码只关注正文中的文本,并不试图提取附件,但是这里的是修改我的循环以将附件保存到您的硬盘驱动器的一个很好的资源。

既然我们已经有了包含每封电子邮件的日期、主题和正文的数据框架,我们就可以开始分析了。

步骤 5:清理数据

为了清理数据,我构建了一个函数,我通常在我的大多数 NLP 项目中使用它来快速清理文本数据。该函数允许您传递一个字典,该字典将对单词标记的任何潜在问题进行标准化,例如将首字母缩略词从“NLP”更改为“自然语言处理”,如果它变得相关的话。代码使用 Python 的 NLTK 库中的工具。

在我们的 dataframe 中创建了“clean_text”列之后,我从文本中构建二元模型。我通过点互信息(PMI)值和基于它们作为名词的状态来过滤二元模型,因为大多数主题都基于文本中的名词。 PMI 本质上是给定二元模型的概率除以每个词独立的概率。使用这些过滤器提高了我们获得有意义二元模型的可能性。一旦我们获得了最终的二元模型列表,我们就为每封邮件创建一个二元模型频率矩阵。

第六步:分析

现在我们有了一个数据框架,其中包含了最终二元模型列表中每个二元模型的频率计数,我们可以分析数据了。为了进行分析,我首先将主体和日期从主数据框架连接到我们的 clean_text 数据框架。然后,我使用 HuggingFace 的“情绪分析”管道添加了一个情绪栏。在生成情感分数的函数中,因为基于 BERT 的转换器有一个字符限制,所以我们需要限制暴露给模型的字符。我遍历正文的每一行,选择前 512 个字符来生成情感评估。最后,我将所有的情感评分*均在一起,以获得每封邮件的总体情感评估。显然,我们不会捕获所有的文本数据,但是可以通过迭代 512 个字符的块来捕获所有的数据。

一旦完成,我们执行一个快速的时间序列分析,绘制一段时间内的情绪,以及通过 bigram 与情绪的相关性分析,以确定哪些短语与整体情绪相关联。

从上面的代码中,我们生成了一些图像来帮助我们解释。让我们先来看看时间序列图:

尽管最初几封邮件的*均情绪很高,但我们看到快速下降,随后从 05–2021 到 06–2021 呈线性上升趋势。仍然有很大的可变性,但是分析确实表明了一种趋势。这种趋势让我假设这些时事通讯可能与新闻中的其他事件相关联。因此,将这些数据与其他数据源(如谷歌趋势)进一步融合会很有意思。让我们来看看我们的二元模型是如何与情绪相关联的:

第七步:解释

在关联热图中有一些有趣的见解,显示了二元模型和*均情绪之间的关系强度。有趣的是,“唐纳德·特朗普”比“特朗普总统”更与积极情绪正相关,这表明极右翼团体可能会以不同的方式使用前总统的标签,这种方式可能取决于他们是否讨论自己对唐纳德·特朗普的热情,而不是描述自由主义者如何对待特朗普总统。

其他关键见解包括倾向于与更多负面情绪相关联的短语,如“关键种族”和“国内恐怖分子”

带回家或 TLDR

总之,我们的电子邮件地址是宝贵的数据来源,如果使用得当,可以带来一些重大的商业和/或社会价值。通过应用数据科学的工具,我们可以为电子邮件的非结构化本质增加结构,并创造新的见解,从而在各种使用案例中推动价值。

比如参与学习更多关于数据科学的知识?加入我

需要帮助做决定吗?问问你的数字双胞胎吧!

原文:https://towardsdatascience.com/need-help-making-decisions-ask-your-digital-twin-6e4cf328cb0?source=collection_archive---------24-----------------------

将实时数据与模拟、机器学习和人类推理相结合,以提升决策水*。

数字双胞胎永远不会是真实世界的完美镜像。然而,我们的目标是设计尽可能精确的现实抽象。在 Unsplash 上由bùI Thanh TM拍摄的照片

让我们面对现实吧:做决定很难。只需考虑以下需要克服的障碍:

  • 你需要弄清楚如何实际评估决策。什么样的绩效指标真正重要,你如何对它们进行排名或加权?
  • 一旦您知道了什么构成了决策的质量,您就需要评估各种决策在定义的度量标准上的得分情况。
  • 决策的后果通常只会在未来显现。没有即时反馈机制。
  • 决策很少是孤立地做出的,但它们会与环境和他人做出的决策相互影响。

自然地,随着决策而来的是错误,而错误既昂贵又痛苦。正如沃伦·巴菲特所说:

“从错误中吸取教训是件好事。不如从别人的错误中吸取教训。”

从本质上讲,这句话抓住了数字孪生兄弟的精神。在现实生活中失败是昂贵的,但在虚拟世界中失败是廉价的。数字孪生是真实世界系统的虚拟表示,其范围可以从物理系统(例如,机器部件或风力涡轮机)到完整的供应链甚至是完整的城市。在这个虚拟代理中,您可以很容易地测试许多决策,并运行许多场景来观察决策的结果。

但是等等,那不就是一个模拟环境吗?

在这一点上,你可能想知道数字孪生不仅仅是一个模拟环境。那些不是已经有几十年了吗?是也不是。虽然你可能会说这只是一个老概念的花哨的新名字,但细微差别在于模型的规模和丰富性。特别是,数字孪生植根于实时数据,随着时间的推移保持其与物理对等物的相似性。

让我们来看看数字双胞胎的一些定义。

IBM:

“数字孪生是对象或系统在其整个生命周期中的虚拟表示,根据实时数据进行更新,并使用模拟、机器学习和推理来帮助决策”

福布斯:

数字孪生是流程、产品或服务的虚拟模型。虚拟世界和物理世界的这种配对允许分析数据和监控系统,以在问题发生之前阻止问题,防止停机,开发新的机会,甚至通过使用模拟来规划未来。

皇家哈斯康宁:

“在相关数据的驱动下,数字孪生是现实世界资产、流程甚至整个系统的虚拟镜像,比如供应链或城市。这种镜子可以让您深入了解该资产在各种模拟条件下的表现,帮助您改进决策并优化业务流程。”

什么是数字双胞胎?Royal Haskoning 的视频

Twi-Global:

数字双胞胎本质上是一种计算机程序,它使用真实世界的数据来创建模拟,可以预测产品或过程将如何执行。这些程序可以整合物联网(工业 4.0)、人工智能和软件分析,以增强输出。

维基百科:

“数字孪生是作为物理对象或过程的实时数字对应物的虚拟表示。[……]物理对象的数字孪生依赖于数字线——数字孪生的最低级别设计和规范——“孪生”依赖于数字线来保持准确性。”

套用一句话:尽管在解释上存在一些差异,但所有人都强调数据的重要性、现实程度以及对决策的应用。特别是考虑到物联网技术的兴起和数据*台的出现,我们现在拥有足够丰富和粒度的数据,可以从抽象的模拟模型向具有代表性的数字双胞胎发展。

数字双胞胎

不是美国宇航局的火箭。由 SpaceXUnsplash 上拍摄的照片

那么,这个数字双胞胎是什么时候出生的呢?大卫·格林特可能是精神之父,他在 1991 年的书《镜像世界》中概述了这个概念。第一个制造应用出现在 2002 年。2010 年,美国宇航局首次在其航天器项目中真正采用了数字双胞胎。直到最*,在物联网技术、机器学习突破和数据可用性爆炸的推动下,这一概念才真正起步。

2017 年,Gartner 在十大战略技术趋势中确定了数字双胞胎。事实上,自那以后,它们已经被广泛应用于各种行业和问题。Digital twin 技术有潜力改进现有的产品和流程,并发现未开发的创新资源。在这里,我将不再进行过多的预测,但数字双胞胎在未来几年肯定会蓬勃发展。

对于的数据科学家,物理世界和数字世界之间的共生关系是他们最感兴趣的。数字双胞胎不是*行的现实,它与现实世界有一个持续的反馈回路,数据推动决策,决策产生新数据。由于数据科学家的工作是探索数据并产生可操作的见解,两个世界之间更紧密的相似性将鼓励领域专家和数据科学家之间的新合作。

应用程序

这里很容易列出许多吸引人的例子,但是让我们坚持一个例子。最*,通用电气公司开辟了一个模仿现实世界的“数字风电场”。对于现实世界中的每一个物理风车,都有一个虚拟的副本在云中运行。随着时间的推移,新的运营数据不断被收集,在我们说话的时候,数字代理变得越来越丰富。在建造新的风力涡轮机之前,首先在数字世界中运行一个虚拟的双胞胎,允许提前微调其配置。

还有更多的例子?考虑城市规划(模拟城市,但更上一层楼)、医疗保健(基于详细的医疗数据构建‘虚拟病人’)、制造(产品生命周期管理)和汽车行业(基于观察到的驾驶风格设计汽车功能)。在这一点上,唯一的限制似乎是我们自己的想象力。

设计特点

数字双胞胎有许多有趣而独特的属性。以下是定义真正数字孪生的关键设计特征。

连接

模拟环境和数字孪生之间的关键区别是数据。物联网及其所有传感器和应用数据允许以前所未有的规模跟踪物理过程。因此,它将物理世界和数字世界拉得更*,数字代理越来越成为现实的一对双胞胎。因此,组织、产品和客户之间的壁垒可以逐渐减少。

数据解耦

在一个与数据*台高度相似的概念中,数字孪生兄弟本质上将数据与其物理实体分离。如今,数据可以以非常低的成本收集、传输、处理和存储。通过将数据分离为一个独立的业务层,为应用各种分析工具和学习算法打开了大门。简而言之:所有利益相关者都可以自由访问信息,而不需要实际观察真实的系统。

诊断

随着数字双胞胎如此准确地代表现实,虚拟代理可以用来诊断和解决问题。例如,如果发生车祸,收集的汽车数据可用于追溯问题的根源。因此,安全功能可能会在汽车部件的未来迭代中进行微调。类似地,数字双胞胎可以用于例如诊断制造过程中的瓶颈。

重新编程

从现实中获取的数据不仅旨在丰富虚拟世界,数字双胞胎也不局限于被动地为那些寻找它的人提供决策支持。基于从现实世界获得的信息,数字双胞胎可以主动识别和测试改进,并将结果直接反馈给物理系统。例如,软件可以根据收到的用户数据即时更新。机器学习算法特别适合于重新编程的任务,即根据持续不断的数据流不断调整和改进流程。

缩放和整形

在这一点上,您可能已经猜到了,数据双胞胎可以扮演多种角色。例如,在产品原型实际存在之前对其进行测试,需要与监控工厂流程不同的环境。孪生可能小到单个组件,也可能大到一个宏进程。根据他们在决策中的应用,数字双胞胎可以被塑造成许多形状。

结束语

数字孪生技术的潜力同样引人入胜。虚拟世界变得越丰富、越准确,它们就越有可能驱动现实生活中的决策。事实证明,物联网、模拟、机器学习、数据*台和人类专家之间的一夫多妻婚姻尤其富有成效。建模这样一个详细的环境需要时间,但从那里开始,可以部署实时数据摄取和机器学习,以自动建立更加准确的现实表示。目前,加强决策的机会似乎是无限的。

所以下次你不知道该做什么决定的时候:问问你的数码双胞胎吧。

图片由 elen aivaliUnsplash 上拍摄

外卖食品

  • 数字双胞胎是模拟真实世界环境的虚拟计算机模型,代表从产品原型到工厂的任何东西。
  • Digital twin 技术可以被视为一种模拟模型,注入了实时数据和逻辑。机器学习算法和物联网技术用于构建丰富和智能的现实表示。
  • 数字双胞胎可以用来测试许多场景下的各种行为,通过首先在虚拟世界中观察它们来增强现实世界的决策。
  • 该技术是当代商业领域的顶级趋势之一,预计将在未来几年极大地增强决策能力。

进一步阅读

福布斯(2017)。什么是数字孪生技术,为什么它如此重要?https://www . Forbes . com/sites/Bernard marr/2017/03/06/what-is-digital-twin-technology-and-why-it-so-important/?sh=249c9d3a2e2a

Gartner (2017)。Gartner 2017 年十大技术趋势。https://www . Gartner . com/smarterwithgartner/Gartner-top-10-technology-trends-2017

通用电气公司。风电场的数字解决方案。https://www . ge . com/renewable energy/风能/陆上风能/数字风电场

国际商业机器公司。什么是数字孪生?https://www.ibm.com/topics/what-is-a-digital-twin

皇家哈斯康宁(荷兰)数字双胞胎——物理与数字相遇的地方。https://global . royalhaskoninghv . com/digital/trends/digital-twin

twi-全球(未标明)。什么是数字孪生技术,它是如何工作的?https://www . twi-global . com/technical-knowledge/FAQs/what-is-digital-twin

维基百科(2021)。数字双胞胎。https://en.wikipedia.org/wiki/Digital_twin

时间不够

原文:https://towardsdatascience.com/neo-darwinistic-concepts-of-chance-and-time-through-the-lens-of-ai-2eee4d5c2bd6?source=collection_archive---------28-----------------------

弗朗西斯科·赫苏斯·纳瓦罗·埃尔南德斯在 Unsplash 上拍摄的照片

从计算复杂性的角度看新达尔文主义的时间观

如果进化是一个计算问题,那么大自然是如何解决的呢?此外,它与人工智能(计算的顶点)有什么关系?根据新达尔文主义,或者查尔斯·达尔文的生命起源进化理论的现代综合,大自然在足够长的 时间里盲目冒险选择基因突变中的变异。在本文中,我试图通过计算复杂性的视角来研究新达尔文主义的时间概念。

盲人钟表匠

新达尔文主义者的“中心教条”说:

给予足够的时间通过一个验证过程,比如自然选择机会可以导致多样性、创造性和独创性,不管它们多么罕见。****

“一个人只有等待;生理学家、诺贝尔奖获得者乔治·沃尔德认为:“时间本身会创造奇迹。”。有时候,稀有性受到挑战,比如在钟表匠类比中,批评家说如果你在地上发现一块手表,我们可以推断一定有人把它掉了,一定有钟表匠制造了它。然而,理查德·道金斯声称,即使大自然就像一个不可思议的盲人钟表匠,时间也会把不可思议变成现实。“自然选择的活生生的结果给我们留下了极其深刻的印象……带有设计和规划的幻觉(道金斯,1985)。”换句话说,手表可能是一个盲人钟表匠的偶然产品,他既不知道手表是什么,也没有制造手表的计划。

虽然关于盲人钟表匠的辩论是隐喻性的,永远无法解决,但这种解释力的总体主张,如果在不同的情况下被无可争议地驳斥,将成为新达尔文主义的致命弱点。

随机猜测者和数学天才

这是这样一个思想实验:

如果有足够的时间,一个精通遵循逻辑规则,但没有数学直觉的随机猜测者能像数学天才一样解决问题吗?

如果你问新达尔文主义者,他们会坚持认为,由于他们的中心教条,随机猜测者展示了数学天才的创造力和独创性。然而,数学家会说,“不,这在数学上是不可能的。”计算机科学家会回应说这在计算上是不可行的。与盲人钟表匠不同,随机数学猜测实验可以在数学和计算机科学中找到它的对应物,这样我们就可以果断地解决这场争论。

让我们从二十世纪初开始,当时由杰出的数学家戴维·希尔伯特领导的数学形式主义者将逻辑推理作为数学的一个组成部分。这样,他们可以把解决问题当作数学的一部分。他们认为直觉思维是人工制品,因此对数学发展没有必要。于是,希尔伯特提出了希尔伯特方案,可以从一组公理和逻辑规则中完整地展开数学。

知道希尔伯特的程序最终失败,我们可以得出直觉起了什么必要的作用?直觉“猜测”开始的正确公理、要研究的突出数学事实以及证明这些事实的必要逻辑步骤。然后使用逻辑来验证这些猜测。正如我们所看到的,在希尔伯特的时代,数学家淡化了猜测的艺术,并认为它可以通过随机猜测被“净化”掉。因此,我们的随机猜测思维实验相当于希尔伯特的程序。如果行得通,数学发展可能是盲目的、无目的的、无计划的,这正是新达尔文主义者对生命进化的描述。

现在让我们继续讨论库尔特·哥德尔和艾伦·图灵,他们证明了希尔伯特的程序在数学上是不可能的,因为自参照产生了不可避免的悖论。根据哥德尔的说法,直觉不仅是不断提炼和扩展公理所必需的,而且根据图灵的说法,直觉还必须参与发现和证明数学事实(参见我的文章《逻辑的极限和计算机的兴起》)。

数学的发展需要直觉,这意味着大自然可能并不盲目。

数学和计算机科学

数学上的两个弱点解释了希尔伯特程序中的数学谬误。首先,它缺乏解决问题所需时间的概念。第二,它没有猜测工具。矛盾的是,数学中的这些缺点导致了计算机和计算机科学的出现。

计算机科学定义了运行一个程序的处理步骤的时间,并配备了一个叫做“搜索”的工具来处理猜测。随机猜测和巧妙猜测分别对应于强力搜索和智能搜索。正确猜测的微小概率可以与通过蛮力和长时间运行在大空间中的搜索相关联。

计算中的相关概念

总结一下:

  1. 强力搜索的运行时间与搜索空间大小成正比。
  2. 做出正确猜测的概率与搜索空间的大小成正比。

现在,我们可以将解决问题的数学问题视为计算问题,并将数学可能性视为计算可行性。关于可行性,我们可以根据计算问题的运行时间或搜索空间是指数增长还是多项式增长,将计算问题分为以下两类。我们可以认为第一种类型是不可行的,因为指数运行时间或搜索空间甚至可以超越宇宙。第二种类型,称为代表多项式时间的 P,被认为是可行的T3,因为多项式运行时间或搜索空间通常可以容纳在宇宙的限制内。

p 与 NP:问问新达尔文主义者

处理不可行的问题是没有希望的,可行的问题似乎太容易而没有意义。幸运的是,还有第三种类型,称为 NP,代表非确定性多项式时间。做出正确的猜测可能很困难(指数时间),但验证猜测很容易(多项式时间)。我们认为希尔伯特的程序是一个 NP 问题,因为使用逻辑推理来验证猜测是可行的,但如果随机猜测或用蛮力搜索则不可行。

同样,根据新达尔文主义,盲目、无目的、无计划的进化就像用蛮力搜索解决一个 NP 问题。自然选择作为验证机制必须花费多项式时间;否则,它不会促进生命的进化。

正如我在文章直觉、复杂性和最后的悖论中所解释的,有一类 NP 问题,称为 NP-完全,被认为是所有 NP 问题中最困难的。如果一个 NP-完全问题有一个多项式时间的解,那么所有的 NP 问题都可以归结为这样一个问题并在多项式时间内求解,从而证明 P = NP。我们把确定 P = NP 称为 P 对 NP 问题。这是数学和计算,甚至是现代科学中最重要的公开问题之一。

一个新达尔文主义者会如何回答 P = NP 这个问题?如果是,那么进化就可以归结为某个 NP 完全问题,由一个不了解生命的多项式时间 NP 完全求解器来求解。因此,大自然可能仍然是盲目的,创造力、独创性和对进化的预见仍然是一种幻觉,正如新达尔文主义者所期望的那样。然而,解释谁设计了这样一个多项式时间解算器的噩梦将困扰着她。正如我们所见,一个新达尔文主义者会坚持 P 不等于 n P。

埃米尔·波莱尔:罕见的事件不会发生

埃米尔·波莱尔,1871-1956 年

回想一下,强力搜索对应于随机猜测。因此,指数增长的搜索空间表示指数运行时间和正确猜测的概率的减少。为了方便起见,我们可以将搜索空间的大小表示为 10^N,其中 n 是 1 后面的零的数量。

因此,我们可以用 N 来表示搜索空间有多大,搜索要花多长时间,以及做出正确猜测的可能性有多大。新达尔文主义者坚持认为,无论 N 有多大,都有足够的时间进行尽可能多的猜测。这一立场也许在乔治·沃尔德的以下引述中得到最好的证明:

给定这么多时间,[几乎]“不可能”变成可能,“可能”变成可能,“可能”变成几乎“确定”(Wald,1954,48–53)。

与新达尔文主义者关于机会和时间的立场相反,法国著名数学家埃米尔·波莱尔(1871-1956)在他的“单一机会法则(Borel,1962)”中说:

概率足够小的事件永远不会发生;或者至少我们必须采取行动,在任何情况下,就好像它们是不可能的。

尽管它被称为“单一”定律,但它描述了两种我们认为足够小的概率为零的重要场景——前者涉及你如何做出日常或一生的决定。例如,你想开车去上班,冒着在车祸中丧生的风险,考虑到天气预报并不总是正确,你每天都带着一把伞,或者把你的退休生活押在中彩票上。

第二个场景是关于你如何处理科学事实或工程决策。Borel 估计概率小于 N = 50,即支配者中 1 后面的零的数量,牛顿定律可能被违反。但在设计桥梁、汽车、飞机和人类登月时,我们会认为这种可能性为零。进一步,考虑统计力学的预测,我们不需要考虑容器中的氧和氮的混合物自发分离成右半部分的纯氮和左半部分的纯氧的可能性。决定向左或向右的每个原子的搜索空间的大小是 N,以亿计,比我们的宇宙在各个方面都大得多,以至于 Borel 认为这样的搜索空间大小是超宇宙规模的。

对于生命的进化,著名的进化生物学家 Carl Sagan 估计搜索空间为 N = 2,000,000,000,或 1/10 的 20 亿次方,以符合新达尔文主义理论,即生命可以在任何一个给定的行星上进化完全是偶然的(Sagan,1973)。然而,新达尔文主义者认为他们的进化机制不是完全随机的,自然选择是非随机因素(Dawkins,2006)。如前所述,如果进化被认为是一个 NP 问题,自然选择就是验证机制。微生物学家詹姆斯·夏皮罗(James Shapiro)认为,“没有变异和新奇,选择就没有任何作用”(夏皮罗,2011)。使其可行或可能的唯一方法是在猜测或搜索中具有非随机性,这意味着在产生变异时有设计或计划,这在中心法则中是严格禁止的。

超越 P 与 NP

尽管在数学、芯片设计、软件检查和与我们日常生活相关的各种领域的关键任务决策中,我们已经成功地采用了启发式和*似求解器,尽管有最坏情况下的指数时间。与此同时,我们正在见证 AI 通过模仿数学天才在解决数学中的 NP 完全问题方面取得进展(Bansal 等人,2019)(Polu & Sutskever,2020) (Selsam 等人,2019)。

在生物学中, Levinthal 悖论一直面临着蛋白质结构预测(PSP)问题,以从蛋白质的线性氨基酸序列中确定三维结构。悖论说

尽管它有巨大的搜索空间,N 约为 300,即使对于一个小的蛋白质分子,它也会在毫秒甚至微秒的时间尺度上自发折叠。

科学家认为 PSP 是 NP 完全的(Unger & Moult,1993) (Unger & Moult,1993)。最*,DeepMind 声称在使用人工智能程序 AlphaFold 以前所未有的准确性和效率解决 PSP 方面取得了突破。现在一个问题如下:如果 AlphaFold 确实“解决”了 PSP 这个已知的 NP 完全问题,那么它的成功不就证明了 P = NP 吗?答案是否定的,因为 AlphaFold 在学术上被归类为*似和启发式求解器之一。然而,与其他解决方案相比,AlphaFold 和 AI 解决方案在以下方面表现突出:

  1. 即使在最坏的情况下,它们也没有指数运行时间
  2. 他们总是“开放”的,并不断学习和适应
  3. 如下所述,它们可以被设计成端到端的,以捕捉人类或自然的直觉

之前声称 PSP 是 NP 完全的可能是由于自然和手工问题公式之间的不匹配,这导致了搜索空间的指数膨胀(Bahi 等人,2013)。相反,AlphaFold 从自然界学习,以端到端的方式将蛋白质的氨基序列直接映射到其最终的三维结构。它不是在一个超级宇宙的搜索空间里跳来跳去,而是把搜索空间看作一个风景,并导航到底部。

从这个意义上说,人工智能为挑战性问题提供了切实可行的解决方案,并启发我们了解自然和人类可能如何类似地解决问题。一个更深刻的问题是大自然如何选择那些可以折叠成三维结构的氨基酸序列。一个有趣的观察结果是,“自然界在进化时间尺度上选择蛋白质序列所使用的能量景观本质上与将这些序列折叠成功能蛋白质的能量景观相同(Morcos 等人,2014)。”大自然可能是通过在进化景观中导航而进化的。

鸣谢:维基百科。NK 健身景观的两个维度的可视化。箭头代表种群在适应度景观上进化时可能遵循的各种变异路径。

罕见事件发生怎么办?

新达尔文主义者认为大自然没有解决任何问题。它更像是一个模拟,而不是毫无目标的盲目前行;任何成绩都纯属偶然。

卡罗尔 2020 年的书的一篇评论指出,“一系列幸运事件讲述了机会的可怕力量,以及它是生活世界中所有美丽和多样性的令人惊讶的来源。”书名类似的书《一系列幸运事件》(Snicket,1999-2006)可能启发了书名的选择。在早期的书中,波特莱尔家的孩子们遭受了一系列悲惨的事故,从在一场火灾中失去父母开始。与卡罗尔对机遇的崇拜相反,波德莱尔家的孩子可能会指责机遇是痛苦和毁灭的根源。

卡雷尔和他的新达尔文主义者伙伴们认为,机遇既不是好事,也不是波德莱尔家的孩子们认为的坏事。它是对尚未发生的事情的不确定性的度量。一件事一旦发生,就叫事件。当一件本该罕见的事情发生时,我们该如何反应?根据似是而非的推理(Polya,1954),波德莱尔的孩子们认为,当一系列几乎不可能的事件发生时,几乎可以肯定的是,有一个邪恶的主谋,结果是奥拉夫伯爵,密谋反对他们。

另一方面,试图将宇宙事件与一个人的存在联系起来,听起来像是道德领袖或精神导师的工作,新达尔文主义者多少渴望扮演他们的角色。用机会和时间来解释细节是绝对错误的。

科学头脑

自从新达尔文主义出现以来,一直有蓬勃发展的研究(第三种进化方式 ) (Koonin,2012) (Shapiro,2011) (Jablonka & Lamb,2005) (Carey,2012) (Woodward & Gills,2012)(Noble,2017)表明新达尔文主义不足以解释进化。它迫切需要用新的科学发现进行修正。

例如,一个与新达尔文主义截然不同的理论是共生理论,生物学家琳·马古利斯是其主要发现者之一。她与道金斯(Noble,2017)有如下对话:

道金斯:它【新达尔文主义】非常合理,经济,节俭,当它是如此不和谐,不经济的【理论】时,你究竟为什么要把共生扯进来?

马古利斯:因为它在那里。

大自然是否真的如新达尔文主义所描述的那样进化,这个问题还没有定论。我坚持认为,一个科学头脑不会因为一个理论简洁而止步不前。相反,它贪得无厌的好奇心和似是而非的推理原则迫使它详细地追寻魔鬼。

参考书目

Aaronson,S. (2016 年)。P=?NP。在数学开放题。斯普林格。**

Bahi,J. M .、Bienia,w .、Cote,n .、Guyeux,C. (2013 年)。蛋白质折叠问题真的是 NP 完全问题吗?初次调查。生物信息学与计算生物学杂志12 (1)。**

Bansal,k .,Loos,s .,Rabe,m .,Szegedy,c .,和 Wilcox,S. (2019)。整体论:高阶定理证明的机器学习环境。第 36 届机器学习会议论文集**

博雷尔,E. (1962)。概率与寿命。).多佛出版公司。

博雷尔,E. (1963)。概率和确定性。沃克公司。

北卡罗来纳州凯里(2012 年)。表观遗传学革命:现代生物学如何改写我们对遗传学、疾病和遗传的理解。哥伦比亚大学出版社。

卡罗尔,S. B. (2020)。一系列幸运事件:机遇和地球的形成,生命和你。普林斯顿大学出版社。**

道金斯河(1985 年)。盲人钟表匠。诺顿&公司**

道金斯,R. (2006 年)。神痴。霍顿·米夫林公司。**

道金斯,R. (2010 年)。地球上最大的表演:进化的证据。新闻自由。

w .哈特和 s .英斯特兰(1977 年)。蛋白质折叠 NP-hardness 的强有力证明:一般晶格和势能。计算生物学杂志4 (1),1–22。**

贾布隆卡和兰姆(2005 年)。四维进化:生命历史中的遗传、表观遗传、行为和符号变异。麻省理工学院出版社。**

杰恩斯(2003 年)。概率论:科学的逻辑(第 10 版。).剑桥大学出版社。**

Koonin,E. V. (2012 年)。机会的逻辑:生物进化的本质和起源。皮尔逊教育公司。**

Morcos,f .,,N. P .,Cheng,R. R .,Onuchic,J. N .,& Wolynes,P. G. (2014 年 8 月 26 日)。共同进化信息、蛋白质折叠景观和自然选择热力学。美国国家科学院院刊。

诺贝尔博士(2017)。随着生命的旋律起舞:生物相对论。剑桥大学出版社。**

Polu,s .,& Sutskever,I. (2020 年 9 月 7 日)。自动定理证明的生成语言建模。https://arxiv.org/abs/2009.03393.

波利亚,G. (1954)。数学和貌似合理的推理。普林斯顿大学出版社。**

波利亚,G. (1954)。数学和貌似合理的推理。普林斯顿大学出版社。**

Selsam,d .,Lamm,m .,Bunz,b .,Liang,p .,Dill,D. L .,& de Moura,L. (2019 年 3 月 12 日)。从单比特监督学习 SAT 求解器。https://arxiv.org/abs/1802.03685.

夏皮罗,J. A. (2011 年)。进化:来自 21 世纪的观点。詹姆斯·夏皮罗。

斯尼克湖(1999 年至 2006 年)。一系列不幸事件。哈珀柯林斯出版有限责任公司。**

昂格尔和莫尔特(1993 年)。寻找蛋白质的最低自由能构象是一个 NP 难题:证明和含义。数学生物学通报55 (6),1183–1198。**

沃尔德·g .(1954 年 8 月)。生命的起源。科学美国人,(191),45–53。**

伍德沃德、T. E .、吉尔斯和 J. P. (2012 年)。神秘的表观基因组:DNA 之外还有什么。克雷吉出版公司。

Neo4j 和 DGL —无缝集成

原文:https://towardsdatascience.com/neo4j-dgl-a-seamless-integration-624ad6edb6c0?source=collection_archive---------12-----------------------

在本文中,我们将说明如何使用深度图形库将图形注意力网络模型集成到 Neo4j 工作流中,并部署 Neo4j Python 驱动程序。

本帖与 克莱尔·沙利文 马克·李约瑟 合著

Cora 数据集可视化—经 https://graphsandnetworks.com/the-cora-dataset/许可复制

介绍

Neo4j GDS 库版本 1.5 的发布和内置的机器学习模型,现在为需要在 Neo4j 中的任何图形上执行机器学习任务的数据科学家提供了两种可能的解决方案。

如果时间是最重要的,并且需要一个受支持的、经过测试的本地工作的模型,那么对 GDS 库的一个简单的函数调用就可以完成这项工作。然而,如果需要更大的灵活性或者有一些数据限制,那么数据科学家可以部署外部机器学习库,结合 Neo4j Python 驱动程序。

在这一系列文章中,我们将说明如何使用不同的外部机器学习库来补充现有的 Neo4j 图形数据科学(GDS)功能。

对于这篇文章,我们使用深度图形库(DGL)包和 TensorFlow 作为后端,并使用 Cora 数据集构建了一个包含完整代码的 Colab 笔记本,可以在这里找到

图形神经网络

作为背景,我们简要描述图形神经网络(GNNs ),从最广泛的意义上来说,它可以被定义为一类适合于处理图形结构数据的神经网络模型。同样地,在最广泛的意义上,对图形的学习(即图形表示学习)可以分为两类学习问题;无监督和监督学习(包括半监督)。无监督学习旨在学习捕捉输入图结构的低维欧几里德表示,这些通常被称为嵌入算法,其一个例子是可以在 Neo4j GDS 库中找到的 Node2Vec 算法。第二类学习任务也学习嵌入,但目标是执行一些下游预测,例如节点或图形分类或链接预测。无监督学习的输入通常是整个图,而对于有监督的任务,输入是节点特征和可能的边特征,此外,图结构(全部或通常部分)也可以用于训练。监督 GNN 任务的一般框架是一个“消息传递”框架,旨在包含不同类型的 gnn。最*的调查将不同的 GNN 组织成大约 5 种 GNN 体系结构的分类,范围从递归 gNN、图卷积 nn 到图注意网络等。

现在,数据科学家可能希望利用这些不同的架构,因为她/他可能面临标记数据量有限的问题,因此只能部署半监督模型,或者可能希望从最重要的功能中获得更多见解等。因此,在这些情况下,数据科学家将希望构建自己的定制模型来进行节点分类或其他下游应用。

由于 Neo4j Python 驱动程序,任何 GNN 包都可以在 Neo4j 图上执行图形机器学习任务。事实上,在过去的几年中,已经开发了一整套的库和工具,根据最*的统计,关于图形神经网络的开源项目已经达到了将* 100 个!

https://awesomeopensource.com/projects/graph-neural-networks

深度图形库

DGL 包是最广泛的库之一,由创建图形的核心构建块、几个消息传递函数以及完整的图形神经网络模型组成,一切就绪。DGL 图书馆的另一个优势是它可以与最常用的后端*台协同工作,比如 TensorFlow、Pytorch 和 MXNet。最后,DGL 提供了一个数据 API,它提供了对一些基准数据集的访问,其中一个是 Cora 引文图表,它相当于图表领域的 MNIST…

图关注网

数据科学家可能想要使用的一个这样的 GNN 是图形注意力网络。这是一个半监督学习模型,除了节点特征之外,只需要有限数量的已知标签来训练模型。它通过计算图中每个节点的隐藏表示来做到这一点,方法是“关注”该特定节点的邻居。也就是说,它应用一种【基于注意力的架构】来执行节点分类。

理论

在我们开始实验之前,我们将首先解释我们正在部署的 GNN 模型。图注意力网络(缩写为' GAT ',例如不要与生成对抗网络)是由 Velickovic 等人在 2018 年引入的,作为对现有图卷积神经网络的改进。顾名思义,GATs 的核心思想是应用基于“注意机制”的架构。

注意机制彻底改变了神经机器翻译和一般的 NLP,并且已经成为许多基于序列的模型中事实上的规范。注意机制可以大致分为两个主要类别:“一般注意”和“自我注意”,前者量化输入和输出元素之间的独立性,后者管理和量化输入元素内部的独立性。在 GAT 模型中,注意机制的作用是"按照自我注意策略,通过关注其邻居来计算图中每个节点的隐藏表示。

我们将简要描述单个“图形注意力层”的关键步骤和组成部分,并向感兴趣的读者推荐该论文以获得更详细的数学解释。

模型的叙述可以总结为 5 个步骤:

  1. 第一步是定义向模型提供输入的节点要素集。正如我们将看到的,在我们的例子中,这些是通过将每个文档的文本嵌入长度为 1433 的 0/1“单词包”向量中而获得的特征向量。
  2. 第二步,我们使用可学习参数的共享权重矩阵对每个特征向量应用线性变换。
  3. 第三步涉及通过如下计算关注系数来执行自关注:我们连接源和目的节点的两个线性变换的节点特征(在步骤 1 中线性变换),并应用关注机制。这种机制无非是将 LeakyReLu 非线性激活函数应用于可学习权重向量(姑且称之为 a )与级联节点特征的点积。同样地,注意机制可以被视为由权重向量参数化的单个前馈神经网络,并且 LeakyRelu 作为激活函数。关注系数可以解释为一个节点的特征对其邻居的重要性。
  4. 作为倒数第二步,通过应用 softmax 函数来归一化关注系数,这使得不同节点之间的系数具有可比性。这将允许分析哪些关注系数对隐藏节点以及输出具有最大影响。反过来,它允许测量注意力分布的“熵”。
  5. 作为最后一步,在可能应用非线性σ之后,归一化的注意力系数用于计算对应于它们的特征的线性组合,并产生每个节点的隐藏表示。

单一的注意机制可以想象如下:

图片摘自图关注网论文

单头还是多头?

GAT 论文的作者发现,为了稳定自我注意的学习过程,将该机制扩展到“多头注意”表现得更好。简而言之,多头机制简单地并行多次贯穿点积注意力。回想一下上面的步骤 3,在注意力系数计算中,我们有一个权重向量。好了,多头注意力现在产生了几个(下图中的 3 个),然后将它们连接起来产生隐藏的表示。然而,在最后一层中,执行*均。

这可以如下所示(使用绿色、蓝色和紫色的 3 个头)

图片摘自图注意力网络论文

实验

我们现在将使用 Neo4j Python 驱动程序来实现图形注意力网络,以访问 DGL 库,执行机器学习任务,将结果写回到 Neo4j 中的原生图形,并执行 Cypher 查询。

数据集

我们将使用的数据集是前面提到的 Cora 引文数据集,它也是 GAT 论文中使用的数据集之一,由机器学习领域的学术论文组成。这些论文分为以下七类之一:

  1. 基于案例
  2. 遗传算法
  3. 神经网络
  4. 概率方法
  5. 强化 _ 学习
  6. 规则 _ 学习
  7. 理论

论文的选择方式是每篇论文都引用或被至少一篇其他论文引用。整个语料库中有 2708 篇论文,5429 条边。

Cora 数据集是 DGL 数据 API 的一部分,为了使工作流程易于复制,我们还使用了这个版本的 Cora 数据集,我们将用 Neo4j 将它写成一个图表。与原始 Cora 数据集的唯一区别是节点标注,在 DGL 版本中是基于索引的。

然而,似乎有一些重复,因为 DGL 用 5278 条独特的边过滤掉了它们。事实上,当将 Cora 边加载到 Neo4j 中时,我们也得到 5278 个关系。因此,数据集有 5278 个关系,我们在 Neo4j 中将其称为“被引用”关系类型。我们使用 Python 驱动程序将 Cora 图写入 Neo4j,如下所示:

关于如何使用 Neo4j Python 驱动程序的极好参考可以在 Clair Sullivan 的这篇文章中找到。

Cora 图中的引用示例

特征向量

对每篇论文的文本进行分析,并提供如下特征向量:在词干化并去除停用词以及频率小于 10 的词之后,我们最终得到 1433 个唯一的词,这提供了字典。该字典现在允许创建二进制值的特征向量(即,如果单词出现在文档中,则向量条目为 1,0,否则为 1,0),也称为“单词包”表示。因此,在我们的例子中,代表一个节点的每个文档都有这样一个长度为 1433 的特征向量。

任务

我们设置 GAT 来模拟直推式学习任务(半监督学习),该任务预测节点的标签,但是每类仅允许 20 个节点用于训练,即总共 2708 个节点中的 140 个。然而,训练算法给出了所有节点的特征向量的完整集合。经过训练的模型也只有 140 个训练标签,在 500 个节点上进行验证,并在一组 1000 个节点上进行测试。该任务可以应用于各种现实世界的应用,例如产品标签,其中特征向量是从产品描述中导出的,或者客户分类,其中特征向量可以由共同购买等组成。

超参数选择

本文附带的 Colab 笔记本可以在这里找到,它包含了每个代码块的详细注释。需要注意的关键点是,该模型选择了 8 个注意头,并且给定了小的训练集和过度拟合的风险,该模型使用 L2 正则化和丢弃(p = 0.6)来降低这种风险。最后,交叉熵被用作 ADAM SGD 优化器的损失函数

运行图形注意力模型

如前所述,Deep Graph Library 是最广泛、记录最完整的图形机器学习库之一,具有能够在 PyTorch、TensorFlow 或 MXNet 上运行的额外优势。

任何机器学习模型的核心都是层,这在 DGL 库中没有什么不同,因此,dgl.nn 包包含了最常用的 GNN 层的实现,当然也包括 GAT 层。最后,DGL 和张量流的组合被设计成完全使用 GPU 的。

工作流程

代码在 Colab 笔记本中进行了注释,工作流程相当简单。

使用 DGL 数据 API 将数据加载到笔记本/模型中,并使用掩码方法进行预处理。这是一个简单的布尔向量,暴露或隐藏相关训练、验证和测试集的标签。GAT 层是 TensorFlow-Keras 层的子类,在实例化类时需要确定参数。为了做到这一点,我们创建了一个单独的函数create_model,除此之外还有几个帮助函数,用于损失、准确性、评估、提前停止等。

最后,train函数调用相关的函数,它的参数决定超参数,如上面所列,我们使用了与本文相同的方法。

我们还确保将预测的标签写入熊猫数据帧,这样我们就可以将它们写回 Neo4j。

至于训练,我们选择了 500 个纪元,但包括一个我们将“耐心”设置为 100 的早期停止。

该模型的运行时间不到 10 秒,并在 379 个周期后达到早期停止触发,实现了令人印象深刻的 82.10%的准确性。

令人欣慰的是,这与论文中取得的结果一致:83.0%,方差为 0.7%。

因此,在我们的测试集中的 1000 个节点中,图形注意力网络模型成功地正确标记了 820 个,只需要大约 5%的标签来训练(2708 个中的 140 个),当然还有每个节点的特征。

将预测标签写入 Neo4j

既然我们与 DGL 的合资企业已经产生了我们需要的结果,是时候返回母舰了。同样,我们调用 Neo4j Python 驱动程序将结果写回 Neo4j 中的 Cora 图。这只需要我们 7 行代码加上标准的 Cypher 查询,如下所示:

我们让模型在整个图上运行预测,所有 2708 个节点,从上面的 Cypher 查询可以看出,我们将预测的标签作为节点属性写入图中。

我们现在在 Neo4j 中有以下内容:

*╒══════════════════════════════════════╕
│"n"                                   │
╞══════════════════════════════════════╡
│{"id":0,"label":"Genetic_Algorithms","│
│Predicted_Label":"Genetic_Algorithms"}│
├──────────────────────────────────────┤
│{"id":1,"label":"Rule_Learning","Predi│
│cted_Label":"Rule_Learning"}          │
├──────────────────────────────────────┤
│{"id":2,"label":"Rule_Learning","Predi│
│cted_Label":"Rule_Learning"}          │
├──────────────────────────────────────┤
│{"id":3,"label":"Case_Based","Predicte│
│d_Label":"Case_Based"}                │
├──────────────────────────────────────┤
│{"id":4,"label":"Genetic_Algorithms","│
│Predicted_Label":"Genetic_Algorithms"}│
└──────────────────────────────────────┘*

我们现在可以运行一些密码查询,例如,我们可以检查有多少预测标签与实际标签不同:

它返回了 454 个——因此,我们在 2708 个标签中有 454 个是不正确的,即 16.7%,因此实际上有 83.3%被正确预测,在去除 140 个训练标签后,这与论文中的结果完全相同。

我们还可以在 Neo4j 中进行一些更详细的分析,方法是将上面的命令分配给一个精度属性,然后计算每类纸张的精度,如下所示:

*╒══════════════════════════════════╤══════════════════╕
│"Label"                           │"Accuracy"        │
╞══════════════════════════════════╪══════════════════╡
│["Theory"]                        │0.9425837320574163│
├──────────────────────────────────┼──────────────────┤
│["Probabilistic_Methods"]         │0.8986175115207373│
├──────────────────────────────────┼──────────────────┤
│["Rule_Learning"]                 │0.8943661971830986│
├──────────────────────────────────┼──────────────────┤
│["Case_Based"]                    │0.8062678062678063│
├──────────────────────────────────┼──────────────────┤
│["Reinforcement_Learning"]        │0.738255033557047 │
├──────────────────────────────────┼──────────────────┤
│["Genetic_Algorithms"]            │0.7286063569682152│
├──────────────────────────────────┼──────────────────┤
│["Neural_Networks"]               │0.7111111111111111│
└──────────────────────────────────┴──────────────────┘*

结论

在本文中,我们已经表明,通过使用 Neo4j Python 驱动程序,可以访问一系列额外的机器学习模型,并补充现有的 Neo4j GDS 功能。

在未来的文章中,我们将说明有多少 Neo4j GDS 算法可用于计算一系列特征向量,这些向量随后可用于训练 GNN,并再次将结果返回到本机 Neo4j 图。

抗生素耐药性的 Neo4j

原文:https://towardsdatascience.com/neo4j-for-antibiotic-resistance-f452f74137e8?source=collection_archive---------31-----------------------

卡片数据库的另一种视图

抗生素的引入是我们公共卫生史上的一个里程碑。它们是用于预防和治疗细菌感染如肺炎和肺结核的药物。抗生素拯救了数百万人的生命。

然而,它们的过度使用和误用导致了抗生素抗性细菌的出现。这些细菌可以在抗生素中存活,因为它们拥有耐药性——赋予抗生素耐药性的基因。其中一些基因编码的蛋白质可以减少药物的输入,增加输出或者使药物失去活性。其他的编码突变的药物靶点,逃避抗生素的攻击。抗生素抗性基因的垂直(母细胞和子细胞之间)和水*(不同细菌之间)转移导致抗生素抗性细菌在全球迅速传播。

作者 Charles Kenny 在他的《鼠疫循环:人类与传染病之间无休止的战争一书中描述了我们目前令人担忧的抗生素耐药性现状。

但是最好的估计是,仅在美国,耐甲氧西林金黄色葡萄球菌(MRSA)每年就杀死 18000 人。在欧洲和美国,抗生素耐药性造成的总人数每年约为 5 万人。在世界范围内,耐药细菌每年已经导致多达 70 万人死亡,是霍乱死亡率的 7 倍,麻疹死亡率的 6 倍。而耐药性是一个有爆发风险的问题。

后抗生素时代前景黯淡:

由英国政府发起、经济学家吉姆·奥尼尔主持的一项关于抗生素威胁的评估预测,如果我们不采取行动,到 2050 年,全球每年将有 1000 万人死于日益增加的抗生素耐药性。这比全世界每年死于癌症的人数还要多。相比之下,世界卫生组织估计,2030 年至 2050 年间,每年因气候变化而死亡的人数将增加 25 万。全球死于恐怖主义的人数大约是抗生素耐药性潜在死亡人数的千分之一。

所以我们需要快速行动,我们需要科学数据。综合抗生素耐药性数据库 (CARD)是一个重要的数据来源。

图一。全面的抗生素耐药性数据库。作者截图。

自 2013 年以来,CARD 数据库已经收集了超过 3300 个基因序列及其相关抗生素。工作人员仔细策划收集,并在抗生素耐药性本体论(ARO)和抗微生物耐药性(AMR)基因检测模型中组织数据。该数据库还为我们提供了用于数据分析的生物信息学工具。CARD 已经成为研究和工业的重要数据来源。CARD 的首席研究员 Andrew G. McArthur 表示,在欧洲,运行通过卡是益生菌产品批准的一项要求。

每种药物、抗生素耐药性和基因都有自己的页面。例如, acrD 外排泵的页面是这样的:

图二。卡片中的 acrD 页。作者截图。

该网页显示了该基因的详细信息,它的流行程度,它可以对抗的抗生素等等。然而,目前还没有关于“耐药体”的网页,准确地说是“病原体”的网页。所以像“这种细菌对哪种抗生素耐药”这样的常见问题,在 CARD 里是无法直接回答的。

在我以前的文章“在图数据库中分析基因组和“ Neo4j 用于疾病”中,我已经展示了我们可以将关系数据库中的生物数据转换成图,并发现新的见解。尽管有很多图形数据库,Neo4j 无疑是这个领域的领导者。它易于使用和扩展。它的密码语言很简单。最后但同样重要的是,图形数据科学库提供了许多强大的图形操作和机器学习能力。在本文中,我将向您展示如何将 CARD 转换为 Neo4j,并从数据中快速获取一些事实。这个项目的代码存放在我的 Github 仓库中:

https://github.com/dgg32/card

1.导入数据

从卡下载页面,下载并解压缩Ontology filesCARD Prevalence, Resistome, & Variants data。事实上,我们只需要从两者中选择aro.obocard_prevalence.txt。运行我的analysis.ipynb中的所有细胞。它将这两个文件转换成五个 CSV 文件,以便导入。你可以在我的知识库中找到所有这些文件。

启动 Neo4j Desktop,创建一个名为card的项目,并将所有这些 CSV 文件放入其Import文件夹中(阅读段落" 2)。将数据导入 Neo4j "如果需要帮助)。在 Neo4j 浏览器中运行以下命令,以导入和索引 Neo4j 中的数据:

这些命令将创建三种类型(标签)的节点(drugpathogenresistance)。它们由两种类型的关系(confers_resistance_to_drug_classhas_resistance)连接。

2.概观

导入后,我们可以快速查看数据。运行以下三个查询来获得三种节点类型的总数:

有 43 种药物,263 种病原菌和 2640 种耐药机制。值得注意的是,下载数据和网络数据之间存在差异。例如,根据aro.obo,SHV-52 (ARO:3001109)不具有授与 _ 抗性 _ 药物 _ 类别关系。但是它的网页表明它可以帮助宿主抵抗青霉烯、碳青霉烯和头孢菌素(图 3)。为了避免混淆,本文仅基于下载的卡数据。这个项目的第二个警告是,分类学的分辨率下降到物种水*,而不是菌株水*,这本来可以更精确。

图 3。SHV-52 的数据在网页和下载之间不一致。作者截图。

我们还可以使用 Neo4j Bloom 快速创建卡片数据的拓扑概览(在此阅读我的文章获取说明)。

图 4。卡片数据的拓扑概述。绿色的点代表药物节点,紫色的是病原体,橙色的是耐药节点。图片作者。

在图 4 中。,我们可以看到数据主要聚集在紫色病原体节点周围。在 Neo4j Bloom 中,我们可以识别出一些大型“枢纽”。分别是大肠杆菌肺炎克雷伯菌铜绿假单胞菌鲍曼不动杆菌。这些也是科学报告中研究最多的抗生素抗性细菌。

3.调查超级细菌

超级细菌是多重耐药细菌,也就是说,它们对一种以上的抗生素具有耐药性。它们可以有多个基因,每个基因都可以抵抗一种抗生素。或者一个基因可以对抗多种抗生素(阅读这篇文章了解更多细节)。耐碳青霉烯类肠杆菌科(CRE)已对“所有或几乎所有”抗生素产生耐药性,包括“最后的治疗手段”碳青霉烯类。2015 年,在中国的患者和牲畜中发现了对另一种最后手段药物粘菌素具有耐药性的细菌。根据疾病预防控制中心的数据,在美国,它们每年感染 200 万人,杀死 23000 人。因此,迫切需要更多地了解这些生物。

我们可以先查一下耐药连接最多的前 10 个超级细菌。请注意,OPTIONAL MATCH子句是必要的,因为在 CARD 中,许多阻抗节点不与任何药物相连。

它返回:

肺炎克雷伯氏菌通常发现于胃肠道的粘膜表面。但是一旦它进入人体,它会变得非常致命并对抗生素产生抗药性。顾名思义,肺炎克雷伯氏菌可导致肺炎,是美国医院获得性肺炎最常见的原因。但是这种细菌也会带来其他疾病,如血流感染、伤口和手术部位感染以及脑膜炎。我们的分析表明 K肺炎连接一千多个阻力节点。这些耐药机制提供了对 13 种抗生素的耐药性,也是我们数据集中最多的。

通过以下查询,我们可以获得更多详细信息:

它会返回一个图表:

图 5。肺炎克雷伯菌抗生素耐药性详情。图片作者。

图表显示肺炎克雷伯菌对头孢菌素类抗生素 KpnEFGH 具有耐药性。它们都是从细胞中泵出抗生素的主要促进超家族(MFS)抗生素外排泵的组成部分。据艾舍斯特等人肺炎克雷伯菌也能以其超广谱β-内酰胺酶(ESBL)降解头孢菌素。因此,另一种抗生素——碳青霉烯成为了一种治疗选择。但是我们的结果表明,这种选择也可能是无效的,因为 LptD 机制本身可以赋予对碳青霉烯和其他三种药物的耐药性。事实上,在 2013 年向 CDC 报告的 9000 例耐碳青霉烯类肠杆菌科感染中,约 80%是由肺炎克雷伯菌引起的。此外,qacE、Edelta1 和 L 基因可以保护细菌免受消毒剂和嵌入染料的影响。

4.耐药性最强的抗生素

使用 Neo4j,我们还可以研究哪些抗生素最有可能成为抗生素耐药性的目标:

结果是:

氟喹诺酮干扰细菌中的 DNA 复制,并导致革兰氏阴性和革兰氏阳性细菌中的细胞死亡。但是 CARD 数据表明,这两种类型的细菌已经发展出许多抵抗其影响的策略(图 6。):

图 6。细菌对氟喹诺酮类药物的耐药性。图片作者。

一方面,革兰氏阳性菌如杆菌葡萄球菌利用 blt、qacAB 等 MFS 抗生素外排泵系统泵出氟喹诺酮类药物。另一方面,肠球菌编码 PmpM,这是一种药物逆向转运蛋白,属于多药和毒性化合物挤压(MATE)家族。然而,在革兰氏阴性细菌中也发现了 PmpM,如嗜麦芽窄食单胞菌粘质沙雷氏菌假单胞菌,另一组革兰氏阴性菌,含有与 abaQ 相似的基因序列,该基因编码一种 MFS 转运蛋白,负责 A 中喹诺酮类药物的挤出。鲍曼

头孢菌素,列表中的第二项,显示了一个非常不同的拓扑结构。

图 7。细菌对头孢菌素的耐药性。图片作者。

与对氟喹诺酮类抗生素的多种耐药机制相反,对头孢菌素只有四种耐药机制。总共有 52 种病原体使用它们。有些病原菌,如产酸克雷伯氏菌植物拉氏菌,具有全部四种耐药机制。

结论

本文展示了 Neo4j 如何快速洞察 CARD。在我看来,CARD 包含了如此多的关系,以至于图形数据库比关系数据库更适合它。在其关系形式中,“这种细菌对哪种抗生素具有抗性”这一问题的答案不是立即显而易见的,因为 CARD 通过抗性机制连接细菌和抗生素。这对于 Neo4j 来说不是问题。我们可以用 Cypher 简单地表达这个问题,然后马上得到答案。

但是下载的卡数据并不总是与在线数据一致。也许我漏掉了一些环节。此外,有些联系是相当投机的。例如,根据描述,cdeA 在 E 中赋予对氟喹诺酮类药物的耐药性。大肠杆菌梭状芽孢杆菌艰难梭菌。但是我们的数据连接 C难与氟喹诺酮类通过 cdeA 机制过。

在这个项目中,我只分析了基于card-prevalenc.txt的细菌种类。但是,如果我们利用 CARD 提供的 NCBI 登录号,就有可能得到菌株的分辨率。那么结果将会更加具体和精确。当然,如果 CARD 一开始就在菌株水*上汇编病原体,事情会简单得多。

这项研究也揭示了抗生素耐药性的情况。上图显示,耐药机制的数量超过了病原体的数量,比例为 10:1。这意味着病原体*均有十种机制来对抗抗生素的作用。同样清楚的是,有比抗生素更多的耐药机制。随着新抗生素研发的放缓,我们正在耗尽抗生素。

请尝试这个项目,告诉我你的经验。

https://dgg32.medium.com/membership

宝莱坞的 Neo4j

原文:https://towardsdatascience.com/neo4j-for-bollywood-5ceb371031f1?source=collection_archive---------17-----------------------

学习图形数据库的有趣项目

厌倦了 SQL 中的那些“JOIN”?每次需要修改关系数据库中的模式时,您是否都感到头疼?如果任何一个答案是“是”,那么你应该给图形数据库,如 Neo4j 一个尝试。

图形数据库将信息存储为节点和边。节点通过边连接,它们都有属性。我们可以通过查询检索和聚集数据。因为它们的逻辑和语义更接*于我们大脑对现实世界的建模方式,所以图形数据库很容易学习。关系数据库的用户可能会很快发现 SQL 和 Neo4j 的查询语言 Cypher 的相似之处。此外,Neo4j 附带聚合函数和机器学习模块,可以快速洞察数据。

在我以前的文章中(抗生素耐药性的 Neo4j、疾病的和基因组分析的),我已经展示了图形数据库 Neo4j 可以提供许多在关系数据库中不那么明显的有趣见解。但是它们都是关于生物信息学的,不是最简单的学科。这些文章更多的是关于 Cypher 相对于 SQL 的优势。读者要求我对 Neo4j 进行更全面的介绍,以加快学习速度。因此,我四处寻找 Neo4j 初学者项目的数据,特别是为有 SQL 背景的读者。最*,我偶然发现了 P. Premkumar 的宝莱坞电影 (CC BY 4.0)的数据集,并认为它非常适合。

组合词宝莱坞Bo mbay 和 Ho llywood 创造。顾名思义,这是总部设在孟买的印地语/乌尔都语电影业。这些电影涵盖了广泛的主题,其中一些甚至触及了敏感的政治和宗教话题。许多电影都包含了欢快的舞蹈场景,让气氛变得轻松起来。宝莱坞电影在全世界都很受欢迎。例如,电影《Dangal》在中国获得了巨大成功,其 3.3 亿美元的全球票房中有三分之二来自中国。好莱坞已经被大量报道,但宝莱坞很少得到应有的关注。因此,更多地了解这个电影行业将是一件好事。Premkumar 的表格数据很小,但包含了 2005 年至 2017 年间的 1698 部宝莱坞电影。所以我认为它是这个介绍性项目的一个极好的数据源。这个项目的代码存放在我的 Github 仓库中:

https://github.com/dgg32/bollywood

数据集来自https://boxofficeindia.com。与 IMDB.com 相比,boxofficeindia.com 的数据非常不完整。此外,请注意,该表仅列出了主要演员。所以它低估了演员和电影之间的联系。另外,这个项目只包括演员、导演,以及他们的电影。原始数据中还有一个小问题:预算和收入列放错了位置。

1.准备和导入数据

首先从链接这里下载数据。交换列名Budget(INR)Revenue(INR)。接下来,运行我的 Python 笔记本prepare.ipynb中的所有单元格。他们应该在data_for_neo4j文件夹中生成三个 CSV 文件。你也可以在我的 Github 库中找到所有的数据文件。

打开Neo4j Desktop。创建一个名为bollywood的项目,并将三个 CSV 文件放入其import文件夹中。

之后,打开Neo4j Browser并输入以下命令。他们将把数据导入数据库(参见 2。将数据导入 Neo4j 一节以获得详细说明)。

我们可以检查三种类型的节点(演员、导演和电影)是如何连接的:

call db.schema.visualization()

图一。宝莱坞项目的模式。图片作者。

2.概观

让我们首先了解一下数据集的概况。打开Neo4j Desktop中的Neo4j Bloom。在Settings中,将Node query limit增加到 3600。在Perspective - > Search phrases中,添加一个名为match all的搜索短语,查询如下:

返回主窗口,在Search graph中选择match all并运行。Bloom 应该生成数据集的拓扑概览(图 2)。

图二。宝莱坞数据集的拓扑概述。绿色:电影;红色:演员;蓝色:导演。图片作者。

概述立即给我们一个宝莱坞电影世界的总体印象。很多演员-电影-导演三重奏都是“孤岛”。但是可以看到一个大的星团。我们可以通过放大或使用过滤器来了解更多信息:

图 3。数据集中大型聚类的详细部分。绿色:电影;红色:演员;蓝色:导演。图片作者。

很明显,这一大群人是由多产的宝莱坞演员聚集在一起的,如三汗、阿克谢·库玛尔埃朗·哈斯米和导演如维克拉姆·帕特莫希特·苏里

我们还可以看看数据集中的流派分布:

Neo4j 的文档解释说,与 Bash 中的管道操作符类似。在上面的查询中,我用 with 语句计算了电影的总数,然后将其用于百分比计算。结果表明,戏剧、喜剧和惊悚片是宝莱坞的三大电影类型。

3.获取一些统计数据

概述完后,我们可以用 Neo4j 快速计算统计。首先,让我们来计算一下阿米尔·汗电影的总收入:

这个 Cypher 首先匹配所有以阿米尔·汗为主角的电影,然后将它们的收入加起来。它很快给了我们总计 29,030,895,000 印度卢比(393,932,987 美元)。作为宝莱坞最成功、最有影响力的演员之一,阿米尔·汗曾在今年票房最高的几部印度电影中扮演主角,如 Ghajini3 个白痴RangeelaDhoom 3PKDangal 。他也被称为“中国票房之王”,因为他的电影在中国也获得了巨大的成功。

接下来,我们可以看到收入最高的人:

与前面的查询相比,这个查询删除了对 actor 节点的约束。它计算了收入预算比率,以显示电影的相对盈利能力。最后,该查询根据收入按降序对结果进行排序。

查询显示,帕拉巴斯的 Baahubali 2 位居榜首。但是这部电影的制作成本也很高。相比之下,丹加尔的收入预算比为 5。可汗又一次占据了榜单。请注意,这些结果与来自维基百科的数据并不一致。

我们可以看到最卖座电影的名单。

这个快速查询返回了数据集中前 10 个失败。位居榜首的是孟买天鹅绒 ,因剧本和导演受到批评。第一天的入住率只有 10-20%。第三天所有的影院都撤下了这部电影。它在投资者的口袋里烧了一个 748,635,000 印度卢比的洞。第二名被 破马 占据。这部电影得到的评价大多是负面的,它也是一个商业上的失败。但对我来说,仅由一名印度导演主演并不能证明这部电影是真正的宝莱坞电影。

之后,我们还可以看到哪些演员最擅长惊悚片或恐怖片。

埃朗·哈斯米和阿杰·德弗恩似乎是最活跃的惊悚片演员。哈什米先生成功地确立了自己作为惊悚电影明星的地位。我们可以在数据集中看到他所有电影的列表:

原来,哈什米先生也是恐怖电影系列 Raaz 最后三部的主角。根据数据集,宝莱坞并没有太多的恐怖电影(1695 部中的 52 部,或 3%,见“2。概述”)。仅这三部恐怖电影就已经让 Hashimi 先生成为了我们数据库中拥有最多恐怖电影的演员。

最后,让我们看看一些演员和导演合作的频率。

超级巨星 Ajay Devgn 和导演罗希特·谢迪之间的兄弟关系是众所周知的。1991 年的电影 是他们合作的第一部电影。到目前为止,他们已经合作了 11 部电影。

4.社区检测

在第二部分,Neo4j Bloom 的拓扑概述向我们展示了一个围绕宝莱坞一些最大的名字的大集群。现在的问题是,是否有可能通过查询获得该社区?在 Neo4j 的图形数据科学库(GDS)的帮助下,答案是响亮的“是”。

在我之前的文章“ Neo4j for Diseases ”中,我展示了如何使用 Louvain 算法计算社区。但是在这个项目中,我没能用 Louvain 得到最优的结果。然后我找到了托马兹·布拉坦尼克的中间文章“Neo4j 图形数据科学库中的子图过滤”。在里面,他提到了另一个算法“弱连通分量 (WCC)”。该算法在无向图中寻找连接节点的集合,其中同一集合中的所有节点形成一个连接组件。我的测试表明,它可以快速识别不连接的组,并有效地隔离第 2 节中的大集群。

要使用 WCC,您需要在您的项目中启用 GDS 插件(阅读第 5 节中关于疾病的说明Neo4j)。首先,我们需要用以下命令创建一个内存中的图形:

之后,我们运行 WCC。它返回前 10 个最大的社区(在 WCC 中称为“组件”):

我们可以看到组件 0 有多达 1750 个节点。但是,我发现有些节点被重复计算了。让我们看看具有不同功能的节点是什么:

该查询返回 1,734 个节点,而不是最初的 1,750 个。我们甚至可以在 Neo4j 浏览器中显示网络。但是首先,在 Neo4j 浏览器中调整可视化参数(图 4)。

图 4。显示大型集群的设置。图片作者。

然后运行命令:

COLLECT 函数将名字转换成一个列表。然后我们做一个普通的匹配查询,用这个列表过滤结果。

图 5。宝莱坞数据中的组件 0。图片作者。

经过仔细的检查,我们可以确认这就是我们在第 2 节的 Neo4j Bloom 中观察到的大星团。

结论

电影 降临 有一个信息:一种新的语言可以改变你的思维方式。从 SQL 到 Cypher 的过渡也是如此。与 SQL 不同,我们需要在 Cypher 中明确定义关系。Cypher 是直观的,因为我们可以在不使用外键的情况下通过关系制定查询。换句话说,Cypher 让我们在网络中而不是在桌子上做事。Neo4j Desktop 和 Bloom 中的图形可视化让我们可以轻松地以交互方式探索各种关系。

这个项目表明,Neo4j 不仅擅长关系丰富的数据,而且还可以像 SQL 一样轻松地聚合表格数据。本教程主要展示了 Neo4j 中的统计函数。读者可以很容易地将 SQL 查询与上面的 my Cypher 查询进行比较,并感受到两种语言在语法和表达能力上的差异。根据维基百科,Cypher 的语法是基于 ASCII-art 的。所以查询看起来非常直观,易于理解。结合其聚合和图形数据科学功能,Neo4j 可以做关系数据库能做的任何事情,甚至更多。

宝莱坞的数据也给了这个项目许多有趣的因素。我们了解到宝莱坞的一些大牌明星有着令人印象深刻的统计数据。这些知识可能会帮助我们在未来更好地欣赏宝莱坞电影。

这里有一个挑衅性的想法:我们是否只能使用 Neo4j 这样的图形数据库来满足我们所有的需求?

https://dgg32.medium.com/membership

用于疾病的 Neo4j

原文:https://towardsdatascience.com/neo4j-for-diseases-959dffb5b479?source=collection_archive---------22-----------------------

用图形数据库分析 KEGG 疾病数据

本文展示了如何:

1.使用 Neo4j 快速浏览 KEGG 疾病数据库。

2.识别多用途药物。

3.显示一些病原体的细节,如新型冠状病毒。

4.用 Louvain 形成疾病社区,用 PageRank 发现关联度最高的疾病。SARS 和新冠肺炎是与其他大型疾病群隔离的“孤岛”。

免责声明:本文不提供医疗建议。它仅供参考。它不能替代专业的医疗建议、诊断或治疗。

新冠肺炎遥遥领先于世界。这种传染病给我们的生活带来了沉重的代价。它扰乱了许多家庭,造成巨大的经济损失,也许永远改变了我们的行为。因此,它提高了我们对公共卫生问题的认识。显而易见,我们人类需要在医学研究上投入更多,以避免下一场灾难。

图一。来自 KEGG 疾病数据库的条目“新冠肺炎”在 Neo4j 中可视化。作者图片。

自从我的上一个故事“在图数据库中分析基因组”以来,我注意到在京都基因和基因组百科全书(KEGG) 数据库中仍然有许多宝藏。其中之一无疑是 KEGG 疾病数据库。该数据库包含许多已知人类疾病的详细信息。此外,连同其他数据库,如基因组,药物和基因,KEGG 为我们提供了一个非常广泛的网络知识的障碍,其原因和药物。正如我在文章中提到的,像 Neo4j 这样的图形数据库有助于生物医学研究中的知识发现。来自 KEGG 的这些信息对于这样一个数据项目来说是完美的。因此,我通过 API 下载并处理了 KEGG 疾病数据库中的数据,将其导入 Neo4j,进行了几次分析,并发现了一些有趣的信息。

在这篇文章中,我将集中讨论疾病、病原体和药物之间的关系。这个项目的代码存放在我的 Github 库中:

https://github.com/dgg32/kegg_disease

1.将数据导入 Neo4j

所有 CSV 文件都位于数据文件夹中。如果你想更新信息,你可以按照我的回购 README.md 中的说明。

从他们的官网下载 Neo4j 桌面。安装完成后,添加一个新的“本地 DMBS”并命名为“kegg_disease”。点击“…”->“打开文件夹”- >“导入”,打开其导入文件夹。将所有 CSV 文件放入文件夹中。然后,运行以下命令,它们将导入所有信息:

2.获取概述

一旦数据被导入,我们就可以对 KEGG 疾病数据库进行一些基本的统计。这三个命令获取所有三种类型节点的总数:

因此,数据库中记录了 333 种病原体、1,339 种药物和 2,498 种疾病。这是一个相当大的数据集。我们也可以用 Neo4j Bloom 看看数据的拓扑结构。在搜索短语中输入下面的密码查询并执行它(我以前的文章展示了详细的步骤):

MATCH p=(n:disease) <-[]-() RETURN p;

图二。此项目中的数据拓扑。绿点代表“疾病”,红点代表“药物”,蓝点代表“病原体”。作者图片。

运行以下命令以获取数据集中排名前十的疾病类别。尽管有些疾病(如 Schwartz-Jampel 综合征和中央核肌病)被分为两类,但要小心,查询不会分别重复计算它们。:

你会看到这样的结果:

令我惊讶的是,在这个问题下,第一名既不是传染病,也不是两个臭名昭著的杀手——心血管疾病和癌症。是先天畸形,包括钉-髌骨综合征和梅克尔综合征。

传染病可由病毒、细菌或真核生物引起。以下命令将显示数据库中每个的编号:

结果是:

令我惊讶的是,细菌,而不是病毒,是数据中最常见的病原体。通过发出以下命令,我们可以更深入地了解病毒:

这个查询结合了分类法的第一层和第二层,并对它们进行计数。

如你所见,核糖病毒是最丰富的病毒领域。但是核糖病毒也是一个非常多样的分类群。新型冠状病毒及其前身 SARS 冠状病毒(2002-2004 年 SARS 爆发的病原体)都属于核糖病毒属。但是人类免疫缺陷病毒(HIV)和肝炎病毒也是如此。

最后,我们可以通过发出以下命令来获得抗传染病药物的数量:

该查询返回 293 种药物。值得注意的是,“DISTINCT”关键字在这里是必要的,因为一些药物可以用于治疗多种疾病,如果没有“DISTINCT ”,它们会被重复计算。

3.寻找多用途药物

多用途药物是可以用来治疗一种以上疾病的药物。换句话说,他们是多才多艺的。因为药物的开发很昂贵,而且需要严格的临床试验,所以如果“旧药能出新招”(请看美国国家卫生研究院主任弗朗西斯·柯林斯富有启发性的 TED 演讲这里),这对患者和制药公司来说无疑都是好消息。在实践中,药物受到美国食品和药物管理局等机构的严格监管,制造商只能将它们用于食品和药物管理局批准的适应症。因此,找出数据中最通用的药物以及它们的适应症将是非常有趣的。

发出以下命令来查看十大最通用的药物:

结果是:

前十名名单基本由两类药物组成:类固醇激素和四环素类抗生素多西环素。类固醇激素用于抑制免疫系统和治疗各种炎症。列表中的第三种地塞米松已经在新冠肺炎患者中进行了研究,初步结果显示,它降低了那些接受有创机械通气或单独使用氧气的患者的死亡率,但没有降低那些没有接受呼吸支持的患者的死亡率(康复合作小组,2020 年)。强力霉素是一种广谱抗生素,用于治疗疟疾、莱姆病、霍乱和梅毒等传染病。事实上,以下查询显示,这些类固醇激素的适应症相互重叠,而多西环素及其衍生物也针对许多相同的疾病。

图 3。KEGG 十大多用途药物的适应症。作者图片。

例如,列表中的前两种药物:泼尼松及其活性形式泼尼松龙,自 1955 年以来在美国已被批准用于医疗用途。它们很受欢迎:根据 DrugStats 数据库,到目前为止,泼尼松是 2021 年美国第 21 大处方药,泼尼松龙是第 134 大处方药。逐一发出这两个命令,查看泼尼松龙磷酸钠的详细信息:

并且查询返回

并且:

事实证明,泼尼松龙不仅用于治疗免疫系统疾病,还用于治疗旋毛虫病和结核病等传染病。由于其抗炎作用,它也用于慢性阻塞性肺病(COPD)。然而,其在特发性肺纤维化(IPF)中的应用尚不确定

到目前为止,美国 2021 年最常开出的药物——阿伐他汀及其衍生物,其用途仅限于四种代谢或心血管疾病:高脂血症、家族性高胆固醇血症、心绞痛和心肌梗死。

图 4。KEGG 中阿伐他汀及其衍生物的适应症。作者图片。

4.一些病原体的细节

现在是探索病原体数据的时候了。首先,我们可以数一数一种病原体能引起多少种不同的疾病。

前十都是病毒。前两种是乳头瘤病毒,可导致人类不同类型的癌症。根据维基百科,大多数乳头瘤病毒感染是无症状的,90%的病例会在两年内消失。但在其他情况下,它们持续存在并导致疣或病变。这些病变增加了人体各部位患癌的风险,如子宫颈、外阴、阴道、阴茎、肛门、口腔、扁桃体或咽喉(图 5。).几乎所有的宫颈癌都是由人乳头瘤病毒引起的;这两种菌株占了 70%的病例。仅 HPV16 就导致了几乎 90%的人乳头瘤病毒阳性口咽癌。

图 5。HPV18 和 HPV16 与癌症。图片作者。

相比之下,非典和新型冠状病毒都与一种疾病有关。SARS 导致了中国 2002 年至 2004 年的 SARS 疫情,到目前为止还没有抗病毒疗法。对于新冠肺炎,KEGG 列出了药物 remdesivir。Siemieniuk 等人。进行了一项活体系统评价(在此处阅读),并声明 remdesivir 可能会缩短 COVID 症状。

图 6。非典和新型冠状病毒以及它们引发的疾病。图片作者。

抗疟药硫酸羟氯喹被视为治疗 KEGG 新冠肺炎的药物。

图 7。硫酸羟氯喹的细节。图片作者。

这与 Siemieniuk 研究中的一个结论相呼应:

羟氯喹可能不会降低死亡率或机械通气,而且似乎不太可能有任何其他好处(对新冠肺炎而言)。

5.使用图形算法发现社区和高度连接的节点

图 2 中的拓扑。有一些有趣的特点。许多小网络围绕着一大群互连的点。确定这些集群并确定一些连接最紧密的节点,即所谓的枢纽,将是一件有趣的事情。幸运的是,Neo4j 为我们提供了一个非常强大的插件:图形数据科学(gds)来处理这些任务。

首先转到 Neo4j 桌面中的项目详细信息选项卡并安装插件:

图 8。安装图形数据科学(gds)插件。作者图片。

在 Neo4j 中,图形算法在图形投影上运行。首先,我们将所有的节点和边放入一个名为“disease-graph”的带 Cypher 的命名图投影中。

5.1 利用 Louvain 算法形成疾病社区

现在我们可以对它运行卢万算法来识别集群或社区。该算法将紧密连接的节点压缩成更大的节点,并且重复直到不可能压缩。首先,我们询问可以形成多少个社区:

在 4170 个节点中,Louvian 算法可以创建 2120 个社区。我用不同的参数运行这个查询,比如“maxIterations”和“tolerance ”,但是看不到任何大的差异。

我们可以查看最大的社区并查看其成员:

它返回:

现在,我们可以通过以下方式检查社区“3421”中的成员:

成员包括:

浏览列表后,很明显这个社区主要包含与肿瘤相关的项目。已知会增加癌症风险的病原体,如乙型和丁型肝炎病毒,也在这个社区。

您可以进一步分析社区。我自己的社区分析表明,大型集群中的疾病是那些受到最多研究关注的疾病,它们通过常见病原体或通用药物密切相关。相比之下,许多孤立的“岛屿”是罕见的疾病,如克里斯蒂安森综合征齐默尔曼-拉班德综合征。值得注意的是,非典和新冠肺炎是两个孤立的“孤岛”(图 2。)尽管它们引起了轰动性的流行病。信息也很清楚:相对而言,我们对新冠肺炎仍然知之甚少。

5.2 用 PageRank 发现连接最多的节点

最后,我们可以使用 PageRank 来检查图中哪些节点连接良好:

最佳结果是:

没有药物或病原体节点进入前十二个最重要的列表,所有都是疾病。这一方面可以解释为,在我们的数据模型中,每个病原体和药物都保证与一个疾病节点相关联。所以疾病节点从一开始就是默认的中心。另一方面,这个列表包含了现代世界中一些最常见的人类痛苦,并且已经开发了许多药物来解决它们。事实上,通过更复杂的查询,我们可以计算出与这些主要疾病相关的药物:

结果显示,有 103 种药物被指定用于治疗高血压,位于列表的顶部节点。牛皮癣是这个列表中的最后一种,影响了 2-4%的西方人口,但在数据库中有 34 种药物治疗牛皮癣。然而,药物数量排名并不完全遵循 PageRank。例如,有 48 种药物用于治疗类风湿性关节炎,这比那些排名较高的疾病如乳腺癌、重性抑郁症和血吸虫病的药物还多。

结论

该项目是展示 Neo4j 在生物医学研究中的力量的又一个例子。一旦数据被导入 Neo4j,我们就可以快速获得大量关于疾病的数据和细节。如果在关系数据库中完成,我们将需要三个表来建模数据,而不是 Neo4j 中的一个模式。此外,Cypher 查询的表述非常简单,读者无需任何“连接”即可理解。最后,在图形数据库中,我们可以对数据运行图形算法,并轻松发现一些有趣的新见解。

这并不是说我们应该放弃其他数据库。当我们的数据包含大量连接时,图形数据库是一个很好的选择,例如我们之前的项目和这里的 KEGG Disease 项目。在简单计数的情况下,如价格表,我们应该使用关系数据库。对于文档,要考虑 MongoDB 等文档数据库。时间序列也有自己的数据库,如 Amazon Timestream 或 InfluxDB。

这个项目也给我们上了关于疾病和健康的宝贵一课。其中之一是关于我们的免疫系统。在目前的新冠肺炎疫情期间,我们更有可能购买那些“增强你的免疫系统”的广告。但是我们的免疫系统非常脆弱,我们绝不希望看到它超速运转。相反,上面的分析表明,一些最通用和广泛使用的药物实际上是免疫抑制剂,即抑制免疫系统的药物。而约翰·霍普金斯大学估计 3%的美国人口患有自身免疫性疾病,也就是一千万人左右!这让我想起马特·里奇特尔在中的一段优雅的辩护 当听到有希望增强免疫系统的广告时,安东尼·福奇博士说

“这几乎让我窃笑。首先,这是假设你的免疫系统需要增强,而这很可能并不需要。如果你成功地增强了你的免疫系统,你可能会让它做坏事。”

这个项目只涵盖了 KEGG 的一小部分:疾病、药物和病原体。我只是想知道,如果我们利用 KEGG 中存储的所有信息,我们可以获得什么样的新见解。因此,我鼓励您使用图形数据库来进一步探索这个数据宝库,并向我展示您在这一过程中发现的东西。

这篇文章是我自己翻译成中文的:https://blog.csdn.net/dgg32/article/details/119081851

https://dgg32.medium.com/membership

NER 在 Reddit 上提取股票提及

原文:https://towardsdatascience.com/ner-for-extracting-stock-mentions-on-reddit-aa604e577be?source=collection_archive---------17-----------------------

如何将命名实体识别用于🚀🚀🚀💎🤲

照片由 Ishant MishraUnsplash 拍摄

eddit 一直处于金融世界最大运动之一的中心,尽管这看起来不太可能是这种运动的源头,但事后看来这并不奇怪。

Reddit 上以交易为中心的子页面是大量关于市场动态的讨论的背景,因此挖掘这个庞大的数据源是合乎逻辑的。

当构建这样的数据提取工具时,我们需要做的第一件事就是确定我们提取的数据实际上是什么——为此我们将使用命名实体识别(NER)。

我们将确定正在讨论哪些组织。简而言之,我们将涵盖:

**> Reddit Data****> NER**
  - SpaCy**> Identifying Entities**
  - DisplaCy Visualization
  - Extracting Entities**> Processing The Dataset**
  - Extracting Entities
  - Pruning Entities**> Building a Frequency Table**

点击此处观看视频教程:

Reddit 数据

首先,我们需要从 Reddit 提取信息——为此,我们有两个选择。我们可以使用requests库直接与 Reddit API 接口,或者使用 PRAW 库,它在访问 Reddit API 时增加了一个额外的抽象层。

在这个项目中,我们将通过requests直接与 Reddit API 接口——但是您可以随意使用您喜欢的任何方法。你可以在这里找到通过requests连接的指南:

我们将使用这个脚本提取 Reddit 数据。你可以在这里找到我们使用的数据(如果你想跳过这一部分)。

使用这个,我们可以很容易地切换我们正在查看的子街道——但是我们将关注/r/investing

NER

一旦我们有了我们的数据,我们需要处理它,并提取组织名称,以便任何进一步的分析是自动分类和结果分配到正确的股票。

在每个子编辑中,组织以各种格式被提及。通常我们会发现两种格式:

  • 组织名称,如特斯拉/特斯拉汽车公司
  • 股票代号,如 TSLA,tsla,或$TSLA

我们还需要能够区分 ticker 和其他缩写/俚语——其中一些是不清楚的,比如 AI (AI 既可以指人工智能,也可以指 C3.ai 的 ticker 符号)。

因此,我们需要一个合理的 NER 过程来准确地分类我们的数据。

空间

spaCy 库是 Python 中最受欢迎的自然语言处理包之一——它附带了一套优秀的 NER 工具,包括 displaCy 中一些非常酷的可视化工具——我们将很快探索这些工具。

要安装 spaCy,打开 CMD/Bash/etc 并键入pip install spacy

安装后,我们可以通过在命令行中输入python -m spacy download <MODEL-NAME>来下载任何 SpaCy 模型。下载后,我们可以用 Python 代码初始化模型,如下所示:

nlp = spacy.load('en_core_web_sm')

空间模型名称分为四部分,[lang]_[type]_[genre]_[size]:

  • Lang —模特的语言(例如en为英语)。
  • 类型 —模型类型,core是通用类型,支持词汇、语法、实体和词向量。
  • 流派 —文本模型被训练的类型(如webnews)。
  • 尺寸 —模型包装尺寸— smmdlg

在我们的例子中,我们将使用一个英国模型,它需要支持 NER(实体)——所以它将是一个通用的core模型。Reddit 线程与web类型保持一致,我们将坚持使用小型号sm

所有这些给了我们模型en_core_web_sm

识别实体

我们将从 ARK 上 /r/investing 中的一个线程开始:

Given the recent downturn in stocks especially in tech which is likely to persist as yields keep going up, I thought it would be prudent to share the risks of investing in ARK ETFs, written up very nicely by [The Bear Cave](https://...). The risks comes primarily from ARK's illiquid and very large holdings in small cap companies. ARK is forced to sell its holdings whenever its liquid ETF gets hit with outflows as is especially the case in market downturns. This could force very painful liquidations at unfavorable prices and the ensuing crash goes into a positive feedback loop leading into a death spiral enticing even more outflows and predatory shorts.

从这里我们想提取出 ARK 作为这个提取的唯一相关组织。为此,我们将返回到我们初始化的nlp模型:

尽管看起来不像,doc实际上包含了我们的 NER 标记的文本。我们只需要进入它。

我们将通过两种方式进行研究,一种是显示可视化,另一种是通过ents属性进行编程。

显示可视化

DisplaCy 允许我们方便地可视化我们的文本,突出显示空间标识的实体,如下所示:

这种方法对于快速可视化我们的模型的结果非常有用——很明显,模型将 ETF 识别为一个组织(我们可能希望删除它),并将文章链接 The Bear Cave 识别为WORK_OF_ART

对我来说,WORK_OF_ART标签是什么意思并不清楚(也许是毕加索?).幸运的是,我们可以使用spacy.explain(<TAG>)得到一个标签描述:

从这个描述来看,这篇文章——虽然不完全是一本书——似乎很有意义。

提取实体

用 displaCy 可视化很棒,但我们还需要一种更程序化的方式来提取组织实体。这就是ents的用武之地。

docents属性包含一个实体列表和它们各自的标签——然后我们可以循环查看我们的数据。

这里我们通过entity.label_访问标签类型,通过entity.text访问各自的文本。我们将只过滤组织标签。

此外,我们在这段文本中标识了 ARK 三次——理想情况下,我们只想返回每个唯一的组织一次,这将通过将输出列表转换为一个集合来实现。

现在我们有了,我们已经从文本中提取了我们的组织实体。现在,我们需要做的就是重构我们到目前为止所做的,并将其应用到我们提取的所有数据中。

处理数据集

我们的数据集看起来像这样:

我们/r/投资数据集的负责人

我们关注的是 selftext 列,它包含了每篇文章的文本内容到 /r/investing

提取实体

为了处理它并输出我们的组织实体,我们所做的就是将我们已经构建的代码重写到一个函数中,该函数接受一个单独的 selftext 字符串作为输入,并返回一个已识别实体的列表:

我们将这些确定的实体添加到我们的数据框架中的一个新列,称为组织

我们的/r/投资数据框架,右边是新的组织

修剪实体

同样,我们引入了一些我们不想包含的实体。为了避免这些,我们在我们的get_orgs函数中的 if 语句中添加了一个附加条件:

现在,如果组织包含在BLACKLIST中,它将被忽略——这可以在我们的数据框架中看到:

我们的/r/investing 数据框架头,现在我们已经包括了一个黑名单‘ETF’和‘Treasury’不再包括在前两行

建立频率表

现在我们所有的数据都准备好了,我们可以继续建立一个频率表。为此,我们将把所有的组织标签提取到一个列表中,然后使用collections创建一个Counter对象(频率表)。

现在我们已经将频率表包装在Counter中。这个对象的结构很像 Python 字典,其中我们将标签作为键,将它们的频率作为值

然而,与 Python 字典不同,Counter附带了几个有用的方法——特别是most_common(n)方法——它为我们返回了 n 个最常提到的组织!

most_common(n) 方法返回前 n 个最高计数

现在我们有了,所有最常被提及的来自 /r/investing 的组织!

这就是本文的全部内容,我们已经介绍了很多内容,包括:

  • 快速浏览一下从 Reddit API 中提取的数据(如果需要,这里有更多的)。
  • 空间模型——如何下载并理解它们的用途。
  • 用我们的空间模型进行实体提取。
  • 使用 displaCy 可视化 NER。
  • 使其适用于完整的数据集。
  • 使用collections建立一个提及频率表。

我希望你喜欢这篇文章!如果你有任何问题,请通过 Twitter 或在下面的评论中告诉我。如果你想要更多这样的内容,我也会在 YouTube 上发布。

感谢阅读!

参考

空间,可视化工具—显示文档

🤖带变压器的 NLP 课程

完整剧本

*所有图片均由作者提供,除非另有说明

NER 与变形金刚和太空

原文:https://towardsdatascience.com/ner-with-transformers-and-spacy-b3240bc65eb4?source=collection_archive---------9-----------------------

使用 roBERTa 提取过强的实体

作者图片

N 命名实体识别(NER)包括从文本中提取“实体”——我们的意思在句子中给出了:

"今年 1 月,苹果公司的股价达到了 143 美元的历史新高。"

我们可能想要提取关键的信息片段——或“实体”——并对这些实体进行分类。像这样:

苹果—组织

143 美元——货币价值

今年 1 月—日期

对于我们人类来说,这很容易。但是,我们如何教会一台机器区分一个史密斯奶奶苹果和我们在纳斯达克交易的苹果呢?

(不,我们不能指望‘A’大写……)

这就是 NER 的用武之地——使用 NER,我们可以提取像苹果这样的关键词,并确定它实际上是一个组织——而不是一种水果。

Python 中 NER 的首选是 spaCy 库——这真的很神奇。例如,我在编写任何代码之前编写了上面的 NER 示例,spaCy 完美地匹配了该示例:

变压器 NER 模型的输出。

很酷的东西…但是,这只是香草空间——如果我们加入变形金刚会怎么样?

空间变压器

变形金刚是自 NLP 中的面包片以来最热门的东西。自 2017-18 年推出以来,它们已经主导了 NLP 基准,成为事实上的语言标准(抱歉,LSTM)。

SpaCy 在 2019 年推出了spacy-transformers库[1]。它将 spaCy 连接到 HuggingFace 的变形金刚库——允许我们像往常一样使用 NER——但由尖端的变形金刚模型驱动。

NER 与变形金刚和空间的视频漫游。

装置

我们首先安装spacy-transformers,使用:

pip install spacy[transformers]

如果你使用 CUDA,用nvcc --version检查你的版本,把 CUDA 版本添加到安装中——我有 CUDA 11.1,所以我的安装命令是:

pip install spacy[transformers,cuda111]

初始化空间转换器

现在我们已经安装了spacy-transformers,我们可以像通常使用 spaCy 模型一样开始使用 transformer 模型。

这里唯一的例外是我们下载并初始化一个 spaCy transformer 模型——而不是通常的模型。

我们下载了 roBERTa-base 模型,其中包含:

python -m spacy download en_core_web_trf

然后用 Python 初始化它:

对于以前使用过 spaCy 的人来说,这应该看起来很熟悉。

NER

我们现在准备用我们的 transformer 模型处理一些文本,并开始提取实体。同样,这里与通常的空间语法没有区别:

变压器 NER 模型的输出。

变形金刚 v 传统空间

很好,但是与传统的空间模型相比,这种模型表现如何?我们将使用en_core_web_lg模型,并比较来自r/投资 子编辑的一些帖子。

传统 en_core_web_lg 型号(左),变形金刚 en_core_web_trf 型号(右)。

在这里,我们可以看到这两个模型之间没有任何差异——我们应该期待有相当数量的样本,因为传统模型en_core_web_lg仍然是一个非常高性能的模型。

但是,让我们从这里尝试一个稍微长一点、更复杂的例子:

Fastly released its Q1-21 performance on Thursday, after which the stock price dropped a whopping 27%. The company generated revenues of $84.9 million (35% YoY) vs. $85.1 million market consensus. Net loss per share was $0.12 vs. an expected $0.11.These are not big misses but make the company one of the few high-growth cloud players that underperformed market expectations.However, the company also lowered its guidance for Q2: Fastly forecasts revenues of $84 - $87 million and a net loss of $0.16 - $0.19 per share, compared to the market consensus of $92 million in revenue and a net loss of $0.08 per share, thereby disappointing investors.Lastly, Adriel Lares will step down as CFO of the company after 5 years.

传统 en_core_web_lg 型号(左),变形金刚 en_core_web_trf 型号(右)。

现在我们看到了不同之处:

除了在百分比标签中包含“巨大的”——transformer 模型明显优于传统模型。

关于在空间中使用转换器进行命名实体识别的文章到此结束!你可以在这里找到完整的笔记本。

我希望你喜欢这篇文章!如果你有任何问题,请通过 Twitter 或在下面的评论中告诉我。如果你想要更多这样的内容,我也会在 YouTube 上发布。

感谢阅读!

参考

[1] M. Honnibal & I. Montani, spaCy 遇上变形金刚:微调伯特、XLNet 和 GPT-2 (2019),爆炸 AI

🤖带变压器的 NLP 课程

如果您有兴趣了解更多关于使用 NER 空间库的信息,我会在这里做更深入的介绍:

*所有图片均由作者提供,除非另有说明

当图形变得可微时会发生什么

原文:https://towardsdatascience.com/nerf-and-what-happens-when-graphics-becomes-differentiable-88a617561b5d?source=collection_archive---------10-----------------------

思想和理论

深度学习和计算机图形之间的浪漫是如何开始的,以及走向照片现实主义的未来之路

渲染,任何图形系统的关键部分,就是让一个电脑化的三维世界在我们的二维电脑屏幕上反映出来的东西,就好像世界上的一个角色从口袋里拿出相机,拍下了他们所看到的东西。

在过去的一年(2020 年),我们已经学会了如何使渲染过程变得可区分,并将其变成一个深度学习模块。这激发了想象力,因为深度学习的格言是:“如果它是可微分的,我们可以通过它学习”。事实上,许多深度学习突破都来自于试图软化零和一之间的差距,将离散变成连续,将 argmax 变成 softmax 。如果我们知道如何有区别地从 3D 到 2D,这意味着我们也可以使用深度学习和反向传播从 2D 回到 3D。

假设我手里拿着一张(2D 的)猫坐在窗户里的照片(在现实世界中拍摄的),并且可以访问一个可微分渲染器,一个将三维(计算机化)世界的表示转换为二维图像的系统。现在,如果我让系统渲染一个 2D 图像,我会得到一些看起来一点也不像猫的随机图像,因为它渲染的 3d 世界只是一些随机初始化的计算机化环境。

但是因为渲染器是可微分的,这意味着结果图像中的每个像素都是计算机化 3d 世界的可微分函数。这实质上意味着我们的深度学习框架保持了从渲染图像回到 3D 世界表示的链接。因此,我们可以问:“我们如何改变我们当前的 3D 世界表示,以便下次我们从相同的角度渲染它时,得到的图像看起来更像照片?”(数学上,我们取照片像素和图像像素之间的差的梯度)。

如果我们相应地改变我们的 3D 世界表示,并一遍又一遍地这样做,最终我们的可区分渲染器将渲染一个看起来非常类似于原始猫照片的图像。

在那一点上,我们可以把注意力转向它所融合的计算机化的 3D 世界。我们能从中得到什么?它在 3D 窗口中有 3D 猫对象吗?如果我们从不同的拍摄角度(获得不同的图像)渲染同一个 3D 计算机化世界,它看起来还会像一只猫吗?好吧,除非我们的 3D 表现已经有了一些关于 3D 猫长什么样的预定义概念,否则很可能没有。仅仅使用一张照片,从一个角度来看,没有足够的信息来了解猫从不同的角度看起来会是什么样子。据我们所知,我们的 3D 世界可能会汇聚成一只印在画布上的扁*猫,而画布就放在摄像机前面。

左边中间:对世界的两种可能解释,右边的照片是在那里拍摄的。资料来源:联合国人类住区规划署

为了让我们对 3d 世界的描述汇聚成有用的东西,我们需要更多的照片,从更多的角度拍摄。

NeRF:每个场景都是从几十个不同的角度拍摄的,以找到它的三维表示。资料来源:NeRF 论文[1]。

这正是加州大学伯克利分校(Ren Ng 的实验室)的一组研究人员在一个名为 NeRF(神经辐射场的缩写)的项目中所做的。他们一次从不少于 40 个不同的角度拍摄了现实世界中的一个静态场景(并获得了 40 幅图像),目标是获得该场景的三维计算机化表示,稍后可以从任何角度正确渲染。他们的结果令人震惊。

由 NeRF 处理的场景。所有帧都是通过从不同角度渲染相同的 3D 表示而完全合成的。注意地板和玻璃上的反射。来源:NeRF github 页面(点击查看附加示例)。

使用同一物体或场景的多个视图来获得其 3D 表示的想法并不新鲜(这被称为视图合成)。然而,以前的方法都无法生成逼真度如此之高的 3D 结构,以至于从视点渲染的图像与真实照片无法区分。

建造 NeRF 的人能够搞定它。他们成功的原因是他们结合了强大的可区分渲染器和强大但不典型的 3D 世界表示。这个强大的 3D 世界表现是一个神经网络。甚至不是那些花哨的神经网络之一,而是一个多层感知器,就像过去的好时光一样,9 个完全连接的层。

NeRF 中心的神经网络是如何表现整个 3D 世界的?答案:它对它的 3D 空间进行分类!它的输入是空间中一个点的任意 3 个坐标(x,y,z)(以及相机视点),它的输出是空间中该点的颜色 (r,g,b) 和材质的不透明度(α)。

NeRF 中心的神经网络。

这就是了。五个号码进,四个号码出。一旦神经网络在场景中得到充分训练,我们就可以在空间的任何一点上查询它,并探测环境。这很好,但是如果我们想知道更多关于场景的实际内容,我们必须努力探测网络。这个神经网络没有明确地告诉我们场景中对象的数量、它们的类别或它们的边界。这是一种更“原子化”、更低级的看待世界的方式。

从计算机图形研究者的角度来看,这是激进的。它们用于在场景中以自己的数据结构(称为“网格”)来表示每个对象。它们用于处理表面、获取深度图和跟踪光源发出的光线。这里什么都没有。

相反,我们有一些更类似于医学图像中用于表示体积的体素网格,如 MRI 或 CT 扫描,除了:

  • MRI/CT 体积具有固定的分辨率,使用离散的体素,而我们可以在任何分辨率下向 NeRF 网络询问任何分数(x,y,z)点。
  • 与 NeRF 多层感知器的相对紧凑的 256 x 256 x 9 权重(粗略地)相比,MRI/CT 体积占据了大量的空间(考虑 512 x 512 x 512 体素)。

因此,NeRF 的神经网络不是表现不同对象的最自然的方式,但它绝对是渲染它们的合适方式,也许这就是为什么结果图像如此逼真。

NeRF 渲染器是如何工作的?

你可以想象我们正在渲染的图像就像一个屏幕放在相机前面,垂直于相机的视角。为了确定该图像中任何像素的颜色,我们从相机发出一条光线,穿过像素在屏幕上的位置并向前。如果光线击中任何表面,像素的颜色将被确定为表面在撞击点的颜色。如果表面是不透明的(𝛂=1),我们就到此为止。但如果没有,我们必须继续跟踪光线,看看它碰到了什么其他表面,因为它们的颜色也会影响像素的颜色。

单像素渲染。图像被渲染为好像放置在垂直于摄像机角度的屏幕上。光线通过像素离开相机并继续。沿着射线采样几个点。像素应该在光线和苹果表面的第一个交叉点得到颜色。来源:David Novotny,pytorch3d 教程2

在该渲染器的不可微分版本中,只有最接*的不透明表面决定了像素的颜色。但是如果我们想使它可微分,我们需要再次将 argmax 变成 softmax 。换句话说,所有被光线击中的表面都需要在计算中发挥一些作用,即使是那些被最*的表面遮挡的表面(仍然会产生最大的影响)。这是维持 3D 世界所有区域和最终图像像素之间必要联系的关键。

更具体地说,为了计算特定像素的颜色,我们沿着上述光线采样 100 个点,并向我们的神经网络请求颜色 (r,g,b) 和每个点的不透明度(𝛂)。像素的最终颜色是所有所有采样点所有颜色的线性组合(加权*均),甚至是那些在半空中的点(𝛂应该接* 0),或者那些在相机“隐藏”的表面上的点(𝛂应该接* 1)。分配给光线上第点(远离相机)的权重将得到权重 T_i 𝛂_i,其中标量𝛂_i

由网络直接计算,并且

取决于前面点的不透明度值。您可以看到最*的曲面如何获得最主要的权重(我们将权重归一化,因此它们的总和为 1)。

前进的道路

我觉得这很令人兴奋。这不再是一个预测物理的神经网络。这个是插在 PyTorch 引擎内神经网络顶部的物理(或光学)。我们现在有了一个现实世界的可微分模拟(利用计算机图形的力量)和一个它的神经表示(利用深度学习的力量)。难怪结果看起来如此逼真。

深度学习和图形之间的这场罗曼史才刚刚开始。它将缩小计算机模拟和现实世界之间的差距。如果你有一个 VR 头戴设备,想象一下看电影,你不只是坐在一个静态的视角,而是可以在场景中移动,甚至可以与之互动。

最新的创新将允许我们将现实世界中的物体和环境导入虚拟世界,减少对艺术家制作的资产的依赖。【在这种情况下,我推荐观看Nvidia 的 Sanja Fidler 关于创建三维内容的讲座,该讲座来自上一期 NeurIPS 关于该主题的研讨会。]

还有我之前提到的关于 NeRF 网络局限性的那些东西?这对于计算机图形学来说太低级了?这将会改变。我们将从这个 3D 世界表示中提取语义元素,这将使我们能够理解和控制它,就像我们对经典网格表示所做的那样,但保留了照片真实感的新标准。

在下一篇文章中,我将解释我们计划如何去做。

延伸阅读

[1]米尔登霍尔等人。艾尔。 NeRF:将场景表示为用于视图合成的神经辐射场。 ECCV 2020 [ 链接

2脸书的 PyTorch3D 图书馆。[ 链接 ] [ 隐函数与 NeRF][[NeRF 专用 jupyter 笔记本](http://dedicated NeRF notebook.) ]

[3]桑娅·菲德勒。用于 3D 内容创作的人工智能。NeurIPS 2020 [ 链接

4弗拉德伦·科尔顿:走向摄影现实主义[ 视频

基于机器学习的多类分类中的嵌套类不*衡问题

原文:https://towardsdatascience.com/nested-class-imbalance-problem-within-machine-learning-based-multi-class-classification-a4b2c43ba832?source=collection_archive---------32-----------------------

揭示现实生活中非人类为中心的 ML 数据

于韦斯屈莱的 Paijä nne 湖-信贷:艾哈迈德·马斯里

放弃

你可能会觉得这篇文章的内容可笑到你可能会笑死的地步。为此,要受到警告,记得在临死前给出建设性的反馈;)

介绍

在基于机器学习(ML)的分类应用中,类不*衡是一个众所周知的问题。当不同类别之间的样本数量不*衡时,就会出现这样的问题,并且所得到的 ML 模型将偏向于具有频繁样本的一个或多个类别,而不是具有不频繁样本的其他类别。例如,训练 ML 模型来从数百万健康病例(类别 2)中检测几个癌症病例(类别 1)将导致与类别 1 相比偏向类别 2 的模型,如果两个类别之间样本数量的不*衡没有解决的话。

本文不详细讨论类不*衡问题本身,因为它是文献中定义明确的问题,不熟悉的读者可以参考那些精选的参考文献以获得更多信息1[3]。除此之外,本文的目标是揭示现实生活中非以人为中心的 ML 数据案例,其中存在一个隐藏的嵌套类不*衡问题,据作者所知,这个问题以前还没有解决。

为了便于理解这个问题,让我们把它放在一个示例场景中。

系统场景

图 1:低轨卫星通信系统场景——鸣谢:艾哈迈德·马斯里

假设我们有几个移动终端(mt)由低地球轨道(LEO)卫星系统服务,如图 1 所示。数百到数千颗 LEO 卫星正在/将要在不同高度绕地球运行,并为被称为 5G NTN 的 5G 移动网络提供类似的服务4。在这种情况下,移动终端从几个可见的低地球轨道卫星接收无线电信号。每个 MT 都试图保持连接,并从其最佳卫星获取数据。这里的最佳并不意味着最*,因为通常大气条件和在比目标 LEO 系统更低的高度运行的其他 LEO 卫星可能会阻碍与 MT 的无线电通信。因此,MT 在失去连接之前不容易决定应该连接到哪个卫星以及何时更换(切换)新的卫星。由于这一点,基于时间序列 ML 的分类解决方案可用于对 MT 上从所有可见 LEO 卫星收集的接收信号帧进行分类,以在正确的时间预测最佳卫星,如图 2 所示。

图 2:MT 从不同可见卫星接收的样本作为神经网络的输入,用于训练多类分类 ML 模型——鸣谢:Ahmed Masri

训练单个监督 ML 模型来处理该任务需要在每个 MT 处收集来自所有可见卫星的接收信号,如图 2 所示。显然,不是所有的卫星都能被 MTs 看到,这取决于它们当前的位置和条件。为此,来自每个卫星的信号的数量和强度在 MT 处将会变化,并且一些 MT 将具有来自“X”卫星的更多信号样本,而其他 MT 可能具有来自“Y”卫星的更多样本。当然,在训练分类 ML 模型之前,应该对收集的数据进行处理和标记。

避免了这种示例场景的所有技术和特定于技术的细节,以保持对目标想法本身的关注,而不会迷失在枝节细节中。现在,随着场景的简单定义,让我们强调嵌套类不*衡问题。

嵌套类不*衡问题定义

多级失衡—1 级

MTs 将从不同的卫星接收不同数量的信号样本的事实可能导致众所周知的多类不*衡问题,如果一个卫星比其他卫星具有更多的样本,并且作为结果,我们的 ML 模型将开始优选并且预测这个流行的卫星为与其他不太流行的卫星相比最好的卫星。

隐藏的二进制—类别不*衡—级别 2

独立地在 MT 处再次研究从每个卫星收集的样本,我们可以看到样本本身可以被二进制分类成两类:当样本值足够好时的停留类,以及当样本值变得衰减并且失去与当前服务卫星的连接的风险变得更高时的切换类,如下图 3 所示:

图 3:MT 处服务卫星样本的放大视图——作者:Ahmed Masri

具有类别 1(停留)的样本的数量将远远高于具有类别 2(切换)的样本的数量,因为一旦类别 2 样本出现,则该模型将预测 MT 很快切换到另一个服务卫星,此时将再次收集更多类别 1 类型的样本。停留样本和切换样本的数量之间的这种隐藏的二元类不*衡将对我们的多类分类 ML 模型做出正确预测的能力产生间接的显著影响,如果它没有被正确解决的话。

由于目标是单个多类分类 ML 模型,该模型不仅能够检测最佳卫星,而且能够在正确的时间检测它,因此很容易发现第 1 级的多类不*衡问题,但是另一方面,如果没有很好地调查,第 2 级的二元类不*衡可能会隐藏起来。鉴于此,在本文中,我们揭示了这种嵌套的不*衡问题,如果您的多类分类模型不仅要预测正确的类,还要在正确的时间预测它,那么注意,您可能有一个嵌套的类不*衡问题。

拟议解决方案

解决方案建议的一个提议是从不同卫星收集相等的样本以解决多类不*衡问题,同时仅在切换区周围收集样本以解决二元嵌套不*衡问题。然而,这可能会引起一些关注,例如,忽略非切换区域是否会影响模型的多类分类精度?模型会不会丢失一些重要的模式?如果是,那么处理嵌套二进制不*衡问题的另一个建议解决方案是通过从所有区域(切换/非切换)收集样本,以便我们不会错过多类分类的任何重要模式,但同时,我们增加少数切换样本的样本权重,以从 ML 模型的角度给予它们更多的关注。

结论

在一个示例场景中强调并讨论了嵌套类不*衡问题。我们揭示了这种嵌套的不*衡问题,如果多类分类模型不仅要预测正确的类,还要在正确的时间预测它,那么我们可能会遇到嵌套的类不*衡问题。此外,还提出了一些解决方案,并进行了简要讨论。

参考

[1]凌春生,盛诉我国阶级不*衡问题。参见:萨姆特·c,韦伯主编的《机器学习百科全书》,2011 年,斯普林格,波士顿,马萨诸塞州。https://doi.org/10.1007/978-0-387-30164-8_110

2 Johnson,J.M .,Khoshgoftaar,T.M .关于深度学习与班级失衡的调查。j 大数据 6,27 (2019)。https://doi.org/10.1186/s40537-019-0192-5

[3] Patel H,Singh Rajput D,Thippa Reddy G,Iwendi C,Kashif Bashir A,Jo O .无线传感器网络不*衡数据分类综述.2020 年,国际分布式传感器网络杂志。doi:10.1177/1550147720916404

4 3GPP,“TR 38.811:技术规范组无线接入网;支持非地面网络的新无线电(NR)研究,“2009–2020,第 15 版,V15.4.0。”

Spark 3.1 中的嵌套数据类型

原文:https://towardsdatascience.com/nested-data-types-in-spark-3-1-663e5ed2f2aa?source=collection_archive---------3-----------------------

在 Spark SQL 中使用结构

埃利斯·陈嘉炜在 Unsplash 上拍摄的照片

在之前关于高阶函数的文章中,我们描述了三种复杂的数据类型:数组、映射和结构,并特别关注了数组。在这篇后续文章中,我们将研究 structs,并了解 Spark 3.1.1 版本中发布的用于转换嵌套数据的两个重要函数。对于代码,我们将使用 Python API。

结构体

StructType 是一种非常重要的数据类型,允许表示嵌套的层次数据。它可用于将一些字段组合在一起。 StructType 的每个元素被称为 StructField ,它有一个名称,也有一个类型。元素通常也称为字段或子字段,它们通过名称来访问。 StructType 也用于表示整个数据帧的模式。让我们看一个简单的例子

from pyspark.sql.types import *my_schema = StructType([
    StructField('id', LongType()),
    StructField('country', StructType([
        StructField('name', StringType()),
        StructField('capital', StringType())
    ])),
    StructField('currency', StringType())
])l = [
        (1, {'name': 'Italy', 'capital': 'Rome'}, 'euro'),
        (2, {'name': 'France', 'capital': 'Paris'}, 'euro'),
        (3, {'name': 'Japan', 'capital': 'Tokyo'}, 'yen')
    ]df = spark.createDataFrame(l, schema=my_schema)df.printSchema()root
 |-- id: long (nullable = true)
 |-- country: struct (nullable = true)
 |    |-- name: string (nullable = true)
 |    |-- capital: string (nullable = true)
 |-- currency: string (nullable = true)df.show()
+---+---------------+--------+
| id|        country|currency|
+---+---------------+--------+
|  1|  {Italy, Rome}|    euro|
|  2|{France, Paris}|    euro|
|  3| {Japan, Tokyo}|     yen|
+---+---------------+--------+

创建的 DataFrame 有一个结构 country ,它有两个子字段: namecapital

创建结构

至少有四种基本方法可以在数据框中创建一个结构类型。第一种方法我们已经在上面看到过——从本地集合创建 DataFrame。第二种也是最常见的方式是从支持复杂数据结构的数据源读取数据,比如 JSON 或 Parquet。接下来,有一些函数将创建一个结构作为结果。这种转换的一个特殊例子是通过 窗口 进行分组,这将产生一个具有两个子字段 startend 的结构,正如您在这里看到的:

l = [(1, 10, '2021-01-01'), (2, 20, '2021-01-02')]dx = spark.createDataFrame(l, ['id', 'price', 'date'])(
    dx
    .groupBy(window('date', '1 day'))
    .agg(sum('price').alias('daily_price'))
).printSchema()root
 |-- window: struct (nullable = false)
 |    |-- start: timestamp (nullable = true)
 |    |-- end: timestamp (nullable = true)
 |-- daily_price: long (nullable = true)

第四种创建 struct 的方法是使用函数【struct()。该函数将从作为参数传递的其他列创建一个 StructType ,并且 StructFields 将与原始列具有相同的名称,除非我们使用 alias() 重命名它们:

df.withColumn('my_struct', struct('id', 'currency')).printSchema()root
 |-- id: long (nullable = true)
 |-- country: struct (nullable = true)
 |    |-- name: string (nullable = true)
 |    |-- capital: string (nullable = true)
 |-- currency: string (nullable = true)
 |-- my_struct: struct (nullable = false)
 |    |-- id: long (nullable = true)
 |    |-- currency: string (nullable = true)

这里,我们创建了一个列 my_struct ,它有两个子字段,这两个子字段是从数据帧中的两个列派生出来的。

访问元素

正如我们上面提到的,结构的子字段是通过名称来访问的,这是通过点符号来完成的:

df.select('country.capital').show()+-------+
|capital|
+-------+
|   Rome|
|  Paris|
|  Tokyo|
+-------+

可能不明显的是,这也适用于结构数组。假设我们有一个数组国家,数组的每个元素都是一个结构体。如果我们只想访问每个结构的大写子字段,我们可以用完全相同的方法,得到的列将是一个包含所有大写的数组:

my_new_schema = StructType([
    StructField('id', LongType()),
    StructField('countries', ArrayType(StructType([
        StructField('name', StringType()),
        StructField('capital', StringType())
    ])))
])l = [(1, [
        {'name': 'Italy', 'capital': 'Rome'},
        {'name': 'Spain', 'capital': 'Madrid'}
    ])
]

dz = spark.createDataFrame(l, schema=my_new_schema)# we have array of structs:
dz.show(truncate=False)+---+--------------------------------+
|id |countries                       |
+---+--------------------------------+
|1  |[{Italy, Rome}, {Spain, Madrid}]|
+---+--------------------------------+# access all capitals:
dz.select('countries.capital').show(truncate=False)+--------------+
|capital       |
+--------------+
|[Rome, Madrid]|
+--------------+

关于访问数组内部嵌套结构中元素的另一个具体例子,参见这个堆栈溢出问题。

添加新元素

从 Spark 3.1 开始,支持使用函数 withField() 向现有结构添加新的子字段。让我们看看我们的例子,其中我们将列货币添加到结构国家:

(
  df
  .withColumn(
    'country', 
    col('country').withField('currency', col('currency'))
  )
).show(truncate=False)+---+---------------------+--------+
|id |country              |currency|
+---+---------------------+--------+
|1  |{Italy, Rome, euro}  |euro    |
|2  |{France, Paris, euro}|euro    |
|3  |{Japan, Tokyo, yen}  |yen     |
+---+---------------------+--------+

在 Spark 3.1 之前,情况更复杂,通过重新定义整个结构,可以向结构中添加新字段:

new_df = (
  df.withColumn('country', struct(
    col('country.name'),
    col('country.capital'),
    col('currency')
  ))
)

如您所见,我们必须列出所有的结构子字段,然后添加新的字段——这可能非常麻烦,尤其是对于具有许多子字段的大型结构。在这种情况下,有一个很好的技巧可以让你一次处理所有的子字段——使用星形符号:

new_df = (
  df.withColumn('country', struct(
    col('country.*'),
    col('currency')
  ))
)

国家中的星号。* 将获取原始结构的所有子字段。然而,在下一个我们想要删除字段的例子中,情况会变得更加复杂。

移除元素

从 Spark 3.1 开始,从结构中删除子字段又是一项简单的任务,因为函数 dropFields() 已经发布。现在让我们使用修改后的数据框架 new_df ,其中该结构包含三个子字段 namecapital、currency 。例如,删除一个子字段大写可以按如下方式完成:

new_df.withColumn('country',col('country').dropFields('capital')) \
.show(truncate=False)+---+--------------+--------+
|id |country       |currency|
+---+--------------+--------+
|1  |{Italy, euro} |euro    |
|2  |{France, euro}|euro    |
|3  |{Japan, yen}  |yen     |
+---+--------------+--------+

正如我们所见,子字段大写被删除。在 Spark 3.1 之前的版本中,情况又变得复杂了,我们必须重新定义整个结构,并删除我们想要删除的子字段:

(
    new_df
    .withColumn('country', struct(
        col('country.name'),
        col('country.currency')
    ))
)

对于大型结构来说,这又是一个繁琐的过程,所以我们可以通过如下列出所有子字段来使其更加可行:

# list all fields in the struct:
subfields = new_df.schema['country'].dataType.fieldNames()# remove the subfield from the list:
subfields.remove('capital')# use the new list to recreate the struct:
(
    new_df.withColumn(
        'country',
        struct(
            ['country.{}'.format(x) for x in subfields]
        )
    )
).show()+---+--------------+--------+
| id|       country|currency|
+---+--------------+--------+
|  1| {Italy, euro}|    euro|
|  2|{France, euro}|    euro|
|  3|  {Japan, yen}|     yen|
+---+--------------+--------+

注意,两个函数 withFielddropFields 都是 类的成员,因此它们被称为列对象上的方法(要了解更多如何使用列类中的方法,请查看我最*的文章,在那里我会更详细地讨论它)。

SQL 表达式中的结构

当您查看 SQL 文档时,您会发现有两个函数可用于创建结构,即 struct()named _ struct(),它们在语法上有所不同,因为 named_struct 也要求为每个子字段传递一个名称:

(
  df
  .selectExpr("struct(id, currency) as my_struct")
).show(truncate=False)+---------+
|my_struct|
+---------+
|{1, euro}|
|{2, euro}|
|{3, yen} |
+---------+(
  df.selectExpr(
    "named_struct('id', id, 'currency', currency) as my_struct")
).show()+---------+
|my_struct|
+---------+
|{1, euro}|
|{2, euro}|
| {3, yen}|
+---------+

结论

在本文中,我们继续描述 Spark SQL 中的复杂数据类型。在之前的文章中,我们讨论了数组,这里我们关注结构,在未来的文章中,我们将讨论映射。我们已经看到了最*版本 3.1.1 中发布的两个重要函数 withField()dropFields() ,它们可以在操作现有结构的子字段时大大简化代码。

药物-药物相互作用的网络分析和可视化

原文:https://towardsdatascience.com/network-analysis-and-visualization-of-drug-drug-interactions-1e0b41d0d3df?source=collection_archive---------12-----------------------

了解如何使用 NetworkX、Pyvis 和 Datapane 探索和可视化药物相互作用数据(Python 格式)

数据子集上药物-药物相互作用的可视化|作者图片

D 药物-药物相互作用当两种或两种以上的药物相互反应时,就会发生药物-药物相互作用,导致意想不到的(且可能致命的)不良反应。

作为一名具有临床药学背景的数据科学家,我热衷于利用我的领域知识来探索药物相互作用的数据。

药物-药物相互作用涉及多个实体之间的联系,因此将网络作为核心概念来分析这些药物相互作用是合适的。

内容

(1)数据采集和准备(2)网络分析用 NetworkX可视化用 Pyvis 和 Data pane**

Volodymyr Hryshchenko 在 Unsplash 上的照片

免责声明 :本文是 而非 意在提供任何形式的医学意见或建议。请向您的医生或药剂师咨询与任何药物治疗相关的专业建议。

(1)数据采集和准备

斯坦福网络分析项目( SNAP )有一个公共的生物医学网络数据集集合,包含许多具有实体间关系信息的数据集。一些例子包括疾病-药物关联,生物过程之间的关系,甚至蝴蝶之间的相似性网络。

我为这个项目使用了ChCh-Miner数据集,它包含了美国食品药品监督管理局( FDA ) 批准的药物之间的相互作用网络。****

原始数据存储为 48,464 行和 2 列的 CSV 文件,其中每行代表特定药物对之间的相互作用。

这些值采用药物库( DB )代码的形式,因此需要与实际药物名称相匹配。这是通过从公共药物库数据库中反复搜索相应的药物名称来手动完成的。

经过进一步的数据预处理(例如,删除没有药物名称的化合物),我们得到了一个熊猫数据帧,如下所示:

已处理药物相互作用数据的样本行|作者图片

该数据集的缺点是没有提供药物相互作用的严重性。因此,添加了一个填充了 1 的的自定义列(名为“ Weight ”)来表示所有交互的“相等”严重性。

(2)用 NetworkX 进行网络分析

(一)概述

一个网络只是一个连接对象的集合,它们对于建模实体(又名节点)之间的关系(又名边)非常有用。

pyvis BSD 许可下使用的网络|图像示例

在我们的数据集中,每一个成对的药物相互作用都是两个节点(即两种药物化合物)之间的关系。

假设我们在药物实体之间有一堆 无向 链接,我们可以继续用 NetworkX 进行网络分析,这是一个用于创建、操作和研究网络的 Python 包。

(二)网络图的创建

NetworkX 可以用pip install networkx[default]安装的

完成后,我们从药物相互作用熊猫数据帧中生成一个网络图对象,并检索网络图的基本摘要:

来自无向药物相互作用网络图的总结结果|图片由作者提供

我们可以看到,该网络共有 1,505 个药物实体(节点),有 48,224 个记录的相互作用(边)。

*均64 ,意味着每种药物一般*均与 64 种其他药物相互作用。(在后面的章节中更多关于节点度)**

网络密度描述网络中潜在连接占实际连接的比例,其中 0 表示一个没有边的图, 1 表示一个所有节点都相互连接的完整图。****

0.04 的低网络密度是有意义的,因为我们不希望太多的药物相互作用。

(三)程度中心性

节点的度是指节点拥有的连接数。当处理网络时,我们处理一个叫做度中心性的关键概念。

简单来说,一个节点的度中心性就是它拥有的边数。这意味着具有 5 个交互的药物节点将具有 5 个的度中心性。

通过计算每个节点的度中心性,我们可以得到 20 种最常涉及药物相互作用的药物:

参与最多相互作用的前 20 种药物(具有相应的节点度)|作者图片

上面的输出显示,药物相互作用中最常涉及的药物是苯妥英钠,,节点度为 442

苯妥英 是一种治疗癫痫发作障碍的常用抗癫痫药物,其血药浓度必须小心保持在一致的水*,以确保其有效性和安全性。

****https://www.mediview.sg/keyword/n-zXKQXN/phenytoin/

以下是一个涉及苯妥英的药物相互作用的例子:

使用的图像基于 Creative Common 的署名-非商业性 4.0 国际许可,如 DrugBank 所示****

(Pyvis 和 DataPane 的可视化

(一)概述

使用网络最酷的部分可能是可视化方面。帮助我们轻松构建这种可视化的工具是 Pyvis,这是一个 Python 库,以创建交互式网络图而闻名。

Pyvis 可以用pip install pyvis安装

从数据帧创建 Pyvis 可视化的顺序如下:

  1. [nx.from_pandas_edgelist](https://networkx.org/documentation/stable/reference/generated/networkx.convert_matrix.from_pandas_edgelist.html)方法从包含边列表的 Pandas 数据帧生成一个 NetworkX 图。
  2. [Network()](https://pyvis.readthedocs.io/en/latest/_modules/pyvis/network.html)初始化一个 Pyvis 网络类实例
  3. Network()类的.from_nx方法将 NetworkX 图形转换成 Pyvis 图形格式

有大量定制可用于构建或修改网络可视化的外观。在我的例子中,我实验了流行的 斥力 解算器巴恩斯小屋 物理模型。

我开始把所有药物相互作用的数据都放入 Pyvis Barnes Hut 的图表中,作为回报,我得到了一个可怕的海胆相似物网络。

完整交互数据集的网络可视化(Barnes Hut 物理模型)|作者图片

㈡探索单一药物

为了使图表更有意义和更易理解,最好是处理更小的数据子集,而不是整个数据集。

因为我们之前发现苯妥英具有最多的药物相互作用,所以让我们单独为苯妥英创建一个 Pyvis 网络(使用排斥解算器):

苯妥英药物相互作用的网络可视化| 请给可视化加载一些时间

注:如果在移动设备上观看此视频,请点击“ 【全屏】” 按钮

上面的图像显示苯妥英钠作为中心节点,被与其相互作用的 442 其他药物实体所包围。

Pyvis 的美妙之处在于可视化效果是交互式的,这意味着你可以将鼠标放在图形上来缩放、指向或拖动节点。

由于 Pyvis 在本地将图形保存为 HTML 文件,所以我们需要一个单独的工具来公开共享结果。这就是 数据面板 介入争论的地方。

Datapane 是一个开源的 Python 库,允许用户在 web 上发布 HTML 文件和 Python 绘图等对象,以便共享和可视化。你可以在这里找到我写的上传 HTML 文件到 Datapane 的脚本。

㈢探索多种药物

只看一种药物可能没什么洞察力,所以让我们探索一个由稍大的数据子集组成的网络。

我挑选了三种药物( 二甲双胍赖诺普利辛伐他汀** )分别在糖尿病****高血压高脂血症这三种常见疾病中的关键作用进行深入探讨。******

在过滤数据以保留涉及这三种药物中至少一种的相互作用后,得到的图表如下所示(有点类似于水母花椰菜的形状):****

涉及部分药物(二甲双胍、赖诺普利和辛伐他汀)的药物相互作用的网络可视化|请给可视化加载一些时间

从网络图中,我们可以很容易地找出与二甲双胍、赖诺普利和/或辛伐他汀有共同相互作用的不同药物。和以前一样,这个网络图是交互式的,所以继续探索吧。

一个有趣的见解是,只有一个实体与所有三种精选药物相互作用(即具有边缘),该药物是 奎宁

奎宁与二甲双胍、赖诺普利和辛伐他汀相互作用|作者图片

(4) Python 实现代码

我在这个 GitHub repo 里面贴了全面的代码和数据 ,所以可以随意探索(和星/叉)里面的内容。

请尝试 NetworkX 和 Pyvis 中的其他功能和网络定制,并尝试创建自己的网络!

费尔南多·埃尔南德斯在 Unsplash 上拍摄的照片

(5)向前迈进

基线分析和可视化完成后,下面是几个潜在的后续步骤:

  • 药物相互作用有不同的严重程度(即轻微、中度、严重),由于缺乏数据,这一点未被考虑在内。理想的情况是找到并包含该信息,以便边缘可以具有不同的厚度来反映不同的严重性。
  • 将鼠标悬停在节点和边上时,以弹出窗口的形式添加交互细节
  • 将该项目部署为一个 Streamlit web 应用程序,这样用户就可以自己选择一组药物,并在网络图中显示出来。

更新:Streamlit 部署最*已经完成!请点击这里查看:

****** ******

在你走之前

欢迎您加入我的数据科学学习之旅!一定要关注这个媒体页面,以便了解更多令人兴奋的数据科学内容,或者访问 LinkedIn 。尽情探索网络图吧!****

******

参考

什么是网络分析?

原文:https://towardsdatascience.com/network-analysis-d734cd7270f8?source=collection_archive---------1-----------------------

带有示例的简介

如果您正在使用任何社交媒体应用程序,您可能已经体验过好友或关注者建议功能。你有没有想过这些功能是如何工作的?在这些情况下,一种常用的技术是网络分析。

什么是网络?

网络是指代表一组对象/人以及他们之间的关系的结构。它在数学中也被称为图形。网络结构由节点和边组成。这里,节点代表我们将要分析的对象,而边代表这些对象之间的关系。

例如,如果我们正在研究脸书用户之间的社会关系,节点是目标用户,边是关系,例如用户之间的友谊或组成员关系。在 Twitter 中,边可以是关注者/追随者关系。

作者图片

为什么要进行网络分析?

网络分析在许多实际应用任务中非常有用。它有助于我们深入理解社会网络中的关系结构,自然现象中的结构或变化过程,甚至对生物体的生物系统的分析。

再次,让我们以社交媒体用户的网络为例。分析这个网络有助于

  • 识别一个群体中最有影响力的人
  • 定义用户组的特征
  • 为用户预测合适的项目
  • 识别 CM 目标等。

其他容易理解的例子有脸书的好友建议功能或 Twitter 的关注建议功能。

谁是重要人物?

网络分析的一个重要应用是识别网络中的重要节点。这项任务称为测量网络中心性。在社会网络分析中,它可以指识别最有影响力的成员或群体代表的任务。

作者图片

比如上图你觉得哪个节点最重要?

当然,要定义最重要的节点,我们需要一个具体的重要节点的定义。有几个指标用于测量节点的中心性。

  • 度中心性:度越高的节点中心性越高
  • 特征向量中心性:在一个节点的度上加上邻居节点的中心性。结果,对应于邻接矩阵的最高特征值的特征向量表示网络中节点的中心性
  • 介数中心性:两个节点之间经过第 I 个节点的路径数被认为是第 I 个节点的介数中心性。
  • 紧密中心性:网络中从第 I 个节点到其他节点的路径长度被认为是第 I 个节点的紧密中心性。例如,利用这个定义,这种中心性可以应用于在城市中定义合适的疏散地点的任务中。
import networkx as nx
import numpy as np
import matplotlib.pyplot as pltG = nx.Graph()
G.add_nodes_from(["A","B","C","D","E","F","G","H","I","J","K"])
G.add_edges_from([("A","C"),("B","C"),("C","D"),("D","E"),
("D","G"),("A","G"),("F","H"),("G","H"),("H","I"),
("I","J"),("I","K")])nx.draw(G, node_size=400, node_color='red', with_labels=True, font_weight='bold')print("degree centrality:")
for k, v in sorted(nx.degree_centrality(G).items(), key=lambda x: -x[1]):
      print(str(k)+":"+"{:.3}".format(v)+" ", end="")
print("\n")print("eigenvector centrality:")
for k, v in sorted(nx.eigenvector_centrality(G).items(), key=lambda x: -x[1]):
      print(str(k)+":"+"{:.3}".format(v)+" ", end="")
print("\n")print("between centrality:")
for k, v in sorted(nx.betweenness_centrality(G).items(), key=lambda x: -x[1]):
      print(str(k)+":"+"{:.3}".format(v)+" ", end="")
print("\n")print("closeness centrality:")
for k, v in sorted(nx.closeness_centrality(G).items(), key=lambda x: -x[1]):
      print(str(k)+":"+"{:.3}".format(v)+" ", end="")
print("\n")

作者图片

作者图片

我们是谁?

网络分析的另一个应用是社区检测任务。此任务旨在将网络划分为在任何特定功能方面都相似的节点组。该任务的例子是定义 SNS 中共享共同兴趣/观点的用户组、寻找客户群以广告特定商品、在线购物系统中的推荐系统等的任务。

许多研究人员正在研究有效解决社区检测问题的算法。该任务中一些众所周知的算法/方法是 Kernighan-Lin 算法、谱聚类、标签传播、模块化优化等。

示例代码

作者图片

作者图片

还有什么?

除了这些应用之外,网络分析在时间序列分析、自然语言处理、电信网络分析等方面也起着重要的作用。最*,机器学习(深度学习)的技术也被用于网络分析。在这种情况下,关于图嵌入和图神经网络的研究是有趣的课题。

要了解更多细节,我推荐以下网站和教材。

操作网络数据的网络分析

原文:https://towardsdatascience.com/network-analysis-in-r-manipulating-network-data-ee388fba7215?source=collection_archive---------16-----------------------

在 r 中使用 igraph 执行网络分析和操作网络数据。

作者图片

介绍

N 网络分析是一种使用图论来研究复杂现实世界问题的技术,例如计算生物学、工程、金融、市场营销、神经科学、政治学和公共卫生(Kolaczyk 等人,2014)。在我之前的工作中,我用 NetworkX 和 node2vec 在 python 环境中做了相当多的网络分析。不过最*偶然看到了 Eric D. Kolaczyk 和 Gábor Csárdi 写的书——《用 R 对网络数据进行统计分析》(这是第 1 版,第 2 版于 2020 年出版),这本书向我展示了 R 中许多很酷的软件包(如 igraph),它们在操纵图形、数学建模、统计建模等方面提供了高质量的网络分析。

这本书附有一份代码演示列表,可以在这里找到:https://github.com/kolaczyk/sand

这个博客是建立在本书的第二章:处理网络数据的基础上的,假设你已经理解了网络分析的基本概念,如节点、边等。然而,如果你需要一个全面的解释,我鼓励你读这本书。

您需要什么:

RStudio(或类似的 ide)和“igraph”(一个 R 包,可从 CRAN 获得)

如果您没有安装“igraph ”:

*## Download and install the package* 
install.packages("igraph") *## Load package* 
library(igraph)

密码

创建无向图和有向图

要手动创建图表,可使用“graph.formula”功能。

为了使创建有向图更容易理解,我提出了一个由三个机场组成的机场网络:JFK(纽约机场)、PEK(北京机场)和 CDG(巴黎机场)。因此,我创建的有向图可以理解为:我们只有从 JFK 到北京和 CDG 的单程航班(假设应用了一些旅行限制);北京和 CDG 是相互连接的,你可以双向飞行。

获取图表的基本信息

为了使博客简洁,演示的其余部分将只关注无向图。更多参考,请访问该书的 GitHub 知识库。

一个图,用 G = (V,E)表示,是由一组 V 个顶点和一组 E 条边组成的数学结构。图中的顶点数和边数有时称为图 G 的大小(Kolaczyk 等人,2014)。

您可以使用【V】【E】来检查顶点和边;使用【vcount(graph)ecount(graph)检查图形的顺序和大小;使用print _ all(graph)来显示图形的摘要。

形象化图表

您可以使用 命令绘制 图形:

图一。图(g)

标记顶点

我制作了这个图,它的顶点用数字 1 到 n 标记。实际上,你可能已经有了自然的标签,比如名字。这里是你如何标注你的顶点,以及它看起来会是什么样子:

V(g)$name <-c("Adam","Judy","Bobby","Sam","Frank","Jay","Tom","Jerry")plot(g)

图 2:带标签的图表

图形的表示

通常,图将以三种基本格式存储:邻接表、边表和邻接矩阵(Kolaczyk 等人,2014)。

邻接表是无序列表的集合。每个无序列表描述了邻接表中图的特定顶点的邻居的集合。这种格式就是 igraph 在图形摘要函数中使用的格式。

边列表是一个两列表格,列出了图中的所有节点对。这种格式是 NetworkX(python 中)的首选格式。

邻接矩阵的条目显示了图中的两个顶点是否相连。如果两个节点“I 和 j”之间有链接,则行列索引(I,j)将被标记为 1,否则为 0。因此,对于无向图,邻接矩阵将是对称的。统计模型通常喜欢用这种格式编码图形,比如 node2vec,它需要邻接矩阵作为输入。

可以使用get . adj list(graph)get . edge list(graph)get . adjacency(graph)的函数分别得到三种不同的格式。

图的运算

在实践中,我们可能想要移除某些边或连接图来得到子图。在这种情况下,数学运算符可以帮助您实现目标。

图 3。图的运算

(1,1)中的图是原图。(1,1)中的图从原始图中删除了两个顶点。(2,1)中的图由某些边组成(由于顶点的移除,这些边从原始图中移除)。(2,2)中的图是(1,1)和(2,1)的联图,并且它具有与(1,1)相同的结构。

使用数据框

在现实问题中,我们很少手动制作图表。相反,我们必须导入数据。对于操作图表的最佳实践,我们通常需要准备两个数据文件/数据框。其中一个文件需要包含图中每个顶点的所有属性。另一个文件需要包含网络中的边(通常是边列表)。

在书中,作者举了一个 Lazega 的律师数据集的例子。信息存储在两个不同的文件中: elist.lazegav.attr.lazega 。原始数据可在 sand(网络数据统计分析)库中获得。因此,下面是您如何读取自己的数据:

图 4。阅读你自己的数据

结论

在这篇博客中,我讲述了创建有向和无向图、可视化图、从图中获取统计数据、标记顶点、生成不同格式的表示、子集化和连接图以及使用 igraph 读取您自己的网络数据的代码。

请随时与我联系LinkedIn

相关阅读

NetworkX:操纵子图的代码演示

使用 NetworkX、Gephi 和 Node2Vec 分析疾病共现

参考

带 R 的网络数据统计分析,作者 Eric D. Kolaczyk 和 Csá rdi Gá bor,Springer,2014 年,第 13–28 页。

ETF |方舟基金的网络图

原文:https://towardsdatascience.com/network-graph-of-etf-ark-funds-4f9242f19702?source=collection_archive---------35-----------------------

最终方舟图——作者图片(https://shyambv.com/ark_net.html)

介绍

让我做一个预先声明;在看了凯西伍德关于特斯拉的预言后,我成了她的粉丝。是的,目前,她的基金业绩不是很好。然而,这并不意味着任何长期表现。我试图密切跟踪她的行动。在本文中,我将添加一些图形分析以及如何添加显示它们。

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

本文的目标

在本文中,我们将浏览以下部分。文章的各个部分都使用了 Python

  1. 以编程方式从网站获取方舟基金数据
  2. 阅读 Gmail 方舟基金每日电子邮件
  3. 对购买/销售进行分析
  4. 总体资金分析
  5. 将全部添加到网络图中
  6. 可视化网络

以编程方式从网站获取方舟基金数据

方舟基金与其他试图隐藏其股票持有量的对冲基金略有不同。他们在自己的网站上公开列出了他们目前持有的所有股票。这使得我们的工作比执行所有的刮擦容易得多。

我们需要循环他们持有的所有资金。他们资金不足。

ARKK —方舟创新 ETF
ARKQ—自主技术&机器人 ETF
ARKW —下一代互联网 ETF
ARKG —基因组革命 ETF
ARKF —金融科技创新 ETF
ARKX —太空探索&创新 ETF

在执行了必要的导入之后,这就是获取

太好了!现在我们有了方舟基金的整体投资组合。接下来获取每日交易数据。

获取每日交易

获取每日交易需要一点努力。以下是步骤

  1. 需要订阅方舟每日更新
  2. 创建一个谷歌云项目并启用 Gmail API
  3. 提供电子邮件的访问权限
  4. 阅读发送的电子邮件
  5. 通过电子邮件获取数据

需要订阅方舟每日更新

你可以在这里订阅方舟每日交易通知

创建谷歌云项目并启用 Gmail API

创建谷歌云项目和启用 Gmail API 是一篇独立的文章。你应该启用 Gmail API 并且API 文档中下载生成的 credentials.json 文件。注意,您可以选择您的 OAuth 客户端作为桌面客户端。

来自谷歌云

pip install google-api-python-client google-auth-httplib2 google-auth-oauthlib

这是快速入门 Gmail API 指南。请在此查看所有步骤。

上面的代码将获取标签。因为我们需要搜索特定的电子邮件,我们可以使用下面的代码来获取电子邮件并将其转换为我们想要的文本。

执行完所有操作后,你将得到一个干净的熊猫数据帧输出。

图形分析

我想对我们得到的数据进行以下分析。

  1. Ark 每天都买/卖股票吗?
  2. 方舟正在积累的股票有哪些?
  3. 根据市值的整体投资组合。

如果我们能够获得优质数据集,我想预测方舟的下一只股票。在下一篇文章中,让我知道你的想法。

在图形分析上,我们可以使用不同的包和数据库来执行。对于本文,我们将使用用法包 pyvis。这是一个创建图形的优秀软件包。

数据提取/清理

为了获得所需的数据,我们需要执行获取相应的数据并相应地清理它。我已经执行了所有的获取和清理处理。这是最终数据集的样子。

股票详细信息-按作者分类的图片

每日购买/销售-按作者分类的图片

完成所有这些工作后,我们有了继续前进所需的数据。

绘制图形

现在是时候用我们清理的数据获得良好的视觉效果了。这里 pyvis 库有一个创建网络图的选项。

from pyvis.network import Network
import pandas as pdark_net = Network(height='1500px', width='100%', bgcolor='#222222', font_color='white')

我们可以在记录级别上遍历熊猫的数据框,并添加节点和边。可以为每个节点和边添加不同的格式,如颜色、粗细、标题、形状等。

一级——同行业股票

在第一组绘图中,我们将添加股票代码和市值行业的节点。

股票到行业—作者图片

第二级——行业部门

下一步,我们将添加部门和行业的节点

行业-按作者分类的图片

第三级——股票、行业、部门

在这一部分,我们将把所有类别股票、行业、部门与所有权重、颜色等结合起来。

第四级—添加每日交易柜

最后,我们将添加由 Ark 执行的每日交易。我们需要区分日常买卖。

我们将在销售时添加红色,在购买时添加深绿色。为了显示基金持有和卖出的数量,我们将在标题中标出。这是最后一张图表。

ark_net.add_node(src, src, size =m_log, title = (str(t), m))
ark_net.add_node(dst, dst, title=dst, color='#00ff1e')
ark_net.add_edge(src, dst, value=w, title = str("Sold: "+str(w)+"%"), color ='Red')

你也可以使用这个链接查看纳斯达克可视化。

最后的想法

为了得到它,我们做了大量的工作。这是他们。

  1. 我们可以获取方舟公司的数据并进行数据清理。
  2. 能够阅读方舟控股公司的日常邮件并进行处理。
  3. 获取市场数据,并结合所有数据。
  4. 创建一个网络图并绘制出来。
  5. 与图表上的这个链接进行交互。

我们可以添加更多的信息,并每天更新。使用气流计划整个操作。

参考文献:

  1. https://ark-funds.com/active-etfs
  2. https://ark-funds.com/trade-notifications
  3. https://developers.google.com/gmail/api/guides
  4. https://pyvis.readthedocs.io/en/latest/
  5. https://towards data science . com/under-appreciated-workflow-tool-air flow-a 078 a3 c 71 a 67
  6. https://medium . datadriveninvestor . com/live-advanced-stock-portfolio-rebalancing-autonomous-trading-for-investors-f 6a e9 bef 3c 25

获取代码

请订阅我的 简讯 获取这篇和我其他文章的工作代码。另外,你会得到其他订阅文章。

用于依赖性解析的网络图

原文:https://towardsdatascience.com/network-graphs-for-dependency-resolution-5327cffe650f?source=collection_archive---------24-----------------------

大多数顶级工作负载管理器使用有向无环图(DAG)的原因很简单!

DAG 表示一组互连的节点,并对如何连接这些节点设置了一些硬性限制。DAG 在两个方面不同于常规的图形网络:节点之间的每个连接代表一种单向关系。节点之间的关系不会导致无限循环。

下图显示了一个有向图。然而,它不是非循环的,因为如果你沿着边的方向绕着图中的节点走,你会无数次地经过起点,甚至不会到达最后一个节点停下来。

一个循环有向图(图片由作者提供)

相反,DAG 强制要求不能像这样循环,因此它的名字中有非循环部分。由于 Dag 的这一固有属性,它们成为表达流程中依赖关系等概念的绝佳候选。请参见下图的修改版本,这确实是一个有效的 DAG。

表示处理管道中数据流的有向非循环图(图片由作者提供)

使用 DAG 来表示流程中的依赖关系,让我们假设上面显示的 DAG 边表示处理管道中的步骤,A 馈入 B,B 馈入 c。在此设置中,我们可以通过沿着边往回走来解决依赖关系。我们遇到的每个这样的节点都是我们开始时的初始节点的依赖项。另一种思考方式如下所示。我们可以颠倒每条边所表达的关系,沿着它们走。如果前向边沿表示数据流,那么反向边沿表示数据相关性。

表示处理管道的数据依赖关系的 DAG(作者图片)

既然我们理解了这个概念,我们就可以开始探索可能用来动态解决数据依赖性的算法。作为我工作的一部分,我一直在从事一个处理引擎的工作,这个引擎创建并运行 SQL 规则集。这个 SQL 对原始数据进行操作,产生类似于数据仓库中的表示层的东西。这里的问题是,有时 SQL 可能依赖于由其他 SQL 脚本创建的表和列,我需要一种好的方法来处理这些依赖性。如果我只想运行一个规则呢?我需要一种方法来找到该规则所依赖的所有规则,然后以适当的顺序运行它们,以便在每个 SQL 脚本试图访问它们之前创建所有的依赖关系。

让我们建立一个我所说的玩具例子。因为我在医疗保健领域工作,所以我将使用它作为上下文,但是这些概念适用于任何过程。假设我们有一些原始数据来解释客户与一组健康服务的交互。我们首先清理人口统计数据和健康服务位置数据。该干净的人口统计和地点数据然后被用作 PCD 风险数据处理阶段的一部分。进而,该 PCD 风险处理数据被另外两个阶段使用,即护理计划阶段和事件信息阶段。最后,在事件信息阶段产生的一些数据被用作计费阶段的一部分。这在下面的图表中有所展示。在这种情况下,非循环图中的箭头方向显示的是数据流,而不是数据依赖关系。

一个 DAG 显示了医疗环境中的数据流(图片由作者提供)

因为我是一名 python 程序员,所以我选择使用 NetworkX 库来构建一些算法的原型,以遍历这些依赖图。NetworkX 有一个 DAG 类,如果我尝试初始化的图不是非循环的,它会引发一个异常,并且它会将初始边列表中的所有边都视为有向边。使用上面描述的情况,让我们建立一个描述这个图的边列表,并使用 NetworkX 构建 DAG。

请注意,在上面的代码中,我们将每个节点的关系定义为面向数据流方向的箭头,而不是数据依赖关系的方向。为了获得我们所依赖的节点,我们将“向后”或朝着节点的“前辈”走。

接下来,我们需要定义一个函数来获取图和一个起始节点,遍历包含起始节点所依赖的每个节点的图,然后返回一个表示执行顺序的列表。为了允许并行化,如果存在不相互依赖的节点,我们将允许在执行顺序中多次使用数字。在上图中,我实际上用节点的颜色进行了编码。黄色节点需要首先运行,但是由于它们相互不依赖,没有理由必须先运行一个,或者如果数据库支持,没有理由我们不能并行运行这些处理阶段。

使用get_node_dependancies(graph, start_nodes),我们可以沿着图往回走,建立一个节点列表,以及从我们遇到它们的开始节点的深度。我们可以用这些深度变量计算执行顺序,因为相同深度的节点可以一起运行!但是,这段代码有一个问题。如果我们使用多个开始节点,随着数据流的分支和合并,节点可以在这个列表中出现两次,甚至出现在不同的深度!我们需要一种方法来清理它,并返回给我们一个节点列表和它们的执行顺序。我选择了一种模型,在这种模型中,我们将在处理引擎的执行流中尽可能晚地运行节点。这意味着,如果一个节点在列表中出现不止一次,将使用最小深度(因为这些深度是负的,并且在执行时,“开始节点”实际上是最后运行的,因为我们是向后走的。

现在我们有了实现依赖关系解析算法所需的所有部分,让我们在我们创建的图上测试它。如果我们要运行 PCD 作业,我们首先需要运行人口统计和地区作业。我们希望看到类似“人口统计(0),位置(0),PCD (1)”的内容,其中括号中的数字是执行顺序。因为人口统计和地点作业相互不依赖,所以它们应该获得相同的“执行顺序”值。PCD 应该是下一个运行的,因此执行顺序高 1。

这里有一点需要注意。我决定尽可能晚地运行作业;这意味着为它们分配执行顺序的最大有效数字。您可能会注意到,在上图中,这意味着在使用此依赖遍历器时,护理计划节点实际上是蓝色的。这是为了在出现故障时尽早做尽可能少的工作。这并不总是合适的,我希望能够在各个阶段中*均分配执行。因此,如果有 4 项任务需要在第二或第三阶段运行,4 项任务需要在第三或第四阶段运行,我会对它们进行负载*衡,这样第二阶段有 2 项,第三阶段有 3 项,第四阶段有 3 项,但是,在这个阶段,这是方便读者的一个练习。如果你真的实施了,请告诉我!

网络学习——从网络传播到图形卷积

原文:https://towardsdatascience.com/network-learning-from-network-propagation-to-graph-convolution-eb3c62d09de8?source=collection_archive---------12-----------------------

思想和理论

计算生物学中流行的网络传播方法的两种不同观点及其与图卷积的联系

网络传播图解,图片来自2

你可能听说过图形卷积,因为它是当时的热门话题。虽然不太为人所知,但网络传播是计算生物学中用于网络学习的主要方法。在这篇文章中,我们将深入探讨网络传播背后的理论和直觉,我们还将看到网络传播是图卷积的一个特例。

TL;速度三角形定位法(dead reckoning)

  • 网络传播是计算生物学中一种流行的方法,它基于联想内疚原理。
  • 网络传播的两种不同观点:随机游走 vs. 扩散,以 HotNet2 为具体例子。
  • 网络传播是图卷积的特例。

计算生物学中的网络传播

网络自然地产生于许多现实世界的数据,例如社交网络、交通网络、生物网络等等。网络结构编码了关于网络中每个个体角色的丰富信息。

在计算生物学中,已经表明生物网络,如蛋白质-蛋白质相互作用(PPI),其中节点是蛋白质,边代表两种蛋白质相互作用的可能性,在重建生物过程中非常有用,甚至揭示疾病基因[1,2]。重建可以简单地通过直接观察靶蛋白的邻*蛋白是否是生物过程或疾病的一部分来完成。这种通过相邻蛋白质推断蛋白质成员的过程被称为网络传播。我们将在下一节中更仔细地研究精确的数学公式,但是现在让我们考虑一下为什么这么简单的方法有效。

酵母 PPI 中蛋白质复合物的例子,图片来自[3]

这一切都可以归结为关联有罪 (GBA)原则,该原则指出,彼此密切相关的蛋白质,无论是通过物理相互作用,还是其他类似的措施,如基因共表达,都有可能参与相同的生物过程或途径。GBA 原理源于观察到许多蛋白质复合物(如酵母中的 SAGA/TFIID 复合物[3])位于内聚网络模块中。同样,在人类疾病基因网络4中,我们可以看到,例如,与耳鼻喉疾病或血液疾病相关的疾病基因定位在网络模块中。顺便提一下,在这篇文章中,蛋白质和基因这两个词会互换使用。

人类疾病基因网络,图片来自4

网络传播的数学公式——两种不同的观点

记号

给定一个(无向)图 G=(V,E,w) ,有 n 个顶点的顶点集 V ,边集 E ,权函数 w ,设 A 为对应的 n 乘 n 维邻接矩阵如下。

使用对角度矩阵 D ,其对角元素是相应节点的度数,我们可以按行或按列对 A 进行归一化,分别得到两个新矩阵 PW,

最后,设 p0 为独热编码标签向量,其中 p0 对应于具有正标签的节点的条目为 1,其他地方为 0。

第一个视图—随机漫步

我们可以像在网络上随机漫步一样进行网络传播。在这种情况下,我们要问的关键问题如下。

通过 1 跳传播,从目标节点开始并在任何一个具有正标签的节点中结束的概率是多少?

数学上,该操作对应于 Pp0 之间的矩阵向量乘法,产生预测得分向量 y

让我们看一个例子。考虑基因 g1、g2、g3 和 g4 的下列子网络。假设 g2 和 g3 被注释为一种疾病,这意味着这两个基因已知对这里感兴趣的疾病有贡献。另一方面,g1 和 g4 对这种疾病没有注释(注意:这并不意味着它们对疾病没有影响,而是说,目前还不知道它们与疾病有关)。

随机游走的网络传播实例,图片作者

为了确定 g1 是否与疾病相关,我们可以简单地设计一个从 g1 开始的 1 跳随机漫步,并看看它落在疾病基因(g2 或 g3)上的概率是多少。简单算了一下,我们看到预测得分是 2/3,相当高。这是有意义的,因为 g1 的三个相邻基因中有两个与该疾病相关,并且根据 GBA 原理,g1 很可能与该疾病相关。

第二种观点——扩散

网络传播的另一个观点是通过网络扩散。在这种情况下,我们要问的关键问题如下。

有多少“热量”正在扩散到目标节点?换句话说,通过一跳传播,从具有正标签的节点开始,并在目标节点结束的概率是多少?

在数学上,该操作对应于 Pp0 波浪号(T4 P0 的规范化版本)之间的矩阵向量乘法,产生预测分数向量 y 波浪号。

注意: p0 的规格化保证了从一个概率分布到一个概率分布的映射,即 y 波浪号总和为 1。

让我们回到上面通过网络传播进行疾病基因预测的例子。这一次,我们希望将标签传播作为扩散来执行。结果,由两个注释的疾病基因产生的总“热量”的大部分(5/12)被 g1 收集。因此 g1 很可能与这种疾病有关。

作为扩散的网络传播示例,图片由作者提供

超越一跳传播

多跳传播的图示,图片来自[5]

一跳传播方法简单而有效。然而,当标记数据稀缺时,这是计算生物学中的典型情况,1 跳传播方法只能计算疾病基因的直接邻居的基因的非*凡预测分数。鉴于人类基因组中有超过 2 万个基因,这显然会导致次优预测。因此,我们可以扩展到 2 跳、3 跳甚至更多,而不是局限于 1 跳的邻域。此处的图说明了从 k = 1 到 k = 2 的 k 跳传播。

热网 2 扩散

有许多不同的变体来执行多跳扩散或随机行走。在这里,我们将把 HotNet2 作为一个具体的例子来关注2。类似于上面介绍的扩散,HotNet2 算法迭代更新初始“热量”分布 p0 波浪号如下。

其中β的值从 0 到 1,是将“热量”带回源头的“重启概率”。包含这种重启概率有几个(有些相关的)原因。首先,扩散算子的先前定义给出了当前节点具有的所有“热量”,因此在步骤 t ,所有先前的扩散信息都丢失了。添加β有效地保留了每个步骤中的一些热量,因此在步骤 t ,分布包含来自先前步骤的所有信息。其次,当 t 趋于无穷大时,(非零)β参数保证了热分布的收敛,这进而给出了在 t= ∞处的热分布的闭合解

最后,在[1]中已经表明,就生物路径重建、疾病基因预测等而言,与上一节中定义的 1 跳网络传播相比,这种 HotNet2 扩散方法可以产生始终更好的预测。

与图卷积的关系

回想一下,图形卷积网络遵循如下的逐层传播规则。

GCN 传播,方程(2)在6

其中 H(l)是第 l 层的隐藏特征,W(l)是可学习的参数,并且非线性 sigma (DAD)内部的主导部分是具有自连接的谱归一化邻接矩阵。自连接的作用类似于重启概率,以保留当前迭代的一些信息。

通过下面的替换,我们可以将标签传播完全重构为图卷积的特例。

  • 用行规范化(P)或列规范化(W)版本替换谱规范化自连接邻接矩阵
  • 将 H(l)替换为 p(l)
  • 用恒等式代替非线性和 W(l)(或者干脆忽略这些变换)

注意,第一次替换不会改变图形频谱,因此仍将执行相同的卷积运算。

现在你知道了,网络传播是图卷积的一个特例!

结论

基于关联原则,由于细胞组织的模块化,网络传播被广泛用于计算生物学中的各种任务,如疾病基因预测。我们已经深入探讨了网络传播的两种观点及其与图形卷积的关系。

参考

[1] R. Liu,C. A. Mancuso,A. Yannakopoulos,K. A. Johnson,A. Krishnan,监督学习是基于网络的基因分类的精确方法 (2020),生物信息学

2 L. Cowen,T. Ideker,B. J. Raphael,r .莎兰,网络传播:遗传关联的万能放大器 (2017), Nat Rev Genet

[3] V. Spirin 和 L. A. Mirny,分子网络中的蛋白质复合物和功能模块 (2003),美国国家科学院院刊

4 K. Goh,M. E. Cusick,D. Valle,B. Childs,M. Vidal,A. Barabasi,人类疾病网络 (2007),美国国家科学院学报

[5] W. L. Hamilton,R. Ying,J. Leskovec,大型图上的归纳表征学习 (2017), arXiv

6 T. N. Kipf 和 M. Welling,利用图卷积网络的半监督分类 (2016), arXiv

网络建模提出了消除网络仇恨的新策略

原文:https://towardsdatascience.com/network-modeling-suggests-novel-strategies-to-eliminate-online-hate-b9d312e35c43?source=collection_archive---------33-----------------------

乔治华盛顿大学和迈阿密大学的研究人员基于他们的分析提出了一种新方法。

照片由 JJ 英Unsplash

网络仇恨是社交媒体上的一个猖獗问题。它不仅会造成歧视性骚扰的有害环境,还会煽动现实世界的暴力和仇恨犯罪。由于创建一个匿名账户很容易,有大量的仇恨者,而且追踪所有事件的挑战很大,监管这些*台很困难。寻找新的解决方案仍在继续。

今天的反仇恨方法

打击网上仇恨的典型方法是本地或*台范围的内容审核和政策执行,有时通过机器学习工具来增强。内容审核成本高且耗时,因为大多数情况下,最好手动完成。然而,即使每个仇恨事件都由工作人员审查,人类版主也远非万无一失。适度会对心理健康造成巨大的伤害,主持人甚至会相信他们被雇来打击的阴谋论。因此,在*台范围内开展有效的反仇恨活动几乎是不可能的,更不用说在互联网范围内了。

已经进行了许多分析,为社交媒体*台推荐不同的策略和政策。通常,重点是监控或引导个别不良行为者,或压制整个意识形态,前提是它们是仇恨意识形态。前者过于精细,不能有效地衡量,而且在许多情况下,公众意见的转变是团体而不是个人的属性。后者使*台容易受到审查的指责。

亚历山大·沙托夫在 Unsplash 上的照片

将在线社交媒体社区建模为网络似乎是反仇恨研究最有效的途径之一。尽管人类行为是复杂的,但人类社会网络与生物网络、计算机网络和其他类型的网络共享许多属性。网络分析允许研究人员在一组简化的条件下测试打击仇恨的不同策略。

来自约翰逊等人的小说策略

一份关于网络仇恨的特别有趣的网络分析由 Johnson 等人发表。2019 年,在期刊自然T5。在这项研究中,在线仇恨被建模为网络的网络——跨越*台、国家、语言和仇恨类型的仇恨网络。

约翰逊等人。与其他建模方法相比,的建模方法使用了稍微不同的范例。它们将每一个仇恨集群表示为具有将仇恨传播到另一个集群的特定概率,当仇恨内容传递到监管更好的*台时会产生成本。他们使用公开可用的数据,并特别关注高度监控的脸书和不那么高度监控的 Vkontakte 之间的仇恨流。

Jason LeungUnsplash 上的照片

约翰逊等人。我发现,全面的、特定于*台的监管只会导致用户转移到监管不那么严格的*台,从而形成网络仇恨的“黑池”。经过伪装,这种仇恨往往会蔓延回最初监管更好的*台。所以,对于打击网络仇恨,约翰逊等人。建议与目前使用的策略稍有不同的策略。基于他们的模型,他们推荐了四种方法,主要是基于孤立或分裂仇恨团体:

  1. 关闭较小的讨厌集群。研究发现,仇恨集群的规模遵循幂律分布。关闭达到一定规模而不是最大规模的仇恨集群的原因是,瞄准最大规模只会让新的仇恨集群重新形成。另一方面,针对已经达到一定规模的仇恨集群,在它们变得太大之前,被证明可以防止集群增长。另一个优势是较小的仇恨集群更容易被发现,因为它们的数量更多。
  2. 随机封禁可恶用户。试图禁止一个*台上所有可恶的用户可能会导致他们迁移到另一个*台,并受到审查的指控。另一方面,随机禁令不必基于个人身份信息,也可以瓦解网上的仇恨团体。随机禁止的用户可以来自与*台相同的国家,以最好地利用社交媒体公司的内部法律知识。然而,团体可能会对随机禁令做出明确的反应。他们如何反应还没有研究过。
  3. 将仇恨集群与反仇恨集群结合起来。大量互联网用户致力于消除仇恨。如果仇恨集群与这些群体接触,他们就是分裂的。他们变得不太可能采取激进的下一步措施,也不太可能在现实世界中做出令人憎恶的行为。虽然这种方法可能不需要*台方面的节制,但研究估计,赶走最后的仇恨者需要很长时间。这种方法的其他缺点是,当人们遇到相反的观点时,他们可能会拒绝参与或他们的立场可能会变得强硬。反仇恨的用户也可能变得激进。研究中没有分析这些可能性。
  4. 将仇恨集群与其他不同意的仇恨集群联系起来。这种方法利用了许多仇恨团体的一个特点——他们与其他仇恨团体存在严重分歧的倾向。例如,一些白人至上主义者支持统一的欧洲,另一些人反对。这项研究表明,反仇恨用户可以促进对欧洲统一持反对意见的白人至上主义者进行接触。他们的内讧可以防止进一步的激进化和仇恨集群的进一步增长。只有部分仇恨集群表现出这种属性。此外,没有研究当遇到相反的观点时,观点可能会变得强硬的可能性。

照片由 dole777Unsplash 上拍摄

约翰逊等人。的范例和方法有许多优点。他们的模型和提出的策略不需要个人信息,这种信息会成为隐私问题。它们也不需要社交网络之间的明确协调,社交网络可能会将彼此视为行业竞争对手,并可能会关注机密信息的共享。

对抗网络仇恨的未来

虽然 Johnson 等人的方法可能很有前途,但需要在更现实的条件下进行进一步的研究,以评估其有效性。相对较少的研究采取了网络建模的方法,额外的网络模型可以帮助阐明打击网上仇恨的方法。

约翰逊等人。例如,特别关注三 k 党仇恨群体,因为他们的符号很容易识别。并非所有类型的网上仇恨都表现出这种特性——例如,巴以仇恨可以有许多不同的形式。分析其他类型的仇恨、其他*台和其他模型表示可以补充这项研究。

这种适度的方法也需要在现实世界的社交媒体*台上进行测试。这可以在试点规模上进行,如果成功和经济,将越来越广泛。不需要*台间大规模协调的方法,如 Johnson 等人中推荐的方法。,更适合小规模测试。

奇拉尤·特里韦迪Unsplash 上拍摄的照片

就算约翰逊等人。的方法或它们的变体奏效了,但它们不是灵丹妙药。他们只会减少而不是消除网上的仇恨。即便如此,消除一些网上的仇恨就像打击犯罪一样。它让互联网和世界对每个人都更安全、更健康。

使用 GRANDstack 的网络可视化

原文:https://towardsdatascience.com/network-visualizations-with-grandstack-a07deb0a0c3a?source=collection_archive---------27-----------------------

了解如何结合 Neo4j、Graphql 和 React 来开发一个图形探索工具

哈利波特世界的网络可视化。图片由作者提供。

这些年来,我参与了几个 Neo4j 项目。几乎所有的项目都有一个共同点,即需要开发一个定制的网络可视化工具,使最终用户无需学习任何 Cypher 查询语言语法就可以浏览图形。这篇博文将展示我开发的一个简单的网络可视化工具,它可以让你可视化并探索哈利波特的世界。可视化应用程序是使用 GRANDstack 构建的。所有代码都可以在 GitHub 上获得。

图片来自 https://grandstack.io/的。由 4.0 在 CC 下授权。

大钉由四部分组成:

  • Neo4j 数据库:存储网络数据的原生图形数据库
  • graph QL:API 的数据查询和操作语言
  • Apollo:一套协同工作来创建 GraphQL 数据流的工具。
  • React:一个 JavaScript 库,用于构建基于组件的可重用用户界面

Neo4j 数据库

Neo4j 是一个本地图形数据库,适合存储、操作和查询网络数据。如果你是一个完全的 Neo4j 初学者,想了解更多,建议你看看 Neo4j 介绍页面

《哈利·波特》网络数据来自我不久前写的一篇博客,在这篇博客中,我使用了 NLP 来提取《哈利·波特》和《魔法石》中人物之间的联系。图表模式模型如下:

哈利波特宇宙图形模式。图片由作者提供。

在我们图表的中心是这本书的人物。有些角色属于像格兰芬多或斯莱特林这样的霍格沃茨学院。人物也是忠于各个群体的。例如,赫敏·格兰杰致力于促进小精灵福利的协会。网络还包含人物之间的家庭关系信息。最后,角色之间的交互也存储在数据库中。这是一个关于哈利波特的子图可视化示例:

围绕哈利波特的样本子图。图片由作者提供。

我已经在 GitHub 库中添加了数据集文件以及如何将数据加载到 Neo4j 中的说明。

GraphQL 端点

GraphQL 最初由脸书开发,后来在 2015 年公开发布。GraphQL 是一种用于 API 的查询语言和服务器端运行时,它优先向客户端精确地提供它们请求的数据。GraphQL 服务是通过定义类型和这些类型上的字段,然后为每个字段提供函数来创建的。Neo4j 开发了一个 GraphQL 库,可以快速开发与 Neo4j 数据库交互的 GraphQL 服务器。此外,该库自动提供检索 GraphQL 模式中定义的类型和字段所需的函数。当然,如果您愿意,您总是可以为任何字段提供一个定制的解析器。

这里,我在模式中定义了两种类型。类型名必须与 Neo4j 中的节点标签相同。Neo4j GraphQL 库默认提供完整的 CRUD 支持。在我们的网络可视化工具中,我们将只从 Neo4j 读取数据,从不更新数据库。由于我们不需要完整的 CRUD 支持,我们可以将创建、更新和删除突变排除在生成之外。您可以将应该通过 GraphQL 端点可用的节点的属性包含在一个类型的字段中。

例如,我们可以使用这两种模式类型在客户机中检索关于 House 或 Group 节点的信息。检索房屋节点信息的 GraphQL 查询示例如下:

query house {
   houses {
     name
   }
}

这个查询的结果是:

{ "data": {
   "houses": [
   { "name": "Gryffindor"},
   { "name": "Slytherin"},
   { "name": "Hufflepuff"},
   { "name": "Ravenclaw"}]
  }
}

嗯,那很简单!对于基本的 CRUD 操作,您甚至不需要了解任何 Cypher 查询语言。Neo4j GraphQL 库还提供了对分页、排序和过滤查询的支持。在文档中了解更多信息。接下来,我们可以为一个角色构造一个模式类型。

字符类型有点复杂。这里,我们介绍了@relationship指令。如果你还记得图形模式,一个角色可以属于一个家族,也可以忠于一个团体。为了检索关于角色的房子的信息,我们必须遍历 BELONGS_TO 关系。在@relationship指令中,您指定要遍历的关系类型及其方向。关系的方向可以是传出或传入。

我们的应用程序包括一个自动完成特性。我们将使用 Neo4j 的全文搜索特性来实现前端的自动完成功能。您可以在Query类型下定义定制的 GraphQL 查询。

这是我们需要为 GraphQL 服务器生成的大部分代码,以便与 Neo4j 交互。我还添加了交互类型,但是它非常基本,没有引入额外的功能,所以我在这里跳过了它。

前端反应组件

现在我们已经准备好了数据库和 GraphQL 服务器,我们可以继续开发前端了。我已经使用了 vis-react 进行网络可视化。我选择它是因为它同时公开了节点/边数据集和网络对象。我们需要节点/边数据集来创建动态网络可视化,而网络对象用于添加交互性。

Apollo 客户端库提供了两个 React 挂钩,用于从 GraphQL 端点检索数据。首先是useQuery钩。当 react 组件装载和呈现时,Apollo 客户机自动执行指定的查询。您可以如下定义useQuery挂钩:

首先,您需要定义 GraphQL 查询。在这里,我指定要检索 PageRank 值大于 0,16 的所有字符。此外,我只对 name、pagerank 和 community 字段感兴趣,所以我可以指定查询只检索这些字段。接下来,您可以通过使用 useQuery 功能来定义 Reach 挂钩。最后,将获取的数据与交互信息相结合,然后输入到 vis-react 库中,以生成下面的网络可视化。

哈利波特世界的网络可视化。图片由作者提供。

Apollo 客户端库提供的第二个 React 钩子是useLazyQueryuseLazyQuery钩子是为响应其他事件而运行查询而设计的。例如,您可以通过单击按钮来执行查询,或者在我们的示例中,通过在可视化中选择一个节点来选择一个字符来填充弹出窗口。

然后,在 characterData 别名下的函数 return 中可以获得角色的数据。注意,我在 GraphQL 查询中使用了where谓词来获取特定字符的数据。我已经使用了 react-modal 库来生成弹出窗口,因此代码如下所示:

有时您希望能够在函数中访问 GraphQL 返回。在我们的示例应用程序中,我们需要将自动完成选项从函数返回到输入组件。要实现这一点,您可以访问 Apollo 客户端,并等待查询通过异步函数完成。

通过组合自动完成、弹出和其他查询,我创建了以下网络探索组件:

哈利波特网络示例探索。作者视频。

结论

希望这篇博文能帮助你开始大规模的网络探索和可视化。如果你有任何想法如何改善这个应用程序,请让我知道生长激素问题或创建一个拉请求。

和往常一样,代码可以在 GitHub 上获得。

操作子图的代码演示

原文:https://towardsdatascience.com/networkx-code-demo-for-manipulating-subgraphs-e45320581d13?source=collection_archive---------18-----------------------

作者图片

介绍

NetworkX 是一个用于研究图形和网络的 Python 库。这是一个代码演示,展示了我们如何使用 NetworkX 进行子图比较,以及如何操作参数来绘制图形。如果您以前不熟悉 NetworkX,它会告诉您如何将加权边列表转换为 NetworkX 图,以及如果您想要研究超级复杂网络图中的特定节点,尤其是在提供了权重属性的情况下,您可以做些什么。

数据

我们正在使用电子健康记录(EHR)数据集,其中包括亚利桑那州 2019 年下半年至 2020 年下半年住院患者的诊断。该数据集包含* 9000 个独特的诊断。每个诊断都标有 icd10 编码。在住院期间,每个病人可能有不止一种诊断。通过研究 EHR,我们可以捕捉疾病或诊断之间的共现关系。

IC D10(https://icdcodelookup.com/icd-10/codes)是国际疾病和相关健康问题统计分类(ICD)的第 10 版,是世界卫生组织(世卫组织)制定的医学分类清单,指明了疾病、体征和症状、异常发现、主诉、社会环境以及伤害或疾病的外部原因。

我们手动将数据集分为三个时间戳:2019 年下半年、2020 年上半年和 2020 年下半年,以研究疾病网络在疫情的不同阶段如何变化。为了用数据实现 NetworkX,我们首先将数据转换成一个加权边列表,它有三列:源、目标和权重。

图 1:样本数据

密码

将边列表转换为网络 x 图:

图 convert _ graph()的示例输出

用边权重画出整个图

下面是一个输出示例:

图 3:示例图

正如我们从图 3 中看到的,由于图中有大量的节点和边,这个图非常复杂,很难阅读。如果您的网络很小而且很简单,那么它现在应该会返回一个明显的视图。

研究图中的某个节点

因此,如果我们想特别了解 2020 年上半年冠状病毒(u071 代表新冠肺炎)的情况,我们需要做的是键入:

drawnodegraph(图 2,“u071”,weightbar=0.1)

图 u071 的疾病网络

用法示例(时间演变图对比):

假设我们想要研究“永久性房颤”(i4821)的疾病网络在疫情的三个不同时间点上是如何变化的。通过使用上面的代码,我们可以看到:

图 5:疫情之前的 i4821 网络

图 6:疫情开始时 i4821 的网络

图 7:疫情疫情期间 i4821 的网络

很明显,在疫情之前,只有少数疾病与永久性房颤显著相关(i4821)。然而,随着 2020 年时间的推移,网络变得越来越复杂。

结论

在这个代码演示中,我们向您展示了如何使用 NetworkX 来操作子图。您可以使用边的权重来更改图形中边的宽度。当然,你也可以在此基础上进行其他变换,例如:使用权重来改变节点的大小,等等。最后,我们还向您展示了这段代码的一个用途——进行时间演化图比较。

请随时与我联系LinkedIn

相关阅读:

使用 NetworkX、Gephi 和 Node2Vec 分析疾病共现

我是在堪萨斯大学商学院商业分析助理教授Karthik Srinivasan博士的指导下完成这篇博客的。

神经架构搜索:一个模型创建公司

原文:https://towardsdatascience.com/neural-architecture-search-a-model-creation-company-602c6ba4f576?source=collection_archive---------21-----------------------

AutoML 如何工作?我们如何在不同的设备上部署模型?看看 NAS 和谷歌大脑的最新进展:BigNAS

图片来自 Unsplash by beasty

https://medium.com/@stefanobosisio1/membership

当我在学习和接触机器学习时,我总是想知道 Google AutoML 如何能够为给定的任务选择合适的模型,返回有希望和令人鼓舞的度量结果。研究越来越多,当我发现神经架构搜索(NAS)的力量时,我感到高兴和兴奋,这是创建新模型的关键,它运行在 AutoML 下面。

如果一方面我们有深度学习,这可以被视为自动化特征工程的成功例子——即我们不必花费数小时来寻找有前途的特征,因为架构本身可以在网络中处理这一点——另一方面,ML 未来的下一个有希望的步骤是自动创建新的强大模型。这一步可以由 NAS 来完成,NAS 正在成为一个越来越令人兴奋的研究领域。

为了理解 NAS,我们必须参考 Elsken、Metzen 和 Hutter 的综述,他们将 NAS 方法分为三个步骤:

  • 这是一个建筑原则生活的空间(例如 CNN、LSTM、RNN 等等)。一些体系结构和任务性能的先验知识有助于快速识别新的模型,减少这个空间的维度;
  • search strategy:我们如何探索搜索空间?搜索策略应该为我们提供如何执行模型研究的规则,在快速找到一个性能良好的架构以避免过早收敛之间进行折衷;
  • performance estimation strategy:我们最终需要一种策略来检测所有创建的架构的性能,满足计算成本。

图 1:将 NAS 分解为三个步骤:1)探索搜索空间,操作(例如池化、卷积等)就在搜索空间中进行;2)有一个好的侦探策略,为特定的任务挑选正确的片段;3)为任何创建的架构建立一个评估系统。【图片由作者提供。]

搜索空间

我们可以天真地认为通过创建 NN 架构作为一系列链状结构的神经网络来填充我们的搜索空间。在这种情况下,层 L_i 的第 i 个输入是层 L_(i+1)的输入。因此,我们可以认为相空间由 n 个最大层和每层的任何种类的操作组成,从卷积到池化,以及与每个操作相关联的任何超参数值。这很好,但是在这样的空间中进行有效搜索的计算成本太高了。

第二种方法是多分支网络。这里,我们将每个层与一个函数 g_i(L_i,…L_out) 相关联,该函数允许来自一个层的输出的组合成为随机新层的输入。此外,每个分支由保持输入维度的单元 : 正常单元和减少空间维度的减少单元组成。通过将每一个细胞堆叠在一起,我们创造了最终的建筑。小区例子可以是 LSTM 块或卷积架构以及 rnn。

图 2:左边是链式结构的神经网络,右边是多分支网络。图片来自 Elsken 的论文。

用编码术语来说,实现搜索空间的最初尝试需要回答这些问题:

  • 我们想要模仿什么样的建筑?能不能从人类已知的建筑开始?我们想从新的开始吗?
  • 我们想要多少层?我们能强加一个限制吗?
  • 我们有多少计算能力?这要花多少钱?
  • 我可以使用哪些 Python 包?Keras?Tensorflow?

试想一下:虽然我们可能会想到小型神经网络,但搜索空间中的参数数量会非常多。为了减少计算成本,我们可以为每个隐藏层中的神经元数量考虑一个列表。从那里,我们可以对一组激活函数做同样的事情。最后,我们甚至可以考虑在建筑功能中插入已知的架构:

搜索策略

既然我们已经定义了搜索空间的组成部分,我们需要一种方法来搜索正确的部分。这是一个奇妙的研究领域,有很多充满活力和令人兴奋的想法。受神经进化(例如遗传算法)的启发,每个新架构都可以基于贝叶斯优化或进化方法来构建。另一种有前途的方法是强化学习方法,其中状态是部分训练的架构,回报是模型的性能,动作是对最终模型的功能保持突变。更*的例子有蒙特卡罗树搜索爬山算法或连续松弛

在 Python 中,我们可以考虑类似的东西来实现搜索策略:

性能评估

为了进一步定义搜索策略,我们需要找到一种合适的方法来计算每个创建的模型的性能指标。天真地,我们可以考虑根据训练数据对所有生成的模型进行评估,但考虑到我们生活的巨大搜索空间,这将需要巨大的计算成本。但是,我们可以找到一些解决办法:

  • 较低的逼真度:可以根据充分训练后的实际表现的较低逼真度来评估表现。这可以是对数据子集或较低分辨率的数据进行训练,或者每层使用较少的过滤器和单元。
  • 学习曲线的外推:只需从早期生成的学习曲线进行几个时期的训练,就可以外推性能
  • 预测性能:可以使用另一个模型来预测各种架构的性能
  • 一次性架构:这是一个基于“图形”的程序。对于每个创建的架构,都有一个包含所有架构的不同部分的一次性模型(例如,一个架构 1 的 CNN,架构 2 的 LSTM,等等)。然后,对该模型进行训练,其权重在所有现有体系结构中共享,并用于检索性能

图 3:一个简短的架构方法:创建的架构显示在左侧。不需要评估每一个单独的模型,可以评估一个一次性的模型,它包含了所有架构的各个部分。由此,权重在所有现有的架构之间共享。图片来自 Elsken paper。

如今,一次性架构被广泛使用。显而易见,我们可以通过训练一个超级网络,然后对几个候选人进行排名来提高效率。然而,通常有彻底的后处理来从每个候选中检索精确的准确性。在搜索之后,需要对权重进行补偿、重新训练和微调。遗憾的是,这些步骤带来了额外的计算成本,以及部署阶段的复杂性。的确,每个候选人在不同的硬件上有不同的表现。例如,即使两个设备可能有相同的 CPU,如在移动电话中,硬件可能更喜欢一个网络架构,返回不同的精度和性能。这个工程方面将我们带到了最后一步:如何正确部署 NAS 模型?

BigNAS:为合适的硬件找到合适的型号

ML 中最被忽视的需求之一是资源感知。这意味着我们经常需要最小化资源使用、延迟或失败。谷歌大脑正在用 BigNAS 解决这个问题,这可以被视为一个两步过程:

  • 首先,训练一个大的单级模型,其重量在展开时就可以使用。考虑到这个模型的规模,我 t 可以分割不同的子架构,这对于不同硬件上的即时推断和部署来说非常方便。
  • 在给定硬件资源限制(例如,CPU 大小、延迟、预算)的情况下,找到最准确的模型

BigNAS 是 NAS 的一种新范式,它已被证明在广泛的硬件架构中超越了最先进的 ImageNet 分类模型搜索。为了让 BigNAS 工作,我们只需要几个简单的步骤:

  • 三明治规则(Sandwich Rule):这个有趣的名字是由 Yu 和 Huang 起的,定义了一种策略,在每次迭代中训练最小和最大的模型。在 BigNAS 环境中,在每个训练步骤中,针对最小的子模型和最大的子模型以及其他一些随机的子模型来处理小批量的数据。然后,来自采样子代的所有梯度被聚集并用于更新单阶段模型中的权重
  • 原位提取:这里的想法是将最大的模型从真实数据中获得的知识转移到所有较小的子模型中。特别地,来自最大模型的预测标签被用作所有较小子模型的训练标签。

最后,通过由粗到细的策略选择最佳模型。在这种方法中,首先搜索有希望的候选网络的粗略框架,然后用细粒度的变化进行采样。在这个设置中,定义了有限的输入分辨率集、深度集和核集来对模型进行基准测试。然后,挑选最佳模型并随机变异(例如,网络分辨率、阶段深度、内核大小)以越来越多地改进最终模型。

这项工作有助于进一步扩展 NAS,这可能会在某个时候为我们带来新的强大的体系结构,以解决越来越复杂的任务。然而请记住,总要付出一定的代价,那就是理解模型在做什么,以及这些特性如何在模型的决策过程中发挥作用。

请随时给我发电子邮件询问问题或评论,地址:stefanobosisio1@gmail.com

或者,你可以在 Instagram 上联系我:【https://www.instagram.com/a_pic_of_science/

神经和服,或人工智能的互文性

原文:https://towardsdatascience.com/neural-kimono-or-intertextuality-of-ai-218fda33ab41?source=collection_archive---------22-----------------------

用人工智能创造古代服装的新图案

和服设计,由人工智能创作//图片由 Merzmensch 提供

S【朱丽娅·克里斯特娃】在她的散文中写道“文字、对话与小说PDF关于文本,它们分别是“对另一种【文本】”的吸收与转化。她推广了术语“互文性”,这是

错综复杂的引文。

没有原文;它们基于不同的先前作品,不断改变我们的叙述。

文本是纹理——它们是我们现代以文字为基础讲故事的材料,其模式、主题、思想,与古代世代相传的不断变化的故事相比,确实具有永恒变化的其他特征(以“中国耳语”游戏的方式,在及时转换的上下文中改变内容)。

随着人工智能时代的后作者叙事,我们不得不重新思考互文性作为生成驱动力。如果基于作者的文本是由有意识和潜意识的人类思想体(作者的知识、经验、偏见、成见、成见、扭曲的记忆)创建的,那么作为创造者的人工智能在以前的数据集上接受训练,并通过重新解释、重新组合已知的特征、模式、视角(就像在基于自我关注的语言模型 GPT-3 中一样)来生成新的作品。

因此,模型越大,知识的潜在空间就越丰富——越多创造性的完成出现。

接受记忆训练

视觉模型以不同的方式工作——通过检测和重新解释可见的图案、颜色和形状。训练数据库越多样化——越令人惊讶和多样的图像完成,就像我的项目“merz mory”一样,由 RunwayML 驱动。

https://medium.com/r/?URL = https % 3A % 2F % 2 ftowardsdata science . com % 2f visual-ai-trained-on-my-memories-a54c 55967 c28 % 3 FSK % 3d 3e 37 e 2716 ccee 2101 ba 07025 e 5 bcfd 60//图片由 Merzmensch 提供

这里我使用了 StyleGAN2 (FFHQ)模型,它最初是在高分辨率照片人像上进行预训练的。它可以创建 1024 x 1024 的图像。作为动机的面部并没有发挥重要作用,因为在无数次迭代之后,它们消失了,并被修改成来自新数据集的图片。在默兹莫里我使用了我的高度异质的摄影收藏——完成相当抽象。在训练(或微调)期间,StyleGAN2 模型创建与原始图像最接*的图像。

两个神经网络相互对抗:

  • 发生器,试图创造尽可能精确真实的图像,愚弄对方;
  • 鉴别器,其任务是检测伪图像并拒绝它们。事实核查!

经过多次迭代后,图像变得越来越接*训练数据集中的原始图像。如果鉴别者不再能够区分真伪,那么训练就可以被认为是成功的。

在 MERZmory 的例子中,我的数据集中有非常不同的图像,所以“最接*原始的”这个概念是不可行的。

MERZmory //图片由 Merzmensch 提供

这种训练的一个有趣的方面是两个对手都非常关注的最突出的视觉特征。他们学会发现它们,产生它们,并揭穿它们。

在我的异构数据集之后,我将我的训练数据限制为仅圆形图像,即在构图中间具有圆形形状的照片:

我的圆形数据集//图片由 Merzmensch 提供

完成变得有点圆——但我在第 500 次迭代时停了下来:初始预训练的人脸仍然可见。圆形人出现了。

圆脸(第 500 步)//图片来自 Merzmensch

在训练这一轮数据集到第 1000 步之后,潜在空间转换到人脸几乎不可识别。最突出的是眼镜,作为一个强有力的主题。

Merzmensch 对圆形数据集//图像的第 1000 次迭代

但是同样,即使已经检测到了一个特征——圆形,原始数据集仍然是异构的,足以创建与原始图像最接*的“相同能量”图像。

神经和服

有了神经和服,我们就有了另一种情况。

正如我昨天在公共领域时事通讯中读到的关于和服图案书籍(ca。1900ies),我受到了启发。

史密森尼图书馆将其中一本图案精美的书籍数字化:

权利:公共领域美国//来源:https://publicdomainreview . org/collection/unk indo-和服设计

然而,为了训练,它们在形状和颜色上有所不同。

In opposite, another book by Metropolitan Museum of Art, Hanafubuki [“花吹雪”, “Falling Cherry Blossoms”], from 1904, caught my attention.

Published by Hatubaijo Honda Unkindō in Kyoto [京都市: 本田金之助: 發賣所本田雲錦堂], it provided a variety of Kimono designs, presented in the Kimono shapes:

来自" Hanafubuki" //公共领域的页面

在这里,我们可以看到贯穿整个出版过程的明显的视觉结构:

  • 两页展开
  • 左右页显示相反的和服方向
  • 上面有汉字的描述

唯一的区别是恒定形状中的图案。

这个集合让我用作和服新神经设计的训练数据集。

所以我开始训练。

训练 AI-和服

第一步仍然显示初始预训练模型:人脸。同样,我使用这种模式不是因为面孔,而是因为该模型具有最佳的输出分辨率,1024 x 1024。

步骤 1,开始 Merzmensch 的 StyleGAN2 训练//图像

这些人并不存在,正如你已经知道的

在步骤 310-480 之后,事情变得更令人毛骨悚然

步骤 310//Merzmensch 的图像

第 480 步//图片由 Merzmensch 提供

正如你所看到的,主要的特征是可以识别的:左右页的垂直分割——在每张图片的中间。这张脸即将被一分为二。

在步骤 820,你不能再识别人脸。只有某人的眼镜仍然是一个突出的特征;它甚至继续到步骤 1060

步骤 820 //图片由 Merzmensch 提供

第 1060 步//图片由 Merzmensch 提供

大约在 1600 年,我们已经可以从书中辨认出图案和形状:

步骤 1610

大约需要另外一半的步骤,直到我们有了神经和服的新模式:

在这里,同样的过程也在进行,用人工智能创作的音乐来产生戏剧性的效果。

当然,花、山、浪这些具体的图案已经消失了。但是我们现在看到:

  • 和服形状
  • 两页展开
  • 颜色;色彩;色调
  • 类似汉字的涂鸦

在这里我们有新的文本,马赛克的语录模式,这是被艾的转化和吸收

人工智能以互文性为驱动方式;它是真实的,对创造新媒体至关重要。但是我们在这里得到了无穷无尽的新变化,这是以前不存在的。

没有原件。但是有独特性。和新鲜感。

神经语言模型

原文:https://towardsdatascience.com/neural-language-models-32bec14d01dc?source=collection_archive---------13-----------------------

从前馈到堆叠递归

马库斯·斯皮斯克在 Unsplash 上的照片

在 NLP 中,语言模型是符号字母表上序列的概率分布。语言建模中的一个中心问题是从例子中学习语言模型,例如从句子的训练集中学习英语句子的模型。

语言模型有许多用途。比如…

  • 建议自动完成:用户在网络搜索引擎或智能手机上键入几个字符(或单词),可能的扩展就会被建议。
  • 识别笔迹:基于图像的识别系统增加了语言模型,提高了准确性。例如,即使一个单词不清晰,它也能从上下文中猜出这个单词。
  • 识别语音:和手写识别一样,用语言模型扩充语音系统可以提高其准确性。
  • 检测并纠正拼写错误
  • 翻译语言:为了将文本从一种语言翻译成另一种语言,为这些语言建立语言模型很有帮助。

在[1]中,我们讨论了统计语言模型,这是 20 世纪 90 年代及更早时期的标准范式。在过去的几十年里,出现了一种新的范式:神经语言模型。这就是这篇文章的主题。

为什么神经语言模型胜过统计语言模型?简而言之:它们以最少的人工工程产生最先进的精确度。为什么?简短的回答是:由于*几十年来两项突破的结合——深度神经网络和递归神经网络。(计算能力和训练数据可用性的指数级增长也有很大帮助。)分布式表示,即单词嵌入,也发挥了作用。

在这篇文章中,我们将在语言建模的背景下讨论递归神经网络(包括深度神经网络)。

我们从主方程开始。这些是本帖中最重要的外卖方程式。除了精确定义语言建模问题之外,它们还可以用来构建解决问题的各种方法。

P ( w 1, w 2,…, w n)表示一个令牌序列( w 1, w 2,…, w n)的概率。学习的目的是从序列的训练集中学习这样的概率。

考虑预测序列的下一个记号的相关问题。我们将此建模为 P ( w n | w 1, w 2,…, w n-1)。请注意,如果我们可以准确预测概率P(wn |w1, w 2,…, w n-1),我们可以将它们链接在一起得到

P ( w 1、 w 2、…、wn)=P(w1)P(w2 |w*1)P(w3 |w*

大多数学习方法将语言建模作为下一个令牌预测问题。这是一个监督学习的问题。输入为( w 1, w 2,…, w n-1)。我们寻求的输出是 wn 可能取的各种值的概率分布。

注意,输出是固定长度的概率向量。(不过,维度可能非常高。几十万到几百万的英语句子语言模型。)

输入不是固定长度的向量。其长度 n 不等。在许多用例中, n 通常很大,在 100 或 1000 以上。这是造成这个问题困难的首要因素。

统计方法估算P(wn |w1、 w 2、…、 w n-1)当 n 较大时必须做一些假设。没有他们,问题就难以解决。假设 n = 101,字母表只有两个符号:0 和 1。可靠估计p(wn |w1, w 2,…, w n-1)的最小训练集大小是 2 ⁰⁰.的数量级这是因为输入可以是这些选择中的任何一个,我们希望能够在每种情况下合理地预测下一个令牌。

统计方法中最广泛采用的假设是马尔可夫假设。具体来说,P(wn |w1、 w 2、…、 w n-1)用P(wn |wn-k、…、 wn -来*似这假设下一个令牌概率仅取决于最后的 k 个令牌。这里的 k 是固定的,往往是一个很小的数(2 或 3)。关于这个主题的更多信息,请参见[1]。

这大大简化了问题。代价是无法模拟长期影响。这里有一个来自2的长期影响的例子。

简走进了房间。约翰也走了进来。时间已经很晚了,每个人都在漫长的一天工作后走回家。简向 __ 问好

答案是约翰。这需要记住约 25 个单词前约翰的出现。

另一个很好的例子来自4

我在法国长大……我说一口流利的法语。

预测法语需要记住法语,这可能在很多句子之前就已经出现过了。

神经语言模型解决了这个“长期影响”的问题。此外,它们还更好地解决了短程影响问题,特别是通过可自动学习的特征向量。(统计方法也可以使用特征;然而,这些都是人为制造的。)

早期神经语言模型

早期的神经语言模型之一,如[3]中所述,本质上是前馈。虽然最*的方法现在都是循环出现的,但我们从这个模型开始,因为它有一些深刻的特征,将为后面的方法奠定基础。

和很多统计语言模型一样,这个模型是 k 阶马尔可夫。即对于 n 大于 k ,假设P(wn |w1、 w 2、…、 w n-1)等于P(wn |wn-k

它对输入单词使用分布式表示。分布式表示,最*也被称为单词嵌入,可以追溯到 20 世纪 80 年代。一个单词的分布式表示将其映射到一个三维数字空间。分布式表示由算法以鼓励语义相关的单词在该空间中彼此靠*的方式来学习。

使用学习过的分布式表示的直觉是希望它们能够提取涉及语义相关的单词的有用特征。例如,如果一个人在同一文本中看到 ParisFrance ,这可能有助于模型做出涉及上下文 French 的合理推断,例如在我们的语言示例中:我说流利的 __

然后这个模型将 wn - k ,…, wn -1 的分布式表示串联起来。这形成了输入向量,维度为 k * d 。因为我们希望输出是整个单词词典的概率分布,这个网络使用 N 个输出神经元,其中 N 是词典的大小。

输入层和输出层之间有一个隐藏层。与任何其他多层神经网络一样,隐藏层将输入映射到特征向量。(神经元是乙状结肠样的,特别是 tanh。)这种映射是通过从每个输入神经元到每个隐藏神经元的可学习权重来完成的。

从隐藏层到输出层的映射使用 softmax 函数。这是因为我们希望输出是输出神经元上的概率分布。softmax 函数由权重参数化,每个(隐藏神经元、输出神经元)对一个权重。

该网络的参数以通常的方式学习,即通过使用随机梯度下降的反向传播。在这个过程中,也可以学习各种单词的分布式表示。可选地,这种分布式表示可以以某种其他方式(例如 word2vec)预先学习,并且仅在这里使用。

值得注意的是,当词典 N 的大小很大时(比如以百万计),涉及输出层的计算成为瓶颈。这是因为特定输入的预测输出需要是整个词典的概率分布。

一个更严重的限制是,这个网络就像典型的统计模型一样,不能模拟相距超过 k 个单位的单词之间的影响。在我们的约翰 - 的例子中,我们需要 k 至少为 25,我们才有希望做出正确的推断。

显式计算P(wn |wn-k,…, wn -1)的统计模型需要随 k 呈指数增长的内存。这种神经网络模型的伸缩性更好。它使用kdh+h*N参数,其中 h 为隐藏神经元的个数。所以参数的数量只随 k 线性增加。

递归神经网络

递归神经网络对语言建模很有吸引力,因为它们不受 k 的约束。也就是说,原则上,他们可以学习任意的远程影响。也就是说,这样做确实需要一些特殊的工程。

我们将从描述一个基本的 RNN 开始。我们会发现它很难学习远距离影响。然后,我们将讨论对此 RNN 的修改,以缓解这一问题。

基本 RNN

作为一个黑盒,即从输入输出接口来看,RNN 乍看起来像一个前馈神经网络。它输入一个矢量 x 并输出一个矢量 y

不过有一个转折。RNN 期望接收向量序列 x (1),…, x (T)作为输入,一次一个向量,并输出向量序列 y (1),…, y (T)。

在时间 t 的输出 y ( t )不仅受到 x ( t )的影响,还受到在此之前接收到的输入的整个序列 x (1)、…、 x ( t )的影响。这就是 RNN 强大的原因。并且相关的学习问题具有挑战性。RNN 必须携带状态。好歹它必须把历史 x (1)、…、 x ( t -1)总结成一个状态,我们就称之为 h ( t -1),从中可以很好的预测 y ( t )。当输入 x ( t )出现时,它首先将其状态更新为 h ( t )。实际上, x ( t )成为它看到的输入历史的一部分。然后从 h ( t )产生输出向量 y ( t )。

我们可以把它正式写成

**h**(*t*) = **f**(**h**(*t*-1),**x**(*t*))
**y**(*t*) = **g**(**h**(*t*))

总之,RNN 可被视为由两部分组成:

  1. 基于当前状态和新输入更新状态的部件。
  2. 将当前状态转换为输出的部分。

第 1 部分让人想起计算机科学中的有限状态自动机。第 1 部分+第 2 部分是计算机科学术语中的有限状态转换器。

FSA 中的状态可以被视为一个分类变量。相比之下,RNN 中的状态是一个多维向量。后者有利于状态的紧凑分布式表示,可以很好地概括,这是现代神经表示的一个主要优势。

锦上添花的是(委婉地说),RNN 的状态变化和状态到输出行为都可以从一组(输入序列输出序列)对的训练集中自动学习。

状态改变和输出功能

遵循通常的神经网络“设计模式”,该模式部分受到生物神经网络的启发,并得到统计学的认可,我们将使用

**f**(**h,x**) = ***S1***(**Whh*****h** + **Wxh*****x**)
**g**(**h**)   = ***S2***(**Why*****h**)

这里的 S1S2 通常是 s 形函数,通常是双曲正切函数或逻辑函数。

f ( hx )计算下一个状态,作为当前状态和通过挤压函数 S1 推送的下一个输入的线性组合。 g ( h )通过挤压函数 S2 将输出计算为新状态的线性变换。

语言建模中的 RNNs

RNNs 的一个基本用例是在语言建模中。回想一下,在语言建模中,我们的主要兴趣是估计P(wn |w1, w 2,…, w n-1)。

在 RNN 中对此进行建模的一种自然方式是将 wn -1 建模为输入向量 x ( n -1),将历史 w 1, w 2,…, w n-2 建模为状态向量 h ( n -1)和输出 y (n 出于这些目的,使用 softmax 函数作为输出函数 S2 是很自然的。而不是挤压函数。 S2 ( u )对 u 的每个分量取幂,然后将得到的向量归一化,形成概率分布。也就是说,它将每个指数值除以指数值的总和。

在结构上,这类似于前面描述的前馈神经语言模型。输出维度为 N ,即词典的大小。输入维度基于单词的表示方式。如果单词是局部表示的,即作为一键编码,则输入维数为 N 。如果单词以分布式方式表示,输入维度就是这种分布式表示的维度。状态向量的维度类似于隐藏层的维度,并控制相应特征空间的容量。

单词序列 w 1、 w 2、…、 w n-1、 wn 可以被转变成这个基于 RNN 的语言模型的训练实例。输入的顺序是 x (1),…, x ( n -1),前 n -1 个字的向量顺序。与该序列相关的目标输出 y ( n -1)是从字 wn 得到的。它是概率向量,所有的质量都集中在这个单词对应的维度上。

让我们停下来思考一下这个问题。输出维度总是 N ,因为我们正在尝试学习一个语言模型。这确实有学习的后果,因为 N 通常非常大。输入维度可以是分布式的和紧凑的,或者是局部的和典型的巨大的,即 N 。有取舍。本地表示赋予模型高容量,并且能够进行细粒度的区分。每个单词对于每个隐藏的神经元都有自己的权重向量。在输入层使用单词的分布式表示的模型是指数级的——更紧凑,可以学习得更快,并且可能概括得更好。他们可以利用已经通过有效算法(如 word2vec 和增强)学习的分布式表示,这些算法可能来自庞大的文档语料库。

学习

可学习的参数是状态转换和输出函数内的权重矩阵 WhhWxhWhyWhh 控制当前状态向量对下一个状态向量的影响, Wxh 下一个输入向量对下一个状态向量的影响, Why 下一个状态向量对下一个输出向量的影响。

为了理解学习是如何发生的,及时展开递归神经网络是有帮助的,如下所述。

现在考虑在时间 t 的输入 x ( t )以及其目标输出 y ( t )。请记住,我们寻求学习的映射实际上是在输入序列 x (1)、 x (2)、…、 x ( t )上输出接*于 y ( t )的值,我们可以将这种情况描述为一个多层前馈神经网络,如下所示。

所以我们可以使用反向传播来学习函数 fg 中的权重。一个转折。上图中所有的 f 必须具有相同的重量。都是一样的 f

好的,我们可以通过对所有层的 f 中每个权重的变化求和来实现这一点。

思考这个问题的一种方式如下。假设我们有两个版本的网络:约束版本(其权重如前一段所述共享)和无约束版本,后者是一个多层神经网络,没有权重共享,即 f 的每个实例都有自己的权重。在学习对( x (t), y (t))之前,我们将把无约束版本中的每个权重初始化为来自约束版本的对应权重。然后,我们运行一次在线反向传播迭代(也称为随机梯度下降)来更新无约束版本的权重。由此,我们通过对每个约束权重取映射到它的无约束权重的*均值,来导出约束版本上的新权重。

原则上,这一切听起来都很棒。但是,注意,展开的网络可以很深!因此,如果存在远程影响,即对于大的 k (比如说 k = 100),意味着 x ( t - k )强烈影响 y ( t ),则反向传播的误差信号可能会变得非常弱。这是因为误差通过 f 反向传播的每个实例都会衰减误差,因为 f 是一个挤压函数。

让我们在下面的背景下详细阐述上一段的最后一句话。

为了简化解释,我们使用具有两个隐藏层的前馈神经网络。加上输入和输出层。所有层各有一个神经元。除了输入层之外的所有层都具有 s 形传递函数。 hi 表示第 i 层神经元的输出, ni 表示该神经元的输入。所以我们有hi=s(ni)其中 s 表示 sigmoid 函数。我们还有ni=w(I-1)**h(I*-1)。

请注意,为了简化符号, h 0 表示输入, h 3 表示输出。

在本图中,我们将使用损失函数 L = (y- h 3)。反向传播算法利用(在需要时应用链式法则)计算 L 相对于每个权重的梯度,以决定对权重进行的改变。更准确地说,

作业指导书=-n** dL/d作业指导书*

这里的 n 是学习率。“-”是因为我们在做梯度下降(因为我们想最小化误差)。

所以现在归结为计算 d L /d wi 的各种权重 wi

先说 w 2。

根据链式法则,

dL/dw2 =(dL/dh3)(dh3/dn3)(dn3/dw2)= 2(y-h3)**s*

不可否认,我们有点超载符号。在上面, h 2, h 3 和 n 3 表示变量(神经元)和它们在输入 x = h 0 上的特定值。我们还利用了这样一个事实:sigmoid 函数 d s /d n 的导数等于s(n)(1-s(n))。还有就是,对于I0,dni/dw(I*-1)等于 h ( i -1)。

类似地,通过稍微深入地应用链式法则,我们得到

dL/dw1 =(dL/dh3)(dh3/dn3)(dn3/dh2)(dh2/dn*

2(y-h3)s(n3)(1-s(n3))w2 **s(n2)(1-s*(

现在想象向我们的网络添加更多的隐藏层(保持拓扑和传递函数不变)并计算 d L /d w 0。

dL/dw0 = 2(y-h(K)s(nK)(1-s(nK)w【t*

考虑任意一项s(ni)(1-s(ni*))。这个产品总是小于。组合 d L /d w 0 中的所有这样的对产生一个乘法因子,其值小于()^ K )。鉴于此,随着 K 的增加,d L /d w 0 非常非常快地接* 0。这就是消失梯度问题。在我们的例子中,这具有潜在的灾难性后果。我们可能永远也学不会 T21。

一个长期的例子

接下来,我们来看一个现实的例子,具有远程影响。我们将用它来说明学习这样的影响是基本 rnn 的问题,而不是表现它们的能力。这个相同的例子也将有助于说明一个更先进的 RNN 缓解这一问题的机制。

我们希望处理一长串英文单词,如果单词恐怖分子至少出现一次,则输出 1,否则输出 0。如果恐怖事件只发生一次,而且发生在序列的最早期,那么这个事件需要被记住直到最后。

为什么不在检测到恐怖分子后立即输出 1,否则继续?这将是调整这个特殊问题的一般解决方案的机制。这种调整不会推广到表现出长期影响的更广泛的问题,这只是一个说明性的例子。

XOR 示例以完全相同的方式用于前馈神经网络设置。作为一个需要解决的问题,XOR 是微不足道的。只需输入两个二进制数,输出的二进制数就是它们的异或。然而,作为说明某些前馈架构的问题和测试改进的例子,它被证明是非常有用的。异或运算是线性不可分的。这就是只能进行线性区分的分类器失败的原因。事实上,在 20 世纪 80 年代,XOR 经常被用作测试和演示多层感知器设置中反向传播的学习能力的基准,多层感知器是具有隐藏层和 s 形神经元的前馈神经网络。

好的,回到我们的例子。为了我们的目的,让我们细化问题描述。输入 x (1),…, x ( t )是一个向量序列,其中 x ( i )代表第 i 个字。如果单词恐怖分子出现在该序列中,输出 y( t )为 1,否则为 0。因此输出是与输入序列对齐的二进制序列,并且具有非常简单的结构:01

我们将把一个单词表示为一个独热编码向量。向量的维数是词典的大小。对应于被表示的字的位是 1,其余的是 0。

现在考虑这个问题的基本 RNN。它的输入和输出结构已经指定。国家呢?让我们将状态向量的维数设置为与输入向量的维数相同。如果由 i 索引的单词在 x (1)、…、 x ( t )中至少出现一次,我们希望 hi ( t )接* 1,否则接* 0。

这在代表性上当然是可行的,有选择的

(t) =乙状结肠( a * (t-1)+bXi(t)+c*)

很容易选择 abc ,比如 a = b = 1、 c 略负,这样 hi ( t )本质上就是 hi (t-1)和Xi()的 or 这就是我们想要的。

一旦我们处理了整个序列,我们可以简单地设置 y ( t )到 hi ( t ),其中 i 索引我们关心的特定单词(在我们的例子中,恐怖分子)。我们可以这样写:y=g(W*h(t))其中 g 是一个乙状结肠。 W 是第 I 个位置足够正(如 1),其余为 0 的向量。

现在我们从的角度来看这个情况。假设我们有一个(文档标签)对的训练集,其中如果某个单词出现在文档的某个地方,那么标签为 1,否则为 0。我们可以假设标记是一致的,即这个“某个单词”总是相同的。然而,我们没有被告知这个词是什么。

因此,这里有两个问题:(1)学习者必须推断出潜在的数百万个单词中哪一个最能区分这两个类别,以及(2)只按顺序学习,如前面的基本 RNN 部分所述。

集中在(ii)上,在许多情况下,时间反向传播可能需要将误差梯度传播回很久以前。如前一节所述,这种梯度会消失。这样做的结果是,如果在大多数肯定的情况下,最后出现的“某个单词”(在我们的例子中,恐怖分子)出现在文档中的最后一个单词之前,学习者将不能建立这个出现和输出 1 之间的联系。如果我们的正面例子至少是有点长的文档,在大多数情况下,单词恐怖分子的最后一次出现将确实是在文档结束之前。

在结束这一部分之前,我们想补充一点,既然我们已经打开了驱动学习的标签的大门,这个问题就变得更加重要了。只要我们有足够丰富的数据集,我们可以用这种方式提出任何文本的二进制分类问题。由递归神经网络解决方案来确定哪些单词和哪些顺序结构有助于解决问题。

也就是说,如果一个人的目标是解决这样一个问题,并且如果没有令人信服的理由来进行顺序学习,那么他应该首先尝试非递归二进制分类器算法。如前馈神经网络、随机森林、朴素贝叶斯分类器等

门控循环单元(GRU)

我们现在将注意力转向更高级的递归神经网络,它能够捕捉长期影响。广泛使用的两个这样的网络是 LSTM 和 GRU

我们将描述 GRU,因为它的机制更简单,同时仍然有效地捕捉远程影响。

在高层次上,GRU 的工作方式与基本 RNN 相同。输入是一个一个呈现的向量序列。GRU 保持状态,捕捉到它目前所看到的一些关键方面。这个状态与下一个输入相结合决定了下一个状态。

进步来自于状态转移函数。

我们将使用我们刚刚介绍的例子来建立对 GRU 的描述。

对于这个例子,考虑基本 RNN 的状态更新功能

h ( t ) =乙状结肠(Ah(t-1)+Bx(*t【T21)+C**)*

GRU 将以不同的方式从 h ( t -1)和 x ( t )建立 h ( t )。它引入了从 h ( t -1)和 x ( t )派生出来的新内存 hnew ( t )的概念。从 h ( t -1)和 x ( t )派生这个新内存的过程有一个机制,首先通过一个过滤门运行 h ( t -1)的各个组件。为此,可以将此视为让网络有选择地关注 h (t-1)的不同组件。

这个滤波器,姑且称之为 si ( t ),取值在 0 和 1 之间。过滤包括将 hi ( t -1)乘以 si ( t )。在向量符号中我们把这个写成s(toh(t-1)。

然后,过滤后的版本 h ( t -1)与 x ( t )进行线性组合,并通过一个分量双曲正切函数。完整的等式是

hnew(t)= tanh(Ax(t)+B(s(t)oh(t-1))+C**

然后,新的存储器与旧的存储器相结合以形成更新的存储器,其方式将在下面描述。相比之下,在基本的 RNN 中,更新的记忆仅仅由旧的记忆形成。

在我们的例子中,什么是好的新闻?让我们用伪代码捕捉期望的行为。

IF i indexes *terrorist* and xi(t) is 1
    hnew,i(t) = ~ 1
IF i indexes *terrorist* and hi(t-1) is ~ 1
    hnew,i(t) = ~ 1
IF i indexes some other word
    hnew,i(t) = ~ 0
ALL ELSE
    hnew,i(t) = ~ 0

hnewi ( t )对于除了恐怖分子以外的任何字 i 都接*于 0。如果新输入的 x ( t )是恐怖分子或者之前已经见过恐怖分子,在这种情况下 hi ( t -1)将接* 1。

我们能选择学习参数来模拟这种期望的行为吗?

首先,我们将把 C 设置为 0 的向量。

第一个 IF 的 THEN 子句可以通过适当选择矩阵 A 来执行。具体来说,设置 Aii 等于 1,A 的其余元素全部为 0。

第二个 IF 的 THEN 子句可以通过选择 si ( t )对于 i 索引恐怖分子接* 1,对于其余的接* 0 来执行。选择 B 作为正值矩阵,例如全 1。

ABs ( t )、 hnewi (t)这些条件下,当前两个 THEN 子句都没有触发时,将设置为接* 0。

在这个阶段,读者可能会想,我们真正得到了什么?如果单词恐怖分子最后一次出现在当前 t 之前,将不会从第二个 THEN 子句的长触发链中计算 hnewi ( t ),该子句的前提是“ i 索引恐怖分子hi ( t -1)

读者这样想是对的。我们还没有完成对 GRU 的描述。一旦我们有了所有的机制,我们将会更好地理解它们是如何一起缓解梯度消失问题的。

GRU 使用第二门,称为更新门,来控制新旧存储器对更新存储器的相对贡献。相比之下,基本 RNN 只是从旧的记忆中获得更新的记忆。

在潜入更新门之前,让我们先完成对过滤门的描述。

滤波门方程

这是

s(t)= s 形(Dx(t)+Eh(t-1)+F**)

这里 DEF 是控制门行为的可学习参数的矩阵和向量。

在我们的恐怖分子示例中,我们从 s ( t )寻求的行为是简单地投射出 hi ( t -1)的值,其中 i 索引单词恐怖分子。我们从训练集中自动学习这种行为有多好是一个完全不同的故事。

举例说明更新门机制

为了对更新门及其所扮演的角色建立直觉,一个不同的例子将会有所帮助。

我们希望使用 RNN 在时间序列中进行异常检测。我们希望异常检测器不仅能检测异常,还能适应新常态。让我们用一个例子来说明这一点。

1, 2, 3, 2, 4, 2, 3, 2, 3, **23**, 22, 25, 24, 22, 23, 24, 25, 21, …

我们从左到右处理这个时间序列。值 23 远远超出了我们目前看到的数值范围,所以我们认为它是异常的。我们应该这样做。当我们继续处理这个异常右侧的值时,我们看到一个新常态正在形成。(具体来说,一个级别的转变。)在不久的某个时候,异常检测器应该适应这种情况,并开始将其视为“正常”。例如,不要认为 20 到 25 之间的值是异常值。

我们还希望能够通过提供一个带标签的数据集来更好地控制“不久的某个时刻”。我们的意思是,一个时间序列被标上了哪些点是异常的,哪些点不是异常的。对于任何特定的时间序列,RNN 应该能够推断出我们希望向“新常态”过渡的激进程度或保守程度。这将是从历史标记中推断出的时序特定行为。

一种方法是训练 RNN 来预测时间序列中的下一个值。如果实际的下一个值与预测的下一个值相差很大,则认为该值异常。

rnn 原则上适合于单步预测,因为这个问题类似于学习语言模型。在这两种情况下,我们都希望从历史输入中预测下一个输入。

RNN 在以预测下一个值为目标的增量学习期间学习的模型可以被解释为“正常值”的当前模型。

现在假设这个 RNN 是一个基本 RNN。遇到第一次出现的 23 会怎么样。我们希望它能将其标记为异常。接下来会发生什么?它对 23 进行增量训练,就像对任何新值进行训练一样。这样做的效果是,随着我们在这个级别看到更多的值,模型将逐渐调整到这个新的级别。也就是在构建一种‘新常态’。到目前为止一切顺利。它正朝着我们想要的方向发展。

如果这个 23 是一个异常值,即一个尖峰信号,而不是一个水*移动,RNN 将很快调整回旧的常态。所以一切似乎都很好。不过,让我们更仔细地看看这个。由于基本的 RNN 不能记住旧的常态(基于第一次出现的 23 左边的时间序列中的值的常态),它必须放弃它对 23 的适应,朝向一个进化的新常态。事后看来,这是一个异常现象。

GRU 更好地解决了这种情况。就像基本的 RNN 一样,GRU 通过预测下一个值并根据预测误差调整其模型来学习适应其“常态”。与基本的 RNN 不同,GRU 使用两种模型:一种是进化较慢的模型,在 h ( t )中捕获,第二种是进化较快的模型,在 hnew ( t )中捕获。实际上,GRU 可以同时记住“旧常态”和试探性的“新常态”。它的复合模型是这两者的结合。这为 it 提供了灵活性,如果“新常态”后来被证明是“假警报”,即异常,它可以只使用“旧常态”。相比之下,基本的 RNN 将不得不忘记它。这也让 GRU 更快地适应新常态,以防这不是一场“虚惊”。

下面的伪代码总结了这种行为。

Evolve two models, a slow one and a fast one, based on forecasting and feedback from forecasting errors.IF the new fast model is somehow deemed as capturing a transient phenomenon
   continue treating the 'old model' as the normal
ELSE
   evolve towards the 'new fast model' as the normal

更新闸门使用公式

我们把这个门叫做 uui ( t )在 0 和 1 之间。使用该门更新存储器的公式为

(t)=(1-ui(t)(t-1)+ui(t*)hnew*, i ( t )

用向量符号表示就是

h(t)=(1-u(t))oh(t-1)+u(t)ohnew(t)

异常检测实例提炼

接下来,让我们细化对异常检测示例的讨论。我们将使用一维输入和输出向量,因为我们正在处理一个时间序列。对于状态向量,我们可以考虑更高维度。无论我们感觉什么都适合于捕捉时间序列的最*值的“正常”特征。例如,如果我们不仅希望捕捉时间序列的最新值(*滑版本),还希望捕捉其趋势,我们可以选择两个维度。

通过小心选择 hhnew 的尺寸,我们可以检测不同类型的异常。为了检测点异常,二维状态向量可能就足够了。一个维度模拟集中趋势,例如均值或中值,第二个维度模拟离差,例如标准差或更稳健的版本。此外,为了检测趋势变化,我们可能需要额外的维度,这些维度对趋势的特征进行建模。

h(t)hnew(t)一样,也是*期数值的典范。也就是说,正如名字所暗示的那样, hnew (t)是一个比 h ( t )更*的值的模型。例如, h ( t )可能是慢速移动*均线, hnew ( t )可能是快速移动*均线。

现在假设时间序列中最*的值是异常的。假设我们知道这个事实。也就是说,异常被标记。我们可以在更新门 u (t)的值中捕捉到这一点,其中 t 是这些异常时间点之一。这使我们能够控制是否希望最*的值(我们知道是异常的)更新我们的“正常”模型。

例如,如果我们处于异常状态,我们可能不想改变我们的“常态”模型。我们可以通过将 u (t)的分量设置为接* 0 来实现这一点。如果我们处于“正常”区域,我们希望我们的常态模型更快地适应数据。

更新闸门方程

我们已经看到了如何使用更新门的值根据新内存和旧内存构造更新的内存。但是更新门的值本身是如何计算的呢?这是按如下方式完成的。

u ( t ) =乙状窦(Ax(t)+Bh(t-1)+C**)

这里 ABC 是可学习参数的矩阵和向量。

把所有的方程式放在一起

我们已经讨论了 GRU 内部的所有机制。让我们把所有的方程放在一起,回顾一下端到端的流程。在一个单一的时间 t 那就是。

**s**(*t*)    = sigmoid(**A*****x**(*t*) + **B*****h**(*t*-1) + **C**)
**hnew**(*t*) = tanh(**D*****x**(*t*) + **E***(**s**(*t*) o **h**(*t*-1)) + **F**)
**u**(*t*)    = sigmoid(**G*****x**(*t*) + **H*****h**(*t*-1) + **I**)
**h**(*t*)    = (**1**-**u**(*t*)) o **h**(*t*-1) + **u**(*t*) o **hnew**(*t*)

现在让我们一次完成端到端流程 t 。我们假设学习已经发生了。

新的输入 x ( t )在时间 t 到达。RNN 当前的存储状态是 h ( t -1)。首先,根据这两个值,我们计算过滤门的值 s ( t )。现在我们有了计算新内存的值 hnew ( t )所需的东西。所以我们这么做了。接下来,我们从 x ( t )和 h ( t -1)计算更新门的值 u ( t )。注意,计算 s ( t )和 u ( t )的方程具有相同的形式。不同的行为源于不同的学习参数。最后,我们使用更新门 u ( t )将旧内存 h ( t -1)和新内存 hnew ( t )结合起来,计算更新后的内存 h ( t )。

【学习】

要学习的参数是矩阵 ABDEGH 以及向量 CFI

我们有意将此部分的名称放在引号中。我们不会以通常的纯监督方式来描述学习,我们只会传达直觉,即如何从人类驱动的偏置和自我监督或监督的机器学习的某种组合中学习 GRU 中的各种机制。

我们将在异常检测示例中说明这些。在这个例子中,我们将对 GRU 做一些改动。也就是说,我们将适当地调整它的机制。我们的目的是通过一个例子提供对机制和变化的见解。

二对一:异常检测也解决预测

我们认为补充一点是有帮助的,即我们下面描述的异常检测方法中包含了某些时间序列预测任务。我们之所以要在这里提出这一点,是因为在描述如何使用(稍微做了调整的)GRU 来解决时间序列异常检测问题的过程中,我们也将隐含地涵盖如何解决时间序列预测问题。所以你可以用 RNNs 来解决这两个问题。

首先,异常未标记

我们得到一个时间序列。如果异常没有被标记,我们可以训练一个 GRU 来预测时间序列中的下一个值。这个过程迫使 GRU 学习一种(最*的)“常态”模式,随着“新常态”的发展而适应它。

h ( t )应该在时间 t 模拟“旧常态”。h 可以是多维的。例如,一个分量可以描述正常区域的*均值,另一个分量可以描述趋势。

hnew ( t )与 h ( t )类似,只是受最*值的影响更大。例如, h ( t )可能表现为较慢的均线, hnew ( t )可能表现为较快的均线。可能带有趋势成分,以便我们可以辨别 hnew ( t )的趋势是否不同于 h ( t )的趋势。

我们怎样才能让 GRU 明白, hnew ( t )应该比 h ( t )模拟更*的值?我们可以通过显式强制 hnew ( t )预测短期预测目标来学习 hnew ( t )方程中的参数。如 y ( t )等于 x ( t -1),即一步预测。

我们怎样才能使 h ( t )模型成为 hnew ( t )的一个适应较慢的变体,即在比 hnew ( t )更粗的时间尺度上模拟常态?(除了当我们想让 h ( t )去追赶 hnew ( t )的时候,比如“新常态”正在发展的时候。)

迫使 h ( t )移动得更慢的一个明智的方法是让它预测一个更长期的目标,即对于足够大的 k ,设置 y ( t )等于x(t-k)。虽然这是一个吸引人的想法,但所需要的架构是两个不同视野下相同输入的两个预测者。这不是 GRU。GRU 必须从单个目标学习它的所有参数,比如说 y ( t )等于 x ( t -1)。再加上这并不容纳例外,即有时我们希望 h ( t )去追 h ( t -1)。我们需要另一种机制来解决这个问题。

为了了解我们必须在 GRU 中处理什么,让我们再次写出状态更新方程

h(t)=(1-u(t))oh(t-1)+u(t)ohnew(t)

假设 h ( t -1)移动缓慢,并且 hnew ( t )与 h ( t -1)非常不同,我们会希望 h ( t )追逐 h ( t -1)我们可以通过将 u (t)的分量设置为接* 0 来实现这一点。但是怎么做呢?

首先,让我们再次写出更新门方程

u ( t ) =乙状结肠(Ax(t)+Bh(t-1)+C**)

如果我们修改它,使 hnew ( t -1)也出现在右边,会怎么样?

这将在原则上允许我们学习行为

IF **hnew**(*t*) is very different from **h**(*t*-1)
    set **u**(*t*) close to **0**
else
    set **u**(*t*) close to **1**

这也可能有助于模型更快地适应发展中的“新常态”。让我们用一个例子来说明这一点。

考虑一个电*移动,例如下面粗体值处的那个。

t: 1  2  3  4  5  6  7  8
x: 1  1  1  1  **4 ** 4  4  4

hnew (5)是 4。 h (4)为 1。所以我们希望 h(5)接* 1。我们将此解释为“我们还不知道 4 是暂时的异常还是新常态的存在,所以让我们的旧常态慢慢适应新值”。

随着我们继续向右移动, h ( t )将慢慢开始向 4 移动,即向 hnew ( t+ 1)移动。这将依次驱动 u ( t )朝向 1 ,这将进一步加速该运动,即产生滚雪球效应。

我们可以用下面这个电*移动的行为来总结这一点。在电*转换事件中,最初,旧模型移动缓慢,因为它还不知道这是电*转换。一旦有证据表明这确实是一个水*转换,这个模型就会加速向新常态移动。

另一方面,如果偏移是暂时异常(例如尖峰或下降),例如在下面的时间序列中

t: 1  2  3  4  5  6  7  8
x: 1  1  1  1  **4 ** 1  1  1

h 将始终保持接*旧常态。

特征工程

如果我们不喜欢修改更新门方程的想法呢?我们也许可以通过特征工程达到类似的效果。例如,通过处理时间序列的变换版本,例如x(t)-x(t-1)。这里的直觉是,这个时间序列更明确地揭示了原始时间序列发生变化的地方。一个可能更强大的变体是将我们的特征化时间序列定义为一个合适的快速移动*均值减去一个合适的慢速移动*均值

我们甚至可以想象一个滑动内核,它可以明确区分瞬时变化和更稳定的变化。如果该核函数以被视为瞬时事件的异常值为中心,则该核函数将具有高值,否则该核函数将具有低值。

有了这样一个内核,我们应该用它来生成特征或标签吗?前者意味着我们用特征向量(t)代替输入 x ( t ),其中一个特征是以 t 为中心的这个核函数的值。后者意味着我们基于这个内核函数在时间 t 的值来设置 y ( t )。

我们不会深入探讨这个问题,只是提出一些想法。使用核函数来生成标签很有吸引力,因为它们将显式地编码事件是短暂的还是更持久的,这正是我们异常检测 GRU 的正确教学信号。另一方面,我们必须考虑这种标记有偏差的风险。一般来说,标签偏向比特征偏向更受关注。标签偏见表现为“你在教模型错误的东西”。

异常被标注:人或计算机

现在,让我们深入学习当异常被人类、计算机或两者结合标记时的 GRU 参数。在本节中,异常是指暂时的异常。

我们可以用标签来设置 u ( t )。

*IF *x*(*t*) is labeled ‘anomalous’
  Set **u**(*t*) close to **0** // **Direct GRU to continue 'old normal'** ELSE 
  Set **u**(*t*) close to 1   // **Direct GRU to move towards 'most recent** // **values'***

请注意,我们已经直接控制了这里的更新门。

让我们看看如何引导 GRU 更接*‘最*值’。如果时间序列中的新值延续旧常态,那么更新也将延续旧常态。如果新的值正在创造一个不同的新常态,就像在我们的电*移动例子中,这将具有 GRU 快速适应它的效果。

好了,这就解决了什么时候更新“正常”和什么时候不更新的问题。但是如何更新两个模型——最*的最*的——他们自己呢?

对于我们的用例来说,重新安排 GRU 的各种机制是很诱人的。当然,我们失去了使用 GRU 作为黑匣子的能力。另一方面,我们学习这些机制的其他组合可以做什么。

我们将继续使用 h ( t )、 hnew ( t )和 u ( t )。 h ( t )和 hnew ( t )将各自学习预测 x ( t ),尽管是在不同的视界。所以每一个都会配备自己的目标y(t)=x(t+k1)对于 h ( t )和ynew(t)=x(t+

u ( t )将以前述方式从异常标签中设置。

该模型可以被视为混合了自我监督预测和监督异常检测。

过滤栅呢?

GRU 的机械装置怎么样?它能在这里得到有益的利用吗?首先,让我们提醒自己它实际上是做什么的。它在 x ( t )的上下文中投射出 h( t -1 )、的那些组件,这些组件与手头的任务相关。在我们的情况下就是检测异常。

实际上,在我们的引擎盖下,我们有另一项任务的两个实例:预测。因为我们已经在异常检测任务中使用了更新门(在预测模型之间切换),所以让我们尝试在预测任务本身中使用它。

预测和过滤门

我们寻求在某个水*上对 x ( t )的良好预测。这种模型保持描述当前“常态”的状态。这用一个可能的多维向量来表示。例如二维向量,其中一维捕捉最*值的*滑估计;第二个是该值的局部估计趋势。

这是一个物理“运动”类比。假设我们想要预测一个点在某个欧几里得空间中运动的未来位置。在这方面,当前位置和当前速度的统计估计是有帮助的。

在这种情况下,我们可以推测过滤门是如何发挥作用的。根据时间序列,“常态”状态的一些特征在我们的预测任务中可能比其他特征表现得更好。对于短期范围(如单步)和没有良好线性趋势的时间序列(尽管它可能有季节性),对最*值的估计可能是最好的预测。对于具有持久线性趋势的时间序列和更长的时间范围,“常态”状态的局部趋势维度可能非常具有预测性。

随着我们向“常态”状态模型添加更多维度,上一段的推理开始变得更加有力。例如各种季节性或滞后。

使用 s ( t )原则上可以选择出那些与当前任务相关的正常状态的组成部分。这起到了与预测模型中的特征选择或修剪类似的作用。这种修剪通常会有所帮助。这在理论上和经验上都是已知的。它迫使算法学习偏向简单的模型。简单的模型通常概括得更好。奥卡姆剃刀。

但是我们如何学习 s ( t )

好的,所以我们认为使用 s ( t )可以有所帮助。让我们更深入一点,看看我们如何才能学到我们希望 s ( t )能学到的东西。

我们将在时间序列预测的基本 RNN 中说明这一点。

我们从输入的 x ( t )中提取某些特征如其值,即 x ( t )本身,并滞后x(t)-x(t-k)对于 k= 1 2 (为了计算滞后,我们需要记住时间序列的先前值。)设 v ( t )表示 x ( t )的特征向量。状态向量 h ( t )反映了这个特征向量。例如, h 1( t )可能会建模一个*滑版本的 x ( t ), h 2( t )一个*滑版本的x(t)-x(t-1),等等。**

状态向量对时间序列值的特征进行建模,有助于预测其未来值。例如最*值的估计、最*趋势的估计以及可能的各种季节性。

RNN 现在可以表示为

***h**(*t*) = **f**(**h**(*t*-1),**v**(*t*))
*y*(*t*) = *g*(**h**(*t*))*

我们可以设定y(t)=x(t+h)为目标。也就是说,我们寻求时间序列 xh 步预测。

f 指定如何从先前的状态向量 h ( t -1)和新值 x ( t )的特征向量 v ( t )的组合中导出新的状态向量 h ( t )。

g 指定如何从当前状态向量 h ( t )中导出预测。例如,如果 h (t)只有两个特征:当前值的*滑估计和趋势的*滑估计,我们可以将第二个与从目标学习的参数相乘(这对于获得不同层位的影响特别有用,例如 h 是小还是大)并将第一个加到其上。在方程式中,这将是

**y*(*t*) = *h*1*(t*) + *b***h*2(*t*)*

右边的第二项模拟了对第一项的基于趋势的修正。

学习通过传播回预测误差并调整隐含在 gf 中的参数来进行。

那么我们应该如何将 s ( t )注入到混合中呢?首先,让我们彻底简化。让我们考虑一下

***h**(*t*) = a***h**(*t*-1) + (1-a)***v**(*t*)*

这对于预测来说并不幼稚。事实上,这就是基于指数*滑的预测者的工作方式。这里 af 中唯一可学习的参数。

请注意,这种方法也符合我们对 h ( t )的角色,作为 v ( t )的*滑版本。

现在我们准备注射 s ( t )。

***h**(*t*) = **s**(*t*)O **h**(*t*-1) + (1-**s**(*t*))o **v**(*t*)*

也就是说,

**hi*(*t*) = *si*(*t*)**hi*(*t*-1) + (1-*si*(*t*))**vi*(*t*)*

这个更新规则可能更丰富,因为我们现在对状态向量更新有了组件级的控制。在这个过程中,我们有效地获得了进行软特征选择的能力。

GRU 和消失梯度问题

消失梯度问题怎么办?GRU 会更坚决地反对吗?我们不会明确回答这个问题;相反,我们会给出一些诱人的暗示,告诉你可能会发生什么。

让我们首先写出 GRU 对基本 RNN 的状态更新方程。

***h**(t) = (**1**-**u**(t)) o **h**(t-1) + **u**(t) o **hnew**(t)  (GRU)
**h**(t) = sigmoid(**A*****h**(t-1) + **B*****x**(t) + **C**)      (Basic RNN)*

有什么跳出来了?第二个方程中的 sigmoid。从我们之前对消失梯度问题的讨论来看,似乎与类 sigmoid 传递函数有关。挤压函数的尾部斜率接*于零。这有助于误差梯度迅速消失,因为通过时间的反向传播会反向传播在输出多个时间段看到的误差,通过这些 sigmoids 链反向传播。

相比之下,GRU 的状态更新方程没有使用挤压非线性。

堆叠 rnn

既然我们对 GRU 和基本 RNN 有了更深入的了解,我们来看一个重要的概括。经过

考虑 RNN 的状态更新功能

h(t)=f(h*(t-1), x (t))*

在我们到目前为止看到的例子中(基本的 RNN 和 GRU),

f ( h,x)=S1(Whhh+Wxh**x

我们可以将此解读为“ h (t)是从 h (t-1)加上 x (t)在零隐层前馈架构中得到的”。

堆叠 RNN 只是在计算中添加了一个或多个隐藏层。也就是状态更新功能变‘深’了。毫不奇怪,这使得 RNN 架构更加丰富,通常在某些任务上表现得更好。

一个堆叠的 RNN 在时间中展开,看起来像这样

现在除了深度时间,我们还深度状态更新功能。我们现在有 L 个函数 f1,…,fL,它们有自己的可学习参数。我们可以这样写

f ( h( l ),h( l-1 ),L)=S1(Whh(L)h(L)+Wxh(L)**h()

其中 h (0)表示 x

时间 t 的状态表示本身更丰富。h(t)=(h(0, t ), h (1, t ),…, h (L, t )。这可以被视为按照粗糙度增加的顺序的状态的分层表示。如在深度前向神经网络中。

推论

接下来,我们谈谈推论。也就是说,我们如何使用一个训练有素的 RNN 来回答各种问题。

我们可以通过一个训练有素的 RNN 运行一系列单词 w 1、 w2 、…、 wn -1,并生成下一个可能单词的概率分布。通常,我们想要的不止这些。我们想要给定序列的某个长度 k 的最可能扩展。也就是说,我们想要

wnwn +1、…、wn+k-1 = arg max*wn*、 *wn* +1、…、*wn*+*k*-1P(【T77

这个推理问题叫做解码问题。当 k 为 1 时,解就是 RNN 将单词 w 1、 w2 、…、 wn -1 依次处理后,RNN 输出向量中概率最高的单词。对于一般情况下的 k ,解码问题比较棘手。也就是说,我们不能指望有效地找到最可能的扩展。所以我们求助于启发式方法。

贪婪解码

寻找长度 k 的一种简单方法是,首先在输出向量中找到概率最高的单词,将这个单词输入到 RNN(以便它输出下一个单词的概率分布),再次找到概率最高的单词,并重复这个过程。这种方法被称为贪婪,因为它在每次迭代中做出最佳的局部决策。

当在每一个贪婪的步骤中,在输出向量中添加概率最高的单词将我们推向全局最优解时,这种方法可以很好地工作。如下例所示。

示例:考虑一个根据国家、州和县公园名称训练的语言模型。考虑一下 x (1) = 黄石。贪拓会 x ^(2) = 国民

不足为奇的是,这种快乐的环境并不总是如此。如下例所示。

示例:考虑一个从多组组织名称中训练出来的语言模型。组织名称的例子有美国银行谷歌美国国立卫生研究院……术语多重集意味着组织名称可能在此列表中重复出现。现在考虑在这个列表中找到最受欢迎的组织名称的问题。贪婪方法的第一步是选择 bankthe 或列表中出现频率最高的单词。最流行的组织名称(比如说 Google )可能不是以这个第一个词开头。

光束搜索

如前所述,最优解码通常是困难的(NP-hard)。有许多启发式方法试图比贪婪解码做得更好,以不同的运行时间和内存需求为代价。Beam 搜索在序列间标记用例(尤其是语言翻译)中已经被证明是一种特别有吸引力的方法。这就是我们将在这里描述的。

波束搜索保留了 k 个最佳前缀序列。在每次迭代中,它考虑这些 k 前缀的所有可能的 1 步扩展,计算它们的概率,并形成迄今为止的 k 最佳前缀序列的新列表。它会一直持续下去,直到达到目标。在我们的场景中,这将是当扩展序列长度为 T 时。然后,它从其候选人列表中抽出得分最高的序列作为最终答案。

参考文献

  1. 统计语言模型。从简单到++以及用例… |作者 Arun Jagota
  2. CS 224d:NLP 的深度学习
  3. 神经网络语言模型
  4. 了解 LSTM 网络— colah 的博客
  5. 时间序列预测中的指数*滑法

神经机器翻译:内部工作,Seq2Seq 和变压器

原文:https://towardsdatascience.com/neural-machine-translation-inner-workings-seq2seq-and-transformers-229faff5895b?source=collection_archive---------6-----------------------

与传统的机器翻译模型相反,序列对序列模型能够在*行语料库的帮助下映射语言之间的关系。

翻译的注意力地图

介绍

最*,我有机会在一个学期项目中使用神经机器翻译(NMT)架构。玩最先进的模型很有趣。所以我决定写我的第一篇关于它的媒体文章,让对 NMT 感兴趣的人,或者更一般的机器学习+自然语言处理,受益并训练他们的定制模型。(对于西班牙语使用者,您可以参考参考资料中的链接。西班牙语词典:[7])

我将尽力涵盖以下主题:

  • 什么是机器翻译?****NMT如何尝试解决?
  • ****序列到序列架构是如何工作的?它能解决什么问题?
  • 最先进的 NMT(实际上是序列对序列)模型,主要是带有注意机制的 RNNs 和变压器(重点是注意机制自注意)。****
  • 什么是字节对编码** (BPE)?它如何帮助我们完成翻译任务?**
  • 如何评价 NMT 系统公司?注意力地图的可解释性。
  • 最后,我将展示如何使用附带的存储库来训练您的定制模型。

什么是机器翻译?****NMT如何尝试解决?

让我们首先确定我们试图与 NMT 解决的问题。我们可以将机器翻译任务视为对条件概率 P(y|x) 进行建模,其中 xy 分别指输入和输出句子。我们本质上想要实现的是,对于语言 X 中的给定句子 x ,我们想要找到另一种语言 Y 中的最佳句子 y 。我们可以把这个目标正式写成 Eq。1,也就是我们要找到最大化条件概率 P 的输出句子y(y|x)。我们可以使用贝叶斯规则将这个目标重写为 P(x|y)P(y)。

等式 1

这里 P( x | y )模拟翻译模型,即单词和短语如何翻译,P( y )模拟目标语言模型,即 Y 。我们可以将后一种概率视为给输出句子一个流畅性分数,例如 P(“我正在学习”)> P(“我正在学习”)。我们可以使用一些方法来创建一个语言模型 P( y )。更困难的问题是如何构建翻译模型 P( x | y )。我们可以利用包含大量句子对的翻译语料库。有尝试找到翻译模型的统计机器翻译方法。但这是一个微妙的问题。一种语言本身是复杂而模糊的,然而我们试图用另一种语言来表达一个句子的意思,即使是简单的句子也是很棘手的。考虑以下土耳其语的例子" yarn al ACA iam ",翻译过来就是"我明天会学习"。图 1 展示了这两个句子之间的对齐。

图 1: 多对一对齐

土耳其语是一种粘合性语言。因此,一个单词可能由几个后缀组成,这些后缀会显著影响句子的语义。在这个例子中,单词“al ACA m”可以分成以下记号:“al+acak+m”,对于简单的单词到单词的对应,分别指学习、will 和 I 。如你所见,提取这两个简单句子之间的关系甚至很困难。现在考虑一下,如果像中文这样更复杂的语言出现在游戏中会发生什么?

有一些统计机器翻译方法试图映射语言之间的关系。但这篇文章旨在解释神经机器翻译如何解决这个问题。提示:NMT 直接模拟 P( y | x )。

神经机器翻译和序列到序列

2014 年,Sutskever 等人提出了自然语言处理应用的序列对序列架构[1]。最初的架构由一对递归神经网络组成:(1)第一个 RNN 负责对输入序列进行编码,称为编码器,(2)第二个 RNN 获取编码向量并生成目标序列。注意,我们把输入和输出称为序列,而不是句子。是为了防止我们把自己仅仅局限在自然语言相关的问题上。图 2 显示了相应的架构,其中输入序列“A B C被映射到“W X Y Z ”。

图 2: 序列对序列架构[1]

我们可以在许多情况下利用序列到序列架构,例如

  • 摘要:给定一个长段落(例如,新闻、一本书的一章、一篇文章),生成它的摘要。
  • 机器翻译(咄!):给定一个来自源语言的句子,用另一种目标语言生成相应的句子。
  • 问答:给定一段文字和一个关于它的问题,为这个问题生成一个答案。
  • 语法错误纠正:给定一个可能有语法或拼写错误的句子,通过纠正错误来生成正确的句子。
  • 这个清单可以一直列下去。其他有趣的应用领域可以很容易地提出来,例如,给定一个哼唱→生成音乐,代码生成(不用担心软件人;模型产生的 bug 比我们多:p)。你可以提出的任何序列到序列的问题都可以用这个架构来建模。

我不会深入研究递归神经网络。因为有大量的资源解释它们是如何工作的。但简而言之,它们逐个符号地处理输入序列。"为什么不一次处理所有的代币?"你问。让我们继续讨论自然语言。显然,句子的顺序很重要。递归神经网络使我们能够对有序输入(如时间序列)进行建模。考虑下面这个函数:h= f(xt14】,h⁰ )其中 x 是第一个字,h⁰是初始隐藏状态。在处理下一个单词 x 时,我们有 h =f( x,h )。将先前的隐藏状态 h 考虑在内使得我们能够在对当前单词建模时使用过去的信息。你意识到我们传递给解码器的是什么了吗?如果输入的句子由 6 个单词组成,那么我们将通过第 6 个隐藏状态 h⁶。还有其他方法来增强这种表示,如双向 RNNs,长短期记忆,门控循环单位。但是让我们坚持最简单的情况。解码器现在有了可以用作初始隐藏向量 h⁰ 的编码向量,并开始解码输出句子。起初可能不清楚,但在架构中存在瓶颈。假设我们使用 128 维向量来表示隐藏单元。这意味着传递给解码器的编码向量也是 128- 维的,参见图 3。现在考虑两个输入句子,一个有几个简单的单词,另一个有复杂的单词和子句。用相同的维数对这两句话进行编码公*吗?测评分数说不是。那么我们如何克服这个问题呢?**

图 3: RNN 编码器和解码器

注意机制

如前所述,使用固定长度的向量会导致模型出现瓶颈。模型没有太多空间将信息从编码器传递到解码器,同时,反向传播不能完全向后传递梯度。为了缓解这种情况,Bahdanau 等人采用了注意机制,以便解码器可以在生成下一个令牌时查看相关的源令牌2。让我们用图 4 所示的例子来解释注意机制。根据前面的例子,我们有下面的输入句子。该模型已经生成了前三个令牌:【我将学习】,现在我们期待它生成【明天】。我们使用解码器的最后一个隐藏表示 u 以及输入令牌的隐藏表示[ h,h ]并计算它们之间的点积。到底什么是点积?它告诉我们两个向量有多少指向相同的方向→它们有多少相关性→相应的记号彼此有多相关。在这个非常具体的例子中,单词 tomorrow 与输入标记yarn*完全匹配,因此我们得到更高的点积分数。这些分数是未标准化的,因此我们通过一个 softmax 函数来传递它们,以获得输入令牌的最终概率分布。我们使用概率分布来获得输入令牌的加权和。在这里,最相关的令牌是亚龙;因此与第二个输入令牌相比,它具有相对较高的分数。然后,我们使用这个加权和来预测下一个令牌,而不是直接使用解码器隐藏表示。*****

图 4: 注意 RNN 编码器和解码器

注意机制显著提高了许多序列间应用的模型性能。但是人们并没有就此止步,更强有力的方法已经被提出。

变形金刚

Vaswani 等人看到了注意机制的效果,提出了神经机器翻译的这个模型[3](尽管它可以应用于其他 seq2seq 任务)。变换器在高层次上与前面的序列到序列模型相同,具有编码器-解码器对。编码器对输入序列进行编码,解码器生成输出序列。然而,他们发现了一种使用编码器内的注意力机制的方法,称为自我注意力机制。我们已经看到,注意力机制帮助我们在编码器-解码器对之间双向有效地传递信息。自我关注此外,帮助编码器更有效地编码序列。

图 5: 自我关注

图 5 说明了自我关注机制所需的步骤。让我们解释一下到底发生了什么:

  1. 我们有了输入序列德米尔约鲁,我们得到了标记德米尔约鲁的嵌入。我们将这些嵌入投射到三个独立的空间,即查询、键、。(项目是用矩阵相乘的奇特说法)****
  2. 我们获取特定令牌的查询向量,并计算该查询向量与所有关键向量之间的点积。这是对输入序列中所有标记的查询向量进行的。人们把这个过程称为一个令牌的查询向量兼顾其他令牌*** 。你已经意识到什么了吗?我们不需要前一个令牌的隐藏状态来计算当前令牌的隐藏状态。这意味着我们可以为输入序列中的所有记号并行运行自我关注。这大大加快了训练和推理时间。*****
  3. 现在我们有了输入序列中每个标记对之间的原始分数。我们将它们通过 softmax 层,以便标准化分数。
  4. softmax 层的输出是输入令牌的概率分布。我们使用这些标准化分数来获得向量的加权和(为每个令牌单独计算)。

更具体地说,假设位置 i 处的令牌与位置 j 处的另一个令牌密切相关。我们期望令牌 i 的查询向量和令牌 j 的密钥向量之间的点乘积比其他无关令牌更大。这意味着在随后的步骤中,标记 j 将在构造标记 i 的输出表示时具有更大的影响。我们可以称输出表示为上下文单词嵌入。因为表示是相对于上下文创建的。理想情况下,我们会期望下面两句话中 这个词的上下文嵌入是不一样的:(1)我在开门的时候弄坏了。(2)演讲中的要点不清楚。****

字节对编码

在进入翻译部分之前,我认为先谈谈 BPE 的方法是有益的。NMT 系统面临的最大问题之一是词汇量不足(OOV)。我们知道我们对词汇表中的每个单词都使用了嵌入。假设我们使用 512 维向量来嵌入土耳其语单词。与最先进的模型相比,512 维的向量实际上并不算大。正如我们前面说过的,土耳其语是粘合性的,它在形态上相当复杂。通过引入后缀来派生新词是相当容易的。考虑下面这个单词"凝胶",意思是"来"。我们可以很容易地生成以下词语:“gel+ECEé+im”表示“我会来的”。如果我们要引入一个全新的单词,每一次在一个现有的单词后面添加一个后缀,词汇量将很容易超过 300K 。假设我们使用单精度浮点格式来存储向量。那就意味着光是字嵌入矩阵就需要 300,000 * 512 * 4 字节或者 ~600 MB 的存储空间,更不用说模型的其余部分了。BPE 方法在大型文本语料库的帮助下,以无监督的方式学习这些后缀和语素。BPE 方法最初是作为一种压缩算法提出的。但是森里奇等人有一个绝妙的主意,用它来解决 OOV 问题4。对于 BPE 来说,单词“geleceim”最好被标记为*“geleceim”。*****

用自回归模型进行转换

到目前为止,我们已经了解了序列到序列模型的来龙去脉。但是实际的翻译是如何进行的呢?让我们使用图 6 所示的翻译示例。我们有输入序列“d ark mak ijin hava souk deil mi?”。为了简化幻灯片,我合并了相关的 BPE 令牌。回到这个例子,我们用 Transformer 编码器对输入序列进行编码。一旦我们完成了,我们用一个人工令牌 < start > 给变压器解码器,让它生成下一个令牌。解码器使用初始令牌以及输入序列令牌来开始生成目标令牌。它生成的第一个令牌是“ it”。这一次我们使用解码器的输出,即“it”,并向它提供先前的令牌,并期望它生成下一个令牌。这个过程继续进行,直到模型生成另一个人工标记,即 < eos > (代表句尾)来指示翻译完成。****

图 6: 自回归*移

注意力地图

现在,为什么箭头的粗细在*移过程中的每一步都会发生变化?这是注意力机制的优势之一。深度学习有如此多的内部机制有待解释清楚。大多数系统仍被视为黑匣子。我们知道他们擅长提取更高级更复杂的表示。但是我们不确定为什么他们在某些情况下决定了一些事情。注意力机制稍微缓解了这个问题,并为模型带来了一些可解释性。在翻译过程中的每一步,我们都知道在特定时间步生成令牌时,哪些输入令牌最有影响力。我们可以利用这些信息来推断单词之间的关系。**

图七:注意地图

图 7 显示了图 6 所示翻译示例的注意力图。列对应于输入序列,行对应于生成的序列。每一行属于一个特定的时间步长。例如,对应于“冷”4 行主要受输入令牌“hava souk”的影响。正如我们将在结果部分看到的,Transformer 架构采用了多个注意力头。因此,我们最终得到了多个注意力地图。**

结果

我们应该如何评价一个神经机器翻译系统?想想那个著名的例子“我做了她的鸭子”。你会如何翻译这句话?以下是一些翻译:**

  • 我给她做了一只鸭子。
  • 我做了一只属于她的鸭子。
  • 我做了一只(玩具)鸭子给她。
  • 我把她变成了一只鸭子。(魔法)
  • 我把她变成了鸭子(作为动词)。(有东西在靠*)

我想说的是,自然语言是模糊的。指望机器完全理解它,而人类却在努力相互理解,这是不公*的。回到问题,你会如何评价这个翻译?注释器本身是有偏见的,并假设在创建数据集时;她饿了。于是她用第一句话来翻译句子。我们的模型,后来,产生了一个其他的选项,都是正确的,因为我们不知道这里的上下文。显然,精确匹配是非常幼稚的,因为它甚至会因为一个不同的单词选择而惩罚整个翻译。或者,人们大多使用 BLEU(双语评价替角)评分。它在【0,1】,之间产生一个分数,在某些情况下,为了方便起见,我们用乘以 100* 。它使用 n 元语法(主要是 1、2、3 和 4)来评估翻译,并使用一些额外的内部技巧。但是这个评估机制在这个例子中也可能会稍微失败。总的来说,评估一个 NMT 系统是一个微妙的问题,人们应该预料到 BLEU 分数的增加并不一定意味着翻译质量的提高。您可以在表 1 中找到在这个项目中所做的实验的结果,其中将带有 GRU 的 seq2seq 模型与 Transformer 模型进行了比较。数据集不包含很长的句子,所以任务相当简单。但是,即使只有一半的参数大小,Transformer 模型也能够比基线模型实现得更好。***

表 1:seq 2 seq 与 RNNs 和变压器的对比

实验

这是我想象过的一些注意力地图。您可以查看不同的矩阵,以了解模型如何以不同的方式处理输入序列。

  • 输入:gelemeyecekmiz。 输出: 我们来不了了。**
  • 输入:otobüsüka RS AK tren le gidebiliriz。 输出: 如果错过了公交车,我们可以坐火车去。**
  • 输入:Tom dün gece arabay ok hzl kulland。ecel ter leri dktüm 输出: 汤姆昨晚用车很快。我洒了很多黄油。😃**
  • 输入:Tom dün gece arabay ok hzl kulland。bu yüzden ona ok k \zd \u m . 输出: 汤姆昨晚用车很快,我很生他的气。**
  • 输入:geen gün park ta k pek gr dum . Bir an Bana sald racak sandm . 输出: 我昨天在公园看到一只狗,我以为它会攻击我。**

图 8: 变压器注意图

写下一篇文章的每一个细节并不容易。但是如果你对这篇文章感兴趣,并且想更深入地了解这个话题,下面的列表将是一个很好的开始阅读的起点:

  1. Sutskever 等人的 Seq2seq 论文“用神经网络进行序列间学习”[1]。
  2. Bahdanau 等人的注意机制“通过联合学习对齐和翻译的神经机器翻译”2
  3. BPE 和子词单元,由森里奇等人所著,《带有子词单元的稀有词的神经机器翻译》4.
  4. 瓦斯瓦尼等人的《变形金刚》,“注意力是你所需要的一切”[3]。
  5. 斯坦福 CS224n:深度学习的自然语言处理

训练自定义变压器 NMT 模型

我将提供源代码、使用的数据集、标记器和一个经过训练的模型,供对这个主题感兴趣的人使用。你可以在https://github.com/azadyasar/NeuralMachineTranslation知识库阅读更多关于如何培训、评估和翻译的细节。

资料组

一个英语-土耳其语*行语料库被用作数据集。数据集是由[5]从 Tatoeba 网站上提取的。数据集由大约 50 万对句子组成。我们有一个想法,如何通过使用电影字幕来扩大数据集的大小。但是我们没有足够的时间去做这件事。对于所有的实验,我们将数据集分别分成大小为 416,038,46,227 和 51,363 的训练集、验证集和测试集。

因为数据集不是很大;它包含在存储库中的数据/ 文件夹下。当您解压缩压缩文件时,您将获得三个独立的 tsv 文件,分别对应于训练、验证和测试数据集。**

字节对编码记号赋予器

这些记号赋予器是记号化输入和输出序列所必需的。我们也在数据/ 文件夹中提供它们。以结尾的文件。型号是以结尾的分词器型号和文件。vocab* 包含特定记号赋予器的词汇表。如果你有一个更大更相关的语料库并且愿意训练你的自定义标记器。使用 train_bpe.py 脚本。***

培养

下面是训练自定义模型的命令。它会自动检测是否有可用的 GPU,并使用一个可用的。否则,它将使用不推荐的 CPU。

训练部

一旦模型顺利开始训练,您应该会看到以下日志。

培训日志

评估和翻译

您可以使用以下命令评估已训练的模型。我们需要模型超参数在加载前首先构建它。所以请确保它们与实际相符。

发出以下命令来交互式翻译句子。

运行翻译脚本时,系统会提示您键入一个句子,如下所示:

互动翻译

结论

我希望这篇文章是有帮助和信息的。我将很快在资源库中提供一个新的 RNN +注意力模型实现。如果你遇到任何错误,或者有什么不对劲的地方,让我知道,这样我也可以试着弥补它们。

参考

  1. 伊利亚·苏茨基弗、奥里奥尔·维尼亚尔斯和阔克·V·勒。用神经网络进行序列间学习。在 Z. Ghahramani、M. Welling、C. Cortes、N. Lawrence 和 K. Q. Weinberger 编辑的《神经信息处理系统进展》,第 27 卷,第 3104-3112 页。柯伦联合公司,2014 年。
  2. Dzmitry Bahdanau、Kyunghyun Cho 和 Yoshua Bengio。通过联合学习对齐和翻译的神经机器翻译。更正,abs/1409.0473,2015 年。
  3. Ashish Vaswani、Noam Shazeer、Niki Parmar、Jakob Uszkoreit、Llion Jones、Aidan Gomez、Lukasz Kaiser 和 Illia Polosukhin。你需要的只是关注。在 I. Guyon、U. V. Luxburg、S. Bengio、H. Wallach、R. Fergus、S. Vishwanathan 和 R. Garnett 编辑的《神经信息处理系统进展》,第 30 卷,第 5998-6008 页。柯伦联合公司,2017 年。
  4. 里科·森里奇、巴里·哈多和亚历山德拉·伯奇。具有子词单元的生僻字的神经机器翻译。《计算语言学协会第 54 届年会论文集》(第 1 卷:长篇论文),第 1715-1725 页,德国柏林,2016 年 8 月。计算语言学协会。
  5. 雅各布·乌兹科雷特。制表符分隔的双语句子对【http://www.manythings.org/anki/,】于 2021 年 1 月 30 日到达。
  6. https://github.com/azadyasar/NeuralMachineTranslationNMT 变压器实施
  7. trad ucción a espa ol aquí:https://www . ibidemgroup . com/edu/trad ucci on-automatica-neuron-seq 2 seq-transformers/

使用 Seq2Seq 架构和注意力的神经机器翻译

原文:https://towardsdatascience.com/neural-machine-translation-using-a-seq2seq-architecture-and-attention-eng-to-por-fe3cc4191175?source=collection_archive---------23-----------------------

实践教程

基于 Tensorflow 和 Keras 的深度学习应用

1.介绍

神经机器翻译(NMT)是一种用于自动翻译的端到端学习方法【1】。它的优势在于它直接学习从输入文本到相关输出文本的映射。它已被证明比传统的基于短语的机器翻译更有效,传统的基于短语的机器翻译需要更多的努力来设计模型。另一方面,NMT 模型的训练成本很高,尤其是在大规模翻译数据集上。由于使用了大量的参数,它们在推理时也要慢得多。其他限制是它在翻译罕见单词和无法翻译输入句子的所有部分时的鲁棒性。为了克服这些问题,已经有一些解决方案,比如利用注意机制复制生僻字【2】

通常,NMT 模型遵循通用的序列到序列学习架构。它由一个编码器和一个解码器递归神经网络(RNN)组成(关于如何设置 RNN 的简单示例,请参见【3】)。编码器将输入句子转换成向量列表,每个输入一个向量。给定这个列表,解码器一次产生一个输出,直到产生特殊的句子结束标记。

我们的任务是使用中等规模的示例对语料库,为英语输入句子生成葡萄牙语翻译。我们使用序列到序列架构来构建我们的 NMT 模型。对于编码器 RNN,我们使用一种预训练的嵌入,一种在英文 Google News 200B 语料库【4】上训练的基于令牌的文本嵌入。另一方面,我们在解码器 RNN 中训练自己的嵌入,词汇量设置为语料库中唯一葡萄牙语单词的数量。由于模型的复杂架构,我们实现了一个定制的训练循环来训练我们的模型。

本文使用了一个由 170,305 对英语和葡萄牙语句子组成的数据集【5】。这些数据来自 Tatoeba.org,一个由志愿者翻译成多种语言的大型例句数据库。

和往常一样,代码和数据也可以在我的 GitHub 上获得。

本文属于使用 TensorFlow 进行深度学习的系列文章:

2.预处理

我们首先在葡萄牙语的每个句子中添加两个特殊的记号,一个<start><end>记号。它们被用来向解码 RNN 发送一个句子的开始和结束的信号。接下来,我们标记葡萄牙语句子,并用零填充句子的结尾。

import pandas as pd
import numpy as np
import tensorflow as tf
import tensorflow_hub as hub
from sklearn.model_selection import train_test_split
from tensorflow.keras.layers import Layer
import matplotlib.pyplot as pltNUM_EXAMPLES = 100000
data_examples = []
with open('por.txt', 'r', encoding='utf8') as f:
    for line in f.readlines():
        if len(data_examples) < NUM_EXAMPLES:
            data_examples.append(line)
        else:
            break

df = pd.DataFrame(data_examples, columns=['all'])
df = df['all'].str.split('\t', expand=True)

df.columns = columns=['english', 'portuguese', 'rest']

df = df[['english', 'portuguese']]

df['portuguese'] = df.apply(lambda row: "<start> " + row['portuguese'] + " <end>", axis=1)

tokenizer = tf.keras.preprocessing.text.Tokenizer(filters='')

tokenizer.fit_on_texts(df['portuguese'].to_list())

df['portuguese_tokens'] = df.apply(lambda row: 
                        tokenizer.texts_to_sequences([row['portuguese']])[0], axis=1)

# Print 5 examples from each language

idx = np.random.choice(df.shape[0],5)

for i in idx:
    print('English')
    print(df['english'][i])

    print('\nportuguese')
    print(df['portuguese'][i])
    print(df['portuguese_tokens'][i])
    print('\n----\n')

portuguese_tokens = tf.keras.preprocessing.sequence.pad_sequences(df['portuguese_tokens'].to_list(),
                                                 padding='post',
                                                 value=0)English
Have you ever taken singing lessons?

portuguese
<start> Você já fez aulas de canto? <end>
[1, 10, 60, 100, 1237, 8, 19950, 2]

----

English
Tom rode his bicycle to the beach last weekend.

portuguese
<start> O Tom foi à praia de bicicleta no último fim de semana. <end>
[1, 5, 3, 34, 61, 1243, 8, 696, 28, 869, 551, 8, 364, 2]

----

English
I have to go to sleep.

portuguese
<start> Tenho que ir dormir. <end>
[1, 45, 4, 70, 616, 2]

----

English
I have already told Tom that Mary isn't here.

portuguese
<start> Eu já disse a Tom que Maria não está aqui. <end>
[1, 7, 60, 50, 9, 3, 4, 106, 6, 13, 88, 2]

----

English
If Tom was hurt, I'd know it.

portuguese
<start> Se Tom estivesse ferido, eu o saberia. <end>
[1, 21, 3, 602, 10016, 7, 5, 16438, 2]

----

2.1 预训练嵌入层

对于编码器和解码器 rnn,我们需要定义嵌入层来将我们的单词索引转换成固定大小的密集向量。对于解码器 RNN,我们训练自己的嵌入。对于编码器 RNN,我们使用来自 Tensorflow Hub 的预训练英语单词 embedding。这是一个基于标记的文本嵌入,在英文谷歌新闻 200B 语料库上训练。它允许我们利用在非常大的语料库上训练的单词表示,遵循迁移学习的原则(参见【6】的扩展定义和对计算机视觉的迁移学习应用)。在把英语句子输入 RNN 之前,我们对它们进行了填充。

# Load embedding module from Tensorflow Hub

embedding_layer = hub.KerasLayer("https://tfhub.dev/google/tf2-preview/nnlm-en-dim128/1", 
                                 output_shape=[128], input_shape=[], dtype=tf.string)maxlen = 13def split_english(dataset):
    dataset = dataset.map(lambda x, y: (tf.strings.split(x, sep=' '), y))
    return dataset

def filter_func(x,y):
    return (tf.math.less_equal(len(x),maxlen)) 

def map_maxlen(x, y):
    paddings = [[maxlen - tf.shape(x)[0], 0], [0, 0]]
    x = tf.pad(x, paddings, 'CONSTANT', constant_values=0)
    return (x, y)

def embed_english(dataset):
    dataset = dataset.map(lambda x, y: (embedding_layer(x), y))
    return datasetenglish_strings = df['english'].to_numpy()
english_string_train, english_string_valid, portuguese_token_train, portuguese_token_valid = train_test_split(english_strings, portuguese_tokens, train_size=0.8)

dataset_train = (embed_english(
                        split_english(
                            tf.data.Dataset.from_tensor_slices((english_string_train, portuguese_token_train)))
                                                                .filter(filter_func))
                                                                .map(map_maxlen)
                                                                .batch(16))
dataset_valid = (embed_english(
                        split_english(
                            tf.data.Dataset.from_tensor_slices((english_string_valid, portuguese_token_valid)))
                                                                .filter(filter_func))
                                                                .map(map_maxlen)
                                                                .batch(16))

dataset_train.element_spec(TensorSpec(shape=(None, None, 128), dtype=tf.float32, name=None),
 TensorSpec(shape=(None, 35), dtype=tf.int32, name=None))# shape of the English data example from the training Dataset
list(dataset_train.take(1).as_numpy_iterator())[0][0].shape(16, 13, 128)# shape of the portuguese data example Tensor from the validation Dataset
list(dataset_valid.take(1).as_numpy_iterator())[0][1].shape(16, 35)

3.编码器递归神经网络

编码器网络是一个 RNN,其工作是将一系列向量 x =(x_1,…,x_T)读入向量 c ,这样:

其中 h_t 为时间 t 的隐藏状态, c 为隐藏状态序列生成的向量, fq 为非线性函数。

在定义我们的编码器网络之前,我们引入了一个学习英语语料库的结束标记的 128 维表示(嵌入空间的大小)的层。因此,RNN 的输入维数增加了 1。RNN 由 1024 个单位的长短期记忆(LSTM)层组成。填充值在 RNN 中被屏蔽,因此它们被忽略。编码器是一个多输出模型:它输出 LSTM 层的隐藏状态和单元状态。LSTM 层的输出不用于序列间架构。

class EndTokenLayer(Layer):

    def __init__(self, embedding_dim=128, **kwargs):
        super(EndTokenLayer, self).__init__(**kwargs)
        self.end_token_embedding = tf.Variable(initial_value=tf.random.uniform(shape=(embedding_dim,)), trainable=True)

    def call(self, inputs):
        end_token = tf.tile(tf.reshape(self.end_token_embedding, shape=(1, 1, self.end_token_embedding.shape[0])), [tf.shape(inputs)[0],1,1])
        return tf.keras.layers.concatenate([inputs, end_token], axis=1)end_token_layer = EndTokenLayer()inputs = tf.keras.Input(shape=(maxlen, 128))
x = end_token_layer(inputs)
x = tf.keras.layers.Masking(mask_value=0)(x)
whole_seq_output, final_memory_state, final_carry_state = tf.keras.layers.LSTM(512, return_sequences=True, return_state=True)(x)
outputs = (final_memory_state, final_carry_state)encoder_model = tf.keras.Model(inputs=inputs, outputs=outputs, name="encoder_model")
encoder_model.summary()Model: "encoder_model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 13, 128)]         0         
_________________________________________________________________
end_token_layer (EndTokenLay (None, 14, 128)           128       
_________________________________________________________________
masking (Masking)            (None, 14, 128)           0         
_________________________________________________________________
lstm (LSTM)                  [(None, 14, 512), (None,  1312768   
=================================================================
Total params: 1,312,896
Trainable params: 1,312,896
Non-trainable params: 0
_________________________________________________________________inputs_eng = list(dataset_train.take(1).as_numpy_iterator())[0][0]memory_state, carry_state = encoder_model(inputs_eng)

4.注意力

我们将要使用的注意力机制是由【7】提出的。使用注意机制的主要区别在于,我们增加了模型的表达能力,尤其是编码器组件。它不再需要将源句子中的所有信息编码成一个固定长度的向量。上下文向量 c_i 然后被计算为:

权重 α_ij 计算如下

其中 e_ij=a(s_i-1,h_j) 是位置 j 周围的输入与位置 i 处的输出匹配程度的分数。

图 1:局部注意力模型——该模型首先预测当前目标单词的单个对齐位置 p_t 。然后,以源位置 p_t 为中心的窗口被用于计算上下文向量 c_t,即窗口中源隐藏状态的加权*均值。从当前目标状态 h_t 和窗口中的那些源状态 h_s 推断出权重 a_t。改编自【8】

**class** **Attention**(tf.keras.layers.Layer):
    **def** __init__(self, units):
        super(Attention, self).__init__()
        self.W1 = tf.keras.layers.Dense(units)
        self.W2 = tf.keras.layers.Dense(units)
        self.V = tf.keras.layers.Dense(1)

    **def** call(self, hidden_states, cell_states):
        hidden_states_with_time = tf.expand_dims(hidden_states, 1)

        score = self.V(tf.nn.tanh(
            self.W1(hidden_states_with_time) + self.W2(cell_states)))

        attention_weights = tf.nn.softmax(score, axis=1)

        context_vector = attention_weights * cell_states
        context_vector = tf.reduce_sum(context_vector, axis=1)

        **return** context_vector, attention_weights

5.解码器递归神经网络

给定上下文向量 c 和所有先前预测的字 y_1,…,y_t-1 ,解码器被训练来预测下一个字 y_t ,使得:

其中 y =(y_1,…,y_T)。我们使用 RNN,这意味着每个条件概率被建模为

其中 g 是非线性函数 s_t 是 RNN 的隐藏状态。

对于解码器 RNN,我们定义了一个嵌入层,其词汇大小设置为唯一葡萄牙语标记的数量。在该嵌入层之后是具有 1024 个单元的 LSTM 层和具有与独特葡萄牙语令牌的数量相等的单元数量且没有激活功能的密集层。请注意,尽管网络相当浅,因为我们只使用了一个递归层,我们最终有* 24M 的参数进行训练。

import json
word_index = json.loads(tokenizer.get_config()['word_index'])

max_index_value = max(word_index.values())class decoder_RNN(tf.keras.Model):
    def __init__(self, **kwargs):
        super(decoder_RNN, self).__init__()
        self.embed = tf.keras.layers.Embedding(input_dim=max_index_value+1, output_dim=128, mask_zero=True)
        self.lstm_1 = tf.keras.layers.LSTM(1024, return_sequences=True, return_state=True)
        self.dense_1 = tf.keras.layers.Dense(max_index_value+1)
        self.attention = Attention(1024)def call(self, inputs, training=False, hidden_state=None, cell_state=None):
        context_vector, attention_weights = self.attention(hidden_state, cell_state)
        x = self.embed(inputs)
        x = tf.concat([tf.expand_dims(context_vector, 1), x], axis=-1)x, hidden_state, cell_state = self.lstm_1(x)
        x = self.dense_1(x)
        return xdecoder_model = decoder_RNN()decoder_model(inputs = tf.random.uniform((16, 1)), hidden_state = memory_state, cell_state = carry_state)
decoder_model.summary()Model: "decoder_rnn" _________________________________________________________________ Layer (type)                 Output Shape              Param #    ================================================================= embedding_1 (Embedding)      multiple                  1789568    _________________________________________________________________ lstm_3 (LSTM)                multiple                  6819840    _________________________________________________________________ dense_4 (Dense)              multiple                  14330525   _________________________________________________________________ attention_1 (Attention)      multiple                  1051649    ================================================================= Total params: 23,991,582 
Trainable params: 23,991,582 
Non-trainable params: 0 
_________________________________________________________________

6.培养

为了训练一个具有序列到序列架构的模型,我们需要定义一个定制的训练循环。首先,我们定义了一个函数,将葡萄牙语语料库分成输入和输出张量,然后输入到解码器模型。其次,我们创建了完整模型的向前和向后传递。我们将英文输入传递给编码器,以获得编码器 LSTM 的隐藏和单元格状态。这些隐藏和单元状态随后与葡萄牙语输入一起被传递到解码器。我们定义了损失函数,该函数是在解码器输出和先前分离的葡萄牙语输出之间计算的,并且计算了关于编码器和解码器可训练变量的梯度。最后,我们将训练循环运行了规定数量的时期。它遍历训练数据集,从葡萄牙语序列创建解码器输入和输出。然后,它计算梯度并相应地更新模型的参数。

模型训练起来相当慢,即使使用 GPU 也是如此。回想一下,我们甚至没有在任何 rnn 中堆叠层,这将减少我们的损失,但同时,使我们的模型更难训练。我们可以从下面的图中看到,训练和验证都随着时间的推移而稳步减少。

def portuguese_input_output(data):
    return (tf.cast(data[:,0:-1], tf.float32), tf.cast(data[:,1:], tf.float32))optimizer_obj = tf.keras.optimizers.Adam(learning_rate=0.001)
loss_obj = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)[@tf](http://twitter.com/tf).function
def grad(encoder_model, decoder_model, english_input, portuguese_input, portuguese_output, loss):
    with tf.GradientTape() as tape:
        loss_value = 0
        hidden_state, cell_state = encoder_model(english_input)
        dec_input = tf.expand_dims([word_index['<start>']] * 16, 1)# Teacher forcing - feeding the target as the next input
        for t in range(1, portuguese_output.shape[1]):
            predictions = decoder_model(dec_input, hidden_state = hidden_state, cell_state = cell_state)loss_value += loss(portuguese_output[:, t], predictions)# using teacher forcing
            dec_input = tf.expand_dims(portuguese_output[:, t], 1)grads = tape.gradient(loss_value, encoder_model.trainable_variables + decoder_model.trainable_variables)
    return loss_value, gradsdef train_model(encoder_model, decoder_model, num_epochs, train_dataset, valid_dataset, optimizer, loss, grad_fn):
    inputs = (14,)
    train_loss_results = []
    train_loss_results_valid = []
    for epoch in range(num_epochs):
        start = time.time()epoch_loss_avg = tf.keras.metrics.Mean()

        for x, y in train_dataset:
            dec_inp, dec_out = portuguese_input_output(y)
            loss_value, grads = grad_fn(encoder_model, decoder_model, x, dec_inp, dec_out, loss)
            optimizer.apply_gradients(zip(grads, encoder_model.trainable_variables + decoder_model.trainable_variables))
            epoch_loss_avg(loss_value)train_loss_results.append(epoch_loss_avg.result())

        print("Epoch {:03d}: Loss: {:.3f}".format(epoch,
                                                  epoch_loss_avg.result()))
        print(f'Time taken for 1 epoch {time.time()-start:.2f} sec\n')
    return train_loss_resultsnum_epochs=15
train_loss_results = train_model(encoder_model, decoder_model, num_epochs, dataset_train, dataset_valid, optimizer_obj, loss_obj, grad)plt.plot(np.arange(num_epochs), train_loss_results)
plt.ylabel('loss')
plt.xlabel('epoch');

图 2:seq 2 seq 模型几个时期的损失演变。

7.结果

为了测试我们的模型,我们定义了一组英语句子。为了翻译句子,我们首先预处理和嵌入句子,就像我们处理训练集和验证集一样。接下来,我们通过编码器 RNN 传递嵌入的句子,以获得隐藏和单元格状态。从特殊的"<start>"令牌开始,我们使用该令牌和编码器网络的最终隐藏和单元状态从解码器获得一步预测和更新的隐藏和单元状态。之后,我们创建了一个循环来获得下一步预测,并使用最*的隐藏和单元状态从解码器更新隐藏和单元状态。当发出"<end>"标记或句子达到定义的最大长度时,循环终止。最后,我们将输出的令牌序列解码成葡萄牙语文本。

获得的翻译相当不错。一个有趣且更复杂的例子是输入‘你还在家吗?’。一个问题有非常清晰的语法规则,其中一些是特定于语言的。返回的翻译‘你在家吗?’表明该模型能够捕捉这些特异性。

english_test = ['that is not safe .',  
                'this is my life .',  
                'are you still at home ?',  
                'it is very cold here .']english_test_emb = embed_english(split_english(tf.data.Dataset.from_tensor_slices((english_test, portuguese_token_train[:len(english_test),:])))).map(map_maxlen).batch(1)total_output=[]

for x, y in english_test_emb:
    hidden_state, cell_state = encoder_model(x)
    output_decoder = decoder_model(inputs = np.tile(word_index['<start>'], (1, 1)), hidden_state = hidden_state, cell_state = cell_state)
    output=[]
    output.append(output_decoder)
    for i in range(13):
        if tf.math.argmax(output_decoder, axis=2).numpy()[0][0] == 2: # <end> character
            break
        output_decoder = decoder_model(inputs = tf.math.argmax(output_decoder, axis=2), hidden_state = hidden_state, cell_state = cell_state)
        output.append(output_decoder)
    total_output.append(output)total_output_trans = []
for j in range(test_size):
    output_trans = []
    for i in range(len(total_output[j])):
        output_trans.append(tf.math.argmax(total_output[j][i], axis=2).numpy()[0][0])
    total_output_trans.append(output_trans)output_trans = np.array([np.array(xi) for xi in total_output_trans], dtype=object)portuguese_trans_batch=[]
inv_word_index = {v: k for k, v in word_index.items()}
for i in range(output_trans.shape[0]):
    portuguese_trans_batch.append(' '.join(list(np.vectorize(inv_word_index.get)(output_trans[i]))))list(english_test)['that is not safe .',  
 'this is my life .',  
 'are you still at home ?',  
 'it is very cold here .']portuguese_trans_batch['nao e seguro .',  
 'e a minha vida .',  
 'ainda esta em casa ?',  
 'muito frio aqui .']

8.结论

NMT 模型的架构非常具有挑战性,需要大量的定制工作,例如在其培训过程中。当在非常大的语料库中使用预先训练的嵌入来嵌入英语序列时,我们使用迁移学习的原理。另一方面,我们为用作解码器网络输入的葡萄牙语开发了自己的嵌入功能。编码器和解码器 rnn 保持尽可能简单,因为训练该模型在计算上是昂贵的。

我们生成了从英语文本到葡萄牙语的翻译,除了提供英语和葡萄牙语的句子对来训练我们的模型之外,没有提供任何东西。该模型理解肯定和否定,重要的语法区别,如在建立一个疑问类型的从句时,并能够解释语法规则,如英语中常用的主语-助词倒装,不能直接翻译成葡萄牙语。

这种方法可以通过增加模型的深度和每层中单元的数量来扩展。可以调整批量大小等超参数来提高准确性。还可以测试更广泛的注意力策略。

保持联系: LinkedIn

9.参考

【1】【吴等人,2016】吴、y、舒斯特、m、陈、z、乐、qv、、m、马切里、w、克里昆、m、曹、y、高、q、马切里、k、克林纳、j、沙阿、a、约翰逊、m、刘、x、祖卡斯凯泽、Gouws、s、加藤、y、工藤、t、和泽、h、史蒂文斯、k、库连、g、帕蒂尔、n、王谷歌的神经机器翻译系统:弥合人类和机器翻译之间的差距。

【2】【让等人,2015】让,s .,乔,k .,梅米塞维奇,r .,本吉奥,Y. (2015)。使用超大目标词汇进行神经机器翻译。

【3】https://towardsdatascience . com/generating-text-with-recurrent-neural-networks-on-the-work-of-f-pes SOA-1e 804d 88692d

【4】https://tfhub.dev/google/tf2-preview/nnlm-en-dim128

【5】https://www.kaggle.com/luisroque/engpor-sentence-pairs】T2

【6】https://towards data science . com/transfer-learning-and-data-augmentation-applied-to-the-Simpsons-image-dataset-e 292716 FBD 43

[7] [Bahdanau 等人,2016 年]bahda nau d . Cho k .和 beng io y .(2016 年)。通过联合学习对齐和翻译的神经机器翻译。

[8] [Luong 等人,2015 年] Luong,m-t .,Pham,h .和 Manning,C. D. (2015 年)。基于注意力的神经机器翻译的有效方法。

亚马逊书评的神经网络协同过滤

原文:https://towardsdatascience.com/neural-network-collaborative-filtering-with-amazon-book-reviews-c50a919a84a7?source=collection_archive---------21-----------------------

在我的项目中,我用亚马逊评论数据构建了一个图书推荐系统。

这个项目的目的是通过分析亚马逊评论并使用 Tensorflow 和 Keras 开发神经网络模型来创建一个协同过滤图书推荐系统。

图片由 Shiromani KantUnsplash 上拍摄

TL;博士:

一.背景

推荐系统是企业用来帮助客户匹配他们可能接触的产品的有用工具。如果开发得当,这些系统非常强大,可以直接提高公司吸引用户的能力。协同过滤是一种通过分析具有相似品味的其他用户的偏好来预测用户偏好的方法。有不同类型的协同过滤系统,这个参考解释得很好。

传统的协同过滤模型容易出现欠拟合,这导致它们在向用户推荐时有较高的误差。随着神经网络变得越来越流行,它们非常适合为推荐系统创建高度自适应的模型。构建神经网络协同过滤模型的指南并不多,因此我在本文中着手帮助演示这一点。

二。数据集

我们的数据集是从 UCSD【1】收集的存储库中加载的。该知识库是通过抓取数百万亚马逊页面创建的,因此它是亚马逊评论和产品评级的非常全面的集合。这些数据在很多方面都很有用,非常适合构建一个推荐系统。原始文件非常大,所以我选择只选择有 5 个或更多评论的(仍然是一个非常大的文件— 27,164,983 个评论)。

理论上,我们可以创建一个适合所有 27,164,983 条评论的协同过滤模型,但这将导致长时间的训练和低质量的嵌入,因为用户-图书矩阵非常稀疏。所以为了克服这一点,模型只选择了评论超过 100 的书籍和用户。

来自亚马逊评论数据集的评论数据

数据集包含. json 格式的上述信息。Pandas 可用于加载和结构化数据,但它需要成块加载,如下所示:

三。情感分析

情感分析是一个复杂的过程。NLTK (Vader)和 Textblob 等很多包都是基于规则的情感分析包,速度快,简单明了,但是不分析数据中任何更深层次的模式。当涉及到持续分析我们数据集中评论的情绪时,他们很难做到。

Flair 是一个强大的自然语言处理工具包,它使用预先训练的模型来预测文本情感。它在亚马逊评论数据上工作得非常好,所以 Flair 是获得所有用户图书评论的情感值的明确选择。唯一的缺点是运行时间,因为 Flair 的运行时间要长得多。

因为 Flair 包更像是一个逻辑分类器,所以我必须使用一些 QuantileTransformers 来转换变量,以便为我们的模型正确地缩放目标变量。

四。模型

我们模型的起点是用户手册矩阵。它是我们原始数据集的数据透视表,每行代表一个唯一的用户,每列代表一本书。

从用户手册矩阵到嵌入(图片由作者提供)

从用户手册矩阵中,可以创建嵌入,这是我们建模的基础。嵌入是表示数据集中要素的矢量。例如,在我们的例子中,嵌入可以代表书籍的流派、主题、长度、风格或者两者的某种组合。嵌入不能被明确地定义,所以我们永远无法确切地知道它们是什么,但是这是一个思考它们的好方法。

在这里了解更多关于嵌入的信息:Kerem Turgutlu 的结构化深度学习

一.矩阵分解方法

简单的矩阵分解包括两个步骤:

  • 将初始用户手册矩阵分解成嵌入(在我们的例子中,我们将使用 64 个单元嵌入)
  • 用户嵌入向量图书嵌入向量的加权点积,得到预测的情感得分。

矩阵分解法(图片由作者提供)

矩阵分解方法的实现如下所示。我用 scipy 将user_book_matrix分解成两个嵌入矩阵,user_embed_dfbook_embed_df

虽然这种方法快速而直接,但它在用户嵌入向量和书籍嵌入向量可以预测评论情感的程度方面有所限制。我们得到的 RMSE 是 0.131,这是可以改进的。

二。神经网络方法

为了改进我们模型的拟合,需要额外的建模来改进简单矩阵分解的局限性。矩阵分解很快,但是它的适应性不足以解释用户嵌入和图书嵌入如何相互作用的复杂性。

对于神经网络来说,这是一个完美的问题,我使用 Tensorflow 和 Keras 建立了一个模型来完成这一任务。如下图所示的神经网络有 3,050,337 个可训练的权重,这些权重中的每一个都可以被训练,这样神经网络就可以充分地考虑任何可能与我们的嵌入发生的复杂交互。

神经网络方法(图片由作者提供)

我们的神经网络结构包含 2048、1024、512、256、64 和 16 个单元的密集层。我们为epochs = 100训练模型,使用batch_size = 64。使用 RTX 2060 图形处理器,训练只花了大约 5 分钟。大多数 CPU 应该能够相当容易地处理这个问题。

该模型有脱落层和批量标准化层,以防止过拟合。我还使用了 optimizer = 'adam ',loss = 'mean_squared_error ',并添加了' mean_absolute_error '作为要跟踪的附加损失变量。我们在验证数据集上的 MSE 是 0.07,这是对矩阵分解模型的显著改进。

三。比较

让我们在用户身上尝试我们的神经网络模型,看看他们的表现如何:

约翰·史密斯(阅读数据集中的 53 本书)

作者图片

对约翰·史密斯来说,他最好的书是关于历史、战争和政治的书籍。根据我们的情感分析,这些书是约翰留下最积极评价的。推荐的书籍似乎符合他的口味,符合历史、传教士故事和移民的体裁。这些书是我们的神经网络模型预测得分最高的书。

推荐者推荐了丹尼尔·席尔瓦的《黑寡妇》,这部小说更像是一部惊悚小说。这似乎有点超出了约翰所习惯的范围,但是,嘿,也许他会喜欢的!

似乎我们的模型工作得相当好!仍有改进的空间,如进一步开发模型,或调整数据准备过程。

所有代码和笔记都可以在我的 github 页面这里找到。感谢您的阅读,希望对您有所帮助!任何反馈也非常感谢。

引用:

[1]简墨倪,,朱利安·麦考利,https://cseweb.ucsd.edu//~jmcauley/pdfs/emnlp19a.pdf【2019】【自然语言处理中的经验方法】

采用张量流时间分布包装器的变长输入神经网络

原文:https://towardsdatascience.com/neural-network-for-input-of-variable-length-using-tensorflow-timedistributed-wrapper-a45972f4da51?source=collection_archive---------5-----------------------

如何使用 Tensorflow 时间分布包装器处理可变长度输入(通常是信号)的指南

目录

  1. 为什么输入长度可变?
  2. Tensorflow 时间分布式包装器
  3. 数据生成程序
  4. 参考

为什么输入长度可变?

你是否曾经想要将神经网络应用于你的数据集,但是数据(信号、时间序列、文本等。)有了一个可变长度?不幸的是,这种情况对于数据科学家来说很常见。

正如我们所知,在现实世界中,数据永远不会像我们希望的那样漂亮和有条理。

有各种各样的方法来解决这个问题,但是没有一个让我满意。

最普遍采用的解决方案是将所有输入截断到相同长度,这通常与较短长度的输入相一致。然而,这造成了巨大的数据损失,正如我们所知,数据对我们来说是金子。

一个可能的替代方案是它的反面,即 填充 (添加数据直到所有信号长度相同)。填充的问题是,它添加了没有实际意义的数据,而且输入非常长,网络的规模变得不可持续。当然,填充可以通过 增强 来完成。然而,特别是对于数据顺序非常重要的信号,应用增强会“污染”这些信息。

我感到很失落,但当我看到这个包装纸时,我知道它就是我要的。

Tensorflow 时间分布式包装器

Thetime distributedwrapper 允许对输入的每个时间片应用一个层。

假设作为输入,我们有一个由以 100 Hz(每秒 100 点)采样的信号组成的数据集。我们的目标是对每个 30 秒的片段进行分类(称为纪元)。

因此,我们希望建立一个深度神经网络,递归地应用于这些片段中的每一个。为了阐明网络的工作原理,下面是一个简化的示意图:

网络如何运作的模式[图片由作者提供]

让我们从导入所有必需的元素开始:

from tensorflow.keras.layers import Conv2D, TimeDistributed,Dropout,Input, Dense,\
    BatchNormalization, GRU, Layer, Flatten
from tensorflow.keras.regularizers import l2
from tensorflow.keras.models import Model
from tensorflow.keras.utils import plot_model
from tensorflow.keras.optimizers import Adam

现在我们可以建立我们的网络。我们将使用【CNN】卷积块从原始信号中提取特征,随后使用【GRU】组合提取的特征。所以让我们写我们的函数:

def nn(shape_1,shape_2):
    input = Input(shape=[None, shape_1,shape_2,1])

    conv1 = TimeDistributed(Conv2D(filters=32, kernel_size=[32,1], activation='relu',strides =(3,1)))(input)
    batch1 = TimeDistributed(BatchNormalization())(conv1)

    conv2 = TimeDistributed(Conv2D(filters=32, kernel_size=[32,1], activation='relu',strides =(2,1)))(batch1)
    batch2 = TimeDistributed(BatchNormalization())(conv2)

    conv3 = TimeDistributed(Conv2D(filters=32, kernel_size=[32,1], activation='relu',strides =(2,1)))(batch2)
    batch3 = TimeDistributed(BatchNormalization())(conv3)

    conv4 = TimeDistributed(Conv2D(filters=32, kernel_size=[32,1], activation='relu',strides =(2,1)))(batch3)
    batch4 = TimeDistributed(BatchNormalization())(conv4)

    flat = TimeDistributed(Flatten())(batch4)

    gru1 = GRU(256, activation='relu',return_sequences=True, kernel_regularizer=l2(0.01))(flat)
    drop1 = Dropout(rate=0.4)(gru1)
    batch1 = BatchNormalization()(drop1)

    gru2 = GRU(128, activation='relu',return_sequences=True, kernel_regularizer=l2(0.01))(batch1)
    drop2 = Dropout(rate=0.4)(gru2)
    batch2 = BatchNormalization()(drop2)

    dense = TimeDistributed(Dense(2, activation='softmax'),name = 'output')(batch2)

    return [input], [dense]

正如我们所见,网络由四个卷积层两个卷积层组成。网络中还有其他元素,如 批量归一化层 ,由于时间原因我们不再赘述。最后,一个密集层 允许分类。如果您想要对整个信号而不是每个时期进行分类,我们可以使用以下内容作为最后一层:

dense = Dense(2, activation='sigmoid',name = 'status_output')(batch2)

需要注意的重要一点是,包装器不应该应用于时间层,比如 GRU 或 LSTM。默认情况下,这种类型的层已经可以处理可变长度。

一旦函数准备就绪,让我们构建模型并详细查看它:

EPOCH_LENGTH = 30
SAMPLE_RATE = 100

input, output = nn(SAMPLE_RATE*EPOCH_LENGTH,1)
model = Model(inputs=input,outputs=output)

optimizer = Adam(learning_rate=2*1e-4)

# Compile Model
model.compile(optimizer=optimizer, loss={
                  'output': 'sparse_categorical_crossentropy', },
              metrics={
                  'output': 'sparse_categorical_accuracy', },
              sample_weight_mode='temporal')
model.summary()

输出:

Layer (type)                 Output Shape              Param #   
=================================================================
input_13 (InputLayer)        [(None, None, 3000, 1, 1) 0         
_________________________________________________________________
time_distributed_58 (TimeDis (None, None, 990, 1, 32)  1056      
_________________________________________________________________
time_distributed_59 (TimeDis (None, None, 990, 1, 32)  128       
_________________________________________________________________
time_distributed_60 (TimeDis (None, None, 480, 1, 32)  32800     
_________________________________________________________________
time_distributed_61 (TimeDis (None, None, 480, 1, 32)  128       
_________________________________________________________________
time_distributed_62 (TimeDis (None, None, 225, 1, 32)  32800     
_________________________________________________________________
time_distributed_63 (TimeDis (None, None, 225, 1, 32)  128       
_________________________________________________________________
time_distributed_64 (TimeDis (None, None, 97, 1, 32)   32800     
_________________________________________________________________
time_distributed_65 (TimeDis (None, None, 97, 1, 32)   128       
_________________________________________________________________
time_distributed_66 (TimeDis (None, None, 3104)        0         
_________________________________________________________________
gru_22 (GRU)                 (None, None, 256)         2582016   
_________________________________________________________________
dropout_20 (Dropout)         (None, None, 256)         0         
_________________________________________________________________
batch_normalization_48 (Batc (None, None, 256)         1024      
_________________________________________________________________
gru_23 (GRU)                 (None, None, 128)         148224    
_________________________________________________________________
dropout_21 (Dropout)         (None, None, 128)         0         
_________________________________________________________________
batch_normalization_49 (Batc (None, None, 128)         512       
_________________________________________________________________
output (TimeDistributed)     (None, None, 2)           258       
=================================================================
Total params: 2,832,002
Trainable params: 2,830,978
Non-trainable params: 1,024
_________________________________________________________________

正如我们所看到的,网络有 280 万个可训练参数,总的来说这是一个很小的数目。让我们形象地描述一下:

model._layers = [
    layer for layer in model._layers if isinstance(layer, Layer)
]

plot_model(model, 'model.png', show_shapes=True)

模型形状[图片来自作者]

从网络的形状中,我们注意到 TimeDistributed 在默认的基础上增加了一个维度(即第二个问号),它对应于每个信号的不同时期数。

此外,GRU(或 LSTM )允许我们利用时间信息,这在信号中是必不可少的。

不幸的是,这个网络不能自我训练,特别是在我们的例子中,我们有各种由 IDs 标识的文件。然后,我们构建一个生成器来管理输入。

数据生成程序

在我们的例子中,我们有一个文件列表,每个文件代表一个输入信号。因此,我们需要为 Tensorflow 构建一个生成器,在运行时接收信号并为网络做好准备。

现在让我们构建一个类,它将类型为 的对象序列 作为输入,并实现训练网络所需的所有方法( initlengetitem,on_epoch_end ):

import numpy as np
from keras.utils import Sequence
from keras.preprocessing.sequence import pad_sequences

class DataGenerator(Sequence):
    *"""Generates data for Keras
    Sequence based data generator. Suitable for building data generator for training and prediction.
    """* def __init__(self, list_IDs, input_path, target_path,
                 to_fit=True, batch_size=32, shuffle=True):
        *"""Initialization* ***:param*** *list_IDs: list of all 'label' ids to use in the generator* ***:param*** *to_fit: True to return X and y, False to return X only* ***:param*** *batch_size: batch size at each iteration* ***:param*** *shuffle: True to shuffle label indexes after every epoch
        """* self.input_path = input_path
        self.target_path = target_path
        self.list_IDs = list_IDs
        self.to_fit = to_fit
        self.batch_size = batch_size
        self.shuffle = shuffle
        self.on_epoch_end()

    def __len__(self):
        *"""Denotes the number of batches per epoch* ***:return****: number of batches per epoch
        """* return int(np.floor(len(self.list_IDs) / self.batch_size))

    def __getitem__(self, index):
        *"""Generate one batch of data* ***:param*** *index: index of the batch* ***:return****: X and y when fitting. X only when predicting
        """* # Generate indexes of the batch
        indexes = self.indexes[index * self.batch_size:(index + 1) * self.batch_size]

        # Find list of IDs
        list_IDs_temp = [self.list_IDs[k] for k in indexes]

        # Generate data
        X = self._generate_X(list_IDs_temp)

        if self.to_fit:
            y = self._generate_y(list_IDs_temp)
            return [X], y
        else:
            return [X]

    def on_epoch_end(self):
        *"""
        Updates indexes after each epoch
        """* self.indexes = np.arange(len(self.list_IDs))
        if self.shuffle:
            np.random.shuffle(self.indexes)

    def _generate_X(self, list_IDs_temp):
        *"""Generates data containing batch_size images* ***:param*** *list_IDs_temp: list of label ids to load* ***:return****: batch of images
        """* # Initialization
        X = []

        # Generate data
        for i, ID in enumerate(list_IDs_temp):
            # Store sample
            temp = self._load_input(self.input_path, ID)
            X.append(temp)

        X = pad_sequences(X, value=0, padding='post')

        return X

    def _generate_y(self, list_IDs_temp):
        *"""Generates data containing batch_size masks* ***:param*** *list_IDs_temp: list of label ids to load* ***:return****: batch if masks
        """* y = []

        # Generate data
        for i, ID in enumerate(list_IDs_temp):
            # Store sample
            y.append(self._load_target(self.target_path, ID))

        y = pad_sequences(y, value=0, padding='post')

        return y

一旦生成器类被编写,让我们提取文件的 id 列表,将它们分成训练验证测试。注意,我们构建了两个生成器,一个用于训练,一个用于验证:

import numpy as np
import re
from os import listdir
from os.path import isfile, joinTEST_SIZE = 128
onlyfiles = [f for f in listdir(input_path) if isfile(join(input_path, f))]

id = [re.search('(.+?).npz', x).group(1) for x in onlyfiles]
id.sort()

np.random.seed(1234)
id_test = np.random.choice(id, size=TEST_SIZE,replace=False)
id = list(set(id) - set(id_test))
id_validation = np.random.choice(id, size=TEST_SIZE,replace=False)
id = list(set(id) - set(id_validation))

print(len(id))

training_generator = DataGenerator(id,  input_path = input_path,
                                   target_path=target_path)

validation_generator = DataGenerator(id_validation, input_path = input_path,
                                   target_path=target_path)

我们现在终于可以进行模型训练了,祈祷好运吧😆。

model.fit(training_generator,
                    validation_data=validation_generator,
                    epochs=8,
                    use_multiprocessing=True)

对于本文,我们已经完成了,我在参考资料中为您留下了包含代码的 repo 的链接。

一会儿见,

弗朗西斯科

参考

  1. 时间分布式张量流包装器
  2. 带有代码的 Github

预测建筑物能源性能的神经网络

原文:https://towardsdatascience.com/neural-network-for-predicting-the-energy-performance-of-a-building-5c2bf5820ebe?source=collection_archive---------24-----------------------

用 Tensorflow 和 Colab 估算夏季和冬季负荷

在我攻读工程学硕士学位期间,我花了几年时间,试图为能源系统建模。在大多数情况下,对于特别简单方便的几何边界条件,只有最简单的问题可以直接建模(所研究系统的控制微分方程的解析解)。使用各种数学/数值或程序技术来处理更复杂的问题,以简化它们的性质,从而可以开发出相当精确(尽管是*似的)的计算模型。

照片由 Zbynek BurivalUnsplash 上拍摄

我最*在深度学习和最广泛意义上的工程(结构分析、流体动力学、能源系统……)的集成方面的经验中,最有趣的一个方面是以完全不同的方式处理所研究的问题的可能性。

数据的丰富性复杂性不再是一个问题,而是一个优势,允许开发更加准确的和更加复杂的预测模型。

在一个问题可以被完美地解释和解析地解决之前,没有必要再把这个问题简化到骨子里。数据的可靠性,再加上复杂的神经网络模型,足以以超过可接受的工程和功能精度对系统进行建模。

Outsite CoUnsplash 上拍摄的照片

所有这些序言对于介绍本文中提出的问题是必要的,即从结构化数据集中对建筑物的夏季和冬季热负荷进行估计。在我的学习和个人生活中,我多次遇到这个问题。按照我的惯例,我总是使用不可避免的 Excel 电子表格和相关的国家立法来处理估算能源性能的问题。这考虑了各种因素的总和(直接和间接的太阳能负荷、通风、显热和潜热负荷……),采用了基于效应叠加和一维的方法,产生了一种解决该问题的常用简化方法。与其实施相关的标准的解释可能远不是一个简单的任务,更多的是因为缺乏清晰度,而不是要开发的计算的数字难度。

通过将数字模拟或安装的家庭自动化传感器生成的大量数据结合起来,彻底改变这种方法的可能性可能是一个有趣的思考点。

为什么要看这篇文章?

在这个故事中,我们将看到如何开发一个顺序(全连接)密集神经网络模型,用于从使用 Autodesk Ecotect 生成的开源数据集中估算建筑的夏季和冬季热负荷。我们将评估我们网络的性能和结构。

数据集

本分析从 能效数据集 开始,免费提供。该能源分析涵盖了 12 栋建筑。每个模拟都是用 Ecotect 进行的。这些建筑在玻璃面积、玻璃面积分布、朝向等方面各不相同……测试了上述参数的各种组合,从总共 8 个自由度开始,获得了 768 种建筑形状。数据集包括 768 个样本、8 个特征和两个实值响应(输出/特征)。

配对图—作者提供的图像

数据集包括 8 个属性/特征()*和两个响应/标签()*。**

目标是用这八个特征来预测两个反应 中的每一个。 具体来说:

  • X1 相对紧密度
  • X2 表面积
  • X3 城墙区域
  • X4 屋顶面积
  • X5 总高度
  • X6 方位
  • X7 玻璃区域
  • X8 玻璃区域分布
  • Y1 加热负荷
  • Y2 冷负荷

Ecotect

Autodesk Ecotect Analysis是一种环境分析工具,使设计师能够在概念设计过程的早期模拟建筑性能。它将分析功能与交互式可视化相结合,直接在建筑模型的上下文中呈现分析结果。

密集神经网络

为了这个分析,我使用了一个密集的神经网络。我使用了 2 个隐藏层(浅层网络),每层 256 个神经元,激活函数为“relu”。

热负荷神经网络—图片由作者提供

如果你对我如何制作这个情节感兴趣,我写了一篇关于它的文章。对于这个分析,我选择了 Keras Functional API 来生成神经网络。你可以在这里找到源代码,在 GitHub 和 YouTube 上找到完整的。我选择 Meas *方误差作为损失函数,在训练期间还监控*均绝对误差和*均百分比绝对误差。最后,我使用 Adam 作为自适应学习率优化器,没有学习率衰减调度。最后,数据集必须分成训练验证数据。将数据归一化到便于模型训练过程。

热负荷神经网络概念—图片由作者提供

结果

神经网络已经训练了 500 个历元,批次大小为 128。我们得到了培训(蓝线)和验证(橙线)损失的良好趋势。

跨时代的损失函数-按作者分类的图像

为了评估模型的性能,建议制作验证图。这些图在横坐标中示出了标签的精确值,而纵坐标示出了神经网络对同一组输入的预测值。对于热负荷,我们得到以下趋势:

热负荷验证图-作者提供的图片

定量的角度,评估了*均绝对误差、均方误差、皮尔逊系数决定系数

**Y0 - mae-train - 0.00474
Y0 - mse-train - 4.44430
Y0 - r2-train - 0.99940
Y0 - pearson-train - 0.99972
Y0 - mae-test - 0.00947
Y0 - mse-test - 0.00015
Y0 - r2-test - 0.99783**

我们可以看到,我们的算法在两个集合上都达到了非常高的精度(对于决定系数和皮尔逊系数,理想条件是值为 1)。对于冷负荷,我们得到以下趋势:

冷负荷验证图-作者提供的图片

定量的角度来看:

**Y1 - mae-train - 0.00685
Y1 - mse-train - 8.63810
Y1 - r2-train - 0.99870
Y1 - pearson-train - 0.99951
Y1 - mae-test - 0.01739
Y1 - mse-test - 0.00058
Y1 - r2-test - 0.99042
Y1 - pearson-test - 0.99606**

无论是数字上的还是质量上的(趋势),所获得的结果仍然非常令人满意。尽管这些结果是部分的,并且没有对模型从未见过的进一步数据进行可能的优化和测试的有益效果,但结果证明是有希望的,并且惊人地准确。****

结论

我们利用模拟软件 + 深度学习算法的有趣组合,利用 Python、Colab 和 Tensorflow 的潜力,解决了一个复杂的工程问题。我们开发了一个神经网络模型,在结构化数据集上训练,用于预测热负荷。我们获得了非常好的结果,表明应用这种方法评估新数据的热性能以及解决这种工程分析的可能性。

下次见,马尔科

3 分钟机器学习

3 分钟机器学习是一系列与人工智能、深度学习和数据科学相关的教程、视频和文章。你可以在 YouTube 上找到完整的视频集。GitHub 存储库包含了文章和视频中显示的所有 Google Colab 笔记本。希望这些内容对你有用,或者只是你感兴趣。欢迎任何反馈。

查看其他剧集:

利用时间反演原理的神经网络

原文:https://towardsdatascience.com/neural-network-from-tenet-exploiting-time-inversion-fdc512f5fec3?source=collection_archive---------8-----------------------

用递归神经网络建模动态系统

前一段时间,我使用了一种基于时间反演的时间序列预测方法,这种方法完美地融入了 Hans-Georg Zimmermann 博士发明的一种特殊类型的递归神经网络,他是一位世界级的深度学习实践者,多年来在西门子领导了一项应用于工业和金融问题的神经网络研究[1]。他利用的潜在哲学思想超出了克里斯托弗·诺兰的宗旨范围,但这种方法仍然是超级合法的。

宗旨的理念

动力系统是一组状态随时间变化的相关事物。开放系统可以对环境做出反应,而封闭系统不受环境影响,完全自主运行。它们仿照如下方式:

(1)开放和封闭的动力系统模型

上述模型假设动态系统具有从过去到现在在时间上前进的信息(因果)。

但是在一些动态系统中,信息流从未来到现在沿着相反的时间方向前进。这些是动态系统,其随时间的变化受到涉及未来可观测性预测的规划的影响。例如,大多数市场价格不仅由供给和需求决定,还由市场参与者的计划方面决定。在这种情况下,我们可能会受益于使用假设因果和追溯因果影响混合的模型。

(2)具有因果和倒因果影响的动力系统模型

幕后模特

1.封闭动力系统的动机

让我们首先考虑因果开放动力系统模型(1)。如果对于转换函数,我们采用一个应用于线性状态转换的激活函数,并添加一个输出方程,您可能会识别出一个标准的递归神经网络 (RNN),它非常适合于通过构造进行动态系统建模,并广泛用于处理时序数据,例如时间序列和自然语言。

(3)开放动力系统的简单递归神经网络

这是一个相当复杂的模型,需要考虑内部自治系统状态和外部输入。因此,让我们通过将问题重新表述为更复杂的问题来简化这个复杂的模型——考虑一下封闭动力系统。为此,我们必须通过添加包含外部变量动态的外部子系统来扩展我们的内部系统空间。模型复杂性和问题复杂性之间的这种权衡并不便宜,我们以后在教模型理解扩展的内部空间的新变量关系时会付出代价。

(4)将开放动力系统转化为封闭动力系统

但是我们获得了一个简单的模型(5 ),其长期一致性仅取决于内部系统变量的相互关系的强度,而不取决于外部输入,这在实践中也很难获得。请注意,在新模型中,我们还摆脱了复杂的输出提取—我们的输出 y 只是系统状态 s 的子集,没有任何变化。

(5) RNN 模拟一个封闭的动力系统

2.教授因果/时间向前模型

在模型(5)中,所有拟合参数位于权重矩阵 a 中。为了拟合它们,我们使用标准误差时间反向传播 (BPTT)算法,该算法具有在每个时间戳纠正误差的特殊技巧,称为教师强制

目标/损失函数,我们希望通过调整权重矩阵 A 使其最小化,初始状态偏差是每个时间戳的误差*方和。

(6)目标/损失函数——系统的识别

拟合 RNN ,即时间反向传播涉及
1)正向传递,其中我们计算每个时间戳的输出
2)每个时间戳的误差计算,然后总误差计算
3)通过时间反向传播误差来计算总误差相对于模型参数的梯度
4)根据梯度更新权重
重复步骤 1-4,直到模型误差足够低。

由于只有一条历史路径,即观察序列 y ,我们只有一个数据样本来训练模型。

在拟合过程的正向传递中,我们使用教师强制 —在每个时间戳,目标被替换在对应于可观察输出的内部系统状态的部分中。**然而,系统内部状态的其余部分 s 对应的这个不可观测的系统变量保持不变。这样,我们不会传播错误,因此在训练模型时不会累积错误。

(7)教师强制纠错

在向前传递之后,我们可以使用模型输出和目标容易地计算总误差(6)。然后,我们必须计算误差相对于模型参数的梯度。

(8)关于权重矩阵的误差梯度

在算法的最后一步,使用计算的梯度,我们更新模型参数/状态转移相关性,即权重矩阵 A:

(9)BPTT 权重矩阵更新

上面描述的带教师强迫的递归神经网络称为误差修正神经网络(ECNN) 或历史一致性神经网络(HCNN)【2】。

请注意,由于自治系统扩展(4),权重矩阵 A 可能非常大,其中标量权重的数量等于系统变量总数的*方。当我们增加系统空间时,它会快速增长,这是建模方法的一个瓶颈。加快训练过程的一个很好的实用技巧是使用稀疏权重矩阵 A——假设系统变量之间的一些联系比假设一切都是相互关联的更接*现实。

您还可以查看我对这一部分的 python 实现:

3.时间反演:从因果模型到逆因果模型

我在 Zimmermann 博士的演讲中发现的逆向工程原理的表述阐明了追溯因果模型背后的内在动机:

当我们能够确定代理人的目标时,我们就可以试着从这些目标向后解释动力学

事实上,我们并不局限于只学习因果依赖,在这里它被利用了。让我们假设我们生活在反转的时间世界中,简单地使用相同的模型架构来学习从未来到过去的系统转换。**

(10)时间倒推的追溯因果 RNN

同样的方法,我们应用 BPTT 与教师强迫,以适应倒置的时间系统转移权重矩阵和初始状态偏差。

对于这部分的实现,我们基本上只需要在倒序上训练来自第二部分的标准因果 RNN* 。***

4.【宗旨】因果和逆因果神经网络的叠加

最后,我们将正常时间网络和反转时间网络对称地组合成一个网络[3]。

(11)组合的因果和逆因果神经网络

再次训练这个网络需要 BPTT 和老师的强迫。

(12)因果和追溯因果网络结合的教师强迫

这部分我在 PyTorch 上的实现:https://github . com/uselesskills/hcnn/blob/master/tutorials/CRC _ hcnn . ipynb

结论

我们从 TENET 提出的时间反演思想开始,然后将其映射到一个由递归神经网络驱动的模型。还是真的反过来了?

特别感谢阿列克谢·米宁博士,他向我介绍了这种非凡的方法,并在我试图理解它时耐心地给我多次建议,直到我感觉到它。

参考

[1]https://www.researchgate.net/profile/Hans-Zimmermann-4

2 齐默尔曼汞。、Tietz C .、Grothmann R .,《历史一致性神经网络:市场建模、预测和风险分析的新视角》,施普林格,2013 年

[3] 齐默尔曼汞。Grothmann R .,Tietz C,“用因果-回溯-因果神经网络预测市场价格”, Springer,2012 年

4 Python 包与我实现的网络描述(HCNN,Causal & Retro-Causal NN):https://github.com/uselessskills/hcnn

基于 FPGAs 的神经网络推理

原文:https://towardsdatascience.com/neural-network-inference-on-fpgas-d1c20c479e84?source=collection_archive---------12-----------------------

如何在 AWS 上从头开始构建和实现 FPGA 应用

作者: 丹尼尔·苏斯高级机器学习工程师马克斯·凯尔森

劳拉·奥克尔在 Unsplash 上的照片

与传统的云部署相比,将深度学习模型直接部署到边缘设备具有许多优势:消除通信可以减少延迟和对网络连接的依赖;由于数据从不离开设备,边缘推断有助于维护用户隐私;由于云资源的数量急剧减少,边缘推理也可以降低持续成本。

运行在边缘设备上的 ML 的激增既推动了专用硬件加速器(如 GPU、ASICs 或 FPGAs)的发展,也受其推动。对于每种硬件类型的优缺点的概述,请参见本系列文章本文

在这篇文章中,我们将讨论如何在 FPGA 器件上运行简单神经网络的推理。主要重点将是更好地了解 FPGA 编程,并略微降低其传统的高准入门槛。

这篇文章将通过一个在 2 层全连接网络上运行推理的简单示例应用来回顾基本开发。通过使用 AWS 的 F1 实例及其提供的 AMI 和所有必要的软件,您需要做的就是创建一个 AWS 帐户。稍加修改,该示例也可以在大多数 Xilinx FPGAs 上运行。

FPGAs 编程

使用 FPGA 的主要挑战之一是,它们的编程模型与大多数其他“编程”有着根本的不同:对 FPGA 编程意味着对实际硬件编程,而不是生成由处理单元运行的指令。要理解这一点,我们首先需要了解什么是 FPGA。

高度简化后,FPGA 由许多可编程逻辑模块组成,例如查找表(LUT)、存储器以及这些构建模块之间的可重新配置连接。重新配置逻辑块的行为和它们之间的连接允许我们实现不同的数字电路。因此,最终的“程序”可以看作是由 FPGA 实现的原理图。

传统上,FPGAs 使用硬件描述语言(如 Verilog 或 VHDL)编程。这些与流行的编程语言有很大不同,这是 FPGA 编程门槛高的一个主要原因。

随着高级综合(HLS)工具的引入,这一障碍已经大大降低,这些工具允许用 C/C++等更主流的语言编写 FPGAs 代码。

通常情况下,这种抽象性和简洁性的提高往往是以电路效率的降低为代价的。因此,对于性能关键的实现,对底层硬件层的良好理解是必不可少的。

对于我们的第一个实现,我们将使用 Xilinx 的基于 OpenCL 的 Vitis *台:OpenCL 设备(如 FPGA)执行称为“内核”的小程序。这些内核由主机设备(CPU)管理和启动。通过使用 HLS 实现这些内核,FPGA 的实现看起来非常接* CPU 的类似实现。

主要区别在于,FPGA 内核不仅仅是像在 CPU 上一样处理的指令,而是作为设备上的数字电路来实现。

所以举个例子,如果我们想并行运行部分代码,不能只在多核上并行运行;相反,我们需要在 FPGA 上复制物理电路。

请注意,Xilinx' Vitis AI *台为常见的网络架构(如用于图像分类的 Resnets)和单级对象检测器(如 SSD 和 Yolo)提供了现成的运行时。然而,在写这篇文章的时候,AWS F1 实例还不被支持

将来,我想看看必要层的简单实现在效率上能有多接*这样的参考实现。

设置开发环境

这篇文章附带的代码可以在 GitHub 上找到。在第一个技术部分,我们将讨论如何运行它。由于必要的软件似乎不是免费提供的,我们将在 AWS 上使用 FPGA 开发者 AMI

你将需要一个 AWS 帐户支付设置,因为自由层的机器是不够强大的。

本例中的构建脚本基于官方 Vitis 教程。然而,这些在 AWS 的 FPGA 环境中不能开箱即用,需要进行两项更改:

  • 需要将[PLATFORM](https://github.com/Xilinx/Vitis-Tutorials/blob/master/Hardware_Accelerators/Introduction/03-Algorithm_Acceleration/docs/module1_baseline/Makefile#L36)变量设置为[$AWS_PLATFORM](https://github.com/dsuess/nn-on-fpgas/blob/master/CMakeLists.txt#L14)——由 FPGA AMI 设置的环境变量,以及
  • 使用的 FPGA 内存条需要在硬件仿真模式下更改

最后一句话已经让我们看到了使用 FPGAs 的一个要点:为实际硬件设备合成程序可能需要很长时间,甚至几个小时,即使是简单的设计也是如此。这就是为什么我们将广泛使用两种不同类型的仿真。

首先,在软件仿真模式下,内核被编译成本机代码,直接在 CPU 上运行。一方面,这使得编译速度非常快,并且在特性开发期间实现快速开发周期是理想的。另一方面,由于这个步骤不需要实际的原理图合成,某些错误不会在软件仿真中出现。

第二种是硬件仿真模式,在仿真设备上运行实际的合成原理图。由于这种模拟非常详细,硬件模拟运行起来比软件模拟慢得多。它也增加了开发周期的额外编译时间,但仍然比实际 FPGA 的编译快得多。

从好的方面来看,硬件仿真不仅允许功能测试,还允许探测在物理设备上运行的性能特征和资源需求。

由于这两种仿真模式都不需要 FPGA,大多数开发工作可以(也应该)在一台强大的纯 CPU 机器上完成,从而节省了大量资金。我们只需要一个 FPGA 实例进行最后的测试。

设置 EC2 实例

如前所述,大多数开发工作不需要 FPGA 实例,可以在通用实例类型上完成。按照本教程,您将需要一个 S3 桶(在这里命名为fpga-storage)和一个 EC2 实例,它具有:

  • AWS FPGA 开发人员 AMI 加载,
  • 至少 16GB 的 RAM(例如,m5.xlarge实例类型或更大以加速仿真),以及
  • 对 S3 存储桶具有读/写访问权限的 IAM 角色,并具有以下权限:

DescribeFpgaImageAttribute

DescribeFpgaImages

CopyFpgaImage

CreateFpgaImage

DeleteFpgaImage

ModifyFpgaImageAttribute

在本节的剩余部分,我们将提供如何启动所需实例的分步说明。有经验的 AWS 用户可以跳到下面的设置环境部分。

1.从 S3 管理控制台创建一个新的 S3 桶。将名称设置为fpga-storage,并保留其余选项的默认值。

2.从 IAM 策略创建创建新策略。

3.对于服务,选择“S3”;对于操作,选择“ListBucket”、“GetObject”、“PutObject”和“DeleteObject”,对于资源,为除“Bucket”之外的所有字段选择“Any”,对于“bucket”,您将 bucket-name 设置为“fpga-storage”:

S3 服务的策略设置

4.单击“添加附加权限”并为“EC2”服务添加以下权限(也在上面列出):

EC2 服务的策略设置

5.继续浏览各个屏幕,直到您到达“审查政策”屏幕。输入“FpgaDevPolicy”作为名称,并完成角色创建。

6.您现在可以使用 IAM 角色创建来创建一个新角色。

7.从下一个屏幕中选择“AWS 服务”→“EC2”作为可信实体。

8.从列表中选择新创建的“FpgaDevPolicy ”,并继续操作,直到到达“查看角色”屏幕。输入名称“FpgaDevRole”并完成角色创建。

9.从 EC2 控制台中,点击“启动实例”。

10、在 AMI 搜索栏中,输入“FPGA”,从左侧菜单中选择 AWS Marketplace。从列表中选择 AWS 的“FPGA Developer AMI”。

选择 FPGA AMI

11.继续执行实例选择步骤。选择m5.xlarge实例类型并点击“下一步:配置实例细节”按钮。

12.为 IAM 角色条目选择创建的“FpgaDevRole”。单击“添加存储”。

13.删除额外的 EBS 卷,并将根分区的大小增加到 200GB。

14.单击“查看并启动”和“启动实例”。

15.如有必要,使用 AWS 中显示的公共 IP 将 ssh 认证和 ssh 设置到新实例中:

*$* ssh -i ~/.ssh/PATH_TO_PRIVATE_KEY centos@xxx.xxx.xxx.xxx

设置环境

现在我们已经使用 FPGA 开发工具连接到 EC2 实例,我们需要安装一些额外的要求:

*$ sudo* yum *install* cmake3 jq
*$* git clone https://github.com/aws/aws-fpga ~/src/project_data/aws-fpga

第二行从 AWS 的官方 Github repo 中克隆了一个 repo 和一些额外的助手脚本。我们主要需要它通过运行以下命令在机器上设置开发环境:

*$ source* ~/src/project_data/aws-fpga/vitis_setup.sh

注意,上述命令需要在每次登录机器时运行,因为它修改了 shell 环境。

运行示例

我们现在准备在这台机器上运行示例。为此,我们将遵循正常的开发周期:软件仿真、硬件仿真,最后为硬件设备编译。要遵循以下示例,您需要克隆示例 repo:

$ git clone https://github.com/dsuess/nn-on-fpgas -b part-1-v1 --recursive && cd nn-on-fpgas

软件仿真

运行这些示例的最快方法是使用软件仿真。这将内核编译成本机代码,完全避开了电路合成。

在构建脚本中,编译模式是通过TARGET变量控制的,该变量有三个可能的值sw_emuhw_emuhw。要在软件仿真中编译示例,我们可以简单地运行:

*$ mkdir* build_sw **&&** *cd* build_sw **&&** cmake3 -DTARGET**=**sw_emu .. **&&** make main kernels tests emconfig.json

如果该命令引发错误,请确保您遵循了上面设置环境部分的说明。这将在build_sw子目录中构建所有必需的目标:

  • main构建示例程序,
  • tests为内核构建测试套件,
  • kernels构建内核二进制文件xclbin/kernels.xclbin,并且
  • emconfig.json包含目标硬件*台的信息。

内核(即应该在 FPGA 上运行的基本数学运算)由应用在运行时加载。

我们现在可以运行测试或示例应用程序了:

*$ XCL_EMULATION_MODE***=**sw_emu ./tests
*$ XCL_EMULATION_MODE***=**sw_emu ./main

后者应该在最后一行打印0 1 2 2 4 5 6 7 8 9。这些是模型在对类别 0 到 9 的图像运行时的类别预测。该模型的精确度约为 94%,这是我们看到标签 3 错误的原因。

硬件仿真

为硬件仿真构建内核只需要改变TARGET变量:

*$ mkdir* build_hw **&&** *cd* build_hw **&&** cmake3 -DTARGET**=**hw_emu .. **&&** make kernels tests emconfig.json

该命令应该从 git repo 的根目录运行。请注意,与软件仿真模式相比,编译需要更长的时间。运行示例也是如此,这就是为什么我们只在硬件仿真中运行测试:

*XCL_EMULATION_MODE***=**hw_emu ./tests

除了二进制文件之外,硬件仿真还会生成关于资源利用的详细报告,并建议在_x/reports中进行更改。我们将在本系列的后面部分回到这些诊断。

在 FPGA 上运行

最后,我们现在可以在实际的 FPGA 硬件设备上运行示例了:

*$ mkdir* build **&&** *cd* build **&&** cmake3 -DTARGET**=**hw .. **&&** make kernels

这一步只会在xclbin/kernels.xclbin中构建内核二进制文件,可能需要一个多小时才能完成。如果你不想等那么久,我们提供一个二进制文件的完成版本作为 Github 版本。

在标准的 Xilinx 系统上,我们可以直接从 xclbin 文件运行内核。然而,AWS 需要一个额外的步骤,即把 xclbin 转换成亚马逊 FGPA 图像(AFI)。构建步骤在官方 AWS FPGA 报告中概述。

首先,我们需要将用于以下命令的默认区域设置为支持 FPGA 实例的区域(这里是us-east-1)

*$* aws configure *set* default.region us-east-1

现在我们可以创建 AFI 映像,并将其保存到我们在初始环境设置中创建的 S3 存储桶fpga-storage:

*$ $VITIS_DIR*/tools/create_vitis_afi.sh -xclbin**=**xclbin/kernels.xclbin \
		-o**=**xclbin/kernels \
		-s3_bucket**=**fpga-storage -s3_dcp_key**=**kernels -s3_logs_key**=**logs

这将创建一个 xclbin 文件xclbin/kernels.awsxclbin,在 F1 实例上运行时,它应该由运行时加载,而不是由xclbin/kernels.xclbin加载。在我们的标准运行时中,这是基于编译时标志自动完成的。我们将该文件复制到 S3 存储桶中以备后用。

*$* aws s3 *cp* xclbin/kernels.awsxclbin s3://fpga-storage/

此外,应该创建一个包含 AFI ID 的*_afi_id.txt文件。使用 AFI ID,我们可以检查在后台运行的转换过程的状态:

*$ export AFI_ID***=**$(*cat* *****_afi_id.txt | jq -r ".FpgaImageId")
*$* aws ec2 describe-fpga-images --fpga-image-ids *$AFI_ID*

注意,当多次运行create_vitis_afi.sh脚本时,目录中将会有多个符合第一个命令的 glob-pattern 的文件。要么手动选择正确的选项,要么删除所有选项并重新运行脚本。

一旦 describe-fpga-images 命令输出的状态代码从“pending”变为“available”,我们就可以在 fpga 硬件设备上运行这个示例了。

为此,遵循上面的设置 EC2 实例一节中概述的设置步骤,但是选择 F1 实例类型。在克隆了示例 repo 之后,我们需要构建除内核之外的所有东西:

*$ mkdir* build **&&** *cd* build **&&** cmake3 -DTARGET**=**hw .. **&&** make emconfig.json main tests

我们可以简单地从 S3 复制 AFI 内核二进制文件:

*$ mkdir* xclbin **&&** aws s3 *cp* s3://fpga-storage/kernels.awsxclbin xclbin/

并在 FPGA 上运行测试和示例应用程序:

*$* ./tests
*$* ./main

履行

既然我们已经介绍了如何构建用于仿真和硬件部署的示例,我们将回顾一下在 FPGAs 上运行推理的 2 层全连接网络的简单基线实现。

代码走查

我们试图运行的模型非常简单。两个完全连接的层;第一层重新激活,第二层(也是最后一层)激活 softmax。

**class** **FCNN:**
    **def** **__init__(***self***,** input_size**:** *int***,** num_classes**:** *int***):**
        *self***.**layer1 **=** Dense**(**input_size**,** 64**)**
        *self***.**layer2 **=** Dense**(**64**,** num_classes**)****def** **__call__(***self***,** x**:** Tensor**)** **->** Tensor**:**
        y **=** x
        y **=** *self***.**layer1**(**y**).**relu6**()**
        **return** *self***.**layer2**(**y**).**logsoftmax**()**

这意味着我们需要实现以下三个内核:

  • 矩阵-矩阵乘法
  • 偏置相加+ ReLu 非线性
  • 偏置相加+ softmax 非线性

将矩阵乘法和偏置加法操作分成两个内核的原因是,前者可能会成为最大的性能瓶颈。

因此,将它们分开会使以后用不同的矩阵乘法实现进行实验更容易。

此外,将偏置相加和非线性函数融合到单个内核中可能有利于性能。这两种操作都相对较快,因此启动内核的额外开销会更明显。

这两种操作还具有低的计算-存储器-传输比,因此,通过在一次通过中执行偏置相加和非线性,受益于减少存储器访问。

[net.hpp](https://github.com/dsuess/nn-on-fpgas/blob/f301d3053bbc0ab7baea4ea92b440add63734369/src/net.hpp)文件中的 C++实现也复制了模型的结构,我们将在后面介绍。

内核实现

我们将编写的第一个也是最简单的内核是 bias + ReLu6 内核。由于 HLS 使用 C++并且不包括任何可选的 FPGA 特定代码,第一个基线实现看起来像标准 C++代码:

**extern** "C" **void** **bias_relu6_kernel(float** ***const** activation**,** **const** **float** ***const** bias**,** **const** uint batch_size**,** **const** uint dim**)**
**{**
   **for** **(**uint b **=** 0**;** b **<** batch_size**;** b**++)**
   **{**
      **for** **(**uint d **=** 0**;** d **<** dim**;** d**++)**
      **{**
         **const** uint ia **=** dim ***** b **+** d**;**
         activation**[**ia**]** **=** relu6**(**activation**[**ia**]** **+** bias**[**d**]);**
      **}**
   **}**
**}**

bias + softmax 内核的实现非常相似。注意,结果是使用activation作为输入和输出就地计算的。这对于矩阵乘法核来说是不可能的,因为输入和输出的形状可能不同。

因此,我们需要在内核之外分配足够的内存,并使用额外的out参数传入一个指针。使用三个 for 循环的简单实现当然不是最佳的,稍后需要重新考虑:

**extern** "C" **void** **matmul_kernel(const** **float** ***const** matrixA**,** **const** **float** ***const** matrixB**,** **const** uint rowsA**,** **const** uint colsA**,** **const** uint colsB**,** **float** ***const** out**)**
**{**
   **for** **(**uint i **=** 0**;** i **<** rowsA**;** **++**i**)**
   **{**
      **for** **(**uint j **=** 0**;** j **<** colsB**;** **++**j**)**
      **{**
         *// Nulling result here causes issues when running in hw-emu mode.*
         *// Looks like io isn't updated "in time"*
         **const** uint io **=** colsB ***** i **+** j**;**
         **for** **(**uint k **=** 0**;** k **<** colsA**;** **++**k**)**
         **{**
            **const** uint ia **=** colsA ***** i **+** k**;**
            **const** uint ib **=** colsB ***** k **+** j**;**
            out**[**io**]** **+=** matrixA**[**ia**]** ***** matrixB**[**ib**];**
         **}**
      **}**
   **}**
**}**

输出数组out应该在内核之外初始化为零,并且所有的数组都假定以行优先的顺序存储它们的元素。

主机应用程序

到目前为止,我们已经实现了将在 FPGA 器件上“运行”的所有代码。剩下的部分构成了代码的大部分,用于主机设备(CPU)和内存管理以及内核调度。

[Matrix](https://github.com/dsuess/nn-on-fpgas/blob/4811b23d4fd4300c53a2f7638d5b9deee93a051d/src/matrix.hpp#L37) 抽象出内存管理以及主机设备内存传输。使用 Vitis 的一个主要限制是,复制到 FPGA 器件或从 FPGA 器件复制的所有存储器都需要在主机器件上按页对齐,即起始地址和存储器大小都必须能被页大小整除。为此,我们使用一个定制分配器,其中DEFAULT_ALIGNMENT被硬编码为页面大小4096:

**template** **<typename** **T>**
T ***aligned_alloc(**std**::size_t** num**,** std**::size_t** alignment **=** DEFAULT_ALIGNMENT**)**
**{**
    **void** *****ptr **=** *nullptr***;**
    **if** **(**posix_memalign**(&**ptr**,** alignment**,** num ***** **sizeof(**T**)))**
    **{**
        **throw** std**::**bad_alloc**();**
    **}**
    **return** **reinterpret_cast<**T ***>(**ptr**);**
**}**

函数[to_device](https://github.com/dsuess/nn-on-fpgas/blob/4811b23d4fd4300c53a2f7638d5b9deee93a051d/src/matrix.hpp#L178)[to_cpu](https://github.com/dsuess/nn-on-fpgas/blob/4811b23d4fd4300c53a2f7638d5b9deee93a051d/src/matrix.hpp#L196)处理主机和设备之间的内存传输。我们通过实现特殊的构造函数和=-操作符来实现Matrix类的移动语义,以允许从函数中自由复制返回值。

最后,[matrix.hpp](https://github.com/dsuess/nn-on-fpgas/blob/4811b23d4fd4300c53a2f7638d5b9deee93a051d/src/matrix.hpp#L210)底部的两个助手函数为我们抽象了 OpenCL 内核调度开销。例如,apply_matmul函数将matmul_kernel应用于两个Matrix实例:

std**::**pair**<**Matrix**,** cl**::**Event**>** apply_matmul**(**Matrix **&**matrixA**,** Matrix **&**matrixB**,** cl**::**Kernel **&**kernel**,** std**::**vector**<**cl**::**Event**>** *****wait_on **=** *NULL***,** DeviceHandle **&**handle **=** HANDLE**)**
**{**
    Matrix result **=** Matrix**::**constant**(**matrixA**.**rows**,** matrixB**.**cols**,** 0.0**,** 4096**);**
    result**.**to_device**(**handle**);**
    kernel**.**setArg**(**0**,** matrixA**.**get_buffer**());**
    kernel**.**setArg**(**1**,** matrixB**.**get_buffer**());**
    kernel**.**setArg**(**2**,** matrixA**.**rows**);**
    kernel**.**setArg**(**3**,** matrixA**.**cols**);**
    kernel**.**setArg**(**4**,** matrixB**.**cols**);**
    kernel**.**setArg**(**5**,** result**.**get_buffer**());**cl**::**Event event**;**
    handle**.**q**.**enqueueTask**(**kernel**,** wait_on**,** **&**event**);**
    **return** std**::**make_pair**(**std**::**move**(**result**),** event**);**
**}**

由于 OpenCL 提供了一个异步 API,我们不只是简单地调用内核,而是将运行内核的任务放入一个命令队列。该任务可能依赖于其他先前排队的任务,这可以使用(可选)wait_on参数来表示。

对新调用的任务的引用作为类型cl::Event的第二个返回值返回。只有在这个任务被处理之后,返回值result才包含计算值。

要了解这是如何使用的,请看一下网络的正向传递:

Matrix **operator()(**Matrix **&**input**)**
    **{**
        std**::**vector**<**cl**::**Event**>** events**;**
        events**.**resize**(**3**);**
        Matrix y**;**
        std**::**tie**(**y**,** events**[**0**])** **=** apply_matmul**(**input**,** weight1**,** MATMUL_KERNEL**);**

第一层中的矩阵乘法独立于任何运算。因此,我们不传递该行中的wait_on参数。然后将 event-result 分配给events向量的第一个条目,并复制到下面的行中,以确保events的每个条目都是有效的cl::Event实例:

events**[**1**]** **=** events**[**0**];**
        events**[**2**]** **=** events**[**0**];**
        events**[**1**]** **=** apply_bias**(**y**,** bias1**,** BIAS_RELU6_KERNEL**,** **&**events**);**

指向这个向量的指针然后被传递到第一层的偏置激活部分,因为它依赖于先前的矩阵乘法来完成。此时只分配一个大小为 1 的向量也可以达到类似的效果,但是在每次额外的操作之后,我们必须调整向量的大小。接下来的几行相应地应用了网络的第二层。

std**::**tie**(**y**,** events**[**2**])** **=** apply_matmul**(**y**,** weight2**,** MATMUL_KERNEL**,** **&**events**);**
        apply_bias**(**y**,** bias2**,** BIAS_SOFTMAX_KERNEL**,** **&**events**);**
        **return** y**;**
    }

现在我们准备看看 main.cpp 中的高级实现:

**int** **main(int** argc**,** **const** **char** *****argv**[])**
**{**
    init_kernels**();****auto** model **=** FCNN**(**"weights/"**);**
    **auto** input **=** Matrix**::**from_npy**(**"weights/samples.npy"**);**
    input**.**to_device**();**

[init_kernels](https://github.com/dsuess/nn-on-fpgas/blob/f301d3053bbc0ab7baea4ea92b440add63734369/src/utils.hpp#L40)的第一次调用从一个单独的二进制文件加载 OpenCL 内核,并将对它们的引用存储在全局变量中。接下来,我们从单独的.npy文件中加载模型权重,每个张量一个。最后,我们还加载将输入到模型中的输入样本。这些.npy文件由训练脚本准备,并存储为 float32 数组。

接下来,我们运行模型,等待所有 OpenCL 事件完成,并将结果从设备复制回主机:

**auto** result **=** model**(**input**);**finish_cl_queue**();**
    result**.**to_cpu**();**
    finish_cl_queue**();**

最后,对于批处理中的每个元素,我们计算置信度得分的 argmax,以获得最终的预测,并将其打印到 stdout:

*// print argmax result*
    **for** **(int** i **=** 0**;** i **<** result**.**rows**;** i**++)**
    **{**
        **float** minval **=** **-**1**;**
        **int** idx **=** **-**1**;****for** **(int** j **=** 0**;** j **<** result**.**cols**;** j**++)**
        **{**
            **auto** val **=** result**(**i**,** j**);**
            **if** **(**minval **<** val**)**
            **{**
                idx **=** j**;**
                minval **=** val**;**
            **}**
        **}**std**::**cout **<<** idx **<<** " "**;**
    **}**
    std**::**cout **<<** std**::**endl**;**
}

我们希望你喜欢这篇文章。在随后的帖子中,我们将研究这种基线实现的性能特征,以及如何改善延迟和减少资源需求。

神经网络模型体系结构可视化

原文:https://towardsdatascience.com/neural-network-model-architecture-visualization-3c2fae610330?source=collection_archive---------15-----------------------

利用 Visualkeras 可视化 keras 模型

神经网络(来源:作者)

神经网络是机器学习的一个子集,受人脑的启发,用于解决人工智能相关的问题。它的灵感来自于人类大脑中发现的神经元,这是一个使用不同神经元连接的网络,称为神经网络。这是数据科学的一个高级领域,通常有助于解决与人工智能相关的问题。

可视化神经网络有助于理解不同层如何相互连接,以及每层之间有多少神经元。这是理解黑盒模型从内部看起来是什么样子的最佳方式之一。可视化也可以通过向某人展示模型来帮助他们理解神经网络的不同层实际上是如何相互连接的。

Visualkeras 是一个开源 Python 库,用于创建神经网络模型可视化。它是理解不同层如何连接的最佳库之一。

在本文中,我们将探索 Visualkeras 并使用它们创建一些可视化效果。

让我们开始吧…

安装所需的库

我们将从使用 pip 安装来安装 Visualkeras 开始。下面给出的命令将使用 pip 安装 Visualkeras。

pip install visualkeras

导入所需的库

在这一步中,我们将导入创建可视化所需的所有库。

from tensorflow import keras
from tensorflow.keras import layers
import visualkeras

创建模型架构

现在,我们将从创建神经网络模型开始。我们将定义一个模型使用不同的层,如密集,展*,Conv2D 等。然后我们将在那之后可视化模型。

encoder_input = keras.Input(shape=(28, 28, 1), name='img')
x = layers.Conv2D(16, 3, activation='relu')(encoder_input)
x = layers.Conv2D(32, 3, activation='relu')(x)
x = layers.MaxPooling2D(3)(x)
x = layers.Conv2D(32, 3, activation='relu')(x)
x = layers.Conv2D(16, 3, activation='relu')(x)
encoder_output = layers.GlobalMaxPooling2D()(x)
encoder = keras.Model(encoder_input, encoder_output, name='encoder')visualkeras.layered_view(encoder, to_file='encoder.png')x = layers.Reshape((4, 4, 1))(encoder_output)
x = layers.Conv2DTranspose(16, 3, activation='relu')(x)
x = layers.Conv2DTranspose(32, 3, activation='relu')(x)
x = layers.UpSampling2D(3)(x)
x = layers.Conv2DTranspose(16, 3, activation='relu')(x)
decoder_output = layers.Conv2DTranspose(1, 3, activation='relu')(x)
autoencoder = keras.Model(encoder_input, decoder_output, name='autoencoder')

在这里,您可以看到我们如何使用不同的层来定义神经网络模型。现在让我们把这个模型形象化。

模型可视化

现在我们将使用 Visualkeras 来可视化模型。

visualkeras.layered_view(autoencoder, to_file="model.png')

模型(来源:作者)

这里我们可以看到神经网络的不同层是如何连接的。这有助于理解模型从内部看起来的样子。

尝试不同的模型,创建不同的可视化效果,让我知道你在回复部分的评论。

本文是与 Piyush Ingale 合作完成的。

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

Python 中从头开始的神经网络优化器

原文:https://towardsdatascience.com/neural-network-optimizers-from-scratch-in-python-af76ee087aab?source=collection_archive---------7-----------------------

从数学和实践角度看非凸优化:Python 中的 SGD、SGDMomentum、AdaGrad、RMSprop 和 Adam

照片由 PexelsLukas 拍摄

本文将从头开始提供常见非凸优化器及其 Python 实现的简短数学表达式。理解这些优化算法背后的数学将在训练复杂的机器学习模型时启发你的观点。这篇文章的结构如下。首先,我将谈论特定的优化算法;然后,我会给出数学公式,并提供 Python 代码。所有算法都是纯 NumPy 实现的。下面是我们将要讨论的非凸优化算法

  • 随机梯度下降
  • SGDMomentum
  • 阿达格拉德
  • RMSprop
  • 圣经》和《古兰经》传统中)亚当(人类第一人的名字

先说最简单的,随机梯度下降。

随机梯度下降

SGD 是在可微误差曲面上的迭代、非凸和一阶优化算法。它是梯度下降的随机估计,其中训练数据是随机化的。这是一种计算稳定、数学上成熟的优化算法。SGD 背后的直觉是,我们对我们可以优化的参数取目标函数的偏导数,这产生了它的梯度,它显示了误差损失的增加方向。因此,我们取该梯度的负值,在损失不增加的地方向前移动。为了确保稳定和较少振荡的优化,我们引入学习率参数ŋ,然后用ŋ.乘以梯度最后,从我们可以以迭代方式优化的参数中减去获得的值。下面是 SGD 更新公式和 Python 代码。

SGD Python 实现

SGDMomentum

在 SGD 的上下文中,我们不是计算损失函数的精确导数,而是以迭代的方式在小批量上逼*它。因此,不能确定模型在损失最小化的方向上学习。为了提出更稳定、方向感知和快速的学习,我们引入了 SGDMomentum,它将下一次更新确定为梯度和前一次更新的线性组合。因此,它也考虑了以前的更新。

总的来说,动量随机梯度下降比经典下降有两个优点:

  • 快速收敛
  • 少振荡训练

下面是 SGDMomentum 的公式和 Python 代码。

其中,α是动量系数,取值范围为[0,1]。α是一个指数衰减因子,它决定了当前梯度和早期梯度对权重变化的相对贡献[1]。在α = 0 的情况下,公式正好是纯 SGD。在α = 1 的情况下,优化过程考虑了先前更新的全部历史。

SGDMomentum Python 实现

从那时起,我们将在深度学习的背景下进入更复杂的优化器。有一些广泛使用的优化算法,如 AdaGrad、RMSprop 和 Adam。它们都是自适应优化算法,即它们通过重新安排学习速率来适应学习过程,以便模型能够更有效和更快地达到期望的全局最小值。下面是公式和实现。

阿达格勒

AdaGrad 优化算法跟踪*方梯度的总和,*方梯度衰减传播到其更新历史的参数的学习速率。其数学表达式为:

其中,𝛿𝑖是梯度*方的累积和,∇𝜃𝑖是𝜃𝑖的梯度,是网络的可配置参数,𝜀是防止零除的标量。当累积和逐渐增加时,更新项的分母同时增加,导致整个更新项ŋ * ∇𝜃𝑖.的减少随着更新项√𝛿𝑖+𝜀的减小,AdaGrad 优化变得更慢。因此,当接*收敛时,AdaGrad 被卡住,因为累积和逐渐增加,使得总的更新项显著减少。

AdaGrad Python 实现

RMSprop

RMSprop 优化算法通过将衰减率乘以累积和来解决 AdaGrad 的问题,并能够在某个点之后忘记累积和的历史,这取决于有助于收敛到全局最小值的衰减项。RMSprop 的数学表达式由下式给出:

𝛼是衰落的术语。因此,这个衰减项提供了更快的收敛,并且忘记了梯度历史的累积和,从而产生了更优化的解。

RMSprop Python 实现

亚当

Adam 优化算法是 RMSprop 的发展版本,它分别采用梯度的一阶和二阶动量。因此,Adam 还解决了在关闭全局最小值时收敛缓慢的问题。在这个版本的自适应算法中,数学表达式由下式给出:

其中,𝛿𝑀𝑖是梯度的一阶衰减累积和,𝛿𝑉𝑖是梯度的二阶衰减累积和,帽子符号𝛿𝑀和𝛿𝑉是𝛿𝑀和𝛿𝑉𝑖的偏差校正值,ŋ是学习率。

Adam Python 实现

非凸优化在起作用

在计算问题公式化的背景下,理解这些优化算法背后的直觉将启发学习曲线以及深度神经网络如何从复杂数据中学习。此外,理解这些非凸算法背后的直觉将有助于您在训练机器学习模型时选择您的优化算法。在本文中,我介绍了非凸算法及其简单 Python 实现的直观观点。例如,当涉及到训练大型深度神经网络时,您会有为什么许多研究人员和数据科学家使用 Adam 优化器而不是 SGD 的直觉,因为 Adam 优化器是自适应处理的,并且与 SGD 相反,具有一阶和二阶动量。文章到此结束。如果你有问题,请告诉我。以下是方法。

我在这里

Twitter|Linkedin|Medium|Mail

参考文献

[1]维基百科撰稿人,《随机梯度下降》,维基百科,自由百科,2021 年 11 月 6 日 11:32 UTC,<https://en.wikipedia.org/w/index.php?title = random _ gradient _ descent&oldid = 1053840730>【2021 年 11 月 7 日访问】

神经网络优化器变得简单:核心算法和为什么需要它们

原文:https://towardsdatascience.com/neural-network-optimizers-made-simple-core-algorithms-and-why-they-are-needed-7fd072cd2788?source=collection_archive---------4-----------------------

动手教程,直观的深度学习

一个温和的指导,用简单的英语介绍梯度下降优化器使用的基本技术,如 SGD,Momentum,RMSProp,Adam 和其他优化器

照片由乔治·斯塔克波尔Unsplash 上拍摄

优化器是神经网络架构的关键组件。在训练期间,它们在帮助网络学会做出越来越好的预测方面发挥着关键作用。

他们通过找到最佳的模型参数集来做到这一点,如权重和偏差,以便模型可以为他们正在解决的问题产生最佳输出。

大多数神经网络最常用的优化技术是梯度下降。

大多数流行的深度学习库,如 Pytorch 和 Keras,都有大量基于梯度下降的内置优化器,如随机梯度下降(SGD)、Adadelta、Adagrad、RMSProp、Adam 等。

为什么有这么多不同的优化算法?我们如何决定选择哪一个?

如果你阅读每一个的文档,它们描述了一个如何更新模型参数的公式。每个公式是什么意思,有什么意义?

在我们准备深入研究数学之前,我这篇文章的目标是提供一些总体背景,并对每种算法如何适用有一些直觉。事实上,我不会在这里讨论公式本身,而是将它留给另一篇文章。

如果你对一般的神经网络架构感兴趣,我有一些你可能会喜欢的文章。

  1. 批处理规范—其工作原理 (显著稳定和加速模型训练的必要深度学习层)
  2. 差分和自适应学习率 ( 优化器和调度器如何用于增强模型训练和调整超参数)
  3. 图像字幕架构 (具有图像特征编码器、序列解码器和注意力的多模态 CNN 和 RNN 架构)

梯度下降优化综述

损失曲线

让我们从梯度下降算法在工作中的典型 3D 图片开始。

梯度下降损失曲线(来源

此图显示了具有两个权重参数的网络:

  • 水*面有两个轴,分别代表重量 w1 和 w2。
  • 纵轴显示了每个权重组合的损失值

换句话说,曲线的形状显示了神经网络的“损失情况”。它绘制了不同权重值的损失,而我们保持输入数据集固定。

蓝线描绘了优化过程中梯度下降算法的轨迹:

  • 它首先为两个权重选择一些随机值,然后计算损失值。
  • 在每次迭代中,当它更新它的权重值,导致更低的损失(希望如此)时,它沿着曲线移动到更低的点
  • 最后,它到达它的目标,也就是曲线底部损失最低的地方。

计算梯度

该算法基于在该点的损失曲线的梯度和学习率因子来更新权重。

梯度下降参数更新(图片由作者提供)

梯度测量斜率,是垂直方向的变化(D1)除以水*方向的变化( dW )。这意味着陡坡的坡度大,缓坡的坡度小。

计算渐变(图片由作者提供)

实践中的梯度下降

这些损失曲线有助于理解梯度下降的概念。然而,我们应该认识到这是一个理想化的场景,而不是现实的场景:

  • 上图显示了一条*滑的凸形曲线。现实中,曲线非常坎坷。

神经网络损失图(来源,经郝莉许可)

  • 其次,我们不会只有两个参数。往往有几千万或者几亿,在你的脑子里是不可能把那个形象化甚至想象出来的。

在每一次迭代中,梯度下降的工作原理是“向各个方向寻找它可以下降的最佳坡度”。那么,当最佳斜率(此时)不是最佳方向时,会发生什么呢?

  • 如果景观向一个方向陡峭倾斜,但最低点在更*缓的斜坡方向,该怎么办?
  • 或者如果周围的地形相当*坦呢?
  • 或者,如果它掉进了一个深沟,它是如何爬出来的?

这些是给它带来困难的曲线的一些例子。接下来让我们看看这些。

梯度下降优化的挑战

局部最小值

在典型的损失曲线中,除了全局最小值之外,你可能还有许多局部最小值。因为梯度下降被设计成保持向下,一旦下降到局部最小值,它发现很难再爬上斜坡。所以它可能会停留在那里,而没有达到全局最小值。

局部最小值和全局最小值(来源

鞍点

另一个关键挑战是“鞍点”的出现。这是在对应于一个参数的一个方向上曲线处于局部最小值的点。另一方面,在对应于另一参数的第二方向上,曲线处于局部最大值。

鞍点(来源

使鞍点变得棘手的是鞍点周围的区域通常相当*坦,就像一个高原。这意味着梯度接*于零。这导致优化器在第一个参数的方向上围绕鞍点振荡,而不能在第二个参数的方向上沿着斜坡下降。

因此,梯度下降错误地认为它已经找到了最小值。

沟壑

梯度下降也很难穿越峡谷。这是一个狭长的山谷,向一个方向陡峭地倾斜。山谷的两侧)和轻轻地(即。沿着山谷)在第二方向。通常这个峡谷通向最低处。由于难以导航,这种形状也被称为病理弯曲。

沟壑(经詹姆斯·马腾斯许可,改编自来源)

把这想象成一个狭窄的河谷,从山上缓缓向下倾斜,直到它在一个湖中结束。你要做的是迅速向下游的山谷方向移动。然而,梯度下降非常容易沿着山谷的两侧来回反弹,并朝着河流的方向非常缓慢地移动。

尽管他们继续使用梯度下降作为核心,但优化算法已经在普通梯度下降的基础上开发了一系列改进,以应对这些挑战。

梯度下降的第一个改进—随机梯度下降(SGD)

梯度下降通常意味着“整批梯度下降”,其中损失和梯度是使用数据集中的所有项目计算的。

相反,小批量随机梯度下降为每次训练迭代随机选择数据集的子集。

这种随机性有助于我们探索损失景观。

前面我们提到过,损失曲线是在保持输入数据集不变的情况下,通过改变模型参数获得的。但是,如果通过在每个小批量中选择不同的数据样本来改变输入,损失值和梯度也会改变。换句话说,通过改变输入数据集,每个小批量的损失曲线略有不同。

因此,即使你在一个小批次中被困在风景中的某个地方,你可能会在下一个小批次中看到不同的风景,这让你继续前进。这可以防止算法卡在景观的特定部分,尤其是在训练的早期阶段。

梯度下降的第二个改进—动量

动态调整更新量

梯度下降的一个棘手方面是处理陡坡。因为那里的坡度很大,当你真的想慢慢地、小心翼翼地前进时,你可以迈出一大步。这可能会导致来回跳动,从而减慢训练速度。

(图片由作者提供)

理想情况下,您希望动态地改变更新的幅度,以便能够对周围环境的变化做出响应。如果坡很陡,你要减速。如果斜坡非常*坦,你可能想要加速等等。

使用梯度下降,您可以根据梯度和学习率更新每一步的权重。因此,要修改更新的大小,您可以做两件事:

  • 调整渐变
  • 调整学习速度

动量 vs 新加坡元

动量是在 ie 上面做前者的一种方式。调整渐变。

使用 SGD,我们只查看当前的梯度,而忽略我们所走路径上所有过去的梯度。这意味着,如果损失曲线突然出现异常,你的轨迹可能会偏离轨道。

另一方面,当使用动量时,你让过去的梯度引导你的整体方向,这样你就能保持在正确的方向上。这让你可以利用到那时为止你所看到的周围景观的知识,并有助于抑制损失曲线中异常值的影响。

  1. 第一个问题是你能追溯到过去多久?越往后走,受异常的影响就越小。
  2. 其次,从过去开始的每一个梯度都同样重要吗?不久前的事情应该比遥远过去的事情更重要,这是有道理的。因此,如果环境的变化不是暂时的异常,而是真正的结构性变化,那么你确实需要对此做出反应,并逐渐改变你的路线。

动量算法使用梯度的指数移动*均值,而不是当前梯度值。

利用动量穿越峡谷

动量帮助您解决病理曲率的狭窄峡谷问题,其中一个权重参数的梯度非常高,而另一个参数的梯度非常低。

冲力帮助你穿越峡谷(经詹姆斯·马腾斯许可,由来源修改)

通过使用动量,你可以抑制 SGD 可能出现的曲折振荡。

  • 对于具有陡坡的第一个参数,大的坡度导致从山谷的一侧到另一侧呈“之”字形。然而,在下一步中,这被反方向的“曲折”抵消了。
  • 另一方面,对于第二参数,来自第一步骤的小更新被第二步骤的小更新加强,因为它们在相同的方向上。这是你想去的山谷的方向。

使用不同公式的动量优化算法的一些示例如下:

  • 带动量的 SGD
  • 涅斯托罗夫加速梯度

梯度下降的第三个改进——修改学习率(基于梯度)

如上所述,修改参数更新量的第二种方式是通过调整学习速率。

到目前为止,从一次迭代到下一次迭代,我们一直保持学习速率不变。其次,梯度更新对所有参数使用相同的学习速率。

然而,正如我们已经看到的,不同参数的梯度之间可能有很大的变化。一个参数可能有一个陡坡,而另一个有一个缓坡。

我们可以利用这一点来调整每个参数的学习速率。我们可以利用过去的梯度(分别针对每个参数)来选择该参数的学习速率。

有一些优化算法可以做到这一点,使用稍微不同的技术,如 Adagrad,Adadelta,RMS Prop。

例如,Adagrad 将过去的梯度*方并相加,对它们进行*均加权。RMSProp 也对过去的梯度求*方,但是使用它们的指数移动*均值,因此给予最*的梯度更多的重要性。

现在,通过*方梯度,它们都变成正的。方向一致。这否定了我们讨论动量的抵消效应,梯度方向相反。

这意味着对于一个斜率很陡的参数,梯度很大,梯度的*方也很大,并且总是正的,所以它们积累得很快。为了抑制这种情况,该算法通过将累积的*方梯度除以一个较大的因子来计算学习率。这使得它在陡坡上减速。

类似地,对于较浅的斜率,累积较小,因此该算法将累积的*方除以较小的因子来计算学习率。这提高了缓坡的学习速度。

一些优化器算法结合了这两种方法——如上修改学习率,以及使用动量来修改梯度。亚当和它的许多变种,羔羊。

梯度下降的第四个改进——修改学习率(根据你的训练进度)

在前面的部分中,基于参数的梯度修改了学习率。此外,我们可以根据训练过程的进度调整学习速度。学习率是基于训练时期设置的,并且与该点的模型参数无关。

这其实根本不是优化人员做的。事实上,它是被称为调度器的神经网络的一个独立组件。我提到这一点是为了完整性,并显示与我们已经讨论过的优化技术的关系,但在这里不会进一步讨论它们。

结论

我们现在了解了基于梯度下降的优化器所使用的基本技术,为什么使用它们,以及它们之间的关系。

这使我们能够更深入地研究许多具体的优化算法,并详细了解它们是如何工作的。我希望很快在另一篇文章中讨论这个问题…

最后,如果你喜欢这篇文章,你可能也会喜欢我关于变形金刚、音频深度学习和地理定位机器学习的其他系列。

让我们继续学习吧!

神经网络修剪 101

原文:https://towardsdatascience.com/neural-network-pruning-101-af816aaea61?source=collection_archive---------2-----------------------

你需要知道的是不要迷路

无论是在计算机视觉、自然语言处理还是图像生成方面,深度神经网络都达到了最先进的水*。然而,它们在计算能力、内存或能耗方面的成本可能令人望而却步,这使得它们中的一些对于大多数有限的硬件来说完全负担不起。然而,许多领域将受益于神经网络,因此需要在保持其性能的同时降低其成本。

这就是神经网络压缩的全部意义。这个领域统计了多个方法家族,比如量化[11],因式分解[13],蒸馏[32]或者,这将是这篇帖子修剪的重点。

神经网络修剪是一种方法,它围绕着一个直观的想法,即删除网络中表现良好但耗费大量资源的多余部分。事实上,尽管大型神经网络已经无数次证明了它们的学习能力,但事实证明,在训练过程结束后,并非所有的部分都仍然有用。想法是在不影响网络性能的情况下消除这些部分。

不幸的是,每年发表的几十篇论文,如果不是几百篇的话,揭示了一个被认为是直截了当的想法隐藏的复杂性。事实上,在训练之前、之中或之后,文献的快速浏览产生了无数种识别所述无用部分或移除它们的方法;事实证明,并不是所有的修剪都可以加速神经网络,而这才是最重要的。

这篇文章的目标是提供一个坚实的基础,以解决神经网络修剪周围令人生畏的野生文学。我们将依次回顾三个问题,它们似乎是整个领域的核心:“我应该修剪什么样的部分?”,“如何判断哪些部分可以修剪?”以及“如何在不损害网络的情况下删减部分内容?”。综上所述,我们将详细介绍修剪结构修剪标准修剪方法

1-修剪结构

1.1 —非结构化修剪

当谈到神经网络的成本时,参数计数肯定是使用最广泛的指标之一,还有 FLOPS(每秒浮点运算次数)。看到网络显示天文数字的重量(对一些人来说高达数十亿)确实令人生畏,这通常与恒星的性能相关。因此,通过删除参数本身来直接减少这个计数是非常直观的。实际上,修剪连接是文献中最普遍的范例之一,足以被认为是处理修剪时的默认框架。韩等人的开创性工作[26]提出了这种修剪,并作为许多贡献的基础[18,21,25]。

直接修剪参数有很多好处。首先,这很简单,因为在参数张量中用零替换它们的权重值就足以删除连接。广泛的深度学习框架,如 Pytorch,允许轻松访问网络的所有参数,使其实现起来极其简单。尽管如此,修剪连接的最大优点仍然是它们是网络中最小的、最基本的元素,因此,它们数量众多,足以大量修剪它们而不影响性能。这种精细的粒度允许修剪非常细微的模式,例如高达卷积核内的参数。由于修剪权重完全不受任何约束的限制,并且是修剪网络的最佳方式,这样的范例被称为非结构化修剪

然而,这种方法存在一个重大的致命缺陷:大多数框架和硬件都无法加速稀疏矩阵的计算,这意味着无论你用多少个零填充参数张量,都不会影响网络的实际成本。然而,真正影响它的是以一种直接改变网络架构的方式进行修剪,这是任何框架都可以处理的。

非结构化剪枝(左)和结构化剪枝(右)的区别:结构化剪枝移除卷积滤波器和核的行,而不仅仅是剪枝连接。这导致中间制图表达中的要素地图更少。(图片由作者提供)

1.2 —结构化修剪

这就是为什么许多工作都集中在修剪更大的结构,如整个神经元[36],或更现代的深度卷积网络中的直接等效物,卷积滤波器[40,41,66]。过滤器修剪允许可利用且足够精细的粒度,因为大型网络往往包括许多卷积层,每个卷积层多达数百或数千个过滤器。移除这样的结构不仅导致可以直接实例化为更薄的层的稀疏层,而且这样做还消除了作为这样的过滤器的输出的特征图。

因此,这种网络不仅由于更少的参数而更易于存储,而且它们需要更少的计算并生成更轻的中间表示,因此在运行时需要更少的存储器。实际上,有时减少带宽比减少参数数量更有益。事实上,对于涉及大型图像的任务,如语义分割或对象检测,中间表示可能会非常消耗内存,远远超过网络本身。由于这些原因,过滤器修剪现在被视为默认的结构化修剪

然而,当应用这种修剪时,应该注意以下方面。让我们考虑一个卷积层是如何构建的:对于 Cin 输入通道和 Cout 输出通道,一个卷积层由 Cout 滤波器组成,每个滤波器计数 Cin 内核;每个滤波器输出一个特征图,并且在每个滤波器内,一个内核专用于每个输入通道。考虑到这种架构,并且承认常规卷积网络基本上堆叠卷积层,当修剪整个滤波器时,可以观察到修剪滤波器以及它输出的特征图实际上也导致修剪随后层中的相应核。这意味着,在删除过滤器时,实际删除的参数数量可能是最初认为要删除的两倍。

让我们也考虑一下,当整个层碰巧被修剪时(由于层折叠[62]而倾向于发生,但并不总是破坏网络,这取决于架构),前一层的输出现在完全不连接,因此也被修剪:修剪整个层实际上可以修剪其输出没有以某种方式连接到别处的所有前一层(由于剩余连接[28]或整个并行路径[61])。因此,在修剪滤波器时,应该考虑计算实际修剪参数的确切数量。事实上,修剪相同数量的滤波器(取决于它们在架构中的分布)可能不会导致相同的实际修剪参数数量,从而无法比较任何结果。

在改变话题之前,让我们提一下,尽管是少数,一些工作集中在修剪卷积核,核内结构[2,24,46]或甚至 T10 特定的参数式结构 T11。然而,这种结构需要特殊的实现来加速(对于非结构化修剪)。然而,另一种可利用的结构是通过修剪每个内核中除一个参数之外的所有参数,将卷积转变为“移位层”,然后可以总结为移位操作和 1 × 1 卷积的组合[24]。

结构化修剪的危险:改变层的输入和输出维度会导致一些差异。如果在左侧,两个图层都输出相同数量的特征地图,并且可以在之后很好地进行汇总,则它们在右侧的修剪后的对应物会产生不同维度的中间表示,如果不对其进行处理,则无法进行汇总。(图片由作者提供)

2 —修剪标准

一旦决定了要修剪什么样的结构,下一个问题可能是:“现在,我如何确定哪些要保留,哪些要修剪?”。为了回答这个问题,我们需要一个合适的剪枝标准,它将对参数、过滤器或其他的相对重要性进行排序。

2.1-重量等级标准

一个非常直观且效率惊人的标准是修剪绝对值(或“幅度”)最小的权重。事实上,在权重衰减的约束下,那些对功能没有显著贡献的预期在训练期间具有它们的大小收缩。因此,多余的重量应该是较小的重量[8]。尽管它很简单,但震级标准仍然被广泛应用于现代著作[21,26,58],使其成为该领域的主要内容。

然而,尽管这个标准在非结构化修剪的情况下实现起来似乎微不足道,但是人们可能想知道如何使它适应结构化修剪。一种简单的方法是根据滤波器的范数(例如 L 1 或 L 2)对滤波器进行排序[40,70]。如果这种方法非常简单,人们可能希望将多组参数封装在一个度量中:例如,卷积滤波器、其偏差及其批量归一化参数,或者甚至是并行层中的对应滤波器,其输出随后被融合,并且我们希望减少其通道。

一种无需计算这些参数的组合范数的方法是,在要修剪的每组图层后为每个要素地图插入一个可学习的乘法参数。当该门减小到零时,有效地删除了负责该通道的整个参数集,并且该门的大小说明了所有这些参数的重要性。因此,该方法包括修剪较小幅度的门[36,41]。

2.2 —梯度幅度修剪

重量的大小并不是唯一流行的标准(或标准系列)。实际上,另一个一直持续到现在的主要标准是梯度的大小。事实上,早在 80 年代,一些基础工作[37,53]通过对移除参数对损失的影响进行泰勒分解,理论上认为,从反向传播梯度中得出的一些度量可以提供一种很好的方法来确定哪些参数可以被删除而不会损坏网络。

这个标准的更现代的实现[4,50]实际上在训练数据的小批量上累积梯度,并且基于这个梯度和每个参数的相应权重之间的乘积进行修剪。这一标准也适用于前述的门[49]。

2.3 —全局或局部修剪

要考虑的最后一个方面是,所选择的标准是全局应用于网络的所有参数或滤波器,还是针对每一层独立计算。虽然全局修剪已经被多次证明可以产生更好的结果,但它会导致层崩溃[62]。避免这个问题的一个简单方法是,当所使用的方法不能防止层崩溃时,采取逐层的局部修剪,即在每层修剪相同的速率。

局部修剪(左)和全局修剪(右)之间的区别:局部修剪将相同的速率应用于每一层,而全局修剪将它同时应用于整个网络。(图片由作者提供)

3 —修剪方法

现在我们已经有了剪枝结构和标准,剩下的唯一参数是我们应该使用哪种方法来剪枝网络。这实际上是文献中最令人困惑的主题,因为每篇论文都会带来自己的怪癖和噱头,以至于人们可能会迷失在什么是系统相关的和什么只是给定论文的特殊性之间。

这就是为什么我们将按主题概述一些最流行的修剪神经网络的方法,以便突出在训练期间使用稀疏性的演变。

3.1 —经典框架:训练、修剪和微调

需要了解的第一个基本框架是训练、修剪和微调方法,该方法显然包括 1)训练网络 2)通过将修剪结构和标准所针对的所有参数设置为 0 来修剪网络(这些参数不能在一段时间后恢复),以及 3)以最低的学习速率训练网络几个额外的时期,以使其有机会从修剪所导致的性能损失中恢复。通常,这最后两个步骤可以重复进行,每次修剪的速度越来越快。

Han 等人[26]提出的方法将该方法应用于权重幅度修剪,在修剪和微调之间有 5 次迭代。迭代已经证明可以提高性能,但代价是额外的计算和训练时间。这个简单的框架是许多作品的基础[26,40,41,50,66],并且可以被视为所有其他作品的默认构建方法。

3.2 —扩展经典框架

虽然没有偏离太远,但一些方法对前面提到的韩等人的经典框架进行了重大修改[26]。Gale 等人[21]通过在整个训练过程中逐步去除越来越多的权重,进一步推动了迭代的原理,这允许受益于迭代的优点,并去除了整个微调过程。He 等人[29]在每个时期将可修剪的滤波器减少到 0,同时不阻止它们学习和随后被更新,以便让它们的权重在修剪后恢复,同时在训练期间加强稀疏性。

最后,Renda 等人[58]的方法包括在网络被修剪后对其进行完全再训练。与以最低学习率进行的微调不同,再培训遵循与培训相同的学习率计划,因此得名“学习率倒带”。事实证明,这种再培训比单纯的微调能产生更好的效果,但成本要高得多。

3.3 —初始化时修剪

为了加速训练,避免微调,并防止在训练期间或之后对体系结构的任何改变,许多工作都集中在训练之前的修剪上。在 SNIP [39]之后,许多著作研究了使用 Le Cun 等人[37]或莫泽尔和斯摩棱斯基[53]的工作在初始化[12,64]时进行修剪,包括深入的理论研究[27,38,62]。然而,最佳脑损伤[37]依赖于多种*似,包括“极端”*似,即“假设参数删除将在训练收敛后进行”[37];这个事实很少被提及,甚至在以它为基础的作品中。一些作品对这种方法生成的掩模的能力提出了保留意见,这些掩模的相关性胜过每层类似分布的随机掩模[20]。

另一个研究剪枝和初始化之间关系的方法家族倾向于“彩票假说”[18]。这一假设指出“随机初始化的密集神经网络包含一个子网网络,该子网网络被初始化,使得在隔离训练时,它可以在最多相同次数的迭代训练后匹配原始网络的测试精度”。在实践中,该文献研究了使用已经收敛的网络定义的修剪掩码在网络刚刚初始化时应用于网络的效果。多部著作扩展、稳定或研究了这一假设[14,19,45,51,69]。然而,又一次,多项工作倾向于质疑假设的有效性和用于研究它的方法[21,42],一些工作甚至倾向于表明,它的好处更多地来自于使用确定的面具而不是假设的“中奖彩票”进行充分训练的原则[58]。

经典的“训练、修剪和微调”框架[26]、彩票实验[18]和学习率倒回[58]之间的比较。(图片由作者提供)

3.4 —稀疏训练

先前的方法被一个看似共享的潜在主题联系在一起:稀疏约束下的训练。这一原则是一系列方法的核心,称为稀疏训练,包括在训练期间实施恒定的稀疏率,同时其分布变化并逐步调整。由 Mocanu 等人[47]介绍,它包括:1)用一个随机掩码初始化网络,该掩码修剪网络的一定比例;2)在一个时期内训练这个修剪的网络;3)修剪一定量的较低幅度的权重;以及 4)重新生长相同量的随机权重。

通过这种方式,最初随机的剪枝掩码被逐步调整为以最小的导入权重为目标,同时在整个训练过程中实施稀疏性。对于每一层[47]或全局[52],稀疏水*可以是相同的。其他方法扩展了稀疏训练,使用某种标准来重新生成权重,而不是随机选择它们[15,17]。

稀疏训练在训练期间周期性地减少和增加不同的权重,这导致调整后的掩码应该只针对相关参数。(图片由作者提供)

3.5 —面具学习

多种方法集中于在训练期间学习修剪掩模,而不是依赖于任意标准来修剪或重新生长权重。两种类型的方法似乎在该领域中流行:1)通过单独的网络或层的掩模学习,以及 2)通过辅助参数的掩模学习。多种策略可以适用于第一种类型的方法:训练单独的代理在最大化准确性的同时尽可能多地修剪一层的过滤器[33],插入基于注意力的层[68]或使用强化学习[30]。第二种方法旨在将修剪视为一个优化问题,该优化问题倾向于最小化网络的 L0 范数及其监督损失。

因为 L0 是不可微的,所以各种方法主要涉及通过使用在正向传递过程中与其相应参数相乘的惩罚辅助参数来规避这个问题[59,23]。许多方法[44,60,67]依赖于一种类似于“二元连接”[11]的方法,即:在参数上应用随机门,这些参数的值每个都是从它们自己的参数 p 的伯努利分布中随机抽取的,这些参数是使用“直通估计器”[3]或其他手段[44]学习的。

3.6 —基于惩罚的方法

许多方法不是手动修剪连接或惩罚辅助参数,而是对权重本身应用各种惩罚,使它们逐渐向 0 收缩。这个概念实际上是非常古老的[57],因为重量衰减已经是重量级标准的一个基本要素。除了使用简单的权重衰减之外,即使在当时,也有许多工作专注于精心设计专门用于增强稀疏性的惩罚[55,65]。如今,各种方法在权重衰减的基础上应用不同的正则化,以进一步增加稀疏度(通常使用 L 1 范数[41])。

在现代作品中,多种方法依赖于 LASSO(最小绝对收缩和选择算子)[22,31,66]来修剪权重或组。其他方法开发了针对弱连接的惩罚,以增加要保留的参数和要删减的参数之间的差距,从而使它们的删除影响较小[7,16]。一些方法表明,通过在整个训练过程中不断增长的惩罚来瞄准权重的子集,可以逐步修剪它们,并使它们的去除无缝[6,9,63]。该文献还列举了一系列围绕“变分放弃”原则建立的方法[34],这是一种基于变分推理[5]的方法,适用于深度学习[35]。作为一种修剪方法[48],它产生了多种作品,使其原理适应结构化修剪[43,54]。

4 —可用框架

如果这些方法中的大多数必须从头实现(或者可以从每篇论文提供的资源中重用,如果它们提供的话),那么存在一些框架来应用基本方法或使上述实现更容易。

4.1 — Pytorch

py torch【56】提供多种生活质量特征,帮助修剪网络。所提供的工具允许容易地将掩码应用于网络,并在训练期间维护该掩码,并且如果需要,还允许容易地恢复该掩码。Pytorch 还提供了一些基本的剪枝方法,比如全局或局部剪枝,无论是否结构化。结构化剪枝可以应用于权重张量的任何维度,这允许剪枝过滤器、内核的行或者甚至内核内部的一些行和列。那些内置的基本方法也允许随机或根据各种规范进行修剪。

4.2 —张量流

来自tensor flow【1】的Keras【10】库提供了一些基本工具来修剪较低量级的权重。如在 Han 等人[25]的工作中,修剪的效率是根据由所有插入的零引入的冗余允许更好地压缩模型的程度来测量的(这与量化结合得很好)。

4.3 —收缩基准

Blalock 等人4在他们的工作中提供了一个定制库,以帮助社区规范剪枝算法的比较。基于py torch,shrink bench旨在使修剪方法的实现更容易,同时规范它们被训练和测试的条件。它提供了不同的基线,如随机剪枝、全局或分层剪枝以及权重幅度或梯度幅度剪枝。

5 —简要回顾已审查的方法

在这篇文章中,引用了许多论文。下面是一个简单的表格,大致总结了它们的作用和区别(假设日期是第一次出版的日期):

6 —结论

在我们对文献的快速概述中,我们看到 1)修剪结构定义了从修剪中预期哪种增益 2)修剪标准基于各种理论或实践的合理性,以及 3)修剪方法倾向于围绕在训练期间引入稀疏性来调和性能和成本。我们还看到,即使它的创始工作可以追溯到 80 年代末,神经网络修剪仍然是一个非常动态的领域,今天仍然经历着基本的发现和新的基本概念。

尽管该领域每天都有贡献,但似乎仍有大量探索和创新的空间。如果方法的每一个子类都可以被看作是对一个问题的回答(“如何重新生成修剪过的权重?”、“如何通过优化学习剪枝遮罩?”、“如何用更柔和的手段放松减肥?”…),那么文献的演变似乎指出了一个确定的方向:贯穿训练的稀疏性。这个方向给自己提出了许多问题,例如:“修剪标准在还没有收敛的网络上工作得好吗?”或者“如何从一开始就区分选择要修剪的权重和使用任何稀疏度进行训练的好处?”

参考

[1]马丁·阿巴迪、阿希什·阿加瓦尔、保罗·巴勒姆、尤金·布莱夫多、陈质枫、克雷格·西特罗、格雷格·科拉多、安迪·戴维斯、杰弗里·迪恩、马蒂厄·德文、桑杰·格玛瓦特、伊恩·古德菲勒、安德鲁·哈普、杰弗里·欧文、迈克尔·伊萨德、杨青·贾、拉斐尔·约泽福维茨、卢卡斯·凯泽、曼朱纳斯·库德鲁尔、乔希·莱文伯格、蒲公英·曼内、拉杰特·蒙加、雪莉·穆尔、德里克·默里、克里斯·奥拉、迈克·舒斯特 TensorFlow:异构系统上的大规模机器学习,2015。tensorflow.org 提供的软件。

2赛义德·安瓦尔、黄奎元和宋元勇。深度卷积神经网络的结构化剪枝。ACM 计算系统新兴技术期刊(JETC),13(3):1–18,2017。

[3]约舒阿·本吉奥、尼古拉斯·莱昂纳尔和亚伦·库维尔。为条件计算通过随机神经元估计或传播梯度。arXiv 预印本 arXiv:1308.3432,2013。

4戴维斯·布拉洛克、何塞·哈维尔·冈萨雷斯·奥尔蒂斯、乔纳森·弗兰克尔和约翰·古塔格。神经网络剪枝是什么状态?arXiv 预印本:2003.03033,2020。

[5]戴维·布莱、阿尔普·库库尔比尔和乔恩·麦考利夫。统计学家评论。美国统计协会杂志,112(518):859–877,2017。

6米格尔·卡雷拉-佩皮南和叶尔兰·伊德尔巴耶夫。神经网络剪枝的“学习-压缩”算法。IEEE 计算机视觉和模式识别会议论文集,第 8532-8541 页,2018 年。

[7]景长与金莎。用改进的 L1/2 罚函数修剪深度神经网络。IEEE 访问,7:2273–2280,2018。

[8]伊夫·肖万。优化使用隐藏单元的反向传播算法。NIPS,第 1 卷,第 519–526 页,1988 年。

[9] Yoojin Choi、Mostafa El-Khamy 和 Jungwon Lee。联合稀疏约束下的深度卷积神经网络压缩。arXiv 预印本 arXiv:1805.08303,2018。

[10] Francois Chollet 等人,Keras,2015 年。

[11] Matthieu Courbariaux、Yoshua Bengio 和 Jean-Pierre David。Binaryconnect:在传播过程中使用二进制权重训练深度神经网络。在日本,2015 年。

12 Pau de Jorge、Amartya Sanyal、Harkirat S Behl、Philip HS Torr、Gregory Rogez 和 Puneet K Dokania。渐进骨架化:在初始化时从网络中剔除更多脂肪。arXiv 预印本 arXiv:2006.09081,2020。

[13]艾米莉·丹顿、沃伊切赫·扎伦巴、琼·布鲁纳、扬·勒昆和罗布·弗格斯。利用卷积网络中的线性结构进行有效评估。2014 年第 28 届神经信息处理系统年会,NIPS 2014,第 1269–1277 页。神经信息处理系统基金会,2014 年。

[14] Shrey Desai,Hongyuan Zhan 和 Ahmed Aly。分布转移下的彩票评估。《第二届低资源 NLP 深度学习方法研讨会论文集》(DeepLo 2019),第 153–162 页,2019 年。

15 蒂姆·德特默斯和卢克·塞特勒莫耶。稀疏网络从零开始:更快的训练而不损失性能。arXiv 预印本 arXiv:1907.04840,2019。

[16]丁小涵、丁桂光、周、郭、韩和。用于修剪深度神经网络的全局稀疏动量 sgd。arXiv 预印本 arXiv:1909.12778,2019。

17 乌特库·埃夫西、特雷弗·盖尔、雅各布·梅尼克、巴勃罗·萨缪尔·卡斯特罗和埃里希·埃尔森。操纵彩票:让所有彩票中奖。在机器学习国际会议上,第 2943–2952 页。PMLR,2020 年。

18 乔纳森·弗兰克尔和迈克尔·卡宾。寻找稀疏的、可训练的神经网络。arXiv 预印本 arXiv:1803.03635,2018。

[19] Jonathan Frankle,Gintare Karolina Dziugaite,Daniel M Roy 和 Michael Carbin。稳定彩票假说。arXiv 预印本 arXiv:1903.01611,2019。

[20] Jonathan Frankle,Gintare Karolina Dziugaite,Daniel M Roy 和 Michael Carbin。在初始化时修剪神经网络:为什么我们会遗漏标记?arXiv 预印本 arXiv:2009.08576,2020。

[21]特雷弗·盖尔,埃里希·埃尔森和萨拉·胡克。深度神经网络中的稀疏状态。arXiv 预印本 arXiv:1902.09574,2019。

[22]苏珊·高、、钱隆生、威廉·张和何塞·M·阿尔瓦雷斯。Vacl:用于修剪深度残差网络的方差感知跨层正则化。IEEE/CVF 国际计算机视觉研讨会论文集,第 0-0 页,2019。

[23]、郭、姚安邦和。高效 dnns 的动态网络手术。在 NIPS,2016。

[24] Ghouthi Boukli Hacene、Carlos Lassance、Vincent Gripon、Matthieu Courbariaux 和 Yoshua Bengio。基于注意力的移位网络剪枝。2020 年第 25 届国际模式识别会议(ICPR),第 4054–4061 页。IEEE,2021。

[25]宋汉,毛和威廉 J 戴利。深度压缩:通过剪枝、训练量化和霍夫曼编码压缩深度神经网络。arXiv 预印本 arXiv:1510.00149,2015。

[26]宋汉、杰夫·普尔、约翰·特兰和威廉·J·戴利。学习有效神经网络的权值和连接。在日本,2015 年。

[27]苏菲亚内·哈尤、江泽龙·东、阿诺·杜塞和伊怀德。初始化时的健壮修剪。

[28],何,,,任,。用于图像识别的深度残差学习。IEEE 计算机视觉和模式识别会议论文集,第 770–778 页,2016 年。

[29]杨何,,康,董宣义,,傅,。加速深度卷积神经网络的软滤波器修剪。arXiv 预印本 arXiv:1808.06866,2018。

[30],何继林,,,王,李,,宋汉.Amc:用于移动设备上模型压缩和加速的 Automl。《欧洲计算机视觉会议论文集》(ECCV),第 784-800 页,2018 年。

[31]何、、、。加速深度神经网络的通道剪枝。IEEE 计算机视觉国际会议论文集,第 1389-1397 页,2017 年。

32 Geoffrey hint on、Oriol Vinyals 和 Jeff Dean。从神经网络中提取知识。统计,2015 年 10:50:9。

[33]黄乾贵,,苏亚友,和乌尔里希·诺依曼。学习修剪卷积神经网络中的滤波器。2018 年 IEEE 计算机视觉应用冬季会议(WACV),第 709–718 页。IEEE,2018。

[34]迪德里克·P·金马、蒂姆·萨利曼斯和马克斯·韦林。变分丢失和局部重新参数化技巧。统计,2015 年 10:50:8。

[35]迪德里克·金马和马克斯·韦林。自动编码变分贝叶斯。统计,2014 年 1050:1。

[36]约翰·克鲁施克和哈维尔·莫韦兰。增益的好处:加速学习和最小化反向传播网络中的隐藏层。IEEE 系统、人和控制论汇刊,21(1):273–280,1991。

[37]扬·勒昆、易小轩·登克和萨拉·索拉最佳脑损伤。神经信息处理系统进展,598-605 页,1990。

[38] Namhoon Lee,Thalaiyasingam Ajanthan,Stephen Gould 和 Philip HS Torr。初始化时修剪神经网络的信号传播观点。在 2019 年国际学习代表大会上。

[39] Namhoon Lee,Thalaiyasingam Ajanthan 和 Philip HS Torr。Snip:基于连接敏感度的单次网络剪枝。2019 年 ICLR 国际学习代表大会。

[40]李浩、阿西姆·卡达夫、伊戈尔·杜尔丹诺维奇、哈南·萨梅特和汉斯·彼得·格拉夫。高效网络的剪枝滤波器。arXiv 预印本 arXiv:1608.08710,2016。

[41],,,,严守孟,张长水。通过网络瘦身学习高效卷积网络。IEEE 计算机视觉国际会议论文集,第 2736-2744 页,2017。

[42]、孙明杰、周廷辉、和特雷弗·达雷尔。重新思考网络修剪的价值。在 2018 年国际学习代表大会上。

43 路易索斯、乌烈芝和韦林用于深度学习的贝叶斯压缩。第 31 届神经信息处理系统会议(NIPS 2017),美国加州长滩。, 2017.

[44]克里斯特斯·路易斯、马克斯·韦林和迪德里克·金马。通过 l 0 正则化学习稀疏神经网络。arXiv 预印本 arXiv:1712.01312,2017。

[45] Eran Malach,Gilad Yehudai,Shai Shalev-Schwartz 和 Ohad Shamir。证明彩票假说:修剪是你所需要的。在机器学习国际会议上,第 6682–6691 页。PMLR,2020 年。

[46]蕙子·毛、宋汉、杰夫·普尔、、、和威廉·J·戴利探索卷积神经网络中稀疏结构的规律性。arXiv 预印本 arXiv:1705.08922,2017。

[47] Decebal Constantin Mocanu、Elena Mocanu、皮特·斯通、Phuong H Nguyen、Madeleine Gibescu 和 Antonio Liotta。受网络科学启发的具有自适应稀疏连接的人工神经网络的可扩展训练。自然通讯,9(1):1–12,2018。

[48] Dmitry Molchanov、Arsenii Ashukha 和 Dmitry Vetrov。变分丢失使深度神经网络稀疏化。在机器学习国际会议上,第 2498–2507 页。PMLR,2017。

[49] Pavlo Molchanov、Arun Mallya、Stephen Tyree、Iuri Frosio 和 Jan Kautz。神经网络剪枝的重要性估计。IEEE/CVF 计算机视觉和模式识别会议论文集,第 11264-11272 页,2019 年。

[50] Pavlo Molchanov、Stephen Tyree、Tero Karras、Timo Aila 和 Jan Kautz。修剪卷积神经网络进行资源有效的推理。arXiv 预印本 arXiv:1611.06440,2016。

[51]Ari S . Morcos、余浩南、Michela Paganini 和田远东。一张票赢所有人:跨数据集和优化器推广彩票初始化。统计,2019 年 1050:6。

52 希沙姆·穆斯塔法和王欣。通过动态稀疏重新参数化的深度卷积神经网络的参数有效训练。在机器学习国际会议上,第 4646–4655 页。PMLR,2019。

53 迈克尔·莫泽尔和保罗·斯摩棱斯基。骨架化:一种通过相关性评估从网络中剔除脂肪的技术。神经信息处理系统进展,107-115 页,1989。

[54] Kirill Neklyudov、Dmitry Molchanov、Arsenii Ashukha 和 Dmitry Vetrov。基于对数正态乘性噪声的结构化贝叶斯剪枝。《第 31 届神经信息处理系统国际会议论文集》,第 6778–6787 页,2017 年。

55 史蒂文·J·诺兰和杰弗里·E·辛顿。通过软加权共享简化神经网络。神经计算,4(4):473–493,1992。

[56] Adam Paszke、Sam Gross、Soumith Chintala、Gregory Chanan、杨德昌、Zachary DeVito、林泽铭、Alban Desmaison、Luca Antiga 和 Adam Lerer。pytorch 中的自动微分。2017.

57 拉塞尔·里德。剪枝算法-综述。IEEE 神经网络汇刊,4(5):740–747,1993。

58 亚历克斯·伦达、乔纳森·弗兰克尔和迈克尔·卡宾。比较神经网络剪枝中的倒回和微调。arXiv 预印本 arXiv:2003.02389,2020

[59]佩德罗·萨瓦雷塞、乌戈·席尔瓦和迈克尔·梅尔。用持续的稀疏赢得彩票。神经信息处理系统进展,33,2020。

[60] Suraj Srinivas、Akshayvarun Subramanya 和 R Venkatesh Babu。训练稀疏神经网络。IEEE 计算机视觉和模式识别研讨会会议录,第 138-145 页,2017 年。

[61]克里斯蒂安·塞格迪、贾、皮埃尔·塞尔马内、斯科特·里德、德拉戈米尔·安盖洛夫、杜米特鲁·埃汉、文森特·万霍克和安德鲁·拉宾诺维奇。用回旋越走越深。IEEE 计算机视觉和模式识别会议论文集,第 1–9 页,2015。

[62]田畑秀则·田中、丹尼尔·库宁、丹尼尔·亚明斯和苏里亚·甘古利。通过迭代保存突触流来修剪没有任何数据的神经网络。神经信息处理系统进展,33,2020。

[63] Hugo Tessier、Vincent Gripon、Mathieu Léonardon、Matthieu Arzel、Thomas Hannagan 和 David Bertrand。重新思考有效神经网络修剪的权重衰减。2021.

[64]齐超·王、,和罗杰·格罗斯。通过保持梯度流在训练前挑选中奖票。在 2019 年国际学习代表大会上。

[65]安德烈亚斯·韦根德、戴维·鲁梅尔哈特和贝尔纳多·胡伯尔曼。加权消除泛化及其在预测中的应用。神经信息处理系统进展,875-882 页,1991。

[66]魏文、吴、王燕丹、陈、。深度神经网络中的结构化稀疏学习。在 NIPS,2016。

[67]小霞、王自庚和 Sanguthevar Rajasekaran。Autoprune:通过正则化辅助参数来自动修剪网络。神经信息处理系统进展,32,2019。

[68]山本康*和仓藤前野。PCA:用注意力统计剪枝通道进行深度网络压缩。arXiv 预印本 arXiv:1806.05382,2018。

[69] Hattie Zhou、Janice Lan、Rosanne Liu 和 Jason Yosinski。解构彩票:零,标志,和超级面具。arXiv 预印本 arXiv:1905.01067,2019。

[70]庄、谭明奎、庄博汉、、、吴庆尧、黄和。深度神经网络的区分感知通道剪枝。在 NeurIPS,2018。

神经网络:死亡的神经元

原文:https://towardsdatascience.com/neural-network-the-dead-neuron-eaa92e575748?source=collection_archive---------9-----------------------

深度学习

ReLU 激活功能的最大缺点

乔希·里默尔在 Unsplash 上的照片

为隐藏层选择激活功能并不是一件容易的事情。隐藏层的配置是一个非常活跃的研究主题,它只是没有任何关于给定数据集有多少神经元、多少层以及使用什么激活函数的理论。当时,由于其非线性,sigmoid 是最受欢迎的激活函数。随着时间的推移,神经网络向更深层次的网络架构发展,这提出了消失梯度问题。纠正线性单位(ReLU)原来是隐藏层的激活功能的默认选项,因为它通过比 sigmoid 更大的梯度来解决消失梯度问题。

消失梯度

消失梯度是训练深度神经网络时最大的挑战之一。这是一种深度神经网络无法将梯度从输出层反向传播回第一个隐藏层的情况。当您试图在其隐藏层上建立一个具有 sigmoid 激活函数的深度神经网络时,经常会发生这种情况。

作者图片

乙状结肠公式如下:

作者图片

它的导数是:

作者图片

问题是 sigmoid 导数总是小于 1。根据上面的公式,我们可以说当 f(x) = 0.5 时获得最大导数,因此 f '(x)= 0.5 *(1–0.5),也就是 0.25。

现在想象一下,当你试图建立 7 层神经网络,每层都有一个 sigmoid 激活函数。无论损失函数提供的梯度是什么,如果我们将梯度乘以 0.25,梯度将随着我们通过网络反向传播而变得越来越小,层数是 7,这意味着我们用小于 0 的值将梯度乘以 7 次。

这是最好的情况。在实际例子中,sigmoid 的导数不会总是 0.25。可能是 0.1,0.06,0.04,也可能是 0.001。那么第一个隐藏层的渐变如何呢?非常小,不是吗?

最简单的解决方案是用校正线性单元(ReLU)替换隐藏层上的激活函数。

整流线性单元

ReLU 被认为是深度学习的最大突破之一,因为 ReLU 使训练非常深度的神经网络成为可能。ReLU 易于优化,因为它非常简单,计算成本低,并且类似于线性激活函数,但事实上,ReLU 是一种非线性激活函数,允许学习数据中的复杂模式。线性激活函数和 ReLU 之间的唯一 difference 是 ReLU 将负值推至 0。

图片由 M. Farid Landriandani 拍摄

ReLU 的公式如下:

作者图片

它的导数是:

作者图片

ReLU 在 x > 0 时产生一个导数为 1 的线性,然后在 x ≤ 0 时产生一个导数为 0 的 0。这使得通过 ReLU 神经元的导数在向前传播期间只要该神经元是活动的就保持很大。当训练更深的神经网络时,在隐藏层上使用 ReLU 被认为是解决消失梯度问题的一种可能的方法,因为导数是 1 或 0。

死亡神经元

ReLU 的缺点是他们不能从激活度为零的例子中学习。如果用 0 初始化整个神经网络并将 ReLU 放在隐藏层上,通常会发生这种情况。另一个原因是当大梯度流过时,ReLU 神经元将更新其权重,并可能以大的负权重和偏差结束。如果发生这种情况,该神经元在正向传播期间将总是产生 0,然后不管输入如何,流经该神经元的梯度将永远为零。

换句话说,这个神经元的权重永远不会再更新。这样的神经元可以被认为是死亡神经元,用生物学术语来说,这被认为是一种永久性的脑损伤。一个死亡的神经元可以被认为是自然的退出。但问题是,如果特定隐藏层中的每个神经元都死了,它会切断前一层的梯度,导致后一层的梯度为零。它可以通过使用较小的学习率来解决,这样大的梯度不会在 ReLU 神经元中设置大的负权重和偏差。另一个方法是使用泄漏 ReLU,它允许活跃间期之外的神经元向后泄漏一些梯度。

泄漏 ReLU

Leaky ReLU 不是将负值推至 0,而是通过将 x 乘以常数 0.01,在负区域允许一些湖

图片来自 M. Farid Landriandani

通过这样做,即使神经元有很大的负权重和偏差,仍然有可能通过层反向传播梯度。泄漏 ReLU 的公式如下:

作者图片

它的导数是:

作者图片

Leaky ReLU 在 x > 0 时产生导数为 1 的线性,然后在 x ≤ 0 时产生导数为 0.01 的 0.01 * x。负区域中的常数也可以制成超参数,如深入研究整流器中介绍的 PReLU 或参数 ReLU 激活功能所示。

结论

无论流行与否,ReLU 都有一个缺点,叫做“T2”死神经元“T3”。这主要是由于流经网络的大负梯度导致 ReLU 神经元的大负权重。在前向和反向传播期间,该神经元将总是产生零,因此该神经元的权重将不再被更新,并且被认为是永远死亡的。作为一个自然的退出者,这可能很难,但是如果这发生在特定层的每个神经元上,它会切断前一层的梯度,导致后一层的梯度为零。作为替代,我们可以使用泄漏 ReLU ,当前馈期间的输出为零时,它至少具有 0.01 导数。

参考

https://arxiv.org/abs/1803.08375#:~:text=We introduce the use of,function as their classification function https://www.amazon.com/Deep-Learning-Adaptive-Computation-Machine-ebook/dp/B08FH8Y533/ref=sr_1_2?dchild=1&keywords=deep+learning&qid=1605266647&s=digital-text&sr=1-2 https://www.amazon.com/Neural-Networks-Deep-Learning-Textbook/dp/3319944622/ref=sr_1_1?dchild=1&keywords=Neural+Networks+and+Deep+Learning&qid=1605266979&sr=8-1 https://machinelearningmastery.com/how-to-fix-vanishing-gradients-using-the-rectified-linear-activation-function/ http://arxiv.org/abs/1502.01852

神经网络:人工神经网络的本质

原文:https://towardsdatascience.com/neural-network-the-essence-of-artificial-neural-network-c605eb32de56?source=collection_archive---------35-----------------------

机器学习,深度学习

人工神经网络到底是什么

乔尔·菲利普在 Unsplash 上的照片

人脑由数十亿个相互连接的神经元组成,每个神经元通过这种连接向另一个神经元传递信号。这导致人类有一个特定的行动被执行。例如,你想伸手到口袋里去拿手机,那么就会有一个信号被发送到你的大脑,并通过这数十亿个神经元连接传递。然后,负责这项任务的神经元就会启动,发回信号,让你的手动起来,抓住你的手机。

人脑具有极其复杂的结构,从其神经元的数量、处理速度和效率来看,都证明了人类是一个完美的生命体。出生时,婴儿的大脑包含 1000 亿个神经元。在生命的早期阶段,大脑会消除很少或从不使用的连接,这是大脑发育的正常部分。

神经元

神经元是人脑中的一个细胞,负责从外部世界接收感官输入,向人体肌肉发送信号,并在其间的每一步转换和传递电信号。

图片由维基百科

神经元由 3 个主要部分组成,即树突、轴突和细胞体。树突是一个神经元从其他神经元接收输入的地方。轴突是神经元的输出,它将信号传递给其他神经元。细胞体包含细胞核和控制细胞活动的遗传物质。

神经元通过在发送神经元的轴突和接收神经元的树突之间的狭窄空间(称为突触)发送信号(称为神经递质)来相互通信。

人工神经元

人工神经网络的目的是模仿人类大脑的工作方式,希望我们可以建立一个像人一样行为的机器。人工神经元是人工神经网络的核心构件。

作者图片

人工神经元的结构与生物神经元非常相似,它由 3 个主要部分组成,权重和偏置分别作为树突用 w 和 b 表示,输出作为轴突用 y 表示,激活功能作为细胞体(细胞核)用 f(x)表示。x 是树突接收的输入信号。

在人工神经元中,输入和权重表示为向量,而偏差表示为标量。人工神经元通过在输入向量和权重向量之间执行点积来处理输入信号,添加偏差,然后应用激活函数,最后将结果传播给其他神经元。

我们刚才谈到的激活函数是什么?为什么激活功能很重要?激活功能的作用是什么使得它如此重要?

激活功能

激活函数是我们不应该低估的重要部分,它是人工神经元用来获得神经元输出的函数,也称为传递函数。权重和输入加偏差之间的点积结果在-inf 和+inf 范围内,激活函数旨在根据函数将结果映射到某个范围内。

图片由维基百科

有许多激活函数,但最重要的是 sigmoid 激活函数。它通常用作二进制分类任务的输出层中的激活。Sigmoid 将结果限制在 0 到 1 的范围内,它表示 x 属于第 1 类还是第 0 类的概率。Sigmoid 通过对结果进行阈值处理来做出决定,如果结果≥ 0.5,则 x 被分类为 1,否则,x 被分类为 0。

人工神经网络

人工神经网络是一组相互连接的人工神经元。人工神经网络(ann)像人脑一样学习解决问题。它们通过密集连接的人工神经元过滤信息来处理信息。神经元之间的每个连接都可以相互传递信号。

作者图片

神经元被构造成几个连续的层。一层中的每个神经元都与上一层和下一层中的每个神经元相连。每一层接收来自前一层的输入,对其进行处理,并将其提供给下一层。第一层被称为输入层,它接受输入并将它们提供给下一层。它没有任何权重、偏置和激活功能。最后一层称为输出层,它对输入的数据做出决策。在这两层之间称为隐藏层。这是计算发生的地方。我们可以堆叠尽可能多的隐藏层,但是会有一个计算速度的权衡。

人工神经网络如何工作

人工神经网络的工作原理是通过整个网络处理输入信号,并在输出层获得结果。这也称为前馈。然后使用函数将结果与地面真实情况进行比较。这个函数被称为损失函数,它是一个告诉我们神经网络对数据建模有多好的度量。损失越高,模型越差。

人工神经网络如何学习

人工神经网络通过微调其权重和偏差进行学习,以便有更好的预测。最流行的算法是梯度下降,这是一个迭代过程,旨在最小化损失函数。换句话说,它试图找到权重和偏差,如果我们使用这些权重和偏差,损失函数将是最小的。

结论

人工神经网络是一种试图模仿人脑工作方式的算法。它通过密集连接的人工神经元过滤信息来处理信息。它通过寻找损失函数最小的权重和偏差来学习。

参考

https://extension.umaine.edu/publications/4356e/#:~:text=At birth%2C a baby's brain,about three weeks after conception.

作为降维工具的神经网络和神经自动编码器:Knime 和 Python

原文:https://towardsdatascience.com/neural-networks-and-neural-autoencoders-as-dimensional-reduction-tools-knime-and-python-cb8fcf3644fc?source=collection_archive---------4-----------------------

用 Python 中的 Knime 和张量流实现,分析空竹中间的数据。

我们能抓住物体的本质吗?。在 Unsplash 上由 Maja Petric 拍摄的照片

在我的第一个故事中,我写了一个关于嵌入来自 OpenML 的 MNIST 数据集中的图像的小故事,这些图像是由 Yann LeCun、Corinna Cortes 和 Christopher J.C. Burges 写的从 0 到 9 的手写数字。我用 UMAP 算法进行降维。之后,我使用 DBSCAN 进行聚类,并识别出原始聚类。我将再次使用相同的数据集。

这个故事的提议是什么?

现在,我将探索一条非常相似的路径,但是我将使用神经网络和神经自动编码器,而不是 UMAP 算法来进行降维。我将在 Knime、Keras integration、environment 和 Python 中的 TensorFlow 中这样做。降维后,我将使用 DBSCAN 来验证由神经网络创建的聚类是否可以被识别。所有代码和工作流将被共享。

关于无代码深度学习的更多信息,我建议下面这本由 Rosaria SilipoKathrin Melcher:无代码深度学习编写的书,作为在 Knime 环境中安静地走过深度学习的指南。**

神经自动编码器

图一。深度神经自动编码器。(图片由作者提供)

简单的神经自动编码器是前馈神经网络的一种特殊结构,如前图 1 所示,输入层的维数等于输出的维数,每幅图像的 n

自动编码器像常规前馈神经网络一样,通过反向传播来训练,以便得到与输入相等的输出。因此,它们能够再现它们被训练过的输入。事实上,如果我们向训练好的网络输入类似于训练时使用的输入,那么预期的输出将非常接*输入。如果没有发生这种情况,我们可以得出结论,该输入不是一个“常规”或常见的输入。例如,这种能力通常用于检测欺诈性信用卡交易。由于没有太多的欺诈卡交易数据可用,所以用正常交易数据训练网络是有意义的,如果最终网络不能再现输入,我们可以说我们面临欺诈。这就是为什么自动编码器被认为是一种无人监管的算法。你可以在 TDS 的以下文章中找到更多关于自动编码器的信息, 使用自动编码器进行异常检测应用深度学习—第三部分:自动编码器 你也可以查看我的自动编码器公开列表故事

回到我最初的目的,即使用自动编码器作为降维技术,如图 1 所示,有一个最小维度层。空竹的中心。

图 2。奥斯卡·尼迈耶首都大教堂。 ckturistandoUnsplash 上拍摄的照片

特别是在图中,维数是 n=2。这一层是代码。它被称为潜在空间。在神经网络中的这一点上,我们可以认为我们已经对输入进行了编码,并且我们应该能够检测到,在这种情况下,在 2D 图中,根据输入数据中存在的不同隐式类别,我们具有不同的点聚类。

结构和来源

我们将使用 TensorFlow 在 Knime 和 Python 中执行测试。

Knime 中需要一些配置,这样你就可以用 Keras 训练一个神经网络。请跟随本教程 KNIME 深度学习——Keras 整合

这篇文章的结构如下:

第一部分。使用自动编码器进行降维

如上所述,我们使用简单的密集自动编码器进行降维,并将逐步比较它在 Knime 和 Python 中的实现。

第二部分。使用密集神经网络进行降维

将执行另一个有趣的方法。因为用于该测试的参考数据集具有关于每个样本的类别的信息,而不是使用自动编码器,所以将使用具有 2 或 3 个神经元的内部层的密集神经网络,因此将定义一种潜在空间。请检查下面的图 3,该图描述了具有特定数量的类 C=10 的网络,这是我们的数据集的情况。

图 3。深度神经网络。(图片由作者提供)

类似地,我们将逐步分析 Knime 和 Python 中的实现。

在我们开始之前,你会在我的 GitHub 中找到所有 Python 代码,在 Knime Hub 的我的公共空间中找到 Knime 工作流。

Knime 工作流程

您会发现 Knime 工作流包含了针对每种不同方法的两种不同的解决方案:

第一部分。使用自动编码器进行维度缩减。对于 2D 和 3D 潜在空间来说,工作流程会有两种不同的结局。或者,

第二部分。使用密集神经网络进行降维也有两个不同的分支,分别用于 2D 和 3D 最小维表示。

让我向您展示整个工作流程的全局概述,以便您可以了解不同的分支。

在图 3b 中,黄色工作流对应于 2D 和 3D 的第 1 部分中的自动编码器架构,蓝色工作流对应于密集架构的第 2 部分。

图 3 之二。全球工作流程概述(图片由作者提供)

Python 代码

有两种 Python 代码可用:

KNIME _ Replication _ 3D _ Midpoint . py用自动编码器进行训练和推理KNIME _ Replication _ 3D _ Midpoint _ DM . py用密集连接网络进行训练和推理。在这两个代码中,当不带参数执行代码时,假定潜在空间为 3D。但是,您可以传递一个参数来指示潜在空间的期望大小,例如 3。

**pyhton3 KNIME_Replication_3DMidpoint_DM.py **3****

还提供了一个辅助 Python 文件, ml_functions.py ,其中定义了一个类 ModelGr 及其方法,并在主代码中使用。

第一部分。使用自动编码器降维

数据预处理

图 4。数据预处理。(图片由作者提供)

如图 4 所示,我们使用 Python 源节点捕获数据,对数据进行标准化,然后立即使用颜色管理器节点定义颜色代码,该代码将在整个工作流程中唯一分配给类,因此不同的图将具有相同的图例。之后,建立不同的用于训练和验证的分区。

图 5。导出颜色代码(图片由作者提供)

使用图 5 中的先前节点,我们可以提取正在使用的颜色代码(在#HEX 列中),这样我们就可以在 Python 中重用它们。这将使比较结果更加容易。

代码 1 显示了与获取数据和分区相关的部分初始 Python 代码。

代码 1。获取和分区。

每当使用为 ModelGr()类定义的forward方法执行前向推理时,就会进行规范化。请参见下面的代码 2,第 5 行。

代码 2。正向函数的规范化。

Keras 神经网络架构

在 Knime 中,神经架构被定义为一系列 Keras 密集层节点。接下来,在图 6 中,示出了定义的全局方案。

图 6。全球培训计划(图片由作者提供)。

图 7。网络定义。

图 7 中显示了一个特殊的节点。这是一个组件节点,它封装了几个节点和一个配置接口,配置接口带有定义内部节点性能的功能参数。在图 8 中,显示了层的顺序,在图 9 中,您可以找到可以为组件配置的参数。CTRL+双击网络定义组件将进入图 8 所示的内部节点定义。双击网络定义组件将打开图 9 的配置窗口。基本上,可以定义层的大小和激活函数。

图 8。配置神经网络模型的层序列(图片由作者提供)。

图 9。网络参数定义(图片作者提供)。

请注意,我们已经定义了一个输入层、五个内部层和一个输出层。在这一点上,激活函数对所有层都是通用的,双曲正切,如图 9 所示。除了上面提到的,层配置参数可以通过进入图 8 中每个节点的配置来配置,也就是说,内核和偏置初始化器、正则化器和约束。请注意,在图 9 中,对于 2D 潜在空间的情况,在第四层中,我们将大小定义为 2。对于 3D 选项,您会发现一个替代的工作流程。

虽然我没有使用脱落层来防止过度拟合,但这很容易,如图 9 之二所示。只需添加一个脱落层并重新连接节点。

图 9 之二。添加脱落层(作者图片)

对于 Python 网络,已经定义了一个类ModelGr(),当被调用时,将被告知激活函数、层大小、层数和名称。请参见代码 3 第 14 行+中的模型定义:

代码 3。网络配置和模型创建。

从概念上讲,定义了一个顺序网络(代码 4,第 15 行),我们递归地添加包含在调用中的大小和激活函数的层(代码 4,第 17+行)

代码 4。神经网络的定义和创建。

从不同的图和代码中可以看出,网络具有以下层次和大小:

  • [784(输入),300,48, 2 或 3(潜在空间),48,300,784]和
  • 激活函数是双曲正切函数。

训练网络

在 Knime 中训练网络很容易。在前面的图 6 中,Keras 网络学习者只需要输入训练数据和验证数据。必须定义培训的输入和目标数据。由于我们正在训练自动编码器,输入和目标数据具有相同的大小,特别是来自 MNIST 的图像的 784 像素。在其它参数中,在该节点中定义了在训练中要最小化的损失函数。请注意,我们选择的是 MSE,均方误差。我们将训练最小化输入和输出向量之间的 MSE,因为理想情况下,我们希望它们相等。

图 10。Keras 网络学员配置对话框(图片由作者提供)。

对于 Python 和 TensorFlow,定义了一个训练函数。请注意,在代码 5 的第 21 行,损失函数的定义是 RMSE,均方根误差,正如我们在 Knime 中所做的那样。RMSE_loss()方法在ModelGr()类中定义,可以在代码 5bis 中找到。

代码 5。自动编码器的训练功能。

代码 5 之二。自动编码器的均方根损失函数。

如果您需要检查培训是如何发展的,这两种方法都可以做到。在 Knime 中,在 Keras 网络学习者节点中,右击并点击“查看学习监视器”。参见学习监视器 un 图 10.1

图 10.1。Keras 网络学习者节点学习监视器(图片由作者提供)。

在 TensorFlow 的情况下, TensorBoard 可以用来收集和分析网络。

TensorBoard 提供机器学习实验所需的可视化和工具:

-跟踪和可视化损失和准确性等指标

-可视化模型图(操作和层)

-查看权重、偏差或其他张量随时间变化的直方图

-将嵌入投影到低维空间…

在代码 5 中,添加了几行代码(6、22、23、30+)来收集关于训练和网络图、权重和损失的数据。共享 Python 代码密集自动编码器,在结束执行前自动启动 TensorBoard。在图 10.2 和图 10.3 中,您可以看到曲线图和损耗变化。

图 10.2。网络图(图片作者)。

图 10.2。TensorFlow 中训练时的损耗演变(图片由作者提供)。

提取中点

我们已经训练了网络,它们被配置为神经自动编码器,现在是时候得到输出了。在 Knime 中,请注意图 11 中的 Keras 网络学习器有一个红色的输出端口。该输出是经过训练的网络模型。因此,执行网络只是连接被告知模型和数据的 Keras 网络执行器节点。但是必须小心。

图 11。推断(图片由作者提供)。

请记住,我们希望提取自动编码器的潜在空间,因此我们必须配置 Keras 网络执行器节点来提供特定的输出。这通过将对应于潜在空间的层定义为输出来完成。图 12 显示了如何将潜在空间配置为网络执行器节点的输出。

图 12。配置网络执行器的输出(图片来自作者)。

在 Python 中,我们构建了一个紧凑的顺序网络,为了提取中点,我们使用了一个名为Encoder()的类。当定义一个对象为Encoder()时,通过调用Encoder = mli.Encoder(model)model一个顺序网络模型,__init__方法将提取网络的层,并将它们添加到另一个顺序网络中,从初始层到最小尺寸层,也就是说,潜在空间。请参见代码 6 第 9 行中的条件。

代码 6。编码器的创建。

定义了一个forward方法来推断编码器。如代码 7 所示。

代码 7。编码器模型的正演方法。

编码器被定义为从初始层到最小尺寸层的神经网络部分,因此forward方法将提供潜在空间。

自动编码器网络的结果

将显示潜在空间的图形结果。

2D 结果并试图得到集群。

在图 12 和 13 中,绘制了 Knime 和 Python 两种环境下自动编码器的 2D 潜在空间。可以检查到,人眼可以感知某种顺序和一致性,但是,对该数据应用 DBSCAN 算法不会导致与在自动编码器的潜在空间中定义的那些聚类相关的任何聚类。

图 13。自动编码器网络的 KNIME 工作流程中的 2D 潜在空间(图片由作者提供)。

图 14。2D 的潜在空间。用于自动编码器网络的 TensorFlow 和 Python。(图片由作者提供)。

在自动编码器工作流程的右侧,应用了 DBSCAN 算法。请记住,DBSCAN 由两个参数决定:

*****ε*:指定点之间的距离,这样它们就可以被认为是一个簇的一部分。如果两个点之间的距离小于ε,则这两个点将被视为属于同一聚类的邻居。

最小点数 :从一个点 p 可达的最小点数,使得 p 点可以被认为是核心点。

经过几次测试后,没有一对参数能够得到正确的聚类。在图 15 中,为了证明这种尝试,显示了 DBSCAN 集群。

图 15。自动编码器网络的 KNIME 工作流中的 2D 潜在空间 DBSCAN 聚类。

3D 结果并尝试获取聚类

或者,我进行了同样的工作,但有一个三维潜在空间。没有太多的变化需要解释,但事实是,在 Knime 和 Python 中,定义潜在空间的层的维度在逻辑上是 3,而不是 2。

参见下图 16–18,来自 Knime 和 Python 的 3D 潜在空间。

可以再次检查,可以设想某种顺序和一致性,但是,再次,对该数据应用 DBSCAN 算法不会导致与在自动编码器的潜在空间中定义的聚类相关的任何类似的聚类。查看图 18。

图 16。自动编码器网络的 KNIME 工作流中的 3D 潜在空间(图片由作者提供)。

图 17。3D 潜在空间。用于自动编码器网络的 TensorFlow & Pyhon。(图片由作者提供)。

图 18。自动编码器网络的 KNIME 工作流中的 3D 潜在空间 DBSCAN 聚类(图片由作者提供)。

自动编码器生成的图像

在图 18.1 和 18.2 中,您可以根据 3D 潜在空间自动编码器推断后的 MSE 计算找到最佳和最差图像。

图 18.1。根据每个原始类别的均方误差得出的最差重建图像(图片由作者提供)

图 18.2。根据每个原始类别的均方误差的最佳重建图像(图片由作者提供)

第二部分。密集神经网络降维

那么,我们可以说,到目前为止,这是一个失败的故事。

投降前我尝试了另一种方法。正如我所解释的,因为我们有数据集中每个样本的类别,所以可以为 2D 和 3D 的潜在空间设想一个如图 3 所示的网络。这是一个分类器网络,其最小尺寸为 2 或 3 个内层,可以被认为是潜在空间。

差异

显然,训练的损失函数有了重大变化。现在,我们希望优化一个分类器和一个正确的损失函数来做到这一点,即交叉熵损失。交叉熵损失主要结合 Softmax 激活函数使用。

研究一下这些概念是很有趣的。

图 19。具有潜在空间的范畴分类器。Softmax 和交叉熵(图片来自作者)

在上图 19 中,Softmax 将 logits,vector O ,转化为 probabilities,vector P 。交叉熵的目的是获取向量 P 中包含的输出概率,并测量与标签向量 L 中表示的类值的距离,作为一个独热向量。参见图 19 右侧的矢量示例。

目标是使模型输出尽可能接*期望的输出(类值)。我们如何做到这一点?

克尼姆

必须将 Softmax 定义为最后一个 Keras 密集层的激活函数,将交叉熵定义为 Keras 网络学习器中的损失函数。参见图 20 和 21。

图 20。配置了 Softmax 激活功能(图片由作者提供)。

图 21。分类交叉熵损失函数已配置(图片由作者提供)。

Python 和张量流

如前所述,必须根据暴露的标准定义损失函数。参见代码 8。

代码 8。分类器结构网络的损失函数

在代码 8 中执行逻辑和标签之间的稀疏 Softmax 交叉熵。使用交叉熵函数的 稀疏变异,不需要建立一个热向量,可以直接输入标签。

在这两个*台中,网络具有以下层和大小:

  • [784(输入),300,100,10, 2 或 3(潜在空间),10,10]和
  • 输出图层的激活函数为双曲正切和 softmax

两个*台以及 2D 和三维潜在空间的总体准确度在 94%和 96%之间,混淆矩阵类似于图 23 中的以下内容,提取自图 22 中 Knime 的 Scorer 节点。

图 22。计分器节点(按作者排序的图像)

图 23。神经分类器的混淆矩阵(图片由作者提供)

2D 的结果并试图得到集群。

接下来,您可以在 Knime(图 24)和 Python(图 26)中找到新方法的 2D 潜在空间的结果。现在可以清楚地区分簇,并且 DBSCAN 算法很容易检测到它们。对 Knime 结果执行 DBSCAN,如图 25 所示。

图 24。分类器架构的 2D 潜在空间。克尼姆。(图片由作者提供)

图 25。Knime 结果上的 2D 数据库扫描聚类。克尼姆。(图片由作者提供)

图 26。Python/TensorFlow 中的 2D 潜在空间(图片由作者提供)

3D 结果并尝试获得集群。

在查看 3D 结果之前,无需进一步解释。对于神经密集架构,我在 Knime 中准备了一些节点,以准备将数据导入到 Plotly 中,这样您就可以探索并与绘图互动。这不是一项大工作,但它也包含在工作流中,所以你可能想探索它并重用它。

图 27 显示了 3D 潜在空间,图 28 显示了 DBSCAN 聚类。这种方法的结果相当不错。识别集群。通过单击图例,可以隐藏轨迹。

图 27。分类器的 Knime 结果的 Plotly 3D 交互散布。(Plotly 图表工作室。按作者)

图 28。分类器的 Knime 结果的 Plotly 3D 交互散布。(Plotly 图表工作室。按作者)

最后,图 29 显示了三维密集网络的张量流结果,这是静态的。

图 29。Python 3D 潜在空间(图片由作者提供)

结论

我的目的是探索一个想法,使用神经网络进行降维,降低到 2 或 3 维,这是非常严格的,并在两种环境中进行,Knime 和 Python。在粗略的方法中,不可能从神经自动编码器中提取清晰的聚类,在这些环境中没有一个没有进一步的改进。低至 2 或 3 维的潜在空间是图形探索的一个好选择,但它太有限,无法捕捉原始对象的特征。另一方面,在两种环境中,用具有 2 维或 3 维内层的密集神经分类器确实可以做到这一点。我们可以得出结论,Knime 与 Keras 集成和 Python 与张量流的结果可以被认为是等价的,至少在本文的范围内是这样。在我看来,是个好消息,因为机器学习的大门敞开着,不需要强大而坚实的编码背景,因此,贡献的人越多,我们一起到达的路就越长。

在不久的将来,我将探索自动编码器中那些必要的改进,这样我就可以实现我最初的目标。

神经网络就像人体一样

原文:https://towardsdatascience.com/neural-networks-are-like-human-bodies-852871fcbdb8?source=collection_archive---------32-----------------------

优化者就像私人教练

神经网络。他们似乎无处不在。如果你是一个经验丰富的从业者,这不是问题;你明白它们是怎么回事。通常,你会很快想出一个解释。

基拉·奥德·海德在 Unsplash 拍摄的照片

然而,如果你是一个局外人或这个领域的新手,事情就有点不同了。你可能没有计算机科学背景,直接告诉你渐变、图层和激活毫无意义。为了顺利进入这个迷人的领域,看看下面的简单比较。

神经网络就像人体一样

神经网络有我们可以调整的参数。这些参数通常称为权重。

你的身体也是如此。你的身体也有参数;它们只是被称为肌肉和肌腱。

有了神经网络,我们往往想达到一个特定的目标,比如检测物体。为了实现这一点,这些参数共同发挥作用。

在你的身体里,这和完全一样。例如,当你走路时,一个目标是保持*衡。为此,你的肌肉相应地收缩和放松,它们一起工作。

现在,神经网络最初并不完美。相反,他们必须接受训练。培训通过向他们展示无数他们应该能够做什么的例子来进行。

以你的身体,这也是一样的。例如,当你学习走路时,你会重复同样的动作很多次,直到它合适为止。大量的重复教会你的肌肉、肌腱和关节相互作用。

奖励:为了“感受”什么是神经网络,你可以直立起来。然后,将两臂向侧面抬起,直到成 90 度左右。最后,将一条腿抬离地面,用另一条腿保持*衡。一旦你稳定下来,向前、向后、向侧面倾斜。你可以感觉到你的身体各部分在一起工作以实现你的目标——就像神经网络的重量一样。

优化者就像私人教练

如前所述,神经网络需要训练才能胜任任务。人们通常使用优化器来实现这一点。

你可以把优化者想象成健身房里的私人教练。当你练习时,教练会观察你的动作。

用于神经网络的优化器(Adam 是一个常见的名字)也有同样的任务。在训练期间,它们告诉网络如何更新它的权重。

在健身房,你的教练纠正你就是这种情况。这些话可能是:“保持背部挺直”或“锁定肘部”。这是为了帮助你更快地实现目标。

亚当和他的朋友们(SGD,Adagrad 是他们的一些名字)走在同一个方向。他们首先计算特定的权重如何影响模型的输出。然后,他们更新该值,使网络变得更好。

你在健身房得到的指导也是类似的方向。首先,你会被检查是否有明显的缺陷(比如过于圆的背部),因为它们对你的目标有最大的影响。之后,你的姿势的更小的方面被纠正(比如张开手指做一个练习)。

训练就像为比赛做准备

一旦亚当和他的团队来帮忙,神经网络的事情就变得严重了。如前所述,它有特定的任务。

对你来说,这样的任务可能是为武术比赛做准备,而私人教练——你的优化者——会帮助你。

神经网络训练的竞赛被称为“ImageNet 大规模视觉识别挑战”或“通用语言理解评估”。这种挑战使得基于标准规则集比较不同神经网络的性能变得容易。

对于你的武术比赛,规则可以是禁止踢腿或肘击。

为了达到良好的效果,神经网络在上述优化器的帮助下进行训练。他们一起工作,用典型的数据告诉他们在比赛中会发生什么。

在你的情况下,训练可能会被构造成执行相同序列的无休止的变化。结果,你的身体通过增长肌肉、变得更加灵活等方式明确适应强加的需求。

神经网络的权重做类似的事情:它们的值增加或减少,并根据训练加强或削弱它们的连接。

验证就像一次中级考试

在训练期间,您通常希望评估神经网络的性能。为此,您可以使用独立于定型数据的数据集:验证数据。每隔几轮训练,网络都要处理这个数据集。

大学讲座也遵循类似的原则。在学期中,你通过做推荐练习来准备期末考试。然后,为了帮助你评估自己的表现,教授们会提供中级考试。

对于神经网络,验证数据必须不同于训练和测试数据,并且应该具有类似的结构。只有这样,我们才能保证我们的评估是公正的,但描述性的。

就你的讲座而言,你的准备练习(=训练数据)和中级考试(=验证数据)应该包含不同的任务,但涵盖相同的概念。同样,训练数据应该不同于两者,但也涵盖相同的想法。这是获得诚实的自我评估的唯一方法。

测试就像一场竞赛

在神经网络被训练之后,是时候在一个标准化的任务中测试它的性能了(如前所述)。各种问题都有挑战,各有排行榜。

在体育界,存在着无穷无尽的各种各样的学科。从跑步等经典运动到滑板等更现代的运动,每个运动都有自己的排名。

为了在看不见的数据上测试神经网络,从业者使用测试数据集。该数据集包含新内容,但具有与训练(和验证)数据相同的特征。

以滑板比赛为例。规则是已知的,每个人都有时间准备他们的行动。然后,参与者在确定的地点集合,让陪审团评判他们的表现。

对于神经网络,度量代替了陪审团。这些指标旨在用一个或多个数字来捕捉模型的性能。通常,指标越高,模型的收益越好。

在我们的运动会上,每个滑板运动员都由同一个评审团评判。他们通过分配数字对参与者的表现进行排名。在这里,相同的技巧必须得到相同的分数,不管是谁做的。否则,我们无法确保公*竞争。

在神经网络的世界中,度量标准用于模型之间的比较。因此,可以对模型进行排名,这导致出现如下所示的排行榜:

强力胶基准测试的排行榜(从 12 年 10 月开始。2021).作者截图;关于强力胶的网页的更多信息。

如你所见,顶部的空气变得稀薄。两位候选人之间的差距不到一个百分点。通常,研究人员投入了大量的工作才走到这一步。

在体育比赛中,公*竞赛是必不可少的组成部分。如果成功不是自然而然取得的,那么比你的对手优秀是没有用的。

当向神经网络提交挑战时(或者更确切地说,是它们获得的分数),第三方理解结果是如何获得的是至关重要的。或者,更好的是,复制它们。

在运动和神经网络方面的一切都被清除后,是时候庆祝胜利了。但只能等到下一次挑战。

神经网络反向传播变得容易

原文:https://towardsdatascience.com/neural-networks-backpropagation-by-dr-lihi-gur-arie-27be67d8fdce?source=collection_archive---------8-----------------------

香草神经网络背后的数学直觉的友好指南。

图一。神经网络中的反向传播|作者图片

介绍

在设计高效的深度模型时,理解神经网络(NNs)背后的数学操作数对于数据科学家的能力非常重要。在本文中,将展示全连接神经网络的高级演算,重点是反向传播步骤。这篇文章面向对神经网络有基本知识的人,他们试图更深入地研究神经网络的结构。

背景

训练过程的目标是找到使误差最小化的权重(W)和偏差(b)。这是通过梯度下降算法完成的。首先,随机初始化权重,并且执行细微权重变化的迭代过程,直到收敛。

每次迭代从正向传递开始,输出当前预测,并通过成本函数 J(等式 6)评估模型的误差。接下来,进行反向传递来计算权重梯度。

图二。简化的成本函数曲线。在神经网络中,这个函数可能不是凸的。|作者图片

为了找到使误差最小的最佳参数,我们使用梯度下降算法。目标是找到成本函数(J)的最小点,其中梯度接*于零(图 2)。该算法在最陡下降的方向上朝着最小点逐步迭代移动。步长被称为“学习速率,它是一个标量,决定了每次迭代中权重的变化,从而决定了 NN 收敛的速度。学习率是一个必须调整的超参数。较小的学习率需要更多的训练时间,而较大的学习率会导致快速训练,但可能会损害性能和不稳定性。

为了更新权重,梯度乘以学习率(α),并且通过以下公式计算新的权重:

等式 1。梯度下降的权重更新公式。W =权重,alpha =学习率,J =成本。

随着模型的迭代,梯度逐渐向零收敛,其中误差很可能是最低的(或者,模型可能收敛到局部最优并呈现次优性能)。

描述网

本文将遵循两层神经网络的结构,其中 X(也称为 A[0])是输入向量,A[1]是隐藏层,Y-hat 是输出层。网络的基本架构如下图所示(每层中的神经元数量与方程无关,因为我们使用的是矢量化方程):

图 3。两层神经网络|作者图片

向前传球

为了理解反向传播是如何计算的,我们首先需要概述一下正向传播。我们的网络从一个矢量化的线性方程开始,其中的层数用方括号表示。

等式 2。直线方程。

接下来,添加非线性激活函数 (A)。这种激活使网络能够打破线性并适应数据中的复杂模式。可以使用几种不同的激活函数(例如, sigmoidReLUtanh ),这里我们将使用我们的 NN 的 sigmoid 激活。

等式 3。乙状结肠激活。

到目前为止,我们计算了第一层。第二层和第一层一样,由一个线性方程(Z2)组成,后面是一个 sigmoid 激活(A2)。由于这是我们网中的最后一层,激活结果(A2)就是模型的预测(Y-hat)。

方程式 4 + 5。直线和 sigmoid 方程。

最后,为了评估和最小化误差,我们定义了一个成本函数(关于激活和成本函数的更多信息,请参考参考文献[ 1 ])。这里我们使用的是“均方误差”(MSE)函数。为了简单起见,我们将使用随机梯度下降(SGD)方法[ 2 ],这意味着在每次迭代中只处理一个样本。

等式 6。均方误差成本函数。

我们可以总结出向前传球的计算图

图 4。作者提供的向前传递|图像的计算图

偶数道次

为了在每次迭代后更新权重和偏差,我们需要计算梯度。在我们的两层网络中,有 4 个参数需要更新:W2,b2,W[1]和 b[1],因此需要计算 4 个梯度:

但是我们如何找到这些复合函数的导数呢?根据'链式法则',我们将沿着连接变量的所有路径构建导数的乘积。让我们遵循第二层(W2)梯度的权重:

图 5。W2渐变|作者图片

从上图中,我们可以清楚地看到,成本 J 相对于 W2的变化为:

方程式 7。成本 J 相对于第二层 W2的权重的梯度

为了解决这个问题,我们将从计算成本 J 对 A2的偏导数开始,这也是预测 Y-hat。原始成本函数显示在左侧,导数显示在右侧:

等式 8。MSE 成本函数(左)及其对 A2的偏导数(右)。

A2中的 sigmoid 激活相对于 Z2的偏导数由下式表示(sigmoid 导数的数学发展在参考文献[ 3 ]中描述):

等式 9。第二层上的 Sigmoid 激活(左)及其对 Z2的偏导数(右)。

Z2相对于权重 W2的偏导数:

方程式 10。第二层的直线方程(左),它对 W2的偏导数(右)。

让我们将所有内容链接在一起,计算 W2梯度:

方程式 11。成本 J 相对于第二层的权重的梯度(W2)

太好了!接下来,我们将以类似的方式计算 b[1]梯度。让我们跟随梯度:

图 6。成本 J 相对于第二层 b2的偏差的梯度|作者的图像

方程式 12。成本 J 相对于第二层(b2)的偏差的梯度

上面已经计算了 b2梯度的前两部分(成本 J 相对于 Z2的偏导数),最后一部分等于 1:

方程式 13。第二层的直线方程(左),它是关于 b2的偏导数(右)。

所以总的 b2梯度是:

方程式 14。成本 J 相对于第二层 W2的权重的梯度

最后,我们完成了第二层的梯度计算。第一层的梯度有点长,但我们已经计算了它的一部分。让我们遵循 W[1]更新的梯度:

图 7。W[1]渐变|作者图片

梯度的前两部分是先前为层 2 计算的。Z2关于 A[1]的偏导数是 W2:

方程式 15。第二层的直线方程(左),它对 A[1]的偏导数(右)。

最后两部分的计算方式与第 2 层中的计算方式相同。综合起来,我们得到:

方程式 16。成本 J 相对于第一层 W[1]的权重的梯度

如果我们遵循 b[1]梯度:

图 8。b[1]渐变|作者图片

我们会得到:

方程式 17。成本 J 相对于第一层 b[1]的偏差的梯度

通过这一部分,我们完成了对我们的神经网络的一次迭代的权重和偏差的所有梯度的计算。

体重更新

一旦计算出梯度,我们就可以更新模型的新参数,并再次迭代直到模型收敛。表示α是学习速率,一个将决定收敛速率的超参数。

权重更新。W =权重,alpha =学习率,J =成本。层号用方括号表示。

最后的想法

我希望这篇文章有助于更深入地理解神经网络背后的数学。在本文中,我解释了小型网络的工作原理。然而,这些基本概念可以推广并适用于更深层次的神经网络。

感谢您的阅读!

想了解更多信息?

参考文献

[1] 激活和成本函数。https://medium . com/@ zeeshanmulla/cost-activation-loss-function-neural-network-deep-learning-what-thes-91167825 a4 de

2随机梯度下降。https://towards data science . com/random-gradient-descent-clearly-explained-53d 239905 d31

[3] 乙状结肠衍生物。https://becoming human . ai/what-is-derivative-of-sigmoid-function-56525895 f0eb

实时音频的神经网络:树莓皮吉他踏板

原文:https://towardsdatascience.com/neural-networks-for-real-time-audio-raspberry-pi-guitar-pedal-bded4b6b7f31?source=collection_archive---------3-----------------------

作者图片

这是关于使用神经网络进行实时音频的五部分系列的最后一部分。
上一篇关于有状态 LSTMs 的文章,点击 这里

重要提示: 从写这篇文章的时候起,软件和硬件都有了很大的改进。这些更新列在本文的末尾,包括一个新的视频演示。

在本文中,我们将一步一步地在 Raspberry Pi 上构建一个实时运行神经网络的功能性吉他踏板。

我们现在已经介绍了三种不同的神经网络模型,并使用 JUCE 框架在实时吉他插件中实现了它们。作为一名吉他手和工程师,对我来说,下一个合乎逻辑的步骤是使用我们从以前的文章中学到的知识来制作吉他踏板。令人惊讶的是,所有的软件工具都是免费的,硬件成本大约为 150 美元(如果你手头已经有所需的电源和音频适配器,价格会更低)。

让这成为可能的秘方是 Elk Audio OS 。这是一个基于 Linux 的开源操作系统,专门用于嵌入式设备上的低延迟音频处理。它允许您在 Raspberry Pi 等设备上运行现有的 VST3 插件。

我写的软件叫 NeuralPi ,在 Github 上开源。我包括了一个依班娜 TS9 电子管发声器踏板的模型,以及一个挡泥板布鲁斯 Jr. 放大器。

下面是一个视频,展示了在 Raspberry Pi 硬件上使用 NeuralPi VST3 插件完成的项目:

特别感谢我的儿子(5 岁)拍摄的介绍(视频作者)

项目设置

该项目由四个主要部分组成:

  1. Raspberry Pi 4b (运行插件的迷你电脑)
  2. HiFi Berry ADC + DAC (位于 Raspberry Pi 顶部的模数、数模转换板。
  3. Elk Audio OS 用于 Raspberry Pi4(专门用于音频的低延迟操作系统)
  4. 为 Elk Audio OS 交叉编译的实时 VST3 插件( NeuralPi )(运行带有吉他放大器/踏板模型的神经网络引擎的插件)

零件和价格的完整列表:

这是我为这个项目购买的所有东西的清单,除了 HiFiBerry ADC +DAC,我从芝加哥电子公司订购的,其他都是从亚马逊订购的。

Raspberry Pi / HifiBerry 设置(图片由作者提供)

  1. 树莓派 4b (亚马逊),50 美元(我见过售价 35 美元的 Rpi4)
  2. Rpi4 电源适配器(USB-C 连接器,5.1V — 3.5A ) $10
  3. Micro SD 卡(最低 8GB,我买的是 32GB),12 美元
  4. Rpi4 + HiFiBerry 兼容外壳,(这里你想花多少就花多少;我买了一个适合原型制作的可定制外壳,但不同的外壳更适合成品)$20
  5. HDMI 微型转标准 HDMI 适配器电缆(Rpi4 有 2 个微型 HDMI 输出)$8
  6. HiFi Berry ADC + DAC ,(有一款“pro”版售价 65 美元,但我坚持用标准版)$50
  7. 双 1/4”女性到 1/8”男性立体声音频适配器(用于将吉他插入 HifiBerry),8 美元
  8. 立体声男性 RCA 到 1/4”女性音频适配器(我买了 1/8”的耳机使用,但 1/4”将是典型的吉他踏板输出),8 美元

零件总成本:166 美元+税费和运费

我已经拥有的其他物品:

  • 带 HDMI 输入的独立电脑显示器(可使用任何带 HDMI 输入的屏幕)(50 美元及以上)
  • 有线 USB 键盘(10 美元)
  • 运行 Ubuntu Linux 的笔记本电脑(用于构建 VST3 插件并通过 WiFi 与 Rpi4 通信(翻新,$250),你也可以使用运行 Linux 的虚拟机
  • 1/8 英寸公头至 1/4 英寸母头适配器 5 美元(用于使用放大器代替耳机)

注意:除非你自己交叉编译插件,否则不需要单独的 Linux 计算机。但是,您需要一台单独的计算机来连接和上传 VST3 到 Raspberry Pi(通过 WiFi 或以太网)

组装硬件

HifiBerry 通过两排插脚连接器插入树莓皮顶部。它带有垫片,可以将 HifiBerry 卡固定在 Rpi4 的顶部。我选择了一个通用原型设置的外壳,但 HiFiBerry 网站提供了一个好看的外壳用于一个简单的吉他踏板项目,没有额外的脚踏开关或旋钮。我可能最终会为最终产品构建自己的外壳。

硬件组装好后,你就可以连接所有必要的适配器了。如果您熟悉使用 Raspberry Pi 2,您会希望注意到它与 Raspberry Pi 4 的一些主要区别:

  1. HDMI 输出为微型(而非标准尺寸)
  2. 电源线是 USB-C(而不是 micro USB)
  3. Rpi4 内置了 Wifi 和蓝牙功能

为 Raspberry Pi 4 + HiFiBerry 设置 Elk 音频操作系统 ADC + DAC

第一步是用树莓 Pi 4 的 Elk Audio OS 来闪存 micro SD 卡。为此,我们将使用一种叫做 balenaEtcher 的工具,但也有其他方法可以对 SD 卡进行成像。

使用 Elk Audio 操作系统对 microSD 进行成像

  1. Github (.bz2)下载 Rpi4 的 Elk 音频操作系统镜像。拉开拉链。wic 文件。
  2. 下载并安装 balenaEtcher。
  3. 将 microSD 卡插入电脑(最低 8GB)(可能需要 USB 适配器将 microSD 连接到电脑)
  4. 运行 balenaEtcher 并按照提示下载 microSD 映像。wic 文件。
  5. 成像完成后,取出 microSD,插入 Raspberry Pi 4 上的 microSD 插槽。

使用 Elk Audio 操作系统启动 Rpi4 并执行初始设置

  1. 使用 HDMI 将 Rpi4 连接到外部显示器,连接 USB 键盘,并连接电源。
  2. 当登录提示出现时,键入“root”并按 enter 以 root 身份登录(默认情况下,root 没有密码,但如果需要,您可以设置一个)。
  3. 配置 Elk 音频操作系统,以配合 HiFiBerry ADC + DAC 使用。在命令提示符下键入以下内容:
    sudo elk_system_utils --set-audio-hat hifiberry-dac-plus-adc

并重新启动 Rpi4 以使更改生效:
sudo reboot

4.按照官方 Elk 文档中的详细说明,配置通过 Wifi 或以太网进行通信。

5.您现在可以通过 WiFi 从另一台计算机 ssh(安全 shell)到 Rpi4。在我的 Ubuntu Linux 计算机上,这就像在终端上运行以下命令一样简单:

ssh mind@<ip_address_here>
# And enter the default password for "mind" user: "elk"# Files can also be transferred to the Rpi4
scp -r YourFile root@<rpi-ip-address>:/target_path/

注意:一旦您将 Rpi4 连接到 WiFi,您可以通过在 Elk OS 终端中键入“ ip a ”来获取分配给它的 IP 地址。

为吉他踏板选择神经网络模型

在过去的三篇文章中,我们讨论了三种神经网络模型及其实时实现。每个模型都有自己的优点和缺点。为了给我们的踏板选择最合适的型号,我们进行了一项简单的贸易研究。每个神经网络模型都有一个从 1 到 3 的分数等级,3 是最好的。选择了三个类别:训练速度、声音质量和实时性能。

表 1:模型选择贸易研究(图片由作者提供)

注意:每个类别都被赋予了相同的权重,但实际上对于使用 Raspberry Pi 来说,实时性能将是最重要的因素,其次是声音质量。

状态 LSTM 模型在实时性能和声音质量方面获得了最高分。没有国家的 LSTM 有更高的训练速度,但是对于我们创建定制吉他踏板的应用程序来说,这相对于拥有好的声音来说是次要的。WavNet 有很好的声音,但它较高的 CPU 使用率可能会在 Raspberry Pi 上造成问题(尽管这值得回去测试)。此外,WavNet 在处理高增益吉他声音方面的困难使得它在吉他踏板中的使用不太吸引人。

Rpi4 与 Elk Audio 工具链和 JUCE 的交叉编译

如果你使用的是来自 Github 的 NeuralPi.vst3,可以跳过这一节。如果您想使用 JUCE 编译自己的 VST3,或者修改现有的 VST3 插件以在 Elk OS 上运行,可以使用这些步骤。Elk Audio OS 运行“无头”插件,这意味着没有图形界面。JUCE 6 包含了 headless 构建特性,但是你可能需要进一步修改你的插件,以满足构建 Elk 插件文档中详述的需求。

在 Linux 电脑或 Linux 虚拟机上(我用的是 Ubuntu 18.04):

  1. 为 Rpi4 下载 Elk Audio SDK
  2. 运行下载的 SDK(。sh 文件)进行安装。我使用了默认位置:/opt/elk/1.0
  3. 打开你的。使用 Projucer 应用程序的 jucer 项目(JUCE 6,我使用的是 JUCE 6.08),并根据 Elk 文档修改项目(参见“内部 Projucer:”部分)。
  4. 创建一个 Linux makefile 构建目标(如果它还不存在),并保存 Projucer 项目以生成 Makefile 目录和 Makefile。
  5. 遵循交叉编译 JUCE 插件文档中详述的步骤。以下是我使用的具体步骤:

进入 make 命令后,插件将开始编译。如果一切顺利,你现在将拥有一个兼容 Elk OS / Raspberry Pi 4 的. vst3 插件。

重要提示:确保编译后的 VST3 中的架构文件夹名称为“aarch64-linux”,例如“plugin name . vst 3/Contents/aarch 64-Linux”,否则插件不会在 Elk OS 上运行。如有必要,将文件夹重命名为“aarch64-linux”。

使用 RTNeural 优化插件代码

当我第一次在 Raspberry Pi 上运行我的插件时,我立刻遇到了问题。它运行没有任何错误,但它发出了可怕的声音:

麋鹿音频论坛的帮助下,我的插件运行太慢了。如果我查看进程诊断,它使用了 99%的 CPU 资源,并且很可能超过了这个数量。我必须找到一种方法来优化我的代码,否则它将无法使用。

在我得出结论说我当前的插件不能在 Pi 上工作的第二天,一个非常偶然的事情发生了,RTNeural 的创建者找到了我,对在我的一个插件中实现他的代码感兴趣。事实证明,他在优化音频处理的神经网络方面做了相当多的研究,并创建了 RTNeural 作为实时音频的推理引擎。

事实证明,将我的 LSTM 推理代码换成 RTNeural 相当简单。我用 Pi 上的 RTNeural 加载了新编译的插件,交叉手指,查看了进程诊断。起初我不敢相信我所看到的:它已经从 99%下降到 16%!我插上吉他和耳机,它听起来就像笔记本电脑上的插件。我添加了一些延迟和混响,并直接从树莓派录制了这个样本:

我不会深入解释为什么 RTNeural 能够为我的插件增压,但这与利用 SIMD (单指令,多数据)指令有关。这些是使用进程矢量化来并行运行计算的低级操作(类似于图形卡所做的)。现代处理器具有这种在 CPU 上进行高性能计算的能力。

在 Elk Audio 操作系统上运行实时插件

Elk 用的是一个叫“寿司”的外挂主机。Sushi 使用配置文件来设置音频路由、插件设置和 midi 设置。你可以在 Github 上查看 NeuralPi 的配置文件示例。为了将你的插件移动到 Raspberry Pi,我推荐在 WiFi 上使用“ssh”(安全外壳)。我使用了一台专用的 Ubuntu Linux 笔记本电脑,但是有几种方法可以做到这一点。我将回顾一下我在这里使用的步骤。

  1. Github 下载 NeuralPi-elk.zip 并解压. vst3 和配置文件。

注意:本文引用了 NeuralPi 的原始版本。有关具有更新功能的最新版本,请参见 NeuralPi 版本 页面。

2。将. vst3 移动到 Rpi4。

使用此处描述的方法之一连接到 Pi。为了通过 ssh over Wifi 进行连接,我在一台单独的 Linux 计算机上使用了以下命令,该计算机与 Pi 连接到同一个 Wifi 网络。

# Secure copy the .vst3 to the Raspberry Piscp -r YourPlugin.vst3 root@<rpi-ip-address>:/home/mind/plugins/ # After you copy the vst3 to the RPi, you can ssh to verify it 
#  copied correctlyssh root@<rpi_ip_address>

3。为运行插件创建一个. json 配置文件。如果运行的是 NeuralPi.vst3,可以使用 Github 发行版中包含的版本。

# Secure copy the .config to the Raspberry Piscp -r YourConfig.config    
       root@<rpi-ip-address>:/home/mind/config_files/

4。连接音频适配器、吉他输入和音频输出设备(扬声器、耳机、放大器)。

5。使用 Sushi 运行插件。

# Login to the "mind" user and run the plugin with sushi
#  (the default password is  "elk")ssh mind@<rpi_ip_address> sushi -r --multicore-processing=2 -c ~/config_files/config_neuralpi.json &

这将在后台运行无头插件。您可以通过键入以下命令查看实时插件的进程使用情况:
watch -n 0.5 cat /proc/xenomai/sched/stat

注意:使用标准的 Linux 流程工具,如“top”只会显示非实时任务。

要退出插件,请在终端中键入以下内容:
pkill sushi

您可以设置 Raspberry Pi 在启动时自动运行配置。这对于像操作典型的音频效果设备一样操作 Pi 非常有用。

实时性能

当 Pi 上的进程使用率为 16%时,有足够的空间添加其他效果,如 cab 模拟(脉冲响应)、混响、延迟、凸缘或任何数量的 CPU 密集型效果。说到树莓派的可能性,天空是无限的。人们可以创建一个手机应用程序,通过 WiFi 控制插件,添加旋钮和控件,甚至双启动另一个运行媒体中心、网络浏览器或视频游戏模拟器的操作系统。

Elk Audio OS 专为低延迟音频而设计,因此您不必像在普通笔记本电脑上那样担心其他进程会干扰插件性能。Raspberry Pi 4 处理器有四个内核,两个运行实时操作,两个运行非实时操作。这确保了音频性能保持不变。

现在这个树莓皮吉他踏板非常简单,但我计划添加物理旋钮和一个好看的外壳,把它变成一个真正的吉他踏板。一旦完成,我将发布一篇关于构建过程的新文章。

软件更新

更新 1 :自从写这篇文章以来,我已经增加了从 Windows 或 Mac 电脑使用 NeuralPi 插件/应用程序通过 WiFi 控制模型选择、均衡器/增益/音量的能力。多个放大器和踏板模型可用这里。(1.1 版)更多详情请参见 NeuralPi GitHub 页面:

https://github.com/GuitarML/NeuralPi

更新 2:neural pi 推出 3d 打印表壳。STL 文件可以在这里获得。

STL 模型(上图)和无盖印刷盒(下图)(图片由作者提供)

更新 3:neural pi 软件的 1.2 版本现在包括加载脉冲响应文件的功能,以及简单的延迟和混响效果。脉冲响应是一种常用的效果,用于模拟吉他音箱或特定空间的混响特性。当与 LSTM 模型相结合,它提供了一个吉他放大器更现实的表现。

https://github.com/GuitarML/NeuralPi/releases/tag/v1.2.0

更新 4:neural pi 1.3 版本增加了加载条件模型(增益/驱动旋钮的全范围)的能力,并将默认快照模型替换为 TS-9、Blues Jr 和 HT40 放大器的条件模型。

https://github.com/GuitarML/NeuralPi/releases/tag/v1.3.0

更新 5(2023 年 2 月 9 日):我使用 NeuralPi 软件的更新版本制作了一个名为 Proteus 的实际吉他踏板,用于更真实的模型。踏板包括一个金属外壳中的缓冲输入、音量控制和线路/乐器电*开关。您可以在此处观看视频演示和硬件演练:

这结束了我的关于使用神经网络进行实时音频的五部分系列。我希望它能激发你对音乐神经网络可能性的好奇心,甚至说服你自己尝试一下。

感谢您的阅读!

如果你想继续阅读关于吉他效果的机器学习,请在这里查看我的下一篇文章:

作者图片

用于实时音频的神经网络:状态 LSTM

原文:https://towardsdatascience.com/neural-networks-for-real-time-audio-stateful-lstm-b534babeae5d?source=collection_archive---------11-----------------------

作者图片

这是关于使用神经网络进行实时音频的五部分系列的第四部分。上一篇关于无状态 LSTMs 的文章,点击 这里

我们将为最后一个神经网络模型重新访问 LSTM。这次我们将使用状态版本,并利用其循环内部状态来模拟 Blackstar HT40 吉他放大器。

快速复习;LSTMs(长短期记忆)是一种递归神经网络,通常用于文本到语音或自然语言处理等任务。它们有一个循环状态,每次通过网络输入新数据时都会更新。这样,LSTM 就有了记忆。在本文中,我们将使用论文“具有深度学习的实时吉他放大器仿真”中提出的 LSTM 模型。

概观

使用有状态 LSTM 允许我们简化前一篇文章中的整个网络结构。我们不会使用两个一维卷积层或数据预处理。这里我们需要的是 LSTM 层,然后是致密层。

图 1:一般网络架构(图片由作者提供)

单个音频样本被馈送到网络,并且单个样本被预测。由于关于过去信号的必要信息存储在 LSTM 循环状态中,因此不需要样本范围。

需要注意的是,会执行一个跳过连接,其中输入样本值会添加到输出值中。这样,网络只需学习输出和输入之间的差异。这种技术在 amp 仿真论文中有定义。

PyTorch 培训

PyTorch 培训的示例代码来自 Github 上的自动吉他建模项目。这个项目不包含许可证文件(在撰写本文时),所以我不会在这里显示代码,但是您可以在 Github 上查看完整的 Python 代码。我使用了在 networks.py 文件中定义的“SimpleRNN”模型。这包括在 amp 仿真白皮书中描述的 LSTM 网络的实施。

在之前的文章中,我们在 25%的增益下使用了 Blackstar HT40 放大器的过驱通道。有状态 LSTM 的初始测试进行得非常顺利,所以我决定将增益提高到 100%,看看网络能处理多少。我用我的 Fender Telecaster 和 HT40 做了一个新的记录。HT40 再次采用舒尔 SM57 动圈话筒。

我使用了 Focusrite Scarlett 2i2 音频接口和运行在 Windows 10 上的 Reaper DAW(数字音频工作站)。录音设置使用吉他的信号分离器,一个信号进入音频接口的通道 1,麦克风输出进入通道 2。这样,两个轨道可以同时记录,两个信号之间的延迟最小。LSTM 模型对两个信号之间的任何时移都非常敏感。

我把录音笔记本电脑和音频接口从扩音器上移开,以减少电子干扰产生的噪音。下图左侧的踏板仅用于信号分离踏板。

录制设置(图片由作者提供)

放大器周围的区域被噪声抑制器(我只是用毯子)包围,以减少录音时的回声。尽可能消除房间混响以提高训练的准确性是很重要的。

麦克风黑星 HT40 放大器(图片由作者提供)

培训是通过在 Google Colab 上运行 PyTorch 代码完成的,这是一个基于浏览器的选项,用于在云中运行 python 代码。该网站甚至允许您免费访问 GPU 和 TPU,但有一些限制。使用 GPU 运行时,我能够在大约 40 分钟内训练 HT40 模型。

对于网络大小,amp 仿真纸测试了 LSTM 隐藏大小值 32、64 和 96。网络越大,它能够学习的信号就越复杂,但这是以处理速度为代价的。我发现 20 的隐藏大小完全能够再现我录制的声音,同时提高实时性能。

HT40 放大器在 100%增益时的损耗值为 0.069。训练代码使用一种称为“自适应学习率”的技术,这种技术可以在整个训练过程中降低训练的积极性。您可以将此视为随着模型越来越接*目标而对其进行微调。

以下是我的 Fender Telecaster 的输入录音示例:

这是 Blackstar HT40 在 100%增益下的样本:

这是 PyTorch 对同一样本的预测:

如果我们比较实际信号和预测信号,我们可以看到音频的幅度和特征非常接*。下面的图是使用 Matplotlib 绘制的,Matplotlib 是一个用 python 创建图表的库。

图 2:100%增益(损耗 0.069)下 HT40 放大器的实际信号与预测信号

模型转换

在实时使用经过训练的模型之前,该模型必须被转换成用于加载到插件中的格式。Automated-guitar amp modeling项目自动将模型状态数据导出到一个 json 文件中。json 文件包含有关图层的信息,如 LSTM 隐藏单元的数量和输入/输出大小。大部分数据来自 LSTM 层和密集层的训练权重和偏差。权重和偏差是将被实时代码使用的值的数组。

实时实现

下面给出了使用 Numcpp 进行矩阵计算的实时实现的示例代码。使用 JUCE 框架的完整插件实现还没有发布,但是我会在这篇文章公开后更新它。

这是 LSTM/致密层推断的主要处理方法。对于缓冲器中的每个音频样本,lstm_layer()dense_layer()被处理。对于跳过连接,输入样本被添加回网络的输出中。

这是 LSTM 层,由 amp 仿真论文提出的算法实现。“c_t”和“h_t”(单元格和隐藏状态)是基于 LSTM 层隐藏大小“HS”为每个索引计算的。基于对准确性和实时性能的测试,我使用了 20 的隐藏大小。

密集层将 LSTM 输出减少到一个音频样本。密集图层只是 LSTM 输出和训练密集图层权重加上偏差值的点积。

这些计算在音频中每秒重复 44100 次。其他数码效果可以添加在 LSTM 模型之前或之后,如均衡或混响。多个模型可用于覆盖特定设置的范围,如增益。在 amp 仿真论文中,他们使用参数调节对多个音频样本训练单个模型,每个样本具有不同的增益设置。然后,该模型可以覆盖给定旋钮设置的整个参数空间。

注:音频中除了 44.1kHz 以外的其他采样率也很常见,比如 48kHz 甚至 96kHz。网络将以更高的采样率运行,但需要更多的测试来确定这对音频的影响。可能是因为训练数据是 44.1kHz,这是唯一可以准确预测的速率。采样速率转换器可能是解决不同输入采样速率的解决方案。

amp 仿真论文提到,未来的工作可能包括实现抗锯齿以进一步改善仿真声音。在录制的音频中会出现混叠现象,非线性函数产生的高次谐波会反射回较低的频率,在音频中产生不希望的失真。关于反走样技术的详细解释,请查看这篇文章

表演

在三种不同的神经网络模型中,我发现有状态 LSTM 在以实时速度再现一系列吉他放大器和踏板方面是最成功的。它能够处理高增益,如这里使用的 HT40,和干净的声音。适中的训练时间胜过了 WaveNet 模型,代码的简单性使其优于前一篇文章中的 conv1d 层+无状态 LSTM。

注:amp 仿真论文定义了另一个 RNN 模型,GRU(门控循环单元)。这包含在Automated-guitar amp modeling代码中,与 LSTM 的预成型类似。该论文指出,GRU 运行速度稍快,但可能无法像 LSTM 一样处理各种声音。

下面是一个用 JUCE 框架构建的插件的视频演示,该插件在几个经过训练的模型上运行有状态 LSTM 推理:

作者提供的视频

我们现在已经介绍了三种不同的神经网络架构,以及它们在 c++中使用 JUCE 框架的实时实现。

感谢您的阅读!在最后一篇文章中,我们将使用有状态 LSTM 模型和 树莓派 构建一个吉他踏板

https://link.medium.com/m1n9gMXd9gb

  1. Alec Wright 等人《深度学习的实时吉他放大器仿真》应用科学 10,第 3 期(2020): 766。

实时音频的神经网络:无状态的 LSTM

原文:https://towardsdatascience.com/neural-networks-for-real-time-audio-stateless-lstm-97ecd1e590b8?source=collection_archive---------12-----------------------

作者图片

这是关于使用神经网络进行实时音频的五部分系列的第三部分。上一篇关于 WaveNet 的文章,点击 这里

在本文中,我们将使用一个无状态的 LSTM 神经网络来实时模拟一个吉他放大器。

代表“长短期记忆”的 LSTM 模型是在 20 世纪 90 年代中期开发的,是一种递归神经网络(RNN)的形式。从那以后,最初的模型被修改并应用于许多不同类型的问题,包括语音识别和文本到语音转换。

与 WaveNet 这样的“前馈”神经网络不同,LSTM 有一个循环状态,每次数据流经网络时都会更新。这样,过去的信息可以用来预测现在。换句话说,网络是有记忆的。这是有状态 LSTMs 的情况,但是在本文中我们将尝试一些不同的东西。

概观

对于这个例子,我们将使用一个无状态 LSTM,这意味着网络的内存对于每一个批处理都会被重置。在这个具体的例子中,我们将使用单批音频数据。因为我们使用的是单批次,所以 LSTM 实质上变成了一个前馈网络,因为没有递归状态。

为什么我们要对单批数据使用无状态 LSTM 呢?无状态 LSTM 是一种有效的音频方法,通过将内部状态设置为零,我们降低了网络的复杂性,提高了网络速度。然而,对于我们的吉他放大器示例,网络仍然需要知道关于过去信号的一些信息,以做出准确的预测。

我们可以通过在无状态 LSTM 层之前添加 1-D 卷积层来做到这一点。在本例中,我们使用两个 1-D 卷积层,接着是 LSTM,再接着是密集(全连接)层。网络的输入是当前样本和指定数量的先前样本。1-D 卷积层用于从音频中提取特征,并减少进入 LSTM 层的数据量,从而显著加快处理速度。

图 1:通过网络的音频数据流(图片由作者提供)

注意:“密集”层与上一篇文章的 WaveNet 实现中的“线性”层执行相同的功能。这只是 Keras 和 PyTorch 之间命名约定的不同。

Keras 培训

我们将使用在 25%增益下从 Blackstar HT40 放大器记录的相同的 4 分钟样本,如上一篇文章中所述。

选择 Keras/Tensorflow 来实现无状态 LSTM 模型。Keras 是谷歌开发的人工智能框架 Tensorflow 的高级接口。Keras 培训的示例代码来自 Github 上的 SmartAmpPro 项目,包含在 train.py 文件中。使用顺序 Keras 模型相当简单,如下所示。

注意:SmartAmpPro 项目是训练和实时代码的结合。对于使用相同模型的纯训练代码,请参见 Github 上的guitar lstm

使用model = Sequential()创建一个基础模型,使用.add(layer_type(layer_params,...))将每个层依次添加到模型中。在上面的代码中,每一层的参数都是由先前定义的变量设置的。在 Keras 中,LSTM 层默认是无状态的,所以唯一需要的参数是hidden_units的数量。此参数决定了 LSTM 的大小。input_size定义了将使用多少先前的音频样本来预测当前样本。稍后在实时代码中使用的默认设置是 120,这是基于对准确性和处理速度的测试而选择的。这意味着当前的音频样本和先前的 119 个样本被用来预测下一个样本的值应该是什么。下图显示了对于给定的信号,音频数据的范围是如何馈入网络的。

图 2:音频范围如何被馈送到网络的示例(此处显示的样本之间的间隔被夸大)(图片由作者提供)

注意:Conv1D 层使用“步幅”参数,该参数用于在卷积中跳过数据点。对于步长 2,网络层将跳过每个卷积运算的每隔一个数据点。这加快了计算速度,同时保留了足够的信息来进行准确的预测。

在初始化顺序模型之后,必须处理输入音频数据。对于input_size = 120的情况,音频数据被切片(使用tf.gather)以获得每个现有音频样本的 120 个样本。每批 120 个音频样本是网络的新输入。输入批次的顺序被随机化以提高训练性能。这种切片操作只对输入进行。wav 文件,而不是输出。wav 包含 44100 个样本(或 1 秒钟的音频),带有一个input_size=120,那么切片后的结果将是一个形状数组:

(44100 - input_size + 1,120)或(43981,120)

样本量的减少是必要的,因为对于音频的前 119 个样本,我们不能查看过去的 120 个样本来进行预测。但是现在,我们有 43981 个由 120 个样本组成的阵列,彼此重叠,而不是 43981 个单一的音频样本。数据加载和处理如下所示。

注意:自定义数据加载器可用于对每个数据输入进行 120 个样本切片,而不是在训练前处理整个 wav 文件。这在训练时节省了 RAM 的使用。这是在 SmartAmpPro 项目中的 Colab 脚本 中实现的。

训练由model.fit()功能启动。随机化的音频数据(X_randomy_random)是拟合函数的输入,同时还有时期数、批量大小以及如何分割数据以进行验证和确认。

培训结果

针对这一特定 LSTM 实现的培训速度非常快。1-D 卷积层(使用默认的 SmartAmpPro 设置)将每个 120 个样本输入减少到 4 个样本,然后输入到 LSTM 层。以前的 WaveNet 在一个特定的 CPU 上要花 24 个多小时,而这个模型在同一个 CPU 上只需要 3 分钟。然而,训练不如 WaveNet 模型精确。可以选择更高的模型参数来提高精度,但是这在实时运行时会产生问题。

以下是 Blackstar HT40 在 30 个时期内的训练结果。获得了 0.11 的损失值。这里使用的损失函数是 amp 仿真论文中定义的 MSE(均方误差)的变体。这里显示了 8 毫秒数据的对比图:

图 3:使用无状态 LSTM 模型的 HT40 放大器的预测信号与实际信号

信号的幅度不像 WaveNet 模型那样紧密匹配,但是仍然可以学习主要特征。预测音频与实际音频的差异比较如下:

实际 Blackstar HT40 amp(过驱通道,25%增益):

由 Keras 模型预测:

模型转换

在实时使用经过训练的模型之前,必须将模型转换成合适的格式,以便加载到插件中。这里选择的格式是“json ”,这是为了可读性和计算世界的普遍接受。Keras 对模型状态数据使用“. h5”格式,这是 HDF5 压缩数据格式。SmartAmpPro " train.py "脚本中的 Python 代码用于执行这种转换。在转换之前,附加的“输入大小”和“步幅”参数被添加到. h5 模型文件中。实时代码中需要这些参数。

实时实现

实时实现的示例代码也来自 Github 上的 SmartAmpPro 。代码使用Num CPP进行矩阵计算,使用 json 加载转换后的 json 模型。NumCpp 是 Numpy Python 库的一个只有头文件的 c++实现。

实时音频插件使用了 JUCE 框架,这是一个用于创建音频应用的跨*台 c++框架。这里的基本目标是用高性能 c++代码重新创建通过 Keras 顺序模型的正向传递。为了将代码转换成 c++,我写了一个中间的 Python 脚本来确保我理解底层的计算。Pytorch 和 Tensorflow 处理图层的方法略有不同,因此实时应用程序以与训练代码完全相同的方式处理图层至关重要。

在“ ModelLoader ”类中加载并设置来自转换后的 json 模型的模型数据(状态参数)。一个经过训练的 json 模型的例子可以在 Github 上查看。然后,来自 ModelLoader 的数据用于实例化“lstm”类,该类也包含 1-D 卷积层和密集层。

下面是 lstm 类的主要处理方法。如果您熟悉 JUCE,这就是您在 PluginProcessor 的 processBlock()方法中调用的内容:

我们必须从训练代码中执行相同的音频切片,这需要对音频缓冲区进行一些仔细的处理,因为需要来自先前缓冲区(或块)的信息来预测当前缓冲区中的样本。用check_buffer(numSamples);检查缓冲区大小(可能有更好的方法来处理这个问题,但是如果用户改变了缓冲区大小, lstm 类需要知道)。然后调用set_data方法来安排音频输入到 LSTM 推理代码。让我们看看这是怎么回事:

在上面的代码中,前一个缓冲区的结束被设置在临时缓冲区的开始,new_buffer。然后当前缓冲区的数据被分配到new_buffer的末尾。执行切片操作,获取每个音频样本并将先前的样本input_size附加到二维数组dataold_buffer被设置为等于将用于下一个音频块的当前缓冲器。现在,来自data的每个输入数组都可以输入到第一个一维卷积层。

一维卷积是最复杂的层。可能有比这里写的更简单和更有效的方法来进行计算。NumCpp 库用于所有矩阵计算,这里使用的主要数据类型是nc::NdArray<float>

这是零填充函数,它向输入数据添加零,以使控件成为输出形状:

这是展开功能,它以与之前音频处理相同的方式分割数据。这些切片数组用于执行卷积计算。

前两个方法是从 main conv1d_layer方法调用的,该方法获取展开的矩阵,并对矩阵执行 tensordot(或 einsum)运算以完成卷积。

注意:第二个 Conv1d 层与第一个基本相同,但它处理输入的方式不同。为了简洁起见,这里省略了它,但是可以在 Github 上查看完整的内容。

处理完前两个 Conv1d 层后,再处理 LSTM 层。这是吉他仿真论文中算法的简化版本。它被简化了,因为对于一个无状态的 LSTM 来说,初始单元状态和隐藏状态可以被设置为零。

首先,在 Conv1d 层的输出和的训练 LSTM 权重之间执行点积。json 文件。这里也加入了偏差。

gates = nc::dot(conv1d_1_out, W) + bias;

当前隐藏状态是在内为循环计算的,其中循环次数由 LSTM 的 hidden_size HS决定。在 PyTorch 文档中可以看到有状态 LSTM 的完整方程组。对于无状态实现,先前的隐藏状态 h(t-1) 可以被设置为零,并且不需要计算单元状态,因为它不用于下一个 LSTM 状态。这里显示了无状态的 LSTM 实现:

最后,LSTM 层的输出被馈送到密集层,它只是输入和来自的训练好的权重的点积。json 文件加上偏差向量。该层的输出是预测音频的单个样本。下一秒声音重复 44100 次。咻!

实时性能

一般来说,上述算法比以前的 WaveNet 实现运行得更快。但是,如果您将层参数增加到高于 SmartAmpPro 默认值,它会很快变得太慢而无法实时运行,尤其是对于 Conv1d 层。大于 120 的 input_size 也会降低处理速度。

因为该模型只考虑了之前的 119 个样本(大约 27 毫秒),所以预测的信号有时会在错误的方向上剧烈摆动,但通常会很快自我校正。当与 WaveNet 输出图比较时,信号可能更加不稳定,这会对声音产生嗡嗡声/噪音影响。在我看来,WaveNet 的声音更流畅。声音的*滑度可以通过更高数量的时期来提高。需要注意的是,声音可能会非常干燥,所以应该使用混响等附加效果来获得更自然的声音。

训练速度是无状态LSTM 的最大优势,对于 TS-9 电子管震音踏板这样“容易”训练的声音,在 CPU 上不到 3 分钟就能获得很高的精度。这里是一个使用 SmartAmpPro 实时插件(加上额外的混响)的双声道录音。该演示展示了如何将相同的基础模型用于两种不同的吉他声音(干净的和过驱动的)。

在下一篇文章中,我们将使用一个有状态 LSTM 进行研究,看看我们能否提高训练的准确性和实时性能。

** [## 用于实时音频的神经网络:状态 LSTM

towardsdatascience.com](/neural-networks-for-real-time-audio-stateful-lstm-b534babeae5d)

感谢您的阅读!

  1. Alec Wright 等人,“深度学习的实时吉他放大器仿真”应用科学 10 期,第 3 期(2020): 766。**

实时音频的神经网络:WaveNet

原文:https://towardsdatascience.com/neural-networks-for-real-time-audio-wavenet-2b5cdf791c4f?source=collection_archive---------6-----------------------

作者图片

这是关于使用神经网络进行实时音频的五部分系列的第二部分。对于之前的介绍文章,点击 这里

在本文中,我们将使用 WaveNet 实时模拟吉他放大器。

WaveNet 由 DeepMind 公司开发,并在 2016 年的论文wave net:Raw Audio 的生成模型中介绍。它解释了该模型如何用于生成音频,如逼真的人类语音。它是一个前馈神经网络,意味着信息只通过网络向前移动,而不像 RNNs(递归神经网络)那样循环。

概观

这里使用的 WaveNet 的具体实现在论文 带深度学习的实时吉他放大器仿真 中有定义。本文使用扩展卷积层来捕捉吉他放大器的动态响应。扩张的层用于增加网络的感受域,允许它及时到达更远的时间来预测当前的音频样本。网络对过去的信号了解得越多,就能越好地预测下一个样本的值。

音频数据是一维的。它是一个随时间变化的数值(振幅)。一个 40 秒声音文件的可视示例(。wav 格式)显示在这里:

图 1:来自电吉他的 40 秒音频图

如果放大上面的图,可以清楚地看到信号是如何随时间变化的。下面显示的是大约 1/125 秒(8 毫秒)的相同音频。

图 2:电吉他 8 毫秒音频的曲线图

这里是上面吉他录音的音频:

这是直接从挡泥板电吉他远程音频信号。不太令人兴奋,是吗?但是,如果我们通过一个 Blackstar HT40 电子管放大器发送同样的信号,情况会变得更加有趣:

在下一节中,我们将尝试使用 WaveNet 在特定设置下创建 HT40 放大器的实时模型。使用过驱通道和中性均衡器将放大器设置为 25%的增益。录音是使用 SM57 麦克风进行的,距离扬声器格栅约 1 厘米,位于锥体中部。

Blackstar HT40 amp 和 SM57 麦克风(图片由作者提供)

请注意,麦克风和扬声器/音箱都会修改来自放大器电子设备的音频信号,这种设置可能不太适合尽可能精确地模拟放大器。但是考虑到这个放大器是租来的,我想他们更希望我不要打开它(你也不应该打开,除非你知道你在做什么!真空管电子设备包含非常高的电流和电压)。

PyTorch 培训

PyTorch 训练的示例代码来自 Github 上的 PedalNetRT ,用 Python 编写。注意,PedalNetRT 使用了Pytorch-lightning,这是一个有用的 py torch 包装器。

为了训练神经网络,我们将检查来自" model.py " python 文件的代码,该文件定义了 WaveNet 类的实现。整个结构由一维卷积层组成。继承 PyTorch 的nn.Module的基本 WaveNet 类如下所示:

forward()功能是进行音频处理的地方。此处使用了门控激活,如吉他放大器仿真论文中所定义。门控激活的输出被馈入self.residual层堆栈。输入样本x被添加回输出,该输出通过self.linear_mix层馈送,以将输出减少为单个音频样本。

网络接收输入音频样本,然后提取内部层中的声音特征,并输出单个预测音频样本。请记住,这种情况每秒钟发生 44,100 次!预测样本与已知音频(来自 HT40 amp 录音)进行比较,PyTorch 确定如何调整网络值以更接*目标。每次通过 4 分钟的训练数据是一个“时期”。在达到可接受的损失之前,典型的训练期可以持续 1500 个时期或更多。

WaveNet 类用定义神经网络的大小和结构的几个参数初始化。基本结构由self.input_layerself.hidden_layer / self.residuals(都是卷积层的堆叠)和self.linear_mix(输出层)组成。你可能已经注意到使用了一个定制的CausalConv1d类,而不是 PyTorch 内置的nn.Conv1d。这是因为 PyTorch 中的因果卷积必须手动完成(在撰写本文时)。因果卷积仅在数据的一侧使用零填充,而不是“相同的”填充,它会均等地填充两侧。

注意:通过向特定维度添加额外的零,使用零填充数据来控制卷积层的输出大小。

自定义的CausalConv1d类本质上是nn.Conv1d的包装器,它只在左侧填充输入数据。这里显示了CausalConv1d类的实现:

设置基本 WaveNet 类的最后一部分是_conv_stack函数,它堆叠所需数量的CausalConv1d层。堆栈中的层数由整数dilations定义。对于dilations=4,你得到一个四层的堆栈,每个层的膨胀率为“1,2,4,8”。对于dilations=8,你得到一个 8 层的堆叠,具有“1,2,4,8,16,32,64,128”的膨胀率。参数num_repeat重复膨胀层。例如,对于dilations=8num_repeat=2,您得到

“1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128”

总共 16 个隐藏卷积层。_conv_stack功能如下所示:

如前所述,在我们很好地匹配目标之前,WaveNet 的典型训练会话可以持续 1500 个时期。根据目标信号的复杂性,更多的历元可以导致更高的精度。一般规律是信号越失真(例如高增益),训练就越困难。通过选择更大的模型参数,可以以处理时间为代价来提高训练性能。训练速度和实时性能之间的权衡在这里很重要,并且对于每个目标硬件是不同的。

还需要注意的是,在吉他踏板的情况下,这种神经网络方法不适用于基于时间的效果,如延迟/混响/合唱/凸缘。它对失真/过驱动有效(即动态响应小于约 50 毫秒的效果)。

培训结果

以下是使用 PedalNetRT 对 HT40 进行 1500 多次训练的结果。损失值下降到大约 0.02。这里使用的损失函数是 amp 仿真论文中定义的 MSE(均方误差)的变体。这里显示了 8 毫秒数据的对比图:

图 HT40 放大器的实际信号和预测信号之间的比较

这是预测的音频(与之前的实际 HT40 音频相比):

由此产生的 0.02 的损失非常接*原始记录。从 SoundCloud mp3 样本中,你很难分辨出哪个是哪个。训练有素的耳朵,高品质的录音室监听系统,以及原声。wav 文件,人们可能会告诉区别,但我认为 0.02 损失是一个成功的捕捉 HT40 放大器。根据其他测试,0.05 损失听起来不错,但感觉不同,0.10 损失明显不同,但可以通过额外的均衡器处理听起来接*。0.2 或更高的损失仍然是一个有趣的声音,但根据经验,我认为这是一个不成功的捕捉。

训练时间取决于硬件、型号大小和录音长度。在 Nvidia Quadro 2000 GPU 上,运行 1500 个 epochs 需要大约 4 个小时。在内置 Nvidia 显卡的中等价位笔记本电脑上,同样的培训大约需要 8 个小时。对于纯 CPU 培训,您将需要 24 小时以上的培训时间。

模型转换

在实时使用经过训练的模型之前,必须将模型转换成合适的格式,以便加载到插件中。这里选择的格式是“json ”,因为它的可读性和在计算世界中的普遍接受性。PyTorch 使用它自己的”。pt“格式”。ckpt "代表 py torch-闪电。PedalNetRT 中使用一个名为“ export.py 的脚本来执行这种转换,并以 WaveNetVA 理解的方式排列数据。

实时实现

实时 c++的示例代码来自 Github 上的 WaveNetVA (也在smart guitar ampsmart guitar pedal中实现)。代码使用 特征值 进行矩阵计算。****

实时插件使用 JUCE 框架,这是一个跨*台的 c++框架,用于创建音频应用。基本目标是用高性能 c++代码从 PyTorch WaveNet 类中重新创建forward()函数。我们不会在这里涵盖所有的代码,但我会触及关键点。

来自转换后的 json 模型的模型数据(状态参数)在 WaveNet 类中加载和设置。下面显示了setParams方法,它基于 json 数据建立了一个 WaveNet 实例。一个经过训练的 json 模型的例子可以在 Github 上查看。

这里定义了inputLayeroutputLayerconvStack(内层)。每层都有通道数、滤波器宽度、扩张和激活功能的设置。

这里显示了 WaveNet 类的主要处理方法,它获取输入音频缓冲区inputData,通过每一层(inputLayerconvStackoutputLayer)对其进行处理,然后将处理后的音频复制到输出缓冲区outputData

音频数据实时流经每一层(通过音频缓冲区或“块”),但实际的卷积计算是在“convolution . CPPprocessSingleSample方法中执行的,该方法处理单个音频样本:

该方法使用 json 模型中的层设置来确定数据如何卷积,或者数据如何在层中流动。在最基本的操作中,这只是与内核(训练的神经网络值)相乘:

outVec = outVec + *(fifo+readPos) * (*it);

以及偏置向量的加法:

outVec = outVec + bias

复杂的部分是确定如何索引每个数组,以便正确计算卷积层。我会留到下一天再说!

一旦当前音频缓冲区被处理(从 16 到 4096 个 2 的倍数的样本,取决于音频设备设置),它将被转换回模拟,并从扬声器或耳机输出。幸运的是,JUCE 框架处理了所有这些问题。

实时性能

这个 WaveNet 实现完全能够在任何现代计算机上实时运行。然而,与使用传统建模的音频 DSP 软件相比,它的 CPU 使用率要高得多。使用电路分析可以以更快的处理速度实现相同质量的建模(以吉他放大器为例)。可以说,只用音频样本而没有领域专业知识来模拟这些复杂系统的能力是一个很好的权衡。

这是一个 SmartAmp 插件的实时演示视频,它使用 WaveNet 来模拟小管放大器(Fender Blues Jr .)和其他放大器。

作为一名吉他手,我对 WaveNet 的看法是,与目标放大器/踏板相比,它的声音非常自然。它似乎在高增益方面有问题(如在金属音乐中),但可以准确处理中增益和干净的音调。在模型中也观察到了低音的衰减。改变模型的大小会对声音产生很大的影响,也会影响它实时*稳运行的能力。

在下一篇文章中,我们将研究使用无状态 LSTM,看看我们是否可以在保持高质量声音的同时提高 CPU 使用率和训练时间。在此继续阅读:

****https://link.medium.com/Jg5ft4WM0fb

感谢您的阅读!

  1. Aaron van den Oord 等人,“wave net:Raw Audio 的生成模型” arXiv 预印本 arXiv:1609.03499 ,2016 年。
  2. Alec Wright 等人,“深度学习的实时吉他放大器仿真”应用科学 10 期,第 3 期(2020): 766。****

用于 R 中生存分析的神经网络

原文:https://towardsdatascience.com/neural-networks-for-survival-analysis-in-r-1e0421584ab?source=collection_archive---------14-----------------------

训练、调整和比较生存网络的演示

更新:我已经把本教程中的大部分包从 CRAN 上拿走了,原因是如果你感兴趣,你可以在这里阅读。要安装本教程中的软件包,你只需要将我的 R-universe 页面添加到你的 repos 中——这在下面的第一个要点中演示过,或者你可以在这里查看安装这些软件包的其他方法。

我收到了许多关于 R 中的生存神经网络(“生存网络”)的问题,从“这可能吗?”到“我如何在 R 中安装 Python?”以及“我如何调整这些模型?”。如果你是一个对生存网络感兴趣的 R 用户,那么这篇文章就是为你准备的!这不是一个如何使用相关软件包的教程,而是一个回答这些问题的演示。

这是一个高级演示,我假设你知道:I)什么是生存分析;ii)什么是神经网络(以及常见的超参数);iii)基本的机器学习(ML)方法,如重采样和调谐。如果需要,我很乐意在以后的文章中全面讨论这些话题。

在本文中,我们将介绍如何:I)在 R 中安装 Python 模块;ii)通过{mlr3proba}使用{survivalmodels}中实现的模型;iii)用{mlr3tuning}调整模型,用{mlr3pipelines}⁴预处理数据;iv)对{mlr3proba}中的模型进行基准测试和比较;v)分析{mlr3benchmark}⁵.的结果这些软件包中有许多都属于 mlr3 系列,如果您想了解更多,我建议您从 mlr3book⁶.开始

本演示中的代码是一个“玩具”示例,选择在我非常旧的笔记本电脑上快速运行代码,预计所有型号的性能都很差。

让我们得到深度学习!

照片由乌列尔 SCUnsplash 上拍摄

安装软件包

我们将使用几个软件包,确保您安装了以下软件:

对于这个演示,我使用了以下包版本:gg plot(v 3 . 3 . 2);MLR 3 benchmark(v 0 . 1 . 2);MLR 3 extra learners(v 0 . 3 . 5);MLR 3 管道(v 0 . 3 . 4);MLR 3 proba(v 0 . 3 . 2);MLR 3 调优(v 0 . 8 . 0);生存模型(v0.1.7)。

生存模型

包{survivalmodels}当前包含神经网络:

  • CoxTime⁷
  • DeepHit⁸
  • DeepSurv⁹
  • 物流危害⁰
  • PCHazard
  • DNNSurv

其中的前五个使用{reticulate}来连接伟大的 Python {pycox} ⁴包,该包由哈瓦德·克瓦梅编写,这意味着您可以使用 r 语言中的神经网络来实现 Python 的速度。DNNSurv 使用 R {keras} ⁵软件包。

在本文中,我们将只看前五个,因为它们在文献中被更好地建立,并且它们具有相同的接口,这简化了调谐,正如我们将在下面看到的。在这篇文章中没有提供网络的描述,但是如果需要的话,我很乐意在以后的文章中详细描述。

在 R 中使用 Python

要在{survivalmodels}中使用 Python 模型,您需要在 R 中设置一个 Miniconda 环境,并安装所需的 Python 模块。使用{survivalmodels}中的函数可以安装所需的模块:

install_pycox使用reticulate::py_install安装 Python 包{pycox}和可选的{torch} ⁶ ( install_torch = TRUE)。install_keras 将安装{keras}和可选的{tensorflow} ⁷ ( install_tensorflow = TRUE)。

播种

确保用 Python 实现的模型产生可再现的结果比通常要稍微复杂一些,因为必须在多个地方设置种子。{survivalmodels}用一个名为set_seed的函数简化了这一过程。

mlr3proba

为了在安装后运行这些模型,我们将使用不同的界面。{survivalmodels}的功能有限,这对于基本的模型拟合/预测来说是可以的,但神经网络通常需要数据预处理和模型调整,因此我们将使用{mlr3proba},它是{mlr3} ⁸系列软件包的一部分,包括概率监督学习功能,生存分析是其中的一部分。{mlr3}软件包使用 R6 ⁹接口在 r 中进行面向对象的机器学习。mlr3 的完整教程可以在{mlr3book}中找到,其中还有一章是关于{mlr3proba} ⁰.的生存分析

现在让我们来设置我们的实验!

生存数据

我们需要做的第一件事是获取一些生存数据集来训练我们的模型,在{mlr3proba}中,数据集保存在任务中,其中包括关于特征和目标的信息。我们将使用{mlr3proba}、whas附带的一个任务,以及我们自己设置的一个任务(虽然{mlr3proba}中也已提供,但这只是一个示例)。

获取和调整学习者

现在该你上场了!我们将在{survivalmodels}(除了 DNNSurv)中训练和调整 Pycox 神经网络。调节由{mlr3tuning}包处理。我们不会为模型指定一个定制架构,而是使用默认架构,如果您熟悉 PyTorch,那么您可以选择创建自己的架构,如果您愿意的话,可以将它传递给模型中的custom_net参数。

超参数配置 训练和调整神经网络是一门艺术,但对于本文,我们保持简单。我们将使用以下配置来调整神经网络:

  • 辍学分数在[0,1]范围内调整
  • 重量在[0,0.5]范围内衰减
  • 学习率超过[0,1]
  • {1,…,32}上一层中的节点数
  • {1,…,4}上的隐藏层数

为此,我们使用{paradox}包(也是{mlr3}的一部分)来创建超参数搜索空间。{survivalmodels}中的所有 Pycox 学习器都有一个相同的参数接口,因此只需提供一个搜索空间。在{survivalmodels}中,节点数num_nodes被指定为任意长度的向量,这是不可直接调整的。因此,我们分别调整一层中的节点数nodes和层数k,然后提供一个转换来组合这两者。

请注意,在我们的转换中,我们假设每层有相同数量的节点,这是一个相当常见的假设,但是我们可以考虑更高级的转换。

我们现在将学习者包裹在一个AutoTuner中,这使得学习者可以很容易地在基准实验中调整。因为我们正在调优多个相似的学习者,所以我们可以创建一个函数来简化AutoTuner 的创建。对于调优,我们使用:2/3 分离维持、c 索引优化和 2 次迭代随机搜索。这些设置不应该在实践中使用,只是为了让事情运行得更快。在实践中,我通常推荐三重嵌套交叉验证,rsmp("cv", folds = 3)和 60 次迭代随机搜索,trm("evals", n_evals = 60)

现在让我们找到我们的学习者并应用我们的函数。对于所有学员,我们将设置以下超级参数:

  • 嵌套训练数据的 30%将被保留作为提前停止的验证数据,frac = 0.3, early_stopping = TRUE
  • 亚当优化器,optimizer = “adam"
  • 最多 10 个历元,epochs = 10

当我们使用早期停止时,历元的数量通常会大幅度增加(比如最少 100 个),但在这里会减少以加快运行速度。所有其他超参数使用模型默认值。

预处理
所有的神经网络都需要一些数据预处理。{mlr3pipelines}包,特别是encodescale pipeops 使这变得简单,它们分别执行一键编码和特征标准化(通过改变参数可获得其他方法)。同样,我们将创建一个适用于所有学习者的函数。

基准

我们准备好了!对于我们的实验,我们将使用三重交叉验证,但通常五重交叉验证将是首选,rsmp("cv", folds = 5)。为了比较,我们还将卡普兰-迈耶和考克斯 PH ⁴学习者添加到实验中。我们将把我们的基准结果与哈勒尔的 c 指数⁵和⁶综合格拉夫得分(也有许多其他措施可用)进行汇总。

结果由 Harrell's C 和 Graf 综合评分汇总

在我们的玩具演示中,我们可以从这些结果中初步得出结论,Cox PH 的性能最好,DeepHit 的性能最差。

分析结果

由于我们已经在多个独立数据集上运行了我们的模型,我们可以使用{mlr3benchmark}更详细地比较我们的结果。下面的注释代码只是展示了可能的情况,但没有提供任何细节(如果您对未来的教程感兴趣,请告诉我!).

独立数据集上的弗里德曼检验结果。

Friedman 检验结果表明,两个模型在任何一个测量方面都没有显著差异(假设 p ≤ 0.05 是显著的)。现在让我们说,如果 p ≤ 0.1,模型是显著不同的(我不建议这是普遍的),所以我们可以看看临界差异图⁷来比较这些模型。

IGS 的临界差异图,左边是表现最好的学生,右边越来越差。粗黑线将没有显著差异的学习者联系起来。

结果表明,没有模型优于 Kaplan-Meier 基线,我们的分析是完整的(对于这个玩具设置,这并不奇怪!).

摘要

在这个演示中,我们使用了用 Python 实现的神经网络,并通过{survivalmodels}进行接口。我们用{mlr3proba}接口加载了这些模型,得到了一些生存任务。我们使用{mlr3tuning}设置超参数配置和调节控制,使用{mlr3pipelines}进行数据预处理。最后,我们使用{mlr3benchmark}来分析多个数据集的结果。我希望这篇文章展示了 mlr3 接口是如何简化从{survivalmodels}中选择、调整和比较模型的。

感谢阅读!继续评论,发电子邮件,或发微博给我(拉斐尔 101 ),提出问题,评论,或只是聊聊 ML 和统计!

参考

¹ Sonabend, R. (2020). survivalmodels: Models for Survival Analysis. CRAN. https://cran.r-project.org/package=survivalmodels
² Sonabend, R., Király, F. J., Bender, A., Bischl, B., & Lang, M. (2021). mlr3proba: An R Package for Machine Learning in Survival Analysis. Bioinformatics. https://doi.org/10.1093/bioinformatics/btab039
³ Lang, M., Richter, J., Bischl, B., & Schalk, D. (2019). mlr3tuning: Tuning for “mlr3.” CRAN. https://cran.r-project.org/package=mlr3tuning
⁴ Binder, M., Pfisterer, F., Bischl, B., Lang, M., & Dandl, S. (2019). mlr3pipelines: Preprocessing Operators and Pipelines for “mlr3.” CRAN. https://cran.r-project.org/package=mlr3pipelines
⁵ Sonabend, R., & Pfisterer, F. (2020). mlr3benchmark: Benchmarking analysis for “mlr3.” CRAN. https://cran.r-project.org/package=mlr3benchmark
https://mlr3book.mlr-org.com/
⁷ Kvamme, H., Borgan, Ø., & Scheel, I. (2019). Time-to-event prediction with neural networks and Cox regression. Journal of Machine Learning Research, 20(129), 1–30.
⁸ Lee, C., Zame, W. R., Yoon, J., & van der Schaar, M. (2018). Deephit: A deep learning approach to survival analysis with competing risks. In Thirty-Second AAAI Conference on Artificial Intelligence.
⁹ Katzman, J. L., Shaham, U., Cloninger, A., Bates, J., Jiang, T., & Kluger, Y. (2018). DeepSurv: personalized treatment recommender system using a Cox proportional hazards deep neural network. BMC Medical Research Methodology, 18(1), 24. https://doi.org/10.1186/s12874-018-0482-1
¹⁰ Gensheimer, M. F., & Narasimhan, B. (2019). A scalable discrete-time survival model for neural networks. PeerJ, 7, e6257.
¹¹ Kvamme, H., & Borgan, Ø. (2019). Continuous and discrete-time survival prediction with neural networks. ArXiv Preprint ArXiv:1910.06724.
¹² Zhao, L., & Feng, D. (2020). DNNSurv: Deep Neural Networks for Survival Analysis Using Pseudo Values. https://arxiv.org/abs/1908.02337
¹³ Ushey, K., Allaire, J. J., & Tang, Y. (2020). reticulate: Interface to “Python.” CRAN. https://cran.r-project.org/package=reticulate
¹⁴ Kvamme, H. (2018). pycox. https://pypi.org/project/pycox/
¹⁵ Allaire, J. J., & Chollet, F. (2020). keras: R Interface to “Keras.” CRAN. https://cran.r-project.org/package=keras
¹⁶ Paszke, A., Gross, S., Chintala, S., Chanan, G., Yang, E., DeVito, Z., … Lerer, A. (2017). Automatic differentiation in pytorch.
¹⁷ Abadi, M., Agarwal, A., Barham, P., Brevdo, E., Chen, Z., Citro, C., … Zheng, X. (2015). TensorFlow: Large-Scale Machine Learning on Heterogeneous Systems. https://www.tensorflow.org/
¹⁸ Lang, M., Binder, M., Richter, J., Schratz, P., Pfisterer, F., Coors, S., … Bischl, B. (2019). mlr3: A modern object-oriented machine learning framework in R. Journal of Open Source Software, 4(44), 1903. https://doi.org/10.21105/joss.01903
¹⁹ Chang, W. (2018). R6: Classes with Reference Semantics. https://cran.r-project.org/package=R6
²⁰ https://mlr3book.mlr-org.com/survival.html
²¹ Lang, M., Bischl, B., Richter, J., Sun, X., & Binder, M. (2019). paradox: Define and Work with Parameter Spaces for Complex Algorithms. CRAN. https://cran.r-project.org/package=paradox
²² Bergstra, J., & Bengio, Y. (2012). Random search for hyper-parameter optimization. The Journal of Machine Learning Research, 13(1), 281–305.
²³ Kaplan, E. L., & Meier, P. (1958). Nonparametric Estimation from Incomplete Observations. Journal of the American Statistical Association, 53(282), 457–481. https://doi.org/10.2307/2281868
²⁴ Cox, D. R. (1972). Regression Models and Life-Tables. Journal of the Royal Statistical Society: Series B (Statistical Methodology), 34(2), 187–220.
²⁵ Harrell, F. E., Califf, R. M., & Pryor, D. B. (1982). Evaluating the yield of medical tests. JAMA, 247(18), 2543–2546. http://dx.doi.org/10.1001/jama.1982.03320430047030
²⁶ Graf, E., Schmoor, C., Sauerbrei, W., & Schumacher, M. (1999). Assessment and comparison of prognostic classification schemes for survival data. Statistics in Medicine, 18(17–18), 2529–2545. https://doi.org/10.1002/(SICI)1097-0258(19990915/30)18:17/18<2529::AID-SIM274>3.0.CO;2-5
²⁷ Demšar, J. (2006). Statistical comparisons of classifiers over multiple data sets. Journal of Machine Learning Research, 7(Jan), 1–30.

从头开始的神经网络(第一部分)

原文:https://towardsdatascience.com/neural-networks-from-the-ground-up-part-1-880e6228d991?source=collection_archive---------37-----------------------

了解神经网络如何工作。不需要神经网络的先验知识。

大家都知道神经网络很神奇。在过去的二十年里,神经网络已经从一种实验方法发展成为我们今天使用最广泛的机器学习技术。现在,你自己也比以往任何时候都更容易获得神经网络的力量;像 TensorFlow 这样的框架使得构建神经网络变得轻而易举。然而,我认为它仍然是值得的,看看引擎盖下,了解一切是如何工作的。

这将是一个多部分的系列,我们将详细研究神经网络,首先发展理论,然后从头开始编码。除了一些高中数学知识外,不需要任何先验知识,也不会使用任何框架——一切都将从头开始编码。在这第一部分中,我们着重于神经网络理论。

第一部分:神经网络力学

让我们从一个神经网络图开始:

一个神经网络的例子。图片作者。

我们网络的输入是向量 x = (x₁,x₂).在机器学习行话中,我们将输入称为输入层。我们网络的目标是计算输出向量 o ,也称为输出层。从图中,我们注意到还有另一个向量, h ,在我们可以计算 o 之前需要计算它。向量 h 被称为隐层,因为它夹在网络中间,不被只能看到输入输出层的外界观察者看到。在这个网络中只有一个隐藏层,实际上你可以有更多的隐藏层。

各层的单个组件(图中的圆圈)被称为网络的节点。箭头上的数字称为网络的权重。每个节点的值是根据前一层的节点和来自这些节点的箭头上的权重来计算的。这听起来很混乱,所以我们来看一个具体的例子。隐藏层中的节点 h₁有两个指向它的箭头,分别来自节点 x₁和 x₂.这两个箭头的权重分别为 2 和 3。由于来自 x₁的箭的重量是 2,对 h₁的贡献是 2x₁.相应的,x₂对 h₁的贡献是 3x₂.因此 h₁的价值是 2x₁ + 3x₂.我们按照这种方法来计算隐藏层中所有节点的值:

h₁ = 2x₁ + 3x₂

h₂ = -2x₁ + 4x₂

h₃ = x₁ + 2x₂

然而,我们还没有计算完。请注意隐藏层下橙色框中的 sigma 符号。这代表了一个激活函数,在我们从上一层计算出隐藏层的所有元素后,我们对它们进行元素化的使用。激活函数的存在是为了给我们的网络引入非线性,允许它学习更多类型的函数。在这篇文章中,我会更详细地解释为什么会这样。一些常见的激活函数是 sigmoid、tanh 和 ReLU 函数。我们将在以后的文章中讨论这些常见的函数,因为现在我们假设σ是某个任意的激活函数。为了加入激活函数,我们需要将方程编辑为:

h₁ = σ(2x₁ + 3x₂)

h₂ = σ(-2x₁ + 4x₂)

h₃ = σ(x₁ + 2x₂)

现在我们已经计算了 h ,我们可以计算 o 。再次跟随箭头,我们有:

o₁=5h₁–2h₂–3h₃

o₂ = 4h₁ + 3h₂ + h₃

请注意,输出层上没有激活功能,这是由一个网络接一个网络做出的决定。有时输出层会有一个激活功能,在我们的例子中没有。

第 2 部分:使用矩阵

我们现在已经看到了神经网络不同部分的概述,以及如何从输入层计算输出层。我们的下一个目标是使这种计算更有效。我们目前单独计算每一层的每个节点。如果有一种方法可以并行计算一层中的所有节点,我们可以节省很多时间。事实证明,矩阵乘法正是这样做的。再次考虑我们计算隐藏层的三个等式:

h₁ = σ(2x₁ + 3x₂)

h₂ = σ(-2x₁ + 4x₂)

h₃ = σ(x₁ + 2x₂)

我们可以用一个矩阵乘法方程来表示这三个方程:

图片作者。

以前σ是从一个标量到另一个标量的激活函数,现在σ是从一个矢量到另一个矢量的激活函数。你可以自己算出,这个矩阵方程确实给出了和上面一样的三个方程。我们也可以把这个矩阵方程写成矢量化的形式:h=σ(w₁x)。W₁被称为权重矩阵,因为它包含了从一层到另一层的权重。这里是 W₁:*

图片作者。

我们还可以使用矩阵来计算输出层:

图片作者。

这个方程的矢量化形式是o=w₂h。W₂是另一个权重矩阵:*

图片作者。

我们现在可以把整个神经网络写成矢量化的形式:o=w₂σ(w₁x)。当我们在以后的文章中为我们的网络编写代码时,我们会看到这种矢量化的形式更容易实现,并且运行速度比我们原来的方程快得多。我们的矢量化方程也可以重写为函数的组合。这看起来像是无用的记数工作,但是当我们推导出训练网络的规则时,另一种形式就会派上用场。

考虑函数 f(W,x*)= W x。该函数取一个矩阵 W 和一个向量 x 作为其输入,并返回矩阵乘法结果作为输出。我们可以把我们的矢量化网络改写为 o = f(W₂,σ(f(W₁, x ))。这将是我们在以后的文章中用来推导训练网络的规则的等式。

到目前为止,我们已经检查了神经网络的机制,并找到了一种很好的计算输出层的矢量化方法。在下一篇文章中,我们将学习如何训练网络。敬请期待!

神经网络:不仅仅是深度学习

原文:https://towardsdatascience.com/neural-networks-more-than-deep-learning-a0c9e1629781?source=collection_archive---------23-----------------------

神经网络是多功能的,让我们看看三种类型

神经网络是计算智能的一个分支,远远超出了深度学习。虽然许多人在寻找最深的网络,但其他人正在寻找不同类型网络的独特实现和用途。在这篇文章中,我给出了三种不同类型的神经网络的高层次概述——卷积神经网络、自组织特征映射和极限学习机。

埃伯哈德·🖐·格罗斯加斯泰格在 Unsplash 上拍摄的照片

动机

计算智能(CI)社区每年产生的研究数量令人震惊。竞争情报的一个特殊分支是一直受欢迎的神经网络。神经网络之所以成为主流,是因为它们的性能和对我们能把架构做多深的着迷。如今,深度学习似乎是“人工智能”的代名词,这推动了他们的接受度。我第一次接触深度学习是在做硕士论文的时候。我试图对多维声音信号进行分类(通过记录从感兴趣的区域反射回来的声音创建的图像)。那时,AlexNet 是精英;很自然地,我实现了这个卷积神经网络(CNN)来评估我的数据。令我惊讶的是,它表现得非常好。这次经历让我见识到了这些黑匣子的威力。然而,直到几年后我才知道神经网络远不止深度分类/回归算法。IEEE 计算学会将这一分支定义为“使用人脑作为灵感的来源,人工神经网络(NNs)是大规模并行分布式网络,可以从示例中学习和归纳。这个研究领域包括前馈神经网络、递归神经网络、自组织神经网络、深度学习、卷积神经网络等等。”您知道神经网络领域不仅仅是深度架构吗?我很兴奋地了解了其他一些领域,我将在这篇文章中分享它们。

卷积神经网络

照片由乔·凯恩Unsplash 上拍摄

卷积神经网络(CNN)(可以说是最流行的神经网络类型)是主要关注图像处理的神经网络。在描述神经网络时,大多数人会给出将图像分类为猫或狗的例子。CNN 正是执行这一任务的神经网络类型。为了分解 CNN,让我们考虑 CNN 的三个不同方面— 滤波器架构优化功能

过滤器
在本文中,我们将过滤器视为 CNN 的构建模块。每个滤波器是在训练阶段优化的一组权重。我们的目标是学习一组代表我们要分类的对象类型的权重。例如,第一层过滤器可以学习边缘,当我们进一步进入网络时,这些过滤器被组合以形成更复杂的形状。然而,这并不是真正发生的事情,因为我们不是为了学习形状而优化,而是为了准确性而优化。尽管优化形状是可能的,但是看看我们为形态学共享神经网络写的一篇论文吧。

架构
如果滤镜是构建模块,那么架构就是我们用滤镜构建出来的。架构是由其结构定义的,结构可以是深的(多层过滤器)和宽的(每层有许多过滤器)。没有完美的架构,这就是为什么有这么多的架构。我的研究领域之一是融合 CNN 进行图像分类2。我们融合了七个网络,我们发现融合网络提高了性能——表明多种架构更好。许多因素限制了哪种架构最适合您的情况。例如,您将在哪里部署您的 CNN?在你的手机上?在云端?更深的网络需要更多的计算能力,因此在使用(或构建)架构时考虑这些因素至关重要。

优化功能
优化功能驱动 CNN 的训练。对于图像分类,其目标可能是正确地分类尽可能多的图像。但是,假设 CNN 正在尝试执行对象定位(在图像中找到一个对象)。在这种情况下,优化函数将尝试查找并放置一个框在一个对象周围(并且只在该对象周围)。我们的创造力仅限于优化函数能做什么。

插图突出了 CNN 的三个组成部分。我的插画:)-Joe Caione 在 Unsplash 上的快乐狗狗 if 的照片

CNN 为一系列问题的解决打开了大门。像 TensorFlow 和 Pytorch 这样的开源软件包不仅促进了 CNN 的使用,也促进了任何 NN 的使用。鉴于它们的易用性,我确实觉得我们应该鼓励负责任地使用这些工具。在一个小时之内建立一个具有定制优化功能的定制架构是可能的(我已经这样做了几次)。我们应该挑战高精度足以部署模型的观念。作为这些技术的实践者,我相信我们每天都在做得更好,但我们应该继续追求卓越——特别是当我们把很多事情留给数据的时候。

应用
一如既往,我给大家留下一个例子。几年前,我在一家提供碎片监测服务的公司工作。监视器通过每年分析成千上万的图像来确保正确的负载估计。因此,我使用 CNN 来估计每次装载中碎片的数量(回归)和类型(分类)。这项任务不需要创建自定义架构;然而,我迭代了几个现成的架构,以找到性能最好的架构。这个项目花了几周时间,因为数据需要清理。数据中有例外,需要删除以确保我们不是在有缺陷的图像上进行训练。我确实改变了这个用例的优化函数。准确度分数对于这个应用程序来说还不够。对客户来说,一个重要因素是,如果加载调用出错,也不会差太多。例如,如果卡车是满的,我们从来不想称它是空的。因此,我将最大绝对误差添加到优化函数中。这种更新可以最大限度地减少回归值的偏差。我们的 CNN 可能会得到更多错误的图像,但它可以根据它们的错误程度来创建一个界限。

自组织特征地图

Marjan Blan | @marjanblan 在 Unsplash 上的照片

如果你用谷歌搜索“神经网络”,它会找到大约 162,000,000 个结果。其中很少是自组织特征映射(SOFMs)。SOFMs 与你今天听到的大多数神经网络相对不同——在应用和设置上都不同。SOFMs 推动了神经气体等其他算法的创建,但在这篇文章中,我们将从基础开始。

SOFMs 是一种无人监管的算法,这意味着我们没有标签(想想猫或狗)。大多数无监督算法要么执行聚类,要么执行降维。降维发生在我们对某个事物有很多维度,需要降维的时候。这是一个粗略的例子,但考虑一个立方体。它的宽度、高度和深度是定义它的一种方式。然而,如果我们将这些特征相乘,就可以计算出它的体积。我们已经从对一个对象的三个描述减少到一个,因此我们已经将它的数据维度从三个减少到一个。

不幸的是,数据并不总是如此清晰。很多时候,当我们从高维空间缩减时,我们会因为缩减到几个维度而丢失信息。同样,如果立方体是蓝色的,我们也不会用它的体积值来表示。结果,一整套算法试图降低数据的维度。在没有完美的归约工具的情况下,存在很多算法。NN 社区开发了 SOFMs 来解决这个问题。

要查看 SOFMs 的算法分类,请查看由阿比纳夫·拉尔汉撰写的这篇文章。

应用

我最喜欢使用的 SOFMs 是它们在二维空间中可视化高维特征向量的能力。SOFMs 有两个阶段——训练和映射。在训练期间,随机生成的神经元“地图”开始训练过程。在每次迭代中,我们向映射提供训练数据,它通过将具有相似输出的神经元分组来更新/组织自身。目标是相似神经元的组/簇将自己与其他组分开。如果成功,我们将能够在二维图像中看到不同的星团。在映射期间,新样本(来自高维)被分类到它们所属的聚类中。一个非常简单的例子涉及像素颜色。像素可以用三个值来表示——R、B 和 B。我们可以使用 SOFM 算法对这些像素进行聚类。在这个例子中,我们知道颜色会聚集在一起,但是如果我们对颜色一无所知,我们会在查看地图后知道它们的相似性。下一张图是我们可以预期的一个例子。

在这个例子中,我们从许多像素值中学习特征图。我的插图:)

无监督方法在连接到应用程序时可能具有挑战性,因为它们通常用于探索数据集以更好地理解它。在大数据时代,我们的样本可能有成千上万个特征,数据科学家无法消化这么多的信息。因此,无监督技术将变得至关重要,因为我们正在收集更多的数据,并需要快速理解这些数据。SOFMs 可能是更好地洞察高维数据的关键。

极限学习机

Unsplash 上的网络甜甜圈拍摄的照片

极限学习机(ELMs)是一种不太为人所知的神经网络。ELMs 背后的理论不同于其他神经网络的训练。记住,神经网络通常使用反向传播来学习神经网络中的所有权重。

然而,在 ELMs 中,在训练期间只学习一组重量。各层中的权重是固定的,并随机初始化,只有最后一层的权重需要学习。当数据在网络中传播时,随机初始化的权重随机地变换数据。网络的最后一层最终变成了一个需要求解的线性方程。要使这个工具工作,一些数学技巧是必要的,这里有一个很好的描述4

通常,我会强调一些类型的应用程序,但是到目前为止,您可能已经看到了一百种监督分类算法。相反,这里有一个关于榆树的有趣事实。榆树周围有戏剧。在学术论文中,戏剧很少出现在这一层面,但在榆树上却出现了。学术界因植根于坚实数学的新方法而繁荣。不幸的是,榆树可能不符合这个要求。榆树收到了反弹,因为榆树的想法不是新的,和[5]的作者想确保分配信贷适当的创造者正确。他们声称榆树是其他方法,他们不需要一个新的名字——极限学习机。

结论

总之,除了世界上典型的、主流的谷歌网络和 GPT-4 之外,还有许多不同类型的网络。当然,我会在该表扬的地方给予表扬,这些国家队绝对值得表扬。但是,记住神经网络的分支作为一个整体同样重要。我在这篇文章中只触及了皮毛,但是这个领域每天都在进步。我等不及要看接下来会发生什么了!

参考

[1]https://arxiv.org/pdf/1912.02259.pdf

[2]https://www . research gate . net/publication/326586154 _ explable _ AI _ for _ Understanding _ Decisions _ and _ Data-Driven _ Optimization _ of _ the _ Choquet _ Integral

[3]https://medium . com/@ abhinavr 8/self-organizing-maps-ff 5853 a 118d 4

[4]https://erdem . pl/2020/05/极限学习机简介

[5]https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.217.2330

Swift 中的神经网络

原文:https://towardsdatascience.com/neural-networks-on-swift-ba181dcdfde5?source=collection_archive---------15-----------------------

在 Swift 中从头开始创建神经网络框架

安迪·凯利在 Unsplash 上的照片

介绍

我们生活在伟大的技术周围,比如自动驾驶汽车、语音助手、图像分析仪。他们中的大多数使用神经网络作为他们算法的基础。我们将使用 Swift 从头开始构建一个基本的神经网络。

一些理论

在开发应用程序之前,我们必须学习神经网络的理论。神经网络由输入、输出和隐层组成。全连接简单层由神经元组成。突触将神经元相互连接起来。每个突触都有自己的权重值。在生成神经网络的过程中,它用随机值填充权重。它们会在训练时改变(在下面的动画中,红色表示高重量蓝色表示低重量)。

训练神经元。图片作者:Yauheni Stsefankou

训练过程分为几个时期。我们在每个时期处理数据集中的所有数据样本。我们用数据样本的输入填充输入层。然后每一层通过激活功能处理输入,并通过突触发送到下一层。当一个值通过突触时,它会将该值乘以突触权重。当计算神经元的值时,它将所有输入值和偏差相加。

正向传播。图片作者:Yauheni Stsefankou

这是一个神经网络的例子。它得到一个无符号的 4 位数字并返回该数字是否为偶数。注意所有偶数的二进制表示都以 0 结尾。这意味着预测只取决于最后一位(输入层的第四个神经元)。这就是为什么我强调了连接到输入层最后一个神经元的突触。输入层的其他突触没有意义,它们的权重在训练期间接*零。

神经网络示例。图片作者:Yauheni Stsefankou

短评

由于缺乏非常紧密的优化和 GPU 兼容性,我们的神经网络框架不会很快。它唯一的优化是通过 DispatchQueue 的并发执行而不是循环的多线程。

并发执行 vs For 循环。图片作者:Yauheni Stsefankou

该实现由密集层、sigmoid 函数、训练和预测方法组成。

开始吧!

数据集结构

我们必须实现包含我们想要训练的所有样本的数据集。

这是一个数据集模型。

数据集模型。图片作者:Yauheni Stsefankou

注意数据集由数据样本组成。让我们在 Swift 中实现该结构。

我们的第二个观察是数据样本包括输入和输出数据

并且为了方便起见,数据块由一个体和它的大小组成。

数据的大小必须有宽度,可选变量是高度和深度(取决于数据大小的类型)。这就是我们为所有数据大小类型提供初始化器的原因。

数据片可以是 1D、2D 或 3D

神经网络模型类

我们在神经网络中实现了一个数据集系统。现在我们需要创建一个神经网络类。它包括层、学习率、每次训练的次数、每个训练批次的样本数

现在我们需要实现层类。每层包括几个神经元(卷积层除外)和一个针对它们的激活函数。此外,我们将为反向传播保留输出缓存。

每个神经元存储每个突触的权重和偏向。此外,我们保留一个缓存来更新权重,以支持批处理梯度下降类型。有 3 种梯度下降类型:批量、随机和小批量。使用批量小批量梯度下降,在多次传播后更新权重。此外,我们保留 delta 用于反向传播。

神经网络使用许多激活函数如 sigmoid,ReLU 。我们需要将这些激活功能定义为一个协议。每个激活包含传递函数(用于正向传播)和导数函数(用于反向传播)。我们还存储 ID (rawValue)用于枚举函数。

现在,对于该协议,可以创建激活功能的结构。让我们做一个 sigmoid 函数。

乙状结肠功能

来自维基百科的渲染方程

我想你已经看过了 sigmoid 函数的图表。这是:

sigmoid 函数的图形。图片来自 Qef 的维基百科

当我们需要获得输出的概率时,sigmoid 函数是合适的。比如偶数的概率。
sigmoid 导函数是输出和输出与 1 之差的乘积。

我们的 sigmoid 结构包含它的标识符(raw value)传递函数和导数函数

此外,我们需要为我们的函数创建一个 enum 和一个从标识符中获取它们的方法。

层功能

每种类型的层应该有单独的传播。他们在这里:

训练算法

我们需要做的第一件事是将数据集分成批次。我们可以通过改组数据样本,然后将它们分成大小等于首选批量大小的组来实现这一点。

分成几批。图片作者:Yauheni Stsefankou

然后,对于一批中的每个样本,该算法执行向前和向后传播。在批量使用所有样本后,该算法更新所有层的权重。

传播正在执行

前向传播通过突触将神经元的输出发送到下一层。

反向传播 通过使用正向传播缓存传播预测误差,并将其推向输入层。对于第一次传播,样本的期望值用作输入。

增量权重方法计算权重的变化,并将其存储在缓存中。它的工作方式类似于正向传播。

致密层

我们的神经网络中的第一层子类是密集层。我们在部分考虑了密集层的一些理论。这是神经网络最简单的一层。

好的。我们已经初始化了一个密集层,现在我们需要为它编写传播函数。我们使用 DispatchQueue 中的并发执行来代替循环。正向传播通过将每个神经元的权重与传递给它的输入相乘,生成每个神经元的输出。这也增加了结果的偏差。具有结果的最后一个操作是激活传递函数的使用。

反向传播使用正向传播的输出将误差传播到所有神经元。它使用激活导数函数传播误差。多线程在这里不是最优的,所以我们不使用它。

增量权数法正在使用并发执行。在建立神经网络模型时,你应该为学习率找到一个甜蜜的运动。此外,在此方法执行期间,偏差也在更新。

在使用批中的所有项目后,神经网络用传播缓存更新神经元的权重。当然,这里最好使用多线程并发执行。

神经网络的第二个重要功能是预测。为了预测结果,函数接收正向传播结果

使用编写的框架实现神经网络模型

万岁!我们已经实现了我们的神经网络框架的基础,sigmoid 激活和它的密集层。现在我们可以用一个简单的例子来验证这一点。

这个例子的任务是按照奇偶性对一个数进行分类。对于神经网络来说,这是一项不同寻常的任务,但很容易理解。

为了初始化一个新的神经网络模型,我们需要将它写入代码:

之后,我们可以更改模型的一些参数(批量大小、时期数和学习率):

实现神经网络模型时最重要的部分是建立层结构。下面是层结构示例:

之后,我们的模型就可以开始训练了。这一切都始于将数据集输入模型。

我们将输入的数字作为它的二进制数,得到它是偶数的概率。我们数据集中的第一个样本是【0.0,0.0,0.0,1.0】,它的期望值是 0.0 。这意味着输入数字的二进制表示是 0001 。用十进制表示,将是 1 。这是一个奇数。所以我们期望 0.0 (零概率表示数是偶数)。

训练好神经网络之后,就可以开始用它来进行预测了。您可以通过将数据样本输入模型来获得预测。

用 30 个纪元训练的结果。图片作者:Yauheni Stsefankou

结果是 0.45 ,表示答案是 55%概率的 0(奇数)或 45%概率的 1(偶数】

用 1000 个纪元训练的结果。图片作者:Yauheni Stsefankou

当我们将历元数改为 1000 时,训练时间延长了三十倍,但 1111 的均匀度概率变为 3.8% 。这意味着我们的神经网络模型变得更加精确。

模型保存

为了保存模型,我们需要准备好所有的结构和类。它们必须与 JSON 编码的可编码协议兼容。几乎所有的类和结构都只需要在声明中添加可编码协议:

我们将该层实现为一个类,而不是一个结构。该类要求编码和解码方法符合可编码协议。编码和解码方法需要所有变量的密钥。

添加之后,我们必须将解码器中的初始化器添加到我们的密集层中。

我们需要为层写一个包装器,因为层类不是最终的,它可以有子类。它不仅编码层的子类,还编码子类的类型。

写完包装器后,我们需要用自己的方法替换神经网络模型的编码和解码方法。我们对层的包装进行编码,而不是像这样对层进行编码和解码,因为我们需要存储层的类型。

现在我们可以编写一个方法来保存模型。首先,我们必须初始化 JSON 编码器,并使用它来编码模型。然后,我们获取当前应用程序目录的 URL,并将编码数据写入其中。

从文件中读取模型并不比保存它更困难。现在,我们不是初始化 JSON 编码器,而是初始化 JSON 解码器。然后我们从文件中获取数据并用我们的解码器解码。我们需要做的最后一件事是从解码的模型变量初始化模型。

结论

我们已经创建了基本的神经网络框架,现在我们可以添加任何类型的功能和层。这里有一个 git 资源库的链接,里面有所有的源代码和一些额外的功能(丢弃、展*和卷积 2D 层,ReLU 激活):https://github.com/stefjen07/NeuralNetwork

感谢阅读。如果你有任何建议或者你在这篇文章中发现了错误,请在评论中留下你的反馈。我已经准备好改善我的读者的体验。

用于代码搜索的神经查询扩展

原文:https://towardsdatascience.com/neural-query-expansion-for-code-search-3d60ebe8b751?source=collection_archive---------28-----------------------

研究论文摘要

作者图片—修改过的来源

以自由流动的自然语言形式制作一个高效的代码搜索工具是一个有趣且具有挑战性的研究问题。这一领域的早期工作之一是脸书的神经代码搜索(NCS)接受自然语言查询并输出相关代码片段。但本文作者发现,在用户进行简短或模糊查询的情况下,NCS 会偏离其预期性能。因此,作者提出了一个名为神经查询扩展 (NQE)的查询扩展引擎,当它与 NCS 一起使用时,能够比单独使用 NCS 执行得更好。

在研究他们公司的搜索数据库日志时,作者发现较长的查询往往具有较少的查询重构(查询编辑、重新措辞等),这强烈表明了较长查询的 NCS 的有效性。他们还注意到了对比,即短查询导致了大量事件,如滚动、查询重构等,这表明用户无法一次性获得相关结果。因此,像 NQE 这样将查询关键词扩展成相关短语的系统在这种简短的查询情况下会有所帮助。

神经查询扩展—方法

让我们先来谈谈一些符号——

D =语料库(所有源代码), di =文档(一个代码), Vm =词汇 _ M(D 中的所有方法名), Vk =词汇 _MT(在 camelCase 和 snake_case 中标记的所有方法名), X =来自 Vk 的一组关键字 xi, R =文档的排序列表(di)

因此,对于给定的查询 X,系统返回 R,并让 dx 成为预期的基本事实文档。因此,我们定义 rank(dx,R) — ,其中较好的搜索结果简单地由 dx 的数值较低的等级来指示。将排名视为搜索结果中的优先顺序,排名越低,优先级越高。因此,扩展系统的目标是确保具有扩展查询 (E) 的预期文档 dx 的等级应该小于原始查询 (O)

作者提出的 NQE 模型是一个编码器-解码器模型,它在输入端接受一个查询 x,并产生一系列方法名 Y = ⟨y1。。。,ym⟩在那里挨个咦∈ Vm。一旦我们有了方法名序列,他们就应用 camelCase 和 snake_case split 函数来获取扩展查询(Xexp)的关键字。

NQE 管道—图片来自原文

正如你在上面的图中看到的,对于每个输入 X,我们通过一个可训练的嵌入层传递每个关键字 xi,以获得每个关键字的密集表示。我们在列级别对所有嵌入求和,以获得整个 x 的表示。然后,这个思想向量通过一堆水*堆叠的 GRU 单元,并且在每个时间步,它在方法名称上产生一个 softmax 分布,并且这种循环直到产生序列令牌的结尾。作者使用波束搜索生成具有最大似然的序列。它们还利用注意力来动态地识别输入序列中与产生下一个输出令牌相关的重要段。

搜索工具

他们使用他们提出的方法 NQE 与两个流行的搜索工具 NCS 和 BM25。

  • 神经代码搜索(NCS)——它是一种无监督的方法将给定的输入查询与相关代码段进行匹配。他们使用 fasttext 来表示查询中的单词和某个密集语义超空间中的代码片段。其中他们将类名、注释、方法名等视为代码中可能的词法单元,并使用 TF-IDF 加权单词级嵌入*均值来获得整个代码片段的表示。对于查询,他们只是对每个单词表示进行*均。最后,他们使用余弦相似性作为两个向量(查询和代码)接*度的度量
  • BM25这是一种流行的 IR 方法,它使用下面提到的公式计算每个查询词和代码片段之间的得分—

设, d 为代码片段, x 为查询词, TF 为词频, IDF 为逆文档频率, kb 为可调参数,则—

BM25 计算

这创建了一个大小为(d x 词汇 _ 单词)的矩阵,其中单元值为 BM25 分数,给出了每个文档 d 的稀疏表示。对于每个查询向量,我们创建了大小为(1 x 词汇 _ 单词)的查询一个热码表示,并在查询和文档向量之间进行余弦相似性运算,以生成相似性分数。

基线

  • 频繁项集挖掘 这是一种在底层数据集中寻找同现词汇单元的技术,基于下面的公式 计算

FMI 公式

这里,sb 和 se 在时间 T 和 T+1 是同现词。它是两个单词一起出现的频率与 T 时刻单词单独出现的频率的比率。为支持度和置信度设置阈值以避免误报是一种常见的做法。作者使用最小支持值为 3,最小置信度为 0.5。

数据集和实验

作者使用公开可用的 android 相关存储库,共有 308,309 种方法,并执行某些预处理步骤来处理低词汇情况。下一个任务是从数据中创建 X 和 Y 对,以便可以训练编码器-解码器模型。他们从每个方法体中提取 X 和 Y,其中 Y 是文档 d 中方法调用的序列。他们对方法调用进行排序,并通过保留前 50%的 tf-idf 方法来限制它们的选择。然后,他们通过应用诸如标记化、删除停用词等转换,从方法名中提取关键字。下一步是从 y 中提取 X。他们提出了两种方法来实现这一点—

  1. Y 组合的所有关键字中前 75%的 TF-IDF 关键字
  2. 每个 y 的前 1 个 IDF 关键字。

这两种方法都是通过从方法名中选择最有代表性的单词来捕捉潜在意图的代理。

在另一种方法中,他们还雇佣人类从 Y 创造 X 来验证上一段中描述的自动选择程序。

结果

在下面的结果表中可以看出,当查询长度较小时,NCS+NQE 比 NCS 具有更好的*均倒数排序。

Tf-IDF 用于查询选择时的 MRR 结果—图片来自来源

P.S. 我也在为这篇论文做多语种字幕的视频讲解。一旦发布,我会在评论中更新!

2021 年 2 月 15 日更新

视频讲解人

NQE 视频解说

您还可以查看我为同一主题撰写的其他研究论文解释— 伯特-QE:情境化查询扩展

如果你仍然对某件事感到困惑,一定要看报纸。另外,向作者问好,感谢他们的贡献。

论文题目:用于代码搜索的神经查询扩展

论文链接:【https://dl.acm.org/doi/abs/10.1145/3315508.3329975】T22

作者:杰森·刘,徐珠贤·金,维贾亚拉冈·穆拉利,斯瓦拉特·乔杜里,萨迪什·钱德拉

组织:脸书莱斯大学

我希望这本书值得你花时间去读。谢谢大家!

Haystack 神经搜索——语义搜索的极致

原文:https://towardsdatascience.com/neural-search-with-haystack-semantic-search-at-its-finest-5f39d07b992?source=collection_archive---------14-----------------------

一个快速简单的指南,用变形金刚和最少的设置建立你自己的搜索引擎

卢卡·胡特在 Unsplash 上的照片

语义搜索在我们的日常生活中相当常见,尤其是我们使用谷歌作为大多数问题(如果不是所有问题)答案的媒介的次数。直到几年前,在没有大量计算资源的情况下构建一个相当不错的搜索引擎还是一件痛苦的事情。简而言之,这太难了,需要大量的高级 NLP 概念的专业知识。

BERT transformer 模型及其后继者的出现改变了这一点。虽然我们仍然需要一个好的 GPU 来微调这些模型,但一些令人敬畏的库,如 Haystack 现在已经可以非常容易地围绕我们选择的数据集构建生产就绪的应用程序。

在本文中,我将展示如何从公开可用的数据集(例如 Kaggle)中快速构建自己的定制搜索引擎。

我们开始吧!👇

但首先,干草堆到底是什么?

简而言之,它是一个非常棒的库,可以用来构建生产就绪的、可伸缩的搜索系统和问题回答系统。

它利用了最新的 transformer 模型,因此对研究人员和开发人员来说都是最好的 NLP 工具包之一。

它提供了用于构建此类系统的不同组件,这些组件非常易于学习和实验。我将在本文中讨论其中一些,希望能给你一个好的起点!

获取数据集

我们将使用来自 Kaggle 的数据集的子集。它包含大约 170 万篇来自 STEM 的 arxiv 研究论文,每篇论文都有不同的特征,如摘要、作者、发表日期、标题等。它是 json 格式的,我编译了一个更小的版本。

在我的 GitHub repo 上的这里有更小的版本。继续将 arxiv_short.csv 下载到您的机器上。

为了简单起见,我确保只保留 50,000 个文档和三列:

  • 作者 —论文的作者
  • 摘要 —论文摘要
  • 标题 —论文标题

和熊猫一起读:

import pandas as pddf = pd.read_csv('arxiv_short.csv')
df.head()

我们来看看数据:

arxiv 数据集标题行

我们现在准备设置我们的 haystack 引擎。

安装干草堆

这一步只需要两行代码。首先确保你处于虚拟环境中。

pip install git+https://github.com/deepset-ai/haystack.gitpip install sentence-transformers

我们将使用 haystack 构建实际的搜索引擎,并使用句子转换器从我们的 摘要 文本列创建句子嵌入,我们的搜索引擎将基于该文本列。

现在,让我们继续为我们的 haystack 搜索引擎构建不同的组件!

初始化文档存储和检索器

一个文档存储库存储我们的可搜索文本及其元数据。

例如,这里我们的文本将是来自数据集的抽象列,其余两列— 标题作者 —将由我们的元数据组成。

初始化和构建相当简单:

document_store_faiss = FAISSDocumentStore(faiss_index_factory_str="Flat", return_embedding=True)

FAISS 是一个用于高效相似性搜索和密集向量聚类的库,因为它不需要额外的设置,所以我更喜欢在这里使用它而不是 Elasticsearch。

现在猎犬来了。

一个检索器是一个过滤器,它可以快速遍历整个文档库,并根据对给定查询相似性搜索,从中找出一组候选文档。

其核心是,我们正在构建一个语义搜索系统,因此从查询中获取相关文档是我们项目的核心。

初始化一个检索器也很简单:

retriever_faiss = EmbeddingRetriever(document_store_faiss, embedding_model='distilroberta-base-msmarco-v2',model_format='sentence_transformers')

在这里,distilloberta仅仅是一个 transformer 模型 BERT 模型的变体——我们在这里使用它来为我们的文本进行嵌入。它作为句子变形金刚套装的一部分提供。

现在,我们想将文档写入我们的文档存储。

构建文档存储

我们只需将数据帧的列传递给文档存储。

document_store_faiss.delete_all_documents() # a precaution document_store_faiss.write_documents(df[['authors', 'title', 'abstract']].rename(columns={ 'title':'name','author' : 'author','abstract':'text'}).to_dict(orient='records'))

这里需要进行一点重命名,因为 haystack 希望我们的文档以这种格式编写:

{ 'text': DOCUMENT_TEXT, 'meta': {'name': DOCUMENT_NAME, ...}     }, ... and so on.

最后,在构建完成后,我们将文档存储提供给我们的检索器。

document_store_faiss.update_embeddings(retriever=retriever_faiss)

数据集越大,这两个步骤需要的时间就越长。

我们快完成了!剩下唯一要做的就是创建一个函数来检索与查询匹配的文档!

总结——获取结果并尝试

我们定义了一个简单的函数来从我们的数据中获取 10 个相关的文档(研究论文摘要)。

def get_results(query, retriever, n_res = 10): return [(item.text, item.to_dict()['meta']) for item in    retriever.retrieve(q, top_k = n_res)]

最后我们测试一下!

query = 'Poisson Dirichlet distribution with two-parameters' print('Results: ')res = get_results(query, retriever_faiss)for r in res:
    print(r)

您可以看到这样的结果:

搜索结果

这就是你要的——一个建立在你选择的数据集上的定制语义搜索引擎!

去玩吧!调整一些参数—例如,尝试更改检索器对象中的转换器模型。

完整的代码也可以在这里的笔记本上找到:

https://github.com/yashprakash13/haystack-search-engine

感谢阅读!😃

独自学习数据科学可能会很难,跟我来,让我们一起让它变得有趣。保证。😎

此外,这里是我所有数据科学故事的代码库。快乐学习!⭐️

这是我的另一篇文章,你可能想读一读:

neur IPS 2021——你不应错过的 10 篇论文

原文:https://towardsdatascience.com/neurips-2021-10-papers-you-shouldnt-miss-80f9c0793a3a?source=collection_archive---------0-----------------------

2334 篇论文,60 场研讨会,8 位主题演讲人,15,000 多名与会者。如果没有一个好的向导和地图,很难找到一个密集的景观,所以这里有一些我们的想法!

使用 Zeta Alpha 创建的图像。

人工智能领域最受欢迎的会议 2021 年版将在这里以“压轴大戏”结束这一年。会议的增长并没有停止:去年的会议————我们也回顾了——有 1899 篇主流论文被接受,相比之下,今年的只有 2334 篇。

NeurIPS 过去十年主要领域的出版物数量。

一些发表的论文已经在 arxiv.org 发表了一段时间,并且已经产生了影响。例如,这里有一份甚至在会议开始前就被引用最多的 10 篇 NeurIPS 论文的列表。这是浏览程序和观看作者展示作品的第一个好的起点。

理解这一令人印象深刻的阵容并不容易,但在人工智能研究导航员Zeta Alpha 的帮助下,我们通过引用最相关的 NeurIPS 论文、spotlight 演示和来自*台的一些建议,确定了一些我们想要强调的酷作品;有些已经众所周知,有些更多的是一颗隐藏的宝石。当然,这些精选并不旨在成为一个全面的概述——我们将错过许多主题,如 ML 理论,联合学习,元学习,公*——但我们只能在一篇博客帖子中容纳这么多!

更新 12 月 1 日:现在最佳论文奖已经揭晓,这也是一个很好的起点,虽然对我们的口味来说理论有点重。

1。用于基于结构的药物设计的 3D 生成模型 |👾代码

作者:罗世同,关,马建柱,。

❓WhyBio ML 已经成为机器学习技术应用和进步最显著的领域之一。这是一个最*的例子,说明如何在基于蛋白质结合的药物设计中使用生成模型。

💡关键见解 →掩蔽语言建模(通过掩蔽一些元素破坏一个序列并试图重建它)的想法被证明对生成分子也是有用的:掩蔽单个原子并“重建”它们应该如何被填充。通过迭代地进行该过程(例如“自回归”),这变成了可以输出候选分子的生成模型。

相对于以前的工作,这篇论文的主要进展是分子的产生取决于特定的蛋白质结合位点,为研究人员提供了一种更好的机制来寻找候选分子,以作为特定目的的药物。

来源:https://papers . nips . cc/paper/2021/file/314450613369 E0 ee 72d a7 f 6 fee 773 c-paper . pdf

为此,训练需要几个技巧,例如建立一个对刚性变换(*移和旋转)不变的编码器,因为分子不关心它们如何取向。这些结果并不是突破性的,该方法仍然存在一些问题,例如它经常可以输出物理上不可能的分子,但这一研究方向对于未来的药物开发来说肯定是有前途的

来源:https://papers . nips . cc/paper/2021/file/314450613369 E0 ee 72d 0 da 7 f 6 fee 773 c-paper . pdf

neur IPS 针对分子结构的 ML 的其他工作: 蛋白质的多尺度表示学习利用探索性 RL 和基于片段的分子生成的 Hit 和 Lead 发现用于非迭代多样性候选生成的基于流网络的生成模型

2。对象的出现:从视频中学习零镜头分割👾代号

刘润涛、、余、林。

作者的 TL;DR → 我们提出了一个适用的零镜头模型,通过从未标记的视频中学习来进行对象分割。

❓Why → 人类可以很容易地追踪我们从未见过也不认识的物体……机器也应该这样做!

💡关键见解→客体性的概念通常被认为是人类重要的先验知识之一,它使我们能够看到并推理我们所看到的东西。这里的关键是,我们不需要知道对象是什么,就知道它是一个对象。相反,当以监督方式训练用于图像分割的神经网络时,模型将仅学习分割在训练期间看到的对象。

本文建议使用视频数据和巧妙的技巧来建立一种自我监督的训练方法,这种方法利用了对象和前景在记录中的不同行为。这让人想起了脸书的《迪诺》[1],该书揭示了在用图像进行自我监督训练后,变形金刚的注意力矩阵类似于某种原始分割。

在这种情况下,作者使用单帧重建损失(分割网络)和运动网络的组合,试图输出像素在图像中如何移动的特征图。这使得他们可以在给定重建和运动图的情况下预测未来的帧,这是端到端的自我监督。

来源:https://papers . nips . cc/paper/2021/file/6d 9 CB 7 de 5 e 8 AC 30 BD 5 e 8734 BC 96 a 35 c 1-paper . pdf

要做到这一点,需要更多的技巧和考虑,结果仍然不是惊天动地的。尽管如此,利用视频将未标记的数据用于计算机视觉是机器学习未来的一个关键发展,因此这一系列工作必将产生影响。

neur IPS 的其他有趣的计算机视觉论文: 用专家的稀疏混合来缩放视觉 ( 我们几个月前已经报道过了! ) 关注 MLPs(6 月还盖回来了)视觉变形金刚的耐人寻味属性压缩视频对比学习

3。使用冻结语言模型进行多模式少量学习 |🌐网站

作者:Maria Tsimpoukelli、Jacob Menick、Serkan Cabi、S. M. Ali Eslami、Oriol Vinyals、Felix Hill。

作者的 TL;博士→ 我们提出了一个简单的方法,将冻结的语言模型的能力转移到多模态设置(视觉和语言)中。

❓Why →提示已经存在:现在是多模式和异步。您能否利用预训练语言模型中的信息来完成视觉任务,而无需重新训练?嗯,有点…继续读。

💡关键见解 →本文提出的想法相当简单:训练一个语言模型,冻结它使其参数保持固定,然后训练一个图像编码器将图像编码成该语言模型执行特定任务的提示。我喜欢将其概念化为“为模型学习一个图像条件提示(通过神经网络的图像)来执行任务”。

来源:https://papers . nips . cc/paper/2021/file/01b 7575 c 38 DAC 42 F3 CFB 7d 500438 b 875-paper . pdf

这是一个很有前途的研究方向,但结果并不令人印象深刻?)就绝对性能而言。然而,比较使用多模态数据完全微调的模型(冻结微调)和保持语言模型冻结的模型(冻结 VQA 盲)是有趣的:只有后者显示出从训练数据集(概念标题4)到目标评估数据集(VQAv2 [5])的良好概括,仍然远离完全监督的模型。

来源:https://papers . nips . cc/paper/2021/file/01b 7575 c 38 DAC 42 F3 CFB 7d 500438 b 875-paper . pdf

4.利用负缓存高效训练检索模型

作者:埃里克·林格伦、萨尚克·雷迪、郭瑞琪和桑基夫·库马尔。

作者的 TL;DR → 我们开发了一个流式负缓存,用于高效训练检索模型。

密集检索中的❓Why → 负采样是神经信息检索领域中最重要的课题之一!这似乎是重要的一步。

💡关键见解→ 密集检索模型旨在将段落和查询编码成向量,以执行最*邻搜索来找到相关匹配。对于训练,经常使用对比损失,其中正对的相似性最大化,负对的相似性最小化。理想情况下,可以使用整个文档集作为“负样本”,但这将非常昂贵,因此通常使用负样本技术。

负采样技术的挑战之一是最终的模型质量在很大程度上取决于使用多少负样本-越多越好-但是使用许多负样本在计算上非常昂贵。这导致了一些流行的建议,如 ANCE 2,其中负样本与来自异步更新指数的“硬负样本”小心地混合,以合理的计算成本改善模型性能。

在这项工作中,作者提出了一个优雅的解决方案,包括在计算时缓存文档的嵌入,并只渐进地更新它们,因此不需要在编码器中对所有负样本执行完整的前向传递,而是使用大部分缓存的文档,这要快得多。

这导致了一个更优雅和简单的方法,在经验上优于现有的方法。

来源:https://papers . nips . cc/paper/2021/file/2175 F8 C5 CD 9604 F6 B1 e 576 b 252d 4c 86 e-paper . pdf

neur IPS 上你可能喜欢的其他信息检索论文: 面向开放领域问答的多文档阅读器和检索器端到端培训跨语言密集段落检索的多语种一个问答模型SPANN:高效亿级*似最*邻搜索

5。VATT:从原始视频、音频和文本进行多模式自我监督学习的变形金刚

作者:Hassan Akbari、梁哲元、芮倩、庄伟红、张世福、尹翠和龚柏青。

作者的 TL;DR → 一个纯基于 Transformer 的管道,用于在没有监督的情况下从原始视频、音频和文本中学习语义表示。

❓Why → 迈向多模式未来之地的又一步。

💡关键见解→ 大型变压器模型仍未开发的领域是多模态。这项工作旨在通过联合使用对比损失的变体对视频、音频和文本模态中的数据进行自我监督学习来构建这些模态的表示,因此这三种模态驻留在同一嵌入空间中。为此,他们使用噪声对比估计(NCE)并将匹配的音频/视频帧/文本三元组用作正样本对,将不匹配的三元组(例如,视频的非对应片段)用作负样本。

这种方法类似于以前的多模式网络,如“自监督多模式通用网络”[3],主要区别在于它依赖于纯变压器架构。它在主要视频基准动力学中实现了 SOTA,同时避免了监督预训练(例如,使用大规模 Imagenet 标签来预训练模型),并且仅使用自监督技术。

来源:https://papers . nips . cc/paper/2021/file/CB 3213 ada 48302953 cb0f 166464 ab 356-paper . pdf

6。鲁棒可预测控制 | 🌐网站

本·艾森巴赫、拉斯·r·萨拉胡季诺夫和谢尔盖·莱文。

作者的 TL;DR → 我们提出了一种利用压缩思想在 RL 中学习健壮且可预测的策略的方法。

❓Why → 优秀的鸟瞰论文,通过压缩的镜头来理解强化学习的一些基本挑战。

💡关键见解→ 尽管环境观察通常是高维的(例如,来自图像的数百万像素),但代理做出决策所需的信息量通常很少(例如,使用摄像机传感来保持汽车的车道)。根据这一观点,作者提出了鲁棒可预测控制(RPC),这是一种使用少量信息学习策略的通用方法。

为了做到这一点,他们的分析基于信息论的角度,即一个模型需要多少信息来预测未来状态:一个状态越可预测,政策就越容易被压缩。这成为代理人学习大部分时间“安全行事”的一个规范化因素(例如,自动驾驶系统将倾向于避免高度不确定的情况)。

来源:https://papers . nips . cc/paper/2021/file/e9f 85782949743 DCC 42079 e 629332 b5f-paper . pdf

算法的细节要复杂得多,所以如果你想深入研究,你需要仔细阅读这篇论文。除了特定的实现和良好的经验结果之外,这似乎是一个有用的视角,可以用来思考在不确定的环境中进行权衡的问题。

更多关于 NeurIPS 的强化学习:来自虚空的行为:无监督的主动预训练语义空间中的涌现离散通信通过双方差缩减的*优离线强化学习

7 .。FLEX:少数镜头 NLP 的统一评估📈排行榜 |👾代号

乔纳森·布拉格、阿尔曼·科汉、凯尔·罗和伊兹·贝尔塔吉。

作者的 TL;DR → FLEX 原则、基准和排行榜统一了评估少数镜头 NLP 的最佳实践;UniFew 是一个简单而强大的基于提示的模型,它统一了预培训和下游任务格式。

❓Why → 少量学习成为 NLP 酷小子已经有一段时间了。是时候让它有自己的基准了!

💡关键见解→ 自从 GPT-3 4在 2020 年 5 月凭借“提示”在 NLP 任务中令人惊讶的零镜头和少镜头性能打入市场以来,新的大型语言模型在零镜头/少镜头设置中对自己进行基准测试已经成为标准。通常,相同的任务和数据集用于微调的模型,但是在这个基准测试中,零/少数镜头设置是一等公民。

来自艾伦人工智能研究所的这个基准寻求标准化在 NLP 少数镜头文献中看到的模式,例如这个基准建立的原则是:传输类型的多样性、镜头和类别的可变数量、不*衡的训练集、文本标签、没有额外的元测试数据、有原则的样本大小设计和置信区间、标准偏差和个体结果的正确报告。希望这将有助于大型语言模型之间的比较,当评估实践有点无处不在时,这是无法保证的:魔鬼在细节中!

作者还开源了用于创建基准的 Python 工具包,以及他们自己的基准 UniFew,并将其与最*流行的方法“使预训练的语言模型成为更好的少量学习者”[5]和“具有分布签名的少量文本分类”6进行了比较。

来源:https://papers . nips . cc/paper/2021/file/8493 eeaccb 772 c 0878 f 99d 60 a 0 BD 2 bb 3-paper . pdf

你可能会在 NeurIPS 上喜欢的其他 NLP 论文: COCO-LM:为语言模型预训练纠正和对比文本序列

8。分区和代码:学习如何压缩图形

圣乔治·布里萨斯,安德里亚斯·洛卡斯,尼古拉·卡拉利亚斯,迈克尔·布朗斯坦。

作者的 TL;DR → 我们介绍了一个灵活的端到端机器学习框架,用于基于图划分、字典学习和熵编码的无损图压缩

❓Why → 压缩常规数据(即像 1 和 0 这样的符号序列)自香农在 1948 年引入信息论以来已经得到了广泛的研究,然而,压缩图形具有不同的特性,却不太为人所知。这里有一个关于如何从基本原理压缩图形的研究。

💡关键见解→ 设计图形压缩算法时需要考虑 3 个特性:

  • 图同构:与数据序列或数组不同,图没有固有的顶点排序,因此图的最佳压缩码字表示应该对这种同构不变。
  • 评估图形的似然性:理论上最佳的编码器依赖于知道每个可能的数据配置的似然性,并分配一个代码,该代码的规模与这种似然性的对数成比例(例如,更可能的图形被压缩成更短的代码,反之亦然)。由于中大型图表的组合爆炸,计算这种可能性通常是困难的!问题需要分解…
  • 如果构建一个复杂的模型来估计图形的可能性并基于此进行压缩,那么这个模型本身的大小就需要考虑在内!一般来说,模型越复杂,压缩数据的能力就越强,但是数据也会越大,因此在存储模型花费多少位和存储每个压缩图实例花费多少位之间会产生权衡。

虽然作者没有声称提出一个最佳解决方案,但他们提出了一个实际的解决方案,大致如下:将图划分为公共子图,为这些子图保留一个码字字典,其长度与每个子图可能性的对数成比例。该方法是完全可微的,因此它可以用梯度下降对任何给定的图形数据集进行优化。

来源:https://papers . nips . cc/paper/2021/file/9 a4d 6 e 8685 BD 057 E4 f 68930 BD 7 c8 ECC 0-paper . pdf

当与现有方法进行经验比较时,它优于现有方法,但是考虑到引入的复杂性,它将在多大程度上被使用仍然是一个开放的问题。不管他们的具体提议如何,这是一篇理解如何从头开始压缩事物的优秀论文。

来源:https://papers . nips . cc/paper/2021/file/9 a4d 6 e 8685 BD 057 E4 f 68930 BD 7 c8 ECC 0-paper . pdf

neur IPS的其他有趣的图形神经网络论文: SIMONe:通过无监督视频分解实现视图不变、时间抽象的对象表示VQ-GNN:使用矢量量化放大图形神经网络的通用框架GemNet:分子的通用方向图神经网络

9。学习绘画:通过素描进行紧急交流 |👾代码

丹妮拉·米哈伊和黄邦贤·黑尔。

作者的 TL;DR → 我们使用自我监督游戏来训练人工智能体通过绘画进行交流,然后证明在适当的诱导偏差下,人类可以成功地与预训练的绘画智能体玩同样的游戏。

❓Why → 这个很有趣。

💡关键见解→ 两个模型学习通过绘画交流图像:发送者模型需要使用输出“笔画”的可微分光栅化器来创建图像的描述,而接收者模型需要从图像池中挑选出发送者代表的图像。

来源:https://papers . nips . cc/paper/2021/file/39 d0a 8908 FBE 6 c 18039 ea 8227 f 827023-paper . pdf

一个有趣的观察是,在没有进一步限制的情况下,发送者和接收者如何想出人类无法解释的绘图表示。但他们尝试了一个聪明的正则化技巧来激励人类的可解释性:在早期视觉阶段(即编码器模型的早期层)添加一个“感知损失”,以便原始图像和绘画在模型中的激活彼此相似。这是受经验观察的启发,即对于一幅给定的图片和一幅画,人类的神经元激活是相似的。

来源:https://papers . nips . cc/paper/2021/file/39 d0a 8908 FBE 6 c 18039 ea 8227 f 827023-paper . pdf

10。失败的修复:机器学习系统中弄巧成拙的改进

作者:韩瑞·吴、、奥尼·汉南和劳伦斯·范德马腾。

作者的 TL;DR → 我们一般孤立地研究机器学习模型。但是 AI 系统由许多机器学习模型组成。改进一个模型会使系统变得更糟吗?是的。

❓Why → 组成人工智能系统的模块可以以复杂而不直观的方式进行交互。这篇发人深省的论文研究了如何使系统的子部分变得更好会使整个系统变得更差。

💡关键见解→ 虽然本文没有提出任何特别令人印象深刻的方法,但这是一个有趣的思想食粮,可以一直记在脑海里。作者研究并形式化了一个重要的问题,即由各种 ML 子系统组成的系统在单个部分得到改进时如何以及为什么会变得更差。这在实际领域非常重要,因为许多人工智能系统都是由。

来源:https://papers . nips . cc/paper/2021/file/619427579 e7b 067421 f 6a aa 89 D4 a 8990 c-paper . pdf

理论分析要比这深入得多,但它的主要要旨是,您可能真的可以通过改进人工智能系统的每个部分来降低其性能,所以在重新训练一个 ML 管道组件之前请三思!

我们的选择到此结束。不幸的是,我们不能包括许多绝对值得强调的有趣的作品,所以你需要进入会议论文的完整列表来找到它们。例如,你可能想看看最新的施密德胡伯的元学习反向传播和改进它,或者 resnet 不是死的重温 resnet:改进的训练和扩展策略,或者最新的等变 NN E(n)等变规格化流?出于对你时间的尊重,我们只能到此为止了。我们希望你喜欢它,你可以在我们的*台上继续探索这个会议。

您还可以参加我们即将于 12 月 3 日(星期五)举行的网络研讨会,届时我和我的同事将讨论今年的会议。该团队将通过我们公司的 Twitter feed 在 @zetavector 现场报道有趣的见解,所以如果你不想错过任何事情,请收听。你呢?你对大会最期待的是什么?欢迎在评论中分享一些建议👇

参考文献

[1]“自监督视觉变压器中的新兴特性”,Mathilde Caron 等人,2021 年。

【2】《面向密集文本检索的*似最*邻否定对比学习》李熊等 2020。

[3]“自我监督的多模式通用网络”,让·巴普蒂斯特·阿拉亚克等人,2020 年。

【4】《语言模型是很少出手的学习者》Tom B. Brown 等人 2020。

[5]“让预先训练好的语言模型成为更好的少投学习者”高天宇,亚当·菲舍尔,陈,2021。

6“基于分布式签名的少镜头文本分类”鲍、吴、常、雷吉娜巴兹莱,2019。

NeurIPS 会议:历史数据分析

原文:https://towardsdatascience.com/neurips-conference-historical-data-analysis-e45f7641d232?source=collection_archive---------9-----------------------

分析从 1987 年到 2020 年的会议趋势。

闭幕式 NIPS 2017 |作者图片

会议通常提供特定年份的统计数据,呈现关于接受率、多样性、地理和主题分布等信息。通常情况下,这种情况只发生在那一年,或者几年前。

然而,为了看到一些趋势并获得潜在的有用的见解,退一步看看全局可能是值得的。

数据源

在这篇博客中,我将重点关注 NeurIPS 会议数据。自 1987 年第一次举办以来,所有会议实例中被接受的论文都可以在https://papers.nips.cc/上公开获得。从被拒绝的论文中会有额外的见解,但不幸的是这些是不可用的。我还要感谢 NeurIPS 组织者维护这个数据库,并允许下载和使用这些数据进行分析。

每篇论文始终可用的信息是:标题作者。对于某些年份,以下元数据也是可用的:摘要全文作者隶属关系评论补充材料

除此之外,我尝试了某些方法来提取更多关于论文、作者及其机构的数据,这些数据在主网站上是无法直接获得的。我用来获取数据和生成图表的所有源代码都可以在 my GitHub 上找到。(所有图片由作者提供)

分析

纸质统计

先从录取论文总数说起。由于没有提交的总数,我们无法监测接受率。然而,*年来被接受的论文数量急剧增加:

在第一次会议上,1987 年,共有 90 篇论文被接受,而 2020 年这个数字是 1898 篇 T21。历年被录取论文总数为 11578

如果我们(过度)拟合这个数据的多项式曲线,我们可以为 2021 年打个赌:

再来看纸质标题,*均标题长度略有下降:

虽然在标题中使用缩写又开始流行了:

以字数衡量的摘要长度一直在稳步增长(变化显示为垂直黑线)。然而,在 2007 年之前,抽象数据并不总是可用的,因此没有该时期的信息:

我最喜欢的情节之一(也是我开始这个分析的原因)是补充材料。自 2007 年以来,包含某种形式的补充材料的论文数量。pdf 或。zip)开始增长,如今几乎达到了 100%。

研究趋势

根据标题中出现的关键词粗略估计一些研究趋势就好了。通过查看标题中出现最频繁的关键词,可以发现有趣的见解,根据每年被接受的论文数量进行标准化。

前 5 个双词关键词的频率显示了短语(蓝色条)流行的两个时期——大约在 2000 年之前和 2010 年。中间的时期显示了统计 ML 术语的增加,如 支持向量 (绿色)和 高斯过程 (红色)强化学习 (橙色),自 90 年代以来一直被提及,在 90 年代末和 2016 年之后出现了更大的峰值。

聚焦 top 6,三字短语,与上图类似,有两个截然不同的“神经网络”集群: 人工神经网络 (红色)和 深度神经网络 (绿色),中间有 支持向量机 (蓝色)。此外,我们还可以注意到在深度学习革命之后,从 2010 年中期开始, 递归神经网络 (橙色)的提及再次出现。

作者统计

关于作者信息,快速免责声明,数据中的给定名称存在一些不一致,因为它们有时会被缩写(例如,“j .”、“Josh”、“Joshua”)。尽管由于大量的作者,很难手动修复所有这样的实例,但是我们仍然可以从手头的数据中获得足够好的估计,以便执行分析。

每年参与的独立作者总数如下所示,与被接受的论文数量密切相关:

或者更有趣的是,根据当时的实际世界人口进行标准化:

第一年有 166 位作者参加,而在上一届会议中有 5917 位作者,总共有 17670 位参与者参加了 34 次会议。

拥有最多被接受论文的前 50 位出版作者:

为了调查论文在作者中分布的实际不*等,我们可以估计基尼系数。下图中的蓝色部分显示的是累计的出版物数量,一旦我们按照作者的出版物数量对他们进行排序。如果每个作者有相同数量的出版物,蓝色区域也会覆盖橙色区域(这将是理想的*均分布)。所以,比值:(橙色面积)/(橙色+蓝色面积)就给了我们基尼系数。值为 0 表示完全*等(没有橙色区域),而值接* 1 表示完全不*等(所有论文几乎都由一个作者发表)。

虽然作者多样性是一个重要的方面,但诸如作者性别多样性的信息无法从 NeurIPS 论文网站获得。使用一个 python 库可以得到一个非常粗略的估计,这个库是基于比较作者的名字和一个名字数据库(然而大多数是“西方”名字)。“未知”标签大多被分配给非西方名字,或者作者的名字被缩写的情况。

下面的图表显示了每个作者群发表的所有论文和最后作者论文的比例。最后一个作者通常是更资深的学者,比如组长或主管。

在这两张图表中,我们可以看到女性和男性之间的差距仍然很大。

如果我们认为“未知”的标签主要是分配给非西方的名字,这一标签最*的增加可能与*年来更多的非西方作者参加会议有关。然而,当查看论文的最后作者时,这种增加是缓慢的。

“博士”作者统计

接下来,我感兴趣的是估计这些年来博士生发表的论文数量。即使没有可靠的方法来估计博士生的数量和哪些作者是博士生,我们可以做的是检查每个作者在本次会议上首次发表论文后的前 5 年内发表了多少篇论文。

无论是论文总量还是第一作者论文都大多不变,略有上升趋势。

**

机构统计

更有趣的见解来自作者的机构关系,以及他们多年来的参与。自 2013 年第一次提到作者关系的会议以来,共有 2672 个机构参与。

免责声明:

  • 2013 年之前没有附属机构的信息。
  • 实际的机构名称有时不一致(例如,“哈佛大学”(小错别字)、“哈佛大学”、“哈佛学院”、“哈佛”、“哈佛医学院”、“哈佛/麻省理工学院”等),这可能会导致最终分析中的一些不准确之处。然而,即使这些例子被算作独立的机构,我们仍然可以得到足够好的分析估计。

论文数量最多的前 50 家出版机构:

与之前类似,下面的估计基尼系数显示了机构间论文分布的不*等。在这种情况下,系数值 0.68 表示比单个作者高得多的不*等。

协作统计

合作指标的代表,可以通过每篇论文的*均作者数量获得。这个数字一直在稳步增长,这可能意味着更复杂的研究项目的发表,更开放的合作,等等。

仅就单作者论文而言,这一趋势已经明显下降:

而每篇论文的机构数量没有显著变化:(变化显示为垂直黑线)

资金统计

另一个有趣的观察是机构所在国家的 GDP 与来自这些国家的被接受的论文总数之间的关系。论文元数据中不包含国家信息,需要根据机构名称进行推断(通过抓取维基百科,成功有限)。每个国家的 GDP 数据可以从世界银行获得。

了解一个国家的国内生产总值如何与可用的研究资金相关联,以及随后是否与被接受的论文数量相关联,将是有趣的。

上面的图表显示了一个国家的 GDP 和该国机构接受的论文总数之间的相关性,包括标准图和对数图,其中美国明显领先。

最后的想法

我希望这些图表是信息丰富的,或者至少是有趣的,因为一些结果可能是预期的,而另一些则不是。我很乐意得到反馈和对我可能错过的分析的想法,这将是有见地的。

有趣的见解也可以通过查看这些年的*均引用次数来获得,这是我推迟到未来的任务(因为谷歌学术 API 是有限的),或者是否有人愿意为做贡献。

承认

我要感谢 Robert Walecki、Linh Tran、Arash Tavakoli 和 Suzana Ili 的有益讨论和评论,它们帮助我形成了我的第一篇博文!

神经拱门:人工智能的建筑意象

原文:https://towardsdatascience.com/neuroarch-ai-imagery-eng-1b9e1d11944a?source=collection_archive---------26-----------------------

GAN 网络的思想与实际应用[ 俄文版

NeuroArch 生成的图片 @aitectus ,图片作者

今天,我们正在目睹生活各个方面的数字化转型,也就是向信息社会的范式转变。正如我在我的 计划文章 中所写的,这为我们提供了一个全新的工具包,让我们重新思考现有的实践,并发明与新兴技术和概念合作的新方法。

然而,技术的未来向我们提出了关于人类的可能性和局限性的问题,包括伦理和人道主义问题。
许多思想家都在质疑人类与人工智能(AI)和虚拟世界的互动:“智能从蛋白质迁移到沙子(蛋白 VS 硅)”【Efim ostrov sky】

机器学习和人工智能的爆炸式增长和渗透也影响着创造力的原则。如果早期的人工智能仅限于分类和回归任务,那么现在生成算法开始用于创建各种性质的对象和作品,以前只有人类才能使用。艺术成为技术的一部分,而技术成为艺术。在这篇文章中,我将试图涵盖更多的伦理问题,而不是技术问题。

NeuroArch 生成的图片,图片由作者提供

在数字媒体时代,视觉再现已经成为一个物体的主要品质,它的数字图像。这种现象的背后是一致性,因为图像变得彼此相似,这是由于相似的技术和陈词滥调被用于创建它们。视觉信息的丰富导致了它的统一化和贬值。

NeuroArch 研究项目的想法是,首先,探索基于现有图像生成新图像的可能性,其次,探索将生成机器学习应用于创造性任务和设计的方法,最后,给出视觉文化的批判性评估:
如果算法能够生成新图像,类似于不可分辨的程度,难道不应该委托人工智能来创建它们吗

如你所知, GAN 网络的本质是“生成器”算法逐渐学会以这样一种方式创建图像,即“评论家”算法无法区分真实图像和生成的图像。因此,您可以基于现有数组创建新的图像,就像它在同一个集合中一样。此外,可以通过改变其属性来控制所生成图像的参数。

我从 Archdaily、一些面向建筑的 Instagram 账号等热门资源中收集了约 6000+现代建筑实例的训练样本;其中既有图像也有照片。作为一个生成算法,使用了 WP-GAN 神经网络的架构,来自知识库大卫·福斯特的书【生成机器学习】,用于生成人脸。你会在书中找到各种 GAN 算法更详细的描述。

建筑师兼设计师迈克尔·汉斯迈尔将生成式设计定义为“思考的不是设计对象——而是生成对象的过程。”设计师的方法变得更像是编程一种算法,它定义了创作过程的框架。

最后,我们得到的不是一个特定的对象,而是一个经过训练的算法或模型,能够生成任意数量的新对象。

NeuroArch 随机样本,图片由作者提供

对样本进行数千次分析(在 NeuroArch 110,000 个学习时期中),神经网络算法学习从样本中提取特征,形成所谓的特征空间,其中特征被分组为模型参数。这些特征然后被用于合成新的图像。特征的空间不是离散的,而是连续的;它不包含单独的图案,因此两个图像之间的*滑过渡是可能的。

因此,GAN 网络能够展示其生成新图像的能力。当然,我们说的不是一个细节图,而是一种印象或者建筑幻想,这种印象或者建筑幻想以前并不存在,而是由很多真实的原型编织而成。可以假定,生成的图像具有一种特殊的美学,这种美学使它们与诸如立体主义或表现主义等抽象艺术趋势的作品相关联。

neuro arch image VSGelmeroda IX,作者利奥尼·法宁格(公共领域,s 来源:wikiart.org)

问题仍然是,作为一种创造活动的创造力和技术计算之间的界限在哪里。正如量子物理学中的纠缠原理一样,当几个物体的量子态相互依赖时,人或算法的作用很难从结果中分离出来。我相信我们正在处理一种新型的人和机器的合成,这需要对方法论的仔细理解和发展。

目前,我们可以说我们获得了一个强大的工具包,能够分析和归纳人类无法访问的大型数据阵列。使用它,你可以更深入地洞察事物的本质,分析事物,合成新的事物。我期望设计和艺术将获得新的发展动力,丰富它们的手段和方法。

神经弓视频[ 更多 ],图片由作者提供

【出版物及图文资料作者】roma.kuchukov@gmail.com 【脸书:https://www.facebook.com/ICARurbs

NeutonAI:介绍一个非常有效的无代码自动化*台

原文:https://towardsdatascience.com/neutonai-introducing-a-remarkably-effective-no-code-automl-platform-454ca935f708?source=collection_archive---------22-----------------------

是的,现在连你奶奶都能建立机器学习模型了

Unsplash 上由 Samia Liamani 拍摄的照片

免责声明 :这不是一篇赞助文章。我和内乌顿或它的创造者没有任何关系。这篇文章公正地概述了 AutoML 解决方案,旨在使数据科学工具能够为更多人所用。

好像每天都有新的孩子来到汽车街区。 NeutonAI 是这样一个孩子,如果三次点击就能让你达到 90%的目标,你会想为什么要花数年时间学习数据科学。90%对我们大多数人来说已经足够了。

书呆子警报: NeutonAI 有一个获得专利的神经网络框架,其工作原理与 TensorFlow 完全不同。创造者宣称它的独特特征使内乌顿区别于其他 AutoML 解决方案,因为它们大多数使用众所周知的算法。你可以在这里了解更多信息

今天您将看到这个 AutoML 解决方案提供了什么。只需点击几下鼠标,您就可以在*台上构建和评估您的第一个机器学习模型——不需要任何先验知识。

这篇文章的结构如下:

  • NeutonAI 入门—注册和设置
  • 创建新的 AutoML 项目
  • 用 NeutonAI 训练机器学习模型
  • 评估机器学习模型
  • 做预测

NeutonAI 入门—注册和设置

在建立机器学习模型之前,你必须在内乌顿和谷歌云上设置一个账户。这一节描述了这个过程,但是如果你遇到困难,可以随时查看他们的官方入门文档

你会想去他们网站上的 免费试用内乌顿的 页面。它看起来应该有点像这样:

图片 1 — NeutonAI 注册页面(图片由作者提供)

你必须填写你的姓名和电话号码,然后,会出现一个连接你的谷歌云账户的选项。这是一个强制步骤,因此要么连接您的云帐户,要么创建一个新帐户。

下一步是选择一个计划,假设你已经准备好了一个谷歌云账户。重力 T2 计划是完全免费的,所以你可以从那个开始。一个新的谷歌云账户附带 300 美元的免费积分,这可能会在未来派上用场:

图 2——谷歌云设置(图片由作者提供)

您应该保留所有选项的默认值,并同意使用条款。这样做之后,你就可以完成 Google Cloud 项目的设置了,这会将你重定向回内乌顿页面。

假设一切顺利,您将看到一个创建新项目的按钮:

图片 3——内乌顿人工智能项目主页(图片由作者提供)

就这样——您已经准备好在这个*台上创建您的第一个 AutoML 项目了。

创建新的 AutoML 项目

点击添加解决方案按钮,将弹出一个新的模态窗口。它将要求您指定项目名称和描述。我们将围绕一个众所周知的泰坦尼克号数据集创建一个机器学习项目:

图 4 —创建新项目(1)(作者图片)

下一步是数据集。内乌顿为您提供了上传数据集或选择数据集的选项。你会在他们的图书馆里找到许多数据集,包括泰坦尼克号:

图 5 —创建新项目(2)(作者图片)

选择数据集后,您必须选择一个目标变量(您想要预测的变量)。Survived栏显示乘客是否在事故中幸存,所以这是您想要选择的内容:

图 6 —创建新项目(3)(图片由作者提供)

最后,您可以点击开始训练按钮。保持其他选项不变。只有当您正在为微控制器构建模型时,才应该使用 TinyML 选项——而现在您不是这样。

图 7 —创建新项目(4)(图片由作者提供)

训练过程现在开始——边等边给自己倒杯咖啡。

用 NeutonAI 训练机器学习模型

模特训练的过程并不复杂。已经开始了,所以你要做的就是坐着等:

图 8-训练机器学习模型(1)(图片由作者提供)

NeutonAI 为您处理数据处理和特征工程。你不用动一根手指。没有更多的时间花在处理杂乱的数据上——只要你的数据格式合理,一切都会自动处理。

对我来说,为泰坦尼克号数据集训练一个模型花了大约 5 分钟。完成后,您应该会看到以下消息:

图片 9-训练机器学习模型(2)(图片由作者提供)

这就是全部内容——您现在可以评估模型并根据新数据做出预测。

评估机器学习模型

内乌顿又一次变得非常简单。系统会自动为您创建一个 EDA 仪表盘,这是我们首先要探索的。

点击我的解决方案—分析工具。应该会弹出这样的菜单:

图 10 —评估机器学习模型(1)(图片由作者提供)

内乌顿点击指数数据分析选项后生成整个仪表板:

图 11 —评估机器学习模型(2)(图片由作者提供)

你也可以点击特征重要性矩阵选项——如下所示:

图 12 —评估机器学习模型(3)(图片由作者提供)

您还可以通过进入培训选项卡,获得对培训指标的更多见解。这将向您展示一个模型质量图和一个混淆矩阵:

图 13 —评估机器学习模型(4)(图片由作者提供)

对于业务用户来说,有很多方便的指标可以帮助他们理解模型是否足够准确。我在这里没有看到的唯一相关指标是 MAPE,但也许它会在未来的版本中添加。你可以在这里了解更多关于模型质量图

总而言之,内乌顿为评估机器学习模型提供了许多选项。当然,故事还有更多,但这是另一个时间的话题。

最后,让我们看看如何对以前看不见的数据进行预测。

做预测

首先,打开您的解决方案,点击粉红色按钮,显示启用预测下的:

图 14 —做出预测(1)(图片由作者提供)

这样做将同时启用 web 界面和 REST API,因此您可以选择最适合您需求的方法。让我们先来看看 web 界面。

网络界面

当您有单独的数据集用于训练和测试时, Web 预测界面非常有用。例如,Titanic 数据集包括两个 CSV 文件。您已经在第一个上训练了模型,现在是时候评估第二个上的性能了。

这就是网络界面的闪光点。

唯一的问题是,免费版本仅限于预测 CSV 文件的 100 行,但是您可以将您的文件切割成多个部分,并根据需要继续使用免费版本。

点击预测—网络预测下的开始按钮:

图 15 —做出预测(2)(图片由作者提供)

它会要求您选择 CSV 文件,因此选择一个由内乌顿提供的文件:

图 16 —做出预测(3)(图片由作者提供)

完成后,您可以下载预测或以表格形式在线查看:

图 17 —预测(4)(图片由作者提供)

选择在线查看预测数据的选项。下面是它的样子:

图 18 —做出预测(5)(图片由作者提供)

您还可以获得概率,这很有用,因此如果需要,您可以手动调整决策阈值。

说到调整,您可以点击任何预测行来打开模型解释器。它允许您更改参数,观察预测如何变化,并获得对模型背后的推理的更多见解。它看起来是这样的:

图 19 —预测(6)(图片由作者提供)

整个口译员有点难找。我希望在未来的更新中它会被放在一个更显眼的位置。你可以在这里阅读更多相关信息

接下来让我们探索 REST API 选项。

REST API

API 或多或少是将机器学习模型投入生产的标准方法。这个想法是公开一个模型的预测功能,这样任何人都可以访问它们,甚至是没有技术知识的人。您还可以围绕 REST APIs 构建应用程序,因此很容易理解为什么它们是生产中的首选方法。

内乌顿为你做了这一切。

在免费版本中,您被限制为 5000 个 API 请求,但是对于一个小型企业或项目来说,这已经足够了。

点击预测 REST API 访问下的访问指令你会看到所有的细节:

图 20 —做出预测(7)(图片由作者提供)

很简单,不是吗?如果你不需要特别的东西,这会节省你几个小时。大多数时候,你不知道。

判决

您现在知道如何从数据集到已部署的机器学习模型。问题依然存在—neuton ai 是这项工作的合适工具吗?

看情况。

如果你是一家以数据科学为先的公司,提供基于 SOTA 研究的定制解决方案,那么 NeutonAI *台不适合你。没有自动解决方案可以满足要求。然而,NeutonAI 作为基线可能会让你感兴趣,因为它在引擎盖下有一个获得专利的神经框架,可以根据创作者自动构建最佳模型。

另一方面,如果你是一个商业用户,不需要什么特别的东西,内乌顿可能就是你要找的。即使是最高级的版本,花费也不到一个中级数据科学家的月薪,而且它肯定能做更多。

你有什么想法?你试过NeutonAI吗?欢迎在评论区留下你的想法。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费:

https://medium.com/@radecicdario/membership

保持联系

  • 关注我的媒体,了解更多类似的故事
  • 注册我的简讯
  • LinkedIn 上连接

永远不要忘记这 8 个 NLP 术语

原文:https://towardsdatascience.com/never-forget-these-8-nlp-terms-a9716b4cccda?source=collection_archive---------23-----------------------

自然语言处理笔记

所有 NLP 爱好者都应该知道术语

凯利·西克玛Unsplash 上拍摄的照片

自然语言处理(NLP)是语言学、计算机科学和人工智能的一个子领域,涉及计算机和人类语言之间的交互,特别是如何对计算机进行编程,以处理和分析大量自然语言数据[ 来源 : 维基百科 ]。

如果你已经决定 NLP 是你希望专攻的数据科学的子领域,下一步是确定你需要了解的关键领域以推进你的职业生涯。问题是,你在网上找到的许多资源都假定你已经熟悉各种术语,因此你才会登陆他们的页面,但事实并非如此。

到本文结束时,您将对在与自然语言处理(NLP)相关的各种文章中可能遇到的一些关键术语有一个清晰的认识。

#1 语料库

由于自然语言处理是语言学的一个分支,语言学中的许多关键术语已经被该领域所采用。语料库翻译成拉丁语的意思是身体。身体构成了人或动物的身体结构,包括骨骼、肌肉和器官,因此我们可以说身体是由其他部分的集合构成的。

同理,我们说语料库是其他部分的集合,但这方面的其他部分是其他文档。例如,您可能有由不同宗教书籍组成的语料库(语料库的复数),其中每本书都被称为一个文档,书籍的集合就是语料库。

#2 标记化

标记化是 NLP 过程中的一个清理步骤。标记化的目标是将短语、句子或整个文本文档拆分成更小的单元,例如单词或术语。每个更小的单元被称为令牌。

符号化示例—作者的图像

#3 词干

在语言形态学和信息检索中,词干提取是将屈折词简化为词干、词根或词根形式的过程——通常是书面形式[来源:维基百科]

使用 NLTK 在 Python 中进行词干提取的示例:

**import** nltk
**from** nltk.stem.porter **import** PorterStemmerwords = ["walk", "walking", "walked", "walks", "ran", "run", "running", "runs"]

*# example of stemming*
stemmer = PorterStemmer()for word in words: 
    **print**(word + " ---> " + stemmer.stem(word))**>>>> walk ---> walk
     walking ---> walk
     walked ---> walk
     walks ---> walk
     ran ---> ran
     run ---> run
     running ---> run
     runs ---> run** 

#4 词汇化

语言学中的词汇化是将一个单词的词尾变化形式组合在一起的过程,这样它们就可以作为一个单独的项目进行分析,通过该单词的词汇或字典形式来识别[ 来源 : 维基百科

尽管 sounding 有相同的词干化目标,但词汇化和词干化是完全不同的。以下是方法:

  • 词干分析只是在考虑了屈折词中常见的前缀和后缀列表后,试图切断单词的结尾或开头。
  • 词汇化执行类似的过程,但是,这种技术考虑单词的形态分析。

使用 NLTK 的 Python 中的词汇化示例:

**import** nltk
**from** nltk.stem **import** WordNetLemmatizerwords = ["walk", "walking", "walked", "walks", "ran", "run", "running", "runs"]
*# example of lemmatization* lemmatizer = WordNetLemmatizer()for word in words:
    **print**(word + " ---> " + lemmatizer.lemmatize(word))**>>>> walk ---> walk 
     walking ---> walking 
     walked ---> walked 
     walks ---> walk 
     ran ---> ran 
     run ---> run 
     running ---> running 
     runs ---> run**

#5 停用词

在每一种语言中,都有许多单词在语言中频繁使用,但往往不会给文本增添多少意义,这些单词被称为停用词。然而,仅仅因为它们没有增加太多的意义,并不意味着你应该盲目地从你的文档中删除它们,因为这可能会损害你的分类器在一些分类任务中的结果。

以下是 NLTK 库中的英语停用词列表:

**import** nltk
**from** nltk.corpus **import** stopwords
nltk.download("stopwords")**print**(set(stopwords.words("english"))**>>>> {'a',  'about',  'above',  'after',  'again',  'against',  'ain',  'all',  'am',  'an',  'and',  'any',  'are',  'aren',  "aren't",  'as',  'at',  'be',  'because',  'been',  'before',  'being',  'below',  'between',  'both',  'but',  'by',  'can',  'couldn',  "couldn't",  'd',  'did',  'didn',  "didn't",  'do',  'does',  'doesn',  "doesn't",  'doing',  'don',  "don't",  'down',  'during',  'each',  'few',  'for',  'from',  'further',  'had',  'hadn',  "hadn't",  'has',  'hasn',  "hasn't",  'have',  'haven',  "haven't",  'having',  'he',  'her',  'here',  'hers',  'herself',  'him',  'himself',  'his',  'how',  'i',  'if',  'in',  'into',  'is',  'isn',  "isn't",  'it',  "it's",  'its',  'itself',  'just',  'll',  'm',  'ma',  'me',  'mightn',  "mightn't",  'more',  'most',  'mustn',  "mustn't",  'my',  'myself',  'needn',  "needn't",  'no',  'nor',  'not',  'now',  'o',  'of',  'off',  'on',  'once',  'only',  'or',  'other',  'our',  'ours',  'ourselves',  'out',  'over',  'own',  're',  's',  'same',  'shan',  "shan't",  'she',  "she's",  'should',  "should've",  'shouldn',  "shouldn't",  'so',  'some',  'such',  't',  'than',  'that',  "that'll",  'the',  'their',  'theirs',  'them',  'themselves',  'then',  'there',  'these',  'they',  'this',  'those',  'through',  'to',  'too',  'under',  'until',  'up',  've',  'very',  'was',  'wasn',  "wasn't",  'we',  'were',  'weren',  "weren't",  'what',  'when',  'where',  'which',  'while',  'who',  'whom',  'why',  'will',  'with',  'won',  "won't",  'wouldn',  "wouldn't",  'y',  'you',  "you'd",  "you'll",  "you're",  "you've",  'your',  'yours',  'yourself',  'yourselves'}**

#6 N-grams

在计算语言学和概率领域,n 元语法是来自给定文本或语音样本的 n 个项目的连续序列。根据应用,这些项目可以是音素、音节、字母、单词或碱基对。n 元语法通常是从文本或语音语料库中收集的[ 来源 : 维基百科 ]。

**from** nltk **import** ngrams# example sentence
sentence = "If you find this article useful then make sure you don't forget to clap"# defining the ngrams
unigrams = ngrams(sentence.split(), 1)
bigrams = ngrams(sentence.split(), 2)
trigrams = ngrams(sentence.split(), 3)# create list to loop
n_grams = [unigrams, bigrams, trigrams]**for** idx, ngram **in** enumerate(n_grams):
    **print**(f"\nN-grams: {idx +1}")
    **for** gram **in** ngram:
        **print**(gram)**>>>> N-grams: 1
('If',) ('you',) ('find',) ('this',) ('article',) ('useful',) ('then',) ('make',) ('sure',) ('you',) ("don't",) ('forget',) ('to',) ('clap',)****N-grams: 2
('If', 'you') ('you', 'find') ('find', 'this') ('this', 'article') ('article', 'useful') ('useful', 'then') ('then', 'make') ('make', 'sure') ('sure', 'you') ('you', "don't") ("don't", 'forget') ('forget', 'to') ('to', 'clap')****N-grams: 3
('If', 'you', 'find') ('you', 'find', 'this') ('find', 'this', 'article') ('this', 'article', 'useful') ('article', 'useful', 'then') ('useful', 'then', 'make') ('then', 'make', 'sure') ('make', 'sure', 'you') ('sure', 'you', "don't") ('you', "don't", 'forget') ("don't", 'forget', 'to') ('forget', 'to', 'clap')**

#7 正则表达式

单词“ Regex ”是正则表达式的简称。从本质上讲,正则表达式是一个字符串,它定义了一个文本模式,以允许您匹配、定位和管理文本。

正则表达式的例子[ 来源:comidoc.com

#8 标准化

文本规范化是将文本转换成以前可能没有的单一规范形式的过程。在存储或处理之前规范化文本它允许关注点分离,因为在对其执行操作之前保证输入是一致的[ 来源 : 维基百科

标准化技术的例子包括:

  • 堵塞物
  • 词汇化
  • 标记化
  • 等等。

包裹

当处理自然语言时,有许多东西要学,但是许多术语在数据科学家和 NLP 工程师中是重复的。了解和理解本文中的术语将为您提供一个健康的基础,以便开始学习构成自然语言的其他领域,如自然语言理解(NLU)和自然语言生成(NLG)。确保你把它们记在心里,永远记得学习新的东西。

感谢阅读!在 LinkedInTwitter 上与我联系,了解我关于人工智能、数据科学和自由职业的最新帖子。

相关文章

在你的探索性数据分析(EDA)中千万不要跳过这一步!

原文:https://towardsdatascience.com/never-skip-this-step-in-your-exploratory-data-analysis-eda-60034da9f0f0?source=collection_archive---------17-----------------------

数据科学。统计学。埃达。PYTHON。

描述性统计如何误导你

卢卡斯·桑基在 Unsplash 上的照片

介绍

如果您是数据科学的新手,并且已经上过初步数据分析的课程,那么进行探索性数据分析(EDA)的第一步可能就是查看摘要/描述性统计数据。但是这一步我们真正想要完成的是什么呢?

汇总统计很重要,因为它们告诉您对数据建模很重要的两件事:位置和比例参数。在统计学中,位置参数是指*均值。这让您知道您的数据是否正常,以及是否有潜在的偏态,以帮助建模决策。

例如,如果数据集是正常的,像普通最小二乘(OLS) 这样的建模技术对于预测结果可能是足够的和强大的。除此之外,我们进行初始数据清理的方式,例如丢失数据的处理,可能取决于数据是否表现出正常的行为。

标度参数指的是我们在数据中的离差量(如标准差和方差)。这个参数越大,我们的分布就越分散。

因此,查看描述性统计数据是必不可少的,特别是对于建模和研究设计目的。然而,认为描述性统计足够用于 EDA 可能是数据专业人员可能犯的最昂贵的假设之一。

为了了解这一点,让我们通过一个流行的数据集 datasaurus dataset 进行一个可视化练习。

DATASAURUS 数据集

人们普遍认为,只有当我们报告或交流数据/见解/结果时,可视化才会占据中心位置。

然而,当查看由 Alberto Cairo 创建的 datasaurus 数据集时,不要错过 EDA 的可视化部分的重要性变得显而易见。数据集可以在这个链接中找到。

来自 Justin Matejka 和 Autodesk 的增强数据集,以及可以从 R 的 datasauRus 包下载的数据集,提出了 13 个几乎相似的数据集来进一步说明这一点。(使用数据的许可来源于发给文章作者的个人电子邮件)

让我们继续生成数据集的描述性统计数据。

描述统计学

# Preliminariesimport pandas as pd
import numpy as npdf.dataset.unique()

这些是 datasaurus 十几数据集内的 13 个子数据集。

unique = df.dataset.unique()for i in unique:
    temp = df[df.dataset==i]
    print(f'---Summary Statistics for \'{i}\' dataset---')
    print(np.round(temp.describe().loc[['mean', 'std'],],2))
    print(f"\nCorrelation: {np.round(temp.corr().iloc[0,1],2)} \n")

作者图片

作者图片

作者图片

为我们的 12 个数据集生成描述性统计数据,特别是位置和比例参数,包括相关系数,会产生几乎相同的值。

因此,单独运行描述性统计会使我们得出结论,它们实际上是相同的数据集,可以相似地建模。

但是,让我们想象一下,看看这个想法有多准确。

可视化数据集

我们开发了一个简单的应用程序,使用 panel 交互式地查看 13 个数据集:

import panel as pn
import holoviews as hv
pn.extension()def visualize_scatter(dataset):
    temp = df[df['dataset']==dataset]
    scatter =  hv.Scatter(temp, 'x', 'y')
    scatter.opts(color='#cb99c9', s=50)
    return scatterpn.extension(comms='default')select = pn.widgets.Select(name='dataset', options=list(unique))dmap = hv.DynamicMap(pn.bind(visualize_scatter, dataset=select))app = pn.Row(pn.WidgetBox('## Dataset', select), 
             dmap.opts(framewise=True)).servable()
app

作者对 Datasaurus 数据集的交互式可视化

太神奇了!这 13 个数据集虽然具有相似的描述性统计数据,但视觉效果却大相径庭。因此,用一种方式对它们进行建模是危险的,可能会对决策产生危险的影响。

结束语

现在我们看到了数据可视化的重要性,它不仅仅是流程的报告部分,让我们将它纳入我们的 EDA 中。

虽然这篇文章并没有阻止我们生成和使用描述性统计,但采用这种习惯实际上可能是好的:在做描述性统计之前先想象一下。虽然不是常规的,但可视化数据集首先允许数据科学家就如何批准正在解决的问题产生一些初步的方向。

对于我的其他可视化文章,请查看:

我的 Github 页面上的全部代码。

让我知道你的想法!

参考

贾斯汀·马特伊卡和乔治·菲兹莫里斯。2017.相同的统计,不同的图形:通过模拟退火生成具有不同外观和相同统计的数据集。2017 CHI 计算系统中人的因素会议论文集。计算机械协会,纽约,纽约州,美国,1290-1294。土井:https://doi.org/10.1145/3025453.3025912

再也不用为在 Kubeflow 管道组件之间共享数据而烦恼了

原文:https://towardsdatascience.com/never-struggle-again-to-share-data-between-your-kubeflow-pipelines-components-b750ab8bcd7c?source=collection_archive---------16-----------------------

实践教程

了解如何使用 Kubeflow 管道实现经济高效的自动化模型再培训解决方案——第 2 部分

约翰·汤纳在 Unsplash 上的照片

这是 3 部分系列的第 2 部分,我将解释如何使用 Kubeflow Pipelines 作为 ML 系统编排器来构建一个具有成本效益的自动化 ML 再培训系统。在第一部分现成的这里,我重点介绍:

  1. 设置 Kubeflow 管道和云 SQL
  2. 建筑管道组件
  3. 编写条件组件和外部触发的管道

现在让我们转向一个稍微高级一点的话题。本文涵盖了如何在管道组件之间共享数据。

掌握数据共享至关重要

当我们给 Kubeflow 管道分配一些工作时,通常可以将这些工作分成多个小的工作。这就是管道组件发挥作用的地方。每个组件负责管道工作的一部分。将管道工作分成许多更小的单元有许多好处。

易于编写、测试、调试和维护

以应用程序代码库中的函数为例。管道代表应用程序,组件代表应用程序代码库中的功能。SoC(关注点分离)原则教导将应用程序代码分解成模块,并将模块分解成功能。然后,每个功能都致力于完成一个更小更简单的工作,随着时间的推移,这使得编写、单元测试、调试和维护单个功能和整个应用程序变得更加容易。

复用性

除了更小、更简单之外,拆分管道后得到的组件也各不相同,专门用于执行它们所负责的任何工作。因此,您通常有能力在许多管道中共享和重用它们。例如,考虑一个负责从远程存储器下载文件的组件。

协作的容易程度

当与具有不同专业知识的人在一个团队中工作时,将管道分成不同的组件可以通过团队协作加快管道的构建。例如,考虑 ML 流水线。数据工程师可以处理数据转换组件,而数据科学家可以处理 ML 培训组件。同时。

可重复性的容易程度

假设有人建议您将管道分割成小块,并遵循这个建议。假设管道的某一段在第 5 个组件处出现故障。Kubeflow Pipelines 允许您从失败的组件开始重试管道,从而节省时间和资源。

让我们更实际地将管道分成组件,并在这些组件之间共享数据。在本文第 1 部分的ML pipeline I 演示中,出租车费用预测器管道负责培训、验证和部署新的模型版本(如果相关)。下图显示了 ML 管道的简化版本。

  • 第一个组件,训练组件,使用训练和测试数据以及模型代码库作为输入来训练 ML 模型,并将评估摘要写入云 SQL 数据库。请注意,这些输入不是由另一个组件传递给该组件的。相反,训练组件直接从管道接收输入。
  • 第二个组件验证组件从数据库中读取由训练组件创建的评估摘要。然后,它决定部署模型是否相关。这个决定也是组件的唯一输出。请注意,评估数据是如何通过外部系统(SQL 数据库)在这两个组件之间共享的,而不是直接共享的。
  • 第三个组件,部署组件,读取由验证组件做出的部署决定。如果决定是有利的,组件还读取它从训练组件接收的模型工件,并部署模型的新版本否则,它不会部署新版本的模型。

好了,在这一点上,您已经感觉到在创建管道时掌握数据共享是多么重要。接下来,让我们讨论在管道内部共享数据时要遵循的最佳实践。

数据共享食谱

让我们来分析一下在两个组件之间进行数据交换时到底发生了什么:

  • 生产者’(产生数据的组件)
  • 消费者’(消费数据的组件)。

【生产者】【消费者】之间的数据交换可以总结为 8 个步骤:

  1. 生产商集装箱开工
  2. 生产者生产数据
  3. Kubeflow Pipelines 将数据复制到其存储系统中
  4. 生产商集装箱退场
  5. 消费者容器启动
  6. Kubeflow 管道将数据从其系统复制到消费者容器的本地文件系统
  7. 消费消费数据
  8. 消费者集装箱出口

你知道第 3 步和第 6 步吗?就我个人而言,我没有。实际上,从我发现有一些步骤是由 Kubeflow 系统本身处理的那天起,我就开始理解 Kubeflow 管道的数据共享是如何工作的。

现在,您还记得有 3 种方法可以构建管道组件吗?事实上,您可以:

  • 编写一个 python 自包含函数,并从中构建一个组件
  • 使用“containerOp”工厂方法从容器映像构建组件
  • 将组件规范写成一个 yaml 文件,并加载它来创建组件

在 Kubeflow 管道组件之间共享数据时,您始终要遵循两条黄金法则:

  • 当产生一些要共享的数据时,让 Kubeflow Pipelines 系统决定在容器文件系统上存储数据的位置,而不是自己选择一个位置。

虽然我不确定 Kubeflow 为什么建议这样做,但我相信遵循这条规则可以防止当 Kubeflow 试图将数据从容器复制到其存储系统时可能出现的任何问题(如权限问题)。然而,请注意,当使用“container op”工厂来构建组件时,这目前是不可能的(根据我的发现)。

  • 无论组件是如何创建的,小数据都是按值消耗,大数据是按文件(按路径)消耗。

理解并应用这第二条规则对于正确共享数据以及让管道在执行时没有错误或意外的高资源请求是至关重要的。

看一下前面提到的 2 条规则,了解共享数据的大小对于决定如何实现数据共享是很重要的。似乎也不太推荐使用 "containerOp" 工厂,因为它要求管道作者选择容器文件系统上产生的数据应该写入的位置。因此,这种选择不包括在本文中。

因此,在接下来的段落中,我将演示如何使用 python 自包含的基于函数的组件和基于 yaml 规范的组件来生成和消费大小数据。

用基于功能的组件产生小数据

如果组件产生的数据很小,例如一个代表文件路径的字符串,只需让函数返回这个数据。如果您需要输出许多这样的小数据,您会想要使用' NamedTuple' 类。

但是,请注意,Kubeflow 管道将把这些数据写到一个文件上,并把这个文件复制到它的存储系统中,以便它接下来可以把这些数据提供给它的消费者。

使用基于函数的组件消费小数据

这很简单。只需将函数定义为普通的 python 函数。然后,当实例化组件时,使用生产任务的“输出”方法。

使用由上述基于功能的组件( get_model_location )产生的位置数据如下:

由于包含数据的文件已经由 Kubeflow 在生产容器的出口处持久化,因此 Kubeflow 管道实际上读取该文件,并将其内容的字符串表示传递给消费组件。

用基于功能的组件产生大数据

还记得适用于生产供下游组件使用的大数据的黄金法则吗?你总是想让 Kubeflow pipelines 系统为你选择一个位置,并把数据写到那个位置。

这通过以下方式实现:

  • 在函数的签名中声明一个' OutputPath()' 参数
  • 处理该路径的父文件夹可能不存在于容器中的事实(即如果需要,创建父文件夹)
  • 将数据写入类型为 'OutputPath()' 的参数所引用的路径

使用基于功能的组件消费大量数据

我们总是希望通过路径来消耗大量数据或文件。如果我们指示 Kubeflow 我们只需要数据的路径,它就不会费心为我们读取数据。相反,Kubeflow 只会将文件复制到容器的本地文件系统,并向消费函数提供该文件的路径。

使用消费函数签名中的一个 'InputPath()' 参数向 Kubeflow 请求文件路径而不是文件内容。当消费组件被实例化时,此参数将接收生产组件的输出。

用基于规范的组件产生小数据

当组件从 yaml 规范构建时,规则不会改变:让 Kubeflow 挑选一个位置并把它给你。你必须:

  • 在规范的‘输出’部分中指定由您的组件产生的数据
  • 使用规范的‘实现’部分中的‘输出路径’关键字,通过容器参数引用此输出
  • 处理 Kubeflow 生成路径的父文件夹可能不在容器中的事实
  • 在路径位置写入数据

这里的是关于编写库巴流管道规范的官方文件。

使用基于规范的组件消费小数据

正如本文前面所讨论的,小数据可以被价值直接消费。要在 yaml 规范组件的上下文中做到这一点:

  • 在您的规范的“输入”部分指定您的组件所消耗的数据
  • 使用规范的‘实现’部分中的‘输入值’关键字,通过容器参数引用此输入
  • 在实例化组件时,使用生产组件的‘outputs’方法来请求数据

用基于规范的组件产生大量数据

与基于功能的组件相反,无论您是使用 yaml 规范生成小数据还是大数据,过程都是完全相同的。您可以在规范的实现部分使用‘output path’关键字,让 Kubeflow 选择并给出写入生成数据的位置。

使用基于规范的组件消费大量数据

我不能经常强调:大数据是要被路径消费的。使用基于规范的组件实现这一点的方法是:

  • 在规格的【输入】部分指定您的组件所消耗的数据
  • 使用规范的‘实现’部分中的‘输入路径’关键字,通过容器参数引用此输入
  • 实例化组件时,使用生产组件的‘outputs’方法请求数据
  • 使用提供的路径读取消费组件容器源代码中的数据

结束注释

如果让我从这篇文章中选择两个最重要的观点,我会引用组件间数据共享的两条黄金法则:

  1. 为下游任务生成数据时,让 Kubeflow 为您选择一个位置
  2. 始终按值消耗小数据,按路径消耗大数据

在研究这些内容时,我发现“container op”工厂在共享数据方面不如基于功能的组件和基于规范的组件灵活。

此外,回想一下当您共享数据时,在幕后发生的数据传输。如果您的组件容器可以访问分布式存储,如谷歌云存储或亚马逊 S3,请考虑将您的大数据写入其中,并通过值来消费到它的路径。

请继续关注本系列的下一篇文章,讨论如何将秘密传递给组件,以及如何设计管道和组件输入。

Scikit-Learn 的新功能

原文:https://towardsdatascience.com/new-features-of-scikit-learn-fbbfe7652bfb?source=collection_archive---------4-----------------------

照片由米 PHAMUnsplash

0.24 版中最重要功能的概述

Python 的机器学习库 Scikit-learn 刚刚变得更好。现在是更新的最好时机。

R 最*,2020 年 12 月,scikit-learn 发布了 0.24 版本的重大更新。这是版本 0 的最后一个稳定版本。下一个版本应该是 1.0 版本,目前正在开发中。

我将概述 0.24 版本中引入的一些重要特性。考虑到大量突出的特性,我强烈建议升级您的 scikit-learn 库。

内容:

  • 升级到 0.24 版本
  • 主要特点
  • 其他有趣的功能

升级到版本 0.24

我正在使用 Python 环境,所以,首先我激活了我想要的环境,然后通过pip升级了 scikit-learn 版本。

# Activate the environment
>>> source activate py38# Upgrade scikit-learn 
>>> pip install — upgrade scikit-learn...
...
**Successfully installed scikit-learn-0.24.0**

主要特点

\照片由托尔加·乌尔坎Unsplash 上拍摄

1)顺序特征选择器(SFS)

这是一种贪婪地从高维空间中选择最重要特征的方式。该变换器使用模型估计器的交叉验证来迭代地通过分别经由前向和后向选择添加或移除特征来找到最佳特征子集。

正向选择从较少的特征开始,并逐渐添加最佳的新特征,直到获得所需数量的特征。向后选择从更多的特征开始,并逐个移除它们,直到选择了所需数量的特征。

它是“SelectFromModel”(SFM)变压器的替代产品。SFS 相对于 SFM 的优势在于,SFS 中使用的估计量(模型)在拟合后不需要具有feature_importances_coef_属性,这与 SFM 不同。SFS 的缺点是,由于其迭代性质和 k 倍 CV 评分,它比 SFM 相对较慢。下面是一个例子。尝试使用不同的分类器来处理代码。

from sklearn.datasets import load_wine
from sklearn.neighbors import KNeighborsClassifier
from sklearn.feature_selection import SequentialFeatureSelectorX, y = load_wine(return_X_y=True, as_frame=True)
n_features = 3model = KNeighborsClassifier(n_neighbors=3)
sfs = SequentialFeatureSelector(model, 
                                n_features_to_select = n_features, 
                                direction='forward') #Try 'backward'
sfs.fit(X, y)print("Top {} features selected by forward sequential selection:{}"\
      .format(n_features, list(X.columns[sfs.get_support()])))**# Top 3 features selected by forward sequential selection: 
# ['alcohol', 'flavanoids', 'color_intensity']**

照片由马库斯·温克勒Unsplash 拍摄

2)个体条件期望(ICE)图

ICE 图是一种新型的部分相关图,它显示了数据集中给定样本的预测如何依赖于某个特征。如果你有 100 个样本(录音)和 6 个特征(自变量),那么你将得到 6 个支线剧情,其中每个剧情将包含 100 行(你可以指定这个数字)。所有子情节中的 y 轴将覆盖目标变量(预测)的范围,而 x 轴将覆盖相应特征的范围。

以下代码生成如下所示的 ICE 图。

from sklearn.datasets import load_diabetes
from sklearn.ensemble import RandomForestRegressorX, y = load_diabetes(return_X_y=True, as_frame=True)
features = ['s1', 's2', 's3', 's4', 's5', 's6'] # features to plotmodel = RandomForestRegressor(n_estimators=10)
model.fit(X, y)ax = plot_partial_dependence(
       model, X, features, kind="both", subsample=60, 
       line_kw={'color':'mediumseagreen'})ax.figure_.subplots_adjust(hspace=0.4, wspace=0.1) # adjust spacing

使用随机森林回归方程显示糖尿病进展对六种血清特征的依赖性的 ICE 图。

塔曼娜·茹米在 Unsplash 上拍摄的照片

3)逐次减半估计量

引入了两种新的超参数调整估计器,即halvinggridsearccvHalvingRandomSearchCV。它们可以分别作为 scikit-learn 迄今为止内置的超参数调优方法 GridSearchCVRandomizedSearchCV、的替代方法。

基本思想是,对最佳超参数的搜索从具有大量参数的几个样本开始。在下一次迭代中,样本数量增加(增加因子 n ,但参数数量减半/减少(减半不仅意味着因子 1/2 (n=2),还可以是 1/3 (n=3)、1/4 (n=4),以此类推)。这个减半过程持续到最后一次迭代。最后,参数的最佳子集是在最后一次迭代中得分最高的那个。

类似于现有的两种方法,可以随机地(HavingRandomSearchCV)或者穷举地(HavingGridSearchCV)执行“连续减半”。下面的示例演示了 HavingRandomSearchCV 的用例(您可以类似地使用 HavingGridSearchCV)。关于如何选择最佳参数的全面说明,请参考此处的

from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import HalvingRandomSearchCVX, y = load_iris(return_X_y=True, as_frame=True)
model = RandomForestClassifier(random_state=123, n_jobs=-1)param_grid = {"n_estimators": [20, 50, 100],
              "bootstrap": [True, False],
              "criterion": ["gini", "entropy"],
              "max_depth": [1, 2, 3],
              "max_features": randint(1, 5),
              "min_samples_split": randint(2, 9)
              }grid = HalvingRandomSearchCV(estimator=model,
                             param_distributions=param_grid,
                             factor=2, random_state=123,)
grid.fit(X, y)
print(grid.best_params_)**# Output
{'bootstrap': True, 'criterion': 'gini', 'max_depth': 2, 'max_features': 4, 'min_samples_split': 8, 'n_estimators': 50}**

照片由罗迪·洛佩兹Unsplash 上拍摄

4)半监督自训练分类器

Scikit-learn 有几个用于监督学习的分类器。现在,这些监督分类器可以执行半监督分类,即,使模型能够从未标记的数据中学习。只有那些预测目标变量的类概率的分类器可以用作半监督分类器。官方示例这里提供了对 Iris 数据集的监督分类和半监督分类的比较。

以下文章很好地解释了半监督学习的概念:

照片由 Anastasia ZheninaUnsplash 上拍摄

5)历史梯度推进中的自然范畴特征

“HistGradientBoostingRegressor”和“histgradientsboostingclassifier”现在都可以支持无序的分类特征。通常,必须使用诸如一键编码、顺序标记等方案对分类特征进行编码。有了新的本地特性,用户可以直接指定分类列(特性),而不需要对它们进行编码。

最好的部分是丢失的值可以作为一个单独的类别。典型地,独热编码被应用于训练集。对于给定的特征(列),假设训练集有六个类别,测试集有七个类别。在这种情况下,在六个附加列上训练的模型(由于一键编码转换,每个类别值有一个额外的特征)将在测试集的验证期间由于未知的第 7 个类别而抛出错误。本机功能可以通过将这第 7 个未知类别视为缺失值来规避这个问题。

参考这个比较不同编码方案的官方例子。

6)不要用 scikit 做什么-了解

添加了新的文档,该文档关注使用 scikit-learn 进行机器学习时的常见陷阱。除了强调常见的错误,它还解释了做某些事情的推荐方法。本文档中涵盖的一些示例包括:

  • 数据转换的最佳实践(例如,标准化)
  • 线性模型系数正确解释
  • 通过正确处理训练和测试数据集,避免数据泄露
  • 推荐使用随机状态来控制随机性,例如在 k 折叠 CV 期间

附加文档

通常, GridSearchCV 用于为我们的模型寻找超参数的最佳子集。基于我们预定义的绩效评分参数(如'accuracy''recall''precision'等)。),我们选择最佳超参数子集。本文件提供了一个示例,展示了根据统计显著性比较不同模型的正确方法。

其他有趣的功能

1)回归的新评估指标

*均绝对百分比误差(MAPE)是针对回归问题引入的新评估指标。该指标对目标变量的全局缩放不敏感。在数据范围超过几个数量级的情况下,通过计算误差与真值的相对百分比,这是一种合理的误差测量方法。更多详情请参见这一页。

*均绝对百分比误差。ϵ是一个任意小的正数,例如 1e-6。变量 y 和 y_hat 代表真实值和预测值。

2)独热编码器将缺失值视为类别

一键编码器现在可以将分类特征中的缺失值视为附加类别。如果特定分类特征中的缺失值是'None''np.nan',它们将被编码为两个独立的类别。

3)使用普通编码器对未知类别进行编码

OrdinalEncoder 现在允许在转换到用户指定值的过程中对未知类别进行编码。

4)决策树回归器的泊松分裂准则

DecisionTreeRegressor 现在支持一个名为 **'poisson'**新分裂标准,该标准基于泊松偏差的减少来分裂一个节点。这有助于对目标变量代表计数或频率的情况进行建模。参见这篇文章,了解更多关于泊松分布的信息。****

5)可选颜色条在confusion matrix plot

绘制混淆矩阵时,颜色条现在是可选的。要做到这一点,你必须通过关键字colorbar=False

plot_confusion_matrix(estimator, X, y, colorbar=False)

结论

这篇文章列出了最新 scikit-learn 更新(v0.24)中的一些突出变化。完整的变更列表可在此处获得。这是版本 0 的最后一次更新。下一个版本将是 1.0。如果你有兴趣了解上一版本(v0.23)中的亮点特性,可以看看我之前的帖子:

** **

为数据科学设置新的 M1 MacBook

原文:https://towardsdatascience.com/new-m1-who-dis-677e085baffd?source=collection_archive---------1-----------------------

一个 Python/熊猫的家伙在苹果芯片上开店

形象唤起工艺!

2021 年 4 月,我有幸打开了一台全新的 2020 M1 苹果 MacBook Air。

TL;博士;医生

如果你希望在你的新 M1 MacBook 上原生运行 Python 库(即没有 Rosetta 2 翻译),省下很多麻烦:使用 miniforge 。它就像 miniconda,但默认支持苹果 M1。

为什么是麦克?

我会考虑安装 Ubuntu,但我对一些商业化的 mac/win 专用应用程序如 Adobe Lightroom 情有独钟。我考虑过切换到 Windows(并使用 WSL2):这样,我仍然可以拥有我愚蠢的 GUI 应用程序和 Linuxy 开发环境,然后在硬件上挥霍。但是 MacBooks 的工业设计有一点很特别!我喜欢把 MacBook air 放在背包里随身携带的轻松感觉。我已经在 macOS 上扎下了根。

我知道苹果芯片的一些问题:新的 arm64 处理器架构对数据科学库兼容性提出了挑战。基本上,这是太新——我不习惯有这个问题。尽管如此,新的苹果芯片还是https://www.youtube.com/watch?v=cAjarAgf0nI&ab_channel=TheDevDoctor快,开发者社区正在努力弥合这一差距。

它也不是你能以这个价格买到的最强大的笔记本电脑。也就是说,在一个生产 ML 的重担越来越多地在云服务器上执行的世界里,UX 对我来说可能比我本地日常机器上的原始计算能力更重要。我已经掌握了 AWS 的基础知识,并且正在上 Docker、Kubernetes、Terraform 等课程。必要时,我仍然可以在运行 plaidML 的旧 x86 Hackintosh 桌面上运行 shell。

为什么是新的?

我一直在易贝上购买二手的 2016-2018 款 MacBooks(小心翼翼地避免蝴蝶键盘),以取代我的 2012 款(不再支持最新的 macOS),但后来我的雇主介入,提出直接给我买一台新的苹果机器,所以我接受了他们的提议。谢谢雇主!我相信,随着时间的推移,与所有流行的数据科学库的完全兼容将会到来,并且这台计算机将比旧计算机运行得更快,寿命更长。

所以现在我有了一台闪亮的新 MacBook。由于缺少花哨的管理设置脚本,我按照以下顺序安装了新硬件:

大苏尔上的前几个按键

  • 微风吹过欢迎屏幕:没有 Siri,只有英语
  • 隐藏码头。为什么要让 dock 保持可见,尤其是在笔记本电脑上,因为屏幕空间非常宝贵?
  • Dock:切换卡通“精灵”最小化动画到更高级的“比例”
  • 连接到我手机的 WiFi 热点,以登录 LastPass
  • 从 LastPass 复制我的家庭 wifi 密码(许多随机字符)
  • 使用复制的密码从移动热点切换到家庭 WiFi
  • 下载 Chrome,使其成为默认浏览器
  • 登录 chrome 上的 Google 账户,安装我的各种扩展:LastPass,RegEx search,Privacy Badger,AdBlock,Grammarly,JSONview,Wikiwand,打开当前旁边的标签,等等。
  • 将触控板灵敏度设定为最大。
  • 操作系统附带的一些应用程序:Garageband、Keynote、iMovie、Pages、Numbers。我更喜欢谷歌的云应用程序作为 MS Office 的替代品,以及用于视频和音频编辑的免费 DaVinci ResolveReaper
  • 关闭大部分 iCloud 的东西。仅保留“查找我的 Mac”和“钥匙串”。我用 dropbox + google 来管理文件、日历、联系人等等

开发相关设置

一些更有生活质量的东西

  • % brew install flycut spectacle —我不知道没有这些剪贴板历史和屏幕空间管理工具,我将如何完成任何事情。
  • 哎呀,奇观没有 rosetta 就跑不了。我猜这是不可避免的。是时候安装大家最喜欢的新翻译环境了。希望每个人都能很快移植到 arm64 上。
  • 打开 FlyCut 粘性挡板。不知道没有这个怎么用 FlyCut。
  • 因为我喜欢一眼就能看出我的电脑有多忙:

通过参数计方便的 CPU 温度和利用率统计

  • % brew install dropbox因为云存储是关键
  • % brew install whatsapp slack android-messages用于通讯。
  • 因为没有音乐我在做什么

回到开发的事情

“thefuck”的常见乐趣。这个木桶实际上叫做 visual studio 代码 btw

  • 设置 vundle ,主要用于 vim 中的航空公司和相关行号。我应该和 vim 一起变好…
  • % brew install visual-studio-code因为不,我不只是用 vim
  • 同步 vscode 设置并确保扩展准备就绪。我喜欢 Python Docstring 生成器、SonarLint、Vim 模拟器等等
  • 因为我需要我的终端文本在每次打开一个新的会话时变大一点。我做了一个额外的 iTerm2 应用程序的副本,选中了“使用 Rosetta 打开”。我可能会更多地利用 iTerm2 的特性。

麻烦开始了

  • 因为这正是我最*一直在用的

我的 python 3.8.6 构建失败了,我认为是因为它与新芯片不兼容。现在怎么办?

  • 因为我们最终都要拥抱未来。它在苹果芯片上开箱即用。
  • % pyenv global 3.9.4因为我说python的时候就是想要这个
  • 试着在 venv 中安装各种大的令人讨厌的 python 库,比如opencv。注意红色错误信息墙。我将回到这一点。
  • 尝试从源代码安装 opencv。这是痛苦的,感觉草图,导致绝望当它在第一次尝试时对我不起作用。乐叹。

这是我预料中的路障。我知道并不是每个人都已经将他们的 Python 数据科学库移植到苹果 M1 芯片上。我希望避免过多地依赖 Rosetta 翻译器,所以我会坚持尝试从源代码中构建一些东西或找到解决方法。

就用 MiniForge

  • 我彻底屈服了,跑了% brew install miniforge。这就行了。
  • 似乎不错。试试% conda create -n .venv python=3.9.2。新环境工程。
  • 假设我想安装一些晦涩的 Python 包,它们存在于 PyPi 上,但不存在于 conda forge 上。我可以尝试:% pip install [obscure_library_name],看看它在哪个依赖项上失败了,然后递归地运行:% conda install [dependency],直到我可以完全安装我想要的晦涩的库。它并不漂亮,但目前为止还能用。还是不用 Rosetta!
  • 上面的方法对 OpenCV 不起作用,所以我按照这个人的指南再次尝试从源代码构建 OpenCV。这一次,我喝了更多的咖啡因,并愿意按照指示去开球。它非常有效。

最后

这是我在新的 M1 MacBook Air 上开店的理由和过程。

起初,我尝试使用 pyenv 以一种非常普通的方式管理 python venvs,但是效果不是很好。

我最终只是通过 brew 安装了 MiniForge(类似于 MiniConda ),这对于管理 venvs 很有效。当我们在苹果芯片和开源数据科学(和其他)库之间架起桥梁时,MiniForge 的“强调支持各种 CPU 架构”就派上了用场。

面向高级从业者的新机器学习专业

原文:https://towardsdatascience.com/new-machine-learning-specialisations-for-advanced-practitioners-862e1b3d28d?source=collection_archive---------39-----------------------

特别关注 MLOps 或 ML 工程

作者图片

今天,你不需要去大学或学院追求机器学习或任何数据驱动领域的职业生涯,但你需要一个计划和一个路线图来指导自己。

一旦你心中有了自己的学习路线图,下一步就是筛选适合你的路线图的课程,然后开始围绕这些课程建立你的基础。

本周,我想分享一些高级专业和课程,它们在我的清单上,可以帮助你寻找正确的课程或正确的职业道路。

所以,给你:

吴恩达《生产专业化中的机器学习》

关于 ML 工程和 MLOps 等主题的讨论为标准化实践的发展提供了动力,以工具和技术的形式生产 ML 模型。机器学习领域中的这些新颖的工程方法没有被很好地记录和教授。

通过这种专业化,通过该领域的一些先驱,您可以训练自己能够编写生产就绪的、ML 支持的应用程序。该专业声称可以帮助您:

  • 设计一个端到端的 ML 生产系统
  • 通过收集、清理和验证数据集来构建数据管道。
  • 建立模型基线,持续改进生产化的 ML 应用。
  • 应用最佳实践和渐进式交付技术来维护和监控持续运行的生产系统。

这是一个为期 5 个月的专业,有 4 门课程针对 ML 工程的每个阶段。

你可以去 Coursera 上的个人课程,并对其进行审核,以便免费使用。

Andrew 在为每个人普及机器学习方面做了出色的工作,这种专业化可能也能为 ML 工程做同样的事情。

一旦我完成了这个专业,我会写一篇详细的评论。如果你在我之前完成它,让我知道你如何找到它。

从拥抱脸看变形金刚课程🤗

对于所有深度学习爱好者,拥抱脸发布了一个关于变形金刚的新课程。这看起来很有希望,因为我真的很喜欢看同一位作者(Sylvian Gugger)写的程序员实用深度学习。

任何想要深入学习训练 NLP 模型的人都应该去看看这个课程。

课程包括:

  • 变压器介绍,微调预训练模型,以及共享模型和记号化器。
  • 使用数据集和 tokenizers 库。
  • 如何开发专门的架构,加速训练,以及编写定制的训练循环。

令人惊奇的是,这门课程完全免费。按照你自己的步调去做,试着构建一个完整的应用程序,而不仅仅是一个训练有素的模型。

学习的最好方法是在你自己的项目中使用它来解决你自己的问题。

由悟空莫汉达斯用 ML 制作的 MLOps 系列

一个月前我发现了小悟空的内容,我对他在 MLOps 上开发这个课程所付出的努力感到惊讶。实际磨练 MLOps 每个阶段的技能需要大量的工作,因为与模型相比,实际产品中有如此多的活动部件。

他将整个课程分成了许多子领域:

  • 产品
  • 数据
  • 建模
  • 脚本
  • API 和接口
  • 测试和再现性
  • 生产系统

我强烈推荐学习他的课程,这是绝对免费的,作为社区的一部分,你可以与类似的人交流。

注:初学者(包括我自己)常犯的一个错误是,他们不停地从一门课程跳到另一门课程,却没有真正完成任何一门课程的交付内容。如果你是在探索,这没问题,但当你把目光投向一门课程时,试着从中建立一些东西,而不是简单地跟着讲课和做填鸭式练习。

本周有趣的阅读——一个自己的项目

上周,我读了保罗·格拉厄姆(通常被称为 Ycombinator 的联合创始人)写的一篇名为一个属于自己的项目的文章,这篇文章不仅证实了而且强化了我自愿参与项目的想法,即使这只是一份兼职。

一篇关于自愿参与雄心勃勃的项目的重要性的优秀文章。

在完全控制和自愿行动的情况下做自己的项目让你感受到自由,并激发好奇心去更深入地探索。

它教给你的东西比别人让你做的任何工作都要多。

如果您有任何问题、建议或想法,请随时联系我们!

和我联系!

如果你喜欢这些内容,可以考虑订阅我的时事通讯,我会每周向你的收件箱发送说明性教程、职业见解/机会或项目想法。

如果您有任何问题或想法,请随时回复本博客。你可以在 TwitterLinkedIn 上与我联系,了解更多关于工作更新和一些有趣的事情!

新论文描述了谷歌 Colab 笔记本电脑有效地运行蛋白质的分子动力学模拟

原文:https://towardsdatascience.com/new-preprint-describes-google-colab-notebook-to-efficiently-run-molecular-dynamics-simulations-of-9b317f0e428c?source=collection_archive---------12-----------------------

继 AlphaFold 在 Google Colab 上取得成功之后,这项新工作将用于分子动力学模拟的 OpenMD 包带到了在线笔记本电脑上,供每个人免费运行非常强大的 GPU。我尝试了一下,并在这里展示了它是如何工作的,讨论了它在教育和研究中的潜在用途。

一种蛋白质在 Google Colab 笔记本中水合并参数化,准备开始分子动力学模拟。图片作者。

你最*肯定听说过在 AlphaFold、CASP 等的背景下“预测蛋白质的结构”。如果不是,但这是你感兴趣的,那么不要错过我在 TDS : deep dive 到 AF 中的三个故事,在 Google Colab 笔记本上运行, Deepmind 与 EBI 合作预测所有蛋白质的结构,以及一个我自己基于最*的学术预印本运行的实际例子。嗯,所有这些关于预测蛋白质结构的事情都属于一个更大的学科领域,这个学科试图用计算机模拟物理、化学和分子生物学。根据科学的确切领域,有些称之为分子建模,有些称之为结构生物信息学,有些称之为计算结构生物学,有些称之为化学信息学,等等。你明白了。我们在这里称之为分子建模,我们将把蛋白质作为研究系统。

我们科学家正在经历的 AlphaFold 宣传中最酷的事情之一与谷歌 Colab 笔记本实现的非常广泛的可访问性有关。你甚至可以在手机上运行蛋白质结构预测,因为计算本身是在谷歌免费提供的在线图形处理器上进行的。正如我在我的故事中讨论的,这极大地民主化了访问,现在很多人都在全职运行这些笔记本,正如 twits 所示。

现在,来自美国加州大学河滨分校的研究人员推出了一套新的谷歌 Colab 笔记本电脑,便于运行另一种对蛋白质分子建模至关重要的关键任务:分子动力学模拟。

简介——如果你已经了解 MD 模拟,继续下一个标题

分子动力学模拟(简称 MD)是在给定尺度下模拟物质行为的一系列计算方法。与本故事最相关的 MD 模拟类型是,分子系统由所有原子描述,将每个原子视为通过弹簧连接到其他原子的球体,并经历与系统中所有其他原子的各种相互作用。对于蛋白质的模拟,“分子系统”最有可能是被水包围的蛋白质,但它也可以包括其他分子,如核酸、结合蛋白质的药物,甚至生物膜或膜模拟物的碎片。

总结一下整个物理过程本身,在 MD 模拟中,在温度槽和给定压力的振动下,原子的位置随着时间的推移随着电势(“力场”)而演变,该电势确定所有可能的相互作用的强度和*衡位置。原子位置的这种演变产生了一种叫做轨迹的电影,它有望代表分子系统能够经历的真实运动。

分子运动的轨迹或电影建立得非常慢,因为在每个时间点,程序需要计算所有原子上的力,然后随着时间传播这些力,但是由于一些力相当强,因此运动积分的时间间隔(“时间步长”)非常非常小。举一些数字来说,时间步长通常在 1-2 飞秒(1E-15s)的数量级,但我们感兴趣的是纳秒、微秒甚至毫秒时间尺度内发生的运动。这意味着我们需要整合这些步骤(即计算力并相应地传播原子的位置)数百万到数十亿次。

你可以想象,随着这些年来更强大的处理器的出现,MD 模拟运行得越来越快,然而今天具有全原子描述的正常 MD 模拟最多达到 10-100 微秒左右。大约 10 年来,GPU 提供了用于运行这些 MD 模拟的大部分计算机能力。尽管运行它们并不是非常困难,至少在研究环境中不是如此,但来自加州的这组研究人员开发了一个 Colab 笔记本电脑,在谷歌的 GPU 上运行 MD 模拟,这是一件好事,因为在许多不发达国家,一个 GPU 可以相当于几个月的博士工资。甚至对于富裕国家来说,在 Google Colab 笔记本中运行 MD 模拟的可能性使这一重要工具在教育层面上变得容易使用。

用于蛋白质分子动力学模拟的造雨笔记本

在 moto 为大家准备的基于云的分子模拟下,软件造雨(这里有,不知道为什么取这个名字)包括三个笔记本:

  • AMBER:用(目前)两个可用的 AMBER 力场之一来参数化一个分子系统,并运行它的 MD 模拟。
  • CHARMM:用 CHARMM-GUI 的 solution builder(本身就是一个极好的工具)参数化一个分子系统,然后运行它的 MD 模拟。
  • AlphaFold2+MD:使用 MMseqs2 运行 alpha fold 2(见本故事)并立即用 AMBER 参数化并运行 MD 模拟。

一份关于造雨 ( 同行评审论文此处)的预印本解释说,该软件背后的两个关键动机是,通过在课程中使用这种方便、简单、廉价的现代技术,为学生提供一种了解更多蛋白质的方法,以及使低收入研究能够进行接*当前标准要求的分子动力学模拟。根据我所做的测试,我认为他们已经很好地完成了他们的主要目标,至少对于小型系统来说是这样。在接下来的部分中,我将指导您完成我所做的测试。

但在此之前,关于这些笔记本的一些细节(参见预印本-现在的论文 -和 github 页面了解所有细节):

  • 首先,分子动力学模拟使用 OpenMM 软件进行分子模拟,该软件在社区中已经很成熟。
  • 第二,笔记本包括常规 MD 模拟的所有常规任务的步骤,从开始时最小化势能,到将系统*衡到所需温度,然后运行实际的所谓“生产”模拟。
  • 第三,笔记本将输出轨迹、日志文件和重启文件写入用户的 Google Drive。当然,这有助于方便地存储文件,直到它们被下载,但这样做的主要优点是,它允许用户在谷歌提供的 12 或 24 小时连续运行时间到期后重新启动模拟。没有这一点,生产模拟将非常局限于他们的第一部分。但是,通过使用重启文件,用户可以创建长轨迹,就像他们在任何常规 HPC 系统中所做的那样,这些系统也有时间限制。
  • 第四,笔记本包括创建的系统和产生的轨迹的浏览器内可视化。我从下面的实际测试中向你展示了这一点。
  • 最后,笔记本电脑包括一套非常丰富的分析,用户可以在下载数据进行更多的特别测量之前对轨迹进行分析。在我动手操作的例子快结束时,我向你们展示了其中的一些分析。

动手操作:在水中建立蛋白质系统并将其参数化

我想尝试一种小蛋白,以适应几个小时内的大量生产。我可能会用更大的蛋白质,因为它跑得比预期的要快!

我使用了 PDB 1L2Y,这是一种色氨酸笼小蛋白的实验确定的结构。利用琥珀笔记本,我建立了一个系统,将蛋白质嵌入到一个足够大的水分子盒中,然后用 ff19 力场参数化蛋白质,用 OPC 力场参数化水分子(要了解更多力场的艺术状态,请参见我今年发表的这篇开放访问论文)。

准备就绪后,笔记本会向您显示准备就绪的系统:

将蛋白质 1L2Y 置于水箱中并用 AMBER19 力场参数化的造雨笔记本,准备开始模拟。作者截图。

请注意,在上图中,水分子没有单独显示,而是显示为一个便于可视化的斑点。请记住,每个水分子实际上是用它的所有原子来描述的,所以有成千上万个原子。你可以在 SYS.pdb 中看到这个,我在这里下载并在 pymol 中打开了它:

启动系统,下载到我的电脑上,用 pymol 可视化。作者截图。

最小化和*衡

运行 MD 模拟之前的一个关键阶段是消除来自结构和/或力场缺陷的任何能量。这叫做最小化,由笔记本直接处理。

在最小化之后,系统必须缓慢地*衡到将进行模拟的温度。这叫做*衡。

笔记本在一个模块中进行最小化和*衡。我让程序把系统温度调到 363 K,也就是 90 摄氏度左右;这是相当高的,但我想促进议案,即使不是很现实。在这个例子中,最小化+*衡的这个阶段花费了大约 10 分钟;在我看来,这太苛刻了,对于更大的蛋白质来说肯定也太苛刻了;但是用户可以在运行模块之前修改所有这些参数。

最小化加*衡程序的日志文件,该程序花费了大约 10 分钟,并带有一个用于演示目的的快速协议。作者图。

运行 10 ns 的生产模拟

一旦系统达到*衡,就可以开始生产模拟。这里我要求笔记本只运行 10 纳秒,即 2 fs 的 500 万时间步长。我告诉它每 50000 步记录一次数据,这导致我的轨迹有 100 帧。

笔记本显示模拟运行时的主日志,直到模拟结束(或分配的时间到期,在这种情况下,您必须重新连接并从最后一组重新启动文件重新启动):

我在 Colab 笔记本上运行的 10 ns 长的模拟花了大约 30 分钟才完成。每天约 475 ns 的通量非常符合小蛋白的当前标准,因为 10 微秒的模拟需要 21 天才能完成,即 42 x 12 小时的跨度。作者图。

在笔记本电脑内可视化生成的模拟结果

现在是有趣的部分。造雨的笔记本整合了 3dmol ,一个直接在浏览器中运行的分子图形插件。只需点击一下,你就可以将轨迹加载到 3dmol 中,然后像播放电影一样播放。在高温下,色氨酸笼试图打开:

检查这个视频,看看模拟产生了什么:一个 MD“轨迹”,这是一种基于现实物理学的电影,由选定的力场建模,蛋白质可能经历的运动。请注意,这一模拟只有 10 ns 长,仅用于演示目的,而对于这种大小的蛋白质,当前标准的范围是 5 到 10 微秒。作者制作的视频。

内置分析

继续有趣的部分,正如我所料,笔记本带来了一套内置的分析,一些非常基本(但对初始分析非常有用),如这些图,测量随着时间的推移与初始结构和回转半径的偏差,或残差波动:

线性类型的分析:起始结构的 RMSD 对时间(左,由于高温快速增加),回转半径对时间(中间,注意尽管 RMSD 增加,蛋白质仍然保持紧密),RMSF 对蛋白质残基(右,注意末端增加了灵活性,而核心仍然保持非常紧密)。请注意,这些图是在 10 ns 长的轨迹上,仅用于演示目的,但是这个模拟长度对于当前标准来说太短了,对于这个大小的蛋白质,在几天的模拟之后,当前标准为大约 5-10 微秒。作者创作的图形。

然后还包括一些更复杂的分析。一种是跟踪轨迹的所有帧之间的 RMSD,这有助于识别可能相互转换的不同状态。第二,对齐轨迹的前两个主要部分,这提供了一种方式来查看运动如何耦合到结构的更大规模的变化中。第三,原子波动的交叉相关性,用于识别机械偶联的蛋白质区域:

2D 类型的分析:每一帧和所有其他帧之间的 RMSD(左),主成分投影(中心,其中每个点是轨迹的一帧),以及原子波动的交叉相关(右,其中绿色点表示以反相关方式移动的残基,品红色点表示以相关方式移动的残基)。请注意,这些图位于 10 ns 长的轨迹上,仅用于演示目的,但对于当前标准来说,该模拟长度太短,对于这种大小的蛋白质,经过几天的模拟后,其长度约为 5-10 微秒。作者创作的图形。

吞吐量和潜在用例

这个系统很小,只有 11000 个原子,因为我研究的蛋白质很小。它每天运行大约 475 ns,这与您在私有 GPU 上所能获得的一致。如果您想模拟这个系统总共 10 微秒,您将需要 21 天来完成,这意味着 42 x 12 小时长的作业。这完全符合当前的标准和生产能力。

对于更大的系统,笔记本的一个缺点是不能并行运行多个 GPU。小型系统无法从并行化中获益,但大型系统可以。确切的限制取决于代码和架构。从这些结果中,我可以猜测,在 20 到 50,000 个原子之间,运行将是正常的,并且在笔记本电脑之外的单个 GPU 上也是有效的。但是很有可能,大于 10 万个原子的系统,也可能是范围从 5 万到 10 万个原子的系统,将遭受这个问题;也就是说,它们可以在笔记本电脑之外运行,使用 2 个、4 个或更多的 GPU 来提高速度,但这在笔记本电脑上是不可能的。

总之,我想象了一个完全可行的场景,资金有限的实验室成员可以在小型系统上运行高效的 MD 模拟,每个人都使用自己的 Google 帐户。对于更大的系统,在将计算提交给本地 GPU 或 HPC 资源之前,笔记本电脑可能仍然足以实现*衡和短期测试。

同样重要的是要记住造雨的笔记本也作为概念证明,表明 MD 模拟在云中是可能的。这些笔记本完全有可能发展成更先进的版本,例如支持先进的采样方法,允许更快地探索分子运动。

最后,对于学习 MD 模拟的学生来说,这些笔记本是极好的。我记得 20 年前,为了运行一个模拟程序,我饱受 Linux 命令和糟糕界面的折磨。笔记本电脑提供了简单性,但在完全控制的情况下,不会损害学习的潜力,因为所有的代码和脚本都是可见的,甚至可以修改。

总之,我当然希望作者继续开发造雨。它有潜力成为真正的教育工具,至少在某些研究领域是如此。

链接和阅读

造雨:基于云的每个人的分子模拟https://zenodo.org/record/5196783#.YRqNNn6xXIU

被接受的造雨论文:https://pubs.acs.org/doi/abs/10.1021/acs.jcim.1c00998

关联的 Google Colab 笔记本:https://Colab . research . Google . com/github/pablo-arantes/Making-it-rain/blob/main/

为了了解更多关于分子动力学模拟的知识,我向你推荐这个故事以及媒体用户 Ankit Agrawal 的其他故事。这里还有一个更广泛的介绍。用户卡梅隆·麦克尔弗雷什也有一些很棒的笔记。

要了解 AlphaFold2 的更多信息,请查看这个故事,然后是这个故事这个故事,每一个故事都涵盖了它的不同方面。

喜欢这篇文章,想给我提示?[Paypal]-谢谢!

我是一个自然、科学、技术、编程和 DIY 爱好者。生物技术专家和化学家,在潮湿的实验室和计算机里。我写我广泛兴趣范围内的一切。查看我的 列表 了解更多故事。 成为媒介会员 访问我和其他作家的所有故事, 订阅通过邮件获取我的新故事 (*台原创附属链接)。

RStudio 的新版本

原文:https://towardsdatascience.com/new-release-of-rstudio-de999fc7559c?source=collection_archive---------12-----------------------

布鲁斯·马斯在 Unsplash 上的照片

概述 RStudio 1.4 最有趣的特性

R 编程使用最广泛的 IDE R studio 刚刚变得更好。你应该现在更新它。

本周为 R 用户带来了一个好消息——R studio预览版发布了 a major,新版本 1.4 。从 1.2 版本开始,RStudio 就以一种花的名字来命名它的版本。1.4 版本叫“蜡海棠。”它带来了一些非常酷的特性,比如代码可读性、文档编写和 Python 对象的集成

装置

让我们来看看一些亮点功能。

托德·克雷文在 Unsplash 上拍摄的照片

1)彩虹括号

通常在编写大块代码时,您会忘记嵌套的括号。有时,当您的代码有十对括号,并且您得到一个“不匹配的括号”错误,您经常求助于多个缩进来调试您的代码。RStudio 最后介绍了“彩虹括号。”就代码可读性增强而言,我认为这是这个版本中最好的特性。

现在,匹配对将以相同的颜色突出显示,如下图所示。随着您添加更多括号,括号甚至会动态改变颜色页面显示了如何激活该功能。

显示 RStudio 1.4 的彩虹括号选项的示例代码

如果你讨厌彩虹,对默认的配色方案不满意,你可以按照这篇文章来创建你的自定义主题。

照片由大卫·克洛德Unsplash 上拍摄

2)改进的 Python 集成

数据科学领域主要分为 Python 和 R,前者是多元化的领导者。我有 Python 背景,喜欢 Jupyter。我花了相当长的时间来熟悉 R 数据帧的分析和可视化。我也嫉妒 RStudio 查看数据帧的便捷性(可以方便地排序和过滤)。

RStudio 1.4 为 Python 支持引入了几个新增功能:

I)选择 Python 解释器

现在,您可以从系统上安装的解释器中选择默认的 Python 解释器来编译在 RStudio 中编写的 Python 代码。然而,关于如何做到这一点的文档并不充分。我遇到了这个问题。

ii)环境窗格中的 Python 支持

与 R 类似,环境窗格现在可以显示 Python 变量、对象和函数的内容。下面,你可以看到显示变量内容的环境窗格(常量、列表、字典等。)、python 模块和用户定义的函数(如“square”)。

显示 RStudio 1.4 中 Python 对象的环境窗格。

iii)查看 Python 对象(也包括熊猫数据帧)

在 R 中,你可以查看对象(列表、向量、数据帧等。)使用View(object)。同样,现在也可以查看 Python 对象。愿意使用 RStudio 进行数据分析/科学研究的 Python 用户可以欣喜地发现,他们现在还可以在 RStudio 中可视化熊猫数据帧。下图显示了View(result)的输出,其中“结果”是上面创建的列表。还显示了变量的数据类型(tuple、list、int、str 等。).

在 RStudio 1.4 中查看 Python 对象。

iv)渲染 Matplotlib 和 Seaborn 图

对于像我这样的顽固分子来说,这是个好消息。

您现在可以在 RStudio 中可视化 Matplotlib 生成的绘图(目前仅支持非交互式绘图)。人们还可以可视化 Seaborn 生成的图 (Seaborn 是一个数据可视化库,它在 Matplotlib 之上提供了一个 API)。

不幸的是,由于这个问题,我暂时无法在 RStudio 中加载这些模块。你可以在这里查看样本代码和图

斯蒂夫·约翰森Unsplash 上拍照

3)新的命令面板

引入了一个名为 命令面板 的新功能,旨在快速改进命令、选项、帮助、设置、等的键盘可访问性

它的名字来源于一位艺术家基于其多用途性质的调色板。可以使用组合键 ctrl + shift + P 弹出。默认选项如下图所示。您可以看到它们主要与创建新的空白文件有关。

如何在默认结果之外进行搜索?

您可以键入查询(由空格分隔的一个或多个单词)。假设你需要函数方面的帮助。下面显示了您在键入“Function”作为搜索关键字时得到的选项。几个“设置”弹出,你可以切换“开”或“关”这是一个非常方便的功能,不需要通过工具或菜单选项毫无头绪地搜索。

在命令调板中搜索关键字“函数”的结果。

下图显示了搜索关键字“数据”的结果被标记为“帮助”的搜索结果会在浏览器中被点击打开,带你到相应的帮助页面(大部分是 pdf 格式)。

在命令调板中搜索关键字“数据”的结果。

照片由埃里克·普劳泽Unsplash 上拍摄

IDE 工作台中的多个源列

Terminal 和 iTerm2 用户可能已经使用了在单独的窗口中垂直分割工作区的特性。它避免了不断切换标签,允许比较几个相邻的文件,代码,数据等。

现在,RStudio 允许您类似地配置您的工作区窗口,最多有三个额外的源列(您可以在那里打开脚本)。在比较两个或多个代码或引用另一个代码时,它非常有用。下面我展示了 RStudio 工作区在添加了两个额外的列后的样子。

注意:您将只有一个控制台,它将显示您选择(在里面单击)并执行的列的输出。所选列(包含下图中的first_notebook.R)用一条细的蓝色虚线突出显示。图像中的原始列包含“结果”窗口。任何额外的列都可以通过关闭其中的所有文件标签来关闭。

RStudio 工作区有两个额外的列,分别包含 Python 和 R 脚本。

图片由 Taras ShypkaUnsplash 上拍摄

5)新的可视化降价编辑模式

这是一个巨大的特点,应该有一个专门的职位。对于在 RStudio 工作区中创建格式良好的文档和文章来说,它非常方便。新的编辑模式引入了几个新功能,包括:

  • 实时拼写检查
  • 插入表格、超链接、代码块、等。文档中的
  • 引用/参考支持来自 Zotero、Crossref、PubMed、enabled-search 使用 DOI、titles 等多个书目源。
  • 能够编写 LaTeX 方程式、脚注、LaTeX 式交叉引用到图、方程式、节、小节等。在减价文件中

点击查看全新视觉降价的全面亮点。

在 RStudio 1.4 的 markdown 编辑器中准备的示例文档。

结论

RStudio 版是预览版。对于院士和其他经常准备科学和技术报告的人来说,新的可视化 markdown 编辑模式是一个福音。Matplotlib 和 Seaborn 的集成提高了数据可视化能力,这为主要使用 Python 进行数据可视化的数据分析师增加了 RStudio 流形的有用性。这个版本可能会吸引许多像我一样经常从事数据分析和建模工作的 Python 爱好者。发布说明的完整列表可从这里获得。

2022 Tableau 桌面专家认证考试复习(新模式)

原文:https://towardsdatascience.com/new-tableau-desktop-specialist-certification-exam-overview-b482a2f373fb?source=collection_archive---------5-----------------------

讨论 2021 年 10 月后考试的最新变化,以及如何准备考试

当你看到这篇文章时,很可能你正在试图寻找一些评论或帖子,关于 2021 年 10 月后最新的 Tableau 桌面认证考试有什么变化,考试看起来如何,以及考虑到新的变化,你应该如何准备考试。

别担心,我也经历过你的处境!我刚刚以不错的分数(903/1000)通过了考试,很乐意分享我对考试最新变化的评论,以及我如何准备考试的旅程。让我们开始吧!

Unsplash 上由 Carlos Muza 拍摄的照片

什么是 Tableau 桌面专家认证考试?

在详细介绍考试以及如何准备考试之前,我们先来了解一些关于认证本身的基本介绍。Tableau 为人们提供了几个证书来展示他们在 Tableau 方面的知识,Tableau 是各种公司和组织使用的最流行的可视化工具之一。在他们现有的认证中, Tableau 桌面专家认证是最基础的,测试的是 Tableau 桌面的基本产品知识。

要通过考试,您需要在 40 道已评分的选择题中获得至少 750 分(满分为 1000 分)(注:考试中总共有 45 道题,其中 5 道未评分,但是您不知道哪 5 道未评分)。与其他一些更高级的 Tableau 认证相比,桌面专家认证没有截止日期,因此您不必太担心每两三年更新一次。

Tableau 桌面专家诉 s. Tableau 认证数据分析师

当你第一次开始考虑获得 Tableau 认证时,你可能会遇到另一个同样关注 Tableau 桌面技能集的认证选项— Tableau 认证数据分析师。事实上,这个认证是几个月前新推出的,现在仍处于测试阶段。从以下角度来看,它被视为更高级别的认证:

  1. 概念覆盖:如果你对比一下专员数据分析师的备考指南,你会发现数据分析师认证考试覆盖了一些更高级的主题,在理解和应用方面更深入。例如,数据分析师考试将涉及 tableau 准备(用于数据准备)、各种 LOD 计算概念等主题,并且还将涉及 Tableau 服务器(或 Tableau Online)方面的概念,这在专家考试中没有涉及。
  2. 考试形式:对于专家考试,随着最新的更新,它现在是纯粹基于理论的 MCQs,没有实践问题,而对于数据分析师考试,您将有一个实践实验室环节。相应地,由于数据分析师考试的额外覆盖范围,两种考试的持续时间也有所不同(专家考试为 60 分钟,数据分析师考试为 150 分钟)。两次考试的及格分数相同(750/1500),并通过 Pearson Vue *台进行。
  3. 经验水*:对于 tableau 专员考试,建议你至少有~3 个月的 Tableau 使用经验。在数据分析师考试的情况下,鉴于它涵盖了更多的概念和更多的细节,推荐的 tableau 相关经验将是> 6 个月。
  4. 职称有效期:最后但同样重要的是,值得一提的是,专家认证没有有效期,而数据分析师职称的有效期仅为 2 年,因为这是一种更高级别的认证。

为什么我最后会去考 Tableau 桌面专家认证?

现在你知道了这两种认证的区别,但是你应该选择哪一种呢?就我而言,我选择专家认证是出于以下考虑。

首先,我在 Tableau 方面没有丰富的经验,甚至一般来说也没有丰富的可视化经验,因为我从 2021 年 9 月才开始从事 Tableau 相关的工作——到目前为止,我在 Tableau 方面已经有大约 3 个月的经验了。此外,当我在 2 个月前考虑采用哪种认证时,Tableau 正在进行一些重要的更改(我将在下一节中更详细地介绍),他们将在 2021 年 10 月底之前淘汰 Tableau 桌面认证助理(对于新手来说,你可以将它视为旧版本的数据分析师认证)。所以对我来说,考虑到所有正在发生的变化和我在 Tableau 有限的经验,选择专家似乎是一个更安全的选择。

说到这里,如果你真的对 Tableau 很认真,或者你打算在日常工作中密集使用它,那么成为一名认证的 Tableau 数据分析师肯定会为你的个人资料增加更多的权重。然而,由于数据分析师认证考试仍然很新(现在仍处于 beta 测试阶段),您可能需要花费更多精力在社区中查找相关信息或指南,以更有效地准备考试。如果你刚刚开始 Tableau 的旅程,或者刚刚开始寻找 Tableau 相关的入门级职业机会,也许专科认证是一个不错的选择,可以作为第一步建立一个良好的基础。

最新的 Tableau 桌面专员认证考试有哪些变化?

正如我刚才提到的,Tableau 桌面专家认证考试有一些新的调整。这一部分将有助于你在考试前就开始准备旧的考试指南,但现在你必须参加最新的考试。这些变化概述如下:

  1. 考试形式:旧版考试中,既有动手题,也有理论题。对于动手问题,这意味着您将获得一些数据集,并使用 Tableau desktop 来操作数据并获得正确的答案。然而,在最新的版本中,不再有的动手问题,取而代之的是更多基于知识的问题。
  2. Tableau 桌面/Tableau 用户手册的可访问性:由于现在的考试是纯理论考试,在考试期间将无法再访问旧考试中提供的 Tableau 桌面或互联网。对我来说,这是最重要的变化之一,因为你准备考试的方式可能会发生很大的变化,这取决于你是否能接触到实际的软件或用户手册。有了 Tableau 桌面软件,你不需要太担心 Tableau 格式中的详细菜单选项,因为你可以方便地检查它,但现在你必须记住这些东西。
  3. 主题覆盖:虽然主题覆盖没有大的变化,但仍有一些小的调整。比如大纲里新加了 关系 v.s. join 这个题目,在实际考试中也考的相当频繁。再比如现在有了 动画 的话题,这也是以前没有的。简而言之,请始终参考最新的考试指南以了解最新考试中涵盖的主题。

虽然我之前没有参加过旧版的考试,但我个人对这些变化的感受是,对于 Tableau 经验较少的人来说,难度水*有所增加。对于你在 Tableau Desktop 中探索所知道的事情,比如如何以不同的方式改变可视化工具提示的字体颜色,现在你必须记住确切的选项才能得到分数。下一节我会分享一些我的备考经验。

如何准备考试?

1.通读 考试备考指南

这可能是你需要仔细阅读的最重要的文件。不管你有没有 Tableau 的经验,我都会建议你花点时间去了解考试中涉及到的关键知识点是什么。在你准备的过程中,你最好不时地重温一下这篇文章,在你所学的知识和本指南中列出的知识点之间建立联系。事实上,如果你能够向他人清楚地解释本指南中的每一项,详细说明大部分概念的内容、方式和原因,那么总体来说,你的状态就很好。

2。学习/复习 Tableau 知识

现在你已经知道考试内容了,是时候复习了!在这个阶段,你学习(或重温)Tableau 的方式实际上取决于你当前的知识水*和你的学习偏好。

  • 对于有经验的 Tableau 桌面开发者:

如果你已经是一个非常有经验的 Tableau 开发人员,拥有多年的 Tableau 经验,并且你参加考试只是为了更新你的认证,或者为潜在的职业机会建立你的简历,你可以在这一步花费最少的时间。也许你可以再看一遍备考指南,只关注那些你需要记忆的部分。在这之后,你可以直接参加网上的模拟考试,检查你是否真的准备好了以后的考试。

  • 对于刚接触 Tableau 的人(< 3 个月经验)

另一方面,如果你像我一样,几个月前刚刚开始 Tableau 之旅,也许以更结构化的方式学习概念是一个好主意。以下是几个你可以考虑的选项:

  1. 画面训练教材(免费!) : 事实上,如果你不想在培训上花额外的钱,Tableau 为你准备了很多资源,而且是免费的!如果您更喜欢通过阅读博客来学习,那么 Tableau 知识库页面提供了您通过考试所需的所有信息,您可以简单地搜索备考指南中列出的相关主题,并在遵循其中一些示例的同时学习相关概念。如果你是一个更加视觉化的人,也有免费的培训视频供你浏览,其中大部分相关主题都包含在 Creator 部分。
  2. Udemy Tableau 培训课程(20-200 新元) : 这是我选择的选项。Udemy 中有大量的 Tableau 培训课程,专门设计用于涵盖备考指南中概述的相关主题。以下是一些关于如何在众多课程中选择合适课程的建议:
  • 检查课程上次更新的时间。鉴于最*的考试变化,这一点尤为重要。典型地,一个好的课程教师总是会根据最新的变化相应地更新他们的课程,并且他们倾向于更频繁地发布公告来解释他/她的课程中已经更新的内容。不要进入那些最后更新日期在 2020 年的课程。
  • 查看最新的学生反馈和评分。尽管听起来像是理所当然的,但选择顶级课程通常不是一个坏主意。我个人会对我喜欢的课程给予积极的评价和良好的评级。
  • 查看课程大纲和教学大纲。起初,我报了几门不同的课程,因为我不知道该选哪一门。最后,我选择了更符合考试指南的课程,也就是说,教师将在考试准备指南中涵盖每个单独的主题,并在每个视频的标题中明确标记这些主题。我发现这对于备考更有效,如果以后你想复习某些主题,你可以快速找到相关的视频。还有一些其他教师遵循另一种教学风格,他们会提出几个项目,并试图涵盖整个项目的相关主题。我发现这种方法有点松散,有些主题最终可能没有被涵盖。
  • 选择合适的时间购买!如果您是 Udemy 的新用户,我们会经常推出促销活动,您可以花更少的钱购买课程(高达 90%以上的折扣!).所以,一旦你决定了要做的事情,也要确保选择正确的购买时机。

3。Tableau 官方培训课程(120 美元) : Tableau 确实提供这种官方培训用于自学。我个人并没有把这个当回事,但是从那些主要以此作为备考参考的人那里看到了一些积极的反馈。如果你走过这条路,请在评论中分享你的经历吧!

3.尝试一些实际的测试

现在您已经完成了培训,是时候评估您是否为考试做好准备了!实际上,在备考指南的最后附有 3 个样题,但是做一些实际的测试可能会帮助你在一次通过考试中获得更多的信心。进行模拟测试的另一个好处是,您可以识别出一些以前没有注意到的“盲点”,这样您就可以及时重温这些概念。

当你在谷歌上搜索“Tableau 桌面专家实践考试”或类似术语时,有大量的资源。就我而言,我会在 Udemy *台上进行一些模拟测试,因为用户的评价似乎相当积极。这里类似的选择 Udemy 课程的指导方针也适用于模拟考试,你应该寻找那些最*更新的考试,考虑到考试形式的最新变化。根据我在考试中的实际经验,我想说这些实践测试真的很有帮助,至少他们设置问题的方式和他们关注的主题与考试非常匹配。

4。动手 Tableau 软件

这一点也许只适用于那些还不熟悉 Tableau 的人。如果你现在在日常工作中使用 Tableau,我会建议你对一路上遇到的问题做笔记。尝试更熟悉 Tableau 桌面界面和不同的菜单选项。如果可能的话,你可以找出是否有多种方式来完成 Tableau 中的同一个任务。例如,如果你想改变工具提示的字体,有什么选择?在什么类型的图表中你可以改变标记的形状?你在探索这些东西的时候动手经验越多,你在备考的时候就越轻松。

考试当天的一些小技巧

  • 考试前完成系统测试。 Tableau 现在与培生 VUE 合作提供测试。一旦您安排了考试,您将收到一封确认电子邮件,其中有一个链接要求您测试您的系统。只要按照说明完成所有的测试,你就没事了。在考试当天,您将经历与您在系统测试中所经历的相同的过程来开始考试。
  • 确保您遵循了确认电子邮件中的指南。考试当天,确保你独自一人在一个安静的房间里,桌面清晰,你只能带着你的笔记本电脑(带网络摄像头功能测试)、电话和政府发放的带照片的身份证。确保您的网络运行良好——尽管如果您遇到意外的网络问题,您可以联系监督者,尽可能首先确保一个可靠的网络
  • 提前 30 分钟登录考试,开始签到流程,以便进行故障排除。基本上,你需要用手机拍下你周围的环境,然后监考人会打电话给你(通过你之前测试过的软件)来澄清他们是否有任何进一步的疑问。对我来说,这个过程在实际考试当天花了大约 15 分钟完成。如果签到过程一切顺利,您实际上可以提前开始考试,尽管给出的总时间仍然是 60 分钟来完成考试。
  • 标出你不确定的问题,稍后再来看。在考试界面中,您可以方便地标记问题以便日后重温。这样做还可以帮助你避免浪费太多时间去思考某些问题,因为考虑到我们有 45 个问题要完成,60 分钟并不算长。就我而言,在第一遍之后,我只剩下大约 15 分钟的时间,在剩下的时间里,我可以专注于之前我不太确定的问题。

我对考试的总体感受和想法

总的来说,我想说如果你对我们之前谈到的实践测试感到满意,你应该可以通过考试。说到这里,我要说实际考试中的问题是以一种需要对相关概念有一些深入理解的方式设计的,你必须非常熟悉 Tableau 使用的术语。例如,当他们在 Tableau 中测试与关系/连接特性相关的概念时,他们不会仅仅列出用户手册中列出的原始语句。相反,他们会改写句子,或者用一些例子来展示 relationship 和 join 之间的区别,并让你确定哪些是正确的答案。

对于我在考试中的情况,在问的 45 个问题中,我在第一遍复习中标记了大约 12 到 15 个问题。在第二遍中,我设法决定了大多数标记问题排除方法的答案,但仍然有 2 到 3 个问题我没有真正在我的复习中覆盖,所以我必须在最后对这些问题做出最好的猜测。幸运的是,你只需要在 1000 分中取得 750 分就可以通过考试,所以你有犯错误的空间。但是,如果你真的想一次通过考试,事先做充分的准备会让你在考试当天更有信心。

差不多就是这样!我希望这篇文章对你准备更新格式的 Tableau 桌面专家认证考试有所帮助。我相信你会在这次旅程中学到很多,同时在 Tableau 中变得更有知识。如果您对此有任何问题,请随时添加评论,或者您愿意分享一些自己的经验。祝你考试顺利!

关于作者

我是 TJ,我喜欢学习数据分析相关的话题,并通过博客分享知识。如果你正在考虑加入中等会员,你可以在这里使用我的推荐链接:https://medium.com/@tianjie1112/membership

看看我的其他一些帖子,也许你会感兴趣!

使用 PyCaret 创建新的时间序列

原文:https://towardsdatascience.com/new-time-series-with-pycaret-4e8ce347556a?source=collection_archive---------11-----------------------

测试版教程-轻松进行预测

Icons8 团队un splash【1】上拍摄的照片。

目录

  1. 介绍
  2. 设置、比较、调整和混合模型
  3. 生产模型
  4. 摘要
  5. 参考

介绍

坦率地说,即使看起来很简单,时间序列算法通常也很难处理。py caret【2】通过自动化建立和比较时间序列的模型过程,减轻了许多单调和混乱的工作。您可以更进一步,使用这个 Python 库生产您选择的模型。然而,通过调整不同的参数,您仍然可以在库中拥有自己的输入和自主权。话虽如此,让我们更深入地研究一个用例,以说明使用下面这个独特的工具和库进行预测是多么简单。

设置、比较、调整和混合模型

格伦·卡斯滕斯-彼得斯在Unsplash【3】上拍摄的照片。

PyCaret 似乎有无数的模型可供选择,也可以进行比较。一些,老实说我甚至没有听说过,以及一些更流行和可靠的像 ARIMA ( 自回归综合移动*均线)模型。

以下是一些您可以尝试的时间序列模型名称,重申一下,还有更多:

  • 季节性天真预测者
  • 指数*滑法
  • ARIMA
  • ARIMA 汽车
  • 多项式趋势预测器
  • k 邻居 w/ Cond。去季节化和去趋势化
  • 线性 w/ Cond。去季节化和去趋势化
  • 弹性网 w/ Cond。去季节化和去趋势化
  • 乘坐 w/ Cond。去季节化和去趋势化
  • 带导管的套索网。去季节化和去趋势化
  • 极端梯度推进 w/ Cond。去季节化和去趋势化

如您所见,有许多模型可供您使用和比较,因此您不必做任何繁琐的工作,例如导入一长串不同的库。你可能还会发现一些你还没有尝试过的新方法。

下面是使用 PyCaret 进行简单时间序列预测的简单教程:

# Code is edited and reorganized from example source:
[https://nbviewer.org/github/pycaret/pycaret/blob/time_series_beta/time_series_101.ipynb](https://nbviewer.org/github/pycaret/pycaret/blob/time_series_beta/time_series_101.ipynb) [4]ex = TimeSeriesExperiment()
ex.setup(data=y, fh=fh, fold=fold, session_id=100)y_train = ex.get_config("y_train")
y_test = ex.get_config("y_test")best_baseline_models = ex.compare_models(fold=fold, sort='MAE', n_select=10)compare_metrics = ex.pull()best_tuned_models = [ex.tune_model(model) for model in best_baseline_models]mean_blender = ex.blend_models(best_tuned_models, method='mean')y_predict = ex.predict_model(mean_blender)
ex.plot_model(estimator=mean_blender)

在上面的代码中,我们可以看到,在短短几行代码中,您可以比较几乎所有的时间序列模型,对它们进行调整,并将其混合以获得最佳结果。如果你想节省一些时间,你甚至可以在不调整或混合的情况下相当精确。另一个很棒的特性是从各种模型中提取指标,并并排查看它们。

总的来说,这一小块代码通常会占用您更多的笔记本空间,因此能够专注于 PyCaret 漂亮的可视化效果,而不是您不再需要处理的较小或不太重要的代码部分,这是一个好处。

生产模型

照片由巴格斯·赫纳万Unsplash【5】上拍摄。

现在,您已经测试了几个模型并比较了它们的指标,如本例中的 MAE(或任何其他指标,如 RMSE、MAPE、SMAPE 和 R2,以及运行模型所需的时间),您可以开始保存并加载您的模型以供将来使用。

首先,无论出于何种原因,您都会保存您选择的最佳模型。然后,您将在新的会话中加载模型,并预测新的数据。

保存您的模型

保存最终模型很容易。只需使用save_model函数,并对其进行命名,这样就可以为未来的预测/预报加载相同的名称或版本。

ex.save_model(final_model, "my_final_model")

加载您的模型

加载模型也很容易,您可以应用 predict 方法来查看您的预测与索引或第一列的关系。

ex_load = TimeSeriesExperiment()
loaded_model = ex_load.load_model("my_final_model")

使用更少的代码,您可以通过保存和加载新的、看不见的数据来生产您的模型。还有更多方法可以让你利用预测区间来定制 alphas。其他功能包括:

  • 窗口拆分
  • 扩展窗口
  • 滚动窗
  • 错误处理

最好从数据集入手,将这些代码应用到您的特定用例中,这样您就可以开始使用时间序列算法进行预测。

摘要

PyCaret 一直在更新,所以请确保每天或每周关注新功能。时间序列可能是不那么吸引人的数据科学问题,但它可能是公司利益相关者要求最多的问题。这真的取决于你,如果你正在与时间序列作斗争,那么这篇文章向你展示了如何,在短短几行代码,你可以比较,分析,并使用预测模型。

总结一下,我们了解到的情况如下:

* Setting Up, Comparing, Tuning, and Blending Models* Productionalize Model

我希望你觉得我的文章既有趣又有用。如果您同意或不同意这种学习和实施时间序列预测的方法,请随时在下面发表评论。为什么或为什么不?你认为你还可以使用哪些库或工具?这个库当然可以被进一步阐明,但是我希望我能够对困难的时间序列问题有所启发。感谢您的阅读!

我不属于这些公司中的任何一家。

请随时查看我的个人资料、 Matt Przybyla和其他文章,并通过以下链接订阅接收我的博客的电子邮件通知,或通过点击屏幕顶部的订阅图标 ,如果您有任何问题或意见,请在 LinkedIn 上联系我。

订阅链接:https://datascience2.medium.com/subscribe

参考

[1]图片由 Icons8 团队Unsplash 上拍摄,(2018)

2 Moez AliPyCaret 时间序列,(2021)

[3]Glenn Carstens-Peters 在 Unsplash 上拍摄的照片,(2019)

4 PyCaret,时间序列 Jupyter 笔记本示例,(2021)

[5]Bagus herna wan 在 Unsplash 上拍摄的照片,(2017)

使用数据可视化的新年祝福

原文:https://towardsdatascience.com/new-year-greetings-using-data-visualization-b0e25f2cb143?source=collection_archive---------41-----------------------

从 1 月 1 日开始变得兴奋

这篇文章是我给你的新年祝福。我有更简单的选择,用简单的短信和漂亮的话语祝你新年快乐,或者复制粘贴新年祝福图片。

然而,我想带着乐观和愉快的心情开始新的一年。所以这就是我是怎么走过来的

收集与新年愿望相关的数据

首先,我搜索了所有与新年愿望相关的关键词。我想出了这里显示的列表。

问候数据-作者图片

它的组织如下

  • 第一列是类别列,例如健康、家庭、专业、繁荣等。
  • 第二列包含相关类别中的问候语
  • 第三列是对应于每个问候的重要性的权重。这纯粹是主观的,但这是我观察到的总体趋势

现在,这里是我使用分析和一些惊人的数据可视化的问候。

使用辐射状树形图问候

让我们从辐射状树形图开始。这种类型的可视化的主要优点是它在形状上是放射状或圆形的。这允许压缩可视化中的大量信息。如你所见,我们的数据有大约 50 条文本。径向树将以圆形或放射状的方式很好地显示所有文本。

因此,这里是我对你的问候使用径向树可视化。所有的问候都安排得很好。看起来比标准的问候更好。

使用径向树的问候—作者图片

这看起来很棒,但我想让它更上一层楼。所以这是我的一个黑暗主题的问候。而且看起来优雅多了!!!

黑暗主题中使用辐射状树的问候——作者图片

太酷了。但是我意识到我没有使用体重栏中的数据。让我用一张旭日图来说明。

使用旭日图问候

当您想要利用圆形布局来显示大量文本,以及表示文本的重量或重要性时,旭日视觉效果非常有用

这是我用旭日可视化表达的问候。正如你所看到的,所有的问候都安排得很好,每个部分的厚度(也称为 burst)都与权重列相对应。所以健康的厚度或重要性最大,变化的厚度最小。当然,正如我刚才所说,这取决于每个人,但这是大势所趋。

使用旭日图问候—图片作者

正如我喜欢黑暗的主题,这里是旭日也在黑暗的主题。

黑暗主题中使用旭日图的问候—作者图片

直到现在都很好。我觉得我真的是真心祝福你。但是后来我意识到如果你不是垂直布局的粉丝会怎么样。所以这里是我的尝试,希望你在一个水*的可视化使用桑基图

使用桑基图问候

通常,桑基图用于表示流程。但是,如果您在数据中看到任何流动,您可以创新地使用它。在问候的数据中,你可以想到类别和问候之间的流程

这是我用桑基图表表达的问候。正如你将看到的,你不需要转动你的头来阅读它

使用桑基图问候—作者图片

所以,我的朋友们,这就是我以一篇文章的形式表达的问候。可视化有助于将大约 50 个单词的问候信息打包成好看的图像。如果没有这些视觉化的东西,就不可能用一种漂亮简洁的方式传达如此多的问候。

我认为我们带着乐观和愉快的心情开始了新的一年

额外资源

网站(全球资讯网的主机站)

你可以访问我的网站进行零编码分析。https://experiencedatascience.com

订阅每当我发布一个新的故事时,请及时通知我。

https://pranay-dave9.medium.com/subscribe

你也可以通过我的推荐链接加入 Medium。

https://pranay-dave9.medium.com/membership

https://www.youtube.com/c/DataScienceDemonstrated 的 YouTube 频道
这里是我的 Youtube 频道
的链接

新闻分类:用 TensorFlow 在 TPUs 上微调 RoBERTa

原文:https://towardsdatascience.com/news-category-classification-fine-tuning-roberta-on-tpus-with-tensorflow-f057c37b093?source=collection_archive---------6-----------------------

使用拥抱脸变形器的多类文本分类教程。

绝对视觉Unsplash 上拍摄的照片

在下游任务上微调大型预训练模型是自然语言处理中的常见做法。在本教程中,我们将使用预训练的 RoBERTa 模型来完成多类分类任务。

RoBERTa:由脸书 AI 开发的稳健优化的 BERT 预训练方法,通过修改关键超参数和在更大的语料库上进行预训练,对流行的 BERT 模型进行了改进。与普通的 BERT 相比,这提高了性能。

Hugging Face 的 transformers 库允许使用几行代码轻松部署各种 NLP 任务的预训练模型。有各种各样的 Auto Model 类,它们包装了预先训练好的模型,自动实现了常见下游任务所需的必要架构更改。此外,这些模型可以被转换为 Keras 模型,从而可以通过 Keras API 进行简单的训练。

在本教程中,我们将对托管在 Kaggle 上的新闻类别数据集上的 RoBERTa 进行微调,根据它们的标题和简短描述来预测新闻的类别。该数据集包含从 2012 年到 2018 年获得的 20 万条新闻标题。

以下公开 Colab 笔记本中有完整代码。

0.安装和导入依赖项

我们首先要安装变形金刚库,这可以通过pip install transformers轻松完成。

接下来,我们导入本教程剩余部分所需的库。

1.实例化 TPU

该模型已经使用 Colab free TPUs 进行了训练。TPUs 将允许我们更快地训练我们的模型,并且还允许我们使用更大的批量。要在 Colab 上启用 TPU,请点击“编辑”->“笔记本设置”,然后在“硬件加速器”字段中选择“TPU”。为了实例化 TPU 以便与 TensorFlow 一起使用,我们需要运行以下代码

为了充分利用 TPU 的潜力,我们设置了一个批量大小,它是集群中 TPU 数量的倍数。然后我们只需要在tpu_strategy.scope()下实例化我们的模型。

2.数据探索

让我们加载数据。我们将把标题和描述连接成一个单一的输入文本,稍后我们将把它发送到我们的网络。

新闻标题被分为 41 类,让我们形象化地看看它们是如何分布的。

类别分布

我们看到我们有许多条目很少的类别。此外,一些类别可能涉及密切相关或重叠的概念。因为有大量的类别需要预测,所以让我们将引用相似概念的类别聚集起来。这将使分类任务稍微容易一些。

因此,我们剩下 28 个汇总类别,分布如下

3.数据预处理

我们现在必须以 Tensorflow Keras 模型可以使用的方式预处理我们的数据。作为第一步,我们需要将类标签转换成索引。我们不需要一次性编码,因为我们将使用张量流稀疏分类损失。

接下来,我们需要对文本进行标记,也就是说,我们需要将我们的字符串转换成可以输入到模型中的索引列表。transformers 库为我们提供了 AutoTokenizer 类,该类允许加载用于 RoBERTa 的预先训练的 Tokenizer。

RoBERTa 使用字节级 BPE 标记器来执行子词标记化,即未知的罕见词被分割成词汇表中存在的常见子词。我们将在示例中看到这意味着什么。

这里标志padding=True将把句子填充到批处理中传递的最大长度。另一方面,truncation=True会将句子截断到模型可以接受的最大令牌数(RoBERTa 为 512,BERT 为 512)。

让我们想象一下文本是如何被标记的。

Input: Twitter Users Just Say No To Kellyanne Conway's Drug Abuse Cure 
Subword tokenization: ['Twitter', 'ĠUsers', 'ĠJust', 'ĠSay', 'ĠNo', 'ĠTo', 'ĠKell', 'yan', 'ne', 'ĠConway', "'s", 'ĠDrug', 'ĠAbuse', 'ĠCure'] 
Indices: [0, 22838, 16034, 1801, 9867, 440, 598, 12702, 7010, 858, 13896, 18, 8006, 23827, 32641, 2, 1, 1, 1] Input: Target's Wedding Dresses Are Nicer Than You Might Think (VIDEO) 
Subword tokenization: ['Target', "'s", 'ĠWedding', 'ĠD', 'resses', 'ĠAre', 'ĠNic', 'er', 'ĠThan', 'ĠYou', 'ĠMight', 'ĠThink', 'Ġ(', 'VIDEO', ')'] 
Indices: [0, 41858, 18, 21238, 211, 13937, 3945, 13608, 254, 15446, 370, 30532, 9387, 36, 36662, 43, 2, 1, 1] Input: Televisa Reinstates Fired Hosts, Is Investigating Sexual Harassment Claims 
Subword tokenization: ['Te', 'lev', 'isa', 'ĠRe', 'inst', 'ates', 'ĠFired', 'ĠHost', 's', ',', 'ĠIs', 'ĠInvestig', 'ating', 'ĠSexual', 'ĠHar', 'assment', 'ĠClaims'] 
Indices: [0, 16215, 9525, 6619, 1223, 16063, 1626, 41969, 10664, 29, 6, 1534, 34850, 1295, 18600, 2482, 34145, 28128, 2]

出现在子词标记化中的字符Ġ表示一个新词的开始,缺少它的标记只是一个更大的词被拆分的一部分。RoBERTa tokenizer 使用 0 作为句子标记的开头,1 作为填充标记,2 作为句子标记的结尾。

作为数据预处理的最后一步,我们从数据中创建一个 TensorFlow 数据集,并使用前 10%的数据进行验证。

3.加载模型和培训

既然我们已经预处理了数据,我们需要实例化模型。我们将使用拥抱脸 TensorFlow 自动类进行序列分类。使用方法from_pretrained,设置num_labels等于我们数据集中的类的数量,这个类将为我们处理所有的脏工作。它将下载预先训练好的 RoBERTa 权重,并实例化一个顶部带有分类头的 Keras 模型。因此,我们可以使用所有常用的 Keras 方法,如compilefitsave_weights。我们用小的学习速率1e-5clipnorm=1.对我们的模型进行 6 个时期的微调,以限制可能破坏预训练期间学习的特征的潜在大梯度。

我们看到验证损失很快饱和,而培训损失继续降低。事实上,该模型非常强大,如果训练时间更长,就会开始过度拟合。

4.估价

在总共 28 个类别的验证集上,该模型达到了大约 77%的前 1 准确率和大约 93%的前 3 准确率。

让我们在验证集上可视化混淆矩阵

让我们计算模型的(加权)精度、召回率和 f1 指标。对于这些指标的快速概述,你可以看看漂亮的帖子多类指标变得简单,第一部分:精度和召回多类指标变得简单,第二部分:F1 分数

Precision:0.769
Recall:0.775
F1 score:0.769

让我们根据验证集中的一些示例的概率来可视化前 3 个预测。每个预测的概率用圆括号表示。

HEADLINE: Homemade Gift Ideas: Tart-Cherry and Dark Chocolate Bar Wrappers 
SHORT DESCRIPTION: This DIY gift only LOOKS professional. 
TRUE LABEL: HOME & LIVING 
Prediction 1:HOME & LIVING (77.5%); 
Prediction 2:FOOD, DRINK & TASTE (19.8%); 
Prediction 3:STYLE & BEAUTY (0.7%); HEADLINE: Small Parties Claim Their Share In Upcoming Greek Elections 
SHORT DESCRIPTION: Some of the country's lesser-known political players believe they've spotted their chance. 
TRUE LABEL: WORLD NEWS 
Prediction 1:WORLD NEWS (99.2%); 
Prediction 2:POLITICS (0.4%); 
Prediction 3:ENVIRONMENT & GREEN (0.1%); HEADLINE: 46 Tons Of Beads Found In New Orleans' Storm Drains 
SHORT DESCRIPTION: The Big Easy is also the big messy. 
TRUE LABEL: WEIRD NEWS 
Prediction 1:WEIRD NEWS (55.0%); 
Prediction 2:ENVIRONMENT & GREEN (14.4%); 
Prediction 3:SCIENCE & TECH (10.0%);

结论

我们已经看到了如何将拥抱脸变形器库与 TensorFlow 一起使用,以在多类分类任务中使用 TPU 来微调大型预训练模型。

由于 transformers 库中有大量的 Auto 类,其他常见的 NLP 下游任务只需对提供的代码稍加修改就可以执行。

我希望这个教程是有用的,感谢阅读!

使用 Python 的新闻摘要应用程序

原文:https://towardsdatascience.com/news-summary-app-with-python-2b1993cf64dd?source=collection_archive---------17-----------------------

使用 Streamlit、sumy 和 News API 构建一个纯 Python 应用程序

照片由罗马卡夫Unsplash 上拍摄

外面新闻很多,很难跟上。由于我不是一个速读者,我很好奇是否能找到一个纯 Python 的解决方案来帮助我保持消息灵通。我过去使用过 News API,并且在数据科学项目中大量使用 Streamlit。快速搜索了一下,找到了 sumy ( Github ),对于问题的文本摘要元素,它竟然是一个很好的解决方案。

假设

本文假设您对 Python、终端和 API 有一定的了解。即使你对这些话题中的任何一个都不熟悉,我想你也会发现其中的大部分都很容易处理而且很有趣。

安装库

pip install sumy

pip install streamlit

Sumy 使用 NLTK,需要下载额外的数据,你可以在这里找到详细说明

我在 macOS 上是这样做的:

在 Python 会话中运行以下代码:

这将启动 NLTK 下载程序。对于集中安装,将下载目录文本字段更改为:/usr/local/share/nltk _ data。如果集中安装导致权限错误,可以将数据安装到其他地方,但是您需要设置环境变量。

要使用 zsh 添加环境变量,您可以在终端中运行以下命令:

echo "export NLTK_DATA=<PATH-TO-YOUR-DATA> >> ~.zshenv"

开始使用 sumy

以下是运行代码所需的导入语句:

下面的函数是 sumy Github 页面上的例子的修改版本。该函数只是对文本中的句子进行排序,并返回一个包含最重要句子的strsentences_count参数指定了summary中句子的最大数量。虽然 sumy 可以用于纯文本文件,但本教程将只讨论 HTML 输入。

下面是一个使用维基百科条目对 sumy Github 页面进行自动摘要的例子:

输出显示了文章中前 10 个最重要的句子,作为摘要。

开始使用新闻 API

首先,你需要注册并获得一个 API 密钥,这很容易做到这里。注册后,API 密匙会自动生成并显示在下一个屏幕上。虽然有 Python 客户端库,但我选择创建自己的函数,因为它是一个直接的 API。

本文将涵盖 API 的两个端点:

  1. /v2/everything: 从故事档案中检索文章(文档)
  2. /v2/头条新闻:检索头条新闻和突发事件(文档)

news_api_request函数只是使用提供的端点和关键字参数发送一个 GET 请求。返回值是一个list,其中每个元素是一个dict,包含关于一篇文章的信息,它将被传递给summarize_news_api

summarize_news_api函数遍历每篇文章,并将文章的 URL 传递给summarize_html函数。articles中的每个dict都用摘要的新元素更新。

下面的代码片段是一个同时使用news_api_requestsummarize_news的例子,用来总结来自 /v2/top-headlines 端点的响应中的文章。

如果您运行上面的代码,您将打印一个代表第一篇文章的dict,带有如下所示格式的键/值对:

应用规格

既然你已经学会了如何从新闻 API 中提取数据,并总结文本,那么是时候构建一个满足以下标准的应用程序了:

  1. 让用户能够按类别搜索头条新闻。这将使用来自新闻 API 的 /v2/top-headlines 端点。用户将能够从新闻 API 文档中指定的类别列表中进行选择。
  2. 让用户能够通过搜索词搜索所有文章,用户将通过文本输入的方式提供。这将使用来自新闻 API 的 /v2/everything 端点
  3. 让用户能够指定摘要的最大长度

开始使用 Streamlit

Streamlit 对于 Python 用户来说是一个超级直观的前端解决方案。它非常适合创建原型和简单的工具,这就是为什么我认为它对这个项目非常有用。

Streamlit 将通过构建上一节中指定的应用程序的前端来引入。

创建标题

运行应用程序:

  1. 将文件另存为 news_app.py
  2. 导航到“终端”中的文件夹
  3. 在终端运行:streamlit run news_app.py

应该会弹出一个浏览器窗口,如下所示:

添加一些用户输入功能

第 6 行创建单选按钮,允许用户选择要搜索的端点。第一个参数是单选按钮簇的标签,我留为空白str,因为比率按钮对这个应用程序来说已经足够描述了。第二个参数让您将单选按钮的选项作为一个list传递。用户输入然后作为str保存到search_choice,这使得在整个应用程序中使用起来很简单。在本例中,列表的第一个元素是默认值。

第 9 行创建了一个滑块输入小部件,让用户能够指定摘要的长度。同样,第一个参数是小部件的标签。其余参数定义滑块的范围和默认值。用户输入作为int保存到sentences_count

当您运行该应用程序时,您应该会看到类似这样的内容:

如您所见,小部件出现在可折叠的侧边栏上。如果将st.sidebar.radio替换为st.radio,小部件将出现在标题下。

基于用户输入添加条件要素

接下来的功能将取决于用户选择“头条”还是“搜索词”。如果“头条新闻”被选中,用户需要有选择类别的选项。如果选择“搜索术语”,用户将需要能够输入一个搜索术语。

如您所见,应用程序的流程是由第 14 行和第 27 行的条件中使用的search_choice的值定义的。如果用户选择“头条”,将出现一个下拉菜单,其中包含类别选项。传递给st.sidebar.selectbox的选项来自 NewsAPI 文档。index参数指定了列表中的哪个元素作为默认元素,我认为“general”是有意义的。

如果用户选择“搜索术语”,将出现一个文本框,接受用户输入。我添加了一个条件语句,在文本输入框为空时提示用户输入。这有助于在添加 API 调用时避免错误。

运行应用程序时,您应该会看到类似这样的内容:

新闻摘要的实时预览

这向您展示了应用程序的原始外壳,它似乎符合上面设置的标准。现在,您只需要整合前面的函数来点击新闻 API 并总结文本。

创建单独的文件来存储函数

我喜欢为函数使用单独的文件,以便 Streamlit 应用程序保持整洁。下面的代码片段显示了该应用程序所需的五个功能。前三个函数,summarize_htmlnews_api_requestsummarize_news_api与我们上面使用的相同。我添加了两个新函数,search_articlesget_top_headlines,它们都将硬编码的端点传递给news_api_request函数,以帮助简化代码。

完成简化应用程序

在上面的代码中,第 2 行从 app_function.py 导入函数。第 23 行调用get_top_headlines,它调用 /v2/everything 端点。这对应于用户为search_choice选择“头条”。

在第 36 行,调用了search_articles,它调用了 /v2/everything 端点。这对应于用户为search_choice选择“搜索术语”。

在第 40 行,应用程序将循环通过summaries,并写出应用程序需要显示的选定信息。在本例中,应用程序将显示标题、出版日期/时间、来源名称以及我们在前面步骤中生成的摘要。

最后,您可以运行完成的应用程序:

streamlit run news_summarizer_app.py

未来的增强

我认为这个应用是一个很好的开始,但还有很多方法可以让它变得更好。以下是我想到的一些改进:

  1. 寻找文本摘要的替代方法
  2. 整合情感分析
  3. 在应用程序中创建更多的用户输入字段,以便用户可以更好地定制查询
  4. 合并几个 API 以获得更多文章

结论

您刚刚学习了如何使用 Streamlit、News API 和 sumy 用 Python 构建一个基本的新闻摘要应用程序。我希望这能给你一些新项目的想法。感谢阅读。

参考

[1]https://github.com/miso-belica/sumy

https://www.nltk.org/data.html

https://newsapi.org

https://streamlit.io/

使用 Elasticsearch 的新一代数据存储和分析

原文:https://towardsdatascience.com/next-gen-data-storage-and-analytics-with-elasticsearch-a833ca7ca54a?source=collection_archive---------13-----------------------

对 Elastic 的简单代码介绍

卢克·切瑟在 Unsplash 上的照片

Elasticsearch 是一个非常受欢迎的服务,它提供了一个强大的无模式文档数据库支持的令人难以置信的搜索引擎和分析工具。

它提供了一个可伸缩的、高度可用的、快如闪电的搜索引擎。数据库本身分布在多个节点上,这些节点可以进一步分成多个碎片,默认情况下,这些碎片会被复制以防止数据丢失。

除了 Logstash、Kibana 和 Beats,我们还开发了世界级的数据收集、转换、分析和可视化*台。

这些被称为弹性(或 ELK)堆栈,是任何处理数据的人的强大工具。Elasticsearch 是这个堆栈的核心。

在本文中,我们将涵盖开始使用 Elasticsearch 所需了解的一切,包括:

**> Elasticsearch****> Getting Free Access to Elastic Cloud****> Key Points of Interest**
  - Deployment Details
  - Kibana Dashboard
  - Console**> API Requests**
  - Request Structure
  - Connecting Remotely**> Adding and Querying Data**
  - Index Creation
  - Adding Data
  - Querying

弹性搜索

在我们开始设置我们的第一个 Elasticsearch 集群之前,有必要对这些集群的结构有一个高层次的了解。

我们不会深入探讨——相反,我们只需要涉及基础知识。

集群是我们部署的顶层,是包含所有其他内容的容器。

节点包含在集群中

在我们的集群中,我们有节点。我们可以将这些视为独立的处理单元,通常我们会尝试将每个节点放在单独的硬件上,这样做是为了提供容错能力,如果一个组件出现故障,一个节点出现故障,我们可以用其他节点来代替它。

我们的索引包含一组文档——我们的无模式数据点

下一层是我们的指数。单个索引就像一个数据集。在这些索引中,我们将数据存储为无模式的“文档”。

无模式指的是缺乏一个通用的数据结构。这与基于模式的 SQL 数据库相反,在基于模式的 SQL 数据库中,每个条目都被分配一组值,这些值对应于表模式定义的一组严格的字段。

我们的索引不是遵循严格的模式,而是由“文档”构成,其中每个条目可以包含一组完全不同的字段。这些文档存储为 JSON 对象,如下所示:

{
    'id': 'abc',
    'project': 'homegrown cucumbers',
    'codename': 'X',
    'cool-factor': '10'
}

同一索引中的另一个文档可能如下所示:

{
    'id': 'def',
    'project': 'making faster lawnmowers',
    'codename': 'go-fast',
    'notes': 'adding stripes do not work',
    'ideas': 'rockets'
}

索引可以进一步分解成更小的子集,称为碎片——这些碎片也可以跨多个节点存储

索引可以被分割成碎片——然后可以分布在我们的节点上。对于本文来说,这种详细程度不是必需的,但是知道这一点还是有好处的。

免费访问弹性云

Elasticsearch 有几个安装选项。到目前为止,最容易上手的是弹性云。

弹性云是一项高级服务,然而,它提供了 14 天的免费试用——这足以让你熟悉这项服务。

要注册免费试用,我们只需点击这里并点击开始免费试用。之后,注册并验证您的电子邮件地址。

接下来,我们导航到弹性云主页,点击开始免费试用

在下一页,我们可以选择我们的服务配置—我们将使用弹性堆栈。从这里,我们简单地使用所有的默认配置设置,最后,点击创建部署

这里您需要注意的唯一部分是显示我们的部署凭据的地方——这里只需单击下载并将凭据 CSV 存储在安全且容易记住的地方——我们很快会再次需要这些凭据。

感兴趣的要点

我们从我们的弹性云主页开始,在那里我们应该能够看到我们的部署列表、文档链接、新闻等等。

部署详细信息

通过点击弹性云主页上的部署名称来访问部署详细信息

首先,我们单击我们的部署—这将带我们进入部署详细信息页面。

Elasticsearch 端点是我们稍后将引导 API 请求的地方

这里我们会发现复制端点按钮——这给了我们 Elasticsearch API 的 URL 地址。我们可以将其粘贴到浏览器地址栏中,并使用凭据 CSV 中提供的用户名和密码登录。

登录后,我们应该会得到一个 JSON 响应对象:

来自访问我们的 Elasticsearch 端点的 JSON 响应——这证实了一切(到目前为止)都在按预期工作

太好了!将这个端点地址保存在手边,因为我们稍后在向集群发出 API 请求时会用到它。

基巴纳仪表板

Kibana 是我们的弹性堆栈的可视界面。在本文中,我们不会详细讨论我们能做的每一件事,但是我们将讨论一些有用的组件。

我们从弹性云主页访问 Kibana

要打开我们的 Kibana 仪表板,请返回到我们的弹性云主页,并单击 Kibana 进行部署。

安慰

我们现在看到的屏幕是我们集群部署的 Kibana 的首页。

在 Kibana 界面中,我们可以点击菜单图标,然后点击开发工具来访问控制台

Kibana 包括一个控制台,允许我们轻松地与 es 交互。我们可以通过点击左上角的菜单图标并选择开发工具来访问它。

开发工具控制台界面

这里我们将看到一个控制台界面,在这里我们可以向 Elasticsearch 实例发送 HTTP 请求。

或者,我们可以轻松地使用 cURL、Postman 或失眠症来发出这些请求——开发工具控制台只是为请求提供了另一个接口。

下面是在开发工具控制台(左)和远程使用失眠症(右)发出的相同 API 请求的比较——稍后将详细介绍

在上面的两个例子中,我们使用函数health查询 ES API _cluster来返回集群的健康状态。对于这两个接口,请求结构几乎是相同的。

使用开发工具控制台的请求有一个小的不同。默认情况下,控制台被配置为使用我们的集群端点——因此与普通请求不同,我们不需要指定集群的完整地址。

API 请求

在介绍控制台时,我们简单地提到了这一点。现在,让我们更深入地了解一下 Elasticsearch API 是如何构建的,以及我们可以用它做什么。

请求结构

我们的请求结构遵循METHOD URL/<API>/<function>的模式——如果我们从开发工具控制台发出请求,我们可以排除URL部分。

在我们之前的例子中,我们查询了_cluster API 并执行了health函数。根据我们想要看到的内容,我们可以用许多不同的函数替换函数health:

使用 GET /_cluster/stats 检查集群统计数据

我们可以使用GET/_ cluster/pending _ tasks来检查任何未完成的任务

或者我们可以通过从_cluster切换来使用完全不同的 API,就像这样:

GET /_cat/nodes?v 返回关于节点的关键信息——添加 v 参数告诉 API 在响应中包含列标题

在这里,[cat_](https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-nodes.html)允许我们查看关于集群节点的【人类可读】信息——比如它的 RAM 使用量ram.percent、负载load_1m、角色(权限)node.rolename

我们也用v添加了第一个参数——这告诉 API 在响应中包含列标题。让我们添加另一个参数h来指定我们希望看到哪些列:

在这里,我们指定了希望看到带有 v 的列标题,并指定了带有 h 的列

这些都是简单的信息请求,但是正是使用这种完全相同的方法,我们可以开始在 Elasticsearch 中添加和查询数据——我们将在后面介绍。

远程连接

我们需要我们的 Elasticsearch 端点将我们的 API 请求指向

如果我们想从开发工具控制台之外与 Elastic 通信,我们需要集群端点。我们之前从我们的部署详细信息页面(如上所示)中发现了这一点。它应该是这样的:

https://012324de56789df.eastus2.azure.elastic-cloud.com:9243

让我们把这个加上/_cluster/health来创建我们完整的请求 URL。

为此,你需要一种提出请求的方式——我将使用失眠症,但还有很多其他方法和工具可用,所以你可以随意使用任何你喜欢的方法和工具。

接下来,我们需要向我们的 API 添加基本授权。就像之前我们通过浏览器访问 API 一样,我们需要提供从我们的凭证 CSV 中收到的用户名和密码。

现在,我们可以从任何地方向我们的弹性云集群发出 API 请求

在失眠症中,我们可以很容易地输入所有这些细节——只需点击 Auth 下拉菜单并选择 Basic——我们在那里输入我们的凭证。然后,我们可以点击 Send ,我们将看到对我们的 API 请求的响应,就像我们在开发工具控制台中所做的一样。

添加和查询数据

现在我们知道了要点,我们可以开始添加数据,以便开始查询我们的集群。这个过程有几个步骤:

  • 索引创建
  • 添加文档
  • 进行查询

现在,让我们逐一解决这些问题。

索引创建

向集群添加索引非常容易——我们所做的就是发送一个包含索引名称的PUT请求。因此,如果我们想创建一个名为people的索引,我们可以在控制台中使用PUT /people来实现——或者像这样在失眠中:

发送一个 PUT 请求来创建一个名为 people 的新索引

我们应该会收到成功创建新索引的确认。

让我们使用GET /_cat/indices?h=health,index,pri,rep,store.size检查一下我们是否已经成功添加了新的索引:

我们可以在回复中看到我们的指数

这就是我们新创建的people索引!我们还有其他一些有用的信息:

  • health —我们的指标状态,绿色表示良好
  • index —我们指数的名称
  • pri —我们的索引被分成的主碎片的数量
  • rep —相应复制品碎片的数量
  • store.size —总索引大小(包括所有副本碎片)

您不需要理解主碎片和副本碎片到底是什么,但是从高层次上来说,副本碎片就像主碎片的备份(但不仅仅用于数据恢复)。

添加文档

好极了。我们已经有了索引,现在我们准备开始添加一些数据。

数据作为文档存储在 Elasticsearch 中。本质上是 JSON 对象。

因此,在向索引中添加数据时,我们使用 JSON 格式。您可以使用自己的数据,或者上面的虚拟数据集。

我们需要做的就是POST /people/_doc并将 JSON 格式的文档添加到请求中:

POST /people/_doc 允许我们创建一个包含存储在 JSON 主体中的信息的新文档

在失眠症中,我们可以点击正文下拉菜单,并选择 JSON 开始输入我们的文档数据。

现在我们有了第一份文件!注意_id值——我们可以用它来更新条目。让我们使用PUT /people/_doc/<ID HERE>将 Joe 的位置更新到纽约:

我们可以通过使用 PUT 方法并在请求中指定文档 ID 来更新文档

我们将在返回的"result"中看到,我们现在有了"updated",这意味着我们成功地更新了 Joe 的文档。

让我们添加剩余的文档:

查询索引

让我们使用GET /people/_search?q=*对索引中的所有内容进行简单搜索,以确认我们已经正确插入了所有文档:

我们使用 q=* 查询索引中的所有内容

我们的响应将显示我们的people索引中的所有文档——我们可以看到我们有五次点击,向下滚动将允许我们查看五个文档中的每一个!

这里的查询参数用代表“查询”的q指定——我们通过键入*来搜索所有内容。

我们可以使用q=field:value在给定的字段中搜索特定的值。如果我们想返回每一个occupationdata scientist的人,我们就写GET /people/_search?q=occupation:data%20scientist ( %20是 keyspace 的意思)。

使用 q=field:value 可以很容易地查询特定的字段

从这个查询中,我们返回三个命中结果——每个都对应于我们的文档,其中职业值是"data scientist"

这就是本文的全部内容,我们已经从设置一个弹性云实例一直到查询我们的数据,涵盖了:

  • 访问弹性云
  • Elasticsearch 和 Kibana 控制台概述
  • 我们如何发出 API 请求
  • 远程发出这些请求
  • 创建索引
  • 添加文档
  • 如何查询!

这实际上只是触及了 Elasticsearch 的皮毛,当然还有很多东西要写——但这些是你需要开始的最基本的东西。

我希望你喜欢这篇文章!如果你有任何问题,请通过 Twitter 或在下面的评论中告诉我。如果你想要更多这样的内容,我也会在 YouTube 上发布。

感谢阅读!

🤖《变形金刚》课程 NLP 的 70%折扣

*所有图片均由作者提供,除非另有说明

NFNets 解释——deep mind 最新的最先进的图像分类器

原文:https://towardsdatascience.com/nfnets-explained-deepminds-new-state-of-the-art-image-classifier-10430c8599ee?source=collection_archive---------15-----------------------

约书亚·戈尔德在 Unsplash 上拍摄的照片

思想与理论

这是批量正常化结束的开始吗?

介绍

DeepMind 最*发布了一个新的图像分类器家族,在 ImageNet 数据集上实现了新的最先进的准确性。这种新的图像分类器家族被命名为 NFNets (无归一化器网络的缩写),达到了与 EfficientNet-B7 相当的准确性,同时训练时间快了 8.7 倍。

NFNet-F1 的训练速度比 EfficientNet-B7 快 8.7 倍,但精度相当。NFNet-F5 实现了一流的精度,超越了之前 EfficientNet 系列的精度。

这种训练速度的提高部分是通过用其他技术代替批量标准化来实现的。这代表了图像分类器世界中的一个重要的范式转变,它在很大程度上依赖于作为关键组成部分的批量标准化。

批量标准化——好处

首先,我们来了解一下批量规范化带来的好处。有了这些知识,我们就可以设计替代方法来恢复这些益处。

批处理规范化缩减剩余分支

在类 ResNet 架构(即 ResNet、ResNeXt、SE-ResNeXt 等)中,通常在剩余分支中应用批处理规范化,这具有减少剩余分支上的激活规模的效果(与跳过分支相比)。这在训练的早期稳定了梯度,使得能够训练明显更深的网络。

批量标准化消除了均值漂移

当使用反对称激活函数(如 ReLUs)时,激活的*均值是非零的,导致激活通常较大且为正。这导致网络在训练早期为所有训练样本预测相同的标签,导致训练不稳定。这种现象被称为均值漂移。批次标准化通过确保每个批次的*均激活度为零,消除了均值漂移。

批处理规范化具有正则化效果

随着批量标准化的引入,研究人员发现退出不再是必要的,因为应用批量标准化有助于规范网络。批次规范化通过防止对有噪声的批次统计数据过度拟合来规范网络。

批量标准化允许高效的大批量训练

通过*滑损失情况,批量标准化允许我们使用更大的批量和训练率,而不会过度拟合。

批量标准化——坏处

尽管*年来批量归一化已经使得图像分类器取得了实质性的进展,但是它确实具有许多负面的后果。

批量标准化成本很高

计算批处理级别的统计数据是一项开销很大的操作。通过消除批量标准化,我们可以更快地训练网络。

批量规范化打破了数据独立性的假设

批量级统计的计算打破了小批量中训练样本之间的独立性。这是许多实现错误的根本原因,尤其是在分布式培训中。事实上,由于批量标准化导致的问题,机器学习研究中的几个众所周知的结果无法精确复制。

为此,许多研究人员试图创建无规格化器的网络,同时仍然享受批量规格化带来的好处。到目前为止,他们中的大多数都没能创造出这种具有竞争精度的无归一化因子的网络。

NFNets——最先进的无归一化器网络

NFNets 是一系列经过修改的 ResNets,无需批量标准化即可实现竞争精度。为此,它应用了 3 种不同的技术:

  • 加权标准化的修正剩余分支和卷积
  • 自适应渐变裁剪
  • 架构优化可提高精确度和训练速度

这 3 种技术本身是复杂的主题,所以我们将在下面的章节中逐一介绍。

修正的剩余分支和卷积

为了在没有归一化的情况下训练深度结果,抑制剩余分支上的激活规模是至关重要的。为了实现这一点,NFNets 使用 2 个定标器(α和β)来定标剩余分支开始和结束时的激活。

α设置为小常数 0.2,而每个模块的β定义为:

在哪里,

并且 h 指的是块的输入。

此外,NFNets 使用比例权重标准化来防止均值漂移。缩放权重标准化将 NFNets 中卷积层的权重归一化,使得:

其中μ和σ分别指权重的均值和标准差, N 指卷积层的扇入。

自适应渐变裁剪

自适应梯度裁剪也被用来训练具有较大批量和学习速率的神经网络。传统上,渐变裁剪用于限制渐变幅度并防止渐变爆炸。

其中 G 是指梯度,λ是任意阈值。然而,作者发现神经网络的训练稳定性对λ的选择极其敏感。因此,作者提出了自适应梯度裁剪,一种梯度裁剪的改进形式。

自适应梯度裁剪背后的直觉是,梯度对权重的比率提供了一个简单的度量,即单个梯度下降步骤将改变原始权重。我们预计,当这个比率很大时,训练将变得不稳定,因此,当这个比率超过某个阈值时,我们应该修剪梯度。

在自适应梯度裁剪中,梯度是按单元裁剪的(即矩阵中的行),根据:

注意,ϵ常数用于防止零初始化参数的梯度被削波为零,这有助于在训练早期稳定梯度。

架构优化可提高精确度和训练速度

即使使用自适应梯度裁剪、修正的剩余分支和卷积,无规格化器的网络仍然不能超过 EfficientNet 的精确度。

因此,作者着眼于优化现有的基于 ResNet 的模型的架构,以提高模型的准确性。作者使用阿瑟-雷斯 NeXt-D 模型作为基线,并做了以下修改。

首先,每个瓶颈块中 3×3 卷积的组宽度固定为 128。组宽度是指瓶颈块的 3×3 卷积中的滤波器数量÷基数(即分组卷积中的组数量)。

接下来,深度缩放模式也被修改。在原始 SE-ResNeXt-D 模型中,第一和最后阶段中的重复块的数量固定为 3,而第二和第三阶段中的重复块的数量是非均匀缩放的。例如,SE-ResNeXt-50 的缩放模式为[3,4,6,3],而 SE-ResNeXt-152 的缩放模式为[3,8,36,3]。

作者认为,这种扩展策略是次优的,因为早期和后期阶段的层都没有足够的容量。相反,作者提出了一个更简单的缩放模式。最小的型号 NFNet-F0 的缩放模式为[1,2,6,3],而 NFNet-F1(下一个更大的型号)的缩放模式为 F0 的 2 倍,缩放模式为[2,4,12,6]。

第三,作者修改了原始 SE-ResNeXt-D 模型的默认宽度模式,其中第一阶段有 256 个通道,在每个后续阶段都加倍,从而产生宽度模式(256,512,1024,2048)。相反,NFNets 修改第三和第四级的宽度,产生(256,512,1536,1536)的宽度模式。作者发现,根据经验,在第三阶段增加宽度,而在第四阶段减少宽度可以提高模型性能,同时保持训练速度。

下表总结了阿瑟-ResNeXt-50 型号和 NFNet-F0 型号之间的架构差异。

SE-ResNeXt-50 和 NFNet-F0 在架构上的区别。注意,在阿瑟-ResNeXt-50 中,批量归一化应用于每个连续的卷积块之间,而 NFNets 是无归一化器的。NFNets 中使用的卷积层的权重也使用缩放权重标准化进行缩放。

实施国家森林网络

DeepMind 在其 GitHub 库中发布了 NFNets 的代码。然而,代码是用 JAX 的和 T2 的写成的。

https://github.com/deepmind/deepmind-research/tree/master/nfnets

在流行的timm库中也可以找到 NFNets 的 PyTorch 实现。

https://github.com/rwightman/pytorch-image-models

结论

这篇论文读起来很有趣,它是创建竞争性无规范网络的一个重要里程碑。尽管在深度网络中采取了重要的步骤来替代批量规范化,但是 NFNets 中的性能提升很大一部分来自于现有 SE-ResNeXt 架构的优化。

尽管如此,我相信在不久的将来会发现更多先进的无归一化器网络,提供更快的训练速度和更高的精度。

NHL 等效性和前景预测模型:建立 NHL 等效性模型(第 2 部分)

原文:https://towardsdatascience.com/nhl-equivalency-and-prospect-projection-models-building-the-nhl-equivalency-model-part-2-6f275a45e22?source=collection_archive---------4-----------------------

对已建立的框架进行一些小的更新

在 NHL 等效性和前景预测模型的第 1 部分中,我提到了一些 NHL 之外的评分。如果所有的潜在客户都在同一个联盟,这将是一件容易衡量的事情。如果他们都在为数不多的几个联盟中打球,并且这些联盟足够相似,可以比较他们中的球员,比如组成 CHL 的 3 个联盟,那就更好了。我之前提到的分析比较了所有 3 个 CHL 联赛中防守球员的得分,并将这些得分率视为相等,我对此没有太大的问题,因为它们都相当相似。

然而,并不是所有的前景都来自 CHL 或直接可比的联盟。以先于米尔科·穆勒一年的圣何塞首轮选秀权托马斯·赫特尔为例:赫特尔在捷克顶级男足联赛捷克 Extraliga 度过了整个选秀年,38 场比赛得到 25 分(0.66 P/GP)。一个前锋如果在选秀之年的任何一个 CHL 联赛中以这样的速度得分,可能会在选秀中被完全忽略,或者至少要等到下一轮才能听到自己的名字被叫到。但是赫特尔被选为第 17 名。与穆勒不同的是,选择赫特尔让圣何塞看起来非常聪明;他在 NHL 职业生涯中的表现在战争中排名第二,在选秀班中排名第三,在重新选秀中他肯定会比第 17 名高得多。

赫特的高选举人和随后在 NHL 级别的成功不应该让任何人感到惊讶,因为他在选秀年的得分率实际上比他的选秀队友中的任何人都好。他的原始得分率并没有反映出来,因为他在一个很难得分的联盟中打球。

我怎么知道赫塔尔在一个更难得分的联赛中打球?仅仅是他和成年人而不是青少年比赛的事实还不足以证实这一点。毕竟,我的啤酒联盟里都是成年人,但一支由 OHL 最糟糕的青少年组成的球队,如果他们正面交锋,仍然会击败我们最好的球队。虽然常识可能足以告诉我们,捷克的 Extraliga 比任何 CHL 联赛都更好,并且 Hertl 的选秀年得分比 CHL 前锋的得分更好,但在没有衡量捷克 Extraliga 和其他联赛有多好的情况下,我们无法准确地说它有多好,或者与其他联赛中得分不同的球员相比。

这强调了需要一个等价模型:一个决定世界上任何一个特定联赛中一分的价值的模型。我建立了一个 NHL 等值(NHLe)模型,以 1 个 NHL 点为尺度,这意味着如果一个联盟的 NHLe 值为 0.5,那么该联盟中的一个点相当于 0.5 个 NHL 点。

“经典”NHLe 模型通过直接比较一组球员在一个联盟中的得分与这些球员在 NHL 中的得分来计算一个联盟中的分数,通常是在同一年或紧接着的一年。在关于这一主题的最早出版作品之一的“联赛等值”中,Gabriel Desjardins 阐述了他的方法:

为了确定 AHL(或任何其他联盟)的质量,我们可以简单地看看第一年在小联盟和第二年在 NHL 的每个球员,并比较他们的 PPG *均水*。换句话说,相对于 NHL 的联赛质量是:

图片来自 Gabriel Desjardins 的等效联赛

这种方法本身非常有效,但是有三个问题:

  1. 球员在第一年和第二年之间经历的发展被有效地“固化”到模型中,这有利于有更年轻球员的联盟。如果甲 A 在各方面与乙 B 完全相同,只是甲 A 充满了更年轻的球员,那么从甲 A 引进的 NHL 在第 1 年和第 2 年之间将比乙 B 经历更多的发展,因此,在第 2 年得分更多。这将导致该模型错误地指出,甲 A 联赛更难得分,而实际上只有年轻球员在他们看到 NHL 之前发展得更好。
  2. 使用每个联盟中每场比赛的*均得分会使数据更容易受到极端值的影响,并且没有考虑样本大小。一个只在甲 A 和 NHL 打一场比赛的球员和一个在两个联赛都打了 82 场比赛的球员拥有相同的体重。
  3. 这个方法只对下赛季直接产生 NHLers 的联赛有效。使用这种方法来计算像 GTHL U16 这样的联赛的 NHLe 值是不可能的,因为在接下来的赛季中,球员实际上不能参加 NHL。此外,虽然少数联盟在接下来的赛季中确实生产 NHLers,但其中许多联盟生产的数量如此之少,以至于任何一个方向上的一个异常值都可能严重影响最终的估计。

当 CJ·图尔托罗发表了网络 NHLe 时,所有这三个问题都在一个地方得到了补救,这是一篇优秀的文章,我推荐你阅读。(顺便说一句,我对 CJ 为出版他的第一部作品所付出的努力以及他为我的作品提供的帮助感激不尽。像 CJ 这样的人不仅拥有帮助他人的智慧和领域知识,还拥有这样做所需的善良和真诚的热情,这使得曲棍球分析社区成为一个不可阻挡的书呆子大军,减少了犯错的频率。)

CJ 处理第一个问题的方法是只使用同一年在两个联盟打球的球员之间的转换。(我也是这么做的,从来没有认真考虑过使用多年过渡。)

他处理第二个问题的方法是用联赛总积分除以比赛总积分。

第三个问题——我认为是三个问题中最大的一个——他用网络方法处理,使用联盟之间的间接路径来确定每个联盟的相对实力。以下示例使用带有精确整数的虚构数据来解释如何计算间接路径:

  • 100 名球员在同一年参加过甲 B 联赛。他们在甲 A 的 1000 场比赛中共得 1000 分(1.0 P/GP),在乙 A 的 1000 场比赛中共得 500 分(0.5 P/GP)。为了确定甲 A 的“乙 B 等值”,我们将乙 B 的场均积分除以甲 A 的场均积分,算出来就是0.5/1.0 = 0.5
  • 500 名球员在同一年参加过 B 联赛和 NHL 联赛。他们在乙级联赛的 1000 场比赛中共得 1000 分(1.0 P/GP),在 NHL 的 1000 场比赛中共得 200 分(0.2 P/GP)。我们遵循上述相同的方法来计算 B 联赛的 NHL 当量:0.2/1.0 = 0.2
  • 我们知道甲 A 的“乙 B 等效值”为 0.5,乙 B 的 NHL 等效值为 0.2。为了确定甲 A 联赛的 NHL 等值,我们简单地将这两个数值相乘:0.5*0.2 = 0.1这条路径写明了甲 A 一分抵 0.1 NHL 分。

没有球员需要在同一个赛季参加过甲 A 联赛和 NHL 联赛,这种方法才能奏效。只要在两者之间有一个连接联盟,就可以为联盟 a 计算 NHLe 值。

以下是一个真实路径的示例,该路径从 KHL 开始,并使用 AHL 作为连接符:

在这种情况下,同一年在 KHL 和 AHL 打球的球员在 AHL 的总得分是在 KHL 的 1.63 倍。这意味着 KHL 的“AHL 当量”系数为 1.63。与此同时,同年参加 NHL 的 AHL 球员在 NHL 的得分率是他们在 AHL 得分率的 0.38 倍。将这两个值相乘得到值 0.63,这是该特定路径的 KHL 的“NHLe”。

然而,并不是所有的道路都只有一个连接联盟。有些路径没有任何功能,但仍然完全有效,例如 KHL 直接到 NHL 的路径:

有些,像从 J18 Allsvenskan 到 NHL 的道路,有不止一个连接联盟:

具有多个连接器的联盟的方法保持不变:计算每个联盟到下一个联盟的转换因子,然后将这些值彼此相乘。在这种情况下,J18 Allsvenskan 和 Division-1(现在称为 HockeyEttan)之间的换算系数为 0.34,Division-1 和 SHL 之间的换算系数为 0.1,SHL 和 NHL 之间的换算系数为 0.33。通过执行0.34*0.1*0.33 = 0.012将这 3 个值相乘,结果表明 J18 Allsvenskan 中一个点的值在 NHL 中约为 0.012 点。(请注意,这些值是四舍五入的,如果您用四舍五入的值手动执行这些计算,您将得到稍微不同的结果。)

我到目前为止展示的只是计算一个* 路径的方法论。但是与经典 NHLe 不同,在经典 NHLe 中,唯一的路径是一条没有连接器的路径,而网络 NHLe 可以有几十条甚至几百条路径!这引发了更多的问题:*

  • 我们如何确定要使用的最佳路径?
  • 一旦我们确定了最佳路径,我们应该只使用那一条,还是应该使用多条?如果更多,那么有多少?
  • 所有的路径都是有效的吗,或者我们应该排除过渡玩家的样本量很小的路径?
  • 我们是对从每条路径获得的不同等价分数赋予不同的权重,还是对它们进行*均?

这些问题的答案是我的 NHLe 与 Turtoro 不同的地方,tur toro 对每个问题都提供了以下答案:

  • 最上面的路径是连接最少的联盟(他称之为边)。
  • 大约会使用前 5 条路径。
  • 一条路径必须包含至少 10 个过渡玩家的实例才有效。
  • 路径按以下公式加权:
*Weight = 1/2^(Connections) * MinimumInstances*

其中连接数是组成路径的连接数(包括到 NHL 的最终连接),而最小实例数是组成路径中实例的最小转换玩家数。

这可能看起来有点棘手,因此这里有一个为 KHL 加权的三条路径的示例:

  1. 这里的第一条路径是 KHL->AHL->NHL。此路径有两个连接。KHL->AHL 连接有 65 个转换实例,而 AHL->NHL 连接有 2,876 个。这意味着该路径的任何连接中的最少实例是 65,并且该路径的权重的计算是1/2^(2) * 65 = 16.25
  2. 第二条道路是 KHL-> NHL。这个路径有一个与 26 个转换实例的连接,计算是1/2^(1) * 26 = 13
  3. 第三条路径是 KHL->白俄罗斯->WJC-20->NHL。这条路有三个连接点。KHL->白俄罗斯连接有 130 个实例,白俄罗斯->WJC-20 连接有 75 个,WJC-20->NHL 连接有 56 个,这意味着此路径的最小实例是 56 个。这条路径的权重的计算是1/2^(3) * 56 = 7

有了每条路径的 NHLe 值和权重,计算联盟最终值的过程就变得非常简单:将每个 NHLe 值乘以其路径的权重,取这些输出的总和,然后除以权重的总和。在这种情况下,计算是((0.63*16.25)+(0.83*13)+(0.85*7))/(16.25 + 13 + 7) = 26.98/36.25 = 0.74。如果我们只使用这三条路径,KHL 的最终 NHLe 将是 0.74。

我认为 CJ 对这些问题的每一个回答都有坚实的理论基础。如果我是从零开始,我可能会以不同的方式回答这些问题,但我在这里的目标不仅仅是复制 CJ 的流程,并做出一些武断的决定来改变我不喜欢的东西。我的目标是将这些对我来说都有意义的问题的一组潜在答案放在一起,然后将这些答案中的每一个与另一个和 CJ 的答案进行测试,希望为建立网络 NHLe 模型确定一组最佳的建模参数。以下是我决定测试的不同参数集,作为每个问题的答案:

用于确定最佳路径:

  • 根据上面列出的加权等式,选择具有最高权重的路径。
  • 选择具有最少连接联盟的路径,根据加权等式使用最高权重作为*局决胜。
  • 在所有连接中选择实例数量最少的路径。

要确定要使用的路径数量:

  • 通过选择最多前 15 条最佳路径,测试仅选择一条最佳路径。

根据样本大小排除路径:

  • 通过选择至少 15 个实例的路径,测试选择至少 1 个实例的路径。

为了对每条路径进行加权:

  • 我只是坚持使用 CJ 的加权公式。我简单地尝试了几种不同的方法,但是他的方法在初步测试中表现得更好,而且太有意义了。

此外,我选择测试 3 个其他参数:

  1. 包括 U20 和 U18 世界青年锦标赛。
  2. 改变两个联赛之间转换系数的计算方法。我测试了 CJ 使用各联赛得分全额总和的方法,Desjardins 使用各联赛场均分均值的方法,以及我自己使用各联赛场均分中位数的方法(CJ 建议)。
  3. 在为一个联盟创建新路径之前,删除该联盟中的第一个连接联盟。例如,如果使用了 KHL->AHL->NHL 路径,则从该点开始,KHL 的所有其他路径都不能使用 AHL 作为第一个连接。(这条规则的最初实施实际上是由于我误解了 CJ 的方法论而造成的意外,但我最终将它作为一个测试参数,因为我认为对于一个给定的联盟来说,不要过于看重任何一种直接关系可能更好。)

有了一组我认为适合构建最终模型的参数,是时候测试每一个参数并确定最佳参数了。我决定我的测试的目标将是最小化所有转换联盟的玩家的每场预测点数和每场实际点数之间的*均绝对误差。基于每个联盟的 NHLe 值和两个联盟的第一个中的每场比赛的点数来计算每场比赛的预测点数,其中 NHLe 值是在用给定的一组参数建立模型之后获得的那些。

我知道我只是向你扔了一个单词沙拉,但是测试过程其实挺简单的;我将使用 Melker Karlsson 在 2010 年的例子来分解它:

  • 本赛季,梅尔克在 superelit 的 27 场比赛得到 35 分(1.3 P/GP),在 SHL 的 36 场比赛得到 2 分(0.06 P/GP)。
  • 如果从一组给定的试验参数中获得的 NHLe 模型表明 SHL 的 NHLe 值为 0.53,superelit 的值为 0.08,那么我们可以通过执行0.08/0.53 = 0.15获得从 superelit 到 SHL 的转换系数。
  • 然后,我们将转换系数乘以他在 superelit 中的得分率,并执行0.15*1.3 = 0.2,这将给出他在 SHL 中的预计得分率。他在 SHL 中的实际得分率是 0.06,0.06 和他的预计得分率 0.2 之间的差的绝对值是 0.14,这将是该特定过渡获得的误差。
  • 然后,我们将使用他在 SHL 中的得分重复这一过程,以预测他在 super lit 中的得分,执行0.53/0.08 = 6.625以获得从 SHL 到 super lit 的转换系数,然后执行6.625 * 0.06 = 0.4以获得他在 super lit 中的预测得分率。
  • 由于他在 superelit 的实际得分率是 1.3 P/GP,这个值和他预测的得分率 0.4 之间的误差将是 0.9。总之,这一个转换会给我们两个误差值:0.14 和 0.9。
  • 给定 NHLe 模型的*均绝对误差是从过渡联盟的玩家获得的每个误差值的*均值。

我用来运行这些测试和建立我的模型的数据集是所有在我从 2005-2006 年到 2019-2020 年的任何一个赛季中使用的 124 个联赛中的任何两个或更多个联赛中至少打了 5 场比赛的运动员,2012-2013 年除外。(2012-2013 年被完全删除,因为 NHL 停摆导致全球竞争质量发生了变化。)我不能简单地在我的整个数据集上使用这些参数集训练我的 NHLe 模型一次,然后在相同的数据上测试它,但是,因为我的目标不是找到能够最好地预测已经发生的事情的确切参数集;我的目标是建立一个模型,它能最好地预测样本外的得分。训练它这样做的方法是“练习”预测样本外得分。我通过将我的数据集随机分成五份并进行五重交叉验证来做到这一点。

五重交叉验证可能听起来令人生畏,但也没那么可怕。首先,训练集由数据集中 4/5 的联盟对组成,测试集包含另外 1/5 的球员对。对于输入的每一组参数,NHLe 模型都是在训练集上建立的,然后在测试集上进行测试。然后,使用其他组的训练集和测试集再重复这个过程四次,从而为每组参数产生五个不同的测试值。(注意,测试/训练集没有重叠;每个单个玩家配对在一个测试集中出现一次,而在其他四个测试集中没有出现,并且相同的玩家配对在其他四个训练集中出现一次,而在相应的测试集中没有出现。)下面是一个有五个假玩家的交叉折叠验证的例子,其中红色突出显示引用测试集,绿色突出显示引用训练集:

使用每一组可能的参数对每个折叠进行交叉验证,以在训练集上建立模型,并在测试集上对其进行测试。在完成所有 5 个折叠的交叉验证后,获得每组参数的*均测试值。具有最佳*均测试值(在这种情况下,最低*均绝对误差)的参数集被认为是构建 NHLe 模型的最佳参数集。

我的 5 重交叉验证的结果确定了以下一组最佳参数:

  • 可用的顶部路径将是具有最少边的路径,如果两条路径具有相同数量的边,则总权重被用作*局决胜符。
  • 联盟将使用最多前 11 条路径。
  • 至少有 8 个过渡玩家实例的路径是有效的;所有其他的都将被丢弃。
  • 世界青年队(U18 和 U20)都将被使用。
  • 积分总和将除以每个联赛的比赛总和,以确定两个联赛之间的转换系数。
  • 在创建任何进一步的路径之前,第一个连接联盟将被永久删除。

这五次折叠的*均绝对误差的*均值为 0.33。(我也计算了 R,也是 0.33,但选择不将其作为训练的目标参数。)

设置好这些参数后,这一次是时候使用整个数据集构建模型了。以下是最终 NHLe 模型的每个联赛的同等分数:

*╔══════════════════╦═══════╗
║      League      ║ NHLe  ║
╠══════════════════╬═══════╣
║ NHL              ║     1 ║
║ KHL              ║ 0.772 ║
║ Czech            ║ 0.583 ║
║ SHL              ║ 0.566 ║
║ NLA              ║ 0.459 ║
║ Liiga            ║ 0.441 ║
║ AHL              ║ 0.389 ║
║ DEL              ║ 0.352 ║
║ Allsvenskan      ║ 0.351 ║
║ VHL              ║ 0.328 ║
║ Slovakia         ║ 0.295 ║
║ EBEL             ║ 0.269 ║
║ WJC-20           ║ 0.269 ║
║ France           ║ 0.250 ║
║ Belarus          ║ 0.242 ║
║ Czech2           ║ 0.240 ║
║ EIHL             ║ 0.235 ║
║ LNAH             ║ 0.232 ║
║ DEL2             ║ 0.205 ║
║ Kazakhstan       ║ 0.201 ║
║ NCAA             ║ 0.194 ║
║ Denmark          ║ 0.190 ║
║ Mestis           ║ 0.178 ║
║ NLB              ║ 0.176 ║
║ Italy            ║ 0.176 ║
║ Norway           ║ 0.173 ║
║ ECHL             ║ 0.147 ║
║ OHL              ║ 0.144 ║
║ MHL              ║ 0.143 ║
║ USHL             ║ 0.143 ║
║ WHL              ║ 0.141 ║
║ Poland           ║ 0.135 ║
║ WJC-18           ║ 0.135 ║
║ Russia3          ║ 0.135 ║
║ Usports          ║ 0.125 ║
║ USDP             ║ 0.121 ║
║ QMJHL            ║ 0.113 ║
║ Division-1       ║ 0.109 ║
║ Czech3           ║ 0.104 ║
║ Erste-Liga       ║ 0.103 ║
║ Slovakia2        ║ 0.102 ║
║ Romania          ║ 0.099 ║
║ Superelit        ║ 0.091 ║
║ NAHL             ║ 0.087 ║
║ Germany3         ║ 0.085 ║
║ ALPSHL           ║ 0.084 ║
║ U20 SM-Liiga     ║ 0.083 ║
║ BCHL             ║ 0.080 ║
║ NMHL             ║ 0.076 ║
║ Czech-U20        ║ 0.074 ║
║ AJHL             ║ 0.062 ║
║ EJHL             ║ 0.060 ║
║ Czech U19        ║ 0.059 ║
║ SwissDiv1        ║ 0.054 ║
║ Belarus-Vysshaya ║ 0.052 ║
║ SJHL             ║ 0.052 ║
║ U20-Elit         ║ 0.049 ║
║ CCHL             ║ 0.048 ║
║ MJHL             ║ 0.046 ║
║ USPHL-Premier    ║ 0.046 ║
║ Slovakia-U20     ║ 0.044 ║
║ Russia-U17       ║ 0.044 ║
║ USPHL-18U        ║ 0.041 ║
║ U18 SM-Sarja     ║ 0.040 ║
║ NAPHL-18U        ║ 0.039 ║
║ Czech U18        ║ 0.038 ║
║ J18 Allsvenskan  ║ 0.038 ║
║ Division-2       ║ 0.038 ║
║ MJAHL            ║ 0.037 ║
║ QJAAAHL          ║ 0.036 ║
║ MPHL             ║ 0.035 ║
║ OJHL             ║ 0.034 ║
║ HPHL-16U         ║ 0.034 ║
║ Slovenia         ║ 0.033 ║
║ Russia-U18       ║ 0.032 ║
║ 16U-AAA          ║ 0.031 ║
║ J18-Elit         ║ 0.029 ║
║ USHS-Prep        ║ 0.028 ║
║ QMAAA            ║ 0.028 ║
║ CISAA            ║ 0.027 ║
║ Norway2          ║ 0.027 ║
║ USPHL-16U        ║ 0.027 ║
║ GOJHL            ║ 0.027 ║
║ AYHL-16U         ║ 0.026 ║
║ Russia-U16       ║ 0.025 ║
║ J20-Elit         ║ 0.024 ║
║ USHS-MN          ║ 0.024 ║
║ DNL              ║ 0.024 ║
║ Denmark2         ║ 0.023 ║
║ VIJHL            ║ 0.021 ║
║ NOJHL            ║ 0.021 ║
║ Slovakia-U18     ║ 0.020 ║
║ CAHS             ║ 0.020 ║
║ AMHL             ║ 0.020 ║
║ PIJHL            ║ 0.020 ║
║ KIJHL            ║ 0.020 ║
║ U17-Elit         ║ 0.018 ║
║ II-DivisioonA    ║ 0.018 ║
║ U20-Top          ║ 0.017 ║
║ BCMML            ║ 0.016 ║
║ U16 SM-Sarja     ║ 0.015 ║
║ NSMMHL           ║ 0.015 ║
║ Czech U16        ║ 0.014 ║
║ Denmark-U20      ║ 0.013 ║
║ MMHL             ║ 0.013 ║
║ U16 SM-Sarja-Q   ║ 0.012 ║
║ GTHL-U16         ║ 0.012 ║
║ J20-Div.1        ║ 0.011 ║
║ U16-SM           ║ 0.011 ║
║ U16-ELIT         ║ 0.010 ║
║ Alliance-U16     ║ 0.009 ║
║ GTHL-U18         ║ 0.008 ║
║ J18-Div.1        ║ 0.008 ║
║ Division-4       ║ 0.008 ║
║ QMEAA            ║ 0.007 ║
║ J20-Div.2        ║ 0.007 ║
║ Denmark-U17      ║ 0.006 ║
║ U16-Div.1        ║ 0.005 ║
║ J18-Div.2        ║ 0.005 ║
║ ETAHL U18        ║ 0.005 ║
║ AMMHL            ║ 0.005 ║
║ QBAAA            ║ 0.004 ║
║ AMBHL            ║ 0.002 ║
║ U16-Div.2        ║ 0.002 ║
╚══════════════════╩═══════╝*

请注意,其中一些联盟与其他联盟合并。例如,在 KHL 出现之前,在 EliteProspects 数据库中有一个名为“俄国”的联盟,实际上就是 KHL;我只是把这两个合并成了 KHL。“俄罗斯 2”和 VHL 以及另外一两个联赛也是如此。

当我提到 2013 年鲨鱼队选中米尔科·穆勒时,我从未看过他打球时,我暗示了这一点,但让我非常明确地说:我是 而不是一个有前景的人。我一生都是鲨鱼队的球迷,十多年来我一直密切关注 NHL,但我从来没有密切关注过任何其他联盟,这意味着我不太清楚 T4 应该是什么样子。我缺乏潜在客户领域的专业知识,这带来了一些好处和坏处:

  • 我对某些联赛没有任何先入为主的想法,所以在建立模型的时候我不会去确认任何偏见。
  • 不利因素:如果不知道事情应该是怎样的,我就很难识别代码中的 bug 和错误,然后在我成功的时候排除并修复它们。这个问题主要与我花费的时间有关,因为据我所知,最终的模型是没有错误的。
  • 赞成:我知道这个模型不仅可能非常糟糕,而且如果是这样的话,我将无法用肉眼识别,这促使我采取高度稳健的数学方法来确保这个模型是合理的好模型。
  • 反对意见:我很难理解和表达我工作的局限性,尤其是从实践的角度来看。例如,我可以查看我的战争模型的输出,并说“这高估了米科·兰塔宁,低估了内森·麦金农,因为它通常高估了像这样的双人组的终结者,我已经看了足够多的比赛,知道麦金农远远更胜一筹。”我很难表达(甚至理解)为什么我的 NHLe 模型高估了欧洲男子联赛,低估了青年联赛,尽管这是我的总体印象。

最后,我在这里做了大量的工作,只是对 CJ 的 NHLe 模型做了一些我认为是微不足道的升级,他自己说“比原始版本(经典 NHLe)精确得可以忽略不计。”我对此很满意,因为我在这个过程中学到了很多,在确认 CJ 已经做了几乎所有正确的事情后,我现在对这个模型更有信心了。虽然还可以做更多的事情来改进这项工作,并建立一个更好的模型,但我认为公*地说,我们很可能已经达到了收益递减的点。

我对以后重新访问 NHLe 框架持开放态度,我建议任何对如何改进我的工作有想法的人都来试试。但现在,我对我建立的模型很满意,我有信心用它来比较不同联盟的两个潜在客户的得分率。

下一步,我将在第 3 部分中介绍,使用这些得分率来预测未来在 NHL 级别的成功。

posted @ 2024-10-17 11:34  绝不原创的飞龙  阅读(467)  评论(0)    收藏  举报