TowardsDataScience-博客中文翻译-2021-五十九-

TowardsDataScience 博客中文翻译 2021(五十九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

数据科学团队成功的关键指标

原文:https://towardsdatascience.com/key-metrics-for-data-science-team-success-822da77f509c?source=collection_archive---------8-----------------------

数据科学团队领导如何衡量团队绩效并证明 C 套件的成功

万花筒宇宙飞船上拍摄的照片

随着数据科学领域的不断发展和成熟,当 C-suite 高管要求他们展示持续的成功时,许多数据科学领导者都在苦苦挣扎。一个团队可能已经交付了大量的项目和模型,交付了有形的结果,但数据科学仍然是科学——它涉及实验和学习,以及发现可操作的学习。有些项目不会展示新的见解,而实验项目可能会带来更长期的影响,但在今天却没有任何有用的结果。起初这没问题,但是您仍然需要一个过程来展示 C-suite 的不断发展和完善。

韦克菲尔德研究公司最近的一项调查发现,71%的数据高管表示,他们公司的领导层预计,他们在数据科学方面的投资将带来收入增长。高级领导不仅仅希望从这些项目中获得增量增长——25%的数据科学领导表示,他们的公司领导预计数据科学将实现两位数的增长,这增加了快速交付的压力。

但是,一个好的数据科学项目可能需要几个月或几年的时间才能启动创新的飞轮——那么,您如何显示每个季度一致的结果,以证明您不仅在今天发现了有用的见解,还在构建一台能够多年增值的分析机器呢?

诀窍在于超越只显示特定项目有效性和结果的度量,部署显示完整数据科学项目整体性能的度量。您想展示您的团队如何发展得更快,他们如何交付可衡量的结果,以及团队如何能够保持增长。这些都是评估数据科学关键绩效指标的关键领域,以显示您的团队如何为更广泛的组织增加价值。

演示速度

显示你不仅仅是坐以待毙(像许多羽翼未丰的团队一样)的最好方法之一是跟踪你整体表现的速度。当你开始一个新项目时,你有目标,有理论,但你不知道项目会如何发展。许多数据科学都是一个研究过程,一个团队可能会在第 100 个实验产生有趣的结果之前尝试 99 个实验……甚至“没有洞察力”也可能是一个有效的结果。

但是“没有洞察力”不应该是那些情况下的唯一产出——你投入了大量的人力资源,你从工作中学到了一些知识,这些知识你可以在未来成功地使用。您需要一个系统来捕获这些工作,并对建模数据集、使用的功能和初始结果进行分类,这样当您开始一个类似的项目时,您就可以在经验证的数据、初步模型或有效方法方面领先一步。使您的过程可重复和可跟踪对于建立高速数据团队非常重要,这样您就可以从定制的“工匠思维”转向可重复和可重用的“模块化系统”思维。

当他们建立在过去的基础上时,表现最好的团队行动最快。在度量方面,我曾经和一位数据科学家一起工作过,他将组件重用作为他们团队的 KPI 之一进行跟踪。当团队中的成员创建了广泛使用的组件时,如一个伟大的数据集诊断工具,他们会得到认可,并因其对整体成功的贡献而受到表扬。

Glenn Hofmann 是纽约人寿的首席分析官,纽约人寿是世界上最大的人寿保险公司之一,拥有超过 175 年的历史记录,并且在一个受到严格监管的行业中运营。霍夫曼是数据科学更系统化方法的早期支持者。在过去五年中,纽约人寿霍夫曼领导的数据科学和人工智能中心(CDSAi)从七人团队发展到近 50 人,并投资于捕捉业务关键型结果的基础设施。在此期间,该团队为关键业务目标(如客户维系和代理生产率)创建了全面的模型,这些模型可以根据业务合作伙伴的新想法进行版本控制或快速扩展。CDSAi 还创建了一个利用 Python 和 R 堆栈的环境、一个数据科学工作台平台和一个 Kubernetes 集群,以实现流程自动化并加快部署。

“我们消除了数月的重新编码工作,可以将 Python 和 R 代码直接投入生产。我们的模型现在可以通过 API 从公司的任何生产平台访问,”Hofmann 指出。通过创建一个可供公司其他人使用的 API,CDSAi 和纽约人寿可以快速部署新项目并支持广泛的业务需求。

领导者需要采取系统化的方法来管理数据科学,并将这一过程从每次复杂的登月变为绕跑道跑一圈。通过标准化模板、重用数据集和保存软件配置来减少迭代时间,您可以在几个小时内部署一个模型,这有助于您的团队实时迭代和改进。

交付投资回报

数据科学的重要性提升了这个领域,但它也创造了很高的期望,特别是对于那些不清楚数据科学的可能性的高管。

Wakefield Research 的研究发现,虽然公司领导层可能对数据科学有两位数的收入预期,但今天 82%的公司正在进行引人注目的短期投资,而没有认识到投资数据科学的持续好处。46%的高管表示,这些短视的投资经常或一直在发生。

如果一个模型失败了,投资和预算可能就消失了。78%的数据高管看到他们的公司在数据模型失败时停止数据科学计划或削减投资,其中 26%的人说这种情况已经发生过几次。所以你需要确定并设定期望值,并展示随着时间推移而改善的结果。

显示直接 ROI 的一种方法是在生产环境中使用控制组。这将有助于您展示整个公司的价值,尤其是在数据科学或 IT 组织之外的高级业务领导面前。我认识的一家公司根据他们的客户细分和价格弹性模型创建了一个“全球抵制者”团体。一年后,他们将抵制者的收入与预测模型指导下的客户进行了比较。通过创建前后对比,该团队展示了超过 10 亿美元的收入提升,这一结果为数据科学团队带来了巨大的可信度,并为新员工提供了支持。

关于投资回报的最后一点是,不要忘记向人们展示全局。确保你社会化了总的投资组合度量。即使只是一个近似值,你也想展示你的整个项目组合的影响。您还希望利益相关者知道有多少项目正在进行中,正在进行中,以及还没有完成。高管可能只关注他们业务线或部门中的几个项目,因此向他们展示全局可能会有所启发。这种定期报告的节奏也让您有机会展示整个数据科学团队的集体成就以及个人贡献。

壮大你的团队

除了寻找见解的日常工作,建立一个强大的数据科学团队是我今天在该领域看到的最大挑战之一。Wakefield 的研究发现,48%的数据高管抱怨员工的数据技能不足,44%的人说他们无法从一开始就雇佣足够的人才来扩展数据科学。

招聘和留住人才将是一个持续的问题,如果你想为取得重大成果打下基础,你需要一个强大、稳定的团队。你必须向你的员工展示你认真对待数据科学,并且有一个严谨的计划。然后,当与首席执行官一起回顾你的目标时,你还可以报告你已经雇佣了多少人,你的流动率,以及新员工能够多快做出有意义的工作。通过一个强大的计划和清晰的程序来支持你的团队,团队可以专注于他们的工作。

为此,您需要部署支持分散团队的技术。对于正在进行的在家工作计划,您甚至可能没有见过团队成员本人——甚至是您的直接下属!在这种权力下放的情况下,你必须做更多的工作来将新员工与业务联系起来,这样他们才能更好地了解公司需要做什么。确保新员工与业务线负责人、营销和销售团队以及帮助他们完成工作的 IT 团队会面。

随着您团队的成长,您今天实施的流程将会带来回报,因为新的团队成员将开始与特定数据科学工具或领域的专家一起工作,以您获得的知识和进行的实验为基础。39%的高管表示,数据科学对其组织产生重大影响的最大障碍之一是不一致的标准和流程。让消化你的知识变得容易,并了解团队的其他成员是如何完成工作的,这样他们就可以模仿这个过程。

一个战术想法是为数据科学团队和整个公司举办“午餐和学习”,以便每个人都了解您的团队已经做了什么以及下一步要做什么。纽约人寿的 CDSAi 不仅每月举办一次关于项目、方法和数据使用的午餐会,该团队还举办一年一度的数据科学博览会和定期论坛,邀请外部嘉宾演讲,教育和激励纽约人寿的广大数据社区。

根据我在 Domino Data Lab 的经验,我见过许多公司正确地做事情,我也见过更多的公司在几个月的努力之后找到我们。我们只能说,那些不太成熟的公司的数据科学项目主管通常不会在这个职位上呆很长时间。因此,我敦促数据领导者创建一个可持续的长期项目。

如果你建立了一个计划,该计划通过可重复的过程和可重用的资产继续加速,保持高层管理人员对全局的了解和理解,并帮助你的团队感到整合和有效,那么你可以建立一个团队,该团队将产生重大影响并交付显著的、可测量的结果。

从 Kaggle 最近的时间序列竞赛-呼吸机压力预测中获得的关键信息

原文:https://towardsdatascience.com/key-takeaways-from-kaggles-most-recent-time-series-competition-ventilator-pressure-prediction-7a1d2e4e0131?source=collection_archive---------2-----------------------

如何在时间序列预测中具有竞争力

布雷特·乔丹在 Unsplash 上的照片

深度学习对于时间序列预测的重要性不断增长。

神经网络第一次在 Kaggle 时间序列竞赛中进入前 3 名解决方案是在 2015 年(Rossmann 商店销售)。从那以后,在排行榜上看到神经网络越来越常见。

而且这种趋势还在继续。事实上,在上次 Kaggle 时间序列比赛中,15 强团队使用了神经网络

我在 2 年前创建了tsai【1】深度学习库,以便于将最先进的深度学习模型和方法用于时序数据。上一届 Kaggle 时间序列比赛结束的时候,我很想知道顶尖队伍是如何取得优异成绩的。于是我查看了 15 支夺金队伍贴出的所有解决方案。以下是一些重要的发现。

Kaggle 时间序列竞赛

在过去的两个月里,Kaggle 主办了谷歌大脑-呼吸机压力预测比赛。目标是模拟一个连接到镇静病人肺部的呼吸机。更具体地说,参与者必须预测每次呼吸的吸气阶段肺部的压力。

数据集由大约 125k 个模拟呼吸组成,其中 60%被标记(训练数据)。每次呼吸有 80 个不规则采样的时间步长,每个时间步长有五个特征。训练集中的每一次呼吸都有一个 80 步的顺序目标(压力)。目标是在测试数据中为每次呼吸预测这样的序列。关键指标是平均绝对误差(MAE)。

由 Ignacio Oguiza 创作

主要发现

任务定义

这个问题是一个序列到序列的任务,其中两个序列并行发生。有趣的是,目标并不是完全连续的。每个目标步骤都是 float 类型,只有 950 个可能的值。

不出所料,大多数顶级团队将这个问题视为回归任务。

然而,一些金牌获得者成功地将比赛作为一项分类任务来处理。他们预测了 950 个类别中每个类别的概率。

我很惊讶地看到分类方法如此有效。您可能想用自己的数据集来尝试一下!(如果您的数据是连续的,您总是可以离散化目标以创建条块)。

特性

顶级团队使用三种不同的方法:

  • 原来的特色只有。只有获胜的团队在他们的一个模型中成功地使用了这种方法。为了补偿少量的特性,他们使用了大量的纪元(2.5k)。
  • 原创加手工特色。大多数团队遵循这条路线,通常会增加数十个团队。精心设计的手工特征可以帮助模型更快地收敛,因此需要更少的历元。手工制作的功能提供了利用专业领域知识提高性能的机会。
  • 原创加手工加学来的特色。一些团队将输入通过具有多个并行卷积层的特征提取器来学习新特征。每个卷积层使用不同的内核大小。

由 Ignacio Oguiza 创作

原始功能、领域专家设计的手工功能和学习到的功能的组合是非常强大的。

型号

LSTMs 和 transformers 主宰了这次时间序列竞赛。CNN 和 boosted 树没有竞争力。

所有顶级团队都使用了神经网络(深度学习)。不像其他领域,提升树没有竞争力。没有一个最好的解决方案包括提升树木。

顶级车型包括:

  • 堆叠式双向 LSTMs (一种递归神经网络)主导了这场竞争。几乎所有的金牌得主都使用了 LSTM 模型的预测作为他们最终组合的一部分。如前所述,一些团队通过在 LSTM 层之前添加特征提取器来构建混合模型。

后台团队(第三位置)模型架构[2]

  • 很少有变压器型号。一些团队提到很难让它们像 LSTMs 一样工作。然而,几个顶级团队设法让他们的工作取得了优异的成绩。Transformer 模型只使用了编码器部分,没有位置编码,因为时间已经是特性之一。两个额外的定制是在变压器模块或跳过连接之前添加卷积层

由伊格纳西奥·奥吉扎创作。基于负压团队使用的变压器架构[3]。

有趣的是,没有一个顶级解决方案使用卷积神经网络(CNN)。

自定义损耗功能:多任务训练

自定义损失函数对顶级团队来说有很大的不同。

使用 mae(平均绝对误差)对提交的数据进行评估。因此,大多数参与者使用 L1Loss 或相关损失(HuberLoss、SmoothL1Loss 等)。).然而,几乎所有的顶级团队都使用了带辅助损失的多任务学习。他们在原始目标的基础上增加了额外的目标,以减少过度拟合和提高泛化能力。

如前所述,这里的目标是具有 80 个时间步长的压力序列。然而,顶级团队对其进行了修改,以预测次要目标,如:

  • 当前时间步长和先前时间步长之间的压力差(相隔一至四个步长),或
  • 每个时间步的累积压力,或
  • 每个时间步长的压力变化

增加压力差和累积压力迫使模型学习目标、其导数和其积分,从而改善其性能。

“公开排行榜的巨大差距可能就是因为这次失利。”(第三名的队伍)

"[自定义损失]帮助模型正确预测pressure及其导数和积分。这提升了 CV LB”(排名第 13 的团队)

后台团队(第三位置)模型架构[2]

框架&硬件

在这场比赛中,参赛队伍使用了 TensorFlow 和/或 Pytorch。大多数团队也使用 Scikit-learn,主要用于预处理和交叉验证。

访问 TPU 或多个快速 GPU 非常重要,因为在单个褶皱上训练一个模型需要几个小时。

数据扩充

数据扩充是减少过度拟合的最佳策略之一。

然而,很少有团队能找到增加数据的好方法。但是那些做了的人显著提高了他们的表现。本次竞赛中使用的一些有用的数据扩充策略有:

  • 附近时间步长的随机洗牌(基于滚动窗口)。

后台团队(第三位置)模型架构[2]

  • 随机掩蔽。在训练期间,其中一个分类变量被设置为零。

后台团队(第三位置)模型架构[2]

  • 混淆

后台团队(第三位置)模型架构[2]

  • 剪切混合

培训

顶级团队使用大量的纪元来训练他们的模型(通常在 150 到 300 之间,尽管其中一些使用了高达 2.5k!).他们都使用了一些学习率调度程序。余弦退火ReduceLROnPlateau 是最受欢迎的。至少有一个团队声称使用余弦退火和热重启可以显著提升性能。

合奏

模特合奏在 Kaggle 比赛中很常见。这一点非常重要。原因是当你使用平均绝对误差 (MAE)来评估一个预测时,通常使用中位数比平均值更好。只有当你有很多值时,中间值才是准确的。

所有顶级团队都构建了一个或多个强大的模型并运行:

  • 多重折叠(10–15+),或
  • 使用不同种子的所有训练数据,或
  • 两者的结合

后处理

金牌获得者使用三种主要技术:

  • 四舍五入到最接近的 950 个压力值
  • 总是使用中间值,或者
  • 使用基于算法的预测平均值或中值

除此之外,至少有三个团队发现了一种非常巧妙的技术。这给了他们巨大的优势。他们在数据中发现了一个(合法的)漏洞,并获得了第一、第二和第四名。

伪标签

一些最佳解决方案还利用未标记的数据集来生成额外的标签。与上述其他技术相比,这种技术的改进是适度的。

结论

时间序列领域遵循计算机视觉和 NLP 的道路,其中神经网络主导了景观。

神经网络加上领域专家知识可以显著提高时间序列任务的性能。
深度学习应用于时间序列的用途近年来发展迅速。它已经成熟,所以现在是开始使用它来解决时间序列问题的好时机。

最后,我要感谢 VPP 竞赛的所有参与者,特别是那些分享了他们的帖子、代码等的人。其余的。所有这些都有助于改进时间序列的预测。

参考文献:

[1] tsai (由 timeseriesAI 创建)是一个基于 Pytorch/ fastai 构建的开源、先进的时间序列和序列数据深度学习库。

[2]摘自 Upstage 团队模型架构(https://www . ka ggle . com/c/ventilator-pressure-prediction/discussion/285330)。我强烈建议您阅读他们的详细解决方案。这是有据可查的。

[3]来自 UnderPressure 团队的 Chris Deotte 创作的笔记本(第 13 名完赛)https://www . ka ggle . com/cdeotte/tensor flow-transformer-0-112?scriptVersionId=79039122

KeyBERT:使用 BERT 提取关键词

原文:https://towardsdatascience.com/keybert-keyword-extraction-using-bert-a6dc3dd38caf?source=collection_archive---------7-----------------------

解码 NLP 库—视觉效果和示例

来自的修改图像

关键词提取的任务是识别最能代表源文档的重要术语或短语。识别好的关键词不仅有助于准确描述文档的内容,还可以通过将关键词作为元数据存储到原始文档中来帮助加快信息检索。在这个领域已经做了很多研究。其中之一就是我们今天要讨论的。

在这篇博客中,我们将讨论一种流行的基于 BERT 的关键字提取技术/库,称为 KeyBERT

没时间看完整个博客?然后看这个快速的< 60 秒的 YouTube 短片—

多看看这样的视频

BERT 概述

BERT 又名变压器的双向编码器表示是一个仅编码器模型,旨在从未标记的文本中学习文本段的深度双向表示。它接受了两项任务的预训练——1 . MLM (蒙面语言造型)2。 NSP (下一句预测)

其中 MLM 的任务使得模型能够基于在其上下文中出现的单词来学习输入中每个单词/记号的表示。NSP 的任务是说,如果给两个句子,然后知道第二个句子是否跟在第一个后面。在这个预训练步骤之后,你可以在任何下游任务中对这个模型进行微调,比如分类等等。你可以在 MLM vs CLMBERT 了解 NLP 中的 BERT中阅读更多关于掩蔽语言建模的内容。

基于 BERT 的关键词提取

因此 KeyBERT 是一个关键字提取库,它利用 BERT 嵌入来获取最能代表底层文本文档的关键字。此外,这个库处理这项任务的方式——你可以说这是一种从给定文本中获取关键字的无监督提取方式。

在很高的层面上,KeyBERT 的工作是下图所示的

KeyBERT Internals |作者图片

整个步骤由 3 个连续的步骤组成。首先,我们从开始,从提供给我们的用于提取关键词的底层文本语料库中提取 n-grams 。n 元文法不过是字符串中 n 个连续记号的序列。作者使用 CountVectorizer 来获得候选 n 元文法的列表。CountVectorizer 根据 n 元语法在原始文档中的出现频率对其进行排序。

N-grams 作为关键字|作者图片

在此之后,使用 BERT 模型将从上一步提取的所有 n 元语法转换为它们的高维表示。下一步是计算每个 n 元语法和原始文本文档之间的语义距离相似度越高,关键词与源文档的相关性和代表性就越强。

确保提取的关键字|作者图片的相关性

因此,在根据这些 n 元语法与底层文档的相关程度获得这些 n 元语法的排序列表后,下一步是根据 【最大边距相关度】 (检查时间戳的描述) 或最大和策略对它们进行重新排序。其中这背后的核心思想是最小化 n-gram 到原始文档的距离,但同时最大化与其他候选 n-gram 的距离。这确保了我们不会在最终的集合中输出相似含义的 n 元语法作为可能的关键字,也就是说确保多样性

确保提取关键字的多样性|按作者分类的图片

我的想法

看到使用上下文表示来获取相关关键词是很有趣的。虽然我觉得这将是很有趣的,看看它比非上下文化的表示好多少,以及平均起来这种方法如何优于早期基于图的关键字提取工作。但肯定的是,多元化步骤在这一研究领域发挥了至关重要的作用。

如果你感兴趣的话,可以随意阅读我不久前写的另一篇关于关键词提取的优美文章——自然语言处理中 10 种流行的关键词提取算法

Github 项目

https://maartengr.github.io/KeyBERT/index.html

我希望你喜欢读这篇文章。如果你愿意支持我成为一名作家,考虑注册成为一名媒体成员。每月只需 5 美元,你就可以无限制地使用 Medium。谢谢!

基于图中心性的关键短语抽取

原文:https://towardsdatascience.com/keyphrase-extraction-with-graph-centrality-989e142ce427?source=collection_archive---------12-----------------------

利用图形表示从自由文本中提取相关短语

自由文本缺乏明确的结构和标准化。在本帖中,我们看到了如何用一个图来表示自由文本,使其结构清晰,易于下游算法管理。

在这篇文章中,我将向您展示如何使用自由文本的图形表示来解决关键短语提取的任务。顾名思义,该任务的目标是从输入文本中返回相关短语(一个或多个单词)的列表。在这种情况下,我们将仅由候选关键字(即,最相关的单字)组成的短语定义为相关短语。候选关键词由图中心性算法直接给出,该算法利用图的结构来对节点评分(在我们的例子中,节点表示文本中的单词以及它们之间的关系)。

我们将按照 3 个步骤解决这个问题(假设我们有一个来自我的前一篇文章的输入文本的图形表示):

  1. 用图中心性算法对图节点(即单词)进行评分
  2. 提取候选关键字(即最相关的单个单词)
  3. 提取关键短语(基于候选关键字)

和上一篇文章一样,为了保持一致性,下面的文档将是我们的运行示例(改编自维基百科):

在数学中,图论是对图形的研究,图形是用于建模对象之间成对关系的数学结构。在这种情况下,图由顶点组成,也称为节点或点,它们通过边连接,也称为链接或线。无向图和有向图是有区别的,在无向图中,边对称地连接两个顶点,在有向图中,边不对称地连接两个顶点。图形是离散数学的主要研究对象之一

示例文档的起始图。在这种情况下,我在创建 graph(NLTK 为英语提供的停用词列表)之前已经删除了所有停用词。请阅读我之前的文章来学习如何建造它。图片作者。

1.给图形节点评分

图中的每个节点代表输入文档中出现的一个术语(一个节点代表同一术语的多次使用)。在极限情况下,我们可以定义任何函数来给图中的节点评分。在这篇文章中,我将向你展示如何利用 NetworkX (我们用来构建我们的图)根据节点的中心性给节点打分。来自维基百科:

中心性指数是对“重要顶点的特征是什么?”答案是根据图的顶点上的实值函数给出的,其中产生的值被期望提供标识最重要节点的排序。“重要性”这个词有很多种含义,导致对中心性有许多不同的定义。

因此,在 NetworkX 上有无数的中心性算法。你可以在这里查看它们,决定哪一个最适合你的问题。在这篇文章中,我们使用哪种算法并不重要,重要的是它能提供有趣的节点分数。

我们首先根据某种中心性算法计算节点得分,并从得分最高到最低对它们进行排序。得分最高的节点代表与我们的任务最相关的单个单词。

这些是前 3 个节点和相应的分数:

  1. 图形:0.56
  2. 研究:0.43
  3. 对象:0.35

2.提取候选关键字

我们简单地将最高得分节点定义为候选关键字。您希望将多少个节点作为候选关键字取决于您的任务。我们将节点总数的三分之一定义为候选关键字的数量。

这些是我们的候选关键字(按得分从高到低的顺序排列):

在输入文档的图形表示中突出显示候选关键字(红色)。图片作者。

1.图表
2。学习学习
3。物体物体
4。五棱五棱
顶点顶点
6。
链接8。授意9
对称地
10。委托人
11。一个

3.提取关键短语

关键短语是输入文档中的相关短语,可用于各种任务,其中之一是摘要。我们将把关键短语定义为输入文档中仅由候选关键字组成的单词序列。例如,如果“数学”和“结构”都是候选关键字,那么“数学结构”是关键短语,这些单词不会被单独考虑。

为此,我们将使用 Spacy ,它允许我们逐个标记地处理输入文档并分配定制属性。这将有助于我们在原始文档中查找候选关键字序列的任务。

算法思想如下。依次检查输入文档中的每个标记,确定它是否是候选关键字。如果是,那么将它连接到一个关键短语(如果有的话)。如果不是,那么关键短语(如果有的话)就完成了,我们可以用相同的过程继续下一个标记,从一个空的关键短语开始。值得注意的是,如果一个候选关键字属于多于一个单词的关键短语,那么它本身不应该被认为是关键短语。

这些是我们的关键短语(注意,根据我们的定义,它们仅由候选关键字组成):

  1. 边对称地连接两个顶点
  2. 有向图
  3. 边链接两个顶点
  4. 主要对象
  5. 研究
  6. 一个

使用其他中心性算法

您得到的结果将在很大程度上取决于您决定使用的算法。这是因为每个中心性算法都以非常具体的方式定义了“节点重要性”或分数。例如,度中心性将节点的得分定义为其所有边的总和。度内中心性,类似地,只考虑进来的边(在有向图中)。外向度中心性考虑每个节点的外向边来计算其得分。

维基百科关于中心性的文章中,一张非常重要的图片显示了关于同一图表上不同中心性度量的主题,突出了结果的差异。我邀请你来理解这个图像,以便你能更好地理解哪种中心性测量对你的问题最有效。

A) 中间中心性,B) 接近中心性,C) 特征向量中心性,D) 度中心性,E) 调和中心性和 F) Katz 中心性同一个图的例子。这张图片来自维基百科关于图的中心性的文章。直接链接到原始图像和许可。图像未被更改。

以下是使用 4 种不同的中心性度量提取的关键短语(仅突出显示任何给定关键短语的第一次出现)。

度内中心性

图片作者。

度外中心性

图片作者。

接近中心性

图片作者。

中间中心性

图片作者。

值得注意的是,一些测量提取了更有趣的短语(而不是单个单词),例如中间中心性。然而,由于停用词的移除,许多短语连贯性丢失(例如,“研究”和“图形”都是单独的关键词,但是更相关的短语“图形研究”永远无法提取,因为的“是被丢弃的停用词)。克服这个问题的一个可能的解决方案是用丢失的停用词(如果有的话)来注释连接两个词的图边,并且在关键短语提取中使用边注释来用丢失的停用词重新填充关键短语。

总结想法

从自由文本中抽取关键短语是一项非常重要的任务,其结果在许多方面都是有用的,例如抽取摘要、索引、响应查询等。自然,有多种方法来执行这项任务:基于单词和句子的语言和统计特征、神经网络和图形表示(我在本文中介绍的方法只是基于图形执行这项任务的多种方法之一),等等。

基于自由文本的图形表示来执行关键短语提取(和其他任务)有各种优势。最明显的一点是直观理解所应用的算法及其预期结果的简单性。另一个优点是图形表示的适应性,以包括比简单的单词共现关系多得多的关系,例如语义关系、句法依赖、引用依赖等等。包含这些信息(在本文中我们没有这样做)以显式形式丰富了表示(注意,这些关系在自由文本形式中是隐式存在的),并允许算法独立或联合地具体利用它们。最重要的是,给定任何图,标准算法都可以毫无争议地应用(就像我们在这篇文章中所做的)。

当然,这种方法也有缺点。最突出的一点是表示的局限性,这也是我们的实现受到影响的原因。如果显式地表示自由文本中隐含的所有关系是可能的和容易的,我们甚至不会有这次讨论。但正因为不容易,我们不得不牺牲我们选择的图表形式。在我们的例子中,我们删除了停用词,这样信息流算法(即中心性)就不会考虑我们本质上知道传达很少或没有语义信息的词。这对我们来说意味着显而易见的关键短语(例如“对图形的研究”)没有被捕获。

从本质上来说,利用图表示可以有很大的优势,但最终会受到表示本身的限制。因此,由算法设计者来理解文本中什么类型的关系和信息与解决任务相关,并发现如何将该知识转换成节点和边。

击键动力学分析和预测第 1/2 部分(EDA)

原文:https://towardsdatascience.com/keystroke-dynamics-analysis-and-prediction-part-1-eda-3fe2d25bac04?source=collection_archive---------17-----------------------

每个按键都有一个故事要讲!

每个用户一生中都会击数百万次键。尽管有许多因素影响击键模式,但每个用户仍然会留下一些隐藏的击键模式签名。这是许多公司已经开始使用的验证用户身份的技术之一。此外,这种技术是非侵入性的(可能在用户不知情的情况下发生)并且是实时的。

图片来源:男高音

维基百科提到:

击键动力学击键生物测定学打字动力学和最近的打字生物测定学,是指当一个人在电脑键盘打字时,准确描述每个键何时被按下以及何时被释放的详细计时信息。

这些动态可以为我们提供帮助认证用户的洞察力。这种认证用户的技术可以追溯到使用莫尔斯电码的时代。每个使用莫尔斯电码发送信息的特工都有一种独特的打圆点和破折号的方式。这有助于区分敌我。

关于技术的更多信息

通过捕捉两次按键之间的持续时间、按下按键的持续时间以及当前按键释放和下一次按键之间的持续时间,可以提供关于用户的大量洞察。下次用户登录时,通过比较他当前的输入模式和他以前的输入模式,公司可以验证登录的用户是合法的还是欺诈的。

通常击键记录者只会记录按键被按下和释放时的时间戳。现在,就其本身而言,这些时间戳将毫无意义。然而,我们可以通过创建诸如按下-按下持续时间(PPD)、保持持续时间(HD)、释放-按下持续时间(RPD)等特征来获得对用户打字模式的洞察。该图显示了按下 2 个键(A 和 b)的持续时间计算。这里,较小的键代表按键事件,较大的键代表按键释放事件。

图片来源:“SUTD 之狼(TWOS):基于游戏化竞争的恶意内部威胁行为数据集”

这些持续时间可用于理解用户的打字模式。为了演示这个概念,我使用了我在 Kaggle 上遇到的数据集:击键动力学挑战 1 | Kaggle

示范

刚才提到的 Kaggle 数据集捕获了 110 个用户的打字尝试。每个用户已经尝试了 8 次键入字符串“united states”(两个单词的第一个字母都没有用大写字母书写以忽略按下 Shift 键的影响),并且已经捕获了相对于第一次按键的按键和释放的相应时间戳。

首先,我们以这种方式从 csv 中读取数据:

同一用户的 5 种用户打字模式;提到的数字是时间戳,假设第一个密钥开始于时间 0 |作者的图像

如前所述,这些数据本身不能直接使用。因此,我们需要从这个数据集中生成按下-按下、保持、释放-按下持续时间的特征。我们使用以下代码来实现这一点:

接下来,我们尝试探索这些生成的数据,并尝试通过其表面价值来理解这些数据。

在进一步分析代码之前,让我们只考虑 110 个用户中的 5 个,即 5x8 = 40 个输入模式。

使用 seaborn 的群集图功能,我们可以为这 5 个用户生成释放-按压、按压-按压、保持持续时间的群集图。

用户发布-按下持续时间的群集图|图片由作者提供

用户按下-按下持续时间群集图|作者图片

用户持有时长群集图|作者图片

正如你从蜂群图中看到的,所有用户的按下-按下持续时间和释放-按下持续时间大致相同。因此,直接使用平均持续时间是没有帮助的。然而,保持持续时间对于每个用户来说大致不同,这是正确的,因为每个用户根据其对打字的熟悉程度而具有不同的打字速度。让我们计划使用直方图来检查是否可以识别任何变化。因为我们知道每个键入模式由 13 次击键组成,所以让我们尝试用散点图和线图来显示这些持续时间在按键事件的时间戳方面的表现。请注意,由于每种打字模式都是相互独立的,因此我们为 5 个用户中的每一个构建了 8 个线图(由 13 个数据点组成),结果得到 8×5 = 40 个线图。

将行要素转换为列要素以进行打印

现在,我们的数据集中的每一行都是对应于一个用户的输入模式,但是如果我们想要分析跨用户的输入模式(由线连接的时间戳),我们需要将这些行特性放在一个单独的列中。出于这个目的,连同其他一些熊猫函数,我们需要使用熊猫的宽到长特性。

按-按持续时间转换为专栏特征|作者图片

现在,让我们尝试使用点和线来绘制按压持续时间 v/s 按压时间戳

新闻时间戳 v/s 新闻-新闻持续时间|作者图片

新闻时间戳 v/s 新闻-新闻持续时间由线连接|图片由作者

注意,这里有 40 个线图,即每个用户 8 个线图,并且考虑了 5 个用户。

这个情节揭示了一个非常有趣的细节。

请注意用户 4 的锯齿状线条(红线)。PPD 突然增加,然后在下一个键变得非常低。这意味着该用户在连续键入两个键之前要等待相对较长的时间。因此,我们可以说这个用户通常以 2 个键为一组进行键入。

这些是我所说的模式类型,通过简单的计算就可以揭示出来。现在,想象一下,如果我们使用复杂的算法来产生洞察力和设计认证技术,安全性会有多高。这是用户甚至不需要记住的事情。

然而,影响打字模式的因素有很多。这些因素中有一些是:

  • 一天中打字的时间
  • 打字时键盘的照明条件(特别是对于非触摸式打字者)
  • 键盘布局(如果有人选择用其他布局替换 qwerty 布局)
  • 对键盘布局的熟悉程度
  • 打字的地方
  • 打字者的手臂、坐姿
  • 打字机的重音

但是有些公司使用多种试探法和技术来自信地认证用户。

在本文第二部分的中,让我们探索创建可训练数据的其余技术,并在一些常用模型上进一步训练。

链接到 Kaggle 笔记本详细介绍整个代码:击键动力学分析和预测 w/ XGB | Kaggle

PS: EDA 的意思是探索性数据分析

直到下一篇,干杯!😃

击键动力学分析和预测第二部分(模型训练)

原文:https://towardsdatascience.com/keystroke-dynamics-analysis-and-prediction-part-2-model-training-a13dc353b6e4?source=collection_archive---------29-----------------------

如果你还没有阅读上一篇文章,请阅读击键动力学分析和预测——第 1 部分(EDA) 。在前一篇文章中,我已经讨论了击键力学,它的目的和挑战。现在,继续讨论击键分析,让我们首先以易于训练模型的格式准备数据。我将再次提及图像以供参考。

图片来源:“SUTD 之狼(TWOS):基于游戏化竞争的恶意内部威胁行为数据集”

代替直接使用这些按压-按压、释放-按压和保持持续时间作为输入,我们可以将这些持续时间分组到直方图中,直方图将代表不同打字速度的组。例如,慢速打字者的击键持续时间会落在较大持续时间的直方图桶中。同时,快速打字者(或者可能是触摸式打字者)的击键持续时间会落在较小持续时间的直方图桶中。

因此,我们将通过使用这种直方图技术来转换整个训练和测试数据。注意, wide_to_long 函数通过将 press-* 的所有行值排列成一列来转换数据帧。

训练组合数据帧|作者图片

使用直方图分桶

现在,让我们查看生成的直方图,以确定可以创建哪些存储桶,以便在它们之间均匀地分割数据。

持续时间直方图|作者图片

现在,我们可以使用另一个有趣的熊猫函数qcut,而不是自己确定桶。在此函数中,我们指定要对其执行宁滨/分桶的列名。该函数检查指定列中值的分布,并将分布分成具有q数量的仓的相等频率。这确保了每个箱具有相等的频率,并且我们可以获得更有意义的箱。

我们将retbins设置为 True,这样我们以后可以在我们的测试数据集上使用这些容器。对于测试数据集,由于我们已经有了这些库,我们不需要执行qcut。相反,我们将使用cut,它直接将值分配到适当的 bin 中。

我们将这些值编码到与箱对应的HDEncPPDEncRPDEnc中的标签 0-9。因为有 12 个 RPD、12 个 PPD、13 个 HD 值对应于打字模式中的 13 个击键,所以我们用-1 填充缺失的 RPD、PPD 值

训练数据现在看起来像这样:

训练组合数据帧|作者图片

现在,让我们来看看作为该操作的结果而创建的箱

直方图仓(已执行单元格的输出)|按作者分类的图像

这意味着,我们的 HD 直方图区间为[0,48]、[48,64]、[64,71]等等。

现在,让我们看看由这些桶形成的编码群图。在群体图中,我们在图上为每个用户绘制所有持续时间的编码值。

宁滨飓风后持续时间的群集图

从语义上来说,这表示每个用户的平均速度。例如,我们可以从 RPD 群图中看到 PPD 持续时间。例如,用户 4 在较高范围的箱中有许多编码(更多 HD、PPD、RPD)。同时,用户 2 在较低范围的箱中有更多的编码。这意味着与用户 2 相比,用户 4 打字相对较慢。

现在,为了进一步处理,我们有以下选项:

  • 将每个用户的打字模式汇总到这 10 个箱中,并确定持续时间的标准化频率(概率)
  • 将每个用户的打字模式汇总为每次击键的平均 bin 值
  • 保留所有打字模式以训练模型并验证准确性

第一种方法最适合文本序列长度不固定的情况。例如,您正在键入一个新的字符串,而不是“美国”,我们可以将所用的时间与任何两次击键的粗略概率进行比较。

现在,当键入“united states”时,连续键击对的相对位置导致这些键击间持续时间的轻微变化。这将在第二种方法中得到固有的考虑。这是因为我们将一对击键(u&n,n&i,…)的持续时间与这些持续时间的平均时间进行了比较。

但是我们的测试数据集只有时间戳,没有用户 id。因此,为了验证我们的模型,我们需要在训练数据集之外保留一些验证数据集。如果我们使用每个用户的平均 bin 值,我们将只有每个用户 1 个值用于训练,这非常非常少。因此,我们将继续第三种方法,仅使用编码值进行训练。

每次击键的用户级完全收集箱

现在,以前,为了确定存储桶值,我们已经将输入模式(按行)转换成分组的列。但是为了将这些作为属性/特征进行训练,我们需要将它们转换回行。这可以帮助我们使用 KNN 来识别用户的最接近的关键动态签名。

train df _ User _ AllSampleProps data frame |图片作者

模型

我们将尝试在 DF: trainDF_User_AllSampleProps上使用 KNN,每个用户有 8 个训练示例。

KNN

如前所述,我们需要在训练数据集之外保留一些验证。我们有 110 个用户,但每个用户只有 8 个样本,所以我们需要确保每个用户在训练集中有足够的样本。因此,在测试期间,对于每个测试用户,至少会有很少的样本。为此,我们执行StratifiedShuffleSplit

在这里,我使用 n_splits 作为 5,这意味着将创建 5 个不同的分裂(用于 5 重交叉验证),test_size 作为 0.2,导致(8 x 0.2) = 1.6 个测试样本,用于(8 - 1.6) = 6.4 个训练样本。

KNN 精确度|作者图片

在这里,正如您所看到的,当选择 1 个邻居时,精确度很高。但是,通常应该有一个以上的邻居在场才能确定用户。因此,6 个邻居似乎是一个很好的标准。接下来,让我们尝试另一种技术。

XGB 模型

尽管这个数据集非常小——每个类 8 个样本和 39 个特征列,我们仍然尝试对这个数据集使用 XGB。这里,让我们也分析一下交叉验证的准确性,以确保这个模型是可靠的。

这花了大约 2.25 小时来搜索。现在,既然我们已经找到了数据集的最佳参数,让我们继续查看从 GridSearchCV 获得的最佳估计量。

找到的最佳 XGB 估算器的详细信息|图片由作者提供

现在,让我们详细了解一下精确度。我们使用从分层混洗分离获得的训练和测试数据集来确定获得的准确度,然后确定平均准确度。

XGB 模型|作者图片的准确性

因为数据集本身很小,这是我能得到的最好的精度。

总结这两篇文章,当用户在系统上工作时,击键动力学似乎是对用户进行非侵入式认证的一个有前途的选择。如果键入模式看起来明显不同,可以对当前用户进行一些二次验证/认证,以进一步验证用户。不仅仅是击键动力学,同样的概念也适用于鼠标动力学。尽管存在多重挑战,但通过大量数据和非常好的启发式方法,我们可以建立一个强大的认证系统。

我已经在 Kaggle 上执行了全部代码。你可以在这里找到 Kaggle 笔记本:击键动力学分析与预测 w/ XGB | Kaggle

直到下一篇,干杯!

关键词提取 Python 中 7 种算法的基准

原文:https://towardsdatascience.com/keyword-extraction-a-benchmark-of-7-algorithms-in-python-8a905326d93f?source=collection_archive---------1-----------------------

提示和技巧

我在一个有 2000 个文档的语料库上比较了 7 个相关的算法

皮雷特·伊尔弗Unsplash 上拍摄

我一直在积极寻找一种有效的算法来完成关键词提取任务。我们的目标是找到一种能够在中提取关键字的算法,一种有效的方式,平衡提取的质量和执行的时间,因为我的数据语料库正在快速增长,达到数百万行。其中一个关键绩效指标是提取那些即使脱离上下文也总是有意义的关键词。

这让我测试和试验了几个著名的关键词提取机制。我在这里和你分享我的小旅程。

图书馆

我使用了以下库来进行研究

Pandas 和 Matplotlib,以及其他通用但核心的库也被使用。

实验的结构

基准测试的工作方式如下

绩效评估的步骤。图片作者。

我们将首先导入包含文本数据的数据集。然后,我们将创建应用提取逻辑的独立函数

_ _ algorithm _ name _ _(str:text)→[keyword 1,keyword2,…,keywordn]

然后我们将创建一个函数,对整个语料库应用提取。

extract _ keywords _ from _ corpus(算法,语料库)→{算法,语料库 _ 关键字,已用时间}

Spacy 将帮助我们定义一个匹配器对象,如果一个关键字匹配一个对我们的任务有意义的语法模式,它将返回 true 或 false

最后,我们将把一切打包成一个函数,输出我们的最终报告。

数据集

我正在处理一系列取自互联网的小块文本。这是样品

['To follow up from my previous questions. . Here is the result!\n',
 'European mead competitions?\nI’d love some feedback on my mead, but entering the Mazer Cup isn’t an option for me, since shipping alcohol to the USA from Europe is illegal. (I know I probably wouldn’t get caught/prosecuted, but any kind of official record of an issue could screw up my upcoming citizenship application and I’m not willing to risk that).\n\nAre there any European mead comps out there? Or at least large beer comps that accept entries in the mead categories and are likely to have experienced mead judges?', 'Orange Rosemary Booch\n', 'Well folks, finally happened. Went on vacation and came home to mold.\n', 'I’m opening a gelato shop in London on Friday so we’ve been up non-stop practicing flavors - here’s one of our most recent attempts!\n', "Does anyone have resources for creating shelf stable hot sauce? Ferment and then water or pressure can?\nI have dozens of fresh peppers I want to use to make hot sauce, but the eventual goal is to customize a recipe and send it to my buddies across the States. I believe canning would be the best way to do this, but I'm not finding a lot of details on it. Any advice?", 'what is the practical difference between a wine filter and a water filter?\nwondering if you could use either', 'What is the best custard base?\nDoes someone have a recipe that tastes similar to Culver’s frozen custard?', 'Mold?\n'

大部分是与食物相关的项目。我们将从 2000 个文档中抽取一个样本来测试我们的算法。

我们还不会对文本进行预处理,因为有些算法的结果是基于停用词和标点符号的存在。

算法

让我们定义关键词提取函数。

每个提取器接受我们想要从中提取关键字的文本作为参数,并返回一个关键字列表,根据它们的加权技术从最好到最差。很简单。

注意:由于某种原因,我无法初始化函数之外的所有提取器对象。每当我这样做时,TopicRank 和 MultiPartiteRank 都会抛出错误。就性能而言,这并不完美,但基准测试仍然可以完成。

工作中的单秩提取函数示例。图片作者。

我们已经通过传递 pos = {'NOUN ',' PROPN ',' ADJ ',' ADV ' }-限制了一些公认的语法模式,这与 Spacy 一起,将确保几乎所有的关键字从人类语言的角度来看都是有意义的。我们还希望关键字至少是三元模型,只是为了有更多具体的关键字和避免过于笼统。查看库文档,深入了解参数及其工作原理。

从整个语料库中提取关键词

现在让我们定义一个函数,它将一个提取器应用于整个语料库,同时输出一些信息。

这个函数所做的就是用作为参数传入的来自提取器的数据和一系列有用的信息填充一个字典,比如执行任务需要多长时间。

语法匹配功能

这是我们确保提取器返回的关键字总是(几乎?)有道理。举个例子,

当脱离上下文阅读时,我们需要的关键词也应该总是有意义的。图片作者。

我们可以清楚的理解,前三个关键词是可以独立存在的。他们有一个意义,他们完全是感性的。当我们是不是——我们需要更多的信息来理解那一大块数据的意义。我们想避免这种情况。

Spacy 在 Matcher 对象中派上了用场。我们将定义一个匹配函数,该函数接受一个关键字,如果定义的模式匹配,则返回 True 或 False。

基准函数

我们差不多完成了。这是启动脚本和收集结果之前的最后一步。

我们将定义一个基准函数,它接收我们的语料库和一个布尔值来决定是否对数据进行洗牌。对于每个提取器,它调用extract _ keywords _ from _ corpus函数,该函数返回一个包含该提取器结果的字典。我们将该值存储在一个列表中。

对于列表中的每个算法,我们计算

  • 提取关键词的平均数量
  • 匹配关键字的平均数量
  • 计算分数时要考虑到找到的平均匹配数除以执行操作所用的时间

我们将所有数据存储在熊猫数据框架中,然后导出到. csv 格式。

结果

运行基准测试就像编写代码一样简单

记录基准的进度。图片作者。

这是结果

基准数据框架。图片作者。

和一个带有绩效得分的条形图

基准测试的结果——性能分数考虑了随时间变化的准确性。图片作者。

根据得分公式(avg _ matched _ keywords _ per _ document/time _ elapsed _ in _ seconds), Rake 在所有其他算法上远远胜出。Rake 在 2 秒内处理 2000 个文档的事实令人印象深刻,尽管准确性没有 Yake 或 KeyBERT 高,但时间因素使其胜过其他人。

如果我们只考虑准确性,计算为avg _ matched _ keywords _ per _ documentavg _ keywords _ per _ document之间的比率,我们得到这些结果

准确性源于我们的基准测试。图片作者。

从精确度的角度来看,Rake 的表现也相当不错。考虑到执行提取所需的时间很短,获得如此高的性能分数是有意义的。

最终考虑

如果我们没有时间在等式中, KeyBERT 肯定会把获胜点作为能够提取敏感关键词的最准确算法。

这个项目的目标是找到效率方面的最佳算法。对于这项任务,Rake 似乎占据了那个位置。

底线是,如果你需要比其他任何东西都精确,KeyBERT 是你的解决方案,否则 Rake 或 Yake。在我没有特定目标,只是想要一个平衡的解决方案的情况下,我会使用 Yake。

很高兴你来了。希望您会发现这篇文章很有用,并在您的代码库中实现它的片段。

推荐阅读

对于感兴趣的人来说,这里有一个我为每个与 ML 相关的主题推荐的书籍列表。在我看来,有一些必不可少的书籍对我的职业生涯产生了巨大影响。
免责声明:这些是亚马逊会员链接。我会收到亚马逊为你推荐这些项目的一小笔佣金。你的体验不会改变,你也不会被收取更多费用,但它将帮助我扩大业务规模,围绕人工智能制作更多内容。

有用的链接(我写的)

如果你想支持我的内容创作活动,请随时关注我下面的推荐链接,并加入 Medium 的会员计划。我将收到你投资的一部分,你将能够以无缝的方式访问 Medium 的大量数据科学文章。

https://medium.com/@theDrewDag/membership

参考

Campos,r .,Mangaravite,v .,Pasquali,a .,Jatowt,a .,Jorge,a .,Nunes,c .,Jatowt,A. (2020 年)。雅克!利用多种局部特征从单个文档中提取关键词。信息科学杂志。爱思唯尔,第 509 卷,第 257-289 页。 pdf

Campos R .、Mangaravite V .、Pasquali A .、Jorge A.M .、Nunes C .和 Jatowt A. (2018 年)。一种基于文本特征的单文档关键词自动提取方法。载于:Pasi G .,Piwowarski B .,Azzopardi L .,Hanbury A .(编辑)。信息检索进展。ECIR 2018 年奥运会(法国格勒诺布尔。3 月 26 日至 29 日)。计算机科学讲义,第 10772 卷,第 684-691 页。 pdf

Campos R .、Mangaravite V .、Pasquali A .、Jorge A.M .、Nunes C .和 Jatowt A. (2018 年)。雅克!独立于集合的自动关键词提取器。载于:Pasi G .,Piwowarski B .,Azzopardi L .,Hanbury A .(编辑)。信息检索进展。ECIR 2018 年奥运会(法国格勒诺布尔。3 月 26 日至 29 日)。计算机科学讲义,第 10772 卷,第 806-810 页。

Csurfer。(未注明)。CSURFER/Rake-nltk:使用 nltk 的快速自动关键字提取算法的 Python 实现。检索于 2021 年 11 月 25 日,发自 https://github.com/csurfer/rake-nltk

利亚德。(未注明)。Liaad/Yake:单文档无监督关键词提取。于 2021 年 11 月 25 日从https://github.com/LIAAD/yake检索

布丹芙。(未注明)。BOUDINFL/pke: Python 关键短语提取模块。检索于 2021 年 11 月 25 日,来自https://github.com/boudinfl/pke

马尔滕格尔。(未注明)。MAARTENGR/Keybert:用 bert 提取最少的关键字。检索于 2021 年 11 月 25 日,来自https://github.com/MaartenGr/KeyBERT

爆炸。(未注明)。爆炸/空间:💫Python 中的工业级自然语言处理(NLP)。检索于 2021 年 11 月 25 日,来自https://github.com/explosion/spaCy

关键词提取方法—概述

原文:https://towardsdatascience.com/keyword-extraction-methods-the-overview-35557350f8bb?source=collection_archive---------9-----------------------

关键词提取方法在文档中查找相关关键词。在这篇文章中,我总结了最常见的关键字提取方法。

文章、社交媒体帖子和出版物等文本文档的数量正在增长。因为我们不能阅读所有的文档,所以我们需要一些方法来帮助我们找到相关的文档。关键词或关键短语提取方法对我们面临的问题有很大帮助。

Patric TomassoUnsplash 上拍摄的照片

什么是关键词提取?

关键词提取是从文本文档中检索关键词或关键短语。它们从文本文档中的短语中选择,并表征文档的主题。在这篇文章中,我总结了最常用的自动提取关键词的方法。

从文档中自动提取关键词的方法使用试探法从文本文档中选择最常用和最重要的单词或短语。我对自然语言处理领域中的关键词抽取方法进行了分类,自然语言处理是机器学习和人工智能中的一个重要领域。

关键词提取器用于提取单词(关键词)或组成短语的两个或多个单词的组合(关键短语)。在本文中,我使用术语关键字提取,它包括关键字或关键短语提取。

但是为什么我们需要提取关键词的方法呢?

节省时间 —根据关键词,一个人可以决定文本的主题(如文章)是否让他感兴趣,是否阅读。关键字向用户提供文档的摘要。

找相关文档 —今天写了成吨的文章,不可能全部看完。关键词提取算法可以帮助我们找到相关的文章。关键词提取算法还可以自动建立书籍、出版物或网络索引。

支持机器学习的关键词提取 —关键词提取算法找到描述文本的最相关的词。它们可以在以后用于可视化或自动分类文本。

关键词提取方法

在这篇文章中,我将概述一些最常用的关键字提取方法。我会考虑无监督的(他们不需要训练)和领域无关的方法。我将方法分成三组:统计的、基于图的和基于嵌入的方法。

统计方法

统计方法是最简单的。他们计算关键字的统计数据,并使用这些统计数据对它们进行评分。一些最简单的统计方法是词频、词语搭配和共现。但是,也有一些更复杂的,如 TF-IDF 和 YAKE!。

TF-IDF术语频率逆文档频率估计单词在文档中相对于整个语料库(更多文档的集合)的重要性。它计算每个术语在文档中的频率,并通过术语在整个语料库中的频率的倒数对其进行加权。最终,得分最高的术语被选为关键词。

TF-IDF 的方程式是

作者图片

其中t是观察项。该等式适用于文档中的每个术语(单词或短语)。等式的蓝色部分是术语频率,橙色部分是逆文档频率。

TF-IDF 的思想是,在文档中出现频率较高的单词不一定是最相关的。该算法偏爱在文本文档中频繁出现而在其他文档中不频繁出现的术语。

TF-IDF 的优点是速度快,缺点是需要至少几十个文档的语料库。TF-IDF 是独立于语言的。

雅客!(又一个关键词提取器)是一种关键词提取方法,使用单个文档的统计特征来提取关键词。它分五步提取关键词:

作者图片

  1. 预处理和候选术语识别 — 文本被分割成句子、组块(用标点符号分隔的句子的一部分)和记号。对文本进行清理、标记,并识别停用词。
  2. 特征提取 — 该算法为文档中的术语(单词)计算以下五个统计特征:a) 大小写 —统计该术语在文本中出现大写或缩写的次数(与所有出现次数成比例)。一个重要的术语通常更经常以大写形式出现。b) 术语位置 —术语在文本中的句子的中间位置。越靠近开头的术语过去越重要。c) 词频标准化—测量文档中平衡的词频。d) 术语与上下文的相关性 — 测量候选术语与多少个不同的术语同时出现。更重要的术语与差异较小的术语一起出现。e) 术语不同句子 —测量术语在不同句子中出现的次数。较高的分数表示更重要的术语。
  3. 计算术语得分 —使用人工公式将上一步的特征组合成一个得分。好奇的读者可以在原文中找到。
  4. 生成 n 元文法并计算关键词得分 —算法识别所有有效的 n 元文法。n 元语法中的单词必须属于同一个组块,并且不能以停用词开头或结尾。然后,每个 n 元语法通过乘以其成员分数来评分,并被归一化以减少 n 元语法长度的影响。停用词被区别对待,以尽量减少它们的影响。
  5. 重复数据删除和排序 —在最后一步算法中,删除相似的关键字。它会保留更相关的内容(分数较低的内容)。相似性是用 Levenshtein 相似性、Jaro-Winkler 相似性或序列匹配器计算的。最后,关键字列表根据它们的分数进行排序。

YAKE 的优势在于它不依赖于外部语料库、文本文档的长度、语言或领域。与 TF-IDF 相比,它在单个文档的基础上提取关键词,并且不需要大的语料库。

基于图形的方法

基于图形的方法从文档中生成相关术语的图形。例如,图表将文本中同时出现的术语连接起来。基于图的方法使用图排序方法,该方法考虑图的结构来对顶点重要性评分。最著名的基于图的方法之一是 TextRank。

TextRank 是一种基于图形的排名方法,用于提取相关句子或查找关键词。我将重点介绍它在关键词提取中的用法。该方法通过以下步骤提取关键词:

作者图片

  1. 使用词性(PoS)标签的文本标记化和标注
  2. 单词共现图构造 —图中的顶点是具有所选词性标签的单词(作者仅选择名词和形容词可获得最佳结果)。如果两个顶点出现在文本中的 N 个单词的窗口内,则它们用一条边连接(根据作者的实验,最佳表现 N 是 2)。该图是无向和无权重的。
  3. 图排序 —将每个顶点的得分设置为1,在图上运行排序算法。作者使用谷歌的 PageRank 算法,该算法主要用于对网站的图表进行排名。该算法使用上图中的等式。考虑连接到节点Vi的顶点的权重,计算顶点Vi的权重S(Vi)。在等式中,d是设置为0.85的阻尼因子,如 PageRank 文章中所建议的。In(Vi)是到顶点Vi的入站链接,Out(Vj)是从顶点Vj的出站链接。因为我们考虑的是无向图,所以顶点的入站链接和出站链接是相同的。该算法在每个节点上运行几次迭代,直到节点上的权重收敛——迭代之间的变化低于0.0001
  4. 最高得分单词选择 —单词(顶点)从最高得分到最低得分排序。最后,算法选择单词的前 1/3。
  5. 关键词提取 —在这一步骤中,如果在前面阶段选择的词一起出现在文本中,则它们被连接成多词关键词。例如,考虑句子She only paints with bold colours 如果同时选择boldcolours 作为关键字,算法输出bold colours作为关键字。新构建的关键词的得分是单词得分的总和。

该算法对每个文档分别执行,并且不需要文档语料库来执行关键词提取。TextRank 与语言无关。

RAKE (快速自动关键词提取)是另一种基于图的关键词提取算法。该算法基于这样的观察,即关键字通常由多个词组成,并且通常不包括停用词或标点符号。

它包括以下步骤:

作者图片

  1. 候选关键词提取 —根据停用词和短语分隔符,在候选关键词上分割文本。候选关键字是介于两个停用词或短语分隔符之间的短语。例如,短语分隔符是标点符号。
  2. 关键词共现图构建 —图中的顶点是词。如果它们一起出现在候选关键字中,则它们是相连的。图表是加权的,权重是相关单词在候选关键字中一起出现的次数。该图还包括到顶点本身的连接(每个单词与其自身一起出现在候选关键字中)。
  3. 单词评分 —图中的每个单词都有一个评分:a) 单词度 deg(w) —单词w共现的单词数(包括指向顶点本身的边在内的边权重之和)。Degree 偏爱出现频率更高、关键词更长的单词。b) 词频 freq(w) —该词在任何候选关键词中出现的次数。频率偏爱出现频率更高的单词。c) 程度与频率的比率 deg(w)/freq(w) —该指标有利于主要出现在较长候选关键词中的词。建议使用词度或度与频率的比值。从这两个角度来看,这个学位更倾向于较短的关键词。
  4. 候选关键词得分 —每个候选关键词的得分是其成员词得分的总和。
  5. 相邻关键词 —候选关键词不包括停用词。因为有时停用词可能是关键字的一部分,所以在这一步添加它们。该算法在文本中查找与停用词连接的关键字对,并将它们添加到现有停用词集中。它们必须在要添加的文本中至少出现两次。新关键字的得分是其成员关键字的总和。
  6. 关键词提取 —结果,提取出 1/3 的最佳得分关键词。

RAKE 和 TextRank 的主要区别在于,RAKE 考虑候选关键字内的同现,而不是固定窗口。它使用一个更简单、更统计的评分程序,不包括优化。该算法对每个文档分别执行,因此它不需要文档语料库来执行关键词提取。

基于深度学习

深度学习的出现使得基于嵌入的方法成为可能。研究人员已经开发了几种使用文档嵌入的关键词提取方法(例如 Bennani 等人)。

那些方法主要寻找候选关键字的列表(例如,Bennani 等人只考虑由名词和形容词组成的关键字)。它们在相同的嵌入空间中嵌入文档和候选关键词,并测量文档和关键词嵌入之间的相似性(例如余弦相似性)。他们根据相似性度量选择与文档文本最相似的关键词。

如果您不熟悉文档嵌入,请阅读本文:

结论

在本文中,我考虑了几种从统计、基于图和嵌入方法中提取关键字的方法。由于这个领域非常活跃,我只考虑最常见的方法。

在本文中,我只考虑了非监督方法的一个子群(它们不需要训练)。也有在带注释文档的训练数据集上训练的监督方法。它们表现很好,但在实践中很少使用,因为它们需要训练、带注释的文档数据集,并且通常仅在训练数据集中的主题上工作良好。

如果我忘记了什么,或者你对这篇文章有任何有价值的补充,请考虑在下面添加你的评论。

参考

[1]Bennani-Smires,Kamil 等.使用句子嵌入的简单无监督关键短语提取. arXiv 预印本 arXiv:1801.04470 ,2018。

[1]坎波斯,李嘉图,等.雅克!利用多种局部特征从单个文档中提取关键词。信息科学,2020,509:257–289。

[3]琼斯,卡伦·斯波克。术语特异性的统计解释及其在检索中的应用。文献杂志,1972 年。

[4]米哈尔恰、拉达;保罗·塔劳。给文本带来秩序。2004.计算语言学协会。

[5] Rose,Stuart 等.从单个文档中自动提取关键词.文本挖掘:应用与理论,2010,1:1–20。

使用自然语言处理(NLP)的 Python 中的关键词提取过程

原文:https://towardsdatascience.com/keyword-extraction-process-in-python-with-natural-language-processing-nlp-d769a9069d5c?source=collection_archive---------0-----------------------

我们将讨论 spaCy,YAKE,rake-nltk 和 Gensim 的关键字提取过程。

奥斯汀·迪斯特尔(Unsplash)拍摄的照片

当你早上醒来,你做的第一件事就是打开手机查看信息。你的思维已经被训练成忽略那些你不喜欢的人和团体的 WhatsApp 消息。您只需检查人员和群组名称的关键字,就可以决定邮件的重要性。

你的大脑会从 WhatsApp 群名或联系人姓名中提取关键词,并训练喜欢它或忽略它。它还取决于许多其他因素。在阅读文章、看电视或网飞连续剧等时,也可以看到同样的行为。

机器学习可以模仿同样的行为。它被称为自然语言处理(NLP)中的关键词提取。所以,阅读文章或新闻将依赖于提取的关键词,如数据科学、机器学习、人工智能等。

关键词提取过程不仅可以分离文章,还有助于节省社交媒体平台上的时间。你可以根据关键词来决定是否阅读帖子和评论。

你可以检查你的文章是否属于当前的趋势。或者你的文章会不会有趋势。在 google trends 上搜索提取的关键词就可以了。是因素之一,不是唯一因素。

每篇文章、帖子、评论都有自己重要的词,让它们变得有用或无用。关键字提取过程识别这些单词并对文本数据进行分类。

在本文中,我们将介绍帮助关键字提取过程的 python 库。

这些库是:

  1. spaCy
  2. 亚克
  3. Rake-Nltk
  4. Gensim

我们开始吧。

1.宽大的

SpaCy 是 NLP 任务的一个 python 库。但是,我们对 spaCy 的关键字提取功能感兴趣。

我们将从安装 spaCy 库开始,然后下载一个模型 en_core_sci_lg。之后,将文章文本传递到 NLP 管道中。它将返回提取的关键字。

每个型号都有自己的功能。如果一篇文章由医学术语组成,那么使用 en_core_sci_lg 模型。否则,可以使用 en_core_web_sm 模型。

找到下面的相关代码。

观察。

  1. 文档对象的输出可以是 1 克、2 克、3 克等。你不能根据 n-gram 和其他参数来控制提取过程。
  2. 对于与医学术语相关的文本,使用 en_core_sci_xx( xx= lg,sm,md)模型。它还表现在非医学术语文章上。
  3. 使用 spacy.load()函数加载不同的模型。参观站点,了解更多关于这些车型的信息。

使用 YAKE python 库来控制关键字提取过程。

2.雅克

另一个关键词提取器(Yake)库使用文本统计特征方法从文章中选择最重要的关键词。在 YAKE 的帮助下,你可以控制提取的关键词字数和其他功能。

找到下面的相关代码。

观察所得。

  1. 如果您想从非英语语言(如德语)中提取关键字,请使用 language='de '。文本语言和语言变量的不匹配会给你不良提取的关键字。
  2. max_ngram_size 是限制提取的关键字的字数。如果保持 max_ngram_size=3,那么关键字长度不会增加超过 3。但是,它也会有小于 3 的关键字。
  3. duplication_threshold 变量限制不同关键字中单词的重复。您可以将重复数据删除阈值设置为 0.1,以避免关键字中的单词重复。如果您将重复数据删除阈值设置为 0.9,则允许在关键字中重复单词。

示例–

对于重复数据删除,阈值= 0.1

输出将是[ 'python 和 cython ','软件',' ines ','库已发布']。

对于重复数据删除,阈值= 0.9

输出将是[ 'python 和 cython ','编程语言 python ','自然语言处理','高级自然语言','语言 python ','语言处理',' ines montani ',' cython ','高级自然',' honnibal 和 ines ','软件公司爆炸','自然语言','编程语言',' matthew honnibal ',' python ','开源软件库','公司爆炸',' spacy ','处理','书面']。

4.numOfKeywords 变量将确定提取的关键字的数量。如果 numOfKeywords = 20,则提取的关键字总数将小于等于 20。

其他关键字提取方法,你可以测试你的数据。

3.Rake-Nltk

通过将快速自动关键词提取(RAKE)算法与 NLTK 工具包结合起来,可以形成一种强大的关键词提取方法。它被称为 rake-nltk。是这个算法的修改版。你可以在这里了解更多 rake-nltk。使用 pip install rake-nltk 安装 rake-nltk 库。

找到下面的相关代码。

观察。

  1. keyword_extracted 变量保存排序的关键字数据。要限制关键字的数量,可以使用下面的代码。

keyword _ extracted = rake _ nltk _ var . get _ ranked _ phrases()[:5]

2.Rake-nltk 性能与 spacy 相当。

4.根西姆

Gensim 主要是为主题建模而开发的。随着时间的推移,Gensim 增加了其他 NLP 任务,如摘要、查找文本相似性等。这里我们将演示 Genism 在关键词提取任务中的使用。

使用 pip install gensim 命令安装 genism。

找到下面的相关代码。

观察:

  1. Genism 在提取关键词方面的性能仍然没有达到 spaCy 和 rake-nltk 的水平。Genism 在关键词提取任务上还有改进的空间。

结论

关键词提取过程有助于我们识别重要的词。它在主题建模任务中也很有效。你只需要几个关键词就可以知道很多关于你的文本数据。这些关键词将帮助你决定是否要阅读一篇文章。

在本文中,我解释了 4 个 python 库(spaCy、YAKE、rake-nltk、Gensim ),它们从文章或文本数据中提取关键字。您也可以搜索其他 python 库来完成类似的任务。

希望这篇文章能帮助你完成 NLP 任务。

在你开始阅读关于 GANs 的论文之前要知道的关键词

原文:https://towardsdatascience.com/keywords-to-know-before-you-start-reading-papers-on-gans-8a08a665b40c?source=collection_archive---------21-----------------------

初学者的深度学习

用简单的英语解释重要的重复出现的关键词/概念

不可否认的是,甘们很棒!如果你不知道它们是什么,看看这篇文章,我从零开始向一个 5 岁的孩子解释 GANs以及如何在 Pytorch 中实现 GANs!简而言之,gan 属于生成模型的一个类别,它让我们生成令人难以置信的真实合成数据,与基础训练数据具有相同的质量。这意味着,如果你输入一些卧室装饰的模型图像,经过几个小时的训练,它可以为你的室内设计产生前所未见的全新想法。

StyleGAN 生成的卧室设计【根据Creative Commons BY-NC 4.0许可证提供】

在过去的几周里,我可能已经阅读了十几篇关于 GANs(及其变体)的论文,并在自定义图像上修补了他们的代码(由开源 Github repos 提供)。虽然这些论文中的大部分都写得很精彩,但我希望在我投入这些学术写作的手稿之前,有几个我已经知道的关键词。下面我将讨论其中的一些,并希望当你在论文中遇到它们时,它能节省你一些时间(和挫折)。先明确一点,这不是一篇深入解释这些论文甚至如何编码的文章,只是简单解释一下某些关键词在特定语境下的含义。请放心,当我读到更多内容时,我会确保更新这个列表。

至于先决条件,我假设你们大多数人已经知道什么是与 GANs 相关的鉴别器和发生器网络。也就这样了!对于那些可能需要回顾的人:

一个生成器网络的目标是产生看起来像真的假图像。它接受一个随机向量作为输入(比如一个来自高斯分布的 100 维数组),并输出一个足够真实的图像,看起来像是属于我们的训练集!

鉴别器网络正确地猜测图像是假的(即由生成器生成)还是真的(即直接来自输入源)。

我们开始吧!

图像的潜在表示

要理解潜在表示,请这样想:我的任何高度和宽度为 100 的彩色图像都可能存储在一个形状数组(100,100,3)中。为了以某种形式表现或可视化这个图像,我需要大约 1001003 ≈ 300k 的维度。哎哟,太多了!

因此,现在我们试图找到一个压缩的图像表示,这样它需要少于 300k 的维度。假设我们用某种降维技术找到了一个仅使用 5 维的表示。这意味着,现在我的图像可以用一个(假设的)向量v1 = [.1,.56,.89,.34,.90](其中. 1,. 56,. 89 等等)来表示。是沿着五个轴中的每一个轴的值)并且我朋友的图像可以使用向量v2 = [.20,.45,.86,.21,.32]来表示。这些向量被称为图像的潜在表现

当然,将它们可视化仍然是一个挑战,因为五维表示更难解析。然而,实际上,我们使用了比简单的 5 更大的表示(大约 100 个)。

潜在空间

上面描述的两个向量(还有我的朋友、同事、家庭成员等等)。)构成了的潜伏空间。在这个潜在空间中,相似的图像(比如两只猫的图像)会被捆绑得更近,而显著不同的图像(猫对汽车)会被分开得更远。

简而言之,潜在空间可以被认为是一个图像的所有潜在表现都存在的空间。如果每个图像用两个元素的向量表示,这个空间可以是 2D;如果每个图像使用三元素向量表示,则为 3D;诸如此类。

这个空间被称为“潜在的”,意思是隐藏的,仅仅是因为在现实中很难想象这个空间。你能想象在你的头脑中想象出三维空间之外的任何东西吗,更不用说 100 维空间了!

潜在空间只是包含点(表示图像)的任何假设空间,以某种方式,生成器知道如何将潜在空间中的点转换为图像(最好看起来类似于它被训练的数据集)。

附:如果我没有链接到 Ekin Tiu 的这篇精彩文章,那将是一种耻辱,这篇文章更详细地解释了潜在空间背后的直觉。此外,不要忘记看看他对包含 0-9 数字的潜在空间的特殊视觉表现。

z 空间

根据先前对潜在空间的定义,Z 空间可以被定义为所有 Z 向量所在的空间。一个 z 向量只不过是一个包含来自高斯(正态)分布的随机值的向量。

z 向量通常作为输入传递给完全训练的 GAN 发生器模型,然后该模型吐出看起来真实的假图像。

如果你在 GAN 的一篇论文中遇到类似“从 Z 空间中采样一个点”或“从 Z 空间中采样一个潜在代码”的内容,请将其视为从 Z 空间中选取一个点,即正态分布的实数向量。

附:在最初的 GANs 和 DCGAN 论文中,z 向量是 100 维的!

风格代码/风格向量

在你学习完香草甘之后,你会发现一种新的甘,即 StyleGANs。虽然 GANs 充其量只能完美地复制训练数据,并产生更多看起来像它的数据,但 StyleGANs 的酷之处在于,它们允许生成高保真图像,其中有更多的变化——各种背景、雀斑、眼镜、发型等。

为此,作者实现了各种架构改进。其中之一如下:不是将 z 向量直接传递到生成器(仅供参考,有时在 StyleGANs 的论文中也称为合成网络),而是首先通过映射网络来产生 w 向量又名样式代码又名样式向量。然后,这被注入到不同层的合成网络中(经过一些特定层的转换),我们得到的输出是一个令人敬畏的高保真图像。

p . s . StyleGAN 架构中 Z 和 W 空间的形状都是 512-D,而且 Z 的分布是高斯型的,但是 W 空间不遵循任何特定的分布。

W-space 和扩展 w-space (W+)

到目前为止,希望您已经理解了如何定义空间。因此,自然地,W-space 是上面定义的所有样式向量w的一些假设居所,这样,如果我们从这个空间中随机选取一个向量,并将其馈送到 StyleGAN 生成器,它就能够产生一个看起来很真实的假图像(比如说,I)。

潜在空间 W 在 StyleGANs 中是一个非常重要的概念,因为它是控制图像各种属性/特征的关键。这是因为 W 空间被解开,这意味着 512 个维度中的每一个都编码了关于图像的独特信息——例如,第一维可能控制表情,第二维控制姿势,第三维控制照明,等等。这种知识允许我们对图像进行某些修改。例如,如果我以某种方式知道向量w中要改变的值,以生成w’,然后将w’馈送给 StyleGAN 生成器,它可以生成原始图像 I 的微笑版本(注意:我们将在教程的后面看到如何在潜在代码中找到这些要改变的“正确”值)。

很多时候,为了增加 StyleGAN 生成器的表现力(即,生成看起来与“平均”人脸不同的独特不同人脸的能力),我们不是对所有层使用一个样式向量,而是对合成/生成器网络中的每一层使用一个独特的样式代码。这被称为 W-空间的扩展,通常表示为 W+。

在潜在空间中编码/投影/嵌入图像

虽然能够对 StyleGAN 生成器生成的假图像的面部特征进行修改很酷,但更酷的是,如果我们可以在你和我的真实图像上做所有这些事情。

要做到这一点,第一步是在 StyleGAN 的 W 空间中找到我的图像的潜在表示(这样我就可以修改那里的正确值来生成我的微笑/皱眉的图片)。这就是,在 W 空间中找到一个向量,当这个向量被输入到一个 StyleGAN 生成器时,它会输出我的精确图像。这就是所谓的在潜在空间中嵌入/投影/编码图像。

研究表明,嵌入真实的输入图像在映射到预先训练的 StyleGAN 的扩展潜在空间(W+)时效果最佳。这意味着潜在表示将具有形状(18,512),即 18 个唯一的样式代码,每个代码由 512 个元素嵌入组成。

注意:能够以 1024 × 1024 的分辨率合成图像的 StyleGAN 发生器有 18 个样式输入层。这就是为什么 W+中的潜在代码采用(18,512)的形状。如果你的风格是以比这个更高或更低的分辨率合成图像,相应的风格输入数量可能会不同,你的潜在表现形式也会不同。

现在回到主要问题:我如何找到我的图像的矢量/潜在表示?GAN 反转就是这么回事!

GAN 反转

GAN 反转是获得给定图像的潜在代码的过程,以便当代码被馈送到生成器时,我们可以容易地重建我们的原始图像。

我不知道这对你来说是不是一个好消息,但如果不是,这里有另一种方式来思考 GAN 反转的有用性(附注:我不能对以下内容负责,我在互联网上的某个地方读到的):

在某种程度上,任何已经出生或将要出生的人都存在于潜在空间中。(你只需要找到正确的反演)。

文献中定义了两种用于反转图像的主要方法:

  • 方法 1:选择一个随机的潜在代表,并努力优化它,直到你最小化给定图像的误差。这种方法需要更长的时间,但允许更好的重建。
  • 方法 2:训练编码器,使其能够将给定图像映射到其对应的潜在代码。这种方法比它的对应方法更快,但是重新创建的图像显示出更高的失真,尽管它们被证明是高度可编辑的。

使用这两种方法中的任何一种(或两种方法的组合),都有可能获得看起来与原始图像相当相似的 GAN 反转图像,并且失真(如果有的话)几乎不明显。这里有一个例子,一个虚构的人物,希迪阿纳贡耶,从一个好地方,由威廉·杰克森·哈珀和他的甘倒置的形象。相当了不起,不是吗!

的原图(左图)和甘的倒像(右图)。[图片由作者使用最近发布的 e4e 编码器生成]。

然而,在我看来,获得完美的娱乐不应该是你的最终目标。更重要的是一旦你有了 GAN 倒像你会怎么处理它!更重要的是,我们能否利用反转来进行有意义的图像编辑?接下来我们来看看!

语义编辑

GAN 反转后最常见的步骤之一是编辑潜在代码,这样就可以成功地处理图像中的一些面部特征。作为一个例子,这里有一个微笑的希迪阿纳贡耶,通过操纵 GAN 反转的潜在代码获得:

微笑编辑在甘倒像上的应用。[图片由作者生成]

语义编辑用一个重要的考虑来封装这样的编辑,即只有预期的特征必须被修改,而其余的特征必须保持不变。例如,在上面的例子中,改变一个人的表情不会改变他们的性别或姿势。

正是因为这个原因,我们应该瞄准一个高度解纠缠的潜在空间,正如研究所指出的,与 Z 空间相比,StyleGAN 的 W 空间表现出更高的解纠缠度,主要是因为“W 不局限于任何特定的分布,可以更好地模拟真实数据的底层特征”。这就是为什么,你会遇到的大多数现有的研究论文会试图在 W 空间而不是 Z 空间找到一个新图像的潜在表示。

潜在空间插值

用投影潜在代码实现的另一个有趣的功能是与另一个潜在代码结合使用。怎么会?你可能会问!

简单地采取两个潜在的代码,这可能是你和你最喜欢的名人的图像代码。现在在一个发展良好的潜在空间,这两点会很远,因为很可能,你看起来一点也不像你最喜欢的名人。但是,您可以在这两个点之间选择一个点(在空间中),将其馈送到生成器并创建一个中间输出。有点像你和你喜欢的名人的混搭,(或者可以说是私生子)!这就是潜在空间插值的全部内容——潜在空间中两个潜在代码之间的平滑过渡。

这里有一个由麻省理工学院研究人员发布的视频短片,可以帮助你形象化插值的概念。在这里,我们可以看到一把带扶手的宽椅子是如何变成一把没有扶手的高椅子的。

线性空间内插【视频在公共领域可用】

最简单的线性插值可以使用简单的矢量算法来实现。也就是说,给定两个潜在向量:ab(都具有(18,512)的形状),分别对应于你和你的名人迷恋的潜在表示:

  • 如果我们正好在中途进行插值,我们将使用公式
    a_b_half = a * 0.5 + b * 0.5
    得到一个新的点。在将a_b_half输入生成器后,合成的图像看起来 50%像你,50%像你喜欢的人。
  • 如果我们插入两者之间距离的四分之一,新的点可以使用公式
    a_b_quarter = a * 0.25 + b * 0.75
    获得。在将a_b_quarter输入到生成器后,结果图像看起来更像你的暗恋对象(我们提取了b的 75%的潜在代码),而不太像你。

线性空间插值是显示两幅图像之间的过渡和探索 GAN 生成的潜在空间的好方法。这种探索有助于发展直觉,并确保甘所了解的潜在空间不是古怪的东西。

潜在方向/语义边界

回到处理面部属性的话题,我答应解释如何在图像的潜在表示中找到“正确”的值来修改。需要注意的重要一点是,需要修改的值将取决于您要修改的属性,如微笑姿势、照明等。

现在找到这个值类似于在潜在空间中找到一个移动的方向,(很像做一些自由式插值)来看看是什么让一张脸从微笑变成皱眉,或者从睁开眼睛变成闭上眼睛,等等。

属性A的潜在方向/语义边界是一个向量,当其被添加到图像的潜在代码时,生成一个新的图像,其属性A被添加到原始图像。

有多种方法(有监督的和无监督的)来学习这些潜在的方向,但对我们来说幸运的是,这些方向通常由许多研究人员开源提供(在这里你可以找到样式根样式根 2 模型的方向)。

如果您想自己生成这些方向(比如“年龄”属性),实现细节已经在 InterfaceGAN 文件中提供:

  • 来自预训练 GAN 模型(可以是 PGGAN、StyleGAN、StyleGAN2 等)的 W 空间的样本潜在代码。)并使用代码生成少量图像。
  • 将生成的图像通过预先训练的年龄分类器,这样每张图像都有一个标签,其中包含A是老还是年轻的信息。
  • 现在训练一个线性 SVM 分类器,将潜在代码作为输入,标签作为输出。
  • SVM 学习的权重对应于年龄的潜在方向。

备注:通常情况下,学习到的方向在 Github repo 中存储为 *.npy* 文件或 *.pt* 文件。

结论

在本教程中,我们解释了 GANs 领域中几个常见术语/概念/关键词的含义,如潜在空间、插值、反演、扩展潜在空间等。希望当你在文学中偶然发现这些术语时,你会对它们的解释有一个公平的想法。

从现在开始,我认为你已经准备好正面处理 GAN 的大部分论文了。我强烈建议您阅读其中的一些文章(我目前最喜欢的是),因为其中的实现和架构细节超出了任何文章或博客的覆盖范围。像往常一样,如果我忽略了一些重要的东西,或者你有更简单的解释,请随时告诉我。

直到下次:)

Python 中的高棉语自然语言处理

原文:https://towardsdatascience.com/khmer-natural-language-processing-in-python-c770afb84784?source=collection_archive---------35-----------------------

利用库美尔-nltk,库美尔的开源 NLP 工具包

Paul Szewczyk 在 Unsplash 上拍摄的照片

通过阅读这篇文章,你将学会用 Python 对高棉语执行自然语言处理任务。供您参考,高棉语是柬埔寨的官方语言,在泰国(东部和东北部)和越南(湄公河三角洲)广泛使用。

在构建任何支持多种语言的 NLP 相关应用程序时,拥有一个专门的语言处理工具包会有很大帮助。在本文中,您将利用一个名为。khmer-nltk。基于官方文档khmer-nltk是一个使用条件随机字段构建的高棉语处理工具包。

在撰写本文时,它支持以下 NLP 任务:

  • 句子分割
  • 分词
  • 词性标注

以下任务已经在路线图中,预计将在未来推出。

  • 命名实体识别
  • 文本分类

让我们继续下一节,开始安装所有需要的 Python 包。

设置

强烈建议您在继续安装之前创建一个新的虚拟环境。

高棉语

激活虚拟环境并运行以下命令来安装khmer-nltk:

pip install khmer-nltk

一旦安装完成,当您运行pip list时,您应该有以下包:

Package          Version
---------------- -------
colorama         0.4.4
khmer-nltk       1.5
pip              21.1.3
python-crfsuite  0.9.7
setuptools       57.1.0
six              1.16.0
sklearn-crfsuite 0.3.6
tabulate         0.8.9
tqdm             4.61.2

履行

在本节中,您将编写一些 Python 代码来测试khmer-nltk。在工作目录中创建新的 python 文件。

导入

您需要根据您的用例导入相应的函数:

from khmernltk import sentence_tokenize
from khmernltk import word_tokenize
from khmernltk import pos_tag

从 1.5 版本开始,khmer-nltk具有以下功能:

  • sentence_tokenize —用于将文本标记成句子
  • word_tokenize —用于将文本标记为单词
  • pos_tag —用于词性标注

句子标记化

对于句子标记化,只需调用sentence_tokenize函数并传入一个字符串,如下所示:

text = 'ខួបឆ្នាំទី២៨! ២៣ តុលា ស្មារតីផ្សះផ្សាជាតិរវាងខ្មែរនិងខ្មែរ ឈានទៅបញ្ចប់សង្រ្គាម នាំពន្លឺសន្តិភាព និងការរួបរួមជាថ្'result = sentence_tokenize(text)
print(result)

运行 Python 文件时,您应该会得到以下输出:

["ខួបឆ្នាំទី២៨!", "២៣ តុលា ស្មារតីផ្សះផ្សាជាតិរវាងខ្មែរនិងខ្មែរ ឈានទៅបញ្ចប់សង្រ្គាម នាំពន្លឺសន្តិភាព និងការរួបរួមជាថ្"]

如果有与 Python 中的文本编码相关的错误,只需将

# -*- coding: UTF-8 -*-

Python 文件顶部的以下文本(在 import 语句之前)如下:

# -*- coding: UTF-8 -*-from khmernltk import sentence_tokenize
from khmernltk import word_tokenize
from khmernltk import pos_tag

如果由于字体错误而无法在命令行中打印输出,尝试通过json模块将其写入文件,如下所示:

import json...with open('temp.txt', 'w', encoding='utf8') as f:
    f.write(json.dumps(result, ensure_ascii=False) + '\n')

记住将ensure_ascii选项设置为False,以防止json包将字符更改为 unicode。

单词标记化

另一方面,word_tokenize函数接受两个附加参数:

  • separator —标记化后用于分隔文本的分隔符。默认为-,仅在return_tokens设置为假时起作用。
  • return_tokens—是返回标记化字符串还是标记列表。默认为True
result = word_tokenize(text, return_tokens=True)
print(result)

输出如下所示:

["ខួប", "ឆ្នាំ", "ទី", "២៨", "!", " ", "២៣", " ", "តុលា", " ", "ស្មារតី", "ផ្សះផ្សា", "ជាតិ", "រវាង", "ខ្មែរ", "និង", "ខ្មែរ", " ", "ឈាន", "ទៅ", "បញ្ចប់", "សង្រ្គាម", " ", "នាំ", "ពន្លឺ", "សន្តិភាព", " ", "និង", "ការរួបរួម", "ជា", "ថ្"]

在某些情况下,您可能希望删除列表中的所有空格。你可以通过列表理解和条件语句很容易地做到这一点:

result = word_tokenize(text, return_tokens=True)
result = [x for x in result if x != ' ']
print(result)

词性标注

对于词性标注,应该改用pos_tag函数。它接受单个字符串并返回一个元组列表(str,str)。

result = pos_tag(text)
print(result)

每个元组表示标记化的单词及其对应的词性标签。

[["ខួប", "n"], ["ឆ្នាំ", "n"], ["ទី", "n"], ["២៨", "1"], ["!", "."], [" ", "n"], ["២៣", "1"], [" ", "n"], ["តុលា", "n"], [" ", "n"], ["ស្មារតី", "n"], ["ផ្សះផ្សា", "v"], ["ជាតិ", "n"], ["រវាង", "o"], ["ខ្មែរ", "n"], ["និង", "o"], ["ខ្មែរ", "n"], [" ", "n"], ["ឈាន", "v"], ["ទៅ", "v"], ["បញ្ចប់", "v"], ["សង្រ្គាម", "n"], [" ", "n"], ["នាំ", "v"], ["ពន្លឺ", "n"], ["សន្តិភាព", "n"], [" ", "n"], ["និង", "o"], ["ការរួបរួម", "n"], ["ជា", "v"], ["ថ្", "n"]]

以下列表说明了所有可用的标签及其对 POS tag 的意义。

  • .:标点符号
  • 1:编号
  • a:形容词
  • n:名词(空格被视为名词)
  • o:连词
  • v:动词

完全码

你可以在下面的要点找到完整的代码。

这个包仍处于开发的早期阶段,将来可能会有更多的东西出现。

结论

让我们回顾一下你今天所学的内容。

本教程首先简要介绍了khmer-nltk包以及可用于高棉语相关 NLP 任务的特性。

接下来,通过pip install介绍安装过程。

接着详细解释了词标记化、句子标记化和词性标注。它还根据您的用例提供了一些代码片段作为参考。

感谢您阅读这篇文章!查看我的其他文章,了解更多关于自然语言处理任务的教程!

参考

  1. Github——高棉语 nltk

利用 AWS EMR 和 Pyspark 启动大数据项目

原文:https://towardsdatascience.com/kickstart-a-big-data-project-with-aws-emr-and-pyspark-38da9b34564a?source=collection_archive---------38-----------------------

利用亚马逊网络服务上的视频游戏数据进行可扩展的数据分析和机器学习

读者们好,我想写一篇关于我在日常工作中使用的 AWS 服务的文章,名为 EMR 。这项服务曾经“轻松运行和扩展 Apache Spark、Hive、Presto 和其他大数据框架。”。在本文中,我将在一个开源数据集上利用这个服务,用 Pyspark 做一些 ETL 工作和简单的分析/预测。

数据设置

对于这个实验,还有什么比育碧开源数据集更好的呢?有一个叫做的数据偷窥(来源:育碧网站,从细节上看人们可以免费使用,没有提到许可证)可以完成这项工作。我将画一个简短的设置描述,但我会邀请你阅读的文章解释更多的数据。

这个项目使用的数据来自对游戏彩虹六号围攻的跟踪,这是一款由育碧蒙特利尔工作室开发的在线战术第一人称射击游戏,于 2015 年 12 月发布,目前仍在一个重要的社区中直播(该游戏在一个月前达到了7000 万玩家)。本文将不会详细介绍彩虹六号围攻的游戏是如何构建的(但它看起来像一个反恐精英游戏,其中的角色被称为具有独特能力和装载的操作员)。尽管如此,我还是邀请你看看这个视频来理解其中的逻辑。

新的内容会定期添加到每三个月一次的季节中,并带来新的角色、化妆品、地图、模式(今年有计划😄).在本文中,收集的数据将集中在第二年的第一季,称为天鹅绒壳行动。

在这一季中,增加了两个新的运营商和一个新的地图。

在赛季期间,有几个补丁(在游戏中更新以调整/修复一些东西)已经部署(来源):

在本文中,我将重点关注包含分级模式下匹配配置的大数据(19 Gb 文件)。

EMR 设置

使用 EMR,您可以非常快速地生成一个称为集群的机器舰队,以高效的方式使用大数据框架(著名的分布式计算)。我是一个 more Spark 用户(pyspark for life ),来介绍一下我在这种情况下的设置。

随着时间的推移,已经发布了各种版本的 EMR ,但目前主要有两个分支:

版本之间的两个主要区别是 6.x 上的 Pypsark 版本是 spark 的第 3 版,而 5.x 上的版本仍然是第 2 版。火花的 x。请注意,每个版本都有其优点和缺点,所以请记住这一点(例如,在 S3 管理的文件类型)。

在这种情况下,用于测试的版本 EMR 5.31.0 (我试图使用 5.32,但它不能很好地与 EMR 笔记本配合使用)。有一个安装在工作机器上的软件列表。

作者图片

可能有很多软件(甚至 Tensorflow),但就我而言,更有用的是 Spark、Hadoop。

因为主要是为了测试,所以我只使用 M5 . XL 大型机器(一个主机和三个内核)。配置是相对的,很小,但我不需要更多(老实说,我正在使用这种方法,但我确信一台机器足以处理这些数据#showoff)。

在设置机器的步骤中,可以选择为将在这个集群上运行的应用程序添加一些配置参数;这叫分类(你可以在这里找到我的)。在这个配置文件中,有:

  • 一个与访问胶合数据目录相关的关键是轻松地构建和保存配置单元表(我将在后面解释)
  • Livy 配置避免了(至少延迟了)spark 应用程序著名的会话超时,如果 Spark 应用程序什么都不做,就会发生这种超时。

当集群启动时,您可以修改您的应用程序,但是这样,每次您正在生成时,一切都将准备就绪(小建议,如果您使用此功能将文件存储在 S3,本地编辑器不太方便更新此配置字典)

作为 EMR 领域的数据科学家,我发现一个非常有用的附加功能是 EMR 笔记本,您可以将它附加到一个集群,以便在 jupyter/lab 环境中利用 spark 内核。如果集群终止,所有的笔记本都会保存下来(之前我使用的是安装在集群上的 jupyterhub 软件,这很好,但是如果集群关闭,你会失去一切。

EMR 上的 notebook 的一个优点是能够快速建立一些探索所需的正确库;有一个很棒的资源正在介绍使用这个特性的方法。

既然设置很简单,那么让我们在分析数据之前先看看处理阶段。

抽取、转换、加载至目的端(extract-transform-load 的缩写)

需要进行一个预处理阶段来转换配置单元表中的 CSV 文件。要开始这一步的处理,需要做两件事:

  • 将 CSV 文件复制到 s3 bucket 中(在特定的子文件夹中)
  • 构建一个指向另一个 s3 位置的数据库,以存储预处理的文件,这些文件将成为配置单元表的数据。

对于这个实验,由 hive 表组成的文件的格式将是 parquet,但是也可以存储为其他类型。我使用笔记本来构建表,这些新数据可以从 AWS Athena 等其他服务中访问。

作者图片

包含关于由 dateid(游戏服务器中数据的创建日期)划分的玩家的玩家信息的表格有助于赛季数据的导航。一些图表显示了可用的匹配数、平台上的重新分配和游戏模式,以说明新构建的表。

作者图片

作者图片

从对构建的新数据的第一次分析中可以注意到:

  • 9187971 发子弹有 1588833 个匹配
  • 在 PS4 上的这个摘录中有更多的比赛(# sonyrepresents)
  • 最流行的游戏模式是 PvP 安全区

正如我们所看到的,这个数据集中有大量的匹配和数据要使用,但是我想应用一个健全性检查阶段来确定

  • 好的比赛:两队从第一轮到最后一轮看起来都一样)并且每方有五名队员
  • 拉基维特比赛:一个队至少失去一名队员,但每个队至少有五名队员
  • 不良匹配:匹配不符合前面的类别

您可以在这里找到包含所有处理过程的笔记本,但在数据处理过程中需要牢记的是:

  • 决定每场比赛的最后一轮
  • 汇总每支队伍与每轮玩家等级和等级相关的信息(有一个玩家的唯一标识符,所以我们将评估如果队伍等级和技能等级不变,队伍是相同的)
  • 对比一下第一轮和最后一轮的队伍。

无论如何,从这个处理过程中,有 10%的匹配被认为是好的,27%是不匹配的,剩下的是坏的。

您可以在这个文件中找到关于每次匹配所计算的信息的摘录;有了这些关于比赛的信息,就可以进行更深入的分析了。

公平性分析

在对匹配做了一些度量计算之后,我想看看在好的和不公平的匹配的设置中是否有一些公平性。在一个在线游戏中,团队和队友的选择背后,有一个被称为匹配的系统,它结合了玩家的知识、当前的在线设置(位置、连接质量等)。)等一些参数。

我在配对方面的知识并不丰富,但如果你感兴趣,我将邀请你看看微软在这些主题上的工作,包括以下论文 TrueskillTrueskill II (更侧重于开发玩家的排名指标)和 True match (侧重于利用玩家知识等。为了建立更好的匹配,在 GDC 2020 上有一个关于这个主题的精彩演讲。

但是从一个玩家的角度来看,我并不觉得匹配很公平(有时是#badplayer,),所以我想看看,例如,在彩虹六号的可用数据上,我们是否可以看到匹配选择中的一些问题。为了进行这种估计,我开始构建团队参考(在本例中是团队 0)的胜利预测器,基于:

  • 每个团队水平的平均值和标准差
  • 技能等级重新划分之间的欧几里德距离(对于每个团队,我计算团队中出现的每种技能等级的团队数量)
  • 比赛的配置(平台,补丁版本,游戏模式,地图)

用于进行该预测的模式是来自 Spark 中 mllib 的随机森林回归器,在 80%的 good/ragequit 匹配中进行训练,并对剩余的 20%进行评估(此处的代码)。预期是,由于有一个匹配系统,所有比赛的胜利预测应该在 50%左右。

作者图片

很高兴看到现有的系统似乎是公平的(或者至少没有太多的极端值,我认为匹配有时可以扩展研究的范围,因为缺乏适合良好匹配的可用玩家)。

为了更深入地了解这个模型,一个图表显示了这个模型中使用的特性的重要性。

作者图片

我们可以注意到,平均水平和黄金等级的数量是本质特征;我们想快速查看一下预测与各队平均水平之间的差异。我们可以看到经验的不同(你期望什么)之间的关系。

作者图片

尽管如此,所有这些分析都是在没有太多论述的情况下完成的:

  • 比赛的确切执行,老实说,通过玩游戏,你可以认识到,预测比赛的输出只基于选定的功能并不是最好的办法(也许会在另一个版本更回合的基础上工作)
  • 不知道玩家的经验(地图,操作者,历史比赛)和当前赛季不是最佳的(不知道他当前的心情如赢得比赛,不知道他是否和他的常规球队一起比赛,等等。)

无论如何,这是一个用 pyspark 构建的非常简单的估计器,有很多问题可以构建和回答。

结论

本文提供了一个 AWS 服务的机会,它可以帮助启动一些大数据框架的测试。有几个元素我在这个项目中没有用到,但可能对你的实验有用:

  • 有了 EMR,你可以衍生和停止集群,但你能做的是生成一个机器的集群,执行特定的脚本(称为 step)并关闭机器;如果我们看到以无服务器的方式更多地使用集群(以节省成本),这种方法会很有帮助
  • 如果 EMR 集群的当前设置非常有限,您可以通过使用一个名为 bootstrap actions 的元素来安装特定的库,基本上,bags 脚本将安装库、软件(如 git)或文件夹来存储数据(完全值得,但对我来说不是必需的)
  • 如果您想要运行命令行脚本(例如,spark 作业的 spark-submit),您可以在集群生成时设置一个 ssh 密钥,以便在 ssh 中建立连接,并作为 Hadoop 用户运行命令

就像事情做得很好一样,EMR 和 Sagemaker 之间有很好的联系,这里有一个很棒的文档,但是我会建议你遵循以下步骤(在他们的情况下,他们希望人们将它添加到生命周期中):

  • 添加与 sagemaker 笔记本关联的角色的跟随策略(并注意 sagemaker 笔记本的安全组)
  • 要启动集群并将其连接到您的笔记本,需要这个笔记本和一个 bash 脚本(由笔记本触发)

如果您对使用 EMR for Spark 不感兴趣,您可以将它与另一个框架一起使用,例如 dask(这里有一个使用 yarn 与 dask )的设置)。在你不知道 dask 的情况下,有一个很好的解释它是什么(以及与 Spark 的区别)。

另一个方面,第一人称射击游戏中没有太多围绕电子游戏和在线比赛的数据集,所以我会建议人们看一看育碧的这个数据集。即使他的原表单上的数据集不好用,你也可以在 Kaggle 上找到类似这里的更为消化的版本。

原载于 2021 年 4 月 5 日 https://www.the-odd-dataguy.comhttps://www.the-odd-dataguy.com/2021/04/05/cluster-and-video-game-data-introduction-to-aws-emr-and-pyspark/

Python 程序员的黑仔数据处理技巧

原文:https://towardsdatascience.com/killer-data-processing-tricks-for-python-programmers-99dd3d703607?source=collection_archive---------1-----------------------

在 Python 编程语言中,我最喜欢的一些改变数据的方法。

(src =https://unsplash.com/photos/1K6IQsQbizI

介绍

T 在过去的几年里,Python 编程语言在数据科学领域内迅速走红。这是有充分理由的,因为 Python 提供了许多现成的工具,这些工具凭借其轻量级语法,在使数据处理、分析和机器学习变得非常容易和容易方面取得了令人难以置信的成功。这是由令人难以置信的生态系统进一步编排的,该生态系统支持 Python 在该领域的自然能力。

Python 数据管理的世界是广阔的,并且还在不断扩展,所以通常很难确切地知道如何处理每种情况并掌握 Python 中的数据处理。然而,在使用这种语言时,有些知识可以用来应对任何挑战。也就是说,有几个简单的函数和模块肯定可以增强使用 Python 处理数据的体验。

笔记本

绘图

我想讲的第一个技巧是映射。这是因为在我个人看来,映射是 Python 中经常用到的东西。在有大量数据的情况下尤其如此,因为 map 方法在处理几乎任何数据问题时都非常有效。除了所有这些好处之外,这个函数使用起来相对简单。

使用这种方法的第一步是创建一个要映射的函数。我们可以通过通常的方式定义一个新函数,或者使用 Python 的 lambda 快速生成一个表达式。使用后者,我们甚至可以在一行中完成一个映射调用——这使得映射代码可能非常简洁,同时仍然非常强大。首先,我们需要注意,map 只适用于单参数函数。考虑以下列表:

data = [5, 10, 15, 20]

我们使用这个列表的目的是将一个数学变化映射到它上面。在这个例子中,我将使用五的加法。我们将快速创建一个函数来实现这一点:

def add5(x):
    return(x + 5)

现在,如果我们试图把我们的数据放入这个函数,我们会得到一个错误,因为我们不能添加一个整数到一个列表中。我们的目标是对整个列表执行这种算法,所以让我们考虑使用 map()方法。map 方法将我们想要映射的函数以及一个 iterable 作为位置参数。

newdata = map(add5, data)

这将返回一个新的“地图”类型。然后,我们可以通过将列表类型转换到这个映射,将这个类型转换到一个应用了映射的列表中:

list(newdata)

或者,我们可以只用一行代码完成同样的运算,而不用编写函数,而是为函数提供一个由 lambda 生成的表达式:

newdata = list(map(lambda x : x + 5, data))

如果你想了解更多关于 lambda 和它在 Python 中的作用,我不久前写了一篇文章,你可以看看:

熊猫面具

处理数据的另一个很好的工具是使用 Python 的 Pandas 模块屏蔽条件的能力。该模块提供了将位数组类型传递到 get index 调用中的能力。换句话说,我们可以用一个条件索引一个数据框,以便根据属性分离数据。这对于数据分析尤其有价值。这是一种在一行简单而简洁的 Python 代码中快速有效地从总体中获取样本的好方法。

import pandas as pd

考虑以下数据帧:

df = pd.DataFrame({"A" : [5, 10, 15, 20],
                   "B" : ["tall", "short", "tall", "short"]})

我们可以用任何条件语句来索引这个数据帧。当然,就列表或 Pandas 系列类型而言,我们可以期望任何 bool 类型的操作符返回一个位数组。位数组只是一个布尔列表,这个名字取自别处——我真的不知道 Python 怎么称呼这些东西。我们可以使用这些位数组来索引 Pandas 数据帧,如下所示:

a_above_ten = df[df["A"] > 10]

现在看看这个数据帧的开头:

a_above_ten.head()

(图片由作者提供)

如果您想了解更多关于条件掩码的内容,以及我喜欢在 Pandas 模块中使用的其他一些很酷的技巧,这篇文章可能会让您感兴趣:

</20-great-pandas-tricks-for-data-science-3a6daed71da0>

熊猫分组依据

除了一些激进的条件屏蔽,Pandas 还有许多打包在 DataFrame 类中的强大函数。其中一个工具是 group by,它将根据某一列的类或连续权重对数据中的观察值进行排序。考虑以下新数据框:

df = pd.DataFrame({'Animal': ['Falcon', 'Falcon',
                              'Parrot', 'Parrot'],
                   'Max Speed': [380., 370., 24., 26.]})

我们可以根据这些不同类别的属性对所有这些数据进行分组。例如,我们可以根据平均值将所有的 falcon 和 parrot 类浓缩成一个观察值:

df.groupby(['Animal']).mean()

使用该函数不仅可以节省大量内存,还可以节省大量时间。不用说,分析不同类别的平均值以及这些特性之间的关系对于真正理解这些问题中的分类非常有用。例如,在上面的数据框中,我们可以快速评估出猎鹰比鹦鹉飞得快得多。

此功能的替代方法是将这些特征放入单独的列表或数据框中,然后计算平均值。不用说,在这种情况下,利用 groupby()函数无疑节省了大量时间。

Zip()

在编程中有很多时候,人们可能希望同时对两个列表中的 dim 执行算术运算。为此,Python 为我们提供了 zip()迭代器。这个迭代器将接受两个都是可迭代的位置参数。当然,这意味着由于 zip()是一个迭代器,我们很可能用一个迭代循环来调用它。考虑以下两个列表:

a = [5, 10, 15, 20]
b = [5, 10, 15, 20]

我们将假设我们的目标是得到列表中每个 dim 的总和。如果没有 zip,在 Python 中可能会这样:

for it in range(0, len(a)):
    a[it] += b[it]

这无疑是一种有效的做事方式。然而,这种方法可能会留下一些不尽人意的地方,并且在处理比本例中提供的更多的数据时会使事情变得更加复杂。另一种方法是使用 zip()迭代器将两个列表合并成一个迭代器,同时遍历两个列表。

empty = []
for ai, bi in zip(a, b):
    z = ai + bi
    empty.append(z)

单行循环

我认为我们在处理数据时应该考虑的最后一个 Pythonic 技巧是单行迭代循环。我认为这非常有用的原因主要是因为它不同于大多数迭代。在大多数迭代循环中,我们不期望从循环中得到回报。当以这种方式完成时,这种期望就改变了。这意味着我们在那个 zip 循环中创建的空列表实际上并不需要存在,我们可以修改那个循环,改为以这种方式循环,以便完全避免添加空循环。

我们可以告诉 Python,我们想通过用方括号将它分隔开来做到这一点。在这些方括号内,我们实际上是向后写循环。这样做有很多好处。第一个优势是我们提到的,回报。然而,这种方法的另一个显著优点是在利用迭代的同时加快了速度并节省了内存。让我们使用这种方法重新创建上面的 zip 循环:

empty = [ai + bi for ai, bi in zip(a, b)]

不用说,这在很多情况下都会派上用场。虽然在 Python 中,我们可以使用 Pandas 来改变一个系列的类型,但在某些情况下,这些循环甚至可以在单独进行造型时派上用场。至少,在朱莉娅身上肯定是这样。

结论

在我看来,本文中列出的不同方法是数据处理中最基本的 Python 技巧。以我的经验来看,这些工具不仅派上了用场,而且基本上是 Python 编程世界中的必备工具。希望这篇文章和其中处理数据的方法是有用的,我希望至少这是一个有趣的阅读!谢谢你看我的文章!

金快车 vs 拉帕沃尼:浓缩咖啡对决

原文:https://towardsdatascience.com/kim-express-vs-la-pavoni-espresso-face-off-5c37158dc3b3?source=collection_archive---------12-----------------------

咖啡数据科学

对杠杆的热爱

在我姻亲家的地下室找到 la Pavoni 后,我得到了我的第一张 Kim Express。这些年来,我使用 Kim 的次数要多得多,我一直认为它的性能更好,但直到现在我也没有好的数据。

所有图片由作者提供

我不小心把另一个金快递送到了我的亲家那里,那是我的帕沃尼的住处。所以我决定离开金快车,我把拉帕沃尼带回了加州。我想我可以更多地使用这台机器,并更好地使用它。

几个星期后,我开始回头看我的拍摄数据,我有足够的重叠拍摄相同的烘烤相似的时间从两台机器。所以我把最好的照片排了出来,进行了比较。

需要注意的一点是,它们的表现不同有三个原因:

  1. 剂量大小不同(la Pavoni 为 14 克,Kim Express 为 21 克)
  2. 过滤篮(la Pavoni 的常规篮,Kim Express 的精密篮)
  3. 取消拍摄(2000 张给金快线)

绩效指标

我使用两个指标来评估技术之间的差异:最终得分和咖啡萃取。然后,我使用相关性来了解这两个指标与其他变量的关联程度。

最终得分 是记分卡 7 个指标(辛辣、浓郁、糖浆、甜味、酸味、苦味和回味)的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难确定。

使用折射仪测量总溶解固体量(TDS),这个数字结合咖啡的输出重量和输入重量用于确定提取到杯中的咖啡的百分比,称为提取率(EY)** 。**

摊牌

这些散点图比较成对的镜头。当机器具有相似的性能时,点应该在直线上。线以上表示拉帕沃尼表现更好,线以下表示金快车表现更好。

****

Kim Express 在这些指标上表现得更好,我还想比较每种烤肉,看看是否有 La Pavoni 表现更好的特定烤肉。

****

就一般统计学而言,除了最终得分(味道)之外,其他都显示出统计学差异。更多样本的最终得分可能存在统计差异。

我很乐意承认我更多地使用了 Kim,如果我以同样的方式使用 la Pavoni,也许我将能够得到那台特定机器的一些更微妙的部分。这项研究让我想起了几年前,当时我正在使用视频来尝试比较机器,现在我有了一些关于这个主题的数据。

如果你愿意,可以在推特、 YouTubeInstagram 上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。也可以关注我在订阅

我的进一步阅读:

我未来的书

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事启动页面

摄影飞溅页面

改善浓缩咖啡

断奏生活方式概述

测量咖啡研磨分布

浓缩咖啡中的粉末迁移

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡用纸质过滤器

浓缩咖啡篮及相关主题

意式咖啡观点

透明 Portafilter 实验

杠杆机维修

咖啡评论和想法

咖啡实验

KITTI 坐标变换

原文:https://towardsdatascience.com/kitti-coordinate-transformations-125094cd42fb?source=collection_archive---------2-----------------------

关于如何在 KITTI 的不同传感器坐标系之间导航的指南。

(上) KITTI 数据集左 RGB 相机图像。(下) KITTI 数据集左 RGB 相机图像,带 3D 边界框()

KITTI 数据集概述

在处理多传感器项目时,根据所使用的传感器,会出现各种坐标框架。在 KITTI 数据集的情况下,有 3 个传感器(相机、激光雷达和 GPS/IMU)。下图描述了 KITTI 数据集的传感器设置。

图 1: (左) KITTI 传感器设置。(右)各种涉及的坐标框架(来源)

有三种不同的传感器,因此在处理 KITTI 数据集时会涉及三种不同的坐标系。上图和下表显示了这些传感器坐标框架之间的关系。

KITTI GT 注释详情

KITTI 数据集的地面实况注释已在相机坐标框架(左 RGB 相机)中提供,但要在图像平面上可视化结果,或训练仅激光雷达 3D 对象检测模型,有必要了解从一个传感器到另一个传感器时起作用的不同坐标变换。下表描述了 KITTI GT 注释的详细信息。
GT 标注 =(类型|截断|遮挡| alpha | 2D bbox |尺寸|位置|分数)

坐标转换细节

KITTI 数据集提供了所有 4 个摄像机的摄像机图像投影矩阵、用于校正摄像机之间平面对齐的校正矩阵以及用于不同传感器之间刚体变换的变换矩阵。下图显示了使用激光雷达数据时涉及的不同投影。

图 2: KITTI 传感器坐标转换(作者)

威力登激光雷达坐标中的 3D 点 x 被投影到第 I 幅相机图像中的点 y 上,如下所示:

y= P(I)@ R(0)@Tvelo _ cam @x

3D 边界框从一个坐标框架到另一个坐标框架的各种变换以及所涉及的步骤在下面提到。

相机-激光雷达 3D 包围盒变换

以下步骤描述了首先使用偏航角在相机坐标系中旋转长方体,然后将其投影到激光雷达坐标系的方法。

  1. 【3D 包围盒角坐标计算(摄像机坐标框)

图 3: 3D 边界框:相机坐标系(作者提供)

x 轴->右(长度),y 轴->下(高度),z 轴->前(宽度)
3B bb 角坐标在摄像机坐标系中,坐标系是在盒子的底部中心。

2.3D BB 角的旋转由 rotation_y angle(摄像机坐标框架)协调

  1. 通过质心坐标平移框(摄像机坐标框)

  1. 3D BB 角坐标从相机坐标投影到 LiDAR 坐标框架

a.逆矫正处理 R(0)_homo 描绘了从原点 R(0)矩阵创建的 4×4 同质矩阵 (没有任何平移)。通过添加所需的 0 和 1,已将 框角从笛卡尔坐标转换为同质坐标

b.逆刚体变换

激光雷达-相机 3D 包围盒变换

下面提到的步骤定义了将 3D 边界框从激光雷达坐标框架转换到相机坐标框架的过程。

  1. 从激光雷达坐标系到摄像机坐标系的 3D BB 形心(x,y,z)投影

a.刚体变换

b.整改处理

  1. 航向/偏航角变换

航向/偏航角是激光雷达坐标系中的 w.r.t z 轴,对应于相机坐标系中的-(y 轴)

3.【3D 边界框角坐标计算】(摄像机坐标框)

图 4: 3D 边界框:相机坐标系(作者提供)

x 轴->右(长度),y 轴->下(高度),z 轴->前(宽度)【3B bb】角坐标在相机坐标系中,坐标系是在盒子的底部中心。

4.3D BB 角的旋转由旋转坐标 _y 角(相机坐标帧)

  1. 通过质心坐标平移框(摄像机坐标框)

相机图像 3D 包围盒变换

下面提到的步骤定义了将 3D 边界框从相机坐标框架转换到图像坐标框架的过程。

  1. 3D BB 角点从相机坐标系到图像坐标系的投影。 框角已通过追加所需的 0 和 1 从笛卡尔坐标转换为同质

2.使用 z 坐标归一化

结论

本文简要介绍了 KITTI 数据集,并试图解释将 KITTI GT 转换为各种传感器坐标框架的步骤。

这里介绍的大部分信息摘自 KITTI 数据集网站,鼓励读者通过引用的参考文献获取更多信息。

这个博客也被收录到了 KITTI vision 的原始数据页面:http://www.cvlibs.net/datasets/kitti/raw_data.php

参考

  1. 相机-激光雷达投影:在 2D 和 3D 之间导航
  2. 视觉遇上机器人:KITTI 数据集——Andreas Geiger
  3. KITTI 数据集

在采取进一步措施之前,要对数据了如指掌

原文:https://towardsdatascience.com/know-the-data-like-the-palm-of-your-hand-before-taking-any-further-steps-ad77e357432b?source=collection_archive---------19-----------------------

否则你的模式注定会失败。

摄影:兰蒂Unsplash 上摄影

最吸引有抱负的数据科学家的是机器学习算法的世界。我踏入数据科学领域的时候就是这样。

谈论我如何使用随机森林回归器来预测二手车价格真是太酷了。我花了大量时间调优超参数,以实现 1%的性能提升。

机器学习算法的世界很奇妙。它有可能让对数据科学充满热情的人感到惊讶。因此,学习数据科学的很大一部分由机器学习算法组成。不这样做是很有说服力的。

学这些算法没有问题。我绝对不反对它。然而,过于关注机器学习部分可能会导致我们忘记最重要的一点:理解数据。

无论您对数据科学做什么,首要任务是理解数据。你应该总是对数据了如指掌。否则,失败是必然的。

这些算法似乎在执行一些奇特的工作或神奇的操作。

机器学习算法没有什么神奇的。他们所做的只是显示你的数据中有什么。

我们仍然需要算法来探索数据中的一些底层结构或关系。但是,他们不能超越数据中的内容。性能受限于数据的质量和兼容性。

我们倾向于在探索性的数据分析上花费更少的时间,并运行算法来观察行动。相信我,这不是正确的方法。你应该花很长时间来理解你的数据。使用这种方法有几个优点。我将在文章的剩余部分详细阐述这些优势。

特征生成

机器学习算法从数据中提取特征(即列),并使用它们来学习数据。我所说的学习包括特征和目标之间的关系(在监督学习的情况下)、数据的底层结构、特征之间的相关性等等。

特征对于模型性能至关重要。先考虑一个简单的案例。您希望创建一个模型来预测二手车价格。首先想到的特征是汽车的品牌、里程和年份。

如果模型没有提供品牌,则可能预测保时捷和丰田的类似价格。当然,其他特征值(例如里程和年份)应该是相似的。

这是一个明显的例子。我们都知道什么影响汽车的价格。然而,现实生活中的案例要复杂得多。没有人会雇佣数据科学家来创建这样一个简单的模型。

我们只能通过了解数据来检测有价值或有信息的特征。它需要一个广泛的探索性数据分析过程。在某些情况下,领域知识对于特征生成也很重要。它是“了解你的数据”的一部分。

大多数算法基于特征重要性度量来评估特征。但是,它只能为输入其中的特性提供此信息。一个模型不能告诉我们它期望或者想要什么样的特性。那会是一部很酷的科幻电影。

选择哪种算法

“了解你的数据”也可以帮助你明智地选择算法。有许多机器学习算法用于监督和非监督任务。它们各有利弊。

算法的表现也取决于数据的特征。你不能只对任何数据采用一种算法。

假设您正在处理一个聚类问题。K-means 聚类算法是该领域中的一种流行算法,在大多数情况下表现良好。但是,如果数据点的分组方式无法用圆形聚类捕获,高斯混合模型可能是更好的选择。

一旦全面了解了手头的数据,选择和调整算法就变得相对容易了。大多数机器学习算法都有旋钮,可以用来调整它们。这些旋钮被称为超参数。

超参数调整通常通过为每个超参数尝试不同的值来完成。当然,这个过程不应该是完全随机的。你专注于一个特定的范围。充分了解您的数据可以帮助您更好地估计数据将如何对不同超参数的调整做出反应。

更好的评估

模型创建是一个迭代过程。通常需要多次迭代才能获得满意的结果。每次迭代都应该是前一次迭代的改进版本,这样我们就可以不断提高模型的性能。

“了解您的数据”提供了在每次迭代中要改变什么的非常有价值的见解。您知道模型如何对特定的变化做出反应。

有些情况下,你很难找到问题的根源。确定您的模型性能不佳的原因可能很有挑战性。在这种情况下,数据是您应该首先关注的地方。

结论

数据科学的一切都是从数据开始的。你的模型和你输入的数据一样好。您的数据产品或应用程序的成功很大程度上取决于数据的质量和兼容性。

任何情况或任务,第一步都是数据。走好第一步,对剩下的部分有积极作用。因此,全面理解数据或“了解数据”至关重要。

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

懂熊猫却不懂 SQL?从 Pandas 操作中了解常见的 SQL 用法

原文:https://towardsdatascience.com/knowing-pandas-but-not-sql-understand-common-sql-usages-from-pandas-operations-a6e975155202?source=collection_archive---------8-----------------------

从熊猫到 SQL

迈克尔·泽兹奇在 Unsplash 上的照片

随着数据科学就业市场的不断增长,许多人正在转行。不是每个人都有时间去攻读数据科学或类似领域的学士或硕士学位。相反,许多人使用逆向工程方法开始他们的数据科学教育。他们只是直奔主题,看看数据科学家在做什么。

好的。似乎大多数数据科学家只是用熊猫来处理一堆数据帧。因此,有抱负的数据科学追求者开始学习熊猫。你猜怎么着他们中的大多数人都可以很好地掌握这个库的要点——不仅是因为他们的辛勤工作,也是因为这个令人敬畏的数据处理工具的用户友好的设计。

然而,他们可能会错过数据科学领域的一些重要支持工具,其中一个工具是 SQL(结构化查询语言)。由于英语是国际公认的语言,SQL 是数据库世界中的一种共享语言。所有主流数据库,如 Microsoft SQL、Oracle、PostgreSQL 和 MySQL,都支持 SQL,尽管确实存在一些变体。

在本文中,我想向您展示我们如何从可比较的 pandas 操作中理解常见的 SQL 用例。可以看出,这篇文章是为那些擅长熊猫,但需要学习 SQL 的人准备的。请注意熊猫是多才多艺的,所以当我向你展示熊猫手术时,几乎可以肯定你有另一种方法来做。关键是从 pandas 转移到 SQL,而不是不同 pandas 操作之间的交叉对话。

事不宜迟,让我们开始吧。

0.样本数据集

为了当前的教程,让我们使用 seaborn 包的 mpg 数据集,它有一堆汽车的燃油效率数据,如下所示。因为有比我们需要的更多的列,为了简单起见,我只保留一些列。

演示数据集

当我介绍 SQL 语句时,我会尽量做到与数据库平台无关。在数据库中,我们就简单的称这个表为 mpgtbl 吧。虽然有些人喜欢使用大写字母作为关键字,但我个人习惯于小写字母。

1.基于特定标准选择数据

在 pandas 中,我们使用以下方法选择满足特定标准的所需行。假设我们想选择汽车,其原产地是美国,重量超过 4900 磅。

熊猫精选数据

相应的 SQL 语句如下。

**select** * 
**from** mpgtbl 
**where** origin = 'usa' **and** weight > 4900
  • select * : select 是关键字,表示选择……星号表示所有列。如果要选择一些列,可以简单的列出来:select mpg, horsepower
  • from the_table:指定从中选择数据的表格
  • where:指定选择标准。请注意,比较运算符只是简单的=,而不是==。AND 逻辑运算符是and
  • 字符串:对字符串使用单引号通常是个好主意,尽管有些数据库确实支持双引号。

2.选择前 3 行

在 Pandas 中,我们可以使用head函数来选择前 N 行。相应的 SQL 语句使用limit关键字,如果定义了标准,它会指定匹配标准的前 N 行。

# Pandas
df.head(3)# SQL
**select** * 
**from** mpgtbl 
**limit** 3

你想选择第 4-6 行吗?这里有一个可能的解决方案。

# Pandas
df.iloc[3:6, :]# SQL
**select** *** **from** mpgtbl 
**limit** 3 
**offset** 3;

在 Pandas 中,我们可以使用iloc属性进行数据选择。请注意iloc使用 index,index 从 0 开始,所以要得到第 4–6 行,我们需要指定 3:6,在 6 之前结束。

在 SQL 中,我们可以通过请求偏移量 3 来提供额外的限制,这样我们就可以得到第 4–6 行。

3.选择唯一的值

Pandas 有内置的unique函数,可以为特定的列选择不同的值。

# Pandas
df['origin'].unique()# SQL
**select** **distinct** origin 
**from** mpgtbl

在 SQL 中,我们将简单地把distinct关键字放在列或列列表之前。

4.排序行

我们使用sort_values对熊猫中的行进行排序。在 SQL 中,我们使用 order 关键字。默认情况下,在这两种情况下,值都按升序排序。当您需要按降序排列数据时,我们有不同的选项。

# Pandas
df.sort_values(['mpg', 'weight'], ascending=[False, True])# SQL
**select** *** **from** mpgtbl 
**order** **by** mpg **desc**, weight

在 SQL 中,当需要反转列的顺序时,需要在列名后面使用desc

5.成员资格检查

这个操作在 pandas 和 SQL 之间是相似的,都涉及到以某种形式使用与in相关的关键字。

# Pandas
df[df['origin'].isin(['japan', 'europe'])]
df[~df['origin'].isin(['usa'])]# SQL
**select** *** **from** mpgtbl 
**where** origin **in** ('japan', 'europe');**select** *** **from** mpgtbl 
**where** origin **not** **in** ('usa')
  • Pandas 使用isin方法来确定行的值是否包含在项目列表中。要否定布尔值,只需在表达式前使用~符号。
  • SQL 使用innot in进行成员资格检查。SQL 不使用方括号,而是使用一对括号来列出所有项目。

6.分组频率表

我们经常需要知道按一列或多列分组的项目出现的频率。你应该这么做。

# Pandas
df.groupby('origin').size()
df.groupby(['origin', 'model_year']).size()# SQL
**select** origin, ***count*(***)** 
**from** mpgtbl 
**group** **by** origin; **select** origin, model_year, ***count*(***) 
from** mpgtbl 
**group** **by** origin, model_year
  • groupby函数创建一个GroupBy对象,size方法将使用该对象计算每组的行数。
  • 在 SQL 中,count方法将计算记录的数量。当数据被分组时,它将分别对每组进行计数。这里的关键语法是group by col1, col2, col3…
  • 在这两种情况下,您都可以指定多个列。

7.创建频率表

是上一个的后续操作。假设我们想要创建一个数据表用于长期存储。在熊猫身上,我们创造了一个新的DataFrame。为了引入一个新特性,假设我们想给 frequency count 列命名为car_count

# Pandas>>> df_summary = df.groupby('origin', as_index=False).size().rename(columns={"size": "car_count"})
>>> df_summary
   origin  car_count
0  europe         70
1   japan         79
2     usa        249

如上图所示,该操作使用参数as_index的设置作为groupby功能中的False

让我们看看如何在 SQL 中实现它。

# SQL**create** **table** car_origin **as** 
**select** origin, ***count*(***) as** car_count 
**from** mpgtbl 
**group** **by** origin;
  • 创建新表的语法是create table tbl_name as the_select_stmt。实际上,从语句中选择的数据将作为数据保存在新创建的表中。
  • 在前一节中,我们已经使用了count方法,但是在这里,使这个操作不同的是给 count 字段一个名称,语法是count(*) as the_name

8.总体聚合操作

除了频率之外,我们还对数据集执行了一些聚合操作,比如最大值、最小值和平均值。

# Pandas
df.agg({"mpg": ["mean", "min", "max"]})

如果希望对其他列执行这些聚合函数,可以向 dictionary 参数添加额外的键值对。相应的 SQL 操作如下所示。

# SQL
select *avg*(mpg), *min*(mpg), *max*(mpg) from mpgtbl

如果您想给这些计算字段命名,您仍然可以使用calculated_field as the_name格式。

9.按组的聚合操作

扩展前面的操作,我们经常需要按组创建聚合。这是通过在 pandas 中使用groupby函数操作 GroupBy 对象来实现的,如下所示。

# Pandas
df.groupby('origin').agg(
    mean_mpg=("mpg", "mean"),
    min_hp=("horsepower", "min")
)

上面的操作使用了命名聚合,它不仅指定了列,还指定了要应用的函数。当然,正如开始时提到的,还有其他方法来创建集合。您可以在我的上一篇文章中找到更多关于 GroupBy 对象的操作。

</8-things-to-know-to-get-started-with-with-pandas-groupby-3086dc91acb4>

当您在 SQL 中需要聚合时,它的语法对我来说看起来稍微干净一点。

# SQL**select** ***avg***(mpg) **as** mean_mpg, ***min***(horsepower) **as** min_hp 
**from** mpgtbl 
**group** **by** origin

到目前为止,一切对你来说都应该很简单。

10.连接表格

当我们有多个DataFrame想要合并时,可以在 pandas 中使用merge函数,如下图。请注意,df_summary 是在#7 中创建的,它有两列:origincar_count

df.merge(df_summary, on="origin")

在 SQL 中,我们可以有非常相似的连接逻辑。

**select** *** **from** mpgtbl
**join** car_origin **using** (origin)

这里的新关键字是连接和使用。join 连接要联接的两个表,而 using 用于指定列。请注意,当相同的列用于连接时,该语法是相关的。

在更一般的情况下,表可能有不同的列用于连接。以下是您在这两种方法中可以做的事情。

# Pandas
df.merge(another_df, left_on="colx", right_on="coly")# SQL
**select** *
**from** tbl1 x
**join** tbl2 y **on** x.col1 = y.col2

您现在使用on而不是using来指定 SQL 中用于连接的列。另一件要注意的事情是,您可以创建一个简短的表引用,以便于引用。在示例中,我们分别将这两个表称为xy

默认情况下,连接是inner类型的。SQL 中也有其他类型的连接。这里有一个有用的参考,你可以开始。

https://www.w3schools.com/sql/sql_join.asp

11.更新记录

当您需要更新特定列的记录时,您可以在 Pandas 中执行以下操作。假设“福特都灵”的正确重量应该是 3459,而不是 3449。

>>> df.loc[df["name"] == "ford torino", "weight"]
4    3449
Name: weight, dtype: int64
>>> df.loc[df["name"] == "ford torino", "weight"] = 3459
>>> df.loc[df["name"] == "ford torino", "weight"]
4    3459
Name: weight, dtype: int64

我们使用loc属性访问特定的单元格并成功更新记录。SQL 有类似的逻辑,下面显示了一个可能的解决方案。

**update** mpgtbl
**set** weight = 3459
**where** name = 'ford torino'

这里新增的关键词是updateset。一般语法如下:

**update** tbl_name
**set** col1 = val1, col2 = val2, ...
**where** the_condition

12.插入记录

当您需要向现有数据帧添加记录时,有多种方法可以完成。这里向您展示了一个可能的解决方案。为了简单起见,让我们假设您想要再添加两条记录,而这些记录只是现有的DataFrame对象中的最后两行。

new_records = df.tail(2)
pd.concat([df, new_records]).reset_index(drop=True)

当您插入新记录时,您可以使它们成为另一个DataFrame对象,然后您可以使用concat方法来连接这些DataFrame对象。下面是如何在 SQL 中进行同样的操作。

**insert** **into** mpgtbl
**select** *** **from** mpgtbl **order** **by** "index" **desc** **limit** 2
  • 我们使用insert into语法向现有表中添加新记录。
  • select部分只是提取表中最后两条记录的一种方法。请注意,该表包含一个名为index的列,它恰好是一个 SQL 关键字,因此我们可以使用双引号使它成为一个列名。顺便说一下,我倾向于对任何名字使用非关键字,只是为了避免这样的麻烦。

更多情况下,我们希望添加单独的数据记录,而不是从现有表中提取的记录。在 SQL 中,更常见的插入操作如下所示。

**insert** **into** tbl_name (col_list)
**values** (value_list1), (value_list2), ...

具体来说,我们在值keyword之后指定每个记录的值。请注意,如果要为所有列添加值,可以省略(col_list)部分。

13.删除记录

数据集可能包含我们不需要的记录。在大多数情况下,我们会删除符合特定标准的记录。对于熊猫来说,drop方法是完美的。一个可能的解决方案如下所示。

df.drop(df[df['name'] == 'ford torino'].index)

SQL 解决方案涉及到 delete 关键字的使用。请对条件的指定极其谨慎,因为如果您离开条件,所有内容都将从表中删除。

**delete from** mpgtbl
**where** name = 'ford torino'

14.添加列

有时我们需要向现有的数据集中添加新的列。在熊猫身上,我们可以做一些如下的事情。请注意,这只是一个微不足道的例子,我们知道数据集只包含 20 世纪的年份,所以我们只需添加 1900,使年份成为 4 位数。

df['full_year'] = df['model_year'] + 1900

要在 SQL 中做同样的操作,我们需要引入一个新的关键字— alter,它涉及到表的更新。让我们看看。

**alter** **table** mpgtbl
**add** full_year **as** (model_year + 1900)

我们只需要在关键字add之后指定新的列并包含计算。如果希望将计算出的列物理存储在数据库中,可以在计算之后添加persisted关键字。

15.移除列

如您所知,在 Pandas 中,drop方法不仅适用于行,也适用于列。下面的代码片段向您展示了如何在 Pandas 中放置列。

df.drop(columns=["mpg", "horsepower"])

与添加列类似,删除列是对现有表的一种修改。因此,正如你可能猜到的,这个操作使用了alter

**alter** **table** mpgtbl **drop** **column** name;

16.串联数据集

在上一节中,当我们学习插入记录时,我们在 Pandas 中使用了concat方法。如您所知,这种方法通常用于连接共享相同列的数据集。

pd.concat([df, df])

在 SQL 中,这个操作涉及到union关键字,如下所示。

**select** *** **from** mpgtbl
**union** **all**
**select** *** **from** mpgtbl

请注意,您可以选择省略all,在这种情况下,将只保留后一个表中的不同记录。

结论

在本文中,我们回顾了您在数据科学项目中可能遇到的 16 种常见数据操作。具体来说,我们假设您对基于 Pandas 的操作有很好的理解,并且我们访问了使用 SQL 执行的相同或基本相同的操作。我希望您现在已经很好地理解了 SQL。

感谢阅读这篇文章。通过注册我的简讯保持联系。还不是中等会员?使用我的会员链接,通过支持我的写作。

了解你的作物的现在和未来

原文:https://towardsdatascience.com/knowing-the-present-and-future-of-your-crop-1ce20abb37b9?source=collection_archive---------24-----------------------

行业笔记

我们如何使用计算机视觉来了解番茄作物的状态,从而预测其产量

托马斯·伊斯基耶多·加西亚·法利亚——中菲特·皮耶曼(表示研究)

摘要

用于作物监测的计算机视觉是精准农业的重要组成部分。在本文中,我们将分享我们设计计算机视觉解决方案的经验,从番茄生命周期不同阶段的图像中收集特征。看完这篇文章,你会确信你可以使用实例分割来精确地计算一个番茄桁架的果实和花朵的数量。希望所做的决定将有助于您的下一个实例分割任务,并且它可能会鼓励您使用计算机视觉的力量来解决类似的任务。

介绍

价值 120 亿美元[1]的精准农业正变得越来越重要,正在彻底改变农业部门。为了预测这些精准农业系统的收成,基于大数据和人工智能的算法正在开发中。精准农业的一个关键组成部分是作物状态的登记。作物状态被用作预测算法的输入,并用于评估这种算法的性能。今天,作物的登记(监测)仍然是由种植者自己完成的手工过程,但预计计算机视觉将开始发挥重要作用。

温室番茄种植者通常通过监测选择的植物来跟踪生长过程。通过给植物桁架贴标签来进行监控(1,2,3,…)。因此,定期登记每束花、座果和可收获果实的数量。在这一过程中,种植者面临的挑战是在整个登记过程中保持一致:例如,一个水果在被归类为可收获之前应该有多红?不一致会导致水果产量看似激增或下降。当一个人在整个季节进行监控时,这些影响是可以避免的。然而,当在温室之间进行比较时,或者当单个温室经历人员或班次的变化时,问题就出现了。

计算机视觉是流水线的一部分

用于估计作物状态的一致性问题使得计算机视觉方法成为感兴趣的方法,并且是如下的潜在过程

  1. 移动应用程序用于拍摄标记桁架的照片。
  2. 收集的图片被上传到云端,在那里计算机视觉模型对标记的桁架进行分类。
  3. 特定的计算机视觉问题是预测出现在桁架中的每种作物类型的实例的数量,该桁架主要出现在由移动电话拍摄的图像中。

在这个过程中,与固定相机相比,使用手持相机的优点是标记桁架的图像不会被番茄植株的叶子遮挡。

在该计算机视觉任务中分析的相关生长阶段(被视为类)是:芽、花、集芽(小绿番茄)、集(绿番茄)和可收获(红番茄)。由于 tomato truss 生命周期的性质,桁架只能有特定的实例组合。例如,桁架不能同时有可收获的果实和花朵。

本文的目的是研究计算机视觉模型可以达到的精度水平。

调查解决方案

设计的管道使客户能够通过使用手机应用程序拍摄番茄桁架的照片,然后预测桁架的状态(如图 1 所示)。

同样的管道也用于构建训练数据集。通过使用相同的手机应用程序,照片被捕获并自动上传到云数据库。

图 1 调查了服务和训练计算机视觉模型的管道。(图片由作者提供)

移动应用程序

移动应用程序是使用 React-Native [3]构建的。该应用程序通过要求每个标记桁架的高质量图片来指导用户完成作物注册过程。每张图片都被直接上传到数据库(AWS S3 桶),之后通过 API 调用,来自计算机视觉模型的预测被提供给用户。这允许用户在出现明显错误的情况下纠正预测。此外,将专家知识纳入循环对于生产绩效的反馈非常重要,也有助于为未来的模型迭代标记图像。

计算机视觉模型:Mask-RCNN 和 Detectron 2

为了预测桁架中每种类型(花蕾、花、集蕾、集、可收获)出现的实例数量,使用了一种实例分割方法,该方法使用掩模 RCNN 模型[4]和脸书的框架,检测器 2 [6]。由于推理时间与用例无关,因此选择了 Mask-RCNN 模型,该模型使用具有 FPN 体系结构的 Resnet-101 模块作为主干。Detectron2 在 ImageNet 数据库上提供预训练的权重,通过在小数据集上进行训练来实现高性能。

注释图像

注释图像是系统的主要瓶颈。有几个开源工具可用于注释图像分割。CVAT [5]导致了几个与图像方向相关的问题(很可能元数据被 CVAT 错误地解释了)。因此,考虑使用 Coco-Annotator [2]。Coco-Annotator 提供了关于实例数量、它们的分布以及标记整个数据集所花费的时间的统计数据。后者在试图了解数据集的平衡程度以及对其进行注释所花费的时间时非常有用。对于这个任务,116 张图像被标记,每张图像花费大约 20 分钟。

训练模型

令人惊讶的是,当在小数据集上训练时,该模型在没有实质性修改的情况下已经给出了不错的性能。使用来自 ImageNet 数据库的权重,在 30 幅图像上进行初始训练,而没有对模型的头部(RoI、分割头部或分类头部)进行任何超参数调整或改变。训练是使用 Nvidia 1080ti 11GB GPU 和 AMD ryzen 7 CPU 完成的。每 80 步/迭代,该模型针对由 16 幅图像组成的验证数据集运行。每 80 次迭代花费不到 3 分钟,平均训练 3000-5000 次迭代。目视检查性能;典型结果如图 2 所示。

图二。左图显示检测到桁架的实例,而忽略背景中的实例。右图显示了遮挡情况下比预期更好的性能。(图片由作者提供)

在分析中,考虑了两个指标:平均精度(AP)和均方根误差(RMSE)。后者是根据下列分组类型计算的:花,(已发芽&已结果)和可收获的果实。

在初始训练之后,使用超参数调整来进一步提高性能。通过分析平均精度、概率阈值、学习速率、冻结层数、感兴趣区域框的大小和学习调度进行了优化。发现最佳值是:概率阈值 0.8,冻结层数 2,ROI 框大小[32,64,128,256,512]。对于学习速率,观察到最佳值 0.0025,从第 1000 次迭代开始,每 500 次迭代,基于步长的衰减为 0.1。收敛通常是在 2000–3000 次迭代后发现的,耗时约 1.5 小时。

图三。两个不同数据集训练时的平均精度收敛。数据集之间的差异是在训练和测试之间进行随机分割。

还探索了图像增强以进一步提高性能。考虑了诸如随机裁剪、随机改变对比度、随机改变亮度和随机旋转的增强技术。然而,这些增强并没有导致任何改善,这可能是由于图像的性质及其对相机焦点和颜色的依赖。

在完全优化了模型之后,获得了表 1 中列出的 RMSE 性能。这些值表明花和可收获的果实比组芽集&集更容易检测。

表 1。就分组类型的 RMSE 而言,已实现的性能

使用训练好的模型来衡量每周的收成

当使用计算机视觉模型来测量每周的收获量时,要考虑观察到的几周之间可收获的水果数量之间的差异。假设两次观测的误差不相关是合理的

其中,左边是(每周)可收获产量的标准误差,右边是在图像中计算可收获产量的标准误差。相对误差取决于一株植物(茎)的可收获数量。对于像 Merlice 这样的一些番茄品种,每株(茎)的典型周产量是 4.5 倍。这给出了相对生产误差

通过包括更多的植物,可以通过对多个测量值(图像)进行平均来进一步减小误差。人们发现,由于植物之间的误差预计是不相关的

人们可能希望以一定的相对误差来测量产量。表 2 给出了各种误差和设备数量的一些典型数字。从表中可以看出,当在 10 株植物上进行登记时,10%的相对生产误差要求可收获果实的数量的 RMSE 约为 1.0。这接近于训练模型所达到的 RMSE(表 1)。

表二。需要 RMSE 的实现一定的误差生产的收获。

结论

本文展示了计算机视觉如何帮助植物注册,以便持续监控生长情况,并帮助种植者优化其生长策略。使用移动电话应用程序来捕捉桁架的照片,这些照片被上传到 AWS 环境,在该环境下进行计算机视觉预测。用 Mask-RCNN 模型结合 Detectron2 训练数据,在 100 张图像上获得了用于计数花的约 0.9 的 RMSE、用于计数芽集和集的 1.8 的和用于可收获果实的 1.1 的。通过使用该模型来测量 10 个计数植物上可收获果实的周产量,发现 Merlice 番茄的相对标准误差约为 10%。每周生产更多水果的番茄类型将导致更低的相对误差。

研究了图像增强以进一步改善计算机视觉模型的性能,但是没有导致精确度的增加。建议考虑其他形式的图像增强,如参考文献[7]中讨论的简单复制粘贴增强。

参考

[1] Bhutani,a .,& Wadhwani,P. (2019,4 月)。精准农业市场| 2019–2025 年统计报告。全球市场观察公司https://GM Insights . com/industry-analysis/precision-farming-Market

[2]布鲁克斯,J. (2021 年 4 月 28 日)。 COCO-Annotator 。GitHub。https://github.com/jsbroks/coco-annotator

[3]脸书。(2019 年 8 月 16 日)。 facebook/react-native 。GitHub。https://github.com/facebook/react-native

[4] He,k .,Gkioxari,g .,Dollár,p .,& Girshick,R. (2017 年)。屏蔽 R-CNN 。ArXiv.org。https://arxiv.org/abs/1703.06870

[5]b . Sekachev(2021 年 4 月 29 日)。 openvinotoolkit cvat 。GitHub。https://github.com/openvinotoolkit/cvat

[6]吴,杨,&(2020 年 5 月 26 日)。Facebook research/detector 2。GitHub。https://github.com/facebookresearch/detectron2

[7] Ghiasi,g .,Cui,y .,Srinivas,a .,Qian,r .,Lin,T.-Y .,Cubuk,e .,Le,q .,& Zoph,B. (2020 年)。简单的复制粘贴是一种强大的数据扩充方法,用于实例分割https://arxiv.org/pdf/2012.07177.pdf

用 PyKEEN 和 Neo4j 完成知识图

原文:https://towardsdatascience.com/knowledge-graph-completion-with-pykeen-and-neo4j-6bca734edf43?source=collection_archive---------1-----------------------

使用知识图嵌入模型集成 PyKEEN 库和 Neo4j 用于多类链接预测

几周前,我遇到了图表数据科学顾问 Francois Vanderseypen。我们决定联合起来,开始一个图形机器学习博客系列。这篇博客文章将介绍如何执行知识图完成,这只是一个多类链接预测。我们不只是预测一个链接,我们还试图预测它的类型。

知识图补全示例。图片由作者提供。

对于知识图完成,底层图应该包含多种类型的关系。否则,如果您只处理单一类型的关系,您可以使用不考虑关系类型的标准链接预测技术。示例可视化只有一个节点类型,但实际上,您的输入图也可以包含多个节点类型。

我们必须将知识图嵌入模型用于多类链路预测流水线,而不是普通的节点嵌入模型。
你可能会问,有什么区别。
节点嵌入模型仅嵌入节点,而知识图嵌入模型嵌入节点和关系。

通过知识图嵌入模型嵌入节点和关系。图片作者。

描述模式的标准语法是,起始节点称为 head (h),结束或目标节点称为 tail (t),关系为 r。

TransE 这样的知识图嵌入模型背后的直觉是,如果关系存在,头部加上关系的嵌入接近于尾部的嵌入。

图片由作者提供。

那么预测就很简单了。例如,如果您想要预测特定节点的新关系,您只需对该节点加上关系嵌入求和,并评估是否有任何节点接近嵌入和。

要了解更多关于知识图嵌入模型的详细信息,我建议你去看看 Jure Leskovec 的以下讲座。

议程

如果你读过我以前的博客文章,你可能知道我喜欢使用 Neo4j,一个原生的图形数据库,来存储数据。然后,您将使用 Neo4j Python 驱动程序获取数据,并将其转换成一个 PyKE EN 图。PyKEEN 是一个 Python 库,其特点是知识图嵌入模型,并简化了多类链接预测任务的执行。最后,您将把预测存储回 Neo4j 并评估结果。

我已经准备了一个 Jupyter 笔记本,里面包含了这篇帖子的所有代码。

在 Neo4j 桌面中准备数据

我们将使用 Hetionet 数据集的子集。如果你想了解更多关于数据集的知识,请查阅原始论文

为了跟随本教程,我建议您下载 Neo4j 桌面应用程序。

https://neo4j.com/

一旦安装了 Neo4j 桌面,就可以下载数据库转储并使用它来恢复数据库实例。

在 Neo4j Desktop 中恢复数据库转储。图片作者。

如果您在恢复转储文件方面需要更多的帮助,大约一年前,我写了一篇关于它的博客文章。

如果您成功地恢复了数据库转储,您可以打开 Neo4j 浏览器并执行以下命令。

CALL db.schema.visualization()

该过程应显示以下图表模式。

图形模型。图片作者。

我们的 Hetionet 图子集包含基因、化合物和疾病。它们之间有许多关系,你可能需要在生物医学领域才能理解它们,所以我不会深入细节。

在我们的例子中,最重要的关系是化合物和疾病之间的治疗关系。这篇博文将使用知识图嵌入模型来预测新的 treats 关系。你可以把这个场景想象成一个药物再利用的任务。

皮基恩

PyKEEN 是一个不可思议的、简单易用的库,可用于知识图完成任务。
目前,它拥有 35 个知识图嵌入模型,甚至支持开箱即用的超参数优化。
我喜欢它是因为它的高级接口,使得构建 PyKEEN 图和训练嵌入模型变得非常容易。
查看其 GitHub 知识库了解更多信息。

https://github.com/pykeen/pykeen

将 Neo4j 转换为 PyKEEN 图

现在我们将进入这篇文章的实际部分。

首先,我们将把 Neo4j 图转换成 PyKEEN 图,并分割训练测试数据。首先,我们必须定义与 Neo4j 数据库的连接。

函数执行一个密码查询,并以 Pandas 数据帧的形式返回输出。PyKEEN 库有一个from_labeled_triples,它接受一个三元组列表作为输入,并从中构造一个图。

这个例子有一个通用的 Cypher 查询,可以用来获取任何 Neo4j 数据集并从中构造一个 PyKEEN。注意,我们使用节点的内部 Neo4j ids 来构建三元组数据帧。出于某种原因,PyKEEN 库希望三元组元素都是字符串,所以我们简单地将内部 id 转换为字符串。在官方文档中了解更多关于如何构建三元组和可用参数的信息。

现在我们有了 PyKEEN 图,我们可以使用split方法来执行训练测试数据分割。

没有比这更容易的了。我必须祝贺 PyKEEN 的作者开发了如此简单的界面。

训练知识图嵌入模型

现在我们有了可用的训练测试数据,我们可以继续训练知识图嵌入模型。在本例中,我们将使用旋转模型。我不太熟悉嵌入模型的所有变体,但是如果你想了解更多,我会推荐我上面链接的 Jure Leskovec 的讲座。

我们不会执行任何超参数优化,以保持教程简单。我选择使用 20 个历元,并将维度大小定义为 512。

附注:我后来了解到,在一个大型复杂的图上,20 个时期可能不足以获得有意义的训练;尤其是在如此高的维度下。

多类链接预测

PyKEEN 库支持多种方法进行多类链接预测。您可以找到网络中的前 K 个预测,或者您可以更具体地定义特定的头节点和关系类型,并评估是否有任何新的预测连接。

在本例中,您将预测L-天冬酰胺化合物的新 treats 关系。因为我们使用内部节点 id 进行映射,所以我们首先必须从 Neo4j 中检索 L-天冬酰胺的节点 id,并将其输入到预测方法中。

将预测存储到 Neo4j

为了更容易地评估结果,我们将把前五个预测存储回 Neo4j。

您现在可以打开 Neo4j 浏览器并运行下面的 Cypher 语句来检查结果。

MATCH p=(:Compound)-[:PREDICTED_TREATS]->(d:Disease)
RETURN p

结果

L-天冬酰胺与五大疾病之间的预测治疗关系。图片由作者提供。

由于我不是医学博士,我不能说这些预测是否有意义。在生物医学领域,关联预测是产生假设而不是盲目相信结果的科学过程的一部分。

解释预测

据我所知,知识图嵌入模型对解释预测没那么有用。另一方面,您可以使用图中现有的连接将信息呈现给医生,让他决定预测是否有意义。

例如,您可以使用以下 Cypher 查询来调查L-天冬酰胺结肠癌之间的直接和间接路径。

MATCH (c:Compound {name: "L-Asparagine"}),(d:Disease {name:"colon cancer"})
WITH c,d
MATCH p=AllShortestPaths((c)-[r:binds|regulates|interacts|upregulates|downregulates|associates*1..4]-(d))
RETURN p LIMIT 25

结果

L-天冬酰胺和结肠癌之间的间接途径。作者图片

左边是结肠癌,右边是 L-天冬酰胺结。在可视化的中间有连接两个节点的基因。

出于好奇,我在谷歌上搜索了 L-天冬酰胺与结肠癌的结合,看到了这篇 2019 年的文章。

https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6412063/

虽然我外行的眼睛并不真正理解是否应该增加或减少天冬酰胺来帮助治疗疾病,但至少看起来两者之间似乎有关系。

结论

大多数时候,您会处理具有多种关系类型的图。因此,知识图嵌入模型对于多类链接预测任务非常方便,在这种情况下,您需要预测新的链接及其类型。例如,如果预测的链接类型是 treatscauses ,则差别很大。

从 Neo4j 到 PyKEEN graph 的转换是通用的,可以在任何数据集上工作。因此,我鼓励您尝试一下,并给我一些反馈,告诉我您对哪些用例感兴趣。

和往常一样,代码可以在 GitHub 上获得。

参考

  • Bordes,a .,Usunier,n .,Garcia-Duran,a .,Weston,j .,和 Yakhnenko,O. (2013 年)。为多关系数据建模转换嵌入。在神经信息处理系统的进展。柯兰联合公司..
  • 生物医学知识的系统整合优先考虑药物的再利用。 eLife 第 6 卷 e26726。2017 年 9 月 22 日,doi:10.7554/eLife.26726
  • Ali,m .,Berrendorf,m .,Hoyt,c .,Vermue,l .,Galkin,m .,Sharifzadeh,s .,Fischer,a .,Tresp,v .,和 Lehmann,J. (2020)。将光明带入黑暗:统一框架下知识图嵌入模型的大规模评估。arXiv 预印本 arXiv:2006.13365
  • 孙志清,智,建,。(2019).旋转:通过复杂空间中的关系旋转嵌入知识图。
  • 杜,冯等。“SOX12 通过调节天冬酰胺合成促进结直肠癌细胞增殖和转移。”细胞死亡&疾病第 10 卷,3 卷 239 页。2019 年 3 月 11 日,doi:10.1038/s 41419–019–1481–9

知识图视角

原文:https://towardsdatascience.com/knowledge-graph-perspectives-88b69c7b1921?source=collection_archive---------19-----------------------

KGS 洞察

搭建从资源描述框架到标记属性图的桥梁

KG 代表 DBpedia(休谟工具)中可用的哲学家的影响链—图片由作者提供

我的原创文章发表在 GraphAware 网站的以下链接:https://graph aware . com/Hume/2021/09/23/kg _ perspectives _ RDF _ to _ lpg . html

从生物技术到电子商务,从情报和执法到金融科技,知识图已经成为各领域实体间关系建模的最有力工具之一。从 2012 年谷歌提出的第一个版本开始,现代 KGs 的功能已经在各种应用程序中使用,包括搜索引擎、聊天机器人和推荐系统。

KGs 至少有两个特征。第一个视角关注知识表示,其中图被编码为使用资源描述框架 (RDF)数据模型形式化的语句集合。它的目标是标准化 Web 上的数据发布和共享,确保语义互操作性。在 RDF 领域中,智能系统的核心是基于在可用语句的语义层上执行的推理。

第二个视角关注图的结构(属性和关系)。这个愿景在所谓的标记的属性图 (LPG)中实现。它强调了图形数据的特征,在数据分析、可视化和以图形为动力的机器学习系统的开发方面实现了新的机会,以推断进一步的信息。

在加入 GraphAware 之前,我在学术界的大部分经验都致力于使用 RDF 和本体论开发的知识。在本文中,我想描述采用 LPG 来改进和扩展 RDF 标准和技术中可用的功能的机会。为了具体分析这样的机会,我使用了 Neo4j 的新语义组件。将使用 Hume 平台的可视化组件显示结果。

探索新语义特征

KGs 的两种观点背后的愿景对用户体验有着直接的影响。在 RDF 图的情况下,不同类型的用户(如开发人员和数据分析师)与序列化为语句的数据进行交互。因此,在图上执行的任何操作都意味着操纵这样的语句,在使用 SPARQL(RDF 图的语言查询)时也是如此。在 LPG 中,Cypher 查询语言在节点、边和相关属性方面与图结构有更透明的交互。

这种细微的差异对用户体验和性能有重大影响。在 LPG 的情况下,数据的冗余性大大降低,因为所有表示数据属性(作为对象的文字值)的语句(或三元组)都变成了节点的属性。作为一个主要的结果,如果在 RDF 域中有多个语句,每个语句对应一个数据属性,那么对于 LPG 来说,有一个唯一的数据结构,它是带有属性的节点。考虑下面的构造查询,从与 Friedrich_Nietzsche 相关的 DBpedia 中获取包含数据属性(也称为文字值)的所有三元组:

PREFIX dbpedia: <http://dbpedia.org/resource/>
CONSTRUCT { 
    dbpedia:Friedrich_Nietzsche ?prop ?value .
}
WHERE {
    dbpedia:Friedrich_Nietzsche ?prop ?value .
    FILTER isLiteral(?value)
}

该查询检索 98 条语句,每条语句对应一个数据属性。然而,如果我们使用 Neosemantic 插件在 Neo4j 中上传所有这些语句,我们会看到图中只创建了一个节点。

在数据导入之前,我们可以为图形数据库设置一个初始配置:

CALL n10s.graphconfig.set({
        handleMultival: 'ARRAY',
        multivalPropList : [ 
            '[http://dbpedia.org/ontology/abstract'](http://dbpedia.org/ontology/abstract'),
            '[http://www.w3.org/2000/01/rdf-schema#comment'](http://www.w3.org/2000/01/rdf-schema#comment'),
            '[http://www.w3.org/2000/01/rdf-schema#label'](http://www.w3.org/2000/01/rdf-schema#label')]
});

这种配置设置有利于信息的一致性。新语义的默认行为是为每个属性只加载一个值。但是,在像 DBpedia 这样的多语言和大规模的 kg 中,多个值可以与一个数据属性相关联。例如,_ rdfs:label _ 通常包括一个特定实体的所有标签,该实体在维基百科上可用的每种语言都有一个标签。在这个初始配置之后,我们可以使用 Neosemantics 获取过程将数据加载到 Neo4j 中。我们从前面介绍的构造查询开始。

CALL n10s.rdf.import.fetch("https://dbpedia.org/sparql","Turtle", {
headerParams: { Accept: "application/turtle"},
payload: "query=" + apoc.text.urlencode("
    PREFIX dbpedia: <http://dbpedia.org/resource/>
    CONSTRUCT {
        dbpedia:Friedrich_Nietzsche ?prop ?value .
    }
    WHERE {
        dbpedia:Friedrich_Nietzsche ?prop ?value .
        FILTER isLiteral(?value)
    }
  ")
});

我们使用 Hume 的图形可视化特性来查看结果:

休谟形象化——作者的形象

正如您在 Hume visualization 系统中看到的,一个带有相关属性的节点被添加到画布中。正如所料,当前的获取过程添加了来自不同语言的属性值,以保持信息的一致性(在下面的示例中,我们将看到如何将过滤器应用于英语)。

通过分析 RDF 和 LPG 的特点,我们注意到,当比较等价的 SPARQL 和 Cypher 查询时,冗余也减少了。为了观察这种差异,首先,我们定义了一个 SPARQL 构造查询,它在不同的哲学家之间创建了“影响”链。我们还设置了一个配置,只保留英文标签。使用 Neosemantics 获取过程将该查询的结果加载到 Neo4j 中:

CALL n10s.rdf.import.fetch("https://dbpedia.org/sparql","Turtle", {
    handleVocabUris: "IGNORE",
    languageFilter: "en",
    headerParams: { Accept: "application/turtle"},
    payload: "query=" + apoc.text.urlencode("
        PREFIX dbo: <http://dbpedia.org/ontology/>
        PREFIX dbp: <http://dbpedia.org/property/>
        CONSTRUCT {
            ?parent dbo:influenced ?child .
            ?parent a dbo:Philosopher .
            ?child a dbo:Philosopher .
            ?parent dbp:birthDate ?birthDate1 .
            ?child dbp:birthDate ?birthDate2 .
            ?parent rdfs:label ?label1 .
            ?child rdfs:label ?label2 .
        }
        WHERE {
            ?parent dbo:influenced ?child .
            ?parent a dbo:Philosopher .
            ?child a dbo:Philosopher .
            ?parent dbp:birthDate ?birthDate1 .
            ?child dbp:birthDate ?birthDate2 .
            ?parent rdfs:label ?label1 .
            ?child rdfs:label ?label2 .
    }")
});

事实证明,设置语言过滤器特别有用。几乎 80%的 RDF 三元组已经被删除:2005 个加载的三元组对 10000 个解析的三元组(10000 是网上可用的 DBpedia 端点的结果限制)。然后,从这个影响图开始,我们想要检索在弗里德里希·尼采之上的第三个影响级别(3 跳)的所有哲学家,按照他们的出生日期排序。相关的 SPARQL 查询如下:

PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
PREFIX dbpedia: <http://dbpedia.org/resource/>
SELECT DISTINCT ?child3 ?label3 ?birthDate3 {
    ?child3 dbo:influenced ?child2 .
    ?child2 dbo:influenced ?child1 .
    ?child1 dbo:influenced dbpedia:Friedrich_Nietzsche .
    ?child3 a dbo:Philosopher .
    ?child2 a dbo:Philosopher .
    ?child1 a dbo:Philosopher .
    ?child3 rdfs:label ?label3 .
    ?child3 dbp:birthDate ?birthDate3 .
    FILTER (lang(?label3) = 'en') .
} ORDER BY DESC(?birthDate3)

相应的密码查询如下:

MATCH (s:ns0__Philosopher
)-[:INFLUENCED*3]->(nietzsche)
WHERE nietzsche.uri = 'http://dbpedia.org/resource/Friedrich_Nietzsche'
RETURN s
ORDER BY s.ns1__birthDate

从这个例子中可以看出,与 SPARQL 查询相比,Cypher 查询要紧凑得多。主要原因是 SPARQL 不是一个图遍历引擎,您必须显式地指定所有的跳数,操作语句。这一方面决定了对查询性能的重要影响。使用 SPARQL,开发人员定义了如何遍历图来检索他需要的信息。这决定了查询的执行严格依赖于查询内容,如果没有结构化或者没有正确排序,查询内容的效率会非常低。

另一方面,Cypher 背后的逻辑是定义做什么,以一种非常接近人类思考图结构导航的方式指定检索什么数据。因此,性能取决于查询引擎实现,直接计算图遍历策略。另一个有趣的元素是,在 SPARQL 查询中,我们必须使用下面的表达式指定标签的语言:过滤器(lang(?label3) = 'en') 。关于 Cypher,我们不定义标签语言,因为它已经在图形配置程序中设置好了。

新语义学观感

从我个人使用 RDF 的经验开始,我已经测试了新语义的许多特性,还有一些我想在将来探索的特性。我发现图形配置程序非常有用。正如我前面提到的,考虑到用户的特定需求,这个功能允许对 RDF 图应用转换。传统上,Web 上可用的通用 RDF 图为单个数据属性提供多个值,例如, rdfs:label 。在这种情况下,我们可以在不同的语言中使用不同的标签。如果最终用户只对英语标签感兴趣(没有语言标签),您可以将此行为设置为一个配置参数。

另一个功能配置与移除 RDF 名称空间有关,我将在以后进一步探讨。当组合覆盖相同领域的不同本体以区分相似属性或类的起源时,名称空间特别有用。然而,这一特性有可能只为企业 kg 创建冗余信息,而这些信息通常是使用唯一的私有本体构建的。

我还欣赏将 RDF 图加载和导入 Neo4j 的动态方式,并彻底研究了从 SPARQL 结果中获取数据的过程。然而,用户也可以从 Web 上或他们自己的系统上的静态文件中加载 RDF 数据。我相信这些导入策略涵盖了文件加载有问题的所有情况,并且避免了为导入数据编写粘合代码。Hume Orchestra 组件采用了类似的原理,它允许您转换来自多个分布式源(S3 桶、Azure Blob 存储、第三方 API、RDBMS 表等)的数据。)转换成由 KG 表示的单个和连接的源。

另一个特性是 RDF 图模型和 LPG 图模型之间的映射。这个特性允许将 RDF 词汇表映射到图元素(标签、属性名、关系名),并保持两个域中使用的词汇表是不同的。例如,我们可以将 RDF 中的 SKOS:narrow 映射到 LPG 中的:CHILD 关系类型。RDF 专家非常熟悉映射语言的概念:万维网联盟(W3C)已经创建了标准来形式化关系数据库模式和 RDF 表示之间的映射(参见:https://www.w3.org/TR/r2rml/)。

结论

总之,我的总体印象是新语义允许保留 RDF 领域的所有特性。高级别的可配置性将使用户能够根据他们的需求选择这些功能的子集,同时利用所有的 LPG 功能。正如我在本文中所展示的,这些功能使您能够更透明地与图形数据结构进行交互。RDF 语句可以被直接视为图的节点、关系和属性,可以利用 Cypher 语言的简单性和表达能力来研究。

如果你喜欢我的文章,你可以支持我使用这个链接https://medium.com/@giuseppefutia/membership成为一名中等会员。

自然语言处理中的知识图@ ACL 2021

原文:https://towardsdatascience.com/knowledge-graphs-in-natural-language-processing-acl-2021-6cac04f39761?source=collection_archive---------2-----------------------

最先进的,2011 年夏天

你的 KG 相关的 NLP 研究指南,ACL 版

欢迎来到我们关于知识图的 NLP 论文的第三次常规综述,这次发表在 ACL 2021 !今年你不想错过的流行趋势是什么?👀

米尔科维在 Unsplash 上拍摄的背景照片,由作者改编

ACL'21 仍然是最大的 NLP 场地之一:今年接受了 700+完整论文和 500+ACL 论文的研究结果📈。除此之外,不要忘记通常有影响力的短论文和广泛选择的研讨会教程。我试图从所有这些曲目中提炼出一些 KG 的论文,放到一个帖子中。以下是今天的话题:

对于数据集爱好者,我用💾,因此您可以更轻松地进行搜索和导航。话虽如此,你可能想要在🧭.这个高质量内容的海洋中导航

我尽力了,我保证。作者迷因

神经数据库和检索

神经修复仍然是发展最快和最热门的领域之一🔥NLP 中的主题:它现在可以处理 100+ GB 规模的数十亿个向量和索引。如果 NLP 栈足够成熟,我们能否从神经方面接近数据库研究的圣杯,嗯,数据库?🤨

作者迷因

是啊! Thorne 等人 引入了自然语言数据库(表示为 NeuralDB ) : 没有预定义的严格模式,相反,你可以在写作时将事实存储为文本话语。

注意:如果你更喜欢数据库,并把“合适的数据库场所”排在更高的位置,那么基本原则也在同一组作者最近的VLDB 21 论文中有所阐述。

它是如何工作的?什么是查询引擎?有什么连接吗?(没有联接—不是数据库!)

一个引入的 NL 数据库由 K 个文本事实(本研究中为 25-1000 个)组成。本质上,对文本事实的查询回答任务被框架化为检索🔎+提取质量保证📑+聚合🧹(to 支持最小/最大/计数查询)。给定一个自然语言问题,我们首先要检索几个相关事实(支持事实)。然后,有了一个查询和 m 个支持集,我们执行一个连接( select-project join ,SPJ 操作符,好了,现在它有资格成为一个数据库了😀)对每一对(查询、支持)寻找答案或确认其不存在(抽取式 QA)。最后,通过简单的后处理来聚合连接结果。

🧱Can:我们只是把所有的 k 个事实连接起来,放在一个大的转换器里?从技术上来说,是的,但是作者表明,当数据库大小超过 25 个事实时,效率相当低。相比之下,多阶段方法允许并行处理和更好的缩放。目前看来,NL 数据库的症结在于检索机制——我们不想创建一个包含所有可能组合的强大集,而是只提取相关的组合。到目前为止,这是通过类似 DPR 的密集检索(支持集生成器)来完成的,它是针对每个查询的带注释的支持集来训练的。

说到注释和训练,作者用一组新的数据集支持 NLDBs💾Wikidata 中的 KG 三元组在句子中被动词化了(并且你可以生成你自己的 DB 来改变许多事实)。

🧪实验表明,T5 和 Longformer(具有更大的上下文窗口)在给定黄金检索结果时只能在最小的图上与神经 SPJ 算子竞争。否则,在 25 个以上事实的较大数据库上,它们的性能会迅速恶化,而 SPJ + SSG 则稳定得多。这篇论文对 NLP 的普通读者来说非常容易理解,绝对是我今年的最爱之一👍!

神经数据库架构。来源: 索恩等人

随着检索变得越来越重要(即使不是在神经数据库的环境中),ACL'21 围绕开创性的密集段落检索及其相关检索器家族拥有丰富的新方法集合。

来源:

陈等 解决了实体消歧的一个常见且重要的信息检索问题,即你有许多实体,它们共享相同的名称(表面形式)但具有不同的属性(👈亚伯·林肯——政治家和亚伯·林肯——音乐家)。

为了更系统地评估寻回犬,作者设计了一个新的数据集💾琥珀色(歧义实体检索)收集自维基百科-维基数据页面对齐。具体来说,数据集强调🌟“受欢迎程度差距”🌟:在大多数情况下,检索器会退回到其索引中最突出的实体(例如,被查看次数最多、内容更多的页面),我们希望量化这种转变。Wikidata 实体和谓词被用作参考 KG 集合,以生成新的复杂消歧任务(称为琥珀集)。

AmbER 由两部分组成: AmbER-H (消除人类歧义)和 AmbER-N (非人类,如电影、乐队、公司),并在 3 个任务中测量性能:QA、槽填充和事实检查。

🧪在实验中,作者表明目前的索塔猎犬确实遭受了低效的歧义消除——在涉及稀有实体的任务中的表现下降了 15-20 分📉。也就是说,要提高检索器的精度还有很多工作要做。

来源: 山田等人

现代寻回犬的一个常见计算问题是它们的索引大小:拥有 2100 万个条目的 DPR 占用了大约 65GB 的内存。 Yamada 等人 提出了一个优雅的解决方案:使用学习散列的思想让我们训练一个近似符号函数的散列层,使得连续向量变成+1/-1 的二进制向量。然后,我们可以使用高效的 CPU 实现汉明距离来计算粗略的 top-K 候选(文中为 1000),而不是昂贵的点积(索引上的 MIPS)。然后,我们可以很容易地计算一个问题和 1000 个候选项之间的点积。

BPR 方法(二进制段落检索器)有几个优点:1️⃣索引大小减少到大约 2 GB(从 66GB 减少到 66gb!)而没有大的性能下降(预计只有前 1 名的准确度受到影响);2️⃣业务流程再造在效率质量挑战中名列前茅👏。总的来说,这是一篇有影响力的短文的很好的例子!

📬最后,我将从会议中概述一些更多的以检索为中心的作品: Sachan 等人 检验了逆向完形填空任务和掩蔽显著跨度的预训练如何提高 DPR 在开放领域问答任务中的表现。 美拉德、卡普欣等人 设计一🌐通用寻回犬🌐,一个经过多任务训练的检索器,适用于许多 NLP 任务,并在结合 QA、实体链接、槽填充和对话任务的 KILT 基准上进行评估。 Ravfogel 等人 展示了一个很酷的神经提取搜索系统的演示(通过新冠肺炎数据)供大家玩。

kg-增强语言模型:🪴🚿

BERTology 的一个主要趋势是探索大型 LMs 的事实知识,例如,输入查询“史蒂夫·乔布斯出生在[面具]”以预测“加利福尼亚”。然后,我们可以使用各种基准来量化这些探针,如 LAMA 。换句话说,我们是否可以将语言模型视为知识库?到目前为止,我们有证据表明 LMs 可以正确预测一些简单的事实。

但是真的,他们能吗?🤔

我们的发现强烈质疑先前文献的结论,并证明当使用基于提示的检索范式时,当前的 MLMs 不能作为可靠的知识库。——曹等人

来源: 曹等人

曹等人 的工作几乎给整个领域泼了一盆冷水——他们发现,大部分报告的表现都可以归因于🥴的虚假相关性,而不是实际的“知识”。作者研究了 3 种类型的探测(图示👈):提示案例(又名少拍学习)和上下文。在所有场景中,LMs 表现出许多缺陷,例如,案例只能帮助识别答案类型(人、城市等),但不能指向该类中的特定实体。这篇论文非常容易阅读和理解,并且有很多说明性的例子,🖌,所以我建议即使对于那些不积极从事这方面工作的人也要好好读一读。

有趣的是,在 ACL'21 的 Wang 等人 也报道了开放域问答中的类似结果。他们分析了巴特和 GPT-2 的性能,得出了几乎相同的结论。是时候反思我们如何在 LMs 中打包显性知识了?🤔

当你意识到 LMs 一直在作弊。来源: gfycat

从前面的帖子中,我们知道存在相当多的 Transformer 语言模型,这些模型中包含了来自知识图的事实。让我们欢迎两位新家庭成员!👨‍👩‍👦‍👦

、王等人、提出 K-Adapters ,一种基于预训练 LMs 之上的知识注入机制。有了 K-Adapters,你就不需要从头开始训练一个大的变压器栈了。相反,作者建议在已经预先训练好的冷冻模型(他们用 BERT 和 RoBERTa 做实验)的层间放置几个适配器层,例如,在第 0 层、第 12 层和第 23 层之后。冻结的 LM 功能与可学习的适配器功能连接在一起,并在一组新任务上进行训练——在这里,它是基于对齐的维基百科-维基数据文本三元组的 T-REx 数据集的 1️⃣关系预测;2️⃣依赖树关系预测。实验表明,这种方法提高了实体分类、常识问答和关系分类任务的性能。

来源: 王等人

艾丽卡预训练任务。来源: 秦等人

秦等 设计 ERICA ,一种用实体和关系信息丰富 LMs 的对比机制。具体来说,他们增加了两个更多的损失标准传销:实体歧视(🖼👈)和关系歧视。在实体辨别的例子中,预训练文档具有成对的注释🍏 🍏实体跨度。要求该模型产生真实对的更高余弦相似度🍏 🍏而不是消极的🍏 🍅通过对比损失项。ERICA 在关系预测和多跳 QA 任务中的低资源微调场景(1–10%的训练数据)中表现特别好。

KG 嵌入和链接预测

多关系 KG 嵌入模型的长处可以是自身容易受到对抗性攻击的弱点吗?一群算法经常被用来比较它们捕捉某些关系模式的能力,比如对称、反转、组合等等。一个简短的回答是 😕

来源: 巴德瓦杰等人

Bhardwaj 等人 的一部颇有见地的著作研究了各种类型和方向的中毒🔫通过添加对抗性三元组嵌入模型(查看示例说明👈).它确实假设我们都可以访问预训练的权重,并且可以执行前转呼叫(白盒设置)。在提出搜索敌对关系和潜在诱饵实体的几种方式后,实验表明最有效的攻击利用了对称性🦋模式(至少在标准 FB15k-237 和 WN18RR 图上)。有趣的是,没有几何或平移先验的卷积模型 ConvE 看起来对设计攻击最有弹性🛡,即普通的 TransE 或 DistMult 中毒更严重。

⚖️本人还概述了 Kamigaito 和 Hayashi 对用于训练 KG 嵌入模型的两个流行损失函数家族的理论相似性的长期预期研究: softmax 交叉熵负采样,特别是自我对抗负采样。在众多的研究中(例如无耻之徒来自 ICLR 的 Ruffinelli 等人20),我们已经看到受过这样或那样损失训练的模型表现出相似的性能。最后,在这项工作中,作者通过 Bregman 散度的透镜来研究它们的理论性质。看完这篇文章你想带回家的两个重要信息:1️⃣ 自我对立的负采样带标签平滑的交叉熵非常相似。2️⃣ 交叉熵模型可能比负抽样模型更适合。如果你忘记用更多的损失函数进行实验,你现在可以引用这篇论文😉

来源: 曹等人

🚨新 LP 数据集警报🚨Freebase 和 Wordnet 图表作为基准已经存在太久了,作为一个社区,我们最终应该采用偏差更少、规模更大的新数据集作为 2021-2022 测试套件。 曹等 探究 FB15k-237 和 WN18RR 的测试集并发现(如图👈)通常,测试三元组要么对人类来说是不可预测的,要么没有太大的实际意义。受此激励,他们创建了一组新的数据集💾infer wiki 16K&infer wiki 64K(基于维基数据😍)其中测试案例在列车组中有接地。他们还为三元组分类任务创建了一组未知的三元组(除了真/假)。🧪The 的主要假设在实验中得到证实——当测试三元组在训练中确实有基础时,嵌入模型确实在非随机分裂上运行得更好。

让我们欢迎👋链路预测的几种新方法。1️⃣BERT-ResNetbylovelace 等人 通过 Bert 对实体名称和描述进行编码,并通过 resnet 风格的深度 CNN 传递三元组,随后进行重新排序和提炼(相当多的内容都放在那里!).该模型产生了很大的改进📈在常识风格的图形上,如 SNOMED CT Core 和 ConceptNet,大量知识编码到文本描述中。接下来, Chao 等人 提出了 PairRE ,这是 RotatE 的一个扩展,其中关系嵌入被分成特定于头部和特定于尾部的部分。PairRE 在 OGB 数据集上展示了极具竞争力的结果。顺便说一下,模型已经在 PyKEEN 库中可用,用于训练和评估 KG 嵌入模型。😉 李等 设计聚类,用于时态 KG 链接预测的模型。CluSTeR 在第一个线索搜索阶段使用 RL,在第二个阶段在它们上面运行 R-GCN 。4️⃣:最后,我很高兴看到更多关于超关系知识的研究!🎇(在这里找到我的评论文章)。 王等人 在 Transformer 的基础上构建了他们的 GRAN 模型,采用了包括限定词交互在内的改进的注意机制。我很想看看它在我们新的 WD50K 超关系基准测试中的表现!

实体对齐:2 个新数据集💾

实体对齐(EA) 的任务中,你有两个图(可能共享相同的关系集),这两个图具有两个不相交的实体集,比如来自英文和中文 DBpedia 的实体,你必须确定一个图中的哪些实体可以映射到另一个图中。

多年以来⏳⌛️,实体对齐数据集意味着两个图之间存在完美的 1-1 映射,但这对于现实世界的任务来说是一个相当人工的假设。最后, 孙等人 通过悬空实体(那些没有各自映射的实体)的概念更正式地研究这种设置。

来源: 孙等人

作者建立了一个新的数据集💾, DBP 2.0 ,其中只有 30–50%的实体是“可映射的”,其余的是悬空。因此,这意味着您的对齐模型必须学习一种方法来决定一个节点是否可以被映射——作者探索了 3 种可能的方法来做到这一点。

由于大多数 EA 基准已经在非常高的值附近饱和,所以看到添加“嘈杂的”实体急剧下降是很有趣的📉整体表现。朝着更实用的设置又迈进了一步!

来源: 帕胡贾等人

通常,如果一个图的一些边可以隐式地包含在一些文本中,那么我们就说 KG-Text 对齐。特别是,我们感兴趣的是是否有任何方法可以用文本嵌入来丰富图形嵌入,反之亦然。 Pahuja 等人 通过设计一个新颖的数据集,提供了对这个问题的大规模研究💾源自全英文维基百科和维基数据:1500 万个实体和 2.61 亿个事实🏋。作者分析了 4 种对齐方法(例如,通过将 KG 嵌入投影到文本嵌入空间)并联合训练 KG /文本嵌入。

🧪任务方面,作者测量了少量链接预测(超过 KG 三元组)和类比推理(超过文本部分)的性能。事实上,与单一模态相比,所有 4 种对齐方法确实提高了两项任务的质量,例如,在类比推理中,融合 KG 信息的最佳方法带来了超过 Wikipedia2Vec 基线的 16%的绝对提高💪。在链路预测任务中,融合可以产生高达 10%的命中@ 1 的绝对改进。

值得注意的是,该方法假设两个独立的模型进行联合训练。绕过校准问题,在这个新任务中探索 KG 增强 LMs(一个在 KG 上预训练的模型)肯定是有趣的。

KG 构建,实体链接,关系抽取

从文本中自动构建🧩kg 是一项非常重要且受欢迎的任务,适用于许多工业应用。

蒙达尔等人 提出了从 ACL 选集(例如,本文所评论的所有论文都属于该文集)中 KG 构造 NLP 论文的工作流程。得到的图形称为 SciNLP-KG 。它并不完全是标题中所说的端到端的(作者在第 5 节中通过错误传播来证明),而是由 3 个阶段组成(🖼👇)围绕关系抽取。SciNLP-KG 建立在之前的研究 (NAACL'21)的基础上,提取任务数据集指标** (TDM) 的提及。KG 模式有 4 个不同的谓词: evaluatedOnevaluatedByco referencerelated 来捕获 TDM 实体之间的链接。作者构建了两个版本的 SciKG:一个小型 MVP 和一个具有 5K 个节点和 15K 条边的成熟版本。这种方法的一个优点是,自动构建的大 SciKG 与代码为的论文有很大的重叠(大约 50%的实体)!**

是的,这只是一个受限领域中的 4 个关系,但这是一个良好的开端——毫无疑问,更多可扩展的端到端方法将随之而来。

来源: 蒙达尔等人

对已知任务的非传统方法。来源: Reddit

在像 BLINK 和这样的神经实体链接器的时代,江、Gurajada 等人** 的一部作品对这个问题采取了非正统的观点:让我们在一个加权的基于规则的框架(逻辑神经网络)中将文本启发与神经特征结合起来。事实上,LNN-埃尔是更大的神经符号 NSQA 系统的一个组成部分,但在下面的 KGQA 部分会有更多的介绍。**

📝该方法LNN-埃尔,要求实体提及与目标 KG 的前 K 名候选人已经在那里。一些文本特征可以是,例如,提及和候选之间的 Jaro-Winkler 距离或基础 KG 中的节点中心性。眨眼和神经方法也可以作为特性插入。然后,专家创建一组具有权重的规则,例如,将 w1 分配给 Jaro-Winkler,将 w2 分配给 BLINK,并且通过边际损失和负采样来学习权重。

🧪 LNN-EL 的表现与 BLINK 相当,并返回一个可解释的加权规则树。此外,它可以推广到使用相同的底层 KG 的其他数据集👏

➖There 也存在一些缺点:看起来眨眼实际上是整体表现中的关键因素,占规则总权重的 70-80%。因此,自然的问题是——制定复杂的专家规则实际上值得吗?🤔其次,作者使用 DBpedia lookup 来检索 top-K 候选项,并“假设类似的服务存在或者可以在其他 kg 上实现”。不幸的是,情况往往并非如此——事实上,这种候选检索系统只存在于 DBpedia 和(部分)Wikidata 中,而对于其他大型 kg 来说,创建这样的机制非常重要。然而,LNN-EL 为 KGQA 的神经符号实体链接奠定了坚实的基础。

当盒子嵌入尺寸过小时。资料来源:gifsboom.net

实体链接通常是紧密相连的🤝使用实体类型。 Onoe 等人框嵌入(Box4Types) 解决了细粒度实体类型化(当你有成百上千个类型时)的问题。通常,细粒度的实体被建模为向量,具有编码的提及+上下文向量和所有类型向量的矩阵之间的点积。相反,作者建议从矢量转向📦方框(d 维超矩形)。此外,不是“只是盒子”,而是 Gumbel(软)盒子(neur IPS’20),当“只是盒子”不相交时,允许在角落情况下进行背面投影。🖼👇给出了一个很好的直觉:本质上,我们将所有的相互作用建模为几何运算符📦将它们的体积标为 1 会给概率解释带来额外的好处。

🧪实验表明,盒子至少和更重的基于向量的模型一样好,在某些情况下甚至超过它们 5-7 个 F1 分👏。除此之外,还有许多具有洞察力的定性实验。总的来说,我很喜欢阅读这篇论文——强烈推荐它作为一篇优秀论文的范例。

来源: Onoe 等人

让我们在关系提取论文上补充几句,这些论文在几个基准测试中略微改进了 SOTA。 胡等 研究预训练的 KG 实体嵌入如何帮助进行包级关系抽取(实际上只是一点点),并创建新的数据集 BagRel-Wiki73K 💾基于维基数据的实体和关系! 田等 提出了一个透视图、 SteREoRel、关于 re 的任务,即段落中的实体、关系、词语都可以建模为一个 3D 立方体。一段的 BERT 编码被发送到几个解码器,以重建正确的关系三元组。最后, 纳德格里等人 提出了 KGPool ,其中来自句子的已知实体诱导出具有后续 GCN 层和池的局部邻域。****

基于 KGs 的问题回答:时态、会话、AMR

当代 KGQA 主要关注经典静态图,即当你有一组固定的实体和边,而问题没有任何时间维度时。

⏳但是时候到了! Saxena 等人 介绍了一个对时态 kg 进行 QA 的大规模任务,那些在边上有时间戳的 kg 像(Barack Obama, position held, POTUS, 2008, 2016)一样表示其有效性。它开启了一系列全新的简单和复杂的问题,围绕着时间维度:“奥巴马之前/之后谁是总统?”、“奥巴马当总统的时候谁演钢铁侠?”诸如此类。作者创建了一个新的数据集💾CronQuestions (基于维基数据😍)具有超过 KG 的 410K 个问题,具有 123K 个实体、大约 200 个关系和 300K 个三元组,并带有时间戳。**

🧐毫不奇怪,BERT 和 T5 不能以任何像样的准确性处理这样的问题,所以作者将 EmbedKGQA (我们在之前的 ACL 评论中强调的来自 ACL'20 的方法)与预先训练的时态 KG 嵌入 TNT-ComplEx (来自 ICLR'20 评论)结合起来,看,通过这个系列,您可以与大多数最新的好东西保持同步😉)在一款新的 CronKGQA 中。本质上,我们将一个句子的 BERT 嵌入作为一个关系嵌入,并将其传递给静态的&时态评分函数,如下所示。
🧪Experimentally,CronKGQA 对简单问题的命中率约为 99%,但对更复杂的问题仍有改进的空间。对于 KGQA 社区的其他人:看,有一个新的非饱和基准👀!

来源: 萨克森纳等人

🗣对话式 KGQA 处理连续的问答步骤,其中在生成对底层 KG 的查询和形成预测时,上下文和对话历史具有更高的重要性。在对话式 KGQA 中,后续问题往往是最难处理的。传统上,对话历史被编码为一个向量,并且没有对最近实体的特殊处理。此外,后续问题中的显式实体命名经常被省略(因为人类通常擅长共指消解),所以自然的问题是:我们如何才能跟踪当前对话中最相关的实体?**

🎯蓝和江提出了焦点实体的概念,焦点实体是一个在对话中被讨论的实体,我们很可能会提出后续的问题。方法假设我们可以访问 SPARQL 端点来动态查询 KG(显然,这不是端到端的神经网络,而是我们可以对整个 Wikidata 的规模更大的图进行操作)。

主要的想法是,我们可以通过计算一个实体转移图中实体的分布,动态地改变正在进行的对话的焦点。1️⃣* 首先,我们通过围绕对话的起始节点扩展图形(1-2 跳)来构建这样一个 ETG。2️⃣然后,ETG 通过 GCN 编码器获得更新的实体状态。3️⃣更新的实体状态与焦点实体预测器(见下图)中的对话历史聚集在一起,该预测器建立关于作为焦点实体的实体分布。4️⃣最后,更新的分布被发送到现成的答案预测器,该预测器返回对当前话语的答案。***

改变焦点实体的🧪The 想法在对话问题CSQA 的对话版本上产生了显著的收益(平均超过强基线 10 分)💾!最大的误差来源源于不正确的关系预测,因此肯定有改进的空间。

来源: 兰和姜

最后,让我们用一个问题来讨论一下普通的 KGQA 用一个图表给出一个答案。Kapanipathi 和来自 IBM Research 的另外 29 个人提出了一个巨大的神经符号 KGQA 系统, NSQA ,围绕 AMR 解析构建。NSQA 是一个流水线系统,有专门定制的组件🧩.也就是说,输入的问题首先被解析成 AMR 树(预训练组件 1️⃣),然后树中的实体被链接到背景 KG (2️⃣就是上面描述的lnn-El!).通过 AMR 树的基于规则的 BFS 遍历来构建查询图。而关系链接是一个单独的组件 SemRel (3️⃣在另一篇 ACL'21 论文中由 Naseem 等人 提出)。****

NSQA 严重依赖 AMR 帧及其互连来更好地将树解析为 SPARQL 查询,例如,“AMR-unknown”节点将是查询中的变量。当然,为了处理 AMR 输出,在精心创建的规则中投入了大量工作👏另一方面,所有其他组件都以某种方式使用变压器。长得相当漂亮的的确像极了!🧪实验表明,AMR 解析在 LC-QuAD 1.0 基准上的准确率约为 84%(与人类专家创建的结果相比),而整体 NSQA 将 F1 度量提高了约 11 个点。亲爱的 IBM,一些公开可用的源代码会非常方便😉****

来源: 卡帕尼帕蒂等人

TL;博士;医生

你进入了最后一部分!无论是从目录还是在阅读了一些相关章节后,感谢您的时间和对这一领域的兴趣😍。请在评论中让我知道你对这整个努力和总体形式的看法!

从神经数据库到问题回答,知识库正被应用于比以往更多的任务中。总的来说,我认为这是一个做 KG 研究的好时机:你总是可以找到一个合适的位置,解决理论和实践的挑战,这可能会被社区中成千上万的人使用。

期待我们在下一次会议上看到的!

下一堆文件!资料来源:tenor.com

知识超图和对象-角色建模

原文:https://towardsdatascience.com/knowledge-hypergraphs-object-role-modeling-ef0f58f38066?source=collection_archive---------21-----------------------

当两个世界已经合二为一时,它们却发生了碰撞

通过世界各地各种项目的努力,知识超图已经获得了关注,并且看起来各种技术正在汇聚到一个基本思想上。

超图被定义为一种边可以链接到多个顶点的图。在接受《走向数据科学》采访时,人工通用智能(AGI)研究员 Ben Goertzel 将元图描述为扩展超图(或完全不同的东西),其中边也可以链接到其他链接。事实上,在与麻省理工学院的莱克斯·弗里德曼的一次采访中,【Mathematica 和 Wolfram Alpha fame 的】史蒂夫·沃尔夫勒姆将超图描述为“任何数量的事物之间可以有联系”。这将使元图和超图成为同样的东西,因此我们在本文中坚持使用术语超图

在更详细地描述超图以及它们如何被对象-角色建模涵盖之前,有趣的是 Goertzel 为 AGI 设计的 OpenCog 架构有一个名为 AtomSpace 的超图模型,Wolfram 开始与 Fridman 谈论宇宙的基本性质是由“原子……以及它们之间的联系”组成的。

与其说我们深入物理学,不如说我们认识到概念模型可以分解成基本的(或原子的)原理和组成部分。

让我们来看一个超图:

超图。图片来自维基媒体。知识共享许可

绿色斑点代表连接顶点 V3、V5 和 V6 的超边

图论的标准图中,你只会有连接两个顶点的边(就像上面的棕色斑点)。

超图,特别是如果扩展到元图的概念,更进一步,有连接边的边。现在让我们看一个例子:

一个注入超图性质的对象-角色模型。图片作者。

边 TimetableBooking 链接讲师、时间段和房间的概念,其中到时间段的链接是到链接学期、工作日和周期的边的链接。所以我们有边连接边。当然,这个模型是一个为大学预订讲座的时间表预订模式。我们正在看一个对象-角色模型。

在弗里德曼对沃尔夫拉姆的采访中,弗里德曼问道,“一个 hypgraph 可以映射到一个 graph…这只是一种方便的表示?”Wolfram 回答说,“没错。”

那是什么意思?好吧,如果我们把我们的对象-角色模型转换成一个属性图模式(就像你在图数据库中使用的那样),我们会得到:

转换为属性图模式的 Hypergraph。图片作者。

NB 在我们从超图到属性图模式的转换中,我们的三元边以其自身的权利成为节点/顶点。所谓的边,时间表预订和时隙,现在变成了节点/顶点。

在大量发表的关于对象-角色建模的研究中,我还没有看到对象-角色建模和超图之间的联系。事实上,我敢说反之亦然。因此,我们正站在两个世界正在碰撞的关头。随着超图越来越受欢迎,它总是存在,但在其他观察世界的方法和方式中变得模糊不清。

两个世界总是一体的

关于这个练习最有趣的事情可能是对象-角色建模最初是为关系数据库的分析和设计而设计的。我们示例中的关系模型如下所示:

关系模型的实体关系图。图片作者。

请注意,在我们的关系模型中,我们在时间表预订中的边现在跨越四(4)个概念,讲师 Id、学期、工作日和周期 NR…即,时间表预订的主键随着我们的边加入我们的超图对象角色模型中的边而完善。对象-角色建模可以追溯到关系数据库兴起的时候,所以我们的核心概念实际上已经有 30 年或更久了。

Wolfram 在他与 Fridman的采访中说:“认识到你可以用那种方式(使用超图)做事情,打破了我在看到这是如何工作之前在模型中感觉到的某些类型的任意性”。如果 Wolfram 以前从未见过对象-角色建模,那么在研究超图时就很容易理解灯泡是如何打开的。

对象角色建模和 AGI 的未来

在早期的一篇文章中,我讨论了对象角色建模在人工智能未来的价值,以及以最原子的方式呈现的模型非常适合 AGI 解决方案,这些解决方案需要原子事实作为 AGI 算法运算的基础数据。随着我研究得越来越多,对我来说似乎很清楚的是,许多研究正在转向对日常图形和图论的超图研究。

对象-角色建模对于超图的研究是理想的,因为 ORM 将模型分解为元素/原子部分。我描绘了一个世界,其中 OpenCog 的 AtomSpace 使用对象-角色建模来可视化,并且 ORM 在对 AGI 中心数据模型的建模和解释中占据了自然的位置。

感谢阅读。如果时间允许,我会写更多关于对象角色建模、超图和人工智能的文章。

———————End—————
勘误表:早先,er 图实体 TimetableBooking 的主键跨 5 个字段/列,而不是 4 个(20210523)。

如何用机器学习找到韩国演员狂看

原文:https://towardsdatascience.com/korean-actor-recommendation-using-machine-learning-e7ba26e3926?source=collection_archive---------46-----------------------

让我根据你目前最喜欢的韩国演员来给你找出下一个你最喜欢的韩国演员

安德鲁·海默尔(安德鲁夫)在 Unsplash 上拍摄的照片

几个月前,一部来自韩国的电视剧《乌贼游戏》迅速走红,引起了全世界人们的关注。根据 FlixPatrol 的数据,它在网飞已经进入全球最受关注的前十名。不仅如此,一些标志性的东西甚至游戏本身现在也在现实生活中被改编(但不是以一种残酷的方式)。

从这部电视剧的受欢迎程度来看,似乎现在世界对韩国文化和电视剧更加熟悉了。现在,由于韩剧越来越受欢迎,在各种平台上访问韩剧变得更加容易。这也意味着韩国演员在全球获得更多曝光率。

有时候,在看了很多电视剧之后,你可能会想你应该看什么电视剧。或者,也许,你想知道和你看过的演员有相似经历的其他演员。你瞧,我来分享一下,你是如何根据主演过的剧的某些特征找到相似的演员的;)

数据是如何得出的

获取 k 剧列表

首先,为了得到尽可能多的 k 剧列表,我在这里查阅了维基百科。从这个链接中,使用 BeautifulSoup 检索了所有的戏剧名称和年代。

之后,下一步就是获取每部剧的电影 ID。为此,我们通过搜索和匹配之前收集的戏剧标题和年份来调用 IMDbPy。棘手的是,这部剧的名字有可能和其他剧相似。在这种情况下,我们收集所有的电影 id。

过滤和收集信息

收集完电影 id 后,下一步就是检查并剔除那些没有找到电影 id 的剧集。我们还必须检查该剧是否来自韩国,以防检索到同名的非韩剧。对找到的每个戏剧和每个电影 ID 执行这些步骤(如果收集了多个电影 ID)。在这些过程之后,与该剧相关的信息,如演员、评级、流派等被检索出来。

对于任何没有分级的戏剧,分级将被平均流派分级所替代。在进行替换之前,对于每个可用的类型,我们计算了属于该类型的所有戏剧的平均评分。然后,对于缺失的戏剧评分,由于戏剧可以有多种类型,该值将通过对相应戏剧类型的平均评分来填充。

清洗和预处理后的 K-Drama 数据集

不仅 K-Drama 数据集被处理,而且由演员姓名和 id 组成的数据帧也被产生用于特征处理。对于这种情况,将只包括每部戏剧中列出的前十名演员,假设列出的前十名演员是每部戏剧中出现次数最多的角色。因此,出现不久的字符将被避免。我们想让演员的选择更加具体化。

你怎么知道谁和谁最亲近?

如上所述,IMDbPy 为我们提供了戏剧及其演员的细节或完整描述。因此,我们可以利用这些细节来创造特色。

剧数和平均收视率

对于每个演员,我们会统计他/她出演了多少部剧,累计他/她的剧评分。然后再用累计的剧收视率除以剧数。

最近主演戏剧的演员

每个演员在决定出演电视剧时都有自己的时间和偏好。有些演员你可以经常在银幕上看到。其他人可能一年做一次,或者他们可能在几年后从上一部戏剧中出现。

基于这个条件,应该有一些特征来衡量一个演员在戏剧中出演的频率/最近。为此,我们尝试计算当前年份(2021 年)与该剧上映年份之间的差异。这将对每个演员进行累加,并存储在“最近”变量中。

领不领?

我也注意到一些演员频繁出演配角。其他人可能会出演配角,但在其他剧中会成为主角。考虑到这种情况,我们将使用在 IMDb 上市的 cast 的顺序。对于每部戏剧,提到的前三名演员将被赋予 2 的权重。然后,其余的造型被赋予一个权重。

每个流派的平均评分

从数据集观察,剧可能有多个流派,当然演员也演过无数剧名。因此,对于每个演员,我们将计算(或累积)属于某些类型的戏剧和评级的总数。

例如,如果演员 X 主演了类型为 Y 和 Z 的戏剧,则类型 Y 的戏剧计数为 1,Z 也为 1。但是,如果同一演员还主演了另一部类型为 W 和 Z 的戏剧,则该演员的总戏剧数对于类型 W 为 1,对于 Y 为 1,对于 Z 为 2。类似的计算也适用于每个类型的总评级。

在此之后,对于每个演员,他/她的每个流派的累积戏剧评级将除以他/她主演的独特戏剧的数量,作为一种标准化形式。

通过余弦相似度找到最接近的演员

为了找到哪些演员与输入的演员最接近,我们使用了 Scikit Learn 的余弦相似度。余弦相似度在自然语言处理中被广泛用于寻找相似的文档或信息。它测量两个向量之间角度的余弦,因此值在-1 和 1 之间。如果两个向量重叠(这意味着非常相似或精确),则值为 1。如果方向相反或不同,余弦相似度为-1。从公式上讲,余弦相似性是两个向量的点积除以向量长度的乘积。

余弦相似度(图片由作者提供)

为了实现这一点,我们使用来自 Scikit Learn 的成对余弦相似度。该函数将返回一个矩阵,该矩阵由输入中所有样本之间的成对相似性组成。当然,输入是经过上述预处理和特征选择后得出的 actorFeatures 数据框。

我们用两个韩国演员的名字来测试一下这个吧!下面,你可以找到三个最接近的演员,给出两个演员的名字。对于这个案例,我们先用李敏镐( )后嗣少男过花丛王者:永恒君主 )和裴苏西( 初创浪子趁你熟睡 )来测试一下。

三位最接近李敏镐和裴苏西的演员(图片由作者提供)

根据上面的结果,如果你是李敏镐的粉丝,你可以查看由以下明星主演的电视剧:

  1. 金泰熙( 嗨再见,妈妈!)
  2. Shin Min-a ( 家乡恰恰恰哎呀我的维纳斯 )
  3. 李准基( 恶之花 月亮恋人:猩红之心 Ry eo )

如果你想看类似裴苏西主演的电视剧,你可以看看这些演员的电视剧:

  1. 申成洛( 凯罗斯 末代皇后 )
  2. 俊智贤(https://en.wikipedia.org/wiki/Jirisan_(TV_series)《蓝色海洋的传说》 )
  3. 朴信惠( 西西弗斯:神话继承人 )

如需进一步参考,可以查看下面我的 Github。

**https://github.com/intandeay/K-Actors **

KPI 进度:使用 Tableau 的可视化(营销数据)

原文:https://towardsdatascience.com/kpi-progress-visualization-with-tableau-marketing-data-529812d13ba3?source=collection_archive---------27-----------------------

通过可视化效率和效果,帮助创建更好的决策过程

使原始数据有意义的第一步是将其转换成正确有效的可视化。最好的可视化有一个明确的目的,必须能够很容易地回答最相关的问题。

效率和效果可视化

在传媒业的世界里,效率和效果是成功的两个主要衡量标准,旨在帮助企业做出决策。今天我们将学习在画面中构建一个关于这个主题的可视化场景。

效率和效果可视化— 作者提供的图片

问题陈述

我们是一个分析团队,希望分析与受众定位相关的营销活动。在 Q1 开展了不同的活动,采用了转换 KPI,我们希望向我们的企业主展示观众的表现,并提供一个涵盖以下问题的美观高效的可视化效果:

1-这些目标观众的表现如何?
2-是否有任何策略表现不佳,需要削减预算?对于在下一季度使用这些策略,有什么建议吗?

假设:这里我们假设所有的初始步骤都已经完成,这意味着数据已经导入并在 Tableau 中可见,我们已经准备好创建我们的可视化。

好了,我们开始吧!😊💪

步骤 1:在 Tableau 中,首先计算你的效率和效果指标。
在我们的活动示例中:

CPA(效率指标):每次行动的成本-转化率 CVR(效率指标):点击转化率

第二步:每次行动成本(CPA) 拖动到中,将转换率(CVR) 拖动到中。

作者图片

第三步:拖动战术瞄准(观众)形状(标记部分下)

作者图片

第四步:右击每动作轴成本,选择编辑轴并在刻度段下勾选“反转

作者图片

第五步:我们要添加显示各轴平均值的参考线。在每个轴上单击右键,选择“添加参考线,选择下图详细信息:
下划线部分:
值:
转换率/每动作成本
标签:

在格式部分-线条:下选择任意线条类型和颜色

作者图片

第六步:右键点击每条参考线的平均值,选择格式,然后你可以很容易地改变字体和阴影,使数值更明显。

作者图片

步骤 7: 从标记部分选择形状,然后选择数据项,将其形状更改为您想要的任何形状。

作者图片

您可以通过在标记部分使用 Ssize来使这些战术的形状更大一些。

作者图片

步骤 8:“媒体花费”拖动到形状中,现在气泡的大小显示了每个战术收到的花费金额。

作者图片

第 9 步:让我们将颜色编码添加到我们的图表中,为此我们必须将“转换”拖动到 Marks 部分下的 Color 中,以映射每个战术的转换量。

作者图片

步骤 10:战术瞄准、CPA 和 CVR 拖动到 Marks 部分下的标签中,并尝试调整标签使其更具可读性。

作者图片

第 11 步:让我们去掉背景网格线,右击图表(任何带有网格线的白色区域)并选择格式,然后在线条部分下,将网格线改为“无”

作者图片

最后,您将能够看到下图:

作者图片

第 12 步:现在,让我们把这张图表复制到 PowerPoint 中,让我们的企业主更容易理解。瞧,瞧!😉

作者图片

现在,是时候向我们的企业主解释这个图表了:

  • 在这个图表中,我们从效率(CPA)和效果(CVR)两个方面比较战术表现。
  • 纵轴表示 CVR,横轴表示我们的 CPA。
  • 泡泡的大小显示了每种战术的花费。
  • 颜色强度显示转化量。
  • 右上角的方块代表我们效率和效果最高的区域,另一方面,左下角代表表现最差的区域。
  • 任何在右上区域结束的战术都表现良好,同样,任何在左下区域结束的战术都是表现最差的。
  • 位于左上角和右下角的任何战术都需要优化。

外卖:

  • 策略 B 是最有效率和效果的策略,具有更好的 CPA 和 CVR,具有最高的投资,并推动了更高的转化量。
  • 策略 E 和 A 花费几乎相同的情况下,策略 E 是我们质量领先的驾驶员,具有更高的 CVR,他们的 CPA 没有显著差异。
  • 战术 D 产生了确实很高的 CVR,但是,其 CPA 还有提升的空间。
  • 战术 C 是 CVR 较低而 CPA 较高的效率和效果最低的战术。

推荐:

减少不良战术的预算或增加性能更好的战术将有助于提高我们的活动性能。

最后一点— 我希望这篇文章能帮助您了解可视化数据结果。欢迎任何反馈,因为它让我获得新的见解。
多谢!😊💪

用于根本原因分析的 KPI 树

原文:https://towardsdatascience.com/kpi-trees-for-root-cause-analysis-59e8d930544a?source=collection_archive---------24-----------------------

KPI 树是了解系统性能变化的一个非常强大的工具。它非常容易实现,并且具有广泛的应用范围。这里我们来看两个例子:

  1. 在线实验中每个用户的收入下降,以及
  2. Gap Inc .年收入下降(模拟数据)

在线 A/B 测试

我们正在进行 A/B 测试,注意到每位客户的收入下降了 13%。

以下是我们正在收集的数据示例:

我们注意到:

  • 每个客户的收入=每个篮子的收入*每个客户的篮子
  • 每个购物篮的收入=每个项目的收入*每个购物篮的项目
  • 每个购物篮中的项目可以根据项目是从哪个页面添加的进一步细分,这里是:浏览页面、主页或搜索。

现在我们可以构建 KPI 树了:

每个客户的收入下降最终是由测试变体中从搜索中购买的商品减少所驱动的

所以我们得出结论:

  1. 每客户收入的下降(-13%)是由每篮子收入的下降(-14.22%)推动的
  2. 每篮子收入的下降是由每篮子商品数量的下降推动的(-13.65%)
  3. 每个购物篮中商品数量的下降主要是由测试变量中从搜索中添加的商品数量的下降(35.48%)造成的

零售店同比业绩

Gap Inc .的销售额下降了 5.1%,管理层希望了解原因。

这是销售数据的一个例子:

我们注意到:

  • 收入=每个客户的收入*客户
  • 每个客户的收入=每个交易的收入*每个客户的交易
  • 顾客=每家商店的顾客*商店数量
  • 每笔交易的收入=每项收入*每笔交易的项目
  • 如果需要,我们可以按品牌进一步划分这些指标

同样,我们可以构建 KPI 树:

收入下降是由于 a)Athleta 的平均商品价格下降,以及 b)一家旧海军商店的关闭

因此,总之,(模拟)收入的下降可以追溯到两个非常具体的原因:一个老海军商店的关闭,加上 Athleta 商店平均商品价格的下降。

KPI 树在将原始数据转化为既可解释又可操作的故事方面非常强大。正如这里所展示的,它们也有广泛的应用。在你的工作中享受使用它们的乐趣!

原始数据+视觉效果

https://docs . Google . com/spreadsheets/d/1 akudtnb _ wf 37 wjof 6 lvbd 7 cyosikn 7 io ycs 8 ubz 5 vji/edit?usp =共享

r 脚本生成原始数据

克里金法法国气温

原文:https://towardsdatascience.com/kriging-the-french-temperatures-f0389ca908dd?source=collection_archive---------9-----------------------

简单克里金法教程,从开源数据到温度图可视化

美国典型的气温图——图片由国家气象局提供。

你有没有想过电视天气预报中的温度图是如何制作出来的?它们对我们来说似乎是显而易见的,因为我们已经如此习惯于每天观察它们。它们很容易阅读:地图上的每个像素用一种颜色(通常从蓝色到红色)表示温度水平,并让你知道你所在的地方明天会有多冷或多暖。

地图上的一个像素代表一个 10 公里 x 10km 公里的区域。为了创建地图,您的第一直觉可能是,在您的国家中,向北和向东每隔 10 公里安装一个气象站,收集所有的温度,然后为每个测量值绘制一个像素。

然而,你肯定不会每隔 10 公里就发现一个气象站。如果你住在农村,你可能离他们中的一个都很远!想想这个:例如法国大陆面积是 544000 平方公里。如果你需要每 10 公里 x 10km 公里一个站点,这实际上意味着必须部署 5440 个站点的网络,完美地网状覆盖整个国家。但这不是你在现实生活中会发现的:网络的几何结构既不规则,也不那么密集。

那么,如果气象站没有定期覆盖整个国家,如何创建温度图呢?这样做的技术一般被称为插值。总体思路如下:一个像素表示

  • 或者是精确的测量值(如果一个站存在于其相应的地理坐标上),
  • 或者是一个插值值,这意味着该值是基于附近站测量的“猜测”值。

如何插值温度?

在一个国家这么大的区域内(例如法国大陆),有两个重要的事实需要记住。

  • 想象你住在巴黎。你知道现在这里有多热。然而,仅凭简单的直觉,你无法准确猜测 650 公里外的马赛有多热。波尔多、图卢兹等也是如此。因此,我们可以说温度在长距离上变得随机
  • …现在,如果你还在巴黎,你可以准确地猜出几公里外的巴黎有多热(例如 T21 的凡尔赛宫或巴黎),因为你知道那里的气温几乎一样。事实上,我们可以合理地说,在短距离上,温度场是高度相关的。物理学表明它是空间的连续函数。

通过适当的概率模型,解释具有这两个特征的物理模型(随机性空间相关性)是可能的。其中使用最多的叫做高斯过程。

图 1 —比较两种高斯过程:不相关(左)和局部相关(右)。图片作者。

如果没有相关性,该过程只是具有独立样本的高斯噪声。但是如果该过程与相邻样本相关,那么该过程就变得平滑了!

正是这种平滑性让我们可以进行插值。实际上,假设该场仅在 20 点处测量。有可能在这些点之间插入场吗?

图 2-通过简单克里金法在线上进行插值。图片作者。

答案是肯定的!正如你在上面看到的,这 20 个点的插值有助于提供真实场的一个很好的猜测。这里使用的插值方法称为克里金法【1,2,3】。请注意,在已知样本数量和插值精度之间存在权衡。在测量点较少的区域,插值具有更多的不确定性,并且可能不太准确。然而,在已知值的点上不确定性为零。

这篇文章的目的

在这里我给出了基于开源数据通过克里金法制作你自己的温度地图的简单指南。在本文中,我宁愿远离数学,因为许多资源已经很好地完成了这项工作【1,2,3,4】。我的目的不是介绍高斯过程和克里金法的理论,而是给你一个从数据预处理到可视化使用这些工具的实用教程。

在我的 GitHub 页面上可以找到重现结果的完整 Python 笔记本。

声明:我不是气象学家,本教程只不过是信号处理爱好者的游乐场!尽管 T21 提到了克里金法在温度、湿度、风和压力的处理中的应用,但我不知道我在制作专业级地图时所做的所有误导性的近似。

教程

在本教程中,我们将制作一张法国大陆的温度地图,其中的开源数据由法国梅特奥公司提供。我们将关注免费的资源:概要数据库,每 3 小时更新一次

我鼓励你同时下载并关注Python 笔记本

A.获取数据

首先,您需要两个下载 2 csv 文件:

图 SYNOP 台站的 csv 表。图片作者。

  • 一个文件包含所有站点的温度时间序列。每个时间序列包含一个月内每 3 小时一个点。这里,“numer_sta”索引对应于上表中的“ID”。

图 4-每个站点每 3 小时一个月的 csv 温度文件。图片作者。

首先,过滤表中的电台以保留进入大陆的电台。让我们用在地图上显示他们的位置。

图 5-保留的天气观测站。温度将被插值到灰色矩形内。图片作者。

我们还预测我们希望绘制地图的界限。让我们暂时选择灰色矩形,并保留一点额外的土地。

在唯一标识符的帮助下,可以获取一个特定站点的数据点。例如,“图卢兹-布拉尼亚克”由数字 7630 标识。

图 6-2020 年 1 月图卢兹-布拉尼亚克温度时间序列。图片作者。

我选择了 2020 年 1 月的档案,但你可以选择任何你想要的月份。小心:有些存档文件包含 NaNs ,可能是因为站点或通信链路有时会出现故障。

从现在开始,我们还必须选择一天的&小时来关注,因为地图只描述了一个特定时间的空间波动。以下处理后的数据对应于 2020 年 1 月 1 日凌晨 3 点。

B.选择相关的高斯过程模型

克里金之前至关重要的一步是选择好概率模型,因为整个克里金插值都依赖于它。记住高斯过程的两个特征:随机性空间相关性

信号的随机性是你天生无法捕捉的。但是,您可以根据数据预测信号的空间相关性。如果你想象两点之间的距离对这两点的温差,你会得到一个叫做变差图的图。

图 7-2020/01/01 凌晨 3 点的变差函数。图片作者。

我所称的温度“差异”实际上对应于图 7 中的恒定平方差——如果你想掌握总体思路,这仍然是一个细节。此处最重要的是您可以通过变异函数的分析函数进行回归,从该点云中获取空间相关性的级别。

图 8-变异函数回归。图片作者。

存在不同的分析变异函数,正确选择其中一个函数需要一些经验…我选择了高斯核函数的“默认”选择[3,幻灯片 22]来描述空间相关性。

C.通过简单克里金法对温度进行插值

一旦选择了高斯过程模型,我们就拥有了进行克里金法的所有元素。基本上,您需要的输入是:

  • 采样点的测量值,
  • 采样点的几何坐标,
  • 要插值的目标点的几何坐标,
  • “校准的”概率模型,具有通过步骤 b 中的数据获得的空间相关性

由此,克里金法给出了两个输出:

  • 目标点处的估计值,
  • 目标点的估计不确定性(估计理论中称为方差)。

笔记本中给出了进行简单克里金法的代码,如果你想了解估计量是如何导出的,我再次鼓励你阅读[1,第 6 章]。如果你很好奇,想尝试不同的克里金法,看看 PyKrige

D.在地图上画画

为了用 Python 轻松绘制地图,我使用了 cartopy 和 matplotlib。Cartopy 自动绘制国家,边界和海洋。更重要的是,它在 matplotlib 图形中创建适当的投影,以便绘制由经纬度坐标引用的地图。因此,不需要在笛卡尔坐标系和地理坐标系之间进行任何繁琐的转换。

下面是期望值(左)和标准差(右)的原始结果,标准差是方差的平方根。

图 9-原始结果:简单克里金法插值(左)和标准偏差不确定性水平(右)。图片作者。

你可以看到地图在大陆内看起来很好。然而,一旦插值点远离采样点,获得的值很快就变得毫无意义,不确定性水平飙升。

这是正常的:克里金法擅长在采样区域内进行插值,但在采样区域外却非常糟糕。请记住,高斯过程首先是一个随机过程!只要内插点被附近的采样点很好地包围,空间相关性就有帮助。然而,自然不可能在离每个采样点太远的地方进行估计。

最后,我裁剪了法国以外的地图部分,因为克里金值与该地区无关。为此,你需要划定国家边界的多边形,找到位于这个多边形内的所有地图点。最后,我使用等高线而不是连续的色图来观察温度四舍五入到最接近的程度。

图 10-最终结果:简单克里金法插值(左)和标准偏差不确定性水平(右)。图片作者。

参考

[1]安德烈亚斯·利希滕斯特恩。 空间统计中的克立格方法 (2014)。【2】鲁道夫·勒·里奇。 克里金法简介 (2014)。鲁道夫·勒·里奇。 克里金法概述 (2019)。
【4】渔歌诗。 高斯过程,不太适合假人 (2019)。

Kubeflow 1.3 会让你爱上 MLOps

原文:https://towardsdatascience.com/kubeflow-1-3-will-make-you-fall-in-love-with-mlops-cf68131193f9?source=collection_archive---------11-----------------------

利用新的 Kubeflow 功能来加速您的机器学习模型工作流。

HalGatewood.comUnsplash 上拍照

Kubeflow 是一个开源项目,致力于使 ML 项目的部署更加简单、可移植和可伸缩。来自的文档:

Kubeflow 项目致力于使在 Kubernetes 上部署机器学习(ML)工作流变得简单、可移植和可扩展。我们的目标不是重新创建其他服务,而是提供一种简单的方法来将 ML 的最佳开源系统部署到不同的基础设施上。无论你在哪里运行 Kubernetes,你都应该能够运行 Kubeflow。

库伯流 101

Kubeflow 由许多组件组成,您可以结合使用或作为独立工具使用:

  • 笔记本服务器 让您置身于一个熟悉且可扩展的工作环境中。
  • kube flow Pipelines使您能够基于 Docker 容器构建和部署可移植和可扩展的机器学习(ML)工作流。
  • MLMD方便了跟踪和管理您的实验产生的元数据的过程。****
  • Katib通过超参数调优和神经架构搜索优化你的模型。
  • KFServing允许您毫不费力地将模型作为可伸缩的 API,甚至可以发布金丝雀版本。****

这些组件是 Kubeflow 的主要支柱,当你将所有东西汇集在一起时,你所获得的力量是无与伦比的。

本周,Kubeflow 1.3 候选版本(1.3-rc)上线了,这个故事将带您了解这个主要且功能丰富的版本中的新内容。

Learning Rate 是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。订阅这里

Kubeflow 1.3 的新增功能

正如我们所说,Kubeflow 1.3 是一个重要的功能发布,它旨在使 Kubeflow 更接近数据科学家,使其成为在 Kubernetes 上进行 ML 的首选。

首先,有新的和更新的用户界面(ui)。有人会说“如果没有用户界面的改变,那么就没有更新。”这当然是个笑话;然而,Kubeflow 1.3 为 Katib 引入了一个更新的皮肤,其中充满了关于您的超参数调优实验的细节。**

Katib 更新的用户界面

另一个新增功能是卷管理器,它让您可以从图形用户界面管理您的存储。最后,Tensorboard Web 应用程序使您能够可视化您的训练过程产生的日志,并做出明智的决策。

其他主要特性包括更新的图像和对新 ide 的支持。Tensorflow 2.0 和 PyTorch 的新示例图像让您快速入门,同时引导一个安全稳定的工作环境,而 Visual Studio Code 和 R Studio 等新 ide 让您有宾至如归的感觉。

最后,对 KFServing 进行了许多改进;现在,通过流量分流创建金丝雀部署比以往任何时候都更容易。现在,您将能够以一种受控的方式推出对您的模型的更新,从而实现从试运行到生产的平稳过渡。

其他改进包括:

  • 多模型服务:同一基础设施上的更多模型
  • Pod affinity: 避免不必要地使用 GPU 加速器或大型 CPU 节点
  • gRPC 支持:消息越少,KFServing 工作负载的带宽越少
  • Katib 试用模板:简化定制模型的超参数调整设置
  • Katib 提前停止:停止无效的超参数调整试验
  • 管道步骤缓存:重用以前运行的步骤的结果
  • 多用户管道:非 GCP 环境的用户和资源隔离
  • 清单重构:简化了 Kubeflow 的安装和升级
  • Istio 升级:改进的安全性、第 2 天操作、兼容性和支持

如果您想在不到 10 分钟的安装时间内轻松开始使用 Kubeflow,请查看以下故事:

****

在有了一个有效的 Kubeflow 安装之后,您可能想尝试几个例子。一个很好的方法是遵循下面的教程之一:

结论

Kubeflow 是一个开源项目,致力于使 ML 项目的部署更加简单、可移植和可伸缩。

几天前,Kubeflow 1.3 候选版本上线了,这个故事将带您了解这个主要且功能丰富的版本中的新内容。

新的用户界面、工具、库集成和安全升级使 Kubeflow 1.3 成为迄今为止最好的版本。新的 MiniKF 版本将在几周内发布,为您的本地工作站带来 Kubeflow 的新功能。我等不及要看你会用它做什么了!

关于作者

我叫 Dimitris Poulopoulos ,我是为 Arrikto 工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。

如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请在 Twitter 上关注我的 MediumLinkedIn@james2pl 。请访问我的网站上的资源页面,这里有很多好书和顶级课程,开始构建您自己的数据科学课程吧!****

库伯弗洛:一个 MLOps 的观点

原文:https://towardsdatascience.com/kubeflow-an-mlops-perspective-17d33ac57c08?source=collection_archive---------8-----------------------

行业笔记

ML 管道和 ML 组件

MLOps 和 DevOps —连接

在设计新技术时,几乎总是会做出牺牲一些特性来换取另一些特性的选择。理解这些选择以及它们如何影响或不影响您的用例是很重要的。通常,当选择技术或框架而不是其他技术或框架时,这样的研究永远不会完成;或者有时候没有选择。

例如,我们有像 Kubernetes 这样设计良好的平台,无论是最具技术性的,都不会出错;或者至少。当然,虽然它仍在发展中,对于硬多租户之类的事情可能有更好的解决方案,但现在一般用户并不太关心这些。它已经成为任何云原生应用的事实上的执行引擎。

这导致了传统软件开发的许多变化。而不是编译一个或多个操作系统的源代码并为其创建安装程序或打包程序;开发人员需要将他们的代码容器化,并创建相关的人工制品——如服务、配置图、秘密;入口和 Kubernetes 特定标记语言(YAML)中的类似内容。现在这已经成为惯例和常规。

对于一个开发者来说;将您的微服务包装在容器中,并部署在 pod 中;保证它将执行相同的操作;在任何有足够资源的 Kubernetes 集群上。人们不必担心 pod 联网或调度的内部复杂性,也不必担心与控制组或名称空间等相关的 Linux 内部问题。当然,这是一种简化;就好像你正在安装一个主机卷,并对底层的 Linux 操作系统做了一个假设,那么这样的假设可能会被打破;但是这些都是离群值,而不是技术必须使用的方式。

这是件好事。您希望其他技术也有类似的抽象;比如数据库;如果不了解数据存储的内部原理;人们可以有效地存储和检索数据。例如,为快速访问而存储的 DB 可能不擅长快速更新;令人惊讶的是,许多开发人员并不知道;直到特性需求中途暴露出系统的隐藏特征。基本上,当系统被用于其设计的用例时,系统开始以一种意想不到的方式运行。

所有这些因素与我们要讨论的内容有什么关系?

我们在 Kubeflow 中寻找的是抽象的无泄漏性——借用 乔尔·斯波尔斯基 的一个术语。

借用一个被广泛使用或误用的陈词滥调,我们在 Kubeflow 中寻找的是“云原生”的程度。基本上,执行被安排在 Kubernetes 集群边缘集群或数据中心。此框被勾选,因为 Kubeflow 是为 Kubernetes 设计的。不像说 ml flow—https://mlflow.org/。其他竞争者 TFX,ZenML 截至目前

在我们进入 Kubeflow 之前,让我们检查一下它适合的环境。

MLOps 流程应该有助于确保 ML 项目的生产质量。

用您的 ML 项目制作一个容器并部署到 Kubernetes 上就足够了吗?还是有其他事情需要处理?CI 是怎么做的?测试是如何执行的?和测试评估?

来自一篇被大量引用的论文;似乎 ML 代码在生产中部署时意义最小。

来自这篇优秀博客的例子→https://cloud . Google . com/architecture/mlops-continuous-delivery-and-automation-pipeline-in-machine-learning

管理信息系统的要素。改编自 隐藏在机器学习系统中的技术债务

作者可能夸大了让我们注意到系统的其他部分,我们往往会错过;也可能不是。

作者可能会更多地考虑结构化数据和依赖于特性的经典 ML 方法;非结构化数据,比如音频、视频或图像分析和深度神经网络

MLOps 和 DevOps 一样,似乎又是一个术语,对许多不同的人以许多不同的方式表示许多不同的事情。我们需要定义我们所说的 MLOps 是什么意思。

DevOps 一般已确定更多地代表 CI/CD 部分-https://aws.amazon.com/devops/what-is-devops/;与开发人员对其组件进行端到端开发、部署和操作的原始概念相比,这是开发人员和他们的部署之间更多反馈的原则。这可能就像主动检查来自客户部署的错误日志,以发现可能的问题,甚至在错误出现之前。这肯定不仅仅是 CI/CD;尽管它与开发和管理文化的联系比技术过程更紧密。

毫不奇怪,现在许多公司都有一个“DevOps”团队来担当这一角色,为 CI/CD 提供工具和服务,并为更好地从部署中获得反馈提供工具和基础架构,如监控、日志记录等。

MLOps —需要关注的几个主要特征

MLOps —类似于微服务的 DevOps。但是这有更多与 ML 相关的方面,不仅仅是算法,像数据和模型管理,模型版本控制,模型漂移等等。至少这是承诺,我们在这个领域有如此多的工具和服务,商业的和开源的,除非我们有一些选择标准,否则真的很容易混淆和陷入困境。

浏览这里或者这里你会得到一些想法;一些作者将这种扩散称为 MLOps 项目的寒武纪大爆发。然而,我们可以把它简化为几个主要阶段和许多相似的角色。像 Hadoop 生态系统这样的一些参与者已经相当老了,准备退出舞台,我们可以放心地忽略它。此外,类似的简单技术,如 S3 胜过更复杂的技术,如 Ceph。

我们在 MLOps 特定工具中寻找什么特征?

云原生 —系统应该设计用于基于容器和 pod 的执行;而不是改装成和 Kubernetes 一起工作。气流的例子 XCom 可能不是最好的管道组件(容器)传递数据-https://medium . com/the-prefect-blog/why-not-air flow-4c fa 423299 C4。类似的 MLFlow 可以被容器化,但可能不是最适合基于 Kubernetes 的系统。

开源 —如果可以的话,我们不想被某个特定的供应商所束缚。这需要很多工具——像 Pachyderm 这样的数据管理工具

ML 工程师易于整合— 为 ML 问题创建 Jupyter 笔记本原型后,需要做大量工作才能投入生产。尽管如此,除了他们的业务领域——数据工程、模型开发和调优,我们不希望我们的 ML 工程师知道更多关于 Kubernetes、Docker 文件之类的东西。

可扩展— 这是云原生和基于 Kubernetes 的设计的一个特征。像分布式训练和全状态负载平衡这样的事情非常复杂,我们暂时不考虑这些事情。

ML 工程和 ML 运营——不同的阶段

在我们继续之前,最好先看一下 MLOps 的主要阶段。工具会随着时间而变化,这更加主观https://valohai.com/blog/the-mlops-stack/

需要有一个好的数据分析工具或者 OLAP 数据库。类似于 Apache Presto 可以从多个数据存储或传统数据库中获取数据。类似于 Google BigQuery,但是在开源空间。数据科学家或 ML 工程师可以使用简单的 SQL 类型查询来分析大量数据;这对算法选择和进一步的 ML 工作将是重要的。

这本身就是一个完整的基础架构,但实际上可以被排除在 MLOps 之外,因为它更多地出现在(大)数据基础架构的预览中。我们可以把这个放在数据工程的一边,在以后的帖子里再讨论这个问题。有时 ML 项目可以从较少的数据开始;但是当收集和分析数据并用于更好地训练模型时,应该选择可扩展的数据分析系统。这里是生态系统的快照https://raw . githubusercontent . com/Alex CPN/learn ove/master/ml flow . png

然后是模型开发环境以及相关的——语言和框架。例如,像 Pandas、Scikit Learn 这样的 python 库,以及编程语言——Python、R. ML 框架(如 TensorFlow 或 PyTorch)和数据格式(如简单的 CSV 或更高效的格式,如 Apache Parquet)。这部分将自己与开发环境联系起来,开发环境通常是 Jupyter Notebook。尽管大多数数据分析都基于 Python 及其库,但对于视频分析之类的东西,它可能是 C++、Go 和相关库——GStreamer、OpenCV 等。

每个从业者都清楚这一点。现在开始了一个在开始时看起来并不明显的部分。模块化组件通过数据流图或管道连接。这正是像 Kubeflow 这样的项目适合的地方。为什么需要这样做?来自 Kubeflow 网站

https://www . kube flow . org/docs/about/kube flow/# the-kube flow-mission

我们的目标是通过让 Kubernetes 做它擅长的事情,尽可能简单地扩展机器学习(ML)模型并将其部署到生产中:

在多样化的基础设施上进行简单、可重复、可移植的部署(例如,在笔记本电脑上进行试验,然后迁移到本地集群或云)

部署和管理松散耦合的微服务

基于需求的扩展

第一句话就说明了一切——便捷可重复便携。因此,我们不是创建一个整体的 python 代码或笔记本,而是将它分割成独立的组件;每个任务做一部分,这些步骤是可移植的——可以在其他项目中重用。我们正在创建 ML 微服务 ,并使用工作流调度器来协调这些微服务。

这是 MLOps 画面的一个重要部分。通过管道,你可以确保不会形成一个整体。这里有一个类似堆栈的维护者的类似观点https://towardsdatascience . com/why-ml-should-be-write-as-pipelines-from-the-get-go-b2d 95003 f998

Kubeflow 是否使创建这样的模块化 ML 组件变得容易和高效,我们将在后面看到。但是是的,它使事情变得简单;尽管效率不高,因为组件之间的所有数据都通过 Python pickle 机制序列化和反序列化到磁盘。因此,如果您编写的是普通 CSV 格式,而不是 Apache Parquet 格式;或者在代码中不使用 TFData 或类似的高效数据表示形式;你可以试试。通过像 GRPC 或 REST 这样的接口机制传递这一点不会太难,但是 Kubelow 必须将组件之间的输入/输出数据作为人工制品持久化。所以它也需要存储数据。

我们还需要什么对 MLOps 至关重要的东西。

模型训练——跟踪训练参数。真正的训练是通过 Tensorflow、Pytorch 等模型框架完成的;这里还有更复杂的框架,如 Horvod,它使用 MPI 等并行编程框架进行分布式培训https://github.com/horovod/horovod,或使用https://developer.nvidia.com/nccl进行基于 Tensorflow 的分布式培训。注意,对于像用于图像或视频分析的非常深的神经网络;培训将需要一个带有 CUDA 内核的 NVIDIA GPU ,而对于数据分析来说,CPU 可能就足够了。

实验跟踪 —这可能有助于从历史上检查数据和模型的准确性、精确度、混淆矩阵或类似指标,并连接到测试集的模型验证阶段。也许在 ML 的 CI-CD 管道中比在开发中更有用。

模型上菜—TF 上菜,Seldon,KF 上菜之类的。最重要的是确保模型与应用程序分离,并且可以通过 CI/CD 进行版本控制和独立更新。另一件要注意的事情是,在媒体分析等用例中,通常需要将大量数据传递给模型。因此,模型和业务微服务应该位于同一个 Kubernetes 节点中,并通过负载平衡层进行扩展。

模型监控— 在传统的开发运维中,对运维或开发人员的反馈是通过矩阵进行的,这些矩阵是通过 Prometheus 或类似工具从部署中收集的,并显示在 Grafana 仪表盘中。类似的方法也可用于模型监控。但是,为了检查模型的预测是否准确,应该在预测-分析循环中加入一些手动检查或操作员参与或客户反馈。或者更高级的 A/B 测试与其他模型,并使用复杂算法比较结果,如多臂土匪。还需要用可用的较新数据来验证模型,以检测模型漂移。模型监控无疑是更高水平的 MLOps 熟练度,这将需要非常强大的基础设施来实现。

模型、数据和实验共享——你需要在不同的团队之间有一个集中的、访问受控的共享;为此,需要一些模型或数据注册。

我还漏掉了其他部分。模型调整可能是其中之一,我们有流行的软件,如 Optuna 或 Katib。可能还有其他重要的原因,我现在还不知道。请在评论中注明。

kube flow m lops 管道组件

Kubeflow 是一个伞状项目;有多个项目与它集成,一些用于可视化,如张量板,另一些用于优化,如 Katib,然后是用于训练和服务的 ML 操作符等。但主要指的是库伯流管道。这是 Kubeflow 项目的核心,管道任务集成到各种其他项目中。注意,Kubeflow 中的所有东西都运行在 Kubernetes 集群上。Kubernetes 是资源供应商和执行引擎。

Kubeflow 基于 Kubernetes。这是它的长处。然而,这意味着内部的一切都必须作为容器运行。

然而,让 ML 科学家或 ML 工程师接触通过 Docker 文件和 K8s 部署文件创建容器映像的复杂性并不是最佳选择。公司会有工程师团队来做这件事。但是,有没有一种方法可以促使 ML 科学家或 ML 工程师开发他们的 ML 程序作为谨慎的组件,而不需要他们了解太多的 Kubernetes 或容器技术?正如我们之前所描述的,这是库巴流的一个主要存在理由。

因此,我们要做的是采用常规的基于 Jupyter 笔记本的 ML 开发,并尝试将其转换为 Kubeflow 系统,但采用模块化的方式。

下面是我们借鉴的 Colab 项目[1]https://Colab . research . Google . com/gist/Alex CPN/fa8b 3207 FBC 72 f 471 BDB 72433102344 c/heart attack-prediction-TF data . ipynb

我们将使这款 Jupyter 笔记本符合 Kubeflow 标准。

安装 Kubeflow

Kubeflow 使用服务网格 Istio。这意味着设置这是一个挑战。这肯定会由“MLOps 团队”来完成。如果你有一台基于 Linux 的现代笔记本电脑;你可以使用集群来设置。

请遵循这个;如果您还没有准备好 Kubeflow 集群,或者您想要使用 Kind clusterhttps://gist . github . com/Alex CPN/f 7068 ba 5b 7205 e 75 b 955404 F2 fc 24427在 Linux PC 或笔记本电脑上创建一个快速集群。

请注意,如果您使用的是 GKE 集群,请确保您的节点有足够的 CPU 和内存,因为部署中设置了资源请求。此外,如果你打算使用 GKE 自动驾驶模式,至少现在它不工作,因为 Istio 不被支持。

请注意,我们使用清单方法从 Kubeflow 清单报告安装 kube flow-https://github.com/kubeflow/manifests

创建一个 Jupyter 笔记本

如果您成功安装了 Kubeflow,您将在 Kubeflow 仪表板中获得一个 Jupyter 笔记本,在这里可以查看大多数默认的“组件”

任务一—连接到 Kubeflow 管道服务器

让我们创建一个 Jupyter 笔记本实例;以下代码用于连接 Kubeflow 管道服务器。

任务二——用 Python 代码创建一个 Kubeflow 组件

我们将使用**create _ component _ from _ func _ v2** SDK helper 方法来创建 Python 组件的部署

在这里列出 python 组件;

让我们更详细地看看这个组件。

从 Python 函数创建组件并发布它

我们在上面做的事情非常简单;接受一个 URL 并使用 Pandas 库读取一些数据。如果你看到原来的 Colab Jupyter 笔记本【1】你可以看到我们正在将阅读部分拆分成不同的功能。

这个函数有一个字符串类型的 URL 输入。因为这是 Python 中的内置数据结构,所以可以按原样提供。我们将输出一个熊猫数据帧作为输出。

一旦我们使它成为一个组件,它就成为一个容器映像,并在 Docker 中作为一个容器运行。所以所有功能的输入输出都需要通过某种接口。Kubeflow 使用文件接口-K8s 持久卷。Kubeflow (v1)有这个输入路径和输出路径组件助手函数,它接收数据并使用 Python pickle 函数序列化到磁盘。

请注意,您可以将 PVC 附加到组件上并向其写入。但这违背了库伯流使用原则;因为添加 PVC 的那一刻,组件不再变成不可重复使用。您可能需要将此用于外部可视化,如张量板可视化。

完整代码在这里

https://colab . research . Google . com/drive/1f _ p 4 evkret 57j 4 maz 4 vrfhccj _ qvv 03 w?usp =共享

以下片段:

让我们看看这个组件是如何创建的。如您所见,基础映像和要安装的包在create _ component _ from _ func方法中给出,Rest 是 Kubeflow magic,用于创建 Pod 部署。

您可以在这个 Kubeflow 仪表板快照中看到输入和输出是如何表示的

注意,我也可以把它写到一个组件中,并说把它放在一个组件存储中,然后从存储中加载组件

我刚刚把这个上传到 gist,你可以看到我从 URL 中读取的第二个片段。任何有权访问的人都可以通过将输入数据更改为他们自己的数据,为他们的流重用相同的组件。

其他组件遵循类似流程。

将元件接线在一起

现在让我们看看这些组件是如何连接在一起的。

在第二个代码片段中,您可以看到 read_data 输出通过管道传输到 process_data 的输入

让我们看看在 process_data 函数中发生的奇迹

#Lets use output or target as preiction label
def process_data( pandas_parquet: InputPath("PandasDataFrame"),
                 out_train_path: OutputPath("TF_DataSet"),
                 out_test_path: OutputPath("TF_DataSet"),
                out_validate_path:OutputPath("TF_DataSet")
                ):
    import pandas as pd
    import sklearn as sk
    import numpy as np
    import tensorflow as tf

    from tensorflow import keras
    from tensorflow.keras import layers
    from tensorflow.keras.layers.experimental import preprocessing
    from sklearn.model_selection import train_test_split

   ** df = pd.read_parquet(pandas_parquet)**

我们读入拼花文件作为输入,并转换成熊猫数据帧。所以是的——没有魔法;类似地,您可以看到我们在一个组件中取出 h5 Keras 模型,并在另一个组件中读取该模型。

这是您在必须分成不同组件时所做的权衡。也许 Kubeflow 的未来版本会为其中一些提供 GRPC 接口,这可能会加快速度。但是这个例子也是一个玩具例子,你不需要把所有东西都分成组件。

数据流的可视化

Kubeflow 提供了数据流的交互式下钻可视化。如果豆荚还在 Kubernetes,你可以看到豆荚日志。T

投入/产出假象在 S3 持续存在。Kubeflow 默认运行基于 Minio 的 S3 存储桶。

您可以通过端口转发直接访问 Minio

kubectl port-forward svc/minio-service -n kubeflow  9000:9000

默认-minio/minio 123

有点像穷人的藏物店。注意,你也可以用它来输出张量板矩阵;尽管我还不能连接运行在名称空间中的 Tensorboard Pod,以便从仪表板 UI 正确地到达 S3 URL。

实验可视化

Kubeflow V1 管道中组件的输出可以从仪表板中可视化。然而,到目前为止,它还不是一个非常强大的 GUI。在 V2 版本中,似乎对此有更好的支持;然而,我测试过的版本似乎有问题(库伯弗洛 V2 正在测试中)

和输出

您也可以在运行之间进行比较;在你暴露的矩阵上

优化

Kubeflow 内部整合了 Katib 但是需要用 docker 容器等指定完整的 YAML 文件-https://www.kubeflow.org/docs/components/katib/experiment/。与 Optuna 不同,我猜 Katib 首先是 Kubernetes,因此很复杂。

参考

https://cloud . Google . com/architecture/mlops-连续交付和自动化-机器学习管道

Kubeflow:如何在本地机器上安装和启动 Kubeflow

原文:https://towardsdatascience.com/kubeflow-how-to-install-and-launch-kubeflow-on-your-local-machine-e0d7b4f7508f?source=collection_archive---------7-----------------------

在本地机器上安装和配置每个 kubeflow 组件的分步指南。

图一。Kubeflow & Kubernetes 互动|作者图片|图标由桉树制作

Kubeflow [ 1 ]是 google 开发的一个开源平台,用于包含机器学习模型开发生命周期。Kubeflow 由一套工具组成,这些工具处理构成机器学习生命周期的每个阶段,例如:数据探索特征工程特征转换模型实验模型训练、模型评估、模型调优模型服务模型版本化。kubeflow 的主要属性是它被设计为在 kubernetes [ 2 ]之上工作,也就是说,kubeflow 利用了 kubernetes 集群提供的好处,比如容器编排自动伸缩

虽然 kubernetes 是容器编排的标准技术,但对于数据科学家机器学习工程师来说,直接在 kubernetes 集群中配置和协调机器学习生命周期的每个阶段可能是一个复杂而耗时的过程。因此,kubeflow 作为一个平台,提供了在 kubernetes 集群中配置、开发、自动化和部署机器学习生命周期的每个阶段的工具,避免了数据科学家机器学习工程师花费时间直接在 kubernetes 集群中配置和应用更改。

在这篇博客中,我们将了解如何在您的本地机器上安装和配置 kubeflow,以便能够在本地使用 kubeflow,而不需要云提供商。因此,本博客将分为:

  • 要求
  • Minikube 安装
  • Kubeflow 安装
  • 创建 Kubeflow 项目
  • 访问 Kubeflow 界面

要求

要在我们的本地机器上安装和运行 kubeflow,我们需要一组基本组件。首先,我们需要一个 kubernetes 集群,kubeflow 服务将在这里安装和部署。由于 kubernetes 需要大量的资源,因此不建议在我们的本地机器上安装 kubernetes,建议为模拟 kubernetes 集群的使用一个面向本地测试的更轻便的替代方案,在这种情况下,我们将使用 minikube [ 3 ](尽管还有其他替代方案,如: microk8skindk3s )。除了 minikube,我们还需要一个虚拟机管理程序,它将允许我们在我们的小型集群中生成虚拟环境,在这种情况下,我们将使用 hyperkit [ 4 ](尽管您可以使用其他替代产品,如 VirtualBox 、linux 的 kvm2 和 windows 的 Hyper-V ),最后是 kubeflow 包。**

免责声明:因为我在 MacOS 上工作,所以使用的命令是针对那个操作系统的,但是在每个组件的文档中,你可以找到它在 Linux 或 Windows 上的对等物

迷你库贝装置

要在 MacOS 上安装 minikube,只需键入:

*$ brew install minikube*

安装完成后,kubectl命令将被添加到$PATH中。kubectl是与 kubernetes 微型集群交互的命令。然后,我们将需要一个虚拟机管理程序来在我们的 kubernetes 小型集群中创建虚拟环境,为此我们将使用hyperkit,它可以按如下方式安装:

*$ brew install hyperkit*

很好,要启动我们的 kubernetes 小型集群,只需键入:

*$ minikube start --driver=hyperkit*

上面的命令将使用hyperkit作为虚拟环境的管理程序来初始化一个 kubernetes 小型集群。要验证我们群集的信息,让我们键入以下命令:

*$ kubectl cluster-info*

您将得到类似于以下的内容:

*> Kubernetes control plane is running at [https://192.168.64.5:8443](https://192.168.64.5:8443)*

很好,现在我们已经有了开始安装和配置 kubeflow 所必需的组件,让我们开始吧!

库伯流装置

对于 kubeflow 的安装,我们将定义一些环境变量,我们将下载 kubeflow 项目,然后继续安装。那么,让我们定义一些变量:

*$ PLATFORM=$(uname)
$ export PLATFORM
$ mkdir -p ~/bin
$ export KF_TAG=1.0.1
$ KF_BASE="https://api.github.com/repos/kubeflow/kfctl/releases"*

KF_TAG变量指的是我们将要使用的图像版本,您可以使用最新的版本,在这种情况下,我将使用版本1.2.0。然后我们将定义URL,下载并解包项目,然后我们将把kfctl二进制文件移动到上一步中创建的二进制文件目录中。

*$ KFCTL_URL=**$(**curl -s ${KF_BASE} |**\**
	      grep http |**\**
	      grep "${KF_TAG}" |**\**
	      grep -i "${PLATFORM}" |**\**
	      cut -d : -f 2,3 |**\**
	      tr -d '\" ' **)**
$ wget "${KFCTL_URL}"
$ KFCTL_FILE=${KFCTL_URL##*/}
$ tar -xvf "${KFCTL_FILE}"
$ mv ./kfctl ~/bin/*

最后,我们将删除 kubeflow 包(不再需要保留它),并将 kubeflow 路径~/bin(包含命令kfctl)添加到我们的$PATH:

*$ rm "${KFCTL_FILE}"
$ export PATH=$PATH:~/bin*

kfctl命令应该准备好了,为了测试它,我们将键入:

*$ kfctl version
kfctl v1.2.0-0-gbc038f9*

kfctl命令将允许我们与 kubeflow 组件进行交互,特别是定义清单并将其应用到我们的 kubernetes 集群。到目前为止,我们已经准备好 kuberentes 小型集群和 kubeflow 安装,接下来是使用kfctl命令生成我们的第一个 kubeflow 项目,让我们开始吧!

创建 Kubeflow 项目

正如我们已经知道的,kubeflow 工作在 kubernetes 之上,因此两个平台之间的交互将通过清单yaml文件进行。因此,为了生成 kubeflow 项目,我们必须通过一个yaml文件来完成,该文件定义了必须部署到 kubernetes 小型集群中的所有服务。

首先,我们将生成一些环境变量,这些变量定义我们将要安装的 kubeflow 版本,然后我们将定义 kubeflow 项目部署的每个服务的所有配置和yaml文件将被分配到的目录,最后我们将获得在我们的 kubernetes 小型集群中部署 kubeflow 项目的yaml

因此,让我们定义一些与我们安装的 kubeflow 版本相对应的环境变量:

*$ MANIFEST_BRANCH=${MANIFEST_BRANCH**:-**v1.2-branch}
$ export MANIFEST_BRANCH
$ MANIFEST_VERSION=${MANIFEST_VERSION**:-**v1.2.0}
$ export MANIFEST_VERSION*

然后,我们定义项目名称并创建目录,每个服务的配置和yaml文件将被分配到该目录:

*$ KF_PROJECT_NAME=${KF_PROJECT_NAME**:-**hello-kf-${PLATFORM}}
$ export KF_PROJECT_NAME
$ mkdir "${KF_PROJECT_NAME}"
$ pushd "${KF_PROJECT_NAME}"*

然后,我们定义存储库,从中获取清单并将其分配给一个环境变量:

*$ manifest_root=https://raw.githubusercontent.com/kubeflow/manifests
$ FILE_NAME=kfctl_k8s_istio.${MANIFEST_VERSION}.yaml
$ KFDEF=${manifest_root}${MANIFEST_BRANCH}/kfdef/${FILE_NAME}*

正如您所看到的,我们使用的是ISTIO(kubernetes 的一个服务网格实现)的清单。最后,我们应用清单来部署我们的 kubeflow 项目。

*$ kfctl apply -f $KFDEF -V*

部署过程可能需要大约 30 分钟。

要验证安装是否成功,可以使用以下命令验证所有服务是否都处于RUNNINGCOMPLETED模式。

*$ kubectl get pods --all-namespaces -w*

如果某些服务处于error状态,您可能需要为您的 kubernetes 小型集群(minikube)分配更多内存,并重新应用部署清单。如果一切进展顺利,我们现在可以在浏览器中查看我们的 kubeflow 项目了。让我们去吧!

访问 Kubeflow 用户界面

由于我们是在本地服务器上安装,要访问 kubeflow UI,只需进行如下的端口转发:

*$ kubectl port-forward svc/istio-ingressgateway -n istio-system 7777:80*

上面的命令是用kubectl执行的,它公开了名称空间为istio-systemistio-ingressgateway服务的端口 7777,允许我们访问 kubeflow UI。最后,如果您转到:http://localhost:7777,您将被重定向到 kubeflow UI,如图 2 所示。

图二。Kubeflow UI |作者拍摄的屏幕截图

结论

在这篇博客中,我们看到了如何下载、配置和安装 kubeflow 及其要求(在 MacOS 操作系统上)。

通过本教程,你将能够从 UI 开始与 kubeflow 进行交互。正如我们所看到的,kubeflow 提供了一套工具来开发机器学习模型的生命周期,在未来的博客教程中,我们将了解 kubeflow 的每个组件以及管道的生成!

参考

[1] Kubeflow

[2] Kubernetes

[3] 迷你库贝

[4] Hyperkit

Kubeflow(不是)为假人设计的

原文:https://towardsdatascience.com/kubeflow-is-not-for-dummies-414d8977158a?source=collection_archive---------15-----------------------

在 EKS 部署和摧毁 Kubeflow 只需一个脚本,不费吹灰之力

图一。Kubeflow 仪表板(来源: Kubeflow 文档

工具、库、框架的创建是为了让我们的工作更容易。它们引入了新的功能,简化了代码,减少了样板文件,实现了自动化。

想象一下你的项目没有依赖关系,想象一下你需要用你自己的代码来替换一个函数调用(例如 yaml.safe_load )。所有这些工具都使应用程序更容易构建、维护、开发和部署。但是如果这些工具本身很难部署呢?哎哟。

Kubeflow 简介

我不会说谎——在我写完工具很难部署之后,我马上介绍了 Kubeflow,这不是巧合。女士们,先生们,来认识一下 Kubeflow — 这是我多年来使用过的最流行也是最烦人的工具之一 (CMake,兄弟,我永远不会忘记你)。

Kubeflow 是最近 ML 和 MLOps 领域最热门的东西之一,大约有 30 个积极开发的存储库,拥有来自 GitHub 用户的近 20,000 颗星。“Kubernetes 的机器学习工具包”是否让你认为这是可能的,并做了几乎所有的事情?好吧,那你说得很对。Kubeflow 有几个关键组件:

  • 使用 YAML 模板或 SDK 创建管道,使用 GUI(图 2)可视化管道执行及其结果,
  • Jupyter 笔记本服务器,
  • katib——超参数优化或神经结构搜索,
  • 藏物店,
  • Dashboard(图 1) web 应用程序管理所有这些以及更多内容。

图二。Kubeflow 管道(来源:管道快速启动)

最重要的是,Kubeflow 运行在 Kubernetes 之上。因此,如果我们谈到 Kubeflow Jupyter 笔记本电脑,这些笔记本电脑运行在可扩展的 Kubernetes 集群中。Pipelines 和 Katib 也是。与目前可用和使用的其他工具相比,这提供了一个巨大的优势。如果你需要大规模训练和管理 ML 模型,当然可以。

用例的官方列表可以在 Kubeflow 文档中找到。

Kubeflow(不是)为假人设计的

与其他 ML 工程工具不同,例如 MLFlowDVC ,安装 Kubeflow 并不容易,而且 pip install 也不够。差远了。首先,您需要一个将部署 KF 的 Kubernetes 集群。这是你在项目中尝试 Kubeflow 的第一个障碍。

它既可以部署在本地集群中,也可以部署在云中。当然,在本地部署它有它的缺点(例如,资源有限),但也可以便宜得多。在云中设置 Kubeflow 的成本会很高,尤其是如果有些事情不太对劲,并且您需要重复部署几次。

去过那里。我进行了几次尝试,最终在 AWS 云上设置了 Kubeflow(将其部署在亚马逊 EKS 集群中)。试了几次,后来发现大约 70 美元。

图 3。图片由 Ariel Biller ( @LSTMeow )提供

因此,在阅读了其他人像我一样努力部署 Kubeflow 后,我决定提出一个解决方案,让我在下次部署 KF 时能够最大限度地减少错误和工作量。我还希望清理环境像设置环境一样快速简单。

我做到了,现在让我来展示一下。

亚马逊 EKS +地形

尽管亚马逊 EKS 集群可以使用 AWS 控制台在几分钟内完成配置,但我决定选择另一种方式来完成,这样我就可以对自己创建(和删除)的资源有更多的控制。

遵循基础设施即代码的方法,我使用 Terraform 从零开始建立整个 EKS 集群,包括 EC2 实例、VPC 和其他必要的资源。由于这一点,我写了一次 Terraform 脚本,我就能够建立基础设施,然后只用一个命令就可以拆除它,我非常确定所有的资源都会被很好地清理。这样我周末不自觉留下的 EC2 就不会被收费了。

不仅如此,IaaC 还让我有可能在我的 GitHub 库中存储版本控制下的构建指令。我可以跟踪和恢复对基础设施所做的任何更改,如果我只是不停地点击亚马逊控制台 UI 中的按钮,这几乎是不可能的。

在 EKS 集群中部署 Kubeflow

一旦配置了 EKS 集群,Kubeflow 就可以最终部署到其中了。这可以使用 shell 从头到尾地完成,但是我需要做一些微小的改变来使它工作(例如,替换 YAML 文件中的区域或集群名,特别感谢 sed )。

如果你只是想拥有你的小游乐场(并且你不在乎隐私和良好的基础设施设计),没有太多的变化要介绍。所有调整都保存在回购协议中我的 delpoy_kubeflow 脚本中。

然后,可以使用脚本中的 kfctl CLI 工具部署 Kubeflow。这需要几分钟时间,希望能顺利完成。当所有窗格和服务准备就绪时,您应该可以使用仪表板 UI 了。

类型

kubectl get service istio-ingressgateway -n istio-system

去看看哪里。当使用我的脚本进行部署时,Dashboard 在本地主机(使用节点端口)上对我可用,并且不需要负载平衡器服务。

图 4。图片由 Ariel Biller ( @LSTMeow )提供

一下子:deploy_kubeflow.sh

如果你想在 EKS 上享受 Kubeflow 组件的乐趣,并想跟随我的脚步,只需简单地克隆这个 repo 并查看 README 文件中的说明。

先决条件:使用管理员权限配置 AWS CLI 和配置文件。

所有需要的变量必须在 set_env_variables 脚本中设置。然后就可以开始了,只需要执行 deploy_kubeflow.sh。所需依赖项和操作的完整列表在 README 中。

笔记

  • 我想保持它的简单性,并且只在我的私人目的上使用 Kubeflow,所以我不关心 IAM 或认证。我不会在任何真实的项目中使用这些代码但是我认为这可能是一个很好的基础,
  • 创建 EKS 集群和在 AWS 上部署 Kubeflow 还有其他方法,根据您的需求,您可以使用 CloudShell 、eksctl 或其他工具。
  • 如果你预算有限,就在本地玩 KF:这里是我对 WSL 的说明,这里是我的同事pawei为 Windows 写的类似的教程,
  • 整个 KF 部署是相当大并且相当昂贵(我不得不使用两个 m5.xlarge 实例来处理它,我在更便宜的机器上没有成功),
  • 如果你只需要 Kubeflow 管道,你可以拥有它。Pipelines 只是整个 KF 系统的一小部分,因此如果使用独立部署,可以使用更便宜的实例,
  • 我知道我在这篇文章中用了太多次 Kubeflow 这个词,抱歉。

Kubeflow:还没准备好生产?

原文:https://towardsdatascience.com/kubeflow-not-yet-ready-for-production-9037ce2f3d35?source=collection_archive---------34-----------------------

为什么我们放弃 Kubeflow,转而采用我们的机器学习参考架构

来源:作者

我们正在构建一个参考机器学习架构:一组免费的文档和脚本,将我们选择的开源工具组合成一个可重用的机器学习架构,我们可以应用于大多数问题。

kube flow——一个建立在 Kubernetes 基础上的机器学习平台,有许多相同的目标——在开始时似乎非常适合我们的项目。我们尝试了几个星期,但在面临几个挑战后,我们现在决定完全放弃它

这篇文章描述了我们的 Kubeflow 体验。我们的目标是帮助其他人比我们更早地看到 Kubeflow 可能还不是它所宣称的那样。

需要明确的是:Kubeflow 有一些缺点,这些缺点阻止了我们在这个项目中依赖它。也就是说,我们仍然尊重 Kubeflow 的目标,我们希望随着项目的成熟和解决其中的一些问题,我们可以在未来重新考虑使用它的想法。

库伯弗洛:好的部分

我们先来看看我们最初为什么会被库伯弗洛吸引。所有生产机器学习项目都由许多组件组成,这些组件可以大致分为三类:

  • 数据转换:训练前扯皮清洗数据;
  • 模型训练和开发:基于处理后的数据训练和准备模型;
  • 模型推理:为训练好的模型服务,根据新数据进行预测。

如果我们将机器学习项目的组成部分视为 Andreessen Horowitz 描述的,Kubeflow 可以用于所有三个类别——至少在理论上是这样。拥有一个内聚的工具来执行这些不同的任务在理论上绝对是有吸引力的。

我们需要一个工具来组合许多不同的组件,但是 Kubeflow 没有达到我们的期望。来源:作者

由于我们已经开始使用 Kubernetes,并且只希望使用开源工具,Kubeflow 看起来非常适合。

不幸的是,Kubeflow 设置起来很挑剔,不可靠,而且很难配置。它还依赖于许多过时的组件和库。最后,许多文档已经损坏或过时,如果不依靠一些简单的解决方法,我们无法将它与 AWS 和 GitHub 很好地集成。

我们将在下面详细讨论这些问题。

注册订阅我们的时事通讯: 把我们下一篇关于我们用什么代替 Kubeflow 的文章直接发到你的收件箱。

库伯弗洛:缺点

初始安装的问题

甚至在我们采用 Kubeflow 之前,我们就已经知道会有一个陡峭的学习曲线。但是我们在团队中有丰富的 Kubernetes 经验,我们认为我们能够很快地完成初始安装并运行。

在我们第一次尝试的几天后,我们仍然在与 KFDef 和 Kustomize 清单相关的错误作斗争。提供的清单失败了很多次,没有明确的错误消息,所以我们必须手动检查每个安装组件,并试图找出哪些组件损坏了。

我们的目标是将 Kubeflow 与 GitHub 身份验证集成在一起,但是为 AWS 和 OpenID Connect (OIDC)提供的清单也包含一个涉及 Kubeflow 入口点的 bug。为了解决这个问题,我们必须手动更新入口以使用所需的 OIDC 信息。

总的来说,虽然 Kubeflow 运行在 Kubernetes 之上,并且是云不可知的,但是我们在 AWS 上运行 Kubeflow 遇到了许多问题。如果我们选择 GCP,这个过程可能会更顺利。因为 Kubeflow 是由谷歌构建的,所以它通常默认使用 GCP,并且还不能与其他云提供商很好地合作——尤其是在认证和权限管理方面。

集成组件的问题

Kubeflow 由许多不同的松散耦合的组件组成。这种松散耦合很好,因为理论上它允许我们选择使用哪些组件。但是它也有缺点。不同的组件依赖于相同依赖项的不同版本,这带来了更多的麻烦。

在我们的测试运行中,我们发现升级一个组件经常会破坏另一个组件。例如,升级 KFServing 组件需要升级Istio——Kubernetes 服务用来相互共享数据的网格服务平台。此升级中断了对仪表板的访问,因为较新的 Istio 版本与 AWS 身份验证不兼容。

结果是一组不兼容的版本,唯一的恢复方法是重新安装 Kubeflow。

我们还必须直接从笔记本上创建我们的管道,但即使使用了一些简单的变通方法,这也被证明是不可能的 Kubeflow 仍然存在未解决的问题。正如一位 AWS 工程师在 GitHub 上所说,“在这个阶段不支持从笔记本到 Kubeflow 管道的集群内通信。”

文件方面的问题

许多文档页面都被标记为“过时”,包括重要的 Kubeflow 组件,如 Jupyter 笔记本。

来源:作者

更糟糕的是,一些也是为老版本的 Kubeflow 编写的文档页面并没有被标记为“过时”所以当我们调试时,很难知道什么时候信任文档——试图找出什么时候我们做错了什么,什么时候问题是过时的文档。这让一切都慢了下来。

文档中的许多链接也返回“找不到页面”或“该页面尚不存在”的错误,这使得体验总体上令人沮丧。

Kubeflow 的未来?

10 月,一篇题为“库伯弗洛死了吗?“注意到 Kubeflow 的发展似乎在放缓,一些首席工程师弃船到其他公司任职。

正如本文所观察到的,感觉速度变慢的部分原因是开发正在从主存储库转移到子存储库。也就是说,我们也发现社区中的其他人反映了我们自己的许多担忧和经历。卢克·马斯登说:

“我在 Kubeflow 1.1 上遇到了困难,在我看来,它真的缺乏对最终用户体验的关注,这比它需要的要困难得多。”

克莱夫·克洛斯说:

“Kubeflow 是一个生态系统,有些项目比其他项目使用得更多。我认为他们发现将所有东西整合成一个有凝聚力的整体很有挑战性。”

挑选 Kubeflow 组件?

Kubeflow Pipelines 是 Kubeflow 的主要关注点,可以只使用这个组件而不使用其他组件。但是,即使当我们试图使用更小的组件时,我们也会遇到问题——并不总是清楚哪些组件是必需的,哪些是可选的。考虑到文档的状态,通过反复试验来解决这个问题是一个耗时且容易出错的过程。

这就是为什么我们决定现在不集成任何 Kubeflow 组件。我们还没有决定用什么来代替它。由于 Kubeflow 有如此广泛的目标,我们可能需要使用几种不同的工具来代替它。很可能我们会使用perfect作为工作流工具,我们会写另一篇关于我们的经验的文章。

你在制作设置中用过 Kubeflow 吗?

如果你在 Kubeflow 上有过类似或矛盾的经历,我们很想听听它们——或者你对本文的任何其他反馈

Kubeflow 管道:如何从零开始构建您的第一个 Kubeflow 管道

原文:https://towardsdatascience.com/kubeflow-pipelines-how-to-build-your-first-kubeflow-pipeline-from-scratch-2424227f7e5?source=collection_archive---------1-----------------------

实践教程

如何设计、建造和运行 Kubeflow 管道的分步指南

图一。Kubeflow Pipelines |作者图片|来自 freepick平面图标的图标

Kubeflow [ 1 ]是一个平台,它提供了一套工具来开发和维护机器学习生命周期,并在 kubernetes 集群之上工作。在它的一套工具中,我们找到了 Kubeflow 管道。kube flow Pipelines[2]是一个扩展,允许我们原型化、自动化、部署和调度机器学习工作流。这样的工作流由一组组件组成,这些组件仅仅是独立的功能,而这些功能又存在于 docker 容器中。然而,当您第一次使用 kubeflow 时,理解如何设计、构建和连接这些组件以创建和部署 kubeflow 管道变得很复杂,这就是为什么在本博客中,我们将通过理解其组件以及它们如何相互作用来了解如何创建 Kubeflow 管道,因此本博客将分为以下几个部分:

  • 什么是 Kubeflow 管道?
  • 建立您的第一条 Kubeflow 管道

如果你想知道如何在你的本地机器上安装和配置 kubeflow,我推荐你看一下这篇文章: Kubeflow:如何在你的本地机器上安装和启动 kube flow

我们开始吧!

什么是 Kubeflow 管道?

Kubeflow Pipelines 是 Kubeflow 扩展,它提供了创建机器学习工作流的工具。基本上,这些工作流是以图形形式设计的任务链,并且被表示为有向无环图(Dag)。图中的每个节点称为一个组件,该组件代表 docker 容器中的一个独立任务。在图 2 中,我们可以看到一个管道组件的可视化描述。

图二。管道组件。在(A)中,我们可以看到一个基于 python 函数的组件,它位于自定义 docker 容器中。在(B)中,我们可以看到一个由装饰器从kfp . components| Image by author 生成的组件

Kubeflow Pipelines 基于 Argo Workflows [ 3 ],这是一个用于 kubernetes 的容器本地工作流引擎。一般来说,Kubeflow 管道由[ 4 ]组成:

  • Python SDK :允许你使用 Kubeflow 管道领域特定语言 (DSL)创建和操作管道及其组件。
  • DSL 编译器:它允许你将 python 代码中定义的管道转换成反映在 YAML 文件中的静态配置。
  • 管道服务:从静态配置或 YAML 文件创建管道运行。
  • Kubernetes 资源:管道服务连接到 kubernetes API,以便定义运行 YAML 文件中定义的管道所需的资源。
  • 工件存储:K ubeflow 管道存储元数据和工件。实验、作业、运行和指标等元数据存储在 MySQL 数据库中。诸如管道包、大规模度量和视图之类的工件存储在诸如 MinIO server [ 5 ]之类的工件存储中。

此外,Kubeflow Pipelines 提供了一个 UI 和一个客户端 API 来管理管道、组件、实验、运行和工件。

Kubeflow 管道建设的一个基本要素是组件之间的连接。这个连接是通过第三个服务的实现来实现的,默认情况下是 MinIO。基本上每个组件的每个inputoutput被表示为存储在 MinIO 中的一个工件,这个工件将被一个 URI 定义和引用,该定义和引用指示这些inputoutput将被分别读取或写入的位置。在图 3 中,我们可以看到如何使用 MinIO 服务进行组件通信的可视化描述

图 3。组件连接|作者图片

在上一个图像中,在左侧,我们可以看到组件之间的连接是如何通过每个元素的inputsoutputs进行的。从右边我们观察它是如何真正发生的,也就是说,每个进入或离开组件的工件都存储在一个存储服务中,比如 MinIO,所以作为inputoutput值传递的是这个工件的引用。我们将在下一节构建第一个管道时详细了解这一点。

现在我们已经了解了 Kubeflow 管道是什么,它的组件以及它们如何相互作用,让我们创建并自动化一个管道,它涵盖了构建 Kubeflow 管道的大部分基础知识,所以让我们开始吧!

建造你的第一条库巴流管道

在这个例子中,我们将为众所周知的乳腺癌数据集建立一个解决分类问题的管道。该管道将由 4 个组件组成,涵盖以下任务:下载和分割数据集,训练和验证两个分类模型(决策树逻辑回归),并最终显示结果。在图 4 中,您可以看到本例中将要构建的管道架构的可视化描述。

图 4。管道架构|作者图片|来自自由选择平面图标的图标

该示例将分为以下步骤:

  • 流程描述
  • 组件:下载 _ 数据
  • 组件:决策树和逻辑回归
  • 组件:显示结果
  • 编译并运行

所以让我们开始吧。

如果你想访问完整的项目,我给你留下了资源库的链接:https://github.com/FernandoLpz/Kubeflow_Pipelines

-流程描述

首先,我们将为管道中的每个组件创建一个容器。出于实用和可解释的目的,组件download_datadecision_treelogistic_regression将是手工构建的 docker 容器,其映像将被托管在 Docker Hub [6]上。组件show_results将是由kfp.components的扩展@func_to_container_op生成的容器(我们将在后面看到)。然后,将为每个 docker 容器生成一组yaml清单。稍后,我们将生成 python 脚本 t,其目标是定义管道图。最后,我们将编译管道,将其托管在 Kubeflow 管道中并运行管道!

所以,让我们从构建组件及其各自的yaml文件的过程开始。

-组件:下载数据

该组件的目标是下载和分割数据集。正如我们已经提到的,我们将使用的数据集是众所周知的乳腺癌,它是作为 scikit-learn 的扩展而发现的。那么,组件将如下所示:

代码片段 1。下载 _ 数据. py

如我们所见,在第 12 行和第 13 行,我们分别下载和分割数据集。接下来有趣的事情发生了,我们生成一个名为datadict类型的结构(第 23 行)来托管训练集和测试集。然后我们将这个结构转换成一个json类型的对象,最后我们在args.data参数中定义的文件中转储这个对象。这个转储数据对象的过程是能够向其他组件(决策树和逻辑回归模型)公开生成的数据(在本例中是训练和测试数据集)的关键。关键是将我们的数据保存在一个文件中,在这种情况下,我们将它设为json类型(这是推荐的),但它可以是任何格式。

嗯,一旦我们有了python script,,我们需要生成Dockerfile来生成我们将上传到 DockerHub 的图像。在这种情况下,我们的图像非常简单,看起来像这样:

代码片段 2。download_data.py 组件的 Dockerfile

一旦Dockerfile准备好了,我们就开始构建映像并上传到容器注册中心。

很好,我们几乎为我们的download_data组件准备好了一切,我们唯一缺少的是yaml清单,它旨在描述我们组件的行为以及定义这样的组件需要的inputsoutputs的类型。因此,download_data组件的清单如下所示:

代码片段 4。下载 _ 数据. yaml

正如我们所看到的,在第 5 行中,我们定义了组件的输出,在本例中,它被定义为名称Data,类型为LocalPath。请务必注意,数据类型是指组件输出的内容,在这种情况下,因为它是包含定型和测试数据集的结构,所以数据类型是存储该文件的位置。然而,不同的目的有不同的数据类型(例如StringFloatInteger等),对于数据类型,建议看一下文档[7]。在第 9 行中,我们引用了将从 DockerHub 中提取的图像(此时我们假设图像已经构建好并上传到容器注册中心)。最后,从第 10 行到第 14 行,我们引用了图像的使用,这种情况下只接收一个参数,即数据。

很好,到目前为止,我们已经看到了如何构建组成download_data组件的每个元素。在下图中,我们可以看到该组件生成过程的可视化描述。

图 5。构建 download_data 组件的过程|作者图片|来自自由选择平面图标的图标

开发decision_treeslogisti_regression组件的过程实际上与dowload_data相同,唯一的区别在于参数的定义,因为这些组件接收由download_data下载的数据集所在的路径作为输入,所以让我们看看我们是如何做到这一点的。

-组件:决策树和逻辑回归

decision_treelogistic_regression组件的构造实际上是相同的,唯一不同的是要实现的模型,因此出于实用目的,我们将只展示如何为decision_tree组件实现。

decision_tree.py模块如下:

代码片段 5。决策树组件

首先,我们来看看第 44 行和第 45 行。正如我们所看到的,我们定义了两个参数dataaccuracydata参数指的是存储由download_data组件生成的数据集的路径,而accuracy参数指的是我们将保存在该组件中获得的精度的路径。正如我们在第 50 行中观察到的,生成了将这种准确性存储为文件的路径。接下来要做的就是读取数据集作为 json 对象的文件(第 12–19 行),训练模型,评估模型,并在由args.accuracy参数定义的路径中保存精度(第 38 行),就这样!

现在,我们必须为该组件创建 docker 文件,如下所示:

代码片段 6。决策树组件的 docker 文件

最后,我们只需要在yaml清单中定义decision_tree组件的使用,如下所示:

代码片段 7。决策树. yaml

要考虑两件事。第一个是我们正在定义一个输入和输出变量,它们分别对应于dataaccuracy。第二个是将输入参数分别定义为dataaccuracyInputPathOutputPath

一旦定义了清单,decision_tree组件就准备好了(正如我们所讨论的,logistic_regression组件的构造方式与decision_tree相同)。

好了,现在让我们继续构建最后一个组件,开始吧!

-组件:显示结果

show_results组件的目的是显示从decision_treelogistic_regression组件获得的精度。这个组件也将被定义在一个容器中,但是,与download_datadecision_treelogistic_regression组件相比,show_results组件将使用kfp.componentes@func_to_container_op扩展被转换成一个容器。当要开发的任务不需要多个依赖项,或者要解决的任务不像该组件那样非常广泛时,该扩展非常有用,因此,该组件如下所示:

代码片段 8。显示结果组件

因为这个组件没有在容器注册表中定义,所以我们不需要yaml清单。在这种情况下,@func_to_container_op扩展负责为我们定义这样一个清单。

太棒了,到目前为止,我们已经创建了管道的每个组件,我们只需要生成 python 脚本来定义组件之间的交互,从而能够执行管道,让我们开始吧!

-编译并运行

最后,我们生成定义管道架构的脚本,也就是说,组件将如何交互。那么,这样的文件将如下所示:

代码片段 9。构建管道

主要功能称为first_pipeline(),由dsl.pipeline()修饰。这个主要功能定义了组件将如何集成。因此,在第 17、18 和 19 行中,组件downloaddecision_treelogistic_regression从已经创建的yaml清单中加载。在第 22 行,执行download_task。稍后,在第 26 和 27 行中,通过将download_task的输出作为输入参数来执行任务decision_tree_tasklogistic_regression_task。最后,在第 31 行,通过将来自decision_tree_tasklogistic_regression_task的输出作为输入来执行任务show_results

移动到 Kubeflow 管道 UI 之前的最后一步是编译前面的脚本,该脚本将生成一个yaml清单(称为FirstPipeline.yaml),该清单将被上传到 Kubeflow 管道服务,以便运行管道。在图 6 中,你可以看到一个关于如何上传和运行你的FirstPipeline.yaml文件的可视化描述。

图 6。上传和运行管道

在图 7 中,您可以看到组件show_restuls的输出。

图 7。结果

如果你想访问完整的项目,我给你留下了资源库的链接:【https://github.com/FernandoLpz/Kubeflow_Pipelines】T4

太好了,我们已经到了教程博客的结尾!

结论

在这篇博客中,我们已经看到了什么是 Kubeflow 管道及其组件。为了向读者展示创建 Kubeflow 管道的实用方法,我们还开发了一个分步管道。

虽然在这篇博客中,我们看到了一个基本管道的开发,但是建议读者看一下文档,因为它在创建和部署 Kubeflow 管道时提供了多种选择和可能性。

参考

[1] Kubeflow

[2] 库伯流管道

[3] Argo 工作流程

[4] 机器学习的 Kubeflow:从实验室到生产

[5] 迷你电脑

[6] 码头工人中心

[7] 创建可重用组件

Kubernetes 101:集群架构

原文:https://towardsdatascience.com/kubernetes-101-cluster-architecture-d79995785563?source=collection_archive---------19-----------------------

他们说一张照片胜过一千(或一百万)个字

Marc-Olivier Jodoin 在 Unsplash 上拍摄的照片

在上一篇文章中,我们将 Kubernetes 定义为一个容器编排引擎,它有助于确保每个容器都在它应该在的地方,并且容器之间可以相互通信。

[## Kubernetes 101:你为什么要关心?

towardsdatascience.com](/kubernetes-101-why-should-you-care-6793a09a096a)

合乎逻辑的下一步是看到一个高层次的概念视图,看看系统由哪些组件组成,以及它们是如何相互连接的。这个故事展示了 Kubernetes 集群的每个组件和概念架构的整体情况。

学习率是我每周给那些对 AI 和 MLOps 世界好奇的人发的简讯。你会在每周五收到我关于最新人工智能新闻、研究、回购和书籍的更新和想法。订阅这里

库伯内特建筑

Kubernetes 集群由一组工作机组成。我们称这些机器为节点。每个集群至少有一个 worker 节点,我们在那里托管封装应用程序工作负载组件的 Pods

另一方面,我们有控制平面。把它想象成我们集群中的主节点。控制平面管理集群中的工作节点和单元。

Kubernetes 的概念建筑——作者图片

节点

让我们从下往上开始;什么是节点?节点是我们运行工作负载的物理或虚拟机。在 Kubernetes 中,我们在集群上操作,集群是由一个或多个工作节点组成的组。然而,这些节点不仅仅是简单的设备。

每个节点都包含运行 pod 和容器所需的服务:

  • 一个容器运行时,如containerdCRI-O,用于管理其主机系统的完整容器生命周期,从映像传输到容器执行和监控,从低级存储到网络附件等等。
  • 一个 **kubelet**,运行在每个节点上的主节点代理确保 Kubernetes 调度的容器在该节点上运行并保持健康。
  • 一个 **kube-proxy**,运行在各个节点上的网络代理,维护网络规则。这些规则允许传入的请求从集群内部或外部的网络会话到达 pod。

制导机

节点是我们的应用程序发生奇迹的地方。然而,手动管理所有的容器是不可能的;这就是 Kubernetes 控制平面发挥作用的地方。

Kubernetes 控制平面负责管理 pod 的生命周期并处理所有细节。让我们来看看它的组成部分:

  • API 服务器是 Kubernetes 的联系点。它处理每个对象的数据验证和配置。它是 Kubernetes 的核心和灵魂,所有其他组件都通过它进行通信。
  • “etcd”是一个键值存储,记录集群的所有重要信息:环境配置、应用程序应该如何运行等等。
  • 调度器监控节点并跟踪所有可用资源,以确保 pod 到达能够处理它的节点。
  • 控制器管理器封装了核心 Kubernetes 逻辑。CM 确保所有部分都正常工作。如果没有,它将采取措施使系统达到期望的状态。
  • 云控制管理器与云提供商(如 GCP、AWS、Azure 等)对话。)并传达集群的需求。如果您在自己的场所运行 Kubernetes,那么集群没有云控制器管理器。

Kubernetes 集群的设计基于三个原则。Kubernetes 集群应该是安全的、易于使用的和可扩展的。这个故事演示了我们如何将 Kubernetes 集群可视化为两个部分:控制平面和节点。

然后,我们更深入地探讨了什么去哪里,控制平面如何编排一切,以及工作节点如何负责执行应用程序。

我们现在已经准备好在下一篇文章中动手运行我们的第一个工作负载。

关于作者

我叫迪米特里斯·波罗普洛斯,我是一名为阿里克托工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。

如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请关注我的 MediumLinkedIn 或 Twitter 上的 @james2pl

所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。

Kubernetes 101:你为什么要关心?

原文:https://towardsdatascience.com/kubernetes-101-why-should-you-care-6793a09a096a?source=collection_archive---------20-----------------------

什么是 Kubernetes,为什么每个人似乎都在谈论它?

约瑟夫·巴里恩托斯在 Unsplash 上拍摄的照片

Kubernetes 是近年来基础设施领域的一个时髦词。Kubernetes 是一个希腊词,用来形容一个人在指挥,除此之外,它还是最成功、发展最快的开源项目之一。

但这是为什么呢?什么是 Kubernetes,它试图解决什么问题?这个故事探讨了 Kubernetes 的现状和原因,作为对容器和编排世界的介绍。

学习率是我每周给那些对 AI 和 MLOps 世界好奇的人发的简讯。你会在每周五收到我关于最新人工智能新闻、研究、回购和书籍的更新和想法。订阅这里

什么是 Kubernetes?

Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务。它采用了一种声明性的配置方法,在这种方法中,用户指定世界的期望状态,而不明确指定这应该如何表现。这种想法让我们可以灵活地运行分布式系统,并根据用户的需求进行扩展。

简而言之,Kubernetes 是一个容器协调器,帮助确保每个容器都在它应该在的地方,并且容器之间可以相互通信。

如果你还是觉得失落,那也没关系。有时你必须理解为什么我们需要这样的东西,问题是什么,以及这个新的闪亮的东西如何提供解决方案。为此,让我们考察一下 Kubernetes 的目的是什么。

为什么是 Kubernetes?

一些应用程序将其所有功能捆绑到一个可部署的构件中。不同的服务、事务和第三方集成存在于同一个核心代码库中。这些应用被称为独石。

照片由Zoltan·塔斯Unsplash 上拍摄

这种设计使得系统僵化,升级困难,因为所有东西都必须同时推出。假设一个开发服务x的团队已经完成了任务。在这种情况下,他们除了等待团队y的开发人员完成他们的 sprint 之外什么也做不了,他们正在开发应用程序的一个完全不同的方面。

而且,缩放也有同样的问题;假设应用程序的一部分需要更多的资源来交付。现在,工程师必须为整个应用程序提供更多的资源,即使瓶颈只在单个领域。

为了应对这些挑战,我们转向了微服务;系统的功能被分解成可重复使用的代码,每个代码负责一项操作。如果我们想更新应用程序的一部分,我们可以很容易地只更新负责的服务。此外,我们可以扩展单个服务,以匹配用户期望的性能,而无需过度配置。

因此,分布式计算开始普及,容器在正确的时间出现在正确的地点。有了容器,开发人员可以将他们的服务与所有的依赖项和配置打包在一起。因此,开发人员现在确信,无论底层基础设施如何,他们的服务都可以以相同的方式运行。

然而,仍有一些问题悬而未决:

  • 更新一个容器很容易,但是我们怎样才能做到不被用户注意到并且没有任何停机时间呢?
  • 服务如何发现彼此,容器如何知道如何通信?
  • 我们如何监控系统的性能,在需要时进行干预,并调试问题?

管弦乐队指挥

我们需要的是一个能够自动化所有日常工作的编排系统。具体来说,理想的系统应该:

  • 在不同节点上调度工作负载(即容器)
  • 监控节点和容器运行状况问题并做出反应
  • 提供存储、网络、代理、安全性和日志记录
  • 声明性的而不是命令性的
  • 可扩展

这就是 Kubernetes 发挥作用的地方;像乐队指挥一样,Kubernetes 管理不同节点上容器的生命周期,这些节点可以是物理或虚拟系统。

这些节点组成一个集群。每个容器都有端点、DNS、存储和可伸缩性。Kubernetes 是为了自动化所有这些重复劳动。

结论

Kubernetes 是近几年来基础设施领域的热门词汇。什么是 Kubernetes,为什么每个人似乎都在谈论它?

这个故事研究了 Kubernetes 是什么,它试图解决什么问题,以及它是如何做到的。我们看到了是什么让我们来到这里,单片系统和微服务架构之间的差异,声明式流程如何工作,以及理想的编排引擎的关键方面是什么。

在接下来的文章中,我们将深入探讨,创建应用程序,管理它们的生命周期,并更详细地解释 Kubernetes 的几个特性。

关于作者

我叫迪米特里斯·波罗普洛斯,我是一名为阿里克托工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。

如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请关注我的 MediumLinkedIn 或 Twitter 上的 @james2pl

所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。

Kubernetes 面向数据科学家的实用介绍

原文:https://towardsdatascience.com/kubernetes-practical-intro-for-data-scientists-739c263efa06?source=collection_archive---------4-----------------------

是的,这又是一篇“k8s 入门”的文章。这个世界不需要它,你也没有要求它,然而我已经在某个地方有了它的要点,所以我想:“为什么不呢”?

我最近为纽约市数据科学院现场演示了这个教程,它是由 T2 在这里录制的。为了方便起见,我把幻灯片和要点改编成了这篇文章。对于感兴趣的人,我也将在 2022-23在生产课上教机器学习!

我和孩子们一起整理 k8s 的东西——作者图片

这篇文章有两个部分,一个高层次的概述和一个实际操作部分,在这个部分中,您可以在您的笔记本电脑上部署一个 ML 模型到 k8s。如果你只是想要本地入门的代码,请看要点或者浏览这篇文章的第二部分!

概观

第一部分概述了 Kubernetes 的一些高级知识,这些知识将为实用部分增添色彩。

学习目标

在这篇文章结束时,你应该能够:

  • 理解人们为什么使用 Kubernetes
  • 理解为什么人们不使用 Kubernetes
  • 从高层次描述一些基本的构建模块
  • 在本地 Kubernetes 集群上部署一个简单的 ML 应用程序

我们将不涵盖:

  • Kubernetes 内部架构
  • 集群设置和管理
  • 或者任何超出我能力范围的东西

什么是 Kubernetes?

Kubernetes,也称为 K8s,是一个用于自动化部署、扩展和管理容器化应用程序的开源系统K8s 网站

好吗?但这到底意味着什么呢?为了解释为什么我们可能想要使用 Kubernetes,让我们看一个简单的例子,在没有它的情况下部署和管理一个应用程序

在没有 Kubernetes 的情况下部署和管理应用

这是一个非常简单的工作流程:

  1. 您构建了一个简单的应用程序来搜索新闻文章
  2. 您将搜索应用程序部署到一台远程服务器上
  3. 用户访问该应用程序以获得搜索结果和查找文章

当 1 个用户访问应用程序时,一切正常。

不幸的是,这是作者的图像

但是当 50 个用户访问应用程序时,单个实例就会过载!

作者图片

如果我们需要升级应用程序,它会使搜索不可用。

作者图片

我们需要 Kubernetes 的一些原因

还有很多例子,但是正如您所看到的,部署应用程序只是战斗的一小部分。大规模自动管理应用程序要困难得多。我们需要:

  • 根据工作负载扩展应用程序
  • 无需应用程序停机即可进行更改
  • 将用户流量分配给我们应用程序的多个实例

Kubernetes 是声明性的,这意味着我们告诉它我们想要发生什么,Kubernetes(在一定程度上)为我们做了。这与像 Python 这样的命令式编程形成了对比,在 Python 中,每一行代码我们都显式地改变程序的状态。

然而,你并不总是需要 k8s。事实上,在许多情况下,这可能是矫枉过正。查看我以前在上的一篇文章,比较和对比不同的 ML 部署策略

Kubernetes 物件 101

Kubernetes 对象是 Kubernetes 生态系统中的持久实体。他们定义了应用程序如何在集群上运行。我们将看看:

  • 分离舱
  • 部署
  • 服务
  • 入口

分离舱

Pods 是您可以在 Kubernetes 中部署的最小可部署计算单元。它们是容器化应用程序的典型实例。基本上,运行 Docker 容器。

作者图片

部署

部署为一个或多个 pod 提供了声明式定义,使扩展应用程序变得容易。

作者图片

服务

服务提供了对部署中的 pod 的查找。这是应用程序的许多实例的抽象层。

作者图片

入口

Ingresses 为请求提供了进入集群的入口,因此您可以向外界公开应用程序。

作者图片

今天我们将向您展示如何在 Kubernetes 上部署应用程序。你只需要在本地安装 Docker Desktop 并启用 Kubernetes。

实际的

这部分是动手操作,请使用代码示例和要点进行操作。

设置

  1. 安装 Docker 桌面
  2. 通过进入首选项-> Kubernetes ->启用 Kubernetes 来启用 K8s

用 Docker 测试我们的应用

要在 Kubernetes 上部署一个应用程序,我们首先需要确保它能在本地与 Docker 一起工作。在这里使用示例 fastapi 应用程序:https://github.com/kylegallatin/fast-bad-ml

# clone repo
git clone git@github.com:kylegallatin/fast-bad-ml.git
cd fast-bad-ml# build and run app with docker 
docker build -t ml-app .
docker run -p 5000:5000 -it ml-app

确保可以在 http://localhost:5000/ 到达 app,在http://localhost:5000/predict 进行预测?feature _ 1 = 0&feature _ 2 = 1&feature _ 3 = 2

这是一个简单的 ML 应用程序,采用 3 个特征并返回一个二元预测。

验证 Kubernetes 正在使用 Docker Desktop

当您使用 Docker Desktop 启用 Kubernetes 时,它会为您安装 Kubernetes CLI kubectl并为您的本地集群进行配置。为了确保它的工作,确保你已经安装了kubectl

kubectl version

现在,我们可以看一些库伯内特的例子。

# ensure your using the docker-desktop cluster
kubectl config use-context docker-desktop# check the "nodes" for your cluster (for docker desktop it's just 1)
kubectl get nodes# check the namespaces (logical separation of resources)
kubectl get ns # check the pods running in a given namespace
kubectl get pods -n kube-system

集群设置

我们的集群有一个快速设置步骤,即安装 nginx 入口控制器。这将把流量路由到我们的应用程序,并使 URL 在集群之外可用。

kubectl apply -f [https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.46.0/deploy/static/provider/cloud/deploy.yaml](https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.46.0/deploy/static/provider/cloud/deploy.yaml)

通过在浏览器中转到 http://localhost:80 来验证安装。您应该会看到 404 —未找到。这看起来很糟糕,但实际上意味着事情正在按预期进行!

作者图片

为我们的应用程序编写对象定义

要为您的容器化应用程序创建 Kubernetes 资源,您需要编写 Kubernetes 对象定义。通常这是使用 YAML(另一种标记语言)或 JSON 来完成的。我们将使用 YAML 来定义我们今天学习的资源。

部署将定义 pod:

服务将为我们所有的 pod 副本提供一个抽象层。

Ingress 将允许用户从集群外部访问我们的应用程序:

我们可以直接从之前克隆的fast-bad-ml存储库中将这些应用到我们的集群中:

kubectl apply -f deployment.yaml  
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml

要验证它是否工作,请访问 http://localhost:80 。为了进行预测,我们可以使用http://localhost:80/predict?feature _ 1 = 0&feature _ 2 = 1&feature _ 3 = 2会是这样的!

作者图片

摘要

我们刚刚创建了一个应用程序,为它制作了一个 Docker 映像,并在本地机器上将该应用程序部署到 Kubernetes。

要在云中做到这一点,您可以使用 K8s 服务,如 EKS(在 AWS 上)或 GKE(在 GCP 上),并在那里应用这些相同的 Kubernetes 对象,让它们在云中大规模运行。祝你好运!

峰度——如何向一个 10 岁的孩子解释

原文:https://towardsdatascience.com/kurtosis-how-to-how-to-explain-to-a-10-year-old-a3224e615860?source=collection_archive---------22-----------------------

制造不太直观的概念,直观的

照片由алексарцибашевUnsplash

峰度是描述统计学中的核心概念之一,也是数学中标准化矩的一部分。这个概念本身虽然简单,但却常常因为与之相关的模糊定义而被曲解和误解。在这篇文章中,我将尝试用非常简单的术语解释峰度背后的直觉及其特征,就像我向一个 10 岁的孩子传达它一样。

如果你是第一次听到峰度这个词,这个故事将有助于理解它背后的核心概念。如果你很了解它,也许想向你的侄子或侄女(或者不了解统计的人)解释一下,这将有所帮助

故事是这样的:

想象你和父母去杂货店购物。因为他们忙得不可开交,所以他们让你每只胳膊上提两、五公斤的袋子。你勉强同意,并在每个手臂携带每个 5 公斤的袋子。

现在,你会注意到一些事情。袋子离你的身体越近,就越容易携带。你的手臂离身体越远,就越难控制重量。

作者图片

在这个特殊的例子中,你离你的身体越远,它就越难,峰度就越高。在上面的例子中,与你的重心的距离与峰度的直觉(以及管理权重的难度)成正比,或者为了简单起见,可以说与峰度相等。

现在,如果我们将重量从 5 公斤增加到 10 公斤,然后增加到 15 公斤,从容易到中等到困难的难度也迅速增加,峰度值也迅速增加。

现在用一个正态分布的概率密度函数代替上面例子中的你自己。因为你的大部分体重都集中在非常靠近你的重心的地方,所以你的皮尔逊峰度为 3,或者费希尔峰度为 0。

我们学到了什么:

用非常简单的术语来说,峰度是分布的两端的权重。在上面的例子中,离你的重心越远的重量越难处理/管理

费希尔峰度比较了分布相对于正态分布的重尾程度(不考虑其均值和标准差)。正的 Fisher 峰度意味着分布具有显著的异常值,而负的 Fisher 峰度意味着概率密度的分布比正态分布更加均匀

费希尔峰度为 0 或非常接近于 0 的分布称为中峰度分布。正态分布属于这个范畴。

均匀或平顶的分布具有负的费希尔峰度,也称为平峰度分布。例如:均匀分布

具有高正费希尔峰度的分布称为细峰分布。细尾分布是“重尾分布”,会受到异常值的影响,可能需要根据使用情况进行处理或加工。例如:利维分布,拉普拉斯分布等。

计算峰度的公式:

作者图片

将-3 分量添加到皮尔逊峰度,使其以正态分布为中心,因此也被称为“过度峰度”

Python 实现

峭度可以通过 scipy 软件包方便地计算。下面是计算各种重要分布峰度的参考代码

import scipy.stats as stats
from scipy.stats import kurtosisdistribution_names = ['uniform', 'norm', 'laplace', 'levy']
for distribution_name in distribution_names:
    if distribution_name == 'uniform':
        distribution = getattr(stats, distribution_name)(loc=-2, scale=4)
    else:
        distribution = getattr(stats, distribution_name)
    sample_data = distribution.rvs(size=1000)
    kurtosis_value = kurtosis(sample_data, fisher=True) # notice the fisher param
    print(f"kurtosis value of the {distribution_name} distribution is {round(kurtosis_value, 2)}")

输出:

正如所料,与其他分布相比,levy 分布(众所周知的异常值重分布)的峰度值非常高。正态分布的值不完全为零,因为它不是从连续分布中提取的。如果您随意调整样本大小,sample_data 的大小越大,就越接近于零。如果我们将数据集大小增加到 10⁸,我们会得到下面的结果

你可能也注意到了,当样本量增加时,重尾分布的峰度会爆炸。

进一步解读:

  1. Python Scipy 文档:https://docs . Scipy . org/doc/Scipy/reference/generated/Scipy . stats . Kurt osis . html
  2. 数学中的矩:https://en . Wikipedia . org/wiki/Moment _(数学)

如果您喜欢这篇文章的直观性和简单性,您可能也会喜欢下面统计学概念的一些其他简化版本:

  1. 特征向量&特征值——如何向一个 10 岁的孩子解释
  2. 熵,由 Sundaresh Chandran 在《走向数据科学》中简单解释

请留下掌声/评论,以防你觉得有用。

用 Python 代码识别 ML 模型中的标签偏差

原文:https://towardsdatascience.com/label-bias-identification-in-ml-model-using-python-code-a0fec9febaa6?source=collection_archive---------24-----------------------

如何识别机器学习模型中的偏差

照片由克里斯蒂安·卢拍摄

机器学习领域正在不断发展,这导致了其需求和重要性的显著上升。机器学习模型的应用现在无处不在——在我们的日常生活中,从网飞的电影推荐到亚马逊的产品推荐。从雇佣新员工到金融产品审批决策,现在都是通过机器学习模型自动完成的。人们认为,通过改进的机器学习算法分析的大量数据可以在没有人工干预的情况下实时指导更好的决策和智能行动。

然而,机器学习模型的这种广泛使用导致了风险——偏见的风险。仅举几个例子:

亚马逊终止 AI 雇佣和招聘,就是一个展品 AI 不可能公平的例子;该算法优先选择男性候选人,而不是女性。这是因为亚马逊的系统是用 10 年来收集的数据训练的,这些数据主要来自男性候选人。

这种自动化的决策过程可能会导致社会歧视。其中的关键原因是有偏见的训练数据——正如上面亚马逊招聘人工智能的例子所强调的那样。因此,最重要的是确保机器学习模型预测的结果不偏向任何特定的保护类变量,如性别、种族、国籍。

我想在这里强调两个关键指标,这将有助于确定模型结果中是否存在任何偏差。

a)完全不同的影响——当选择过程对不同的群体产生非常不同的结果时,就会出现这种情况。衡量的方法之一是查看特定受保护类别变量在目标群体中相对于总体人口的分布。我们将使用双样本 Kolmogorov-Smirnov 检验来检验两个样本是否来自同一个分布。零假设是 H0:两个样本都来自同一分布的总体。

b)机会均等——分类器在受保护人群中的真实阳性率应与整个人群中的真实阳性率相等。这里我们将使用 F1 统计来计算偏差。

方法:让我们考虑目标是预测更有可能获得房屋贷款的客户。已经开发了分类器模型,并且已经对属于训练数据集的所有客户进行了评分。让我们假设分数范围从 100 到 1000,任何分数大于 600 的人都是目标人群的一部分。现在的目标是确定在这个目标人群中是否存在任何关于年龄和性别这两个受保护阶层变量的偏见。

在我们的例子中,数据 df 看起来像下面这样——id、事件(实际目标变量)、标签(目标的预测值)和年龄

示例数据

#code for Continuous variable like - age**def** bias_dist_test(data_df,var):
    col_name=var+str('_bucket')
    data_df[col_name] = pd.qcut(data_df[var], q=3)
    data_df2 = data_df.groupby([col_name]).agg({'id': 'count'}).reset_index()
    data_df2[col_name + str('_pop_perc')] = round(100 * data_df2['id']  / data_df2['id'].sum(),2)
    data_df_target=data_df.loc[data_df['score']>600]
    data_df_target2 = data_df_target.groupby([col_name]).agg({'id': 'count'}).reset_index()
    data_df_target2[col_name + str('_target_perc')] = round(100 * data_df_target2['id']  / data_df_target2['id'].sum(),2)
    bias_data_fin=pd.merge(data_df2,data_df_target2,on=col_name,how='left')
    bias_data_fin1=bias_data_fin[[col_name,col_name + str('_pop_perc'),col_name + str('_target_perc')]]
    a,p=stats.ks_2samp(bias_data_fin[col_name + str('_pop_perc')], bias_data_fin[col_name + str('_target_perc')])
    **if** p <.1:
        print("Distribution of "+ var +" is similar with 90**% c**onfidence level between the population and target base and Model is not biased ")
    **else** :
        print("Distribution of "+ var +" is different between the population and target base and Model is biased ")
    **return** bias_data_fin1# Call the function -
bias_dist_test(df,'AGE')

年龄分布相似,人群和目标人群之间的置信水平为 90%,模型没有偏差

从上表可以明显看出,目标人口和总人口的年龄分布非常相似。
接下来,为了衡量机会均等关键绩效指标,首先将为各个受保护类别变量创建不同的类别,然后计算 F1 分数。一旦 F1 分数被计算出来,这些分数的比率将被计算用于不同的类,然后将创建一个 1 比率的指数。该指数被称为偏差分数,较高的值表示模型有偏差。

def bias_check(main_data, var, target,predicted_target):
    # Initialize the empty bias matrix
    bias_df = pd.DataFrame(columns = ["metric", "class1", "class2", "class1_score", "class2_score", "ratio", "bias_score"])
    col_name=var+str('_bucket')
    main_data[col_name] = pd.qcut(main_data[var], q=3)
    class_grp = main_data[col_name].unique().tolist()
    # Generate list of all combinations of classes:
    class_bucket_perm = list(combinations(class_grp, 2))

    for s in class_bucket_perm:
        # Create subset for each class
        class1_grp = main_data[main_data[col_name] == s[0]]
        class2_grp = main_data[main_data[col_name] == s[1]]init_df = {"metric" : ['F1-Score'],
                    "class1" : [s[0]] ,
                    "class2" : [s[1]] ,
                    "class1_score" : [round(f1_score(class1_grp[target], class1_grp[predicted_target]), 4)],
                    "class2_score" : [round(f1_score(class2_grp[target], class2_grp[predicted_target]), 4)]}metric_df = pd.DataFrame(init_df, columns = ["metric", "class1", "class2", "class1_score", "class2_score"])metric_df["ratio"] = round(metric_df[["class1_score", "class2_score"]].min(axis = 1) 
                                 / metric_df[["class1_score", "class2_score"]].max(axis = 1), 4)

        metric_df["bias_score"] = round(abs(1-metric_df["ratio"]) * 100, 1)bias_df = pd.concat([bias_df, metric_df])
        bias_score= max(bias_df["bias_score"])return bias_df,bias_score#Call the function -
bias_df,bias_score=bias_check(df, 'AGE', 'mevent','Label')

不同年龄段的 F1 得分

从上表中可以看出,F1 分数在不同年龄段之间并不十分接近——1 类和 2 类代表不同的年龄段组合。在这里,我创建了 3 个年龄区间,然后检查这些区间的 F1 分数并进行比较。在此基础上,我们创建了一个偏差分数,即 1 类和 2 类 F1 分数之比。
根据经验,最大偏差分数< 10 可被视为模型中无偏差,10–25 可被视为需要更多调查,而> 25 可被视为模型中存在偏差。

标签平滑是另一个正则化技巧

原文:https://towardsdatascience.com/label-smoothing-as-another-regularization-trick-7b34c50dc0b9?source=collection_archive---------17-----------------------

什么是标签平滑,如何在 PyTorch 中实现

戴夫Unsplash 上拍摄的照片

过拟合和概率校准是训练深度学习模型时出现的两个问题。深度学习中有很多正则化技术来解决过拟合;体重下降、提前停止和辍学是其中最受欢迎的一些。另一方面,Platt 的标度和保序回归用于模型校准。

但是有没有一种方法可以同时对抗过度适应和过度自信呢?

标签平滑是一种正则化技术,它扰动目标变量,使模型的预测更不确定。它被视为一种正则化技术,因为它抑制了输入到 softmax 函数中的最大对数比其他对数大得多。此外,作为一个副作用,最终的模型得到了更好的校准。

在这个故事中,我们定义了标签平滑,实现了使用这种技术的交叉熵损失函数,并评估了它的性能。如果您想了解更多关于模型校准的信息,请参考下面的故事。

学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!

标签平滑

假设我们有一个多类分类问题。在这样的问题中,目标变量通常是一个热点向量,其中我们在正确的类的位置有1,在其他地方有0。这是一项不同于二元分类或多标签分类的任务,二元分类中只有两个可能的类,多标签分类中一个数据点中可以有多个正确的类。因此,多标记分类问题的一个例子是,如果您必须检测图像中存在的每个对象。

标签平滑少量改变目标向量ε因此,我们不是让我们的模型预测正确的类别的 **1** ,而是让它预测正确的类别的 **1-ε** 和所有其他类别的 **ε**

标签平滑少量改变目标向量ε。因此,我们不是要求我们的模型预测正确的类的 **1** ,而是要求它预测正确的类的 **1-ε** 和所有其他类的 **ε** 于是,带标签平滑的交叉熵损失函数被转化为下面的公式。

在这个公式中,ce(x)表示x(如-log(p(x)))的标准交叉熵损失,ε为小正数,i为正确类别,N为类别数。

直观上,标签平滑将正确类别的 logit 值限制为更接近其他类别的 logit 值。以这种方式,它被用作正则化技术和对抗模型过度自信的方法。

PyTorch 实现

PyTorch 中标签平滑交叉熵损失函数的实现非常简单。对于这个例子,我们使用作为 fast.ai 课程的一部分开发的代码。

首先,让我们使用一个辅助函数来计算两个值之间的线性组合:

接下来,我们实现一个新的损失函数作为 PyTorch nn.Module

我们现在可以在代码中删除这个类。对于这个例子,我们使用标准的 fast.ai pets 示例

我们将数据转换为模型可以使用的格式,选择 ResNet 架构,并以优化标签平滑交叉熵损失为目标。四个时期后,结果总结如下。

我们得到 7.5%的错误率,这对于十行左右的代码来说是可以接受的,在大多数情况下,我们使用默认设置。

有许多事情我们可以调整,使我们的模型表现得更好。不同的优化器、超参数、模型架构等。例如,您可以在下面的故事中了解如何进一步发展 ResNet 架构。

结论

过拟合和概率校准是在训练深度学习模型时出现的两个问题。深度学习中有很多正则化技术来解决过拟合;体重下降、提前停止和辍学是其中最受欢迎的一些。另一方面,Platt 的标度和保序回归用于模型校准。

在这个故事中,我们研究了标签平滑,这是一种试图对抗过度拟合和过度自信的技术。我们看到了何时使用它以及如何在 PyTorch 中实现它。然后,我们训练了一个最先进的计算机视觉模型,用十行代码识别不同品种的猫和狗。

模型正则化和校准是两个重要的概念。更好地理解对抗方差和过度自信的工具,会让你成为更好的深度学习实践者。

关于作者

我叫迪米特里斯·波罗普洛斯,我是一名为阿里克托工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。

如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请关注我的 MediumLinkedIn 或 Twitter 上的 @james2pl

所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。

标注平滑-使您的模型不那么(过于)自信

原文:https://towardsdatascience.com/label-smoothing-make-your-model-less-over-confident-b12ea6f81a9a?source=collection_archive---------16-----------------------

解决机器学习中过度自信的直观解释。

艺术家的某种死亡是过度自信——罗宾·特罗沃

还记得那次 你关掉了谷歌地图 因为你非常自信知道去目的地的路,但结果却是因为施工道路被关闭了..毕竟你不得不使用谷歌地图。那是你过于自信了。如何解决对机器的过度自信?有时,很容易把一件事和另一件事混淆。因此,对某些你 100%有信心的事情,最好少一点信心。

来源: unsplash

标签平滑可以防止网络变得过于自信,并已被用于许多最先进的模型,包括图像分类、语言翻译和语音识别。标签平滑是一个简单而有效的正则化工具,可以对标签进行操作。

通过谈论机器学习中的过度自信,我们主要是在谈论硬标签。

软标签:软标签是一个带有某种概率/可能性的分数。例如:(0.1 0.2 0.8)

硬标签:硬标签通常是这两个类之一的一部分。它本质上是二进制的(0 或 1)

对于二进制交叉熵损失,我们通过在均匀分布和硬标签之间应用加权平均来将硬标签转换成软标签。标签平滑通常用于提高鲁棒性和改善分类问题。

来源:深入研究标签平滑

标签平滑是输出分布正则化的一种形式,它通过软化训练数据中的基本事实标签来防止神经网络的过度拟合,以试图惩罚过度自信的输出。

标签平滑背后的直觉不是让模型知道特定的输入仅导致特定的输出 。这与过度适应有关,但与过度自信关系更大。我们可以将硬标签转换为 ie,而不是像上面显示的那样将 100%的概率分配给某个类别索引。100%到 91%,把剩下的 9%的不确定性交给其他完全没有信心的阶层。这不会损害模型性能,同时提供了更高的泛化能力。

Tensorflow 只需将指定为参数,就可以更容易地实现交叉熵损失的 label_smoothing。

您可以使用以下公式执行标注平滑:

new_labels = original_labels * (1 – label_smoothing) + label_smoothing / num_classes

示例:假设您有三个 label_smoothing factor 为 0.3 的类。

那么,根据上面的公式,new_labels 将是:

=[0 1 2](1–0.3)+(0.3/3)*

=[0 1 2](0.7)+0.1 =[0.1 0.8 1.5]*

现在,新标签将是[0.1 0.8 1.5]而不是[0 1 2]

如你所见,模型变得不太自信,带有极度自信的标签。这正是我们想要避免的。现在,由于不正确的预测而给予模型的惩罚将略低于使用标签,这将导致更小的梯度。

参考资料:

[1]https://ai . stack exchange . com/questions/9635/about-the-definition-of-soft-label-and-hard-label

[2] 标签平滑什么时候有帮助?

[3] 深入研究标签平滑

用复杂网络标注数据

原文:https://towardsdatascience.com/labeling-data-with-complex-networks-c630d884327e?source=collection_archive---------28-----------------------

如何使用复杂的基于网络的半监督方法来标记您的数据

米卡·鲍梅斯特在 Unsplash 上的照片

可用数据的数量正在快速增长,一方面,这对机器学习模型和实践者来说是极好的,因为这将允许在该领域开发新的解决方案。另一方面,这些数据中的大部分没有被标记,并且标记过程通常是昂贵和麻烦的[1]。

面对大多数机器学习解决方案都局限于监督学习范式的事实,这带来了一个大问题:如何处理如此大量的未标记数据?

为了解决这个问题,半监督范式被创造出来。它的重点是试图用一小组已标记的数据和大量未标记的数据来进行预测。

在这篇文章中,我们将会看到一个半监督学习工具:标签传播。我们将学习如何使用复杂网络和 sknet 库将标签传播到未标记的数据中。

复杂网络上的模块化

为了使用复杂网络传播标签,我们必须首先理解什么是模块性度量,以及它如何与网络上的社区检测相关联。

社区是图中的一个区域,其内部紧密相连,但与网络的其他区域稀疏相连。检测这样的社区提出了一个无监督的 NP 完全问题,并且可以从传统机器学习的角度被视为一个聚类问题。

模块化测量是一种量化网络划分好坏的方法。它基本上测量与没有社区结构的随机网络相比,所发现的社区在多大程度上呈现这种密集/稀疏连接特征。

使用模块化,无监督算法进行社区检测。对我们有用的算法是模块化贪婪算法。

模块化贪婪算法

该算法试图通过首先将每个节点设置为一个社区本身,然后在每一步将它们合并,来找到网络内部的社区结构。

被选择合并的社区将会产生更大的模块化增量。因此,对于每一步,我们选择在该点上最大化的合并,我们正在处理一个贪婪的算法。

为了使用这种算法,称为模块性增量矩阵的矩阵定义如下:

模块化增量矩阵方程

在该矩阵上,Qij 表示在社区 I 和 j 被合并的情况下模块性的增量。

标签传播算法

模块性标签传播算法严重依赖于上面的贪婪模块性算法。这里的想法是,我们可以使用它来传播我们的标签到未标记的数据,以某种方式在我们的网络中生成内聚的组。

因此,算法背后的基本思想如下:

  • 我们从网络中的 L 个标记节点开始
  • 网络的每个节点被定义为一个社区
  • 在每一步,我们使用模块化增量矩阵来合并最大化模块化的社区
  • 如果合并是不可能的(我们很快就会知道为什么),我们就去矩阵中第二高的条目,等等
  • 我们不断重复,直到网络上没有节点是未标记的

很简单,对吧?现在,让我们看看为什么有些合并是不可能的。

给定两个节点,我们有与它们的标签相关的四种不同的可能性:两个都已经被标记但是具有不同的标签,两个都是未标记的,一个是未标记的或者两个都被标记了相同的标签。

对于前两种情况,我们不能合并,因为我们要么改变一些标签,这是我们不能做的,要么不传播任何标签。在后两种情况下,可能会发生合并,因为我们正在传播一个标签,或者只是从相同的标签加入一个社区。

这样,预计我们将结束所有的实例标记。

在 sknet 中使用标签传播器

为了实现这个算法,我们将使用 sknet 库,它专注于在复杂网络中实现机器学习算法。为此,让我们从安装库开始:

pip install scikit-net

现在安装了库,让我们导入所需的库。此外,我们还将导入 Iris 数据集,用于传播我们的标签:

from sklearn.datasets import load_iris
from sknet.network_construction import KNNConstructor
from sknet.semi_supervised import ModularityLabelPropagationX, y = load_iris(return_X_y = True)
y[10:30] = np.nan
y[70:90] = np.nan
y[110:130] = np.nan

请注意,我们将一些 Iris 实例设置为 NaN,这是算法知道哪些标签丢失的方式。

现在,我们必须告诉算法如何将这种表格数据转换为复杂网络。为此,我们将使用一个 KNNConstructor,它使用 K-Nearest-Neighbors 算法来创建图形。如果你想了解更多,可以查看我之前的帖子或者看的文档。

knn_c = KNNConstructor(k=5, sep_comp=False)

这里需要注意的是,我们将参数set_comp设为 False。此参数控制是否应该将数据标签插入到单独的组件中。因为我们想要传播我们的标签,我们不能在不同的标签之间没有边,因为那将把 nan 只连接到他们自己。

最后,我们将实例化传播器,并使其适合数据:

propagator = ModularityLabelPropagation()
propagator.fit(X, y, constructor=knn_c)

然后,用户可以通过以下方式访问生成的标签:

propagator.generated_y

如果我们查看整个代码,我们只有:

from sklearn.datasets import load_iris
from sknet.network_construction import KNNConstructor
from sknet.semi_supervised import ModularityLabelPropagation
X, y = load_iris(return_X_y = True)
knn_c = KNNConstructor(k=5, sep_comp=False)
y[10:20] = np.nan
y[70:80] = np.nan
y[110:120] = np.nan
propagator = ModularityLabelPropagation()
propagator.fit(X, y, constructor=knn_c)
propagator.generated_y

当然,有些标签是不正确的。和每一个机器学习算法一样,不会有 100%准确的解。但是,这种方法为标注数据提供了一个很好的起点。

如果你想进一步了解这个算法,请查阅参考文献[1]。

关于 sknet 库的更多信息

sknet 是一个在复杂网络中实现机器学习算法的库,并允许将数据从一种数据类型转换为其他几种数据类型。它旨在帮助研究人员和实践者开发新的解决方案,并改进现有的机器学习方法。

希望你喜欢并测试 lib!

[1] Silva,T.C .,赵,L .复杂网络中模块性测度指导下的半监督学习(2012),神经计算.78.30–37.10.1016/j.neucom.2011.04.042

拉姆达函数 101:从零到英雄

原文:https://towardsdatascience.com/lambda-functions-101-from-zero-to-hero-81b066cb82b7?source=collection_archive---------20-----------------------

大蟒

了解如何对熊猫使用 lambda 函数——一起编码

图片由 Vlada Karpovich 提供。来源:像素

当我开始学习 Python 时,我记得当我读到 Lambda 函数部分时,我感到多么失落。我尝试阅读相关文章和观看相关视频,但花了一段时间才最终学会如何为我的数据科学项目创建复杂的 Lambda 函数。互联网上的文章最大的问题之一是,它们解释了它是如何工作的,它们展示了一个很容易理解的简单例子,但在现实生活中,它永远不会像它们展示给我们的那样简单。为此,在本文中,我将解释如何在您的数据科学项目中使用 lambda 函数。我将解释如何构建和读取它们。

什么是 lambda 函数?

Python 编程中的 Lambda 函数是一个没有名字的函数。它通常是一个小而有限的单行函数,就像任何其他函数一样,它可以在一个表达式中有多个参数。你还困惑吗?不再害怕。我们把它应用到一个项目中,会更容易理解它的工作原理。我将使用著名的泰坦尼克号数据集。我们会用lambda做一些数据清理和数据工程。你可以在这里找到完整的笔记本。

首先,让我们导入所有我们需要的包。我将使用pyforest在一行代码中导入pandasseabornmatplotlib。我在这个博客里讲过pyforest。然后,我将导入我们将使用的数据集。你可以在这里找到数据集。这个项目的主要目标是创建一个机器学习模型,预测乘客是否在泰坦尼克号上幸存。在这篇博客中,我不会把重点放在模型上,但我会带着这个目标研究数据集。

import pyforest
train = pd.read_csv('train.csv')

让我们检查一下现有的数据集,看看我们能做些什么。我用train.head(2)检查了前 2 行。

似乎我们的数据集中有一些分类值和数值。让我们使用train.dtypes仔细检查一下,这样我们就可以看到数据类型

我们可以看到Sex列是一个对象。对于机器学习,我们应该使用数值,这是我们第一次使用lambda的机会。我将解决 1 个男性和 2 个女性。这是一项简单的任务,我们可以这样做。

train['Sex'] = train['Sex'].apply(lambda x: 1 if x == 'male' else 2)

好吧,这是怎么回事?我们分批去吧。我没有创建新的列,而是将数值寻址到现有的Sex列。出于这个原因,我使用train['Sex'] =。如果我要创建一个新列,我应该使用不在数据集中的列的名称。然后,我写下我感兴趣的值所在的列的名称。在这种情况下,是同一个train['Sex']列。到目前为止,我们有train['Sex'] = train['Sex']。下一步是使用apply(),它允许用户传递一个函数,然后应用到 Pandas 系列的每一个值。

在里面apply()我们将编写我们的 lambda 函数,这里是乐趣所在。我们分批去吧。首先,我们来检查一下lambda x:部分。这里,我们初始化 lambda 并命名一个变量,我们将使用它来调用一个确定列中的每个单元格。x代表Sex列中的每个值。你可以写任何字母或单词;用x只是约定俗成。现在,让我们检查一下1 if x == 'male' else 2部分。这部分的意思是:如果 x 等于‘男’字,把 x 变成 1;如果不是,就把 x 变成 2 。你能看到这里发生了什么吗?让我们再分解一次。以下是每一部分应该如何阅读。

# Apply function to this columns
train['Sex'] =# This is the columns where the values I'm looking for are
train['Sex'].apply()# Calling lambda function
lambda x: # Turn value into 1 if value is equal to 'male'
1 if x == 'male' # If value is not equal to 'male', then turn value into 2
else 2

我也可以这样写,它会以同样的方式工作:

train['Sex'] = train['Sex'].apply(lambda x: 1 if x == 'male' else 2 if x == 'female')

你可以把上面这个例子理解为如果 x 等于‘男性’,就把 x 变成 1。然而,如果 x 等于“女性”,则将 x 变成 2现在有意义吗?我们可以看一个更复杂的例子,确保你能理解。

现在让我们继续关注Fare列。我把它画出来,这样我们就可以看到票价分布。它可能有机会进行一些功能工程。

作者创造的形象

我们可以清楚地看到,大多数门票都不到 100 英镑(我假设票价以英镑为单位)。他们大多数不到 50 岁,极少数超过 100 岁。200 多甚至 500 的门票少之又少。我们可以利用这些数字创造新的价值。我将为这些票创建类别。第一个是给那些多付了 200 美元的人的。另一个给那些支付了 100 到 200 英镑的人,等等。我假设员工没有支付任何费用,所以我将为那些支付 0 的员工创建一个类别。这是我的 lambda 函数:

train['fare_category'] = train['Fare'].apply(
                        lambda x: 1 if x >= 200 
                        else 2 if x >= 100 and x < 200
                        else 3 if x >= 50 and x < 100
                        else 4 if x < 50 and x > 0
                        else 5)

这是一个很大的信息量,但不要担心,让我们分部分进行。我正在使用Fare列中的值创建一个名为fare_category的新特性。然后,我启动了这个函数,就像 a 在第一个例子中做的那样。以下是你阅读一切的方法:

# Turn x into 1 if x is equal or greater than 200
lambda x: 1 if x >= 200 # Then, turn x into 2 if x is equal or greater than 100 and less than 200
else 2 if x >= 100 and x < 200 # Then, turn x into 3 if x is equal or greater than 50 and less than 100
else 3 if x >= 50 and x < 100 # Then, turn x into 50 if x is less than 50 and greater than 0
else 4 if x < 50 and x > 0 # Then, turn x into 5 for all the other instances
else 5

我知道,这太多了,但我希望这有意义。这是最难的了。lambda功能没有做的这么长,有时候用普通的functions会更好。不过,我觉得lambda函数可以让你的代码更干净,更易读。

最终想法

如果你到了这一步,恭喜你!你只是向成为一名伟大的程序员迈进了一步。我真的希望我能很容易地解释清楚。最好的学习方法是练习。出于这个原因,我建议你用我给你的这些例子来玩一玩,也许你可以创造更多。让我知道我是否能帮助你。

Python 中如何使用 Lambda 函数?

原文:https://towardsdatascience.com/lambda-functions-in-python-15b60ff4207d?source=collection_archive---------20-----------------------

语法、用法和常见错误的快速概述

劳拉·奥克尔在 Unsplash 上的照片

如果你是 Python 编程的新手,你可能不熟悉 Lambda 函数。不过,你可能听说过它们。这是学习更多 Lambda 函数的时候了。这篇文章是关于 Python lambda 函数的,为了方便起见,分为 3 个部分——语法用法常见错误

包含的主题(作者图片)

句法

Python 函数的两种主要类型是:

  • 普通功能—def关键字定义,有一个用户自定义名称。
  • 匿名函数—lambda关键字定义,没有用户定义的名称。

让我给你看一些例子。

以下示例显示了一个 普通函数 的定义,该函数在给定半径的情况下返回圆的周长:

import mathdef circle_circum(radius):
  return 2 * math.pi * radius

这里,circle _ circun是函数的名字。是用户给的。半径为自变量。使用此函数时,我们应该为此参数提供一个有效值。假设我们要计算一个半径为 5 cm 的圆的周长。然后,我们可以看到下面的函数调用:

circle_circum(5)

这会返回 31.4159,这是以厘米为单位的周长。

同样的函数可以用 Lambda 来定义。以下示例向您展示了超常规函数的 lambda 函数 的定义:

import mathlambda radius: 2 * math.pi * radius

这里我们使用lambda关键字,而不是def关键字。没有用户定义的函数名和return关键字。你也可以在这里看到半径参数。

尽管上面的 Lambda 函数本身没有任何用户定义的名称,但它可以被赋予一个用户定义的名称:

cir = lambda radius: 2 * math.pi * radius

这里, cir 是分配给 Lambda 函数的用户自定义名称。我们可以用它来调用函数。

cir(5)

这也返回 31.4159。但是,我不建议以这种方式使用 Lambda 函数。这不是一个好的做法。在这种情况下,您可以使用普通的函数定义。

让我再给你看几个例子。下面的例子向您展示了一个 普通函数 的定义,该函数在给定长度和宽度的情况下返回矩形的面积。这一次,我们使用两个参数—长度和宽度。

def rect_area(length, width):
  return length * width

与此等效的 Lambda 函数为:

lambda length, width: length * width

因此,Lamda 函数的一般语法是:

lambda <arguments>: <single expression>

语法解释:一个 Lambda 函数可以有零个或者多个参数。当有许多参数时,每个参数用逗号()分隔。一个 Lamba 函数只能有一个表达式,该表达式是该函数根据自变量的定义。表达式和参数名称由冒号( : )分隔。所有这些都应该写成单行的语句。

注意:带有零(无)参数的 Lambda 函数也是可能的。看起来像是:

lambda: x - y

要使用此函数,应在 Lambda 函数之前定义 xy

使用

λ函数是优选的:

  • 当您希望一次性使用该函数时。
  • 当函数定义中只有一个表达式时。
  • 当你想用几行代码写出清晰的语法时。

然而,这并不合适:

  • 当你需要反复重用函数的时候。
  • 当函数定义中有许多或复杂的表达式时。

Lambda 函数经常与 filter()map()reduce()sorted()apply() 函数一起使用。

带过滤器的λ()

filter() 函数是 Python 内置函数。它选择给定可迭代的元素(例如,列表、元组等)。)满足应用于每个元素的函数定义。语法是:

filter(function, iterable)

我们可以使用一个 Lamba 函数作为 filter() 函数中的函数参数。

以下示例向您展示了 filter() 函数如何从满足 lambda 函数中定义的给定 iterable 中选择 3 的倍数。

iterable = [1, 3, 5, 6, 9, 11, 15, 16, 21]list(filter(lambda x: x % 3 == 0, iterable))

(图片由作者提供)

带有映射的 Lambda()

map() 函数也是 Python 内置函数。它将给定 iterable 的元素转换成新值。语法是:

map(function, iterable)

我们可以使用一个 Lamba 函数作为 map() 函数中的函数参数。

以下示例向您展示了如何使用 map() 函数来计算给定 iterable 中元素的平方(新值)。

iterable = [1, 3, 5, 6, 9, 11, 15, 16, 21]list(map(lambda x: x ** 2, iterable))

(图片由作者提供)

带 reduce()的 Lambda

reduce() 函数不是 Python 的内置函数。它在 functools 模块中,需要额外的导入。它将给定 iterable 的元素简化为一个值。语法是:

reduce(function, iterable)

我们可以使用一个 Lamba 函数作为 reduce() 函数中的函数参数。

# First import the reduce function
from functools import reduceiterable = [1, 3, 5, 6, 9, 11, 15, 16, 21]reduce(lambda x, y: x + y, iterable)

这将返回 87,这是 iterable 中所有元素的总和。如果你想得到所有元素的乘积,将 Lambda 函数定义改为lambda x, y: x * y

reduce(lambda x, y: x * y, iterable)

这返回 44906400!

带有排序()的 Lambda

sorted() 函数也是 Python 内置函数。它可用于按升序或降序(反向)对 iterable 的元素进行排序。语法是:

sorted(iterable, key, reverse)

默认,reverse=False。如果我们将它设置为True,排序将以相反的顺序进行。自定义排序也可以使用可选的参数。参数接受一个函数。我们可以为此使用 Lamba 函数。

正常排序的示例如下:

iterable = [1, 5, 3, 9, 6, 11, 16, 21, 15]sorted(iterable) # Ascending order

(图片由作者提供)

iterable = [1, 5, 3, 9, 6, 11, 16, 21, 15]sorted(iterable, reverse=True) # Descending (reverse) order

(图片由作者提供)

自定义排序的一个示例是:

iterable = [1, 5, 3, 9, 6, 11, 16, 21, 15]sorted(iterable, key=lambda x: x % 5)

(图片由作者提供)

这里,iterable 中的每个元素都根据除以 5 后的余数进行排序。这个标准是由关键论点中的 Lamda 函数给出的。

带应用的 Lambda()

apply() 是熊猫系列或 DataFrame 对象的方法。它沿数据帧或系列的轴(行或列)应用函数。一般语法是:

pandas.DataFrame.apply(function, axis) # For a DataFramepandas.Series.apply(function) # For a Series

为了说明这一点,我们使用下面的数据框架。

import pandas as pddf = pd.DataFrame([[1, 2], [3, 4], [5, 6]],
                  columns=['X', 'Y'])
df

(图片由作者提供)

然后,我们考虑 X 列,将该列中的每个元素加 5,得到一个名为 X+5 的新列。然后,我们在原始数据帧的末尾添加新列。lambda 函数可用于定义一个函数,该函数为 X 列中的每个元素加 5。

df.insert(loc=2, column='X + 5',
          value=df['X'].apply(lambda x: x + 5))
df

(图片由作者提供)

常见错误

如果没有正确使用 Lambda 函数,可能会出现错误。以下是常见的错误类型:

语法错误

当您遗漏了每个参数之间的逗号,或者当您遗漏了分隔表达式和参数名称的冒号,或者当您没有在一行中编写 Lambda 函数时,就会发生这种情况。

iterable = [1, 3, 5, 6, 9, 11, 15, 16, 21]reduce(lambda x y: x + y, iterable) # Missing the commareduce(lambda x, y x + y, iterable) # Missing the colonreduce(lambda x y: x +
       y, iterable)    # Using multiple lines

在每种情况下,都会出现以下错误信息。

(图片由作者提供)

类型错误

当表达式中包含的参数名称比 arguments 部分中给出的多时,就会发生这种情况。

iterable = [1, 3, 5, 6, 9, 11, 15, 16, 21]reduce(lambda x: x + y, iterable)

在这种情况下,将出现以下错误消息。

(图片由作者提供)

交付 0%抄袭内容的承诺

没错,以上内容有 0%抄袭!在发布之前,我已经用语法检查过了。为了保证唯一性,我做了这个 0%抄袭的内容。

我总是传递标题和副标题中承诺的内容

写一对有意义的标题和副标题增强了上下文的 。交付标题和副标题中承诺的内容是我的责任。

编写独特的内容,在上下文和外观上为读者增加价值,这是我自己的责任,定义如下:

https://rukshanpramoditha.medium.com/10-best-practices-that-i-always-follow-to-make-medium-a-better-place-for-readers-e48c6bc27126

下次再见,祝大家学习愉快!同时,你可以在以下网址阅读我的其他帖子:

https://rukshanpramoditha.medium.com

特别感谢 Unsplash 网站上的劳拉·奥克尔,为我提供了这篇文章的封面图片。作者对本帖中包含的书面内容、代码示例、其他图片和内容链接拥有版权。

鲁克山普拉莫地塔
2021–07–05

Python 中的 Lambda 函数及其实例

原文:https://towardsdatascience.com/lambda-functions-with-practical-examples-in-python-45934f3653a8?source=collection_archive---------0-----------------------

如何、何时使用以及何时不使用 Lambda 函数

照片由 Pixabay 发自 Pexels

介绍

当我第一次遇到 python 中的 lambda 函数时,我非常害怕,以为它们是为高级 Pythonistas 准备的。初学 python 的教程称赞这种语言的可读语法,但 lambdas 肯定看起来不太用户友好。

然而,一旦我理解了一般的语法并检查了一些简单的用例,使用它们就不那么可怕了。

句法

简单地说,lambda 函数就像任何普通的 python 函数一样,只是在定义它时没有名称,它包含在一行代码中。

lambda argument(s): expression

lambda 函数计算给定参数的表达式。你给函数一个值(参数),然后提供操作(表达式)。关键字lambda必须在前面。完整的冒号(:)分隔参数和表达式。

在下面的示例代码中,x 是参数,x+x 是表达式。

#Normal python function
def a_name(x):
    return x+x#Lambda function
lambda x: x+x

在我们进入实际应用程序之前,让我们提一下 python 社区认为 lambda 函数好与不好的一些技术细节。

优点

  • 适用于易于理解的简单逻辑运算。这也使得代码可读性更好。
  • 当您需要一个只使用一次的功能时,这种方法很好。

缺点

  • 他们只能表演一个表情。在一个 lambda 函数中不可能有多个独立的操作。
  • 对于在普通的def 函数中跨越多行的操作(例如嵌套的条件操作)是不好的。如果您需要一两分钟来理解代码,请使用命名函数。
  • 不好是因为你不能像在普通的def函数中那样写一个文档串来解释所有的输入、操作和输出。

在本文的最后,我们将看看常用的代码示例,其中 Lambda 函数是不被鼓励的,即使它们看起来是合法的。

但是首先,让我们看看什么情况下使用 lambda 函数。注意,我们在 python 类中经常使用 lambda 函数,这些 python 类接受一个函数作为参数,例如 map()和 filter()。这些也被称为高阶函数。

1.标量值

这是当你对单个值执行 lambda 函数的时候。

(lambda x: x*2)(12)###Results
24

在上面的代码中,创建了函数,然后立即执行。这是一个立即调用函数表达式或生命的例子。

2.列表

过滤器()。这是一个 Python 内置的库,只返回那些符合特定标准的值。语法是filter(function, iterable)。iterable 可以是任何序列,比如 list、set 或 series 对象(更多内容见下文)。

下面的例子过滤了一个列表中的even号。请注意,filter 函数返回一个“Filter object ”,您需要用一个列表封装它以返回值。

list_1 = [1,2,3,4,5,6,7,8,9]
filter(lambda x: x%2==0, list_1)### Results
<filter at 0xf378982348>list(filter(lambda x: x%2==0, list_1))###Results
[2, 4, 6, 8]

地图()。这是另一个内置的 python 库,语法是map(function, iterable).

这将返回一个修改后的列表,其中原始列表中的每个值都根据函数进行了更改。下面的示例对列表中的每个数字进行立方。

list_1 = [1,2,3,4,5,6,7,8,9]
cubed = map(lambda x: pow(x,3), list_1)
list(cubed)###Results
[1, 8, 27, 64, 125, 216, 343, 512, 729]

3.系列对象

一个系列对象是一个数据框中的一列,或者换句话说,是一个带有相应索引的值序列。Lambda 函数可以用来操作 Pandas 数据帧中的值。

让我们创建一个关于家庭成员的虚拟数据框架。

import pandas as pddf = pd.DataFrame({
    'Name': ['Luke','Gina','Sam','Emma'],
    'Status': ['Father', 'Mother', 'Son', 'Daughter'],
    'Birthyear': [1976, 1984, 2013, 2016],
})

Lambda 用Apply()功能通过熊猫。该函数对列中的每个元素进行操作。

为了得到每个成员的当前年龄,我们从当前年份中减去他们的出生年份。在下面的 lambda 函数中,x 是指出生年份列中的一个值,表达式为2021(current year) minus the value

df['age'] = df['Birthyear'].apply(lambda x: 2021-x)

Lambda 带有 Python 的滤镜() 功能。这需要两个参数;一个是带有条件表达式的 lambda 函数,两个是 iterable,对我们来说是一个 series 对象。它返回满足条件的值列表。

list(filter(lambda x: x>18, df['age']))###Results
[45, 37]

Lambda 带有Map()功能的熊猫。 Map 的工作方式与 apply()非常相似,它根据表达式修改列的值。

#Double the age of everyonedf['double_age'] = 
df['age'].map(lambda x: x*2)

我们还可以执行条件运算,即根据一定的标准返回不同的值。

如果状态值是父亲或儿子,下面的代码返回“男性”,否则返回“女性”。注意applymap在这种情况下是可以互换的。

#Conditional Lambda statementdf['Gender'] = df['Status'].map(lambda x: 'Male' if x=='father' or x=='son' else 'Female')

4.数据帧对象上的 Lambda

我通常在特定的列(series 对象)上使用 Lambda 函数,而不是整个数据框,除非我想用一个表达式修改整个数据框。

例如,将所有值四舍五入到小数点后 1 位,在这种情况下,所有列都必须是 float 或 int 数据类型,因为 round()不能处理字符串。

df2.apply(lambda x:round(x,1))##Returns an error if some 
##columns are not numeric

在下面的示例中,我们在数据帧上使用 apply,并在 Lambda 函数中选择要修改的列。注意,我们必须在这里使用axis=1,以便表达式按列应用。

#convert to lower-casedf[['Name','Status']] = 
df.apply(lambda x: x[['Name','Status']].str.lower(), axis=1)

不鼓励的用例

  1. 给 Lambda 函数命名。在 python 风格指南中,这是不被鼓励的,因为 Lambda 创建了一个不应该被存储的匿名函数。相反,如果您想存储函数以供重用,请使用普通的def函数。
#Bad
triple = lambda x: x*3#Good
def triple(x):
     return x*3

2.传递 Lambda 函数内部的函数。对于 Lambda 来说,不需要使用像abs这样只有一个数字参数的函数,因为你可以直接将函数传递给 map()或 apply()。

#Bad
map(lambda x:abs(x), list_3)#Good
map(abs, list_3)#Good
map(lambda x: pow(x, 2), float_nums)

理想情况下,lambda 函数中的函数应该有两个或更多的参数。例如pow(number,power)round(number,ndigit).你可以试验各种内置的 python 函数,看看在这种情况下哪些需要 Lambda 函数。我在这个笔记本里已经这么做了。

3.当多行代码可读性更高时使用 Lambda 函数。一个例子是在 lambda 函数中使用 if-else 语句。我在本文前面使用了下面的例子。

#Conditional Lambda statementdf['Gender'] = df['Status'].map(lambda x: 'Male' if x=='father' or x=='son' else 'Female')

使用下面的代码可以获得相同的结果。我更喜欢这种方式,因为您可以拥有无限的条件,并且代码简单易懂。更多关于矢量化条件的信息,请点击

结论

许多不喜欢 Lambdas 的程序员通常认为,你可以用更容易理解的列表理解内置函数和标准库来代替它们。生成器表达式(类似于列表理解)也是 map()和 filter()函数的方便替代。

无论您是否决定在代码中包含 Lambda 函数,您都需要了解它们是什么以及如何使用它们,因为您不可避免地会在其他人的代码中遇到它们。

my GitHub 中查看这里使用的代码。感谢您的阅读!

参考资料:

定制模型的 Lambda 层

原文:https://towardsdatascience.com/lambda-layers-for-custom-models-df96401c6281?source=collection_archive---------19-----------------------

张量流神经网络中的实用和定制操作

在开发不同复杂度的人工智能算法时,有时需要对可用数据执行特定操作。在此背景下,我们将使用 Tensorflow 2。x,特别是 Keras API。这个工作环境提供了广泛的数学运算、数据处理和图层,但可能需要执行特定的和 运算。在另一篇文章中,我们已经谈到了定制层以及这些工具如何让我们创建适合我们应用的完全原创的模型。但是,我们并不总是需要定义一个真正的原始层,尤其是当要执行的操作简单直接时。例如,我们正在考虑预处理操作、数据大小调整、后处理…

请记住,您可能总是在自定义图层和 Lambda 图层中仅使用 TensorFlow 操作,以从算法中获得最佳性能,并从 TensorFlow 的图形功能中受益。

在这篇文章中

我们将介绍 lambda 函数的概念,它在 Python 语言中的用途,它的潜力和典型应用。我们将从理论的角度,然后在应用案例中,看到如何在 Tensorflow 中创建一个λ****层。我提醒你 关注我的 中的 简介 来支持我的工作,你可以在我的 YouTube 频道和 GitHub repo 中找到它的所有使用代码和插图。

Python Lambda 函数:匿名函数

如果你熟悉 Python 编程,你可能知道 def 语句对于函数 对象的定义。然而,这种说法还有另外一种表达方式:λ。这个名字乍一看可能令人害怕(这个名字本身来源于 lambda calculus,一种符号逻辑),但是在 Python 中,只是一个关键字,它允许您引入快速表达式作为快捷方式

就像 def 语句一样,这个表达式创建了一个您稍后会调用的函数,但是在本例中,它返回函数,而没有在实际的作用域中给它赋值。正因如此,我们通常将 lambda 函数称为函数

lambda 函数的主要应用与函数的内联定义有关,在实际作用域中没有给函数本身指定名称。

照片由沙哈达特·拉赫曼Unsplash 上拍摄

lambda 语句的应用非常简单:我们使用 lambda 单词,后跟一个或多个参数。

x,y,z: f(x,y,z)

其中 x,y,z 是 lambda 函数参数, f 是所需的表达式,使用参数本身。我们可以发现与 def 语句有很强的关系。但是,让我们关注一下不同之处,这在某些情况下很有用:

  1. lambda 函数是一个表达式,而不是语句 :语句 def 将新函数赋给头中的名字,函数 lambda 返回结果。记住: lambda 返回值(新函数)。
  2. lambda 函数的主体是一个表达式,而不是语句块:lambda表达式主体(f)可以被认为是带有 def 语句的标准函数中的返回语句。由于这个原因, lambda 函数也不太通用,因为它的主体仅限于单个表达式,没有有用的逻辑语句(if,for…)。

我们可以注意到 deflambda 主要做相同的工作。以下示例向您展示了如何使用两种策略生成相同的 dummy_calculator 函数。 默认 处理λ参数就像在 def 中一样。

def 与 Lamba 对比—作者图片

lambda 函数遵循作用域查找规则,就像一个函数在另一个函数中一样,它引入了一个局部作用域,这个局部作用域在封闭函数中、在模块中以及显然在内置作用域中看到名字。

为什么我应该使用 lambda 函数?

总结 : lambdas 函数是一种函数速记。你只需要在使用它的代码中嵌入一个函数定义。但是,请记住,它们绝对是可选的解决方案,但是可以成为嵌入小段代码的强大解决方案。

使用 lambda 函数可以生成另一个有趣的 Python 代码结构,即跳转表:列出了用户要求的时间/地点将执行的动作/字典。让我们看看下面的例子:

跳转表示例—按作者排序的图像

这个简单的例子允许我引入另一个概念: lambda 函数也可以用在 def 语句在语法上不合法的地方。给出的代码显示了嵌入在列表文字中的可调用函数列表。我不能用 def 语句这样做:它们是语句,不是表达式。

带有 def 语句的跳转表—作者图片

您可以通过生成一个字典来增强这个解决方案,在这个字典中,每个嵌套的 lambdas 函数生成一个您稍后将调用的函数,从而创建一个通用的多路分支工具。

兰姆达斯词典—作者图片

为了完整起见,我们再提醒另一个重要的方面: 代码接近度。 如果你的函数必须在单一上下文中使用,那么创建一个 lambda 可能是一个好的解决方案。同时, def 语句要求在实际作用域中为新函数指定一个名称,但是这些名称可能会与其他名称冲突。

兰姆达斯不是一个限制

正如我之前所说的,函数的主体必须是一个表达式,而不是一段代码。这看起来像是对表达式本身复杂性的严格限制。实际上,通过利用 Python 语法提供的一些可能性,可以创建更复杂的逻辑表达式,即使它们包含在一个表达式中。我们甚至可以用一行简单的代码来创建循环和迭代,让我们来看看下面的代码:

带有 lambda 函数的 if 语句和循环—作者图片

Lambda 函数和 Python 咒语

正如蒂姆·彼得斯的《Python 之禅》中所述:

漂亮总比难看好。显性比隐性好。简单比复杂好。复杂总比复杂好。扁平的比嵌套的好。疏比密好。可读性很重要。

由于这个原因, lambda 函数通常局限于简单的表达式和小块的内联代码。对于更大的逻辑,最好使用 def 语句。

张量流中的λ函数

在 Tensorflow 中,一个 Lambda layer “将任意表达式包装为一个层对象”。

Lambda层的存在是为了在构建Sequential和功能 API 模型时,任意表达式都可以用作LayerLambda图层最适合简单操作或快速实验。对于更高级的用例,请遵循本指南[tf.keras.layers.Layer](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer)的子类化。

请记住:Lamba 层有一些重要的(反)序列化限制。

子类化[tf.keras.layers.Layer](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer)而不是使用Lambda层的主要原因是保存和检查模型。Lambda通过序列化 Python 字节码来保存层,这从根本上说是不可移植的。它们只能在保存它们的相同环境中加载。子类化的层可以通过覆盖它们的get_config方法以更便携的方式保存。依赖于子类层的模型通常也更容易可视化和推理。

**https://github.com/GitMarco27/TMML/blob/main/Notebooks/010_Lambda_Layer.ipynb

这里显示的代码涉及对著名的 fashion-mnist 数据集的简要分析。服装图像是一个图像处理和分类的问题。这些是 28x28 的黑白图像。目标是开发一种算法,能够以尽可能高的准确度自动对它们进行分类。

时尚 MNIST 数据集-作者图片

为了这个任务,我创建了两个非常简单的模型:一个全连接的密集 和一个卷积分类器。本教程的目的是 Lambda 层在人工智能工作流中的应用,所以让我们检查一下它们的应用。

数据标准化是最大化我们模型训练有效性的重要工具。一般来说,Python 和 Tensorflow 为我们提供了各种图像标准化和处理的工具,但在这种情况下,我决定使用Lambda层来标准化数据。这一层已经使用 python lambda 函数作为第一个参数进行了实例化,并且已经在前一层的输出中按照 Keras Functional API 的语法进行了计算。

在第二个应用案例中,我们可以看到如何利用的实用性来执行扩展数据维度的简单操作,以使其与后续的二维卷积层兼容。

卷积分类器性能—按作者分类的图像

结论

我们回顾了 Python 语言中 lambda 函数的关键概念,了解了如何在 Tensorflow 中实现模拟层以在我们的工作流中执行一些方便的操作,并了解了一个在著名的多类分类数据集上的有用应用示例。

下次见,马尔科

3 分钟机器学习

3 分钟机器学习是一系列与人工智能、深度学习和数据科学相关的教程、视频和文章。你可以在 YouTube 上找到完整的视频集。GitHub 包含了文章和视频中显示的所有 Google Colab 笔记本。希望这些内容对你有用,或者只是你感兴趣。欢迎任何反馈。

查看其他剧集:

LambdaNetworks:高效、准确,但也是可访问的?CIFAR-10 的再现性项目

原文:https://towardsdatascience.com/lambdanetworks-efficient-accurate-but-also-accessible-a-reproducibility-project-with-cifar-10-3429d8ece677?source=collection_archive---------36-----------------------

LambdaNetworks 胜过 attention 和 CNN。这是否适用于小型和低维数据集?

洛伦佐·埃雷拉在 Unsplash 上的照片

我们介绍了我们使用更小和更低维度的 CIFAR-10 数据集复制 LambdaNetworks 的实现和结果,LambdaNetworks 是由 Irwan Bello 在 Google Brain 开发的一种新的机器学习架构。

这个再现性项目的作者是joséIgnacio de alv ear cárdenasWesley A.J.G. de Vries ,代尔夫特理工大学航空航天工程硕士研究生。我们实现 LambdaNetworks 的源代码可以在 GitHub 中找到。我们还有一张总结这篇文章的海报在这里。如果你对代尔夫特大学学生的其他复制品感兴趣,可以在这个链接找到。

这篇文章的结构如下:

  1. 简介
  2. 现有的 LambdaNetworks 论文评审和再现性项目
  3. 本再现性项目的目标
  4. 为什么要λ层?
  5. 【LambdaNetworks 解释
    5.1 内容λ
    5.2位置λ
    5.3λ应用于查询
    5.4 多查询λ层
  6. 约束、数据集和参数
    6.1 约束
    6.2 数据集
    6.3 参数
  7. 实施细节:ResNet-50
    7.1 数据预处理
    7.2 模型准备
    7.3 训练和测试
  8. 实现细节:lambda networks
    8.1单 Lambda 层实现
    8.2 Lambda 层集成在 ResNet-50 内
  9. 结果
    9.1 准确度和模型复杂度
    9.2 训练时间和吞吐量
    9.3 学习率敏感度分析
  10. 结论
  11. 建议
  12. 作者对 Lambda Networks 论文的看法

参考文献

1.介绍

Irwan Bello 在“LambdaNetworks:Modeling long-range interactions without attention”【1】中提出了一种方法,其中通过将上下文转换为称为 lambdas 的线性函数的层来对远程交互进行建模,以避免使用注意力图。根据 Bello 的原始论文,lambda 层的巨大优势在于,它们比自我关注机制需要更少的计算。这太棒了,因为它不仅能更快地提供结果,还能省钱,并有更好的碳足迹!然而,Bello 仍然使用 32TPU v3和 200 GB 大小的 ImageNet 分类数据集。因此,我们开始了这个再现性项目,想知道:lambda 层是否可以在保持其吸引人的特性的同时,适用于主流计算机?

2021 年,世界不仅要应对新冠肺炎疫情,还要应对 T2 芯片短缺,这也是由于家用电子产品的增加、中国工厂的关闭和加密货币价格的上涨。这使得供应下降到创纪录的低点,价格下降到创纪录的高点。导致研究人员、学者和学生(他们通常都在预算范围内)不再能够利用 COTS(商用现成)GPU 快速构建集群,从而不得不处理更旧、更少、效率更低的硬件。

在 2021 年 3 月启动该项目时,没有发布任何官方代码。因此,为了回答上述问题,我们需要尽可能准确地复制 Bello 的论文,同时尝试将其缩小,以便可以在普通的消费者计算机上运行。产生的代码是公开的

2.现有的 LambdaNetworks 论文审查和再现性项目

Bello 的论文已于 2021 年 2 月 2 日发表,在撰写本文时已被引用 7 次。这意味着这篇文章是全新的,因此还没有被学术界梳理过。

然而,一些研究人员和机器学习社区的成员已经阅读了这篇文章,并提供了这篇论文的评论。

  • Yannic Kilcher 在 Bello 发表这篇文章的 4 个月前,已经在 YouTube 上发表了“LambdaNetworks:建模没有注意力的远程相互作用(论文解释)”。基尔彻检查了论文的初稿,向听众解释了它们,并向作者提供了建议。
  • Carlos Ledezma 发表了一个类似 Kilcher 的视频,但是花了更多的时间来阐明注意力层和 lambda 层结构之间的区别。
  • Myeongjun Kim 不仅复制了 lambda 层代码,该社区成员还将其应用于不同的 ResNet 版本和不同的数据集,并进行消融研究。来自上述数据科学家的代码不用于生成我们的代码。然而,我们将简单地将我们的代码与他们的代码进行比较,以了解他们为什么为自己的实现做出特定的选择,并证明我们的代码是正确的。
  • 王飞用 Pytorch 发布了关于 lambda 层的非官方代码。

幸运的是,Bello 已经澄清,他将很快发布与 LambdaNetworks 论文相对应的代码。这很可能会增强每个人对 LambdaNetworks 的理解。

3.这个再现性项目的目标

最初,本文的科学目标是复制 Bello 论文表 3 中的两个特定结果,如下所示。这些结果分别是(何等,2016)* 、λ层。这是为了确定我们是否能够在没有先前代码实现的情况下重现这一点。*

在具有 ResNet-50 架构的 ImageNet 上,lambda 层与卷积和注意力机制的比较。benchmark from "lambda networks:无需关注的远程交互建模

然而,由于 Bello 在他的研究中使用了大量数据集,即 ImageNet,以及他为在合理的时间内获得这些结果而开发的计算资源,即 8–128 TPU v3,这些结果的一对一再现对于普通学生和研究人员来说是不可能的;超出我们作为学生所掌握的资源。因此,范围略有变动。我们的目标不再是在没有公开代码的情况下准确地再现上述结果,而是找出这些结果是否也可以用更小的数据集来实现。

这个再现性项目的个人目标是双重的。首先,随着大量正在进行的研究,注意力似乎是目前最先进的。然而,注意力有一些缺点,lambda 层旨在解决这些缺点,同时略微提高准确性。因此,复制 lambda 层有助于社区在未来尽早采用这种潜在的高级算法。此外,它在更小和更低维数据集上的实现证明了该算法的鲁棒性,以及它在资源受限设备(TinyML)上的潜在实现。

第二个原因是增强和拓宽了此处展示的可再现性项目作者的深度学习知识和技能,这是代尔夫特理工大学由Jan van Gemert博士教授的深度学习课程的一部分。为了感受深度学习,不仅要阅读大量的在线资源,还要对一些开创性的论文有亲身体验。在阅读了名为“注意力是你所需要的全部” [2]的广受欢迎的论文后,我们对可能跟进的所有论文感到兴奋。从抽象上来说,lambda 层有望成为变形金刚的一大进步,它针对多个弱点,带来更高的性能和更低的计算负载。渴望了解更多关于注意力的知识,并对 lambda 层的潜力感到兴奋,选择这个再现性项目对我们来说是一个显而易见的选择。

4.为什么是 lambda 层?

Lambda 层与自我关注机制密切相关,因为它们允许模拟长程互动。然而,自我注意机制有一个很大的缺点,这与它们需要注意图来模拟层激活的相对重要性的事实有关,这需要额外的计算并且渴望 RAM(随机存取存储器)。这使得它们不太适用于严重依赖图像(由像素网格组成)的机器视觉应用,因为对这些像素中的每一个之间的远程交互进行建模需要计算和 RAM。因此,很明显,为了减少任何基于注意力的视觉任务的训练和推理时间,应该解决这个问题。

正如 Bello 在他的文章[1]: 中所说的,“我们提出了 lambda 层,它以更低的内存成本对查询和一组结构化的上下文元素之间的长期交互进行建模。Lambda 层将每个可用的上下文转换成称为 lambda 的线性函数,然后直接应用于相应的查询”。

线性注意力机制【3】提出了一个解决高内存使用率问题的方案。然而,这些方法不捕捉查询和上下文元素之间的位置信息(例如,像素在图像上的位置)。相比之下,Lambda 图层的内存使用率较低,并且可以捕获位置信息。后者甚至导致性能的提高,使得它在 ImageNet 数据集上优于具有线性注意和局部相对自我注意的卷积。

5.LambdaNetworks 解释道

LambdaNetworks 优于 Transformers 的主要优点是,计算上下文的所有组件之间基于内容和位置的交互,可以选择是全局的还是局部的,而不产生昂贵的和存储器密集型的注意力图。为了实现这一点,lambda 层有 3 个主要步骤:

  1. 计算内容 lambda 封装了上下文内容。
  2. 位置λ的计算,其封装了查询和上下文元素之间的相对位置信息。
  3. 将内容和位置应用于输出计算的查询。

下图提供了完整流程的概览。在下面的小节中,我们将详细解释每一个步骤,不断地引用所呈现的 lambda 层计算图。

λ层的计算图。图片由作者提供,灵感来源《lambda networks:无需注意的远程交互建模》

5.1 含量λ

对于内容λ的计算,使用全局上下文。在单个正方形图像的情况下,全局上下文由所有像素组成。因此,如果图像形状是 d×n×n,n 是沿着图像的宽度和长度的像素数,d 是图像尺寸(在彩色图像的情况下是 3),则上下文是形状|n|×d,其中|n|=n。当理解上下文的尺寸时,计算图可能会产生误导,因为它显示它是形状|m|×d。与内容λ相比,位置λ使用局部上下文,作者决定根据后者的计算需要来表示尺寸。实际上,首先用全局上下文计算内容λ,然后用局部上下文计算位置λ。不幸的是,这种对λ和不同矩阵维数的顺序计算没有清楚地反映在计算图中。

在全局上下文中,值和键的计算如下:

然后使用 softmax 沿着|m|维度对键进行规范化,而对值进行批量规范化。最后,从标准化值和密钥的矩阵乘法中获得内容λ。

这种方法的好处是,内容 lambda 编码了如何独立于每个查询,仅基于上下文内容来转换查询。结果,内容λ在图像的所有查询/像素之间共享。

5.2 位置λ

对于内容λ的计算,用户可以通过使|m|等于|n|来选择是使用大小为|m|×d 的局部上下文还是使用全局上下文。出于该再现性项目的目的,由于馈送到λ层的输入的低|n|值,即|n|⊂ [8,4,2,1],全局上下文用于位置λ的计算。这个小的输入维度是由所使用的数据集(即 CIFAR-10)造成的,其图像比 ImageNet 小 6 倍。与从输入中提取局部上下文所需的额外计算相比,利用这个减少的数据集,从较小的上下文中计算位置λs 所获得的潜在加速是微不足道的。

接下来可以观察到,位置λ是值矩阵和位置嵌入之间的乘积的结果。后者是封装了 n 个查询中的每一个与上下文之间的位置关系的 n 个学习|m|×k 矩阵。结果,嵌入是产生 n 个位置λ的|n|×|m|× k 块。

由于内容和位置信息的分离,可以在接收相同输入大小的 lambda 层之间共享位置嵌入,从而降低内存占用。位置λ编码查询需要如何仅基于它们相对于其上下文的每个组件的相对位置进行转换。

5.3 应用于查询的 Lambdas

一旦计算了内容和位置λ,就有可能通过对两个分量求和来计算将应用于查询的最终λ矩阵。

此外,查询的计算方式与键和值类似,即通过将线性投影矩阵应用于输入。

一旦计算了查询和它们各自的λ,λ通过计算的λ和从每个像素生成的查询之间的简单矩阵乘法将查询转换成输出;矩阵中的每一行。**

5.4 多重查询λ层

在 LambdaNetworks 论文[1]中,观察到值维|v|的减少可以极大地减少计算成本以及空间和时间复杂性。因此,作者决定通过随意操纵它的值来将这些复杂性与这个维度解耦。

为此,他建议对应用相同 lambda 的每个(像素)输入使用|h|查询。那么单个(像素)输入的输出是 h 个输出中的每一个的级联结果:

因此,|v|现在等于 d/|h|,这将复杂度降低了|h|倍。作者将这种值维度的减少称为多查询 lambda 层。值得注意的是,在 lambdas 的大小之间有一个权衡:

,以及查询的大小:

6.约束、数据集和参数

在本节中,我们将解释 compute 中的约束如何导致使用不同的数据集,以及 Bello 如何以及为什么从原始论文中调整一些参数。然而,我们想强调的是,为了公平比较,大多数参数都与 Bello 使用的参数完全相同。

6.1 制约因素

与 Bello 的设置相比,存在一些计算限制。Bello 作为一名谷歌研究员,在他的研究项目中使用了 32 个 TPUv3 单位的 ImageNet 分类数据集。不幸是,我们没有这台计算机。代尔夫特大学非常慷慨地向我们提供了 50 欧元的谷歌云信用。然而,50 欧元很可能不足以用 200 GB 大小的 ImageNet 来训练该架构几次。根据 Bello 使用的数据集,ImageNet 由 1.3 亿张过滤和平衡的 JFT 图像组成,这些图像带有由 EfficientNet-L2 生成的伪标签,准确率为 88.4%。因此,选择了不同的数据集,即 CIFAR-10。

这些数据是在谷歌 Colab 和一台高端笔记本电脑上进行训练和测试的,该笔记本电脑配有 2020 年的普通显卡。由于组件的可用性是固定的,本地笔记本电脑提供了可比较的结果作为健全性检查,而 Colab 根据运行时的可用性为客户机分配不同的资源。

主要环境是 Google Colab。它可以免费获得,因此被认为是这个项目最合适的候选。在这种环境中,由于资源是在平台的用户之间共享的,所以无法保证资源,因此很难说获得的结果在运行时间方面是否一致。这是因为在 Nvidia K80、T4、P4 和 P100 之间,不仅 RAM 的数量会发生变化,而且可用的 GPU 类型也会发生变化。该算法根据具体情况确定最有可能使用的内存量,并为重度用户分配更多内存,最高可达 12 GB。一次会话的最大允许时间为 12 小时。就本项目而言,关键是分配的资源在整个会议期间不发生变化,这使得闭会期间的结果可以可靠地进行比较。

第二个培训环境包括一台笔记本电脑,配备 Intel i7–10750h,具有足够的冷却能力,Nvidia Quadro T1000 Max-Q 4 GB DDR5(库存速度)和 16 GB DDR 4 ram,采用单槽配置,库存速度为 2400 MHz。由于完全独立运行,所有结果都是可重复的。

6.2 数据集

我们决定使用一个更小的数据集,即 CIFAR-10
这是一个包含 10 类 60,000 幅 32x32 彩色图像的数据集,每类 6,000 幅图像,分割成 5:1 的训练测试比率。下面是这些图像的一个例子。

CIFAR-10 数据集样本。

6.3 参数

为了找出论文作者是如何准确地汇编结果的,查看用于获得结果的初始条件和超参数是很重要的。接下来,我们编译一个列表,列出所有最重要的参数及其相应的定义和值。它们被分成三个表:

第一个表包含用户可以轻易改变的参数。它们都可以在我们的代码中的 user_input.py 中找到。这些参数包括批量大小、输入大小和初始学习速率等。

第二个表包含在 ResNet-50 和 lambda 层的实现中使用的其他参数。分别在 lambda_layer.pyresnet.pyresnet \ _ lambda . py中定义。

第三表包含关于算法实现的更多信息。要了解更多信息,我们希望读者参考代码中的文档。

7.实现细节:ResNet-50

对于基线实现,我们使用的是由 Pytorch 团队提供的。接下来,我们解释数据预处理步骤、模型准备,并简要讨论训练和测试步骤。

7.1 数据预处理

在将数据输入算法之前,需要对其进行预处理。在这里,数据首先被下载、扩充和标准化。为此,原始图像被随机裁剪,通过用四个黑色像素填充所有图像边来保持原始大小。此外,以 50%的概率随机翻转图像,并用均值[0.4914,0.4822,0.4465]和方差[0.2023,0.1994,0.2010]进行归一化;对应于 CIFAR-10 数据沿 3 个图像维度的平均值和方差的值。训练数据集的转换可以在下一个代码片段中观察到。

此后,训练和测试数据被馈送到迭代器(数据加载器),并且训练图像的样本被绘制用于视觉验证。

7.2 模型准备

在使用预处理的数据执行训练和测试之前,需要创建模型。为此,需要定义损失函数和优化器,以及学习率调度器。

对于损失函数或标准的定义,LambdaNetworks 论文的作者提到使用了平滑值为 0.1 的标签平滑。但是,在所选的 ResNet-50 架构实现中,默认情况下这是找不到的。因此,Christian Szegedy 在论文“反思计算机视觉的初始架构”[5]中提出的标签平滑必须实现。为此,我们调整了由 Suvojit Manna 提出的标签平滑,这导致了如下面的代码片段所示的最终紧凑形式。可以看出,在标签平滑之前应用的损失是与 log softmax 激活的交叉熵。

此外,Adam 优化器与超参数(重量衰减、初始学习率等)一起使用。)显示在参数部分。学习率调度器基于线性和余弦学习率调度器的组合。

在模型准备中,进一步检查模型是否可以在具有 CUDA 的主机 GPU 中运行,并且在由用户指定的情况下,它用存储在先前运行的用户指定的检查点中的参数来填充模型参数。作为设计选择,该模型每隔 5 个时期自动存储检查点。

7.3 培训和测试

一旦定义了模型并预处理了数据,就在 Nvidia Quadro T1000 max-Q 4GB DDR5 上同时执行 90 个时期的训练和测试。在这一过程中,实施了两项措施,以保证顺利分析和比较结果。首先,训练和测试精度、损失和计算时间,以及每个时期的学习率,被存储在日志文本文件中,用于以后的分析。此外,存储精度和损耗信息,以便可以在 Tensorboard 中绘制。

8.实现细节:LambdaNetworks

8.1 单λ层实现

尽管本文中提供了一些代码片段,但它假设已经计算了键、值和查询,没有提供层参数初始化,并且不清楚如何定义位置嵌入。为了实现 lambda 层及其在 ResNet-50 架构中的平滑集成,使用 3 个主要方法创建了一个类:

init :接收输入大小(|n|)、上下文大小(|m|)、值大小(|v|)、输出大小(d)、头数(h)和位置嵌入( E )作为输入的初始化方法。位置嵌入不是在类中创建的,因此它们可以在多个层中轻松共享。在类之外,嵌入被创建并作为输入提供给不同的 lambda 层。位置嵌入的实例化及其在 lambda 层之外的初始化定义如下:

对于键、值和查询的计算,应用单一线性变换而没有偏差。在查询的情况下,线性转换的输出大小为|n|×(kh ),如多查询部分所述。可以在下面的代码中观察到这些转换:

此外,为值和查询实例化了 1D 批处理规范化层,并为键实例化了 softmax 函数:

该函数通过调用“ reset_params ”方法结束,这将在下面解释。

reset_params :初始化 lambda 层的学习矩阵,即文中提到的具有相同正态分布的键、值和查询投影矩阵。如前所述,位置嵌入在λ层之外被初始化。

正向 :神经网络正向传播过程中运行的函数。首先,由于λ层需要将输入图像的高度和宽度压缩成一维,即|n|,输入 x 被整形如下:

此外,由于全局上下文用于当前的再现性项目,因此上下文也通过相应地调整输入的大小来获得:

下一步是使用 init 中定义的线性变换和归一化来计算关键字、查询和值:

最后,通过使用 torch.einsum 函数并遵循λ网络解释章节中概述的等式,计算λs 和输出。输出在最后被整形,使得它具有与馈送到λ层的输入相同的维数。

可以看出,复制 lambda 层所需的所有计算都可以压缩到不到 20 行代码。

8.2 ResNet-50 中的 Lambda 层集成

当阅读来自脸书人工智能研究所的原始 ResNet 论文 [6]时,提出了不同的架构,其主要区别在于层数。从第一列可以看出,ResNet 架构包含 5 个模块( conv1conv2_xconv3_xconv4_xconv5_x ),在 LambdaNetworks 白皮书中称为 cx 级。

来自“图像识别深度残差学习的 ResNet-50 架构

LambdaNetworks 论文 [1]中指出,(非混合)lambda 网络是通过用 lambda 层替换 ResNet 架构的瓶颈块中的 3×3 卷积而获得的,即 conv2_xconv3_xconv4_xconv5_x 。因此,原始 ResNet-50 体系结构中的主要变化可以在瓶颈层的定义中找到,也可以在初始化位置嵌入的 ResNet 的初始化中找到。

以下两个代码片段显示了部分原始 ResNet-50 瓶颈层初始化及其在具有集成 lambda 层的 ResNet-50 中的相应代码行。它清楚地显示了 3×3 CNN 层如何被替换为 lambda 层,而其余代码保持不变。

此外,从 lambda 层架构可以看出,lambda 层的输出与其输入具有相同的维度。然而,在最初的 ResNet-50 架构中,一些 3×3 CNN 层通过使用大于 1 的步幅来减小输入图像的大小。为了在基线和λ层实现之间建立公平的比较,在 ResNet-50 架构的那些阶段,也需要在λ层实现中缩小图像,其中原始 3×3 CNN 层使用大于 1 的步幅。为此,在网络的这些阶段,引入了一个平均 2D 池层,其内核大小为 3×3,(1,1)填充和相应的步长。与 1×1 卷积相比,汇集层的好处是网络不需要学习额外的参数。

每当对图像进行下采样时,都会生成新的位置嵌入,这些位置嵌入将与下一个 lambda 层共享,直到对图像进行新的下采样。

最后,下图显示了没有和有 lambda 层的 ResNet-50 的瓶颈层中的一个层的当前架构。在给出的场景中,该层使用的步幅是 2。在最初的 ResNet-50 中,已经存在由 1×1 卷积构成的下采样块,该下采样块应用于剩余连接,并且增加瓶颈层输入的维度以匹配其输出。现在,前面提到的平均汇集下采样块被添加到瓶颈层的末端。这种下采样的实施导致所需的 GPU RAM 从 5GB 减少到 2GB。

该框图显示了在基于 2D 平均池的具有 lambda 层的 ResNet-50 中附加下采样模块的实现。

9.结果

原始论文对 lambda 层的主要主张是,与卷积层和注意力层相比,它们具有更好的性能和更高的计算效率。因此,下面两个部分分别比较了原始 ResNet-50 与其带有 lambda 层的修改版本的准确性,以及它们所需的训练计算时间和吞吐量。然后,第三部分提供了对初始学习率执行的简单灵敏度分析,以便将该超参数调整到新的架构-数据集组合。

除了使用的初始学习率是 0.0005 之外,所有的结果都是用先前定义的参数和值获得的;因为它被发现是最佳选择。

9.1 准确性和模型复杂性

下面两个图表示 ResNet-50 及其 lambda 层修改版本相对于历元数的训练和测试数据分裂的准确度和损失。它显示了前 1 名的准确性,即其顶级类(softmax 之后概率最高的类)与其相应目标相同的数据点的百分比。正如可以观察到的,ResNet-50 的训练和测试精度性能度量高于具有 lambda 层的版本。在测试数据集的情况下,它高出 3.2%。结果,当在较低维度的数据集(如 CIFAR-10)上训练时,lambda 层并不优于卷积层;然而,他们仍然达到了竞争的结果。

前 1 个 vs 时期的精度图

损失与时期的损失图

在原始的 ImageNet 数据集上,Bello 报告卷积基线的准确率为 76.9%,而 lambda layers 版本的准确率为 78.4%。与在 CIFAR-10 数据集中获得的结果相比,两种体系结构之间的关系已经颠倒。除此之外,据观察,在 CIFAR-10 上,两种架构的精度都有所提高。这个观察暗示了在 10 类而不是 1000 类中对图像进行分类的较低难度。

最后,Bello 报道了基线和 lambda 层模型分别具有 25.6 米和 15 米的可训练参数。在我们的例子中,他们分别有 23.5 米和 12.8 米。由于两个模型丢失了大约相同数量的参数,即 2M,我们假设丢失的参数来自借用的 ResNet-50 实现,而不是来自我们的 lambda 层实现。

9.2 培训时间和吞吐量

准确度和损失图还显示了每个模型的训练时间。对于 ResNet-50,这是 1 小时 17 分 29 秒,结果每个时期的平均时间为 51.6 秒。对于具有实现的 lambda 层的 ResNet-50,总运行时间为 1 小时 3 分 6 秒,导致每个时期 42.1 秒。因此,看起来 ResNet-50 的训练和测试时间大约长了 18.5%,而准确性仅增加了 3.2%,并且 lambda 层的实现是有回报的。然而,人们不仅可以访问在时期 90 获得的最终结果,还可以访问中间结果。可以看出,对于基线 ResNet-50,在时期 90 具有λ层的 ResNet-50 的最高测试精度已经达到时期 41 左右。在这种情况下,基线 ResNet-50 的时期 41 转换为大约 35 分 20 秒,因此比其具有 lambda 层的等效物几乎快两倍。

当比较不同架构的吞吐量结果时,它们必须运行在相同的平台上。鉴于 Bello 在多个 TPUv3s 上运行他的算法,不可能将这个再现性项目的通量结果与 Bello 的结果进行比较。但是,可以比较 CIFAR-10 上基线和 lambda 层版本之间的吞吐量。在基线的情况下,训练时期平均花费 50.92 秒。假设有 50,000 个训练样本,基线的吞吐量是 981.93 ex/s。在λ层的情况下,训练时期大约花费 38.96 秒。结果,λ层模型具有 1283.26 ex/s 的吞吐量。从这些值可以看出,λ层具有比卷积层更高的吞吐量,即高 31%。

9.3 学习率敏感性分析

最后,为了确定在该再现性项目中提出的架构-数据集组合的良好学习速率,初始学习速率( initial_lr )被修改;然而,学习速率调度器保持不变。结果,前 5 个时期的学习速率被定义为[]initial _ lr]T7],2 个⋅]T9]initial _ lr]t11],3 个⋅]t13]initial _ lr]t15],4 个⋅]t17]initial _ lr]t19],5 个⋅【t21]initial _ lr]并且增加,而后面时期的学习速率遵循 a************

对于以下初始学习率,基线和 lambda 模型获得了最高的测试精度:0.01、0.005、0.001、0.0005 和 0.0001。使用 Bello 提出的公式得到了最高的学习率(0.01),即initial _ lr= 0.1⋅b/(256⋅5),以 b 作为我们 128 个样本的批量。其余的学习率是通过将预先计算的最高学习率连续减半而获得的。对于基线和λ层变体,可以在 0.0005 处观察到最大精度。结果可以在下图中看到。

10.结论

LambdaNetworks 承诺提供优于卷积和注意力替代方案的性能,以及更低的内存占用和在训练和推理期间的显著加速。更高的准确性主要归因于提取的基于位置和基于上下文的交互的组合,而更低的存储器使用和更高的速度是通过绕过存储器密集型注意力图、在批元素之间共享上下文信息以及在 lambda 层之间共享位置嵌入来实现的。在最初的论文中,Bello 通过在 ImageNet a ResNet-50 上用 lambda 层交换其标准的 3×3 卷积来验证所有这些说法。这种数据集的选择阻碍了论文的可重复性,因为作者使用 32 TPUv3 进行训练,这是一种大多数学生和研究人员远远无法获得的资源。因此,本文介绍的工作通过在低维数据集(即 CIFAR-10)上进行训练来评估 lambda 层的准确性和速度。为此,我们不仅总结了 LambdaNetworks 上的原始论文并介绍了我们的实现,而且还讨论了我们认为对理解或复制它有歧义的那些方面。

从再现性项目中,我们可以突出 4 个主要结论:

  1. 当在 CIFAR-10 这样的低维数据集上训练时,lambda 层并不优于卷积层;然而,他们仍然达到了竞争的结果。
  2. 在 ImageNet 数据集上,Bello 报告基线准确率为 76.9%,λ层准确率为 78.4%。在 CIFAR-10 上,两种架构的精度都有所提高。这个观察暗示了在 10 个类别中对一幅图像进行分类的难度低于 1000 个类别。
  3. λ层具有比卷积层更高的吞吐量,即高 31%。这导致更少的训练时间。
  4. 两种架构的最佳初始学习率都是 0.0005。

这项工作的结果表明,LambdaNetworks 可以应用于较小的低维数据集,其性能与原始论文中提出的性能相当,并且在可承受的计算时间预算内,即几个小时而不是几天。

这项工作的下一步是用本地上下文实现位置 lambda,其中| m |≦| n |。先前的再现性尝试为此目的使用了 3D 卷积。然而,得到的相对位置嵌入的维数是|m| × |k|,而不是|n| × |m| × |k|。因此,他们不是为每个像素计算相对位置嵌入,而是为整个输入计算单个位置嵌入。

最后,我们希望这项工作将有助于研究界对这种新型架构的讨论和潜在采用,并且我们的实施将加速业界对它的整合。

11.推荐

为了对获得训练和测试准确度结果所需的时间得出更合理的结论,这些运行必须执行多次,并通过取其平均值或中值进行后处理。当在(免费的)Google Colab 中执行时,多次运行的重要性增加了,因为计算可用性会随着时间的推移而变化,并且人们无法正确地确定在每个时间点使用了哪个硬件配置。然而,一个会话内的结果是可比较的,但是建议在更稳定的平台上运行该算法,以便获得更准确的运行时间结果。

Bello 在 ImageNet 上使用的最大学习速率与我们在 CIFAR-10 上使用的有很大不同。当他使用一个特定的公式来获得最大学习速率时,我们使用一个粗糙的 1D 网格来调整学习速率。比较他的结果和我们的结果的准确性可能不公平。也许他训练过的 ResNet-50 和带有 lambda 层网络的 ResNet-50 的行为与我们的有很大不同,因为我们优化了学习速率。因此,他的人际网络中可能有比显示的更多的潜力。建议进行进一步的研究以找到最佳的学习速率。在这种情况下,观察热重启的调整或取消以及调度程序的类型是否会对准确性产生重大影响也是很有趣的。

12.LambdaNetworks 论文作者的观点

这篇关于 LambdaNetworks 的论文承诺,与现有的基于注意力的替代方法相比,在加速训练和推理以及减少内存占用方面取得巨大进步,同时保持或略微提高性能。在此,我们希望向您介绍我们对该论文的看法,其中包括一些使其从现有文献中脱颖而出的方面,以及一些可以改进的地方。

总是先有好消息。尽管论文很长,也就是 31 页,但我们很高兴作者在讨论算法时非常完整和详细。Bello 不仅在 lambda 层的部分实现中包含了紧凑的代码片段,还包含了精确再现结果所需的所有信息(本文中已经讨论了模糊性),甚至包括用于可学习参数的初始化。此外,他还包括一项消融研究,以支持他对建筑的选择。

我们也对论文的附录 A 感到非常惊讶。它以“常见问题”的形式提出了读者可以问自己的理论和实践问题。本附录中的一些条目有助于我们更好地理解论文并加以实施。因此,我们认为这是对文件的巨大补充,也是机构群体可以考虑在未来出版物中采用的成功格式。在提交给会议时,作者总是要回答审稿人提出的问题,以使他/她的提交被接受。如果这些问题不会导致最终文档的变化,它们可以作为“问答”附录包含在作者的回复中。

虽然这是事实,为复制文件,它包含了所有需要的信息,我们认为,作者提出了太多的变化,他的模型,使其阅读困难,有时令人困惑。因此,我们认为,该文件可能已被分成多份文件。例如,在论文的多个部分,Bello 提到了 ResNet-RS 在挤压和激励下的使用,这是一种与 lambda layers 论文同时发布的架构。这种分散在整篇论文中的信息的结合只会使读者迷失方向,即使对于注意力领域的专家来说也是如此,因为该信息最近才变得可用。此外,LambdaResnets 和带有 lambda 层的 ResNet 体系结构之间的区别不是很清楚。我们认为后者是前者的一个特例,但这在论文中没有明确指明。

除此之外,与“注意力是你所需要的全部”论文[2]相比,我们对 LambdaNetworks 论文的难度和复杂性感到惊讶。尽管架构和一般概念有许多共同点,但我们发现 LambdaNetworks 的论文更难阅读和可视化。鉴于这种架构的巨大潜力,我们认为可以从 2017 年推动机器学习领域关注的原始论文中吸取一些教训。

此外,我们认为原始论文中的图 2 可能非常误导人,因为它没有清楚地反映出全局上下文可用于内容λ,而局部上下文用于位置λ。此外,它没有显示如何从层输入中获得上下文。由于它是唯一显示概念的图形,该图中的模糊性会对研究团体对λ层的接受和传播产生不利影响。

总之,尽管该文件有许多含糊之处,但我们已经亲身体验了这一框架的巨大潜力。因此,我们希望作者将他未来的工作建立在 lambda 层的基础上,并通过提供 Google Colab 教程和概念的逐步解释来简化这种新方法的可访问性。通过这里提出的再现性项目和开源实现,我们希望为研究社区和行业提供访问这个新框架的便利。

参考文献

[1] I. Bello, LambdaNetworks:建模无注意的远程交互 (2021),学习表征国际会议

[2] A. Vaswani,N. Shazeer,N. Parmar,J. Uszkoreit,L. Jones,A. N. Gomez,L. Kaiser 和 I. Polosukhin,注意力是你所需要的全部 (2017),神经信息处理系统的进展

[3]李,苏,段,郑,线性注意机制:一种有效的语义切分注意机制 (2020),arXiv:2007.14902 [cs .简历]

[4] S. Ioffe 和 C. Szegedy,批量标准化:通过减少内部协变量偏移加速深度网络训练 (2015),第 32 届国际机器学习会议论文集

[5] C. Szegedy,V. Vanhoucke,S. Ioffe,J. Shlens 和 Z. Wojna,重新思考计算机视觉的初始架构 (2016),2016 年 IEEE 计算机视觉和模式识别会议(CVPR)

[6]何国光,张,任,孙,【深度残差学习用于图像识别】 (2016),2016 年 IEEE 计算机视觉与模式识别会议(CVPR)

基于 Python 的卫星影像土地覆盖分类

原文:https://towardsdatascience.com/land-cover-classification-in-satellite-imagery-using-python-ae39dbf2929?source=collection_archive---------2-----------------------

机器学习|遥感

使用 K-最近邻(K-NNC)、支持向量机(SVM)和 Python 中的梯度推进分类算法对 Sundarbans 卫星影像进行土地覆盖分类。

保罗·西莫斯·门德斯在 Unsplash 上的照片

本文通过 Python 使用不同的分类算法,帮助读者更好地理解孙德尔本斯卫星数据上的土地覆盖分类。

目录

  1. 孙德尔本斯卫星图像
  2. K 近邻分类器(K-NNC)
  3. 支持向量机(SVM)
  4. 梯度推进分类器
  5. 结论
  6. 参考文献

让我们开始吧……

孙德尔本斯卫星图像

来源:谷歌地图

孙德尔本斯是孟加拉湾恒河、布拉马普特拉河和梅克纳河汇合形成的三角洲中最大的红树林区之一。孙德尔本斯森林横跨印度和孟加拉国,面积约为 10,000 平方公里,其中 40%位于印度,是许多珍稀和全球濒危野生物种的家园。上面的谷歌地图显示了孙德尔本斯地区。在本文中,我们将使用 2020 年 1 月 27 日使用 Sentinel-2 卫星获得的 Sundarbans 卫星数据的一部分。

让我们开始编码吧..,

读出数据

让我们使用 rasterio 读取 12 个波段,并使用 numpy.stack()方法将它们堆叠成一个 n 维数组。堆叠后的结果数据具有形状(12,954,298)。使用 loadmat 方法从 scipy.io 包中读取卫星图像的地面实况。地面的真相有 6 类,包括水,植物,树木,裸地,等等

数据可视化

这些 Sundarbans 数据有多个波段,包含从可见光到红外的数据。所以对人类来说很难将数据可视化。通过创建 RGB 合成图像,可以更容易有效地理解数据。要绘制 RGB 合成图像,您将绘制红色、绿色和蓝色波段,分别为波段 4、3 和 2。由于 Python 使用从零开始的索引系统,所以需要从每个索引中减去值 1。因此,红色波段的指数为 3,绿色为 2,蓝色为 1。

如果像素亮度值偏向零值,我们创建的合成图像有时会很暗。这种类型的问题可以通过拉伸图像中的像素亮度值来解决,使用自变量stretch=True将这些值扩展到潜在值的整个 0-255 范围,以增加图像的视觉对比度。此外,str_clip参数允许您指定想要截取多少数据尾部。数字越大,数据将被拉伸或变亮的越多。

让我们看看绘制 RGB 合成图像以及应用拉伸的代码。

让我们使用eathpy . plot中的 plot_bands 方法来可视化地面真相。

下图显示了孙德尔本斯卫星数据的合成图像和地面实况。

作者图片

正如我们所讨论的,数据包含 12 个波段。让我们用 EarhPy 包来可视化每个波段。plot_bands()该方法采用带和图的堆栈以及自定义标题,这可以通过使用title=参数将每个图像的唯一标题作为标题列表传递来完成。

乐队的可视化-作者提供的图像

预处理

标准化是另一种缩放技术,其中数值以平均值为中心,偏差为一个单位标准。这意味着属性的平均值变为零,结果分布有一个单位标准偏差。缩放后的数据以 30:70 的比例分为训练数据和测试数据。下面的代码用于缩放和分割数据。

K 近邻分类器(K-NNC)

k 近邻分类器是机器学习中广泛使用的分类器之一。这种方法的主要目的是同一类的数据实例在特征空间中应该更接近。

让我们考虑一个有 n 个数据点的数据集,表示为f(x1, y1), (x2, y2)... (xi, yi)...(xn, yn)。其中xiyi 分别是特征向量和对应的类别标签。对于新的数据点p,类别标签可以通过具有k值的 k-NNC 来预测,其中k是相邻数据点的数量,如下所示:

K-KNC,作者图片

我们将使用 scikit 学习包来实现 k-NNC。下面的代码 K-NNC 实例用n_neighbors作为 6,并拟合训练数据,预测测试数据的标签,显示准确性,并打印分类报告,其中包括精度,召回和每类的 F1 分数。K-NNC 在测试数据上显示了 98.94%的准确率

K-NNC 分类报告-作者图片

让我们来可视化 K-NNC 的分类图,下面的代码用于预测 Sundarbans 数据的标签,并使用 earthpy 包中的plot_bands()方法绘制数据。

使用 K-NNC 的分类地图-按作者分类的图像

支持向量机(SVM)

支持向量机(SVM)是一种监督学习方法,它从一组已标记的训练数据中生成输入-输出映射函数。映射函数可以是分类函数,即输入数据的类别,也可以是回归函数。

对于分类,诸如径向基函数(RBF)、多项式、Sigmoid 等非线性核函数通常用于将输入数据变换到高维特征空间,在该空间中,输入数据与原始输入空间相比变得更加可分。然后创建最大利润超平面。由此产生的模型仅依赖于类边界附近的训练数据的子集。

下面的代码用于创建一个正则化参数C为 3 和 RBF 核的 SVM 实例。拟合数据,预测测试数据的标签,并打印准确性和分类报告。

支持向量机(SVM)算法在测试数据上显示出 99.88%的准确率。分类报告如下所示:

作者图片

让我们来可视化 SVM 的分类地图,下面的代码用于预测 Sundarbans 数据的标签,并使用 earthpy 包中的plot_bands()方法绘制数据。

使用 SVM 的孙德尔本斯分类地图-图片由作者提供

梯度推进分类器

梯度推进是一种因其预测速度和准确性而备受关注的技术,尤其是对于大型复杂数据。梯度推进是一种机器学习推进。它依赖于直觉,即最佳可能的下一个模型,当与先前的模型结合时,最小化整体预测误差。关键思想是为下一个模型设定目标结果,以最小化误差。

今天我们将使用 lightGBM ,它是一个梯度推进框架,利用了基于树的学习算法。LightGBM 之所以被称为“ Light ,是因为它的计算能力和给出结果的速度更快。运行需要更少的内存,并且可以处理大量数据。它是竞赛中使用最广泛的算法之一,因为该算法的目的是获得良好的结果精度。

下面的代码用于创建一个lightgbm的实例,参数包括学习速度、最大深度、类的数量等

lightbgm分类器对测试数据显示了 98.55% 的准确率,分类报告如下所示。

作者图片

让我们形象化使用lightgbm分类器生成的分类图。以下代码用于预测 Sundarbans 数据的标签,并使用 earthpy 包中的plot_bands()方法绘制数据。

使用 lightgbm 分类器的孙德尔本斯分类图-图片由作者提供

结论

本文展示了如何使用 Python 实现 K-NNC、SVM 和 LightGBM 分类器对孙德尔本斯卫星数据进行土地覆盖分类。与 K-最近邻分类器(K-NNC)和 LightGBM 分类器相比,支持向量机表现出更好的性能。下图显示了上述三个分类器的分类图。

基于准确率的分类器比较——按作者分类的图像

本文中使用的代码可以从下面的 GitHub 库获得。

https://github.com/syamkakarla98/Satellite_Imagery_Analysis

快乐学习✨

更多来自作者

参考

https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html

利用卷积神经网络对卫星图像进行土地覆盖分类

原文:https://towardsdatascience.com/land-cover-classification-of-satellite-imagery-using-convolutional-neural-networks-91b5bb7fe808?source=collection_archive---------4-----------------------

深度学习|遥感

使用卷积神经网络对卫星影像进行土地覆盖分类的 Python 实践教程。

美国地质勘探局在 Unsplash 上拍摄的照片

利用遥感数据进行土地覆盖分类的任务是对光谱特征相似的像素或对象进行分类,并将其分配到指定的分类类别,如森林、草原、湿地、荒地、耕地和建筑区。各种技术已被应用于土地覆盖分类,包括传统的统计算法和最近的机器学习方法,如随机森林和支持向量机等

本文涵盖了使用卷积神经网络(CNN)对卫星影像进行土地覆盖分类的 Python 实践教程。

目录

  1. 简介
  2. 卷积神经网络
  3. 萨利纳斯恒指
  4. CNN 的实现
  5. 培训
  6. 结果
  7. 结论
  8. 参考文献

让我们开始吧,✨

介绍

卫星图像有着广泛的应用,它融入了人类生活的方方面面。特别是遥感经过多年的发展,已经解决了不同领域的很多问题。在遥感中,高光谱遥感器被广泛用于监测具有高光谱分辨率的地球表面。

高光谱成像是遥感中的一项重要技术,它收集从可见光到近红外波长范围内的电磁波谱。超光谱成像传感器通常提供来自地球表面同一区域的数百个窄光谱带。在高光谱图像(HSI)中,每个像素可以被看作一个高维向量,其条目对应于特定波长的光谱反射率。

由于具有分辨细微光谱差异的优势,高光谱遥感已被广泛应用于各种领域,如 C rop 分析,G 生态制图,M 矿产勘探国防研究、城市调查、军事监视、洪水跟踪、等。

使用下面的文章和研究论文来更好地理解高光谱图像。

https://link.springer.com/chapter/10.1007/978-3-662-47456-3_9

卷积神经网络(CNN)

深度学习是机器学习的一个子集,通过合成多个非线性变换来产生高级抽象。在深度学习算法中,卷积神经网络(CNN)在计算机视觉和遥感领域,尤其是图像分类领域,已经获得了广泛的应用。

卷积神经网络(CNN)是一种基于人工神经网络使用卷积乘法的深度学习方法。近年来,细胞神经网络在土地覆盖分类中得到了广泛的应用,表现出了显著的性能。典型的 CNN 由卷积层、汇集层和全连接层组成。

给定 HSI(1-D CNN 的向量)的一个像素,几个具有特定窗口大小的滤波器扫描图像(或向量)以在卷积层创建特征图。训练过滤器以提取输入数据的重要特征。池图层通过从给定窗口中提取代表值(如平均值或最大值)来减小要素地图的空间大小。

这一过程被广泛用于通过避免过拟合问题同时显著降低计算成本来使 CNN 模型更加稳健。完全连接的图层使用先前图层的要素生成分类或回归的最终结果。此外,放弃是一种广泛使用的正则化方法,以缓解过拟合问题。Dropout 通过将连接的权重设置为零来随机丢弃层之间的一些连接。Dropout 可以应用于任何上述层。

萨利纳斯恒指

加州萨利纳斯山谷上空的 224 波段 AVIRIS 传感器采集到萨利纳斯 HSI。其特点是空间分辨率高(3.7 米像素)。覆盖的区域包括 512 行乘以 217 个样本。与印度松树场景一样,我们丢弃了 20 个吸水带。该图像仅作为 at 传感器辐射数据提供。它包括蔬菜、裸露的土壤和葡萄园。下面是萨利纳斯 HSI 的 RGB 合成图像。

萨利纳斯 HSI 的 RGB 合成图像—作者提供的图像

下图显示了 Salinas HSI 数据的 10 个波段。

萨利纳斯 HSI 的乐队——作者图片

Salinas HSI 包含 16 个类别,如西兰花、绿色杂草、休闲、残茬、芹菜、葡萄、葡萄园、玉米、莴苣等。下图显示了有关类别的信息以及样本数量。

类别描述—按作者分类的图像

salinas HSI 数据的基本事实如下所示,HSI 的光谱样本不包含被定义为零(0) 的信息,它们必须在分析前被丢弃,并以色显示。

萨利纳斯·希的地面真相——作者的形象

实施 CNN

让我们建立一个具有不同层的一维 CNN,例如卷积、最大池、漏失和密集层。

CNN 模型的架构如下所示:

CNN 模型摘要—作者图片

培养

让我们从加载数据开始,salinas 数据在中可用。mat 格式。以下代码用于加载数据,并将数据转换为 pandas 数据帧,以便进一步处理。

下面的代码将数据标准化,并以 70:30 的比例将数据分成训练和测试。

用于训练 DNN 的优化器、损失和回调的简要说明。

Adam 优化器

Adam 是一种优化算法,可用于替代经典的随机梯度下降程序,根据训练数据迭代更新网络权重。使用 adam 优化器的优点是:

  • 易于实现。
  • 计算效率高。
  • 内存需求小。
  • 对梯度的对角重标度不变。
  • 非常适合在数据和/或参数方面很大的问题。
  • 适用于非静止目标。
  • 适用于非常嘈杂和/或稀疏梯度的问题。
  • 超参数有直观的解释,通常需要很少的调整。

范畴交叉熵

交叉熵是用于多类分类问题的默认损失函数。在这种情况下,它适用于多类分类,其中目标值位于集合{0,1,3,…,n}中,每个类都分配有一个唯一的整数值。数学上是最大似然推理框架下的首选损失函数。首先要评估的是损失函数,只有在你有充分理由的情况下才会改变。

交叉熵将计算一个分数,该分数总结了问题中所有类的实际和预测概率分布之间的平均差异。分数被最小化,并且完美的交叉熵值是 0。

在编译模型时,可以通过指定'categorial _ cross entropy'将交叉熵指定为 Keras 中的损失函数。

不同的回调如模型检查点,提前停止,张量板。

复试

提前停止:一种减少神经网络过拟合的技术是使用提前停止。如果没有真正学到任何东西,提前停止可以通过终止训练过程来防止模型过度训练。这是非常灵活的——您可以控制要监控什么指标,它需要改变多少才能被视为“仍在学习”,以及在模型停止训练之前它可以连续失败多少个时期。

ModelCheckpoint: 这个回调会在每次成功的历元之后将你的模型保存为一个检查点文件(以hdf5 or h5格式)到磁盘。您实际上可以将输出文件设置为基于 epoch 动态命名。您也可以将损失值或准确度值作为日志文件名的一部分。

以下代码用于训练 CNN 模型。

图表

训练期间的准确度和损失图的代码如下所示, X 轴代表时期,而 Y 轴代表百分比。

结果

训练后的 CNN 模型有 92.40%的准确率,让我们看看混淆矩阵——一种表格表示,通常用于描述分类模型(或“分类器”)在一组真实值已知的测试数据上的性能。

输出如下所示:

混淆矩阵-作者图片

分类报告如下所示:

分类报告—按作者分类的图像

结论

本文正式介绍了高光谱图像及其应用,卷积神经网络(CNN)在 Salinas HSI 土地覆盖分类中的实现,并以分类报告混淆矩阵的形式解释结果。

详细的实践教程可以通过下面的 GitHub 链接获得。

https://github.com/syamkakarla98/Hyperspectral_Image_Analysis_Simplified/tree/master/1D_CNN

更多来自作者

参考

http://www.ehu.eus/ccwintco/index.php/Hyperspectral_Remote_Sensing_Scenes https://plotly.com/python/ https://keras.io/

使用 Python 和 ArcGIS 进行土地覆盖分析

原文:https://towardsdatascience.com/landcover-analysis-using-python-and-arcgis-74223a2c508a?source=collection_archive---------27-----------------------

在 Jupyter 笔记本中创建数据地图或执行空间分析

美国地质调查局提供的陆地卫星图像

ArcGIS 是地质统计分析的顶级平台之一。将 ArcGIS 库与 python 结合使用,您将能够分析 shapefiles、显示 Landsat 卫星影像、创建数据地图,以及在 Jupyter 笔记本中完成更多工作!使用这个库可以创建无限数量的数据科学项目,但对于本文,我将重点关注一个简单的 NDVI(归一化差异植被指数)分析。

在我们开始之前,确保你已经安装了所有必要的库,在 ESRI 的网站上查看 arcpy,了解更多你需要的东西。以下是我在分析中使用的所有库:

**import** **pandas** **as** **pd**
**from** **datetime** **import** datetime
**from** **IPython.display** **import** Image
**from** **IPython.display** **import** HTML
**import** **matplotlib.pyplot** **as** **plt
import sys
import** **arcgis**
**from** **arcgis.gis** **import** GIS
**from** **arcgis.raster.functions** **import** apply, clip, remap, colormap
**from** **arcgis.geometry** **import** lengths, areas_and_lengths, project
**from** **arcgis.geometry** **import** Point, Polyline, Polygon, Geometry
**from** **arcgis.geocoding** **import** geocode
**from** **arcgis.features** **import** FeatureLayer

1。定义你的区域

这部分完全取决于你,对于这个项目,我将使用纽约市。选择区域后,您需要找到与该位置相关的要素图层文件。通常,这可以通过使用 ESRI 的 RESTful API 找到,下面是我如何找到 NYC 的 FeatureLayer:

nyc_fl = FeatureLayer('https://gisservices.its.ny.gov/arcgis/rest/services/NYS_Civil_Boundaries/FeatureServer/4')
ny_df = pd.DataFrame.spatial.from_layer(nyc_fl)
nyc_df = ny_df.iloc[32:33]

这给了我一个地理数据框架,我挑出了覆盖纽约县的第 32 行。在我确定了面积之后,我只是把空间部分转换成一个 shapefile。

作者图片

2.获取卫星图像

这就是我们如何定义我们的要素图层的土地覆盖。NDVI 分析的工作原理是基于卫星图像的每个像素分析颜色。最简单的方法是使用 ESRI 的陆地卫星图像:

landsat_item = gis.content.search('title:Multispectral Landsat', 'Imagery Layer', outside_org=**True**)[0]
landsat = landsat_item.layers[0]

然后,您可以使用 Landsat 项目,定义理想的云量百分比(尽可能保持低的百分比)并设置开始和结束日期:

selected = landsat.filter_by(where="(Category = 1) AND (cloudcover <=0.05)",time=[datetime(2020, 4, 1), datetime(2020, 6, 30)],                              geometry=arcgis.geometry.filters.intersects(area['extent'])) df = selected.query(out_fields="AcquisitionDate, GroupName, CloudCover, DayOfYear",                   order_by_fields="AcquisitionDate").sdf df['AcquisitionDate'] = pd.to_datetime(df['AcquisitionDate'], unit='ms')

美国地质调查局提供的陆地卫星图像

3.添加 NDVI 滤镜并创建一个剪辑

现在你有了你的卫星图像,你可以应用“NDVI 原始数据”函数来计算每个像素的 NDVI

nyc_colorized = apply(nyc_image, 'NDVI Raw')

然后,您可以使用我们之前定义的 shapefile 来获得您所在区域的完美剪辑

nyc_clip = clip(nyc_colorized,nyc_poly)
nyc_clip.extent = area['extent']

作者图片

4.颜色变换

NDVI 值的范围从-1 到 1,由你决定如何对你的土地覆盖进行分类,但是我建议阅读更多关于这个值代表什么的。对于这个项目,我将土地覆盖分为三组:水,混凝土和植被。

masked = colormap(remap(nyc_clip, 
                        input_ranges=[-1,0,     *# water*
                                     -0.1, 0.4, *# Concrete*
                                     0.4, 1],   *# Vegetation, Trees* 
                        output_values=[1, 2, 3]),
                        colormap=[[1, 1, 255, 248], [2, 144, 148, 148], [3,14,247,22]], astype='u8')

作者图片

4.分析

现在你有了你的色彩映射表,你可以分析它了!

xpixel = (nyc_clip.extent['xmax'] - nyc_clip.extent['xmin']) / 800
ypixel = (nyc_clip.extent['ymax'] - nyc_clip.extent['ymin']) / 400

full_res = masked.compute_histograms(nyc_clip.extent,
                                   pixel_size={'x':xpixel, 'y': ypixel})
total_pix = 0
hist = full_res['histograms'][0]['counts'][0:]
**for** x **in** hist[1:]:
    total_pix += xcolors=['#0EF716','#01FFF8','#909494']
labels =[ (hist[1]/sum(hist)), (hist[2]/sum(hist)), (hist[3]/sum(hist)) ]
plt.pie(hist, labels=['', 'Water', 'Concrete', 'Green Cover'],colors=colors,
        shadow=**True**)
plt.title('Landcover of New York City')
plt.show()

作者图片

这只是一个项目想法,但我希望你能以此为灵感,创造出更好的东西。想知道您所在位置的土地覆盖在这些年里发生了怎样的变化?更改开始和结束日期以创建多个色彩映射表。想知道云量如何影响精确度吗?提高云量百分比,比较两者。想要在简历中添加一个独特的、以空间为重点的数据科学项目吗?考虑将 ArcGIS 与 python 结合使用!

感谢您的阅读!

完整笔记本:https://github . com/Bench-amble/geo/blob/main/NYC _ land cover . ipynb

监管大型技术的前景

原文:https://towardsdatascience.com/landscape-for-regulating-big-tech-438c06411801?source=collection_archive---------56-----------------------

使用公共卫生技术的注意事项 |第四部分

这是“将技术用于公共健康的预防措施”系列的第四篇文章,讨论了美国即将出台的监管大型技术的立法,并引用了欧盟的例子。

evUnsplash 上的照片

皮尤研究中心揭示,大多数美国人对公司在使用和保护个人数据方面的正当行为缺乏信心。在这个系列中,我们强调了大型科技公司已经并将继续验证这些担忧的几种方式。第一篇帖子介绍了新兴技术,以及它们在公共卫生和医疗保健中的使用如何具有歧视性和剥削性,第二篇帖子关注技术如何产生电子废物(e-waste)和碳排放,这些废物也危害人类和环境,第三篇帖子强调了医疗科技公司如何利用其用户的敏感数据。

虽然之前的博客强调了公共卫生领域的具体问题,但数据和技术可以以多种方式影响人们的健康和福祉。例如,执法部门使用的面部识别技术(FRTs) 和刑事法律系统使用的风险评估工具都显示出种族偏见。这导致了错误的逮捕和不必要的黑人入狱率不成比例。使用首次登记税的非常真实的影响进一步加剧了这些人口由于生活在支持白人至上的社会结构中而已经面临的压力;“风化”理论“少数群体压力”模型假定,边缘化群体以偏见和歧视的形式经历更大的压力,最终导致更大的健康差距。持续的监视和始终存在的歧视和暴力威胁导致警惕性增加和慢性压力,这可能导致高血压风险增加、睡眠质量下降和许多其他负面健康后果。此外,社会和社区环境的破坏影响了健康社会决定因素中的其他潜在因素。少数群体的错误逮捕和不必要的监禁的增加与获得稳定就业和住房的机会减少相一致,这最终会影响一系列与个人福祉相关的因素,如生活条件、食物获取和学校教育质量。因此,需要进行广泛的监督,让各组织对其技术开发和人民数据的使用负责,并限制政府使用歧视性技术。

国际监管范例

在实施数据保护和环境法规方面,欧盟(EU)走在了美国的前面,但它仍在努力实施问责机制。通用数据保护条例(GDPR) 于 2018 年颁布,是一部数据保护法,通过让处理数据的组织对其使用数据负责来保护欧盟公民的隐私。该法律要求组织采取措施来证明他们符合 GDPR 法规。这包括但不限于为员工指定数据保护责任、维护关于数据使用的文档以及实施技术和组织安全措施。该法规可以对违反其限制的组织处以巨额罚款,无论该组织位于何处。然而,这些罚款还没有被证明是有效的。

欧盟还采取了更广泛的措施来回收过时的电子产品,并减少制造这些电子产品时使用的有害材料的数量。2003 年制定的废弃电气和电子设备(WEEE)指令就是为了解决这些问题而提出的。欧盟最近更新了这些指令,让成员国对电子垃圾的正确回收更加负责。此外,被发现非法出口废物的成员国将被处以巨额罚款。然而,研究表明,尽管采取了这些严格的措施,欧洲产生的许多电子垃圾最终仍然被错误地管理或在欧洲境内非法交易。

修复权运动致力于减轻技术对环境的影响,尤其是电子产品。这一运动的目标是通过要求公司向公众和修理厂公开他们的零件、工具和修理信息,来阻止因修理过于困难而导致的“一次性文化”。今年年初,T2 将开始给电子产品贴上可修复指数的标签。这一举措与奥地利决定降低可修复服务的税收并为消费者维修提供补贴相一致。这些行动旨在确保消费者优先考虑更容易修复的物品,因此,更持久,这最终可能导致垃圾填埋场的电子垃圾减少。虽然这些措施提高了透明度,但减少电子垃圾的责任不应该仅仅落在消费者身上,还应该迫使企业停止生产计划淘汰的产品。

联邦层面的考虑

美国正在采取必要的措施来安装保护措施,以保护美国人的数据。在联邦层面的政策方面,有 2020 年的国家人工智能倡议法案,该法案提出了人工智能(AI)研究和发展的国家战略。这一新的潜在法律将通过授权国家科学基金会(NSF)和国家标准与技术研究所(NIST)在相应领域,解决培训人工智能熟练劳动力和人工智能系统培训数据标准的需求。此外,参议员艾米·克洛布查尔(Amy Klobuchar)提出了竞争和反垄断执法改革法案,该法案更新并加强了合并法,并为美国联邦贸易委员会(FTC)和司法部的反垄断部门提供了更多资源来执行监管。谷歌的三起诉讼和针对其他大型科技公司的案件可能会进一步支持新反垄断法的论点,因为它们的反竞争行为和对人们数据的深远访问暴露了这些过时法规的局限性。电子前沿基金会(EFF)发布了一份全面的备忘录,其中包括反垄断改革和保护消费者隐私的建议。虽然手头的任务很艰巨,但拜登政府也有颁布这些法规的紧迫感。

在这些提议的改变之前,还有其他一些监管新兴技术的使用和保护美国人数据的著名提议。例如,纽约州众议员 Yvette Clark 的团队推出了 2019 年的算法问责法案,该法案要求大公司评估并纠正其机器学习系统中与偏见和歧视有关的问题,并像最近提议的变化一样,将监管权力置于联邦贸易委员会权力之下。2019 年两党减少在线用户欺骗体验(绕道)法案将禁止平台设计用户界面,误导用户在同意让公司访问他们的个人数据之前做出知情决定。最后,参议员谢罗德·布朗的 2020 年数据问责和透明法案旨在通过创建一个机构来监控公司的数据收集行为,防止大型科技公司商品化个人数据,并给予美国人法律工具来追究这些公司的责任,从而“结束侵入性数据收集”。

像在法国和奥地利一样,维修权利运动在美国也越来越受欢迎。2020 年 8 月,民主党人在国会提出一项法案,在疫情的推动下,阻止制造商对医疗设备的限制。这项法律将通过提高维修的便利性和降低维修成本来抑制有计划的报废和电子垃圾的产生。除了这种努力,在加速化石燃料开采和“非能源政策”分析的标准实践中,应该有对人工智能使用的监管。“非能源政策”指不明确涉及或披露气候或能源使用,但仍有严重气候影响的政策。走向数字化健康记录的运动是“非能源政策”的一个例子,有必要考虑其能源和气候影响。

除了政策,其他关键的技术专家、学者和活动家也提出了其他形式的联邦层面的问责制。目前的监管机构,如 FTC,可能没有能力处理与监管人工智能相关的社会、技术和法律挑战。当食品药品监督管理局(FDA)正在更新其作为医疗设备的软件的监管框架以包括人工智能和机器学习软件时,Joy Buolamwini 和他的同事们提议建立一个类似于 FDA 的新联邦办公室。虽然他们白皮书的重点是对首次公开募股的监管,但他们对新联邦办公室的核心主张也适用于更通用的人工智能技术。此外,凯茜·奥尼尔博士提议为数据科学家发放许可证,类似于临床医生和律师。这项工作将涉及标准化的课程和道德标准的制定。任何不道德的违规行为都将导致许可证被吊销,这让数据科学家不必在被解雇或保护公众之间做出选择。这些保障措施可以加强防止伤害和保护人民所需的监督。

正在执行的国家级法规

在州一级保护人们的数据也取得了一些进展。加州效仿欧盟,于 2018 年颁布了加州消费者隐私法(CCPA) ,而伊利诺伊州自 2008 年以来已经有了生物识别信息隐私法(BIPA) 。CCPA 管理企业对个人信息的访问、删除和共享。BIPA 规定,如果企业有意收集或披露个人的生物识别信息,必须征得个人同意,安全存储这些生物识别信息,并及时销毁生物识别信息。《BIPA》是美国唯一一部允许个人就侵犯生物识别特征造成的损害提起诉讼的法律。目前,华盛顿有几个法案提供类似的保护人们的数据,并禁止国家机构部署歧视性的自动决策系统。尽管取得了这些进步,但仍有需要改进的地方。例如,CCPA 允许公司向选择退出或拒绝分享数据的人收取费用。正如我们在欧盟看到的那样,任何形式的立法都需要实施问责机制来实现变革。

对创可贴的保障和承诺

我们需要强有力的法规来限制大技术的进入和权力,而不是把技术的责任完全放在用户身上,否则我们就会面临大技术统治我们的风险。内华达州的立法提案说明了这种替代现实,该提案授权科技公司在其所在地周围的土地上组建政府。“经济发展”的潜力听起来可能很诱人,但治理应该建立在保护人民健康和福祉的基础上,而不是建立在大型科技公司首席执行官认为“正确”的反应和突发奇想上。科技公司已经证明,他们没有能力通过证明以牺牲安全为代价、为了利润而开发和滥用人们的数据以及推卸对其有害行为的责任来进行治理。权力整合的威胁强调了政府和大型科技公司分离的必要性。我们这个系列的最后一篇文章将深入挖掘科技行业中长期压迫的系统性问题,列出技术专家可以用来消除这些问题的资源,并探索专注于正义、自治和主权的其他努力。

[1] Teachout,Z. 2020。把他们分开。圣马丁出版集团:所有要点书籍。

这篇文章是“将科技用于公共卫生的注意事项”系列的第四篇——查看该系列的第一篇第二篇 第三篇

本博客系列由Priya Govil合著。韩瑜和普里亚·戈维尔是健康研究院的工作人员。本博客系列中反映的观点是作者的观点,不一定代表 AcademyHealth 的官方立场。**

了解朗之万动力学背后的数学概念

原文:https://towardsdatascience.com/langevin-dynamics-29bbb9407b47?source=collection_archive---------9-----------------------

物理学(一如既往)丰富了

图像的来源

在这篇文章中,我的目标是总结一篇由马克斯·韦林伊惠德撰写的相当“老”的论文。它提出了 随机梯度朗之万动力学(SGLD)的概念。如今 越来越多地使用 的一种方法。

我的动机是展示推动 SGLD 前进的数学概念。对于那些可能觉得乏味的人,你可以简单地采用方法论,忽略严谨的部分

时代思潮ˌ时代精神

正如我提到的,这篇论文是大约 10 年前写的。与今天相比,那个时期的 ML 既相似又不同:

  • 相似的——网络和现代计算提供的大量数据极大地促进了人工智能的发展,许多研究人员对它产生了热情
  • 不同的——DL 还不常见

因此,ML 研究主题略有不同:

研究人员认为神经网络是一种有前途的工具,但仍然只是另一种工具,如决策树或朴素贝叶斯。贝叶斯方法(对于理解作者的动机是必不可少的)在大量的学术培训中是强制性的。

为了对 21 世纪第一个十年的 ML 研究有一个更广阔的视野,我推荐阅读诸如杜达主教的书籍

作为一个轶事,主要作者,Max Welling 是该学院的贝叶斯研究员,并就此主题撰写了论文。但 DL 来到了小镇,2013 年他发表了一篇论文 自动编码变分贝叶斯 成为了 VAE 的基础。说明 DL 吞并了大家。

数学工具

为了更好地理解这篇论文,我们必须熟悉一些数学工具:

  • 贝叶斯方法
  • 大都会黑斯廷斯
  • 随机优化
  • 朗之万方程

我将简要描述这些工具

贝叶斯方法

显然,这是一个出现在许多领域的广泛话题。然而,贝叶斯问题很容易描述。我们有一组观察值(实验的图像、数字或分类结果),表示为x。我们假设观察值由分布 P 生成,其形状(例如高斯或均匀)已知,但其超参数未知。

因此,我们的目标是找到 H. 在更正式的术语中,我们有贝叶斯公式:

因为

我们有

如您所见,分母独立于 H. 此外,我们可以注意到 P(X)通常很难处理,例如,当您希望估计概率以获得单个观察值时,请考虑 GMM。

我们可以重写

  • P(H) - 先验分布超参数的分布(正如我们所相信的)
  • P(X|H)- 似然,获取观测值的概率假设超参数值集
  • P(H|X) — 后验分布

因此,贝叶斯问题是关于寻找后验分布,其中我们假设:

  • 后牙有一定的形状
  • 超参数是从之前的给定中提取的

例子

  • 当我们研究高斯分布时,我们通常假设均值本身来自高斯分布,标准差来自某个伽玛分布
  • 一个二元序列,我们假设它有一个二项式分布,其中它的 P 是从贝塔分布中抽取的。

提供最优后验分布的解我们称之为最大后验估计(MAP)

对于熟悉 MLE 解决方案的读者来说,MAP 与 MLE 的区别仅在于前者。

大都会黑斯廷斯

我曾经写过一篇关于这种方法(吹牛的权利)的文章,显然网络上有更好的来源。这是一种 MCMC 采样方法,通常用于寻找后验分布,因为它依赖于马尔可夫链收敛特性来获得所需的参数。

  • 在每一步中,我们从一个提议函数中抽取一个样本,通常它的参数取决于前一个样本。这个函数往往是“简单的”:比如高斯
  • 接受\拒绝步骤——我们将新样本与其“前一个”样本进行比较,如果新样本的得分更大,我们就接受它,否则我们仍然使用前一个样本。

这是一个无偏差的算法,但有一个巨大的方差(许多其他采样算法)。这种算法的主要缺点是必须对整个数据进行多次迭代,也就是说,不能使用复杂的技巧,如使用小批量。

随机优化

Robbins & Monro 在 50 年代早期发表的一种算法提供了对以下问题的解决方案:

fa函数和 b a 实数并且有解**

我们不能直接测量 f 的值,但是我们可以测量一个函数 g 使得

下面的公式收敛到所需的解:

对于条件:

如果我们尝试将贝叶斯方法的小节与这一部分联系起来,我们可以猜测随机优化是一种寻找地图解的好方法

朗之万方程

朗之万方程描述了作用在花粉粒上的力,它是布朗在 1827 年开始的研究的一个发展

可以这样写:

在哪里

m-质量

a-加速度

垂直速度

F 力

ε-均值为 0 且方差与时间成比例的随机项

由于质量很小,LHS 可以忽略不计。众所周知,速度是位置的时间导数,力是势梯度。

朗之万方程变成了:

现在让我们对时间导数做一些离散化:

如果我们忽略最后一项,我们得到了每个数据科学家都见过一次的东西。

有意思吗?

是的。从物理学上我们知道,方程的稳态解允许从后验分布中取样。我暗示过贝叶斯方法因缺乏小批量技术而遭受损失

如果我们有一个工具:

  • 可以用一种很好的“可分级”的方式来写(对于小批量来说,分级很好)
  • 知道在哪里汇合

也许我们能够找到一种很好的方法来进行贝叶斯研究。

在我们前进之前,人们还可以注意到

可以认为是 Metropolis Hastings 的均值方差对:

这将问题修改为“我们知道它可能工作,我们只需要研究接受\拒绝机制”

让我们造纸吧

第一部分

正如我在时代精神一节中所描述的,作者们在这段时间对 ML 进行了高水平的调查。他们提到了大量的数据,这些数据提高了对好的 ML 的需求,以及在这个领域确实发生的进步。根据作者的观点(他们是对的),ML 无处不在:视觉、语言和语音处理。这一进展提高了对具有两个重要特性的算法的需求:

  • 它们可以在最优化问题中表现出稳健的收敛性
  • 他们能很好地处理大量的数据

****随机优化两者皆有,这是一种优化算法,因为它依赖于误差测量,可以用于小批量。

现在作者开始讨论贝叶斯方法。这些方法在“ML 进步党”里是没有的。他们既不擅长在线处理,也不擅长处理大量数据。乍一看,人们可以说这是告别的时候了。不再需要贝叶斯方法。然而,这些方法具有两个重要的特性:

  • 他们处理得很好
  • 他们可以量化模型不确定性

由于我们处理的是巨大的数据集,过度拟合几乎总是一个问题,而且随着模型变得越来越复杂,评估其风险的需求就变得不可避免。因此不要放弃贝叶斯方法。

论文的想法

让我们结合随机优化和朗之万动力学来使用贝叶斯方法。前者将把我们带到 MAP 解,后者将建议一个稳定的后验采样机制。

第二部分

在这一节中,作者描述了贝叶斯问题的随机优化的实现。

回想一下, X 是观察数据,表示参数设置为

优化问题的更新步骤是:

其中 N 是小批量的大小,N 是数据量。爱普西龙满足罗宾斯和门罗条件。这样的解收敛于映射。这是一个很好的解决方案,但它不提供不确定性估计,并且明显容易过度拟合。下一步是针对朗之万方程修改随机优化

对于的先验。最后一项是零均值噪声项,也是要研究的方差。注意这个方程是朗之万方程的离散形式(它是一个随机微分方程** - SDE ),它的解是一个后验分布。我们还不知道这种离散化是否保持了所需的收敛性。然而,我们知道,由于这个解类似于 Metropolis Hastings,如果我们很好地控制ε的减少,我们可以得到满足要求的低拒绝率。**

可以看出,从数据科学的角度来看,该论文简单地建议

“做 SGD 的时候,简单加高斯噪声,仔细检查方差就行了”。

第三节

所以我们讨论了朗之万离散方程

现在,我们希望检查它是否适用于小批量解决方案。也就是说,它可以近似为

其中:

注:在论文中,写的是

这是一个错误。

现在我们可以将随机优化与朗之万动力学结合起来

  • 我们构建满足 R&B 条件的ε序列(例如,递减为

  • 在运行的早期,随机部分占主导地位,我们简单地将它添加为零均值项(如 R&B 所允许的)
  • 系统走向地图解决方案
  • 当我们接近地图时:

1.两个相邻步骤之间的比率收敛到 1(因此废品率变为 0)

2.ε衰变,因此梯度部分被忽略,朗之万项起支配作用。

这是为什么呢?由于我们正在接近地图,梯度项变得很小,这意味着我们可以在它周围创建一个嘈杂的步骤,这提供了大部分的波动(简单地说,因为我们是在固定点附近)

在这个阶段,我们可以简单地从朗之万方程开始采样,通过 MH 和物理学知道我们是从后验采样。

图像来源

让我们严格-选修

我们现在希望证明小批量解收敛于离散解。

即:

遵循这个

****

我们可以采用“批量”朗之万方程:

并重写为:

其中:

第一项的方差是

对于有限 v。

当ε衰减到 0 时,朗之万方差遵循ε大小,而随机项具有ε平方大小的方差。因此,朗之万项成为主导。

最后一部分使用马尔可夫性质表明样本收敛于所需的后验分布,

第四节

如上所述,我们经常使用贝叶斯问题的抽样算法(即寻找后验)。我们展示了一个抽样,它提出了两个问题:

  • 转变点是什么时候
  • MC 估计量的期望值是什么

过渡时间

跃迁时间是朗之万方程开始支配的点,我们可以假设它的输出很好地反映了所需的后验分布。因为梯度对于不同的方向可能具有不同的比例。我们引入一个矩阵 M 来缩放梯度方向(人们可以把 M 看作是对批量标准化的模拟)。我们可以将更新步骤编写如下:

回想一下,随机项的方差是

根据 CLT 公式,我们预计 h 在 g 附近的误差服从正态分布。在一系列非常简单的计算中,我们得到这个方差大约是

其中 Vs 是经验协方差矩阵。我们希望 M 的条件是

其中λ是λ的最大特征值,这意味着我们需要选择一个遵循α条件的步长,以验证我们是否达到了朗之万机制。

后验预期

我们生成一系列样本

这个序列的预期表现为它是从一个后验分布中抽取的,我们有

由于ε衰变,我们期望一种不同于常规马尔可夫链的方式:这里我们可能在终止阶段有更强的相关性。我们希望减少这种情况,因此我们可以给 MC 估计量增加权重

例子

高斯的

让我们采样如下:

获得的图

摘自论文

该图比较了真实后验数据和样本数据

摘自论文

这个图表显示了相变

逻辑回归

我们提出了逻辑回归问题,并用 SGLD 解决了这个问题

β参数具有标度=1 的拉普拉斯先验分布

我们有

a9a 数据集上进行试验,获得了以下图形:

来自论文的图表

摘要

这个算法被描述为“每计算单位最精确的”(不确定是否仍然正确)。进一步研究的主要动机是开发用于 MCMC 的小批量梯度方法。作者强调需要一个连贯的理论来描述一些细节,如收敛速度和接受拒绝步骤。显然,SGLD 有望成为动力系统和衍生采样方法(如 HMC)的兼容工具

今天用在哪里?

有很多文章,比如在文章开头提到的那些,人们以不同的方式将噪声项添加到梯度中。

SGLD 经常被讨论的一个话题是 BNN,在那里后验分布是训练目标。因此,为此目的使用小批量的概念是有吸引力的,它是与变分推理一起使用的常用工具。

承认

这篇文章是一个惊人的项目#deep night learners的一部分,该项目由迈克·埃尔里克森和阿夫拉哈姆·拉维夫领导,在以色列进行。****

此外,我还要感谢 Amit Miller 和 Uri Itai,感谢他们进行了大量讨论并提供了相关文件。

自然语言处理中的语言不变性

原文:https://towardsdatascience.com/language-invariant-properties-in-natural-language-processing-561e04b5fa0d?source=collection_archive---------15-----------------------

思想和理论

将消息转换(例如翻译)为另一种语言时,文本属性会保留吗?

当你转换一个文本(例如,翻译,解释,总结)时,你希望你的信息的一般属性在输入和输出之间保持不变。例如,你希望你的信息即使被翻译成另一种语言也能让人感到愉快。

如果不这样做,就会出现问题。例如,一名巴勒斯坦男子被逮捕,因为他在脸书上的帖子被错误地从“早上好!”去“攻击他们”。

这篇博文描述了我们的新论文的主题:

费德里科·比安奇,德博拉·诺扎,德克·霍维(2022)。自然语言处理中的语言不变性。NLP 中高效标杆管理的第一次研讨会记录。

语言不变属性(简称 LIPs)是不应受转换影响的语言属性。作为另一个例子,解释文本应该产生具有相同情感效价的文本:我们不想让一个快乐的信息悲伤的。因此,在开发文本转换算法时,我们需要考虑和控制这个属性。
我们引入了不应受任何转换影响的属性的概念,以及可用于评估该问题的 python 包

语言不变属性

翻译让你听起来更老,更男性化

让我们从我们最近的一篇论文中的一个实际例子开始:“你听起来就像你的父亲”商业机器翻译系统包括文体偏见。 (ACL 2020)。

我们发现,在翻译(例如,从德语到英语)后,大量消息被预测为男性(比我们在原始数据中看到的更多)。我们发现年龄也有类似的影响:信息听起来更老。

翻译不应该改变说话者的人口统计。翻译系统 1 让你听起来更老。图片作者。

语言不变属性

说话者人口统计数据不应该受到翻译的影响。那么现在我们来谈谈我们的新论文:《自然语言中的语言不变性》。

上面的讨论使我们认识到,有必要更好地定义那些改变文本表面形式的转换方法(例如,转述、摘要)不应该影响什么。

我们称那些在转换后不应该改变的属性为语言不变属性( LIPs )(如前所述,这可以是翻译、释义或摘要)。

可能有许多嘴唇,但重要的是意味着说话者人口统计。转变不应该影响信息,如果你 26 岁,你不希望你的信息听起来像是 87 岁的人写的。

更正式的定义

假设存在所有可能说出的句子的集合。让我们将 AB 定义为 S 的子集。出于我们的目的,这两个集合可以使用相同或不同的语言。现在让我们介绍下面的映射函数:

也就是说,我们可以认为 t 是将文本 A 的表面形式转换成 B 的转换(如果转换是翻译,该函数会将一种语言的句子翻译成另一种语言)。

一个语言属性 p 是一个将 S 的元素映射到一组 P 属性值的函数。p 是不变的当且仅当

这意味着对 a 应用函数 t 不会改变属性 p. 的值

评估嘴唇

我们如何评价这一点?嗯,这比你想象的要简单:

让我们再从上面的例子开始。我们从一个数据集开始,用户用英语、荷兰语、意大利语、法语、德语用男女二元性别和年龄自我认同。我们训练了特定语言的年龄和性别分类器,这意味着对于每种语言的每篇文本,我们现在可以预测年龄和性别。

然后,我们可以使用一堆商业机器翻译工具来翻译我们数据集的测试部分(姑且称之为 O )(例如,我们将测试文本从荷兰语翻译成英语)。特别是我们用了谷歌翻译,微软翻译和 DeepL。

现在我们已经翻译了数据,我们对原始的 O 数据和翻译的数据集使用我们的分类器(荷兰语和英语)。因此,我们获得了对原始数据P0和翻译数据 PT 的预测。
研究这两个预测集( POPT )与原始数据集( O )之间的差异,就可以了解年龄和性别在转换后是否被保留。如果 PO 具有类似于 O 的分布,而 PT 没有,我们可能会发现一些偏差。

上述设置可用于评估许多不同的嘴唇。只要有足够的数据来训练特定于语言的分类器,就可以使用内部工具来应用转换并检查分布之间是否有任何显著的差异。

嘴唇框架

我们已经建立了一个框架来测试和验证嘴唇是否会受到变形的影响。可以在 GitHub 上找到。

我们框架的标志。

API,到目前为止,仍然有点不稳定,但是我们正在努力使它变得更加稳定。但是一般的前端 API 应该不会有太大的变化。

我们试图让它尽可能容易使用。只要您有自己的转换方法(例如,翻译模型),您就可以很容易地从您的模型中获得分数(根据 KL 散度和显著性效应)。

测试性别唇所需的代码。图片来自 Carbon,作者制作。

该框架还为您提供了原始的预测分布图。这是我们在一个数据集上运行的一个实验,这个数据集有自我注释的性别值。

o 是原始测试数据,PO 是分类器对原始数据的预测。PT 是分类器对转换数据的预测。我们可以看到,在转换之后,许多消息被识别为来自男性用户,这表明转换在分布中引入了偏差。

尝试一种解释算法。o 是原始测试数据,PO 是分类器对原始数据的预测。PT 是分类器对转换数据的预测。我们可以看到,在转换之后,许多消息被识别为来自男性用户,这表明转换在分布中引入了偏差。图片作者。

限制

LIPs 是一个有趣的理论概念,但是它们可能并不总是推广到任务。例如,从西班牙语翻译到日语必须考虑两个国家的文化差异,这可能无法简化为一套嘴唇。

我们实现的工具有一些限制。我们不能完全消除分类器中习得的偏见。我们总是假设当有两个分类器时,这两个分类器在两种语言上都可靠地运行良好,以比较输出。这同样适用于释义:我们假设 LIP 分类器在原始文本和转换后的文本上表现得一样好。

结论

我们相信 LIPs 有助于更好地理解转化方法的工作原理。在这个领域中,我们已经达到了这样一个点,即这些方法足以可靠地转换一般信息(例如,Google Translate 对于许多用例来说已经足够好了);然而,在转换过程中不保持嘴唇固定会产生误解。

感谢您阅读我们的作品!你可以在论文中找到更多关于这个的信息!如果您有任何问题,请随时联系我们!请随意在推特上联系。

承认

感谢德克和黛博拉对此的编辑和评论!

语言模型是开放的知识图..但对我来说很难!

原文:https://towardsdatascience.com/language-models-are-open-knowledge-graphs-but-are-hard-to-mine-13e128f3d64d?source=collection_archive---------7-----------------------

入门

请和我一起深入研究关于使用基于 transformer 的语言模型创建知识图的最新研究论文

在本文中,我们将探讨关于利用基于 transformer 的语言模型从文本构建知识图的最新研究论文。我们将看到的论文名为“语言模型是开放的知识图”,作者声称,“这篇论文展示了如何在没有人类监督的情况下,从预先训练的语言模型(例如,伯特,GPT-2/3),构建知识图。”

最后一部分,声称已经将人类从这个过程中移除,让我非常兴奋。话虽如此,我已经学会对这种说法持保留态度。我决定通过试验本文中提出的管道的各种组件来进一步探索这种方法。这个想法是为了理解管道中的每一步对特定领域示例的影响,并判断领域专家或数据科学家是否需要任何监督。

注意:我假设你对知识图和基于转换器的语言模型的概念有些熟悉。简而言之,如这里所说的“知识图(KG)表示实体的相互链接的描述的集合——真实世界的对象和事件,或者抽象概念(例如,文档)”。它允许我们将现实世界建模成一个图表,然后可以对其进行推理以断言关于世界的事实。要了解更多关于基于 transformer 的模型,请参考 Jay Alammar 的帖子这里这里。你也可以参考我的帖子“超越与变形金刚的分类和拥抱脸”,在那里我深入研究了这些模型,尤其是注意机制,这是大部分“知识”的储存地。

事不宜迟,我们开始吧!😃

大多数领先的公司已经开始使用知识图(KG)来组织、管理和扩展关于他们业务的知识。虽然大多数企业在用来自各种结构化数据源的实例填充 kg 方面取得了很大进展,但是他们很难用来自文本等非结构化数据源的实例填充 kg。使用基于机器学习(ML)和自然语言处理(NLP)的技术从文本中提取和构建知识已经成为许多领先大学和研究人员关注的领域。让我们从下面的鸟瞰图开始,看看大多数研究人员通常遵循的方法。整个行业的流程非常标准,你可以找到许多出版物和演讲,但是我在这里找到了一个演讲(有点过时,但是非常简单和简洁):演讲

图 1:用于为自动知识图填充生成三元组的典型管道(大部分是从在线谈话中推断出来的,像这样:链接

如上图所示,这个过程从用元数据解析和丰富文本开始,比如 POS 标签、命名实体、依赖解析树等。下一步是识别文本中最有可能作为知识图中的实体的提及(即文本的部分)。这被称为提及检测。这然后通过实体链接器传递,实体链接器从目标 KG 中找到最可能的候选实体,然后通过在上面运行逻辑来消除歧义(这可以是 ML、查找字典、字符串匹配等。),将每个提及映射到目标 KG 中的特定节点。最后一步是根据第一步完成的丰富和使用 ML、一阶逻辑或原始规则技术的实体,提出精心设计的语言特征,以提出最可能的关系。然后,已消除歧义的实体和关系被生成为输出三元组(例如,主语、谓语和宾语),以链接成图。

大多数这些方法的最大难点是它们需要技术专家的时间和精力,这些专家可能是数据科学家、语言学家和知识库开发人员。他们需要与领域专家密切合作,根据丰富的内容提出原始的语言特征,定义特定领域的字典和/或一阶逻辑,根据规模和复杂性,这可能需要几周或几个月的时间,并且由于领域中的大量变化,最终仍可能丢失信息。

利用语言模型构建知识图

最近,研究界已经开始探索如何利用深度学习来构建传统上由人类构建的语言特征。让我们来看一篇这样的论文——语言模型是开放的知识图,作者是、小刘、宋晓。网上有一些资源更详细地解释了这篇文章,但这篇文章也很容易阅读。我将试着从高层次上阅读这篇论文,然后将我们的注意力转向对他们提出的管道进行实验。

本文的主要思想是在从文本数据创建知识图的过程中尽量减少人类的参与。作者假设像 BERT 或 GPT2 这样的基于 transformer 的模型有能力学习和存储关于领域的知识,这些知识可以转换成结构化的知识图。他们继续在 TAC 知识库人口(KBP)数据集和 Wikidata 上测试这一点,并使用所提出的方法在 KG 人口上发表了令人鼓舞的结果。

提出的方法有两步匹配&地图(妈妈)。让我们看看这些是如何修改我们上面讨论的管道的:

图 2:在论文“语言模型是开放的知识图”中提出的高级“MaMa”过程流

这种方法与之前方法不同的地方是使用注意力机制 来推断文本中的候选三元组。预先训练的基于变压器的模型在训练期间学习的注意力权重,为我们提供了对文本中各种术语之间关系的洞察。这些权重应用于标准库中的锚词(名词块),如 spaCy ,提供了可能的候选事实(头、关系、尾),然后可以使用现成的实体链接器如 REL 来消除歧义。

下面是一张直接取自论文的图表。它显示了匹配过程是如何通过运行 beam 搜索来查找具有最高总得分的三元组的。

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

让我们更进一步,基于这里提供的代码(本文没有提供一些更小的细节)创建一个建议管道的粒度版本

图 3:详细的流程图,以较低的粒度显示了管道中的步骤

正如我们从上面的流程中看到的,管道不仅仅是通过 LM 运行句子。虽然 LM 可以帮助我们生成候选事实,但是调整管道的其他部分也同样重要。管道的所有其他部分都试图利用来自库的预训练模型,如 spaCyRELFlair

实验

现在我们知道了论文作者试图实现的目标,让我们开始试验他们的管道,看看我们是否能在几个小样本上实现预期的结果。

我们将选择一个通用领域和医疗保健领域有重叠的例子:

来源:https://www . survivor net . com/articles/did-you-know-Robert-de-Niro-is-15-years-cancer-free-now-hes-主演-爱尔兰人-获 2 项艾美奖提名/

第二个例子是特定于医疗保健的:

来源:https://www . dph . Illinois . gov/topics-services/diseases-and-conditions/diseases-a-z-list/结膜炎

我们将通过使用他们的默认实现来开始实验,然后继续调整管道中的不同步骤,在进行的过程中可视化输出。

论文原码可以在这里找到:原码

我派生了 repo 并做了一些更改,即——使用 dash 运行和可视化输出的包装器,支持运行 scispaCy 命名的实体识别器(NER)和实体链接器,以及运行通过拥抱脸变形金刚库支持的不同语言模型的能力。这是我的分叉回购的链接(当我添加更多东西进行实验时,它仍然在一个分支中,最终将被合并到主目录中)

1.现成的:

  • 使用来自 spaCy 的 en_core_web_md 模型找到锚点术语的名词块
  • 语言模型的 Bert-大格模型
  • REL 图书馆,用于链接到维基数据 2019 知识图的实体
  • 许多人不知道演员劳勃·狄·尼诺的一件事——他因在电影《盗亦有道》和《出租车司机》中扮演许多臭名昭著的硬汉角色而闻名——那就是他是一名 15 年的癌症幸存者。德尼罗在 2003 年 60 岁时被诊断出患有前列腺癌。但多亏了定期的癌症筛查,他的医生及早发现了这种疾病,这位演员得到了迅速的治疗,并能够继续他多产的表演生涯。

图 4:第一句话(与 Robert Di Nero 相关)上运行的原始回购的默认配置

正如你所看到的,它只找到了一个三元组,并能够将其链接到维基百科实体:

:“罗伯特 _ 德尼罗”,关系:“诊断”,:“前列腺癌”,置信度 : 0.16

注意——你可以在实体前加上https://en.wikipedia.org/wiki/来浏览该实体的维基百科页面。例如:https://en.wikipedia.org/wiki/Prostate_cancer

2.除了名词块之外,利用命名实体来识别锚文本(图 3 中的步骤 3)

作者使用 spaCy 中的名词块来识别锚词,然后用于查找三元组。我们看到开箱即用的实现只生成了一个三元组。大多数先前的研究在这个步骤中使用命名实体(参见图 1 中的步骤 1,该步骤讨论了整个方法),所以让我们也使用命名实体识别器(NER)来辅助这个过程。让我们利用空间为我们提供命名实体,除了名词块(我们删除任何重叠部分)。让我们看看同一个句子会生成什么:

图 5:从 en_core_web_md 模型添加命名实体使我们能够使用相同的语言模型(bert-large-cased)来生成更多的三元组

正如我们所看到的,使用命名实体有相当大的影响,因为它能够生成更多的三元组。

注意:你还可以看到,实体链接器(REL)尽最大努力识别各种提及的实体,事实上,我们有比需要更多的提及会导致噪音。比如说我们有“ 【多人】 ”这样一提,就消歧到了【难忘 _(Nat _ King _ Cole _ song)”,**”虽然我们还没有做出明确的努力从空间中过滤出特定的实体类型,但是我们可以基于用例需求来这样做,这应该会删除许多不需要的提及,从而删除关系。这些是用例必须做出的典型的成本收益权衡。

现在,让我们尝试将它用于医疗保健领域的特定示例:

结膜炎是覆盖眼白和眼睑内表面的薄而透明的膜(结膜)的炎症。结膜炎,俗称“红眼病”,最常见的是由病毒引起的,但也可能由细菌感染、过敏(如化妆品、花粉)和化学刺激引起。

默认模型 en_core_web_md 这次并没有产生太多东西,即使在向流程中添加了命名实体之后也是如此

图 6:在医疗保健领域的特定示例中使用默认空间模型的 NER

让我们切换到一个特定领域的预训练 NER,它是由 allenai 在一个医疗保健数据集上训练的,并在这里发布: scispaCy

图 7:从 scispaCy 下载的领域特定模型 en_core_sci_lg 的 NER

正如我们上面看到的,领域特定的 NER 生成更多的三元组。也有一些不正确的三联体被提取出来,为什么会发生这种情况有几个原因-

  1. 用于过滤掉三元组的阈值很低(默认值为 0.005),这将带回更多的关系。我们将在本文中进一步研究阈值的影响。
  2. 三元组的置信度(基于关注度生成)也取决于所使用的 LM 的类型。这个模型主要是在维基百科(不是专门的医疗保健)这样的通用数据集上训练的,因此可能没有看到这些术语足够多的次数。

切换到不同的科学模型来识别命名实体会给我们带来明显不同的结果:

图 8:从 scispaCy 下载的领域特定模型 en_ner_bc5cdr_md 的 NER

观察:很明显,当我们利用一个相关的命名实体模型来选择锚词,而不仅仅是名词块或使用 SpaCy 中的默认 ner 时,同一个语言模型产生了更多的三元组。这表明即插即用并不容易,数据科学家/NLP 专家需要提前选择正确的方法来识别锚文本,这可能需要一些实验或训练。

3.选择一个相关的实体链接器(图 3 中的步骤 8)

让我们通过默认的实体链接器(REL)运行关于结膜炎的领域特定的例子。 REL 可以选择维基百科语料库的年份(我选择了 wiki_2019),然后将提及映射到 2019 年版本的维基百科中的实体。让我们看看输出:

图 9:被训练来匹配维基语料库中的实体的 REL 实体链接器。这是工具的链接—https://github.com/informagi/REL

我们在上图中看到,它在解析实体方面做得不错。这是因为我们选择了一个具有众所周知的概念的例子,这些概念在 wikipedia KG 中有一些参考。让我们从同一个领域中挑选一个复合句-

**Phenylketonuria (PKU) and mild hyperphenylalaninemia (MHP) are allelic disorders caused by mutations in the gene encoding phenylalanine hydroxylase (PAH).**

图 10:通过 bert-large-cased 模型和来自 scispaCy 和 REL 实体链接器的 en_core_sci_lg 模型运行的复杂医疗保健示例

上面的图形是通过将句子传递给 bert-large-cased 模型、scispaCy 中用于命名实体的 en_core_sci_lg 模型和 REL 实体链接器生成的。我们可以看到,实体链接器在一些实体上运行良好,但在另一些实体上却失败了。像“突变 _(漫威 _ 漫画)”或“国家 _ 运动 _ 党”这样的实体显然是不正确的。

下图是使用除 scispaCy 实体链接器之外的相同配置生成的,scis pacy 实体链接器是为了识别医疗保健领域中的概念而构建的。scispaCy 实体链接器还允许我们将概念映射到医学领域的不同知识图。我选择了 UMLs KG 作为目标。我们可以看到,这个实体链接器很好地消除了节点的歧义。这里,再次,调整阈值可以删除一些不正确的三元组,这将在下一节讨论。

图 11:通过 bert-large-cased 模型、en_core_sci_lg 模型和来自 scispaCy 的实体链接器运行的复杂医疗保健示例

****观察:访问相关实体链接器可以通过识别目标 KG 中的正确实体来节省大量时间和精力。它在能够自动提取尽可能多的内容方面发挥了关键作用,从而减少了人类纠正实体和关系的工作量

4.选择合适的阈值来过滤三元组(图 3 中的步骤 7)和相关的语言模型(图 3 中的步骤 2)

最后,让我们研究一下切换语言模型的影响以及用于过滤掉三元组的阈值。这两个方面是相关的,因为选择语言模型将决定过滤过程的平均阈值。

本文提供了一些关于使用伯特类模型与 GPT 风格模型(本质上是自回归模型)之间差异的见解。他们指出,类似 BERT 的模型在识别关系方面更成功,因为它们本质上是双向的,并且在学习预测屏蔽记号时看到两个方向的记号。这在我的实验中是一致的,因此,我决定将重点放在基于 BERT 的模型上进行进一步分析。

让我们从讨论结膜炎的同一个例子开始:

结膜炎是覆盖眼白和眼睑内表面的薄而透明的膜(结膜)的炎症。结膜炎,俗称“红眼病”,最常见的是由病毒引起的,但也可能由细菌感染、过敏(如化妆品、花粉)和化学刺激引起。

我们将使用两种基于变压器的模型进行实验:

来自拥抱脸(链接):" 'bionlp/blue Bert _ PubMed _ mimic _ un cased _ L-24 _ H-1024 _ A-16' "

默认型号:Bert-大型机箱

我们还将尝试阈值的三个值:0.005、0.05 和 0.1

下面的每个图表都是下面描述中详细描述的一种配置的输出。您还可以查看每个图的顶部,以了解使用的其他参数。每个三元组的置信值用图案<relationname_confidencescore>标记在相应的边缘上:</relationname_confidencescore>

图 12(上图):型号:Bert-大箱,阈值** : 0.005(默认)**

图 13(上图):型号:bionlp/bluebert _ PubMed _ mimic _ un cased _ L-24 _ H-1024 _ A-16,阈值** : 0.005(默认)**

图 14(上图):型号:伯特大箱,门限** : 0.05**

图 15(上图):型号:bionlp/bluebert _ PubMed _ mimic _ un cased _ L-24 _ H-1024 _ A-16、阈值** : 0.05**

图十六:(上图):型号:bionlp/bluebert _ PubMed _ mimic _ un cased _ L-24 _ H-1024 _ A-16,阈值** : 0.1**

观察**:当阈值设置为 0.005(作者建议)时,两个模型的图形几乎相同。当我们移动到更高的阈值 0.05 时,差异开始显现。当阈值从 0.005 移动到 0.05 时,域特定模型(bionlp/blue Bert _ PubMed _ mimic _ un cased _ L-24 _ H-1024 _ A-16)在其三元组中显示出更大的总体置信度。最初我曾假设阈值只会移除一些现有的三元组,并保持其余的原样,但这是一个错误的假设。当阈值从 0.005 变为 0.05 时,大多数三胞胎的分数都有所更新,比以前更高。这意味着为每个三元组分配分数的波束搜索,由于候选人数量较少,为每个三元组累加了更多的值。

总的来说,在阈值和三元组数量之间有一个权衡,由 NLP 专家来选择正确的阈值,这确实会显著地改变提取的三元组。

结论

看到语言模型可以用来从文本中提取候选事实是令人鼓舞的,但是正如我们在上面的实验中观察到的,对于数据科学家/NLP 专家来说,让管道的其余部分适应用例同样重要。

获取正确的“知识”在很大程度上取决于更多因素,而不仅仅是插入预先训练好的 LM,例如:

  1. 识别正确的锚定术语(名词块、命名实体等。)
  2. 配置相关的关系类型(本文没有讨论这个方面,但是作者也根据预定义的字典设置了关于什么关系是有效的约束
  3. 能够接触到相关的预先培训的实体联系人
  4. 调整三胞胎的正确阈值

参考

**https://www.ijddr.in/drug-development/diabetes-mechanism-pathophysiology-and-managementa-review.php?aid=6713

[https://www.kaggle.com/tboyle10/medicaltranscriptions](https://www.kaggle.com/tboyle10/medicaltranscriptions)

大涡模拟

原文:https://towardsdatascience.com/large-eddy-simulations-e485dd929682?source=collection_archive---------17-----------------------

LES 背后的理论及其在计算流体动力学中的应用。

你有没有想过模拟物理物体如何与空气和水相互作用?以下是方法。

SpaceX 在 Unsplash 上拍摄的

大涡模拟(LES)是一种尖端技术,用于模拟硬件如何与流体相互作用。它在计算效率和粒度之间取得了平衡,这使得它在航空航天和汽车行业非常受欢迎。然而,它们还不是灵丹妙药。

在本帖中,我们将讨论 LES 的基础知识。如果你想要代码教程,请留下评论。

事不宜迟,我们开始吧。

技术 TLDR

大涡模拟(LES)是在计算上“高效”的模拟,它求解纳维尔-斯托克斯方程。主要的计算优势来自过滤,它将我们的数据分成计算上可行的块。对于每个区块中的信息,我们直接求解方程,对于更小的亚网格尺度(SGS)数据,我们可以开发近似模型。

但是实际上是怎么回事呢?

如果你不是有数学背景的物理学家,那可能已经很多了,所以让我们慢一点。

1 —纳维尔-斯托克斯方程

我们将从一个具体的例子开始:我们希望设计一个能最大化向前推力的船形推进器。

在发展这种推进器的过程中,将有两条主要的前进道路。第一个是利用我们关于船舶螺旋桨物理学的知识,提出理论设计。不幸的是,我们中没有多少人是流体动力学专家,所以这个选择可能会有问题。

相反,让我们讨论第二种选择:大涡模拟(LES)。

LES 可以结合物理和计算模拟来估计水流的特性,然后将其转化为推力的估计值。LES 的核心依赖于支配所有流体动力学的两个纳维尔-斯托克斯方程。

让我们依次讨论每个方程。

1.1 —质量守恒

第一个等式非常直观。它指出,无论我们如何移动我们的流体,流体的质量将保持不变。

图 1:质量守恒方程。作者图片

在图 1 中, u_bar (上面带杠的 u)对应我们流体的速度。速度包括速度和方向,在我们的例子中,我们对推力的所有三维都感兴趣,所以让我们将 u_bar 分解成 x、y 和 z 分量。

图 2:分解了 x、y 和 z 分量的速度。图片作者。

如图 2 所示,我们可以将 u_bar 分解成它的 u,v,w 分量,它们对应于我们速度的 x,y,z 方向。这三个分量中每一个的大小都对应于那个方向的速度。

既然我们理解了速度项,让我们看看纳布拉(∇).∇指出,我们正在寻找速度的梯度。如果你熟悉随机梯度下降,这个梯度是相同的概念——它只是速度对 xyz 的偏导数。

图 3:扩展的质量守恒方程。图片作者。

1.2 —动量守恒

两个等式中的第二个也非常直观。它只是简单地陈述了一个系统中所有的动量都会随着时间而保持。这也恰好是牛顿第二定律。

图 4:动量守恒方程。图片作者。

在图 4 中,等号(绿色)左边的值是动量。只是我们的流体密度ρ (rho)乘以 u_bar 随时间的变化率。值得注意的是,这个术语只是质量 x 加速度的不同表示。

红色的两个值是内力——它们对应于流体粒子固有的相互作用。第一项,压力梯度,是将颗粒从高密度区分散到低密度区的压力。举个例子,想想气味在房间里是如何分散和消散的。第二个术语,粘度,是物质的“厚度”,对应于流体中颗粒之间的摩擦力。

最后,我们有唯一的外力,显示为蓝色。这通常只是用引力常数来代替。

今天有趣的事实是,如果你能证明这些方程的解存在并且是光滑的,你就赢得了一百万美元。

2 —湍流的问题

当寻求解决上述方程时,有一个主要的挑战:湍流。

照片由帕韦尔·切尔文斯基Unsplash 上拍摄

上面艺术地展示的湍流是“以压力和流速的混乱变化为特征的运动”理论上,我们流体中的每个粒子都可能导致湍流,所以除非我们有非常强大的计算机(如原子计算机),否则我们无法解决上述方程。

因此,为了降低计算的复杂性,我们过滤掉数据的某些部分。纳维尔-斯托克斯方程有三种主要的“版本”,具有不同的粒度水平和计算复杂性。他们是…

  1. 直接数值模拟(DNS) :无滤波器——仅适用于小规模理论模拟。
  2. 大涡模拟(LES) :过滤掉小尺度的“漩涡”并为其建模——这是一种非常精确的方法,但在计算上仍然容易处理。
  3. 雷诺平均纳维尔-斯托克斯(RANS) :通过对低于阈值的值进行平均来过滤它们——这是一种精度较低的方法,但比 LES 计算效率更高。

历史上,RANS 一直是最先进的方法,但随着计算能力的增加,LES 在需要精度的应用中的受欢迎程度激增。一个例子是内燃机设计。

3 —大涡流模拟

既然我们理解了为什么计算流体动力学模拟可能非常昂贵,那么让我们看看在实践中我们可以做些什么来降低它的复杂性。

3.1 —低通滤波

LES 中使用的一种简单的显式滤波方法称为低通滤波。正如你所料,我们减少或消除高频信号,让低频信号通过不变。“高”和“低”由阈值δ(delta)确定。

图 5:卷积滤波的简化示例。来源图片由 Pawel Czerwinski 在 Unsplash 上拍摄。

这个过程的一个简单类比是像素化图像,如图 5 所示。我们通过使用卷积核来实现这种“像素化”。类似于 CNN 中的卷积层,我们使用滑动“窗口”移动数据,并在每个位置执行低通滤波操作。还要注意,我们不只是对 2D 数据这样做,我们还可以将这些数据应用到 3 维以及我们的时间组件。

从视觉角度来看,应用于数据中空间成分的过滤器通常由覆盖在数据上的网格来表示。图 6 中的每个网格单元对应于一个卷积核(或一些其他滤波方法)的输出。

图 6: LES 网格示例— src 。图片作者。

正如上面所暗示的,还有很多其他的过滤方法。一些明确地确定应该被允许通过的信号的大小,而另一些利用复杂的数学来动态地减少小湍流过程的数量。还有亚网格尺度(SGS)模型,试图以计算高效的方式封装湍流的相关信息。

3.2——求解纳维尔-斯托克斯方程

现在我们有了一个计算上易处理的数据集,我们可以应用基于微积分的求解器,从而进行模拟。数学和代码可能会变得非常复杂,所以如果你想了解更多,这里有一些资源:

  • 斯坦福高保真 LES :航天计算实验室设计的研究型 LES
  • dedaLES:LES 最流行的 python 库
  • ARXIV.org:了解 LES 研究的一个好的(免费的)方法

这就是你要的——最荣耀的事!

摘要

为了强调一些概念,让我们重申一下我们上面讨论的内容,然后将我们的新知识与一些很酷的应用联系起来。

大涡模拟(LES)是一种计算量大但易于处理的流体动力学模拟。他们的成名在于他们使用过滤器来消除小尺度湍流,这导致了大量的计算复杂性。从那里,它利用高效和理想的并行求解器来确定纳维尔-斯托克斯方程的解。

LES 在硬件建模领域已经变得非常流行。一些应用包括内燃机航空航天工程风力涡轮机设计,以及海洋能源。通过利用计算机,我们可以在构建物理原型之前,从理论上测试数千种可能的设计。

感谢阅读!我会再写 28 篇文章,把学术研究带到 DS 行业。查看我的评论,链接到这篇文章的主要来源和一些有用的资源。

新冠肺炎之前关于疫苗在线对话的大规模分析

原文:https://towardsdatascience.com/large-scale-analysis-of-on-line-conversation-about-vaccines-before-covid-19-ecebde4180ef?source=collection_archive---------31-----------------------

在前疫情时代,推特和新闻来源发挥了作用

你还记得过去反对疫苗接种的争论吗?有没有影响到今天的态度?数据可以暴露一切

Mehmet Turgut Kirkgoz 在 Unsplash 上拍摄的照片

关于疫苗的作用和需求的讨论从未如此激烈。新冠肺炎疫情戏剧性地改变了这个问题在外行人日常生活中的可见度。

然而,疫苗接种近年来一直是一个有争议的话题。多年来,反疫苗接种运动的增长已被记录在案。虽然疫苗反对者的大本营仍然在与新冠肺炎疫苗作斗争,但不要忘记和忽视导致当前疫苗辩论的历史是极其重要的。

这激发了我们对新冠肺炎袭击前社交媒体上关于疫苗接种的辩论和讨论的以数据为中心的研究。在这项研究中,我们绘制了新冠肺炎事件前四年推特上关于疫苗接种的英语对话。我们的目的是:

  • 发现对话的数量和趋势;
  • 将 Twitter 上的讨论与报纸上的内容进行比较;
  • 将人们分为支持或反对疫苗接种,并探究他们的行为有何不同。

推特数据集

在新冠肺炎疫情出现之前,我们收集了 4 年关于疫苗接种的推特数据,使用了三个关键词:“疫苗”、“疫苗接种”和“免疫”,获得了大约 6.5 条 MLN 推特。

新闻来源

我们分析了推文中引用最多的新闻来源,不仅包括“官方”报纸或新闻机构,还包括在线媒体和博客,如 YouTube、NaturalNews(通常被认为是有偏见的假新闻网站)和脸书。

总体而言,在被引用最多的来源中,32%可以被标记为可靠,25%可以被标记为阴谋/假新闻来源。另外一个有趣的点是,在 Twitter 上分享的所有链接中,有 32%的引用指向了其他社交网络(包括 YouTube)。这项分析显示了社交媒体和不可靠的信息来源如何频繁地推动 Twitter 上与疫苗相关的对话。

基本分析

我们的分析显示,与该主题相关的推文数量逐年增加,在 2019 年达到峰值。除其他外,我们确定 2019 年麻疹爆发是增长的主要原因之一。这一点突出体现在推文量与美国疾病预防控制中心 2019 年麻疹病例数据的高度相关性以及关于该主题的大量报纸文章,这两者在 2019 年都有显著增加。还进行了其他人口统计、时空和内容分析。

科目

除了一般的数据分析,我们还考虑了疫苗对话中经常涉及的一些特定主题,如流感、hpv、脊髓灰质炎等。我们确定了时间趋势,并进行了与这些主题相关的具体分析,同时也结合了各自的媒体报道。

讨论和 NYT 新闻涉及特定疾病的疫苗接种,如流感和麻疹。[作者图片(*)]

用户立场。

多年来疫苗接种立场的演变。[作者图片(*)]

我们对推文的作者进行了立场分析,以确定用户对疫苗接种的取向,即他们是支持还是反对疫苗。初步分析显示大量内容具有讽刺或嘲笑的性质,导致许多分类技术在数据集上表现不佳。

鉴于其他研究认为立场指示标签的存在是发现极化推文和用户的有效方法,因此应用了基于规则的分类,基于 100+标签的选择。这允许自动将推文分类为支持疫苗接种或怀疑疫苗接种,在 4 年中获得了总共 250,000+分类推文。

措辞和引用

这两组用户在讨论疫苗相关话题时使用的词汇有着深刻的不同,他们参考的信息来源也是如此。
反疫苗用户引用的大多是假新闻网站和极少数可靠的消息来源,而这些消息来源大多被支持疫苗的用户引用。在这两种情况下,社交媒体(主要是 Youtube)代表了链接内容的很大一部分。反疫苗使用者使用的词语强调了对抗大型制药公司的趋势,对效果的不信任,受伤和自闭症的风险(以及阴谋论和告密者)。

支持疫苗接种(左)和反对疫苗接种(右)群体最常使用的词和共现词。[作者图片(*)]

地理和人口统计

此外,我们对两类用户(支持和反对疫苗)进行了人口统计(年龄、性别、种族)和空间分析,目的是了解这两个群体的特征。我们的分析还显示了美国各州在 Twitter 上支持或反对疫苗接种的程度。结果如图所示。

推特上美国各州支持和反对疫苗接种的两极分化。[作者图片(*)]

视频中描述了更多细节和结果:

总结视频报告研究的主要结果。[作者视频(*)]

现在的问题是:由于新冠肺炎及其全球影响,这种情况如何改变?请继续关注进一步的分析。

这项工作是米兰理工大学的马可·布拉姆贝拉和玛格丽塔·里科蒂在数据科学实验室开展的活动的一部分。它已于 2020 年 7 月 17 日至 20 日在美国马萨诸塞州剑桥市麻省理工学院举行的 IC2S2 2020 会议上发表(由于新冠肺炎的限制,在网上发布),它是触发器和潜望镜欧盟 H2020 研究项目的一部分。

您可以参考并引用以下作品:

玛格丽塔·里科蒂,马可·布拉姆贝拉。关于疫苗相关现象的在线对话的大规模分析。IC2S2 2020。

带 Kubernetes 算子的大规模分布式随机森林

原文:https://towardsdatascience.com/large-scale-distributed-randomforest-with-kubernetes-operator-797c68c065c?source=collection_archive---------44-----------------------

使用简单的 YAML 文件在 Kubernetes 集群中进行分布式培训

几天前,我正在用一个巨大的数据集探索 RandomForest 模型。令我失望的是,训练数据无法放入单个工作节点的内存中。我必须手动拆分训练数据来训练几个 RandomForest 模型,然后再将这些模型合并成一个模型。

这促使我产生了一个想法:我能否提出一个框架来自动化和分布对具有巨大数据集的可集成模型的训练?我可以准备并提交一个简单的配置文件,框架将编排、监控并分发培训并自动产生模型工件

经过几天的研究和实现,我提出了这样一个框架的第一个版本,这是一个 Kubernetes 操作符。我使用了 GCP 的 operator-SDK(0 . 19 . 4)和 Kubernetes 集群(1.16.15)。操作员满足了分布式培训自动化的基本要求,尽管仍有很大的改进空间。github 库在这里是。

在下面几节中,我将解释 Kubernetes 操作符是什么,然后解释分布式训练操作符是什么。最后,我还将向您展示如何在您自己的集群中设置操作符。

1.什么是 Kubernetes 运算符

简而言之,Kubernetes 操作员是一个特定于应用程序的控制器,它扩展了 Kubernetes API 的功能,以代表 Kubernetes 用户创建、配置和管理复杂应用程序的实例。

您可能熟悉 Kubernetes 的基本概念,如 Pod、部署、服务等。这些是内置的 Kubernetes API 资源。然而,在 Kubernetes 的早期,自动化和管理复杂的有状态应用程序已经变得困难重重。

从 1.7 版本开始,Kubernetes 引入了一个 API 插件机制:自定义资源定义或 CRD。CRD 允许用户指定他们自己的 API 资源(客户资源)。Kubernetes 操作员利用定制的 Kubernetes 控制器和定制资源** (CR)来管理应用程序及其组件。**

在我的例子中,定制资源被称为 DistributedTraining ,它由 1 个带有 1 个 Pod 的主部署&服务和 1 个带有用户指定数量的 Pod 的工作部署组成。操作员自动协调、监控和管理所有组件以及它们之间的工作关系。

2.分布式训练算子

下面是整个过程的工作流程。用户需要做的只是指定并提交配置文件。操作员将负责剩下的步骤。

YAML 配置文件

apiVersion: ahhuisg.com/v1
kind: DistributedTraining
metadata:
  name: dt-test1
spec:
  name: dt-test1
  baseGcsBucket: distributed-randomforest

  model:
    module: sklearn.ensemble
    class: RandomForestClassifier
    parameters: "n_estimators=500, max_leaf_nodes=16, random_state=666, n_jobs=-1"
    merger:
      module: merge_list_rfs
      function: combine_rfs

  image:
    master:
      repository: ahhuisg/dt-master
      tag: 0.0.2
    worker:
      number: 3
      repository: ahhuisg/dt-worker
      tag: 0.0.2
  • ****先决条件:模型必须是可组合的(装袋、助推或堆叠)。在我的例子中,一个随机森林模型可以由多个随机森林模型组合而成
  • baseGcsBucket :来自 Google 云存储的桶名,里面包含了训练数据集,最终的合并模型以及合并模型的 python 脚本
  • ****model . module&model . class&model . parameters:模型模块、类和实例化参数
  • ****model . merge:这包含了如何合并来自工人的模型的 python 脚本。您可以指定您想要如何集合模型。在下面的示例中,python 脚本名为 merge _ list _ rfs . py(model . merger . module ),集成函数名为 combine _ rfs(model . merger . function)
merge_list_rfs.py:def combine_rfs(rfs):
    rf_a = rfs[0]
    for rf in rfs[1:]:
        rf_a.estimators_ += rf.estimators_
        rf_a.n_estimators = len(rf_a.estimators_)
    return rf_a
  • image.master :包含主 pod 的容器图像。操作员中只有一个主 pod。
  • image.worker :包含 worker pods 的容器图像。操作员中可能有 N 个工人舱

正如您所看到的,YAML 配置文件相当简单。在 GCS 存储桶中准备好培训数据后,您只需根据 Kubernetes 的容量和您的要求指定与模型相关的值、存储桶名称以及工人数量。然后您可以将文件提交到集群(ku bectl apply-f)并等待模型工件可用。****

3。在您的集群中设置操作员

克隆我的 Github 库

git clone [https://github.com/ahhuisg/distributed-training](https://github.com/ahhuisg/distributed-training)

设置 ServiceAccount、Role 和 RoleBinding(仅完成一次)

kubectl create -f deploy/service_account.yaml
kubectl create -f deploy/role.yaml
kubectl create -f deploy/role_binding.yaml

设置操作员和自定义资源定义(仅完成一次)

kubectl create -f deploy/operator.yaml
kubectl apply -f deploy/crds/dt_crd.yaml

创建并运行您的分布式培训

  • 在 GCS 存储桶准备您的数据(如 baseGcsBucket 中所指定的)。当前在 bucket 中必须有一个数据子目录。在数据目录中,训练数据的每个分区应该是 pickle 文件格式,命名为 training_ < n >。pkl/label_ < n >。pkl
  • 分区的数量应该与配置文件中的 image.worker.number 的数量相同
  • 修改 yaml 文件 deploy/crds/dt_cr.yaml 。您可以在配置文件的模型部分指定与模型相关的属性。比如要用 XGBoost 进行分布式训练,可以设置模型模块、类、参数。您还应该通过更改合并部分来定义您想要如何合并子模型
kubectl apply -f deploy/crds/dt_cr.yaml

4.我的示例演示

GCS 桶

GCS 存储桶中的数据目录

创建服务帐户、角色和角色绑定

创建 CRD 和操作员

应用自定义资源并触发培训

运行成功,组合模型保存到 GCS

确认

使用 40,000 个数据点的模拟数据集,我验证了来自 3 个来源的模型:

  • 单一随机森林模型(精确度:0.909)
  • 局部组合随机森林模型(精度:0.908)
  • 运营商的组合随机森林模型(精度:0.908)

请参考本笔记本以作进一步参考

需要改进的地方

  • 根据员工人数自动拆分和保存培训数据,而不是目前手动拆分和保存数据到 GCS 存储桶
  • 允许每个工人训练实例具有其自己的模型参数,以利用集成学习中更多的多样性和随机性

5.结论

在本文中,我介绍了我为 ML 模型的分布式训练开发的 Kubernetes 操作符。Kubernetes 是一个非常流行和强大的平台,用于自动编排和管理分布式工作负载。Kubernetes 中工作负载的声明性质,加上它在应用程序中定义和管理复杂关系的卓越能力,使 Kubernetes 成为处理复杂 ML 工作负载的最合适的工具之一。如果您有类似的用例,我希望这个小工具能让您的生活变得更轻松!

矩阵中最大的矩形

原文:https://towardsdatascience.com/largest-rectangle-in-a-matrix-33dd93bd2c45?source=collection_archive---------20-----------------------

如何结合编程技术

随着我在编码和生活中积累了更多的经验,在我的观察中有一件事让我印象深刻,那就是,每当有一个问题需要解决时,通常都会有一个非常直观的解决方案。有时这种解决方案碰巧是有效的,有时是次优的。这在算法中尤其明显,因为算法通常是现实生活问题的概念化,通过算法,问题的基本要素被保留,允许我们直接处理问题。

在我看来,矩阵中最大的矩形就是这样一个问题。以下是对该问题的简要描述。

问题

我有一个由红蓝点组成的棋盘,想找出由蓝点组成的最大矩形:

(图片由作者提供)

在这个例子中,很容易看出由蓝点形成的最大矩形的大小为 8。

但是让我们从算法上想出一个办法。

解决方案#1

如何简单地做到这一点

我第一次尝试解决这个问题时,我心想:

嗯,看起来我可能需要遍历矩阵中的每个点,在每个点上,我需要找到包含该点的最大矩形。我将把那个矩形与我已经找到的矩形的大小进行比较。如果新的更大,我就保留它,否则我继续下一个点。

这听起来很棒,但是有一个问题。如何找到包含特定点的最大矩形?我想不出任何能帮我解决这个问题的方法。

如果我只想找到以当前点为左上角的最大矩形呢?我认为这是一个更容易处理的问题。

为了让我搞清楚,我将遍历当前点右侧的每个点,在每个点我找到蓝点的最大高度,如果它小于当前点的高度,我将当前点的高度更新为新的高度,并找到新矩形的大小,如果它是一个更大的矩形,我将更新最大大小。

让我们将这个过程应用到我们的例子中。

假设我循环到点(1,0):

(图片由作者提供)

我找到了我当前点的高度,是 2,给定这个信息,右上角为(1,0)的最大矩形也是 2。

(1,0): height = 2,max_rectangle = 2。

我迭代右边的每一点:

点(2,0)的高度是 3,但是它比起点大,所以高度仍然是 2。但是现在我们知道我们可以有一个 2 * 2 = 4 的矩形:

(2,0): height = 2,max_rectangle = 4

点(3,0)的高度为 1,它小于当前高度,因此我们将当前高度更新为 1,可以创建的矩形为:1 * 3 = 3,但当前最大值为 4,因此我们忽略它:

(3,0): height = 1,max_rectangle = 4

对其余的点进行相同的过程:

(4,0): height = 1,max_rectangle = 4

(5,0): height = 1,max_rectangle = 5

我们发现右上角为(1,0)的最大矩形的大小为 5。

让我们把它写成代码:

def find_max001(matrix):

    width = len(matrix[0])
    height = len(matrix)

    # max width and max height at the a point
    # uses memorization and dynamic programming
    max_matrix = [[None for v in row] for row in matrix]
    def get_max(i, j):
        if i >= width:
            return 0, 0
        elif j >= height:
            return 0, 0
        elif max_matrix[j][i] is not None:
            return max_matrix[j][i]
        elif matrix[j][i] == 0:
            max_matrix[j][i] = (0, 0)
            return max_matrix[j][i]

        max_down = get_max(i, j + 1)
        max_right = get_max(i + 1, j)

        max_matrix[j][i] = (max_right[0] + 1,
                            max_down[1] + 1)
        return max_matrix[j][i]

    max_rect = 0
    for i in range(width):
        for j in range(height):
            rect = get_max(i, j)
            cur_max = rect[1]
            for k in range(1, rect[0]):
                cur_max = min(cur_max, get_max(i+k, j)[1])

            max_rect = max(max_rect, cur_max * rect[0])

    return max_rect def problem003(solver):

    m001 = [
        [1, 1, 1, 1, 1, 1],
        [0, 1, 1, 0, 1, 1],
        [0, 0, 1, 0, 1, 1],
        [0, 0, 0, 0, 1, 1],
        [0, 0, 0, 0, 0, 0]
    ]

    res1 = solver(m001)
    print(f'res1: {res1}') def test003():
    solver = find_max001
    problem003(solver) test003()
# res1: 8

解决方案#1 的性能

算法的复杂度是多少?

由于我们循环遍历每个点,复杂性至少是 w * h。幸运的是,我们能够使用记忆和动态编程技术来找到每个点的高度,因此它们不会增加复杂性。

在每一点上,我们都循环遍历矩阵的宽度,以找到该点上最大的矩形,这将复杂度降低到 whw。

所以复杂度是:O(w *h)

因为我们还使用地图来存储每个点的宽度和高度:

内存使用量为:O(w*h)。

解决方案 2

如何改进算法?

有没有办法降低复杂度中的 w 项?

事实证明,是有的。

让我们回到我们的例子:

(图片由作者提供)

假设现在我们正在循环第一行。

从(0,0),(1,0),(2,0)高度不断增加 1,2,3。我们保留了一个列表:

[(0, 0: 1), (1, 0: 2), (2, 0: 3)]

在位置(3,0),高度下降到 1。这个新信息告诉我们什么?

实际上,相当多。给定该信息,我们可以肯定地说,左上角在位置(2,0)且高度为 3 的矩形的最大尺寸只能是 3。

我们也可以肯定地说,一个左上角在位置(1,0)且高度为 2 的矩形的最大尺寸只能是 4。

处理完这两个点后,我们可以永久删除它们,但是我们需要添加一个新点,在(1,0)(注意,不是在(3,0)),高度为 1:

[(0, 0: 1), (1, 0: 1)]

本质上,我们所做的是修剪(2,0)和(1,0)的高度,使其等于(3,0)的高度。

以这种方式移动到这一行的末尾,我们不会遇到更多的高度下降。

[(0, 0: 1), (1, 0: 1), (5, 0: 4), (4, 0: 4)]

然后,我们可以处理其余的行:

(5,0) max_rectangle = 4

(4,0) max_rectangle = 4 * 2 = 8

(1,0) max_rectangle = 1 * 5= 5

(0,0) max_rectangle = 1 * 6 = 6

所以处理第一行后的 max_rectangle 是 8,我们只循环了 6 个点!这意味着算法的复杂度现在是 w*h!

下面是代码中的算法:

from collections import deque

def find_max002(matrix):

    width = len(matrix[0])
    height = len(matrix)

    # max depths
    max_matrix = [[None for v in row] for row in matrix]

    def get_max(i, j):
        if i >= width:
            return 0, 0
        elif j >= height:
            return 0, 0
        elif max_matrix[j][i] is not None:
            return max_matrix[j][i]
        elif matrix[j][i] == 0:
            max_matrix[j][i] = (0, 0)
            return max_matrix[j][i]

        max_down = get_max(i, j + 1)
        max_right = get_max(i + 1, j)

        max_matrix[j][i] = (max_right[0] + 1, max_down[1] + 1)
        return max_matrix[j][i]

    def get_rect(stack, j):
        cur_idx = stack.pop()
        cur_max = cur_idx[1] * (j - cur_idx[0])
        print(f"cur_max at {cur_idx[0]}: {cur_max}")
        return cur_max

    max_rect = 0
    for i in range(width):

        # implement the algorithm with stack
        stack = deque()
        stack.append((-1, 0))
        for j in range(height):
            rect = get_max(i, j)
            cur_width = rect[0]
            cur_idx = j
            while stack[-1][1] > cur_width:
                cur_idx = stack[-1][0]
                max_rect = max(max_rect,
                               get_rect(stack, j))
            stack.append((cur_idx, cur_width))

        while len(stack) > 1:
            max_rect = max(max_rect, get_rect(stack, height))

    return max_rectdef test004():

    solver = find_max002

    problem003(solver) test004()
# res1: 8

注意,为了在到达(3,0)后实现点(2,0)和(1,0)的移除,我们使用堆栈数据结构来有效地推送和弹出点。

解决方案 2 的复杂性

如前所述,我们对解决方案 1 进行了改进,因此在每一点上,我们都不必再遍历其右侧的其余点。复杂度提高到:O(w*h)!

内存使用保持不变:O(w*h)。

能从中得到什么?

除了算法和编码技术

一个算法可以有很多变化,你想出的第一个通常不是最有效的。理解复杂性分析和编程技术会有很大的不同。这种认识的重要性不仅延伸到编程,而且延伸到生活中的几乎所有事情,因为生活中的所有事情都是算法。

LASSO 增加了线性模型的可解释性和准确性

原文:https://towardsdatascience.com/lasso-increases-the-interpretability-and-accuracy-of-linear-models-c1b340561c10?source=collection_archive---------15-----------------------

了解套索的工作原理和原因

爱德华·克鲁格艾琳·欧菲莱因迈克尔·斯特兰克

Joshua Sukoff 在 Unsplash 上拍摄的照片

为什么是套索?

LASSO 或 L1 正则化是一种可用于改进许多模型的技术,包括广义线性模型(GLMs)和神经网络。LASSO 代表“最小绝对收缩和选择操作符”然而,你可能想知道是短语还是缩写先出现的。

套索执行子集选择

在线性回归、泊松回归和逻辑回归等(GLMs)情况下,LASSO 可以选择要素子集。子集选择通常通过消除特征和预测度量以及适用模型的泛化来增强 GLMs 的可解释性。GLMs 中的 LASSO 功能强大,因为它可以内生地选择子集-无需构建大量不同的模型并与要素子集进行比较。

套索提高了可解释性

LASSO 相对于许多其他子集选择方法的另一个优势是,它倾向于具有较少共线性的要素子集。由于预测指标通常不会受到共线性的影响,依赖于预测指标的子集选择技术通常无法排除高度相关的变量。

然而,对于解释和因果推断,共线性可能是毁灭性的。

例如,考虑在此处找到的sci kit-Learn 糖尿病数据集。目标是衡量糖尿病的进展。标记为“s1”到“s6”的六个特征是每个受试者在不同时间进行的血清测量的记录。

即使只有一些读数是因果上重要的,线性回归和其他 GLMs 也会给每个特征一些权重。为什么?

因为非因果读数与因果读数相关,而因果读数与目标相关,非因果无关读数与目标相关

后果不仅是非因果特征会影响模型中的目标,而且模型会对因果特征产生错误的影响!直观上,通过添加与另一个特征相关的特征,估计过程将在两个特征之间分割原始特征的因果权重。

当要素之间存在共线性时,LASSO 倾向于将这些要素系数中的一部分降低为零。

如果您有兴趣查看共线性如何影响推理的模拟,或者如何使用 SciKit-Learn 将 LASSO 应用于糖尿病数据集,订阅我的邮件列表以获取即将发布的文章。

正则化提高了准确性和泛化能力

更少的特征可以导致具有更好预测指标的更精确的模型,这可能是反直觉的。尽管如此,在训练中,尤其是在小型或中型数据集上,该模型将识别无意义特征和目标之间的弱关联。在极端情况下,当对模型评分时,一些观察值将具有无意义特征的相对高或低的值,从而导致极端的预测。

泛化是指模型在训练集和测试集的观察值上的表现。很难量化一个模型概括得有多好。尽管在实践中很少见,但在理想的情况下,如果测试数据来自相同的数据生成过程,测试度量可以评估泛化性能。在任何情况下,稀疏模型都更简单,并且不容易出现不可量化的风险,即留下弱预测特征。

在神经网络中,l1 正则化不会在模型级别执行子集选择。然而,在神经元层面,它会选择哪些特征是重要的。这种正则化产生了一个更稀疏的神经网络,该网络在测试度量上更有性能,并且泛化得更好。

让我们回顾一下!

在我们深入了解 LASSO 的工作原理和原因之前,让我们回顾一下。通过排除倾向于相关的特征,LASSO 构建了更稀疏、更易解释且通常更具性能的 GLMs。一些其他模型也可以受益于预测准确性的提高。

套索是如何工作的

了解了它的应用,我们可以看看套索是如何在数学上工作的。LASSO 算法是许多正则化技术中的一种,它通常对问题的损失函数应用惩罚项。我们将使用线性回归来演示这项技术。

线性回归如何工作

在我们将 l1 惩罚应用于线性回归之前,让我们快速回顾一下线性回归是如何工作的。

回想一下,线性回归根据以下形式进行预测。

线性形式(来源:作者)

为了训练模型,我们需要估计系数。为了估计系数,我们通过选择系数值来最小化以下等式给出的平方和。

平方和(来源:作者)

代入线性形式,我们得到下面的损失函数。

线性回归的损失函数(来源:作者)

使用线性代数符号编写表达式会产生一个看起来更简洁但等效的函数。

线性回归的损失函数(来源:作者)

请注意,除了系数之外,这个方程中的所有内容我们都知道。我们可以使用几种最小化技术来找到这个问题中系数的最佳值,包括:

  • 解析求解一阶条件
  • 使用 QR 分解
  • 使用诸如梯度下降的数值方法

在我们总结线性回归之前,让我们从几何角度来看这个问题。我们想通过一组点找到最佳平面。直觉上,最好的平面是最接近这些点的平面。在下图中,我们有两个维度用于特征,一个维度用于创建 3d 空间的目标。线性形式是三维平面,因此线性回归会给我们一个最佳拟合平面。黑线表示每个点和平面之间的距离。

线性回归几何学(来源:作者)

一个合理的目标是找到使黑线的绝对值之和最小的平面,但相反,线性回归使它们的平方和最小。有几个数学和计算上的原因让我们更喜欢用平方和作为损失函数。紫色平面代表最佳拟合平面。

添加惩罚

要使用 LASSO 回归,我们只需在损失函数中添加以下惩罚项。

L1 刑罚(来源:作者)

该表达式由系数的 L1 范数和惩罚系数(也称为正则化强度)的乘积组成。惩罚参数是一个固定的外生超参数。这些项的乘积被称为 L1 罚项,然后应用于损失函数或线性回归,以生成 LASSO 的损失函数,如下所示。

拉索的损失函数(来源:作者)

这个最小化问题没有封闭形式的解。因此,我们必须使用数值方法,如梯度下降法,来求解最佳系数。

这就是套索回归的全部内容,但是如果不深入研究最小化问题,很难对它的工作原理有任何直觉。

套索为什么有效

作为约束优化问题的套索

为了理解套索为什么有效,让我们从另一个角度去发现损失函数。

假设我们有以下问题,我们必须最小化最小二乘,但在系数的选择上受到限制。特别是,系数的绝对值之和必须小于罚参数。

拉索作为一个约束优化问题(来源:作者)

事实证明,这个约束优化问题可以通过将其重写为无约束优化问题来解决,从而得到我们针对 LASSO 的损失函数。

如果你对将约束问题转化为损失函数背后的数学和直觉感到好奇,请查看安德鲁·张伯伦博士的精彩文章!

https://medium.com/@andrew.chamberlain/a-simple-explanation-of-why-lagrange-multipliers-works-253e2cdcbf74

可视化约束区域

既然这两个公式是等价的,那就让我们从几何上更仔细地看一下约束问题。

但是,首先,让我们快速绕道。另一种正则化罚函数叫做 L2 罚函数,它的应用方式与 L1 罚函数完全相同。在线性回归中加入 L2 惩罚的模型称为岭回归。

岭回归惩罚(来源:作者)

相关的约束如下。

脊约束区域(来源:作者)

这可能看起来不熟悉,但让我们看看二维空间,设置惩罚参数为 1,平方两边,看看等式边界。我们得到下面的等式。

单位圆(来源:作者)

不认的话就是单位圆!看看二维的套索约束,我们得到类似的东西。

单位钻石(来源:作者)

这就是单位钻石。让我们想象一下这些约束区域。

约束区域(来源:作者)

事实证明,这种菱形约束负责产生稀疏模型。

可视化约束优化问题

让我们通过在下图中可视化整个约束优化问题来理解约束区域的形状如何产生稀疏模型。

约束最优化问题(来源:作者)

我们看到不同损失函数的套索和脊约束区域和轮廓集(没有惩罚项)。

  • 一组环表示每个轮廓集。类似于地形图,每个连续的向外环表示更高的损失函数值。
  • 在每个轮廓集中心找到的每个点代表无约束问题的解。相比之下,轴相交处的菱形和圆形区域代表约束区域。
  • 橙色菱形对应于套索的约束区域,由所有服从 L1 罚约束的有效候选解组成。相比之下,红色圆圈对应于脊约束区域,由遵守 L2 约束的所有有效候选解组成。

请注意,左上角的轮廓集(带有绿色的内部轮廓)在形状上更像椭圆形,而不是圆形。当等值线集具有相关的要素时,会产生此形状。轮廓组的椭圆形状和约束区域的菱形形状使得轮廓组的最佳点与约束区域的角点重合的机会很高。此时,一些特征可能会被消除,因为一个轴坐标上的值为 0。这就是 LASSO 生成稀疏解的原因。

选择正则化强度

现在我们理解了为什么 LASSO 产生稀疏解,我们可以检查正则化强度如何产生更多的稀疏解。这由分配给惩罚参数的值控制,该值决定正则化强度。下图显示了系数收缩的路径,即系数向 0 收缩时的路径。

正则化强度对系数的影响(来源:作者)

此图展示了 LASSO 与岭回归的不同之处,LASSO 在应用更多惩罚时会将一些系数设置为零。对于 Ridge,这种现象只在罚值非常大的情况下出现,罚值会将所有系数收缩到零。

查看套索模型系数的正则化路径可能会很有趣,尤其是当它们将下一个系数设置为 0 时。路径给出了一系列越来越稀疏的模型。在选择一个时,如果我们主要关心预测,我们可以应用我们的主题专业知识或使用交叉验证。

结论

这是对 LASSO 回归方法的介绍,我们已经展示了它可以执行正则化和内生变量选择。请继续关注我们的下一篇文章,它将演示如何用 Python 实现 LASSO!

要了解更多关于数据科学、机器学习和开发的内容,请查看 Edward 的 YouTube 频道,并订阅我下面的邮件列表,成为第一个听到新文章的人!

https://edkruegerdata.com/subscribe [## 每当爱德华·克鲁格发表文章时,就收到一封电子邮件。

edkruegerdata.com](https://edkruegerdata.com/subscribe)

从零开始的层电导

原文:https://towardsdatascience.com/layer-conductance-from-scratch-df53005e08b8?source=collection_archive---------26-----------------------

理解神经网络中隐藏单元的重要性

这是关于深度神经网络中使用集成梯度和相关技术的可解释性的文章的第二部分。

介绍

上一篇文章中,我们已经看到了如何使用综合梯度计算特征属性,它显示为从基线到特征值的线性路径上梯度的简单平均值。但是,如果我们想测量特定层中神经元的重要性,而不是测量某个特征的重要性,会怎么样呢?为此,我们需要看看层的电导。

解释电导

电导是基于积分梯度的,我们在本系列的第一部分已经讨论过。提醒一下,我们将积分梯度定义为:

Ref:深度网络的公理化归属(【https://arxiv.org/abs/1703.01365】T2

为了计算层的电导,我们需要通过链规则分解积分梯度,如下所示:

Ref:神经元有多重要?(【https://arxiv.org/abs/1805.12233】T4)

我们也可以将其近似为:

作者图片

履行

注意:我们将使用本系列第一部分中的相同模型和数据。

为了计算层电导,我们采用与综合梯度相同的策略——因为模型是饱和的,为了看到有意义的梯度,我们需要从基线到输入捕捉它们。下面我们计算模型中 sigmoid1 层的电导:

为了计算导数 dydx_i 我们需要使用一个向后的钩子(我个人发现这个教程有助于理解 py torchhttps://www.youtube.com/watch?v=syLFCVYua6Q中的钩子)覆盖向后的梯度直到层 y 然后从那里继续向后传播。

我们可以手动计算 dydx_i 进行反向传播,而不是使用亲笔签名的:

偏导数 dfdy_i 不需要钩子——我们简单地计算输出相对于 sigmoid 层的导数。

结论

希望你发现这个系列有助于通过代码更好地理解集成梯度和层电导是如何实现的。使用原始公式计算电导非常慢,并且在 tensorflow 中首次实现时没有很好地缩放,因此提出了另一个计算效率更高的公式,您可以在这里熟悉。

参考

[1]https://arxiv.org/pdf/1805.12233.pdf

[2]https://captum.ai/tutorials/Titanic_Basic_Interpret

懒惰预测:拟合和评估 scikit 中的所有模型——用一行代码学习

原文:https://towardsdatascience.com/lazy-predict-fit-and-evaluate-all-the-models-from-scikit-learn-with-a-single-line-of-code-7fe510c7281?source=collection_archive---------7-----------------------

约书亚·阿拉贡在 Unsplash 上的照片

查看哪些模型最适合您的数据集的最简单方法!

当开始处理监督学习问题时,我们通常不确定哪些模型将与手头的数据集一起工作。一个可能的解决方案是从一个对许多数据集(如 Random Forest)相当有效的模型开始,然后进行迭代。这样,我们就可以建立一个旨在提高的基准。

“早起的人不会取得进步。它是由懒惰的人试图找到更简单的方法来做某事而制造的。”罗伯特·海因莱茵

最有可能的是,在某个时间点,你也考虑过将所有的模型扔向数据集,看看会发生什么。然而,这并不是那么简单的编码(或者更确切地说,它是相当乏味的),所以很可能你放弃了这个想法,只是尝试了一些你过去曾经使用过的模型。但是现在,有一个方便的库叫做[lazypredict](https://github.com/shankarpandala/lazypredict),用它你可以用一行代码训练scikit-learn中所有可用的模型(还有更多,像 XGBoost 和 LightGBM)。听起来很棒,对吧?让我们看看这在实践中是如何实现的!

实践示例

首先,您需要通过运行以下命令来安装库:

pip install lazypredict

很有可能,你会遇到一些关于缺失库的错误,那么就用pip或者conda分别安装吧。我稍后会提到这一点,作为可能的改进。然后,我们加载所需的库:

from lazypredict.Supervised import LazyClassifier, LazyRegressor
from sklearn.model_selection import train_test_split
from sklearn import datasets

lazypredict支持分类和回归问题,所以我将对两者进行简单介绍。

分类任务

因为这篇文章的目的是快速展示这个库是如何工作的,所以我没有使用任何花哨的数据集,只是使用了 scikit-learn 中的例子。对于分类任务,我使用乳腺癌数据集。我加载数据,并将其分成训练集和测试集。

# load data
data = datasets.load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=42)# fit all models
clf = LazyClassifier(predictions=True)
models, predictions = clf.fit(X_train, X_test, y_train, y_test)

对于任何熟悉scikit-learn的人来说,使用lazypredict非常容易和直观。我们首先创建估计量的一个实例,在本例中是LazyClassifier,然后使用fit方法使其适合数据。通过在创建LazyClassifier的实例时指定predictions=True,我们还将接收每个观察的所有模型的预测。以防我们以后想用它们做别的事情。此外,我们可以使用custom_metric参数来传递我们想要用来评估模型性能的自定义指标。

注意:通过查看代码,您可以看到哪些估算器被排除在可用模型列表之外。对于分类,我们收到以下 4 个指标,以及模型适合数据集所需时间的指示。

另一个对用户隐藏的重要事情是,库自动对数据集应用预处理。首先,它使用SimpleImputer估算缺失值(对数字特征使用平均值,对分类特征使用常量‘missing’值)。然后,它将StandardScaler用于数字特性,将OneHotEncoderOrdinalEncoder用于分类特性(取决于基数——唯一值的数量)。虽然这很方便,并且可以确保模型实际运行,但是一些用户可能更喜欢不同的方法来预处理数据集。这就是为什么在我看来,这应该是图书馆的一个自愿的特点,而不是强制性的。

注意:对于被视为分类的特征,它必须在底层数据帧中被表示为object类型。虽然这不是这个数据集的情况,但它在下面描述的回归问题中很重要。其中,数据集包含一些分类特征(例如,CHASRAD特征)。如果不将类型转换为object,库将把它们视为数字特征,并应用不正确的预处理!

models数据帧包含所有分类器的性能总结,而predictions(此处未显示,因为数据帧相当大)包含每个模型的所有预测。

回归任务

如前所述,回归任务与分类问题非常相似。我使用了 Boston Housing 数据集,并实例化了一个不同的类— LazyRegressor。剩下的就是类比了。

# load data
boston = datasets.load_boston()
X, y = boston.data, boston.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=42)# fit all models
reg = LazyRegressor(predictions=True)
models, predictions = reg.fit(X_train, X_test, y_train, y_test)

自然,包含模型性能的表对于回归任务有不同的度量,即 R 平方和 RMSE。我们可以使用custom_metric参数添加更多(例如,MAPE)。为了保持文章简洁,下表被截断了,但是可用回归变量的列表要长得多。

可能的改进

在简单地摆弄了一下lazypredict库之后,我认为有几件事可能会有显著的改进:

  • 这是一个简单的方法,但是要确保这个库有一个合适的依赖项列表,这样用户就不必根据他们得到的错误手动安装每个库,
  • 允许访问最佳/所有经过训练的模型,现在我们只能看到包含结果和预测的表格,
  • 并行训练模型——这对于小数据集来说不是问题,但是,对于大数据集来说,加快速度会更好,
  • 创建一个专用的predict方法来获得预测,
  • 使默认的预处理成为可选的,并清楚地记录下来,
  • 允许一些超参数调整。

结论

lazypredict是一个方便的包装器库,它使我们能够快速将所有模型与我们的数据集相匹配,并比较它们的性能。通过这种方式,我们可以看到“开箱即用”的有效方法。然而,这并不是模型训练和选择的灵丹妙药,因为只训练默认变量。众所周知,超参数调整可以极大地改变性能。

您可以在我的 GitHub 上找到本文使用的代码。一如既往,我们欢迎任何建设性的反馈。你可以在推特上或者评论里联系我。

觉得这篇文章有趣?成为一个媒介成员,通过无限制的阅读继续学习。如果你使用这个链接成为会员,你将支持我,不需要你额外付费。提前感谢,再见!

如果您喜欢这篇文章,您可能还会对以下内容感兴趣:

参考

懒惰文本预测

原文:https://towardsdatascience.com/lazy-text-predict-1d85389598a7?source=collection_archive---------44-----------------------

用 AUTO-ML 分类文本

一个用于快速简单的文本分类的开源库

杰洛特通过 pixabay 拍摄(CC0)

简介和动机

有很多很棒的文本分类包可以帮助你解决你的业务问题。比如决定一句话的情绪。然而,有一个复杂的问题。许多任务都是定制的,因此没有预先训练好的现成模型可供您开箱即用。对于初学者来说,制作一个定制的文本分类模型是非常具有挑战性的。定制机器学习包之间的差异通常非常细微。因此,需要丰富的经验来选择不同的工具。此外,为您的数据集实现选择的解决方案需要技术经验。这阻止了门外汉前进。

如果你想直接跳到代码,点击这里

汽车救援队

我们是一个机器学习开发人员团队,认识到开发人员社区面临的挑战,我们问“有没有一种解决方案可以让开发人员轻松地在不同的文本分类选项之间进行选择,而不必成为机器学习专家?”由于没有找到文本数据集的简单解决方案,我们决定构建一个并与开发人员社区共享。我们称之为懒惰文本预测。使用这一新工具,您可以在各种不同的文本分类模型上测试您的数据集,然后进一步训练最佳模型,以产生为您的特定需求定制的非常好的解决方案!

由于我们接触了 lazypredict 项目和其他 AutoML 解决方案,我们受到了构建这个项目的启发。

lazy-text-predict 包含一个工具包,让您加载数据来训练不同的文本分类模型,并比较它们的性能,以选择适合您情况的最佳工具。我们选择了几个深度学习(例如,transformers)和基于计数矢量器(sci-kit learn pipelines)的模型,这些模型可以解决各种文本分类任务。开始非常简单。

快速入门

开始使用这个工具真的很容易!您需要运行一个命令并键入 5 行代码:

首先,安装软件包:

pip install lazy-text-predict

接下来,使用代码:

上面的代码将训练一系列模型,根据输入文本“X”预测标签“Y”。该工具还将报告每种模型类型的性能。您可以使用“trial.print_metrics_table()”查看试验的摘要,并根据您即时想到的一些定制数据测试模型。例如:

trial.predict("This movie was so good that I sold my house to buy tickets to see it")

可以将自己的数据集加载到“X”和“Y”中,自己训练模型。一旦你做到了这一点,你就可以更严格地训练你最喜欢的这些模型,然后导出它用于你自己的代码中(这个工具也很方便)。我们已经准备了几个带注释的例子来展示如何做到这一点,我们的文档也给出了非常清晰的说明(我们希望!).以下是文档的链接:

https://github.com/lemay-ai/lazyTextPredict

其他工具

我们认为我们的工具在帮助人们开始学习 NLP 方面非常棒,我们希望您能使用它,但是如果您真的想深入这个令人兴奋的领域,您应该看看其他几个来源:

****拥抱脸:拥抱脸的团队策划了大量的自然语言处理模型和用于部署它们的软件包。我们已经将他们的许多模型整合到这个工具中。看看吧!

****Scikit-learn:Scikit-learn是当今最流行的机器学习和数据科学库之一,所以它们被包含在我们的工具中是很自然的。一般来说,它们是学习机器学习的很好的资源,并且它们有很多关于如何实现 NLP 和其他机器学习管道的有用教程。

下一步是什么?

lazy-text-predict 是一个不断改进的开源项目。我们有兴趣与社区合作承担这个项目。如果您想参与,请联系我们,联系方式为 daniel@lemay.ai

特别感谢开发团队对这个项目的第一次发布和这篇文章的贡献。

  • 爱德华·布克( GitHub
  • 吉特什·帕布拉( GitHub )
  • Rajitha Hathurusinghe
  • 赛义德·阿巴斯( GitHub
  • farzad amirjeavid(“t0”github
  • rabah al-qudah(“T2”ACM【T3])

-Daniel
lemay . ai
【Daniel @ lemay . ai】

线性判别分析——如何用监督降维改进你的模型

原文:https://towardsdatascience.com/lda-linear-discriminant-analysis-how-to-improve-your-models-with-supervised-dimensionality-52464e73930f?source=collection_archive---------3-----------------------

使用 Python 示例对 PCA 和 LDA 进行深入比较

线性判别分析(LDA)。图片由作者提供。

介绍

线性判别分析(LDA)是一种常用的降维技术。然而,尽管与主成分分析(PCA)相似,但它在一个关键方面有所不同。

它不是寻找新的轴(维度)来最大化数据中的变化,而是关注于最大化目标变量中已知类别(类)之间的可分性

在本文中,我直观地解释了 LDA 的工作原理,同时强调了它与 PCA 的不同之处。同时,我提供了一个对真实数据执行线性判别分析的 Python 示例。

内容

  • LDA 属于机器学习技术的范畴
  • 对 LDA 工作原理的直观解释
  • 对真实数据执行 LDA 的 Python 示例
  • 结论

线性判别分析(LDA)属于哪一类机器学习技术?

与主成分分析(PCA)不同,LDA 要求你为你的目标提供特征和类别标签。因此,尽管它是一种类似于 PCA 的降维技术,但它位于机器学习的监督分支内。

下图是交互式的,所以请点击不同的类别来放大并展示更多的👇。

机器学习算法分类。由作者创建的互动图表。

如果你喜欢数据科学和机器学习 ,请 订阅 每当我发布一个新故事时,你都会收到一封电子邮件。

线性判别分析(LDA)是如何工作的?

理解 LDA 概念的最简单的方法是通过一个例子。因此,我没有关注算法背后的数学,而是为我们创建了一个可视化的解释。

数据

假设我们已经收集了一系列关于城市公寓价格的数据。我们根据某个门槛,比如 100 万美元,将它们分为“昂贵”和“便宜”两类。

I.e., <$1M = cheap, and ≥$1M = expensive. 

我们将数据显示在一个散点图上,其中 x 和 y 轴代表纬度和经度,为我们提供公寓的位置。同时,颜色代表类别/级别(便宜与昂贵)。请注意,我们已经对这个虚构示例中的数据进行了标准化,因此它以原点为中心。

*S 串联化是一种数据转换技术,它会重新调整数据,使每个属性的平均值为 0,标准差为 1。这种转换可以用下面的公式来描述:

标准化。图片由作者提供。

让我们看一下示例数据的散点图:

公寓数据散点图。图片由作者提供。

现在,让我们比较 PCA 和 LDA 过程,以了解这些算法是如何工作的以及它们有什么不同。

应用主成分分析(PCA)

由于 PCA 是一种无监督的机器学习技术,我们不需要提供带有类别标签的目标变量。这意味着 PCA 不关心公寓是属于“便宜”还是“昂贵”的类别。

尽管如此,我还是保留了下图中的颜色标签,以突出与 LDA 的主要区别。

寻找主成分 1 (PC1)。图片由作者提供。

PCA 的目标是捕捉最大的变化量,这是通过算法找到一条线来实现的,该线使数据点到该线的距离最小。有趣的是,这相当于最大化同一条线上数据点投影的分布,这就是为什么我们可以捕捉最大的方差。

从上面的图表中可以看出,我们已经很好地找到了一个新的轴,它保留了大部分的方差,使我们能够从二维下降到一维。这是我们将数据映射到新的一维(PC1)后的样子:

公寓数据映射到一个维度(PC1)。图片由作者提供。

您可以清楚地看到,在这个场景中,我们能够保留大部分的差异,但是仍然丢失了一些在试图分离两个类别(类)时有用的信息。

如果你想更深入的了解 PCA,可以参考我之前的文章:

应用线性判别分析(LDA)

现在让我们回到我们的原始示例数据,并应用 LDA 而不是 PCA。快速提醒,LDA 的目标是最大化我们的目标变量(“便宜”、“昂贵”)中已知类别的可分性,同时降低维数。

下面是我们执行 LDA 时新轴的样子:

寻找线性判别式 1 (LD1)。图片由作者提供。

如您所见,在这种情况下,新轴的选择与 PCA 的选择非常不同。在这种情况下,通过将数据映射到 LD1,我们最终会损失大量的方差。但是,我们实现了两个类别的更好分离:

公寓数据映射到单一维度(LD1)。图片由作者提供。

虽然这种分离并不完美,但它明显更好,两个类别中只有一些重叠的观察结果。

LDA 如何找到合适的轴?

在为我们的新轴寻找“最佳”线时,使用了两个关键标准,这两个标准是同时考虑的。

  1. 最大化距离(d)。
    2 类 —当你的目标变量中有两个类时,距离是指类 1 的均值(μ)与类 2 的均值之差。
    超过两个类别 —当目标变量中有三个或更多类别时,算法首先找到所有数据的中心点,然后测量每个类别平均值(μ)到该中心点的距离。

2.最小化变化,也称为 LDA (s)中的“分散”。

让我们用图表来说明这两个标准:

LDA 步骤。图片由作者提供。

实际上,计算通常借助奇异值分解(SVD)或特征值分解来进行。这两个选项在 sklearn 的 LDA 实现中都是可用的,我们将在下一节中使用它。

对真实数据执行 LDA 的 Python 示例

最后,是有趣的时候了,我们可以使用 Python 来应用 LDA。让我们从为我们的分析获取正确的库和数据开始。

设置

我们将使用以下数据和库:

让我们导入所有的库:

接下来,我们从 Kaggle 下载一个摄取的房价数据

下面是数据的一个片段:

Kaggle 的房地产数据。图片由作者提供。

数据准备

对于这个例子,我们想要创建一个多类目标变量。因此,我们将“Y 单位面积的房价”分成三个相等的类别。我们称它们为:‘1。“负担得起”(最低的 33%),‘2。中档”(中间 33%)和“3。“昂贵”(前 33%)。

类别(类)标签分布。图片由作者提供。

因为我们已经创建了分类标签,而算法需要数字标签,所以让我们使用顺序编码器将它们转换成数字标签。【注意,我们可以直接分配数字标签,但是分类标签将使我们更容易阅读即将到来的可视化】。

编码的目标变量类标签。图片由作者提供。

为了保持可视化数据的能力,我们将限制自己使用前 3 个特征变量:“X1 交易日期”、“X2 房屋年龄”和“到最近的 MRT 站的 X3 距离”。

让我们通过在 3D 散点图上绘制这三个要素来看看数据是什么样的:

模型特征的 3D 散点图。图表作者作者

我们可以看到数据非常分散。此外,我们注意到,较便宜的房地产位于远离捷运站,而昂贵的往往更接近捷运,也较新。

数据准备的最后一步是特征的标准化。

请注意,在这个阶段,我们还应该将数据分为训练样本和测试样本,但是我们将处理整个数据集,以保持这个示例的简单性。

执行主成分分析(PCA)

出于兴趣,我们还将执行 PCA,这样我们可以将 PCA 的结果与 LDA 的结果进行比较。

PCA 结果。图片由作者提供。

有趣的是,PC1 和 PC2 的解释方差比率仅占总方差的约 69%,这意味着当从 3 维下降到 2 维时,我们损失了约 31%的总方差。这很大程度上是由于这三个特征之间的相关性很小。

以下是应用主成分分析后得到的 2D 散点图:

PCA 图。图片由作者提供。

虽然我们损失了 31%的方差,但我们仍然设法保持了两个新维度之间的大量差异。然而,由于 PCA 只考虑特征而不考虑目标,所以这三个类别(类)最终都混在一起了。

接下来,我们来看看 LDA 与 PCA 相比如何。

执行线性判别分析(LDA)

我们将使用特征分解作为我们的求解器(sklearn 实现使您能够在 SVD、LSQR 和特征之间进行选择),并将组件参数(维数)设置为 2,将所有其他参数保留为默认值。注意,这一次我们还需要向算法提供我们的目标(y)。

LDA 结果。图片作者作者

和以前一样,我们也将结果可视化在 2D 散点图上。

LDA 图。图片由作者提供。

与 PCA 相比,LDA 结果有显著差异。由于 PCA 的目标是分离目标类别,而不是最大化方差,因此它设法找到了减少蓝色(' 2。中档)和红色(‘3。昂贵的)点,使它们基本上保持在自己的空间内。与此同时,尽管在绿色(‘1。实惠)类,红蓝分离的还蛮不错的。

为了验证我们在这些散点图中看到的内容,让我们构建几个决策树模型,看看我们可以根据使用 PCA 和 ld a 创建的特征预测“价格带”的效果如何。

用决策树分类器创建预测模型

让我们建立一个可重用的函数,我们可以快速调用它来训练模型并显示结果。

现在让我们用它来建立一个具有 PCA 转换特征的模型。

以下是模型结果:

使用 PCA 变换特征的决策树模型结果。图片由作者提供。

正如所料,结果不是很好,准确率只有 64%。应用主成分分析后类别的混合无疑增加了预测价格标签的难度。

让我们对 LDA 变换的特征重复同样的操作。

使用 LDA 转换特征的决策树模型结果。图片由作者提供。

这一次模型似乎好了很多,准确率接近 79%。这些结果支持了我们早期的直觉,即与 PCA 相比,LDA 更好地保存了与预测公寓价格相关的信息。

结论

当我们希望降低数据的维数,同时保留尽可能多的与预测目标相关的信息时,LDA 是一个很好的工具。

然而,直接比较 PCA 和 LDA 可能不完全公平,因为它们是用于不同目的的两种不同技术。例如,PCA 是一种非监督学习技术,而 LDA 则属于 ML 的监督分支。

因此,请不要把上面的结果作为 LDA 优于 PCA 的证据。相反,请首先评估这些算法对您的独特情况的适用性。

我真诚地希望我的文章能够帮助您更好地理解线性判别分析,使您能够将其融入到自己的数据科学项目中。

干杯!👏
索尔·多比拉斯

如果你已经花光了这个月的学习预算,下次请记得我。 我的个性化链接加入媒介是:

https://solclover.com/membership

如果你喜欢这个故事,这里有几篇你可能会喜欢的文章:

从零开始领导数据科学项目

原文:https://towardsdatascience.com/leading-a-data-science-project-from-scratch-af66670f3e6a?source=collection_archive---------35-----------------------

每一个数据科学项目。

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

如果你是领导数据科学项目的新手,你会有很多问题,尽管作为实习生或团队中的工程师,你已经经历了太多次相同的步骤。

当谈到领导一个项目时,你需要鸟瞰是什么使你的项目成为一个好的产品。你的客户会为此杀人或送命。

为了给你一个即将到来的项目领导角色的组织蓝图,这里有一些从头开始的每个数据科学项目共有的东西。

1.想法。

首先,建立一个可以付诸实施的项目组合。这一部分比表面看起来要稍微困难一些,因为项目创意可能来自无数个地方。

马克·弗莱彻-布朗Unsplash 上拍摄

不可能提前预见到所有的障碍,并确信一个项目能够成功地启动。从接受这种不确定性开始,在需求迫切的地方启动一个项目。

以下问题将很好地帮助你关注你的兴趣点。

  1. 你的客户一直以来都渴望的东西。
  2. 你的客户可以从中受益,但还不知道。
  3. 哪些地方因为缺少信息而出现问题升级?
  4. 哪里有现成的数据却躲在暗处?
  5. 哪一个盲点被消除后,会引发其他 10 个领域的开悟。

这些通常是有利润丰厚的项目的领域。

请记住,项目并不总是要把特斯拉放在太空中。有时候,揭开一个以前不为人知的专栏会让你喜极而泣。

尊重微小的胜利。它们往往会带来更大的胜利。

2.数据收集

弄脏你的手。真实世界的数据并不干净。花足够的时间,识别所有的信息来源。

照片由戴吉永Unsplash 上拍摄

检查是否需要额外的硬件。真正的数据收集可能需要一个月到几年的时间,这取决于项目的复杂程度和记录的可用性。一些数据可能是手动记录的(票据、评论等)。).不要忽视这些来源。

在机器学习或人工智能项目中,一个额外的好处是当你可以用人工信息增加你收集的数据时。看看您是否可以使用开源图像来满足您的需求,生成您自己的数据集,处理您现有的数据,并用更多信息来扩充数据集。

3.数据清理

这一步是数据处理的潘多拉盒子。打开它。

这里有一些你在清理数据时应该考虑的事情。使用它来剔除数据集中不需要的信息,并确保您看到的是您认为自己看到的东西。

阿维纳什·库马尔Unsplash 上拍摄的照片

清理数据集后,可用数据可能会比原始数据集少得多。准备好用你所拥有的干净的数据来重新组织你的问题。

数据清理的一个重要方面是人。庞大的数据集和计算能力是过去几十年的事情,但人们已经与系统和数据打交道几个世纪了。

平静地与每个人见面,了解他们在系统中的角色。尽你所能获取所有有价值的信息,增加你对系统的了解。

4.探索性数据分析

制作你的数据的摘要,让你的客户能够立即理解。浓缩、分析和解释意思,并与有关方面讨论你的见解。

照片由卡伦·艾姆斯利Unsplash 上拍摄

了解您的参数之间的关系,消除错误记录、异常,并在每个分析级别获得洞察力。区分分类数据和连续数据,并相应地处理它们。

根据您的数据是分类数据还是连续数据,您将选择一种方法来构建模型。检查集中趋势和可变性(平均值、中间值、众数、标准差、范围等。).总结和可视化您的数据。确定频率、季节性、百分比等。

你可能会觉得有趣,许多专家可能会对你在可视化和压缩数据方面的最基本的发现感到惊讶。

5.模型结构

弗拉德·希利塔努在 Unsplash 上拍摄的照片

在选择了数据和特征之后,理解了你正在处理的事物的基本性质,你就可以创建一个模型了。

您想执行回归、分类、聚类还是预测?你有多少数据?它的本质是什么(绝对的,连续的)?根据你对这些问题的回答,你将选择一个模型。实际上,您可以从选择多个模型开始。

注意你的数据是否是线性可分的,你的目标变量是什么等等。您可以选择执行线性回归、逻辑回归、聚类模型,如随机森林、K 均值、神经网络等。

根据您的模型度量、您的计算能力以及预测或洞察力的需要,从您的实验中选择一个模型。然后,使用更多数据或自数据收集过程结束以来新收集的数据来验证您的模型。

如果你使用机器学习,注意你的结果要一般化。

6.生产

一旦您找到了正确的模型、一组超参数,并且您确定您的模型有效,您就会想要部署它。

当您部署项目时,您应该考虑它如何扩展,以及如何使用户界面对您的客户端友好。

要部署您的模型并使其广泛可用,您可能需要创建一个 web 应用程序,以便向其发送和接收请求。否则,您可以保存您的模型,并让您的用户使用它来获得对他们的数据的预测。

您可以在 Django、flask、shiny 或 dash 等 web 应用程序框架中实现您的模型。为了可扩展性,许多大公司使用 AWS 或 Azure 等服务来大规模部署机器学习模型。

这应该是开始下一个大数据科学项目的快速入门。你的做法不同吗?

如果你对技术或社交能力方面的文章感兴趣,请联系我, Sruthi Korlakunta

通过 LinkedInMedium 保持联系。给我写张纸条,能见到你就太棒了!

以身作则改善公民生活

原文:https://towardsdatascience.com/leading-by-example-to-improve-civic-life-550d88a16b27?source=collection_archive---------15-----------------------

社区聚焦

伦敦金融城的人工智能实验室正在为加拿大(及其他地区)的地方政府采用机器学习铺平道路

在 Community Spotlight 系列中,TDS 编辑与数据科学社区成员畅谈有助于推动该领域发展的激动人心的计划。今天,我们很激动地与大家分享 埃利奥特·冈恩 马特·戴利、 马特·罗斯布莱克·范贝罗**

图片由《走向数据科学》和斯科特·韦伯制作

****【Mat Daley】(LinkedIn)是伦敦金融城信息技术服务部主任。Mat 在公共和私营部门拥有 20 年的管理经验,并有幸在五个不同的行业工作过。作为一名企业家,马特参与了三家初创公司的领导工作。Mat 在滑铁卢大学完成了本科学业,在西方大学完成了公共管理研究生课程,是指定的项目管理专业人员。

(LinkedIn)***过去十年一直在技术与社会善的交汇处工作。创建了一家非营利性的技术创业公司,作为独立的数据科学承包商工作,并在伦敦金融城共同创建了人工智能实验室。马特在休伦大学攻读哲学学位,在西方大学攻读化学学位。*****

(LinkedIn)***是范贝罗咨询公司的创始人,这是一家专门从事机器学习应用研发的公司。Blake 之前在西方大学获得了软件工程学士学位,现在是滑铁卢大学 Cheriton 计算机科学学院的研究生。*****

在市级政府层面找到一个内部人工智能实验室并不常见。我很想更多地了解这个团队。你能分享一下这个实验室在伦敦做什么吗?典型的一天是什么样子的?

城市人工智能应用实验室是伦敦市信息技术服务部门的一部分。由于一些人事变动,实验室正处于过渡阶段。该实验室寻找机会利用人工智能和分析来部署低成本、低风险的解决方案,以改善该市市民和/或员工的生活。我们目前是一个非常小的团队,但由于不同项目的不同性质,我们试图变得灵活。

实验室典型的一天包括与利益相关者和开发者的频繁交流。利益相关者通常是城市服务的一部分或与之相关。由于我们的项目是由业务需求驱动的,我们不断地就正在进行的项目与利益相关者联系,接收反馈并提供教育。开发人员可能是内部员工或外部顾问,他们根据涉众提出的不断发展的需求,在项目上工作。我们也一直在寻找新的项目,接触城市中愿意合作的人。

你在 TDS 发表的文章 是第一篇讨论实验室将机器学习应用于公民问题的项目的博文( 也在 CBC )。你能分享一下这个项目是如何产生的吗?

长期无家可归预测系统确实是该实验室首次将机器学习应用于公民问题的举措。该项目的想法来自一位在金融城工作的商业系统分析师,它诞生于一个旨在发现应用机器学习机会的黑客马拉松。这个人与无家可归预防利益相关者密切合作,他想知道是否有一种方法可以使用机器学习来根据无家可归个人和家庭信息系统(HIFIS)数据库中包含的信息进行预测,该数据库包含有关获得无家可归服务的个人的信息。这个想法后来演变成从这些记录中预测长期无家可归者。在用一个小原型展示了这种方法的前景后,我们让利益相关者参与到无家可归者预防工作中。与他们的讨论强调了可解释的机器学习的重要性。从那时起,项目就处于开发人员和利益相关者不断迭代的循环中。

我们希望分享这项工作,因为这样做可能会给其他城市带来好处。作为一个市政府,我们认为我们不仅对伦敦有责任,而且对所有社区的福祉也有责任。通过展示我们的工作,我们增加了其他城市看到我们工作的机会。由于 HIFIS 应用的普及,我们的解决方案适用于加拿大的其他地区。为了让我们的工作尽可能容易理解,我们在 GitHub 库中包含了关于如何开始编写代码的详细说明。

你能告诉我们一些已经看到有希望结果的项目吗?

我们对长期无家可归预测项目感到特别自豪。该项目已经部署,现在可供与寻求无家可归服务的客户互动的个案工作者使用。

另一个我们引以为豪的项目是我们在水需求预测方面的工作。根据过去的用水量记录,我们开发了一个模型来预测未来几年全市的需水量。这项工作可能有助于基础设施规划和预算预测。这个项目的一个关键方面是,我们采用的模型本身是可以解释的;因此,水资源管理部门可以更好地理解和信任其预测。

在资源有限的情况下,政府如何确定有前景的项目并对其进行优先排序?你如何使 ML 项目与政府更广泛的目标保持一致?

市政当局提供广泛的服务;因此,有几个应用机器学习的流。政府的长期总体目标是变得更加有效和高效。更好的资源和更高效的服务交付直接关系到成功的机器学习项目的机会。因此,我们根据潜在项目实现这一目标的能力来评估它们。例如,无家可归和住房安全的内在和普遍性质促使我们应用机器学习来改善无家可归服务的提供。

该团队如何降低部署人工智能解决方案和干预与边缘化社区相关的漏洞的风险?

首先,我们与利益相关方进行持续的讨论,以确定突出的风险。我们将利益相关者放在第一位,确保开发由他们领导,并认为数据科学家会提供支持。例如,在我们的第一个项目中,我们与无家可归者预防组织(经理和个案工作者)密切合作,以确保数据得到尊重。

我们遵循多种策略来优先考虑信息安全和隐私。首先,我们与该市的隐私专员密切合作,发现并应用一流的安全和隐私考虑因素。我们要求明确同意数据使用,并在开发人员访问数据或将其发送到部署环境之前取消数据标识。

为了确定其他可能的风险,我们努力遵守加拿大政府关于自动决策的指令。为此,我们完成了联邦政府的算法影响评估工具,以确定我们项目的影响水平。

最后,我们优先考虑可解释的机器学习,以提高透明度。本质上不可解释的模型总是与可解释性方法产生的解释结合在一起。解释确保涉众理解为什么模型做出他们所做的决定。它们还可能揭示模型中存在的偏差,这些偏差可能触发后续的开发迭代。

有没有一些项目可能更适合由加拿大的政府机构来处理,而不是由 AI 和 DS 的盈利机构来处理?

有些服务由政府机构提供要比由私营企业提供好得多。我们认为有益于社会的服务属于这一类。在市政一级,这包括提供清洁饮用水、废水管理和公共交通。在省一级,示例可能包括医疗保健、教育、法律服务、警务、消防管理和应急服务。明确地说,我们不认为私营部门不能发挥作用——我们只是认为有些服务更自然地适合政府提供。

另一个考虑是,用于市政服务相关项目的数据集位于政府范围内。数据共享是一项复杂的任务,尤其是当个人数据可能与私人组织共享时。此外,数据科学工具和开源代码的普及需要政府机构免费使用,从而减少政府在这些项目上对私营部门的依赖。

作为数据科学造福社会的领导者,你认为这个团队扮演着什么样的角色?

我们视自己为榜样。我们分享从我们的项目中产生的代码和方法,旨在帮助其他城市采用相同的工具。

你喜欢什么样的 DS/ML 写作,你更希望看到什么?

我们喜欢阅读关于端到端机器学习项目的文章和论文,我们希望看到更多的产品。所谓“端到端”,我们指的是涵盖一个 ML 项目的所有步骤:从研究到部署。数据科学社区充斥着教程和想法,但我们很少看到关于可操作性、可持续性和资源的出版物。

您希望 DS/ML 社区在未来的哪些领域继续发展?

在接下来的几个月/几年里,我们希望看到对可解释的 ML 的更大推动。深度学习的进步以增加不透明性为代价,产生了更强大和更具表现力的模型。在市政府,透明度是向公民提供公平服务的关键。我们希望看到现有解释方法的应用得到更大的推动,新的解释方法得到发展,固有的可解释建模方法得到重新考虑。

我们希望社区更加关注机器学习系统的可持续性和维护。我们有几个关于这些主题的问题,我们一直在寻找关于当前和即将到来的项目的答案。当新数据可用时,保持系统相关性的最佳做法是什么?如果数据分布和/或特性集随着时间的推移而变化,会怎么样?谁在支持部署的系统,如何维护它们?

我们希望社区继续采用开放的方法,代码继续开源。如果没有免费的机器学习软件包,我们的项目(当然还有其他政府的项目)就不可能实现。

最后,我们希望看到对人工智能治理的更多追求。关于部署提供公共服务的系统的立法对于公平和安全地提供这种服务至关重要。

想在伦敦金融城的市政人工智能应用实验室了解更多关于数据科学的知识吗?下面是采访中提到的两篇文章,它们分享了利用机器学习造福社会的项目的深入案例研究。

使用 Tableau 和 Scikit Learn 进行线索预测

原文:https://towardsdatascience.com/leadprediction-with-tableau-und-scikit-learn-aa90b388bae1?source=collection_archive---------12-----------------------

基于 Kaggle 数据的案例研究

www.pexels.com 知识共享组织 CC0

任务

利用潜在客户(“潜在客户”)在网站上留下的数据,可以获得关于客户行为的重要见解和结果。然后使用机器学习从这些数据中创建预测模型。实例研究表明,该预测模型的准确率为 90%。

一家教育公司向行业专业人士出售在线课程。在任何一天,由于营销努力,许多对课程感兴趣的专业人士都会登陆他们的网站并浏览课程。这就是社交媒体渠道、网站或搜索引擎(如谷歌)吸引新潜在客户的方式。

一旦人们登陆该网站,他们就可以浏览课程,填写课程表格,或者观看一些视频。如果他们没有完成这一预期活动就再次离开网站,他们会被重新定位的活动带回来,并转化为销售线索。当这些人填写表格并提供他们的电子邮件地址或电话号码时,他们就被归类为潜在客户

一旦获得这些线索,销售团队成员就开始打电话、写电子邮件等。通过这一过程,一些销售线索被转化,而大多数则没有。典型的铅转化率在 30%左右。

例如,如果他们一天收到 100 条线索,其中只有 30 条会转化。为了使这一过程更加高效,该公司希望识别出潜在的潜在客户,也称为热门客户。如果他们能够识别这些销售线索,销售线索转化率应该会提高。因为销售团队现在更专注于与潜在的潜在客户沟通,而不是打电话给所有潜在客户。这不仅使销售过程更快、更成功,还节省了人员成本。

我们的任务是创建一个模型,在该模型中,每个销售线索都分配有一个销售线索得分。销售线索得分较高的客户转化机会较高,而销售线索得分较低的客户转化机会较低。

数据

我们在这个演示中使用了来自 Kaggle 的数据https://www.kaggle.com/ashydv/leads-dataset

数据集包含以下信息:

  • 请求是否成为客户—该列称为“已转换”。
  • 网站上的行为,如花费的时间、浏览的内容等。
  • 表格中提供的信息
  • 访问者是如何来到网站的(搜索引擎、推荐人、直接)

下表显示了数据的摘录。有 9240 人的数据记录,有 37 个特征。存储每个导联的特征。有些是数字特征,如访问网站花费的时间,但也有许多分类特征,如人口统计信息或来自 web 表单的信息。

数据可以通过 Kaggle 提供的 CSV 文件导入 Tableau。

记录的第一行

数据清理

正如实践中经常出现的情况,不完整的数据集提出了一个必须解决的问题。简单地删除所有不完整的记录通常不是可行的方法,因为太多的记录受到影响。详细的分析是必要的。

我们删除缺失值超过 40%的特征,因为这里没有什么可做的。在缺失数据较少的要素中,这些数据将被要素的主导值所取代。

此外,数据集中的许多列都有“选择”值。这些来自输入表单,其中客户没有从表单的列表中选择值(可能这不是强制输入)。“选择”显示在这里的数据集中。“选择”值和空值一样好,所以用空值替换。

如何执行这些步骤的详细描述可以在 https://www.kaggle.com/danofer/lead-scoring找到

根据分析,我们发现许多特征没有向模型添加信息,因此我们从进一步的分析中移除它们。 16 个特征保留在数据集中

使用 Tableau 进行探索性数据分析

让我们首先通过创建一个简单的条形图来看看有多少潜在客户和非潜在客户。为此,将“已转换”作为维度拖至“行”,将销售线索数拖至“列”。

“已转换”功能指示销售线索是否已成功转换(1)或未成功转换(0)。在我们的数据集中,大约 38%的客户被赢得。

现在,让我们通过根据记录数量显示带有彩色国家的地图来查看数据的区域分布。

映射销售线索来源

为此,我们使用“国家”维度和销售线索数量以及适当的图表类型。Tableau 然后自动生成纬度和经度数据,并将它们放在“行”和“列”中。

很多数据来自印度,如图所示。

我们现在考虑数字特征“总访问量”、“在网站上花费的总时间”和“每次访问的页面浏览量”。我们使用“盒须”图来检查数据的分布。

数字特征的“盒须”图

已转化和未转化销售线索的网站访问次数的中位数是相同的。根据访问的总次数,不能期望得出结论性的陈述。

在网站上花更多时间的人更有可能改变信仰。建议改进网站,使其对用户更有帮助,并让用户继续关注网站。

转化和未转化的潜在客户每次访问的页面浏览量中位数是相同的。从每次访问的页面浏览量来看,没有什么可以特别说明潜在客户的转化。

现在我们考虑范畴特征。

销售线索是从哪个来源产生的?

潜在客户的来源

二维条形图(引线来源和转换)用于显示引线计数。

  • ‘Lead Add Form’的转化率非常高,但是 lead 的数量不是很高。
  • “API”和“登录页面提交”带来了更多的潜在客户。
  • “销售线索导入”产生的销售线索非常少

为了提高整体销售线索转化率,我们需要更加注重提高 API 和登录页面提交来源的销售线索转化率,并从销售线索添加表单中生成更多销售线索。

联系信息

我们看到,不想收到邮件的人,转化率很低。

作为最后一个例子,让我们看看用户的最后活动。

最后一次活动

大多数销售线索都将打开电子邮件作为他们的最后一项活动。对于那些将手机短信记录为最后一次活动的潜在客户来说,发送的手机短信具有很高的转化率

预测模型

我们现在创建一个预测模型,为每个销售线索提供一个预测,说明它是否会在所考虑的时间段内转换。为了评估模型,只有 70%的数据用于创建模型。剩余的 30%用于通过创建预测并将其与实际转换数据进行比较来测试模型。

这为未来提供了一种计算方法,它根据销售线索特征计算转化概率,并提供了一种对该预测有多好的估计。平均多久出错一次?

为了构建预测模型,我们使用了逻辑回归模型类。逻辑回归是模拟二元因变量的统计模型。在我们的案例中,线索是否被转换。

模型中有许多特征,但是它们中的许多对模型的良好性没有任何贡献。我们现在执行特征选择。从我们可用的众多特征中,我们希望仅使用最重要的特征来建立模型,以便一方面获得更简单但也更稳定的模型。

递归特征消除(RFE) 的目标是逐渐选择越来越少的特征。首先,对原始特征集进行训练,并计算每个特征的重要性。然后,从当前特征集中移除最不重要的特征。在缩减的集合上递归地重复该过程,直到最终获得缩减的期望数量的特征。然后,我们用减少的特征数创建一个新模型。

使用 Scikit Learn 训练模型的代码可在此处找到:

用 30%测试数据进行评估

这样,我们现在可以用测试数据来确定预测的准确性。这个大概是 90.5%。

误差矩阵

通过误差矩阵,我们可以了解模型在评估过程中出现何种误差的频率。在 5.7%的预测中,一个转换被错误地预测,尽管没有。这是一个相当适合实践的数值。

16%的转化案例未被检测到。这也是一个有用的值。

摘要

我们从分析数据中获得了以下见解:

  • 花在网站上的时间是成功完成的一个很好的指标。
  • “潜在客户来源”在潜在客户数量和转化率方面有很大差异。
  • 最后记录的活动为预测提供了重要信息。

该信息用于创建新销售线索的预测模型,在评估时,显示预测准确率略高于 90%

精益毫升

原文:https://towardsdatascience.com/lean-ml-c003511b29a1?source=collection_archive---------45-----------------------

萨姆·穆卡达姆在 Unsplash 上拍摄的照片

入门

精益软件开发的原则如何应用于机器学习项目?我们来看看吧!

介绍

诞生于汽车行业的精益制造原则已经被软件工程社区热情拥抱。总的来说,精益原则寻求在软件开发过程中最小化浪费的努力,并最大化客户对你的产品的满意度。如果它适用于制造汽车和构建传统软件,那么对于您的下一个 ML 项目来说,它值得一看!

以下是原则:

  • 消除浪费
  • 中构建质量
  • 加速学习
  • 推迟决策
  • 送快递
  • 授权给你的团队
  • 整体优化

启动你的冲浪板

微软 Azure 上的看板(图片由作者提供)

在我对一个项目做任何事情之前,我确保我有我的看板板设置!本着保持精益的精神,管理一个项目,没有比定义任务(当它们显露出来的时候)并跟踪每个任务从 到>做- >完成 更简单的了!

这是敏捷方法的最简单、最轻的版本。完整的方法论包括将像功能故事任务这样的事情安排到冲刺中——这对于很多项目来说可能是多余的。

最棒的是——看板免费!点击微软的链接,开始在云中做这件事:

https://docs.microsoft.com/en-us/azure/devops/boards/boards/kanban-quickstart?view=azure-devops

概念验证 vs MVP vs 产品

微软文字处理产品(作者图片)

要想在一个 ML 项目中取得成功,重要的是先走后跑。我总是从一个无技术或低技术的概念验证开始,来梳理这个项目是否值得。当回报遥遥无期时,没有理由投入大量时间或金钱来构建一个复杂的 ML 模型。

当我从浅入深时,就我的 ML 项目的价值主张来挑战我自己是必要的。

为了说明的目的,我们可以想到微软的文字处理产品:记事本是一个基本的文本编辑器;写字板在基本的富文本格式上更进了一步;微软 Word 是面向专业人士的终极文字处理软件。

概念证明(POC)

这是原型阶段,我证明了将机器学习技术应用于我的项目的整体概念是有价值的。在这一点上,快速行动/快速失败是很重要的:我只是使用现成的算法和框架来快速建立我所想的几乎不起作用的版本。

最小可行产品(MVP)

现在是时候认真构建一个能够经受住部署到生产的严酷考验的机器学习模型了。如果我已经扫清了概念验证的障碍,并走到了这一步,那么是时候投资于详尽的模型选择/调整工作,并确保我的 MLOps 管道中的管道能够承受压力。

这个阶段成功的关键是抑制我对产品功能的热情。我的机器学习项目的这个版本不需要取悦客户——它只需要为他们提供一些基本的功能,让他们体验即将到来的东西。

产品

假设我的 MVP 产生了很多兴奋,是时候卷起袖子,认真对待功能了。管道和脚手架现在应该已经准备好了,所以在这一点上的大部分工作都围绕着梳理出哪些特定的特性会让我的客户高兴,以及什么是最佳的工作流。

我努力不低估工作流程的重要性。过去,有这些笨重的便携式 MP3 播放器用来听音乐。早期的模型一点也不直观,需要阅读用户手册才能操作。然后苹果公司带着他们的 iPod 出现了,游戏完全改变了。我们现在都希望能够在没有指导的情况下使用手机上的应用程序——我们的机器学习产品应该具备这种可用性水平。

进化而非革命

从本质上来说,精益原则是关于从一个基本的原型发展成为生产中功能齐全的产品。我发现这个过程中最难的部分之一是放下死胡同:当我发现自己朝着一个没有结果的方向前进时,我需要停止支持、以及再次尝试!说起来容易做起来难。但这并不是用完美的计划描绘出完美的产品,而是通过快速、反复的尝试发现理想的产品。

7 项原则

Fabrizio Chiagano 在 Unsplash 拍摄的照片

精益原则与其说是具体的项目生命周期方法,不如说是一种态度或哲学。我试图在我的 ML 项目中记住它们——但避免对此过于严格——这都是为了保持精益!

消除浪费

这里的当务之急是简化开发过程——去除任何减缓向客户交付价值的东西。这可能意味着过度官僚化的过程、过度的上下文切换、需求变动、过高的目标等等。

将质量建立在

bug 是在浪费大家的时间。降低软件质量最可靠的方法是建立一个质量保证部门。质量需要成为每个人的关注点——在整个过程中——而不仅仅是那些标题中有名词的人。

加速学习

ML 项目的团队应该在结束时带着比开始时更多的知识离开。同行评审、频繁的头脑风暴会议、培训演示、全面的文档和有意义的注释代码是如何实现这一点的一些例子。

推迟决定

我试图尽可能晚地将假设和决策锁定在我的 ML 模型中,拥抱迭代的方法来充实我的项目,并抵制在不得不提交之前提交的诱惑。

快速交付

我的 ML 项目越早交到客户手中,我就能越早收到有价值的反馈——为我下一次迭代的成功做好准备。

授权给你的团队

团队成员必须有一种主人翁意识,才能达到最高的工作效率,因此确保沟通渠道保持畅通,每个人的意见都得到尊重,这一点至关重要。

整体优化

我们对这一原则的关注是提高我们向客户交付价值的速度——在整个 ML 项目团队中。这是关于所有团队成员和利益相关者在追求速度最大化的过程中减少摩擦。

结论

挑战自己,在下一个 ML 项目中使用看板——即使只是一个快速教程。将这 7 条精益原则放在你面前,并考虑如何将它们应用到你目前正在做的事情中。是否有机会将您的交付成果分成 POC / MVP /产品?那会是什么样子呢?

精益六适马与 Python-Kruskal Wallis 测试

原文:https://towardsdatascience.com/lean-six-sigma-data-analytics-with-python-kruskal-wallis-test-3afafa097ed?source=collection_archive---------17-----------------------

如何用 Python 替换 Minitab 来执行克鲁斯卡尔沃利斯测试评估培训对仓库操作员生产力的影响

仓库操作员培训—(图片由作者提供)

精益六适马(LSS) 是一种基于逐步改进流程的方法。

这种方法通常遵循 5 个步骤(定义、测量、分析、改进和控制)来改进原因不明的现有流程问题。

在本文中,我们将探讨 Python 如何在分析步骤中取代Minitab(LSS 专家广泛使用的软件) 来测试假设了解什么可以提高特定流程的性能指标

💌新文章直接免费放入你的收件箱:时事通讯

**SUMMARY**
**I. Problem Statement** *Can we improve the operators' productivity by giving them a training designed by R&D team?*
**II. Data Analysis
1\. Exploratory Data Analysis**
Analysis with Python sample data from experiment with few operators 
**2\. Analysis of Variance (ANOVA)**
Verify the hypothesis that training impacts productivity
ANOVA assumptions are not verified
**3\. Kruskal-Wallis test** Confirm that the hypothesis can be generalized
**III. Conclusion**

如果你喜欢看,你可以看看这篇文章的视频版本

一.问题陈述

1.方案

你是一家专注于时装、香水和手表的标志性奢侈品牌配送中心(DC)持续改进经理

仓库在入库流程中接收需要总装增值服务服装

某奢侈品牌配送中心的 4 条增值服务生产线车间示例—(作者提供的 CAD 模型)

对于收到的每件服装,您的操作人员需要用当地语言打印标签并且执行标签缝制

标签示例—(图片由作者提供)

在本文中,我们将重点关注标签缝制生产率的提高。

标签以 30 个为一批分发给操作人员。生产率是根据完成一个批次所需的时间(秒)来计算的。

4 个标签缝制工作站—(作者提供的 CAD 模型)

2.培训员工的影响

在 R&D 团队的支持下,您为 VAS 操作员设计了培训,以提高他们的生产力并减少质量问题。

问题
培训对操作员的生产力有积极影响吗?

假设
培训对 VAS 操作员的生产力有积极影响。

实验 随机选择操作者,测量每批时间(以秒为单位完成一批 30 个标签的时间)构建 56 条记录的样本

测试我们假设的数据驱动分析—(图片由作者提供)

http://samirsaci.com

二。数据分析

你可以在这个 Github 资源库中找到完整的代码: 链接

1.探索性数据分析

你可以把这个实验的结果下载到这个 CSV 文件中,在你的电脑上运行整个代码(此处)。

实验结果:每个操作员的生产率(秒/批次)

56 条记录
35 条未培训操作人员记录
21 条培训操作人员记录

方框图

实验结果的箱线图—(图片由作者提供)

根据样本数据,我们可以看到,受过培训的操作员的中值和平均值要低得多。

假设
该训练减少了每批的平均时间。

代码

**Minitab**
Menu Graph > Box Plot > Simple > 1 Y with Groups 

2.方差分析(ANOVA)

在这个场景中,我们想要检查培训(变量 X) 是否影响每批总时间(变量 Y)

因为 X 是分类变量(训练=是/否) Y 是数值,所以合适的方法是 ANOVA

ANOVA 是一种统计方法,用于检查我们是否可以将样本数据中的均值差异推广到整个人群。

第一步:计算 p 值

Source: Training
ddof:   11
ddof:   245.267
F:      17.1066
**p-unc**:  0.000151308
p:      20.173692p-value is below 5%

代码

**Minitab**
Menu Stats > ANOVA > One-Way 

第二步:验证方差分析的假设

基于 p 值,我们知道平均值的差异是真实的,而不是由于随机波动。

然而,在得出结论之前,我们需要检查方差分析假设是否得到满足

  • 残差是自然分布的

残差分布—(图片由作者提供)

回答:没有

  • 没有异常值或不规则性

对比顺序—(图片由作者提供)

回答:没有

结论

代码

**Minitab**
Menu Stats > ANOVA > One-Way > Graphs > Four in one

3.克鲁斯卡尔-沃利斯试验

如果您的样本数据不符合 ANOVA 的要求,您可以使用 Kruskal-Wallis 检验来检查均值的差异是否是由于随机波动造成的。

**statistic** = 54.99
**pvalue** = 1.205e-13
**p-value is below 5%**

结论

我们可以确认培训对操作员的生产力有积极的影响。

代码

**Minitab**
Menu Stats > Non-parametric > Kruskal Wallis > Graphs > Four in one

如果您对使用 Python 的精益六适马方法的其他应用感兴趣,可以看看下面的文章:

https://www.samirsaci.com/lean-six-sigma-with-python-chi-squared-test/ https://www.samirsaci.com/lean-six-sigma-with-python-logistic-regression/

三。结论

关注我的 medium,了解更多与供应链数据科学相关的见解。

这种数据驱动的方法为您提供了足够的要素,让您能够说服管理层投资劳动力培训。

通过使用统计学从样本数据中归纳出模式,你用适度的实验努力带来了足够的洞察力。

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运营并降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

参考

[1]变异数的 ANOVA 分析, Ted Hessing ,六适马学习指南, link
[2]奢侈品总装线的排产与 Python,Samir Saci, link

基于 Python 的精益六适马—逻辑回归

原文:https://towardsdatascience.com/lean-six-sigma-with-python-logistic-regression-36d160e84548?source=collection_archive---------30-----------------------

用 Python 替换 Minitab 以执行逻辑回归估计达到 75%的生产率目标所需的最低奖金

最低奖金问题-——(图片由作者提供)

精益六适马是一种可以定义为过程改进的逐步方法的方法。

在之前的一篇文章中,我们使用了克鲁斯卡尔-沃利斯测试来验证特定培训对运营者入站增值服务生产力产生积极影响的假设。(链接)

在本文中,我们将使用 Python 实现逻辑回归,以评估每日生产率奖金对您的仓库操作员拣选生产率的影响。

💌新文章直接免费放入你的收件箱:时事通讯

**SUMMARY**
**I. Problem Statement** *What should be the minimum amount of daily incentive to get 75% of workers that reach their productivity target?*
**II. Data Analysis
1\. Exploratory Data Analysis**
Analysis with Python sample data from experiment 
**2\. Fitted Line Plot of your Logistic Regression**
What is the probability of reaching the target for each value of daily incentive?
**3\. Validation with the p-value** Validate that your results are significant and not due to random fluctuation
**III. Conclusion**

如果你喜欢看,可以看看这篇文章的视频版本

一、如何优化仓库操作员的生产力奖金?

1.方案

你是一家物流公司(3PL) 的区域总监,你的职责范围内有 22 个仓库

带提货、VAS 和包装的履行中心—(作者设计的 CAD 模型)

在每个仓库,现场经理为操作人员确定了一个拣货生产率目标;你的目标是找到正确的激励政策,以达到该目标的 75%。

2.找到正确的激励政策

目前,除了日薪 64 欧元 (税后)之外,有生产能力的操作人员(达到每日生产能力目标的操作人员)每天还能获得 5 欧元

但是这个激励政策在 2 个仓库应用的效果不是那么好;只有 20%的操作员达到了这个目标。

问题 要达到 75%的拣货生产率目标,每天需要的最低奖金应该是多少?

实验

  1. 在你的 22 个仓库中随机选择操作员
  2. 实施每日奖励金额,在 1 至 20 欧元之间变化
  3. 检查操作员是否达到他们的目标

二。数据分析

1.探索性数据分析

你可以在这个 Github(跟我来:D)资源库中找到完整的代码: 链接
我的投资组合与其他项目:
小萨奇

样本分布的箱线图

按目标划分的激励分布箱线图—(图片由作者提供)

达到目标日的奖励中值比低于该目标日的奖励中值高两倍以上。

2.逻辑回归的拟合线图

逻辑回归将为我们提供一个概率图。我们可以估计每天激励的每个值达到目标的概率。

样本数据的拟合线图—(图片由作者提供)

确认当前趋势:5 欧元->达到 20%的生产率目标

我们需要每天至少 15 欧元的奖励,以确保 75%的可能性达到目标

代码

**Minitab**
Menu Stat > Binary Fitted Line Plot

3.使用 p 值进行验证

为了检查这些基于样本数据的结果是否显著,我们需要计算 p 值。

p-value: 2.1327739857133364e-141
p-value < 5%

p 值低于 5% ,因此我们可以得出均值差异具有统计学意义的结论。

结论 如果你固定了价值 15 欧元每天的激励,你将达到目标的 75%。

代码

**Minitab**
Menu Stat > Binary Fitted Line Plot

如果您对使用 Python 的精益六适马方法的其他应用感兴趣,可以看看下面的文章:

https://www.samirsaci.com/lean-six-sigma-with-python-chi-squared-test/ https://www.samirsaci.com/lean-six-sigma-with-python-kruskal-wallis-test/

三。结论

关注我的 medium,了解更多与供应链数据科学相关的见解。

投资回报率是多少?

基于这一实验,我们确定了最低金额为 15 欧元/天,用于奖励达到您的 生产率目标 的 75%。

在实施这一新的激励政策之前,您需要检查您的投资回报是否为正:

  • 提货操作员每小时的总公司成本(CTC) (基本工资+社会贡献)是多少?(欧元/小时)
  • 生产率提高后获得的总小时数是多少?(小时)
  • 雇佣这个小时数的临时工的 CTC 是多少?(欧元)****
  • 激励措施的总 CTC 是多少?

回答完这些问题后,你将能够估计这项新激励政策的投资回报。根据操作员的每小时成本,您可能会损失或节省资金。

后续步骤

然而,操作员的工作效率可能不仅受他们的动机驱动,还会受到仓库布局、提货流程或订单概况的影响。

因此,该分析应通过流程优化研究来完成,以确保运营商能够在适当的激励下充分发挥其潜力。(更多信息可以查看我之前关于仓库拣货效率的系列: 链接 )

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运营和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

参考

sklearn 逻辑回归的 P 值, Rob Speare

[2]使用 Python、Samir Saci、L ink 的订单批处理提高仓库生产率

[3]精益六适马与 Python — Kruskal Wallis Test,Samir Saci,链接

从 Matplotlib 到 Plotly 的飞跃:初学者实践教程

原文:https://towardsdatascience.com/leap-from-matplotlib-to-plotly-a-hands-on-tutorial-for-beginners-d208cd9e6522?source=collection_archive---------12-----------------------

如何使用 Plotly 创建带有自定义工具提示和范围滑块的交互式组合图

图片来源: Pixabay

介绍

作为一名数据科学家,在了解 Plotly 之前,我曾经非常依赖 Matplotlib 来完成我的数据可视化任务。虽然 Matplotlib 是一个在 Python 中创建可视化的快速而简单的工具,但它最适合于初始探索性分析和静态绘图。如果你想用 Matplotlib 做一些不仅仅是基本的静态图,有时会变得非常复杂。

Plotly,另一方面,是一个更新的开源图形库,旨在高效地创建更复杂的交互式可视化。它通常只需要最少的努力和几行必要的代码就能创造出美观和互动的情节。近年来,它在数据科学社区获得了显著的增长和发展,将来可能会超过 Matplotlib 的受欢迎程度。

在本文中,我将一步一步地向您展示如何使用 Plotly 创建一个带有定制工具提示和范围滑块/选择器的交互式组合图。在整个教程中,你将学习到的关键概念和特性,同时提供完整的代码供你一路尝试。

我们正在构建的交互式组合图如下所示:

使用 Plotly 的交互式组合图(图片由作者提供)

Plotly Express vs. Plotly Go

Plotly Python 库是一个交互式的开源图形库,涵盖了广泛的图表类型和数据可视化用例。它有一个名为 Plotly Express 的包装器,是 Plotly 的高级接口。

Plotly Express 作为一个起点,使用简单的语法创建最常见的图形既简单又快捷,但在涉及更高级的图表类型或自定义时,它缺乏功能性和灵活性。

与 Plotly Express 相比,Plotly Go (图形对象)是一个低级的图形包,通常需要更多的编码,但更具可定制性和灵活性。在本教程中,我们将使用 Plotly Go 创建如上所示的组合图。您还可以将代码保存为模板,以便在其他用例中创建类似的图表。

下载数据

用于创建组合图的数据可以从 CDC 的网站下载。这是一个开放式数据集,用于跟踪美国每天的新冠肺炎新病例和 7 天移动平均数。

每日新冠肺炎病例数据(数据来源: CDC

导入库并读取数据

让我们首先导入本教程所需的所有库,并将数据读入 python。如果这是你第一次使用 Plotly,你需要在导入库之前安装 Plotly 。你可以在你的 Jupyter 笔记本上运行下面的命令行(我已经有了 Plotly 所以它显示‘需求已经满足’)。

安装 Plotly(图片由作者提供)

数据集信息(按作者分类的图像)

这是一个相当简单的数据集,几乎可以被可视化。我们注意到“日期”字段是一个字符串,所以我们需要将其转换为“日期”类型。此外,为了最佳实践,我总是重命名单词之间有空格的字段,所以我们将通过删除空格来重命名最后三个字段。

最后一件事是,后来,我们想显示“新的情况”和“7 天移动平均”在工具提示的阴谋。如果用千位分隔符显示数字,会更容易阅读。我们可以通过创建两个新的重新格式化的字段(对象类型)来处理这个问题,这两个字段将显示带有千位分隔符的数字。

可用于可视化的数据框

使用 Plotly Go 创建标准组合图

要使用 Plotly Go (图形对象)开始绘图,我们需要首先使用 go 创建一个图形。Figure() 然后使用 fig.add_trace()向其添加两条轨迹什么是痕迹?来自 Plotly 的文档:

“跟踪只是我们给数据集合起的一个名字,以及我们想要绘制的数据的规格。请注意,轨迹本身也是一个对象,并且将根据您希望数据在绘图表面上的显示方式来命名。

追踪类似于您希望用数据绘制的特定可视化类型。每个轨迹都有 40 多种可能的类型,包括散点图、条形图、饼图、choropleth 图等。在我们的例子中,由于我们正在绘制一个组合图(折线图和条形图的组合),我们将向图中添加两条轨迹。

注意,线形图是使用 go 绘制的。散布()。这是因为 Plotly 折线图被实现为相连的散点图。这也意味着数据点按照它们在数据集中出现的顺序与线连接。因此,如果最初的排序没有得到想要的输出,您可能需要在将数据传送到 Plotly 之前对数据进行明确的排序。

使用 Plotly 的基本交互式组合图(图片由作者提供)

自定义悬停工具提示

默认情况下, Plotly 自动在工具提示中显示 x 轴和 y 轴值。例如,在上图中,如果将鼠标悬停在折线图中的任何数据点上,将出现一个工具提示,并显示新案例的快照日期和 7 天移动平均值。

我们可以自定义工具提示的外观,首先在数据框中创建一个名为“文本”的新列。这个“文本”列显示了我们想要在工具提示中显示的信息,并定义了工具提示的外观和感觉。然后,我们将这个列“文本”传递给 go。通过将其分配给 hoverinfo 参数来散布()轨迹。

以下代码在数据框中创建“文本”列。被称为 Boldface 元素的 HTML 元素在这里被用来将“State”字段的文本加粗。HTML 元素在文本中产生一个换行符,并且文本在文本块的下一行的开始处重新开始。

现在让我们将“文本”列传递给 go 中的 hoverinfo 参数。Scatter() 并检查它在工具提示中的外观:

带有自定义工具提示的组合图(图片由作者提供)

这个看起来不错!让我们对剧情做一些额外的调整,让它看起来更专业。我们将把工具提示的背景颜色从红色改为浅蓝色。我们还将为该图添加一个图表标题,并将 x 轴刻度改为月度(而不是季度)。所有这些更改都可以使用 fig.update_layout() 来实现,如下面的代码所示。

作者图片

添加范围滑块/选择器

我们还可以向绘图添加一个范围选择器/滑块,以便用户可以放大到特定的时间序列范围,这使得可视化更加丰富和互动!这可以通过使用 fig.update_xaxes() 用几行代码轻松实现。

交互式组合图(图片由作者提供)

这就对了。您已经使用 Plotly Go 创建了一个交互式组合图,通过定制的工具提示和范围滑块/选择器来可视化美国每天的新冠肺炎病例趋势。正如你所看到的,Plotly 图形库非常强大,优雅,高度可定制。它使得创建复杂的交互式可视化的任务变得非常容易和高效。我希望这篇文章对你有所帮助,并准备好将 Plotly 添加到你的数据科学家工具箱中。

参考和数据来源:

  1. Plotly 官方文档页面:https://plotly.com/python/
  2. 数据来源:来自疾病控制和预防中心(CDC)网站(https://covid.cdc.gov/covid-data-tracker/#trends_dailycases)的公开新冠肺炎追踪数据集

你可以通过这个推荐链接注册 Medium 会员(每月 5 美元)来获得我的作品和 Medium 的其他内容。通过这个链接注册,我将收到你的会员费的一部分,不需要你额外付费。谢谢大家!

快速学习一项新技术?—以下是方法

原文:https://towardsdatascience.com/learn-a-new-technology-quickly-here-is-how-3ae4313366a4?source=collection_archive---------4-----------------------

关于如何快速学习的一些技巧——尤其是在数据科学领域。

《仰望》,波兰 2021。作者照片。

科技是迷人的。正是缺失的一环,带来了今天明天的梦想。对许多人来说,这也是一个有吸引力的职业——工程师、经理、企业家和各种问题解决者都受欢迎。

不幸的是,还有一个陷阱。问题在于不断变化的技术环境和空前丰富的信息。从哪里开始,如何保持专注和相关性?你不觉得很熟悉吗?

在这篇文章中,我想分享一些“窍门”,它们让我在经历了两次职业生涯的转变后,能够快速上手。每次我投入新的水域,我都必须学习游泳。现在,当我回顾过去 10 多年的职业生涯时,我想分享一下我对学习技巧的看法。

屋顶和地基

让我直入主题。因为要解决一个问题,你必须理解它。虽然听起来显而易见,但我们大多数人只会从一个角度来看待问题。作为人类,我们倾向于用我们熟悉的术语来描述他们,并使用与我们背景相关的语言。

然而,当被要求提供解决方案时,我们经常会看到现实经常逃离我们思维的僵硬框架,并且找出方法一点也不容易。一个朋友曾经说过“如果你是一把锤子,所有的东西看起来都像钉子。”要想知道这有多真实,你可以看看那些人们尽管有着最好的意图却失败了的案例。

那么,怎样才能获得第二种视角呢?

想想房子。没有屋顶或坚实的基础,好的建筑是不可能存在的。你可能认为它是功能特性的集合,比如提供庇护、存储或保护的能力。你也可以认为它是材料、结构、砖块和所有东西的混合物,它实际上就是这样。两种方式都是对的,只是侧重点不同。根据抽象层次的不同,我们可能在“特性层次”或“基本原则层次”(一个极端的例子)上操作,但是要成为一个好的“与房子相关的问题解决者”需要同时掌握这两个层次。

根据我的经验,在任何任务中,关键的挑战总是识别高层业务特性和使用的特定方法和结构之间的桥梁——为什么使用它们?为什么用他们的方式?这是命中注定的吗?还是单纯的当时最有意义?

要知道问这些问题可能会让人产生戒备心理,所以建议小心。尽管如此,还是自己问他们吧。他们将帮助你将理论与实践相结合,也可能与更深奥的社会背景相结合。

这完全是关于决策过程的映射。

搭建一个棚子

建筑物越大,建造它所花费的时间和精力就越多。不仅如此——许多建筑被设计成执行多种功能,或者在不同时期根据不同的治理或法律进行建造和改造。有些地方花了几十年(如果不是几百年)才建成。

好消息是(通常)不需要太多就能掌握这个过程。虽然毫无疑问,一个棚子不是一个完全成熟的房子,但创造一个棚子需要解决相当多的较小的问题和挑战。通常,最重要的是需要做出决策的步骤。

当我开始一项新工作或一个项目时,我的首要目标之一是定义一个与我需要专业交付的项目有些相似的宠物项目。在不损害秘密或道德的情况下,我试图创造一个“棚子”,并假装它是一个假想顾客的产品。有时候,它是一个有用的小工具或应用程序,有时是一个无用的软件,不可避免地会腐烂。不管是什么,它总能让我快速理解“发生了什么”

如前所述,关键部分是做出设计决策。它们影响一切:选定的组件、库、方法、接口、工具、验证结果的方法,以及人力资源分配(阅读:我的睡眠)。不像纯粹通过阅读书籍或解决编码难题来学习,经历整个创作过程会产生有价值的体验。还有,它的好处是,失败没有惩罚——只有学习。

可能会很难看

你最喜欢的项目——一个棚子——是你工作的证据。它不需要赢得选美比赛。除非关键卖点是它的外观,否则只要它能发挥作用,你就能完全开心。

通常,当我在做项目时,我会尝试留下一两个更具“探索性”的特定领域,同时让其他所有事情不那么具有挑战性——甚至可能使用一些架子组件。然而,探索区是我试图从第一原理开始搭建棚子以获得更基本理解的地方。比如说你想学 docker 。构建一个真正的应用程序来服务于您的预测模型并使用“新”工具部署它是有意义的。而不是关注你的“产品”的所有方面:建模、web 等。,尝试用几种不同的方式“dockerize”一个简单的 app。

随着时间的推移,你可能想详细阐述其他领域。然而,在各条战线上工作是很累的,而且不太可能通过完成你开始的事情来获得内啡肽。如果你对这些踢腿上瘾,你会频繁地传递你的“棚子”。久而久之就会变成小房子!

今天学习人工智能 05:用 U-Net 模型进行图像分割

原文:https://towardsdatascience.com/learn-ai-today-05-image-segmentation-with-u-net-models-800105e400d1?source=collection_archive---------18-----------------------

今天学 AI

面向实用深度学习的图像分割简介

丹尼尔·库切列夫Unsplash 上的照片。

这是 学艾今日 系列的第 5 个故事!如果你还没有,一定要检查以前的故事。

你将从这个故事中学到什么:

  • 图像分割的意义和一些实际应用。
  • 用于图像分割的 U-Net 体系结构。
  • 如何使用 fastai 库训练 U-Net 模型标注街景数据?
  • 如何使用基于预训练 ResNet34 的 fastai U-Net 类模型?

什么是图像分割

图像分割是一个计算机视觉问题,其中给定一些输入图像,你的任务是识别图像中每个像素的类别。一个常见的应用是标记街景图像/视频,以便在自动驾驶汽车中使用。正如您在下图中看到的,输入(左)是一张常规图片,输出(右)中叠加的标签对应于几个类别,包括人、车道标志、建筑物、天空等等。

图 0。来自 CamVid 数据集的街景样本。

除了街景图像,图像分割的一些常见应用包括:

  • 生物医学图像分割(X 射线、MRI 等)以识别异常并帮助医生进行医疗诊断。
  • 卫星图像分割,以确定土地覆盖,烧毁地区,街道,房屋,云,水体,作物健康,任何你能想象到的。

U-Net 模型架构

U-Net 是用于图像分割任务的非常常见的模型架构。早在 2015 年,它就在一篇展望生物医学图像分割的科学论文中被提出,但很快成为任何图像分割问题的主要选择之一。

图一。U-Net 架构。图片来自原学术论文

U-Net 这个名字直观地来自图 1 中模型图的 U 形结构。

  • 左侧(编码器)具有图像分类模型的典型结构,其中卷积层插入逐渐降低图像维度的最大池层。
  • 右侧(解码器)是一种相反的情况——一组卷积运算和放大,然后将特征图恢复到原始大小。(图中的输出尺寸比输入尺寸稍小,但现在通常的做法是输入和输出尺寸相同)。
  • U-Net 架构的一个非常重要的特征是,在模型的解码器部分,输入不仅是来自前一层的特征图(图中的绿色箭头),还来自编码器上的相应模块(图中的灰色箭头)。这确保了没有空间信息由于图像尺寸的压缩而丢失。

编写一个基本的 U-Net

让我们根据图 1 中的图表开始用 Pytorch 编写一个基本的 U-Net。为了使代码更简单、更清晰,我们可以定义几个模块,从仅仅是 2d 卷积层的 ConvLayer 开始,然后是 2d 批处理规范化和 ReLU 激活。请注意,在卷积层中,偏差被设置为假,因为后面的批范数已经有一个偏差项。

定义 ConvLayer 模块。

接下来,让我们定义 ConvBlock ,这将对应于上面定义的一组 2 个 ConvLayers,然后是将图像大小减半的 max-pooling。

定义 ConvBlock 模块。

注意:我把 ConvLayer 和 ConvBlock 定义为 nn 的子类。顺序。这就是为什么没有 forward 方法,因为它必须在创建 nn 的子类时发生。模块。我从 fastai 的课程中借鉴了这个想法:-)另外,请注意 fastai 库已经实现了更完整版本的 ConvLayer 和 ConvBlock(带有额外的选项)。

转到解码器,每个模块需要两个输入,一个对应于 U-Net 图(图 1)中的绿色箭头,另一个对应于灰色箭头。

  • 绿色箭头对应于放大,因此对第一个输入(下面代码中的 x1)应用了内核大小为 2、步长为 2 的 2d 转置卷积。这使得输出的大小是输入的两倍。(如果你想了解更多关于卷积的知识,请查看这个故事)。
  • 然后,升级后的特征映射(下面代码中的 x_up)与来自编码器的输入(下面代码中的 x2)连接在一起。
  • 最后,应用两个转换器,结束我们的上变频模块

定义上变频模块。

就是这样!有了三个各有几行代码的模块,我们现在就有了创建 U-Net 的基础了!

下面的代码定义了 U-Net 模型,你可以看到我们有 5 个编码器模块和 5 个解码器模块。我在注释中加入了每个特征图的形状,以输入张量的大小开始:批量大小 x 3 x 128 x 128。

花些时间看看这些数字,并确保您理解计算是如何工作的,以获得与输入图像大小相同的最终输出。

定义 UNet 模型。

现在是将这一模式付诸实践的时候了!

训练基本的 U-Net 模型

Fastai 使这项任务变得非常简单。下面的代码是你在 CamVid 数据集上训练模型达到 0.87 精度所需要的全部!(为了简单起见,省略了损耗和度量的代码,但是完整的代码可以在这个 Kaggle 内核中找到)。

  • 在第 1 行中,数据被下载并解压缩。
  • 在第 2 行中,我们读取每个类别的标签名称。
  • 在第 3–8 行,创建了数据加载器,包括图像放大和调整到 256x384 图像大小。
  • 在第 10 行中,我们创建了一个 UNet 模型的实例,它有 3 个输入通道,输出通道的数量等于类的数量。然后我们用。cuda()。
  • 在第 11 行中,我们创建了 fastai 学习器对象,它将数据加载器、模型、损失函数、优化器和指标放在一起。
  • 最后,在第 13 行,我们调用 fit_one_cycle 对模型进行 12 个历元的训练,最大学习速率为 3e-3,权重衰减为 1e-2。注意 fit_one_cycle 以低学习率开始,然后增加到最大学习率,然后按照余弦退火学习率计划逐渐降低。

用于训练我们之前定义的 UNet 模型的代码。这段代码的一部分来自 CamVid 上的 fastai 课程笔记本

我们现在可以将模型预测可视化(图 2,中间一栏),并将它们与目标(右栏)和输入图像(左栏)进行比较。请注意,像天空、建筑物、树木和街道这样的大特征大多都被很好地识别出来。然而,对于一些较小的特征来说,情况并非如此。这就是为什么像准确性这样的简单指标有时会产生误导。

图二。列分别表示输入图像、模型预测和目标。每行对应于验证集中的不同样本。

火车 fastai U-Net (ResNet34)型号

当然,fastai library 已经提供了一个更现代的 U-Net 版本,它使用一个分类模型(如 ResNet34)作为编码器,并根据 Imagenet 数据进行了预训练。是的,下面几行是你训练这个新模型所需要的,从只训练解码器开始,然后解冻所有层,以较低的学习速率进行下一个周期的训练。

如图 3 所示,结果要好得多!

图 3。如图 2 所示,但用于带有 ResNet34 编码器的 fastai U-Net。

结束语

今日学 AI系列第五个故事到此结束!

欢迎在评论中给我一些反馈。你觉得什么最有用,或者什么可以解释得更好?让我知道!

你可以在下面的故事中了解更多关于我的深度学习之旅!

感谢阅读!祝您愉快!

使用 Python 解释器学习计算机视觉

原文:https://towardsdatascience.com/learn-computer-vision-using-the-python-interpreter-8cfb79041adb?source=collection_archive---------47-----------------------

在终端中玩语义分割

使用语义分段将微笑女子的原始背景替换为山脉的图像。原图:迈克尔·达姆Unsplash 拍摄的照片

如果您和我一样,在构建应用程序时,喜欢打开 Python 解释器,在终端中尝试函数或使用新的数据结构。对于内置模块来说,这是非常容易的,但是对于外部包来说,这可能会变得稍微复杂一些,尤其是对于处理计算机视觉模型输出来说!我制作这个教程是为了帮助提供一个在计算机视觉应用中使用语义分割的基础。您可以使用相同的通用技术来处理其他计算机视觉模型输出:对象检测、关键点和图像分类。

注:你可以在Unsplash上找到免费的图片,女人的图片来自那里,山的图片(如下图)来自那里。本教程中的所有其他图像都是我自己生成的,在这些原始图像上使用了图像分割。

一些背景

本教程使用了一套由 alwaysAI 提供的免费计算机视觉工具,这是一个基于 Python 的平台,用于构建和运行计算机视觉应用程序,我是该平台的成员。如果您不想使用该工具,您仍然可以参考本文中更通用的 NumPy 操作!

alwaysAI 编写了一个 Python API ,名为 edgeiq,使处理计算机视觉模型输出成为一个更加标准化和简单的过程,并且包含了许多流行的包,所以你不需要单独安装它们。我们将介绍如何从命令行与 edgeiq 和其他有用的计算机视觉模块交互,如 OpenCV 的 cv2。这对于逐步执行分段掩码的不同操作和查看输出非常有用。

这篇博文是在演示了下面嵌入的 YouTube 视频中的一些语义分割应用程序之后发表的,目的是在进入更一般的应用程序之前提供一个更好的基础。本教程将展示如何一步一步地用语义分割替换图像的部分。

本教程中使用的部分代码演示。

该视频介绍了几个语义分段应用程序,这两个应用程序的完整代码可以在 GitHub 上找到:

  1. 原虚拟绿屏储存库
  2. 一个应用程序,通过运行语义分割平滑返回的边缘

这些库向您展示了如何使用语义分割结果来替换一个图像中与另一个图像中的标签相对应的像素,以及如何使用 numpy 数组操作和其他技术来创建更平滑的边缘。

建立

注意,你必须在你的本地机器上安装 alwaysAI 来使用 API 并完成本教程。你可以从 alwaysAI 仪表盘免费下载 alwaysAI。或者,如果你喜欢,就按照 NumPy 操作!

安装 alwaysAI 后,让我们来设置您的环境。您需要配置和安装任何使用语义分段模型的应用程序;所以使用上面的任何一个库,或者任何一个使用语义分割的入门应用都可以。您可以通过在终端中键入aai get-starter-apps来获得启动应用程序;此命令会将初学者应用程序下载到您当前的工作目录中。然后,您可以使用ls查看所有的启动应用程序,然后使用cd导航到“semantic _ segmentation _ cityscape”目录或“semantic_segmentation_voc”目录。

选择您的应用程序,并从工作目录中运行

aai app configure

您应该为目录选择您的本地机器。接下来,运行

aai app install

该命令构建了虚拟环境,其中包含 alwaysAI API、edgeiq 以及 OpenCV、cv2 中流行的开源计算机视觉库。如果你想使用任何其他的包,只需将它们添加到 app 目录下的一个requirements.txt文件中,然后重新运行aai app install

接下来,通过运行以下命令激活 python 虚拟环境,该环境将安装所有必需的包

source venv/bin/activate

最后,通过运行以下命令启动 python 终端

python3

您应该看到终端变成了 python 解释器,它有如下提示

>>>

注意:完成后,您可以通过键入 *exit()* 退出 Python,然后在终端中键入 *deactivate* 退出虚拟环境。

现在,您已经准备好学习本教程了!

笔记

  • 您可以使用type(variable)来检查 python 中输出的类型
  • 您可以尝试使用以下代码查看图像,尽管我在虚拟环境和 python 解释器中遇到了问题:
def display(image):
    cv2.imshow("image", image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

这将创建一个函数,您可以使用display(image)调用该函数来显示任何图像。我在关闭窗口时遇到了麻烦,但你可以按任意键,然后回到终端,尽管显示窗口可能会保持打开。

  • 另一个解决方案是像这样写出图像:
cv2.imwrite("test1.png", image)

任何时候你想看到一个步骤的输出,我建议写出一个图像,这就是本教程要做的。

辅导的

我将在下面的代码中拼接一些图像和文本,但是您仍然可以将代码文本复制粘贴到您的终端中来完成本教程。以下大部分代码摘自虚拟绿屏库

首先,我们需要导入必要的库。

import edgeiq
import cv2
import numpy as np
import sys

alwaysAI API,edgeiq,是我们用来进行语义分割的。我们将使用 OpenCV 的库 cv2 来写入和输出图像。Numpy 用于一些数组操作,sys 用于更改 numpy 数组的显示格式。

# use this if you want to see the entire numpy array (not very user 
# friendly, but can be helpful to seeing what labels are used)
np.set_printoptions(threshold=sys.maxsize)

在你的工作目录中你需要一个图像,我把我的命名为‘output . png’。我刚刚从 Unsplash 得到一张图片。

照片由迈克尔·达姆Unsplash 拍摄

下面的代码读入一个图像,然后使用 edgeiq 创建一个SemanticSegmentation对象的实例,并指定在哪个推理引擎上运行输入。在第三个块中,它从输入图像中获得分割结果。

# read in the image
image = cv2.imread("output.jpg")# instantiate a semantic segmentation object and load the engine
semantic_segmentation = edgeiq.SemanticSegmentation("alwaysai/fcn_alexnet_pascal_voc")
semantic_segmentation.load(engine=edgeiq.Engine.DNN)# run segmentation and get the results
segmentation_results = semantic_segmentation.segment_image(image)# to view the class_map of the resulting segmentation_results object:
segmentation_results.class_map

上述代码块中的最后一行代码产生以下输出(在重置显示选项之前运行,以用于本教程):

数组([[ 0,0,0,…,0,0,0],
[ 0,0,0,…,0,0,0],
[ 0,0,0,…,0,0,0],【T9…,
[ 0,0,0,…,11,11,11],
[ 0,0,0,…,11,11,11],
[ 0,0,0,…,11,11]

我们还可以用下面的代码写出这个类别映射的样子:

# to write out an image of the class map (note, the class_map is a numpy array!)
cv2.imwrite("class_map.png", segmentation_results.class_map)

使用微笑女人的原始图像生成的语义分割掩模。

注意,这有点难以看出,但是在教程的后面还有一个例子会更明显一些。

# get a label map, which is the same dimensions as the class map but # uses labels
label_map = np.array(semantic_segmentation.labels)[segmentation_results.class_map]

上述代码产生以下输出:

数组([['背景','背景',,…,'背景',

背景','背景'],

['背景','背景','背景',…,'背景',

背景','背景'],

['背景','背景','背景',…,'背景',

背景','背景'],

…,

['背景','背景','背景',…,' diningtable ',

diningtable ',' diningtable'],

['背景','背景','背景',…,' diningtable ',

diningtable ',' diningtable'],

['背景','背景','背景',…,' diningtable ',

' diningtable ',' diningtable']],dtype = '

Now we’ll start building a mask that just has our desired labels in it.

# First just make a numpy array that is the same shape as the class # map but just zeros
filtered_class_map = np.zeros(segmentation_results.class_map.shape).astype(int)# print the filtered class map
filtered_class_map

This yields the following:

array([[0, 0, 0, …, 0, 0, 0],

[0, 0, 0, …, 0, 0, 0],

[0, 0, 0, …, 0, 0, 0],

…,

[0, 0, 0, …, 0, 0, 0],

[0, 0, 0, …, 0, 0, 0],

[0, 0, 0, …, 0, 0, 0]])

And, just to show how the ‘type’ command works, we can check the type of the output like so:

type(filtered_class_map)

Which yields:

这里是当前 filtered_class_map 的样子(不要紧张,现在都是黑色的!):

# you can add labels here if you want to pick up more labels, 
# check out what you get from the 
# label_map print out to see what is being picked up 
# around the person
labels_to_mask = ['person']# now toggle the cells that mapped to ‘person’
for label in labels_to_mask:
    filtered_class_map += segmentation_results.class_map * (label_map == label).astype(int)# Print out the map
filtered_class_map# Now, If we write out the image
cv2.imwrite(“new_filtered_class_map.png”, filtered_class_map)

同样,这个输出是模糊的,但是它与 class_map 输出略有不同:

您还可以查看我们使用过的所有地图的尺寸:

image.shape
label_map.shape
filtered_class_map.shape

对于我的输入图像的结果,上面的代码分别产生(960,640,3),(960,640),(960,640)。请注意,它们的大小都一样!第一个元组中的“3”表示深度为三,用于 BGR(或 RGB)颜色通道。

# Now we can make a map to pull out just the 
# labels of interest (i.e. people)
detection_map = (filtered_class_map != 0)

示例输出:

数组([[假,假,假,…,假,假,假],

[假,假,假,…,假,假,假],

[假,假,假,…,假,假,假],

…,

[假,假,假,…,假,假,假],

[假,假,假,…,假,假,假],

[假,假,假,…,假,假,假]])

我们还可以通过运行以下命令来检查 detection_map 的形状

detection_map.shape

示例输出:

(960, 640)

现在我们将选择一个背景图像。请注意,您可以在 GitHub 资源库中找到一些图片示例!下载其中一个,并在下面的示例命令中指定您选择的任何名称。

# Read in an image for your background. I found a picture of a mountain on Unsplash.
background = cv2.imread("mountain_pic.jpg")

我们将使用这张山的图片作为我们的新背景!照片由来自佩克斯蒂姆·高拍摄

每当我们使用一个新的图像,它必须是相同的形状!所以我们可以用

shape = image.shape[:2]
background = edgeiq.resize(background, shape[1], shape[0], keep_scale=False)

请注意,由于背景是水平的,输入图像是垂直的,我们将不得不使用' keep_scale=False ',这将扭曲图像一点。你也可以为你的背景选择一个垂直的图像,或者如果你的流/输入图像是水平的,保持它不变。

最后,我们用原始图像替换背景中对应于检测图中“真实”部分的区域

background[detection_map] = image[detection_map].copy()# And finally write out the new image!
cv2.imwrite("final_background.png", background)

保留了带有“人”标签的原始图像,所有其他图像都替换为山的图像。

现在,只有原始图像中被标记为“人”的部分被用来替换背景中的相应部分。这是一个(粗略的)虚拟绿屏例子!

接下来,我们将看到更多分段遮罩的例子,包括一些模糊。

让我们更改标签颜色,使蒙版更容易查看。

# iterate over all the desired items to identify, 
# labeling those white
for label in labels_to_mask:
    index = semantic_segmentation.labels.index(label)
    semantic_segmentation.colors[index] = (255,255,255)# build a new mask, and write a new image
new_mask = semantic_segmentation.build_image_mask(segmentation_results.class_map)
cv2.imwrite("new_mask.png", new_mask)

这是输出:

现在,对应于“人”的像素是白色的。

现在我们有了这个更容易看到的面具,让我们做一些图像操作。如果我们想模糊背景,我们可以这样做:

# Create a blurred mask
blurred_mask = cv2.blur(new_mask, (100, 100))
cv2.imwrite("blurred.png", blurred_mask)

这会创建以下图像:

与之前显示的图像相同,但边缘模糊。

如果我们只想让标签变成白色,其他的都变成黑色,执行下面的代码并重新运行上面的 for 循环:

# this makes all the colors in the label map black
semantic_segmentation.colors = [ (0,0,0) for i in semantic_segmentation.colors]

运行 for 循环后,重新构建掩码并写出输出,结果是:

现在,只有人的像素是白色的,其他所有标签都是黑色的。

现在我们有了如何使用和操作蒙版的想法,让我们使用这些技术来平滑这些边缘,并创建一个更具视觉吸引力的虚拟绿色屏幕。本教程的下一部分将使用来自以下资源库的代码:【https://github.com/alwaysai/smooth-semantic-segmentation】T4。

我们正在处理的图像与上面显示的图像相同。但是,如果您想确保设置正确,可以重新运行以下代码:

# read in the initial image again
image = cv2.imread("output.jpg")# build the color mask, making all colors the same except for background
semantic_segmentation.colors = [ (0,0,0) for i in semantic_segmentation.colors]# iterate over all the desired items to identify, labeling those white
for label in labels_to_mask:
   index = semantic_segmentation.labels.index(label)
   semantic_segmentation.colors[index] = (255,255,255)# build the color mask
mask = semantic_segmentation.build_image_mask(results.class_map)

首先,我们将从放大扩张蒙版开始(平滑边缘报告中的第 95 行)。

dilatation_size = 15
dilatation_type = cv2.MORPH_CROSS
element = cv.getStructuringElement(
                        dilatation_type,
                        (2*dilatation_size + 1, 2*dilatation_size+1),
                        (dilatation_size, dilatation_size))
mask = cv2.dilate(mask, element)

现在面具看起来像:

现在,图像已经有一个扩大应用到人的面具。

接下来,我们将平滑应用到遮罩:

mask = cv2.blur(mask, (50, 50))

现在面具看起来像这样:

应用于遮罩的平滑(模糊)。

接下来,我们将设置背景图像。为了安全起见,我们将重新导入它并运行调整代码。

# Also import the background image again
background = cv.imread("mountain_pic.jpg")
background = edgeiq.resize(background, image.shape[1],
image.shape[0], keep_scale=False)

最后,我们将使用 edgeiq 内置的“覆盖”功能。这将使用模糊的面具,前景图像和背景图像,并交织他们,以提供良好的,平滑的边缘。

# Now overlay the background and foreground using the overlay function
frame = edgeiq.overlay_image(frame, background, mask)
cv.imwrite("overlayed_frame.png", frame)

这是结果输出:

现在背景从原来的女人换成了山。

现在,注意到女人的中间部分是树吗?这些看起来像是对应于我们创建的原始类别映射的红色部分。如果我们查看label_map输出,我们会看到diningtablesofa是打印出来的其他标签。这有点像黑客,但是让我们把这些添加到labels_to_mask中,并重新运行上面平滑边缘部分的所有代码。

现在输出如下所示:

使用不同的标签,我们填补了女人的空白。

好多了!

我希望这篇教程对你有所帮助。我们讲述了如何在终端内与 edgeiq 和 cv2 交互,如何使用分段掩码,以及如何使用这些掩码替换图像的特定部分。这将使您能够使用语义分割模型。我们还介绍了如何平滑来自更粗粒度分段模型的输出,当粗粒度分段模型是唯一可用的分段模型,或者是唯一最适合您的特定用例的模型时,这将有助于您改进您的应用程序。

注册一个免费的 alwaysAI 帐户可以让你访问不同的计算机视觉模型类型,因此你可以使用 Python 解释器来探索物体检测、图像分类和姿态估计!

立即学习数据科学:条件概率

原文:https://towardsdatascience.com/learn-data-science-now-conditional-probability-acae6ec7b474?source=collection_archive---------23-----------------------

机器学习中的吉娃娃、松饼和混淆矩阵

艾丽西娅·高蒂耶在 Unsplash 上拍摄的照片

条件概率是概率和统计中的基本概念之一,通过扩展,也是数据科学和机器学习中的基本概念之一。

事实上,我们可以使用混淆矩阵来思考机器学习模型的性能,混淆矩阵可以使用条件概率的观点来解释。

在这篇博客文章中,我们将涵盖所有这些,甚至更多

  1. 介绍
  2. 条件概率的形式定义
  3. 直觉到条件概率:走向新的宇宙
  4. 机器学习中的条件概率与混淆矩阵
  5. 如何学习更多的概率

让我们开始吧。

条件概率介绍

条件概率是一种基于部分信息对实验结果进行推理的方法。

在不使用任何公式的情况下,我们试着用一个例子直观地理解条件概率。

问题:你掷出一个六面骰子。你的朋友看着这个卷,告诉你这个卷是偶数。有多大可能是 6?

Lea bhmUnsplash 上拍摄的照片

在你的朋友看掷骰子之前,掷骰子有 6 种可能的结果(1,2,3,4,5,6)

当你的朋友告诉你掷骰子是偶数时,我们只剩下 3 种可能的结果——2,4,6。

因此,在三种可能的情况中,其中一种是我们掷出 6。假设掷骰子是一个事件数,掷出 6 的概率是 1/3。

条件概率形式定义

我们现在可以寻求将这种直觉形式化。

我们现在可以说,如果所有的结果都是同样可能的,就像上面掷骰子的情况一样,我们可以说

进一步概括,我们可以说

有了这个概念,我们也可以寻求回答以下问题—

(b)你是一个密码黑客。您的高级黑客技能告诉您,迈克尔的电子邮件密码有 8 个小写字母。如果所有的密码组合都是可能的,那么密码是‘密码’的几率是多少?

(c)如果一个人的艾滋病毒检测呈阴性,那么这个人感染艾滋病毒的可能性有多大?

(d)你建立了一个机器学习模型来对吉娃娃和松饼的图片进行分类。你的分类模型通知你图片 X 是吉娃娃的照片。模型出错的可能性有多大?

请注意,条件概率试图回答的问题的模式是“给定 X,求 Y 的概率”的形式。

条件概率直觉:走向新的宇宙

条件概率的一个直觉是,我们可以把条件概率看作一个新的宇宙 B 上的概率定律,因为所有的条件概率都集中在 B 上。

在解决条件概率问题 P(A|B)时,我们可以想象把自己传送到一个给定事件 B 肯定已经发生的世界,我们可以简单地在那个宇宙中寻找事件 A 的简单概率。

我们来比较两个场景。在这两种情况下,您都想侵入迈克尔的 Dunder Mifflin 邮件。默认情况下,密码的长度没有限制。

场景 A)在没有任何附加信息的情况下,迈克尔的密码是“1234”的可能性有多大?

在这种情况下,迈克尔的密码是 1234 的概率接近于零,甚至无限小。这是因为有无限的密码组合,1234 只是其中之一。

假设迈克尔的电子邮件密码只包含数字 1、2、3、4,那么密码是“1234”的可能性有多大?

在场景 B 中,我们可以想象我们进入了一个所有电子邮件密码都必须是 4 个字符并且包含 1、2、3 和 4 的世界。现在,在这个世界上,我们问自己,这 4 个数排列成 1234 序列的概率是多少?

在这个世界上,密码只能是 1234,1243,1342,1324,1423,1432,2134,…,4321 中 24 种组合中的一种

因此,条件概率是 1/24。

有了这样的直觉,我们可以更轻松地解决简单的问题,而不需要求助于无脑的数学。

机器学习中的条件概率与混淆矩阵

条件概率在评估机器学习模型的上下文中是有用的。我用一个例子来说明。

你建立了一个机器学习模型来对吉娃娃和松饼的图片进行分类。

吉娃娃 vs 松饼:可爱还是好吃?图片来自 ImageNet [1]

获得了以下结果。

现在,你给你的机器学习模型输入一张新图片。假设你的分类模型预测图片 X 是一张吉娃娃的照片,那么这张照片实际上是吉娃娃照片的可能性有多大?从数学上来说,这可以解释为

答案是 3/4。我们怎么知道的?让我们一步一步来找答案。

  1. 既然模型预测了“吉娃娃”,我们将只关注黄色突出显示的列,而忽略另一列。换句话说,我们把自己传送到一个“新的宇宙”,在那里模型只能预测照片是一只吉娃娃。
  2. 在这个新的宇宙中,该模型总共做出了 600 次预测。
  3. 在 600 个预测中,450 个是正确的,而 150 个是错误的。
  4. 于是,条件概率为 450/600,简化为 3/4。

你看到的是一个混淆矩阵,常用于机器学习。直观地说,混淆矩阵是一个表格,它告诉我们你的模型在被训练后表现得有多好。

更具体地说,混淆矩阵是一个具有两行和两列的表格,报告假阳性、假阴性、真阳性和真阴性的数量,如上所述。

理解混淆矩阵及其相关度量需要理解条件概率。

实际上,我们刚刚计算的是一个叫做精度的度量。事实上,精度和其他一些度量标准也是如此。

你能使用上表计算召回率和特异性吗?

结论

条件概率是我们对不同条件下的不确定性进行逻辑量化的一种方式。它是数据科学家工具箱中的一个重要工具。如果你真的想成为一个好数据,一定要掌握它。这里我提供一些我推荐的资源。

对于也想学习编程和编码的新学员HarvardX 的 Data Science-Probability(ph 125.3 x)on Data camp*将温和地介绍概率,同时允许您在 r 中实现概率。此外,这还附带了一个关于 2007-08 年金融危机的激励性案例研究,这可能是一个您可以进一步研究和展示您的投资组合的项目。

对于进阶学习者,我建议参加 HarvardX Stat 110:概率入门 *。这个班是迄今为止我参加过的最有收获的一个班。布利茨坦教授是我最喜欢的概率教授之一,他严谨而直观地讲述了这些话题。

这里还有一份我写的完整指南—

此外,如果您有任何问题,或者只是想一起学习数据科学,请随时与我联系。

https://www.linkedin.com/in/travistang/ [## Travis Tang -数据分析师

www.linkedin.com](https://www.linkedin.com/in/travistang/)

这是概率系列的一部分。这是一个很小的数据科学,你现在可以在 5 分钟内学会。

  1. 概率模型和公理
  2. 概率 vs 统计
  3. 条件概率(你来了!)
  4. 贝叶斯统计(即将推出)
  5. 离散概率分布(即将推出)
  6. 连续概率分布(即将推出)
  7. 平均值和大数定律(即将推出)
  8. 中心极限定理(即将推出)
  9. 联合发行(即将推出)
  10. 马尔可夫链(即将推出)

参考文献和脚注

[1]邓俊杰,董文伟,索彻,李,李,李,,李(2009).Imagenet:一个大规模分层图像数据库。2009 年 IEEE 计算机视觉和模式识别会议(第 248-255 页)。

*这些是我推荐的课程的附属链接。这意味着,如果你点击链接后购买,我会收到一定比例的费用,没有额外的费用给你。

学习不确定情况下的决策——第 1 部分:用平均值解决问题

原文:https://towardsdatascience.com/learn-decision-making-under-uncertainty-part-1-solve-the-problem-with-mean-values-368c35add0b7?source=collection_archive---------24-----------------------

使用 Python 和 PuLP 的随机规划来最大化种植作物的预期利润

让·维默林在 Unsplash 上拍摄的照片

介绍

许多决策问题可以作为线性方程组来解决。处理问题中的不确定性并不简单。在这一系列文章中,我们将探索在一个简单的业务问题上使用随机编程的概念。这是第一篇文章,介绍了构建一个模型的基本方法,该模型可以基于平均值解决问题。在我们能够处理不确定性之前,以这种方式对问题建模是很重要的。我们将用 python 来解决这个问题,使用一个开源的解算器,它拥有这些算法。

在以后的文章中,我们将改变这个模型来考虑不确定性,并改进我们在这里找到的解决方案。

先决条件

  • 线性方程
  • 概率,期望值

注:报摊问题是用来学习这个题目的另一个问题。媒体上已经有几篇文章了。这个农民问题提供了一个不同的视角,尤其是在未来被揭示后所做的决定。这个问题已经在教科书中解释过了(见下面的参考文献),但是要得到解决方案需要使用线性编程软件。使用 Python 可以更容易地试验和可视化解决方案,而无需安装新软件或获取许可证。

你将学到的技能

  • 用 Python 求解线性方程组
  • 使用 Python 计算任何解决方案的期望值,尤其是“平均值解决方案”
  • 解决方案的直观解释(可选)

商业问题

一位农民正在计划今年这个季节的作物。生产的庄稼将用来喂牛,直到明年。剩余的庄稼可以在公开市场上出售。

“作者形象”——农民流程步骤

农民必须决定每种作物的种植面积。她共有 500 英亩农场可供使用。每种作物的种植成本如下表所示。给出了每种作物的平均产量。在不好的季节产量只有 80%,在好的季节产量增加到 120%。这几种情况发生的概率是相等的(33%)。每种作物的平均产量如下表所示。

当生长季节结束时,农民根据产量知道农场生产了多少作物。为了满足农场直到下一季的消费需求,农民也可以在公开市场上购买农作物(只有小麦和玉米)。多余的庄稼可以卖到市场上。请注意,农场并不需要大豆,但可以种植到 6000 吨并获得丰厚利润,6000 吨以上价格更低。

“作者图片”——产量、成本和售价

用线性规划模型求解平均收益率问题

我们有足够的信息来解决这个问题吗?我们的收益率是多少?让我们假设我们的产量是平均的,并尝试规划分配给每种作物的英亩数。这是一个非常合理的方法,因为它既考虑了不良收益率,也考虑了良好收益率。许多线性和混合 inter 编程模型正在被构建,以使用这种方法来解决业务问题。

我们将通过使用线性方程组来解决这个问题。我会推荐一步一步的运行笔记本来了解以下内容。

决策变量:

农民要做几个决定。我们可以认为决策是在两个阶段做出的——产量已知之前和产量已知之后。因此,像这样的问题被称为两阶段随机规划问题。然而,对于这个问题,就像报童问题一样,第二阶段的决策是微不足道的(不要购买超过我们养牛所需的作物,出售所有剩余的数量)。

  • 每种作物的种植面积(第一阶段)
  • 小麦和玉米的购买量(第二阶段)
  • 小麦、玉米和豆类的销售金额(第二阶段)
  • 以较低价格出售的多余豆量(第二阶段)

目标:

农场主希望我们在季末实现利润最大化。我们从出售牛消费后剩余的作物中获得收入。我们产生的成本来自季节前的种植成本和购买小麦和玉米来喂养牲畜。

利润最大化=

季末作物销售收入—购买小麦和玉米的成本赤字—种植作物的成本

M = LpProblem("Farmer", LpMaximize)M += lpSum( 
      [      selling_prices[item]       * var_tons_sold[item]        for item in items ]
    + [      selling_price_excess_beans * var_excess_beans_sold]     #excess beans
    + [ -1 * planting_costs[item]       * var_acres_planted[item]    for item in items ]  
    + [ -1 * purchase_prices[item]      * var_tons_purchased[item]   for item in purchasable_items ]    
)

约束:

农场可用英亩数

所有作物的种植面积≤ 500 英亩

M += lpSum([var_acres_planted[item] for item in items]) <= total_acres

对于小麦和玉米:

种植生产的作物+购买的作物=用于消费的作物+出售给市场的作物

M += lpSum([yields[item] * var_acres_planted[item]] + [var_tons_purchased[item]] + [-1 * var_tons_sold[item]]) == consumption_feed[item]

对于豆子:

  • 种植生产的作物-以正常价格出售给市场的作物-以较低价格出售给市场的作物=豆类消费(我们的农民为 0)
  • 以正常价格出售给市场的作物≤ 6000 吨
M += lpSum([yields[item] * var_acres_planted[item]] + [-1 * var_tons_sold[item]] + [-1 * var_excess_beans_sold]) == consumption_feed[item]  

M += lpSum([var_tons_sold[item]]) <= limit_on_beans_regular_price

用 Python 求解模型

照片由丹尼尔·里卡洛斯Unsplash 上拍摄

该方程组可以在任何线性规划求解器中求解。尽管 Excel 有插件,但建模语言更容易使用,而且对于解决这个问题的随机版本是必要的。商业解决方案(IBM CPLEX、Gurobi、FICO Xpress、AMPL 等。)可用于此目的,但它们需要安装。一些商业解算器有 python APIs,但是它们需要许可。对于具有更好性能和客户支持的生产系统,商业解决方案可能是更好的选择。出于学习的目的,我选择了开源 Python 包 PuLP,允许任何人以最小的安装运行笔记本。

笔记本可以在这里找到。请使用 conda 或 pip 安装 pip。

pip install pulp

我们可以运行求解器并获得最优解,然后使用 python 计算下表来计算成本、收入和利润。 解决的办法是种植豆子以更高的价格卖出 6000 吨,生产足够喂牛的玉米,用剩下的几亩地生产小麦。

“按作者分类的图像”——最佳解决方案

如果产量不同,农民会有什么变化?

我们已经知道从最优解到平均收益率的平均收益率(118600)的利润(见上表)。

如果产量不好,并且我们已经根据平均产量的解决方案进行了种植,我们将实现以下结果。(不需要做出真正的决定——在这种情况下,我们必须购买赤字 48,并出售剩余的赤字)

“按作者分类的图像”——当产量很低时,使用一般情况下的解决方案(120,80,300)获利

同样,如果我们实现了良好的收益,我们可以计算利润

“按作者分类的图像”——当产量很低时,使用一般情况下的解决方案(120,80,300)获利

如果农民决定根据平均产量实施我们的建议,她将在 33%的时间里获得 118600 英镑的最优利润,但也会获得 55120 英镑和 148000 英镑的利润。从长远来看,她的预期利润可以计算如下(在 99 个赛季中,他将实现每个利润 33 次)。

均值解的 EV =(55120+118600+148000)/3 = $ 107240

请注意,这比我们希望的要低(118600 美元)。这是因为我们是基于平均收益率进行规划的——我们在好年景获得的利润无法弥补坏年景的利润损失。

使用笔记本进行实验

使用笔记本探索解决方案在以下场景中会如何变化。

  • 如果用其他收益率代替平均收益率,最优解是什么?(提示:使用笔记本更改产量)。
  • 如果农民有一个乐观或悲观的偏见,并希望我们使用使用坏或好产量找到的最佳解决方案,使用这些解决方案的预期价值是什么?它们与使用平均值解决方案相比如何?对照下表检查你的答案。对于这个例子,看起来一个乐观的农民想要使用我们的基于好产量的解决方案会比使用平均产量做得更好。请注意,我们的平均值解决方案是接近的。

“作者图像”——三种场景下的最优解

  • 我们可以同时使用所有三个最优解吗?由于我们不知道哪个季节会有哪个产量,所以只有在我们能够聘请一位能够 100%准确预测产量的甲骨文或机器学习专家的情况下,我们才能做到这一点。我们可以计算这种方法的期望值,这样我们就可以建立利润的上限。在本例中,它是 1/3(59950+118600+167666)= $ 115406。因此,我们的平均值解决方案表现良好(107240 美元),但仍有改进的空间。如果农民对 8166 美元的增长不太兴奋,我们就不需要投入更多的精力来提高利润。
  • 有没有一个解决方案能使我们的预期利润最大化,不是针对一个给定的收益率,而是同时针对所有三个收益率?是的,有,该解决方案的利润应该在 107240 美元到 115406 美元之间。我们将在下一篇文章中讨论这个问题。

结论

  • 我们已经将商业问题建模为线性方程组
  • 我们使用 Python 和 Pulp 获得了一个基于一般场景的解决方案。这个笔记本可以用来评估所有参数之间的权衡。
  • 即使发生其他情况,我们也知道该解决方案的预期价值。这将是我们试图通过在线性程序中添加随机元素来击败的基准。
  • 了解了不同的解决方案在三种不同场景下的表现后,我们就可以从线性规划转向随机规划了。

照片由 Unsplash 上的 Ugne Vasyliute 拍摄

参考

我将把我的参考资料限制在解释基础知识和涉及这个问题的资源上。

[1] J .林德洛特,课堂笔记涵盖了这个问题。附加注释

[2] J. Birge,F. Louveaux,教科书:随机规划介绍 —这个问题在第 1 章中有所涉及。

[3]Python 中的纸浆解算器的官方网站

思考的食粮——尝试用直觉解决问题(可选练习)

杰克·杨Unsplash 上拍摄的照片

阅读这一部分只是为了获得权衡的直觉。像这样的方法在存在复杂约束的情况下不能保证最优。此外,一旦我们开始做随机规划,这种方法是不可能的。

我们是否可以采取贪婪的方法,将每一英亩土地分配给一种能给我们带来最大利润的作物,直到我们遇到一个约束?

让我们计算一下每种作物每英亩的利润。因为我们计划的是平均情况,所以我们将使用平均收益率。

小麦是每英亩 2.5 * 170 -150 = 275 美元
同样,玉米是 220 美元,豆类是 460 美元(正常价格)和-60 美元(降价)。

然而,对于小麦和玉米,在我们满足农场需求之前,利润来自于农民避免以高得多的价格购买而节省的成本。换句话说,在满足消费需求之前,他可以通过卖给自己(以买方价格)来增加利润。小麦是 2.5 * 238–150 = 445,玉米是 400。在我们能够满足农场的消费之前,这些数字非常重要。

算法:

按递减顺序排列边际利润:460(出售豆类),445(生产小麦以满足需求),400(生产玉米以满足需求),275(生产小麦以出售),220(生产玉米以出售),-60(生产豆类以低价出售)

对每个利润率执行这些步骤,直到农田被消耗或利润率消失。

  1. 使用 300 英亩土地生产豆子,直到边际利润在 6000 单位时消失。剩余英亩数= 200
  2. 用 80 英亩土地生产小麦以满足农场的需求。剩余英亩数= 120
  3. 用 80 英亩的土地生产玉米来满足农场的需求。剩余英亩数= 40
  4. 用 40 英亩的土地生产小麦并销往市场。剩余英亩数= 0

这给了我们答案:小麦 120 英亩,玉米 80 英亩,豆类 300 英亩。

事实证明,我们的直觉解决方案确实是最优的,因为没有其他复杂的约束。

注意:为了理解这种方法背后的直觉,试着改变一级和二级咖啡豆的销售价格。

豆类的边际利润与消费小麦和玉米的边际利润匹配时,有两个拐点= 33 和 35.25(提示:你可以通过求解简单的方程很容易地计算出来)。在价格低于 33 美元时,我们应该先生产小麦和玉米,然后再生产大豆出售。

有几个拐点,豆子的边际利润与 24 美元和 26.75 美元的玉米产量相当。在低于 24 美元的价格下,我们应该首先生产小麦和玉米用于消费,然后销售,然后我们只生产豆类用于销售。

在我的媒体 个人资料 查看关于这个话题的新文章。如果你想联系我这里是我的LinkedIn

学习不确定情况下的决策——第 2 部分:解决随机问题

原文:https://towardsdatascience.com/learn-decision-making-under-uncertainty-part-2-solve-the-stochastic-problem-773767e96d33?source=collection_archive---------45-----------------------

学习使用 Python 最大化所有可能场景的预期价值

Unsplash 上的 Edge2Edge 媒体拍摄

第一部中,我们帮助一位农民探索了三种不同的种植方式。尽管我们基于平均收益率的决策相当有效,但我们发现为乐观收益率制定计划实际上更有效。但是我们必须确保我们没有忽略另一个可能更好的选择。一种方法是采用强力方法生成所有可能的种植方案,并计算每个方案的预期利润值(EV ),就像我们计算我们提出的 3 个方案的 EV 一样。如果我们允许分配英亩的真实值,可能的选项是无限的,因此这种方法是不可能的。如果将选择限制在 0 到 500 之间的整数选项,我们也许能够列举出这些选择,但是如果农民想要增加种植作物的限制,这是一个很难修改的方法。

我们实际上可以聪明地列举出所有可能的选项,而不需要使用蛮力方法。我们将强迫线性规划求解器为我们做那件事。

这本笔记本有很好的解释,你可以一步一步来。我建议在使用笔记本之前阅读下面的方法。

随机线性规划

让我们改写一下利润的等式。

利润= —种植作物的成本+季末作物销售收入—购买小麦和玉米的成本赤字

请注意,种植作物的成本仅取决于分配给每种作物的英亩数,而不取决于实现的产量。然而,销售的收入和购买作物的成本取决于产量。

到目前为止,我们已经尝试在假设收益率的情况下决定买入和卖出的数量,然后计算三种情况下的预期价值。然而,我们必须解决三个独立的线性规划。如果我们把三个线性程序合并成一个呢?这就是随机规划的本质——我们通过评估所有可能场景的预期利润值来动态寻找最佳的第一阶段决策

这个提法叫做确定性等价问题 ( DEP )。

决策变量

请注意,我们被允许对每个场景的购买和销售做出三个不同的第二阶段决策(收益率在我们必须做出这些决策时实现)。然而,对于种植的英亩数,我们只能做出一个可能的第一阶段决策(如果我们被允许做出三英亩决策,这意味着我们有完美的信息)。换句话说,我们在各种情况下对冲第一阶段决策的影响。但是,我们不是手动计算我们决策的 EV,而是让线性程序为我们的英亩选择在所有可能的情况下最大化预期利润的值。

我们可以把决策变量分为两个阶段。

一组第一阶段变量,链接到每组第二阶段变量。这些与我们第一个用产量平均值求解的线性程序相同。

var_acres_planted = LpVariable.dicts("plant_acres", items, lowBound=0, cat='Continuous')

每种可能情况的几组第二阶段变量。请注意,当我们完成求解时,我们对第二阶段变量没有一个答案;我们有几个答案——每个场景一个。我们的代码可以通过添加场景作为每组变量的键来重用。

目标函数

第一阶段和第二阶段都对利润有贡献。然而,第二阶段的贡献取决于每个场景,因此我们必须考虑所有场景的期望值。

利润= —种植作物的成本+

1/3(季末作物销售收入——购买小麦和玉米的成本赤字),因为产量不佳+

平均产量+的 1/3(季末作物销售收入-购买小麦和玉米的成本赤字)

1/3(季末作物销售收入——购买小麦和玉米的成本赤字)用于高产

限制

我们可以把约束看作两组。

第一阶段约束

这些约束只影响第一阶段的决策。我们今天只有总英亩数约束,但该模型可以处理任何其他约束。这些与我们第一个用产量平均值求解的线性程序相同。

农场可用英亩数

所有作物的种植面积≤ 500 英亩

M += lpSum([var_acres_planted[i] **for** i **in** items]) <= total_acres

第二阶段约束

这些约束将每组第二阶段变量链接到第一阶段变量。请注意,我们知道这些约束条件中每一个的情况,因此所有的参数都随着情况的变化而变化,例如,当我们为与不良产出情况相关的变量编写约束条件时,我们知道产出是不良的)

小麦和玉米:

种植生产的作物+购买的作物=用于消费的作物+出售给市场的作物

对于豆子:

  • 种植生产的作物-以正常价格出售给市场的作物-以较低价格出售给市场的作物=豆类消费(我们的农民为 0)
  • 以正常价格出售给市场的作物≤ 6000 吨

用 Python 求解随机模型

Pakata GohUnsplash 上拍摄的照片

该方程组可以在任何线性规划求解器中求解。出于学习的目的,我选择了开源 Python 包 PuLP,它允许任何人以最小的安装运行代码。

笔记本可以在这里找到。请使用 conda 或 pip 安装纸浆。

pip install pulp

我们可以运行求解器并获得最优解,然后使用 python 计算下表来计算成本、收入和利润。解决方案如下。鉴于豆类的二级销售价格非常低,分配给豆类的英亩数是直观的,但玉米和小麦的选择却不是。一般来说,凭直觉找到这个解是非常困难的。

  • 种植大豆,确保我们永远不会低价出售大豆——250 英亩高产大豆可产 6000 吨。
  • 种植玉米以满足平均产量下的农场需求。
  • 在剩下的几英亩土地上种植小麦。

对于任何单个场景产量,该解决方案显然不能胜过该场景的最优解决方案(根据最优解决方案的定义)。但是它在三个可能场景中的期望值比三个解决方案(我们在第 1 部分中计算的 86600 美元、107240 美元、107683 美元)和任何可能的第一阶段解决方案都要好。我们解决的随机线性规划使这成为可能。

随机解决方案(VSS)的价值和交付的总价值

我们的竞争对手只懂线性规划,根据平均收益率做出合理的推荐。通过了解这种随机方法,我们给农民增加了额外的利润。这就是随机方法(VSS)的价值。在本例中,它是 108390 美元–107240 美元= 1150 美元。

VSS =随机解(DEP)的 EV—均值解的 EV

我们给农民增加的总利润值是多少?这取决于农民会如何利用自己的直觉种植作物。我们可以计算该解决方案的预期价值,并计算我们增加的额外利润。在我们的笔记本中,通过将变量设置为农民的手动解决方案,可以很容易地做到这一点。请注意,该价值的很大一部分是由线性程序提供的,利润为 107240 美元。

练习:如果农民通常种植两种利润最高的作物——豆类和小麦,种植 300 英亩豆类和 200 英亩小麦,预期利润值是多少?我们总共增加了多少价值(Ans:10190 美元?线性程序传递了什么价值(答案:9040 美元)?VSS 占总价值的百分比是多少(答案:12.7%)?

完全信息的期望值

一个机器学习专家团队提出,他们将能够以 100%的准确率提供每年的产量预测。当农民已经可以得到我们的随机解时,他能为这个信息支付的最高价格是多少?这被称为完美信息的期望值(EVPI)。

EVPI =每个场景使用最优解的 EV-随机解的 EV

EVPI = 1/3(59950 美元+118600 美元+167667 美元)-108390 美元= 7016 美元

如果收益因子(收益的乘数)有一个概率分布

  • 如果概率分布是离散的,我们可以通过为每个离散值生成收益字典来重复这个笔记本。
  • 如果概率分布是连续的,我们可以通过生成分布的切片使其离散。这种方法有多靠谱?我不会在这里涵盖细节,但理论表明,如果我们产生足够的样本,这是非常准确的。请注意,为了获得更多的准确性,我们将有数百或数千个场景。对于这个问题,这个问题应该很容易解决,但是如果给定场景的线性规划(第 1 部分的平均值问题)本身很复杂,我们将面临计算上的挑战。我们可以使用强大的商业软件包,但我们甚至可以测试它们的极限。有一种技术叫 Benders 分解(L 形法),可以通过分解成两个阶段来解决问题。

结论

  • 我们学会了如何修改我们的线性程序,通过为依赖于场景的每个变量创建多个副本来考虑所有可能的场景。
  • 这个解为我们提供了第一阶段的最优解。第二阶段变量有几个答案。农民可以在产量实现后每年计算它们,并采取相应的行动(购买赤字并出售剩余的作物)。
  • 解决这个问题的随机版本,通过对冲所有可能的情况,使我们获得更好的利润预期值。

后续步骤

  • 在这个问题中,我们解决了期望值最大化的问题。这是最受欢迎的选择。我们也可以求解其他目标;其中一些很难建模。我建议解决它们。
  • 解决多阶段问题。在下面提到的课堂笔记中,有一个财务规划问题就是一个很好的例子。

参考

我将把我的参考资料限制在解释基础知识和涉及这个问题的资源上。

[1] J. Linderoth,课堂笔记涵盖了这个问题。附加注释

[2] J. Birge,F. Louveaux,教科书:随机规划介绍 —这个问题在第 1 章中有所涉及。

[3]Python 中的纸浆解算器的官方网站

在 5 分钟内学会数据科学家必备的 SQL 技能

原文:https://towardsdatascience.com/learn-essential-sql-skills-for-data-scientists-in-5-minutes-de853505e6c?source=collection_archive---------24-----------------------

想快速学习 SQL?

学习基本的 SQL 技能,让你的数据科学简历更有吸引力

约书亚·索蒂诺在 Unsplash 上拍摄的照片

先说一个有趣的事实。SQL 是数据分析师和数据工程师最需要的技能,也是数据科学家第三需要的技能。好吧,这个事实只是告诉你了解 SQL 有多重要。

好吧,但是为什么 SQL 是一个非常需要的技能呢?通常,数据科学家使用 Python 或 r 处理数据框。然而,当今数据科学中的海量数据无法完全加载到数据框中,甚至无法加载到. csv 文件中。对于这种情况,需要一个 SQL 数据库。SQL 非常简单易学。对于熟悉数据框架的数据科学家来说,学习 SQL 变得容易多了。在本文中,我们将学习执行普通数据科学操作的所有基本 SQL 技能。博客的内容如下:

  • 创建表格
  • 选择表和列,选择不同的值
  • 条件选择、选择行、排序列
  • 插入、更新和删除值
  • 基于基本统计值的条件:最小值、最大值、计数、平均值、总和
  • 连接表格

不用再等了,让我们开始学习不同的话题吧。

吉菲

创建表格

SQL 数据库由几个表组成。表格相当于数据帧,它有列和行。创建表格命令用于创建表格。表格的每一列都被分配了一个数据类型,例如 charvarchar。Char 是固定长度的字符串。 Varchar 是一个可变长度的字符串。该命令还使用了一些约束,如主键不为空。关系表的主键唯一地标识表中的每个元组或行。它还可以防止表中出现重复值。Not null 确保这些字段不能包含空值。

*CREATE TABLE users
(id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
user_name VARCHAR(255))*

上面的命令将创建一个名为“users”和[columns id,name,user_name]的表。

选择表和列

当我们已经有了一个数据库,那么我们需要一些查询语句来读取数据。在本节中,我们将看到如何做到这一点。 SELECT 命令决定您想要从给定的表中提取哪些列。来自 命令的决定了你想要从哪个表中提取信息。要选择某些列,使用以下语法:

SELECT column1, column2 FROM table_name;

要选择所有列,请执行以下操作:

SELECT * FROM table_name;

在表中,列可能包含重复值。如果我们只想要唯一的值,可以使用选择不同的命令。

SELECT DISTINCT column1, column2 FROM table_name;

条件行选择和列排序

在上一节中,我们已经学习了如何获取某个表的一些列。在本节中,我们将了解如何根据不同的标准选择一些行。SQL 中的 WHERE 命令允许有条件地选择行。语法是

SELECT column1, column2 FROM table_name WHERE condition;

举个例子,

SELECT column1, column2 FROM table_name where column1 = 10;

此查询从 table_name 中选择值 column1 和 column2,其中 column1 的值等于 10。中的操作者所在的命令包括:

  • <不到
  • >对于大于
  • =为平等
  • <=为小于或等于
  • >=为大于或等于
  • <> for not equal(在 SQL 的某些版本中可以写成!=)
  • BETWEEN x AND y用于xy之间的所有值,以及xy
  • LIKE string对于某种模式(例如,字符串s%返回以s开头的列的所有值)

如果希望列 1 满足一个条件,列 2 满足另一个条件,可以使用。例如:

SELECT * FROM table_name WHERE column1 < 3 AND column2 > 8;

以上将返回列 1 值小于 3 且列 2 值大于 8 的行。同样,您也可以使用而不是命令。

现在,我们已经看到了如何根据不同的标准筛选出行。为了以特定的顺序得到行的输出,我们可以使用 ORDER BY。例如

SELECT column1, column2 FROM table_name ORDER BY column1 ASC WHERE column1 < 3;

以上将返回 column1 和 column2 的值,其中 column1 的值小于 3,返回的数据将根据 column1 的值按升序排列。 ASC 可替换为 DESC ,如果数值是从最大到最小,而不是从最小到最大(默认)。为了更好地理解,让我们再举一个例子。

SELECT * FROM table_name ORDER BY country, income;

以上将返回整个表,按国家的字母顺序排序,如果国家相同,则按收入排序。

插入、更新和删除值

使用插入命令将数据插入到表中。在此命令的语法中,表名标识表,列名列表标识表中的每一列,值列表指定要添加到表中各列的数据值。请注意,values 子句中提供的值的数量等于列名列表中指定的列名的数量。

INSERT INTO table_name (column1, column2, column3) VALUES (value1, value2, value3);

如果将值插入到每一列中,则不需要指定值要插入到哪一列,因为假设值是按照从左到右的列排列方式排序的。例如,如果您有一个包含 3 列的表格,您可以使用:

INSERT INTO table_name VALUES (value1, value2, value3);

更新值遵循以下语法:

UPDATE table_name SET column1 = value1, column2 = value2 WHERE condition;

只要指定了条件,它就会更新 column1 和 column2 的值。

DELETE 的语法是

DELETE FROM table_name WHERE condition;

注意,如果没有给出 WHERE 命令,整个表格内容将被删除。

基于基本统计值的条件

它们采用值的集合或整个列来输出单个值。例子包括 COUNT()、SUM()、MIN()、MAX()、AVG()、等。,分别输出行数、值的总和、最小值、最大值和平均值。例如

SELECT COUNT(column1) from table_name where column1=3

以上将返回列 1 的值为 3 的行数。类似地

SELECT MAX(column1) from table_name where column2>1

以上将返回 column2 的值大于 1 的 column1 的最大值。

连接表

为了合并两个表中的数据,我们使用了 JOIN 命令。有多种连接表的方法。在这篇博客中,我们将只关注内部连接。在这种类型的连接中,两个表的结果是匹配的,它只显示与查询中指定的条件匹配的结果集。

说有两个表,员工JOB_HISTORY 。我们希望根据员工 ID 将员工与工作历史联系起来。

*select EMPLOYEES.F_NAME,EMPLOYEES.L_NAME, Job_History.START_DATE
from EMPLOYEES 
INNER JOIN JOB_HISTORY on EMPLOYEES.EMP_ID=JOB_HISTORY.EMPL_ID*

上面的命令将输出一个包含列名为" EMPLOYEES "的组合表。F_NAME ","员工。L_NAME "," Job_History。开始日期”。它将只输出两个表中员工 ID 匹配的值。还有其他类型的联接,如左联接右联接全外联接、,我们不会在本博客中一一介绍,因为本博客的主要目的是为您提供数据科学家所需的 SQL 基本功能。

结论

我希望这篇文章能够帮助您理解和学习数据科学家所需的基本 SQL 技能。现在继续把 SQL 作为一项技能添加到你的简历中。如果您喜欢其中的内容,并希望随时了解广阔的数据科学领域,请关注我们的 medium

成为 介质会员 解锁并阅读介质上的许多其他故事。

学习 ML 项目的 Git 基础知识

原文:https://towardsdatascience.com/learn-git-basics-for-your-ml-project-46ecf03865b?source=collection_archive---------24-----------------------

开始使用 Git,并通过使用版本控制系统来模拟真实软件和机器学习工程师的工作风格。

你已经在你的数据科学和机器学习项目中使用 Git 版本控制了吗?如果你还没有考虑这个问题,让我问你第二个问题,你在数据科学或机器学习的旅程中处于什么位置?

在 Jupyter 笔记本上修修补补似乎不再是正确的选择。——伊夫·布特利尔

这个问题是我两个月前完成生物学和计算科学学士学位后问自己的。在我的学习期间,我在数据科学和机器学习方向总共选修了 6 门课程。尽管我为那些课程解决了几个项目。作为学生,我们经常坚持用最简单的方法来完成这些项目。在 Jupyter 笔记本上修修补补,直到代码和结果令人满意,然后提交它们。

然而,回到引言问题:我问自己,我想用我在学习期间获得的数据科学和机器学习知识工作吗?我对这个问题的回答是肯定的,我决定暂停学业,兼职做我的数据科学/ MLE 项目,以找到一份工作,或者尝试将这个或另一个项目变成一家初创公司。但是现在 在 Jupyter 笔记本上修修补补似乎不再是正确的选择

我想模仿机器学习工程师的工作风格,这就是为什么我决定学习 Git 版本控制的基础知识,并将其应用到我的项目中。

这篇文章将为你提供遵循这个想法的基础知识,并用另一种技能升级你的投资组合: Git 版本控制

为什么是 Git?

我曾经像一个业余爱好者一样修补我的代码。有什么不好?嗯,如果你想为你的简历创建一个项目来获得一份工作,你要确保它是一个体面的项目,不是在短时间内完成的。他们希望看到你能从事比小项目更大的项目,因为如果他们雇佣你,你会从事他们的产品,当然这也不是小项目。你应该表明你以一种有组织的方式编码,你可以计划、测试和部署独特的功能,同时仍然独立地开发代码的其他部分。

Git 使您能够做到这一点。维护多个不同的版本,并跟踪您所做的更改。 1) 我们先看基础, 2) 远程存储库,然后是 3) 分支

在每个主题(1-3)之后,我将展示命令行命令来练习从每个段落中获得的知识。

1.Git 基础

Git 是如何看待文件的?

Git 将文件视为一系列快照。如果你想要版本控制系统,即。Git,为了保存你最近的修改,Git 基本上是对你所有的文件进行快照,并保存对这个快照的引用。因此 Git 的效率很高,如果一个或多个文件没有改变,Git 会存储一个到先前相同版本的链接。

请记住三个状态

Git 有三种文件状态:

  • 已修改:文件已修改但未提交
  • 暂存:文件被修改,标记为下一次提交快照的一部分
  • 已提交:文件安全地存储在您的本地数据库中

我们现在可以如下观想我们的知识:

作者手绘

工作树(工作目录)是项目的一个版本。这个版本是给你修改的。要么是旧版本的。git 目录,或者它反映了已修改但未提交或暂存的最新版本。

暂存区是一个存储信息的文件,该信息表示哪些文件在下一次提交时被提交。

最后, Git 目录是 Git 保存项目的对象数据库和元数据的地方。它可用于与其他计算机和人员共享项目。

现在是时候看看 Git 工作流了,因为您已经学习了基本的基础知识。

基本 Git 工作流程

  1. 你修改你的文件
  2. 您将包含更改的文件添加到临时区域
  3. 您提交,这将文件保存在临时区域中,并将快照永久存储到您的 Git 目录中。我们现在把这些改变后的文件称为 ie。版本,已提交。

下一段介绍一个例子,自己练习学到的知识。

练习 1 -练习 Git 基础知识

首先,我们想要设置一个 Git 存储库,我们有一个链接的暂存区和一个工作树。你有两种可能。要么你在一个已经存在的项目上工作。或者创建一个新项目。

1.1 创建新项目

要创建一个新的项目,在你的本地计算机上创建一个目录,然后手动或者用 cd (其中 表示更改目录)转到你想要你的项目所在的位置。

$ cd /Users/user/my_project (MacOs or Linux)
$ cd C:/Users/user/my_project (Windows)

接下来你输入:

$ git init

这将为您创建一个本地 git 存储库。一个.git文件夹。更具体地说,这将是您的目录 my_project 中的一个子目录。

1.2 克隆已经存在的项目

另一种方法是获得一个已经存在的项目。要做到这一点,您只需复制远程存储库的 url,这里表示为并键入

$ git clone <url>

请记住,我们有三种状态:已修改、已暂存和已提交

1.3 准备和提交

我们可以创建文件并在其中写些东西。他们在状态下改装了。要将它们转换到状态" staged ,我们可以使用命令add

$ git add HelloWorld.py

最后,为了将它提交到本地 git 存储库,我们编写:

$ git commit -m 'This message describes what changes I made'

每个提交都需要一个消息,-m 是一个标志,表示下面的字符串就是消息。

你现在可以继续去偏远的地方了:)

照片由 Yogendra SinghUnsplash 上拍摄

2.远程基础

大多数操作只需要本地文件。然而,如果你考虑在你的项目中与其他同事合作,或者你想展示你的作品,例如在 Github.com,你需要学习一些其他的工具。

远程存储库由服务器托管。一个非常受欢迎的地方是 GitHub。与远程存储库相关联的是名称和 url。一旦有了本地 Git 存储库,创建远程存储库就非常简单了。

练习 2 -创建远程存储库

一旦您编写了git init并建立了一个本地存储库,您还可以将一个远程存储库与它相关联。只需为你的遥控器选择一个名字(originmain)这些都是流行的名字,然后从 Github 复制 url。

git remote add <remoteName> <url>

例如,它可能看起来像这样

git remote add origin [https://github.com/myusername/ourproject](https://github.com/myusername/ourproject)

一旦您对项目中的一些代码感到满意,您就可以添加到您在例 1 中学到的工作流之上

$ git push <remoteName> <localName>

总的来说,你会写一些类似这样的东西

$ git add HelloWorld.py
$ git commit -m 'This message describes what changes I made'
$ git push origin main

现在 HelloWorld.py 是 GitHub 上远程存储库的一部分。

其他同事可以像第 1 节中提到的那样克隆这个存储库,并与您一起工作。但是如果你工作并尝试不同的东西。这时你可能需要分支。

3.分支

分支会扩大本文的篇幅,因此包含在这篇流行的文章中:

摘要

你带着学习版本控制的强烈愿望而来,但是你不知道如何开始,然后你走过了介绍性的解释。你学会了通过小练习来运用知识。您当然可以创建一个存储库,并向其中添加和提交文件。远程存储库也变得为您所熟悉。请记住,远程资源库是您可以通过 Github 为您的团队共享您的工作的地方。如果您仍然渴望了解更多,那么关于分支的文章将在另一个层面上带给您关于版本控制的知识。

如果图形机器学习更适合你,你可能想看看:

图的跳格神经网络

初学者节点嵌入

用您的 ML 项目学习 Git 分支

原文:https://towardsdatascience.com/learn-git-branches-with-your-ml-project-7f58bdf1ae80?source=collection_archive---------14-----------------------

让我提出一个假设来开始这篇文章。你知道 git 的基础知识。你做 git init,git clonegit addgit commitgit push,git fetch,git pull 。但是让我来测试你。下面这句话是什么意思?

$ git switch -c development

我跟你说实话,在我一个月前开始我的机器学习项目之前,我不知道这一行是做什么的。但是我在学习分支的过程中偶然发现了这个命令,以使我在 Git 版本控制方面的技能更加完整。这篇文章总结了我的学习,也是我想要的,这样我就可以尽可能快速有效地学习分支。如果你和我来自相似的地方,我鼓励你通过阅读这篇文章来适应分支。

为了使这种学习有效,我们首先看看 Git 的内部,真正理解分支。这将包括指针、blobs、提交对象其次,我定期向您展示我写的代码行,这样您就可以在 Git 库的不同分支中拥有多个版本的项目。

照片由凯拉·霍泽尔Unsplash 拍摄

分支是如何在引擎盖下工作的?

如果输入git commit -m “update"会怎么样?它创建了一个提交对象。它包含作者的姓名和电子邮件地址、您为此提交键入的消息(“更新”)、指向之前提交的指针以及指向您暂存的文件的指针。好吧,有点快了。我们从舞台开始。

让我们假设您创建了两个文件

  • 自述文件
  • HelloWorld.py

并用git add README HelloWorld.py将它们登台

Staging 导致对每个文件进行校验和检查,并将该版本存储在 Git 存储库中。在 Git 中,这个校验和单个文件的结果被称为 blob。每个 blob 代表文件的内容。当我们提交时,每个子目录(包含已转移的文件)也依次进行校验和检查。这一步的结果是一个树对象。树对象保存指向单个 blobs 的指针,存储单个文件的名称和 SHA-1 散列。不要忘记我前面提到的提交文件。这指向以前的提交,也指向根文件,以便能够在需要时重新创建版本。我们现在有 4 个 Git 文件:

作者绘图,Git 文件示意图

我注意到一个提交文件指向前一个提交文件,也称为父文件。让我们也想象一下。

提交指向其树对象的对象

现在,您已经准备好听听分支到底是什么了!

分支基本上是指向一个提交对象的可移动指针。

因此创建一个分支就是创建一个指针。这是一个非常轻量级的解决方案。分支是一个 40 个字符的 SHA-1 散列,它是对提交对象进行校验和检查的结果。创建一个分支就像创建 41 个字节并将它们写入一个文件一样简单(41 是因为 1 个换行符)。

分支在实践中是如何工作的

创建名为“testing”的分支的命令如下所示:

$ git branch testing

但是你可能想知道这个分支在哪里分叉?为了理解这一点,我们必须引入另一个 Git 要素。头部指针

头部指针

Git 通过维护一个 HEAD 指针知道你在树状结构上的位置。HEAD 指向您当前所在的分支。所以如果你输入git branch testing,现在分支testing指向相同的提交,就像头指针之前指向的另一个分支。但是git branch并没有改变头部指针指向的位置,所以它仍然在 master 上。

我画了一张图让你更清楚。一个名为 master 的分支在我们创建一个名为 testing 的新分支之前就存在了,因为git branch没有改变 HEAD 的位置,所以在创建testing之后它仍然指向 master。

一个简单的提交历史,有两个分支和头指针

这意味着如果你想对分支的位置有更多的控制,你必须首先改变头指针指向的位置。这是用单词checkout完成的,但是它只能检出已经存在的分支。请注意,如果您checkout其他分支,您的工作目录中的文件会更改为保存在其他分支中的版本,如果您签出这些其他分支的话。

还记得git switch -c testing吗?它结合了git branch testinggit checkout testing,让你一次完成。你创建一个分支/指针,让 HEAD 指向这个新的分支。

EAD 决定向哪个分支添加新的提交。

如果我们编写了git checkout testing,然后向我们的库git commit -m "another commit"提交一些东西,我们的情况看起来是这样的:

测试分支提前一个提交

在这种情况下,它看起来不像我们从自然界中所知道的实际分支。但是如果我们回到分支主节点git checkout master,然后在主分支上回到commit,我们会得到这两个分支的共同祖先或节点。这种情况看起来更像实际的分支。但是你明白了。

测试分支仍然提前 1 次提交,但现在也落后 1 次提交

我们必须谈论合并

有分支有什么用?你有两条或多条开发路径,你可能想两全其美,例如,从一个分支获得新的功能,并将其与主开发合并。

为了理解合并,让我们考虑两种可能的合并机制。

快进合并

使用快速向前合并,您基本上将落后的分支(主)向前移动到领先的分支(测试)。我再次展示了之前的情况。如果在后面的分支(主分支)没有在前面的分支(测试分支)中丢失的提交,这个快速前进合并起作用。

之前:

这种情况是为快速向前合并而设计的

之后:

快进合并的结果

为此,首先将头部指针移动到master,然后移动到merge:

$ git checkout master
$ git merge testing

如果你不再需要测试指针,你可以通过写来删除它

$ git branch -d testing

基本合并

另一种合并方式发生在两条路径都存在的情况下,如下图所示

一个稍微困难一点的合并工作,测试是提前 2 次提交和滞后 1 次提交

在这种情况下,Git 必须执行三个版本的合并。Git 不是向前移动分支指针,而是创建文件的快照,并创建指向它的新提交。这个提交有一个特殊的名称。它被称为合并提交,因为它有多个父级。

创建了一个名为合并提交的提交对象,以从两个分支获取关于共同祖先 f30ab 的更改

创建远程分支

如果您想与他人共享您的分支,以便多个编码人员可以处理您的项目,或者在 GitHub 上向他人展示您的项目,您需要将分支推送到远程存储库并创建远程分支。

语法如下所示:

$ git push <remote> <branch> #for example
$ git push origin master

这个命令创建了两件重要的事情。

  1. 它创建了一个远程分支,其他人可以使用并进一步构建
  2. 它在您的本地存储库中创建一个远程跟踪分支

将远程跟踪分支视为对远程分支状态的引用。他们有下面的名字结构remotes/<remoteName>/<branchName>。您仍然拥有分支的本地版本master,这意味着您的本地 Git 存储库拥有以下分支:

master
remotes/origin/master

注意,带有语法remotes/<remoteName>/<branchName>的远程跟踪分支是本地引用,不能用git merge移动它们。相反,如果您在master上做了更改,您可以将它们推送到服务器并获得一个更新的远程跟踪分支remotes/origin/master。因此,只要您不与远程储存库联系,远程跟踪分支就不会移动。如果您的一位同事想要进行更改,并且他们已经克隆了他们使用的存储库:

git fetch origin 

远程跟踪分支将被置于在那些分支上完成的最新提交。但是请注意,如果您获取和接收新的远程跟踪分支,您将不会自动拥有可以编辑的本地副本。如果issue是一个新的分支,它会是这样的:

master
testing
remotes/origin/master
remotes/origin/testing
remotes/origin/issue

您将只有一个无法修改的指针remotes/origin/issue。这意味着您需要使用以下命令来创建本地可编辑副本:

$ git checkout -b issue origin/issue

git 拉

也可以通过编写一步完成fetchmerge

git pull <remote>

知道你的团队在做什么

你正在失去概观?别担心。我将用一个命令结束这篇文章,这个命令让您了解您的分支超前或落后了多少个版本。但是要确保,首先输入git fetch,这样您的本地 repo 就会得到更新,并从您的同事那里了解最新的提交。

$ git branch -vv

结果可能如下所示

testing     7e424c3 [origin/testing: ahead 2, behind 1] change abc  master      1ae2a45 [origin/master] Deploy index fix
* issue     f8674d9 [origin/issue: behind 1] should do it          cart        5ea463a Try something new

我想从这个例子中指出几点:

  • 在左边你可以看到分支的名称,星号表示头部指针的位置
  • 右边是代表每个分支上最后一次提交的 SHA-1 散列
  • 远程分支在版本差异旁边的方括号中表示,例如,前面的 2 表示我向本地分支testing提交了两次,而这个工作还没有推送到远程。此外,我们的本地分支机构还没有完全更新。团队中有人推到了偏远地区,我们还没有将这项工作合并到我们当地的分支机构。
  • 右边是提交消息

删除(远程)分行

最后,如果你不再需要树枝..

远程,

$ git push <remoteName> --delete <branchName>

本地,

$ git branch -d <branchName>

开始时,记住在两个地方都删除可能会很烦人,但是我向您展示了如何删除,并且您可能会在对其中一个命令感到不确定时返回到本文。

摘要

您了解了提交、树和 blob 对象。您知道分支实际上只是指向提交对象的指针。此外,记住 HEAD 指针的存在是至关重要的,因为这个指针将决定你的新分支将在你的git branch命令上创建的位置。您现在熟悉的一个概念是合并分支,并在不使用它们之后删除它们。请务必记住快速向前合并和基本合并之间的区别。

如果你喜欢这篇文章,你可能会喜欢我在 medium 上写的其他一些文章。

了解决策树是如何生长的

原文:https://towardsdatascience.com/learn-how-decision-trees-are-grown-22bc3d22fb51?source=collection_archive---------22-----------------------

用 Python 中的一个例子解释决策树

作者:爱德华·克鲁格希德尔·邦戈尔道格拉斯·富兰克林

卡丹和彼得在 Unsplash 上拍摄的照片

什么是决策树?

决策树是一种受监督的机器学习算法,可用于回归和分类问题。决策树遵循一组嵌套的 if-else 条件来进行预测。

由于决策树可用于分类和回归,因此用于生成决策树的算法通常被称为 CART(分类和回归树)。没有单一的决策树算法。已经提出了多种算法来构建决策树,但是我们将重点关注 scikit-learn 中使用的 CART 算法。

决策树是二叉树,其中每个节点代表一个决策。

可视化购物车模型

  • 根节点:这是启动图形的节点。深度为零。
  • 内部/子节点:这些是做出二元决策的子节点。
  • 叶节点:这些是树的最终节点,在这里进行类别或数值的预测。

该算法旨在从一组输入变量及其属性中预测目标变量。树结构是通过从根节点经由分支的一系列二进制分裂(是/否)构建的。当我们深入到树中时,我们会经过几个内部节点,直到到达叶节点。正是在这些终端节点上进行预测。

训练决策树

该算法首先将训练集分成两个子集。一旦 CART 算法成功地分割了训练集,它就使用相同的逻辑等递归地分割子集。

它一旦到达最大深度就停止分裂,或者找不到分裂来减少杂质。这种方法使决策树成为一种贪婪算法— 它贪婪地在根节点搜索最优分裂,并在每个后续级别重复该过程。

决策树是通过使用来自数据的特征递归分割我们的训练样本来构建的。

随着树的深度增加,杂质或不确定性的水平降低,导致更好的分类或每个节点的“最佳分割”。

将属性的最佳值确定为分割点相当于分割数据集以最小化给定的成本函数。所采用的成本函数取决于我们是在解决分类问题还是回归问题。在上面的可视化例子中,我们使用误分类率作为代价函数。

分类树的另外两个常见的成本函数是基尼不纯度和信息增益(熵)。当算法遍历一个属性的所有可能值时,它会计算该点的基尼系数或信息增益。最佳最小化成本函数的属性的值被用作分割。

一个节点的基尼指数或熵测量其杂质和无序度。一个节点是“纯”的,即如果它应用的所有训练实例属于同一类,则基尼指数或熵为零。默认情况下,使用基尼杂质测量,但您可以通过更改超参数来选择熵杂质测量。

对于回归树,您可以使用回归度量作为成本函数。均方误差是一个非常常见的选择。当算法遍历独立变量的不同值时,它选择最大程度地减少 MSE 的分割。

编码示例

我们将使用 scikit-learn 中的经典葡萄酒数据集来构建一个购物车模型。该数据包含三个等级,没有明显的不平衡。在这里找到数据集。

葡萄酒数据集信息

导入工具和数据

load_wine()的结果存储在bunch中是一个类似地图的物体,有六个主要成分:['data', 'target','frame', 'target_names', 'DESCR', 'feature_names']

熊猫可以很容易地将这一串转换成数据帧:

葡萄酒数据

决策树的主要优势之一是它们需要很少的数据准备或特征缩放。

模型度量

现在让我们的模型可视化。

在这个可视化中,每种颜色代表一个葡萄酒类别。颜色的深浅表明纯度。每个决策节点中的第一个值表示用于从根到叶遍历的二进制逻辑。另外,请注意,样本大小是从父节点到子节点进行分割的,演示了最佳分割是如何分割样本的。

让我们用一个葡萄酒的例子来看看这棵树。想象一款颜色强度为 2.0,酒精含量为 12.o,灰分为 2.0 的葡萄酒。在第一个节点,当颜色强度≤ 3.82 时,我们将向左。按照这个逻辑,我们在酒精节点处向左,在 ash 节点处向左,最终在最左边的叶节点(class_1)处结束。

结论

决策树(CART)是强大的算法,与其他 ML 方法相比,很容易解释。它们不需要太多的计算能力,允许你快速种树。

虽然您需要小心不要过度拟合您的数据,但 CART 是解决许多问题的好算法。如果你想提高模型的性能和健壮性,你也可以探索集合方法,比如随机森林或者修剪。

决策树的优势

  • 简单的理解和解释,易于使用,多功能和强大的。
  • 需要很少的数据准备或特征缩放。
  • 可以处理数字和分类数据。也可以解决多输出问题。

决策树的局限性

  • 决策树的主要问题是它们对训练数据中的微小变化非常敏感。随机森林可以通过在许多树上平均预测来限制这种不稳定性。
  • 没有正则化,决策树很容易过度拟合,因为决策树学习者可以创建过于复杂的树,不能很好地概括。随机森林也有助于防止过度适应。
  • 树也相当不稳定。训练数据集中的一些变化可以导致完全不同的树。假设选择不同的特征作为第一个分割特征,整个树结构会改变。这也会给模型的可解释性带来问题。

参考

了解如何利用强大的决策模型对您的分析项目进行财务评估

原文:https://towardsdatascience.com/learn-how-to-financially-evaluate-your-analytics-projects-with-a-robust-decision-model-6655a5229872?source=collection_archive---------12-----------------------

利用考虑定量和定性因素的有用框架,估算收入和成本、评估风险并计算分析项目的价值

全球的公司、政府和非政府组织已经意识到分析可以为他们的组织带来巨大的价值。自动化流程以节省成千上万的工时,基于数据驱动的分析改进决策制定,以及通过变得更加敏捷和有效来获得竞争优势,这些只是公司大力投资分析项目的几个原因。

话虽如此,首席数据官(CDO)必须以财务方式正确评估分析用例,以说服首席财务官和首席执行官投资于为其组织带来最大价值的项目。

为了了解如何做到这一点,我们将研究一个商业案例,展示进行商业分析项目的财务含义。我们将评估最相关的财务指标,并查看分析结果如何流经公司的损益表(P & L)。最后,我们将通过考虑定量和定性因素,说明在什么样的假设下,我们会建议是否继续进行该项目。

我们将着手的商业案例集中在政府对分析领域的投资。我们将给出政府可以从分析项目中获益的三个领域的例子,然后我们将选择其中一个项目来构建 Excel 电子表格模型,以评估其潜在的好处。

我们将对其中的一些数字进行假设,但重点是要考虑模型结构以及这些数字在模型中的处理方式。最后,我们将在面向非技术观众(例如政府机构)的幻灯片中总结我们的结果。

Unsplash 上的absolute vision拍摄的照片

文章的结构

  1. 我们的商业案例——政府在分析领域的投资

2.政府可以从分析中获益的三个领域示例

3.介绍我们的决策模型

4.将 Excel 电子表格模型应用于潜在的政府分析项目

5.执行演示文稿——将我们的结果移交给政府机构

1.我们的商业案例——政府在分析领域的投资

大数据和高级分析的进步为政府提供了前所未有的机会来改善收入管理和支付方面的成果。根据麦肯锡&公司在 2018 年发表的一篇文章,全球近 20%的政府收入,或约 5 万亿美元,每年都消失,要么是欠下的美元从未支付,要么是对外支付出错。

三个趋势为政府创造了一个独特而直接的机会,动员起来争取更大的成功。这些趋势包括:

  • 数据的可用性;
  • 数据和分析工具以及存储的成本直线下降;和
  • 将分析转化为行动的新技术。

为了利用这些机会,政府领导人需要能够有效地评估对分析项目的投资,以在社会中产生最大的积极影响。

为了做到这一点,我们将使用一个决策模型,主要利益相关者可以将其作为制定更明智决策的指南。值得一提的是,该模型并不仅限于政府项目,因此公司和非政府组织也可以使用它来评估他们的分析业务用例。

2.政府可以从分析中获益的三个领域示例

政府对分析的投资可以对社会产生巨大的积极影响。这些好处的一些例子包括:改善城市的安全,减少浪费,以更有效的方式进行审计,以及升级一个州的卫生系统。

我们将介绍三个具体的例子, Jane Wiseman 在她于 2019 年 9 月发表的题为“ 政府投资分析的研究论文中介绍的例子。在每一个例子中,我们将指出将发生的投资和运营成本的总和,以及可以实现节约的地方。

值得一提的是我们将对这些数字做一些假设,比如投资金额或运营成本中涉及的概念,当它们没有在示例描述中说明时。

例 1

增加收入——利用流程改进在堪萨斯市创建更高效的税收流程

密苏里州堪萨斯城利用数据分析和精益流程改进将税收增加了两倍。在首席数据官 Eric Roche 的领导下,数据团队(DataKC)与该市的法律部门合作,检查该市的过期税款征收流程。数据提供的见解导致了一种新的案件处理方式,并决定增加两名专门的工作人员来追踪滞纳金。年度收款从 2015 财年的 110 万美元增长到 2018 财年的 320 万美元。算上员工工资,这是投资的八倍回报。

投资 :支付给数据专家咨询组的工资。一名数据工程师、一名数据科学家、一名机器学习工程师和一名 UX/UI 开发人员被临时聘用,以支持 DataKC 团队改进税收流程。这个项目的回报是投资的八倍。

受益 :税收增加三倍,发现办案新途径。这种新方法也有助于政府实体变得更加敏捷和灵活。年度收款额从 2015 财年的 110 万美元上升至 2018 财年的 320 万美元。

例 2

通过提高效率节省成本—波士顿通过数据分析监控节省资金并降低碳足迹

波士顿市通过一种优化校车路线的算法,每年节省 500 万美元,同时减少 20,000 磅的碳排放。该市实施该解决方案无需成本,因为它是由麻省理工学院的研究生开发的,是该市主办的黑客马拉松的一部分,奖金由一家私人基金公司赞助。

该市还通过实时监控和能源经理每年节省 100 万美元的城市建筑能源成本,能源经理可以在高峰成本 times⁴.期间战略性地调整消耗这一节省包括仅在一栋建筑(该市的主图书馆)中每年节省的 40,000 美元。

投资 :直接来说这个项目是没有投资的。以一种间接的方式,组织了一个黑客马拉松来创建这个解决方案,一个私人投资者为进一步的开发和部署提供资金。

运营成本:data robot(一个自动化机器学习平台)的年度许可证订阅以及云中数据存储的可变月度费用。此外,有必要向数据科学家和数据工程师支付月薪,以保持算法的更新,并制定严格的数据治理协议。**

好处 :波士顿市每年节省 500 万美元,同时减少了校车路线上的 2 万磅碳排放。此外,该市每年还在城市建筑能源成本上节省了 100 万美元。

例 3

欺诈检测—在德克萨斯州发现失业保险欺诈

得克萨斯州发现并阻止了利用 analytics⁵.进行的 9000 万美元的欺诈德克萨斯州信息资源部门的数据协调员 Ed Kelly 领导了德克萨斯州的透明和开放数据、数据共享和数据扫盲工作。得克萨斯州数据投资高回报的一个例子是得克萨斯州劳动力委员会(TWC),该委员会发现了 9000 万美元的欺诈性失业救济金,被关押在该州监狱和拘留所的个人可能会申请这些救济金。通过将失业索赔数据与该州刑事司法部门的数据进行比较,该州现在可以确保不向被监禁者支付失业救济金。在该计划的早期,每年确定超过 2500 万美元,2018 年为 1800 万美元。这种避免欺诈的下降趋势可能表明,有消息称分析团队将识别潜在的欺诈,阻止更多的尝试。

投资 :招聘和保留计划对于吸引和保留德克萨斯劳动力委员会的合适分析人才至关重要。这些举措被认为是一项投资,也是项目开始时为以最佳方式改善数据共享流程而实施的数据架构。

运营成本 : 向政府实体的员工推出了季度培训计划,以提高他们的数据素养。额外的运营成本包括数据存储的可变成本、分析员工的固定工资成本以及起诉流程中额外三名律师的可变工资成本。

救济金 :阻止了 9000 万美元的欺诈性失业救济金。

这几个例子帮助我们看到了大数据和人工智能项目可以在政府实体中产生的价值。很少有政府数据团队拥有记录其价值的资源,但那些有资源的团队可以显示高达 8 比 1 的成本回报。此外,还有一个重要的非财务利益,因为当节省时间和金钱与提高透明度和问责制相结合时,公众对政府的信任可能会提高。

3.介绍我们的决策模型

为了评估决策,使用考虑了主要因素的通用决策模型是有意义的。在下面的视频中,BI 挪威商学院商业分析理学硕士项目的副院长 pl berth ling-Hansen 描述了这样一个模型。虽然有几种方法来构建这样一个序列模型,但是对于这个特定的模型有一些很好的论据。**

建议的决策模型是通用的,适合大多数决策类型。重要的是要考虑到定性因素总是存在的,并旨在总结最终影响财务的所有积极和消极因素。这些因素是有关联的,因项目而异,也随着时间而变化。

现在,我们已经看到了决策模型的结构,我们将继续看一个具体的例子。 Excel 电子表格模型遵循与之前相同的方法,但现在我们将添加一些数字以使其更容易理解。请观看以下视频,了解我们将使用的模型的更多背景信息。

在本文的下一部分中,我们将对电子表格模型进行修改,使之适应示例 1 的一个小变化,以便更详细地理解如何将该模型应用于一个分析业务项目。

4.将 Excel 电子表格模型应用于潜在的政府分析项目

假设您在佛罗里达州税务局工作,该部门是负责佛罗里达州税收管理的政府实体。您已经了解了堪萨斯市如何通过流程改进增加税收收入(示例 1) ,并且您希望在您所在的州启动类似的计划,以增加政府实体的价值。该州有几个分析业务用例要考虑,所以现在是时候以严格的方式评估您的项目,以说服关键利益相关者您的项目是最好的!**

首先,你需要的是建立模型,然后处理现金流,最后,你将评估定性因素及其潜在风险,以做出最终决定。在这个过程中,你将研究和假设这些数字中的一些,以获得一个可靠的财务估计。

模型结构

  • 第 1 部分—建立模型
  • 第 2 节——建立现金流模型
  • 第 3 部分—评估定性因素、其潜在风险,并做出最终决策

第一节模型设置

我们将分解这些数字来描述我们的假设。

对于 所需投资 我们建议,鉴于项目的规模,有必要聘请一组数据专家来协助佛罗里达州税务局。我们建议雇佣一个由 13 名顾问组成的团队,包括数据工程师、数据科学家、机器学习工程师和 UX/UI 开发人员。总的来说,咨询集团将向州政府收取 1387242 美元的服务年费,该费用基于 Glassdoor 上的美国年薪。需要额外的投资来访问外部数据源、研究和软件许可,这又增加了 93,000 美元,总投资为 1,480,242 美元。该金额将在项目开始时一次性支付。

根据美国国内税收署(ISR) 的税收统计,佛罗里达州 2020 财年 的年度税收为 210,024,433 美元。此外,咨询集团预测,由于流程改进,年度税收将增长如下:第 1 年增长 2.9%,第 2 年增长 2.1%,第 3 年增长 1.7%,第 4 年增长 0.9%,第 5 年增长 0.4%。**

该团队还决定将 Tableau 作为主要的 分析可视化工具 ,供政府实体中的员工用于其分析和日常运营。这将使他们的固定成本每年增加 48,720 美元。**

该团队还将增加 5 名新的专职工作人员的工资,以追踪迟缴的税款。 税务律师年薪为 107,549 美元,因此每年的固定成本总计为 537,745 美元。

对税务所员工进行特殊的 分析培训 对项目的成功至关重要。每月将安排研讨会和个人培训,教员工如何使用新工具,变得更加数据驱动。这将产生每年12,000 美元** 的固定成本。****

可变成本 将包括亚马逊网络服务 (AWS)针对云存储和维护 的每月现收现付服务。这些费用每年从 75,000 美元到 95,000 美元不等,取决于公民和企业每年提交的纳税申报数量。为了对此建模,我们使用了 Excel 中的 RandBetween 函数来简化事情,但在现实生活中,肯定有更好的方法来估算这些成本。

最后,我们决定采用 28%的税率和 8.3%的 资本成本。**

第二节——建立现金流模型

在模型的第二部分,我们构建现金流以获得项目的净现值(NPV) ,在本例中为 7,187,955 美元。如果你想更详细地分析现金流模型,你可以查看我在下面附上的 Google Sheet 链接。

****https://docs.google.com/spreadsheets/d/1bqOesbj5UOvhdWz0XY-LvtBONdZF2NaD76c-k0FQ_Gs/edit?usp=sharing

第 3 节——评估定性因素、其潜在风险,并做出最终决策

现在,在模型的最后部分,是时候关注能够以积极或消极的方式影响项目的定性因素了。如上图所示,我们决定根据内部外部负、以及它们的影响 ( 中、)对这些因素进行细分。

对于这个项目,我们确定了三个需要考虑的内部负面因素,因为它们可能是潜在风险,会降低项目的盈利能力,甚至完全取消项目。关于积极因素,我们确定了其中两个,一个是内部因素,另一个是外部因素。

风险联系在一起,我们尤其要关注影响较大的负面因素。对于这个项目,我们确定了一个是“政治官僚主义和项目期限的延误”。我们认为,为了在这个项目中取得成功,依靠佛罗里达州税务局的主要利益相关者的支持是至关重要的。该项目可能会面临许多操作问题和官僚主义,为了克服这一点,得到决策领导人的支持至关重要。

与积极因素相关,我们认为政府实体增强其分析能力有很多好处。这将有助于政府变得更加灵活、数据驱动、透明、有组织和可信,最终将带来长期的好处。

我们计算了如果计划被延迟,对项目的相对影响。例如,让我们假设该项目需要一年多的时间才能投产,税收的增长低于预期,项目的寿命从五年缩短到四年。

该项目的净现值仍然为正,净现值为 390 万美元。不同的场景可以通过修改模型的参数(如寿命、初始投资或成本)来创建,以查看潜在的财务影响。之前解释过的悲观情景的模型可以在这里访问:

https://docs.google.com/spreadsheets/d/1-mJVGdNn6SIBpHIFbh7lBtZTDvq7auUMLkw4GovtxEk/edit?usp=sharing

为了做出最终决定,我们需要平衡定量和定性因素,同时考虑项目的潜在风险。

量化因素中,我们使用了现金流模型,计算出的净现值为 7,187,955 美元。这是一个非常好的结果,因为 NPV 需要为正才能有吸引力。然而,重要的是要考虑我们还应该将 NPV 和内部收益率(IRR)与政府实体正在考虑的替代分析项目进行比较,以确定哪一个更有吸引力。

定性因素潜在风险、相关,我们可以得出结论,如果项目得到一群有影响力的领导人的支持,那么积极的方面会超过消极的方面。总的来说,我们建议对这个项目进行决策。

5.执行演示文稿——将我们的结果移交给政府机构

现在,我们已经以广泛的方式完成了对分析项目的评估,是时候将我们的结果以压缩幻灯片的形式呈现给佛罗里达州税务局的政府领导了。

以简短、精确和令人信服的形式展示结论对于说服关键利益相关者投资你的项目至关重要。我建议使用一个好的行动标题,写下与你的项目最相关的需求,使用图表来可视化你的结果,在底部有一些关键的要点和建议。

下面,您将看到一个如何向政府实体展示最终结果的示例。

最后,我想感谢您有兴趣阅读我的文章。希望对你有用!

最诚挚的问候,

胡安·曼努埃尔·鲁伊斯·阿科斯塔

附加材料

为了更好地理解什么是商业案例以及为什么它在撰写项目建议书时如此重要,我推荐你观看来自 YouTube 上项目管理视频的 Devon Dean 的视频。

致谢

这篇文章反映了许多个人的有益贡献和启发。这篇论文反映了简·怀斯曼的宝贵意见和建议,她是哈佛大学肯尼迪学院民主治理和创新阿什中心的美国政府创新研究员。此外,BI 挪威商学院负责商业分析理学硕士项目的副院长pl berth ling-Hansen提供了决策模型的解释视频,之前引用的麦肯锡文章对于丰富分析以得出更好的结论也至关重要。

参考书目

[1]:苏珊·坎宁安;戴维斯,乔纳森;以及 Dohrmann,Thomas, 《万亿美元大奖:用高级分析堵住政府收入漏洞》 ,2018 年 1 月,麦肯锡&公司。

[2]: Wiseman,Jane,“ 政府投资案例分析 ”,2019 年 9 月哈佛大学肯尼迪学院— ASH 民主治理与创新中心。

[3]:麦金蒂,乔·克雷文。“你是怎么修好校车路线的?打电话给麻省理工学院。”《华尔街日报》2017 年 8 月 12 日。

[4]:科林·伍德(Colin Wood),“波士顿如何计划通过观看其电力账单节省 100 万美元”,Statescoop,2017 年 3 月 30 日。

【5】:木头,科林。“数据共享协议为德克萨斯州节省了 9000 万美元,”Statescoop,2019 年 1 月 11 日。****

了解如何使用 Google Cloud Workflow 执行无服务器流程编排

原文:https://towardsdatascience.com/learn-how-to-perform-serverless-orchestration-with-google-cloud-workflow-5e20cee72a7c?source=collection_archive---------13-----------------------

关于创建工作流以连接服务的简单教程

安德里亚·扎内加拍摄于 Unsplash

简介

谷歌工作流于2020 年8 月 25 日首次推出。它是一个平台,作为开发人员的无服务器工作流来编排和自动化 Google Cloud,并连接一系列基于 HTTP 的 API 服务。例如,您可以使用 Google Workflow 连接云运行微服务、云功能、外部 API 等。

工作流由一系列步骤组成,这些步骤指定了每个步骤要执行的功能,并以 YAML 或 JSON 格式编写。完成工作流创建后,您需要部署工作流,然后才能执行。在执行时,它将基于创建的工作流中指定的逻辑运行。

在本文中,让我们学习如何使用 Google Cloud Workflow——我将通过涵盖以下项目,提供如何在 Google Workflow 上执行特定任务的示例:

(1)打印“Hello World”消息

(2)调用 HTTP 端点/ API /微服务

(3)用数组和字典进行循环和迭代

(4)向工作流添加日志

我们开始吧:

如果这是您第一次访问 Google Workflow,您将需要启用 API。

启用 Google 工作流 API

启用工作流 API 后,您可以创建新的工作流。选择“创建”以创建您的第一个工作流程:

创建 Google 工作流

点击“下一步”按钮,您可以开始定义您的工作流程。

(1)打印“Hello World”消息

让我们从基础开始,创建一个要返回的“Hello World”消息。我们需要定义一个返回消息的步骤。下面是我们将如何定义:

- returnHelloWorld:
        return: "Hello World"

工作流程示例—打印“Hello World”

定义完工作流后,单击“部署”按钮部署工作流,然后执行它。您会注意到,如果没有错误,您的工作流已经成功执行,输出消息为“Hello World”。

工作流示例—打印“Hello World”执行结果

恭喜你!您已经创建了第一个工作流。让我们继续,看看如何从 Google workflow 调用 API 端点。

(2)调用 HTTP 端点/ API /微服务

现在,我们将构建一个调用 HTTP 端点的步骤。常见的 HTTP 请求方法有“GET”和“POST”。但是在这个例子中,我们将尝试一个“HTTP。GET”请求使用已部署的云运行微服务。我们可以从部署的服务细节中检索云运行 URL。

云运行端点

这个云运行微服务使用 GET 方法,需要传递一个输入。在本例中,输入“AZ”(state-Arizona)将被传递给服务,它将返回一条消息,其中包含该州新冠肺炎病例总数的值。 (该数据集是 Google BigQuery 数据集程序下检索的新冠肺炎公共数据集,日期范围为 2020 年 5 月至 2020 年 10 月)

云运行微服务—返回消息

如上图所示,cloud run 服务将以 JSON 格式返回亚利桑那州的全部新冠肺炎病例。现在,要从 Google workflow 中调用这个服务,我们需要创建一个步骤( getMicroservice ),调用属性为“http.get”,URL 需要在参数下指定。

- getMicroservice:
       call: http.get
       args:
           url: [https://microservicesexample1-3wv4vbmeja-as.a.run.app/state/AZ](https://microservicesexample1-3wv4vbmeja-as.a.run.app/state/AZ)
       result: state_result
- returnResult:
       return: ${state_result.body}

工作流示例—呼叫端点

注意,在最后一步( returnResult ),我们从 HTTP 端点检索返回消息的主体。返回消息将采用 JSON 格式,说明它是如何被指定的,并从云运行微服务返回。

工作流示例—调用端点执行结果

干得好!您现在了解了如何在 Google Workflow 中调用 URL。让我们继续,看看如何通过迭代数组值列表来创建循环和迭代。

(3)用数组和字典进行循环和迭代

在本例中,我们将创建循环和迭代,这些循环和迭代将遍历定义的数组列表,并将数组值传递给 HTTP 端点,并使用不同的输入值多次触发 HTTP 端点。在上一步中,我们只传递了“Arizona(AZ)”的输入值,而数据集中还有其他州。让我们看看如何为多个状态创建一个数组列表,并通过多次迭代传递这个值来调用 HTTP 端点。我们将创建一个数组列表来调用“亚利桑那(AZ),加利福尼亚(CA),佛罗里达(FA)”。

- define:
        assign:
            - array: ['AZ','CA','FL']
            - result: ""
            - i: 0
    - checkCondition:
        switch: 
            - condition: ${i<len(array)}
              next: iterate
        next: returnResult 
    - iterate:
        steps:
            - getMicroservice:
                call: http.get
                args:
                    url: ${"[https://microservicesexample1-3wv4vbmeja-as.a.run.app/state/](https://microservicesexample1-3wv4vbmeja-as.a.run.app/state/)"+array[i]}
                result: state_result
            - assign_loop:
                assign:
                    - i: ${i+1}
        next: checkCondition
    - returnResult:
        return: ${"Result has been Successfully executed"}

注意,有一个称为( checkCondition) 的步骤,用于决定循环应该何时结束。如果循环条件为真,它将把数组值传递给步骤(迭代)。在步骤( iterate) 下,数组值将作为输入值传递给 HTTP 端点“ +array[i]”。在完成数组列表中的值的迭代后,循环将结束并移动到最后一步( returnResult )。

工作流示例—使用数组列表进行循环和迭代

干得好!您现在已经了解了如何创建一个循环并使用数组列表进行迭代。接下来,我们想添加日志来了解每个循环中发生了什么。

(4)向工作流添加日志

在 Google workflow 中,有内置的日志记录功能,我们可以将这些功能添加到工作流中,以创建更多关于正在发生的事情的可见性。例如,在我们前面的例子中,我们想知道在每个循环中传递哪个数组值,以及这些值是什么。让我们将这个额外的日志步骤添加到我们的工作流中。

- define:
        assign:
            - array: ['AZ','CA','FL']
            - result: ""
            - i: 0
    - checkCondition:
        switch: 
            - condition: ${i<len(array)}
              next: iterate
        next: returnResult 
    - iterate:
        steps:
            - logstep-1:
                call: sys.log
                args:
                    text: ${"Job is running for " + array[i]}
                    severity: INFO
            - getMicroservice:
                call: http.get
                args:
                    url: ${"[https://microservicesexample1-3wv4vbmeja-as.a.run.app/state/](https://microservicesexample1-3wv4vbmeja-as.a.run.app/state/)"+array[i]}
                result: state_result
            - logstep-2:
                call: sys.log
                args: 
                    text: ${"Result for State " + array[i] + " total is " + state_result.body.Total}
                    severity: INFO
            - assign_loop:
                assign:
                    - i: ${i+1}
        next: checkCondition
    - returnResult:
        return: ${"Result has been Successfully executed"}

要将日志添加到工作流中,只需添加一个新步骤和对函数“sys.log”的调用。在示例 create 中,有几个关于严重性的选项,如 INFO、WARNING、CRITICAL 等。请注意,在下面的可视化中,logs 步骤被添加为循环迭代的一部分。因此,日志会打印出每次迭代中发生的事情。

工作流示例—添加日志

可以通过导航到日志选项卡来查看日志。让我们看看我们的日志上打印了什么:

工作流示例-添加日志:日志结果

从日志中我们可以看到,我们知道第一次运行的迭代是针对 Arizona (AZ)的,总案例数是 140471。后续的迭代细节也会在日志中打印出来。添加日志确实让工作流中发生的事情更加清晰。

结论:

当您需要管理多个服务时,例如处理一系列事件/API,Google workflow 是一个合适的平台。此外,它易于管理,因为不需要基础架构,并且平台可以按需扩展。Google Workflow 中还有本文没有涉及的其他特性,比如错误处理、重试步骤、睡眠功能等。尽管如此,我希望这篇文章能让你很好地理解如何在 Google Cloud 上创建工作流。

参考文献&链接:

[1]https://cloud.google.com/workflows/docs

[2]https://cloud . Google . com/workflows/docs/reference/stdlib/sys/log

[3]https://atamel . dev/posts/2020/09-08 _ first _ look _ at _ workflows/

了解如何使用 Spark ML 和 Spark 流

原文:https://towardsdatascience.com/learn-how-to-use-spark-ml-and-spark-streaming-3a731485d052?source=collection_archive---------9-----------------------

关于如何使用 SparkML 对使用 PySpark 的流数据进行预测的教程

马库斯·温克勒在 Unsplash 上的照片

目标:

在本文中,我将通过一个例子来说明如何使用 Spark ML 来预测流数据。请注意,我们不会将重点放在比较不同的模型和调整模型上。主要的焦点将是我们如何能够结合火花流来使用数据块进行预测。除此之外,您应该对如何使用 Spark ML 有一些基本的了解。如果你对 Spark ML 不熟悉,可以看看下面的视频。

对于这个例子,我们将根据某人的年龄、性别和医疗状况来预测他是否会心脏病发作。逻辑回归将被训练,我们流入看不见的数据来做预测。

数据收集:

杰西·奥里科在 Unsplash 上的照片

对于这个项目,我使用了 Kaggle 上可用的数据集。如果您想跟进,请点击此处的。数据由 303 行和 14 列组成。每行代表一名患者的信息。此数据集的要素由以下各列组成:

  • 年龄:以年为单位的年龄 1。年龄:以年为单位的年龄
  • 性别:性别(1 =男性;0 =女性)
  • cp:胸痛型(1 =典型心绞痛;2 =不典型心绞痛;3 =非
    心绞痛;0 =无症状)
  • trtbps:静息血压(入院时以毫米汞柱为单位)
  • chol:血清胆固醇,单位为毫克/分升
  • fbs:空腹血糖> 120 mg/dl (1 =真;0 =假)
  • restecg:静息心电图结果(1 =正常;2 = ST-T
    波异常;0 =肥大)
  • thalachh:达到最大心率
  • exng:运动诱发心绞痛(1 =是;0 =否)
  • oldpeak:相对于静息运动诱发的 ST 段压低
  • slp:运动 ST 段峰值的斜率(2 =上坡;1 =平坦;
    0 =下降)
  • caa:透视着色的主要血管数(0-3)
  • thall: 2 =正常;1 =固定缺陷;3 =可逆缺陷

目标列如下:

  • 输出:0=心脏病发作几率降低,1=心脏病发作几率增加。

第一步是创建一个模式,以确保在读取 csv 文件时数据包含正确的数据类型。接下来,我们将使用 spark.read.format()函数,以“csv”作为参数,添加选项以读入标头,并将我们创建的模式分配给数据框。最后,我们加载数据,我们还将目标列更改为 label,以便我们的逻辑回归可以识别目标变量是哪一列。

from pyspark.ml import Pipeline
from pyspark.sql.types import StructType,StructField,LongType, StringType,DoubleType,TimestampType# We use the following schema
schema = StructType( \
                     [StructField("age", LongType(),True), \
                      StructField("sex", LongType(), True), \
                      StructField("cp", LongType(), True), \
                      StructField('trtbps', LongType(), True), \
                      StructField("chol", LongType(), True), \
                      StructField("fbs", LongType(), True), \
                      StructField("restecg", LongType(), True), \
                      StructField("thalachh", LongType(), True),\
                      StructField("exng", LongType(), True), \
                      StructField("oldpeak", DoubleType(), True), \
                      StructField("slp", LongType(),True), \
                      StructField("caa", LongType(), True), \
                      StructField("thall", LongType(), True), \
                      StructField("output", LongType(), True), \
                        ])data = "dbfs:/FileStore/tables/heart.csv"
df=spark.read.format('csv').option('header',True).schema(schema).load(data)
df = df.withColumnRenamed("output","label")
df.display()
df.printSchema()

一旦我们运行上面的代码,我们会得到下面的输出:

作者图片

机器学习:

说到数据预处理步骤,我首先将数据分为训练集(70%)和测试集(30%)。

testDF, trainDF = df.randomSplit([0.3, 0.7])

之后,我创建了一个包含五个阶段的管道。第一阶段是一个向量汇编器,它接收 age、trtbps、chol、thalachh、oldpeak 列,并将它们转换成一个向量。第二阶段需要上述特征的缩放过程。我使用 pyspark.ml.feature 库中的 MinMaxScaler()函数。之后,我一次性编码了 sex、cp、fbs、restecg、slp、exng、caa 和 thall 列,因为它们是名义上的分类变量。接下来,我创建了第二个矢量组装器,并将一个 hot 编码列和缩放特征添加到一个矢量中。最后但并非最不重要的是,最后一个阶段由具有以下参数的逻辑回归组成:

  • maxIter = 10
  • regParam = 0.01

我选择了逻辑回归算法,因为我们的目标由二进制数(0 和 1)组成。一旦创建了管道,我就调整并转换训练集。之后,我选择标签、概率和预测列。训练模型时,请参见下面管道施工和预测的片段。

from pyspark.ml.feature import OneHotEncoder
from pyspark.ml.feature import MinMaxScaler
from pyspark.ml.feature import StringIndexer
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.feature import OneHotEncoder
from pyspark.ml.classification import LogisticRegression# Create the logistic regression model
lr = LogisticRegression(maxIter=10, regParam= 0.01)# We create a one hot encoder.
ohe = OneHotEncoder(inputCols = ['sex', 'cp', 'fbs', 'restecg', 'slp', 'exng', 'caa', 'thall'], outputCols=['sex_ohe', 'cp_ohe', 'fbs_ohe', 'restecg_ohe', 'slp_ohe', 'exng_ohe', 'caa_ohe', 'thall_ohe'])# Input list for scaling
inputs = ['age','trtbps','chol','thalachh','oldpeak']# We scale our inputs
assembler1 = VectorAssembler(inputCols=inputs, outputCol="features_scaled1")
scaler = MinMaxScaler(inputCol="features_scaled1", outputCol="features_scaled")# We create a second assembler for the encoded columns.
assembler2 = VectorAssembler(inputCols=['sex_ohe', 'cp_ohe', 'fbs_ohe', 'restecg_ohe', 'slp_ohe', 'exng_ohe', 'caa_ohe', 'thall_ohe','features_scaled'], outputCol="features")# Create stages list
myStages = [assembler1, scaler, ohe, assembler2,lr]# Set up the pipeline
pipeline = Pipeline(stages= myStages)# We fit the model using the training data.
pModel = pipeline.fit(trainDF)# We transform the data.
trainingPred = pModel.transform(trainDF)# # We select the actual label, probability and predictions
trainingPred.select('label','probability','prediction').show()

作者图片

正如我们在上面看到的,标记的黄色行表明概率越低,模型越有信心预测为 1。另一方面,标记的红色行显示概率越高,它预测输出为零就越确定。除此之外,我还评估了模型的性能,计算了总的准确度分数。请看下面我如何计算准确度分数的代码片段。

作者图片

在对训练数据进行模型训练时,准确率达到了 0.902913%,这是一个令人满意的结果。

流媒体:

为了合并 Spark 流,我将测试数据集重新划分为十个不同的文件来复制流模拟。

# We now repartition the test data and break them down into 10 different files and write it to a csv file.
testData = testDF.repartition(10)#Remove directory in case we rerun it multiple times.
dbutils.fs.rm("FileStore/tables/HeartTest/",True)#Create a directory
testData.write.format("CSV").option("header",True).save("FileStore/tables/HeartTest/")

之后,我首先创建了一个源代码,它由以下代码行组成。

# Source
sourceStream=spark.readStream.format("csv").option("header",True).schema(schema).option("ignoreLeadingWhiteSpace",True).option("mode","dropMalformed").option("maxFilesPerTrigger",1).load("dbfs:/FileStore/tables/HeartTest").withColumnRenamed("output","label")

从上面可以看到,我使用 spark.readStream,读入一个格式为“csv”的文件。除此之外,我还添加了我在开始读取文件时创建的模式,后面是多个选项,例如:

  • ignoreleeadingwhitespace:True→删除前导空格。
  • 模式:drop formattered→当设置为 drop formattered 时,将忽略所有损坏的记录。
  • maxFilesPerTrigger: 1 →每个触发器中要考虑的新文件的最大数量。

之后,我从重新划分测试数据的目录中加载数据,以复制流的模拟。最后但同样重要的是,为了实现逻辑回归,我将输出列更改为 label。

最后一步是建立测试数据的流。我使用适合训练集(pModel)的管道,并使用带有参数“sourceStream”的转换功能,这是我之前创建的源。最后,我选择标签、概率和预测列。请参见下面的代码片段。

作者图片

正如我们所看到的,绿灯亮了,这表明我们正在传输看不见的数据,这些数据来自为了传输而重新划分以复制模拟的测试数据。下面是我们的流输出示例,它向我们展示了测试数据的实际标签、概率以及模型对未知数据的预测。

作者图片

为了评估对测试数据的预测,我们可以看到流数据属于哪一类的概率。例如,当我们看第 1 行时,我们可以看到概率列中的向量,它由[0.06936682704327157,0.93631729567284]组成。向量中的第一个元素表示 0 级(没有心脏病发作)的概率,第二个元素表示 1 级(心脏病发作)的概率。该模型选取较高的概率值,并将流数据分配给具有较高概率的类。在第一个示例中,模型预测 1,当与实际标签进行比较时,这是正确的。

最后的话:

我希望这个例子能帮助您更好地理解如何使用 Spark 的流数据进行预测。同样,本文的主要焦点不是关于模型的性能,而是关于我们如何在我们的机器学习模型中使用看不见的流数据。如果您对将 Spark 流合并到 Spark ML 有更多的问题,我强烈建议您仔细阅读 databricks 文档。请查看下面的链接:

如果你对这个话题有任何问题或者有任何反馈,请随时联系我。如果你能在任何社交媒体平台上分享这篇文章,我将不胜感激。谢谢,下次再见!✌️

https://www.navidma.com/

学习高级 Python 可视化:用例方法

原文:https://towardsdatascience.com/learn-plotly-for-advanced-python-visualization-a-use-case-approach-7a43b2f9d5d1?source=collection_archive---------28-----------------------

使用 Plotly Go 创建交互式散点图的实用指南

图像源( Pixabay )

介绍

我最近完成了一个有趣的数据科学项目,该项目使用无监督的机器学习根据几个关键的住房市场指标对北卡罗来纳州的 162 个社区进行了细分/聚类。如果你有兴趣了解更多关于这个项目的信息,你可以阅读我的文章房产市场聚类分析

在项目的最后,我使用 Tableau 绘制了一个散点图来可视化各个部分。散点图是一种优秀的可视化技术,适用于可视化分割结果等用例。它允许你将你的集群投射到“三维”上——前二维是你的 x 和 y 轴,第三维是气泡大小。下面是我为这个项目创建的 Tableau 仪表盘的截图。

在 Tableau 中绘制的散点图(图片由作者提供)

虽然 Tableau 是创建交互式可视化的绝佳工具,但在两个平台之间切换有点麻烦:在 Python 环境中训练模型和创建片段,然后在另一个工具中可视化结果。因此,在本教程中,我将向您展示如何使用 Python 的 Plotly Go (Graph Objects)来创建相同的交互式图表,这些图表具有定制的颜色和工具提示,可以满足我们在这个用例中的需求。

Plotly Express vs. Plotly Go

Plotly Python 库是一个交互式的开源绘图库,涵盖了广泛的图表类型和数据可视化用例。它有一个名为 Plotly Express 的包装器,是 Plotly 的高级接口。

Plotly Express 作为一个起点,使用简单的语法创建最常见的图形既简单又快捷,但在涉及更高级的图表类型或自定义时,它缺乏功能性和灵活性。

Plotly Express 相比,Plotly Go (图形对象)是一个较低级别的图形包,通常需要更多的编码,但更具可定制性和灵活性。在本教程中,我们将使用 Plotly Go 创建与 Tableau 中创建的相同的交互式散点图。您还可以将代码保存为模板,以便在其他用例中创建类似的图表。

阅读并准备数据

住房市场聚类分析项目结束时,我们创建了一个数据框,其中包含北卡罗来纳州 162 个社区的住房市场指标以及通过 k-means 算法分配给它们的聚类(cluster_nbr)。让我们来看看这些数据,看看这些数据是什么样的:

作者图片

我们有 162 行和 17 个字段。“cluster_nbr”字段是我们根据 k-means 算法分配给每个邻域的分类标签。最后三个字段是从 PCA 得到的主成分,这将允许我们将我们的聚类投影到散点图上,前两个主成分是 x 和 y 轴。

让我们也重命名一些列,使它们更容易理解。此外,cluster_nbr 列是一个整数,这在我们的代码中不会产生期望的输出。因此,我们需要将其数据类型更改为 string。

聚类数据(作者图片)

添加集群描述

现在我们已经读取并准备好了集群数据,让我们做一个快速分析来显示集群级别的汇总统计信息。这将帮助我们理解每个聚类的独特特征,并为每个聚类添加有意义的描述(而不是通用的聚类标签,如 0、1、2、3 等)。)

聚类摘要统计(按作者分类的图片)

基于汇总统计数据,我们可以描述每个集群的特征。例如,集群“1”的平均上市天数最短,年同比价格涨幅第二高,而集群“2”的市场价格相对较高,平均销售价格最高,但与去年相比价格降幅最大。这个集群中的房子也需要最长时间才能卖出去。根据我们的观察,我们可以向数据集添加一个分类描述列:

图片由作者提供

使用 Plotly 创建一个基本的散点图

为了熟悉 Plotly ,让我们首先创建一个标准简单的散点图,只有几行代码,如下所示。

基本散点图将 162 个街区投射到一个二维图表上。X 轴是第一个主成分(PC1 ),代表销售速度/上市天数指标。Y 轴是第二个主成分(PC2 ),它代表供应/新上市 YoY 指标。

使用 Plotly 的基本散点图(图片由作者提供)

当悬停在每个数据点上时,默认情况下,绘图会显示带有 x 和 y 坐标的工具提示。只用了几行代码,我们就制作了一个非常方便的基本交互式图表。现在,我们可以向图表中添加更多功能和自定义设置,使其信息量更大。具体来说,我们将通过以下方式定制和优化情节:

  • 用代表不同分类的自定义颜色显示数据点
  • 添加代表每个数据点的“销售价格增长中值(YoY)”的气泡大小
  • 自定义悬停工具提示以显示每个数据点的附加信息
  • 添加图表标题、x 轴和 y 轴标签等。

向基本散点图添加自定义内容

为了添加自定义项,如聚类颜色、气泡大小和悬停提示,我们需要首先向数据框添加三个新列,将这些“自定义参数”分配给每个数据点。

以下代码将向数据框添加一个名为“color”的新列。我们首先定义一个名为“color”的函数,它为每个 cluster_nbr 分配一个唯一的颜色代码(由我们指定)。然后,我们将该函数应用于数据帧中的每个数据点,使得每个数据点将根据其所属的聚类而具有其自己的颜色代码。

将“颜色”列添加到数据框(图片由作者提供)

我们还将为每个数据点添加一个名为“size”的新列,以显示每个气泡的大小。我们希望气泡的大小代表销售价格同比增长的中位数:气泡越大,与去年同期相比,销售价格的增幅越大。

一些数据点的中值价格变化变量为负值,当您试图直接使用该变量来绘制泡沫大小时,会出现错误。因此,让我们使用最小-最大缩放器来缩放此变量,并使其介于 0 和 1 之间,所有值都为正值。

为气泡大小添加大小“列”(图片由作者提供)

最后,让我们添加一个“文本”列,当鼠标悬停在每个数据点上时,它将显示定制的工具提示。这可以通过在下面的代码中使用代替循环来实现。

为自定义工具提示添加“文本”栏(图片由作者提供)

将所有定制放在一起

现在我们已经将自定义列添加到了数据框中,我们可以创建一个图形并将这些自定义添加到图形中。

在下面的代码中,我们首先创建一个字典,其中包含每个聚类的数据框。然后,我们创建一个图形,并添加使用第一个集群的数据帧的第一个轨迹。我们遍历字典,将剩余的轨迹(聚类)一次一个地添加到图形中,并最终在同一个图形中绘制所有的聚类。

带有自定义颜色和工具提示的气泡图(图片由作者提供)

设置图表的样式和格式

我们实现了定制基本散点图的目标,用不同的颜色分割、工具提示中的定制文本以及指定的气泡大小。我们注意到,在工具提示中,一些指标显示在许多小数位,很难阅读。有些指标用百分比表示可能更好。因此,让我们改变一下样式,让工具提示更容易理解。

我们还将向图表添加图表标题和轴标签。请记住,我们的 x 轴和 y 轴是代表销售速度和供应/新上市同比的两个主要组成部分,因此让我们根据这些含义来标记轴。

交互式散点图(图片由作者提供)

现在我们用 Python 和 Plotly 创建了一个交互式散点气泡图!最初我认为这应该是一个很容易制作的图表。但是正如您所看到的,当您实际处理一个真实世界的用例时,在您的编码中有许多细节和细微差别需要考虑,以使图表看起来完全像您所想的那样!感谢阅读,我希望你喜欢这篇文章。快乐学习!

你可以通过这个推荐链接注册 Medium 会员(每月 5 美元)来获得我的作品和 Medium 的其他内容。通过这个链接注册,我将收到你的一部分会员费,不需要你额外付费。谢谢大家!

学习力量 BI: 10 个免费资源

原文:https://towardsdatascience.com/learn-power-bi-free-resources-88238927045d?source=collection_archive---------34-----------------------

用于学习 DAX、Power Query、数据建模等的 10 种免费资源

照片由马太·亨利发自突发

当开始使用新工具时,可能很难知道从哪里开始。这里有一些免费的资源,可以帮助你开始你的商务智能之旅:
1。Dax 和 Power 查询/M
2。数据建模
3。持续学习
4。社区和实践

我们开始吧!

DAX 和 Power 查询/M

当我刚开始使用 Power BI 时,我最大的障碍之一是理解 DAX 和 M 以及计算列和度量之间的差异。简而言之, power query 是您用来将数据加载并格式化到 Power BI 中的引擎。 M 是 power query 背后的语言——你可以用 M 写出函数,也可以通过指向和点击来使用 power query。 DAX 有点像你放在 Excel 的公式栏中的 Power BI 版本(这是一个超级简化的版本,所以一旦你更熟悉了,请不要回来对我大喊大叫)。这里有一个更全面的差异概述。

1。SQBLI to Learn DAX :数据分析表达式(DAX)是您在 Power BI 中工作得越来越多就会越来越熟悉的东西。如果没有遇到 Marco Russo 和 Alberto Ferrari,你也不太可能在 Power BI 之旅中走得很远,他们是 SQLBI 和丰富的 Power BI 资源(许多是免费的,有些是付费的)的幕后策划者。

2。DAX 指南 (同样来自 SQLBI):DAX 公式的参考指南。当使用一个新的公式时,本指南将为您提供所需的参数以及如何正确使用的示例。这是一个很好的书签,并参考定期回来!

3。DAX 图案 (还从,你猜对了,SQLBI!):超级有用的一些常见 DAX 模式的演练,如时间智能计算。随着你开始更多地使用 DAX,你会发现它会很快变得复杂。浏览这些示例模式有助于直观地理解如何在 DAX 中有效地处理复杂的问题。

数据建模

4。理解星型模式 :该资源来自微软,因此您可以直接从马嘴里听到它!星型模式是 Power BI 中数据建模的基础。这个概述对那些不太熟悉建模的人特别有用。想知道事实表和维度表之间的区别吗?在这里找到你的答案!(短文)

5。平面文件到数据模型 (来自 Guy in a Cube YouTube):这将对那些习惯于使用单个 Excel 文件的人有所帮助。Guy in a Cube 一步一步地介绍了如何从单个文件构建数据模型!(10 分钟视频)

持续学习

以下是一些您可以持续访问的资源,以了解更多微妙的 Power BI 概念。这里有两个很棒的 YouTube 频道,它们不断推出令人惊叹的新内容:

⑥。立方体中的家伙:帕特里克和亚当做了一项惊人的工作,让人们感觉可以轻松获得力量。每个级别的体验都有内容!
-周一:信息综述
-周二和周三:技术视频

7。Curbal :虽然也有入门级的内容,但 Ruth 通常有更高级的技术内容。她还有很多关于 power query 和 M 的信息,这些信息有时很难找到。
-周一:电力查询
-周三:电力 BI
-周五:DAX。

社区和实践

拥有一个支持你的社区和练习的机会,对于你是否采用一项新技能来说是至关重要的。Power BI 也不例外。幸运的是,Power BI 和更大的数据 viz 社区一直在呈指数增长,因此每天都有更多的资源和更多的人可以求助。以下是一些开始的地方:

蒂姆·马歇尔在 Unsplash 上的照片

第八期。锻炼周三 (WoW):这是 2021 年新的 Power BI 社区挑战赛。WoW 有一个受欢迎的 Tableau 每周挑战,它是如此令人兴奋地看到类似的东西现在被提供给 Power BI!

https://jeagleson.medium.com/new-in-2021-learn-power-bi-with-weekly-challenges-8742db48a52

9。Power BI 社区 :当你在某个特定问题上需要帮助时,这里是你可以去的地方。在发布新内容之前,总是先尝试搜索一下,看看是否有人已经回答了类似的问题。发帖时请遵循本指南,以便您的问题更快得到解答。

10。DAX.do :这是 SQLBI 免费提供的另一个神奇的工具。这是一个新的工具,让您可以轻松地测试和共享 DAX 所有在您的浏览器!难以置信!

奖金

Twitter :我从来都不是 Twitter 的忠实粉丝,但那里的数据社区(#datafam)令人惊叹。首先是一些标签:#powerbi、#dax、#powerquery 和#dataviz。那里有大量的内容可以激发灵感,还有一个社区随时准备支持和鼓励你。

在学习 Power BI 时,您发现的最有帮助的资源是什么?你如何保持你的商务智能知识和技能是最新的?

继续用你的头撞墙——这样会好得多!

詹娜·伊格尔森我的背景是工业组织心理学,我在人物分析中找到了自己的家。数据使我的作品变得生动。我主要使用 Power BI,但偶尔也会使用 Tableau 和其他工具。我很想听到更多关于你的旅程!在此评论或在LinkedinTwitter上留言联系我。

通过示例了解 Python 数据分析-航班到达延误

原文:https://towardsdatascience.com/learn-python-data-analytics-by-example-airline-arrival-delays-e26356e8ae6b?source=collection_archive---------10-----------------------

一个有趣的项目和详细的数据分析步骤演练,帮助您学习 Python、pandas、matplotlib 和底图

Unsplash 上的 CHUTTERSNAP 拍摄

介绍

在攻读商业分析硕士学位期间,我发现通过实例学习是我学习 Python 数据分析的最佳方式。获得一个数据集和一组编码任务比阅读教科书或听教授讲课要有益得多。

我想把这种学习方法分享给其他人,他们也会受益。你需要的只是一个 Python 开发环境(我推荐 Jupyter Notebook )和乐于学习的意愿。

本文包括一个数据分析任务列表,后面是如何完成这些任务的详细演练。在通读演练之前,请尝试自己完成这些任务,这样您会获得更多的收获。请记住,有很多方法可以解决编码问题,所以你的代码可能不会和我的一字不差,这没关系。

另请查看:通过示例学习 Python 数据分析:纽约市停车违规

项目描述

对于这个项目,我们将使用大约 40,000 条记录的数据集,这些记录代表了美国 18 家航空公司的航班到达延迟。数据集中的每一行代表指定月份的承运商-机场对的延误数据的汇总。该数据集创建于 2021 年 1 月,包含 2018 年 1 月 1 日至 2019 年 12 月 31 日的数据,数据来源于交通统计局

如果你还没有熊猫matplotlib底图库,你需要安装它们。

数据分析任务

请使用从 GitHub repo 中获得的 delays_2018.csvdelays_2019.csvairport _ coordinates . CSV数据集在 Python 中执行以下任务。

  1. 将包含航班延误数据的 CSV 文件读入单个数据帧。然后显示导入的总行数。
  2. 日期列改为日期格式 YYYY-M(如 2018–1)。然后对导入的数据集执行探索性数据分析,以识别无效数据—编写代码以删除受影响的行。最后,显示剩余的行数。
  3. 显示数据集中出现的所有田纳西机场的列表。
  4. 导入坐标数据集,并将其与现有数据集合并。在地图上标出所有机场的坐标(提示:使用 Matplotlib 和底图)。
  5. 显示每个承运商-机场对的改航航班数量。
  6. 显示 2019 年有多少抵达 JFK 的航班遇到了天气和承运人延误。
  7. 显示航班取消最多的航空公司,占到达航班总数的百分比。
  8. 确定每个机场的总平均延误次数。
  9. 请显示延误航班数量最少的三家航空公司。
  10. 请求用户输入航空公司。然后画出该航空公司每月的国家航空系统(NAS)延误分钟数。显示趋势在过去两个月是上升还是下降。

数据字典(delays_2018.csv,delays_2019.csv)

数据集中的每一行代表指定月份的承运商-机场对的延误数据的汇总。例如,一行可以表示 2018 年 5 月到达纽约市 JFK 机场的美国航空公司航班的延迟数据。

当多个原因被分配给一个延误的航班时,每个原因根据它所负责的延误分钟数按比例分摊。这些数字是四舍五入的,相加可能不等于总数。

约翰尼·科恩Unsplash 上拍摄的照片

步骤 1:将包含航班延误数据的 CSV 文件读入单个数据帧。然后显示导入的总行数。

Number of Rows: 41177

代码解释:

我们首先将熊猫模块的内容提供给我们的程序。pandas 是一个易于使用的开源数据分析和操作工具,构建于 Python 编程语言之上。我们将在整个项目中广泛使用它。

import pandas as pd

我们通过调用 read_csv()方法导入 delays_2018.csv 文件的内容,并将其存储在一个 DataFrame 中,命名为 df_18 。DataFrame 是一个带有标记轴的二维数据结构,由数据、行和列组成。可以把它想象成在 Microsoft Excel 或 Microsoft Access 中构建的表。然后,我们对 delays_2019.csv 文件重复相同的操作,将其命名为 df_19

df_18 = pd.read_csv('delays_2018.csv')
df_19 = pd.read_csv('delays_2019.csv')

为了将两个数据帧组合成一个数据帧,我们调用 pandas 的 concat()方法,这是 concatenate 的缩写。我们传递两个参数:第一个是包含我们想要连接的两个数据帧的名称的列表,第二个是告诉 pandas 忽略两个数据帧中的现有索引,从而创建一个新的索引。

df = pd.concat([df_18, df_19], ignore_index=True)

我们使用 print()函数打印字符串‘Number of Rows:'后跟 DataFrame 中的行数。我们传递给 print()函数的参数由两部分组成。第一个是用单引号括起来的字符串“Number of Rows:”表示它是一个字符串。参数的第二部分是计算 df 中的行数。我们使用 len()函数告诉我们 df 中的行数,然后将其封装在对 str()方法的调用中,将长度转换为字符串。最后,+将两个字符串部分连接在一起。传递给 print()函数的参数的所有部分都必须是字符串类型。

print('Number of Rows: ' + str(len(df)))

第二步:将日期列改为日期格式 YYYY-M(如 2018–1)。然后对导入的数据集执行探索性数据分析,以识别无效数据—编写代码以删除受影响的行。最后,显示剩余的行数。

以下数据被视为无效:

  • 年份:不是 2018 或 2019 的值
  • 到达航班:没有到达航班的机场( arr_flights 栏空白值)
  • 承运人:空白值
  • 机场:空白值
Number of Rows: 41077

代码解释:

在我们寻找无效数据之前,我们将把日期列从字符串数据类型转换为日期。为此,我们调用 pandas 的 to_datetime()方法。作为参数,我们传递现有的日期列和日期格式,即使它们存储为字符串。%Y-%m 代表 YYYY-M,例如 2018–1。如果我们停在这里,那么熊猫会用年、月、日和时间格式化日期,这是我们不希望的。为了避免这种情况,我们使用. dt.strftime('%Y-%m ')来强制我们需要的日期格式。

df['date'] = pd.to_datetime(df['date'], format='%Y-%m').dt.strftime('%Y-%m')

我们需要子集 df 来过滤掉无效数据的记录。我们可以通过将每个参数括在括号中并在它们之间使用&字符来一次应用多个参数。我们用> =表示大于等于,< =表示小于等于。对于到达航班、承运人、承运人名称、机场和机场名称列,我们需要通过调用 notnull()方法来检查 null 值。

df = df[(df['date'] >= '2018-01') & (df['date'] <= '2019-12') & (df['arr_flights'].notnull())
              & (df['carrier'].notnull()) & (df['carrier_name'].notnull()) 
              & (df['airport'].notnull()) & (df['airport_name'].notnull())]

我们使用 print()函数的方式与上面的步骤 1 完全相同。

print('Number of Rows: ' + str(len(df)))

第三步。显示数据集中出现的所有田纳西机场的列表。

Tennessee Airports:
{'Chattanooga, TN: Lovell Field', 'Memphis, TN: Memphis International', 'Bristol/Johnson City/Kingsport, TN: Tri Cities', 'Nashville, TN: Nashville International', 'Knoxville, TN: McGhee Tyson'}

代码解释:

首先,我们需要识别数据集中到达田纳西机场的航班的行。为此,我们需要沿着数据帧的轴应用一个函数。因为我们没有指定轴,所以默认为 0,这是索引。因此,我们将向下迭代机场名称列。

lambda 函数对每个机场名称调用 find()方法,以便在其中查找子字符串 TN 。如果在机场名称中没有找到子字符串 TN ,则在新的 TN 列中放置一个值-1。如果找到了 TN ,则将一个非-1 的整数放入 TN 列。

df['TN'] = df['airport_name'].apply(lambda x: x.find('TN'))

既然我们已经确定了田纳西州的所有机场,我们需要创建一个它们的列表,但是不要重复。我们可以使用 set()函数来实现这一点,并作为参数传递 DataFrame 的一个子集,该子集仅包含机场名称包含 TN 的行,如 TN 列中的 a -1 所示。

airports = set(df[df['TN'] != -1]['airport_name'])

然后我们打印出田纳西机场的列表。

print('Tennessee Airports:')
print(airports)

第四步。导入坐标数据集,并将其与现有数据集合并。在地图上标出所有机场的坐标(提示:使用 Matplotlib 和底图)。

代码解释:

请在这一点上容忍我,因为有许多代码需要解释。这种努力是值得的,因为您将学习如何显示地图并使用坐标在地图上绘制点。

我们通过调用 read_csv()方法导入 airport_coordinates.csv 文件的内容,并将其存储在名为 df_coords 的 DataFrame 中。

df_coords = pd.read_csv('airport_coordinates.csv')

我们现在将创建一个新的数据框架来表示数据集中的所有机场及其坐标。我们将 df 分成子集,只包含机场和机场名称的列。通过添加对 drop_duplicates()函数的调用,我们能够创建一个每个机场只出现一次的数据帧。最后,通过调用 reset_index()函数,我们将数据帧索引重置为原始索引。

df_airports = df[['airport', 'airport_name']].drop_duplicates().reset_index(drop=True)

现在,我们使用 pandas 的 merge()函数来合并 df_airportdf_coords 数据帧,以创建我们最终的机场数据帧及其各自的坐标。前两个参数是我们正在合并的数据帧,第三个参数是两个数据帧中的公共列— airport,它是到达机场的三个字符指示符。

df_airports = pd.merge(df_airports, df_coords, on='airport')

您可能需要也可能不需要下面的代码行。我在从 mpl_toolkits.basemap 导入底图代码行运行时遇到了一个错误,解决方案是添加以下内容。

import os
os.environ["PROJ_LIB"] = "C:\\Users\\Nick\\anaconda3\\envs\\sandbox\\Library\\share\\basemap";

我们让 matplotlib 库的内容对我们的程序可用。matplotlib 是一个用于在 Python 中创建可视化的综合库。

然后,我们将 mpl_toolkits.basemap 库提供给我们的程序使用。底图是一个用于在地图上绘制 2D 数据的库,我们将使用它来绘制数据集中的机场地图。

import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap

我们指定地图的大小为 16 x 16。接下来,我们创建一个底图类的实例,传递一大组参数。前四个(llcrnclon、llcrnrlat、urcrnrlon 和 urcrnrlat)指定绘图左下角的经度、左下角的纬度、右上角的经度和右上角的纬度。对于这个项目,我们正在指定坐标,给我们一个美国地图。对于项目参数,我们将通过 lcc (Lambert Conformal ),它通常用于航空图表。其余参数是特定于 lcc 的选择。

有关参数的更详细描述,请参考官方的底图文档

fig = plt.figure(figsize=(16, 16))
m = Basemap(llcrnrlon=-119,llcrnrlat=22,urcrnrlon=-64,urcrnrlat=49,
        projection='lcc',lat_1=32,lat_2=45,lon_0=-95)

上述代码为我们提供了地块上的正确坐标,但没有为我们提供美国及其各州的轮廓。为此,我们需要使用 shapefiles。该项目所需的 shapefiles 可以在底图 GitHub repo 中找到。查找 st99_d00.dbf、st99_d00.shp 和 st99_d00.shx,将这些文件放在与其他源文件相同的文件夹中。

我们在 Basemap 对象上调用 readshapefile()方法,并向它传递两个参数。第一个是我们下载的 shapefile 的名称,第二个是我们分配给保存 shapefile 映射点的属性的名称。

m.readshapefile('st99_d00', name='states')

现在剩下的工作就是通过调用底图对象的 scatter()方法在地图上绘制坐标。传递的参数是我们的 df_airports 数据帧中机场的经度和纬度坐标,latlon 参数等于 True,表示我们的坐标以度为单位。我们指定。值,以便只传递数据帧中的值,从而排除索引。

m.scatter(df_airports['long'].values, df_airports['lat'].values, latlon=True)
plt.show()

第五步。显示每个承运商-机场对的改航航班数量。

代码解释:

创建了一个很棒的地图绘图后,我们现在将转向另一个强大的 pandas 函数——crosstab。交叉制表是一种定量分析多个变量之间关系的方法。在这个项目中,我们希望确定每个航空公司-机场对的改航航班数量,例如:有多少计划到达 JFK 机场的美国航空公司航班被改航?使用 pandas 的 crosstab()函数,我们可以创建一个表,显示我们数据集中所有航空公司-机场对的信息。

我们传递的第一个参数是来自 df 的 carrier 列,这将是我们的交叉表中的行。第二个是 airport 列,这将是我们的交叉表中的列。我们希望在交叉表中显示的值是改航航班的数量,arr_diverted 列。使用第四个参数,我们指定要对每个承运商-机场对的改航次数求和,这是必需的,因为每个承运商-机场对在数据集中出现多次,每月一次。最后,我们通过调用 fillna()函数用空白替换 NaN 值来结束这一行代码——这消除了结果交叉表中的噪声,并降低了可读性。

只有一行代码,但是非常强大。

pd.crosstab(df['carrier'], df['airport'], values=df['arr_diverted'], aggfunc='sum').fillna('')

第六步。显示 2019 年有多少抵达 JFK 的航班遇到了天气和承运人延误。

Number of Delays: 6919.429999999999

代码解释:

我们在上面的步骤 2 中使用了类似的代码。我们正在对 df 进行子集化,以便只获取那些代表 2019 年抵达 JFK 的航班的行,这些航班既有航空公司的延误,也有天气原因的延误。我们将结果存储为 df_f

df_f = df[(df['date'] >= '2019-01') & (df['date'] <= '2019-12') & (df['airport'] == 'JFK') 
          & (df['carrier_ct'] > 0) & (df['weather_ct'] > 0)]

延误总数是承运人和天气延误的总和,我们打印出来。请记住,在打印之前,我们需要将总和转换为字符串。

print("Number of Delays: " + str(df_f['carrier_ct'].sum()  + df_f['weather_ct'].sum()))

第七步。显示航班取消最多的航空公司,占到达航班总数的百分比。

代码解释:

为了计算取消百分比,我们需要表示分子(取消的航班)和分母(所有航班)的数据框架。我们从后者开始:我们按照承运商名称对 df 中的行进行分组,并对每个承运商到达的航班数量进行求和。我们将“num_arrived”的 name 参数传递给 reset_index()函数,以命名包含总和值的列。

然后,我们按照承运商名称对 df 中的行进行分组,并对每个承运商取消的到达次数进行求和。我们再次使用 reset_index()。最后,我们通过使用“carrier_name”的公共列合并数据帧来创建 df_cancelled 数据帧。

df_flights = df.groupby('carrier_name')['arr_flights'].sum().reset_index(name='num_arrived')
df_cancelled = df.groupby('carrier_name')['arr_cancelled'].sum().reset_index(name='num_cancelled')
df_cancelled = pd.merge(df_cancelled, df_flights, on='carrier_name')

然后,我们可以通过将每个承运商取消的航班数除以到达的航班数来计算每个承运商取消航班的百分比。

df_cancelled['proportion'] = df_cancelled['num_cancelled'] / df_cancelled['num_arrived'] * 100

最后一步,我们通过调用 sort_values()函数对值进行降序排序,然后使用 head(1)只显示取消航班百分比最高的航空公司。

df_cancelled.sort_values(by=['proportion'], ascending=False).head(1)

第八步。确定每个机场的总平均延误次数。

Average Number of Delays per Airport: 7544.997245179064

代码解释:

为了计算每个机场的总平均延误次数,我们首先需要计算每个机场的延误次数,然后求出这些值的平均值。我们能够在一行代码中实现这一点。我们按照机场对 df 中的行进行分组,并对每个机场的延迟到达数进行求和。通过在最后添加对 mean()函数的调用,我们计算出总和的平均值。

avg_delays = df.groupby('airport')['arr_del15'].sum().mean()

然后我们简单地打印出结果。

print('Average Number of Delays per Airport: ' + str(avg_delays))

第九步。请显示延误航班数量最少的三家航空公司。

代码解释:

我们按承运人对 df 中的行进行分组,并对每个承运人的延迟到达次数进行求和。我们只对延迟到达次数最少的三家承运商感兴趣,所以使用。给我们三个最低的承运人。出于显示的目的,我们在对 reset_index()的调用中传递 name 参数。

df.groupby('carrier')['arr_del15'].sum().nsmallest(3).reset_index(name='num_delays')

第十步。请求用户输入航空公司。然后画出该航空公司每月的国家航空系统(NAS)延误分钟数。显示趋势在过去两个月是上升还是下降。

What airline (9E, AA, AS, B6, DL, EV, F9, G4, HA, MQ, NK, OH, OO, UA, VX, WN, YV, YX)? EV

Total NAS delay minutes for EV are increasing.

代码解释:

我们使用 input()请求用户输入承运人,并将值保存在航空公司变量中。为了保持代码简单,我们不对用户输入的内容执行任何验证检查,因此我们希望他们只输入有效值。

airline = input("What airline (9E, AA, AS, B6, DL, EV, F9, G4, HA, MQ, NK, OH, OO, UA, VX, WN, YV, YX)? ")

我们根据用户输入的承运人子集 df ,因为我们只对国家航空系统(NAS)延迟感兴趣,所以我们也对其进行过滤,以排除没有任何 NAS 延迟的行。我们将结果存储为 df_nas

df_nas = df[(df['carrier'] == airline) & (df['nas_delay'] > 0)]

我们按照日期对 df_nas 中的行进行分组,并对每个月 nas 延迟的数量进行求和。

df_nas = df_nas.groupby('date')['nas_delay'].sum()

现在是我们使用 matplotlib 绘制结果的时候了。我们指定 16 x 8 作为图的大小, df_nas 作为图的数据源,因为在 x 轴上有许多标签,我们将它们旋转 85 度以整齐地显示它们而没有重叠。

plt.figure(figsize=(16, 8))
plt.plot(df_nas)
plt.xticks(rotation=85)
plt.show()

项目的最后一步是显示用户选择的运营商在过去两个月中 NAS 延迟是增加还是减少。我们可以使用简单的 if-else 逻辑来打印一个增加或减少的语句。我们利用 iloc 基于整数的索引来访问 df_nas 中的最后一个值(-1)和倒数第二个值(-2),并对它们进行比较。如果最后一个值大于倒数第二个值,则延迟增加,否则延迟减少。

if df_nas.iloc[-1] > df_nas.iloc[-2]:
    print('Total NAS delay minutes for ' + airline + ' are increasing.')
else:
    print('Total NAS delay minutes for ' + airline + ' are decreasing.')

我希望你已经发现这个项目是学习 Python 数据分析的一个有用的方法。请在评论区分享您的反馈。

另请查看:通过示例学习 Python 数据分析:纽约市停车违规

通过示例了解 Python 数据分析—芝加哥交通事故

原文:https://towardsdatascience.com/learn-python-data-analytics-by-example-chicago-traffic-crashes-4840f6f15ed?source=collection_archive---------22-----------------------

一个有趣的项目和详细的数据分析步骤演练,帮助您学习 Python、pandas、matplotlib、seaborn 和 Folium

介绍

在攻读商业分析硕士学位期间,我发现通过实例学习是我学习 Python 数据分析的最佳方式。获得一个数据集和一组编码任务比阅读教科书或听教授讲课要有益得多。

我想把这种学习方法分享给其他人,他们也会受益。你所需要的只是一个 Python 开发环境(我推荐 Jupyter Notebook )和乐于学习的意愿。

本文包括一个数据分析任务列表,后面是如何完成这些任务的详细演练。在通读演练之前,请尝试自己完成这些任务,这样您会获得更多的收获。请记住,有很多方法可以解决编码问题,所以你的代码可能不会和我的一字不差,这没关系。

另请查看:通过示例学习 Python 数据分析:纽约市违章停车通过示例学习 Python 数据分析:航班到达延误

项目描述

对于这个项目,我们将使用一个包含近 150 万条记录的数据集,这些记录代表了 2013 年至 2021 年芝加哥报告的交通事故以及其中涉及的车辆。该数据集创建于 2021 年 2 月,包含来自芝加哥市的数据。

如果你还没有 pandasmatplotlibseabornleave库,你需要安装它们。

数据分析任务

请使用此驱动器中可用的 crashes.csvcrashes_vehicles.csv 数据集在 Python 中执行以下任务。也可以参考这个 GitHub repo

  1. 阅读包含芝加哥交通事故数据的 CSV 文件。确定两个文件共有的列,并在该列上将它们合并在一起。然后显示报告的崩溃总数。
  2. 将“崩溃日期”列更改为日期格式。2018 年、2019 年或 2020 年未发生的跌落观测(其他年份数据不完整)。
  3. 显示一个图表,显示一天中每小时发生的崩溃次数。
  4. 说出 2018 年 8 月白天撞车最多的车辆品牌。请记住,车祸可能涉及多辆车。
  5. 确定每种事故最常见的天气条件。
  6. 按照从高到低的顺序,画出报告事故的主要原因。
  7. 显示发生车祸最多的 10 个州的车牌。请记住,车祸可能涉及多辆车。
  8. 显示 2019 年每个月车祸的比例,其中酒精被确定为主要原因。
  9. 确定是雪上汽车还是休闲越野车卷入了更多的车祸。
  10. 显示一个聚类图,显示涉及肇事逃逸的车祸地点。

数据字典

crashes.csv: 数据集中的每一行都代表芝加哥报道的一起交通事故。

crashes_vehicles.csv: 数据集中的每一行都代表一辆发生在芝加哥的车祸。

照片由安特·哈默斯特Unsplash 上拍摄

步骤 1:读取包含芝加哥交通事故数据的 CSV 文件。确定两个文件共有的列,并在该列上将它们合并在一起。然后显示报告的崩溃总数。我们将需要在整个项目中使用合并数据帧和崩溃数据帧。

Total Number of Reported Crashes: 474262

代码解释:

我们首先将熊猫模块的内容提供给我们的程序。pandas 是一个易于使用的开源数据分析和操作工具,构建于 Python 编程语言之上。我们将在整个项目中广泛使用它。

import pandas as pd

我们通过调用 read_csv()方法导入 crashes.csv 文件的内容,并将其存储在一个名为 df_crashes 的数据帧中。DataFrame 是一个带有标记轴的二维数据结构,由数据、行和列组成。可以把它想象成在 Microsoft Excel 或 Microsoft Access 中构建的表。然后,我们对崩溃 _ 车辆. csv 文件重复相同的操作,将其命名为df _ 车辆。对于 crashes_vehicles.csv 文件,我们删除了“CRASH_DATE”列,因为它也包含在另一个文件中。

df_crashes = pd.read_csv('crashes.csv', low_memory=False)
df_vehicles = pd.read_csv('crashes_vehicles.csv', low_memory=False).drop('CRASH_DATE', axis=1)

为了将两个数据帧组合成一个数据帧,我们调用 pandas 的 merge()方法。我们传递三个参数:前两个是我们要合并的两个数据帧的名称,第三个指定两个数据帧共有的列。最后,通过调用 reset_index()函数,我们重置了数据帧索引。

df = pd.merge(df_crashes, df_vehicles, on='CRASH_RECORD_ID').reset_index()

我们使用 print()函数打印字符串“报告的崩溃总数:”后跟数据帧中的崩溃数。我们传递给 print()函数的参数由两部分组成。第一个是用单引号括起来的字符串“报告的崩溃总数”,表示它是一个字符串。参数的第二部分是计算 df 中的崩溃次数。我们使用 nunique()方法来计算 df 中唯一的 CRASH_RECORD_ID 的数量,因为一个值可以重复。

print('Total Number of Reported Crashes:', df['CRASH_RECORD_ID'].nunique())

第 2 步:将“崩溃日期”列更改为日期格式。2018 年、2019 年或 2020 年未发生的跌落观测(其他年份数据不完整)。对合并的和崩溃的数据帧都这样做。

代码解释:

为了将 CRASH_DATE 列转换为日期类型,我们使用 pandas 函数 to_datetime(),将要更改的列作为参数传递。

df['CRASH_DATE'] = pd.to_datetime(df['CRASH_DATE'])
df_crashes['CRASH_DATE'] = pd.to_datetime(df_crashes['CRASH_DATE'])

我们需要子集 dfdf_crashes 来过滤 2017 年、2018 年和 2019 年发生的崩溃。我们用> =表示大于等于,< =表示小于等于。日期格式为 YYYY-MM-DD。

df = df[(df['CRASH_DATE'] >= '2018-01-01') & (df['CRASH_DATE'] <= '2020-12-31')]
df_crashes = df_crashes[(df_crashes['CRASH_DATE'] >= '2018-01-01') & (df_crashes['CRASH_DATE'] <= '2020-12-31')]

第三步。显示一个图表,显示一天中每小时发生的崩溃次数。

代码解释:

我们让 matplotlib 和 seaborn 库的内容对我们的程序可用。matplotlib 和 seaborn 一起在 Python 中创建可视化。我对我的情节有一个风格偏好,并通过调用 seaborn 的 set_theme()方法将 seaborn 主题风格设置为 darkgrid。我们还提供了 numpy 库来帮助标记绘图轴。

import matplotlib.pyplot as plt
import seaborn as sns
sns.set_theme(style='darkgrid')
import numpy as np

为了使绘图更容易和更具视觉吸引力,我们在数据帧中创建了一个新的列来表示每次撞车发生的时间。0 代表 12am 到 1am,1 代表 1am 到 2am,一直到代表 11pm 到 12am 的 23。为此,我们在 CRASH_DATE 列上使用. dt.hour 来获取小时,并将其放入新列 hour 中。

df['Hour'] = df['CRASH_DATE'].dt.hour

现在是我们策划的时候了。我们指定 15 x 8 作为绘图的大小,然后调用 seaborn 的 barplot()方法。我们传递给它 5 个参数,每个参数我们将依次接受。第一个参数是我们希望绘制的数据:我们按照新的 Hour 列对记录进行分组,然后使用 nunique()方法计算每组中唯一的 CRASH_RECORD_ID 的数量。第二个和第三个参数是绘图的 x 和 y,分别是撞车的小时数和次数。第四个参数是选择的调色板,第五个参数指定条形周围没有线条,这是一种风格偏好。

剩余的代码行设置绘图的标题和轴标签。

plt.figure(figsize=(15,8))
s = sns.barplot(data=df.groupby('Hour')['CRASH_RECORD_ID'].nunique().reset_index(), x='Hour', y='CRASH_RECORD_ID', palette='GnBu_r', linewidth=0)
s.set_title('Hourly Number of Reported Crashes in Chicago (2018 - 2020)', y=1.02, fontsize=14)
s.set_xlabel('Hour of Day', fontsize=13, labelpad=15)
s.set_ylabel('Number of Crashes', fontsize=13, labelpad=15)
plt.show()

第四步。说出 2018 年 8 月白天撞车最多的车辆品牌。请记住,车祸可能涉及多辆车。

CHEVROLET    49779
Name: MAKE, dtype: int64

代码解释:

我们需要执行的第一项任务是创建一个数据帧,其中只包含在日光照明条件下发生的崩溃。我们从 df 开始,而不是从 df_crashes 开始,因为我们想考虑碰撞中涉及的所有车辆。我们只需在 LIGHTING_CONDITION 列中为带有日光的记录设置 df ,并将结果存储在 df_daylight 中。

df_daylight = df[df['LIGHTING_CONDITION'] == 'DAYLIGHT']

现在我们已经准备好了源数据,我们对数据帧中的 MAKE 列调用 value_counts()方法来计算每个 MAKE 出现的次数。因为我们只想知道发生最多碰撞的车辆的品牌,所以我们使用 nlargest(1)来显示我们需要的数据。

df_daylight['MAKE'].value_counts().nlargest(1)

第五步。确定每种事故最常见的天气条件。

代码解释:

对于这一步,我们可以使用一行代码。因为这是一个很长的代码行,我将把它分成几个部分来解释。

我们首先按照 FIRST_CRASH_TYPE 对 df_crashes 中的崩溃记录进行分组。

df_crashes.groupby('FIRST_CRASH_TYPE')['WEATHER_CONDITION']

接下来,我们要确定哪种天气条件下每种坠机类型的坠机次数最多。为此,我们需要沿着分组数据的轴应用一个函数。因为我们没有指定轴,所以默认为 0,这是索引。

lambda 函数对每个组(崩溃类型)调用 value_counts()方法,并按降序对每个组中每个天气条件的实例数进行计数。然后,对 head()方法的调用为我们提供了每个崩溃类型组的最佳天气状况。

.apply(lambda x: x.value_counts().head(1))

我们使用 reset_index()方法将数据帧索引重置为原始索引。我们在这里使用它以更优雅的方式呈现结果。我们传递“COUNT”的 name 参数来命名包含计数值的列。

.reset_index(name='COUNT')

最后,我们调用 rename()方法将 level_1 列重命名为 WEATHER,以使输出更具可读性。

.rename(columns={'level_1': 'WEATHER'})

第六步。按照从高到低的顺序,画出报告事故的主要原因。

代码解释:

我们在这里使用的大部分代码类似于我们在步骤 3 中创建的图。

我们指定 15 x 15 作为绘图的大小,然后调用 seaborn 的 countplot()方法。我们给它传递 3 个参数。第一个是我们的 df_crashes 数据帧。第二个选项指定我们希望对每个主要原因的撞车次数进行计数,通过指定 y ,条形图将在图上水平显示。因为 seaborn 没有一个简单的方法来按大小排序条,对于第三个参数 order ,我们告诉 seaborn 使用df _ crashes[' PRIM _ contributive _ CAUSE ']的结果。value_counts()。索引以订购棒材。这给出了我们正在寻找的降序。

剩余的代码行设置绘图的标题和轴标签。

plt.figure(figsize=(15, 15))
sns.countplot(data=df_crashes,  y='PRIM_CONTRIBUTORY_CAUSE', order = df_crashes['PRIM_CONTRIBUTORY_CAUSE'].value_counts().index)
plt.title('Primary Contributing Cause of Reported Crashes in Chicago (2018 - 2020) ', y=1.01, fontsize=14)
plt.xlabel('Number of Crashes', fontsize=13, labelpad=15)
plt.ylabel('Primary Contributing Cause', fontsize=13, labelpad=15)
plt.show();

第七步。显示发生车祸最多的 10 个州的车牌。请记住,车祸可能涉及多辆车。

代码解释:

我们从 df 而不是 df_crashes 开始,因为我们想考虑碰撞中涉及的所有车辆。我们按照 LIC 车牌州对记录进行分组,然后计算每组的车辆标识号。我们使用这个字段,因为它是每辆车的唯一标识符,而不是没有实际的牌照数据。因为我们想要前 10 名,所以我们调用。nlargest(10)方法。最后,我们调用 reset_index()并将计数列命名为 count。

df.groupby('LIC_PLATE_STATE')['VEHICLE_ID'].count().nlargest(10).reset_index(name='COUNT')

第八步。显示 2019 年每个月车祸的比例,其中酒精被确定为主要原因。

代码解释:

因为我们只对 2019 年的崩溃感兴趣,所以我们使用数据过滤器对 df_crashes 进行子集化,从而得到 df_alcohol 。在第二行代码中,我们按月份对崩溃进行分组,然后通过调用 nunique()方法计算每月的崩溃次数,将结果存储为 df_total —这将是我们计算每月比例时的分母。

df_alcohol = df_crashes[(df_crashes['CRASH_DATE'] >= '2019-01-01') & (df_crashes['CRASH_DATE'] <= '2019-12-31')]
df_total = df_alcohol.groupby(df_alcohol['CRASH_DATE'].dt.strftime('%m'))['CRASH_RECORD_ID'].nunique()

现在我们需要分子,即每月与酒精相关的车祸数量。首先,我们根据主要原因对车祸进行分类,但前提是它们包含酒精或饮酒。调用 contains()方法,将单词作为参数传递给我们需要的东西。我们使用|字符来分隔这两个单词。接下来,我们按月份对结果记录进行分组,然后通过再次调用 nunique()方法计算每月的崩溃次数,将结果存储回 df_alcohol

df_alcohol = df_crashes[df_crashes['PRIM_CONTRIBUTORY_CAUSE'].str.contains('ALCOHOL|DRINKING')]
df_alcohol = df_alcohol.groupby(df_alcohol['CRASH_DATE'].dt.strftime('%m'))['CRASH_RECORD_ID'].nunique()

既然我们有了分子和分母,我们就可以计算出酒精被记录为主要原因的每月车祸比例。然后,我们像在其他步骤中一样调用 reset_index(),并使用 rename()来重命名列,以便显示。

df_proportion = df_alcohol / df_total * 100
df_proportion.reset_index().rename(columns={'CRASH_DATE': 'MONTH', 'CRASH_RECORD_ID': 'PROPORTION'})

第九步。确定是雪上汽车还是休闲越野车卷入了更多的车祸。

Number of snowmobiles: 4
Number of recreational off-highway vehicles: 6

代码解释:

对于这一步,我们使用相同的代码两次,第一次寻找雪地车,第二次寻找休闲越野车。我们为每种车辆类型设置子集 df ,并使用 len()函数来计算各个子集中的记录数。

print('Number of snowmobiles:', str(len(df[df['VEHICLE_TYPE'] == 'SNOWMOBILE'])))
print('Number of recreational off-highway vehicles:', str(len(df[df['VEHICLE_TYPE'] == 'RECREATIONAL OFF-HIGHWAY VEHICLE (ROV)'])))

第十步。显示一个聚类图,显示涉及肇事逃逸的车祸地点。

代码解释:

我们只希望显示涉及肇事逃逸的碰撞位置,所以我们从子集化 df_crashes 开始,以获得我们希望绘制的数据,将结果存储为 df_hitrun 。DataFrame 中有一些没有坐标的记录,所以我们使用 notna()方法删除它们。

df_hitrun = df_crashes[df_crashes['HIT_AND_RUN_I'] == 'Y']
df_hitrun = df_hitrun[df_hitrun['LONGITUDE'].notna()]

为了显示我们的地图,我们将使用叶和一个相关的标记集群插件。我们首先让程序可以使用 follow 模块的内容,并导入插件。Folium 非常强大,只需要很少的代码就可以创建一个非常详细的交互式地图。

import folium
from folium import plugins

我们需要通过传递芝加哥的 GPS 坐标和缩放级别(我们将缩放级别设置为 12)来实例化一个叶子地图。我们将使用的纬度是 41.8781,经度是-87.6798(我通过快速的谷歌搜索找到了这些)。

m = folium.Map(location=[41.8781, -87.6798], zoom_start=12)

我们正在创建一个集群映射,所以使用 MarkerCluster 插件,通过调用 add_to()方法将它添加到我们的映射中,并将我们的叶子映射 m 作为参数传递。

然后,对于 df_hitrun 中的每个崩溃,我们创建一个标记。我们使用 for 循环遍历 df_hitrun 。zip()函数为每个崩溃创建一个纬度和经度元组,为每个崩溃创建一个标记。最后,我们显示地图 m 。当您放大和缩小地图时,聚类会以交互方式调整大小。

hitrun = plugins.MarkerCluster().add_to(m)for lat, lng in zip(df_hitrun['LATITUDE'], df_hitrun['LONGITUDE']):
    folium.Marker(
        location=[lat, lng],
           icon=None,
    ).add_to(hitrun)
m

我希望你已经发现这个项目是学习 Python 数据分析的一个有用的方法。请在评论区分享您的反馈。

另请查看:通过示例学习 Python 数据分析:NYC 停车违规通过示例学习 Python 数据分析:航班到达延误

通过示例了解 Python 数据分析:纽约市停车违规

原文:https://towardsdatascience.com/learn-python-data-analytics-by-example-ny-parking-violations-e1ce1847fa2?source=collection_archive---------19-----------------------

一个有趣的项目和详细的数据分析步骤,以帮助您学习 Python,pandas 和 matplotlib。

乔希·牛顿在 Unsplash 上的照片

介绍

在攻读商业分析硕士学位的过程中,我发现通过实例学习是我学习 Python 数据分析的最佳方式。获得一个数据集和一组编码任务比阅读教科书或听教授讲课要有益得多。

我想把这种学习方法分享给其他人,他们也会受益。你需要的只是一个 Python 开发环境(我推荐 Jupyter Notebook )和乐于学习的意愿。

本文包括一个数据分析任务列表,后面是如何完成这些任务的详细演练。在通读演练之前,请尝试自己完成这些任务,这样您会获得更多的收获。请记住,有很多方法可以解决编码问题,所以你的代码可能不会和我的一字不差。

项目描述

对于这个项目,我们将使用 2021 财年期间纽约市发布的 50,000 次停车违规的数据集。该数据集创建于 2021 年 1 月,包含 2020 年 4 月 1 日至 11 月 30 日的数据,数据来源于 NYC Open Data

如果你还没有的话,你需要安装 pandasmatplotlib 库。

数据分析任务

请使用 GitHub repo 中可用的 violations.csv 数据集在 Python 中执行以下任务。

  1. 阅读包含纽约市停车违规数据的 CSV 文件。将“发布日期”列更改为日期格式。然后打印出导入的行数。
  2. 对导入的数据集执行探索性数据分析,以识别无效数据。编写代码以删除受影响的行。然后打印出数据集中剩余的行数。
  3. 显示一个简单的图表,显示每辆车每年违规停车的次数。
  4. 列出在纽约州以外的州注册的车辆的前 5 个违章代码。
  5. 说出本田收到最多违规停车罚单的街道。
  6. 对于仅来自纽约的车辆,创建一个图表,逐月显示非乘客牌照类型的比率。
  7. 确定违规次数最多的客车牌照车辆的颜色是否与违规次数最多的商用牌照车辆的颜色相同。
  8. 显示数据中表示的登记州数以及每个登记州的平均违章停车数。
  9. 显示每个违章代码中违章停车次数最多的车牌类型。
  10. 计算每个县违规停车的百分比,并按降序显示。

尼克·卡沃尼斯在 Unsplash 上的照片

步骤 1:读取包含纽约市停车违规数据的 CSV 文件。将“发布日期”列更改为日期格式。然后打印出导入的行数。

Number of Rows: 50000

代码解释:

我们首先将熊猫模块的内容提供给我们的程序。pandas 是一个易于使用的开源数据分析和操作工具,构建于 Python 编程语言之上。我们将在整个项目中广泛使用它。

import pandas as pd

我们通过调用 read_csv()方法导入 violations.csv 文件的内容,并将其存储在名为 df 的数据帧中。DataFrame 是一个带有标记轴的二维数据结构,由数据、行和列组成。可以把它想象成在 Microsoft Excel 或 Microsoft Access 中构建的表。

df = pd.read_csv('violations.csv')

我们使用 print()函数打印字符串‘Number of Rows:'后跟 DataFrame 中的行数。我们传递给 print()函数的参数由两部分组成。第一个是用单引号括起来的字符串“Number of Rows:”表示它是一个字符串。

争论的第二部分是计算 df 中的行数。我们使用 len()函数告诉我们 df 中的行数,然后将其封装在对 str()方法的调用中,将长度转换为字符串。最后,+将两个字符串部分连接在一起。传递给 print()函数的参数的所有部分都必须是字符串类型。

print('Number of Rows: ' + str(len(df)))

步骤 2:对导入的数据集执行探索性数据分析,以识别无效数据。编写代码以删除受影响的行。然后打印出数据集中剩余的行数。

以下数据被视为无效:

  • 注册州:不是两个字母的州或省标识符的值。
  • 孔板类型:不是三个字母标识符(注册类别代码)的值
  • 发布日期:不在财政年度内的日期(使用 2020–11–30 作为财政年度的结束日期)
  • 违章代码:1 到 99 之间的代码(违章代码)
  • 车辆制造商:空白值
  • 违规时间:空白值
  • 车辆年份:日期在未来的车辆(使用 2020 年作为当前年份)
Number of Rows: 38937

代码解释:

我们需要子集 df 来过滤掉无效数据的记录。我们可以一次应用多个参数,方法是将每个参数用括号括起来,并在它们之间使用&字符。我们用!=表示不等于,> =表示大于等于,< =表示小于等于。对于车辆制造和违规时间列,我们需要通过调用 notnull()方法来检查空值。

df = df[(df['Registration State'] != "99") 
    & (df['Plate Type'] != "999") 
    & (df['Issue Date'] >= '2020-04-01') 
    & (df['Issue Date'] <= '2020-11-30') 
    & (df['Violation Code'] != 0) 
    & (df['Vehicle Make'].notnull()) 
    & (df['Violation Time'].notnull()) 
    & (df['Vehicle Year'] != 0) 
    & (df['Vehicle Year'] <= 2020)]

我们使用 print()函数的方式与上面的步骤 1 完全相同。

print('Number of Rows: ' + str(len(df)))

步骤 3:显示一个简单的图表,显示每辆车每年的违章停车次数。

代码解释:

我们让 matplotlib 库的内容对我们的程序可用。matplotlib 是一个用于在 Python 中创建可视化的综合库。

import matplotlib.pyplot as plt

我们需要为该图创建一个数据集,其中包含车辆年份以及这些年份中每一年的违规停车数量。为此,我们将 df 中的记录按车辆年份分组,并统计每年的违章停车次数。每一次违章停车都有一个独特的传票号码。

df_vehicle_year = df.groupby('Vehicle Year')['Summons Number'].count()

我们使用 matplotlib 的 plot()函数来创建绘图。作为一个参数,我们简单地传递我们创建的新数据集。然后,我们使用 show()函数来显示该图。

plt.plot(df_vehicle_year)
plt.show()

步骤 4:列出在除纽约以外的州注册的车辆的前 5 个违章代码。

代码解释:

在这一行代码中有很多元素需要解包,所以我们将一步一步来。请慢慢理解这一行,因为在接下来的步骤中,我们将会多次使用这一结构。

在语句的第一部分,我们将 df 过滤为那些注册州不是 NY 的记录。

df[df['Registration State'] != 'NY']

接下来,我们按违章代码对结果记录进行分组,并计算每个违章代码的违章停车次数。

.groupby('Violation Code')['Summons Number'].count()

我们通过使用 nlargest()方法并向其传递参数 5 来显示具有 5 个最高计数的违规代码。将按降序显示 count 列中具有最大值的前 n 行。

.nlargest(5)

最后,我们使用 reset_index()方法将数据帧索引重置为原始索引。我们在这里使用它以更优雅的方式呈现结果。我们传递“Count”的名称参数来命名包含计数值的列。

.reset_index(name='Count')

第五步:说出本田收到最多违规停车罚单的街道。

代码解释:

这一行代码严格遵循我们在上面第 4 步中使用的结构。在这种情况下,我们将 df 过滤为那些车辆品牌为本田的记录,按街道名称对结果记录进行分组,计算每条街道的违规停车数量,并仅显示违规停车最多的街道。

df[df['Vehicle Make'] == 'HONDA'].groupby('Street Name')['Summons Number'].count().nlargest(1).reset_index(name='Count')

步骤 6:对于仅来自纽约的车辆,创建一个图表,逐月显示非乘客牌照类型的比率。

代码解释:

我们通过只选择那些注册状态为 NY 的记录来对 df 进行子集化,并将其存储为 df_ny

df_ny = df[df['Registration State'] == 'NY']

为了计算请求的比率,我们需要创建一个数据集来表示分子(按车辆年份划分的所有非客运车辆的违规停车次数)和另一个数据集来表示分母(按车辆年份划分的所有车辆的违规停车次数)。

对于分子,我们过滤 df_ny 以仅过滤那些牌照类型不等于“乘客”的记录,按车辆年份对结果记录进行分组,并计算每年的违章停车次数。我们将其存储为 df_ny_notpas

df_ny_notpas = df_ny[df_ny['Plate Type'] != 'PAS'].groupby('Vehicle Year')['Summons Number'].count()

对于分母,我们不需要过滤 df_ny ,因为我们需要所有记录。相反,我们只是按车辆年份对记录进行分组,并计算每年违规停车的次数。我们将其存储为 df_ny_all

df_ny_all = df_ny.groupby('Vehicle Year')['Summons Number'].count()

要计算每年的比率,我们只需用分子除以分母。这是 pandas 的神奇之处之一,它将除法函数应用于数据帧中的每一个计数对,一年一年。当车辆年份仅出现在一个数据框中时,结果为 NaN。

ratio = df_ny_notpas / df_ny_all

我们无法绘制 NaN 值,因此我们在比率数据帧上使用 fillna()方法将它们替换为 0。inplace=True 参数直接更新比率中的值。

ratio.fillna(0, inplace = True)

我们使用 matplotlib 的 plot()函数来创建绘图。作为一个参数,我们简单地传递我们创建的新数据集。然后,我们使用 show()函数来显示该图。

plt.plot(ratio)
plt.show()

第 7 步:确定违规次数最多的客车牌照车辆的颜色是否与违规次数最多的商用牌照车辆的颜色相同。

代码解释:

我们将 df 过滤为仅具有乘客车牌类型的记录,按照车辆颜色对结果记录进行分组,计算每种颜色的违规停车次数,并使用 nlargest()显示违规停车次数最多的颜色。

df[df['Plate Type'] == 'PAS'].groupby('Vehicle Color')['Summons Number'].count().nlargest(1).reset_index(name='Count')

代码解释:

我们将 df 过滤为那些车牌类型为“商业”的记录,将结果记录按车辆颜色分组,计算每种颜色的违章停车次数,并使用 nlargest()显示违章停车次数最多的颜色。

df[df['Plate Type'] == 'COM'].groupby('Vehicle Color')['Summons Number'].count().nlargest(1).reset_index(name='Count')

第 8 步:显示数据中表示的登记州数和每个登记州的平均违章停车数。

Number of Registration States: 45
Average Number of Parking Violations per Registration State: 865.2666666666667

代码解释:

我们在 df 中打印字符串“注册状态数”和注册状态数。为了确定注册状态的数量,我们在 df 中的注册状态列上调用 nunique()方法,该方法返回不同观察的计数,即列中列出的唯一状态的数量。和前面一样,我们使用 str()将数值转换成字符串。

print('Number of Registration States: ' + str(df['Registration State'].nunique()))

我们打印字符串“每个注册州的平均违章停车次数”和平均违章停车次数。为了计算后者,我们按照注册州对 df 中的行进行分组,计算每个州的违规停车数量,然后通过调用 mean()方法对这些数量进行平均。

print('Average Number of Parking Violations per Registration State: ' +  str(df.groupby('Registration State')['Summons Number'].count().mean()))

步骤 9:显示每个违章代码中违章停车次数最多的车牌类型。

代码解释:

在这一步中,我们将使用更高级的功能。我们将把这段代码分解成片段来解释。

我们首先通过违规代码对 df 中的记录进行分组。

df.groupby('Violation Code')['Plate Type']

接下来,我们要确定对于每个违章代码,哪种车牌类型的违章停车次数最多。为此,我们需要沿着分组数据的轴应用一个函数。因为我们没有指定轴,所以默认为 0,这是索引。

lambda 函数对每个组(违规代码)调用 value_counts()方法,并按降序计算每个组中每个孔板类型的实例数。然后,对 head()方法的调用为我们提供了每个违例代码组的顶板类型。

.apply(lambda x: x.value_counts().head(1))

我们使用 reset_index()方法将数据帧索引重置为原始索引。我们在这里使用它以更优雅的方式呈现结果。我们传递“Count”的名称参数来命名包含计数值的列。

.reset_index(name='Count')

最后,我们调用 rename()方法将 level_1 列重命名为 Plate Type,以使输出更具可读性。

.rename(columns={'level_1': 'Plate Type'})

第十步:计算每个县违规停车的百分比,并按降序显示。

代码解释:

我们按照违规县对 df 中的行进行分组,统计每个违规县的停车违规次数,然后将其存储为 df_county 。我们调用 reset_index()方法来重置索引,并将结果列重命名为 Percentage。

df_county = df.groupby('Violation County')['Summons Number'].count().reset_index(name='Percentage')

我们通过将百分比列中先前计算的值除以违规总数来计算每个违规的百分比,从而替换这些值。

df_county['Percentage'] = df_county['Percentage'] / df_county['Percentage'].sum() * 100

最后,我们在 df_county 上调用 sort_values 方法,以降序对百分比进行排序。

df_county.sort_values(by='Percentage', ascending=False).reset_index(drop=True)

我希望你已经发现这个项目是学习 Python 数据分析的一个有用的方法。请在评论区分享您的反馈。

学习 Python,在 2021 年助推你的职业生涯

原文:https://towardsdatascience.com/learn-python-to-become-a-backend-developer-in-2021-fec514cc76db?source=collection_archive---------8-----------------------

使用 Python 启动您的旅程

照片由来自佩克斯克里斯蒂娜·莫里洛拍摄

如果你是我们文章的热心读者,我们相信你一定注意到了我们对 Python 的热情。这背后的原因很简单。与其他编程语言相比,Python 是一种非常容易掌握的编程语言。

但这并不是 2021 年学习 Python 的唯一理由。

我们专门为那些可能听说过 Python 一两件事,但不知道它的真正潜力以及为什么你应该在 2021 年学习它的人写下了这篇文章。

Python 的创造者的故事—

来源:甲骨文开发者

为什么你应该在 2021 年学习 Python

如果您正在阅读这篇文章,那么您很有可能喜欢了解编程世界的最新动态,并且很有可能亲眼目睹了 Python 在世界各地开发人员社区中的兴起。

Python 是一种解释型、通用的高级编程语言,在构建 web 应用游戏、图形用户界面、处理人工智能&机器学习工作负载、自动化等等时,它已经成为全世界开发者的首选。

请继续阅读下面的内容,了解让 Python 成为具有不同编程知识水平的人的最佳编程语言的主要原因。

1.简单易行

显然,Python 最受关注的特性是其隐含性和易用性。好奇想知道为什么?

,秘诀在于编程语言本身的设计。还记得我们之前称 Python 为高级编程语言吗?

这是因为在使用 Python 时,开发人员不一定需要关注像缺少分号这样的低级东西。相反,Python 处理所有这些,并允许开发人员将更多精力放在创建完美的应用程序逻辑上。

大多数开发人员认为 Python 拥有所有编程语言中最简单的词汇,这是绝对正确的。

这意味着 Python 有一个类似英语的结构,允许使用空格和普通表达式,这不仅使理解代码块在做什么变得更容易,而且使整个代码看起来干净而有吸引力。

最重要的是,Python 提供了一个巨大的库集合,它可以用最少的代码行抽象出你的大部分任务,使你的项目看起来更加易于管理。

所有这一切的结果是一种编程语言,它具有简单和容易的语法,没有任何怪异的语言规则,使应用程序开发变得有趣。

2.到处都是

我们确信到现在为止,您一定已经明白 Python 是多么的通用了:)。您可以将 Python 视为著名的瑞士军刀,它不仅仅做一件事。

不像许多其他编程语言特别擅长做一两件事,Python 可以做更多的事情,用于更广泛的领域,假设你知道如何充分利用它。

使用 Python 的方法有很多。你可以钻研无数的项目,比如从互联网上抓取数据的网页抓取器,创建网站和网络应用程序,为其他应用程序创建库或插件,为它们添加额外的功能。

您还可以使用 Python 来学习和解决与人工智能、数据科学和机器学习等领域相关的问题。Python 甚至可以用来快速创建更小但极其方便的自动化脚本,只需按一下按钮就可以完成枯燥的任务。然后,您可以使用 Python 开发丰富的视频游戏,创建可视化效果,这样的例子不胜枚举。

通过开发这样的应用程序,您不仅可以直接感受到编程语言的灵活性和功能,还可以帮助您识别和解决现实世界中的问题。

3.丰富的 Python 库和框架

在前一篇文章中,我们仅仅触及了 Python 提供的大量库和框架的表面。在撰写本文时,Python 的库总数已经接近 29 万个。

这对您来说意味着,无论您计划创建什么样的应用程序或程序,都很有可能已经存在一个库来简化您的工作。Python 为你能想到的几乎每一个应用领域都提供了库和框架。

想要处理多维数组和高级数学函数,你有 NumPy 。需要处理科学数据,并且想要类似 NumPy 的处理能力?你可以使用 SciPy 库

想要为您的机器学习和数据科学工作负载找到一些东西,您可以使用像 TensorFlowKerasPandas 这样的库,以及许多其他专门研究该领域的库。

想要通过直观的交互式可视化展示您的数据分析技能吗?你可以使用 Python 的几个可视化和图形库中的一个,比如 MatplotlibPlotlyGgplotSeaborn 等等。

对 web 开发感兴趣,你可以选择使用流行的 web 开发框架,如 DjangoBottleFlask

还有用于 GUI 开发的库和框架,比如 KivyPyQtTkinter 。类似地,有许多 Python 库和框架可以用于您的数百个用例。很神奇,对吧?

4.多用途

由于 Python 提供的好处,例如它的简单性、大量的库集合以及同样令人印象深刻的社区支持,现在已经很清楚为什么它能与现代少数几种最流行的编程语言并驾齐驱了。

根据跟踪开发人员使用软件的行业领先分析公司 SlashData 发布的报告,有超过 820 万开发人员使用 Python,而且这个数字还在增长。

今天,Python 正以这样或那样的方式影响着我们的生活。普通大众现在正在与数十万个网站、应用程序和系统进行交互,这些网站、应用程序和系统在底层运行一些 Python 代码。Python 对于数据科学、机器学习、Web 开发和自动化等新兴技术也不陌生。更多信息请见下文:

㈠数据科学

数据科学被认为是本世纪最热门的领域之一,它在使数据科学家能够访问大量数据以获得关键知识和见解方面发挥着关键作用。 ScrapyNumPyTensorFlowKerasMatplotlib 是这项工作中使用最多的库。

(二)机器学习

与数据科学类似,处理机器学习任务的人会发现 Python 正是他们项目的合适编程语言。实际上,有了像 Scikit-learnMatplotlibNumPyTensorFlow 这样的库,Python 通过创建像聊天机器人推荐系统语音和图像识别系统这样的应用程序,成为了练习机器学习技能的最佳语言之一。

㈢网站开发

Python 为 web 开发提供了大量的库和框架,让您不必太担心更细粒度的东西。 DjangoBottleFlaskWeb2PyRequestsSanic 是一些最常用于 Web 开发的库和框架,它们可以为您自动完成大量工作。

㈣自动化

从事应用程序开发项目时,您一定遇到过大量无聊但必要的低级任务,或者花费太多时间的任务。Python 为您提供了所有必要的火力,通过 Selenium Python、PyTest、PyUnit 和 Robot framework 等框架,您可以瞬间无缝地自动化这些枯燥的任务。

用 Python 自动化枯燥的东西—

来源: Al Sweigart

5.高薪意味着金钱金钱金钱

Alexander MilsPexels 拍摄的照片

众所周知,软件开发现在是世界上收入最高的行业之一,而 Python 开发人员是其中收入最高的。想知道为什么吗?

由于人工智能、数据科学和机器学习等不断发展的领域的使用越来越多,IT 界的一些最大的参与者,如谷歌、脸书、微软、亚马逊、网飞、网飞、优步等,都非常热衷于将这些领域深入到他们的服务中。可以毫不费力地完成所有这些甚至更多的编程语言是 Python。

这就是为什么 Python 开发人员成为这个行业中最受欢迎的人,他们的平均年薪从 7 万美元到 15 万美元不等,而且从现在开始这个数字只会越来越高。你可能会惊讶地知道,尽管新冠肺炎疫情正在进行,Python 开发者是 2020 年市场上最受欢迎的人。

无论你选择哪个领域,总会有很多选择来赚取可观的金钱,学习 Python 也可能是你获得六位数薪水的黄金门票。

6.就业和增长

Python 开发人员分布在一系列领域和工作岗位上,在全球整个开发人员社区中占了相当大的一部分。这背后的原因?

如今,Python 满足了一系列任务的需求,并催生了行业中的许多工作岗位。在现实世界中,您可以找到几个涉及 Python 的概要,下面列出了一些最常见的概要。

㈠软件工程师或开发人员

Python 软件开发人员的任务是构建我们非常喜爱的应用程序的前端和/或后端。这个简介提供了进入 Python 编程世界的入口,在这个行业中非常普遍,拥有比这里任何其他简介都多的职位空缺。

㈡数据科学家

正如数据科学在现代世界变得如此重要一样,Python 也需要受到高度赞扬,因为它在为数据科学家提供足够的马力,以便从手头的海量数据中挖掘出正确的见解方面发挥了关键作用。

㈢地理信息系统分析员

GIS 分析师必须处理来自世界各地的大量地理信息。由于 Python 提供了用于数据处理和分析的库,这项任务变得非常容易。如果没有 Python,事情可能会更困难。

㈣质量保证工程师

QA 工程师负责确保应用程序符合公司公布的质量标准。他们监督整个开发过程,以确保始终保持质量,产品及时上市。在这里,Python 知识使您能够顺利理解每个阶段。

7.庞大且不断增长的社区

奥马尔·洛佩兹在 Unsplash 上的照片

当谈到学习一门新的编程语言时,人们经常忽略它的一个重要方面。这是它的在线社区。

学习像 Python 这样的新编程语言总是会带来一系列挑战,这些挑战有时可能超出了您的理解或经验。如果你不能有效地使用编程语言,那它有什么用?这就是 Python 的开发者社区发挥作用的地方。

有了一个积极支持的开发人员社区,开发人员不仅可以理解 Python 最深层的内容,还可以消除疑虑,继续学习更多。

众所周知,开发人员倾向于放弃缺乏社区支持的编程语言,因为他们可能找不到问题的答案,但是使用 Python,情况正好相反。

如今,你几乎可以在所有主要平台上找到 Python 社区,包括 RedditLinkedinStack OverflowYouTube 等等。

启动您的 Python 之旅

现在有许多选项可以帮助您开始使用 Python。你可以选择在线课程,在 YouTube 上观看教程,听 Python 播客,阅读书籍,甚至在 GitHub 上玩代码来熟悉 Python。

你会惊讶地发现,我们在之前的文章中已经非常深入地讨论了所有这些学习媒介。如果我们成功地激发了您对 Python 的兴趣,我们强烈建议您现在就浏览它们,开始您的 Python 之旅。祝你好运!

学习 Python —

来源:freeCodeCamp.org

了解你的作者

克莱尔 D 。是 Digitalogy 的内容设计师和战略家,他可以将你的内容想法转化为清晰、引人注目、简洁的文字,与读者建立强有力的联系。

上连接我Linkedin&Twitter。****

作为数据科学家学习一些前端 Web 开发!

原文:https://towardsdatascience.com/learn-some-front-end-web-development-as-a-data-scientist-da662dde6d22?source=collection_archive---------13-----------------------

为什么会有人做这种事?

马库斯·温克勒在 Unsplash 上的照片

为什么我应该关心前端 Web 开发?

数据科学家和前端 web 开发者是不同的品种。前端 web 开发人员的动机是创建漂亮和用户友好的设计。另一方面,数据科学家喜欢将原始数据转化为可操作的见解。从表面上看,这些话题似乎毫无关联。

如果你从事数据科学工作(或者梦想从事数据科学工作),那么你可能会问自己:

我为什么要学习前端开发?那不就是颜色之类的东西吗?

首先,你应该为认为前端 web 开发仅仅是“颜色和材料”而感到羞耻😉

让我给你三个作为数据科学家学习前端 web 开发的好理由:

  • 你将受益于拥有一个展示你作为数据科学家的项目和技能的个人网页。雇佣数据科学家的人通常不是数据科学家。因此他们不能理解你工作的细节。他们必须依靠你如何展示你的作品。一个精心制作的个人网页就像面试开始时自信的握手;它设定了很高的期望。
  • 了解好的设计原则是有用的,比如排版、空白和视觉层次。必须向高层管理人员展示您的成果?你会本能地用 Matplotlib、Seaborn 或 Tableau 创建更漂亮的图形。你甚至会看到你的 PowerPoint 演示文稿上升了一个档次。不是因为你突然更擅长 PowerPoint,而是因为你不自觉地想到了设计。往往是这些简单的事情抓住了决策者的注意力。实话实说:即使是数据科学家也不介意看华丽的演示文稿!
  • 在许多企业中,数据科学家有时不得不与网络开发人员合作。了解前端 web 开发的基础知识可以使协作更加顺畅。更好的是,它可以给与你合作的 web 开发人员留下深刻的印象。像流言一样,伟大的印象在中小型公司里有一种像野火一样蔓延的方式。

为什么我不能为我的个人网页使用预制模板?

你可以。我甚至鼓励这样做。有很多网站可以买到这样的模板。甚至还有一些像 HTML5 UP 这样看起来很神奇的免费模板(需要归属)。

然而,你总是要以某种方式修改它们。也许你的简历文本对于模板来说太长了,所以你必须增加页边空白。也许你的照片分辨率不够高,所以你必须减小它们的尺寸并把它们移到右边。也许你想尝试另一种颜色主题?

在不知道自己在做什么的情况下,试图修改代码是一场耗时的噩梦。先学点前端 web 开发。之后,你可以毫不费力地制作网站,让你成为一名杰出的数据科学家。

我没有时间去学一门全新的行业!

鲁道夫·巴雷托Unsplash 上的照片

有一些人在 web 开发和数据科学方面都很有天赋。我喜欢称他们为独角兽;大多数人听说过,但很少有人在现实生活中见过。

我主要从事数据科学方面的工作,我会第一个承认:我不是专业的 web 开发人员。如果在任何前端框架中被一个真正的前端 web 开发者挑战,我会被打成肉酱。这将是一场大屠杀😧

我为什么要告诉你这些?因为只知道前端 web 开发的一小部分,就能让你作为数据科学家脱颖而出很多!

老实说,你不需要和 Shannon 竞争,他已经做了七年的专业前端 web 开发人员。实际上,你需要和鲍勃竞争。鲍勃是谁?

  • 鲍勃是一名数据科学家,他喜欢中世纪字体。
  • 鲍勃认为由 15 种截然不同的颜色组成的调色板看起来很“壮观”。
  • Bob 认为没有理由关心设计,因为重要的是数据。

鲍勃是正确的,因为数据很重要。然而,认为数据的呈现是不相关的是天真的。这就像在求职面试时穿运动裤和连帽衫,因为重要的不是衣服。虽然从技术上来说是正确的,但是有一种东西叫做第一印象。

你应该从哪里开始?

要学习前端 web 开发,有大量不同的资源:

要制作数据科学家作品集网页,我建议您熟悉:

  • 1-基本 HTML
  • 2-基本 CSS
  • 3 —一般设计原则
  • 4 —响应式设计
  • 5 —使用 Github 页面进行部署

谁知道呢,你甚至可能会爱上它!

与数据科学一样,通过构建项目可以学到最多的东西。试着尽快为你的数据科学职业生涯建立一个作品集网页。一开始看起来会很业余,但是不要绝望。你的技能将会很快提高,你将会很快制作出很棒的网站!

我喜欢 web 开发的一点是,你可以很快看到代码的结果。在处理数据管道时,在你看到自己的劳动成果之前,可能需要几个月的工作。不在前端 web 开发!

设计一个按钮,用户可以点击它来查看您的数据科学家简历?你可以马上自己测试!为你的个人项目页面设计一个漂亮的设计?马上去看看,看你喜不喜欢。你明白了。

你还在等什么?学习一些前端开发来提升你作为数据科学家的职业生涯!

喜欢我写的东西?查看我的其他帖子,如类型提示黑色格式Python 中的下划线5 字典提示了解更多内容。如果你对数据科学、编程或任何介于两者之间的东西感兴趣,那么请随意在 LinkedIn 上加我,并向✋问好

了解 SQL Server Management Studio —第 10 部分:通过电子邮件导出查询数据。战斗支援车

原文:https://towardsdatascience.com/learn-sql-server-management-studio-part-10-export-tables-by-email-as-csv-29bf2d990656?source=collection_archive---------27-----------------------

让你在派对上开心的技能!循序渐进。

迈克尔·泽兹奇在 Unsplash 上的照片

在最后几集里…

你好。欢迎来到 SQL 和 SQL Server Studio 系列教程的第 10 期。有一个简单的目标:让你熟悉和适应这个工具和语言。“这有什么关系?”我知道你在问。事实证明,好奇心和副业往往是被新项目选中甚至获得新工作的关键。事实上,您已经使用了一个重要的工具,比如 SQL Server Studio,并且编写了一些 SQL 查询,这将会给您一个清晰的开端。

别忘了回来😉。

期待什么?

在查看了视图和临时表之后,是时候深入了解一个特性了,这个特性不会引起太多的关注,但会被证明非常有用。在本教程结束时,您将会感到能够在 SQL 过程中利用报表生成的强大功能。让我们直接跳进来吧!

介绍

有时,尽管您的数据显示在精美的 PowerBI 报告上,但用户仍然需要访问原始数据。生的意思是。例如 csv。虽然在那个著名的“什么都有”表上写一个快速查询是很有礼貌的(剧透:根本没有这回事),但是如果用户频繁地请求,这可能会变得令人不知所措。一种解决方案是安排一个作业,并在其上附加一个包含所需信息的. csv 文档。

幸运的是,有一个有用的函数,可以通过调整一组参数来获得该报告。解决方案不是现成的,它需要一点创造力,但是你会发现实现起来很简单。

通过电子邮件将 SQL 数据导出为 CSV 格式

我们假设您的 SQL Studio 环境已经启动并正在运行。如果您需要帮助,这里有一个分步指南:第 1 部分 SQL Server Studio 的分步设置

对于本教程,我们将利用存储过程和 SSMS 调度功能,有些部分可能会很仓促,您可以在这里找到更多信息:第 5 部分存储过程&调度

我们将利用的表非常简单,由“名字”和“姓氏”组成

  1. 让我们创建一个过程。SSMS 提供的典型骨架是:
CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName>
AS
BEGIN
SELECT <@Param1, sysname, @p1>, <@Param2, sysname, @p2>
END
GO

我们的案例中不需要的一些样板代码已经被删除。

2.我们从声明一个参数< @query >开始,并把它的类型指定为 NVARCHAR(MAX)

CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName>
AS
BEGIN
**DECLARE @query NVARCHAR(MAX)**

3.然后我们开始定义参数<@查询 >:

SET @query = N'....'

N 将下面的字符串定义为 NVARCHAR,

4.然后,我们设置下面的语句,防止消息通知我们受查询影响的行数。

SET @query = N'
SET NOCOUNT ON

由于上述原因,我们不会在 CSV 摘录中看到这些内容:

5.后来出现了众所周知的 SELECT 语句,为了尊重字符串格式,使用了一组双单引号。对于我们虚构的包含[FirstName]和[LastName]列的表,这会给出:

SET @query = N'
SET NOCOUNT ON
SELECT 
''FirstName'' as FirstName,
''LastName'' as LastName

请注意,在这种情况下,我们没有引用表,我们只是准备 CSV 导出的标题。

6.然后,我们将上述语句的结果与第二个语句产生的数据(即表中的数据)结合起来:

UNIONSELECT
[FirstName] AS [FirstName],
[LastName] AS [LastName]
FROM [myDatabase].[dbo].[Users]

7.然后,我们通过关闭 NOCOUNT 语句来关闭这个字符串

SET NOCOUNT OFF'

8.因此,第一部分看起来像这样:

CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName>
AS
BEGINDECLARE @query NVARCHAR(MAX)SET @query = N'
SET NOCOUNT ON**SELECT 
''FirstName'' as FirstName,
''LastName'' as LastName****UNION****SELECT
[FirstName] AS [FirstName],
[LastName] AS [LastName]
FROM [myDatabase].[dbo].[Users]
SET NOCOUNT OFF'**

9.在这个阶段,尝试运行从“DECLARE”开始并以“SET NOCOUNT OFF”语句结束的代码是一个很好的做法。因为它是字符串变量的一部分,任何打字错误、多余或丢失的逗号都不会被 SSMS IDE 高亮显示。

要测试它,复制以粗体突出显示的部分,并将其粘贴到一个新屏幕上。对于第一个 select 语句,从列名的每一端删除一个单引号。然后运行该语句。它应该会返回表。

10.然后,我们将利用 SSMS 函数发送一封电子邮件,并提供参数信息,将这些数据添加为 CSV 附件。

EXEC msdb.dbo.sp_send_dbmail@profile_name= 'Reporting Team',@recipients= 'max@medium.org',@subject= 'Names CSV export',@body= 'Hello, <br><br> Please find attached your CSV export <br><br> Reporting Team',@body_format = 'HTML',

第一部分很简单,我们提供了概要文件名称、收件人、主题、正文……如果需要的话,大部分参数都可以添加变量。在我们的例子中,我们提供了一些硬编码的虚拟值。添加您的电子邮件地址,以确保您将获得该文件。

接下来是有趣的部分:

@query = @query,@attach_query_result_as_file = 1,@query_attachment_filename = 'ExportResults.csv',@query_result_separator = ',',@exclude_query_output = 1,@query_result_header = 1,@query_no_truncate = 1,@query_result_no_padding = 0,@query_result_width = 8192END

在上面,我们首先向查询参数提供 NVARCHAR 字符串,并定义将附加一个文件及其名称。然后我们可以定义分隔符。其他参数确保导出的 CSV 精简、干净,具有最大宽度且没有填充。

因此,概括地说,我们在这个过程中的整个代码是:

CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName>
AS
BEGINDECLARE @query NVARCHAR(MAX)SET @query = N'
SET NOCOUNT ON**SELECT 
''FirstName'' as FirstName,
''LastName'' as LastName****UNION****SELECT
[FirstName] AS [FirstName],
[LastName] AS [LastName]
FROM [myDatabase].[dbo].[Users]
SET NOCOUNT OFF'**EXEC msdb.dbo.sp_send_dbmail
@profile_name= 'Reporting Team',
@recipients= 'max@medium.org',
@subject= 'Names CSV export',@body= 'Hello, <br><br> Please find attached your CSV export <br><br> Reporting Team',@body_format = 'HTML',
@query = @query,
@attach_query_result_as_file = 1,
@query_attachment_filename = 'ExportResults.csv',
@query_result_separator = ',',
@exclude_query_output = 1,
@query_result_header = 1,
@query_no_truncate = 1,
@query_result_no_padding = 0,
@query_result_width = 8192END

让我们从头到尾选择代码并运行它…一封附有文件的电子邮件应该正在进行中!

公地臭虫

上面的内容可能非常强大,但实现起来需要一些耐心,因为错误可能隐藏在我们开始时声明的查询字符串中,而这些通常不会被 SSMS IDE 发现。

  • 单引号太少或太多,例如
''FirstName' as FirstName,
  • 逗号太多或缺失(尤其是在 UNION 语句之前复制粘贴了大量并调整了行的情况下),例如
''FirstName' as FirstName,
''LastName'' as LastName,
UNION
  • 应该转换为 VARCHAR 的日期时间格式,例如
**-- REPLACE THIS**...
[BirthDate],
...**-- BY THIS**...
CAST([BirthDate] AS VARCHAR),
...
  • 确保 SELECT 语句两边的列数相同,
  • 再三检查所有提到的列是否确实是您正在查询的表的一部分——这很明显,但仍有可能发生。

如果你还是卡住了:

  • 深呼吸,也许休息一下,
  • 从一两列开始,把它做好,然后向上移动到更多列
  • 不停地测试,测试,测试😉。

一旦得到控制,您就可以将这个过程包含在一个预定的作业中,并通过电子邮件通知您的用户他们很快就会收到该报告🎉。

最后的话和接下来会发生什么

暂时就这样吧!我希望您更有信心创建和利用 SQL 过程来基于底层查询生成和导出 CSV 文件,然后通过电子邮件将它们发送给用户。

  • 它可以很好地替代或补充您现有的数据可视化报告,
  • 它可以用作审计工具或证据,每周导出数据库中任何给定时间点的内容,
  • 如果连接到无代码或低代码工具,它也可以被利用,触发器将启动这个 SQL 过程并向用户提供数据。

感谢您的阅读,请告诉我您的想法,或者是否有我应该涉及的话题。与此同时,请随时订阅并关注我。下次见!

快乐编码🎉!

感谢阅读!喜欢这个故事吗? 加入媒介 可完整访问我的所有故事。

了解 SQL Server Management Studio —第 11 部分云中的 SQL 数据库和服务器介绍(Azure)

原文:https://towardsdatascience.com/learn-sql-server-management-studio-part-11-intro-to-sql-database-server-in-the-cloud-azure-b59b9855ba2c?source=collection_archive---------44-----------------------

让你在派对上开心的技能!循序渐进。

迈克尔·泽兹奇在 Unsplash 上的照片

在最后几集里…

你好。欢迎来到 SQL 和 SQL Server Studio 系列教程的第 11 期。有一个简单的目标:让你熟悉和适应这个工具和语言。“这有什么关系?”我知道你在问。事实证明,好奇心和副业往往是被新项目选中甚至获得新工作的关键。事实上,您已经使用了一个重要的工具,比如 SQL Server Studio,并且编写了一些 SQL 查询,这将会给您一个清晰的开端。

别忘了回来😉。

期待什么?

有了在本地服务器上创建数据库、存储过程和时间表的良好基础,理解如何在云中处理对等的东西是很自然的下一步。云的使用正在增加,随之而来的是对能够利用它的熟练人员的需求。即使是对云以及如何建立一些环境的远程理解,也可以决定你是否会参与一个项目或获得一份工作。好奇心是关键。

在本教程中,我们将介绍如何在云中创建服务器和数据库。然后,我们将把云服务器连接到 SQL Management studio 桌面应用程序。在本教程结束时,您会觉得自己有能力利用云计算的力量,并有望深入其中。让我们直接跳进来吧!

介绍

云计算领域充满了常见的嫌疑人,一些你可能会想到的知名企业:Azure(微软)、GCP(谷歌)、AWS(亚马逊)、阿里巴巴(Alibaba)、IBM Cloud。当然还有其他玩家。前面提到的云平台提供类似的服务,例如计算、存储、备份、AI/ML、数据库等。

对于本教程,我们将使用 Azure 门户。事不宜迟,我们开始吧。

  1. 登录 Azure 门户
  2. 在顶部搜索栏中,键入 SQL Server。你可能有资格以 200 美元的信用开始免费试用。

选择+创建,然后你会进入一个新的屏幕

4.选择您的订阅名称、资源组(或创建一个),输入服务器名称和位置,然后定义服务器管理员登录 ID 和密码。

为了我们的教程,其他选项卡(网络;附加设置;标签)可以被跳过。我们可以点击“查看+创建”。然后大约需要一分钟的时间进行部署。您可以安全地浏览门户的其他页面。

5.现在我们有了服务器,我们可以创建一个数据库。搜索 SQL 数据库并选择服务,然后单击+创建。

6.我们看到了一个类似的屏幕。定义数据库名称并选择我们刚刚创建的服务器。

7.接下来,我们将定义我们对计算+存储的要求。单击“配置数据库”。它被配置为“通用”,默认情况下计算机层设置为“已调配”。

这种设置的每月预计账单将为 159.82 美元。根据您的需要,也可以选择“无服务器”。这些选项之间的区别在于,对于“无服务器”方法,计算资源是自动扩展的,而对于调配的方法,计算资源是预先分配的。

有了无服务器设置,我们每月的预计账单将大幅减少至几美分:

8.您可以通过启用自动暂停来进一步降低成本,尽管这可能意味着如果您过一段时间后查询数据库,服务会变慢,因为它需要被“唤醒”。如果几秒钟的事情不能改变游戏规则,那么这个选择是有意义的。

9.然后,我们可以点击“查看+创建”。至于我们的服务器的设置,大约需要一分钟来部署。现在我们有了服务器和数据库,让我们连接到我们的 SQL Server Studio。

将 Azure 云服务器连接到 SSMS

  1. 我们可以在主屏幕上找到我们最近的资源。让我们选择我们的数据库。

2.我们得到了这个数据库的要素列表。在右侧,将鼠标悬停在以“. database.windows.net”结尾的服务器名称上,然后复制它。

3.打开 SSMS。在“连接到服务器”窗口中,粘贴我们刚刚复制的服务器。然后输入创建服务器时提供的管理员 ID 和密码。从“身份验证”下拉列表中,选择“SQL Server 身份验证”。

4.Azure 服务器将出现在右边,我们创建的数据库在它下面。

5.在这个数据库中,我们可以像在第二部分数据库中一样创建一个表,表&命名约定

6.我们在这个新表上所做的操作在我们的 Azure 门户数据库仪表板中是可见的。

最后的话和接下来会发生什么

暂时就这样吧!我希望您现在对在 SSMS 创建和利用云资源(如 SQL 数据库和服务器)更有信心了。云为本地服务提供了一个有趣的替代方案。一些好处是:

  • 维护成本(硬件和软件,包括更新)由云提供商承担。
  • 安全,
  • 可用性符合 SLA,
  • 资源和计算能力可以放大和缩小,
  • 按使用量付费选项,
  • 备份(灾难恢复/业务连续性、损失预防)

我承认,开始时可能还是会有一些与账单相关的焦虑。自动暂停资源的选项有助于缓解这种压力。客户服务通常是有帮助的,我曾经从其他云提供商那里获得退款,这些服务仍然在运行,但没有被使用(我的错😅).

感谢您的阅读,请告诉我您的想法,或者是否有我应该涉及的话题。与此同时,请随时订阅并关注我。下次见!

快乐编码🎉!

感谢阅读!喜欢这个故事吗? 加入媒介 可完整访问我的所有故事。

了解 SQL Server Management Studio —第 3 部分 CRUD 操作、主键和外键

原文:https://towardsdatascience.com/learn-sql-server-management-studio-part-3-crud-operations-primary-foreign-keys-9d884b32ad70?source=collection_archive---------10-----------------------

让你在派对上开心的技能!循序渐进。

迈克尔·泽兹奇在 Unsplash 上的照片

在最后几集里…

大家好,欢迎来到 SQL 和 SQL Server Studio 系列教程的第三部分。目标?让你熟悉和适应这个工具和语言。“这有什么关系?”我知道你在问。事实证明,好奇心和副业往往是被新项目选中的关键,甚至是获得新工作的关键。您已经使用了一个重要的工具,比如 SQL Server Studio,并且编写了一些 SQL 查询,这一事实可以并且将会给您一个清晰的开端。

如果您错过了关于如何设置我们的环境和本地服务器的第 1 集,请阅读本文:

如果您错过了第 2 集,关于使用设计工具或通过编写查询来创建数据库和表,以及关于命名约定的重要性,请继续阅读本文😉。

期待什么?

今天我们将看看 CRUD 操作、公共表表达式、主键和外键,以及如何构建我们的第一个简单表关系。我们将介绍两种删除记录的方法,使用常见的表表达式和 delete 语句。也会有具体的例子,一些有用的捷径,和一个迷因。让我们直接跳进来吧!

创作你的第一张唱片

一开始,什么都没有。然后出现了光,第一张唱片。创建或添加新记录是 CRUD 操作的 C

  1. 我们假设已经启动了 SQL Server Studio,并连接到本地服务器的实例。
  2. 让我们打开一个查询窗口,这可以通过以下任一方式完成:
  • CTRL + N
  • 右键单击数据库名或表名,然后单击“新建查询”

3.在表中创建新记录的结构是:

INSERT INTO *table_name* (*column1*, *column2*, ...)
VALUES (*value1*, *value2*, ...);

这些值需要与我们设计表时定义的数据类型相匹配。提醒一下,我们使用这种结构:

例如,尝试对 Department_ID 使用字符串值将会返回错误。自己看:

所以我们会写这个,建议你自己写,而不是复制粘贴,用手指记忆😉

INSERT INTO HR_data.dbo.DepartmentsVALUES (1, 'Finance', 'finance@mycompany.com');

由于 Department_NameDepartment_Email 是字符串,我们将该信息放在单引号中。

4.让我们通过运行来验证结果

SELECT * FROM HR_data.dbo.Departments

成功了。我们“读取”或查询我们的表,R 来自 CRUD 的缩写。还剩两个。再加几条记录吧。

5.我们可以连续运行几个:

INSERT INTO HR_data.dbo.DepartmentsVALUES 
(2, 'HR', 'HR@mycompany.com'),
(3, 'IT', 'IT@mycompany.com'),
(4, 'Sales', 'Sales@mycompany.com');

6.让我们看看这是怎么回事:

如您所见,我继续添加了比提到的还要多的几个。在我仓促的热情中,我错误地加了两次金融。现在怎么办?让我们借此机会从 CRUD 中学习另一种操作。删除。

删除记录

俗话说得好,给猫剥皮的方法不止一种。删除记录也是如此。这要看你的情况和需求。我们来讨论两种方式。

删除给定行中的记录

这里我们想删除给定行中的一条记录。该查询比我们之前编写的更进了一步。我们将一行一行地浏览这个片段。

with cte(rownum) as (select row_number () over(partition by Department_ID order by Department_ID) from HR_data.dbo.Departments)delete from cte where rownum = 2

第 1 行

  • 使用‘WITH’意味着我们将使用‘公共表表达式’(CTE)。这允许我们定义一个临时命名的结果,以便以后引用。语法是:
**WITH** expression_name[(column_name [,...])] **AS** (CTE_definition) SQL_statement;

在我们的例子中,我们将 expression_name 命名为“cte”,将 column_name 命名为“rownum”。

二号线

  • 我们选择“row_number”,其中 row_number 是一个 SQL 系统函数,这解释了它为什么会变成粉红色/洋红色。
  • 我们使用上的分区 BY** 子句来指定我们需要执行聚合的列。在我们的例子中,我们将关注 Department_ID 和按** Department_ID 排序的。请注意,“ORDER BY”是必需的,明确命名它可以防止在使用 row_numbers 时出现任何误解。

第 3 行&第 4 行

我们精确我们的源表,并关闭我们的 OVER 子句。

第 5 行

上面语法中的 SQL_statement 就是在这里编写的。SQL 的美妙之处在于它通常是不言自明的。作为提醒,我们有:

delete from cte where rownum = 2

我们将从' cte '表达式中删除,其中 rownum(ber)是 2,因为我们要删除的记录在第二行。

使用删除删除记录

以上内容可能看起来很乏味。如果记录可以通过主键(PK)唯一标识,事情就简单多了。关于 PK 和外键(FK)的一句话。在这种情况下,我们可以通过写入以下内容来删除记录:

DELETE FROM HR_data.dbo.Departments
WHERE Department_ID = 6

而且我们的‘管理’记录也没了;抱歉,各位😁。像往常一样,让我们运行下面的查询来检查是否一切正常。

SELECT * FROM HR_data.dbo.Departments

更新记录

既然我们已经介绍了 CRUD 首字母缩写词的创建、读取和删除部分,那么让我们处理最后一个部分,并“更新”一个记录。

  1. 假设 IT 部门更改了电子邮件地址。我们希望确保这一点在我们的表格中得到正确反映。
  2. 要遵循的语法是
UPDATE *table_name*
SET *column1* = *value1*, *column2* = *value2*, ...
WHERE *condition*;

3.我们的查询应该是这样的,因为我们将把 Department_Email 从它设置为“information _ technology @ my company . com”

UPDATE HR_data.dbo.Departments
SET Department_Email = 'information_technology@mycompany.com'
WHERE Department_Name = 'IT'

4.再次,让我们重复我们的好习惯来检查我们的结果

SELECT * FROM HR_data.dbo.Departments

主键和外键

键对于定义唯一记录和建立表之间的关系很有用。

设置主键

主键(PK)创建一个约束,它唯一地标识表中的每条记录。

  1. 我们将 Department_ID 定义为我们的主键。虽然你可能认为会有一个简单明了的方法,但 MS Server 将会进行一些斗争。所以最简单的方法是删除 Department_ID 列,然后重新创建它。
ALTER TABLE Departments DROP COLUMN Department_ID

2.然后我们重新创建它,我们使用 IDENTITY(1,1)。

ALTER TABLE Departments ADD Department_ID INT IDENTITY(1, 1)

这将授予 Department_ID 自动递增功能。每个新记录都将有其唯一的标识符,并且 ID 将自动增加 1。

3.让我们插入一个虚拟记录来检查一下。您可能还记得如何:

INSERT INTO DepartmentsVALUES ('test', 'test')

在这里,如您所见,我们没有定义任何“Department_ID ”,这与我们之前所做的不同:

INSERT INTO HR_data.dbo.DepartmentsVALUES (1, 'Finance', 'finance@mycompany.com');

这要归功于我们的表的自动递增功能,以及它的主键。

4.我们运行一个快速的“SELECT * FROM Departments”检查,我们的虚拟记录就在那里。

5.让我们自己收拾吧

DELETE FROM Departmentswhere Department_ID = 6

一开始就设定一个 PK

我们删除了一个列,然后重新创建了一个列作为 PK。但事后看来,我们本可以做得不同。在创建表的初始步骤,我们可以编写以下内容:

CREATE TABLE Departments (
    Department_id int NOT NULL IDENTITY(1,1),
    Department_Name nvarchar(50),
    Department_Email nvarchar(50),
    PRIMARY KEY (Department_Id)
);

正如我们在第 2 部分中看到的,这创建了一个表“部门,然后定义列名和数据类型。您会注意到,我们设置了所需的设置,使 Department_id 支持“主键”,不为空,并通过 Identity(1,1)自动递增。

创建外键(FK)

我们使用外键将两个表链接在一起。它是一个表中与另一个表中的主键相关的字段。让我们用一个例子来说明:

  1. 想象第二张桌子,雇员。它包含名,姓,工作电子邮件的数据。此外,每个员工都是一个数字(哎呀,迷因来了)。

来源

我的意思是每个雇员都有一个编号 ID,Employee_ID。而且每个员工也是一个部门的一部分。这就是 Department_ID 派上用场的地方。

2.我们的桌子看起来像这样

CREATE TABLE Employees (Employee_ID int NOT NULL IDENTITY(1,1),Employee_Name nvarchar(MAX),Employee_Email nvarchar(MAX),PRIMARY KEY (Employee_ID),Department_ID int);

3.让我们验证我们的表是否存在,这可能需要刷新,然后打开设计面板—右键单击表名,然后单击 Design

结构就是这样。如您所见,Employee_ID 是一个主键。

4.让我们向该表添加一条记录:

INSERT INTO [HR_data].[dbo].[Employees]VALUES ('Max', 'Max@mycompany.com', 1)

由于 Employee_ID 具有设置 IDENTITY(1,1 ),所以它是自动创建的,并随着新记录的增加而增加。这解释了为什么我们在值括号中没有提到任何 Employee_ID。现在让我们看看如何将 Department_ID 设置为外键。这样做的方法不止一种。

5.首先让我们使用一个查询:

ALTER TABLE [dbo].[Employees]ADD FOREIGN KEY ([Department_ID]) 
REFERENCES Departments([Department_ID])

上面发生了什么?

第 1 行——我们精确地指出要修改哪个表

第 2 行——我们指出我们想要添加一个外键,并明确它是如何被调用的

第 3 行—在我们的例子中,我们提供这个外键也将与我们的 Departments 表相关的引用。

让我们看看创建外键的第二种方法。

6.使用数据库图表。右键单击数据库图表。

7.选择这两个表,然后添加,并关闭窗口。

8.他们出现在我们的操场上,我们可以拖拽他们。

9.现在,我们将通过将主键 Department_ID (Departments 表)链接到未来的外键 Department_ID (Employees 表)来创建它们之间的关系。

10.选择一个表中的 Department_ID 行,以及出现的小箭头。

11.选择并拖动到另一个表格。出现一条虚线。释放,出现一个新窗口。它将连接部门和雇员表的主键和 FK。让我们点击确定。

12.出现第二个窗口。它允许我们定制外键以及与 PK 表的关系。

我们现在跳过它,接下来讨论它。

13.图表随表之间的连接而更新。

14.让我们在继续之前保存我们的图表,通过选择

然后“是”,并给我们的图表命名。

更改关系的设置(PK-FK)

  1. 右键单击两个表之间的关系。我们可以决定删除关系,或者访问它的属性。

2.“删除”选项很简单。属性打开了一组我们在前一部分中已经看到的选项。

3.上半部分告诉我们这个关系的连接细节:

4.在数据库设计器下,我们可以调整四个设置:

  • 强制复制&强制外键约束

默认情况下,它们被设置为“是”,建议保持这种状态。何时应将它们设置为“否”?下面是来自 StackOverflow 的的简要说明。

(…)当你在开发或重构一个数据库时,或者当你需要“净化”(清理)大量数据时,关闭外键约束以允许将“无效”数据加载到表中是有意义的。(…)

  • 删除&更新规则

这两个设置很有趣,可以确保模式中的不同表“一起移动”。选项范围包括:

  • 串联
  • 设置默认值
  • 设置为空

如果选择的设置是 Cascade 或 Set Default/Null,并且对我们的 Departments 表应用了更改,则连接的表 Employees 将受到影响。

5.让我们来看一个例子。让我们将删除/更新规则设置为“级联”。然后添加一名新员工,来自行政部门的 Bob。

INSERT INTO [dbo].[Employees]VALUES ('Bob', 'Bob@mycompany.com', 5)

运行此查询以验证 Bob 是我们员工列表的一部分。

SELECT * FROM [dbo].[Employees]

6.我们现在是两年后的未来。公司管理层决定将行政部门外包出去。因此,该部门将被删除。不幸的是,这个部门的员工不能留下来。这对鲍勃来说是个坏消息。

7.我们删除行政部门

DELETE FROM Departments WHERE Department_Name = 'Administration'

8.如果您还记得,我们为删除和更新设置了“级联”。你认为会发生什么?让我们看看 Employees 表对删除“管理”部门的反应。

SELECT * FROM [HR_data].[dbo].[Employees]

鲍勃走了。虽然这很可悲,但它帮助我们了解了“级联”规则以及表之间的连接是如何工作的。如果连接设置得很好,这允许我们在一个动作中处理其他表中的相关记录。如果我们需要从我们的记录中删除一个用户,它会很有用。

最后的话和接下来会发生什么

暂时就这样吧!我希望您现在对使用 SQL Server 和以下方面更有信心:

  • 使用 CRUD 操作,创建-读取-更新-删除记录,
  • 设置主键,并知道它们为什么重要(欺骗代码:它们有助于使记录唯一,通过创建逻辑标识符为连接表提供第一个基础)。您已经看到了查询和设计方法。
  • 通过查询或使用图表定义外键,以及
  • 理解关系表的有用属性,例如如何跨表级联更改。

感谢您的阅读,请告诉我您的想法,或者是否有我应该涉及的话题。下次见!

编码快乐!

感谢阅读!喜欢这个故事吗? 加入媒介 可完整访问我的所有故事。

从关于模式和规范化的第 4 集开始继续这一旅程!

或者选择你喜欢的另一集

在第 5 集,我们覆盖存储过程&调度,这是一个真正的野兽。我怎么强调这将如何促进和自动化你的日常(数据)生活都不为过。第五部分存储过程&调度

在第 6 集中,我们介绍了用于 ETL 的 SSIS 包,并回顾了如何在两个数据库之间以及一个数据库和 Excel 之间导入和导出数据。第六部 SSIS 套餐简介

在第 7 集中,我们将 SQL Studio 连接到 PowerBI,并构建了我们的第一批视觉效果。[第 7 部分连接到 PowerBI &第一视觉效果](http://Part 7 Connect to PowerBI & First Visuals)

SQL 模式和规范化简介

原文:https://towardsdatascience.com/learn-sql-server-management-studio-part-4-schemas-normalization-80bcd6a5258?source=collection_archive---------19-----------------------

让你在派对上开心的技能!逐步地

迈克尔·泽兹奇在 Unsplash 上的照片

在最后几集里…

你好。欢迎学习 SQL 和 SQL Server Studio 系列教程的第 4 部分。有一个简单的目标:让你熟悉和适应这个工具和语言。“这有什么关系?”我知道你在问。事实证明,好奇心和副业往往是被新项目选中的关键,甚至是获得新工作的关键。您已经使用了一个重要的工具,比如 SQL Server Studio,并且编写了一些 SQL 查询,这一事实可以并且将会给您一个清晰的开端。

如果您错过了关于如何设置我们的环境和本地服务器的第 1 集,请阅读本文:

在第 2 集,我们重点介绍了使用设计工具或通过编写查询来创建数据库和表,以及命名约定对本文的重要性:

在第 3 集,我们讨论了 CRUD 操作,它给你极大的权力来决定记录的可信度,以及主键和外键的主题。

别忘了回来😉。

期待什么?

今天我们来看看模式。桌子可以被看作是积木,而你可以是建筑师,把它们组合在一起。我们将讨论不同的模式类型,它们的优缺点,并给出具体的例子。让我们直接跳进来吧!

什么是模式?

图式,来自希腊语σχῆμα (skhēma),意为形状、计划。

好的,模式是一种组织事物的方式。在我们的例子中,组织我们的表。我们可以不严格地使用“图表”、“结构”或“建筑”作为同义词。

模式的类型

我们可以把它们分成三类。第一个可能会让一些人有点畏缩,但这是为了演示。

平面表模式——也就是普通模式

将用于解决方案的复杂平面表称为“模式”可能有点牵强。然而,当考虑到模式意味着形状时,一个复杂的平面表可以被认为是一个简单的模式。

“复杂平板”到底是什么?在这种情况下,所有列或与数据相关的特性都收集在同一个表中。想象一下,将所有人力资源数据存储在一个表中:

  • 员工姓名、职业和私人电子邮件、职业和私人电话号码、入职和离职(如有)日期,
  • 职称,级别,部门,
  • 薪资、上次绩效、绩效趋势、…

如上所述的平面表具有易于理解和排序以快速获得结果的优点。这可能非常方便。但这并不是因为它可以,而是因为 T2 应该。如果你在浏览了上述专栏后至少皱过一次眉头,我同意你的观点,原因有二:

  1. 不同级别的数据隐私

上面提到的数据元素有不同的隐私级别。作为一名员工,公司内的所有人都可能知道同事的姓名或工作电子邮件。

但是私人邮箱和电话号码呢?那是禁止的。SQL 表中数据的可用性也是如此:

  • 对员工列表具有 SQL 访问权限的用户应该只能看到公司内部所有人都可以看到的内容,
  • 被认为更机密的信息应该存在于其他地方,在另一个表或系统中,并且应该只由负责员工数据的核心人力资源团队中的一小部分用户查询。
  • 这同样适用于工资和绩效指标,除了人力资源工资团队,任何人都不能使用这些指标。

2。拆分结构可以提供更清晰、更快速的查询和更小的表格

这张看似平平无奇的桌子,却能迅速长成乳齿象。还存在冗余的风险,因为我们使用的是平面表,而不是利用关系数据库。如果我们要跟踪一段时间内的绩效趋势,我们将为每个新的绩效评估提供多行 Maxime,其余的是关于等级、工资的冗余数据重复。

在性能方面,也有一些问题:

  • 有更多的数据要读取,所以查询可能会很慢,
  • 表的大小正在快速增长,由于重复的数据,使得它们在操作上不是最佳的。

我们已经讨论了平面表结构的优缺点。由于所有列都是单个表的一部分,我们可以说这是一个集中式结构。现在让我们来看看分散模式或规范化模式。

规范化的方式

每当数据结构被拆分到不同的表中时,我们就说模式是规范化的。如果我们要将前面提到的平面表格可视化,我们可以用类似的方式呈现它:

在这种关系模式下,每个雇员都连接到:

  • 部门,
  • 薪水,
  • 员工私人联系信息,
  • 资产,资产与资产类型相关联

这种模式允许我们跨不同的表隔离我们的信息,此外,它还允许更简单的数据保护方法,因为我们需要在表或数据库级别而不是行级别进行处理。然而,规范化数据库的问题是,要从数据中获得洞察力,需要许多连接。

普通表的规范化遵循一定的步骤。

  • UNF: 那是一个非规格化的形式,作为一个普通的表。
  • 1NF: 为了满足这个要求,每一列应该只包含一个值,并且是唯一的。拥有两项资产的员工最初会有
#PLAIN TABLE
**Employee_Name       Assets**
'Maxime'        'Laptop, Monitor'

为了满足 1NF,它可以分成两列,成为 Asset_1,Asset_2。

#Employee PLAIN TABLE
**Employee_Name       Asset_1      Asset_2   (... other columns ...)**
'Maxime'           'Laptop'     'Monitor'
**(... other rows...)**

但是如果一个员工有三项资产会怎么样呢?该员工的记录不适合,因为我们只有两个资产列。类似地,对于一个图书仓库,假设我们只有两个图书类别。一本分为四类的书,如“生活、健康、幸福、自助”不适合。

更好的方法是有一个新表,只用于资产。正如前面在第 3 部分中以雇员表和部门表之间的关系为例所讨论的,这在主键和外键的帮助下成为可能。

  • 2NF: 要达到 2NF 这一步,我们需要先完成 1NF。在这个阶段,我们也要去除表里不一。主键和外键会派上用场,我们来看看为什么。正如在我们想象的普通员工表中提到的,我们有员工的历史绩效评估列表。
#Employee PLAIN TABLE
**Employee_Name       Performance_Date   Performance_Rating**
'Maxime'               'June 2020'               5
'Maxime'             'December 2020'             4
'Jane'                 'June 2020'               5
'Jane'               'December 2020'             5

相反,我们将把绩效日期和评级移到另一个表中。这将把我们的雇员表变成:

#Employee table
**Employee_ID (PK)      Employee_Name       (... other columns ...)**
     1                 'Maxime'                    
     2                  'Jane'
**(... other rows...)   ** 

我们的性能表:

#Performance
**Perf_ID Performance_Date   Performance_Rating      Employee_ID (FK)**
   1     'June 2020'               5                   1
   2     'June 2020'               5                   2  
   3     'December 2020'           4                   1
   4     'December 2020'           5                   2

我们的 Employee_ID 是 Employee 表中的主键(PK)和 Performance 表中的外键(FK)。它可以让我们了解每个员工的表现。但是,在性能表中不是有些表里不一吗?你说得对,我们也可以想象将其规范化,用 Performance_Rating 来获取评级,用 Performance_Cycles 来获取日期。

  • 3NF: 我们需要遵循 2NF,我们想要解决任何传递函数依赖。这具体意味着什么?对于这个规范化步骤,以及下一步,我们将使用另一个例子来传达这些概念。

想象这张桌子:

来源

我们有传递函数依赖,因为作者国籍依赖于作者,而作者又依赖于书[标题]。我们还有一个带[流派名称]的,依赖于[流派 ID],反过来又依赖于书[书名]。

我们想要的是[作者国籍]和[流派名称]在它们自己的表中。

#Author table
 **Author        Author Nationality**
Chad Russel       American
 EF Codd           British

和[流派]表:

#Genre table
 **Genre ID       Genre Name**
    1             Tutorial
    2          Popular Science

这是正常化的步骤吗?不会。但大多数情况下,归一化发生在 3NF 以内。我们上面回顾的已经是标准化和组织数据并限制异常的一个强有力的开始。查看下一节以获得更多资源。

更进一步

  • BCNF:它代表 Boyce-Codd 范式,通常被称为 3.5NF,因为它专注于 3NF 未涵盖的异常。博伊斯·科德因其发明而受到称赞。Boyce 共同发明了 SQL,而 Codd 发明了数据库管理的关系模型,是我们一直在讨论的标准化步骤的幕后推手。

BCNF 是 defined⁴作为:

一个关系模式 R 在 BCNF 当且仅当对于它的每一个依赖关系 X → Y ,至少有一个下列条件成立:

xy是平凡的函数依赖(Y ⊆ X),(y 是 x 的子集)**

**X是模式 R 的超级键。

3NF 覆盖的大多数关系在 BCNF,但不是全部。这里有一个例子。

  • 4NF,5NF 和 6NFT22【这个环节】或者这个可能有帮助

最后的话

暂时就这样吧!本文更侧重于模式和规范化的理论概念,而不是 SQL Server 的使用。然而,在以前文章的支持下,您现在可以按照规范化步骤来尝试规范化一个表。

感谢您的阅读,请告诉我您的想法,或者是否有我应该涉及的话题。下次见!

编码快乐!

感谢阅读!喜欢这个故事吗? 加入媒介 获取完整的我的所有故事。

继续第五集的旅程!

通过第 5 集学习如何使用 SQL 作业代理编写 SQL 存储过程和调度作业。

****

或者选择你喜欢的另一集

在第 6 集中,我们介绍了用于 ETL 的 SSIS 包,并回顾了如何在两个数据库之间以及一个数据库和 Excel 之间导入和导出数据。第六部 SSIS 套餐简介

在第 7 集中,我们将 SQL Studio 连接到 PowerBI,并构建了我们的第一个视觉效果。[第七部分连接到 PowerBI &第一视觉效果](http://Part 7 Connect to PowerBI & First Visuals)****

参考文献

  1. Schema-Wikipedia,https://en . Wikipedia . org/wiki/Schema #:~:text = The % 20 word % 20 Schema % 20 comes % 20 from,is % 20 used % 20 as % 20 plural % 20 forms
  2. 博伊斯——维基百科,https://en.wikipedia.org/wiki/Raymond_F._Boyce
  3. Codd —维基百科,https://en.wikipedia.org/wiki/Edgar_F._Codd
  4. 亚伯拉罕·西尔伯沙茨(2006 年)。 数据库系统概念 (第 6 版。).麦格劳-希尔。第 333 页。国际标准书号 978–0–07–352332–3。

了解 SQL Server Management Studio —第 5 部分存储过程和调度

原文:https://towardsdatascience.com/learn-sql-server-management-studio-part-5-stored-procedures-scheduling-88fd9788d314?source=collection_archive---------12-----------------------

让你在派对上开心的技能!循序渐进。

迈克尔·泽兹奇在 Unsplash 上的照片

在最后几集里…

你好。欢迎学习 SQL 和 SQL Server Studio 系列教程的第 5 部分。有一个简单的目标:让你熟悉和适应这个工具和语言。“这有什么关系?”我知道你在问。事实证明,好奇心和副业往往是被新项目选中的关键,甚至是获得新工作的关键。事实上,您已经使用了一个重要的工具,比如 SQL Server Studio,并且编写了一些 SQL 查询,这将会给您一个清晰的开端。

如果您错过了关于如何设置我们的环境和本地服务器的第 1 集,请阅读本文:

第二集将教你如何创建自己的数据库、表格,以及关于命名约定的重要注释:

在第 3 集,我们介绍了 CRUD 操作以及主键和外键:

在第 4 集,我们讨论了模式&主要的规范化步骤:

别忘了回来😉。

期待什么?

今天我们将看看存储过程和作业调度。本教程结束时,您将创建自己的过程,并安排它们在方便的时候运行。这看起来并不多,但它是一项强大而简单的自动化技能,可以添加到您的工具箱中。让我们直接跳进来吧!

存储过程、奇妙的工具以及在哪里可以找到它们

存储过程是奇妙的工具。它们允许您保存和存储查询。虽然这对于诸如“SELECT * FROM Departments”之类的简单查询似乎并不重要,但对于涉及多个表的复杂查询,或者利用系统存储过程,这将节省大量时间。“系统存储过程”?这些是 SQL Studio 中存在的过程,例如,可以使用sp _ send _ dbmail向使用 SQL Studio 的电子邮件收件人发送邮件。

现在,让我们回顾一下上面的内容,希望你会接受这个想法…

  • 将脚本存储为过程,
  • 使用系统过程,如 sp_send_dbmail,
  • 安排程序

我希望上面提到的潜在用例能让你头脑发热😉让我们看看如何开始。

  1. 在 SQL Server Studio 中,存储过程(或简称为过程)驻留在任何数据库中的 programmability 子目录下。请看下面的内容:

起初,没有,然后出现了第一个。让我们看看这是如何发生的。

2.右键单击存储过程,然后单击存储过程

3.将出现典型的查询窗口,其中填充了一个过程模板

任何以双破折号“- -”开头的内容都会自动变成绿色,这些是注释。它们将被 SQL 查询编辑器忽略(我可以说编译器吗?🤔)当我们运行脚本时。你可以随意删除绿色的评论,但是部分内容需要调整,以提供作者、创作日期和描述等信息。

然后是“创建过程<procedure_name>”。CREATE 过程后面的名称将定义该过程的名称。没有必要保留符号< >。</procedure_name>

对于这个例子,我们将其命名为通货膨胀 _ 调整

4.现在,为了保存和检查我们新创建的过程,我们将编写一个占位符查询。在开始和结束之间,添加以下内容。“部门”是我们在前面的练习中创建的表格。我们假设您已经学习了前面的教程,如果没有,请继续创建您自己的表或调整查询以匹配您的环境。

SELECT * FROM HR_data.dbo.Departments

这是我有的

5.我们可以突出显示该查询并运行它(F5 或执行绿色箭头)

6.现在让我们运行整个脚本,这将创建并保存过程。

使用蓝色箭头刷新,出现该过程。

7.要修改它,请右键单击,然后单击“修改”。将出现查询编辑器。

现在可以调整脚本,然后点击“执行”。这将保存和更新程序。在此之前,我们将在我们的薪金表中添加一条新记录,然后我们将返回到该过程并创建一个将自动运行的脚本。

8.让我们打开工资表。提醒一下,创建表的一种方法是右键单击 Tables > New > Table,然后输入不同的列名和数据类型。

9.我们现在将向该表添加一条记录

INSERT INTO SalariesVALUES (1, 2500, 1)

这样,雇员#1 的薪金为 2500。

10.回到我们的过程屏幕,我们将编写一个脚本来根据通货膨胀率调整工资。代替我们原来的占位符代码 SELECT * FROM Departments,,我们将编写以下代码:

UPDATE SalariesSET Salary_USD = Salary_USD * 1.03

该查询更新了 Salary 表,并将 Salary_USD 的值设置为 Salary_USD 乘以 1.03,这意味着我们增加了 3%的通货膨胀率。

11.让我们选择这两行,并运行它们(F5 或 Execute)

快速检查一下我们的原始表,我们看到 2500 现在是 2575,增加了 3%。

12.现在,如果您已经学习了以前的教程,这仅仅是对一个专栏进行更新,并不是什么新鲜事。这种加薪每年都要进行,如果我们能安排这样的事情,不是很好吗?进入日程安排。

计划作业

这里我们将讨论如何安排一个任务,例如如何运行我们的通货膨胀调整程序。但首先,有些坏消息。允许您从 SQL Studio 中运行和计划作业的 SQL Server 代理在 SQL Express 中不可用,这是因为 SQL Express 是免费软件。

但是,我将向您展示环境是什么样子的,如何安排作业,这样您就可以了解这个特性,或者如果您有付费版本的话,也可以继续学习。或者,可以使用 Windows 任务计划程序运行脚本。这超出了 SQL Studio 文章系列的范围,将在附录文章中讨论。

SQL Server 代理

该部分位于服务器功能列表的末尾。

  1. 右键单击作业,然后单击新建作业,将出现一个新窗口

在这里你可以命名一个工作,精确的分类并提供描述。大多数时候只会填写姓名

2.在“步骤”下,用户可以设置作业应该遵循的不同步骤。

如果一个作业有多个步骤,可以使用“移动步骤”下的上下箭头重新排列其运行顺序。

3.点击“新建”,出现一个新窗口。我们为该步骤定义了一个名称,我们精确了数据库,这里应该是 HR_data 和一个命令。该命令将执行我们的存储过程,因此是 EXEC [dbo]。【通货膨胀 _ 调整】

4.在新步骤窗口的“高级”选项卡下,我们可以定义下一个操作,无论我们的步骤是成功还是失败。

以下是我们在成功情况下的行动范围:

如果失败:

它们不言自明。然后,我们可以验证步骤的创建,并点击 OK。

5.该步骤出现在我们的列表中

6.现在让我们安排一下

如您所见,除了调度功能,还有一个功能是在作业运行或失败时得到通知。

类似的简单屏幕和一组选项:

7.设置新时间表的窗口如下所示

频率可以设置为每天、每周或每月。在我们的示例中,我们将选择每月一次,然后调整参数使其每年运行一次。

这意味着每 12 个月一次。正如摘要描述所解释的,该计划将从 2022 年 1 月 1 日开始使用,并在该月的第二天运行。如果这听起来不错,我们为我们的作业计划定义一个名称,然后单击 ok。

8.已经安排好了。如果我们有更复杂的需求,而这些需求不能由单一的计划来处理,我们可以创建新的计划来涵盖所有的情况。

我们确认所有打开的窗口,新作业将出现在我们的作业列表中。

注意:作业调度程序显示的开始时间与您的服务器相关联。也就是说,如果它位于德国,则基于该时区安排作业。

最后的话和接下来会发生什么

暂时就这样吧!我希望您现在对使用 SQL Server 更有信心,并且:

  • 创建和修改 SQL 存储过程,
  • 了解 SQL 作业调度程序的工作原理,
  • 如果你有 SSMS 付费版,你就知道如何浏览 SQL 作业调度程序

感谢您的阅读,请告诉我您的想法,或者是否有我应该涉及的话题。下次见!

编码快乐!

感谢阅读!喜欢这个故事吗? 加入媒介 可完整访问我的所有故事。

继续第六集的旅程!

通过第 6 集,了解如何创建 SSIS 包来导入和导出数据,以便在两个数据库之间传输或在 excel/CSV 和数据库之间传输。

或者选择你喜欢的另一集

在第 7 集中,我们将 SQL Studio 连接到 PowerBI,并构建了我们的第一个视觉效果。[第 7 部分连接到 PowerBI &第一视觉效果](http://Part 7 Connect to PowerBI & First Visuals)

了解 SQL Server Management Studio —第 6 部分 SSIS 软件包

原文:https://towardsdatascience.com/learn-sql-server-management-studio-part-6-ssis-packages-9438dbc90437?source=collection_archive---------12-----------------------

让你在派对上变得有趣的技巧——一步一步来

迈克尔·泽兹奇在 Unsplash 上的照片

在最后几集里…

你好。欢迎学习 SQL 和 SQL Server Studio 系列教程的第 6 部分。有一个简单的目标:让你熟悉和适应这个工具和语言。“这有什么关系?”我知道你在问。事实证明,好奇心和副业往往是被新项目选中的关键,甚至是获得新工作的关键。事实上,您已经使用了一个重要的工具,比如 SQL Server Studio,并且编写了一些 SQL 查询,这将会给您一个清晰的开端。

如果您错过了关于如何设置我们的环境和本地服务器的第 1 集,请阅读本文:

第二集将教你如何创建自己的数据库、表格,以及关于命名约定的重要注释:

在第 3 集,我们介绍了 CRUD 操作以及主键和外键:

在第 4 集,我们讨论了模式&主要的规范化步骤:

在第 5 集,我们讨论了存储过程和调度,这是一个真正的野兽。我怎么强调这将如何促进和自动化你的日常(数据)生活都不为过。

别忘了回来😉。

期待什么?

今天我们来看看 SSIS 套餐。在本教程结束时,您将创建自己的包,并且通过利用时间表,您将能够自动化诸如数据导入和导出之类的任务。让我们直接跳进来吧!

快速定义

SQL Server Integration Services(SSIS)是 SQL Server Studio 的一个组件,可以执行数据迁移任务。它有一个用于 ETL 步骤(数据提取、转换和加载)的数据仓库工具。一个 SSIS 包用微软的话说就是:

连接、控制流元素、数据流元素、事件处理程序、变量、参数和配置的有组织集合,您可以使用 SQL Server Integration Services 提供的图形设计工具进行组装,也可以通过编程方式进行构建

图形窗口使执行这些任务变得很容易,所有人需要做的就是提供所需的信息或从下拉列表中选择选项。我们将关注的特性是导入/导出。

开始工作

我假设您已经安装了 SQL Studio 环境,并且已经连接。下一步是:

  1. 右键单击数据库,选择任务,然后选择导入数据

2.你会看到一个典型的微软向导窗口,让我们继续

3.我们被要求选择复制数据的来源。在可用选项中,我们找到了 Microsoft Excel 和 SQL Server Native Client 11.0

SQL 数据库之间的导入/导出

要在 SQL 数据库或表之间导入,我们需要执行以下操作:

  1. 我们的来源将是 SQL Server Native Client 11.0

2.然后,我们选择将数据导出到哪里,并决定从一个或多个表或视图中复制数据

3.6.接下来,我们可以决定复制数据或编写查询来指定要传输的内容。我们会选择第一个选项。

4.然后,向导让我们选择要复制的表,并定义名称或选择一个现有的表。在这个例子中,我们将“雇员”复制到的表将被命名为“雇员 _ 副本”。

5.在编辑映射下,我们有几个选项。在我们的例子中,当我们创建一个新表时,Employees_copy 还不存在,一些选项是灰色的。如果我们要复制到一个现有的表,我们可以决定“删除目标表中的行”或“向目标表追加行”。

6.然后,我们可以决定立即运行包,并将包保存在 SQL Server 上或本地(文件系统)。我们会把它保存在本地。

7.我们可以定义名称和目标路径

7.在下一页,SQL Studio 提供了一个摘要

8.然后,流程运行并提供逐步反馈。

逐步流程和相关状态的示例(此处:Excel 到 SQL)

9.用户可以使用 Microsoft Visual Studio 或 NotePad++打开. dtsx 文件。该脚本详细说明了来源、目的地等。如果流程中的某个步骤发生了变化,而不是重新创建一个包,那么调整脚本是有意义的。

让我们用 Microsoft Excel 来介绍导入。

  1. 重新启动该过程,右键单击数据库,然后选择任务>导入数据

2.选择 Microsoft excel,向导窗口会更新,并要求我们提供导入数据的 Excel 路径以及 Excel 版本。从经验来看,Excel 版本已经导致了一些意想不到的结果。如果您的导入无法正常工作,请尝试将扩展名更改为。xls 或者。xlsx,这有时会起作用。单击下一步。

3.然后,我们可以选择将这些数据拷贝到哪里。我们选择 SQL Server Native Client 11.0。但是不要点击“服务器名称”旁边的箭头。这个向导有一个特点,当你点击它时,它会冻结。它开始搜索实例,并且在提供任何东西时都很慢。让我们来看一个快速的技巧。

4.在 SQL Studio 主窗口中,单击连接>数据库引擎

然后复制粘贴您的服务器实例的名称。

回到我们的向导窗口,让我们将其粘贴到“服务器名称”字段。就是这样,这花了 2-3 秒,而下拉列表会冻结…我从来没有发现,它太慢了。

5.下一步是挑选我们的数据库。为此,我们可以安全地单击下拉菜单,可用选项将来自我们上面的服务器名称。

6.以下步骤与数据库到数据库拷贝的步骤相同。SQL 将 Excel 源文件视为一个数据库,其中的每一张表都是一个表。用户可以定义目标表的名称,从而创建一个表,或者选择一个现有的表。

最后的话和接下来会发生什么

暂时就这样吧!我希望您现在对使用 SQL Server 更有信心,并且:

  • 创建您自己的 SSIS 软件包,
  • 使用 Excel 或其他数据库将数据从数据库中导出或导入到数据库中,

接下来会发生什么?在接下来的文章中,我们将结合 SSIS 包和作业调度的力量,来自动化一些 ETL 任务。

感谢您的阅读,请告诉我您的想法,或者是否有我应该涉及的话题。下次见!

编码快乐!

感谢阅读!喜欢这个故事吗? 加入媒介 完整访问我的所有故事。

继续第七集的旅程!

了解如何将 SQL Server 连接到 Power BI,这是一款功能强大的可视化工具,也是通过创建您的第一批视觉效果首次介绍这款商业智能工具。

如何将 SQL 连接到 PowerBI & First Visuals

原文:https://towardsdatascience.com/learn-sql-server-management-studio-part-7-connect-to-powerbi-first-visuals-b13df9d78ccc?source=collection_archive---------33-----------------------

让你在派对上变得有趣的技巧——一步一步来

迈克尔·泽兹奇在 Unsplash 上的照片

在最后几集里…

你好。欢迎学习 SQL 和 SQL Server Studio 系列教程的第 7 部分。有一个简单的目标:让你熟悉和适应这个工具和语言。“这有什么关系?”我知道你在问。事实证明,好奇心和副业往往是被新项目选中甚至获得新工作的关键。事实上,您已经使用了一个重要的工具,比如 SQL Server Studio,并且编写了一些 SQL 查询,这将会给您一个清晰的开端。

如果您错过了关于如何设置我们的环境和本地服务器的第 1 集,请阅读本文:

第二集将教你如何创建自己的数据库、表格,以及关于命名约定的重要注释:

在第 3 集,我们介绍了 CRUD 操作以及主键和外键:

在第 4 集,我们讨论了模式&主要的规范化步骤:

在第 5 集,我们讨论了存储过程和调度,这是一个真正的野兽。我怎么强调这将如何促进和自动化你的日常(数据)生活都不为过。

在第 6 集,我们介绍了用于 ETL 的 SSIS 包,并回顾了在两个数据库之间以及数据库和 Excel 之间导入和导出数据。

别忘了回来😉。

期待什么?

今天,我们将看看如何将数据连接到可视化工具。我们这次旅行的伙伴将是 PowerBI。在本教程结束时,您将有信心将数据库连接到 PowerBI,并开始构建可视化效果。让我们直接跳进来吧!

快速介绍

PowerBI 或 PBI 是一个可视化工具,或者在封闭的圈子里被称为 T2 商业智能工具。它是由微软创建的,这个工具已经存在了几年了。它在不断发展,不断添加新功能,并通过 PBI 博客进行交流。为什么这是好消息?有两个原因:

  • 一个正在被积极开发的工具是一个紧跟当前趋势的工具(希望如此),并且是所有者承诺的标志,
  • 它是微软 PowerPlatform 的一部分,该平台还包括 PowerAutomate 和 PowerApps 等工具。在一家顶级科技公司的支持下,PowerPlatform 似乎是一个重要的焦点,好消息是它不会很快消失。

为什么要关心 PowerBI?

  • 在广泛使用所有这些工具后,他们为许多项目提供了流畅而强大的端到端体验。
  • PowerBI 也是一项受欢迎的技能,它带有常见的微软环境和界面。它背后有一个强大且不断发展的社区,可以在线回答问题。

入门指南

PowerBI 可以免费下载,尽管存在不同的定价方案来提供额外的功能。

要求

根据官方文档报告,运行 PowerBI Desktop 有以下最低要求:

  • 自 2021 年 1 月 31 日起,Windows 7 不再支持 Power BI Desktop 需要 Windows 8.1 / Windows Server 2012 R2 版或更高版本
  • 内存(RAM):至少 2 GB 可用,建议 4 GB 或更多。
  • 显示器:至少需要 1440x900 或 1600x900 (16:9)的分辨率。不支持较低的分辨率,如 1024x768 或 1280x800,因为某些控制(如关闭启动屏幕)会超出这些分辨率。
  • Windows 显示设置:如果您将显示设置设置为将文本、应用程序和其他项目的大小更改为 100%以上,您可能看不到某些必须与之交互才能继续使用 Power BI Desktop 的对话。如果您遇到此问题,请转到“设置”>“系统”>“显示”,在 Windows 中检查您的显示设置,并使用滑块将显示设置恢复到 100%。
  • CPU:建议使用 1 千兆赫(GHz) 64 位(x64)处理器或更好的处理器。

导入数据

在第 6 集,我们已经看到了如何导入数据。让我们用示例销售数据来做这件事。

  1. 为此创建一个新的数据库 AW2019。为了做到这一点,作为一个提醒:右键单击您的服务器名称,然后创建一个数据库。
  2. 从 MS AdventureWorks 下载这个数据集,它是一个专注于销售数据的子样本。
  3. 在您的 SQL 环境中导入它。提醒一下,首先右击数据库>任务>导入> Excel
  4. 给它一个名称,在我们的例子中,它将是[SalesQuota]。结果看起来像这样:

下载 PowerBI 并设置环境

  1. 要下载 PowerBI,请访问

https://powerbi.microsoft.com/en-us/downloads/并选择“下载”

2.你被重定向到微软商店,在那里你可以下载该程序(我不清楚为什么会有这个额外的重定向,但我们不要开始咆哮😀)

正如你从 3 PEGI 的标签上可以看出的,这是一个安全的地方。欢迎每个人都来玩 PowerBI —万岁!

3.让我们启动 PowerBI。顶部色带与其他 MS 产品相似。单击 SQL Server

4.我们会看到一个新窗口,提示我们提供服务器名称

我们还有两种数据连接模式:Import 和 DirectQuery。有什么区别?

  • 导入—将数据副本导入 Power BI 桌面环境。PBI 使用导入的数据进行任何创建或与数据的交互。
  • DirectQuery —没有数据导入或复制到 Power BI Desktop 中。对于每个可视化,Power BI 向数据源发送一个查询并返回结果。

你应该用哪一个?视情况而定……我们来回顾一下优点和局限性。

优势

  • DirectQuery 允许在非常大的数据集上创建可视化效果,这在常规导入中是不可能的,
  • 更方便地处理数据更改。每当有更新的数据时,只需要刷新,而不是重新导入整个数据集。
  • 1gb 数据集限制不适用于 DirectQuery。

限制

  • 如果查询编辑器查询过于复杂,就会发生错误。建议的解决方案是删除该步骤或导入数据。微软文档还告诉我们没有像 SAP Business Warehouse 这样的多维数据源的查询编辑器。
  • Power BI 服务(即浏览器)不支持从具有 SSO 身份验证的数据源引用 DirectQuery 表的计算表和列。
  • DirectQuery 中不支持自动日期/时间,也就是说,DirectQuery 模式不支持日期列的处理(按年、季度、月或日向下钻取)。
  • 云数据源有 100 万行的限制,本地数据源的有效负载限制为每行 4 MB(取决于专有的压缩算法)或整个视觉的 16MB 数据大小。使用高级容量时,可能会提高某些限制。该限制不影响用于创建使用 DirectQuery 返回的数据集的聚合或计算。它只影响返回的行。

在我们的例子中,我们将从一个简单的导入开始

数据现在被导入到我们的环境中:

PowerBI 提供了四个主要面板,从左边开始:包含可视化效果的面板、过滤器、用于调整可视化效果参数的可视化窗格,以及数据集/字段

第一组图像

  1. 我们首先选择 SalesAmountQuota,然后选择 Employee Key。EmployeeKey 是对个人的引用。
  2. PowerBI 将这些数据变成了现实,选择了集群柱形图。

通过选择它,“可视化”窗格会在“值”下显示 SalesAmountQuota,在“轴”下显示 EmployeeKey。

3.好的开始,但是让我们重新安排一下…员工键被认为是连续的,这解释了我们视觉中的空白。但是我们的员工数据是绝对的。让我们调整一下。在可视化下,转到 x 轴,然后交换分类。

我们的图像更新了。看起来已经好多了。

为了澄清这一点,我们将再次使用 EmployeeKey 添加一个图例。将其拖放到图例字段。

我们得到:

很好。这可能是保存我们仪表板的好时机。

4.最后,我们将重点关注前 5 名卖家。为此,在“筛选器”下,对于 EmployeeKey,我们将选择筛选器类型“前 N 名”,将其设置为 5,并精确地将其设置为 SalesAmountQuota。然后,我们按下应用过滤器。

我们看到了前五名的销售情况。显然还有很多可以做的来增强这个图表,但是我们有第一个。

5.现在,让我们为公司和我们的前三名销售人员总结一些销售趋势。我们从折线图开始,将 CalendarYear 设置为轴,将 SalesAmountQuota 设置为值。很简单。我们的销售停滞不前,甚至略有下降。我们的畅销书表现如何?

6.选择视觉效果,复制并粘贴它,然后将它移到一边。我们将选出过去 3 年的前 3 名销售人员。

7.使用我们的上述视觉新副本,我们将添加一个图例。随着时间的推移,我们的销售突然出现了明显的分化。我们现在需要

  • 选择我们的前 3 名员工

如前所示,除了我们限制为 3 个而不是 5 个。

  • 定义 3 年时间窗口

我们将设置 CalendarYear 过滤器来关注 2011 年及以后发生的事情。

这是我们的结果:

这仍然很粗糙,但是一个好的开始。

一个教训的旁注

关于所学课程的一个简短的题外话。当我最近查看我的任务管理器时,我决定终止一个与 SQL 相关的进程。当时我没有使用这个程序,想清空一些内存。所以我摆脱了:

这是一个错误的举动。那天晚些时候,当我试图启动 PowerBI 并连接到服务器时,我就是做不到。我在 SQL Studio 和 PowerBI 上都一直收到这个错误消息。

找不到服务器或服务器不可访问。SQL 网络接口,错误 26 —定位指定的服务器/实例时出错

如何解决错误-26 SQL 网络接口

我们需要的是重新启动正确的 SQL 服务。

  1. 打开 Windows 菜单并键入服务

2.在新窗口中,查找 SQL Server (SQL Express)

3.点击绿色箭头“开始服务”。

4.Windows 将启动该服务并显示它正在运行

5.让我们再次尝试连接到服务器…它现在工作了🎈。

最后的话和接下来会发生什么

暂时就这样吧!我希望您现在对使用 SQL Server 更有信心,并且:

  • 将 SQL Studio 连接到 Power BI,
  • 理解处理数据的两个选项:导入数据或使用 DirectQuery,
  • 创造你的第一个视觉效果,

感谢您的阅读,请告诉我您的想法,或者是否有我应该涉及的话题。下次见!

编码快乐!

感谢阅读!喜欢这个故事吗? 加入媒介 可完整访问我的所有故事。

继续第八集的旅程!

了解如何利用 SQL 视图。这是一个非常简单而强大的工具。在本教程结束时,您将会感到有能力利用视图的力量。

资源

  1. https://docs . Microsoft . com/en-us/power-bi/fundamentals/desktop-get-the-desktop
  2. https://docs . Microsoft . com/en-us/power-bi/connect-data/desktop-use-direct query

了解 SQL Server Management Studio —第 8 部分利用视图

原文:https://towardsdatascience.com/learn-sql-server-management-studio-part-8-leverage-the-views-206fbcef3957?source=collection_archive---------18-----------------------

让你在派对上开心的技能!循序渐进。

迈克尔·泽兹奇在 Unsplash 上的照片

在最后几集里…

你好。欢迎来到 SQL 和 SQL Server Studio 系列教程的第 8 期。有一个简单的目标:让你熟悉和适应这个工具和语言。“这有什么关系?”我知道你在问。事实证明,好奇心和副业往往是被新项目选中的关键,甚至是获得新工作的关键。事实上,您已经使用了一个重要的工具,比如 SQL Server Studio,并且编写了一些 SQL 查询,这将会给您一个清晰的开端。

别忘了回来😉。

期待什么?

直到第 7 集,我们有一个线性的渐进的学习曲线。它从 SQL Studio 的设置开始,然后我们继续创建数据库、CRUD 操作、对话模式、SSIS 包、调度和自动化以及连接到 PowerBI。现在我们有了一个坚实的基础,让我们看看另一个有趣的特性,视图。这是一个非常简单而强大的工具。在本教程结束时,您将会感到有能力利用视图的力量。让我们直接跳进来吧!

什么是 SQL 视图?

视图是存储在我们环境中的 SQL 查询。由于视图是一个 SQL 查询… * drumrolls *…它可以被查询。让我们看一个假设的例子:

假设您有一组表,并构建一个复杂的连接。留着以后用不是很好吗?我希望你会同意。虽然我们可以将这个连接的结果保存为一个新表,但这可能不是最佳方法。为什么不呢?

  • 维护新表 —需要维护连接产生的新表,以保持相关性。当然,我们可以在重新创建新表之前,通过调度一个作业来删除或截断新表。但是这对服务器来说是更多的工作。
  • 空间是稀缺的,存储是黄金 —作为连接结果的新表的创建也意味着存储现在将被该表占用。应该没问题吧?嗯,如果只是一次性的事情,那也没什么,虽然在野外,没有这样的事情,而且事情可能会很快升级。在一个月或六个月内,您可能会从类似的连接操作中得到 10 个以上的表。所有这些空间现在都已被占用,需要保持更新。

相反,如果我们能够利用观点的力量,我们就可以摆脱上述担忧。为什么?

  • 视图只是一个查询。每当更新底层表时,查询视图会自动为我们提供新数据。也就是说,视图提供一致的数据。
  • 一个视图本质上是轻量级的,因为它只有几行代码。也就是说,它们是高效的。

如何构建视图

假设您已经安装并启动了 SQL Studio。

  1. 在数据库结构中,指向“表”下的“视图”。
  2. 右键单击并选择“新建视图”

3.新窗口显示了视图环境,其中有一个弹出窗口提供表的初始选择。这些是我们在前几集创建的表。

4.在这个例子中,我们将重点构建一个视图来收集包含部门和雇员的表。选择两者,然后添加,然后关闭。

5.因为那些表有主键和外键,我们在第 3 部分中讨论过,我们可以使用这些关系将它们匹配在一起。

6.然后,我们可以从表中手工选择感兴趣的列,下面的查询会自动更新。

该查询使用两个表中的 Department_ID 作为匹配键来构建内部连接。

7.然后我们可以保存视图,并给它一个有意义的名字。下面是一个简短的题外话。

如何命名视图

如果您将 SQL Server 连接到另一个系统,该系统可以显示您存储的所有基础表、视图和存储过程,清楚地区分表和视图的命名约定可能会很有用。一种方法是以大写的 V 开始命名所有的视图,后面跟着一个下划线 _。如果您需要一个视图来匹配用户和他们的购买,我们可以使用 V_userspurchases,它与表 Users 和 Purchases 明显不同。

我们将选择 V _ DepartmentsEmployees 员工。

8.接下来,让我们通过查询视图来检查它的外观。

select * from V_DepartmentsEmployees

这将返回一个表,这是我们的视图的结果,它连接了两个表。如前所述,这个视图是轻量级的,让我们来看看到底有多轻。

视图与表格比较

我们之前讨论过,视图的优势在于只是查询,并不存储数据本身。下面是我们的数据表和 SQL 脚本的大小之间的一个快速的&比较。对于这个例子,表的大小是 7 行 x 163 列。该查询是一行代码:

select * from v_SalesQuota

在我们的快速和脏比较之后的 SQL 查询重约 262 字节。

现在对于底层数据(7 行 x 163 列,没有空值也没有空白),导出为。CSV,我们的快速和肮脏的方法显示约 9933 字节。

我们可以采用另一种方法,找出 SQL Server 中某个元素占用的空间。为此:

  1. 通过 CTRL+N 打开一个新的查询窗口
  2. 键入以下命令
sp_spaceused '[TableName]'

这将返回关于我们的表的一些信息:

我们可以对我们的视图做同样的事情:

sp_spaceused '[AW2019].[dbo].[v_SalesQuota]'

正如我们所见,视图不是表,它不包含任何数据,它只是一段轻量级代码。

最后的话和接下来会发生什么

暂时就这样吧!我希望您现在对在 SQL Server 中创建和利用视图更有信心了。

  • 视图是轻量级的,它们是存储在 SQL Server 上的查询,可以被查询。因此,它们不保存任何数据。
  • 与通过连接创建表相比,它们是更好的选择,
  • 它们不需要像连接产生的表那样被“维护”。无论何时查询,视图都会从基础表中提取数据。请注意,如果基础表发生变化,视图使用的列被删除,视图将会中断。

下一步是什么?我们将讨论临时表的主题。

感谢您的阅读,请告诉我您的想法,或者是否有我应该涉及的话题。下次见!

编码快乐!

感谢阅读!喜欢这个故事吗? 加入媒介 获取完整的我的所有故事。

了解 SQL Server Management Studio —第 9 部分临时表

原文:https://towardsdatascience.com/learn-sql-server-management-studio-part-9-temporary-tables-f69aee616833?source=collection_archive---------18-----------------------

让你在派对上开心的技能!循序渐进。

迈克尔·泽兹奇在 Unsplash 上的照片

在最后几集里…

你好。欢迎学习 SQL 和 SQL Server Studio 系列教程的第 9 部分。有一个简单的目标:让你熟悉和适应这个工具和语言。“这有什么关系?”我知道你在问。事实证明,好奇心和副业往往是被新项目选中甚至获得新工作的关键。事实上,您已经使用了一个重要的工具,比如 SQL Server Studio,并且编写了一些 SQL 查询,这将会给您一个清晰的开端。

别忘了回来😉。

期待什么?

在建立了坚实的基础直到第 6 集之后,我们转而连接到 PowerBI,然后最近发现了视图。现在我们将介绍和使用临时表。至于视图,这是一个非常简单,但是非常强大的工具。它允许您即时检查您的结果,或临时保存数据以供以后在程序中使用。在本教程结束时,您会觉得有能力利用临时表的力量。让我们直接跳进来吧!

介绍

临时表,酷孩子们称之为' temp tables ',正如他们的绰号所暗示的,是只暂时存在于数据库服务器上的表。这种表只是暂时存储常规表中的数据。

当需要使用大型表时,临时表非常方便,但只需要其中的记录或列的子集。当您发现自己需要反复使用同一个子集时,您可以构建一个临时表来存储相关的数据子集并加以利用,而不是进行过滤。临时表驻留在系统数据库 tempdb 中。

临时表可以是本地的,也可以是全局的。临时表是局部的还是全局的将影响它的寿命。正如微软所说:

  • 本地临时表仅对用户的当前连接可见,当用户断开与 SQL Server 实例的连接时,它们将被删除。
  • 全局临时表在创建后对任何用户都是可见的,当引用该表的所有用户从 SQL Server 实例断开连接时,它们将被删除。

一旦创建了临时表,就可以对它执行查询。事不宜迟,让我们看看如何建立一个临时表。

创建临时表

我们假设您的 SQL Studio 环境已经启动并正在运行。如果您需要帮助,这里有一个分步指南:第 1 部分 SQL Server Studio 的分步安装

  1. 让我们创建一个简单的表
CREATE TABLE workers(name VARCHAR(50),age INT,job_title VARCHAR(50))INSERT INTO workersVALUES ('Max', 20, 'Analyst'),('Bob', 33, 'Manager'),('Kelly', 25, 'CEO');

我们创建具有三个属性(姓名-年龄-职位)的表 workers,,并为 Max、Bob & Kelly 插入三个条目。让我们运行它(F5 或绿色箭头),查询运行成功。

现在让我们验证我们的表的状态:

select * from workers

一切都好!

2.现在这张桌子又短又甜。但是想象一下它有 100,000 行和 50 列。这可能发生在野外。如果您要编写一个过程或任何查询来处理这个问题,可能会很麻烦。让我们用它做一个临时表格。

在我们的例子中,我们将决定排除年龄列和“分析师”职位的子集。

3.让我们从简单的开始,从我们的查询中排除年龄列:

select name, job_titlefrom workers

这给了我们:

4.现在,我们将过滤掉“分析师”的职称

select name, job_titlefrom workerswhere job_title not like '%Analyst%'

这给了我们:

5.所有这些小步骤都完成了,现在让我们将这个结果保存在一个本地临时表中。

select name, job_titleinto #temp_without_age_analystfrom workerswhere job_title not like '%Analyst%'

我们成功运行了查询:

就语法而言,临时表和常规表之间到底有什么区别?关键是数字标签,或者 hash #(我个人总是走一条错误的捷径,把它们叫做 hashtags ,我的错)。这告诉 SQL server 该表将是临时的。

6.我们现在将查询这个临时表来检查它的外观。当输入时,自动补全已经提供了线索,表明它是一个临时表。

查询结果显示了我们想要的表,没有年龄,过滤掉了“分析师”职务。

还有我们原来的表怎么了?希望它没有受伤。让我们检查一下。

它很安全&完好无损🎉。

如前所述,这个临时表是短暂的,它只在查询窗口内存在短暂而有意义的生命。检查它的一种方法是打开一个新的查询窗口(CTRL+N)并查询那个临时表。

全局临时表

要构建一个全局临时表,需要使用两个散列而不是一个,即##而不是#:

select name, job_titleinto ##temp_without_age_analystfrom workerswhere job_title not like '%Analyst%'

成功运行查询后,让我们检查表是否在当前窗口之外:

在全局临时表的情况下,我们看到它在查询窗口之外仍然存在。我还断开-重新连接到 SQL server,它似乎也活了下来。关闭 SQL Studio,然后重新启动它,导致了全局临时表的消失。但是显然有一个更好的方法,就像你可以删除一个表,你可以删除一个临时表。

删除临时表

  1. 让我们在下面输入:
IF OBJECT_ID(N'tempdb..#temp_without_age_analyst') IS NOT NULLDROP TABLE #temp_without_age_analyst

2.现在,让我们查询临时表#temp_without_age_analyst 以进行验证

select * from #temp_without_age_analyst

它不见了,我们成功了!

最后的话和接下来会发生什么

暂时就这样吧!我希望您现在更有信心在 SQL Server 中创建和利用临时表,无论它们是本地的还是全局的。

  • 临时表是创建数据子集的简单而灵活的工具,
  • 它们可以是本地的或全局的,
  • 他们的生命短暂,
  • 然而,一个好的经验法则是,一旦你完成了,就把它们扔掉。

感谢您的阅读,请告诉我您的想法,或者是否有我应该涉及的话题。下次见!

编码快乐!

感谢阅读!喜欢这个故事吗? 加入媒介 可完整访问我的所有故事。

参考

  1. https://docs . Microsoft . com/en-us/previous-versions/SQL/SQL-server-2008-R2/ms 177399(v = SQL . 105)?redirectedfrom=MSDN

通过手套快速学习编码,无需参考

原文:https://towardsdatascience.com/learn-to-code-quickly-and-without-reference-through-gauntlets-3a32f79bf7db?source=collection_archive---------32-----------------------

你需要知道的 10 件事,用 Python 和 R

作者图片

两个书呆子的故事

想象两个数据科学家。你给他们每个人一个数据集,给他们一个问题。第一个人听你说,做笔记,并说他们会“继续做这件事,回头再和你联系”。

第二位数据科学家拿出他们的笔记本电脑,坐在你旁边(或分享他们的屏幕),说“让我们现在就解决这个问题”。只要你们两个能尽快地交流想法,他们就能实时编码并绘制出结果。20 分钟内,你就有了答案、图表和对数据的新理解。

你想和哪个书呆子一起工作?你想雇佣哪个书呆子?你想让哪个书呆子成为

为什么学习如何在没有参考的情况下快速编码很重要。

你为什么要学习如何快速编码?因为速度往往胜过质量。现在有一个像样的答案通常比下周有一个很好的答案要好。

速度也需要一定水平的能力。在谷歌上搜索“如何在 Pandas 中选择一列”的每一行代码后停下来,是打断你思路的一个绝妙方法。如果您可以立即将您的想法转化为代码,您就可以快速迭代并开发解决问题的更好方法。

当然,你也可以很容易地写出快速、糟糕的代码,产生不准确的结果。但是让我们现实一点,如果你要失败,最好也快点!更快的失败意味着你有更多的时间去成功!

事实上,失败正是导致人们害怕在他人面前编码的原因。我们都讨厌我们的同行看到我们的缺点,我们手指上的代码看起来像是你的想法的小代表。如果代码失败了,感觉就像是我们智慧的失败。

我来这里是为了宣传让你尽快从自我中解脱出来,在其他人面前编码的想法。你的代码不是你。就像你现在正在阅读的文字一样,你的代码只是屏幕上的文字。我有一个大秘密要和你分享!数据科学的编码很容易。

数据科学的编码很简单

嘘…

无论你做什么,不要让人力资源部的人知道我们的秘密!目前数据科学的薪水很高,我不想破坏大家的兴致。

但是,数据科学的编码真的没有那么难。

是不是神经网络或者支持向量机模型某某只是做复杂了?当然可以。但是有时实际的模型只有 3-10 行代码。让我们不要忘记模型上面的 700 行代码!这是以原始格式获取数据,然后进行清理、编码、组合、聚合等操作的代码。

这是数据科学中 99%的工作。每花一分钟建立一个模型并感觉自己很聪明,你就有两个小时的时间来获取丑陋的数据并将其转化为稍微不那么丑陋的数据。

那么我们需要知道的 10 件事是什么呢?

这 10 件事会帮你度过大多数情况。即使是看起来非常复杂的数据科学脚本,通常也可以通过以下项目的组合来实现:

  • 基本选择(选择和重命名列,不同)
  • 过滤数据
  • 用运算符(and、or 等)过滤。)或通过其他方式(顶、头等。)
  • 通过串联(如名字+姓氏)和聚合(如价格*数量)来组合列
  • 连接和追加数据
  • 汇总数据(总和、平均值、中间值、标准偏差等。)
  • 分组和聚合数据
  • 在不同的分组级别聚合(例如,解组或窗口类型功能)
  • if 语句在数据中设置标志或布尔值
  • 制作一些简单的图表(条形图、折线图、散点图)

没有谷歌,你如何快速学会做这 10 件事?

解决方案:手套!

护手是我多年来一直在做的小练习,现在我将与你分享它们。下面是它们的工作原理。

您从您选择的编程语言/ IDE 开始,有一个类似如下的空白模板:

这个模板涵盖了我之前列出的 10 件事情中的大部分。你需要做的就是:

  • 引入数据集,我们将使用来自 R 的免费和流行的 MPG 数据集(对于 Python 和 R 模板)
  • 就在模板中每个注释行的下面,凭记忆试一试。试着一路穿过铁手套。
  • 如果你能想出一个,看一看你的语言的填充模板。然后输入它。

就是这样。

周一到周五,当你第一次开始工作的时候,你就这样做。你在查看邮件或参加会议之前做这件事。

第一次做这些的时候,你可能需要查看每个部分的填写模板,这就可以了!但我向你保证,两周内你会记住每一部分。如果你能凭记忆做这 10 件事,那么你可以把它们结合起来做任何事。

代码

这里是用 python 和 r 填写的模板。对于 Python,您需要在这里下载 mpg 数据集。对于 R,数据集内置在 Tidyverse 包中,所以不需要下载它。

Python 代码

R 代码

包装它

不要让我的挑战模板阻碍你!一旦你确定了这 10 件事,你就可以继续扩大你每天要做的事情的清单。

即使你不是为数据科学编程,而是做传统编程,你也可以设计类似的手套。我可以很容易地想象出任何一个程序员在学习一门新语言时可能想要添加的东西。一些例子:

  • 运算符-与、或、等于、赋值、迭代
  • 循环- for,while,do while
  • 开关
  • 功能
  • 类——创建一个类,覆盖参数,获取/设置实例中的值,等等。
  • 基本递归(调用自身的函数)

祝你在挑战中幸存!顺便说一句,你知道你可以为一篇文章点击 50 次鼓掌按钮吗?说到你手指的护手!!

从头开始学习实现编辑距离

原文:https://towardsdatascience.com/learn-to-implement-edit-distance-from-scratch-7a6f34412d07?source=collection_archive---------13-----------------------

简·侯伯Unsplash 上的照片

我最近在 Coursera 上完成了 deeplearning.ai使用概率模型进行自然语言处理的课程。本课程涵盖了广泛的主题,包括拼写纠正词性标注语言建模单词到向量。所有主题都进行了深入探讨,并附有详细的实践练习。

但是,我们都知道,如果我们不练习所学的概念,我们肯定会很快忘记它们。因此,我想到写这篇博客,内容是关于课程中涉及的一个非常重要的指标——“编辑距离或 Levenshtein 距离”。

本文将涵盖以下主题:

  • 编辑距离简介
  • 使用递归实现它
  • 理解动态编程并实现它
  • 利用学到的技能解决问题

什么是编辑距离,如何实现?

编辑距离或 Levenstein 距离(最常见)是计算一对序列之间相似性的度量。两个序列之间的距离以将一个序列转换为另一个序列所需的编辑次数(插入、删除或替换)来衡量。

在本节中,我们将学习如何实现编辑距离。

距离度量

Levenstein 距离的计算公式如下:

图片来自 Wikipedia.com

其中 tail 表示序列中除第一个字符之外的其余部分,在 Python 行话中是a[1:]

对这些条件的解释如下:

  • 如果 b 是一个空序列(|b|=0),那么 cost 就是 a 的长度(|a|)。
  • 如果 a 是一个空序列(|a|=0,那么 cost 就是 b 的长度(|b|)。
  • 如果 a 和 b 的第一个字符相同(a[0] = b[0]),那么代价就是子序列尾(a) ( a[1:])和尾(b) ( b[1:])的代价。
  • 最后,成本是插入、删除或替换操作的最小值,定义如下:
  • lev(tail(a), b)表示从中删除一个字符
  • lev(a, tail(b)表示一个字符被插入到
  • lev(tail(a), tail(b))表示替代

注意:在上面的公式中,插入、删除或替换的成本保持不变,即 **1** 。但是,替换成本通常被认为是 **2** ,我们将在实现中使用。

使用递归编辑距离

我们可以直接将上述公式转换成递归函数来计算两个序列之间的编辑距离,但这种解决方案的时间复杂度是𝑂(3(𝑚+𝑛)).

因此,一旦我们弄清楚了编辑距离是如何工作的,我们将使用时间复杂度为𝑂(𝑚∗𝑛).的动态规划来编写一个更优化的解决方案

下面是递归函数。我还将添加一些叙述,即打印出它正在执行的操作(插入、删除或替换)的功能。

*# Below are the costs of different operations.*
ins_cost = 1
del_cost = 1
sub_cost = 2# Below function will take the two sequence and will return the distance between them.def edit_distance_recurse(seq1, seq2, operations=[]):
    *"""Returns the Edit Distance between the provided two sequences."""*

    if len(seq2) == 0:
        operations = operations + ([f"Delete `**{**seq1**}**` from sequence1."] if len(seq1) else [])
        return len(seq1), operations

    if len(seq1) == 0:
        operations = operations + ([f"Insert `**{**seq2**}**` into sequence1."] if len(seq2) else [])
        return len(seq2), operations

    if seq1[0] == seq2[0]:
        operations = operations + [f"Make no change for character `**{**seq1[0]**}**`."]
        return edit_distance_recurse(seq1[1: ], seq2[1: ], operations)

    *# calculate cost if insertion was made*
    ins_operations = operations + [f"Insert `**{**seq2[0]**}**` in sequence1."]
    insertion, ins_operations = edit_distance_recurse(seq1, seq2[1: ], ins_operations)

    *# calculate cost if deletion was done*
    del_operations = operations + [f"Delete `**{**seq1[0]**}**` from sequence1."]
    deletion, del_operations = edit_distance_recurse(seq1[1: ], seq2, del_operations)

    *# calculate cost if substitution was done*
    sub_operations = operations + [f"Replace `**{**seq1[0]**}**` in sequence1 with `**{**seq2[0]**}**`."]
    substitution, sub_operations = edit_distance_recurse(seq1[1: ], seq2[1: ], sub_operations)

    *# calculate minimum cost*
    min_cost = min(insertion + ins_cost, deletion + del_cost, substitution + sub_cost)

    if min_cost == (substitution + sub_cost):
        return min_cost, sub_operations
    elif min_cost == deletion + del_cost:
        return min_cost, del_operations
    else:
        return min_cost, ins_operations

让我们举几个例子来测试这个函数

seq1 = "numpy"
seq2 = "numexpr"score, operations = edit_distance_recurse(seq1, seq2)
print(f"Edit Distance between `**{**seq1**}**` & `**{**seq2**}**` is: **{**score**}**")
print("**\n**Operations performed are:**\n**")
for operation **in** operations:
    print(operation)

输出:

Edit Distance between `numpy` & `numexpr` is: 4Operations performed are:Make no change for character `n`.
Make no change for character `u`.
Make no change for character `m`.
Insert `e` in sequence1.
Insert `x` in sequence1.
Make no change for character `p`.
Replace `y` in sequence1 with `r`.

编辑距离为 **4** 的原因是:字符n,u,m保持不变(因此 0 成本),然后插入e & x导致到目前为止2的总成本。然后,p没有变化,所以成本没有变化,最后,y is replaced with r,导致额外成本为 2。

因此,总成本为4

使用动态编程编辑距离

对于有 重叠子问题 的问题,可以应用动态规划。就像在我们的例子中,为了得到numpy & numexpr之间的编辑距离,我们首先对子序列nump & nume进行相同的计算,然后对numpy & numex进行计算,以此类推...

一旦我们解决了一个特定的子问题,我们就存储它的结果,以后用它来解决整个问题。

想了解更多关于动态编程的知识可以参考我的短教程— 动态编程入门

现在让我们了解如何将问题分解成子问题,存储结果,然后解决整体问题。

在下图中——跨行的是我们想要以最小的转换成本转换成sequence2(跨列)的sequence1

两个序列前的字符#表示空字符串或字符串的开头。

现在,我们将用不同子序列的成本填充这个矩阵,以获得整体解决方案。但是,首先,让我们看看基本情况:

  • sequence1为空时,那么获得sequence2的成本就是添加sequence2中出现的角色的成本。矩阵中的第一行表示sequence1为空。

  • 如果两个序列都是空的,那么代价就是0

  • 如果我们将字符n添加到sequence1中,我们将得到1的成本。

  • 同样,我们将填充我们的第一行,其中每一列中的值是1 + previous column value,即添加多 1 个字符的成本。

  • 注意:最后一列的值 7 表示如果sequence1为空,那么将sequence1转换为sequence2的成本为7。同样,将空序列转换为子序列'num'的成本是3
  • 与此相反,我们有一种情况,当sequence2为空,但sequence1不为空。然后,跨行的值表示删除字符以获得空序列的成本。

  • 注:此处成本5代表删除sequence1所有角色获得一个空sequence2的总成本。

现在填充了基础案例成本的矩阵如下:

求解子问题并填充矩阵。

  • (' n ',' n ')下的值是 ***0*** ,因为这两个字符是相同的,因此没有转换成本。

  • 下面的矩阵显示了将#n转换为#nu的成本是1,由于子串#n & #n的成本是0,我们只将u加到sub-sequence1的成本相加。

  • 与上面类似,将#nu转换为#n的成本是1,由于子字符串#n & #n的成本是0,我们只增加从sub-sequence1中删除u的成本。

  • 经过几次迭代后,矩阵将如下所示。注:成本用户子序列#num & #num0,因为它们是相同的。

  • 到目前为止,我们只看了插入和删除操作,但是现在我们也将考虑一个替换的例子。为了求解子序列**#nump**&**#nume**,我们将首先计算子序列**#num**&**#num**(也就是我们上面提到的 **0** ),因此总成本为 0+2=20+2=2 ,这是将 **p** 代入**e**的成本

  • 完整的矩阵如下,总成本列在最后一行的最后一列,即 **4**

此外,通过从最后一行的最后一列到第一行的第一列追踪最小成本,我们可以得到为达到该最小成本而执行的操作。

下面的函数获取为获得最小成本而执行的操作。

def min_cost_path(cost, operations):

    *# operation at the last cell*
    path = [operations[cost.shape[0]-1][cost.shape[1]-1]]

    *# cost at the last cell*
    min_cost = cost[cost.shape[0]-1][cost.shape[1]-1]

    row = cost.shape[0]-1
    col = cost.shape[1]-1

    while row >0 **and** col > 0:

        if cost[row-1][col-1] <= cost[row-1][col] **and** cost[row-1][col-1] <= cost[row][col-1]:
            path.append(operations[row-1][col-1])
            row -= 1
            col -= 1 elif cost[row-1][col] <= cost[row-1][col-1] **and** cost[row-1][col] <= cost[row][col-1]:
            path.append(operations[row-1][col])
            row -= 1 else:
            path.append(operations[row][col-1])
            col -= 1

    return "".join(path[::-1][1:])

下面的函数使用动态编程计算编辑距离

def edit_distance_dp(seq1, seq2):

    *# create an empty 2D matrix to store cost*
    cost = np.zeros((len(seq1)+1, len(seq2)+1))

    *# fill the first row*
    cost[0] = [i for i **in** range(len(seq2)+1)]

    *# fill the first column*
    cost[:, 0] = [i for i **in** range(len(seq1)+1)]

    *# to store the operations made*
    operations = np.asarray([['-' for j **in** range(len(seq2)+1)] \
                                 for i **in** range(len(seq1)+1)])

    *# fill the first row by insertion* 
    operations[0] = ['I' for i **in** range(len(seq2)+1)]

    *# fill the first column by insertion operation (D)*
    operations[:, 0] = ['D' for i **in** range(len(seq1)+1)]

    operations[0, 0] = '-'

    *# now, iterate over earch row and column*
    for row **in** range(1, len(seq1)+1):

        for col **in** range(1, len(seq2)+1):

            *# if both the characters are same then the cost will be same as* 
            *# the cost of the previous sub-sequence*
            if seq1[row-1] == seq2[col-1]:
                cost[row][col] = cost[row-1][col-1]
            else:

                insertion_cost = cost[row][col-1] + ins_cost
                deletion_cost = cost[row-1][col] + del_cost
                substitution_cost = cost[row-1][col-1] + sub_cost

                *# calculate the minimum cost*
                cost[row][col] = min(insertion_cost, deletion_cost, substitution_cost)

                *# get the operation*
                if cost[row][col] == substitution_cost:
                    operations[row][col] = 'S'

                elif cost[row][col] == ins_cost:
                    operations[row][col] = 'I'
                else:
                    operations[row][col] = 'D'

    return cost[len(seq1), len(seq2)], min_cost_path(cost, operations)

对样本序列执行上述功能。

seq1 = "numpy"
seq2 = "numexpr"score, operations = edit_distance_dp("numpy", "numexpr")print(f"Edit Distance between `**{**seq1**}**` & `**{**seq2**}**` is: **{**score**}**")
print("**\n**Operations performed are:**\n**")
for operation **in** operations:
    if operation == '-':
        print('No Change.')
    elif operation == 'I':
        print('Insertion')
    elif operation == 'D':
        print('Deletion')
    else:
        print('Substitution')

输出:

Edit Distance between `numpy` & `numexpr` is: 4.0Operations performed are:No Change.
No Change.
No Change.
Insertion
Deletion
No Change.
Substitution

用编辑距离解决问题。

我们将要使用的数据集包含一些文件,这些文件包含为 Python 语言的两个版本(3.6 和 3.9)安装的包及其版本的列表。

两个档案中关于熊猫套餐的记录是:

  • pandas
  • pandas==1.2.1

在这个练习中,对于一个文件中提到的每个包,我们将从第二个文件中找到最合适的一个。适用性将基于 Levenstein 距离或编辑距离度量。

加载数据

def preprocessor(package):
    *"""*
 *This takes a input package and applies preprocessing steps like converting to lowercase,*
 *strip the `\n` and `space` from the ends.*
 *"""*
    return package.lower().strip()

加载 Python 3.6 的需求

*# Open the file and read the list of packages*
with open('/kaggle/input/pip-requirement-files/Python_ver36.txt', 'r') as f:
    py36 = f.readlines()

*# clean the data*
py36 = list(map(preprocessor, py36))

print("Number of packages for Python 3.6 are: ", len(py36))
print(f"**\n**Few of the records are:**\n{**py36[:5]**}**")

输出:

Number of packages for Python 3.6 are:  276

Few of the records are:
['absl-py==0.11.0', 'alabaster==0.7.12', 'anaconda-client==1.7.2', 'anaconda-project==0.8.3', 'appdirs']

加载 Python 3.9 的需求

with open('/kaggle/input/pip-requirement-files/Python_ver39.txt', 'r') as f:
    py39 = f.readlines()

*# clean the data*
py39 = list(map(preprocessor, py39))

print("Number of packages for Python 3.9 are: ", len(py39))
print(f"**\n**Few of the records are:**\n{**py39[:5]**}**")

输出:

Number of packages for Python 3.9 are:  146

Few of the records are:
['alabaster==0.7.12', 'anyio==2.0.2', 'appdirs==1.4.4', 'argon2-cffi==20.1.0', 'astroid==2.4.2']

获取需求文件之间的成对距离

现在,我们已经构建了一个函数来计算两个序列之间的编辑距离,我们将使用它来计算来自两个不同需求文件的两个包之间的得分。

然后,对于 Python 3.6 版本的需求文件中提到的每个包,我们都会从 Python 3.9 版本文件中找到最匹配的包。

*# to store the best matching package for py36 found in py39*
p36_best_match = {}*# for each package in py36 get the score*
for pack36 **in** py36:

    best_score = float('inf')
    best_package = None

    *# match with each package in py39*
    for pack39 **in** py39:

        *# get the edit distance between pack36 and pack39*
        score, _ = edit_distance_dp(pack36, pack39)

        *# if the score is less than best score so far*
        *# store the new score and package name*
        if score < best_score:
            best_score = score
            best_package = pack39

    *# append the details of best package found for pack36*
    p36_best_match[pack36] = (best_package, best_score)*# print the results*
for pack36, (pack39, score) **in** p36_best_match.items():
    print(f"Best matching package for `**{**pack36**}**` with distance of **{**score**}** is `**{**pack39**}**`")

部分输出记录:

Best matching package for `absl-py==0.11.0` with distance of 9.0 is `py==1.10.0`Best matching package for `alabaster==0.7.12` with distance of 0.0 is `alabaster==0.7.12`Best matching package for `anaconda-client==1.7.2` with distance of 15.0 is `nbclient==0.5.1`Best matching package for `anaconda-project==0.8.3` with distance of 17.0 is `odo==0.5.0`Best matching package for `appdirs` with distance of 7.0 is `appdirs==1.4.4`Best matching package for `argh` with distance of 10.0 is `rsa==4.7`

检查上述解决方案的准确性

为此,我们将简单地从 py36 和 py39 中去掉包名==x.x.x的版本部分,然后检查它们是否相同。

*# this function will trim the versions and return of they are same or not*
def is_same(pack1, pack2):
    return pack1.split('==')[0] == pack2.split('==')[0]print(f"Are packages `pandas` and `pandas==1.1.1` same? **{**is_same('pandas', 'pandas==1.1.1')**}**") **Are packages `pandas` and `pandas==1.1.1` same? True**

获得准确性

*# get total number of packages in py36*
total_packs_in_py36 = len(py36)*# get the count of records where match was found*
total_matched_records = sum([is_same(pack36, pack39) for pack36, (pack39, _) **in** p36_best_match.items()])*# get the accuracy*
accuracy = total_matched_records * 1.0 / total_packs_in_py36print(f"The total number of correct matches are: **{**total_matched_records**}** out of **{**total_packs_in_py36**}** and the accuracy is: **{**accuracy**:**.2f**}**")

输出:

The total number of correct matches are: 138 out of 276 and the accuracy is: 0.50

让我们看看下面的例子,了解为什么我们的准确度如此之低。

距离为 10.0 的 *xlrd* 最佳匹配包是 *rsa==4.7*

*# find the actual corresponding record of 'xlrd' in py39 list*
for pack39 **in** py39:
    if pack39.startswith('xlrd'):
        print(pack39)
        break

输出:

py39 列表中没有匹配的“xlrd”记录,因为 Python 3.9 版本中从未安装过它。

py36 中的记录数是 276 ,而 py39 中只有 146 ,因此我们只能找到 py36 列表中记录的 53% ( 146/276 )的匹配名称。

此外,所使用的数据被上传到 Kaggle 上,可以使用https://www . ka ggle . com/pikkupr/implement-edit-distance-from-sratch访问工作笔记本

希望解释清楚了,你从这个笔记本中学到了什么,如果你有任何问题,请在评论中告诉我。

学习复制论文:初学者指南

原文:https://towardsdatascience.com/learn-to-reproduce-papers-beginners-guide-2b4bff8fcca0?source=collection_archive---------8-----------------------

思想和理论

如何理解深度学习论文并实现所描述的方法的分步指导。举个例子:今天我们要复制一篇关于图像超分辨率的基础论文。

来源:https://arxiv.org/abs/1608.00367

对于数据科学家来说,能够复制最新的科学论文是一项极具竞争力的技能。因为没多少人能做到。

如果你想成为一名思想家,了解黑匣子里正在发生的事情,激发你的创造力,或者成为第一个将最新科学研究引入商业的开发者——这篇文章就是为你准备的。

今天我们将讨论如何选择一篇“好”的论文,这对初学者来说相对容易;我们将概述典型的论文结构和重要信息的位置;我会给你一步一步的指导,告诉你如何实现纸质实现,并分享一些链接,当你遇到困难时,这些链接会对你有所帮助。

这个帖子也有一个“实践部分”,所以今天我们要复制一篇关于图像超分辨率的基础论文。我不指望你有超分辨率的经验,但我假设你已经与卷积神经网络。这次的深度学习框架是 Tensorflow 2。

内容
—从哪里开始?
—论文结构:跳过什么,读什么
—举例。理解论文
—哪里可以找到帮助?
—举例。我们来编码一下
—祝你好运!

从哪里开始?

如果你希望你的学习顺利,没有压力,你应该找到一个“好”的论文。作为一个起点,我真的推荐你选择 一篇老的高被引论文 来描述你所熟悉的概念。

  • 老的高被引论文通常解释非常基本的概念,成为最近研究的基础。你知道基本原理——你也会更好地理解最近的论文。对于深度学习来说,2016 年之前的论文被认为已经很老了。
  • 高被引论文可复制。这意味着许多其他科学家能够理解和实施这种方法。要想知道某篇论文被引用的次数,在谷歌学术谷歌一下。引用次数超过 1000 次的论文被认为是高被引论文。
  • 通常,较老的论文描述的是较简单的概念,这对于初学的你来说是一大加分。

这几周我一直在看关于超分辨率的论文,所以我选择了这个 2016 年的研究来和你一起重现——加速超分辨率卷积神经网络。它描述了用于超分辨率任务的第一个基于 CNN 的模型之一——fsr CNN(快速超分辨率 CNN)。

超分辨率任务非常简单:取一张低分辨率(小,质量差)的图像,然后把它变成高分辨率(大,质量好)。正如我所说的,你不需要任何超分辨率的经验就能理解这篇论文,然而,CNN 是一个你必须熟悉的概念。

超分辨率任务:高级可视化。作者图片

论文结构:跳过什么,阅读什么

典型的深度学习论文具有以下结构:

1.摘要
2。简介
3。相关工作
4。详细介绍
5。实验
6。结论
7。参考

典型深度学习论文的结构。作者图片

1。摘要是“营销”的总结。它很短,重点是为什么这种方法比以前的方法更好,以及它的新颖之处。摘要发表在会议日程和在线档案中(如 Arxiv ),它们唯一的目标就是说服你阅读这篇特定的论文。你已经选择了一篇要阅读(和复制)的论文,所以可以随意跳过摘要。

2。简介是一个重要的章节,也是必读的。它给出了该方法的高级概述。通常情况下,它并不太专业,而且非常“人性化”,所以先阅读介绍部分,在深入研究算法细节之前,先预热一下大脑。

3。相关工作。所有科学论文(以及深度学习)都是相关的:每一项发现都是建立在数十名研究人员之前的工作基础上的。相关工作概述是每篇论文的必修部分。作者必须确保他们的工作是相关的,解决重要的问题,并且不重复其他研究人员以前做过的工作。这对于科学界来说是一个重要的部分——但对于我们(从业者)来说不是,所以跳过它!

(好吧。有时你可能需要它——但只是在你寻找该领域其他基本论文/概念的情况下。)

4。走近细节。有趣的事情开始了。这是论文中最复杂和最具挑战性的部分,也是最重要的部分(一定要读!).不要期望太高,也不要期望从一次阅读中理解所有的东西。这是你在编码时会一次又一次回来的部分。

不要害怕复杂的公式,大多数情况下,它们解释的是基本概念。我相信研究人员就是这样开玩笑的。过一会儿,你会习惯的。

在阅读论文时,捕捉你可能需要的所有信息——数据预处理技术、详细的神经网络架构、损失函数、训练技巧和后处理。尽你所能去得到它。如果你试了几次还是不明白,没关系,以后我会告诉你怎么做。

5。实验。这个部分充满了图表、表格和图像。通常,它包含有关数据集、训练和评估的详细信息,以及对该模型在各种超参数下的表现以及与其他论文中最先进方法的比较的综述。如果论文是关于计算机视觉的,也会有模型预测的可视化。我会说这一部分是你唯一感兴趣的部分。

6。结论是论文的总结,有时包含作者对未来研究的想法。你应该跳过它。

7。参考文献。科学界(不仅仅是科学界)有一条严格的规则:如果研究人员使用了属于他人的观点,他/她需要添加对原始作品的引用(引用)。当这些参考文献中的概念已经在论文中解释过,或者不重要时,你可能会跳过大部分这样的参考文献。然而,有时作者可能会说:“我们使用了论文[2]中描述的模型架构,只修改了最终层中的激活”。在这种情况下,你需要找到并阅读文章[2]来完全理解这种方法。

现在——该读报了。关掉音乐,把手机调到飞行模式,喝杯茶。在接下来的 30 分钟里,你应该高度集中注意力,因为你正在潜入一个新的世界——令人兴奋,但相当具有挑战性。

在这一点上,我建议您暂停阅读论文加速超分辨率卷积神经网络,我们接下来将复制该论文。注意数据预处理、模型架构、损失函数和训练细节。

举例。理解论文

完成了吗?太好了。现在,让我们回顾一下我们从论文中获得的所有重要细节,以再现快速超分辨率 CNN (FSRCNN)。

FSRCNN:一般信息

  • 所提出的方法是一种卷积神经网络,它采用低分辨率(LR)图像,“巧妙地”以某种因子放大它,并返回高分辨率(HR)图像。所以输出图像比输入大 N 倍。
  • 放大因子 N 由用户定义,并且是像 2、3、4 等这样的数字。放大因子越大,恢复质量越差。
  • 特定的放大因子需要单独的神经网络来训练。这些网络仅在最后(去卷积)层不同,并且可以共享所有其他层的权重。

FSRCNN:模型架构

  • 模型由几个连续的卷积层和一个最终的反卷积层组成。下面是一个详细的流程:
    —内核大小= 5×5、滤波器个数= d
    的卷积层—参数化 ReLU 激活
    —内核大小= 1×1、滤波器个数= s 的卷积层
    —参数化 ReLU 激活
    —内核大小= 3×3、滤波器个数= s
    的 m 个卷积层—参数化 ReLU 激活(不清楚这 m 个卷积层之间是否使用了激活函数。可能,他们是。)
    —卷积层,内核大小= 1×1,滤波器数量= d
    —参数 ReLU 激活
    —去卷积层,内核大小= 9×9,步幅=放大因子,滤波器数量=图像中的通道数量(由于某种原因,作者使用 1 作为通道数量,但对于彩色图像,它应该是 3。还是我错过了什么?)
    —最后一层无激活功能
  • 零填充用于所有层。
  • d、s、m 是超参数。作者推荐使用 d=32,s=5,m=1 进行实时预测,使用 d=56,s=12,m=4 获得更好的恢复质量。

FSRCNN 架构。来源: 加速超分辨率卷积神经网络

FSRCNN:数据

  • 模型在 T91 数据集上进行训练,并在 General-100 上进行微调。
  • 这些数据集只有高分辨率图像。低分辨率图像是通过缩小高分辨率图像来创建的。
  • 数据扩充是 90 度旋转和作物。每张图像都以各种可能的方式旋转了 90 度,并通过滑动窗口裁剪成小块。看起来这些扩充是在训练之前完成的(但不是随机进行的),所以最终的训练集是预定义和固定的。

FSRCNN:培训详情

  • 损失是 MSE(均方误差)。
  • 优化器是随机梯度下降。
  • 卷积层训练期间的学习率是 0.001,去卷积层是 0.0001;微调学习率低两倍。
  • 去卷积层的权重通过从具有零均值和标准偏差= 0.001 的高斯分布中随机抽取来初始化。
  • 卷积层的权重用[23]中为 PReLU 设计的方法初始化。这是对另一篇论文的引用,那篇论文解释了正规的初始化式。

我们现在对 FSRCNN 有了相当多的了解,可以转到编码和训练。

去哪里寻求帮助?

对许多人来说,“复制论文”意味着“快速阅读论文,然后在互联网上寻找现成的实现”。这是最简单的方法,但不是有益的方法。我真的建议你从头开始,不要马上寻找现成的解决方案。至少自己做些事情——那是你学习的时候。

即使你完全是复印纸张的初学者,你也总有办法做到:

  • 下载数据集,探索它,编写一个数据加载器。

简单易行的任务,但一旦完成,它会给你信心并帮助你继续前进:

  • 开始写模型架构,简化或者跳过不理解的部分。有一个奇怪的权重初始值设定项——现在跳过它,使用默认的。您以前从未使用过 PReLU 激活,请改用 ReLU。你现在的目标是创建一个可训练的模型,不是纸上谈兵的模型或者性能好的模型,只是可训练的。它有输入,有输出,所以你可以运行培训。
  • 论文中有一个自定义丢失——用深度学习库中实现的类似的替换掉。
  • 对优化器、数据扩充、后处理做同样的事情——简化或跳过。

你最终会被征召入伍。你甚至可以训练一下草稿,看看效果如何——也许结果不会那么糟糕🙂

然后填补空白,修复工作不佳的部分。首先,自己进行实验——测试你在写草稿时想到的想法,再读一遍论文,希望能抓住你之前漏掉的概念。如果你很快就卡住了,不要沮丧。你写了一份草稿,这是一个很大的进步,你已经学到了很多。所以下一次,下一篇论文你会写得更好。这是一个学习的过程。

感觉完全卡住了?搜索的最佳时机。

记住,我建议你选择一篇高被引论文。现在你会感受到好处。流行的报纸在互联网和博客上有许多描述复杂部分的实现。尽情享受吧!

第一个要检查的地方是代码为的论文,这是一个很大的库,可能包含了所有流行论文的代码实现。这些实现要么是官方的,要么来自像你我这样的研究人员。例如,在 PyTorch 和 Tensorflow 中,FSRCNN 在代码为的论文上实现了 7。(好了,现在是 8,我也添加了我的实现。)

你可以复制粘贴,但是要花时间去理解这些代码。这是最后一条建议。

举例。我们来编码吧!

现在我将向您展示如何用代码实现 FSRCNN。深度学习库这次是 Tensorflow 2。

当你在实现论文中的方法时,没有必要 100%准确地复制它。所以关掉完美主义模式,开心就好!使用不同的数据集,试验模型架构,添加数据扩充,改变损失函数,…

数据

  • 让我们使用 DIV2K 来代替 T91 和 General-100 数据集。这是一个更新、更大的数据集,是专门为超分辨率任务创建的。
  • 我们只从 DIV2K 获取高分辨率(HR)图像,包括训练和验证部分,总共 900 张图像。然后将训练和验证部分合并到一个文件夹中,并根据图像 id 创建自定义的训练-验证-测试分割:训练的 id 为 1–700,验证的 id 为 701–800,测试的 id 为 801–900。低分辨率(LR)图像是通过双三次下采样从高分辨率图像生成的。
  • 对于训练和验证数据扩充,让我们使用随机裁剪成 648×648 小块、水平翻转以及亮度、对比度、饱和度和色调的轻微变化。对于测试集,我们只对 648×648 的小块进行随机裁剪。在 HR 图像上执行数据增强,并且从增强的 HR 图像创建 LR 图像。
  • 选择这种随机裁剪大小,以便它甚至可以应用于 DIV2K 数据集中最小的图像。648 可以被 4 整除,这是我们模型中的比例因子。
  • 因此,这里是我们得到的 Tensorflow 数据加载器

数据准备流程。作者图片

型号

  • 我们创建一个上采样因子为 4 的模型,因此输入是大小为 162×162 的 LR 图像(因为 648/4 = 162),输出是大小为 648×648 的 HR 图像。
  • 模型层、过滤器大小和数量、激活、填充和初始化器与论文中描述的相同。
  • PReLU 激活有点棘手,因为它有一个可学习的参数— alpha。当在 Tensorflow 中使用默认参数初始化 PReLU 时,每次激活都有数千个这样的 alphas。然而,根据论文,这个数字应该很小。我在 Tensorflow PReLU 文档中找到一个建议,像这样跨维度共享 alpha】,我也这么做了。它大大减少了激活中的参数数量。
  • 这里是完整的 Tensorflow 模型代码。超参数 d、s、m 是在模型初始化期间指定的。我们使用 d=56、s=12 和 m=4,这应该给出最佳的恢复质量。

训练详情

  • 初始学习率为 0.001。对所有层使用相同的学习速率更简单,并且该模型也训练得相当好。让我们使用 ReduceLROnPlateau 回调来降低每次列车损失停止下降时的学习率。
  • RMSprop 被用来代替 SGD,因为它可以确保更快更流畅的训练。
  • 我用 batch_size=30 和 steps_per_epoch=20 进行训练。使用 batch_size=20,steps_per_epoch=4 进行验证。您可以更改这些数字,但是请注意,batch_size*steps_per_epoch 不能超过数据集大小。
  • 最大历元数为 500。当验证损失停止下降时,我们使用提前停止回调来完成训练。当我训练模型时,它在大约 300 个时期内完成。
  • 我在单个 GPU 上花了大约 5 个小时来训练这个模型。
  • 这里是用于训练的代码和带有训练配置文件。

评估

  • 超分辨率模型用度量— 峰值信噪比 (PSNR)进行评估。这里是它的 Tensorflow 实现。我们的模型 PSNR 在 DIV2K 测试集上是 26.625。
  • 更有意思的是看结果是什么样的。通常,模型恢复质量是根据双三次上采样进行视觉评估的。
  • 虽然用双三次插值上采样的图像看起来有点模糊,但用 FSRCNN 上采样的图像具有更好的纹理。
  • 如果你想看更多的模型预测,这里有一个笔记本供你参考。

FSRCNN 在 DIV2K 测试集上的性能。左—输入图像,右 FSRCNN 的输出。

由 FSRCNN 恢复的图像比向上采样的图像具有更多的纹理。

FRCNN 恢复质量仍然远非完美,即使它是在 2K 分辨率图像上训练的 s。

祝你好运!

再一次:

  1. 选择一篇旧的高被引论文。
  2. 通读一遍,尽量抓住——数据准备、模型架构、损失函数、训练细节。
  3. 什么都不懂也不要难过。
  4. 通过跳过和简化您不理解的概念来创建一个实现草案。如果你的草稿与论文中的方法相差甚远,也没关系。
  5. 试着自己去完善草稿。
  6. 当你遇到困难的时候——在互联网上寻找文章和用纸实现的代码。复制粘贴,但要阅读理解。
  7. 把你的工作包装成 Github 项目(为什么不呢?).看,我是怎么做到的
  8. 用一篇新论文重复。感受一下第二次有多顺利🙂

真正的学习发生在步骤 2-5,所以你在这里花的时间越多,你学得越快。祝你好运!

原载于 2021 年 8 月 10 日https://notrocketseconomy . blog
如果你想阅读更多类似的教程,请订阅我的博客“不是火箭科学”——
电报 推特

用图形卷积神经网络学习嗅觉(分子)

原文:https://towardsdatascience.com/learn-to-smell-molecules-with-graph-convolutional-neural-networks-62fa5a826af5?source=collection_archive---------18-----------------------

结合化学和图形深度学习的端到端项目

拉斐尔·比斯卡尔迪Unsplash 上拍摄的照片

在这里,我们要完成以下任务:

  1. 构建一个定制的图形数据集,其格式适合在 DGL 工作(这是本文的主题😎)
  2. 随机准备训练和测试数据集(了解这一点很好👍)
  3. 定义 Conv 网络图(小菜一碟🍰)
  4. 训练和评估准确性(像往常一样🧠)

1.构建适用于 DGL 的自定义图表数据集格式

我们要处理的数据集来自于AIcrowd Learning to smear Challenge,它由一个列和另一个列组成,其中一个列是识别特定分子的微笑字符串,另一个列是这些分子的气味名称。

https://www.aicrowd.com/challenges/learning-to-smell

例如,下表中的第二个分子,碳酸二甲酯-13C3,其微笑是 COC(=O)OC,其气味被定义为“清新、飘渺、果味”,这当然与人们对这种物质的了解相对应[1]。对于所有这些 4316 个分子,有 100 多种不同的气味形成无序的组合。

然后,我们希望 a)将每个分子的微笑转换成 DGL 图,b)标记它是否有水果味,c)去除任何有问题的分子。以下代码块处理每个请求:

A)必须为每个分子定义 DGL 图形对象。我们可以使用 RDKit 首先从它的微笑中形成一个 mol RDKit 对象(第 2 行)来实现这一点。由于我们想识别节点及其连接,我们可以得到邻接矩阵(第 3 行和第 4 行)。非零值的索引标识连接的节点(第 5 行)并给出双向图的源节点和目的节点(第 6 行和第 7 行)。

我们使用来自 ogb 库【2】的atom_to_feature_vector来生成原子的特征向量

例如,当我们对字符串 COC(=O)CO 应用feat_vec 时,我们得到:

注意,每一行对应于一个具有 9 个特征的原子。这些特征是原子的物理化学性质,例如,原子序数、氢的数目,或者原子是否在环中,等等。

c)现在我们有了带有特征的图表,是时候定义标签了。正如我们所见,每个分子都与一种以上的气味相关联。这里为了简单起见,问题将是一个二元分类来确定分子是否有水果气味。下面的代码块执行该任务,如果有水果香味,则分配标签 a 1 ,如果没有,则分配标签 0

在这个数据集中,我注意到有一小部分分子没有正确地转换成 DGL 图,所以我决定去掉它们。我通过简单地忽略如下所示的异常来做到这一点:

2.随机准备训练和测试数据集

完成所有这些步骤后,数据集就准备好了,但我们将进一步将其转换为 DGL 数据集,以便顺利地进行预处理并形成训练和测试子集。这里我将引用 DGL 团队的“制作自己的数据集”官方教程中的概述[3]:

您的自定义图形数据集应该继承dgl.data.DGLDataset类并实现以下方法:

__getitem__(self, i):检索数据集的第i个例子。一个例子通常包含一个 DGL 图,偶尔还包含它的标签。

__len__(self):数据集中的样本数。

process(self):从磁盘加载并处理原始数据。

过程方法是我们给图形加标签的地方。从一个文件中得到它是可能的,但是在我们的例子中,只有图表列表和标签列表被转换成 torch 张量。因此这是一个非常简单的类:

然后,我们继续构建列车并测试随机抽样。这样做的好处是可以设置批量大小。在这里,我们将其设置为每批五个图形:

3。定义 Conv 网络图

我们正在定义 GCNN 的路上。我已经在之前的一篇文章中解释了 GCN 类是如何构建的。每个节点都有一个输出特征张量,因此为了进行二元分类,我们可以将输出特征的长度设置为类的数量(此处为两个),然后使用dgl.mean_nodes对所有特征节点进行平均,以获得每个图的平均(二维)张量:

4。训练和评估准确性

最后,我们建立模型,每个原子接受 9 个原子特征,并返回一个二维张量,用于定义是否有水果香味。历元在批次上运行,损失用交叉熵计算。最后一部分只是一个循环,对正确的预测进行计数,以评估准确性:

我们得到的精度大约是 0.78,这已经很不错了。现在,你可以尝试预测其他气味,甚至更好地制作你自己的定制数据集,与分子或任何你想要的 DGL 一起工作。

如果你想试代码,打开这个 Colab 笔记本。如果你有任何问题,我将非常乐意回答。最后,考虑订阅邮件列表:

https://jnapoles.medium.com/subscribe

并查看我以前的帖子:

参考资料:

https://doi.org/10.1039/C7GC01764B

https://github.com/snap-stanford/ogb

学习使用数据科学中最重要的七个 python 库

原文:https://towardsdatascience.com/learn-to-use-the-seven-most-crucial-python-libraries-for-data-science-c5bc8dcffdd4?source=collection_archive---------6-----------------------

作为一名数据科学家,这些库将在实现 ML/DL 算法的同时拯救你的生命。

马库斯·斯皮斯克在 Unsplash 上的照片

嗯,说我作为一名数据科学家在工作中不使用图书馆,就像说我拥有一辆自行车,但只能通过步行从一个地方到另一个地方。这在理论上是可能的,但并不是对所有的情况都切实可行或有效。类似于不同的交通方式,我们在 python 中有多个库,这让我们的工作变得更加简单快捷。了解这些库将帮助您在从头实现算法时节省精力、时间和脑力。

目前,当数据科学蓬勃发展时,有多个用于实现一个算法的库,因为所有这些选项而感到不知所措完全没关系。在本文中,我将列出一些基本的库及其用例,帮助您找到适合您的用例的库。

NumPy

好吧,我在这里陈述明显的事实。NumPy 是我们社区中最重要和最常用的库之一。它是处理数组、结构化数据、科学计算、统计分析(如均值、中值、线性代数)等的最佳库。NumPy 库在计算速度上是非常高效的。

你可以在这里了解更多关于 NumPy 的信息

尝试一下这种实践体验:

  1. 生成两个大小为(10,10)的数组,分别命名为 array1 和 array2,并用随机整数填充。
  2. 找出数组 1 中值大于 10 的位置,并将它们设为 0
  3. 找出数组 2 中值小于 5 的位置,并将它们设为 10
  4. 将这两个数组按元素相乘
  5. 将结果数组保存在一个。npy”文件

试着用尽可能少的代码行来实现这些,以体验 NumPy 的效率。

熊猫

Pandas 主要用于读取、分析、操作和保存表格数据。Pandas 本质上提供了两种数据结构。

  • 系列——熊猫系列是一维数据结构,由一个键值对组成。它类似于 python 字典。
  • 数据框-熊猫数据框是一种二维数据结构。它是两个或两个以上熊猫系列的组合。

每当我得到 CSV 文件中的数据时,我想到的第一件事就是用熊猫来分析。这是一个用于数据分析、操作和填充缺失值等的基本库。

你可以在这里了解更多关于熊猫的信息。

尝试一下这种实践体验:

  1. 这里下载 csv,并用于所有实验。
  2. 读取 csv 文件并删除重复的行
  3. 对于具有整数/浮点值的列,获取统计参数,如平均值、中值、方差等。
  4. 将数据帧写入 csv 文件

Matplotlib

Matplotlib 是一个数据可视化的常用库。从为了我们的理解而可视化数据到为演示文稿制作漂亮的可视化效果,matplotlib 全都做了。我想你可以理解 matplotlib 的作用在一个数据科学家的生活中是多么重要。

你可以在这里了解更多关于 matplotlib 的信息。

尝试这些方法来获得实践经验:

  1. 使用两个系列数据绘制标准图表。
  2. 向图表、x 轴和 y 轴添加标题
  3. 为图表添加图例
  4. 保存图表

sci kit-学习

Scikit learn 是一个有价值的库,用于实现各种传统的机器学习算法,包括监督和非监督算法。您可以实现各种算法,如决策树、随机森林、KNN、K-means 等。,可在 Scikit 中获得。该库还提供了各种数据预处理和后处理算法的实现,如标准化、将标签转换为一键编码等。您会发现这个库出现在许多课程和书籍中,因为它的实现范围很广。因此,每当您必须实现任何基本的机器学习算法时,您应该首先尝试看看 scikit learn 是否可以使用。

你可以在这里了解更多关于 Scikit 的知识。

尝试这些方法来获得实践经验:

  1. 这里下载住房数据,并阅读使用熊猫
  2. 使用 pandas 填充缺少的值,使用 matplotlib 可视化数据
  3. 使用 sklearn 的 scaler 模块归一化数据,然后使用 sklearn 拟合线性回归模型。

上面的练习展示了如何使用多个库来解决一个基本的机器学习问题。

OpenCV

如果您正在处理图像或视频,几乎不可能找到可以与 OpenCV 的功能范围相匹配的库。它提供了广泛的传统图像处理算法,如 canny 边缘检测,SIFT,SURF,hough 变换等。它还提供了基于深度学习的算法的实现,用于图像分类、对象检测、分割、图像中的文本检测等。我在图像和视频方面做了很多工作,我可以告诉你,对于任何任务,我都必须至少使用一次 OpenCV。

你可以在这里了解更多关于 OpenCV 的信息。

尝试一下这种实践体验:

  1. 下载任何图像,然后使用 OpenCV 读取图像
  2. 将图像转换为灰度
  3. 使用双边滤波器减少图像中的噪声,然后应用腐蚀和膨胀滤波器。
  4. 使用 canny 边缘检测器在图像中查找边缘
  5. 保存新图像。

NLTK

就像 OpenCV 是图像和视频的基本库一样,NLTK 是文本的必要库。对于所有任务,如词干化、词汇化、生成嵌入、标记化、可视化等。,可以使用 NLTK 库。NLTK 库中也实现了一些必要的深度学习算法。

你可以在这里了解更多关于 NLTK 的信息。

尝试一下这种实践体验:

  1. 使用文集。将整个语料库转换为小写
  2. 对语料库进行分词,然后对给定数据进行词干提取。

PyTorch

虽然我是最后写这篇文章,但我对 PyTorch 的开发者感激不尽。这是我实现任何自定义神经网络或基于深度学习的方法的首选库。无论是音频、文本、图像、文本还是表格数据,都可以使用 PyTorch 编写一个神经网络,在给定的数据上训练一个模型。PyTorch 还在 GPU 上部署基于深度学习的方法方面发挥了重要作用,通过使用并行化减少了推理时间。

你可以在这里了解更多关于 PyTorch 的信息。

尝试一下这种实践体验:

  1. 下载 MNIST 数据集
  2. 为数据和优化器编写数据加载器
  3. 编写自定义的全连接神经网络
  4. 为 MNIST 数据集训练神经网络
  5. 评估验证数据集上的模型
  6. 保存模型。

结论

我已经包含了我在数据科学例程中使用的所有库。并不是只有这些库。这里提到的每个库都有一个可供选择的库。但总的来说,我认为这七个库提供的功能范围是竞争对手中最好的。如果你觉得更多的库需要包含在这个列表中,请在评论中告诉我。

关注我们的 medium 了解更多此类内容。

成为 媒介会员 解锁阅读媒介上的无尽故事。

了解什么是深度图以及如何用 Python 创建深度图

原文:https://towardsdatascience.com/learn-what-a-depth-chart-is-and-how-to-create-it-in-python-323d065e6f86?source=collection_archive---------16-----------------------

奥斯汀·迪斯特尔Unsplash 上拍摄的照片

使用币安的 API 获取订单数据

如果你曾经冒险进入任何一个加密货币交易所,我敢肯定你已经看到了一个深度图,就像上图中的那个。在本文中,我想快速讨论深度图实际上是什么,我们可以从中推断出什么样的信息,然后展示如何使用 Python 创建深度图。

请记住,这是一篇专注于获取订单簿数据和创建适当的可视化的文章。这不是一条投资建议!

深度图——是什么?

深度图是一种可视化,它告诉我们特定资产(股票、商品、密码等)的需求和供给。)价格不同。它基于订单簿数据,即未结买卖订单的数量,包括资产的数量。此类订单的数量越大,该资产的市场流动性就越强。

交易员利用实时供求来评估资产价格的可能走向。此外,它还用于估计在不导致价格上涨的情况下可以购买的资产单位数量。举个例子,一个流动性很强的资产(有大量买家和卖家)的价格在一个大订单完成后不太可能有太大变化。缺乏流动性的资产就不一样了。

Python 中的示例

和往常一样,我们从导入所需的库开始。

为了创建深度图,我们需要访问订单簿数据。我们从币安 ( 免责声明:附属链接)获得数据,这是最受欢迎的加密交易所之一。我们可以通过多种方式访问数据:

  • 通过 Python 的requests库使用币安的 API,
  • 使用非官方的python-binance库,
  • 使用binance-connector图书馆。

我们将采用最后一种选择。我们从实例化币安客户端开始。对于这个特定的端点,我们不需要帐户和 API 密钥。然而,如果你计划更广泛地使用他们的 API,你可能想要设置它。然后,我们使用depth方法为ETHUSDT对下载订单簿数据。

返回的数据存储在一个带有以下关键字的字典中:[‘lastUpdateId’, ‘bids’, ‘asks’]。出价和要价被存储为列表的列表,所以我们需要使用下一个代码片段将它们转换成一个pandas数据帧。

数据帧如下所示:

作者图片

我们也可以使用describe方法来检查数据。

df.groupby("side").price.describe()

作者图片

我们可以看到每边包含 100 个观察值。我们可以要求每边多达 5000 次观察。更多详情,请参见文档

作为探索订单簿数据的第一步,我们可以使用散点图将其可视化。

作者图片

虽然我们已经可以看到更多的数据细节,但很难根据图表做出任何决定。这就是为什么我们需要更多的聚合。作为探索这些数据的第二步,让我们绘制一个直方图。

作者图片

直方图显示了具体价格的出价和要价数量,但是它掩盖了交易量。这意味着价格为 3300 美元、数量为 0.1 个硬币的数据点实际上与价格为 3301 美元、数量为 100 个硬币的数据点价值相同。

该图中所有条形的总和将是 200,因为我们有那么多数据点。

我们可以通过创建一个加权直方图将关于数量的信息合并到分析中,这只需要对代码做一点修改。

作者图片

这个情节已经传达了一个更准确的关于供求的故事。但很难据此做出决定。假设您想要购买 50 个 ETH。使用加权直方图,您无法判断您需要以什么价格出价来确保您的购买订单将被匹配引擎满足。这就是深度图发挥作用的地方。

为了回答上面的问题,我们需要以升序排列的数量和价格信息的累积和。同样,对于与上面相同的问题,但重点是要价,我们需要降序排列的类比信息。

我们可以通过使用经验累积分布函数 ( ECDF )得到上述信息。seaborn附带了一个方便的函数(sns.ecdfplot),我们可以用它来获取图表。为了得到我们确切需要的,我们必须指定一些参数:

  • *weights*=”quantity” —确保 ECDF 按数量加权,就像我们对加权直方图所做的那样,
  • *stat*=”count” —因此我们使用计数,并且该图没有标准化到范围[0,1],
  • *complementary*=True—当我们想要颠倒累计和的顺序时。我们只在出价的情况下使用这个。

作者图片

利用这个图,我们可以回答前面提出的问题。为了相对确定我们 50 ETH 的订单将被完成,我们应该提供大约 3392.5 美元每 ETH。

外卖食品

  • 深度图是一种显示特定资产在不同价格下的需求和供给的可视化形式。
  • 我们可以基于订单簿数据构建深度图表,即特定价格的买卖订单列表。
  • 查看深度图,我们可以估计购买/出售一定数量资产的目标价格,以确保交易所的匹配引擎将履行订单。

您可以在我的 GitHub 上找到本文使用的代码。此外,欢迎任何建设性的反馈。你可以在推特上或者评论里联系我。

喜欢这篇文章吗?成为一个媒介成员,通过无限制的阅读继续学习。如果你使用这个链接成为会员,你将支持我,不需要你额外付费。提前感谢,再见!

您可能还会对以下内容感兴趣:

[## 用 Python 创建交互式烛台图表的最简单方法

towardsdatascience.com](/the-simplest-way-to-create-an-interactive-candlestick-chart-in-python-ee9c1cde50d8)

参考

跟我学:图像字幕

原文:https://towardsdatascience.com/learn-with-me-image-captioning-48f22c168912?source=collection_archive---------32-----------------------

让我们一起学习并创建一个神经网络模型,它以一幅图像作为输入,并返回一个描述性文本作为输出。

k .米奇·霍奇在 Unsplash 上拍摄的照片

介绍

不久前,我开始尝试“图像字幕”的问题。这里,目的是为给定的图像生成文本描述。类似于一个人如何向他的同伴描述一幅画。正如在实验中经常发生的那样,你不会直接得到最佳解决方案——你会尝试、犯错、改进自己,然后最终得到一个不错的解决方案。这正是我对这个项目的探索。在本文中,我想介绍我是如何开始解决这个问题的,偶然发现一个不太好的解决方案,但最终达到了“足够好”的状态。所以,让我们开始吧!

问题定义

如前所述,任务是为图像生成自然语言描述或标题。这个问题非常有趣,因为它是两个领域的结合——计算机视觉(CV)和自然语言处理(NLP)。因此,要想出一个手写的高级解决方案,我们需要这样做——将图像作为输入,用 CV 做一些魔术,用一个做一些 NLP 魔术的块修补它,并期望文本描述作为输出。听起来很简单,对吗?让我们试试这个。😃

资料组

在深入研究技术细节之前,让我们花一些时间来理解我们的数据集——“Flickr 8k”。它由 8091 个图像(大小不同)组成,每个图像有 5 个不同的标题,因此标题总数为 8091*5=40455。我们有一个图像文件夹(包含所有的图像),和一个标题文本文件(CSV 格式),将每张图像映射到它的 5 个标题。首先,让我们看看字幕文件是什么样子的,

标题 CSV(按作者)

让我们也来看一些图片和它们各自的标题,

带标题的示例图像(由作者提供)

带标题的示例图像(由作者提供)

模型架构——第一次尝试

拐弯抹角说够了,让我们来形式化我们将用来解决这个问题的神经网络模型的架构。正如我们已经讨论过的,整个流程看起来会像这样,

我们将在本文中创建的解决方案的高级流程(按作者)

现在选择第一部分,也就是说,首先,我们要用计算机视觉来处理图像。这种“处理”通俗的解释就是把一个图像作为输入,转换成矢量表示。在这样做的同时,希望网络将学习到字幕所需的重要信息,而忘记不相关的信息。所以我们希望图像作为输入,向量作为输出。在 CV 中最常见的方法是使用卷积神经网络。详细讨论 CNN 超出了本文的范围,但是为了简单的细节,我将建议这个。首先,为了测试 waters,我们可以创建简单的 CNN 图层。代码如下所示,

CNN 部分的代码(按作者)

理解代码,

  • 第 6 行:初始化顺序 Keras 模型
  • 第 9–21 行:你可以看到一对多次使用的Conv2DMaxPooling2D层。这是定义 CNN 模型最常见的方式之一。
  • 第 23 行:我们展平最后一层,创建一个矢量作为图像表示。
  • 第 24 行:这是最终的 CNN 图层,我们已经将图像表示缩减为 256D 大小的矢量。

接下来,我们希望将这个向量表示输入到 NLP 模块中,该模块将生成输出文本描述。为此,我们可以使用 LSTM,这是一个递归层类型的神经网络。它可以很好地处理任何序列数据,其中它处理序列的每个元素并生成各自的向量表示。更多细节,我会建议这篇这篇文章。所以如果你看到,我们的描述,也就是文本,遵循连续的顺序,因此非常适合递归型 NN。所以我们需要文本作为输出,因此 LSTM 将图像向量作为输入,并给出向量表示,我们将使用 softmax 函数将其转换为单词。这将使字幕写作模型成为一个分类模型,在每一步中,我们将预测每个单词的概率,并选择具有最高值的一个。这将在所有步骤中重复(LSTM 模型的大小,通常是固定文本描述的大小)。NLP 解码器模块可以被编码为,

NLP 部分的代码(按作者)

理解代码,

  • 第 2 行:由于 LSTM 层需要输入到它的所有步骤,我们将重复图像向量并将其传递到 LSTM 的所有步骤作为输入。这里的步长是config['max_len'] (=39)。
  • 第三行:LSTM 层。return_sequence为真,因为我们希望返回所有步骤的输出。
  • 第 4–5 行:对于每一步,我们将把向量表示传递给一个密集层,该层充当分类器部分,并挑选一个config['max_vocab'] (=10k)单词。在所有的步骤中这样做,我们将得到我们的标题!

如果你对max_vocabmax_len感到困惑,不要担心,在下一节中它会变得清晰。

数据准备和数据生成器

现在我们已经修复了我们的架构,让我们看看如何处理数据加载并使用它来训练模型。首先要做的是转换文本数据。代码如下所示,

清理、标记和填充标题文本(按作者)

理解代码,

  • 第 6 行:为我们的每个标题添加前缀<开始>和后缀<结束>。这将使我们的递归模块更容易了解标题的边界。
  • 第 8–12 行:我们在这里做了很多事情。总的来说,我们希望将文本从单词序列转换为数字序列,因为数字是神经网络所能理解的。在此之前,我们还(1)删除非字母字符,(2)仅考虑config['max_vocab'] (=10k)唯一的单词,以及(3)将任何其他单词表示为 0。
  • 第 14–15 行:我们想让每个序列(标题用数字符号表示)长度相同,为此我们填充较小的序列来匹配最大的序列config['max_len'] (=39)。这会用 0 填充较小序列的右侧。

预处理完成后,我们就可以创建数据生成器了,它将加载数据并将其传递给模型进行训练。

数据生成器(按作者)

理解代码,

  • 第 1 行:我们的函数接受以下输入,(1) pick_from_caption_indices:我们可以从中随机采样的标题的索引,(2) batch_size:一次返回的(图像,标题)对的数量,以及(3) reproduce:设置随机种子的标志,以便我们返回相同顺序的(图像,标题)对。
  • 第 2 行:因为这是一个数据生成器,所以函数会不断迭代。因此这里出现了无限循环。另外,请注意第 25 行的yield使这成为可能。
  • 第 8–10 行:从字幕 CSV 中随机抽取字幕及其相应图像的路径。
  • 第 12 行:我们重复下面的过程,直到(图像,标题)对等于batch_size (=32)。
  • 第 14–16 行:从驱动器加载图像,并将其调整为(229,229,3)形状。这将确保每个图像的大小相同。此外,我们通过保留所有 3 个通道来保留颜色信息。接下来,我们还将图像像素值归一化到 0 和 1 之间。
  • 第 18–19 行:将序列数据(来自预处理)转换为一键编码,以便进行分类。它接受一个长度为 39 的数字序列,并返回一个大小为(39,10000)的矩阵。这是因为我们的最大词汇大小是 10k,所以对于序列的每一步,我们创建一个 10k 大小的向量,除了该步的数字之外,其他地方都是 0。
  • 第 28–29 行:创建两个数据生成器,一个用于训练,另一个用于测试。注:对于测试,我们有reproduce=True,因为无论是模型还是试验,我们都希望测试相同的数据。此外,train_indicestest_indices可以通过从标题 CSV 中抽取 80%的索引来轻松创建(更多细节见代码

培训和结果— v1

现在我们已经准备好了模型和数据生成器,让我们来训练模型。在这里,我们所要做的就是定义一些回调函数并编写训练程序。代码如下所示,

培训脚本(作者)

理解代码,

  • 第 2–4 行:检查点回调,保存过去 10 个时期的最佳模型。
  • 第 5 行:提前停止回调,如果我们在 10 个时期内没有看到任何显著的进步,则停止训练。
  • 第 8 行:通过定义优化器和损失函数来编译模型。
  • 第 11–16 行:使用fit功能训练模型。它接受以下输入,(1)训练数据生成器,(2)要训练的最大时期(这里是 100),(3)每个时期的步骤(这里是 1000),(4)进度详细级别,以及(5)定义的回调。

训练会花一些时间,但是对于支持 GPU 的系统来说,会快很多。对我来说,训练过程在 25 个纪元后停止,损失约为 1.65。这个完整的过程大约需要 2 小时 30 分钟。

v2(按作者)的历元(x 轴)上的训练损失(y 轴)

现在我的期望很低,但我仍然很好奇,想看看结果。退一步说,结果并不太好😅。

v1 的样本测试图像结果(由作者提供)

似乎我们的模型学习的只是一个单一的模式,所有的图像都预测到了同样的模式。这很糟糕,但是你注意到描述总是以一个标记开始吗!至少模型那东西没错。😃

丰富

现在的问题是——为了改善结果,我们接下来应该修改什么,CV 部分还是 NLP 部分?经过一番阅读,我得出了这个结论——为什么不两者都要呢?这是我接下来做的,

  • 计算机视觉使用已经在大型图像数据集上训练过的预训练模型。这种将在一项任务中训练的模型用于另一项任务的过程被称为“迁移学习”。这里的主要思想是,预先训练的模型为新任务提供了推动力,因为它已经学会了从图像中提取重要的特征。把这想象成创建一个网络,而不是用随机数初始化权重,我们使用以前工作过的预训练权重。Keras 包在其应用部分提供了几个这样的预训练模型。我们使用“exception”预训练模型,它很小,但具有相当好的准确性。

来自 Keras 应用网站的前 5 个预培训应用。(作者)

  • 自然语言处理使用双向 LSTM 被证明可以改善序列数据编码。双向 LSTM(或 biLSTM)基本上是一个堆叠在另一个之上的 LSTM,但有一个扭曲。一个 LSTM 从左到右处理序列,而另一个以相反的方向处理。因此,我们得到了一个方向不可知的嵌入。我会建议这篇文章(自私的自我推销😃),它比较了一个简单分类任务的不同重现图层。

在 Keras 中执行这些修改非常容易,新的模型定义脚本如下所示(适用于 CV 和 NLP)

修改后的型号代码(作者)

理解代码,

  • 第 8–16 行:我们加载异常应用程序,并将其附加到模型上。我也使这一层不可训练。最后,我添加了一个 256D 的密集层,以获得最终的翻译图像。
  • 第 19–21 行:一切都和以前一样,除了第 20 行,我在那里添加了双向 LSTM。

培训和结果— v2

训练代码和以前一样。这次模型训练了超过 75 个纪元,用了~7 个小时!损失值也突破了 1 大关。

v2(按作者)的历元(x 轴)上的训练损失(y 轴)

这一次我真的支持这个模型,让我们看看同样的测试图片的标题是什么样子的。

v2 的样本测试图像结果(由作者提供)

这个比上一个好多了!想想我们的模型只有 15 行代码!我认为我们可以在这里停止,至少现在。

下一步是什么?

即使结果很好,也不是完美的。如果你仔细观察,标题不是以符号结束的。此外,虽然字幕的开头很好,但在字幕的过程中,它变得有点没有意义。因此,有很大的改进空间。我有以下想法,我想接下来尝试一下,

  • CV: (1)从 Keras 应用列表中尝试更好的预训练模型。(2)使预训练的模型可训练(将增加参数和时间,但是也应该增加精度),(3)在应用层之后添加更多可训练的 FC 层,等等。
  • NLP: (1)使用多个 biLSTM 栈,(2)使用 attention 或 transformers 或 BERT

结论

学习是一个持续的过程,只有当你真的生病了,或者像我一样,周末即将结束时,你才应该停下来😅。这篇文章背后的想法不是展示最好的图像字幕解决方案,而是通过人工智能/人工智能解决问题的过程。目的是向读者介绍实验的想法,并推动他们不只是复制解决方案,而是尝试创造自己的解决方案。对我来说也是如此,因为我认为试图在一个系统的流程中处理问题确实有助于人们将问题内在化。

无论如何,我选择了这个问题,因为它是两个不同领域的结合——CV 和 NLP。因此,它有可能帮助我同时应用这两个领域的知识。这就像是一石二鸟。希望这有所帮助!

本文中使用的代码可从这里获得。随意发挥,随意修改。

你可以在 LinkedIn 上和我联系。

干杯。

学你一个凯卓*

原文:https://towardsdatascience.com/learn-you-some-kedro-be67d4fc0ce7?source=collection_archive---------6-----------------------

编写可复制、可维护和模块化的数据科学代码

* 致敬,学你一个哈斯克尔好了!

拿杯咖啡坐下。这是一个很长的帖子!

https://flic.kr/p/d9KiHk,段丽阳·本田在 Flickr 上的拿铁艺术(CC BY-SA 2.0)

在本文中,我将介绍 Kedro,这是一个开源的 Python 框架,用于创建可复制、可维护和模块化的数据科学代码。在简要描述了它是什么以及为什么它可能成为每个数据科学家工具链的标准部分之后,我描述了一些技术性的 Kedro 概念,并通过一个教程说明了如何使用它们。

总的来说,你应该能够在 30 分钟内阅读并消化这篇文章。但是使用 Kedro 的好处将会持续你的职业生涯。

假设你是一名数据科学家,为一名为公司做出关键财务决策的高管工作。她请你提供一个特别的分析,当你这样做时,她感谢你为她的计划提供了有用的见解。太好了!

三个月后,新晋升的主管,现在是你的首席执行官,要求你在下一次计划会议上重新运行分析…而你不能。代码被破坏是因为您覆盖了文件的一些关键部分,并且您不记得当时使用的确切环境。或者,代码可能是好的,但它在一个大的 Jupyter 笔记本中,所有文件路径都是硬编码的,这意味着您必须费力地检查和更改每一个新数据输入。哎呀!那不太好!

它发生了。可能比应该的更频繁。当它发生时,通常的说法是最初的项目没有被规划到一个高标准,因为它不是为生产系统设计的。

但是……任何支持业务决策过程的代码都应该被认为是生产代码!

当然,如果你是一名数据科学家,你可能不认为你工作的主要产出是代码。但是你的项目仍然使用代码,为什么不利用软件工程师来之不易的经验呢?希望您的项目至少具备以下特征:

  • 它应该被版本化——使用 git 或类似的工具定期保存您的更改,无论您是独自工作还是在团队中工作。
  • 它应该是可复制的——你应该能够将一个项目转移到另一台计算机上,然后毫不费力地运行它。
  • 它应该遵循标准——坚持通用的项目结构、标准的编码约定和工具,以便未来的协作和更好的团队合作。
  • 它应该被记录 —使用自动化文档来保持你的文档与你的代码保持同步。
  • 它应该是模块化的——代码可以很容易地执行和测试。

关于这些原则的更多细节,请看 Thomas Huijskens 的一篇有用的博客文章。

介绍 Kedro

Kedro 帮助您创建可复制、可维护和模块化的数据科学代码。它从软件工程中借用概念,并将它们应用到机器学习代码中;应用的概念包括模块化、关注点分离和版本控制。

Kedro 概念

首先,让我们用一个传统的“Hello World”例子来研究 Kedro 的最基本的元素,这个例子被分成几个部分。你可以在 Kedro 词汇表中找到更多关于这些概念的信息。

节点

节点是 Python 函数的包装器,用于命名该函数的输入和输出。节点是管道的构建块,您可以链接它们,这样一个节点的输出就是另一个节点的输入。

这里,一个名为return_greeting_node的节点没有输入,只有一个输出(my_salutation)。它封装了函数(return_greeting):

*# Prepare first node
def return_greeting():
    return “Hello”return_greeting_node = node(func=return_greeting, inputs=None, outputs=”my_salutation”)*

这里,名为join_statements_node的第二个节点命名为单输入(my_salutation)和单输出(my_message)。它封装了函数(join_statements):

*# Prepare second node
def join_statements(greeting):
    return f”{greeting} Kedro!”join_statements_node = node(join_statements, inputs=”my_salutation”, outputs=”my_message”)*

注意my_salutationreturn_greeting_node输出 ,也是join_statements_node输入

管道

Kedro 管道组织了一组节点的依赖关系和执行顺序。在这个例子中,流水线在执行join_statements_node之前执行return_greeting_node:

*# Assemble nodes into a pipeline
pipeline = Pipeline([return_greeting_node, join_statements_node])*

数据目录

Kedro DataCatalog是项目可以使用的所有数据源的注册表。它将节点输入和输出的名称映射为一个DataSet中的键,这是一个 Kedro 类,可以专门用于不同类型的数据存储。Kedro 为简单存储在内存中的数据使用了一个MemoryDataSet,它还为不同的文件类型和文件系统提供了不同的内置数据集,因此您不必编写读/写数据的逻辑:

*# Prepare a data catalog
data_catalog = DataCatalog({“my_salutation”: MemoryDataSet()})*

转轮

Runner 是运行管道的对象。Kedro 解析执行节点的顺序:

  1. Kedro 首先执行return_greeting_node。这将运行return_greeting,它不接受任何输入,但输出字符串“Hello”。
  2. Kedro 将输出字符串存储在名为my_salutationMemoryDataSet中。
  3. Kedro 然后执行第二个节点join_statements_node。这会加载my_salutation数据集并将其注入到join_statements函数中。
  4. 该函数用“Kedro!”加入输入的问候语以形成输出字符串“Hello Kedro!”
  5. Kedro 在字典中返回管道的输出,关键字为my_message

你好,凯卓!

现在是时候把所有东西缝合在一起了。以下是完整的示例:

如果您将这个示例放入一个文件,例如hello_kedro.py,并在终端(python hello_kedro.py)中运行它,您应该看到{‘my_message’: ‘Hello Kedro!’}被打印到控制台。

开始吧!

现在你对这些概念有了一个基本的理解,为什么不安装 Kedro 并试用一下呢?大多数人从 Kedro spaceflights 教程开始,你可以在文档中找到,但为了简化它,我在下面创建了一个简短的版本。

参考 Kedro 文档中的安装先决条件。准备好之后,运行以下命令从 Python 包索引(PyPI)安装:pip install kedro

检查是否安装了 Kedro:kedro info

您应该会看到一个 ASCII 艺术图形和 Kedro 版本号。

如果您没有看到显示的图形,或者您的安装有任何问题,请参见常见问题或 Kedro 社区对 Discord 的支持。更多信息,请查看关于安装 Kedro 的文档。

Kedro spaceflights 教程

在本教程中,您将通过一个示例了解 Kedro 项目开发工作流的每个步骤,该示例为以下价格预测场景构建节点和管道:

现在是 2160 年,太空旅游业正在蓬勃发展。在全球范围内,有数千家航天飞机公司将游客送上月球并返回。你已经能够找到每架航天飞机提供的便利设施、顾客评论和公司信息。

您想要构建一个模型来预测每次登月旅行以及相应的返程航班的价格。

Y 您将需要大约 20 分钟来完成本教程,它使用 Kedro starter 为您创建 spaceflights 项目,然后遍历最重要的代码部分,将它们与您在上面学到的概念联系起来。

设置项目

我们假设您已经安装了 Kedro,如上所述。首先,使用Kedro starter for the space flights 教程 : kedro new --starter=spaceflights在您喜欢的工作目录中创建您的项目

当您使用它时,您将拥有一个完整的工作项目,所有的代码和数据都已设置好并准备好运行。

你可以随意命名你的项目,但是这里我们假设它叫做 Kedro 教程

出现提示时,保留 repo_name ( kedro-tutorial)和 python_package ( kedro_tutorial)的默认名称。

接下来,使用 Kedro 安装特定于项目的依赖项。导航到项目的根目录并运行:kedro install

Kedro 管理您的项目的依赖项,使其他人更容易运行该项目。它避免了版本冲突:Kedro 确保你们都使用相同的 Python 包和版本。你可以在 Kedro 文档中找到更多关于如何处理项目依赖关系的信息。

此时,您可以运行项目,看看会发生什么。因此,如果您想向前跳,请向下滚动到“测试管道”部分。

设置数据

spaceflights 教程使用了公司的虚拟数据集,将客户往返于月球。您将使用这些数据训练一个模型来预测班车租赁的价格。但是,在开始训练模型之前,您需要为模型构建准备数据。

航天教程有三个文件,使用两种数据格式:.csv.xlsx。你会在你的项目目录的data/01_raw/文件夹中找到原始数据:

  • [reviews.csv](https://quantumblacklabs.github.io/kedro/reviews.csv)
  • [companies.csv](https://quantumblacklabs.github.io/kedro/companies.csv)
  • [shuttles.xlsx](https://quantumblacklabs.github.io/kedro/shuttles.xlsx)

数据集需要注册,以便 Kedro 可以加载它们。所有 Kedro 项目都有一个conf/base/catalog.yml文件,在示例中,您将看到 starter 在该文件中添加的每个数据集:

  • 文件位置(路径)
  • 给定数据集的参数
  • 数据类型
  • 版本控制

对于csv数据集:

*companies:
type: pandas.CSVDataSet
filepath: data/01_raw/companies.csvreviews:
type: pandas.CSVDataSet
filepath: data/01_raw/reviews.csv*

对于 xlsx 数据集:

*shuttles:
type: pandas.ExcelDataSet
filepath: data/01_raw/shuttles.xlsx*

要确认 Kedro 可以正确加载数据,请打开一个 Kedro iPython 会话(kedro ipython)并运行以下命令:

*companies = catalog.load(“companies”)
companies.head()
shuttles = catalog.load(“shuttles”)
shuttles.head()*

该命令加载每个数据集。pandas 的 head 方法显示数据帧的前五行。

完成后,关闭 iPython 会话:exit()

接下来,我们将为项目设置两条模块化管道:

  • data_processing_pipeline预处理数据
  • data_science_pipeline创建特征,训练和评估模型。

数据处理模块流水线

让我们看一下用于预处理三个输入数据集以创建主表并为建模准备数据的示例节点。

src/kedro_tutorial/pipelines/data_processing/nodes.py中,您将看到两个函数:(preprocess_companiespreprocess_shuttles),每个函数输入一个原始数据帧并输出一个包含预处理数据的数据帧:

您将在src/kedro_tutorial/pipelines/data_processing/pipeline.py内的create_pipeline()中找到两种功能的节点,以及用于数据处理的模块化管道:

注:公司和班车指的是conf/base/catalog.yml中定义的数据集。这些是preprocess_companiespreprocess_shuttles功能的输入。Kedro 管道使用命名的节点输入(和输出)来确定节点之间的相互依赖关系,从而确定它们的执行顺序。

每个节点输出一个新的数据集(preprocessed_companiespreprocessed_shuttles)。Kedro 的DataCatalog将自动保存数据集(在本例中为csv数据)。

在上面的管道中,您将看到另一个节点create_master_table(),它在src/kedro_tutorial/pipelines/data_processing/nodes.py中将三个数据帧连接成一个主表:

Kedro 使用从数据集preprocessed_shuttlespreprocessed_companiesreviews加载的数据调用create_master_table(),并将输出保存到dataset master_table

面向数据科学的模块化管道

现在让我们看看用于价格预测的数据科学管道,它使用来自 scikit-learn 库的 LinearRegression 实现。

您将在src/kedro_tutorial/pipelines/data_science/nodes.py中看到三个数据科学功能:

输入参数在配置文件conf/base/parameters.yml中:

*test_size: 0.2
random_state: 3
features:
- engines
- passenger_capacity
- crew
- d_check_complete
- moon_clearance_complete
- iata_approved
- company_rating
- review_scores_rating*

这些是管道执行时输入到DataCatalog的参数。参数test_sizerandom_state被用作训练测试分割的一部分,而 features 给出了主表中用作特性的列的名称。

训练好的模型被保存为数据集(见conf/base/catalog.yml):

*regressor:
type: pickle.PickleDataSet
filepath: data/06_models/regressor.pickle
versioned: true*

数据科学的模块化管道在src/kedro_tutorial/pipelines/data_science/pipeline.py中创建:

合并管道

数据处理和数据科学管道被添加到register_pipelines within src/kedro_tutorial/pipeline_registry的项目中:

“__default__”: data_processing_pipeline + data_science_pipeline中使用的__default__ key将两个模块化管道合并成一个项目默认管道。

**注意:将管道添加在一起的顺序并不重要,并且data_science_pipeline + data_processing_pipeline将产生相同的管道,因为 Kedro 自动检测结果管道中所有节点的正确执行顺序。

测试管道

运行管道:kedro run

您应该会看到类似下面的输出(可能会有一些警告):

总结

在本教程中,我们展示了一个标准的 Kedro 开发工作流程:

1。 项目模板

我们用 kedro new 创建了一个新项目,用kedro install安装了项目依赖项(完整教程也谈到了配置)

2。 数据

我们将数据添加到data/文件夹,并在conf/base/catalog.yml中引用项目的输入数据集

3。 管道

我们将数据转换步骤创建为 Python 函数(节点),构建模块化管道并将它们合并到一个项目管道中。为了简洁起见,我们没有介绍如何可视化你的管道

哇,那是一些长的教程!

抱歉,是的,就是它!在 Kedro 文档中有更多的细节,如果你想更深入地了解正在发生的事情,或者如果你在运行这个例子时有任何问题,你会发现它很有用:

承认

Spaceflights 的例子是基于 2019 年 QuantumBlack Labs 的 Kedro 团队编写的教程。没有他们我什么都做不了。非常感谢 QB 实验室的 Yetunde DadaIvan DanovDmitrii DeriabinLorena BalanKiyohito KuniiMerel Theisen 以及其他加入团队的人。

边做边学—成为高效的数据科学家

原文:https://towardsdatascience.com/learning-by-doing-become-an-effective-data-scientist-1a7f4c3254c?source=collection_archive---------32-----------------------

我听见了,我忘记了。我看见了,我记得。我知道,我也理解。

图片来自 Pixabaygya Min

课程是学习的好方法,但是参与项目可以提高你的技能。你将被迫对这个问题进行批判性的思考,并自己提出解决方案。实践积累了无法教授的知识和技能,因为看着别人做比自己学着做要容易得多。

我喜欢保罗·格拉厄姆在的文章中的描述:

想到所有的高中生都放弃建造树屋,坐在课堂上尽职尽责地学习达尔文或牛顿以通过考试,这有点令人难过,而让达尔文和牛顿出名的工作实际上在精神上更接近于建造树屋,而不是为考试而学习。

个人项目允许你在更深的层次上探索和应用你所学到的东西。从头到尾做一个项目会让你面临各种各样的问题。你将知道如何提出正确的问题,特别是如何搜索正确的问题来找到解决方案。我们想获得更多的实践经验来磨练我们的技能。

高效数据科学家

边做边学通过端到端的方式让您成为一名高效的数据科学家,知道如何从项目的开始(识别问题)到结束(解决问题并提供价值)进行工作。他们能用数据识别和解决问题,为公司提供价值;这提高了你产生有意义影响的能力。

以下是成为有效的端到端数据科学家的技能列表(既不是强制性的,也不是详尽的):

  • 范围 —定义问题,确定成功标准
  • 沟通 —促进团队合作,获得认同,分享成果
  • 数据工程 —获取、清理和准备数据,建立数据管道
  • 数据分析 —理解数据,衡量绩效
  • 构建产品 —无论是应用机器学习来执行预测还是数据分析来提取答案
  • 开发运营 —代码结构、单元测试、自动化工具、部署

例如,让我们构建一个项目,它提取历史股票数据,并使用机器学习模型来预测第二天的价格(范围)。我们发现我们可以从 Alpha Vantage 获取金融市场数据,因此我们构建了一个脚本来提取股票数据(数据工程)。有了原始数据,我们在训练模型之前准备数据,归一化原始数据,并将数据拆分成训练和验证数据集(数据分析+数据工程)。然后,我们开发并训练一个简单的 LSTM 模型,学习使用过去 50 天的数据预测第二天的价格(构建产品)。为了确定我们的模型是否做得很好,我们通过用均方差(数据分析)测量来评估模型的性能。我们建立一个网络界面,然后部署它来展示这项工作,这样任何人都可以尝试(开发-运营)。最后,写下关于建筑和思想的过程,这样其他人可以从中学习来建造他们自己的(沟通)。

建立你的投资组合

拥有个人项目还能让你建立一个投资组合,并向潜在雇主展示。在线作品集向招聘经理展示了技术和软技能。

技术技能——你如何组织你的文件和代码,你如何获取和准备数据,你如何通过视觉分析和理解你的数据,你如何训练和评估你的机器学习模型。这向他们表明你能把事情做好。

软技能 —写下你的思维过程,解释分析和结果,显示你的沟通能力,这对于一个高效的数据科学家来说是必不可少的。

特质——从事个人项目表现出除了完成课程和领取证书之外的自学能力。拥有投资组合也展示了好奇心和激情等特质。当你利用空闲时间学习时,这表明你比其他可能参加同一份工作面试的人更有动力和激情。你要表明你是自愿做这件事的(),而不是仅仅因为有人告诉你这样做(被推)。

作品集有助于你的简历在简历的海洋中脱颖而出,获得第一轮面试。你从这些项目中获得的技能和特质将引导你胜任这个角色。

它对我有什么作用?

2017 年,我在阿里巴巴集团面试了一个数据科学家的角色。像大多数面试一样,我的招聘经理开始问了我几个机器学习问题。气氛很严肃,问题一个接一个。

然后,我们继续描述我以前做过什么。我分享了一个我制作的自然语言处理应用程序,用户可以上传一个包含调查问题答案的 Excel 文件。该应用程序将提取每个响应的情绪,并根据主题对它们进行动态分组。我向我的招聘经理展示了该应用程序的外观,以及从用户角度看它是如何工作的。

在分享了它的易用性以及它如何让用户受益之后,他的态度和采访氛围都变了。这不再像是一次采访,而更像是与朋友分享我做了什么,我是如何做的,以及它如何极大地帮助了用户。描述以前做过的事情比重述每个数据科学和机器学习概念要容易得多。谈话变得更加活跃和友好;这是一次愉快的面试经历。是的,我得到了这份工作。

在收盘时……

当决定做一个个人项目时,最困难的事情之一就是找时间开始。因为我们大多数人都有一份全职工作(或学习),剩下的空闲时间都可以用来看《网飞》。但是你从个人项目中获得的学习和成长是金子。

不要专注于建立投资组合;关注通过实践获得技能的过程。投资组合是我们学习的成果,是我们发展的技能,是我们拥有的特质。在试图建立我们的投资组合时,我们应该找到本质上有回报的项目。它们应该是有趣的,有个人意义的,并能拓展我们的能力;这使得它们更具可持续性。随着时间的推移,一个接一个的项目,你会有一个投资组合。

我听见了,我忘记了。我看见了,我记得。我知道,我也理解。

读也:

https://eugeneyan.com/writing/data-science-portfolio-how-why-what/

通过实现来理解:高斯朴素贝叶斯

原文:https://towardsdatascience.com/learning-by-implementing-gaussian-naive-bayes-3f0e3d2c01b2?source=collection_archive---------8-----------------------

建立你自己的模型

了解高斯朴素贝叶斯的工作原理,并在 Python 中实现它

高斯朴素贝叶斯分类器的决策区域。图片由作者提供。

我认为这是每个数据科学职业生涯开始时的经典之作:朴素贝叶斯分类器。或者我应该说是朴素贝叶斯分类器的家族,因为它们有很多种风格。例如,有一个多项式朴素贝叶斯,一个伯努利朴素贝叶斯,还有一个高斯朴素贝叶斯分类器,每个分类器只有一个小细节不同,我们会发现。朴素贝叶斯算法在设计上非常简单,但在许多复杂的现实情况中证明是有用的。

在本文中,您可以了解到

  • 朴素贝叶斯分类器如何工作,
  • 为什么以他们的方式定义他们是有意义的
  • 如何使用 NumPy 在 Python 中实现它们。

你可以在 my Github 上找到代码。

检查一下我的贝叶斯统计初级读本可能会有所帮助,这是对贝叶斯推理的温和介绍以习惯贝叶斯公式。因为我们将以 scikit learn-conform 的方式实现分类器,所以也值得看看我的文章构建您自己的定制 scikit-learn 回归。然而,scikit-learn 的开销很小,无论如何您都应该能够跟上。

我们将开始探索朴素贝叶斯分类的惊人简单的理论,然后转向实现。

该理论

分类时我们真正感兴趣的是什么?我们实际上在做什么,输入和输出是什么?答案很简单:

给定一个数据点 x,x 属于某类 c 的概率是多少?

这就是我们想要用任何分类来回答的所有问题。你可以直接把这个语句建模成条件概率:p(c|x)。

例如,如果有

  • 3 班 c ₁、 c ₂、 c ₃,以及
  • x 由两个特征组成 x ₁, x ₂,

分类器的结果可能类似于 p ( c ₁| x ₁, x ₂)=0.3,
p(c₂|x₁, x ₂)=0.5 和p(c₃|x₁,x如果我们关心单个标签作为输出,我们将选择概率最高的一个,即 c ₂,这里概率为 50%。**

朴素贝叶斯分类器试图直接计算这些概率。

朴素贝叶斯

好,那么给定一个数据点 x ,我们要计算所有类 cp(c|x),然后输出概率最高的 c 。在公式中,您通常会看到这种情况

图片由作者提供。

注:maxp(c|x)返回最大概率,arg maxp(c|x)返回概率最大的 c

但是在我们能够优化p(c|x)之前,我们必须能够计算它。为此,我们使用贝叶斯定理:

贝叶斯定理。图片由作者提供。

这是朴素贝叶斯的贝叶斯部分。但是现在,我们有了以下问题:什么是p(x|c)和 p ( c )?

这就是朴素贝叶斯分类器的训练。

培训

为了说明一切,下面让我们用一个有两个真实特征 x ₁、 x ₂、三个类 c ₁、 c ₂、 c ₃的玩具数据集。

可视化的数据。图片由作者提供。

您可以通过以下方式创建精确的数据集

from sklearn.datasets import make_blobs

X, y = make_blobs(n_samples=20, centers=[(0,0), (5,5), (-5, 5)], random_state=0)

让我们从类概率 p ( c )开始,在标记的数据集中观察到某个类 c 的概率。估计这一点的最简单的方法是只计算类的相对频率,并使用它们作为概率。我们可以用我们的数据集来看看这到底意味着什么。

在数据集中,20 个点中有 7 个被标记为类别 c ₁(蓝色),因此我们称之为p(c₁)=7/20.我们也有 7 点给职业 c ₂(红色),因此我们设定p(c₂)=7/20.最后一班 c ₃(黄)只有 6 分,于是p(c₃)=6/20.

这种简单的类别概率计算类似于最大似然法。但是,如果您愿意,也可以使用另一个previous分布。例如,如果您知道这个数据集不代表真实的总体,因为类 c ₃应该出现在 50%的情况下,那么您设置 p ( c ₁)=0.25, p ( c ₂)=0.25 和 p ( c ₃)=0.5.任何有助于提高测试集性能的东西。

我们现在转向可能性p(x|c)=p(x₁, x ₂| c )。计算这种可能性的一种方法是过滤标签为 c 的样本的数据集,然后尝试找到捕获特征 x ₁、 x ₂.的分布(例如,二维高斯分布)

不幸的是,通常情况下,我们没有足够的样本对每一类进行适当的可能性估计。

为了能够建立一个更健壮的模型,我们做了一个天真的假设假设特征 x ₁, x ₂是随机独立的,给定 c 。这只是通过一种奇特的方式使数学变得简单

图片由作者提供。

为每一类c。这就是朴素贝叶斯的朴素部分的来源,因为这个等式一般不成立。尽管如此,即便如此,朴素贝叶斯理论在实践中也能产生良好的、有时是杰出的结果。特别是对于具有词袋特征的 NLP 问题,多项式朴素贝叶斯大放异彩。

上面给出的参数对于你能找到的任何朴素贝叶斯分类器都是一样的。现在就看你怎么造型了p(x₁|c₁】,p(x₂|c₁】,p(x₁|c₂】,p()

如果你的特征只有 0 和 1,你可以使用一个伯努利分布。如果它们是整数,一个多项式分布。然而,我们有真实的特征值,并决定为一个高斯分布,因此得名高斯朴素贝叶斯。我们假设以下形式

图片由作者提供。

其中, μᵢ,ⱼ 是平均值, σᵢ,ⱼ 是我们必须从数据中估计的标准偏差。这意味着我们为每个特征得到一个平均值 i 和一个类 c在我们的例子中是 2*3=6 个平均值。标准差也是如此。这需要一个例子。

让我们试着估计一下₂,₁和 ₂,₁.因为 j =1,我们只对类别 c ₁感兴趣,让我们只保留带有这个标签的样品。以下样本仍然存在:

# samples with label = c_1
array([[ 0.14404357,  1.45427351],
       [ 0.97873798,  2.2408932 ],
       [ 1.86755799, -0.97727788],
       [ 1.76405235,  0.40015721],
       [ 0.76103773,  0.12167502],
       [-0.10321885,  0.4105985 ],
       [ 0.95008842, -0.15135721]])

现在,因为 i =2,我们只需要考虑第二列。 μ ₂,₁是该列的平均值, σ ₂,₁是该列的标准差,即 μ ₂,₁ = 0.49985176, σ ₂,₁ = 0.9789976。

如果你再次从上面看散点图,这些数字是有意义的。从图片中可以看到,₁c级样品的特征 x ₂在 0.5 左右。

我们现在为其他五个组合计算这个,我们完成了!😃

在 Python 中,可以这样做:

from sklearn.datasets import make_blobs
import numpy as np

# Create the data. The classes are c_1=0, c_2=1 and c_3=2.
X, y = make_blobs(n_samples=20, centers=[(0,0), (5,5), (-5, 5)], random_state=0)

# The class probabilities.
# np.bincounts counts the occurence of each label.
prior = np.bincount(y) / len(y)

# np.where(y==i) returns all indices where the y==i.
# This is the filtering step.
means = np.array([X[np.where(y==i)].mean(axis=0) for i in range(3)])
stds = np.array([X[np.where(y==i)].std(axis=0) for i in range(3)])

我们收到

# priors
array([0.35, 0.35, 0.3 ])# means 
array([[ 0.90889988,  0.49985176],
       [ 5.4111385 ,  4.6491892 ],
       [-4.7841679 ,  5.15385848]])# stds
array([[0.6853714 , 0.9789976 ],
       [1.40218915, 0.67078568],
       [0.88192625, 1.12879666]])

这是高斯朴素贝叶斯分类器的训练结果。

做预测

完整的预测公式是

图片由作者提供。

让我们假设一个新的数据点 x=* (-2,5)进来。

图片由作者提供。

为了查看它属于哪个类,让我们计算所有类的p(c|*x **)。从图片上看,它应该属于类 c ₃ = 2,但让我们看看。让我们暂且忽略分母 p ( x )。使用以下循环计算出 j = 1,2,3 的命名数。

x_new = np.array([-2, 5])

for j in range(3):
    print(f'Probability for class {j}: {(1/np.sqrt(2*np.pi*stds[j]**2)*np.exp(-0.5*((x_new-means[j])/stds[j])**2)).prod()*p[j]:.12f}')

我们收到

Probability for class 0: 0.000000000263
Probability for class 1: 0.000000044359
Probability for class 2: 0.000325643718

当然,这些概率(我们不应该这样称呼它们)并不等于 1,因为我们忽略了分母。然而,这没什么问题,因为我们可以把这些未标准化的概率除以它们的和,然后它们会加起来等于 1。因此,将这三个值除以它们的总和约为 0.00032569,我们得到

图片由作者提供。

正如我们所预料的,一个明显的赢家。现在,让我们实施它吧!

完整的实现

这种实现方式效率很低,在数值上也不稳定,它只用于教育目的。我们已经讨论了大部分事情,所以现在应该很容易理解了。你可以忽略所有的check函数,或者阅读我的文章构建你自己的定制 scikit-learn ,如果你对它们到底做什么感兴趣的话。

请注意,我首先实现了一个predict_proba方法来计算概率。方法predict只是调用这个方法,并使用 argmax 函数返回概率最高的索引(=类)(又来了!).该类等待从 0 到 k -1 的类,其中 k 是类的数量。

import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.utils.validation import check_X_y, check_array, check_is_fitted

class GaussianNaiveBayesClassifier(BaseEstimator, ClassifierMixin):
    def fit(self, X, y):
        X, y = check_X_y(X, y)
        self.priors_ = np.bincount(y) / len(y)
        self.n_classes_ = np.max(y) + 1

        self.means_ = np.array([X[np.where(y==i)].mean(axis=0) for i in range(self.n_classes_)])
        self.stds_ = np.array([X[np.where(y==i)].std(axis=0) for i in range(self.n_classes_)])

        return self

    def predict_proba(self, X):
        check_is_fitted(self)
        X = check_array(X)

        res = []
        for i in range(len(X)):
            probas = []
            for j in range(self.n_classes_):
                probas.append((1/np.sqrt(2*np.pi*self.stds_[j]**2)*np.exp(-0.5*((X[i]-self.means_[j])/self.stds_[j])**2)).prod()*self.priors_[j])
            probas = np.array(probas)
            res.append(probas / probas.sum())

        return np.array(res)

    def predict(self, X):
        check_is_fitted(self)
        X = check_array(X)

        res = self.predict_proba(X)

        return res.argmax(axis=1)

测试实现

虽然代码很短,但仍然太长,无法完全确定我们没有犯任何错误。因此,让我们检查一下它与 scikit-learn GaussianNB 分类器的对比情况。

my_gauss = GaussianNaiveBayesClassifier()
my_gauss.fit(X, y)
my_gauss.predict_proba([[-2, 5], [0,0], [6, -0.3]])

输出

array([[8.06313823e-07, 1.36201957e-04, 9.99862992e-01],
       [1.00000000e+00, 4.23258691e-14, 1.92051255e-11],
       [4.30879705e-01, 5.69120295e-01, 9.66618838e-27]])

使用predict方法的预测是

# my_gauss.predict([[-2, 5], [0,0], [6, -0.3]])
array([2, 0, 1])

现在,让我们使用 scikit-learn。扔进一些代码

from sklearn.naive_bayes import GaussianNB

gnb = GaussianNB()
gnb.fit(X, y)
gnb.predict_proba([[-2, 5], [0,0], [6, -0.3]])

生产

array([[8.06314158e-07, 1.36201959e-04, 9.99862992e-01],
       [1.00000000e+00, 4.23259111e-14, 1.92051343e-11],
       [4.30879698e-01, 5.69120302e-01, 9.66619630e-27]])

这些数字看起来有点类似于我们的分类器,但它们在最后几个显示的数字中有点偏离。我们做错什么了吗?sci kit-learn 版本只是使用了另一个超参数var_smoothing=1e-09。如果我们把这个设为 0,我们就能得到准确的数字。完美!

看看我们的分类器的决策区域。我还标记了我们用于测试的三个点。靠近边界的那个点只有 56.9%的机会属于红色类,正如您从predict_proba输出中看到的。另外两点被归类为具有高得多的置信度。

具有 3 个新点的决策区域。图片由作者提供。

结论

在本文中,我们已经了解了高斯朴素贝叶斯分类器的工作原理,并直观地解释了为什么要这样设计——这是一种对感兴趣的概率进行建模的直接方法。与逻辑回归比较:在逻辑回归中,概率是用一个线性函数来模拟的,在这个线性函数上应用了一个 sigmoid 函数。这仍然是一个简单的模型,但感觉不如朴素贝叶斯分类器自然。

我们继续计算了一些例子,并收集了一些有用的代码。最后,我们实现了一个完整的高斯朴素贝叶斯分类器,它与 scikit-learn 配合得很好。例如,这意味着您可以在管道或网格搜索中使用它。

最后,我们通过导入 scikit-learn 自己的高斯朴素贝叶斯分类器进行了一个小的健全性检查,并测试我们和 scikit-learn 的分类器是否产生相同的结果。这次测试是成功的。😎

我希望你今天学到了新的、有趣的、有用的东西。感谢阅读!

作为最后一点,如果你

  1. 想支持我多写点机器学习和
  2. 无论如何,计划获得一个中等订阅,

为什么不做 通过这个环节 ?这将对我帮助很大!😊

说白了,给你的价格不变,但大约一半的订阅费直接归我。

非常感谢,如果你考虑支持我的话!

有问题就在LinkedIn上写我!

学习曲线图第 1 部分:对抗数据需求诅咒

原文:https://towardsdatascience.com/learning-curve-graphs-part-1-countering-the-data-requirement-curse-6bdeb7750edf?source=collection_archive---------25-----------------------

为你的下一个 ML 项目避免基于试错的数据集大小估计。

克里斯·利维拉尼在 Unsplash 上的照片

广义地说,大多数机器学习算法属于两类之一:线性模型或非线性模型。线性模型易于解释,训练和部署速度更快,并且不需要过多的计算资源。线性模型学习并产生输入的加权和,加上偏差(截距)项,从而将单个输入特征 X 映射到单个目标 f(X)。

作者图片

线性与非线性

然而,现实世界的挑战是复杂的,很少有线性的投入产出关系。因此,虽然线性模型简单且易于实现和集成,但它们通常无法充分模拟真实世界的系统。因此,这一缺点要求我们将注意力转向非线性模型。虽然许多非线性机器学习模型用于解决复杂的现实世界问题,但神经网络及其变体在广泛的应用中解决现实世界问题的能力越来越强,并迅速受到欢迎。神经网络(包含非线性激活函数)更具表现力,可以学习数据中的复杂模式和相关性,并且可以比线性模型更好地进行概括,但神经网络的这种高鲁棒性和高性能,像其他非线性模型一样,也有一个代价:数据需求诅咒。

大多数算法,尤其是神经网络及其变体,被设计成对它们被训练的数据集的底层分布进行建模。这些算法有数百万个可训练的参数,一旦学习,将识别训练数据集中的模式和趋势。不管训练数据集本身有多大,它仍然只是所有可能实例的子集——总体。随着总体复杂性和/或算法复杂性的增加,我们需要越来越多的数据点来可靠地估计潜在的分布。考虑两个例子:1 .一个模型被训练来区分生产装配线上的彩色盒子,比如红色、绿色和蓝色盒子。模型被训练来区分人体中的组织以辅助手术。我们可以做出一个有根据的猜测,第二种情况与第一种情况相比,需要更多的数据点来可靠地估计潜在的分布,这仅仅是因为数据中可能的变化和波动。一个小的数据集对于潜在的趋势可能是误导性的或者不具有代表性的。

数据集大小

由于研究社区和对机器学习解决方案日益增长的兴趣,我们看到了高质量基准数据集的数量、数据质量和注释质量的显著增长,但这些基准数据集中的数据点数量从几千到数百万个数据点不等。此外,随着迁移学习和数据扩充等强大技术的引入,对巨大数据集的需求正在下降。然而,问题仍然存在:我们需要多少数据来训练一个健壮的机器学习解决方案?

你可能会出于多种原因问自己这个问题:

  1. 数据收集:你可能还没有收集数据,需要知道收集足够的数据来训练一个高性能的 ML 模型所需的价格和时间。
  2. 数据扩充:您可能已经收集了一些数据,并且需要知道需要扩充多少数据集。
  3. 历史数据:您可能已经有了一个大型数据集,并且需要知道最佳的数据集大小,以减少您的计算和存储成本。
  4. 迁移学习:你可能已经有了一个训练好的模型,并且想把这个模型应用到一个“类似的”问题上,只需要尽可能少的再训练。

在所有这四种情况下,知道所需的数据集大小成为一个瓶颈。从一个问题到下一个问题,所需的数据集大小是变化的,并且与问题的复杂性和所选择的训练算法相关。坏消息是,目前没有办法 100%准确地确定这一点。真实世界的数据有很多噪音和变化,这使得很难完美地对训练数据集进行采样。除此之外,环境的变化、数据收集传感器的波动、日志记录错误、数据损坏和存储错误,都使得了解确切的所需数据集大小变得不可能。这是否意味着我们应该继续增加数据集的大小,希望它能提高模型的性能和健壮性?幸运的是,有更聪明、更简单的方法来处理这个瓶颈。一种这样的方法是使用学习曲线图。

学习曲线图

粗略定义的学习曲线图是相对于受控参数的模型性能随经验或时间的曲线图。学习曲线图通常被用作诊断工具,以评估模型在受控参数变化时的增量性能。学习曲线图的应用非常广泛,因为它们也可以用来估计所需的数据集大小。在这种情况下,受控参数将是数据集大小。下图显示了在这样的学习曲线图中,你通常可以期望看到什么。

作者图片

模型性能

ML 模型的性能最初通常会随着数据集的大小而增加。换句话说,随着数据集大小的增加,模型会学习并更新其对潜在趋势的估计。在某些时候,模型的性能会达到饱和,添加更多的数据并不会导致性能的显著提高。当模型性能饱和时,我们可以潜在地假设普通人群和训练数据集现在具有非常相似的基础分布。因此,进一步计算和存储的成本回报递减。我们的目标是使用学习曲线图和插值技术来估计目标性能值所需的数据集大小,或者找到最大性能的饱和点。在第 2 部分中,我们将看到这种方法在 MNIST 时装数据集和学习曲线图实验中的应用。

学习曲线图第二部分:实验

在第 1 部分中,我们讨论了非线性机器学习模型的数据需求诅咒。我们看到,我们可以使用学习曲线图来估计目标性能的数据集大小。在第 2 部分中,我们将使用一个基准数据集来设计这个实验:Fashion-MNIST。时尚-MNIST 数据集包含来自 10 个班级的 60,000 幅时尚和服装项目的训练图像(和 10,000 幅测试图像)。每个图像都是标准化的灰度图像,28×28 像素(总共 784 个像素)。这是一个比 MNIST 数字更具挑战性的分类问题,顶级结果是通过深度学习卷积神经网络实现的,在测试数据集上的分类精度约为 90%至 95%。每个训练和测试示例都被分配到以下标签之一:

作者图片

下图显示了我们将在实验中使用的时尚 MNIST 数据点的一些例子。

作者图片

我们的目标是看看我们是否可以复制一个图表来验证我们的学习曲线假设,并估计可接受的模型性能所需的最小数据集大小(尽可能接近最高结果)。

投入到实验中

我们将使用 Google Colab (python 3)来设计我们的实验,并使用 keras API 来访问时尚-MNIST 数据集并定义我们的 CNN 架构。首先,让我们看看这个实验需要的导入。

作者图片

我们使用 matplotlib 库来满足我们的显示需求,使用 keras 来访问时尚 MNIST 数据集和创建我们的 CNN 架构。接下来,让我们定义 3 个函数调用,使我们的代码模块化,让我们的生活更轻松。

  1. 准备用于训练和评估的数据集:

作者图片

首先,我们改变数据点的形状,使它们具有单一的颜色通道,然后我们将标签转换为用于训练的一键编码。最后,数据集中的每个像素的值都在 0-255 之间。我们需要将这些值从无符号 int 转换成 float32,并将这些值规范化为 0–1。

2 。创建 CNN 架构:

作者图片

在这个实验中,我们将使用一个非常简单的序列模型。该模型将具有 32 个 3×3 卷积滤波器,具有 RELU 激活。卷积图层之后是 2x2 maxpooling 图层,其输出将被展平以提供分类器的要素。然后,我们将使用具有 100 个节点的密集层来解释特征。最后,我们将使用另一个具有 10 个节点的密集层来表示 10 个类,并将 softmax 激活作为分类器。

所有层将使用权重初始化方案来播种权重。我们将使用保守学习率为 0.01、动量为 0.9 的随机梯度下降作为优化器,类别交叉熵作为损失函数。请记住,所有这些参数都是可配置的,并且为了有一个好的模型,首先需要这些参数。像自动驾驶和语音识别这样更复杂的问题将需要非常复杂的模型,但因为我们的问题陈述相对简单,所以我们使用的是相对简单的网络。

3.训练并评估模型:

作者图片

我们的最后一个功能将训练和评估模型。这一步是旅程中最重要的部分,但也是最容易理解的。我们首先使用模型定义来创建我们的 CNN 架构,然后使用 model.fit 来训练它,最后使用 model.evaluate 来评估训练的模型。在这个实验中,我们选择使用 32 的批量大小,并训练模型 10 个时期。

就是这样。我们有了运行学习曲线图实验的所有构件。让我们首先使用整个 60,000 张图像作为训练数据,以了解模型在最大数据集大小下的基准性能。我们将使用它来对我们的模型进行基准测试,并运行实验来查看在保持可比性能的同时我们可以减少多少数据利用率。

要运行这个实验,我们需要做的就是使用 keras 数据集访问时尚 MNIST 数据集,然后准备我们的数据进行训练,最后训练和评估模型,如下所示。

作者图片

一旦我们完成培训和评估,我们应该会看到类似如下的结果:

作者图片

在我们的运行中,我们观察到每个纪元运行大约需要 34 秒。这意味着我们在 60,000 张图像上训练这个模型的总时间大约是 340 秒。该训练在 10,000 个图像测试集上产生大约 91%的分类准确度。不算太糟吧?现在,让我们看看我们可以消除多少数据来获得相当的性能。让我们从 5000 个训练图像开始,每次迭代再增加 5000 个。虽然有更好的方法来处理这个问题,但为了简单起见,我们将为每次迭代手动更改训练数据集的大小,如下所示。

作者图片

当使用这样的实验设置时,建议交叉检查类别不平衡,但是,我们不会在这个实验中包括这样的策略。当我们从 keras 加载数据集时,它已经被打乱了。在这个实验中,由于数据集的简单性,我们将依赖于初始混洗和使用类别交叉熵损失来处理由采样引起的类别不平衡。

现在,让我们来看看在仅使用 5000 个训练图像的情况下,我们的模型性能是什么样的。

作者图片

我们观察到,在大约 30 秒的训练时间内,分类准确率为 86%——训练时间减少 11 倍,准确率降低 5%。在任何一天,这都将是一个很好的权衡,但是,我们的目标是看看在减少训练数据的情况下,我们可以在多大程度上接近我们模型的最大性能。下表和相应的曲线图显示了训练示例、训练时间和模型性能之间的映射。

作者图片

作者图片

从上表中,我们可以说 35,000 个训练图像是一个很好的价值权衡。对于 0.91%准确度的损失,这提供了训练数据需求的大约 42%的减少和训练时间的 41%的减少。您的用例的适当权衡是主观的,应该基于项目管理目标。

现在,这一切都很棒,但是如果我们一开始就没有 60,000 张图片呢?我们能估计数据集大小和性能之间的映射吗?是啊!这就是推断的由来。假设您只有 30,000 张图像,并且想要了解理论上的权衡,以了解还需要收集或扩充多少数据。这意味着您只有上表中前 6 个条目的数据(您总是可以获得更细粒度的数据,以便更好地播种插值算法)。随着样本数量的增加,从现有值外推学习曲线图将给出模型性能的适当估计。因此,我们可以估计目标性能的近似数据集大小要求。在下面的例子中,使用 scipy 的 interpolate 库,我们可以估计模型在不久的将来的性能,具有相当的准确性(90.16%的估计值对 90.23%的实际值)。

作者图片

那么坏处是什么呢?好吧,有许多外推法。我们假设学习曲线图遵循二次曲线,但我们可能会看到一个放大的快照。此外,你想估计的距离越远,你的预测就越不准确;外推只是一个简单的估计,可以给你一个大概,但不能保证 100%的准确性。

学习曲线图极大地帮助我们根据目标性能、所需资源和项目编译时间来估计所需的数据集大小,但它们仍然只是估计。研究人员还使用类似于统计学习理论、幂律函数估计和类比估计的技术来计算目标模型性能所需的粗略数据集大小。然而,学习曲线图仍然是帮助开发人员理解和确定项目范围的一种强大且相对简单的方法,因此他们可以更仔细地研究项目。

识别机器学习中过拟合和欠拟合的学习曲线

原文:https://towardsdatascience.com/learning-curve-to-identify-overfitting-underfitting-problems-133177f38df5?source=collection_archive---------1-----------------------

本文讨论了机器学习中的过拟合和欠拟合,以及使用学习曲线来有效地识别机器学习模型中的过拟合和欠拟合。

图片由克里斯里德Unsplash 上拍摄

过度拟合和欠拟合

过度拟合(又名方差):

如果一个模型对数据进行了过度训练,以至于它甚至可以从中学习噪声,那么这个模型就被称为过度拟合。过度拟合模型完美地学习了每一个例子,以至于它错误地分类了一个看不见的/新的例子。对于过度拟合的模型,我们有完美/接近完美的训练集分数,而测试/验证分数很差。

过度拟合背后的原因:

  1. 使用复杂模型解决简单问题,从数据中提取噪音。示例:将神经网络拟合到 Iris 数据集。
  2. 小数据集,因为训练集可能不是宇宙的正确表示。

欠拟合(又名偏差):

如果一个模型不能正确地学习数据中的模式,那么它就被认为是不合适的。欠拟合模型不会完全了解数据集中的每个示例。在这种情况下,我们看到训练集和测试/验证集的得分都很低。

不合身背后的原因:

  1. 用一个简单的模型来解决一个复杂的问题,这个模型不需要学习数据中的所有模式。示例:使用逻辑回归进行图像分类
  2. 底层数据没有固有的模式。比如,用一个学生父亲的体重来预测他的分数。

学习曲线介绍

学习曲线通过递增地添加新的训练样本来绘制训练样本的训练和验证损失。学习曲线有助于我们确定添加额外的训练示例是否会提高验证分数(在看不见的数据上的分数)。如果模型过度拟合,则添加额外的训练示例可能会提高模型在看不见的数据上的性能。类似地,如果一个模型不合适,那么添加训练样本也没有帮助。“learning_curve”方法可以从 Scikit-Learn 的“model_selection”模块导入,如下所示。

在本文中,我们将使用逻辑回归来预测“虹膜数据”的“种类”。我们将创建一个名为“learn _ curve”的函数,该函数的将逻辑回归模型拟合到 Iris 数据,并返回交叉验证分数、训练分数和学习曲线数据。

良好拟合模型的学习曲线

我们将使用“learn_curve”函数,通过将逆正则化变量/参数“c”设置为 1 来获得良好的拟合模型(即,我们不执行任何正则化)。

作者图片

在上述结果中,交叉验证准确率和训练准确率接近。

作者图片

解读培训损失

良好拟合模型的学习曲线在开始时具有适度高的训练损失,随着训练样本的增加,该损失逐渐减少,并且逐渐变平,这表明增加更多的训练样本不会改善模型在训练数据上的性能。

解读验证损失

良好拟合模型的学习曲线在开始时具有较高的验证损失,随着训练样本的增加,验证损失逐渐减少,并且逐渐变平,这表明增加更多的训练样本不会提高模型在看不见的数据上的性能。

我们还可以看到,在添加了合理数量的训练样本后,训练和验证损失彼此接近。

良好拟合模型的学习曲线的典型特征

  1. 训练损失和验证损失非常接近,验证损失略大于训练损失。
  2. 最初减少训练和验证损失,在某个时间点之后直到结束,训练和验证损失相当平稳。

过拟合模型的学习曲线

我们将使用“learn_curve”函数,通过将逆正则化变量/参数“c”设置为 10000(高值“c”会导致过度拟合)来获得过度拟合模型。

作者图片

与欠拟合和良好拟合模型相比,交叉验证准确度的标准偏差较高。训练精度高于交叉验证精度,这是过度拟合模型的典型特征,但不会高到检测不到过度拟合。但是过度拟合可以从学习曲线中检测出来。

作者图片

解读培训损失

过拟合模型的学习曲线在开始时具有非常低的训练损失,随着训练样本的增加,训练损失逐渐略微增加,并且不会变平。

解读验证损失

过度拟合模型的学习曲线在开始时具有较高的验证损失,随着训练样本的增加,该损失逐渐减少,并且不会变平,这表明增加更多的训练样本可以提高模型在未看到的数据上的性能。

我们还可以看到,训练和验证损失彼此远离,在添加额外的训练数据后,它们可能彼此接近。

过拟合模型学习曲线的典型特征

  1. 训练损失和验证损失相距甚远。
  2. 在添加训练样本时逐渐减少验证损失(没有拉平)。
  3. 非常低的培训损失,在添加培训示例后略有增加。

欠拟合模型的学习曲线

我们将使用“learn_curve”函数,通过将逆正则化变量/参数“c”设置为 1/10000 来获得一个欠拟合模型(“c”的低值导致欠拟合)。

作者图片

与过度拟合和良好拟合模型相比,交叉验证准确度的标准偏差较低。然而,欠拟合可以从学习曲线中检测出来。

作者图片

解读培训损失

欠拟合模型的学习曲线在开始时具有较低的训练损失,该损失随着训练样本的增加而逐渐增加,并在结束时突然下降到任意的最小点(最小并不意味着零损失)。这种结尾的突然下跌可能不会一直发生。下图也显示了欠拟合。

作者图片

解读验证损失

欠拟合模型的学习曲线在开始时具有较高的验证损失,该损失随着训练样本的增加而逐渐降低,并在结束时突然下降到任意最小值(这种在结束时的突然下降可能不总是发生,但它可能保持平坦),这表明增加更多的训练样本不能提高模型在看不见的数据上的性能。

欠拟合模型学习曲线的典型特征

  1. 增加训练样本会增加训练损失。
  2. 训练损失和验证损失在最后是接近的。
  3. 培训损失和最终确认损失的突然下降(并非总是如此)。

上图清楚地表明,学习曲线是识别过拟合和欠拟合问题的有效方法,即使交叉验证指标可能无法识别它们。

用可逆的(基于流的)解释网络学习解纠缠的表示

原文:https://towardsdatascience.com/learning-disentangled-representations-with-invertible-flow-based-interpretation-networks-9954554a28d2?source=collection_archive---------11-----------------------

什么是解开的表征?我们如何使用基于流的生成模型来学习任何任意模型的不纠缠的表示?

图 1:IIN 网络可以应用于任意的现有模型。IIN 采用由任意模型学习的表示 z,并将其分解成更小的因子,使得每个因子学习表示一个生成概念。图片来源:[1]。

解开的表示在处理许多下游任务时会很有用,并有助于提高模型的健壮性和通用性。在本帖中,我们将探讨如何从使用基于流的生成模型的任意预训练模型所学习到的表示中学习解开的表示。具体来说,我们将研究埃塞等人在论文《用于解释潜在表征的解开可逆解释网络》中提出的可逆解释网络(IIN)。艾尔。[1].我们将看到 IIN 背后的想法,它们是如何工作的,它们的用途是什么。我们还将简要了解一下该文件所取得的成果。

解开的表象

一个不纠缠的表征是这样的,其中单个潜在单位的变化对一个生成因素的变化敏感,而对其他因素的变化保持不变[2]。换句话说,给定一个解开的表征,潜在单位的变化将导致一个生成因素的变化,反之亦然。

解开的表征在多种任务中是有用的,例如新样本生成、新颖性检测、学习压缩的表征等。良好的表示有助于模型的健壮性和通用性。除此之外,在需要知识转移的任务中,在学习的表示可以帮助模型快速收敛的情况下,如转移学习或领域适应,解开的表示也有帮助。

基于流程的生成模型

当我们观察 VAEs 和 GAN 这样的生成模型时,他们都没有明确地了解真实的数据分布 p( x ),因为 p(x)=∫p(|z)p(z)dz通常是难以处理的,因为我们不可能对 z ~ p(z) 的所有值进行积分。另一方面,基于流的生成模型能够通过使用标准化流来克服这个问题。

标准化流程:标准化流程通过应用一系列双射变换,一个在另一个之上,将简单的分布变换为更复杂的分布。双射函数也有一个反函数,这意味着我们可以计算正向和反向。

基于流的生成模型只是一系列标准化的流,一个堆叠在另一个之上。因为变换函数是可逆的,所以基于流的模型也是可逆的( x → zz →x)

情商。1: A 流程

这里,z0是初始分布, x = z_k 是我们要学习的最终分布而 f_i(。)是一系列双射变换函数。

基于流量的模型允许我们直接优化数据的对数似然性,如下所示:

情商。2:对数似然计算。

这里π_ 0(z0)是初始分布。通常,选择变换使得对数行列式易于计算。

要了解更多关于基于流程的生成模型及其工作原理,请查看这篇令人惊叹的博客帖子

用于学习非纠缠表示的可逆解释网络

论文[1]背后的主要思想是学习非线性映射,该非线性映射将来自任意预训练模型的学习到的表示转换到一个空间,在该空间中,新的表示可以分解成因子,使得每个因子的表示对应于一个人类可理解的语义概念。为此,作者提出了一种基于流的可逆网络 T ,该网络学习从已学习的 larent 空间到新的、不纠缠的空间的映射(图 1 ,即:

并且由于 T 是可逆的,所以反过来也是可能的:

为了获得一个清晰且可解释的空间,作者建议将 Z~(读作 Z 颚化符)分解为 K+1 个因子,其中每个因子代表一个可解释的概念。

z 的因式分解。z被分解成 k 个因子,其中每个 z ~ k 是 N_k 维的。所有 k 的 N_k 总和为 n。

这里使用基于流的可逆网络是有意义的,因为我们能够从 T: z →z~ 以及 z~ → z 学习映射。这意味着,可逆模型 T 也应该允许我们通过修改解开空间中的单个因素 z~_k 来有意义地修改原始潜在表示 z

实现因子 z~_k 的解纠缠意味着对于所有 k,每个 z~_k 的分布彼此独立,并且所有 z~_k 的联合分布可以写成

情商。2:p(z ~)的因式分解。

每个因子 z ~ k 被模拟为一个单位高斯,因此联合分布成为

情商。3:联合分布 p(z~)

为了有解纠缠的因素,我们需要满足两个条件:
【I)每个 z~_k 应该只对一个可解释的概念敏感
ii) z~_k 应该对它不代表的所有其他概念不变。

这是通过查看成对的图像( x _a, x_b )来实现的。每个语义概念 F ∈ {1,…,K} 都用 z~_F 来表示。使用从 p(xa,xb | F)中提取的图像对(xa,xb)来训练每个 z~_F 。除了 F ∈ {1,…,K},之外的所有其他语义概念的表示都是通过剩余因子 z~_0 来学习的。

给定共享相同概念的一对图像 F 和它们的表示 z~^az~^b (来自可逆模型的图像的表示),我们需要确保两个图像的 f 因子的表示是相似的。为此,将图像 b 的 F 因子作为以图像 a 的 F 因子为中心的高斯:

情商。4

正相关因子σ_ab ∈ (0,1)控制 z~^a_Fz~^b_F 有多接近/相似。

ii) 所有其他因素的表示是不变的(无相关性),并被建模为单位高斯分布:

情商。5

为了训练流动模型,我们最大化图像对( z _a, z _b)的原始表示的可能性。该对的可能性计算如下

情商。6

记录日志并应用 Eqs。2、4 和 5 到等式 6,我们得到损失函数:

情商。7:一个图像对的丢失

在哪里,

红框中的项对应于 p(z^a 的所有因子的对数似然),
蓝框中的项对应于除 p(z^b 之外的所有因子的对数似然),
绿框中的项对应于图像 b 的因子 f 的对数似然,

T( z ^j_k) = z~_k

总损失是图像对在所有因子 F 上的损失:

情商。8:全损耗功能

估计每个因素的维度

在 IIN 模型中,我们将潜在的 z~ 分解为 K+1 个因子(残差+ K 个因子),其中 K 个因子中的每一个都可以具有不同的维度,条件是所有维度的总和等于 z~ 的总和。

通过计算每个因素的分数来估计每个因素的维度。因子 f 的分数被计算为所有图像对之间的原始表示的相关性的总和( z ^a, z ^b) ~ p( z ^a, z ^b|F),即,

情商。9:每个因素的得分。

剩余因子被赋予分数 N (尺寸 z )。那么每个因素的维数估计为:

情商。10:每个因子的估计维度。

结果

交换解开的因素

图 2:将目标图像(最左边一列)的残差( z~ _0)与目标图像(最上面一行)的动物类别因子( z~ _1)相结合。图片来源:[1]。

在图 2 中,将目标图像(最左边的列)的残差( z~ _0)与目标图像(最上面的行)的动物类别因子( z~ _1)相结合,导致在结果图像中动物类型的转移,同时保持源图像的姿态。

图 3:沿着语义轴 F → F~沿着微笑因子插值。图像来源:[1]

在 CelebA 数据集上沿着微笑的语义轴进行插值时,可以看到该模型能够控制微笑的数量,同时保持其他因素相对恒定。关于如何执行插值的更多信息可以在[1]中找到。

密码

论文的代码可以在这里找到

结论

在本文中,我们讨论了什么是无纠缠表示及其用途,然后简要地研究了基于流的生成模型是如何工作的。我们还深入研究了可逆解释网络。IIN 是一个强大的网络,可以在任何预训练的网络上使用,以学习从原始表示到解开的表示的映射。利用基于流的模型的可逆性,该模型还可以用于任意修改解开的因子 z~ _k,以实现原始表示中语义上有意义的改变。

页(page 的缩写)s:如果您发现任何错误/问题,请留下评论,我将很乐意修复它们!😃

参考

[1] Esser,Patrick,Robin Rombach 和 Bjorn Ommer。"一个用于解释潜在表征的解开的可逆解释网络."IEEE/CVF 计算机视觉和模式识别会议文集。2020.

[2]本吉奥、库维尔和文森特。表征学习:回顾与新观点。在 IEEE 模式分析汇刊&机器智能,2013。

从音频中学习:音高和色谱图

原文:https://towardsdatascience.com/learning-from-audio-pitch-and-chromagrams-5158028a505?source=collection_archive---------20-----------------------

为音乐信息检索解释音高变化

介绍

既然已经完全理解了声谱图的概念,我们想更深入地研究频率以外的各种结构。当研究 Mel 标度上的声波时,我们体会到了这一点——特别是使用 MFCCs。虽然可视化 MFCCs 在技术上不是光谱图,但粗略的想法仍然成立。

然而,这篇文章将更侧重于音乐信息检索(MIR ),因为我们将研究音高随时间的变化。为了做到这一点,我们需要了解什么是音高,它是如何表示的,以及我们如何使用傅立叶变换来确定音高的变化。

相关文章:

一如既往,如果你想查看 Jupyter 笔记本中的代码,你可以在我的 GitHub 上找到一切。

什么是音高?

音高可以理解为声音的相对高低。声音越高,音调越高,声音越低,音调越低。很简单,对吧?为了完全理解音高,我们需要理解音高类别和八度音阶。

音高类别是与每个声音相关联的字母。所有的音高都属于 7 个字母中的一个:A、B、C、D、E、F 和 g。让我们假设我们正在弹钢琴,我们从 A 开始。我们将一直上升一个白键,直到我们到达 g 键。当我们随着每个白键上升时,我们不可避免地一遍又一遍地循环这些字母。然而,当我们按下 G 后的第二个 A 键时,重要的是要注意,它不是我们最初开始时的那个音。音高类是一样的;这是一把钥匙。然而,声音比以前更高,表明我们在下一个(更高的)八度。

在潜入八度之前,我们先快速覆盖一下黑键。如果我们从 C 开始,上升一个黑键,我们就达到了所谓的 C#(读作 C 调。)如果我们再看一下这幅图,我们还会发现它也被称为 D♭(pronounced 降 d 调。)这是因为黑键也在 d 之前,简单来说,如果我们上一个黑键,音符就“升”了,如果我们下一个黑键,音符就“降”了。就人类听到的而言,它们是等价的,所以我们称这些音符为等音。至于两个白键之间没有黑键的情况,你不必为这篇文章担心,因为这涉及到更多的音乐理论。

一个八度音程是一个数字,它指明了我们所处的音高组。如果我们重复我们的例子,知道我们在 A3,下一个 A 键是 A4。同样,这应该不难理解。键盘的中间键是 C4,它通常被用作你所在八度的参照。

值得注意的是,该数字不是在每个 A 值之后增加,而是在每个 C 值之后增加。这意味着,如果我们从中间的 C,或 C4 开始,它后面的 B 键是 B3,B 键在 B4 之后。

关于色谱图

既然我们了解了音乐中的音高,我们就可以深入到色度滤波器中去,它是我们色度图的基础。

色度滤波器可以从色度滤波器组中导出。滤波器组旨在将录制声音的所有能量投射到 12 个箱中,即我们看到的所有音符,加上小调/大调(也是钢琴的黑键),而不管它在哪个八度音阶中。通过忽略八度音阶,我们可以创建一个音高如何随时间变化的热图,这是 MIR 的一个重要方面。例如,如果你决定教 LSTM 人如何演奏音乐,这些功能将非常有用,因为它们会告诉神经网络音高可能如何随时间变化。

让我们想象一下不同频率下的色度滤波器组。

作者照片

通过取我们基于傅立叶的声谱图(通过取 STFT)和这个滤波器组的点积,我们可以将所讨论的歌曲映射到我们之前讨论过的一组音高上。幸运的是,多亏了librosa,创建色谱图的功能已经为我们创建好了。请注意,我们不必使用音频上的 STFT 作为我们的基础,但这超出了本文的范围。

记住这一点,让我们研究我们的各种体裁片段的色谱图。

作者照片

现在我们可以看到音高是如何随时间变化的,我们可以在每种体裁中看到一些有趣的观察结果。

对于 R&B 来说,很明显艺术家决定让歌曲围绕 e 音符,对于 Rap 来说,它是高度分散和分布的,这是有意义的,因为这种类型利用了类似于打击乐的声音节奏,而对于 Rock 来说,它围绕 C#或 D♭.音符

结论

到目前为止,您应该已经很好地理解了什么是音高,我们如何对每个音高进行分类,色度滤镜的目的是什么,以及我们如何可视化色度图。

如果你有任何问题,请在下面留下。

从音频中学习:频谱图

原文:https://towardsdatascience.com/learning-from-audio-spectrograms-37df29dba98c?source=collection_archive---------23-----------------------

将音频结构可视化到毫秒级。

到本文结束时,你将能够创建像这样的图形。图片作者。

简介:

当涉及到机器学习,甚至深度学习时,如何处理数据是模型训练和测试性能的基础。当在音频领域工作时,在到达这个阶段之前有几个步骤需要理解,但是一旦你到达那里,从音频中学习就成为一个相当容易的任务。在阅读本文之前,请务必理解下面链接的概念。

相关文章:

在这篇文章中,我的目标是分解什么是频谱图,它是如何在机器学习领域使用的,以及你如何使用它们来解决你试图解决的任何问题。

和往常一样,如果你想查看代码,以及需要跟进的文件,你可以在我的GitHub上找到一切。

什么是声谱图?

你可以把光谱图想象成声音的图片。我知道这有点奇怪,但你应该尽可能加强这种直觉。光谱图中的 spec 部分来自光谱,你在图右侧看到的色带就是这个。的光谱是什么?音频的频率。

记住所有这些信息,让我正式定义。

声谱图是表示一段时间内记录的音频的频谱的图形。

这意味着,当我们在图中颜色变亮时,声音严重集中在这些特定频率周围,而当我们颜色变暗时,声音接近空/死声。这使得我们甚至不用听就能很好地理解音频的形状和结构!这就是光谱图在各种 ML/DL 模型中发挥作用的地方。

如何创建光谱图:

现在出现了一个问题,我们如何计算光谱图?这个问题的答案比预想的要简单很多。

  • 将音频分割成重叠的块或窗口。
  • 在每个窗口上执行短时傅立叶变换。记得取其绝对值!
  • 每个结果窗口都有一条垂直线代表幅度与频率的关系。
  • 取结果窗口并转换为分贝。这给了我们声音结构的丰富图像。
  • 最后,我们将这些窗口重新布置成原始歌曲的长度,并显示输出。

现在我们已经对频谱图有了一个很好的理解,让我们学习如何用 Python 从声音中检索它们!使用librosa中的函数,我们可以不费吹灰之力就完成这项工作。

首先,让我们导入所需的包并加载音频。

第二,我要定义两个函数;一个将执行所有必要的步骤并输出处理后的信号,另一个将绘制频谱图。请务必通读注释和行,以了解完成此操作的过程。

现在,定义好函数后,我们可以简单地使用plot_spec来绘制结果!

plot_spec(to_decibles(guitar), sr, 'Guitar')

作者图。

plot_spec(to_decibles(kick), sr, 'Kick')

作者图。

plot_spec(to_decibles(snare), sr, 'Snare')

作者图。

结论:

至此,您应该能够理解如何使用短时傅立叶变换创建光谱图,以及如何用 Python 创建光谱图。音频的这些表示允许各种深度学习架构比波形甚至傅立叶表示更容易地提取特征。

请继续关注更多音频声谱图。

感谢您的阅读。

从音频中学习:梅尔标度、梅尔频谱图和梅尔频率倒谱系数

原文:https://towardsdatascience.com/learning-from-audio-the-mel-scale-mel-spectrograms-and-mel-frequency-cepstral-coefficients-f5752b6324a8?source=collection_archive---------2-----------------------

打破对类似人类的声音表达的直觉

相关文章:

到现在为止,我们对光谱图是什么以及如何创建光谱图有了更强的直觉。简而言之,声谱图让我们能够看到音频和这些声波产生的压力,从而让我们看到记录的声音的形状和形式。

本文的主要目的是介绍一种新的光谱图——一种在机器学习领域广泛使用的光谱图,因为它很好地代表了类似人类的感知。

和往常一样,如果你想查看代码,以及需要跟进的文件,你可以在我的GitHub上找到一切。

让我们首先从导入所有必需的包开始。

注:所有图片均由作者创作。

梅尔标度

在讨论 Mel 光谱图之前,我们首先需要了解 Mel 标度是什么以及它为什么有用。Mel 标度是信号频率的对数变换。这种转换的核心思想是,Mel 标度上距离相等的声音被感知为与人类距离相等。这是什么意思?

例如,大多数人可以很容易地分辨出 100 赫兹和 200 赫兹的声音。然而,出于同样原因,我们应该假设我们能够区分 1000Hz 和 1100 Hz,对吗?不对。

实际上,人类很难区分较高的频率,而区分较低的频率更容易。因此,即使两组声音之间的距离相同,我们对距离的感知却不同。这使得 Mel 标度成为音频机器学习应用的基础,因为它模拟了我们对声音的感知。

从赫兹标度到梅尔标度的变换如下:

注意,这里的log指的是自然对数(也表示为ln)。)如果对数的底数是 10,则方程的系数(1127)会略有变化。然而,在本文中,我们将简单地参考上述等式。

让我们想象一下 Hertz 和 Mels 之间的关系:

正如我们从上面的图表中看到的,频率较低的 Hz Mel 之间的距离较大,而频率较高的 Hz Mel 之间的距离较小,从而加强了其类似人类的属性。

现在我们已经很好地理解了梅尔标度的效用,让我们利用这种直觉来开发梅尔光谱图。

梅尔光谱图

Mel 声谱图是在 Mel 标度上可视化声音的声谱图,与频域的相对,正如我们之前看到的。现在,我知道你在想什么,真的有那么简单吗?是的,它是。

一旦光谱图的直觉建立起来,学习它们的各种味道就变得非常容易。我们所需要的是一个新的框架,在这个框架下我们可以开发光谱图。我将假设你知道这是如何做到的基本属性。开发 Mel 光谱图比它们的定义更容易。

我们是这样做的:

回忆波形图中的信封遮罩。此功能创建一个遮罩来生成一个包络,该包络会修剪掉不必要的无用噪声。这使我们能够专注于音频的重要部分。

类似于我们在频谱图中的结果,我们可以看到每个声音是如何根据它实际产生的声音而呈现出独特的形状的。

吉他(长度比脚鼓和小军鼓长)比其他研究过的声音更能向外共鸣。直觉上,这应该是有意义的,因为当一个人弹吉他时,被拨动的琴弦甚至在弹奏后仍在振动,这就是这种共振结构是如何被描绘的。底鼓的声音很低且很快。你可以把踢鼓想象成一种重击。响弦频率很高,虽然向外轻微共鸣(向上共鸣更多),但比其他声音消散得更快。

梅尔频率倒谱系数

Mel 频率倒谱系数(MFCC)最初用于各种语音处理技术,然而,随着音乐信息检索(MIR)领域开始进一步发展为机器学习的附属物,人们发现 MFCC 可以很好地表示音色。

开发 MFCCs 的基本程序如下:

  • 从赫兹转换到梅尔标度
  • 取音频 Mel 表示的对数
  • 取对数幅度并使用离散余弦变换
  • 这个结果在 Mel 频率上而不是在时间上创建了一个频谱,因此创建了 MFCCs

如果 ML 问题保证使用 MFCCs,例如自动语音识别或去噪音频,则使用的系数的数量是模型的超参数。因此,MFC 的数量会根据问题的不同而不同。然而,对于这个例子,我们将使用librosa的默认 20 个 MFCCs。在librosa中,我们可以完成所有这些工作,并在短短几行代码中可视化输出:

结论

作为本文的总结,您现在已经了解了:

  • 什么是 Mel 音阶,它如何在类似人类的音频解释中发挥作用
  • 如何将 Mel 标度映射到光谱图上
  • 什么是 MFCC,MFCC 的某些用例,以及如何开发它们

利用 Mel Spectrograms 是处理音频的一种非常好的方式,这样各种深度学习和机器学习问题就可以从记录的声音中学习。

在下一篇文章中,我们将使用我们已经建立的基础更深入地研究音乐信息检索(MIR ),并试图获得更多关于是什么使音乐对人类如此独特的见解。

从音频中学习:时域特性

原文:https://towardsdatascience.com/learning-from-audio-time-domain-features-4543f3bda34c?source=collection_archive---------12-----------------------

在时间上更深入。

介绍

虽然深度学习经常利用频域中的过程,但在时域中仍有许多相关特征可以利用,这些特征与许多机器学习技术相关。简而言之,可以提取和分析这些特征来理解波形的属性。当在时域内提取特征时,我们通常会研究每个样本的幅度。我们如何操纵振幅,给我们提供了有关信号的某些细节。

相关文章:

开始之前,我想建立一些符号:

在这些例子中,我将详细说明什么是特性,如何正式定义它,并展示如何用 Python 提取特性。在前面的例子中,我们看了乐器的某些声音。然而,在本例中,我们将随机查看不同流派(特别是 R&B、说唱和摇滚)的 7 秒歌曲片段,以便更好地了解这些特征的属性。

出于版权原因,我不能分享有问题的歌曲,但是我会分享歌曲的输出情节和风格。这将允许我们研究流派之间的细微差别。

一如既往,资源库中的所有代码都可以在 上从音频学习 GitHub 资源库 中找到。

注:所有数字均由作者提供。

振幅包络

振幅包络(AE)旨在提取每帧中的最大振幅,并将它们串在一起。记住振幅代表信号的音量(或响度)是很重要的。首先,我们将信号分成不同的窗口,找出每个窗口内的最大幅度。从那里,我们沿着时间绘制每个窗口中的最大振幅。

我们可以使用 AE 来进行开始检测,或者检测声音的开始。在各种语音处理应用中,这可能是有人说话或外部噪声,而在音乐信息检索(MIR)中,这可能是音符或乐器的开始。

AE 的主要缺点是对异常值的鲁棒性不如均方根能量,我们将很快对此进行研究。

下面是我们如何将这个概念形式化:

在 Python 中搜索可以完成这项任务的已定义方法时,我没有找到。因此,我们将从头开始定义它,因为这很容易做到。我们将看到的其他特征提取方法已经在librosa中定义了,所以我们将在正式定义它们之后使用这些函数。

值得注意的是,在这个for循环的设置中,我们没有指定hop length。这意味着当我们创建上限和下限时,窗口不会重叠,使得hop lengthframe length相同。

现在,为了可视化和比较不同流派的 AE:

均方根能量

如前所述,均方根(RMS)能量与 AE 非常相似。然而,与开始检测相反,它试图感知响度,这可用于事件检测。此外,它对异常值更加鲁棒,这意味着如果我们分割音频,我们可以检测到新的事件(如新的乐器、有人说话等)。)要可靠得多。

均方根能量的正式定义:

如果你熟悉均方根的概念,这对你来说不会太陌生。然而,如果你不是,不要担心。

当我们在波形上加窗时,我们对窗内的振幅求平方,然后求和。一旦完成,我们将除以帧长度,取平方根,这将是该窗口的均方根能量。

要提取均方根,我们可以简单地使用librosa.feature.rms。现在,我们想象一下:

从均方根和声发射可以看出,均方根波动不如声发射剧烈。这一特性使得幅度的均方根值对异常值更加稳健。

过零率

过零率(ZCR)旨在研究信号幅度在每一帧内改变符号的速率。与前两个特征相比,这个特征很容易提取。

ZCR 的正式定义如下:

对于和平号来说,这一特征与识别撞击声相关,因为它们通常具有波动信号,can ZCR 可以很好地检测到这些信号以及音高检测。然而,该特征通常被用作语音识别中用于声音活动检测的特征。

使用librosa,我们可以使用librosa.feature.zero_crossing_rate提取 ZCR。

结论

到目前为止,您应该已经了解了时间特征提取是如何工作的,如何在各种基于音频的应用中使用它,以及如何自己开发特征提取方法。通过利用特定窗口内的振幅,我们对 MIR 和 ASR 中的各种应用有了深入的了解。感谢您的阅读,如果您有任何问题,请随时提问!

从数据中学习:鸟瞰

原文:https://towardsdatascience.com/learning-from-data-a-birds-eye-view-4e47bd53be8f?source=collection_archive---------58-----------------------

什么是数据科学?什么是机器学习?穴居人、艾萨克·牛顿和数据科学家讨论从数据中学习的本质:从史前学会生火到 21 世纪的数据科学

照片由merit ThomasUnsplash 上拍摄

著名的哈佛教授 Joseph Blitzstein 在他的《概率》一书中指出了新手和专家之间的区别:

新手努力记住大量看似不相关的事实和公式,而专家看到的是一个统一的结构,其中一些原则和想法将这些事实连贯起来

换句话说,专家可以毫不费力地看到全局,即该领域的鸟瞰图。Blitzstein 教授用上面引用的话中蕴含的精神在哈佛和更广阔的世界讲授概率和统计。本文将本着 Blitzstein 的引用精神,为您提供从数据中学习的鸟瞰图,以及它与数据科学和机器学习的关系。我将保持这篇文章相当高的水平,这样任何在这个领域开始的人,或者只是好奇的人,都会发现它很有用。有经验的数据科学家也会发现这篇文章很有用,并对数据科学和机器学习的本质有了新的看法。

为了做好铺垫,我们先来讲一个在这个宇宙中很可能没有发生的跨代篝火会的故事。篝火会议有 3 位特别嘉宾讨论数据科学领域。这三个人是:

一个史前时期的穴居人,艾萨克·牛顿爵士(17 世纪的著名科学家),一个数据科学家(21 世纪)。会议期间,数据科学家开始向牛顿和穴居人解释数据科学:

数据科学家: 数据科学是一个广阔的领域,但简言之,它就是使用模型从数据中学习,并交流这些结果。

艾萨克·牛顿爵士:这听起来很像我们科学家做的事情。我们通过收集数据来观察世界,然后我们试图用一个假设来解释数据背后的现象。这个假设是我们解释我们观察到的现象的模型。然后,该模型帮助我们进一步构建事物并提供解决方案。

穴居人: 我原以为我会完全不合时宜,但我想补充一些东西。我的祖父告诉我,我们的祖先过去住在茂密的森林里,他们观察到野火,但不知道如何生火或控制火。然后我们观察到摩擦可以生火,这就是我们发明弓钻( 一种史前手动工具,用于通过摩擦生火 )帮助我们生火的原因。我想我们那时在做数据科学。我们观察(生火),形成我们的模型(摩擦生火),把那个知识交流提炼出来解决一个问题(如何生火,如何控火)。

每个人似乎都学到了一些东西,并分享了一些信息:

穴居人: 人类已经取得了巨大的进步,虽然他们已经想出了很酷的名字(科学/数据科学),但他们所做的本质上与我们过去所做的一样(观察、构建、交流)。

牛顿: 这门科学现在是真正的主流,尽管他们现在有了新的名称。

数据科学家: 我从来没有意识到数据科学其实和人类本身一样古老!

正如序言试图断言的那样,我们人类从数据中学习的想法并不新鲜。自从我们在这个星球上存在以来,我们一直在这样做。我们观察(收集数据),总结那些观察结果(用一个模型或假设),然后用那个模型解决问题(例如,预测)。多年来,各种学科已经开发了工具和技术来准确地做到这一点:从数据中学习(一些例子是计算机视觉、数字信号处理、统计信号处理、自适应信号处理、数据挖掘、系统识别、模式识别等)。).所有这一切意味着,所开发的技术和工具的主体已经存在(并在不断发展)很长时间了,而该领域本身(数据科学或机器学习)并不新鲜。然而,与其他术语不同,机器学习(以及现在的数据科学)已经获得了广泛的普及。本质上,它们是一个总括术语,指的是帮助我们从数据中学习的各种工具和技术。

所开发的技术和工具已经存在了很长时间(并在不断发展),该领域本身(数据科学或机器学习)并不新鲜。然而,与其他术语不同,机器学习(以及现在的数据科学)已经获得了广泛的普及。本质上,它们是一个总括术语,指的是帮助我们从数据中学习的各种工具和技术。

理解该领域的一个很好的起点是使用文氏图来说明该领域的跨学科性质(这首先由 Drew Conway 提出,多年来已经提出了几个变体):

数据科学维恩图(最初由德鲁·康威构思,略有改编版本),图片由作者提供

现在从数据中学习需要的两个重要组成部分是计算机科学(在 Drew Conway 的原始图表中称为黑客技能)和数学与统计。这两个领域共同构成了机器学习的基础,机器学习涉及从数据中学习的工具和技术。当机器学习的知识与该领域的知识相结合来帮助解决问题时(然后作为解决问题途径的一部分进行交流),这就是数据科学。用简单的英语来说:数据科学就是拥有足够的计算机科学技能来运行可以处理数据的软件代码,足够的数学和统计知识来理解对数据使用什么模型,以及足够的领域专业知识来提出正确的问题和解决问题。

用简单的英语来说:数据科学就是拥有足够的计算机科学技能来运行可以处理数据的软件代码,足够的数学和统计知识来理解对数据使用什么模型,以及足够的领域专业知识来提出正确的问题和解决问题。

既然你对什么是数据科学有了一个概念,一个有效的问题是:如果数据科学已经存在了很长时间,为什么它现在还受欢迎?

数据科学受欢迎的两个关键原因是计算能力和我们现在生成的数据量。

我们现在产生了前所未有的大量数据。据《福布斯》报道,我们仅在两年前就收集了全球超过 90%的数据,而那篇文章现在已经发表两年了!)我们生成的数据量与日俱增。这些数字令人难以置信。估计有 45 亿人在线(截至 2019 年 6 月),谷歌、脸书、Youtube 产生了大量数据。据估计,到 2025 年,将有 750 亿台物联网(IoT)设备。我想我不需要说服你,我们现在正在产生大量的数据,完全是前所未有的。如果没有别的,想想你每天使用的智能手机(以及你通过数字媒体阅读这篇文章的事实,当你阅读这句话时,它会产生一些关于浏览量和阅读时间的数据)。现在把这个比例扩大到你在 24 小时内的每一次互动,然后扩大到你周围的所有人,你很快就会发现,这些数字是可以理解的,令人难以置信的。

除了数据之外,计算能力也有了惊人的增长(存储、GPU、云计算的成本,以及工具可用性和可访问性的相应提高)。这是一个很好的资源,可以通过各种数字和图表来更好地了解指数级进展(以及摩尔定律在起作用)。

让我们更深入地了解从数据中学习的概念。划分学习类型的一种方法(也是最流行的方法)是根据可用的反馈类型。使用这种方法的三种学习类型是监督学习、非监督学习和强化学习。

三种类型的学习是:监督学习,无监督学习和强化学习。

监督学习中,我们知道输入和输出,我们试图找到一个模型,可以最好地总结输入和输出之间的关系。例如(见下图),假设我们想要构建一个模型,该模型可以使用婴儿的心率和呼吸频率(即婴儿呼吸的快慢)来告诉我们婴儿是健康的(显示为绿色)还是生病的(显示为红色)。我们使用我们拥有的所有婴儿的所有现有数据,并将其提供给学习模型,包括关于他们是否健康或生病的信息。学习模型然后使用该数据来寻找决策边界。这个决策边界然后帮助我们找出已知心率和呼吸率(但未知健康状态)的婴儿(新数据实例)是生病还是健康。

监督学习:使用现有数据(学习过程中使用的输入和输出)学习决策边界,由作者创建图像

无监督学习中,我们只有用于学习的输入数据,在学习阶段没有提供明确的反馈。无监督学习最常见的应用是聚类。举个例子,假设我们有很多人的身高和体重信息,我们想把他们分成不同的组。我们将使用无监督学习方法来发现数据中的自然分组。

无监督学习:仅使用输入数据识别聚类(在学习阶段没有明确的反馈/输出),按作者分类的图像

强化学习中,反馈以奖励或惩罚的形式提供,代理学习找到最合适的行动。代理人是一个学习系统,它存在于一个环境中,通过采取行动并因此受到奖励或惩罚而与之互动。

强化学习:代理在环境中采取行动,并根据收到的反馈进行学习。收到的反馈要么是奖励,要么是惩罚

在我结束之前,关于我概述的学习方法有一点需要注意:从特定的数据点学习模型(或函数)是归纳学习(一种自下而上的方法)。一种不同的学习方法是演绎学习(从模型到数据)。将学习类型分为有监督、无监督和强化是机器学习社区在引入该领域时最常用的方法。然而在实践中,迭代方法是典型的,在那里你建立一个模型,看看模型如何执行,然后根据反馈再次做出改变(参见我在数据科学文章中关于咨询的顶级技巧,以了解在实施数据科学项目时更实际的一面)。实际上,这是结合了自下而上的方法(归纳学习)和自上而下的方法(演绎学习)。数据科学实际上是一个迭代过程,因此在解决问题时会使用这两种方法。

总之,这篇文章断言数据科学不是一个新领域,并且(几乎)与我们人类一样古老,给出了该领域现在变得广泛流行的两个最重要的原因(计算能力和现在产生的数据量,这两者在我们的历史上都是前所未有的),并给出了从数据中学习的类型的鸟瞰图(有监督的、无监督的和强化学习)。我希望你在阅读这篇文章时感到愉快:)。

https://ahmarshah.medium.com/membership

从机器学习错误中学习

原文:https://towardsdatascience.com/learning-from-machine-learning-mistakes-how-to-find-weak-spots-of-a-regression-model-2cf3e91306b9?source=collection_archive---------14-----------------------

入门

如何找到回归模型的弱点

作者图片

当我们分析机器学习模型性能时,我们通常会关注单个质量指标。对于回归问题,这可能是梅,MAPE,RMSE,或任何最适合问题领域的。

在训练实验中,针对单个指标进行优化绝对有意义。这样,我们可以比较不同的模型运行,并可以选择最好的一个。

但是当涉及到解决一个真正的商业问题并将模型投入生产时,我们可能需要知道更多一点。该模型在不同用户群中的表现如何?它会犯什么类型的错误?

在这篇文章中,我将更详细地介绍一种评估回归模型性能的方法。

回归误差:太多还是太少?

当我们预测一个连续变量(如价格、需求等)时,误差的常识性定义很简单:我们希望模型预测尽可能接近实际。

实际上,我们可能不仅关心绝对误差值,还关心其他标准。例如,我们捕捉趋势的能力有多强,预测值和实际值之间是否存在相关性,以及我们的错误到底是什么。

低估和高估目标价值可能会有不同的商业含义。尤其是在模型输出之上有一些业务逻辑的时候。

假设您正在为一家连锁杂货店做需求预测。一些产品容易腐烂,根据错误的预测交付太多会导致浪费。高估显然要考虑成本因素。

图片作者。来源于 Unsplash 的图片: 12

除了经典的误差分析,我们可能想要跟踪这种误差偏斜(高估或低估的趋势)以及它如何随时间变化。在验证和生产监控过程中分析模型质量时,这是有意义的。

为了解释这个分析误差偏差的概念,我们来看一个例子。

评估模型性能

假设我们有一个预测城市自行车租赁需求的模型。(如果你想玩这个用例,这个自行车需求预测数据集是公开可用的)。

我们训练了一个模型,模拟了部署,并将它在“生产”中的性能与它在训练集上的表现进行了比较。

在实践中,我们需要知道这方面的基本事实。一旦我们了解了实际需求,我们就可以计算模型的质量,并估计我们的预测有多远。

在这里,我们可以看到培训中的参考绩效和当前生产绩效之间的误差大幅增加。

截图来自显然是的报道。

为了更好地理解质量,我们可以看看误差分布。它证实了我们已经知道的:误差增加了。也有一些高估的偏见。

截图来自显然是的报道。

事情看起来并不理想,我们想更深入地了解正在发生的事情。我们的业务利益相关者也是如此。为什么会出现这些错误?具体在哪里?再培训是否有助于我们提高质量?我们需要设计新的功能或创建进一步的后处理吗?

这里有一个如何探索它的想法。

观察边缘

总体质量指标向我们展示了平均性能。然而,这些都是极端的情况,往往可以给我们提供有用的信息。让我们直接看那里!

我们可以将我们有高误差的预测分组,并从中学习一些有用的东西。

我们如何实现这种方法?

让我们来计算每个预测的误差。然后,我们根据错误类型创建两组:

  • 高估。模型预测值高于实际值的情况。
  • 低估。模型预测值低于实际值的情况。

让我们通过选择误差最大的 5%的最极端的例子来限制每个组的大小。这样,我们就有了模型高估的前 5%预测和模型低估的前 5%预测。

其余 90%的预测是“大多数”这组的误差应该接近平均值。

这就是我们如何可视化建议的部分。这是我们希望看到的一种情况:大多数预测都接近实际值。分析异常值可以带来有意义的洞察力。

图片作者。

怎么可能有用?

让我们举一个时间序列的例子。如果我们建立了一个伟大的模型,并从数据中“学习”了所有的信号,那么误差应该是随机的。应该没有模式。除了少数可能的异常值,误差将接近所有组的平均值。有时稍大,有时小。但平均来说,差不多。

如果数据中有一些有用的信号可以解释错误,情况可能会有所不同。特定群体可能存在较大误差。也可能存在明显的低估或高估倾向。

在这些情况下,误差可能依赖于特定的特征值。如果我们能找到并描述比平时更高的情况会怎样?这正是我们想要调查的!

发现缺陷

在我们的例子中,我们可以看到,高估和低估组的误差明显高于“多数”组的误差。

截图来自显然是的报道。

然后我们可以尝试调查和探索新的模式。

为此,我们查看两个 5%组中的对象,并查看它们对应的特征值。如果可以的话,一个特征接一个特征。

我们的目标是确定特定特征值和高误差之间是否存在关系。为了获得更深的洞察力,我们还区分高估或低估。

想象一下,我们预测医疗保健成本,并一直高估某些人口统计数据的患者的价格?或者,误差是无偏的但很大,我们的模型在特定的段上失败了?这是我们想要找到的一种洞察力。

图片作者。

我们可以制定一个复杂的(计算量大的)算法来搜索性能不佳的片段。作为一种合理的替代,我们可以逐个特性地进行分析。

我们怎样才能做到呢?让我们画出特征分布和我们的目标需求,并用颜色标记我们犯高错误的例子。

在我们的自行车需求预测用例中,我们已经可以获得一些见解。如果我们绘制“湿度”特征,我们可以注意到,当湿度值在 60 和 80 之间(绘制在右侧)时,我们的模型现在明显高估了需求。

我们在训练数据集中看到了这些值(绘制在左侧),但是误差是无偏的,并且在整个范围内是相似的。

截图来自显然是报道。

我们也可以注意到其他模式。例如,温度。该模型还高估了温度高于 30℃时的需求

截图来自显然是的报道。

我们现在可以怀疑天气发生了变化,新的相关模式出现了。实际上,我们只使用一年中寒冷月份的数据来训练模型。当它进入“生产”阶段时,夏天才刚刚开始。随着新的天气出现了新的季节模式,这是该模型之前未能把握的。

好消息是,通过观察这些图,我们可以看到数据中似乎有一些有用的信号。根据新数据重新训练我们的模型可能会有所帮助。

如何对我的模型进行同样的操作?

显然,我们在开源库中实现了这种方法。要使用它,您应该将模型应用程序数据准备为 pandas 数据框架,包括模型特征、预测和实际(目标)值。

如果您想要将模型在生产中的性能与您的训练数据或过去某个时期的数据进行比较,该库将使用一个或两个数据框架。

图片作者。

回归性能报告将生成一组模型性能图和一个误差偏差表。该表有助于探究特征值与错误类型和大小之间的关系。

您还可以快速对要素进行排序,以找到那些“极端”群体与“大多数”群体看起来不同的要素它有助于识别最感兴趣的片段,而无需逐个手动查看每个特征。

你可以在 Github 上阅读完整文档。

这个什么时候有用?

我们相信这种分析在您的模型生命周期中会有不止一次的帮助。您可以使用它:

  1. 对模型测试的结果进行分析。例如,一旦您在离线测试中或者在 A/B 测试或影子部署之后验证了您的模型。
  2. 对生产中的模型进行持续监控。您可以在每次运行批处理模型时这样做,或者将其安排为常规作业。
  3. 决定模特再培训。查看报告,您可以确定是时候更新模型了,还是重新培训会有所帮助。
  4. 在生产中调试模型。如果模型质量不合格,您可以找出模型表现不佳的部分,并决定如何解决它们。例如,您可以为表现不佳的细分市场提供更多数据,重建您的模型或在其上添加业务规则。

如果想要一个实际的例子,这里有一个教程关于调试机器学习模型在生产中的性能:“如何在 20 天内攻破一个模型”。

作为一名数据工程师,向微服务学习

原文:https://towardsdatascience.com/learning-from-microservices-as-a-data-engineer-1334ce13876c?source=collection_archive---------10-----------------------

专业化的软件是不是更好的软件?

为什么软件工程师转向微服务,我们如何从他们的经验中学习📖

我能找到的最好的独角兽😄,照片由 马克·格兰西 发自 像素

闪购独角兽

早期的 Gilt.com,一家专门从事时尚单品闪购的网购网站(及手机 app)👠:该技术是一个由 PostgreSQL 数据库支持的用 Ruby On Rails 编写的大型应用程序。

有一段时间,它使 Gilt 能够快速移动,因为所有的东西都在一个地方,并且很容易对架构进行推理。

然而,当吉尔特变得超级受欢迎时,问题开始了…

flash 销售的性质造成了流量高峰,这最初在很大程度上由于云的按需资源和弹性(在这种情况下,AWS)而得以缓解,但是扩展 monolith 来处理高峰需要成本高昂的资源💸。

除了成本和稳定性问题之外,工程团队还在成长,让多个团队在单一应用程序的不同部分工作需要大量的协调来确保变更可以安全部署。

微服务

因此决定,单片应用处理的不同进程将逐渐转移到专门的小型服务,最终成为微服务(参见扼杀者模式)。这些服务将高度解耦,并通过版本化的显式接口进行通信:RESTful APIs。

这种新架构支持:

  • 每项服务都要单独扩展📈。
  • 每项服务都要单独部署📦。
  • 团队明确拥有 X 数量的服务。
  • 团队自治🏃 🏃‍♀.
  • 代码库更小,更容易被拥有它们的团队理解。
  • 通过 API 和 API 版本化,不同团队之间可以更好地协作。
  • 微服务将分别进行框架和语言更新。

使用微服务的组织优势,我简单地称之为“快速和自治”,在这篇博客文章中,在领域驱动开发的背景下进行了广泛的探讨:

**https://medium.com/datadriveninvestor/if-youre-building-microservices-you-need-to-understand-what-a-bounded-context-is-30cbe51d5085

为了更深入地了解 Gilt 的微服务方法和经验教训,我建议您观看 QCon 上的 约尼·戈德堡*演示 *

2017 年,我加入了 Gilt.com 的数据团队

那时,有超过 100 个微服务。事实上,一些微服务被进一步分解成更小的应用程序,称为“lambdas”。我想强调的是,管理超过 100 个微服务是一项艰巨的任务,它只对一定规模的组织有益。在您开始下一个绿地项目之前,微服务阅读:

*https://www.martinfowler.com/bliki/MonolithFirst.html

我在这里的目的不是宣称微服务是银弹!🙅‍♂

他们有自己的问题,例如:

  • 由于多个微服务相互作用和相互依赖,提供开发/测试/集成环境变得更加困难。
  • “调用堆栈”可能很复杂,因为一个操作可能会导致对不同微服务的多次调用。
  • 将代码库分成不同的微服务会产生开销,例如,需要设置不同的包,设置 CI/CD 资源…
  • 网络/CPU 不是免费的!“太小”的微服务由于需要发出所有请求而表现不佳。

相反,我的目的是强调整体架构中固有的问题,以便我们在开发数据解决方案时能够注意到这些问题。⚠️*

它与数据工程有什么关系?

在数据工程中,今天,我们倾向于创建更少的服务,并在框架中实现逻辑(如 Airflow、Spark、Flink……)。但是有些原则仍然是正确的:

  • 一个软件的范围应该被清晰地定义,并且容易推理:松散定义的范围会导致你的应用程序变成一个整体。
  • 清晰的团队边界和所有权允许团队更快地前进。
  • 较小的应用程序允许更细粒度的扩展。
  • 更小的应用程序使得“尽早发布,经常发布”更加安全,不仅是团队开发的代码,还有库更新和编程语言更新。
  • 较小的应用程序更容易将逻辑“组合”在一起,或者换句话说:增加可重用性。🙌

将这些原理应用于气流

Apache Airflow 是一个流行的调度程序和数据管道创作框架。它也是一个“模块化的整体”:一个做很多事情的应用程序,,但是组件有明确定义的角色。

气流由以下物质组成:

  • Web 服务器。
  • 工人。
  • 得益于 Airflow 2.0 的多重调度程序😀。
  • 定义任务如何在基础设施上运行的执行者。
  • 定义任务如何连接到外部服务的挂钩。
  • 定义任务执行期间发生何种工作的操作员/传感器。

两年前,当我开始使用气流时,运营商对我发出了警告🚩。当我们在操作符中编写转换、提取和加载逻辑时,我们将许多有价值的、可重用的软件锁定在了 Airflow 中。为了使用这些组件,其他团队被迫依赖或直接使用气流。

我们最终还会引入依赖性,这可能会很快堆积起来并产生冲突。

借鉴微服务,我认为将我们自己限制在触发和监控在气流的之外部署和管理的应用的操作员是一个更好的模式。

杰西卡·拉夫林写了一篇关于 Bluecore Engineering 转向 KubernetesPodOperator 并将他们的逻辑打包到容器中的非常详细的帖子,这是实现这一目标的一种方式。

*https://medium.com/bluecore-engineering/were-all-using-airflow-wrong-and-how-to-fix-it-a56f14cb0753

在 Spark 上重复过去的错误

在 Gilt,当我们采用 Spark Scala 时,我们创建了一个单一 Scala 项目。我们构建的不同管道依赖于共享类,共享类将为 Spark 会话定义助手和实用程序,读取/写入默认值和用户定义的函数。

因为所有的数据管道由于它们共享的项目而紧密耦合,所以我们必须在更新 Spark 时迁移“ All or Nothing ”。这在 Spark 中尤其令人痛苦,在某些负载和资源配置下会出现错误,因此我们希望在发布之前在生产条件下测试整个项目。

我们只有两个团队在 Spark 项目上工作,我想除此之外,更新一个完整的 Spark 项目需要大量的协调工作,特别是当错误可能出现在推进更新的团队不拥有和不理解的管道中时。😢

回过头来看,每个团队或者每个管道都应该是自己的 Spark 项目,我们可以单独更新和打包。共享助手库的有用性并没有超过管道中共享依赖所带来的问题。

注意,拥有独立的项目会带来开销,就像微服务一样。

当将应用程序分割成更小的部分时,考虑您的团队结构、团队规模,以及如何减少管理小项目的开销。例如,如果您有许多数据管道和小团队,为新项目创建模板将会很有价值。共享的 CI/CD 逻辑 or/和 Monorepo 设置也会有所帮助。

打破数据仓库

数据工程中软件的专门化和解耦可以从从前云数据仓库到新的数据湖库系统的演变中看出。

下面是构成数据仓库的工具列表,它们实际上是“解构的”数据仓库:

  • 特殊文件格式(如 Avro、Parquet)。
  • 分布式文件系统(例如 S3、GCS)。
  • 元数据存储(例如,Hive Metastore)。
  • 计算引擎(例如 Spark、Presto)。
  • 事务层(例如,德尔塔湖、阿帕奇胡迪)。

我想象新一代的专有云数据仓库产品的结构也是由专门的组件组成的,甚至可能使用我刚刚列出的开源工具的某个版本,但是对这些架构的可见性有限(所以我只能猜测😃).

最后

作为数据工程师,我们可以从微服务架构旨在解决的问题中学习,并意识到紧密耦合软件的危险。

我个人觉得有趣的是,现代数据堆栈中的趋势也正朝着模块化专用组件发展,这种趋势我们在后端工程中已经看到,但在具有“微前端”的前端中也是如此。🤔

所以,保持简单,也许小?

附加 Gilt 微服务资源

我想再分享一些 Gilt 校友发给我的 Gilt.com 资源(谢谢!!)

这位土耳其大师说,在 Kaggle 上,向他人学习是成功的必要条件

原文:https://towardsdatascience.com/learning-from-others-is-imperative-to-success-on-kaggle-says-this-turkish-grandmaster-d8b5bf28ac87?source=collection_archive---------24-----------------------

与 Fatih oz Turk 的对话:数据科学家和 Kaggle 竞赛大师。

作者图片

在这一系列采访中,我在 H2O.ai 展示了一些知名数据科学家和 Kaggle 大师的故事,他们分享了自己的旅程、灵感和成就。这些采访旨在激励和鼓励那些想了解成为一名 Kaggle 特级大师的人。

在这次采访中,我将分享我与法提赫·厄兹图尔克的互动。他是 Kaggle 竞赛的‘特级大师数据科学家atH2O . ai。Fatih 以优异成绩获得伊斯坦布尔博阿齐齐大学工业工程学士学位。在加入 H2O.ai 之前,他在 UrbanStat 担任数据科学家。Fatih 大约四年前加入 Kaggle,并赢得了七枚金牌,包括一枚单人金牌。他也是讨论层的主要成员。

在这次采访中,我们将更多地了解他的学术背景、他对 Kaggle 的热情以及他作为数据科学家的工作。以下是我与 Fatih 对话的摘录:

你有工业工程的背景。是什么促使你选择数据科学作为职业?

:我在工业工程领域的主要工作是运筹学、供应链和统计学。除了这些主课,我们还可以根据自己的兴趣选择具体的选修课。在我最后一个学期,我选修了“数据挖掘”这门课。选择这个选项的原因之一是它的受欢迎程度。在学习数据挖掘的时候,我第一次接触到随机森林、分类、预测事物等概念。我发现这很有趣,类似于玩一些竞技游戏。我意识到我的激情在于数据分析领域,我立即知道我毕业后必须从事什么领域。

你和 Kaggle 的幽会是如何开始的,是什么让你在你的大师之旅中一直保持动力?

法蒂赫的卡格尔轮廓

法提赫 :我的第一份工作是在一家科技初创公司做的初级数据科学家。我是那里唯一的数据科学家,我们只为那里的保险相关公司工作。加入公司几个月后,我的老板在 kaggle 上发现了 Porto Seguro 竞赛 ,他问我是否可以看看,因为这是一个保险用例。我对我在比赛中的发现很满意,因为我看到人们分享了很多。所以在那场比赛中,我意识到两件主要的事情:

  • 当我在内核和讨论的时候,我的学习率要高得多。
  • 我好胜的一面被触发了,我了解到我非常喜欢竞争。

在 kaggle 上竞争和学习是齐头并进的。这是我参加任何比赛的主要动机。成为大师或特级大师只是这个过程的自然结果。

能告诉我们一点你最喜欢的 Kaggle 比赛吗?

Fatih :我喜欢 房屋信用违约风险 比赛。数据集没有完全匿名,因此有很大的空间进行特征工程。试图理解竞争的领域,然后能够生成有用的功能是有趣的。此外,我们的团队有一个很好的验证策略,最终在私人排行榜上非常成功。我们从公共排行榜的第 29 位上升到了私人排行榜的第 10 位。

你通常如何处理一个难题?

Fatih : 对于任何比赛,我的第一个尝试总是有一个可靠的验证方案在我这边。有一个良好的相关 CV-LB 关系就是一切。那么如何实现这个呢?这主要取决于正确的探索性数据分析(EDA)。弄清楚测试集与训练集有什么不同(如果有),然后在您的验证方案中模仿这一点是一个很好的起点。除了用图和数字做 EDA,我还检查这方面的对抗性验证分数。

有了一个好的验证策略后,我会专注于寻找没有在公共论坛上分享的有用的东西,因为拥有不同的技巧对于最终获得好的排名至关重要。

对于任何竞争,我的第一个尝试总是有一个可靠的验证方案在我这边。有一个良好的相关 CV-LB 关系就是一切

你能让我们先睹为快吗,比如你最喜欢的编程语言、IDE、算法等等

法提赫 : 我使用 Python,并且大部分时间都在使用 JupyterLab。我也有一个 Google Colab pro 账号来访问 GPU,因为我没有本地账号。我发现这是一项不错的投资,因为我们在 Kaggle 笔记本上每周的 GPU 时间有限。

我最喜欢的建模算法是 Lightgbm。我仍然认为这是一个非常有效和生产友好的算法,因为它很容易调整,也能很快得到足够好的分数。

你经常在 meetup 活动中发言。土耳其及其周边地区的数据科学前景如何?

Fatih 是伊斯坦布尔技术周活动的发言人之一

Fatih :我发现在土耳其人们对数据科学的兴趣相当值得注意,而且每天都在增加。越来越多的学生选择计算机科学作为他们的专业,而不是其他工程专业。这种流行的主要原因是数据科学在每个行业的整体采用。

我在 kaggle 比赛中遇到的土耳其人的数量也在快速增长。这是温暖人心的,因为几年前不是这样。类似的情况也反映在 meetup 社区中。活动的数量和参与的学生人数也在迅速增加。最近,很多土耳其公司开始在 Kaggle 上举办同类比赛。

作为 H2O.ai 的数据科学家,你的角色是什么,你在哪些具体领域工作?

Fatih 和 H2O.ai 的其他 kaggle 大师们

Fatih : 我参与了 POCs 和其他客户相关的项目,帮助他们从无人驾驶 AI 中受益更多。此外,我通过 Wave 框架开发新应用,并用新数据集测试无人驾驶人工智能。

由 Fatih 创建的 ExploRNA wave 应用程序。你可以在这里阅读更多关于 app 的内容。

数据科学领域正在快速发展。你是如何设法跟上所有最新发展的?

Fatih :我认为社交网络是其中的关键。仅仅靠你自己是几乎不可能保持最新的。然而,如果你有合适的空闲频道,并且有一个有意义的 LinkedIn feed,那么关注新闻就更容易了。。除此之外,参加 kaggle 竞赛和定期关注竞赛论坛是另一个有用的资源。

2021 年你打算如何度过在 kaggle 的时光?你想达到什么特殊的里程碑?

法提赫 : 我想参加 2021 年的计算机视觉比赛。我很高兴能在这些比赛中作为单人选手进入前 50 名。当然,作为一个团队获得金牌也是很棒的。😃

对于刚刚开始或希望开始数据科学之旅的数据科学有志者,有什么建议吗?

:我建议不要太担心诸如从哪里开始、学习哪些课程、学习哪些工具等问题。与其一开始就处理所有这些问题,不如直接投入到一个数据科学项目或竞赛中,学习他人的代码。这是我早期通过弄脏自己的手来提高自己的方法。分析其他人的代码,并提出类似这样的问题——这段代码在这里是做什么的?作者为什么这样编码?它对这个项目/比赛有什么帮助?等等是让我磨练技能的一些方法。下一个任务是回答这些问题。人们既可以在网上寻找答案,也可以利用论坛。

Fatih 的 Kaggle 的成就反映了他对解决问题的热情和对努力工作的一贯爱好。他如何从工业工程过渡到数据科学,然后在两年内获得 Kaggle 特级大师的头衔,这是值得称赞的。

阅读本系列的其他采访:

学习图表 QL

原文:https://towardsdatascience.com/learning-graphql-4e913f12640d?source=collection_archive---------29-----------------------

深入探究 API 的查询语言

马库斯·斯皮斯克在 Unsplash 上的照片

不久前我写了一篇关于 GraphQL 和 REST 区别的文章。虽然我对 GraphQL 做了一些研究以形成比较,但我发现这种查询语言可能非常强大,但有一个陡峭的学习曲线。有几个概念,比如只有一个端点,让我觉得在尝试使用 GraphQL 之前,我们需要更多地了解它。

当对它了解得更多时,不仅要知道什么时候使用 GraphQL 是理想的,还要知道它的优点和缺点。此外,我们需要理解一些“怪癖”,主要是语法方面的。然而,我们不会深入研究语法,因为这与其说是一个教程,不如说是一个概述。但是一旦我们有了一个好的基础,以后请留意我的指导。

基本意图

GraphQL 是 API 用来从数据库中查询信息的语言。这被认为是中间层,因为数据能够显示在前端网页上。GraphQL 的目标是成为一种查询语言,允许开发人员只收集他们需要的数据,仅此而已。它还旨在运行时更快。作为一个给定,结果应该是预测的,这意味着数据没有意外改变或收集不正确。使用 GraphQL,查询运行得很快,因为它们只收集必要的信息,而且很稳定,因为它控制数据,而不是由服务器控制。

GraphQL 实现了一个使用模式定义语言(Schema Definition Language,SDL)语法定义 API 模式的系统。这意味着在它的语法中,您可以创建必需的字段,构建图表版本的表,甚至定义两个表之间的关系。

使用单个端点

正如我在比较文章中提到的,GraphQL 使用单个端点。对于其他典型的查询语言,比如 REST API,我们通常会为每个表请求创建一个端点。例如,给定一个表,您将创建一个端点来选择、插入、更新和删除。这将是四个独立的端点。那将是每张桌子。然而,对于 GraphQL,您只为每种类型创建一个端点,包括不同的表。

所以,这是我发现有点困惑的一个痛点。如果只有一个端点,那么我们如何区分哪些表正在被更新,或者哪些表可能被选中?经过一点研究,我发现了一个教程,可以演示这是如何工作的,但还没有完全投入进去。

对于单个端点,我们也在主体中发送单个参数。这个参数是“query”,我们通过它发送我们想要采取的任何 GraphQL 动作。例如,如果我想从我的样本表中获取或选择所有内容,我首先创建我的 GraphQL 代码,测试它,当我知道它可以工作时,复制它作为测试主体中的值。这将把查询作为键发送,代码作为值发送。还和我在一起吗?这看起来有点令人困惑,但我认为稍加练习,这将非常有用。

查询灵活性

另一个需要注意的关键点是,GraphQL 在查询方面要灵活得多。使用 REST API,如果您想从表中获得更多/更少的列,您需要创建一个全新的端点来处理该请求。使用 GraphQL,我们只需改变通过参数发送的变量。对于移动开发,这是 GraphQL 的一个主要用途,这对速度和使用该应用程序的电池寿命都有好处。

理解类型

GraphQL 使用类型系统来描述模式的形状。然而,这描述了更广泛的定义。首先,类型可以指数据类型,比如 Integer 或 String。一个类型也可以是另一个表的类型,这会创建一个关系。类型也指被描述的表本身。

然而,类型不仅仅是数据。例如,查询和变异也是类型。这是因为它描述了正在做的事情。

对于值,另一个需要考虑的重要事项是考虑可空性。默认情况下,GraphQL 的类型系统允许任何值都可以为 NULL。这意味着如果没有任何明确的说明,值可能为空。这可以减少请求中的失败。但是,空值可能会导致问题,因为某些数据是必需的。有很多方法可以使列成为语法中必需的,只需简单地添加一个感叹号(!)在数据类型旁边。比如“Int!”。这将要求整数有一个值,而不是可空的。所以,这是一个很容易解决的问题,但是我必须考虑一下,因为我使用的所有东西都不是空的,除非特别说明。

突变

对于 API,我们需要有改变数据的能力。这可能表示更新、插入或删除。这种突变类型可能类似于一个函数,在这里它被声明为一个突变,给定参数,然后调用表,然后将必要的列设置为变量值。这使得突变仍然在单个终点完成。

图表语法

GraphQL 有一个利用图形的独特语法。这意味着您可以写出您的模式,在其中声明不同的节点类型。在这些节点中,您还可以确定是否要定义节点之间的任何关系。在 GraphQL 中,节点就像数据库的表,而模式就像 DBMS 一样表示结构。这个语法非常类似于 JSON。

使用什么数据库

正如前面在类型中提到的,可以通过将一个条目的数据类型用作另一个表的类型来声明关系。因为关系存在这种可能性,所以关系数据库是 GraphQL 的一个非常有效的选择。然而,对于 RDBMS 来说,它就不那么具体了。它可以是你喜欢的任何东西。这是因为 JSON 语法是通用的,允许更容易地连接到其他数据库管理系统。

虽然关系可以包括在内,但这并不意味着 NoSQL 是不可能的。就像选择 RDBMS 一样,选择 NoSQL DBMS 也是通用的。只要你对这些怪癖做了正确的研究,你想使用的任何 DBMS 都有可能与 GraphQL 一起工作。

结论

本文概述了什么是 GraphQL,以及如何使用它。GraphQL 是一种功能强大的查询编写语言,采用语法定义语言(SDL)风格。该语法特定于 GraphQL,它是一种图形格式。这个图看起来很像 JSON,很容易适应各种 DBMS 或构建表之间的关系。

虽然功能强大,但 GraphQL 确实有一点学习曲线。具体来说,GraphQL 只使用一个端点。这是因为您不是设置不同的端点,而是发送一个包含图形代码的查询变量,并将其直接发送给 API。

GraphQL 使用类型系统来定义我们的模式。这包括数据类型、可能的关系、表,甚至数据是否会被查询或变异。突变包括插入新数据、更新现有数据,甚至删除不再需要的数据。

尽管有学习曲线,GraphQL 似乎是一种有趣的 API 查询语言。尽管我们已经在 GraphQL 和 REST API 的比较文章中简要讨论了 GraphQL,但这是一个更深层次的探索,我们学到了更多,特别是关于语法,而没有做任何编码。然而,下一步将是通过编码来学习。但是那将不得不等待另一天,所以将来在这里寻找 GraphQL 教程。在那之前,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想看完介质上的所有文章?成为中等 成员 今天!

查看我最近的文章:

[## 一头扎进 Dash

towardsdatascience.com](/a-dive-into-dash-ed5561f11021) https://python.plainenglish.io/getting-the-weather-with-python-dce8f20331fd https://python.plainenglish.io/build-your-own-plex-client-using-python-11cf2e566262

参考资料:

https://graphql.org/ https://www.freecodecamp.org/news/a-beginners-guide-to-graphql-60e43b0a41f5/ https://graphql.org/learn/ https://graphql.org/learn/best-practices/ https://www.howtographql.com/basics/2-core-concepts/ https://blog.couchbase.com/creating-a-graphql-application-with-node-js-and-a-nosql-database/

通过例子学习熊猫

原文:https://towardsdatascience.com/learning-pandas-by-examples-8105771c723c?source=collection_archive---------19-----------------------

Python 熊猫库的有用、有趣、鼓舞人心的用法概要

托尔加·乌尔坎Unsplash 拍摄的照片

来说说熊猫套餐吧。

当你浏览 Stackoverflow 或者阅读《走向数据科学》上的博客时,你有没有遇到过一些超级优雅的解决方案(可能只有一行),可以代替你的几十行代码(对于循环、函数)

我经常遇到这种情况,我经常想,“哇,我不知道这个功能可以这样使用,真是太神奇了!”不同的人肯定会有不同的兴奋点,但我敢打赌,如果你曾经在应用数据科学领域工作过,这些时刻一定会发生在你身上。

然而,令我困惑的一件事是,没有一个地方或储存库来存储和记录这些鼓舞人心的时刻和相关的现实世界的例子。这就是为什么我想主动构建一个 GitHub 知识库,专注于收集这些有趣/令人印象深刻的用法/例子,特别是在 Pandas 库中,让你想大声喊出来

以下是存储库的链接:

https://github.com/frankligy/pandas_by_examples

现在我将向您展示发生在我生活中的两个具体例子,以及为什么我认为拥有这样一个知识库会有所帮助。

我的熊猫 60%的编码错误归因于忽略了“dtype”

dtype是一个特殊的对象,即每个熊猫数据框的列、系列和索引对象的属性,它通常是自动确定的,所以我通常会忘记这个隐藏属性的存在,这导致了很多意想不到的错误。

例如,让我们创建一个数据框:

df = pd.DataFrame({'col1':[1,2,'first'],
                   'col2': [3,4,'second'],
                   'col3': [5,6,'third']})

然后我删除了第三行,因为它们都是字符串,我只需要数值来绘制热图。

df = df.iloc[:-1,:]

现在,我可以使用df数据框绘制热图:

import seaborn as sns
sns.heatmap(df)

我们得到了一个错误:

TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

你可能想知道这是为什么?我们来看看dfdtype:

df['col1].dtype# dtype('O')

它是“object”类型,而不是“int ”,即使该数据框中的所有值都是整数。原因是 dtype 是从原始数据框中推断出来的(第三行是一个字符串,强制每一列的 dtype 变成“object”),你去掉最后一行,但是 dtype 不会自动改变

我们将 dtype 更改为 int 并再次绘制热图,

df = df.astype('int')

输入数据框列应为数字

所以我推测这是一个容易陷入的陷阱,值得在某个地方强调一下,我创建了一个的例子来告诉你在使用熊猫时指定dtype的重要性。这只是一个超级基本的例子,但包含了关注dtype变量的关键思想。

https://github . com/frank ligy/pandas _ by _ examples/blob/main/examples/3 _ Learning _ dtype . ipynb

让我们看另一个例子:

如何将两列转换成一个字典?

这是我最近遇到的一个真实世界的例子,在这里我把这个问题简化了一点。想象我们有一个这样的数据框:

我们拥有的数据框架

我想要一个像这样的 python 字典:

我想要的 Python 字典

为了描述这个问题,在真实环境中,它实际上是一个有几十万行的巨型数据帧,因此我们肯定希望有一个自动解决方案来实现这一点。

您只需使用一行代码就可以实现:

df.groupby(by='nationality')['names'].apply(
**lambda** x:x.tolist()).to_dict()

它是如何工作的?我在我的 GitHub 示例中有一个逐步说明,

https://github . com/frank ligy/pandas _ by _ examples/blob/main/examples/5 _ columns 2 dict . ipynb

我把它粘贴在这里:

将两列转换为字典

结论

这篇文章的真正目的是让你明白为什么我要创建这样一个来存储 Python Pandas 库中那些令人印象深刻的用例。我会不断更新和添加我在日常工作中遇到的例子。如果您同意我的倡议,如果您也愿意为此做出贡献,我将不胜感激,只需简单地提交一个 pull 请求,这样我就可以将您的示例合并到存储库中。我希望这个知识库能够成为编程初学者和中级数据科学家每天都喜欢查看的地方,并能给他们带来方便。

存储库链接:

https://github.com/frankligy/pandas_by_examples

感谢阅读!如果你喜欢这篇文章,请在 medium 上关注我,非常感谢你的支持。在我的 TwitterLinkedIn 上联系我,也请让我知道你是否有任何问题或你希望在未来看到什么样的熊猫教程!

数据科学的学习途径—你应该学什么?

原文:https://towardsdatascience.com/learning-pathways-for-data-science-what-should-you-learn-a0a580a705a2?source=collection_archive---------17-----------------------

简要概述您应该学习什么来熟悉数据科学

(src =https://pixabay.com/images/id-868715/

介绍

数据科学领域非常庞大,涵盖了广泛的主题。数据科学角色的范围可以从主要涉及统计的工作到完全基于统计的工作。在数据科学的奇妙世界中,有许多主题是任何有抱负的数据科学家至少应该熟悉的,如果不是精通的话。面对所有这些话题,很难找到一条教育之路,甚至很难找到一个好的起点,开始走上正确的道路。

数据科学有许多不同的途径,其中一些途径会比其他途径更容易进入。不管你决定选择哪种专业来让自己步入正轨,对于数据科学家来说,跨领域学习通常都是很好的建议。幸运的是,我们有一个共同的起点,可以为数据科学的各个方面打下坚实的基础。

共同的起点

在数据科学的大多数(如果不是全部)应用中,关键词将是数据。数据是几乎所有数据科学应用的重要组成部分。开始数据科学教育的一个好地方是数据教育。数据实际上是一个非常宽泛的话题,你可以花上几周的时间单独研究它。干净的数据将不仅是机器学习的重要资产,也是提供精确分析的重要资产。此外,了解不同的数据类型如何应用于统计以及如何收集数据是一个很好的起点。

我想说唯一比这第一步更重要的事情是真正知道如何使用电脑。这并不意味着知道如何启动应用程序和搜索网页,而是像目录和文件分配表的概念。为了处理你的文件和数据,你需要了解数据是如何存储在文件中的,以及互联网本身是如何工作的。

不同的道路

一旦您牢固掌握了数据以及如何使用数据,掌握您在数据科学世界中可能接触到的不同途径就会变得容易得多。你想要应用你所拥有的数据科学技能的方式将是决定你的教育方向的最重要因素。如果你最终选择了一条你并不喜欢的道路,你也不太可能喜欢学习这条道路。数据科学技能非常多样,用途也非常广泛,不久前我在一篇文章中详细介绍了这一点,如果您感兴趣,可以在此处查看:

分析学

我想谈的第一条路是数据科学家可以走的,那就是分析师的路。分析师通常更倾向于统计,通常很少涉及计算机科学领域的概念。也就是说,对于分析师来说,还有许多突出的商业和经济应用。拥有机器学习技能的基础也有利于这些领域。

分析的一个伟大之处在于,有多少工作利用了适用于标准分析师的完全相同的数学和技能。例如,许多数据科学家利用分析技能来跟踪他们的个人投资、股票和经济。此外,对于普通应用科学来说,分析是一项非常重要的技能,这也是我的许多应用科学学士所围绕的问题。统计学是一个强有力的工具,对于赚钱来说,它甚至更有价值,因为我们生活在一个基于统计推断的世界里。

也就是说,我认为开始分析的最好方法是熟悉数据和统计。统计数据将成为发现真实资产的最有价值的资产,这当然是值得拥有的知识——不管是不是数据科学家。希望专注于这方面学科的数据科学家可能还希望拥有商业经验,或者非常擅长将数据和统计数据应用到他们希望呈现的想法中。

机器学习

大多数数据科学家可能因为对机器学习感兴趣而进入该领域,然而,机器学习和成为机器学习工程师有许多不同的方面经常被忽略。这些都是我认为需要先看的方面。一个新兴的数据科学家不太可能进入这个领域,直接投入到创建明天的机器学习模型的任务中。相反,很多工作实际上是路由、争论和处理数据。自动化也是数据科学这一方面的重要组成部分。

为了开始机器学习,我想说最大的技能或教育可能是计算机科学。与数据科学的其他应用相比,计算机科学在这里会更方便,因为你更有可能从事算法方面的工作。理解计算机和应用程序如何工作对于创造伟大的算法至关重要。当然,统计数据在这方面也发挥了相当大的作用,所以重要的是要记住,所有这些路径都会触及到其他路径的各个方面。

端点应用

另一种常见的数据科学家是我所称的“Web 开发科学家”虽然数据科学的这些应用不是 web 开发,但是它们直接应用于 web 开发和软件工程。这些类型的数据科学家与软件工程师团队一起工作是很常见的。

这个角色比其他人需要更多的与外部资源的合作,然而一个很大的好处是你最终可能一起工作的人通常了解技术,这可能是作为一个业务分析师的一个缺点。对于这个方向,计算机科学知识肯定是适用的。我还想说,这可能是数据科学最容易理解的形式之一,仅次于数据工程。对于那些想要进入机器学习领域,但可能没有学位或那么多技能的人来说,这也可以作为一个很好的切入点。

数据工程

我想回顾的数据科学领域的最后一条道路是数据工程师。与创建和部署端点的数据科学家类似,数据工程师的角色非常容易获得。数据工程师通常是那些在机器学习工程师之下进行激烈争论的人,他们通过提供足够的数据进行训练,使他们的奇妙模型成为可能。这当然是一个很酷的数据科学应用!

可能专注于分析或机器学习的数据科学家与数据工程师或主要从事端点工作的数据工程师之间的一个关键区别是统计数据。与可能从事分析或机器学习工作的人相比,数据工程师需要的统计知识要少得多。这也是在没有学位的情况下进入这个领域的一个很好的方式,可以说是为了磨练你的技能和“沿着阶梯向上爬”。

结论

数据科学是一个包含多个其他学科的巨大领域。这可能很复杂,看起来有点不可能进入,但有许多不同的路径,你可以选择简单的起点和有益的结局。这是数据科学的另一个伟大之处,因为您可以经常选择您可能碰巧特别感兴趣的内容,而不是在您可能不特别喜欢的方面工作。我希望这篇文章对您有所帮助,或许能为您的数据科学之旅指明正确的道路。谢谢你的阅读,我真诚地希望你有一个美好的一天!

学习力 BI

原文:https://towardsdatascience.com/learning-power-bi-f06d95119f28?source=collection_archive---------25-----------------------

我用来不断学习和掌握 Power BI 的最喜欢的资源

Unsplash 上的窗口拍摄

对于我遇到的那些学习能力 BI 的人来说,最常见的问题之一与 有关,从 学习的最佳资源是什么。

有很多很棒的博客、YouTube 频道和各种社区成员在学习开发 Power BI 数据集和报告时发布了很棒的提示和技巧。在本文中,我将列出我在学习该工具的过程中遇到的一些我最喜欢的工具。资源将被分类,大致从后端到前端。

电源查询

构建 Power BI 数据集的第一步是获取和转换数据。这就是 Power Query 的用武之地——工具的这一部分允许您从各种来源(csv、SQL 等)获取数据,并在加载到模型之前进行任何转换。

  1. Alex Powers 和 30 天查询(T9):Alex 精通 Power BI 的所有知识,但我从他那里学到了很多 Power 查询和 M 代码领域的知识。他提出的一个倡议是 30 天查询挑战,在 30 天内每天解决一个问题,尝试不破坏查询折叠。你可以在 Twitter 上关注他,在这里了解更多关于 30 天查询挑战的信息。
  2. 马修·罗氏:马修的文笔很棒,你可以在这里找到他的博客。他关于 Power BI 中的数据流(想想服务中的 Power Query)的文章有助于理解和巩固一般概念,以及如何将知识应用于构建企业级解决方案。

DAX 和数据建模

DAX 是一种公式语言,用于在数据集中创建计算列和度量值。我还将围绕数据建模(表之间的关系、基数、构建星型模式、定义数据类型等)对资源进行分组。

  1. 对于 Power BI 中的万物 DAX 和建模数据,我最喜欢的是 sqlbi 。他们的文章深入探讨了这些领域和其他领域的概念。他们也有很棒的书籍和视频课程,我强烈推荐。
  2. 菲尔·西马克的 博客 非常棒,在深入研究性能优化和更复杂的聚合场景时,它真的非常有用。如果你想突破性能极限,优化数据集,Phil 的博客是一个激发灵感的好地方。

前端设计

创建性能良好且关注最终用户体验的交互式报告尤为重要。

  1. Chris Hamill 的 博客 在报表设计领域有很好的概念。创造性地使用书签,提高前端渲染性能,以及许多其他概念都涵盖在他的博客和相关作品。
  2. Reid Havens 在他的 YouTube 频道上报道了一些关于建立权力的很棒的技巧和诀窍。

万物动力 BI

  1. 方盒里的家伙:这个 YouTube 频道涵盖了所有 Power BI 的东西。这是一个很好的学习方式,也是了解最新发展和学习技巧的好方法。
  2. 微软的 Power BI 博客可能是保持产品发布领先的一个好方法。我建议做书签,并定期返回,以了解所有最新进展。每个月都可以看到新的功能,这有助于保持所有功能的顶部。你可以点击查看博客

这就是我的首要任务。这绝不是详尽无遗的——有大量精彩的资源。有自己喜欢的吗?在评论中发帖帮助他人。

原载于https://data stud . dev

从 Python 中学习 R——我希望一周前就知道的 5 课

原文:https://towardsdatascience.com/learning-r-from-python-5-lessons-i-wish-i-knew-a-week-ago-78e312aca37a?source=collection_archive---------7-----------------------

(或者,为什么我希望我读过这些文件)

经过很多很多的抗争,上周我终于决定是时候完全停止使用 Python 了,并且弄清楚我一直听到的这些 R 废话。关于哪一个最好的文章数不胜数,所以我不会在这里重复——足以说你不能在两者中做任何事情——但是有一些小问题,我希望我在开始之前就已经知道了。相反,我做的是一头扎进去,写了一些非常非常乱的代码,探索在伦敦 COVID 封锁下入室盗窃和抢劫是如何转移的。

记住这一点,下面是我希望在开始编码之前知道的 5 件事。希望你会发现它很有用,不会像我一样对其中一些感到沮丧。

凯利·西克玛Unsplash 上拍摄的照片

1.Python 是宽泛的,R 是“专注的”——所以使用核心工具,不要担心

Python 是所有人的一切——它是一种语言的庞大生态系统,可以做任何事情,从训练你的神经网络到托管你的网站到驱动你的机器人。

r 是而不是那个。虽然它可以通过正确的推动来建立你的网站,但它首先是一个研究和分析的工具……这意味着你在探索 Python 时面临的许多选择在 r 中是不存在的。这是一个祝福。你将和其他人一样使用同样的工具,而他们只是工作

你见过多少没完没了的帖子问什么是最好的 Python IDE?你应该用康达还是皮普?蟒蛇核心还是康达锻造?有一百万个问题,很少有一个“正确”的答案,因为这取决于你在做什么。

在 R 中,没有这些:您将下载现成的 R(有一个例外,我稍后会谈到),并且您将运行 R studio。一切都会好的,而且会很棒。当你导入一个库时——有一个图形界面和一切——你将全局导入。90%的情况下,你会没事的。

r 笔记本使代码和漂亮的可视化结合变得容易(图片由作者提供)

R 中的核心工具集是主动维护的、免费的、为研究而构建的,非常棒。从那里开始就可以了。

2.你可以在 Python 中搜索任何东西——你可能需要更广泛地搜索 r。

如果你和我一样,你会在谷歌上搜索很多你知道应该存在的函数,但是你不太记得它的代码。“只删除第一个重复的行”、“删除列名中的空白”……你知道,你可能应该只需要弄清楚,但是从第一个堆栈溢出帖子中抓取一些快速代码更容易。在 Python 中,会有 100 个帖子符合你的确切需求。R 中可能没有 100,有时你可能根本找不到。

很难衡量这一点——毕竟,R 的栈溢出问题几乎是熊猫的两倍——但我发现快速获得非正式答案比我想象的要难得多。对于教程来说也是如此:在 Python 中有数以千计的中型帖子带你通过训练随机森林,而在 R 中则少得多(尽管这部分归因于搜索单个字母有多难)。

我怀疑这反映了人们的学习方式:R 是由学者和统计学家教授的,而 Pandas 是由像我这样的半程序员黑客爱好者选择的(无意冒犯任何一方)。后者生活在谷歌上,前者有图书馆、教室和课本。

好消息是,这些教科书通常是免费的,在线的,并且管理和策划得很好——事实上,甚至有完整的课程可以使用它们的内容,有些还可以作为互动教程。因此,花一个小时,浏览一遍教程,并考虑在深入研究堆栈溢出问题之前阅读一本真正的书。你可能不会后悔。我在下面留下了一个很棒的资源列表。

3.哦对了, Tidyverse

我知道,我知道…我说过你不需要担心工具集,但是我撒了一个小小的谎:Tidyverse 是证明规则的例外。

Tidyverse 是一个精心管理、维护良好的库生态系统,用于数据科学和 R 中的操作。事实上,如果您正在任何地方学习 R,您可能已经在学习 Tidyverse 了——最著名的 R 工具,如 ggplot2、dplyr 和 tibble,它们使数据操作和华丽的可视化变得轻而易举,都在 Tidyverse 中,所以不用太担心。如果你来自 Python,你可能想知道这些是否值得学习…不要担心。Tidyverse 很棒,它是必不可少的,而且你可能正在学习它。

4.笔记本还是很牛逼,但是有点不一样了

记得我说过你会喜欢 RStudio 吗?如果你在 Jupyter 笔记本上工作,那就更是如此了,因为 R Markdown 太棒了,稍加调整,RStudio 就是 Jupyter Lab 的绝佳竞争对手。

一旦你让 r studio打开一个笔记本,并在窗口中设置预览,你可能会发现一个非常熟悉的界面。你可以在 Markdown 中写笔记,添加图片,等式,每个单元格执行…你在 Jupyter 中做的任何事情都可以很好地翻译。您甚至可以在其中安装一个方便的文档查看器(这是我推荐的)。

有一些差异需要一些时间来适应。r 接受各种各样的格式,有些会在最后把你的文档“编织”在一起——可以随意选择,但是默认的 html_notebook 可能就可以了。被执行的代码也比我希望的更容易被删除,这需要一些时间来适应。根据您的需要,您可能想要探索缓存选项。

在某些方面,它也比好得多。R markdown 使得隐藏单元格的特定位,添加目录,以及生成漂亮的 HTML 或 PDF 文档变得如此容易。甚至还有一些很好的仪表板和网站功能。

在这种事情上,R 再次奖励一点耐心。阅读 RMarkdown 文档,了解更多选项,享受您的笔记本电脑。添加目录和一些参考资料。是可爱的

5.如果你只是一头扎进去,那也很好

尽管我遇到了很多麻烦,但从功能和结构的角度来看,R 和 Pandas 非常相似。敲击 Ctrl+Shift+Enter 和 Ctrl+Enter 永远不会让我停止困惑,当我发现决定“%>%”应该是一个基本代码段的人时,我可能不得不扔给他们一些东西——这到底意味着什么——但是如果你对 Python 很熟悉,你所知道的所有基本工作流和原则将会很好地翻译preeetty……当他们不喜欢时,去阅读文档。

希望至少其中一些是有用的!我当然不会为了日常的数据争论而转到 R,但是学习一个我觉得不再那么陌生的完整的 near 工具集非常有趣。愿你的笔记本编织得比我的快!

下面我整理了一些我发现并依赖的资源。如果你觉得它们有用,请看看作者/买他们的书/给他们发一封漂亮的电子邮件——它们都是非常宝贵的。

我觉得很棒的资源

普通 R 和犯罪

R 代表数据科学 - Garrett Grolemund 和 Hadley Wickham

R 代表犯罪学家 - 瑞卡·索利莫希

RStats-Ed 回购

数据营替代方案

制图和空间建模

数据科学家的空间建模- Francisco Rowe 和 Dani Arribas-Bel

犯罪地图在 R - 雷卡·索利莫希和胡安乔·麦地那

犯罪绘图课程- 马特·阿什比

深度学习模型的学习率

原文:https://towardsdatascience.com/learning-rates-for-deep-learning-models-e500efe09f2e?source=collection_archive---------14-----------------------

实践教程

如何通过优化让好的模型变得伟大

照片由斯蒂芬·彼得森Unsplash 上拍摄

eep 学习模式非常灵活,但要使其有效,还需要大量的关注。学习速度的选择至关重要。

本文是关于微调深度学习模型系列文章的第一篇。

本文将讨论学习率对深度学习模型的收敛性和性能的影响。使用的模型是一个简单的神经网络来展示学习率和学习计划之间的差异。

本文涵盖的主题:

  • 不同学习率和优化问题背后的直觉。
  • 指数衰减学习调度器。
  • 循环学习率调度程序。
  • 自定义学习率计划程序。

尽管深度学习模型很灵活,但要创建一个健壮的模型,你需要考虑你将如何训练模型。例如,一个灵活的、动态的模型可能具有非凡的性能,但是如果没有适当的时间和关注,结果是无法实现的。

有许多可能的方法来改进深度学习模型。其中包括激活函数、学习速率、优化器、批量大小、权重初始化的选择,以及深度学习模型的许多其他方面。

虽然每个选择对整个模型都至关重要,但这里只关注学习速率的选择。

学习率

通常,在讨论学习率时,您会看到如下图像。

学习率(好—左)和(太大—右)(作者照片)

函数是这个完美的抛物线,事情要么很好地收敛,要么疯狂地失去控制。不幸的是,这个例子太简单了,不能让你理解优化问题所面临的问题。

相反,让我们从没有学习率的数学表示开始。相反,想象你在山腰上。你的目标,找到最高山的最高点。

优化作为一种景观

问题是雾多得令人难以置信。你看不到山峰。你甚至不知道你在半山腰的什么地方。你只知道你站在哪里。寻找山峰最直接的方法是继续向上攀登。只要有可能,就继续向更高的地方走。

但是如果雾太浓,你甚至不能确定哪条路是向上的。这种方向性的缺乏就是优化技术使用梯度的原因。坡度给出了你所站位置的坡度。所以现在,尽管有雾,你知道哪条路是向上的。

带着你对前进方向的新认识,你想要朝那个方向前进。但是你应该迈出多大的一步。一个大跳跃?或者你的脚有点乱?记住,雾太大了,你不知道你会在哪里着陆。你只知道你现在所处位置的斜率。

决定如何迈步

但是你很自信你了解这个山坡。所以你跳了。突然,你发现自己在一个裂缝的底部。你刚刚走下悬崖,进入一个深深的裂缝。离山顶如此之远。

更谨慎的读者可能会想,“我们慢慢来,这样就不会发生这种事了。”。你避开了裂缝。但是你迈出的每一步都让你一事无成。所以你拖着脚步,花了很长时间才到达山顶。你甚至可能会中途放弃。

假设你坚持在每一步都进行大的跳跃。但是在这种情况下,没有大的裂缝。相反,你在创纪录的时间内迅速跃上山顶,大大减少了到达山顶所需的时间。

这些问题代表了小学习率和大学习率之间的权衡。你是想冒险掉下山坡,还是想冒险永远到达山顶?当然,这两种选择都有风险,但你可以选择。

迪伦·鲁德在 Unsplash 上的照片

山上的问题

然后,甚至有这样的场景,你正在爬山,你发现自己在山上的一个凸起处,一个小峰,这让事情变得更糟。步子迈得太小意味着你认为你已经找到了最高点。当你来回穿梭时,你的周围没有更高的点,所以据你所知,这是最高峰。迈出更大的步伐会让你摆脱这个小颠簸,帮助你探索更多的山峰。

但是,虽然大步帮助你走出较低的峰值(局部最优),大步在最高峰也有同样的效果。他们把你直接送上最高点。所以你发现自己在山顶上来回跳跃,但速度永远不够慢,无法停留在最高点。

现在,山脉是深度学习中优化的简化表示。但是这个类比揭示了优化的另一个问题。这个问题越来越有可能出现,因为我们从三维的真实世界中挣脱出来,试图优化具有潜在无穷维度的深度学习模型。

环形鞍座

这个问题就是鞍点。想象一下马背上的马鞍。在山上,这看起来像是山的平坦部分,向两边下降。问题在于梯度。当你在这些部分看斜率时,斜率是零或接近零。没有坡度。所以你没有办法给自己定位。你被困住了。

威格勒·戈多伊在 Unsplash 上的照片

这种缺乏斜率或接近零的斜率就是鞍点的问题。结果就是你没有办法进步。幸运的是,完全平坦的区域在山脉和深度学习优化中并不常见。幸运的是,现实是通常存在某种程度的倾斜。但是当你到达这个区域时,进展是有限的。

所以这些鞍点会导致寻找最高山峰的优化过程停止。虽然这些区域在低维中不太常见,但当维度增加时,这些鞍点越来越有可能出现。所以你很有可能在你的几个 n 维之间遇到一个鞍点,这会导致学习停滞。但是,有一些方法可以减轻这种情况。

选择学习率

这些问题给我们带来了学习率的替代方法。在前面的部分中,你可能一直在想,“为什么不使用一个可调整的学习率”?有时候想迈一大步,有时候又想迈一小步。这种策略是一种改进。

其余部分将讨论不同学习速度的选项。这些选项有助于缓解前面提到的问题。然而,正如您将在以后的文章中看到的,优化器的选择也起着巨大的作用。许多优化器选项支持利用二阶导数,这有助于将动量等概念融入到模型的收敛中。

那么什么是模型优化的学习率呢?

学习率是步长,即模型学习的程度。较大的速率训练模型更快,但是不允许模型有效地收敛到更健壮的解决方案。相反,较低的速率会减慢学习,但会让你的深度学习模型更接近最佳配置。

优化需要一个学习率。但是学习率本身就涉及到优化。没有放之四海而皆准的方法,选择可以影响模型的整体性能。

幸运的是,对于像 TensorFlow 这样的机器学习包,已经有很多可用的功能,使您可以非常容易地在您的模型中测试不同的变化和实现不同的学习率。

本文的剩余部分将讨论固定学习率的一些替代方案。虽然以固定的速率开始或者简单地尝试几个不同的值是好的,但是更灵活的解决方案有助于防止前面讨论的一些问题场景。

实验设置

对于这个例子,我在公共领域许可下使用 diamonds 数据集。这个数据集由分类变量和数字变量的组合组成。对于本文,我已经删除了分类特性。

https://www.kaggle.com/shivam2503/diamonds

该数据集提供了许多要素的大量数据。因此,损失函数的空间是完全凸的可能性不大。因此,创造了一个有许多小峰、奇怪的突起和突然下降的山脉的场景。理想情况下,用于比较不同学习速率的收敛性。

数据加载和缩放(由作者编写代码)

使用的模型是在 TensorFlow 中设计的简单多层神经网络。但由于深度学习模型依赖于相同类型的优化,这些实验将在其他深度学习模型中保持一致。

目标输出是连续的,损失设置为平均绝对误差。激活是一个 ReLU。最终模型有两个完全连接的层,每层有 50 个节点。

创建模型和参数初始化(由作者编写代码)

为了可视化实验的结果,我使用了库 Plotly。我过去广泛使用过这个包。复制文章中的情节的代码来自下面的代码。关于 Plotly 的细节可以在链接文章中找到。

情节训练与验证损失(作者代码)

基线模型

第一个模型作为基线。学习率是固定的。尽管如此,这里的学习率已经相对较低。注意学习率是如何在优化器 Adam 中设置的。

恒定的学习速率(由作者编码)

培训与验证损失对比如下所示。该模型稳定地收敛,但经过了许多时代。优化可能受益于更高的学习速率和快速收敛,尤其是在给定更多数据的情况下。

持续学习率(作者提供的数据)

灵活的学习速率和调度程序

以下实验使用不同的学习调度器。要在 TensorFlow 中应用这些可变学习率,请直接在优化器中使用学习计划程序。TensorFlow 中的每个优化器都支持学习率调度程序,而不是恒定的学习率。非常适合优化深度学习模型。

指数式衰减

所示的第一种选择是指数衰减。在训练模型的早期阶段,模型是非常不适合的。所以最初,大的学习率对于权重的调整是理想的。该模型将很快适应数据,但一开始可能预测得很笼统。该模型将保持高水平的偏差。

但是,随着训练的进行,步数越来越小。这种收缩策略通过山脉表现出来。你已经找到了一个高地,你正在慢慢地绕着顶峰转。随着台阶越来越小,你跳过最高点的几率也就越来越小。

以这种方式将学习速率设置为衰减允许模型很好地进入最终状态。它在大步骤和小步骤之间提供了一个很好的平衡,大步骤可以节省你的训练时间和更少的迭代,小步骤可以挤出你的深度学习模型的最后一点性能。

指数衰减代码

指数衰减是 TensorFlow 中预打包的调度程序。所需要的只是指定初始学习率、衰减率和衰减的步数。然后,整个调度器对象作为学习率被传递。

指数学习率衰减(作者代码)

实验

虽然结果与恒定汇率相似,但您可以看到,该模型在回顾时停留在稍低的低点。这种变化正在从相同的数据和模型中挤出更多的性能。只有学习率在训练过程中是变化的。

指数衰减——学习率(作者提供的数据)

循环调度程序

虽然步长的逐渐减少提供了快速学习和有效收敛之间的折衷,但是仍然存在局部最优的问题。让你的深度学习模型停留在一个局部最优,而更高的局部最优接近意味着你会留下一些性能。

想象一群紧密聚集在一起的山峰。当然,最高峰在混音中,但你只是选择了你遇到的第一个。

相反,循环学习率方法试图破坏优化过程的收敛。

该策略包括从低学习率开始,慢慢增加,然后跳回到低学习率,然后再增加。

如果你的深度学习模型已经处于一个稳定的最佳点,那么这些优化后期的大步骤将不会有什么效果。如果最优解是不稳定的,意味着在它周围还有其他最优解。那么这些大步骤将有助于优化方法探索这些。

循环调度程序的代码

循环调度器是 TensorFlow-Addons 包的一部分。一个必须知道的包是你在 TensorFlow 中建立深度学习模型。值一整篇文章。

循环学习率(作者代码)

实验

有了这个新的学习计划,这个模型改进得更多。当学习率跳跃时,训练中也有不同的点。这些点是损失的突然下降,整体上改善了模型。

周期性学习率(作者提供的数字)

自定义计划程序

尽管有不同的选项可用于调整学习率,但您可能希望对优化进行更多的控制。

幸运的是,有一些选项可以创建您想要的精确的学习计划。

对于标准指数衰减学习调度器,学习速率的降低速率是一致的。但是,您可能不希望衰减一致地收敛。因此,在训练深度学习模型时,随着模型的稳定,较小的学习速率可能更合适。

在这些情况下,从深度学习模型中挤出最后一点性能涉及到仅在最后几次迭代和训练时期对权重的微小调整。

自定义计划程序代码

对于自定义调度程序,设置略有不同。与前面的方法相比,在训练期间使用回调来完成定制的学习速率改变。回调接受时期和学习率作为参数,并进行定制调整。

对于这个例子,我根据时期手动覆盖学习率。这些变化是任意的,但是显示了模型的丢失将如何在不同的学习速率下起作用。

自定义学习率(作者代码)

实验

奇怪的是,自定义学习率产生了损失最低的模型。此外,它也显示了学习率过高的问题。

当学习率设置为最低时,模型显示出最佳性能。然而,在这个阶段,验证损失波动更大。这些变化显示了这种最佳状态的一些不稳定性。

当学习率回升时,直接的劣势是显而易见的。该模型的表现比以前差得多,即使经历更多的时代也无法收敛。

自定义学习率(作者提供的数据)

借助自定义计划程序的灵活性,您可以进一步提高指数衰减计划程序或循环计划程序的优势。一种选择是应用相同的循环方法,但是随着模型在更多时期上的进展,更新最大和初始速率。

方法比较

我包含了这些方法的并列比较,供您回顾。为了重新创建情节,运行下面的代码。

Plot 多个深度学习模型收敛(作者代码)

在 y 轴刻度相同的情况下,模型的细微差异更加明显。

虽然这些余量相对较小,但在大型深度学习模型中,这些微小的变化可能意味着模型有效性的重大变化。

学习率调度器比较(图由作者提供)

结论

学习率是训练深度学习模型的一个重要方面。深度学习和机器学习的所有变体都是基于这种优化的概念。

标准优化方法的核心是学习率。

太多时候,模型开发人员依赖于固定的学习率,错过了更好的模型。尝试几个不同的学习速度是一个微小的进步,但这仍然是有限的,尤其是当你考虑到所有可能发生的问题时。

花时间观察你的深度学习模型如何学习,它们的性能如何在多次迭代中变化,并亲自看看如何通过智能设计选择获得更多。

花时间了解不同的学习率对你的深度学习模型意味着什么,以及你的表现如何因此而改变。

如果你有兴趣阅读关于新颖的数据科学工具和理解机器学习算法的文章,可以考虑在 medium 上关注我。我总是在我的文章中包含代码,您可以将其应用到您的工作中!

如果你对我的写作感兴趣,想直接支持我,请通过以下链接订阅。这个链接确保我会收到你的会员费的一部分。

https://zjwarnes.medium.com/membership

用深度连体网络学习生物医学信号的相似性

原文:https://towardsdatascience.com/learning-similarities-between-biomedical-signals-with-deep-siamese-network-7684648e2ba0?source=collection_archive---------17-----------------------

一个自动神经网络框架用于 信号匹配 问题

TL;DR:全码

嗨,朋友们。

今天,我将带您浏览心电图(ECG)生物医学信号数据,目的是了解两个记录的信号数据事件之间的相似性表示。ECG 是人类医疗记录中最常见的信号数据类型之一。因此,让我们先简单了解一下什么是"信号"通俗地说,什么是 ECG 信号为什么需要它什么是连体神经网络它如何有助于比较两个向量,最后我们将看到一个用例,从 ECG 数据分析开始,包括单变量/多变量绘图、滚动窗口和绘图、数据分析、过滤异常值、检测 r 信号到信号

信号

代表某种信息的基本量,用简单的工程术语叫做“信号”。而在数学世界的上下文中,信号只是一个简单地传达一些信息的 函数 ,其中信息可以是时间的函数【y = y(t)】,或者可以是空间坐标的函数【y = y(x,y)】,或者可以是与源的距离的函数【y = y(r)】等等。举个例子。

医疗信号(心电、脑电、EOG、肌电图等。)

生物医学信号基本上是以非侵入的方式从我们的人体中收集的电信号。例如心电图(ECG)、脑电图(EEG)、眼电图(EOG)、肌电图(EMG)、表面肌电图(sEMG)等。是最常见的。这些信号非常有用&有非常大的价值,因为它可以进一步用于诊断目的。

心电图(心电图或 EKG)

心电图(ECG 或 EKG)测量心脏的电导率用于诊断目的,以测试我们心脏的功能,并确定是否有任何问题。它有助于描绘心跳的速率和规律性,心脏腔室的大小和位置,以及是否有任何损伤等等。心跳通常由一个小录音机来监测,录音机贴在贴在我们胸部的叫做“T2 电极”的标签上。

下图描绘了一个 QRS 复合波正常心电信号轨迹的示意图。顾名思义, QRS 复合体包括 Q 波R 波S 波。这三种波通常快速连续出现。组成心电图的不同波形代表心房和心室的去极化和复极化序列。心电图以 25 毫米/秒(5 个大方块/秒)的速度记录,电压校准为垂直方向 1 毫伏= 10 毫米(2 个大方块)。QRS 复合波代表通过心室传播的电脉冲,并指示心室去极化。与 P 波一样,QRS 复合波恰好在心室收缩之前开始。

人体心脏图和正常 ECG 轨迹示例—图像版权[ N. H. Kamarudin 等人]

连体神经网络

暹罗神经网络暹罗网络是由简·布罗姆利在贝尔实验室&的和团队早在 1993 年开发的。它包括双同神经网络,这些网络中的单元共享它们的权重。这些网络接受不同的输入,输出通过简单的比较能量函数组合。能量函数可以是距离函数,最常见的是欧几里德距离。这种类型的网络将高维输入映射到目标空间,并使用能量函数来比较难以定义的&解释输出空间的语义特征。

动手演示

现在,我们已经了解了一些关于 ECG 信号和连体网络的基本理论,让我们通过一个示例快速入门。在这里,我们将使用我从一家领先的智能服装和纺织品公司获得的数据,该公司为健身爱好者生产运动红外性能和康复运动服,旨在监测 altheles 的性能。提供的数据包括受试者/参与者穿着运动夹克进行不同活动(如坐、走、站等)的心电图记录。

请注意 :-出于数据隐私和安全的原因,我希望保持实际数据源的匿名性,并且也将只为读者提供来自整个数据集的实际数据(样本数据)的子集,只是为了跟随本教程。

我们将看到" Deep-XF "一个 python 库也可以直观地用于学习信号相似性。为了快速介绍&,所有其他由 deep-xf 包支持的用例应用程序都在这篇博文中列出。另外,看看预测、临近预报博客,其中有来自 此处&此处 的实际演示教程,这些都是在同一个服务包中提供的服务。如果热衷于从原始信号数据集中滤除噪声,请点击此处的博客https://ajay-arunachalam08.medium.com/denoising-ecg-signals-with-ensemble-of-filters-65919d15afe9

对于库安装遵循以下步骤 此处 &对于手动先决条件安装检查 此处

数据分析

让我们非常清楚地了解一件事,在我们谈论 AI 或任何机器学习的东西之前,数据分析在整个数据科学工作流程中起着非常重要的关键作用。事实上,它占用了整个管道中的大部分时间。

探索性数据分析(EDA) 是工作流程的初始和重要阶段。它有助于初步了解数据,并帮助生成相关假设和决定后续步骤。然而,EDA 过程在大多数时候可能是一个麻烦。

下面给出的代码片段用于 EDA,具有用于检查缺失值、绘制原始信号、滚动窗口 sumplots、分析数据和生成相应报告、移除异常值、使用可用检测器类型检测 R 信号到信号峰值(R 峰值)的实用函数,例如 swt 检测器christov 检测器、二平均值检测器、engzee 检测器、hamilton 检测器、pan tompkins 检测器、匹配滤波器检测器等。

图片作者:ECG1 — ECG5 原始信号图

作者图片:ECG1 — ECG5 信号的滚动窗口图

作者提供的图片:使用 Christov 检测器作为输入参数,在原始信号中绘制检测到的 R 峰

信号相似性比较

下图直观地展示了如何使用连体神经网络为我们的信号匹配用例获得相似性得分。如下图所示,它包括双相同的神经网络,并且这些网络中的单元共享它们的权重。输出最终导出的相似性得分,其估计输入向量之间的匹配。

作者图片:SigSimNet 架构

Siamese_Model 函数采用具有多个特征的输入向量&执行一系列数学运算,然后通过前馈网络架构进行连接,以获得所需的输出分数,如下面给定的代码片段所示。

接下来,我们使用 Siamese_Model 函数创建 Siamese 网络架构,将输入特征的数量作为参数,然后使用“均方误差作为我们的损失函数,如下面给定的片段所示,使用Adam optimizer&不同的评估指标,如均方误差(MSE)、平均绝对误差(MAE)、平均绝对百分比误差(MAPE)和余弦相似性。最终输出每个信号实例的估计相似性得分,其将两个输入向量作为自变量。下图显示了我们的暹罗模型摘要和后续信息。

作者图片:模型摘要

结论

通过这篇文章,我们看到了连体神经网络模型(又名双神经网络)如何对我们的信号匹配问题示例有用。这当然可以推广到任何上下文(图像/视频/文本/点云等)。)与任何相应的网络架构的构建类似(暹罗 CNN/RNN/点云/等。),作为这些人工神经网络背后的原理,它简单地使用相同的权重,同时对两个不同的输入向量并行工作,以计算可比较的输出向量。我们还简要讨论了生物医学信号,并使用一系列不同的效用函数进行数据分析,如检测 R 峰、分析、去除异常值、可视化图等。我们看到了软件包 deep-xf 如何在探索性数据分析、预处理、学习表示、过滤等方面为信号数据带来便利。

让我们连接起来

通过 Linkedin 联系;或者,你也可以打电话到ajay.arunachalam08@gmail.com找我

关于作者

我是 AWS 认证的机器学习专家&云解决方案架构师。根据我处理现实世界问题的经验,我完全承认,找到良好的表示是设计系统的关键,该系统可以解决有趣的挑战性现实世界问题,超越人类水平的智能,并最终为我们解释我们不理解的复杂数据。为了实现这一点,我设想学习算法可以从未标记和标记的数据中学习特征表示,在有和/或没有人类交互的情况下被引导,并且在不同的抽象级别上,以便弥合低级数据和高级抽象概念之间的差距。我也确实相信人工智能系统的不透明性是当前的需要。考虑到这一点,我一直努力使人工智能民主化,并且更倾向于建立可解释的模型。我的兴趣是建立实时人工智能解决方案,大规模的机器学习/深度学习,生产可解释的模型,深度强化学习,计算机视觉和自然语言处理,特别是学习良好的表示。

参考文献

**https://www.nhs.uk/conditions/electrocardiogram/ https://en.wikipedia.org/wiki/Electrocardiography https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6412424/ https://scipy.org/ https://www.sciencedirect.com/topics/engineering/biological-signal https://en.wikipedia.org/wiki/QRS_complex https://www.aclsmedicaltraining.com/basics-of-ecg/ https://www.cvphysiology.com/Arrhythmias/A009 https://kidshealth.org/en/parents/ekg.html https://github.com/berndporr/py-ecg-detectors **

学习 SQL 和以太坊(第 3 部分)

原文:https://towardsdatascience.com/learning-sql-and-ethereum-part-3-5422f080ad36?source=collection_archive---------15-----------------------

实践教程

让我们看看 Barnbridge(一种信贷份额协议)的合同和对锁定总价值和用户利润的查询。

Unsplash 上的 Loic Leray 拍摄的照片

我将在解释以太坊的基本概念时创建更多的小型查询细目,这是我写的 初级 中级 指南的延续。

这篇文章是与我的朋友 0x 九龙合作写的,请去看看他对 barn bridge 的可靠性架构的深入研究,以更好地理解该协议的来龙去脉。

我们之前已经研究过资产证券化,你必须在一项资产中存入一定数量的抵押品(比如瑞士联邦理工学院),才能借入另一项资产中 75%的抵押品价值(比如 USDC)。就像在传统的金融系统中一样,你可以赚取固定或可变的利息,除了在 DeFi 中,这个利率通常由你存入或借入的资产的“利用率”决定。

让我们以复合(类似于 Aave 的协议)为例来看看 USDC:

https://compound.finance/markets/USDC

重要的图表在左边,黑线表示 USDC 的当前利用率(借入的 USDC 总额/存入的 USDC 总额),绿线和紫线分别表示支付的可变利率和固定利率。你会注意到有一个点,利率的斜率会突然上升,通常设定在 80%左右,这是为了避免资产池被 100%利用(借入)。

现在,如果你是存款人,愿意放弃你获得的任何额外回报,以换取总是在某个固定利率上获得全部回报,会怎么样?例如,假设你和另一个投资者都存可变利率 USDC。你想每年获得 2%的回报。其他投资者已经同意从他们的存款(本金)中支付给你,以弥补差额,如果可变利率在一段时间内低于 2%(差额你的本金time_under_2%)。作为交换,如果可变利率超过 2%,那么你就支付他们额外的收益(差额你的本金时间 _ 高于 _2%)。这就是巴恩布里奇和他们的 SmartYield 产品的基本运作方式,有数百名投资者在安全(2%有保证)和高风险(2%以上/以下)部分之间进行选择。

然而,如果巴恩布里奇推出自己的存款和借款资产池,那么他们将不得不从头开始增加市场的流动性。自举流动性可能会很困难,并导致利用率大幅波动,进而导致利率波动。这就是金钱概念的重要性所在——本质上,BarnBridge 可以构建一种产品,在这种产品中,你从其资产池中借入或存入的资产将直接存入 Compound 或 Aave。通过这种方式,巴恩布里奇可以处理智能合约中的双重份额逻辑,同时利用复合或 Aave 市场的稳定性。如果你想更多地了解这个金钱乐高结构,我推荐阅读我的 Web3 产品讲解者

现在我们可以进入数据分析了。这就是我们想要的:

https://duneanalytics.com/ilemi/Barnbridge-PnL

为此,我们需要知道用户在智能合约上进行的主要事务(函数调用和发出的事件)。请记住,SQL 表是基于每个智能合约的交易数据。用户可以进入或离开风险较高的部分(次级代币/债券),也可以进入或离开较安全的部分(高级债券),因此我们有四个主要操作。在“离开风险部分”的过程中有一点需要注意的地方,但是我们稍后会解决这个问题。

让我们从将“锁定的总价值”(指存入的总资产)放入协议开始。这意味着我们需要加上总存款,减去初级和高级部分的总提款。

将 USDC 存入初级部分与存入 Aave 不同,因为初级部分的回报取决于他们从高级部分欠下(或获得)多少。这意味着,如果你在发行后加入这一部分,它不会是基础资产(USDC)和你作为回报获得的代币(bb_USDC)的 1:1 存款。同样,当你出售时,价格也不是 1:1。

我们用以下公式计算比率:

SELECT  date_trunc('day', evt_block_time) as day,
                contract_address,
                "underlyingIn"-fee, 
                "tokensOut",
                ("underlyingIn"-fee)/"tokensOut" as ratios
        FROM barnbridge."smartYield_evt_BuyTokens" 

UNION ALL

SELECT  date_trunc('day', evt_block_time) as day,
                contract_address,
                "underlyingOut", 
                "tokensIn",
                "underlyingOut"/"tokensIn" as ratios
        FROM barnbridge."smartYield_evt_SellTokens"
        where "tokensIn" != 0

我们正在查询 Barnbridge 初级阶段的表中的BuyTokensSellTokens事件。因为该部分中有许多类型的令牌(如、戴、),所以我们需要保留contract_address列,以便稍后进行过滤。tokensOut代表为用户制造的令牌,而underlyingIn是存放在协议中的资产。underlying/tokens的比值给了我们两者之间的汇率。我们将在用total barnbridge tokens in pool * ratio锁定的总价值中使用这一比率计算,以回到总基础资产的价值。

day将只返回交易发生的日期,因此在没有人从 BarnBridge 存款或取款的日子可能会有间隔。这将导致非常不连贯或扭曲的时间序列图,因此我们将使用generate_series表填充所有缺失的日期。

SELECT generate_series('2021-03-14'::timestamp, date_trunc('day', NOW()), '1 day') AS day 

接下来,我们将计算第二天(在数据的最后一天之后)作为系列的终点:

SELECT  ratios,
                contract_address,
                day,
                lead(day, 1, now()) OVER (ORDER BY day) AS next_day 
        FROM ratioavg

这看起来有点复杂,但本质上是创建一个常量值列next_day作为时间序列中的最后一天。

我们可以用一个连接把它们放在一起:

SELECT  ratios, 
                d.day,
                a.contract_address,
                symbol
        FROM days d
        left join ratio_with_lead_day a on a.day <= d.day AND d.day < a.next_day
        left join dune_user_generated.smartyield_token_mapping u on u.contract_address= a.contract_address

这样就完成了在没有事务的日子里包含行的时间序列(在时间序列图中显示为 0 ),并在next_day结束。我们还加入了一个表,该表将contract_address映射到底层资产的令牌符号,以便以后阅读和过滤。

所有这些返回下表

完整查询此处https://duneanalytics.com/queries/67210

既然这个问题已经解决了,我们可以看看初级份额代币的存款和取款总额。这从两个查询开始:

SELECT  buyer,
        evt_tx_hash,
        contract_address,
        "tokensOut" as deposit,
        date_trunc('day', evt_block_time) as day

FROM barnbridge."smartYield_evt_BuyTokens"

SELECT  seller as buyer,
        evt_tx_hash,
        contract_address,
        -"tokensIn" as deposit,
        date_trunc('day', evt_block_time) as day

FROM barnbridge."smartYield_evt_SellTokens"

我认为这两个不需要太多的解释,因为列是不言自明的,我们在这里做了同样的日期填充,但是使用了 contract_address 分区。

SELECT
        buyer,
        contract_address,
        deposit, 
        day,
        lead(day, 1, now()) OVER (partition by evt_tx_hash, contract_address ORDER BY day) AS next_day 
FROM redeemjbonds

我们用这个看起来有些混乱的查询将所有这些放在一起:

SELECT
sum(((d.deposit + coalesce(r.deposit,0))/10^u.u_decimals)*ratios) as deposits,
sum(coalesce(r.deposit,0)/10^u.u_decimals*ratios) as withdrawlsFROM
depositfinal dLEFT JOIN redeemfinal r  on d.day = r.day and d.buyer = r.buyer and r.contract_address = d.contract_address LEFT JOIN ratioq q on d.day = q.day and q.contract_address = d.contract_addressLEFT JOIN dune_user_generated.smartyield_token_mapping u on u.contract_address= q.contract_addressWHERE((d.deposit + coalesce(r.deposit,0))*ratios)/10^u.u_decimals > 0
AND u."symbol"='cUSDC'

我们将每个用户的总存款(depositfinal)和总取款(redeemfinal)以及资产(contract_address)连接起来。我们在这个连接中也保持日期一致。接下来,我们加入从第一次查询到日期的ratioq(记住,随着利息和高级部分付款/奖励的增加,比率每天都在变化)。最后,我们将contract_address 上的映射加入到资产符号中,并只过滤复合 USDC 存款(cUSDC)。至于我们选择的内容,我们用存款总额减去取款总额(COALESCE在这里用于涵盖用户没有提取任何东西并且值为 null 的情况,我们希望用 0 来代替——把它想象成一个if null then value (0) 函数)。然后我们将总和除以资产的小数(由于你在 solidity 中没有小数,我们必须在前端进行转换)。最后,我们用比率乘以这个存款,因为这个存款用 BarnBridge 代币表示,我们需要它来显示 USDC 值。如果这不是使用像 USDC 这样的稳定货币资产,那么我们将使用另一个连接(在连接symboldate时添加价格列)将它乘以每个日期的价格。

这为我们提供了下表:

https://duneanalytics.com/queries/67226

我们将对 select 查询稍加修改,以添加高级令牌,但过程几乎完全相同(只是没有比率)。

完整的 TVL 查询可以在这里找到,并给出了如下图表:

https://duneanalytics.com/queries/67051/134549

现在我们唯一需要计算的是每个用户和日期的利润和损失。我们想要检查已经进入和完全退出池的用户获得或丧失了多少利息(即deposit-withdrawals=0)。我之前提到的额外警告是,当有人退出初级部分时,他们需要补偿高级部分的任何利息损失。在典型的证券化式结构中,份额被锁定发行,任何人都不能随心所欲地退出或进入(至少不能以改变主要发行的方式)。在 BarnBridge 案中,提前提款的补偿有两种形式:要么是没收,要么是考虑到所欠利息的加权平均到期日的次级债券。

计算方法如下:

SELECT date_trunc('day',buy."evt_block_time") as date, buy."buyer", buy."tokensIn", redeem."underlyingOut", buy."maturesAt", true as did_redeem
        FROM barnbridge."smartYield_evt_BuyJuniorBond" buy
        INNER JOIN barnbridge."smartYield_evt_RedeemJuniorBond" redeem ON buy."juniorBondId" = redeem."juniorBondId" AND buy."buyer" = redeem."owner"
        INNER JOIN dune_user_generated."smartyield_token_mapping" map ON buy."contract_address"=map."contract_address"
        WHERE map."u_symbol"='USDC'

这里我只考虑那些既购买了债券(BuyJuniorBond)又赎回了债券(RedeemJuniorBond)的买家。连接在买方地址和次级债券 ID 上(以防他们有多个不同到期日和金额的债券)。我创建了一列作为did_redeemtrue值,用于以后的健全性检查。

然后,我们将这些赎回与初级部分存款和取款查询结合起来(表jtokens_t是我们原始查询的修改版本):

SELECT "date","buyer","underlyingOut","underlyingIn","tokensOut","tokensIn", false as "did_redeem"
        FROM jtokens_t
        UNION 
        SELECT "date","buyer","underlyingOut", 0 as "underlyingIn", 0 as "tokensOut","tokensIn", "did_redeem"
        FROM  SELECT "date","buyer","underlyingOut","underlyingIn","tokensOut","tokensIn", false as "did_redeem"
        FROM jtokens_t
        UNION 
        SELECT "date","buyer","underlyingOut", 0 as "underlyingIn", 0 as "tokensOut","tokensIn", "did_redeem"
        FROM junior_bond_redemptions

请注意,junior_bond_redemptions没有underlyingIntokensOut列,所以我用常量值0创建了它们,以便 UNION 函数按预期工作。

最后,我们将选择查询放在一起:

SELECT union_by_date."buyer", sum("underlyingOut" - "underlyingIn")/1e6 as net_profit_loss
FROM union_by_date
INNER JOIN
    (SELECT "buyer" 
    FROM buyer_pivot
    WHERE "out" - "in" = 0) as exit_buyers
ON union_by_date."buyer" = exit_buyers."buyer" 
GROUP BY 1
ORDER BY 2 DESC

这里,我用sum(“underlyingOut” — “underlyingIn”)/1e6来表示已经完全退出的买家子集的 PnL。我通过子查询exit_buyers上的内部连接来实现这一点,然后除以 USDC 的六位小数。最后是一个GROUP BY,因为我使用了一个聚合函数和一个ORDER BY来使图表更漂亮。

这给了我们这个:

https://duneanalytics.com/queries/66812

它显然有点倾斜(有人肯定是条鲸鱼),这就是为什么我也在仪表板中包含了表格视图。对于 PnL 的日期版本,我对最终的选择查询做了一点调整,但在其他方面没有变化。总的来说,它看起来相当均匀,损失可能是由一般的加密市场压力造成的。

https://duneanalytics.com/queries/65891

如果您对仪表板本身感到好奇,它只是查询的拖放,所以没有什么复杂的解释。Dune 使这一部分变得非常简单,不需要在 Python Plotly Dash 或 Bokeh 中摆弄来获得正确的可视化效果,也不需要担心部署。

这个简短的讲解到此结束,希望你学到了一些以太坊和/或 SQL 的知识!

学习 SQL?了解如何使用复杂的数据库练习 SQL

原文:https://towardsdatascience.com/learning-sql-learn-how-to-practice-sql-with-a-complex-database-4b2ce933b1ef?source=collection_archive---------23-----------------------

结构化查询语言

了解如何找到并开始使用复杂的数据库来练习 SQL

图像由卡斯帕卡米尔鲁宾。来源: Unsplash

如今,SQL 已经成为专业人士的顶级技能之一。每天,越来越多的公司开始使用关系数据库。出于这个原因,希望在职业生涯中成长的专业人士明白学习 SQL 是必须的。即使是使用 SQL 几年的专业人员(像我一样)也可能会对所有的 SQL 命令感到困惑,并且知道他们需要练习。另一个场景问题是多个关系数据库管理系统和许多基本命令并不相同。

问题来了。有数百种在线课程可以教授如何使用 SQL。然而,他们中的大多数使用学生在课程中创建的简单数据库。有些课程可能会用到你可以下载的数据库,但它们通常都是一些基础的。这里的事实是,这些数据库与现实相差甚远。您将不会在专业领域中使用基本数据库。因此,即使您每天练习 SQL,如果它是一个简单的数据库,您也不会理解 SQL 的全部潜力。

幸运的是,有人让世界变得更美好,并提供了雇员数据库。Employees 数据库是奠定 SQL 基础的最佳选择。它的复杂性提供了具有挑战性的任务和所有你需要提高你的技能。

这些员工可以在 GitHub 上的这个链接中找到。然而,来自 365 DataScience 的家伙们在这个链接的一个易于下载的文件中提供了这个数据库。数据库大约有 89 MB,从大小上看,我们可以看到我们正在处理一个巨大的数据集。

现在,您需要将数据库添加到 RDBMS 中。如果您正在使用 MySQL Benchwork,您可以点击下面显示的图标并按照步骤操作。我应该和其他 RDBMSs 一样简单。现在,您已经准备好像专业人士一样练习 SQL 了。让我们稍微探索一下数据库。

作者图片

首先,让我们看一下数据库图表。要在 MySQL Benchwork 上找到图,只需要进入database > reverse engineer...按照步骤操作即可。

好了,我们有多个表要探索。我们有关于雇员、部门、薪水、经理、头衔等信息的表格。我们可以通过键入SELECT COUNT(*) FROM employees;来检查数据库包含多少行。

作者图片

超过 30 万行。令人印象深刻!基本上可以用这种规模的数据库做任何查询。最棒的是,即使对于使用 SQL 多年的专业人员来说,它也足够复杂。来自 w3resource 的牛人创造了 114 个问题,让你用雇员数据库练习 SQL。你可以在这个链接上找到它们。

现在,您已经具备了成为专业 SQL 用户的所有条件。干杯!

在 30 多岁的时候学习编码

原文:https://towardsdatascience.com/learning-to-code-in-your-30s-24b5b8cce5de?source=collection_archive---------2-----------------------

关于如何踏上旅程的几点见解

布雷特·乔丹在 Unsplash 上的照片

如果你在 30 岁的时候开始写第一行代码,很容易感觉为时已晚。有很多有才华的程序员比你年轻得多,很难不被淹没。

我在 29 岁时写了第一行有用的代码。虽然我在方法上犯了很多错误,但我发现了一些有用的见解,可能对处于相同位置的任何人都有用。

不要为了把它写进简历而学习如何编码

奇怪的是,求职者在简历中列出 Python,却什么都不会,这是多么常见的事情。完成高级 Python MOOC 并不意味着你就是高级 Python 用户。它最多让你成为一个初学者。我理解处于职业生涯中期并试图寻找提升技能的方法是什么感觉,但你最好专注于自己的优势,而不是假装自己是程序员。

学习如何编码,因为你喜欢构建东西。不要纯粹为了在面试过程中脱颖而出而去做。除非你有能力解决真正的问题,否则它很可能帮不了你。

不要担心该学哪种语言

我第一次对编程感兴趣的时候是 24 岁,但我不确定该学哪种语言。我阅读了无数的留言板,并开始随机购买关于 C++、C#和 VBA 的书籍。我花了很多时间阅读如何编码,但我几乎没有花时间写代码。寻找完美的编程语言让我精疲力尽,我放弃了。

虽然一定量的研究是必要的,但它会很快变成拖延。读到你的目标可能会让你感到满足,但是你并没有在工作。

我担心我会把时间浪费在学习错误的语言上,而且一无所获。这是错误的思考方式。每种语言都会给你一些有用的东西,应用到你将来可能需要的任何语言中。

你不应该需要超过一个小时的研究来决定一种语言。如果你已经迟到了,你没有时间浪费在这上面。

许多开发人员告诉你从学习 c 开始。这对许多人来说可能是有意义的,但我不认为这是职业生涯中期开始的人的最佳途径。你应该瞄准一门能帮助你今天开始解决问题的语言,这就是为什么我建议从 Python 或 Javascript 开始。这些语言物有所值,因为它们将为您提供快速解决各种问题的工具。

尝试很多学习方法

在学和做之间取得平衡是很重要的。有时候我太专注于疯狂地构建东西,而其他时候我则陷入了教程的循环中。

我通过重做已经在 Excel 中完成的工作来学习 R,这种方法有利有弊。这很好,因为这是现实世界的问题解决方案,你已经知道答案应该是什么。然而,我发现边做边学的方法会在你的知识中留下巨大的漏洞。

用教程、书籍、竞争性编码、Kaggle 等来补充项目是很重要的。这有助于保持事情的趣味性,你会学到像算法和数据结构这样的基础知识。我还发现教程有助于你专注于使用库,这会让你的生活更轻松。

请记住,你应该做多少教程是有限度的。你必须确保你正在尝试将你在教程中学到的东西应用到实际问题中。

找到在日常生活中使用代码的方法

我是从看一本 C#的书开始的。在我完成所有的练习后,我不知道该如何处理这些新知识。我只是缺乏世界观,无法理解编程可以解决什么类型的问题。

我很幸运地加入了一个使用 R 进行统计分析的团队。如何将代码融入到我的工作中突然变得有意义了,我开始学习如何用 R 做通常会在 Excel 中做的事情。这最终导致我每天都在使用 Python、R 和 SQL。

如果可能的话,试着让编码成为你当前工作的一部分。考虑可以自动化的任务或可以更好地维护和可视化的数据。如果你能从小处着手,让你的团队对你的项目感兴趣,你就能把你的角色转变成你想要的角色。

不要只写代码,也要读代码

如果你不花时间阅读开源项目,那你就做错了。这是学习软件开发的最佳资源之一。在 Github 中搜索您使用的项目,看看开发人员是如何构建这些工具的。

简单的项目和教程可以帮助你学习编程的基础,但是软件开发对风格非常固执己见。当你阅读流行的开源库时,你会开始有一种项目应该如何组织的感觉。

记住如何成为一个初学者

随着年龄的增长,大多数人投入学习的时间越来越少。一旦你到了 30 岁,就开始专注于其他事情,这是很常见的。重新开始很难,尤其是当你想学习一些有挑战性的东西的时候。

我认为初学者的能力是一项重要的技能。我见过有人很难捡起编程和数据科学,因为他们无法接受再次成为新手。他们从解决过于复杂的问题开始,最终放弃。你必须丢掉自我,从一些容易处理的事情开始。

冷静点。人生漫漫。

感觉自己已经过了巅峰很容易,但是一年能学到多少东西就很疯狂了。如果你今天已经 30 多岁了,你还有很多事业要做。不要担心错过的机会,去创造一些东西。

结论

这概述了我在以后学习如何编码时收集的一些见解。我想象有很多人在同一条船上,我希望这有所帮助。

学习散列

原文:https://towardsdatascience.com/learning-to-hash-36367b9814f1?source=collection_archive---------13-----------------------

将书籍摆放到书架的不同位置。照片由西格蒙德Unsplash 上拍摄

小窍门

如何设计应用于快速检索任务的数据表示技术

哈希是数据管理中最基本的操作之一。它允许使用少量内存快速检索数据项。哈希也是一种基本的算法操作,具有严格理解的理论属性。事实上,所有高级编程语言都提供了用于在哈希表中添加和检索项目的库。

最近,散列法已经成为一种强大的相似性搜索工具。这里的目标不是精确检索,而是快速检测彼此相似的对象。例如,对于不同的相似性概念,同一物品的不同图像应该具有相似的散列码,并且我们应该能够快速搜索这种相似的散列码。

最近的一个研究趋势是设计特定于数据的散列函数。不同于传统的散列算法,其中散列函数是通用的并且不依赖于底层数据分布,学习散列方法基于这样的前提,即可以通过发现数据中的隐藏模式来设计最佳散列函数。

在这篇文章中,我将讨论设计特定于数据的散列函数及其应用的机器学习技术。

数据分布散列法

这是标准的散列法,例如 Python 中的字典,我们在其中存储键、值对。这些键被映射到唯一的散列码,如果一个键出现在我们的散列表或字典中,我们可以在常量时间内进行检索。

数据独立(传统)散列法

我们假设项目或密钥由整数表示。(不可变的数据类型,如字符串、浮点或元组,可以表示为整数。)

标准的散列方法是将项目 x 映射到 f(x ),其中 f(x)只能取 m 个不同值中的一个。重要的是 f(x)值尽可能随机,即我们想要的

这样,我们就不太可能发生碰撞,i e,f(x)=f(y)。通常通过创建一个列表来处理冲突,该列表包含散列到给定地址的所有项目。如果列表太长,检索会变得很慢,因为我们需要遍历列表。

为了避免冲突,哈希函数应该是独立的:

对于所有输入,0 ≤ i,j ≤ m-1。

上述条件被称为双向独立性,因为我们只考虑成对输入项的独立性。如果我们有三个项目,我们将有 3 个方面的独立性,一般来说,k 个方面的独立性。k 越高,函数越随机。

对散列函数的一个主要要求是它们可以被有效地评估。一个典型的例子是线性散列函数,如

其中 ab 为随机选取的素数。可以证明这个函数是双向独立的。诸如高阶多项式的更复杂的函数产生 k > 2 的 k 方向独立性。代价是更复杂的函数计算起来也更慢。我参考这些课堂讲稿来了解更多关于散列的细节。

使用机器学习的数据相关散列

在数据无关哈希中,为了避免很多冲突,我们需要一个“足够随机”的哈希函数和足够大的哈希表容量 m,参数 m 取决于数据中唯一项的数量。最先进的方法实现了恒定的检索时间结果,使用

*m = 2 唯一项目数

然而,想象一下我们的数据是从具有已知参数的正态分布生成的特殊情况,假设平均值为 0,标准偏差为 1。那么我们实际上不需要随机分配物品。我们可以简单地创建覆盖不同时间间隔的存储桶。我们需要在 0 附近有许多短的间隔,但是我们离 0 越远,间隔应该变得越大。显然,在区间[0,0.1]中我们会有很多值,但几乎没有大于 10 的值。

图一。x 轴上的标签给出了散列值的容器。图片作者。

这是将机器学习方法应用于哈希的直觉。通过了解数据的分布,我们可以以最佳方式将物品分配到箱中。这是数据独立哈希无法实现的。

2017 年,谷歌的研究人员因声称他们能够改进最著名的哈希算法而成为头条新闻[2]。

相似性保持散列

数据独立方法

已经设计了不同的方法,使得对于不同的相似性概念,散列码保持对象之间的相似性。位置敏感哈希(LSH)是一系列哈希算法,保留对象之间的不同度量,如欧几里德距离或集合重叠。让我们考虑一个估算矢量间夹角的具体例子。

假设我们的输入数据是 d 维向量。我们选择 k 个随机 d 维向量 w_i,其中每个条目选自标准正态分布 N(0,1)。

图二。绿色向量是分离超平面。图片作者。

随机向量被堆叠成矩阵 w。散列码然后被计算为

上面说我们计算 x 和每个随机向量 w 的内积,并把符号作为哈希码。你可以把每个 d 维随机向量想象成 d 维空间中的一个随机超平面。符号表示向量 x 位于超平面的每一边。参见图 2 中的二维示例。因此,如果两个向量之间的角度很小,它们很可能在超平面的同一侧,即它们将有很大的重叠。LSH 的主要结果是

其中θ(x,y)表示矢量 x 和 y 之间的角度。

为什么是位向量?

目标是创建由单个比特组成的散列码。位向量非常紧凑,因此即使是大型数据集也可以在主存中处理。此外,位向量的算术运算非常高效。对位向量的相似性穷举搜索比对具有连续值的向量的穷举搜索更有效。原因是位向量可以在快速 CPU 缓存中加载和处理。因此,通过对两个比特向量进行 XOR(计算相同比特的数量)来代替一般向量的向量内积 u^T*v,产生了显著的计算优势。

用于相似性搜索的无监督哈希学习

最初提出的算法之一是基于 PCA 分解。我们找到协方差矩阵中方差最大的 k 个方向

然后我们使用 d-乘以-k 的投影矩阵 W,将数据 X 投影到 k ≤ d 个主特征向量上,即对应于 k 个最大特征值的特征向量:

注意它成立:

在上面的λ是由最大特征值组成的对角 k 乘 k 矩阵,W 包含相应的特征向量。

哈希码计算如下

一个明显的缺点是,这样所有方向都被平等对待。但我们需要更加关注方差较高的方向。研究人员提出了不同的技术,将更多的比特分配给方差较大的方向。

监督学习散列相似性搜索

这是一个我们已经标记了数据的设置。例如,用不同类别标记的 n 个图像的数据库。在这里,我们可以创建图像之间的相似性得分,并将它们存储在 n 乘 n 矩阵 S 中。例如,条目 S_{i,j}表示两幅图像基于它们的标签有多相似,例如两组标签之间的 Jaccard 相似性。(当然,相似性是一个非常通用的概念,不同的度量是可能的。)

我们要求条目 S_{i,j}是介于-1 和 1 之间的值,因此对于具有[0,1]中的值的相似性度量 sim(i,j ),我们设置

目标是解决下面的优化问题。

矩阵 B 包含 n 个对象的散列码。请注意,我们将相似性矩阵乘以 k,因为 BB^T 中的值介于-k 和 k 之间。在上面的内容中,下标 f 表示矩阵的 Frobenius 范数:

上面的优化问题很难解决,因为我们要求 B 中的值要么是-1,要么是 1。放松版由下式给出

然后,通过取 b 中每个条目的符号,将解转换为位向量。

学习排名

另一个被广泛研究的问题是可以用来保持元素秩的散列码的设计。设置如下。对于查询 q,有一个按降序排序的相关性分数列表

项目 I 的等级由下式给出

让我们用来自{-1,1}的条目来定义两个二元向量之间的距离:

I 为二元指示函数,使得 I(E) = 1 当且仅当事件 E 为真。使用距离函数和二进制码的排序可以写成

然而,该指标导致了一个难以优化的问题。因此,我们使用 sigmoid 函数将其替换为概率表达式:

为了学习二元向量,我们使用一个带有可学习参数的矩阵。

然而,使用符号函数又会导致一个难以优化的问题。因此,我们去掉符号,得到下面的概率表达式

这可以用于排名的表达式中,即

一旦我们有了一个学习排名参数的表达式,我们就可以将其插入到一个损失函数中,如归一化贴现累积收益(NDCG) 。我请读者查阅[4]以了解更多细节。

讨论

人们应该永远记住,学习散列函数是一个机器学习问题。因此,它带来了机器学习的优点和缺点。它可能会导致卓越的性能和接近最佳的散列码。而且,获得散列码可能很慢,容易出错,并且容易过度拟合。学习哈希代码时,建议使用具有众所周知的属性的数据独立哈希函数作为基线。事实上,像布谷鸟哈希这样的高级数据独立哈希方法可以获得与【2】中报告的结果相当的结果。

参考

[1]学习大数据哈希:教程。李武军。在https://cs.nju.edu.cn/lwj/slides/L2H.pdf上市

[2]学习指数结构的情况。蒂姆·菲利普·克拉斯卡,亚历克斯·比特尔,埃德·h·齐,杰弗里·迪恩,尼奥科利斯·波利佐蒂斯。在https://arxiv.org/pdf/1712.01208.pdf有售

[3]一个关于学习 Hash 的调查。王京东,,宋京宽,Nicu Sebe 和沈。IEEE 模式分析与机器智能汇刊(TPAMI) 2017。可在https://arxiv.org/abs/1606.00185买到

[4]用于快速相似性搜索的排序保持散列法。王启帆、张志伟和洛斯。IJCAI 2015。地点:【https://www.ijcai.org/Proceedings/15/Papers/549.pdf

posted @ 2024-10-18 09:27  绝不原创的飞龙  阅读(274)  评论(0)    收藏  举报