TowardsDataScience-博客中文翻译-2021-十三-
TowardsDataScience 博客中文翻译 2021(十三)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
所有数据集成都应该使用变更数据捕获
原文:https://towardsdatascience.com/all-data-integrations-should-use-change-data-capture-a1d207091773?source=collection_archive---------17-----------------------
唐纳德·詹纳蒂在 Unsplash 上的照片
数据集成已经存在了几十年,但最近出现了新的、引人注目的数据集成公司,这些公司提供云原生的、易于配置的连接器以及对高价值分析的快速访问。这些产品来自 Fivetran、Stitch Data、Matillion 和 Airbyte 等公司。任何数据团队都很难知道是坚持现有的数据堆栈还是采用这些新工具。虽然很高兴看到数据集成变得越来越主流,新方法不断涌现,我们认为这个领域的新进入者正在创造越来越大的差距。今天的一些更难的问题要么被忽略,要么在未来的版本中承诺,但是客户今天就需要解决方案。让我们仔细看看数据集成现在处于什么位置,以及我们认为它们在未来需要走向哪里。
TL;DR: 所有数据集成都应构建基于日志的变更数据捕获(CDC)架构!
什么促成了健壮的数据集成?
数据集成是将来自多个来源的数据汇集到一个集中的存储库(如数据仓库或数据湖)的过程。集成和连接器从这些源中批量(大部分)提取数据,并将提取的数据加载到数据仓库中,以便进一步清理和转换。然后,这些数据混合在一起,产生有意义的商业见解。
数据分析师依靠来自多个来源的集中式数据来形成这些见解。分析师的目标是通过切片和切块获得对数据的最佳理解。当对数据如何随时间变化有一个清晰的概念时,数据是最容易理解的。但是并不是所有的数据集成都是相同的,这使得很难清楚地了解数据的变化。很少有集成架构能够捕获所有的数据变更,这就是为什么我们相信变更数据捕获是数据集成的最佳设计模式。
CDC 更胜一筹,因为它提供了数据源数据如何随时间变化的完整画面——我们称之为数据的**“动态叙述”。**基于日志的 CDC 提供了一种低开销、高性能的方式来捕获每一个数据更改,无论其大小如何。通过 CDC,数据集成可以以轻量级的方式提取数据变更,以低风险为生产基础架构提供高价值。
一个例子:获取电子商务中数据的动态叙述
让我们考虑一家电子商务公司,其用户通过将产品添加到购物车来进行购买。该公司的一名分析师正试图确定一组类似产品的受欢迎程度。为了了解为什么有些产品不太受欢迎,分析师调查了所有用户的购物车变化。记录购物车的每一次更改可以让您更深入地了解几个注意事项:
- 用户是否经常将特定品牌的产品添加到购物车中,但并不购买它?
- 用户是用一个品牌换另一个品牌吗?
- 用户是否在购买前弃车?
购物车的变化提供了用户行为的动态叙述,以及对产品性能的更丰富的理解。通过访问完整的数据集,分析师可以向业务或产品团队提出更好的建议。
获取购物车数据
让我们看看为上面的例子获取购物车变化数据的不同方法。数据集成从源同步数据有三种方式:
- 快照
- 增量拉动
- 变更数据捕获
每种数据同步机制的工作方式不同,并为数据分析师提供不同级别的支持。
快照:可以处理删除,但可能会浪费资源且成本高昂—数据不完整
来自数据源的表/对象的定期快照提供了数据在时间点的高保真副本。分析快照可以让分析师了解数据随时间的变化,但可能会造成浪费和成本**。拉快照的持续时间与数据更改量成比例增加。这可能会给数据源带来压力,危及生产工作负载的性能和可用性。**
换句话说,源位置的数据更改越多,获取快照所需的时间就越长。获取快照的时间越长,性能风险就越大。由于这些快照通常直接针对生产数据库运行,这对于客户和内部利益相关者来说可能是一个大问题。
即使一些对象/行在源中没有改变,它们仍然在快照拉取中被获取,导致不需要的获取。高性能应用和最新的分析需要大量的关心和关注。没有时间处理“额外”的数据、行或计算。
最后,由于快照是定期获取的,因此数据分析师看不到获取之间发生的数据更改。为了进行补偿,分析师会查看快照之间的变化并做出假设。更改的粒度取决于拍摄快照的频率。快照之间发生的所有购物车更改都可能丢失,并且分析师不得不根据不完整的信息拼凑一个故事。
增量读取:比快照成本低,但无法有效处理删除,而且数据不完整
在某些方面,定期增量读取比快照要好。它们仅获取自上次拉取以来更改过的数据,这并不像一直获取所有数据那样昂贵。但是它们也会错过读取之间的数据更新。
在我们的例子中,分析师仍然需要做出假设来填补数据缺口。如果用户数据每 15 分钟进行一次增量提取,并且在这 15 分钟的时间间隔内对购物车进行了多次更新,则增量提取将仅在最后一次更新应用于源之后提取购物车的最终状态。这 15 分钟间隔内的任何其他变化都不可用于分析。所以分析师可能不会看到用户购物车的每一次变化。
此外,**增量获取通常不能很好地处理硬删除。**已删除的数据不会显示在增量拉动中,因为它在源中不再存在。事实上,快照处理硬删除更好,因为快照获取自动包括硬删除。
变更数据捕获:完整数据—不折不扣!
与快照和增量获取不同, CDC 提供了源端数据如何随时间变化的完整画面。对于支持通过 CDC 提取数据的连接器来说,源必须支持发布对每个数据元素的每个更改。对于大多数来源来说,这是一个很高的要求。
幸运的是,数据库可以为灾难恢复和高可用性用例编写完整且健壮的变更日志。使用 CDC 的数据库连接器从这些更改日志中提取数据。变更日志的健壮性直接转移到数据集成本身。CDC 提升了数据集成的游戏级别,并提供了数据动态叙述的完整视图。
为了更好地理解 CDC 如何提供完整的数据视图,让我们看看下图。
图片由 Datacoral 提供
上图显示了对于相同的每小时数据延迟,快照、增量和 CDC 方法的行为。源表在 10:00 和 11:00 之间获得两组更改。
快照提供高保真拷贝(源表和目标表在 11:00 是相同的),但不捕获中间更改。因此,分析师无法看到以下缺失的数据:
- '将 1 更新到 1 '
- 插入 4(只有 4 '可见)
- 插入 5
- 删除 5
此外,即使是未更改的行(第 3 行)也会被不必要地提取。另一方面,增量读取更有效,因为它们只读取已更改的行,但是它们也面临与快照读取相同的数据丢失问题。
**CDC 显然对源数据如何随时间演变有最完整的了解。**没有浪费的行提取,所有的删除都被捕获,没有丢失任何数据更改。
你可能会问自己,**“如果 CDC 这么棒,那为什么大家都不用呢?”**这是一个很好的问题,我们有一个简单的答案:**构建和维护一个健壮的 CDC 连接器需要付出很多努力。**此外,CDC 数据集成的源系统和目标系统也应服从高效的 CDC 管道。在下一节中,我们将介绍如何构建一个鲁棒的 CDC 连接器。
获得强大的 CDC 数据集成需要什么?
支持 CDC 的系统应提供以下功能,以实现可靠的数据集成:
- 捕获每个数据项的所有更改,包括硬删除
- 允许自省(即提供检测哪些对象被添加、删除或编辑的方法)
- 允许快速批量提取初始加载的所有数据,也称为“历史同步
三个不同的系统必须协同工作进行数据集成,以成功提供 CDC:
- 源系统
- CDC 连接器
- 目的仓库
最后,功能 CDC 连接器的要求如下:
- 模式映射:在连接器添加过程中,在目标仓库中创建与源模式/对象相对应的表。
- 批量同步:用于初始加载或从故障中恢复的批量提取和加载。能够预填充连接器添加过程之前存在的历史数据。
- 持续的变更数据捕获:将所有插入、删除和更新从源传播到目的地。
- 数据新鲜度/质量保证:围绕数据新鲜度和数据质量提供可见性和保证。
- 传播模式更改:检测和应用模式更改,如添加新表、删除表、添加列、删除列和更新列。
在下表中,我们列出了三个不同的系统应该如何针对上面列出的功能的不同部分进行设计,以针对给定的源和目标对获得稳健的 CDC 解决方案。
图片由 Datacoral 提供
CDC 数据集成蓝图
上图展示了为任何源系统构建健壮的 CDC 解决方案所需的端到端管道。需要将多个组件协调在一起,不仅要让数据流动,还要提供数据新鲜度和质量保证。
- CDC 事件读取器—高效地从源系统获取更改日志,并确保源系统不会被备份。更改日志由对源中所有对象或表的更改组成,因此读者还必须将更改日志分成特定于表的更改,然后将这些更改应用到目标中相应的数据表。
- 元数据传感器—捕获源系统中的表/对象结构,并将该结构(模式)映射到目标表模式。如果源表/对象结构不断发生更改,元数据传感器还会协调将更改传播到目标表,并根据需要使用批量数据读取器执行历史同步。
- 批量数据读取器—直接从源系统获取数据(而不是只获取更改日志)。对于数据库,大容量读取器可以在源数据库上运行 SQL 查询并检索结果。SQL 查询可以用于初始历史同步,也可以用于数据质量检查的计算概要(聚合和校验和)。
- 转换管道-计算目标表上的概要,并执行实际的数据质量检查。当数据具有质量保证时,此管道可以生成事件,或者当数据质量检查失败时,可以生成警报。
在本节中,我们提供了如何构建 CDC 数据集成管道的蓝图。我们过去也曾写过关于 Datacoral 如何使用我们的端到端数据管道实现来构建 CDC 连接器,该实现是用元数据优先架构构建的。
目前哪些源系统支持 CDC 数据集成?
用于数据集成的 CDC 有许多好处,但不是每个源系统都能提供这些好处。不同类型的数据源提供不同的数据检索功能。我们将这些来源分为以下几类:
- 数据库
- 文件系统
- 蜜蜂
- 事件流
下表总结了连接器如何使用我们讨论过的提取类型从不同类型的源中提取数据。
图片由 Datacoral 提供
如您所见,并不是所有的源系统都支持 CDC 连接器。数据库早就提供了构建 CDC 连接器所需的所有属性。我们认为具有批量数据集成 API 的服务也应该提供变更日志来捕获服务中每个对象的变更。基于 Webhook 的服务正在实现,但通常只提供了一部分变化。数据集成仍然需要使用其他 API 来获取 webhooks 没有覆盖的更新对象,这导致了类似于定期快照或增量获取的数据间隙。像 Stripe 这样的服务在提供 CDC API 方面处于领先地位,我们希望其他人也能效仿。
已经有很多关于事件驱动架构如何成为未来的文章,但是在很多情况下,事件驱动架构也与实时需求相关联。我们相信事件驱动架构支持更丰富的数据分析,即使分析是通过批处理事件来完成的!
结论
我们很高兴看到如此多的公司进入数据集成领域。他们为众多公司带来了更多的数据分析意识。商业和技术领导者正在体验数据的动态叙事。但是快照和增量获取还不够。我们希望 CDC 无处不在,以便分析师和数据团队能够真正利用数据堆栈的力量。
快照支持硬删除和高保真数据,但它们不能捕捉完整的画面,并且存在性能风险。增量获取通常比快照更有性能,但会错过硬删除,而且也不完整。变更数据捕获是唯一一种能够在几乎没有性能风险的情况下全面了解数据的架构。Stripe 等公司正在提供事件驱动的 API,为其环境中的对象提供完整的更改日志。我们希望看到更多这样的情况。
**建立一个强大而高效的疾病预防控制中心渠道需要大量的努力和策略。**需要协调几个系统,必须满足功能需求,并且应该利用元数据来实现自动化模式更改检测和其他重要特性。
在 Datacoral ,我们使用元数据优先的数据管道为 PostgreSQL 和 MySQL 等数据库构建了 CDC 连接器。在 CDC 和其他 80 个连接器上工作过之后,我们确信 CDC 提升了数据集成的水平。没有 CDC 的数据集成仅仅提供了用于分析的数据全貌的影子。如果所有的数据源都开始支持事件 API,那么所有的数据集成最终都会变成一个软件。
如果你有兴趣了解更多,请访问我们的网站或在 hello@datacoral.co 给我们留言。
2022 年你应该知道的所有机器学习算法
原文:https://towardsdatascience.com/all-machine-learning-algorithms-you-should-know-in-2022-db5b4ccdf32f?source=collection_archive---------1-----------------------
最流行的机器学习模型的直观解释
安德烈·德·森蒂斯峰在 Unsplash 上拍摄的照片
请务必 订阅此处 千万不要错过另一篇关于数据科学指南、诀窍和技巧、生活经验等的文章!
去年我写了一篇名为2021 年你应该知道的所有机器学习算法 的文章,那么我为什么要为 2022 年再写一篇呢?在过去的一年里,有那么多新的算法出现吗?
嗯,没有。
但是今年,我想改变这篇文章的结构。我不想列出所有的机器学习算法,而是想提供几种类型的机器学习模型,以及每种类型最广泛使用的模型。
我为什么要这么做?
- 应用。如果知识不能应用于任何事情,它实际上是无用的。通过提供模型的一般类别,你会更好地理解你能解决什么问题而不是有什么模型存在。
- 关联性。事实是,并非所有的机器学习模型都是相关的。您将立即看到,像朴素贝叶斯和支持向量机这样的传统算法没有包含在本文中,原因很简单,它们被增强算法远远超过了。
- 消化率。我想让这个尽可能容易消化。网上有成千上万的资源可以教你如何实现我将要谈到的模型。因此,我将更多地关注何时使用每种类型的模型。
话虽如此,让我们深入探讨 5 种最重要的机器学习模型:
- 集成学习算法
- 解释性算法
- 聚类算法
- 降维算法
- 相似性算法
如果您想测试这些 ML 算法,请查看 土星云 ,这是一个可扩展的、灵活的数据科学平台,有免费层和企业层。
1.集成学习算法(随机森林 XGBoost,LightGBM,CatBoost)
什么是集成学习算法?
为了理解什么是集成学习算法,你首先需要知道什么是集成学习。集成学习是一种同时使用多个模型来实现比单个模型本身更好的性能的方法。
从概念上讲,考虑以下类比:
作者创建的图像
想象一下,如果一个学生必须解决一个数学问题,而不是整个教室。作为一个班级,学生可以通过检查彼此的答案来合作解决问题,并一致决定一个单一的答案。另一方面,个人没有这个特权——如果他/她的答案是错的,没有其他人来验证他/她的答案。
因此,有几个学生的教室类似于一个集成学习算法,几个较小的算法一起工作来制定最终的响应。
如果你想了解更多关于集成学习的知识,可以看看这篇文章:
它们什么时候有用?
集成学习算法对于回归和分类问题或者监督学习问题是最有用的。由于其固有的性质,它们优于所有传统的机器学习算法,如朴素贝叶斯、支持向量机和决策树。
算法
- 随机森林
- XGBoost
- LightGBM
- CatBoost
如果您想测试您的 ML 技能,请查看 【土星云】 ,这是一个可扩展、灵活的数据科学平台,有免费层和企业层。
2.解释性算法(线性回归、逻辑回归、SHAP、LIME)
什么是解释性算法?
解释性算法允许我们识别和理解与结果有统计显著关系的变量。因此,我们可以创建解释性模型来理解模型中变量之间的关系,而不是创建模型来预测响应变量的值。
从回归的角度来看,这里非常强调具有统计意义的变量。为什么?几乎总是,您将处理一个数据样本,它是整个总体的一个子集。为了对给定样本的总体做出任何结论,确保有足够的显著性来做出自信的假设是很重要的。
作者创建的图像
最近,还出现了两种流行的技术,SHAP 和莱姆,用于解释机器学习模型。
它们什么时候有用?
当您想要了解“为什么”做出决策,或者当您想要了解两个或多个变量“如何”相互关联时,解释性模型非常有用。
在实践中,解释你的机器学习模型做什么的能力与机器学习模型本身的性能一样重要。如果你不能解释一个模型是如何工作的,没有人会信任它,也没有人会使用它。
算法
基于假设检验的传统解释模型:
- 线性回归
- 逻辑回归
解释机器学习模型的算法:
- SHAP
- 石灰
务必 订阅此处 或至我的 独家快讯 千万不要错过另一篇关于数据科学的指南、窍门和技巧、生活经验等!
3.聚类算法(k 均值、层次聚类)
作者创建的图像
什么是聚类算法?
聚类算法用于进行聚类分析,这是一项无监督的学习任务,涉及将数据分组为个簇。与目标变量已知的监督学习不同,聚类分析中没有目标变量。
它们什么时候有用?
当您想要发现数据中的自然模式和趋势时,聚类特别有用。在 EDA 阶段进行聚类分析以揭示更多关于数据的见解是非常常见的。
类似地,聚类允许您基于不同的变量识别一组数据中的不同段。最常见的聚类细分类型之一是用户/客户细分。
算法
两种最常见的聚类算法是 k-means 聚类和层次聚类,尽管还有更多算法:
- K-均值聚类
- 层次聚类
4.降维算法(PCA,LDA)
作者创建的图像
什么是降维算法?
降维算法是指减少数据集中输入变量(或特征变量)数量的技术。降维主要用于解决维数灾难,这是一种现象,即“随着维数(输入变量的数量)的增加,空间体积呈指数增长,导致数据稀疏。
它们什么时候有用?
降维技术在许多情况下很有用:
- 当数据集中有数百甚至数千个要素,而您需要选择少数要素时,它们非常有用。
- 当您的 ML 模型过度拟合数据时,它们非常有用,这意味着您需要减少输入要素的数量。
算法
以下是两种最常见的降维算法:
- 主成分分析
- 线性判别分析
5.相似性算法(KNN、欧几里德距离、余弦、Levenshtein、Jaro-Winkler、奇异值分解等)
作者创建的图像
什么是相似度算法?
相似性算法是那些计算记录/节点/数据点/文本对的相似性的算法。有比较两个数据点之间距离的相似性算法,如欧几里德距离,也有计算文本相似性的相似性算法,如 Levenshtein 算法。
它们什么时候有用?
相似性算法可以在各种应用中使用,但是它们对于推荐特别有用。
- Medium 应该根据你之前阅读的内容向你推荐哪些文章?
- 你可以用什么成分来代替蓝莓?
- 根据你已经喜欢的歌曲,Spotify 应该推荐什么歌曲?
- 亚马逊应该根据你的订单历史推荐什么产品?
这些只是我们日常生活中使用相似性算法和推荐的许多例子中的几个。
算法
下面是一些相似性算法的非穷举列表。如果你想了解更多的距离算法,请查看这篇文章。同样,如果你想阅读更多的字符串相似性算法,请查看本文。
- K 个最近邻居
- 欧几里德距离
- 余弦相似度
- Levenshtein 算法
- 贾罗-温克勒算法
- 奇异值分解(SVD) (不完全是相似性算法,但间接涉及相似性)
如果您想测试您的 ML 技能,请查看 【土星云】 ,这是一个可扩展、灵活的数据科学平台,有免费层和企业层。
感谢阅读!
如果你喜欢这篇文章,请务必 订阅 千万不要错过另一篇关于数据科学指南、技巧和提示、生活经验等的文章!
读完这篇文章后,你不仅应该对现有的各种 ML 模型有更好的了解,而且你还应该知道什么时候适合使用这些模型。
现在出去看看你能用 ML 解决什么问题!
一如既往,我祝你在数据科学的努力中一切顺利。如果你喜欢这篇文章,我会很感激你给我一个关注。:)
不确定接下来要读什么?我为你挑选了另一篇文章:
还有一个:
</10-most-practical-data-science-skills-you-should-know-in-2022-9487d7750e8a>
特伦斯·申
- 如果你喜欢这个,就 订阅我的媒介 获取内容!
- 同样,您也可以订阅我的独家简讯
- 跟我上LinkedIn其他内容
所有有意义的数据科学探索都应该是可复制的
原文:https://towardsdatascience.com/all-meaningful-data-science-explorations-should-be-reproducible-194edc25c9b6?source=collection_archive---------27-----------------------
凯文·Ku 在拍摄的照片
摘要
如果你没有时间,这里有 30 秒的版本:
- 如果您或您的团队正在进行一项并非完全浪费的数据科学探索工作,您需要以这样一种方式保存这项工作,以便您、您的团队或其他人可以在以后没有太多麻烦的情况下重新开始这项工作。一个想法的价值始于探索,而探索的价值始于以一种易于复制的方式分享。
- 在探索的时候,提到运行在你或你的团队可以访问的平台上的笔记本可能很有诱惑力,例如托管的 JupyterHub 、 Databricks 等。然而,这种方法经受住时间考验的概率很低。越难复制的作品,数月或数年后不被仔细研究的几率就越高。这种情况可能会增加接受先前探索所否定的假设的可能性,拒绝推荐的命题,或者更糟糕的是,重新进行得出相同结论的相同探索。
- 复制数据科学工作需要维护其依赖项的版本,即代码、数据(输入和输出)以及参数。此外,它还需要一个指南来解释问题是什么、解决方法、解决方案的假设和限制、潜在的未来工作、什么是代码执行环境以及如何在该环境中执行代码、数据位于何处以及在执行代码时如何访问/加载数据、对操纵代码和结果分析至关重要的关键参数和指标的解释,以及对结果和结论的简要分析。
- 建议的方法是将代码放在分布式版本控制系统中,如 GitHub ,库及其版本定义在显式文件中,如 requirements.txt ,参数和数据路径保存在嵌套文件结构中,如 yaml,一个基础设施描述文件,它定义了代码可以执行的环境,如 environment.yml 或 Dockerfile , 像 README.md 这样的用户指南,包含尽可能多的细节以方便手动步骤,例如,在外部平台上运行代码、加载数据、理解代码、分析结果等。
版本化探索工作的样本结构(作者提供照片)
如果你感兴趣并且有更多的时间,这里有一个更长的版本:
背景
数据科学探索是理解有助于 AI/ML 解决方案的技术方法的需求和可行性的过程。在写这篇文章的时候,我正在和一家时装零售商合作。这里有几个探索的例子,可能与时装零售商有关。请在评论中提供您对探索领域的想法,以便更广泛地了解探索的工作方式。
照片由 Artem Beliaikin 在像素上
- 我们可以使用图像特征来识别相似/互补的服装吗?
- 能否通过模拟评估折扣策略对服装库存的影响?
- 如果我们选择分配策略 X 而不是 Y,我们可以在客户订单履行上节省多少时间?
- 购买同一件衣服的不同款式会增加退货的可能性吗?
这些探索变化很大。从范围的角度来看,探索可以回答数据源上的一个简单问题,也可以回答需要对真实世界的流程进行建模的更复杂的问题。从人力资源的角度来看,它可以由单个专家来完成,也可以由几类专家组成的团队来完成。从持续时间的角度来看,它可以从一周到几个月不等。从一个领域的角度来看,它可以包括数据分析、概念的工程证明、算法实验或所有这三个领域的某种组合。
探险本身就是混乱的。不能保证它会产生一个好的、有用的结果。应用工程和科学的许多其他学科都是如此,例如航空、制药等。如果对这些领域的探索者的期望是尽可能多地保留每个重要实验的细节,那么我们为什么要降低标准,尤其是当我们的决定很有可能影响数百万人的生活时,这些决定往往会受到我们探索的影响。
目前,数据科学中的探索通常意味着编写一些代码来研究数据中的一些东西,以得出结论来回答问题或在平台中暴露问题/假设,这些平台允许轻松执行代码、分析结果,并保存探索表格、模型和图,这些表格、模型和图可与许多其他合作者共享/查看。Databricks 和谷歌联合实验室是基于云的平台的例子,被世界各地的组织和公司广泛采用。对于这些强大的平台,我们的工作无疑已经变得更好,因为在这些平台上完成探索已经变得明显更快了。对于这些平台的用户来说,通常的做法是只将探索作为笔记本(具有某些状态)存档在平台中。这是一种反模式,来自对数据科学领域影响很大的软件工程学科。这种方法有几个问题,可能会改变最初开发人员传达的事实:
- 能接触到笔记本的人可以修改密码
- 平台中的源代码和其他类型的文件可能被有权访问该环境的人删除/重命名/移动
- 如果代码读取的数据是实时数据,该数据可能会改变
- 数据和结果可能会被最近执行的最新数据所覆盖
- 平台可能是暂时的,可能会被清除
在上述任何一种情况下,由于平台的灵活性,很容易无意中导致问题。
建议的方法
建议的方法非常明显。我确信在我之前有成千上万的人提倡这一点。然而,这个问题如此重要,需要反复说明。
再现探索需要归档探索工作,包括探索工件、过程和细节,以保证它们的版本在很长时间内保持完整。这意味着我们执行探索的平台不应与归档平台相混淆。除非执行平台是专门为优化存档活动而设计的,例如,版本控制探测的所有方面,即使平台被清除,存档的长寿命,探测的“提升和转移”迁移等。
作者照片
我不具备这种平台的广泛知识。然而,就我所了解的情况来看,我还没有发现一个可扩展的平台能够保证探索的简单执行和持久存档。这可能会在不久的将来成为现实。在这一时刻到来之前,我们必须使用我们当前的武器库来制定可行的归档策略。所以,这里有一些建议:
- **数据版本:**将您的输入和输出数据保存为快照,如果可能的话,将版本化的快照保存在长期存储设备中。避免在代码的版本控制系统中对数据进行版本控制,因为它们是为不同的目的而构建的,维护小文件而不是大文件。
- **代码/参数版本:**在分布式版本控制系统中维护您的实验和分析代码和参数。将您的数据生成管道作为代码维护在版本控制系统中。如果不能保证数据的再现性,避免使用图形工具生成数据。应该明确提到代码和数据访问路径中使用的外部库。在一个单独的系统中维护参数可能很诱人,但是这种方法保持了它的简单性。
- **导读:**添加一篇小报道,讲述如何结合以上几点去理解和再现作品。报告也可以包含在代码版本中,因为它可能是一个小文件。避免在报告中使用大尺寸的图像。
请注意,我并不提倡在执行平台中进行归档。在执行平台中存档探索以便立即使用是非常有益的。然而,这种益处随着时间的推移而减少。
具体例子
我将提供一个具体的例子,这个例子是由我目前的探索工作方式启发而来的。如果您认为符合上述原则,请在评论中提供与您的观点相符的建议。了解所有的可能性真的很好。
我最近使用的一个堆栈包括以下内容:
- Python
- Azure 数据块
- 蔚蓝回购
- 蔚蓝数据湖
- 微软 Sharepoint
以下是我的建议,基于上面的堆栈:
**数据版本:**保留从 Azure datalake 中的数据库/Data lake/其他表/流中提取的所有非聚合/非连接但已过滤的输入,Azure Data lake 应该是长期存在的。数据版本控制技术仍处于起步阶段。使用先进的技术可能很诱人,例如三角洲湖,但是要理解它的局限性。对于输出来说,保存生成图或分析的数据比保存图和分析本身更重要。对于探索来说,保存几个版本就足够了,这可以通过简单的策略来管理,例如,遵循单调递增的数字(例如,整数、时间戳等)的目录。如果您的堆栈基于其他一些公共/私有云,请选择允许保存各种文件格式的 datalake,包括但不限于 csv 、 parquet 、 avro 、 png 、 pkl 、 json 、 yml 等。
**代码/参数版本:**在分布式版本控制领域,技术已经有了显著的改进,不仅在效率方面,而且在存储库到不同平台的可移植性方面。无论你的代码是在 Azure repos 、 Bitbucket 还是 Github 中维护,都没什么区别。在存储库中维护所有代码。添加以下文件以提供依赖关系信息,即使您没有明确使用它们:
- requirements.txt 中的库及其版本号
- 执行环境文件,如 conda 的 environments.yml、Docker 的 Dockerfile 或 yaml 文件中的 Databrick 的集群描述
- json 或 yml 文件中的代码操作参数、数据访问路径(及其版本号)、外部集成信息(不惜一切代价避免包含敏感信息)
**指南:**在代码库中添加一个 README.md 文件,该文件包括以下内容:
- 联系信息,例如开发人员的姓名、电子邮件地址、角色和团队
- 对问题、解决方案、假设/限制和未来工作的简要描述。浅析勘探及其结论。这些信息通常包含在演示材料中,如 powerpoint 或 pdf 文件。在这种情况下,将文件保存在 Sharepoint(或您拥有的任何文档存档解决方案)中,并在本指南中添加指向该文件的链接。如果探索使用了其他人发表的方法,请参考出版物。
- 对执行环境的简要描述,解释集群配置、库安装、数据文件加载、机密管理等。如果存在支持文件,例如 requirements.txt,请参考这些文件。如果您使用模型管理系统,例如 MLflow ,请提及实验名称。
放弃
在这篇文章中,我根据常识和经验表达了我的观点。我不认为它会符合你的现实。然而,就像我的代码一样,我的观点也有版本。下周或下个月不会有太大变化,但明年可能会有很大变化。如果你不同意我的观点,或者更喜欢我的建议,请在评论中提供反馈。在创作这个作品的时候,我听了比尔·马厄的演讲,他提倡说出你的想法。我可能受到了一些影响。
如何使用倾向假设的方法进行正确的推理
原文:https://towardsdatascience.com/all-models-are-wrong-a75103196cdb?source=collection_archive---------34-----------------------
为什么所有的模型都是错的,但有些是有用的。
米歇尔·玛特隆在 Unsplash 上的照片
统计是基于假设的。如果这些假设变得无效,基于这些假设的所有结论同样也变得无效。
“所有的模型都是错误的,但有些是有用的”——乔治·博克斯
宾夕法尼亚大学的统计学家提出的一种[假设倾斜方法](http://Statistics is a practice that's based on assumptions. If those assumptions become invalid, all conclusions based on those assumptions likewise become invalid.)概述了如何从我们的数据中得出更有说服力的结论。该方法描述了一种用于解释模型系数以及置信区间计算的新语言,该置信区间计算对于基于假设的方法是稳健的。
虽然这种方法有细微差别,但它的计算效率很高,实现起来也很简单。
技术 TLDR
- 在实践中,保证一个正确指定的模型是非常困难的。“真实”模型要求包括所有相关预测值,并且噪声项为 IID。
- 采用假设-精益方法。因为通常不可能证明我们有所有相关的预测值,我们简单地假设数据是独立同分布的(IID)。
- **考虑到仅使用 IID 假设,我们改变了置信区间的计算。**讨论的两种方法是三明治方法和我们观察数据的自助法。
好吧,但是到底发生了什么?
让我们慢一点,理解我们如何从数据中得出结论。
一个简单的例子
在本例中,我们希望对力的方程进行建模:
图 1:力的方程式。图片作者。
这种关系是倍增的,两个预测变量是质量(M)和加速度(A)。理论上,如果我们有一个线性模型以及一些质量和加速度数据,我们可以完美地预测力。对吗?
是的,但我们不是生活在理论中。我们生活在现实世界中,人际关系模糊而混乱。例如,如果我们测量一个物体从建筑物上掉下来的力会发生什么?突然,我们不得不包括阻力(D)和重力常数(g)。等式变得更加复杂:
图 2:下落物体的力的方程式— 来源。图片作者。
风呢?下雨了,水滴打在物体上怎么办?
如果我们不考虑所有这些因素,我们可能会得到不正确的预测系数估计。用数学术语来说,我们下面的 β 可能不完全是 1.0。
图 3:力方程的线性回归。图片作者。
力是一个众所周知的等式,但如果我们试图用一个未知的关系来建模,会发生什么呢?我们能知道所有相关的预测因素都包括在内吗?
这是乔治 E.P 博克斯的观点。模型简化了复杂的现象,所以它们从来都不是完美的。
模型误差的类型
尽管大多数模型都是“不完美的”,但有些不完美比其他的更糟糕。这里,我们将讨论两类错误:
第一类是噪声 (ε)。噪声是我们数据中的波动,它完全独立于一切,也就是说,即使我们有完美的数据,我们也无法对其建模。在上面的例子中,噪声可能是力的非系统测量误差。
几乎所有的建模技术都假设因变量中存在噪声。
第二类被称为误差,由于模型错误设定 ( η )。它不包含在大多数统计建模框架中。相反,我们经常假设一个“完美”的模型,因此 η 为零。
但是如果博克斯博士是对的,为什么我们要假设模型是正确指定的呢?这个假设允许我们做出因果结论。如果我们有一个完美的力的方程,我们可以随便地宣称 F=M*A。
在实践中,我们从来没有一个完美的模型,因此通常假设由于模型设定错误而导致的误差只是噪声。
问题是
这个假设是个问题。统计学是一种依赖于假设的精确方法。如果假设是错误的,就不能保证结论是准确的(尽管它们可能接近正确答案)。
现在,我们知道缺少预测变量是有问题的,所以让我们解决另一个关键假设:我们的模型有能力来拟合 X 和 y 之间的关系。因此,如果我们的数据显示线性关系,我们将使用线性模型。如果关系是抛物线,我们应该用 X 代替 X。
如果我们无法满足这一假设,那么在查看新数据时,我们可能会观察到非常不同的拟合值。
图 4:错误指定的指数数据线性模型和正确指定的线性模型之间的差异。图片作者。
以图 4 为例。我们可以看到左边有一个错误指定的模型;X 和 Y 之间的关系是非线性的,但我们用线性模型拟合。如果我们选择样本 1 (S1 ),它的 X 值很小,那么我们直线的估计斜率将比我们选择更大的 X 值(S2)要小得多。
现在在实践中,我们希望有整个数据集的代表性样本,但这个例子强调了一个错误指定的模型对数据中的微小变化是多么敏感。
另一方面,如果我们正确地指定了我们的模型,我们应该看到 X 的任何样本都有相似的斜率,如右图所示。此外,随着我们适应更大的样本量,我们的准确性将会提高。对于一个错误指定的模型,情况可能并非如此。
解决方案
为了解决这个问题,宾夕法尼亚大学的统计学家开发了一种不假设模型正确的方法。
这种假设-精益方法只要求我们的数据是独立的和同分布的(IID)。在英语中,IID 意味着我们的观察不是系统相关的,它们是从同一人群中随机抽样的。
只要有一个 IID 假设,我们就可以解释博克斯悖论,并对我们的模型做出正确的解释。然而,我们确实失去了因果解释,因为我们没有假设我们的模型包括所有相关的预测。
下面是开发一个有效的假设精益模型所需的两个变化:
1 —置信区间计算
正如你可能想象的那样,在一个不正确指定的模型中,置信区间(CI)更大——我们对自己的估计不太有信心。为了说明一个潜在的错误模型,提出了两种方法。
第一种称为三明治方法,使用异方差一致性标准误差来估计对模型错误设定稳健的置信区间。这些估计的计算超出了本文的范围,但是在大多数编程语言中都有进行计算的库。
第二种叫做 bootstrap 标准误差,包括多次重新采样数据,并从重新采样的分布中得出百分位数。同样,计算也超出了本文的范围,但是 bootstrap 采样在大多数编程语言中也很常见。
每种方法的估计置信区间几乎没有差别,因此您可以使用任何一种方法。第一种方法的主要优点是计算效率更高。然而,bootstrap 抽样给你更多的数据来得出结论——例如,你可以用 QQ 图来检验正态假设。
2 —口译语言
我们还需要考虑因果关系的缺失。通常,在解释模型系数时,我们会说:
“对于 X 中的一个单位变化,我们将看到 Y 中的β单位变化,保持所有其他预测因子不变。”
这里 beta ( β )是我们的线性回归系数。然而,这种语言假设了一个正确指定的模型,因此为了涵盖我们有一个不正确模型的可能性,我们改为说:
β是在所有其他预测值保持不变的情况下,X 的单位差与 Y 的最佳线性近似值之差
这是不是矫枉过正?
这是一个很难简明回答的问题。
在大多数数据科学应用中,我们不需要做到完美。但是,如果你想尽可能做到统计上的严谨,你应该采用这个框架。
在大多数行业应用中,如果我们希望从一个模型中开发因果推断,我们希望包括许多预测因素,以开发最可靠的模型。然而,如果你同意 Box 的基本原理,完美的模型是不可能的。
作者建议使用“不正确的”模型进行探索性推理,然后使用 A/B 检验来确定真正的因果关系。
实施说明
- 模型的正确说明被广泛接受。如果你不是资深员工,在向团队其他成员推销之前,最好能真正理解这些细微差别。
- 有时候,我们不需要真正的因果关系来做出决定。如果我们有一个“真实”模型的很好的近似,我们仍然可以开发精确的推论——我们只是不能保证准确性。
感谢阅读!我将再写 43 篇文章,将“学术”研究引入 DS 行业。查看我对开发 正确 型号的链接/想法的评论。
所有模型都是错的,但有些是随机的…
原文:https://towardsdatascience.com/all-models-are-wrong-but-some-are-random-25ff1491406f?source=collection_archive---------33-----------------------
小窍门
比较各种采样模型,以确定哪种模型产生最准确的结果。
TL;博士*——如果你不想经历整个分析,而只是对结果感兴趣,跳到随机模型部分,然后跳到本文结尾的总结*
我从丹尼尔·瓦坎蒂那里学到了如何使用蒙特卡洛模拟来预测一个团队在一段时间内可以完成多少工作。Dan 使用他的可操作敏捷工具演示了如何从团队过去的数据中随机抽样来运行这些模拟。运行数千次这样的模拟可以帮助获得一个团队可以完成多少工作的概率预测。
本文的其余部分取决于对使用团队吞吐量的蒙特卡罗模拟的基本理解。下面的#DrunkAgile 视频是我和 Dan 之间的一段对话,概述了这项技术。
醉酒敏捷第三集——使用蒙特卡罗模拟的概率预测
这些 MC 模拟的中心过程是从过去的数据中随机抽样的概念。利用团队的真实数据,预测他们可能的未来。学数学的学生会告诉你,并非所有的随机变量都是一样的。我们可以使用多种不同的模型从过去的数据中“随机”取样。这种分析是要弄清楚不同的随机抽样模型表现如何。我们很好地回测了这些模型的预测,并确定了哪些模型在什么条件下表现最好。
随机性模型
照片由 Erica Li 在 Unsplash 上拍摄
下面是我们将用来做预测的六个模型。这些模型的实现复杂程度不同。Random 是最简单的,而 Markov Chain By Range 是最复杂的。正如所料,从速度的角度来看,Random 运行速度最快,而 Markov Chain By Range 执行速度最慢。
随意
这是最简单最纯粹的随机抽样模型。它从均匀分布中生成一个随机数。然后,使用源数据集的大小对该数字进行缩放。选择由缩放数字表示的源数据集中的一天,并将其吞吐量用作模拟中第二天的样本。
工作日和周末
这个模型类似于随机模型,除了从两个不同的集合中进行采样。源数据分为两组——
集合 1:属于工作日(周一至周五)的所有数据
集合 2:属于周末(周六和周日)的所有数据
如果我们模拟的未来日期是工作日,我们从集合 1 中取样,否则从集合 2 中取样。预期周末设置将具有较低的吞吐量,并且以这种方式进行采样将为我们提供更好的结果。
星期几
该模型将“工作日和周末”模型中使用的抽样方法向前推进了一步。我们没有将源数据分成两组,而是分成 7 组
集合 1:属于周一的所有数据
集合 2:属于周二的所有数据
集合 3:属于周三的所有数据
集合 4:属于周四的所有数据
集合 5:属于周五的所有数据
集合 6:属于周六的所有数据
集合 7:属于周日的所有数据
根据模拟的未来日期属于一周中的哪一天,我们选择要从中采样的集合。例如,如果被模拟的一天是星期三,我们将从集合 3 中取样。我们期望这个模型能够更好地模拟一周中某些天吞吐量的下降(或上升)。
吞吐量马尔可夫链
该模型使用马尔可夫链来分配下一个样本的概率,然后使用这些概率伪随机地选择下一个样本。马尔可夫链表示从一种状态转移到另一种状态的概率。
马尔可夫链示例(维基共享)
例如,吞吐量 0 后跟吞吐量 1 的概率是 35%。首先,我们根据过去的数据创建马尔可夫链。我们将源数据按日期排序,这样就可以按时间顺序遍历过去。当我们遍历源数据时,每个唯一的吞吐量都成为一个状态。从一个吞吐量转移到另一个吞吐量会增加这两个状态之间的边缘权重。
此后,我们通过将从状态 1 到状态 2 的边的权重除以从状态 1 发出的边的总权重来确定从一个状态移动到另一个状态的概率。知道从一个状态移动到所有其他状态的概率被用来伪随机地选择在模拟中第二天要采样的日期。预期这将比纯粹的随机选择更接近团队的吞吐量趋势。
按范围划分的马尔可夫链
该模型将来自团队的源数据分割成三个集合,然后在它们之间创建一个马尔可夫链。数据分割如下——
集合 1:吞吐量最低三分之一的所有数据(L)
集合 2:吞吐量中间三分之一的所有数据(M)
集合 3:吞吐量最高三分之一的所有数据(H)
注意—周末往往会使这些 H、M 和 L 分类的分布发生偏斜。我们使用与“工作日和周末”模型相同的程序对周末进行采样。如上所示,工作日吞吐量分为三组。
正如我们在创建吞吐量马尔可夫链时所做的那样,我们按照时间顺序遍历源数据。我们创建三个状态(H、M 和 L)之间的马尔可夫链。然后,我们使用这些状态之间的转移概率来导出用于模拟的样本吞吐量。我们的期望是,这个模型可以获得团队吞吐量的季节性,并使用它来有效地进行预测。
全体
该模型是上述五种模型的组合。每个运行集包含 2500 个模拟。在集合模型中,在每次蒙特卡罗模拟开始时,从上述五个模型中随机选择一个。这就创建了一个模型,它可以从所有五个编码模型中收集结果,并将它们作为一组结果呈现出来。这种方法已被 NOAA 成功地用于创建飓风的一致预测。人们的期望是,这一模型将产生一套平衡的预测。
数据
为了回测这里描述的模型,我们将使用 86 个不同团队的真实数据。对于这些团队中的每一个,我们获取了这些团队在 2021 年 1 月 10 日和 2021 年 3 月 17 日之间每天的实际吞吐量。我们将使用一个 28 天的滑动窗口作为运行蒙特卡罗模拟的源数据(稍后将详细介绍)。对于每个团队,我们将做出并测试 5、10、14 和 20 天的预测。对于滑动窗口,这将导致每个团队针对每个模型测试总共 103 个预测。每次预测我们将运行 5000 次模拟。
总之,我们将运行超过 2.65 亿次模拟,以测试 6 个模型的有效性,每个模型为 86 个不同的团队做出 103 个预测。这应该会导致在各种不同的条件下对这些模型进行一些非常健壮的测试。
疯狂的方法
我们想测试预测的准确性。在我们继续之前,我们应该建立一个准确性的衡量标准。测量单点预测的准确性比概率预测的准确性相对容易。对于单点确定性预测,我们可以查看预测值与实际值的差距。概率结果就没那么容易了。
布赖尔乐谱
为了判断概率结果的准确性,我们将使用 Brier 评分。为了解释这个分析的结果,理解 Brier 分数不是必要的。读者只要知道 Brier 评分是判断概率预测准确性的标准方法就足够了,分数越低,预测越好。
生成预测
如前所述,为了运行模拟,我们将使用 28 天的滑动窗口作为采样的源数据。对于每个团队,我们将以前 28 天(1/10 到 2/7)的吞吐量作为源数据。使用这些第一个数据集,我们将尝试预测团队在 5、10、14 和 20 天内可以产生多少吞吐量。因为我们是从概率上来看的,所以我们将在以下两种概率下生成预测—
第 15 百分位预测 —我们有 15%的信心团队可以做到这一点或更多。
第 85 百分位预测 —我们有 85%的信心团队可以做到这一点或更多。
飓风伊尔玛的预测与实际
然后,我们将这些预测与团队完成的实际吞吐量进行比较。预计 70%的情况下,实际吞吐量将介于这两个预测值之间。然后,我们将所有数据向前移动一天,并使用新的一组 28 天(1/11 到 2/8)的吞吐量作为源数据。再次进行 5、10、14 和 20 天的预测,并将它们与实际吞吐量进行比较。
这一过程将在我们评估的 6 款车型中重复进行。然后,我们应该能够通过评估实际吞吐量落入第 85–15 百分位“圆锥”的频率来判断我们的模型的准确性。Brier 分数将用于捕捉模型在团队和预测持续时间中的整体表现。
结果呢
首先,让我们从使用每个模型的所有团队的所有预测表现的总体评估开始。下面显示的预测圆锥是整个数据集中第 15 百分位(深蓝色)、第 85 百分位(浅蓝色)和实际值(橙色)的累积轨迹。正如我们所看到的,我们的实际总和很好地跟踪了我们 85%到 15%的信心预测。它似乎更倾向于第 15 百分位。这是否意味着我们的预测通常是悲观的?
总体预测圆锥
上图的分析充其量是一个嗅觉测试。它只是告诉我们,我们的预测并没有错。这张图表中的各种元素需要单独梳理和探究。让我们从笼统的概括转向一些具体的细节。单个模型的表现如何。下面是由模型过滤的同一个圆锥体的网格。
模型预测锥
我们看到,对于大多数模型来说,实际(橙色)线在圆锥的中间跟踪得相当好。除了我们最复杂的模型——马尔可夫链。该模型在预测吞吐量的总体趋势方面似乎不错,但在预测实际吞吐量方面相当糟糕。这一个模型的结果就是为什么总体平均值似乎是悲观的。
对模型进行排序
使用我们为模型收集的 Brier 分数,我们可以对我们的模型进行排名,看哪些模型对每个团队和预测日范围表现最好。我们可以尝试确定一个模型在预测 5、10、14 和 20 天时对一个团队的效果如何。基于 Bier 评分,我们可以对 6 个模型进行排名。提醒一下,Brier 分数越低越好。例如,我们数据集中的一个团队在评分和排名时会产生以下预测排名—
样本分数和排名
我们解释这些结果的方式是,在为团队 A 预测他们在 5 天内可以完成的工作量时,随机抽样模型在准确性方面排名第一,星期几模型排名最后(第六)。同样,在预测 14 天后,按吞吐量划分的马尔可夫链最准确(第 1),按范围划分的马尔可夫链最不准确(第 6)。
在所有 86 个团队和 4 个预测日范围内,总共有 300 多个机会对模型进行排名。这些等级使用相同预测日范围的相同基础数据来比较模型。这些同类比较可以让我们更好地了解哪种模型在每种情况下表现更好。它还可以帮助我们对哪些模型在大多数情况下表现良好,哪些表现最差做出一些概括的陈述。下表显示了每个型号达到某个等级的频率。
模特排名
标题“1”下的列表示该模型在每个单独的上下文中最擅长生成预测的频率。“6”以下的数字是他们预测最差的频率。这里有明显的赢家和输家。
在这 86 支球队的背景下,似乎最简单的模型——纯随机抽样表现最好。在超过 66%的案例中,它排在第一位。在超过 87%的预测上下文中,Random 是表现最好或第二好的模型。
同时,我们也有我们整体表现最差的模型。最复杂的模型——马尔可夫链表现最差。在超过 66%的上下文中,马尔可夫链是表现最差的模型。随机的,我们表现最好的模型在任何情况下都没有排名第六。
模型排名的频率
不过有一点需要注意,即使是我们表现最差的模型也在 36 个案例中排名第一。虽然我们可以说,一般来说,我们有一个明确的赢家和输家,进入细节,一般来说,“失败”的模型可能对某些团队和预测日范围表现更好。然而,深入地看,这似乎发生在具有高度不稳定和不稳定吞吐量的团队中。事实上,按范围划分的马尔可夫链是性能最好的模型,它应该(在大多数情况下)指向过程改进和生产能力稳定的机会。
机器学习蒙特卡罗
我们可以在这个分析中更上一层楼。按团队汇总这些排名可以帮助我们了解这些模型在团队中的表现。哪些模型最适合预测每个团队的吞吐量?当我们按团队看这些排名时,我们确实看到不同的模型更适合不同的团队。
按团队列出的模型平均排名
上图显示了一个团队的平均排名。图表上模型的点越低,该模型对该团队的预测就越好。这些信息现在可以用于确定每个团队应该使用哪个模型进行预测。
蒙特卡洛引擎现在可以成为一个学习系统。我们可以根据特定团队在过去几个月中表现最好的模型来切换模型。我们对未来使用哪种模式的选择现在是由机器做出的动态选择,而不是根据个人偏好进行选择。
按团队对模特进行排名
正如所预料的,当聚集到团队级别时,模型如何被分级的分布与非聚集等级的分布非常相似。随机模型是大多数团队的首选模型,马尔可夫链是大多数团队的最后选择模型。
预测范围的影响
我们可以用这些数据回答的另一个问题是,当我们预测越来越远时,我们的预测会怎么样。随着我们对未来的预测越来越深入,欧石南的得分会发生什么变化?下图试图回答这个问题。
超出预测范围的模型的 Brier 分数
首先要注意的是,这张图也证实了之前的结论。因为 Brier 分数越低越好,所以随机线(粉色)位于所有其他线的下方。马尔可夫链的直线距离远高于其他所有直线距离。按吞吐量划分的马尔可夫链是第二个最成功的模型。
我们确实看到图中所有的线都有上升的趋势。随着我们预测的天数的增加,我们的模型的准确性下降。他们仍然大部分保持他们的相对位置,但是他们的准确性的绝对测量在更长的预测期间变得更差。
摘要
让我们通过回答我们详细探究的问题来总结这个分析。
一款车型是否总体上优于其他车型?
是的,看起来最简单的模型——Random out 执行更复杂的采样模型。按范围划分的马尔可夫链是表现最差的模型。其他模型都落在中间的某个地方。
某些型号更适合某些团队吗?
是的,似乎即使是总体表现不佳的模型也更适合预测某些球队。对此进行更深入的分析可以发现,这些团队的系统非常不稳定。
模型性能会随着我们对未来的预测而改变吗?
总的来说,随着我们对未来的预测,模型性能似乎会受到影响。比起长期预测,我们更喜欢做短期预测。
在蒙特卡罗模拟中,我应该使用哪些采样模型?
从随机开始,除非你想做我在这里做过的学术练习,否则就随机停止。这是本次回测分析中最成功的一次。如果随机没有给你好的结果,很可能是系统的问题,而不是模型的问题。纯随机采样也是最容易实现的。这无疑是巴克模型最大的支持。
所有熊猫切()你应该知道把数值数据转换成分类数据
原文:https://towardsdatascience.com/all-pandas-cut-you-should-know-for-transforming-numerical-data-into-categorical-data-1370cf7f4c4f?source=collection_archive---------1-----------------------
所有的熊猫切()你应该知道如何将数字数据转换成分类数据(图片由作者使用canva.com)
数值型数据在数据分析中很常见。通常情况下,您会得到连续的、大范围的或高度倾斜的数值数据。有时,将这些数据绑定到离散的区间会更容易。当值被分成有意义的类别时,这有助于执行描述性统计。例如,我们可以将确切的年龄分为幼儿、儿童、成人和老人。
Pandas 内置的cut()
函数是一种将数值数据转换成分类数据的好方法。在本文中,您将学习如何使用它来处理以下常见任务。
- 离散成大小相等的箱
- 添加自定媒体夹
- 向垃圾箱添加标签
- 用
right=False
配置最左边的边缘 - 用
include_lowest=True
包括最低值 - 将一只
IntervalIndex
传给bins
- 带
retbins=True
的回收箱 - 创建无序类别
请查看笔记本获取源代码。
1.离散成大小相等的箱
cut()
最简单的用法必须有一个列和一个整数作为输入。它将值离散化到大小相等的容器中。
df = pd.DataFrame({'age': [2, 67, 40, 32, 4, 15, 82, 99, 26, 30]})df['age_group'] = pd.**cut(df['age'], 3)**
(图片由作者提供)
你观察过 年龄组 栏的那些区间吗?那些间隔值在开始有一个圆括号,在结尾有一个方括号,例如**(1.903, 34.333]**
。基本意思是圆括号边的任何值都不包含在区间内,方括号边的任何值都包含在内(数学上称为开区间和闭区间)。
现在,让我们来看看新的专栏 age_group 。
df['age_group']
(图片由作者提供)
它显示带有 3 个标签值的dtype: category
:**(1.903, 34.333]**
、**(34.333, 66.667]**
和**(66.667, 99.0]**
。这些标签值按照符号<
的指示进行排序。在主题后面,为了生成大小相等的容器,间隔计算如下:
interval = (max_value — min_value) / num_of_bins
= (99 - 2) / 3
= 32.33333 (<--32.3333-->] < (<--32.3333-->] < (<--32.3333-->] **(1.903, 34.333] < (34.333, 66.667] < (66.667, 99.0]**
2.添加自定媒体夹
让我们将上述年龄值分为 4 个自定义组,即 0-12 岁、12-19 岁、19-60 岁、61-100 岁。为此,我们可以简单地将列表中的值([0, 12, 19, 61, 100]
)传递给参数bins.
df['age_group'] = pd.cut(df['age'], **bins=[0, 12, 19, 61, 100]**)
(图片由作者提供)
我们在新列 age_group 中添加了年龄的组值。通过观察柱子
df['age_group']0 (0, 12]
1 (61, 100]
2 (19, 61]
3 (19, 61]
4 (0, 12]
5 (12, 19]
6 (61, 100]
7 (61, 100]
8 (19, 61]
9 (19, 61]
Name: age_group, **dtype: category**
Categories (4, interval[int64]): **[(0, 12] < (12, 19] < (19, 61] < (61, 100]]**
我们可以看到dtype: category
有 4 个有序的标签值:(0, 12] < (12, 19] < (19, 61] < (61, 100]
。
让我们按列**年龄组:**对数据帧进行排序
df**.sort_values('age_group')**
(图片由作者提供)
让我们数一数有多少个值落入每个容器中。
**df['age_group'].value_counts().sort_index()**(0, 12] 2
(12, 19] 1
(19, 61] 4
(61, 100] 3
Name: age_group, dtype: int64
3.向垃圾箱添加标签
将这些年龄组值标记为“< 12”、“青少年”、“成人”、“老年人”更具描述性。为此,我们可以简单地将列表中的值传递给参数labels
bins=[0, 12, 19, 61, 100]
**labels=['<12', 'Teen', 'Adult', 'Older']**df['age_group'] = pd.cut(df['age'], bins, **labels=labels**)
(图片由作者提供)
现在,当我们查看该列时,它显示的是标签
df['age_group']0 <12
1 Older
2 Adult
3 Adult
4 <12
5 Teen
6 Older
7 Older
8 Adult
9 Adult
Name: age_group, dtype: category
Categories (4, object): **['<12' < 'Teen' < 'Adult' < 'Older']**
同样,在分类和计数时,它会显示标签
(图片由作者提供)
**df['age_group'].value_counts().sort_index()**<12 2
Teen 1
Adult 4
Older 3
Name: age_group, dtype: int64
4.用right=False
配置最左边的边缘
熊猫cut()
中有一个参数right
用来配置 bin 是否包含最右边。right
默认为True
,表示[0, 12, 19, 61, 100]
这样的仓表示(0,12]
、(12,19]
、(19,61]
、(61,100]
。为了包含最左边的边,我们可以设置right=False
:
pd.cut(df['age'], bins=[0, 12, 19, 61, 100], **right=False**)0 **[0, 12)**
1 **[61, 100)**
2 **[19, 61)**
3 **[19, 61)**
4 **[0, 12)**
5 **[12, 19)**
6 **[61, 100)**
7 **[61, 100)**
8 **[19, 61)**
9 **[19, 61)**
Name: age, dtype: category
Categories (4, interval[int64]): [**[0, 12) < [12, 19) < [19, 61) < [61, 100)**]
5.用include_lowest=True
包括最低值
假设您想将上述年龄值分为 2–12,12–19,19–60,61–100。将箱子设置为[2, 12, 19, 61, 100]
时,您将获得包含NaN
的结果。
df['age_group'] = pd.cut(df['age'], bins=[2, 12, 19, 61, 100])
(图片由作者提供)
我们得到一个NaN
,因为值2
是第一个面元(2.0, 19.0]
的最左边的边缘,并且不包括在内。为了包含最低值,我们可以设置include_lowest=True
。或者,您可以将right
设置为False
以包含最左边的边缘。
df['age_group'] = pd.cut(
df['age'],
bins=[2, 12, 19, 61, 100],
**include_lowest=True**
)
(图片由作者提供)
6.将一个IntervalIndex
传递给bins
到目前为止,我们已经向bins
传递了一个数组。除了数组,我们还可以传递一个IntervalIndex
。
让我们创建一个有三个箱子(0, 12]
、(19, 61]
、(61, 100]
的IntervalIndex
:
**bins = pd.IntervalIndex.from_tuples([(0, 12), (19, 61), (61, 100)])** IntervalIndex([**(0, 12], (19, 61], (61, 100]**],
closed='right',
dtype='interval[int64]')
接下来,让我们把它传递给论点bins
df['age_group'] = pd.cut(df['age'], **bins**)
(图片由作者提供)
请注意,IntervalIndex
未覆盖的值被设置为NaN
。基本上,为bins
传递一个IntervalIndex
会准确地得到那些类别。
7.带retbins=True
的回收箱
有一个名为retbin
的参数用于返回 bin。如果它被设置为True
,结果将返回bins
,当bins
作为单个数值被传递时,它是有用的
result, bins = pd.cut(
df['age'],
**bins=4, # A single number value**
retbins=True
) # Print out bins value **bins**
array([ 1.903, 26.25 , 50.5 , 74.75 , 99\. ])
8.创建无序类别
ordered=False
传递标签时会产生无序类别。此参数可用于允许非唯一标签:
pd.cut(
df['age'],
bins=[0, 12, 19, 61, 100],
labels=['<12', 'Teen', 'Adult', 'Older'],
ordered=False,
)0 <12
1 Older
2 Adult
3 Adult
4 <12
5 Teen
6 Older
7 Older
8 Adult
9 Adult
Name: age, dtype: category
Categories (4, object): **['<12', 'Teen', 'Adult', 'Older']**
结论
Pandas cut()
函数是一种将数值数据转换成分类数据的快速便捷的方法。
我希望这篇文章能帮助你节省学习熊猫的时间。我建议你查看一下关于cut()
API 的文档,并了解你可以做的其他事情。
感谢阅读。请查看笔记本获取源代码,如果你对机器学习的实用方面感兴趣,请继续关注。
你可能会对我的其他一些熊猫文章感兴趣:
- 熊猫系列实用介绍
- 使用熊猫方法链接提高代码可读性
- 如何对熊猫数据帧进行自定义排序
- 为了数据分析你应该知道的所有熊猫移位()
- 何时使用 Pandas transform()函数
- 你应该知道的熊猫串联()招数
- 熊猫的应用()和变换()的区别
- 所有的熊猫合并()你应该知道
- 在 Pandas 数据框架中处理日期时间
- 熊猫阅读 _csv()你应该知道的招数
- 用 Pandas read_csv()解析日期列应该知道的 4 个技巧
更多教程可以在我的 Github 上找到
所有熊猫 groupby()你应该知道分组数据和执行操作
原文:https://towardsdatascience.com/all-pandas-groupby-you-should-know-for-grouping-data-and-performing-operations-2a8ec1327b5?source=collection_archive---------1-----------------------
熊猫帮助你开始数据分析的提示和技巧
由absolute vision在 Unsplash 上拍摄的照片
在探索性数据分析中,我们经常希望通过一些类别来分析数据。在 SQL 中,GROUP BY
语句将具有相同类别值的行分组到汇总行中。在 Pandas 中,SQL 的GROUP BY
操作是使用类似命名的groupby()
方法执行的。Pandas 的groupby()
允许我们将数据分成不同的组来执行计算,以便更好地进行分析。
在本文中,您将学习“分组”过程(拆分-应用-合并)以及如何使用 Pandas 的groupby()
功能对数据进行分组和执行操作。这篇文章的结构如下:
- 什么是熊猫
groupby()
以及如何访问群组信息? - “分组依据”流程:拆分-应用-合并
- 聚合
- 转换
- 过滤
- 按多个类别分组
- 用
as_index
重置索引 - 处理缺失值
为了演示,我们将使用 Kaggle 上的 Titanic 数据集。
df = pd.read_csv('data/titanic/train.csv')
df.head()
泰坦尼克号数据集(图片由作者提供)
请查看笔记本获取源代码。
1.什么是熊猫groupby()
以及如何访问群组信息?
groupby()
的作用是在我们想按某些类别分析数据的任何时候。最简单的调用必须有一个列名。在我们的例子中,让我们使用 性别 列。
df_groupby_sex = df.**groupby('Sex')**
这句话的字面意思是我们想通过不同的性别值来分析我们的数据。通过对结果调用type()
函数,我们可以看到它返回了一个 DataFrameGroupBy 对象。
>>> **type(df_groupby_sex)**pandas.core.groupby.generic.**DataFrameGroupBy**
groupby()
函数返回一个 DataFrameGroupBy 对象,但本质上描述了原始数据集的行是如何被拆分的。我们可以使用一些属性和方法来访问组信息
我们可以使用ngroups
属性来获得组的数量
>>> df_groupby_sex.**ngroups**2
使用groups
属性获取 groups 对象。列表中的整数就是行号。
>>> df_groupby_sex.**groups**{**'female':** [1, 2, 5, 8, 10, 21, 22, 25, 26, 27, 36, 41, 44, 47, 51, 58, 60, 65, 70, 71, 72, 76, 77, 78, 80, 87, 88, 93, 94, 95, 100, 102, 104, 105, 109, 113, 116, 119, 120, 121, 123, 129, 134, 138, 144, 146, 147, ...], **'male':** [0, 3, 4, ...]}
我们可以使用size()
方法来计算和显示组大小。
>>> df_groupby_sex**.size()**Sex
female 256
male 456
dtype: int64
要预览分组,我们可以调用first()
或last()
来预览第一个或最后一个条目的结果。
df_groupby_sex**.first()**df_groupby_sex**.last()**
(图片由作者提供)
我们可以使用get_group()
方法来检索一个已创建的组
df_female = df_groupby_sex**.get_group('female')**
df_female.head()
(图片由作者提供)
2.“分组依据”流程:拆分-应用-合并
一般来说,“分组依据”指的是涉及以下一个或多个步骤的过程:
(1)将数据分组。(2).将函数独立地应用于每个组,(3)将结果组合成数据结构。
在这些当中,熊猫
groupby()
被广泛用于分步法,它是最简单的。事实上,在许多情况下,我们可能希望与这些群体一起做一些事情。在应用步骤中,我们可能希望执行以下操作之一:聚合:计算每个组的汇总统计。例如,总和、平均值或计数。
转换:执行一些特定于组的计算,并返回一个相似索引的对象。例如,标准化组内的数据或替换组内缺失的值。
过滤:根据评估
True
或False
的分组计算,丢弃一些分组。例如,丢弃属于只有几个成员的组的数据,或者根据组总和或平均值过滤掉数据。By 熊猫官方教程: groupby:拆分-应用-合并 [1]
在下面的文章中,我们将探索“分组”过程的真实用例。
2.聚合
一旦 DataFrameGroupBy 被创建,几种方法可用于对分组数据进行计算。一个显而易见的方法是执行聚合——为每个组计算一个汇总统计。
带列
对特定列执行聚合
>>> df.groupby('Sex')**.Age.max()**Sex
female 63.0
male 80.0
Name: Age, dtype: float64
用agg()
方法
有一个叫做agg()
的方法,它允许我们一次指定多个聚合函数。
df.groupby('Sex').Age.**agg(['max', 'min', 'count', 'median', 'mean'])**
(图片由作者提供)
有时,您可能更喜欢使用自定义列名:
df.groupby('Sex').Age.agg(
**sex_max=('max')**,
**sex_min=('min')**,
)
(图片由作者提供)
如果您想使用自定义聚合函数:
**def categorize(x):
m = x.mean()
return True if m > 29 else False**df.groupby('Sex').Age.agg(['max', 'mean', **categorize**])
(图片由作者提供)
我们也可以使用 lambda 表达式
df.groupby('Sex').Age.agg(
['max', 'mean', **lambda x: True if x.mean() > 50 else False**]
)
(图片由作者提供)
不带列
事实证明,当编写一个groupby()
时,我们实际上并不需要指定一个像年龄这样的列。如果没有列,它将对所有数字列执行聚合
df.**groupby('Sex').mean()**
(图片由作者提供)
同样,我们可以不使用列来调用agg()
。
df.**groupby('Sex').agg(['mean', 'median'])**
(图片由作者提供)
3.转换数据
转换是一个过程,在这个过程中,我们执行一些特定于组的计算,并返回一个相似索引(相同长度)的对象。在寻找转换数据时,transform()
和apply()
是最常用的函数。
让我们为标准化创建一个λ表达式。
standardization = lambda x: (x - x.mean()) / x.std()
用transform()
对年龄栏进行标准化
df.groupby('Sex').**Age.transform(standardization)**0 1.630657
1 1.516751
2 0.574994
...
707 -0.294321
708 NaN
709 0.956720
710 0.282784
711 NaN
Name: Age, Length: 712, dtype: float64
使用apply()
对年龄栏进行标准化
df.groupby('Sex').**Age.apply(standardization)**0 1.630657
1 1.516751
2 0.574994
...
707 -0.294321
708 NaN
709 0.956720
710 0.282784
711 NaN
Name: Age, Length: 712, dtype: float64
如果您想了解更多transform()
和apply()
,请查看:
4.过滤
过滤是一个过程,在这个过程中,我们根据评估真或假的分组计算来丢弃一些分组。
让我们看看如何丢弃属于只有几个成员的组的数据。
首先,我们按舱将数据分组,并快速查看每组的大小。
df.groupby('Cabin').size()Cabin
A10 1
A14 1
A16 1
A19 1
..
F2 2
F33 3
F4 1
G6 2
T 1
Length: 128, dtype: int64
现在,让我们过滤数据,返回居住在客舱中的所有乘客人数≥ 4 人。为此,我们使用带有 lambda 表达式的filter()
方法。
df.groupby('Cabin').**filter(lambda x: len(x) >= 4)**
(图片由作者提供)
6.按多个类别分组
到目前为止,我们已经向groupby()
传递了一个标签,通过一列对数据进行分组。除了标签,我们还可以传递一个标签列表来处理多个分组。
# Creating a subset
df_subset = df.loc[:, ['Sex', 'Pclass', 'Age', 'Fare']]# Group by multiple categories
df_subset.groupby(**['Sex', 'Pclass']**).mean()
(图片由作者提供)
7.用as_index
重置索引
按多个类别分组将产生一个多索引数据框架。但是,当我们需要执行一些数据分析时,将 Sex 和 Pclass 列作为索引是不实际的(见上图)。
我们可以调用 DataFrame 上的reset_index()
方法来重置它们,并使用默认的从 0 开始的整数索引。
df_groupby_multi = subset.groupby(['Sex', 'Pclass']).mean()# Resetting index
df_groupby_multi**.reset_index()**
(图片由作者提供)
但是使用as_index
参数有一个更有效的方法。参数是配置索引是否是组标签。如果设置为False
,组标签表示为列而不是索引。
subset.groupby(['Sex', 'Pclass'], **as_index=False**).mean()
(图片由作者提供)
8.处理缺失值
默认情况下,groupby()
函数会忽略缺失的值。让我们首先在性别列中创建一些缺失值。
# Creating missing value in the Sex column
**subset.iloc[80:100, 0] = np.nan**# Validating the missing values
subset.isna().sum()**Sex 20**
Pclass 0
Age 146
Fare 0
dtype: int64
在计算性别列中每个类别的平均值时,我们不会得到任何关于缺失值的信息。
# The groupby function ignores the missing values by default.
subset**.groupby(['Sex', 'Pclass'])**.mean()
(图片由作者提供)
在某些情况下,我们还需要了解缺失值的概况。我们可以将dropna
参数设置为False
来包含丢失的值。
subset.groupby(['Sex', 'Pclass'], **dropna=False**).mean()
(图片由作者提供)
结论
Pandas groupby()
函数是数据分析中应用最广泛的函数之一。它非常重要,因为它能够聚合、转换和过滤每个组中的数据。
我希望这篇文章能帮助你节省学习熊猫的时间。我建议你查看一下关于groupby()
API 的文档,并了解你可以做的其他事情。
感谢阅读。请查看笔记本获取源代码,如果您对机器学习的实用方面感兴趣,请继续关注。
你可能会对我的其他一些熊猫文章感兴趣:
- 所有熊猫 json_normalize()你应该知道的扁平化 JSON
- 使用熊猫方法链接提高代码可读性
- 如何对熊猫数据帧进行自定义排序
- 为了数据分析你应该知道的所有熊猫移位()
- 何时使用熊猫变换()函数
- 你应该知道的熊猫串联()招数
- Pandas 中应用()和转换()的区别
- 所有熊猫合并()你应该知道
- 在熊猫数据帧中处理日期时间
- 熊猫阅读 _csv()你应该知道的招数
- 用 Pandas read_csv() 解析日期列应该知道的 4 个技巧
更多教程可以在我的 Github 上找到
参考
- [1]熊猫官方教程:分组依据:拆分-应用-合并
扁平化 json 你应该知道的所有熊猫 json_normalize()
原文:https://towardsdatascience.com/all-pandas-json-normalize-you-should-know-for-flattening-json-13eae1dfb7dd?source=collection_archive---------0-----------------------
一些最有用的熊猫把戏
所有熊猫 json_normalize()你应该知道的扁平化 json(图片由作者使用canva.com)
读取数据是任何数据科学项目的第一步。作为机器学习实践者或数据科学家,您肯定会遇到 JSON (JavaScript 对象表示法)数据。JSON 是一种广泛使用的存储和交换数据的格式。比如像 MongoDB 这样的 NoSQL 数据库是以 JSON 格式存储数据的,REST API 的响应大多是以 JSON 的形式提供的。
虽然这种格式很适合存储和交换数据,但需要转换成表格形式以便进一步分析。您可能要处理两种类型的 JSON 结构,一个 JSON 对象或一个 JSON 对象列表。在内部 Python 行话中,你最有可能处理的是一个字典或字典列表。
字典和字典列表(图片由作者提供)
在本文中,您将学习如何使用 Pandas 的内置函数json_normalize()
将这两种类型的 JSON 展平成 Pandas 数据帧。这篇文章的结构如下:
- 简化一个简单的 JSON
- 用多个级别扁平化 JSON
- 用嵌套列表扁平化 JSON
- 如果键不总是存在,则忽略 KeyError
- 使用
sep
自定义分隔符 - 为元数据和记录数据添加前缀
- 使用本地文件
- 使用 URL
请查看笔记本获取源代码。
1.简化一个简单的 JSON
让我们从 2 个简单的 JSON、一个简单的 dict 和一个简单的 dict 列表开始。
当 JSON 是一个简单的字典时
a_dict = {
'school': 'ABC primary school',
'location': 'London',
'ranking': 2,
}df = **pd.json_normalize(a_dict)**
(图片由作者提供)
结果看起来很棒。让我们来看看使用df.info()
的数据类型。我们可以看到,数值列被转换为数值类型。
>>> **df.info()**<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1 entries, 0 to 0
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 school 1 non-null object
1 location 1 non-null object
2 ranking 1 non-null **int64**
dtypes: int64(1), object(2)
memory usage: 152.0+ bytes
当数据是字典列表时
json_list = [
{ 'class': 'Year 1', 'student number': 20, 'room': 'Yellow' },
{ 'class': 'Year 2', 'student number': 25, 'room': 'Blue' },
]**pd.json_normalize(json_list)**
(图片由作者提供)
结果看起来很棒。json_normalize()
函数能够将列表中的每条记录转换成一行表格形式。
不总是出现的键怎么办,例如,num _ of _ students在第二条记录中不可用。
json_list = [
{ 'class': 'Year 1', 'num_of_students': 20, 'room': 'Yellow' },
**{ 'class': 'Year 2', 'room': 'Blue' }, # no num_of_students**
]pd.json_normalize(json_list)
(图片由作者提供)
我们可以看到没有抛出错误,那些丢失的键显示为NaN
。
2.用多个级别扁平化 JSON
熊猫json_normalize()
非常适合简单的 JSON(被称为扁平化 JSON)。多层次的 JSON 呢?
当数据是字典时
让我们先来看看下面的格言:
json_obj = {
'school': 'ABC primary school',
'location': 'London',
'ranking': 2,
**'info': {
'president': 'John Kasich',
'contacts': {
'email': {
'admission': '**[**admission@abc.com**](mailto:admission@abc.com)**',
'general': '**[**info@abc.com**](mailto:info@abc.com)**'
},
'tel': '123456789',
}
}**
}
info 的值是多级的(称为嵌套字典)。通过调用pd.json_normalize(json_obj)
,我们得到:
结果看起来很棒。所有嵌套值都被展平并转换为单独的列。
如果您不想深入到每个值,请使用max_level
参数。使用参数max_level=1
,我们可以看到我们的嵌套值 contacts 被放到一个单独的列 info.contacts 中。
pd.json_normalize(data, **max_level=1**)
(图片由作者提供)
当数据是字典列表时
json_list = [
{
'class': 'Year 1',
'student count': 20,
'room': 'Yellow',
'info': {
'teachers': {
'math': 'Rick Scott',
'physics': 'Elon Mask'
}
}
},
{
'class': 'Year 2',
'student count': 25,
'room': 'Blue',
'info': {
'teachers': {
'math': 'Alan Turing',
'physics': 'Albert Einstein'
}
}
},
]pd.json_normalize(json_list)
(图片由作者提供)
我们可以看到,列表的每个记录中的所有嵌套值都被展平并转换为单独的列。类似地,我们可以使用max_level
参数来限制级别的数量,例如
pd.json_normalize(json_list, **max_level=1**)
(图片由作者提供)
3.用嵌套列表扁平化 JSON
有嵌套列表的 JSON 呢?
当数据是字典时
让我们看看如何将下面的 JSON 展平到一个数据帧中:
json_obj = {
'school': 'ABC primary school',
'location': 'London',
'ranking': 2,
'info': {
'president': 'John Kasich',
'contacts': {
'email': {
'admission': '[admission@abc.com](mailto:admission@abc.com)',
'general': '[info@abc.com](mailto:info@abc.com)'
},
'tel': '123456789',
}
},
**'students': [
{ 'name': 'Tom' },
{ 'name': 'James' },
{ 'name': 'Jacqueline' }
],**
}
注意学生的值是一个嵌套列表。通过调用pd.json_normalize(json_obj)
,我们得到:
(图片由作者提供)
我们可以看到,我们的嵌套列表被放入一个单独的列 students 中,其他值被展平。如何才能将嵌套列表扁平化?为此,我们可以将参数record_path
设置为['students']
:
# Flatten students
pd.json_normalize(data, **record_path=['students']**)
(图片由作者提供)
结果看起来很棒但是不包括学校和电话。为了包含它们,我们可以使用参数meta
来指定我们想要的结果中的元数据列表。
pd.json_normalize(
json_obj,
record_path =['students'],
**meta=['school', ['info', 'contacts', 'tel']],**
)
(图片由作者提供)
当数据是字典列表时
json_list = [
{
'class': 'Year 1',
'student count': 20,
'room': 'Yellow',
'info': {
'teachers': {
'math': 'Rick Scott',
'physics': 'Elon Mask'
}
},
**'students': [
{
'name': 'Tom',
'sex': 'M',
'grades': { 'math': 66, 'physics': 77 }
},
{
'name': 'James',
'sex': 'M',
'grades': { 'math': 80, 'physics': 78 }
},
]**
},
{
'class': 'Year 2',
'student count': 25,
'room': 'Blue',
'info': {
'teachers': {
'math': 'Alan Turing',
'physics': 'Albert Einstein'
}
},
**'students': [
{ 'name': 'Tony', 'sex': 'M' },
{ 'name': 'Jacqueline', 'sex': 'F' },
]**
},
]pd.json_normalize(json_list)
(图片由作者提供)
所有嵌套的列表都放在一个单独的列中学生,其他值被展平。为了展平嵌套列表,我们可以将参数record_path
设置为['students']
。请注意,并非所有记录都有数学和物理,那些缺失的值显示为NaN
。
pd.json_normalize(json_list, **record_path=['students']**)
(图片由作者提供)
如果您想包含其他元数据,请使用参数meta
:
pd.json_normalize(
json_list,
record_path =['students'],
**meta=['class', 'room', ['info', 'teachers', 'math']]**
)
(图片由作者提供)
4.errors
参数
errors
参数默认为'raise’
,如果meta
中列出的键并不总是存在,将引发 KeyError 。例如,数学老师从第二条记录中不可用。
data = [
{
'class': 'Year 1',
'student count': 20,
'room': 'Yellow',
'info': {
'teachers': {
**'math': 'Rick Scott',**
'physics': 'Elon Mask',
}
},
'students': [
{ 'name': 'Tom', 'sex': 'M' },
{ 'name': 'James', 'sex': 'M' },
]
},
{
'class': 'Year 2',
'student count': 25,
'room': 'Blue',
'info': {
'teachers': {
**# no math teacher**
'physics': 'Albert Einstein'
}
},
'students': [
{ 'name': 'Tony', 'sex': 'M' },
{ 'name': 'Jacqueline', 'sex': 'F' },
]
},
]
当试图拉平数学时,将抛出一个 KeyError 。
pd.json_normalize(
data,
record_path =['students'],
meta=['class', 'room', **['info', 'teachers', 'math']**],
)
(图片由作者提供)
为了解决这个问题,将参数errors
设置为'ignore'
,那些缺少的值用NaN
填充。
pd.json_normalize(
data,
record_path =['students'],
meta=['class', 'room', ['info', 'teachers', 'math']],
**errors='ignore'**
)
(图片由作者提供)
5.使用sep
参数的自定义分隔符
默认情况下,所有嵌套值将生成由.
分隔的列名。例如 info.teachers.math 。要用其他东西分隔列名,可以使用sep
参数。
pd.json_normalize(
data,
record_path =['students'],
meta=['class', 'room', ['info', 'teachers', 'math']],
**sep='->'**
)
(图片由作者提供)
6.为元数据和记录数据添加前缀
有时,为列名添加前缀可能更具描述性。为了对meta
和record_path
执行此操作,我们可以简单地将字符串分别传递给参数meta_prefix
和record_prefix
:
pd.json_normalize(
data,
record_path=['students'],
meta=['class'],
**meta_prefix='meta-',**
**record_prefix='student-'**
)
(图片由作者提供)
7.使用本地文件
通常,您将处理的 JSON 数据作为一个存储在本地。json 文件。然而,Pandas json_normalize()
函数只接受一个字典或字典列表。要解决这个问题,你需要第三个模块的帮助,例如 Python json 模块:
**import json**
# load data using Python JSON module
**with open('data/simple.json','r') as f:**
**data = json.loads(f.read())**
# Flattening JSON data
pd.json_normalize(data)
data = json.loads(f.read())
使用 Python json 模块加载数据。之后,对数据调用json_normalize()
将其展平成 DataFrame。
8.使用 URL
JSON 是在 REST APIs 中传输数据的标准格式。通常,您需要使用 JSON 格式的 API 响应。最简单的方法是使用 Python 请求模块:
**import requests**URL = '[http://raw.githubusercontent.com/BindiChen/machine-learning/master/data-analysis/027-pandas-convert-json/data/simple.json'](http://raw.githubusercontent.com/BindiChen/machine-learning/master/data-analysis/027-pandas-convert-json/data/simple.json')
**data = json.loads(requests.get(URL).text)**# Flattening JSON data
pd.json_normalize(data)
结论
Pandas json_normalize()
函数是将 JSON 展平成数据帧的一种快速、方便和强大的方式。
我希望这篇文章能帮助你节省整理 JSON 数据的时间。我建议你查看一下json_normalize()
API 的文档,并了解你可以做的其他事情。
感谢阅读。请查看笔记本获取源代码,如果您对机器学习的实用方面感兴趣,请继续关注。
你可能会对我的其他一些熊猫文章感兴趣:
- Pandas cut()函数,用于将数值数据转换为分类数据
- 使用熊猫方法链接提高代码可读性
- 如何对熊猫数据帧进行自定义排序
- 数据分析你应该知道的所有熊猫移位()
- 何时使用 Pandas transform()函数
- 你应该知道的熊猫串联()招数
- Pandas 中 apply()和 transform()的区别
- 所有的熊猫合并()你应该知道
- 在 Pandas 数据帧中处理日期时间
- 熊猫阅读 _csv()你应该知道的招数
- 你应该知道的用熊猫 read_csv()解析日期列的 4 个技巧
更多教程可以在我的 Github 上找到
基于样本分位数的宁滨数字数据
原文:https://towardsdatascience.com/all-pandas-qcut-you-should-know-for-binning-numerical-data-based-on-sample-quantiles-c8b13a8ed844?source=collection_archive---------9-----------------------
将数值数据转换成分类数据的技巧和诀窍
照片由 v2osk 在 Unsplash 上拍摄
数值型数据在数据分析中很常见。通常情况下,您会得到连续的、大范围的或高度倾斜的数值数据。有时,将这些数据绑定到离散的区间会更容易。当值被分成有意义的类别时,这对于执行描述性统计非常有帮助。例如,用年龄组代替确切的年龄,用体重级别代替确切的体重,用年级级别代替确切的分数。
Pandas 有两个内置函数cut()
和qcut()
,用于将数值数据转换为分类数据。
cut()
根据箱边缘将数据装入离散区间qcut()
根据样本分位数将数据分入离散区间
在上一篇文章中,我们已经介绍了cut()
函数。
****
在本文中,您将学习如何使用qcut()
基于样本分位数对数字数据进行分类。这篇文章的结构如下:
- 离散成大小相等的桶
- 用分位数列表离散化到桶中
- 添加自定义标签
- 带
retbins=True
的回收箱 - 配置箱精度
请查看笔记本获取源代码。
访问 Github Repo 获取其他教程****
1.离散成大小相等的桶
与熊猫类似,qcut()
最简单的用法必须有一列和一个整数作为输入。它将值离散化到大小相等的桶中:
**df = pd.DataFrame({
'age': [2, 67, 40, 32, 4, 15, 82, 99, 26, 30, 50, 78]
})df['age_group'] = pd.qcut(**df['age']**, 3)**
作者图片
让我们数一数有多少个值落入每个容器中。
**df['age_group']**.value_counts()**(1.999, 28.667] 4
(28.667, 55.667] 4
(55.667, 99.0] 4
Name: age_group, dtype: int64**
我们可以看到已经选择了箱,因此结果在每个箱中具有相同数量的记录(称为大小相等的桶)。
此外,您可能会注意到那些区间值在开头有一个圆括号,在结尾有一个方括号,例如(1.999, 28.667]
。基本意思是圆括号边的任何值都不包含在区间内,方括号边的任何值都包含在内(数学上称为开区间和闭区间)。
现在,让我们来看看新的专栏年龄组。
作者图片
显示dtype: category
,有三个标签值:**(1.999, 28.667]**
、**(28.667, 55.667]**
和**(55.667, 99.0]**
。这些标签值按照符号<
的指示进行排序。让我们按列年龄组对数据帧进行排序:
**df.**sort_values('age_group')****
作者图片
2.用分位数列表离散化到桶中
先前方法的一个问题是,结果在每个箱中总是具有相同数量的记录。换句话说,每个箱具有相同的比例/百分比。例如:
**pd.qcut(df['age'], **2**)
Result: **|<- 50% ->|<- 50% ->|**pd.qcut(df['age'], **3**)
Result: **|<- 33.3% ->|<- 33.3% ->|<- 33.3% ->|**pd.qcut(df['age'], **4**)
Result: **|<- 25% ->|<- 25% ->|<- 25% ->|<- 25% ->|**pd.qcut(df['age'], **5**)
Result: **|<- 20% ->|<- 20% ->|<- 20% ->|<- 20% ->|<- 20% ->|****
在某些情况下,您可能希望明确选择比例,而不是大小相等的存储桶,例如:
**10%, 40%, 50%**
为此,我们可以将一个分位数列表传递给第二个参数。
**df['age_group'] = pd.qcut(df['age'], **[0, .1, .5, 1]**)df.sort_values('age_group')**
作者图片
注意,4 个值[0, .1, .5, 1]
用于产生 3 个比例/百分比10%
、40%
和50%
为了验证结果,让我们按如下方式对每个容器中的值进行排序和计数:
**df.sort_values('age_group')['age_group']**.value_counts()****(36.0, 99.0] 6
(5.1, 36.0] 4
(1.999, 5.1] 2**
Name: age_group, dtype: int64**
3.添加自定义标签
将这些年龄段的价值观贴上“千禧一代”、“X 世代”、“婴儿潮一代”、“最伟大”的标签更能说明问题。为此,我们可以简单地将列表中的值传递给参数labels
****labels=['Millennial', 'Gen X', 'Boomer', 'Greatest']**
df['age_group'] = pd.qcut(df['age'], [0, .1, 0.3, .6, 1], **labels=labels**)**
作者图片
现在,当我们查看该列时,它显示的是标签
**df['age_group']0 Millennial
1 Greatest
2 Boomer
3 Boomer
4 Millennial
5 Gen X
6 Greatest
7 Greatest
8 Gen X
9 Boomer
10 Greatest
11 Greatest
Name: age_group, dtype: category
Categories (4, object): ['Millennial' < 'Gen X' < 'Boomer' < 'Greatest']**
同样,在分类和计数时,它会显示标签
**df.sort_values('age_group')**
作者图片
**df['age_group'].**value_counts().sort_index()**Millennial 2
Gen X 2
Boomer 3
Greatest 5
Name: age_group, dtype: int64**
4.用retbins=True
返回箱子
有一个名为retbin
的参数用于返回 bin。如果设置为True
,结果将返回bins
。当第二个参数q
作为单个数值传递时,这很有用。
**result, **bins** = pd.qcut(
df['age'],
**5, # A single number value**
retbins=True
)# Print out bins value
**bins**
array([ 2\. , 17.2, 30.8, 46\. , 75.8, 99\. ])**
5.配置箱精度
您可能会注意到,到目前为止我们制作的所有 bin 间隔值都有一些小数点,例如pd.qcut(df['age'], 3)
**pd.qcut(df['age'], 3)0 (1.999, 28.667]
1 (55.667, 99.0]
2 (28.667, 55.667]
3 (28.667, 55.667]
4 (1.999, 28.667]
5 (1.999, 28.667]
6 (55.667, 99.0]
7 (55.667, 99.0]
8 (1.999, 28.667]
9 (28.667, 55.667]
10 (28.667, 55.667]
11 (55.667, 99.0]
Name: age, dtype: category
Categories (3, interval[float64]): [**(1.999, 28.667] < (28.667, 55.667] < (55.667, 99.0]**]**
一般来说,年龄组间隔不使用小数位。幸运的是,有一个名为precision
的参数来定义在计算 bin 精度时使用多少个小数点。我们可以将precision
设置为0
来避免任何小数位。
**pd.qcut(df['age'], 3, **precision=0**)0 (1.0, 29.0]
1 (56.0, 99.0]
2 (29.0, 56.0]
3 (29.0, 56.0]
4 (1.0, 29.0]
5 (1.0, 29.0]
6 (56.0, 99.0]
7 (56.0, 99.0]
8 (1.0, 29.0]
9 (29.0, 56.0]
10 (29.0, 56.0]
11 (56.0, 99.0]
Name: age, dtype: category
Categories (3, interval[float64]): [**(1.0, 29.0] < (29.0, 56.0] < (56.0, 99.0]**]**
您也可以将其设置为任何其他值,例如precision=1
表示 1 位小数。
**pd.qcut(df['age'], 3, **precision=1**)0 (1.9, 28.7]
1 (55.7, 99.0]
2 (28.7, 55.7]
3 (28.7, 55.7]
4 (1.9, 28.7]
5 (1.9, 28.7]
6 (55.7, 99.0]
7 (55.7, 99.0]
8 (1.9, 28.7]
9 (28.7, 55.7]
10 (28.7, 55.7]
11 (55.7, 99.0]
Name: age, dtype: category
Categories (3, interval[float64]): [(1.9, 28.7] < (28.7, 55.7] < (55.7, 99.0]]**
结论
Pandas qcut()
函数是一种基于样本分位数的宁滨数值数据的快捷方式。
我希望这篇文章能帮助你节省学习熊猫的时间。我建议你查看一下qcut()
API 的文档,并了解你可以做的其他事情。
感谢阅读。请查看笔记本获取源代码,如果您对机器学习的实用方面感兴趣,请继续关注。
你可能会对我的其他一些熊猫文章感兴趣:
- 熊猫系列实用介绍
- 使用熊猫方法链接提高代码可读性
- 如何对熊猫数据帧进行自定义排序
- 为了数据分析你应该知道的所有熊猫移位()
- 何时使用 Pandas transform()函数
- 你应该知道的熊猫串联()招数
- 熊猫的应用()和变换()的区别
- 所有熊猫合并()你应该知道
- 在 Pandas 数据帧中处理日期时间
- 熊猫阅读 _csv()你应该知道的招数
- 用 Pandas read_csv()解析日期列应该知道的 4 个技巧
更多教程可以在我的 Github 上找到
六分钟内解释所有概率分布
原文:https://towardsdatascience.com/all-probability-distributions-explained-in-six-minutes-fe57b1d49600?source=collection_archive---------5-----------------------
最重要的概率分布的直观解释
作者创建的图像
简介
当我第一次看到概率分布时,它是如此令人生畏,部分原因是它们太多了,而且它们都有如此陌生的名字。
快进到今天,我意识到它们实际上是非常简单的概念,当你去掉它们背后的所有数学知识时,这就是我们今天要做的。
我将从概念上回顾一下我认为最基本和最重要的概率分布,而不是进入事物的数学方面。
到本文结束时,你不仅会了解到几种概率分布,而且还会意识到其中许多分布彼此之间有多么密切的联系!
首先,你需要知道几个术语:
- 一个概率分布简单地显示了得到不同结果的概率。例如,翻转头或翻转尾的分布是 0.5 和 0.5。
- 离散分布是一种分布,其中数据可以呈现的值是可数的。
- 另一方面,连续分布是数据可以呈现的值不可数的分布。
请务必 订阅此处 或至我的 独家快讯 千万不要错过另一篇关于数据科学的指南、技巧和提示、生活经验等!
1.正态分布
作者创建的图像
正态分布可以说是最重要的分布,因为许多现象都符合这个分布。智商、身高、鞋码、出生体重都是正态分布的例子。
正态分布呈钟形曲线,具有以下特性:
- 它有对称的钟形
- 平均值和中值相等,都位于分布的中心
- 约 68%的数据落在平均值的 1 个标准偏差内,约 95%的数据落在平均值的 2 个标准偏差内,约 99.7%的数据落在平均值的 3 个标准偏差内。
正态分布也是统计学的一个组成部分,因为它是几种统计推断技术的基础,包括线性回归、置信区间和假设检验。
2.t 分布
t 分布类似于正态分布,但通常较短,尾部较厚。当样本量很小时,它用来代替正态分布。
需要注意的一点是,随着样本量的增加,t 分布收敛于正态分布。
务必 订阅此处 或至我的 独家快讯 千万不要错过另一篇关于数据科学的指南、窍门和技巧、生活经验等!
3.γ分布
作者创建的图像
伽玛分布用于预测未来事件发生之前的等待时间。当某事物的自然最小值为 0 时,这是有用的。
也是卡方分布和指数分布的广义分布(后面会讲到)。
4.卡方分布
作者创建的图像
如上所述,卡方分布是伽马分布的一个特例。由于卡方分布有很多内容,所以我不会讲得太详细,但它有几种用途:
- 它允许您估计总体标准差的置信区间
- 当基础分布为正态时,它是样本方差的分布
- 您可以测试预期值和观察值之间的差异偏差
- 你可以进行卡方检验
注意:如果这个版本让你感到困惑,不要太担心,因为下面的版本更容易理解和掌握!
5.均匀分布
均匀分布非常简单——每个结果都有相等的概率。这方面的一个例子是滚动染料。
上图显示了一个近似均匀分布的分布。
6.二项分布
作者创建的图像
为了理解伯努利分布,你首先需要知道什么是伯努利试验。伯努利试验是一个随机实验,只有两种可能的结果,成功或失败,每次成功的概率都是相同的。
因此,伯努利分布是一次伯努利试验的离散分布。
例如,投掷硬币可以用伯努利分布来表示,在染料上滚动奇数也是如此。
7.二项分布
作者创建的图像
现在您已经了解了伯努利分布,二项分布简单地表示了多次伯努利试验。具体来说,二项式分布是一种离散分布,表示从 n 次独立的伯努利试验中获得 x 次成功的概率。
下面是一些使用二项式分布的例子:
- 10 次掷硬币中有 5 次正面朝上的概率是多少?
- 100 封邮件中获得 10 次转化的概率是多少(假设转化概率相同)?
- 从 500 份客户反馈调查中得到 20 份回复的概率是多少(假设得到回复的概率相同)?
关于二项分布的一个有趣的事情是,当 n(伯努利试验的次数)变大时,它收敛到正态分布。
务必 订阅此处 或至我的 独家快讯 千万不要错过另一篇关于数据科学的指南、窍门和技巧、生活经验等!
8.几何分布
几何分布也与伯努利分布有关,就像二项式分布一样,只是它回答的问题略有不同。几何分布代表在第一次成功之前出现 x 次伯努利(p)失败的概率?换句话说,它回答了“在你第一次成功之前需要多少次尝试?”
这方面的一个例子是,“我需要买多少张彩票才能买到一张中奖的彩票?”
您还可以使用几何分布来找出在失败之前伯努利(1-p)成功次数的概率。几何图形还可用于检查事件是否符合分布。
9.威布尔分布
作者创建的图像
威布尔分布类似于几何分布,只是它是一种连续分布。因此,威布尔分布模拟了某件事情发生故障所需的时间或故障间隔时间。
威布尔分布可以回答如下问题:
- 一个特定的灯泡多久会熄灭?
- 顾客多久会有反应?
10.泊松分布
作者创建的图像
泊松分布是一个离散分布,代表一个事件在特定时间段内可能发生的次数。
泊松分布最常用于排队论,它回答了类似于“在给定的时间内有多少顾客可能会来(排队)”的问题。
11.指数分布
作者创建的图像
指数分布与泊松分布密切相关。如果到达是泊松分布,那么到达之间的时间(也称为到达间隔时间)具有指数分布。
感谢阅读!
如果您喜欢这篇文章,请务必点击 订阅此处 或至我的 独家快讯 千万不要错过另一篇关于数据科学的指南、技巧和提示、生活经验等文章!
不确定接下来要读什么?我为你选了另一篇文章:
又一个!
</10-statistical-concepts-you-should-know-for-data-science-interviews-373f417e7d11>
特伦斯·申
- 如果你喜欢这个, 订阅我的媒介 获取独家内容!
- 或 跟我上
- 有兴趣合作吗?下面我们连线上LinkedIn
所有的公共交通都通向乌得勒支,而不是罗马
原文:https://towardsdatascience.com/all-public-transport-leads-to-utrecht-not-rome-bb9674600e81?source=collection_archive---------38-----------------------
实践教程
我们都知道“条条大路通罗马”这句谚语。在这篇文章中,我会告诉你这在定义上不适用于公共交通。事实上,在荷兰,所有的公共交通都通往乌得勒支。
通往乌得勒支的所有公共交通路线详情(图片由作者提供)
是的,我们都知道“条条大路通罗马”这句话。在这篇文章中,我将展示在过去的 2000 年里发生了很多变化。“条条大路通罗马”可能仍然是对的,但在荷兰,公共交通不是这样。都去乌得勒支,乌得勒支中央车站。有几个通往罗马的所有道路的可视化,但我将第一次向你展示公共交通前往乌得勒支。
这将基于荷兰的 GTFS 数据,行程规划器 OpenTripPlanner 和一些带有 GeoPandas 和 Python 的魔法。这些将用于计算所有公共交通站和乌得勒支之间的路线,并绘制路线图。
这篇文章的完整代码可以在 G ithub 上找到。
计算所有到乌得勒支的路线
第一步是计算从该国所有公共交通站点到乌得勒支的所有路线。所有计划计算都使用 OTP 执行。OTP 需要一个 OpenStreetMap PBF 文件,其中包含您感兴趣区域的街道和步行时间,以及 GTFS 的公共交通时刻表。OTP jar 是从 Maven 下载的。阴影部分是为了简单起见,因为它包括了所有的依赖项。OSM PBF 从 GeoFabrik 获得,命名为‘Netherlands-latest-osm . pbf’。GTFS 从 OVapi 下载,并以 zip ('gtfs-nl.zip ')格式下载。这三个文件都存储在同一个位置。
OTP 从命令行启动:
它将在当前目录中找到 OSM 和 GTFS 文件,并开始构建网络图。由于规模(我们正在创建一个整个国家的地图,而不是一个单一的城市)这将需要一些时间,但最终 OTP 服务器启动。需要 12G 的堆大小才能在内存中加载网络图。要测试服务器,请尝试 URLhttp://localhost:8080。除了 web 接口之外,还有一个 REST API 用于使用 OTP-server,它将在下面的代码中使用。
使用所有公共交通站(公共汽车、电车、地铁、火车等)。从这些站点中的每一个计算到乌得勒支中央车站的路线。首先,编译要计算的路线集。
数据集包含起点和终点位置,其中终点位置是乌得勒支中央车站前广场的 GPS 位置。数据集还包含路线计算的日期和时间,这对于所有要计算的路线都是相同的,在本例中为 2021 年 3 月 17 日 16:00。停用位置的 GTFS 数据集可能包含重复条目,因此这些条目将被移除以防止多余的计算。
荷兰的 GTFS 数据也包含国外的一些车站,因为这些车站可以通过国际列车到达。通过使用 GeoPandas 可用的国家边界来移除国家以外的这些站。
国家边界是从 GeoPandas 分布中可用的世界边界数据集获得的(第 4 行和第 5 行)。起止数据集被转换为 GeoPanda(第 1 行和第 2 行),并通过 sjoin 命令与边界数据集连接,即空间连接。该连接根据地理空间关系连接两个数据集,在这种情况下,它确定每个点是否在 nl GeoPanda 的边界内。最后,对数据集进行过滤,使其仅包含荷兰的点。
路线数据集现在被用作路线计算的输入。对于数据集中的每个条目,计算公共交通路线并将其添加到包含所有路段的数据集中(计算出的路线包含一条或多条路段):
对于路线数据帧中的每一行,计划请求被发送到 OTP。结果是一个带有路线描述的 JSON。一条路线由一条或多条线路组成。对于每个非步行(换乘)路段,路线细节被存储并添加到结果数据帧中。根据可用的硬件,此步骤需要几个小时。请耐心等待:-)
大多数航段将被多条航线使用。最后两行计算每个航段的出现次数,并删除重复的航段条目。
包含所有折线的数据框(图片由作者提供)
线段的计算
在下一步中,我们可以使用路段的起止位置,并使用 GTFS 数据集重建旅程。但是很方便的是,OTP 返回腿的 GPS 轨迹作为 Google polyline 。解码这个字符串(lat,lon)对比基于 GTFS 的重建“稍微”简单,但是仍然有些麻烦。幸运的是,可以在网上找到示例实现。
所有分支都被解码成它们的底层段,其中段是(lat,lon)对。这是地图上的一条直线。将该段中的出现次数复制到段中。最后一步是合并所有相等的段,并对其出现次数求和。
我们现在有一个经纬度格式的(x,y)对的数据集,其中包含该路段在所有计划路线中的出现次数。
所有部分的数据框架(图片由作者提供)
标图片段
在我们绘制数据之前,要执行的最后一步是将段数据帧转换为由两个点之间的线段组成的 GeoPanda 数据帧。
最后一行将出现的计数标准化为 0 到 5 之间的行宽度。我们的第一个图只绘制了片段,以检查最终数据集的内容:
通往乌得勒支的所有公共交通路线(图片由作者提供)
这张图片显示了所有的公共交通路线,看起来是正确的。它很好地概述了这个国家所有的公共交通线路。观察 Afsluitdijk 上的总线如何令人惊讶地成为图表的一部分。从弗里斯兰的一个或多个地点出发,穿过阿夫斯卢伊特街去北荷兰会更快。从西南部(Zeeuws-Vlaanderen)开始,一些路线穿过比利时。如果我们在图像中添加一张地图,就可以清楚地看到这一点:
所有带 OpenStreetMap 背景的路线(图片由作者提供)
最后一步是使用图中线段的计算宽度。为了提高可见度,[0,5]的范围宽度减小到[0.1,2.9]。如果不采用这种方式,最粗的线条会太粗,使图像混乱,而最细的线条则不可见。
这是最终的结果,显示所有的公共交通确实都去了乌得勒支:
所有路线都通向乌得勒支(图片由作者提供)
该地图显示了从该国所有公共交通站到乌得勒支中央车站的所有路线。线条的粗细表示线条服务的停靠点数量。它不代表乘客的数量,只代表停靠站的数量。但是这张地图看起来很壮观,它就像是这个国家的心血管系统。
我希望你喜欢这篇文章。要获得更多关于使用公共交通开放数据的灵感,请查看我的其他文章:
- 用开放数据和开普勒来想象荷兰火车的拥挤
- 使用 OTP 和 QGIS 可视化行程时间
免责声明:本文包含的观点和意见仅归作者所有。
练习数据科学技能和制作优秀投资组合所需的所有数据集
原文:https://towardsdatascience.com/all-the-datasets-you-need-to-practice-data-science-skills-and-make-a-great-portfolio-74f2eb53b38a?source=collection_archive---------2-----------------------
阿玛多·洛雷罗在 Unsplash 上的照片
大量不同种类的数据集
每次我试图做一个项目来学习一个新的主题,或者做一个项目,我都会花大量的时间来寻找一个合适的数据集。这样,我就有了相当多的数据集,帮助我学习并为我的投资组合做一些很酷的项目。我将在这篇文章中分享这些数据集,以便你有一个数据集来练习和制作你的作品集。
奥林匹克数据集
这个数据集包含奥运成绩的信息。每行包含一个国家的数据。这个数据集将让您开始体验数据清理。
我用这个数据集学习了 Python 的像 Numpy 和 Pandas 这样的库。
从这里下载这个数据集
房价数据集
该数据集常用于教与学 回归 模型 。当然,它也可以用于其他工作人员。
该数据集包含这些列:id、日期、价格、卧室、浴室、sqft_living、sqft_lot、楼层、滨水区、视图、条件、等级、sqft_above、sqft_basement、yr _ built、yr _ renovated、邮政编码、lat、long、sqft_living15、sqft_lot15。
这里是链接。
心脏病数据集
这个数据集来自 Kaggle。出于演示目的,我在几篇文章中使用了它。
这是两个例子:
我们做了一些探索性的数据分析,也提供了 Kaggle 中特性的细节。
从这个链接下载这个数据集。
蘑菇数据集
我在 Coursera 的应用数据科学与 Python 专门化课程中发现了这个数据集。
我用它来解决 分类 的问题。它也可以用于其他目的。
它包含这些列:类,帽形,帽面,帽色,瘀伤,气味,鳃附着,鳃间距,鳃大小,鳃色,茎形,茎根,茎面上环,茎面下环,茎色上环,茎色下环,面纱型,面纱色,环数,环型,孢子印色,种群,栖息地。
这里是到这个数据集的链接
NHANES 数据集
这是一个包含大量连续和分类特征的大型数据集。因此,您可以将整个数据集或其中的一部分用于许多不同的目的。一开始,名为的专栏可能看起来不太容易理解。但是一旦你习惯了,它可以成为一个非常有用的数据集来练习 数据分析、可视化、统计建模和机器学习 模型(分类和回归)。
在本文中,我剪切了数据集的一部分,并将其用于多元线性回归:
这里我用它来做一些可视化演示:
从这里下载
泰坦尼克号数据集
另一个非常受欢迎的数据集。我自己经常使用它,我看到不同的有经验的人使用这个数据集来展示一个概念。
该数据集包含这些列:PassengerId、Survived、P-class、姓名、性别、年龄、SibSp、Parch、机票、费用、舱位、上船。
这个数据集有利于机器学习模型 专门 分类模型**统计分析、**数据可视化 练习。
这是我使用该数据集的教程:
*
以下是使用该数据集的一些 pandas 函数的演示:
的链接
人口普查数据集
如果您想体验一下如何探索大型数据集,请使用这个数据集。这个数据集非常大。
这一款非常适合 探索性数据分析、统计分析&建模、 、 数据可视化练习 。
以下是使用该数据集进行数据分析的一些实践:
https://github . com/rashida 048/Advanced-Pandas-Application/blob/master/advancedpandas practice . ipynb
从这里下载这个数据集。
信用卡欺诈数据集
这个数据集不同于这里提到的其他数据集。因为没有功能名称。有时数据科学家不得不处理这样的数据集。
这个数据集是关于信用卡欺诈检测的。银行很可能不会将其客户信息与数据科学家共享。因此,功能名称将不可用。这个数据集提供了一种味道。它有一个二进制列,表明交易是否是欺诈性的。该数据集可用于分类模型。
GitHub 页面中的一个例子:
https://github.com/rashida048/Credit-Card-Fraud-Detection/blob/master/creditCardFraudDetection.ipynb
该数据集也可用于探索性数据分析和可视化。
从此链接下载该数据集。
电影数据集
该数据集包含与不同电影相关的特征。对于一些自然语言处理项目来说,这是一个很好的数据集。
这些是特征:
索引、预算、流派、主页、id、关键词、原创语言、原创标题、概述、受欢迎程度、制作公司、制作国家、发行日期、收入、运行时间、口语、状态、标语、标题、投票平均、投票计数、演员、工作人员、导演。
以下是使用该数据集的电影推荐算法演示:
从此链接下载该数据集。
人民维基数据集
这个数据集是维基百科对不同类型的人的简介。它有三个特征:URI、名字(人名)和文本(包括维基百科的简介)。正如您可能已经想到的,这也是一个用于自然语言处理的良好数据集
以下是使用此数据集的项目示例:
*https://pub.towardsai.net/similar-texts-search-in-python-with-a-few-lines-of-code-an-nlp-project-9ace2861d261
这是这个数据集的链接
亚马逊产品评论数据集
该数据集包含亚马逊产品的数百万条产品评论。
它有三列:产品名称、评论和评级。这个数据集几乎是一个真实的数据集,非常适合 N 自然语言处理 。
我有一个情感分析项目和一篇文章,其中我使用了这个数据集。请点击此处查看:
从此链接下载此数据集。
BBC 文本数据集
另一个精彩的数据集用于 自然语言处理。
该数据集包含来自 BBC 档案馆的不同类型新闻的信息。这是一个很大的文本数据集。
它通常适用于 多类分类 问题。
数据集很大,但只有两列:文本和类别。
这是这个数据集的链接
数字数据集
该数据集包含 10 位数的像素值。它通常用于图像识别问题。
我将这个数据集用于几个不同类型的多类分类问题。
这是一个逻辑回归算法:
以下是 python 中神经网络的演示:
从这个链接下载这个数据集。
Cifer 数据集
此外,数据集包含不同图像的像素值。但与 digits 数据集不同的是,像素值是三维矩阵。
在这个项目中,我使用 Tensorflow 和 Keras 对这个数据集尝试了不同的神经网络结构:
https://github.com/rashida048/Image-Recognition-with-Tensorflow/blob/master/Final_Results_on_cipher10_dataset.ipynb
猫 vs 狗
非常常用来练习 图像分类 。
该数据集包含猫和狗的图像。
对计算机视觉问题有好处。
这里是链接
恶性与良性
另一个有用的数据集为 计算机视觉问题
该数据集还包含两种皮肤癌的图像。
适用于 图像分类 问题
从此处下载该数据集
汽车数据集
这是一个合理大小的数据集,可用于实践一些 回归模型和探索性数据分析。
该数据集包含这些列:年份、品牌、型号、尺寸、(kW)、未命名:5、类型、城市(kWh/100 km)、HWY (kWh/100 km)、梳子(kWh/100 km)、城市(Le/100 km)、HWY (Le/100 km)、梳子(Le/100 km)、(g/km)、等级、(km)、时间(h)。
这是这个数据集的链接
加拿大移民数据集
该数据集提供了每年有多少移民来自哪个国家的信息。
伟大的数据集练习 探索性数据分析数据可视化
这里是链接
脸书股票数据
它提供脸书股票每天的表现。
该数据集中的列有日期、开盘、盘高、盘低、收盘、调整收盘、成交量。
这一条在 时间序列分析可视化 或时间序列相关问题中可以非常有用。
以下是使用该数据集的一些时间序列分析和可视化教程:
这里是链接
Airbnb 数据集
不久前,我在一次采访中收到了这个数据集。
我被要求做一个 探索性数据分析 ,并使用这个数据集开发一个 机器学习模型 。
这个数据集有大量的文本数据和数值数据。您可以使用这个数据集来实践许多不同类型的项目。
您将在链接中看到几个数据集。但是我被要求为我的面试下载 listings.csv 文件。
佛罗里达下沉事故报告
如果您对地理空间分析感兴趣,我想添加一个包含纬度和经度数据的数据集。我将这个数据集用于一些可视化实践:
结论
这些都是我今天想分享的数据集。你应该从这一页找到足够好的数据集和一些项目想法,来练习必要的技能并制作一个作品集。希望这有所帮助。
请随时在 Twitter 上关注我。**
Python 3.10 中的所有重要特性和变化
原文:https://towardsdatascience.com/all-the-important-features-and-changes-in-python-3-10-e3d1fe542fbf?source=collection_archive---------1-----------------------
Python 3.10 的发布越来越近了,所以是时候看看它将带来的最重要的新特性和变化了
大卫·克洛德在 Unsplash 上的照片
又到了一年中最后一个 Python alpha 版本发布的时候了,第一个 beta 版本也在路上了,所以这是一个理想的时间来体验一下新版本的 Python,看看这一次 Python 3.10 中有哪些很酷的新特性!
安装 Alpha/Beta 版本
如果你想尝试最新最好版本 Python 的所有特性,那么你需要安装 Alpha/Beta 版本。然而,考虑到这还不是一个稳定的版本,我们不想用它覆盖我们的默认 Python 安装。因此,要安装 Python 3.10 和我们当前的解释器,我们可以使用以下代码:
运行上述代码后,您将看到 Python 3.10 Alpha IDLE:
随着 Python 3.10 的安装,我们可以看看所有的新功能和变化…
类型检查改进
如果你在 Python 中使用类型检查,你会很高兴听到 Python 3.10 将包括许多类型检查改进,包括带有更简洁语法的类型联合操作符:
最重要的是,这个简单的改进不仅限于类型注释,还可以用于isinstance()
和issubclass()
函数:
类型别名语法更改
在 Python 的早期版本中,添加了类型别名,以允许我们创建代表用户定义类型的别名。在 Python 3.9 或更早的版本中,应该是这样的:
这里的FileName
是基本 Python 字符串类型的别名。但是,从 Python 3.10 开始,定义类型别名的语法将更改如下:
这个简单的改变将使程序员和类型检查人员更容易区分普通的变量赋值和类型别名。这一更改也是向后兼容的,因此您不必更新任何使用类型别名的现有代码。
除了这两个变化之外,打字模块还有其他的改进——即 PEP 612 中的参数规格变量。然而,这些在大多数 Python 代码库中并不常见,因为它们用于将一个可调用的参数类型转发给另一个可调用的参数类型(例如在 decorators 中)。如果你有这样的用例,去看看上面提到的 PEP。
种群统计
从 Python 3.10 开始,你可以使用int.bit_count()
来计算一个整数的二进制表示的位数。这也被称为人口计数(popcount) :
这当然很好,但是现实一点,实现这个函数并不困难,它只是一行代码:
也就是说,这是另一个方便的功能,在某些时候可能会派上用场,这些有用的小功能是 Python 如此受欢迎的原因之一——似乎所有东西都是现成的。
Distutils
已被弃用
在新版本中,不仅添加了一些东西,还取消/删除了一些东西。对于distutils
包来说就是这样,它在 3.10 中被弃用,并将在 3.12 中被移除。这个包已经被setuptools
和packaging
取代有一段时间了,所以如果你正在使用这两个中的任何一个,那么你应该没问题。也就是说,你可能应该检查一下你的代码中distutils
的用法,并开始准备在不久的将来去掉它。
上下文管理器语法
Python 上下文管理器非常适合打开/关闭文件、处理数据库连接和许多其他事情,在 Python 3.10 中,它们的语法将获得一点生活质量的改善。这一变化允许带括号的上下文管理器跨越多行,如果您想在一条with
语句中创建多个上下文管理器,这将非常方便:
正如你从上面看到的,我们甚至可以引用一个上下文管理器(... as some_file
)创建的变量到它后面的另一个上下文管理器中!
这些只是 Python 3.10 中众多新格式中的两种。这种改进的语法非常灵活,所以我不会费心展示每一个可能的格式选项,因为我非常确定无论你在 Python 3.10 中抛出什么,它都很可能会工作。
性能改进
和所有最新版本的 Python 一样,Python 3.10 也带来了一些性能改进。首先是对str()
、bytes()
和bytearray()
构造函数的优化,应该会快 30%左右(摘自 Python bug tracker 示例):
另一个更值得注意的优化(如果使用类型注释)是函数参数及其注释不再在运行时计算,而是在编译时计算。这使得创建带参数注释的函数的速度提高了大约 2 倍。
除此之外,Python core 的各个部分还进行了一些优化。你可以在 Python bug tracker 的以下几个问题中找到细节: bpo-41718 、 bpo-42927 和 bpo-43452 。
模式匹配
你肯定已经听说过的一个重要特性是结构模式匹配。这就要加上case
语句,这个语句我们都是从其他编程语言中知道的。我们都知道如何使用case
语句,但是考虑到这是 Python——它不仅仅是简单的 switch/case 语法,它还增加了一些强大的特性,我们应该探索一下。
模式匹配最基本的形式是由match
关键字后跟表达式组成,然后根据连续case
语句中的模式测试其结果:
在这个简单的例子中,我们使用day
变量作为表达式,然后与case
语句中的单个字符串进行比较。除了带有字符串文字的case
之外,您还会注意到最后一个case
,它使用了_
通配符,相当于其他语言中的default
关键字。不过可以省略这个通配符,在这种情况下可能会出现 no-op,这实质上意味着返回None
。
在上面的代码中需要注意的另一件事是|
的用法,它使得使用|
( 或)操作符组合多个文字成为可能。
正如我提到的,这种新的模式匹配并不以基本语法为结束,而是带来了一些额外的特性,比如复杂模式的匹配:
在上面的代码片段中,我们使用tuple
作为匹配的表达式。然而,我们并不局限于使用元组——任何可迭代的都可以。此外,正如您在上面看到的,通配符_
也可以用在复杂模式中,而不像前面的例子那样单独使用。
使用普通元组或列表可能并不总是最好的方法,所以如果您更喜欢使用类,那么可以用以下方式重写:
这里我们可以看到,用类似于类构造函数的模式来匹配类的属性是可能的。当使用这种方法时,单个属性也被捕获到变量中(与前面显示的元组相同),然后我们可以在各自的case
的主体中使用这些变量。
上面我们还可以看到模式匹配的一些其他特性——在第一个case
语句中,它是一个保护,这是一个遵循模式的if
条件。如果按值匹配还不够,并且您需要添加一些额外的条件检查,这将非常有用。看看这里剩下的case
,我们还可以看到,关键字(例如name=name
)和位置参数都使用这种类似于构造函数的语法,同样的情况也适用于_
(通配符或*“一次性”*)变量。
模式匹配还允许使用嵌套模式。这些嵌套模式可以使用任何可迭代对象,既可以使用类似于构造函数的对象,也可以使用更多的可迭代对象:
在这些类型的复杂模式中,将子模式捕获到变量中以便进一步处理可能是有用的。这可以使用as
关键字来完成,如上面第二个case
所示。
最后,*
操作符可用于*“解包”*模式中的变量,这也适用于使用*_
模式的_
通配符。
如果你想看更多的例子和完整的教程,那就去看看 PEP 636 。
结束语
Python 3.10 带来了许多有趣的新特性,但这是 alpha (很快将是 beta )版本,它还远未经过全面测试和生产准备。因此,现在就开始使用它绝对不是一个好主意。因此,最好是坐下来等待 10 月份的完全发布,并不时查看Python 3.10 页面中的新内容,以了解任何最新的补充。
也就是说——如果你渴望升级——抓住第一个 beta 版本(将在 6 月的某个时候发布)并进行测试,看看你现有的代码库是否与所有即将到来的变化、功能/模块的弃用或删除兼容,这可能不是一个坏主意。
本文最初发布于martinheinz . dev
为了一个好的线性回归,你必须做的所有统计测试
原文:https://towardsdatascience.com/all-the-statistical-tests-you-must-do-for-a-good-linear-regression-6ec1ac15e5d4?source=collection_archive---------5-----------------------
线性回归不仅仅是运行代码和评估 R。
由 Maksym Kaharlytskyi 在 Unsplash 上拍摄的照片
摘要
这篇文章的目的是展示许多围绕线性回归的统计测试。我知道这听起来可能有些重复(“*又一篇关于线性回归的文章”),*但是我将要写的信息并没有像我们想象的那样广泛传播。
我们将涵盖以下主题:
- 线性回归模型的必要假设是什么
- 检验残差的正态性
- 检验残差的可变性
- 检查残差中的异常值
- 检验残差的独立性
- 着眼于多重共线
不要担心,我会把整个代码留在最后,在那里你可以看到我为每个测试导入了什么。
作为数据集,我将使用来自sklearn
的关于葡萄酒的“玩具数据集”。
对于建模和测试,我将使用statsmodels
,因为它有库中需要的所有测试。您可以用 statsmodels 执行测试,然后用 sklearn 构建它。你的电话。
# Load the dataset
import sklearn.datasets
data_ = sklearn.datasets.load_wine()# Create dataframe
df = pd.DataFrame(data_.data, columns=data_.feature_names)
df['target'] = data_.target
df.rename(columns={'od280/od315_of_diluted_wines': 'test_diluted_wines'}, inplace=True)
初步考虑
好了,在“又一篇关于线性回归的文章”这一点上,我想说一些事情。
首先,我知道上面的数据集很适合线性回归,我也知道它只是为了研究的目的。这里的想法是显示每个测试的执行方式,以及模型实际通过测试时的样子,这样我就可以给你理解和评估数据的关键。
其次,现实生活是艰难的,人们。老实说,来自现实生活的大多数数据集不会通过这些测试,你必须对它们进行处理,转换数据,进行特征工程,调整模型,甚至选择不同的算法来为你的数据建模。这就是你报名参加的工作——数据科学家。
最后,但同样重要的是,当我们执行线性回归模型时,我们应该遵循许多假设。正如查尔斯·惠兰在他的巨著《赤裸裸的统计》中所说:
LR 在操作上易于执行。即使是一个孩子也可以用现在可用的优秀软件做到这一点,但是要正确地完成它,那就是另一回事了。
线性回归
普通最小二乘法(OLS)是 LR 最常用的方法,简而言之,它试图在给出最佳拟合的点之间画一条线,当我们将实际值与回归线之差相加时,它会给出最小的数字。
这种差异就是著名方程*y = a+bx+****e .***的误差成分,【OLS】方法将对这些误差进行平方,并对这些量进行求和,试图达到最小数作为结果,这将产生最佳拟合方程的系数。
OLS 方法。图片由作者提供。
作为等式中的误差部分,它非常重要。在一篇出色的文章中,作者 Dalson FIGUEIREDO FILHO、Felipe NUNES、Enivaldo CARVALHO DA ROCHA、Manoel LEORNARDO SANTOS、Mariana BATISTA e joséAlexandre SILVA JUNIOR 在 Revista Política Hoje,Vol.20,n. 1,2001 中描述了我们应该测试 LR 残差的许多假设,我们将在本文中描述和编码这些假设:
- 残差必须服从正态分布。
- 残差是齐次的,有齐次方差。
- 误差中没有异常值。
- 误差中没有自相关。
- 自变量之间没有多重共线性。
误差必须服从正态分布
当我们创建 LR 模型时,有时我们会听到变量必须遵循正态分布。这不完全正确。必须遵循这种分布的是残差。
LR 模型的残差必须遵循正态分布,因此通过 OLS 方法找到的估计量不会有偏差,并且更有效(FIGUEIREDO FILHO et all,2011)。
这是在数据集加载后如何完成的。
**# Regression Model**model = smf.ols('target ~ alcohol + ash + alcalinity_of_ash + total_phenols + flavanoids + nonflavanoid_phenols + color_intensity + hue + test_diluted_wines + proline', data = df).fit()**# Extract the residuals**
model_resid = model.resid
测试常态。
**# Kolmogorov-Smirnov test**
_, p = lilliefors(model_resid, dist='norm')
print('Not normal | p-value:' if p < 0.05 else 'Normal | p-value:', p)
print('-------------------------------')**# Anderson**
stat, p3, _ = scs.anderson(model_resid, dist='norm')
print('Anderson:')
print('Not normal | stat:' if stat > p3[2] else 'Normal | stat:', stat, ':: p-value:', p3[2])**[OUT]:**
Normal | p-value: 0.2 -------------------------------
Anderson: Normal | stat: 0.35916418199656164 :: p-value: 0.77
我还可以绘制 QQ 图,看看数据在哪里偏离了正态分布,当情况就是这样。
**# QQPlot**
scs.probplot(model_resid, dist='norm', plot=plt)
plt.title('QQ Plot')
plt.show()
残差的 QQ 图。图片由作者提供。
同方差性
残差必须是齐次的。如果我们从逻辑上考虑,这很有意义。我的意思是,如果我们正在分析线性关系的数据,我想表明 Y 随着 X 和 Z 的增加而增加,那么很明显,误差将在一定范围内。误差不应该离直线太远,否则我们就谈不上良好的线性关系。
我们可以用数字和图形来验证。
# Ho = Homocedasticity = P > 0.05
# Ha = There's no homocedasticity = p <=0.05**# Homocedasticity test**
stat, p, f, fp = sms.het_breuschpagan(model_resid, model.model.exog)
print(f'Test stat: {stat}')
print(f'p-Value: {p}')
print(f'F-Value: {f}')
print(f'f_p_value: {fp}')**[OUT]:**
Test stat: 14.254047656267216
p-Value: 0.16171589669144282
F-Value: 1.45373117596194
f_p_value: 0.16108656286704198
形象地说。
plt.scatter(y= model_resid, x=model.predict(), color='red')
plt.hlines(y=0, xmin=0, xmax=4, color='orange')
plt.xlabel('Predicted values')
plt.ylabel('Residuals')
plt.show()
误差看起来是恒定的。图片由作者提供。
异常值检验
除了最后一个测试,另一个好的测试是残差中异常值的存在。该测试将帮助我们确定是否有我们的模型不能给出令人满意的结果的地方。它证实了模型的质量。建议数字在-3 和 3 之间甚至-5 和 5 之间。
**# Outliers test**
outliers = model.outlier_test()print(outliers.max())
print(outliers.min())**[OUT]:** student_resid 3.254315
unadj_p 0.999499
bonf(p) 1.000000
dtype: float64
student_resid -2.460243
unadj_p 0.001377
bonf(p) 0.245188
dtype: float64
残差独立性
残差的独立性意味着观测值也是独立的。所以在 t1 时刻的测量不会影响 t2 时刻的测量。
这里,测试的统计量越接近 2 越好。这意味着相关性(r)接近于零,当代入这个公式 2 x (1-r) 时,结果将是 2。
print( f'Test stat: {durbin_watson(model_resid)}')**[OUT]:** Test stat: 1.5212847896408088
多重共线性
多重共线性会搞乱线性回归模型。
当它存在时,计算 OLS 的模型会丢失信息。因此,多重共线性越多,模型的信息就越少。
多重共线性的问题是估计参数的方差增加。这是因为自变量之间的高度相关性使得精确估计每个变量对因变量的影响变得不可能。(菲格雷多·菲尔霍等人,2011 年)。
# check correlations
variables = df.drop('target', axis=1)variables.corr()
你也可以使用变动通货膨胀因素,因为这给你一个单一的数字来看。它计算受其他变量影响的给定变量的方差。根据经验,这个数字应该低于 10。有人说低于 7。
from statsmodels.stats.outliers_influence import variance_inflation_factor
from statsmodels.tools.tools import add_constant**# VIF Test**
vif = add_constant(variables)
pd.Series([variance_inflation_factor(vif.values, i) for i in range(vif.shape[1])], index=vif.columns)const 680.485185
alcohol 2.460372
malic_acid 1.656647
ash 2.185448
alcalinity_of_ash 2.238732
magnesium 1.417855
total_phenols 4.334519
flavanoids 7.029350
nonflavanoid_phenols 1.796380
proanthocyanins 1.975683
color_intensity 3.026304
hue 2.551447
test_diluted_wines 3.785473
proline 2.823849
dtype: float64
模型分析
在模型通过了所有这些测试之后,我们现在可以很好地评估它的总结了。statsmodels
带来了一个伟大的。
print( model.summary() )
模型的总结。图片由作者提供。
我们的模型很好。我们应该看看 R 平方的 T4,看看这个线性方程能解释多少关系。是 89%。如果我们想知道这些选择的变量实际上如何影响目标并解释方差,那么我们应该看看 R2 调整的,通常也用于与 AIC 和 BIC 一起比较模型(最后提到的两个指标,越低越好)。
R2 和调整后的 R2 都让你知道有多少数据点落在回归方程的直线上。然而,R2 和调整后的 R2 之间有一个主要区别:R2 假设每个变量都可以解释因变量的变化。调整后的 R2 告诉你仅由实际影响因变量的自变量解释的变化的百分比。
查看 P > |t|列,这是每个变量的 P 值。它解释了该模型的统计意义。理想情况是所有数据的显著性水平都低于 0.05。门槛那边有几个人。
由于某些原因,我们损失了 10%的方差。为了改进这个模型,应该有一个完整的数据探索,特征工程,必要时执行转换。嗯,很多可能性。
在你走之前
LR 是一个强大的工具。特别是当你知道如何创建它并测试它的假设时。
记住要经常进行这些测试。它们并不僵硬。他们应该是灵活的,应该给你一个好的方向,无论你的模型是好是坏。
以下是完整的代码:
参考
什么是 VIF 可以接受的价值观?
在 LR 中什么该做,什么不该做。
R2 和 R2 的区别——调整后的。
如果你喜欢这个内容,探索并关注我的博客。
https://medium.com/gustavorsantos
Python 中压缩和归档文件的所有方法
原文:https://towardsdatascience.com/all-the-ways-to-compress-and-archive-files-in-python-e8076ccedb4b?source=collection_archive---------2-----------------------
用 Python 压缩、解压缩和管理你可能需要的所有格式的档案和文件
托马斯·索贝克在 Unsplash 上拍摄的照片
Python 标准库为你能想到的几乎任何任务提供了很好的模块和工具,处理压缩文件的模块也不例外。无论是像tar
和zip
这样的基础,还是像gzip
和bz2
这样的特定工具或格式,甚至是像lzma
这样更奇特的格式,Python 都有。有了所有这些选择,决定什么可能是手头任务的正确工具可能就不那么明显了。因此,为了帮助您浏览所有可用的选项,我们将在本文中探索所有这些模块,并了解如何借助 Python 的标准库来压缩、解压缩、验证、测试和保护各种格式的档案。
所有的格式
如上所述,Python 拥有(几乎)所有可以想象的工具/格式的库。所以,让我们先来看看它们,看看为什么你会想使用它们:
zlib
是一个库和 Python 模块,它提供了使用 Deflate 压缩和解压缩格式的代码,这种格式被zip
、gzip
和其他许多人使用。因此,通过使用这个 Python 模块,您实际上是在使用gzip
兼容的压缩算法,而没有方便的包装器。关于这个库的更多信息可以在维基百科上找到。bz2
是为bzip2
压缩提供支持的模块。该算法通常比 deflate 方法更有效,但可能会更慢。它也只对单个文件起作用,因此不能创建档案。lzma
既是算法的名字,也是 Python 模块的名字。它可以产生比一些旧方法更高的压缩比,并且是xz
实用程序(更具体地说是 LZMA2)背后的算法。gzip
是我们大多数人都熟悉的一种实用工具。这也是一个 Python 模块的名字。这个模块使用已经提到的zlib
压缩算法,并作为一个类似于gzip
和gunzip
实用程序的接口。shutils
是一个模块,我们通常不会将其与压缩和解压缩联系起来,但它提供了处理档案的实用方法,可以方便地生成tar
、gztar
、zip
、bztar
或xztar
档案。zipfile
——顾名思义——允许我们用 Python 处理zip
文档。这个模块提供了创建、读取、写入或附加到 ZIP 文件的所有预期方法,以及更容易操作这些文件的类和对象。tarfile
-和上面的zipfile
一样,你大概可以猜到这个模块是用来处理tar
档案的。可以读写gzip
、bz2
、lzma
文件或档案。它还支持我们从tar
实用程序中了解到的其他功能,这些功能的列表可以在上面的链接文档页面的顶部找到。
压缩和解压缩
我们有很多图书馆可供选择。其中一些更基本,一些有很多额外的特性,但它们的共同点是(显然)都包括压缩功能。因此,让我们来看看如何对它们中的每一个执行这些基本操作:
第一个上来,zlib
。这是一个相当低级的库,因此可能不会经常使用,所以让我们只看一下整个文件的基本压缩/解压缩:
在上面的代码中,我们使用由head -c 1MB </dev/zero > data
生成的输入文件,它给了我们 1MB 的零。我们打开并读取这个文件到内存中,然后使用compress
函数创建压缩数据。然后,这些数据被写入输出文件。为了证明我们能够恢复数据,我们再次打开压缩文件并对其使用decompress
函数。从打印语句中,我们可以看到压缩和解压缩数据的大小是匹配的。
下一个你可以使用的格式和库是bz2
。它的使用方式与上面的zlib
非常相似:
不出所料,这些模块的接口几乎是相同的,所以为了显示一些不同,在上面的例子中,我们简化了压缩步骤,减少到几乎只有一行,并使用os.stat
来检查文件的大小。
这些低级模块中的最后一个是lzma
,为了避免重复显示相同的代码,我们这次做一个增量压缩:
我们首先创建一个输入文件,该文件由从/usr/share/dict/words
中提供的字典中提取的一串单词组成。这是为了让我们实际上可以确认解压缩的数据是相同的原始数据。
然后我们像前面的例子一样打开输入和输出文件。然而这一次,我们以 1024 位的块迭代随机数据,并使用LZMACompressor.compress
压缩它们。这些块然后被写入输出文件。在整个文件被读取和压缩后,我们需要调用flush
来完成压缩过程,并从压缩器中清除任何剩余的数据。
为了确认这是可行的,我们以通常的方式打开并解压缩文件,首先打印文件中的几个单词。
继续学习更高级别的模块——现在让我们使用gzip
来完成相同的任务:
在这个例子中,我们结合了gzip
和shutils
。看起来我们像之前用zlib
或bz2
做了同样的批量压缩,但是由于shutil.copyfileobj
我们得到了分块的增量压缩,而不必像用lzma
那样循环数据。
gzip
模块的一个优点是它还提供了命令行接口,我不是在说 Linux gzip
和gunzip
而是在说 Python 集成:
拿把大锤子来
如果你更喜欢使用zip
或tar
,或者你需要其中一个提供的格式的文档,那么这一节将告诉你如何使用它们。除了基本的压缩/解压缩操作,这两个模块还包括一些其他的实用方法,如测试校验和,使用密码或在档案中列出文件。因此,让我们深入了解一下所有这些活动。
这是一段相当长的代码,但是涵盖了zipfile
模块的所有重要特性。在这个代码片段中,我们首先使用ZipFile
上下文管理器在*“write”*(w
)模式下创建 ZIP 存档,然后将文件添加到这个存档中。您会注意到,我们实际上并不需要打开正在添加的文件——我们需要做的只是调用write
传递文件名。添加完所有文件后,我们还使用setpassword
方法设置了存档密码。
接下来,为了证明它有效,我们打开归档文件。在读取任何文件之前,我们检查 CRC 和文件头,之后我们检索存档中所有文件的信息。在这个例子中,我们只打印了ZipInfo
对象的列表,但是您也可以检查它的属性来获得 CRC、大小、压缩类型等。
检查完所有文件后,我们打开并阅读其中一个。我们看到它有预期的内容,所以我们可以继续将它提取到 path 指定的文件中(/tmp/
)。
除了创建阅读档案/文件,ZIP 还允许我们将文件添加到现有的档案中。为此,我们只需将访问模式更改为*“追加”* ( "a"
):
和gzip
模块一样,Python 的zipfile
和tarfile
也提供了 CLI。要执行基本的存档和提取,请使用以下命令:
最后但同样重要的是,tarfile
模块。该模块类似于zipfile
,但也实现了一些额外的功能:
我们从归档的基本创建开始,但是这里我们使用访问模式"w:gz"
,它指定我们想要使用 GZ 压缩。之后,我们将所有文件添加到存档中。有了tarfile
模块,我们还可以传入符号链接或整个目录,它们将被递归添加。
接下来,为了确认所有的文件都确实存在,我们使用了getmembers
方法。为了深入了解单个文件,我们可以使用gettarinfo
,它提供了所有的 Linux 文件属性。
tarfile
提供了一个我们在其他模块中没有见过的很酷的特性,那就是当文件被添加到存档时,可以修改文件的属性。在上面的代码片段中,我们通过提供修改TarInfo.mode
的filter
参数来更改文件的权限。该值必须以八进制数的形式提供,这里0o100600
将权限设置为0600
或-rw-------.
。
为了在做了这一更改后获得文件的完整概览,我们可以运行list
方法,它给出了类似于ls -l
的输出。
最后要做的是打开并解压tar
文件。为此,我们使用"r:gz"
模式打开它,使用文件名检索 info 对象(member
),检查它是否真的是一个文件,并将其提取到所需位置:
结论
正如你所看到的,Python 的模块提供了很多选项,有低级的也有高级的,有特定的也有通用的模块,有简单的也有更复杂的接口。您选择什么取决于您的用例及需求,但一般来说,我会建议使用通用模块,如zipfile
或tarfile
,只有在必要时才求助于像lzma
这样的模块。
我试图涵盖这些模块的所有常见用例,以便为您提供完整的概述,但显然还有更多函数、对象、属性等。因此,请务必查看第一部分中链接的文档,找到一些其他有用的信息。
本文最初发布于martinheinz . dev
[## Python 中重载函数的正确方法
towardsdatascience.com](/the-correct-way-to-overload-functions-in-python-b11b50ca7336)
扩大人工智能创新漏斗的模型
原文:https://towardsdatascience.com/all-things-tend-towards-chaos-a-model-for-widening-the-ai-innovation-funnel-aa5690b086c?source=collection_archive---------60-----------------------
帕特里克·托马索在 Unsplash 上的照片
几年前,一个朋友分享说,他是一个集装箱商店的超级粉丝——他认为所有的事情都趋向于混乱,有一个地方来组织你的生活令人难以置信地放松。这是我在 2020 年上半年留下的印象,当时我正在构建一套流程,以在现有业务内促进人工智能(AI)创新。对某些人来说,这完全是在混乱中强加秩序(从事有商业价值的项目)(建立一种产生新想法的文化)。
从那以后,我开始接受另一种观点。
- 首先,一个合适的运营模式提供了约束,可以促进新想法(这是我几年前在与 BuzzFeed 的前设计副总裁的一次对话中实际学到的,但并没有意识到!).
- 第二,新想法可能是偶然发现的,但对新想法的探索是通过严格的系统实验框架完成的。合适的运营模式应该有助于创新者浮出水面,强化这些创意所带来的价值。
经过反思,我认为这种态度上的变化归结为两件事:1)对“颠覆性创新”的精确定义有了清晰而深刻的理解,2)认识到实施的核心正在改变文化——这不是一个小壮举(我将在第五节详细阐述这两件事)。
那么,在一个更大的组织中,什么是“合适的”运营模式呢?总的来说,有很多关于创新战略的伟大文献,在科技领域,我想起了几个孵化器的例子。在这篇文章中,我分享了我对现有机构内人工智能创新的看法(第一节& II)。我将这一系列过程(价值观、运营模式和工作标准)称为产品孵化器过程。
我很高兴我的观点发生了转变。它让我走上了一条迷人的道路,用科学来塑造科学过程(第三部分)。尽管产品孵化器过程对我们的团队产生了积极的影响,一个追踪各种成功标准的过程(第四节),我公开分享这项工作的动机是为了促成更大的讨论。我很想听听其他组织的人是如何努力克服这个问题和相关挑战的。
为科学的过程使用科学…(【http://gph.is/1hyPhds】T2)
一、问题
我们知道现有业务的创新对于长期增长是必要的。这意味着精心设计一个稳健的运营模式和激励结构(不止两年一次的黑客马拉松!)至关重要,必须及时完成,并影响公司最终构建的产品(康威的模型;也就是,“你发货你的组织”。这很难做到,因为公司通常以创造短期商业价值为导向。
为了建立产品孵化器流程,我专注于这种二分法的核心问题:在一个价值超过成本的现有机构中,你如何找到并激发创新的人工智能想法?
(还有其他问题,但几乎都归结到这个问题。例如:
- 你如何创造一个鼓励而不是抑制探索的过程?
- 什么时候你鼓励对一个想法进行更深入的挖掘(开发)?
- 你能确保在短期内为企业创造价值吗?
- 您如何衡量短期内实施这种运营模式的成功程度?)
二。解决方案(产品孵化器结构概述)
产品孵化器流程列出了详细的工作标准和完整的运营模式指南,用于创新、孵化和扩大团队的工作漏斗。
- 工作的标准包括 1)预期的结果,2)成功的标准,以及 3)建议的工件。
- 运营模式提供了一个框架来回答具体的战术问题,例如每个提案的创新者数量、投资者委员会的组成、每个阶段的时间限制以及审核的节奏。
在高层次上,产品孵化器流程可以被认为是一个风险投资(VC)模型(T1),它被映射到一个 T2 产品发布漏斗(T3)的顶部。
- 与典型的风险投资模式不同,产品孵化器过程中的价值既包括“近端的”(明显的和财务的)利益,也包括“扩散的”(第二或第三)利益。扩散利益可以包括,例如,产品对社会的影响,创新者的知识获取,或与组织内其他团队建立关系。
- 通常,产品发布漏斗包含四个阶段。产品孵化器流程大致指的是下图中的阶段 1 和阶段 2。我包括了从每个阶段过渡到下一个阶段的指南,以及针对阶段 0 的轻量级指南,以及从产品孵化器中走出来的指南。
产品发布漏斗的高级视图(Anita Mehrotra)。
- 随着每个后续阶段的进行,尽职调查的程度会变得更深,从而可以更准确地估计潜在价值和执行建议想法的预计成本(例如,时间、资金、数据采集、所需的基础设施)。
最终,如果创新者和投资者委员会对成本和价值进行了评估,那么一个被提议的想法就会离开产品孵化器。
三世。为科学而科学&迭代测试
在开发这些过程中,我借鉴了从软件工程到数学和金融的一系列框架和理论。
有非常丰富的文献涵盖了上述内容,这为产品孵化器过程提供了一个极好的理论起点。然而,现实的约束并没有显露出来,直到这个过程用真实的用例进行了电池测试。
为此,在开始创建过程之前,我与团队的所有 25 名成员进行了一系列的用户需求收集和头脑风暴会议。这使得团队能够参与进来,并对产品孵化器的成功至关重要。然后,我对产品孵化器过程进行了两个测试:1)一个独立的、原型的提议想法,它“跑在”2)一个更大的、团体的“试运行”的前面。
- 从 2020 年 2 月 15 日到 3 月 31 日, alpha 测试是一个典型的提议想法,我与我们组织中的一个商业伙伴团队一起独立工作。作为流程的第一步,该测试告知了对预期、与潜在合作伙伴团队合作的方式以及评估试运行成功的运营模式的更新。
- 测试版测试是一次试运行,我的团队中有 10 名参与者,从 2020 年 2 月 26 日持续到 3 月 20 日。大多数参与者没有 100%成为产品孵化器的带宽,第一阶段的最后期限是交错的。这使得试运行能够具体测试以下内容:围绕一系列想法召集一组人,以及确定时间限制阶段 1 的合理时间窗口(分别用 4、6 和 2 个提案测试了 1.5 周、2.5 周和 3.5 周)。此外,试运行还提供了一个实验平台,用于测试从以交付为中心到以“失败没关系”为心态的有组织混乱的文化演变。事实证明,管理相互竞争的优先级比部署产品孵化器时更具挑战性,也更不现实。
四世。测量影响
产品孵化器流程根据预先定义的六个指标来跟踪成功。(特别欢迎在此讨论;测量模糊的东西是很困难的,你会在下面的第 6 条中看到!)
- 到 2020 年 5 月 15 日(2020 年 Q2 中期),在产品积压中用一句话捕捉 100 个想法
- 在 2020 年 3 月 31 日前提交 20 份单页简报,包括业务案例、提议的方法和估计的影响
- 2020 年 6 月 30 日前的 10 个价值证明
- 5 在 2020 年 6 月 30 日前提交完整提案。完整的建议书包括:价值证明演示;我们团队和合作伙伴团队的业务主管就价值和归属达成一致;轻量级/概要产品需求文档和估计的产品路线图
- 到 2020 年 7 月 1 日,整个组织内至少有七个强大的合作伙伴关系,其中有三至四个新业务
- 一种“群聚并领导”的团队动力,带有“适当的工具”
最终,仅试运行的影响是:
- 在产品孵化器产品积压中提出了 80 多个想法
- 12 个单页工件,通过第一阶段标准进行尽职调查
- 3 个提议的想法通过 MVP 阶段获得资助,并从产品孵化器中移出
- 4 与公司业务团队的新合作伙伴关系
五、建立产品孵化器过程中克服的挑战
**语言的清晰。**术语和定义的语言和一致性对于产品孵化器流程的成功至关重要。
- 在这个旅程的早期,我就知道颠覆性创新已经被过度使用;根据我和谁说话以及什么时候说话,它会产生不同的效果(从眼球转动到渴望)。我面临的部分挑战是,当我们谈论推动一种支持颠覆性创新的模式时,确保所有利益相关者都清楚这意味着什么:
“一个产品或服务最初在市场底部的简单应用程序中扎根,然后不断向市场高端移动,最终取代现有竞争对手的过程。” - “变得创新”不仅需要改变人们如何一起工作,还需要改变他们如何感受。著名的羞耻感和脆弱性研究员 Brene Brown 博士咨询了那些努力培养创新文化的企业领导人,一次又一次地证明只有当一个组织拥有让人们对失败感到舒适的空间时,他们才能真正具有创新精神*。尽管从零开始创造这种文化具有难以置信的挑战性,但改变现有的文化使之成为这样就更难了。*
不同的工作方式。最大的挑战之一是提供一种结构,同时不让流程抑制创造力。对于我们团队中的一些研究人员来说,这种思维模式的改变很难驾驭,他们觉得文档很麻烦。对我来说,这是一个关于转变心态和做出文化决定的有趣观点。
产品孵化器过程的长期影响仍有待观察,但最终,它们提供了一个似乎站得住脚的框架。创造它们的旅程也是一个独特的机会,将科学的“思维方式”融入到我们团队的运营中。
参考文献
在开发产品孵化器过程中参考文献的子集可以在这里找到。
- 网飞文化宣言。https://jobs.netflix.com/culture/#introduction
- 克里斯滕森和雷诺,《创新者的困境》(2003)。
- 赖夫,2020 年 3 月 5 日。A、B、C 系列融资:运作方式。<https://www . investopedia . com/articles/personal-finance/102015/series-b-c-funding-what-it-all-means-and-how-it-works . ASP>
- Zider,1998 年 11 月至 12 月号。风险投资是如何运作的。<https://hbr.org/1998/11/how-venture-capital-works
- 伯恩哈德松,2019 年 4 月 15 日。为什么软件项目花费的时间比你想象的要长:一个统计模型<https://Erik Bern . com/2019/04/15/why-software-projects-take-long-than-you-think-a-statistical-model . html>
- 格雷厄姆,“做不可扩展的事情”(2013 年 7 月)。<http://paulgraham.com/ds.html
- 产品计划。产品管理:产品发布。【https://www.productplan.com/glossary/product-launch/<https://www.productplan.com/glossary/product-launch/
- Gottesdiener,e . 2019 年 1 月 15 日。使用产品画布定义您的产品:入门。<https://www . ebg consulting . com/blog/using-product-canvas-define-product-get-started/>
- 传统的 POC 已经死亡。视点万岁。<https://www.omnetric.com/blog/iot-poc-pov
- 赖斯,2009 年 8 月 3 日。摘自《创业经验》最低可行产品:指南。<http://www . startuplessonslearned . com/2009/08/minimum-viable-product-guide . html>
- 英国楚门,2016 年 12 月 25 日。产品和解决方案:你知道区别吗?<https://hacker noon . com/products-and-solutions-do-you-know-the-difference-4ff 9169 cefe 3>
- 贝尔,2001 年。“社会研究方法”,第三章:研究设计,概念化,操作化,测量。社会研究方法/研究设计。<https://en . wiki books . org/wiki/Social _ Research _ Methods/Research _ Design>
- 2015 年 4 月 17 日,j。谷歌著名的“20%时间”政策的真相。<https://www . business insider . com/Google-20-percent-time-policy-2015-4>
- 2020 年 1 月 15 日。公交因素。<https://en.wikipedia.org/wiki/Bus_factor
- 希克森,2016 年 5 月 15 日。敏捷自行车:软件开发的更好类比。<https://m.dotdev.co/the-agile-bicycle-829a83b18e7?gi = 49 ee 7a 37 a4 cc
所有顶级数据科学 Python 库解释(带代码)
原文:https://towardsdatascience.com/all-top-python-libraries-for-data-science-explained-with-code-40f64b363663?source=collection_archive---------2-----------------------
简明英语的数据科学 Python 库和免费学习资源
约翰·施诺布里奇在 Unsplash 上的照片
Python 是数据科学中最流行的编程语言之一。它提供了大量的库,这些库提供了处理数学、统计和科学函数的强大功能。
然而,Python 有超出数据科学的应用,所以有很多 Python 库是你永远不会在数据科学项目中使用的。
为了帮助您专注于学习数据科学所需的 Python 内容,我将使用实际例子向您介绍所有顶级的数据科学 Python 库。除此之外,我会分享大量的资源来帮助你免费学习它们。
注意:你可以用 *pip*
或者 *conda*
安装本文提到的大部分库。查看我将在每一节末尾留下的指南或它们的文档,以便轻松地安装它们。
**Table of Contents** 1\. [Python libraries for Data Collection](#c268)
2\. [Python libraries for Data Cleaning & Wrangling](#9d79)
3\. [Python libraries for Feature Engineering](#a7e4)
4\. [Python libraries for Data Visualization](#35e9)
5\. [Python libraries for Model Building & Deployment](#b542)
用于数据收集的 Python 库
每个数据科学项目都是从数据收集开始的。有时数据是 CSV 格式的,或者需要从数据库中提取。然而,当数据不可用时,你可以从世界上最大的数据库——互联网上获取公共数据。下面的库帮助你用一种叫做网络抓取的技术从互联网上提取数据。
免责声明:并非所有网站都允许网络抓取。如果您正在访问网站,您应该始终考虑他们的服务条款并检查robots.txt
文件(更多详细信息在此)。如果你发出太多的请求,你可能会被网站屏蔽。记住,如果网站有一个 API 或者有一个免费的数据集(你可以在 Kaggle 上找到数百个),那么做网络抓取就没有意义了。
请求&美丽的汤
通过使用 Request 和 Beautiful Soup 库,我们可以从不运行 JavaScript 的网站中提取数据。
请求库帮助我们用 Python 发出 HTTP 请求。得益于此,我们可以获得一个网站的内容。然后我们使用解析器(例如 html.parser、lxml 等)和 Beautiful Soup 来提取网站中的任何数据。
让我们看一个例子:
硒/瘙痒
硒和刺痒的作用和美人汤一样;然而,他们更强大。
它们都可以从 JavaScript 驱动的网站中提取数据。Selenium 也可以用于 web 自动化,而 Scrapy 速度很快,允许您轻松地将数据导出到数据库,并且具有其他功能,使其成为最完整的工具。
下面是从头开始学习这些库的指南:
- 美汤指南(刮电影抄本)
- 硒导(刮庄家)
- 抓取指南(抓取人口数据)
- 4 网页抓取项目让你的生活自动化
- 网页抓取备忘单
用于数据清理和争论的 Python 库
一旦有了可读格式(CSV、JSON 等)的数据,就该清理它了。熊猫和 Numpy 图书馆可以在这方面提供帮助。
熊猫
Pandas 是一个强大的工具,它提供了多种操作和清理数据的方式。Pandas 处理数据帧,它将数据组织在一个类似于 Excel 电子表格的表格中,但速度更快,并具有 Python 的所有功能。
这是你创建熊猫数据框架的方法:
import pandas as pd# data used for the example (stored in lists)
states = ["California", "Texas", "Florida", "New York"]
population = [39613493, 29730311, 21944577, 19299981]# Storing lists within a dictionary
dict_states = {'States': states, 'Population': population}# Creating the dataframe
df_population = pd.DataFrame.from_dict(dict_states)print(df_population)
作者图片
Numpy
Numpy 是一个具有数学功能的 Python 库。它允许我们处理多维数组、矩阵、生成随机数、线性代数例程等等。
当涉及到扯皮和转换数据时,经常使用一些 Numpy 方法,如np.where
和np.select
。除此之外,其他库如 Matplotlib 和 Scikit-learn 在某种程度上依赖于 NumPy。
让我们看看如何用 NumPy 创建一个二维数组。
import numpy as npb = np.array([[1.5,2,3], [4,5,6]],dtype=float)IN [0]: print(b)
IN [1]: print(f'Dimension: {b.ndim}')OUT [0]: [[1.5 2\. 3\. ]
[4\. 5\. 6\. ]]
OUT [1]: Dimension: 2
不平衡学习
不平衡学习是一个帮助我们处理不平衡数据的库。当每个类的观测值数量分布不均时,就会出现不平衡数据。例如,在亚马逊产品的评论部分,您通常会看到大量的正面评论(大多数类别)和少量的负面评论(少数类别*)。*
我们使用不平衡学习(imblearn)库对数据进行重采样。您可以对正面评价进行欠采样,也可以对负面评价进行过采样。
让我们看看我是如何使用RandomUnderSampler
对正面评价进行欠采样的(完整代码可以在下面列出的指南中找到)
下面是从头开始学习这些库的指南:
- 【Excel 用户熊猫指南
- Numpy 指南
- 通过 Sci-kit 学习实现不平衡学习
用于数据可视化的 Python 库
饼图、条形图、箱线图和直方图等图表通常用于探索性数据分析,也用于展示结果。Python 库允许我们制作传统的以及交互式的图形。
Matplotlib/Seaborn
Matplotlib 是一个允许我们进行基本绘图的库,而 Seaborn 则擅长统计可视化。
主要区别在于创建一个情节需要编写的代码行。Seaborn 更容易学习,有默认主题,默认情况下制作的剧情比 Matplotlib 好看。
让我们为在 Pandas 部分创建的df_population
数据帧创建一个柱状图。
import matplotlib.pyplot as plt
plt.bar(x=df_population['States'],
height=df_population['Population'])plt.xlabel('States')
plt.ylabel('Population')
plt.show()
作者图片
现在让我们用 Seaborn 创造同样的情节。
import seaborn as sns
sns.barplot(x=df_population['States'],
y=df_population['Population'],
palette='deep')
plt.show()
作者图片
如您所见,我们不需要在 Seaborn 中指定轴名(它取自 dataframe 列),而 Matplotlib 需要更多的代码行,默认情况下绘图看起来一点也不好看。
Plotly/Bokeh(熊猫集成)
如果想更上一层楼,应该尝试用 Plotly 或者 Bokeh 做交互可视化。两者都允许创建大量的交互式绘图,最酷的是你可以使用它们中的任何一个直接用 Pandas 绘图语法来绘图。
两者都使绘制交互式可视化变得容易,但在我看来,Plotly 默认创建更好看的图。
这是一个如何使用熊猫绘图语法创建交互式绘图的例子。
import pandas as pd
import cufflinks as cf
from IPython.display import display,HTML
cf.set_config_file(sharing='public',theme='white',offline=True)
df_population = df_population.set_index('States')
df_population.iplot(kind='bar', color='red',
xTitle='States', yTitle='Population')
作者图片
词云/风格云
Wordclouds 允许我们识别一段文本中的关键词。Python 有两个这种类型的图形库——word cloud 和 stylecloud。
第一个制作基本的词云,甚至允许我们上传自己的图像作为词云的遮罩,而第二个用几行代码创建华丽的词云,并提供大量高质量的图标,你可以在你的词云上使用。
让我们把著名的史蒂夫·乔布斯在斯坦福的演讲做成文字云。的。我用于 wordcloud 的 txt 文件可以在我的 Github 上找到。
import stylecloud
stylecloud.gen_stylecloud(file_path='SJ-Speech.txt',
icon_name= "fas fa-apple-alt")
这就是你制作这个单词云所需要的全部!您可以移除停用字词并使用其他功能。要了解更多细节,请查看我的 wordcloud 指南。
下面是从头开始学习这些库的指南:
- Python 中美丽可视化的简单指南(Matplotlib&Seaborn Guide)
- 用熊猫制作漂亮的互动视觉效果的最简单方法(Plotly 指南)
- 如何用 Python 轻松制作漂亮的文字云
用于要素工程的 Python 库
一旦清理了数据,下一步就是让数据更容易分析。尽管数据被整齐地组织在表格/数据帧中,但是对于机器来说,这些数据可能仍然难以理解和处理。
通过实施特征工程,我们将使数据易于阅读,因此,我们的机器学习模型将提高其性能。
在建模之前,您可以使用特征缩放或标准规范化来准备数字数据,但当涉及到文本时,我们需要在自然语言处理(NLP)领域找到解决方案。让我们来看看帮助我们处理人类语言数据的流行的 NLP 库。
NLTK
NLTK 包含超过 50 个语料库和词汇资源以及文本处理库。这允许我们执行标记化、分类、词干提取、标记等等。
例如,一个句子有不同形式的单词(单数、复数)。我们可以使用 NLTK 的 WordNetLemmatizer 来获取每个单词的引理(又名一个单词的字典形式),并使文本统一。
让我们在下面的words
列表中找到单词的字典形式。
from nltk import WordNetLemmatizerlemmatizer = WordNetLemmatizer()
words = ['papers', 'friendship', 'parties', 'tables']for word in words:
print(lemmatizer.lemmatize(word))
词汇化中的默认词类(POS)值是一个名词,所以上一个例子的打印值将是paper
、friendship
、party
和table
。
空间
SpaCy 可以用于 NLTK 中描述的相同任务,但是它更快也更容易学习。
让我们看看命名实体识别(NER)如何与 spaCy 一起工作。
import spacynlp = spacy.load("en_core_web_sm")
doc = nlp("Messi will go to Paris next summer")
print([(X.text, X.label_) for X in doc.ents])
这将打印以下值
[('Messi', 'PERSON'), ('Paris', 'GPE'), ('next summer', 'DATE')]
Spacy 发现“梅西”是一个人,“巴黎”是 GPE(国家,城市,州等),而“明年夏天”是一个日期。
下面是从头开始学习这些库的指南:
- 用 Python 完成自然语言处理(NLP)指南
- 用 Python 可以轻松实现的 7 种 NLP 技术
- Python 中的 NLP 课程
用于模型构建和部署的 Python 库
一旦数据准备好进行处理,我们就应用不同的算法来获得最佳模型,调整模型以获得最佳结果,然后部署模型。这里有一个 Python 库的列表可以帮助你做到这一点。
sci kit-学习
Scikit-learn 是一个机器学习库,它允许我们训练和评估许多算法。它支持许多监督学习算法(线性回归,随机森林,SVM,决策树等)以及非监督学习算法。
让我们看看如何在 sklearn 中使用 LogisticRegression 来训练一个模型。
from sklearn.linear_model import LogisticRegressionlog_reg = LogisticRegression()
log_reg.fit(train_x_vector, train_y)
Keras/Tensorflow/Pytorch
说到深度学习,我们可以与 3 个库合作——Keras、Tensorflow 和 Pytorch。
TensorFlow 是 Google 开发的深度学习框架。它允许我们创建具有许多层的大规模神经网络。TensorFlow 的一些流行用例是语音/声音识别、基于文本的应用、图像识别、时间序列和视频检测。
Keras 是用 Python 编写的高级神经网络 API,它提供了深度神经网络的快速实验。它是用户友好的和可扩展的。2017 年整合到 tensor flow,但仍可独立运营。
最后,PyTorch 由脸书开发,用于 NLP 应用程序。
您可以查看这篇文章来深入比较这 3 个库。
瓶
Flask 是一个微框架,它提供了 web 应用程序的基本特性。尽管您不会以数据科学家的身份创建 web 应用程序,但您仍然需要围绕您构建的模型构建 web API。
之所以选择 Flask 而不是 Django 之类的其他 web 框架,是因为它更 Pythonic 化,更容易学习,并且更适合小型项目。
下面是从头开始学习这些库的指南:
- Scikit-Learn 简单指南——用 Python 构建机器学习模型
- TensorFlow 2.0 完整教程
- 带张量流航向的 Keras】
- 深度学习课程 py torch
我找不到专门介绍数据科学所需内容的 Flask 教程。如果你知道一个,请在评论区分享。
与 3k 以上的人一起加入我的电子邮件列表,获取我在所有教程中使用的 Python for Data Science 备忘单(免费 PDF)
如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑报名成为一名媒体成员。每月 5 美元,让您可以无限制地访问数以千计的 Python 指南和数据科学文章。如果你使用我的链接注册,我会赚一小笔佣金,不需要你额外付费。
https://frank-andrade.medium.com/membership
你所需要知道的关于熊猫切和 Qcut 函数
原文:https://towardsdatascience.com/all-you-need-to-know-about-pandas-cut-and-qcut-functions-4a0c1001c38b?source=collection_archive---------9-----------------------
它们之间到底有什么区别?
亚历克斯在 Unsplash 上的照片
Pandas 可以说是数据科学生态系统中最受欢迎的数据分析和操作工具。感谢众多的函数和方法,我们可以自由地处理数据。
在许多情况下,cut 和 qcut 函数非常方便。起初我并不清楚它们之间的区别。在做了几个例子之后,我就能弄明白了。
在本文中,我们也将这样做。本文中的例子将演示如何使用 cut 和 qcut 函数,并强调它们之间的区别。
让我们从创建一个样本数据框开始。
import numpy as np
import pandas as pddf = pd.DataFrame({
"col_a": np.random.randint(1, 50, size=50),
"col_b": np.random.randint(20, 100, size=50),
"col_c": np.random.random(size=50).round(2)
})df.head()
(图片由作者提供)
第一列和第二列分别包含 1-50 和 20–100 之间的整数。第三列包含 0 到 1 之间的浮点数。我们使用 numpy 函数来随机生成这些值。
剪切功能将整个取值范围划分为多个区间。每个箱覆盖的范围将是相同的。
在第一列(col_a)中,我们随机分配 1 到 50 之间的整数。让我们首先检查这一列中的最小值和最大值。
df.col_a.max(), df.col_a.min()(49, 3)
如果要将此列分成 5 个范围相等的容器,每个容器的大小将为 9.2,计算如下:
(49 - 3) / 5 = 9.2
cut 函数执行这种宁滨运算,然后将每个值分配到适当的 bin 中。
df["col_a_binned"] = pd.cut(df.col_a, bins=5)
df.col_a_binned.value_counts()(21.4, 30.6] 16
(39.8, 49.0] 14
(12.2, 21.4] 8
(30.6, 39.8] 6
(2.954, 12.2] 6
正如我们所看到的,除了最小的那个,每个箱子的大小正好是 9.2。下限不包含在内。因此,最小容器的下限稍微小于最小值(3)以能够包括它。
我们可以通过手动定义箱边缘来自定义箱。边值作为列表传递给 bin 参数。
pd.cut(df.col_a, bins=[0, 10, 40, 50]).value_counts()(10, 40] 33
(40, 50] 13
(0, 10] 4
默认情况下,右边缘是包含的,但可以更改。
pd.cut(df.col_a, bins=[0, 10, 40, 50], right=False).value_counts()[10, 40) 33
[40, 50) 13
[0, 10) 4
使用 cut 函数,我们无法控制每个容器中有多少值。我们只能指定箱边缘。
这就是我们需要学习 qcut 函数的地方。它可用于将值划分为多个桶,每个桶包含大约相同数量的值。
先说个例子。
pd.qcut(df.col_a, q=4).value_counts()(40.75, 49.0] 13
(19.5, 25.0] 13
(2.999, 19.5] 13
(25.0, 40.75] 11
我们有 4 个桶,每个桶包含几乎相同数量的值。在 4 的情况下,存储桶也称为四分位数。值总数的四分之一在第一个四分位数中,一半在前两个桶中,依此类推。
使用 qcut 功能,我们无法控制 bin 边缘。它们是自动计算的。假设一列中有 40 个值(即行),我们希望有 4 个存储桶。从最小值开始,第一个桶的上限范围将按照第一个桶包含 10 个值的方式来确定。
- 剪切功能:重点是根据值范围(即,容器上边缘和下边缘之间的差异)来确定容器的大小
- Qcut 函数:重点是根据每个箱中值的数量来确定箱的大小。
qcut 功能允许定制铲斗尺寸。让我们创建 3 个桶。第一个包含最小的 50%的值(即下半部分)。然后,我们把上半部分分成两个箱。
pd.qcut(df.col_a, q=[0, .50, .75, 1]).value_counts()(2.999, 25.0] 26
(40.75, 49.0] 13
(25.0, 40.75] 11
cut 和 qcut 功能都允许给箱子或桶贴标签。我们如下使用标签参数。
df["new"] = pd.qcut(df.col_a, q=[0, .33, .66, 1], labels=["small", "medium", "high"])df["new"].value_counts()high 17
small 17
medium 16
这就像把一个连续变量转换成一个范畴变量。让我们检查每个类别中的平均值,以确保 qcut 函数正常工作。
df.groupby("new").agg(avg=("col_a","mean")) avg
new
small 14.000000
medium 26.687500
high 43.705882
平均增加,因为我们从小到大,这是意料之中的。
结论
cut 和 qcut 函数都可以用于将一组连续值转换为离散或分类变量。
cut 函数关注于 bin 的取值范围。它根据最小值和最大值之间的差异确定整个范围。然后,它根据所需的箱数将整个范围划分为多个箱。默认情况下,每个箱的大小是相同的(大约),它是箱的上边缘和下边缘之间的差值。
qcut 函数关注每个 bin 中值的数量。这些值从最小到最大排序。如果我们需要 5 个桶,前 20%的值放在第一个桶中,后 20%放在第二个桶中,依此类推。
这两个功能都允许定制上边缘和下边缘。因此,我们可以有不同大小的箱子或桶。
感谢您的阅读。如果您有任何反馈,请告诉我。
关于 Python 字典,您需要知道的
原文:https://towardsdatascience.com/all-you-need-to-know-about-python-dictionaries-ccd05e5c61dd?source=collection_archive---------3-----------------------
它们是什么,何时使用它们,以及如何高效地使用它们!
本·怀特在 Unsplash 上的照片
介绍
成功地处理数据并编写可读和高性能的代码是我们努力的目标。实现这一目标的一个关键部分是为给定的问题选择理想的数据结构。数据结构是一种组织数据的特殊方式,以便可以有效地存储、检索或更新数据。
Python 自带各种内置的数据结构,例如列表、元组、集合、队列或字典等等。在本帖中,我们将看看词典。我试图涵盖从新手的基本用法到专业人士的高级主题的广泛范围。让我们看看我是否能兑现💪。
字典
让我们从一个简单的问题开始,这个问题很可能我们所有人都已经能回答了
什么是字典?
字典是具有唯一键的键值映射。相应的值可以是任何类型。在其他编程语言中,您可能会发现 map、hashmap、关联数组或查找表等术语都指代同一个概念。
那么,字典有什么用呢?它们适合通过键以快速和可读的方式访问元素,而不必搜索整个数据集。这意味着您可以同时获得性能提升和使用字典编写更可读的代码。现在,他们有什么属性?
字典是可变的,或者如果你想骄傲的话,是可变的😃。这意味着您可以随时更新、添加或删除键值对。
此外,由于 Python 3.7 字典保留插入顺序。也就是说,当你迭代一个字典的元素时,元素将按照它们被添加时的顺序被遍历。如果您使用 Python 3.6 或更早版本,我希望您不要这样做😃,你必须使用一个 OrderedDict 来保证你的字典的顺序。
在我们开始研究真正的代码之前,我想提到的最后一点是字典键必须是可散列的。你也经常读到键必须是不可变的,但那只是因为不可变类型也是可散列的。可以用作键的哈希类型的例子有数字、字符串或数字或字符串的元组。您不能用作键的可变类型是例如列表或字典。所以你不能用字典作为字典中的键😃。顺便提一下,如果你想使用某个类的实例作为键,你必须为那个类实现魔法函数 __hash__
。
好了,说够了,让我们把手弄脏,来有趣的部分;实码。
创建词典
我们需要知道的第一件事是我们如何能创造一本字典。Python 提供了各种方法来做到这一点,所以让我们看看
创建词典
创建词典有两种基本方法。首先,您可以使用花括号并向其中添加逗号分隔的key: value
对。其次,您可以使用dict
类并将键值对传递给构造函数。当您的键是字符串和适当的 Python 名称时,这很好。如果不是,你将不得不传递一个形式为(key, value)
的元组的 iterable 到dict
。这实际上是在编写第 6 行所示的dict(zip(keys, values))
时以一种非常紧凑的方式得到的。
创建字典的另一种方法是将多个字典结合起来。你怎么能这样做?你可以通过用**
操作符解包字典,然后用花括号把它们组合起来,见第 9 行。Python 3.9 中引入的另一种方法是使用|
操作符来连接字典,如第 10 行所示。
如果组合字典有公共键,将使用最后添加的那个值。但是,第一个添加的将决定插入顺序。在给定的例子中,这意味着combined
的第一个键值对是python: 10
。听起来很疯狂,不是吗?我只能建议玩简单的玩具例子,并熟悉这些细节。
最后,我想简单提一下字典理解,如第 14 行所示。您可能已经熟悉了列表理解来创建列表,这与创建字典是一样的。因为这个概念应该是相当众所周知的,所以我只给你一个例子。
从字典中阅读
既然我们现在知道如何创建字典,我们应该开始利用它们存储的数据。同样,让我们从一些代码开始
从字典中读取数据
获取条目最常见的方式是使用第 1 行所示的键在字典中建立索引。这种方法的一个问题是,如果一个键不在字典中,就会引发一个KeyError
异常。为了避免这种情况,您可以使用字典的get
方法,如第 2 行所示。此方法或者返回与键关联的值,或者如果找不到键,则返回默认值。如果不指定默认值,它将返回None
。
为了不仅处理单个键值对,而且处理整个数据,字典提供了不同的方法来访问所有条目。在第 3 行,您可以看到如何使用items()
方法迭代所有的键值对。
您还可以迭代字典本身。在这样做的时候,您迭代这些键,如第 7 行所示。另一种迭代或获取所有键的方法是使用a_dict.keys()
。
最后,如果您只对值感兴趣而对键不感兴趣,您可以使用a_dict.values()
来获得它们。在第 10 行,你可以看到一个例子,我们计算字典中所有语言的平均等级。
更新词典
正如开头所说,字典是可变的。这意味着我们可以添加、删除或更新字典的条目。让我们看看 Python 为此提供了什么
如第 2 行所示的setdefault
函数可能是 dicts 公开的最令人困惑的命令😕。那么它是做什么的,有什么帮助呢?如果在字典中没有找到给定的键,setdefault
将带有给定默认值的键添加到字典中,并返回该值。这意味着它更新了字典。如果键存在,它将返回相应的值。尽管函数的名字令人困惑,但它可以帮助您用更少的if-else
语句编写更少的代码。使用这种方法的另一种方法是使用集合模块中的[defaultdict](https://docs.python.org/3/library/collections.html#collections.defaultdict)
。
现在,要更新或添加条目,我们可以使用索引操作并赋值,如第 3 行所示。如果我们想要添加或更新多个条目,我们可以使用第 4 行所示的update
方法。或者,从 Python 3.9 开始,我们可以使用|=
操作符,如第 5 行所示。在这两种情况下,我们都必须将要添加或更新的键值对放入另一个字典中,并将其传递给方法或操作符的左侧。
最后,要从我们的字典中删除条目,我们有两个方法,即popitem
和pop
。Popitem 移除最后插入的项,并以元组的形式返回相应的键值对。与此相反,pop
删除给定键的键值对,并返回相应的值。如果不指定默认值,当找不到键时,pop
会引发一个KeyError
。如果指定了默认值,则在键不存在的情况下将返回该值。popitem
和pop
都修改调用它们的字典。
最后,还可以使用del
删除项目。但是,我不喜欢这个语法,故意把它留在这里。抱歉,我不得不固执己见😃
使用字典键入注释
我喜欢现代 Python 的一点是类型注释。类型注释极大地帮助我们理解代码和接口。此外,它们提高了我们的编码速度,因为我们的 ide 在自动完成时会用到它们。最后,当使用像 mypy 这样的类型检查器时,您可能会在投入生产之前就发现错误。
因为我们没有讨论类型注释的细节,所以让我们继续讨论如何对我们的字典进行类型注释。您可能已经猜到了,我们从一些代码开始
我在这里做了什么?首先,我创建了一个接受字典作为输入并返回字典的函数。要进行类型注释,您可以使用来自类型模块的Dict
,或者从 Python 3.9 开始,您可以与dict
交换以节省一次导入。现在,必须将键的类型指定为第一个参数,将值的类型指定为第二个参数。就是这样。很简单,不是吗?我希望你们都同意,这个界面比随便输入名字更容易理解。
关于类型注释,我想介绍的最后一点是所谓的类型注释。当你预先知道你的键的名字和类型时,你可以使用 TypeDict。为此,您必须编写一个从 TypedDict 继承的类,并将键定义为属性,并用相应值的类型对它们进行类型注释。然而,在我看来,它们的用途相当有限,在许多情况下,您可以使用功能更丰富的数据类或命名的元组。
词典的替代用法
在结束这篇文章之前,我想谈谈我们如何使用字典不仅保存数据,而且提高代码库的可读性。为了说明这一点,我给你们看两个突出的例子。
首先,有了字典,我们可以替换某些 if-else 语句,使我们的代码不那么冗长,更整洁。这是怎么回事?我们来看一些代码!
在给定的示例中,我们希望构建一个函数来从三个不同的数据仓库加载数据。对于每个仓库,我们都有一个专门的功能来完成这项工作。因此,根据定义的仓库名称,目标是选择三个函数中的一个。一种简单的方法是使用一些 if 子句来检查仓库名称,以使用正确的函数。这显示在功能load_data_verbose
中。
或者,我们可以定义一个字典,将仓库名称映射到相应的函数。现在,我们所要做的就是使用仓库名称从字典中获取函数,如load_data.
所示,这是一个更好的接口,也更容易扩展到更多的仓库。如果必须添加一个新的,我们只需编写加载函数并更新字典。完成了。
我想提到的第二个也是最后一个例子是,我们可以在调用函数时使用字典来指定关键字参数。以上面的例子为例,我们可以定义一个字典call_args={"data_base":"snowflake", "from_": datetime.utcnow()}
,并使用它来调用load_data
函数,就像data = load_data(**call_args)
。例如,当您想要有条件地覆盖关键字参数的默认值时,这种语法会非常方便。
大概就是这样。咳,那篇文章比我最初想象的要长得多😃会的。
照片由悉尼·瑞伊在 Unsplash 上拍摄
包裹
在这篇文章中,我们讨论了什么是 Python 字典以及如何有效地使用它们。我的目标是为新手和专业人士提供见解。我希望我已经做到了这一点,并且您现在已经掌握了新的知识,能够编写更棒的代码,并交付您的下一个数据项目。
感谢您关注这篇文章。一如既往,如有任何问题、意见或建议,请随时联系我或关注我,无论是在这里还是通过 LinkedIn 。
在 PyTorch 建立您的第一个网络
原文:https://towardsdatascience.com/all-you-need-to-know-about-pytorch-a0ba3af897fa?source=collection_archive---------16-----------------------
启动你深度学习生涯的总结。
在 Unsplash 上由 Max Duzij 拍照
开始一个深度学习项目,听起来很吓人,很难?我已经通读了关于神经网络的文章,上过课,看过视频,但是我如何开始编程呢?我们都经历过那个阶段,这就是为什么我写这篇文章来告诉你开始 PyTorch 模型训练项目的一切(或者至少是我知道的大部分事情)。
指南以自下而上的方式呈现。我将首先描述对训练深度网络很重要的各个组件,然后提供如何将所有组件组合在一起进行训练和测试的示例。
边注:
文章是将 ML 中的理论知识直接转化为代码的桥梁。假设有先验的 ML 知识。
我的项目主要在计算机视觉领域,所以我发现 PyTorch 中最有用的功能也偏向于图像方面的应用。
目录
目录
导入
网络组件
∘ 全连通层
∘ 卷积族
∘ 递归网络
∘ 激活功能
结合一切
∘ 导入 PyTorch
∘ 创建网络
∘ 创建数据集和数据加载器
∘ 初始化网络、优化器和调度器
∘ 培训、评估和保存
导入
PyTorch 有很多相关的库,这里我列出了执行下面所有操作的基本库:
**import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data
from torch.utils.data import Dataset, DataLoader
import torchvision**
所有的代码将基于上述的进口,所以请注意所有的名称别名由' as '创建。
网络组件
让我们从 PyTorch 中训练网络的最重要的方面开始,设计网络本身。深度网络可以由各种类型的层组成,这里我列出了一些最常用的层类型。
完全连接的层
这是最传统的神经网络的主要组成部分,也在今天的大多数模型中使用。它可以通过以下方式创建:
**nn.Linear(input_size, output_size, ...)**
**输入 _ 大小和输出 _ 大小本质上是进出该层的通道数量。
卷积家族
回旋
围绕计算机视觉/图像的任务通常由卷积神经网络(CNN)处理。与正常的全连接层不同,CNN 由卷积构建,卷积可以通过以下方式创建:
**nn.Conv2D(input_size, output_size, kernel, stride, padding, ...)
nn.ConvTranspose2D(input_size, output_size, kernel, stride, ...)**
nn。Conv2D() 本质上是一个 2D 卷积,带有创建它所需的参数(例如,输入和输出通道大小、内核、步幅、填充)。PyTorch 还提供 1D 和 3D 卷积,具体取决于您查看的是一维数据还是 3D 表示。
要执行反卷积(主要用于网络的解码阶段),请使用 nn。ConvTranspose2D() 。通过简单地将 2D 改变为 1D 或 3D,再次支持一至三维。
联营
卷积通常与池化图层成对出现,以改变输出要素地图的大小。最常用的汇集方法包括:
**nn.MaxPool2d(kernel_size, stride, padding, ...)
nn.AvgPool2d(kernel_size, stride, padding, ...)**
指的是最大和平均池。如果你很懒于计算,只想得到一个目标尺寸,你也可以选择:
**nn.AdaptiveAvgPool2d(output_size)**
这将自动确定应如何进行池化,以便以您想要的大小输出要素。
批量标准化
想要执行批量标准化吗?PyTorch 也为你解决了:
**nn.BatchNorm2d(num_features, ......)**
你可以在卷积层之后直接应用它
循环网络
如果你更喜欢自然语言处理或时间序列数据分析,你可能会遇到比 CNN 更多的递归网络。以下是 PyTorch 支持的更著名的循环网络类型列表:
**nn.RNN(...)
nn.GRU(...)
nn.LSTM(...)**
你可以关注一些详细的博客。有大量的变化(单向或双向),有大量的在线资源供你研究。
激活功能
对于要学习的网络,你需要在每一层之后应用激活函数。一些常用的激活,如 sigmoid、ReLU 或 LeakyReLU,可通过以下方式创建:
**nn.Sigmoid()
nn.ReLU()
nn.LeakyReLU()**
请注意,sigmoid 函数存在梯度消失的问题,因此它通常用于最终输出图层,以在 0 和 1 之间进行预测,而在其他地方则不进行预测。LeakyReLU 通常性能更好,但也比计算 ReLU 慢。
同样重要的是不要将两个激活函数堆叠在一起。这将使你的网络几乎无法学习,你将花费大量时间调试它!
损失函数
一些最常用的损失(例如,MSE 损失、二元交叉熵、kl 散度)可通过以下方法计算:
**nn.MSELoss()
nn.BCELoss()
nn.KLDivLoss()**
乐观主义者
为了配合损失函数,下面是 PyTorch 提供的几种最广泛使用的优化器:
**optim.Adam(model.parameters, lr, ...)
optim.SGD(model.parameters, lr, momentum, ...)**
你可能还需要一个学习率计划程序,当你的训练似乎达到平稳状态时,学习率会降低。这可以通过以下方式实现:
**optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode, patience, ...)**
设置 GPU
深度模型计算量很大。非常贵。如果你有 GPU,建议对他们进行培训。有几种方法可以使用 PyTorch 将你的网络、张量和其他东西放到 GPU 上:
**# 1
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
tensor = tensor.to(device)# 2
tensor = tensor.cuda()**
更明智的方法是第一种方法,因为第二种方法假设 GPU 可用,并且在没有 GPU 的设备上中断。
当您有多个 GPU 时,您也可以使用:
**network = nn.DataParallel(network).cuda()**
将网络分布到多个 GPU 上进行并行计算。
结合一切
每个模型都是不同的,但在如何创建和训练它们方面,它们或多或少都有相似的结构。以下是整个过程的大致轮廓:
进口 PyTorch
创建网络
这是您收集所有网络组件来编写模型的部分。将输入输入网络时,您需要初始化所需的一切:
创建数据集和数据加载器
我们必须处理数据,这样我们就可以迭代地从数据集中获取批量数据,并将其输入神经网络:
初始化网络、优化器和调度器
培训、评估和储蓄
就在那里!模型可以变化,训练方法可以不同,可视化可以应用,损失可以是许多奇怪组件的组合,但最终它将基于这样一个简单的主干。关于实际网络的例子,请随意在这里或者在这里 找到 。
预训练模型
如果您想使用一些成熟的架构,而不是设计自己的架构,PyTorch 也能满足您的要求:
**torchvision.models.resnet50(pretrained=True)**
预训练权重将加载到您的模型中,您可以继续在自己的数据集上对其进行微调。
其他有趣的 PyTorch 函数
以下是我在深入学习的过程中发现的一些有用的功能:
**torch.ge(input, constant)**
如果值>常数,则将整个输入张量转换为 1,否则转换为 0。适用于计算交集和并集之类的东西。
**torch.topk(input, k)**
从输入张量中查找前 k 个值。输出将是前 k 个值及其相应索引的元组。
**torch.stack(list)**
将长度为 n 的张量列表转换为大小为 n 的张量。
结束注释
所以你有它。关于如何开始你的第一个深度学习项目的简单、全面的指南。希望这有所帮助,你的网络工作!
感谢您坚持到现在🙏! 我会在计算机视觉/深度学习的不同领域发布更多内容,所以 加入并订阅 如果你有兴趣了解更多!
你需要知道的关于 Seaborn 的一切
原文:https://towardsdatascience.com/all-you-need-to-know-about-seaborn-6678a02f31ff?source=collection_archive---------11-----------------------
python-可视化-教程
什么时候应该用 Seaborn vs matplotlib,怎么用?
由唐纳德·詹纳蒂在 Unsplash 上拍摄的照片
这是我的 python 可视化系列的最后一个教程:
- 教程一:Fig 和 Ax 对象
- 教程二:线图、图例、颜色
- 教程三:箱线图、条形图、散点图、直方图、热图、色彩图
- 教程四:小提琴剧情,树状图
- 教程 Seaborn 中的图(聚类热图、对图、距离图等)
你不需要阅读所有以前的文章,这篇文章与我的前四篇文章有点不同。我将向您展示 python 中 matplotlib 库和 Seaborn 库的直接比较。
正如我在我的教程 I 中提到的,我特意使用最底层的可视化库——matplotlib 来演示如何获得完全的控制并理解每种绘图类型中的每个元素。如果你有机会阅读我以前的文章,我希望它确实有助于你实现这个目标(如果没有,请不要犹豫,让我知道,我可以发布额外的教程)。与 matplotlib 相反,Seaborn 是一个高级接口,通过减轻痛苦和将我们从编写大量样板代码中解放出来,它将使我们的生活变得更加容易。这是一个很棒的包,在这篇文章中,我将提供有用的指导,告诉你什么时候应该使用 Seaborn,更重要的是,我将使用具体的例子来引导你完成使用 Seaborn 的过程。
我应该什么时候使用 Seaborn?
我制作了一个包含所有 Seaborn 支持的地块类型的表格:
所有 Seaborn 支持的地块类型
所有我标记为“难以在 matplotlib 中绘制”的绘图类型,例如,我们刚刚在教程四:小提琴绘图和树状图中提到的小提琴绘图,使用 Seaborn 将是缩短绘图时间的明智选择。我概述了一些指导如下:
- 对于"matplotlib中易于绘制的"类型,您可以使用任何一种工具,并且在时间和复杂性方面不会有太大差异。(如果你不知道如何在 matplotlib 中做到这一点,请查看我以前的帖子)
- 对于"难以在 matplotlib 中绘制的类型,我建议在实践中使用 Seaborn,但我也建议至少理解如何从头开始绘制这些图。
- 对于所有图形类型,如果涉及多个类别,Seaborn 将是一个更好的选择,例如,您需要绘制一个并排的盒子图或小提琴图。
接下来,我将向您展示如何在那些“难以在 matplotlib 中绘图”的场景下使用 Seaborn。有一件事是我们将很快涉及的其他情节的基础,那就是, Seaborn 是为熊猫数据帧设计的。因此,作为一个安全的赌注和良好的做法,请始终表示您的数据作为一个熊猫数据框架。
长格式和宽格式数据帧
为了理解什么是长格式和宽格式数据框,我准备了两个数据集,我们将在以下示例中使用。
第一个是penguin
数据集,它是一个长格式的数据帧:
Penguin,长格式数据帧
在我向您展示什么是宽格式数据帧之后,将会更清楚为什么它被称为长格式数据帧:
我创建了一个名为synthesis
的合成数据集,它是一个宽格式的数据框:
合成:一种宽格式的数据帧
一个宽幅数据帧synthesis
只包含三列全数值,每列对应一个类别,名称显示为列名var1
、var2
、var3
。让我们使用以下代码将其转换为长格式的数据帧:
synthesis.stack().reset_index(-1)
合成:转换为长格式
正如您所看到的,现在我们堆叠了这个数据框,并以某种方式压缩了它的宽度,迫使它成为一个更长的格式,每个类别现在都按顺序列在第 1 列中,与其相关值的对应关系没有改变。简而言之, **long-formatted**
数据框和 **wide-formatted**
数据框只是包含不同类别数据的数据框的两种不同视图。
这两个概念将帮助我们理解 Seaborn 包的逻辑和不同行为。
分布图
我们使用示例来演示不同的分布图,参见下面的代码:
fig,ax = plt.subplots()
sns.histplot(data=penguin, # the long-formatted data frame
kde=True, # draw kernel density estimation line as well
stat='frequency', # the y-axis is the frequency
x='bill_length_mm', # the column of dataframe we want to visualize
hue='species', # the categorical column
multiple='layer', # how to lay out different categories's data
kde_kws={'bw_adjust':5}, # adjust the smoothness of kde curve
line_kws={'linewidth':7}, #adjust the aesthetic element of kde curve
palette='Set2', # choose color map
ax=ax). # the ax object we want to draw on
代码应该是自解释的,除非有两个点,stat
和bw_adjust
,但是让我们先看看效果:
长格式分布图
stat
接受四个关键词:
count
:每个箱子的数量
frequency
:每个箱子的数量除以每个箱子的宽度
density
:总和(每个箱的密度*每个箱的宽度)= 1
probability
: sum(每个箱的概率,或高度)= 1
然后bw_adjust
参数调整 kde 曲线的平滑程度,这里我们将它设置为一个大值,所以它应该非常平滑。你可以把它改成 0.2,看它怎么变。
让我们看另一个宽格式的例子。
fig,ax = plt.subplots()
sns.histplot(data=synthesis, # wide format data
kde=True,
stat='density',
common_norm=False, # sum of all category is equal tot 1 or each category
hue_order=['var2','var1','var3'], # the order to map category to colormap
multiple='layer',
ax=ax)
先看效果:
宽格式(合成数据集) :分布图
这里,我们将stat
设置为density
,这意味着所有面元的总和*面元宽度将为 1。然而,现在我们有了多个类别,你的意思是三条曲线下的所有面积总和都是 1 还是每个类别会计算它们自己的密度?这种混淆是通过common_norm
论证进行的,True
表示前一种情况,False
表示后一种情况。
宽格式的区别在于,这里我们没有单独的一栏作为 **hue**
,而是将每一栏自动识别为一个类别。在这种情况下,您甚至不需要指定 **x**
参数,而只需要输入整个宽格式数据帧。
如果你只想画 kde 曲线呢,简单!
sns.kdeplot(data=penguin,
x='bill_length_mm',
hue='species',
clip=(35,100)). # the range within which curve will be displayed
KDE 图
这里,clip
参数是控制 KDE 曲线显示的范围,换句话说,超出这个范围的 KDE 曲线不会在这里显示。这在某些情况下是有用的,例如,你知道你绘制的x
变量具有非负属性,所以你想只关注正分支,而clip
参数将是实现这一点的便利工具。
最后,如果您想将地毯添加到分布图中,只需使用rugplot
功能:
sns.rugplot(data=penguin,x='bill_length_mm',hue='species')
x 轴的 KDE 曲线加地毯
你看,只要你理解了数据帧的长而宽的格式,所有的 Seaborn 情节就变得非常好理解了。
分类图
一个带状图是与每个类别相关联的所有数据点将并排显示,请在此处查看示例:
虫群图更进一步,它保证那些点不会互相重叠,参见这里:
让我们用penguin
数据集画一个蜂群图:
sns.swarmplot(data=penguin,x='species',y='bill_length_mm',hue='sex',dodge=True)
群体图
dodge
表示不同的hue
会被分离出来,而不是聚在一起。尽管如此,只要你理解 Seaborn 如何画作品的哲学,所有的情节类型都是相互联系的,对吗?
再来一个,就是小提琴剧情,你还记得我们在教程四:小提琴剧情和树状图里从零开始画小提琴剧情有多辛苦吗?现在让我们看看在 Seaborn 会有多容易。
sns.violinplot(data=penguin,
x='species',
y='bill_length_mm',
hue='sex',
split=True, # will split different hues on different side of categories
bw=0.2, # the smoothness of violin body
inner='quartile', # show the quartile lines
scale_hue=True, # scale arcross each hue instead of all violins
scale='count'). # scale the width of each violin
我们来看看效果:
小提琴情节
对论点的解释:
scale
:它接受三个值:
area
:默认情况下,每把小提琴都有相同的面积
count
:小提琴的宽度将根据每个类别的观察结果进行缩放
width
:每把小提琴都有相同的宽度
对于scale_hue
,这意味着上述缩放是在图中的所有小提琴上执行还是仅在每个hue
组中的小提琴上执行。
inner
接受几个值,如果quartile
,它会显示所有的四分线,如果box
,它会像我们在 matplotlib violin plot 中所做的那样显示四分线框。如果point
或stick
,基本上显示所有的点。
最后,我们一起再看一个例子,point plot
。点阵图有助于可视化不同类别的点估计和置信区间变化,连接每个点估计的线条将使可解释变量x
对响应变量y
的影响变得更加清晰。
sns.pointplot(data=penguin,x='species',y='bill_length_mm',hue='sex')
点图
我将把boxenplot
留给您自己探索,但它只是 boxplot 的增强版本,在某种意义上,它不仅会显示 25、50 和 75 四分位数,还会显示一些额外的四分位数,因此它可以为复杂的数据数组提供更丰富的信息。
回归图
在这里,我想引起您的注意,与其他图不同,回归图非常容易绘制,但我建议您了解实际情况。换句话说,这些回归线是如何从数据中得出的,每个参数将如何影响最终的绘图?
sns.regplot(data=penguin,x='bill_length_mm',y='bill_depth_mm')
回归图
简而言之,您可以将这一过程描绘成我们计算每个x
位置的平均值,然后我们或者通过自举估计置信区间,或者将标准差(sd)输出为图表上显示的半透明带。但是还有一些额外的参数,如logistic
、lowess
、logx
、robust
等,将有一个底层的统计模型函数来执行每个回归推导。只要记住这一点,并确保你能描述回归线是如何得出的,就是这样。
热图
嗯,你很快就会发现 Seaborn 的 Heatmap 有多方便,让我们看看:
sns.heatmap(data=synthesis.iloc[0:5,:],
annot=True, # superimpose the text
linewidths=0.5, # add grid line
square=True,
yticklabels=False)
热图
我最喜欢的参数是annot
和linewidth
,如果你还记得我们在教程三:热图中是如何制作热图的,那是一个非常痛苦的过程,现在只是一键操作,超级爽!!
另一个方便的参数是mask
,它允许你任意屏蔽掉任何你不需要或不想看到的方块。让我们首先定义一个掩码,记住,掩码矩阵与数据矩阵具有相同的维数,并且您想要掩码的位置将接收真值或 1 值。
mask = np.array([[0,0,0],
[0,0,0],
[0,1,0],
[0,0,0],
[0,0,0]])
那我们来策划一下:
sns.heatmap(data=synthesis.iloc[0:5,:],annot=True,linewidths=0.5,square=True,yticklabels=False,mask=mask)
带遮罩的热图
你绝对想在 Seaborn 尝试的三个情节
- 集群热图
- 配对图
- 联合地块
如果你认为 Seaborn 在上面的图中只是给你带来了适度的方便,在这三个例子中,如果没有 Seaborn 的方便界面,你可能要花几个小时来绘制它们。
让我们从集群热图开始:
sns.clustermap(data=synthesis)
集群热图
真正发生的事情比这一行代码要复杂得多,你必须进行分层聚类,然后你基本上需要绘制一个热图,对其进行注释,然后绘制树状图(你刚刚在教程四:树状图中提到过),想象一下这有多复杂。
这可以说是我在 Seaborn 中最喜欢的功能,非常感谢开发者!
接下来我将介绍另一个很酷的功能,它可以添加任意数量的行颜色条和列颜色条,我将演示如何添加两层行颜色条。
row_cb = pd.DataFrame(data=np.random.choice(['r','g','b','m'],(100,2)),
index=np.arange(100),
columns=['hey','ha'])
我基本上创建了一个数据框,该数据框的每一行对应于主热图中的一行,该数据框的两列包含您想要分配给每个样本的颜色。然后我们可以将行颜色条添加到主热图中。
sns.clustermap(data=synthesis,row_colors=row_cb)
带有行颜色条的聚类热图
做得非常好!!!
让我们进入下一个激动人心的剧情功能,pairplot
。
sns.pairplot(data=penguin.iloc[:,[2,3,4,5]],dropna=True)
让我们只使用属于数值的四列penguin
数据集,并且我们删除数据集中具有 NAN 的观察值。
配对图
您可以在函数中更改对角线绘图种类和非对角线绘图类型,但我将留给您探索。只需查看其文档。
最后但同样重要的是,我们有jointplot
。
sns.jointplot(data=penguin,
x='bill_length_mm',
y='bill_depth_mm',
kind='scatter')
联合绘图(默认类型)
你也可以在上面加上回归线和 KDE 曲线,
sns.jointplot(data=penguin,
x='bill_length_mm',
y='bill_depth_mm',
kind='reg')
只要把kind
改成reg
,就大功告成了!
联合图(带回归和 KDE 曲线)
最后的评论
这就把我们带到了本教程的结尾,我们从使用 matplotlib 进行繁琐枯燥的底层编码开始,也体验了 Seaborn 能给我们带来什么样的刺激。但我敢打赌,如果没有一开始的痛苦,我们就无法感受到最后的快乐。回到我最初的愿望,我试图分享我如何用 python 制作出版物质量的数字。制作出版物质量的数字的关键是(a)简洁,(b)有一个体面的前景。此外,您应该能够随意调整图上的任何元素。**我喜欢一个比喻,说绘制出版物质量的数字就像在一张完全空白的草稿纸上绘图,**这就是为什么我在我的教程中开始向你展示如何理解你的画布,然后一路向下到每个特定的情节类型。我希望它在某些方面是有用的,请不要犹豫问我问题。
如果你喜欢这些教程,请在 medium 上关注我,非常感谢你的支持。在我的 Twitter 或 LinkedIn 上联系我,也请问我你想学习哪种图形以及如何简洁地画出它们,我会回复!
所有的代码都可以在https://github.com/frankligy/python_visualization_tutorial获得
构建您的第一个闪亮应用程序所需要知道的一切
原文:https://towardsdatascience.com/all-you-need-to-know-to-build-your-first-shiny-app-653603fd80d9?source=collection_archive---------14-----------------------
涵盖了从数据准备到连接用户界面和服务器再到在线发布应用程序的基本概念
斯蒂芬·道森在 Unsplash拍摄的照片
hiny 是数据分析师和数据科学家手中开发基于 web 的应用程序和交互式数据可视化的强大工具之一。闪亮的应用程序包含两个重要的功能:UI 和服务器功能。Shiny 的一个关键特性是使用反应式编程,在输入发生变化时自动更新输出。
我们使用联合国粮食及农业组织(FAO)的数据集来获得从头构建一个闪亮应用程序的实践经验(应用程序的链接)。本文分为以下几个部分:
- Shiny 概述:了解 Shiny 的工作原理和不同的可用选项
- 数据准备:准备应用程序要使用的数据
- 编写 UI 代码
- 连接到服务器
- 运行和发布应用程序
闪亮的概览
RStudio 开发的 Shiny 是一个同名的包。闪亮的框架由 CSS、HTML 和 Java 组成。这给了它添加功能的自由。在闪亮服务器的帮助下,这些应用程序托管在 shinyapps.io 上。
让我们从闪亮的 RStudio 画廊看一些例子来获得动力。Shiny 还为用户提供演示、布局和小部件。这也有助于确定它们的工作原理,并为您自己的应用选择它们。
所以让我们开始吧…
要开始构建应用程序,我们可以打开一个新的闪亮的 Web 应用程序文档,如下图所示。这将弹出一个新窗口,提示您选择应用程序名称、应用程序类型(选择单个文件选项),并设置工作目录。这将打开一个名为 app.R 的文件。该文件有一个默认代码为“老忠实喷泉数据”应用程序。
作者图片
另一个选择是打开一个新的 R 脚本(Windows 的 Ctrl+Shift+N ),并以 app 的名称保存它。R ( 这很重要)在选择的文件夹中。然后只需在编辑器中键入shinyapp
,这将打印出应用程序的框架,如下图所示。
作者图片
此时,我们将使用命令install.packages(“shiny”)
确保我们已经在 over 设备上安装了闪亮的包。
运行shinyapp
命令后,我们看到编辑器上显示了 4 个内容。
- 它通过调用
library(shiny)
来加载闪亮的包。 - UI 是用户界面,它决定了用户如何与 HTML 网页交互。
- 服务器是应用程序的后端,UI 端的所有交互都在这里实现,它们的结果被发送回 UI 进行显示。
shinyapp
功能是构建 app。
在深入研究 UI 和服务器提供的功能细节之前,让我们来设计一下用户界面的布局。一旦解决了这个问题,构建我们的应用程序将会更加直观。
作者图片
现在我们可以看看 UI 和服务器提供的功能。
用户界面控件
这部分将处理用户在面板上可以访问的不同输入和输出控件。面板的宽度为 12。我们可以定义我们选择的布局,并相应地定制它。实现这一目标的关键功能是:
【fluid page():确保应用自动调整以填充浏览器空间。
titlePanel() :这应该是默认情况下在代码中标识应用程序将做什么。
sidebarLayout()
需要的其他功能是sidebarPanel()
和mainPanel()
。与在面板上向与侧边栏相关的最终用户显示功能相关的所有代码都将在sidebarPanel()
中,而对于主面板,则在mainPanel()
函数中。
ui <- fluidPage(
titlePanel("My first App"),
sidebarLayout(
sidebarPanel("Sidebar panel"),
mainPanel("Main panel")
)
)
作者图片
fluidRow() :另一种方式可以是将面板分成多行。并且这些行中的每一行都可以有多列。通过多次使用fluidRow()
函数实现多行,在fluidRow()
函数中,我们可以使用column()
定义列。
ui <- fluidPage(
titlePanel("My first App"),
fluidRow(
titlePanel("Row 1"),
column(4,"Column 1"),
column(4,"Column 2"),
column(4,"Column 3")
),
fluidRow(
titlePanel("Row 2"),
column(6,"Column 1"),
column(6,"Column 2")
)
)
作者图片
现在我们知道如何建立骨架,我们可以开始填充前端的空白空间。前端处理 Shiny 应用程序提供的输入和输出。
输入部件
用户界面中的输入部件可以是文本、数字或日期,可以使用文本字段、滑块输入、单选按钮、复选框等输入。所有输入函数都有相同的第一个参数,即标识字段。
这个分配的 id 对于函数应该是唯一的,并且应该是仅由字母、数字和分数组成的单个字符串。
第二个参数是标签,它是用户理解要执行的操作的标识符。这个参数存在于大多数输入函数中。其他参数更具体地针对输入函数类型,最好的方法是浏览它们的文档或直观地查看。
输出
像输入函数或输入小部件这样的输出函数有一个惟一的标识符作为它们的第一个参数。输出可以是图表、数据表、文本或总结的形式。
计算机网络服务器
服务器功能是你的应用程序的大脑,所有的决定都在这里做出,并反映到用户界面上。
现在我们已经有了用 Shiny 构建一个应用程序所需的所有基础知识和细节,所以让我们开始吧。
数据集和包
为了构建应用程序,我们将使用粮农组织提供的粮食损失和浪费数据库。到数据集的链接在这里是。数据由 18k 多行和 22 列组成。
我们将使用shiny
包来构建应用程序,readxl
包用于读取 CSV 文件,plotly
包用于交互式数据可视化,tidyverse
包用于所有数据操作,ggplot2
包用于绘图。
数据准备
在开始开发 app 之前,需要准备好资料。在目前的研究中,我们将在一定程度上复制粮农组织开发的应用程序。在本练习中,我们将获取两个输入,并以图表和数据表的形式生成两个输出。
安装相关软件包后,使用read_csv()
功能读取 CSV 文件,同时用 NA 值替换所有空单元格。为了简单起见,删除了一些不必要的列。因为我们对粮食损失如何随时间变化感兴趣,所以为了简单起见,带有年份数据的列被重命名为 year 。
接下来,变量 supplychain 已被定义,并被赋予我们感兴趣的参数。仅绘制相对于 fsc_location1 的百分比损失数据就显示了一个收割的错别字,该错别字随后被纠正。
使用filter()
函数后,定义了一个新变量 food_new 。由于我们只关心供应链变量中的参数,我们将数据过滤到新创建的变量中。
定义了一个名为换行符的函数,以避免稍后在 UI 中重复使用换行符。定义了一个名为复选框的新变量,包含使用checkboxGroupInput()
功能可获得的所有选项。
编写 UI 代码
我们的目标是让用户界面带有侧边栏,主面板带有两个选项卡。我们将从fluidPage()
函数开始,并在其中构建所有东西。有三个主要步骤:
- 使用
titlePanel()
功能向应用程序提供航向。 - 定义
sidebarLayout()
功能,定义其主体部分由sidebarPanel()
和mainPanel()
组成。 - 在
mainPanel()
函数中,我们使用tabsetPanel()
中的tabPanel()
函数定义标签。
一旦创建了框架,我们就可以开始填充细节了。我们从侧边栏面板开始,用户将在那里与数据进行交互。考虑的两种不同的交互方式是(1)滑块输入和(2)复选框。对于滑块输入,我们将使用带有 id = "year" ,*label = " Select year range "*的sliderInput()
函数,设置所考虑年份的最小值和最大值以及默认年份范围。从复选框中选择选项时,将使用checkboxGroupInput()
功能。此函数有一个标识符, id="valuechain" ,label = " Select value chain ", check_box 变量,所有选项都显示给用户,默认选择值为“all”。
我们现在转到mainPanel()
功能。在tabsetPanel()
函数中,我们设置 type="tabs" 在用户界面的布局上有标签。接下来,我们定义两个tabPanel()
来表示两个不同的选项卡。将名称分配给选项卡作为第一个参数,在我们的例子中,它们是*“盒图”和“数据表”*。
一旦定义了输入函数,我们就开始输出函数。第一个选项卡将显示使用 plotlyOutput()
功能的交互图,第二个选项卡将显示使用dataTableOutput()
功能的数据表,这些功能生成具有内置搜索功能的动态表。像输入函数一样,输出函数的第一个参数是标识符。对于图形和表格输出,标识符值分别设置为*“box _ plot”和“food data”*。
连接到服务器
完成 UI 代码后,我们将使用 UI 的各种输入和输出函数中定义的标识符将 UI 连接到服务器。服务器函数有三个参数:输入、输出和会话。我们将只处理输入和输出参数。
session 参数确保每次在网络上打开应用程序时,它都会启动一个新的会话。这样,一个用户所做的更改不会反映到另一个用户的会话中。
服务器中定义了两种不同的函数:反应函数和渲染函数。我们将逐一查看它们,看看这些函数是如何与 UI 通信的。
我们将reactive()
功能留到最后,先讨论渲染功能。在 UI 中,我们为每个输入和输出函数定义了标识符。在这里,我们将使用信息流的标识符来连接 UI 和服务器。
查看盒图,我们看到输出$box_plot 变量被分配给renderPlotly()
函数。需要注意的重要一点是,输出$box_plot 借助于 box_plot 标识符连接到 UI 中的plotlyOutput()
功能。UI 中的每个输出功能都与服务器中的一个render()
功能相关联。在该应用中,UI 中的plotlyOutput()
功能与renderPlotly()
关联,dataTableOutput()
与renderDataTable()
功能关联。并且为 UI 中的每个输出函数定义的唯一标识符将其与相关的渲染函数连接起来。这样,我们就将用户界面中的盒图和数据表与服务器连接起来了。
在renderDataTable()
函数中,我们定义了options
参数,将页面长度限制为 10 行数据。
我们现在已经准备好了静态应用程序,可以在线发布了。这个应用程序所缺少的是,对滑块或复选框所做的更改不会显示在 boxplot 或数据表中。为了让应用程序更加动态,我们将使用reactive()
表达式。
这里要解决的一个关键点是,应用程序的动态特性不需要一个reactive()
表达式。UI 的所有输入功能都可以直接连接到render()
功能。这种风格可能适用于具有基本功能的应用程序,但随着应用程序变得复杂,最好使用reactive()
表达式。
reactive()
表达式做了两件重要的事情:它使应用程序更快更有效,消除了代码的重复,并保持渲染函数与所有外部操作的清洁。reactive()
表达式被分配给在 Shiny 中被称为 variable() 的变量。在我们的例子中,我们定义了两个反应表达式 plot1 和 plot2 。在 plot2 中,对 UI 中的复选框输入面板进行基于条件的过滤。在 plot1 中,过滤与滑块输入相关联。因为我们希望这两个变化都反映在显示的输出中,所以,我们使用了 plot2() 作为 plot1 的输入变量。最后, plot1() 被用作render()
函数中的数据。
为了反映用户界面上所做的更改,我们将在标识符的帮助下连接 UI 的输入函数,就像输出函数一样。这里,我们将使用输入$valuechain 来反映对“选择价值链”选项所做的任何更改,这些更改将直接告诉服务器使用reactive()
表达式采取行动,并将反映在用户界面上的方框图和数据表中。类似地,输入$year 将反映在绘图和数据表的滑块上所做的更改。
运行应用程序
现在您已经填写了 UI 和服务器的详细信息。现在是时候使用编辑器右上角的运行应用程序选项来启动应用程序了。
作者图片
按下运行应用程序按钮,应用程序将在一个新窗口中打开,如下所示。
作者图片
在线发布应用程序
如果这是你第一次在 ShinyApps.io 上打开一个用户帐户,接下来,在 R 上安装 rsconnect 包,然后从你的 Shiny 帐户复制令牌细节,并在 R 控制台上运行命令,这将授权你从你的笔记本电脑发布到 ShinyApps.io 网页。
要在线发布应用程序,请按应用程序右上角的发布按钮(您可以参考上图)。现在将打开一个窗口,按下一步,然后选择 ShinyApps.io 选项。接下来的事情是选择需要发布的文件,并给你的应用程序命名,这将显示在 URL 中。
作者图片
按下“发布”后,应用程序需要几分钟才能上线。这将显示在 ShinyApps 网站上您帐户的仪表盘中。
已发布 app 链接:https://abhinavmalasi.shinyapps.io/World_food_waste/
结束语
Shiny 是一个强大的工具,一旦你对它的内部工作有了基本的了解,它就可以非常直观和容易地构建应用程序。它既被动又懒惰。在用户界面上所做的改变会很快反映在界面上,从而使它变得被动和懒惰,因为它只会做最少量的工作来更新应用程序。
用 Shiny 构建应用程序的最佳方法是首先在一张纸上设计用户界面,以确定你需要什么。然后开始在 UI 中逐个添加组件,然后连接到服务器。确保为 UI 中的每个功能定义唯一的标识符。这样,当一个功能完成时,运行应用程序,看看它是否能根据您的需要工作。如果它是好的,然后添加其他功能,并与前一个连接。这样,在构建你的应用程序时,卡住的机会就少了。
我希望这能激励你构建自己的闪亮应用。有大量关于构建闪亮应用的文献和教程。从闪亮网站的教程开始,并从网页上分享的应用中获得灵感。然后你也可以读一读《掌握闪亮的 T9》这本书,这本书很好地理解了哈德利·威克姆(Hadley Wickham)构建闪亮应用背后的思维过程。
如果你开发了应用程序,请在评论或链接中分享你的想法。到那时,快乐的编码!
对 R 的更多阅读感兴趣,请查看:
**</3-lesser-known-pipe-operators-in-tidyverse-111d3411803a> </7-shortcuts-worth-knowing-for-efficient-workflow-in-r-cc52c351cb73>
参考资料:
- https://mastering-shiny.org/index.html
- https://data catalog . world bank . org/dataset/what-waste-global-database
- 【http://www.fao.org/platform-food-loss-waste/flw-data/en/
- https://shiny.rstudio.com/reference/shiny/1.5.0/
该应用程序的完整代码的链接是这里是。
您可以在 LinkedIn 和 Twitter 上与我联系,跟随我的数据科学和数据可视化之旅。**
使用 CloudFront 功能和 S3 保护应用程序,您只需知道
原文:https://towardsdatascience.com/all-you-need-to-know-to-secure-apps-with-cloudfront-functions-and-s3-d9f5c966d8a9?source=collection_archive---------12-----------------------
行业笔记,我所了解到的
帮助我们成功通过安全审计的安全最佳实践
由美国国家航空航天局、欧空局和 STScI 拍摄的船底座星云(“名人星”星云)
C 目前,亚马逊 S3 和 CloudFront 是交付生产就绪 spa 的最佳云服务,如 Angular 应用程序、Vue 应用程序或 React 应用程序。不幸的是,默认情况下,S3 和 CloudFront 并没有启用所有的安全功能,需要在生产中运行这样的 SPA 前端应用程序。
最近,我们推出了一个前端(Angular apps)平台,托管在亚马逊 S3 和 CloudFront 上。在本文中,我想分享主要的安全最佳实践,以及我们如何在我们的平台上实现它们。有了这些安全最佳实践,帮助我们成功通过了非常严格的安全审核!
S3 和 CloudFront 的安全最佳实践概述
S3 和 CloudFront 都是非常成熟的云服务,开始时也相对简单。然而,还有比第一眼看到的更多的东西,特别是如果这些服务一起使用的话。此外,如果与 Route 53 (AWS DNS 服务)和 Amazon Certificates Manager 等其他云服务相结合,它们将成为任何 web 开发人员的强大必备工具套件。不幸的是,它们的灵活性和表面上的简单性可能是一个安全隐患。在过去的几个月里,我们大多数人可能听说过至少一个 S3 数据泄露的例子(无论你什么时候读到这篇文章)。
下图显示了托管在 S3 和 CloudFront 上的典型 SPA 的示例基础架构。自然,这样的前端应用程序将依赖于一组后端服务和 API。由于这篇文章已经超出了我最初的预期,我们将不在本文中讨论平台的后端。
使用 S3 和 CloudFront 的 Angular、Vue 或 React 应用程序的示例部署图(作者)。
在本文中,我将主要关注安全性最佳实践,这些实践有助于解决以下问题:
- 如何保护存储敏感用户数据和应用程序代码的 S3 存储桶?
- 如何安全地配置 CloudFront 发行版?
- 如何用 CloudFront 功能保护前端应用免受常见 OWASP 威胁?
因此,让我们首先看看我们可以用 S3 和 CloudFront 做些什么来保护我们的 Angular、Vue 或 React 前端应用程序。
注意:我决定基于 AWS 服务来组织这篇文章,因为我想尽可能多地亲自动手。
固定 S3 铲斗
多年来,S3 已经发展成为一个功能极其丰富的云服务。亚马逊 S3 可以实现许多用例。因此,保护 S3 桶和物体在很大程度上取决于它们的使用方式。大概,最常见的用例,也是我想更详细考察的用例是:托管 web 应用,为用户的二进制对象数据提供存储,比如:图像、视频和文档。
保护 S3 桶主要需要:锁定对桶的访问,阻止所有公共访问, 保护静态数据,保护传输中的数据。
让我们从配置 bucket 访问权限开始。首先,我们需要了解有几种方法来控制对 S3 存储桶和对象的访问:使用 S3 存储桶策略、S3 ACL、S3 接入点策略或 IAM 策略。如果你对其中的区别感兴趣,你应该看看:IAM 策略和 Bucket 策略以及 ACL!哦,天啊! ”。
使用 S3 存储桶策略的访问控制
我将重点介绍使用 S3 存储桶策略配置访问控制,因为在我看来,它们最适合手头的任务。以下策略在保护 S3 水桶方面做得很好。
通过 CloudFront 配置访问的 S3 策略示例。
我们的示例 S3 存储桶策略包含两个语句。第一条语句用于锁定对 bucket 对象的读访问,即只允许通过特定的 CloudFront 发行版访问它们。该发行版通过使用其原始访问标识来指定,其中可以通过 CloudFront 控制台轻松创建。这很容易设置,但它已经提高了安全性,因为 S3 桶策略将拒绝一个动作,除非有明确的允许。在我们的策略中,只明确允许 GetObject 动作,并且只允许我们的 CloudFront 发行版读取 bucket 的对象。注意,这个策略并不阻止通过 CloudFront 发行版访问数据。任何知道 CloudFront URL 的人都可以阅读我们 S3 桶中的所有数据。稍后我们将讨论如何进一步限制对数据读访问。
解开我们政策中的第二个声明要稍微复杂一点。它用于阻止向 S3 存储桶添加对象,除非写请求是由具有BACKEND_ROLE_ID
角色的后端服务发出的。更正式的说法是:否认 PutObject
动作对于任何原则*,除非其userId
以BACKEND_ROLE_ID
开头。或者相反,只有当委托人已经承担了BACKEND_ROLE_ID.
的角色时,才允许写入这个桶*
需要注意的是,在我们的条件中,我们没有使用角色的 ARN,而是使用其唯一的角色 Id* 来指定期望的角色*。为了检索角色 Id ,我们可以运行aws iam get-role --role-name ROLE_NAME
。如果由于某种原因无法使用 AWS CLI,另一个解决方案是使用条件键aws:PrincipalArn
而不是aws:userId
,,因为它也总是包含在请求中。例如,您可以更改上面的策略来指定下面的条件语句,而不更改策略的语义。**
使用 PrincipalArn 代替 UserId 的替代条件。
眼尖的读者会注意到,我们在语句“条件”中也指定了*AIDA**
。通过将它添加到我们的条件表达式中,我们还允许所有 IAM 用户将对象写入 S3 桶。原因是 AWS IAM 为所有用户分配唯一的 id,所有这些 id 都有相同的前缀,也就是*AIDA*
。虽然添加这个条件并不是生产所需要的(记住总是让人们远离数据 ),但它在开发过程中非常有用。此外,我们可以使用类似的方法为 CI/CD 管道、lambda 函数、自动缩放组中的 EC2 实例等设置权限。
注意:激活 IAM Access Analyzer 在实践中非常有用,在策略创建期间(充当“语法检查器”)和系统运行期间(持续监视安全策略的更改)都是如此。而且是免费的。
这种方法是允许后端服务和外部服务器到服务器回调将数据上传到我们的 S3 桶的好方法。然而,许多应用程序也希望最终用户能够上传他们自己的数据,例如个人资料图像。为了能够将文件从前端应用程序直接上传到 S3 存储桶,我们需要 S3 预先指定的 URL。这个过程的工作方式(大致)是让后端服务向 S3 发送一个上传请求。然后,它使用 POST 或 PUT 方法生成加密的上传 URL,并将其返回给调用服务。最后,后端服务将这个签名的 URL 发送到前端客户端,然后前端客户端可以直接上传到 S3。降低成本和更好的性能(特别是使用 S3 传输加速)只是使用预设计 URL 的一些好处。查看以下文章了解更多细节。
*https://aws.amazon.com/blogs/compute/uploading-to-amazon-s3-directly-from-a-web-or-mobile-application/
保护 S3 的静态数据
保护静态数据是一个非常广泛的主题,涉及的技术包括:数据加密、标记化(匿名化数据)和屏蔽(编辑数据)。S3 提供了许多有用的功能,可以为驻留在 S3 的数据增加额外的安全层。尽管保护静态数据可能是一个非常复杂的过程,但大多数 web 应用程序通过采取以下措施应该是没问题的:
- 启用 默认桶加密 n⁴ 。亚马逊 S3 支持用户数据的服务器端加密,并且对最终用户完全透明。也可以在 S3 控制台中一键启用。我推荐使用亚马逊 S3 管理的密钥(SSE-S3),因为这将降低成本,而且因为 SSE-S3 不受任何费率限制。
- 激活 桶版本 g. 这使得 S3 为每个修改或删除的对象存储一个新版本,如果需要的话,我们可以从该版本中恢复(意外)受损的对象。另外,我发现在 bucket 上启用 MFA delete 非常有用,但是必须由 root 帐户来完成。激活版本控制非常简单,类似于启用服务器端加密,不需要我们改变应用程序的业务逻辑。
- 启用 为 S3 ⁴ 进行 CloudTrail 日志记录。这是我推荐的最低标准。它支持记录 S3 API 调用,包括来自控制台的调用和对亚马逊 S3 API 的代码调用(例如,来自后端服务)。
- 最后,作为额外的安全层,确保阻止所有公共访问你的 S3 桶。
阻止所有公众访问 S3 桶。
保护 CloudFront 发行版
在其核心,CloudFront 是一个内容交付网络(CDN ),它(除了缓存层之外)不存储任何数据。因此,在保护我们前端的 CloudFront 分发的背景下,主要讨论:保护传输中的数据和管理访问控制是有意义的。
我们的 CloudFront 发行版是我们应用程序的唯一入口。这意味着所有用户请求都需要通过 CloudFront 发行版。CloudFront 还支持将多个来源放在一个发行版后面。这使我们能够通过单个分布,即单个(子)域,公开多个 S3 桶。所有这些使得保护我们的 CloudFront 发行版成为一个非常重要的问题。
使用 CloudFront 的签名 URL 进行访问控制
通过限制只有 CloudFront 才能访问我们的 S3 存储区,我们已经极大地限制了访问控制。然而,一些数据可能需要额外的安全层。输入 CloudFront 签名的 URL。
签名的 URL 是一个非常有用的特性,它本身可能值得写一篇文章。在这里,我简要地讨论了何时以及 如何使用它们,因为没有经过签名的 URL,我们的安全最佳实践将是不完整的。
我们通常决定额外保护 S3 对象,当我们不想让网上的每个人都可以读取它们的时候。这可能是因为数据是敏感的(例如,用户的购买发票),或者它应该只对付费用户开放(例如,课程视频)。例如,私人用户文件应该只允许特定用户访问,而不是网络上的所有人。下面是一个签名网址的例子,可以用来访问user_invoice.pdf
。
https://example.com/user_invoice.pdf?**Expires**=1622924658&**Signature=**9MwQEvSlsWvNfv9GrW71WMiG4X…&**Key-Pair-Id**=APKAJXX2ABBXX6HIX
我们注意到它只是一个普通的 URL,末尾附加了三个参数。Expires
,它决定了 URL 的有效时间,(哈希和签名)Signature
本身和用于生成签名的公钥的Key-Pair-Id
。如果任何参数被省略或不正确,CloudFront 将返回禁止,并带有 HTTP 403 状态代码。还要注意,在我们的例子中,为了可读性,签名被缩短了。
生成一个 CloudFront 签名的 URL 并使用签名的 URL 检索一个 S3 文件(由作者完成)。
那么我们如何生成这样的 URL 呢?据我所知,最常见的使用模式是拥有一个后端签名服务,它充当一个可信的签名者,并在用户请求时对 URL 进行签名(见上图)。URL 通常存储为“原始的”(基本 URL,没有签名),签名服务用于在请求时按需生成签名的 URL。然后,这些可以被嵌入到前端页面中,并例如在用户仪表板上向用户显示。
注意:最近,生成签名的 URL 变得更加方便,因为现在 IAM 用户可以通过密钥组管理用于签名的 URL 的公钥(参见上面例子中的
Key-Pair-Id
),而不需要 AWS root 帐户。签名 URL 的一种替代方法是签名 cookies。它们都有自己的目的,但是一般来说,我们可以用签名的 URL 和 cookies 达到相似的效果。
通过 CloudFront 和 S3 保护传输中的数据
CloudFront 提供了许多配置旋钮,可以很容易地“转动”它们来提高传输中数据的整体安全性。在这里,我们认为传输中的数据是查看者(用户)和源(我们的 S3 桶)之间的所有数据流,它们通过 CloudFront 分布(边缘位置)。最重要的 CloudFront 配置旋钮 include⁵:
- 确保安全策略正确配置了安全 TLS 和密码。这保证了 CloudFront 使用安全版本的 TLS 协议在 CloudFront 的边缘位置和您的用户(查看者)之间进行 HTTPS 通信。根据经验,我建议使用 TLSv1.0 或更高版本(如果浏览器兼容性允许,最好只使用 TLSv1.2_2019),并严格避免使用 SSLv3 协议。注意:参见 CloudFront 发行版的安全策略设置。
- 确保 CloudFront 发行版和查看器之间的通信通过 HTTPS 进行。注意:只需将查看器协议策略设置为总是要求查看器只使用 HTTPS protocol⁴.
- 确保 CloudFront edge 位置与其客户源之间的通信使用 HTTPS,以满足传输中数据加密的合规性要求。注:如前所述,通过设置查看器协议策略自动启用。
最后,还有一个有用的 S3 功能,用于额外保护传输中的数据——VPC 端点,特别是 S3 的网关端点。网关端点类似于 AWS 公共区域服务的网关。它通常用于使私有子网中的 EC2 实例能够访问 S3(或 DynamoDB),而无需离开私有 VPC 网络。它们基于路由表工作,即添加新的路由规则。安全性是通过 VPC 端点策略实现的。然而,我不会更详细地讨论 VPC 端点,因为我相信大多数应用程序使用数据,不一定需要这种级别的隔离。*
CloudFront 功能和防范常见 OWASP 威胁
许多十大 OWASP 威胁不容易(甚至不可能)仅通过 S3 和 CloudFront 特性解决。直到最近,我们不得不使用 Lambda@Edge⁶,但从几周前开始,我们可以使用 CloudFront 函数来实现与 Lambda@Edge 函数相同的功能,而成本只是它的一小部分。下面是函数,我们用它来注入最常见的安全 HTTP 响应头,并实施一些最佳安全实践。我们希望在向用户返回响应之前激活这个函数。因此,它应该与 CloudFront Functions 事件类型相关联:查看器响应。
一个添加通用安全响应 HTTP 头的 CloudFront 函数。
我们的 CloudFront 函数向来自 CloudFront 的用户/查看者响应注入了几个常见的 HTTP 安全头:
- HTTP Strict-Transport-Security(HSTS)是 HTTP 响应头,指示浏览器始终使用 HTTPS 访问网站。我们添加这个标题是为了保护我们的用户免受中间人攻击。
- 内容安全策略(CSP) 是一个 HTTP 响应头,它告诉浏览器应该如何以及在哪里加载页面内容。例如,CSP 可用于限制仅从可信来源(如 own domain、Stripe 和 Google)加载 JS 脚本。CSP 在检测和缓解跨站脚本(XSS) 和数据注入攻击方面发挥着重要作用。
- X-XSS 保护是一个 HTTP 响应头,它指示浏览器在检测到反射的 C 罗斯站点脚本(XSS) 攻击时阻止页面加载。这对于不支持 CSP 的旧浏览器非常有用。
- X-Content-Type-Options 是一个 HTTP 响应头,它指示浏览器按原样使用 MIME 类型,并禁用浏览器的内容嗅探试探法。通过将这个头添加到响应中,我们可以防止 MIME 混淆攻击。
- X-Frame-Options 是一个 HTTP 响应头,指示是否允许浏览器在
<frame>
、<iframe>
、<embed>
或<object>
元素中呈现页面。我们可以用这个头来防止点击劫持攻击 s。 - Referrer-Policy 是一个 HTTP 响应头,它控制对外部链接的请求应该包含多少 Referrer 信息。引用策略用于确保没有跨域的引用泄漏。
- Expect-CT 是和 HTTP 响应头,使用证书透明性策略,即要求证书存在于公共日志中,并且客户端响应附有有效签名。
注意:这个函数最初是用 Lambda@Edge 实现的。这个版本的功能可以在 GitHub gist 这里获得。
结束语
Amazons 良好架构的框架指定了 6 个安全最佳实践,这些实践被分解为 10 个安全问题。在本文中,我们主要关注为前端应用程序实现数据保护最佳实践,这些应用程序使用 S3 和 CloudFront 进行数据存储和交付。特别是,我们解决了 SEC 9(保护静态数据)和 SEC 10(保护传输中的数据)安全问题。此外,我们还看到了如何通过使用 CloudFront 函数(或 Lambda@Edge 函数)来防范常见的 OWASP 威胁。
我最初的目标是分享我在 AWS 上保护前端应用程序的经验,以及从上次安全审计中学到的一些教训。然而,这被证明是(我所认为的)一个保护具有 S3 和 CloudFront 功能的前端应用程序的综合指南。
反正有很多教程讲解如何部署 Angular 或者 React 之类的 spa。然而,对于侧重于实施安全最佳实践的全面的端到端指南来说,情况并非如此。
感谢阅读到最后!希望你喜欢这个!
尾注
- 下面是一个实际的 模式 如何使用 AWS 云开发套件(CDK)部署这样一个应用。
- 注意,在 AWS 术语中,bucket owner 实际上是 AWS 帐户,而不是 IAM 用户,它创建了 bucket 或对象。另请参见下面的尾注 3。
- 注意,所有想要访问 S3 桶的服务(和用户)都需要一个明确的许可。该许可可以通过 S3 存储桶策略或 IAM 策略来授予。我更喜欢用后者。因此,在本文中我假设
*BACKEND_ROLE*
有一个关联的 IAM 策略,这允许它与 S3 对话。 - 这可能会产生额外的费用。
- 除了以上几点,我们还可以对特别敏感的数据使用字段级加密,比如信用卡信息。它是 HTTPS 之上的附加加密层,它保证只有你的应用程序才能解密这些字段。例如,这可以防止通过系统日志或诊断工具泄漏信息。
- AWS 确实提供了 WAF 和 Shield 等附加服务,但我们不能完全依赖它们。相反,我们应该始终致力于深度防御方法,即保护我们应用程序的所有层。**
使用深度学习开始语音处理需要知道的术语
原文:https://towardsdatascience.com/all-you-need-to-know-to-start-speech-processing-with-deep-learning-102c916edf62?source=collection_archive---------12-----------------------
凯利·西克玛在 Unsplash 上的照片
我们都爱我们的 Alexa 和 Siri,但你知道你可以自己从头开始做一个吗?
在接下来的系列博客中,我们将讨论更多关于音频和围绕音频的深度学习研究。但首先,让我们花些时间来了解与处理音频相关的基本术语。
通过这篇博客,我将讲述以下主题,这些主题将使您能够更深入地研究文本到语音转换和语音处理:
- 声音的
- 傅里叶变换
- 短时傅里叶变换和频谱图
- 梅尔光谱图
- 音位
音频
我们的主要交流方式是通过语音,我们经常听音频。但是计算机是如何理解音频的呢?计算机只能理解数字,所以我们采集一段时间内的气压样本,这就成了一段音频剪辑。我们对该数据的采样速率可以变化,但最常见的是 44.1 kHz(频率)。
可视化音频样本(图片由作者提供)
以上是音频的数字表示。假设我以 16kHz 对该数据进行采样,这意味着在一秒钟内有 16000 个幅度的序列。因此,如果音频为 10 秒,总振幅将为 16000*10,这是一个很大的数字!那么,我们如何从这个巨大的振幅集合中提取必要的信息呢?这就是傅立叶变换帮助我们的地方。
傅立叶变换
音频信号由几个单频声波组成。在上面的图示中,我们只能看到在每个时间步长上,所有不同频率的波的振幅相加所产生的波。傅立叶变换通过将信号分解成单个频率和对应于该频率的幅度来帮助我们。换句话说,我们可以说我们正在将信号从时域转换到频域。这种转换是可能的,因为每个音频信号都可以分解为余弦和正弦波的总和。
快速傅立叶变换(FFT)是一种快速有效的傅立叶变换算法。下面是我们之前看到的音频样本的 FFT。
以上音频的 FFT(图片由作者提供)
上图显示,这个特定的音频信号具有较高振幅的低频波和较低振幅的高频波。
一般来说,在一个音频片段中,不同频率波的振幅随时间而变化。因此,我们可以有一个音频剪辑,其中一些补丁只有高振幅的高频波,而同一剪辑中的其他一些补丁只有高振幅的低频波。现在,如果我们看到整个音频的 FFT,那么最终频谱的低频和高频幅度将达到平均,因为它将在整个片段上达到平均。另一方面,我们可以计算对应于多个音频片段的多个 FFT,这些 FFT 是通过以固定的时间间隔分割原始剪辑而获得的。这些 FFT 集合实际上会提供更多关于原始剪辑中发生的变化的信息,因为它们正确地表示了局部信息。
短时傅里叶变换和频谱图
我们发现多次 FFT 对我们更有利,所以我们使用短时傅立叶变换(STFT)。STFT 将较长的音频信号分成等长的小段,然后在每个小段上分别计算傅立叶变换。
STFT 可视化(纸
- 窗口长度是 STFT 划分信号的固定间隔的长度。
- 跳跃长度是窗口长度的非交叉部分的长度。
- 重叠长度是窗口长度相交部分的长度。
为了表示 STFT,我们使用声谱图。在频谱图中,y 轴的一个单位对应于对数域中的频率,x 轴的一个单位对应于用于计算 STFT 的窗口长度。(x,y)处的值表示对应于窗口时间和频率的幅度(以 dB 为单位)。这里的 dB 标度类似于幅度的对数标度。
声谱图(图片由作者提供)
梅尔声谱图
从数学上来说,梅尔标度是频率标度的非线性变换的结果。梅尔标度是这样的,它接近地代表了人耳对两个独特声音之间的差异的感知程度。因此,如果人耳能够清楚地理解两个声音之间的差异,那么在 Mel 标度上,它们将比人类不能清楚地区分的另外两个声音彼此相距更远。
这比 Hz 标度更好,因为在 Hz 标度上,500-1000 Hz 和 7500-8000 Hz 之间的差异是相等的,但对于人耳来说,500-1000Hz 之间的差异非常明显,而对于 7500-8000Hz,我们几乎注意不到这种差异。
因此,我们通过将频率转换为 Mel 标度,将上面的频谱图转换为 Mel 频谱图,以获得我们数据的更实际的表示。
音素:
音位是使一个词的发音和意义不同于另一个词的最小声音单位。例如,' soar '中的/s/与' roar '中的/r/不同,因为它与' soar '在发音和意义上都不同。
总结
- 音频只不过是我们可以以不同频率采样的气压幅度列表。
- FFT 用于将信号从时域转换到频域。但是使用 FFT 转换整个音频会导致信息丢失,因此我们使用 STFT。
- STFT 对音频使用滑动窗口 FFT。
- 为了表示 STFT,我们使用声谱图。
- 声谱图在对数域中具有频率,当我们将其转换到 Mel 标度时,所得声谱图成为 Mel 声谱图。
我希望这个博客能给你一些关于语音处理中常用术语的必要信息。要了解语音处理中使用的不同深度学习算法,请查看这个博客。
成为 媒介会员 解锁阅读媒介上的许多其他故事。关注我们的Medium阅读更多此类博文。
Python 中的 Allan 方差
原文:https://towardsdatascience.com/allan-variance-in-python-d1175e5aeee2?source=collection_archive---------3-----------------------
尿囊醇的简要背景和用途
作者图片
简介
传感器在我们的日常生活中有着广泛的用途,在现代物联网中发挥着举足轻重的作用。这些芯片感应必要的机械激励,并转换成电实体。智能手机、智能手表、运动器材、笔记本电脑和其他物联网工具等日常用品中都有传感器。这些设备的性能很大程度上取决于安装在内部的传感芯片的质量。容易捕捉噪声和不必要信号的传感器不能提供精确的结果,最终退出市场。在传感器行业,开发能够有效区分信号和噪声的顶级芯片的竞争非常激烈。
在本文中,我将介绍 MEMS 传感器的噪声测量过程。MEMS 代表微机电系统。工程学的这一分支研究那些需要电子和机械工程知识的设备。AVAR (Allan 方差)测试是检查 MEMS 器件噪声性能的众多测试之一。它以美国物理学家大卫·w·艾伦的名字命名。该测试提供了器件相对于时间尺度的噪声性能,并且需要解释 AVAR 曲线来得出器件是否有噪声的结论。有时用离差代替方差来绘制曲线。
艾伦偏差曲线示例如下所示。该图特别针对时钟的频率稳定性,但人们可以在足够长的时间内测量任何感兴趣的变量,以获得这些偏差曲线。我将在后面的部分解释艾伦偏差图。
图片来自维基百科
噪声测量
如果方差太大,数据被称为有噪声的。我们都知道标准偏差或标准方差,公式如下
可汗学院
如果来自设备的数据由随机尖峰或下降组成,它将具有高偏差,并且最终它将被认为是有噪声的设备。有时,如果噪声的相对振幅与信号的振幅相似,则噪声与信号无法区分。通常,在 MEMS 传感器中,噪声应该比真实信号小几个数量级。因此,噪声的第一估计是从设备收集的样本数据的偏差。为什么我们不坚持标准差/方差呢?为什么我们需要像 Allan variance 这样的不同类型的变化?
对于 MEMS 传感器,开发人员对器件参数的长期稳定性感兴趣,因此需要长时间收集数据。通常,传统的标准偏差随着数据量的增加而增加,因此,利用该偏差作为器件性能参数没有什么意义。我们需要某种偏差参数,该参数将基于设备性能,而不依赖于任何数据伪影[1]。
艾伦方差的变化
艾伦方差有许多不同的公式。最常见的是重叠艾伦方差,其中数据点被分成与后续组有一定数量重叠的聚类。经典的 Allan 偏差公式仅包含两个连续的数据点用于计算。这就是为什么它有时被称为双样本方差。
但是这种方法的可信度很差。最常用的方法是重叠法,公式如下
本质上。该方法收集数据点,并在τ初始值的 m 倍上求平均值。例如,如果 2 个数据点被平均,m 的值将是 2。两个连续数据点之间的最小时间差是初始τ。
艾伦偏差曲线解读
样本 MEMS 传感器 AV 曲线[2]
我们来看一个样本 AVAR 结果,如上图所示。AV 曲线通常以双对数标度绘制。偏差最初增加,直到某个时间点,它增加,然后开始下降。x 轴是聚类时间,其中的值表示数据分组在一起的时间量。将这些聚类一起平均,以获得 Allan 偏差。偏差的下降是一段时间内平均数据的结果。最初的增加归因于滚降的假象。在很短的时间跨度内,我们通常没有一个完整的样本,但我们希望平均。偏差在这一点上升。这是在非常短的时间尺度上相关传感器运动的假象。
初始时间簇是高频噪声的代表。由于这是一个双对数图,偏差随着负半斜率快速下降,这实质上描述了白噪声的存在。曲线中的最低点通常被定义为“偏置稳定性”,它被视为一个非常关键的噪声参数。通常期望偏置稳定性在一定的上限和下限内。超过这个点,有时偏差开始增加,表明低频噪声占主导地位。这种类型的噪声可能包括温度效应、设备老化或其他次级效应。对于许多设备来说,如果没有在足够长的时间内收集数据,就无法观察到这种上升趋势,因为这是一个对数-对数图。白噪声区对于陀螺仪称为角度随机游走(ARW ),对于加速度计称为速度随机游走(VRW)。随机游走系数有时可以从所需聚类时间的直线斜率中获得。
Python 实现
由 AllanTools 的开发者们已经做出了巨大的努力来生成 python 包来实现 Allan variance。这里我将使用这个 python 包在笔记本环境中实现 Allan variance。为了演示,我之前已经使用 R 语言创建了一个合成数据集,我将在这里使用它。
数据首先被转换成一个列表,因为 allantools.oadev()方法接受一个列表作为输入。
最后,将该数据提供给生成对数标度的 AVAR 曲线的方法。
作者图片
由于这是一个合成数据集,我们最初没有看到滚降效应。oadev()方法以 1 Hz 的采样率获取数据。它返回绘制的所需 tau 和偏差值。通常,传感器有多个轴,参数也在所有轴上进行检查,如下所示
作者图片
如果我们在原始值上绘图,它将看起来像下面这样
作者图片
在这里,我们可以看到温度效应或其他低频效应接近曲线带的末端,曲线开始上升,表明偏差较大。因此,我们有一个偏差最小的最小点,该平均点是最理想的工作点。
当不使用重叠方法时,偏差变得随机。
作者图片
结论
本文展示了 Allan 偏差/方差作为噪声参数在现代传感器业务中的应用。结合 python 工具描述了 Allan 曲线的解释。AllanTools 软件包用于绘制 Allan 偏差曲线。合成数据集没有清楚地显示 AV 曲线的所有方面,但真实的传感器肯定会展示滚降和次级效应。
感谢阅读。
Github 页面
参考
[1] D. W. Allan,“精密时钟和振荡器的时间和频率(时域)表征、估计和预测”,载于 IEEE 超声波学、铁电体和频率控制汇刊,第 34 卷,第 6 期,第 647-654 页,1987 年 11 月,doi: 10.1109/T-UFFC.1987.26997。
[2]坦纳豪斯、马丁&盖修、蒂姆&卡洪、迪安&霍兰德、亚历克斯。(2010).通过应用和处理 MEMS 惯性传感器阵列的精确实时惯性导航装置。20–26.10.1109/计划。56610.86686866616
头韵相似性
原文:https://towardsdatascience.com/alliterative-affinities-do-parents-select-first-names-to-match-surnames-574c04528ec1?source=collection_archive---------43-----------------------
父母会选择名字来匹配姓氏吗?
乔恩·泰森在 Unsplash 上的照片
名称又能代表什么呢对于很多父母来说,一切。考虑到婴儿名字书的广泛流行,令人眼花缭乱的标题如 100,000+婴儿名字:最有帮助的,最完整的,&最新的名字书和60,000 婴儿名字的大书。对一些父母来说,这个决定太重要了,除了专家之外,不能托付给任何人。在这种情况下,婴儿命名顾问会提供个性化的命名建议,价格从几百美元到近 3 万美元不等。在这篇文章发表时,报道范围的上限超过了美国中等家庭收入的 50%。
所有这些努力,以及在某些情况下的支出,会带来什么?由经济学家兼记者二人组史蒂芬·列维特和史蒂芬·都伯纳合著的著名流行经济学著作《魔鬼经济学》在最后一章中对这个问题提出了质疑。莱维特和杜布纳认为,孩子的名字最终会更多地反映孩子的父母,而不是孩子本身。一个像“胜利者”这样据说吉祥的名字不会注定一个孩子的魅力或成功,被命名为“失败者”也不会注定一个孩子的生活艰难。这个例子来自一个奇怪的案例,一位父亲将一个孩子命名为“赢家”,另一个孩子命名为“输家”,他们的人生轨迹与他们被赋予的名字不符。
莱维特和杜伯纳进一步指出,相对于期望值,父母对孩子的影响很大程度上取决于孩子出生时父母是什么样的人,而不是他们掌握育儿科学的程度。也就是说,父母可能比养育更重要(超过最低限度的体面和关心的某个阈值)。
就名字而言,一个名字对一个人的描述可能不如一个人对一个名字的描述。在我们对这种关系的方向感到困惑的时候,我们把一种地位和权力的感觉归因于某些名字,父母可能会被这些名字所吸引。例如,2008 年和 2009 年,取名为巴拉克的新生儿数量激增,这似乎是巴拉克·奥巴马当选总统的直接影响。
父母会把头韵名字视为这类理想名字的一员吗?
为了回答这个问题,我利用了 IPUMS 1930 年人口普查中 5%的样本。我知道这很老了,但是有代表性的、及时的个人身份信息来源是很难得到的,尤其是对于许多人认为是愚蠢的问题。我向你保证,我会是第一个认为这确实是一个愚蠢问题的人。
我对这些数据提出了一个简单的问题:如果一组父母的姓氏以某个字母开头(比如“Anderson”),他们是否比其他父母更有可能为孩子选择以相同字母开头的名字(比如“Amelia”)?
答案似乎是肯定的,除非你的姓以 j 开头。
我们可以在下面的图中看到这种效果。蓝条表示姓氏以给定字符开头的人和名字以相同字符开头的人的比例。灰色的条柱报告了姓氏不是以给定字符开始的而不是以给定字符开始的名字是以给定字符开始的个人的比例。
资料来源:美国 IPUMS 和作者的计算
例如,看一看最左边的 2 个条形,对应于字母 A。姓氏以 A 开头的个人有 8.3%的时间以 A 开头,详细情况由灰色条形表示。相比之下,姓以 A 开头的人有 9.0%的时候名字以 A 开头,这在蓝条中有报道。
灰色条可以被认为是以给定的第一个字符开始的名字的基本比率,而蓝色条是那些可能有头韵名字的人的比率(因为他们的姓以给定的字符开始)——我称之为头韵比率。对于下面显示的每个字母,头韵率都超过了基本率(我只显示了最常见的 15 个字符,占名字的 90%),但 J 除外,其效果奇怪地相反。
头韵和基础率之间的一些差异似乎微不足道。那么,这些差异有多大意义呢?我在下面以不同的格式给出了这些相同的估计值,按字符组织的基本和头韵率的置信区间为 95%。只有 G 和 R 在头韵和基础率之间没有表现出显著差异。
资料来源:美国 IPUMS 和作者的计算
我们可以通过将头韵率标准化为基本率来进行字符间的比较。例如,虽然 A 的头韵率和基本率之间的差距为 0.7 个百分点,B 仅为 0.3 个百分点,但这两个头韵率都比各自的基本率大 8.4%。因此,姓氏以 A 开头的人,其名字以 A 开头的可能性比姓氏以 A 开头的人高 8.4%。如果我们对 15 个最常见字符的头韵倾向进行平均,排除 J 并按基本比率加权,我们会得到 7.0%的平均影响。
西班牙裔个体的平均头韵效应为 13%,接近人口平均水平的两倍。农村居民的平均头韵效应为 4.9%,城市地区个人的平均头韵效应为 8.6%。对 35 岁以下的人来说,平均影响从大约 7%攀升到 36 岁及以上的人的 11%以上。
在男女婚姻中,妇女随夫姓的普遍做法减少了头韵倾向。J 的头韵效应仍然是负的,对两组都有统计学意义。其余 14 种头韵效果中,只有 5 种对已婚女性有意义,相比之下,14 种对已婚男性有意义。
头韵倾向在不同的人口统计学维度上差异很大。然而,选择头韵名字的趋势似乎相当普遍。
一共是三万美元,谢谢。
参考文献
[1] D. Baer,人们支付高达 29,000 美元请一个婴儿命名顾问给他们的孩子取名 (2016),商业内幕
[2] A. S .吉布斯,成长巴拉克:遇见以奥巴马总统命名的三个男孩 (2017),NBC
[3] S. Ruggles,S. Flood,S. Foster,R. Goeken,J. Pacas,M. Schouweiler 和 m .索贝克, 1930 年 5%样本 (2021),IPUMS
在一系列基准测试中,几乎自由归纳嵌入在图分类中的表现优于训练过的图神经网络
原文:https://towardsdatascience.com/almost-free-inductive-embeddings-out-perform-trained-graph-neural-networks-in-graph-classification-651ace368bc1?source=collection_archive---------26-----------------------
*训练还是不训练——这不是问题
(匿名)*
具有随机分配的权重的未训练的图卷积网络[1] (uGCN)由于极低的成本、实现的简单性和相当明显的优雅性,已经成为我在一系列图数据任务中的主要基线编码器。然而,没有人(据我所知)报告过这个简单模型相对于它的姐姐(一个在监督设置下完全成熟(端到端训练)的图卷积网络(CGN))的实际性能基准。于是我照做了。
动机:找出 uGCN 是否产生高质量的表示,可以在归纳设置中的图上的一系列下游任务中使用,以便训练的模型可以归纳到以前看不到的数据(受最近报道的直推设置结果的启发[2])。
结果很有趣。在最坏的情况下,简单模型(uGCN + degree kernel + random forest)与端到端训练的 GCN 相比,得分为 54:90,而更现实的情况导致了毁灭性的 93:51,这表明我们可以几乎免费的嵌入,在图形分类任务中表现优于或接近匹配端到端训练的 gcn,而成本只有一小部分。小模型的训练只花了 10 分钟,而整个实验持续了 4 个小时。让我们详细了解一下,看看发生了什么事!
万一你的阅读偏好是喜欢代码而不是文章,请随意使用附带的 colab 笔记本进行实验。
预赛
许多重要的现实世界数据集以图形或网络的形式出现:社会网络、知识图、蛋白质相互作用网络、万维网等。(仅举几例)[1]。
通常写为 G=(V,E)的图是一个数学模型,由一组顶点 V 和一组边 E 组成——顶点 I 和 j 之间的成对连接 e(i,j)。图的扩展是一个带标签的属性图,允许将特征向量 xi 分配给顶点 vi(我们也可以将特征分配给边,但这超出了今天实验的范围)。
图形神经网络[3] (GNN)是一个机器学习模型(一个参数函数,用于调整或从数据中学习参数),它将一个众所周知的生物启发算法家族扩展到非结构化图形数据领域。依我看,对于 GNNs 的机制来说,信息传递是最简单的直觉,参考记忆法则“告诉我谁是你的朋友,我会告诉你你是谁”是合理的。图卷积网络(gcn)被它的发明者(https://tkipf.github.io/graph-convolutional-networks/)很好地描述了,我发现更好地讲述这个故事很有挑战性。
带一阶滤波器的多层 GCN。作者图片
数据
让我们对公开可用的数据进行一系列实验。我们将(I)从数据集4中获取数据,以及(ii)将我们的练习限制在小分子的二元分类(性质预测)上。我们努力的另一个限制是(iii)使用带标号顶点的图。
归纳约束留给我们一个广泛用于测试新算法的数据集列表。这些是:艾滋病,BZR,二氧化碳,DHFR,穆塔格和蛋白质。所有这些数据都已经作为 Pytorch Geometric 5的一部分,有两个版本:原始版本和清除重复版本[6]。这样我们手头就有 12 个数据集了。
艾滋病抗病毒筛查数据[7]
DTP 艾滋病抗病毒筛查已经检查了数万种化合物的抗 HIV 活性证据。可以获得保密协议未涵盖的化合物的筛选结果和化学结构数据。原始数据集包含 2000 个分子,其清理后的版本留给我们 1110 个数据点。
苯二氮卓受体(BZR)配体【8】
原始数据集包含 405 个分子,其清理后的版本留给我们 276 个数据点。
环氧合酶-2 (COX-2)抑制剂【8】
原始数据集包含 467 个分子,其清理后的版本留给我们 237 个数据点。
二氢叶酸还原酶(DHFR)抑制剂【8】
原始数据集包含 756 个分子,其清理后的版本留给我们 578 个数据点。
穆塔格【9】
MUTAG 数据集由 188 种化合物组成,根据它们对细菌的诱变作用分为两类。它的净化版本留给我们 135 个结构。
蛋白质类【10】
来自蛋白质数据库(PDB)蛋白质文件的蛋白质图——一个酶和非酶的数据集。原始数据集包含 1113 个分子,其清理后的版本留给我们 975 个数据点。
实验设计
锦标赛就是这样!
对于每个数据集,我们运行 12 轮训练和测试。
对于每一轮,我们:
我
在 Pytorch Geometric 中进行随机的 80/20 分割(从随机种子= 42 开始,并且对于接下来的每一轮将种子增加 1),使得 80%的数据点(图形)被分配到训练集中,而剩余的 20%进入测试集;
II
在训练集上训练模型,在测试集上评估精度。
对于微小的模型,这意味着预处理,以生成输入分类器的特征。
对于 gcn,我们运行 200 个时期的训练和测试,学习率= 0.01,并报告:
(A)10 个最终时期的平均精度 —一个现实的场景;
(B)在训练过程中达到的最佳精度(就好像我们保存中间状态以便挑选最佳性能的模型)GCNs 的最佳情况(以及我们的小模型的最差情况);
三
最佳模特得 1 分;
四
如果出现平局的情况,问题就出在最小的模特身上。
有 288 个点要奖励:12 个数据集* 12 轮* 2 个场景。
型号
度核(DK) —节点度(与特定顶点关联的边的数量)的直方图,归一化为给定图中的节点数量(使得每个图的特征向量由具有特定数量连接的节点的分数大小组成——这些总和为 1)。
import networkx as nx
import numpy as np
from scipy.sparse import csgraph *# g - a NetworkX* graph
numNodes = len(g.nodes)
degreeHist = nx.degree_histogram(g)
*# normalize*
degreeKernel = [x/numNodes for x in degreeHist]
未训练的图形卷积网络(uGCN) —一种前馈图形卷积网络,具有为 3 层随机分配的权重,其间具有 ReLU 激活。我们将全局平均池应用于输出的 64 维向量(节点嵌入),以便获得图形的表示。
*# INPUT
# g - a NetworkX* graph
*# X - node features of a graph g (np.array)*
*# W0, W1, W2 - randomly assigned weights*# PREPROCESSING
*# A - adjacency matrix of a graph g*
A = nx.convert_matrix.to_scipy_sparse_matrix(g)
# D - normalized laplacian matrix of a graph g derived from A
D = sparse.csgraph.laplacian(A, normed=True) # GRAPH CONVOLUTIONAL NETWORK - FORWARD PASS
*# Layer 0*
Xc = D @ X @ W0
*# ReLU*
Xc = Xc * (Xc>0)
*# concatenation of node features with those aggregated of neighbors*
Xn = np.hstack((X, Xc))
*# Layer 1*
Xc = D @ Xn @ W1
*# ReLU*
Xc = Xc * (Xc>0)
Xn = np.hstack((Xn, Xc))
*# Layer 2 - node embeddings*
Xc = D @ Xn @ W2
*# global mean pooling - graph embedding*
embedding = Xc.sum(axis=0) / Xc.shape[0]
DK 和 uGCN (Mix) 的组合——由 DK 和 uGCN 模型获得的图形表示的串联。
mix = degreeKernel + list(embedding)
具有最大深度 17 的 100 棵树的随机森林(RF) 分类器(来自 Scikit-learn [11]包)在上面被训练。
图卷积网络(CGN) —一个端到端分类器,由 3 个卷积层(64 维)组成,其间有 ReLU 激活,一个全局平均池层(直到此刻 GCN 与 uGCN 非常匹配),后面是一个丢弃层和一个线性分类器。我们将把最佳情况场景(B)中的模型称为 GCN-B,将现实场景(A)中的模型称为 GCN-A。我们将使用 Pytorch Geometric 的参考实现和 GCN 的,以使比赛尽可能公平。
结果
在简单模型和端到端训练的 gcn 之间的 144 轮(12 个数据集* 12 轮)基准测试之后,总计 288 点分布如下:
147:141
测试集的准确性在不同的分裂之间有所不同,并且存在微小模型支配复杂竞争者的情况。
**小模特胜出的数据集:**艾滋病、DHFR(A)、穆塔格。图片由作者提供,使用 Matplotlib [13]的 Seaborn [12]扩展制作
例如,degree 内核采用了 AIDS 数据集上的所有 48 个点,证明比端到端训练的 GCN 高 10%以上的准确性。
gcn 大放异彩的数据集: BZR、COX2 和蛋白质。作者图片
收集的点数:
90—GCN-B;
71—DK;
51—GCN—A;
21 — uGCN。
Clean wins:DK in all versions of AIDS dataset in both scenarios (48 points);
GCN-B (scenario B) has championed in cleaned BZR (12), COX2 (24) and PROTEINS (24) - all versions;The rest of the points distributed as follows.-----------------
Dataset: BZR, cleaned: yes
Scenario: A
DK 0
uGCN 3
Mix 1
GCN 8-----------------
Dataset: BZR, cleaned: no
Scenario: A
DK 4
uGCN 1
Mix 4
GCN 3-----------------
Dataset: BZR, cleaned: no
Scenario: B
DK 1
uGCN 0
Mix 1
GCN 10-----------------
Dataset: COX2, cleaned: yes
Scenario: A
DK 0
uGCN 3
Mix 1
GCN 8-----------------
Dataset: COX2, cleaned: no
Scenario: A
DK 0
uGCN 1
Mix 1
GCN 10-----------------
Dataset: DHFR, cleaned: yes
Scenario: A
DK 1
uGCN 1
Mix 4
GCN 6-----------------
Dataset: DHFR, cleaned: yes
Scenario: B
DK 0
uGCN 0
Mix 3
GCN 9-----------------
Dataset: DHFR, cleaned: no
Scenario: A
DK 2
uGCN 4
Mix 5
GCN 1-----------------
Dataset: DHFR, cleaned: no
Scenario: B
DK 0
uGCN 1
Mix 5
GCN 6-----------------
Dataset: MUTAG, cleaned: yes
Scenario: A
DK 2
uGCN 3
Mix 6
GCN 1-----------------
Dataset: MUTAG, cleaned: yes
Scenario: B
DK 1
uGCN 2
Mix 5
GCN 4-----------------
Dataset: MUTAG, cleaned: no
Scenario: A
DK 5
uGCN 0
Mix 7
GCN 0-----------------
Dataset: MUTAG, cleaned: no
Scenario: B
DK 5
uGCN 0
Mix 6
GCN 1-----------------
Dataset: PROTEINS, cleaned: yes
Scenario: A
DK 2
uGCN 1
Mix 0
GCN 9-----------------
Dataset: PROTEINS, cleaned: no
Scenario: A
DK 0
uGCN 1
Mix 6
GCN 5-----------------
请查看 colab 笔记本了解详细的性能报告,或者参考本回合摘要 (csv)或 本谷歌电子表格 。
总体而言,数据集的清理版本和原始版本之间的性能一直存在差异。这提醒了拥有高质量数据对于相当好的基准的价值。毕竟,数据很少,这可能是我们得到如此不稳定结果的原因。好消息是,研究界有解决这一问题的趋势,并且做了大量工作来实现公平的基准测试。
结论
正如我们所看到的,实验证明了这样一个猜想,即在小分子的图属性预测设置中**,我们可以以很小的成本**获得几乎免费的嵌入,这些嵌入在图分类任务中胜过或接近匹配端到端训练的 gcn。这些发现与[2]的结果一致,因为在概念上,标签传播非常类似于图卷积网络中的消息传递。对这种良好性能的解释,也许是植根于两难境地:我们是否应该调整光谱滤波器参数,以便输出嵌入变得线性可分,或者只是选择一个更鲁棒的分类器,就像我们刚才做的那样。
各轮之间的表现差异再次提醒我们,每个基准都是不稳定的。值得一提的是免费午餐定理,并指出使用几个模型很可能是一个很好的选择。同样值得注意的是,分割确实会影响性能——对于相同的数据集,相同的模型表现出明显不同的决策质量。这就是为什么当在模型之间进行基准测试时,请确保在相同的数据上进行训练和测试。另外,设置随机种子并不是万能的…
下一步可能是在更大的数据集上进行基准测试。同样值得探索的是不同的问题,例如:链接预测、节点和链接分类、图上的回归等等——图卷积网络(训练过的,没有那么多)是非常有能力的模型。
后记
两年前,在 PyData-Lisbon Meetup 上,我第一次公开谈论 uGCN 作为一种几乎适用于所有解决方案,将它命名为通过傅立叶空间的皇家宏伟捷径,并在那时组装了第一个图形分类管道,以便向一个渴望启动她的航空航天初创公司的女孩展示图形卷积的力量。这篇文章是一个真实实验(基于私人数据)的副产品,在这个实验中,经过数小时的训练后,我们可以超越微小模型设定的性能。
如今,随着图的机器学习成为名人,每周都有新的图神经网络架构出现。然而,对于 gnn 为什么在实践中是成功的以及它们是否是良好性能的必要条件的理解相对较少[2]。
在您进入图形机器学习的奇妙世界之前,请熟悉一些基础知识。有很大的努力投入到使最新的发现(以及经典方法)免费提供给更广泛的受众。仅举几个值得关注的努力:cs224w 课程和讲座、开放图基准【14】,以及最近关于几何深度学习【15】基础的工作,为尚未开发的新架构提供了一个清晰的框架。还有一点——一定要从简单的基线开始,如核方法或无监督图卷积网络——通常这些微小的模型很出色。
可持续发展,使用高效的算法。有时候不学就是力量。
2018 年 8 月,在瑞典议会大楼外,格里塔·图恩伯格(Greta Thunberg)开始了一场针对气候的学校罢工。她的标牌上写着,“Skolstrejk fr klim atet”,意思是“学校为气候罢工”。图片由 Anders Hellberg 提供,根据知识共享 署名-分享相似 4.0 国际许可协议授权。
参考
[1] Kipf & Welling,用图卷积网络进行半监督分类(2017),国际学习表示会议;
[2]黄等,结合标签传播和简单模型优于图神经网络(2021),学习表征国际会议;
[3]斯卡塞利等,图神经网络模型(2009),IEEE 神经网络汇刊(第 20 卷,第 1 期,2009 年 1 月);
[4] Morris et al .,TUDataset:用图学习的基准数据集集合(2020),ICML 2020 图表示学习研讨会及以后;
【5】Fey&Lenssen,PyTorch Geometric 快速图表示学习(2019),ICLR 关于图和流形上的表示学习研讨会;
【6】Ivanov,Sviridov & Burnaev,理解图数据集中的同构偏差(2019),arXiv 预印本 arXiv:1910.12091;
【7】Riesen&Bunke,IAM 基于图形的模式识别和机器学习图形数据库库(2008),载于:da Vitora Lobo,n .等人(编辑。),SSPR&2008 年春季,LNCS,第 5342 卷,第 287–297 页;
[8] Sutherland 等人,用遗传算法进行样条拟合:开发分类结构-活性关系的方法(2003),化学杂志。Inf。计算机。Sci。, 43, 1906–1915;
【9】deb Nath 等,诱变芳香和杂芳香硝基化合物的构效关系(1991),医学杂志。化学。34(2):786–797;
【10】Dobson&Doig,在没有比对的情况下区分酶结构与非酶(2003),J. Mol .生物。, 330(4):771–783;
[11] Pedregosa 等人,sci kit-learn:Python 中的机器学习(2011),JMLR 12,第 2825–2830 页;
【12】was kom,seaborn:统计数据可视化(2021),开源软件杂志,6(60),3021;
【13】Hunter,Matplotlib:2D 图形环境(2007),科学计算&工程,第 9 卷,第 3 期,第 90–95 页;
[14]胡等,开放图基准:图上机器学习的数据集(2020),arXiv 预印本 arXiv:2005.00687;
【15】布朗斯坦等,几何深度学习:网格、组、图、测地线和量规(2021),arXiv 预印本 arXiv:2104.13478。
几乎没有数据也没有时间?释放 GPT3 的真正潜力,案例研究
原文:https://towardsdatascience.com/almost-no-data-and-no-time-unlocking-the-true-potential-of-gpt3-a-case-study-b4710ca0614a?source=collection_archive---------21-----------------------
思想和理论
使用 GPT3 快速构建复杂的 NLP 应用原型
由阿尔方斯·莫拉莱斯在 Unsplash 上拍摄的照片
介绍
大型预训练语言模型(如GPT 3【1】)的出现正在自然语言处理领域催生“即时工程”的新范式。这种新的范例使我们能够基于非常少量的数据,不费吹灰之力地快速构建复杂的 NLP 应用程序的原型。我将展示一个案例研究,我在 Waylay的夏季实习期间使用这一技术创建了一个应用程序,使每个人都可以使用语音和文本输入来实现行业级自动化(想想类似谷歌助手的东西,但用于物联网和类固醇!).该解决方案只需极少的数据点,无需重新培训即可轻松适应新情况。最后,我将对这一令人振奋的新趋势发表一些看法。
如果你不想看,你可以看一下这段我向公司提出我的解决方案的内部会议的录音。
提示工程:新的深度学习范式?
回到机器学习的旧时代,工程师们不得不花费无数时间来创建信息丰富和有区别的特征,以提高他们模型的质量。随着深度学习的出现,模型现在能够在给定大量数据的情况下提取自己的质量特征。最终,数据科学家创造了通过迁移学习将大型预训练模型应用于许多下游任务的技术,这使得这些模型可以在许多任务上获得强大的性能,只需看似少量的数据。
自然语言处理(NLP)领域也经历了这些发展。有趣的是,这个领域似乎正在出现一种新的范式,这可能对我们未来如何使用深度学习产生重大影响。
最近,大型预训练生成模型风靡一时。GPT3,这些模型中的一个,通过尽可能准确地预测给定句子的延续来训练(这个任务被称为因果语言建模)。因为这项任务不需要额外的注释(我们称之为自我监督,研究人员能够收集大量数据(40GB 的文本),并训练一个大得离谱的深度学习模型(1750 亿个参数)。因此,GPT3 是目前生成类人语言的最佳模型。给定一个输入句子,GPT3 以自然的方式继续它。
事实证明,善于生成连贯的自然语言有很多好处。当继续那句“虽然演员阵容还可以,但电影剧本很恐怖。这部电影是……”,比起“好”,GPT3 输出“坏”字的可能性要大得多。因此,本质上,通过学习生成文本,我们还学习了如何在不需要访问情感注释的情况下进行情感分类。许多不同的 NLP 应用程序在某种程度上都出现了类似的情况。
我们甚至可以在生成过程中指导 GPT3。如果想知道比利时的首都是什么,可以让 GPT3 继续下面的句子:“法国的首都是巴黎。日本的首都是东京。比利时的首都是……”。另一方面,如果我们只是问“比利时的首都是……”,我们很可能会得到一个延续,如“一个不错的城市”,而不是“布鲁塞尔”。
(图片由作者提供)prompt engineering 背后的核心理念。
我们如何问 GPT3 这些问题,我们使用什么格式,我们包括什么例子被称为提示工程。Prompt engineering 是 NLP 世界中的一种新范式,它可以从根本上改变我们与深度学习模型的交互方式。现在,我们不再需要收集大量数据并对现有模型进行微调,而是能够利用少量数据点来获得显著的结果。额外的好处是,当新数据可用或者当我们想要改变任务定义时,我们甚至不需要重新训练我们的模型。我们甚至不需要自己托管模型,因为可以通过 API 访问 GPT3!
和任何新的范例一样,研究人员和实践者正在快速探索许多不同的利用即时工程的方法。这可以从动态选择提示中的示例(我们将在案例研究中进行)到学习提示的最佳形状。论文“预训练、提示和预测:自然语言处理中提示方法的系统调查”[2]很好地概述了当前对提示方法的研究。
使用 GPT3 实现物联网自动化:案例研究
物联网自动化
Waylay 是一个低代码平台,允许开发者在任何地方应用企业级自动化。连接传感器,推送数据,开始享受低代码自动化的好处。
自动化规则是 Waylay 平台的核心。开发人员编写小的代码片段(或使用预先存在的代码片段)并用逻辑操作符将它们链接在一起,以定义自动化规则。自动化规则可以允许您在连续 3 天无雨的晴天打开洒水器,或者在众多传感器中的一个传感器检测到异常时安排对工业机器的检查。通过将这些规则链接在一起,我们可以创建任意复杂的自动化软件。
让这种自动化技术为每个人所用是 Waylay 的核心价值观之一。想象一下,如果我们可以简单地通过语音或文本控制,以自然的方式与这个自动化引擎进行交互。这就是 NLP 的用武之地。我们可以想象一个工厂工人问他们的机器“烤箱 5 的温度是多少”,而不是必须以典型的方式与计算机交互或者告诉它“如果冷冻室的温度上升到零下 10 度以上并且门是开着的,就发出紧急警告”。
做好这件事当然不容易。人说的规则可能带有很多模糊性,需要大量的智能来正确解析和翻译成 Waylay 自动化规则。
解决方案
如果我们想建立一个解决方案,将人类说出的规则翻译成 Waylay 自动化规则,“传统的”方法是不够的。首先,我们正在处理数据缺乏的问题。为了稳健地解析人类话语并捕获必要的信息以将它们翻译成拦路抢劫系统可以理解的东西,我们将需要跨越不同说话方式和相应的拦路抢劫规则的大量数据。目前没有这方面的数据。即使我们有这些数据,我们的模型也需要重新训练,每次我们想让它服务于一种新的说话方式或一种新的拦路抢劫规则。
我们求助于工程来解决这个问题。如果我们可以使用 GPT3 来为我们做艰苦的工作,我们就可以建立一个高度数据高效的系统,而不需要重新培训来处理新的案件。那该有多好?
现在的问题变成了“我们如何利用 GPT3 的能力来为我们做脏活?”。不幸的是,很难教会 GPT3 根据自然语言输入输出正确的内部数据结构。幸运的是,我们可以用一个聪明的方法来解决这个问题(为此我们必须感谢微软的聪明人[3])。在我们的解决方案中,我们将让 GPT3 输出一个规范句子。这个句子与我们的自然语言输入包含相同的信息,但是以一种更加结构化的方式。例如,“给大卫发一条消息,告诉他在巴黎下雨时安全驾驶”和“只有当巴黎下雨时,告诉大卫“安全驾驶!”“通过短信”都可以简化为标准句“如果巴黎下雨,那么给大卫发短信,告诉他“开车小心!”。
(图片由作者提供)使用 GPT3 将话语映射到规范。
将这些话语转换成规范更像是翻译或摘要任务,GPT3 可以更容易地处理。仅根据几个例子(不到 10 个),GPT3 已经非常擅长将自然声音语言翻译成这种结构化的规范语言。一旦我们得到这个规范的,我们需要一些额外的解析来把它变成表示一个中途停留规则的内部数据结构。虽然这最后一步肯定需要一些额外的工程努力,但我们已经成功地将问题的“智能部分”委托给了 GPT3。
为了获得最佳性能,我们还有一个锦囊妙计。最初,我们只有少量可用的例子。然而,一旦更多的例子变得可用,我们需要根据我们想要转换的话语来选择将哪些例子输入到 GPT3。一个简单的方法是选择与给定的口语句子最相似的例子。这样,我们可以确保 GPT3 始终能够访问最相关的示例。为了验证这个想法,我们采取了最简单的方法:使用静态单词嵌入的均值池来嵌入所有句子,并使用余弦相似度作为距离度量。虽然更高级的相似性度量当然是可能的,但这种快速简单的解决方案已经提供了大部分价值:给定一个大型数据集,我们现在可以快速提取样本,GPT3 将能够使用这些样本来处理给定的话语。
(图片由作者提供)建议的解决方案。
实现这个解决方案非常简单。几个 Flask 微服务、一个小型数据库和一个 Vue.js 前端就很好地完成了这个任务。部署深度学习模型不需要专业知识!
结果
现在是有趣的部分,探索结果。
基于不到 10 个话语示例及其在提示中对应的规范,该解决方案已经显示出显著的效果。该模型能够处理 10 个给定示例中没有表示的不同种类的话语。这一点非常重要,因为在生产过程中,我们可以预期解决方案会以许多不同的不可预见的方式被调用。该解决方案对于打字错误和语法错误是健壮的。此外,该解决方案还利用了 GPT3 强大的“常识”推理能力。它知道如何将“比利时首都”翻译成“布鲁塞尔”,并将“关于独角兽的事实”映射到“独角兽是神秘的生物!”。它甚至可以根据需要讲笑话(尽管它们并不总是好笑)!
在一次内部演示中,一名 Waylay 员工让我用荷兰语输入一些内容。接下来发生的事情震惊了在场的每一个人……在看过零个荷兰语示例后,GPT3 成功地正确解释了荷兰语,并输出了相应的标准英语。如果你有时间,我建议看这个演示的视频记录,我们所有人脸上的表情都是无价的。
(图片由作者提供)取得的一些成果。
结论
通过将我们的语义解析任务重新表述为翻译任务,我们能够利用大型预训练语言模型(GPT3)来为我们完成所有困难的工作。我们的解决方案只需要极少的数据点,无需重新培训就可以轻松适应新的情况,我们甚至不需要自己托管深度学习模型。由于 GPT3 的强大功能,我们的解决方案显示了对未知场景(甚至未知语言)的卓越的泛化能力!).
在接下来的几年中,这种快速工程方法将允许数据科学家以前所未有的速度和便利性构建许多不同的自然语言应用程序的原型。这些原型可以作为实验性功能推出,当越来越多的数据可用时,性能会提高。一旦收集了临界量的数据,就可以探索更传统的深度学习技术。
随着公司目前专注于构建更大的预训练语言模型和研究人员开源他们对这些模型的实现,我们只能期待在接下来的几年里 prompt engineering 变得更加重要。
看看 prompt 工程领域在不久的将来会朝哪个方向发展将会很有趣。有一点是肯定的,随着更大的语言模型的发布(在 API 之后,但也是开源的),我们一定会看到大量有趣的技术,这些技术可以用来立即构建高数据效率的 NLP 应用程序。
参考
- 语言模型是一次性学习者。arXiv 预印本 arXiv:2005.14165 (2020)。
- 刘,彭飞,等。〈预训练,提示和预测:自然语言处理中提示方法的系统综述〉。arXiv 预印本 arXiv:2107.13586 (2021)。
- 受约束的语言模型产生少量的语义解析器。arXiv 预印本 arXiv:2104.08768 (2021)。
AlphaFold 2 正式发布三个月后的衍生产品
原文:https://towardsdatascience.com/alphafold-2-spin-offs-three-months-after-its-official-release-90c2d8714757?source=collection_archive---------5-----------------------
思想和理论,应用,限制和未来
迄今为止与 AlphaFold 2 相关的最重要作品的总结。
自 AlphaFold 2 论文和代码发布以来的三个月里,许多新的文章和预印本问世,它们分析了它的潜力和局限性,在它的基础上产生新的发现,并利用它的力量开发新的结构数据库,试图填补实验结构数据中的知识缺口。
截至 2021 年 10 月初,Nature 2021 关于 AlphaFold 2 的论文已被引用超过 200 次(已审查的论文+未审查的预印本)。在这些作品中,大多数只是在其他更广泛的引用更适合的情况下引用它。在这个故事中,我总结了我认为与 AlphaFold 直接相关的领域最相关的论文和预印本,强调了它的评估,它的直接应用,以及它在建立新的结构数据库中的使用。
索引
简介
先说第一件事:CASP14 中 AlphaFold 2 的原评价
- 需要新的方法来进行评估
用 AlphaFold 2 和 RoseTTAFold 的模型扩展蛋白质结构数据库的覆盖范围
- 涵盖蛋白质宇宙中的“所有”结构
- 蛋白质复合体模型数据库
- 用α折叠多聚体预测蛋白质复合物
对 AlphaFold 2 的预测进行评估,其目的不是预测
- 实验结构生物学家共同努力评估 AlphaFold 在其研究领域的效用
- 蛋白质-肽复合物的预测
- 预测折叠结构不同于预测折叠途径
摘自期刊特刊分子生物学
其他评估和潜在应用概述
进一步注释和解读
简介
去年年底,当结构预测批判评估披露他们的程序 AlphaFold 2 已经击败了所有其他参与者时,Deepmind 成为了新闻。然后在 2021 年 7 月,就在 3 个月前,Deepmind 和 AlphaFold 2 再次成为新闻,当时它的代码被发布。正如我在这篇报道中所报道的,Deepmind 进一步发布了该程序的改编版,可以作为谷歌 Colab 笔记本运行。更令人震惊的是,独立研究人员发布了一整套与特殊序列搜索程序 MMSeqs2 相耦合的 Colab 笔记本电脑,从而使这项强烈依赖于蛋白质序列比对的技术的全部功能可以广泛使用,并且零成本。
AlphaFold 2 以不同的形式如此迅速地被广泛使用,很快就让世界各地的研究人员能够对它进行实验。突然间,许多科学家开始测试它的极限,以及它对结构生物学领域中真实世界问题的适用性。来自世界各地的推文展示了 AlphaFold 2 的模型如何帮助他们更容易地从实验数据中解决结构,在某些情况下,甚至纠正了人类在“手动”解决结构时引入的错误。有时他们也显示出预测中的不一致和问题。
其他小组致力于测试,如果给定 AlphaFold 2 的预测质量,它是否也可以预测蛋白质的其他特征。他们的理由是,即使它被专门训练来预测蛋白质结构,如果它真的学会了完整的蛋白质生物物理学(剧透:它没有!)那么它就有可能预测它们的动力学、相互作用、折叠路径等。引人注目的是,其中一些测试确实发现 AlphaFold 2 可以在预测这些特征方面取得一些进展。
然而,其他小组和 Deepmind 本身应用了 AlphaFold 2 和其他程序,有时甚至整合了它们,以根据它们的预测开发新的结构数据库,首先试图覆盖所有蛋白质组的单个蛋白质结构,然后对多蛋白质复合物进行建模。
以下是我在最近 3 个月 AlphaFold 2 的所有“衍生产品”中发现的最相关和最有趣的作品的非技术总结。
首先:第十四章中 AlphaFold 2 的原始评估
在我开始之前,我先回顾一下一篇非常重要但在很大程度上被媒体忽视的论文:最初的 CASP14 评估确定 AlphaFold 2 是截至 2020/2021 年硬目标(即在蛋白质数据库中没有同源物的蛋白质,因此不容易建模)的最佳建模程序:
本文描述了由指定评估员(美国 HHMI gris hin 小组,长期与 CASP 相关)对所有 CASP14 参与者预测的所有模型进行的官方 CASP14 分析,特别考虑了预测困难靶标的结构的问题,即难以通过同源建模等经典技术建模的蛋白质结构。通过使用与以前版本的 CASP 非常相似的指标,评估人员发现,顶级组(是的,AlphaFold 2)的表现远远优于预测社区的其他成员。但不是在所有的高难度目标上!对于两个目标,其他组的预测者表现更好(然而 AlphaFold 2 确实得到了正确的全局拓扑)。评估人员发现,AlphaFold 2 为大多数目标提供了高度准确的模型,包括一些相当大的蛋白质(较大的蛋白质通常更难建模)。此外,它的一些预测是杰出的,达到了与原子位置的实验不确定性相当的精确度,在许多情况下甚至是氨基酸侧链(在 CASP 的这个轨道中通常甚至不被评估)。像其余的预测者一样,AlphaFold 2 仍然很难对柔性区域和寡聚体装配进行建模(但是,它确实取得了进展,并有助于改善他们的预测-见下一节)。
在另一篇论文中,同一组评估人员显示,CASP14 的目标不是特别容易;事实上,它们是有史以来最难的:
需要新的评估方法
AlphaFold 预测的高度准确性引发了一个我们在 CASP13 中已经提出的问题。到那时,当 AlphaFold 的第一版进入游戏时(它以微弱优势获胜,并不真正意味着像 AlphaFold 2 那样的革命),我们得出结论,随着蛋白质三级结构预测取得新的里程碑,需要为未来的 CASPs 设计新的方向:
https://onlinelibrary.wiley.com/doi/full/10.1002/prot.25787
具体来说,我们建议放弃将靶分成不同的结构域,重新考虑难度指标,不仅评估主链,还评估氨基酸侧链,评估残基方式和可能的残基-残基质量评估。因此,对于 CASP14,鉴于 AlphaFold 2(以及其他方法)的成功,评估人员对评估的新挑战进行了单独的分析和讨论:
https://onlinelibrary.wiley.com/doi/abs/10.1002/prot.26192
一个这样的进一步分析需要评估组成蛋白质靶标的不同结构域之间预测的相互作用:
在通过测量 3D 单位之间相互作用质量的互补分数评估整个蛋白质靶标的模型(与仅评估结构域相反,仅评估结构域是通常进行的主要评估类型),并考虑 10 个特定靶标时,排名最高的预测因子再次是 AlphaFold 2。事实上,它预测了 10 个完整蛋白质中的 8 个的高度准确的模型,其中 3 个的得分远远高于所有其他组的模型。
CASP14 论文的另一个亮点是发现了 AlphaFold 2 的模型,该模型可用于一种称为“分子置换”的基于 X 射线的蛋白质结构确定技术,在该技术中,模型被用作根据实验 X 射线衍射数据求解结构的基础。虽然严格来说,这在以前的 CASP 版本中对一些目标已经是可能的,但是 AlphaFold 2 的高质量模型使得这可以在更多的目标上实现。事实上,对于一些目标,实验数据是可用的,但不是“分阶段的”(通过“分子置换”使用模型来促进实验结构确定的步骤);在某些情况下,AlphaFold 提供的模型有助于解决相位问题和完成实验结构测定(然后可以比较所有模型):
https://onlinelibrary.wiley.com/doi/full/10.1002/prot.26214
用 AlphaFold 2 和 RoseTTAFold 扩展蛋白质结构数据库的覆盖范围
涵盖蛋白质宇宙中的“所有”结构
我已经在 TDS 之前的一个故事中讨论过这篇论文:欧洲生物信息学研究所与 Deepmind 合作开发了最完整的蛋白质结构数据库,对整个社区免费开放。EBI-Deepmind 的目标是覆盖整个蛋白质宇宙,即从所有测序的基因组中模拟所有蛋白质的结构。在撰写本文时,该数据库包含 21 个物种的全蛋白质组模型,其中包括与生物技术相关和/或用作研究模式生物的人类和物种。因此,除了人类蛋白质组之外,该数据库还涵盖了一些致病生物、面包酵母、大米的蛋白质组,以及深入研究的模型,如拟南芥(一种模式植物)和秀丽隐杆线虫(一种模式蠕虫)。
这 21 种生物的所有蛋白质模型都可以在 https://alphafold.ebi.ac.uk/download*[免费下载。EBI 网站还允许用户根据所有有模型的蛋白质序列搜索蛋白质序列;这样,用户可以找到与他们感兴趣的蛋白质非常相关的蛋白质模型,然后使用该模型作为替代或对他们自己的蛋白质进行同源性建模。](https://alphafold.ebi.ac.uk/download)*
我不会在这里花更多的时间,因为我在下面的文章中专门讨论了 Deepmind-EBI 的工作,强调了一些重要的观点,如该数据库中的模型在其他方面的局限性:
*
但我将在此补充这篇预印本,它提供了一个仔细的分析,表明从可折叠蛋白质区域 47%的结构覆盖率的当前基线(考虑实验衍生的加上基于模板的同源性模型), EBI-阿尔法折叠数据库中当前可用的模型将覆盖率提高到 75%。特别是,50%的人类蛋白质组覆盖着实验结构数据或高质量的结构模型,考虑到大约 20%的蛋白质组只是长的无序片段或完全无序的蛋白质,这就更加令人印象深刻了。
https://www.biorxiv.org/content/10.1101/2021.08.03.454980v1
蛋白质复合物模型数据库
EBI-Deepmind 数据库不断增长,这对实验和计算生物学家社区来说很好,但它只专注于单体形式的单个蛋白质的结构。然而,CASP 评估发现,相对于当时的技术水平,AlphaFold 2 在预测蛋白质之间的复合物结构方面似乎有所改进(进一步的工作进一步解决了这一问题,见下一节)。事实上,不仅 CASP 评估得出了这一结论,CAPRI 竞赛也得出这一结论,该竞赛专门用于评估和跟踪蛋白质-蛋白质复合物建模的最新进展:
https://onlinelibrary.wiley.com/doi/full/10.1002/prot.26222?casa_token=NPEuF3FwyZsAAAAA%3A76nV_Sr8iXLNq4b_TnbqzQSmZHHwneD4gVR9IurVrxEY6QZXdDC14I07-YuoN3dfd8yHNkx1FJIsUA
一项刚刚作为预印本问世的新工作利用了 AlphaFold 2 和 RoseTTAFold(一种精确度接近 AlphaFold 2 的蛋白质建模方法,与 AlphaFold 2 同时发表在 Science 上的)来预测蛋白质复合物的结构,而不是单个蛋白质的结构。更具体地说,这项工作提出了一系列系统识别的,酿酒酵母(酵母)蛋白质组的核心真核蛋白质复合物的可能精确的模型。RoseTTAFold 和 AlphaFold 用于扫描 830 万对酵母蛋白质的成对多重序列比对,以检测相互作用对,筛选应该可以实现准确预测的情况,然后建立它们组装的 3D 模型。这项工作产生了一个预测蛋白质复合物的新的大型数据集,每个蛋白质复合物包含两到五个蛋白质成分,几乎跨越了真核细胞中所有的关键过程。超过 100 个模拟的蛋白质装配体以前没有被识别,超过 600 个已知可能形成复合物,但是它们的结构还没有被描述。
这份预印本肯定会在一级期刊上成为一篇突出的论文,其影响类似于 Deepmind-EBI 合作对所有单个蛋白质建模的影响。您现在可以在这里阅读(不幸的是,完整的模型复合体列表尚未发布):
https://www.biorxiv.org/content/10.1101/2021.09.30.462231v1
一个相关的预印本,实际上与上面的预印本共享一些作者姓名,使用了 AlphaFold 2 和 RoseTTAFold 的类似组合来模拟人类线粒体蛋白质的复合物:
https://www.biorxiv.org/content/10.1101/2021.09.14.460228v1
用α折叠多聚体预测蛋白质复合物
就在我准备提交这篇文章的时候,一份来自 Deepmind 的新预印本登陆了 bioRxiv。这份预印本介绍了一种新的α折叠模型,专门用于已知化学计量的多聚体输入(“α折叠多聚体”)。开发人员报告说,它大大提高了预测多聚体界面的准确性,超过了整个社区迄今为止一直在做的仅适用于多种蛋白质的常规α折叠。新程序在复杂的基准数据集上实现了中高精度,即使在没有可用模板的情况下也是如此:
https://www.biorxiv.org/content/10.1101/2021.10.04.463034v1.full.pdf+html
评估 AlphaFold 2 对它的预测,以及它不是为预测而设计的
严格来说,AlphaFold 2 被设计用来预测蛋白质结构,即组成蛋白质的所有原子在空间中的相对位置。但是蛋白质结构不仅仅是三维原子位置。正如我们在上面看到的,它们可以相互作用形成复合物,它们也可以采用多种构象,它们甚至可以缺乏确定的结构并且是无序的,或者具有中间有无序片段的折叠结构域。即使是折叠良好的蛋白质也可能有一些灵活的环。
实验结构生物学家共同努力评估阿尔法折叠在其研究领域的效用
上周刚刚出版的这本伟大的预印本,收集了专家对 AlphaFold 预测蛋白质结构本身以外的几个特征的潜力进行的评估:
https://www.biorxiv.org/content/10.1101/2021.09.26.461876v1
这项工作评估了 AlphaFold 2 预测在蛋白质特征结构元素研究中的应用,作为评估突变影响的工具,用于预测小分子的功能和结合位点(关键是因为大多数药物实际上是结合蛋白质的小分子),相互作用的建模(与上一节和下一节相关),以及实验结构数据的建模。本预印本的一些亮点:
- 与蛋白质组的哪些部分可以通过蛋白质序列之间的简单同源性进行建模相比,作者发现用 AlphaFold 2 进行建模大大增加了可信模型的范围,尽管这因蛋白质组而异。有趣的是,他们报告说,在某些情况下,AlphaFold 的模型识别出了 PDB 罕见的结构特征。我在自己应用 AlphaFold 2 的工作中亲眼目睹了这一点。
- 蛋白质紊乱和蛋白质复合物的预测超越了最先进的工具。是的,AlphaFold 2 不是为了预测紊乱而设计的,但它的一个自我质量指标,即衡量每个氨基酸预测的可信度,被证明是一个优秀的蛋白质紊乱预测。
- 正如许多人所预期的,甚至 CASP14 评估也显示了几个目标,这项工作记录了更多的情况,其中 AlphaFold 2 模型可以用于促进实验结构的确定。
- 对于许多蛋白质,作者表明 AlphaFold 2 的模型质量如此之高,如果严格考虑置信度,它们可以用于各种应用以及实验确定的结构。
在大多数情况下,置信度的作用和模型本身一样重要。正如作者判断的那样,从提交的评估中可以清楚地看出,AlphaFold 带来的进步将对结构生物学和更广泛的生命科学研究产生变革性的影响。没什么新鲜的,因为我们已经在研究中看到了这种转变。
蛋白质-肽复合物的预测
上面引用的预印本表明,AlphaFold 2 确实适用于蛋白质之间的复合物建模。这篇预印本评估了一个更具体的问题,即它是否也可以模拟折叠良好的“规则”蛋白质和短的、大部分无序的肽之间的复合物。为此,作者从蛋白质-肽复合物的 PepBDB 数据库中获取条目,获得它们的氨基酸序列,并在没有模板的情况下运行 AlphaFold 2(这很重要,因为参考结构都可以在 PDB 获得)。
这项工作发现,总的 AlphaFold 2 预测结合结构相当好,超过一半的情况具有良好的准确性,其中相当一部分实际上非常准确。不过,我在这里发现了一个警告:尽管作者为此放弃了模板的使用,但众所周知,AlphaFold 2 对蛋白质数据库有点“烂熟于心”。这意味着,如果你给它一个序列,它的结构在 PDB 中已经存在,它可能能够非常精确地恢复它,甚至不需要任何模板信息。事实上,一些非正式报告和 Deepmind 的论文本身表明,在输入比对中有大量序列时,模板信息变得不那么重要,并且在许多情况下可以忽略,而不会损害预测质量。
https://www.biorxiv.org/content/10.1101/2021.07.27.453972v2.abstract
致力于开发蛋白质对接方法的重要团体也在开发 AlphaFold 来辅助他们自己的方法。例如,在这里,这份预印本结合了作者自己的方法 ClusPro 来重做 AlphaFold 的蛋白质-蛋白质复合物模型,然后使用 AlphaFold 来完善这些模型:
https://www.biorxiv.org/content/10.1101/2021.09.07.459290v1
这项其他工作探索了如何调整输入序列比对和模型识别,以改善 AlphaFold 2 对蛋白质-蛋白质复合物的预测:
https://www.biorxiv.org/content/10.1101/2021.09.15.460468v2
这另一份预印本也探索了使用 AlphaFold 来模拟蛋白质-肽复合物:
https://www.biorxiv.org/content/10.1101/2021.08.01.454656v1
预测折叠结构不同于预测折叠路径
AlphaFold 2 出来的时候说了很多,说它“解决了蛋白质折叠问题”。对于我们这些研究蛋白质的科学家来说,显然不是。一件事是蛋白质折叠后获得的结构,另一件事是蛋白质获得折叠结构的机制。回想一下,蛋白质通过从伸展、灵活的状态折叠到自身上(有时也折叠到其他蛋白质上)来采用它们的 3D 结构。
这篇预印本将包括 AlphaFold 2 在内的最先进的蛋白质结构预测方法产生的途径与实际折叠途径的实验数据进行了比较。这种比较很棘手,因为折叠数据很少给出原子随时间的位置;相反,大多数数据是关于蛋白质折叠时蛋白质的氨基酸暴露在溶剂中多长时间(蛋白质折叠时氨基酸受到保护,不受溶剂影响,因为它们形成接触并被埋在蛋白质内部)。然而,这些数据得到了基于物理学的蛋白质折叠模拟的补充,蛋白质折叠受到已知结构的限制。简而言之,这项工作发现,至少对我来说不奇怪,当前的蛋白质结构预测方法不能产生正确的折叠路径,即使当它们的最终折叠结构高度准确时也是如此:
https://www.biorxiv.org/content/10.1101/2021.09.20.461137v1.abstract
摘自《分子生物学杂志》的一期特刊
著名的分子生物学杂志上的特刊文章讨论了 AlphaFold 2 和相关人工智能技术应用于生物学的重大进展的影响,以及科学家如何在这些进展的基础上进行发展。生物学不同领域的科学家讨论了各种问题,并达成共识,即 AlphaFold 将影响(我想说它已经影响)生命科学研究的方式。蛋白质结构的模型在有信心的时候总是有用的,所以像 AlphaFold 那样增加模型的信心只会产生影响。
本期的许多文章根本不是关于 AlphaFold 的,但提供了有趣的观点,说明结构生物信息学、蛋白质设计、蛋白质动力学、蛋白质折叠和蛋白质生物物理学领域的主要研究人员如何看待这些方法和一般机器学习正在带来的革命:
https://www.sciencedirect.com/science/article/pii/S0022283621004642
我在这里只评论我特别感兴趣的文章,这些文章与机器学习有更多的关系,但是我建议你访问上面的链接了解更多。
在的文章中,身兼多职的蛋白质科学家 Alan Fersht 就机器学习如何影响他的研究领域(广义而言,即蛋白质生物物理学)给出了个人观点。当他开始工作时,计算机还是一种奢侈品,蛋白质数据库之类的东西甚至还不存在,阅读他的观点尤其有趣。此外,他非常了解蛋白质生物物理学和结构生物学的故事,他的文章始于 1968 年,当时 3D 蛋白质结构的建模是基于使用已知结构作为模板开始的(“同源建模”)。那时,计算机科学发展迅速,机器学习领域开始发展,甚至没有想象过半个世纪后计算机能够在没有模板的情况下预测蛋白质结构,而是针对“更简单”的问题,如与人类玩游戏。大约在同一时间,提出了蛋白质折叠途径的问题,这一问题目前基本上没有解决(正如上面的一篇预印本中所述,即使机器学习方法可以正确预测折叠结构,它们也无法解释蛋白质如何折叠成这样的结构)。事实上,Fersht 论文围绕的主题是计算机程序是否能够预测蛋白质折叠路径,并有助于澄清哪些原则控制蛋白质如何折叠。
Dill group 的另一篇文章更详细地回顾了蛋白质折叠问题,这是如何由球状蛋白质的第一个实验结构设定的,以及早期生物物理学家如何进行其研究,首先通过聚合物理论来模拟无序和有序结构之间的转变,然后转向坍塌和折叠漏斗的理论。这篇综述没有涉及用于结构确定的机器学习,但它是任何蛋白质生物物理学新手的必读之作,因为它还讨论了无序蛋白质状态的性质,为什么折叠是快速和定向的,多蛋白质关联,天然样和基于纤维的聚集,蛋白质装配,以及 p hase 分离(可能是当今蛋白质生物物理学最有趣的话题)以及其他主题——一切都具有有趣的理论和历史视角。
与上面评论的文章相关,该期的其他论文专门致力于蛋白质无序和聚集的问题,其中一篇专门谈到了机器学习方法如何帮助揭示无序蛋白质的蛋白质序列、结构、动力学和功能之间的关系。其中,文章回顾了直接从序列推断蛋白质特征的方法,例如相互作用基序、功能和无序;此外,它还回顾了机器学习如何帮助预测蛋白质-蛋白质相互作用(在本文前面有很多介绍),以及为分子模拟参数化力场,解释实验数据等。
本期的两篇有趣论文讨论了(膜)蛋白质设计(此处和此处),今天它严重依赖于实验工作和计算机辅助设计,但不太使用机器学习方法,然而该领域预计将受到它们的影响,特别是生成网络——并提供了一些例子。
另一篇有趣的文章提到了蛋白质预测方法可以帮助解决的一个非常重要的问题,特别是现在它们越来越准确:预测基因变异的功能效应。在他们的文章中,Diwan 等人讨论了 AlphaFold 的预测和结构在帮助预测表型遗传变异中的作用。在效用的极端情况下,人们想要预测的事情是什么突变(基因变异)导致疾病(表现型),为什么会这样,以及我们如何补偿这些影响。这篇论文的一个重要亮点是,遗传变异所在的蛋白质的结构,无论是预测的还是实验的,通常都不足以理解这种变异如何与观察到的表型相关。为了从基因型完全预测表现型,我们需要了解结构、动力学、折叠途径、复合物、与其他分子的相互作用,以及可能其他我们不怀疑的方面。
其他评估和潜在应用概述
- 这份预印本表明,AlphaFold 的预测或参数都不能作为突变后蛋白质稳定性变化的代理。虽然这是意料之中的,但还是值得一探:【https://www.biorxiv.org/content/10.1101/2021.09.19.460937v1
- 另一篇预印本中的工作开发了一种从固定骨架设计蛋白质的方法,利用了 AlphaFold 的预测能力。对于几个设计,作者证明了 AlphaFold 预测的结构与所需的主链一致,表明 AlphaFold 和类似的方法可以促进一系列新的和精确的蛋白质设计方法的发展——即使用一个程序来预测将获得所需折叠的氨基酸序列:【https://www.biorxiv.org/content/10.1101/2021.08.24.457549v1】T4
- 这份预印本评估了 AlphaFold 2 可以如何准确预测膜蛋白,这是一个重要的问题,因为该程序没有任何针对这种类型蛋白质的规则。他们的发现是预测是杰出的:https://www.biorxiv.org/content/10.1101/2021.08.21.457196v1尽管考虑到在 CASP14 中已经有一些膜蛋白靶点是很重要的。
进一步的注释和阅读
(与我之前的故事相关的新论文用粗体标出)
在一个非常特殊的应用中使用 AlphaFold 对某些卵壳蛋白质建模的示例:https://onlinelibrary.wiley.com/doi/full/10.1002/mrd.23538
与特别比对互补的 AlphaFold 用于锥虫和利什曼原虫寄生虫https://www.biorxiv.org/content/10.1101/2021.09.02.458674v1的模型蛋白的实例
AlphaFold 2 的原文,以防你没看过:https://www.nature.com/articles/s41586-021-03819-2
最初的 EBI-Deepmind 论文展示了 21 个蛋白质组的模型数据库:https://www.nature.com/articles/s41586-021-03828-1
deep mind 的一篇新论文,解释了他们在 CASP14 期间到底是如何使用 AlphaFold 2 的:https://onlinelibrary.wiley.com/doi/10.1002/prot.26257注意,团队作为一个人类群体参与,因为他们执行了专家驱动的干预。基于他们在这个过程中学到的东西,他们可以完善最终的全自动程序,我们今天都知道。
RoseTTAFold,大概几乎和 AlphaFold 2 一样好,尽管还没有在任何 CASP 中进行基准测试:https://www.science.org/doi/full/10.1126/science.abj8754
EMBL/EBI 发布关于蛋白质宇宙建模:https://www . embl . org/news/science/alpha fold-potential-impacts/
关于 ColabFold 的主要预印本,能让你轻松使用 AlphaFold 2 和 Rosetta fold:https://www . bior XIV . org/content/10.1101/2021 . 08 . 15 . 456425v 1 . abstract
喜欢这篇文章,想给我提示?[Paypal]-谢谢!
我是一个自然、科学、技术、编程和 DIY 爱好者。生物技术专家和化学家,在潮湿的实验室和计算机里。我写我广泛兴趣范围内的一切,其中一部分包括交流科学。查看我的 列表 了解更多故事。 成为媒介会员 访问我和其他作家的所有故事, 订阅通过邮件获取我的新故事 (平台原创附属链接)。*
基于 AlphaFold 的数据库和成熟的,易于使用的,在线 AlphaFold 界面准备彻底改变生物学
原文:https://towardsdatascience.com/alphafold-based-databases-and-fully-fledged-easy-to-use-alphafold-interfaces-poised-to-baf865c6d75e?source=collection_archive---------15-----------------------
不仅有计算还有实验生物学。对生物学中数据科学领域未来的思考。
在最近的一篇 故事 中,我报道了描述 AlphaFold 第二版及其源代码的学术论文的发布,我向你展示了世界各地的科学家如何开始通过谷歌 Colab 笔记本将该程序应用于他们喜爱的蛋白质,免费且不需要任何硬件。这些笔记本正在迅速发展,以实现更多的功能,允许任何人不仅模拟分离的蛋白质,还模拟多种蛋白质的复合物,并包括相关蛋白质的已知结构和多序列比对,以改善程序的结果。此外,Deepmind 和欧洲生物信息学研究所开始上传“所有”蛋白质的 AlphaFold 计算模型,已经覆盖了 20 个完整的生物体,并可供免费下载。尝试该程序和模型数据库的科学家在 Twitter 上报告了几个成功的故事,这些故事预测了这些和相关技术将如何扰乱结构生物学领域。不仅是计算性的,也是实验性的结构生物学,因为预测的模型促进了蛋白质结构的实验测定。
在上周发表的这篇文章中,我在《自然》杂志的一篇同行评审文章中报道了 AlphaFold 2 的正式发布细节,这是一个由谷歌的 Deepmind 开发的赢得 CASP14 的结构预测程序,以及它在 GitHub 中的代码。我还向您展示了尽管这个模型非常庞大,它对其他库和硬件需求的复杂依赖性,但由于一些非常善良的科学家开发的 Google Colab 笔记本,世界各地的科学家已经在网上运行这个程序。但是在这个时代,历史揭开的速度非常快,所以自从我的上一篇文章以来,许多额外的令人兴奋的消息出现了。
在快速回顾了什么是蛋白质,为什么生物学家对了解它们的结构感兴趣,它们如何通过实验确定或由计算机预测,以及 AlphaFold 2 如何工作之后,我开发了突发新闻:增强的 Colab 笔记本,展示了 AlphaFold 最先进的功能,一个不断增长的免费模型数据库,由 AlphaFold 2 为从测序基因组中已知的所有蛋白质的主要部分预先计算,已经发生的成功应用,以及测试该程序限制的“实验”结果。最后,我讨论了这一切对生物学的未来意味着什么,以及作为 AlphaFold 带来的这些新技术以及导致 Deepmind 掌握它的所有先前学术工作的结果,结构生物学和生物信息学的哪些利基可能会蓬勃发展。
目录
- 背景:蛋白质,为什么生物学家有兴趣知道它们的结构,结构如何通过实验确定或通过计算机程序预测,AlphaFold 2 如何工作——如果你已经熟悉蛋白质结构和 AlphaFold,跳过这个。**
- 增强的 Colab 笔记本,展示了充分利用 AlphaFold 所需的功能:多重序列比对、相关蛋白质的已知结构和寡聚化状态。
- 挑战极限:AlphaFold 非常好,它可以做一些它甚至可能没有设计到的事情,但它也陷入了一些长期存在的问题
- Deepmind 和欧洲生物信息学研究所联手,用 AlphaFold 2 计算“所有”蛋白质的蛋白质模型。20 种生物的模型已经可以免费下载
- alpha fold 2 及相关技术的一些具体成功应用
- 生物学和数据科学的未来在生物学内部的利基,以及对机器学习科学本身的影响
- 链接并进一步读作
背景:蛋白质,为什么生物学家对了解它们的结构感兴趣,结构如何通过实验确定或由计算机程序预测,以及 AlphaFold 2 如何工作
简而言之,蛋白质是由多个氨基酸组成的线性链,每个氨基酸由 4 个非氢原子的恒定单元和一个大小可变的侧链组成,从无到约 20 个原子不等。氨基酸通过称为骨架的恒定单位连接,形成不再保持随机而是获得一种或多种空间排列的多肽。也就是说,它们折叠成 3D 结构。蛋白质在 3D 中将采用什么样的确切结构基本上取决于氨基酸侧链的同一性,即其氨基酸序列。非常简单和简化的定义是非常复杂的,氨基酸序列由基因编码;一个生物体的基因集合就是它的基因组;基因组中编码的蛋白质的集合就是蛋白质组。
更准确地说,这一点在后面会很重要,多肽实际上可以折叠成多个亚结构,每个亚结构称为一个结构域。(原则上,AlphaFold 掌握的是这些域,而不一定是整个蛋白质——因为这主要是 CASP 跟踪的内容。)此外,某些蛋白质或蛋白质区域实际上不会折叠成明确的 3D 结构,而是保持“无序”。无序区域可以很小,连接折叠良好的结构域,或者很长,这反过来可能有一些生物学相关性(大多数情况下)或没有;此外,有些蛋白质完全是“内在”无序的。我知道,对于非生物学家来说,所有这些都超出了蛋白质和蛋白质结构的经典定义,但是对于本文后面的讨论来说,这些都是很重要的。不仅预测蛋白质的结构,而且预测它们的无序区域和蛋白质如何移动,都是现代结构生物信息学的关键。
具有不同程度的无序和有序域的蛋白质的例子,以及人们应该期望像 AlphaFold 这样的当前程序合理地预测什么。图片作者。
为什么生物学家想知道蛋白质的结构?正如在我的另一个故事的引言中简要提到的,了解蛋白质的结构有助于推进生物技术和制药。药物是结合到蛋白质结构中特定口袋的小分子,以积极的生理结果调节它们的结构。例如,一个小分子可以瞄准一种控制细胞分裂的蛋白质来攻击癌症。另一个小分子可能会干扰细菌的基本蛋白质,从而杀死它。这样的例子不胜枚举。了解蛋白质的结构也有助于我们了解它是如何执行其功能的,因此我们可以改变它(通过在编码基因中引入突变)以适应它在一些生物技术过程中的用途,如发酵、油脱胶等。
我们可以很容易地对基因和整个基因组进行测序,但从氨基酸序列到实际的 3D 结构并不简单。在最好的情况下,当生物学家想要知道一种新蛋白质的结构时,他们可以检查类似序列的其他蛋白质是否已经解决了它们的结构(蛋白质数据库是一个免费的数据库,学者可以在其中存放和找到所有实验确定的结构)。如果没有已知的结构可用于通过同源性可靠地模拟新蛋白质,那么有两个主要选择:要么尝试新蛋白质的实验测定,要么应用不依赖于已知结构同源性的预测方法。在大多数情况下,实验性的结构测定是乏味的、昂贵的和劳动密集型的,并且经常失败。有三种主要的技术可以通过实验来解决蛋白质结构:蛋白质晶体的 X 射线衍射,这需要你的蛋白质产生良好衍射的晶体,核磁共振光谱学在可处理的大小和溶液条件方面有严重的限制,冷冻电子显微镜学发展非常迅速,但仍然非常局限于相当大的、明确定义的蛋白质或复合物,对于许多蛋白质来说,它还不能产生原子分辨率,而只是一些原子密度的斑点。另一方面,在没有任何已知结构的同源蛋白的情况下预测或“建模”蛋白质结构是(或有点“曾经是”)一个极其困难的问题,现在这变得更加容易,这不仅要感谢 AlphaFold,还要感谢在它之前的几项技术。
在没有相关蛋白质的已知结构的情况下预测蛋白质结构的领域是 CASP 追踪了超过四分之一世纪的领域。你可以在我上周的故事中看到,在很长一段时间里,这些预测都相当糟糕,直到检测氨基酸对之间接触的方法被引入,帮助指导蛋白质模型的折叠。这些方法本质上利用了与正在研究的序列相似的序列比对,寻找一起变化的氨基酸对,并推断共变何时反映了两个氨基酸在 3D 结构中接触。这是由 CASP11 和 12 完成的,然后对于 CASP13,一些学术团体和 Deepmind 通过机器学习模型重新路由了类似的基于比对的分析,以预测残基之间的接触以及距离和方向,这有助于更好地约束折叠蛋白质模型。然后在 CASP14 中,许多团队推进了这一点,获得了一些预测能力,但 Alphafold 2 通过几个新颖的想法解决了这个问题。虽然细节在他们的论文中,但对我来说,它最有趣的成分是(I)他们如何处理输入序列比对和相关蛋白质的已知结构的新方法;(ii)它们代表网络内蛋白质折叠问题的事实,即它们不像所有学者通过 CASP14 甚至 AlphaFold 1 通过 CASP13 所做的那样使用外部折叠;事实上,从序列或比对输入到 3D 模型输出的一切都在一个单一、巨大、端到端可区分的网络中流动。
蛋白质结构如何在进化过程中诱导氨基酸之间的相关性,建模程序可以根据从蛋白质数据库等大型数据库中学习到的有关蛋白质结构的知识,推断出驱动折叠甚至更复杂的几何特征的联系。图片作者。
增强的 Colab 笔记本,揭示了 AlphaFold 最大限度利用它所需的功能:多序列比对、相关蛋白质的已知结构和寡聚化状态。
正如我在之前的故事中所讨论的,AlphaFold 2 模型非常庞大,许多研究人员担心他们手头永远无法拥有运行它所需的硬件资源。然而,在发布后不到一周,一些很酷、很友好的科学家推出了谷歌 Colab 笔记本,任何人只要有一个谷歌账户,就可以运行 AlphaFold 最喜欢的蛋白质序列。早期的笔记本非常简单,只允许对单个蛋白质链进行建模,毕竟这是 AlphaFold 的设计目标,主要在最受欢迎的 CASP 赛道上进行测试。但很快,科学家们开始在笔记本上添加更多 AphaFold 的功能,这样用户现在就可以完全控制和输入任何蛋白质。
主要增加了两个对 AlphaFold(以及任何其他现代结构预测程序)的良好运行非常重要的功能。一种是从输入序列中计算多序列比对的可能性,输入到程序中,以便从中提取结构信息。CASP12 显示,可以找到更多序列的蛋白质平均起来建模更好。CASP13 显示了相同的趋势,但也发现程序可以用更少的序列工作。CASP14 表明,程序可以使用更少的序列,但它们(包括 AlphaFold 2)仍然需要它们来进行高质量的预测。在早期的 Google Colab 笔记本中,用户使用单个输入序列运行程序,根本没有比对。这通常导致中等质量到差的模型,如 LDDT 图所示(其预测每个氨基酸的模型的预期质量)。用户也可以提供他们自己的比对,但是用于结构预测的良好比对有一些特殊的要求。新的 Colab 笔记本考虑到了这一点;此外,他们利用一些为此而优化的特别方法,在加起来超过 2000 万个序列的多个数据库中搜索蛋白质序列。
第二个非常重要的补充是可以找出“模板”,即可能与想要建模的蛋白质具有相同结构特征的蛋白质的实验结构,并将这些模板传递给 AlphaFold。这当然对建模非常有帮助,直到最近,基于这种同源性的建模是保证某些成功的唯一方法。模板和目标的相似度越高越好。当然,对于许多目标来说,没有好的结构可以用作模板。
最好的 Colab 笔记本是谢尔盖·奥夫钦尼科夫、马丁·施泰因格、米洛特·米尔迪塔和闵京白的这两本:
https://colab . research . Google . com/github/so 氪/colab fold/blob/main/alpha fold 2 . ipynb
https://colab . research . Google . com/github/sokrypton/colab fold/blob/main/alpha fold 2 _ complex . ipynb # scroll to = g-rpnoxdjf 18
除了构建序列比对和使用模板的选项之外,该笔记本还包括两个额外的有趣功能:通过分子模拟进行最终优化的可能性,以及一起模拟蛋白质多个拷贝的可能性。前一个特性对于优化小问题很重要,只有当模型看起来已经相当可靠时才有意义。当你知道或怀疑你的蛋白质实际上可能是寡聚体时,对蛋白质的多个拷贝一起建模的选项是有意义的,正如我在下一节中描述的。
为了完成这款 Colab 笔记本的简短描述,它提供了 5 个模型和一个预测质量评估图,所有这些都可以轻松下载。虽然这款笔记本可能会有一些改进和一些进一步的扩展,但我认为主要的新有趣功能将来自科学家们正在测试 AlphaFold 2 极限的不同测试。
位于的 Google Colab 笔记本 https://Colab . research . Google . com/github/sokrypton/Colab fold/blob/main/alpha fold 2 . ipynb图片由作者提供。
挑战极限:AlphaFold 非常好,它可以做一些它可能甚至没有设计到的事情,但它也遇到了一些长期存在的问题
科学家们很快开始测试这个程序的极限,强迫它做出预测,原则上它不太可能完成得很好。令人惊讶的是,这些测试的一些结果是非常积极的!
首先,从 CASP14 评估中已经知道(我提醒你这是盲目的,独立于做结构预测的人),AlphaFold 不仅可以正确折叠组成蛋白质的单个结构域,还可以正确折叠它们的相对排列。也就是说,它可以得到正确的整体结构,至少对于结构良好的蛋白质来说是如此,对于这些蛋白质,可以建立大的比对,并且对于类似的蛋白质,一些实验结构是可用的。CASP14 评估还发现,AlphaFold 2 不仅可以正确模拟蛋白质的主链,还可以正确模拟氨基酸侧链。从历史上看,这个问题非常困难,以至于 CASP 过去基本上只评估主链,但到了 CASP13,当我还是评估员时,很明显顶级程序(包括 AlphaFold 1 和一些学术程序)在建模主链方面非常出色,侧链也应该考虑在内。现在对于大多数目标蛋白,AlphaFold 2 很好地模拟了侧链。
接下来,这是由几位自己运行 AlphaFold 2 的科学家报告的,该程序似乎在预测两个或更多蛋白质形成的复合物方面取得了巨大的进步。在生物学中,这种复合物对于蛋白质之间传递信息是必不可少的,并且在许多情况下,因为真正的功能单元是多个蛋白质的组装体,如果将其分离,则不会执行任何功能。有些人甚至在没有伴侣的情况下也不稳定。蛋白质复合物有两种主要类型:由同一分子的多个拷贝组成的所谓同源寡聚体,以及由两种或多种不同蛋白质组成的异源寡聚体。CASP 有一个专门研究复杂事物的专门轨道,历史表明这仍然是一个非常困难的问题——当然,许多人正在研究这个问题。甚至还有另一个专门针对蛋白质复合物预测的比赛,叫做 CAPRI,在那里我不会惊讶很快就会看到 Deepmind 也参加比赛。
更具体地说,科学家们发现,如果他们将两个连接的蛋白质序列输入 AlphaFold 2,那么它很有可能会返回相当合理的复合物。这绝不是小事,而且已经研究了好几年,原因有二。一个是串联蛋白质意味着在整个输入多序列比对中串联它们,这本身不是一件容易的事情。第二,蛋白质对之间的共同进化信号确实存在,但它们通常较弱,对于同源寡聚体来说,分子间信号(包含两个蛋白质复合物的信息)很难从分子内信号(包含每个蛋白质如何折叠的信息)中分离出来。
我刚刚告诉你的所有这些目前仍然是轶事,只是在 twitter 上,没有同行评议,但越来越多的成功蛋白质复合物预测的案例出现了。我敢肯定,现在一些团体在更大的范围内对此进行了进一步的基准测试,我们将很快看到一项同行评审工作评估 AlphaFold 预测复合物的能力。
两种不同蛋白质形成复合物,即异二聚体的例子。图片作者。
AlphaFold 2 还不能模拟哪些结构特征?这当然也很重要。首先,它可以很好地模拟短无序环,这些环连接折叠良好的域内的结构化片段,或者连接单独的域。但是它根本不能模拟更长的循环,所以最好不去做预测,特别是当它们是终点的时候。毕竟,仅从序列中很容易识别出长的无序区域。好的一面是 LDDT 图很好地预测了这些环是不准确的。时刻关注 LDDT 的情节。
谈到 LDDT,重要的是要记住,这是一个相当局部的模型质量估计。这是非常重要的,因为序列上相距较远的两个区域可能具有较高的 LDDT 分数,表明这些氨基酸可能具有良好的品质,但它们的相对方向和距离却完全不同。在我自己的测试中,我看到当一个寡聚蛋白质被建模为单体时,这种情况尤其会发生。如果程序被告知蛋白质是单体的,它当然会试图通过使单体变形来满足所有接触和短距离限制。因此,模型的整体形状将是错误的,即使每个氨基酸的 LDDT 估计值相当高。一个新的实验将有望解决这个问题,该实验表明在预测中必须包含多少个蛋白质拷贝。
我见过的另一个问题是蛋白质,它们大部分是水溶性的,但含有跨膜元素。膜是脂质的层状排列,脂质不喜欢水,所以它们自我组装成膜,以隐藏自己不接触水。一些蛋白质只存在于整合到膜中,这些蛋白质大多被很好地模拟了。其他人完成他们在解决方案中的角色;这些也大多建模正确。但其他的是可溶的,但有小分子,通常是螺旋的,插入膜中。在我所做的测试中,这种螺旋往往会产生α折叠问题,显然是因为它试图将它们与折叠部分打包在一起。不知何故,这并不全是错的,因为如果蛋白质在溶液中,没有任何膜可以结合,这种元素可能会这样做!现实实际上更复杂,因为这种情况通常使蛋白质变得难以处理,所以实验人员无法解决这些类型蛋白质的完整结构;相反,在这些情况下,他们只解决了可溶域的结构。
我所看到的报道和我自己看到的另一个问题是对蛋白质数据库中可用的 3D 排列的强烈偏见。这完全没问题,因为 AlphaFold 是在这个数据库上训练出来的,每个谨慎的、有知识的用户可能都会意识到这些限制。到底是什么问题?嗯,许多蛋白质结合更小的分子甚至元素离子作为它们正常功能的一部分,为此它们采用不同的结构。通常,结合了小分子或离子的结构更稳定,所以这是蛋白质数据库中的最后一个。另一个分子可以用其他实验方法研究,这些方法不能给出原子的细节,但通常可以揭示小分子束缚态和自由态之间的实质性差异。当你训练一个模型来预测结构时,它最有可能预测这种状态,因为这是它所知道的,即使你只提供了一个序列,并没有表明任何离子或小分子被束缚。事实上,无论是 AlphaFold 还是任何其他结构预测程序都没有为“结合的相关小分子”提供输入字段。同样,如果多种选择没有在蛋白质数据库中得到反映,他们也不会考虑任何其他来源的结构可变性。我看到人们在 Twitter 上讨论 AlphaFold 2 的一个典型例子是结合金属离子的蛋白质,比如铜或锌:参与结合离子的氨基酸通常只以结合形式存在,但以未结合形式存在。一位用户感到惊讶的是,AlphaFold 预测了离子结合形式,尽管它没有提供任何关于结合离子的信息。这是完全可以预料的,因为对于这种蛋白质,蛋白质数据库主要由离子结合形式控制,因为游离形式通常很难表征。
这一节对局限性的总结是明确的:用户仍然需要了解他们的化学和生物学,并使用它们来解释一个模型正在讲述什么新的东西,什么部分是可以信任的,以及为什么它正在讲述它正在讲述的东西。这就是为什么像任何其他蛋白质模型一样,查看质量评估和程序使用的模板和比对是必不可少的,当然要时刻记住关于蛋白质的已知信息。
Deepmind 和欧洲生物信息学研究所联手用 AlphaFold 2 计算“所有”蛋白质的蛋白质模型。20 种生物的模型已经可以免费下载。
对于生物学家来说,最新的消息是 Deepmind 和欧洲生物信息学研究所共同努力,试图对所有已知基因组的所有蛋白质进行建模。这意味着大约 2000 万个结构模型,其中 350,000 个来自人类和 20 个其他物种。这意味着减少运行程序的时间和不需要专业知识(尽管 Colab 笔记本已经使它变得非常容易!).
这些模型可以在 https://alphafold.ebi.ac.uk/免费获得。对于那些蛋白质组已经被处理过的生物,在 https://alphafold.ebi.ac.uk/download 的有直接的下载链接。用户可以通过各种关键字搜索数据库,从自由文本到生物学中广泛使用的蛋白质标识符。但对我来说,最好的工具是允许你在 https://www.ebi.ac.uk/Tools/sss/fasta/通过比较氨基酸序列来搜索模型。为什么?因为您感兴趣的确切蛋白质可能尚未建模,但可能有一个高度相似的模型,您可以使用它通过同源性轻松地对您的蛋白质建模。
该数据库提供的模型的一个重要注意事项是,它们都是基于假设的单体状态,我已经看到这在许多我知道是二聚体、三聚体等的蛋白质中引起问题。AlphaFold 没有办法知道(或者猜测)这个。也许 Deepming + EBI 提供假设不同寡聚化状态的模型会很好?目前,你最好运行低聚物的计算,以补充 EBI 提供的。同样,如上所示,运行偏向于产生类似于蛋白质数据库中已经存在的模型;这意味着,如果你输入一个蛋白质的序列,该序列只在配体结合的实验表征中是稳定的,你将最有可能得到一个对应于这种形式的模型,即使严格地说你想单独对蛋白质建模。在完成这篇文章后,我发现 EBI 确实强调了所有这些限制,他在 https://www . ebi . AC . uk/about/news/opinion/alpha fold-potential-impacts 中写道
左图:位于 https://alphafold.ebi.ac.uk/[的 AlphaFold-EBI 门户网站。右图:作者在](https://alphafold.ebi.ac.uk/)https://www.ebi.ac.uk/Tools/sss/fasta/图片上通过蛋白质序列匹配搜索 AlphaFold 模型的工具。
alpha fold 2 及相关技术的一些具体成功应用
使用通过机器学习方法处理的比对和模板的结构预测方法的浪潮已经在 CASP 的早期版本中给出了一些实际的惊喜,但是 AlphaFold 2 在 CASP14 中垄断了这些情况。也就是说,这些模型本身有助于完成对实验数据的解释,这些数据正等待着在一个被称为分子置换的过程中被用来完成实验结构测定,在这个过程中,模型草案被用来解释 X 射线衍射数据。一旦完成,就可以对模型(和其他模型)进行最终评估;当然,这个和实验结构非常接近。
类似的报告在 CASP 之外已经有好几年了。例如,在最近的工作中通过实验方法解析的结构基本上依赖于使用学者编写的程序建立的部分模型——在这个过程中为 AlphaFold 1 奠定了基础,有些实际上与它没有太大区别。
另一个已经从这种模型中受益的领域,可能是从 AlphaFold 2 中受益最多的领域,是低温电子显微镜。在这种技术中,获得的主要实验数据实质上是电子密度的 3D 图。当这个分辨率足够高时,特殊程序(使一个长过程变短,但当然它实际上需要大量的人工干预)可以将氨基酸放入其中,并以这种方式获得实验结构。但是与产生的数据量相比,高分辨率地图相对较少。因此,对于通过冷冻电子显微镜检查的大量蛋白质,很难通过氨基酸序列来确定其结构。但有了来自 AlphaFold 等程序的高质量模型,人们可以——快速而肤浅地——简单地将模型放入电子密度图中进行“验证”,最好的情况是将其扭曲一点,以更好地匹配实验数据。这并不是什么新鲜事,这是相当常规的做法,但目前仅限于易于建模的蛋白质。现在,AlphaFold 2 将允许对几乎所有蛋白质应用同样的技巧。此外,冷冻电子显微镜通常对几种蛋白质的组装效果最好,因此 AlphaFold 据称也能模拟它们的能力如果得到证实将非常有用。
而且这些应用只限于结构生物学,即在原子水平上处理结构细节的生物学部分。但获得模型也将直接影响生物学的其他领域,如细胞生物学,在细胞生物学中,即使是蛋白质结构的粗略模型也往往足以解释实验结果并设计新的实验。
生物学和数据科学在生物学领域的未来,以及对机器学习科学本身的影响
AlphaFold 和类似程序的直接影响当然是改进了蛋白质结构建模的方法。正如我在上面的一些例子中所展示的,这绝不是实验结构生物学的终结,因为这些程序中没有一个能够获得足够正确的细节,并且因为它们天生偏向于蛋白质数据库中的可用信息。相反,在上一节中,我指出了从这些程序中得出的模型对实验结构求解有很大的帮助。这意味着 AlphaFold 和其他建模技术绝不会取代结构生物学家,而是让他们的工作变得更简单,让他们专注于更复杂的方面和系统。
21 世纪初有几个基因组项目备受关注,因为他们承诺“破解生命密码”。尽管 DNA 测序和全基因组带来了许多进步,但从结构生物学的角度来看,显然只有这些基因组是不够的。解析结构的时代很快就开始了,但这远不如测序 DNA 有效,也更昂贵。结构基因组学联盟的努力将优先考虑哪些蛋白质对解决结构最重要,试图加快蛋白质数据库的完成速度。现在,相当精确地模拟蛋白质的可能性(假定有足够的信息可用,并且本文中讨论的所有限制加上某些其他限制是肯定的!)使得蛋白质组结构覆盖的梦想变得更加可行。当然,这种成就在一定程度上要归功于结构基因组学项目期间所做的工作,该项目用程序学习的结构数据填充了蛋白质数据库。以及数年来 DNA 测序蛋白质获得的数百万蛋白质序列,现在允许蛋白质建模程序所需的数据丰富的比对。
对结构生物学的影响不仅在于预测蛋白质的结构和辅助它们的实验测定,还在于设计它们,甚至是从零开始。从接触、距离和方向的中间预测预测蛋白质结构的神经网络最近被重新用于优化蛋白质序列以获得给定蛋白质结构的迭代方法。蛋白质设计本身就是一个领域,我推荐这篇综述来了解不同的方法,包括那些基于神经网络的方法。
Deepmind 工作的另一个重大影响可能会更加广泛,并且与 AlphaFold 2 中开发和整合的所有技术有关。正如我已经描述过的,这不是 AlphaFold 1 的改进,而是一个整体的重新设计,包括许多更小的(然而很大!)机器学习和数据科学社区的新工具。从他们的论文来看,这些新的发展包括:
- 一种联合处理序列比对和成对特征的新架构,它也可以应用于处理文本的其他问题。
- 3D 模型的新的输出表示和新的损失函数一起实现完整的端到端结构预测,这可以适用于各种其他问题,也可以将它们重新整形为端到端形式。
- 一种新的注意力结构,帮助在预测问题的不同阶段起关键作用的不同信息部分如何在网络中移动。
- 使用中间损失来实现预测的迭代改进,这有助于程序在运行时以不同的分辨率水平在内部逐步改进模型。
- 与结构联合训练的掩蔽 MSA 损失,这允许它即使在比对没有太多序列时也能很好地执行。
- 从没有实验结构但可以可靠建模的蛋白质序列中学习。我想这是有风险的,但显然成功了。
- 在预测结构的同一个网络中计算的自我精度估计。精确度的估计应该有益于神经网络在所有领域的应用!
这些新的“小”发明和对现有神经网络组件的改进中的每一个都可能用于生物学的其他问题,以及更广泛的计算机科学。Deepmind 表示,他们正在致力于改善蛋白质复合物的预测以及小分子结合,这些都是生物学中关键的、仍未解决的问题。他们已经在生物学和临床的许多其他领域开展工作,例如在医学图像中自动检测肿瘤,这只是一个例子。
学者们比以往任何时候都更热衷于将这些新想法应用到其他问题上。蛋白质结构预测之外的化学和生物学领域包括预测突变对疾病的影响,自动解释人类书写的文本以注释到数据库中,自动图像分析以检测、定界、提取和识别对象,更好的化学计算自动化,等等。因此,我们可以预计,在不久的将来,用于构建 AlphaFold 的技术可能会对科学和工程的许多领域产生影响,并激发影响。
链接和进一步阅读
- 一个关于 AlphaFold2 与调用一流的序列比对生成器 MMSeqs2 相结合的后续故事,让用户在简单的 Colab 笔记本上充分利用这项技术:https://towards data science . com/the-hype-on-alpha fold-keep-growing-with this-new-preprint-a 8 C1 f 21d 15 c 8
- 我在 AlphaFold 2 上的第一个故事,以及科学家们如何在 Google Colab 上运行它
- 我正在使用的用于单体和同低聚物的 Colab 笔记本:https://Colab . research . Google . com/github/so 氪/Colab fold/blob/main/alpha fold 2 . ipynb
- 你正在使用的用于异二聚体的 Colab 笔记本:https://Colab . research . Google . com/github/so 氪/Colab fold/blob/main/alpha fold 2 _ complex . ipynb # scroll to = g-rpnoxdjf 18
- 官方 Deepmind 笔记本(截至 2021 年 7 月未使用相关蛋白质的可用结构):https://colab . research . Google . com/github/deep mind/alpha fold/blob/main/notebooks/alpha fold . ipynb
- https://alphafold.ebi.ac.uk/ EBI 的 AlphaFold 2 车型:(见文中其他链接)
- Mohammed AlQuraishi 在 Nature 论文发布后的博客文章:https://moalquraishi . WordPress . com/2021/07/25/the-alpha fold 2-method-paper-a-fount-of-good-ideas/
- 卡洛斯·奥特拉尔在《自然》杂志论文发布后的博文:https://www . blo pig . com/blog/2021/07/alpha fold-2-is-here-whats-behind-the-structure-prediction-miracle/
- AlphaFold 2 的纸张和代码
- Deepmind 关于人类蛋白质组的新论文被 EBI《自然》杂志的 AlphaFold 覆盖
喜欢这篇文章,想给我提示?【https://www.paypal.me/LAbriata】-谢谢!
我是一个自然、科学、技术、编程和 DIY 爱好者。生物技术专家和化学家,在潮湿的实验室和计算机里。我写我广泛兴趣范围内的一切。查看我的 列表 了解更多故事。 成为媒介会员 访问我和其他作家的所有故事, 订阅通过邮件获取我的新故事 (平台原创附属链接)。
Altair:Python 中的交互式数据可视化变得简单
原文:https://towardsdatascience.com/altair-interactive-data-visualizations-in-python-made-easy-7f002336b692?source=collection_archive---------35-----------------------
在几分钟内实现 S&P500 的交互式可视化,结果令人惊叹
罗汉 G 在 Unsplash 上的照片
数据可视化帮助我们理解大量杂乱的表格数据。作为数据科学的首选语言,Python 有几个优秀的数据可视化库。其中之一是牛郎星,今天你将学习它的基础知识。
作为一名数据科学家,数据的可视化表示是必须的,尤其是在向不太懂技术的观众展示数据和见解时。你还应该注意你的可视化的美感,这就是 Altair 的亮点。您可以轻松制作令人惊叹的交互式图表,这是使用 Matplotlib 不容易实现的。
Altair 还可以用于构建和部署交互式报告。本文解释了如何:
今天的文章结构如下:
- Altair 安装和数据集介绍
- 牛郎星基础—简单面积图
- Altair 的基本款式
- Altair 的高级风格—渐变
- 添加交互性
- 保存图表
- 最后的话
Altair 安装和数据集介绍
您可以像安装任何其他 Python 库一样安装 Altair。我们将它安装在一个名为altair_env
的独立虚拟环境中,基于 Python 版本。
Numpy 和 Pandas 是 Altair 的依赖,不用手动安装。如果您使用的是 Anaconda,下面一组 shell 命令将设置环境,激活它,并安装所有需要的东西:
conda create — name altair_env python=3.8
conda activate altair_envconda install -c conda-forge altair altair_saver
conda install -c anaconda pandas-datareader
conda install jupyter jupyterlab
厉害!您现在可以启动 Jupyter Lab 并创建一个新的空笔记本。
在开始可视化之前,我们还需要一些数据。您可以使用pandas_datareader
库下载历史股票数据。以下代码片段下载 S & P500 指数的数据,将其重新采样为月平均值,并将值四舍五入到小数点后两位:
下面是前几行的样子:
图片 1-S&P500 索引数据集的头部(图片由作者提供)
这就是我们开始的全部内容。接下来让我们做一个基本的牛郎星可视化。
牛郎星基础—简单面积图
可视化时间序列数据的一种优雅方式是使用面积图。简单的折线图就可以了,但是面积图将用户体验带到了一个新的层次。
用 Altair 做面积图还是挺容易的。mark_area()
函数就是这样做的,并且可以接受多个参数。其中之一是line
,您可以在其中指定顶部线条的外观。我们将把它漆成漂亮的深蓝色。
要将列名与实际的 X 和 Y 轴连接起来,您必须使用encode()
函数。x
和y
参数现在已经足够了。
以下是完整的代码片段:
这是视觉效果:
图 2-基本牛郎星面积图(图片由作者提供)
你得承认,默认情况下看起来还不错。如果您还没有注意到,右上角的三个点提供了保存图表(SVG 和 PNG)的选项,以及其他一些东西:
图 3 —图表保存/导出选项(作者图片)
我们将在文章的最后探讨储蓄。
接下来,让我们探索一下如何给你的图表添加一些基本的样式。
Altair 的基本款式
我们现在将稍微改变可视化的外观—包括标题、图表宽度和 Y 轴格式。我们将使图表更宽,包括一个标题,这样每个人都知道它代表什么,并将 Y 轴刻度格式化为 USD。
您必须进行以下代码更改:
这是更新后的可视化效果:
图 4-带有基本样式的牛郎星图(图片由作者提供)
马上就好看了。一般来说,增加时间序列图表的宽度可以显著改善外观。如果你有很多数据点,那就更是如此。
接下来,让我们通过添加渐变来使图表看起来更好。
Altair 的高级风格—渐变
我现在不喜欢的一点是区域填充颜色。它和线条颜色一样,只是增加了一点透明度。基于时间序列的面积图之所以吸引人,是因为面积中从一点到另一点的颜色变化(渐变)。
添加渐变颜色需要在mark_area()
函数中添加大量代码,但是这种努力是值得的。我们将使 Y 值越低颜色越亮,越高颜色越暗。
下面是代码片段:
图表现在是这样的:
图 5-带有渐变区域的牛郎星图(图片由作者提供)
好多了。还缺一样东西。你会发现任何好看的在线图表都有一个共同点——交互性。让我们在下面的部分添加它。
添加交互性
没有人喜欢静态图表。添加一个简单的工具提示可以节省用户猜测正确轴值的时间和麻烦——特别是对于一个大的 X 或 Y 范围。
幸运的是,用 Altair 添加工具提示只需要一行代码。您只需在encode()
函数中为tooltip
参数指定一个值。预期值是一个列表,其中包含您希望值包含在工具提示中的列名。
代码如下:
这是视觉效果:
图 6 —带有基本工具提示的牛郎星图表(图片由作者提供)
这比预期的要容易得多,尤其是当你用 Plotly 做很多数据可视化的时候。
最后,让我们探索一下如何将图表保存到本地机器上。
保存图表
您已经了解了如何以 PNG 或 SVG 格式保存图表。altair_saver
库给了你几个额外的选项。但是在使用之前,请将图表的最终版本保存到变量中。这里有一个例子:
太好了!如果您安装了altair_saver
库,您可以将可视化保存为 JSON 和 HTML 格式。方法如下:
这两者都将在您的根目录中立即可用。
*但是 png 和 SVG 呢?*事实证明,您需要安装一些额外的包来以编程方式保存它们。程序相当冗长,文中就不讨论了。参考以下链接获取完整指南。
最后的话
这就是你要做的——从收集历史股票数据到漂亮的交互式可视化,只需要几分钟,几行代码。Altair 需要一些时间来适应语法,但对所有可视化库来说都是如此。
最终,可视化效果看起来比用 Matplotlib 和 Seaborn 产生的效果好得多。
但是 Plotly 呢?嗯,那是另一个话题了。请继续关注我的博客,了解两者之间的详细对比。
感谢阅读。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
https://medium.com/@radecicdario/membership
了解更多信息
- 2021 年学习数据科学的前 5 本书
- 如何用 Cron 调度 Python 脚本——你需要的唯一指南
- Dask 延迟—如何轻松并行化您的 Python 代码
- 如何用 Python 创建 PDF 报告——基本指南
- 2021 年即使没有大学文凭也能成为数据科学家
保持联系
- 在 Medium 上关注我,了解更多类似的故事
- 注册我的简讯
- 在 LinkedIn 上连接
Altair:Python 的统计可视化库(第 4 部分)
原文:https://towardsdatascience.com/altair-statistical-visualization-library-for-python-part-4-9ec970fb12e8?source=collection_archive---------18-----------------------
自定义可视化
艾萨克·史密斯在 Unsplash 上拍摄的照片
Altair 是 Python 的统计可视化库。它的语法清晰易懂,我们将在示例中看到。用 Altair 创建交互式可视化也非常简单。
Altair 在数据转换方面非常灵活。在创建可视化时,我们可以应用许多不同种类的转换。它使得库对于探索性数据分析更加有效。
Altair 系列的前三部分涵盖了以下主题。
- 第一部分:简介
- 第二部分:过滤和转换数据
- 第 3 部分:互动情节和动态过滤
在本文中,我们将看到用 Altair 定制可视化的不同方法。创建信息可视化来展示数据中的底层结构或揭示变量之间的关系是数据科学的关键部分。
同样重要的是让他们看起来漂亮和有吸引力。因此,我们应该花一些时间来定制可视化效果,以获得更好的外观。
我们将使用 Kaggle 上的保险数据集。让我们从导入库和将数据集读入 Pandas 数据帧开始。
import numpy as np
import pandas as pd
import altair as altinsurance = pd.read_csv("/content/insurance.csv")
insurance.head()
(图片由作者提供)
该数据集包含关于保险公司的客户和保险收费金额的一些度量(即特征)。
我们可以创建一个散点图来检查身体质量指数(bmi)和保险成本(费用)之间的关系。吸烟者栏可用于区分吸烟者和不吸烟者。
(alt.
Chart(insurance).
mark_circle().
encode(x='charges', y='bmi', color='smoker').
properties(height=400, width=500))
(图片由作者提供)
所有的 bmi 值都高于 15。因此,如果 y 轴上的刻度从 15 开始,看起来会更好。我们可以使用 scale 属性来调整自定义 y 轴。
(alt.
Chart(insurance).
mark_circle().
encode(
alt.X('charges'),
alt.Y('bmi', scale=alt.Scale(zero=False)),
alt.Color('smoker')).
properties(height=400, width=500))
为了使用 scale 属性,我们用 Y 编码(alt。Y('bmi '))而不是传递一个字符串(y='bmi ')。零参数设置为“假”以防止轴从零开始。
以下是更新后的可视化效果:
(图片由作者提供)
我们还可以使用 domain 参数来指定一个自定义范围。让我们也使用 properties 函数来改变可视化的大小。
(alt.
Chart(insurance).
mark_circle().
encode(
alt.X('charges'),
alt.Y('bmi', scale=alt.Scale(domain=(10,60)),
alt.Color('smoker')
).
properties(height=300, width=400))
(图片由作者提供)
我们可能还想定制散点图中点的外观。例如,大小、颜色和不透明度可以调整如下:
(alt.
Chart(insurance).
mark_circle(size=50, color='darkblue', opacity=0.6).
encode(
alt.X('charges'),
alt.Y('bmi', scale=alt.Scale(domain=(15,55)))
).
properties(height=400, width=500))
(图片由作者提供)
我们也可以在编码函数中指定这些变化。下面的代码生成与上面相同的可视化效果。
(alt.
Chart(insurance).
mark_circle().
encode(
alt.X('charges'),
alt.Y('bmi', scale=alt.Scale(domain=(15,55))),
size = alt.value(50),
color = alt.value('darkblue'),
opacity = alt.value(0.6)
).
properties(height=400, width=500))
Altair 也允许定制图例。
(alt.
Chart(insurance).
mark_circle(size=40).
encode(
alt.X('charges'),
alt.Y('bmi', scale=alt.Scale(zero=False)),
alt.Color('smoker',
legend=alt.Legend(
title='Do they smoke?',
orient='left',
titleFontSize=13,
labelFontSize=13
)
)
).
properties(title="Bmi vs Insurance Cost")
)
我们已经更改了图例的标题,并将其放在左侧。标题和标签的字体大小也进行了调整。
(图片由作者提供)
我们还使用 properties 函数添加了一个标题。
在某些情况下,我们需要更改轴标题,因为列名可能不合适或不太清楚。X 和 Y 编码的标题用于改变轴标题。
(alt.
Chart(insurance).
mark_circle(size=40).
encode(
alt.X('charges', title="Insurance Cost"),
alt.Y('bmi', scale=alt.Scale(zero=False),
title="Body Mass Index"),
alt.Color('smoker',
legend=alt.Legend(
title='Do they smoke?',
orient='left',
titleFontSize=13,
labelFontSize=13
)
)
).
properties(title="Bmi vs Insurance Cost",
height=350, width=500)
)
(图片由作者提供)
我们最后取得的成果似乎比我们创作的第一个情节要好得多。
结论
我们已经介绍了 Altair 提供的定制可视化的一些选项。当然,有更多的方法来创建高度定制的可视化。
在许多情况下,默认设置稍加调整就可以了。然而,我们总是可以使可视化更有吸引力和独特性。这会帮助你更清楚地传达信息。
感谢您的阅读。如果您有任何反馈,请告诉我。
替代分布语义方法
原文:https://towardsdatascience.com/alternative-distributional-semantics-approach-e40fe1370c13?source=collection_archive---------22-----------------------
实践教程
解决歧义不再是歧义了
如果你在这里登陆,这意味着你有足够的好奇心去学习更多关于在 NLP/NLU 中解决歧义的不同方法。
背景信息是机器产生歧义的原因。这种模棱两可的信息产生于人类在交流中使用的自然语言。将这种语言“翻译”成一种全面的机器人工语言的过程可能会产生歧义。这可以用人类语言本身固有的非正式性和模糊性来解释。
传统的分布式语义方法是基于词向量化的地址语义。这里显示的替代方案是基于一个知识图,直接请求解决词汇歧义。
本教程将强调一些我们可以用来解决这个问题的歧义消解任务,通过一个简单方便的应用程序,因此,一个自然语言 API (NL API) 。
在 Unsplash 上paweczerwiński拍摄的照片
机器本身既不能解释也不能理解文本;要做到这一点,并解决语言歧义,他们需要通过多层次的语言分析对文本进行注释。处理歧义的现象称为“歧义消除”。这是帮助机器检测文本中的意思(语义)的过程。考虑上下文、句法和单词关系来确定含义。
接下来的文章将强调可以用来帮助机器减少歧义和揭示文本理解的不同方法,如词汇化、词性标注等。
这项工作将基于自然语言 expert.ai NL API 的使用。
Expert.ai NL API?
expert.ai 自然语言 API 是一个能够通过几行代码在文本中提供多层次信息的应用程序。为了构建 NLP 模块,API 提供了深入的语言理解。它显示了执行深层语言分析(标记化、词元化、词性标注、形态/句法/语义分析)的特征子集。最重要的是,该库允许解决命名实体识别(NER)、这些实体之间的语义关系和情感分析等问题。文档分类也可以通过现成的分类法来实现。
Python 如何使用 Expert.ai NL API?
安装库
首先,您需要使用以下命令安装客户端库:
pip 安装专家-nlapi
一旦你在developer . expert . ai门户上创建了你的凭证,该 API 就可用了。Python 客户端代码希望您的开发人员帐户凭据被指定为环境变量:
- Linux:
导出 EAI _ 用户名=您的用户
导出 EAI _ 密码=您的密码
- 视窗:
SET EAI _ USERNAME = YOUR _ USER
SET EAI _ PASSWORD = YOUR _ PASSWORD
您的用户是您在注册时指定的电子邮件地址。
您还可以在代码中定义凭证:
2 深入的语言分析
语言学把对语言的分析分成不同的部分。所有这些分支都是相互依赖的,一切都用语言联系在一起。
文档经过多级文本分析处理;每个文本被分割成句子,这些句子被解析成记号、词条和词类,找到句法成分和谓词之间的关系,并解释句法以建立完整的依存树。
要检索这些信息,首先要导入库的客户端部分:
让我们举一个例子来说明这些操作:
“索菲亚是一个由香港汉森机器人公司开发的社交人形机器人。索菲亚于 2016 年 2 月 14 日被激活。”
a/文本细分
该操作允许将文本从最长的形式划分到最小的形式,在这种情况下,从段落级别开始,经过句子和短语,直到标记级别。当令牌是一个搭配(复合词)时,文本细分可以在分析中变得更深,直到原子级别为止,它不能被进一步划分。
一旦导入了库并实例化了客户端,就应该设置文本的语言和 API 的参数:
在 API 请求里面,你要提到 正文 里面要分析的句子和 params 里面的语言。资源参数与您需要对文本执行的操作相关,例如,这里的消歧基于 expert.ai NL API 提供的多级文本分析。
这种多层次的文本分析一般分为三个阶段:
1。一个词法分析:允许文本被分解成基本实体(记号)的文本细分阶段。
2。一个**句法分析:**在于识别构成句法实体的词位组合(包括词性标注)。
3。A **语义分析:**消歧发生在这个层面,它根据交际语境和实体之间可能的关系来检测这些实体的含义。
词法分析从第一个细分开始:
Paragraphs: Sophia is a social humanoid robot developed by Hong Kong-based company Hanson Robotics. Sophia was activated on February 14, 2016.
由于我们的文本已经是一个段落(这里是两个句子),细分的输出提供了与输入相同的文本。让我们试着把段落分解到句子层面,在这种情况下,我们只需要修改元素**。段落至。句子**。最常见的句子定界方式是基于点**(。)**:
Sentences: Sophia is a social humanoid robot developed by Hong Kong-based company Hanson Robotics.
Sentences: Sophia was activated on February 14, 2016.
结果我们确实有两个句子。让我们更深入地细分检索短语级别。我们使用与上面相同的过程,修改元素**。带的句子。短语**:
Phrases: Sophia
Phrases: is a social humanoid robot
Phrases: developed
Phrases: by Hong Kong-based company Hanson Robotics
Phrases:.
Phrases: Sophia
Phrases: was activated
Phrases: on February 14, 2016
Phrases:.
我们注意到,一旦我们深入细分,我们会在结果中获得更多的元素。我们也可以得到文本中短语的数量:
phrases array size: 10
b/标记化
此外,我们可以将短语级别分解成更小的单元,即记号。这是**“标记化”任务,在 NLP 中很常见。它帮助机器理解文本。为了用 Python 执行标记化,我们可以使用。【split()【功能如下图所示:**
例如,考虑这个句子:
“美国消费者新闻与商业频道评价了索菲亚栩栩如生的皮肤和她模仿 60 多种面部表情的能力。”
These are the tokens of the sentence ['CNBC', 'has', 'commented', 'on', 'the', "robot's", 'lifelike', 'skin', 'and', 'her', 'ability', 'to', 'emulate', 'more', 'than', '60', 'facial', 'expressions.']
如果不在 split()中指定分隔符,文本将根据空格分隔。使用 expert.ai NL API,我们也可以执行标记化,并具有附加功能。换句话说,API 提供了不同的单词级令牌分析;API 产生的标记可以是单词、字符(如缩写)甚至标点符号。
让我们看看如何用 API 执行这个任务,我们使用与上面相同的过程,修改元素**。短语与。代币**:
TOKEN
----
CNBC
has
commented
on
the
robot
's
lifelike
skin
and
her
ability
to
emulate
more
than
60
facial expressions
.
我们注意到这些记号要么是像皮肤、能力、仿效这样的单词,要么是像的这样的缩写,要么是数字: 60 ,甚至是像点这样的标点(。)。
标记化会产生搭配,就像使用 split()函数无法实现的面部表情一样。API 能够根据单词的位置和上下文来检测句子中的复合词。这种搭配可以进一步细分到原子级别,这是我们可以拥有的最后一个小词汇单位:
CNBC
has
commented
on
the
robot
's
lifelike
skin
and
her
ability
to
emulate
more
than
60
facial expressions
atom: facial
atom: expressions
.
c/ PoS 标签
标记化导致 NLP 中的第二个过程,即词性标注(词性标注),它们一起工作,以便让机器检测文本的意思。在这一阶段,我们介绍包括词性标注任务的句法分析。后者包括给每个单词分配一个词性或语法类别。词性表征了每个词素的形态句法性质。这些归属于文本元素的标签可以反映文本的一部分意义。我们可以列出英语中常用的几个词类:限定词、名词、副词、动词、形容词、介词、连词、代词、感叹词 …
同形异义词(同形异义词)可以有不同的含义(多义词)。这个单词可以有不同的词性,即使它有相同的形式。语法类别取决于单词在文本中的位置及其上下文。让我们来考虑这两句话:
这项活动的目的是为慈善机构筹款。很多人将反对书。
从语言学的角度来看,在第一句中,宾语是名词,而在第二句中,宾语是动词。词性标注是消除歧义的关键步骤。根据这种标记,从上下文、从单词的形式(例如,专有名词开头的大写字母)、从位置(SVO 词序)等推断单词的意思。因此,单词之间产生语义关系;根据关系的类型将每个概念相互联系起来,构建一个知识图。
让我们尝试使用我们的 API 为前面两个句子生成词性标记:
我们首先导入库并创建客户端,如下所示:
我们必须声明与每个句子相关的变量,宾语 _ 名词用于单词宾语是名词的句子,而宾语 _ 动词用于带有动词的句子:
单词宾语在两个句子中具有相同的形式,但是具有不同的词性。以便向专家展示。Ai NL API,我们需要调用后者。
首先,我们指定要进行词性标注的文本,对于第一个句子,它是宾语名词,对于第二个句子,它是宾语动词。然后是例子的语言,最后是资源;这与所执行的分析相关,在这种情况下是歧义消除,如下所示:
一旦我们设置了这些参数,就需要对标记进行一次迭代,以便为每个示例分别分配一个 POS
**Output of the first sentence :**
**TOKEN POS**
The DET
object NOUN
of ADP
this DET
exercise NOUN
is VERB
to PART
raise VERB
money NOUN
for ADP
the DET
charity NOUN
. PUNCT
**Output of the second sentence : **
**TOKEN POS**
A lot of ADJ
people NOUN
will AUX
object VERB
to ADP
the DET
book NOUN
. PUNCT
一方面,宾语确实是名词,前面加了冠词/限定词【DET】。另一方面,单词宾语实际上是连接主语“很多人”和宾语“书”的动词。
自然语言处理中使用的传统词性标注工具通常使用相同类型的信息来标注文本中的单词:上下文和词法。专家系统中词性标注的特殊功能。Ai NL API 不仅仅是为每一个 token 标识一个语法标签,更是引入了意义。
换句话说,一个词可以和其他词有相同的形式,但它包含几个意思(一词多义)。每个意思都在一个概念中传达,与其他概念相联系,创建一个知识图。上面看到的单词 object 有不止一个含义,因此,它属于不同语义的概念,我们在 expert.ai NL API 的知识图中称之为 "Syncons" 。词性标注可以揭示同一个词的不同标签,从而产生不同的含义。这就是我们可以用 API 检查的内容:
***Concept_ID for object when NOUN**
**TOKEN POS ID**
The DET -1
object NOUN 26946
of ADP -1
this DET -1
exercise NOUN 32738
is VERB 64155
to PART -1
raise VERB 63426
money NOUN 54994
for ADP -1
the DET -1
charity NOUN 4217
. PUNCT -1
**Concept_ID for object when VERB **
**TOKEN POS ID**
A lot of ADJ 83474
people NOUN 35459
will AUX -1
object VERB 65789
to ADP -1
the DET -1
book NOUN 13210
. PUNCT -1*
可以注意到,名词对象*属于 ID 为 26946 的概念。这一概念包括其他具有相同含义的词(同义词)。相比之下,它在第二句中的同形异义词与 ID **65789 相关。*这些 ID 是知识图中每个概念的标识。
因此,不同的词性导致不同的意思,即使我们有相同的词形。
***请注意*****以-1 为 ID 的词如 ADP (Adposition 指介词和后置)、PUNCT(表示标点)、限定词)等,在知识图中是不存在的,因为它们本身没有语义。
d/词汇化
这是自然语言处理中的另一个核心任务,称为词汇化。除了标记化和词性标注,这是执行信息提取和文本规范化的重要步骤。对于观点挖掘和情感检测特别有用,词条允许在文档中出现主要的语义趋势。
词汇化是一种将某些标记组合在一起的语言资源。简而言之,它将每个标记与字典中代表它的标准形式相关联:
- 动词的不定式:wear,wear->wear/ran,running,runs - > run
- ****的单数形式为名词:mouse->mouse/die->dice
- 等等。…
这个概念(或 Syncon)可以包含许多引理 (lexemes) 。在消除歧义的过程中,文本中识别的每个标记都返回到其基本形式,去除屈折词缀。每个引理与知识图中的一个概念相关联。因此,引理化使得能够将不同记号的集合减少到不同引理的集合。这可以通过这个例子来说明;
起初,一个词位“ living ”的听者几乎是无意识地就能辨别出这个词的意思。这对于人类来说是可能的,通过基于世界的知识等进行推论。如果上下文不存在,这对于机器来说是不可能的。
对于机器来说,预测一个单词的几个意思,具有相同的拼写和相同的发音,词汇化是处理词汇歧义的关键解决方案。
我们可以用 expert.ai NL API 来执行这个任务。让我们考虑这两个例子:
她正在过着她最美好的生活。你靠什么为生?****
******Output of the first sentence :**
**TOKEN LEMMA POS**
She she PRON
's 's AUX
living live VERB
her her PRON
best good ADJ
life life NOUN
**Output of the second sentence : **
**TOKEN LEMMA POS**
What what PRON
do do AUX
you you PRON
do do VERB
for for ADP
a a DET
living living NOUN
? ? PUNCT****
如上所述,“living”属于两个不同的引理,取决于上下文及其在句子中的位置。在第一个例子中, living 对应于引理“live”,它是句子的动词。相反,第二个句子中的 living 是一个名词,有一个引理**“living”。意思也不一样,第一个引理描述的是*【生存】的概念,然而,作为名词的生存属于【收入或挣钱的手段】的概念。*
因此,词汇化有助于机器推断同形异义词的意思。
结论
一个表达或单词可能有一个以上的意思,因此,机器的语言理解存在问题。这要归功于非常基本的自然语言处理任务,比如词汇化、词性标注等。,以及几行代码,我们可以解决这种模糊性,这就是我在本文中想要分享的内容。
希望解决歧义现在不那么模糊了…
alteryx——一个有价值的数据平台?
原文:https://towardsdatascience.com/alteryx-a-worthy-data-platform-b3444fc7a63b?source=collection_archive---------32-----------------------
如何将 Alteryx 用于数据工程和科学
克里斯托弗·扎里略在 Unsplash 上拍摄的照片
Alteryx 被认为是一个结合了分析、数据科学和过程自动化的平台。与许多工具的集成可以非常容易地实现,并用于许多有趣的用例。在这个演练中,我使用 Google BigQuery 作为源和目标平台。
如何开始:
- 安装 Alteryx 并创建一个 GCP 帐户,该帐户有权创建一个服务帐户。
- 为 Alteryx 安装大查询工具。
- 通过服务对服务验证或最终用户验证来验证 big query(完整指南)【1】。
用例
这里是我遇到的一些典型用例,可能会给你一些 Alteryx 可以做什么的灵感。
数据准备
虽然像 GCP 这样的工具和云平台已经带来了他们自己的数据准备工具(Cloud Dataprep)或者像数据传输服务这样的服务,但是你可能会选择 Alteryx,因为它的多样性。它还为您提供了 ESB 和数据分析/科学家功能—您可以从众多工具中选择一个来完成工作,或者使用 Python 和 R 代码。
无编码的数据准备—图片由作者提供
另一个原因可能是内部版本,由于数据治理问题,这可能是您和您的公司的必备产品。因此,一个典型的用例是从任何来源获取数据或已经加载到 BigQuery 中的数据,并为进一步的分析案例准备数据。
数据准备工作流程-按作者分类的图像
你可以使用许多内置的数据准备工具中的一个(如上图中的蓝色图标所示),或者像上面已经说过的那样,使用 python 和 R 代码来变魔术。最后,您可以使用 BigQuery 输出工具轻松地将其加载回 BigQuery 中的新表。
数据集成
另一个用例是将 Alteryx 用于您的 ETL/ELT 过程。如上所述,Alteryx 提供了一套广泛的连接器和数据集成工具。
ELT/ETL 工作流—按作者分类的图像
与上面的用例类似,在这个例子中,您可以从 MSSQL 数据库中提取数据,转换它,最后将它加载到您的数据仓库中。输入工具支持的广泛数据源(如绿色图标所示)无疑是一大优势。
支持的数据源-按作者分类的图片
这一应用领域在热带冰沙咖啡馆的成功故事中也有描述,该咖啡馆的数据来源是 AWS——见此处 [2]。
报告和分析
与其他案例类似,但侧重于分析,可以使用 Alteryx 作为构建报告的工具。通常,您的数据仓库或湖中有原始数据,并希望用它来构建报表。在这里,您可以使用 Alteryx 来完成更繁重的数据分析/科学任务,如准备、聚合、统计以及机器学习。此后,您可以使用众多受支持的 BI 和 BI 服务器工具之一将您的数据上传到那里。在这个用例中,我将数据上传到 Tableau 服务器。
分析工作流程-按作者分类的图像
在这里,Alteryx 在您的数据处理中是一个真正的大优势,因为 BI 工具通常不提供各种各样的分析功能。在这个的故事中,西门子描述了一个类似的用例。
结论
Alteryx 不仅仅是一个数据分析工具,它还适用于数据集成任务,并且可以通过它的许多系统和数据库连接器大放异彩。与 BigQuery 等技术以及许多其他软件和数据库一起,您可以实现数据集成和准备,以及报告和分析用例。我喜欢的是在众多 Alteryx 工具(拖放)之间进行选择的可能性,以及使用 Python 或 r 的机会。这两种工具的结合将为您提供一个出色的数据集成和分析平台,使您和您的公司能够获得广泛的工具集,以应对敏捷和数据驱动的世界中的挑战。
资料来源和进一步阅读
[1] Alteryx,谷歌大查询输入工具 (2020)
[2] Alteryx,利用 Alteryx、AWS 和 Tableau 将 40 亿行数据转化为洞察力 (2018)
[3]西门子公司 2020 年的 5000 万美元预算
永远测量你的基线——数据科学家的黄金法则
原文:https://towardsdatascience.com/always-measure-your-baseline-a-golden-rule-for-data-scientists-2bf38371cc41?source=collection_archive---------32-----------------------
你很容易发现自己注定会失败。在开始之前验证和检查指标是我学到的最有价值的经验之一(艰难的方式)。
在开始任何改善现有模型或流程的项目之前,一定要确保你没有受到不公平的衡量(图片由 Unsplash 上的威廉·沃比拍摄)
注定失败
这是我多年来见过几次的问题,也是我职业生涯早期碰到的问题。这也是我学到的最重要的一课。
众所周知,大部分数据科学项目都会失败。这通常归因于工作模型从未投入生产,以及围绕 MLOPs 和机器学习工程的困难。在我继续之前,如果你想要一个超级简单的指南来完成端到端的过程,我不久前写了一篇关于这个的文章,介绍了一些基本知识。你可以在这里查看:
这不会让你很快得到一份 MLE 的工作,但是如果你刚刚开始,这真的可以增强你的自信,让一些步骤不再神秘。
现在,虽然 MLOps 是许多数据科学项目的巨大障碍,但我认为许多项目失败实际上还有另一个重要原因。事实上,在我做顾问的日子里,我不止一次在我们合作过的组织中发现这一点,这些组织谴责他们对数据科学的整个尝试是失败的。
我非常清楚这个问题,因为它在我职业生涯的早期就困扰着我。幸运的是,有一个非常简单的方法可以解决这个问题,我们很快就会看到,但是首先,有一个故事…
热切的数据科学家的寓言
在职业生涯的早期举起手来表现出热情是很好的,但是要小心你自愿做的事情(照片由国家癌症研究所在 Unsplash 上拍摄)
当我完成博士学位时,我非常渴望成为一名数据科学家。我花了数年时间构建复杂激光系统和量子力学过程的计算模型——甚至为了激光设计玩强化学习!我很幸运地在格拉斯哥的一家非常早期的初创公司找到了一个很有前途的职位。不幸的是,这一承诺没有转化为销售,不到一年,我不得不继续前进。
我进入了一家保险公司,也是一家初创公司,但比我的第一份工作做得更好——我们实际上在盈利!我被引入定价团队,研究如何改进作为业务核心的全能定价模式。
人们最终如何支付他们的保险有一个特别的输入。我不会在这里详述,但基本上有四种结果。两个是中性的,一个意味着企业获得了超出预期的额外利润,一个意味着企业赚的钱比预期的少。
所以,新来的人告诉我,这可能是一个特别棘手的问题,也是他们想用数据科学解决的问题。急于取悦我举起我的手,并陷入其中。
这是一个很大的问题,定义明确,有大量的数据——在英国,如果你注册成为四大价格比较网站的供应商,你每天会收到大约 100 万份汽车保险报价,每个报价(当时)大约有 900 个字段。
我花了一些时间研究整个行业的其他模式和方法,从我们组织的主题专家那里获取专业知识,并与同事和社区等合作。我最终得出了一个非常合理的模型,ROC AUC 为 0.82,用于预测某人落入负面结果类别的可能性。
这是事情变得困难的时候。
当插入大定价机制时,优化开始给出与中小企业所知道的不一致的结果。我被拷问,模型被撕成碎片。
回到绘图板。
我经历了几次这样的迭代,没有太大的变化。每一种新的方法和所有额外的研究都不断让我得到类似的结果。作为一名早期职业数据科学家,仅仅在我的第二份工作中,我就开始担心了。
我开始感到很困惑,于是要求向我展示中小企业得出结论的具体过程。他们使用了什么样的模型给出了如此大相径庭的结果?
那时一切都变得清晰了。
当我看到事情是如何完成的,我开始钻研之前的计算方法时,很明显我们测量的是完全不同的东西。事实上,他们是如此的不同,以至于我不可能得到一个满意的结果。
经过一段时间和咨询后,我的模型最终超越了现有的方法,并导致了一些违反直觉的发现——定价模型核心的优化实际上更有利于那些处于负面结果类别的人,因为他们有一些不太明显的长期行为,这些行为显著增加了他们的终身价值!
苹果对苹果
检查你是否真的在比较苹果(照片由悉尼·雷在 Unsplash 上拍摄)
那么这一切有什么意义呢?
自从那件事之后,我给自己定了一个新的规则,我是否应该开始一个项目来改进现有的模型或过程:
使用您打算用来衡量模型的相同流程,重新计算现有模型的评分标准
对许多人来说,这似乎很简单,但却很容易被忽视。我已经看到这是整个团队的失败,他们努力做出真正的改进,因为他们严格的方法无法与管理层对现有过程珍视的草率的幻想度量相竞争。你知道这种电子表格,充满了捏造的因素和调整,已经运行了公司多年,或者数据拼凑在一起,每个月手动“按摩”成型。
如果不将更广泛的业务与您自己的方法保持相同的标准,您将处于非常不利的地位。
再加上你经常能从急于证明数据科学是浪费时间的人那里找到的阻力,你甚至可能永远无法起步。
现在必须说,在某些情况下,准确或严格地重现现有的方法/理解实际上是不可能的。没关系。在这种情况下,你需要做的就是从一开始就列出这个限制。如果可能的话,建议一个代理或类似的计算来比较你的进展。
作为一名数据科学家,你的工作是教育更广泛的组织变得更加数据驱动。
如果处理得当,这真的可以让你脱颖而出,成为整个企业变革的积极力量,并让人们与你同行。
摘要
小心你不是在尝试不可能的事情,确保你(或组织中的某个人)可以重新创建衡量你的标准。
如果你不知道你从哪里开始,就很难知道你已经走了多远。
永远记住数据先于科学
原文:https://towardsdatascience.com/always-remember-data-comes-before-the-science-681389992082?source=collection_archive---------24-----------------------
获取数据的不同方法
粘土银行在 Unsplash 拍摄的照片
没有数据,我们肯定会忘记做科学部分。然而,令我惊讶的是,我们对数据的谈论如此之少——别担心,我不是在指责谁。我也有罪;数据是我们作为数据科学家所做的一切的核心,但这并不像谈论 BERT 如何推动自然语言处理(NLP)任务的边界,或者无论新的最先进的(SOTA)架构是什么那样有趣。
这种对人工智能(AI)和数据科学未来的固有 FOMO(害怕错过)类似于让许多人迷上社交媒体的事情。
当我们可以幻想我们的未来可能会有多么美好的时候,谈论现在真正重要的事情并不有趣。
至少这是我的一个小理论,关于为什么在数据领域的人们没有给予真正重要的东西那么多的关注。数据!
这听起来可能很疯狂,但您知道工业项目中的大多数瓶颈都是由数据造成的吗?别让我从道德方面说起。
也许我住在岩石下,我不知道。我要说的是,我很少看到数据相关领域的从业者讨论数据的实际获取。这是一个疯狂的观察,因为数据实际上是整个工作流程中最重要的部分之一——如果我一直在错误的地方寻找,我很高兴被指向正确的方向。
注:我建议阅读这篇文章的每个人都把编码偏见放在他们的观察清单上——你可以在网飞上找到它。
什么是数据采集?
根据 维基百科 的说法,数据采集被描述为“对测量现实世界物理状况的信号进行采样,并将所得样本转换成可由计算机操纵的数字数值的过程”来源 : 维基百科。
在一个理想的世界里,我们应该有所有需要的数据集,这些数据集有足够的数据点来解决我们的问题(实际的数量可能会因项目而异)。在这种情况下,我们不必考虑数据采集。然而,这个世界通常并不理想,因此,在我们考虑将数据转换成可以处理的格式之前,我们必须掌握获取数据的技术。
数据采集技术
在我们进行任何数据采集之前,我们需要知道我们希望测量的物理现象是什么(即光强、房价、力等)。).在任何实际活动开始之前,人工智能团队通常会就业务问题是什么、它的不同需求以及他们需要什么类型的数据进行长时间的讨论。
一旦开始工作的号角响起,所有的数据源都需要被拉到一个数据科学家可以访问的位置。
在本文的剩余部分,我将介绍在理想场景没有出现时收集数据的不同方法。
公共数据
有时,我们有可能找到公共数据集来完成我们的任务。这里列出了一些可以找到免费公共数据集的地方:
- NLP-datasets Github 知识库
- Awesome-Project-Ideas Github 知识库
- Awesome-Public-Datasets Github 知识库
- 谷歌的专业搜索引擎(数据集)
如果你能找到一个合适的并且与你正在解决的问题相似的数据集,那就太好了!你可以建立一个模型并评估它。
数据抓取
如果没有任何公共数据集可供使用,我们很可能会在互联网上找到一些相关的数据源,例如,人们用来与企业互动的 FAQ 或论坛。我们可以抓取这些数据,然后让人类注释者为我们标注。
然而,在许多工业环境中,这种从外部来源收集数据的策略是不够的,因为数据不会包含典型产品的细微差别(即产品名称、产品特定的用户行为)。这意味着我们的外部数据可能与在生产环境中看到的数据非常不同,这是灾难的完美配方。
注意:当你决定从事网络抓取任务时,有几个问题需要注意——在网络抓取挑战中阅读更多相关信息。此外,您总是希望通过检查您希望抓取的网站的 robots.txt 文件以及使用条款来确保您尊重您抓取的网站(这通常是一个更具限制性的文件,因此检查这一点非常重要)。
产品干预
在现实世界中,人工智能模型很少(如果有的话)作为一个单独的行为存在。人工智能模型通常通过产品或功能为用户服务。因此,人工智能团队应该确保他们与产品团队合作,通过为产品开发更好的仪器来收集更多和更丰富的数据。这种策略在技术领域被称为产品干预。
一般来说,当涉及到在工业环境中构建人工智能应用时,产品干预会取得胜利。
数据扩充
这些技术中的大部分都需要时间,而在企业界,时间就是金钱。举个例子,用仪器测量产品来收集数据。如果我们现在对某些产品进行检测,可能需要 3 到 6 个月的时间来收集足够多的数据集。为了克服这个问题,我们可以在我们的小数据集上执行一些数据扩充技术来创建更多的数据。
数据分析中的数据扩充(Data Augmentation)是一套用于增加数据量的技术,通过添加已有数据的略微修改的副本或从已有数据中新创建的合成数据[ 来源 : 维基百科 ]。
在以后的文章中,我将介绍一些为 NLP 任务增加数据的方法。
最后的想法
为了让列出的数据采集技术发挥作用,我们首先必须确保我们有一个干净的数据集,即使它非常小。数据来自异构数据源并不罕见,这可能意味着我们的早期生产模型是使用公共数据集、标记数据集和增强数据集的组合开发的,因为我们在开始时可能没有足够大的数据集用于我们的定制场景。
感谢您的阅读!
通过 LinkedIn 和 Twitter 与我联系,了解我关于数据科学、人工智能和自由职业的最新帖子。
相关文章
</4-data-related-books-ill-be-reading-in-april-efd06b367e35>
总是从“为什么”开始你的数据科学项目
原文:https://towardsdatascience.com/always-start-your-data-science-projects-with-why-ad4bb13c9a3e?source=collection_archive---------19-----------------------
练习笔记
业务问题对于在现实生活中的数据科学项目中取得成功的重要性。
由岩田良治在 Unsplash 上拍摄的照片
在我两年的内部创业中,我做了很多很多的总结。对于那些不熟悉的人来说, pitch 是对你的工作的简短介绍——通常由初创公司用来吸引投资者。准备一个在 3 到 5 分钟内讲述一个端到端故事的演示文稿确实需要认真的准备。
这就是我开始痴迷于更好地讲故事、演讲和展示的原因。如果我想擅长什么,我看最好的。在这种情况下 Ted 讲话——很明显。
这导致了一个意想不到的结果:我看了西蒙·西内克的伟大的领导者如何激励行动(以及其他许多演讲*)。如果你还没看,这是你可以投资给自己的最好的 18 分钟之一。它改变了我对如何沟通的所有看法。
Sinek 说你所有的交流都应该遵循为什么->如何->什么的顺序。简单。
为什么现实生活中的数据科学项目的实际上是你的 业务问题 。在任何数据科学项目之前完全发现它是重要的,但并不容易。
例子:员工规划
让我们和我们的商业伙伴坐在一起,一起努力找到一个好的问题定义。在许多情况下,您需要更多的人在房间里(例如 IT),但是让我们假设这是一个初始会议,目的是发现真正的业务问题:
我们需要一个预测模型…
否。不要从解决方案开始。如果你的定义中不包含任何技术(数据科学)术语,那就更好了。一个商人的需求从来不是一个预测模型。这不是你在本次会议结束时的预期结果。
我们需要一个预测来计划我们的人员配备…
No. 现在你谈 什么 要求什么 如何 才能实现,这很棒。另一方面,在定义一个业务问题的时候,你需要了解并制定 为什么 业务要做这个项目。
由于需求多变,我们无法有效地规划我们的员工
那看起来好多了。该定义提到了您与企业进行对话的原因( 为什么 ),并给出了一个宽泛的概述。仍然商业中的痛苦不存在了。我肯定会再尝试一次迭代来挖掘得更深一点。
由于需求多变,我们无法有效地规划我们的员工。这导致 30%的时间人手不足,15%的订单被延迟。
这是一个很好的说法!它谈到了问题,可能的原因(千万不要拿那个给定!)和 it 为企业带来的痛苦。但是我们能让它变得更好吗?
由于需求多变,我们无法有效地规划我们的员工。这导致 30%的时间人手不足,15%的订单被延迟。延迟订单每减少一个百分点,我们就可以节省 x 美元的罚款和客户服务成本。
太神奇了!在一个伟大的声明之上,现在有一个联合动机:减少人手不足,节省资金。 x$ 确实是你整个项目生命周期中的一个重要因素。我需要测试另一种方法吗?我是不是再花 3 个月的时间去建立一个深度学习模型?我能得到外部专家的支持吗?
知道每一次额外的改进会产生多大的影响 有助于你知道什么时候继续改进,什么时候停止。
**但是……**在很多情况下,想出实际的 x. 并不容易,可能需要多次迭代、A/B 测试、模拟或其他方法来估计你的模型的影响。很好,如果你能把最后一句话加到你的业务问题上。如果没有,你仍然应该确保你定义了项目的最终影响/成功。
由于需求多变,我们无法有效地规划我们的员工。这导致 30%的时间人手不足,15%的订单被延迟。延迟订单的减少将减少我们的罚款和客户服务成本。
哇,这不是一次轻松的会议,但结果很好!
现在你对这个问题有了很好的理解,你可以开始你的数据科学项目了。看起来在这种情况下,一个预测模型反馈到一个员工调度模型可以帮助企业。
不仅仅因为你被要求解决它,并不使成为一个数据科学问题。在我们当中,很常见的做法/陷阱是匆忙提供数据科学解决方案,而解决根本原因的更简单的解决方案可能已经存在。数据科学项目需要专业技能、高质量的数据和相当多的时间,也就是说,它们并不便宜。您在解决方案上花费的每额外时间都是您在业务方面损失的额外 金钱和机会成本!
在上面的例子中,我仍然会问其他问题:
- 您对已经确认的订单有足够的可见性吗?仪表板/报告能帮助解决您的问题吗?
- 我们能通过其他方式调节需求吗?(通过定价/促销塑造需求,为客户提供更便宜但更长的交付日期)
- 我们能找到灵活的劳动力来解决员工短缺的替代方法吗?
我希望现在有一个完整的商业问题定义的重要性是清楚的:没有一个完整的定义,我将永远无法提出这些总体的问题。我强烈建议你进一步探索这种类型的提问,作为系统思考的一部分,
在你的早期职业生涯中,知道该问哪些问题可能并不容易,或者你可能没有领域知识。那也不应该阻止你挑战 T37。无论如何,问那个傻问题! 最差(!)这样你会学到一些新的业务知识,最好的情况是你可以节省双方的宝贵时间和精力。
*如果你也对更好的演讲感兴趣,另一个我非常喜欢的 ted 演讲是西蒙·兰卡斯特的 像领导一样说话 。又一个值得花的 18 分钟。
我要感谢我亲爱的同事莱昂纳多·迪·马特奥(LinkedIn/Medium)和乌古尔·阿里坎(LinkedIn)对本文提出的宝贵意见和建议。
我是一名运筹学从业者/领导者,为德国邮政 DHL 集团工作。另一方面,这些观点并不代表我的现任或前任雇主的观点。如果你想取得联系,请随时联系LinkedIn
基于深度学习的阿尔茨海默病诊断研究综述
原文:https://towardsdatascience.com/alzheimer-diagnosis-with-deep-learning-a-survey-265406fa542a?source=collection_archive---------16-----------------------
理解大数据
医学中的深度学习是一个不断发展的领域;让我们来分析一下阿尔茨海默氏症诊断的现状。
由 Robina Weermeijer 在 Unsplash 上拍摄的照片
本文是我揭露从我的人工智能硕士论文中提取的研究、实现和结论的系列文章的一部分。虽然本文呈现的是论文的探索阶段(文献综述),但其他文章将处理描述阶段(数据预处理和模型实现)。
整个项目可以在下面的 GitHub 资源库中找到:https://github.com/oscardp96/TFM-Alzheimer-Diagnosis
感谢阅读
在过去的二十年里,人工智能(AI)的理论和实践进展已经渗透到各个领域,并使其受益,如医学、旅游、教育、娱乐等。具体来说,在医学领域,人工智能已经证明了其潜力:通过病变检测,细胞和器官分割,自动对话等,帮助检测和诊断几种疾病;此外,还可以通过远程监控患者、发现药物、机器人辅助手术等来帮助治疗各种疾病[1] — [3]。
在过去二十年中,深度学习的兴起推动了对解决方案的研究,以帮助改善基于神经成像数据的阿尔茨海默病诊断。因此,已经使用了各种不同的技术,但是在过去十年中已经观察到明显转向使用卷积神经网络(CNN)。事实上,提出的各种选择是巨大的,每一个都有其特殊性。例如,他们中的一些人使用磁共振成像(MRI),而另一些人选择正电子发射断层扫描(PET)图像。另一方面,可以使用不同的机器学习模型。
基于上述内容,本文旨在对机器学习,或者更具体地说,深度学习模型进行综述,这些模型已被证明在阿尔茨海默病诊断方面是有用的。在其他文章中,从这项研究中提取的结论将被付诸实践,以获得更广泛的领域知识。最后,将为试图在该领域开展工作的数据科学家提供一些建议。
概观
医学图像的使用是几种疾病的诊断和治疗的一个关键方面,因为这些图像是提取有用生物标志物的强大来源[4]。它们是电子健康记录(EHR)的重要组成部分,通常由称为放射科医生的专业人员进行检查。还有各种各样的图像格式,磁共振成像(MRI)和正电子发射断层扫描(PET)是阿尔茨海默氏症诊断中最常见的。然而,如上所述,专家基于对记录图像的视觉检查做出诊断,这是基于医生的经验,因此可能导致人为错误,从而导致错误的诊断。
鉴于这一挑战,在过去的 15 年中,使用人工智能的医学图像分析已经成为医学应用中的主要研究方向之一,其目的是提供第二种意见来支持专家做出的诊断。
在这种情况下,已经使用了应用简单机器学习算法的方法,例如支持向量机(SVM) [5]和统计方法,例如独立成分分析(ICA) [6]。然而,最近五年的趋势是使用深度学习,具体来说是 CNN [7],[8]。与此相关的主要因素有三个:
- 提高数据的数量和质量。在这方面,该领域正在接近大数据。
- 试图减少人为错误,因为放射科医生受到几个因素的限制,如速度或经验[7],[5]。
- 人工智能本身的崛起,更具体地说,深度学习。如果这种类型的系统在最近几十年里没有表现出如此突出的性能[9],[10],将它们应用于医疗应用就不会被认为是可行的。
这些技术也已经用于医学图像分析中的不同应用。它们可以浓缩为以下几类[7]、[8]、[11]、[12]:
- 计算机辅助检测。识别图像中的某些元素,如器官或细胞。这对于突出物理学家感兴趣的区域也是有用的,例如病变。
- 分段,不要和 CADe 混淆。将整个图像区域与其余区域隔离开来。
- 计算机辅助诊断(CADx),这是本文的重点。基于某些信息的诊断,可以用更简单的术语解释为分类任务。在阿尔茨海默病的情况下,通常分为三类:正常人群(NC)、轻度认知障碍(MCI)或阿尔茨海默病(AD)。最近,这一类别被称为计算机化诊断[13]。
在[12]中,提到了一个额外的有趣类别;这被称为深度特征学习。它基于能够从数据中提取有用特征的系统的设计和实现。它允许获得更高层次的特征,这些特征对于人眼是不可见的,并且碰巧在不同的场景中是可重用的。在计算机化诊断中,它通常被用作从图像中提取有用特征或预训练深度网络的前一步,通过无监督模型,如自动编码器[14]-[17]。
这种深度特征提取的过程似乎逐渐被废弃,可能是因为它需要额外的开发阶段,并且不再提高整体精度[18]。这两个事实使得直接训练深度卷积神经网络对于实现 AD 诊断的实际解决方案更加可行。然而,注意到 AI 不仅可以评估纯诊断,还可以帮助理解诊断结果和大脑结构变化之间的关系,这也非常重要,同时可以在未来更好地实现深度神经网络[19]。
总之,CNN 代表了过去五到十年中使用的绝大多数模型的基础。这些通常以监督的方式训练,但是它们的非监督应用也是非常重要的。在任何情况下,图像必须进行预处理,以便模型可以充分利用它们。
图像预处理
对自动 AD 诊断的研究表明,对于图像预处理,最初,作者利用手动定义的特征,这需要非常复杂的预处理技术。然而,使用 CNN 和自动编码器进行自动特征提取稍微简化了这个过程。在这种情况下,两种常用的方法是:1)图像配准,和 2)颅骨剥离。
图像配准包括将一幅图像与另一幅参考图像(通常称为图谱)相适配,寻求两者的相同区域代表相同的解剖结构[20]。对于 CNN 或自动编码器来说,将图像的某个区域识别为相关会更简单,因为相同的信息将在所有图像中被表示。图像配准算法种类繁多[20],不仅适用于神经成像[16]、[21]-[23],还适用于其他医学领域,如乳腺癌[24]。
颅骨剥离是从 MRI 图像上出现的颅骨中去除信息。目标是获得尽可能清晰的最终图像,仅包含与手头任务相关的信息。显然,在 AD 的病例中,没有一个最相关的生物标记在头骨中被发现。因此,某些出版物使用不同的技术来提取头骨和其他非大脑区域[21] — [23],或者直接使用已经提取头骨的图像数据集[25]。图 1 显示了颅骨如何占据图像的重要部分,尤其是在较低的轴向切面中。
图一。无颅骨剥离的 MRI 图像的低轴切面。由 Toubibe 在 Pixabay 上拍摄的照片
还有其他技术,如图像归一化,它可以分为两种变体:强度归一化和空间归一化。前者是基于根据某个标准调整像素值的范围,例如将它们减少到某个范围或减去平均值并除以标准偏差,这被称为白化[26]。后者包括调整像素(或三维体素),使其代表特定的空间(或体积)[26]。例如,在[27]中,调整 3D 图像,使得每个体素代表 2mm 的空间。在这方面,图像配准可以被视为一种形式的空间标准化[26]。
用于 AD 诊断的训练模型
近年来,CNN 在阿尔茨海默病的计算机化诊断领域发挥了重要作用[21]、[25]、[27]。这并不意味着这些模型以前没有使用过,但它们曾经得到过其他深度学习策略的支持,如深度特征提取。直接和特定的应用实际上最近已经开始,实现了比以前的方法更高的准确性,同时也提供了更简单的解决方案。
AlexNet [10]是深度学习历史上的一个转折点。它证明了 CNN 如何能够在图像分类中获得优异的结果。几年后,它的想法得到了进一步发展,产生了其他重要的架构,如 VGGNet [28]、Inception [29]和 ResNet [30]。虽然它们最初是为处理 ImageNet 数据而设计的,但是它们出色的结果使它们成为了多种应用程序的默认选择。大多数深度学习框架都提供了这些已经用 ImageNet 训练过的网络,因此开发人员可以根据自己的目的对它们进行微调。
医学图像分析也不例外。虽然这两个领域确实有很大的差异,限制了通过微调这些网络可以获得的性能,但这种技术仍然被证明是实践中最有前途的技术。不仅是阿尔茨海默病,还有其他疾病的诊断,如糖尿病视网膜病变[31],乳腺癌[32]和皮肤癌[33]。
- 在[31]中,作者微调了一个 Inception V3 模型。
- 在[32]中,作者尝试了 Inception V3 模型和 ResNet50。
- 在[33]中,Inception V3 模型也用于 757 种不同疾病类别的分类。
事实上,Inception V3 [34]和 ResNet 是文献中最常见的架构。表 1 显示了直接使用 CNN 诊断阿尔茨海默氏病和前面提到的疾病的出版物。
表 1。使用 CNN 的出版物。LeNet5 是一个相对较老的架构,源自[9]。VoxCNN 是由 VGGNet 衍生而来的一种体卷积神经网络。VoxResNet 是一个体积残差网络。
关于 AD,在针对诊断的特定情况训练 CNN 的第一次尝试中,研究人员没有使用 ImageNet 权重或微调;相反,他们使用盗梦 V1 和 AlexNet 架构[21]。然而,研究人员发现,当使用更先进和复杂的架构时,有限的可用数据会导致过度拟合。因此,他们将两种模型结合起来,设计了一种决策算法,其准确率接近 100%。
进一步的研究表明,CNN 可用于生成特征和对 AD 阶段进行分类[25]。为此,他们尽可能地简化了模型的创建,仅使用了 231 张图片。他们建立了一个受 VGGNet 启发的 3D CNN,他们称之为 VoxCNN 并与体素网模型(3D ResNet)进行了比较。与[17]进行直接比较,结果明显更差,但他们强调了实施其解决方案的简单性。
最后,最近的出版物用 18F-FDG PET 图像微调了 InceptionV3 网络,使用 Keras 框架实现模型,使用 SciPy 预处理图像。通过与放射科医生进行直接比较,他们证明了他们的模型在统计上明显优于他们,特别是在提前六年多预测阿尔茨海默病的发作方面[27]。
挑战
人工智能在临床应用中的不同用途面临一系列挑战。
第一个是标记数据的有限可用性。虽然这个问题随着时间的推移而减少,但它仍然是研究人员之间的一个主要问题,特别是当与 ImageNet 等其他数据集进行比较时。当然,ImageNet 数据库有数百万张图像,而 OASIS Brains 只有 1098 名受试者的 MRI 和 PET 数据。尽管事实上,通常情况下,医疗应用程序中的类数量也较少(ImageNet 支持 1000 个类),但情况并非总是如此。例如,已经指出,在[33]中,在 757 个标签之间进行分类。这个问题通常会导致过度拟合。因此,一个常见的解决方案是从图像中提取几个随机的小块,包括二维的[14]和三维的[15]。这种技术与放射科医生按区域检查图像的工作方式有些相似[22]。其他解决方案以不完全随机的方式提取补片,试图从每个图像中关联多个补片以利用上下文信息[35],或者还使用数据扩充[27]或者甚至合成图像的创建[36],尽管这些不太常见。但是最常见的技术可能是使用迁移学习[27]、[31]-[33]、[37]、[38]。当微调初始网络或 ResNet 时,预期需要较少的训练数据。
另一方面,还有数据不平衡的问题。与积极阶层相比,消极阶层通常人数过多。这是因为获得健康患者信息的过程更简单。更糟糕的是,消极类通常是强相关的,而积极类则有很大的差异。关于这个主题的研究表明,对代表过多的类进行欠采样从来都不是一个好主意,而对代表不足的类进行过采样在某些情况下可能会有所帮助[39]。
此外,图像的结构多样性是一个具有挑战性的话题。除了可以使用的不同扫描类型的数量(MRI、fMRI、PET 等。),这些可以用不同的方式。主要地,该决定基于是否直接使用三维数据,因为所有这些图像通常是 3D 的(有时甚至在 4D),或者将图像转换到 2D。理论上,3D 数据应该是默认的选择,因为它可以防止信息的丢失[15]–[17],[25]。然而,有一种趋势是将图像转换成 2D,主要是因为训练 2D 网络要快得多,并且更容易避免过度拟合[14]、[21]、[27]。在[15]中,对从图像中提取 2D 和 3D 补片进行了直接比较,得出的结论是差异并不显著。
除了技术挑战,还有几个伦理和哲学问题。EHR 是非常敏感的数据,这不仅限制了可以收集的图像的数量,而且迫使人们非常小心地使用它们。与此相关的是,对人工智能的信心是另一个重要的问题,因为普通大众仍然缺乏关于人工智能是什么或它如何真正工作的知识。此外,在有经验的人工智能专业人员中,存在黑盒问题,这是一个非常重要和活跃的研究课题,尽管不仅仅与医疗应用相关[40],[41]。
结论
从这篇综述中可以得出的主要结论是,讨论不再集中在哪些模型应该用于医学图像分类的任务上。CNN 已经被广泛接受并被大多数研究人员使用。
在过去的几年中,研究之间的差异主要体现在图像预处理的方式上,以及 CNN 训练的一些具体方面。常见的做法是用于预处理的图像配准,以及用于训练网络的迁移学习或深度特征提取。
然而,在未来几年中,这一领域仍存在需要解决的重大挑战。这已经表明,在真实的临床环境中部署这些解决方案几乎是不可行的。
参考
[1] Z. Akkus,A. Galimzianova,A. Hoogi,D. L. Rubin 和 B. J. Erickson,大脑 MRI 分割的深度学习:现状和未来方向 (2017),《数字成像杂志》,第 30 卷,第 4 期,第 449-459 页
[2] F. Ciompi 等人,使用 2D 视图和卷积神经网络的集成对计算机断层摄影中的肺裂周
结节进行自动分类 (2015),《医学图像分析》,第 26 卷,第 1 期,第 195–202 页
[3]罗世昌、楼世良、林、弗里德曼、钱和门世光,人工卷积神经网络技术及其在肺结节检测中的应用 (1995),IEEE 医学成像汇刊,第 14 卷,第 4 期,第 711-718 页
[4] J. P. B. O'Connor 等人,癌症研究的成像生物标志物路线图 (2017),《自然评论临床肿瘤学》,第 14 卷,第 3 期,第 169-186 页
[5]s . klp pel 等人,痴呆症诊断的准确性——放射科医生和计算机化方法之间的直接比较 (2008 年),《大脑》,第 131 卷,第 11 期,第 2969-2974 页
[6] W. Yang 等,基于独立成分分析的阿尔茨海默病 MRI 数据分类 (2011),阿尔茨海默病杂志,第 24 卷,第 4 期,第 775–783 页
[7] J. Ker,L. Wang,J. Rao 和 t .Lim,深度学习在医学图像分析中的应用 (2018),IEEE Access,第 6 卷,第 9375–9389 页
[8] G. Litjens 等人,医学图像
分析中深度学习的调查 (2017),《医学图像分析》,第 42 卷,第 1995 期,第 60–88 页
[9] Y. LeCun,L. Bottou,Y. Bengio,P. Haffner 等人,基于梯度的学习应用于文档识别 (1998),IEEE 会议录,第 86 卷,第 11 期,第 2278-2324 页
[10] A. Krizhevsky、I. Sutskever 和 G. E. Hinton,使用深度卷积神经网络的 Imagenet 分类 (2012),神经信息处理系统的进展,第 1097-1105 页
[11] H. Greenspan、B. van Ginneken 和 R. M. Summers,客座编辑
医学成像中的深度学习:令人兴奋的新技术的概述和未来前景 (2016),IEEE 医学成像汇刊,第 35 卷,第 5 期,第 1153-1159 页
[12] D. Shen、G. Wu 和 H.-I. Suk,医学图像分析中的深度学习 (2017),《生物医学工程年刊》,第 19 卷,第 221-248 页
[13] Thijs Kooi,为什么皮肤病变是花生和脑瘤一个更硬的坚果 (2020),梯度
[14] A .古普塔、m .埃汉和 a .梅达,表示神经成像数据的自然图像库 (2013),机器学习国际会议,第 987–994 页
[15] A. Payan 和 G. Montana,预测阿尔茨海默病:一项使用 3D 卷积神经网络的神经成像研究 (2015),arXiv Prepr。arXiv1502.02506
[16] E. Hosseini-Asl,R. Keynton 和 A. El-Baz,阿尔茨海默氏病
通过调整 3D 卷积网络进行诊断 (2016),IEEE 图像处理国际会议(ICIP),第 126–130 页。
[17] E. Hosseini-Asl,G. Gimel'farb 和 A. El-Baz,阿尔茨海默氏病
通过深度监督适应性 3D 卷积
网络进行诊断(2016),arXiv Prepr。arXiv1607.00556
[18]e . hellstrm,使用深度神经网络进行特征学习,用于
击键生物识别:监督预训练和
自动编码器的研究 (2018)
[19] F.J. Martinez-Murcia 等人,研究阿尔茨海默病的流形结构:使用卷积自动编码器的深度学习方法 (2019), IEEE 生物医学和健康信息学杂志,第 24 卷,第 1 期,第 17-26 页。
[20] A. Klein 等人,对应用于人脑 MRI 配准的 14 种非线性变形算法的评估 (2009),《神经影像》,第 46 卷,第 3 期,第 786–802 页
[21] S. Sarraf,G. Tofighi 等人, DeepAD:使用 MRI 和 fMRI 通过深度卷积神经网络进行阿尔茨海默病分类 (2016),BioRxiv,第 70441 页
[22] H.-I. Suk,S.-W. Lee,D. Shen,A. D. N. Initiative 等人,用于 AD/MCI 诊断的分层特征表示和具有深度学习的多模态融合 (2014),《神经影像》,第 101 卷,第 569-582 页
[23] H.-I. Suk,S.-W. Lee,D. Shen,A. D. N. Initiative 等人,用于 AD/MCI 诊断的堆叠式自动编码器的潜在特征表示 (2015),《大脑结构和功能》,第 220 卷,第 2 期,第 841-859 页
[24] D. Rueckert,L. I. Sonoda,C. Hayes,D. L. G. Hill,M. O. Leach 和
-
- Hawkes,使用自由变形的非刚性配准:应用于乳房 MR 图像 (1999),IEEE 医学成像学报,第 18 卷,第 8 期,第 712-721 页
[25] S .科洛列夫、a .萨菲乌林、m .贝尔亚耶夫和 y .多多诺娃,用于 3D 大脑 MRI 分类的残差和普通卷积神经网络 (2017),IEEE 第 14 届国际生物医学成像研讨会(ISBI 2017),第 835-838 页
[26] M. Rajchl,S. I. Ktena 和 n .鲍洛夫斯基,关于使用 TensorFlow 和 DLTK 进行生物医学图像分析的介绍 (2018),Medium.com
[27] Y. Ding 等,利用脑的 18F-FDG PET 预测阿尔茨海默病诊断的深度学习模型 (2018),放射学,第 290 卷,第 2 期,第 456–464 页
[28] K. Simonyan 和 A. Zisserman,用于大规模图像识别的甚深卷积网络 (2014),arXiv 预印本 arXiv1409.1556
[29] C. Szegedy 等人,深入卷积 (2015),IEEE 计算机视觉和模式识别会议论文集,第 1–9 页
[30]何国光,张,任,孙军,深度残差学习用于
图像识别 (2015)
[31] V. Gulshan 等人,用于检测视网膜眼底糖尿病性视网膜病变的深度学习
算法的开发和验证
照片 (2016),Jama,第 316 卷,第 22 期,第 2402-2410 页
[32] S. Vesal,N. Ravikumar,A. A. Davari,S. Ellmann 和 A. Maier,使用迁移学习对乳腺癌组织学图像进行分类 (2017),《公共科学图书馆综合》,第 12 卷,第 6 期,第 812-819 页
[33] A. Esteva 等人,皮肤科医生水平的皮肤癌分类
与深度神经网络 (2017),《自然》,第 542 卷,第 7639 号,第 115 页
[34] C. Szegedy,V. Vanhoucke,S. Ioffe,J. Shlens 和 Z. Wojna,重新思考计算机视觉的初始架构 (2016),IEEE 计算机视觉和模式识别会议论文集,第 2818-2826 页。
[35] T. Tong 等,脑 MRI 痴呆分类的多示例学习 (2014),医学图像分析,第 18 卷,第 5 期,第 808-818 页
[36] E. Castro,A. Ulloa,S. M. Plis,J. A. Turner 和 V. D. Calhoun,用于深度学习预训练的合成结构磁共振图像的生成 (2015),IEEE 第 12 届国际生物医学成像研讨会(ISBI),第 1057-1060 页
[37]于,林,孟,魏,郭,赵,深度迁移学习在医学图像模态分类中的应用 (2017),《信息》第 8 卷第 3 期第 91 页
[38] H. G. Kim、Y. Choi 和 Y. M. Ro,医学图像分类的模态-桥迁移学习 (2017),第十届图像和信号处理、生物医学工程和信息学国际大会,第 1–5 页
[39] M. A. Mazurowski、P. A. Habas、J. M. Zurada、J. Y. Lo、J. A. Baker 和 G. D. Tourassi,为医疗决策训练神经网络分类器:不平衡数据集对分类性能的影响 (2008),《神经网络》,第 21 卷,第 2–3 期,第 427–436 页
[40] G. Montavon、S. Lapuschkin、A. Binder、W. Samek 和 K.-R. Müller,用深度泰勒分解解释非线性分类决策 (2017),《模式识别》,第 65 卷,第 211-222 页
[41] M. D .泽勒和 r .弗格斯,(2014),欧洲计算机视觉会议,第 818–833 页
再次感谢您的阅读…
基于深度学习的阿尔茨海默病诊断:数据预处理
原文:https://towardsdatascience.com/alzheimer-diagnosis-with-deep-learning-data-preprocessing-4521d6e6ebeb?source=collection_archive---------5-----------------------
预测阿尔茨海默病模型实施前的 MRI 数据预处理
阿伦·巴洛在上的照片
本文是我揭露从我的人工智能硕士论文中提取的研究、实现和结论的系列文章的一部分。虽然以前的一篇文章讨论了论文的探索阶段(文献综述),但这篇文章介绍了描述阶段(数据预处理)的第一部分。最后一篇文章将描述模型实现。
整个项目可以在下面的 GitHub 资源库中找到:https://github.com/oscardp96/TFM-Alzheimer-Diagnosis
感谢阅读
在之前的一篇文章中,分析了阿尔茨海默病计算机化诊断的当前艺术状态。从该综述中,可以为基于 MRI 的分类系统的实现过程提取一些有趣的结论。这些结论归纳为以下几点:
- 卷积神经网络是模型实现的明显选择。关于是否应该使用任何其他机器学习或深度学习模型来代替,没有太多讨论。讨论主要集中在如何训练 CNN。
- 图像配准真的很重要。适应于参考图谱的多个医学图像将在图像的相同区域上表示相同的解剖结构。这将有助于 CNN 确定感兴趣的领域。
- 颅骨剥离可能是一种非常有用的消除噪声的技术。头骨的信息与阿尔茨海默氏症的诊断无关,因此消除这些信息可以简化模型训练。
- 必须决定数据集图像的结构。可以使用多种图像类型,最常见的是 MRI 和 PET。此外,图像维度可以是 4D(时间序列)或 3D,但是可以被转换为 2D,它们可以被增强,可以从它们中提取补片,等等。
在这个实验中,将训练两个神经网络:用 ImageNet 权重预训练的 2D InceptionV3 网络和 3D ResNet。
数据
本文准备过程中使用的数据来自阿尔茨海默病神经影像计划(ADNI)数据库(adni.loni.usc.edu)。因此,ADNI 的调查人员参与了 ADNI 的设计和实施和/或提供了数据,但没有参与分析或撰写本报告。ADNI 调查员的完整名单可在以下网址找到:https://adni . loni . USC . edu/WP-content/uploads/how _ to _ apply/ADNI _ acknowledge ment _ list . pdf
从 ADNI 提供的数据中,获得了超过 3000 个 T1 加权的 MRI 图像。样本由年龄在 55 岁到 92 岁之间的患者组成,他们被分配到三个可能的标签中的一个:AD、MCI 和 NC。完整的分布情况见表 1。
表 1。磁共振图像的类别分布
在整个样本中,15%保留在训练之外,作为测试集。同时,从剩余的训练集中分离出另外的 15%作为验证集,用于随着训练的进行(随着每个时期)评估模型的质量。
工具
生物医学数据的预处理可能相当复杂,但在本实验中,该过程是使用对所有图像不加区分地应用的库和开源工具来执行的,以寻求最佳的可能结果,但没有单独处理每幅图像。这是测试当今可用工具在多大程度上使构建这种类型的系统成为可能的好方法,因为对于在放射学方面没有深入经验的数据科学家来说,单独的图像处理可能是负担不起的。如上所述,以下工具用于图像预处理:
- 用于医学成像的 深度学习工具包(DLTK)【1】是一个 TensorFlow 扩展,它提供了有用的方法和模型来实现对生物医学图像的深度学习。虽然这个框架不用于模型实现,但它对于图像预处理非常有用,为图像的白化和空间归一化提供了基本方法。此外,这个框架允许简单快速的实验,尽管许多使用的方法并没有在最后的工作中应用。
- SimpleITK 用于转换。ADNI 提供的 nii 图像放入 numpy 数组。
如何加载。nii 图像作为 numpy 数组,中间使用 SimpleITK 格式
- 使用 simple elastix【2】将 ADNI 图像配准到 MNI 305 图谱【3】【6】。这是一个建立在 SimpleITK 上的医学图像配准库。
- 对于颅骨剥离,使用了由ni type[8]库实现到 Python 中的 FSL 打赌 [7】工具。尽管 FSL BET 本身可以作为 UNIX 系统的命令行工具,但是 Nipype 方法允许在 Python 环境中执行它。
空间标准化
空间归一化预处理步骤旨在确保数据集的所有图像的空间结构尽可能相似。最初,来自 ADNI 的图像有相当多不同的形状,数据库中不同的图像已经用不同的技术进行了预处理。由于这个原因,图像需要重新采样到一个共同的各向同性分辨率,并需要注册到一个共同的地图集。
因此,在第一步中,图像被重新采样到 2mm 的各向同性分辨率,这意味着每个体素将代表“真实”世界中 2mm 的空间。为此,创建了一个非常简单的方法,基于代码片段包括,这里是 [1]。注意,该方法采用 SimpleITK 格式的图像,而不是 numpy 数组。
图像重采样方法
一旦图像被重新采样,它就可以被注册到参考图像。一个地图集基本上是一个像其他任何图像一样的图像,它可以用同样的方式管理。它还应该被重新采样到与其余图像相同的各向同性分辨率:
加载和重采样地图集图像
将 MNI 305 地图集重新采样到 2mm 的各向同性分辨率,得到了最终分辨率为 78x110x86 的图像。因此,在配准之后,数据集中的每个图像将具有相同的分辨率。
对于图像配准,使用 SimpleElastix 实现了以下方法。值得一提的是,使用了仿射变换,因为非刚性变换要慢得多,而且往往会扭曲最终图像。
图像配准方法
在定义了重采样和配准方法并加载了图集之后,可以构建完整的预处理流程。最初,ADNI 数据库混合了所有图像,忽略了标签(AD/MCI/NC),而是提供了一个描述文件(。csv),其中标签可以使用图像 ID 进行索引。因此,对于每个图像,该预处理流程应该:
- 加载图像并提取其标签。
- 对图像进行重新采样,并将其配准到图集。
- 将映像写入一个新的磁盘位置,组织在一个允许轻松识别其标签的文件夹中。
对于最后一步,应该准备一个目标文件夹:
最后,可以实现主要的预处理方法:
使用这种方法,剩下的就是遍历原始数据库来预处理所有的图像。这可以使用简单的循环来完成。
颅骨剥脱术
在空间标准化之后,执行颅骨剥离步骤,以从图像中移除不相关的信息,仅留下脑组织。如前所述,FSL 打赌是用于这一点,运行在 Nipype。这里的关键是为主要的超参数找到合适的值:分数强度阈值。它基本上测量算法在去除不代表脑组织的图像成分方面的积极性。非常小的值会在图像中留下一些不相关的信息,而非常大的值会移除一些脑组织。
这里的问题是,由于不是所有的 MRI 数据在存储到 ADNI 数据库之前都以相同的方式获得和预处理,因此为整个数据集找到理想的分数强度阈值是不可行的。同时,保持一个简单的方法是这个实验的一个关键方面。所以在多次测试后,使用了 0.2 的阈值,因为它能够为大多数图像保持正确的平衡,而不是对大多数图像都完美。
颅骨剥离方法
一旦实施了颅骨剥离方法,可以迭代空间归一化图像以生成新的颅骨剥离数据集。
对整个数据库应用颅骨剥离
图 1 最后显示了完全预处理的 MRI 的三个切片。它被重采样到 2mm 的各向同性分辨率,注册到 MNI 305 地图集,并被剥离头骨。在此图像中,几乎没有任何头骨的痕迹,也没有丢失脑组织,但在其他情况下,可能会出现这些情况之一,因为分数强度阈值 0.2 并不适用于所有图像。
图一。轴向,冠状和矢状切面,分别配准和颅骨剥离图像。作者图片
准备 2D 数据集
数据集的当前状态将允许训练 3D 卷积神经网络,这是本文开始时建立的目标之一。另一个目标是微调用 Imagenet 预训练的 InceptionV3 网络,这将需要一个二维数据集。
对于 3D 到 2D 变换,从[9]的工作中得到启发,实现了一个简单的算法。它包括制作多个轴向(水平)切口,并将它们放置在同一平面上,以构建二维图像。更具体地说,从每个 3D 图像中取出 16 个不同的切片,并放置在 4x4 图像的“矩阵”上。产生的二维图像被复制三次以采用 RGB 尺寸。因此,110x86 大小的 16 个切片产生 440x344x3 的图像。
在提取切割之前,3D 图像被标准化为具有零平均值和单位标准偏差。换句话说,应用了白化过程。随后,在轴向高度 28 和 60 之间选择 16 个切片,在多次测试后发现这代表了足够的信息。高度大于 60 的切片显示了非常远的大脑上部,高度小于 28 的切片显示了脑干的大部分区域。16 个切片彼此等距分布,即从每两个切片中提取一个轴向切片。结果示例可以在图 2 中看到。
图二。2D 转换后的结果图像示例。请注意,在这种情况下,颅骨剥离过程并不像图 1 中那样有效。作者图片
以下代码显示了创建 2D 图像的方法:
将 3D MRI 转换成 2D 的方法
该方法在另一个方法中使用,该方法加载 3D 图像并应用白化过程。该方法必须在数据集的所有图像上运行。为了简洁起见,本文不打算展示这最后一个基于循环的代码,但是可以在这里查看。
白化和应用 2D 变换
TFRecords 数据库和培训/测试拆分
如前所述,谷歌实验室用于模型训练。这个平台有两个限制因素:
- 模型训练有时间限制,所以训练过程尽可能快是很重要的。
- 它提供了 12GB 的内存,这显然不足以在内存中加载所有 3000 张图像,尤其是来自 3D 数据集的图像。
第一个问题没有真正的解决方案,它总是一个限制因素。但是,第二个问题可以通过构建 TFRecords 数据库来解决。 TFRecords 是 Tensorflow 提供的一个解决方案,允许以一种特殊的格式保存数据集,使用张量可以更快读取的文件。这需要复制硬盘上的信息,以这种格式保存,但这也比使用 Python 的原生生成器快得多。
这个过程非常普通,所以为了简洁起见,本文将不解释代码。这里可以结账。
未来的步骤
本文描述了构建 3D 和 2D MRI 数据集的过程。所有图像都可以用于训练深度学习模型,这将在未来的文章中讨论。
参考
[1] M. Rajchl,S. I. Ktena,n .鲍洛夫斯基,【TensorFlow 和 DLTK 生物医学图像分析导论 (2018),Medium.com
[2] K. Marstal、F. Berendsen、M. Staring 和 S. Klein, SimpleElastix:用于医学图像配准的用户友好的多语言库 (2016),IEEE 计算机视觉和模式识别研讨会会议录,第 134-142 页
[3] A. C. Evans,来自 250 名年轻正常受试者的基于 MRI 的立体定向图谱 (1992),Soc。神经科学。文章摘要
[4] D. L. Collins,P. Neelin,T. M. Peters 和 A. C. Evans,标准化 Talairach 空间中 MR 体积数据的自动 3D 主体间配准 (1994) ,《计算机辅助断层摄影杂志》,第 18 卷,第 2 期,第 192-205 页
[5] A. C. Evans 等,立体定位坐标空间中功能激活的解剖标测 (1992),神经影像,第 1 卷,第 1 期,第 43–53 页
[6] A. C. Evans、D. L. Collins、S. R. Mills、E. D. Brown、R. L. Kelly 和 T. M. Peters,来自 305 个 MRI 卷的 3D 统计神经解剖学模型 (1993),IEEE 会议记录核科学研讨会和医学成像会议,第 1813-1817 页
[7] S. M. Smith,快速鲁棒的自动大脑提取 (2002 年),人类大脑绘图,第 17 卷,第 3 期,第 143-155 页
[8] K. Gorgolewski 等,ni type:python 中灵活、轻量、可扩展的神经影像数据处理框架 (2011),《神经信息学前沿》,第 5 卷,第 13 页
[9] Y. Ding 等,利用脑的 18F-FDG PET 预测阿尔茨海默病诊断的深度学习模型 (2018),放射学,第 290 卷,第 2 期,第 456–464 页
再次感谢您的阅读。让我们在 LinkedIn 上继续这个对话:https://www.linkedin.com/in/oscar-darias-plasencia/
基于深度学习的阿尔茨海默病诊断:模型实现
原文:https://towardsdatascience.com/alzheimer-diagnosis-with-deep-learning-model-implementation-5a0fd31f148f?source=collection_archive---------18-----------------------
实践教程
阿尔茨海默病预测与深度学习的模型实现策略比较
国立癌症研究所在 Unsplash 上拍摄的照片
本文是我揭露从我的人工智能硕士论文中提取的研究、实现和结论的系列文章的一部分。第一篇文章论述了论文的探索阶段( 文献综述 ),第二篇文章呈现了第一部分的 描述阶段 ( 数据预处理 )。这最后一篇文章介绍了这个描述阶段的第二部分:模型实现,比较两种常用的策略
整个项目可以在下面的 GitHub 资源库中找到:https://github.com/oscardp96/TFM-Alzheimer-Diagnosis
感谢阅读
在之前的文章中,对 MRI 图像的两个数据集进行了预处理,目的是训练两个卷积神经网络:用 ImageNet 权重预训练的 2D 概念 3 网络和 3D ResNet 并转换成 TFRecords 文件。本文描述了构建和训练这些模型的过程。随后,对结果进行分析和比较,得出一系列实施阿尔茨海默病计算机诊断模型的建议。
第一步
- 导入需要使用的主库。
2.声明常量,这些常量定义 TFRecords 文件的路径以及用于保存定型模型和所有定型、验证和测试信息的目标文件夹。
3.定义一种方法来计算三种标签在测试集上的 AUC。注意这个方法是如何被设计来接收一个训练好的模型和测试数据的。
盗梦空间 V3
随着近年来将预训练 ImageNet 网络用于医疗应用的成功趋势[1] — [4],创建的 2D 数据集用于微调 Inception V3 网络。完整的代码,包括几个测试和实验,可以在这里查看。在本文中,描述了主要过程。
第一步是解码 TFRecords 数据,检索图像数据和类标签。为此,创建了以下方法:
使用这些方法,可以定义训练张量和验证张量。此外,还会导入 Keras 预定义的 InceptionV3 网络。
对 Keras 中定义的默认 InceptionV3 模型的唯一修改是具有 512 个单元和 80%的下降正则化的最终层,以及最终的 softmax 层。
在第一个训练阶段,只有新定义的最后两层用 Adam 优化器训练 10 个时期,使用 1 e-4 的学习率和 8 的批量。还设置了 0.001 的学习率衰减。
接下来,对整个网络进行微调,将历元的数量增加到 70 个,并将学习速率衰减到 1 e-7 ,并保持其余的超参数值不变。分类交叉熵是损失函数,准确性也被监控以指导训练过程。然而,值得注意的是,由于类别不平衡,准确性不是一个很好的指标[5],因此指导本实验的主要评价指标是 AUC。在本文的后面部分,将介绍和讨论获得的最佳 AUC。
该模型还被训练为在 MCI 类上执行欠采样,当与 AD 或 CN 相比时,MCI 类被过度表示。然而,正如之前其他研究表明的那样[5],这种策略并没有改善结果。
ResNet3D
实施的第二种方法基于适用于体积数据的残差网络,在 Keras 上实施,完整代码可在此处查看。在这种情况下,3D 数据集用于训练。与 2D 数据相比,解码 3D TFRecords 数据的过程略有不同:
训练一个 3D 建筑是一个非常慢的过程,它增加了对更多图像的需求。一般来说,网络越复杂,需要处理的信息越多,需要学习的观察数据就越多。由于这些限制,只对两个最小的可用网络进行了测试,分别由 18 层和 34 层组成。
18 层 3D ResNet 的最后一层被移除,并添加了一个具有 512 个单元的全连接层,具有 80%的下降率和最后的 softmax 层。这是为 Inception V3 模型执行的相同过程。使用 Adam 优化器对其进行 50 个时期的训练,学习率为 10e 5,批次大小为 8。分类交叉熵被用作损失函数,准确性也被监控。模型很容易陷入过度拟合,所以用控制 L2 正则化的正则化因子( r eg_factor)进行了一些实验。最佳值介于 0.03 和 0.05 之间,它们之间的差异很小。
使用 70 个时期,用类似的超参数训练 34 层 3D ResNet。训练一个 50 层的网络是难以忍受的,因为只有三个时期需要大约 30 分钟。
结果
为了研究实施的网络的潜力,进行了几次培训尝试,但由于基础设施的限制,交叉验证和其他更严格的验证技术是不可能的,这意味着谷歌联合实验室不是一个适合长期培训大规模网络的平台。尽管如此,从结果中可以得出有趣的结论。
微调 Inception V3 网络始终比训练 3D 残差网络产生更好的结果,这可能是因为网络复杂性和可用数据量的差异。然而,在两种模型上的训练是高度不规则的,并且控制过度拟合成为一项困难的任务。例如,图 1 示出了当训练 Inception V3 模型时验证损失和准确性的演变。其他训练尝试产生了类似的结果,具有阶梯状曲线和不规则的结果。与训练损失(图 2)相比,只有具有较高正则化因子(0.05)的 ResNet3D-18 保持了验证损失的适度发展,但总体结果最终比初始 V3 或较低正则化因子(0.03)更差。
图一。当训练 70 个时期的 Inception V3 模型时,准确性(左)和损失(右)的演变。结果非常不规则
图二。训练正则化因子为 0.05 的 18 层 ResNet3D 时精度(左)和损失(右)的演变
尽管准确性和损失的演变并没有表明结果接近可以被认为是体面的,但当查看测试预测的 ROC 和 AUC 值时,可以得出非常不同的结论。图 3 示出了通过微调 Inception V3 网络获得的最佳结果。该模型保持了一种非常简单的方法,是三级分类中最强的模型之一,正如在研究 AUC 值时的现有技术中所述。值得注意的是,代表性过强的阶层也是该模式遇到最大困难的阶层(MCI)。同样的情况也发生在[1]中,这里的过度表示不太明显,所以这些困难可能是这些类的本质所固有的。
图 3。通过微调 Inception V3 网络获得最佳结果。无欠采样
图 4 示出了通过训练 18 层 ResNet3D 获得的最佳结果。将深度增加到 34 层并没有导致更好的结果,尽管由于训练的缓慢,对这种深度的实验是有限的。尽管如此,通过微调 Inception V3,结果明显更好,因此使用 3D 架构似乎没有任何有趣的潜力,至少在标记数据有限的情况下。
图 4。使用 ResNet3D、18 层和正则化因子 0.03 获得最佳结果
分析和讨论
将结果与当前的技术水平联系起来,应该考虑两个出版物。在[1]中,作者保留了基于 2D 变换和微调 Inception V3 的类似方法。该出版物中获得的结果高出约 5 个百分点,AD 类的 AUC 为 0.98,而本研究中获得的 AUC 为 0.93。然而,这两项研究之间存在着值得注意的关键差异。
第一,扫描类型。虽然在这项工作中使用了 T1 加权 MRI 图像,但在[1]中使用了 18FGD-PET 图像。这种差异很重要,因为 MRI 图像更便宜,对病人无害[6] — [8]。这可能会导致对使用 MRI 图像进行阿尔茨海默病计算机诊断的兴趣增加。
第二,基于简单性的方法。尽管 2D 转化过程非常相似,但该出版物的作者执行了更复杂的步骤。例如,“通过选择代表超过 100×100𝑚𝑚的脑实质的最颅侧和最尾侧部分,使用连通分量分析来导出相关的成像体积”[1]。一个更简单的过程,像在这个实验中执行的过程,被证明能够产生体面的,虽然明显较差的结果。此外,在这项研究中,图像配准和颅骨剥离进行了易于使用的工具。
关于 3D 网络,考虑了[9]中的结果。该研究还试图通过直接使用 3D 图像和体积残差网络来保持一种非常简单的方法。当考虑本研究中获得的最佳模型时,结果非常相似。例如,在[9]中 AD 对 NC 的 AUC 约为 0.87,而两类的 AUC 达到 0.89,如图 5 所示。这里的关键区别在于,这项研究执行三类分类,而在[9]中,作者构建了多个二元分类器。一方面,本研究获得的结果可以表明,多类分类是一个同样可行的发展道路。另一方面,值得一提的是,在[9]中,考虑的是平均值,而在本文中,考虑的是最大值。由于硬件限制,无法执行进一步的验证。
最后,应该注意的是,这些类型的模型在真正的临床环境中部署之前还有很长的路要走。直接看结果,很难说它们足够精确。然而,其他研究也确实与放射科医生进行了直接比较,并得出了令人惊讶的结论,表明这些模型明显更优越[1],[10]。在这种情况下,最好的模型应该总是直接与人类专业人员进行比较,以便提取真实质量的度量,并估计在真实环境中部署它们是否真的可行。
推荐
在对结果进行彻底分析并与近年来的其他重要工作进行比较后,可以向开始研究基于人工智能的阿尔茨海默氏症诊断系统的数据科学家提出一系列建议。
首先,应该注意的是,卷积神经网络的使用应该是直接的选择,因为它们实际上捕获了一般医学图像分析中的所有应用,而不仅仅是在阿尔茨海默氏病诊断中。
其次,说到数据,可以说 ADNI 数据库包含了足够高质量的图像来构建好的模型。这是可以从以前的工作中得出的结论[9]。然而,处理这些信息有点复杂,因为可用的开源工具并不完美,尤其是在颅骨剥离方面。可取的做法是对图像进行分组处理,或者根据在 ADNI 系统上存储之前对图像进行的预处理步骤,或者甚至根据获取图像的硬件的特性;寻求适当地调整分数强度阈值(在 FSL 下注的情况下)。问题是,管理阈值是否正确的唯一方法是直接观察结果,对于非常大的图像集,这可能非常昂贵。
第三,图像注册工具工作得很好。它们足以自动处理图像,只要它们被注册到相同模态的图谱(在本工作的情况下,T1 加权),并且所有图像被归一化到相同的空间分辨率。在这一点上,应该注意,空间分辨率越高,得到的图像就越大,并且每个体素将代表更小的区域。这表明使用 1𝑚𝑚的各向同性分辨率对于细节来说会更好,但是更大尺寸的图像会使训练过程更慢。所以是时间和硬件能力的问题。
第四,关于图像的结构,将图像转换成 2D 是可取的,即使这是通过一个非常简单的程序,如在这项工作中使用的程序。3D 网络的训练要复杂得多,速度更慢,效果更差,至少在可用数据的情况下是如此。另一方面,2D 网络训练速度更快,而且有各种各样的先进模式可供微调。此外,它们更直观,因为它们需要像放射科医师那样以类似的方式定位问题,分别检查多个切面或切片。
第五,就扫描类型而言,MRI 和 PET 都可以使用。后者不需要颅骨剥离,并且在其他出版物中显示了极好的结果,但是它们获得起来更昂贵并且对患者更有害。另一方面,MRI 价格低廉,对患者无害,但需要更仔细的预处理。最终,选择归结于可用性和利益相关者的偏好。
第六,决定如何进行培训也很重要。一般来说,使用公认的架构,比如 Inception 或 ResNet,应该是默认的选择,因为它们已经被证明在各种各样的应用程序中非常好。在这项工作的情况下,使用小批量和小学习率已经获得了更好的结果。Adam 之类的自适应优化器也非常适合。此外,最近的工作也遵循这些准则[1],[9]。
最后但同样重要的是,主要建议是不要部署这种类型的系统。疾病的诊断是一个极其敏感的问题,不仅需要出色的结果——在写这几行字的时候还没有达到——还需要对模型的可靠性进行深入的检验。在未来的几年里,越来越多的可用数据将缓解这些问题,但目前还需要更多更好的研究。
参考
[1] Y. Ding 等,利用脑的 18F-FDG PET 预测阿尔茨海默病诊断的深度学习模型 (2018),放射学,第 290 卷,第 2 期,第 456–464 页
[2] V. Gulshan 等人,用于检测视网膜眼底糖尿病视网膜病变的深度学习
算法的开发和验证
照片 (2016),Jama,第 316 卷,第 22 期,第 2402–2410 页
[3] S. Vesal,N. Ravikumar,A. A. Davari,S. Ellmann 和 A. Maier,使用迁移学习对乳腺癌组织学图像进行分类 (2017),PLoS One,第 12 卷,第 6 期,第 812-819 页
[4] A. Esteva 等人,皮肤病学水平的皮肤癌分类
与深度神经网络 (2017),《自然》,第 542 卷,第 7639 号,第 115 页
[5] M. A. Mazurowski、P. A. Habas、J. M. Zurada、J. Y. Lo、J. A. Baker 和 G. D. Tourassi,为医疗决策训练神经网络分类器:不平衡数据集对分类性能的影响 (2008),《神经网络》,第 21 卷,第 2–3 期,第 427–436 页
[6] Hoffman,John M .等人病理证实的痴呆患者的 FDG PET 成像 (2000)《核医学杂志》,第 41 卷,第 11 期,第 1920-1928 页
[7] Nordberg,Agneta 等人PET 在阿尔茨海默病中的应用 (2010)《自然评论神经学》,第 6 卷,第 2 期,第 78-87 页
[8] Pichler,Bernd J .等人 PET/MRI:为下一代临床多模态成像应用铺平道路 (2010)《核医学杂志》,第 51 卷,第 3 期,第 333-336 页
[9] S .科洛列夫、a .萨菲尤林、m .贝尔亚耶夫和 y .多多诺娃,用于 3D 大脑 MRI 分类的残差和普通卷积神经网络 (2017),IEEE 第 14 届国际生物医学成像研讨会(ISBI 2017),第 835-838 页
[10]klp pel,Stefan 等人痴呆症诊断的准确性——放射科医生和计算机化方法之间的直接比较 (2008)《大脑》,第 131 卷,第 11 期,第 2969-2974 页
我是那个分析 Reddit AITA 帖子的数据怪胎吗?是的。
原文:https://towardsdatascience.com/am-i-the-data-geek-who-analyzed-reddit-aita-posts-yes-4954a8d37055?source=collection_archive---------16-----------------------
我们试图用主题建模、情感分析和一些好的统计数据来回答我们这个时代的经典问题。
照片由 苏珊 Q 尹 上 下
是数据集一直在呼唤我的名字。我不太确定这说明了我什么。
自从我听说它,我就想探索一个来自红迪网帖子的数据集,它来自一个著名的叫做的子编辑“我是个混蛋吗?” (AITA),用户发布冲突的故事,在这些故事中,他们不确定自己是否做了正确的事情,或者相反,嗯,是个混蛋。其他用户根据他们的判断进行评论和投票:你是混蛋(YTA),不是混蛋(NTA),这里每个人都很烂(ESH),这里没有混蛋(NAH),或者信息不够(Info)。
图片经由 GIPHY
该数据集包含超过 97,000 个帖子的文本,以及投票结果和每个帖子的评论数量。只有大约 27%的案例中,用户给出了 YTA 或 ESH 的判断,这意味着几乎四分之三的案例被判断为不包含任何错误。这实际上是对人性和我们担心做正确的事情的倾向的安慰。
尽管混蛋只是少数,我们可以进一步挖掘这个复杂的人类情况的丰富数据集。这是很多文本,但我们在 Alteryx Designer 中有必要的工具,还有来自Alteryx Intelligence Suite的文本挖掘调色板。
我决定使用这些工具和数据调查工具面板来探索 AITA 邮报中有趣的模式。享受这个稍微有点粗鲁的情感分析、主题建模和相关性复习。也许我们会在这个过程中对人类行为有更多的了解。
一些 AITA 帖子的标题和判断
AITA……
当我的狗舔我的胳膊时,我替它把口水擦掉了?(NTA)
因为在 2013 年过期的 sriracha 酒瓶上发表评论?(YTA)
因为我只想把我的秘密圣诞礼物送给他们的猫?(NTA)
因为我把我室友所有发霉的脏盘子和垃圾放在她的浴室里?(NTA)
因为对这个大富翁游戏感到不安?(YTA)
把糖果藏在商店里,这样我就可以在打折的时候买了?(YTA)
匆忙做出判断:文本分析的三个简单步骤
数据集非常干净(至少从数据的角度来看),所以我只是整理了一些小的文本格式问题,并为原始帖子的长度创建了一个新变量。我认为,看看帖子的长度——情况的复杂性和/或某人认为他们必须解释自己的程度——是否与其他变量相关会很有趣。
在对文本进行任何其他处理之前,我使用了情感分析工具来评估每个帖子的标题和正文的积极、中性或消极价值,或情感权重。VADER,这个工具背后的算法,被设计成即使在包含 NSFW 单词,表情符号,夸张的标点符号的文本上也能很好地工作!!!以及社交媒体内容中的其他奇怪现象。所有这些都应该原封不动地留给情感分析。
图像通过 GIPHY
然而,在主题建模之前,我准备了更多的文本。文本预处理工具处理了这个大任务。(请在我们关于文本规范化的帖子的第一部分和第二部分T21 中阅读相关内容。)这个工具基于 Python NLP 库 spaCy ,它会对文本进行归一化和过滤。它做了一件奇怪的事情:它用符号-PRON-代替了代词。如果你在互联网上呆过一段时间,你可能会怀疑 spaCy 指的不是代词。实际上,这个缩写是它在文本中对代词的替代。我用公式工具中的 REGEX_Replace 函数从标题和处理后的文章文本中删除了所有这些符号。
然后,我将主题建模工具添加到工作流中,将其配置为来识别帖子中的三个主题。由此产生的可视化非常容易解释;看看下面的 GIF 图,看看出现的主要话题。
话题一:工作/工作;话题二:浪漫/友谊;主题 3:家庭(作者图片)
基于每个话题的关键词列表和对 AITA 语境的了解,这三个话题可以说代表了“家庭问题”、“爱情/朋友关系冲突”和“工作/工作问题”在主题间距离图中,这三个主题被很好地分开,描述每个主题的单词列表也很有意义。主题建模工具还为数据集中的每个帖子添加每个主题的分数,反映该主题在帖子中出现的程度。
在超过 97,000 个帖子中快速找到主要主题,并分析其中的情绪,这真是太棒了。但是这些主题和情绪水平与用户对 AITA 的评价有联系吗?为了找到答案,我打开了数据调查工具面板,看看我们能在这些帖子和回复中找到什么样的模式。
图像通过 GIPHY
调查一个洞和情绪
列联表工具使得比较分类变量并查看它们的值如何一致变得容易。这是一个更近距离观察情感分析结果和 AITA 判断的好方法。我们可以用数据集中提供的“is _ 屁眼”变量来比较标题和帖子的正面或负面情绪。(如果最终投票结果不是混蛋,这里没有混蛋,或者信息不够,is _ 混蛋变量为 0,如果结果是你是混蛋或者这里的每个人都很烂,变量为 1。)
也许令人惊讶的是,就数量而言,被判定为含有虚假内容的标题和帖子的情感价值并没有太大的区别。积极的帖子实际上比消极的帖子更容易被认为是 YTA 或 ESH。
帖子情感与屁眼存在的对比(图片由作者提供)
使用关联分析工具稍微深入一点,我们可以检查出我们的情感价值分数、主题得分和我添加的帖子长度变量之间的相关性。我选择了“目标字段进行更详细的分析”选项,以获得这些变量与“is _ 屁眼”变量关系的 p 值。
这里我们看到,有点令人惊讶的是,虽然在头衔和帖子中的负面情绪与无知没有显著的相关性,但在头衔和帖子中的正面情绪却有。所以对一种情况持积极态度可能会让你更有可能被 YTA,或者至少你会被别人这样评价。
作者图片
当然,皮尔逊相关是基于变量之间的线性关系;我们也可以尝试一下 Spearman 相关工具,它的计算并没有假设线性关系。与皮尔逊相关一样,越接近-1 或 1 的值分别表示越强的负相关或正相关。
职位的积极性和“是混蛋”之间的 Spearman 相关系数是 0.31。标题越正面,越有可能被判定为无信仰。(有了这个数据集,我们不得不有点怀疑;例如,一个正价值很高的帖子标题是“最好的朋友聚会便壶惨败”VADER 可能会被“最好的朋友”和“派对”这两个快乐的词搞得有点晕头转向,但不会注意到标题中最后两个相关的词。)
《AITA 邮报》最正面的标题,最初都以“AITA”开头(图片由作者提供)
帖子的积极性和 is _ 屁眼之间的 Spearman 相关性只有 0.04,所以标题在设定选民的期望方面可能更重要(尽管我们不能假设这有因果关系)。
图像通过 GIPHY
家里和工作上的漏洞
关于感情,说够了;哪些话题似乎涉及到最多的学问?当人们分享家庭、爱情/友谊或工作时,他们更容易被认为是混蛋吗?我们可以看看上面的相关性来进行比较,但也可以把它们看作类别。我确定了每个帖子的三个主题中哪个得分最高,然后比较了这些主题是如何被全面评判的。另一个列联表工具揭示了下面的比较。
作者图片
事实证明,坏行为在我们的生活中分布相当均匀,至少根据这些情景和判断是这样的。Reddit 的投票者对家庭和工作情况稍微宽容一些,对爱情/友谊问题的判断稍微严厉一些,但比例并没有太大不同。
图片经由 GIPHY
什么让人们感兴趣?
如果你对 YTA 很好奇,并想把你的困境提交给 AITA 的选民,怎样才能让人们投票或评论你的帖子呢?该数据集中的“得分”变量代表一篇帖子获得的净投票数(上投票数减去下投票数),它自然与评论数高度相关(皮尔逊相关系数为 0.83)。总体而言,对 YTA 或 ESH 的评价与帖子的评论数量之间只有轻微的相关性,与分数的相关性非常小。
事实证明,如果你在帖子中谈论你的家庭(上面结果中的话题 3),或者至少写很多,人们可能会稍微更有可能参与其中。但是不要写一个听起来积极的标题,因为标题的积极程度与评论和分数有轻微的负相关。
量化人类行为,好的和坏的
对《AITA 邮报》的分析表明,如何快速将大量非结构化文本信息提取为主题和情感洞察,并以多种不同方式进行分析。这种方法可以用于你的社交媒体内容、产品评论、调查回复和许多其他类型的文本数据,也可以集成到预测模型中。不管你的项目是什么,我希望你能发现在你的数据中混蛋也是少数。
推荐阅读
- 使用文本预处理工具进行分词和过滤停用词
- 我们关于主题建模的系列文章,从开始进入主题建模的要点|第 1 部分——什么是 LDA?
- 嗬,嗬…嗷!利用主题建模识别假日危险
- 更多关于皮尔逊积差相关(又名皮尔逊相关)和斯皮尔曼等级顺序相关
原载于 Alteryx 社区 数据科学博客 。
从 3.7 到现在 Python 中添加的主要特性
原文:https://towardsdatascience.com/amazing-features-added-to-python-from-3-7-to-now-4f35f0bb1ea6?source=collection_archive---------14-----------------------
Python 3.7–3.9 中添加的最佳新特性概述
扬西·敏在 Unsplash 上的照片
随着 Python 3.7 的发布,2018 年为我们带来了大量的新功能,随后是 2019 年的 3.8 和 2020 年的 3.9。
许多这些变化都是幕后发生的。优化和升级,我们绝大多数人永远不会注意到,尽管他们的好处。
其他的更明显,语法或功能的增加会改变我们写代码的方式。但是即使这些可见的变化也很难跟上。
在本文中,我们将浏览更明显的升级,对 Python 在过去几年中的所有新东西提供一个简短但有价值的回顾。
**> Python 3.7**
- Breakpoints**> Python 3.8**
- Walrus Operator
- F-string '=' Specifier
- Positional-only Parameters**> Python 3.9**
- New Parser
- More Type Hinting
- Dictionary Unions
如果你喜欢视频,我已经在这里浏览了所有内容(包括代码):
Python 3.7
断点
有时,或者实际上,几乎总是——代码调试令人沮丧。Python 3.7 包含了breakpoint()
,使得它不那么烦人了。
这个新功能允许我们直接在脚本中添加断点,如果我们看到一个我们根本无法解决的错误,我们可以添加breakpoint()
来停止代码,并允许我们尝试找出是什么导致了错误。
breakpoint() 默认使用 pdb 调试器,但是也可以使用其他替代调试器。
然后我们可以运行代码,它将在我们的断点处中断,并为我们提供一个交互式 shell 来测试我们的代码。
它允许我们用不同的数据类型/变量打印、测试我们的函数——并简单地做我们需要做的事情来调试我们的代码。
在 PEP 553 中阅读更多相关信息。
Python 3.8
海象操作员
大多数人已经看过了 walrus operator,它是任何人在 3.8 版本中报道新特性的首选。
除了作为 Python 语法的有趣补充之外,操作符确实非常有用。它允许我们“动态地”给变量赋值。
这意味着我们可以编写更紧凑的代码。虽然下面不是一个好的用例,但它清楚地表明了操作员可以做什么。
如果没有 walrus 操作符,我们需要在进入 if 语句之前赋值 t_len 。
这里我们需要检查一个列表的长度,如果它超过了一定的长度,打印一个关于它的长度大于三的声明。
walrus 运算符允许我们将变量赋值和 if 语句合并成一行,如下所示:
我们可以使用 walrus 操作符编写更紧凑的代码。
或者更有用的例子是使用 RegEx,我们需要检查模式是否存在,如果匹配,返回匹配的模式:
与 RegEx 一起使用的 walrus 运算符示例。
PEP 572 涵盖了你想知道的关于海象运营商的一切。
f 字符串“=”说明符
调试的另一个好特性。当打印 f 字符串时,我们可以添加=
来打印变量名和值,如下所示:
= '说明符可以在 f 字符串中使用,以返回变量名和值。
一个更小但仍然有用的附加物。在 bpo-36817 中有全面的介绍。
仅位置参数
3.8 的最后一个特性是包含了指定函数输入参数的语法,这些参数不能通过名字调用,而是通过位置调用。例如:
我们可以通过给定的关键字指定输入参数,也可以不指定——有时强制用户不指定是有益的。
在这里,我们可以通过给定的名称来指定输入参数——在大多数情况下这是有意义的。
但是,有时这可能是我们想要阻止的行为。例如,如果我们正在编写一个函数,其中输入参数的名称将来可能会改变。
我们可能希望避免让用户指定输入参数名,这样我们就可以在将来毫无问题地更改变量名。
如果我们和函数的其他用户指定输入参数名,然后我们更新该函数以使用不同的变量名——我们可能会破坏使用该函数的所有其他代码库。
为了阻止用户使用输入参数名,我们可以添加仅位置语法/
。让我们看看当添加到我们的原始代码中时,这是如何表现的:
如果我们试图通过关键字指定一个仅定位的参数,我们将收到一个 TypeError。
我们看到在/
之前定义的所有参数都引发了一个 TypeError。这防止用户从一开始就使用这些变量名**。现在,用户将不得不使用op
的位置,而不是关键字:**
添加仅位置参数意味着用户将被迫通过位置而不是关键字来指定参数。
因此,当我们将来将op
改为method
时,我们的用户会受到保护:
现在,当用户从使用 op 的旧函数切换到使用方法的新函数时——他们不会注意到差异——也不会破坏他们的代码。
在 PEP 570 中阅读所有相关内容。
Python 3.9
我已经在这篇文章中写了更多关于 Python 3.9 的内容,但是我将在这里总结所有内容。
新解析器
虽然这不会立即带来任何新的语法,但它仍然是重要的,并会在今后导致一些大的变化。
吉多·范·罗苏姆在 30 年前写了之前的 Python 解析器 pgen。这是为 Python 编写的第一批代码之一。
Pgen 使用基于 LL(1)的语法的变体。这意味着解析器从上到下、从左到右地读取代码,只需一个标记的前视。****
这造成了一些限制:
- 单标记前瞻限制了语法规则的表达能力**。**
- 非 LL(1)语法的实现需要 Python 开发人员做大量混乱的工作**。**
- 左递归语法会导致解析树无限循环,导致栈溢出**(这里解释)。**
从 Python 3.9 开始。CPython 将使用基于 PEG 的解析器**,我们将从 Python 3.10 开始看到它的影响。你可以在 PEP 617 这里了解更多。**
更多类型提示
Python 中类型提示的稳步引入和改进是过去几年 Python 中反复出现的主题。
简而言之,他们引入了一个可选的语法层**,帮助我们理解代码中需要哪些数据类型。**
无类型提示(左),Python 3.9 类型提示(右)。
在上图中,我们有不带类型提示的代码(左)和带类型提示的代码(右)。 Python linter 也将通读这段代码,并识别在我们的类型提示定义的数据类型和实际使用的数据类型之间哪里看起来不匹配。
指定预期的输入和输出数据类型。
我们也可以使用-> type
语法来确定函数的输出数据类型**。**
我们可以将不同的类型结合起来创建更复杂的注释。
或者我们也可以定义更复杂的数据类型。 PEP 585 涵盖了 Python 3.9 中的类型提示。
字典联盟
Python 操作符的另一个有趣的补充。两者都用于字典联合。我们有合并操作符|
:
a = {1: **'a'**, 2: **'b'**, 3: **'c'**}
b = {4: **'d'**, 5: **'e'**}c = **a | b**
print(c)
[Out]: {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}
以及更新操作符|=
,它允许我们进行就地合并**:**
a = {1: 'a', 2: 'b', 3: 'c'}
b = {4: 'd', 5: 'e'}**a |= b**
print(a)
[Out]: {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}
在 PEP 584 中阅读更多关于字典联合操作符的内容。
这就是本文的全部内容,涵盖了 Python 在过去几年中的一些最大变化和升级。
当然,还有大量的特性我们没有在这里介绍。但是,当使用 Python 时,这些是最明显的和产生最大差异的。
Python 3.10 的开发始于 2020 年中期,我们可以期待 2021 年 10 月的完整发布。
尽管如此,这些新特性足以让您跟上 Python 的发展和演变。在即将到来的 Python 3.10 变化中,有很多东西需要学习。
我希望你喜欢这篇文章!如果您有任何问题,请通过 Twitter 或在下面的评论中告诉我。如果你想要更多这样的内容,我也会在 YouTube 上发布。
感谢阅读!
资源
[1]吉多·范·罗苏姆, PEG 解析器 (2019)。
🤖《变形金刚》课程 NLP 的 70%折扣
*所有图片均由作者制作,除非另有说明。
亚马逊红移 vs 谷歌大查询:最大的 OLAP 数据仓库之战
原文:https://towardsdatascience.com/amazon-redshift-vs-google-bigquery-battle-of-the-biggest-olap-data-warehouses-8311241b2c91?source=collection_archive---------47-----------------------
会是亚马逊吗?还是谷歌会拿走蛋糕?让我们找出答案
对于大数据领域的企业来说,拥有灵活、可扩展、同时经济高效的数据仓库势在必行。鉴于现代企业越来越多地将大数据视为在所有领域提升的解决方案;从客户支持到生产进度,分析数据仓库对大多数业务需求都变得至关重要。
虽然数据分析的世界仍在蓬勃发展,但大型企业已经通过自己的数据仓库成功地在市场上站稳了脚跟。处于大数据热潮核心的行业巨头亚马逊和谷歌提供了备受追捧的数据仓库 Redshift 和 BigQuery。我将在今天的博客中分析这两个最大的在线分析处理(OLAP)数据仓库,以帮助您选择更好的解决方案来满足您的数据需求。但是在我们深入研究这两个数据仓库哪一个更好之前,我将带您简单了解一下什么是数据仓库。请继续阅读。
这是一个大数据仓库!
娜娜·斯米尔诺娃在 Unsplash 上的照片
数据仓库可以简单地认为是一个存储容器或存储大量数据以供处理的地方。现在,从这个仓库获取某些信息的过程,或者处理数据查询的方式,在体系结构方面从一个仓库到另一个仓库是不同的。此外,与存储容器的大小以及其中可以存储或处理的内容量类似,数据仓库也有其自身的限制和功能,企业可以根据这些限制和功能找到自己的最佳选择。现在,让我们详细看看两个强大的 OLAP 数据仓库。
AWS 红移
亚马逊红移是一个数据仓库,是电子商务巨头亚马逊网络服务(AWS)云计算平台的一部分。Redshift 于 8 年前首次发布,它允许企业用户从少量数据(几百千兆字节)开始,直到高达数千兆字节的数据,所有这些都借助云的力量实现。
它是如何工作的?
Redshift 是一款快速且经济高效的 BI 工具,使用标准 SQL 存储所有数据,以集群或块的形式存储数据,与传统或本地数据仓库相比,可以实现更快的无缝查询。聚类格式最大限度地减少了信息输入或输出的实例,以便只关注相关的信息提取。
与传统的数据仓库不同,Redshift 允许您对 TB 级到 Pb 级的结构化和半结构化数据进行复杂的分析查询。它使用复杂的查询优化、列存储和跨多个物理资源的并行查询执行。
通过使用熟悉的基于 SQL 的客户端和使用标准开放式数据库连接(ODBC)和 Java 数据库连接(JDBC)的 BI 工具,Redshift 承诺了令人印象深刻的快速查询功能,大多数在几秒钟内返回。
在定价方面,Redshift 允许您以每小时 0.25 美元的价格从几千兆字节的数据开始,以每年 1,000 美元的价格扩展到千兆字节和千兆字节,成本不到传统内部解决方案的十分之一。它还包括亚马逊红移光谱,以帮助您直接对亚马逊 S3 数据湖中的非结构化数据运行 SQL 查询。
即使数据量很大,Redshift Spectrum 也会根据检索到的数据自动扩展计算能力,以便针对亚马逊简单存储服务或 S3 进行更快的查询。更何况不需要加载,也不需要改造。可以使用开放数据格式,包括 Avro、CSV、Grok、Amazon Ion、JSON、ORC、Parquet、RCFile、RegexSerDe、Sequence、Text、胡迪、Delta 和 TSV。
红移一览:
- 快速且经济高效
- 以分栏格式存储数据
- 成本不到传统内部解决方案的十分之一
- 并行查询执行
- 直接允许 SQL 查询
- 通过 AWS IAM 集成、列级访问控制、VPC、加密等实现安全。
- 使用复制和连续备份来提高性能
最佳使用案例
Redshift 非常适合处理需要实时分析的时间敏感型工作负载的企业。例如,每日股市指数报告、广告竞价或实时仪表板。Redshift 上的预测模型允许近乎实时的广告竞价。需要通过刷新进行连续查询的实时数据流用例也处理得令人印象深刻。
谷歌大查询
Google BigQuery 是搜索巨头自有云基础设施 Google Cloud 下的另一个受欢迎的数据仓库。无服务器的多云数据仓库旨在处理海量数据,同时保证灵活性和可伸缩性。
它是如何工作的?
BigQuery 的核心是 Dremel —谷歌的查询服务,允许你对庞大的数据集运行 SQL 查询,并在几秒钟内获得准确的结果!因此,BigQuery 是 Dremel 的外部化,使用 Rest API、命令行界面、web UI 和访问控制向第三方开发人员提供其核心特性集。为了估计它的潜力,Dremel 可以在几十秒内扫描 350 亿行而不用索引。通过共享谷歌自己的云基础设施,它可以将每个查询并行化,并同时在数万台服务器上运行。
回到 BigQuery,它与 Dremel 共享相同的架构和性能特征。通过利用谷歌的计算和云基础设施,好处包括跨区域的多次复制和高数据中心可扩展性,而不需要开发者的任何管理。
BigQuery 还以一种称为 Capacitor 的列格式存储数据。表中的每一列都存储在单独的文件块中,所有列都存储在单个电容器文件中,然后对该文件进行压缩和加密。
它允许使用标准 SQL 跨云进行数据分析。它是完全管理的,针对企业的大规模数据处理。BigQuery 的一个关键的与众不同的特性是它更加兼容 AI 和 ML。它允许您使用自然语言处理(NLP)获得数据洞察力,提供内置的 ML 和 AI 集成,提供 ODBC 和 JDBC 驱动程序,并使用谷歌的工具提供无缝数据集成。
BigQuery 概览:
- 与大型数据集兼容
- 支持人工智能、人工智能集成
- 非程序员的易用性
- 依赖于谷歌自己的云基础设施
- 使用文件系统存储数据
- 快速且自我管理
最佳使用案例
顾名思义,当数据查询高峰且空闲时间很长时,BigQuery 处于最佳状态。一些例子包括每天运行一次的电子商务网站上的推荐、偶尔需要复杂查询的季度报告、团队通过自定义数据分析进行特别发现的销售智能,以及最重要的用于发现和分析数据模式(如消费者行为)的机器学习。
共性
考虑到这两个数据仓库都有满足 BI 需求的潜力,很明显它们提供了一些共同的特性。以下是其中一些例子:
- SQL 标准:BigQuery 和 Redshift 都支持标准的 SQL 数据类型。但是,前者适用于一些标准的 SQL 数据类型。
- 更新和删除:这两个工具都是仅追加的,但是如果查询出错,它们可以处理更新和删除。
- 安全性:Redshift 使用 Amazon IAM,而 BigQuery 使用 Google Cloud IAM,允许安全的身份管理。
竞争优势
- 集成:Redshift 和 BigQuery 都提供了大量的集成。然而,Google 的 BigQuery 因其 ML 集成而脱颖而出,使数据科学家能够在结构化或半结构化数据上构建和操作 ML 模型。
- 可扩展性:借助 Redshift,企业无法独立扩展资源,因为存储和计算不是分开的。任何微调都需要集群重新配置,这是一个耗时的过程。另一方面,BigQuery 将存储和计算分开,提供了更大的灵活性和更多的可伸缩性。
- 维护:红移需要定期清空或表分析。你可能会花费数小时做简单的维护,如更新。BigQuery 维护性低;它没有索引或列约束,并且不允许性能调优功能。这是一个完全由谷歌管理的服务,处理所有的后端配置和调整。
- 定价:使用 Redshift,您可以从每小时 0.25 美元开始,扩展到数 Pb 的数据和数千个并发用户,总计每年每 TB 1000 美元。您还可以选择按需定价,根据集群中节点的类型和数量按小时付费。Redshift 还提供基于频谱、扩展、存储和部署 ML 模型的现收现付定价模式。另一方面,BigQuery 对数据存储、流插入和查询数据收费,但加载和导出数据是免费的。有两种订阅模式—每 TB 5 美元的现收现付价格和 100 个保留插槽每月 1,700 美元起或 100 个灵活插槽每小时 4 美元起的统一价格。
谁拿了蛋糕?
如果您是一家处理数据的企业,并希望赶上新时代的数字化转型,Redshift 和 BigQuery 都是非常有前途的数据仓库解决方案。由于处理大型数据查询和提供快速准确结果的潜力相似,在这两种服务之间做出决定可以归结为工作流的性质和 BI 需求。
在我看来,谷歌的 BigQuery 是一个比 Redshift 更健壮的解决方案,因为它提供了额外的功能,如 ML 集成。以谷歌自己的云基础设施为核心,它是一个更具性价比的工具。它是完全受管理的,这减少了部署系统工程师在使用 Redshift 时根据需要不断进行微调的需要。对于更大的数据量和不同的查询负载,BigQuery 非常适合。
最初发表于【https://anujsyal.com】。
亚马逊 SageMaker 和🤗变压器:使用自定义数据集训练和部署汇总模型
原文:https://towardsdatascience.com/amazon-sagemaker-and-transformers-train-and-deploy-a-summarization-model-with-a-custom-dataset-5efc589fedad?source=collection_archive---------18-----------------------
深入探讨新发布的端到端模型培训和部署功能
Igor Saveliev 在 Pixabay 上拍摄的照片
2021 年 3 月 25 日,亚马逊 SageMaker 和 HuggingFace 宣布了一项合作,旨在利用可访问的变形金刚库,让训练最先进的 NLP 模型变得更容易。 HuggingFace 深度学习容器开放了大量预先训练的模型,可直接与 SageMaker SDK 一起使用,从而轻松为工作提供正确的基础设施。
从一个已经在一个巨大的语料库上训练过的模型开始也意味着,为了在你的特定用例上获得良好的性能,你不需要获取一个非常大的数据集。在本教程中,我将带您完成以下 3 个步骤:
- 在一个定制的数据集上微调一个摘要模型:这将需要准备您的数据用于摄取,并启动一个 SageMaker 培训工作;
- 将微调后的模型部署到 SageMaker 托管服务:这将自动提供一个托管您的模型的持久端点,您可以从中获得实时预测。
- 在我们的本地机器上启动一个 Streamlit 应用程序来与您的模型进行交互;这是一个开源框架,允许您从非常简单的 Python 脚本创建交互式 web 应用程序,常用于 ML 和数据应用程序。
我们将从设置一个 SageMaker Notebook 实例开始,在这里我们将运行本教程的代码。您可以按照这些说明来设置您的笔记本电脑环境;ml.m5.xlarge Notebook 实例类型应该就可以了。继续启动一个新的 Jupyter 笔记本,带有一个conda_pytorch_p36
内核。我们需要的所有软件包都预装在笔记本电脑环境中。
如果你打算遵循本教程中的代码,现在是将这个回购克隆到你的实例中的好时机。有三个笔记本(数据准备、微调和部署),其中包含接下来的代码片段。做完那件事,让我们开始吧!
模型和数据集
出于本教程的目的,我们将使用 PEGASUS 模型,以及在 Transformers Github 资源库中可用的微调脚本。您可以将脚本原样用于 PEGASUS 的,以及 HuggingFace 模型中枢中可用的其他几个序列到序列模型,例如[BART](https://huggingface.co/facebook/bart-large)
和[T5](https://huggingface.co/t5-large)
(参见脚本的自述文件的支持的架构部分中的所有合适选项)。
脚本向用户公开配置和超参数选项,同时负责适当的文本标记化、训练循环等。您可以通过两种方式之一提供您的数据集,要么是 1) 指定一个dataset_name
(将从hugging face Dataset Hub)或 2) 您本地数据文件的位置(test_file
、validation_file
和test_file)
);我们对后者感兴趣。我们将会看到,这些文件是在培训时从亚马逊 S3 下载的。
极端摘要(XSUM)数据集包含约 225,000 篇 BBC 文章及其摘要,涵盖各种领域。在第一个笔记本中,我们下载数据集,并提取每篇文章的正文和相应摘要。然后,我们将数据分为训练集和验证集,并将每个数据集的 CSV 文件上传到 S3。这些文件中的每一行对应不同数据样本的**text,summary**
;这种格式在训练脚本中被自动识别(保留 CSV 头)。上面的自述文件详细说明了如何以更通用的方式使用 CSV 或 JSONLINES 文件,以及如何在文件有多个额外列的情况下指定正确的列名。
微调
现在,我们已经准备好为培训作业设置配置和超参数了!首先,我们定义一些导入,并检索我们的 SageMaker 执行角色、会话和默认 S3 存储桶:
然后,我们将超参数传递给[HuggingFace](https://sagemaker.readthedocs.io/en/stable/frameworks/huggingface/sagemaker.huggingface.html#huggingface-estimator)
估计器,以及其他一些配置:
一个评估器是一个抽象,它封装了 SageMaker SDK 中的训练;因为 git 支持是内置的,所以我们可以直接指定训练脚本名称和目录为entry_point
和source_dir
,以及git_config
中的 repo 和 branch。PyTorch、Transformers 和 Python 版本对应于撰写本文时 HuggingFace 容器中支持的最新版本。
在不耗尽 GPU 内存的情况下,这个特定模型在一个ml.p3.2xlarge
实例上可计算的最大批量大约为 2。这个容量将取决于其他因素,例如我们为输入序列定义的最大长度。由于这是一个相当大的数据集,如果你想增加批量大小,大幅加速训练,可以利用 SageMaker 分布式数据并行训练;这个特性已经被集成到Transformers
训练器 API 中,所以你可以利用它,除了你在上面代码片段中看到的最小设置之外,不需要改变你的训练脚本。
hyperparameters
将作为命令行参数传递给微调脚本。我们定义了训练参数(比如时期数和学习率),以及训练容器中数据所在的目录。在文件模式下,SageMaker 从 S3 下载你的数据,使其在/opt/ml/input/data/<channel_name>
目录下可用。当您调用Estimator.fit()
——有效地开始训练作业——时,您提供< channel_name >,以及训练和验证集在 S3 的相应文件位置。
培训工作结束后,一个model.tar.gz
文件会上传到你在 S3 上默认的session_bucket
;它将包含部署我们的微调模型和服务推理请求所需的模型和记号化器工件。
部署
最后,我们将微调后的模型部署到一个持久端点。SageMaker 托管将公开一个 RESTful API,您可以使用它从您的模型中实时获得预测。
在inference_code
目录下,你会找到脚本inference.py
。这对流程很重要,它详细描述了:1)如何在端点之间转换输入和输出,2)如何将模型加载到推理容器中,以及 3)如何从模型中获得预测。这个脚本必须有一个特定的结构,这样 SageMaker 就知道你的代码的哪一部分用于这些不同的功能。
我们首先定义一个[HuggingFaceModel](https://sagemaker.readthedocs.io/en/stable/frameworks/huggingface/sagemaker.huggingface.html#sagemaker.huggingface.model.HuggingFaceModel)
,包含关于模型和推理代码位置的细节:
注意,我们可以通过使用huggingface_estimator.model_data
获得模型工件的 S3 URL;另外,entry_point
和source_dir
指定推理脚本的名称和目录(存储在您的笔记本上)。
然后,我们将模型部署到一个ml.m5.xlarge
实例:
一旦部署完成,您可以直接使用predictor
对象从您的模型中获得预测。注意,我们可以传入任何模型的生成参数;在这种情况下,我们指定length_penalty
——一个实数,如果>为 1,则激励生成更长的摘要,反之亦然*。我们将在测试中使用一个新闻更新示例:*
我们可以看到,在总结这个具体的新闻故事时,长度参数的变化非常有意义,因为较短的摘要忽略了较长摘要中透露的一条重要信息:计划停电的原因*。*
启动一个简单的 Streamlit 界面
*为了不必一直通过手动运行代码行来与您的模型进行交互,此时您将在本地机器上部署一个 Streamlit UI。正如您在脚本streamlit_app.py
中看到的,Streamlit 允许我们用 30 多行代码创建一个直观且响应迅速的界面。在这段代码中,我们将使用用于 Python 的 SageMaker 运行时 Boto3 客户端,以不同于以前的方式调用我们的 SageMaker 端点。您需要在您的本地环境中设置适当的权限,或者通过使用 AWS CLI 配置您的凭证,或者直接将它们作为参数传递给客户端。
首先,打开一个新的终端并运行以下命令来安装 Streamlit:*
*pip install streamlit*
要启动界面,请运行以下命令:
*streamlit run \
streamlit_app.py -- --endpoint_name summarization-endpoint*
*这将在localhost
上启动您的应用程序,默认监听端口 8501。运行该命令后,应该会自动弹出一个浏览器标签,但如果没有,就访问http:localhost:8501
。
这是界面的样子:*
现在,您甚至可以更新/切换支持应用程序的模型端点,这样您就可以在不同的数据集上进行重新训练或微调后对其进行实时测试!
结论
*在这篇博文中,我们看到了如何利用 HuggingFace SageMaker 估计器的固有功能来微调最先进的摘要模型。最重要的是,我们使用了一个自定义数据集和一个现成的示例脚本,您可以复制这些东西,以便轻松地根据您个人/公司的数据训练模型。
我们还看到了如何轻松地获得最终的微调模型,将其部署到完全受管的端点,并通过调用简单的 Streamlit 接口的*。
在现实生活场景中,您将能够轻松地优化和扩展该流程的各个部分,如设置自动缩放以基于负载自动启动更多端点实例,将 GPU 的一部分[附加到您的端点以加速推理,以及许多其他有用的功能。
我希望你现在能够更快地利用大量可用的 NLP 资源。下次见!](https://docs.aws.amazon.com/sagemaker/latest/dg/ei.html)**
附:非常感谢Heiko Hotz激励并支持这篇博文的创作。
参考文献
[1] J. Zhang,Y. Zhao,M. Saleh,P. Liu, PEGASUS:用于抽象概括的提取间隙句的预训练 (2020)第 37 届机器学习国际会议论文集
【2】s .纳拉扬,S.B .科恩,m .拉帕塔,不要给我讲细节,只讲概要!用于极端摘要的话题感知卷积神经网络(2018)2018 年自然语言处理经验方法会议录
亚马逊 SageMaker 快速文件模式
原文:https://towardsdatascience.com/amazon-sagemaker-fast-file-mode-d12829479c39?source=collection_archive---------11-----------------------
提示和技巧
从亚马逊 S3 向亚马逊 SageMaker 传输训练数据的方法——第二部分
由 Christina Rumpf 在 Unsplash 上拍摄的照片
去年我们发表了一篇博文,其中我们调查了将存储在亚马逊 S3 中的训练数据流式传输到亚马逊 SageMaker 训练会议的不同方法。我们强调了不同选项的一些优势和劣势,并检查了它们解决某些特定需求的能力,例如:
- 动态增强,需要在训练过程中改变数据采样方式。
- 自由选择除 TFRecord 格式以外的数据格式,以及
- 随机访问数据记录。
上个月,AWS 向宣布了一个名为快速文件模式 (FFM)的新机制,用于利用来自亚马逊 S3 的数据在亚马逊 SageMaker 进行培训。在这篇文章中,我们将回顾这种新方法的一些特性,并将其与我们在上一篇文章中回顾的一些替代方法进行比较。
正如在我们之前的帖子中,我们处理的场景是数据集的大小如此之大,以至于在训练之前将它完整地下载到本地磁盘是不可能的或低效的。相反,我们将数据直接从 S3 传入训练循环。我们将把重点放在 TensorFlow 的培训上,特别是 2.6 版,尽管我们将进行的大多数观察也同样适用于其他培训框架。
快速文件模式——工作原理
要对您的 Amazon SageMaker 培训课程进行编程,以使用快速文件模式从 S3 传输数据,您需要将 input_mode 设置为 FastFile ,并输入您的数据集 S3 路径到 fit 函数,如下面的代码块所示:
*from sagemaker.tensorflow import TensorFlow
estimator=TensorFlow(entry_point='main.py',
role=<AWS IAM role>,
py_version='py37',
framework_version='2.6.0', #tf version
instance_count=1,
instance_type='ml.g4dn.xlarge',
**input_mode='FastFile'** )**train_data="s3://sagemaker-path-to-train-data"
test_data="s3://sagemaker-path-to-test-data"**estimator.fit(**{'train':train_data, 'test':test_data}**)*
这里我们定义了两个通道,分别命名为训练和测试*。训练作业将从对应于两个数据通道的两个环境变量 SM_CHANNEL_TRAIN 和 SM_CHANNEL_TEST 开始。每一个都将被设置为一个本地路径,该路径对于培训应用程序来说就像是 S3 编程路径中所有数据的 POSIX 文件系统挂载。因此,为了访问位于S3://sage maker-path-to-train-data/relative-path的文件,而不是下载文件(例如,使用 boto3),训练应用程序将简单地打开:
path=os.path.join(os.environ["SM_CHANNEL_TRAIN"],<relative-path>)
例如,如果您的文件以 TFRecord 格式存储,您可以使用TF record dataset创建一个数据集,如下面的代码块所示:*
**paths=[<list of relative filepaths>]
local_root=os.environ["SM_CHANNEL_TRAIN"]
filepaths=[os.path.join(local_root,path) for path in paths]
ds=tf.data.TFRecordDataset(
filepaths,
num_parallel_reads=tf.data.experimental.AUTOTUNE)**
FFM 的优势
在我们之前的博客文章中,我们介绍了将数据从 S3 传输到亚马逊 SageMaker 培训课程的几种选择。在本节中,我们将重点介绍 FFM 相对于其他方法的一些优势,尤其是 Amazon SageMaker 管道模式的替代方案。关于管道模式的更多细节,请查看之前的帖子。
1.多数据集支持
正如我们在过去的中讨论过的,管道模式支持的数据流数量被限制为 20(截至本文撰写之时)。使用多个数据流可以解决某些需求,例如数据分区(其中我们根据类别对数据进行分区)或流复制(例如,在执行数据分布式训练时,以独特的洗牌方式将相同的数据集流式传输到多个进程)。正如这篇博文中所详述的,对频道流数量的限制可能会带来挑战,这可能需要创造力来克服。通过 FFM,可以使用单个数据通道配置定义多个数据集。您只需将通道的基本 S3 路径配置为所有数据集的根。
2.增强对数据输入流的控制
当您对作业进行编程以使用管道模式时,您可以配置一组通过管道传输的固定文件,并且可以选择将洗牌和/或分片委托给管道模式管理器。一旦培训开始,您就不能更改管道的内容或其配置。相对于管道模式,FFM 提供了更大的控制:
- 洗牌 —您可以应用自己的数据洗牌策略,也可以捕获随机生成的参数。
- 分片 —你可以定义自己的分片策略。
- 在训练期间更新数据集内容 —您可以在模型训练期间更改数据的混合。
- 文件块支持 — FFM 支持读取文件的一部分,而无需提取整个文件。这可能会影响您在 S3 选择数据的文件格式,因为有些格式依赖于文件分块。请注意,虽然可以使用文件分块(假设文件格式合适)来实现对数据记录的随机访问,但这可能会严重影响性能。然而,您可以通过分析您的机器学习项目的最小可接受块大小来实现某种程度的随机访问。
在下面的代码块中,我们演示了如何创建一个自定义生成器来控制(和记录)混洗、分片和在训练中更改数据混合。
**import random
def generator():
paths=... # optionally shard filepaths
for e in range(num_epochs):
seed=random.randrange(100)
print(f"starting epoch {e}. Random seed is {seed}")
random.seed(seed)
random.shuffle(paths)
# optionally modify contents based on current metrics
paths=...
for p in paths:
yield pfilepaths_ds=tf.data.Dataset.from_generator(
generator,
output_types=tf.string,
output_shapes=())
ds=tf.data.TFRecordDataset(
filepaths_ds,
num_parallel_reads=tf.data.experimental.AUTOTUNE)**
这里的参见如何利用该方案实现两个类的动态增强的示例。
3.文件格式自由
虽然管道模式可以配置为传输任何二进制数据,从而传输任何文件格式,但高级别亚马逊 SageMaker SDK 仅通过PipeModeDataset为 TFRecord 文件格式提供支持。在管道模式下使用任何其他文件格式都需要一点努力。与管道模式相反,FFM 并不偏爱任何一种文件格式。
在之前的帖子中,我们调查了用于 TensorFlow 培训的几种不同的文件格式选项。使用 FFM 你可以自由使用其中任何一个。
请记住,在云中存储文件有一些最佳实践。特别是,这些实践规定了最佳的文件大小。我们通常将数据存储在大小为几百 MB 的文件中。
另一个考虑因素是文件的数量。根据 FFM 文档,培训开始时间可能会受到文件总数的影响。
4.使用标准 TensorFlow 数据集类
如上所述,使用 FFM 时,我们可以使用与本地环境中相同的标准 TensorFlow 数据集类。这与管道模式相反,后者需要一个特殊的自定义数据集 PIPEmodeDataset。这有几个含义:
- 更易于编程——将您的代码从本地培训课程调整到基于云的培训课程所需的修改更少。
- 更容易调试—与本地运行的相似性使得调试问题更容易。
- API 支持-使用标准化 TensorFlow 数据集意味着自动支持所有 TensorFlow 数据集实用程序 API。
性能比较
在本节中,我们将在由TF record文件组成的数据集上对 FFM、管道模式和直接 S3 访问进行性能比较。我们比较的指标是:1 .平均数据吞吐量,以每秒的记录数度量,以及 2。平均 CPU 利用率。为了评估输入模式对潜在 CPU 瓶颈的影响程度,测量 CPU 利用率非常重要。我们用来执行测试的代码可以在下面的代码块中找到:
***count = 0
begin = time.time()
stime = begin
for x in ds:
count = count + 1
if count % 1000 == 0:
etime = time.time()
print(f"step: {count} step/sec: {float(1000)/(etime-stime)}")
stime = time.time()
if count==100000:
break
print(f"average step/sec: {float(100000)/(time.time()-stime)}")***
请注意,我们通过迭代数据集将我们的分析隔离到管道的数据输入部分,而没有将数据实际输入到训练管道中。测试是在 ml.c5.xlarge 实例类型上执行的。结果如下图所示。在我们已经运行的测试中,FFM 拥有最好(最低)的步长时间,管道模式紧随其后。同时,注意 CPU 利用率的增加。这些结果是您可能会看到的比较指标类型的一个示例。这些指标可能高度依赖于您的模型架构,并且您得到的结果可能非常不同。例如,如果您的步进时间目前完全由您的 GPU 活动决定,您可能对数据输入模式完全不感兴趣。
输入模式性能比较(按作者)
摘要
最近宣布的亚马逊 SageMaker 快速文件模式提供了一种新的方法,可以将训练数据直接有效地传输到亚马逊 SageMaker 训练课程中。它提供了管道模式的潜在性能以及本地数据集的便利性和灵活性。重要的是,每个机器学习项目都是独一无二的;在一个模型中观察到的绩效行为可能与在另一个模型中观察到的完全不同。在转换项目之前,评估采用 FFM 的性能影响至关重要,并建议您以一种使流选项之间的切换变得容易的方式对解决方案进行编码。祝你好运!
亚马逊 SageMaker 管道:在云中部署端到端的机器学习管道
原文:https://towardsdatascience.com/amazon-sagemaker-pipelines-deploying-end-to-end-machine-learning-pipelines-in-the-cloud-9199b637e8ca?source=collection_archive---------29-----------------------
使用当前最先进的工具之一,构建一个从原始数据到模型部署的机器学习管道
一级方程式赛车每年都会汇集最好的车手、最好的赛车和最好的技术。对于后者,他们使用像 SageMaker 这样的 AWS 工具。卡尔·乔根森在 Unsplash 上的照片
介绍
云计算是机器学习领域发展最快的技能之一。在云服务公司中,亚马逊因提供最先进的机器学习工具之一而脱颖而出:亚马逊 SageMaker。使用 SageMaker,除了其他许多事情之外,你还可以构建、测试和部署机器学习模型。此外,您可以创建端到端的管道,以便在 CI/CD 环境中集成您的模型。
在这篇文章中,我们将使用 Amazon SageMaker 一步一步地创建端到端的管道。首先,我们将对项目做一个概述,然后我们将进行一些理论解释,最后但同样重要的是,我们将编码。对于编码部分,我们将使用这个 Jupyter 笔记本。
我们将使用成人人口普查收入数据集。我们将使用“收入”作为目标变量,这是一个解释一个人收入是否超过 50k 的二元变量。对于训练步骤,我们将使用 AWS 提供的 XGBoost 图像。
项目概述
在解释如何建立管道之前,我认为首先理解计划是至关重要的。再往下一点,你会发现一张管道图,这将是我们创建管道的蓝图。如果你能理解这个图表,一半工作就完成了(剩下的只是把它放进代码里)🙈 ).但是,在查看图表之前,我认为先了解这些事情是有益的:
- 我们的管道中有哪些步骤
- 每一步的输入和输出是什么
为了理解这一点,我们将以直观的方式解释流水线中的所有步骤:
📒注意:尽量记住文件名,这样你就更容易理解图表。
- 预处理步骤:在这一步我们将预处理原始数据。因此,这一步的输入是原始数据,输出是经过处理的数据(准备好传递给模型的数据)。在我们的项目中,原始数据是“成人. csv”文件,处理后的数据文件名将是“train.csv”、“validation.csv”和“test.csv”。
- 训练步骤:在这一步我们将训练模型。此步骤中的输入是经过处理的数据,特别是“train.csv”和“validation.csv”文件。输出将是我们训练好的模型。这个文件叫做“model.tar.gz”。
- 评估步骤:在这一步中,我们将用新数据测试我们的模型。输入将是模型文件和带有测试数据的文件,即“model.tar.gz”和“test.csv”。输出将是存储该步骤的元数据(例如精度)的文件。我们将称之为“evaluation.json”。
- 条件步骤:在交付之前,我们必须知道我们的模型是否足够好。在条件步骤中,我们将测试精度与阈值进行比较。如果精度高于阈值,我们继续下一步。如果不是,我们停止管道,这样模型就不会被部署。
- 创建模型步骤:如果模型通过了条件步骤,我们创建一个 SageMaker 模型。SageMaker 模型是可以部署到端点的实例。
- 注册模型步骤:如果模型通过了条件步骤,我们将注册模型,这样我们就可以随时访问它。在 SageMaker model registry 中,您可以拥有一个模型及其相应元数据的目录。
一旦我们了解了所有这些,让我们来看看期待已久的管道图:
作者图片
📒注意:“创建模型步骤”和“注册模型步骤”是独立的步骤:它们之间没有特定的顺序。
好了,现在我们知道了计划,是时候学习理论了!
萨格马克管道理论:我们需要知道什么
这一节只是试图回答以下问题:在开始编码之前,您必须了解 SageMaker 管道的哪些知识?
首先你必须理解 SageMaker 构建管道的方式是首先指定管道的步骤,然后用一个管道实例将它们连接起来。
为了创建管道步骤,我们使用步骤类。在开始编码之前,有两个步骤类特别重要:一个是ProcessingStep
类,另一个是TrainingStep
类。
ProcessingStep 类
对于我们的“预处理步骤”和“评估步骤”,我们将使用一个ProcessingStep
类(你可以在这里看到文档)。基本上,这是 SageMaker 用来构建我们处理数据的步骤的类。当构建一个ProcessingStep
时,您必须传递一个处理器实例和代码。代码只是一个处理数据的 Python 脚本。处理器实例是一个 Docker 映像,带有运行该步骤的规范。
等等,所以我要创造一个码头工人的形象?
如果您愿意,您可以创建一个,但您不需要这样做。您可以只使用 SageMaker 提供和维护的处理器实例。最常用的有 SKLearnProcessor (针对 SKLearn)和 PySparkProcessor (针对 Apache Spark)。为了导入特定的图像,您可以使用 ScriptProcessor 实例。
📒注意:在我们的项目中,我们将为预处理步骤传递一个SKLearnProcessor
实例,为评估步骤传递一个ScriptProcessor
。对于ScriptProcessor
,我们将传递 SageMaker 提供的 XGBoost 图像。
关于这个话题的更多信息,你可以去这里。如果缺少了什么,不要担心,一旦你完成了动手操作部分,一切都会变得更加清晰。
训练步骤类
对于培训步骤,我们将使用TrainingStep
类(你可以在这里看到文档)。当指定一个TrainingStep
类时,你必须通过一个评估器。
有三种方法可以构建评估器:
- 使用内置算法:您可以从 SageMaker 存储库中导入一个评估者的图像。
- 在支持的框架中使用脚本模式:你可以在 Python 脚本中构建自己的算法,并使用支持它的框架。这比内置算法更加灵活。
- 自带容器:终于可以自己创建容器了。该选项比脚本模式和内置算法选项更灵活。
在我们的项目中,我们将创建一个 XGBoost 估计器,您可以在这里检查创建它的不同方法。您也可以查看 SageMaker 培训文档了解更多信息。
好了,现在我们大脑中有了所有这些信息,是时候编码了!
和 SageMaker 一起动手
⚠️ 警告 ⚠️:如果你正在读这篇文章,并且你完全是 AWS 的初学者,那么要小心:你将使用付费服务,所以你应该知道如何管理它。如果你了解 AWS 的基础知识(S3、EC2、IAM 角色、计费…),这个练习应该不成问题。你可以在 SageMaker 免费层下做,不需要支付任何费用。但是,小心点,完成后移除所有东西,因为如果你不这么做,迟早 AWS 会开始收费。我强烈建议你设置一个计费闹铃**,一旦费用超过特定阈值,它就会给你发一封电子邮件,以防万一。如果你是 AWS 的完全初学者,想学习基础知识,我强烈推荐你这个课程。**
如果你有信心,准备好了,那就去争取吧!
我们要做的第一件事是创建一个 SageMaker 工作室(如果你已经知道如何做,你可以跳过这一部分)。在 AWS 搜索栏中,搜索 SageMaker,点击 Amazon SageMaker。一旦你进入,点击侧边栏上的 Amazon SageMaker Studio:
作者图片
您可以使用快速启动选项创建一个工作室,只需输入一个名称并选择一个附加了 AmazonSageMakerFullAccess 策略的 IAM 角色。
📒注意:如果您不知道如何创建 IAM 角色,您应该在继续下一步之前创建,所以要小心。IAM roles 是一个您需要了解的工具,因为它可以处理安全问题。学习 IAM 角色如何工作可能是一件苦差事,但是请记住 AWS 是一个非常强大的工具。权力越大,责任越大。别忘了本叔叔。
创建工作室后,单击打开工作室。
作者图片
现在你加入了,你可以开始一个机器学习项目了!
对于我们的项目,你必须导入一个 Jupyter 笔记本和原始数据。你可以将这个 Github 仓库克隆到 Amazon Sagemaker Studio 中,方法是转到 Git,克隆一个仓库,
作者图片
并粘贴存储库的 URL。单击“克隆”后,您应该会在边栏中看到一个文件夹,其中包含笔记本和数据。
最后但同样重要的是,你可以通过进入内核,改变内核…
作者图片
Python 3(数据科学)适合我。
现在您已经准备好运行笔记本并构建 SageMaker 管道了!
我现在,你手中有一个完整的笔记本,也许你会想一次运行每个单元,看看它是否工作,但记住什么是最佳实践。我强烈建议您慢慢阅读代码和注释,并提取其中的要点。然后玩玩代码:我要求你尝试用不同的数据集复制管道,或者将内置的估计器改为用“支持的框架中的脚本模式”选项制作的估计器(参见使用 XGBoost 作为框架)。你也可以尝试实施新步骤。
一旦你用笔记本结束,你将知道如何用 Amazon SageMaker 创建一个管道!
AWS 是一个巨大的世界,你总能学到新的东西。如果你想了解更多,推荐你查看 SageMaker 开发者指南(特别是管道部分)亚马逊 SageMaker 示例笔记本及其 Github 资源库。也可以考虑做 DeepLearning 的实用数据科学专业。AI 和 AWS。
希望你学到了很多!感谢阅读!
参考
- 亚马逊 SageMaker 开发者指南
- 实用数据科学专业
- 亚马逊 Sagemaker 示例
亚马逊 SageMaker 工作室实验室:Google Colab 的绝佳替代品
原文:https://towardsdatascience.com/amazon-sagemaker-studio-lab-a-great-alternative-to-google-colab-7194de6ef69a?source=collection_archive---------15-----------------------
介绍 AWS 新的免费机器学习平台
斯科特·格雷厄姆在 Unsplash 上拍照
从机器学习开始可能是一个令人生畏的经历,尤其是如果你不是技术型的,也没有计算机方面的经验。Anaconda 是一个神奇的工具,但是它需要一些专业知识来正确设置和使用。此外,拥有一台强大的计算机对于在大数据集上训练机器学习模型是必要的,如果你对深度学习感兴趣,这一点尤其如此。幸运的是,有各种替代方法可以让初学者尝试机器学习,通过在云服务上轻松执行他们的代码。在过去的几年里,Google Colab 已经成为一种行业标准,因为它是一种用户友好的服务,只需创建一个 Google 帐户就可以轻松访问。亚马逊最近推出了 SageMaker Studio Lab ,这是一项提供有用特性和功能的替代服务。在本文中,我将介绍它的主要特性,并提供一个简短的教程来帮助您熟悉这项服务。我们开始吧!
服务介绍
SageMaker Studio 实验室提供了对 AWS 运行时的免费访问,这些运行时针对机器学习和深度学习任务进行了优化。如果您对技术规范感兴趣,CPU 运行时基于 T3.xlarge 实例,而 GPU 运行时运行在 G4dn.xlarge 上。每个运行时都带有 JupyterLab,这是一个基于 web 的界面,允许您创建和执行 Jupyter 笔记本,这是数据科学事实上的标准。此外,该服务提供 15 GB 的持久存储,让您存储数据集和实验结果。
访问 AWS 运行时非常有用。例如,在自己的计算机上安装 Anaconda 和 JupyterLab 有困难的人可以从中受益匪浅。此外,即使是有经验的用户也不总是能接触到强大的硬件,所以在这种情况下,利用云服务是一个很好的选择。最后,由于硬件短缺和各种其他原因,GPU 价格在过去几年中有所上涨。因此,利用 SageMaker Studio Lab 的 GPU 运行时对于那些买不起 GPU 卡的人来说将是无价的!
与 Google Colab 的比较
Google Colab 是 SakeMaker Studio Lab 的主要替代方案,所以我打算简单比较一下。Google Colab 是一项成熟的服务,被数百万数据科学家和机器学习工程师使用,因此该领域的大多数专业人士都已经熟悉它。在我看来,Google Colab 是精简且易于使用的,同时还具有高级协作功能,这是 SageMaker Studio 实验室目前有些缺乏的领域。
无论如何,应该注意的是,Google Colab 不提供持久存储,每次重启实例都会丢失数据。此外,谷歌 Colab 通常将特斯拉 K80 GPU 分配给免费账户,而更快的 GPU 则留给高级 Colab Pro 服务的订户。另一方面,sage maker Studio 实验室的 GPU 运行时利用了特斯拉 T4 模型,这是一种比特斯拉 K80 好得多的 GPU,因此使这项服务对那些对深度学习感兴趣的人具有吸引力。无论如何,这两种服务都是在云上运行 Jupyter 笔记本的绝佳选择。
SageMaker Studio 实验室入门
作者图片
首先,你需要访问这个链接并完成表格来申请一个免费的 SageMaker Studio 实验室账户。根据亚马逊的说法,申请通常会在 1 到 5 个工作日内获得批准,但我在提交表格后几个小时就可以访问我的帐户,所以你可能会很幸运。在您的帐户获得批准后,您可以使用您的凭据登录服务。
作者图片
登录 SageMaker Studio 实验室后,您只需选择您喜欢的实例类型,可以基于 CPU 或 GPU。在这种情况下,我决定启动 CPU 运行时,如屏幕截图所示。单击“启动运行时”按钮后,会话将启动并在接下来的 12 个小时内保持活动状态。如果选择 GPU 运行时,最长时间限制为 4 小时。当达到时间限制时,运行时将重新启动,但您的文件将保存到永久存储中。我们现在可以单击“打开项目”按钮来启动 JupyterLab 界面。
作者图片
我们现在使用的是 JupyterLab 环境,它提供了一些高级特性,比如执行 Python 代码、编写 Markdown 文本、在终端上运行 Linux 命令以及其他各种特性。此外,您可以通过使用pip
和conda
包管理器来安装任何您想要的 Python 包。如果你不熟悉 JupyterLab,我建议你阅读官方文档来熟悉它。
作者图片
如果你想熟悉 SageMaker Studio Lab,你可以克隆studio-lab-examples
库并用提供的笔记本进行实验。如屏幕截图所示,这可以通过启动终端并运行以下命令轻松完成。显然,您可以克隆任何其他可能有用的 Github 库。
git clone [https://github.com/aws/studio-lab-examples.git](https://github.com/aws/studio-lab-examples.git)
执行 Jupyter 笔记本
作者图片
在克隆了studio-lab-examples
存储库之后,我们现在将执行它包含的一个笔记本。我选择了EDA_weather_climate.ipynb
笔记本,但其余的过程是相似的。首先我们需要打开NOAA_Exploratory_Analysis
目录,右键点击env_eda.yml
文件。之后,我们选择“构建 Conda 环境”选项来创建一个 Conda 环境,其中包含该笔记本所需的所有软件包。这些命令将在新的终端上执行,该过程可能需要几分钟才能完成。
创建环境后,我们可以通过选择eda
内核来激活它。请记住,没有必要为每台笔记本电脑创建一个新的环境,但这被认为是最佳做法,这样我们可以避免包依赖冲突和其他问题。
作者图片
激活eda
Conda 环境后,我们只需选择“运行所有单元”来执行所有笔记本单元并渲染结果图,如上面的截图所示。
结论
很明显,亚马逊 SageMaker Studio Lab 是一项引人注目的服务,它提供了对 JupyterLab 环境的轻松访问,让任何人都可以从事机器学习项目。它的高级特性和功能使它成为 Google Colab 的一个很好的替代品,因此引入了竞争,这可能会激励 Google 改善其服务,也许是通过向 Colab 用户提供持久存储。因此,我鼓励你尝试 SageMaker Studio Lab,看看它是否适合你的需求!欢迎在评论中分享您的想法,或者关注我的 LinkedIn,我会定期在那里发布关于数据科学和其他主题的内容。你也可以访问我的个人网站或者查看我的新书,书名是用 PyCaret 简化机器学习。
亚马逊 SageMaker 初学者工作室实验室
原文:https://towardsdatascience.com/amazon-sagemaker-studio-lab-for-beginners-b5421b1550d3?source=collection_archive---------14-----------------------
使用 SageMaker Studio Lab、GitHub 和 Kaggle 数据集,探索学习 ML 是如何变得简单而有趣
尼克·莫里森在 Unsplash 上拍摄的照片
机器学习无处不在。今天,随便挑一篇文章或一个工业应用,你都会阅读或使用 ML。学习和实验 ML 最简单的方法是使用 Jupyter 笔记本。我们使用笔记本以自己选择的编程语言编写代码,用文本进行注释,并处理数据。每当我学习一个新的话题,我发现自己在 Evernote、Quip 或 notes 上草草记下笔记。然后我切换到 Word 或 PDF 文档来起草最终版本。涉猎 ML 应该没什么区别。你想快速开始并尝试 ML。
亚马逊 SageMaker Studio Lab 是什么?
Amazon SageMaker Studio Lab 是一个免费、无需设置的笔记本环境,旨在学习和试验 ML。如果你熟悉 Jupyter 笔记本,使用 SageMaker Studio Lab 会有宾至如归的感觉。最棒的是,你不需要建立一个 AWS 账户或使用信用卡。首先,用你的邮箱注册一个账户。
我使用 Amazon SageMaker Studio Lab 快速、轻松地对 ML 进行实验。无论您是学习 ML 课程的学生,还是运行许多 TensorFlow 模型的专家数据科学家,您都需要一个工具来试验 ML。
(注 :我是亚马逊 SageMaker 团队的产品经理,职业上不是数据科学家或者 ML 工程师。我每天都像你一样学习、呼吸和建造所有的东西。不过,你应该对我的意见有所保留😊)
我为什么要用它?
是单纯,是安心。SageMaker Studio Lab 让你花更多的时间学习 ML,而不是为数据科学建立基础设施。如果你想知道这与在笔记本电脑上设置自己的 Jupyter 笔记本或使用其他免费的笔记本解决方案有何不同,请继续阅读。
- 从头开始构建一个环境并管理它是一件痛苦的事情。您不想花时间设置数据科学环境。
- 你不希望注册一个云提供商,并在计算上花钱来试验 ML。
- 您希望有一个环境,即使您注销了帐户也能保存您的结果,并且每次登录时不会强迫您从头开始。
- 您希望从环境中快速连接到 GitHub 和 Kaggle 等服务以构建原型。
彼得·康伦在 Unsplash 上的照片
让我们试一试
首先,您需要从 SageMaker Studio 实验室网站申请一个新帐户。您将被添加到等待列表中,一旦您的帐户获得批准,您就可以登录了。
作者图片
登录后,您将看到项目界面,其中包含启动运行时、打开项目和运行示例的选项。选择**打开项目。**您将被带到您的项目,在那里您可以创建笔记本、终端、源代码、降价文件等等。
作者图片
让我们打开一个终端(文件>新建>终端或选择终端按钮)来检查配置。
作者图片
让我们检查一下 CPU 信息。如果选择计算类型作为运行时的 CPU,请运行以下命令。
作者图片
从项目登录页面,您可以通过切换计算类型从 CPU 切换到 GPU(反之亦然),运行时将使用新硬件重新启动。选择计算类型为 GPU 后,返回终端窗口并运行以下命令。
作者图片
接下来,让我们检查内存信息。
作者图片
您还可以使用以下命令检查 JupyterLab 版本。
作者图片
我们运行的是 JupyterLab 3.2.4,这是 JupyterLab 开源包的最新版本。现在我们已经看到了基本的硬件和软件配置,是时候创建和运行一个 ML 模型了。
你好 SageMaker 工作室实验室
我们将使用运行 PyTorch 的 SageMaker Studio 实验室构建一个图像分类 ML 模型。创建模型有三个步骤:
1.从 GitHub 打开笔记本
2.连接到 Kaggle 数据集
3.使用 PyTorch 训练图像分类模型
1.在 GitHub 中打开笔记本
最快的实验方法是从 GitHub 的笔记本开始。您可以使用天气数据图像分类笔记本并根据我们的需要进行调整。或者,我已经在 GitHub 中发布了笔记本,上面有我们将在这个实验中使用的自然图像数据集。
如果您登录到 SageMaker Studio 实验室,请打开上面的 URL。选择**复制到项目,**示例将加载到运行时中。确保您的运行时正在运行,计算类型为 CPU。
作者图片
2.从 SageMaker 工作室实验室连接到 Kaggle
我们将使用来自 Kaggle 的自然图像数据集和 8 个不同类别的 6.8K 图像。要下载和使用数据集,你需要一个 Kaggle 账户。
在 Kaggle 的帐户页面中,创建一个新的 API 令牌,如下所示。您的浏览器将下载 kaggle.json 文件,该文件包含通过命令行连接 kaggle 的凭证。
作者图片
将这个 JSON 文件上传到您的笔记本目录中。然后在笔记本中运行以下命令来安装 Kaggle 库并使用您的凭证。
导航到自然图像数据集页面并复制 API 命令以下载图像。
作者图片
在笔记本中添加一个新单元格,然后粘贴 API 命令。下载完成后,您可以解压缩该文件并将其重命名,以便与示例的其余部分一起使用。
3.规范化数据并训练模型
我们将更新示例以引用数据集中正确的图像类。
在数据集规范化下,使用以下数据集类
dataset_classes = ['airplane', 'car', 'cat', 'dog', 'flower', 'fruit', 'motorbike', 'person']
接下来,遍历将对数据进行规范化的单元格,加载 DenseNet 模型以对图像进行分类,并使用样本数据对模型进行微调。为我训练模型用了不到 10 分钟。
查看结果
模型训练完成后,您可以可视化图像子集的分类结果。
作者图片
您还可以查看模型的混淆矩阵。记住,对于这个示例,将类的数量更新为 8。
您现在可以在 GitHub 上发布您的笔记本,供其他人在 SageMaker Studio Lab 上使用。您也可以通过在 Markdown 或 HTML 中添加代码片段来添加一键启动按钮以加载您的笔记本。
将上面的笔记本网址替换为您在 GitHub 上的笔记本链接。
结论
我们在今天的预览版中看到了 SageMaker Studio Lab 的功能。具体来说,我们研究了如何在 GitHub 中打开笔记本并连接到 Kaggle 数据集。如果想深入学习,可以用几个 Jupyter 笔记本例子这里。如果你对 SageMaker Studio Lab 有任何问题,或者对上述实验有任何反馈,请随时发表评论,或者就堆栈溢出问题联系 #amazon-sagemaker 。
其他资源的链接
[1]吴恩达,斯坦福机器学习课程,Coursera
[2]吴恩达,深度学习专精,Deep Learning。人工智能
[3]张,阿斯顿和利普顿,扎卡里 c .和李,穆和斯莫拉,亚历山大 j .,潜入深度学习 (2021)
[4] AWS 机器学习大学 (2021)
【5】丹尼尔·伯克,‘我想学习人工智能和机器学习。我能从哪里开始? (2018),走向数据科学
伊恩·施耐德在 Unsplash 上拍摄的照片
感谢阅读!
使用 TigerGraph 和 Google Vertex 检测 AMLSim 欺诈第一部分:准备数据
原文:https://towardsdatascience.com/amlsim-fraud-detection-with-tigergraph-and-google-vertex-part-i-preparing-the-data-2f3e6487f398?source=collection_archive---------13-----------------------
使用 TigerGraph 运行图形查询以准备 AMLSim 欺诈检测数据集
这个项目是和德州陈 ( 领英)在乔恩·赫克 ( 领英)的帮助下共同创作的。它基于 Jon Herke 创建的 AMLSim Python Lab。
概述和目标
图形数据库最流行的用例之一是欺诈检测。在这篇博客中,我们将加载基于 IBM 的 AMLSim 项目的数据(我们将在这里使用来自实验室的数据),一个来自银行交易模拟的数据集。
在这个实验中,我们将利用 TigerGraph 的图形数据库和 Google Vertex 的机器学习来将交易分类为欺诈性或非欺诈性交易。
本博客将向您介绍如何使用 TigerGraph 创建 AML Sim 图,运行 pagerank 和 label prop 等图形算法,最后编写查询从 TigerGraph 中提取所需信息。我们开始吧!
第一部分:在 https://tgcloud.io/创建一个免费的 TigerGraph 解决方案
首先,你需要在https://tgcloud.io/创建一个免费的解决方案。这是我们存放图表数据库的地方。如果您还没有,请前往https://tgcloud.io/创建一个帐户。你可以在谷歌、LinkedIn 或电子邮件上注册。
注册或登录后,导航至左侧边栏中的“我的解决方案”选项卡,然后点击右上角的蓝色“创建解决方案”按钮。
转到“我的解决方案”选项卡,然后单击“创建解决方案”
在第一个选项卡上,从“选择初学者工具包”中选择“空白”选项。不要更改任何其他内容,然后按下一步。
单击空白,然后单击下一步。
第二步,不要修改任何东西(本质上这只是创建一个免费的解决方案),然后点击 next。
不要在这里修改任何东西,然后按下一步。
第三步,添加您的解决方案名称、标签、密码、子域和描述。请记住您的初始密码和子域!
注意:每个子域必须是唯一的,所以你可能无法使用我使用的相同的子域。
将此更新为您自己的
仔细检查第四步中的所有信息,然后按“提交”创建您的解决方案。创建您的解决方案可能需要几分钟时间。
仔细检查您的解决方案摘要是否正确,然后按提交!
恭喜你。您已经用 TigerGraph 创建了一个解决方案!现在,让我们转到笔记本来创建图表、加载数据、创建和运行查询!
第二部分:用 TigerGraph 创建一个 AMLSim 图
步骤 1:连接到您的解决方案
首先,我们将使用 pyTigerGraph 连接到我们刚刚创建的解决方案。pyTigerGraph 是一个用于 TigerGraph 的 Python 包,我们将使用它与我们的解决方案进行交互。
在 Colab 中,我们需要首先 pip 安装 pyTigerGraph,然后导入库。
!pip install pyTigerGraphimport pyTigerGraph as tg
太好了!现在,让我们连接到刚刚创建的解决方案。为此,我们可以使用 tg.TigerGraphConnection。
conn = tg.TigerGraphConnection(host="https://SUBDOMAIN.i.tgcloud.io", password="PASSWORD")
运行之后,您就可以连接并准备创建一个模式了!
步骤二:创建一个模式
现在我们要创建一个模式。这将由包括账户和交易在内的几个顶点组成,这些顶点将由无向和有向边连接。例如,帐户和交易顶点将用两条有向边连接:Send_Transaction 和 Recieve _ Transaction。
下面的代码将创建所有的顶点和边。
print(conn.gsql('''CREATE VERTEX Country (PRIMARY_ID id STRING) WITH primary_id_as_attribute="true"
CREATE VERTEX Customer (PRIMARY_ID id STRING) WITH primary_id_as_attribute="true"
CREATE VERTEX Account (PRIMARY_ID id STRING, init_balance DOUBLE, account_type STRING, tx_behavior INT, pagerank FLOAT, label INT, current_balance DOUBLE, min_send_tx DOUBLE, min_recieve_tx DOUBLE, max_send_tx DOUBLE, max_recieve_tx DOUBLE, avg_send_tx DOUBLE, avg_recieve_tx DOUBLE, cnt_recieve_tx INT, cnt_send_tx INT) WITH primary_id_as_attribute="true"
CREATE VERTEX Transaction (PRIMARY_ID id STRING, tx_behavior_id INT, amount DOUBLE, is_fraud BOOL) WITH primary_id_as_attribute="true"
CREATE VERTEX Alert (PRIMARY_ID id STRING, alert_type STRING, ts INT) WITH primary_id_as_attribute="true"CREATE UNDIRECTED EDGE Based_In (From Customer, To Country)
CREATE UNDIRECTED EDGE Customer_Account (From Customer, To Account)
CREATE UNDIRECTED EDGE Transaction_Flagged (From Transaction, To Alert)
CREATE DIRECTED EDGE Send_To (From Account, To Account) WITH REVERSE_EDGE="reverse_Send_To"
CREATE DIRECTED EDGE Send_Transaction (From Account, To Transaction, ts INT, tx_type STRING) WITH REVERSE_EDGE="reverse_Send_Transaction"
CREATE DIRECTED EDGE Recieve_Transaction (From Transaction, To Account, ts INT, tx_type STRING) WITH REVERSE_EDGE="reverse_Recieve_Transaction"''', options=[]))
接下来,我们将使用上面创建的所有顶点和边创建一个名为 AMLSim 的图(我们将把它作为参数传递给 CREATE GRAPH 函数)。
print(conn.gsql('''CREATE GRAPH AMLSim(Country, Customer, Account, Transaction, Alert, Based_In, Customer_Account, Transaction_Flagged, Send_To, Send_Transaction, reverse_Send_Transaction, Recieve_Transaction, reverse_Recieve_Transaction)''', options=[]))
现在,如果您返回到 https://tgcloud.io/的,点击“我的解决方案”选项卡,点击“操作”下的四个框(悬停值为“应用”),然后点击 GraphStudio,您将能够看到您创建的图表。
转到 GraphStudio。
单击“设计模式”查看全局模式。
模式的全局视图。
如果您单击“全局视图”,将会出现该解决方案中所有图表的下拉列表。您会注意到我们刚刚创建的图表 AMLSim 就在那里!点击那个。
您会注意到 AMLSim 是下拉选项之一。点击 AMLSim。
在“设计模式”中,您将再次看到您的模式!
AMLSim 图的架构。
如果您点击左侧边栏中的“加载数据”,您将能够看到加载到图表中的任何数据。
加载数据页面。
现在,没有数据加载,所以让我们改变这一点!
第三步:加载数据
让我们将数据加载到图表中。为此,我们首先需要从 GitHub 存储库中获取从 CSV 加载的数据。我们将首先导入 pandas 来读取 CSV,然后 git 克隆存储库。我们将使用 pandas 的 read_csv 函数来创建 csv 数据的数据帧,并将其分配给变量 accounts、alerts 和 transactions。
import pandas as pd!git clone https://github.com/TigerGraph-OSS/AMLSim_Python_Labaccounts = pd.read_csv("AMLSim_Python_Lab/data/accounts.csv", sep=",")
alerts = pd.read_csv("AMLSim_Python_Lab/data/alerts.csv", sep=",")
transactions = pd.read_csv("AMLSim_Python_Lab/data/transactions.csv", sep=",")
接下来,我们将把数据帧中的所有 id 列更新为字符串,而不是整数。
accounts['ACCOUNT_ID'] = accounts['ACCOUNT_ID'].astype(str)alerts['ALERT_ID'] = alerts['ALERT_ID'].astype(str)
alerts['SENDER_ACCOUNT_ID'] = alerts['SENDER_ACCOUNT_ID'].astype(str)
alerts['RECEIVER_ACCOUNT_ID'] = alerts['RECEIVER_ACCOUNT_ID'].astype(str)transactions['TX_ID'] = transactions['TX_ID'].astype(str)
transactions['SENDER_ACCOUNT_ID'] = transactions['SENDER_ACCOUNT_ID'].astype(str)
transactions['RECEIVER_ACCOUNT_ID'] = transactions['RECEIVER_ACCOUNT_ID'].astype(str)
现在,在我们将数据加载到图表中之前,让我们更新图表参数。我们将创建一个 API 令牌,并将 graphname 设置为 AMLSim。
conn.graphname = "AMLSim"conn.apiToken = conn.getToken(conn.createSecret())
最后,我们将使用 pyTigerGraph 中的 upsertVertexDataFrame 和 upsertEdgeDataFrame 函数将数据帧作为顶点和边向上插入到我们的图形中。
# UPSERT VERTEX "Customer"
v_customer = conn.upsertVertexDataFrame(accounts, "Customer", "CUSTOMER_ID", attributes={"id": "CUSTOMER_ID"})
print(str(v_customer) + " Customer VERTICES Upserted")# UPSERT VERTEX "Account"
v_account = conn.upsertVertexDataFrame(accounts, "Account", "ACCOUNT_ID", attributes={"id": "ACCOUNT_ID", "init_balance": "INIT_BALANCE", "account_type": "ACCOUNT_TYPE", "tx_behavior": "TX_BEHAVIOR_ID"})
print(str(v_account) + " Account VERTICES Upserted")# UPSERT VERTEX "Transaction"
v_transaction = conn.upsertVertexDataFrame(transactions, "Transaction", "TX_ID", attributes={"id": "TX_ID", "amount": "TX_AMOUNT", "is_fraud": "IS_FRAUD"})
print(str(v_transaction) + " Transaction VERTICES Upserted")# UPSERT VERTEX "Alert"
v_alert = conn.upsertVertexDataFrame(alerts, "Alert", "ALERT_ID", attributes={"id": "ALERT_ID", "alert_type": "ALERT_TYPE", "ts": "TIMESTAMP"})
print(str(v_alert) + " Alert VERTICES Upserted")# UPSERT EDGE "Send_Transaction"
e_send_transaction = conn.upsertEdgeDataFrame(transactions, "Account", "Send_Transaction", "Transaction", from_id="SENDER_ACCOUNT_ID", to_id="TX_ID", attributes={"ts": "TIMESTAMP", "tx_type": "TX_TYPE"})
print(str(e_send_transaction) + " Send_Transaction EDGES Upserted")# UPSERT EDGE "Send_Transaction"
e_recieve_transaction = conn.upsertEdgeDataFrame(transactions, "Transaction", "Recieve_Transaction", "Account", from_id="TX_ID", to_id="RECEIVER_ACCOUNT_ID", attributes={"ts": "TIMESTAMP", "tx_type": "TX_TYPE"})
print(str(e_recieve_transaction) + " Recieve_Transaction EDGES Upserted")# UPSERT EDGE "Send_To"
e_send_to = conn.upsertEdgeDataFrame(transactions, "Account", "Send_To", "Account", from_id="SENDER_ACCOUNT_ID", to_id="RECEIVER_ACCOUNT_ID", attributes={})
print(str(e_send_to) + " Send_To EDGES Upserted")# UPSERT EDGE "Transaction_Flagged"
e_transaction_flagged = conn.upsertEdgeDataFrame(alerts, "Transaction", "Transaction_Flagged", "Alert", from_id="TX_ID", to_id="ALERT_ID", attributes={})
print(str(e_transaction_flagged) + " Transaction_Flagged EDGES Upserted")# UPSERT EDGE "Customer_Account"
e_customer_account = conn.upsertEdgeDataFrame(accounts, "Customer", "Customer_Account", "Account", from_id="CUSTOMER_ID", to_id="ACCOUNT_ID", attributes={})
print(str(e_customer_account) + " Customer_Account EDGES Upserted")# UPSERT EDGE "Based_In"
e_based_in = conn.upsertEdgeDataFrame(accounts, "Customer", "Based_In", "Country", from_id="CUSTOMER_ID", to_id="COUNTRY", attributes={})
print(str(e_based_in) + " Based_In EDGES Upserted")# PRINT OUT STATS
print("=====TOTAL_UPSERTS=====")
print(str(v_customer+v_account+v_transaction+v_alert) + " TOTAL VERTICES")
print(str(e_send_transaction+e_recieve_transaction+e_send_to+e_transaction_flagged+e_customer_account+e_based_in) + " TOTAL EDGES")
最后,您可以转到 GraphStudio 中的 loading 选项卡,您会发现所有数据都被向上插入。
我们的图表中现在有数据了!
恭喜你。您已经用 TigerGraph 正式创建了一个图形数据库,创建了一个模式并加载了数据!现在,让我们编写一些查询和图算法来更新我们的图,并为机器学习做准备。
第三部分:创建和安装查询
查询 I:帐户活动
我们的第一个查询 accountActivity 将用于使用有关帐户活动的特性来更新图中顶点和边的属性。例如,它将更新帐户的当前余额、帐户的最大、最小和平均交易金额,以及帐户的交易数量。
print(conn.gsql('''CREATE QUERY accountActivity() FOR GRAPH AMLSim {SumAccum<DOUBLE> @s_sumAmt, @r_sumAmt;
SumAccum<DOUBLE> @s_txCnt, @r_txCnt;
MinAccum<DOUBLE> @s_minAmt, @r_minAmt;
MaxAccum<DOUBLE> @s_maxAmt, @r_maxAmt;
AvgAccum @s_avgAmt, @r_avgAmt;Seed = {Account.*};acctSend = SELECT tgt FROM Seed:s -(Send_Transaction:e)-> Transaction:tgt
ACCUM s.@s_sumAmt += tgt.amount, s.@s_txCnt += 1, s.@s_minAmt += tgt.amount, s.@s_maxAmt += tgt.amount, s.@s_avgAmt += tgt.amount
POST-ACCUM s.current_balance = s.@s_sumAmt - s.init_balance, s.min_send_tx = s.@s_minAmt, s.max_send_tx = s.@s_maxAmt, s.avg_send_tx = s.@s_avgAmt, s.cnt_send_tx = s.@s_txCnt;acctRecieve = SELECT tgt FROM Seed:s -(reverse_Recieve_Transaction:e)-> Transaction:tgt
ACCUM s.@r_sumAmt += tgt.amount, s.@r_txCnt += 1, s.@r_minAmt += tgt.amount, s.@r_maxAmt += tgt.amount, s.@r_avgAmt += tgt.amount
POST-ACCUM s.current_balance = s.@r_sumAmt + s.init_balance, s.min_recieve_tx = s.@r_minAmt, s.max_recieve_tx = s.@r_maxAmt, s.avg_recieve_tx = s.@r_avgAmt, s.cnt_recieve_tx = s.@r_txCnt;PRINT "Features Have Been Calculated";}INSTALL QUERY accountActivity''', options=[]))
查询二:label_prop
标签属性是一种图形算法。要了解更多信息,请访问德州陈的博客!你也可以在 TigerGraph 的算法页面了解。简而言之,这种算法试图找到社区,并根据其社区标记一个顶点。
print(conn.gsql('''CREATE QUERY label_prop (SET<STRING> v_type, SET<STRING> e_type, INT max_iter, INT output_limit, BOOL print_accum = TRUE, STRING file_path = "", STRING attr = "") FOR GRAPH AMLSim{OrAccum @@changed = true;
MapAccum<INT, INT> @map;
MapAccum<INT, INT> @@commSizes;
SumAccum<INT> @label, @num;FILE f (file_path);Start = {v_type};
Start = SELECT s FROM Start:s ACCUM s.@label = getvid(s);WHILE @@changed == true LIMIT max_iter DO
@@changed = false;Start = SELECT s
FROM Start:s -(e_type:e)-> :t
ACCUM t.@map += (s.@label -> 1)
POST-ACCUM INT maxV = 0, INT label = 0,
FOREACH (k,v) IN t.@map DO
CASE WHEN v > maxV THEN maxV = v, label = k
END
END,CASE WHEN label != 0 AND t.@label != label AND maxV > t.@num THEN
@@changed += true,
t.@label = label,
t.@num = maxV
END,
t.@map.clear();END;Start = {v_type};Start = SELECT s FROM Start:s
POST-ACCUM
IF attr != "" THEN s.setAttr(attr, s.@label) END,
IF file_path != "" THEN f.println(s, s.@label) END,
IF print_accum THEN @@commSizes += (s.@label -> 1) END
LIMIT output_limit;IF print_accum THEN
PRINT @@commSizes;
PRINT Start[Start.@label];END;}INSTALL QUERY label_prop''', options=[]))
查询三:page_rank
页面排序是另一种图形算法。要了解更多,请查看即将在德州陈的网页上发布的博客!你也可以在 TigerGraph 的算法页面了解。简而言之,这个算法将查看图中每个顶点对每个其他顶点的影响,并给它一个影响分数。
print(conn.gsql('''CREATE QUERY pageRank (STRING v_type, STRING e_type, FLOAT max_change=0.001, INT max_iter=25, FLOAT damping=0.85, INT top_k = 100, BOOL print_accum = TRUE, STRING result_attr = "", STRING file_path = "", BOOL display_edges = FALSE) FOR GRAPH AMLSim {TYPEDEF TUPLE<VERTEX Vertex_ID, FLOAT score> Vertex_Score;
HeapAccum<Vertex_Score>(top_k, score DESC) @@topScores;
MaxAccum<FLOAT> @@max_diff = 9999;
SumAccum<FLOAT> @recvd_score = 0;
SumAccum<FLOAT> @score = 1;
SetAccum<EDGE> @@edgeSet;FILE f (file_path);Start = {v_type};WHILE @@max_diff > max_change LIMIT max_iter DO
@@max_diff = 0;V = SELECT s FROM Start:s -(e_type:e)-> v_type:t
ACCUM t.@recvd_score += s.@score/(s.outdegree(e_type))
POST-ACCUM s.@score = (1.0-damping) + damping * s.@recvd_score, s.@recvd_score = 0, @@max_diff += abs(s.@score - s.@score');END; IF file_path != "" THEN
f.println("Vertex_ID", "PageRank");
END;V = SELECT s FROM Start:s
POST-ACCUM
IF result_attr != "" THEN s.setAttr(result_attr, s.@score) END,
IF file_path != "" THEN f.println(s, s.@score) END,
IF print_accum THEN @@topScores += Vertex_Score(s, s.@score) END;
IF print_accum THEN PRINT @@topScores;
IF display_edges THEN PRINT Start[Start.@score];Start = SELECT s FROM Start:s -(e_type:e)-> v_type:t
ACCUM @@edgeSet += e;
PRINT @@edgeSet;END; END;}INSTALL QUERY pageRank''', options=[]))
查询四:多重限制
这是我们将使用的最后一个查询。这个查询将能够获取我们想要的所有期望的属性。它将抓取前 1000 笔交易,订单基于是否欺诈。
print(conn.gsql('''CREATE QUERY txMultiHopLimit() FOR GRAPH AMLSim SYNTAX v2 { /* This grabs the first 1,000 transactions. The beginning has all of the fraudulent transactions and the latter part has some non-fraudulent transactions. */TYPEDEF TUPLE <BOOL tx_fraud, DOUBLE tx_amount, FLOAT s_pagerank, INT s_label, DOUBLE s_min_send_tx, DOUBLE s_min_receieve_tx, DOUBLE s_max_send_tx, DOUBLE s_max_recieve_tx, DOUBLE s_avg_send_tx, DOUBLE s_avg_recieve_tx, INT s_cnt_recieve_tx, INT s_cnt_send_tx, INT s_timestamp, FLOAT r_pagerank, INT r_label, DOUBLE r_min_send_tx, DOUBLE r_min_receieve_tx, DOUBLE r_max_send_tx, DOUBLE r_max_recieve_tx, DOUBLE r_avg_send_tx, DOUBLE r_avg_recieve_tx, INT r_cnt_recieve_tx, INT r_cnt_send_tx, INT r_timestamp> ORDER_TX;HeapAccum<ORDER_TX>(1000, tx_fraud DESC) @@txRecords;Seed = {Account.*};acctSend = SELECT tgt FROM Seed:s - ((Send_Transaction>):e1) - Transaction:v1 - ((Recieve_Transaction>):e2) - Account:tgt ACCUM @@txRecords += ORDER_TX(v1.is_fraud, v1.amount, s.pagerank, s.label, s.min_send_tx, s.min_recieve_tx, s.max_send_tx, s.max_recieve_tx, s.avg_send_tx, s.avg_recieve_tx, s.cnt_recieve_tx, s.cnt_send_tx, e1.ts, tgt.pagerank, tgt.label, tgt.min_send_tx, tgt.min_recieve_tx, tgt.max_send_tx, tgt.max_recieve_tx, tgt.avg_send_tx, tgt.avg_recieve_tx, tgt.cnt_recieve_tx, tgt.cnt_send_tx, e2.ts); PRINT @@txRecords; }INSTALL QUERY txMultiHopLimit''', options=[]))
干得好!您现在已经创建并安装了您需要的所有查询!现在让我们开始执行查询来更新我们的图表并获取我们的数据(我们将使用这些数据进行机器学习)。
第四部分:执行查询来构建图表
现在,让我们把所有的东西放在一起更新我们的图表。首先,我们需要在图表中生成属性/特征,所以让我们运行 accountActivity 查询。
accAct = conn.runInstalledQuery("accountActivity", {})
接下来,我们需要更新图中的 label_prop 和 pagerank 值,所以接下来让我们运行它们。
pagerank = conn.runInstalledQuery("pageRank", {"v_type":"Account", "e_type":"Send_To", "max_change":"0.001", "max_iter":"25", "damping":"0.85", "top_k":"10", "print_accum":"TRUE", "result_attr":"pagerank", "file_path":"", "display_edges":"FALSE"})label_prop = conn.runInstalledQuery("label_prop", {"v_type":"Account", "e_type":"Send_To", "max_iter":"10", "output_limit":"10", "print_accum":"TRUE", "file_path":"", "attr":"label"})
太好了!我们的图表正式全面更新!现在让我们用 txMultiHopLimit 获取我们想要的所有值。
tx_hop = conn.runInstalledQuery("txMultiHopLimit", {}, timeout="99999999999", sizeLimit="1500000000")
最后,我们将导入 flat_tables 来规范化图形(注意任何有问题的值,比如 NaN)。我们将删除索引列并保存 CSV。
!pip install flat-table
import flat_tabledf_tx_hop = pd.DataFrame(tx_hop[0]["@@txRecords"])
df_tx_hop = flat_table.normalize(df_tx_hop)df_tx_hop = df_tx_hop.drop(columns=["index"])df_tx_hop.to_csv("tg_fraud_data.csv", index=False)
太棒了。现在您的 Colab 中有一个 CSV 文件可以下载了!我们将在控制台中对 Vertex AI 使用该查询,并且我们将对自定义训练使用 txMultiHopLimit 查询。
第五部分:祝贺+下一步
恭喜你。您已经使用 TigerGraph 创建了一个图表,创建并运行了用于特征提取和图表算法的查询,并保存了数据的 CSV 文件!接下来,我们将探索如何使用 Google 的 AutoML 来处理我们刚刚导出的 CSV 数据。明天在博客上看看吧!
与此同时,如果您有任何问题或者您想了解更多关于 TigerGraph 的信息,请加入 TigerGraph Discord!
https://discord.gg/gRHWBZNpxW
使用 TigerGraph 和 Google Vertex 的 AMLSim 欺诈检测第二部分:在 Vertex AI 上使用 AutoML 和 TigerGraph 数据
原文:https://towardsdatascience.com/amlsim-fraud-detection-with-tigergraph-and-google-vertex-part-ii-using-automl-with-tigergraph-data-65cb86fc34b3?source=collection_archive---------20-----------------------
如何在 TigerGraph 数据上使用 Google 的 AutoML
这是用 TigerGraph 和 Google Vertex 检测 AMLSim 欺诈的第二篇博客。在这里找到第一篇博客:https://towards data science . com/AML sim-fraud-detection-with-tiger graph-and-Google-vertex-part-I-preparing-the-data-2f3e 6487 f 398。
概观
这个项目是由德州陈 ( LinkedIn )在乔恩赫尔克 ( LinkedIn )的帮助下创建的。
欢迎光临!这是 Tiger Vertex 系列的第二部分,集成了 TigerGraph 和 Vertex AI。
在前面的模块中,我们使用 TigerGraph 加载数据,然后使用图形算法更新数据,最后将数据导出到 CSV 中。在本模块中,我们将使用我们在 Google Vertex AI 的控制台中导出的 CSV,并且我们将使用 Google 的 AutoML 来创建预测。我们开始吧!
第一步:在 Google Cloud 上创建一个项目
首先,你需要在 Google Cloud 上创建一个项目。为此,首先导航至https://console.cloud.google.com/vertex-ai。
https://console.cloud.google.com/vertex-ai
在左上方显示“选择一个项目”的地方,如果您已经有一个现有的项目,请从窗口中选择一个项目。如果没有,请按右上角的“新建项目”并按照提示的步骤创建您的项目。
注意:要使用 Google Vertex AI,必须启用计费。
一旦你点击进入你的项目,并导航到顶点人工智能仪表板,你会看到如下所示的屏幕(虽然你的项目可能不会与数据填充)。如果是这样,恭喜你!你已经准备好进入下一步了!
选定项目的 Vertex AI 仪表板
第二步:上传 TigerGraph 数据集到 Vertex AI
接下来,我们需要创建一个数据集。在仪表板上,单击“创建数据集”这将把您重定向到设置数据集的页面。
点击“创建数据集”
创建数据集 GUI
首先将数据集重命名为类似“tg_amlsim”的名称。
更新数据集的名称
接下来,由于我们想要上传一个 CSV,我们需要选择一个“表格”数据集。由于我们想要确定交易是否是欺诈性的,我们将为该类型选择一个回归/分类。
点击表格并选择回归/分类
您不需要更改任何高级选项。向下滚动并点击“创建”当你这样做时,你将被重定向到如下页面。这是我们将数据添加到数据集的地方。
我们将在这里添加数据。
确保选择了“从您的计算机上传 CSV 文件”,然后按“选择文件”按钮。上传我们从 TigerGraph 数据创建的 CSV。
从 TigerGraph 中选择我们在过去模块中创建的 CSV
将云存储路径改为 Google Cloud 上的 bucket。点击“浏览”,然后选择一个出现的选项。(应该只出现一个,但是如果有多个,请选择您喜欢的存储桶。)单击您想要的选项,然后按“选择”
选择你的桶
最后,按“继续”
按继续
您的 CSV 将开始上传。这可能需要几秒钟才能完成。上传后,您将被重定向到如下页面,在这里您可以看到您所有的栏目名称。如果你达到了这一点,祝贺你!您已经正式上传了您的数据,并准备运行分析!
CSV 上传!
第三步:训练你的模型
最后,我们来训练模型!在上面的屏幕中,按“训练新模型”
对于第一个屏幕,将目标更改为“分类”然后确保您使用的是 AutoML。然后按“继续”
使用分类和自动
在下一个屏幕中,将型号名称更改为您喜欢的名称。对于目标列,选择 tx_fraud。我们不会改变任何高级选项。按继续。
选择 tx_fraud。
滚动到培训选项的底部,点击高级选项。在那里,选择“AUC PRC”这将使模型专注于最大限度地提高不太常见的欺诈交易类别的准确性。然后按继续。
在高级选项中,单击 AUC PRC。
最后,选择你的预算。这里,我们将使用最小值 1。当你准备好开始训练时,点击“开始训练”这将需要大约一个小时,所以在等待 Vertex AI 的电子邮件时,请随意休息一下。
键入 1(或您的偏好),然后按“开始训练”
第四步:探索分析
现在您的模型已经训练好了,您可以查看它了。
您将看到一个概述,其中包含 PR 和 ROC AUC、log loss、F1 得分和其他指标等数据。
韵律学
接下来,还显示了精确召回和 ROC 曲线。现在,它们不是很合理,这可能是由于我们的数据不平衡。
曲线
可能对我们来说最重要的是,Google Vertex 也有一个混淆矩阵。在这里,对我们来说最重要的部分是真实和真实部分。在这种情况下,我们的模型只能正确识别 52%的欺诈交易。这个不太好(基本随机)。
最后,Vertex 有一个特性重要性图表。从这里,我们可以看到交易金额是最重要的变量,其次是发送方交易的最大值、平均值和最小值,但是像接收方交易的最大值、平均值和最小值这样的变量在我们创建的模型中并不重要。
特征重要性图表
为了获得更好的结果,我们可以训练更长的时间,限制我们传递的变量,并生成更多的数据来平衡我们的数据集。
第五步:祝贺你!+资源
恭喜你。你已经正式使用 AutoML 对 TigerGraph 的数据进行分析了!
如果您有任何问题,请加入 TigerGraph Discord 并提问:
https://discord.gg/gRHWBZNpxW
使用 TigerGraph 和 Google Vertex 检测 AMLSim 欺诈第三部分:为定制数据准备模型
原文:https://towardsdatascience.com/amlsim-fraud-detection-with-tigergraph-and-google-vertex-part-iii-preparing-your-model-for-custom-561e333e1806?source=collection_archive---------37-----------------------
设置 Google Vertex AI,加载我们的 TigerGraph 数据,并创建和拟合我们的模型
注意:这是将 TigerGraph 与 Google Vertex AI 结合使用的系列文章的第三部分。要在本博客中使用这些数据,请关注本博客:https://towards data science . com/AML sim-fraud-detection-with-tiger graph-and-Google-vertex-part-I-preparing-the-data-2f3e 6487 f 398
如果你想了解如何在谷歌控制台中通过 AutoML 使用 TigerGraph 数据,请查看这篇博客:https://towardsdatascience . com/AML sim-fraud-detection-with-tiger graph-and-Google-vertex-part-ii-using-AutoML-with-tiger graph-data-65 CB 86 fc 34 b 3
概观
注:该系列由德州陈 (LinkedIn)在乔恩赫尔克 (LinkedIn)的帮助下共同创作。本实验基于 Google Vertex 的在线预测和批量预测的笔记本演练。
在这个博客系列中,我们将 TigerGraph 的强大功能与 Google 的 Vertex AI 相结合。在第一篇博客中,我们加载了数据,运行了图形算法,编写了查询,最后导出了一个 CSV。在第二篇博客中,我们在 Google 的控制台中使用了导出的 CSV,并使用了 AutoML。现在,让我们对我们的数据使用一个定制模型。这将在笔记本中通过 Python 完全运行。
在这篇博客中,我们将加载我们的模型并设置必要的配置,然后在下一篇博客中,我们将运行批处理和在线预测。我们开始吧!
第一部分:安装库
首先,我们需要安装所有的库。如果你在 Google Cloud 笔记本上运行你的程序,你需要运行这个单元格来添加一个用户标志。如果不是,那么这个细胞就没什么用了。
import osIS_GOOGLE_CLOUD_NOTEBOOK = os.path.exists("/opt/deeplearning/metadata/env_version")USER_FLAG = ""
if IS_GOOGLE_CLOUD_NOTEBOOK:
USER_FLAG = "--user"
接下来,我们需要安装所有的库。这将包括 Vertex AI、Google 云存储、pyTigerGraph、flat tables、NumPy 和 Pandas。
! pip3 install {USER_FLAG} --upgrade google-cloud-storage
! pip3 install {USER_FLAG} --upgrade pyTigerGraph
! pip3 install {USER_FLAG} --upgrade flat-table
! pip3 install {USER_FLAG} --upgrade numpy
! pip3 install {USER_FLAG} --upgrade pandas
最后,您需要重启笔记本来查找包。
import osif not os.getenv("IS_TESTING"):
import IPython
app = IPython.Application.instance()
app.kernel.do_shutdown(True)
运行该单元后,笔记本应该会自动重启。一旦完成,让我们开始设置模型!
第二部分:启用顶点 AI API 和计算引擎 API,并连接到 Google Cloud
注意:这些服务中的一部分是要收费的。谷歌云自动启动用户 300 美元免费。
第一步:启用 API
本实验将使用两个 API:顶点 AI 和计算机引擎 API。为此,请访问此链接:【https://console.cloud.google.com/flows/enableapi? apid = ai platform . Google APIs . com,compute_component
在该页面上,您需要选择要使用的项目。我们将使用我们在过去的博客中创建的相同的谷歌云项目。选择它后,按继续。
选择您在过去的博客中创建的项目。
给它几分钟来设置,然后你会收到一个确认页面。
API 已启用。
干得好!您已经启用了您的 API!现在,让我们验证您的 Google Cloud 帐户。
第二步:认证谷歌云
接下来,您需要授予您的 Google 帐户使用 Cloud SDK 的权限。运行以下代码:
import os
import sysif "google.colab" in sys.modules: from google.colab import auth as google_auth
google_auth.authenticate_user()elif not os.getenv("IS_TESTING"): %env GOOGLE_APPLICATION_CREDENTIALS ''
当您运行此程序时,您将收到一个验证链接。当你点击它时,选择链接到你的谷歌云项目的谷歌账户。谷歌会要求下面的权限。如果你按“继续”,你会找到一个代码复制并粘贴到你的笔记本上,然后按 enter。
Google Cloud SDK 的权限
第三步:在笔记本中设置变量
干得好!最后,您需要设置两个变量:PROJECT_ID 和 TIMESTAMP。
PROJECT_ID = "tigergraph-test"from datetime import datetime
TIMESTAMP = datetime.now().strftime("%Y%m%d%H%M%S")
你可以在你的控制台主页上找到你的项目 id。
在控制台的主页上找到您的项目 ID。
干得好!接下来,您需要为您将使用的 Google Cloud bucket 设置 bucket 名称和区域。
BUCKET_NAME = "gs://[your-bucket-name]"
REGION = "[your-region]"
你可以在这里 : 找到地区列表 https://cloud . Google . com/vertex-ai/docs/general/locations # available _ regions
对于 bucket,您可以复制并粘贴您在过去的博客中选择的相同的 bucket 名称。
最后,您可以通过运行以下命令来验证您是否连接到了正确的存储桶:
! gsutil ls -al $BUCKET_NAME
不错!现在,您设置了我们将使用的所有工具。接下来,让我们为谷歌云声明一些变量。
第三部分:设置顶点人工智能
第一步:导入你的库并初始化顶点人工智能
首先,导入顶点 SDK 库并初始化你的顶点 AI 连接。在初始化过程中,您需要传递您的项目 id、位置/地区和存储桶名称。
import os
import sys
from google.cloud import aiplatform
from google.cloud.aiplatform import gapic as aipaiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=BUCKET_NAME)
第二步:设置加速器、预构建的容器和机器类型
接下来,设置加速器。如果不想使用加速器,请将其设置为(无,无)。否则,检查这里的以查看哪个 GPU 可用于哪个位置/区域。
TRAIN_GPU, TRAIN_NGPU = (None, None)
DEPLOY_GPU, DEPLOY_NGPU = (None, None)
然后选择一个预构建的容器用于培训和部署。你可以在这里找到训练版本和部署版本的预建容器列表。一旦你找到一个你喜欢的选项,你可以复制并粘贴除了:latest 以外的所有内容。
复制除:latest 以外的最后一节。
将您复制的内容粘贴到以下代码中的 TRAIN_VERSION 或 DEPLOY_VERSION 中。
TRAIN_VERSION = "tf-cpu.2-4"
DEPLOY_VERSION = "tf2-cpu.2-5"TRAIN_IMAGE = "gcr.io/cloud-aiplatform/training/{}:latest".format(TRAIN_VERSION)
DEPLOY_IMAGE = "gcr.io/cloud-aiplatform/prediction/{}:latest".format(DEPLOY_VERSION)print("Training:", TRAIN_IMAGE, TRAIN_GPU, TRAIN_NGPU)
print("Deployment:", DEPLOY_IMAGE, DEPLOY_GPU, DEPLOY_NGPU)
最后,我们将设置机器类型。
MACHINE_TYPE = "n1-standard"
VCPU = "4"
TRAIN_COMPUTE = MACHINE_TYPE + "-" + VCPU
print("Train machine type", TRAIN_COMPUTE)MACHINE_TYPE = "n1-standard"
VCPU = "4"
DEPLOY_COMPUTE = MACHINE_TYPE + "-" + VCPU
print("Deploy machine type", DEPLOY_COMPUTE)
太棒了。最后,让我们创建一个训练脚本,训练我们的模型!
第四部分:建立培训档案
第一步:设置参数
让我们首先设置要传递到培训文件中的参数。我们将从声明 JOB_NAME 和 MODEL_DIR(模型目录)开始。接下来,我们将为我们的模型确定训练策略、时期数和步骤。
JOB_NAME = "custom_job_" + TIMESTAMP
MODEL_DIR = "{}/{}".format(BUCKET_NAME, JOB_NAME)if not TRAIN_NGPU or TRAIN_NGPU < 2:
TRAIN_STRATEGY = "single"
else:
TRAIN_STRATEGY = "mirror"EPOCHS = 25
STEPS = 50
CMDARGS = [
"--epochs=" + str(EPOCHS),
"--steps=" + str(STEPS),
"--distribute=" + TRAIN_STRATEGY,
]
第二步:编写培训脚本
注意:这整个部分应该在一个单元格中,但是为了便于解释,它将被分解。
现在,我们需要编写我们的培训脚本。在这里,我们将导入数据并创建模型。首先,我们将导入我们所有的库,包括 Tensorflow、argparse、pyTigerGraph 等等。
%%writefile task.pyimport tensorflow as tf
from tensorflow.python.client import device_lib
import argparse
import os
import sys
import pyTigerGraph as tg
import flat_table
import pandas as pd
from sklearn.model_selection import train_test_split
import numpy as np
接下来,我们将使用 argparse 来读取我们传递的所有参数。
parser = argparse.ArgumentParser()
parser.add_argument('--lr', dest='lr', default=0.01, type=float, help='Learning rate.')
parser.add_argument('--epochs', dest='epochs', default=10, type=int, help='Number of epochs.')
parser.add_argument('--steps', dest='steps', default=200, type=int, help='Number of steps per epoch.')
parser.add_argument('--distribute', dest='distribute', type=str, default='single', help='distributed training strategy')args = parser.parse_args()
我们将使用策略论点来确定张量流分布。
if args.distribute == 'single':
if tf.test.is_gpu_available():
strategy = tf.distribute.OneDeviceStrategy(device="/gpu:0")
else:
strategy = tf.distribute.OneDeviceStrategy(device="/cpu:0")
elif args.distribute == 'mirror':
strategy = tf.distribute.MirroredStrategy()
elif args.distribute == 'multi':
strategy = tf.distribute.experimental.MultiWorkerMirroredStrategy()
接下来,我们将设置缓冲区大小和批处理大小变量
BUFFER_SIZE = 10000
BATCH_SIZE = 64
然后我们将创建一个 prepare_dataset 函数。为了加载我们的数据,我们将首先连接到 TigerGraph 上的图表。在运行该命令之前,转到 GraphStudio 并确保您的解决方案旁边有一个绿色的“Ready”。如果它有一个蓝色的“停止”,然后按“操作”下的“解决方案操作”和下拉菜单,并按“开始”可能需要几分钟才能开始。
如果您的状态显示为“已停止”,请转到“操作”下,然后从下拉列表中按“开始”。
当“状态”为绿色并显示“就绪”时,您就准备好继续前进了
一旦连接到我们的解决方案,我们将运行 txMultiHopLimit 查询。然后我们将使用 pandas 将结果转换成数据帧。我们将使用 flat_table 删除任何 NaN 值或其他潜在错误。最后,我们将使用 sklearn 的 train_test_split 将结果分成训练和测试部分,这将是我们返回的值。
def prepare_dataset():
conn = tg.TigerGraphConnection(host="https://SUBDOMAIN.i.tgcloud.io", username="tigergraph", password="tigergraph", graphname = "AMLSim")
conn.apiToken = conn.getToken(conn.createSecret())
tx_hop = conn.runInstalledQuery("txMultiHopLimit", {}, timeout="99999999999", sizeLimit="1500000000")
odf_tx_hop = pd.DataFrame(tx_hop[0]["@@txRecords"], index=None)
dataset = flat_table.normalize(odf_tx_hop)
features = ['tx_amount', 's_pagerank', 's_label', 's_min_send_tx', 's_min_receieve_tx', 's_max_send_tx', 's_max_recieve_tx', 's_avg_send_tx', 's_avg_recieve_tx', 's_cnt_recieve_tx', 's_cnt_send_tx', 's_timestamp', 'r_pagerank', 'r_label', 'r_min_send_tx', 'r_min_receieve_tx', 'r_max_send_tx', 'r_max_recieve_tx', 'r_avg_send_tx', 'r_avg_recieve_tx', 'r_cnt_recieve_tx', 'r_cnt_send_tx', 'r_timestamp']
X_train, X_test, y_train, y_test = train_test_split(dataset[features], dataset["tx_fraud"], test_size=0.2, random_state=42)
return X_train, X_test, y_train, y_test
接下来,我们将使用 Keras 创建我们的神经网络模型。这将是一个简单的序列模型。
def build_and_compile_model():
model = tf.keras.Sequential([
tf.keras.layers.Dense(32, activation='relu', input_shape=(1, 23)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(1, activation="sigmoid")
])
model.compile( loss=tf.keras.losses.MSE, optimizer=tf.keras.optimizers.Adam(learning_rate=args.lr), metrics=['accuracy'])
return model
然后我们将设置一些变量,特别是 NUM_WORKERS、GLOBAL_BATCH_SIZE 和 MODEL_DIR。
NUM_WORKERS = strategy.num_replicas_in_sync
GLOBAL_BATCH_SIZE = BATCH_SIZE * NUM_WORKERS
MODEL_DIR = os.getenv("AIP_MODEL_DIR")
我们将运行 prepare_dataset 函数,然后构建模型。
res = prepare_dataset()
train_dataset, X_test, y_train, y_test = reswith strategy.scope():
model = build_and_compile_model()
最后,我们将拟合模型并保存它。
model.fit(train_dataset, y_train, epochs=args.epochs, steps_per_epoch=args.steps, batch_size=GLOBAL_BATCH_SIZE, validation_data=(X_test, y_test))
model.save(MODEL_DIR)
厉害!一旦执行完毕,剩下的就是运行文件了。
第三步:训练模型
最后,我们将运行并训练模型。
job = aiplatform.CustomTrainingJob( display_name=JOB_NAME, script_path="task.py", container_uri=TRAIN_IMAGE, requirements=["tensorflow_datasets==1.3.0", "pyTigerDriver==1.0.6", "pyTigerGraph==0.0.9.6.8", "pandas==1.1.5", "flat-table==1.1.1", "sklearn==0.0"], model_serving_container_image_uri=DEPLOY_IMAGE)MODEL_DISPLAY_NAME = "tg_custom_fraud_model-" + TIMESTAMPif TRAIN_GPU:
model = job.run(model_display_name=MODEL_DISPLAY_NAME, args=CMDARGS, replica_count=1, machine_type=TRAIN_COMPUTE, accelerator_type=TRAIN_GPU.name, accelerator_count=TRAIN_NGPU)else:
model = job.run(model_display_name=MODEL_DISPLAY_NAME, args=CMDARGS, replica_count=1, machine_type=TRAIN_COMPUTE, accelerator_count=0)
一旦你运行这个,你将能够在顶点人工智能面板的“模型”标签中看到你的模型。
模型显示在顶点人工智能控制台。
暂时就这样吧!
第五部分:祝贺你!
感谢您关注本博客!期待下一个,我们将使用批量和在线预测!在此期间,如果你有任何问题,你可以加入 TigerGraph Discord。
https://discord.gg/gRHWBZNpxW
使用 TigerGraph 和 Google Vertex 检测 AMLSim 欺诈第四部分:运行在线预测
原文:https://towardsdatascience.com/amlsim-fraud-detection-with-tigergraph-and-google-vertex-part-iv-running-online-predictions-b1bcc64e9576?source=collection_archive---------31-----------------------
使用我们的定制模型运行在线预测
注意:这是系列的第四篇博客。要获得数据,请阅读这篇博客:https://towards data science . com/AML sim-fraud-detection-with-tiger graph-and-Google-vertex-part-I-preparing-the-data-2f3e 6487 f 398。
要创建使用的模型,请阅读本博客:https://towards data science . com/AML sim-fraud-detection-with-tiger graph-and-Google-vertex-part-iii-preparing-your-model-for-custom-561 e333 e 1806。
要在谷歌的控制台中查看正在使用谷歌 AutoML 的数据,请阅读这篇博客:https://towards data science . com/AML sim-fraud-detection-with-tiger graph-and-Google-vertex-part-ii-using-AutoML-with-tiger graph-data-65 CB 86 fc 34 b 3
概观
注:这是与德州陈在 Jon Herke 的帮助下共同创作的。该实验室基于谷歌的顶点人工智能在线预测笔记本。
这是 TigerGraph 和 Vertex AI 系列(目前)的倒数第二篇博客,它正在探索使用带有 TigerGraph 和 Vertex AI 的图形的力量。在过去的博客中,我们使用来自 TigerGraph 的定制数据来创建和拟合我们的模型。现在,我们需要部署我们的模型,用它进行预测,最后进行清理。
第一篇博客讲述了如何创建我们的图表(设计模式、加载数据、创建和执行查询等)。).然后,在的第二篇博客中,我们使用谷歌的控制台对我们的数据运行 AutoML。在的第三篇博客中,与 AutoML 路线相反,我们使用 TensorFlow 准备了一个定制模型。最后,利用过去博客的数据,我们有两个选择:在线预测和批量预测。本博客将介绍运行在线预测,明天的博客将介绍批量预测。所以让我们开始吧!
第一部分:创建端点
首先,我们需要部署我们的模型并创建一个端点。让我们从创建常数开始。这些是我们在部署模型时要传递的一些变量。
DEPLOYED_NAME = "tg_custom_fraud_model_deployed-" + TIMESTAMP
TRAFFIC_SPLIT = {"0": 100}
MIN_NODES = 1
MAX_NODES = 1
然后我们将部署模型。
注意:传递的一些变量是在前面的博客中声明的。
if DEPLOY_GPU: endpoint = model.deploy(
deployed_model_display_name=DEPLOYED_NAME,
traffic_split=TRAFFIC_SPLIT,
machine_type=DEPLOY_COMPUTE,
accelerator_type=DEPLOY_GPU.name,
accelerator_count=DEPLOY_NGPU,
min_replica_count=MIN_NODES,
max_replica_count=MAX_NODES,
)else: endpoint = model.deploy(
deployed_model_display_name=DEPLOYED_NAME,
traffic_split=TRAFFIC_SPLIT,
machine_type=DEPLOY_COMPUTE,
accelerator_type=None, # DEPLOY_COMPUTE.name,
accelerator_count=None, # 0,
min_replica_count=MIN_NODES,
max_replica_count=MAX_NODES,
)
在我们的例子中,我们在过去的博客中将 GPU 设置为 None,如下所示。
TRAIN_GPU, TRAIN_NGPU = (None, None)DEPLOY_GPU, DEPLOY_NGPU = (None, None)
因此,上面的代码将运行 else。因为我们没有使用任何加速器,所以计数和类型的值被设置为 None,但是如果您确实声明了某些加速器,您可以使用注释值。
您可以在 Google Vertex 仪表板的“端点”选项卡中查看您部署的端点。
顶点人工智能控制台中的端点
现在我们的端点已经部署好了,让我们开始使用我们的模型进行预测吧!
第二部分:使用测试数据运行预测
第一步:验证 TG Cloud 上的解决方案是否就绪
现在我们准备运行预测!首先,我们需要从图表中获取测试数据。为此,请确保您在 TigerGraph Cloud 上的解决方案显示就绪。
确保你的状态下有一个绿点和“准备好”字样。
第二步:导入库
接下来,我们需要导入我们的库。我们将再次使用 pyTigerGraph、flat-table、pandas、numpy 和 sklearn。
import pyTigerGraph as tg
import flat_table
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
第三步:连接到图表
然后,您需要连接到您的图表。再次用您的框中的值修改 conn.TigerGraphConnection,将 SUBDOMAIN 更改为您的子域,将 PASSWORD 更改为您的密码。
conn = tg.TigerGraphConnection(host="https://SUBDOMAIN.i.tgcloud.io", username="tigergraph", password="PASSWORD", graphname = "AMLSim")
conn.apiToken = conn.getToken(conn.createSecret())
第四步:运行查询并解析数据
最后,我们将运行查询(txMultiHopLimit)并解析数据。我们将再次使用平面表来删除数据中的任何错误,并使用 train_test_split 将数据分为训练和测试两部分。最后一步将把 X_test 变成一个列表,而不是 DataFrame。
tx_hop = conn.runInstalledQuery("txMultiHopLimit", {}, timeout="99999999999", sizeLimit="1500000000")odf_tx_hop = pd.DataFrame(tx_hop[0]["@@txRecords"], index=None)
dataset = flat_table.normalize(odf_tx_hop)features = ['tx_amount', 's_pagerank', 's_label', 's_min_send_tx', 's_min_receieve_tx', 's_max_send_tx', 's_max_recieve_tx', 's_avg_send_tx', 's_avg_recieve_tx', 's_cnt_recieve_tx', 's_cnt_send_tx', 's_timestamp', 'r_pagerank', 'r_label', 'r_min_send_tx', 'r_min_receieve_tx', 'r_max_send_tx', 'r_max_recieve_tx', 'r_avg_send_tx', 'r_avg_recieve_tx', 'r_cnt_recieve_tx', 'r_cnt_send_tx', 'r_timestamp']X_train, X_test, y_train, y_test = train_test_split(dataset[features], dataset["tx_fraud"], test_size=0.2, random_state=42)X_test = list([list(i) for i in np.array(X_test)])
第五步:预测
到目前为止做得很好!最后,我们需要创建预测。为此,我们将运行 endpoint.predict。然后我们可以将它与 y_test 正确答案进行比较,并最终将其打印出来。
predictions = endpoint.predict(instances=[X_test])
y_predicted = np.argmax(predictions.predictions, axis=1)correct = sum(y_predicted == np.array(y_test))
accuracy = len(y_predicted)print( f"Correct predictions = {correct}, Total predictions = {accuracy}, Accuracy = {correct/accuracy}" )
恭喜你。如果到目前为止一切正常,那么您已经部署了您的模型,现在您可以对它进行预测了!如果你导航回谷歌顶点人工智能控制台,你现在可以看到一些图表填充了你的预测数据。
带预测的端点
第三部分:清理
最后,为了避免来自 Google Cloud 的任何未来费用,让我们取消部署模型并进行清理。你可以删除整个谷歌云项目,或者按照以下步骤撤销在线预测部分。
首先,为了取消部署模型,我们将运行 endpoint.undeploy。
deployed_model_id = endpoint.list_models()[0].id
endpoint.undeploy(deployed_model_id=deployed_model_id)
此外,我们可以使用。delete()函数。
job.delete()
model.delete()
endpoint.delete()
最后,如果您想删除您的存储桶,您可以运行以下命令:
! gsutil -m rm -r $BUCKET_NAME
运行完所有这些之后,所有的更改都应该被恢复。
第四部分:祝贺+资源
干得好!本课还有最后一节是关于批量预测的!与此同时,如果您有任何问题,请直接联系 TigerGraph Discord:
https://discord.gg/gRHWBZNpxW
感谢您阅读这篇博客,希望您继续探索 TigerGraph!
如果 A/A 测试失败,A/B 测试就失去了光彩
原文:https://towardsdatascience.com/an-a-b-test-loses-its-luster-if-a-a-tests-fail-2dd11fa6d241?source=collection_archive---------7-----------------------
实验和因果推理
A/A 测试的统计方法
安迪·萨拉扎在 Unsplash 上的照片
介绍
一个严格的实验过程。A/B 测试已经成为一种时尚,并在技术领域广泛采用。作为早期采用者,FAANG 公司已经将实验融入到他们的决策过程中。
例如,微软必应对其 80%的产品变更进行 A/B 测试。谷歌依靠实验来确定面试过程中表现最好的候选人。网飞利用交错,一种成对实验设计,改进了个性化算法。
越来越多的采用实验源于其高水平的内部有效性,这进一步由两个因素决定。首先,数据科学家在宏观层面上对整体研究设计和模型选择具有选择性,确保所选设计适合问题及其关键假设完整无损。第二,数据科学家在微观层面上对随机化过程非常小心,并将人群分成两个可比较的组。
然而,你怎么能如此确定分配分割按设计的那样工作呢?
拆分比例不对怎么办?
你如何诊断错配?
这些问题值得立即关注。为了建立可信的实验平台,数据科学家必须仔细检查随机化过程;否则,实验平台会在干预前在治疗组和对照组中引入偏差,从而使任何测试结果无效。
在之前的帖子中,我们已经学习了 A/B 测试的有效性、常见陷阱、用户干扰和最佳实践。在今天的帖子中,我们建立了一个简化的内部实验平台,并检查它是否可以呈现两个可比较的组。
什么是 A/A 测试?
正如 Ronny Kohavi 所建议的,我们应该进行一系列的 A/A 测试,并检查 p 值分布。对于那些实验领域的新手来说,Ronny 被认为是在线实验的教父和“值得信赖的在线控制实验的作者
如果我们不能通过 A/A 测试,A/B 测试就失去了它的光彩。
从概念上讲,A/A 测试遵循与 A/B 测试相同的设计逻辑,将用户分成两组,并相应地分配处理方法。唯一的区别是 A/A 测试对两组都分配了相同的治疗。
因此,实验组在随机化后具有相同的协变量分布,并接受相同的治疗条件。我们不应该期望结果指标有什么不同。在测试之前知道真实的无效效果作为基准,并将其与从实验企业获得的实际效果进行比较,这是 A/A 设计的最大优点。
为什么要进行 A/A 测试?
主要有两个目的。首先,收集数据并评估功率计算关键指标的可变性( Kohavi 等人,2012 & 2020 )。在之前的帖子中,我们已经了解了什么是功效分析,样本量由以下公式决定:
我自己的截图
其中:
- σ:样本方差。
- 𝛿:治疗组和对照组之间的差异。
我们可以对指标运行 A/A 测试,以获得其方差()并为 A/B 测试的样本量计算做准备。
第二,A/A 测试评估实验平台是否按预期工作,这是今天帖子的主要目的。
例如,我们希望流量平均分配,一半用于处理,另一半用于控制。在流量分割之后,我们获得每组中的实际观察数量。
我们如何判断观察到的比率分割在统计上是否不同于预期的比率?
进行卡方检验!
我们可以运行卡方检验来检查观察到的比率和设计的比率在统计上是否不同( Kohavi 等人 2012 & 2020 )。如果差异确实具有统计学意义,我们可以得出结论,在干预之前,实验系统包含选择偏差。让我们在下一节详细说明如何解释这个结果。
迈克尔·巴钦在 Unsplash 上拍摄的照片
如何解读?
尽管两组接受相同的治疗条件,我们仍然应该期望在 A/A 测试中有合理的假阳性率。在重复的 A/A 试验中,给定指标的零假设应该被拒绝 5%的时间,设置置信水平为 95%。还有,重复 A/A 试验的 p 值遵循均匀分布,这也是今天博文的中心论点。**
有两种检查分布的方法。首先,我们可以观察 p 值,并检查其分布是否具有以下方案,正如微软的实验团队所建议的那样:
- p < 0.05 为 5%的时间
- p < 0.10 为 10%的时间
- p < 0.20 为 20%的时间
- p < 0.30 为 30%的时间
- …
此外,我们可以进行假设检验,并应用Kolmogorov–Smirnov 检验来正式检查它是否遵循均匀分布。我们将在 Python 模拟中实现这两种方法。
当 A/A 测试失败时该怎么办?
如果 A/A 测试显示统计差异的结果超过 5%,这意味着我们的实验系统包含选择偏差。我们应该回到数据收集过程并检查根本原因。
如果 A/A 测试失败,停止分析数据并返回数据收集。
检查出了什么问题。
A/A 测试可能由于各种原因而失败,我们将重点讨论两个典型原因。首先,治疗组和对照组之间的实际流量分配在统计上不同于预期比率,这种现象称为 样本比率不匹配 、 SRM 。请查看以下资源,了解如何诊断 SRM:
- Python 中 A/B 测试的实用指南
- Fabijan 等,2020,诊断 A/B 测试中的样本比例不匹配 。
- Fabijan 等,2019,在线对照实验中诊断样本配比错配 。
第二,另一个常见的原因是哈希函数,它错误地倾向于一种变体而不是另一种。哈希是实验过程中的一个关键话题,值得在单独的博客文章中讨论。
Python 中的统计模拟
在本节中,我们将实验系统中使用的实际散列过程降级,并简化治疗分配过程。降级意味着我们不遵循分配治疗状态的标准两步程序:
1.用户→存储桶
2.铲斗→变型
相反,我们使用一个随机数生成器来决定分配组。
这很好地满足了我们的目的,因为我们主要关注的是如何运行 A/A 测试,而不是实际的散列过程。
第一步:生成正态分布
我们的总体服从均值为 100、标准差为 5 的正态分布。
步骤 2:对于单次迭代
**Ttest_indResult(statistic = 0.21648391567473418, pvalue = 0.8286548031632164)**
这里,我们应用双样本 t 检验来检验独立性。由于 p 值(0.829)大于阈值,我们得出结论,a1 和 a2 之间没有差异。换句话说,我们已经通过了一次迭代的 A/A 测试。
接下来,我们模拟一万次这个过程,计算它导致多少次误报。
#目视检查 p 值分布
这是一个多余的 if-elif-else 语句。
**count_10_perc/10000
0.0997count_20_perc/10000
0.1035count_30_perc/10000
0.0986
...**
从表面上看,p 值遵循均匀分布,并在 10,000 次模拟中在[0,1]范围内均匀分布。
#正式检验 p 值是否服从均匀分布
我们从上面的 for 循环中获得 p 值,并应用下面的命令来检查它的分布。
**KstestResult(statistic=0.004665761913861394,pvalue=0.98142384029721)**
对于 Kolmogorov-Smirnov 检验,零假设假设给定的分布(“p_values”)与指定的分布(“均匀”)没有不同。事实证明,我们未能拒绝零假设,并得出 p 值遵循均匀分布的结论。
我对不等分割(例如,10%对 90%)和重尾分布(例如,指数分布)应用了相同的分析程序,没有观察到不同的结果,这与我们的直觉相矛盾。
主要原因可能在于,如上所述,我们的模拟处理分配比实际的散列过程更具确定性。我会写一篇关于哈希的后续文章,检查结果是否有变化。
完整的 Python 代码请参考我的Github。
外卖食品
- 我们的实验平台如预期的那样工作!这并不奇怪,考虑到我们使用一个随机生成器来决定变量赋值。
- 如果我们遵循实际的散列过程,结果可能会改变。
- Kolmogorov-Smirnov 检验是测试获得的 p 值是否遵循均匀分布的好方法。
Medium 最近进化出了它的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。
**https://leihua-ye.medium.com/membership **
进一步阅读
**
喜欢读这本书吗?
请在 LinkedIn 和 Youtube 上找到我。
还有,看看我其他关于人工智能和机器学习的帖子。**
面向数据分析师的强大而熟悉的工作流
原文:https://towardsdatascience.com/an-accelerated-big-data-workflow-for-the-data-analyst-5921c9fda866?source=collection_archive---------29-----------------------
在谷歌云的人工智能平台笔记本电脑上使用 RAPIDS & Nvidia GPUs 更快地分析数十亿条记录。
照片由祝铭震·艾文在 Unsplash
“在提到的角色中…每个企业都需要数据的唯一角色是决策者和分析师”
—凯西·科济尔科夫(数据科学最被误解的英雄)
分析师和"公民数据科学家"是每个组织中经常被遗忘的英雄。他们往往有广泛的职责,包括业务领域知识、数据提取&分析、预测分析&机器学习,以及向利益相关者报告&沟通。小菜一碟,对吧?
随着数据规模的增长,许多从业者不得不学习大数据框架和基础设施管理的部分内容。这种工作范围的扩大是不可持续的,并对工作流程中最重要的步骤产生直接影响:数据探索和实验。这可能导致不完善的报告、不太准确的预测模型和预测,以及不太创新的见解和想法。
我真的在建议另一种大数据框架/服务吗?我们不是已经有 Hive,Impala,Presto,Spark,Beam,BigQuery,Athena 了吗,不胜枚举。不要误解我。对于为大型组织运行数据平台的团队来说,这些框架/服务中的一个或多个对于管理数百个批处理和流式作业、庞大的数据源生态系统和生产管道至关重要。
然而,我在这里关注的是数据分析师,他们需要一个灵活、可扩展的解决方案,只需对代码进行最少的更改,就能加速他们现有的工作流。在考虑多节点集群和新框架之前,您会惊讶地发现,在 GPU 的帮助下,一台机器上的现有代码可以完成多少工作。以我自己为实验对象,我想探索一个具有以下约束的工作流程:
- 我希望设置(硬件和软件)简单快捷(< 30 分钟)
- 我不想管理分布式集群或学习新的框架
- 我希望完全灵活地与 python 数据和机器学习生态系统(jupyter,pandas,xgboost,tensorflow,pytorch,sklearn)进行交互
- 我希望能够扩展到数以亿计的数据行,而无需通宵等待结果
这些限制让我在新的强大的 Nvidia A100 GPU 的帮助下进入了 RAPIDS。
作者图片
为什么在谷歌云上使用 RAPIDS+Nvidia A100 GPU
- 速度:GPU 通过加速管道中的深度学习训练步骤,一直处于机器学习创新的前沿。 RAPIDS 希望通过数据接收、数据转换和预测分析,为您的整个工作流程提供类似的收益。 Dask 扩展了 RAPIDS,使其能够在单个集群(以及多节点集群,如果需要的话)上跨 GPU 进行扩展,并处理分布在数百个文件中的源数据。
- 交互式 Python 熟悉度 : RAPIDS 在很大程度上遵循了 pandas 和 sklearn API,并允许一个舒适的交互式工作流来分析每一步之后的结果。入门门槛比学习一个不同概念的新框架要低很多。这就是为什么 Spark 和 Beam 都大力投资熊猫 API 的原因。
- **按需按照自己的节奏扩展:**仅在需要时使用 Nvidia A100 GPUs 并为其付费。从 CPU&系统 RAM 上的 Pandas 开始,在负担得起的 T4 GPU 上测试 RAPIDS(或者甚至在ka ggle&Colab上免费测试),然后扩展到 Nvidia A100s 以获得最大的数据集。
- 谷歌云上的 Nvidia A100s:16 x 40GB GPU RAM:虽然您可以围绕 RAM 限制进行创造性设计(例如,分区,将汇总聚合卸载到数据仓库),但将数据装入 GPU RAM 可以实现最佳加速,并在最精细的级别上充分灵活地分析数据。Nvidia A100s 拥有 40GB 的 GPU RAM,您可以在一台机器上扩展到 16 个,而不必担心多节点分布。这给了你一个巨大的 640GB 的 GPU 内存来玩。这既简化了环境管理,又限制了在处理多节点设置时出现的任何网络问题。
GPU 不是灵丹妙药,所以看看我之前关于评估 GPU 是否是你正确选择的博客。
端到端示例
GitHub 笔记本这里
商业问题
我将探索房利美单户贷款业绩数据,查看 17 年(2000 年至 2016 年)约 3700 万笔贷款和 18 亿英镑记录的业绩历史。我想回答几个问题:
描述性分析:
- 每年发放的贷款数量是多少?
- 有百分之多少的贷款有拖欠事件?
- 哪一年的拖欠率最高?
预测分析:
- 我们能预测未来贷款拖欠的可能性吗?
硬件设置
我首先使用 Python 3、CUDA 11.0 和 Ubuntu 18.04 映像在 AI 平台笔记本上创建了一个托管 JupyterLab 环境。我选择了一台带有 2 个 Nvidia A100 GPUs 的机器,但也可以从 1 个或 2 个 T4 GPU 开始,在一个较小的数据样本上进行测试。Nvidia A100s 目前仅在美国中部地区提供,以防您在下拉列表中没有看到它。
作者图片
软件设置
设置一个有许多活动部件的合适环境(GPU 驱动程序、CUDA、NCCL、RAPIDS、Python 等)。)可能是复杂而痛苦的。我已经在我们的基础映像中选择了 Ubuntu 18.04、Python 3 和 CUDA 11.0,所以我们需要构建合适的兼容 RAPIDS 环境。幸运的是, RAPIDS 站点有一个很棒的 UI 工具,可以根据你的需求生成准确的 conda 命令。我添加了 gcsfs 来访问 Google 云存储中的文件,添加了 matplotlib 来生成一些图表。设置硬件和软件环境花了我 20 分钟。
资料来源:https://rapids.ai/start.html
conda create -n rapids-0.17 -c rapidsai -c nvidia -c conda-forge -c defaults rapids-blazing=0.17 python=3.7 cudatoolkit=11.0 matplotlib=3.3.3 gcsfs=0.7.1
Dask 初始化
由于我的 JupyterLab 环境有 2 个 GPU,我将使用 dask 来编排 RAPIDS,将每个 GPU 视为一个工人。这很简单,只需 2 条 import 语句和 2 行集群初始化代码。
from dask_cuda import LocalCUDACluster
from dask.distributed import Clientcluster = LocalCUDACluster()
client = Client(cluster)
数据摄取
你可以从这个 Nvidia 演示库下载完整的 17 年数据或更小的子集来测试这个工作流。我在 GCS 呆了整整 17 年,有 100 多个 csv 文件,总计约 200GB,可以使用熟悉的 pandas 方法阅读它们。您还可以将文件下载到本地文件系统,并相应地更新位置。
csv_acq_fnames='gs://mchrestkha-github-ml-examples/fannie_mae_loans/acq/Acquisition_20*'
csv_perf_fnames='gs://mchrestkha-github-ml-examples/fannie_mae_loans/perf/Performance_20*'df_acq = dask_cudf.read_csv(csv_acq_fnames, sep='|', names=col_acq_names, dtype=dtype_acq, columns=col_acq, parse_dates=parse_dates_acq)df_per = dask_cudf.read_csv(csv_perf_fnames, sep='|', names=col_per_names, dtype=dtype_per, columns= col_per, parse_dates=parse_dates_per)
数据探索
使用 RAPIDS+dask 的一个主要原因是利用所有您喜欢的 pandas 功能,但在多个工作人员之间在 GPU 上运行更快。下面是我用于初始数据探索和分析的几个例子。
df_acq['OrYr']=df_acq['OrDate'].str[-4:]
df_acq['OrUnpaidPrinc $M']=df_acq['OrUnpaidPrinc']/1000000df_acq.head()df_acq_describe=df_acq.describe().compute()df_acq_nulls=df_acq.isna().sum().compute()df_acq_summary = df_acq.groupby('OrYr',as_index=False).agg({'LoanID': 'count','OrUnpaidPrinc $M': 'sum'}).compute()
在理解了数据的结构、粒度和信息之后,我定义了我要预测的内容。在查看数据字典时,有两列很有趣。‘当前贷款拖欠状态’可用于标记一笔贷款是否曾经拖欠过,而’止赎日期可用于检查一处房产是否被止赎。我为每个事件创建标志,并可以根据我试图回答的业务问题将它们作为我的目标变量(又名标签)。对于这个例子,我希望预测贷款是否会有任何拖欠事件,所以我将使用前者作为标签。
df_per['DelinquentEvent']=0
df_per['DelinquentEvent']=df_per['DelinquentEvent'].where(df_per['CLDS']<1,1)df_per['ForeclosureEvent']=0
df_per['ForeclosureEvent']=df_per['ForeclosureEvent'].where(df_per['ForeclosureDate'].isnull()== True,1)
对我来说,一个很大的收获是,虽然直接从 dask _ cudf 或 cudfdata frames 绘制图表有局限性,但你可以很容易地围绕它进行设计。我使用了以下方法:
- 使用 GPU+Dask 进行繁重的数字处理,以创建汇总视图
- 将汇总的数据帧转换回熊猫
- 使用任何 MatPlotlib 库,使用系统内存绘制您最喜欢的图表
下面是一个总结全部 1.8B 记录,然后按年份绘制拖欠率时间序列图表的例子
df_per_yr_summary = df_per.groupby('YrRep',as_index=False).agg({'LoanID': 'count', 'DelinquentEvent':'sum'}).compute()df_per_yr_summary['DelinquencyEventsperLoan']=df_per_yr_summary['DelinquentEvent']/df_per_yr_summary['LoanID']df_per_yr_summary.to_pandas().sort_values(by=['YrRep']).plot.line(x='YrRep',y='DelinquencyEventsperLoan')
作者图片
建模数据集
然后,我将每笔贷款的数据聚集到一行(也就是 example ),并加入所有贷款属性(特性),这些属性(特性)只在发起时可用。这确保了我没有数据泄漏。
df_per_loan = df_per.groupby('LoanID',as_index=**False**).agg({'DelinquentEvent':'sum'}).compute()df_per_loan['DelinquentFlag']=0
df_per_loan['DelinquentFlag']=df_per_loan['DelinquentFlag'].where(df_per_loan['DelinquentEvent']<1,1)joined=df_acq.merge(df_per_loan,on=['LoanID'],how='left')
然后,我选择我的特征,并将分类变量转换成指示变量(一次性编码)。
label=['DelinquentFlag']
cat_features=['Channel','OccStatus','FTHomeBuyer','LoanPurpose','PropertyType','ProductType','RelMortInd']
num_features=['OrInterestRate','OrUnpaidPrinc','OrLoanTerm','OrLTV','OrCLTV','CreditScore']
modeling_dataset=joined_categorized[cat_features + num_features + label]modeling_dataset=dask_df.get_dummies(modeling_dataset)
培养
最后,我为 XGBoost 设置了输入参数,并训练了模型。
<define feature columns>X = joined[features]
y = joined['DelinquentFlag']
dtrain=xgb.dask.DaskDeviceQuantileDMatrix(client, X,y)param = {
'max_depth': 8,
'objective': 'reg:squarederror',
'tree_method': 'gpu_hist'
}
bst = xgb.dask.train(client,param, dtrain,num_boost_round=100)
摘要
大数据生态系统继续发展,有许多选择(Spark、Beam、Flink、Dask、Modin、Ray、BigQuery、SnowFlake、Athena 等)。).历史上,这些选项中的许多都需要在可用性、灵活性和规模之间进行权衡。幸运的是,这些项目中的许多正在投资,以减少这些权衡的需要。
我最兴奋的是这将对数据世界的无名英雄数据分析师产生的影响。让数据分析师和公民数据科学家能够无缝地探索和分析大数据对企业有着巨大的好处:更具洞察力的 BI 报告、更准确的预测和预测模型,以及更具数据驱动力的创新决策。
我在谷歌云的 AI 平台笔记本电脑上提供了一个带有 RAPIDS 的工作流,任何数据分析师今天都可以利用它。该架构遵循以下原则,这是开始加速您的大数据(和数据科学)工作流的良好开端,之后可能会扩展到 Spark 或 Beam,以满足更复杂的管道编排需求。
- 快速简单的设置(< 30 min)
- No distributed cluster; Scale vertically on one machine before adding horizontal scaling complexity
- Familiar python tools and APIs (pandas for the win!)
- Scale to 100s of millions of rows of data
- Accelerate the entire data life cycle
Big data and machine learning technologies are evolving as fast as ever. High tech companies and research departments will continue to push the limits for their advanced needs. It is however important to step back and think about what is available today. I believe there is a HUGE backlog of use cases that data analysts can solve better & faster with the tools available today. I am excited for many projects (RAPIDS, Dask, BQML, Koalas on Spark) focusing on scalability AND usability to lower the barrier to entry and empower a much larger part of the data community.
Have a question or want to chat? Find me on Twitter
这个博客的笔记本例子可以在我的 GitHub 上找到。
非常感谢艾瑟姆·坎、雷米·韦尔奇、董蒙、阿伦·拉曼、拉杰什·塔拉姆、迈克尔·托马斯、拉詹·阿罗拉和苏巴汉·阿里对我的教育和对示例工作流程的帮助。
常见问题解答
- **【问】对于上游的数据处理,数据仓库(像雪花或者 BigQuery)不是更高效吗?【A】**如果您的公司/团队能够访问可扩展的数据仓库,那么是的,在您的工作流程早期,尽可能多地将计算(可以用 SQL 编写的)推给它。这篇博客的重点是一个自包含的工作流,它只需要对象存储(或本地文件系统)和一个带有 GPU 的按需 Jupyter 笔记本实例。它更像是一个数据湖架构。
- 【问】GPU 不是超级贵吗?【A】首先阅读本文,因为 GPU 可能不太适合您的工作流程。然而,GPU 正在成为机器学习模型训练步骤的标准。如果您计划在管道的一个步骤中使用 GPU,RAPIDS 允许您运行并加速管道的其余部分,这可能会增加 GPU 的投资回报。
- **【问】急流如何融入火花与光束?【A】**这篇博客关注的是单节点设置,其中各种 RAPIDS 库(即 cudf、cuml)可以像 pandas 一样独立使用。对于多节点设置,您可以将 RAPIDS 视为一个较低级别的 GPU 加速层,可以支持不同的分布式大数据框架。当在 GPU 上运行数据任务时,Spark 和 Dask 都在幕后利用 RAPIDS。我假设 Apache Beam 项目将来也会考虑集成 RAPIDS 来加速 GPU。
- **【Q】这个好像没那么快!这能优化多快?【A】**我不是专家,所以我相信有几种方法可以加速(例如,优化文件大小&分区、索引、利用一些未使用的 CPU 内核等。).这将需要一些试错。我计划在未来进一步探索的一个部分是使用 Dask Dashboard 来更好地了解瓶颈,使用 NVDashboard 来更好地了解 GPU 利用率。如果你有一个用例,数据集和基准,我很乐意连接并帮助你测试它。
- **【Q】多个用户可以共享同一个环境来共享基础设施和 GPU 吗?【A】**好抓!这种工作流保持了每台机器一个用户的简单性(可以按需关闭),但对于团队来说仍然不具成本效益,尤其是对于更昂贵的 Nvidia A100 或 V100 GPUs。有一些在 Kubernetes 上建立多租户笔记本环境的解决方案,这确实增加了一些复杂性。Nvidia A100 也因其多实例 GPU (MIG) 架构而引人入胜,该架构允许您将每个 GPU 分成 7 个单元,以便不同的用户可以同时在每个单元上运行任务。为未来的博客做些调查。
Julia 中构造函数的高级视图
原文:https://towardsdatascience.com/an-advanced-look-at-constructors-in-julia-5b428882dde8?source=collection_archive---------32-----------------------
用 Julia 完整地看一下如何创建复杂的构造函数。
(图片由作者提供)
介绍
构造函数是一种计算机编程工具,它允许将数据类型压缩到易于理解的容器中,这些容器可以有效地用作变量和方法,以创建一些非常惊人的结果。然而,在 Julia 语言中,构造函数是自成一体的——比人们第一眼看到的要复杂得多。Julia 中的类型可以以多种方式处理,它们可以是编译器熟知的完全函数式类型,也可以是完全不可变的面向对象类型,这些类型在创建时就交付给编译器——这是该语言魅力的一部分。
在 Julia 编程语言中有两种不同类型的构造函数:
- 内部构造函数
- 外部构造函数
这两个构造函数都有自己特定的用途,并且最终都返回相同的类型。然而,我们可以使用外部构造函数来支持不同类型的算术和类型处理。
外部构造函数
外部构造函数是程序员将在 Julia 中使用的典型构造函数类型。也就是说,这通常只是冰山一角,更多的是对终极编程接口的掩盖。也就是说,您可以使用 struct 关键字创建一个外部构造函数。见见我的新朋友,看门人哈尔:
abstract type Employee endstruct Janitor <: Employee
wage
age
yearsend
Hal = Janitor(25, 63, 2)
我们刚刚为我们的新类型——看门人——创建了一个外部构造函数。你可能对这类构造函数很熟悉,但是,假设我们不查询数据库就不知道 Hal 的年龄,但是,我们有每个雇员的 UUIDs 列表?这个应用程序会很快崩溃,需要调用一个函数来替换类型。这正是内部构造函数的目的。
内部构造函数
内部构造函数可以用来创建不一定是用户提供的数据容器的类型,而是你的函数。虽然在大多数函数式编程语言中,这意味着创建一个远离该构造函数的完全独立的函数,但在 Julia 中,这两个构造函数可以相互协作,并让编译器准备好返回内部构造函数正在处理的类型,请看:
abstract type Employee endstruct Janitor <: Employee
wage::Float64
age::Int64
years::Int64 function Janitor(uuid::Int64) wage, age, years = query_db(uuid) return new(wage, age, years)
end
如果我们用一个浮点数和两个整数调用看门人,就像这样:
Hal = Janitor(8.25, 5, 1)
我们仍然得到和以前一样的回报。然而,我们也可以用单个整数调用它,这将运行我们的内部构造函数,并使用 UUID 的逻辑!
Hal = Janitor(hals_UUID)
当然,这将返回一个带有我们提供的信息的看门人类型,我们可以在它上面添加许多类型转换来优化这段代码,使它比其他方式更有效。对于用一个完全独立的方法构造外部构造函数来说尤其如此!
我们可以更进一步,以多种方式将 dispatch 与适当的类型一起使用。例如,我们可以在内部构造函数中使用 dispatch 来为数据类型创建更多的功能,这些数据类型可以被传递用于返回。使用这种方法我们还可以做的另一件大事是利用 Julia 的类型层次系统。这个系统类似于 Python 中的子类系统。
尽管 Julia 本质上是一种相对基本的函数式编程语言,但正是这种简单性帮助它实现了这些突破性的特性。至少对我来说,这个概念是非常惊人的,因为我们不仅可以通过函数方法调用在全局范围内使用 dispatch,而且还可以通过各种可能的方式一起使用多个构造函数来完成任务!
结论
一般来说,构造函数是一个必要且重要的编程概念。然而,在 Julia 编程语言中,构造函数的能力实际上是惊人的。它们不仅可以用来创建可变和不可变类型,还可以利用初始化函数。如果对构造函数的这种观察很有趣,您可能也会喜欢另一篇文章,在这篇文章中,我使用相同的概念在 Julia 中进行面向对象编程!:
谢谢你的阅读,这对我意义重大!
一个 AI 智能体学习玩井字游戏(第 3 部分):训练一个 Q 学习 RL 智能体
原文:https://towardsdatascience.com/an-ai-agent-learns-to-play-tic-tac-toe-part-3-training-a-q-learning-rl-agent-2871cef2faf0?source=collection_archive---------10-----------------------
我们用 Q 学习训练一个强化学习代理玩井字游戏
本文是让计算机使用强化学习玩井字游戏系列的一部分。你可以在这里找到 所有文章 。我们的目标是提供一个完整的实现,您可以真正从中挑选并学习强化学习。按顺序阅读文章可能是最好的。文章包括所有代码 都可以在 Github 上找到。
强化学习回顾
在本系列的第 1 部分和第 2 部分中,我们为我们的强化学习(RL)代理构建了对手,所以现在我们可以开始实际的 RL 代理了。在我们进入实际实现之前,我想花一些时间了解一下 Q 学习是如何工作的。
正如我们在第 1 部分中了解到的,RL 基于以下关键概念:
代理的目标是找到一个有效的策略,即在给定的情况下什么行动是最优的。在井字游戏中,这意味着给定棋盘上的状态,哪一步棋是最优的。请注意,该策略关注的是长期价值 Q,而不仅仅是短期回报 R。更数学地说,该策略是具有状态𝑠和行动𝑎的函数𝑄(𝑆,𝑎,强化学习是学习该函数的方式。
RL 的列表方法
Q-learning 是一种常见的强化学习方法。这种方法的核心是 Q 表,它存储状态和动作的所有组合,本质上表示 Q 函数的离散版本。在本文中,我们使用字典存储 qtable。给定某个 boardstate,我们可以确定哪个动作具有最高的 Q 值:
'e'
给定board_state_1
,我们能做的最好的移动是e
(中间的方块),因为它有最高的 Q 值。
定义了 Q 表后,我们的主要挑战是学习适当的 Q 值。以下伪代码描述了学习过程:
for all episodes:
if not boardstate in qtable:
qtable[boardstate] = 0 for all actions
if (pick random action with chance epsilon)
pick random action
else
pick action with highest q value for boardstate
Q[boardstate, action] = update_qtable(Q[boardstate, action],
reward for action,
Q[next_boardstates])
tree search makes move
于是我们就对着树搜索玩了很多井字游戏(剧集),慢慢更新 Q 值。一些重要的观察结果:
- 我们用
0
初始化我们的 qtable,开始时没有清楚的指示什么是好的移动。 - 如果存在多个具有最大 Q 值的移动,我们从这些移动中选择一个随机动作。这是为了刺激对 boardstates 的探索。在我们训练过程的开始,有多个最大值是很常见的。
- 我们并不总是从 q 表中选择最优的移动(剥削),而是随机选择𝜖.这是为了通过探索可能会有好的回报的随机新板状态来刺激学习过程。这确保我们不会很快陷入局部最小值,而是继续寻找更好的移动。这种开发与探索的动态是有效学习 Q 表的重要部分。
- 如果我们赢了,奖励是+10 分,如果我们输了,奖励是-10 分,如果我们平了,奖励是+5 分。
Q 学习的魔力
Q 学习中最重要的步骤是更新表中的 Q 值。下面的伪等式描述了它的工作原理:
new Q value = old Q value + instantaneous reward + maximum Q for next states after the action we took
因此,新的 Q 值考虑了以前的 Q 值,我们在状态S
采取行动a
得到的奖励,以及在状态S
采取a
行动后可能的 Q 值*。请注意,要了解长期 Q 值,我们只需预测下一个可能的最大 Q 值。这与树搜索方法形成了鲜明的对比,树搜索方法一直向前看,直到游戏结束。对我来说,通过只看一步棋就能获得长期回报,这让 Q-learning 变得相当神奇。当然,不利的一面是我们需要玩很多游戏来慢慢地让所有的 Q 值在 Q 表中传播。*
以下等式更正式地表达了更新规则:
其中(1−𝛼)𝑄(𝑠_𝑡,𝑎_𝑡)等于在𝑠_𝑡州𝑎_𝑡采取行动的旧 q 值,𝛼𝑟_𝑡等于瞬时回报,𝛼𝛾 max(𝑠_𝑡+1,𝑎)在采取行动a
并在𝑠_𝑡+1.州结束后,我们下一步行动可以得到的最大 q 值该等式包括多个系数:
- 𝛼学习率,它决定了给定新信息时 q 值更新的速度。如果学习率为零,新值就是旧值。这实质上意味着算法没有学习任何新东西。alpha 值为 1 只是丢弃了这个旧值,并完全依赖于由其他项计算的新 Q 值。介于 0 和 1 之间的值允许您控制学习进度。在足够快地学习和不要太快地专注于一个特定的 Q 值之间取得平衡是 Q 学习挑战的一部分。
- 𝛾贴现因子。这决定了我们是主要关注短期回报(小𝛾)还是长期价值(大𝛾).
训练我们的特工
有了理论基础之后,我们就可以开始实际训练我们的 RL 代理了。Github 上的 Python 脚本[train_qlearning.py](https://github.com/PaulHiemstra/qlearning_paper/blob/master/train_qlearning.py)
按照我们之前定义的伪代码训练方法执行我们的整个训练循环。前十几行初始化我们构建的和优化的的树,这将作为我们 RL 代理的对手。接下来,我们初始化两个对象:
第一个对象跟踪井字游戏棋盘的状态。它允许一个人采取行动,检查游戏是否结束,并在游戏结束时分发奖励。GitHub 上的文件[support_functions.py](https://github.com/PaulHiemstra/qlearning_paper/blob/master/support_functions.py)
包含了所有的细节。第二个对象player_tree
代表我们的 RL 代理,它玩游戏并慢慢更新它的 Q 表。注意,我们手动调整了alpha
、gamma
和epsilon
的值,但是我们的学习似乎对这些值不太敏感。大概井字游戏对于 Q 学习来说真的不是一个有挑战性的问题。
训练循环用这些 Python 对象玩井字游戏,慢慢学习 Q 表:
这里我们玩 10000 个井字游戏。
我们的代理表现如何?
作为我们训练过的 RL 代理的基准,我们首先让一个未训练过的代理来对抗树搜索。我们简单地从零开始创建一个播放器,并让它在没有 Q 学习的情况下与树搜索进行游戏:
-10.0 768
5.0 232
dtype: int64
未经训练的代理通常会输掉游戏(-10)或和棋(5)。鉴于我们被允许开始游戏,这是糟糕的表现。相比之下,使用[train_qlearning.py](https://github.com/PaulHiemstra/qlearning_paper/blob/master/train_qlearning.py)
对接受过 100.000 次游戏培训的代理进行相同的分析:
5.0 1000
dtype: int64
显示 RL 代理已经变得非常擅长对付树,总是打成平局。
Q 表
为了更深入地了解 Q learning 如何学习如何玩井字游戏,我们将重点放在 Q 表的内容上。下图显示了 100.000 训练游戏结束时的最终 Q 表。请记住,我们是X
玩家,蓝色表示好的 Q 值,红色表示负的 Q 值:
Q 表包含 RL 代理具有的关于井字游戏策略的信息。好的例子有:
在这里,我们了解到弯角是开始时很好的动作,这从深蓝色中可以明显看出。此外,我们(X
)学会了通过树搜索(O
)来阻止移动。这里的阻挡移动是蓝色的,其他移动是深红色的。
除了最终学习的 Q 表,下面的 youtube 电影很好地说明了 Q 表是如何在 100,000 个游戏中慢慢发展的。
随着新状态的引入,表会不断增长。此外,白色慢慢地被正值(蓝色)和负值(红色)所取代,表明代理知道什么是好的和坏的移动。
在我们的下一部分,我们将关注我是如何可视化 Q 表的。
我是谁?
我叫 Paul Hiemstra,是荷兰的一名教师和数据科学家。我是科学家和软件工程师的混合体,对与数据科学相关的一切都有广泛的兴趣。你可以在 medium 上关注我,或者在 LinkedIn 上关注。
如果你喜欢这篇文章,你可能也会喜欢我的其他一些文章:
- 没有像应用数据科学这样的数据科学
- 牛郎星图解构:可视化气象数据的关联结构
- 面向数据科学的高级函数式编程:使用函数运算符构建代码架构
一个人工智能代理学习玩井字游戏(第 4 部分):使用 plotnine 和 ffmpeg 可视化 Q 表
原文:https://towardsdatascience.com/an-ai-agent-learns-to-play-tic-tac-toe-part-4-visualising-the-q-table-using-plotnine-and-ffmpeg-9462d50ae482?source=collection_archive---------15-----------------------
在这里,我们可以看到培训过程中 Q 表的发展
本文是让计算机使用强化学习玩井字游戏系列的一部分。你可以在这里找到 所有文章 。我们的目标是提供一个完整的实现,您可以真正从中挑选并学习强化学习。按顺序阅读文章可能是最好的。文章包括所有代码 都可以在 Github 上找到。
可视化学习过程
很难真正理解机器学习算法在做什么。尤其是当性能没有改善时,机器学习的黑盒性质真的很难发现算法是否真的在学习什么。能够确定算法正在学习什么,对于诊断我们的黑盒方法实际上在做什么非常重要。
在我们的例子中,Q 值的变化代表 RL 代理正在进行的学习。幸运的是,对于我们简单的井字游戏来说,有一个非常直观的方法来可视化 Q 表。在下一张图中,我们用X
和O
显示了玩家已经做出的移动,并以颜色显示了相应的 Q 值:
X
和O
代表我们必须做出决定之前的状态,彩色方块代表可能的下一步行动的 Q 值。这证实了 Q 表存储了政策:在给定的棋盘状态下,什么棋是好的(高 Q)。在这个特殊的示例图中,我们了解到拐角是开始时很好的移动,从深蓝色中可以明显看出这一点。此外,我们学会了通过树搜索来阻止移动。这里的阻挡移动是蓝色的,其他移动是深红色的。
建立我们的观想
为了我们的可视化,我们需要来自第 3 部分的训练有素的 RL 代理的以下信息,这些信息代表 Q 表:
- 表中所有可能状态的标识符列表,按它们在训练过程中出现的顺序排列。这被存储为 boardstate 数组的一个 sha1 散列。
- 状态链接到实际电路板状态数组的字典
- 状态与下一个可能动作的 Q 值相关联的字典,即 Q 表本身。
rl_data.pkl
包含第 3 部分中针对受训代理的信息。为了说明内容,我们打印了属于某个州的项目:
351d61138857f04cc521e13b7173f266420ea412
{'d': -3.7017636879676767, 'f': -3.5089737163159778, 'g': -3.5089737163159778, 'h': 3.9726827543029692, 'i': -3.63814513936129}
[[ 1\. -1\. 1.]
[ 0\. -1\. 0.]
[ 0\. 0\. 0.]]
接下来,我们需要将电路板状态数据与 Q 值结合起来。对于上面打印的状态,这将产生:
该绘图数据包含电路板上每个 x、y 坐标的 board_state 和 Q 值。请注意,显然只能通过电路板状态或 Q 值。接下来,我们可以使用[plotnine](https://plotnine.readthedocs.io/en/stable/index.html)
绘图库中的geom_tile
来绘制。如果您不熟悉 plotnine 或 ggplot2,请阅读本教程。
其中我们已经走的棋(棋盘状态)是灰色的'X'
和'O'
,下一步棋的 Q 值是彩色方块。这些值是有意义的,因为蓝色移动阻挡了'O'
玩家,而红色移动让他们获胜。
可视化整个表格
随着我们对一个棋盘状态的可视化,我们需要将它扩展到整个 Q 表。所以我们:
- 将数据生成部分包装在一个函数中,并为所有可能的状态调用它。我们将结果连接成一个大的
DataFrame
。 - 在
plotnine
代码中添加对facet_wrap
的调用,以创建每个唯一状态的可视化电路板状态。 - 确保每个电路板状态的可视化顺序是按时间顺序排列的,即在培训过程中添加到 Q 表中的顺序。我使用
pd.Categorical
来实现这一点,其中分类变量的顺序由传递给categories
参数的列表决定。
这会产生以下结果:
注意,您可以在 Player 类中找到代码,更具体地说是在plot_qtable
方法中。详见 Github 上的支持功能。
制作 Q 表的动画
到目前为止,Q 表的可视化是 100,000 场比赛后的决赛表。为了了解 Q 表是如何随时间发展的,我们可以简单地在整个培训过程中绘制 Q 表,并将这些图拼接成一部电影。在剧本[train_and_generate_frame.py](https://github.com/PaulHiemstra/qtable_movie_paper/blob/master/train_and_generate_frames.py)
中,我们训练了一个 Q 学习代理,但除此之外,我们每隔这么多集就创造情节。训练循环:
现在有了一个额外的部分,它在一个plots
字典中存储了一个 Q 表的图形。完成培训后,我们可以将这些图作为图像转储:
为了节省时间,我们使用tqdm
中的process_map
来创建 5 个工作进程,每个转储将这些进程绘制到磁盘上的映像中。请注意,由于一个 bug ,您不能在 Jupyter 笔记本中运行这段代码,但是在一个单独的脚本中这可以很好地运行。
运行脚本后,我们在磁盘上得到几百张图片,我们用ffmpeg
把它们拼接成一部电影。在命令行上(在我的例子中是 WSL ),我向ffmpeg
发出以下调用:
ffmpeg -r 30 -f image2 -s 1920x1080 -i qtable_ep%06d.png -vcodec libx264 -crf 25 -pix_fmt yuv420p qtable.mp4
以 30 秒的 mp4 文件结束:
随着新状态的引入,表会不断增长。此外,白色慢慢地被正值(蓝色)和负值(红色)所取代,表明代理知道什么是好的和坏的移动。
我是谁?
我叫 Paul Hiemstra,是荷兰的一名教师和数据科学家。我是科学家和软件工程师的混合体,对与数据科学相关的一切都有广泛的兴趣。你可以在 medium 上关注我,或者在 LinkedIn 上关注我。
如果你喜欢这篇文章,你可能也会喜欢我的其他一些文章:
- 没有像应用数据科学这样的数据科学
- 牛郎星图解构:可视化气象数据的关联结构
- 面向数据科学的高级函数式编程:使用函数运算符构建代码架构
一个人工智能代理玩井字游戏(第 1 部分):建立对手来对抗
原文:https://towardsdatascience.com/an-ai-agent-plays-tic-tac-toe-part-1-building-the-opponent-to-play-against-bb5af74fded1?source=collection_archive---------9-----------------------
我们构建了一个强力极大极小树搜索,它将作为我们强化学习方法的对手
本文是让计算机使用强化学习玩井字游戏系列的一部分。你可以在这里找到https://towardsdatascience.com/tagged/rl-series-paul的所有文章。我们的目标是提供一个完整的实现,您可以真正从中挑选并学习强化学习。按顺序阅读文章可能是最好的。文章包括所有代码 可以在 Github 上找到
强化学习到底是什么?
强化学习是继监督和非监督建模之后的第三种建模范式。它最近取得了巨大的成功,包括击败世界最佳围棋手。仅仅几年前,这一壮举还被认为是不可能的,因为围棋中巨大的可能棋步甚至让国际象棋相形见绌。我只会简单地介绍一下强化学习是如何工作的,但下面的 youtube 电影应该会提供更深入的介绍( Intro RL , Deep RL )。
强化学习(RL)基于以下关键概念:
有一个计算机代理采取行动( A )作用于环境( E )。该环境通过为该行为提供奖励( R )做出响应,并使系统进入下一个状态( S )。以下面的状态为例:
这里我们考虑 O 玩家下一步行动的两个选项:绿色和红色选项。选择绿色选项会产生很高的奖励,因为我们阻止了 X 玩家获胜。或者,红色选项产生低奖励,因为这允许 X 玩家获胜。通过多次玩井字游戏并获得奖励,RL 代理将慢慢了解在特定状态下什么行为提供良好的长期价值。状态到最优行为的映射在 RL 行话中被称为策略。
我们第一个简单的极大极小算法
有了 RL 的基础知识,我们现在可以专注于本文的目标:为我们的 RL 代理构建一个对手。对我们来说幸运的是,井字游戏足够简单,可以用蛮力的方式解决。这确保了我们在井字游戏中以最佳的走法结束,确保我们的 RL 代理可以从最佳的走法中学习。
主要思想是将所有可能的井字游戏状态存储在一个树中,并确定对于给定的状态,下一步采取什么措施会产生好的结果。这是通过递归搜索树并找到奖励来完成的。每个可能的下一步棋下面的子树中的奖励告诉我们哪一步棋是最优的。为了说明这是如何工作的,我们从一个非常简单的树开始(基于这个 youtube 视频):
在这个游戏中,两个玩家竞争:一个有最大化分数的目标,一个有最小化分数的目标。首先,最大化玩家可以在树的顶端选择,然后最小化玩家可以选择,以此类推。作为最大化玩家,我们的最优选择似乎是向右走,这就是 9 的高分所在。然而,第二个玩家在有选择的时候会选择 2。所以,在这种情况下,最优选择是向左走,得三分。
使用最小最大算法来解决这种树。在树的每一层,最小或最大玩家做出他们的最佳选择。如果我们用 Python 表达这棵树,我们得到:
*root
├──
│ ├── 3
│ └── 5
└──
├── 2
└── 9*
我们可以通过遍历树来解决极大极小问题:
*3*
这实际上显示了给定这一特定的树,最大玩家可以得到的正确的最大分数:3。用伪代码显式实现递归揭示了幕后发生的事情:
*start-game: minmax('root') ->
max-player: max([minmax('l1'), minmax('r1')]) ->
min-player: max([min([minmax('l1-1), minmax('l1-2')]),
min([minmax('r1-1'), minmax('r1-1')])]) ->
end-tree : max([min([3, 5]),
min([2, 9])]) ->
max([3, 2]) ->
3*
井字游戏树上的最小最大树搜索
对于井字游戏,我们可以使用完全相同的极大极小方法,使用更大的树。首先,我们从顶部开始,最大玩家有九个可能的移动,然后我们剩下最小玩家有八个移动,等等:
留给我们的是一棵巨大的树,上面有所有可能的组合。为了存储井字游戏状态,我们为棋盘上的每个区域分配一个字母:
创建一个 Python 类来存储状态,允许更新棋盘,检查游戏是否结束,并根据结果返回游戏的值:
接下来,我们递归地创建巨型树,并在每个节点添加棋盘状态对象。每个节点的 ID 是所采取的步骤的顺序,例如acig
。
完成树后,我们可以使用非常类似于我们首先开始的简单树的极大极小码:
使用determine_move
我们现在可以得到下一个最好的移动。请注意,如果多个移动具有相同的最大值,我们在这些最大移动中选择一个随机移动。比如 max 玩家玩a
方块的时候:
*e
2.986009120941162*
请注意,它选择了中间的e
方块,这在井字游戏中确实是非常强的一步棋。此外,确定这一步大约需要 3 秒钟。
解决速度慢的问题
所以,现在我们的 RL 代理有了一个有价值的对手。唯一的问题是它非常慢,实际上对于我们的 RL 代理来说太慢了,因为它需要玩很多游戏来学习井字游戏。在第 2 部分中,我们将使用一种高级编程技术来大大加快树搜索的速度。
我是谁?
我叫 Paul Hiemstra,是荷兰的一名教师和数据科学家。我是科学家和软件工程师的混合体,对与数据科学相关的一切都有广泛的兴趣。你可以在 medium 上关注我,或者在 LinkedIn 上关注。
如果你喜欢这篇文章,你可能也会喜欢我的其他一些文章:
- 没有像应用数据科学这样的数据科学
- 牛郎星图解构:可视化气象数据的关联结构
- 面向数据科学的高级函数式编程:使用函数运算符构建代码架构
人工智能代理玩井字游戏(第 2 部分):使用记忆化加速递归函数
原文:https://towardsdatascience.com/an-ai-agent-plays-tic-tac-toe-part-2-speeding-up-recursive-functions-using-memoization-97253529aea8?source=collection_archive---------19-----------------------
我们提高了蛮力树搜索的速度,使其在强化学习中更实用
本文是让计算机使用强化学习玩井字游戏系列的一部分。你可以在这里找到https://towardsdatascience.com/tagged/rl-series-paul的所有文章。我们的目标是提供一个完整的实现,您可以真正从中挑选并学习强化学习。按顺序阅读文章可能是最好的。文章包括所有代码 都可以在 Github 上找到。
在本系列的第 1 部分中,我们实现了一个树搜索极大极小算法,作为我们的强化学习(RL)代理的对手。结论是,虽然它有效,但算法太慢,不能用于训练我们的 RL 代理。第 2 部分的目标是显著加快极大极小算法的速度。
一个可能的解决策略是最小化树的大小。例如,井字游戏是全面对称的,所以我们可以彻底消除大约一半的树。然而,我选择让算法和树保持原样,并且更专注于用一种叫做记忆化的高级编程技术来解决这个问题。
一般的想法是,当一个函数被调用时,函数的结果被存储在一个字典中,其中的键等于函数调用参数。下一次使用这些参数调用函数时,字典中的结果将被简单地返回。在我们的例子中,这将减少从递归搜索树到在字典中查找值的最佳移动。
让我们首先将树加载回内存,并加载我们的 minimax 代码。请注意,github 存储库包含一个生成该树的 Python 脚本。
现在我们可以请求最小化玩家的下一步行动,假设最大化玩家已经开始了第a
步:
*2.9204039573669434*
在我的机器上大约需要 3 秒钟。
在网上我找到了下面的记忆实现。它创建了一个记忆化类,我们可以用它来修饰我们的递归极大极小树搜索。这很好地将记忆功能与被调用来完成工作的实际函数分离开来。注意,我从字典中排除了第一个参数,以防止键变得太大,从而减慢记忆过程。
这种技术的工作方式类似于我在本文中使用的函数操作风格,将核心函数与辅助函数分离开来。在这里,函数操作符是装饰类的一个很好的替代品。
有了记忆,我们可以测试它是否真的表现得更好。在下面的代码中,我们调用该函数两次,并计算有内存的版本要快多少:
*49962.9296875*
很好,这产生了大约 50k 倍的速度提升。最后一步是通过 minimax 函数强制所有可能的棋盘状态,用所有函数调用填满记忆缓冲区:
在我的机器上大约需要 30 秒。
由于预先计算了所有的树搜索,determine_move
现在足够快,可以快速运行所需数量的井字游戏。在下一部分,我们将实现称为 Q-learning 的 RL 算法。
我是谁?
我叫 Paul Hiemstra,是荷兰的一名教师和数据科学家。我是科学家和软件工程师的混合体,对与数据科学相关的一切都有广泛的兴趣。你可以在 medium 上关注我,或者在 LinkedIn 上关注我。
如果你喜欢这篇文章,你可能也会喜欢我的其他一些文章:
- 没有像应用数据科学这样的数据科学
- 牛郎星图解构:可视化气象数据的关联结构
- 面向数据科学的高级函数式编程:使用函数运算符构建代码架构
赖以生存的算法
原文:https://towardsdatascience.com/an-algorithm-to-live-by-f60dccfa553d?source=collection_archive---------33-----------------------
37%法则
克里斯蒂安·祖尼加博士
假设你正在找房子,想找到最适合你的公寓。虽然你通常可以在网上找到租金价格和图片,但你可能还是想亲自去看看。你终究要住在那里。您可能想查看一些以收集信息,但不想进行扩展搜索。等待太久也可能代价高昂。你怎样才能最好地选择你的新公寓?图 1 显示搜索顺序开始,在看到一些公寓后结束。这也适用于其他情况,比如你的新工作、新员工或新搭档。一般来说,这个问题被称为最优停止问题。[1]
图 1 应该参观多少套公寓才有机会选出最好的一套?(图片由作者提供)
根据 37%规则,你应该先探索候选公寓的 37%,然后继续探索,选择下一个比你之前参观过的所有公寓都好的公寓。这种策略很有可能(37%)给你最好的公寓,而不必探索所有的选择。《赖以生存的算法》一书更彻底地探讨了这一策略,但没有很好地解释为什么它是最佳的。[2]
概率来拯救我们。如参考文献《概率模型导论》所示,用这种策略选择最佳公寓(或最佳奖问题)的概率,其实可以通过一些简化的假设找到[3]。你有 n 个候选公寓,将依次访问它们。这没有太大的限制性,因为这是您通常会做的事情。你收集了一份类似公寓的清单,一旦你进去看了每一个,你就会做出决定。最好的一个同样有可能是那 n 个公寓中的一个。在你参观完一个公寓后,你可以将它与你之前参观过的所有公寓进行比较,然后决定是接受还是拒绝它。例如,如果你有 10 个候选公寓,在你第四次拜访后,(10 的 37%大约是 4),你应该选择下一个比前 4 个更好的。
一般来说,如果 k 是要访问和拒绝的公寓数量,那么在给定最佳公寓在第 I 个位置的情况下,利用选择最佳公寓的条件概率,就可以求出选择最佳公寓的概率。这种技术被称为条件反射,通常可以简化概率计算。假设 k 是固定的,但最佳 k 是未知的。
X 是最佳公寓的位置,P(X=i) =1/n,最佳公寓位于位置 I 的概率。条件概率 P(选择最佳|X=i)可分为两种情况。
1.如果 i ⇐ k,那么最好的公寓在前 k 次拒绝中被拒绝,并且以后没有机会选择它。如果 i ⇐ k,p(选择最佳|X=i) = 0。
2.如果我> k,那么最好的公寓还没有被选中。选择最佳的概率取决于从位置 k 到 i-1 的所有公寓都比前 k 个公寓差。具体来说,前 k 公寓最好的,也应该是前 i-1 公寓最好的。因为概率是相等的,P(选择最佳| X=i) = k/(i-1)
选择最佳的概率变成:
对于 n= 10 套公寓,编写这个规则并绘制多个 k 值的概率非常简单,如图 2 所示。该图显示,37%法则表明,最大概率发生在 3-4 套公寓附近!
图 2 通过拒绝 k 个初始公寓,然后选择目前看到的最佳公寓,选择最佳公寓的概率。有 n=10 套公寓。(图片由作者提供)
虽然概率可以模拟,但也有近似解析解。求和可以用积分来近似。n 值越大,近似值越好。
选择最佳公寓的概率是 k 的函数。为了找到最大值,我们可以假设 k 是连续的,对 k 求导,并将其设置为 0。
求解 k 得到 k=n/e 。因为自然对数的底 e 是 2.718,所以 1/e 大约是 0.37,揭示了 37%法则的来源。
如前所述,37%规则有几个可能不成立的假设。然而,它仍然可以提供有用的指导。
参考文献
[1]https://en.wikipedia.org/wiki/Optimal_stopping
[2] Christian 和 Griffiths《算法生存》Henry Holt and Company,LLC 版权所有 2016
[3]罗斯《概率模型导论》第 11 版,爱思唯尔版权 2014
新冠肺炎疫情期间法国每日死亡率的分析
原文:https://towardsdatascience.com/an-analysis-of-daily-mortality-in-france-during-the-covid19-pandemic-95286928e80c?source=collection_archive---------25-----------------------
可视化不同时间和年龄组的死亡率趋势
此帖子包含过去 4 年法国每日死亡率的分析。这些数据在全球范围内按年龄组进行分析,并尽可能与当时有效的疫情遏制措施联系起来。
这里分析的原始数据可以从法国国家统计和经济研究所( INSEE )免费下载。要直接下载我的分析数据,请点击这里。数据跨度从 2018 年 1 月 1 日到 2021 年 12 月 6 日。我用来生成这里展示的各种情节的笔记本可以在 GitHub 上公开获得。
1.概观
研究期间法国每日死亡人数的比较可以在下图中看到。对应于 2020 年春季第一波 covid19 的峰值在图上很容易看到,从 2020 年 11 月开始的第二波也是如此。
由于疫苗接种的部署(从 2020 年 12 月 27 日开始)和治疗方案的整体改善,2021 年的总体死亡率仍然很高,但不会达到 2020 年的峰值。
法国每日死亡人数(图片由作者提供)
几个重要的日期有助于理解图上可见的一些趋势:
- 2020 年 3 月 17 日——法国政府首次对人口实施全面严格限制。它将持续到 2020 年 5 月 10 日。
- 2020 年 7 月 20 日—口罩成为封闭环境中的强制要求。
- 2020 年 10 月 30 日——第二次分娩(比第一次稍微宽松)。它将持续到 2020 年 12 月 15 日,一些限制仅在 2021 年 2 月初解除。
- 2021 年 2 月—50 岁以上的人可以接种疫苗。
- 2021 年 4 月 3 日——第三次全面分娩开始,持续到 2021 年 5 月 3 日(在此期间,学校和托儿所仍然关闭)。
- 【2021 年 7 月 — Delta 变体代表大多数新病例。
- 2021 年 7 月 21 日—健康通行证在法国推出,其应用范围将在 2021 年 8 月逐步扩大。
- 2021 年 9 月 13 日—超过 6 个月前注射过最后一次疫苗的人可以注射第三次疫苗。
2.按年龄组的全球分析
这些数据被分成了与 INSEE 发表的不同分析中相同的年龄组。这使我们能够比较不同年份不同年龄组的死亡总数。
作者图片
请记住,2021 年最后三周的数据缺失,在这最后三周,每日平均死亡人数在增加,如这里的所示。然而,我无法整合这些信息,因为没有提供年龄组的详细信息。
为了更详细,我们可以按年份和年龄组分析每日死亡率的分布。从下面的箱线图可以看出,对于 0-24 岁、25-49 岁和 50-64 岁年龄组,法国的平均每日死亡人数在过去 4 年中保持稳定(0-24 岁年龄组略有下降)。然而,对于 50-64 岁年龄组,一些高异常值是可见的,尽管平均值似乎与其他年份相似。
按年龄组划分的每日死亡率分布(图片由作者提供)
65-74 岁年龄组似乎受到疫情的严重影响,到 2020 年死亡率明显更高,平均水平在 2021 年保持高位。对完整时间序列的研究将提供更多的见解,但较高的比率可能是因为该年龄组在 covid19 感染方面的脆弱性以及他们获得疫苗接种的延迟(在法国疫苗接种已分批部署,优先考虑较大年龄组)。
按年龄组划分的每日死亡率的核密度图(图片由作者提供)
对于 75–84 和 85+组,2020 年两次 covid19 波的影响清晰可见(特别是在分布右侧的异常值中)。2021 年,这些群体的平均值仍然很高,但分布尾部的数字有所减少(红色曲线 2021,绿色曲线 2020)。
3.按年龄组划分的每日死亡率图
时间序列图完成了上一节中强调的观察,并有助于理解箱线图中看到的每日死亡率的一些极值。
对于 0-24 岁和 25-49 岁年龄组,死亡率在过去 4 年中非常相似,似乎不受 covid19 疫情的影响。
作者图片
作者图片
covid19 导致的额外死亡率在 50-65 岁年龄组开始显现,尤其是在 2020 年的第一波期间。2021 年,5 月份可见的额外死亡率似乎达到了与 2018 年季节性流感疫情类似的水平,但时间略长
作者图片
如前一节所述,65-74 岁年龄组并未受到每日死亡率大幅上升的影响,但较高的平均值在 2020 年和 2021 年持续了很长一段时间。与 2020 年相比,2021 年秋季的改善可能归因于该年龄组的整体高疫苗接种覆盖率。
作者图片
对于 75-85 岁和+85 岁的年龄组,2020 年前两次浪潮的影响显而易见。疫苗接种开始后,额外死亡率稳定在与 2019 年和 2018 年季节性流感流行期间相当的水平,但特殊性在于额外死亡率跨越了更长的时间。
疫苗接种为这些年龄组提供的保护在 2021 年秋季达到的正常日死亡率中清晰可见。
作者图片
作者图片
结论
我为自己做了这个分析,以理解当前的时代。法国目前正受到奥米克隆变异体传播的影响,因此这里提出的观察结果可能不会在很长一段时间内保持有效。
美国枪支背景调查分析
原文:https://towardsdatascience.com/an-analysis-of-firearms-background-checks-in-us-d2e4b2bfafe1?source=collection_archive---------20-----------------------
1999-2020 年枪支背景调查趋势分析
简介
近年来,美国发生了许多与大规模枪击和枪支暴力有关的悲剧事件。本文旨在了解 1999 年至 2020 年间枪支背景调查与政治和宏观经济趋势之间的一些潜在趋势和关系。为了实现这一目标,必须收集和汇编不同来源的数据。r 用于该数据集的统计分析。下面我会解释数据集的每个变量指的是什么。
总数:这一数字代表通过国家即时犯罪背景调查系统(NICS)启动的枪支背景调查总数。“它们并不代表售出的枪支数量。根据不同的州法律和购买情况,无法在枪支背景调查和枪支销售之间建立一一对应的关系。”虽然无法建立一一对应的关系,但这一统计数据可以很好地表明售出的枪支数量。
人口:给定年份每个州的人口。
每 1000 人的总数:每 1000 人中背景调查的总数。
总统选举:各州如何在总统选举中投票。成绩有效期四年。例如,亚利桑那州在 2016 年投票给共和党,在 2020 年投票给民主党。因此,从 2016 年到 2019 年,它将保持 R,从 2020 年到现在,它将变为 D。1 代表民主党,0 代表共和党。
在任总统:在任总统的政党。1 代表 D,0 代表 r。
大规模射击:数据汇编自斯坦福 MSA 数据库和 TVP 大规模射手数据库。应该注意的是,每个数据库对报告的大规模枪击事件使用不同的标准。对于 1999 年至 2016 年,使用斯坦福数据库,对于 2016 年至 2021 年,使用 TVP 数据库记录每次大规模拍摄的时间和状态。应当指出,大规模枪击受害者只占伤亡人数的一小部分。
MSpM:每 100 万人中的大规模枪击数量。
实际 GDP:基于 2012 年美元的各州年度 GDP。2021 年的数据是前两个季度的平均值。
人均 GDP:基于 2012 年美元的各州年人均 GDP。
城市:每个州的城市人口百分比。1999-2009 年使用 2000 年的数据,2010-2021 年使用 2010 年的数据。
尽管我已经尽最大努力从不同来源收集数据并在一个数据集中呈现它们,但是读者应该参考原始来源以获得关于每个参数的准确数据。
相关矩阵
我们可以做的第一件事是创建数据的相关矩阵,这是总结数据和查看模式的好工具。每个相关系数量化了一对变量之间的关联,并且是该对变量之间线性关系的度量。生成的值范围从-1 到 1,随着数字越来越接近这两个极限,相关性越来越强。
> dim(gun)[1] 13923 12> names(gun)[1] “ï..year” “month” “state” “totals” “Population” “Totals.per.1000”[7] “Pres.Election” “Sitting.President” “Mass.Shooting” “Real.GDP” “GDP.per.capita” “Urban”> attach(gun)> gun_Q=gun[,-3]> cor(gun_Q)
**表 1。**基于月度数据集的相关矩阵
从表 1 的相关矩阵中观察到:
“Month”与其他任何变量都没有很强的相关性,因此可以减小数据库的大小。相反,年度数据可以用于分析。
“总数”随着“年份”(0.279)的增加而增加,表明从 1999 年到 2021 年火器销售增加。“总数”随着“人口”的增加而增加,这意味着人口越多的州有越多的枪支交易,“总数”和实际 GDP 之间存在同样的相关性。这就是为什么通过包括人均 GDP 数据和“总量”来标准化基于人口的数据很重要。
“每 1000 人的总数”按“年”增加,表明从 1999 年到 2021 年枪支销售增加。“每千人总数”与“Pres”呈负相关。“选举”和“城市”。这意味着城市人口较多的州人均枪支销量较低。此外,支持民主党的州人均枪支销量也较低。然而,“Pres。“选举”和“城市”也密切相关(0.399),这意味着城市人口更多的州会投票给民主党。“每 1000 人的总数”与“人均国内生产总值”呈负相关,这意味着人均国内生产总值较高的州枪支销量较低。
我们还可以根据相关矩阵收集一些人口统计信息。例如,城市越多的州人口越多(0.405),选举民主党(0.399),人均 GDP 越高(0.435)。
**表二。**基于年度数据集的相关矩阵
在年度数据集上运行相关矩阵产生了与之前观察到的月度数据集相同的趋势。然而,对于年度数据集,只包括 1999 年至 2000 年的数据,还增加了每百万人的群体射击数据。唯一的主要区别似乎与“大规模射击”有关:
“大规模枪击事件”与“年份”、“总数”、“人口”和“实际 GDP”呈正相关。然而,其中一些参数是相互关联的(即共线的),如“人口”和“实际 GDP ”,这意味着人口越多的州实际 GDP 也越高。然而,可以肯定地说,从 1999 年到 2020 年,大规模枪击事件有所增加,并且在人口众多的州更加普遍。
“MSpM”与“年份”和“现任总统”的正相关性最高,表明随着时间的推移,大规模枪击事件变得更加普遍。与“现任总统”的正相关意味着当现任总统是民主党人时,大规模枪击事件更为普遍。然而,我们知道最近的总统是民主党人(即在任总统和年份之间有轻微的正相关)。
主成分分析
主成分分析(PCA)是一种有用的技术,可用于具有相关变量的大型数据集。PCA 本质上是一种降维技术,我们试图减少表示数据所需的变量数量,并用于探索性数据分析。基于上述相关矩阵,为了消除共线性,我们首先从数据集中删除'总数','人口','大规模射击'和'实际国内生产总值'。对于主成分分析,数据应该是定量的,因此“状态”也将从数据集中移除:
> names(gun_Q)[1] “ï..Year” “Totals.per.1000” “Pres.Election” “Sitting.President”[5] “MSpM” “GDP.per.capita” “Urban”>pr.out=prcomp(gun_Q,scale=TRUE)> pr.out$rotation
表 3 显示了所有 7 台电脑的电脑负载向量。本质上,每个 PC 都是原始变量的线性组合,系数如表 3 所示。
**表 3。**主成分载荷
以下命令将为每台 PC 计算并绘制解释的方差比例(PVE)。
> pr.var=pr.out$sdev²> pve=pr.var/sum(pr.var)> pve[1] 0.26944377 0.19945339 0.15671898 0.11911631 0.09628290 0.08377159 0.07521306> plot(pve , xlab=”Principal Component”, ylab=”Proportion of Variance Explained”, ylim=c(0,1) ,type=”b”)> plot(cumsum(pve), xlab=”Principal Component”, ylab =”Cumulative Proportion of Variance Explained”, ylim=c(0,1) , type=”b”)
图 1 显示了每种 PCs 的解释方差比例(PVE ),累积 PVE 如图 2 所示。例如,图 2 显示前两个 PC 的累积 PVE 约为 0.5,这意味着前两个 PC 可以解释数据集中 50%的方差。
**图一。**每个主成分的 PVE(图片由作者提供)
**图二。**累积 PVE 与主成分数(图片由作者提供)
> biplot(pr.out,scale = 0)
图 3 显示了前两个 PC 的数据集的 PC 分数和相应的 PC 加载向量。请注意,加载向量与表 3 中获得的相同。换句话说,图 3 是整个数据集在前两个 PCs 空间上的投影。
**图三。**年度枪械数据集的前两台电脑。箭头显示了前两个 PC 加载向量。每个数字代表前两个主成分的分数。(图片由作者提供)
从表 3 和图 3 中我们可以看出,PC1 的主要组件是“Pres”。“选举”、“城市”和“人均 GDP”,这意味着这三个参数相互关联,表明更多的城市州倾向于选举民主党人,人均 GDP 更高。PC2 的主要组成部分是“年份”、“MSpM”和“现任总统”,表明这三个参数相互关联,因为近年来大规模枪击事件更加普遍,民主党人被选为总统。
参数“Total per 1000”同时显示在 PC1 和 PC2 中,表明它与 PC1 和 PC2 中的参数相关。“每 1000 人总数”箭头的方向也很重要,它指向 PC2 的正值和 PC1 的负值。换句话说,“每 1000 人的总销售额”(即枪支销售额)逐年上升(箭头方向指向正的 PC2 值),并且在城市人口较少、选举共和党和人均 GDP 较低的州更为普遍(箭头方向指向负的 PC1 值)。
图 3 中还有一个需要注意的重要特性。从图 3 中我们可以看到,数据集分为两大组,分别在 PC2=0 以上和以下。这表明,不考虑 PC1(换句话说,在 D 和 R 状态中),我们看到从 1999 年到 2020 年的人均枪支销售和人均大规模射击有所增加。在此期间,人均国内生产总值也有所增长,但与人均枪支销售和人均大规模枪击相比,增长速度较慢,而且与 R 国相比,D 国的增长速度更快(因为箭头方向指向 PC1 的正值)。
我们可以根据 D/R 投票对图 3 上的数据集进行颜色编码,如下所示:
> attach(gun)> plot(pr.out$x[,1:2],col=Pres.Election+3)
**图 4。**年度枪械数据集的前两个 PC 分数。蓝色代表投票给民主党的数据点,绿色代表共和党。(图片由作者提供)
从图 4 中我们可以清楚地看到,D 州的 PC1 得分较高,它们的人均 GDP 较高,并且更加城市化。
图 3 和图 4 显示了 PCA 的强大功能,我们可以在一个图中总结所有数据集,并解释所有变量之间的趋势和相关性。
趋势
以下两个数字显示了多年来“每 1000 人的总数”和“人均国内生产总值”的趋势,并基于 D 和 r 的投票模式。
**图五。**历年“每 1000 人总数”的平均值(图片由作者提供)
**图六。**历年人均 GDP 平均值(图片由作者提供)
图 5 和图 6 的趋势证实了前几节中讨论的调查结果,即“每 1000 人的总数”(即枪支销售)逐年增加,R 州比 D 州高(几乎两倍)。人均国内生产总值逐年增加,但 D 国的人均国内生产总值高于 R 国,而且 D 国的人均国内生产总值比 R 国增长得更快。
结论
枪支背景调查数据与 1999 年至 2020 年各州的 GDP 和投票数据相结合。完成了相关矩阵和主成分分析来分析这些数据并确定趋势。研究发现,从 1999 年到 2020 年,R 和 D 两个州的人均枪支销量和大规模枪击事件都有所增加。与 D 州相比,r 州城市化程度较低,人均 GDP 较低,人均枪支销量较高。
来源
国家即时犯罪背景调查系统(NICS) —联邦调查局
git hub-BuzzFeed news/NIC-枪械-背景调查:来自联邦调查局全国即时犯罪背景调查系统的月度数据,从 PDF 转换为 CSV。
东亚银行:区域经济账户:下载“本网站发布的信息属于公共领域,未经特定许可,不得使用或复制”。
最全面的枪手数据库——暴力项目。服务条款见服务条款-暴力项目。
美国大规模枪击事件|斯坦福图书馆“斯坦福 MSA 是根据创作共用属性 4.0 国际许可发布的”。
git hub—stanforgeospatialcenter/MSA:美国大规模枪击事件数据库。由斯坦福地理空间中心维护
2019 年国家和州人口估计(census.gov)“美国人口普查局对引用我们网站上的信息没有具体的风格建议”。
各州城市人口百分比,历史|爱荷华州社区指标计划(iastate.edu)原始数据来自美国人口普查局。
统计学习导论(statlearning.com)
Faghihnejad/Gun:1999 年至 2021 年枪支背景调查(github.com)
用 Python 解析你的梦幻英超球队
原文:https://towardsdatascience.com/an-analysis-of-your-fantasy-premier-league-team-with-python-de4acf77e444?source=collection_archive---------18-----------------------
如何使用几行 Python 代码来可视化您的 FPL 团队的表现
作者图片
#动机
如果你关注足球,你一定在某个时候听说过梦幻足球游戏。很多足球联赛都有自己的,有自己特定的规则,英超也不例外。不仅如此,这个游戏在那个岛上非常受欢迎,全世界有超过 800 万人玩这个游戏。在这篇文章中,我们将看看梦幻英超的经理们如何使用 Python 来分析他们的球队。
虽然这个游戏很好地展示了你对你的团队的一些见解,但它可能比页面上的数字更生动。这就是 FPL API 和几行 Python 代码派上用场的地方,它们可以构建不同类型的可视化,显示任何经理团队和他们一周接一周的开发游戏的最重要方面。
#识别和获取相关数据
这里的想法是从小处着手,从基本要素开始(点数、等级、团队价值、转会、队长选择和每个位置的点数)。这已经带来了大量关于经理团队的见解。
为了获得这个项目所需的数据,我们将使用 FPL API。尽管没有围绕它们构建的文档,但由于使用 Google Chrome DevTools 对不同的 FPL 网页进行了简单的网络扫描,我们可以找到我们需要的 URL 端点。然后,对这些特定端点的请求使您能够访问 JSON 格式的数据,这在 Python 中处理起来非常实用。
Google Chrome“Inspect”工具的屏幕截图 URL 端点以黄色突出显示
以下是我们用来获取所需数据的 4 个端点:
https://fantasy.premierleague.com/api/bootstrap-static/
关于 PL 球队、球员和比赛周详情的一般信息
https://fantasy.premierleague.com/api/entry/*teamID*/event/*GW number/picks/* 关于给定的 FPL 队和给定的比赛周的详细信息
*https://fantasy.premierleague.com/api/entry/*团队 id/**/
给定 FPL 团队的一般信息
https://fantasy.premierleague.com/api/element-summary/*playerID*/
具体英超球员的详细信息
也就是说,这就是数据挖掘部分的样子:
在此基础上,让我们构建几个函数来获取英超球员的具体数据:
有了这个,我们就可以开始了!
#组织数据
既然我们已经从 FPL API 获得了所有的原始数据,游戏的名称就是只保留我们需要的东西,整理东西,并把所有东西组织在列表和字典中。这将使在我们的仪表板上绘制数据变得更加简单。
在初始化了我们想要建立的所有列表和字典之后,我们循环通过所有的游戏周来获取我们需要的数据并填充我们刚刚定义的对象。我们使用 append 方法向列表中添加元素,而对于字典,我们直接添加(键,值)对。
#创建图表
好了,现在让我们来建造这个东西。将所有数据正确地排列在列表和字典中,我们真正需要的就是 matplotlib!
1.游戏周分数以及与最高和平均分数的比较
让我们从基础开始。一个队每周得到的分数以及与比赛周最高和平均分数的比较是要建立的第一个图表。我从未接近过比赛周的最高分数,但与平均分数相比还是很有趣的。
作者图片
2.每个比赛周的排名变化
其次,我们来看看每个比赛周的队伍排名,以及整体排名的演变。有了这张图表,你可以监测你的球队一周接一周的比赛表现和整体趋势。
作者图片
3.每个比赛周团队价值的演变
如果你不想在赛季结束时落后,FPL 的“金融”部分是至关重要的。关注你的财务状况是很重要的,这张图表就是这么做的。
作者图片
4.转让次数和相关费用
现在让我们来看看到目前为止,这位经理在这个赛季中有多活跃。该图显示了所进行的转移及其潜在的相关成本。
作者图片
5.船长付款
在 FPL,队长的选择非常重要,它可以完全改变一支球队在特定比赛周的表现。下一张图将向你展示你的队长在哪些地方表现不佳,哪些地方表现过度。
作者图片
6.每个位置的点数
我们仪表盘上的最后一张图显示了您每个职位获得的积分。多亏了这张图表,你将清楚地了解到哪些球员给你带来了最多的分数,以及你在整个赛季中遵循了哪些策略。这可能是一个好主意,比较它与游戏中的顶级玩家,看看你可以做什么不同!
作者图片
#结论
以我的团队为例,在 10 个游戏周之后,仪表板最终看起来是这样的:
作者图片
我们在这个项目中制作的图表集是分析 FPL 团队的良好开端。然而,不言而喻,通过我们设法获得的所有数据,可以得出更多的 FPL 洞见。在这里,我把重点放在观想最重要的事情上,可能会有更多的事情发生!
如果你想分析你的团队,完整的代码可以在这里找到:
【https://github.com/Guigs11/fpl_team_analysis】T2
Arvato 解决方案客户细分和预测
原文:https://towardsdatascience.com/an-analysis-on-arvato-customers-e3d56a366c78?source=collection_archive---------31-----------------------
照片由约书亚·索蒂诺通过 Unsplash 拍摄
介绍
客户细分是营销行业中最重要的过程之一,它允许公司将精力集中在具有相似特征的特定客户子集上。这使得公司能够有效地、适当地向各种受众群体营销群体。据 Shopify 称,客户细分有助于公司:
- 创建有针对性的沟通方法,与特定的客户群体产生共鸣,但不与其他人产生共鸣。
- 确定改进产品、新产品或服务机会的方法。
- 专注于最赚钱的客户。
一个顶点项目关注德国人口统计数据的这一过程。具体来说,它需要分析德国普通人口的人口统计数据以及一家邮购公司的客户数据。该分析的目标是使用包括 K-Means 聚类在内的无监督学习方法来确定邮购公司的客户与一般人群相比如何。
在对客户进行细分并解释分组后,下一步是使用单独的训练数据集来实施和调整一些监督学习算法,以预测个人成为公司客户的概率。
找到最佳预测模型后,最后一步是在测试数据集上使用它来预测客户对活动做出反应的概率。这些预测的概率将被上传到 Kaggle 比赛中,该比赛将测量这些预测与其他参赛作品相比的准确性。
这个项目是 Udacity 数据科学纳米学位顶点的多个选项之一。因此,贝塔斯曼的这个项目成为我的首选,因为几个月前我已经在机器学习纳米学位项目的另一个版本上工作过。那个版本只包含第一步——从清理数据到对客户进行聚类。现在,这是一个超越这一步的机会,同时进一步应用数据挖掘和机器学习的新技能。
数据
这三个步骤中的每一步都包含具有相同特征的不同数据集。人口统计数据集包含大约 366 个特征,每个特征描述成千上万人的个性和行为。每一行代表一个人以及该人以外的信息,即家庭、建筑和邻居数据。
德国人口统计数据和邮购公司的客户数据将用于该分析的无监督学习部分。前者包含总共 366 个特征和 891211 个样本,而后者包含 369 个特征和 191652 个样本。两者在功能上的区别是 CUSTOMER_GROUP、ONLINE_PURCHASE 和 PRODUCT_GROUP,它们属于客户数据,提供了更多的客户信息。
邮寄出的训练和测试数据集包含与人口统计数据相同的所有特征。虽然两者都有近 43000 个样本,但这些数据代表了作为营销活动目标的个人。训练数据中的结果变量被命名为 RESPONSE,它指示客户是否响应了成为公司客户的活动。测试数据集包含除响应特征之外的所有特征。这将用于在本项目的最后部分使用最佳模型进行最终预测。
第 1 部分—数据预处理
像每一个数据科学问题一样,这个项目在分析数据和进行预测之前涉及到数据预处理和清理。由于四个数据集具有相同的结构,数据清理将被处理到 ETL 管道中,该管道执行缺失值的修改,确定要删除哪些特征和行,如何处理分类/混合特征,以及生成虚拟变量。
缺少值
由于人口统计数据的规模很大,我上传了前 100,000 个样本,以便更快地执行初始清理。原始数据包含几个缺失值的特征,这些缺失值用 NaN 以外的许多不同值编码,即-1,0,X,XX。幸运的是,一个单独的 Excel 文件包含每个特性的值及其描述的索引。与含义“未知”相关联的值是缺失值,因此被收集到字典中。在将所有原始的“未知”编码替换为“NaN”之后,我继续确定哪些特性可以被排除。
图 1 —按特征分类的缺失值百分比直方图(按作者分类的图片)
从**图 1,**一个特征的缺失值的最佳阈值是 40%,因为任何高于这个阈值的值在特征数量中出现的频率都非常低。结果,九个特征被丢弃,包括阿格 _ TYP-最佳阿格类型学,KBA05 _ 鲍马克斯-单元内的普通建筑,以及蒂特尔 _ KZ-此人是否有学术头衔。
图 2—按行划分的缺失值百分比直方图(按作者划分的图像)
在删除了大部分缺失的列之后,下一步是对行进行类似的处理。从**图 2 中可以看出,**行缺失值在 50%之后变得不那么频繁,任何缺失值在 70%左右的行对分析都没有好处。因此,丢失超过 50%的任何行都将被丢弃。
分类变量
检查要素的数据类型时,其中一些数据类型具有多个值。例如,CAMEO_DEU_2015 和 CAMEO_INTL_2015 将被拆分为两个要素-财富和人生阶段。CAMEO_DEUG_2015 已转换为数字变量,因为其值只有一种含义。
基于 PRAEGENDE _ JUGENDJAHRE 创建了两个特征。这一原创功能结合了三个维度的信息——十年、运动和国家。根据 Excel 文件中关于此功能的信息,这些值被转换为十进制和主流。KZ 西部的特征已经代表了这个国家。
在去掉一些无用的分类变量后,剩下的变量被转换成虚拟变量。这是数据清理过程的最后一步。
在执行各自的分析之前,上述所有步骤将用于所有四个数据集。
第 2 部分—客户细分
通过数据清理管道,德国人口统计数据和客户数据集均可用于客户细分分析。客户细分包括缺失值的数据插补、数据标准化、主成分分析降维以及用于细分的 K 均值聚类。
一旦在人口统计数据和客户数据集中生成了聚类,就会对这些聚类进行比较,以确定哪些聚类代表了邮购公司的目标受众,即那些比其人口对应部分获得更高客户比例的聚类。这些聚类将根据最高主成分中的主导特征进行解释,给出营销活动目标人群类型的详细信息。
主成分分析
干净数据预处理的第一步是为分割分析找到最佳数量的组件和聚类。对于前者,我创建了一个函数,根据解释的方差阈值的百分比,返回某个主成分的最高主成分权重的特征的条形图。对于人口统计数据,图 3 表明,约 154 个主成分解释了 85%的数据变化。
图 3——解释 85%数据变化的主成分数量。
图 4-主成分 1 中权重最高和最低的 10 个特征(作者图片)
从**图 4,**第一主成分中权重最大的特征包括流动模式、单/双户数量、社会地位和汽车份额。具体来说,这些特征与该成分正相关。另一方面,最小的要素权重包括 6 至 10 个家庭住宅的共享、每 6 至 10 个家庭住宅的汽车拥有量、财富/生命阶段和家庭净收入。这意味着第一主成分与大家庭负相关。
图 5—主成分 2 中权重最高和最低的 10 个特征(图片由作者提供)
从图 5 来看,第二个主成分中最大的特征意味着它与在线亲和力、交易活动频率、省钱金融拓扑、年龄组正相关。相反,这一部分与财务准备和最近的财务交易现状负相关。
k 均值聚类
对于人口统计中成千上万的个体,最好估计高于 5 的聚类数。为了测试要使用多少个分类,肘形方法图显示了当 K-means 分类分数降低,分类数增加时,一条线显示出肘形的方向变化。对于像人口统计数据这样大的数据集,循环迭代聚类数并收集分数的快速方法是使用小批量 K-Means 方法。使用常规的 K-means 将增加计算时间来拟合并在循环中产生分数,特别是对于较大的聚类。另一方面,小批量方法减少了 K-mean 算法的时间和空间开销。具体来说,它使用固定大小的小批量随机数据。该方法的评分如图 6所示。
图 6 —从小批量 K 均值得出的人口统计数据的肘形图。k 的最佳值被确定为 k = 8。(图片由作者提供)
在拟合了 25 个聚类之后,8 个和 21 个聚类之间似乎有些曲折。因为大型数据集最好用较高数量的聚类来说明,所以图中的最佳弯头似乎集中在 k =8 个聚类处。
为了将人口统计数据与客户数据进行比较,从对聚类的插补来看,后者将具有与前者相同的 sklearn 对象。具体来说,客户将被扩展到 154 个主要成分,并细分为 8 个集群。两个数据集的聚类分布如图 7所示。
图 7——德国人口和邮购公司客户的人群比例(图片由作者提供)
从上面的两个图来看,集群 7 在德国人口中最具代表性,约占 16%,而集群 8 在公司客户中最具代表性,约占 20%。相反,聚类 6 在人口统计中最少被代表约 8%,而聚类 5 在客户中最少被代表约 7.5%。有趣的是,集群 6 是最具代表性的客户之一。此外,分类 7 是人口统计中最具代表性的分类之一,也是客户中最不具代表性的分类之一。
聚类解释
图 8 —聚类比例比较,其中目标受众为正差异,非目标受众为负差异(按作者分类)
为了确定哪些分类代表邮购公司的目标受众,将从其各自的客户分类比例中减去人口分类比例。此外,目标受众群是那些客户比例大于人口比例的群体。另一方面,非目标受众群体是那些客户比例低于人口比例的群体。根据**图 8,**邮购公司的目标受众在集群 8 和集群 6 中。聚类 8 具有最高的正容限,而聚类 7 具有最大的负容限。
表 1——按年间隔定义的 ALTERSKATEGORIE_FEIN 值(图片由作者提供)
这里要理解的一个重要变量是年龄组。该项目的任何附件中都没有解释 altersketaorie _ FEIN(年龄类别,精细比例)特征。然而,一个变量 GEBURTSJAHR——出生年份——与该变量直接相关。创建一个关联这两个特征的字典有助于理解 ALTERSKATEORIE_FEIN 特征的含义。表 1 列出了与每个年龄类别变量相关的 5 年间隔。
图 9-按聚类划分的年龄类别比例热图(图片由作者提供)
图 9 中的热图显示了将要分析的聚类中年龄类别的比例。在这两个目标受众群体中,1930 年至 1949 年出生的人在年龄组中所占比例最高。对于群组 3 中的非目标受众,按年龄组划分的最高比例在两个目标群体中几乎相同。另一方面,第 7 组中 1945 年至 1969 年间出生的人比例较高。由于在这种情况下理解诸如年龄组这样的重要变量是重要的,所以目标观众群的质心将带来对彼此之间的相似性和差异的更广泛的洞察。
聚类分析和解释包括计算所有特征的 8 个聚类质心,并将它们逆变换到原始特征尺度。然而,由于有超过 300 个特征,聚类解释仅限于 10 个具有最高正主成分权重的特征,如图图 4 和 5 所示。
目标受众
图 9 —前两个主成分的最高特征的目标受众聚类质心(作者图片)
乍一看,除了聚类 7 之外,第一主成分特征的质心值在所有观众聚类中都是相似的。另一方面,对于第二主成分,该群的大多数质心与所有其他目标观众群相似。
表 2 —聚类 6 值及其含义(图片由作者提供)
在集群 6 中,客户倾向于 20 世纪 40 年代出生的新房主。他们居住在大型社区的单/双家庭住宅中,在社会中的流动性很小。由于储蓄和投资的规模很大,他们必须有很高的退休金。虽然这一群体由普通收入者组成,但他们在过去两年中很少或没有金融交易活动。此外,他们拥有较高的汽车份额和适中的在线亲密度。
表 3—聚类 8 值及其含义(图片由作者提供)
与集群 6 类似,集群 8 中的受众通常出生于 20 世纪 40 年代初,生活在大型社区的单/双家庭住宅中,在社会中的流动性较小。由于储蓄的规模很大,他们必须有很高的退休金。虽然这一群体由普通收入者组成,但他们在过去两年中很少或没有金融交易活动,在线亲密度适中。然而,与集群 6 不同,这些客户是更有经验的业主,并且具有更高的投资活动。
非目标受众
表 4-聚类 3 质心值及其含义(图片由作者提供)
与目标受众类似,第 3 类客户是 20 世纪 40 年代初出生的房主,他们居住在大型社区,在社会中流动性很小。由于储蓄规模非常大,他们必须有很高的退休金。虽然这一群体由普通收入者组成,但他们在过去两年中很少或没有金融交易活动。然而,一些关键的区别是,这一群体的客户平均拥有单/双家庭住房份额,汽车拥有率低,至少有几个交易活动,以及更高的在线亲和力。
表 5—聚类 7 质心值及其含义(图片由作者提供)
乍一看,分类 7 显示的值与其他分类不同。与目标群体一样,这一群体包括居住在大型社区的单/双家庭住房中的房主。由于储蓄规模非常大,他们必须有很高的退休金。然而,这些客户更年轻,并且在过去两年中增加了金融交易活动。而且,他们的线上亲和力很高。
非监督分析的结论是,营销活动的目标受众是 1935 年至 1949 年间出生的人,他们在投资和存钱方面具有较高的财务拓扑结构。他们也是很少或没有整体或邮购交易活动的人,即使他们有适度的网上关系。
第 3 部分—监督学习
在对德国人口统计和客户数据集执行聚类分析以确定哪些客户更有可能是邮购公司的客户之后,下一步是将监督学习应用于单独的数据文件。这个数据集与前两个相似,但是每个人都是邮寄活动的目标。此外,它还包括一个响应变量,表示个人在活动结束后是否成为了邮购公司的客户。也就是说,这些数据用作训练集,将用于为单独的测试数据集建立最佳预测算法,该数据集将用于 Kaggle 比赛。
图 10 —培训数据中的客户响应频率(图片由作者提供)
由于训练数据集几乎有 43,000 个样本,图 10 显示响应变量明显不平衡。换句话说,大约 1.24%的目标个人成为了公司的客户。由于这是预测模型将使用的目标变量,因此在测试数据中对个人是否会成为客户进行分类将是一个挑战。一种补救方法是在训练预测模型之前,除了数据预处理和训练/测试拆分之外,还实施采样方法。
数据预处理
一旦将 300 个预测因子和反应变量彼此分开,基于 0.1 的验证比率和 0.2 的测试比率,将邮寄出的训练数据分成训练、验证和测试集。这三个分割用于在对整个邮寄数据使用最佳模型之前评估候选模型。
分割后,训练集、验证集和测试集分别通过插补、标准化和 PCA 缩减为 154 个组件进行转换。对于这种分析,这些经过处理的数据集将用于评估三种预测算法:逻辑回归、AdaBoost 和梯度增强分类器。该过程包括使用 ROC 分数而不是 f1 分数对模型执行交叉验证,但不是在对训练数据实施额外修改之前。
重采样— ADASYN
在对明显不平衡的数据实施模型之前,重采样方法对于精确的模型至关重要。少数反应——反应= 1——非常罕见,以至于任意模型对结果几乎一无所知,从而导致弱模型。为了使积极的反应更重要,模型需要更好地了解它,这就是过采样的用武之地。
两种可能的重采样方法是欠采样和过采样。欠采样包括平衡数据,使得多数类(响应= 0)的观测值随机减少到与少数类相同的大小。然而,对于该数据以及在一些应用中,一个主要的缺点是多数类观察的显著遗漏导致重要信息的丢失,而这些信息对于模型的学习过程可能是至关重要的。另一方面,过采样通常将少数类样本复制到与多数类相同的大小,而不是省略多数类的样本。然而,由于少数样本 的高重复率,这种策略很可能会使数据过拟合。
要在两种重采样策略之间做出选择,过采样更好,因为这样会保留更多信息,而不是丢弃 https://zyxo.wordpress.com/2008/12/30/oversampling-or-undersampling/ 。即便如此,imblearn 包提供了一些增强的过采样方法,减少了一般过采样的缺点。
图 11—ADASYN 少数民族样本的 KNN 世代(图片由 imblearn 提供)
一种很好的技术是 ADASYN——自适应合成采样方法。这种重采样技术旨在通过生成少数类样本的合成版本来对其进行过采样。考虑一个样本 x_i,它变成一个新的样本 x_new。这个新样本是通过原始样本的 k 个最近邻生成的。从所有可能的邻居中选择 x_zi,新的观测值计算如下:
其中λ是 0 和 1 之间的随机数。这个新样本一般位于 x_i 和 x_z 和之间的线上。图 11 说明了这一过程。此外,ADASYN 使用密度分布作为标准来决定少数样本的合成样本数。这是通过自适应地改变不同少数样本的权重,同时考虑任何偏斜分布 ⁴ 来实现的。
ADASYN 重采样适合分割的训练数据,从而产生总共超过 61044 个样本,而不是 30000 个样本。
逻辑回归
图 12 —验证和测试集的逻辑回归分类报告(图片由作者提供)
根据对重新采样的训练数据的默认逻辑回归模型,验证和测试分数彼此相似。对于肯定回答,召回分数是 0.43,精确分数是 0.2。这意味着 43%的实际客户被正确分类为 2%的被预测为客户的个人实际上是客户。验证 ROC 得分为 0.53。
对于测试数据,55%的实际客户被正确预测,2%的预测客户被正确分类。ROC 评分为 0.59,高于验证集。
AdaBoost 分类器
图 13—验证和测试集的 AdaBoost 分类报告(图片由作者提供
根据重采样训练数据的默认 AdaBoost 模型,验证和测试分数彼此相似。对于肯定回答,召回分数是 0.26,精确分数是 0.2。这意味着 26%的实际客户被正确预测,2%被预测为客户的个人实际上是客户。验证 ROC 得分为 0.54。
对于测试数据,26%的实际客户被正确预测,2%的预测客户被正确分类。ROC 评分为 0.54,与验证集大致相同,但略高。
极端梯度提升分类器
图 14——验证和测试集的极端梯度提升分类报告(图片由作者提供)
根据对重新采样的训练数据的默认极端梯度提升模型,验证和测试分数彼此相似。对于肯定回答,召回分数是 0.07,精确分数是 0.1。这意味着实际上是客户的个人中有 7%被正确预测,而被预测为客户的个人中有 1%实际上是客户。验证 ROC 得分为 0.47,小于其他两个模型。
在测试数据中,10%的实际客户预测正确,1%的预测客户正确。ROC 评分为 0.49,高于验证集。
型号选择
根据上述一般模型的初步信息,如果可以选择一个模型,那么向前发展的最佳模型将是逻辑回归模型。因为通过验证和测试,所有三个模型的精确度分数是相同的,所以另一个要考虑的度量是召回和 ROC 分数。关注正面回答,即使它是少数类,逻辑回归在测试和验证集中也具有最高的回忆和 ROC 分数。
然而,对于这种分析,监督模型的目标不是挑选哪个模型通常预测得最好。虽然极端梯度增强可以给出比逻辑回归更高的 ROC 分数,但它被证明是最低的,并且显著低于逻辑回归的 ROC 分数。那么,这是否意味着在真实的测试集上,逻辑回归会比极端梯度推进给出更高的 ROC 分数?为了找出答案,需要对列出的三个模型进行交叉验证和优化,以确定对邮寄测试数据的应用是否会给逻辑回归比其他两个整体模型更高的分数。
交叉验证模型调整
逻辑回归
一旦启动通用逻辑回归模型,它将通过网格搜索交叉验证方法来应用,以找到整个训练数据的最佳参数。通用模型是在包含三种数据转换的流水线中定义的,除了模型之外,还有 ADASYN 过采样。此管线模型的参数集由三个独立的实例组成。
lr_parameters = [
{'model__penalty':['l1'],
'model__C': np.arange(0.1, 1.1, 0.1),
'model__max_iter':[300, 500, 800, 1300],
'model__solver':['saga']
},
{'model__penalty':['l2'],
'model__C': np.arange(0.1, 1.1, 0.1),
'model__max_iter':[100, 200, 300, 500, 800],
'model__solver':['newton-cg','lbfgs']
},
{'model__penalty':['l2'],
'model__C': np.arange(0.1, 1.1, 0.1),
'model__max_iter':[300, 500, 800, 1300],
'model__solver':['sag']
}
]
逻辑回归接受四种不同的惩罚,但在这种情况下,将使用两种惩罚— l2(默认)和 l1。参数字典结构由一个 l1 集合和两个略有不同的 l2 集合组成。每一个都包含范围从 0.1 到 1.1 乘 0.1 的 C 系数、范围从 100 到 1300 的最大迭代次数(取决于惩罚)以及不同的解算器。第一个实例对应于 l1 ,它只接受‘saga’或‘liblinear’解算器。由于该模型将应用于大型数据集,因此将只使用“saga”。第二个实例是对于 l2 用‘牛顿-CG’和‘lbfgs’。第三个实例是带有解算器“sag”的 l2 ,它处理最大迭代次数至少为 300 的大型数据集。网格搜索完成后,系数为 0.8 的逻辑回归、1300 次最大迭代和“sag”求解器得出 ROC 得分为 0.63。
LogisticRegression(C=0.8, max_iter=1300, solver='sag')
结果,该算法在邮寄测试集上的预测导致 37.6%的个人被预测为客户。最终提交的分数为 0.609。
AdaBoost 分类器
与逻辑回归相反,AdaBoost 参数搜索将通过随机搜索进行。虽然有两个参数需要搜索,但几次拟合需要很长时间。学习率值从 0.1 到 0.8 按斐波纳契数列组织,包括默认值 1。估计数的组织方式相同,从 100 到 300,加上值 50。
ab_parameters = {'model__learning_rate': [0.1, 0.2, 0.3, 0.5, 0.8, 1],
'model__n_estimators': [50, 100, 200, 300]
}
AdaBoost 分类器上的随机搜索包括 12 次迭代,其中得分最高的模型具有 0.2 的学习率和 200 个估计量。
AdaBoostClassifier(learning_rate=0.2, n_estimators=200,
random_state=0)
该算法对邮件发送测试集的预测导致 22%的个人被预测为客户。最终提交的分数为 0.579。
极端梯度推进分类器
该模型的参数搜索不同于其他两个模型。因为极端梯度平滑在参数和功效上都比 AdaBoost 更复杂。管道的定义方式与其他两个模型相同。在这个算法的 27 个不同参数中,我选择了 5 个最重要的参数——最大深度、alpha、子样本、树的数量和学习速率。
xgb_parameters = {
'model__max_depth': np.arange(3, 13, 1),
'model__alpha': np.arange(0.1, 0.8, 0.05),
'model__subsample': [None, 0.1, 0.25, 0.5, 0.75, 1],
'model__n_estimators': np.arange(10, 200, 10),
'model__learning_rate': np.linspace(0.01, 0.8, 10)
}
定义参数后,将通过随机搜索而不是网格搜索来执行交叉验证。这里定义的 XGBoost 参数将花费大量的时间和计算工作。因此,通过一定次数的迭代,有限但随机的搜索将改善这两个问题。对于这种随机搜索,设置了 45 次迭代以增加捕获最佳模型的机会,因为在网格搜索中会有数百种组合可以持续几天。最后,除了搜索中没有的默认参数之外,最佳 XGBoost 分类器还有以下参数。
XGBClassifier(**alpha=0.7**, base_score=0.5, booster=None, colsample_bylevel=1,
colsample_bynode=1, colsample_bytree=1,
gamma=0, gpu_id=-1, importance_type='gain',
interaction_constraints=None,
**learning_rate=0.09777777777777778**,
max_delta_step=0, **max_depth=3**,
min_child_weight=1, missing=nan,
monotone_constraints=None, **n_estimators=90**,
n_jobs=0, num_parallel_tree=1, ***random_state=0***,
reg_alpha=0.699999988, reg_lambda=1,
scale_pos_weight=1, subsample=1,
tree_method=None, validate_parameters=False,
verbosity=None)
该算法对邮件发送测试集的预测导致 20%的个人被预测为客户。最终提交的分数为 0.587。
在这三个模型中,在 Kaggle 竞赛中获得最高分的模型是逻辑回归模型。就像基本分类报告一样。
表 6 —最终预测结果
结论
这个顶点项目的目标包括在 Arvato Financial Solutions 的类似数据集中进行非监督和监督学习。无监督分析需要主成分分析和 K-均值聚类来描述哪些人最有可能成为邮购公司的客户。监督分析侧重于对训练集进行缩放和过采样,以便预测模型可以准确预测活动的目标个人是否会成为公司的客户。该过程包括初始化和优化三个不同的模型,以确认哪一个在应用缩放和重采样后最准确。
未来的工作
如果通过添加更多参数或增加迭代次数来进一步调整极限梯度提升算法,则可以改进监督结果。与其他通用模型相比,通用 XGBoosting 验证和测试结果的 ROC 得分提高了近 10%。训练数据不平衡的方式可能意味着测试数据中的客户百分比也很低。也就是说,更一致的随机搜索或替代参数搜索可能会导致 XGBoost 模型超过逻辑回归得分,考虑到两个最终得分如何相互接近,并且它具有最低的客户预测百分比。
看我的 GitHub 库这里。
一个绝对的快乐:简化
原文:https://towardsdatascience.com/an-app-solute-delight-streamlit-f9f1e7d55a85?source=collection_archive---------41-----------------------
探索帮助构建数据应用程序的超酷工具
艾萨克·史密斯在 Unsplash 上拍摄的照片
一个用户友好的工具,通过在几分钟内将数据脚本转换为可共享的应用程序,帮助轻松部署任何机器学习模型和任何 Python 项目?是的,这是真的。就在这里!
Streamlit 入门视频
开始使用 Streamlit |构建您的第一个数据/ML 应用程序,作者 Anuj Syal
解码流水线
Streamlit 由 Adrien Treuille、Thiago Teixeira 和 Amanda Kelly 创建,是一个开源的 Python 库,使您能够毫不费力地为机器学习和数据科学构建漂亮的定制 web 应用程序,而不用担心前端,而且是免费的。该工具是在考虑数据科学家和 ML 工程师的情况下精心开发的,允许他们创建一个交互式环境,从而更容易地共享他们的模型并将其展示给他们的同事和客户。这些值可以根据提供的输入进行更改,所有更改和结果都以交互方式实时发生,这都归功于它的热重装功能。Streamlit 主要使用 Markdown 和 Python,但也支持 HTML 和 CSS。Streamlit 免费且易于安装,以网络应用程序的形式将您的想法在互联网上变为现实。
是什么让 Streamlit 脱颖而出?
该工具背后的主要思想是让数据应用程序的创建像编写 Python 脚本一样简单。这正是创造者们努力实现的目标。
- 它是交互式的,尤其是对你的客户来说,非常美观
- 如果你知道如何编写 Python 脚本,你就可以创建很酷的应用程序了
- 从您的 GitHub 库进行即时部署
如何简化?
人们只需要输入:
pip install streamlit
在您的终端/命令提示符下,它已经可以使用了(前提是您首先安装了 pip)。成功安装 Streamlit 后,运行下面给出的 python 代码,如果没有出现错误,则自动表示 Streamlit 安装成功。打开命令提示符或 Anaconda shell 并键入:
streamlit run filename.py
注意: 为了避免与其他应用程序的任何版本兼容性问题,请在单独/独立的虚拟环境中安装 Streamlit。
Max DuzijT5Unsplash
虽然称这个工具相当简单和方便是一回事,但对它进行测试又是另一回事。让我们开发一个简单的 web 应用程序来读取和可视化熊猫数据框。
测试 Streamlit 的时间到了:我的演示 Web 应用
步骤 1:导入 Python 库添加应用程序的标题+主体
import streamlit as st
import pandas as pd
import numpy as np
st.title(‘App by Anuj’)
st.write('This app walkthroughs on creating your first data app with streamlit. It demonstrates how easy it is now for data scientists to develop and deploy quick prototypes.')
步骤 2:将数据读入数据帧
df = pd.read_csv('game_of_thrones_battles.csv')
第三步:加入互动元素
#Use sidebar
option = st.sidebar.selectbox(
'Which number do you like best?',
df['first column'])
'You selected:', option
第四步:创建你的第一张图表
chart_data = pd.DataFrame(
np.random.randn(20, 3),
columns=['a', 'b', 'c'])
st.line_chart(chart_data)
步骤 5:创建一个带有地块的地图
map_data = pd.DataFrame(
np.random.randn(1000, 2) / [50, 50] + [37.76, -122.4],
columns=['lat', 'lon'])
st.map(map_data)
步骤 6:添加进度条
# Add a placeholder
latest_iteration = st.empty()
bar = st.progress(0)
for i in range(100):
# Update the progress bar with each iteration.
latest_iteration.text(f'Iteration {i+1}')
bar.progress(i + 1)
time.sleep(0.1)
步骤 7:保存并运行
现在我们已经完成了一个简单的脚本,是时候保存它了。我将把它保存为从终端运行的 myapp_ streamlit.py (确保安装了 pip 需求)
streamlit run myapp_streamlit.py
(命令 streamlit run 后跟您的 Python 脚本名称)
现在你知道了!您的第一个演示 web 应用程序。随意探索其他命令,添加边栏、进度条、列和其他迭代,特别是当你有太多东西要在 UI 上显示,但想要一个更整洁的外观时。
Streamlit 的缓存功能是其主要亮点之一。缓存的能力使它相对更快,尤其是当你做一些小的调整,然后试图重新运行。
注意:我建议我的数据科学家同事将代码和应用程序的浏览器窗口并排打开,以便高效、快速地获得结果,因为可以实时看到变化。
关注 streamlit 的竞争对手
虽然 Streamlit 完全在 Python 中工作,但 R 和 Plotly Dash 是另一个支持 Python 和 Julia 的流行选择。特别是对于 R 用户来说,R shiny 是快速开发 web 应用的一个很好的选择。
我的想法:Streamlit 真的亮了吗?
Streamlit 是数据科学家的福音。关于它没有两种方法。它不仅可以帮助他们构建 ML web 应用程序,还可以方便地向利益相关者、客户和同事共享和展示他们的模型,特别是如果他们是非技术人员和/或不熟悉程序或脚本的话。今天,它已经成为 ML 工程师事实上的选择,使他们能够快速构建和共享概念证明,同时给他们一个快速调整的选项。Streamlit 美观且用户友好,熟悉 Python 脚本的任何人都可以轻松学会。Streamlit 具有丰富的特性,它使用户能够轻松地部署模型,这是值得称赞的。很简单。而且是杰出的!
有兴趣看代码的话,看看这个 github rep 链接
在 Linkedin 和 Twitter 上关注我
如果你对类似的内容感兴趣,点击 Medium 上的关注按钮,或者在 Twitter 和 Linkedin 上关注我
原载于https://anujsyal.com。
用 Streamlit 优化熊猫数据框架的应用程序
原文:https://towardsdatascience.com/an-app-to-optimize-a-pandas-dataframe-with-streamlit-759a270a6d0e?source=collection_archive---------28-----------------------
理解大数据
使用此代码和应用程序,熊猫数据帧内存减少 50%或更多。
照片由尤利娅·马特维延科在 Unsplash 拍摄
我构建了一个简单的应用程序,它接受一个 csv 文件并返回一个内存优化的 pickle 文件以用作 Pandas data frame——这个故事分享了我使用 Streamlit 构建的经验,描述了要解决的问题,并推广了该应用程序的原型。
如果您正在处理大型 CSV 文件、Pandas 数据帧和 Python,那么这篇文章可能适合您。
【2021 年 4 月 7 日编辑:自从撰写本文以来,我已经创建并部署了一个名为 pd-helper 的 Python 包,它运行本文中讨论的代码的优化版本。可以搜索“pd-helper”或者pip install pd-helper
。更多信息,请参见 PyPi 。
问题是
在进入数据项目的核心之前,我经常花大部分时间清理、争论和管理数据。然而,随着我的数据集变得越来越大,我发现自己更加关注内存优化。换句话说,当使用 Pandas 时,我们需要使数据帧消耗尽可能少的内存。
如果您有一个 csv 文件,并且想要一个没有任何开销的优化的 Pandas 数据框架,该怎么办?
现有解决方案
有很多关于如何为解决方案编码的文章和要点,我自己也写了一些。然而,尽管文章很多,但有时代码太多,实现令人不知所措。那么,如果您有一个 csv 文件,并且想要一个没有任何开销的优化的 Pandas 数据帧,该怎么办呢?
代码
我在许多其他博客和资源的帮助下开源了这个应用程序;但是,app 的编排和实现是我的原创作品。对其他作品的引用与代码一起提供;然而,有两个关键资源本身值得一提。
首先,我改编了这个 GitHub gist 的一个函数,以编程方式降低数据的数值精度,即从 float64 到 float32。我的改进包括将数据类型转换为布尔型、字符串型、日期型和/或分类型。该函数的目的是在可能或合理的情况下,将所有列更改为除 object 之外的 dtype。目标是减少 50%或更多的内存使用。
第二,我利用 Streamlit 博客来了解如何启用一个腌数据帧的数据下载。与 CSV 文件不同,pickled 文件(除了 HDF5 之外)非常重要,因为它们如上所述保持数据转换。
如何用代码自己实现这一点。以下要点提供了一个名为 reduce_precision() 的函数,该函数消耗一个数据帧并返回一个内存减少的数据帧。您应该能够将它复制并粘贴到您的代码中,让它发挥一些内存魔力。
使用此功能可减少 50%或更多的内存。
该应用程序
最近发生了两件事。首先,我想获得构建一个有很多用户交互的应用程序的经验,比如数据上传、数据操作和数据下载。其次,我想做一些有用的东西——至少,创建一个我会经常使用的应用程序。因此,当我发现自己在为另一个项目编写优化代码时,我认为制作这个关于数据优化的应用程序可能值得一试。
app 链接:【编辑——由于 App 限制(每个用户限三个),我已经在 streamlit 上更换了 App,但完整代码仍可在 GitHub 中自行运行!
数据
为了测试和开发应用程序,我编写了另一个函数,它在磁盘上创建了 500,000 行和 58 MB 的完美数据作为 CSV 文件(此处有https://raw.githubusercontent.com/justinhchae/app_helper/main/data/source.csv)。我喜欢 58 MB 的大小,因为我认为它正好处于磁盘和内存都无法处理的极限。
UX
使用 Streamlit 是获得纯 Python 前端体验的一种有趣方式。在这个原型中,核心功能是转换用户的输入。默认的 Steamlit 用户界面非常干净,我试图保持这种美感,让用户专注于工作流程。然而,在进行这些转换时,有些事情是用户期望看到的。
例如,我通常在减小数据帧的大小时过滤某些列,并通过列名检查数据类型。因此,我创建了一个响应式特性选择器,它按列过滤数据帧——最初,它由用户以后可以编辑的所有列填充。
此外,我想确保用户得到关于节省了多少内存的反馈,以显示进程的价值。因此,我最终创建了一个带有容器的并排布局来显示内存中的变化。
gif 演示
数据助手应用的 0 版原型——来自作者 Justin Chae
结果
原始 CSV 文件从 34 MB 的内存转换为大约 15 MB,节省了 50%以上的内存。在磁盘上,文件大小从 58MB 减少到 31mb——节省的空间不是很大,但可以通过压缩(如. BZ2 或. ZIP)来改善。
丰富
这个原型正如我所希望的那样工作,但还有一些改进,我仍然需要工作。目前为止排名前三的问题。
- ****文字处理。在没有清除唯一数据类型的情况下应用分类数据类型。因此,“烤面包机”被视为与“烤面包机”不同的物体,并导致描述同一事物的两个类别。通过条件检查和文本处理来解决。
- ****数据完整性。在开发应用程序功能时,我从 文档 中了解到取消数据酸洗有一个安全考虑。因此,由于应用程序提供了备份数据,我需要用【HMAC】包含某种类型的文件验证,以减轻网络安全风险。
- ****特性。我发现像 pandasgui 这样的应用程序在探索数据框架方面非常有用,而且有一些“很好”的功能可以传达关于表格的见解。虽然该应用程序提供了一个非常简短的概述,我想包括其他有用的功能。例如,一些可视化数据的高级直方图和统计数据可能会有用。
结论
在这个故事中,我分享了一个原型应用程序,它解决了我几乎每天都会遇到的一个数据优化问题。该问题涉及以编程方式降低数据帧中列的精度,以便它占用更少的内存和磁盘空间。
为了积累 UX 设计的经验,我决定把这个编码问题变成一个 web 应用程序开发项目。现在,用户可以上传一个 csv 文件,生成一个腌熊猫数据帧,这样可以减少一半的内存消耗。通过一些额外的功能,这个应用程序可能足够有用,可以启动一个新项目或快速启动,而无需编写大量代码。
尽管还有待改进,但我对最初的产品很满意,也很高兴在栈的前端获得了一些经验。
这个项目的所有代码都在我的 GitHub 储存库中:
https://github.com/justinhchae/app_helper
该应用程序:
[ 编辑——由于应用程序的限制(每个用户限三个),我已经在 streamlit 上替换了应用程序,但完整的代码仍然可以在 GitHub 上自行运行!
Python 包(2021 年 4 月 7 日编辑):
这段代码的更新版本现在可以在https://pypi.org/project/pd-helper/或通过pip install pd-helper
以一个方便的 Python 包的形式获得。
我很有兴趣知道这个 app 对你有没有帮助。你喜欢吗?有用吗?它应该有什么特点?在 Git 发表一个问题或者在这里留下评论。谢谢!!
一位应用数据科学家:一窥他们的世界
原文:https://towardsdatascience.com/an-applied-data-scientist-a-sneak-peek-into-their-world-6971c0500191?source=collection_archive---------6-----------------------
在数据科学世界里,一个看似新的工作简介中的“谁”、“什么”以及介于两者之间的一切。
活动发起人在 Unsplash 上的照片
数据科学是一个不断发展的领域,在过去的十年里,在运营以客户为中心的服务或业务方面,它已经从一个“好东西”变成了一个“必备东西”。与任何不断发展的领域一样,它的边界正在被突破,技能组合正在重新塑造自己,关于“数据科学家”的概念也在不断受到挑战。毫不奇怪,企业已经重新组织起来,以充分利用这一改变游戏规则的资产。
由此,我们看到了应用数据科学家的出现——这似乎是一种新的工作描述。但是是吗?它已经出现了很长时间,经历了命名约定的变化,并且仍然是业内最强大、最广泛需要的技能之一。过去我们称他们为“数据分析师”,现在我们有时称他们为“数据科学家”,或者在一些组织中专门称为“应用数据科学家”。
谁是应用数据科学家
简而言之,应用数据科学家是研究数据(即数据科学)的人,其目的是通过在底层数据(即数据科学)上应用理论框架(即概念框架)和算法,为商业问题提供可行的解决方案。
某人处理、分析、建模和解释任何类型的数据以驱动有意义的见解并帮助解决业务问题 (在大多数情况下,识别更多的数据!)。
应用数据科学家处理底层数据,应用合适的技术/逻辑概念,为业务问题提供有意义的解决方案。
应用数据科学家是这样的人:
擅长“应用数据科学”
成为一名优秀的数据科学家是成为一名优秀的应用数据科学家的基础。不言而喻,人们确实需要对正在处理的数据有很好的理解。此外,这通常意味着:
- 对数据科学算法的深刻理解从简单的基础分析到高级机器学习模型。深入了解所有这些的工作原理是有益的,但不是强制性的。与许多其他领域一样,帕累托原则在数据科学中也适用,和 20%的算法 或方法可用于解决 80%的业务问题 。
-了解这些算法并了解它们在行业内的可能应用非常重要。 - 牢固掌握实施所需的平台(或工具/软件)。如果你不知道如何在底层数据上使用数据科学算法,那么理解数据科学算法没有多大用处。这是通过具有机器学习/统计包的编码平台以及帮助我们解释和分析的可视化工具来完成的。
-知道如何读取数据、处理数据、清理数据、处理数据、可视化数据和建模数据至关重要。
必须具备方法的技术知识和实施方法的能力
牢牢掌握领域知识
领域知识或行业知识是应用数据科学家的关键。在分析项目期间,经常会出现需要将分析导向一个方向而不是另一个方向的时候,这就是行业知识可以帮助一个人应用业务背景/逻辑并引导分析的地方。一个应用数据科学家对他的领域有很好的理解。
领域知识对于在分析过程中做出决策有很大的帮助,并且常常是好的和伟大的区别。
为行动带来洞察力
如果说应用数据科学家有什么与众不同的地方,那就是在对底层数据应用数据科学技术后,对业务问题提出可行建议的能力。在处理完数据并在此基础上使用他们的领域知识进行上下文分析后,一位应用数据科学家通过编写一个故事将分析带入生活。一个故事,以基于潜在数据的见解的建议结束,利益相关者可以根据这些建议采取行动。
*例如,在零售业中创建客户细分是一项涉及复杂数据科学的工作。然而,为了与业务利益相关者达成一致,描述一下这些细分市场代表的客户类型会有所帮助。解决问题,如他们长什么样,他们主要属于哪个人群,他们如何购物,他们买什么等。帮助企业理解它们,将它们可视化,并使分析变得生动(非常真实)。*蛋糕上的樱桃是数据科学家可以覆盖他们的领域知识,并描述业务可以实施的策略,以激活这些群体。
什么?那又怎样?“现在——什么?”框架通常用于将分析带入生活,并可以帮助基于洞察力决定关键行动。
此外,应用数据科学家与客户(或商业利益相关者)密切合作。这是他们拥有强大的领域知识并能够将业务基本原理应用于数据科学问题的一个原因。与业务(或客户)对应方建立牢固的关系也意味着他们能够知道他们的分析的哪些部分可以采取行动以及如何采取行动。
发展和培养与客户的密切关系是持续提供巨大客户价值的重要因素。
化繁为简
对于外行人来说,一些数据科学算法可能非常复杂。所涉及的数学可能很难掌握,如果不是数据科学背景的人,这一点更是如此。
数据科学项目的关键利益相关者通常是决策者,他们可能/可能不具备数据科学背景。这使得数据科学家的工作变得非常困难,因为获得利益相关方的认可非常重要,以确保分析引导决策过程,而不仅仅是最终成为“值得一做的研究”。这涉及到用简单的门外汉术语向关键利益相关者解释复杂科学的能力,并让他们相信分析结果。这种对复杂数学数据框架/模型的简单外行描述可能会因利益相关者的数据科学知识或理解倾向而异。
复杂的数据科学项目的简单性确保了它的广泛应用。
知道—伟大与足够好的分析
应用数据科学家有时从事短期(2-3 天)项目,有时从事长期(数周)项目,并且经常跨越不同长度的多个项目。这种广泛的范围意味着有时利益相关者会提出快速的要求/请求,而时间是最重要的。为了实现这些目标,应用数据科学家需要对企业内的现有产品/定制解决方案有全面的了解;并且能够依靠他们在这些场景中提供快速解决方案**。这显然意味着与其他垂直部门*(如产品团队、数据工程团队、商业团队等)互动。)定期进行,并记录这些工作之间的相互联系。*
几乎总是不希望从零开始,而是利用现有的知识库/工具集
另外,如果对时间敏感的项目意味着接一个电话,那么**是好还是不够好?**了解在何处利用同类最佳的科学算法深入分析,以及何时使用更简单的框架并及时完成分析以帮助决策。
当一个业务结果依赖于分析时,超时瞄准好的解决方案是好的,及时交付足够好的是好的。
也许不是新的,但它是不同的
在数据科学领域,应用数据科学概要文件当然不是新的概要文件。然而有一点是不同的*(..和更好的)*,是它是更精确地定义和更好地区分比一般的数据科学家的个人资料。
应用数据科学档案有很多好处:
- 显而易见的是学习 —随着时间的推移,人们可以学习数据科学、其应用、关键工具以及开发坚实的领域知识。
- 定义明确的角色意味着角色中的人更加清楚组织的期望,能够设定明确的目标并实现它们。
- 由于与客户密切合作,他们经常能够看到在他们的分析背后做出的决定,并且能够很容易地看到他们工作的影响。
- 与多个项目的多个利益相关者合作,这通常意味着应用数据科学家拥有一个跨越多个垂直领域的强大网络。
- 应用数据科学家通常可以在他们职业生涯的后期,基于他们所掌握的众多技能,为自己开拓出不同的职业道路
应用数据科学家与研究数据科学家
一些组织只有一个“数据科学家”档案,而一些组织有两个独立的数据科学家档案——应用数据科学家和研究数据科学家(请注意,这些档案中的任何一个也可以被命名为“数据科学家”)。
应用数据科学家和研究数据科学家有区别吗?
这是一个价值百万美元的问题。在我看来,在这两种情况下所需的技能组合之间没有太大的区别,而且这两者可以在他们想要的时候互换。
然而,由于工作方式的本质或组织的期望,它们之间有时会有一条细线。
但是,必须再次强调的是,这两种技能没有理由是不同的。
让我们看看这条细线,以便更好地理解它:
数据科学技能:
这两个配置文件中的数据科学技能没有理由不同。组织期望研究数据的科学家深入研究问题*(即* 垂直深度 很重要),而应用数据的科学家则期望对更广泛的数据科学问题和解决方案有更全面的了解*(即* 水平覆盖 更有价值)
- 由于他们的工作性质,应用数据科学家可能不知道所有的数据科学算法,而研究人员或多或少会有透彻的理解。
- 应用型专家更擅长 20%概念的广泛应用,这些概念可以帮助解决他们领域中 80%的数据科学问题。
- 预计两者都将处理复杂的高级分析、机器学习、Python 等。;然而,应用数据科学家将始终牢记实际应用,而研究数据科学家将更深入地研究问题。
客户互动技巧:
还是那句话,这些不一样没什么特别的原因。这两种模式都要求对业务问题有详细的了解,能够将它们转化为数据科学问题,并为它们提供数据支持的解决方案。
然而,由于工作的性质,应用数据科学家将更接近利益相关者,因此将获得对业务目标更广泛/更深入的了解,使他们能够从分析中得出可操作的结果
在我看来,有两个独立的工作简介是有益的,并给个人提供了根据自己的愿望选择深入或广泛的机会。显然,对员工有更清晰的期望对组织和员工都非常有帮助。
摘要
有趣、有活力、有回报 —当我想到当今世界的应用数据科学时,这些词会浮现在我的脑海中。
应用数据科学| (图片由作者提供)
→它似乎在适用的技术专长和业务知识之间达到了完美的平衡,以完成有影响力的工作。
保持联系..
如果你喜欢这篇文章并且对类似的文章感兴趣 在 Medium 上关注我 、 加入我的邮件列表 和*(..如果你已经不是了..)跳上去成为 中的一员获取上千篇有帮助的文章。(如果你使用以上链接,我将获得你 50%的会员费)*
..不断学习,不断成长!
一种选择 K-均值聚类数的方法
原文:https://towardsdatascience.com/an-approach-for-choosing-number-of-clusters-for-k-means-c28e614ecb2c?source=collection_archive---------7-----------------------
所建议的方法考虑了内部距离和聚类数目之间的一般权衡,并自动选择聚类数目
弗兰基·查马基在 Unsplash 上拍摄的照片
当我们使用聚类算法时,选择聚类的数量总是一项具有挑战性的任务。虽然有一些现有的方法可以帮助完成这项任务,但它们通常是单独使用,以便做出决定。此外,您可能还需要根据方法的结果手动选择最终的集群数量。
在这里,我建议一种方法,它考虑了内部距离和集群数量之间的折衷,并自动选择集群的数量。
现有方法
在本节中,您可以找到选择集群数量的两种最常见的方法。各有各的优势和局限。
轮廓分析
这是一个众所周知的方法,也提供了非常酷的可视化。它允许我们解释和验证集群内的一致性。完整的 Python 实现和解释可以在 scikit-learn 页面中找到:
https://scikit-learn.org/stable/auto_examples/cluster/plot_kmeans_silhouette_analysis.html
这个 scikit-learn Python 代码产生了下面的可视化效果,帮助我们理解所选择的集群数量是否是一个好的选择。
这种方法的一个缺点(在链接中也有提到)是,它可能会产生多个集群,所以您需要自己从不同的选项中进行选择。
惯性和肘法
惯性是样本到它们最近的聚类中心的平方距离的总和。我们希望这个数字尽可能小。但是,如果我们选择 K 等于样本数,我们将得到惯性=0。这是我们能够达到的最小惯性值,但是我们没有达到将数据聚类到最佳数量的聚类中的目标。
惯性值随着聚类数的增加而减少——所以我们需要手动选择 K,同时考虑惯性值和聚类数之间的权衡。为此,我们通常使用肘方法,我们选择惯性图中的肘点。之后,惯性值的改善不显著。
惯性图
基于这种方法,选择的 K 大约为 8–11,但是需要手动选取。
这里有一篇很好的文章总结了这种方法:
建议的接近比例惯性
上述两种方法需要您手动决定集群的数量。基于我从这些方法中学到的东西,我开发了一个自动选择 K(聚类数)的过程。
所建议的方法考虑了每个可能的 K 的惯性值,并通过惩罚参数对其进行加权。该参数表示惯性和簇数量之间的权衡。
我们没有单独使用惯性,而是计算了它的加权版本:
比例惯性公式
- 惯性-样本到其最近的聚类中心的距离的平方和
- 阿尔法-手动调整的因素,给予惩罚的集群数量
- 惯性(K=1)-所有数据点都在同一聚类中的基本情况的惯性
比例惯性图
Alpha 是手动调整的,因为在我看来,集群数量的损失是一个商业决策,应该纳入分析中。
使用缩放的惯性,选择的 K 是明显的,并且可以自动完成。在上述情况下,K=9。
密码
以下函数是在并行计算中为每个 K 计算调整后的惯性。非并行选项在下一段代码中。
非平行选项:
示例-如何使用
该函数返回最佳 k 值和一个数据框,该数据框包含所有可能的 k 值的所有调整惯性值:
返回的结果
关闭
建议的解决方案对我过去遇到的各种业务问题非常有效。请让我知道它是如何为你工作的,如果你认为可以做更多的调整来改善它。
非常感谢 Oshry Ben-Harush 帮助我开发了这种方法,并感谢 Noga Gershon Barak 和 T2 Noam Kalush 提供的技术反馈以及对本文的校对和评论。
附加阅读
很好的指南,详细介绍了 k-means 算法以及在 Python 中的使用
https://realpython.com/k-means-clustering-python/
对深度学习的攻击
原文:https://towardsdatascience.com/an-attack-on-deep-learning-b437bdf3c860?source=collection_archive---------29-----------------------
意见
是的,但是听我说完!
信用:Pixabay
随着数据科学和机器学习的不可分割的元素,深度学习已经变得无处不在。它塑造了人类与机器的互动方式,也许比迄今为止数学建模的任何其他进步都更重要。随着自动驾驶汽车、计算机在各自的桌面游戏中战胜大师,以及全球任何智能手机都可以进行语言翻译,人们很自然会想知道——深度学习做不到什么?
深度学习颠覆了我们的世界;但在这一过程中,它推断并放大了隐藏在训练此类模型所需的真正大规模数据集中的社会偏见。相应地,对算法偏见的批评导致被高度公开的员工解雇 (s)。提出上述批评的主要呼吁是:
模型、数据和其中的潜在偏见无法解开,并且这些信息不应该以深度学习产品采用的名义被忽视。【自己的总结。]
对基准问答数据集上的模型性能持批评态度的研究人员指出,如果对问答结构进行小的更改,则的性能会下降 20%以上;换句话说,单词之间的虚假关联使得模型的表现令人难以置信,而不是对语言的真正理解。这一事实构成了深度学习研究的一个核心问题:深度学习的进步和成就是由基准数据集的性能来衡量的——继续基准驱动的研究有双重财务激励&开发: (A) 为(监督的)深度学习模型的训练创建数据集非常昂贵,而 (B) 基准数据集的性能是人工智能价值主张的核心——它表达了进步,这意味着货币价值,这意味着对<插入大型科技公司的影响(我稍后会再回到为什么大型科技公司被激励传播广泛的深度学习热情的另一个原因。)
深度学习是有效的黑盒模式匹配。这些模型很容易在小数据集上过度拟合,但是当样本大小接近人群大小时,泛化能力很好。深度学习模型不会思考(尽管名称如此),它们只是简单地将输入映射到输出:照片中的人脸、句子中的主题等。模型架构每隔几年就会改变,并且没有得到严格的数学证明来验证为什么这样的设计是最佳配置;更确切地说,它们的更新是为了对用户选择的一些性能指标进行有意义的微调。我们通常称这样的方法为 启发式方法 ,意思是:
任何解决问题的方法……采用一种实用的方法,这种方法不能保证是最佳的、完美的或合理的,但足以达到一个直接的、短期的目标或近似值。
当解释(甚至近似)一个系统的全部复杂性是不可行的时候,启发式方法是一个明智的选择,特别是当我们对系统的行为没有任何假设的时候。作为一种启发式方法,深度学习在非结构化数据任务上表现得非常好,如面部识别,因为我们根本没有办法清晰地说出每一种可以想象的像素配置模式,而可以定义一张脸是什么或者不是什么。在这样的背景下,非常需要一个高度灵活的黑盒模式匹配机。
然而,在无数的问题中,我们确实有办法提出关于系统如何工作的假设,我们不仅需要准确的结果,还需要对我们预测的信心和*增强对系统如何工作的理解。*例如,谷歌研究人员在 2017 年开发的分层/多级贝叶斯模型,可以用来了解营销渠道支出对销售的影响,包括——投资达到峰值效果的延迟,进一步投资导致回报递减的饱和点,以及每个渠道投资对销售的强度。相比之下,深度学习模型只能进行预测;我们不能带着它的 500 万个参数,带着对系统实际行为的更多理解离开。
贝叶斯方法的优点和缺点是它们把用户放在了驾驶座上。你必须通过描述它们的参数和概率分布来提供关于你的系统如何工作的信念。换句话说,你要让模型符合数据。相比之下,黑盒方法允许用户将数据压缩成适合充分研究的任务的形状,如分类、回归或聚类。确实一个知识渊博的神经网络库用户(PyTorch,TensorFlow/Keras 等。)将能够塑造一个特定于手头任务的深度学习架构;然而,这种架构的有效性完全由性能来判断,并且其中的调整是通过拧动机器的螺母和螺栓直到达到任意的满意阈值来完成的;换句话说,这些调整并不是由您试图建模的系统的知识决定的。
这让我们看到了基于云的机器学习的真正价值主张:谷歌和亚马逊都有各自现成的基于云的深度学习驱动的机器学习产品。亚马逊网络服务的 SageMaker 允许插件&播放机器算法,例如对象检测,而无需对用户强加任何数学知识要求。您采用所述产品的理由在于它们在*基准测试任务中真正非凡的准确性。然而,*如果你需要提高你的人类对你的系统如何工作的理解,这些工具对你帮助不大。因此,科技巨头受到激励来传播这样一种信念,即深度学习对于任何可以想象的任务都是完美的,因为它有助于产品的采用。(我保证过我会回到这个话题。)
我在与业务领域专家合作时遇到的一个问题是,当意识到深度学习仅在基准测试任务中非常好,而在其他任务中非常好时,当可用的数据非常大时,他们的期望就会降低。例如,最新的命名实体识别(NER)模型可以检测文本中的人、地点、组织、日期、货币(通常还有更多)。然而,这并不一定保证从简历中提取技能是一项微不足道的任务——你仍然需要大量的训练数据,而获取这些数据的成本很高。这个问题是如此的根深蒂固,以至于亚马逊土耳其机械公司(Amazon Mechanical Turk)为你众包了数据标记(训练数据集准备过程)——在负担得起的情况下,这依赖于人力。
对于深度学习的新任务问题,一个常见的缓解是使用迁移学习。在自然语言处理的上下文中,这采取单词嵌入的形式。把迁移学习想象成一张餐馆的优惠券——“订购一份任意大小的比萨饼,就可以得到免费的鸡翅。”鸡翅是一道开胃菜,让你吃得饱饱的,这样你就可以只点一个小号或中号的披萨,而不是大号(或特大号)的。)你还是要为一个披萨买单——只是没那么贵了。数据摄取过程就像比萨饼;当然你需要少一些,但你肯定还是需要一些。因此,由于你的迁移学习(在这个比喻中是水牛翅膀),你可能会得到几十万行,而不是几百万个观察结果。)用一个下午的时间在一百份简历上,甚至用一周的时间在几千份简历上标注技能,然后指望迁移学习来完成剩下的工作,这是不现实的。
我忽略的一个例外是强化学习——无人驾驶汽车和桌上游戏掌握背后的动力。这种形式的机器学习(在这两个例子中是深度学习)不需要训练数据集。然而,它确实需要一个环境,可以奖励/惩罚一个代理人采取的行动。然而,一个被设计成游戏的商业系统,适合强化学习,被正式称为马尔可夫决策过程。而这个确实需要用户的一些数学知识(它就像贝叶斯方法一样复杂),并且不太可能在短期内成为基于云的机器学习提供商的现成产品。
我忽略的第二个例外是贝叶斯神经网络。这种设计允许结合先前的信念,这在深度学习上下文中,调整给定参数可以呈现的值。相应地,该方法不太可能在小数据量上过度拟合(一个重大的改进),并且最重要的是,将返回超过其预测的分布——不仅返回它所相信的,还返回它对其的信心。但这是福也是祸——网络越大,典型的贝叶斯训练方法——MCMC 采样所需的训练时间就越长。这个问题如此棘手,以至于一种新的学习算法正在积极研究中:变分推理。该方法试图初始化一组样本,并迭代地缩小该合成分布和目标分布之间的熵。贝叶斯统计社区中的各种工具都有可用的实现,比如 PyMC3。然而,它的研究时间还没有 MCMC 采样长——所以我们不确定它容易陷入什么陷阱,如何减轻这些风险,等等。考虑到这些限制,代表用户进行大量的贝叶斯神经网络研究工作才能在实践中有所收获。因此,在不久的将来,它们不太可能出现在开箱即用的云 ML 产品中。
说到贝叶斯方法,任何时候你需要了解你的系统实际上是如何运行的,你的首选应该是贝叶斯统计。如今,像 PyMC3 这样的高级 API 抽象掉了许多低级细节,同时允许您保留对参数实际建模的控制。我强烈推荐这本书,Richard McElreath 的《统计学再思考》第二版,相应的 YouTube 讲座系列,以及这本书的代码,移植到 GitHub 上的 PyMC3。
总的来说,我不是要哀叹云 ML 解决方案,而是要质疑(A)基准 DL 任务的广泛适用性的假设和(B)在一个新的任务上摄取足够的 DL 性能数据的容易程度。Cloud ML 产品,比如 AWS,使您能够上传 docker 映像,完成任务的特定库需求,大大扩展了您的建模选择,超越了基准(DL)任务。
总之,由于使用了巨大的基准数据集,深度学习在充分研究的任务中是不可思议的;然而,算法偏见的批评者主张不同的研究团队审查数据摄取过程,这增加了本已昂贵的过程的成本。对于研究较少的任务的性能期望需要与非常真实的期望进行校准,即数据摄取非常昂贵和缓慢,可能如此之多,以至于我们不应该排除不会使人类与模型疏远的方法。换句话说,你没有被卖给一个谎言,但你被卖给了一个巧妙的营销活动,歌颂深度学习作为解决你所有数据需求的解决方案的优势,但掩盖其弱点。
我将留给你们柏拉图的告诫不要写作:
他们将停止行使记忆,因为他们依赖于写下的东西,不再从他们自己内部,而是通过外部的标志来唤起记忆。
简而言之——我们不是为了记忆而写作;我们写信是为了忘记。书面语言的发明产生了一个无意的后果——通过扩展我们获取信息的途径,我们无意中摆脱了记忆信息的义务。当然,书面语言无疑改善了社会;尽管如此,书面语言对希腊口头传统有着深远的影响。这个例子说明,我们对信息编码方式的改变有隐藏的后果,影响我们访问和操纵这些信息的能力。
当然,自动驾驶汽车和语言翻译模型证明了深度学习所接受的广泛研究是正确的。但是随着的广泛采用,即任何问题都可以通过深度学习来解决,我们无意中限制了理解我们希望建模的系统和其中强大技术的价值。
构建 Spotify 算法的尝试
原文:https://towardsdatascience.com/an-attempt-to-construct-spotify-algorithm-9ac21ae1ecfb?source=collection_archive---------24-----------------------
使用最近邻方法实现基于内容的过滤以开发推荐系统
音乐聚类分析-作者雷达图
介绍
在本文中,我将尝试使用最近邻算法构建一个 Spotify 推荐系统模型,并使用 Spotify 进行数据收集。这项研究将是一个无人监督的机器学习项目。
作者的 Spotify 桌面设置图片
你在周日早上醒来很晚,在 Spotify 上播放你选择的歌曲,然后去浴室。当歌曲完成时,音乐播放器不会就此停止,而是播放一大堆类似的歌曲,除非你关闭自动播放,否则不会让你以一种奇怪的方式从浴室出来,逃离潮湿的地板,并改变音乐。好吧,我的观点是,你曾经想知道 Spotify 如何在大多数时候推荐一套近乎完美的歌曲。Spotify 前机器学习工程师克里斯·约翰森分享了一场演讲,对 Spotify 推荐系统及其架构的发展提供了大量见解。
克里斯·约翰森在 Spotify 上的算法音乐推荐
内容 - 基础过滤
这是一种基于项目相似性的推荐系统。一种方法是利用产品的特性。例如,假设您刚刚完成了一个网络系列,现在您想观看一个类似的网络系列,在这种情况下,基于内容的过滤是如何工作的,它会建议其他网络系列具有与所观看的相似的功能。为了计算这种相似性,我们将采用基于邻域的方法。
基于邻域的方法
余弦相似性
它有助于量化对象之间的相似性。可以使用余弦的相似性度量来计算相似性。在这里,我展示了如何衡量两个网络系列之间的相似性。x 轴和 y 轴分别反映科幻和恐怖类型。它的存在和不存在分别由值 1 和 0 给出。以这种方式,可以在稀疏矩阵中表达特征,该稀疏矩阵作为输入数据提供给我们的最近邻模型。
稀疏矩阵
余弦相似公式
为了计算距离/相似性,余弦公式如上所示。一旦计算出相似性/距离,我们就可以搜索最近的 K 个具有相似特征的 Web 系列。
数据集
数据集是一个4358 首曲目 的播放列表,累计播放时间是 273 小时 ,而且因为是协作播放列表,所以还在增加。这个播放列表由几乎 900 个子流派 组成,范围从古典到说唱等等。
这个播放列表/数据集是在我的朋友们的帮助下制作的:阿达什·米什拉,阿什温·拉古南丹,苏亚迪普·马拉,瓦龙·维诺德,丁奇·米什拉 & 尼兰詹·戈斯瓦米。非常感谢各位!
“数据科学”播放列表(数据集来源)
在 Spotipy 的帮助下,我们可以从这个庞大的数据集中提取元数据和其他有用的属性。
要提取的有用特征列表:
[A]元数据
- uri——该曲目的唯一 Spotify URI。
- id —曲目的唯一 Spotify ID。
- 流行度——专辑的流行度。该值将介于 0 和 100 之间,100 是最受欢迎的。流行度是根据专辑中各首歌曲的流行度计算出来的。
- 名称—轨道的名称
- duration_ms —以毫秒为单位的音轨长度
- 艺术家—艺术家的姓名
- release_date —专辑首次发行的日期,例如“1981–12–15”。根据精度,它可能显示为“1981”或“1981–12”。
- 专辑—曲目所属专辑的名称
- 艺术家 _ 流派—艺术家的流派
【B】音频特性
- 声学—[ 0–1]音轨是否声学的置信度。
- 可跳舞性—[0–1]描述了基于音乐属性(包括速度、节奏、稳定性、节拍强度和整体规律性)的轨道适合跳舞的程度。
- 能量—[0–1]强度和活动的感知度量。充满活力的音轨感觉起来很快,很响,很嘈杂(例如死亡金属:高能,巴赫前奏曲:低能)
- 乐器性—[0–1]预测轨道是否不包含人声(高于 0.5 的值表示乐器轨道,而说唱歌曲的分数接近 0)。
- 活跃度—[0–1]检测录像中是否有观众。
- 响度—[-60–0 dB]整个轨道的平均音量。
- speech iness—[0–1]检测音轨中是否存在口语单词(高于 0.66 的值描述音轨可能完全由口语单词组成,0.33–0.66 描述音轨可能包含音乐和语音,低于 0.33 的值最有可能代表音乐和其他不像语音的音轨)。
- 化合价—[0–1]描述了轨道所传达的音乐积极性。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。
- 调式(Mode)——调式表示轨道的调式(大调或小调),其旋律内容来源于音阶的类型。大调用 1 表示,小调用 0 表示。
- 速度—轨道的总体估计速度,单位为每分钟节拍数(BPM)。在音乐术语中,速度是给定作品的速度或节奏,直接来源于平均节拍持续时间。
- time_signature —轨道的估计整体拍号。拍号(拍子)是一种符号约定,用于指定每个小节(或小节)中有多少拍。
- 调—轨道所在的调。整数映射到使用标准音高的音高
关于这些功能的更多信息: Web API 参考|面向开发者的 Spotify】
挑战
上面提到的[B]音频功能是制作 Spotify 算法所必需的功能。但是它们不足以建立一个有效的模型,因为有一首英语歌曲和一首印地语歌曲有相似的音频特征。在这种情况下,这些音轨可能会使模型互相推荐,这并不表示推荐模型是有效的。因此,要解决这个挑战,潜在的解决方案是获取曲目的流派,但是 Spotipy 没有任何曲目的流派。Spotipy 只提供艺术家和专辑的流派。但是大多数时候专辑的流派是不可用的(如果还没有分类,数组是空的)。所以,最终,我们必须选择适合每个艺术家的艺术家类型。
进口
import pandas as pd
import numpy as npimport spotipy
from spotipy.oauth2 import SpotifyClientCredentialsfrom IPython.display import clear_output
import matplotlib.pyplot as plt
import plotly.graph_objects as gofrom kneed import KneeLocator
from sklearn.preprocessing import MinMaxScaler
from scipy.sparse import csr_matrixfrom sklearn.neighbors import NearestNeighbors
from sklearn.cluster import KMeans
资格证书
Spotify 开发者仪表盘应用
为了访问数据提取,我们需要用我们的 API 凭证生成一个令牌。你需要在他们的网站上注册开发者账户来获得你的令牌。建立帐户后,您需要在仪表板中创建一个应用程序,该应用程序会提供您的客户 ID 和客户密码。
#Define ConstantsCLIENT_ID = '####'
CLIENT_SECRET = '####'
username = '####'
playlist_id = 'spotify:playlist:0KY6lRcsNYtf6pHPfXDkFN'
我们将从共享选项中获得播放列表 id,其中显示复制 Spotify URI。
#Get Access Tokencredentials = SpotifyClientCredentials(client_id=CLIENT_ID,client_secret=CLIENT_SECRET)
token = credentials.get_access_token()
sp = spotipy.Spotify(auth=token)
提取 Spotify 数据
下面的代码从 spotipy 数据库中提取信息,并将所有信息存储在将用于创建 DataFrame 的列表中。
#Initiating lists to store features
uri,id,popularity,name,duration_ms,artist,year,album =[],[],[],[],[],[],[],[]
acousticness,danceability,energy,instrumentalness,key,liveness,loudness,mode,speechiness,tempo,time_signature,valence = [],[],[],[],[],[],[],[],[],[],[],[]
artist_genre = []a=0playlist_tracks = []
offset=0# To surpass extracting limit of 100
while True:
results = sp.user_playlist_tracks(username, playlist_id, offset=offset)
playlist_tracks += results['items']
if results['next'] is not None:
offset += 100
else:
breakfor track_meta in playlist_tracks:#Meta Data
uri.append(track_meta['track']['uri'])
id.append(track_meta['track']['id'])
popularity.append(track_meta['track']['popularity'])
name.append(track_meta['track']['name'])
duration_ms.append(track_meta['track']['duration_ms'])
artist.append(track_meta['track']['artists'][0]['name'])
year.append(track_meta['track']['album']['release_date'])
album.append(track_meta['track']['album']['name'])#Audio Features
track_feature = sp.audio_features(track_meta['track']['uri'])[0] acousticness.append(track_feature['acousticness'])
danceability.append(track_feature['danceability'])
energy.append(track_feature['energy'])
instrumentalness.append(track_feature['instrumentalness'])
key.append(track_feature['key'])
liveness.append(track_feature['liveness'])
loudness.append(track_feature['loudness'])
mode.append(track_feature['mode'])
speechiness.append(track_feature['speechiness'])
tempo.append(track_feature['tempo'])
time_signature.append(track_feature['time_signature'])
valence.append(track_feature['valence'])#Genre
resultd = sp.search(track_meta['track']['artists'][0]['name'])
try:
trackd = resultd['tracks']['items'][0]
artist_meta = sp.artist(trackd["artists"][0]["external_urls"]["spotify"])
artist_genre.append(artist_meta["genres"])
except:
artist_genre.append([])
finally:
a = a+1
clear_output()
print(a)
创建数据框架
df = pd.DataFrame(list(zip(name,album,artist,year,popularity,duration_ms,uri,id,acousticness,danceability,energy,instrumentalness,
key,liveness,loudness,mode,speechiness,tempo,time_signature,valence,artist_genre)),
columns=['name','album','artist','year','popularity','duration_ms','uri','id','acousticness','danceability','energy','instrumentalness',
'key','liveness','loudness','mode','speechiness','tempo','time_signature','valence','artist_genre']
)df['playlist'] = sp.user_playlist(username, playlist_id.split(':')[2])['name']df = df.drop_duplicates(subset='id', keep="first")
df.reset_index(inplace=True,drop=True)df.head(3)
特征抽出
正如您在艺术家流派栏中看到的,每个艺术家都有一个或多个列表形式的流派。下面的代码列出了所有流派的唯一列表。
genre_list = []for i in df['artist_genre']:
for j in i:
if j not in genre_list:
genre_list.append(j)print(pd.Series(genre_list).nunique())905
正如我们所看到的,有 905 个子流派可用。现在我们使用这些类型作为我们数据框架的离散特征。
list_of_row,row=[],[]for i in df['artist_genre']:for j in genre_list:
if j not in i:
row.append(0)
else:
row.append(1)list_of_row.append(row)
row=[]#Checking out the Shape
print(len(list_of_row))
print(len(list_of_row[0]))3773
905#Creating DataFrame of genre
df_genre = pd.DataFrame(list_of_row,columns=genre_list)#Copy id column for merging DataFrame
df_genre['id'] = df['id'].copy()
df_genre.head()
df _ 流派
#View some columnsdf_genre.columnsIndex(['florida rap', 'scorecore', 'soundtrack', 'video game music', 'compositional ambient', 'french soundtrack', 'hollywood', 'new age', 'album rock', 'art rock', ... 'mumbai indie', 'pakistani indie', 'indian lo-fi', 'indian folk', 'pop r&b', 'horror synth', 'british post-rock', 'cosmic post-rock', 'british orchestra', 'id'], dtype='object', length=906)
基于列“id”合并两个数据帧
merged_df = pd.merge(df, df_genre, on='id')
分析
merged_df.info()<class 'pandas.core.frame.DataFrame'> Int64Index: 3773 entries, 0 to 3772 Columns: 927 entries, name to british orchestra dtypes: float64(9), int64(910), object(8) memory usage: 26.7+ MB
使聚集
文章的这一部分深受 K 均值聚类和 PCA 的影响,通过相似的音频特征对音乐进行分类| Sejal Dua | 2020 年 12 月|走向数据科学
在我们创建基于音频特征的聚类之前,我们需要确定有多少个聚类将适合对我们的播放列表进行聚类。为此,我们将使用 WCSS。这将使我们能够使用肘过程找到 K-Means 的最佳聚类数。
# get within cluster sum of squares for each value of k
wcss = []
max_clusters = 200
for i in range(1, max_clusters):
kmeans_cluster = KMeans(i, init='k-means++', random_state=42)
kmeans_cluster.fit(df[['acousticness','danceability','energy','instrumentalness','liveness','loudness','speechiness','valence']])
wcss.append(kmeans_cluster.inertia_)
# programmatically locate the elbow
n_clusters = KneeLocator([i for i in range(1, max_clusters)], wcss, curve='convex', direction='decreasing').knee
print("Optimal number of clusters", n_clusters)
# visualize the curve in order to locate the elbow
fig = plt.figure(figsize=(20,8))
plt.plot(range(1, max_clusters), wcss, marker='o', linestyle='--')
# plt.vlines(n_clusters, ymin=0, ymax=max(wcss), linestyles='dashed')
plt.xlabel('Number of Clusters', fontsize=18)
plt.ylabel('Within Cluster Sum of Squares (WCSS)', fontsize=18)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
plt.show()Optimal number of clusters 8
所以肘部在第八组
应用 K 均值和最小最大缩放来可视化
kmeans = KMeans(n_clusters=n_clusters, init='k-means++', random_state=42,)
kmeans.fit(df[['acousticness','danceability','energy','instrumentalness','liveness','loudness','speechiness','tempo','valence']])
scaled_df = df[['acousticness','danceability','energy','instrumentalness','liveness','loudness','speechiness','tempo','valence']].copy()scaler = MinMaxScaler()
scaled_values = scaler.fit_transform(scaled_df)
scaled_df.loc[:,:] = scaled_valuesscaled_df['Cluster'] = kmeans.labels_
可视化集群
fig = go.Figure()angles = list(scaled_df[['acousticness','danceability','energy','instrumentalness','liveness','loudness','speechiness','tempo','valence']].columns)
angles.append(angles[0])layoutdict = dict(
radialaxis=dict(
visible=True,
range=[0, 1]
))for i in range(n_clusters):
subset = scaled_df[scaled_df['Cluster'] == i]
data = [np.mean(subset[col]) for col in subset[['acousticness','danceability','energy','instrumentalness','liveness','loudness','speechiness','tempo','valence']].columns]
data.append(data[0])
fig.add_trace(go.Scatterpolar(
r=data,
theta=angles,
fill='toself',
name="Cluster " + str(i)))
fig.update_layout(
polar=layoutdict,
showlegend=True,template='plotly_dark'
)
fig.show()
星团的雷达图分析
正如你所看到的,群集 5 有更多的乐器和声音,这意味着它包括更多的环境电影配乐。我们可以用这种方式评估其余的集群。
数据预处理
将数据转换为将输入到最近邻算法的稀疏矩阵。
#List of columns to be used as features
list1=['acousticness','danceability','energy','instrumentalness','liveness','loudness','speechiness','tempo','valence']list2=list(df_genre.columns)dataset = merged_df[list1+list2].copy()#set index
dataset.set_index('id',drop=True,inplace=True)
创建稀疏矩阵
dataset_matrix = csr_matrix(dataset.values)
稀疏矩阵
最近邻
实施项目的大脑。
模型拟合
model_knn = NearestNeighbors(metric='cosine', algorithm='brute')
model_knn.fit(dataset_matrix)
推荐系统
我们需要设置 n 值来获得一定数量的推荐。
#Enter Track URI here for which you want Recommendations
search_uri = 'spotify:track:2LVr6WQ6W7B3i8CeWFjcLP'query_index = df[df['uri']==search_uri].index.values[0]distances, indices = model_knn.kneighbors(dataset.iloc[query_index,:].values.reshape(1,-1),n_neighbors = 10 )for i in range(0,len(distances.flatten())):
# if distances.flatten()[i] <= 0.0001:if i == 0:
print('Recommendations for {0}:\n'.format(df[df['id']==str(dataset.index[query_index])]['name'].values[0]))
else:
print('{0} : {1} by {3}, with distance of {2}'.format(i,
df[df['id']==str(dataset.index[indices.flatten()[i]])]['name'].values[0],
distances.flatten()[i],
df[df['id']==str(dataset.index[indices.flatten()[i]])]['artist'].values[0]))
测试
为下面的测试选择的所有歌曲都来自这个播放列表,并且推荐的曲目将仅来自这个播放列表(因为这是我们模型的整个数据集)。
对于数据科学播放列表(数据集源)
测试— 1
测试模型的时间到了,首先我会得到我最喜欢的歌曲的推荐,蒙特塞拉特艺术编辑,一种基于电子音乐的流派的推荐
测试— 2
推荐 Baarishein,基于印地语原声的流派
测试— 3
推荐基于说唱的流派《知更鸟》
测试— 4
推荐基于视频游戏原声音乐的流派《战地一号》
测试— 5
推荐卢克和莱娅——出自《星球大战:绝地归来》,这是一部根据电影配乐改编的电影
测试— 6
宽大推荐,以钢琴独奏为基础的体裁
结论
如果你觉得一些推荐没有达到预期,那么我相信这个挑战可以通过用更多种类的歌曲填充播放列表来克服,并且如果 Spotipy 开始为歌曲和专辑提供流派,那么我认为这些事情可以帮助我们使模型更有效地工作。总之,大多数歌曲都得到了类似的推荐,如印度原声歌曲、钢琴独奏和家庭音乐,考虑到这样一个小的手工数据集,这似乎是一个很大的进步。
谢谢你留下来!!
如果你喜欢这篇文章,你可能想看看我的另一篇 Spotify 排行榜分析文章。[ 链接
关注我的社交活动
链接到我关于这个项目的笔记本:【colab.research.google.com
我的 LinkedIn 个人资料:【https://www.linkedin.com/in/hardik-deshmukh/
我的其他中型文章: Hardik Deshmukh —中型
我的 GitHub:https://github.com/smarthardik10
参考
[1] K-Means 聚类和 PCA 通过相似的音频特征对音乐进行分类| Sejal Dua | 2020 年 12 月|走向数据科学
[2]https://youtu.be/kccT0FVK6OY
[3] 基于内容的推荐—第 3 部分| rakesh 4 real | Fnplus Club | Medium
利用 Jupyter 部件的自动预报方法
原文:https://towardsdatascience.com/an-automated-forecast-approach-utilizing-jupyter-widgets-142b6c51d314?source=collection_archive---------31-----------------------
创建用户友好的代码和小部件来访问和比较预测结果
马库斯·斯皮斯克在 Unsplash 上的照片
你有几个系列来预测未来 24 个月,比如说 50 到 150 个月。你没有时间为每一个都找到完美的模型,所以你需要某种一般化的方法。你可以写一个循环,应用一个安全的,虽然不是很动态的方法,比如简单的指数平滑,移动平均,或者其他。但是你需要更精确一点的东西来提高你的准确度,而不需要投入大量的时间。
在过去的几年里,我在一些场合遇到过同样的问题。我开发了一个现在经常使用的 Python 模块。源代码如下:
https://github.com/mikekeith52/AllStatesForecast
我以前在自动预测季节性的背景下写过这个模块。你可以在这里看到文章。我假设你正在使用 Jupyer Lab 或 Jupyter Notebook,如果你想继续下去的话。
数据格式化和加载
首先,让我们将观察到的数据加载到预测器对象中。我们可以使用 pandas 数据框架,其中每一列都是要预测的序列,行索引是 pandas 日期时间周期。在这个例子中,我们的数据是每月的。这种格式的伪代码如下所示:
现在,我们有了一个带有名称空间预测的字典,其中每个键是来自我们的 pandas 数据帧的一个列标签,值是为预测未来 24 个月而加载的预测器对象。同样的概念应该适用于任何粒度,无论是每天、每小时、每周等等。
预测
接下来,我们将选择要应用的预测。这需要我们的时间序列的一些知识,以及哪些模型可能捕捉到我们的序列的特点。幸运的是,预测器模块为您提供了许多模型选项,包括许多自动应用程序,以找到最佳超参数。这些包括但不限于:
- ARIMA(包括 SARIMA、ARIMAX 和 SARIMAX)
- 指数平滑(包括霍尔特温特斯、ETS 和 TBATS)
- 神经网络自回归
- 向量自动回归
对于这个例子,为了能够使用实际数据,我将选择两个序列进行预测:犹他州经济巧合指标和佛罗里达州巧合指标,因为它们很容易从圣路易斯美联储网站上提取,而且因为它们是我最近居住过的两个州。3 个月的样本外测试集似乎是合理的,因为我们正处于衰退之中,使用比这长得多的时间段并不能真正表明最有可能捕捉最近趋势的预测。我将使用 ARIMA、TBATS 和 ETS,因为它们自动处理与平稳性相关的问题,并设置自己的超参数。我还将使用表现最好的两个模型的平均值。代码如下:
可视化结果
现在,让我们看看结果。显然,我的例子只针对与一个州的经济相关的两个序列,但是这个解决方案应该可以扩展到许多序列和不同的业务环境。我建议,在获得结果后,逐一查看每个系列,以确保至少有一个预测看起来合理,样本外误差率较低。下面给出了使用 Jupyter 小部件实现这一点的简单方法。
首先,让我们安装一些要求:
pip install ipywidgets==7.5.1
conda install -c conda-forge nodejsjupyter nbextension enable --py widgetsnbextension
如果您使用 Jupyter Lab:
jupyter labextension install @jupyter-widgets/jupyterlab-manager
让我们也导入所有必需的库:
from ipywidgets import widgets
from IPython.display import display, clear_output
import matplotlib.pyplot as plt
import seaborn as sns
查看所选系列的多个型号
现在,创建小部件。我们将使用下拉菜单深入到单个系列,并使用一个表来选择一个、一个或几个我们想要绘制的模型。选择后,我们使用一个按钮来完成选择。我们必须告诉笔记本显示小部件的所有三个部分——下拉菜单、表格和按钮(以及输出)。代码如下所示:
models = ('auto_arima','tbats','auto_hwes','average')ts_dropdown = widgets.Dropdown(options=mm.keys(), description = 'Time Series:')mo_select = widgets.SelectMultiple(options=sorted(list(set(all_models))),description='Models',disabled=False)button = widgets.Button(description="Select Time Series")output = widgets.Output()
display(ts_dropdown, mo_select, button, output)
如果您照原样运行这段代码,它将为您输出一些小部件,这意味着将出现一个下拉列表、一个表格和一个按钮。但是你的选择没有任何作用。下一段代码告诉您的笔记本对用户选择做一些事情:
def on_button_clicked(b):
ts_selection = ts_dropdown.value
mo_selection = list(mo_select.value)
with output:
clear_output()
forecasts[ts_selection].plot(models=mo_selection, print_mapes=True, plot_fitted=True)button.on_click(on_button_clicked)
我们可以将这两个代码段放在一个函数中:
现在,我们有了漂亮的输出,可以在我们的时间序列之间轻松切换:
作者图片
您可以使用标有“时间序列”的下拉菜单在预测的每个序列之间切换,还可以关闭和打开绘制模型。根据您选择在系列中使用的模型数量,您可以对这种格式进行一些调整(例如,如果您选择应用一组模型,使用前 n 名模型的下拉列表可能会更有效地快速找到您的最佳表现模型),但这种基本的视觉结构允许我快速评估自己的结果。
可视化模型性能
假设您还对直观地比较每个系列的每个模型的评估准确度感兴趣。为此,您可以使用类似的小部件方法。代码如下:
输出看起来很惊人。
作者图片
这显示了给定系列的模型误差率之间的相对差异。我并不总是选择具有最佳误差度量的模型作为要实现的模型——这也取决于哪一个看起来最合理。但是,使用预测的可视化表示以及模型之间的相对误差率的可视化表示,我通常可以做出好的决定,并且我的预测已经通过使用这种方法的真实数据证明是准确的。
结论
我们使用预测模块和 Jupyter 小部件构建了一个简单的可视化分析。使用这个基本示例,我们可以将预测解决方案扩展到多个系列,这使得为多个系列建模这一看似困难的任务变得更加容易。如果你感兴趣,下面是包含完整笔记本的 zip 文件。
Twitter 情感分析问题的自动超参数优化
原文:https://towardsdatascience.com/an-automatic-hyperparameter-optimization-on-a-twitter-sentiment-analysis-problem-6d5dc732f500?source=collection_archive---------19-----------------------
这是一个漂亮的超参数调整技术的解释,使您的生活更容易。请放心在你的下一个 ML 项目中使用它!
照片由丹尼斯·莱昂在 Unsplash 上拍摄
H 超参数调优是机器学习生命周期中最重要的部分之一。这在计算上是昂贵的,并且也是耗时的过程。
在读硕士期间,我偶然发现了一个自动超参数优化框架 Optuna 。一个有趣的方面是,我们可以将 Optuna 与标准的机器学习算法以及神经网络方法一起使用。
在本文中,我将通过展示一些例子来记录我发现的关于 Optuna 的所有有用的东西。最重要的是,我将解决您在测试这个 Optuna 库时将会遇到的常见问题。
继续阅读这篇文章,你会发现:
- 如何使用 XGBoost 和 LSTM 对情感分析问题建模。
- 如何将 Optuna 集成到 XGBoost 和 LSTM 模型中,并执行超参数调整。
- 在使用 Optuna 时,我们如何减少一些常见的陷阱。
感兴趣?开始阅读!
问题是
杰瑞米·泽罗在 Unsplash 拍摄的照片
我们可以为此挑选任何问题,但我希望它更有趣一些,所以我选择了Twitter 数据的情感分析 。
情感分析属于自然语言处理领域,我们使用多种文本处理方法来理解文本数据并从中获得洞察力。这种方法最常见的用途是识别推文的极性或情绪。
简而言之,我们的目标是将一条推文/短语或一句话归类为一组情绪,如积极、消极或中性。这是一个更广泛的分类,但我们可以更进一步,对推文情绪进行更详细的分类,如非常快乐、适度快乐,以及类似版本的悲伤、愤怒、厌恶等。
我使用的数据集来自一场卡格尔比赛。
数据:知识共享署名下的 4.0 国际许可
虽然,比赛谈论的是推文提取,但我将数据重新用于情感分析。
来自数据集的样本推文(来源:作者)
对于实验,我将使用text
和sentiment
功能,在这里我将建立一个机器学习模型,它将一条推文作为输入,并告诉我们它的情感/情绪。由于我们有 3 种情绪类型(积极、消极和中性),这是一个 多类分类任务 的情况。
数据预处理
并非推文的每一部分对我们进行的文本处理都很重要。推文的某些方面,如数字、符号、停用词,对于情感分析来说并不那么有用。
所以我们只需在预处理步骤中移除它们。我使用了nltk
python 库和regular expressions
来删除停用词、电子邮件、URL、数字、空格、标点符号、特殊字符和 Unicode 数据。
代码如下所示:
正如我之前提到的,我们将使用两种不同的方法进行情感分析,即 XGBoost 分类器和 LSTM 神经网络架构。
XGBoost 分类器
照片由 Haithem Ferdi 在 Unsplash 上拍摄
“清理”完文本数据后,下一步就是矢量化。在这里,我们只是将文本转换成数字格式,以便机器学习模型可以“理解”它。
您可以观察到,在构建 ML 模型之前,需要将文本、图像、图表等数据结构转换成数字表示。
矢量化
为了对文本进行矢量化,我们可以简单地使用 Sci-Kit Learn 的计数矢量化工具方法。基本上,我们将文本转换成唯一单词的稀疏矩阵,其中我们使用数字来表示文本示例中某个单词的存在。
我们将数据分为训练集、验证集和测试集,分割比例为-80:10:10。分割是分层的,因此我们在所有数据分割中具有相同比例的标签/情感。
您可以使用以下代码来实现这一点:
Optuna 集成
现在,我们准备好训练模型并调整超参数。通过以下方式安装 Optuna:
pip install optuna
在下面的代码中,您会注意到一个被 Optuna 优化的目标函数。首先,我们定义我们感兴趣的超参数,并将它们添加到试验对象中。在这里,我选择调learning_rate, max_depth and n_estimators
。根据超参数的类型,我们可以使用suggest_float, suggest_int, suggest_categorical
等方法。
在这个目标函数中,我们创建了一个模型实例,并使其适合训练集。在训练之后,我们预测验证集上的情感,并计算准确性度量。Optuna 的目标函数将通过用不同的超参数值进行试验来尝试最大化这个准确度分数。在优化过程中,可以采用不同的采样技术。
我们可以重写目标函数来处理模型的损失值。在这种情况下,我们将尝试最小化目标函数。
一种提前停止的方法以修剪的形式实现。如果看起来没有希望,试验将被跳过/取消。
你可能已经注意到了set_user_attr
方法。这是用来保存任何变量,我们可能会发现重要的。这里我们感兴趣的是保存与最高验证准确性相关的最佳模型。我们在这个用户属性中保存了最佳的 XGboost 模型。
在 Optuna 优化过程中,您会看到:
通过运行试验调整超参数(来源:作者)
如果您希望 Optuna 覆盖更大范围的超参数值,则试验次数可以更多。
试验完成后,我们可以检索超参数重要性图,如下所示:
XGBoost 超参数重要性(来源:作者)
我们观察到learning_rate
是比其他参数更重要的超参数。有了这个,我们就知道需要关注哪些超参数了。
在测试集上预测
因此,我们已经完成了模型训练和超参数调整。我们进行了 20 次试验来寻找最佳超参数。现在,我们可以检索我们的最佳模型,并对测试集进行预测。
# retrieve the best model from optuna study
best_model = study.user_attrs['best_model']y_pred = best_model.predict(x_test)print(accuracy_score(y_test, y_pred))
测试精度(XGBoost): 0.683
不算寒酸的分数!让我们看看我们是否能做得更好。
LSTM 建筑
泰勒·维克在 Unsplash 上的照片
长短期记忆神经网络结构在自然语言处理领域中很流行,因为它具有在其“记忆”中保留序列信息的能力。
就像 XGBoost 一样,我们应该对文本数据进行矢量化,以便训练 LSTM 模型。我们执行标记化,然后将矢量化的序列填充到相同的长度。
数据以类似于 XGBoost 模型的方式分割,这样我们就可以对两者进行比较。
标记化和填充
现在,我们将 LSTM 模型定义如下:
我选择了optimizer, epochs and batch_size
作为可调超参数。
这个神经网络模型现在可以开始训练了!!
在训练 LSTM 模型时,让我们集成 Optuna 来执行超参数调整。
这个 Optuna 集成的代码如下所示:
这个 Optuna 集成的结构是相同的。我们只是改变了目标函数中的模型和超参数。
类似地,我们获得 LSTM 的超参数重要性图:
LSTM 超参数重要性(来源:作者)
我们看到 optimizer 是一个重要的超参数,批处理大小对准确性分数的提高没有太大贡献。
我面临的问题
对于 XGBoost,我们可以直接保存模型,但是当您试图以类似的方式保存 Keras 模型时,Optuna 会给出一些错误。从我的搜索中,我发现这是因为 Keras 模型是不可挑选的?!
对此的解决方法是只保存最佳模型的权重,然后使用这些权重来重建模型。
以下代码将对此进行更多解释:
您只需创建模型的一个新实例,并设置从 Optuna 检索的权重,而不是再次训练它。
用 LSTM 获得的测试准确度分数:
测试精度(LSTM): 0.72
这个分数比 XGBoost 好。通常,神经网络方法比标准的机器学习方法表现得更好。通过使用 BERT、RoBERTa 或 XLNet 等变压器架构,我们可以进一步提高这一精度分数。
最后,我喜欢使用 Optuna 进行超参数调优。我可以很容易地从所有不同的试验中检索出最佳模型,并了解在训练过程中哪个超参数是重要的(使用超参数重要性图)。
如果你看到了这篇文章的这一部分,感谢你的阅读和关注。我希望你觉得这篇文章内容丰富,如果你有任何问题,请随时通过 LinkedIn 、 Twitter 或 GitHub 联系我。
2021 年建立营销组合模式的完整指南
原文:https://towardsdatascience.com/an-complete-guide-to-building-a-marketing-mix-model-in-2021-fb53975be754?source=collection_archive---------2-----------------------
充分理解什么是营销组合模型以及如何使用它
约书亚·厄尔在 Unsplash 上的照片
介绍
营销一直被认为是一门艺术,而不是一门科学。但随着在线营销和大数据的出现,营销比以往任何时候都更加数学化和有条不紊。事实上,数据科学和机器学习应用的最大机会领域之一是营销!
这篇文章将集中在一个非常流行和强大的营销科学技术称为营销组合建模。本文将介绍它是什么,为什么它如此有用,如何用 Python 构建一个,最重要的是,如何解释它。
什么是营销组合模式?
营销组合模型是一种建模技术,用于确定市场属性,即给定公司使用的每个营销渠道的估计影响。
与归因建模(另一种用于营销归因的技术)不同,营销组合模型试图衡量不可估量的营销渠道的影响,如电视、广播和报纸。
一般来说,你的输出变量是销售额或转化率,但也可以是网站流量。您的输入变量通常包括按时段(日、周、月、季度等)划分的渠道营销支出,但也可以包括我们稍后将讨论的其他变量。
为什么这么有用?
您可以通过多种方式利用营销组合模式的力量,包括:
- 更好地了解您的营销渠道和目标指标(即转化率)之间的关系。
- 区分高投资回报率营销渠道和低投资回报率营销渠道,最终更好地优化您的营销预算。
- 根据给定的输入预测未来的转换。
这些见解中的每一个都可以在您扩展业务时提供大量的价值。让我们深入了解用 Python 构建一个这样的模型需要什么。👀
构建营销组合模型
为了对营销组合模型有更好的直觉,本节将从头开始用 Python 构建一个营销组合模型。这个营销组合模型将建立在 Kaggle 的数据集之上。
步骤 1:导入所有相关的库和数据。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as pltdf = pd.read_csv("../input/advertising.csv/Advertising.csv")
步骤 2:执行一些 EDA
一般来说,您会进行更多的探索性数据分析,但对于本教程,我们将重点关注三个最常见的(根据我的经验,也是最强大的):
- 相关矩阵:显示每个配对关系的相关值的表格
- 结对图:一种简单的方法来可视化每个变量之间的关系
- 特征重要性:根据每个特征在预测目标变量时的有用程度来给它们打分的技术
相关矩阵
再次重申,相关矩阵是显示每个配对关系的相关值的表格。这是理解特征关系的一种非常快速有效的方式。这是我们矩阵的代码。
corr = df.corr()
sns.heatmap(corr, xticklabels = corr.columns, yticklabels = corr.columns, annot = True, cmap = sns.diverging_palette(220, 20, as_cmap=True))
上面的相关矩阵显示,电视和销售之间有很强的相关性(0.78),广播和销售之间有中等的相关性(0.58),报纸和销售之间的相关性很弱(0.23)。现在下结论还为时过早,但这有利于我们继续前进。
配对图
配对图是一种直观显示每个变量之间关系的简单方法,它类似于相关矩阵,只是它显示的是每个配对关系的图表,而不是相关性。现在让我们来看看结对图的代码。
sns.pairplot(df)
我们可以看到我们的配对图和我们的原始相关矩阵之间的一些一致性。看起来电视和销售之间有很强的正相关关系,对广播来说没有,对报纸来说就更没有了。
特征重要性
要素重要性允许您确定每个输入变量对预测输出变量的“重要性”。如果打乱某个要素的值会增加模型误差,则该要素非常重要,因为这意味着模型依赖该要素进行预测。
# Setting X and y variables
X = df.loc[:, df.columns != 'sales']
y = df['sales']# Building Random Forest modelfrom sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error as maeX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.25, random_state=0)
model = RandomForestRegressor(random_state=1)
model.fit(X_train, y_train)
pred = model.predict(X_test)# Visualizing Feature Importance
feat_importances = pd.Series(model.feature_importances_, index=X.columns)
feat_importances.nlargest(25).plot(kind='barh',figsize=(10,10))
上面的代码首先创建一个随机森林模型,将销售额作为目标变量,将营销渠道作为特征输入。一旦创建了模型,我们就可以计算每个预测值的特征重要性,并将其绘制在条形图上。
似乎有一种模式,电视是最重要的,其次是广播,最后才是报纸。接下来是实际构建模型。
第三步:建立营销组合模型(又名。OLS 模型)
是时候建立我们的营销组合模型了!我们正在构建的模型的另一种说法是 OLS 模型,是普通最小二乘法的缩写,是一种用于估计线性回归模型中参数的方法。OLS 模型是一种回归模型,在构建营销组合模型时最常用。
Python 如此神奇的地方在于它已经有了一个库,可以用来创建 OLS 模型:
import statsmodels.formula.api as smmodel = sm.ols(formula="sales~TV+radio+newspaper", data=df).fit()print(model.summary())
上面的代码创建了我们的普通最小二乘回归模型,该模型指定我们根据电视、广播和报纸的营销费用来预测销售额。
步骤 4:绘制实际值与预测值的对比图
接下来,让我们用实际销售值绘制预测销售值的图表,以直观地了解我们的模型的表现。在业务用例中,如果您试图了解您的模型反映实际发生的情况有多好,这是一件特别有用的事情,在这种情况下,如果您试图了解您的模型根据每个营销渠道的支出金额预测销售额有多好。
from matplotlib.pyplot import figurey_pred = model.predict()
labels = df['sales']
df_temp = pd.DataFrame({'Actual': labels, 'Predicted':y_pred})
df_temp.head()figure(num=None, figsize=(15, 6), dpi=80, facecolor='w', edgecolor='k')
y1 = df_temp['Actual']
y2 = df_temp['Predicted']plt.plot(y1, label = 'Actual')plt.plot(y2, label = 'Predicted')
plt.legend()
plt.show()
实际值与预测值
还不错!在给定电视、广播和报纸支出的情况下,这个模型似乎在预测销售方面做得很好。
如何解释营销组合模型
回到。summary(),有几件事需要注意:
- T1。总结() 为我们提供了关于我们模型的丰富见解。回到的输出。summary() ,我们可以看到几个需要关注的领域(您可以参考下面 OLS 回归结果中的这些见解):
- 调整后的 R 平方为 0.896 。这意味着数据中大约 90%的总变化可以用模型来解释。这也意味着该模型没有占所用数据的 10%,这可能是由于缺少变量,例如是否有另一个营销渠道没有包括在内,或者只是由于数据中的噪音。
- 在上半部分可以看到 Prob (F 统计量):1.58e-96 。这个概率值(p 值)表示目标变量没有好的预测值的可能性——在这种情况下,没有好的销售预测值。由于 p 值接近于零,我们知道模型中至少有一个预测器能够很好地预测销售额。****
**如果查看 P > |t|列,可以看到每个预测值的 P 值。**电视和广播的 p 值小于 0.000,但报纸的 p 值为 0.86,这表明报纸支出对销售没有显著影响。一般你希望 p 值小于 1%或者 5%,这是实践中的两个标准。
感谢阅读!
通过阅读这篇文章,你现在应该知道什么是营销组合模式,如何建立一个,以及如何有效地使用它为您的业务。一如既往,我祝你学习一切顺利:)
不确定接下来要读什么?我为你挑选了另一篇文章:
[## 六分钟内解释所有概率分布
towardsdatascience.com](/all-probability-distributions-explained-in-six-minutes-fe57b1d49600)
又一个!
特伦斯·申
- 如果你喜欢这个, 跟我上中等 更多
- 有兴趣合作吗?让我们连线上LinkedIn
Git 入门指南第 1 部分
原文:https://towardsdatascience.com/an-easy-beginners-guide-to-git-2d5a99682a4c?source=collection_archive---------1-----------------------
入门
在短短 12 分钟内学习 Git 的基础知识
扬西·敏在 Unsplash 上的照片
如果你是编程新手,你肯定会想学习 Git!
Git 是一个分布式版本控制软件,基本上允许多人并行工作,并且它保存了所有更改的历史记录。这将有助于确保没有代码冲突,并允许开发人员将文件或整个项目恢复到他们代码的先前版本。
Git 可以跟踪做了什么更改,谁做了更改,他们什么时候做的更改,以及他们为什么做了更改。多酷啊。更好的是,这一切都是免费的!
在本文中,我将帮助您使用 Git 导航。一旦你掌握了它的窍门,它就会很容易使用。以下是主题的概要:
- 安装 Git
- 创建本地 Git 存储库
- 将文件提交到本地存储库
- 检查所有提交
- 提交时忽略文件
- Git 分支
- 创建与其他人共享的远程存储库
- 在本地和远程存储库之间移动代码
- 加分内容!磨尖
安装 Git
如果您的计算机上还没有安装 Git,请按照下面链接中的说明进行安装。
https://Git-SCM . com/book/en/v2/Getting-Started-Installing-Git
如果您不确定您是否有它,您可以在您的终端中键入以下命令来查看它是否已安装。
git --version
注意:要使用 Git,Mac 用户将使用终端进行交互。对于 Windows 用户,它将是命令提示符。
创建本地 Git 存储库
如果您从一个全新的项目开始,您将需要创建一个本地 Git 存储库。这是您的文件和变更检查点的存储位置,以便进行版本控制。
在我们初始化本地存储库之前,让我们在您的桌面上为我们的示例创建一个文件夹。姑且称之为“git-demo-example”。
现在,打开您的终端(或命令提示符)。复制下面的命令。第 1 行将导航到我们刚刚创建的文件夹,第 2 行将创建我们的本地存储库。
cd ~/Desktop/git-demo-example
git init
就是这样!我们已经创建了第一个本地存储库,它位于 git-demo-example 文件夹中。
接下来,让我们把一些文件放到文件夹中,这样我们就有东西可以用了。在我们的 git-demo-example 文件夹中创建一个名为 fruits.py 的文件,并将下面这段代码复制到该文件中。注意: 如果你没有安装 Python,你可以创建一个. txt 文件,而不是. py 文件,然后继续。
fruits = ['apple', 'dragonfruit', 'peach', 'banana', 'grape', 'apple', 'peach', 'watermelon', 'grape', 'grape']
保存文档并退出。在同一个文件夹中再创建一个名为 veggies.py 的文件,并将下面这段代码复制到该文件中。
veggies = ['cabbage', 'carrot', 'spinach', 'asparagus', 'artichoke', 'pumpkin', 'lettuce']
现在 git-demo-example 文件夹中应该有两个文件。
来源:作者
将文件提交到本地存储库
到目前为止,我们已经创建了一个本地存储库,并将两个文件添加到我们的工作目录(git-demo-example 文件夹)中。为了能够开始跟踪文件和我们所做的更改,我们必须将文件添加到本地存储库中。将文件添加到本地存储库的过程称为提交。
这是一个两步的过程,以便我们将代码提交到本地存储库。我们需要首先将文件添加到临时区域,然后提交。这个过程中的额外步骤使您能够控制您实际上想要提交到本地存储库的文件,并且如果您最初不小心选择了错误的文件,也允许您改变主意。
要将单个文件添加到临时区域,您可以使用git add fruit.py
要添加多个文件,使用这个:git add fruit.py veggies.py
如果你有很多文件或者懒得输入文件名,你可以使用git add .
来添加文件夹中的所有文件。
来源:作者
继续使用上面提到的两个选项之一将这两个文件添加到临时区域。如果您想仔细检查暂存区中有什么,您可以使用git status
来检查暂存区。您可以在下面看到我们的两个新文件,更改尚未提交。
来源:作者
为了提交文件,我们将使用git commit -m “My First Commit”
。“我的第一次提交”可以是你想对代码或者对你所做的修改所做的任何评论。这绝对是一个好主意,输入一些相关的东西,这样将来你就可以记住做了什么。
我们刚刚完成了第一次承诺!干得好!
Viktor Nikolaienko 在 Unsplash 上拍摄的照片
我真傻。在我们的蔬菜清单中,我们把南瓜列为一种蔬菜,但实际上它是一种水果!你知道吗?让我们改正那个错误。打开我们创建的两个文件,将南瓜从蔬菜中移除,添加到水果中。在对这些文档进行更改之后,继续练习进行另一次提交。
git add .
git commit -m “Changed pumpkin from veggie to fruit”
我曾经对南瓜上瘾,但后来我去了补丁。
照片由麦蒂·贝克在 Unsplash 拍摄
到目前为止,我们已经提交了两次。可以把这些看作是我们可以在任何时间点恢复的检查点。
有益提醒:记得常犯!它会让你的生活变得更加轻松!
检查所有提交
如果您想查看到目前为止我们已经提交的所有提交的列表,您可以使用git log
。在日志中,您可以找到提交的作者、提交日期以及每次提交的提交消息。
如果您已经提交了很多次,那么您可能需要在这个日志中滚动一段时间。使用git log --pretty=oneline
可能是值得的,它会将您的提交消息压缩到一行。
来源:作者
如果您想查看 Julia 提交的所有内容,还可以使用其他很酷的参数,比如git log — author=julia
。
如果你很好奇,这篇文章向你展示了使用日志工具的 10 种不同方式。.)
提交时忽略文件
如果有些文件您永远不想提交,您可以创建一个. gitignore 文件来帮助解决这个问题。这个。gitignore file 将告诉 git 哪些文件或模式应该被忽略,这样它们就不会意外地被暂存和提交。这是明智之举!
安德鲁·乔治在 Unsplash 上拍摄的照片
创造。gitignore 文件在终端中用这个命令:touch .gitignore
开门。gitignore 并添加不想被跟踪的文件的名称。注意:如果您没有看到。gitignore,它可能是隐藏的,所以请确保您正在查看隐藏的文件。
下面的代码片段是一个. gitignore 文件的示例。第一行和第二行是我不想包含的文件名。您还可以指定与文件名匹配的模式。例如,picture*将查找所有以单词 picture 开头的文件。这里的星号实际上是匹配零个或多个字符的通配符。
来源:作者
有关模式匹配的更多信息,请点击这里的链接。
继续练习第三次提交。gitignore 文件到您的本地存储库。
Git 分支
使用 Git 可以做的一件非常酷的事情是,您可以创建不同的分支,这样您就可以将您的工作与主分支分开。如果您想测试代码,这很有用。
在您的终端中,如果您键入git status
,您可以看到您在主分支上。
来源:作者
默认情况下,您将总是在 Git 的主分支下工作。我们之前进行的两次提交是在主分支上。我们有能力创建一个新的分支(例如 test ),在那里我们可以测试新的代码,而不会弄乱主分支中的代码。
来源:作者
在上面的例子中,每个圆圈代表一次提交。当我们在测试分支中提交时,这些检查点将与主分支分开保存。如果我们喜欢测试分支中的代码,我们可以与主分支合并。如果在测试分支中实现的想法失败了,我们可以放弃它们。当与多个协作者一起工作时,您也可以各自创建自己的分支。
让我们创建一个名为 test 的新分支。
git branch test
要查看你所在的分支,你可以输入git branch
,你所在的分支将以绿色突出显示。我们目前在主分支上。
如果我们想要将代码提交到测试分支,我们将需要从主分支转移到测试分支。为此,请使用以下命令:git checkout test
来源:作者
如果您再次输入git branch
,请注意我们现在在测试分支上。
合并分支
当我们在测试分支中时,让我们修改我们的 fruits.py 文件,并将更改提交到这个测试分支。您可能已经注意到,我们的列表中有重复的水果。在下面的代码中添加 fruits.py 文件以获得一个唯一的集合。
fruits = set(fruits)
保存并提交新的更改。
git add fruits.py
git commit -m “Removed duplicate fruits”
这个测试分支包含我们之前进行的前两次提交以及我们最近的代码提交,而主分支只包含之前的前两次提交。然而,我们可以将测试分支合并到主分支,这样主分支就有了最新的代码。
在合并两个分支之前,可以通过使用git diff test master
来看看分支之间发生了什么变化。Test 是您的源分支,master 是您的目标分支。
要执行合并,您必须返回到主分支,然后像这样使用合并功能:
git checkout master
git merge test
创建与其他人共享的远程存储库
您已经将所有的更改保存在本地存储库中,这很好,但是也许您想与您的同事或全世界共享它。我们可以创建一个远程存储库,并将其与您的本地存储库同步。这样,您可以将更改推到一个中心位置,在那里其他人可以访问您的代码,他们也可以提供帮助。
有几个网站可以托管 Git 项目,但是为了这些练习的目的,我将使用一个名为 Github.com 的网站。报名是免费的!如果您还没有帐户,请在 https://github.com/的[上注册。](https://github.com/)
在主页上,单击启动项目并创建存储库。我将把它命名为“Git-for-初学者”。
来源:作者
设置好 repo 之后,复制存储库的 url。如下图所示,我的知识库网址是https://github.com/julia-git/Git-for-Beginners.git
来源:作者
现在,我们需要告诉我们的本地存储库我们的远程存储库在哪里,以便在两者之间建立一个链接。用您自己的存储库 url 替换下面的代码行。
git remote add origin [repository url]
您需要输入您的 Github 用户名和密码才能连接。
在本地和远程存储库之间移动代码
既然已经建立了连接,要将本地存储库中的所有代码移动到远程存储库中,可以使用git push -u origin master
。
有了这一行代码,我们本地存储库中主分支的所有内容现在都将位于远程存储库中。如果您希望推送不同的分支,只需将“主”替换为您想要推送的分支的名称。
如果您返回到您的浏览器选项卡,您应该看到您的项目已经成功地被推送到远程存储库。
来源:作者
如果其他人正在处理这个项目并将变更推送到远程存储库,您可以将它们拉下到您计算机上的本地存储库。您将使用以下代码从主分支中提取:git pull origin master
。
总之,下面的命令是我们到目前为止学到的一些东西。
来源:作者
克隆远程存储库
现在让我们尝试一些不同的东西。假设你没有重新开始一个项目,但是你正在帮助你的队友完成他们的项目。我们必须去他们的远程存储库,并将其克隆到我们的计算机上,以创建一个本地存储库。请随意使用下面的库 url 克隆我为本文创建的库:https://github.com/julia-git/Git-for-Beginners
git clone https://github.com/julia-git/Git-for-Beginners
该命令实际上将存储库下载到您的本地计算机,并保留两个存储库之间的连接。
现在,您已经学习了使用 Git 导航的所有基本命令。如果您遇到困难,需要帮助来决定使用什么命令,您可以随时使用git --help
。另外,这里有一个方便的备忘单,以防你忘记任何 Git 命令。
如果您想继续了解更多,请查看 Git 的简单初学者指南的第 2 部分。
加分内容!(对于那些特别喜欢冒险的人)
标签
您可以将提交历史中的特定点标记为重要点,例如,软件发布版本 1.0、2.0 等。
轻量级与带注释的标签
您可以创建两种类型的标记:轻量级和带注释的。
轻量级标记意味着更多的临时用途,因为它只是指向一个特定的提交。带有注释的标签充斥在包含标签者的姓名、电子邮件、日期、消息和身份验证的对象上。
要为 1.4 版创建轻量级标签:
git tag v1.4
要为 1.6 版创建带注释的标记,请执行以下操作:
git tag -a v1.6 -m "my version 1.6"
您可以用自己的信息替换上面引号中的信息。
如果你想看看你目前有哪些标签,你可以使用git tag
。
在稍后的时间点进行标记
如果当前提交不是您想要标记的,我们可以查看提交历史来找到我们想要的。
git log --pretty=oneline
让我们假设第二次提交是我们想要标记的提交。将整个 id 或部分 id 复制到标记语句中。如上面的片段所示,我们将使用的 id 是479d92
。
git tag -a v1.6 479d92 -m "new version 1.6"
将标签推送到远程存储库
标签不会被推送到远程存储库,除非您明确地这样做。将下面标签的名称替换为您要推送到服务器的名称。
git push origin <tagname>
删除标签
如果您想要删除本地存储库中的标记,您将使用以下内容:
git tag -d v1.0
如果您想要删除远程存储库中的标签,您将使用:
git push origin --delete <tagname>
Git 入门指南第 2 部分
原文:https://towardsdatascience.com/an-easy-beginners-guide-to-git-part-2-a35bbbc89490?source=collection_archive---------15-----------------------
审查代码和撤销更改的 Git 基础知识
罗曼·辛克维奇在 Unsplash 上拍摄的照片
现在你已经从我的文章中学习了如何使用 Git 的基础知识,Git 第 1 部分的简单初学者指南,让我们做更多的练习来熟悉 Git 的使用和导航。
您已经看到了 Git 如何跟踪所做的更改,谁做了更改,他们何时做了更改,以及他们为什么做了更改。现在我们将学习如何利用这个版本控制软件来帮助我们审查不同版本的代码以及撤销更改。
坚持我们之前的蔬菜水果主题,开始吧!
审查代码变更
A.将当前代码与上次提交的代码进行比较
B.查看以前提交的文件
C.在提交之间检查代码
撤销更改
A.撤消添加到临时区域
B.撤消您的上次提交
C.撤消当前更改并恢复到上次提交时的版本
D.撤消提交到错误的分支
检查代码更改
A.将当前代码与上次提交的代码进行比较
让我们添加一些新代码,并学习如何检查您所做的具体更改。在 veggies.py 文件中,复制以下代码。
来源:作者
代码细节:上面名为 veg_dict 的字典保存了蔬菜的名称和我们收取的单位价格。我们有一个客户从我们这里订购,order1 存储了我们提供给该客户的商品名称和数量(以千计)。for 循环计算 order1 的总成本。
保存文件,然后用我们的新代码提交。如果您忘记了,下面是在终端中使用的命令。
git add veggies.py
git commit -m "calculate veggie order cost"
照片由 NeONBRAND 在 Unsplash 上拍摄
我们的敌人通货膨胀来袭了!我们必须提高蔬菜的价格,所以让我们用上涨的价格更新我们的字典。一切都上涨了。
veg_dict = {'cabbage': 3.57, 'carrot': 2.99, 'spinach': 4.13, 'asparagus': 3.56, 'artichoke': 4.00, 'lettuce': 3.83}
此外,让我们也添加水果到我们的市场。水果价格存储在变量 fruit_dict 中。我们最喜欢的消费者保持同样数量的蔬菜,但也在他们的订单中添加了水果。请参见下面的新代码。
来源:作者
在 veggies.py 文件中粘贴新代码后,保存它。让我们转到命令行并键入以下内容,以比较对上次提交的更改。
git diff
git diff 来源:作者
您可以在终端输出中一行一行地看到到底做了什么更改!这不是很神奇吗?!
红色显示的是我们上次提交时删除的代码,绿色显示的是上次提交时添加的代码。如果代码是白色的,这意味着没有对该行进行任何更改。
在回顾了这些变化之后,我们很满意。所以让我们练习再做一次提交。如果你已经忘记了,这又是一次。
git add veggies.py
git commit -m "updated veggie prices and added fruits"
B.查看以前提交的文件
比方说,您想回过头来看看上一次提交的代码。通货膨胀发生前蔬菜的价格是多少?
第一步是找到您想要查看的提交。您可能还记得本文的第 1 部分,如果您使用git log --oneline
,您可以在左边看到黄色的惟一提交散列代码和白色的提交消息。
git 日志—在线—来源:作者
包含我们的原始蔬菜价格的提交哈希代码位于 6398269,如上面的截图所示。就像我们如何使用 git checkout 来切换分支一样,我们可以使用 git checkout 来切换到以前的提交。
git checkout 6398269
git checkout —来源:作者
您可能会看到这条关于“分离头”状态的消息。这是怎么回事?把头想象成一个指针。它指向您正在查看的当前提交。
回头看看前面使用git log --oneline
时得到的输出。注意最近一次提交旁边的单词 HEAD。HEAD - > master 告诉我们,指针正指向我们当前所在的 master 分支。也就是说,它指向主分支中的最新提交。大多数时候,HEAD 会指向分支名称。
git 日志来源:作者
现在我们切换到提交 6398269,如果您再次键入git log --oneline
,您会注意到单词 HEAD 现在就在下面截图中我们切换到的提交旁边。
来源:作者
这里有一个插图告诉你头指向哪里。在我们使用git checkout 6398269
之前,头部是指向主分支的,如左图所示。在我们完成 git 检验之后,头部现在指向我们的 commit 6398269。
来源:作者
我们之前得到的分离 HEAD 消息只是告诉我们,指针当前指向一个特定的提交,而不是当前的分支。这听起来很糟糕,但实际上这更像是一个警告信息,而不是错误信息。
分离的头部——由里克·蒙泰罗在 Unsplash 上拍摄
根据输出的消息,在这种分离状态下,“您可以四处查看,进行实验性的更改并提交它们,您可以通过切换回一个分支来放弃在这种状态下所做的任何提交,而不会影响任何分支。”本质上,您可以在这种状态下运行实验,然后决定是保留还是删除它们。
对于本练习,我们不做任何更改。我们只是查看包含蔬菜旧价格的代码行。打开 veggies.py 文件,您将看到来自 6398269 提交的代码。这是我们以前的价格!是不是很酷?
好了,现在让我们回到最近的提交。就是,我们来附个头吧!本质上,我们把头指向我们的主分支。你能猜到该用什么命令吗?
如果你没有,没关系。下次你会得到它的。我们将使用git checkout master
。头部现在应该像下面这样连接。
来源:作者
C.在提交之间检查代码
如果您想比较不同提交的文件之间的差异,您可以很容易地做到这一点。
首先,让我们将另一组代码更改添加到 veggies.py 文件中,以包含第二个订单,如下所示。
保存并再次练习提交。希望你现在已经记住了!
git add veggies.py
git commit -m "add second order"
假设我们想要比较提交 6398269 和提交 d224761 的代码。两者有什么区别?
我们可以使用git diff 6398269 d224761
与前面类似,您可以看到绿色的代码行来自我们最新的代码,红色的代码行来自之前的提交。现在你可以比较和对比。
git diff 来源:作者
你现在是审查代码变更的专家了。让我们继续学习如何撤销更改。
撤消更改
照片由菲利佩佩拉昆在 Unsplash 拍摄
有时我们会犯错误,只希望时光能倒流。幸运的是,Git 为您提供了返回并撤销错误的能力。让我们来看几个你在开始时可能会遇到的不同场景。
A.撤消添加到临时区域
如果您向临时区域添加了不想提交的文件,可以在提交之前将其取出。
作为对您在我的文章的第 1 部分中学到的内容的一个提醒,您首先使用 git add 命令将变更移动到暂存区域。让我们来学习如何撤销一个git add
!
来源:作者
对于这个例子,让我们在您的工作目录中创建一个名为 my_notes.txt 的新文件。然后使用以下命令将工作目录中所有已更改的项目添加到您的文件夹中。
git add .
来源:作者
假设您不想将文件 my_notes.txt 添加到暂存区,因为该文件只是您不想提交的注释。
要撤消对临时区域的添加,可以使用以下命令。
git reset my_notes.txt
这将从您的暂存区中删除文件 my_notes.txt 。
类似于使用git add .
添加所有文件,您可以使用git reset .
从暂存区移除所有文件。
做一个git status
就可以自己看到 my_notes.txt 已经不在暂存区了。
B.撤消您的上次提交
如果你已经完成了一个git commit
,不要担心,有一个方法可以撤销git commit
!
来源:作者
让我们快速制作一个测试提交示例。
git add my_notes.txt
git commit -m “added my_notes”
git log
要取消提交最后一次提交,您需要做的就是
git reset --soft HEAD^
现在继续执行git log
,这样你就可以看到你的最后一次提交已经被撤销了。
记住,这只是为了撤销
git commit
功能。这意味着 my_notes.txt 现在在暂存区。如果你做git status
,可以看到文件在暂存区等待。如果要将其从暂存区中删除,请参考上一节。
如果您想撤销最后两次提交,您可以使用下面的代码。
git reset --soft HEAD~2
用您想要撤消的任意数量的提交替换 2。
另一个注意事项。
git reset
最适合在计算机上撤销本地更改时使用。
C.撤消当前更改并恢复到上次提交时的版本
如果您一直在处理一个文件,并且不喜欢您添加的任何新代码,您可以恢复到上次提交时的版本。
例如,打开 veggies.py,将以下内容复制并粘贴到第 1 行。
#This is a test comment.
继续保存文件。然后转到您的终端,键入以下内容:
git checkout veggies.py
现在回到 veggies.py 文件,您可以看到注释已经消失,代码与上次提交的代码完全相同。
如果您对多个文件进行了更改,您可以使用git checkout .
将所有文件恢复到上次提交时的版本。
汉斯-尤尔根·马格在 Unsplash 拍摄的照片
如果你通过了第 1 部分和第 2 部分,你真的做得很好。Git 可能令人生畏。现在只是从这里开始练习,从错误中学习。还有很多 Git 命令我没有在这些文章中介绍,所以大胆地去 Google 上继续学习吧!
感谢阅读!如果你想在我有新文章发表时第一个知道,请随时点击 订阅这里的 。
来源:作者
Python 和 Pandas 中 SQLite 的简易初学者指南
原文:https://towardsdatascience.com/an-easy-beginners-guide-to-sqlite-in-python-and-pandas-fbf1f38f6800?source=collection_archive---------5-----------------------
了解如何在 SQLite 中创建表和查询数据,以及从 Pandas 访问 SQLite
照片由 Clément Hélardot 在 Unsplash 上拍摄
欢迎阅读 SQLite 的简易初学者指南。在本文中,您将了解什么是 SQLite,如何连接到数据库、创建表、插入和查询数据,以及在 Pandas 中访问 SQLite。我假设您对 SQL 有基本的了解,我在本文中的重点将是如何在 Python 中使用 SQLite。
什么是 SQLite?
SQLite 是一个软件库,它为我们提供了一个开源的关系数据管理系统,我们可以在其中存储大量的数据。
它易于设置,是独立的(需要最少的支持),并且不需要服务器。SQLite 数据库实际上只是一个普通文件,这使得它易于访问和移植。鉴于 SQLite 的简单性,它是部署最广泛的数据库引擎。
SQLite 有很多优点,但是在实践中,如果要处理大量数据,就不应该使用 SQLite。该数据库实际上限为 281。
入门指南
如果你愿意跟随,你可以在这里下载我的 Jupyter 笔记本。
我们首先在 python 文件中导入 SQLite 库。如果您使用的是 Python 2.5 和更高版本,那么这个库不必下载,因为它应该已经包含在标准库中了。
import sqlite3 as db
接下来,我们可以连接到一个现有的数据库,或者创建一个新的数据库,如果它不存在的话。
conn = db.connect('my_database.db')
作者图片
请注意,SQLite 引擎将数据库维护为扩展名为. db 的文件,因此上面的代码行将连接到一个名为 my_database.db 的文件,如果它存在于文件夹中的话。如果它不存在,将在您的计算机上自动创建一个名为 my_database.db 的文件,如上面的代码片段所示。
为了与数据库进行交互,我们现在必须创建一个游标。这就是我们将用来发布命令,允许我们查询或修改我们的数据库。
c = conn.cursor()
创建和修改表格
既然我们已经创建了数据库连接和游标,现在我们可以开始交互了。让我们在数据库中创建第一个表。
创建表格
我们对之前创建的游标c
使用方法execute
,并传入我们的 SQL 语句。
c.execute("CREATE TABLE employees (empid INTEGER PRIMARY KEY, firstname NVARCHAR(20), lastname NVARCHAR(20))")
上面的语句将创建一个名为 employees 的表,该表包含三列:empid、firstname 和 lastname。
您可以使用以下语句检查该表是否已成功创建。
c.execute("SELECT name FROM sqlite_master WHERE type='table';")
print(c.fetchall())
作者图片
上面的选择查询将显示数据库中的所有表。请注意,如果只有第一条语句,则不会输出查询结果。你必须使用c.fetchall()
来显示结果。
将数据插入表格
要填充该表,我们有几个选项。如果只插入几行,可以使用下面的 insert 语句向 employee 表中输入两行。
c.execute("INSERT INTO employees VALUES (12986,'Michael','Scott')")
c.execute("INSERT INTO employees VALUES (12987,'Dwight','Schrute')")
如果有许多行要输入到表中,可以考虑制作一个元组列表,并使用executemany()
命令。
new_employees = [(12987, 'Jim', 'Halpert'),
(12988, 'Pam', 'Beesly'),
(12989, 'Andy', 'Bernard'),
(12990, 'Kevin', 'Malone'),
(12991, 'Toby', 'Flenderson'),
(12992, 'Angela', 'Martin'),
(12993, 'Stanley', 'Hudson')]c.executemany('INSERT INTO employees VALUES (?, ?, ?)', new_employees)
请注意,我们已经用(?, ?, ?).这里的问号代表我们输入到表格中的三个项目的占位符。
由上的窗口拍照
让我们看看现在我们的表中有什么。我们可以在 execute 命令中使用 select 语句,就像我们以前做的那样。
作者图片
从输出中,我们可以看到我们所有的员工都被正确地输入到表中。万岁!
提交更改
我们已经对我们的数据库做了一些更改,但是它们还没有保存到数据库中!这些只是临时的修改,所以我们必须确保用下面的命令提交这些修改。
conn.commit()
否则,一旦我们关闭连接,更改将会丢失。
照片由 Afif Kusuma 在 Unsplash 上拍摄
最后,一旦完成,关闭光标和连接总是一个好习惯。我们可以用下面的命令做到这一点。
c.close()
conn.close()
SQLite via Pandas
你可以做的一件很酷的事情是同时使用 SQLite 和 Pandas。Pandas 有一个read_sql_query
方法,允许你以 Pandas dataframe 的形式返回数据。从那里,您可以更容易地操作 Pandas 中的数据。就我个人而言,我更喜欢把数据放在熊猫体内进行研究。
我们再次必须首先建立到数据库的连接。然后我们可以使用pd.read_sql_query
并将输出保存为名为df_employees.
的数据帧
#import library
import pandas as pdcon = db.connect('my_database.db')
df_employees = pd.read_sql_query('select * from employees', con)
作者的图片
现在它是一个 pandas 数据框架,您可以使用您常用的 Pandas 函数随意操作数据。
例如,假设 Stanley *(桌子上的最后一个人)*本来就不该被雇佣,所以我们需要把他从桌子上赶走。
df_new = df_employees[:-1]
作者图片
我们可以将新的 dataframe 写回 SQLite 并替换原始的 employee 表。为了写入 SQLite,我们在新的数据帧上使用方法to_sql()
。
df_new.to_sql("employees", con, if_exists="replace")
我们在这个方法中提供了三个参数:
- SQL 表的名称
- 与数据库的连接
- 如果表已经存在,该如何操作。“替换”将删除原始表格。“失败”将在 Python 中引发一个值错误。“追加”会将数据作为新行插入到表中
为了检查它是否如我们预期的那样工作,我可以再次查询这个表,看看 Stanley 是否已经被删除。它有!
pd.read_sql_query ('select * from employees', con)
作者图片
就像之前一样,一旦我们完成,让我们关闭连接。
con.close()
就是这样!SQLite 使用起来非常简单。如果你正在寻找一个好的数据库来练习 SQL 和/或 SQLite,你可以在这里下载 Chinook 数据库。关于 Chinook 数据库中数据的更多信息可以在这里找到。
感谢您的阅读!如果你有问题或者想讲一个 SQL 笑话,请在评论中告诉我。
医学家在 Unsplash 上拍摄的照片
为线性回归正确转换非线性数据的简单工具
原文:https://towardsdatascience.com/an-easy-tool-to-correctly-transform-non-linear-data-for-linear-regression-5fbe7f7bfe2f?source=collection_archive---------24-----------------------
使用 Tukey 和 Mosteller 膨胀规则将数据转换为线性关系
照片由戈兰·艾沃斯在 Unsplash 上拍摄
介绍
线性回归的两个重要假设是残差相互独立,并且这些误差中存在恒定的方差(也称为同方差)。这基本上意味着,当我们画回归线时,我们希望在整个直线的顶部和底部有相对相等数量的误差。
在许多情况下,我们想要为其建立模型的变量并不是线性相关的。当用线性回归模型拟合上述假设时,这导致了上述假设的失败。我们可以将变换函数应用于这些变量,以便使关系成为线性的。下图有助于我们决定对正在处理的非线性数据应用何种转换。
图基和莫斯特勒的膨胀规则图(也称为权力阶梯规则)
本文的目标是演示如何使用这个图表对数据进行转换。在我们开始举例之前,您可以这样阅读这个图表:
- 如果您看到的数据看起来像左上角的曲线,您可以尝试降低 x 的放大率和/或增加 y 的放大率。
- 如果你看到的数据看起来像右上角的曲线,你可以尝试增加 x 和/或 y 的力量。
- 如果您看到数据看起来像右下角的曲线,您可以尝试增加 x 的幂和/或减少 y 的幂。
- 如果你看到的数据看起来像左下角的曲线,你可以尝试降低 x 的幂和/或 y 的幂。
有趣的是,谷歌上关于这个规则的资源并不多(只有几千个搜索结果)。这是一个简单而强大的框架,用于快速确定要使用的转换,允许您在非线性数据上潜在地拟合线性模型。
生成数据
对于本文,我们将使用从以下 python 函数生成的数据:
def random_data(p=1, size=200, noise_sd = .1, q=1):
x = list(np.linspace(0.01, 1, size))
y = [(3 + 5 * x_val ** p + (random.normalvariate(0,noise_sd))) ** (1/q) for x_val in x]
return x, y
上面要理解的两个重要变量是p
和q
。变量p
表示应用于 x 值的功率,而q
表示应用于 y 值的功率的倒数
我们正在为 0.01 和 1 之间的x
生成size
值,每个值之间的间隔相等。我们增加 3,将 y 值缩放 5,以避免负数,因为负数会导致我们在本文中讨论的规则出现问题。最后,我们使用random.normalvariate(mean, sd)
给数据添加一点噪声,以使数据不完全符合我们想要演示的转换。
将 Tukey 和 Mosteller 膨胀规则应用于数据
让我们从上图右下角的数据分类示例开始。
p=2 和 q=1 时的数据散点图
当我们试图用最小二乘线性回归线拟合数据时,我们发现数据没有很好的线性关系。
p=2 和 q=1 的数据图,带回归线
该图告诉我们尝试降低 y 的幂或增加 x 的幂。下面我们看到,增加 x 的幂给我们带来了明显更好的线性关系和拟合。
p=2,q=1,x 转换为 x 的平方时的数据图
重要的是要记住考虑不同的变换可以有相同的形状。也就是说,数据可以用增加的 y 的幂生成,并且需要转换 y 变量以获得更好的线性拟合。
p=1 和 q=0.5 的数据图,带有线性回归线
在这种情况下,降低 y 的幂以获得更好的线性拟合是合适的。
p=1,q=0.5,y 转换为 y 的平方根时的数据图
结论
在上面的例子中,我们能够看到如何将 Tukey 和 Mosteller 膨胀规则应用于随机生成的数据(特别是符合图的右下角)。
值得注意的是,我们已经知道什么是正确的转换,因为我们在数据生成过程中选择了数据的参数。在实践中,您将不得不在图表的特定象限中尝试不同的转换,以找到最佳的转换。该图表旨在帮助您快速确定应该尝试哪些方法。
照片由莎伦·麦卡琴在 Unsplash 拍摄
另一个需要注意的是,这个简单的规则有一些限制。具体来说,它为转换数据时的前进方向提供了一个良好的起点,但不是最佳的转换。考虑使用 Box-Cox 变换来构建一个更加复杂和精确的框架(尽管 Tukey 和 Mosteller 规则作为一种近似做得相对较好,这种类型的精度不一定会对你的模型产生有意义的改进)。在 R 中比较这两个规则的一些代码可以在这里找到。
另一件要注意的事情是,很多这样的转换需要正变量值才能工作。因此,该规则可能无法应用于具有负值的数据,或者可能需要额外的工作来确保所有值都是正值。
感谢您花时间阅读这篇文章,我希望它能帮助您构建下一个模型。
一种简单的方法来替换熊猫数据帧中的值
原文:https://towardsdatascience.com/an-easy-way-to-replace-values-in-a-pandas-dataframe-2826bd34e59a?source=collection_archive---------2-----------------------
大蟒
使用内置的 Pandas 方法进行高级数据处理和字符串操作
我天才姐姐的封面艺术
Pandas 库被广泛用作数据处理和分析工具,用于从数据中清理和提取洞察力。
在处理数据时,作为预处理步骤的一部分,您通常需要编辑或移除某些数据。这可能涉及从现有的列创建新的列,或者修改现有的列,使它们适合更容易使用的框架。为此,Pandas 提供了多种方法,您可以使用这些方法来处理数据帧中所有数据类型的列。
在这一部分中,让我们具体看一下在数据帧中替换列中的值和子字符串。当您想要替换列中的每个值或者只想编辑值的一部分时,这将非常方便。
如果你想继续,在这里下载数据集并加载下面的代码。
import pandas as pd
df = pd.read_csv('WordsByCharacter.csv')
我们开始吧!
使用“替换”来编辑熊猫数据帧系列(列)中的字符串
Pandas 中的 replace 方法允许您在数据帧中的指定系列中搜索值,以找到可以更改的值或子字符串。首先,让我们快速地看一下如何对表中的“Film”列进行简单的更改,将“Of Of Of”改为“Of Of”。
# change "Of The" to "of the" - simple regex
df["Film"].replace("Of The", "of the") # won't work if you do this
df["Film"].replace("Of The", "of the", regex=True)
上面,我们所做的只是将我们正在寻找的子字符串作为第一个参数传递给replace
方法,然后将我们想要替换的值作为第二个参数传递给它。您将会看到,我们还必须通过regex=True
才能让操作运行。否则,replace
方法只会改变“属于”的列值,因为它只会匹配整个值。
通过匹配精确的字符串并提供您想要更改的整个值,您可以完成与上面相同的事情,如下所示。
df["Film"].replace("The Fellowship Of The Ring", "The Fellowship of the Ring")
这种方法的问题是,您必须逐个匹配值。也就是说,您需要传递您想要更改的每个值,以及您想要将其更改为什么值。在某些情况下,使用查找和替换匹配您定义的正则表达式的所有内容可能更容易。
然而,在您想要将不同的值更改为不同的替换值的情况下,您不必多次调用replace
方法。相反,您可以简单地传递一个字典,其中键是您想要搜索的列值,值是您想要用来替换原始值的值。下面可以看到一个简单的例子。
# you can do multiple replacements in within one call of the replace method by creating a mapping dictionary
# very scalable woo
replacement_mapping_dict = {
"The Fellowship Of The Ring": "The Fellowship of the Ring",
"The Return Of The King": "The Return of the King"
}
df["Film"].replace(replacement_mapping_dict)
之前,我们只是简单地传递了regex=True
,这样我们就可以在子字符串上进行匹配。让我们更进一步,写一些正则表达式来匹配。您会在“章节”栏中看到,章节名称前面有章节号和冒号。让我们做一点数据清理,并在replace
方法中使用 regex 删除这些数据。
# remove number number colon from "Chapter" - bit more complex regex example
# regex is just <= 3 repetitions of any numeric character (0-9) immediately followed by a colon and a space
df["Chapter"].replace(r"\d{,3}: ", "", regex=True)
我们所做的就是传递r"\d{,3}: "
来匹配一个重复三次或更少的数字字符,后跟一个冒号和一个空格(这将捕获“01:“”、“02:“”、…、“100:”等等)。每当在列值中发现这一点时,它就会从字符串中删除,因为我们传递的第二个参数是一个空字符串。
或者,如果您不想在每次调用replace
方法时都传递regex=True
,那么您可以通过下面的方法实现相同的结果:
# alternate way of doing the same thing (instead of having to pass regex=True at the end)
# if you had multiple things you want to replace you can put them all in a list
regex_list = [r"\d{,3}: ", r"The "]
df["Chapter"].replace(regex=regex_list, value="")
结果和之前的一样,只是有一些不同,使得这个方法更加清晰。首先,如果您想要匹配多个正则表达式,您可以在一个列表中定义它们,并在replace
方法中将其作为关键字参数传递。然后,您需要显式地传递另一个关键字参数value
来定义您想要的替换值。有人(包括你未来的自己)看着你的代码可能会很容易理解它做了什么,并对它进行扩展。
我才华横溢的哥哥的页脚艺术
仅此而已!
对于清理数据来说,这是一个相当常见的过程,所以我希望这个对 Pandas replace
方法的快速介绍对您自己的工作有用。熊猫能提供的还有很多,所以请随意查看我在上面的一些其他作品,以获得更多关于你可以轻松利用熊猫做什么的实际例子。
祝您的数据之旅好运!
**More by me:** - [Check for a Substring in a Pandas DataFrame](/check-for-a-substring-in-a-pandas-dataframe-column-4b949f64852?sk=bfb5bbab11ae45c47bfb316d931c3b56)
- C[onditional Selection and Assignment With .loc in Pandas](/conditional-selection-and-assignment-with-loc-in-pandas-2a5d17c7765b?sk=e5672d859a3964c1453a1c09edca22cf)
- [2 Easy Ways to Get Tables From a Website With Pandas](/2-easy-ways-to-get-tables-from-a-website-with-pandas-b92fc835e741?sk=9981ddaf0785a79be893b5a1dd3e03dd)
- [5 (and a half) Lines of Code for Understanding Your Data with Pandas](/5-and-a-half-lines-of-code-for-understanding-your-data-with-pandas-aedd3bec4c89?sk=7007a1ae248cf7ea4ef5fcd4af7ae72b)
- [Top 4 Repositories on GitHub to Learn Pandas](/top-4-repositories-on-github-to-learn-pandas-1008cb769f77?source=friends_link&sk=d3acc38062490a86ecb46875342224e6)
EDA 演练 Iris 数据集
原文:https://towardsdatascience.com/an-eda-walkthrough-the-iris-dataset-3f79246266c1?source=collection_archive---------35-----------------------
在拟合模型之前视觉探索虹膜数据集
这是一系列文章中的第一篇,在这篇文章中,我将通过不同的数据集展示建模前的景象。这些文章的目的是强调在为 ML 模型提供数据之前理解数据的重要性。
由迈克尔·泽兹奇在 Unsplash 上拍摄的照片
介绍
目标源于对常见的 ML 模型是如何构建的理解。回归、神经网络、支持向量机和决策树是以迭代和自我改进的方式利用线性代数基础的模型。这些模型的单个部分背后的数学相对简单,例如神经网络可以被认为是一系列较小的回归,决策树是每个节点上简单的是/否规则的集合,这些规则将数据分成越来越小的子部分。这些都只是对数学运算的模仿,这些运算可能在我们的大脑中以普通的方式进行。扩展决策树的例子,如果我们想把动物分成不同的组,我们会寻找共同的属性——腿的数量,皮毛的颜色,它是生活在陆地还是海洋等等。尽管这些信息已经呈现在我们面前,但我们可能看不到的是其他不太相关的属性,比如眼睛的颜色或反应速度。
当存在大量不相关的属性时,一些 ML 模型可能不够智能,无法分离出相关的属性。因此,重要的是,我们提供给模型的输入给它做出正确预测的最佳机会。因此需要 EDA——探索性数据分析。即使我们不从数据中删除特征(在通过模型运行数据之前,我们不一定要这样做), EDA 也能让我们初步了解数据的组成。当我们进入建模阶段时,我们知道哪些变量预计会在预测中大量涉及(通常通过回归中的较高系数显示),或者在分类问题中区分某些类别的困难可能在哪里。
也就是说,从 iris 数据集开始一系列机器学习似乎是唯一符合逻辑的。iris 数据集是 ML 历史上最古老和最著名的数据集之一。它由 R.A. Fisher 在 1936 年的一篇论文中用来引入聚类概念,并且通常是一个新的编码人员在分类问题上获得一些实践经验的最佳起点之一。
该数据集包含 150 行,平均分布在 3 种鸢尾花上。每个实例由 4 个值表征,其萼片长度、萼片宽度、花瓣长度和花瓣宽度,下面提供了一个示例。
作者图片
每个解释变量都是连续的,所以从散点图开始是合理的。
作者图片
从最初的观点来看,我们可以对这些情节做出一些结论。首先,在很大程度上,Setosa 花和 Versicolour 和 Virginica 之间有明显的区别,当我们观察花瓣的长度和宽度时,这一点尤其明显。在不使用机器学习的情况下,如果花瓣宽度小于 0.7 和/或花瓣长度小于 2,我们可能能够对 Setosa flower 进行分类(或者,如果您希望留出一些空间,因为我们不知道我们看不见的数据的确切性质,我们可以将边界设置为 2.5)。因此,我们应该可以轻松地用四个变量中的两个来完美地预测我们的 Setosa 花。这是我在评估我的模型时要考虑的特性之一。由于一个物种有如此大的差异,我预计特别是 Setosa 花的预测准确率为 100%,如果不是,这将需要进一步的调查。
作者图片
我们可能注意到的另一个特征是这个数据集中的复杂性来自于另外两个物种,云芝和海滨锦鸡儿。在所有 4 个变量中,没有一个变量能给我们提供任何明确的分离,这是可以理解的,因为如果我们确实看到了这一点,我们就不需要复杂的算法。花瓣宽度,作为一个单一的变量,似乎是最接近的,1.6 是一个潜在的边界数字。如果我们观察两个变量,穿过花瓣长度和宽度图的对角线是另一个粗略的估计值。
作者图片
当我们看箱线图时,我们注意到的第一件事是没有异常值。通过回顾散点图可以证实这一点,这告诉我们,我们不必对异常数据点的有效性进行任何抽查。我们也不希望任何非常不一致的数据点扭曲或分散我们的模型,虽然这不是我们在现实中遇到的典型数据集,但我们至少找到了一种方法来找到不寻常的值,并为未来的数据集提供了一个框架。
既然我们已经确定了濑户花分类的区别,我们的注意力应该转移到其他两个。一个有趣的观察是,特别是当观察萼片的长度和宽度时,似乎很难区分云芝和海滨锦葵。在这两种情况下,Virginica 似乎具有更高的方差,但是用非常相似的方法,这两个变量几乎是不可区分的。
事实上,唯一的变量似乎显示任何区别是花瓣长度和宽度,这证实了我们的观察散点图。Versicolor 和 Virginica 花的花瓣长度和宽度的平均值似乎相差很远,虽然它们在分布的末端有一些重叠值,但中间 50%的数据明显不同。
从几个图表来看,这些是我进入 ML 工作流建模阶段的最初想法。在这个数据集中,我特别关注我的测试数据中 Setosa 预测的准确性。我也对萼片长度和宽度的系数感兴趣,因为我不期望它们非常高,并且比花瓣长度和宽度小很多。当评估我的模型时,我可能还会重新运行一个算法,仅将花瓣长度和宽度作为我的输入变量,因为这些似乎提供了准确预测的最佳机会,我想知道萼片测量实际上是帮助还是阻碍了我的模型的性能。
将两个优化器结合起来,形成一个训练模型的强大方法
原文:https://towardsdatascience.com/an-efficient-hybrid-algorithm-to-solve-nonlinear-least-squares-problems-262801bcfe25?source=collection_archive---------8-----------------------
实践教程
当 Levenberg-Marquardt 遇到准牛顿。是的,我们用 Python 从头开始构建它!
由约书亚·阿拉贡在 Unsplash 上拍摄的照片
**Table of Contents** (read till the end to see how you can get the complete python code of this story)· [Seeing the Big Picture](#48e0)
· [Defining The Problem](#e640)
· [A Hybrid Method](#d4e9)
∘ [Objective Function](#0b95)
∘ [General Algorithm](#d56d)
∘ [Levenberg-Marquardt Step](#9602)
∘ [Quasi-Newton Step](#3fca)
· [Implementation](#d1e8)
· [Conclusion](#440b)
看到全局
在之前的文章中,我们已经看到了梯度下降和共轭梯度算法的作用,作为两种最简单的优化方法。我们实现了线搜索来搜索目标函数的优化方向。
还有另一种生成步骤的方法,称为信任区域。信赖域方法在当前迭代周围定义一个区域,在该区域内,它们相信模型是目标函数的适当表示,然后选择步长作为该区域中模型的近似极小值。实际上,与线搜索不同,它们同时选择方向和步长。
还有很多其他优化方法,如牛顿法和拟牛顿法。在本文中,我们将使用 Levenberg-Marquardt 和拟牛顿法的混合,利用信赖域进行步长选择。此外,这篇文章带来了一个不同的问题。我们将得到一个数据集和数据的非线性模型,然后找到模型的最佳优化参数,而不是找到目标函数的优化器。优化的参数是由那些给出最小残差平方的人定义的。有些人可能称之为曲线拟合问题。
让我们导入一些库。
定义问题
如下创建一个虚构的数据集。它有 11 个观察值和 2 个特征,第一个特征相当于第二个特征的索引。
t y
------------------
[[ 0.0000 0.0000]
[ 2.0000 3.5500]
[ 4.0000 3.8200]
[ 6.0000 2.9800]
[ 8.0000 2.3200]
[10.0000 1.4800]
[12.0000 1.0200]
[14.0000 0.8100]
[16.0000 0.4100]
[18.0000 0.4200]
[20.0000 0.1500]]Data shape: (11, 2)
将数据可视化为卡特修斯平面中的点( t , y ) = ( tᵢ , yᵢ ),其中 i = 1,2,…,11。
图片由作者
我们立即意识到数据没有线性趋势(这里的点(0,0)是而不是一个异常值)。因此,我们使用的模型也是非线性的。相反,我们将使用两个指数函数的线性组合,根据定义,它被声明为
如前所述,参数 x = [ x₁ , x₂ , x₃ , x₄ ,将使用 Levenberg-Marquardt (LM)和拟牛顿(QN)的混合方法进行估计。
混合方法
目标函数
图片由矢量-市场在平面图标上显示
总的来说,我们要为一组 m 数据点( tᵢ 、 yᵢ )建立一个模型 M ( x 、 t )。为此,目标函数的具体定义是必要的。对于最小二乘问题,这个目标函数是每个数据点残差的平方和。数据点的残差由实际数据到模型预测的距离来定义,即通过用实际数据点减去该点的模型预测来定义。从数学上讲,第 i 个数据点的残差为
或者以向量的形式
由于目标函数是每个数据点残差的平方和,因此可以写成
为方便推导 F ,附上上述系数。
设ǁ⋅ǁ是向量的最大范数的符号。我们的任务是找到使 F 最小的 x 。为此,我们将找到 x ,其中ǁ g ( x )ǁ ≈ 0,其中g=*f’*是 F 的一阶导数。衍生
w.r.t .每个 xⱼ 利用链式法则,我们得到
定义雅可比矩阵
g 的值可以计算如下
下面这个 python 函数,除了返回 g 之外,还返回 J ,后面会派上用场。
一般算法
由 becris 在平面图标上拍摄的图像
设 x* 为残差平方和的极小值。最小二乘问题可以用一般的最优化方法来解决,但我们将提出更有效的特殊方法。1988 年,Madsen [1]提出了一种混合方法,该方法将 LM 方法(二次收敛,如果 F ( x* ) = 0,否则线性收敛)与 QN 方法相结合,即使 F ( x* ) ≠ 0,该方法也能给出超线性收敛。
在信赖域方法中,算法在当前迭代 x 的邻域中生成 F 行为的信任模型 L ,
其中 h 是要采取的步骤。我们假设我们知道一个正数δ,使得该模型在半径为δ、以 x 为中心的球内足够精确,并且该算法将步长确定为
在阻尼型中,步长确定为
其中阻尼参数 μ ≥ 0。该术语
是用来惩罚大步流星的。
从现在开始,我们将开始迭代。因此,我们将引入一个索引 k ,这意味着所讨论的变量是针对第 k 次迭代的。例如, xₖ 是 x 在第 k 次迭代的值,如此类推fₖ=f(xₖ)gₖ=g(xₖ)jₖ=j(【t54
在迭代开始之前,重要的是初始化阻尼参数 μ = μ ₀和海森近似 B ₀(海森在迭代 x 时由f】’(x)定义,QN 方法使用其近似 B )。
B ₀的合理选择是对称正定矩阵 I ,即单位矩阵。 μ ₀的选择应与中元素的大小有关
例如通过让
其中 aᵢᵢ ⁰是 A ₀的第 i 个对角线分量, τ 由用户选择。在本文中,我们将设置 τ = 1 × 10⁻。
下面这个 python 函数,除了返回 μ ₀,还返回 A ₀,后面会派上用场。
在初始化了 μ ₀和 B ₀之后,迭代从 LM 方法的一系列步骤开始。如果性能指示 F ( x* )显著非零,那么我们切换到 QN 方法以获得更好的性能。我们可能会得到一个指示,即最好切换回 LM 方法,因此也有一个机制,我们将在后面介绍。迭代继续进行,直到满足以下停止标准之一:
- 目标函数的梯度的范数足够接近零,也就是说,
- 步长的范数满足
- 采取的步骤数是 1000
本文将 ε ₁和 ε ₂设为 1 × 10⁻⁵.
在每一步之后,无论是通过 LM 还是 QN 方法, Bₖ 通过首先定义来更新
如果
然后更新 Bₖ 由
其中 vₖ = Bₖhₖ 。否则, Bₖ 不变,即 Bₖ₊₁ = Bₖ 。
由 LM 或 QN 方法找到的新的xₖ₊₁=xₖ+hₖ然后被传递到下一次迭代。整个过程可以写成下面的代码。
现在,让我们来看看每一步的细节。上面的LMstep()
和QNstep()
函数是怎么回事?
勒文伯格-马夸特步骤
在混合迭代开始时,首先使用 LM 方法。在第 k 次迭代时,通过求解找到步骤 hₖ
然后计算
其中 Fₖ₊₁ 就是f(xₖ+hₖ)。
然后我们考虑两种情况:
- 如果ϱt80】0,这意味着迭代成功,我们可以更新xₖ₊₁=xₖ+hₖ。此时,我们需要检查 F ( x* )是否远离零,即通过检查:如果ǁgₖǁ<0.02⋅fₖ连续三次迭代成功,那么我们就换成 QN 法进行下一次迭代。另外,更新
2.如果 ϱ ≤ 0,则迭代不成功,我们不会更新 xₖ ,即 xₖ₊₁ = xₖ 。对于这种情况,更新 μₖ₊₁ = μₖν 和 ν := 2 ν 。
上面说的 μ 的更新方法是尼尔森开发的。我们也有另一个由马夸特的变化,如下所示。
整个 LM 步骤如下所示。请注意,在下面的代码中,我们正在传递δₖ,这是 QN 步骤将使用的信赖域半径,以防我们在未来的迭代中将步骤计算方法更改为 QN。这里我们不用δₖ。
准牛顿步
由于 QN 方法使用信赖域进行步长计算,因此在开始使用 QN 方法时,初始化信赖域半径很重要
其中 hₗₘ 是前一个 LM 步获得的步。但是不要担心,这个初始化部分是不需要的,因为我们总是在 LM 和 QN 步骤中计算δₖ。如你所见,上面的最后一个公式已经嵌入到LMstep()
函数行 14 中。
在第 k 次迭代时,通过求解找到步骤 hₖ
如果ǁhₖǁ>δₖ,那么将 hₖ 的长度减少为δₖ,即通过设置
δₖ然后在 ϱ 的几个条件下被更新,其使用与我们在 LM 步骤中使用的公式相同的公式计算:
- 如果ϱt94】0.25,则设定δₖ₊₁=δₖ/2
- 如果ϱt95】0.75,则设定δₖ₊₁= max {δₖ,3 ǁ hₖ ǁ}
- 否则,δₖ₊₁=δₖ
接下来,我们考虑两种情况:
- 如果fₖ₊₁≤(1+δ)fₖ和ǁgₖ₊₁ǁ<ǁgₖǁ,或者fₙt34<fₙ,那么迭代成功,我们可以更新 x 此时,我们专注于使 g 更接近零,因此我们接受 F 的值稍微增加,例如小至 δ = √ε 乘以先前的 F ,其中 ε 是机器ε。
- 否则迭代视为失败, xₖ 不会更新,即 xₖ₊₁ = xₖ 。
如果梯度下降得不够快,即ǁgₖ₊₁ǁ≥ǁgₖǁ,那么我们转到 LM 步进行下一次迭代。
整个 QN 步骤可以如下所示。注意,在下面的代码中,我们像在 LM 步骤中一样计算 ϱ 。
履行
我们现在准备应用我们的知识来解决本文开头定义的问题。我们将在三种不同的情况下改变初始点:
- ₀ = [-1,1,-10,10]
- ₀ = [-4,1,2,-3]
- ₀ = [0,0,0,0]
但首先,让我们引入一个 python 函数MakeAnimation()
来动画化算法的学习过程。
场景 1
Iteration:1 x = [-1.0000 0.9500 -10.0000 9.9997],
gradient = 64932772695986634752.0000, step = LM
Iteration:2 x = [-1.0000 0.9001 -10.0000 9.9994],
gradient = 8871075343566318592.0000, step = LM
Iteration:3 x = [-1.0000 0.8510 -10.0000 9.9992],
gradient = 1250145055141384192.0000, step = LM
Iteration:4 x = [-1.0000 0.8050 -10.0000 9.9990],
gradient = 199964648437467488.0000, step = LM
Iteration:5 x = [-1.0000 0.7686 -10.0000 9.9988],
gradient = 46950703393293552.0000, step = LM
Iteration:6 x = [-1.0000 0.7454 -10.0000 9.9987],
gradient = 18613190948807260.0000, step = LM
Iteration:7 x = [-1.0000 0.7283 -10.0000 9.9986],
gradient = 9421138350386658.0000, step = LM
Iteration:8 x = [-1.0000 0.7127 -10.0000 9.9985],
gradient = 5067642599353893.0000, step = LM
Iteration:9 x = [-1.0000 0.6974 -10.0000 9.9984],
gradient = 2761173975265880.5000, step = LM
Iteration:10 x = [-1.0000 0.6822 -10.0000 9.9983],
gradient = 1508437660486741.0000, step = LM
Iteration:11 x = [-1.0000 0.6670 -10.0000 9.9983],
gradient = 824513384402736.2500, step = LM
Iteration:12 x = [-1.0000 0.6518 -10.0000 9.9982],
gradient = 450734053994430.5000, step = LM
Iteration:13 x = [-1.0000 0.6366 -10.0000 9.9981],
gradient = 246409971021028.8438, step = LM
Iteration:14 x = [-1.0000 0.6214 -10.0000 9.9980],
gradient = 134711382454059.4531, step = LM
Iteration:15 x = [-1.0000 0.6062 -10.0000 9.9980],
gradient = 73647395414745.6094, step = LM
Iteration:16 x = [-1.0000 0.5909 -10.0000 9.9979],
gradient = 40264084923738.5469, step = LM
Iteration:17 x = [-1.0000 0.5757 -10.0000 9.9978],
gradient = 22013352246245.9766, step = LM
Iteration:18 x = [-1.0000 0.5605 -10.0000 9.9977],
gradient = 12035471978657.0332, step = LM
Iteration:19 x = [-1.0000 0.5452 -10.0000 9.9976],
gradient = 6580356674017.7891, step = LM
Iteration:20 x = [-1.0000 0.5299 -10.0000 9.9976],
gradient = 3597874150520.1475, step = LM
Iteration:21 x = [-1.0000 0.5146 -10.0000 9.9975],
gradient = 1967223429070.2634, step = LM
Iteration:22 x = [-1.0000 0.4993 -10.0000 9.9974],
gradient = 1075656653534.5968, step = LM
Iteration:23 x = [-1.0000 0.4840 -10.0000 9.9973],
gradient = 588175745878.2034, step = LM
Iteration:24 x = [-1.0000 0.4687 -10.0000 9.9973],
gradient = 321629128815.2425, step = LM
Iteration:25 x = [-1.0000 0.4534 -10.0000 9.9972],
gradient = 175881428072.9430, step = LM
Iteration:26 x = [-1.0000 0.4380 -10.0000 9.9971],
gradient = 96183963098.1861, step = LM
Iteration:27 x = [-1.0000 0.4226 -10.0000 9.9970],
gradient = 52602379508.8333, step = LM
Iteration:28 x = [-1.0000 0.4072 -10.0000 9.9969],
gradient = 28769372395.6593, step = LM
Iteration:29 x = [-1.0000 0.3918 -10.0000 9.9969],
gradient = 15735488020.7650, step = LM
Iteration:30 x = [-1.0000 0.3763 -10.0000 9.9968],
gradient = 8607119032.2862, step = LM
Iteration:31 x = [-1.0000 0.3609 -10.0000 9.9967],
gradient = 4708326165.4597, step = LM
Iteration:32 x = [-1.0000 0.3454 -10.0000 9.9966],
gradient = 2575789155.9012, step = LM
Iteration:33 x = [-1.0000 0.3298 -10.0000 9.9965],
gradient = 1409268155.2911, step = LM
Iteration:34 x = [-1.0000 0.3142 -10.0000 9.9965],
gradient = 771119669.0625, step = LM
Iteration:35 x = [-1.0000 0.2986 -10.0000 9.9964],
gradient = 421988746.9021, step = LM
Iteration:36 x = [-1.0000 0.2829 -10.0000 9.9963],
gradient = 230960695.7163, step = LM
Iteration:37 x = [-1.0000 0.2672 -10.0000 9.9962],
gradient = 126427578.6262, step = LM
Iteration:38 x = [-1.0000 0.2514 -10.0000 9.9961],
gradient = 69218466.4778, step = LM
Iteration:39 x = [-1.0000 0.2356 -10.0000 9.9960],
gradient = 37904445.7661, step = LM
Iteration:40 x = [-1.0000 0.2197 -10.0000 9.9960],
gradient = 20761560.5190, step = LM
Iteration:41 x = [-1.0000 0.2036 -10.0000 9.9959],
gradient = 11374897.3379, step = LM
Iteration:42 x = [-1.0000 0.1875 -10.0000 9.9958],
gradient = 6234064.0376, step = LM
Iteration:43 x = [-1.0000 0.1713 -10.0000 9.9957],
gradient = 3417848.7040, step = LM
Iteration:44 x = [-1.0000 0.1550 -10.0000 9.9956],
gradient = 1874634.8523, step = LM
Iteration:45 x = [-1.0000 0.1385 -10.0000 9.9955],
gradient = 1028702.8782, step = LM
Iteration:46 x = [-1.0000 0.1218 -10.0000 9.9954],
gradient = 564808.7854, step = LM
Iteration:47 x = [-1.0000 0.1049 -10.0000 9.9953],
gradient = 310298.2705, step = LM
Iteration:48 x = [-1.0000 0.0877 -10.0000 9.9952],
gradient = 170587.3249, step = LM
Iteration:49 x = [-1.0000 0.0703 -10.0000 9.9951],
gradient = 93845.4326, step = LM
Iteration:50 x = [-1.0000 0.0524 -10.0000 9.9950],
gradient = 51660.5782, step = LM
Iteration:51 x = [-1.0000 0.0341 -10.0000 9.9949],
gradient = 28451.8639, step = LM
Iteration:52 x = [-1.0000 0.0153 -10.0000 9.9947],
gradient = 15670.8490, step = LM
Iteration:53 x = [-0.9999 -0.0043 -10.0000 9.9946],
gradient = 8624.8546, step = LM
Iteration:54 x = [-0.9999 -0.0246 -10.0000 9.9944],
gradient = 4736.1605, step = LM
Iteration:55 x = [-0.9998 -0.0461 -10.0000 9.9941],
gradient = 2587.7373, step = LM
Iteration:56 x = [-0.9996 -0.0687 -10.0000 9.9939],
gradient = 1399.9325, step = LM
Iteration:57 x = [-0.9993 -0.0928 -10.0000 9.9936],
gradient = 743.3551, step = LM
Iteration:58 x = [-0.9987 -0.1184 -10.0001 9.9931],
gradient = 381.2687, step = LM
Iteration:59 x = [-0.9976 -0.1456 -10.0001 9.9925],
gradient = 183.0379, step = LM
Iteration:60 x = [-0.9952 -0.1736 -10.0002 9.9917],
gradient = 76.6425, step = LM
Iteration:61 x = [-0.9894 -0.1972 -10.0005 9.9901],
gradient = 26.4382, step = LM
Iteration:62 x = [-0.9744 -0.2105 -10.0012 9.9871],
gradient = 6.8472, step = LM
Iteration:63 x = [-0.9336 -0.2136 -10.0030 9.9797],
gradient = 4.4702, step = LM
Iteration:64 x = [-0.8269 -0.2088 -10.0070 9.9631],
gradient = 4.2573, step = LM
Iteration:65 x = [-0.6379 -0.1953 -10.0103 9.9430],
gradient = 6.5882, step = LM
Iteration:66 x = [-0.5576 -0.1832 -10.0023 9.9499],
gradient = 1.3240, step = LM
Iteration:67 x = [-0.5559 -0.1827 -9.9933 9.9681],
gradient = 0.0227, step = LM
Iteration:68 x = [-0.5544 -0.1829 -10.0000 9.9888],
gradient = 0.0087, step = LM
Iteration:69 x = [-0.5527 -0.1832 -10.0389 10.0305],
gradient = 0.0117, step = LM
Iteration:70 x = [-0.5482 -0.1843 -10.1523 10.1442],
gradient = 0.0548, step = LM
Iteration:71 x = [-0.5372 -0.1868 -10.4402 10.4325],
gradient = 0.2795, step = LM
Iteration:72 x = [-0.5173 -0.1916 -11.0244 11.0175],
gradient = 1.0133, step = LM
Iteration:73 x = [-0.5025 -0.1958 -11.5877 11.5812],
gradient = 0.7806, step = LM
Iteration:74 x = [-0.4883 -0.2000 -12.1891 12.1835],
gradient = 0.8407, step = LM
Iteration:75 x = [-0.4787 -0.2030 -12.6707 12.6659],
gradient = 0.4784, step = LM
Iteration:76 x = [-0.4704 -0.2057 -13.1195 13.1156],
gradient = 0.4040, step = LM
Iteration:77 x = [-0.4656 -0.2073 -13.4055 13.4021],
gradient = 0.1502, step = LM
Iteration:78 x = [-0.4629 -0.2083 -13.5758 13.5728],
gradient = 0.0525, step = LM
Iteration:79 x = [-0.4622 -0.2085 -13.6183 13.6154],
gradient = 0.0030, step = LM
Iteration:80 x = [-0.4622 -0.2085 -13.6218 13.6188],
gradient = 0.0000, step = LM
Iteration:81 x = [-0.4622 -0.2085 -13.6218 13.6188],
gradient = 0.0000, step = LMFinal estimated parameters: [-0.4622 -0.2085 -13.6218 13.6188]
视频作者作者
该算法运行 81 次迭代,产生参数估计结果 x* = [-0.46,-0.21,-13.62,13.62],ǁ g ( x* )ǁ ≈ 0。换句话说,该算法在满足停止准则ǁ gₖ ǁ ≤ ε ₁的情况下成功收敛。还可以看出,该算法在给定数据的曲线拟合中总是使用 LM 方法。这意味着每连续 3 次迭代,就有一次迭代 xₖ 满足ǁgₖǁ≥0.02⋅fₖ。
场景 2
Iteration:1 x = [-4.0000 0.9500 2.0000 -2.9990],
gradient = 5843944048763837440.0000, step = LM
Iteration:2 x = [-4.0000 0.9001 2.0000 -2.9981],
gradient = 798393836723220864.0000, step = LM
Iteration:3 x = [-4.0000 0.8510 2.0000 -2.9973],
gradient = 112511464378970688.0000, step = LM
Iteration:4 x = [-4.0000 0.8050 2.0000 -2.9965],
gradient = 17995869734728704.0000, step = LM
Iteration:5 x = [-4.0000 0.7687 2.0000 -2.9959],
gradient = 4224958744295105.0000, step = LM
Iteration:6 x = [-4.0000 0.7454 2.0000 -2.9955],
gradient = 1674832246409442.5000, step = LM
Iteration:7 x = [-4.0000 0.7283 2.0000 -2.9952],
gradient = 847705835813273.6250, step = LM
Iteration:8 x = [-4.0000 0.7128 2.0000 -2.9950],
gradient = 455980000478269.1875, step = LM
Iteration:9 x = [-4.0000 0.6975 2.0000 -2.9947],
gradient = 248446618239291.2812, step = LM
Iteration:10 x = [-4.0000 0.6823 2.0000 -2.9945],
gradient = 135727074063636.5469, step = LM
Iteration:11 x = [-4.0000 0.6671 2.0000 -2.9942],
gradient = 74188516827416.2656, step = LM
Iteration:12 x = [-4.0000 0.6519 2.0000 -2.9940],
gradient = 40556383042130.0234, step = LM
Iteration:13 x = [-4.0000 0.6367 2.0000 -2.9937],
gradient = 22171597557325.9102, step = LM
Iteration:14 x = [-4.0000 0.6215 2.0000 -2.9934],
gradient = 12121123175141.8398, step = LM
Iteration:15 x = [-4.0000 0.6063 2.0000 -2.9932],
gradient = 6626677353862.0400, step = LM
Iteration:16 x = [-4.0000 0.5910 2.0000 -2.9929],
gradient = 3622898207455.6821, step = LM
Iteration:17 x = [-4.0000 0.5758 2.0000 -2.9927],
gradient = 1980725783949.0017, step = LM
Iteration:18 x = [-4.0000 0.5606 2.0000 -2.9924],
gradient = 1082932002365.9087, step = LM
Iteration:19 x = [-4.0000 0.5453 2.0000 -2.9922],
gradient = 592089574010.1783, step = LM
Iteration:20 x = [-4.0000 0.5300 2.0000 -2.9919],
gradient = 323730717048.8542, step = LM
Iteration:21 x = [-4.0000 0.5148 2.0000 -2.9916],
gradient = 177007495788.6531, step = LM
Iteration:22 x = [-4.0000 0.4995 2.0000 -2.9914],
gradient = 96785827387.7305, step = LM
Iteration:23 x = [-4.0000 0.4842 2.0000 -2.9911],
gradient = 52923125898.6776, step = LM
Iteration:24 x = [-4.0000 0.4688 2.0000 -2.9909],
gradient = 28939714442.5817, step = LM
Iteration:25 x = [-4.0000 0.4535 2.0000 -2.9906],
gradient = 15825580540.4678, step = LM
Iteration:26 x = [-4.0000 0.4381 2.0000 -2.9903],
gradient = 8654531799.0783, step = LM
Iteration:27 x = [-4.0000 0.4228 2.0000 -2.9901],
gradient = 4733127210.2534, step = LM
Iteration:28 x = [-4.0000 0.4074 2.0000 -2.9898],
gradient = 2588665603.7885, step = LM
Iteration:29 x = [-4.0000 0.3919 2.0000 -2.9895],
gradient = 1415891078.6356, step = LM
Iteration:30 x = [-4.0000 0.3765 2.0000 -2.9893],
gradient = 774485568.1282, step = LM
Iteration:31 x = [-4.0000 0.3610 2.0000 -2.9890],
gradient = 423672773.1613, step = LM
Iteration:32 x = [-4.0000 0.3455 2.0000 -2.9887],
gradient = 231785640.8201, step = LM
Iteration:33 x = [-4.0000 0.3300 2.0000 -2.9885],
gradient = 126819882.7775, step = LM
Iteration:34 x = [-4.0000 0.3144 2.0000 -2.9882],
gradient = 69396974.7767, step = LM
Iteration:35 x = [-4.0000 0.2988 2.0000 -2.9879],
gradient = 37980046.8186, step = LM
Iteration:36 x = [-4.0000 0.2831 2.0000 -2.9876],
gradient = 20789502.5936, step = LM
Iteration:37 x = [-4.0000 0.2674 2.0000 -2.9874],
gradient = 11382078.3240, step = LM
Iteration:38 x = [-4.0000 0.2516 2.0000 -2.9871],
gradient = 6233151.4407, step = LM
Iteration:39 x = [-4.0000 0.2358 2.0000 -2.9868],
gradient = 3414510.4438, step = LM
Iteration:40 x = [-4.0000 0.2198 2.0000 -2.9865],
gradient = 1871192.9516, step = LM
Iteration:41 x = [-4.0000 0.2038 2.0000 -2.9862],
gradient = 1025947.0256, step = LM
Iteration:42 x = [-4.0000 0.1877 2.0000 -2.9859],
gradient = 562874.5612, step = LM
Iteration:43 x = [-4.0000 0.1714 2.0000 -2.9856],
gradient = 309077.3735, step = LM
Iteration:44 x = [-4.0000 0.1550 2.0000 -2.9853],
gradient = 169908.6045, step = LM
Iteration:45 x = [-4.0000 0.1384 2.0000 -2.9850],
gradient = 93547.0603, step = LM
Iteration:46 x = [-4.0000 0.1215 2.0000 -2.9847],
gradient = 51612.8671, step = LM
Iteration:47 x = [-4.0000 0.1044 2.0000 -2.9843],
gradient = 28559.4009, step = LM
Iteration:48 x = [-4.0000 0.0869 2.0000 -2.9839],
gradient = 15867.2252, step = LM
Iteration:49 x = [-4.0000 0.0688 2.0000 -2.9835],
gradient = 8865.7762, step = LM
Iteration:50 x = [-4.0000 0.0500 2.0000 -2.9830],
gradient = 4993.1844, step = LM
Iteration:51 x = [-4.0000 0.0303 2.0000 -2.9825],
gradient = 2843.2836, step = LM
Iteration:52 x = [-4.0000 0.0092 2.0000 -2.9818],
gradient = 1643.5749, step = LM
Iteration:53 x = [-4.0000 -0.0138 2.0000 -2.9809],
gradient = 969.1664, step = LM
Iteration:54 x = [-4.0000 -0.0397 2.0001 -2.9798],
gradient = 585.9656, step = LM
Iteration:55 x = [-4.0000 -0.0695 2.0001 -2.9782],
gradient = 364.7187, step = LM
Iteration:56 x = [-4.0000 -0.1047 2.0003 -2.9760],
gradient = 233.9465, step = LM
Iteration:57 x = [-4.0000 -0.1465 2.0005 -2.9730],
gradient = 154.2224, step = LM
Iteration:58 x = [-4.0000 -0.1954 2.0008 -2.9690],
gradient = 103.9455, step = LM
Iteration:59 x = [-4.0000 -0.2516 2.0014 -2.9638],
gradient = 71.2219, step = LM
Iteration:60 x = [-4.0000 -0.3152 2.0023 -2.9571],
gradient = 49.3390, step = LM
Iteration:61 x = [-4.0000 -0.3865 2.0037 -2.9486],
gradient = 34.3994, step = LM
Iteration:62 x = [-4.0000 -0.4659 2.0060 -2.9378],
gradient = 24.0583, step = LM
Iteration:63 x = [-3.9999 -0.5540 2.0095 -2.9242],
gradient = 16.8404, step = LM
Iteration:64 x = [-3.9999 -0.6510 2.0148 -2.9069],
gradient = 11.7791, step = LM
Iteration:65 x = [-3.9998 -0.7574 2.0228 -2.8848],
gradient = 8.2216, step = LM
Iteration:66 x = [-3.9998 -0.8733 2.0348 -2.8567],
gradient = 5.7186, step = LM
Iteration:67 x = [-3.9996 -0.9990 2.0522 -2.8209],
gradient = 3.9571, step = LM
Iteration:68 x = [-3.9995 -1.1349 2.0768 -2.7754],
gradient = 2.7180, step = LM
Iteration:69 x = [-3.9992 -1.2813 2.1103 -2.7183],
gradient = 1.8476, step = LM
Iteration:70 x = [-3.9987 -1.4390 2.1533 -2.6485],
gradient = 1.2392, step = LM
Iteration:71 x = [-3.9980 -1.6079 2.2038 -2.5681],
gradient = 0.8190, step = LM
Iteration:72 x = [-3.9968 -1.7865 2.2547 -2.4842],
gradient = 0.5357, step = LM
Iteration:73 x = [-3.9949 -1.9699 2.2945 -2.4089],
gradient = 0.3513, step = LM
Iteration:74 x = [-3.9920 -2.1517 2.3148 -2.3524],
gradient = 0.2345, step = LM
Iteration:75 x = [-3.9878 -2.3283 2.3156 -2.3155],
gradient = 0.1603, step = LM
Iteration:76 x = [-3.9863 -2.3635 2.3124 -2.3081],
gradient = 0.1487, step = QN
Iteration:77 x = [-3.9803 -2.4682 2.2972 -2.2863],
gradient = 0.1189, step = QN
Iteration:78 x = [-3.9577 -2.7803 2.2395 -2.2211],
gradient = 0.0613, step = QN
Iteration:79 x = [-3.9319 -3.0541 2.1785 -2.1639],
gradient = 0.0344, step = QN
Iteration:80 x = [-3.9000 -3.3271 2.1135 -2.1068],
gradient = 0.0193, step = QN
Iteration:81 x = [-3.8784 -3.4807 2.0776 -2.0748],
gradient = 0.0140, step = QN
Iteration:82 x = [-3.8657 -3.5574 2.0604 -2.0588],
gradient = 0.0119, step = QN
Iteration:83 x = [-3.8510 -3.6338 2.0437 -2.0428],
gradient = 0.0101, step = QN
Iteration:84 x = [-3.8335 -3.7098 2.0276 -2.0269],
gradient = 0.0086, step = QN
Iteration:85 x = [-3.8227 -3.7473 2.0198 -2.0191],
gradient = 0.0080, step = QN
Iteration:86 x = [-3.8090 -3.7840 2.0123 -2.0114],
gradient = 0.0074, step = QN
Iteration:87 x = [-3.7911 -3.8190 2.0053 -2.0041],
gradient = 0.0073, step = QN
Iteration:88 x = [-3.7664 -3.8489 1.9996 -1.9979],
gradient = 0.0076, step = QN
Iteration:89 x = [-3.7581 -3.8559 1.9998 -1.9981],
gradient = 0.0077, step = LM
Iteration:90 x = [-3.7330 -3.8766 2.0004 -1.9986],
gradient = 0.0081, step = LM
Iteration:91 x = [-3.6535 -3.9361 2.0028 -2.0011],
gradient = 0.0096, step = LM
Iteration:92 x = [-3.3739 -4.0948 2.0180 -2.0161],
gradient = 0.0168, step = LM
Iteration:93 x = [-1.8970 -4.4431 2.1579 -2.1553],
gradient = 0.3573, step = LM
Iteration:94 x = [-1.8970 -4.4431 2.1579 -2.1553],
gradient = 0.3573, step = LM
Iteration:95 x = [-1.8970 -4.4431 2.1579 -2.1553],
gradient = 0.3573, step = LM
Iteration:96 x = [-1.8970 -4.4431 2.1579 -2.1553],
gradient = 0.3573, step = LM
Iteration:97 x = [-0.4821 -4.4514 2.3330 -2.2979],
gradient = 12.9667, step = LM
Iteration:98 x = [-0.4821 -4.4514 2.3330 -2.2979],
gradient = 12.9667, step = LM
Iteration:99 x = [-0.4821 -4.4514 2.3330 -2.2979],
gradient = 12.9667, step = LM
Iteration:100 x = [-0.4821 -4.4514 2.3330 -2.2979],
gradient = 12.9667, step = LM
Iteration:101 x = [-0.4821 -4.4514 2.3330 -2.2979],
gradient = 12.9667, step = LM
Iteration:102 x = [-0.3361 -4.4514 2.3517 -2.2985],
gradient = 23.2634, step = LM
Iteration:103 x = [-0.3361 -4.4514 2.3517 -2.2985],
gradient = 23.2634, step = LM
Iteration:104 x = [-0.0195 -4.4514 2.3844 -2.3000],
gradient = 141.8487, step = LM
Iteration:105 x = [-0.0542 -4.4514 2.5491 -2.3129],
gradient = 2.7825, step = LM
Iteration:106 x = [-0.0622 -4.4515 2.7408 -2.3468],
gradient = 3.8567, step = LM
Iteration:107 x = [-0.0733 -4.4516 3.1240 -2.5063],
gradient = 5.6536, step = LM
Iteration:108 x = [-0.0887 -4.4519 3.7063 -3.0302],
gradient = 7.1668, step = LM
Iteration:109 x = [-0.1056 -4.4518 4.4259 -4.0061],
gradient = 6.3086, step = LM
Iteration:110 x = [-0.1190 -4.4484 5.0608 -4.9286],
gradient = 3.4276, step = LM
Iteration:111 x = [-0.1236 -4.4311 5.3256 -5.3076],
gradient = 0.7579, step = LM
Iteration:112 x = [-0.1239 -4.3717 5.3572 -5.3565],
gradient = 0.0396, step = LM
Iteration:113 x = [-0.1239 -4.1687 5.3583 -5.3584],
gradient = 0.0016, step = LM
Iteration:114 x = [-0.1240 -3.2559 5.3610 -5.3611],
gradient = 0.0427, step = LM
Iteration:115 x = [-0.1240 -3.2559 5.3610 -5.3611],
gradient = 0.0427, step = LM
Iteration:116 x = [-0.1240 -3.2559 5.3610 -5.3611],
gradient = 0.0427, step = LM
Iteration:117 x = [-0.1248 -1.1768 5.4018 -5.4026],
gradient = 4.7877, step = LM
Iteration:118 x = [-0.1248 -1.1768 5.4018 -5.4026],
gradient = 4.7877, step = LM
Iteration:119 x = [-0.1248 -1.1768 5.4018 -5.4026],
gradient = 4.7877, step = LM
Iteration:120 x = [-0.1248 -1.1768 5.4018 -5.4026],
gradient = 4.7877, step = LM
Iteration:121 x = [-0.1248 -1.1768 5.4018 -5.4026],
gradient = 4.7877, step = LM
Iteration:122 x = [-0.1244 -1.1290 5.5183 -5.4517],
gradient = 0.1904, step = LM
Iteration:123 x = [-0.1292 -1.0057 5.7614 -5.6610],
gradient = 1.1816, step = LM
Iteration:124 x = [-0.1382 -0.8383 6.2791 -6.1944],
gradient = 3.1482, step = LM
Iteration:125 x = [-0.1464 -0.7806 6.8138 -6.7630],
gradient = 1.7846, step = LM
Iteration:126 x = [-0.1599 -0.6524 7.7451 -7.7208],
gradient = 5.7805, step = LM
Iteration:127 x = [-0.1658 -0.6428 8.2978 -8.2944],
gradient = 0.8161, step = LM
Iteration:128 x = [-0.1770 -0.5710 9.2787 -9.2788],
gradient = 4.5341, step = LM
Iteration:129 x = [-0.1818 -0.5588 9.8477 -9.8546],
gradient = 0.7032, step = LM
Iteration:130 x = [-0.1902 -0.5204 10.7897 -10.7955],
gradient = 2.9184, step = LM
Iteration:131 x = [-0.1941 -0.5090 11.3439 -11.3510],
gradient = 0.6201, step = LM
Iteration:132 x = [-0.1999 -0.4878 12.1563 -12.1617],
gradient = 1.6519, step = LM
Iteration:133 x = [-0.2027 -0.4799 12.6128 -12.6178],
gradient = 0.3816, step = LM
Iteration:134 x = [-0.2059 -0.4697 13.1434 -13.1472],
gradient = 0.5800, step = LM
Iteration:135 x = [-0.2073 -0.4656 13.4035 -13.4068],
gradient = 0.1173, step = LM
Iteration:136 x = [-0.2082 -0.4629 13.5699 -13.5729],
gradient = 0.0504, step = LM
Iteration:137 x = [-0.2085 -0.4622 13.6148 -13.6177],
gradient = 0.0034, step = LM
Iteration:138 x = [-0.2085 -0.4622 13.6188 -13.6218],
gradient = 0.0000, step = LM
Iteration:139 x = [-0.2085 -0.4622 13.6188 -13.6218],
gradient = 0.0000, step = LMFinal estimated parameters: [-0.2085 -0.4622 13.6188 -13.6218]
视频作者作者
该算法运行多达 139 次迭代,产生参数估计结果 x* = [-0.21,-0.46,13.62,-13.62],ǁ g ( x* )ǁ ≈ 0。换句话说,该算法在满足停止准则ǁ gₖ ǁ ≤ ε ₁的情况下成功收敛。还可以看出,在给定数据的曲线拟合过程中,算法在第 76–88 次迭代时将步长方法改为 QN,然后再改回 LM。这意味着在迭代 76 之前的最后 3 次迭代中,没有迭代 xₖ 满足ǁgₖǁ≥0.02⋅fₖ从而 QN 方法被认为在迭代 76 之后能够比 LM 方法更快地收敛。然后,在迭代 88,我们得到ǁgₖ₊₁ǁ≥ǁgₖǁ,这意味着使用 QN 方法梯度下降得不够快,使得该方法切换到 LM 用于下一次迭代。
因为初始值 x ₀离解很远,所以需要比场景 1 更多的迭代。还有,注意到目前为止满足收敛值 x* 的解有两个,分别是 x* = [-0.46,-0.21,-13.62,13.62]和 x* = [-0.21,-0.46,13.62,-13.62]。
场景 3
Iteration:1 x = [0.0000 0.0000 0.7705 0.7705],
gradient = 42.5292, step = LM
Iteration:2 x = [-0.0815 -0.0815 1.3987 1.3987],
gradient = 16.7516, step = LM
Iteration:3 x = [-0.0400 -0.0400 1.2150 1.2150],
gradient = 18.3468, step = LM
Iteration:4 x = [-0.0607 -0.0695 1.3851 1.3851],
gradient = 4.8184, step = LM
Iteration:5 x = [-0.0607 -0.0695 1.3851 1.3851],
gradient = 4.8184, step = LM
Iteration:6 x = [-0.0607 -0.0695 1.3851 1.3851],
gradient = 4.8184, step = LM
Iteration:7 x = [-0.0607 -0.0695 1.3851 1.3851],
gradient = 4.8184, step = LM
Iteration:8 x = [-0.0607 -0.0695 1.3851 1.3851],
gradient = 4.8184, step = LM
Iteration:9 x = [-0.0607 -0.0695 1.3851 1.3851],
gradient = 4.8184, step = LM
Iteration:10 x = [-0.0631 -0.0584 1.3830 1.3830],
gradient = 1.3008, step = LM
Iteration:11 x = [-0.0596 -0.0627 1.3811 1.3811],
gradient = 0.4178, step = LM
Iteration:12 x = [-0.0620 -0.0601 1.3793 1.3792],
gradient = 0.2770, step = LM
Iteration:13 x = [-0.0604 -0.0616 1.3775 1.3775],
gradient = 0.2522, step = LM
Iteration:14 x = [-0.0613 -0.0605 1.3758 1.3757],
gradient = 0.2432, step = LM
Iteration:15 x = [-0.0604 -0.0612 1.3737 1.3737],
gradient = 0.2332, step = LM
Iteration:16 x = [-0.0615 -0.0597 1.3708 1.3708],
gradient = 0.2541, step = LM
Iteration:17 x = [-0.0582 -0.0627 1.3678 1.3677],
gradient = 0.6396, step = LM
Iteration:18 x = [-0.0582 -0.0627 1.3678 1.3677],
gradient = 0.6396, step = LM
Iteration:19 x = [-0.0607 -0.0600 1.3668 1.3668],
gradient = 0.1995, step = LM
Iteration:20 x = [-0.0603 -0.0604 1.3658 1.3658],
gradient = 0.1930, step = LM
Iteration:21 x = [-0.0603 -0.0601 1.3639 1.3638],
gradient = 0.1840, step = LM
Iteration:22 x = [-0.0593 -0.0605 1.3587 1.3586],
gradient = 0.2076, step = LM
Iteration:23 x = [-0.0593 -0.0605 1.3587 1.3586],
gradient = 0.2076, step = LM
Iteration:24 x = [-0.0593 -0.0605 1.3587 1.3586],
gradient = 0.2076, step = LM
Iteration:25 x = [-0.0608 -0.0590 1.3571 1.3570],
gradient = 0.2311, step = LM
Iteration:26 x = [-0.0584 -0.0611 1.3556 1.3555],
gradient = 0.3672, step = LM
Iteration:27 x = [-0.0609 -0.0586 1.3545 1.3544],
gradient = 0.3171, step = LM
Iteration:28 x = [-0.0590 -0.0603 1.3536 1.3536],
gradient = 0.1788, step = LM
Iteration:29 x = [-0.0600 -0.0593 1.3528 1.3527],
gradient = 0.1280, step = LM
Iteration:30 x = [-0.0594 -0.0598 1.3519 1.3519],
gradient = 0.1237, step = LM
Iteration:31 x = [-0.0597 -0.0594 1.3510 1.3510],
gradient = 0.1192, step = LM
Iteration:32 x = [-0.0597 -0.0594 1.3508 1.3510],
gradient = 0.1183, step = QN
Iteration:33 x = [-0.0597 -0.0594 1.3500 1.3510],
gradient = 0.1155, step = QN
Iteration:34 x = [-0.0596 -0.0594 1.3475 1.3510],
gradient = 0.1084, step = QN
Iteration:35 x = [-0.0592 -0.0594 1.3401 1.3510],
gradient = 0.1055, step = QN
Iteration:36 x = [-0.0589 -0.0594 1.3328 1.3510],
gradient = 0.2028, step = QN
Iteration:37 x = [-0.0595 -0.0585 1.3319 1.3501],
gradient = 0.1538, step = LM
Iteration:38 x = [-0.0595 -0.0585 1.3319 1.3501],
gradient = 0.1538, step = LM
Iteration:39 x = [-0.0587 -0.0592 1.3314 1.3496],
gradient = 0.0704, step = LM
Iteration:40 x = [-0.0591 -0.0588 1.3310 1.3492],
gradient = 0.0640, step = LM
Iteration:41 x = [-0.0588 -0.0590 1.3306 1.3488],
gradient = 0.0618, step = LM
Iteration:42 x = [-0.0588 -0.0590 1.3304 1.3488],
gradient = 0.0615, step = QN
Iteration:43 x = [-0.0588 -0.0590 1.3300 1.3488],
gradient = 0.0610, step = QN
Iteration:44 x = [-0.0587 -0.0590 1.3288 1.3488],
gradient = 0.0582, step = QN
Iteration:45 x = [-0.0586 -0.0590 1.3275 1.3488],
gradient = 0.0571, step = QN
Iteration:46 x = [-0.0586 -0.0590 1.3263 1.3488],
gradient = 0.0554, step = QN
Iteration:47 x = [-0.0585 -0.0590 1.3251 1.3488],
gradient = 0.0646, step = QN
Iteration:48 x = [-0.0590 -0.0585 1.3247 1.3484],
gradient = 0.0576, step = LM
Iteration:49 x = [-0.0585 -0.0589 1.3243 1.3481],
gradient = 0.0494, step = LM
Iteration:50 x = [-0.0589 -0.0585 1.3240 1.3477],
gradient = 0.0455, step = LM
Iteration:51 x = [-0.0585 -0.0588 1.3237 1.3474],
gradient = 0.0409, step = LM
Iteration:52 x = [-0.0588 -0.0585 1.3233 1.3471],
gradient = 0.0393, step = LM
Iteration:53 x = [-0.0585 -0.0588 1.3230 1.3468],
gradient = 0.0377, step = LM
Iteration:54 x = [-0.0588 -0.0585 1.3228 1.3465],
gradient = 0.0363, step = LM
Iteration:55 x = [-0.0585 -0.0587 1.3225 1.3462],
gradient = 0.0348, step = LM
Iteration:56 x = [-0.0587 -0.0585 1.3222 1.3459],
gradient = 0.0335, step = LM
Iteration:57 x = [-0.0585 -0.0587 1.3219 1.3457],
gradient = 0.0321, step = LM
Iteration:58 x = [-0.0587 -0.0585 1.3217 1.3454],
gradient = 0.0307, step = LM
Iteration:59 x = [-0.0584 -0.0587 1.3214 1.3452],
gradient = 0.0294, step = LM
Iteration:60 x = [-0.0587 -0.0584 1.3212 1.3449],
gradient = 0.0319, step = LM
Iteration:61 x = [-0.0584 -0.0587 1.3209 1.3447],
gradient = 0.0330, step = LM
Iteration:62 x = [-0.0587 -0.0584 1.3207 1.3445],
gradient = 0.0357, step = LM
Iteration:63 x = [-0.0584 -0.0587 1.3205 1.3442],
gradient = 0.0362, step = LM
Iteration:64 x = [-0.0586 -0.0584 1.3203 1.3440],
gradient = 0.0363, step = LM
Iteration:65 x = [-0.0584 -0.0586 1.3201 1.3439],
gradient = 0.0321, step = LM
Iteration:66 x = [-0.0586 -0.0584 1.3199 1.3437],
gradient = 0.0281, step = LM
Iteration:67 x = [-0.0584 -0.0586 1.3198 1.3435],
gradient = 0.0228, step = LM
Iteration:68 x = [-0.0585 -0.0584 1.3196 1.3434],
gradient = 0.0203, step = LM
Iteration:69 x = [-0.0584 -0.0585 1.3195 1.3432],
gradient = 0.0195, step = LM
Iteration:70 x = [-0.0585 -0.0584 1.3193 1.3431],
gradient = 0.0188, step = LM
Iteration:71 x = [-0.0584 -0.0585 1.3192 1.3429],
gradient = 0.0181, step = LM
Iteration:72 x = [-0.0585 -0.0584 1.3190 1.3428],
gradient = 0.0174, step = LM
Iteration:73 x = [-0.0584 -0.0585 1.3189 1.3426],
gradient = 0.0166, step = LM
Iteration:74 x = [-0.0585 -0.0583 1.3187 1.3425],
gradient = 0.0175, step = LM
Iteration:75 x = [-0.0583 -0.0585 1.3186 1.3423],
gradient = 0.0212, step = LM
Iteration:76 x = [-0.0585 -0.0583 1.3185 1.3422],
gradient = 0.0264, step = LM
Iteration:77 x = [-0.0583 -0.0585 1.3183 1.3421],
gradient = 0.0264, step = LM
Iteration:78 x = [-0.0585 -0.0583 1.3182 1.3420],
gradient = 0.0201, step = LM
Iteration:79 x = [-0.0583 -0.0584 1.3182 1.3419],
gradient = 0.0130, step = LM
Iteration:80 x = [-0.0584 -0.0583 1.3181 1.3418],
gradient = 0.0124, step = LM
Iteration:81 x = [-0.0584 -0.0584 1.3180 1.3417],
gradient = 0.0120, step = LM
Iteration:82 x = [-0.0584 -0.0583 1.3179 1.3416],
gradient = 0.0115, step = LM
Iteration:83 x = [-0.0583 -0.0584 1.3178 1.3415],
gradient = 0.0110, step = LM
Iteration:84 x = [-0.0584 -0.0583 1.3176 1.3414],
gradient = 0.0186, step = LM
Iteration:85 x = [-0.0584 -0.0583 1.3176 1.3414],
gradient = 0.0186, step = LM
Iteration:86 x = [-0.0583 -0.0584 1.3176 1.3413],
gradient = 0.0112, step = LM
Iteration:87 x = [-0.0584 -0.0583 1.3175 1.3412],
gradient = 0.0095, step = LM
Iteration:88 x = [-0.0583 -0.0584 1.3174 1.3412],
gradient = 0.0092, step = LM
Iteration:89 x = [-0.0583 -0.0584 1.3174 1.3412],
gradient = 0.0090, step = QN
Iteration:90 x = [-0.0583 -0.0584 1.3173 1.3412],
gradient = 0.0260, step = QN
Iteration:91 x = [-0.0584 -0.0583 1.3173 1.3411],
gradient = 0.0085, step = LM
Iteration:92 x = [-0.0583 -0.0584 1.3172 1.3411],
gradient = 0.0083, step = LM
Iteration:93 x = [-0.0583 -0.0583 1.3171 1.3410],
gradient = 0.0080, step = LM
Iteration:94 x = [-0.0583 -0.0583 1.3171 1.3409],
gradient = 0.0077, step = LM
Iteration:95 x = [-0.0584 -0.0583 1.3170 1.3409],
gradient = 0.0075, step = LM
Iteration:96 x = [-0.0583 -0.0584 1.3169 1.3408],
gradient = 0.0110, step = LM
Iteration:97 x = [-0.0584 -0.0582 1.3169 1.3407],
gradient = 0.0165, step = LM
Iteration:98 x = [-0.0583 -0.0584 1.3168 1.3407],
gradient = 0.0109, step = LM
Iteration:99 x = [-0.0583 -0.0583 1.3168 1.3406],
gradient = 0.0062, step = LM
Iteration:100 x = [-0.0583 -0.0583 1.3167 1.3406],
gradient = 0.0059, step = LM
Iteration:101 x = [-0.0583 -0.0583 1.3167 1.3406],
gradient = 0.0057, step = LM
Iteration:102 x = [-0.0583 -0.0583 1.3167 1.3405],
gradient = 0.0055, step = LM
Iteration:103 x = [-0.0583 -0.0583 1.3166 1.3404],
gradient = 0.0075, step = LM
Iteration:104 x = [-0.0583 -0.0583 1.3166 1.3404],
gradient = 0.0075, step = LM
Iteration:105 x = [-0.0583 -0.0583 1.3165 1.3404],
gradient = 0.0090, step = LM
Iteration:106 x = [-0.0583 -0.0583 1.3165 1.3403],
gradient = 0.0099, step = LM
Iteration:107 x = [-0.0583 -0.0583 1.3164 1.3403],
gradient = 0.0064, step = LM
Iteration:108 x = [-0.0583 -0.0583 1.3164 1.3403],
gradient = 0.0064, step = QN
Iteration:109 x = [-0.0583 -0.0583 1.3164 1.3403],
gradient = 0.0043, step = LM
Iteration:110 x = [-0.0583 -0.0583 1.3164 1.3402],
gradient = 0.0041, step = LM
Iteration:111 x = [-0.0583 -0.0583 1.3164 1.3402],
gradient = 0.0040, step = LM
Iteration:112 x = [-0.0583 -0.0583 1.3163 1.3402],
gradient = 0.0038, step = LM
Iteration:113 x = [-0.0583 -0.0583 1.3163 1.3401],
gradient = 0.0050, step = LM
Iteration:114 x = [-0.0583 -0.0583 1.3163 1.3401],
gradient = 0.0050, step = LM
Iteration:115 x = [-0.0583 -0.0583 1.3162 1.3401],
gradient = 0.0045, step = LM
Iteration:116 x = [-0.0583 -0.0583 1.3162 1.3401],
gradient = 0.0044, step = LM
Iteration:117 x = [-0.0583 -0.0583 1.3162 1.3400],
gradient = 0.0040, step = LM
Iteration:118 x = [-0.0583 -0.0583 1.3162 1.3400],
gradient = 0.0040, step = QN
Iteration:119 x = [-0.0583 -0.0583 1.3162 1.3400],
gradient = 0.0037, step = LM
Iteration:120 x = [-0.0583 -0.0583 1.3161 1.3400],
gradient = 0.0032, step = LM
Iteration:121 x = [-0.0583 -0.0583 1.3161 1.3400],
gradient = 0.0030, step = LM
Iteration:122 x = [-0.0583 -0.0583 1.3161 1.3400],
gradient = 0.0027, step = LM
Iteration:123 x = [-0.0583 -0.0583 1.3161 1.3399],
gradient = 0.0026, step = LM
Iteration:124 x = [-0.0583 -0.0583 1.3161 1.3399],
gradient = 0.0025, step = LM
Iteration:125 x = [-0.0583 -0.0583 1.3160 1.3399],
gradient = 0.0024, step = LM
Iteration:126 x = [-0.0583 -0.0583 1.3160 1.3399],
gradient = 0.0023, step = LM
Iteration:127 x = [-0.0583 -0.0583 1.3160 1.3399],
gradient = 0.0022, step = LM
Iteration:128 x = [-0.0583 -0.0583 1.3160 1.3398],
gradient = 0.0021, step = LM
Iteration:129 x = [-0.0583 -0.0583 1.3160 1.3398],
gradient = 0.0020, step = LM
Iteration:130 x = [-0.0583 -0.0583 1.3160 1.3398],
gradient = 0.0020, step = LM
Iteration:131 x = [-0.0583 -0.0583 1.3159 1.3398],
gradient = 0.0022, step = LM
Iteration:132 x = [-0.0583 -0.0583 1.3159 1.3398],
gradient = 0.0024, step = LM
Iteration:133 x = [-0.0583 -0.0583 1.3159 1.3398],
gradient = 0.0026, step = LM
Iteration:134 x = [-0.0583 -0.0583 1.3159 1.3397],
gradient = 0.0025, step = LM
Iteration:135 x = [-0.0583 -0.0583 1.3159 1.3397],
gradient = 0.0023, step = LM
Iteration:136 x = [-0.0583 -0.0583 1.3159 1.3397],
gradient = 0.0018, step = LM
Iteration:137 x = [-0.0583 -0.0583 1.3159 1.3397],
gradient = 0.0015, step = LM
Iteration:138 x = [-0.0583 -0.0583 1.3158 1.3397],
gradient = 0.0014, step = LM
Iteration:139 x = [-0.0583 -0.0583 1.3158 1.3397],
gradient = 0.0014, step = LMFinal estimated parameters: [-0.0583 -0.0583 1.3158 1.3397]
视频作者作者
该算法运行 139 次迭代,产生参数估计结果 x* = [-0.06,-0.06,1.32,1.34],ǁgₖǁ≈0.0014>ε₁.换句话说,算法没有成功收敛,但是迭代已经终止,因为满足了停止准则ǁhₖǁ≤ε₂(ǁxₖǁ+ε₂)。还可以看出,在给定数据的曲线拟合过程中,由于情景 2 中描述的原因,算法反复将步长方法更改为 QN,反之亦然。从上图来看,显然,找到的解决方案 x* 不够好。
通过在迭代过程中查看 x 的值,观察到 x ₁ ≈ x ₂和 x ₃ ≈ x ₄.因此,我们可以得出结论,选择初始值 x ₀ = [0,0,0,0]是一个糟糕的选择,因为该值是对称的,并且该算法不能破坏对称性。你可以试着看看同样的事情发生在选择其他初始对称值上,比如 x ₀ = [-1,-1,-1], x ₀ = [1,1,1,1],或者 x ₀ = [2,2,2,2]。哦,这只是一个巧合。你怎么想呢?
从实验中你还发现了什么有趣的东西?
结论
我们开发了一种有效的算法来解决非线性最小二乘问题。该算法结合了 Levenberg-Marquardt 和拟牛顿法,利用信赖域进行步长选择。该算法能以超线性收敛速度准确找到模型的最佳参数。但是,不良的参数初始化可能会导致不好的结果。在我们的研究案例中,该算法找到了符合数据的以下两个模型:
当然,通过重新排列参数 x 的组件,这两个模型是等价的。
🔥你好!如果你喜欢这个故事,想支持我这个作家,可以考虑 成为会员 。每月只需 5 美元,你就可以无限制地阅读媒体上的所有报道。如果你注册使用我的链接,我会赚一小笔佣金。
🔖想了解更多关于经典机器学习模型的工作原理,以及它们如何优化参数?或者 MLOps 大型项目的例子?有史以来最优秀的文章呢?继续阅读:
艾伯斯·乌兹拉
从零开始的机器学习
View list8 stories
艾伯斯·乌兹拉
高级优化方法
View list7 stories
艾伯斯乌兹拉
MLOps 大型项目
View list6 stories
艾伯斯乌兹拉
我最好的故事
View list24 stories
艾伯斯乌兹拉
R 中的数据科学
View list7 stories
[1] K. Madsen (1988): 一种用于非线性最小二乘法的组合高斯-牛顿和拟牛顿方法。DTU 数值分析研究所(现为 IMM 的一部分)。报告 NI-88–10。
将数据从 Web 直接读入 Python 的有效方法
原文:https://towardsdatascience.com/an-efficient-way-to-read-data-from-the-web-directly-into-python-a526a0b4f4cb?source=collection_archive---------7-----------------------
而不必下载到你的硬盘上
七射手在 Unsplash 上拍照
我硬盘上的存储空间非常宝贵,我不想下载一大堆数据,因为我只想把它们整理成易于管理的东西。
有时我们可以将一个 URL 粘贴到pd.read_csv()
或xr.read_dataset()
中,它会很高兴地读取数据。例如,xarray 支持 OPeNDAP 通过 HTTP 访问一些数据集,但不是全部。
这篇文章将描述一个解决方案,当事情不顺利,直接将 URL 粘贴到 xarray 失败时,你可以使用它。我将概述如何从 web 服务器直接读取数据到 Python 中,甚至是从 zip 文件中读取,所有这些都不需要写入磁盘。
基本思想
目标是通过 HTTP 或 FTP 访问数据,这使用了请求和响应结构。例如,我们可以请求一个 URL 的内容,服务器将(希望)把数据作为响应发送给我们。下面是这个结构在urllib.request
Python 包中的工作原理:
**url='https://google.com'**
: 这是我们要访问的 URL。**req=urllib.request.Request(url)**
: 创建一个请求对象,指定我们想要的 URL。**resp=urllib.request.urlopen(resp)**
: 从服务器返回请求 URL 的响应对象。**data=resp.read()**
: 响应对象(resp
)是类文件的,表示我们可以读取。
现在让我们将这个基本思想应用到一些真实的数据中。
从 URL 读取数据
下面的代码从 NCEP 再分析中获取特定年份的气温。我总是喜欢在打开 URL 时使用上下文管理器,这样我就不会忘记关闭它。
这段代码的最后一行用我们的数据返回一个 xarray 数据集。然而,那条线路有点忙,让我们打开它:
resp.read()
:是我们要求的数据。但是,它是以字节为单位的。io.BytesIO()
:将我们请求的数据以字节的形式保存在内存缓冲区中。xr.open_dataset()
:打开字节文件作为 xarray 数据集。我可以这样做,因为我请求的 URL 是 NetCDF 文件。
这太棒了!不费吹灰之力,我们就可以将数据读入内存,而无需下载。
注意
如果您得到一个错误消息说“不能以字节形式打开 NetCDF”,那么您需要安装 h5netcdf。
conda install -c conda-forge h5netcdf
如果数据被压缩了呢?
没问题,Python zipfile
包可以搞定。在下面的代码中,我向服务器请求一个 zip 文件。然后我使用zipfile
包列出里面的文件。具体来说,我使用的是namelist()
方法。最后,我使用 xarray 将其中一个 NetCDF 文件的内容读入一个数据集。
HTTP 错误 403:禁止
如果你请求访问并得到这个错误信息,这意味着服务器知道你正试图从一个程序访问它。然而,我们比计算机更聪明,可以欺骗它认为我们是一个网络浏览器。这可以通过在我们的请求中附加一个用户代理来实现,这样看起来就像是来自一个 web 浏览器。打个比方,这就像敲敲门,宣布我们是谁。附加一个不同的用户代理类似于冒充我们不认识的人。
你从哪里得到数据 URL?
当你在网上找到一个数据集时,通常会有一个下载该数据集的按钮。我们想知道链接到该数据的 URL。在大多数浏览器中,你可以右击下载链接和“复制链接地址”这里有一个使用 Brave 浏览器获取海洋数据集链接的例子。
最后的想法
这种方法可以简化数据管道,并使您的代码易于被他人复制。然而,也有一些缺点。例如,如果服务器关闭,您将无法访问数据。这种方法可能并不适用于所有情况,例如数据集太大而无法放入内存。我还没有遇到任何问题,但是我不确定这种方法对于仍然可以放入内存的大型数据集是否有效。
总而言之,我发现这是一种让我的代码可以被其他研究人员复制的干净方式。好处是我不依赖他们先下载数据。至少这是另一个添加到你工具箱的技巧。
我很乐意帮助您解决从服务器读取数据到 Python 时遇到的任何问题。
感谢阅读和支持媒体作者
https://lukegloege.medium.com/membership
用 ONNX/Torchscript 加速 BERT 推理的经验方法
原文:https://towardsdatascience.com/an-empirical-approach-to-speedup-your-bert-inference-with-onnx-torchscript-91da336b3a41?source=collection_archive---------5-----------------------
丹尼·米勒在 Unsplash 上的照片
近年来,基于 Transformer 架构的模型已经成为研究和行业中 NLP 突破背后的驱动力。伯特,XLNET,GPT 或 XLM 是一些模型,提高了艺术的状态,并达到像胶水流行基准的顶端。
这些进步伴随着巨大的计算成本,大多数基于变压器的模型是巨大的,并且用于训练的参数和数据的数量都在不断增加。虽然最初的伯特模型已经有 1.1 亿个参数,但最后的 GPT-3 有 1750 亿个参数,这是两年研究价值的惊人增长**~ 1700 倍**。
这些庞大的模型通常需要数百个 GPU 进行几天的训练才能有效,幸运的是,由于迁移学习,我们可以下载预训练的模型,并在我们自己的小得多的数据集上快速微调它们,成本很低。
也就是说,一旦培训完成,您仍然有一个大规模的模型,您可能想要部署到生产中。与更适度的模型相比,推断需要相对较长的时间,并且可能太慢而无法达到您需要的吞吐量。
虽然您可以投资更快的硬件或使用更多的服务器来完成这项工作,但有不同的方法来缩短模型的推理时间:
- 模型 修剪:减少层数、嵌入维数或隐藏层单元数。
- 量化:权重不用 32 位浮点(FP32),用半精度(FP16)甚至 8 位整数。
- 将****模型从本机 Pytorch/Tensorflow 导出到适当的格式或推理引擎(torch script/ONNX/tensort...)
- 批量:对一批样本而不是单个样本进行预测
第一种和第二种方法通常意味着重新训练你的模型,而最后两种方法是在训练后完成的,本质上与你的特定任务无关。
如果推理速度对您的用例极其重要,那么您很可能需要试验所有这些方法,以产生一个可靠的、速度惊人的模型。然而,在大多数情况下,将您的模型导出到适当的格式/框架并进行批量预测将会以最少的工作量为您提供更快的结果。我们将在这里关注这种方法,看看它对我们模型的吞吐量的影响。
我们将通过几个实验来探索改变模型格式和批处理的影响:
- 基准用香草T2【py torch】CPU/GPU
- 将 Pytorch 模型导出到 Torchscript CPU/GPU
- Pytorch 型号到 ONNX CPU/GPU
- 所有实验都在 1/2/4/8/16/32/64 批次的样品上进行
在这篇文章中,由于缺乏对 Pytorch 嵌入使用的 int64 的支持,还不能直接将 transformer 模型从 Pytorch 导出到 TensorRT,所以我们现在跳过它。
我们将在 camemBERT (~100M 参数)上执行句子分类,camemBERT 是 Roberta 的法语变体。因为绝大多数计算都是在 transformer 模型中完成的,所以不管您的任务是什么,您都应该得到类似的结果。
首先,我们将快速查看如何将 Pytorch 模型导出到相关的格式/框架,如果您不想阅读代码,可以直接跳到结果部分。
如何导出您的模型
香草火炬
在 Pytorch 中保存和加载模型非常简单,尽管有不同的方法。对于推断,官方文档建议保存模型的“state_dict ”,这是一个 python 字典,包含模型的可学习参数。这比酸洗你的整个模型更轻便和坚固。
#saving
model = SequenceClassifier()
train_model(model)
torch.save(model.state_dict(), 'pytorch_model.pt')#loading
model **=** SequenceClassifier()
model**.**load_state_dict(torch**.**load(PATH))
model**.**eval() #Set dropout and batch normalization layers to evaluation mode
with torch.go_grad():
logits = model(**batch_x)
点击此 链接 了解关于保存/加载 Pytorch 的更多信息。
Torchscript JIT
TorchScript 是一种从 Pytorch 代码创建可序列化和可优化模型的方法。一旦导出到 Torchscript,您的模型将可以从 Python 和 C++中运行。
- Trace :通过模型发送一个输入,所有操作都记录在一个定义 torchscript 模型的图中。
- 脚本:如果你的模型比较复杂,有条件语句之类的控制流,脚本会检查模型的源代码,编译成 TorchScript 代码。
请注意,由于您的模型将被序列化,因此您将无法在保存后对其进行修改,因此您应将其置于评估模式,并在保存前将其导出到适当的设备上。
如果你想在 CPU 和 GPU 上进行推理,你需要保存两个不同的模型。
#saving
jit_sample = (batch_x['input_ids'].int().to(device), batch_x['attention_mask'].int().to(device))model.eval()
model.to(device)
module = torch.jit.trace(model, jit_sample)
torch.jit.save('model_jit.pt')#loading
model = torch.jit.load('model_jit.pt', map_location=torch.device(device))
logits = model(**batch_x)
更全面的介绍你可以跟随官方教程。
ONNX
ONNX 为 AI 模型提供了一种开源格式,大多数框架可以将它们的模型导出到 ONNX 格式。除了框架之间的互操作性之外,ONNX 还提供了一些优化,可以加速推理。
导出到 ONNX 稍微复杂一些,但是 Pytorch 确实提供了直接导出功能,您只需要提供一些关键信息。
- opset_version ,每个版本都有一组支持的操作符,一些具有更奇特架构的型号可能还不能导出。
- ****输入名称和输出名称是分配给图的输入和输出节点的名称。
- dynamic_axes 参数是一个字典,它指示输入和输出变量的哪个维度可以改变,例如 batch_size 或序列的长度。
#saving
input_x = jit_sample ## taking sample from previous exampletorch.onnx.export(model, input_x,'model_onnx.pt',export_params=True, opset_version=11, do_constant_folding=True, input_names = ['input_ids', 'attention_mask'], output_names = ['output'],
dynamic_axes= {
'input_ids' : {0 : 'batch_size', 1:'length'},'attention_mask' : {0 : 'batch_size', 1:'length'},
'output' : {0 : 'batch_size'}
})#loading
model = onnxruntime.InferenceSession(model_onnx)
batch_x = {
'input_ids':sample['input_ids'].cpu().numpy(),
"attention_mask":sample['attention_mask'].cpu().numpy()
}
logits = model.run(None, batch_x)
ONNX 运行时可以与 GPU 一起使用,尽管它需要特定版本的 CUDA、cuDNN 和 OS,使得安装过程在开始时具有挑战性。
要获得更全面的教程,你可以遵循官方的文档。
实验结果
每个配置已经在 1k 个不同长度的句子的数据集上运行了 5 次。我们测试了两种不同的流行 GPU: T4 和 V100 与 torch 1.7.1 和 ONNX 1.6.0。请记住,结果会因您的特定硬件、软件包版本和数据集而异。
在我们的数据集上,推断时间的范围从平均每个样本 50 毫秒到 0.6 毫秒,取决于硬件设置。
在 CPU 上,与 pytorch 上的批处理大小 1 相比,ONNX 格式显然是 batch_size ❤️2, at which point the format seems to not really matter anymore. If we predict sample by sample, we see that ONNX manages to be as fast as inference on our baseline on GPU for a fraction of the cost.
As expected, inference is much quicker on a GPU especially with higher batch size. We can also see that the ideal batch size depends on the GPU used:
- For the T4 the best setup is to run ONNX with batches of 8 samples, this gives a ~ 12x 加速的赢家
- 对于批量为 32 或 64 的 V100,与 GPU 的基准相比,我们可以实现高达 28 倍的加速比,与 CPU 的基准相比,我们可以实现高达 90 倍的加速比。
总的来说,我们发现选择合适的格式对较小的批量有很大的影响,但随着批量的增大,这种影响会缩小,对于 64 个样品的批量,3 个设置之间的误差在 10%以内。
序列长度和批处理策略的影响
另一个要考虑的是序列长度。变压器通常被限制为 512 个令牌的序列,但是对于该范围内的不同序列长度,在速度和内存需求方面存在巨大差异。
****
对于较大的批次而言,推断时间与序列长度大致成线性比例增加,但对于单个样本而言并非如此。这意味着,如果你的数据是由很长的文本序列组成的(例如新闻文章),那么你就不会通过批处理获得很大的加速。一如既往,这取决于你的硬件,V100 比 T4 快,在预测长序列时不会受到太大影响,而另一方面,我们的 CPU 确实会完全不堪重负:
如果您的数据在长度上是异构的,并且您使用批处理,这些差异将会导致问题,因为必须将您的样本填充到批处理中最长的一个,这会增加大量计算。因此,通常最好将相似长度的样本一起分批,因为预测多个相似长度的批次比预测一个主要是填充标记的大批次更快。
作为快速检查,让我们看看在运行推理之前对数据集进行排序时会发生什么:
正如我们所料,对于较大的批量,将相似长度的样品分组是一个重要的激励。对于未排序的数据,随着批次变大,出现一些较长样本的可能性越来越大,这将显著增加整个批次的推断时间。我们可以看到,从 16 到 64 的 batch_size 降低了 20%的推断速度,而对于排序后的数据,它的速度提高了 10%。
这种策略也可用于显著减少训练时间,但应谨慎操作,因为它可能会对模型的性能产生负面影响,尤其是在标签和样本长度之间存在某种相关性的情况下。
后续步骤
虽然这些实验是直接在 Python 中运行的,但 Torchscript 和 ONNX 模型都可以直接在 C++中加载,这可以进一步提高推理速度。
如果你的模型对于你的用例来说仍然太慢,Pytorch 确实为量化提供了不同的选项。动态量化可以在训练后进行,但很可能会对你的模型精度产生影响,而量化感知训练需要重新训练,但对你的模型性能影响应该较小。
结论
正如我们所看到的,优化您的推理时间没有直接的答案,因为它主要取决于您的特定硬件和您试图解决的问题。因此,您应该使用自己的目标硬件和数据进行实验,以获得可靠的结果。
尽管如此,还是有一些指导方针应该适用并且易于实施:
- 对批处理进行预测可以显著加速到一定的大小(取决于您的特定硬件),特别是如果您可以一起批处理长度相似的样本。
- 使用 Torchscript 或 ONNX 确实为较低的批量和序列长度提供了显著的加速,在对单个样本进行推断时,这种效果尤其明显。
- ONNX 似乎是我们测试的三种配置中性能最好的,尽管它也是最难安装在 GPU 上进行推理的。
- Torchscript 确实为较小的批量提供了可靠的加速,并且非常容易设置。
一个端到端的机器学习项目—心力衰竭预测,第 1 部分
原文:https://towardsdatascience.com/an-end-to-end-machine-learning-project-heart-failure-prediction-part-1-ccad0b3b468a?source=collection_archive---------12-----------------------
数据探索、模型训练、验证和存储
在这个系列中,我将介绍一个端到端的机器学习项目,涵盖从数据探索到通过 web 应用程序部署模型的所有内容。我的目标是提供关于将模型投入生产所涉及的不同组件的一般见解;本系列不是机器学习管道的全面概述。本文将涵盖数据探索、模型训练、验证和存储。在整个系列中,读者将接触到各种语言和技术,如 Git、Python、SQL、Catboost、Flask、HTML、CSS、JavaScript 和 Heroku。这个系列的所有代码都可以在 GitHub 上找到。第二部分现已推出这里。
问题陈述
制定问题陈述是任何机器学习项目的第一个也是最重要的先决条件。问题陈述应该足够清晰,以显示机器学习如何用作解决方案。我为这个系列选择了下面的问题陈述:
我们希望分析心力衰竭的风险因素,并对个体心力衰竭的概率进行建模。
这个问题陈述有两个组成部分可以潜在地用机器学习来解决:分析风险因素和建模心力衰竭的概率。特别是,解决这个问题的一个方法是建立一个模型,该模型可以准确地预测个体心力衰竭的可能性,并以证据支持该预测。
数据
接下来,也是最重要的,机器学习项目的先决条件是拥有可靠、干净和结构化的数据源。在企业环境中,这些数据集通常是辛勤工作的数据工程团队的产品,不应该被视为理所当然。幸运的是,像 Kaggle 这样的网站为我们提供了准备建模的干净数据集。我们将在这个项目中使用一个流行的心脏病数据集。
https://www.kaggle.com/fedesoriano/heart-failure-prediction
该数据集包含 11 个特征,我们将使用这些特征对心力衰竭概率进行建模。此外,在进行预测时,我们希望我们的模型能够告诉我们哪些特性贡献最大(在以后的文章中会有更多相关内容)。为了使数据源更加真实,我将把。csv 文件转换为. db 文件。这将使数据检索更加模块化,因为它将模拟一个实际的数据库。
数据探索
我们将从检查用于心力衰竭概率建模的数据开始。我不会检查每一行代码,但所有代码都可以在这个笔记本中找到。首先,我们将导入所有必需的库,并指定一些稍后将使用的存储路径:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from catboost import CatBoostClassifier, Pool, cv
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, classification_report, accuracy_score
import optuna
from optuna.samplers import TPESampler
import sqlite3
from datetime import datetime# display all of the columns of the dataframe in the notebook
pd.pandas.set_option('display.max_columns',None)%matplotlib inline# Path to mock database
SQL_PATH = 'data/MockDatabase.db'# Path to model storage location
MODEL_STORAGE_PATH = 'models/'
接下来,我们将从。数据库文件使用 SQL 查询。对于任何有兴趣知道如何创建一个. db 文件的人,请看这个笔记本。下面使用的“创建连接”函数直接来自 sqlite 教程。
# Read in training data
conn = create_connection(SQL_PATH)read_query = '''SELECT Age,
Sex,
ChestPainType,
RestingBP,
Cholesterol,
FastingBS,
RestingECG,
MaxHR,
ExerciseAngina,
Oldpeak,
ST_Slope,
HeartDisease
FROM heart'''data_train = pd.read_sql(read_query, conn)
conn.close()print(data_train.shape)
data_train.head()
训练数据的峰值。图片作者。
我们的数据集似乎是分类特征和数字特征的完美结合。只有 918 行,没有太多的训练数据要处理。然而,这将使模型训练时间更快,并允许我们轻松地执行超参数调整和交叉验证。幸运的是,数据中没有缺失值;这对于医疗数据来说尤其令人惊讶,是数据工程团队工作出色的标志。好的数据工程的重要性怎么强调都不为过。
我们的下一个目标是分析分类和数字特征。下面的代码创建了两个列表,一个用于分类特性,一个用于数字特性。分类特征列表将在稍后构建模型时使用。
# Separate columns by data type for analysis
cat_cols = [col for col in data_train.columns if data_train[col].dtype == np.object]num_cols = [col for col in data_train.columns if data_train[col].dtype != np.object]# Ensure that all columns have been accounted for
assert len(cat_cols) + len(num_cols) == data_train.shape[1]
从这里,我们可以看到每个分类特征的基数(唯一值的数量)。
# Look at cardinality of the categorical columns
cards = [len(data_train[col].unique()) for col in cat_cols]fig,ax = plt.subplots(figsize=(18,6))
sns.barplot(x=cat_cols, y=cards)
ax.set_xlabel('Feature')
ax.set_ylabel('Number of Categories')
ax.set_title('Feature Cardinality')
每个分类特征的基数。图片作者。
所有分类特征的基数都相对较低,因此模型很容易对这些特征进行编码和处理。这个数据集的一个有趣的特性是,大约 79%的患者是男性。此外,超过 90%的心脏病患者是男性。
更多被研究的病人是男性。图片作者。
超过 90%的心脏病患者是男性。图片作者。
接下来,我们观察患病和未患病患者之间的静息血压分布。
图片作者。
虽然分布看起来相对相似,但似乎疾病患者往往血压略高——这一观察结果可以通过统计测试得到验证。现在,当我们开始分析模型结果时,我们应该记住这些图中的一些。
最后,在我们开始建模之前,我们应该看看这些类是如何不平衡的。也就是有多少病人有和没有心脏病。
心脏病分布。图片作者。
大约 55%的被研究患者患有心脏病,这提供了一个基准百分比来衡量我们的模型。换句话说,如果我们的模型从数据中学习到任何东西,它应该有超过 55%的准确性。如果我们的模型预测心脏病的准确率为 55%,这表明没有从数据中获得新的信息。该模型可以简单地预测每个病人都有心脏病,准确率为 55%。在许多真实世界的分类问题中,如欺诈检测,基线准确率可以达到 90%或更高(大多数交易不是欺诈)。在这些情况下,通常会跟踪除准确性之外的指标,如精度、召回和 f1 分数。
初始模型训练
本系列选择的模型是 Catboost ,我们将从训练和评估一个简单的模型实例开始。下面,我们创建训练和测试数据集。训练数据集包含大约 80%的原始数据,而测试集包含大约 20%的原始数据。要复制训练结果,请在“train_test_split”函数中指定随机状态 13。
# Create training and testing data
x, y = data_train.drop(['HeartDisease'], axis=1), data_train['HeartDisease']
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=13)print(x_train.shape)
print(x_test.shape)
x_train.head()
下一步是创建 Catboost 模型实例。在我们这样做之前,必须创建一个包含每个分类特征的列号的列表。利用之前创建的“cat_cols”列表,可以轻松创建该列表。
# Specify index of categorical features in input data
cat_features = [x.columns.get_loc(col) for col in cat_cols]
然后,我们可以用所需的模型参数创建一个字典。首先,我们将只指定几个参数,因为 Catboost 以出色的“开箱即用”性能而闻名。
# Model parameter dict
params = {'iterations':5000,
'loss_function':'Logloss',
'depth':4,
'early_stopping_rounds':20,
'custom_loss':['AUC', 'Accuracy']}
Catboost 参数的描述可以在这里找到。这里要指出的重要参数是“迭代”和“早期停止轮次”。在这种情况下,我们将训练模型,直到经过 5000 次迭代(树)或者经过 20 次迭代而测试误差没有减少。最后,我们实例化模型并调用“fit”方法。在“fit”方法中,我们传递测试集,以便模型可以实现早期停止回合(实际上更常见的是创建训练、测试和验证集)。
# Instantiate model
model = CatBoostClassifier(**params)# Fit model
model.fit(
x_train,
y_train,
cat_features=cat_features,
eval_set=(x_test, y_test),
verbose=50,
plot=True
)
模型完成训练后,我们对测试数据进行预测,并输出性能指标。
# Make predictions on test data
preds = model.predict(x_test)# Evaluate predictions
print(classification_report(y_test, preds))
print(confusion_matrix(y_test, preds))
初始训练/测试分割的性能指标。图片作者。
在这个由 184 名患者组成的测试集上,该模型达到了 89%的准确率。这意味着该模型能够正确识别测试集中 89%的患者是否患有心脏病。我们可以把的精度解释为:当模型预测一个病人有心脏病时,它的正确率为 89%。类似地,我们可以将回忆解释为:在患有心脏病的患者数量中,该模型在 91%的情况下成功预测了这些患者存在心脏病。
接下来,我们可以看看模型实例的全局特性重要性。
fig,ax = plt.subplots(figsize=(10,6))feature_importance_data = pd.DataFrame({'feature':model.feature_names_, 'importance':model.feature_importances_})feature_importance_data.sort_values('importance', ascending=False, inplace=True)sns.barplot(x='importance', y='feature', data=feature_importance_data)
第一个模型实例的特征重要性。图片作者。
特征重要性表明“ST_Slope”是心脏病的头号预测因子。“ST_Slope”是患者运动时记录的心脏电活动的测量值;它采用“向上”、“向下”和“平坦”值。“胸部疼痛类型”是第二个最有影响力的预测因子,取值为“TA”(典型心绞痛)、“ATA”(非典型心绞痛)、“NAP”(非心绞痛性疼痛)和“ASY”(无症状)。第三,“Oldpeak”是“ST_Slope”大小的度量。总的来说,在没有广泛的心脏病学知识的情况下,特征重要性的顺序似乎是直观的。
超参数调谐
超参数调整通常被称为机器学习的“黑暗艺术”。这是因为有许多方法可以确定模型超参数的最佳集合,并且在大多数情况下,不可能知道是否已经找到了参数的最佳集合。此外,随着训练数据大小的增加,以及可能的超参数数量的增加,调优成为一个极其昂贵的高维优化问题。幸运的是,训练数据相对较小,可供搜索的有用超参数数量也很少。
我们将使用一个著名的优化库 Optuna ,来搜索一组好的超参数。本节使用的一些代码改编自扎卡里·沃恩斯写的一篇很棒的文章。
我们必须首先定义一个目标函数来优化:
更多细节请参见本文文章。图片作者。
“参数”字典定义了要搜索的所有超参数,以及要考虑的值的范围。值得注意的是,我们正在优化 5 重交叉验证测试的准确性,而不仅仅是在任意测试集上的准确性。这是通过使用 Catboost 的“cv”函数来完成的。
优化试验使用以下代码进行:
classification_study = optuna.create_study(sampler=TPESampler(), direction="maximize")
classification_study.optimize(classification_objective, n_trials=20, timeout=600)
trial = classification_study.best_trialprint(f"Highest Accuracy: {trial.value}")
print("Optimal Parameters:")
for key, val in trial.params.items():
print(f"{key}:{val}")
需要指出的两个主要问题是试验次数和超时。利用上述配置,优化算法将运行 20 次迭代,或者如果 10 分钟已经过去,它将在 20 次迭代之前终止。在第一次迭代之后,Optuna 将输出如下内容:
第一次迭代后的 Optuna 输出。图片作者。
这告诉我们,第一组超参数的交叉验证测试准确度约为 86.7%。人们可能会注意到,这低于我们在初始测试集上达到的 89%的准确率。这是意料之中的,因为交叉验证的准确性为我们提供了对真实模型准确性的更好估计,即模型在生产中的准确性。经过 20 次迭代后,Optuna 能够找到一组参数,将交叉验证的准确度提高到 88%左右。
找到的最佳超参数集的输出。图片作者。
模型中迭代(树)的数量将通过使用这组超参数的交叉验证来确定。具体来说,最终的迭代次数由最大化交叉验证测试准确性的迭代次数决定。
# Create new parameter dictionary using optimal hyper-parameters
new_params = trial.params.copy()
new_params['loss_function'] = 'Logloss'
new_params['custom_loss'] = ['AUC','Accuracy']cv_data = cv(
params = new_params,
pool = Pool(x, label=y, cat_features=cat_features),
fold_count=5,
shuffle=True,
partition_random_seed=0,
plot=False,
stratified=False,
verbose=False)final_params = new_params.copy()# The final number of iterations is iteration number that maximizes cross-validated accuracyfinal_params['iterations'] = np.argmax(cv_data['test-Accuracy-mean'])final_params['cat_features'] = cat_features
训练和导出最终模型
最后,我们使用最优超参数集训练最终模型,并将其导出到所需的存储位置。
final_model = CatBoostClassifier(**final_params)
final_model.fit(x,y,verbose=100)# Export model
model_name = f'heart_disease_model_{str(datetime.today())[0:10]}'
final_model.save_model(MODEL_STORAGE_PATH + model_name)
第 1 部分概述
在本系列的第 1 部分中,我们检查了训练数据,训练并评估了一个模型实例,执行了超参数调整,并导出了最终的模型。同样,这绝不是一篇全面的文章。每一个机器学习项目都是独一无二的,大多数问题都需要对训练数据给予比这里给出的更多的关注。然而,我希望这里展示的代码为读者提供了一个机器学习项目的通用框架。
在下一篇文章中,我们将通过创建一个为最终用户提供我们的模型的应用程序来窥视 web 开发的世界。这将涉及到 HTML、CSS、JavaScript 和 Flask 的使用。感谢阅读!
使用 TypeDB 的企业数据堆栈
原文:https://towardsdatascience.com/an-enterprise-data-stack-using-typedb-aa6df12b420b?source=collection_archive---------26-----------------------
https://www . shutterstock . com/image-illustration/3d-render-abstract-database-server-stack-1737433799
拜耳医药公司用于药物研发的数据架构
在世界上最大的制药公司之一拜耳公司,深入了解生物系统对于发现新的治疗方法至关重要。这促使人们采用能够加速和自动化发现的技术,从数据库开始,跨越数据基础架构的所有组件。
数据和发现过程中的挑战并非拜耳独有:
- 大规模加载异构数据集
- 将异构数据集映射到一个真实的来源——给定一种疾病,我们如何在多个数据集之间协调其不同的 id?
- 模拟生物系统的复杂性——基于基因组上的位置以及基因、蛋白质、途径、细胞、组织之间的三元关系,在数据库中自然地表示基因和变异
- 如此复杂系统上的查询构造
- 将 ML 管道连接到数据库
拜耳的团队——Henning kui ch、Dan Plischke 和 Joren Retel——着手建立一个堆栈来帮助他们解决这些挑战。
第一步是找到一个数据库,让他们能够模拟疾病周围生物系统的复杂性。它需要能够表示生物学中固有的相互联系,在需要时动态更新模型而不干扰过程的其余部分,并能够有效连接到知识提取管道,无论是可视化还是学习过程。他们在 TypeDB 中找到了他们的数据库,这是来自 Vaticle 团队的强类型数据库(社区版本完全开源)。
"….我们实际上已经在内部开发了一个堆栈,以便非常认真地使用 TypeDB,所以我们已经建立了一个数据迁移器来将内容放入其中,然后我们现在有两个分支来将知识取出。”— Henning Kuich,拜耳制药公司资深计算科学家
拜耳的生产栈,用于 TypeDB 的高级工作——经许可使用。
用于模拟复杂性的数据库— TypeDB
生物学中的一切都是极其相关和依赖于上下文的,这使得在传统的关系数据库中表示数据非常困难。正因为如此,Henning 和他的团队认为 TypeDB 的类型系统是一种更自然的生物学建模方式。
生物医学实验是高度上下文相关的,因此在构建生物医学知识图时,您希望能够快速查询使用了哪些参数。实际的化验是什么?是在体外,还是在细胞里?这需要一个能够捕捉这种复杂程度的数据库,以及一种允许我们轻松地对这些数据提出复杂问题的查询语言。有了 TypeDB,Henning 的团队就能做到这一点。
Bayer 还利用了 TypeDB 中本机推理引擎的优势。推理可以为拥有类似复杂生物医学数据的团队做很多事情。例如,Henning 和他的团队使用 TypeDB 的推理引擎,根据它们在染色体上的位置来推断variant
到gene
的连接。
基因本质上只是基因组中的序列,实际上是沿着一长串其他位置的位置。变体是这些序列的变体,也沿着相同的数字和位置延伸。使用 type QL(TypeDB 的查询语言),该团队能够根据重叠位置将变异映射到基因,而不是依赖于其他需要他们导入变异和基因之间关系的数据库。重要的是,这避免了维护其他数据库的需要,因为定期更新和迁移这些数据库需要很长时间。所有这些都可以通过使用 TypeDB 的推理引擎来避免。
TypeDB 还允许您在数据库生命周期中的任何时间点重新定义模式。例如,我们可以添加一个新的定义,根据基因的位置来定义与基因相关的变异。这很重要,尤其是当我们添加新的数据集时。所有这些都使 Henning 的团队能够更有效地运作,并加速他们的药物发现过程。
数据摄取— 类型数据库加载器
TypeDB Loader 是一个 Java 应用程序和库,使您能够将其用作 CLI 工具或在自己的 Java 项目中使用。这是一个工具来加载许多大规模的 csv 文件,并将数据缝合在一起,成为一个真正的图形格式的 TypeDB。它可以用最少的配置文件来实现所有这些,配置文件告诉加载器使用哪些列将被加载的各种表中的数据关联在一起。使用它相对简单,只需指定正在与哪个实例对话,以及正在写入哪个 TypeDB 数据库。然后提供您的数据配置、处理器配置、TypeDB 模式,然后确定您希望在哪里跟踪迁移状态。这可以像一个 JSON 文件一样简单。
Henning 的团队决定构建自己的定制加载器,以提供一种可伸缩的方式将大量数据加载到 TypeDB 中。为了加载数据,最初的 TypeDB 文档建议构建一个读入文件(例如以表格格式)的函数,并构建一个生成插入查询的模板函数。然后,文档建议使用其中一个客户端驱动程序插入到 TypeDB 数据库中。然而,当大规模地这样做时,引入了 TypeDB Loader 试图解决的许多挑战:
- 处理所需模板函数的重复逻辑
- 注意潜在的脏数据,防止插入过程中的错误
- 大规模插入查询的并行化和批处理
- 大数据容错
数据探索— GraEs
考虑到生物学的复杂性,特别是对疾病的理解,自然会期望模型(TypeDB 模式)能够快速增长。
模式是您的领域的模型,在 TypeQL 中作为类型(实体、属性、关系、角色)和规则来实现。插入到 TypeDB 中的所有数据都将实例化部分模式,确保您的数据符合您已经实现的模型。
这在编写查询时提出了挑战,因为用户必须记住或查找在哪个关系中允许哪些角色扮演者,对于给定的变量或事物哪些属性可用,以及查询中约束的所有可能属性值。为了解决这个问题,Bayer 的团队建立了一个自动完成引擎,在你编写查询时提供基于语法和模式的建议。
该团队旨在解决的另一个挑战是创建一种快速可视化评估特定重要查询的方法。为了解决这个问题,GraEs 提供了汇总表和单个子图可视化。此外,它将自动返回从查询中返回的概念的所有可能的属性,因此您不必手动请求它们。如今,GraEs 已经拥有解决所有这些问题的基本布线:
- 查询完成
- 查询开发
- 子图的标准可视化
- 某些实体或关系的汇总表
- 为特定查询或查询类型的更多自定义可视化铺平了道路
用于链接预测和新发现管道的学习系统——type db 到 PyTorch 连接器
今天,很明显药物发现过程在时间和金钱上都是昂贵的。正如 Henning 指出的,生物学最自然的表现形式是图表,团队可以利用这种相互联系的性质来识别新的潜在目标。能够利用 TypeDB 提供的丰富语义建模,可以预测哪些基因、蛋白质或变体是最重要的。
虽然 kg lib(va ticle 的开源机器学习库)提供了与 TensorFlow 和 GraphNets 的连接,但拜耳的 ML 团队现在已经在 PyTorch 工作了两年。因此他们希望扩展 KGLIB 来连接 PyTorch。
他们构建的连接器背后的概念是从他们的 TypeDB 数据库中提取子图,并将它们直接传递给学习者。使用子图作为训练示例允许图学习方法在规模上操作。否则,整个图形(大小可能达到万亿字节)将需要保存在内存中以供学习。
这为他们提供了如下管道:
- 能够导出到 Python 内存中的 NetworkX 子图
- 从 TypeDB 超图实体/关系/属性模型编码成传统的节点-边模型
- TensorFlow 和 PyTorch 嵌入器自动将 TypeDB 中的类型和值数据解释为特征
- 端到端管道已经准备好与任何新的和令人兴奋的本地图形学习算法一起使用,例如 py torch Geometric(GitHub 的链接)内置的那些算法
结论
希望这能让你对当今日益复杂的生物医学领域的药物发现过程有所了解。
虽然这只是围绕 TypeDB 构建的企业生产堆栈的一个例子,但我们看到越来越多的社区构建工具和库继续推进其应用程序和复杂问题的解决方案。从开发自动驾驶汽车系统的混合方法,为制造和物流行业建立因果关系模型,到患者治疗和精确医疗,网络智能威胁检测和供应链分析,TypeDB 使团队能够比以前更有效地工作,并更具表现力地建立领域模型。
要更多地了解社区正在构建什么,并为您自己的项目获得一些灵感,以下是一些方法:
- 加入社区不和
- 找到您的本地聚会
- 下载最新的 TypeDB 版本并开始构建
强化学习考试的一个例子——问题背后的基本原理(第一部分)
原文:https://towardsdatascience.com/an-example-of-reinforcement-learning-exam-rationale-behind-the-questions-part-1-682d1358b571?source=collection_archive---------22-----------------------
在考试中你应该期待什么?我当老师的经历
Nguyen Dang Hoang Nhu 在 Unsplash 上拍摄的照片
- 学生在强化学习考试中最常犯的错误是什么?
- 有没有有效备考的方法?
- 强化学习中最重要的研究课题是什么?
- 有哪些可能的问题?
在这一系列文章中,我将回答这些问题,并提供如何应对测试的见解。
由于我在 KTH 皇家理工学院的教学经验,我遇到了学生可能遇到的不同问题,我将主要关注我自己的经历。KTH 大学的博士生需要教学,这是他们活动的一部分,也是我作为博士生最喜欢做的事情之一。
对于那些不再是学生的人来说,这篇文章可能仍然有助于获得新知识。
希望这能对许多学生有所帮助。
练习介绍:预期的 SARSA 和政策内与政策外学习
练习介绍
上学期(2021 年 1 月)据我的导师说,我在设计考题的时候还是蛮有创意的。在上图中,你可以找到练习的介绍。
作为一门研究生课程,学生应该发展反思和批判性思维技能,以及对强化学习的理解。
因此,我设计了这个活动来评估学生在以下方面的技能:
- 批判性思维
- 理解基本的强化学习概念:策略上的、策略外的学习和收敛
- 使算法适应不同需求的能力
我将简要描述我是如何评估这三点的。
第一个问题——批判性思维和理解
对于我的学生,我通常会教他们如何通过他们的作品来思考。毕业后,我坚信拥有这种技能是必不可少的,也是必要的。
考试的第一部分旨在测试理论知识和评估算法的能力。本质上,这个测试评估学生在评估一件作品时的批判性判断。
下图显示了一个错误的 SARSA 算法的伪代码。
这是我问学生的第一个问题
1.找出算法中的所有错误。激励为什么这些是错误,并纠正它们。
该算法包含许多错误。
这个问题本身可能看起来很简单,但事实并非如此。**首先,我没有提供错误的总数。**它让这个练习看起来像一个真实的场景,在这个场景中,你必须评估其他人的工作。此外,为了纠正错误,学生们需要了解基本的强化学习概念(否则你怎么能纠正它们呢?)
这个练习值 3 分(满分 10 分),学生往往误以为每个错误值 1 分,总共 3 分(整体考试值 50 分,有 5 个练习,每个 10 分)。
不幸的是,这是一种幼稚的思维方式,学生应该避免用那些术语来思考。一个错误的价值可能超过 1 分,也可能低于 1 分。
总共 6 个错误,每个错误值半分。
然而,这些错误并不都具有同样的重要性(在我看来),将来我可能会使用不同的方法。
但是,有哪些错误呢?
大多数错误需要学生注意细节,而其余的是简单的数学错误(加号而不是减号,等等)。
第一个错误是关于学习速度
- **第一个错误涉及罗宾斯-门罗条件,这是强化学习的基石之一。**随机近似算法用于强化学习中的数据学习。以下两个条件是随机逼近格式收敛的必要条件:∑ α(t) = ∞和∑ α (t) < ∞。
- 在练习中,后一个要求没有得到满足。人们可以简单地选择不同的学习速率,例如 1/n
三个错误是关于目标值的
- 第二个主要错误是目标值 y(t)的计算。SARSA 是一种政策学习方法。
- 这意味着目标值应该根据行为策略采取的动作来计算(换句话说,如果你采取了动作 x,你应该使用相同的动作 x 来计算目标值),而不是使用 Q 学习中的最大操作!
- 另一个错误是遗漏了折扣因子!
- 正确答案是 y(t) = r + λ Q(s(t+1),a(t+1))。
- 唯一的小错误(真正的小错误)是,当插曲结束时(即我们已经到达最终状态),目标值应该只等于回报(y(t)=r)。
两个错误是关于 Q 值的更新
- 最后但并非最不重要的是,Q 值的计算也包含一些小误差。
- 我们更新当前状态和动作对的值,而不是后续的值!左手边应该是 Q(s(t),a(t)),而不是 Q(s(t+1),a(t+1))。
- 而且,α前面有个负号应该是加号。
第二和第三个问题:批判性思维、理解和适应
练习的第二和第三个问题
练习中的第二个和第三个问题给了我一点试验算法的自由。
这是为了测试学生适应意外情况的能力。
首先,我改变了计算目标值的方式。为了稍微改变一下,我引入了一个新元素,策略π。使用这种方法,我可以评估他们对基本强化学习概念的理解,即策略外学习与策略内学习。
就其本身而言,这些问题并不难。然而,在考试中引入意想不到的因素会对学生产生巨大的心理影响。他们中的大多数人可能会因为这一变化而感到紧张,这可能会影响他们的表现。
不过,只要改的不需要复杂的答案,我感觉同学们应该都能搞定。
你可以用一行回答问题 2:
- 在问题(2)中,这个策略π就像一个自由参数。要回答这个问题,学生需要理解政策内学习和政策外学习的区别。
- 此外,符号可能会让学生感到害怕。尽管是一所工程学校,但并不是所有的学生都能在这个水平上掌握数学符号。
在我看来,这反映了缺乏数学知识,这是行业需要能够解决不需要数学建模的问题的数据科学家/数据工程师的结果。 - 问题(2)的答案简单明了 : π应该就是行为策略,也就是你用来采取行动的策略。(因此政策μ)。
问题 3 也有点难,但不多,需要 1-2 行答案。
- 假设行为策略无限频繁地对所有状态-动作对进行采样,非策略算法将学习在目标值计算中使用的策略的 Q 值。****
- 因此,给定一个充分探索的行为策略,Q 值将收敛到策略π的 Q 值,而不是策略μ的 Q 值。
结论和后续文章
安吉丽娜·利特温在 Unsplash 上的照片
这是一个系列的第一篇文章,我将描述一些在强化学习测试中最常见的问题。
在这篇文章中,我展示了我在上次考试中提出的一些简单而棘手的问题。在接下来的几篇文章中,我将展示更多的练习,并更详细地讨论其他强化学习问题。
我将主要讨论强化学习的方法和理论方面,重点是教师对学生的期望。
希望这篇文章在你的解题方式上对你有所启发,以便对你即将到来的考试或者以后的学习有所帮助!
感谢您的阅读!
强化学习考试的一个例子:问题背后的基本原理(第二部分)
原文:https://towardsdatascience.com/an-example-of-reinforcement-learning-exam-rationale-behind-the-questions-part-2-e66509ba50ee?source=collection_archive---------37-----------------------
在考试中你应该期待什么?我当老师的经历
真诚媒体在 Unsplash 上拍摄的照片
- 学生在强化学习考试中最常犯的错误是什么?
- 有哪些可能的问题?
在这一系列文章中,我将回答这些问题,并提供如何应对测试的见解。
由于我的教学经验,我遇到了学生可能遇到的不同问题,我将主要集中在我自己的经验。
对于那些不再是学生的人来说,这篇文章可能仍然有助于获得新知识。
查看前面的文章 这里的 。
在这里,我将涵盖我在上一篇文章中遗漏的几个问题(你可以在这里找到)。
下面的问题是整个练习中最难的、,但是正如我们所看到的,它们可以用几行来回答。
问题测试学生的概率和强化学习知识,以及解决问题的能力。
这些问题如下:
作者图片
首先,做一些澄清:
- ****π是这里的策略,其中π( a|s )表示给定状态 s. 时选择动作 a 的概率
- 目标 y 是 TD-target ,如果我们使用 on-policy 或 off-policy 算法,它会发生变化(如果这不清楚,请查看我以前的文章https://towards data science . com/an-example-of-enforcement-learning-exam-rational-behind-The-questions-part-1-682d 1358 b571)。
- SARSA(又名预期 SARSA ) 的变体是一种算法,其中 TD-target 根据以下公式进行计算
TD-SARSA 变体的目标(也称为预期 SARSA);作者图片
- 偏见只是衡量一项政策好坏的标准。如果策略是最优的,我们期望偏差项为 0。
问题(a)的解决方案
问题(a)是关于熟悉概率中的高塔法则属性,并知道 TD-target 是什么。
这是一个经典的解决问题的练习,学生需要一次走一步。简单地写下你希望证明/解决的事情通常是个好主意。
**首先,为了不混淆,让我们用 SARSA 、用 y 表示目标值,用 SARSA 的变体用y’表示目标值。因为 Q(s,a) 在每个偏置项中是相同的值,所以该练习归结为表明以下等式成立
我们需要证明什么!(图片由作者提供)
接下来:什么是 y 和y’?这些只是 TD 目标。我们已经知道如何写它们了。**
作者图片
因此,原问题简化为证明以下等式
这是我们需要证明是真实的平等(图片由作者提供)
这确实是练习的第一个难点。我们怎样才能从这里搬走一个呢?不要惊慌。
- 注意,在左手边我们有两个随机变量,t+1 时刻的状态-动作对,而在右手边只有一个随机变量(右手边只有一个随机变量,t+1 时刻的状态)。
这是一个人需要更新他/她的概率工具包的地方。这个想法是通过使用条件期望的塔属性来洗去左侧额外随机变量的影响。
只需执行以下操作(从左至右阅读):
从左至右:应用(1)塔规;(2)把内心的期望写成和;作者图片
- 解释:考虑左手边的表达式,对下一个动作取一个平均值,假装你知道下一个状态是什么(我们得到中间的表达式)。
然后,写出平均值是多少**(右边最后一步)**。**** - 这表明 Sarsa 的偏差相当于 SARSA 变体的偏差(也称为预期 SARSA)。
- 塔性质为我们提供了一次处理一个随机变量的能力,在处理多个随机变量的期望时,我们的生活变得更加轻松。
问题(b)的解决方案
在第二个问题(b)中,我们被要求回答两种算法是否收敛到相同的 Q 值(你可以再次检查下面的问题)。
作者图片
这是一种开放式问题,学生被迫思考这个问题。学生需要了解哪些假设会导致肯定(或否定)的答案。
需要注意的一件重要事情是,政策π是固定的,不会随着时间而改变。 这意味着我们并不是真的对学习更好的政策感兴趣,而只是学习π的值。
我们该如何开始?
- 首先,我们需要假设罗宾斯-门罗条件得到满足。
- 其次,我们知道 SARSA 的变体使用一种行为策略,即ϵ-greedy 策略。
这两件事暗示着 SARSA 的变体会收敛到策略π的 Q 值(不是最优 Q 值)。
- **由于行为策略将无限频繁地探索每个状态-动作对,那么算法将收敛到我们用来计算 TD-target y,的策略的 Q 值,即π的 Q 值。
【SARSA 呢?
- SARSA 将学习被无限频繁访问的状态-动作对的值。
- 然而,可能有些国家行动对从未被访问过。例如,考虑这样的情况,其中到达特定状态 z 的唯一方式是在状态 s 中执行动作 a 。如果那个概率是 0 ( π(a|s)=0 ,我们将永远无法学习到 z 中的 Q 值。
如果在状态“s”中,我们从不执行动作“a ”,就不可能知道状态“z”中动作的值(图片由作者提供)
- 另一方面,SARSA 的变体将学习 z 中的 q 值,因为在这种情况下,行为策略是ϵ-greedy(这保证了状态 z 将在某个点被访问)
- 所以,唯一的办法就是保证π有足够的探索性。这就需要满足以下条件:我们需要一个正概率来挑选每个状态下所有可能的动作,即对于所有的状态-动作对, π(a|s) > 0 。
- 如果满足后一个条件,那么通过 SARSA 学习的 Q 值收敛到策略π的 Q 值。
结论和后续文章
这是 系列 的第二篇文章,我在这里描述了一些你可以在强化学习测试中找到的最常见的问题。
在接下来的文章中,我将展示更多的练习,并更详细地讨论其他强化学习问题。
我将主要讨论强化学习的方法和理论方面,重点是老师对学生的期望。
希望这篇文章对你的解题方式有所启发,或许对你即将到来的考试或者以后的学习有所帮助!
感谢您的阅读!
Python 3.x 中决策树分类的详尽指南
原文:https://towardsdatascience.com/an-exhaustive-guide-to-classification-using-decision-trees-8d472e77223f?source=collection_archive---------2-----------------------
图片来自 Pinterest
使用决策树进行分类的端到端教程
有各种机器学习算法可以用于处理分类问题。一种这样的算法是决策树算法,除了分类之外,它还可以用于解决回归问题。虽然这是一种最简单的分类算法,但是如果对其参数进行适当的调整,可以产生非常精确的结果。
在这篇文章中,我将首先尝试给你一个什么是算法的直觉,以及它如何做出预测。然后,我将尝试分解与该算法密切相关的一些重要术语,最后,在本文结束时,我将使用决策树设计一个非常简单的分类器。
在开始这篇文章之前,我建议你看一下我以前的文章,我在这些文章中讨论了各种学习算法。另外,如果你喜欢这篇文章,请考虑为这篇文章鼓掌,并确保关注我以获得更多#MachineLearningRecipes。整篇文章的 PDF 副本可以从这里下载,继续你的离线学习。
决策树是如何做出决策的?
正如我在以前的文章中所讨论的,决策树算法是一种简单而有效的监督学习算法,其中数据点根据某些参数和/或算法试图解决的问题被连续分割。决策树通常也被称为 CART (代表分类和回归树)。
如果您有兴趣了解更多关于使用决策树解决回归问题的知识,请考虑查看我以前的文章这里。
图片来自黑客地球
每个决策树包括一个根节点,一些分支,和叶节点。树中的内部节点描述了不同的测试用例。决策树可以用来解决分类和回归问题。该算法可以被认为是一个图形树状结构,使用各种调整参数来预测结果。决策树将自顶向下的方法应用于训练期间输入的数据集。
为了理解算法实际上是如何工作的,假设需要开发一个预测模型,该模型可以预测学生申请进入特定课程是否被接受。考虑以下提供给任何决策树模型的数据集。
图片作者作者
某个学生的申请只有在满足下述条件的情况下才会被接受:
- 入门考试成绩应等于或大于 60 分。
- 毕业、10 级和 12 级的成绩应在 60 分以上。
在这种情况下,尽管上述条件可能有某些例外。在这种情况下,申请将被列入等候名单。
- 如果申请人的 GATE/毕业分数低于门槛分数,但有工作经验,则该申请将被列入名单。
- 如果申请人在第 12 类中的分数超过 75 分,但低于第 10 类中的最低要求分数,则他们的申请将被列入名单。
图片来自豆类
上例中考虑的问题可以用图形的形式来考虑,如决策树或流程图。一棵树将满足问题中提供的所有可能的情况。决策树算法的工作方式类似于一组嵌套的 if-else 语句,其中检查连续的条件,除非模型得出结论。
树的决策节点或简单节点是树在经过每个节点(从根节点开始)后呈现的问题。分支或子树是整个树的一个子部分。树的每个边对应于问题的结果,并且该结果由代表类别分布的叶节点或终端节点来表示。
决策树在分类中是如何使用的?
决策树算法使用一种称为树的数据结构来预测特定问题的结果。由于决策树遵循有监督的方法,该算法被提供了预处理数据的集合。这些数据用于训练算法。点击了解更多关于此的信息。
图片来自 KDNuggets
决策树遵循自上而下的方法,这意味着树的根节点总是在结构的顶部,而结果由树叶表示。决策树是使用一种称为递归划分(通常称为分治法)的启发式方法构建的。根节点之后的每个节点都被分成几个节点。
其核心思想是使用决策树将数据空间划分为密集区域和稀疏区域。二叉树的分裂可以是二进制的,也可以是多进制的。该算法继续分裂树,直到数据足够同质。在训练结束时,将返回一个决策树,该决策树可用于进行最佳分类预测。
这个算法发展中的一个重要术语是熵。它可以被认为是给定数据集的不确定性的度量,其值描述了特定节点的随机程度。当结果的差异幅度非常低,模型因此对预测的准确性没有信心时,就会出现这种情况。
图片来自维基百科
熵越高,数据集中的随机性就越高。构建决策树时,应优先选择较低的熵。计算决策树熵的表达式如下:
用于类似目的的另一个指标是基尼指数。它使用基尼系数法来创建分割点。信息增益是通常用于测量数据集中不确定性减少的度量。决策树中的信息增益通常由以下公式描述:
该度量可以进一步用于确定决策树的根节点和要进行的分裂的数量。决策树的根节点通常被称为决策节点或主节点。
图片来自 Kaggle
每棵树都有一个根节点。根节点通常被认为是与所有其他特性相协调的最重要的特性。通常,所有要素中精度最高的要素被选为根节点。
决策树中的分裂
随着决策树中分裂数量的增加,构建决策树所需的时间也会增加。然而,具有大量分裂的树容易过度拟合,导致精度差。然而,这可以通过决定最大深度参数的最佳值来管理。随着该参数值的增加,分割数也会增加。
可用于控制决策树拆分的其他参数包括 min_samples_split 、 min_samples_leaf 和 max_features 。
图片来自维基百科
另一种可以在很大程度上避免过度拟合的方法是通过去除在决策过程中具有很小或没有意义的分支。这被称为修剪。有两种不同类型的修剪— 预修剪和后修剪。预修剪在树生长时完成,而后修剪在树构建到一定深度后修剪节点。
如果你已经读到这里,我相信你一定喜欢这篇文章,并且发现它内容丰富,所以请考虑为这篇文章鼓掌,并关注我后面的文章。点击这里查看我的其他#机器学习食谱。
现在,我已经对算法及其工作的理论概念有了更好的理解,我们将尝试应用我们的知识来构建我们自己的分类器。用于构建分类器的代码和其他资源可以在我的 GitHub 句柄中获得。
步骤 1:导入所需的库和数据集
库是一组有用的功能,消除了从头编写代码的需要,在开发机器学习模型和其他应用程序中起着至关重要的作用。Python 提供了大量的库,可以用来开发高度复杂的学习模型。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
首先,我们将引入一些流行的库,如 Pandas 和 NumPy。Pandas 是一个快速、强大、灵活且易于使用的开源数据分析和操作工具,构建于 Python 编程语言之上。另一方面,NumPy 由一组多维数组对象和处理这些 NumPy 数组的例程组成。
图片由作者
与 C/C++不同,Python 为我们在程序中前进时导入库提供了灵活性。Matplotlib 是一个基于 NumPy 数组的多平台数据可视化库,旨在与 SciPy 一起工作。
另一个满足类似需求的库是 Seaborn 库,它构建在 matplotlib 之上,并与 pandas 数据结构紧密集成。可视化是 Seaborn 的核心部分,有助于探索和理解数据以及探索性数据分析和洞察力研究。
import warnings
warnings.filterwarnings('ignore')data = 'car_evaluation.csv'
df = pd.read_csv(data, header=None)
一旦导入了所有这些库,下一步就是获取训练和测试预测模型所需的数据集。 read_csv() 方法用于将数据集加载到 python 文件/笔记本中。用于构建该决策树分类器模型的数据集可以从这里下载。
第二步:探索性数据分析和特征工程
将数据加载到 pandas 数据框后,开发模型的下一步是探索性数据分析。探索性数据分析是一种分析数据的方法,以便深入了解数据中隐藏的事实和模式,这些事实和模式通常是我们看不到的。
图片来自媒体艾伦·杰弗里斯
这一步还包括清理和预处理数据。在这一步中,我们深入了解了将要处理的数据类型。在这一步中,我们还对数据进行了一些更改,例如删除缺失值、删除某些列、查看字段、研究某些变量以及定义各种不同变量之间的关系。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.33, random_state = 42)encoder = ce.OrdinalEncoder(cols=['buying', 'maint', 'doors', 'persons', 'lug_boot', 'safety'])
X_train = encoder.fit_transform(X_train)
X_test = encoder.transform(X_test)
数据经过适当的预处理后,下一步就是将数据分成训练数据和测试数据。通常 70–80%的数据作为训练数据,而剩余的数据作为测试数据。有时,测试数据可以进一步分类到称为验证数据的附加部分,用于评估模型。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.33, random_state = 42)
图片来自维基百科
我们在训练模型之前的最后一步是特征工程。这是将原始数据转化为有用特征的过程,这些特征揭示了关于模型的有用见解,从而提高了模型的预测能力。在此步骤中,对分类值进行编码,并对数据进行其他适当的更改。到这一步结束时,预测模型就准备好了。
第三步:拟合模型,评估结果,可视化树木
现在,数据已经完全准备好了,分类器被实例化,模型适合数据。为这个分类器选择的标准是熵,尽管也可以使用基尼指数。一旦我们的模型符合数据,我们尝试使用分类器模型预测值。这样做通常是为了执行公正的评估,并获得模型的准确性分数。
from sklearn.tree import DecisionTreeClassifier
clf_en = DecisionTreeClassifier(criterion='entropy', max_depth=3, random_state=0)
clf_en.fit(X_train, y_train)y_pred_en = clf_en.predict(X_test)
应确保模型既不过度拟合也不欠拟合数据。这可以通过计算训练和测试数据的准确度分数来完成。如果值是可比较的,那么模型没有过度拟合。
图片来自维基共享资源
一旦模型适合数据并做出预测,我们的最后一步将是评估分类器。这种方法最流行的工具之一是计算分类器的混淆矩阵。混淆矩阵是总结模型性能的工具。
from sklearn.metrics import accuracy_score
print('Model accuracy score with criterion entropy: {0:0.4f}'. format(accuracy_score(y_test, y_pred_en)))y_pred_train_en = clf_en.predict(X_train)
y_pred_train_enplt.figure(figsize=(12,8))
from sklearn import tree
tree.plot_tree(clf_en.fit(X_train, y_train))
混淆矩阵为我们提供了按每个类别细分的正确和错误预测的完整摘要,揭示了分类模型的性能和模型产生的错误。
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred_enprint('Confusion matrix\n\n', cm)
图片来自 ML Wiki
混淆矩阵有四种可能的结果,即真阳性、真阴性、假阳性和假阴性。混淆矩阵通常以表格形式输出。分类器的其他评估技术包括精度分数、 f1 分数、召回率和支持度分数。
决策树算法的优势
决策树分类器是最广泛使用的分类预测算法之一。使它如此受欢迎的一些特征是:
- 未知记录的极快分类。
- 忽略预测中不太重要或不重要的特征。
- 如果参数调整到最佳状态,效率极高。
- 构建成本低廉,逻辑易于解释。
决策树算法的局限性
尽管决策树分类器是最复杂的分类算法之一,但它可能有一定的局限性,尤其是在现实世界中。其威慑因素如下所述:
- 决策树分类器通常倾向于过度拟合训练数据。
- 数据的变化可能会导致结果发生不必要的变化。
- 大树有时很难解释。
- 这些偏向于具有多个级别的特征的分割。
图片来自维基百科
由于决策树分类器在大多数情况下容易过拟合,因此对于具有大量特征的数据集,用主成分分析替换决策树分类器是有利的。
决策树分类器的应用
在讨论了决策树算法的优点和局限性之后,是时候阐明决策树分类器的应用了。决策树算法最受欢迎的用途之一是在生物医学工程中,其中它用于识别可植入设备中使用的功能和探索潜在的药物。
决策树分类器也在数据挖掘、金融分析和经济产品开发中得到应用,其中它们被用于理解客户满意度、商业金融和相关行为。
在其他应用中,决策树分类器也用于系统设计和物理学,尤其是粒子检测。它还在制造和生产中得到应用,其中它可以用于质量控制、异常检测和半导体制造。
图片来自 Finereport
至此,我们已经到了这篇文章的结尾。我希望这篇文章能帮助你对决策树分类器的工作原理有所了解。如果你有任何问题,或者如果你认为我犯了任何错误,请随时与我联系。通过邮箱或 LinkedIn 与我联系。快乐学习!
体验“数据生态系统”
原文:https://towardsdatascience.com/an-experience-of-a-data-ecosystem-4f86e98fd013?source=collection_archive---------3-----------------------
我对数据世界的了解之旅—这篇文章描述了在产品组织中如何处理和消费数据,以及在数据生命周期的不同阶段,各种专业角色如何与数据进行交互
十多年来,数据一直是一种有价值的商品。它不仅改变了我们文明进步的方式,还为我们提供了一个新的视角来审视我们的技能和职业发展。对于一个刚开始处理数据的人来说,理解什么是数据以及如何处理和使用数据显然很重要。但是,了解使用数据意味着什么、数据的各种形式是什么、谁使用数据以及如何使用数据也很重要。这样的个体应该能够认同他们在这个生态系统中扮演的角色,以及他们可以进步到哪里。同时,他们还应该认识到这个生态系统中其他人的需求,以便理解问题陈述并创建更好的解决方案。
这篇文章概括了我在一家视频 OTT (B2C)产品公司担任数据专家的经历。这里的目的是描述现代数据驱动的产品公司的生态系统是什么样的,其生命周期的各个阶段是什么,以及谁是这个生态系统的生产者和消费者。数据不仅与工程和技术概念有关,还与正确转化为智能的决策和运营有关。
体验是独一无二的——这个生态系统对于一个组织来说也是独一无二的,可能不完全适用于其他地方。这个想法是为了给那些不熟悉这种生态系统的人一种工作的感觉。
认识一下这个生态系统的玩家!
虽然数据可能是 21 世纪最强大的人工资源,但人类在这个生态系统中扮演的角色至关重要。让我们看看他们是谁。
作者创作的插图
消费者是这个生态系统的中心——他们消费产品,享受不断发展的用户体验带来的好处。他们是这个世界的金矿,他们与各种数字产品的互动转化为贯穿整个生态系统的原始数据。
产品经理和商业利益相关者的任务是不断为消费者和他们所服务的产品/组织创造价值。他们齐心协力,满足消费者的期望,提高产品的价值定位,同时优化投资回报,实现组织目标。
数据架构师与产品经理合作,为需要生成何种原始数据以及如何消费这些数据奠定基础。它们提供了数据生态系统愿景的技术地图,该地图促进了数据处理管道、商业智能仪表板、数据馈送等的开发。
数据工程师通过设置资源和创建系统来存储和处理数据并支持其利益相关者的分析需求,在此基础上构建。他们的工作围绕着建立数据管道和维护各种形式的数据可用性。
QA(质量保证)工程师通过检查数据工程师生产的工作产品的质量,并确保正确满足利益相关者的期望,发挥着重要的作用。
数据分析师扮演了一个有趣的角色,因为他们与未知事物打交道。他们致力于回答组织中任何人提出的问题。他们帮助理解独特的用户行为,创建市场预测,调试问题和异常,等等。他们可能与技术、产品或业务团队合作,解决各种问题陈述。
分析师是工具箱中的扳手,可以调整它来拧紧各种大小的螺母和螺栓,并提供超出此范围的价值。
最后,还有数据科学家——他们肩负着从帽子里变出一只兔子的重任。他们的角色围绕着通过分析数据和使用数据科学和高级分析技术来产生更深刻的见解。从预测模型到创建推荐系统,他们的工作仍然是非结构化的,但非常有价值。
这些技术大脑聚集在一起,创造出令人惊叹的分析工作产品,让组织了解其消费者的行为,并帮助利益相关者每天做出更好的决策。
数据的方方面面——如何看待数据?
数据生态系统中的不同参与者以不同的方式与数据进行交互,这种交互定义了他们如何感知数据以及如何使用数据。2006 年,当 Clive Humby 创造了“数据是新的石油”这个短语时,他对这两种资源进行了明确的比较。就像石油要经历提取、提炼和储存等不同阶段一样;有些人重视原始形式的数据,有些人只利用经过处理的形式,有些人只需要了解数据的特征就可以存储和处理数据。
与数据的交互定义了玩家对数据的感知和使用。作者创作的插图。
在这个生态系统中,数据呈现 3 个方面。这些方面虽然对任何人都是可见和可访问的,但只对少数玩家有更高的相关性。
- 卷&特征 —这个方面对于数据工程参与者来说是最明显和最相关的,因为他们负责理解数据的结构和大小、存储数据、处理数据并创建分析工作产品,如报告、模型和分析。虽然他们也接触到其他两个方面,但与其职责的相关性较低,只能作为他们了解生态系统的额外知识,这可能有助于他们创建更好的解决方案。
- 模式&行为 —这个方面与数据分析师和科学家最相关。他们有责任弄脏自己的手,找到没有人知道如何解决的答案。他们研究隐藏的模式和消费者行为,以解决手头的问题陈述,这些陈述本质上总是探索性和诊断性的。他们的工作成果通常以开发新的生产流程的形式贡献给数据架构师和工程师。
- 总结信息 —这个方面对于生态系统的决策者来说是最重要的。产品经理和业务利益相关者借助报告仪表板、预测模型的结果、来自特别分析的见解等,执行各种运营(日常)和战略(长期)功能。他们依靠这些分析工具来改善产品体验,为消费者和组织创造价值。
这些相互作用可能不像上面看起来的那样具有排他性,生态系统中的任何人都可能经历相当多的重叠。业务利益相关者可能永远不会接触到原始数据或其元数据,因为他们可能在技术上不具备消费这些数据的能力,但没有什么可以阻止数据或 QA 工程师消费和理解呈现给这些利益相关者的汇总信息。这可能只是为了更好地理解他们工作的影响,或者是为了提升他们对所工作的产品或组织的了解。同样,虽然数据科学家的工作可能具有高度的技术性或统计性,但他们通常必须深入了解各种业务功能和市场动态,以便更好地了解他们对问题陈述的理解。
可以肯定地说,任何对所有这些方面如何相互作用有深刻理解的专业人士,在这个生态系统中都将是非常有用的,并且可能比其他人创造更大的价值。
数据会发生什么?
种植我们的作物——生成数据
数据生态系统的一个重要组成部分是原始数据的准确生成。消费者应用可以具有各种特性和功能、分支用户体验、视频播放器、支付网关等。为了更好地理解用户行为,有必要捕捉正确的用户接触点,要做到这一点,您必须正确设计您的应用程序事件记录架构。一个正确设计的架构可以帮助你了解关于你的大部分用户群的宝贵的行为信息;另一方面,设计不良的事件记录系统可能会让您失去宝贵的洞察力。
作者创作的插图
大多数生态系统依靠前端和后端系统之间的交互来生成用户交互的事件日志。每次用户与特定功能交互时,都会将一个事件日志推送到数据接收系统,其中包含定义所捕获事件的各种变量和参数。
比方说,用户试图在应用程序上搜索视频,当她点击搜索时,一个搜索请求被发送到后端服务,一个响应被发送回前端,为用户呈现多个相关的搜索结果。这个过程包括从后端和前端系统生成一个事件日志,该日志进入数据仓库,并作为原始数据存储起来,用于各种分析用例。该日志可以包含各种属性,如搜索关键字、搜索结果、语言等。这可以在以后帮助理解用户搜索什么或者评估所提供的搜索结果的质量。
在这里,产品经理和数据架构师扮演了一个重要的角色,他们理解并决定需要获取什么信息,以及如何将这些信息包含在服务的架构中。
智能工厂——数据平台
商业智能系统长期以来一直是任何公司决策过程中至关重要的一部分,并且随着数据管理和处理技术的发展而不断发展。在我们的生态系统中,架构完善的数据平台有助于组织构建数据驱动的战略,丰富面向消费者的产品。
作者创作的插图
从各种来源收集数据,包括消费者应用和后端服务的事件日志、外部供应商的内容元数据、支付合作伙伴的账单交易、社交媒体账户的交互数据、客户服务数据等。为了提取情报,所有这些数据都需要被正确地摄取、高效地存储和处理。数据工程团队接受了这一挑战,其中数据架构师与数据工程师一起创建了一个端到端的数据处理平台。他们建立数据接收管道,设计具有多个数据集市的数据仓库,创建 ETL 流程以满足各种业务报告的需求,并在一个或另一个企业数据可视化工具上构建这些报告。他们还确保可以与第三方服务集成,以便在它们之间建立数据馈送。
数据工程团队与产品经理一起创建各种分析工作产品——仪表板、总结报告、预测模型、知识图表和各种探索性分析。这些产品是来自业务涉众的各种需求以及产品管理和工程领域内的计划的结果。专业人员合作来理解什么样的产品将解决他们的用例,并记录他们的需求版本,然后与工程师讨论,以便将它付诸实施。 QA 工程师通过理解这些需求并确保可交付产品具有最高的质量和准确性,为这一过程做出了重要贡献。他们以汇总的形式验证任何报告中呈现的事实,从消费者的角度评估这些产品的使用情况,并确保利益相关者提出的任何问题都得到及时解决。
生态系统的一个重要组成部分是数据民主。存储和管理数据的负担可能落在工程团队身上,但是每个人都应该具备使用和分析这种资源的能力。在这个时代,越来越多的商业战略是数据驱动的,所以那些决策者更好地访问数据是有意义的。职能团队与他们的分析师一起创建定制的仪表板和分析,以支持他们的日常分析需求。数据民主化确保了对业务和行业的理解很容易被纳入问题解决流程,并减轻了工程团队在解决功能性问题时投入额外带宽的压力。
游说增长—产品管理
由产品经理和分析师组成的核心团队从核心驱动产品的发展和增长。产品经理处理产品的各个方面——一些人管理消费者应用程序的开发,而另一些人管理商业市场及其 KPI 的增长。这些经理中的一个小组负责通过与工程团队以及业务利益相关者协作来构建和推动数据生态系统。其他产品经理利用这个生态系统来推进他们自己产品组件的战略路线图。
作者创作的插图
“这些数字告诉了我们什么?”—业务利益相关者
这些团队是我们生态系统中所有分析工作产品的主要消费者。他们围绕各种业务/市场运营制定战略,如获取和保留用户的线下和在线营销、广告和订阅工作流、内容获取和编程等。他们还不断评估各种产品功能的市场适应性,以及用户如何使用它们。这对于确保产品供应始终与其目标群体相关非常重要。
这些功能需求需要对用户行为和产品性能有深刻的理解,这些需要通过一系列及时的仪表盘、性能跟踪器、预测和预测模型、用户细分算法来实现……不胜枚举。商业利益相关者与产品经理合作,定义他们想要跟踪什么以及他们想要如何研究它。这些需求沿着树向下渗透到工程人员,他们为这些需求提供技术形式,并构建分析产品,为业务利益相关者提供可操作的见解。
作者创作的插图
生态系统似乎以循环的形式出现,产品消费者生成的数据以增强的用户体验和新产品功能的形式返回给他们。但是,在这个生态系统中创造的价值取决于其中人们的协作努力。坏的合作往往为客户创造零价值或低价值,而好的合作创造历史。最重要的是确定你在这个生态系统中的角色,既要成为一名高效的数据专家,又要成为一名成功的合作者。太棒了。
作者创作的插图
学分—
特别感谢Supriya Pathak对这件作品的宝贵见解和合作。
https://www.linkedin.com/in/supriya-pathak-57485459/
图形是使用 diagrams.net 的(draw . io)和flat icon开发的。巨大的资源!这篇文章是思想的原创作品。
一种解决多元优化问题的实验设计方法
原文:https://towardsdatascience.com/an-experimental-design-approach-to-solve-a-multivariate-optimization-problem-58b40b29166d?source=collection_archive---------16-----------------------
响应值未知时寻找最佳输入参数
在这篇文章中,我将描述我在未知响应值的多元优化问题中寻找最大值的经历。我在滑铁卢大学参加的实验设计研究生课程的期末项目中研究过这个问题
语境
通常,在科学和工程环境中,有时甚至在商业环境中,我们会遇到一些定量问题,我们知道输入值及其范围,并得到相应的输出(响应)值,但不知道它们之间的关系。当可以安全地假设该关系是线性的时,我们可以拟合多元线性回归模型并确定该关系,并使用它来找到响应变量的最佳值或确定其对输入变量的敏感度。在非线性设置中,机器学习技术可以用来为我们做曲线拟合工作。
另一方面,如果我们只知道每个输入变量可以变化的范围,但没有提供响应变量值,并要求我们找到将导致响应变量最佳值的组合,那么我们就面临着一个困难的挑战。为了最有效地达到最佳值,我们应该进行多少次实验,以什么样的顺序进行?根据我对这个问题的研究,这个简单的问题可能会变得很难回答。这是问题陈述:
问题陈述
与混凝土相比,沥青在铺路方面有一些优势,比如初期成本较低,噪音也较低。然而,缺点之一是它的强度较低。在这项研究中,我们必须优化沥青的成分,以最大限度地提高其强度(抗压强度——响应变量)。
我们有三个输入变量及其变化范围:
𝑥1(水灰比):0.28–0.4
𝑥2(粗骨料粒径):9.5-12.5 毫米
𝑥3(空隙率):15%-25%
我们的目标是找到最大化𝑦(抗压强度或简单的强度)的𝑥1,𝑥2 和𝑥3 的设置。
请注意简单优化问题和这个问题的区别:
在常规优化问题中,我们已知输入变量和相应输出值的组合,但我们只知道输入变量的范围,而不知道响应变量的信息。
让我们考虑一下业务背景:这里的实验意味着,选择水灰比、粗骨料尺寸和空隙率的特定组合,使用该组合制造沥青,然后在材料测试实验室中确定最终沥青的抗压强度。我们的预算有限,因此不能做我们想做的那么多实验。例如,我们可以用这些输入变量的各种组合做一千个实验,然后报告产生强度最大值的组合吗?我们可以,但这将非常昂贵(想想安装成本、员工工资、原材料、电力……)。此外,这种方法将被视为蛮力,应该只在紧急情况下或所有其他方法都失败时使用。
在这种情况下,有一种叫做“实验设计”的统计学分支可以帮助我们。我们的时间和资源有限,必须想出一个好的解决方案(如果不是最好的)来解决一个基于合理的数学原理的问题。我现在一步一步地描述实验设计方法。
实验设计法
首先,我在 0.0-5.0 的范围内调整了所有三个变量,以便于实验的设计。我这样做是为了确保不同输入变量的大小不会影响以后的回归系数。换句话说,如果变量 1 在 0-1 之间变化,变量 2 在 0-100 之间变化,对我们来说应该没有关系。
我们不知道 y 和(x1,x2,x3)之间关系的本质。它可能是一次函数,二次函数,或者其他我们不知道的函数。我们所知道的是输入变量可以变化的范围。该关系在变量空间的某些部分可以是近似线性的,而在其他部分可以是非线性的。
由于我们事先没有这些信息,所以从一个小的输入变量空间开始,在这个区域进行一些实验,然后根据我们在这个区域的发现移动到整个变量空间的其他区域是有意义的。这种实验方法被称为顺序策略。我们从小处着手,并在有希望的方向上增加赌注,而不是从大处着手(即,一次性承担整个可变空间)
实验设定 1
我做了第一组实验,所有三个(x1,x2,x3)值都在[0,1]区域。我们注意到,这些是换算值,输入参数的实际值可以通过再次将换算值转换为未换算值来找到。在这个区域,我进行了所谓的 2 +4 中心点实验。这包括从该区域仔细选择 12 种(x1,x2,x3)组合,并测试由这些组合制成的沥青的抗压强度。你可以在这里了解更多 2 +4 方法 。
你可能会问我,我是如何在这些实验中找到抗压强度的。我是从教授提供的基于 excel 的计算器中得到的!在现实世界中,材料科学家将在实验室进行这些实验,并确定这些值。别无选择!
所以实验组 1 的设计如下:
实验装置 1 的设计
因子及其范围:x1(0.00–1.00)、x2(0.00–1.00)和 x3(0.00–1.00)
2 (1 次重复)+ 4 个 CP,总共 12 次运行
动机:如前所述,我们现在不知道我们在参数图上的位置,我们是在包含最佳值的区域,还是在斜坡或山脊上。所以我们从参数空间的一个小区域的实验开始,拟合一个模型来检查,然后继续。
实验表如下所示。这样的表格可以在 Minitab 或 Python / R 中轻松生成:
2 +4 CP 设计(图片由作者提供)
我在 Minitab 中做了回归,但同样,它可以在任何标准软件包中完成。这 12 个实验的回归结果如下图所示:
2 + 4 CP 设计的回归结果(图片由作者提供)
正如我们所观察到的,由于 Ct Pt 变量具有相当高的 p 值(0.866),曲率在该区域并不显著。此外,交互术语如 x1x2、x1x3 等也不重要。因此,我去掉了中心点和这些相互作用项。再次运行回归后,结果如下:
去掉中心点和相互作用项后 2 + 4 CP 设计的回归结果(图片由作者提供)
下图显示了该模型的残差图:
y 变量相对于 x1 和 x2 的等值线图如下所示:
去掉中心点和交互项后的 2 + 4 CP 设计的等高线图(图片由作者提供)
强度相对于 x1 和 x2 的等高线图表明我们在一座山的斜坡上(图形山),并且我们应该在最陡的斜坡上上升以快速到达最佳点。
实验组 1 的结论
因此,实验组 1 的结论如下:
x1、x2 和 x3 是重要的,如 p 值所示,而相互作用项不重要,并且在该区域也没有曲率
x1 在该区域具有最大的影响,如与其他变量相比相对较高的斜率所示(0.4538)
-拟合似乎很好:高𝑅(调整后)=98.98%,残差无异常,如上面的残差图所示(残差无非正态性,无异方差)
-很明显,我们在一座山的斜坡上,我们需要沿着最陡的上坡路径在实验区域中移动。
最陡峭的上升路径
从线性回归模型中,我们发现 x1、x2 和 x3 的系数分别为 0.4538、0.1213 和 0.2628。我们使用这些系数来寻找最陡的上升路径。
我们从中心点(0.5,0.5,0.5)开始
影响最大的是 x1,其步长为 1
接下来是 x3 的效果,其步长大小为 1 x 0.2628/0.4538 = 0.579
接下来是 x2 的效果,其步长大小为 1 x 0.1213/0.4538 = 0.267
最陡爬坡路径如下表所示:
最陡上坡路径(图片由作者提供)
点(4.5,2.1,4)是目前为止最陡的上坡的最佳点。要么我们现在已经越过了山顶,要么我们已经越过了山脊。
为了确定函数在这一点的形状,我们以(4.5,2.1,4)为中心点做一组新的实验。
实验装置 2 的设计
实验二还是以(4.5,2.1,4)为中心的 2 + 4 CP 实验。
因子及其范围:x1(4.0–5.0)、x2(1.6–2.6)和 x3(3.5–4.5)
2 (1 次重复)+ 4CP,共 12 次运行
*动机:*我们想了解 y 在(4.5,2.1,4)附近如何变化。如果(4.5,2.1,4)恰好是一圈同心圆的中心点,那么我们已经到达了顶点。否则,我们需要做更多的工作来达到最佳值。
实验组 2: 2 +4 CP 设计(图片由作者提供)
这 12 个实验的回归结果如下图所示:
2 + 4 CP 设计的回归结果(图片由作者提供)
很明显,曲率效应现在很重要,除了 x1x2 之外的相互作用效应并不显著。我们再次看到 x1x3 和 x2x3 的影响并不显著,这表明 x3 可能不会与 x1 和 x2 相互作用,因此可以单独进行优化。*因此,向前看,我将 x3 作为固定值,并进行实验以找到 x1 和 x2 的最佳值。*一旦找到,x3 已被单独优化。
下面的回归拟合没有交互效应 x1x3 和 x2x3:
去掉中心点和相互作用项后+ 4 CP 设计的回归结果(图片由作者提供)
接下来,我通过用轴点和额外的中心点扩充 2 (1 次重复)+ 4 CP 模型来拟合响应面模型。由此产生的设计被称为中心复合设计,有 20 次实验运行,如下表所示:
以点(4.5,2.1,4)为中心的中心复合设计
CCD 帮助我们找到这个区域的函数方程。中心复合设计回归分析产生以下结果:
以(4.5,2.1,4)为中心的 CCD 实验设计的回归结果(图片由作者提供)
以 x1 和 x2 为变量的函数的等值线图如下所示:
以(4.5,2.1,4)为中心的 CCD 实验设计的等高线图—箭头显示 y 最大增加的大致方向(图片由作者提供)
实验组 2 的结论:
由于 x1 的系数为负,x2 的系数为正,所以当 x1 减小而 x2 增大时,y 有可能增大。这通过上面所示的以(4.5,2.1,4)为中心的等高线图得到了证实。这里似乎有一个山脊,我们的移动方向应该是箭头所指的山脊顶部。
实验集 3
我将下一组实验集中在点(4,2.5,4)上,该点位于前面等高线图中所示的箭头处。这是我下一个实验的下一个地点,我在下面描述了它:
实验装置 3 的设计
因子及其范围:x1(3.5–4.5),x2(2.0–3.0),x3 =4.0(固定)
动机:这里的目标是向山脊值递增的方向移动,并检查相邻区域的 y 值如何变化。考虑到响应函数的高度非线性特性,应采取小增量的步骤。
我从 2 (1 次重复)+ 4 CP 开始,并根据对显著曲率的检测改变为响应面设计(CCD),其运行如下所示:
以点(4,2.5,4)为中心的中心复合设计
该集合的回归分析结果如下所示。我删除了不重要的术语,并在此展示了仅包含重要术语的模型:
以(4,2.5,4)为中心的 CCD 回归结果(图片由作者提供)
该区域的等高线图如下所示:
以(4,2.5,4)为中心的 CCD 等高线图—箭头显示 y 最大增长的大致方向(图片由作者提供)
同样,该模式是朝着 x1 的较低值和 x2 的较高值增加的增加脊。因此,下一步是在相邻的 1 阶盒区域进行实验,即 x1 =[3–4]和 x2 =[2.5–3.5]。为了简洁起见,我展示了等高线图来指示接近的方向,而不是详细讨论接下来两个 CCD 实验的结果。这些实验在以下地区进行
4.x1 =[3–4]和 x2 =[2.5–3.5]
5.x1 =[2.5–3.5]和 x2 =[3–4]
6.x1 =[2–3]和 x2 =[3.5–4.5]
从所有这 3 个区域得出的一般结论是,响应面设计更合适,轮廓开始显示接近峰值的模式。这些区域的等高线绘制如下。
区域 4、5 和 6 的 CCD 等值线图——箭头显示了 y 最大增长的大致方向(图片由作者提供)
来自实验组 3 的结论(包括区域 4、5、6 中的 CCD 运行):
现在很清楚,我们可能正在接近一个峰值,下一个逻辑步骤是继续朝着减少 x1 和增加 x2 的方向前进,并移动到下一个区域。
实验集 4
这很可能是峰值区域,我在(2,4,5,4)中心做了一个 CCD
实验装置 4 的设计
因子和范围:x1(1.5–2.5),x2(4.0–5.0),x3 =4.0(固定)
实验四:以(2,4.5,4)为中心的 CCD(图片作者提供)
回归响应和等高线图如下所示:
以(2,4.5,4)为中心的 CCD 回归结果(图片由作者提供)
(2,4,5,4)周围区域的 CCD 等值线图—最佳值区域(图片由作者提供)
很明显,我们已经达到了一个峰值,y 的最大值出现在 x1 = 2 和 x2 = 4.5
现在很清楚,最佳值出现在 **x1 = 2 和 x2 = 4.5 处,**我们现在必须找到 y 值最高的 x3 的值。因为我们发现 x1、x3 和 x2、x3 之间没有交互作用,所以我们可以简单地运行 10 个实验,其中 x1 和 x2 的值为最佳值,x3 在 0.5 和 5.0 之间变化。
下表显示了 10 次试验:
实验确定 x3 的最佳设置(图片由作者提供)
基于这 10 次运行,很明显 y 的全局最优值出现在 x1 = 2、x2 = 4.5 和 x3 = 5(这些是编码值,但是可以通过简单的线性变换容易地解码),并且 y 的值是 9.52
实验顺序图
我所做的一系列实验如下图所示:
为确定最佳设置而执行的一系列实验(图片由作者提供)
驻点描述
我还使用简单的微积分在(2,4,5,4)周围的区域中解析地导出了静止点,以检查最优值集。
最佳点的描述(图片由作者提供)
回归方程给出了 y 的期望值,但也有与之相关的标准差。我是在最佳设置下计算的:
最佳参数设置下抗压强度标准偏差的计算
我们可以使用这个标准偏差来找到抗压强度的置信区间,该置信区间可以反过来用于确定我们可以接受的强度下限,比如 95%置信区间。
结论
简而言之,多元优化的实验设计方法是一种强大的方法,它使用小步前进的原则,并利用未知设计函数在搜索空间中探索最大收益的路径。它帮助我们通过采取这些智能步骤快速找到最佳值,而不是使用在计算和财务上非常昂贵的暴力方法。我用三个参数工作,这有助于可视化算法在做什么。然而,这种技术也可以适用于大规模的多元问题。
我希望我的帖子能引发你进一步探索实验设计的兴趣!
树集合层上的解释器
原文:https://towardsdatascience.com/an-explainer-on-tree-ensemble-layer-b7e445621a3f?source=collection_archive---------17-----------------------
一种具有决策树优点的新型神经网络层。
由 Unsplash 上的 Pietro Jeng 拍摄
神经网络和决策树都在多个机器学习问题上表现出色。如果我们可以在一个模型中同时获得两者的优点,会怎么样?这就是谷歌研究团队试图在他们名为树集成层:可微性符合条件计算的论文中寻求的东西。
树支持条件计算,即它们能够通过少量节点路由每个样本。这可以带来性能上的好处,增强统计属性,并有助于可解释性。但是树的性能严重依赖于特征工程,因为它们缺乏表示学习的机制。这是神经网络的优势所在,特别是在图像和语音识别问题上,尽管缺乏对条件计算的支持。本文提出了神经网络的一层可加可微决策树,树集成层(TEL),。该层可以插入神经网络中的任何位置,并且可以通过标准的基于梯度的优化方法(例如 SGD)来训练。
可微分决策树
软路由,https://arxiv.org/abs/2002.07772
在经典的决策树中,每个样本在每个节点处被精确地指向一个方向(硬路由),这在损失函数中引入了不连续性。由于不能应用连续优化技术,所以采用贪婪方法来构建树。软树是执行软路由的决策树的变体,即以不同的比例将每个样本路由到左侧和右侧。在这种结构中,损失函数是可微的,并且可以使用基于梯度的优化方法。
但是我们如何对一个特定样本, x, 到达一个叶节点, l 的概率建模呢? 为了到达节点 l ,样本 x 必须访问其所有的祖先节点。并且在每个节点都会以一定的概率发送到左右两个子树。到达节点 l 的总概率是在每个节点移动到包含 l 的子树的联合概率。
样本 x 到达节点 l 的概率
r_i,l(x) 是在节点 i ,样本 x with 将向包含叶子 l 的子树移动的概率。逻辑函数是激活函数的一个普遍选择,但它并不精确地给出 0 或 1。这意味着需要计算所有节点,计算量随着树的深度呈指数增长。继连续和可微分激活函数被提出来解决这个问题:
平滑阶跃激活函数
选择 \gamma 控制硬路由到 0 或 1 的样本数。该函数非常接近逻辑函数。
平滑步长 vs 逻辑函数(1/(1+e^(-6t)):https://arxiv.org/abs/2002.07772
条件计算
为了优化 TEL,可以使用一阶优化方法,例如随机梯度下降(SGD)的变体。梯度的计算随着树的深度呈指数增长,这已经成为一个主要的瓶颈。通过利用上面定义的激活函数及其梯度中的稀疏性来开发有效的前向和后向传播。
**条件正向传递:**在计算梯度之前,需要在树上正向传递。这里,通过丢弃任何子树和随后的计算来利用稀疏性,其中激活函数被硬路由到 0。
**条件反向传递:**反向传递遍历树,用梯度更新每个节点。值得注意的重要观察是,对于值被硬路由到 0 或 1 的任何节点,梯度都是 0。因此,在后向过程中要访问的节点数量甚至低于前向过程中访问的节点数量。这是通过创建节点数量减少的分数树来实现的,从而加快计算速度。
来自论文的实验结果表明,TEL 实现了与梯度增强决策树(GBDT)和密集神经网络(DNN)层竞争的性能,同时导致显著更紧凑的模型。这篇论文非常有趣,因为它采用了一种新的方法将可解释性引入神经网络模型。DNN 中的每个隐藏层学习一个表示,将 TEL 层放在输出层之前肯定有助于理解该表示与输出的直接联系。
- Hazimeh,h .,Ponomareva,n .,Mol,p .,Tan,z .,& Mazumder,R. (2020 年 11 月)。树集合层:可微性满足条件计算。在机器学习国际会议(第 4138–4148 页)。PMLR。
使用经验测试解释回归的偏差-方差权衡
原文:https://towardsdatascience.com/an-explanation-of-bias-variance-trade-offs-for-regression-using-empirical-testing-d6935140139f?source=collection_archive---------47-----------------------
实证模拟可以增强有抱负的数据科学爱好者对统计概念的理解。
摄影:迈克尔·斯科特在的 Unsplash
偏差-方差权衡是机器学习初学者的基本学习要求,以确保基于样本数据选择最合适的模型。关于这一主题的最常见的在线图表如图 1 所示,它显示了三种类型的误差:偏差、方差和总误差以及它们之间的关系。随着模型复杂性的增加,偏差减少,而方差增加,总误差呈抛物线形状。尽管许多专家对此进行了严谨的论述,但这些解释可以通过一定的实证实验来补充,以帮助学习者对这一概念获得令人满意的直观理解。这篇文章的目的是在计算机上使用随机数据计算偏差和方差。
在我们开始之前,为了一致性和更好的理解,注意某些定义和符号是有用的[1,2]:
**模型的类/族:**线性的、某次多项式的、或其它一些具有确定结构的非线性模型(如 ax2 + bx +c 属于模型的二次族)
**成员模型:**是模型的实例,参数固定。例如,典型的二次方程(3x2 + 7x + 1)就是二次方程族的一员。
**偏差:**是响应变量的观察值(真实值)与拟合响应的期望值之间的差值。它是模型的属性,而不是数据。
**方差:**描述模型的输出如何根据看不见的数据而变化。与偏差一样,偏差-方差概念中的方差也是模型的一个属性。
样本数据挑战
在现实世界中,计算与模型拟合相关的偏差-方差图具有挑战性,原因有两个。首先,我们从来没有超过一个数据集,这就是为什么自举采样变得流行。该技术从单个数据集随机生成许多数据集,这不仅有助于选择正确的模型系列,还可以识别该系列中最合适的模型成员。第二,我们常常把观察值当作真实总体的最具代表性的值。如果一个样本包含几个数据收集偏差[3]并且不具有代表性,那么重复重采样对减少原始样本中的误差作用不大;
虽然我们不能改变现实,但多亏了计算机,我们总是可以创造我们自己的现实,产生合成数据来理解统计概念,并根据经验对它们进行测试。让我们假设输入变量(为简单起见,考虑一个输入变量)和观察到的响应变量之间的关系(在现实世界中我们从来不知道)可以用下面的等式表示(参见 get_y 函数):
import numpy as np
import matplotlib.pyplot as plt
import pandas as pdfrom collections import defaultdictfrom sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeaturesdef get_y(x):
# yes I know, it is complicated; don't ask how I came up with it
y = np.sin(x) + 0.001*(x**4 + 4*x**3 - 20*x**2 + 400)
# adding noise
rand_err = [np.random.normal(0,0.1*abs(i)) for i in y.flatten()]
y = y + np.array(rand_err).reshape(samp_size, 1)
return ydef transform_x(x, order):
poly = PolynomialFeatures(order)
return poly.fit_transform(x)
第二个等式中的最后一项表示均值为零的正态分布噪声。我们首先随机生成一个样本大小为 50 的数据集 X (x_true),并计算相应的 Y 值(y_true + errors)(见图 1)。这代表了我们将用于比较的具有真实(或测试)值的基线数据集。
图 1 输入和输出变量之间的真实关系
现在,我们将其重采样 100 次,以获得总共 100 个样本,每个样本有 40 个数据点,响应变量中添加了随机噪声。我们拟合了次数从 1(线性回归)到 9 众多多项式回归模型。因为只使用了一个变量,所以不存在交互项。下面分享了代码片段
np.random.seed(24)y_pred = defaultdict(list)
y_pred_mean = defaultdict(list)
bias, variance = dict(), dict()range_of_error = dict()nsamp = 100
samp_size = 50# getting a baseline dataset (lets call it true dataset)
x_true = np.linspace(-7, 7, samp_size).reshape(samp_size, 1)
y_true = get_y(x_true)fit_models = ['PolyReg1', 'PolyReg2', 'PolyReg3', 'PolyReg4', 'PolyReg5',
'PolyReg6', 'PolyReg7', 'PolyReg8', 'PolyReg9']for name in fit_models:
# transforming true (test) input for the polynomial model
order = int(name[7:])
trans_x = transform_x(x_true, order = order)
for i in range(nsamp):
# bootstraping sampling with replacement
idx = np.random.choice(samp_size, samp_size)
x = x_true[idx]
y = get_y(x)
poly = PolynomialFeatures(order)
x = poly.fit_transform(x)
model = LinearRegression()
model.fit(x, y)
ytemp = model.predict(trans_x) # temporary variable
y_pred[name].append(ytemp.flatten())# to numpy array
y_pred[name] = np.array(y_pred[name])
y_pred_mean[name] = y_pred[name].mean(axis=0)# bias of the estimator
# E((f(x) - E(y_fit))**2)
# for each single point from all datasets
bias[name] = (y_true.flatten() - y_pred_mean[name])**2
# average over all data points
bias[name] = bias[name].mean()
range_of_error[name] = (y_true.flatten() - y_pred[name])**2
range_of_error[name] = range_of_error[name].mean(axis=1)
# for each point from over all datasets
# indirect formula
#variance[name] = ((y_fit_mean[name] - y_fit[name])**2).mean(axis=0)
# standard formula
variance[name] = y_pred[name].var(axis=0)
# average over all data points
variance[name] = variance[name].mean()
结果
图 2 显示了简单模型(线性回归)在解释训练数据时表达性较差,这需要更高阶的多项式来获得更好的性能。当我们从简单模型转向复杂模型时,在 6 阶多项式的误差再次增加之前,5 阶多项式似乎为模型提供了最佳“拟合”。虽然并不完美,但这是偏差-方差计算的传统表示。
图 2 偏差方差权衡;来源:图片由作者提供;注 : PolyRegK:第 k 阶多项式回归。为了更好地说明,这些值已针对所有模型的最大值进行了标准化。
然而,进一步的过度拟合实际上减少了误差、偏差以及方差,这似乎是一个双重下降的观察结果,这是数据科学界正在讨论的话题[4,5]。双下降现象表明,过拟合的缺点可能仅在模型复杂性达到一定水平时出现,并且极高水平的复杂性不一定会恶化模型性能。
图 3 显示了不同模型的分布。绿色曲线显示真实数据,而红色曲线描述模型对所有数据集的预期(平均)预测。灰色散点图显示了每个数据集的预测值。正如我们所见,高阶多项式的偏差较低(红色曲线接近绿色曲线),但对于某些多项式,分布(灰色分散区域)变得更宽。
图 3 不同模型相对于真实模型的性能
测试误差范围
我们还可以通过使用我们的合成数据集来检查每个模型的误差范围。从图 4 中可以看出,均方误差的范围是真实数据集(所有数据集通用)和每个数据集的拟合值之间的差异。虽然每个模型的平均值反映了图 1 的值,但它显示了测试误差如何从一个数据集变化到另一个数据集。红色和蓝色虚线显示,对于某些数据集,“差”拟合模型可能比更具表现力的模型具有更少的测试误差。没有足够的高质量样本,单一数据集可能导致模型选择不当,这强调了使用单一数据集的多个变量生成偏差-方差曲线的重要性。
请注意,箱线图中的方差(分布)可能看起来是相关的,但它在数学上不同于偏差-方差图中的方差。在这里,它是基于不同数据集的预测误差的分布,与偏差-方差权衡不同,方差描述偏差的分布,是模型的一个属性
图 4 均方误差范围;来源:图片由作者提供
结论
这篇文章的目的是帮助初学者,包括我自己,通过经验模拟对偏差-方差概念有一个更直观的理解。偏差-方差权衡是一个统计学术语,像统计学中的所有其他概念一样,适用于预测的“预期”结果,而这种结果不能仅由一个样本数据集产生。Bootstrapping 技术可用于重现给定数据集的变量,并反复拟合模型以计算预期预测值以及预测值与观测值的差异。
虽然我使用回归进行说明,但是这个概念也应该适用于分类问题。鼓励读者进一步探索最近关于偏差-方差误差曲线双下降的发现[4,5],其中随着模型复杂性的增加,偏差-方差权衡可能不再成立。
参考文献
[1]威廉·科恩,机器学习中的偏差-方差 (2008),机器学习,10–601 课堂讲座,CMU。
[2]A . Singh 和 Eric Xing,偏差方差权衡和模型选择 (2012),机器学习 10-701/15-781,CMU
https://en.wikipedia.org/wiki/Sampling_bias
[4] P. Nakkiran,G. Kaplun,Y. Bansal,T. Yang,B. Barak,I. Sutskever,Deep Double Descent(2019),OpenAI,
[5]安德鲁·杨,每个数据科学家都应该知道:偏向-方差权衡一般化是错误的 (2021),对数据科学而言
70 年空间探测数据的探索性分析
原文:https://towardsdatascience.com/an-exploratory-analysis-on-7-decades-of-space-exploration-data-f0f2b78a6bb2?source=collection_archive---------27-----------------------
探索性数据分析
人类在太空最初 70 年的迷人见解和引人入胜的故事
美国宇航局在 Unsplash 拍摄的照片
简介
探索性数据分析是任何数据科学家工具集中的一项关键技能。用数据讲述故事的能力对于激励决策者、激发对某个话题、领域或主题的兴趣至关重要。毕竟,我们都喜欢好故事。
为了说明它的威力,我对 70 年的太空旅行数据进行了探索性分析。我想分享一些令人着迷的见解,这些见解一定会让你震惊和惊喜。有无数种方法来分析数据进行探索,但最终为了防止你迷失方向,你应该始终牢记你探索的目的。
在整篇文章中,我用宇航员这个词来指代任何去过太空的人
接近
为了让读者了解,我从数据中提取了一些见解,并以“前 10 名”、记录和显著成就的形式表达出来,从而构建了我的分析。
为了提供一些背景信息,我制作了一个太空任务的时间序列。我以此开始,来描绘一幅太空旅行在过去 70 年中是如何发展的画面。
尽管火箭、卫星和公司是太空探索的重要组成部分,但我的大部分分析还是集中在宇航员本身的成就上。来自这些数据的一些最令人着迷的见解与你可能认为人类不可能取得的成就有关。
重要的是要记住,人们通常会更好地与关于他们的故事联系起来;任何数据科学家在进行探索性数据分析时,如果他们希望讲述令人信服的故事,都应该记住这一点。
注意:所有的记录都与撰写这篇文章的时间有关。
数据
在我的探索中,我使用了两个数据集,它们都是公开的。一个是太空任务级别,另一个是宇航员级别。重要的是要记住,任何数据都不应该用大写字母“D”来表示,任何来自数据的见解都应该进行感官检查。通过这样做,我发现了一些数据质量问题。
宇航员:2020 年 1 月 15 日前参加过太空任务的所有宇航员。数据来源是 NASA、Roscosmos 和好玩的网站。数据集是任务宇航员级别的,包含每个宇航员的详细信息和特定任务的详细信息。它由 517 个独特的任务组成,假设一个单一的任务可以通过连接任务年份、任务名称和 ascend shuttle 来识别。
任务 :这是从网上抓取的任务级数据。它包括了自 1957 年开始以来的所有太空任务。详细介绍了任务的各个方面,如成本、火箭、发射时间、位置等。飞行任务数据包含 4,324 次飞行任务,其中 3,879 次是成功的。
宇航员数据中的任务总数与任务数据之间有很大的差异。对此的一个解释可能是因为任务数据中捕捉到的许多追踪都是无人驾驶的。
工具
我使用 Python 进行所有的数据探索。许多数据争论都是在 NumPy 和 Pandas 图书馆的帮助下进行的。
对于数据可视化,我使用了 Matplotlib 和 Seaborn。我不会在这篇文章中分享代码片段。但是,我会在 GitHub 中提供完整的端到端代码。
太空探索背景
作者图片
自 1957 年开始太空探索以来,太空任务的数量逐年上升,1971 年达到 119 次的高峰。它保持在每年 97 次以上,直到 1979 年下降到 49 次。直到 2018 年,它才再次恢复,当年达到了 117 次任务。是什么导致了这次下跌?
以下是一些可能性:
1971 年——联盟 11 号的机组人员在脱离空间站礼炮 1 号后遇难。
1975 年——美国和苏联联合进入太空,引发了太空竞赛的结束。
1986 年——挑战者号航天飞机发射 73 秒后发生灾难,机上 7 名机组人员全部遇难。
2018 年的复兴可能是由企业对太空探索兴趣的不断扩大所驱动的。像 SpaceX 和中国 CASC 这样的公司已经因其在该领域的成就而成为头条新闻。
仅在 2020 年 1 月,CASC 就完成了 19 次发射,SpaceX 完成了 14 次。
成为一名宇航员需要多久?
从选择(训练开始)到第一次任务的平均时间约为 6.3 年。75%的宇航员在最初选择的 8 年内完成了他们的第一次任务,特别是 25%的宇航员在 4 年内完成了任务。
作者图片
太空行走者
也许比月球漫步更酷,太空行走指的是在地球大气层以外的交通工具中度过的时间。它被记录为宇航员数据中的舱外时间。
作者图片
Anatoly Solovyev,现已退休的俄罗斯苏联宇航员,进行了 16 次太空行走,他保持着太空行走次数的记录。阿纳托利的舱外时间似乎存在一些数据质量问题。在一次任务中,他的时间记录大于他在所有任务中的总时间。这就是为什么不完全相信你得到的任何数据是至关重要的!
因此,我无法从他最长的太空行走或太空行走总时间的数据中得出任何见解。他的官方记录是 82 小时。
阿纳托利·索洛维耶夫来源
阿纳托利是一名军事指挥官;他最后一次任务是在 1997 年。一想到在太空行走时间最长的人是军人,就觉得很可怕。他在上面做什么?
太空长老
目前最年长的太空行走者是帕维尔·维诺格拉多夫,他在 60 岁时进行了太空行走,累计时间为 6.62 小时。如果你认为宇航员通常年轻健康(嗯,不到 60 岁),你并不孤单。
作者图片
首次执行任务的宇航员平均年龄为 39 岁,四分之一的宇航员年龄超过 43 岁。四分之一的宇航员在第一次任务中年龄不到 31 岁。这看起来不像是年轻人的游戏。
记录:最老的太空旅行者是小约翰·h·格伦,他离开地球大气层时 77 岁。
这张照片归功于美国国家航空航天局。
在轨道上穿梭
国际空间站是在轨道上执行任务最多的航天飞机。任务数在 125 左右。这是和平号空间站任务次数的两倍多,该空间站由苏联运营,于 2001 年解散。
作者图片
国际空间站是一个绕地球轨道运行的大型宇宙飞船。它绕行一周大约需要 90 分钟,速度大约为每小时 17500 英里。美国宇航局目前使用该飞行器来了解人们如何在太空中生活和工作。顾名思义,几个国家合作维护和使用空间站。相对而言,这就解释了为什么对它的访问如此之多。
空间站的体积相当于一栋五居室的房子(或两架波音 747 飞机)。
点击这里了解更多关于国际空间站的信息。
礼炮 7 号:礼炮 7 号有 13 次任务,最后一次是在 1985 年。空间站最终坠毁在地球上。
我们的数据表明,在所有在轨航天器任务中,有两次爆炸。事实上,这只是一次爆炸:1986 年的挑战者号灾难。field ascend 航天飞机存在一些数据质量问题,1985 年挑战者号一半的机组人员乘坐了不同的航天飞机。
图片由美国宇航局拍摄:号许可【1986 年挑战者号灾难
单次任务在太空停留时间最长
这个奖颁给了瓦列里·波利亚科夫,他在太空中度过了 10,000 个小时(相当于单程 14 个月)。他是前宇航员,这次旅行是在和平号空间站上进行的。
作者图片
使命的故事
美国在记录的太空任务总数中领先,大约有 283 次。这比俄罗斯、日本和加拿大的任务总和还要多,它们是下一个最有竞争力的国家。
失败:美国海军的任务失败率最高,在其 17 项任务中高达 82%。很有可能,虽然他们已经掌握了海洋,但他们完全超出了太空的深度。另一种可能是,他们对自己的表现要求更高。
作者图片:方格条代表任务数量,实线代表失败率
任务总数和失败率之间有微弱的负相关(-0.26)。进一步研究是什么驱动了成功的太空任务将会很有趣。
更多战绩
第一个进入太空的人:第一个进入太空的人是尤里·加加林,他是苏联空军飞行员,于 1961 年遨游太空。尤里实现这一飞跃时才 27 岁,在太空旅行者的年龄中,他排在倒数第 25 位。
图片由[RV 1864](https://www.flickr.com/photos/summer1978/18699907011/in/photolist-uurURR-dzCg8c-9ABkZi-f468mg-bAm8Z1-DNSjdt-4unfG4-2dNUS2s-XraPVr-288N7tE-9z6PY1-UBdyen-8VGDJD-9xMBK9-MZEvCN-dwERLu-srbeQu-in6ohs-f7bYPM-uHrLn-ajDGGA-2aZX5oA-czqSiy-a5qd97-26k7noA-27eWiD1-fME5Dm-a5nkrH-4ESQpE-2ixsEPw-2iHgMi7-2jw1UoA-tf8Emu-2jw32Bs-2jQwEdQ-GjnrDM- 8tfKrx-2jFxe5L-2jcpVqF-2jKXocg-AYuHHf-f4kV2u-potVBA-4VKdGR-ruwZrP-7xMx5q-9xKGte-f46CnM-3JZUPU-f46DjR)T2 授权:尤里·加加林
第一位进入太空的女性:瓦伦蒂娜·捷列什科娃是第一位也是最年轻的进入太空旅行的女性。1963 年,26 岁的她在东方 6 号上独自执行任务。
图片由詹姆斯·乔尔 授权拍摄:瓦伦蒂娜·捷列什科娃
Svetlana Svitskaya 是第二位进入太空的女性,也是第一位进行太空行走的女性。在 1984 年前往礼炮 7 号的任务中,她完成了 3.58 小时的行走。她当时 36 岁。
另一个值得一提的是 Kathryn D. Sullivan,她在同年进行了 3.45 小时的太空行走,成为第一位在太空行走的美国女性。
进一步分析
任务成本:看看任务成本的趋势会很有见地。有很多缺失的数据,并且该字段极其混乱,成本用字符串表示。即使在尝试将它们转换成 floats 之后,仍然有几个实例会产生异常。
为了进一步分析,我想生成一个每年任务平均费用的时间序列。由于所有的缺失值,只有一个样本的成本是可用的,因此我推断人口平均在 95%的置信区间。
预测模型:并不是所有的太空任务都是成功的。失败的原因大概有一些共性。也许可以用任务数据做一些预测模型,以了解是什么驱使任务成功或失败。我的数据中没有足够的特征来生成有用的模型。然而,也许我可以通过获得更多的任务数据来扩展分析。或者甚至利用数据集中的一些高基数字段进行特征工程。
最后的想法
我可以从许多不同的方向进行分析。然而,我把大部分分析集中在人身上,因为我相信这是最引人注目的故事的来源。
🚀我已经创建了一个活页夹,所以你可以用这个笔记本进行实验请点击这里查看这个笔记本!
https://www.linkedin.com/in/john-adeojo/
使用 Python 3 从 Twitter API v2 收集用于学术研究的推文的广泛指南
原文:https://towardsdatascience.com/an-extensive-guide-to-collecting-tweets-from-twitter-api-v2-for-academic-research-using-python-3-518fcb71df2a?source=collection_archive---------0-----------------------
实践教程
从设置、访问端点到保存以 CSV 格式收集的推文的一步一步的过程。
由 NASA 在 Unsplash 上拍摄的照片
目录:
- 介绍
- 开始的先决条件
- 不记名代币
- 创建标题
- 创建 URL
- 连接到端点
- 把所有的放在一起
- 将结果保存到 CSV
- 循环请求
1.介绍
2020 年底,Twitter 推出了全新构建的 Twitter API。Twitter API v2 提供了更多您可以提取和分析的特性和数据、新的端点和许多功能。
随着新 API 的引入,Twitter 也为学术界引入了一个新的强大的免费产品:学术研究产品 track 。
该路线允许免费访问完整存档搜索和其他 v2 端点,每月的推文量上限为 10,000,000 条!如果你想知道你是否有资格进入赛道,请查看这个链接。
我最近在卡耐基梅隆大学从事一个数据分析研究项目,利用本专题提供的能力,作为一名研究人员,它给你的力量是令人兴奋的!
然而,由于 API 的 v2 是相当新的,如果您在收集数据进行研究的过程中遇到问题,那么存在的资源会更少。
因此,在本文中,我将一步一步地介绍从设置、访问端点到保存以 CSV 格式收集的 tweets 以供将来分析使用的过程。
本文将使用仅适用于学术研究跟踪的端点(全存档搜索端点),但是本指南中的几乎所有内容都可以应用于适用于所有开发人员帐户的任何其他端点。
如果您没有访问完全存档搜索端点的权限,您仍然可以使用最近搜索端点来遵循本教程。
建议您在阅读本文时使用 Jupyter 笔记本,这样每个代码片段都可以在单独的单元格中运行。
2.启动的先决条件
首先,我们将为本指南导入一些基本的库:
为了能够向 Twitter API 发送您的第一个请求,您需要有一个开发人员帐户。如果你还没有,可以在这里申请一个! (别担心,这是免费的,你只需要提供一些你打算从事的研究的信息)
获得批准的开发者帐户了吗?太棒了!
你所需要做的就是创建一个项目,并通过开发者门户连接一个应用程序,我们就可以开始了!
- 转到开发者门户仪表板
- 使用您的开发者帐户登录
- 创建一个新项目,给它一个名字,一个基于你想要实现的目标的用例,以及一个描述。
新项目页面截图
4.假设这是你第一次使用,请选择“创建新应用”并为你的应用命名,以便创建新应用。
为你的应用程序选择一个名称
如果一切顺利,您应该能够看到包含您的密钥和令牌的页面,我们将使用其中一个来访问 API。
图片也取自 Twitter 开发团队创建的这个分步指南。
3.不记名令牌
如果你已经走到这一步,**恭喜你!**您有资格从 API 发送您的第一个请求:)
首先,我们将创建一个 auth() 函数,该函数将具有来自我们刚刚创建的应用程序的“不记名令牌”。
由于这个不记名令牌是敏感信息,你不应该与任何人分享它。如果你和一个团队一起工作,你不希望任何人能接触到它。
因此,我们将把令牌保存在一个“环境变量”中。
有很多方法可以做到这一点,你可以看看这两个选项:
环境变量。env 与 Python利用 Python 中的环境变量
在本文中,我们将在代码中运行这一行来设置一个 "TOKEN" 变量:
os.environ['TOKEN'] = '<ADD_BEARER_TOKEN>'
只需将 Twitter 上的******替换为您的不记名令牌,运行该函数后,删除这两行。如果这种方法有任何错误,请尝试上面列出的任何链接。
现在,我们将创建我们的 auth() 函数,它从环境中检索令牌。
4.创建标题
接下来,我们将定义一个函数,它将获取我们的承载令牌,传递它以进行授权,并返回我们将用来访问 API 的头。
5.创建 URL
现在我们可以访问 API 了,我们将为将要使用的端点和要传递的参数构建请求。
上面定义的函数包含两部分:
A.搜索 _url:
这是我们想要访问的端点的链接。
Twitter 的 API 有很多不同的端点,下面是在撰写本文时可以提前访问的端点列表:
撰写本文时存在的一些早期访问端点
您还可以在这个链接中找到关于每个端点的完整列表和更多信息。
对于这篇文章,因为它是针对可能试图从 Twitter 的新产品中受益的学术研究人员,我们将使用 全存档搜索端点 。
B.查询参数:
端点提供的参数,我们可以使用这些参数来定制我们想要发送的请求。
每个端点都有不同的参数,我们可以传递给它,当然,Twitter 的文档中有每个端点的 API 引用!
例如,对于我们在本文中使用的全存档搜索端点,您可以在这里的 API 参考页面的**“查询参数”**部分下找到查询参数列表。
完整归档端点 API 文档中的查询参数示例屏幕截图
我们可以将上面函数中的查询参数分解为三个部分:
该端点参数的简单分解
1.前 4 个参数是我们控制的参数
'query': keyword,
'start_time': start_date,
'end_time': end_date,
'max_results': max_results,
2.接下来的 4 个参数基本上是我们指示端点返回更多信息,这些信息是可选的,默认情况下不会返回。
'expansions': 'author_id,in_reply_to_user_id,geo.place_id',
'tweet.fields': 'id,text,author_id,in_reply_to_user_id,geo,conversation_id,created_at,lang,public_metrics,referenced_tweets,reply_settings,source',
'user.fields': 'id,name,username,created_at,description,public_metrics,verified',
'place.fields': 'full_name,id,country,country_code,geo,name,place_type',
3.最后,“next_token”参数用于获取下一页结果。参数中使用的值直接从 API 提供的响应中提取。如果存在比每个请求的上限更多的结果,我们将在本文中对此进行更多的讨论。
'next_token': {}
现在我们知道了 create_url 函数的作用,有几个重要的注意事项:
- 所需端点:
在全存档搜索端点的情况下,query参数是发出请求**所需* *的唯一参数。请务必查看您正在使用的端点的文档,以确认哪些参数必须存在,这样您就不会遇到问题。
- 查询参数:
查询参数是您放置想要搜索的关键字的地方。
查询可以简单到搜索包含单词“xbox”的 tweet,也可以复杂到(xbox europe)或(xbox usa),返回包含单词 xbox AND europe 或 xbox AND usa 的 tweet。
此外,可以使用搜索运算符定制查询。有很多选项可以帮助你缩小搜索结果的范围。我们有望在另一篇文章中更深入地讨论操作符。现在,你可以在这里找到构建查询操作符的完整列表。
带有操作符的简单查询示例: "xbox lang:en"
- 时间戳:
Twitter 用于时间戳的结束时间和开始时间格式是
YYYY-MM-DDTHH:MM:ssZ(ISO 8601/RFC 3339)
所以一定要把日期转换成这种格式。如果你不确定如何做,这是一个很好的时间戳转换器一定会有帮助。
- 成绩卷:
一个请求返回的搜索结果数量目前限制在 10 到 500 个结果之间。
现在你可能会问,我怎么能得到超过 500 个结果呢?这就是next_token和分页发挥作用的地方!
答案很简单:如果您的查询存在更多结果,Twitter 将返回一个唯一的 next_token ,您可以在下一次请求中使用它,它将为您提供新的结果。
如果您想要检索您的查询中存在的所有 tweet,您只需使用每次收到的新next_token不断发送请求,直到不存在 next_token 为止,这表明您已经检索了所有 tweet!
希望你不会感到太困惑!但是不要担心,当我们运行我们刚刚创建的所有函数时,就会很清楚了!
6.连接到端点
现在我们已经有了想要的 URL、头和参数,我们将创建一个函数将所有这些放在一起并连接到端点。
下面的函数将发送“GET”请求,如果一切都正确(响应代码 200),它将以“JSON”格式返回响应。
注意: next_token 默认设置为**【无】**,因为我们只关心它是否存在。
7.把所有的放在一起
现在我们已经有了所有需要的函数,让我们测试一下把它们放在一起创建我们的第一个请求!
在下一个单元格中,我们将设置我们的输入:
- 来自 API 的 bearer_token 和 headers。
- 我们将寻找包含单词“xbox”的英语推文。
- 我们将寻找 2021 年 3 月 1 日至 31 日之间的推文。
- 我们只想最多返回 15 条推文。
现在我们将创建 URL 并从 API 获得响应。
Twitter API 返回的响应以 JavaScript 对象符号“JSON”格式返回。
为了能够处理它并分解我们得到的响应,我们将使用我们之前导入的 python 的编码器和解码器。你可以在这里找到更多关于库的信息。
如果从以下代码返回的响应是 200 ,则请求成功。
url **=** create_url(keyword, start_time,end_time, max_results)json_response **=** connect_to_endpoint(url[0], headers, url[1])
让我们使用这个 JSON 库函数以可读的格式打印响应
print(json.dumps(json_response, indent=4, sort_keys=True))
现在让我们来分解返回的 JSON 响应,响应基本上是作为 Python 字典读取的,键要么包含数据,要么包含更多字典。最上面的两个键是:
A.数据:
字典列表,每个字典代表一条推文的数据。如何检索第一条推文创建时间的示例:
json_response['data'][0]['created_at']
B.元:
关于我们发送的请求的属性字典,我们通常只关心字典中的两个键, next_token 和 result_count 。
对两个键中数据的解释
例如,要检索 next_token,您可以编写:
json_response['meta']['result_count']
现在,我们有两个选项来保存结果,这取决于我们希望如何处理数据,我们可以将结果保存为我们收到的相同的 JSON 格式,或者保存为 CSV 格式。
要在 JSON 中保存结果,我们可以使用这两行代码轻松完成:
with open('data.json', 'w') as f:
json.dump(json_response, f)
8.将结果保存到 CSV
您可能会问自己,为什么我们要将结果保存为 CSV 格式?简而言之,与 JSON 对象相比,CSV 是一种广泛使用的格式,可以很容易地导入 Excel 电子表格、数据库或数据可视化软件。
现在,要将结果保存为 CSV 格式的表格,有两种方法,一种简单的方法和一种更加定制的方法。
嗯… 如果有一个通过 Python 库的简单方法,为什么我们需要自定义方法呢?
答案是:自定义函数将使我们将一些返回结果中嵌入的字典分解并精简到单独的列中,使我们的分析任务更容易。
例如,公共指标关键字:
"public_metrics": {
"like_count": 0,
"quote_count": 0,
"reply_count": 0,
"retweet_count": 0
},
该键返回另一个字典,简单的方法是将该字典保存在一个 CSV 列下,而在自定义方法中,我们可以在将数据保存到 CSV 之前将每个字典分成不同的列。
A.简单的方法是:
对于这种方法,我们将使用熊猫包
df = pd.DataFrame(response['json_response'])
df.to_csv('data.csv')
这是基于推特开发团队关于这个主题的博客文章的内容,我尝试了这个方法,它在简单的查询下运行得很好。
B.定制方法:
首先,我们将创建一个带有我们想要的列标题的 CSV 文件,我们将与我们的实际函数分开进行,这样以后它就不会干扰对请求的循环。
然后,我们将创建我们的 append_to_csv 函数,我们将把响应和期望的文件名输入到该函数中,并且该函数将把我们收集的所有数据附加到 csv 文件中。
现在,如果我们在最后一次调用中运行 append_to_csv()函数,我们应该有一个包含 15 条推特的文件(或者更少,这取决于您的查询)
append_to_csv(json_response, "data.csv")
9.循环请求
干得好!我们已经发送了第一个请求,并保存了第一个回复。
**现在,如果我们想保存更多的回复,该怎么办?**除了推特给我们的前 500 个结果之外,或者如果我们想在特定时期自动获得推特。为此,我们将使用循环和从 Twitter 接收的 next_token 变量。
让我们想想这个案例:
我们想收集 2020 年包含“新冠肺炎”一词的推特,分析人们在推特上谈论病毒时的情绪。可能有数百万条推特,我们每个月只能收集 1000 万条推特。
如果我们只是在 2020 年 1 月 1 日至 2020 年 12 月 31 日之间发送收集推特的请求,我们将很快达到上限,而不会在 12 个月内得到很好的分布。
因此,我们可以做的是,我们可以设定我们希望每月收集的推特数量的限制,这样,如果我们在某个月达到了特定的上限,我们就可以进入下一个月。
下面的代码就是一个例子,它将完全做到这一点!下面的代码块由两个循环组成:
- 我们希望覆盖的月/周/日内的 For 循环(取决于设置方式)
- 一个 While-loop,控制每个时间段我们希望收集的最大推特数量。
请注意,在调用之间添加了 time.sleep() ,以确保您不只是向 API 发送请求。
总结
在本文中,我们已经通过了一个广泛的逐步过程,使用 Python 从用于学术研究的 Twitter API v2 收集 Tweets。
我们已经涵盖了所需的先决条件,身份验证,创建请求和向搜索/所有端点发送请求,最后以不同的格式保存响应。
如果你喜欢这个,请随时通过 Twitter 和 LinkedIn 与你的朋友和同事分享!
请随时在 LinkedIn 上与我联系,或者在 T2 的 Twitter 上关注我!
置信区间的广泛指南和为什么你需要知道它
原文:https://towardsdatascience.com/an-extensive-guide-to-confidence-intervals-and-why-you-need-to-know-it-aca707fb2c3?source=collection_archive---------37-----------------------
像数据科学家一样思考这个重要的统计概念
乔恩·泰森在 Unsplash 上的照片
介绍
几乎在商业中的任何角色,你都必须做出估计:
- 在市场营销中,你必须估计未来活动的投资回报率。
- 在供应链管理中,你必须预测(估计)你需要的库存量。
- 在产品开发中,置信区间对于确定产品的可靠规格非常重要。
现在,做出估计是一回事,但给出估计是另一回事和提供置信水平。
考虑以下情况…
- 陈述 A:我估计我们明年的销售额会达到 50 万美元。
- 陈述 B:我估计并且我有 95%的信心我们明年的销售额会在 450,000 美元到 550,000 美元之间。
两者有什么区别?
语句 B 为我们提供了更多的信息,因为它不仅为我们提供了一个统计数据,还告诉我们对这个统计数据有多大的“信心”。如果信心和信心水平的想法对你没有意义,不要担心,继续读下去。
目标
在本文中,我们将介绍什么是置信区间,为什么它们很重要,以及如何计算它们。
但是在深入置信区间之前,我们首先需要讲一个极其重要的概念,中心极限定理。
中心极限定理
中心极限定理非常强大——它指出样本均值的分布近似于正态分布。
作者创建的图像
举个例子,假设你从一个数据集中抽取一个样本,然后计算这个样本的平均值。一旦重复多次,你就可以把所有的样本均值和它们的频率绘制到一个图表上。不管初始分布是什么样的,最终总会是正态分布。
这真的很重要,因为这意味着我们可以利用假设正态分布的统计技术,比如置信区间。
那么什么是置信区间呢?
作者创建的图像
置信区间只是一个很可能包含感兴趣的参数(或统计数据)的数值范围。
例如,使用上面的图片,我们可以说样本均值是 100,或者我们可以说我们有 95%的把握样本均值在 90 和 110 之间。
另一方面,点估计是一个样本统计量,它提供了一个总体参数的单值估计(即平均值)。
误差幅度是点估计和置信区间终点之间的距离。
如前所述,使用置信区间而不是点估计(即平均值)的好处是因为它为我们提供了更多的信息。
一般来说,置信区间越宽,你越有信心真实参数在区间内。
均值的置信区间
由于中心极限定理,我们知道采样平均值的采样分布是正态分布,因此我们知道以下内容:
- 平均值等于μ
- 样本平均值等于 x̅
- 标准偏差等于σ/√n
作者创建的图像
因此,如果我们想要找到 95%的置信区间,知道经验法则,我们的误差幅度将是标准偏差的两倍——这是因为大约 95%的数据位于 2 个标准偏差内。
均值的置信区间
然后我们可以退一步,把它概括为一个方程。Z 分数简单地由我们希望我们置信区间有多“自信”来确定。
现在你可能在想,“在这之前,我们怎么知道σ呢?”这是个好问题。一般来说,如果你不知道μ,你可能也不会知道σ。也就是说,数学上可以证明,你可以用样本标准差作为替代。
因此,等式看起来像这样:
因为我们依赖中心极限定理来成立,所以有几个条件也需要成立。第一,样本必须是随机的,第二,样本大小(n)必须大于或等于 30。
比例的置信区间
现在,如果你想找到人口比例——也就是说,人口中具有某种特征的人/事物与人口总规模的比率。
在这种情况下,等式有一点改变:
- 您现在要寻找的不是平均值(μ),而是人口比例(p)
- 样本比例被表示为 p̂
- 标准偏差现在是= sqrt[p̂(1—p̂]/n]
这导致以下等式:
比例的置信区间
感谢阅读!
如果你坚持到了最后,那太好了!你应该知道什么是置信区间,它为什么有用,以及如何计算它。在进行估计时,置信区间是非常有用的,我强烈建议你除了进行点估计之外,还要使用置信区间。
如果你喜欢这样的文章,一定要给我一个关注介质。一如既往,我祝你在努力中好运!
不确定接下来要读什么?我为你挑选了另一篇文章:
</10-statistical-concepts-you-should-know-for-data-science-interviews-373f417e7d11>
又一个!
特伦斯·申
- 如果你喜欢这个, 跟我上媒 了解更多
- 报名我的邮箱列表 这里 !
- 有兴趣合作吗?让我们连线上LinkedIn
量子优势的例证
原文:https://towardsdatascience.com/an-illustrative-case-of-quantum-advantage-6dd1a0168a73?source=collection_archive---------26-----------------------
实践中的 Deutsch-Jozsa 量子算法
量子机器学习要不要入门?看看 动手量子机器学习用 Python 。
关于量子计算的帖子通常以它将如何改变世界的轶事开始。据说它可以在几秒钟内完成经典计算机需要几千年才能完成的任务。
作者图片
然后,我们开始调查。首先,我们了解量子比特(量子比特)与经典比特有何不同。它们处于叠加状态。叠加是状态 0 和 1 的复合(如在复数中)线性组合。许多人喜欢量子位不是 0 或 1,而是同时是 0 和 1 的概念。尽管这个概念不正确——或者至少不精确——但它生动地说明了量子算法的优势。经典计算机按顺序处理任务,一次一个,而量子计算机一次完成所有步骤。
在之前的一篇文章中,我们研究了大卫·多伊奇的算法。这种量子算法通过只查看一次来分类函数是恒定的(总是返回相同的结果)还是平衡的(给定不同的输入返回不同的结果)。相比之下,经典算法需要查看函数两次。
量子算法同时评估一个输入的不同方面的能力是惊人的。但是我们使用的例子似乎过于简单和解释。它不提供任何实用价值。因此,我们现在来看一个更实际的例子。
让我们假设有人给你一枚硬币,要你赌正面或反面。有人带着赌博的意图直接接近你?这听起来很可疑,不是吗?
作者图片
在你同意玩之前,你首先要确定硬币没有被操纵。假设有两种选择。要么,硬币是公平的,一半的情况下落在两边。或者,硬币被骗了,总是落在同一边。判断硬币是否公平的唯一可靠方法是扔硬币,看它落在哪一边。
假设我们测试硬币四次。一枚公平的硬币会落在两边两次。那么,你需要多久抛一次硬币才能发现呢?如果你只扔一次,它要么正面朝上,要么反面朝上。这根本没告诉你什么。如果你再扔一次,它落在另一边,你就完了。那么,你知道这是一枚公平的硬币。但是如果硬币再次落在同一边呢?一枚公平的硬币可能有四分之二落在一边。要肯定地说一枚硬币被骗了,你至少需要抛三次(当我们假设在样本量为 4 的情况下是公平的)。
从数学上讲,当硬币在第 n 次投掷时是公平的,我们需要投掷硬币2^(n/2–1)+1次。对于 n=4,这些是2^(4/2–1)+1=3投掷。对于 n=8,这些是 2^(8/2–1)+1=7 投掷,对于 n=10,这些是 2^(10/2–1)+1=15 投掷,等等。这个数字呈指数增长。
在最坏的情况下,我们可能会重复得到相同的结果,而不知道硬币是否仍然公平。这将需要指数数量的查询——至少如果我们以传统方式进行。
有了量子计算,我们可以一次性解决这个问题。相反,我们对每一种可能的投掷组合使用一个量子位。为了简单起见,假设我们只扔硬币三次。假设 1 代表正面,0 代表反面。因此,有八种可能的输入:(0,0,0)、(0,0,1)、(0,1,0)、(0,1,1)、(1,0,0)、(1,0,1)、(1,1,0)、(1,1,0)、(1,1,1)。
在我们的量子电路中,我们考虑的每一次投掷使用一个量子位,外加一个辅助量子位。因此,我们使用四个量子位。
我们从导入所需的库和指定量子电路开始。该电路包含一个表示投掷的量子寄存器、一个包含辅助量子位的量子寄存器和一个接收测量值的经典寄存器。
算法的主要部分是量子预言。如果这是你第一次听说量子计算领域的先知,不要担心。不是魔术,也不涉及神力。量子预言只不过是转换门的占位符。甲骨文就像你在经典编程中可能知道的开关盒控制结构。你有一个变量,先知。并为它可能具有的每个可能值指定行为。
作者图片
在我们的例子中,神谕代表了硬币的行为。一枚被骗的硬币要么只产生 0,要么只产生 1。
Qiskit 在|0⟩.初始化一个量子位在这种状态下,我们总是将一个量子位测量为 0。所以,当我们什么都不做的时候,我们已经有了代表一枚被骗硬币的神谕,这枚硬币总是反面朝上。
无论如何,我们把“无所事事”包装成一个函数。这个函数为我们创建了一个定制的转换门。为了清楚我们做了什么,我们在所有代表投掷的量子位元上应用 I-gate。I 门是身份门,保持量子位不变。
下图以图形方式描绘了tails_oracle
。
作者图片
当我们运行一个仅由这个 oracle 组成的电路时,它输出状态000
——代表三次尾朝上。
作者图片
“非门”将一个量子位从|0⟩态翻转到|1⟩.态因此,我们可以通过对所有量子位应用非门来创建一个代表被骗硬币的预言。
下图描述了这个 oracle。
作者图片
这个神谕总是产生州名111
——代表三次平视的州名。
代表公平硬币的神谕有点棘手。不过,它也不太复杂。对于三个量子位,我们可以说它至少正面朝上一次,反面朝上一次。函数balanced_oracle
采用额外的config
参数。这应该是一个表示抛硬币结果的位串。我们将非门应用于代表正面掷硬币的量子位。
此外,我们添加受控非门,每次投掷作为控制量子位,辅助量子位作为目标量子位。
下图描绘了配置110
的平衡 oracle 代表头对头尾。
作者图片
这个预言导致我们在config
位串中指定的状态。在我们的例子中,它是110
。它也适用于所有其他输入。请注意,量子位从右向左读取。
作者图片
显然,三个 CNOT 门并没有影响。这似乎是合理的,因为只有当控制量子位处于|1⟩.态时,CNOT-gate 才像非门一样作用于目标量子位我们所有量子位都在|0⟩.状态参见这篇文章以获得 CNOT 门更详细的视图。
问题出现了:“如果 CNOT 门不重要,我们为什么要把它放在首位?
答案就是我们的量子算法。到目前为止,我们只为不同的情况创建了神谕。我们看到神谕正确地代表了硬币的行为。
所以,让我们实现我们的算法,识别硬币是常数(欺骗)还是平衡(公平)。
我们从一系列的哈达玛门开始,将量子位带入|+⟩态,将辅助量子位带入|-⟩.态在这些状态下,一个量子位元被测量为 0 或 1 的机率各为 50%。|+⟩州和|-⟩州的区别在于量子位相位(参见这篇文章了解更多关于量子位相位的信息)。
然后,我们应用神谕。最后,我们在量子位元上加上另一个哈达玛门,让它们从叠加态回到基态。
下图显示了电路,包括一个神谕。
作者图片
所以。让我们看看这个电路的工作情况。我们从持续反面硬币的神谕开始。
作者图片
它结束于状态000
。
接下来,我们用heads_oracle
运行算法。
作者图片
它也在000
州结束。
最后,我们用平衡甲骨文运行电路(你可以用任何位串运行它)。
作者图片
对于平衡输入的预言,电路结束于状态111
。您提供哪个位串作为输入并不重要。
“但这是怎么做到的?”
当预言不变时,我们要么应用 I 门,要么应用非门。但是由于我们的算法将量子位放入|+⟩状态,我们没有改变任何东西。当我们在|+⟩态的量子位元上应用非门时,它会停留在那个状态。当我们在电路末端使用哈达玛门时,它们会将量子位从|+⟩态转换回|0⟩.态我们有简单的 HIH 序列。
但是当我们应用balanced_oracle
时,我们额外应用了 CNOT-盖茨。虽然如果量子位处于基态(如|0⟩),这些都无关紧要,但如果量子位处于叠加态,它们就有关系了。然后,CNOT 门将目标量子位的相位应用于控制量子位。我们使用辅助量子位作为我们电路中的目标量子位,我们把它放入|-⟩.状态因此,当我们应用 CNOT 门时,我们将这个相位“复制”到其他量子位上。
结果,这些量子位也被转换到|-⟩态。最后的哈达玛门将|-⟩的量子位变成了|1⟩.我们称这种效应为相位反冲。
结论
开发了这个算法。它是 Deutsch 算法的推广,只使用两个量子位。
这个算法是量子算法比经典算法指数级更快的第一个例子之一。
此外,一个算法使用了相当多的量子特定技术,如叠加、预言和相位反冲。而且,当你一步一步地学习这些技术时,你会对量子算法在实践中的工作有很好的感觉。
量子机器学习要不要入门?看看 动手量子机器学习用 Python 。
在这里免费获得前三章。
使用 TensorFlow 的深入 EfficientNet 教程—如何在自定义数据集上使用 EfficientNet。
原文:https://towardsdatascience.com/an-in-depth-efficientnet-tutorial-using-tensorflow-how-to-use-efficientnet-on-a-custom-dataset-1cab0997f65c?source=collection_archive---------5-----------------------
使用 Tensorflow 在具有挑战性的 Kaggle 数据集上训练效率网
桑德·韦特林在 Unsplash 拍摄的照片
卷积神经网络(ConvNets)通常在固定的资源预算下开发,然后如果有更多的资源可用,则按比例增加以获得更好的准确性。在本文中,我们系统地研究了模型缩放,发现仔细平衡网络深度、宽度和分辨率可以获得更好的性能。基于这一观察,我们提出了一种新的缩放方法,该方法使用简单而高效的复合系数来统一缩放深度/宽度/分辨率的所有维度。我们证明了这种方法在扩展 MobileNets 和 ResNet 上的有效性。
来源: arxiv
EfficientNet 是目前最先进的图像分类网络中相当强大的一个。我可以看到它在 Kaggle 的图像分类比赛中被大量使用,AUC 为 0.90 以上,我想我应该把我们的教程放在这里,因为网上没有那么多。
我将不会讨论 EfficientNet 的理论部分,因为有大量的在线资源,相反,我将讨论编码部分。你可以使用 efficientNet-pytorch ,然而,我通常发现 TensorFlow 更快更容易使用。
我们将在此使用的数据集是来自 Kaggle 竞赛 VinBigData 的胸部 x 光数据集。我们将使用 512x512 图像的调整版本,因为原始图像非常大(2k+)。你可以在这里找到调整后的版本。无论如何,本教程的主要目的是让你在自定义数据集上使用它。
除了图像之外,我们还有一个数据帧,用于指定每个图像的 class_id:
包装和进口
你想做的第一件事就是跑
!pip install tensorflow-gpu
这将允许您在 GPU 上训练您的模型(如果您有一个)。接下来要导入几个包:
from tensorflow.keras.applications import * #Efficient Net included here
from tensorflow.keras import models
from tensorflow.keras import layers
from keras.preprocessing.image import ImageDataGenerator
import os
import shutil
import pandas as pd
from sklearn import model_selection
from tqdm import tqdm
from tensorflow.keras import optimizers
import tensorflow as tf#Use this to check if the GPU is configured correctly
from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())
设置效率网络:
为了更进一步,我们使用神经架构搜索来设计一个新的基线网络,并将其放大以获得一系列模型,称为 EfficientNets,它比以前的 ConvNets 实现了更好的准确性和效率。特别是,我们的 EfficientNet-B7 在 ImageNet 上实现了最先进的 84.3%的顶级准确性,同时在推理上比现有的最佳 ConvNet 小 8.4 倍,快 6.1 倍。我们的 EfficientNets 也能很好地进行迁移,并在 CIFAR-100 (91.7%)、Flowers (98.8%)和其他 3 个迁移学习数据集上实现了最先进的准确性,并且参数数量级更少。源代码在 https://github . com/tensor flow/TPU/tree/master/models/official/efficient net
来源: arxiv
由卢卡·布拉沃在 Unsplash 上拍摄
好了,接下来我们需要做的是建立一个有效的网络,并安装预先训练好的砝码
# Options: EfficientNetB0, EfficientNetB1, EfficientNetB2, EfficientNetB3, ... up to 7
# Higher the number, the more complex the model is. and the larger resolutions it can handle, but the more GPU memory it will need# loading pretrained conv base model#input_shape is (height, width, number of channels) for images
conv_base = EfficientNetB6(weights="imagenet", include_top=False, input_shape=input_shape)
Weights="imagenet "允许我们进行迁移学习,但如果您愿意,可以将其设置为 None(您可能不应该这样做)。include_top=False 允许我们轻松地将最终图层更改为自定义数据集。
安装模型后,我们希望做一点配置,使它适合我们的自定义数据集:
model = models.Sequential()
model.add(conv_base)
model.add(layers.GlobalMaxPooling2D(name="gap")) #avoid overfitting
model.add(layers.Dropout(dropout_rate=0.2, name="dropout_out")) # Set NUMBER_OF_CLASSES to the number of your final predictions.
model.add(layers.Dense(NUMBER_OF_CLASSES, activation="softmax", name="fc_out"))
conv_base.trainable = False
准备数据集:
模型准备好了。现在我们需要准备数据集。我们将使用 flow_from_directory 和 Keras 的 ImageDataGenerator 。此方法需要培训和验证目录。在每个目录中,每个类都应该有一个单独的目录,该目录下有相应的图像。
首先,让我们为培训和验证下的每个类创建一个目录。
TRAIN_IMAGES_PATH = './vinbigdata/images/train' #12000
VAL_IMAGES_PATH = './vinbigdata/images/val' #3000
External_DIR = '../input/vinbigdata-512-image-dataset/vinbigdata/train' # 15000
os.makedirs(TRAIN_IMAGES_PATH, exist_ok = True)
os.makedirs(VAL_IMAGES_PATH, exist_ok = True)classes = [ 'Aortic enlargement',
'No Finding']# Create directories for each class.for class_id in [x for x in range(len(classes))]:
os.makedirs(os.path.join(TRAIN_IMAGES_PATH, str(class_id)), exist_ok = True)
os.makedirs(os.path.join(VAL_IMAGES_PATH, str(class_id)), exist_ok = True)
接下来要做的是将每个图像复制到其正确的目录中:
Input_dir = '/kaggle/input/vinbigdata-512-image-dataset/vinbigdata/train'def preproccess_data(df, images_path):
for column, row in tqdm(df.iterrows(), total=len(df)):
class_id = row['class_id']
shutil.copy(os.path.join(Input_dir, f"{row['image_id']}.png"), os.path.join(images_path, str(class_id)))df = pd.read_csv('../input/vinbigdata-512-image-dataset/vinbigdata/train.csv')
df.head()#Split the dataset into 80% training and 20% validation
df_train, df_valid = model_selection.train_test_split(df, test_size=0.2, random_state=42, shuffle=True)#run the function on each of them
preproccess_data(df_train, TRAIN_IMAGES_PATH)
preproccess_data(df_valid, VAL_IMAGES_PATH)
现在,您可以检查数据集目录,所有图像都应该复制到它们正确的子目录中。下一步是将数据集传递给生成器,然后开始训练:
# I love the ImageDataGenerator class, it allows us to specifiy whatever augmentations we want so easily...
train_datagen = ImageDataGenerator(
rescale=1.0 / 255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode="nearest",
)# Note that the validation data should not be augmented!#and a very important step is to normalise the images through rescaling
test_datagen = ImageDataGenerator(rescale=1.0 / 255)train_generator = train_datagen.flow_from_directory(
# This is the target directory
TRAIN_IMAGES_PATH,
# All images will be resized to target height and width.
target_size=(height, width),
batch_size=batch_size,
# Since we use categorical_crossentropy loss, we need categorical labels
class_mode="categorical",
)
validation_generator = test_datagen.flow_from_directory(
VAL_IMAGES_PATH,
target_size=(height, width),
batch_size=batch_size,
class_mode="categorical",
)
model.compile(
loss="categorical_crossentropy",
optimizer=optimizers.RMSprop(lr=2e-5),
metrics=["acc"],
)
如果一切按计划进行,您应该会得到与此类似的消息:
Found X images belonging to x classes.
Found Y images belonging to x classes.
训练模型:
history = model.fit_generator(
train_generator,
steps_per_epoch=NUMBER_OF_TRAINING_IMAGES // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=NUMBER_OF_VALIDATION_IMAGES // batch_size,
verbose=1,
use_multiprocessing=True,
workers=4,
)
预测
y_pred = model.predict(X_test)
score = model.evaluate(X_test, y_test,verbose=1)
评估:
# Import the modules from `sklearn.metrics`
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score# Confusion matrix confusion_matrix(y_test, y_pred)
precision_score(y_test, y_pred)
recall_score(y_test, y_pred)
f1_score(y_test,y_pred)
下一步是进一步评估模型,有很多资源可以做这件事,因为你可能会对探索大量不同的指标感兴趣,使用 Keras 应该很容易。
对本教程的一些可能的改进是通过创建几个折叠,然后组合最终的预测来使用交叉验证。此外,您可以使用更高级的数据增强技术,如混合、分割和抖动。
易访问数据可视化的不完整指南
原文:https://towardsdatascience.com/an-incomplete-guide-to-accessible-data-visualization-33f15bfcc400?source=collection_archive---------15-----------------------
做得更好的实用技巧。
作者的原创艺术
从最直接的意义上来说,可访问的可视化旨在让读者访问视觉呈现的信息。最常见的是,易访问性问题是指色盲或失明。然而,实际上,可访问性超越了特定的永久性残疾,涵盖了可用性优化的所有方面——适用于所有人。
记住残疾不是少数人的固定状态是很有用的。相反,残疾是一系列的经历,既有永久性的,也有暂时性的。例如,你可能会患上白内障,或者摔断手臂。偏头痛可能会让你蜷缩在黑暗的房间里,或者一个不眠之夜可能会模糊你的理解力。
坦率地说,让可视化变得普及是困难的。许多可视化工具不支持可访问设计,那些支持的工具学习起来会很混乱。即使有了可以想象到的最好的工具,可访问性也会使艺术超过科学,对一个人来说完美的设计对另一个人来说可能是不可用的。
因此,下面的指南肯定是不完整的。毫无疑问,我错过了或过于简化了重要的事情。可能是我笨拙地冒犯了你。但是,如果完美是遥不可及的,我希望这个指南至少提供了一些可以实现的想法,如何变得更好。
文本、标题和题注
如果不强调可视化文本元素的重要性,我们就不能谈论访问信息。没有文字,只有形状。所以请注意,并确保你使用的文本是有目的的。
标题应该告诉你可以用图形回答什么问题,但不一定要写成问题。例如,“2020 年供应商销售的单位数量”回答了问题去年每个供应商销售了多少单位?
图例应清楚地标识视觉映射和图形元素,并在连续数据中直接标出有意义的界标。尽量使用事物的实际单词,而不是变量名。
轴标签应该是简单明了的、水平的(如果可能的话)和描述性的。例如,“时间(2004–2009)”比“x”更有用。
标题应该给出任何可能影响图表解释的内容。帮助读者理解他们所看到的。例如,“这些数据是通过网络调查收集的,该调查使用客户的存档地址进行管理。将该图解读为,“在应用上花费较少时间的用户倾向于在扩展和附件上花费较少的钱,其中一个显著的异常值在不到 5 秒钟内花费了 24k 美元*。”*
色盲友好
有 3 种主要类型的色觉缺陷。红绿色觉缺失包括偏色或偏色,使绿色显得更红;和 protanomaly 或 protanopia,使红色显得更绿。
蓝黄色觉缺陷包括三色异常使蓝色呈现绿色,黄色呈现红色;以及使蓝色呈现绿色、紫色呈现红色、黄色呈现粉红色的 tritanopia 。
最后,完全色觉缺失包括色盲、色盲或**单色。**这种情况非常罕见,通常伴有其他视觉障碍。
Coolors 调色板工具的快照
不管出于什么原因,如果你只是用颜色来区分可视化中的元素,有很多模拟器可以帮助你选择可区分的颜色。我个人使用上图所示的酷派工具来检查我的调色板。
有时会有一种误解,认为你不应该在可视化中使用红色或绿色;这样做会立即使它们失去可用性。这并不完全正确,忽视两种最具文化相关性、高联想色彩是不必要的严重。
取而代之的是,试着让红色略带橙色,绿色略带蓝色。对于色觉正常的人来说,这个小小的变化不会有太大的影响。然而,对于那些难以区分红色和绿色的人来说,这些小调整可以极大地提高区分度。
作者图解
您还可以检查调色板中的颜色是否可以区分为黑色和白色。如果您需要打印没有颜色的可视化效果,这将会很方便,并且可以帮助总体色觉较低的用户。
亮度对比度
亮度对比度是两种颜色的亮度(或明度)之比。这个比例影响着物体被区分的程度。亮度对比通常是针对文本和背景来讨论的,但是同样的原理也适用于图形元素。您可以使用 WebAim 对比度检查器来验证您使用的是足够高对比度的颜色。
作者图解
杂项设计提示和技巧
即使对于那些能看到的用户来说,也有一些设计技巧可以让图形看起来更舒服。一个简单的技巧是在堆叠的条和点周围添加一个细的白色边框。这使得区分形状变得更加容易,并且减少了交叉点处无意的视觉效果。
作者图解
您还可以对齐图例,使其与最接近的可视元素的结构和顺序相匹配。这确保了读者确切地知道哪个元素具有什么值,并最大限度地减少来回扫视的时间。
作者图解
使用直接标注是避免使用图例的好方法。使用图例本身没有错,但是直接的标签可能会让你的读者更容易将一个视觉元素与一个值联系起来。在某些视觉元素远离图例的情况下,您可以选择同时使用图例和直接标签。
作者图解
最后,你可以改变纹理线和点的形状。这使得颜色不再是唯一的信息载体。在可视化中,我们称之为冗余编码或双重编码,这意味着数据用多个可视属性表示。我建议用颜色更浅的虚线连接起来,这样线条就能保持连接。同样,确保选择明显不同的形状。
作者图解
数据导出
使数据可访问的最直接的工具之一是简单的数据导出。即使 visual 与屏幕阅读器不兼容,导出也可以允许屏幕阅读器用户浏览数据。
然而,在进行数据导出时,重要的是要记住您是从可视化中提供值*。*这意味着提供预处理值,人们可以从视觉上合理地推断出这些值,而不是原始的、未清理的、未聚集的数据集。
键盘导航和屏幕阅读器
有人可能会使用键盘导航有各种各样的原因。例如,盲人用户或那些运动受限的用户可能更喜欢使用键盘而不是鼠标来导航。其他用户可能喜欢键盘导航的效率。无论哪种方式,这都是可能的,因为网页的 HTML 结构表明了所选内容的类型及其在页面上的位置。
当你为网页制作可视化效果时,确保使用标准的 HTML 结构,并带有键盘友好的标志。你可以在 WebAIM 网站,这里是上阅读更多关于如何做到这一点的信息。
屏幕阅读器获取嵌入网页 HTML 中的信息,并大声朗读出来。关于可视化,这是我们上面提到的文本元素中最常见的。不幸的是,并不是所有的可视化工具和平台都能很好地与屏幕阅读器一起工作;例如,这个页面不支持交互式媒体。在这种情况下,您需要使用 alt-text 来描述静态可视化。
<button aria-label= “publish article”>Publish</button>
<img src="graph.png" alt="Bar chart of ice cream preferences by nationality. 70% of Americans preferred sourdough ice cream.">
数据发音
进入可访问可视化的新领域,在*数据语音化领域有一些有趣的工作正在进行。*图表库 HighCharts 是这一领域的先驱。顾名思义,发音将数据映射到声音,而不是视觉元素。聆听可视化可以告诉用户趋势和异常值。也许作为一个独立的工具并不精确,但是 sonification 是对屏幕阅读器体验的一个很好的补充。也很好玩!
一个艺术的数据发音的例子,来自我们在 NASA 的朋友。这项工作是关于蟹状星云的。
数据物理化
最后,数据物理化是用物理介质表示数据的实践。这意味着除了颜色等视觉属性之外,纹理、温度、重量和大小都可以作为触觉编码。这是一个仍在研究中的领域,但却像成堆的岩石一样古老。这里有一个致力于数据物理化的维基你可以在这里找到。
没有别的办法:让数据可视化变得可访问需要额外的工作。有工具约束、知识约束和个人偏好。但是,这并不意味着我们不能在制作更容易访问的可视化方面做得更好。为了填补上面我可能遗漏的空白,我加入了社区中其他人的一些文章。欢迎在评论中分享其他资源!
https://medium.com/nightingale/data-visualization-accessibility-where-are-we-now-and-whats-next-b2c9eeac4e8b https://medium.com/nightingale/accessibility-is-at-the-heart-of-data-visualization-64a38d6c505b
Google Colab:如何从 Github、Kaggle 和本地机器上传大型图像数据集
原文:https://towardsdatascience.com/an-informative-colab-guide-to-load-image-datasets-from-github-kaggle-and-local-machine-75cae89ffa1e?source=collection_archive---------2-----------------------
在 Google Colab Jupyter 笔记本上访问大型数据集,用于训练深度学习模型
约书亚·索蒂诺在 Unsplash 上拍摄的照片
∘ 了解 Colab 的文件系统
∘ 1。从 Github
∘ 2 这样的网站上传数据。从你的本地机器上传数据到 Google Drive,然后到 Colab
∘ 3。从卡格尔∘
上传数据集结论
Google Colab 是来自 Google 的免费 Jupyter 笔记本环境,其运行时托管在云上的虚拟机上。
有了 Colab,你不必担心你的计算机的内存或软件包安装。你可以获得免费的 GPU 和 TPU 运行时,笔记本电脑预装了机器和深度学习模块,如 Scikit-learn 和 Tensorflow。也就是说,所有项目都需要数据集,如果你不是使用 Tensorflow 内置数据集或 Colab 样本数据集的T21,你将需要遵循一些简单的步骤来访问这些数据。
了解 Colab 的文件系统
您创建的 Colab 笔记本保存在您的 Google drive 文件夹中。然而,在运行时(当笔记本电脑处于活动状态时),它会根据您的喜好,从云中分配一个基于 Linux 的文件系统或 CPU、GPU 或 TPU 处理器。点击笔记本左侧的文件夹(矩形)图标,可以查看笔记本的 当前工作目录 。
按作者分类的 Colab 当前工作目录
Colab 提供了一个包含数据集的sample-data
文件夹,您可以随意使用,或者使用上传图标(在“搜索”图标旁边)上传您的数据集。请注意,一旦运行时断开连接,您将失去对虚拟文件系统的访问,并且所有上传的数据都将被删除。但是,笔记本文件保存在 Google drive 上。
在sample_data
文件夹上面有两个点的文件夹图标显示了 Colab 的文件系统中的其他核心目录,比如/root, /home, and /tmp
。
作者在 Colab 上的文件系统
您可以在“文件”面板的左下角查看您分配的磁盘空间。
作者的 Colab 的磁盘存储
在本教程中,我们将探索从三种介质上传图像数据集到 Colab 文件系统的方法,以便笔记本可以访问它们进行建模。我选择将上传的文件保存在/tmp
中,但是你也可以保存在当前工作目录中。Kaggle 的狗与猫数据集将用于演示。
1.从 Github 等网站上传数据
要将数据从网站直接下载到 Google Colab,你需要一个直接指向 zip 文件夹的 URL(网页地址链接)。
- 从 Github 下载
Github 是一个平台,开发者可以在这里托管他们的代码,并在项目上合作。项目存储在存储库中,默认情况下,存储库是公共的,这意味着任何人都可以查看或下载内容到他们的本地机器上并开始使用它。
第一步是搜索包含数据集的存储库。这里的是由 laxmimerit 制作的 Github repo,其中包含了猫与狗各自文件夹中的 25,000 张训练和测试图像。
要使用此流程,您必须拥有一个免费的 Github 帐户并已登录。
导航到包含数据集的 Github repo 。在回购的 主页 上,找到绿色的“代码”按钮。
作者图片
点击“代码”按钮右侧的箭头。这将显示一个下拉列表。
右键单击“下载 Zip”
右键单击“下载 zip”上的,并单击“复制链接位置”。注意:这将下载回购中的所有文件,但我们将在 Google Colab 上提取内容时筛选出不需要的文件。
导航到 Google Colab,打开一个新的笔记本,输入并运行下面两行代码,导入我们需要的内置 python 库。
下面的代码是我们粘贴链接的地方(第二行)。整个代码块下载文件,解压文件,并将内容提取到/tmp
文件夹中。
wgetUnix 命令 : wget <link>
下载网页内容并保存到 当前工作目录 (注意!
因为这是一个由系统命令行执行的 shell 命令。另外,链接必须以.zip
结尾。在上面的代码中,我们提供了(可选)一个下载目录(/tmp
),以及下载的 zip 文件的期望名称(cats-and-dogs.zip
)。我们使用— -no-check-certificate
来忽略 SSL 证书过期的网站上可能出现的 SSL 证书错误。
现在我们的 zip 内容已经提取到了/tmp
文件夹中,我们需要数据集相对于我们正在处理的 Jupyter 笔记本的路径。如下图所示,单击文件夹图标(箭头 1),然后单击文件系统(2)以显示虚拟系统的所有文件夹。
作者图片
向下滚动并找到所有图像文件夹所在的/tmp
文件夹。
作者图片
您可以使用os.listdir(path)
返回文件夹内容的一个 python 列表,您可以将它保存在一个变量中用于建模。下面的代码显示了 train 和 test 文件夹中猫和狗的图像数量。
- 从其他网站上传数据
其他网站,比如广受欢迎的 UCI 知识库,对于加载用于机器学习的数据集也很方便。一个简单的谷歌搜索把我带到了微软的这个网页,在那里你可以找到狗和猫数据集的下载链接。
当您点击“下载”按钮时,“取消”询问是“打开”还是“保存”文件的弹出消息。
网页现在显示一个链接,“点击这里手动下载”。右键点击,然后点击“复制链接位置”。
作者图片
打开一个新的 Google Colab 笔记本,按照上面 Github 链接描述的相同步骤操作。
2.从你的本地机器上传数据到 Google Drive,然后到 Colab
如果数据集保存在您的本地机器上,Google Colab(运行在云上的一个单独的虚拟机上)将无法直接访问它。因此,我们需要首先将它上传到 Google Drive,然后在构建模型时将其加载到 Colab 的运行时。
****注意:如果数据集很小(比如一个.csv
文件),你可以在运行时直接从本地机器上传到 Colab 的文件系统。然而,我们的图像数据集很大(543 Mb),我花了 14 分钟将 zip 文件上传到 Google Drive。在驱动器上,我现在可以打开一个 Colab 笔记本并将其加载到运行时,这将花费大约一分钟的时间(在下面的代码中演示)。但是,如果您要将它直接上传到 Colab 的文件系统,假设上传需要 14 分钟,一旦运行时断开连接,您必须再次上传相同的时间。
在将数据集上传到 Google Drive 之前,建议它是一个单独的 zip 文件(或类似的归档文件),因为驱动器必须为每个文件分配单独的 id 和属性,这可能需要很长时间。
一旦数据集保存在你的本地机器上(我从这里的下载到 Kaggle 上的,打开你的 Google Drive ,点击左上角的“新建”按钮。从下拉列表中,点击“文件上传”,然后浏览到您系统上的 zip 文件,然后“打开”它。
由作者将文件上传到驱动器
右下角将出现一个进度条,指示上传过程完成。
作者的 Google Drive“上传完成”
现在打开一个新的 Colab 笔记本。第一个代码块挂载Google Drive,这样 Colab 的文件系统就可以访问它。
Colab 将提供一个链接,授权其访问您的 Google 帐户的驱动器。
作者将 Google Drive 安装到 Colab
点击此链接(上面的箭头 1),选择您的电子邮件地址,然后在底部点击“允许”。接下来,从弹出窗口中复制代码并粘贴到 Colab 的文本框中(箭头 2),最后将显示这条消息:Mounted at /content/drive
。
现在,当我们查看屏幕左侧的文件时,我们会看到已安装的驱动器。
按作者安装 Google Drive 文件夹
接下来是将数据集读入 Colab 的文件系统。我们将解压文件夹,并使用下面的代码将其内容提取到/tmp
文件夹中。
现在你可以从文件系统中查看到 Colab 的/tmp/train
文件夹的路径。
作者的 Colab 文件系统
使用os.listdir(path)
方法返回数据文件夹中的内容列表。下面的代码返回了train
文件夹的大小(图片的数量)。
3.从 Kaggle 上传数据集
Kaggle 是一个数据科学家和机器学习从业者互动、学习、竞争和分享代码的网站。它提供了一个公共数据平台,拥有数以千计的公共数据集,这些数据集要么来自过去或正在进行的 Kaggle 比赛,要么由希望分享其数据集的社区成员上传。
2013 年,Kaggle 上的一场机器学习比赛中使用了猫 vs 狗数据集。我们将把这个数据集直接从 Kaggle 下载到 Colab 的文件系统中。以下步骤非常重要,因为从 Kaggle 下载数据集需要身份验证和权限。
第一步:从 Kaggle 下载配置文件
Kaggle 提供了一种与其 API 交互的方式。您需要一个免费的 Kaggle 帐户并登录。
点击你主页右上角的头像。从下拉菜单中选择“帐户”。
作者图片
在“帐户”页面上,向下滚动到“API”部分,然后单击“创建新的 API 令牌”。
作者图片
系统会提示您下载一个文件 kaggle.json。选择将它保存到您的本地机器上。这是包含您的凭据的配置文件,您将使用它直接从 Colab 访问 Kaggle 数据集。
注意:**您在此文件上的凭证将在几天后过期,当您试图下载数据集时,将在 Colab 笔记本中得到一个401: Unauthorised
错误。删除旧的 kaggle.json 文件,回到这一步。
第二步:上传配置文件到 Colab 笔记本
现在有了一个新的 kaggle.json 文件,你可以把它留在你的本地机器上(下面的步骤二 a ,或者保存(上传)到 Google Drive 上(后面的步骤二 b )。
步骤二(a) :如果文件还在你的本地机器上,你可以使用上传图标,或者使用 Colab 的files.upload()
将它上传到 Colab 的当前工作目录。如果您的项目使用同一台计算机,此选项会更简单。如果使用代码(不是上传图标),在新笔记本中运行下面的代码,浏览到下载的 kaggle.json 文件,然后‘打开’它。
该文件将出现在您的工作目录中。
作者上传的文件
第二步(b) :第二个选项是将 kaggle.json 文件保存(上传)到 Google Drive。打开一个新的 Colab 笔记本,按照简单的步骤将硬盘安装到 Colab 的虚拟系统中(如下所示)。有了这个选项,你可以从另一台机器上运行笔记本,因为 Google Drive 和 Colab 都托管在云上。
在 Google Drive 上,创建一个新文件夹,命名为 Kaggle。双击打开该文件夹,并上传ka ggle . JSON 文件。
由作者将 kaggle.json 文件上传到驱动器
接下来,打开一个 Colab 笔记本,运行下面的代码,将驱动器挂载到 Colab 的文件系统中。
一旦成功,运行下面的代码将 kaggle.json 从驱动器复制到我们当前的工作目录,这个目录是/content
( !pwd
返回当前目录)。
刷新文件部分,在当前目录中找到 kaggle.json。
第三步:将操作系统环境指向配置文件的位置
现在,我们将使用os.environ
方法来显示包含认证细节的 kaggle.json 文件的位置。记得导入为此所需的文件。
第四步:从 Kaggle 中复制数据集的 API 命令
**Kaggle 上的每个数据集都有一个相应的 API 命令,您可以在命令行上运行该命令来下载它。**注意:如果数据集是为一个竞赛准备的,请转到该竞赛的页面并‘阅读并接受规则’,这样您就可以提交数据了;否则你会在 Colab 上得到一个403-forbidden
错误。
对于我们的狗对猫数据集,打开比赛页面并点击“数据”选项卡。向下滚动并找到 API 命令(下面以黑色突出显示)。
由作者复制竞赛 API 命令
对于其他数据集(非竞赛),单击“新建笔记本”按钮旁边的 3 个点,然后单击“复制 API 命令”。
按作者复制其他数据集 API
步骤 5:在 Colab 上运行这个 API 命令来下载数据
回到我们的 Colab 笔记本,将这个 API 命令粘贴到一个新的块中。记得包括!
符号,它告诉 python 这是一个命令行脚本。
如果一切正常,将会显示下载确认。我得到了下面的结果。
按作者下载确认
现在,从左侧的文件窗格中,您可以看到所有已下载的文件夹。
按作者下载的文件
第六步:提取文件
现在我们可以提取 train.zip 文件中的文件并保存到/tmp
(或者当前目录/content
)。
运行下面的代码以返回解压缩文件夹中的文件数量。
结论
在本教程中,我们探讨了如何将图像数据集从 Github 和 Kaggle 等网站以及您的本地机器上传到 Google Colab 的文件系统中。现在你已经将数据存储起来,你可以训练一个深度学习模型,比如 CNN,并尝试正确地对新图像进行分类。对于更大的图像数据集,这篇文章给出了替代方案。
我希望你喜欢这篇文章。每当我发表新的文章时,想要收到更多这样的文章,请在这里订阅。如果你还不是一个媒体成员,并且愿意支持我作为一个作家,跟随这个链接,我将赚取一小笔佣金。感谢您的阅读!
斯坦福人工智能在医疗保健系列课程(医疗保健专业人工智能)的初步评价
原文:https://towardsdatascience.com/an-initial-review-of-the-stamford-ai-in-healthcare-courses-ai-in-healthcare-specialization-99a42532a83f?source=collection_archive---------29-----------------------
为什么在医疗保健环境中实施人工智能和机器学习如此具有挑战性
作者图片
开始之前,请注意以下几点:
- 虽然我被培养成科学家,但我不是医学博士。这意味着我在 Coursera 上选修了这门非 AMA 学分的课程作为证书。
- 根据打字错误和录音信号的数量等。我希望是第一批尝试这个系列课程的人之一。
- 课程系列的链接可以在这里找到:https://www.coursera.org/specializations/ai-healthcare
格式:
课程系列的形式是一系列人们站在原地从屏幕上阅读的视频。有两个拍摄角度,但附加的视觉效果很少,所以跟随拍摄是一个真正的听力技巧练习。所提供的学习指南提供了所有相同的视觉效果和朗读文本,因此这些课程可能很容易在播客模式下进行(只需听,然后阅读学习指南)。
作业是自我检讨(帮助你思考你是否学到了什么)和测验(无限重试的多项选择)。有些问题假设你听了例题或做了一些关于题目的课外阅读。
序列:
该系列的第一门课程是 医疗保健介绍 。对于那些不把“中介”作为健康保险公司的标准术语的人来说,这是一门非常有用的课程,介绍了医疗保健市场词汇。所使用的示例有助于更好地理解为什么医疗保健数据如此分散且看起来毫无关联。
该系列的第二门课程是 **临床数据介绍。**虽然本课程涵盖了一些标准的机器学习数据问题,但它也强调了时间的重要性,并建议所有数据都包括一个时间范围,因为程序之前和之后的测试结果可能意味着非常不同的事情。建议是将所有特征排列在一个时间线中,以允许更好的推断。另一个见解是,鉴于医疗保险报销的变化和医疗程序的进步,数据窗口可能缺少分析、建模和预测。讨论的数据来源是电子健康记录(EHR),健康保险索赔数据和公共数据来源。
该系列的第三门课程是 面向医疗保健的人工智能和机器学习基础。 虽然本课程涵盖了从决策树到 CNN、RNNs 的标准机器学习方法,但它带来了结果-行动-配对的重要性。这个 OAP 概念提出了这样一个问题:“有人能够或愿意根据模型的结果采取行动吗?”在医疗保健行业,如果数据不可操作,它可能会很有趣,但可能不是特别有用。高度准确但其数据不能被采取行动的模型可能不如可能触发可采取行动的行为的较不准确的模型有用。
该系列的第四门课程是 **医疗保健中人工智能应用的评估。**本课程涵盖偏差的可能性、部署比例模型的挑战以及在给定人口统计范围的情况下,研究项目和可用于多个医疗机构的模型之间的适用性差异。这个单元还涵盖了医疗保健中人工智能的联邦指南和批准过程。涉众广泛参与部署,可操作的数据以问题“有时间采取行动吗?”。
注:以上所有单元均可自定进度,并在指定日期前开始和完成。
该系列的最后(第四)门课程是医疗保健顶点 中的 AI。本单元采用同伴评估的方式,在这种方式下,您可以根据提供的 3 分制评分标准对其他课程参与者进行评分。到目前为止,这些问题并不需要医学知识,但是随着我们的进展,我会学到更多。
疾控中心在 Unsplash 上拍照
到目前为止课程的收获:
整个课程假设科学词汇的合理水平。受过医学训练的人可能不需要去寻找铁蛋白和新冠肺炎之间的潜在关系。我做到了。
对统计学的基本理解是有帮助的,虽然所涵盖的机器学习主题对于完成任何机器学习课程基础的人来说都是熟悉的,但例子中提到的偏见和缺乏可解释性的应用和风险,尤其是医疗保健,可能会令人大开眼界。
由于不完整的人口统计或历史数据(主要是白人或男性)导致的偏见风险可能非常高,并且在主要不是白人和男性的医疗保健地区阻碍了有用模型的实施。
美国的医疗保健系统如此复杂,如果患者的私人数据被暴露,对患者的惩罚是如此之高,以至于人工智能的成功实施存在许多障碍。有一种感觉是,美国和欧盟对数据的保护比中国更强,可能会在医疗保健的人工智能“竞赛”中输给中国研究人员。人们只能希望美国能够找到一种方法,为患者提供隐私保障和积极的激励措施,以分享他们的医疗保健数据,这似乎是前进的方向。
概要:
虽然在枯燥的演示格式下,本课程要求比其他在线学习经验更高水平的注意力和听力技能,但它概述了数据、建模、偏见和实施方面的挑战,因此值得花时间学习本课程。
虽然这些课程被安排成一系列,但在很大程度上,它们可以根据兴趣相互独立地进行。
如果你对在医疗保健环境中成功实施人工智能或机器学习所面临的挑战感兴趣,这是一个有趣的概述。如果你不是听觉型学习者,你可能会发现你会更成功地下载和复习学习指南,观看更有趣主题的视频。
随着医患沟通已经转移到作为数据录入员的医生手中,通过自动化日常任务、利用计算机比人眼更好以及患者对数据的所有权,释放人工智能的力量以重新人性化医疗保健的潜力是巨大的。
照片由乔恩·泰森在 Unsplash 上拍摄
顶石项目可能比其他单元需要更多的医学专业知识,所以我可能不会完成该单元,所以这可能是唯一张贴的审查,而不是整个系列更全面的审查。如果没有,请查看将课程知识应用于新冠肺炎 x 射线和 EHR 数据分析和模型的最新回顾!
点击此处查看顶点评论
从第一原理导出逆变换采样方法
原文:https://towardsdatascience.com/an-insight-on-generating-samples-from-a-custom-probability-density-function-d0a06c290c54?source=collection_archive---------18-----------------------
从自定义概率密度函数生成样本的见解
快速提示:
在本文中,我提供了关于使用逆变换采样方法从定制概率密度函数生成样本的见解。
几乎每种编程语言都允许用户生成随机数。但是如何生成遵循一定概率分布的数字呢?这个问题是我决定阅读这个话题的主要原因。
当处理抽象概念,即数学和编程时,通常面临的挑战是在头脑中描绘这些概念。有鉴于此,在整篇文章中,我将不断地使用图表或动画来阐述我的想法。
最后,我将努力实现的是从零开始构建——一个支持从自定义概率密度函数进行采样的工具。
概率密度函数很容易构造,但取样却不容易
在概率统计中,确切地说是在描述连续随机变量时,我们经常会碰到概率密度函数的概念。这是一个描述随机变量的强大工具,因为它给出了随机变量的值出现的概率/频率。
举例来说(见下图,如果我们考虑一个由密度函数*【f】、*** 描述的随机变量 Y ,那么如果我们生成总共 100 个独立样本,理想情况下,其中 24 个样本落在 1-2 之间,40 个落在 2-3 之间,16 个落在 3-4 之间,依此类推。**
概率密度函数图解[作者图解]
碰巧有一个庞大的概率密度函数家族,范围从最常用的(均匀、正态、指数等)到最不可见的。事实上,如果你想构造你自己的密度函数,只要取一个可积函数,用它的积分归一化,就这样!
分布的例子:第一行是 3 种常见的分布,而第二行是 3 种不常见的分布[作者举例]
从数值上来说,从均匀分布中生成样本相当简单,因为它相当于生成随机数。很明显,几乎每种编程语言都有一个伪随机数发生器,比如 Python 的 random.random() 和 JavaScript 的 Math.random() 。
然而,为一个定制的分布函数做同样的事情并不简单,需要一些考虑。
这种被限制只能从均匀分布中取样却能轻松构建密度函数的挫败感是我下定决心的导火索。
我承认,在互联网上做了一些研究之后,我发现了一些已经存在的工具可以做到这一点(Python:scipy . stats . RV _ continuous)。然而,这还不足以满足我的好奇心。
我在本文中试图实现的是通过从头开始构建——使用均匀分布——一种支持从自定义密度函数进行采样的工具(,来揭示隐藏在引擎盖下的东西。
寻找统一分布和自定义分布之间的联系
假设我构造了一个自定义密度函数 f 。我现在的目标是利用均匀分布从中生成样本。我想到的基本想法是找到均匀密度函数和期望密度函数之间的映射。换句话说,我将从均匀分布中生成样本,并将这些数字与其对应的对等体进行映射。
根据自定义密度生成样本所遵循的模式【作者举例】
考虑到这一点,剩下的工作就是构建统一密度和定制密度之间的映射函数,换句话说就是揭示上面的齿轮实际上在做什么。
建立这种映射的提示可以从测量理论中得到。简而言之,测度论是长度、面积和体积概念的概括。除了在概率论的背景下——,这是一个特例——我们测量的是概率。密度可能起作用——更准确地说是“f dx”——可以被感知为度量,它们的积分与概率有直接联系。
将密度函数曲线下的面积解释为概率[作者举例]
在均匀密度和自定义密度两种情况下,我们测量的是概率,即曲线下的面积。因此,要找到映射,我们只需要找到均匀密度和自定义密度曲线下的区域之间的联系。
为了做到这一点,我们首先从制服上抽取一个号码。然后测量它所界定的面积。最后,我们找到在自定义分布曲线下划定相同区域的对应数字。
从定制密度中取样的详细流程图[作者插图]
将其放入一个等式中,我们需要为来自均匀分布的每个采样数 x 求解以下等式,以在自定义密度函数中找到其对应的对等体
其中 F 下标 X (分别为 F 下标 Y )表示密度函数的 x (分别为 y )所界定的曲线下的面积。在文献中, F 称为累积分布函数。它测量随机变量落在由指定界限界定的左侧区间内的概率,在我们的例子中,该区间就是由指定界限界定的曲线下的区域。
统一分布和自定义分布之间映射过程的实现
现在,我们有了所有的理论材料,可以将一个统一的生成样本映射到它在自定义密度中的对等样本。剩下的就是建立一个程序来求解上面的方程。
为了简单起见,我们将从 0-1 之间的均匀分布中取样。因此,每个采样数的曲线下面积将正好等于该数本身。
另一方面,对于给定的 y ,计算定制密度曲线下的面积是简单的,因为我们有密度函数的显式表达式。事实上,是我们输入了这个表达。我们通过计算积分来计算这个面积。为了实现这一点,我们可以使用 Python:scipy . intergrate . quad。因此,必须求解的方程的最终外观如下:
解决这个问题相当于求上述非线性方程的根。为此,我们可以再次使用求解器。比如 Python:scipy . optimize . f solve。
然而,我们如何保证这个方程有解呢?如果是这样的话,如果它太多了,我们如何挑选正确的呢?
累积分布函数测量概率。因此,它是一个介于 0-1 之间的量。由于均匀分布的样本数也是一个介于 0-1 之间的量,我们保证该方程至少有个解**。**
另一方面,累积分布函数是单调递增函数。因此,我们确信无论何时有解,它都必须是唯一的**。**
基于这种推理,我们可以毫无顾虑地使用解算器来解方程。非线性求解器背后的核心思想是建立一个收敛到期望解的序列。通常,这个序列是通过一个递归公式来定义的,换句话说,序列在给定阶段的值依赖于前一阶段计算的值。因此,选择求解器的起点是一个关键因素,因为选择不合适的起点可能会产生错误的解,在最坏的情况下会产生一个根本不收敛的序列。
为了避免这样的问题,我们需要找到一种方便地选择起点的方法。为此,我们可以再次利用累积分布函数的一个性质,即它的单调性。
我们可以——在构建密度函数的时候——创建一个元组数组(见下图)。因此,数组的元素按升序排序。基于此,假设我们从均匀分布中抽取一个数 x 。我们可以使用稍微修改过的二分搜索法版本来找到最接近它的两个元素。对应于这两个元素的' y 将定义我们的解最可能出现的区间。因此,我们可以选择这个区间的中点作为起点。**
选择合适起点的方法说明[作者说明]
现在,我们有了从制服中找到给定抽样数的映射的所有要素。
在示例上测试映射过程
将前面的思路编码后,我开始逐步测试映射过程(见下图)。**
我从一个特殊的例子开始,在这个例子中,我想要采样的自定义密度是一个均匀分布。基于此,映射过程应该理想地给出与从均匀分布生成的值完全相同的值。实际上,在这种情况下,我使用制服从制服中生成样本。
我选择的第二个测试是从通常的分布中产生样本,在我的例子中,我选择了正态分布。从视觉上看,我期望看到两条曲线的相同定界区域。例如,无论何时我们在正方形的右边得到一个数字(统一),映射的数字也必须在钟的右边(正常)。
最后一个测试是在一个不寻常的分布上测试这个过程。坦率地说,我真的很有创造力,想象出了我见过的最不寻常的密度函数:)
我已经收集了所有以前的动画测试,在左边我放了均匀分布的样本。另外,我用一个红点来表示取样的数字。在右边,我放上我试图从中取样的密度。类似地,我用红点表示映射的数字。
在制服上测试映射过程[作者插图]
正态分布映射的检验[作者举例]
在自定义发行版上测试映射过程[作者举例]
在确保映射过程给出准确的结果之后,是时候测试整个过程了,目标是从给定的密度函数生成样本。所以我考虑了一个定制的密度函数,我从一个制服中产生了一个大样本,然后我将这些样本与它们相应的对等体进行映射。最后,我用直方图表示结果。我的期望是,随着样本数量的增加,直方图的条应该接近密度函数的曲线。
另一次,我制作了一个动画,展示了随着样本数量的增加,直方图条长度的变化。
在自定义密度函数上测试整个过程[作者插图]
结论
在整篇文章中,我描述了如何利用均匀分布从自定义密度函数中生成样本。准确地说,我建立了一个工具来实现这一点。首先,我解释了它的实现过程。最后,我在几个发行版上测试了它,从常用的发行版到最不熟悉的发行版。
参考文献,本文描述的方法称为逆变换采样。还有其他方法可以达到同样的目的。查看这篇文章以便进一步阅读。
在写这篇文章时,我有意避免写任何代码,尽管我采用了数字视角。事实上,我希望这篇文章对于程序员和非程序员都是可以理解的。然而,如果你对事情实际上是如何实现的感到好奇,你可以查看我的 GitHub 库。在那里,我上传了关于代码的细节。
最后但同样重要的是,我可以说我已经成功地达到了我的目标。所以,为了庆祝这样的成就,满足我的自我,没有什么比想象各种密度函数并从中取样更好的了
使用内置工具生成的发行版示例[作者说明]
Rendezvous:“对伪数字生成器的洞察”
具有 Plotly 和 Streamlit 的交互式二氧化碳排放仪表板
原文:https://towardsdatascience.com/an-interactive-co2-emissions-dashboard-with-plotly-and-streamlit-b0bd4ae80cc8?source=collection_archive---------30-----------------------
实践教程,数据可视化
借助 Plotly charts 和 Streamlit 灵活的输入、布局和主题化选项,您可以从实时数据构建一个出色的交互式数据可视化应用程序
示例应用程序—作者图片
Streamlit 没有最全面的用户界面组件,但它们易于使用,只要有点想象力,就可以组合出良好的效果。
我们将看看如何在 Streamlit 中使用主题化和各种交互式输入和布局选项,以及 Plotly 图表,来制作一个有吸引力的、有希望提供信息的 web 应用程序。
要阅读本文,您需要对 Streamlit 和 Plotly 有所了解。文章中的大部分代码会以要点的形式显示,在文章的最后还有完整代码的要点以及下载链接。
上面的图片可能看起来不像一个典型的 Streamlit 应用程序,因为你看到的大多数应用程序都是用默认的 light 主题制作的。这一个利用了配置工具来选择默认的黑暗主题,但是其他定制的主题也是可能的。
你可以看到的图表是由 我们的世界在数据(CC BY license)中提供的定期更新数据 Plotly 创建的。这些图表跟踪全球二氧化碳(CO2)排放水平以及各个国家或地区(如欧盟或全世界)的人均排放量。
因为它们是 Plotly 应用程序,所以它们是交互式的,你可以用鼠标悬停在它们上面来查看更多细节。除此之外,Streamlit 滑块和多种选择输入设备让您能够更好地控制显示内容。
在下面的截图中,左边的图表显示了一张根据每个国家的二氧化碳排放水平而着色的地图。它有一个用于选择年份的滑块,当你移动滑块时,你会看到地图的颜色发生变化(随着排放量的增加,它们通常会随着时间的推移而变暗)。
右边的图表显示了单个国家或地区(如全球或欧盟)的人均排放量。设置了一些默认国家,但单击控件会显示一个下拉菜单,您可以在其中选择或取消选择任何有可用数据的国家。
作者图片
上面的截图是应用程序屏幕的上半部分,使用两列来显示图表。
下半部分,如下图所示,试图通过对比两个图表来显示二氧化碳排放量的增加和全球变暖之间的相关性。它使用了三列两列用于图表,一列用于文本描述。
然而,为了在图表之间建立适当的分隔,在应用程序的上部和下部,在包含图表的列之间插入窄的空白列。我们很快就会看到它是如何工作的。
作者图片
希望你现在能看到这个应用程序的样子,以及它的基本结构。那么,现在让我们来看看它是如何放在一起的。
获取数据
我们在 data 的 Github 存储库中检索来自我们世界的数据。所有 OWID 的数据都是在 CC 的许可下提供的,这意味着只要 OWID 有信用,它就可以按照你想要的方式使用。
我们使用两个文件,一个是关于二氧化碳和温室气体排放的 OWID 数据,另一个是关于气候变化影响的 OWID 数据。
更新:第二个数据集似乎已经从 OWID 存储库中删除,因此应用程序中依赖于此的部分将不再工作。
两者都是 csv 文件,我们把它们读入熊猫数据帧。
如你所见,有三个函数get_data
、get co2_data
和get_warming_data
。第一个函数从 url 返回一个 dataframe,而另外两个函数实际上设置了适当的 url 并从第一个函数返回 dataframe 结果。
还有两件事需要注意。
首先,当返回 warming 数据帧时,我们过滤数据帧,只返回那些包含小于 2021 年的年份并且“实体”(即国家或地区)是“世界”的行。这样做的原因是,首先我们只对 changedata 感兴趣,其次 year 列中的条目肯定不是真实的年份。老实说,我不知道他们代表什么,但他们的数字远远高于今年。所以我们忽略这些数据。
(仔细想想,>=2021
可能应该更高一些,比如说>=3000
,否则这款应用在今年之后就没什么用了!)
贮藏
第二件要注意的事情是 Python 装饰器@st.cache
用在了每个函数上。这个装饰器确保函数的结果被缓存,并且在应用程序的生命周期中不会不必要地调用函数。
这样做的原因是,每次进行更改时,Streamlit 应用程序都会完整地从上到下运行。因此,在我们的应用程序中,移动滑块或选择一个新的国家将导致应用程序重新运行。我们使用的数据不会经常更改,因此为了获得最佳性能,我们希望避免每次更改时都下载数据,而是使用之前缓存的数据。
如果我们要使用变化非常快的数据,比如股票行情,那么缓存数据是不合适的,因为我们会错过应用程序运行期间的更新。但其后果将是应用程序运行得更慢。
布局
应用程序的基本布局如下所示,其中未标记的列是空白的,用作其他列之间的填充。
作者图片
这是在 Streamlit 中实现的,如下面的代码大纲所示。
大纲代码—不用于复制!
我使用with col2
符号,因为我认为它使代码的布局更容易理解。
这里唯一需要注意的是标有space
的列。这些仅用作填充。所以,这一行代码
col2, space2, col3 = st.column((10,1,10))
创建三列。最外面的两个col2
和col3
宽度相同,将包含图表,而中间的一个space2
是另外两个的十分之一,并且是空白的。这在外柱之间提供了合适的间隙。
制作图表
这四张图表都是用 Plotly 制作的。第一个是在col2
中,但是这里我们从滑块组件开始,它允许你在 1750 年和 2020 年之间选择一年。选择的结果存储在变量year
中。
接下来,我们创建一个 Plotly choropleth(基本上是一个带有彩色区域的地图),其中颜色由 CO2 水平决定,数据帧由滑块设置的年份过滤。
第二张图是一个折线图,每个国家一张,显示了该国一段时间内的人均二氧化碳排放量。我们再次从输入控件开始,这次是多选框。默认国家名称列表与唯一的国家列表一起设置。除非选择了其他国家,否则 multiselect 控件将返回一组默认值。
然后,选定的国家用于设置图表上线条的颜色。
最终的图表很简单,不需要输入控件。第一个是全球海洋温度随时间变化的散点图。在此基础上,使用 lowess 平滑绘制趋势线。
第二张图表是全球排放量的折线图。
将平滑线放在第一个图表上的想法是为了让你看到它与排放线有多相似,从而试图显示两个测量值之间的相关性。
黑暗主题
在 Streamlit 中你可以做很多主题化的工作,但是要简单地启用黑暗模式你只需要在你的工作文件夹中创建一个名为.streamlit
的文件夹,并在其中放一个名为config.toml
的文件。在config.toml
文件中输入以下代码。
[theme]
base = "dark"
现在,下次你运行你的应用程序时,它将处于黑暗模式!
如果你想创建一个自定义的主题,其他的主题设置会放在同一个文件中,但是我们现在就把它放在这里。
就这些了
我希望从编码的角度来看这是有用的,但是我们也可以从这里展示的数据中学到一些东西。
如果你想试验代码,下面有完整代码的要点,或者你可以从我的 Github 库下载(向下滚动直到你看到文章的标题——链接会在那里)。
这里有一个这个应用的现场版。
一如既往地感谢阅读,如果你想知道我什么时候发表新文章,请考虑在这里注册一个电子邮件提醒。我也偶尔在子栈上发布免费的时事通讯。请在下面留下任何评论,或者您可以通过 LinkedIn 或 Twitter 联系。
完全码
https://alanjones2.github.io/
机场交通的交互式仪表板
原文:https://towardsdatascience.com/an-interactive-dashboard-for-airport-traffic-40fcc3680042?source=collection_archive---------50-----------------------
挪威机场有多忙?数据,Plotly,和破折号,可以帮助我们看到。
托马斯·威廉姆斯在 Unsplash 上的照片
现场演示 仪表盘活动-机场或查看项目**GitHub**。****
摘要
与其他欧洲国家相比,挪威在地理上是一个很大的国家,尤其是与它的居民相比。挪威的工业中心遍布全国。许多挪威公司经常开设新的较小的办公室,以获得合适的人,如果他们不愿意搬迁,或者如果该位置有足够的人来产生经济效益。此外,当一家公司收购另一家公司时,该公司的位置可能会在地理上被分割。这些因素导致了大量的国内航空旅行。本文中描述的公开可用的仪表板旨在提供视觉上愉悦和直观的用户体验,使用所需的工具查看给定机场的乘客数量,或者根据交通类型和日期比较不同的机场。
介绍
本文描述了在设计和实施探索性仪表板时所使用的数据收集和准备工作,该仪表板旨在清晰地描述给定位置或日期的挪威国内机场客流量。
功能
辅助函数定义并存储在 functions.py 中,并根据需要导入到用于准备数据的 jupyter 笔记本中。这样做的原因是为了让 Jupyter 笔记本更容易使用。已经注意到,如果笔记本有许多单元格或者很长,nbextensions 中的一些扩展往往会有滞后。我的偏好是从第一步到最后一步都在一个笔记本里。
数据集收集和准备
仪表板中用于勘探的数据来自挪威政府统计机构 SSB ,该机构拥有最新的详细数据和公开可用的 API。然而,为了简单起见,表格是从表单选择中创建的,并作为 CSV 文件下载[1]。选择包括的类别有乘客数量、月份、年份、机场名称和交通类型。然而,根据任务说明,只有国内航班和起飞及抵达时的乘客才包括在内。挪威字母表中有三个额外的字母?、和,它们都包含在机场名称中。但是,SSB 的 CSV 生成器不支持这些字符,它们被替换为“?”符号。因为没有上下文就无法创建脚本来更改这些,所以每个机场都需要手动重命名。
输入数据
CSV 文件由每个特征的列构成,“机场”、“交通类型”、“国内/国际航班”、“乘客组”,每个日期表示为“乘客 yyyyMmm”。为了进一步处理,CSV 文件被导入到 Pandas 数据框架中。
预处理
应用重命名列名或索引名的函数。该函数用于将“yyyy”从“mm”中拆分出来,删除“M ”,并将该列转换为“datetime”数据类型。
检查数据集是否有可能在以后导致问题的缺失值,但是没有发现任何缺失值。
Instances of missing data: 0
Columns with missing data: 0
Column names with missing data: None
宽数据
当前状态的数据集被称为“宽数据”,它不太适合制作图表。但是下面的一些操作在宽表单中更容易,所以现在还不会改变。
对于地理表示,需要位置数据。应用上面定义的基于机场名称查找每个机场的地理点的函数,方法是向数据帧添加带有位置数据的新列。
缺失数据
应用地理位置函数后,我们发现一些缺失值。显然,它无法识别挪威的所有机场。
Instances of missing data: 70
Columns with missing data: 5
Column names with missing data: location, point, latitude, longitude, and altitude
上面定义的missing_location()
函数用于定位缺失值的位置,以便决定下一步做什么。
经过一番调查,找到了没有给出位置的机场名称。
虽然只有两个机场,这使得手动步骤快速而简单,但这也是学习如何从地理数据中获取地址的绝佳机会。在 Jupyter 中工作时,内核有时必须重新启动,其中一些步骤非常耗时,因此结果被导出到一个 CSV 文件中。现在可以导入处理过的数据,而不是重新处理。
Instances of missing data: 0
Columns with missing data: 0
Column names with missing data: None
长数据
在制作仪表板之前,数据集被转换为“长数据”,其中日期列被融合到数据集中,因此每一行都有一个日期。不同流程生成的一些不必要的列被删除,时间和日期从日期中减去,因为它们由于无法从源中获得而完全相同。数据现在可以使用了,并且建立了快速更新数据的流程。
设计和实施
仪表盘
仪表板的用户交互设计非常强调直观性和自明性。仪表板的结构是每个图形都有自己的选项卡,因此不会给用户带来视觉负担。每个图形的控件都是自适应的,所以如果不适用于当前图形,它们会自动调整屏幕大小或隐藏起来。如果一个控件组是共享的,但是单个控件不合适,它们将被禁用并变灰,并在其标签中注明。交互的标签尽量简短明了,只陈述其功能。仪表板及其图形的视觉设计非常强调简约,以保持对数据描述内容的关注。在任何可能的情况下,蓝色、灰色和黑色的方案都被用于美学目的。第一印象对于说服用户仪表板制作精良至关重要。因此,项目标题和图标包含一个导航栏,浏览器窗格由一个 favicon 和项目标题组成。仪表板是由 Dash 框架中的自定义编码 HTML、CSS 和 Python 制作的。仪表板通过 Heroku 部署为 Flask 应用程序。尽管这不是最简单的解决方案,但它是启用所有仪表板功能所必需的。
如何部署应用程序不在本文讨论范围内,但是有许多关于如何部署的教程[2]。
要访问仪表盘,请点击此处:https://active-airport.herokuapp.com/
图表
有很多资料描述了在制作图表时应该考虑什么;PolicyViz [3]的一份整洁的备忘单总结了其中大部分的要点。所有图表的共同之处是,标题在左上角用大号粗体显示。这被大多数专业人士认为是最佳实践,因为它模仿了我们被教导阅读的方式,因此也是我们被教导对呈现给我们的信息的重要性进行优先排序的方式[4]。在适用的情况下,每个机场的值以文本或气泡尺寸的形式提供。因此,没有一个图表有任何网格线,因为它们不提供任何额外的信息,会分散注意力。此外,每个机场的任何相关信息都是通过将鼠标悬停在每个机场上来显示的。
地图图形
我不太喜欢 plotly 中的默认地图;我觉得它们很粗糙,视觉上也不美观。图 1 中显示的地图是使用 MapBox 提供的定制地图 Plotly 制作的,将土地灰和水白混合在一起,从而将焦点放在数据上。一个机场的旅客量由大小和颜色来表示,就像数量表示一样,它会自动调整所选择的机场数量和旅客总量。由于对数标度上的图形没有明显变化,因此该功能被禁用。请注意,当切换到“地理”标签时,地图并不总是完全加载。虽然这不是必须的,但是通过标签改变回调来更新图表大小已经过测试,但是没有影响到地图。然而,它适用于任何其他对象。发现“mapboxgl-canvas-container”CSS 类是问题所在,不可编辑。如果单击任何控制按钮,地图会调整大小。
图 1:地图(图片由作者提供)
条形图
图 2 所示的条形图是用 Plotly 制作的,并使用了数据集的副本,该数据集根据控件的选择与应用回调进行聚合。有很多机场可以选择,所以竖条是最好的选择。这些条根据乘客数量从高到低排序,并根据所选的机场数量自动调整,因此它们不会有令人尴尬的高度。由于各机场之间的乘客数量差异很大,可以选择对数标度来更好地表示。
图 2:条形图(图片由作者提供)
线图
图 3 所示的线形图对可接受的机场选择数量没有限制,但是因为在一个图中有许多线条被认为是不好的做法,所以没有制作“全选”按钮来促进这种行为。由于这个原因,线形图在颜色选择上有点突出,因为它是唯一一个需要选定机场图例的图,而且它们都需要是不同的。因为线形图的 x 轴是时间,所以可用的选项是“交通类型”、“机场”和“规模”。提供了范围滑块和“月”、“6 个月”、“今天”、“年”和“全部”的预设,以帮助用户探索数据并发现有趣的方面,如 2020 年 2 月新冠肺炎发生的时间。
图 3:折线图(图片由作者提供)
桌子
图 4 中所示的表格包含了所使用的数据,让用户可以看到这些图表是由什么组成的。一些数据没有包括在内,因为它只是为了功能的缘故。但是,该表是这样设置的,用户可以对数据进行筛选和排序,以找到感兴趣的特定行。
图 4:表格(图片由作者提供)
源代码
结论
机场数据从挪威统计局收集,并以适当的方式用于选定的任务。利用这些数据作为其来源,设计、实现和部署了一个仪表板。仪表板由 4 个选项卡组成,每个选项卡都有不同的数据交互方式。
参考
****[1]:挪威统计局。空运。按机场、交通类型和国内/国际航班划分的乘客。(2020),网址:【https://www.ssb.no/en/statbank/table/08507/ ****
【2】:魅力数据。"【https://www.youtube.com/watch?v=b-M2KQ6_bM4】用 Heroku 和 Dash Plotly(2020)部署你的第一个 App,网址:t
[3]: PolicyViz。数据可视化的核心原则。(2018),网址:https://policyviz.com/2018/08/07/dataviz-cheat sheet/
[4]:史蒂夫·韦克斯勒。"[不要将仪表板上的文本居中、右对齐或两端对齐。](https://www. datarevelations.com/resources/dont-center-right-align-or-justify-text-on-a-dashboard/)(2019),网址: https://www。data revenuations . com/resources/dont-center-right-align-or-justify-text-on-a-dashboard/
关于作者
Lewi Uberg 是挪威应用数据科学专业的一名四年级学生,拥有各行各业的极客、IT 经理和 CAD 工程师的背景。欢迎在 媒体上 关注他或者访问他的 网站 。
纽约医疗价格差异的互动研究
原文:https://towardsdatascience.com/an-interactive-look-at-healthcare-price-disparities-in-nyc-66f9212bcb0b?source=collection_archive---------40-----------------------
数据新闻
价格太高了。2
平均值。每个提供商/服务的调整后中间价格与每个提供商/服务的纽约市中间价格之间的差异
GitHub 资源库T3 此处 | Jupyter 笔记本T7 此处
“每个人都会死——但在美国,向出价最高者提供最好的延期机会一直被认为是合理的。”—査蒂·史密斯,暗示
有什么问题?
动机
2017 年,我定期在布鲁克林的绿点(Greenpoint)看物理治疗师,每次 80 美元。我的情况没有任何好转,在我第八次坐在椅子上,双臂被毫无意义的电击后,我决定是时候开始见其他人了。我的下一站是中城东区的一位职业治疗师,每次治疗收费约 300 美元。新的设施肯定比绿点的好,设备也更好。甚至有一台机器,我可以把胳膊伸进去,玉米皮碎片会飞来飞去打它们。现代医学!我每两周 300 美元的按摩手臂和剥玉米皮是由一个英俊的年轻人管理的,所以这次我坚持了整整一年。不幸的是,在此期间,我还做了一次无效的 19000 美元的手术(谢天谢地,由保险支付)。但最后时刻到来了。不是他,是我。我没有好转。
最终找到我的诊断的职业治疗师带来了一大笔费用——在上东区一家世界著名的医院,每次治疗大约 550 美元。当然,在我见过她之前,我不知道要花多少钱,因为医疗系统是疯狂的,买家通常在购买已经完成之前不知道价格。谢天谢地,我的雇主给我提供了不错的健康保险,这意味着四次治疗后,我基本上可以“免费”去了。想到困惑的安泰保险精算师可能会看到一个 23 岁的女人每年花费公司超过 20,000 美元的医疗索赔,我不禁笑了。我的方式坚持到男人我猜?
这段旅程,从绿点 80 美元的无用医疗护理到上东区 550 美元的改变生活的护理,让我对这个我们生活所依赖的古怪系统思考了很多。当然,更好的东西通常比更差的东西更值钱。我明白了。但是我在相当剧烈的疼痛中度过了两年。一想到挡在我和一生的痛苦之间的只是 3 万美元,我就觉得恶心。(有人打电话给上东区的医生……)
如果我真的有很高的https://www.healthcare.gov/glossary/high-deductible-health-plan/#:~:text=For%202020%2C%20the%20IRS%20defines,or%20%2413%2C800%20for%20a%20family.】免赔额,或更高的最高自付费用,或没有足够的可支配收入来支付这些自付费用,或我处于工作空档期,或我正在接受医疗补助(世界著名医院不接受医疗补助),或该医院被我的雇主保险计划视为“网络外”怎么办?我可能负担不起 550 美元的预约,更不用说去看 15 位医疗专业人士(以及毫无意义的 19,000 美元的手术),这位职业治疗师改变了我的生活。除非我幸运地拥有一个病毒式的 GoFundMe 页面,否则我会陷入一生的痛苦之中。这是美国。《独立宣言》说了什么——生命、自由和对止痛药的追求?
该项目
纽约拥有一些世界上最优秀、最聪明的医学专业人士。我知道是因为我现在已经见过超过 15 个了,其中有几个非常非常聪明。其中一个非常刻薄,我甚至说“你能不能不要再对我刻薄了?”所以我们就不算她了。不幸的是,对纽约的病人来说,最好的往往也是价格最高的。我亲眼看到同样的服务在三个社区之间的价格差异有多大,所以我想把我的医疗保险索赔分析的下一部分重点放在纽约市。作为复习,请查看我的 项目概述 以及 我的分析 的第一部分,其中查看了各州和不同时间的价格差异(关键要点:从 2012 年到 2017 年的平均价格。所分析的服务价格变化为+16%,而 CPI(通货膨胀)+7%)。
许多因素 导致美国医疗费用高昂。吝啬的保险计划、持续的药品价格上涨和不断上升的医疗索赔是许多促成因素中的三个。我想看看这第三个因素,因为它通常让人感觉不受保险公司和大型制药公司的攻击。这可能是因为我们爱我们的医生、护士和其他医疗专业人员,不想责怪他们。对大多数人来说,这并不是他们的错。他们甚至可能不知道他们的病人被要求支付的费用(尽管,他们可能应该知道)。真正的问题可能是大型医院和医疗保健集团在行业中的整合,他们吞并了私人诊所,抬高价格,并额外收取“设施费”(整合是有据可查的 这里 ,而设施费在新冠肺炎时代成为头条新闻,见 这里;还可以看看《华尔街日报》最近的一篇文章,内容是 2021 年的一项新规定,要求医院公布秘密协商的价格。我在一家私人诊所的理疗师(可以说她的工作并不出色,但还不错):80 美元。我在世界著名医院的职业治疗师。$550.
在此分析中,我看一下 2017 年医疗保险提交的索赔 从医疗保险中心获得的&医疗补助服务、种族人口统计和收入。我会在一个区和一个社区的水平上查看所有这些数据。目的是不仅找出价格如何不同,而且可能找出它们不同的原因。从 NYS 健康部门的网站上获得了一张邮政编码到社区的映射图。 2018 年收入数据按邮政编码 从国税局获得。 按邮政编码 统计的种族人口统计数据是从 2019 年美国社区调查中获得的。
方法学
2017 年医疗保险索赔数据被过滤到纽约市,并通过邮政编码映射到街区和区。保留了 25 种最常见的提供者类型及其提供的 5 种最常见的服务。在少于 15 个(共 42 个)社区中提供的任何提供商/服务组合都将被取消。这样,我们可以降低异常值扭曲邻域统计数据的风险。我们剩下了 111 个提供商/服务组合,原来是 125 个。收入和种族人口统计数据同样映射到街区和自治市,并重新计算(因为所有数据最初都是按邮政编码计算的)。对于我们的收入指标,我们使用国税局的税收数据计算每个社区的“调整后人均总收入(AGI)”。这可能不是最理想的统计数据,因为它会被曼哈顿的超高收入者扭曲,但这是我在这样一个粒度级别上能找到的最好的数据。中等收入和中等家庭收入似乎不是最好的衡量标准,因为儿童也需要医疗保健。人均收入似乎是最好的选择。
一旦一切都绘制出来,我们就可以使用一系列的熊猫分组和合并来执行简单的计算。每项服务的中间价格是按纽约市、区和社区计算的。对“调整后的”每项服务的中间价格也是如此,它是通过比较社区/自治市的人均 AGI 与纽约市的人均 AGI 来计算的。以 AGI 区公园的人均 2.7 万美元和纽约市 AGI 的人均 5.3 万美元为例。如果在区公园提供的手术价格为 100 美元,其调整后的价格将为 100 美元(53k 美元 27k 美元)=~200 美元。区公园的人均收入大约是纽约市总和的一半,所以它的医疗服务费用大约是当地居民的两倍(有点像我们在调整生活成本)。*
一旦计算出纽约市、行政区和社区的每项服务的调整/未调整中值价格,我们就可以计算出每项服务与纽约市调整/未调整中值之间的差异。然后,我们可以对每个社区/自治市提供的所有服务的差异进行平均。最后,我们计算每个社区/自治市每个提供商/服务有多少人,将其与纽约市的总统计数据进行比较,并取每个社区/自治市提供的所有服务的平均值。****
对于每个具有长名称的区和街区,我们只剩下三个重要的指标,因此我将它们缩写为:
- 平均值。每项服务的平均价格与纽约市平均价格的差异:平均值。中间价差异
- 平均值。每项服务调整后的中间价格与纽约市调整后的中间价格之差:平均值。调整后的中间价差异
- 平均值。每个提供商/服务的人数与纽约市中位数的差异:平均值。每个供应商的人员差异。
结果
自治市统计
每个纽约市行政区的主要统计数据
我们可以看到,即使在调整人均 AGI 之前,布朗克斯区的医疗保险索赔相对较高,平均为+33%,高于纽约市的中位数。一旦我们对 AGI 的人均收入进行调整,由于财富集中在曼哈顿,除了曼哈顿(为-51%)之外,几乎每个区的人均收入都在飙升。布朗克斯调整后的房价现在是令人震惊的+404%。如果我们看看平均值。每个供应商的人数差异,皇后区似乎有最不堪重负的供应商,为+259%。曼哈顿在这一指标上再次表现良好,平均每个供应商少了 67%的人。
这些都是有趣的结论,但是任何去过纽约的人都知道这些区包含了非常广泛的社区。就拿曼哈顿来说——从唐人街,到地狱厨房,到东哈莱姆区,到上东区,这些街区会有很大的不同。我们将使用 散景 来创建这些统计数据的交互式 choropleth 地图(参见 jupyter 笔记本 获取代码),并将使用 数据面板 将地图嵌入到本文中,如下所示。
Choropleth 地图#1:每项服务的中间价格(未调整)
平均值。中值价格的差异,按邻近地区(边界代表邮政编码;多个邮政编码可以是同一街区的一部分)
从左右滚动,我们可以看到,平均。绿点的中间价格差为-14%,而 UES 为+7%。然而,最值得注意的是,我们可以看到皇后区东南部(+69%)和布朗克斯公园/福特汉姆社区(+60%)的房价有多高。
Choropleth 地图#2:每项服务的中间价格(调整后)
平均值。调整后的中值价格差异,按邻近地区(边界代表邮政编码;多个邮政编码可以是同一街区的一部分)
在这张地图上,我们可以通过考虑收入来更实际地看到价格差异。当然,人们可以去城市的其他地方寻求护理。但是,如果它就在附近,显然更容易寻求护理,获得护理的障碍更少。使用调整后的中间价格,很明显曼哈顿大部分地区的医疗费用相对较低。这个岛的最北端是个例外:东哈莱姆区、中部哈莱姆区和因伍德/华盛顿高地,在+200%/+130%/+233%。然而,即使是这样,与布朗克斯相比也相形见绌。布朗克斯公园/福特汉姆现在是+654%,它以南的社区都在+300–350%的范围内徘徊。另一个异常值是东纽约和新地段,为+337%。
平均值比较:白人≥50%的社区与白人< 50%的社区
白人人口≥50%和白人人口< 50%的社区中关键变量的平均值比较
在上表中,我们比较了白人人口比例≥50%的社区(13 个社区)与人口比例为<50% white (29 neighborhoods). Note that all values should be interpreted as percentage points, except AGI per Capita (dollars) and AGI Log (the log of AGI per Capita). In this table, we can see that in majority-white neighborhoods, mean AGI per Capita is $136k vs. $32k, Avg. Difference in Median Price is -4.5% vs. +4.4%, Avg. Difference in Adjusted Median Price is +26% vs. +205%, Avg. Difference in People per Provider is +34% vs. +71%, and the percentage of all provider/service combos offered in the neighborhood (out of all 111 provider/services included in analysis) is 68% vs. 53%.
This indicates that healthcare conditions in majority-white neighborhoods are more optimal: lower prices (both unadjusted and adjusted for AGI), fewer people per provider, and more services offered. However, these are small sample sizes and we should check for significance before we take anything too seriously. Simple t tests (using scipy) are run to check if the differences in means are statistically significant. In the end, only AGI Per Capita and Avg. Difference in Adjusted Median Price are significant (p<0.05; last column).
Checking for Correlations
Correlation matrix of our variables of interest
Before we run our regression analyses to see which variables can help us predict healthcare price disparities, it helps to first create a correlation matrix to gauge the strength and direction of relationships between our variables. In this heatmap, blue indicates a positive correlation and red a negative one. Again, we really only care about significant relationships between variables. Therefore, in the table below we include not only the correlation coefficient (as seen in the matrix above), but also the p value (calculated using pearsonr from scipy.stats) and R² (correlation coefficient²). As a reminder: we like p values when they are <0.05 and R² can be defined as the percentage of variation in y that can be explained by x ( (见此处 )的社区的关键变量的平均值。
我们感兴趣的变量之间的显著相关性(p<0.05)
在上表中,我们只包括显著的相关性(p <0.05), and sort high to low on R². The strongest relationships are between the Avg. Difference in Adjusted Median Price and White population rate, Hispanic/Latino population rate, and AGI per Capita. Interestingly, the percent of the population that is white or Hispanic/Latino appear to explain MORE of the Avg. Difference in Adjusted Median Price (higher R²) than AGI per Capita (lower R²), even though AGI per Capita was part of the adjusted price calculation in the first place. So there might be something about a high white or Hispanic/Latino population, beyond just AGI per Capita, that explains differences in median Medicare claims?
Let’s take the variables with the strongest correlations and visualize them with a Pair Plot, so we can see how linear (or non-linear) their relationships seem to be.
Pair Plot of correlated variables to visualize their linear (or non-linear) relationships
The positive linear relationship between the Hispanic/Latino population and adjusted claims is very apparent. The same can be said for the negative linear relationship between the white population and adjusted claims. On the other hand, the relationship between AGI per Capita and adjusted claims seems to be logarithmically decreasing — not really a linear relationship. This might explain why the correlation between the two variables was not the strongest in the correlation matrix above, although we might have expected it to be. That matrix was looking at linear correlation, not logarithmic correlation. To account for this, we will take the log of our AGI per Capita variable and add it to our pandas dataframe for further analysis.
Next, we’ll run a few multiple regressions to see if we can take a closer look at the size and significance of the effects of these different variables on Avg. Difference in Adjusted Median Price.
Running Regressions
Before we run our regressions, let’s first make sure there isn’t too much “collinearity” among our independent variables. For example, if the percent of the population that is white is too highly correlated with the percent of the population that is Black, it wouldn’t make sense to include both variables in our regression because they would essentially both be saying the same thing (in opposite directions). This could mess with our model. One way of checking for this is to see if any correlation coefficients are ≥0.8. We didn’t have that in our correlation matrix, but a second check is to look at “方差膨胀因子”(VIFs) 。如果任何变量的 VIF ≥ 5,我们就有麻烦了。
检查我们感兴趣的变量的共线性
看起来共线性没有问题,所以我们可以进行第一次回归。我们将检验人口统计学是否有助于预测调整后的价格差异。为此,我们将对因变量(平均值)进行多元线性回归。调整后的中值价格差异)对我们的三个独立变量(黑人、西班牙裔/拉丁裔和白人的人口百分比)的影响。
回归:平均值。人口统计学上调整后的中间价格的差异;调整后的 R = 0.65
我们看到,随着西班牙裔/拉丁裔人口比例的增加,价格也在上涨。调整后的中间价格的差异,其他条件相同)。白人人口的情况正好相反(+1%白人= -3.15%平均。调整后的中间价格的差异,其他条件相同)。黑人/非洲裔美国人在人口中所占的百分比在这一回归中没有显著影响(p > 0.05)。重要的是,这个回归的调整后 R 是 0.65。在我们的下一次回归中,我们将删除“黑人或非裔美国人(%)”作为独立变量(因为它没有显著影响),并查看它如何影响我们调整后的 R 值。
回归:平均值。西班牙裔/拉丁裔和白人人口比例调整后的中间价格差异;调整后的 R = 0.66
当我们从回归中去除“黑人或非裔美国人(%)”时,调整后的 R 略有改善,我们剩下两个与第一个回归相似大小的显著影响。调整后的 R 现在是 0.66。西班牙裔/拉美裔平均+1% =+2.92%。调整后中值价格的差异,其他条件相同。平均+1%的白人= -3.20%。调整后中值价格的差异,其他条件相同。
一个 0.66 的调整后 R——这还不错。这意味着只要看看西班牙裔/拉丁裔和白人的百分比,我就可以解释平均年龄变化的 66%。调整后中间价的差异。但也许人口统计学的整体效应真的只是被人口统计学和人均 AGI 之间的关系所调节。https://www.federalreserve.gov/econres/notes/feds-notes/disparities-in-wealth-by-race-and-ethnicity-in-the-2019-survey-of-consumer-finances-20200928.htm按种族和民族划分的财富差距是有据可查的。我们在计算调整后的汇率时使用了人均 AGI 汇率,因此人均 AGI 汇率显然会对调整后的汇率产生影响。为了探索这种潜在的中介效应,我将使用弗吉尼亚大学描述的 中介分析策略 。
首先,我将根据西班牙裔/拉美裔和白人的人口比例回归 AGI 的人均人口比例。对于这种回归,我将使用人均 AGI 的日志。记住,在我们的配对图中,我们发现了人均 AGI 和平均收入之间的对数递减关系。调整后中间价的差异。
回归:AGI 人均对西班牙裔/拉丁裔和白人人口百分比的对数;调整后的 R = 0.56
在上面的回归中,我们可以看到,在其他条件相同的情况下,人口中的白人比例对人均 AGI 对数有显著影响。然而,在其他条件相同的情况下,西班牙裔/拉美裔人口的百分比对 AGI 人均对数没有显著影响。因此,我们之前发现的白人比例对平均年龄的显著负面影响。调整后的中位数价格的差异可能只是由于白人人口比例与人均 AGI 人口比例的密切关系。
我们可以通过把人均 AGI 的对数加到我们的原始回归中来验证这一点。如果任何其他条款失去了他们的意义,一旦 AGI 人均对数被包括在内,这意味着他们对平均的影响。调整后的中位数价格的差异实际上是由人均 AGI“调节”的。我不知道你怎么想,但我天生不会用对数思考。在我们的结果中,我们如何解释人均 AGI 对数的系数?AGI 人均收入每增加 1%,平均收入就会增加。调整后的中间价的差额(无论系数是/100)。
回归:平均值。AGI 人均对数调整后的中间价格与西班牙裔/拉丁裔和白人人口百分比的差异;调整后的 R = 0.76
在这次回归中,白人所占的百分比已经失去了它的显著性(p > 0.05),但是西班牙人/拉丁美洲人所占的百分比仍然保持着它的显著性,甚至当 AGI 人均对数被加入到回归中时。这似乎表明,在西班牙裔/拉美裔人口较多的地区,价格较高的原因不仅仅是 AGI。也许这解释了我们在布朗克斯看到的更高的价格,不仅是 AGI 调整后的索赔(+404%),而且是未经调整的索赔(+33%),因为布朗克斯大多数是西班牙裔/拉丁裔(56%)。解释这一回归的结果,调整后的 R 为 0.76。西班牙裔/拉美裔人口每增加 1%,平均。在所有其他因素不变的情况下,调整后的价格中位数的差异增加了 2.3%。AGI 人均收入每增长 1%,人均收入就增长 1%。调整后的中位数价格差异减少 0.9%。
结论
- 除了关注保险公司和大型制药公司,我们还需要关注不断上涨的医疗价格和差距
- 纽约是世界上最好的城市,但它的众多行政区和社区之间的医疗价格差距确实很大
- 无论你怎么看,布朗克斯区的医疗保健价格都更高
- 平均值。调整后的中间价格的差异可以很好地解释,只要看看白人人口的百分比和西班牙裔/拉丁裔人口的百分比(0.66 R)
- 人口中白人百分比对平均年龄的影响。调整后的中位数价格的差异实际上是由人均 AGI 的影响调节的(更多的白人=更高的人均 AGI =更低的调整后索赔,主要是因为更高的 AGI)
- 即使控制人均 AGI,拉美裔人口较多的地方(如布朗克斯)也有较高的索赔中位数(拉美裔/拉美裔人口每增加 1%,索赔中位数就增加 2.3%,其他条件相同)
感谢您的阅读,并保持健康!
使用 Plotly 和 Flask 的交互式 Web 仪表板
原文:https://towardsdatascience.com/an-interactive-web-dashboard-with-plotly-and-flask-c365cdec5e3f?source=collection_archive---------2-----------------------
数据可视化
要用 Dash 创建一个真正交互式的应用程序,你需要使用回调。你可以用 Plotly 和 Flask 达到同样的效果。
应用程序和代码—由 autho 提供的图像
看起来好像我对 Dash 有意见。老实说,我没有;这是一个很好的产品,得到了 Plotly 的大力支持,做了它想做的事情。
但是,正如我在上一篇文章中试图演示的那样,当您可以用 HTML 编写 HTML 时,就没有必要用 Python 编写 HTML(因为 Dash 要求您这样做)!我现在要补充的是,Flask 应用程序中不需要额外的复杂层——从根本上说,Dash 是一个 Flask 应用程序——只要一点 Javascript 和 HTML 就可以完成同样的工作。
在我的上一篇文章中,我展示了你可以创建一个简单的 web 应用程序,不需要破折号就可以合并 Plotly 图表。相反,你可以结合使用 Flask 和网页模板。这也给了你创建多页面应用的优势。
[## 用 Plotly 和 Flask 实现 Web 可视化。
towardsdatascience.com](/web-visualization-with-plotly-and-flask-3660abf9c946)
但是 Dash 也允许你通过使用回调函数将新数据加载到图表中来创建交互式应用。所以问题是,我们能用 Plotly plus Flask 模型轻松做到这一点吗?当然,答案是肯定的。你可以用 Dash 做的任何事情也可以用它的底层技术来做:Python、Flask、HTML 和 Javascript。
但是,这真的更容易吗?
这要由你来判断,但从我(可能有偏见)的角度来看是这样的。如果你需要学习一点你以前从未接触过的 HTML 或 Javascript,那么很好,你可能会在未来找到它的用处。
为了演示这一点,我们将快速运行一个显示一系列国家人均 GDP 的基本 web 应用程序。交互性体现在您可以键入一个新的国家名称,图表会通过回调服务器并使用新数据重新加载图表来自动更新。
该应用程序如下所示:
它基于来自 Gapminder 基金会的数据,这些数据包含在 Plotly 库中,并在他们的一些示例程序中使用。
这个应用程序非常小,非常简单,但是演示了可以用来创建令人印象深刻的交互式仪表板应用程序的技术(并提供了可以重用的代码)。你将需要使用一点 HTML,一点 Javascript,并知道如何创建和运行 Flask 应用程序的基本知识(见这里的简单介绍:如何创建和运行 Flask 应用程序)。
您可以在本文末尾找到代码的链接——以 zip 文件的形式下载它,或者从我的 Github 存储库中访问它。
烧瓶应用程序
您可以在下面的代码中看到定义了两条路由:第 13 行的根、 /、和第 9 行的回调。他们都使用来自函数 gm (完成大部分工作)的数据,但是方式不同。根路径使用模板chartsajax.html(我们将在下面看到)并将数据传递给它,而回调只是返回数据本身。你大概可以看到这是怎么回事。
这个应用程序是一个由根路径和chartsajax.html渲染的页面。这将绘制一个初始图,但也允许用户输入一个新的国家名称。当输入该名称时,一个请求被发送到回调路径,从该路径返回的数据被用于更新绘图。结果是一个令人满意的图表更新,但没有您在重新加载整个页面时会遇到的空白屏幕。
第 17 行的函数 gm 实际上创建了情节。它需要一个参数,我们要绘制的国家的名称。该参数缺省值为‘英国’,以满足从没有传递参数的根路径进行调用的需要。然后在第 18 行从 Gapminder 数据集创建一个 Pandas 数据帧。由此我们创建了这个国家的图表。
第 22 行使用 Plotly 自带的编码器将图表编码为 JSON,这是在 HTML 页面中呈现图表所必需的,然后将它返回给调用者。
HTML 页面
HTML 定义了一个简单的布局,如下面第 17 到 23 行所示。几个标题后面是一个单独的段落,一个文本输入框,然后是这个节目的明星,图表。Plotly 需要一个 HTML 中的 < div > 标签来构建一个图表,并在第 22 行显示。
这是最简单的部分——并不是说其余的部分很复杂。
当页面加载 Plotly 和 JQuery 的库时——我们需要 Plotly 来呈现图形,当然,我们将使用 JQuery 函数来实现对服务器的回调。接下来,Javascript 函数 cb 被定义——稍后会详细介绍。
然后加载页面主体,第 25 行到第 28 行的 Javascript 第一次也是唯一一次被执行。我们可以在这段代码中看到,变量 d 被设置为模板变量 graphJSON 的值——这是我们在 Flask 应用程序中传递给模板的值。然后使用 Plotly Javascript 库中的 newPlot 函数绘制 Plotly 图形。这给了我们默认的情节。
现在,如果我们想改变图表以显示不同国家的数据,我们只需输入国家的名称,然后按回车键。图表会自动更新。(注意,如果你输入一个无效的国家,你只会得到一个空白的图表。)
这通过使用第 21 行输入字段中的 onchange 属性来实现。 onchange 做的正是你所期望的:当输入字段的值改变时,函数 cb 用字段的值调用。
回电
那个函数 cb ,就是回调函数。它获取输入字段的值,并通过 JQuery 函数 getJSON 将其发送给回调路由。 getJSON 是一个 AJAX 调用,它对指定的 URL 执行异步 HTTP 请求,向其传递数据,接收响应(它将其解释为 JSON 编码的),并定义当接收到成功结果时要调用的函数。
success 函数获取返回值——这是 JSON 编码的图表——并调用 Plotly newPlot 函数来更新图表。
(顺便说一下,AJAX 代表异步 Javascript 和 XML——换句话说,使用 Javascript 的异步 HTTP 请求使用 XML 作为数据传输的格式,只是目前 JSON 是更常见的数据传输格式,而不是 XML。)
我不会深入介绍 JQuery 函数如何工作的细节,您可以将它作为可以重用的样板代码,或者在这里了解更多关于 JQuery 的内容。然而,了解有用的是数据参数。这看起来像这样
data: { ‘data’: selection }
并且它是将被发送到 Flask 应用中的回调函数的数据。数据是正在发送的参数的名称,而选择是它的值(从文本输入字段传递过来)。
下一步怎么样
正如所承诺的,这是一个使用 Flask、Plotly 和 AJAX 的简单交互式 web 应用程序的快速设计。我希望,随着“Web Visualization with Plotly and Flask”的发布,您可以使用 Dash 的底层技术轻松地构建交互式仪表盘,而且这并不是一项令人畏惧的任务。
Dash 教程还演示了其他一些更复杂的行为,当然,这些也可以使用与我演示的技术类似的技术来实现。但那是以后的事了。
一如既往,感谢阅读。如果你想知道我什么时候发表新文章,请考虑在这里注册一个电子邮件提醒。
如果你不是一个媒体订阅者,那就注册吧,这样你就可以每月花 5 美元阅读尽可能多的文章。在这里注册,我会赚一点佣金。
更新:在你可以在下面下载的代码中,我包含了一个新版本,它只使用 Ajax 来加载图表,也就是说,它不使用传递给模板的参数来加载初始图表。它还在图表上标注了它所代表的国家,我认为这是一个小小的改进——详情请参见自述文件。
获取代码
请在我的代码库中查看代码,或者在这里的 Github 页面上下载这篇文章和上一篇文章的 zip 文件。
贝叶斯统计的一次有趣的散步:MAP 和 MLE 之间的差异。
原文:https://towardsdatascience.com/an-interesting-walk-from-bayesian-statistics-differences-between-map-and-mle-2daea5fc15b?source=collection_archive---------29-----------------------
纳赛尔·塔米米在 Unsplash 上的照片
这篇文章将让你了解任何机器学习模型的基础。用简单的文字和几个公式,你将得到贝叶斯,最大似然估计和最大后验估计充分的能力。
具体来说,让我们从概率和判别函数的角度开始讨论二元分类。这是一次有趣的步行,旨在了解 scikit-learn 和 keras 设施之外的机器学习算法的原理。
想象一下,我们必须将汽车分为两类:环保型和污染型。我们拥有的关于汽车的信息是制造年份和消耗量,我们用两个随机变量 X1 和 X2 来表示。当然,还有其他影响分类的因素,但它们是不可观测的。记住我们可以观察到的,汽车的分类由伯努利随机变量 C 表示( C=1 表示环保, C=0 污染),条件是可观察值 X =【X1,X2】。因此,如果我们知道 P(C|X1,X2) ,当一个新的入口数据点以 X1=x1 和 X2=x2 出现时,我们会说:
作者图片
其中错误概率为 1-max(P(C=1|x1,x2),P(C=0|x1,x2)) 。表示 x=[x1,x2] 那么我们可以使用贝叶斯定理,它可以写成:
作者图片
P(C)被称为先验概率,因为它是我们之前在数据集中拥有的关于 C 的信息,用来分析可观测的 x. 正如你所想象的, 1=P(C=1)+P(C=0)。
P(x|C)被称为类可能性,因为它是属于 C=c 的事件具有相关观察值 x. 的概率
P(x)是证据,因为它是在我们的数据集中看到观察值 x 的概率。这个术语也称为规范化术语,因为它将表达式相除,得到一个介于 0 和 1 之间的值。证据概率是所有可能情况的总和(也称为全概率定律):
P(x)= P(x | C)1)P(C = 1)+P(x | C = 0)P(C = 0)
最后,P(C|x)是我们想要知道的,每一类给定一个观察值的概率。这被称为后验概率因为我们在看到观察值 x 后对其进行了分类,当然 P(C=0|x)+P(C=1|x)=1。
在有几个类的情况下,我们可以将这个表达式扩展到 K 类:
作者图片
并且贝叶斯分类器将从 K 个选项中选择具有最高后验概率 P(Ci|x)的类。
在之前的文章中,我解释了如何根据区分函数来理解分类,区分函数限制了空间中的假设类别区域。按照同样的思路,我们可以实现那组判别函数。具体来说,我们选择 C_i,如果:
作者图片
如果我们将判别函数视为贝叶斯分类器,则最大判别函数对应于最大后验概率,得到:
作者图片
请注意,我们已经删除了归一化项(证据),因为它对所有判别函数都是一样的。该集合将特征空间分成 K 个决策区域:
作者图片
在实践中,我们观察到的信息片段,又名数据点,它们通常遵循一个给定的概率分布,我们将其表示为 P(X=x) ,正如我们之前所讨论的。当我们有像 P(C=1|x)或 P(X=x)这样的值时,贝叶斯分类似乎很容易计算。然而,如果我们不确切地知道P(X),因为我们不能访问所有的数据点,我们试图从可用的信息中估计它,于是统计就出现了。
统计数据是从给定样本中计算出的任何值。
P(X)可以有不同的形状,但是如果给定的样本来自一个已知的分布,那么我们说它遵循一个参数分布。参数分布是非常理想的,因为我们只需要知道几个参数就可以画出一个完整的分布。我们该怎么办?基于我们所看到的(样本),我们通过计算样本的统计量来估计分布的参数,即分布的充分统计量。这使我们能够获得数据的估计分布,我们将使用它来做出假设和决策。
最大似然估计
如果你已经到了这一步,请忘记之前贝叶斯解释的一切。
让我们从头开始:我们的数据集中有 N 个数据点。看起来这些数据点的概率密度遵循一个清晰的分布族 **p(x),**但是我们对真实分布的形状没有任何线索(它的真实中心,它的真实离差,等等)。如果我们面对的是参数分布,那么计算定义真实分布的参数就很简单。怎么会?让我们根据现有的给定样本来看看最有可能的选项。
我们有一个独立同分布(iid)样本:
作者图片
它的概率密度由一组参数θ定义。让我们找出使给定样本的分布尽可能接近的具体θ参数。因为数据点是独立的,所以它们的似然性是各个点的似然性的乘积。具体来说,对于给定的θ,我们来看概率 p(x|θ)。概率越高,匹配度越高。
作者图片
那么,对于给定的数据集 X, l(θ|X) 的θ的可能性等于 *p(X|θ)。*为了使事情更简单,我们通常将对数应用于可能性,因为计算速度更快(求和而不是乘法):
作者图片
现在,我们只需驱动对数似然,然后根据θ将其最大化(例如使用梯度下降)。
**重要提示:**我们通常互换术语“可能性”和“概率”。然而,它们是不同的东西。概率是固定分布(特定情况)下的面积。对于概率,我们想知道给定分布情况下的概率。相比之下,可能性是分布中可以移动的固定点的 y 轴值。似然性是指为某个特征的固定值找到最佳分布。可能性包含的不确定性信息要少得多,它只是一个点而不是一个区域。
作者图片
我们搜索不同的θ值,选择使对数似然最大的θ:
图片作者。蓝点代表样本的数据点。从不同的θ值得出不同的分布,选择“最匹配”的一个。
如果我们观察许多不同的样本,分布参数的估计量将更准确,与真实参数的偏差更小。稍后我们将看到如何评估估计量的质量,换句话说,估计量与θ的差异有多大。
将最大似然法应用于伯努利分布
在伯努利中,有两种可能的状态:真或假,是或否。事件发生或不发生。因此,每个数据点可以取两个值:0 或 1。实际上,它以概率 *p,*取值 1,以概率 1-p. 取值 0,因此:
作者图片
该分布用一个参数建模: p. 因此,我们想从一个样本中计算它的估计量 p̂。让我们根据 p: 来计算它的对数似然
作者图片
现在,求解 dL/dp=0 以获得最大化表达式的 p̂:
作者图片
最大后验概率
现在是时候回到贝叶斯理论了。有时,在查看样本之前,我们可能有一些关于参数θ可能取值范围的信息。当样本很小时,这些信息会非常有用。
因此,先验概率 p(θ) 定义了θ在查看样本之前可能取的值。如果我们想在查看 X 样本后知道可能的θ值, *p(θ|X),*我们可以使用贝叶斯:
图片由作者基于[1]
注: 我们可以忽略规格化项(或证据),当我们在谈论优化时,它并不影响。
因此,如果我们想要一个模型来预测给定输入 x 的输出, y=g(x) ,就像在回归中一样,我们实际上是计算 *y=g(x|θ)。*视分布情况而定。
然而,由于我们不知道 *θ、*的真实值,我们必须使用 θ ( 按概率加权)的所有可能值对预测取平均值:
作者图片
积分的计算可能非常复杂和昂贵。代替这样做,我们可以只取一个点,最可能的点,最大后验概率。
因此,我们想要得到 *θ,*最可能的值,或者换句话说,最大化 P(θ|X),,这与最大化 P(X|θ)P(θ): 相同
图片由作者基于[1]
如果你花一点时间将这个公式与 MLE 方程进行比较,你会发现它的不同之处仅在于 MAP 中包含了先验 P(θ) 。换句话说,可能性是用来自先验的信息来加权的。最大似然法是无先验信息映射的特例。
MLE 是映射的一个特例。
如果这个先验信息是恒定的(均匀分布),它对最大化没有贡献,我们将得到 MLE 公式。
具体来说,想象θ可以取六个不同的值。因此,P(θ)在分布中处处都是 1/6:
图片由作者基于[1]
然而,如果先验不是常数(它取决于分布的区域),概率也不是常数,必须考虑它(例如,如果先验是高斯的)。
**重要:**可以选择最大后验概率而不是计算积分,前提是我们可以假设 P(θ|X) 在其模周围有一个窄峰。为什么?因为我们取的是单个点,而不是计算所有的区域,没有不确定性的表示。当模式周围没有窄峰时,可能会发生这样的事情:
作者图片
参考书目:
[1]奥古斯丁·克里斯蒂亚迪的博客https://wiseodd.github.io/techblog/2017/01/01/mle-vs-map/
[2]艾瑟姆·阿尔帕丁。机器学习导论,第 4 版。
PyTorch 闪电简介
原文:https://towardsdatascience.com/an-introduction-of-pytorch-lightning-230d03bcb262?source=collection_archive---------9-----------------------
只需更改一个参数,即可将代码从单 GPU 移植到多 GPU 训练
PyTorch lightning 帮助您将代码扩展到多 GPU 培训,无需任何工程工作
Johannes Plenio 在 Unsplash 上拍摄的照片
坊间传言 PyTorch lightning 是普通 PyTorch 的更好版本。但是,它能给我们的世界带来什么样的共识呢?嗯,它帮助研究人员通过多 GPU 训练、Fp-16 训练和 TPU 支持的训练来扩展模型,只需改变一个参数。
由吉菲
是的,你没看错。只要改变一个论点,你就可以做所有这些惊人的事情。还记得我们过去是如何编写多 GPU 训练代码的吗?我们必须了解 PyTorch 支持的不同训练架构,然后自己实现它们。谢天谢地,再也没有了!PyTorch Lightning 将改变我们编写代码的方式,并帮助我们在一秒钟内完成所有这些任务。
为了涵盖所有的变化,我用以下方式构建了这个博客:
- PyTorch 和 PyTorch Lightning 在实现上的差异的总体比较
- 比较每个模块,如模型、损失函数等。为了 PyTorch 和 PyTorch 闪电
- 多 GPU 训练
- TPU 培训
- FP16 培训
- 提前停止
- LR 取景器
py torch 和 PyTorch Lightning 的基本对比
两个框架之间的比较(图片由作者提供)
具有相同颜色的代码块表示相同模块的实现。例如,两个框架中的模型定义都是浅绿色的。
首先要注意的是,PyTorch lightning 在类 Net 本身*中加入了 train_dataloader、configure _ optimizers、training_step 。*另外,请注意,我们在 PyTorch 中编写的整个训练循环在 PyTorch lightning 中只有几行。
通用深度学习代码组件
一般来说,深度学习代码具有以下组件
- 模型
- 数据
- 失败
- 【计算机】优化程序
- 训练和测试回路
- 记录
让我们了解 PyTorch 和 PyTorch lightning 在上述组件方面的区别。
模型
正如我们上面注意到的,模型架构和定义是相同的,除了在 Pytorch Lightning 中所有其他函数定义也在同一个类中。
模型对比(图片由作者提供)
数据
在 Pytorch Lightning 中定义数据加载器有两种方法。
- 您可以在 Net 类中定义 train_dataloder 和 val_dataloader 函数,就像前面所做的那样(在第一个例子中)
- 你可以像 PyTorch 中一样定义自己的 train_dataloader 和 val_dataloader 到 trainer.fit ,如下图所示。
MNIST 数据加载器
使用上述方法,您可以为 PyTorch 和 PyTorch lightning 定义数据加载器。两者的主要区别在于 Pytorch Lightning 中的 trainer.fit() 将所有数据加载器作为参数。
trainer.fit(net, train_dataloader, val_dataloader)
trainer.test(net, test_dataloader)
失败
对于 n 类分类,我们要计算交叉熵损失。交叉熵与 NegativeLogLikelihood(log _ soft max)相同,所以我们将使用它来代替。
损失比较(图片由作者提供)
【计算机】优化程序
让我们使用 Adam 优化器。
优化程序比较(图片由作者提供)
自我。 parameters() 这里传递的,包括模型中定义的所有可学习的参数。
训练和验证循环
在 PyTorch,我们必须
- 定义训练循环
- 加载数据
- 通过模型传递数据
- 计算损失
- 做零工
- 反向传播损失函数。
然而,在 PyTorch 闪电中,我们必须
- 定义 training_step 和 *validation_step,*在这里我们定义我们希望数据如何通过模型
- 计算损失
我们甚至不用指定 model.train() 和 model.eval() 。
训练和验证比较(图片由作者提供)
记录
Tensorboard 是美国研究人员最常用的记录器之一。所以正如你在 PyTorch lightning 上面注意到的,在函数 training_step 和 validation_step 的最后一行,提到了 self.log() ,这是用来记录训练损失的。这将创建一个名为 lightning_logs 的文件夹,并在其中保存所有日志和时期。
概述
- 模型定义过程类似,但有两个主要区别。1)所有其他函数也是用 PyTorch lightning 的模型类本身定义的。2)神经网络。Pytorch 中的模块在 PyTorch lightning 中被 nn.LightningModule 覆盖。
- 可以用同样的方式定义数据加载器。对于 PyTorch lightning,我们必须在 train.fit() 时通过 train_loader 和 val_loader
- Optimizer 和 loss 可以用同样的方式定义,但是它们需要作为 PyTorch lightning 的主类中的一个函数存在。
- 培训和验证循环在 PyTorch lightning 中预定义。我们必须定义训练 _ 步骤和验证 _ 步骤,即给定一个数据点/批次,我们希望如何通过该模型传递数据。
- 用于记录的函数是预定义的,可以在 Pytorch Lightning 中直接调用。
既然我们知道了这两者之间的区别,那就让我们来理解为什么我们首先要开始这个比较。为了使代码可伸缩并减少我们的工程工作,让我们看看感兴趣的特性。
多 GPU 训练
我们可以使用下面的代码来实现。
trainer = Trainer(gpus=8, distributed_backend='dp')
您可以定义要用于分布式培训的 GPU 数量,以及要使用的后端。这里我定义了“dp ”,它是并行分布的。也可以定义为‘DDP’,即分布式数据并行。
TPU 培训
我们可以使用下面的代码来实现。
trainer = Trainer(tpu_cores**=**[5])
这个代码意味着模型将在 ID 为 5 的 TPU 核心上训练。我们还可以通过使用单个参数启用多 TPU 训练来定义需要使用多少个内核。
FP16 培训
这是我最喜欢的。FP16 有助于加快训练过程,而不会对性能造成太大影响。
trainer = Trainer(precision**=**16)
提前停止
这用于在训练模型时,如果您看不到模型性能有任何进一步的提高,则停止训练。我们如何持续检查模型性能是否在提高?为此,我们可以使用验证损失或准确性。
from pytorch_lightning.callbacks.early_stopping import EarlyStoppingdef validation_step(...):
self.log('val_loss', loss)trainer = Trainer(callbacks=[EarlyStopping(monitor='val_loss', patience=3)])
在上面的例子中,培训师将跟踪验证的准确性。如果过去 3 个时期(耐心值)的性能没有改善,那么它将停止训练,从而防止过度拟合。
LR 取景器
学习率是最重要的超参数之一,正确设置初始学习率至关重要。否则,在训练模型时,可能会出现模型收敛到无法提供最佳性能的局部最优值的情况。
net **=** LightningMNISTClassifier()
*# finds learning rate automatically*
*# sets hparams.lr or hparams.learning_rate to that learning rate*
trainer **=** Trainer(auto_lr_find**=True**)
trainer**.**tune(net)
为了找到最佳学习率,你必须使参数 auto_lr_find 为真*,*,然后调整训练器(使用 trainer.tune() ),这将帮助你找到学习率。之后可以调用 trainer.fit() 对模型进行训练。
只需添加一些参数,Pytorch Lightning 就能帮助我们享受许多功能,而每一项功能对我们来说都至关重要。现在您有了一个基本的想法,通过编写您的第一个神经网络并探索该库提供的不同功能,开始实践 PyTorch lightning。
如果你想学习深度学习的很酷的应用,请查看我们关于深度学习语音处理的博客这里。
成为 介质会员 解锁并阅读介质上的许多其他故事。关注我们的 中 阅读更多此类博文。
阿帕奇气流简介
原文:https://towardsdatascience.com/an-introduction-to-apache-airflow-21111bf98c1f?source=collection_archive---------6-----------------------
作为数据科学家,这是一个很好的管道自动化工具
克里斯托夫·高尔在 Unsplash 上拍摄的照片
什么是阿帕奇气流?
成为数据科学家的很大一部分是能够自动进化模型并生成报告。对于需要定期收集数据、生成周期报告等的模型。手动运行程序非常耗时且不可扩展。能够自动化整个数据管道来生成报告是非常有用的。这正是阿帕奇气流带来的东西。
Apache Airflow 是一个开源的作业调度程序,它可以组织、执行和监控任何周期性时间间隔内的任何工作流。这个项目是从 Airbnb 开始的,已经被很多大公司如谷歌和亚马逊接手。
气流是如何工作的?
Airflow 利用有向无环图(Dag)来创造就业机会。
DAG 由节点和有向箭头组成。每个节点都是一个函数,当该函数运行时将被执行,每个箭头都指向当前节点之后将被执行的下一个节点。对于有多个箭头进入的节点,必须先完成所有的依赖关系,然后节点才能启动。
图中的每个节点都由一个运算符定义。有许多运算符,如 BashOperator、PythonOperator 等。每个操作员负责运行该操作员类型的功能。例如,如果您有一个 PythonOperator,您可以告诉操作员运行 python 函数。这是所有可能的气流操作员的列表。
每个 DAG 由 DAG python 文件指定,该文件指定节点和节点之间的依赖关系。
气流 DAGs 页面
从 Dag 视图中,您可以看到当前注册到 Airflow 中的所有 Dag。从这里,您可以查看作业的状态、触发现有作业、刷新作业等等。
设置气流
设置气流非常简单。此设置过程将用于 MacOS,但在线也有相应的 Windows 设置步骤。在安装过程之前,请确保您已经安装了自制软件[ 说明 ]。家酿是一个软件包安装程序,它使得安装程序和软件包更加简单。
1.安装 Python3 和 pip
安装 Python3,然后检查以确保 Python 版本是 3+
% brew install python% python --version
python 3.8.3
安装 pip
% curl [https://bootstrap.pypa.io/get-pip.py](https://bootstrap.pypa.io/get-pip.py) -o get-pip.py% python get-pip.py
要安装 Airflow,请确保 pip 版本为 20.2.4
% pip install --upgrade pip==20.2.4% pip --version
pip 20.2.4 from /usr/local/anaconda3/lib/python3.8/site-packages/pip (python 3.8)
2.[可选]创建虚拟环境安装气流
一般来说,安装一个虚拟环境是一个很好的实践,这样你就不会把你的本地环境和很多包聚集在一起。虚拟环境可以很容易地激活和停用。安装virtualenv
并为虚拟环境创建一个名称,本例中的名称是venv
。
% pip install virtualenv% virtualenv -p python venv
现在激活虚拟环境,这样所有的包都会安装到虚拟环境中,而不是您的计算机上。
% source venv/bin/activate
现在,您的虚拟环境被激活。你的控制台现在应该有(venv)
在它前面。
3.安装和设置气流
在新的airflow
目录中安装气流
(venv) % mkdir airflow && cd airflow(venv) % pip install apache-airflow
设置正确的目录结构,并创建一个新的气流文件夹。首先用pwd
获得 airflow 文件夹的路径,然后将其作为 airflow 主目录导出到该路径。
(venv) % pwd
/Users/<username>/airflow/airflow(venv) % export AIRFLOW_HOME=/Users/<userid>/airflow/airflow
最后,初始化气流数据库。Airflow 使用 Sqlite 数据库来跟踪所有 airflow DAGs 的元数据。
(venv) % airflow db init
现在,您应该会看到 airflow 目录中的一堆文件。在下面的终端输出中,我使用了一个名为tree
的包,但是ls
也可以工作。是一个非常有用的查看目录结构的包。
(venv) % brew install tree(venv) f.liang@fliang-ltm airflow % tree
.
├── airflow.cfg
├── airflow.db
├── logs
│ └── scheduler
│ ├── 2021-04-16
│ └── latest -> /Users/<userid>/airflow/logs/scheduler/2021-04-16
├── unittests.cfg
└── webserver_config.py
4.启动气流
在第一次启动 Airflow 时,您必须创建一个新用户。我刚刚对大多数字段使用了简单的admin
,但是你可以自定义它。
(venv) % airflow users create \
--role Admin \
--username admin \
--email admin \
--firstname admin \
--lastname admin \
--password admin
要检查用户是否已成功添加,请列出所有用户
(venv) % airflow users list
id | username | email | first_name | last_name | roles
===+==========+=======+============+===========+======
1 | admin | admin | admin | admin | Admin
然后启动 Airflow 作业调度程序
% airflow scheduler
创建一个新的终端(Mac 上的CMD + T
,并再次设置AIRFLOW_HOME
路径。如果您之前设置了虚拟环境,请不要忘记激活虚拟环境。如果不这样做,那么airflow
命令在新的终端中将不起作用。然后启动 web 服务器。
(venv) % export AIRFLOW_HOME=/Users/<userid>/airflow/airflow(venv) % airflow webserver
从这里开始,一切都应该设置好了,所以打开任何网络浏览器并转到 localhost:8080 。8080 应该是您的airflow.cfg
文件中的默认端口,但是如果这不起作用,请打开您的 airflow.cfg 文件,查找web_server_port
字段并将其设为 8080。在这里,只需输入您之前创建的用户名和密码(用户名和密码都是admin
)并登录。
登录后,您可以浏览并运行许多示例 airflow 作业。
5.创建您自己的 Dag
要阻止示例 dag 的显示,请打开您的airflow.cfg
文件并将load_examples
设置为False
,然后创建一个 Dag 文件夹,如airflow.cfg
中的dags_folder
变量所指定的。故障 dags 文件夹路径为AIRFLOW_HOME/dags
。
(venv) % mkdir /Users/<userid>/airflow/airflow/dags
将您的 DAG 文件添加到dags/
文件夹中,Airflow scheduler 将自动拾取 DAG,并在几分钟内将其反映在 web 服务器中。任何编译错误也会显示在 UI 和 logs 文件夹中。
结论
Apache Airflow 对于任何机器学习工程师或数据科学家来说都是一个非常方便的工具,可以用来安排和自动化工作流。通过用 docker 容器替换虚拟环境并将 docker 映像托管在云中,工程师可以在几分钟内部署和监控整个数据管道。
机器人简介
原文:https://towardsdatascience.com/an-introduction-to-bots-ff142bb07603?source=collection_archive---------24-----------------------
它们是什么,它们的类型是什么?
安德烈斯·乌雷纳在 Unsplash 上拍摄的照片
在当今世界,我们被技术包围着,每天都有新的技术被开发和制造出来。技术以我们以前无法想象的方式让我们的生活变得更好。也许其中一项有影响力的技术是机器人。
机器人是一种特殊的软件,被设计和开发用来在没有人类帮助的情况下自动完成特定的重复性任务。机器人被开发出来是为了通过比人类更快、更有效地完成某些任务来减轻人们的负担。
大多数时候,机器人是在某种类型的网络上运行的软件,通常是互联网。它们与其他机器人、网页甚至人类互动,寻找它们旨在解决的问题。如果我们想对机器人进行分类,我们可以定义两个通用类别,好机器人和坏机器人。
</6-web-scraping-tools-that-make-collecting-data-a-breeze-457c44e4411d>
“好的机器人”是一个用来描述帮助用户并提供有效服务的机器人的术语。坏的或恶意的机器人是那些执行非法且有时不道德的任务的机器人。但是,我们必须记住,机器人就像任何其他技术形态一样,没有好坏之分;相反,人们决定使用它们的方式决定了它们是好是坏。
如何对机器人进行分类?
如果你试着用谷歌搜索各种类型的机器人,你会发现有些人说有六种、七种,或者有些人甚至说有四种类型的机器人,因为当对机器人进行分类时,人们通常会设置自己的规则和术语来描述他们将如何做。因此,我们最终有了各种各样的分类。
在本文中,我们将坚持好的和坏的机器人的一般分类,以探索我们在机器人领域的道路。也就是说,机器人可以以许多其他不同的方式分类。
具有良好应用程序的机器人(好机器人)
№1:聊天机器人
从名字上看,聊天机器人是那些被设计用来与人类对话的机器人。这些机器人最常用于客户服务,以解决问题并帮助人们更好地了解服务或产品。聊天机器人是为了模仿自然的人类互动而构建的。
要让聊天机器人模仿人类互动,它们需要能够理解和使用人类语言。理解人类语言是一个复杂的问题;这是自然语言处理的核心挑战。这就是为什么大多数聊天机器人被设计为针对特定场景的狭义上下文 AI。
有很多聊天机器人,但第一个,也是被认为是聊天机器人诞生的人是伊莱扎。这个聊天机器人有硬连线的问答脚本,用于与人类交流。聊天机器人的其他例子有来自美洲银行的财政援助埃里卡,以及通过推特与人互动的微软人工智能聊天机器人泰伊。
</6-nlp-techniques-every-data-scientist-should-know-7cdea012e5c3>
№2:爬虫
好的机器人列表中的第二种类型的机器人是爬虫。爬虫是持续运行的机器人,分别与 API 或网站进行交互以收集一些数据。这些类型的机器人只获取公共可用的数据或他们有权获取的数据。
最广为人知的爬虫是搜索引擎蜘蛛。搜索引擎蜘蛛是一种机器人,旨在从 web 中提取 URL,然后这些 URL 用于下载和解析数据到可搜索的索引中。常用的搜索引擎蜘蛛有 Googlebot 和 Bingbot 。
爬虫不仅仅是搜索引擎蜘蛛;另一种类型的爬虫是机器人,它们被构建来监视和管理系统,并在发生变化时发出警报。这类爬虫的例子有定价助手、监控电子商务网站的价格变化,以及 Alertbot 监控网站的服务器正常运行时间、漏洞和网站错误。
№3:交易型机器人
交易型机器人是为了代表人类而构建的。他们需要与系统交互来完成某些任务,这些任务通常与数据移动有关。由于事务型机器人是为特定的任务而构建的,它们可以被设计成不同的定制解决方案。
交易型机器人涉足的领域之一是机器人领域。一些已知的事务性机器人是 Birdly 一个用于为你检索特定数据的 Slackbot,以及 x.ai 的 Amy Ingram,一个旨在通过电子邮件与人互动的机器人,以找到分布式团队的最佳会议时间。
№4:信息机器人
最后但同样重要的是,在好的机器人列表中,我们有信息机器人。信息机器人旨在通过推送通知或发送电子邮件和文本来提供有用的信息。
信息机器人最常见的用法是突发新闻机器人。这些机器人监控新闻,并在有事发生时发出警报。这种机器人的一个例子是 GuardianBot ,它允许你通过 Facebook Messenger 获得最新新闻的点播简报,以及 GamerBot,允许你通过 Facebook Messenger 获得特定点播内容的定期游戏新闻更新。
在不良应用中使用的机器人(不良机器人)
№1:黑客
让我们从黑客机器人开始我们的坏机器人名单。这些机器人旨在通过电子邮件或网站分发和启用恶意软件。这些机器人的目标是攻击数据,有时破坏网络。他们通过寻找网络或应用程序中的漏洞,然后利用这些漏洞来破坏网络或应用程序。
黑客机器人的数量每年都在增加;一旦电脑或网络被黑,他们的信息就永远被利用。机器人的设计者可以将它用于不同的目的。
№2:刮刀
爬行器是爬行器的坏版本。爬虫在从 API 或网页获取数据时遵循 low。然而,抓取程序会窃取他们不该访问的数据,如电子邮件地址、密码和个人信息。
这些机器人通常被设计为忽略 API 和网站数据获取规则来获取目标数据。一旦这些机器人窃取了数据,它们就会重新发布数据并利用这些敏感信息。
№3:垃圾邮件制造者
垃圾邮件发送者是一种机器人,顾名思义,垃圾邮件是通过电子邮件或错误广告向用户提供的内容,最终将流量导向某个特定的网站或博客。你可能在网上见过的例子有评论和邮件垃圾。
幸运的是,由于好的机器人和搜索引擎的发展,检测坏机器人的行为,垃圾邮件或任何垃圾邮件的数量在最近几年迅速下降。
</4-software-development-techniques-to-level-up-your-data-science-project-59a44498ca3f>
№4:模仿者
最后但同样重要的是,我们有模仿机器人。这些机器人旨在模仿特定用户的行为,以获取有关他们的信息或窃取一些敏感数据。
这些机器人经常在政治中大量使用,以模仿人类行为,并将注意力从对手身上转移到特定目标上。为此使用模仿者创造了所谓的宣传机器人。
最后的想法
作为数据科学家,我们有时需要比想象中更频繁地设计、构建、开发和处理机器人。不仅仅是作为数据科学家,如今每个人都至少每周与机器人打交道一次。这就是为什么知道什么是机器人和什么类型的机器人是一个很好的信息。
我们可以用不同的方式对机器人进行分类;在本文中,我们根据使用方式对机器人进行了一般分类。机器人可以被构建并用于执行合法的、道德的任务,也可以被用于执行非法的任务。
机器人仅仅是一项技术,一项本身没有好坏之分的技术;总的来说,他们是中立的。这只是取决于如何利用它们。所以,下次你听到有人称一个机器人为“坏机器人”,只要知道他们的意思是这个机器人已经被用坏了。
构建世界级欺诈预测模型简介
原文:https://towardsdatascience.com/an-introduction-to-building-a-world-class-fraud-prediction-model-aed1c3c314d2?source=collection_archive---------32-----------------------
模型的类型、要使用的关键特性以及如何评估模型
Bermix 工作室在 Unsplash 拍摄的照片
介绍
随着世界变得越来越数字化,人们更好地配备了新技术和工具,欺诈活动的水平继续达到创纪录的高水平。根据普华永道的一份报告,2020 年欺诈损失总计 420 亿美元,在过去 24 个月中影响了 47%的公司。
矛盾的是,同样的技术进步,如大数据、云和现代预测算法,让公司比以往任何时候都更好地应对欺诈。在本文中,我们将特别关注最后一点,欺诈预测算法,具体来说,我们将了解欺诈模型的类型、欺诈模型中使用的功能以及如何评估欺诈模型。
欺诈预测模型的类型
因为“欺诈”是一个非常全面的术语,所以您可以构建几种类型的欺诈模型,每种模型都有自己的用途:
特定于配置文件的模型与特定于交易的模型
档案特定模型专注于识别用户级别的欺诈活动,这意味着这些模型可以确定用户是否欺诈。
交易特定模型采用更精细的方法,识别欺诈交易,而不是欺诈用户。
乍一看,这些模型似乎服务于相同的目的,但欺诈交易并不总是来自欺诈用户。这方面的一个例子是信用卡盗窃-如果用户的信用卡被盗,并且在该信用卡上进行欺诈性交易,则该用户不应被视为欺诈。类似地,欺诈用户进行欺诈交易的情况并不总是如此——是否应该允许该用户进行任何交易是另一个话题。
因此,考虑特定于概要文件和特定于事务的模型是很重要的。
基于规则的模型与机器学习模型
基于规则的模型是带有硬编码规则的模型,想想“if-else”语句(或者 case-when 语句,如果你是 SQL 天才的话)。对于基于规则的模型,您有责任自己提出规则。如果您知道指示欺诈活动的确切信号,基于规则的模型非常有用。
例如,信用卡公司通常有一个基于规则的方法来检查您使用信用卡的位置。如果你用信用卡消费的地方和你的家庭住址位置之间的距离超过某个阈值——如果你离家太远——交易可能会自动被拒绝。
随着过去十年数据科学的出现,机器学习欺诈检测模型变得越来越受欢迎。当您不知道指示欺诈活动的确切信号时,机器学习模型非常有用。相反,你提供一个具有少量特征(变量)的机器学习模型,并让该模型自己识别信号。
例如,银行将数十种工程特征输入机器学习模型,以识别哪些交易可能是欺诈性的,并进入第二阶段进行进一步调查。这将进入下一部分,这是您应该在欺诈模型中使用的功能。
在您的模型中使用的关键功能
为您的模型选择特征的主要目的是包含尽可能多的指示欺诈活动的“信号”。
为了帮助激发一些想法,下面是机器学习模型中常用的关键功能的非穷举列表:
- 注册或交易时间:用户注册或交易的时间是一个很好的信号,因为欺诈用户的行为并不总是与普通用户相同。这意味着他们可能会在人们通常不进行交易的时候进行大量交易。
- 交易地点:正如我之前提到的,交易发生的地点可以很好地表明交易是否欺诈。如果交易是在远离家庭住址 2000 英里的地方进行的,这是一种不正常的行为,可能是欺诈行为。
- 成本与平均支出比率:这是给定交易的金额与给定用户的平均支出的比较。比例越大,交易越不规范。
- 邮件信息:您可以实际查看邮件的创建时间。如果在同一天创建了电子邮件和帐户,这可能意味着欺诈行为。
您可以提供的信号越多,信号越强,您的模型在预测和识别欺诈活动方面就越好。
如何评估一个欺诈模型
由于问题的性质,评估欺诈预测模型必须以不同于正常机器学习模型的方式进行,这将在下一节中详细阐述。
为什么你不应该使用准确性
欺诈检测被归类为**不平衡分类问题。**具体来说,欺诈性档案/交易的数量与非欺诈性档案/交易的数量之间存在显著的不平衡。因此,使用准确性作为评估标准是没有帮助的。
举例来说,考虑一个包含 1 个欺诈性交易和 99 个非欺诈性交易的数据集(在现实世界中,这个比例甚至更小)。如果一个机器学习模型将每一笔交易都归类为非欺诈性的,那么它的准确率将达到 99%。然而,这未能解决手头的问题,即对所有欺诈交易进行分类。
要使用的度量标准
相反,在评估欺诈预测模型时,您应该考虑两个指标:
精度也称为正预测值,是相关实例在检索到的实例中所占的比例。换句话说,它回答了“多大比例的积极认同是正确的?”
当将非欺诈性交易归类为欺诈性交易的成本太高,并且您可以接受仅捕获一部分欺诈性交易时,Precision 是首选。
回忆,也称为敏感度、命中率或真阳性率(TPR),是实际检索到的相关实例总数的比例。它回答了“有多少比例的实际阳性被正确识别?”
当确定每一笔欺诈性交易至关重要,并且可以接受将一些非欺诈性交易错误归类为欺诈性交易时,最好使用召回。
每种方法都有自己的优缺点,应该根据手头的业务问题进行选择。下面是一张图片,可以更好的理解两者的区别。
作者创建的图像
感谢阅读!
如果你想了解更多关于欺诈、电子商务和数据科学的知识,请收听 Riskified 数据科学副总裁 Elad Cohen 的播客。同样,如果您想了解如何用 Python 构建一个实际的欺诈预测模型,您可以查看这个 Kaggle 的信用卡欺诈预测模型库。
一如既往,我祝你学习一切顺利:)
不确定接下来要读什么?我为你挑选了另一篇文章:
又一个!
特伦斯·申
- 如果你喜欢这个, 跟我上中等 更多
- 有兴趣合作吗?让我们连线上LinkedIn
云原生模型简介
原文:https://towardsdatascience.com/an-introduction-to-cloud-native-model-3076183294e5?source=collection_archive---------18-----------------------
转向云原生的原则和优势
照片由西格蒙德在 Unsplash 上拍摄
云原生改变了软件行业的动态,以及人们对部署和操作软件应用程序的看法。
根据 维基百科 ,云原生计算是软件开发中的一种方法,它利用云计算“在现代的动态环境中构建和运行可扩展的应用程序,如公共云、私有云和混合云”。
简而言之,它允许您基于云计算交付模型构建和运行应用程序。
让我们来了解一下什么是云计算——“它指的是云存储等资源的按需可用性,并在没有直接主动用户管理干预的情况下计算能力”
请注意,类似云的交付不限于公共环境,它同样适用于私有云。它本质上关注的是如何创建和部署应用程序,而不是在哪里。
根据云原生计算基金会(CNCF),云原生计算使用开源软件堆栈来:
- 集装箱化
- 动态编排
- 面向微服务
了解关键组件和术语:
在我们进一步讨论之前,有许多术语需要进一步讨论和澄清,所以让我们先了解它们:
- DevOps: 它是软件开发(Dev)和 It 运营(Ops)的结合。它是一种跨职能的文化,促进高质量软件的更快交付。
- **容器:**它将执行应用程序所需的一切,例如虚拟机、应用服务器和应用程序本身,打包到一个可执行的包中。然后,容器在虚拟环境中运行,因为应用程序变得独立于其环境,所以具有可移植性。它可以被认为是部署单个微服务的计算介质。
容器具有水平伸缩的优势,可以根据用户需求添加或删除容器的多个实例。
随之而来的是下一个关注点,即如何管理当前的系统负载并决定是启动额外的节点还是关闭已经运行的节点。这让我们想到了编排的概念。
- **编排:**它监控系统并自动启动/关闭容器,以便管理活动应用程序实例之间的负载。
- **微服务:**顾名思义,微服务是一种小型的、很大程度上解耦的服务。每个微服务都提供了一个小的应用程序,它具有定义明确的边界和 API,易于由一个小团队操作。许多这样的微服务一起构成了系统的整体功能。
将一个大型应用程序分解成多个较小的应用程序,可以加快实现速度,并易于适应新的需求。
高效的扩展是它的另一个好处:如果单个微服务接收到更多的负载,在其他服务继续无缝运行的情况下,扩展微服务系统被证明是非常划算的。这省去了启动完整单片系统的额外实例。
但是如果构建微服务允许如此高效地使用云资源,那么挑战在哪里?微服务确实允许可扩展性,但增加了系统级的复杂性。这种增加的复杂性可以降低吗?在一定程度上,是的,可以通过使微服务尽可能相互独立或者通过在依赖服务之间提供有效的通信来减少这种情况。
- **连续交付:**它使组织能够自动地将增量软件变更推向生产。
云原生原理:
- 基于微服务构建应用
- 将微服务打包成容器
- 使用 DevOps 进行基础架构部署
- 向最终客户持续交付应用程序
云原生模式的优势:
- DevOps 团队由开发人员和运营团队组成,能够快速交付软件,即缩短交付周期。
- 手动完成基础架构扩展时,人为错误的范围更大(由于手动创建和管理服务器),这在云原生产品中得以消除,因为基础架构扩展是自动进行的
- 云原生抽象出底层基础设施的依赖性,让团队只关注软件。而应用程序与传统应用程序系统中的底层操作系统、硬件、存储和支持服务有着密切的依赖关系。
- 持续交付促进了对客户需求的更快响应,因为单个功能/更新一旦准备好就会发布。
- 微服务允许开发人员进行快速更新和扩展,从而实现敏捷开发和部署。
- 由于业务需求和 IT 团队之间的一致性更好,云原生支持更快的代码交付
- 基于云模型的部署允许组织构建可以在任何云(公共云或私有云)上顺利运行的应用程序。
网飞、优步和微信等公司已经采用了云模式,能够更快地部署服务。
上面提到的是基于云的模式对组织业务影响的几个例子。您可以查看此链接,了解更多关于采用云原生模式的一些公司的迁移目标、策略和结果。
总之,转向云原生是满足用户不断增长的需求的解决方案,不会出现停机和错误。但是,组织在以下方面有自己的顾虑:正确的云迁移方法是什么,如何在内部基础架构和公共云提供商之间做出决定,如何构建可扩展的结构,这需要在开始云之旅之前进行适当的研究和时间投入。
结尾备注:
我希望这篇文章对您有所帮助,在这篇文章中,我们讨论了什么是基于云的模型,以及组织如何跟上这一领域的发展以获得竞争优势。很高兴知道你的建议,或者如果你想让我解释任何具体领域或细节,这些都是受欢迎的。
参考文献:
- https://stackify.com/cloud-native/
- https://tanzu.vmware.com/cloud-native
决策树和预测分析简介
原文:https://towardsdatascience.com/an-introduction-to-decision-trees-and-predictive-analytics-92924a8a77e7?source=collection_archive---------6-----------------------
你如何确保产品发布会成功?决策树是使用数据科学解决这类业务问题的绝佳入门
图片由 Pixabay 上的 fietzfotos 拍摄
决策树表示一系列连接的测试,这些测试越来越向下分支,直到特定的路径匹配一个类或标签。它们有点像抛硬币的流动图表,if/else 语句,或者当满足时导致最终结果的条件。决策树对于机器学习中的分类问题非常有用,因为它允许数据科学家选择特定的参数来定义他们的分类器。因此,无论您面对的是降价还是数据的目标 KPI 值,您都有能力在多个级别对数据进行排序,并创建准确的预测模型。
现在有很多很多的应用程序利用决策树,但是在这篇文章中,我将着重于使用决策树来做出商业决策。这涉及到衡量客户对新产品的兴趣,我们将使用来自在线咖啡豆经销商的数据!
问题:
图片由内森·杜姆劳在 Unsplash 上拍摄
您的客户 RR Diner Coffee 是一家总部位于美国的零售商,在世界各地销售特种咖啡豆。他们希望增加一个精选品牌的新产品。这种新的增加将大大提高销售额,改善他们的声誉,但他们需要确保产品将实际销售。为了添加该产品,您需要向您的客户证明至少有 70%的客户可能会购买它。幸运的是,您的营销团队发出了一份调查,您已经获得了大量数据。让我们来看看。
探索数据
作者图片
作者图片
在继续之前,我们肯定需要清理我们的数据,但是仅仅通过查看数据,我们就可以知道如何处理它。关于这些数据,非常方便的是,由于“决策”列,我们已经知道一些客户是否会购买这种新产品,因为我们不必对我们的训练数据进行任何猜测,我们可以建立一个监督模型。在确定哪类客户会说“是”时,任何其他特征都可能是有用的,但我们稍后会弄清楚。
为了清理这些数据,我所做的就是:
- 更改一些列名,使其更容易理解
- 确保所有的性别回答都是相同的格式,比如把“男性”、“M”、“M”和“男性”都变成“男性”,反之亦然。
- 将决策列中的 1.0s 和 0.0s 分别更改为“是”和“否”,暂时保留空数据。
现在我们知道了我们的数据是什么样的,我们可以采取什么方法,让我们继续为我们的模型进行训练/测试分割
训练/测试分割
因为只有 702 个条目,所以我想保存尽可能多的数据,即使是那些具有空决策的数据。对于这个训练/测试分割,我创建了一个决策值不为空的数据子集,并将其称为 NOPrediction。
就像这样,我们有了训练/测试分割,可以用来评估我们的模型。现在让我们开始真正的表演:决策树模型!
车型
就像每一种机器学习方法一样,在选择模型时,有大量不同的方法可供选择。我只是给你看一些我在这个项目中尝试过的,但是你应该多读一些,找出哪些最适合你!Scikit-learn 的网站有大量优秀的文档:点击这里查看。
熵模型
你可能还记得高中物理,熵测量系统中的无序或随机。当使用决策树时,你会遇到很多随机性,但作为一名数据科学家,你的工作就是用最小的熵来建立预测模型。基本熵模型试图从最大熵的树的顶部开始,向下到最小熵的根部,这就是如何准确地对数据进行分类。这在视觉上更容易解释,所以让我告诉你我的意思。
输出应该如下所示:
作者图片
如果你从顶部开始,你可以看到,随着你的工作沿着模型向下,你会做出正确和错误的决定。随着这些决策分支,熵变得越来越低,我们能够创建定义清晰的数据集群。
在这种情况下,我们从未定义最大深度或给模型任何其他参数,因此这个版本是最准确的,平衡精度得分为 98.7%。不过,有时为了时间和计算机处理能力的限制,牺牲一些准确性也是好的。就像在这个例子中,我们将最大深度设置为 3:
作者图片
该模型需要做出的决策更少,并且产生了 86.5%的平衡准确度分数。这仍然是一个非常可靠的预测模型,只有没有最大深度的模型的一半决策。你现在大概能明白我在说什么了。如果你在寻找最精确的模型,时间和计算能力不是问题:没有必要设置最大深度。但是,如果你时间紧迫或者资源有限:设置一个最大深度将会节省你很多时间,并且给你带来非常相似的结果!
基尼杂质模型
就像熵模型一样,这种决策树模型在对数据进行分类时寻求最小化任何随机性。然而,与前两个模型不同,基尼杂质模型不使用对数函数,随着时间的推移,它可以为您节省大量计算能力。这两者的区别如下:
图片来自 scikit-learn 文档
设置与熵模型非常相似,让我们看看它是如何执行的。
作者图片
这样,我们得到了 98.1%的平衡准确度,只是比第一个熵模型稍差一些。就像熵模型一样,你也可以设置基尼决策树的最大深度。
作者图片
这个模型惊人地拥有 96.9%的平衡精度!与原始基尼模型相比,只有 1.2%的差异,决策数量要少得多。
每个模型都有自己的优点和缺点,除了这四个例子之外,还有其他的可以探索。你会选哪一个?在我看来,最大深度为 3 的基尼模型为我们提供了良好性能和高度准确结果的最佳平衡。肯定存在这样的情况,其中最高的准确度或最少的总决策是优选的。作为一名数据科学家,你可以选择哪个对你的项目更重要!
做预测
现在我们已经创建了模型,让我们使用它们吧!为了证明 RR Diner 的咖啡会引起至少 70%顾客的兴趣,我们必须向预测模型中输入一些新数据。还记得在我们的数据集中,实际上只有 474/702 人做决定吗?如果我们使用其他 228 个条目进行预测呢?我们必须建立一个新的数据框架,添加一些虚拟变量,然后将它们输入到模型中。看起来是这样的:
这将输出 45NO 和 183 YES 的数组。如果我们使用 value_counts()原始数据集的“决策”列,我们会得到 151 个否和 323 个是。现在我们可以把它们加在一起:
- 183 是+ 323 是= 506 是
- 506 个是/ 702 个客户总数= 0.72
这意味着,根据我们进行的调查和我们的模型预测,72%的客户会有兴趣购买 RR Diner 咖啡!在这种情况下,我们已经满足了供应商设定的标准,应该能够将他们的产品添加到我们的业务中。如果你真的想打动他们,你甚至可以补充说,我们的预测模型准确率超过 96%。谁知道呢,获得这样一笔交易可能会给你带来奖金,甚至升职;数据科学是商业世界中极其宝贵的资产。
结论
我希望通过这个例子,你已经很好地了解了决策树,以及如何使用它们来帮助你或你的企业做出准确的预测!关于决策树,还有很多很多有趣的事情我没有提到,比如随机森林模型或者在衡量整体准确性时使用精度/召回分数。我很想在未来写更多关于它们的文章,但是现在,有很多很好的资源可以让你了解更多关于预测分析的知识。查看 scikit-learn 的文档进行真正的深度探索,或者观看来自 Edureka 的这个信息丰富的视频!如果你想了解更多!
一如既往,非常感谢您阅读这篇文章!如果你喜欢我的内容,请考虑在 medium 上关注我,因为我希望在未来发布更多数据科学内容。希望你有一个伟大的一天!:)
跟我来!——https://bench-5.medium.com/
数据源-https://github . com/akthammomani/Decision-Tree-Based-Binary-Classifiers/Tree/main/Tree _ Based _ Classifier _ RR _ Diner _ Coffee/raw _ data
实体解析简介——需求与挑战
原文:https://towardsdatascience.com/an-introduction-to-entity-resolution-needs-and-challenges-97fba052dde5?source=collection_archive---------2-----------------------
因为好的分析和数据科学始于正确的数据
介绍
实体解析是一种技术,用于识别单个数据源或多个数据源中引用同一现实实体的数据记录,并将这些记录链接在一起。在实体解析中,几乎相同但可能不完全相同的字符串在没有唯一标识符的情况下进行匹配。
真实世界的数据远非完美。各种组织经常面临各种人以自己的方式从不同的来源多次输入的大量客户数据。
这里有两种不同的客户规格。
在上述记录中,姓名或者分为名、中、姓、首字母,或者是组合在一起。名字有时与称呼混在一起,头衔不同,中间名不见了,电话号码写得不同,地址被拆分和组合,一个城市的新旧名字被记录为同一地址,使用缩写,标点符号不同,一些字段被省略。
当您阅读这些记录时,您会理解这两个数据源描述的是同一个人。但是,只知道相等或不相等的计算机会将这些数据值标记为相同吗?
为了理解数据,计算机需要识别引用同一个现实世界实体*的记录。这个识别谁是谁的过程——不考虑无数的表示——是实体解析或记录匹配。实体解析也称为模糊匹配、合并清除和数据匹配。当在人的上下文中使用时,实体解析被称为身份解析。当涉及单个数据源并且目的是删除重复条目时,模糊匹配被称为记录重复数据删除或重复数据删除。
公司服务提供商可以使用实体解析来解析组织名称,尽管存在不同的表示、拼写错误、缩写和印刷错误。
一家保险公司需要协调拼写差异、缩写、同义词和不同的词序来关联其数据。
金融和银行公司要求匹配不同的数字和百分比表示。
前导和尾随空格、连字符、大小写差异和点可以使任何两个地址看起来不同,而实际上它们并不不同。
此外,国际客户数据库可能包含不同语言的数据。总而言之,由于数据的非标准化,在同一实体的不同记录中,每个属性都可能以多种方式变化,数据库中充满了这些变化。
公司使用实体解析来连接不同的数据源以清理数据,查看多个数据仓库之间不明显的关系,并获得数据的统一视图。在这个过程中,他们可能通过组合来自各种来源的数据来构建主数据管理系统(MDM ),从而开发出单一的真实来源。
企业实体解析
我们都知道数据质量的 1-10-100 规则,而 Gartner 将规则描述为:在记录输入时验证一条记录需要 1 美元,清理和删除重复数据需要 10 美元,如果什么都不做,则需要 100 美元,因为错误的后果会反复出现。
实体解析是至关重要的,因为它匹配不相同的记录,尽管所有的数据不一致,而不需要不断制定规则。通过使用模糊匹配连接数据库,我们可以清理数据和分析信息。我们可以在统一的数据上绘制模式,得出结论,并看到更大的画面。
这种更干净、更精简、关联度更高的数据对于高效运营和防止欺诈也至关重要。最重要的是,我们以更低的运营成本获得了单一客户视图。
让我们来看一些不同的场景,在这些场景中,模糊数据匹配使组织能够提供个性化的客户体验,高效地推动营销工作,提高销售额,并保持合规性。
行业使用案例
生命科学和医疗保健
《金融时报》援引麦肯锡全球研究所的一份报告称,通过更好地整合和分析从临床试验到医疗保险交易到智能跑鞋的所有数据,美国医疗体系每年可以节省 3000 亿美元——每个美国人 1000 美元。
生命科学和医疗保健行业需要关于医疗保健组织和提供商、患者及其互动和治疗、医院、医生、实验室和产品的最新和最相关的数据,以便不仅清楚地了解这些相互依赖的利益相关方,而且在适当的时间在他们喜欢的平台上向他们提供统一和个性化的信息。
例如,一家制药公司可以使用模糊匹配来汇总从其所有地点配送的药物数据,以了解一年中每种药物的处方量和销售量。由于数据输入不同的系统,药品名称会有差异,模糊匹配将能够协调名称。该公司还可以使用其所有购买者(医院和诊所)的单一视图来查看谁需要新的供应品以及谁欠他们钱。
制药公司还必须整合全球实验室科学家的生物和医学研究数据,以进行研究和制造新药。模糊匹配在这里很方便,可以连接和匹配包含数百万行的数千个电子表格中的化合物和反应,所有这些电子表格都有不同的列名、格式和不一致性(如甘精胰岛素和甘精胰岛素)。
除了一般的研究和分析之外,医疗保健系统还需要对每位患者的医疗旅程有一个全面的了解(也许是一个 MDM 平台)。他们利用患者的这种实时 360°视图来提供个性化的智能医疗建议,改善患者体验以建立强大的客户关系,并创造更好的产品。干净和匹配的患者数据也可用于创建健康指标。实体解析支持整合来自各种数据源的患者数据,匹配来自医院和私人诊所、保险提供商和理赔、个人档案以及来自互联网和社交平台的数据,以创建每个患者的独特档案。
例如,医疗保健行业可以分析汇编的数据,以了解患者过去是否有任何过敏反应,或者上次适合患者的确切布洛芬混合物。使用这些数据,医疗保健提供者可以计算出统计数据,如定期心脏健康检查期间印度 55-60 岁年龄组男性的平均心率,并得出结论。
制药公司还在推出任何新产品之前,使用关联数据进行市场研究,进行竞争和定价分析。如果他们对市场没有一个统一的看法,产品发布要么失败,要么推迟。
生命科学和健康行业有着复杂的法规遵从性要求。如果一家公司未能遵守各种健康责任法案或消费者数据隐私法规中的任何一项,它可能会受到严厉处罚或被关闭。
以前,公司要花费前所未有的大量时间来汇总报告以提交给监管机构。但是,敏捷记录匹配可以连接和协调生命科学数据的各种大量流入,如来自医院、内部记录、第三方来源、离线媒体和社交媒体的数据,以确保永远符合法规要求。
保险
保险公司经常与碎片化的数据孤岛作斗争,因为不同的保单(汽车、健康、家庭等)维护着他们自己的个人记录。因此,它们无法协调客户的人口统计数据、偏好、过去的保险单和信用评级。
在缺乏对客户的整体看法的情况下,保险业缺乏对她理想的保险范围、风险暴露和其他分析的理解。个性化营销和交叉销售的机会也被错过了。
例如,如果保险提供商不知道申请健康保险的感兴趣的客户是该公司现有保险持有人的丈夫,他们将无法提供组合方案,并将在客户服务和/或这些客户的最佳回报上妥协。投保者可能不知道他们的选择,但公司应该能够告诉他们。在这种情况下,将所有内部数据与可能的潜在客户进行集成和匹配,可以提供特定地理位置的大量客户的统一视图。
实体解决方案是保险业以客户为中心的关键。如果保险管理人员对他们的潜在客户有统一的看法,他们可以为他们提供高度个性化的保险计划,从而轻松击败竞争对手。
欺诈检测是保险行业中模糊记录匹配的最大用例之一。如果保险公司不能识别出那些在过去犯有保险欺诈的人,而这些人现在申请了细节略有变化的高额保险计划,他们可能会遭受巨大的损失。
索赔管理、策略管理和法规遵从性也依赖于策略和法规数据的整合。
制造业
借助模糊数据匹配,制造商可以分析他们在大范围内的支出,优化供应商和原材料采购。这种分析将允许公司通过缩小支出差距、聘用最便宜的供应商并从他们那里采购来降低成本。库存分析有助于消除库存和配送中的盲点。
例如,如果一个制造单位已经有 100,000 个单位的过去库存,那么他们不需要生产更多的单位,直到收到新的订单。但是,如果他们来自中国的零部件供应链由于政治动荡而中断,那么他们需要迅速查看整合的供应商数据库,以确定下一个最便宜的供应商,并立即下订单。
对客户的统一看法将允许制造企业提供一致的客户体验,并交叉销售和追加销售他们的产品。交叉连接来自研究、过去的设计项目、竞争、制造质量、故障和维护报告的数据也可以为卓越的质量铺平道路。
实体解析还允许合并产品目录和价目表。多个条目,因此,同一产品的不同定价会在任何公司引起混乱。协调定价对于向每位买家展示一致和正确的产品信息至关重要。
金融服务
由于金融服务的高风险性,如果客户经理的服务质量差或态度不认真,金融服务可能会失去很多客户。不连续和不干净的数据也可能使企业面临不必要的风险。
支持统一投资组合准备和审计的单一客户数据源对于每个金融公司的顺利运营和成功至关重要。例如,不同关系经理为同一客户输入的不同客户数据(姓名、电话号码、地址等的拼写错误)必须使用实体解析进行汇总和清理,以获得客户的整体视图。
只有统一的客户观才能使金融公司提供良好的客户服务,这将导致更高的客户保留率,从而带来更高的投资组合价值。如果你和一家投资银行有值得信赖的关系,你会希望他们将你每年的储蓄持续投资,而不是寻找新的金融服务。
关联客户数据对于建立个人信用评级和财务稳定性也至关重要。这些评级可用于在发放贷款、移交信贷和检测欺诈活动方面做出明智的决策。模糊数据匹配用于将 KYC 数据与客户投资联系起来。KYC 信息连同信用评级可以证明是非常有助于检测和避免债务欺诈。
麦肯锡关于反洗钱的一篇文章指出“在美国,主要银行的反洗钱(AML)合规人员在过去五年左右的时间里增加了十倍。”文章强调,模糊逻辑(众多工具之一)可以让银行验证更多的客户身份,并映射特定客户与高风险个人和法律实体之间的联系。
能源、石油和采矿
全球能源、采矿和石油公司需要清理、分类、统一和理解来自各种来源、地理位置和工程角度的不同数据,以降低运营成本并平稳运营。这些公司需要对零件和材料进行分类,了解他们把钱花在哪里,并发现更好更便宜的机械供应商。
能源组织需要统一的数据,这不仅是为了降低成本,也是为了保持合规性并高效准确地报告。模糊匹配帮助这些公司整合他们的数据,并为他们提供一个强大的数据管理平台,可以提供上述所有功能。
随着用例列表变得越来越长,模糊记录匹配有着无尽的好处这一认识令人欣喜。
我们没有将两个记录理解为一个实体,这可能会破坏主数据。关系和模式会被错过。聚合和计算没有任何意义。关键信息将会被搁置。关键的决定会失控。生活、国家、组织和社区的方方面面都可能受到威胁。
在所有情况下,我们可以通过链接记录来了解情况,并可以跟踪从人到疾病到新计划的任何事情。整合不同行业的数据仓库具有指数级的价值。
功能用例
销售和营销
向客户提供的建议和有效的营销方案无法基于不同的数据孤岛进行预测。
如果在整合中没有查看买家数据,大多数营销工作都会白费,因为外联计划和客户互动不会个性化,购物者不会购买。在缺乏有用的客户体验的情况下,公司会因为糟糕的客户服务而被抛弃,从而输给竞争对手。
通常,由于客户姓名的不同拼写或电话号码的键入错误,客户在两个不同的商店数据库中被多次列出不同的购买记录。来自该公司的重复电子邮件只会错失销售机会,或者更糟的是,可能会导致客户将该公司的营销电子邮件标记为垃圾邮件。
CRM 中的客户重复数据删除是实体解析非常有效的另一个领域。由于不同销售人员的不同条目,或者从多个渠道获得的潜在客户名单,客户关系管理系统通常具有同一客户的多个条目。在外展过程中,多次联系同一个销售线索是一种浪费,因为这会导致糟糕的品牌体验和接受者的不适。宝贵的销售周期也被浪费了,因为不止一个销售人员在联系同一个人。通过记录匹配进行的客户重复数据删除确实有助于销售和营销的卓越运营。
在另一个场景中,汽车供应商需要通过网站和移动应用程序来协调所有线索,以消除重复的线索,然后专注于紧凑列表。
例如,如果一位顾客退回一件产品,但第二天又买了一件更大的,公司会发送以下信息:
方案一:你退了产品,买了一个更大的。请放心,我们会尽快把它寄给你。
选项 2:您刚刚退回了一件产品。再来这里购物。
信息 2 对客户来说是多余的。在这种情况下,退货详情必须首先与客户档案进行核对。
在所有场景中,在进行任何营销之前,必须通过实体解析来统一客户数据。
通过模糊匹配和统一来自不同内部和外部数据仓库(如网上商店、移动应用程序、线下商店、忠诚度计划和个人资料)的客户数据,企业可以创建一个 360 度的客户视图,并通过为每个客户提供独特的个性化体验,将营销工作提升到一个新的水平。
360 度客户视角也是了解交叉销售和追加销售产品和服务机会的非常有效的工具。现在,以低得多的客户获取成本增加客户终身价值将成为可能。
如果顾客在商店买了一件大衣,这些离线信息可以用来给她发送冬季服装的折扣代码。不管接触点是什么,对客户来说都是同一个品牌。
这种客户统一可以通过更新和匹配来自客户独特旅程之上的所有来源的实时客户交互数据来实现。
所有数据驱动和面向客户的企业,如酒店、医疗服务提供商、保险公司、零售品牌、汽车公司,都将从这种个性化营销方法中受益匪浅。根据麦肯锡的说法,以客户为中心的思维模式的根本改变,以及运营和 IT 方面的改进,可以使客户满意度提高 20%到 30%。
通过将各种营销计划和最终的销售联系起来,公司可以了解带来最高投资回报率的广告渠道和形式。买家行为也可以用来修改营销活动和预算。
供应链
准确、互联的供应商数据对于保持敏捷的供应链至关重要。在缺乏供应商统一的情况下,供应链的竞争力将会下降,大量的资金将会花在应对供应和库存问题上。
匹配供应商并建立统一的供应商档案并不容易。除了体积复杂之外,描述中的变化可能是巨大的,名称可能会被拼错或以不同的方式表示。每个季度都会有不同描述的新采购。
实体解析通过整合分布在各种业务单位、地区、地理位置以及零件和材料类别的数据仓库中的供应商数据来维护一个强健的供应链。
供应商匹配还将使公司能够了解跨部门的定价,轻松找到给定产品的最佳供应商,协商价格,更快地加入新供应商,消除重复供应商,并管理与供应商地理位置相关的风险。
假设一家 CPG 公司想要比较两家类似产品的供应商,以确定谁以更低的价格销售了大部分产品。两家厂商会用不同的方式表达产品名称。一个卖主可能称这种产品为薄纸,另一个卖主可能称它为纸手帕、薄纸或卫生纸。
由于产品名称不会完全匹配,实体解析用于协调产品,比较它们的价格,并决定哪个供应商卖得更便宜。实体解决方案还将阻止再次注册的欺诈性卖家,他们的详细信息略有变化。
挑战
比较来自不提供任何唯一标识符的不同数据源的充满非标准和不一致数据的大数据记录是一个复杂的问题。
计算机可以评估等式并进行数学比较,但无法自行理解模糊匹配。尽管人们可能会把记录中的两个人——卡玛拉·哈里斯夫人和哈里斯·卡玛拉——称为同一个名字,但一个编程系统却不知道该怎么办。
不同的用户、技术系统、地理位置、地区、年份和组织可以用不同的格式表示相同的数据。记录在打字错误、称呼、空格、缩写、语言、拼写、完成、省略、语音、顺序、后缀、前缀等方面有所不同(如上所示)。数据输入中的错误会导致一个实体的多个记录,即使是在一个源中。
考虑到表现形式的变化,相同数据的排列和组合的数量是空前的。根据各个实体的类型,名称匹配、地址匹配、位置匹配、供应商匹配、产品匹配都具有独特的匹配标准。
数据管理系统应该理解所有标准,并匹配各种记录来代表一个客户或产品或销售商或供应商。姓名、地址、位置、零件、产品、电话号码、日期匹配对于协调来自不同仓库的数据至关重要。
我们谈论的是大量的数据。庞大的数据量加上丰富的格式使得匹配成为一项艰巨的任务。微调任何算法以适应每种实体类型、记录类型和值将是一项艰巨的工作。
传统的数据管理方法无法在实际的时间范围内处理这些不同的数据。
为了理解数据匹配解决方案的复杂性,让我们更仔细地分析基于规则的匹配。为了匹配同一实体的任意两个记录,将定义各种基于字符串的比较规则。每个记录将与所有这些规则上的其他记录一起运行,以推断这两个记录是否相同。
这里只是这种基于规则的匹配的一些限制。
完全
考虑到一个属性的单个数据值的不可预测的变化数量,为一个字段定义匹配规则并不容易,需要对数据配置文件有深刻的理解。你能涵盖阿尔茨海默氏症的所有拼写或所有不同的细长纤维的描述吗?例如,在我们写这篇文章并研究汽车行业的模糊匹配之前,我们不知道底盘是指车架。那就忘了同义词相等规则吧。
设置匹配规则是一个麻烦、昂贵且冗长的过程。
复杂性
除了定义规则之外,组合记录的不同属性的匹配规则将更具挑战性。如果街道 1 和街道 2 看起来相似,但电话号码不匹配或不相交,记录应该相同吗?
维护
必须定义大量的规则来涵盖各种各样的数据表示。但规则仍会被遗漏,角落案件会不了了之。
更新规则并使其适应不断变化的数据也很棘手。随着数据源数量的增加,格式和数据类型随着数据量的增长而增长,定义规则变得越来越复杂。
无论您创建多少规则,一组固定的规则都无法处理所有前所未有的数据变化,这使得基于规则的匹配非常难以实施和维护,并且成本高昂。
规模
由于大多数实体缺少可以比较的唯一键,所以每条记录都以强力方式与其他记录匹配。对于 n 个记录,存在 n*(n-1)/2 个唯一对。为了建立平等,每一个规则将在每一对上运行。
当记录数增加 10 倍时,比较次数增加 100 倍。因此,随着记录数量的增长,比较的次数会呈指数增长。因此,即使我们假设最快的比较技术,比较的时间也是指数级的。
基于规则的数据匹配是一种计算上具有挑战性且不可扩展的解决方案。运行这些规则的时间也将立即呈指数增长。
精确
即使在推导出匹配逻辑之后,区分匹配和不匹配的最佳匹配阈值是什么?由于规则的性质,许多误报和漏报肯定会出现在结果中。
回忆
你在匹配标准中犯了一个错误,整个数据匹配将被连根拔起。许多真正的积极因素可能会被遗漏。理解属性和记录为什么可以说是相同的是一个游戏改变者。
其他挑战
除了基于规则的集成解决方案的复杂性之外,这里还有更多适用于所有数据匹配解决方案的复杂性,这说明了为什么匹配是最难解决的问题之一,
变量数据存储器
数据将保存在各种数据存储中,如关系数据库、NoSQL 数据存储、云存储和本地文件系统。不同的数据库意味着数据会以不同的格式出现——文本、专有、JSON、XML、CSV、Parquet、Avro 等等。
数据源中的模式变化
实体表示通常因系统而异。属性的数量可以不同,它们的表示也可以有很大的不同。一个数据系统中的地址属性可以在另一个数据系统中分为地址 1 和地址 2。或者,即使是相同的属性,列的命名也可能不同。例如,可以写街道 1 和街道 2,而不是地址 1 和地址 2。价格可以写成 MRP 或销售价格。对齐各种模式是一项具有挑战性的任务。
*实体定义:正如我们所知,实体是一种独特的东西——一个人、一家企业、一种产品、一个供应商、一种药物、一个组织。每个实体都有其描述属性,如名称、地址、日期、颜色、形状、价格、年龄、网站、品牌、型号、容量等。
实体解析是匹配不一致数据的一种很好的技术,但它也带来了挑战。我们最近开源了一个基于 Spark 的工具 Zingg ,通过使用机器学习来解决实体解析。如果您需要帮助来协调您组织的数据,请务必查看。
数据科学信息论导论
原文:https://towardsdatascience.com/an-introduction-to-information-theory-for-data-science-4fcbb4d40878?source=collection_archive---------11-----------------------
思想和理论,机器学习
定义一般相关性度量的第一步
本文旨在信息论框架内简要介绍信息量的概念,并概述这一概念在数据分析领域的可能用途。从这些简单的元素中,我想到了本文https://medium.com/analytics-vidhya/how-to-measure-the-non-linear-correlation-between-multiple-variables-804d896760b8中提出的多元非线性相关性度量。
代表信息可变性
信息量代表描述任何情况所需的最少字数
信息论在很大程度上是基于克劳德·香农在 20 世纪 40 年代末发表的著作(参见文章一种通信的数学理论*,发表于 1948 年的贝尔系统技术杂志,以及次年发表的 《通信的数学理论 )。*
它的主要目标是提供工具来改善电信系统中的信号传输。这意味着对信息的含义有一个特殊的定义,尽管如此,在数据分析等领域,这个定义还是很丰富的,乍看之下,它与电信系统中的信号编码技术没有什么关系:一条消息中包含的信息被定义为编写该消息所需的最少比特数。
哈夫曼树的实用方法
为了更清楚地理解这个定义,让我们假设我想用特定的编码来写单词“analyse ”,以便将每个字母翻译成 0 和 1 的序列。
我可以选择任何编码,比如这个:
*╔════════╦══════════╗
║ Letter ║ Encoding ║
╠════════╬══════════╣
║ a ║ 111 ║
║ n ║ 110 ║
║ l ║ 101 ║
║ y ║ 100 ║
║ s ║ 01 ║
║ e ║ 00 ║
╚════════╩══════════╝*
因此,单词“分析”将被写成:111–110–111–101–100–01–00(我写破折号只是为了简化阅读,当计算机编写或解密消息时,它们不存在)。因此,这个词是用 19 位编码的:“分析”这个词包含的信息量最多等于 19。
然而,字母“a”的出现频率高于其他字母,这意味着如果该字母例如由 01 编码,而字母“s”由 111 编码,那么该单词的编码将只需要 18 位。这使得我们可以确认“分析”一词所包含的信息量最多等于 18。
为了定义简约编码,这意味着用最少的比特数对文本进行编码,可以使用霍夫曼码,基于这样的想法,即最好用短的二进制数对频繁符号进行编码,并且仅对最不频繁的符号使用最长的二进制数。
霍夫曼码可以用霍夫曼树来定义(这里我不详细介绍)。对于单词“分析”,可能的树是:
单词“分析”的霍夫曼树(图片由作者提供)
该树提供了以下代码:
*╔════════╦══════════╗
║ Letter ║ Encoding ║
╠════════╬══════════╣
║ a ║ 00 ║
║ n ║ 01 ║
║ l ║ 100 ║
║ y ║ 101 ║
║ s ║ 110 ║
║ e ║ 111 ║
╚════════╩══════════╝*
我们最终得到了“分析”这个词的二进制编码:00–01–00–100–101–110–111。
单词“分析”再次由 18 位编码。这个位数是对单词“分析”进行编码所需的最少位数吗?一般来说,给定任何消息,有人能容易地确定消息中包含的信息量吗?克劳德·香农给出了这些问题的答案。
香农熵的理论方法
如果我们注意到 P(1)字母“a”在单词“analyse”中出现的频率,P(2)字母“n”出现的频率,等等。,那么 Claude Shannon 告诉我们,对单词“analyse”的每个字母进行编码平均所需的最少位数是:
熵的定义(作者图片)
他把这个量命名为“熵”。对于“分析”这个词,我们得到数量 2.5。
由于这代表了对单词“analyse”的每个字母进行编码所绝对需要的平均位数,所以这个数量必须乘以单词中的字母数,最终得到 17.5。
因此,对该字进行编码所需的最小位数是 18 位,因为只能使用整数位,而数字 17.5 被解释为包含在“分析”字中的信息量。
从现在开始,我将把重点放在熵上,也就是说每个字母编码所需的平均比特数。事实上,这赋予了消息(或数据)内在的“可变性”,而不管其长度(或数据量)。
“可变性”的概念对于研究变量之间的相关性是至关重要的,因为研究相关性是关于研究变量如何相对于彼此变化。例如,在气象学中,如果一个人注意到在地球的一部分,当温度上升时降水量增加,那么这两个变量是相关的,不管记录温度和降水量的天数是多少。
为什么不考虑方差而不是检查香农的熵呢?
因此,熵表征了集合的“可变性”:元素的集合越多样化,这个集合的熵就变得越重要。然而,在统计学领域,集合的可变性可以由集合中元素之间的方差来表示。为什么我们不满足于方差,而使用熵呢?
方差要求对数据进行推测
方差虽然众所周知并且非常有用,但它需要对所研究的数据做出许多假设。
首先,方差只能对数值型数据进行计算。
另一方面,方差的确定是基于均值的估计:
Var(X) = E[(X - E[X]) ]
当数据是数字的并且有足够数量时,这并不构成问题:通常的均值和方差估计量给出非常精确的结果。
然而,最终目的不是确定不同变量的方差,而是确定几个变量之间的相关性。因此,我们必须计算一个变量的方差,假设另一个是已知的:
Var(Y|X) = E[(Y|X - E[Y|X]) ]
在这种情况下,如果我不假设变量 X 和 Y 之间的关系,方差的任何估计都是可能的。事实上,如果我拒绝做出任何假设,对我来说,考虑一个从可用数据中过拟合的足够程度的多项式模型就足够了,因此当 X 的实现已知时,断言 Y 的方差为零。
“完美”的模型总是可以找到的(图片由作者提供)
所以,要计算两个变量之间的皮尔逊相关,我们假设 X 和 Y 的关系是线性的,除了测量误差;在所有可能的方差中,我们选择最小方差。由于这个原因,皮尔逊相关是线性相关,并且通过普通最小二乘法与线性回归有内在联系,该方法包括最小化:
Var(Y|X) = E[(Y|X - E[Y|X]) ]
假设:
E[Y|X = x] = αX+β
熵不需要假设,以数据离散化为代价
与方差不同,熵不能从数值数据中计算,而是需要分类数据。
一个集合中的类别越多,这些类别被发现的可能性越大,熵就越大。因此,熵度量的是可变性,即数据集中数据的“内在无序”,而不对数据应该如何组织做出任何假设。
因此,熵使得克服关于数据之间关系的假设成为可能,特别是线性假设,但是以离散化信息为代价。在考虑数字数据时,试图定义一个不是基于任何假设的相关性在任何情况下都是注定要失败的。事实上,如果我拒绝对变量之间的关系做出任何假设,这意味着我没有限制潜在模型的复杂性。因此,我总是能够找到一个模型,将完美地插值数据,这将允许我说,两个变量之间的相关性总是完美的。这当然是过度拟合的情况:因此,必须通过表达假设(如线性假设)或通过离散化数据来防止过度拟合,从而限制基础模型的复杂性。
最后,应该注意,任何多样性指数都可以替代熵,因为它们具有对于非线性相关性的定义至关重要的相同性质。
量化两个变量之间的互信息
第一部分的考虑,尤其是方差和熵之间的比较,值得更详细地解释。从今以后,我认为我们正在研究两个变量 X 和 y 之间的关系。我们如何测量这两个变量之间的相互信息,或者说得不那么细致,一个可以在多大程度上预测另一个?
为了避免皮尔逊线性相关性和非线性相关性之间的任何混淆,我将讨论线性情况下的相关性,以及非线性情况下两个变量之间的互信息。
然而,在我们研究互信息的理论方面之前,让我们看看熵如何帮助我们比较不同的变量。
信息论和集合论
香农的信息测度和集合论之间存在联系,集合论以一种非常实用的方式允许我们使用集合论进行推理,并利用维恩图来直观地表示公式。
理论辩护
我在这里不提出信息论和集合论之间联系的理论依据。有兴趣的读者可以参考 Raymond T. Weung 的《信息论初级教程 第六章 。
公式的可视化
通过考察信息论和集合论之间的联系,我们可以得出结论:用文氏图直观地表示信息论公式是可能的。在这样的图中,每个圆盘代表一个变量的“可变性”,而“可变性”的度量就是香农熵。因此,我使圆盘 X 的面积等于相关的熵 H(X)。
单个随机变量的熵(图片由作者提供)
多元熵 H(X,Y)被定义为变量 Z=(X,Y)的熵。在图形术语中,H(X,Y)是 X 和 Y 圆盘并集的面积。
两个随机变量的联合熵(图片由作者提供)
因此,图表显示:
联合熵不等式(图片由作者提供)
两个变量共有的“可变性”是两个变量圆盘的重叠表面:这个交集的面积是两个变量之间的互信息。换句话说,X 和 Y 之间的互信息 I(X,Y)由圆盘 X 和 Y 之间的相交面积表示,并对应于 X 和 Y 之间“共享”的熵。
两个随机变量之间的互信息(图片由作者提供)
当变量 X 和 Y 完全相关时,那么两个圆盘 X 和 Y 完全重叠,因此 H(X,Y)=H(X)=H(Y)。相反,当 X 和 Y 没有任何共同点时(变量之间没有相关性的情况),则盘 X 和 Y 不相交,H(X,Y)=H(X)+H(Y)。
互信息的定义
考虑到数据分析的实际应用,现在有可能以简化的方式介绍 Claude Shannon 的互信息定义。
在离散变量 X 和 Y 的情况下,两个变量之间的归一化互信息的度量可以定义为:
两个变量的归一化互信息(图片由作者提供)
这种互信息的标准化度量假定值在 0 和 1 之间。事实上,从前面的公式可以推断出:
归一化互信息的界限(图片由作者提供)
当变量 X 和 Y 完全“相关”时,则 H(X,Y)=H(X)=H(Y),因此标准化互信息值为 1。相反,当 X 和 Y 没有共同点时,则 H(X,Y)=H(X)+H(Y)并且互信息因此也为零。
连续变量的情况
对于连续的 X 和 Y 变量,我们必须:
- 将变量离散化,以便能够应用前面的部分公式(或类似的公式)
- 或者使用一种形式的微分熵(例如 Kullback-Leibler 散度——一种非对称互信息的度量),它假设我们知道随机变量 X 和 y 的概率分布。
当变量 X 和 Y 的概率分布已知时,第二种方法可以给出 X 和 Y 之间的互信息的精确测量。为此,Kullback-Leibler 散度可以被视为一种定义互信息的精确测量的方法,而无需离散化变量。事实上,这是一个比较与变量相关的分布的问题,可能是连续的。
然而,在实践中,变量的分布往往不是一眼就能看出来的。估计它们迫使我们要么对分布的形状作出假设,要么通过创建直方图来离散化变量,这些直方图随着观察次数的增加,最终与未知分布的形状相匹配。因此,最后一种方法相当于离散化数据的行为,因为从直方图估计分布相当于采用数据的离散化视图。
概括地说,要计算任何类型的“相关性”,要么对所研究的变量之间的关系做出假设,要么将数据离散化,这一点似乎至关重要。
线性相关的相似性
归一化互信息非常类似于皮尔逊相关。一个显著的区别是皮尔逊相关性在-1 和 1 之间,而归一化互信息在 0 和 1 之间。这是因为在两个变量之间存在线性关系的情况下,它们可以以两种方式相关,并且只有两种方式:正相关或负相关。然而,在变量之间有任何关系的情况下,它们之间有无数种相互关联的方式。因此,归一化互信息应该主要与皮尔逊相关的绝对值进行比较。
皮尔逊相关的几个性质
类似于标准化的互信息,皮尔逊的绝对值总是在 0 和 1 之间,并且当 X 和 Y 独立时,它们之间的相关性为零。
相比之下,如果 Y=αX+β(完全线性相关),那么皮尔逊相关等于 sgn(α)。因此,根据α是正还是负,相关等于 1 或-1。
学习所需的数据量
我说过,为了测量几个变量之间的非线性“相关性”,数据科学家面临着一个两难的境地:要么对变量之间的关系做出假设,要么对数据进行离散化。
实际上,这两种可能性是等价的。事实上,对于任何对学习理论感兴趣的人来说(Vapnik-Chervonenkis 理论或 PAC-Bayesian 理论——“PAC”的意思是“可能大致正确”),很明显有四个方面是相关联的:
- 可供学习的数据量
- 研究空间中的数据分布(数据是集中在一起,还是非常分散?换句话说,数据方差是多少?)
- 用于表达变量之间关系的模型的复杂性(模型是线性模型还是 10 次多项式?)
- 模型的泛化误差。
我们拥有的数据越少,我们就越被迫局限于简单的模型,以便能够合理地希望模型在一般情况下给出令人满意的结果:这就是为什么当只有两个点可用时,使用线性模型是无用的。
当考虑到大量变量时,这种情况更为明显,这就是所谓的“维数灾难”。
通过使用大量的类来离散化数据,我们允许计算机观察变量之间非常复杂的关系。这相当于考虑非常复杂的模型:互信息的测量因此可能是极好的,但是泛化误差将很可能非常大。相反,通过只使用几个类,计算机只能考虑它们之间的基本关系:因此,互信息分数会降低,另一方面,泛化误差通常会更低。
因此,进行离散化的方式直接关系到可用的观察值的数量和问题的维数。在一般情况下,数据科学家可以多次这样做:例如,他可以在训练数据上建立决策树,然后检查验证数据,泛化错误似乎是合理的。如果在验证样本上获得的结果不令人满意,数据科学家可以在这种情况下考虑新的模型,并重复他的工作,直到他获得适当的结果(同时注意不要过度拟合验证样本本身)。
不幸的是,这种方法在目前的情况下毫无意义,因为我们要寻找几个变量之间“相关性”的度量。让我们想象一位数据科学家,在发现两个变量之间的高度“相关性”后,决定建立将它们绑定在一起的线性关系。然后,他注意到,即使在训练样本上,这种线性关系也是不存在的(例如,学习样本上的线性回归呈现 5%的 R):最初使用的“相关性”将是非常无用的(这同样适用于任何降低问题维度的尝试,例如主成分分析基于变量之间相关性的测量)。
如果我们不谨慎的话,在线性相关情况下不可能发生的事情很可能在互信息测量的情况下发生。特别是,能够定义“良好的离散化”仍然是必不可少的。然而这是一块绊脚石。关于这个主题的文献浩如烟海,结果有时非常复杂,据我所知,没有完美的解决方案(至少目前是这样)。
因此,我在这里只提出一些实际实现互信息测量的经验法则。假设我们试图测量一组称为描述符的变量所提供的信息,以描述称为目标变量的其他变量。
第一条规则是,目标变量必须根据实际情况的需要和需要进行离散化。例如,如果目标变量由以摄氏度为单位的温度数据组成,并且如果对于用例来说区分“低”、“中”和“高”温度是必要且充分的,那么将目标变量离散成三个相应的类别是必要且充分的。目标变量的类的数量越多(对于描述符以相反的方式工作),过度拟合(即,不适当地获得高互信息分数)减少得越多;尽管如此,要求超过必要的水平会产生为利息问题获得人为的低互信息分数的风险(除非你有非常大量的数据)。
第二个规则是,描述符必须根据不同的分位数进行离散化,以使类别尽可能平衡。为了确定要考虑哪些分位数,我假设每个描述符的类数量对应于以下公式的一个不等式:
离散化的经验法则(图片由作者提供)
在这个等式中,m 是可用数据项的数量。为了确定 c,让我们假设我们必须回答以下问题:如果我想在两个变量 X 和 Y 之间建立可能的线性关系,我可以从训练样本的多少最小数据量允许自己执行线性回归(希望泛化误差将“非常可能足够接近”学习误差)?这个量等于 c。
假设上一个问题的答案是 c = 7。假设我们试图预测 Z 是 X 和 Y 的函数(因此描述符的数量是 2),并假设我们有 500 个数据项。因此,变量 X 和 Y 中每一个的最大类别数将是:
(1/7) ∙ √500 ≃ 3,20.
因此,我们可以使用中位数(将数据分为两类)或三分位数(创建三类)来离散化 X。对于 y 也是一样。
在一些变量(描述符或目标变量)已经是离散的情况下,为了满足前面的要求,一些类最终必须被合并。
正确量化两个变量 X 和 Y 之间的线性关系所需的最小数据量并不明显,我将在以后的文章中详细介绍一种可能的方法。
结论
简而言之,信息论是一个特别广泛的理论,超出了电信应用的范围,可以方便地用于数据分析。它通常用于构建某些决策树,但据我所知,只考虑了单变量的影响。然而,从这里提出的基本考虑,有可能制定一个多元非线性相关定义,这是我上一篇文章的主题。然而,当从线性相关性转移到非线性相关性时,复杂性出现了,因为被认为是潜在模型的函数的复杂性不再是有限的,于是话题转向了学习理论。
内核方法介绍
原文:https://towardsdatascience.com/an-introduction-to-kernel-methods-9c16fc8fefd2?source=collection_archive---------25-----------------------
从核密度估计到非参数回归。
斯科特·韦伯在 Unsplash 上拍摄的照片
介绍
统计和机器学习中的许多技术都源自“从某种概率分布中抽取数据”的概念。概率分布本身是数据点可能性(或者频率,如果你愿意的话)的模型,即观察到某个值、结果等的可能性有多大。基于这种想法的方法(或算法)被称为参数化,因为它们是由底层分布(如高斯分布)的参数指定的。
然而,假设的可能性模型可能不真实;“真实的”分布可能是偏斜的,具有不同成分的多模态,等等。一般来说,这对于分析数据的科学家来说是未知的。为了克服参数模型的局限性,一类基于所谓的 内核 的非参数方法被并行开发。这篇文章旨在展示内核背后的基本思想以及它们在统计学和机器学习中的应用。
核密度估计
当估计某个变量 x 的概率分布时,会出现第一个问题。为了获得分布的第一印象,绘制了具有不同仓宽的三个直方图(图 1)。
图 1: 不同仓宽下 x 的经验分布。(来源:作者)
根据仓宽的不同,关于底层分布的结论完全不同;它可以是均匀的,也可以是具有三种或更多模式的多模式。因此,不清楚使用哪个概率分布来估计相应的参数(如均值和方差)。注意,每一次观察都将 ρ 的一些“量”添加到它所在的仓中。因此,上面的图可以通过在 x 的不同水平的个人贡献的总和来构建。假设样本是独立同分布的。因此,我们所能做的就是将概率分布表示为数据点 xᵢ 周围的“小密度”的叠加,即所谓的 核密度 (通过观察量归一化)。因此,p(x)= 1/nσk(x,xᵢ) ,以 K(x,y) 为内核。
核密度函数。
一个可能的内核是 高斯内核;高斯核的公式如下所示。它本质上是一个以 xᵢ为中心的概率分布。
高斯核函数。
图 2: 高斯核对于 γ 有不同的取值。(来源:作者)
高斯核由一个超参数 γ (图 2)进行参数化,该参数作为方差并确定点 xᵢ 周围的密度“浓度”。还有其他可用的核(均匀核、抛物线核、余弦核等)。),但是现在使用这个就足够了。
形式上,内核是一个具有两个输入 x 和 y 的非负函数。对内核 K(x,y) 的要求是
- 它是对称的,即 K(x,y) = K(y,x) ,
- 半正定的,即具有成对评估的有限矩阵应该没有负特征值,
- 它应该整合成一个。
图 3: 不同 γ值的概率密度。(来源:作者)
出现的一个问题是 γ 的选择,其值必须是固定的。根据 γ 的值,密度可能看起来非常不同(图 3),就像图 1 中的面元宽度一样。对于太大的值,模型过于简单,重要信息丢失(拟合不足),而对于太小的值,情况正好相反(拟合过度)。这里的主要问题是“小”样本量,因为通常估计量是 一致的 并且收敛于无限多个样本的极限中的真实密度。虽然有选择 γ 的经验公式,但最简单的方法是进行 交叉验证 寻找其最优值。
核密度估计的交叉验证。
更准确地说,使验证集中的数据概率最大化的值 γ 被认为是最优的。图 4 显示了作为 γ 的函数的负对数似然性,以及具有最佳参数的密度,这似乎非常符合。
图 4: 负对数似然和核密度,以及 γ的最佳值。(来源:作者)
非参数回归
因为回归和分类问题可以从概率分布中导出,所以核也可以用于执行回归和分类。一条回归线是条件分布 p(y|x) 的期望 E ,即f(x)= E【p(y | x)】。而且认为 p(y|x) = p(x,y)/p(x) 。于是, E[p(y|x)] = ∫ y[p(x,y)/p(x)]dy 。
这产生了 f(x) 的以下表示,称为 Nadaraya-Watson 核估计器。
非参数回归函数。
预测可以被视为加权平均,而权重是训练数据中的样本到新点的相对位置。因此,核充当相似性度量。此外,出现与上述相同的问题,因为超参数 γ 必须被“调整”。这一次,要优化的度量将是 均方误差 。
回归问题的交叉验证。
γ 的最佳值是最小化均方误差的值。在图 5 中,最左边的图显示,对于高值,函数过于简单(欠拟合),而对于低值,函数变得有些嘈杂(过拟合)。最佳值似乎在 0.01 和 0.001 之间,最右边的图显示了通过交叉验证发现的该问题的最佳回归线。注意,均方误差的最小值对应于数据中不可约的误差(噪声)。
图 5: 非参数回归。(来源:作者)
内核作为内积
除了作为一种表达概率分布的方式,内核还可以以另一种方式进行解释,这在对高斯内核进行泰勒级数展开时变得清晰(图 6)。
图 6: 高斯核的泰勒级数展开。(来源:作者)
展开表明,核 K(x,y) 实际上是两个向量 x 、 y 的多项式基展开φ的<(x)、φ(y)>(具有无限阶)。因此,原始数据被隐式地映射到由多项式的新基向量构建的新空间,即特征图 — ,在支持向量机中被用作所谓的核技巧。
结论
总之,核方法是估计函数的另一种简单的方法。然而,这种非参数技术也有一些缺点。例如,计算从训练转移到评估(懒惰学习),因为训练几乎是免费的(除了只有一个超参数估计)。另一方面,他们不能在训练数据之外进行外推,这在图 5 中最右边的图中是可见的;对于 x 的高值,曲线变平,这直观上看起来是“错误的”。最后,潜在的机制没有被发现,也就是说,模型不是真正可解释的,除非应用一些模型检查技术。对于参数模型,参数的大小表示变量的相关性。尽管如此,如果唯一的目标是预测,核方法无疑是经典方法的一种替代方法。
斯蒂芬·菲利普斯-Hostreviews.co.uk 在 Unsplash 上的照片
知识图导论
原文:https://towardsdatascience.com/an-introduction-to-knowledge-graphs-faedb6f2435a?source=collection_archive---------13-----------------------
了解如何使用知识图不仅可以让数据科学家能够从大量数据中提取相互关联的事实和假设,还可以帮助他们了解如何通过链接和语义元数据形成上下文联系和理解数据,这有助于提供统一的数据分析和智能方法。本文是对知识图、重要概念及其应用的介绍。
杰森·温加特在 Unsplash 上拍摄的照片
简介
知识图用于绘制来自不同来源的数据集合,并在给定主题(如人、地点或事物)的不同实体之间建立联系,以提供数据的意义并消除任何语义模糊(Ristoski 和 Paulheim,2016 年)。图表技术和分析为连接驱动的系统提供了工具——从社交连接到金融连接,它有助于将数据分析和智能从仅仅制表和检索数据转移到形成现实世界的意义和关系(Needham 和 Hodler,2019)。
知识图可以被认为是一种语义网络,它形成了网络中概念和实体之间关联的基础——现实世界对象、事件、情况或抽象概念之间的连接(“语义网络”,2021)。尽管它们可以互换使用,但知识库和知识图并不相同,因为知识图中的信息是用图来组织的,这并不适用于所有的知识库。不同的组织提出了不同版本的知识图,每个版本都有不同的复杂程度,如谷歌的知识图、知识库、微软的 Satori、脸书的实体图等。作者图片
2012 年,谷歌推出了名为“谷歌知识图”的知识图,利用现代人工智能诞生以来一直存在的方法,使用户能够快速发现与他们的查询相关的新信息(Singhal,2012)。
资源描述框架和本体
知识图是不同范例的组合,一个提供通过结构化查询探索数据的方法的数据库,一个提供网络数据结构的图,一个解释数据和推断新事实的知识库,以及一个用作正式语义数据模型的本体,该模型用于定义主题中存在的对象类型和用于描述它们的属性(本体文本,无日期)。
资源描述框架
资源描述框架是一种图形数据模式,用于以三元组的形式描述信息的语义或含义,三元组基于实体属性值(EAV)模型,即资源、属性和属性值(主语、谓语、宾语)的组合,形成用于表示不同资源之间复杂关系的语句(Wu et al .,2014)。这意味着 RDF 让我们有机会通过基于一组规则发现关于数据的新事实来从数据中进行推断,并且由于 RDF 的语义性质,我们不需要存储显式的关系,这意味着 RDF 可以从现有的三元组中生成新的事实。
在表 1“Muizz 研究机器学习工程”中,Muizz 是主语,Studies 是谓语,机器学习是宾语。与示例中的 RDBMS 相比,它旨在通过预先创建的连接向计算机应用程序提供可理解的信息。
作者图片
图 1 中的 RDF 模式是与 rdf:type 数据科学相关的一切,我们看到指向数据科学的实体是数据科学下的一个主题,我们看到项目管理虽然与数据科学有相似的特征,因为他们都学习项目管理课程,但他们不是数据科学 rdf:type 的一部分,因此也不是数据科学家。这使得查看实体之间的连接变得容易,而不必创建复杂的连接,因为我们知道任何指向数据科学的实体都是该类的一部分。RDF 通过支持现有标准和本体重用的按作者的统一图像结构提供互操作性。他们使用跨不同系统的独特标准,通过使不同的代理、服务和应用程序能够共享知识和情报来促进数据集成和发布(Noy et al .,2005)。
作者图片
本体
在计算机科学中,本体是我们如何正式创建命名和定义类别、属性和话语域之间关系的约定(“本体(信息科学)”,2021)。本体论不同于分类学,分类学是一组受控的词汇表,用于使相关信息的查找、管理和呈现变得更容易——它们表达了一个类别内的层次关系(SCHWEIZER,无日期)。
本体是一种知识库,帮助建立人、地点和事物之间的关系,即类、实体和属性,使用户能够以各种方式将多个概念与其他概念联系起来。本体表示允许知识的语义建模,这意味着它为数据和它们之间的关系添加了基本的意义,并用于形成人工智能(AI)应用程序中的知识库(SCHWEIZER,无日期)。
知识图可以被描述为一个非常大的本体,具有额外的功能,如数据收集、提取、整合来自外部来源的数据,扩展了基于知识的系统和推理引擎(Ehrlinger 和 W o,2016)。诸如网络本体语言(OWL)之类的语言用于表达本体,它们被设计成通过指定对象类和关系属性以及分类法(本体文本,无日期)来表示关于对象和它们之间的关系的广泛知识。
知识图表的可用性
我们将探索知识图表在分析和商业智能中的应用。电信是关于连接的——在人、卫星或计算机之间交换信息,这使得知识图成为建模、存储和查询各种电信数据的完美候选。电信系统具有结合了各种复杂网络结构和系统的体系结构,它们提供各种各样的产品供应和捆绑,并在高度竞争的环境中高度投资于客户满意度和流失率,实施知识图不仅提供了监控网络系统本身的有效手段,而且使企业能够更加敏捷地处理他们的客户需求和要求。
考虑一家拥有数百万客户、代理和合作伙伴的大型电信公司。他们使用监控系统来监控客户使用情况、关键绩效指标、应用程序运行以及报告和事件通知的生成(SLAC,2021)。此类组织通常会有分析问题,例如:
作者图片
知识图降低了传统数据库中使用的一些昂贵连接的成本,因为它需要较少的资源来回答分析问题。在传统的商业智能平台中,寻找不同关系数据库之间的连接需要耗时的数据建模和查询操作。随着每一个新的业务问题的出现,我们将需要一个新的数据集和模式,这不是一个智能和知识的可持续方法(Clark,2020)。实施客户智能知识图,重点关注与客户最相关的实体,如其用户中最常见的实体:捆绑包类型、投诉、数据使用和订阅率,将为企业带来竞争优势。专注于那些最有可能提供最佳和令人愉快的用户体验的领域将有助于提高此类组织的分析和智能(Kempe,2014)。
真实世界知识图示例:微软学术图
Microsoft academic graph 是学术信息和数据的知识图实现,它收集了诸如人员、出版物、研究领域、会议和位置等实体。它提供了研究人员和与他们相关的研究之间的联系,这可能很难确定(Noy 等人,2019 年)。
Microsoft Academic Knowledge Graph(MAKG)是一个大型 RDF 数据集,包含超过 80 亿个关于科学出版物和相关实体(如作者、机构、期刊和研究领域)的三元组信息。MAKG 使用在开放数据共享归属许可(ODC-By)下许可的数据。通过使用 RDF 转储文件,这种知识图能够将大量的学术出版物和数据汇集到网络上,这些数据来源于与 URIs 相链接的开放数据云,该开放数据云能够工作并连接到多个数据源(Farber,2006)。Microsoft academic graph 以通过识别表示实体或联系的语义对象的词汇结构从文本中获取知识为中心。MAKG 使用一种称为概念的分层实体类型来表示文档的语义内容,这是一种定义作者和从属关系等实体的抽象方法,因此没有定义它们的具体方法(Kuansan 等人,2019)。
参考文献
[1]克拉克,K. (2020)什么是知识图?。可在以下网址查阅:https://www . stardog . com/blog/what-is-a-knowledge-graph/(访问日期:2021 年 5 月 11 日)。
[2] Ehrlinger,L .和 W . o . W .,《走向知识图的定义》语义学(2016)。
[3] Farber,M. (2006)微软学术知识图:具有 80 亿三元学术数据的链接数据源。德国卡尔斯鲁厄理工学院 AIFB 学院。
[4]C . Feilmayr 和 W . o . W .,“对应用于商业数据知识工程的本体论及其成功因素的分析”语义学(2016)。
[5] Kempe,S. (2014)为什么您的企业需要客户数据知识图?。可从以下网址获得:https://www . data versity . net/business-needs-customer-data-knowledge-graph/(访问日期:2021 年 5 月 11 日)。
[6]关山,w .,智宏,s .,池源,h .,杰汉,w .,达林,e .,小宇,d .,接君,q .,安舒尔,k .,阿尔文,c .,和理查德,R.(2019)“微软科学学学术服务的生物学家观点”,大数据前沿杂志,(2),第 45 页。可在:https://www . frontiersin . org/article/10.3389/fdata . 2019 . 2020015(访问日期:2021 年 5 月 11 日)。
[7] Noy,n .,Gao,Y .,Jain,A .,Narayanan,A .,Patterson,A,和 Taylor,J .(2019)行业规模知识图表:经验和挑战。可查阅:https://cacm . ACM . org/magazines/2019/8/238342-industry-scale-knowledge-graphs/(查阅时间:2021 年 5 月 10 日)。
[8]诺伊,麦克吉尼斯,和海斯,P.J. (2005)“使用 RDF 和 OWL 的语义集成互操作性”,W3C 期刊。可在:【https://www.w3.org/2001/sw/BestPractices/OEP/SemInt/ (访问时间:2021 年 5 月 11 日)。
[9]《本体论》(2021)。维基百科。在 https://en.wikipedia.org/wiki/Ontology.可用(访问时间:2021 年 5 月 11 日)。
[10]《本体论(信息科学)》(2021)。维基百科。可在https://en . Wikipedia .org/wiki/Ontology _(information _ science)获取。(访问日期:2021 年 5 月 11 日)。
[11] Ontotext(无日期)可在以下网址查阅:https://www . onto text . com/knowledge hub/fundamentals/what is-a-knowledge-graph/(查阅日期:2021 年 5 月 11 日)。
[12] Ontotext(无日期)可在以下网址查阅:https://www . onto text . com/knowledge hub/fundamentals/whatare-ontologies/(查阅日期:2021 年 5 月 11 日)。(正文,无日期)
[13] Needham,m .和 Hodler,E. A. (2019)图形算法:O'Reilly Media,Inc .
[14] Ristoski,p .和 Paulheim,H.(2016)“数据挖掘和知识发现中的语义网:一个全面的调查,Web 语义学杂志”,Web 语义学杂志,4(2),第 1–22 页。可用时间:https://doi.org/10.1016/j.websem.2016.01.001.(访问时间:2021 年 5 月 11 日)。
[15] SCHWEIZER,c .(无日期)分类学和本体论有什么区别?这是一个复杂的问题。可从以下网址获得:https://www . earley . com/blog/what-difference-between taxonomy-and-ontology-it-matter-complexity(访问日期:2021 年 5 月 11 日)。
[16]《语义网络》(2021)。维基百科。可在https://en.wikipedia.org/wiki/语义网获得。(访问日期:2021 年 5 月 11 日)。
[17] SLAC 国家加速器实验室(2021 年)可在:https://www.slac.stanford.edu/xorg/nmtf/nmtf-tools.html获得(访问日期:2021 年 5 月 11 日)。
[18] Singhal,A. (2012)介绍知识图:事物,而不是字符串。可在:https://blog . Google/products/search/introducing-knowledge-graph-things-not/(访问时间:2021 年 5 月 11 日)。
[19] Stanford CS 520(无日期)可在以下网址查阅:【https://web.stanford.edu/class/cs520/2020/】T4notes/What _ Are _ Some _ High _ Value _ Use _ Cases _ Of _ Knowledge _ graphs . html(访问日期:2021 年 5 月 11 日)。
[20] Wu,b .,Zhou,y .,Yuan,p .,Jin,h .和 O'Hara,j .(2014)“SEM Store:一个语义保持的分布式 RDF 三元组存储。”,载于第 23 届 ACM 信息和知识管理国际会议(CIKM '14)的会议录。美国纽约州纽约市计算机械协会,网址:https://doi . org/10.1145/2661829.2661876(访问日期:2021 年 5 月 11 日)。
面向深度学习的线性代数导论
原文:https://towardsdatascience.com/an-introduction-to-linear-algebra-for-deep-learning-c1b72de78543?source=collection_archive---------20-----------------------
深度学习都是关于数据的,我们需要表示数据并对其进行操作,以训练我们的深度网络。
线性代数构成了深度学习的基础。更好地掌握该领域的基础知识将有助于你对深度学习算法中数据的处理方式有更好的直觉。
https://en.wikipedia.org/wiki/Linear_algebra
深度学习都是关于数据的,我们需要表示数据并对其进行操作,以训练我们的深度网络。数据必须用矩阵形式表示。更好地理解矩阵运算和矩阵代数将有助于你对深度学习算法如何工作有更好的直觉。这就是为什么线性代数可能是深度学习中最重要的数学分支。在这篇文章中,我将试着澄清这个领域的基本话题。
我们所说的数据是什么意思?
让我们考虑一个简单的例子,其中你有每所房子的属性,你的目标是尝试并预测给定房子的价格。这些属性也称为解释变量,我们将利用它们来训练我们的模型。为了简单起见,我们只考虑三个属性:卧室数量、房子大小、位置。现在,每座房子将被表示为一个包含三个值的向量。
【X _ number of bedrooms,X_size,X _ location】
但是等等,这里我们只考虑单套房子。我们通常有由数千所房子组成的数据集,每所房子被称为一个数据点。至此,我们要做的就是把房子的向量叠加起来,形成一个矩阵。每行代表一所房子,每列代表一个解释变量。太好了,我们现在已经有了设计矩阵!
x₁₁:第一栋房子的房间数
x₂₁:第一栋房子的大小
x₃₁:第一栋房子的位置
简单线性回归
这里,我们将尝试建立一个简单的模型来预测给定房屋的价格。让我们来看看这三个解释变量的线性组合。我的意思是,这可能是你能得到的最简单的模型;简单的线性回归。现在让我们正式地看看这个:
y =xβ+ϵ
如你所见,我们有三个权重,每一个都乘以 EV。你可以认为它们是决定价格的每个变量的重要性。简单的想一想,如果房子大,位置好,价格肯定高。因此,所有电动汽车都与价格正相关。通过查看最高权重,我们可以确定最相关的变量,这将为我们提供模型对每个变量的敏感性的良好感觉。现在,让我们用矩阵符号重写一切。
作者图片
如您所见,以矩阵形式编写所有内容可以更简洁地描述正在发生的事情。但是我们如何乘矩阵呢?别担心。这是令人震惊的简单和直观。
乘法矩阵
首先让我们直观地思考一下。我们只想将每个 EV 乘以其相应权重。我们有 n 个房屋/示例,所以从逻辑上讲,我们应该将设计矩阵中的每一行乘以列向量 w。为了简洁起见,我们将考虑一个简单的示例,其中有两个示例和三个解释变量:
作者图片
矩阵和列向量的乘法将产生另一个列向量。
现在让我们考虑两个矩阵相乘。不要忘记,要乘矩阵,第一个矩阵的列数应该与第二个矩阵的行数相同。结果矩阵的大小可以很容易地计算出来:如果 A=[aij]是 m×n 矩阵,B=[bij]是 n×k 矩阵,则 AB 的乘积是 m×k 矩阵。我有一些好消息;你已经知道如何乘两个矩阵。这个过程与矩阵乘以向量是一样的,但是这一次,假设您有不止一个列向量。然后,将得到的列向量并排放到一个矩阵中。
PyTorch 和 Tensors
在这一节中,我们将研究 PyTorch 张量,并使用它们进行矩阵乘法。PyTorch 是著名的深度学习库,张量起着至关重要的作用。你可以把张量想象成更高维的矩阵,PyTorch 让我们可以高效地对它们进行数值运算。现在你可能已经猜到了,矩阵和张量构成了深度学习的基础。
让我们看一个简单的例子,我们初始化两个矩阵并对它们执行矩阵运算:
*A = torch.tensor([[1,2,3] , [2,3,4]])**B = torch.tensor([[3,1] , [4,2] , [2,3]])**torch.matmul(A,B)*
矩阵乘法的输出
神经网络。
考虑到目前为止我们所学的一切,我们可以开始应用矩阵运算来表示神经网络。在这里,我将假设你知道神经网络的基础知识。因此,首先,让我们看看我们的模型架构在单一隐藏层的情况下会是什么样的。
http://alexlenail.me/NN-SVG/index.html
从上图可以看出,我们有输入神经元,它们的表现方式和我们的房子数据一样。接下来,我们有四个神经元的隐藏层。每个神经元将是通过非线性函数的输入神经元的线性组合。在这个例子中,我们将考虑一个广泛使用且简单易懂的激活函数。整流线性单元是一个激活函数,如果输入值为负,则输出零,否则输出输入。数学上,ReLU 函数为 f(x)=max(0,x) 。为了表示隐藏层中的四个神经元,我们将把我们的设计矩阵乘以具有四列三行的权重矩阵;行数应等于输入的维数,列数应等于后续层中目标神经元的数量。
作者图片
剩下的就是最终的输出层了。输出神经元也是前一层神经元的线性组合。因为我们正在处理一个回归问题,其中我们想要一个没有边界的值,所以我们不需要最后一层的激活函数。这一层的矩阵乘法要容易得多,因为我们将只采用隐藏层的线性组合。这应该类似于线性回归,事实上,它确实是线性回归。整个模型可以表示如下:
摘要
所有的深度学习操作都用矩阵计算来表示。学习数据如何用矩阵和张量表示的基础知识,将会让你对事情的本质有更好的直觉。我建议任何人通过观看 3Blue1Brown 关于线性代数本质的系列文章来学习更多的线性代数知识。当然,人们永远不会忘记吉尔伯特·斯特朗教授的精彩讲座。学习愉快,愿母体与你同在!
参考
https://en.wikipedia.org/wiki/Linear_algebra https://ocw.mit.edu/courses/mathematics/18-06-linear-algebra-spring-2010/
朱莉娅中的线性代数导论
原文:https://towardsdatascience.com/an-introduction-to-linear-algebra-in-julia-1d6f8764c910?source=collection_archive---------19-----------------------
Julia 中线性代数包的快速概述。
(src =https://pixabay.com/images/id-327488/
介绍
OJulia 编程语言的一个伟大之处是语言中强大的数学功能。这种语言有一些非常棒的特性,在这方面使它有别于类似的语言。线性代数对于数据科学极其重要。Julia 的目标是科学计算和数值分析,因此可以假设 Julia 非常擅长线性代数。这当然是事实,然而,Julia 中的线性代数被构建在语言的核心中,这在编程中并不常见。除了 Julia 和其他类似编程语言之间的差异之外,代数表达式和语法与许多其他选项也有很大不同。
每当我考虑有人想使用 Julia 语言进行数据科学研究时,我总是会想到 Python 用户。话虽如此,Python 和 Julia 还是有很多区别的。其中一些只是方法调用上的细微差别,其他的则是相当戏剧性的,改变了我们在语言中处理数字的方式。考虑到这一点,我想在本文中为那些对编程和线性代数不熟悉,但对 Julia 语言不熟悉的人创建一个基础速成班。
笔记本
阵列和矩阵
在我们开始在 Julia 中创建代数表达式之前,我们首先需要回顾一下我们在做线性代数时可能会看到的不同类型以及它们之间的区别。这个类型列表中的第一个是向量。Julia 中的 vector 与 Python 中的 list 概念完全相同,我们可以使用[]元素语法创建一个 vector:
one_D = [5, 5, 7, 2, 3]
这将创建一个一维数组。为了创建一个多维数组,我们改为像 Lisp 那样用空格分隔元素,然后用分号分隔行。
multi_D = [5 10 2 4; 5 8 10 3]
这将创建一个新的 2 x 4 矩阵。我还做了另一个同样尺寸的,用来执行一些基本的算术运算:
multi_D2 = [10 7 4 3; 9 5 3 10]
one_D = [5, 5, 7, 2, 3]
让我们也考虑一下这些新变量的类型。多维数组是矩阵类型的,一维数组是向量类型的。然而,这两种类型都是抽象数组类型的子类型,如下图所示:
println("An array is a sub-type of an abstract array:\n")
println("Type: ", typeof(one_D))
println(typeof(one_D2) <: AbstractArray)
println("\n==============================\n")
println("Is a matrix an abstract array?\n")
println("Type: ", typeof(multi_D2))
println(typeof(multi_D) <: AbstractArray)
(图片由作者提供)
这意味着尽管它们是不同的类型,但它们通常会被分派给相同的方法。这意味着可以使用一个到另一个的许多方法。举个例子,
println(length(multi_D))8
让我们也考虑一下这些数组的形状。我们可以使用 shape()方法来重塑我们的数组。我们还可以使用 size()方法来检查数组的大小:
size(one_D)
size(multi_D)
例如,我将复制并重塑我们的多维数组:
copmd = copy(multi_D)
copmd = reshape(copmd, (4, 2))
尽管该方法通常不会对类型进行变异,也没有变异函数(带有!,)我还是复制这个数据结构以防万一。没有什么比丢失数据更糟糕的了,尤其是如果它只是请求的数据,而不是本地存储的数据。让我们来看看两者的区别:
println("We went from this")
display(multi_D)
println("to this:")
display(copmd)
作者图片
发电机
我们接下来要看的是发电机。生成器是线性代数中非常重要的一部分,尤其是在机器学习应用中。Julia 拥有你能想到的所有生成器,比如零,都是受支持的。然而,在 Julia 中有一些相当独特的生成器怪癖,其中一些是最近才出现的。不赞成使用 eye 方法,而赞成使用 UniformScaling 运算符。只需在整数后加一个 I 就可以使用这个运算符,这是一种非常朱利安式的方法:
5I
让我们来看看零的例子:
zeros((5, 10))
单位矩阵和零可能是两种最常见的生成器,但是您可以随意查看完整的文档来了解其他各种生成器:
操作
现在我们已经完全熟悉了处理和创建矩阵的一些基本方法,让我们来看看一些基本操作。我们将从可以用来执行一些运算的基本操作符开始。第一个是逐元素乘法。这将把每个元素乘以另一个数组中相应的元素,这个运算的运算符是。*.
multi_D .* multi_D2
对于 Julia 中的所有数学位操作符,也有等价的元素操作符。
multi_D .+ multi_D2
multi_D .- multi_D2
multi_D ./ multi_D2
由于这些是基于元素的,所以它们也可以用于一维数组:
one_D .* one_D2
现在我们已经看了所有的元素操作符,让我们考虑一些处理矩阵的基函数。我首先要介绍的是 transpose 方法,它将执行与我们在前面的示例中所做的完全相同的整形操作:
transpose(multi_D)
如您所料,还有 dot():
dot(multi_D, multi_D2)
还有通过 cat、vcat、hcat …方法的串联:
hcat(multi_D, multi_D2)
最后,我们可以使用 cumsum()方法进行累积求和。我们需要为这一呼叫提供 dims 关键字参数:
cumsum(multi_D, dims = 5)
当然,还有很多这方面的功能可以从 Julia 的基础上使用。此外,LinearAlgebra.jl 包中还有更多可以使用的内容。但是,浏览它们可能需要相当长的时间,所以我将提供文档链接:
https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/
结论
感谢您阅读我在 Julia 中的线性代数入门。虽然与许多其他语言相比,它肯定是独一无二的,但它肯定适合这份工作。我认为,人们可能会发现,朱莉娅处理这类任务的方式实际上是相当令人印象深刻的!尽管这仅仅是对该语言能力的一个简要介绍,但是您还可以做更多的事情,尤其是使用 LinearAlgebra.jl。希望这篇文章能够很好地介绍整个伟大的数组数学世界!