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

龙哥盟 / 2024-10-21 / 原文

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

使用 Apromore 进行业务流程模拟和假设分析

原文:https://towardsdatascience.com/business-process-simulation-and-what-if-analysis-with-apromore-7b70beddbeca?source=collection_archive---------28-----------------------

图片由作者提供,截图来自 Apromore

对我的流程来说,什么是最好的设计!?如果我收到两倍的订单会怎么样?如果我多雇两个专家会怎么样?

现代业务流程挖掘(BPM)工具能够生成业务流程的副本(也称为数字孪生),运行模拟并分析条件改变时会发生的情况(假设分析)。这篇文章一步一步地展示了如何在 Apromore 中实现这一点,这是目前最先进的 BPM 工具之一。

概要:

  1. 创建一个流程模型,
  2. 定义模拟参数(任务需要多长时间,有多少资源可用),
  3. 通过添加/删除资源、更改流程任务的持续时间或修改流程的设计来创建模型的替代版本。
  4. 运行模拟并比较结果。

创建流程模型

让我们首先在 Apromore 的 BPMN(业务流程模型和符号)编辑器中创建一个模型。顾名思义,您可以通过创建任务、网关并连接它们来构建传统的 BPMN 式流程。

为了这个演示的目的,我将对技术到演示的过程进行建模。这是我们部门的流程之一,旨在发现新的数字技术并向我们的业务部门展示。该过程具有以下步骤:

  • 技术研究,
  • 将技术添加到评估列表中,
  • 验证技术,
  • 根据评估结果将技术标记为“测试”或“保留”,
  • 选择技术进行演示,
  • 找到一个用于演示的用例,
  • 执行概念验证,
  • 演示一下。

下图显示了我们如何构建和连接流程的最初两个任务。

图 1:用 Apromore 的 BPMN 编辑器构建流程模型(图片由作者提供—截图来自 Apromore)

我们继续添加任务、网关和连接器,直到模型完成。是的,我知道这是同样的老无聊的 BPMN 的东西,但我保证事情很快会变得有趣得多:)!

图 2:在 Apromore 的 BPMN 编辑器中完全构建的流程模型(图片由作者提供—截图来自 Apromore)

定义模拟参数

Apromore 的 BPMN 编辑器通过“模拟参数”定义过程元素的动态特性,使我们的静态模型变得生动。下图说明了可以设置的不同类型的模拟参数:

  1. General —我们多长时间有一个新案例,正在模拟的流程实例(案例)的总数以及模拟的开始日期。
  2. 任务 —设置所有流程任务的持续时间分布(即:执行任务需要多长时间)。
  3. 时间表 —定义人员和机器的工作时间表(例如,专家从上午 9 点到下午 17 点工作)。
  4. 资源 —定义可用资源的类型和数量(人和机器)。
  5. 关口 —定义关口的转移概率(例如,通过评估的案例比例)。

图 3:apro more 中不同类型的仿真参数(图片由作者提供—截图来自 Apromore)

注意,这个工具可以将持续时间设置为概率分布。换句话说,我们可以说,*均来说,新病例每两周出现一次,但有时需要 5 天甚至 10 天的时间,有时新病例在前一个病例后几天出现。在进行模拟时,这种概率性质极其重要,因为对于静态值,我们无法看到边缘情况(例如,可能发生的最坏情况是什么)

运行模拟

为所有任务定义模拟参数后,我们可以通过选择模型并使用“模拟模型”功能(1)来运行模拟。这产生了一个模拟的业务日志(2 ),我们可以打开并分析它。

图 4:在 Apromore 中生成模拟流程日志(图片由作者提供—截图来自 Apromore)

假设分析

假设分析是关于更改模拟参数(例如添加或删除资源)并重新运行模拟。这些步骤包括:

  1. 在 BPMN 编辑器中更改一些模拟参数。
  2. 运行模拟以创建替代流程日志。
  3. 分析模拟日志以查看变化。

下图显示了假设我添加了一个额外的开发团队的结果。在商业模型的第一个版本中,我将开发团队的数量设置为 2,在第二个版本中,我将团队的数量增加到 3。在这两个版本中,都创建了模拟流程日志(img 1)。接下来我对比了一下进程日志的统计,看看,增加一个开发团队(img 2 & img 3)能有什么确切的效果。

我们的假设分析显示,对于 2 个开发团队(img 2),执行 20 个从技术到演示的流程实例需要大约 1 年零 1 个月的时间。对于 3 个团队(img 3 ),相同数量的流程实例需要大约 11 个月。因此,基于假设分析,我们可以得出结论,拥有一个额外的开发团队将使我们获得 2 个月的时间

图 5:通过比较两个模拟的流程日志(作者提供的图片——来自 Apromore 的截图),分析增加一个额外开发团队(img 2 有 2 个开发团队,img 3 有 3 个开发团队)的效果

摘要

新颖的流程挖掘工具能够创建动态流程模型,用于模拟各种条件下的流程。假设分析就是模拟流程的几个不同版本,并比较结果。在设计新的业务流程时,这是一个非常有用的特性——人们可以尝试不同的流程设计,并修改资源数量以找到最佳设置。此外, 假设分析对现有流程非常有用,因为它能够 a)分析添加/删除资源的影响,b)通过增加引入的工作来测试流程的限制,c)在安全(模拟)环境中查看重新设计的影响。总之,模拟和假设分析的结合具有将过程管理带入新时代的巨大潜力。

企业在应该寻找信号的时候却在购买数据集

原文:https://towardsdatascience.com/businesses-are-buying-datasets-when-they-should-be-finding-signals-d82e1969dcb2?source=collection_archive---------27-----------------------

对外部数据的访问解决了问题的一部分,但也产生了另一部分。

人工智能带来了对数据的贪得无厌。大数据似乎永远不够大。人们总是渴望更多的容量,更多的变化。今天,企业竞争的不是最好的 ML 算法,而是最好的数据和领域专业知识。

为了满足这种需求,商业提供商提供各种类型的数据集——金融、地理空间、生物。企业购买这些数据集,组织它们,提取他们认为会使他们的模型更具预测性的属性,并丢弃其余的。

但是请注意那个词:“思考”他们不知道自己需要什么。他们猜测。他们认为。这是个问题。

约书亚·索蒂诺在 Unsplash 上拍摄的照片

问题

使用外部数据的全部目的是改善人工智能和分析的结果,而不是使用组织内部的数据。对外部数据的访问解决了问题的一部分,但也产生了另一部分。企业的选择越多,就越难找到哪种数据组合能提供最好的结果。就像出去买叉子,被逼着买了整套 300 块的餐具。

另一种方式是,企业购买数据集,但并不真正需要数据集。它们需要特定的内部“信号”。他们永远不会将一个地区中小企业业务数据集的整个厨房水槽扔进一个人工智能模型。相反,他们会挑选出看起来有预测性的信号,比如客流量、收入中位数、网站流量,甚至年降雨量。

照片由陈乐德在 Unsplash

一个企业可能从十几个数据提供商那里购买数据,但只使用其中一个信号(或属性)。许多数据集甚至可能包含相同的属性。即使设置了冗余的问题,大量的数据也很快变得令人困惑。从成千上万个可用的信号中寻找,如何确定需要哪些信号来填补模型中的空白呢?

需求

这就是为什么对企业来说,从一开始就关注他们需要的信号而不是他们可以拥有的数据集是如此重要。借助当今的数据和 ML 技术,可以从各种来源聚集数据集,识别和标记最相关的信号,并协调它们以供立即使用。使用这种方法,企业可能会发现来自 24 个数据源的 100 个信号,而不必评估和采购这 24 个数据集。

由于信号经过标记和协调,基于 ML 的系统可以推荐与特定分析最相关的信号。例如,客流量数据或在线评论和评级可能会为小型企业的信用风险预测提供信息。该系统可以发现数百个这样的信号,而数据科学家可能从未想过要包括这些信号。

此外,一旦这些信号得到协调,就没有必要担心数据匹配和集成。系统可以自动将内部数据与所选信号进行匹配和整合。

机会

这种方法——将信号置于数据集之前——可能看起来像是一个小小的程序调整,但它改变了人工智能和分析的日常使用。不再受限于内部数据或企业可以自行获取的数据,突然之间,它可以访问任何可能需要的信号,从而构建任何可以想象的分析。

它在概念上与复合应用程序非常相似,在复合应用程序中,开发人员将来自不同应用程序的上下文服务组合在一起,组成订单到现金之类的流程。对数据分析做同样的事情——从数据宇宙中挑选预测信号——而不需要购买整个数据集,这让企业可以自由地将他们最大的想法付诸实践。

打破常见的编程神话

原文:https://towardsdatascience.com/busting-common-programming-myths-55167b1f2a22?source=collection_archive---------43-----------------------

揭示编程常见误解的真相

(src =https://pixabay.com/images/id-1244572/

介绍

尽管科学和计算机编程的世界可能是纯粹理性的,更重要的是;数据驱动,人类天生不可思议的不理性。人类持有的大多数观点都是基于反应,而不一定是数据,有时假设事情而不知道它们可能不是真的会更容易。在某些情况下,事实甚至可能比小说更奇怪,这种思维方式当然有可能不时渗透到计算机编程的世界中。

在编程的世界里,肯定有一些错误的信息。此外,人们可能会根据初步诊断做出一些假设,但从长远来看,这些假设很可能并不成立。今天,我想揭示一些非常流行的编程神话的真相,并提供一些数据来支持它们背后的真实真相。

误区 1:越多的程序员越有效率

让我们从一个假设的场景开始第一个神话。您有一个大约七个人的中等规模的开发团队,但是您有截止日期。压力越来越大,看起来你的团队可能无法成功。在这种非常普遍和不幸的情况下,最初的反应可能是雇佣新的程序员与您的团队一起工作。毕竟,如果你将程序员的数量增加一倍,交付产品的时间应该会减少一半,对吗?

乍一看,这似乎是真的。如果我们正在建造一座房子,并且拥有两倍的劳动力,那么它的建造速度很可能会是两倍——那么为什么同样的情况不能应用于软件工程呢?答案在于开发团队实际上是如何工作的。

为了让两个或更多的程序员高效地一起工作,最重要的变量总是交流。没有适当的沟通,没有人能知道谁提交了什么代码来做什么,并且很容易理解为什么这对试图理解他们到底在编程什么的团队来说是有问题的。

定量软件管理(QSM)做了一项研究,揭示了这一点。他们决定将团队分为小团队和大团队。一方面,他们有五人或更少的团队,另一方面有二十人或更多的团队。两个团队在日程安排上的差异通常是一个日历周。在更小的团队中也有更多的可变性。虽然拥有大量程序员的团队确实设法完成了更多的工作,但是每个成员的工作效率实际上都很低。这意味着他们的养老金远没有有效地用于满足项目的最后期限。更大的团队也不断地创造出更多有缺陷的软件。这两者都可以归结为沟通,持续与超过 20 个人沟通并协调好这么大的一个编程项目几乎是不可能的。如果您想了解有关该研究的更多信息,请点击此处:

https://www.qsm.com/risk_02.html

误区 2:编程语言的选择无关紧要

如果我是诚实的,这是一个神话,我已经成为受害者。对我来说,编程语言并不经常成为生产力的限制因素。通常,我会认为这总是程序员自己。当然,编写像 C 这样的低级语言可能比编写像 Python 这样的高级语言要慢一点,但一般来说,我认为生产率水*是一样的。

事实证明,这完全是一个神话,当谈到这个论点时,数据实际上与我猜测的相反。根据 NameCook analytics 收集的数据,编程语言的生产率或多或少取决于它们的范式和语法。这可能会让许多软件工程师感到震惊,因为大多数时候,当涉及到我们的生产力时,我们并不觉得受到我们的工具的限制,而是我们自己。他们发现 SmallTalk 是效率最高的编程语言之一,而 C 是效率最低的语言之一!如果我只是从别人的假设中听到这些,我可能会认为这是疯狂的言论,但这确实是真的!

我认为,针对这项研究,真正要做的事情是看看这些不同编程语言的所有变量。有如此多的因变量,似乎不可能控制一个适当的实验,因为语言中有如此多的因素可能会对此有所贡献。以文档为例。不充分的文档肯定会降低程序员的工作效率。现在我并没有写闲聊的代码,但是我决定看一下它的文档,我发现它并没有什么特别的,尽管确实很深入。另一方面,c 文档不是很好。C 语言文档的问题在于,它更多的是面向示例和演示,而不是面向解释,这可能是有问题的——尤其是对于新手!

如果你想更多地了解事实上反驳这一神话的数据,你可以在这里查看 NameCook analytics 发表的论文:

误区 3:更多的时间意味着更多的软件

软件世界通常节奏很快,压力很大。随着软件工程社区的发展,出现了一定程度的“磨人心态”,我认为这源于一种误解,即更长的时间和更多的时间在键盘后面会导致更多的开发。这不仅会严重影响所生产软件的质量,还会降低团队的产量。

大脑需要时间休息,编程也是如此。当你累的时候,很容易犯一些简单的错误,而且每周多工作一天也不会让你的大脑得到真正完成工作所需的适当休息。这种休息是至关重要的,因为它让你以全新的视角看待问题。你有没有试过解决一个问题,然后回头再来看时马上意识到解决的方法?每当你的大脑处于第二阶段思考的时候,就很难让它脱离已经处于的状态。事实是,较轻的第二阶段思维和第一阶段思维是你大脑处于巅峰的地方。尽管第一阶段消耗的能量较少,但你的大脑仍然很擅长即兴假设事情,有时拥有并利用这种想法是有好处的。

微软做了一个实验,他们开始给工程师更多的休息日。他们没有给员工仅仅两天的周末,而是决定给他们三天,每周工作四天。这产生了一些有趣的结果,因为工程师们在此期间的工作效率比以往任何时候都要高。他们甚至在四天内完成了比*时更多的工作!如果你想了解更多,这里有一篇来自 Business Insider 的文章:

https://www.businessinsider.com/microsoft-4-day-work-week-boosts-productivity-2019-11#:~:text=Microsoft%20experimented%20with%20a%204,and%20productivity%20jumped%20by%2040%25&text=Microsoft%20found%20that%20implementing%20a,Work%2DLife%20Choice%20Challenge.%22

误区 4:团队成功是基于经验的

公司看待员工的一个非常常见的方式是通过认证和工作经验。许多软件团队都失败了,这通常与团队中员工的资格和经验无关。大多数时候,对于一个给定的软件开发团队来说,最重要的事情是沟通,正如我前面提到的。

成员更善于沟通的团队会比不善于沟通的团队做得更好。你碰巧是一个多么优秀的程序员并不重要,因为最终能让你和其他人有所不同的是你能够和他们一起工作。也就是说,个性对于一个软件工程师的能力起着非常重要的作用。贝尔宾做了一项研究,他们发现情商高于智商的程序员远比智商高于情商的程序员过得好。这意味着,要成为一名伟大的程序员,你不一定要成为最擅长编程的人。

当与一个团队一起工作时,适当的沟通总是产品推出的支柱。很多项目都以失败告终,因为团队不能很好地合作,我认为这是一个人在尝试做程序员之前应该注意的事情。如果你想了解贝尔宾在这方面的研究,你可以点击这里:

https://www.belbin.com/resources/blogs/belbin-and-project-aristotle-everything-you-need-to-know

结论

就像任何其他学科一样,软件工程的世界笼罩在某种神秘之中。关于计算机编程有许多奇怪的事情,人们最终可能会认为是真的。在任何情况下,使用数据得出真正准确的结论都是很重要的。我认为总的来说,其中一些是可以预料的。显而易见,由于显而易见的原因,软件团队不可能很大,工程师需要休息的原因也很清楚,但是每当我们考虑到编程语言比其他语言更有生产力时,这确实有点奇怪。感谢您的阅读!

购买到死:用 Python 预测客户终身价值

原文:https://towardsdatascience.com/buy-til-you-die-predict-customer-lifetime-value-in-python-9701bfd4ddc0?source=collection_archive---------0-----------------------

行业笔记

端到端示例:Beta 几何/负二项分布模型(BG/NBD),使用 Python 中的生存期

La Catrina 女孩服装 Pixabay 上的免费照片Jose Sanchez _ photos

1.我们正在寻找的洞察力

今天的文章将把焦点放在非契约性商务环境上。我们希望预测客户的交易频率及其流失风险。

过去*均每 20 天购买一次产品,但 50 天没有活动的客户,必须被评定为增加的流失风险。她可能即将离开我们的业务,转向竞争对手的产品系列。当我们的应用程序向客户指出高流失风险时,营销团队可以考虑促销、折扣和其他外联活动。

我们想要的是一个能为我们标记流失风险客户的模型。我们还希望它能预测每个客户的购买量。同时,它应该计算我们所有客户的终身价值。

满足这些要求的数据科学方法被称为Buy ' unt You Die 模型:BTYD ( Wikipedia ):从客户的“出生”(当她向我们的企业下第一个订单)到她“死亡”(当她转向竞争对手,从而对我们这个被她唾弃的企业而言已经死亡)。

我们在数据科学中最常遇到的客户流失模型适用于合同设置。客户与互联网提供商、移动电话网络、保险公司和基于订阅的服务提供商签订有期限限制的合同。契约环境中的企业可以对有流失倾向的客户有更清晰的认识。他们的原始数据显示,每当合同期限接*尾声时,风险就会上升。销售和营销团队往往会在客户开始考虑续订或取消订阅之前联系她。例如,IBM Telco 数据集已经成为解决契约流失问题的普遍例子,我们可以对其应用一系列众所周知的模型,如逻辑回归、随机森林、梯度推进方法和其他分类器。

然而,在一个非契约性的商业环境中,情况更加不明朗。销售和营销团队无法在其日程表中预见客户的高风险。我们通常应用于合同商业环境中客户流失问题的大多数分类模型不适用于非合同环境。流失日期是不透明的。

相反,我们需要通过做出分布假设来分析客户的购买行为。概率模型也将使我们能够预测购买量。

购物中心橱窗 PhotoMIX 公司在 Pixabay 上的免费照片

我们将要建立的模型将使营销团队能够将他们的工作重点放在那些被模型确定为转折点的客户身上。

在今天的文章中,我们将实现 2 口:

  • 贝塔几何/负二项(BG/NBD)模型
  • 结合伽玛-伽玛模型估算客户终身价值。

这听起来比实际情况更可怕。数学很复杂——涉及到四种分布和贝叶斯推理。不过,大部分的数学知识将会被安全地保存起来。这个寿命包将为我们进行数字运算。虽然我会跳过方程,但我们应该理解这两个模型在得出预测时所应用的原理和假设。这就是为什么当我们建立和运行模型时,我会添加一些解释。

下面的屏幕截图显示了我们希望从模型中获得的输出示例。一个列出我们所有客户的数据框架,我们将为这些客户推导出以下绩效指标。

作者图片

  • CLV 表示客户终身价值:在这种情况下,是在一段选定时间内的收入,例如 12 个月。
  • 四个预测列预测我们在接下来的 10、30、60 和 90 天内可以从每个客户那里预期的购买交易数量。
  • prob_alive 估计客户活着的概率。它的补充(1-p)相当于客户流失风险:远离我们的业务,偏向竞争对手。

2.属国

除了顶部的核心库,我们还安装并导入了生存期库。

  • 快速入门—寿命 0.11.2 文档
  • 明明白白::Anaconda.org
  • 寿命 PyPI
  • 康达安装-康达锻造寿命
  • pip 安装寿命

3.数据争论

我们要使用的数据源可以从加州大学欧文分校的机器学习库下载 Excel 文件。(2015).UCI 机器学习知识库。知识共享的属性。”

它包含一家英国在线零售商 2010 年和 2011 年的 542,000 条记录。

作者图片

首先,我们寻找没有可识别客户的记录。我们发现多达 135,000 个,分布在 3,710 个发票号码上。

作者图片

假设,我们可以考虑使用发票号作为虚拟变量,每个虚拟变量代表一个未知的客户。但这会扭曲我们的模型。我们对回头客及其需求模式感兴趣。通过将这 3,700 个发票号码中的每一个解释为虚拟客户,我们将增加一次性购买者的数量。它们不会为我们提供一个可识别的趋势,相反会淡化我们可以为可识别的客户推断的模式,我们发现这些客户有 4300 个。因此,我们需要删除这 135,000 条缺少客户 ID 的记录。

在我们开始修改源数据之前,我们复制数据帧以保持原始源数据不变。

让我们回顾一下数字变量。

作者图片

我们观察负的量。这些肯定是产品退货或取消。我们需要删除他们的记录。

作者图片

在将数据集限制为正数之后,我们利用这个机会调整一些数据类型。

  • dt.date 方法从发票日期中删除时间部分。
  • Pandas 将客户 ID 解释为一个数字变量。让我们将其重新定义为对象/字符串类型。

作者图片

该数据集包含时间范围内的 4,339 个唯一客户 id 和 305 个发票日期。

发票号、库存代码和描述不能为我们的分析提供有意义的信息,因此我们将其删除。

“国家/地区”列可能有助于客户细分。但是,尽管数据集包含的记录数量相对较高,有 400,000 条,但它并没有覆盖很长的一段时间:只有 2 年。如果我们试图将它分散在 20 个不同的国家中——其中一些国家几乎没有客户和交易——我们会稀释我们分析的原材料,并冒着得到不太可靠的结果的风险。因此,我们也删除“国家”列,并将分析全球客户行为。

作者图片

为了确定交易的货币价值,以及随后所有客户的终身价值,我们通过将数量乘以相应的单价来插入一个新列“收入”。

作者图片

作者图片

作者图片

4.生命周期中的 RFM 模型:新*性、频率和货币价值

贝塔几何/负二项分布模型做出的预测依赖于 RFM 概念的度量:新*性、频率、货币价值和所谓的客户年龄或寿命。

提着纸袋走在街头的女人照片 Unsplash 上的自由女人形象Jon Ly

RFM 概念基于这样一个公理,即最*下订单、购买更频繁、倾向于在交易中花费更多的客户很可能是回头客,也是最有价值的客户。虽然这听起来像是一个不言自明的分类,但 RFM 概念提供了 BG/NBD 模型可以从中得出其预测的基础。BG/NBD 在 RFM 指标中增加了分布假设。

4.1 定义

  • 最*:客户第一次和最后一次(最*)交易之间的时间间隔
  • 频率:顾客初次购买后再次购买的时间段数
  • **货币价值:**客户交易的*均价值(每笔交易的收入或利润)

此外,

  • 客户年龄 T :客户第一次购买后的时间段数

寿命包将为我们计算这些值。为了理解它们的定义,让我们演示如何为一个选定的客户确定它们:ID = 14527。我们创建一个小型数据框架来保存客户的交易。

  • 顾客的“出生日期”2010 年 12 月 5 日是她第一次购买的发票日期。
  • 她最*一次购物是在 2011 年 12 月 7 日。
  • 包含所有客户的完整数据集,延伸至 2011 年 12 月 9 日。我们将此作为我们分析范围的结束日期。
  • 她的最*交易是她第一次和最后一次交易之间的天数:367 天。有点违背直觉,它没有计算她最*一次购物后的天数。
  • 她的年龄或寿命 T 是她“出生”——第一张发票——和我们 2011-12-09:369 天分析范围结束之间的天数。
  • 她的频率被定义为记录一次或多次重复购买的时间段数。这发生在第 53 天。第 18 行按照发票日期对数据集中的所有交易进行分组。然后减去 1,因为 RFT 和 BG/NBD 模型关注重复购买。它省略了初始事务。
  • 请注意,这个定义几乎肯定不同于你在其他领域所理解的频率。在其他地方,频率表示单位时间内发生的次数。我们的数据集由每日发票记录组成。但是模型不会将频率定义为每天或每月或每年的*均发票数量。相反,它只计算自第二张发票以来的交易天数。在某种程度上,该模型将“时间单位”定义为所有活动天(每当记录发票时)的总数,并将该人工时间单位设置为 1.0。这是一个特定于客户的时间单位,它忽略了客户不活动的所有日历日。

作者图片

作者图片

寿命包为客户 14527 计算的值与我们刚才计算的值相同。

为了在我们的应用程序中实现更全面的传统 RFM 分析,我们可以将最*值、频率值和货币值分成五个部分,即所谓的五分位数。客户可能在容器#2 中具有新*值,在容器#3 中具有频率值,在容器#4 中具有货币值。那么客户的 RFM 分数等于 234。最高分 555。这种方法可以作为营销团队的客户细分启发式方法,类似于供应链管理中的 ABC 库存分析。

RFM 的概念是在 40 年前开发的,那时数据科学和计算资源还没有为客户细分提供更先进的技术。我们将对英国天然气公司/NBD 公司使用 RFM 指标,但不尝试 RFM 评分。

网购服装 HutchRock 在 Pixabay 上的免费照片

4.2 训练和测试数据集的拆分

Lifetimes 使用术语校准保持期来表示我们在大多数其他应用中标记的训练测试数据集

其函数*calibration _ and _ holdout _ data()*将校准周期的所选结束作为其自变量;和观察期的结束。下面的笔记本单元格为维持期保留了数据集中的最后 240 天。它在第 7 行计算校准周期的结束日期 max_cal_date 。我们希望使用完整的数据集,无论如何,它不会覆盖许多时间段。因此,我们将 observation_period_end 设置为数据集中的最新日期。

请注意,校准周期和保持周期之间的划分可能会非常严格。这个特定的数据集包含 400,000 条记录,但它们分布在 4,000 多个客户中,覆盖时间仅为两年。许多小客户隔几个月就提交重复订单。如果我们将维持期设置为很少的时间段,那么它将只包含少量小客户的重复交易。我们的风险是,它没有完全反映他们的需求模式。我发现短于 100 天的抵制期在这种情况下效果不好。理想情况下,应该接* 200 天。然而,如果我们为抵制期预留了太多的天数,同样的问题也会困扰培训阶段:短至 365 天的培训期可能无法捕获足够多的客户特定交易来确定他们的需求模式。

最好是通过从整个数据集中随机抽取客户来创建维持数据集,然后检查定型数据集中客户的购买行为是否不同于维持客户的行为。但是,许多寿命评估函数将时间段 t 作为其参数,如果校准和维持交易在同一时间段重叠,则这些函数将不起作用,即使客户保持分离。

作者图片

calibration _ and _ holdout _ data()函数在训练数据集和测试数据集之间拆分数据集。同时,它计算每个客户的最*值、频率货币值、年龄 T 值。它创建一个新的数据帧,我们将其分配给变量 df_ch(“数据帧校准和保持”)。原始源数据 df1 是按照客户 ID 和发票号组织的;而 df_ch 使用唯一的客户 id 作为索引,并按客户汇总发票记录。

作者图片

下表显示了每个客户的*均频率(有效发票天数减 1)。大多数顾客只购买一次。请记住,频率为 0 表示客户没有重复交易—他刚刚完成了一次首次购买,但此后再没有回来。一小部分顾客会回来购买 6 次或更多次。这种模式凸显了我之前提到的困难:将数据集分为培训期和测试期,这两个时间段同样很好地反映了客户的需求模式,这些客户中的大多数人每隔几个月就会有一次从企业购买任何东西的适度冲动。

作者图片

为了形象化最*、频率和年龄 T 的模式,我们可以使用 Seaborn 的 distplots。

作者图片

我们再次观察到,在训练数据集涵盖的不到 1.5 年的时间里,只有少数客户会再次购买第二次或第三次产品。

作者图片

最*度衡量客户第一次交易和最*一次交易之间的天数。由于他们中的大多数是一次性购买者,我们认为峰值出现在 0 天。

作者图片

客户年龄 T 表示自购买者“出生”以来的天数,即他们作为企业新客户的第一天:从他们第一次购买开始,一直到数据集结束。大多数客户是在过去 120 天或更长时间内上船的。在 4 个月的短期内,图表显示了在 20 天、40 天、60 天或 80 天前进行首次购买的新客户的*均水*。该图表表明,企业并未发现自己处于下滑趋势。在 120 天的时间里,它以稳定的速度吸引了新客户。

5.贝塔几何/负二项分布(BG/NBD)模型

5.1 BG/NBD 概念

在非契约性的商业环境中,顾客的购买行为并不遵循确定性的趋势。需求水*和流失率都是随机变量。像 BG/NBD 这样的分布模型描述了影响顾客行为的随机过程,无论是个体行为还是总体行为。

该方法依赖四个分布假设来模拟不确定性:

  • 客户在一段时间内的订单数量遵循交易率为λ的泊松分布。这种泊松计数分布相当于假设交易之间的时间遵循具有相同交易速率λ的指数分布。
  • 客户之间的需求独立变化:λ的异质性。λ的变化是一个随机变量,遵循具有形状参数 r 和比例α伽马分布**。**
  • 在任何购买之后,客户可能以概率 p 变得不活跃,并且远离该业务。流失风险遵循几何分布
  • 客户之间的流失风险独立变化:p 的异质性。流失或退出概率 p 的变化是一个随机变量,遵循 Beta 分布。

C:JFMKSC -2MKSC0098。DVI(brucehardie.com)

负二项分布“NBD”是从哪里来的呢?是否涉及第五次分配?没有,上面的四个要点没有留下空隙。前两个假设结合起来形成泊松-伽马混合分布。如果λ率是伽马随机变量,那么混合分布等于一个负二项分布——维基百科。

5.2 将 BG/NBD 模型拟合到观测值

寿命包将观测数据与分布进行拟合,以获得它们的参数。

作者图片

作者图片

作者图片

plot_period_transactions 方法绘制一个图表,将训练数据集中的预测值与实际观察值进行比较。预测精度看起来相当不错。

寿命法plot _ calibration _ purchases _ vs _ holdout _ purchases将预测频率与测试期间的实际购买量进行比较。

作者图片

我们看到模型预测的橙色线与蓝色的实际线非常接*,每个客户最多有 3 笔交易。对于较高的交易水*,该模型倾向于低估频率,因为很少有客户在短训练时间窗口内重复购买 3 次以上。

6.完整数据集的血糖/NBD 模型

我们示例中的数据集涵盖了一个很短的时间段,大多数客户的交易很少。在回顾了第 5 章中的训练和测试结果后,我倾向于在完整数据集上重新运行模型。

6.1 RFM:新*性、频率、货币价值和寿命测试

我们使用寿命函数*summary _ data _ from _ transaction _ data()*来获得完整数据集中每个客户的 RFM 简档。该函数将它们收集在一个新的、以客户为中心的数据框架 df_rft 中。

作者图片

作者图片

6.2 拟合英国天然气公司/NBD 模型

我们将 Beta 几何/负二项分布模型拟合到 df_rft 中的完整数据集。

作者图片

为了检查预测的准确性,我们调用寿命的方法。该图表表明,该模型对购买数量的预测与实际观察结果非常接*。

作者图片

6.3 预计购买量

频率/最*矩阵可视化了客户档案中的这两个属性如何预测她在选定时间段内的购买次数。

我们将绘制两个矩阵,分别用于 10 天和 90 天的预测期。第 15 行中的列表理解向第 6 行中的寿命方法plot _ frequency _ recency _ matrix提供两个预测范围。

作者图片

作者图片

频率/最*矩阵都显示了 10 天和 90 天的概率分布的相同形状,在右下角有一个红色的热区。分布的形状保持不变。它们只是在右边的刻度上有所不同:在更长或更短的天数内的购买次数。

每个矩阵都表明,一个高频率(80 次或更多交易)的客户,加上一个长时间的最*交易(第一次和最*一次交易之间超过 300 天),将表现出最高的未来购买倾向:橙色到红色,这意味着在未来 90 天内有 15 到 25 次交易。

当然,尽管它看起来很吸引人,但用处有限。我们需要将视觉线索转化为针对单个客户的具体、量化的预测值。

让我们从数据集中随机挑选一个客户,例如 ID = 12748,并预测她在未来 30 天的购买量。

寿命预测功能评估客户的*期、频率和年龄;并得出结论,根据这个侧写,我们应该预计她在接下来的 30 天内会做 7.7 笔交易。

作者图片

下一个笔记本单元格将这个单一买家预测扩展到数据库中的所有客户。第 12 行中的列表理解询问 10、30、60 和 90 天内的预期购买量。它调用的助手函数, *predict_purch(),*会将其特定于客户的预测作为四个新列插入到 dataframe 中。

作者图片

接下来,我们可以根据这一预测对数据框架进行排序和筛选,例如,研究前 10 名客户,根据他们在未来 30 天内的预计购买次数进行排序。

作者图片

当然,Seaborn 的 distplot 显示了一个严重向右倾斜的分布。只有少数挥金如土的人有意向或有能力一个月下一次以上的订单。

作者图片

生命周期法probability _ of _ n _ purchases _ up _ to _ time计算一段时间内每个客户的*均交易次数。

作者图片

6.4 客户流失概率

在前一章中,我们已经预测了每个客户的购买量。在下一步中,我们将估计客户的流失风险,或者相反,估计她在时间 t 活着(作为客户)的概率。

“寿命”方法plot _ probability _ alive _ matrix根据客户的频率和最*概况可视化生存概率。一个客户的交易覆盖了很长一段时间(高新*性),有大量的交易,表现出一个坚实的,红色的生存概率。

作者图片

我们将视觉线索转化为指标,以获得可操作的信息。

函数conditional _ probability _ alive计算每个客户的生存概率。我们将数组作为新列插入到数据帧中。

其描述性统计数据显示,鉴于当前的*期/频率特征,最不可靠的客户的生存概率仍高达 75%。

作者图片

只有少数客户的存活率低于 99%。如果我们将分析局限于不完全可靠的候选人,即存活率低于 90%的候选人,我们会发现四个客户。

作者图片

让我们检查客户 ID 15107,评级为 75%。

寿命法 plot_history_alive 向我们展示了客户的交易和她存活的概率在 2 年的观察中是如何发展的。她在最初几个月完成了五次购买,但在 2011 年 3 月至 12 月期间一直没有行动。该模型仍然认为她有 75%的可能是一个活跃的客户,因为我们的数据集包含许多在 10 个月的过程中只是稍微活跃一些的客户。具有更多活跃客户的不同数据集,这些客户倾向于每月或每周订购一些东西,这将促使模型降低数月不活跃的客户的概率。

作者图片

作者图片

7.客户终身价值

电子商务在线销售 Mediamodifier 在 Pixabay 上发布的免费照片

7.1 伽玛-伽玛模型

BG/NBD 模型使我们能够预测每个客户的交易数量和流失风险(相反,是存活的概率)。

现在我们要估计与计数数据相对应的货币值。我们将把血糖/NBD 结果链接到伽玛-伽玛模型中。

GG 模型基于以下假设

  • 顾客的*均交易价值各不相同:例如,一些挥金如土的人可能倾向于在每笔交易中花费两倍于其他人的金额
  • 单个客户的*均货币交易额在分析区间内不随时间变化;客户交易的价值围绕*均值变化,而*均值本身随着时间的推移保持稳定

时不变的*均交易值是我们想要确定的随机变量 Z。

1994 年,Schmittlein 和 Peterson 提出交易值遵循正态分布。但是正态分布延伸到负无穷大,并且围绕其均值对称——而现实世界的支出频率曲线是非负的,并且是右偏的,这一点通常很明显。Fader/Hardie 建议将 Gamma 分布作为反映客户*均交易价值的更合适的替代方法。他们将其比例参数定义为自己的伽马随机变量,因此标签为伽马-伽马模型。(γ_γ。DVI (brucehardie.com))

利用贝叶斯定理,他们推导出客户*均交易价值的条件期望值。观察到的交易越多,模型对先验分布的权重就越小,而对客户的观察均值的权重就越大。

GG 模型只适用于正的货币价值。因此,我们排除了单价为零的少数交易。

作者图片

GG 模型还要求购买频率独立于其货币价值。相关矩阵证实,在我们的例子中,皮尔逊相关系数达到适度的 0.016,足够低,我们将继续进行。

作者图片

7.2 根据 RFT 数据拟合伽马-伽马模型

我们实例化 Lifetimes 'gamma gamma fitter,它将 BG/NBD 模型的频率和货币值作为其参数。

作者图片

7.3 GG 预测

在拟合 GG 模型后,我们可以使用寿命函数计算每个客户的预期货币价值。我们的源数据集不提供利润率,因此该函数,尽管其名称如此,返回预期的*均收入

我们将结果作为一个新列“exp_avg_rev”插入到我们的数据框架中,同时插入预测*均收入和实际*均货币值之间的差异。

作者图片

7.4 客户终身价值 CLV

在我们的最终代码单元中,我们将再次将血糖/NBD 结果与拟合的伽马-伽马模型联系起来。

  • 顾客的寿命代表了她第一次购买和观察数据结束日期之间的时间段。
  • 同样,客户的“一生”指的是从她第一次交易到她未知的未来客户流失日期的时间,那时她将离开我们的业务。出于实际目的,应该将“生命周期”范围限制在用户定义的时间段内,例如下面第 3 行中我设置为超参数的未来 12 个月。

lifetimes ' customer _ lifetime _ value 函数将在所选的 12 个月期限内累加预测收入。

客户终身价值是贴现现金流(DCF)计算的结果。它基于货币的时间价值概念。一笔钱在*期比远期更有价值。我们现在赚的钱,我们可以立即投资,并开始产生利息或股息。一个现在就有收益流入企业的客户比一个在更遥远的未来贡献收入的客户更有价值。金钱的时间价值由 customer_lifetime_value 函数向我们请求的贴现率来表示。折扣应该反映我们公司的资本成本:加权*均

  • 公司所欠贷款的利率
  • 公司股东期望获得的股本回报率(股息率)。

这两个比率应根据股东和贷款人对公司资产负债表的出资额进行加权。

在这个例子中,我在第 2 行设置了 6%的低年利率。请注意,Lifetimes 实际上期望的是贴现率。第 5 行将年利率转换为月利率。

customer_lifetime_value 函数采用我们从 BG/NBD 函数*summary _ data _ from _ transaction _ data:*recency、frequency、lifetime T 和 monetary value 中获得的所有四个指标。

它返回一个客户终身价值的数组,每个客户一个,我们将它作为一个新列“CLV”插入到我们的数据帧中。

作者图片

所有客户的*均 CLV 为 2,847。

当我们根据客户价值对数据框架进行排序时,我们可以看到我们的前 5 名客户,他们的终身价值超过 100,000 英镑—显然是批发商;或者极度热衷于纪念品和礼物的私人消费者。

作者图片

8.结论

我们通常用于解决客户流失问题的大多数分类工具并不能很好地处理非合同环境。非合同商业环境中的流失日期是不透明的。

BG/NBD 模型将分布假设应用于观察数据。它使我们能够根据客户的新*度、频率和寿命来评估客户流失风险和未来购买。在第二步中,可以将 BG/NBD 模型的计数数据链接到估计货币值的伽马-伽马模型。

Jupyter 笔记本可在 GitHub 上下载: h3ik0th/clv:客户终身价值 BG/NBD 模型(github.com)

数据集:在线零售。(2015).UCI 机器学习知识库。 UCI 机器学习知识库。该数据集根据知识共享署名 4.0 国际版(CC BY 4.0)许可协议进行许可。这允许为任何目的共享和改编数据集,只要给予适当的信任。

拜拜 PowerPoint。你好,马普!

原文:https://towardsdatascience.com/bye-bye-powerpoint-hello-marp-3c0e3b3198b1?source=collection_archive---------1-----------------------

这个免费的基于 Markdown 的工具能取代 PowerPoint 吗?是的,但是有一个条件。

亚历克斯·利特温在 Unsplash 上的照片

你觉得 PowerPoint 很烦人吗?我也是。它有时会滞后,并且有大量的选项。如果你想买更简单的东西,今天是你的幸运日。Marp 可能是节省你时间和精力的正确工具。

它是基于 Markdown 的 Visual Studio 代码扩展,允许您创建可以导出为 PPTX、PDF 和 HTML 的演示文稿。今天,你将学习基础知识,并创建你的第一个演示文稿。

不想看书?请观看我的视频:

如何安装 Marp

你应该已经安装了 Visual Studio 代码。这是一个代码编辑器,可以让你写任何东西,从自述文件到机器学习模型。如果你不把 Markdown 算作代码,你今天就不会写代码,这是不应该的。

一旦进入 Visual Studio 代码,点击扩展选项卡并搜索 Marp :

图 Visual Studio 代码中的 Marp(图片由作者提供)

点击安装按钮,几秒钟后就可以运行了。然后在机器上的任意位置创建一个文件夹,并在 VSCode 中打开它。

我将我的文件命名为marp_slideshow,并在其中创建了一个slideshow.md文件。你可以根据自己的喜好随意更改名字。

就这样,您现在可以开始制作您的第一张幻灯片了。

Marp:创建您的第一张幻灯片

你有打开的slideshow.md文件吗?很好。继续样板文件。您必须指定您使用的是 Marp,因为 Markdown 文档在默认情况下不知道它:

---
marp: true
---

让我们在下面添加一个 H1 标签,这样屏幕上就有东西可看了:

# Slide 1 Title

您现在可以点击预览图标查看您的演示文稿:

图 2 — Marp 预览窗口(图片由作者提供)

到目前为止,一切顺利。让预览窗口开着——它会在你写的时候自动更新。

您还可以更改演示主题:

---
marp: true:
theme: gaia
---

图 3 —改变主题(作者图片)

我不太喜欢黄色,所以稍后我会告诉你如何改变它。

您可以按 CTRL + SPACE 列出所有可用的属性。其中两个是authorsize,所以我们来调整一下:

---
marp: true:
theme: gaia
author: Dario Radečić
size: 4:3
---

图 4 —更改比率(作者图片)

您可以看到我们是如何从 16:9 提高到 4:3 的宽高比的,但这是个人偏好的事情。

添加内容

接下来,让我们看看如何使用 Markdown 向幻灯片添加内容。下面的代码片段增加了两个要点。第二个有子元素,每一个都有不同的样式。这些向您展示了如何加粗、斜体和预格式化您的文本:

# Welcome to MARP
- It's an awesome VSCode extension for making presentations.
- It's based on Markdown:
  - **Bold**
  - _Italic_
  - `code`

*简单,对吧?*现在一切应该是这样的:

图 5 —向幻灯片添加内容(作者提供的图片)

您可以通过键入---来创建新的幻灯片。

让我们给第二张幻灯片添加一张图片。我在维基共享资源上找到一个展示神经网络的,但是你可以自由使用其他的。

以下代码片段将标题、项目符号和图像添加到幻灯片中:

# Welcome to Slide 2
- This is a neural network:

![A neural network](https://upload.wikimedia.org/wikipedia/commons/3/3d/Neural_network.svg)

它应该是这样的:

图 6 —向幻灯片添加图像(作者提供的图像)

今天让我们保持事情简单,所以我们将在这里停止与内容。接下来,我将向您展示如何定制演示文稿的风格。

Marp:设计你的演示文稿

您可以通过添加样式表来自定义 MARP 演示文稿,但是这需要基本的 CSS 知识。您可能想回到文档的开头,打开 CSS 样式标签:

<style>
</style>

然后,您可以通过编辑 CSS 变量来自定义颜色。例如,下面是如何更改文本和背景颜色:

<style>
    :root {
        --color-background: #101010 !important;
	--color-foreground: #FFFFFF !important;
    }
</style>

你的演示会突然得到一个阴暗的主题:

图片 7 —设计 Marp 演示文稿(1)(图片由作者提供)

你也可以改变字体。例如,下面的代码片段将所有标题 1 元素设置为等宽字体:

h1 {
    font-family: IBM Plex Mono;
}

图片 8 —设计 Marp 演示文稿(2)(图片由作者提供)

这是一个自定义字体,所以如果你没有安装的话就用Courier New吧。您可以根据自己的喜好设计任何其他元素的样式——唯一的限制因素是您的 CSS 知识。

最后,我想向您展示如何导出演示文稿。

Marp:导出演示文稿

您可以将演示文稿存储为 PowerPoint 文档、PDF 文件或 HTML。PNG 和 JPG 选项确实存在,但它们只会导出第一张幻灯片。

以下是开始导出的方法:

图 9 —导出演示文稿(作者图片)

我会将它保存为 PDF 和 Powerpoint 演示文档。

让我们现在打开 PDF 来验证导出是否成功:

图 10-Marp PDF 导出(图片由作者提供)

一切看起来都很好,接下来让我们检查 PPTX:

图 11 — Marp PPTX 导出(图片由作者提供)

PowerPoint 文档会打开,但您不能对幻灯片做任何操作。你不能修改文本或图像,所以这可能是一个潜在的障碍。

这就足够了。接下来让我们总结一下。

判决

总之,对我来说,Marp 看起来像是一个可行的 PowerPoint 替代品,因为编写和编辑 Markdown 文档很容易,而且它不会让你不知所措。不要误解我的意思,有选项没有错,但是我用幻灯片做的大部分事情都相对简单。

我几乎从不在演示文稿中添加动画和过渡,我总是将其保存为 PDF 文档。pdf 更容易分享和打开,因为你不需要启动一个资源密集型应用程序。此外,PowerPoint 有时会滞后,这是我不想处理的另一个问题。

如果你需要 Powerpoint 提供的所有功能,那么 MARP 对你来说可能太简单了。

你对 Marp 有什么看法?你认为它是一个可行的 PowerPoint 替代品吗,或者它的功能对于你的需求来说太基本了?请在下面的评论区告诉我。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

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

保持联系

  • 注册我的简讯
  • 订阅 YouTube
  • 在 LinkedIn 上连接

ByT5:通过预先训练的字节到字节模型走向无令牌的未来

原文:https://towardsdatascience.com/byt5-towards-a-token-free-future-with-pre-trained-byte-to-byte-models-3638791a44b2?source=collection_archive---------37-----------------------

NLP 研究论文摘要

作者图片

在这篇博客中,我试图根据我的理解,用预先训练好的字节到字节模型 来总结论文 ByT5:迈向一个无令牌的未来。请随时评论你的想法!

想法

迄今为止,大多数 NLP 研究广泛使用了记号赋予器的概念来将文本序列分成更小的词汇单元。如今,你会发现子词标记化是人们用来表示文本单元的事实上的技术,(在过去的某个时候是单字,双字)

考虑到这些方法的局限性,其中一些是—

  • 处理 OOV 时不够稳健
  • 拼写、大小写等方面的变化导致了不同的表示

作者提出的无令牌模型直接在原始文本(字节)上操作**,给我们带来了下面提到的好处——**

  • 他们可以处理任何语言的文本。我们需要而不是需要特定于语言的标记器。您只需要一个标记器!】
  • 它们对噪声具有很强的鲁棒性,并最大限度地减少了复杂文本预处理管道的麻烦。
  • 我们现在不需要庞大的词汇矩阵作为字节级模型,根据定义,只需要 256 个嵌入。

mT5(薛等,2020)和 ByT5(本作品)的训练前实例创建和网络架构比较|图片来自来源

虽然,字节级模型的主要缺点之一是字节序列通常比原始文本序列长,导致处理成本较高。众所周知,变形金刚中的自我关注是一种二次计算,当试图处理越来越长的序列时,这种计算会带来巨大的挑战。话虽如此,我们确实有进步,如 Longformer 等,它们利用稀疏注意力和其他巧妙的技术来处理非常大的序列。

mT5 与 ByT5 —设计

  1. mT5/ T5 使用子字标记,而 ByT5 使用原始字节作为模型的输入,这使得不知道文本预处理的类型,等等。
  2. mT5/T5 使用跨度掩蔽的概念作为在大量未标记数据上预先训练模型的自我监督目标。ByT5 通过屏蔽字节使用类似的概念。此外,mT5 *均屏蔽掉 3 个子字标记,这里作者发现更长的屏蔽序列有利于模型,因此他们将其*均屏蔽跨度长度设置为 20 字节。
  3. mT5/T5 使用所谓的“*衡架构”*(编码器深度= =解码器深度),然而,byT5 的作者发现,当编码器深度几乎是解码器深度的 3 倍时,它工作得最好,从而使整个架构编码器很重。此外,即使在降低解码器的容量后,他们发现该模型在分类和生成(翻译/摘要)*任务上表现更好。

此外,作为质量控制协议,由于根据 UTF-8,并非所有的字节序列都是合法的,因此作者通过使用 python 的字节解码函数—. bytes . decode(" utf-8 ",errors="ignore") 来删除任何无效的序列

技术性能分析

  1. 通常,词汇表中每个标记的向量表示采用模型总参数空间中的大多数参数。例如,在最*的 mT5-Base 模型中,词汇和 softmax 输出矩阵占总参数计数的 66%。对于字节模型,由于不会出现这种情况,如果我们要补偿大的模型参数计数,我们可以通过使我们的模型更深更宽来实现它,通过拥有更复杂的模型来给我们带来优势。
  2. 与使用单词或子单词标记化方案相比,给定文本片段的字节序列通常更长。因此,你会有明显较高的计算成本,因为变压器使用自我关注,具有二次时间复杂度。

结果

摘要文本摘要*(英语)*

他们在 XSum 数据集上评估 mT5 和 ByT5 来进行抽象文本摘要。正如您在下表中看到的,对于所有大小的变体,ByT5 都优于 mT5,并且接*专门为抽象概括而训练的Pegasusmodel*(17.0)*。

GEM-XSUM |图片来自来源

文本分类(英语)

他们评估了 mT5 和 ByT5 在不同模型尺寸下在粘合强力胶任务上的表现。正如我们在下表中看到的,仅在小型和基本型号中,ByT5 的性能优于 mT5。作者解释说,这可能是由于有效的参数使用,因为大多数 mT5 参数只是作为词汇表矩阵被锁定。

mT5 和 ByT5 在胶水和强力胶上不同型号的性能|图片来自来源

正如您在下表中看到的,在固定参数计数设置下,随着模型大小的增加,两个模型的 dmodeldff 变得可比,这与模型大小较低时不同。这是上表所示行为的可能原因。

mT5 和 ByT5 架构的比较|图片来自来源

好了,这篇博客到此为止。论文中提到了更多的实验。我鼓励你也阅读它们。

如果你愿意,你也可以 查看我写的其他研究论文摘要

请随意阅读整篇论文,并向作者问好,感谢他们的贡献。

论文标题: ByT5:用预先训练好的字节到字节模型走向无令牌的未来

论文链接:https://arxiv.org/pdf/2105.13626v1.pdf

作者: 【林挺】薛,阿迪雅巴鲁阿,诺亚恒,拉米阿尔-Rfou ,莎兰纳朗,米希尔卡莱, Adam Roberts ,科林·拉斐尔

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

字节对编码:基于子字的标记化算法

原文:https://towardsdatascience.com/byte-pair-encoding-subword-based-tokenization-algorithm-77828a70bee0?source=collection_archive---------2-----------------------

了解最新的 NLP 模型使用的基于子词的符号化算法——字节对编码(BPE)

照片由克拉克在 Unsplash 上拍摄

人工智能的分支**【自然语言处理(NLP)** ,就是让机器理解和处理人类语言。对于机器来说,处理人类语言不是一件容易的事情,因为机器处理的是数字而不是文本。💻NLP 是人工智能的一个如此巨大和广泛研究的分支,我们不时听到这个领域的新进展。研究人员正在努力让机器理解人类语言及其背后的语境。

在理解人类语言的过程中,一个主要的角色是由标记化者扮演的。标记化算法可以是基于单词、子单词或字符的。每种类型的分词器帮助机器以不同的方式处理文本。两者各有优势。如果您想了解 NLP 中使用的不同类型的记号赋予器,那么您可以阅读这篇文章。这篇文章是关于 TDS 的实践教程,可以让你很好地理解这个主题。😇

这些分词器中最流行的是基于子词的分词器。大多数最新的 NLP 模型都使用这个标记器。因此,让我们首先了解什么是基于子词的记号赋予器,然后理解最新的 NLP 模型使用的字节对编码(BPE)算法。🙃

基于子词的标记化

基于子词的标记化是介于基于词和基于字符的标记化之间的一种解决方案。😎主要思想是解决基于单词的标记化(非常大的词汇量,大量的 OOV 标记,以及非常相似的单词的不同含义)和基于字符的标记化(非常长的序列和不太有意义的单个标记)所面临的问题。

基于子词的记号化算法不会将频繁使用的词分成更小的子词。而是将生僻的单词拆分成更小的有意义的子单词。例如,“男孩”不是分裂的,而是“男孩”分裂为“男孩”和“s”。这有助于模型了解单词“boys”是使用单词“boy”形成的,单词“boy”的意思略有不同,但词根相同。

一些流行的子词标记化算法是单词块、字节对编码(BPE)、Unigram 和句子块。在本文中,我们将讨论字节对编码(BPE)。BPE 用于语言模型,如 GPT-2,罗伯塔,XLM,福楼拜等。这些模型中的一些使用空间标记化作为预标记化方法,而一些使用由 Moses、spaCY、ftfy 提供的更高级的预标记化方法。那么,我们开始吧。🏃

字节对编码(BPE)

BPE 是一种简单的数据压缩算法,在这种算法中,最常见的一对连续数据字节被替换为该数据中不存在的字节。在 1994 年发表的文章“一种新的数据压缩算法中首次对其进行了描述。下面的例子将解释 BPE,并取自维基百科。

假设我们有需要编码(压缩)的数据**。字节对 aa 出现的频率最高,因此我们将使用 Z 替换它,因为 Z 在我们的数据中没有出现。所以我们现在有了 ZabdZabac 其中 Z = aa 。下一个公共字节对是 ab ,所以让我们用 Y 来代替它。我们现在有了 ZYdZYac 其中 Z = aaY = ab 。唯一剩下的字节对是 ac ,它看起来只有一个,所以我们不会对它进行编码。我们可以使用递归字节对编码将 ZY 编码为 X 。我们的数据现在已经转换为 XdXac ,其中 **X = ZY,Y = ab,Z = aa 。它不能被进一步压缩,因为没有字节对出现超过一次。我们通过以相反的顺序执行替换来解压缩数据。

NLP 中使用了它的一个变体。让我们一起来了解一下它的 NLP 版本。🤗

BPE 确保最常见的单词在词汇表中被表示为单个记号,而不常见的单词被分解为两个或多个子单词记号,这与基于子单词的记号化算法所做的是一致的。

假设我们有一个语料库,其中包含单词(在基于空间的预标记化之后)——old、old、high 和 lowest,我们计算这些单词在语料库中的出现频率。假设这些词的频率如下:

{“老”:7,“老”:3,“最好”:9,“最低”:4}

让我们在每个单词的末尾添加一个特殊的结束标记“”。

{ "老< /w > ": 7,"老< /w > ": 3,"最细< /w > ": 9,"最低< /w > ": 4}

在每个单词的末尾添加“”标记来标识单词边界,以便算法知道每个单词的结束位置。这有助于算法检查每个字符,并找到频率最高的字符对。当我们将在字节对中包含“”时,我将详细解释这一部分。

接下来,我们将把每个单词拆分成字符,并计算它们出现的次数。初始标记将是所有字符和“”标记。

由于我们总共有 23 个单词,所以我们有 23 个“”记号。第二高频率的标记是“e”。我们总共有 12 种不同的代币。

BPE 算法的下一步是寻找最频繁的配对,合并它们,并一次又一次地执行相同的迭代,直到我们达到我们的令牌限制或迭代限制。

合并可以让你用最少的符号来表示语料库,这是 BPE 算法的主要目标,也就是压缩数据。为了合并,BPE 寻找最频繁出现的字节对。这里,我们认为一个字符和一个字节是一样的。这是英语中的一种情况,在其他语言中可能有所不同。现在,我们将最常见的 bye 对合并成一个标记,并将它们添加到标记列表中,并重新计算每个标记的出现频率。这意味着我们的频率计数将在每个合并步骤后改变。我们将继续进行这个合并步骤,直到达到迭代次数或达到令牌限制大小。

迭代次数

迭代 1: 我们将从第二常见的标记“e”开始。在我们的语料库中,带有“e”的最常见的字节对是“e”和“s”(在单词 finest 和 lowest 中),它们出现了 9 + 4 = 13 次。我们将它们合并形成一个新的标记“es ”,记下它的频率为 13。我们还将从单个令牌(“e”和“s”)中减少计数 13。这将让我们知道剩余的“e”或“s”令牌。我们可以看到“s”根本没有单独出现,“e”出现了 3 次。以下是更新后的表格:

迭代 2: 我们现在将合并标记“es”和“t”,因为它们在我们的语料库中出现了 13 次。因此,我们有一个频率为 13 的新令牌“est ”,我们将把“es”和“t”的频率减少 13。

迭代 3: 现在让我们使用“< /w >”令牌。我们看到字节对“est”和“< /w >”在我们的语料库中出现了 13 次。

**注意:**合并停止令牌“< /w >”非常重要。这有助于算法理解“估计”和“最高”这样的词之间的区别。这两个单词都有“est”这个词,但是一个在末尾有一个“est”标记,一个在开头。因此,像“est”和“est < /w >”这样的标记将被不同地处理。如果算法将看到标记“est < /w >”,它将知道这是单词“最高”的标记,而不是单词“房地产”的标记。

迭代 4: 查看其他标记,我们看到字节对“o”和“l”在我们的语料库中出现了 7 + 3 = 10 次。

迭代 5: 我们现在看到字节对“ol”和“d”在我们的语料库中出现了 10 次。

如果我们现在查看我们的表格,我们会看到“f”、“I”和“n”的频率是 9,但我们只有一个包含这些字符的单词,所以我们没有合并它们。为了本文的简单起见,现在让我们停止迭代,仔细看看我们的令牌。

频率计数为 0 的令牌已从表中删除。我们现在可以看到,令牌总数是 11,比我们最初的 12 少。这是一个小语料库,但在实践中,大小减少了很多。这 11 个单词的列表将作为我们的词汇表。

您一定也注意到了,当我们添加一个令牌时,我们的计数要么增加,要么减少,要么保持不变。实际上,令牌计数先增加后减少。停止标准可以是令牌计数或迭代次数。我们选择这个停止标准,以便我们的数据集可以以最有效的方式分解成记号。

编码和解码

现在让我们看看我们将如何解码我们的例子。为了解码,我们必须简单地将所有的标记连接在一起以得到整个单词。例如,编码序列["the 、" high "、" est 、" range 、" in 、" Seattle],我们将被解码为["the "、" high "、" range "、" in "、" Seattle"],而不是["the "、" high "、" enever "、" in "、" Seattle"]。请注意“est”中出现了“”标记。

对新数据进行编码的过程也很简单。然而,编码本身在计算上是昂贵的。假设单词的顺序是[“最”、“最高、“范围”、“在、“西雅图”]。我们将遍历我们在语料库中找到的所有标记——从最长到最短,并尝试使用这些标记替换给定单词序列中的子字符串。最终,我们将遍历所有的令牌,我们的子字符串将被替换为令牌列表中已经存在的令牌。如果还剩下一些子字符串(对于我们的模型在训练中没有看到的单词),我们将用未知的标记来替换它们。

一般来说,词汇量很大,但仍然有可能是一个未知单词。在实践中,我们将预先标记的单词保存在字典中。对于未知(新)单词,我们应用上述编码方法来标记新单词,并将新单词的标记添加到我们的词典中以供将来参考。这有助于我们为将来积累更丰富的词汇。

**不是贪心吗?**🤔

为了以最有效的方式表示语料库,BPE 通过查看其频率,在每次迭代中检查每个潜在的合并选项。所以,是的,它遵循一个贪婪的方法来优化最佳可能的解决方案。

不管怎样,BPE 是使用最广泛的子分词算法之一,尽管它很贪婪,但它有很好的性能。💃

我希望这篇文章能帮助你理解 BPE 算法背后的思想和逻辑。😍

参考文献:

  1. 【https://aclanthology.org/P16-1162.pdf
  2. https://huggingface.co/transformers/tokenizer_summary.html
  3. https://www . drdobbs . com/a-new-algorithm-for-data-compression/184402829
  4. https://en.wikipedia.org/wiki/Byte_pair_encoding

感谢大家阅读这篇文章。请分享您宝贵的反馈或建议。快乐阅读!📗 🖌

字节字符串、Unicode 字符串、原始字符串 Python 中所有字符串的指南

原文:https://towardsdatascience.com/byte-string-unicode-string-raw-string-a-guide-to-all-strings-in-python-684c4c4960ba?source=collection_archive---------3-----------------------

区别,用法,Python 对 NumPy 对熊猫?

在 Unsplash 上由 Hitesh Choudhary 拍摄的照片

Python 中的“字符串”?听起来像是每个 Python 程序员在他们的第一个 Python 教程中应该已经掌握的最基本的主题。然而,你知道在原始 Python 中至少有四种类型的字符串吗?你知道你的字符串实际上是如何在 Numpy 或 Pandas 或任何其他包中表示的吗?我需要知道哪些区别和注意事项?(见下文)

在这里,让我根据自己的学习经历,试着为你澄清一些困惑。我们将讨论以下主题:

  1. 「编码」和「解码」是什么概念?
  2. 什么是 raw(r)字符串或 format(f)字符串,何时应该使用它们?
  3. Numpy/Pandas 字符串和原始 Python 字符串有什么区别?

字节字符串和 Unicode 字符串(默认的 Python3 字符串)——都是关于编码的

要理解字节串和 Unicode 串的区别,我们首先需要知道什么是“编码”和“解码”。

编码和解码(图片由作者提供)

为了在计算机上存储人类可读的字符,我们需要将它们编码成字节。相比之下,我们需要将字节解码成人类可读的字符来表示。在计算机科学中,字节表示 0/1 的单位,通常长度为 8。所以字符“Hi”在计算机上实际上是以“01001000 01101001”的形式存储的,消耗 2 个字节(16 位)。

定义编码过程的规则称为编码模式,常用的有“ASCII”、“UTF-8”等。现在,问题是这些编码模式看起来怎么样?

" ASCII "将每个字符转换成一个字节。因为一个字节由 8 位组成,每一位包含 0/1。“ASCII”能代表的字符总数是 2⁸=256.26 个英文字母加上一些常用字符绰绰有余。完整信息见“ASCII”表。

但是,256 个字符显然不足以存储世界上所有的字符。有鉴于此,人们设计了 Unicode 码,其中每个字符将被编码为一个“代码点”。例如,“H”将被表示为代码点“U+0048”。根据维基百科,Unicode 可以包含 144697 个字符。但是,代码点仍然不能被计算机识别,所以我们有“ UTF-8 ”或其他变体编码模式来将代码点转换为字节。“UTF-8”是指表示一个字符的最小比特长度是 8,所以你可以猜测,“ UTF-16 是指最小比特长度是 16。UTF-8 比 UTF-16 更受欢迎,所以在本文和你的大部分工作中,因为它们与旧的原始 ASCII 标准兼容(一个字符可以用一个字节表示),理解 UTF-8 就足够了。完整信息见“UTF-8”表。

了解了基本概念后,让我们来看看 Python 中一些实用的编码技巧。在 Python3 中,默认的字符串叫做 Unicode string (u string) ,你可以把它们理解为人类可读的字符。如上所述,您可以将它们编码成字节字符串(b 字符串),字节字符串可以解码回 Unicode 字符串。

u'Hi'.encode('ASCII')
> b'Hi'b'\x48\x69'.decode('ASCII')
> 'Hi'

在 Python IDE 中,通常,在打印输出时,字节字符串会使用“ASCII”自动解码,所以这就是为什么第一个结果是人类可读的(b'Hi ')。更多的时候,字节串应该用十六进制代码(b'\x48\x69 ')表示,可以在任何“ASCII”表中找到。

为了总结这一节,让我们看一个“UTF-8”的例子,同样每个字符的十六进制代码可以在 UTF-8 表中找到:

b'\xe0\xb0\x86'.decode('utf-8')
> 'ఆ'

原始字符串

从这种类型的字符串开始,我们只需要知道关于默认 Unicode 字符串(u string)的一件事——反斜杠(" \ ")是 Unicode 字符串中的一个特殊字符,这样后面的字符将具有特殊的含义(即\t,\n 等)。所以为了忽略反斜杠的特殊含义,我们有了 Raw string (r string) ,其中反斜杠只是一个反斜杠,它不会对改变其后面字符的含义产生影响。

Unicode 和原始字符串(图片由作者提供)

下面是我个人的建议,除非在需要定义正则表达式匹配模式的场景下(见下面的例子),我建议使用带转义的 Unicode 字符串(使用反斜杠忽略特殊字符)。如第三个示例所示,我们使用反斜杠来确保我们输出的是文字“\”而不是新的制表符“\t”。

为什么我会推荐这个?这是因为原始字符串不能真正解决所有问题,例如,如何在原始字符串中输出文字单引号?

r'ttt'g''File "<ipython-input-76-2839752ff4e6>", line 1
    r'ttt'g''
          ^
SyntaxError: invalid syntax

然而,将转义思想与 Unicode 字符串一起使用似乎是一种更通用的方法:

u'ttt\'g\''> "ttt'g'"

Raw string (r string)唯一有用的地方是当你处理正则表达式的时候。正则表达式是一个复杂的问题,我不打算在本文中讨论它。但是当使用正则表达式时,我们通常需要首先定义一个匹配的模式,其中推荐原始字符串。

import re
pat = re.compile(r'ENSG\d+$')
string = 'ENSG00000555'
re.search(pat,string)<_sre.SRE_Match object; span=(0, 12), match='ENSG00000555'>

格式字符串

对于有经验的 Python 程序员来说,格式字符串应该不是一个陌生的概念,它允许你动态配置我们想要打印的字符串。在 Python 版之前,创建格式字符串的推荐方法如下:

var = 'hello'
print('{} world'.format(var))> hello world

从 Python 3.5 和更高版本开始,有一个新的" f 字符串来帮助我们实现同样的目标:

var = 'hello'
print(f'{var} world')> hello world

这里我要注意的重要一点是,当使用格式字符串时,花括号“”变成了一个非常特殊的字符,包含了它独特的含义。因此,如果我们的目标仍然是输出文字“”,我们需要使用双花括号“{ }”对其进行转义:

'{{}}{}'.format(5)> '{}5'

此外,还要注意格式字符串中的\1(或反斜杠后的其他数字):

# Make sure to write the command in a python file and execute the python file
'ttt {} \1'.format('rr')
> ttt rr 
'ttt {} \\1'.format('rr')
> ttt rr \1

请注意,在上面的代码中,输出是通过运行 python 文件生成的,如果您使用交互式 Python 控制台,这将会令人困惑,因为输出实际上会自动编码为字节:

# if using interactive python console
'ttt {} \1'.format('rr')
> 'ttt rr \x01'
'ttt {} \\1'.format('rr')
> 'ttt rr \\1'

最后但同样重要的是,可以使用rf string,其中我们希望为正则表达式构造一个原始字符串,但我们希望在其中包含一些变量:

v1 = 3
pattern = re.compile(rf'^E{v1}\.{v1+1}$')

串起熊猫和熊猫

到目前为止,我们讨论的都是 Python 中的原始字符串类型,我们还没有涉及到在其他流行的 Python 包中如何处理字符串。在这里,我将分享一些 Numpy 和 Pandas 中的字符串类型。

在 Numpy 中,通常可以用三种不同的“数据类型”来指定字符串:

  1. 可变长度 Unicode (U)
  2. 固定长度字节
  3. Python 对象(O)
import numpy as np
arr1 = np.array(['hello','hi','ha'],dtype='<U5')
arr2 = np.array(['hello','hi','ha'],dtype='|S5')
arr3 = np.array(['hello','hi','ha'],dtype='object')> array(['hello', 'hi', 'ha'], dtype='<U5')
> array([b'hello', b'hi', b'ha'], dtype='|S5')
> array(['hello', 'hi', 'ha'], dtype=object)

<U5表示最长的是一个长度为 5 的字符串,然而,一个更节省内存的方法是使用固定长度的|S5,它本质上是将它们转换成字节字符串。如果您试图将其转换为强类型数据结构(即存储为 h5 文件),这是首选方式。此外,我们可以将字符串视为 Python 对象,并将它们存储在 Numpy 数组中,因为每个 Python 对象都可以使用“object”类型存储在 Numpy 数组中。

熊猫身上的弦可以用两种方式来表示:

  1. 对象数据类型(大多数时候应该没问题)
  2. 字符串数据类型
import pandas as pd
s1 = pd.Series(['hello','hi','ha'],dtype='object')
s2 = pd.Series(['hello','hi','ha'],dtype='string')> s1
0    hello
1       hi
2       ha
dtype: object> s2
0    hello
1       hi
2       ha
dtype: string

这两种类型大体相似,细微的差别在文档中有所概述。

结论

总之,我们讨论了 Python 中“字符串”的不同表示。从默认的 **Unicode 字符串(u 字符串)开始,我们讨论了它与字节字符串(b 字符串)**的关系。理解这种转换非常重要,因为有时来自其他程序的标准输出将是字节格式,我们需要首先将它们解码为 Unicode 字符串,以便进行进一步的流操作。然后我们谈到了 Raw string (r string)Format string (f string) 以及使用它们时需要注意的事项。最后,我们总结了 Numpy 和 Pandas 中字符串表示的不同方式,在用 string 实例化 Numpy 或 Pandas 对象时应该特别小心,因为它们的行为与原始的 Python 字符串有很大的不同。

差不多就是这样!我希望你觉得这篇文章有趣和有用,感谢阅读!如果你喜欢这篇文章,请在 medium 上关注我,非常感谢你的支持。在我的 Twitter 或 LinkedIn 上联系我,也请让我知道你是否有任何问题或你希望在未来看到什么样的教程!

C++基础:数组数据结构

原文:https://towardsdatascience.com/c-basics-array-data-structure-c25b8ad4d32c?source=collection_archive---------16-----------------------

C++提供了不同类型的数组,了解它们的内部工作方式将有助于我们为自己的应用选择正确的类型

照片由 Fotis Fotopoulos 在 Unsplash 上拍摄

数组

当我们用任何编程语言编码时,最重要的事情之一是选择正确的数据结构来表示我们的数据。这一点很重要,因为我们不希望我们的应用程序变慢到成为瓶颈,或者在应用程序扩展时使用过多的内存。

其中一种数据结构是数组,它是一个连续的内存块,可以存储许多相同数据类型的变量(元素)。

内存中的数组(图片由作者提供)

假设我们有一个大小为 4 字节的数据类型,我们有 6 个字节。上图直观地显示了我们的数据是如何存储在内存地址 0x00000000 中的,数字 0 到 5 是元素的索引。

数组存储在连续的内存块中这一事实意味着数组可以提供以下功能:

int data[6];
  • 随机访问任何元素
    例如,我们可以用**数据【3】**访问索引为 3 的元素
  • 使用指针偏移量
    不仅使用下标操作符,我们还可以使用指针偏移量,例如,我们可以用 *(data + 3) 访问索引 3 处的元素参见指针算法

正如我们在上面看到的,无论我们使用下标操作符还是使用常规指针的偏移量,读取特定位置的元素都没有开销或者 O(1)。但是对于搜索,复杂度是 O(n ),假设我们不对数组进行排序,这不是本文的重点。

插入和删除等其他操作取决于我们选择的数组类型。我们将在接下来的章节中讨论细节。

c 风格数组

C++支持固定大小的 C 风格数组,有时也称为裸数组。这就是我们如何声明一个数组。

int data[6];

这意味着我们有 6 个整数存储在连续的内存块中。我们也可以直接初始化我们的数据。

int data[6] = {1, 2, 3, 4, 5, 6};

或者,

int data[] = {1, 2, 3, 4, 5, 6};

根据我们声明数组的位置和方式(局部/全局和初始化/未初始化),可以在堆栈或数据/bss 上创建数组。我们还可以使用 new[] 操作符在堆内存上创建数组,并使用 delete[] 操作符销毁它们。这些运算符不同于新增删除运算符,不要混淆。

int *data = new int[5];
delete[] data;

数组/指针二元性

c 风格的数组可以退化为指针。这意味着它们可以被转换成指针,并在这个过程中丢失它们的类型和大小。我们可以将指针用作数组,反之亦然。

int data[6] = {1, 2, 3, 4, 5, 6};std::cout << *(data+3);

上面的代码将打印“4”。

void print_array(int *data, int len)
{
   for (int i=0; i<len; i++)
   {
     std::cout << data[i] << "\n";
   }
}

上面的代码将打印 1 到 6。正如我们所看到的,我们的数组类型退化为指针类型,并在此过程中丢失了大小信息,这就是为什么我们将长度/大小作为参数传递。

固定大小的数组

C++标准模板库或 STL 在 std::array 中提供了固定大小的数组,本质上与 C 风格数组 相同,封装在 structs 中的 保存 C 风格数组,带有额外的标准 STL APIs,如访问元素、返回迭代器、检查容量等。

就像 C 风格的数组一样,根据我们声明它们的位置和方式,std::array 可以在 stack 或 data/bss 上创建。

以下示例假设我们使用 C17 之前的 C版本。

std::array<int, 6> data{1, 2, 3, 4, 5, 6};

它不会衰减成指针类型

除了拥有标准的 STL APIs,C 风格数组的另一个不同之处是它不会退化成指针。当我们把它传递给一个函数时,我们需要指定类型和大小。

void print_array(const std::array<int, 6>& data)
{
   for (const auto& x : data)
   {
     std::cout << x << "\n";
   }
}

好的一面是,由于它保留了大小信息,我们可以使用 for-range 循环。它也更安全,因为如果类型或大小不匹配,我们会得到一个编译错误。

std::array<int, 6> data{1, 2, 3, 4, 5, 6};void print_array(const std::array<int, 5>& data)
{
   for (const auto& x : data)
   {
     std::cout << x << "\n";
   }
}

我们将得到以下错误消息:

error: invalid initialization of reference of type ‘const std::array&’ from expression of type ‘std::array’

如果我们希望函数支持不同的类型或大小,我们可以将函数创建为模板:

template <typename T, std::size_t size>
void print_array(const std::array<T, size>& data)
{
   for (const auto& x : data)
   {
     std::cout << x << "\n";
   }
}

它提供了 STL APIs

我想说的最大好处是它提供了 STL APIs,所以我们可以使用 STL 算法来处理我们的数组。虽然我们也可以使用 C 风格的数组来使用 STL 算法,但是代码是不可移植的,比如当我们想换成另一种类型的容器时,比如我们将在下一节讨论的 std::vector

对于 C 风格的数组,我们可以使用 std::find_if 算法如下:

int data[6] = {1, 2, 3, 4, 5, 6};
int *result = std::find_if(data, data+6,
              <const int x>
              {
               if (x == 4) return true;
               else return false;
              });

std::array ,看起来是这样的:

std::array<int, 6> data{1, 2, 3, 4, 5, 6};
auto result = std::find_if(data.begin(), data.end(),
              <const int x>
              {
               if (x == 4) return true;
               else return false;
              });

我们可以简单地用 stdvector 替换 stdarray,它仍然可以工作,如下所示。

std::vector<int> data{1, 2, 3, 4, 5, 6};
auto result = std::find_if(data.begin(), data.end(),
              <const int x>
              {
               if (x == 4) return true;
               else return false;
              });

有很多标准 API 比如 back() 或者 front() 分别访问最后一个和第一个元素。

随机存取和指针偏移

就像 C 风格的数组一样,std::array 通过下标操作符为随机访问提供了灵活性:

std::array<int, 6> data{1, 2, 3, 4, 5, 6};
int x = data[3];

以及获取原始指针和使用偏移量来访问数据:

std::array<int, 6> data{1, 2, 3, 4, 5, 6};
int *pData = data.data();
int x = *(pData+3);

动态大小数组

在许多情况下,固定大小的数组不是我们编码问题的解决方案。例如,当我们不知道数据的大小或者数据的大小在运行时自然变化时。

C++为动态大小的数组提供了 stdvector。要声明 stdvector,我们只需指定类型:

std::vector<int> data;

如果你正在用 C++写代码,我相信你已经用了很多这种数据结构,因为如果你不知道使用哪种数据结构,大多数人会说这是最好的数据结构。

但是了解它是如何工作的是很重要的,这样下次你就可以更明智地选择你的数据结构。

std::vector 从堆中分配内存

stdvector 从堆中动态分配内存来存储我们的数据。当我们的 stdvector 对象超出范围时,它会将内存返回给系统。

默认情况下,如果我们不指定它,stdvector 将使用 stdallocator 来分配内存。std::allocator 的内部结构并不是本文的重点,出于本文的目的,我们假设它的工作方式就像 C 编程语言中的 malloc() 一样。

因为我们的数据大小是动态的 stdvector 在运行时分配和重新分配内存。为了避免每次添加或删除元素时都要调整内存大小(释放和分配),stdvector 会根据大量内存调整大小,比如将当前大小增加一倍。不同编译器的实现细节可能有所不同。

让我们看一个使用 gcc 的例子:

std::vector<int> data{1, 2, 3, 4};

如果我们通过调用 data.capacity()来查询元素的数量,它将返回 4。当我们再添加一个元素时:

data.push_back(5);

现在尺寸变成了 8,而不是 5。如果我们再增加 4 个元素:

data.push_back(6);
data.push_back(7);
data.push_back(8);
data.push_back(9);

尺寸变为 16,而不是 9。我们可以看到,每当先前分配的内存满了,大小就会翻倍。

内存增长示例(图片由作者提供)

它不会自动收缩

我们需要注意的一点是,当我们通过调用 pop_back()erase() 删除元素时,std::vector 不会自动收缩。

继续我们上面的例子,即使我们删除了 8 个元素,大小仍保持不变:

for (int i=0; i<8; i++)
{
  data.pop_back();
}

数据 对象仍然拥有 16 个元素的容量。如果我们想要移除未使用的内存,我们必须通过调用 shrink_to_fit() 显式地要求它收缩:

data.shrink_to_fit();

迭代器失效

在使用动态大小数组 std::vector 时,我们需要注意的另一件事是使用迭代器。迭代器是我们在使用 STL 时经常使用的类似指针的对象。

迭代器指向 stdvector 中的一个元素,例如,调用 begin() 将返回一个指向 stdvector 中第一个元素的迭代器。

std::vector<int> data{1, 2, 3, 4};
auto it = data.begin();

迭代器(作者图片)

如果 std::vector 的内存发生变化,这个迭代器可能会失效。

data.push_back(5);

在这种情况下,添加一个元素会触发重新分配,这是一个新的内存块。现在我们的迭代器无效了,因为它仍然指向旧的位置。下图说明了内部发生的情况:

无效的迭代器(图片由作者提供)

摘要

总而言之,在很多情况下,我们需要将数据存储在连续的内存块中。数组数据结构的特征如下:

  • 恒定访问时间,包括随机访问和指针偏移
  • 没有/较少内存分配开销

为了保存少量已知大小的数据,我们可以使用固定大小的数组,这在分配内存方面没有成本,对于 c++我们可以使用 std::array。

当我们需要存储较大的数据时,可以使用动态数组 stdvector。使用 stdvector 时要记住几件事:

  • 它可能会分配比优化插入时间所需更多的内存
  • 尺寸不会因为移除元素而自动缩小
  • 当内存改变时,迭代器失效
  • 它不支持 push_front()和 pop_front(),因为这两个操作总是会触发内存中的数据转移,如下图所示

在开始添加新元素时移动数据(图片由作者提供)

如果您需要频繁地在数据的开头插入和/或删除元素,c++提供了 std::deque,这是一个针对这种情况优化的双端队列。

我没有把它放在这篇文章中,因为 stddeque 不连续存储数据。它实现为数组的集合,你可以把它想象成 stdvector 的链表。

https://debby-nirwan.medium.com/subscribe

C++基础:朋友

原文:https://towardsdatascience.com/c-basics-friends-740d9667041e?source=collection_archive---------15-----------------------

在什么场景下应该使用 C++中的 Friend?

由 Pakata Goh 在 Unsplash 上拍摄的照片

介绍

C++中 Friend 的使用对于初学者来说往往是比较混乱的,因为网上有很多关于使用它是会增加封装性还是会打破封装性的争论。

如果您是面向对象编程的新手,这一点尤其正确——面向对象编程的要点是封装的概念,即通过阻止其他类访问类的内部状态来限制对类的内部状态的访问。

C++中的友元概念是一种机制,一个类可以故意让其他类或函数访问它的内部状态。现在你可以明白为什么有些人认为这违背了 OOP 的要点。

在这篇文章中,我们将看到 C++中的 friend 概念,它的用途,以及如何使用 friend 函数和 Friend 类的细节。在那之后,我们将会看到我们应该在什么样的场景中使用它们,从不同的来源中总结。

C++中的朋友概念

当我们在一个类中声明一个友元时,我们授予该友元对该类的私有受保护 成员的访问权。这意味着朋友可以访问类的成员变量和成员函数。

如果我们不将其声明为友元,访问私有或受保护的成员将导致编译错误。

编译这段代码给我们提供了:

In function ‘void Print(const Test&)’:
error: ‘void Test::Print() const’ is private within this context

C++中的访问规则由编译器检查,因此编译错误。

在这个例子中, Print() 函数 违反了访问规则 导致编译错误被抛出。为了使编译通过,我们可以将 Print() 函数声明为 Test 类的朋友。

只需添加一个朋友声明,我们就可以构建并执行我们的程序,该程序将打印号码:

2 3

我可以把好友声明放在哪里?

我们可以把友元声明放在类体的任何地方,因为访问说明符不会影响它。在这个例子中,我把它公开,但它可以在任何地方。

朋友不是继承的,不是传递的,也不是互惠的

在引言部分,提到了宣布朋友是一个深思熟虑和明确的过程。这意味着我们有以下限制:

  • 朋友不是继承的:朋友类的孩子不是朋友。
  • 朋友是不可传递的:朋友的朋友不是朋友。
  • 朋友不是对等的:我不能访问我朋友的内部状态,除非他/她也声明我是朋友。

所有这些限制都是为了确保类的作者慎重选择是否允许朋友访问其他类和函数。

在下一节中,我们将看到如何声明友元函数和类的细节。

朋友函数

我们可以在类体中将成员函数和自由函数都声明为友元。

对于自由函数,它非常简单,不需要前向声明。我们可以简单地声明朋友如下:

***void Print(const Test&Test)***函数可以访问 Test 类的私有成员。

对于成员函数,它不像自由函数那样简单。即使向前声明具有该函数的类也是不够的。以下内容将导致编译错误。

error: invalid use of incomplete type ‘class Printer’
In member function ‘void Printer::Print(const Test&)’:
error: ‘void Test::Print() const’ is private within this context

原因是 Printer 类中没有声明**void Printer::Print(const Test&Test)**函数。编译器只从 forward 声明中知道有一个名为 Printer 的类。我们可以通过向上移动打印机类并向前声明测试类来修复错误。

朋友类

不仅仅是函数,我们还可以声明一个类作为我们类的朋友。在现代 C++中,有两种方法可以声明友元类:

  • 朋友类 F;
  • 朋友 F;

如果没有现有的类,前者将声明一个新的类,而后者只有在该类存在的情况下才起作用。以下代码编译无误,因为声明友元时引入了一个新的类 Printer

但是下面的代码失败了,因为编译器找不到打印机类。

error: ‘Printer’ does not name a type

当然,我们可以通过向前声明打印机类或者改变类声明的顺序(并向前声明测试类)来简单地解决这个问题。所以最简单的解决方法是前者。

什么时候我们应该使用朋友?

现在我们已经了解了如何在 C++中正确声明友元,我们需要知道何时应该使用它们。

一些使用案例如下:

  • 界面设计灵活性
  • 运算符重载

两者都是自由函数,对于成员函数和类,我能找到的唯一用例是数据结构实现的一部分(细节和例子见 Wikipedia )。

界面设计灵活性

从下面的例子中,我们有两个不同的选项来调用 Print() 函数。

我们可以从以下表格中选择可读性更强的表格:

Test test(2, 3);test.Print(); // Option 1
Print(test);  // Option 2

有些人认为选项 2 比选项 1 可读性更强。无论如何,你可以灵活地选择如何设计你的界面。

运算符重载

出于调试目的,我们希望重载的最常见的操作符是插入操作符。例如:

std::cout << test;

我们不能将这个操作符实现为成员函数,因为第一个参数的类型是 std::ostream。

如何将单元测试类声明为友元类?

对此有相反的意见,但就个人而言,我同意这种观点,即我们应该只测试公共接口。

如果我们发现很难涵盖公共接口的所有情况,这可能表明我们的类太大了,做了太多的事情,因此我们可能想要重构它。

参考

https://docs.microsoft.com/en-us/cpp/cpp/friend-cpp?view=msvc-160 https://stackoverflow.com/questions/4171310/what-is-wrong-with-making-a-unit-test-a-friend-of-the-class-it-is-testing

C++基础:移动资源

原文:https://towardsdatascience.com/c-basics-moving-resources-4bd58bc5e6c8?source=collection_archive---------26-----------------------

什么时候应该写自己的 move 构造函数和 move 赋值操作符?

照片由 Unsplash 上的 Fotis Fotopoulos 拍摄

简介—为什么要移动资源

在编写程序时,你会遇到需要将(大量)资源从一个对象转移到另一个对象的情况。

在 C++中,我们有移动语义,这是一种移动资源的方式,以避免在内存中进行复制,这不仅会使我们的程序变慢,而且会使用更多不必要的空间。

我们在这里不讨论移动语义,因为你可以在互联网上找到很多解释右值和移动语义的资源。

不太明显的是,什么时候我们可以依靠编译器来帮助我们移动资源,什么时候我们必须编写自己的移动构造函数和移动赋值操作符。

我们将在下面的章节中看到一些例子。当然,要求你使用现代 c++,至少是 c++11。

隐式声明和定义的特殊成员函数

如果我们创建一个像下面这样的简单结构,编译器会隐式地为我们生成一些特殊的函数,这样我们就不用写冗长的代码了。我们将由编译器生成以下函数:

  • 默认构造函数
  • 复制 ctor
  • 移动构造函数
  • 复制赋值运算符
  • 移动赋值运算符
  • 破坏者

了解这一点对于我们理解在管理(大量)资源时是否需要编写它们是很重要的。

移动资源

我们可以用多种方式管理资源,最常见的方式是使用 std::vector,但在其他情况下,我们可能希望使用原始指针或智能指针。

我们可能还需要在创建包装器时管理操作系统的资源,例如像 Linux 中的套接字句柄。

用 std::vector 管理资源

在编写管理向量的类时,我们不必专门编写 move 构造函数和 move 赋值操作符,因为 std::vector 已经为我们实现了。请看下面的例子:

在我们的 数据 类中,我们只实现了一个默认的构造函数,仅此而已。但是正如你看到的,我们可以复制和移动我们的资源。

Data data2 = data;

上面一行调用复制构造函数,下面一行调用移动构造函数。

Data data3 = std::move(data);

如果我们看到程序的输出,我们会看到类似这样的内容:

Data's internalData is at: 0x558d72e74eb0
Data2's internalData is at: 0x558d72e75460
Data3's internalData is at: 0x558d72e74eb0
data is now empty

我们可以看到 数据 2 具有不同的地址,这是因为资源被复制到内存中的新空间,而 数据 3数据 具有相同的地址,因为资源刚刚被移动。结果, 数据 变空,因为它的资源已经从中释放。

智能指针呢?

有共享指针和唯一指针,但我们在这里将重点放在共享指针上,因为唯一指针不允许你复制它,因为它必须是唯一的:),它只能移动。

这个程序的输出是:

Data's internalData is at: 0x5599c3db8ec0
Number of owners: 1
Data2's internalData is at: 0x5599c3db8ec0
Number of owners: 2
Data3's internalData is at: 0x5599c3db8ec0
Number of owners: 2
data is now null

在这种情况下,我们的地址都是一样的,这是因为 shared_ptr 是为了共享资源,所以当你通过调用这行代码进行复制时:

Data data2 = data;

资源没有被复制,但是它们现在是共享的,这可以从所有者的计数中看出,在那一行之后变为 2。

现在如果我们调用下面的行:

Data data3 = std::move(data);

调用 move 构造函数, data3 的 internalData 指向与 data2 的 internalData 相同的地址,但是现在 data 已经无法访问这些资源,因为它们已经被转移到 data3

在这种情况下,我们也可以依靠编译器来完成它的工作,为我们实现 move 构造函数(以及所有其他特殊的成员函数)。

原始指针呢?

在某些情况下,我们可能想要管理原始指针,让我们看一个例子。

就像前面的例子一样,我们试图依靠编译器来完成它的工作。该程序的输出如下:

Data's internalData is at: 0x5565b0edaeb0
Data2's internalData is at: 0x5565b0edaeb0
Data3's internalData is at: 0x5565b0edaeb0

它们都指向同一个地址,这里有点不对劲。至少我们期望 Data2 的 internalData 指向不同的地址,因为它应该复制。

这显然行不通。原因是隐式生成的复制构造函数对成员进行了成员式复制,所以复制的是地址,而不是数据。

代码中缺少的另一件重要的事情是,当对象被销毁时,我们没有释放内存,这将导致 内存泄漏 。所以我们需要写自己的析构函数。

在我们添加了析构函数之后,会发生什么呢,当我们执行它的时候,这个程序会崩溃。

Data's internalData is at: 0x5632d3066eb0
Data2's internalData is at: 0x5632d3066eb0
Data3's internalData is at: 0x5632d3066eb0
double free or corruption (!prev)
Aborted (core dumped)

这是因为我们没有正确实现下面的特殊成员函数:

  • 复制构造函数
  • 移动构造函数
  • 复制赋值运算符
  • 移动赋值运算符

现在让我们将完整的实现编写如下:

输出将是正确的,如下所示:

Data's internalData is at: 0x5638e02c2eb0
Data2's internalData is at: 0x5638e02c4270
Data3's internalData is at: 0x5638e02c2eb0
Data is now empty

Data2internalData 现在指向不同的地址,有自己的数据副本,而 Data 在其 internalData 被移动到 Data3 后变为空。

结论

在试验了上面的不同场景后,我们现在可以得出结论,当我们的类管理原始资源(如原始指针)和操作系统句柄(如套接字)时,我们只需要编写自己的移动构造函数和移动赋值操作符。否则,我们可以依靠编译器为我们生成它们。

三/五法则

要记住的一件重要事情是三法则,它说:

如果您需要显式声明析构函数、复制构造函数或复制赋值操作符,您可能需要显式声明这三者。

对于现代 C++来说,我们需要增加两个函数,即移动构造函数和移动赋值操作符,这就是五的规则。

在上面的例子中,我们需要编写析构函数,所以我们需要所有五个特殊的成员函数。

C++基础:理解异常处理

原文:https://towardsdatascience.com/c-basics-understanding-exception-handling-b2a8271433a7?source=collection_archive---------22-----------------------

为什么它是处理错误的更好方法?它是如何在引擎盖下工作的?让我们后退一步,看看它到底提供了什么。

凯文·Ku 在 Unsplash 上的照片

什么是异常处理?

软件中的异常是指阻止软件执行常规路径的错误情况。这些错误可能是软件本身可以控制的,如错误的参数或超出其控制范围。例如,打开文件、套接字、分配内存块等系统调用返回的错误。

异常处理提供了一种更好的机制来检测和处理错误。为了理解为什么它更好,现在让我们看看在没有异常处理的情况下,我们如何检测和处理错误,比如在像 c 这样的编程语言中。

检测和处理错误的传统方法

我们通常将程序分解成多个函数或子程序,使其模块化,更容易理解。这意味着我们的程序将有多个链接的函数调用。每个函数都可以返回一些信息供调用者使用。

让我们看一个简单的程序,将两个必须小于 100 的整数相加。我们可以这样写程序:

错误传播 1(作者编写的代码)

所有涉及的函数都返回一个整数,当我们遇到错误时,我们返回 -1 。但是我们这里遗漏了一些东西, -1 可能是加法的结果。我们可能想要添加一个检查来确保参数不小于 0 。但是现在,在主函数中,当我们收到一个错误时,我们不知道它是哪一个,是 < 0 还是 > 100 。我们需要添加一个全局变量**。**

错误传播 2(作者编写的代码)

所以现在我们有了一个检测错误和处理错误的机制。根据您的程序,函数调用可能会更长。

这是我们以传统方式处理错误的方式,例如当我们想用 C 编程语言打开一个文件时:

FILE *fp;
fp = fopen ("file.txt", "w+");

如果 fp == NULL ,则操作失败,全局变量 errno 被更新。

传统方法的一些问题

上述传统方法存在一些问题。这些是其中的一些:

  • 所有涉及的函数必须返回相同的类型,例如 integer 来传播错误状态。这些函数调用可能相当长,并且它们被强制返回相同的类型。
  • 在处理程序的函数调用返回后,必须立即检查全局变量,或者缓存全局变量。因为当随后发生另一个错误时,它可能被更新。
  • 是否处理错误取决于调用者。如果不处理它,可能会导致程序稍后崩溃或程序异常继续。

用异常处理来处理错误

异常处理如何改进传统方法?

对于初学者来说,它在知道错误的代码和知道如何处理错误的代码之间提供了一个清晰的分隔,并且中间的所有代码都可以安全地忽略错误

带异常处理(由作者编写的代码)

有了异常处理,我们的代码现在看起来不同了。中间的函数 add_wrapper() 不一定要返回 integer 类型。它不需要知道错误。当抛出一个错误时,将在捕获该错误的 main() 函数中进行处理。现在,无论您在错误检测器和错误处理程序之间添加多少函数,它们都可以忽略它们不应该关心的错误。

我们可以去掉全局变量。

关于最后一点,如果没有处理异常,程序将会终止,因为 C++运行时将调用 std::terminate。

如果我们删除代码中的 try-catch 并执行它,我们会得到以下结果:

terminate called after throwing an instance of 'std::invalid_argument'
  what():  parameters must be >= 0
Aborted (core dumped)

所以它是更安全的,从某种意义上说,程序不会继续运行,我们会得到一些关于发生了什么的信息。

现在我们已经看到了异常处理提供了什么,让我们深入了解更多的细节。

C++中的异常处理

上面我们已经看到了如何用 C++编写异常处理,它由两部分组成:

  • 错误检测器:我们调用 throw 语句的地方
  • 错误处理程序:我们编写 try-catch 语句的地方

异常作用于函数

异常通过在所有相关函数中添加额外的信息和代码来工作。所涉及的功能不仅包括探测器和处理器还包括之间的所有功能。

现在你可以看到这不是魔术,所有涉及的功能必须仍然做一些事情来实现这个错误报告。

不同的是,所有这些工作都是由编译器 为我们完成的 ,所以从我们的代码中是看不到的。这就是为什么我们需要理解这个概念,因为仅仅看代码是不明显的。

添加到参与异常的所有函数中的额外信息和代码都被添加到相关函数代码的末尾,位于称为 LSDA(语言特定数据区)的区域。

LSDA 包含函数是否能捕获异常、异常的类型以及如何清理函数的信息。

无一例外的函数代码(图片由作者提供)

异常的函数代码(图片由作者提供)

如上所示,当我们使用异常时,编译器会为我们生成额外的代码。

实现细节是特定于语言和编译器的,通常通过一个名为 的函数来实现个性函数 ,它使用 C++运行时的元数据(见上图)来:

  • 搜索可以处理所引发的异常类型的处理程序
  • 执行清理程序,如销毁物品

当调用 throw 语句时,C++运行时将搜索处理程序,并在一个称为堆栈展开的过程中执行清理例程。根据编译器的不同,这可能是一次通过或两次通过的过程。

在一次通过过程中,每次展开返回一个功能时,搜索之后是清除过程,直到找到 try-catch

在两遍过程中,搜索在没有清理的情况下完成,只有在第二遍中找到处理程序时才执行清理例程。

安全设计

在 C++中有一些我们需要知道的细节,以确保我们的代码是安全编写的。

内存泄漏(作者代码)

如果 add() 抛出异常,上面的代码可能会导致内存泄漏。因为最后两行没有执行。编译器不能为这个函数生成 cleanup 例程,它能做的就是生成 cleanup 来调用析构函数,但是 temp 不是对象。

记住这一点的最简单的方法是不要在所有涉及的函数中使用指针。

另一个细节是构造函数中引发的异常。如果在构造函数中引发异常,编译器不会生成清理例程。

ctor 中的异常(作者代码)

在上面的代码中,我们有一个内存泄漏,因为没有进行适当的清理。编译器不会为***error propagator()***函数生成清理例程。我相信是因为物体被认为是部分创造的。

没有清理的异常(图片由作者提供)

为了解决这个问题,我们应该避免在构造函数中使用原始指针,而是使用包装器。并且,我们所有的对象都应该实现 RAII(资源分配是初始化)习语%20to%20the),以确保所有的对象都被清理。

这是因为清理例程是为构造函数生成的。下面我们来看看正确的版本。

正确清除的 ctor 中的异常(由作者编写的代码)

这样,我们就为构造函数生成了一个清理例程。

清理时出现异常(图片由作者提供)

没有例外——打破链条

有些情况下,我们不想捕捉或传播异常。C通过在函数名末尾添加一个 noexcept 关键字提供了一种方法。如果我们通过向***error propagator()***函数添加一个 noexcept 关键字来修改上面的代码,则不会生成元数据,并且对错误处理程序的搜索将会失败,这将导致 C运行时调用 std::terminate。

void ErrorPropagator() noexcept
{
    Error error;
    error.Test();
}

结果是:

terminate called after throwing an instance of 'std::invalid_argument'
  what():  wrong error parameter
Aborted (core dumped)

除了错误传播器(图片由作者提供)

摘要和参考文献

我们现在知道了异常处理可以解决什么问题,它是如何工作的——编译器添加了额外的代码,以及我们在编写 C++代码时需要注意什么。

理解这个概念有助于我们写出更好的 C++代码。

一些好的参考

https://docs.microsoft.com/en-us/cpp/cpp/exception-handling-in-visual-cpp?view=msvc-160 http://systemtbe.blogspot.com/2017/02/notes-on-c-exception-handling-and-stack.html https://www.codeproject.com/Articles/2126/How-a-C-compiler-implements-exception-handling

C++基础:理解对象模型

原文:https://towardsdatascience.com/c-basics-understanding-object-model-b8152c8a4bcf?source=collection_archive---------18-----------------------

当你开始学习 C++的时候,首先要了解的是对象模型。在你理解了对象模型之后,其他的一切都将变得有意义。

阿诺·弗朗西斯卡在 Unsplash 上的照片

介绍

C++可能很难学,尤其是如果你来自 Python 这样的高级编程语言。通过了解基础知识来开始你的学习之旅是非常重要的。

其中之一就是理解一个物体是什么。它在记忆中是如何表达的,以及它与语言中的其他概念是如何联系的。

在本文中,我们将研究 C++中对象模型的细节。

对象模型

我们从理解对象的定义开始。在 C++标准中,对象是内存中的一个存储区域。

看到它是如何存储在内存中的,会更容易理解。假设我们有下面的结构。

普通旧数据— POD

它非常简单,只有两个整数。根据我们声明对象的位置,可以在数据、堆栈或堆中创建对象。但是对于这个例子,让我们假设我们将它声明为一个局部变量,因此存储在堆栈中。如果我们打印地址,我们会得到:

start addr: 0x7ffd04a11be0
a: 0x7ffd04a11be0
b: 0x7ffd04a11be4

就像 C 语言中的结构一样,我们的对象只是内存中两个整数的集合。

具有成员函数

现在,让我们看看当我们在结构中添加一个成员函数时会发生什么。

当我们打印成员变量的地址时,它们保持不变:

start addr: 0x7ffd04a11be0
a: 0x7ffd04a11be0
b: 0x7ffd04a11be4

这是因为函数存储在其他地方——在文本/代码部分,而不是数据/堆栈/堆中成员变量存储的一部分。

内存中的对象(图片由作者提供)

成员函数就像非成员函数一样,只要程序运行,它们就存在于文本/代码部分。

多重实例化

如果我们构造两个物体呢?就像下面的代码一样。

正如你所猜测的,我们在内存中的不同区域有两个对象:

start addr of data1: 0x7ffe79920fb8
data1.a addr: 0x7ffe79920fb8
data1.b addr: 0x7ffe79920fbcstart addr of data2: 0x7ffe79920fc0
data2.a addr: 0x7ffe79920fc0
data2.b addr: 0x7ffe79920fc

但是成员函数呢?它只有一个,存储在文本部分。

内存中的多个对象(图片由作者提供)

现在,你会想当我们调用 GetSum() 时会发生什么?它如何知道使用哪些数据?

这就是 的神奇之处,这个 指针发挥了它的作用。编译器将 这个 指针添加到我们的函数中,并修改函数内部的成员访问。

除了添加隐藏的 这个 指针,编译器还将 const 关键字移入括号内,所以现在constcv-qualifier 也开始有意义了。就是说 这个 指针是一个指向常量对象的指针。

除此之外,编译器将我们函数的名称改为如下形式:

成员函数被编译器重命名,它就像一个非成员函数。

在调用方,编译器修改代码,将对象的地址传递给函数,以便函数可以使用正确的对象。

现在我们已经解决了这个由编译器执行的魔术,并且理解了它是如何工作的。这里似乎没有什么新奇的东西,就像我们在 C 编程语言中做的一样,只是现在编译器为我们做了。

静态成员函数

在我们理解了编译器如何修改我们的函数之后,现在就很容易理解什么是静态成员函数了。

对于静态成员函数,编译器不添加 这个 指针它只改变函数的名字。

静态成员函数和非成员函数之间的唯一区别在于我们如何调用它们(作用域)。

更复杂的对象

现在让我们看看更复杂的对象,比如具有用户定义类型(非原语)、继承和多态的对象。

用户定义的类型

我们已经看到了一个带有基本成员的简单结构,现在让我们看一个更复杂的例子。

地址打印如下:

start addr of complexData: 0x7ffc95b94bf0
complexData.a addr: 0x7ffc95b94bf0
complexData.data.a addr: 0x7ffc95b94bf4
complexData.data.b addr: 0x7ffc95b94bf8
complexData.b addr: 0x7ffc95b94bfc

所以没什么特别的。它们就像我们订购时那样摆放。

使用用户定义的类型(按作者分类的图像)

遗产

就像用户定义的类型一样,数据的布局和继承没有什么特别的。请参见以下示例:

这是它在内存中的样子:

继承(作者图片)

父代成员放在子代成员之前。

多态性

这就是我们引入静态与动态绑定概念的地方。在这个上下文中,绑定指的是将函数调用和函数定义链接起来的过程,更准确地说是函数在内存中的地址。

静态绑定是指过程发生在编译时,而动态绑定是指过程发生在运行时。

在 C++中实现多态性需要这些过程。

多态的一种形式是函数重载,这是一个创建同名但参数不同的函数的过程。让我们看看我们的例子。

实际情况是,我们在内存中有两个不同的函数,名字不同。

函数重载(图片由作者提供)

函数调用到函数定义的链接可以在编译时完成,因为所需的信息在编译时是可用的。编译时还会链接以下内容:

  • 正常函数调用
  • 运算符重载

多态的另一种形式是函数覆盖,这是一个创建函数来覆盖基类/父类的函数的过程。基类和子类中的两个函数具有相同的名称和参数。请看这个例子:

您可能已经猜到,这段代码在编译时会产生两个不同的函数:

int Data::GetSum(const Data* this);
int ComplexData::GetSum(const ComplexData* this);

就像函数重载的例子一样,链接发生在编译时。这个代码

int main()
{
  Data data;
  ComplexData complexData;

  int b = complexData.GetSum();
  int a = data.GetSum();

  return 0;
}

在编译时更改为以下内容

int main()
{
  Data data;
  ComplexData complexData;

  int a = ComplexData::GetSum(&complexData);
  int b = Data::GetSum(&data);

  return 0;
}

虚拟功能

我们想用函数覆盖做的一件事是能够从基类访问不同类型的子类,这提供了一个有用的抽象机制。当我们编写这段代码时:

void PrintSum(const Data& data)
{
  std::cout << data.GetSum() << "\n";
}int main()
{
  ComplexData complexData;
  PrintSum(complexData);

  return 0;
}

我们想要数据。GetSum() 调用complex Data::GetSum(),而不是Data::GetSum()

现在的问题是,我们在编译时没有信息将调用者链接到正确的函数定义。编译器只知道在 PrintSum() 函数中类型是 数据

这里我们可以使用动态绑定来强制编译器在运行时在调用者和正确的函数定义之间进行匹配。在 C++中,这可以通过在基类的函数声明中添加虚拟关键字来实现。

有了这个声明,在这段代码中

void PrintSum(const Data& data)
{
  std::cout << data.GetSum() << "\n";
}int main()
{
  ComplexData complexData;
  PrintSum(complexData);

  return 0;
}

数据。GetSum()** 会正确调用complex data::GetSum()

虚拟指针和虚拟表

现在,让我们来看看当我们在类中使用虚拟函数使动态绑定成为可能时,我们的对象会发生什么。

虚拟函数覆盖(图片由作者提供)

我们的对象现在看起来不同了,我们有了一条额外的信息来存储名为虚拟指针的虚拟表的地址— vptr

虚拟表是一个函数查找表,用于将调用者链接到正确的函数定义。它通常存储在文本/常量部分中。

我们现在可以明白为什么这个过程被称为动态/后期绑定了。因为调用函数的过程是通过 vptr 完成的。

vptr 是怎么设置的?它在构造函数中设置,从基类开始,直到层次结构中最低的派生类。对于我们的示例,如下所示:

Data::Data()
{
  vptr = &data_vtable;
}ComplexData::ComplexData()
{
  vptr = &complexData_vtable;
}

它首先被设置为基类 Data 的 vtable,然后被设置为派生类 ComplexData 的 vtable。

现在我们明白了为什么我们的程序可以在不知道对象类型的情况下调用正确的函数。

结论

在我看来,在理解更高层次的概念之前,先理解好基本面是非常重要的。

通过理解对象在 C中是如何建模的,我们可以理解为什么我们必须以特定的方式编写 C代码。同样重要的是,我们知道何时以及为什么我们需要使用动态绑定和静态绑定。

我们也知道为什么人们说使用虚函数是有“成本”的,因为动态绑定的代码中有额外的步骤。

我希望这些信息对你有用。

参考

用于数据处理的 C++内存分配/释放

原文:https://towardsdatascience.com/c-memory-allocation-deallocation-for-data-processing-1b204fb8a9c?source=collection_archive---------4-----------------------

理解如何管理内存将有助于我们更明智地分配/释放内存。

附身摄影在 Unsplash 上拍照

概观

除非您正在运行 RTOS 或裸机的资源非常有限的嵌入式系统上工作,否则几乎肯定需要动态分配内存来处理数据。在 C++中有许多动态分配内存的方法,比如使用 newdelete 操作符以及它们的对应操作符 new[]delete[]std::allocator ,或者 C 的 malloc()。

无论采用哪种方法,系统都必须连续分配内存块。

C++ STL 提供了许多方便的库,比如容器,它们也在内部动态分配内存。C++中的动态内存分配随处可见。

在本帖中,我们将讨论在 C++中如何管理内存,以便我们可以更明智地使用它。

存储配置

物理和虚拟内存

请记住,这个内存布局是用户空间应用程序的虚拟内存布局。在像 Linux 这样的系统中,物理内存大体上分为内核空间和用户空间,对于应用程序,我们说的是用户空间。此外,系统中的每个进程都分配有虚拟内存,该虚拟内存通常大于可用内存。例如,在一个 4GB 内存的系统中,每个进程都假设它拥有所有可用的内存。

C++内存布局

C++内存布局(图片作者提供)

这是我们的应用程序的虚拟内存的布局。在这篇文章中,我们对堆段感兴趣,堆段是我们用来动态分配内存的段。

Text/Code 是存储代码指令的地方,data/BSS 是存储全局数据(已初始化/未初始化)的地方,stack 是用于管理函数调用和局部变量的调用栈。

操作系统如何管理堆?

不同的操作系统管理堆内存的方式不同,为了让本文直观地理解堆内存的管理方式,我们假设有一个类似 unix 的系统,比如 Linux。

控制程序中断地址以分配/取消分配内存(作者图片)

在 Linux 中,我们可以通过调整程序中断来分配/释放内存,程序中断是当前的堆限制。用户空间应用程序可以通过使用 unistd.h 中包含的系统调用 brk()和 s brk()来调整它,有关详细信息,请参见手册页。

不建议以这种方式手动管理内存,因为这样容易出错。我们拥有的第一级抽象是由 C 运行时提供的内存分配库,malloc()系列。

动态内存分配

与直接调用系统调用相比,C 标准库提供了一种更方便的分配/释放内存的方式。它提供:

  • malloc():根据给定的大小分配内存
  • free():释放以前分配的内存
  • realloc():调整先前分配的内存大小
  • calloc():为对象数组分配内存

使用这种方法不容易出错,因为应用程序不需要知道当前的堆限制。它所要做的就是通过传入大小来请求内存块,一旦完成了对内存的处理,就通过调用 free()来请求释放内存。

int *ptr = (int *) malloc(sizeof(int));
free(ptr);

malloc()系列 API 使用 brk()、sbrk()和 mmap()系统调用来管理内存。这是抽象的第一层。

malloc()是如何工作的?

实现细节可能因编译器和操作系统而异,但这里我们将概述 malloc()所做的内存管理。

在内部,malloc()通过在应用程序请求的每个内存块中添加元数据来管理内存。出于本文的目的,我们假设它的元数据中有两条信息:

  • 大小
  • 分配状态(使用中/空闲)

Malloc 内存块(作者图片)

当您调用 malloc()、realloc()或 calloc()时,它会在内存中搜索符合您所请求大小的空闲区域。

malloc 示例(图片由作者提供)

例如,在上图中,可用块显示为蓝色。如果大小合适或更小,块将被重用,否则如果内存中的空闲区域在系统中仍然可用,malloc()将通过调用 brk()、sbrk()或 mmap()系统调用来分配新的内存。

分配新块(图片由作者提供)

如果系统中没有可用的内存,malloc()将失败并返回 NULL。

存储器分配

当你想分配内存块的时候,在引擎盖下发生的是一个搜索。有多种策略,例如:

  • First-fit:首先遇到的 fit 内存块
  • 下一个 fit:第二个遇到的 fit 内存块
  • 最合适的:就尺寸而言最合适的

并非在所有情况下,我们请求的大小都与可用的空闲块匹配,大多数情况下,只有部分可用的空闲块会被使用,并且这些块会被拆分。

蓝色的可用区块(图片由作者提供)

以红色分配的内存(图片由作者提供)

内存释放

当您释放内存时,它不会返回给系统。只有其元数据被改变以反映其现在未被使用的状态。

当内存被释放时,可能发生的一件事是空闲块合并。相邻的空闲块可以合并成一个更大的块,用于更大的请求。

如果当前我们在中间有一个小的空闲块,如下图所示:

当前状态(作者图片)

我们解放了最后一个街区:

另一个块被释放(作者图片)

它们将结合形成更大的块:

最终模块(图片由作者提供)

内存重新分配

正如您可能已经猜到的,内存重新分配,即当我们调用 realloc()时,只是分配内存+将现有数据复制到新分配的区域。

内存碎片

内存碎片是指 小内存块 在较大内存块之间分配的情况。这种情况会导致系统无法分配内存,即使大部分区域可能未分配。

下图说明了这种情况:

全部免费(图片由作者提供)

我们分配 3 个数据块、1 个数据块和 8 个数据块:

所有已分配(图片由作者提供)

然后,我们释放 3 个块和 8 个块:

释放两块内存(图片由作者提供)

现在,我们想要分配 9 个块,尽管我们总共有 11 个空闲块,但是它们都是碎片,还是失败了。

当您的程序在运行时频繁地在堆上分配/释放小对象时,很可能会发生这种情况。

C++动态内存分配

现在我们已经看到了系统中的第一级抽象,我们可以看到 C++提供的下一级抽象。

新建和删除运算符

在 C++中,当我们想从自由存储(或者我们可以称之为堆)中分配内存时,我们使用 new 操作符。

int *ptr = new int;

为了解除分配,我们使用了删除操作符。

delete ptr;

与 C 编程语言中的 malloc()相比,不同之处在于新的操作符做了两件事:

  • 分配内存(可能通过调用 malloc())
  • 通过调用对象的构造函数来构造对象

类似地, delete 操作符做两件事:

  • 通过调用对象的析构函数销毁对象
  • 释放内存(可能通过调用 free())

以下代码显示了这一点:

C++中的新建和删除操作符(由作者编写代码)

为了分配内存和构造对象数组,我们使用:

MyData *ptr = new MyData[3]{1, 2, 3};

为了销毁和解除分配,我们使用:

delete[] ptr;

如果我们已经分配了内存块,并且只想构造一个对象,我们可以使用所谓的放置 new

typename std::aligned_storage<sizeof(MyData), alignof(MyData)>::type data;
MyData *ptr = new(&data) MyData(2);

第一行将分配在堆栈上存储 MyData 对象所需的内存(假设这些代码行在一个函数中),第二行将在该位置构造对象,而不分配新的内存。这里要小心,因为我们不应该在 ptr 上调用 delete

标准::分配器

如你所知 STL 容器如 stdvector,stddeque 等。内部动态分配内存。它们允许您使用自己的内存分配器对象,但是通常情况下,我们使用默认的对象 std::allocator。

他们不使用 newdelete 操作符的原因是他们想分别分配内存和创建对象。例如,std::vector 通过将当前大小增加一倍来动态增加内存以优化速度,更多详细信息请参见我的另一篇文章。

我们可以认为 std::allocator 会调用 malloc(),尽管它可能会做一些其他的事情,比如为优化预分配内存。

智能指针

到目前为止,我们所看到的一切都没有解决手动内存管理的问题,分配和释放内存的责任在于开发人员。众所周知,手动内存管理会导致如下问题:

  • 内存泄漏,当我们忘记释放内存时
  • 崩溃/未定义的行为,当我们试图释放已被释放或双释放的内存时
  • 当我们试图访问已经释放的内存块时,出现崩溃/未定义的行为

由于性能和便利性的权衡,C++没有隐式的垃圾收集器来自动管理内存。但它在智能指针中有一个显式的垃圾收集器,当对象超出范围或没有其他对象引用它时,它会自动分配内存和释放内存。

它们是:

  • 管理不可复制的另一类型指针的对象(唯一的)
  • std::shared_ptr
    类似于 unique_ptr,但是可以通过使用引用计数来共享所有权
  • std::weak_ptr
    一个不拥有的对象,它拥有对指针的引用,但不拥有它

大多数情况下,您应该使用智能指针,并忘记何时释放内存。我们可以在将来的另一篇文章中讨论细节。

其他内存管理库

在内存管理中,我们可能还需要考虑其他一些事情,比如减少使用内存池分配/释放内存时的开销,或者在某些情况下,我们可能需要特别注意小对象分配。我们将在以后的文章中讨论它们。

摘要

关于如何在 C++中分配/释放内存,有多个抽象层次。了解它们非常重要,因为我们不仅知道应该使用哪个级别,还知道在我们的应用程序中可能会出现什么问题。下图说明了不同级别的 API。

C++中不同级别的内存管理(图片由作者提供)

https://debby-nirwan.medium.com/subscribe

C++:可选对象,可能包含另一个对象

原文:https://towardsdatascience.com/c-optional-object-that-may-contain-another-object-f04d5cfb6b63?source=collection_archive---------17-----------------------

使用第一原则思维来学习更好地编码以处理我们的数据。了解可选对象能解决什么问题,分解它,并重新构建它

穆罕默德·拉赫马尼在 Unsplash 上的照片

概观

从 C17 开始,C标准库提供了 std::optional ,这是一个管理可选包含值的类模板。可选的类型或者有时也叫可能类型代表一个可选值的封装。

在这篇文章中,我将介绍 std::optional 解决的问题,描述解决这些问题的需求,最后构建一个简单版本的可选类来演示它是如何工作的。

可选对象解决的问题

在我们代码中的一些场景中,我们会面临这样的情况:我们希望从函数中返回一个可选对象,或者在函数中接受可选参数。例如,在下面的代码中,我们希望返回一个只有在满足某些条件时才可用的数据对象。

另一个例子是当我们想设置数据,但有时他们不可用,我们希望函数检查和决定。

如果不使用像 std::optional 这样的类模板来包装数据对象,在 C++17 之前,我们可以使用以下技术。

用一个标志将我们的数据包装在一个结构/类中

我们可以创建以下结构, OptionalData :

我们是这样调用这个函数的:

这种技术不仅增加了大小开销(bool + padding),还增加了构造数据对象的时间开销,当数据对象无效时,这是不必要的。

使用指针包装我们的数据

为了避免在不需要的时候构造数据对象,我们可以使用智能指针,比如 std::unique_ptr 来包装我们的数据。当条件不满足时,我们可以返回 nullptr

在呼叫者方面,它看起来是这样的:

与前一种技术相比,这种技术要好得多,但是代码不是很有表现力,因为为此目的使用指针不能很好地解释函数的意图。

返回多个值

从 C++11 开始,我们可以使用 std::tuple 返回多个值,或者在这种情况下我们想返回两个值,可以使用 std::pair 。这可能是最常用的技术。

在呼叫端,它看起来是这样的:

从语义上来说,这种技术与我们的第一种技术相同,在第一种技术中,我们将数据对象包装在一个结构中。因此,它遭受同样的问题,此外,程序员必须记住是否使用“第一”或“第二”。

传入指针并返回布尔状态

我们也可以使用类似 C 的技术,传递一个指针并返回一个布尔值。

在呼叫端,它看起来是这样的:

我们不仅在这里使用了可能被认为是不安全的原始指针,而且尽管它是有效的并且总是需要构造数据对象,但是它的表达性较差。

问题

我们现在可以列出上述各种技术存在的问题,如下所示。

  1. 他们没有清楚地传达意图。我们的目的不是获取一个指针或一对对象,而是希望在数据对象可用时可以选择获取它
  2. 其中一些不必要地构造了数据对象
  3. 对于类似 C 的技术,它是不安全的,尤其是如果指针是从空闲存储/堆中分配的

我们如何解决这些问题?

从上面列出的问题来看,这些是我们的需求。

  1. 可选对象必须包含真实对象
  2. 包含的对象应该在可选对象内(不是动态分配的)
  3. 可选对象可能为空
  4. 所包含的对象可以稍后设置
  5. 包含的对象可能在可选对象之前被销毁

包含另一个对象的可选对象(图片由作者提供)

编写简单的可选对象

我们构建可选对象来理解 std::optional 是如何工作的。我们省略了大部分接口,把注意力集中在存储对象的主要内容上。

第一个要求是包含任何对象,并有一个标志来检查它是否为空。

但是这和我们上面的第一个技术是一样的,只是现在它是一个类模板。我们希望可选对象在默认情况下不构造包含的对象。实现它的一种方法是使用 std::aligned_storage 为包含的对象保留空间。

这里发生的情况是,被包含的类型没有被存储,但是当我们构造可选对象时,存储它所必需的空间被保留。

可选对象内存布局(图片由作者提供)

当我们构造一个空的可选对象时,我们只初始化这两个对象。为了初始化包含的对象,我们使用放置 new ,即使用 new 运算符在现有位置构造一个对象。

另一种方法是使用匿名联合,这可能是一种更好、更干净的方法。

下一个要求是,我们可能希望在销毁可选对象之前销毁包含的对象,为此我们添加了 reset()函数。

我们可能还想稍后设置包含的对象,如下例所示:

为此,我们可以实现复制赋值和移动赋值操作符。

我们可以用类似的方式实现移动赋值操作符。通过调用可选<数据>(常量数据& t) 构造器,然后调用复制赋值操作符,首先将数据对象隐式转换为可选<数据> 类型。

其余的接口

为了获得包含的对象,我们可以很容易地实现 value() 函数,如果包含的对象存在,则返回该对象,否则抛出异常。

其余的接口可以很容易地实现,在这篇文章中没有全部展示,因为它可能会变得太长。可以看这个页面看其他界面。

现有 std::optional 的其他改进

可以对现有的 std::optional 进行进一步的改进。在某些情况下,我们可能希望根据可选对象的状态调用其他函数。

为此,根据此页面,C++23 将添加以下内容:

  • and_then(f)
    如果返回的可选对象包含另一个对象,则执行可调用的‘f’可以返回任何类型,否则返回空的可选对象。
  • transform(f)
    如果返回的可选对象包含另一个对象,则执行可调用的‘f’返回可选的类型,否则返回空的可选对象。
  • or_else(f)
    如果返回的可选对象为,则执行可调用的‘f’返回可选类型,否则返回可选对象。

它们被称为一元函数,其工作是抽象出样板代码,我们可以以更简单、更易读的形式修改上面的代码。

Python 中的类似功能

您可能已经意识到,在 Python 中,我们可以通过不返回任何对象来轻松实现可选对象。

在 C中,我们必须使用 C标准库中的 std::optional 来实现这一点。

摘要

关键要点是:

  • 我们使用 std::optional 使我们的代码更具表现力
  • std::optional 包含对象本身,这取决于它的存储位置(堆栈/数据/堆)
  • std::optional 复制包含的对象
  • 一元函数将被添加到 C++23 中,通过消除编写样板代码的需要来改进我们代码中的抽象

https://debby-nirwan.medium.com/subscribe

C++类型擦除:包装任何类型

原文:https://towardsdatascience.com/c-type-erasure-wrapping-any-type-7f8511634849?source=collection_archive---------2-----------------------

了解如何用 C++编写类中任何类型的包装器,以提高代码的抽象层次。

Unsplash 上 AltumCode 拍摄的照片

介绍

我们从泛型编程、面向对象编程和 Duck Typing 概念的一些基础知识开始,以理解这种技术试图解决什么问题。我们将在这篇文章的最后一步一步地介绍细节。

通用编程

泛型编程是指一种编程风格,其中函数或算法被编写为接受不同类型,而不是单一类型。在 C++中,你可以用模板来实现这一点。

使用模板,我们可以要求编译器根据代码中使用的类型为我们生成函数/类。这有助于我们避免多次编写类似的代码块,以保持代码整洁。这里有一个简单的例子:

我们可以如下创建一个模板,而不是编写上面的两个函数。

只有在我们需要的时候,编译器才会为我们生成函数。例如,当我们将这些调用添加到我们的 main() 函数中时:

编译器将生成这些函数:

统一界面

一些基本的编程原则包括“不要重复自己— DRY”,这是为了避免我们的代码中出现重复。方法之一是创建一个统一的接口。

为了更好地理解这个想法,让我们看一个例子。假设我们想要创建一个函数,它接收任何具有 Id 的类型,我们可以通过调用我们想要打印的 GetId() 函数来获得这个类型,让我们调用我们的函数 PrintId()

假设我们有如下两个不同的类型和一个自由函数,我们也可以添加 lambdas。

简单的解决方案是为我们想要打印的每种类型编写函数重载:

下面是我们调用它们的方法:

第三个函数可以处理自由函数和无捕获 lambdas。它对无捕获 lambdas 有效,因为它们衰减成函数指针。

这里我们想要解决的问题是,我们想要一个能够接受上述所有类型的函数。

多态性

首先想到的是使用继承,这是 OOP 中的一个概念。我们可以创建一个接口,抽象基类 ABC,并让对象继承或实现它。

并且只实现了一个 PrintId() 函数:

显然,当我们传递不同的类型时,比如函数指针,它就不起作用了。

模板

说到统一接口,还有一个来自 Python 编程语言的概念叫做 鸭子打字 。这基本上意味着我们不需要知道对象的类型,只要它支持我们需要的行为。在我们的例子中,我们需要一个不接受任何东西并返回一个 int 的行为/函数, *int(behavior)()

在 C中,我们可以使用模板来实现同样的事情。Python 的不同之处在于,Python 中的检查是在运行时进行的,而 C是在编译时进行的。

现在, Object1Object2 不需要相互关联,只要有一个名为 GetId 的函数就可以了。在引擎盖下,我们实际上有两个不同的函数(参见关于泛型编程的第一部分)。

但是,我们仍然不能调用自由函数和 lambdas,因为它们没有一个名为 GetId() 的函数。

使用仿函数使其更通用

我们可以通过使用仿函数来改变我们的类和 PrintId() 函数,使其更加通用。如果你需要更多的细节,请阅读我关于 C++ Lambda 的帖子。

有了这个变化,所有类型都可以工作了。

在引擎盖下,我们有许多由编译器生成的函数,它们是:

第一个 lambda 通过在前面添加“+”运算符隐式转换为函数指针。

现在看起来我们有了解决方案,但是我们还有一个问题要解决。

如果我们想把对象存储到一个数组中呢?

用相同的行为包装任何类型

在我们代码的某些场景中,我们希望将可调用对象存储到一个数组或其他容器中。就我们目前的实现而言,这是不可能的,因为我们没有 STL 容器所需的单一类型,比如 std::vector 。举一个具体的例子,如果我们将 PrintId() 函数改为:

我们将会有编译错误,因为我们还没有实现 ObjectWrapper 类。

创建任何类型的包装

为了解决这个问题,我们需要一个单独的类来包装所有不同类型的对象。这就是我们在 C++中使用类型擦除技术的地方。让我们一步一步地构建我们的包装器。我们的包装类必须:

公开公共接口

我们的包装器首先需要提供统一的接口,在我们的例子中,它是int( behavior)()*。

复制传递的对象

我们的包装类必须管理对象的生存期,以避免使用悬空引用或指针。另一个考虑是对象的大小可能相当大,所以我们需要将它们存储在空闲存储/堆中。我们选择使用智能指针。为此我们需要一个新的类型,我们称之为 ObjectBase

多态性

现在我们有了一个名为 ObjectBase 的新类型,我们的目标是包装任何类型。解决方案是使用多态性,我们将 ObjectBase 作为一个接口,并从编译器那里获得帮助来创建继承它的子类。

子类必须是模板类,这样编译器才能生成它们。

提供一个接受不同类型的构造函数(显然)

最后一步是为我们的构造函数创建一个模板函数来接受不同的类型。

形象化

为了帮助更好地理解它,用 UML 图可视化我们的包装类是很好的。我们现在可以包装支持我们通用接口的不同类型, *int(behavior)()

我们也可以将它们存储在一个向量中:

类图(图片由作者提供)

实际上,我们有 5 个不同的类实现了 ObjectBase 接口。当我们调用 operator()时,会发生以下情况:

当我们调用 operator()时的事件序列(图片由作者提供)

我们可以看到有两个额外的函数调用,这是包装对象的成本。运行时发生的另一个开销是由我们的虚函数引起的动态分派。

这种技术的真实例子

现在,我们已经看到了用相同的行为包装任何类型的技术,我们可能想知道在什么情况下使用这种技术。您可能在代码中经常使用的两个示例是:

  • std::function
    一个通用多态函数包装器。
  • std::any
    任何可复制构造类型的单个值的类型安全容器。

摘要

在这篇文章中,我们将讨论通过使用 C中的类型擦除技术来提高代码的抽象层次。通过结合 OOP 和编译时 duck typing——c中的模板,我们可以创建存储任何类型的包装器。

了解一些库(比如 stdfunction)是如何实现的,对于避免不必要的使用非常重要。例如,我们可能不希望在我们的算法中调用 stdfunction 对象一百万次,因为上面描述的函数调用和动态分派的开销。

https://debby-nirwan.medium.com/subscribe

在开始我的第一份数据科学工作之前,我希望知道的 5 件关键事情

原文:https://towardsdatascience.com/c5-key-things-i-wish-i-knew-before-starting-my-first-data-science-job-818556079665?source=collection_archive---------22-----------------------

在你的第一份数据科学工作中,知道这五件关键的事情是很有价值的

Zan 在 Unsplash 上的照片

到今天为止,我已经完成了作为数据科学家的第一个月的工作。至少可以说,这是一个陡峭的学习曲线,但也是最有收获和最令人兴奋的经历之一!

然而,在这几个星期的介绍中,我不得不迅速掌握一些我以前不了解或了解非常有限的基本技术。在这篇文章中,我希望揭示一些工具,这些工具将帮助新的数据科学家从事他们的第一份工作。

面向对象编程

您可能会使用 Python,它本身就是一种面向对象编程(OOP)语言。这种编码范式在现实生活的数据科学问题中非常有用,在这些问题中,您通常有非常大的数据集和包含数千行代码的笔记本。与典型的过程式编程风格相比,使用 OOP 有助于精简脚本,并为您的程序提供更清晰的结构。事实上,行业中的大多数代码都是使用这种思想编写的,所有的公共库和包也是如此。

我对 OOP 的经验有限,我真希望在开始工作之前,我能用这种范式多练习编码。我对任何初露头角的数据科学家的建议是学习 OOP,比如类、自我、固有等,然后尝试使用这种范式编写一些基本的机器学习算法。网上有很多教程可以让你从不同的人以不同的方式解释 OOP 开始,所以会有一个解释给你!

Git 和 GitHub

“你是 GitHub 的头吗?”

“是啊!”

“你知道怎么用吗?”

“不尽然”

这是我关于 Git 和 GitHub 的第一次对话。据我所知,每个公司都使用 GitHub 做这样或那样的事情,它是任何技术专业人员的必备工具和技能。

我以前用过 GitHub,但只是作为作品集来展示我的作品。然而,Git 和 GitHub 远不止于此,它有着非常有用的功能,我现在仍然习惯于它。

对于那些可能不知道的人来说,Git 和 GitHub 是一个版本控制系统,它简化了编码项目的结构化和管理。还有其他版本控制系统,但 GitHub 是目前的市场领导者。

与 OOP 类似,学习 Git 和 GitHub 相当简单,有大量的在线资源供您探索。学习起来也相当简单,但像任何事情一样,要精通它需要练习。我建议学习基本原理,如推、拉、合并、分支等。

命令行/终端

尽管我们不是软件工程师或开发人员,但数据科学家确实在某些任务中半频繁地使用命令行。很大一部分数据科学家没有计算机科学背景,因此他们使用终端或命令行的经验可能有限。

同样,与 Git 和 OOP 一样,一个简单的教程可以涵盖数据科学家会使用的大部分功能。所以学习一些东西,比如编译、安装包、改变目录等等。这些都是非常琐碎的命令,但我认为任何技术专业人员都应该知道这一点,并能自如地使用它。

模特不是一切

实现最新的机器学习算法通常是项目中最令人兴奋的部分,也是大多数人进入数据科学的原因。我记得我曾经花几个小时来微调我的算法,尽可能地为我的模型挤出最大的性能。

然而,在工业中,这并不总是首选的方法。对于模型表现不佳的原因,最常见的解决方案是您正在训练的数据的质量、类型和大小。您可能听说过数据社区中新出现的“以数据为中心”的概念,它专注于改进数据以改进模型。这在工业上变得非常丰富。

其理念是关注数据的来源、质量,并改进特征工程流程以生成更好的模型。因此,确保您理解甚至将您的学习重点放在项目中的数据预处理上。

我犯的错误是学习了所有关于 ML 算法的知识,这很好,但是忽略了在预处理步骤上投入大量时间。因此,确保你在数据方面和 ML 建模方面都同样关注你的学习,这样你就能精通这两方面。

了解和学习你的行业

你可能是世界上最有技术天赋的数据科学家,但是如果你对你的业务领域没有概念,你的工作将不会有多大价值。数据科学家的工作是回答业务问题并提供宝贵的见解。这意味着你必须知道你的行业是如何运作的,并跟上它的发展。

这在你工作前很难了解,因为你可能不知道你将在哪个业务领域工作。然而,当你了解你的行业时,我建议你每天花大约半个小时阅读它最*的新闻和发展。即使只是一个简单的维基百科潜水也会让你受益匪浅,我注意到它真的在我的项目中帮助了我。值得一提的是,每天在那里工作,你会通过简单的潜移默化学到很多东西。然而,加速这一进程并无坏处。

然而,更普遍的是,只听和阅读新闻,因为这将提高你对一切的知识,使你成为一个更全面的专业人士!

结论

每个数据科学工作都是不同的,工具也因公司和行业而异。我相信上面列出的五个主题是必不可少的,无论你最终将在哪里工作,它们都会让你受益。

和我联系!

  • 要在媒体上阅读无限的故事,请务必在此注册!T3💜
  • 当我在这里发布注册邮件通知时,可以获得更新! 😀
  • 领英 👔
  • 推特 🖊
  • github🖥
  • https://www.kaggle.com/egorphysics🏅

(所有表情符号由 OpenMoji 设计——开源表情符号和图标项目。许可证: CC BY-SA 4.0

用 Python 计算峰度(有例子)

原文:https://towardsdatascience.com/calculate-kurtosis-in-python-with-examples-pyshark-2b960301393?source=collection_archive---------10-----------------------

在本教程中,我们将探讨如何在 Python 中计算峰度。

https://stats . stack exchange . com/questions/84158/分布的峰度如何与密度的几何形状相关

目录:

  • 介绍
  • 什么是峰度?
  • 如何计算峰度?
  • Python 中如何计算峰度?
  • 结论

介绍

峰度主要是描述概率分布形状的一种度量,特别是它的“尾部”。

计算的统计值评估给定概率分布的尾部与正态分布相比有多厚或多薄。

其中偏斜度关注于根据极值区分分布的尾部(或者仅仅是尾部的对称性),峰度测量在任何一个尾部中是否有极值(或者仅仅是尾部是重还是轻)。

为了继续学习本教程,我们需要以下 Python 库:scipy。

如果您没有安装它,请打开“命令提示符”(在 Windows 上)并使用以下代码安装它:

pip install scipy

什么是峰度?

在统计学中,峰度是一个概率分布的相对峰值的度量,或者说它的尾部有多重或多轻。峰度值描述了给定概率分布的尾部与正态分布的不同程度。

峰度可以取几个值:

https://stats . stack exchange . com/questions/84158/how-of-the-kortosis-of-a-distribution-related to-the-geometry of-the-density-fun

  • 正的过度峰度-当(峰度-3)给出的过度峰度为正时,则分布有一个尖锐的峰,称为细峰分布。
  • 负的过度峰度-当(峰度-3)给出的过度峰度为负时,则该分布具有*坦的峰值,并被称为*峰分布。
  • 零超额峰度-当(峰度-3)给出的超额峰度为零时,则分布遵循正态分布,也称为中峰度分布。

下面以表格形式总结了上面提到的内容:

如何计算峰度?

峰度的度量被计算为分布的第四个标准化矩。

听起来有点复杂?按照下面的步骤,对计算有一个完整的理解。

分布的第k 个力矩可以计算为:

如前所述,偏斜度是分布的四阶矩,可计算如下:

并且知道分布的二阶矩是它的方差,我们可以将上面的等式简化为:

其中:

举例:

上面是很多公式。为了使这一切成为一个更好理解的概念,让我们来看一个例子!

请考虑以下代表学生考试成绩的 10 个数字序列:

X = [55,78,65,98,97,60,67,65,83,65]

计算 x 的*均值,我们得到:x̄=73.3.

求解 m_4:

求解 m_2:

求解 K :

Python 中如何计算峰度?

在这一节中,我们将通过一个例子来计算 Python 中的峰度。

首先,让我们创建一个类似于上一部分的数字列表:

为了计算偏度的 Fisher-Pearson 相关性,我们需要 scipy.stats.kurtosis 函数:

我们应该得到:

2.0453729382893178

注意:在上面的代码中设置 fisher=False 会计算 Pearson 的峰度定义,其中正态分布的峰度值= 3。

我们发现,对于给定的数列,峰度值约为 2.05,而过度峰度值约为-0.95。这表明我们有一个比正态分布更厚更*的分布。

结论

在本文中,我们讨论了如何使用 scipy 库在 Python 中计算一组数字的峰度。

如果你有任何问题或对一些编辑有建议,请随时在下面留下评论,并查看更多我的统计文章。

原载于 2021 年 9 月 2 日 https://pyshark.comhttps://pyshark.com/kurtosis-in-python/

用牛顿-拉夫逊法计算最大似然估计量

原文:https://towardsdatascience.com/calculate-maximum-likelihood-estimator-with-newton-raphson-method-using-r-7d3f69fbf8fe?source=collection_archive---------5-----------------------

卢卡斯·布拉塞克在 Unsplash 上的照片

使用此方法可以帮助您计算模型中任何估计量的最大似然估计量(MLE)。

动机

在统计建模中,我们必须计算估计量来确定你的模型的方程。问题是,估计量本身是很难计算的,尤其是当它涉及到一些分布,如贝塔分布、伽玛分布,甚至 Gompertz 分布。

最大似然估计(MLE)是计算这些分布的估计量的许多方法之一。在这篇文章中,我会给你一些例子,用牛顿-拉夫逊法计算最大似然估计。

概念:MLE

首先,我们考虑

作为具有概率分布函数(PDF)的独立同分布(iid)随机变量

其中参数θ未知。该方法的基础是由下式给出的似然函数

该函数的对数,即对数似然函数,表示为

为了确定 MLE,我们确定对数似然函数的临界值;也就是说,最大似然法解了这个方程

概念:牛顿-拉夫逊法

牛顿-拉夫森法是计算函数 f 的根的迭代程序。在这种方法中,我们希望通过计算来逼*函数的根

其中 x_{n+1}是第(n+1)次迭代。这种方法的目标是使*似结果尽可能接*精确结果(即函数的根)。

综合起来:计算最大似然估计的牛顿-拉夫逊方法

牛顿-拉夫逊方法可用于生成收敛于最大似然估计的序列。如果我们假设θ为一个 k × 1 向量,我们可以迭代

其中 l'(θ) 是对数似然函数的梯度向量, l''(θ) 是对数似然函数的海森。

R 中的实现

对于实现,假设我们有

而我们想用 MLE 来估计μ。我们知道泊松分布的 PDF 为

似然函数可以写成如下形式。

根据上面的似然函数,我们可以将对数似然函数表示如下。

在 R 中,我们可以通过取 PDF 的对数来简单地写出对数似然函数,如下所示。

#MLE Poisson
#PDF : f(x|mu) = (exp(-mu)*(mu^(x))/factorial(x))#mu=t
loglik=expression(log((exp(-t)*(t^(x))/factorial(x))))
dbt=D(loglik,"t")
dbtt=D(dbt,"t")

然后,我们通过分别运行dbt=D(loglik,"t")dbtt=D(dbt,"t")来计算对数似然函数对μ的一阶和二阶偏导数(然后μ对第二个偏导数)。结果如下。

dbt=(exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * (t^(x)))/factorial(x)/(exp(-t) * 
    (t^(x))/factorial(x))dbtt=(exp(-t) * (t^(((x) - 1) - 1) * ((x) - 1) * (x)) - exp(-t) * 
    (t^((x) - 1) * (x)) - (exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * 
    (t^(x))))/factorial(x)/(exp(-t) * (t^(x))/factorial(x)) - 
    (exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * (t^(x)))/factorial(x) * 
        ((exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * (t^(x)))/factorial(x))/(exp(-t) * 
        (t^(x))/factorial(x))^2

然后,我们可以开始在 r 中创建 Newton-Raphson 方法函数。首先,我们生成泊松分布的随机数作为我们用来计算 MLE 的数据。对于这个函数,我们需要如下这些参数。

  • n对于泊松分布的生成数据的数量,
  • t为μ值,且
  • iter为牛顿-拉夫逊法的迭代次数。

由于均值的泊松分布的 MLE 是μ ,那么我们可以如下编写函数的第一行代码。

x=rpois(n,t)
x.mean=mean(x)
par.hat=matrix(0,1,1)
estimate=c(rep(NULL,iter+1))
difference=c(rep(NULL,iter+1))
estimate[1]=t
difference[1]=abs(t-x.mean)

然后,我们创建循环函数来计算偏导数的和(这就是为什么我们只需要将对数似然函数的 PDF 的对数写在 R 中)、梯度向量Hessian 矩阵MLE *似值,如下所示。

for(i in 1:iter)
  {
    #First partial derivative of log-likelihood function with respect to mu
    dbt=(exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * (t^(x)))/factorial(x)/(exp(-t) * 
    (t^(x))/factorial(x))

    #Second partial derivative of log-likelihood function with respect to mu, then mu
    dbtt=(exp(-t) * (t^(((x) - 1) - 1) * ((x) - 1) * (x)) - exp(-t) * 
    (t^((x) - 1) * (x)) - (exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * 
    (t^(x))))/factorial(x)/(exp(-t) * (t^(x))/factorial(x)) - 
    (exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * (t^(x)))/factorial(x) * 
        ((exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * (t^(x)))/factorial(x))/(exp(-t) * 
        (t^(x))/factorial(x))^2

    sdbt=sum(dbt)
    sdbtt=sum(dbtt)

    #hessian matrix
    h=matrix(sdbtt,1,1)

    #gradient vector
    g=matrix(sdbt,1,1)

    #parameter
    par=matrix(t,1,1)
    par.hat=par-solve(h)%*%g
    t=par.hat[1,]
    estimate[i+1]=t
    difference[i+1]=t-x.mean
  }

当迭代达到极限时,我们需要计算每次迭代中最大似然估计的实际值和*似值之差,以评估牛顿-拉夫逊方法计算最大似然估计的性能。规则很简单:差异越小,性能越好。我们可以把它写成我们函数的最后几行代码,如下所示。

tabel=data.frame(estimate,difference)
rownames(tabel)=(c("Initiation",1:iter))
print(x)
print(tabel)
cat("The real MLE value for mu is :",x.mean,"\n")
cat("The approximated MLE value for mu is",t,"\n")

完整的函数如下所示。

nr.poi=function(n,t,iter=100)
{
  x=rpois(n,t)
  x.mean=mean(x)
  par.hat=matrix(0,1,1)
  estimate=c(rep(NULL,iter+1))
  difference=c(rep(NULL,iter+1))
  estimate[1]=t
  difference[1]=abs(t-x.mean)
  for(i in 1:iter)
  {
    #First partial derivative of log-likelihood function with respect to mu
    dbt=(exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * (t^(x)))/factorial(x)/(exp(-t) * 
    (t^(x))/factorial(x))

    #Second partial derivative of log-likelihood function with respect to mu, then mu
    dbtt=(exp(-t) * (t^(((x) - 1) - 1) * ((x) - 1) * (x)) - exp(-t) * 
    (t^((x) - 1) * (x)) - (exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * 
    (t^(x))))/factorial(x)/(exp(-t) * (t^(x))/factorial(x)) - 
    (exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * (t^(x)))/factorial(x) * 
        ((exp(-t) * (t^((x) - 1) * (x)) - exp(-t) * (t^(x)))/factorial(x))/(exp(-t) * 
        (t^(x))/factorial(x))^2

    sdbt=sum(dbt)
    sdbtt=sum(dbtt)

    #hessian matrix
    h=matrix(sdbtt,1,1)

    #gradient vector
    g=matrix(sdbt,1,1)

    #parameter
    par=matrix(t,1,1)
    par.hat=par-solve(h)%*%g
    t=par.hat[1,]
    estimate[i+1]=t
    difference[i+1]=t-x.mean
  }
  tabel=data.frame(estimate,difference)
  rownames(tabel)=(c("Initiation",1:iter))
  print(x)
  print(tabel)
  cat("The real MLE value for mu is :",x.mean,"\n")
  cat("The approximated MLE value for mu is",t,"\n")
}

对于这个函数实现的例子,假设我们想要计算 100 个泊松分布数据的最大似然估计,其*均值为 5。通过使用上面已经写好的牛顿-拉夫逊法函数,迭代次数为 5,结果如下。

> nr.poi(100,5,5)
[1]  5  4  6  9  7  8  7  2  9  4  5  6 10  1  4  8  5  7  4  3  6  3  4  4  4  7  6  6  3  6  5  5  6  4  5  5  9  5
[39]  5  3  5  6  5  8  5  3  3 12  6  5  3  4  8  5  4  5  7  8  8  5  7  2  8  3  6  4  2  3  7  5  3  4  6  5  2  6
[77]  3  3  5  4  8  2  4  7  6  5  4  3  4  7  3  4  6  6  4  7  4  4 14  4
           estimate    difference
Initiation 5.000000  2.400000e-01
1          5.229008 -1.099237e-02
2          5.239977 -2.305956e-05
3          5.240000 -1.014779e-10
4          5.240000  0.000000e+00
5          5.240000  0.000000e+00
The real MLE value for mu is : 5.24 
The approximated MLE value for mu is 5.24

作者图片

从上面的结果中,我们可以看到牛顿-拉夫逊法 MLE 产生的结果与真实的 MLE 值相同。请注意,该方法使用生成的数据,因此每次运行的结果可能不同。

结论

MLE 可以帮助我们根据对数似然函数计算估计量。我们可以用牛顿-拉夫逊法在数值上逼*极大似然估计的结果。

现在我们在这里,你可以用牛顿-拉夫逊法,用 R 来计算最大似然。关于这个话题的更多讨论,请随时通过 LinkedIn 联系我。

参考文献:

[1] Robert V. Hogg,Joseph W. McKean 和 Allen T. Craig,数理统计导论,第七版 (2013),培生教育。

[2]阿迪·本-伊斯雷尔,《求解方程组的牛顿-拉夫森法》 (1966),数学分析与应用杂志。

[3]https://book down . org/rdpeng/advstatcomp/newtons-method . html # proof-of-newtons-method

从活动跟踪器的日志中计算指标

原文:https://towardsdatascience.com/calculate-metrics-from-the-logs-of-your-activity-tracker-4e84437c3b3b?source=collection_archive---------40-----------------------

计算距离,速度和海拔增益从您的活动跟踪器的日志

弗兰克·布施在 Unsplash 上的照片

介绍

前一篇文章描述了如何从你的活动跟踪器或应用程序导入日志文件。我们还创建了一个热图,显示地图上的轨迹。本文将向您展示如何从 gpx 日志文件中计算一些基本指标,如行驶距离、速度和方位。一些活动记录器将这些信息存储在日志文件中,但大多数不这样做。

计算行驶距离

从日志文件中计算旅行的距离听起来很简单。测井记录由一系列经度/纬度位置组成,因此计算所有时间之间的距离,并将这些时间相加,即可得出行进的距离。但是计算两个经度/纬度位置之间的距离很繁琐,即使是很短的距离。

我们将尝试几种方法来找到速度和准确性之间的*衡。您可能已经猜到,与低精度相比,高精度需要更多的计算。我们将把上一篇文章中的数据框架用于所有活动,并过滤掉一个:

df = df[df.name == 'XXXXX'].reset_index(drop=True)
df = df[['timestamp', 'lat', 'lon', 'elevation']]

在这种情况下,我们根据名称过滤一个活动,但也可以使用源文件或开始日期和/或时间。

*坦的地球

用 lon/lat 计算距离需要一些三角学知识。三角函数以弧度作为输入。gpx 文件将经度和纬度存储为度数,因此我们首先添加(第 4–5 行)以弧度表示的经度和纬度。

为每个距离公式创建一个名为dist_xxxx的方法,计算结果将存储在名为dist_xxxx的列中。第 14 行循环所有的实现(到目前为止只有一个),第 16 行创建列 an,在第一行存储0。第 17–19 行调用距离函数,将当前位置和先前位置作为参数。结果存储在适当的列中。第 20 行根据距离公式打印行驶的总距离。

第一个实现假设两点之间的距离是一条直线(勾股定理)。它没有考虑到当你靠*其中一个极点时,经线会彼此靠*。假设这些线*行,经度为 1 度,距离为 110.25 公里。计算很简单,但即使在短距离内,误差也相对较大。结果是 10.8 公里。

flat             : 10864.7117

地球是一个球体

一个简单的改进是假设地球是一个完美的球体。当你越靠*两极,两条经线之间的距离就越小。

纬度和经度(来源:维基百科

这个距离取决于所在位置的纬度。在赤道是 110 公里,但在两极是 0 公里。通过将 110 km 乘以纬度的余弦,应用球体形状(0 度的余弦为 1,90 度的余弦为 0)。

活动日志每隔几秒钟存储一次位置。看起来这些距离的误差可能很小,但是总距离变化很大:

flat             : 10864.7117
sphere           :  8057.7413

差别是惊人的 26%,但这种差别取决于我活动的纬度。如果在赤道附*记录到这种活动,它将接*于 0。根据上面的结果,你可以计算出该活动是在纬度 50 度附*记录的。所以要小心,由于信息量有限,活动的位置从地球上的某个地方缩小到纬度约为 50 度的范围内。

地球是椭球体

那么地球是球体吗?不,它不是,它是一个椭球体。赤道的半径(“水*”)是 6378 公里,从极点到极点的半径(“垂直”)是 6356 公里。

椭圆计算(来源:维基百科)

FCC 已经定义了公式来计算两点之间的距离,其中考虑了这个椭球体形式:

地球的小椭球形对计算的距离有影响:

flat             : 10864.7117
sphere           :  8057.7413
ellipsoid        :  8143.150109

哈弗辛函数

哈弗辛函数是计算球体上两点间距离的另一种方法。最早的查找表形式的实现可以追溯到 1805 年。它是基于哈弗辛的定律,该定律描述了两点之间的距离,该距离基于它们与网格原点一起形成的三角形。哈弗辛函数没有考虑地球的椭球形状。

与其他实现相比的哈弗线距离:

flat             : 10864.7117
sphere           :  8057.7413
ellipsoid        :  8143.1501
haversine        :  8126.8135

还有更多像文森特的公式一样的计算方法。但是从这里我们将采用椭球体实现:

df = df[['timestamp', 'lat', 'lon', 'elevation', 'latrad', 
         'lonrad', 'dist_eucledian']]
df = df.rename(columns={"dist_eucledian": "dist"})

带有距离栏的活动日志(图片由作者提供)

计算速度

所以现在距离有了,就可以计算速度了。速度是距离除以时间,因此我们需要获得两个日志条目之间的时间,并将行驶距离除以该时间(速度单位为 km/h):

那很简单…让我们想象一下结果:

df.speed.plot(figsize=(15,8))

速度随时间的变化(图片由 auhtor 提供)

的确,这好得令人难以置信。该图显示了一个行走活动,速度肯定不是恒定的,但它是可变的吗?不太可能。这是怎么回事?

正如您在最后打印的数据帧中所看到的,每秒钟都会记录一次该位置。*均速度 1.6 米/秒。但是 Garmin 活动追踪器公认的精确度是 3 米。在实践中,它可以更精确,但会发生一些不准确,并且对于 1 米的预期位移,不准确性相对较高。在整个活动过程中,它会工作(见显示的*均速度 5.1 公里/小时),但在这个详细的水*上不是那么好。

为了过滤掉极端情况,我们将实现一个*均速度的策略。我们想要每 30 秒的*均速度。为了确定要*均的行数,我们首先确定数据集中两行之间的*均时间。用 30 除以这个数,我们得到要*均的行数。我们使用 dataframe 的rolling()函数来创建移动*均值:

速度,移动*均线(图片由作者提供)

这是速度的一个更好的表示。选择 30 秒是基于我的行走习惯。在旅途中,每个地点拍照大约需要 30 秒。使 30 秒的时间间隔更长会使识别这些停车点变得更加困难。

在第一张图中,停车瞬间将速度降至零,30 秒移动*均速度在行程后期降至 1 km/h 或 3 km/h 以下。

让我们看看滚动窗口大小的影响:

df['speed_ma_10'] = df['speed'].rolling(window=10, 
                          min_periods=1, center=True).mean()
df['speed_ma_30'] = df['speed'].rolling(window=30, 
                          min_periods=1, center=True).mean()
df['speed_ma_60'] = df['speed'].rolling(window=60, 
                          min_periods=1, center=True).mean()
df[500:1000][['speed_ma_10', 'speed_ma_30',
              'speed_ma_60']].plot(figsize=(15,8))

多个滚动窗口(图片由作者提供)

滚动窗口越小,停止时刻越明显,但窗口越大,停止时刻越不明显。滚动窗口越大,图形越*滑。找到合适的窗口大小是准确性和可读性之间的*衡。对于我的使用,我把它保持在 30 秒,但是你需要根据你的规格来改变它。

请注意,无法使用df.iloc[::30, :]分割数据帧并在 30 行中保留 1。行驶的距离将是不正确的,因为 31 和 60 之间的最短路径被用于计算速度,从而切断了路径上的所有拐角:

分割数据帧对行驶距离的影响(图片由 authot 提供)

海拔

当确定上升和下降时,同样的问题出现了。由于高程数据的不准确性,分析原始高程数据会导致上升和下降数字较高:

高程数据(图片由作者提供)

总的上升和下降是用每行的高程*均值计算的,并对下降的负数和上升的正数求和:

与海拔高度和活动概况相比,上升和下降的数字较高。通过使用移动*均值*滑与速度相当的高程数据,可以提高这些值。

30 秒移动*均值保持高程数据的形状,并过滤小的差异,正如您在高程数据的子集中看到的,滚动窗口由 30、60 和 120 行组成:

滚动窗口对高程数据的影响(图片由作者提供)

最后的话

使用活动跟踪器跟踪您的活动会产生一个包含位置和高度数据的详细数据文件。记录的数据包含一些(或大量)噪声,使得从数据中得出结论更加困难。在计算距离、速度和高度等指标之前,需要进行一些数据清理。

使用简单的移动*均滤波器来*滑数据。也可以使用更复杂的滤波器,如 FIR 和 Butterworth 。从数学的角度来看,这非常有趣,但解释起来要复杂得多(与移动*均线相比)。过滤后的数据不会有更好的价值。这些滤波器从信号中移除高频噪声,并且在噪声还包含模式时工作得最好。这在我们的活动数据中并非如此。当我们创建一个带有高频噪声的信号时,IFR 滤波器将比移动*均效果更好:

x = np.arange(0, np.pi, 0.05)
y = np.sin(x) + 0.2*np.sin(x*40) + + 0.05*np.sin(x*80)df = pd.DataFrame(y,x, columns=['y'])
df = df.reset_index().rename(columns={'index': 'x'})df['y_ma'] = df['y'].rolling(window=5, min_periods=1).mean()
#FIR filter
h = sg.get_window('triang', 5)
fil = sg.convolve(df.y, h / h.sum())
df['y_fir'] = fil[:len(df)]df.plot('x', ['y', 'y_ma', 'y_fir'], style=['--','-','-'])

IFR 滤波信号比移动*均值更接*原始正弦:

FIR 滤波器在去除高频噪声方面更好(图片由作者提供)

理解你的数据是成功的关键:-)。

在你的活动日志文件中隐藏着更多的数据。我们将在下一篇文章中揭开它们的面纱。

我希望你喜欢这篇文章。要获得更多灵感,请查看我的其他文章:

  • 根据你的活动跟踪器的日志创建热图
  • 用 Python 删除文本中的个人信息
  • Python 中字符串的并排比较
  • 使用 Python 实现并行 web 请求
  • 所有公共交通工具都通向乌得勒支,而不是罗马
  • 使用 OTP 和 QGIS 可视化行程时间

免责声明:本文包含的观点和意见仅归作者所有。

在 Data Studio 中计算一个月的剩余天数

原文:https://towardsdatascience.com/calculate-remaining-days-of-a-month-in-data-studio-97debe22e68d?source=collection_archive---------12-----------------------

这并不像听起来那么简单!

Joshua Hoehne 在 Unsplash 上拍摄的照片

介绍

你有没有遇到过这样的情况,你创建一个数据工作室的报告,有很多障碍要通过?

上周我也遇到过类似的事情。我正在使用不同的数据源、计算字段、混合等进行仪表板自动化工作,突然我意识到我需要一个非常具体的指标。

那是什么?

我想计算到月底为止每天可用的*均预算。但是在 Data Studio 中,没有提供该月剩余天数的字段。作为一个纯 90 后的孩子,我从谷歌搜索开始。经过一些搜索和博客文章阅读,我意识到没有工作的解决方案,将涵盖我的需求。大多数解决方案建议创建一个谷歌表,然后计算一个月的剩余天数,然后将其与我的 Data Studio 仪表板连接,诸如此类。

不够好!正如我所说的,我正在为一个自动化任务工作。所以,我开始研究自己的解决方案。

它并不花哨,但很有效…

该过程

对于我自己的任务,我使用了 Google Ads 数据源。当然,您可以使用自己的数据源,但是您必须适当地调整字段,以便解决方案能够工作。

流程背后的想法:我需要哪些领域?

  1. 每月的一个字段
  2. 一个带有当月剩余天数的字段

在整个过程中,我们将需要一些额外的修改,但主要的想法是创建这两个字段。

让我们看看实践中…

正如你可能已经知道的,谷歌数据工作室定制字段,不能在一个案例函数中结合维度和度量——真扫兴。因此,像下面这样的字段最终将不起作用:

CASE
  WHEN Month = 'January' THEN 31
  WHEN Month = 'February' THEN 28
  ...
END

诀窍是表现为两个场都是二维的。

字段 1: 一年中的月份

对于我的解决方案,我们希望将月维度从日期类型修改为文本类型。我不喜欢修改我的原始字段,所以我们将创建一个新字段,其中只包含月份维度。就像下面这样:

自定义字段:一年中的月份

Data Studio 会自动将您的字段识别为日期类型。

  • 转到数据源以更改自定义字段的类型

  • 单击“类型”列中的项目
  • 选择文本选项

字段 2:每月的天数

现在我们有了一年中的月份字段,我们可以创建一个新字段来为每个月分配正确的天数:

自定义字段:每月的天数

⚠️In 为了在我的计算中调用我的“一年中的月份”字段,我创建了一个表来查看我的字段的格式。我建议您对自己的数据源也这样做。

字段 3: Num(每月的天数)

正如你可能已经注意到的,在我的计算中,我给每个月分配了一个数字**作为维度。**我们需要用一个新的自定义字段来解决这个问题…

自定义字段:Num(每月的天数)

⚠️When:你将“Num(每月的天数)”字段添加到一个可视或表格中,你必须使用 MAX ,作为你的聚合方法。

到目前为止,我们应该能够用您的月维度和我们创建的 Num(每个月的天数)创建一个数据表,并且能够看到每个月的正确天数(!idspnonenote)。!!不要忘记使用 MAX!!!).

字段 4:本月剩余天数

接下来是“本月剩余天数”。这当然是这篇文章的最终目的!

自定义字段:一个月的剩余天数

我们流程的最后一步,当您使用我们的“本月剩余天数”字段时,您应该定义符合您需求的日期范围。我喜欢使用“本月至今”,它不包括当天,但是您也可以使用“本月”来获得总天数。在下表中,您可以看到正在运行的字段:

实际日期:2021 年 1 月 17 日

万岁!!!🎆

最后的想法

我告诉过你,这不会是幻想…

Data Studio 是一个强大的工具,功能丰富,但有时,像这样的重要字段会丢失。有时候很容易计算,有时候却不容易。可能还有其他更好的方式,但我希望我为你节省了一些填写谷歌表单的时间。🤓

我叫 Alexandra Poulopoulou,是 Reprise Digital 的数据和分析主管。在我的职业生涯中,我参与了几个分析项目,以推动成功的商业决策。

如果你喜欢刚刚阅读的内容,请在 Medium 、 LinkedIn 或 Twitter 上关注我,因为还会有很多类似的活动。下次见…

用 Python 计算偏斜度(有例子)

原文:https://towardsdatascience.com/calculate-skewness-in-python-with-examples-pyshark-b7467dfa166d?source=collection_archive---------43-----------------------

在本教程中,我们将探索如何在 Python 中计算偏斜度

作者图片

目录:

  • 介绍
  • 什么是偏斜度?
  • 如何计算偏斜度?
  • Python 中如何计算偏斜度?
  • 结论

介绍

偏斜是我们在日常生活的许多领域观察到的现象。例如,人们经常在网上搜索的是感兴趣的特定国家的工资分布。这里有一个例子:

来源

在 Statista 找到更多统计数据

从上面的图表中,我们可以看到 2019 年加拿大的收入分布,*均收入大约在 40,000 美元到 50,000 美元之间。

我们还注意到,数据不是正态分布在*均值周围,因此存在某种类型的偏斜。

在上面的例子中,很明显有一些负偏斜,分布的左尾更粗。但是为什么会有歪斜呢?我们看到,分布的中位数将在 60,000 美元左右,因此它大于*均值;并且分布的模式将在$60,000 和$70,000 之间,因此产生了我们上面观察到的偏斜。

其中峰度衡量的是两个尾部中是否存在极值(或者只是尾部是重还是轻),偏斜度关注的是基于极值(或者只是尾部的对称性)来区分分布的尾部

为了继续学习本教程,我们需要以下 Python 库: scipy

如果您没有安装它,请打开“命令提示符”(在 Windows 上)并使用以下代码安装它:

pip install scipy

什么是偏斜度?

在统计学中,偏度是概率分布关于其*均值的不对称性的度量,有助于描述概率分布的形状。基本上,它衡量给定分布与正态分布(对称)的差异程度。

偏斜度可以取几个值:

来源

  • 正-当分布具有较厚的右尾且众数
  • Negative — observed when the distribution has a thicker left tail and mode>中值>*均值时观察到。
  • 零(或接*零)-当分布关于其均值对称且*似众数=中位数=均值时观察到。

注:上述定义是一般化的,值可以根据分布族的不同而有不同的符号。

如何计算偏斜度?

在大多数情况下,样本偏度的计算方法是 Fisher-Pearson 偏度系数(注意:还有更多计算偏度的方法:Bowley,Kelly's measure,Momental)。

这种方法把偏斜度看作分布的第三个标准化矩。

听起来有点复杂?按照下面的步骤,对计算有一个完整的理解。

分布的第 k 阶矩可以计算为:

作者图片

如前所述,偏斜度是分布的三阶矩,可计算如下:

作者图片

其中:

作者图片

如果您想要校正统计偏差,那么您应该求解调整后的 Fisher-Pearson 标准化力矩系数,如下所示:

作者图片

举例:

上面是很多公式。为了使这一切成为一个更好理解的概念,让我们来看一个例子!

请考虑以下代表学生考试成绩的 10 个数字序列:

X=【55,78,65,98,97,60,67,65,83,65】

计算 x 的*均值,我们得到:x̄=73.3.

求解 m_3:

作者图片

作者图片

求解 m_2:

作者图片

作者图片

求解 G1:

作者图片

在本例中,Fisher-Pearson 偏斜系数等于 0.647511,表明数据中存在正偏斜。另一种检查方法是查看这些值的众数、中位数和*均值。这里我们有 mode

In addition, let’s calculate the adjusted Fisher-Pearson coefficient of skewness:

Image by Author

How to calculate Skewness in Python?

In this section we will go through an example of calculating skewness in Python.

First, let’s create a list of numbers like the one in the previous part:

To calculate the Fisher-Pearson correlation of skewness, we will need the scipy.stats.skew 函数:

我们应该得到:

0.6475112950060684

要在 Python 中计算调整后的偏斜度,请将 bias=False 作为参数传递给 skew() 函数:

我们应该得到:

0.7678539385891452

结论

在本文中,我们讨论了如何使用 scipy 库在 Python 中计算一组数字的偏斜度。

如果您有任何问题或对一些编辑有建议,请随时在下面留下评论,并查看更多我的统计文章。

原载于 2021 年 7 月 26 日 https://pyshark.comhttps://pyshark.com/skewness-in-python/

为分类模型选择基线精度

原文:https://towardsdatascience.com/calculating-a-baseline-accuracy-for-a-classification-model-a4b342ceb88f?source=collection_archive---------8-----------------------

选择一个简单的基线精度来证明您的分类模型在某个问题上有技巧

罗伯特·阿纳奇在 Unsplash 上的照片

当你评估一个新的机器学习模型,并最终得到一个准确度数字或其他指标时,你需要知道它是否有意义。特别是在不*衡的分类模型中,看起来你的模型并不比猜测好多少。什么样的精度才足以称你的模型有用?

这篇文章只是为了展示你的模型的简单的基线准确性,我发现这很有用。

问题是

我创建了一个选举模型,使用经济指标预测了美国所有 3200 多个县(民主党或共和党)的投票习惯。该模型的准确率为 86%。这听起来很棒,直到你意识到美国 84%的县都投票给共和党。这些县碰巧更小,更农村,所以有更多。像许多数据集一样,我有明显的阶级不*衡。

你可以简单地预测所有的县都是共和党的,准确率为 84%。我的模型真的仅仅比猜测每个县的共和党好一点点吗?

零速率分类器

我们刚刚描述的模型基线有一个名字。

ZeroR(或零比率)分类器总是分类到最大的类,换句话说,只是*凡地预测最频繁的类。对于一个两种结果的模型来说,只是随波逐流往往是正确的。

总是选择多数组(ZeroR 分类器)作为基线是有见地的,并且是任何分类模型都应该选择的。对于一个机器学习算法来说,要证明它在某个问题上有技巧,它必须达到比这个零值更好的精度。

对于高度不*衡的问题(如投票分类问题),一个比 ZeroR 稍高一点的模型精度可能是非常重要的。不管怎样,你的模型必须比 ZeroR 更好才能被认为对问题有用。

随机速率分类器(加权猜测)

现在我们将把我们的高中数学运用到工作中。我们可以使用的另一个基线策略是,如果我们猜测每个类的加权百分比,看看我们的准确度会是多少。该值将始终低于 ZeroR 值,因此它不应该是您的下限基线。相反,它可以用来解释和理解您的结果,即您的模型增加了多少价值。

随机比率分类器—在进行随机类别分配时应用类别分配的先验知识。

我们将针对几个分类问题研究这两种策略。

抛硬币

让我们先来看一个抛硬币模型。50%的结果是反面(0),50%的结果是正面(1)。

我们的基线策略在这里是如何工作的?:

  • 零——猜测所有的头像会给我们 50%的准确率。
  • 随机比率——我们凭直觉知道,猜测 0.50 的正面和 0.50 的反面也会给我们 50%的准确率。我们将有一半正面预测和一半反面预测是正确的。

猜测随机速率分类器的半头半尾在数学上是这样工作的:

Odds of Guessing Heads Correct: 0.50 * 0.50 = 0.25
Odds of Guessing Tails Correct: 0.50 * 0.50 = 0.25Baseline = 0.50**2 + 0.50**2 = 0.50

不*衡的结果

现在我们来看一个不是 50/50 的。假设结果是 75/25。我们现在将对猜测进行加权,这样我们可以在 75%的情况下预测大多数结果。这个随机速率猜测策略看起来像这样

Odds of Guessing Minority Correct: 0.25 * 0.25 = 0.0625
Odds of Guessing Majority Correct: 0.75 * 0.75 = 0.5625Baseline = 0.25**2 + 0.75**2 = 0.625

如果我们以这个速度猜测,我们的正确猜测率只有 62.5%。任何在这个基线上改进的机器学习模型都是增值的,但也必须高于零或 75%的阈值才能用作预测器。

我们的投票示例

那么我在本文开头描述的投票模型到底做得怎么样呢?它高于零基线,所以这个模型是有用的。如果我们猜测实际速率,我们还可以找出我们的基线,然后将其与我们的模型准确性进行比较。

Odds of Guessing Democratic Correct: 0.16 * 0.16 = 0.0256
Odds of Guessing Republican Correct: 0.84 * 0.84 = 0.7056Baseline = 0.16**2 + 0.84**2 = 0.73

所以用随机加权猜测,我们只能预测 73%的县。我们的实际准确率是 86%。这比加权猜测的理论值提高了 13%。这个看起来没什么前途的模型,无疑增加了重要的价值。它也在 ZeroR 基线之上,所以这个模型对这个问题很有用。

多类问题

你能为多类问题这样做吗?当然可以。

我最*做了一个 Twitter 情绪分类器,它将一条推文的情绪分为积极、消极或无情绪。这些班级在以下方面不*衡:

No emotion toward brand or product    0.593
Positive emotion                      0.328
Negative emotion                      0.080

使用我们的猜测策略的理论基线是:

0.593**2 + 0.328**2 + 0.080**2 = 0.465633

我们的实际准确率是 0.81,所以机器学习给我们的理论基线增加了 34%。这很重要。更重要的是,如果我们对每一个结果都预测了“无情绪”,我们的准确度也远高于 0.59 的零值。

要点和建议

  • 你的模型必须比零规则(ZeroR)做得更好,才能在预测中有用。这是无法回避的。
  • 您可以将您的模型与随机猜测的理论基线进行比较,并使用它来评估您的模型的有用性。
  • 您可能会发现其他一些有用的基线(统一猜测、随机猜测和一个规则就是其中的几个)。
  • 查看sk learn . dummy . dummy classifier,它为以下基线策略提供了自动化解决方案:、【分层】、【最频繁】、【先验】、【统一】、【恒定】。
  • 当评估不*衡分类问题的准确性时,考虑查看 AUC。
  • 在构建模型之前创建基线,并建立用于评估最终模型的规则。

此处展示的技术为您的模型性能提供了一个“现实检查”,对于广大观众来说是可以理解和解释的(我可以很容易地用非技术演示来解释这一点)。他们帮助我评估和理解我自己的模型,我希望你也能发现它们有用。

计算火灾探测的可靠“黄金时间”

原文:https://towardsdatascience.com/calculating-a-reliable-golden-time-for-fire-detection-8fa8f6086d57?source=collection_archive---------51-----------------------

将关于野火的空间信息转换成基于时间的信息。线性回归增加了可信度。

在 Alchera Inc .工作期间,我被分配到视觉异常检测技术产品部门工作,目前我们正在从事基于摄像头的烟雾和火灾检测。野火缓解空间中的典型对话领域是“黄金时间”,即从着火事件到需要检测它以防止它变成灾难之间的时间量。虽然有许多因素在起作用,但下面的文章是我试图对火灾探测的黄金时间进行适当的分类,以便根据部署位置为我们的火灾探测系统提供一个明确的基准。

在我开始之前,我想说清楚野火的灾难是什么。如果不对“灾难”一词进行定义,黄金时间的概念也会过于主观。我将“野火灾难”定义为一场超出消防员在“失控”之前将其扑灭的能力的火灾。那么,让我把‘失控’的意思说清楚。我建议,考虑控制火灾的实体,如果火灾蔓延范围/速度,经济损失,灭火花费的时间等。变得不可预测,不可计算,火势处于‘失控’状态。现在我准备好继续问题/解决方案分析了。

问题:关于防止野火失控的最晚可能时间,没有确定的“基于时间”的信息。

解决方案:利用既定的可防御空间面积、火势蔓延速度、风力条件和湿度数据,我们可以创建一个代理公式来计算给定位置的黄金时间。

可防御空间是“建筑物周围的自然和/或景观区域,经过维护和设计以降低火灾危险。在野火的情况下,该术语尤其用于荒地-城市界面(WUI)。”这个空间降低了火势从一个区域蔓延到另一个区域或一个结构的风险,并为消防队员提供了通道和一个更安全的区域来保卫受威胁的区域。这意味着,即使在森林中的随机区域发生火灾,只要它在可防御的空间内,消防员就可以阻止它进一步蔓延。

根据 CalFire 网页上的一篇文章,防御空间有两种类型的区域。1 区从建筑物延伸 30 英尺(如果发生野火,它将是起火点)。区域 2 从建筑物或着火点向外延伸 100 英尺。现在我们有了野火的空间数。

然后,韩国国立森林科学研究所(NIFOS)进行了一项实验。他们根据风速和土地坡度测试了火势蔓延的速度。以下是 NIFOS 实验的结果。

作者图片

地势越陡,火势蔓延越快。此外,大风会导致火势蔓延得更快。虽然需要更多的原始数据来获得更好的准确性,但为了制定一些通用的代理公式,我进行了多元线性回归。

(当然,它可以是取决于变量的二次函数;然而,为了简单起见,让我们假设它是线性关系)

作为线性回归的结果,X1(风速)的系数是 1.245625,X2(土地坡度)的系数是 0.170425,Y 截距是-2.58388;

为了计算可防御空间的黄金时间,我们用传播速度来划分空间范围。

作者图片

  • 100 英尺= 30.48 米
  • 30.48 米/传播速度(按米/分钟)=黄金时间(分钟)

因此,我们黄金时间计算的结果如下:

作者图片

作者图片

因为基本的线性回归公式由于数据相当缺乏而相当极端,所以我们可以在低风速和低坡度的情况下稍作调整以使数字合理。可以将 Y 截距设置为 0,这个数字看起来更有说服力,但与 NIFOS 数据相比有些保守(图片由作者提供)

从分析中可以看出,野火的黄金时间会因位置而异,只要我们知道位置的坡度并监控该区域的风速,就有可能为任何给定的位置创建实时黄金时间。例如,美国的加利福尼亚州是全球最大的野火危害区之一,从春季到秋季野火最为频繁。在此期间,加州洛杉矶的*均风速约为 3.2 米/秒。假设加利福尼亚的一个位置有 10°的坡度,基本线性模型(LM)给出 9.8 分钟的黄金时间,调整后的 LM 给出 7.7 分钟的黄金时间。

虽然这是一个合理的估计,如果不是粗略的话,但仍然有一个变量没有包括在内:湿度。有理由认为湿度会极大地影响火势的蔓延。理想情况下,上述分析还应包括上述线性回归中的湿度。不幸的是没有足够的原始数据。尽管如此,还是有必要看看湿度是否与火势蔓延呈负相关。

两篇著名的论文论述了这个问题。根据湿度和温度对火焰在滤纸上向下蔓延的影响(2000) 由铃木、Kushida 和 Dobashi 提出,绝对湿度和相对湿度都与火焰蔓延速率负相关。它说火焰传播速度随着湿度的增加而降低,当绝对湿度高于临界值时,火焰传播速度变为零。下面是一个图表。

铃木,Kushida,Dobashi (2000),湿度和温度对滤纸上向下火焰蔓延的影响,日本东京 113–8656()T4【https://pdf . semantic scholar . org/38 a2/0647392 C9 c 145 CFB 8 f 76173088 EC 79 f 38 c 7b . pdf

此外,相对湿度对波兰中部森林火灾的影响研究了湿度和野火点燃次数之间的关系,条件是与湿度相关的环境因素。表 3 显示,火灾爆发与相对湿度之间通常存在负相关关系。

konca-kdzierska,Pianko-Kluczyńska (2018 年),*相对湿度对波兰中部森林火灾的影响,*波兰波德莱娜 61,01–673(https://content . science do . com/download pdf/journals/FRP/79/3/article-p269 . XML)

要提供尽可能精确的计算,这一篇文章是不够的;我们需要用更多的原始数据进行另一个实验,将所有四个变量(三个自变量和一个因变量)考虑在内。然而,值得注意的是,本文提出的方法是可行的,并适用于实际计算。

不管怎样,我相信我们已经提出了最可靠的方法来计算野火探测的黄金时间。利用这一点,我们的目标是将这一计算引入我们的火灾探测工作,为我们的客户增加情景意识。Alchera Inc .目前正在加州各地的摄像机上部署基于机器视觉的火灾检测,在 2020 年已经捕捉到数百起早期野火点火,并在 2021 年继续这样做。

关于 Alchera: Alchera Inc .是一个人工智能专家团队,他们解决需要人工智能但受资源限制的问题。凭借世界级的速度和准确性,Alchera 将系统和硬件不可知的 AI 技术部署到影响社会的行业。

参考

[1]https://en . Wikipedia . org/wiki/Defensible _ space _(fire _ control)

[2]https://www . readyforwildfire . org/prepare-for-wild fire/get-ready/defensible-space/

[3] 2016.03.23.韩国보도자료国立森林科学研究所

[4]铃木,Kushida,Dobashi (2000),*湿度和温度对滤纸上向下火焰传播的影响,*日本东京 113-8656

[5]Konca-kdzierska,Pianko-Kluczyńska (2018),*相对湿度对波兰中部森林火灾的影响,*波兰波德莱娜 61,01–673

计算和设置阈值以优化逻辑回归性能

原文:https://towardsdatascience.com/calculating-and-setting-thresholds-to-optimise-logistic-regression-performance-c77e6d112d7e?source=collection_archive---------1-----------------------

如何创建一个简单的类来优化精确度、召回率、f1 分数、准确度、TPR-FPR 或定制成本函数的阈值

照片由肖恩·林在 Unsplash 拍摄

背景

我已经了解了逻辑回归、混淆矩阵、ROC 曲线、阈值等。我参加过各种数据科学课程,但我从未完全理解它们,并希望更详细地探索它们。

此外,我还在网上看到了各种例子,说明如何在给定阈值的情况下重新计算真假分类,但这些例子没有提供我在现实世界中使用阈值所需的细节。

我怀疑可能有一种方法可以将阈值优化封装到一个简单的面向对象的类中,这样我就可以在将来轻松地使用它们,因此本文记录了我实现这些目标的学习之旅。

准备

让我们从导入我们将需要的库开始…

我们还需要一些数据来操作。我选取的数据是来自 ka ggle—https://www . ka ggle . com/c/credit-default-prediction-ai-big-data/overview的银行信用违约数据。

我对这些数据进行了一些清理,包括处理空值、转换分类特征和*衡数据以均匀地表示真假分类,这超出了本文的范围。下面导入的数据包括所有这些数据清理步骤…

作者图片

让我们通过将数据分为测试和培训来完成准备工作,这样我们就可以根据培训数据进行优化,稍后再回到测试数据上来…

((4754, 32), (1189, 32), (4754,), (1189,))

标杆管理

初步分析

好了,让我们对测试数据进行基本的LogisticRegression拟合,然后查看结果...

array([0, 0, 0, ..., 1, 0, 0], dtype=int64)

混淆矩阵的可视化将有助于我们评估性能…

作者图片

银行数据被用来预测哪些客户会继续违反他们的信贷协议,哪些不会违约。

我们可以直接看到,一个基本的逻辑回归有 79%的准确性,预测了 352 个客户将违约,3395 个客户不会违约。

听起来很不错,对吧?好吧,如果我是接收这个算法的经理之一,我的第一个问题会是——“那 934 个假阴性呢?”。有* 1000 名客户没有被算法预测为违约,而是继续违约。

如果银行默认账户的*均成本是 10,000 英镑,我的数据科学团队刚刚让企业损失了 934 万英镑,对此我肯定不会满意!

这个简单的分析揭示了三个关键点-

  • accuracy测量可能并不总是评估分类算法性能的最佳方式。
  • 分类算法的优化方式在很大程度上取决于企业想要实现的目标。
  • 必须对算法进行适当的优化,以实现预期的业务成果。

进一步分析

更深入的挖掘将揭示我们基本算法性能的所有关键指标-

accuracy = 0.7881783761043332 precision = 0.8282352941176471

recall = 0.2737169517884914

f1 score = 0.4114552893045003

true positive rate (tpr) = 0.2737169517884914

false positive rate (fpr) = 0.02104959630911188

tpr-fpr = 0.2526673554793796

我通常也会看一下 ROC(受试者工作特性)曲线

作者图片

黑点代表最佳点的一种解释。

一种可用于计算 ROC 曲线上最佳点的方法是𝑇𝑃𝑅−𝐹𝑃𝑅,其中𝑇𝑃𝑅=的真阳性率和𝐹𝑃𝑅=的假阳性率。𝑇𝑃𝑅−𝐹𝑃𝑅达到最大值的点是最佳点。

该图显示,如果我们将逻辑回归的阈值设置为 0.31261,而不是默认值 0.5,那么我们将优化𝑇𝑃𝑅−𝐹𝑃𝑅.的逻辑回归算法

快速回顾一下阈值

如果所有这些关于阈值的讨论令人困惑,有许多在线文章将解释细节,但最简单的设想是这样的

我们数据的每一行将被分类为Default=TrueDefault=False。逻辑回归为每一行分配一个带来True的概率,然后对每一行进行预测,其中该概率为> = 0.5,即 0.5 是默认阈值。

一旦我们对其工作原理有了更多的了解,我们就可以使用 0.5 的默认值来改进和优化我们预测算法的结果。

分析结论

根据这个快速分析,证据表明我们可以做得比接受默认阈值 0.5 更好,默认阈值是在作为sklearn.linear_model库的一部分的LogisticRegression算法中实现的。例如,我们已经知道,如果我们改变默认值为 0.31261,我们将优化𝑇𝑃𝑅−𝐹𝑃𝑅TPR−FPR.

然而,没有简单的方法来改变LogisticRegression类中的阈值,通常数据科学家将手动完成这一点,并在多个项目中重复工作。

我们需要的是一个简单的类,每当我们想要优化阈值时,它就会为我们做这件事。

自动化阈值计算

这是我第一次尝试编写一个类来扩展LogisticRegression类,以优化基于𝑇𝑃𝑅−𝐹𝑃𝑅TPR−FPR 计算的阈值。它由一个类定义、一个名为threshold_from_optimal_tpr_minus_fpr的方法和一个predict方法组成,后者覆盖了基类方法,使threshold参数能够被传入...

有了这个新的实用程序类,我们现在可以轻松地将训练数据与它相匹配,要求该类告诉我们𝑇𝑃𝑅−𝐹𝑃𝑅TPR−FPR 的最佳阈值,然后使用该阈值返回一组新的预测…

(0.3126109044627986, 0.3383474055618039)

作者图片

嗯,这种优化确实改变了结果的形状,如混淆矩阵所示。假阴性和真阴性减少了,而假阳性和真阳性增加了。

这个发现让我问了一个问题——“还有什么其他的优化方法?”

精确和召回的快速回顾

评估分类算法结果的另一种方式是绘制混淆矩阵的精确度和召回率,而不是 FPR 和 TPR。

快速提醒一下,精确度和召回率的计算如下-

作者图片

即精度是混淆矩阵的右手列,精度是底行。

𝑇𝑃𝑅−𝐹𝑃𝑅通常用于挑选 ROC 曲线上的最佳点,而 F1 分数可以用于挑选精度-召回曲线上的最佳点。F1 分数的计算方法如下-

作者图片

F1 分数是精确度和召回率的调和*均值。我们使用调和*均值而不是简单*均值,因为它会惩罚极值。

我们默认算法的精确度和召回率的关系图如下所示-

作者图片

这里我们可以看到最佳(即最大)F1 分数是 0.5237148537347345,最佳精度和召回率分别是 0.41 和 0.72。从算法中产生这个结果的阈值是 0 . 32660 . 386383863686

自动化阈值计算需要 2

扩展LogisticRegression类的第二次尝试增加了一种优化 F1 分数的新方法,以产生最佳精度和阈值-

现在,我们可以很容易地使用该类的新版本来告诉我优化 f1 分数所需的阈值,然后使用该值来微调算法,以获得最佳精度和召回率…

(0.3126109044627986, 0.5237148537347345)

作者图片

这个版本大大减少了假阴性,代表了最大可能的优化精度和召回。

现在想象一下,我把新模型带回给银行的管理团队,他们说“嗯,这是一个改进,但我们必须召回 90%的产品,这种模型才能有效”。

记住,回忆是𝑇𝑃/(𝑇𝑃+𝐹𝑁)而此刻这个模型有 922 / (364+922) = 71.7%。

我们需要向管理团队解释召回率和精确度是相互权衡的,因此如果模型被调优为 90%的召回率,精确度肯定会降低,但是如果这是可以接受的,如何实现呢?

自动化阈值计算需要 3

第三次尝试增加了两种新方法来计算给定特定召回(和精度)所需的阈值,现在可以使用这两种方法来实现管理团队要求的性能-

(0.19142214362243234, 0.35382262996941893)

作者图片

我们可以看到,管理团队要求的召回已经实现,因此精确度从 41.3%降到了 35.4%。

自动化阈值计算需要 4

在这一点上,我有点忘乎所以了,我想要一个可以实现自定义成本函数的优化版本。

让我们假设管理团队现在给我们以下新信息-

  • 每一个真负值意味着我们可以向不会违约的客户销售 10,000 份额外的信贷产品。
  • 每一次误报都会让我们损失 1000 英镑,因为我们本可以吸引这些客户,但我们却避开了他们。
  • 因为我们未能干预并阻止这些客户违约,所以每一次假阴性都会让我们损失 1500 英镑。
  • 每一个真正的积极有助于我们防止信贷违约,每一个都产生 20,000 英镑的新收入。

实现这一点的“成本函数”很容易构建

再做一点工作,我们可以修改我们的类,计算出优化这个成本函数所需的阈值,然后应用它-

…可以按如下方式使用-

(0.4324142856743824, -40033500)

新的混淆矩阵看起来像这样..

作者图片

…这是我们的自定义成本函数值与阈值的关系图…

作者图片

阈值计算自动化—最终版本

鉴于我已经意识到最佳精度的阈值可以使用与定制成本函数非常相似的方法来计算,我想我会将其添加到最终版本中。

毕竟,许多数据科学竞赛确实是基于准确性进行评估的,尽管我已经开始考虑这并不总是,事实上也不经常是分类算法有效性的最佳衡量标准。

也就是说,当我将使用训练数据计算的最佳准确性阈值插入到测试数据中时,它将预测的准确性提高了整整 1%,这在数据科学竞赛中可能会有所不同!

LogisticRegressionWithThreshold类的最终版本增加了一个新方法来计算优化精度所需的阈值

(0.5654501621491699, 0.7968026924694994)

这是最佳(最高)精确度的混淆矩阵…

作者图片

…这是精度与阈值的关系图…

作者图片

结论

我们已经看到,有许多优化逻辑回归的方法,这些方法可以顺便应用于其他分类算法。这些优化包括为精确度、召回率、f1 分数、准确度、TPR-FPR 或定制成本函数的优化寻找和设置阈值。

我们还看到,所选择的优化严重依赖于期望的业务成果。

我们已经看到,sklearn.linear_model中的LogisticRegression类无法设置阈值来优化算法,但是我们可以使用本文中开发的LogististicRegressionWithThreshold类来让我们即时访问所有必要的功能,以便根据期望的业务结果来调整基本算法。

完整的代码可以通过以下链接在 GitHub 上找到

https://github.com/grahamharrison68/Public-Github/blob/master/Logistic%20Regression%20Thresholds/Logistic%20Regression%20Thresholds.ipynb

感谢您的阅读!

如果你喜欢读这篇文章,为什么不看看我在 https://grahamharrison-86487.medium.com/[的其他文章呢?](https://grahamharrison-86487.medium.com/)

此外,我很乐意听到您对这篇文章、我的任何其他文章或任何与数据科学和数据分析相关的内容的看法。

如果你想联系我讨论这些话题,请在 LinkedIn 上找我—https://www.linkedin.com/in/grahamharrison1或者发邮件给我ghar rison @ Lincoln college . AC . uk。

用 OSM 数据计算建筑密度

原文:https://towardsdatascience.com/calculating-building-density-in-r-with-osm-data-e9d85c701e19?source=collection_archive---------23-----------------------

介绍

OpenStreetMaps 是一个很好的空间数据源。大多数通用编程语言都有从 OSM 下载数据的包。

在本教程中,我将展示如何使用 R 的 osmdata 包下载建筑数据,执行密度分析,并使用 ggplot 绘制,以及交互使用 tmap。

这需要一些空间数据结构的知识。

获取数据

第一步需要使用 osmdata 从 OSM api 下载数据。首先,我需要为 OSM 设置一个边界框来搜索数据。接下来,我将下载用于制作 choropleth 地图的行政边界。最后,我将为定义的边界框下载建筑数据。

设置搜索区域

我将在土耳其的伊兹密尔市搜索数据。为了定义我的搜索,我将使用getbb命令。该命令将位置名称作为字符串,并返回由 OSM 定义的边界框。也可以返回一个多边形的边界框,这很有用,因为我想搜索由行政边界定义的建筑物。

因为该函数返回一个矩阵,所以您可以使用自己的多边形来定义 OSM opq查找(如下),但是确保数据的 CRS 是 EPSG:3857 是很重要的。

获取边界多边形

检索边界线

在这个项目中,我正在寻找伊兹密尔的街区边界。因为各国的行政级别界限并不统一,所以可能需要进行一些研究来确定需要什么样的行政级别。幸运的是,他有一个有用的工具,可以让你在交互式地图中找到 OSM 的边界。

地区名称旁边的数字表示 OSM 的行政级别。在我的例子中,我在 8 级寻找界限。我可以使用osmdata请求特性传递这个信息,它是 OSM API 的包装器。

检索 OSM 边界线

(注意:OSM 有更多可用的地图功能,可以使用右键键:值对进行查询。)

该函数返回一个 osmdata 对象,这是一个sf数据帧的列表。每个数据帧由不同的几何类型组成,这意味着返回的对象可能很大。为了得到正确的数据,你需要知道你在寻找哪种几何图形。

在这种情况下,我需要的形状是多多边形几何类型。OSM 查询最终会返回大型对象。为了保留一些空闲空间,我将删除多余的数据帧。我还会清理一些数据。

清理边界数据

现在我想检查一下我是否有正确的界限。

原始边界多边形的 OSM 边界线

看起来不错,但是它也返回了所有外围区域的边界,因为它们可能落在边界多边形线上。这是我以后可以处理的事情。

检索建筑

使用与上面相同的过程,查询 OSM 原始边界多边形:iz_bbox内的所有建筑物。建筑物多边形对象将比我的边界对象大 100 倍,所以我将再次去掉多余的数据。这一次我将保持多边形 sf 对象。

然后我会画出结果。

在边界多边形上打印建筑多边形

返回的建筑物并不真正遵循任何多边形的边界,所以现在我将做一些空间修剪。

剪裁点数据

为了过滤掉所有的外围建筑,我需要将它们作为点来计算,这可以通过找到它们的质心来完成。我将使用建筑质心创建一个新的数据框。在此之前,我想计算所有建筑物的面积,这样数据就可以与新创建的数据框一起使用。从现在开始,我不再需要建筑多边形了。

我还需要创建一个多边形几何图形,以过滤外围建筑。我可以用原来的边界框iz_bbox来做这件事。但是,因为这个对象是一个矩阵,我需要把它转换成一个 sf 对象。这可以通过使用sf_headers::sf_polygon来完成。

红色的多边形是目标区域,我可以使用这个多边形来裁剪建筑数据

现在我有了一个可以过滤点的多边形。首先,我必须创建一个允许我过滤的数据框架。将st_join连接变量设置为st_within将给出一个列,指示一个点是否在多边形数据框内。列id被创建,1 表示一个点落在多边形内。我将策划检查结果。

将质心构建为边界多边形内的点

它工作了,所以现在我将过滤正确的点,然后从iz_polys数据帧创建一个新的数据帧,但是使用过滤的点。

使用更精细的数据框架,我可以对每个地区内所有建筑的总面积进行汇总和求和。我将创建一个最终的数据框,其中包含总建筑面积以及地区多边形的总面积。

现在我将使用tmap创建一个漂亮的交互式地图。

互动图截图。看这里的实物:https://greggsaldutti . netlify . app/post/2021-05-05-calculating-building-density-in-r-with-osm-data/

结论

这里我们有一张建筑的面积密度图,以占总土地面积的百分比来表示。当你有很多数据要处理,或者需要以编程方式访问数据时,r 是一个很好的工具。其他程序,如 QGIS,可能对用户更友好,但是 R 给你更多的控制,也能制作漂亮的地图。

注意:这篇文章基于 Matt Herman 关于纽约树木的文章,以及这个使用 Python 的伟大开源 GIS 课程。

原载于 2021 年 5 月 5 日https://greggsaldutti . net lify . app

在 BigQuery 中计算内部收益率(IRR)

原文:https://towardsdatascience.com/calculating-internal-rate-of-return-irr-in-bigquery-75e6703e8ec3?source=collection_archive---------12-----------------------

在 BigQuery 中实现 Excel 的 IRR 函数的分步指南

内部收益率(IRR)是财务中经常出现的一种常见计算方法。在这篇博文中,我将展示如何在 BigQuery 中构建一个查询,该查询执行相当于 Excel 的 [IRR](https://support.microsoft.com/en-us/office/irr-function-64925eaa-9988-495b-b290-3ad0c163c1bc) 函数的计算。如果现金流存储在 BigQuery 表中,并且您希望在不将数据移动到 Excel 的情况下计算 IRR,或者如果您希望将 BigQuery 用作数据可视化和 BI 的来源,这将很有帮助。

照片由斯科特·格雷厄姆在 Unsplash 上拍摄

1.背景:内部收益率(IRR)和净现值(NPV)

内部收益率(IRR)是投资产生的所有现金流的净现值等于零的收益率。它主要作为一个决策规则:一项投资的一系列现金流的内部收益率越高,超过资本成本的金额越大,该项投资就越有利可图。

从数学上讲,IRR 是求解以下方程的r的值:

这与以下内容相同:

这里,t是时间段(从 0 到N),CF是时间段t的现金流,r是收益率(IRR)。

上述方程没有解析解。换句话说,没有数学公式可以给我们内部收益率。解决这个问题的唯一方法是用数值方法,尝试r的多个值,看看哪一个最接*满足这个方程。

对于r的任何给定值,上述等式的左侧给出了净现值:

2。示例使用 Excel 的 IRR 函数计算 IRR

在本指南的其余部分,我们将使用下面的简单示例。让我们假设我们在文件irr.csv中存储了以下现金流

PERIOD, CASHFLOW
0, -10000
1, 2000
2, 6000
3, 6000

我们可以用 Excel 的IRR函数来计算内部收益率。 Excel 的文档对IRR函数描述如下:

返回由数值中的数字表示的一系列现金流的内部收益率。这些现金流不必像年金一样均匀。然而,现金流必须定期发生,例如每月或每年。

在 Excel 中计算 IRR 相当简单:

我们的目标是在 BigQuery 中实现这一点。

3.现在净价值

a. 首先,让我们在 BigQuery 中计算上述现金流的净现值。我们可以使用 BigQuery 控制台轻松地将irr.csv数据导入到 BigQuery 表中。在本指南中,生成的表被命名为tutorial.irr.cashflows

b. 一旦创建了表,我们就可以运行下面的查询,该查询返回一个包含每个现金流现值的附加列:

SELECT
  period,
  cashflow,
  cashflow/POWER(1+0.16, period) AS present_value
FROM
  `tutorial.irr.cashflows`
ORDER BY
  period

BigQuery 输出以下查询结果:

c. 净现值就是现金流的现值之和。因此,我们可以使用 SUM aggregate 函数来获得现金流的净现值:

SELECT
  SUM(cashflow/POWER(1+0.1614, period)) AS net_present_value
FROM
  `tutorial.irr.cashflows`

BigQuery 输出以下查询结果:

净现值接*于零,这验证了我们从 Excel 得到的结果,即 16.14%是 IRR 的*似值。

4.内部收益率

。现在我们知道了如何计算净现值,我们的目标是找到r的一系列值的净现值,并选择最接*零的一个。为了生成r的一系列值,我们将利用 BigQuery 的GENERATE_ARRAY函数。下面是来自 BigQuery 的官方文档对GENERATE_ARRAY函数的简要说明:

[GENERATE_ARRAY](https://cloud.google.com/bigquery/docs/reference/standard-sql/array_functions#generate_array)根据起始值、结束值和步长值生成一个值数组。例如,以下查询生成一个数组,其中包含从 11 到 33 的所有奇数,包括 11 和 33:

SELECT GENERATE_ARRAY(11, 33, 2) AS odds;

`+--------------------------------------------------+
| odds |

[11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33]

b 。为了说明我们将如何找到 IRR,让我们考虑一小组r [0.14, 0.15, 0.16, 0.17, 0.18, 0.19]的值作为 IRR 的猜测值。(我们稍后将考虑更大范围的值。现在,假设我们知道 IRR 在上述范围内。我们从前面的计算中知道,IRR 最接* 0.16。)以下查询为这些猜测值中的每一个生成净现值:

SELECT
  guess,
  SUM(cashflow/POWER(1+guess, period)) AS net_present_value
FROM
  `tutorial.irr.cashflows`
CROSS JOIN
  UNNEST(GENERATE_ARRAY(0.14,.19,0.01)) AS guess
GROUP BY
  guess

我们可以看到,当猜测值等于 0.16 时,结果表中的净现值最接*于零。

我们的下一个任务是编写一条 SQL,给出净现值最接*于零的r的值(即 IRR)。以下查询通过使用公用表表达式来实现这一点:

WITH
  npv_table AS (
  SELECT
    guess,
    SUM(cashflow/POWER(1+guess, period)) AS net_present_value
  FROM
    `tutorial.irr.cashflows`
  CROSS JOIN
    UNNEST(GENERATE_ARRAY(0.14,.19,.01)) AS guess
  GROUP BY
    guess)
SELECT
  guess AS IRR
FROM
  npv_table
WHERE
  ABS(net_present_value) = (
  SELECT
    MIN(ABS(net_present_value))
  FROM
    npv_table)

BigQuery 输出以下查询结果:

d. 现在我们知道了如何计算 IRR,我们可以考虑使用下面的查询来计算GENERATE_ARRAY函数中r的更大范围的值:

WITH
  npv_table AS (
  SELECT
    guess,
    SUM(cashflow/POWER(1+guess, period)) AS net_present_value
  FROM
    `tutorial.irr.cashflows`
  CROSS JOIN
    UNNEST(GENERATE_ARRAY(0,2,.0001)) AS guess
  GROUP BY
    guess)
SELECT
  ROUND(guess*100,2) AS IRR_percentage
FROM
  npv_table
WHERE
  ABS(net_present_value) = (
  SELECT
    MIN(ABS(net_present_value))
  FROM
    npv_table)

BigQuery 输出以下查询结果:

这与我们从 Excel 的 IRR 函数中得到的值完全相同。(在最终查询中,IRR 值已被格式化为小数点后两位的百分比。)

感谢阅读!请在评论中分享反馈。

使用 DAX 幂 BI 计算负数和正数的增长率百分比

原文:https://towardsdatascience.com/calculating-percentage-growth-rate-with-negative-and-positive-numbers-with-dax-power-bi-5b30de2cb575?source=collection_archive---------13-----------------------

简单但复杂的算术

计算百分比变化的常用方法(【A-B/| B |)在涉及负数的情况下不起作用,但我有一个更好的替代方法,可以让你的工作保持干净和敏捷。

照片由卢克·切瑟在 Unsplash 上拍摄

A-B/ABS(B) 计算增长率似乎是大多数分析师的标准,我们经常忽略这样一个事实,即我们所依赖的简单公式并不是在所有情况下都是正确的。

我最*完成了一份报告,正在向团队展示结果,一名成员要求我延长报告的时间线,其中包括一些负增长期,我随意延长了过滤器,令我惊讶的是,结果显然是错误的。

我回到我的 DAX 公式,看看我是否将 absolute ABS() 应用于分母,是的!我做了,但我的结果仍然是错误的,这使我开始思考负数会如何影响我们的百分比增长率计算的输出。

为了更清楚起见,我读了几篇文章,这篇来自 Linkedin 上Ismael的帖子解释了相对增长率脱颖而出,阐明了我们在计算增长率时经常忽略的灰色区域。

做了一些谷歌搜索,我看到一些分析师使用不同的方法来解决这个问题,懒惰的方法通常涉及返回空白()或零,其中任何值小于零。另一种方法是创建一个回报 P 或 N(正或负),以掩盖我们亲爱的公式“A-B/ABS(B)”的低效率。

在阅读了这么多关于如何解决这个问题的文章后,Excel 超级用户论坛来帮忙了。来自论坛的超级用户(塔赫尔·艾哈迈德)建议考虑不同的场景,并使用 If 函数来解决问题。

下面是我最后的 DAX 查询,它最终处理了所有可能影响百分比增长计算的场景,并为任何使用 DAX 的人解决了这个问题

Net Value - Growth Rate MoM% =
VAR _PREV_MONTH =
    CALCULATE ( [Net Value], DATEADD ( 'Calendar Table'[Date], -1, MONTH ) )VAR _CURR_MONTH =
    CALCULATE ( [Net Value] )VAR _RESULT =
    IF (
        AND ( AND ( _CURR_MONTH < 0, _PREV_MONTH < 0 ), _CURR_MONTH < _PREV_MONTH ),
        ( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ) * -1,
        IF (
            AND ( AND ( _CURR_MONTH < 0, _PREV_MONTH < 0 ), _CURR_MONTH > _PREV_MONTH ),
            ( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ),
            IF (
                AND ( _CURR_MONTH < 0, _PREV_MONTH < 0 ),
                ( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ) * -1,
                IF (
                    AND ( _CURR_MONTH > 0, _PREV_MONTH < 0 ),
                    ( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ) * -1,
                    IF (
                        _PREV_MONTH < _CURR_MONTH,
                        ( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ),
                        IF (
                            _PREV_MONTH > _CURR_MONTH,
                            ( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ),
                            ABS ( ( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ) )
                        )
                    )
                )
            )
        )
    )RETURN
    _RESULT

以下是对计算增长率百分比时预期的不同情景的简单解释,所有这些都用上述 DAX 公式进行了完美的处理(简单的说明归功于 Taheer

  1. A>0,B>0,A
  2. A>0,B>0,A>B
  3. 一个<0, B> 0,|一个
  4. A <0, B> 0,|A|>B
  5. A>0,B <0, A
  6. A> 0,B<0, A>| B | 0
  7. A <0, B<0, |A|
  8. A<0, B<0, |A|> |B|

下一次,当您使用 DAX 在 Power BI 报告中计算增长率百分比时,请仔细考虑您的公式,并考虑利用上面的片段。

在 Linkedin 上关注我以了解我的故事

这个片段在 GitHub 上——叉出来!

**https://github.com/raymonbell01/Calculate-Percentage-Growth-Rate-with-DAX/commit/d873ff809c10ba6ed8f2ea3cca4f42e17acc3254 **

计算数据科学项目的商业价值

原文:https://towardsdatascience.com/calculating-the-business-value-of-a-data-science-project-3b282de9be3c?source=collection_archive---------9-----------------------

性能度量不能告诉你你想知道的:一个项目实际上有多大价值

照片由 Unsplash 上的 israel palacio 拍摄

数据科学非常关注各种性能指标。数据科学家将花费几个月的时间来尝试改进项目的各种性能指标。问题是,不清楚所有这些努力是否真的有价值。如果你只看性能指标,就不可能知道你是否增加了你的模型所提供的价值。

绩效指标不知道你的预测有多大价值。举一个例子,F1 分数明确地对精确度和召回率赋予了同等的权重。在实践中,假阳性和假阴性通常有不同的业务成本。

您可以使用一百万种不同的指标来告诉您您的模型做得有多好。但是这些都没有告诉你利益相关者真正想知道的:这有什么商业价值?

金钱万能

什么是商业价值?归根结底,对于营利性企业来说,商业价值就是货币价值。

商业价值= $ $

这对数据科学家来说是个好消息:我们热爱数字。钱是量化的。

Photo by 金 运 on Unsplash

不幸的是,我们建造的东西和货币价值之间的联系并不总是简单明了的。

将数据科学项目与商业模型联系起来的最具体的方法之一是计算实现该模型对公司的底线意味着什么。这并不总是可能的,但它是一个有用的练习。通过查看我们可以计算显式值的情况,我们可以澄清联系不太清楚的领域。

计算模型商业价值的一个具体例子

让我们举一个简单的例子,我们正在为一个业务问题建立一个模型:在一个部件工厂检测制造缺陷。

照片由拉利特·库马尔在 Unsplash 上拍摄

我们知道,如果我们检测到一个有缺陷的部件,我们会扔掉它,导致生产成本的损失。更换有缺陷的部件的成本是 100 美元

如果我们未能检测到有缺陷的部件,我们会将部件运送给客户,然后必须更换他们的部件并支付新部件的运费。假设运输成本为 50 美元,加上替换小工具的 100 美元损失。

如果我们有一个预测缺陷部件的模型,我们就可以写出不同场景的成本:

真阳性:-100 美元用于关闭一个小工具

误报:-100 美元更换我们认为有缺陷的部件

真负值 : 0(我们认为“无缺陷”是比较成本的默认场景)

假阴性:-150 美元运送替换部件

此场景的成本矩阵

请注意,这相当于说假阳性的成本是 100 美元(假阳性和真阴性之间的差异)假阴性的成本是 50 美元(假阴性和真阳性之间的差异)。

现在,我们可以构建一个分类器,并为该分类器计算如果我们将该分类器用作筛选过程,缺陷的成本会是多少。评估模型的商业价值很简单——我们只需要在测试集上产生一个混淆矩阵。让我们举个例子:

然后,我们将每个结果的成本乘以该结果发生的次数比例:

(-1000.2) + (-1000.05) + (-150 * 0.05) + (0 * 0.8) = -32.50.

换句话说,*均来说,如果我们使用这种模式,由于缺陷,每个小部件我们将*均损失 32.50 美元。

我们可以将此与当前政策的成本进行比较。让我们假设目前没有缺陷筛选,所有的小部件都已发货。根据上面的混淆矩阵,25%的部件是有缺陷的。因此,要计算这项政策的成本,我们只需将 0.25 乘以运输缺陷产品的成本:

-150 * 0.25 = -37.50

这项政策的*均成本为每件 37.50 美元。因此,实施我们的模型来筛选小工具将为公司节省*均每个小工具 5 美元

就是这样!我们已经计算了模型的商业价值。当然,在现实世界中,实施一项新政策可能会有成本,这些成本必须与实施该模型的计算收益进行比较。

不对称成本改变了最优决策阈值

有了明确定义的成本矩阵,我们就有机会微调我们的模型,以进一步降低成本。

默认情况下,大多数分类器使用 0.5 的概率决策阈值来确定标记积极或消极的内容,但对于不对称成本,这不一定是使用的最佳阈值。

例如,在这种情况下,假阴性的成本低于假阳性(假阳性为 100 美元,假阴性为 50 美元)。这将最优决策阈值推得更高;假阴性比假阳性成本低,所以我们应该更愿意接受假阴性。

下面是成本矩阵的成本曲线的简单模拟(请注意,成本曲线的最小值约为 0.7,因此这将是我们的最佳决策阈值):

不同概率阈值的成本曲线示例。成本已标准化,因此 1 是成本最高的方案。

因此,我们应该把任何预测概率在~0.7 以上的东西贴上有缺陷的标签,其他的都贴上没有缺陷的标签。

改变成本矩阵

认识到成本矩阵的改变不仅会改变模型的商业价值,还会改变最佳决策阈值,这一点很重要。

例如,假设公司里有人开发了一种新的有缺陷部件的测试。它很贵,所以我们不想在每个部件上都使用它,但是它明确地告诉我们一个部件是否有缺陷。如果这个测试花费 20 美元,我们的模型的成本矩阵会有很大的变化:

真阳性:-120 美元(100 美元的生产成本,另外 20 美元用于最终测试,以确保它是有缺陷的)

假阳性:-20 美元的最终测试费用,这将免除好的部件

真负值 : 0(我们再次考虑将“无缺陷”作为比较成本的默认场景)

假阴性:-150 美元运送替换部件

成本矩阵,如果我们有一个有缺陷的部件的决定性测试

因为假阳性的成本现在更低了,这就改变了收益曲线。我们现在应该更愿意出现假阳性,因为假阳性的成本没有假阳性高,而假阴性的成本仍然一样高:

随着成本矩阵的变化,成本曲线移动。成本已标准化,因此 1 是成本最高的方案。

使成本最小化的最优决策阈值已经转移到 0.3 左右。我们会将更多的部件标记为潜在缺陷,但这没关系,因为现在我们会将它们提交给进一步的测试,而不是扔掉它们。我们可以计算这个策略的总体成本,并将其与其他策略进行比较(例如,对每个小部件进行 20 美元的测试)。

在更模糊的情况下进行归纳

在现实世界中,我们很少遇到如此明确定义的问题。以这种方式定义一个业务问题就是我所说的数据科学的困难部分。

在现实世界中,成本并不为人所知,而且很少有直接的分类问题能够完全抓住业务问题的本质。然而,通过观察这些简化的案例,我们可以更清晰地处理更复杂的问题。认识到项目定义中的模糊或缺失是澄清问题并将其与带来最大商业价值的技术解决方案联系起来的第一步。

使用地理编码计算两个位置之间的距离

原文:https://towardsdatascience.com/calculating-the-distance-between-two-locations-using-geocodes-1136d810e517?source=collection_archive---------18-----------------------

PYTHON。地理空间分析。位置数据。

如何使用 Python 计算两组地理编码之间的距离

塔玛斯·图兹-卡泰在 Unsplash 上的照片

介绍

你可能听说过著名的短语“位置,位置,位置”,例如人们想要强调位置对商业和房地产的中心地位。

然而,在数据分析和计算中,这个短语有点含糊不清。计算机理解“位置”概念的方式是通过我们所知的“地理编码”这些是经度和纬度,并且是特定于特定位置的。

注:对于那些想知道如何计算这些地理编码的人,我写了一篇关于这个的文章。

根据不同位置的地理编码,我们可以生成其他“特征”这个过程是地理空间特征工程的一个例子。

一个特别的特征是起点和目的地位置之间的距离。距离在许多机器学习问题中发挥着重要的作用,例如,客户和员工流失预测,客流量,以及在某些情况下,财富预测。

例如,某些研究表明,离兴趣点较远的员工和客户,比如一个分支机构或公司,流失的可能性更高。但是,仅使用地理编码,不可能生成此特征并因此在机器学习模型中使用它们。

但是,如何计算一组经度和纬度之间的位置呢?

一种方法是使用大圆距离公式。

大圆距离/哈弗线距离

粘土堤在 Unsplash 上拍照

大圆距离,有时称为正圆,或球面距离,是球面上两点之间的最短距离**。**

虽然不是一个完美的球体,地球表面上两点之间的距离因此可以*似为大圆距离。

假设我们有地理编码,公式如下:

作者配制的配方

作者配制的配方

请注意,在公式中,地理编码假定为弧度,而不是度。我们通常从网上或通过谷歌 API 等提供商获得的地理编码是分等级提供的。

PYTHON 代码

事不宜迟,下面是计算哈弗线距离的代码:

import numpy as npdef haversine_distance(lat1, lon1, lat2, lon2):
    '''
    Calculates the spherical distance between two sets of geocodes coming from an origin and a destination.

    Parameters:
    --------------
    lat1: float
         - latitude of the origin location in degrees
    lon1: float
         - longitude of the origin location in degrees    
    lat2: float
         - latitude of the destination location in degrees
    lon2: float
         - longitude of the destination location in degrees 

    Returns:
    --------------
    Float distance in km.

    '''
    r = 6371 # radius of the Earth in Km

    # Convert degrees to radians  
    phi1 = np.radians(lat1)
    phi2 = np.radians(lat2)

    delta_phi = np.radians(lat2 - lat1)
    delta_lambda = np.radians(lon2 - lon1)

    a = np.sin(delta_phi / 2)**2 + np.cos(phi1) * np.cos(phi2) *   np.sin(delta_lambda / 2)**2

    c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))

    d = r * c

    return f'{d:.2f} KM'

让我们试试我们的功能:

作者图片

尝试从谷歌地图上查看实际距离,并验证这确实是一个很好的*似值。

结束语

大圆距离,或称哈弗线距离,是两个短距离位置之间的*似距离。

对于更长的距离,由于更多的道路障碍、堵塞和道路延长了整个路径,这种*似法就失效了。

为此,可以尝试使用 Google API 来计算两点之间的总距离。

参见我关于地理编码和访问 Google Maps API 的文章:

使用谷歌地图 API 生成地理编码

让我知道你的想法!

校准基于代理的细胞复制模型

原文:https://towardsdatascience.com/calibrating-an-agent-based-model-of-cell-replication-2016d796d2d?source=collection_archive---------33-----------------------

解释现实世界细胞样本中的部分同步性

基于主体的模型提供了探索和解释世界的另一种方式。他们可以通过告知其行为的逻辑提供预测解释力,特别是如果他们根据现实世界的数据进行校准。

在这篇论文中,研究人员构建了一个数学模型来预测细胞样本复制中发生的部分同步性。我很好奇,想看看我能否采取一种基于智能体的方法来解决这个问题,这是否也能让我解释这一现象。我将使用 HASH,一个基于代理的在线模拟*台来构建我的模型,并根据原始论文中使用的真实数据对其进行校准。

细胞复制

细胞在许多不同的阶段之间有规律地转换: G1eSS/G2/M 。它们只在这个周期结束时进行有丝分裂(复制),分裂成两个不同的细胞。由于这种加倍,细胞样品的生长呈指数增长,但仍然是离散的。因此,如果细胞样本是完全同步的(所有细胞处于周期的同一阶段,同时复制),绘制细胞数量随时间的变化曲线将不会产生*滑的曲线,而是离散的跳跃。

为了确保样品中的细胞生长是*滑的曲线,为生物实验室和分析准备了异步样品,细胞随机分布在不同的阶段。然而,实验数据显示,大多数样本的行为是部分同步的,而不是异步的。这是很重要的,因为研究和结果是基于*稳指数增长的假设。

让我们尝试创建一个模型来解释这种部分同步的行为。

模型

这个模型中的代理只需要一种行为:复制。这种行为将跟踪每个代理的细胞周期,并在达到适当的阶段时生成一个新的细胞。定义这种行为暴露了一条非常重要的信息。当细胞分裂时,产生的两个细胞都处于细胞周期的开始。他们已经同步。尽管我们的代理最初是在细胞周期的随机阶段产生的,但我们的细胞复制得越多,同步性就可能出现得越多。如果我们的模型与观察到的数据匹配得足够好,这可能是理解制备样本中部分同步性的关键。

我将通过在细胞周期的每个阶段初始化正确数量的代理来确保我的初始状态与数据一致。每种试剂都根据其当前的细胞周期阶段用不同的颜色标记,与原始论文中使用的颜色相匹配。有三个不同的图来解释我们系统的状态:总细胞的时间序列、按颜色计数的细胞的时间序列和 Q 的时间序列(基于每个周期中细胞数量计算的比率)。

你可以在这里找到型号。让我们看看我的第一个版本是什么样子的,与实际数据相比,我估计了每个周期的时间(模型是蓝色的,对比实验数据是橙色的):

总细胞生长(图片由作者提供)

各期细胞比例: Q(t) = R(t) / (Y(t) + G(t)) (图片作者提供)

总的形状看起来是正确的,细胞总数呈指数增长,Q 值也是振荡的,尽管离数据还很远。增长和振荡周期都太快了。让我们看看是否可以使用优化引擎使模型更接*数据。我们将尝试发现细胞周期中每个阶段长度的最佳值,并确定我们先前的关键观察是否是部分同步性的有效解释。

校准

通过检查数据,看起来我们的细胞周期应该是大约 70 步长。我将为细胞周期的长度选择一个数值范围*、G1* 、 eSS/G2/M ,它们的总和大约在那里。我将提供它们作为优化引擎的潜在值

在 HASH 中定义优化实验(图片由作者提供)

我将创建一个定制代理来计算每个时间步的模型输出和实验数据之间的误差。该代理将使用简单的*方和来捕获错误,优化引擎将尝试减少该值。首先,让我们试着拟合第二张图中的曲线,该图根据细胞周期中的阶段对药剂进行计数。

总细胞生长—第一次校准尝试(图片由作者提供)

细胞分阶段生长—第一次校准尝试(图片由作者提供)

q 比率—第一次校准尝试(图片由作者提供)

在前两个图中拟合看起来很好,但是 Q 的第三个图看起来不太拟合。让我们将误差度量改为对应于 Q 中的误差。这意味着*方和计算将使用从模拟和数据集计算的 Q 比率。这是优化的结果:

总细胞生长—第二次校准尝试(图片由作者提供)

细胞分阶段生长—第二次校准尝试(图片由作者提供)

q 比率—第二次校准尝试(图片由作者提供)

q 现在有了一个更好的拟合,以其他两个图为代价。我将尝试合并这两个误差(按颜色的代理计数和 Q 比率),以便找到模型的最佳拟合。因为我从这些优化中获得了一些关于好的参数值的信息,所以我可以缩小实验定义的范围以提高其有效性。对于每个阶段的长度,我们将缩小到 5–10 之间的范围,而不是大约 20 个值的范围。

总细胞生长—第三次校准尝试(图片由作者提供)

细胞分阶段生长—第三次校准尝试(图片由作者提供)

q 比率—第三次校准尝试(图片由作者提供)

现在看来,我们已经找到了一组值,为第二个和第三个图提供了最佳的拟合*衡。每个阶段长度的最终值为:

  • G1: 25 个时间步骤
  • 埃斯:27 个时间步
  • S/G2/M: 18 个时间步长

每个时间步长相当于 1/4 小时。

用基于主体的模型复制实验数据的能力提供了对导致系统以特定方式运行的机制的洞察。与黑盒方法不同,使用基于代理的模型使我们不仅可以预测细胞生长,还可以解释为什么它会部分同步发生。在这种情况下,我们可以假设,观察到的行为是因为细胞复制得越多,它们就越有可能与共享“母”细胞的其他细胞排成一行。

像这样的洞察力可以让研究人员、实验室技术人员和审查委员会对细胞样本的行为方式做出更好的假设,让他们在预期和实验结果之间做出更明智的比较。这只是一个例子;使用根据真实世界数据校准的基于主体的模型也可以改善我们在经济、政府和许多其他领域的假设。

呼唤属性图模式标准

原文:https://towardsdatascience.com/call-for-a-property-graph-schema-standard-eff921287c83?source=collection_archive---------18-----------------------

重视人际关系。

属性图模式。图片作者。

我使用数据库作为图数据库已经有一段时间了,并且认真地研究了有向图的概念。我的观点是,有向图是看图的一种相当原始的方式。

上图是一个简单订单管理数据库的属性图模式。人们下订单,每个订单都包含一定数量的商品。订单、人员和物品是由边/关系连接的图论的图中的节点/顶点。有向图是指每个边/关系都有一个方向的图,如下所示:

有向图。图片作者。

微妙的区别在于,现在每条水*线(关系)都有一个指向一个方向的箭头。

我不觉得有向图特别有用。从本质上来说,关系是双向的。例如,对于每个由 人员下达的 订单,该人员 下达 订单。更不用说,在我们的数据库模式中,每个订单最多由一个人下。如果我们用箭头表示只能存在一个关系(作为该关系的实例),那么我们会将第二个图理解为每个订单只包含一个*商品。显然,这不会是一个非常有用的数据库。***

对标准的呼唤

本文是对数据库行业标准的呼吁。如果我们要有属性图模式,让它们背后至少有一点逻辑和意义。

多对多关系。图片作者。

我的建议是,带有两个大箭头的边代表多对多关系。也就是说,在我们的模式中,一个项目可以有多个订单,一个订单可以包含多个项目。

我还建议:

  1. 如果关系包含一个大箭头和一个小箭头,则表明数据库中存在关系的反向读数;
  2. 带有大箭头和可选小箭头的关系表示该关系是多对一的。

多对一关系提案。图片作者。

例如,在我们的数据库中,许多订单可能由一个人下,而它的倒数…任何一个人都可以下许多订单。

为什么专门的图形供应商会锁定有向图?

在我对专用(本地)图形数据库所做的研究中,出现了简单的有向图概念,因为它反映了数据是如何存储在数据库的磁盘层的。也就是说,当数据库中的数据最终存储到永久介质中时,它的存储方式是焦点位于有向图的非箭头侧……相关的节点信息从该节点延伸到一个有效且复杂的一维数组中。

当数据被放入随机存取存储器时,一个更传统的被开发出来,使得该图在概念上形成被称为无索引邻接的链接;更像是一个三维图形,因为随机存取存储器中的晶体管矩阵可以被认为是三维的。

数据科学是非常技术性的,但基本上,它归结为…如果你做你的研究,你会很容易地发现从业者抱怨图形数据库性能差,当图形数据库以这种方式而不是那种方式查询时,只有图形数据库供应商和专家告诉你,图形数据库的查询性能在很大程度上取决于你如何构造有向图。我甚至读到过这样的评论,有人抱怨说,为了达到他们所追求的查询性能,他们需要在混合中引入索引(放弃了无索引邻接所带来的好处的整个概念),数据库供应商的专家说了类似这样的话:“好吧,如果这真的是您想要做的查询类型,那么图形数据库可能不适合您”。即关系数据库将会是

也就是说,这些都没有回答描绘关系的基数或它们的相互关系的问题。在我看来,将数据在磁盘级别存储的方式以及单个数据库如何工作融入到图形的概念中,并不是标准化属性图模式的任何方式。

为什么?

在我看来,答案很简单。世界正朝着多模型(关系和图形)数据库的方向发展,不管怎样,图形数据库供应商正在悄悄地向关系领域发展。

正在发生的情况是,专用图形数据库的营销材料几乎总是基于它们的索引而轻视关系数据库,只是转而告诉它们的数据库的用户“为了获得这种类型的查询所需的查询性能,你将需要一个索引”。

也就是说,图只是查看模式概念化的一种方式,如果我们无论如何都要在混合中加入索引的话,它也可以被看作是一个实体关系图。

也就是 所有的 要说…属性图模式最好像周围最好的实体关系图一样信息丰富,如果它们要让数据库专业人员相信的话,这些专业人员知道他们在谈论什么,并且希望概念模型在他们的意义上是清晰和信息丰富的。

我的业务是编写软件,将数据库概念化,就好像它已经是一个多模型数据库(关系或图形)。我之所以呼吁属性图模式的标准,是因为我发现简单的有向图太简单了。我觉得是时候让人们拥有概念模型了,它们尽可能地具有表现力,并且是数据库不可知的。当我创建一个属性图模式时,我更关心的是模型在概念上是否合理,而不是任何数据库的底层架构。在许多情况下,我可能甚至没有选择我想要使用的数据库。我当然不希望使用一个不能满足我的概念模型的数据库;我想使用那些 对概念模型表现良好的数据库。

让我们停止在图形数据库空间中遵从单个数据库供应商,并创建单个数据库供应商可以向往的标准。让我们抛弃旧的有向图的概念,转而使用同样表示基数的双向图。

感谢阅读。如果时间允许,我将写更多关于图数据库、关系数据库、多模型数据库和属性图模式的文章。

— — — — —结束— — — —

回调、布局和引导:如何在 Plotly Dash 中创建仪表板

原文:https://towardsdatascience.com/callbacks-layouts-bootstrap-how-to-create-dashboards-in-plotly-dash-1d233ff63e30?source=collection_archive---------2-----------------------

由卢克·切瑟在 Unsplash 上拍摄的照片

数据科学家和分析师最重要的角色之一是以可理解的方式向利益相关者呈现数据和见解。创建仪表板是显示您在数据探索和机器学习建模中发现的东西的一种很好的方式。Plotly 提供了一个健壮的开源版本的库,用于构建仪表盘 Dash。此外,还有多个额外的开源库,使得在 Dash 中构建仪表板变得容易。本教程概述了使用 Dash 实现您的第一个多页面仪表板应用程序的一种方法。

Dash 是什么?

Dash 是一个框架,允许您创建高度可定制和交互式的数据可视化应用程序,这些应用程序仅使用 Python 在您的 web 浏览器中呈现。Dash 在 R 和 Julia 中也可用,但本教程将重点介绍 Python。Dash 中的仪表板构建在 Plotly、Flask 和 React 之上,能够部署到互联网上,并在移动设备上跨*台显示。本质上,Dash 能够创建 web 应用程序,而不直接使用 HTML 或 CSS。这里我们将重点介绍免费的开源版本,但是 Plotly 为 Dash 提供了一个企业版,用于管理企业仪表盘。

Dash 的关键要素

在我们深入细节之前,让我们回顾一下我们将在构建第一个多页 dash 应用程序时使用的一些关键想法:

  • 布局&组件: 布局描述了您的仪表板的外观。这包括样式选择,如 CSS 脚本生成的字体和颜色,以及哪些组件将填充应用程序。dash_core_componentsdash_html_components库提供了 dash 应用程序的各种常用组件。HTML 组件是 HTML 标记的 python 版本,可以在 dash 应用程序中使用,允许您创建 div、显示文本、构建段落/标题等。你也可以像在 HTML 中一样给它们分配一个样式、一个类或者一个 id。核心组件是可以放在仪表板上的各种有用的元素,就像下拉菜单、图表、滑块、按钮等等。你可以在 Dash 的文档中找到许多额外的 Dash 组件库。
  • 回调: 回调是 python 装饰器,控制你的 dash 应用的交互性。装饰器是一个包装另一个函数的函数,在它们装饰的函数之前和/或之后执行代码。在 Dash 中,回调装饰器使用该属性来查找用户对您的 dashboard 应用程序组件所做的更改,并执行您定义的任何相关更改。例如,您可以设置一个回调,从仪表板上的滑块组件获取信息,然后根据滑块的输入对图形进行更改。
  • Bootstrap: 如果你已经熟悉 CSS,你可以通过编写自己的 CSS 脚本来设计你的 Dash 应用程序。但是,如果你不熟悉 CSS 或者不想花时间自己写,Bootstrap 是个不错的选择。Bootstrap 是一个流行的 CSS 框架,用于创建交互式的移动应用。faculty.ai 的dash_bootstrap_components库提供了 CSS 样式以及附加组件,如应用导航工具、可折叠内容、对话框等等。Bootstrap 使您能够创建包含组件的列和行,从而简化了内容的组织。这里有一个关于它如何操作的概要,查看文档了解如何将其翻译成 python。

开始使用您的仪表板

首先,您需要安装 Dash 和 Dash 引导组件(核心和 HTML 组件应该预装在 Dash 中)

$ pip install dash==1.19.0
$ pip install dash-bootstrap-components

安装 dash 后,您需要创建一个目录来保存构建应用程序的所有 python 脚本。注意,有多种方法来构造这个目录和其中的 python 文件,下面只是构造它的一种方法。我喜欢用这种方式组织它,因为我发现它有助于我保持代码的条理性。在这个结构中,您将有四个文件:

PyFile #1:应用程序

app.py:这个脚本简短明了。它会创建您的 dash 应用程序,并将其连接到服务器。如果您选择使用 Bootstrap CSS 样式(或另一个预制的 CSS 样式表),您也可以在这里这样做。

PyFile #2:索引

这将是你进入仪表板的主要入口。这意味着当你想运行 dashboard 应用程序时,你可以在命令行中输入python index.py。在这里,您还将定义在应用程序的哪些页面上显示哪些布局。app.layout将是你的总体结构。在这个例子中,我有一个 location 组件,它将结构与 URL 联系起来,实例化一个水*导航栏,并将页面内容放在一个 HTML div 中。这种结构将在应用程序的所有页面上显示相同。下面的回调是一个特殊的回调,当你点击导航栏中的链接到一个新页面时,它将页面布局发送到结构中的page-content HTML div。确保从layouts.py中导入您想要显示的布局、组件和样式。

PyFile #3:布局

layouts.py:这是你设计仪表盘应用的地方。你需要将每个布局、组件或样式设置为一个变量或存储在一个函数中,这样你就可以在index.py和这个布局脚本的其他地方访问它。请记住,layouts.py只是定义每个页面的布局和各种附加组件,如导航栏。我们将在后面讨论如何在 **callbacks.py** 中实现交互性。

在这个例子中,我已经导入了经典的 iris 数据集来生成两个 Plotly Express 图形进行显示。我还创建了一个导航栏、两种样式和两种布局。每个布局由一个 1 行 2 列的引导网格组成。在第一个布局中,左边的列有两个选项卡,将显示不同的图形。右边的列显示与用户在图上的点击相关联的文本。对于第二个布局,它展示了两个非常有利于交互性的 dash 核心组件:下拉菜单和单选按钮。除了显示选择的值之外,它们现在不做太多事情,但这是您可以发挥创造力并弄清楚如何使用选择的值与其他组件和图形进行交互的地方。

layouts.py很可能是你最长的 py 剧本。

PyFile #4:回调

您想要创建的任何互动都应该放在这里。您会注意到上面的layouts.py脚本中的许多元素都传递了一个id=参数。这些 id 是callbacks.py中的回调如何识别哪些组件监听用户输入,以及在哪里显示回调的输出。回调的结构如下:

@app.callback(
    Output("component-id-to-output-to", "children"),
    Input("component-id-to-listen-to", "valuesIn")
)
def callback_name(valuesIn):
    #code for callback to execute
    return output_to_children

每个回调都监听一个组件并从中获取值。这是Input()的作品。然后使用这些值执行回调函数。一旦函数返回一个值或对象,它就被发送到Output()"children"是每次回调的通用输出。子元素是组件的子元素。我们实际上已经用了很多孩子。在上面的脚本中,每次我们将组件嵌套在另一个组件中时,我们都添加了一个子组件。所以本质上,当children在回调的输出中时,它告诉 Dash 将返回的内容放在 id 与输出中列出的 id 相匹配的组件中。例如,callbacks.py中的第一个回调从 id 为tabs的组件获取值active_tabs,并将回调的输出返回给 id 为tab-content的组件。返回的内容现在是tab-content组件的子组件。

我在下面的脚本中设置了四个回调:

  1. 监听当前点击了哪个选项卡,并返回相关的图表
  2. 监听图表上的点击并返回与该点击相关联的文本
  3. 监听下拉菜单并以字符串形式返回选定的值
  4. 监听单选按钮并以字符串形式返回选定的值

大多数回调并不有趣,但是在开始构建更复杂的回调之前,理解简单的回调是有帮助的。

一旦你设置好了所有的四个文件,编辑它们到你的数据,来自 Plotly 的可视化,等等。此外,尝试改变结构/布局,并创建自己的回调。学习 Dash 的最好方法是尝试不同的布局和风格。当你想看看你的应用程序头输入python index.py到你的命令行。它应该是这样的:

$  python index.pyDash is running on http://127.0.01:5000/* Serving Flask app "app" (lazy loading)* Environment: productionWARNING: This is a development server. Do not use it in a production deployment.Use a production WSGI server instead.* Debug mode: on

在任何网络浏览器中输入运行 Dash 的 URL,看看你创建了什么!如果调试模式是打开的,你应该能够更新你的脚本,你的应用程序将改变生活。您可以通过设置debug=False来关闭index.py中的调试模式。

Dash 是一个庞大、灵活、强大的库,需要学习的东西太多了,一开始可能会有点不知所措。但是这是一个很好的工具,一旦你投入进去,它就值得了。

在这里找到这个项目的 GitHub 库。

用 ctypes 模块从 Python 调用 C++代码

原文:https://towardsdatascience.com/calling-c-code-from-python-with-ctypes-module-58404b9b3929?source=collection_archive---------3-----------------------

决策树实现示例

Python 在过去几年变得非常流行,因为它有一个很大的社区和很多可用的包,这些包非常容易使用,可以帮助你相对快速地完成工作。但是很多包不是用纯 Python 写的,因为作为一种解释语言,这意味着你不需要编译你的程序来执行指令,它非常慢。例如,一个名为 xgboost 的流行数据科学包主要是用 C++编写的,这是一种编译语言,因此执行起来很快。出于这个原因,如果我们能用这样一种语言编写计算量最大的操作,但从一种较慢但非常用户友好的编程语言(如 Python)调用它,那就太好了。好消息是我们可以做到,在本教程中,我们将看到如何使用 ctypes 模块。

先决条件:您需要安装 Python 3(ctypes 是一个内置库)和 Visual Studio buildtools 来编译 C++代码。

为了能够从 Python 中调用 C代码,我们需要精确地定义我们将在语言之间传递的输入和输出数据类型,因为 C需要在编译时知道所有的数据类型。在 Python 中,一切都是对象,包括像 intfloat 等数据类型。虽然它们通常不对应于唯一的 C类型,例如,Python 中的 int 是唯一的,而在 C中,我们可以有 short、long、unsigned integers 等等,它们的不同之处在于它们可以存储多少位或符号。因此,当在语言之间转换时,我们需要指定确切的数据类型,以防止 Python 整数溢出/下溢 C整数(即,传递的 Python int 的大小大于或小于某个 C整数类型预期的大小)。所以,一旦我们定义了对应于 Python 对象的 C 类型,我们就差不多完成了,可以从 Python 中调用我们的 C++函数了!

履行

我们不打算在这里深入研究决策树算法——当前的 C++实现与 sklearn 模型非常相似,如果我们不使用样本权重,它应该会给我们相同的结果,正如我将在本教程末尾展示的那样。

因为 Python 和 C都是基于 C 编程语言构建的,所以我们可以使用它来使两者进行交互——我们需要的是将我们希望 C 可以调用的函数封装到 extern "C" 命令中,如果我们在 Windows *台上,则在它们之前添加 __declspec(dllexport) 。在下面的代码中,由于我们希望我们的 Python 代码能够与决策树类初始化器fitpredict_data 方法交互,我们定义了 3 个可从 Python 调用的函数(将它们包装在extern“C”)——*new _ tree、fit_tree & predict。new_tree,*在被调用时返回一个指向新初始化的决策树实例的指针,该实例具有已定义的 max_depthmin_size 参数, fit_tree 函数将初始化的决策树实例的指针、指向 2d 数组的双指针、行数、列数和布尔值作为参数,如果为真,将打印出拟合的树。传递行数和列数对于循环 C数组指针至关重要,否则我们无法推断出它的维数。最后预测函数采用与 fit_tree 相同的参数,除了最后一个布尔值,并返回给定特征数组的预测值。

既然我们已经使相关函数可以从 Python 中调用,第二步就是构建 C++模块。为此,我们需要在命令行中运行 python setup.py build ,它将编译在 setup.py (见所附链接)文件中的 ext_modules 参数下定义的扩展模块,然后我们可以调用这些模块。

现在我们要用 Python 定义一个决策树类

在加载了构建好的 C编译模块( decision_tree.pyd )并定义了决策树实例之后,我们调用了 fit 函数,在这个函数里面发生了 ctypes 的神奇之处!首先,我们需要确保我们有一个连续的数组,即数组存储在一个连续的内存块中,这样我们就可以在知道第一个元素的地址和元素数量的情况下遍历它。然后我们开始定义输入(argtypes)返回类型(restype)new_tree 方法的输入类型非常简单,因为它只是 2 c_int (max_depthmin _ size),而输出被设置为 c void 指针,这将允许我们获得指向 C决策树实例的指针,并在稍后将其传递给 fit_treepredict 方法。事实上,我们可以观察到最后两个方法的第一个参数将 a c_void_p 作为输入。Void 指针没有与之相关的数据类型,所以存储我们的决策树类对象很方便。对于 fit_tree 函数,我们需要定义一个指向 2d 数组的双指针——我们首先将连续的 numpy 数组转换成一个 c 类型数组 ( ct_ar ),然后将其转换成双指针。请注意,我们没有将 ct_arr 直接转换为双指针,这样做会在遍历数组时引发访问冲突错误。因此,我们首先将 2d 数组的每一行转换为一个指针,然后将其转换为一个双指针。基本上对预测功能也是如此。最后值得注意的是, fit_tree 方法不返回任何东西,而 predict 方法返回一个数组指针,我们需要为返回类型定义该指针来指示预期的输出长度,否则我们将无法返回正确的预测数。

结果

我们可以比较 C++决策树和 sklearn 的结果

Sklearn 决策树图和预测:

作者图片

C++决策树绘图和预测:

作者图片

你可以在 this GitHub 页面找到完整的代码,包括 C++决策树实现。

结论

在本教程中,我们已经看到了如何使用内置的 ctypes 模块从 python 中调用 C++代码。虽然这不是唯一的选择,实际上我们可以使用其他的库,比如 SWIG ,它实现起来非常快,但是在某些情况下可能会变得复杂。 CFFI 是另一种选择——不用手动定义 c 类型,你只需用 C 代码描述你的数据类型,然后 cffi 就会从中推断出它们。尽管如此,在切换到 cffi 之前,我相信理解使用 ctypes 库的逻辑是有用的。

带 Flask 和 OpenCV 的相机应用程序

原文:https://towardsdatascience.com/camera-app-with-flask-and-opencv-bd147f6c0eec?source=collection_archive---------2-----------------------

使用 flask 构建一个相机应用程序,应用 Snapchat 一样的过滤器,点击照片和录制视频…

在这篇博文中,我们将使用 flask framework 构建一个相机应用程序,在其中我们可以点击图片,录制视频,应用灰度、负片和“仅面部”滤镜等滤镜,就像 Snapchat 上出现的那样。我使用了一个非常基本的前端设计,因为这个项目背后的主要动机是让自己熟悉 flask web-framework,还包括实时视频流。同样的功能也可以扩展,以增加更多的功能。

巴斯蒂安·里卡迪在 Unsplash 上拍摄的照片

演示:

作者 GIF

我们利用了像线程、HTTP 请求-响应、全局变量、错误处理人脸检测这样的概念。让我们详细看看所有这些是如何发生的。

前端:

首先,前端是一个基本的 HTML 文件,带有接受输入的按钮和在后端预处理后显示输出帧的图像源标签。文件中的按钮将数据发送到服务器。该文件还显示了一些使用该应用程序的说明。该文件保存在项目目录的“templates”文件夹中。

作者截图

后端:

至于后端,它是一个完成所有魔术的 python 脚本。它保存在项目目录中。让我们分别看一下文件的各个部分,以便理解它的工作情况。

初始化:

在上面的代码中,我们导入了所有必要的模块。

Flask 是一个微型的 web 框架,它就像是前端和后端之间的桥梁。从 flask 中,我们导入' Response 和' request 模块来处理 HTTP 响应请求。 render_template 用于渲染之前显示的 HTML 文件。OpenCV 是用于执行所有计算机视觉任务的模块。线程模块用于产生新的线程。

然后,我们声明所有的全局变量,它们就像一个“拨动开关”来执行不同的任务,如捕捉图像、开始/停止记录和应用过滤器。将变量初始化为 0,将所有内容设置为 false。

在第 18 行,我们尝试创建一个名为“ shots 的文件夹,如果它不存在的话。这是保存所有捕获图像的地方。

第 24 行加载了一个预训练的人脸检测模型供将来使用,第 27 行创建了 Flask 应用程序的一个实例。第 30 行为内置摄像头创建了一个视频捕获对象。

功能:

记录功能用于开始记录,即将帧写入 avi 文件,同时将变量 rec 设置为真。它使用“ out ,这是后来初始化的视频编写器的对象。(注意:如果你觉得录制的视频快或慢,调整一下 time.sleep 的值)。

detect_face() '将相机帧作为输入,并返回一个裁剪出的帧,其中只包含在该帧中检测到的人脸。它使用之前加载的预训练人脸检测模型。(请访问 本网站 深入了解这是如何做到的)。

gen_frames 是一个重要的功能,在其中完成实际的帧捕捉(通过摄像机)和处理。它在一个无限的 while 循环中运行。第 4 行从相机对象中捕获帧。如果帧捕获成功,它将检查是否有任何过滤器开关为真。如果'*人脸'、'负片'*或'灰度'为真,则分别对读取帧应用人脸滤镜、负片滤镜和灰度滤镜。

如果' capture '变量被设置为 true,它被重置为 false(全局变量),当前帧以' png '格式保存。如果' rec '为真,帧被复制到' rec_frame '全局变量,该变量在被触发时被保存到视频文件中。

第 25 行将帧编码到内存缓冲区,然后转换成字节数组。第 27 行产生了需要作为 HTTP 响应发送的格式的帧数据。

HTTP 路由:

这是前端与服务器通信的地方。通信通过 URL 路由发生在*‘GET*’和 POST 方法中。

@app。route('/')'是 Flask 提供的一个 Python 装饰器,用于轻松地将 URL 分配给我们应用程序中的函数。Route '/'是根 URL,输入根 URL 时调用' index() '函数。 'index.html' 文件从函数渲染到网页中。

在 html 文件中,Route ' /video_feed '被设置为图像源。此函数返回由循环中的“ gen_frames() ”生成的帧的响应块。

路由'/请求'被分配给'任务()'功能,该功能处理所有开关和视频记录。该路由既有' POST '又有 'GET '方法,即接受信息,也发送信息。之前所有路线默认为' GET '。

如果来自客户端的 HTTP 方法是' POST ',那么' request.form.get '接受来自用户按下的按钮的数据,并反转全局变量的先前状态,这些变量就像' gen_frame 函数中的开关。例如,当用户按下'灰色'按钮时,灰色'全局变量被设置为真,从而在' gen_frames '函数中将帧转换为灰度。当再次按下灰色按钮时,“灰色”设置为假,将画面恢复正常。

在运行 flask 应用程序的同时将帧记录到视频中是非常棘手的。最简单的解决方案是启动一个新的线程

一个线程是一个独立的执行流。这意味着你的程序将同时发生两件事。一个线程共享数据段、代码段、文件等信息。与其对等线程,同时包含其自己的寄存器、堆栈、计数器等。

在我们的例子中,'record()【T21]'函数有自己的 while 循环,所以这个循环在新线程中运行。首先,当' rec '为真时,我们创建一个' VideoWriter 对象。在第 37 行,我们初始化一个新线程,目标是' record() '函数,第 38 行启动新线程,其中' record()' 函数正在运行。再次按下录制按钮时,【video writer】对象被释放,录制停止,将视频保存到根目录。

最后,如果来自客户端的 HTTP 方法是' GET ',则呈现' index.html '模板。

主要功能:

'app.run()' 用于启动默认地址**:**http://127 . 0 . 0 . 1:5000/**的烧瓶 app。**您可以通过将“主机”和“端口”参数添加到函数“运行”来设置不同的主机和端口号。将主机设置为广播地址 0.0.0.0 将使应用程序在整个局域网(wifi 等)中可见。因此,如果移动设备连接到同一个 Wi-Fi,您就可以从移动设备访问该应用程序。这是一个很好的“间谍凸轮”。

结论:

要运行这个应用程序,你应该在你的电脑上安装 python、flask 和 OpenCV。要启动应用程序,请在命令提示符中移动到项目目录。键入并输入:

python camera_flask_app.py

现在,将http://127 . 0 . 0 . 1:5000/复制粘贴到你最喜欢的互联网浏览器中即可。

你可以添加更多像人工智能滤镜这样的功能来构建一个 Snapchat 式的应用程序。您还可以增强用户界面,使其更具交互性和丰富多彩。你可以在 我的 GitHub 账号 中获取这个项目的源代码。

谢谢大家!!

摄像机标定

原文:https://towardsdatascience.com/camera-calibration-fda5beb373c3?source=collection_archive---------3-----------------------

相机几何和针丨孔丨模型

摄像机校准或摄像机切除估计给定照片的针丨孔丨摄像机模型的参数。通常,针丨孔丨摄像机参数用一个称为摄像机矩阵的 3 × 4 矩阵表示。我们用这些参数来估计一个物体的实际大小或者确定摄像机在世界上的位置

怎么

在我们讨论摄像机校准之前,首先你需要了解针丨孔丨摄像机是如何工作的。

为什么我需要了解针丨孔丨摄像头?

因为这是任何相机工作的本质。针丨孔丨相机模型解释了世界上的一个点与图像*面(图像传感器)上的投影之间的关系。

我们如何将世界上的点投影到相机传感器中?

针丨孔丨型号

如果我们使用大开的相机传感器,我们最终会得到模糊的图像,因为成像传感器在传感器的同一位置收集来自物体上多个点的光线。

解决这个问题的方法是在成像传感器前面放一个有微小孔洞的障碍物。

该屏障仅允许有限数量的光线穿过该孔,并降低了图像的模糊性。

https://en.wikipedia.org/wiki/Depth_of_field

【示例】不同光圈大小的真实图像

https://en . Wikipedia . org/wiki/Depth _ of _ field # Effect _ of _ lens _ aperture

针丨孔丨摄像机模型中最重要的两个参数

  1. 焦距:针丨孔丨与像面之间的距离

它影响投影图像的尺寸。使用镜头时会影响相机对焦

2.摄像机中心:针丨孔丨中心的坐标

https://en.wikipedia.org/wiki/Pinhole_camera_model

针丨孔丨摄像机模型非常简单。知道了焦距和相机的中心,我们就可以用数学方法计算出物体反射的光线到达图像*面的位置。

焦距和相机中心是相机内参数,K 。( K 是表示固有矩阵的行业规范。)

内在参数

(又名,相机矩阵。)

固有参数,K

(C x,Cy) :以像素为单位的相机中心。
( fxfy ):以像素为单位的焦距。

FX=F/px
fy=F/py

F :世界单位焦距(如毫米。)

像素倾斜

(P x ,P y ):以世界单位表示的像素大小。

s :倾斜系数,如果图像轴不垂直,则不为零。
s=FXtan(α)

坐标系转换(通过矩阵代数!)

我们为什么想要这个?

为了将世界帧中的点投影到摄像机图像*面!

做什么?

(如果说的是自动驾驶汽车)把自动驾驶汽车本土化!

光线(从物体反射)从世界通过相机光圈(针丨孔丨)传播到传感器表面。通过孔径投射到传感器表面上导致翻转的图像。为了避免翻转混淆,我们在摄像机中心前定义了一个虚像*面(黄色*面)。

图来自简化的摄像机模型投影

# World Coordinate System 
**Oworld = [Xw, Yw, Zw]**# Camera Coordinate System
**Ocamera = [Xc, Yc, Zc]**# Pixel Coordinate System
**Oimage = [u,v]**

我们定义了一个 3 乘 3 的旋转矩阵 ( R )和一个 3 乘 1 的*移向量 ( t ),以便对世界坐标系和另一个坐标系之间的任何转换进行建模。

现在我们可以将投影问题(世界坐标→图像坐标)框架为

  1. 世界坐标 →摄像机坐标
  2. 相机坐标→ 图像坐标
**Oworld [Xw,Yw,Zw]** → **Oimage [u,v]**

怎么会?通过使用线性代数!

**1\. World coordinates** →  Camera coordinates**Ocamera = [R|t] * Oworld**2\. Camera coordinates → **Image coordinate****Oimage = K * Ocamera** Remind me what **K** (camera intrinsic parameter) was?

内参数,K: f 为焦距,c 为相机中心,是相机特有的参数

步骤 1 和 2 都只是矩阵乘法。因此,它可以重写(组合)为:

**Oimage = P * Oworld = K[R|t] * Oworld****Let P = K[R|t]
P** as Projection

等等, K 是(3,3)矩阵。**【R | t】**为(3,4)。(|意味着你将矩阵 R 与向量 t 连接起来。) Oworld [Xw,Yw,Zw] 为(3,1)。

那就不能用 Oworld [Xw,Yw,Zw] (3,1) 乘以 K[R|t] (3,4)

😎我们可以通过在 Oworld vector [Xw,Yw,Zw,1]的末尾添加一个来解决这个问题,称为齐次坐标(或投影坐标)

如果想进一步把图像坐标转换成像素坐标:用 x 和 y 除以 z,得到图像*面上的齐次坐标。

**[x, y, z] -> [u, v, 1] = 1/z * [x, y, z]**

这就是了。这是核心。这个简单的投影原理将被用于每一个 3d 视觉感知算法,从物体检测到 3d 场景重建。

在现实生活中,会有更复杂的场景,比如非方形像素、摄像头访问倾斜、失真、非单位长宽比等。但是,他们只是改变了相机矩阵 K ,方程还是一样的。

需要注意一些事情:

a)旋转矩阵 ( R )和*移向量 ( t )被称为外部 参数,因为它们在摄像机的“外部”。

*移向量 t 可以解释为相机坐标中世界原点的位置,旋转矩阵 R 的列代表相机坐标中世界轴的方向。这可能有点难以理解,因为我们习惯于用世界坐标来思考。

b)通常,多个传感器(如摄像机、激光雷达、雷达等。)用于自动驾驶车辆中的感知。每个传感器都有自己的外部参数,用于定义从传感器框架到车辆框架的变换。

  1. 图像坐标(虚像*面)**【u,v】**从虚像*面的左上角开始。这就是为什么我们将像素位置调整到图像坐标框架。

眼见为实

看一下功能project_ego_to_image。它连续调用两个函数,首先是project_ego_to_cam,然后是project_cam_to_image,就像我们把世界坐标分解成两步转换成图像坐标一样:世界坐标 →相机坐标,然后相机坐标→ 图像坐标

cart2hom将笛卡尔坐标转换成齐次坐标。

上面的代码片段来自 argoverse-api 。

https://www.argoverse.org/

在下面的 jupyter 笔记本中,您可以看到手动计算(从世界到图像*面的点云投影)与 argoverse api 的结果相匹配。

code:https://github . com/aerinkim/towards data science/blob/master/Camera % 20 calibration % 20 Argo verse . ipynb

一个数据科学家能代替一个 NBA 球探吗?最佳转会建议的 ML 应用程序开发

原文:https://towardsdatascience.com/can-a-data-scientist-replace-a-nba-scout-ml-app-development-for-best-transfer-suggestion-f07066c2773?source=collection_archive---------16-----------------------

实践教程

使用 NBA API 创建自己的 ML 模型并预测最佳球员交易

“我有一个行动计划,但这个游戏是一个调整的游戏” |迈克·沙舍夫斯基

照片由 JC Gellidon 在 Unsplash 上拍摄

由于最*达到顶峰的希腊怪胎,我给了这个项目一个机会,这个项目我潜伏了几个月。那就 NBA 吧!

本文的主要内容是提出一个端到端的 ML 应用程序开发过程,其中包含了大量的监督和非监督算法,包括高斯混合模型(GMM)K-Means主成分分析(PCA)XGBoost随机森林和多项逻辑回归分类器

概念

在成功聚集威士忌品种以促进供应商的销售后,数据公司接受了一个新项目:协助密尔沃基雄鹿队在 2020 年交易窗口期间做出最佳下一步行动。即预先接触得分后卫(SG)位置的候选球员,并购买表现最好的球员。对篮球知识的无知让我想到了一个棘手的选择:

请求 NBA API,从过去赛季的比赛中获取球员数据(例如,助攻失误率、助攻百分比等),以一种有意义的方式为总经理(GM)分类,并最终指导他应该在谁身上花费转会预算,怎么样?

为了更好地传达结果,我们做了几个假设:

#1:我们在 2020 赛季(10 月)结束。雄鹿通用为 SG 职位准备了 3 名候选人名单:朱·霍勒迪丹尼·格伦博格丹·博格达诺维奇

#2:为了完成任务,我们必须从数据中发现任何可能导致雄鹿在各自主场进攻中提高表现的见解(最大助攻数、最小失误数等),同时保留其余的统计数据(即加权投篮命中率%等)。也就是说,我们不应该简单地建议总经理购买最好的传球手或得分手,因为这可能会损害其他有价值的数据。

作案手法

  1. 构建数据集;获取每个游戏的玩家统计数据(从现在开始“游戏”)。
  2. 执行**EDA;**对变量的利用建立直觉,得出最早的结论。
  3. 集群‘玩’通过K-Means&GMM;揭示潜在模式并确定最适合该案例的群集。
  4. 使用现在标记的数据集(clusters = labels),训练多个多类分类器,包括多项式 逻辑回归随机森林 & XGBoost
  5. 对候选球员的最新‘比赛’(2020 赛季)进行预测,并据此对其进行基准测试。
  6. 通过构建&服务 API(在下一篇文章中分析),向最终用户提供**训练好的模型。

工作流程图(图片由作者提供)

您可以运行解释过的工作流程的笔记本或脚本文件(。py)为自动的

1.资料组

该数据集分两步构建:(a)从这个 Kaggle 数据集开始,我们查询basketball.sqlite以提取 2017-2020 赛季的GAME_IDs,( b)我们向 NBA_api 发出请求以获取每场比赛的球员数据。

整个过程被打包在[dataset.py](https://github.com/makispl/ml-nba-transfer-suggestion-app/blob/main/src/dataset.py)中,你可以选择运行它,或者使用已经准备好的数据集,放在“ data/raw 目录中。

我们使用 2017-2019 赛季的比赛来训练聚类和分类模型,并保留 2020 年的数据用于测试。以下是数据集的样本和对变量的充分的解释:

plays_df数据集样本

在减杂的脉络中,我不深究 数据清理 预处理 程序——大家可以分别参考00 _ EDA . ipynb&preprocess . py

2.电子设计自动化(Electronic Design Automation)

00 _ EDA . ipynb中提供了一个完整的 EDA

当涉及到评估 SG 的性能时,我们必须根据真正重要的东西来建立直觉。在这种情况下,我们根据领域知识将特性从最不重要的到最重要的进行分类。这也会让你更容易做出最终决定。

*# classify features by domain importance
group_1 = [OF_RATING,AST_PCT,AST_TOV,TM_TOV_PCT,EFG_PCT,TS_PCT,POSS]
group_2 = [MIN, AST_RATIO, DREB_PCT]
group_3 = [OREB_PCT, REB_PCT, USG_PCT, PACE, PACE_PER40, PIE]
group_4 = [START_POSITION]
group_5 = [DEF_RATING]*

已解释-分类特征

简而言之,就零存在、重复样本或低方差而言,所有特征都是高质量的,而它们的边界是有意义的(没有不合理极值的可疑情况)。

特征直方图

然而,它们中的许多都包含了任一侧的异常值。这是意料之中的,因为我们处理的是真实的游戏,没有人(甚至是不同游戏中的同一玩家)能够总是在一个固定的性能“范围”内表现。

特征的须盒图

关于关键的一组group_1特征,它们在左右倾斜之间几乎是*衡的。然而,占主导地位的因素是超出相关上限的异常值的大量存在。有许多球员经常表现出色,超出预期,这一事实符合我们最初的结论:

归纳#1 :我们必须深入研究group_1,不仅要保证各自特性的显著水*,而且不能损害(尽可能多的)其他特性。

考虑到这一点,我们启动了一种简单的方法,通过主特征(AST_PCT)对数据集进行排序,取其较高的部分(第 95 百分位)并“水*地”(跨所有特征)评估剧本。

plays_df描述性统计(人口)

plays_df描述性统计(第 95 百分位)

结果令人失望。通过将人口与第 95 百分位的*均特征进行比较,我们看到随着AST_PCT的最大化,许多剩余的特征变得更差,违反了假设 2。另外,我们也不愿意买一个助攻率很高但投篮表现很差的 SG(EFG_PCT)!

因此,很容易想到,我们无法基于简单的探索技术完成构建最佳 SG 轮廓的任务。因此:

归纳#2 :我们必须在现有数据的基础上建立更好的直觉,并使用更先进的技术,有效地对其进行细分并捕捉潜在的模式,这可能会引导我们找到最佳的 SG 档案。

集群拿起火炬…

3.使聚集

参考01 _ 聚类【kmeans_gmm】。ipynb

k 均值

我们从流行的 K-Means 算法开始,但是首先实现 PCA,以便降低数据集的维数,同时保留大部分原始特征的方差[1]。

pca4clustering.py

PCA ~解释方差

我们选择一个 4 部分的解决方案,因为它解释了至少 80%的人口方差。接下来,我们通过使用肘形法并绘制 WCSS 线,找到最佳的簇数(k ):

locate _ 肘部. py

WCSS ~团簇图

最佳聚类数是 4,我们准备好拟合 K 均值。

kmeans.py

k-均值聚类

得到的聚类还不错,但是分别有许多cluster_2cluster_3蓝绿色&蓝色的重叠点。为了寻求潜在的增强,我们将研究另一种聚类算法。这次不是基于距离,而是基于分布;高斯混合模型【2】。

戈-梅-莫三氏:男性假两性畸形综合征

一般来说,GMM 可以处理更多种类的形状,而不需要假设聚类是圆形的(像 K-Means 那样)。此外,作为一种概率算法,它为数据点分配概率,表示它们与特定聚类的关联有多强。然而,没有免费的午餐;GMM 可能会很快收敛到局部最小值,从而恶化结果。为了解决这个问题,我们可以用 K-Means 初始化它们,通过调整各自的类参数[3]。

为了挑选合适的聚类数,我们可以利用 Scikit 中的贝叶斯高斯混合模型类——了解哪些权重聚类,将错误的聚类拉*为零或接*零。

贝叶斯 _gm.py

*# returns
array([0.07, 0.19, 0.03, 0.14, 0.19, 0.09, 0.06, 0.18, 0.05, 0.01])*

显然,只有 4 个集群超过 0.01 阈值。

gmm.py

GMM 星团

就是这样!cluster_3(蓝色)这次更好分离,而cluster_2(青绿色)也更好包容。

聚类评估

为了增强聚类评估,我们引入了一个新的变量,它描述了被检查特征的净得分。对每组进行加权,以便更好地表达其对最终性能的影响,并计算它们的代数和。我将权重分配如下:

*NET_SCORE = 0.5*group_1 + 0.3*group_2 + 0.2*group_3 - 0.3*group_5# group_4 (START_POSITION) shouldn't be scored (categorical feature)
# being a center ‘5’ doesn't mean to be ‘more’ of something a guard ‘1’ stands for!# group_5 (DEF_RATING) is negative in nature
# it should be subtracted from the Net Score*

那么,让我们对集群进行评分和评估。

net_scoring.py

通用汽车集群得分由NET_SCORE

显然,cluster_3的表现优于其他产品,其NET_SCORE为 aprox。662.49,而cluster_1紧随其后。但是,这里值得强调的是第 95 百分位和新引入的cluster_3之间的量化比较:

**

NET_SCORE第 95 百分位& cluster_3 的须盒图

通过注意 146.5 个NET_SCORE单位的增加,可以清楚地看到cluster_3在第 95 百分位段中占主导地位!因此:

归纳#3 : Cluster_3以一种真正*衡的方式概括了那些源自 SG 出色表现的“剧本”——group_1特性达到了较高水*,而其余大部分保持了不错的*均水*。该分析考虑了比最初尝试更多的特性(参考文献 1)。EDA),它利用了一个主导者(AST_PCT)。这证明了…

归纳#4 :聚类促进了更全面的数据分离,这些数据来自更多组件的信号,沿着这些思路,我们设法揭示了顶级 SG 的预期性能的更清晰指示。

现在,我们能够操纵标记的(具有聚类)数据集,并开发一种方法来预测新样本(未标记的“播放”)所属的聚类。

4.分类器

参考02 _ 分类【logres_rf_xgboost】。ipynb ]

我们的问题属于多类分类的范畴,要采取的第一步是选择一个验证策略来解决潜在的过度拟合。

*# check for the clusters' balance
0    27508
1    17886
3    11770
2     5729*

偏斜的数据集意味着必须选择一个分层 K 倍交叉验证,而不是随机验证。这将使标签的比率在每个折叠中保持不变,无论我们选择什么度量来评估,它都将给出相似的结果[4]。说到指标,F1 分数(精确度和召回率的调和*均值)看起来比准确度更合适,因为目标是倾斜的[5]。

创建 _ 折叠. py

接下来,我们标准化数据,以便训练我们的(基线)逻辑回归模型。请注意,这里首先要适合训练数据集,然后转换训练和测试数据。这对于避免数据泄露至关重要[6]!

基线 _ 模型. py

*# returns
Mean F1 Score = 0.9959940207018171*

特征重要性

如此惊人的准确性从一开始就令人生疑。在检查特征重要性的可用方法中(例如 MDI),我选择了置换特征重要性,它是模型不可知的,因此我们能够对所有模型使用任何结论【7】。

置换 _ 专长 _ 重要性. py

排列特征重要性为:(a)所有特征,(b)所有START_POSITION,(c)所有START_POSITIONMIN

START_POSITION贡献的重要性极高(单独计算,得分 F1=0.865 )。如果我们检查相关的描述性统计,我们看到所有的group_1特征在START_POSITION为 0(即 NaN)时得到最低水*。

START_POSITION描述性统计

暴露了这些玩家没有开始游戏,所以他们很有可能比其他人玩的时间少,因此他们的统计数据更差!这同样适用于MIN变量——它精确地表达了一名球员在球场上花费的时间。因此两者都会导致数据泄漏,我们忽略它们。除此之外,我们还区分了最重要的特征。

特征工程

此外,我们试图通过构建一个新的、数量更少的变量来减少特征的数量,这些变量捕获了原始信息的重要部分。我们再次将 PCA 置于聚光灯下,这一次尝试 9 和 7 组分。注意只使用剩余的标准化特征(≦START_POSITIONMIN)!

最终,我们产生了以下特征“桶”:

*all_feats   = [all] - [START_POSITION,MIN]
sgnft_feats = [all_feats] - [OFF_RATING,AST_TOV,PACE,PACE_PER40,PIE]
pca_feats   = [pca x 9]
pca_feats   = [pca x 7]*

超参数优化

在考虑了特征选择之后,我们开始优化每个模型的超参数。 GridSearch 非常有效,尽管很耗时。该过程与所有模型相似——为了简单起见,我只给出 XGBoost 案例:

xgboost_grid_search.py

*# returns
Best score: 0.7152999106187636
Best parameters set:
      colsample_bytree: 1.0
      lambda: 0.1,
      max_depth: 3,
      n_estimators: 200*

模型

现在,我们在 model_dipatcher.py 中声明每个模型的最佳超参数,它将我们选择的模型分派到 train.py 中。后者总结了整个训练过程,使训练具有每个特性“桶”的调整模型变得更加容易。我们得到:

*## Logistic Regression ## used               num_feats            F1_weighted
=========      |      =========     |      ==========
all_feats      |         16         |        0.7144
sgnft_feats    |         11         |        0.7152
pca_feats      |          9         |        0.7111 # sweet-spot
pca_feats      |          7         |        0.7076## Random Forest ## used               num_feats             F1_weighted
=========      |      =========     |       ==========
all_feats      |         16         |         0.7213
sgnft_feats    |         11         |         0.7145
pca_feats      |          9         |         0.7100
pca_feats      |          7         |         0.7049## XGBoost ## used               num_feats             F1_weighted
=========      |      =========     |       ==========
all_feats      |         16         |         0.7238  #best
sgnft_feats    |         11         |         0.7168
pca_feats      |          9         |         0.7104  
pca_feats      |          7         |         0.7068*

:由于模型的随机性质或数值精度,您的结果可能会有所不同。

引入了经典的性能简单性的权衡;我选择了具有 pca_feats (x9)的逻辑回归的潜力来进一步进行。

5.预言

现在,对于测试数据集的剧本,我们通过使用所选择的模型来预测它们的聚类。

预测. py

确认

为了进行验证,基本事实标签是必要的。然而,这不是我们的情况,因为测试数据集(test_proc.csv)没有被标记。您可能想知道为什么我们不通过聚类来标记它,但这将引导我们执行完全相同的程序,交叉验证已经完成了 5 次—隔离一小部分数据并进行验证。

相反,我们将通过进行定性检查来进一步评估分类器。我们可以手动检查一部分数据的标签,以确保它们是好的,或者将预测值与训练聚类进行比较,并检查任何主要的描述性统计数据是否仍然有效。

通过NET_SCORE预测集群得分

事实上,cluster_3以 109.35 辆的NET_SCORE成绩再次领先于其他厂商,同时在大多数关键特性(OFF_RATINGAST_PCTAST_TOVPOSS)上保持最高水*。

交易

最后也是最有趣的部分涉及到决策。首先,我们对候选球员(朱·霍勒迪丹尼·格伦博格丹·博格达诺维奇)在 2020 年上半赛季的“发挥”进行预测,并用各自的聚类对他们进行标注。

然后我们检查它们在cluster_3中的成员资格,根据各自的cluster_3_plays / total_plays比率对它们进行排序。因此,我们运行predict.py脚本并得到:**

**# Results
{
 '**Jrue Holiday**': **0.86**,
 'Bogdan Bogdanovic': 0.38,
 'Danny Green': 0.06
}**

你猜怎么着?

密尔沃基雄鹿队关于朱·霍勒迪转会太阳队的推特

2020 年 11 月 24 日,雄鹿官方宣布朱·霍勒迪交易!你这样认为;一个脱离现实的验证…

结论

到目前为止,我们已经走了很长的路……从 Kaggle & NBA API 开始,我们建立了一个庞大的数据集,对它进行了聚类,并揭示了成为一名真正优秀的得分后卫所需要的深刻模式。然后,我们在带标签的数据集上训练各种分类模型,以相当高的精度预测新玩家条目可能注册的集群。通过这样做,我们成功地聚焦了密尔沃基雄鹿队的下一步行动。)拿着,去补 SG 的位置。

类似于 DJ vs 数据科学家的案例,几乎不可能武断地回答数据科学在球探领域的潜力。然而,时代的迹象再次表明了人工智能在体育产业决策领域实施的有利温床…

照片由帕特里克·福尔在 Unsplash 拍摄

我把这个项目献给我的好朋友帕诺斯——一个狂热的篮球迷、天文爱好者和 IT 专家。

感谢您的阅读&祝您度过愉快的一周!如果有任何问题,欢迎在下面留言或通过 Twitter / LinkedIn 联系我。无论如何…

坐下来,克隆回购,开始下一步……行动🤝

参考文献

[1]https://machine learning mastery . com/dimensionally-reduction-for-machine-learning/

[2]https://www . analyticsvidhya . com/blog/2019/10/Gaussian-mixture-models-clustering/

[3]https://towards data science . com/Gaussian-mixture-models-vs-k-means-one-to-choose-62f 2736025 f 0

[4] A .塔库尔,《接*(几乎)任何机器学习问题,第一版(2020),isbn-10‏: 9390274435

[5]https://towards data science . com/comprehensive-guide-on-multi class-classification-metrics-af 94 CFB 83 FBD

[6]https://machine learning mastery . com/data-preparation-without data-leaving/

[7]https://sci kit-learn . org/stable/modules/permutation _ importance . html

高压锅可以冲全豆咖啡吗?

原文:https://towardsdatascience.com/can-a-pressure-cooker-brew-coffee-with-whole-beans-d28cf50b1d0f?source=collection_archive---------14-----------------------

咖啡数据科学

这可能是个坏主意

我没花太多心思在这上面。我想预先警告所有可能想玩巨魔的人。我有很多咖啡实验,非常酷和有趣,还有一些是因为我看着像我的火锅一样的东西,问自己,“我想知道我是否可以用它来煮咖啡,但不需要研磨?”所以我就这么做了。

首先,它不工作,但我很高兴这样做。

所有图片由作者提供

我将 18 克咖啡放入装有 54 克水的杯子中。我以为会吸收一些水分。我把它放入装有水的球拍上的火锅或速溶锅里,然后我打了蒸汽。

我想水应该是热的,有压力,这两样东西加上流量就成了浓缩咖啡。那么没有流量呢?而不磨呢?

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

2 分钟后,我测量了一下,只有 1.52 TDS。所以我又戴了 15 分钟。

仍然只有 4.43 TDS,所以我又做了 15 分钟,以 5.29 TDS 结束。这很难令人满意。

支点!

所以我想,为什么不把这整个混合物扔进维生素 a 混合物里呢?因为如果你想变得古怪,那就试试吧!

好吧,也许这是个糟糕的主意,咖啡没有磨好。大概是因为是刀片研磨机,液体不够。

使用毛刺研磨机!

再次旋转!

所以我把它废弃了,我把它放进了我全新的零号位置!

开个玩笑!

我疯了,但不傻。我把它放进一个杯子里,用我的浸泡式搅拌机多加了一点水。

然后我需要过滤这种混合物,所以我把它倒进我信赖的 Kompresso。首先,我过滤掉所有的液体:

然后我加入了剩下的大块咖啡。

虽然颜色不吸引人,但我尝了第一半,尝起来像是未充分提取的酿造品。我还做了一些 TDS 测量来估算提取率。

从数字来看,咖啡没被充分提取。我想知道根据云量,TDS 测量是否关闭。

就像随机实验一样,有时它们不起作用。然而,我已经进入了发布我正在尝试的任何东西的模式,以防万一。

这个故事的寓意是,你应该在冲泡之前研磨咖啡豆,以防这还不明显。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我中。

我的进一步阅读:

个人故事和关注点

乐高故事启动页面

浓缩咖啡系列文章

一台用于制作优质浓缩咖啡的叶片研磨机

浓缩咖啡:群头水温分析

真空罐能更快去除咖啡豆中的气体吗?

在水中跌跌撞撞:浓缩咖啡水实验

克莉玛,嗯,它有什么用?

南印度咖啡

重新研磨用过的咖啡,制成意式浓缩咖啡

冲泡咖啡渣

咖啡水果茶 via Flair Espresso

强迫症工具对浓缩咖啡不起作用

单个 app 能代替所有图像神经分类器 app 吗?一个有趣的夹子

原文:https://towardsdatascience.com/can-a-single-one-replace-all-image-neural-classifier-apps-a-fun-with-clip-cdaa4c4edd84?source=collection_archive---------31-----------------------

Android 设备上零镜头学习的 OpenAI CLIP 模型部署。TL DR:app 在这里这里,随意试验一下吧!

通用分类器适用于概念概括(作者拍摄的应用程序截图)。灵感来自 unsplash (中)和 unsplash (右)的 Ed van duijn

什么是剪辑,为什么有趣?

今年 1 月,图像处理领域取得了一项重大突破——open ai 展示了一种新的神经网络生成器 Dall-E,它可以根据文本描述生成图像。尽管名为 OpenAI,但它并没有开源。然而,我对一个作为 Dall-E 训练和最佳生成范例选择的辅助神经网络非常感兴趣。与 Dall-E 相反,CLIP 是一个在 MIT 许可下发布的开源项目,因此人们可以在任何地方轻松使用它。这个神经网络可能不太适合演示,但它让我印象深刻。总的来说,这是一个两个模块的项目。第一个模块是一个非常有效的图像转换器神经网络。该深度神经网络使用最先进的注意力机制将图像编码到 512 维嵌入空间中。另一个部分是文本转换器,它将文本转换成向量,再转换成同样的 512 维空间。

零镜头学习的剪辑工作和 it 应用方案(图片来自剪辑 github

我没有找到任何关于训练过程的数据,但我认为这是对 cosface/arcface loss 的一些修改,对这两个模块采用了不同的训练机制。至于数据,尽管模型本身的大小相对较小,但训练这样的模型所需的数据是巨大的。因此,CLIP 在大量签名图像上进行训练,这些图像可能是在整个互联网或维基上解析的。然而,每个人都可以使用预训练剪辑。

为什么剪辑让我印象深刻?

由于它有效地将图像和文本转换到一个空间(CLIP 意味着对比语言-图像预训练),因此使用它可以容易地执行零镜头学习。如果我们生成类似“这是一张猫的照片”和“这是一张狗的照片”的文本,并将它们转换为矢量(对它们进行编码),我们可以检查任意转换的图像是更接*“猫”还是“狗”矢量。正如 OpenAI 博客文章中所示,这种分类方式甚至比针对特定分类任务在大数据集上预先训练的经典卷积神经网络更有效。我检查了这个事实,发现它对我尝试过的大多数任务都是正确的。在极少数任务中(例如,照片中的矿物名称),经典搜索结果显示稍好的结果。我在玩 CLIP 的过程中发现的第二个令人印象深刻的事实是预测的灵活性,我甚至发现 CLIP 的图像部分能够识别一些文本的照片(它在英语照片上工作得很好,其他语言感觉更差)。这种能力来自注意力机制,它允许更复杂的特征估计。几天前 OpenAI 发表了另一篇关于在剪辑的图像部分探索神经元激活的精彩帖子,显示相同的神经元在完全不同的图像中被激活,对应于相同的概念。例如,类似的神经元在蜘蛛的图像、蜘蛛侠的图画和文字“蜘蛛”的照片上被激活。
第三,CLIP 的图像转换器部分相对较轻。它甚至可以在 CPU 上实时工作。在 GPU 工作显示出非常高的帧率。另一方面,Textual transformer 没有这么快。
我已经测试过,发现 CLIP 图像转换器部分可以很容易地在 android 设备上运行,我决定创建一个应用程序,可以使用 CLIP 的转换器部分进行分类。

应用架构

我实现了图像转换器以及图像预处理部分,可以访问图像存储和 android 应用程序的设备摄像头。图像转向其 512 维嵌入。还有,我有几组对应不同概念的向量(在 pc 上预生成)。每个集合可以对应一个特定的主题(例如宠物品种、食物、国籍、年龄、名人等)
之后,我将该图像与集合中的每个向量进行比较(使用余弦相似度的 softmax ),并显示得分最高的前 5 个答案。为了扩展分类器的可能性,增加了用于生成新集合的模块。新分类器的类别列表可以从应用程序发送到服务器。服务器使用文本转换器部分将概念转换为向量,并将其返回给应用程序。用户获得了一个新的分类器!开发部署方案如下所示:

应用程序的流水线和架构(图片由作者提供)

Python 部分

我用过 python 的 Anaconda 发行版。让我们从虚拟环境的创建和调整开始

安装所有软件包后,让我们开始工作!在 jupyter 笔记本中导入所有必需的包:

比我载入模型

选择和编译可视转换器部件“aardvark.jpg”可以是任何图像:

然后我寻找一些与主题相关的列表(大部分来自 wiki ),并使用该功能从模板中创建句子:

该函数将模型保存为*。pt 文件,并为 android 的进一步使用创建 XML。该 XML 包含所有的类名。csv 列出了 4000 个最常用的英语名词

Java 部件(应用程序)

尽管 Kotlin 语言更容易用于 android 开发,但我更喜欢 Java,因为我在这方面有一些经验,而在 Kotlin 方面完全没有经验。

不幸的是,Java 代码太重,可读性差,所以我将只展示 2 个重要的部分

  1. 加载可视转换器和顶级模型(这里我还添加了传统训练的头部模块,用于在 X 射线上检测肺部肺炎,以显示额外的可扩展性):

2.然后我添加一个重要的客户端部分(服务器部分)。这是一个用于服务器请求并将响应(头模型)保存到 ExternalFilesDir 的模块。类和模型名称的 Dir 列表保存在这里:

请求的 URL 是基于要扩展的类和句子构建的。代码的另一部分以及接口部分在当前的出版物中没有显示。

Python Flask 服务器部分

我在其中一个网站上租了 VPS。关于系统——我已经在 Centos 7 下用 WSGI/Flask 启动了一个 apache 2.0 服务器(对我来说这是最难的部分,因为我以前从未使用过服务器部署,所以需要几天的 googling 和 StackOverflow 搜索)
Python 服务器部分类似于 cerate_xml 函数。唯一的区别是处理请求和发送回生成的模型文件。不幸的是,服务器的运行速度没有我希望的那么快。如果该应用程序将会流行,我应该将一些计算转移到 AWS Lambda:

app 修改方案(图片作者提供)

好玩的部分!测试!

该应用程序运行得非常好。首先,让我们重复一下 OpenAI 的惊人结果,它在一个由不同方式表示的概念上发现了相似的神经元激活:

通用分类器适用于概念概括(作者拍摄的应用程序截图)。作者打印的左侧图像。中央图片由艾德·范·杜伊因从 unsplash 拍摄。右图由hello ' mnik从 unsplash 拍摄

通用名词分类器使用由模板“这是名词的图像”生成的 4000 个最常用的英语名词和句子

该应用程序明确“理解”所有这些概念都与蜘蛛有关。有趣的是,它可以识别文本,所以我决定在比利时艺术家雷内·玛格利特的作品上测试它,他的作品充满了文字和图像的互动:

雷内·玛格利特艺术品描述(autor 截图)

没什么特别有趣的。但有趣的是,当我试图用国籍或用鸡尾酒名或狗品种来描述这张图片时:

不同的分类器处理同一个图像示例(作者制作的截图)

这里肯定有法国的东西)。我还发现用鸡尾酒的名字来描述图像特别有趣:

有限选择的关联搜索示例(作者截图)图片来自 unsplash 的 HelloI'mNik

绿魔?真的吗?这里我真的被联想思维的那个变形金刚给打动了)。有人可能会说,这是一个又红又大、会飞、甚至类似昆虫的东西的图像。为了测试服务器部分,我创建了一个自定义分类器,通过图像来确定职业。我从一些英语教科书上找到了 30 种职业的清单,并把它们加了进去。模型已在服务器上成功生成并下载。不幸的是,这需要几分钟(

自定义模型创建图像模板和类的界面可以更改(作者截图)

让我们测试新的分类器:

用户创建的职业分类器工作的例子(作者制作的截图)。左图 iby westwindairservice 发自 unsplash 。右图来自Francisco venncio来自 unsplash

帕克先生是谁?

蜘蛛侠先生是谁?(作者截图,图片由hello ' mnik来自 unsplash )

至于其他类型的分选机机头,它们可以按预期工作:

不同分类器工作的结果(作者截图),左图由
吉拉辛·约斯里来自 unsplash 右图由历史高清来自 unsplash

或者,正如 OpenAI 研究人员发现的那样,我们可以用它们来捕捉一些明显的关联:

中国风景描述(作者截图,landskape 作者 Alice Triquet 来自 unsplash )

但是另一方面,剪辑网络继承了关联,包括来自训练数据集的一些预先判断:

分类器的预判断存在于图像转换器中(作者制作的截图,图像来自高清的历史记录来自 unsplash )

应用程序部署到 Google Play

我已经将应用程序发送到 Play market,但它正在 1 周的检查过程中,所以一旦它通过,我会在这里添加一个链接。尽管如此,如果你不害怕,你可以在这里使用 alpha 版本 apk(广告尚未添加,所以我计划在 Google play 版本发布后关闭 alpha 应用的服务器部分)。更新:在 Play Market 上!

货币铸造

我将从 AdMob 添加几个横幅来获得一些钱)

问题

在描述的应用程序中有几个问题。首先,我发现由于应用程序启动时图像转换器加载到 RAM,几个设备出现了缓慢的(5s)冷启动。第二个问题是服务器对新分类器请求的响应缓慢。可以通过把计算搬到云端来解决(我考虑的是 AWS lambda 服务),但是现在我在纠结 AWS lambda 价格的估算和 app 的受欢迎程度。我可能应该限制每个用户对服务器的每日请求,或者向用户收取限制增强费,以弥补 AWS 的开支并提供更好的 UX(

未来的改进

我还在考虑增加一次拍摄模式(用于分类器创建的单张照片)。这种改进很容易在应用程序中实现。此外,我还尝试了很多 CLIP 和 BERT 的组合来生成图像的自然语言描述,并已经获得了一些有希望的结果。但是 BERT 肯定不能在手机上运行,甚至不能在我的 rtx3080 GPU 上运行,这种透视系统的快速原型化存在一些问题。

谢谢大家!

如果有新想法、提议或问题,请随时联系我!

有用的链接:

关于达尔-e:

https://openai.com/blog/dall-e/

关于剪辑:

https://openai.com/blog/clip/

剪辑 github:

https://github.com/openai/CLIP

关于 CLIp 和多模态中的神经元激活:

https://openai.com/blog/multimodal-neurons/

人工智能能改变我们回收垃圾的方式吗?

原文:https://towardsdatascience.com/can-ai-transform-the-way-we-recycle-our-trash-75a91bd9e0c6?source=collection_archive---------29-----------------------

大多数 TDS 帖子汇集了理论专业知识和现实世界的影响——无论是简短的教程还是对前沿研究的透彻解释。本周,你应该看看我们在最*的记忆中看到的一个最好的例子,一个弥合理论/应用差距的项目。

你有没有站在回收箱前不确定某样东西是否属于它? Duncan Wang 、 Arnaud Guzman-Annès 、Sophie Courtemanche-Martel和 Jake Hogan 向我们介绍他们关于人工智能简化和优化回收项目潜力的项目。他们出色地奠定了技术基础(在这种情况下,CNN 或卷积神经网络),然后展示了如何利用 CNN 来推动真正的变化,并在影响我们所有人的领域产生积极的结果。我们希望你在阅读他们的作品时会有所启发——我们当然有!

Lee Jeffs 在 Unsplash 上拍摄的照片

灵感可以——也确实——有多种味道和色调。通常,与我们的读者产生共鸣的不是一个特定的主题或方法,而是一种有用的洞察力:你离开文章时感觉自己处于一个更好的位置来思考问题或执行解决方案。Seth billiou 的对排列特征重要性的探索是前者的一个坚实的例子。看着黑盒模型和解释它们如何产生结果的困难,Seth 展示了放大特定特征如何帮助我们看到哪些特征具有最大的预测价值。后退几步(还是前进?),TDS 播客主持人 Jeremie Harris 和他最*的嘉宾 Evan Hubinger 聊了聊内部校准问题以及我们如何解决目前潜伏在该领域不远的将来的安全问题。另一方面,Prukalpa 分享了她和她的团队在与时尚零售商 TechStyle 的合作中获得的经验。她重点讲述了他们如何实施符合公司需求的全新数据仓库,详细介绍了他们在此过程中面临的挑战。

想要找到一篇*衡实践知识和奇思妙想的文章,只需看看马特·索斯纳关于算法和大型鱼群行为惊人相似之处的文章。以他的博士研究为出发点,Matt 在他观察到的鱼的集体决策和集成学习算法之间画出了迷人的联系,并想知道“鱼群是否充当了一个巨大的神经网络。”

发现不同领域和概念之间意想不到的联系是有效学习的标志之一;如果你正在寻找一些关于如何扩展你的数据科学技能组合的实用建议, Julia Nikulski 根据她的个人经历为整理了几个极好的建议——从创建你自己的数据集到深入学术研究。想要更多的想法(和更多的灵感),一旦你阅读了 Julia 的帖子,继续阅读 TDS 编辑 Elliot Gunn 最*与谷歌定量用户体验研究员 Randy Au 的对话。Randy 强调让利益相关者了解数据洞察的价值的重要性,以及在与你加入的组织相关的特定领域进行自我教育的重要性。

如果您正在寻找其他方法来改进您的工作流并提高日常数据科学流程的效率,我们还没有完成!诺亚·伯班克基于他在 Salesforce 的工作,发表了一篇全面的深入探讨选择正确的文本分类模型的艺术,在 sales force,选择通常取决于“我们的训练数据在多大程度上捕捉了它将在生产中得分的数据的多样性。”同时, Parul Pandey 提供了一个解决常见难题的方法——当你意识到破译自己的代码库有多困难的时候。作为一个解决方案,Parul 建议自动化你的项目结构,从创建一个可重用的模板到将你的代码推送到 GitHub。

无论你处于数据科学之旅的哪个阶段,我们都希望你在本周发现了新的东西,无论是工具、流程还是崇高理念的实际应用。感谢您的阅读、讨论和对我们工作的支持。

直到下一个变量,
TDS 编辑

我们策划主题的最新内容:

入门指南

  • Node2vec 图文解说作者刘雷米
  • Mathias Gruber从初级数据科学家到首席数据科学家的 20 个经验教训
  • LinkedIn 对 Eryk Lewinson 的《预言家——银风筝和灰风筝

实践教程

  • 你认为你的社交媒体评论有多恶毒?由 Navjot Bians
  • 如何调整机器学习模型的超参数作者 Chanin Nantasenamat
  • 如何用 Python 解决一个人员调度问题作者 Khuyen Tran

深潜

  • 知识之座:具有深度结构化知识的人工智能系统作者加迪·辛格
  • 我们能用卫星研究积雪吗?由威尔·诺里斯
  • 树莓派园艺:用树莓派监测菜园——第 1 部分作者克里斯蒂安·霍林格

思想和理论

  • 机器学习和量子物理之间的对称性改善了模拟Therese Paoletta
  • 困扰艾的伪哲学作者本楚格
  • 数据匿名化:来自一位前怀疑论者的观点作者 Patricia Thaine

算法可以种族歧视吗?

原文:https://towardsdatascience.com/can-algorithms-be-racist-6dddf8d69065?source=collection_archive---------18-----------------------

语言模型中法律和社会困境的简要探讨

由马库斯·斯皮斯克在 Unsplash 上拍摄的照片

随着人工智能(A.I .)继续快速融入日常生活,一些伦理困境也同步出现,它们对用例的影响成为了许多辩论的主题(Kilbertus 等人,2017;哈特等人,2016;Pazzanese,2020)。本文关注的一个困境与包容性和边缘化有关(Bender 等人,2021)。在算法模型的形成中,强化霸权力量的训练数据如何影响参与的概念?因此,本文将通过对文献进行定性调查以讨论偏见放大而获得的基础解释主义观点,来寻求强调人工智能中的伦理挑战。正如 Bender 等人(2021)所概述的,关于语言模型的发展和利用,存在几个法律和社会困境。这包括强化对边缘化人口的霸权力量,这是具体化力量不*衡的训练数据特征的结果。

富裕国家从语言模型中受益更多,而贫穷国家则受到训练数据的负面环境影响,而这些数据对它们几乎没有好处(Pratik et al .,2020);他们也在很大程度上被排除在技术进步之外或代表性不足。在解决这些问题时,Bender 等人(2021)建议仔细规划和管理数据集,以期采用价值敏感的设计方法,从而减少语言模型不准确以及进一步征服某些群体的定型观念的永久化所造成的负面影响。

此外,建议在构建模型时建立基准,通过预记录严格审查数据收集和使用情况,以提高包容性,确保公*性并鼓励准确性。参与的概念也受到训练数据的负面影响,这些数据的背景和制度基础是深度学习中的偏见。例如,美国惩教罪犯管理概况分析替代制裁(COMPAS)中使用的算法对非裔美国人有固有的偏见,因为它给予这一群体比高加索人更高的风险评级,即使两者都有确切的罪犯概况(Mehrabi 等人,2019 年)。Obermeyer 等人(2019)引用了一种在美国医院中广泛使用的流行算法,该算法减少了黑人在与其他群体相同的复杂健康情况下访问医疗计划的可能性。

这种在深度学习算法模型的形成中霸权力量的加强突出了人工智能中的偏见放大,以及对识别、根除和丢弃歧视性训练数据的严格检查的需要,无论是在数据收集、预处理、处理中还是后处理阶段(Mehrabi 等人,2019)。计算机视觉是人工智能中另一个存在霸权结构的领域。Buolamwini 等人(2018 年)强调了分析人脸的算法中的性别和种族问题:肤色较浅的男性比肤色较深的女性更少出现任务错误。同样,算法模型如何以一种形成标准自然智能的方式安排视觉世界,取决于它接收的数据集,这些数据集通常不具有包容性。

例如,在谷歌上快速搜索冠状病毒图片,会显示大量彩色分子的图片,而搜索埃博拉病毒,会显示各种非洲人处于虚弱状态的图片。尽管冠状病毒在全球范围内产生了更大的负面影响,但网上的图片并没有反映出一个群体比另一个群体更糟糕。人们可以提出这样一个问题:谁来决定应该看什么和如何看?谁来决定现实世界和虚拟世界是如何协商的?因此,如果计算机视觉有能力塑造感知,从而塑造行为和思想,那么,正如 Pereira (2021)所建议的,有必要从根本上摆脱这些歧视性的概念。但是如何做到这一点呢?在上述人工智能领域,研究人员对伦理挑战保持警惕的动机是什么?

首先,财政补贴应该给予那些在训练数据或部署模型中积极展示权力动态*衡的研究人员,也就是说,建议消除一个人口统计学对另一个人口统计学的显性或隐性优势。其次,事实上反过来说,经济支持或公共资金应该被取消,所创建的算法模型对那些在研究中不注意伦理困境的人工智能研究人员来说是一种令人厌恶的刺激。第三,应该从高质量的研究中建立一个经过同行评审的标准化和最佳实践指标分类框架,该框架应在整个研究过程中积极、一致地纳入道德规范的使用。

人工智能在主要行业中得到成功应用,因此,该领域面临的各种挑战是全方位的。考虑到这一点,如果训练算法的数据集错综复杂地局限于某些霸权原则,那么数据化过程最终将扩大这一点,进一步挑战参与的概念。因此,伦理在人工智能中至关重要,研究人员有责任确保系统地捍卫和推进是非、公*和*衡的概念。

文献学

Bender,e .,Gebru,t .,McMillan-Major,A & Shmitchell,S. (2021)论随机鹦鹉的危险:语言模型会不会太大?。关于公*性、问责制和透明度的会议。纽约,3 月 3 日至 10 日,1 日至 14 日。

J .布朗利(2019 年)。具有深度学习的多标签分类。可在网上获得:https://machine learning mastery . com/impact-of-dataset-size-on-deep-learning-model-skill-and-performance-estimates/【访问于 2021 年 12 月 12 日】。

J .布朗利(2021 年)。如何选择深度学习的激活函数
网上有:https://machine Learning mastery . com/impact-of-dataset-size-on-Deep-Learning-model-skill-and-performance-estimates/【2021 年 12 月 12 日访问】。

Buolamwini,j .和 Gebru,T. (2018 年)《机器学习研究会议录》81:1–15。

*2018 公*、问责和透明性别阴影会议:商业性别分类的交叉准确性差异。*纽约,2 月 23 日至 24 日,1 日至 15 日。

Doshi,S. (2019)训练神经网络的各种优化算法。正确的优化算法可以成倍地减少训练时间。可在线获得:https://towards data science . com/optimizer-for-training-neural-network-59450d 71 caf 6【访问日期:2021 年 12 月 12 日】。

Dabbura,I. (2017)梯度下降算法及其变体。可在线查阅:https://towards data science . com/gradient-descent-algorithm-and-its-variants-10f 65280 6a 3[访问时间:2021 年 12 月 14 日]。

《监督学习中的机会均等》。*第 30 届神经信息处理系统会议,*巴塞罗纳,12 月 5 日至 11 日,3315 年至 3323 年。

图片(无日期)。可在:【https://pixabay.com/ (2021 年 12 月 13 日进入)。

kilbertus,m . Rojas-carulla,g . parascandolo,Hardt,m . janzing,D & Sch ̈olkopf,B. (2017 年)通过因果推理避免歧视。第 31 届神经信息处理系统会议,加利福尼亚州,2017 年 8 月 6 日,656–666。

Nguyen,H & Evangelos,T. (2021)数据挖掘中过拟合和过泛化对分类准确性的影响。路易斯安那州立大学博士论文。

Obermeyer,z .,Powers,b .,Vogeli,C & Mullainathan,S. (2019)剖析用于管理人口健康的算法中的种族偏见。理科,366 (6464),447–453。

Pazzanese,C. (2020)随着人工智能在更多行业中发挥更大的决策作用,伦理问题越来越多。网上有:https://news . Harvard . edu/gazette/story/2020/10/ethical-concerns-mount-as-ai-take-bigger-decision-making-role/【2021 年 11 月 24 日访问】。

佩雷拉,G. (2021)走向拒绝作为一个关键的技术实践:与霸权计算机视觉作斗争。安普哈 10(1),2245–7755。

Pratik,j .,Sebastin,s .,Amar,b .,Kalika,B& mono JIT c .(2020)NLP 世界中语言多样性和包容性的状况和命运。计算语言学协会第 58 届年会。在线,6282–6293。

Rohith,G. (2018)提高神经网络的性能。网上有:https://www . kdnugges . com/2018/05/improving-performance-neural-network . html【2021 年 13 月 12 日访问】。

人工智能能帮助我们对抗假新闻吗?

原文:https://towardsdatascience.com/can-artificial-intelligence-help-us-fight-fake-news-fa33c6109eb4?source=collection_archive---------21-----------------------

加剧假新闻影响的算法是否也可以用来对抗假新闻,并大规模培养批判性思维?

科林·伯伦斯来自的图片

假新闻和虚假信息现在被广泛认为是煽动对世界各国政府、个人和社区不信任的武器。我们每天都被新闻报道、图片、视频、迷因、WhatsApp 转发、电子邮件等虚假信息淹没。为推进议程而歪曲事实本身并不是一个新问题;政客和广告商对此相当熟悉。社交媒体的爆炸式增长与人工智能的新兴力量相结合,给这个问题增加了新的维度,并极大地放大了它。

人工智能在生成惊人的类似人类的内容方面逐年进步。像 GPT-3 这样的语言模型只需要输入一行提示就可以独立完成整篇文章。深度神经网络经常被用来创建被称为 deepfakes 的虚假图像或视频。篡改视频曾经是一个繁琐而昂贵的过程,需要大量的专业技术。开源软件如 FaceSwap 和 DeepFaceLab 使这项技术变得更容易使用。今天,任何专业知识有限的人都可以使用电脑或手机轻松制作 deepfakes。

互联网已经成为数十亿人消费信息的最重要渠道。我们在网上的所见所闻塑造了我们的观点和世界观。获取信息对民主至关重要。通过不断地篡改真相,假新闻正在千刀万剐地伤害民主。

虽然假新闻的传播得到了几个既得利益者的资助、帮助和教唆,并受到人类行为的进一步推动,但帮助制造假新闻的技术也可以用来打击假新闻。加剧假新闻影响的算法是否也可以用来对抗假新闻,并大规模培养批判性思维?

本文探讨了各种技术解决方案,以首先识别并阻止假新闻的传播。

检测假新闻

可以用 AI 识别假新闻吗?为此,我们必须首先回答一个非常微妙的问题:什么是真理?研究人员和公司没有正面解决这个问题,而是试图回答更简单的问题。

例如,AI 可以确定一段内容是由计算机还是人类创建的吗?是的,它可以——达到一定的精确度。分析语言线索的技术,如单词模式、句法结构、可读性特征等。可以区分人类和计算机生成的文本。类似的基于特征的方法也可以用于从真实照片中分离合成图像。

然而,最*生成对抗网络的成功表明,算法将很快能够很好地模仿人类,以至于它们产生的内容将与我们创造的内容难以区分。

生成对抗网络是由两个互补部分组成的深度神经网络。一个生成器算法将一组真实样本——文本或图像——作为输入,并试图复制这些模式来创建合成样本。另一方面,鉴别器算法学习区分真实样本和合成样本。生成器和鉴别器竞相智取,在这个过程中,两者都在不断改进。这个过程以一个生成器结束,该生成器可以生成无法与真实样品区分开来的合成样品。

OpenAI 最*推出的 GPT-3 可以写文章、故事、电子邮件、诗歌、商业备忘录、技术手册等。它可以回答哲学问题,简化法律文件,并在语言之间进行翻译。对于短小的文本,几乎不可能将 GPT-3 的输出与人类书写的文本分开。

检测假新闻的第二种方法包括确定文章中提到的事实的真实性,不管是人还是计算机写的。Snopes、Politifact、FactCheck 等服务。雇佣人类编辑进行研究并联系第一手资料来核实一个声明或一张图片。这些服务也越来越依赖人工智能来帮助他们翻找大量数据。

我们写事实的方式不同于我们写谎言的方式。研究人员正利用这一点,通过使用 14 年来撰写的愚人节恶作剧新闻文章的语料库训练人工智能模型,来教机器区分真实和虚构。

另一种验证方法是给每个新闻网站分配一个信誉分数。只有当具有高信誉分数的网站认可一个陈述时,该陈述才被认为是经过验证的。例如,信托项目使用诸如道德标准、来源和方法、矫正政策等参数。评估新闻渠道的可信度。

除了标记潜在的虚假故事,社交网络也开始对屡犯者采取惩罚措施。这些行动包括压制甚至封杀散布假新闻或仇恨言论的账户。这方面的一个例子是脸书推出的“群体质量”功能。如果社交网络也显示新闻来源的信任指数和被识别为虚假的危险信号故事,这将有所帮助。

遏制假新闻的传播

除了有助于假新闻的产生,技术在假新闻的传播中也起着至关重要的作用。由于其耸人听闻的性质,假新闻在社交媒体上的传播速度远远快于真实新闻。麻省理工学院的研究人员在《科学》杂志上发表的一项详细研究显示,真实消息到达 Twitter 上 1500 人的*均时间是虚假消息的六倍。当他们查看转发链时,他们发现真实新闻的链长从未超过 10,但虚假新闻的链长达到了 19——这比真实新闻达到 10 次转发的时间快了* 10 倍。

为什么虚假故事比真实故事在社交网络中传播得更快更深入?许多人本能地指责机器人,在我们的脑海中浮现出恶意黑客雇佣大量机器人来传播虚假故事的画面。

机器人是由程序自动运行的社交网络上的用户帐户。在过去的几年里,技术公司已经开发了复杂的机制来检测 bot 帐户。他们监控网络,以发现并阻止沉迷于恶意行为的账户,如利用自动化来中断或扩大对话;产生虚假的赞、分享或其他形式的参与;参与群发、垃圾邮件或攻击性帖子;瞄准,玷污或垃圾邮件其他用户等。像 Twitter 这样的网站每天都会删除大量的恶意机器人账户,这是由技术辅助的。此外,像僵尸工具这样的机器学习应用程序使用成千上万的特征,如用户的个人资料细节、联系、活动模式、语言和情感,来预测一个账户是机器人的可能性。

但是机器人是传播假新闻的唯一责任吗?似乎不是这样。机器人确实放大了新闻的传播,但它们同样放大了真假新闻。在上面提到的同一项研究中,研究人员通过从他们的数据中包含和排除机器人账户来重复他们的实验。在这两种情况下,他们得出了相同的结论,表明虚假新闻传播得更快,因为人类——而不是机器人——更有可能分享它。

私人信息*台

与社交媒体网络不同,消息*台有更严格的隐私政策。比如 Whatsapp 支持端到端加密。这些信息只能被预期的接收者解密和阅读,甚至 Whatsapp 的开发者也不能。即使政府当局意识到 Whatsapp 上流传着一个虚假的故事,他们也无法阻止它。

Whatsapp 过去曾试图通过推出限制转发数量、限制群组规模等措施来缓解这一问题。这非但没有帮助,反而鼓励用户转向 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 和 Signal 等没有实施这些限制的其他消息*台。

由于这些*台的性质,监控这种通信以打击假新闻变得几乎不可能。

需要齐心协力

虽然与假新闻有关的高调事件占据了人们的注意力,但更大的问题是虚假信息的普遍存在。印度正在见证高情感低事实的新闻故事的迅速崛起。这模糊了耸人听闻的报道和彻头彻尾的假新闻之间的界限。

支持假新闻的机制是复杂的,涉及利益不同的多个行为者。

个人出于恶作剧,为了推进政治议程或经济利益而制造假新闻。耸人听闻的内容充当点击诱饵,可以在 YouTube 等*台上货币化。

当故事像病毒一样传播时,科技公司就能获得广告收入。因为他们要对股东和广告商负责,他们不愿意压制任何内容——不管是假的还是真的。

像大多数其他国家一样,印度缺乏专门处理网络虚假信息的监管框架。我们需要法律来惩罚恶意传播虚假言论,同时不影响公民言论自由的宪法权利——这是一个具有挑战性的法律问题。

应该让公民意识到未经证实的消息对他们自己的未来是有害的。印度的一些学校开始向中学生灌输核实事实的习惯。学生们被教授批判性思维和验证他们所见所闻的方法。

人性和科技对假新闻问题负有同等责任。要解决这个问题,我们需要改变人类行为,以适应我们作为大信息消费者的新角色。我们需要认识到可信度和真实性的重要性,并学会珍惜它们。这不会在一夜之间发生——这是一个逐渐的觉醒,我们希望有一天会到来。在此之前,技术可以减轻这种影响,并成为这种变化的催化剂。

Viraj Kulkarni 拥有加州大学伯克利分校的计算机科学硕士学位,目前正在攻读量子计算和人工智能的博士学位。Sahil Deo 是 CPC Analytics 的联合创始人,CPC Analytics 是一家数据驱动的政策咨询公司,在浦那和柏林设有办事处。Sanjana Krishnan 是 CPC Analytics 的合伙人。

贝叶斯统计能给出和 ML 一样质量的预测吗?

原文:https://towardsdatascience.com/can-bayesian-statistics-give-predictions-of-the-same-quality-as-ml-bc0f9c886819?source=collection_archive---------14-----------------------

在某些情况下是的。这就是方法。

巴勃罗·加西亚·萨尔达尼亚在 Unsplash 上拍摄的照片

最大似然算法是当今解决预测问题的主要方法。这种算法可能易于使用,并且通常提供更准确的预测。另一方面,统计方法提供了关于过程的更多信息,另外,由于算法更加透明,结果对最终用户来说似乎更加可靠。但是精度上的差距是不是太大了?

介绍

任务如下:给我们一个数据集,代表 400 家商店。对于每个商店,都有其 3 年的收入,以及一组反映内部因素的特征,如商店的外观、可达性等。以及外部因素,如行人流量、该地区的房地产价格等。目标是根据商店的特征预测商店的日收入。

在一次头脑风暴会议期间,我们的团队决定开发两种方法:基于 ML 树的方法和使用贝叶斯统计并比较结果的方法。

统计方法包括 3 个步骤:

  1. 线性回归并通过将收入除以相关特征来构成新的目标。
  2. 从与新目标不相关的特征中,我们根据它们提供的信息增益挑选出最有用的特征。
  3. 基于所选特征的值,用贝叶斯分析对新目标进行预测。以及使用先前计算的线性回归系数来计算收入预测。

现在,让我们更深入。

1.线性回归

首先,我们需要找出哪些特征与目标相关,从而适合线性回归。不出所料,他们人数很少。基本上,我最后只得到一个——商店的工作时间,但它的相关系数为 0.7。

我认为这里可能会出现一个正反馈循环:不仅商店营业时间越长,产生的收入越多,而且管理层也倾向于减少不太成功的商店的工作时间,以削减开支。所以工作时间短可能说明店铺业绩不好。

无论如何,在计算线性回归系数后,我可以通过将收入除以工作时间来生成一个新的目标。实际上,我最终得到的是商店的每小时收入,这反映了它的核心业绩。这个目标似乎与任何特征都没有很强的相关性,

在进入下一步之前,我们要做的一切就是从数据集中删除所有相关的要素,只留下独立的要素。

2.复杂依赖关系,差分熵

现在是最有趣的部分。我们有一组独立的特征,它们既不与目标相关也不彼此相关。

如果特征与目标不相关,并不一定意味着它没有给出关于它的信息。让我用下面的例子来说明:

让我们生成一个数据集:

这是它看起来的样子

这个特征告诉我们很多关于目标的信息,但并不与目标相关(图片由作者提供)

这里的相关指数是-0.18,这意味着基本上没有依赖性,但很明显,该特征具有很高的信息量。

有一种度量随机变量不确定性的方法叫做熵。对于连续变量,它可以计算为:

其中ρ(x) —概率密度函数

为了挑选最有信息的特征,我们可以简单地根据它们提供的信息增益对它们进行分类

其中
y-要素
nᵢ-数据集中具有要素 Y = yᵢ值的条目数

基本上,信息增益是数据集的初始熵和由特征值选取的子集的熵的加权*均值之间的差。

在这一点上,可能不清楚为什么不使用标准差?事实上,在上面的图片中,每个子集的标准偏差比整个数据集的标准偏差小 5 倍,这也同样有效。

但是让我们考虑下面的例子:

信息越丰富的要素标准偏差越大(图片由作者提供)

在上图中你可以看到两个分布,一个是宽高斯分布,另一个是两个窄峰。第一个分布的标准差是 0.5,而另一个分布的标准差是 3。但是让我们计算熵,我们得到 1.04 和-0.27(是的,熵可以是负的)。第二个分布提供了更多关于变量的信息,尽管有更大的标准差。

3.贝叶斯分析介绍,部分分布→可能性

现在让我们试着做一些预测。首先,快速提醒一下贝叶斯推理是如何工作的。主要的想法是你用基于你的观察的可能性因子来更新你先前的信念。

可能性是假设你先前的信念,观察给定证据的概率。现在,用概率分布来改写它:

α—归一化常数

为了获得观察到具有特定收入的商店的特定特征的概率,我们需要计算在显示该收入的所有商店中拥有该特征的商店的分数。

为了让这个技巧发挥作用,我们需要把一个连续的特征变成一个分类的特征。我用 pd.qcut()把所有的连续特征分类成 8 个八分位数。常规线性宁滨似乎不适用于此目的,因为大多数要素的分布并不均匀。这意味着,虽然 2-3 个箱将包含几乎所有的商店,但其他箱将包含很少的商店,并且很难评估此类箱的部分收入分布。

作为先验分布,使用数据集中收入的总体分布是合理的。

现在,我们要做的就是用所有特征的似然因子更新先验分布,并计算结果的*均值。当然,在计算部分分布之前,有必要将商店本身从数据集中排除。

贝叶斯推理后得到的收益分布(图片由作者提供)

为了获得对初始目标的预测,我们需要将从步骤 1 中获得的预测乘以车间的工作时间。

预测和结果分析

在下图中,你可以看到预测与事实的散点图。为保密起见,预测和实际收入均以常规单位表示。

作者图片

实现了以下性能指标:

MAPE — 23.1
MdAPE — 20.0

出现错误的店铺数量:
错误< 10% — 14
错误< 20% — 29
错误< 30% — 43
错误> 50% — 5

同时,基于树的 ML 模型已经在具有以下性能指标的相同数据集上被训练:

MAPE — 22.5
MdAPE — 19.2

误差店铺数:
误差< 10% — 17
误差< 20% — 30
误差< 30% — 43
误差> 50% — 5

从误差分布可以看出,ML 在小误差领域表现更好。ML 模型预测了 17 家商店的收入,误差小于 10%,而 Bayesian 只对 14 家商店达到了这一分数。不管怎么说,ML 只比 MAPE 好 0.6,比 MdAPE 好 0.8。

总的来说,ML 模型提供了更好的准确性。但是该实验表明,对于 0.6 MAPE 的价格,人们可以获得概率分布以及获得该结果的更透明的算法,这在某些情况下对于最终用户是至关重要的。

感谢阅读!

https://vityazevdanil.medium.com/

大数据可以讲述人类的故事吗?

原文:https://towardsdatascience.com/can-big-data-tell-human-stories-40f87bc6d5e2?source=collection_archive---------33-----------------------

在数据科学的背景下,美丽似乎是一个奇怪的概念——图表可能清晰且易于理解,数据库可能干净且维护良好,但它们能变得美丽— 甚至动人吗?

Kie Ichikawa 最*的帖子让我们好奇用大数据讲述强大人类故事的各种新可能性。Kie 利用了日本几个世纪的樱花数据,表明围绕我们塑造和呈现数据的方式,以及我们如何利用它的力量将客观事实与个人和社会经历联系起来,还有很多值得探索的地方。看完你不会后悔。

马库斯·斯皮斯克在 Unsplash 上拍摄的照片

如果不美观,一个健壮的、性能良好的机器学习模型至少有某种优雅。在过去的一周里,两个帖子在他们创建和维护长期交付的模型的方法上引起了我们的注意。 Aparna Dhinakaran 写了一篇被广泛阅读的关于数据质量控制的帖子,以及即使(如果不是特别)一旦模型投入生产,维护模型的重要性。与此同时,韦丹特·贝迪探索了经济计量模型和模型稳定性的概念——衡量其即使面对不断变化的输入也能做出正确预测的能力。

从数据集和模型维护的本质上退一步,崇高的概念和它们在我们自己的日常现实中的表现方式之间的紧张关系一直是几次生动对话的焦点。在人工智能方面,技术进步产生了对隐私、偏见和歧视的担忧(仅举几个例子)。博士研究员 Matthew Stewart 同意这些担心在很大程度上是合理的,但他希望我们能通过新兴的人工智能研究领域超越这些担心,为社会造福。花时间和他一起深入了解当前利用人工智能解决生物多样性、气候变化和物质滥用等问题的工作。

最后,从出色完成的工作中可以获得大量的快乐——职业上的、智力上的——当我们知道自己已经尽了最大努力,并且做出的工作给别人留下了积极的印象时,我们会有一种成就感。在求职的背景下,赵明杰解释了你应该如何谈论你过去的项目,这样不管你的听众是什么技术背景,你的贡献都是清晰而有意义的。即使您已经开始了您的数据科学之旅,也总会有改进的方法(并使您的生活变得更加轻松)——要获得灵感,请查看我们对最*关注简化和加速您的工作流的热门帖子的综述。

为又一周的良好学习和生动对话干杯——感谢你加入我们的行列,感谢你对我们工作的支持。

直到下一个变量,
TDS 编辑器

我们策划主题的最新内容:

入门

  • 在 Plotly Dash 上构建自己的谷歌翻译应用作者 Vanessa Wong
  • 由拉胡拉·辛格撰写的关于自然语言处理(NLP)的详细新手介绍
  • 这些错误很容易毁掉你的数据科学面试

实践教程

  • 看看贝叶斯键盘内部作者丹尼尔·布切克
  • 数据科学家的 Python 高效编码指南作者Varshita Sher 博士
  • 人工智能说书人的制作作者 Kenil Cheng

深潜

  • 如何应对需求预测引擎的功能挑战作者 Debayan Bose
  • 规范化流的变分贝叶斯推理:一个简单的例子
  • 5 种方法使组织病理学图像模型对域转移更加稳健作者希瑟·库特尔

思想与理论

  • 偏差-方差误差的简单数学推导
  • 野外潜泳:谷歌、英特尔、苹果和 IBM 的监管不力欧内斯特·陈著
  • Idil Ismiguzel的集成学习实用指南

写关于数据科学的博客真的能让你被聘为数据科学家吗?

原文:https://towardsdatascience.com/can-blogging-about-data-science-really-get-you-hired-as-a-data-scientist-7f02fec085ec?source=collection_archive---------12-----------------------

剧透警告——是的,但是有一个问题。下面是我 2.5 年后的经历。

卢卡·奥尼博尼在 Unsplash 上的照片

数据科学职位从未有过如此多的职位空缺,但是,成为一名数据科学家却从未如此困难。

为什么?答案很简单——较小的公司通常不需要整个数据科学部门,所以他们最终会雇佣几个资深员工。这对你来说太糟了。另一方面,在地狱结冰之前,没有经验的你可能不会被大公司雇用。

你可以做一些事情来增加你的机会,甚至完全停止寻找数据科学的工作。见鬼,在过去的 2.5 年里,那个叫的东西给我带来了几十份工作。最棒的是——同样的事情也会发生在你身上。那个东西正在开一个数据科学博客。

不想看书?改看我的视频?

作为一名数据科学家,你为什么应该开一个博客

我可以就此谈论几个小时,但推理归结为三点。我相信你知道所有这些,所以把这部分当作一个可选的回顾。

这是最快的学习方法

那么,你已经了解了 PCA 是如何工作的。你能向一个 10 岁的孩子解释吗?你能抛弃花哨的特征值和矩阵术语而不丢失核心思想吗?如果是这样,你就真正理解了这个主题。如果没有,回到绘图板。

一开始,写复杂的主题,因此,不用大词来教授它们是一项具有挑战性的任务。毕竟,他们中的许多人在这里只是为了让写这本书的人听起来更聪明。事实上,不必要的过度复杂化会让你听起来像个傻瓜。使用小的,容易消化的单词。你的读者会喜欢它的,因为他们中的大多数人没有持有定量领域的高级学位。

用简单易懂的语言写复杂的话题也会让你的理解水*飙升。

这是一种建立声誉的神奇方式

我永远也不想成为一名负责筛选数百名求职者的 IT 招聘人员。这是一个可怕的地方。更糟糕的是,从背景噪音中分离出好的匹配的时间窗口有限。

这是一条经验法则——如果你不突出,你就会被过滤掉。

在你的简历中链接到你的数据科学博客可以让世界变得不同。大多数申请者都没有个人数据科学博客,所以这可能是你的黄金入场券。

它显示了你的思维过程

将复杂的话题浓缩成 5 分钟的文章是一项巨大的成就。好处不止于此。你的文章还展示了你的思维过程,这向潜在雇主表明了你如何思考和应对现代数据科学家的挑战。

这表明你已经花了时间去完全理解这个话题,而且你没有匆忙地从一件事跳到另一件事。这听起来不多,但在当今这个注意力持续时间很短的世界里,能够专注于一件事是很难得的。

我写了大约 2.5 年关于数据科学的博客后的结果

当我开始写数据科学博客时,我是全职工作。我仍然在做同样的工作,直到年底。最终,我决定辞职,因为写关于数据科学的博客比做数据科学家多赚 2 到 3 倍的钱。这也大大减少了我的工作时间。

关于数据科学的博客带来了两大类数十份工作机会——数据科学和技术写作。两者都不错,但不同类别的报价差别很大。接下来我会尽力解释这两个问题。

数据科学博客➡️数据科学招聘

仅仅根据我的数据科学博客,我就获得了 4-5 份全职数据科学职位的工作机会。但是残酷的现实是——这些都是在我把最初的努力投入到博客中之后才发生的。开一个数据科学博客是一回事,但保持一致是另一回事。我花了大约 1.5 年才得到第一份工作。

我认为这很公*——如果你不认真对待你和你的小博客,没人会认真对待。没有比坚持下去却看不到任何结果更好的方式来表明你是认真的了。

我收到的一些工作邀请完全遥不可及,但我决定放弃所有的邀请。毕竟,这只是用一份全职工作换来另一份,如果你对现在的工作感到满意,这就没有意义了。此外,他们中的大多数都是在我不太关心的工作领域,比如公司财务。我宁愿自焚。

数据科学博客➡️技术作家工作机会

我收到了几十份技术写作职位的邀请,有的是自由职业者,有的是兼职,有的是全职。我比第一份数据科学工作更早得到了第一份技术写作工作。我不认为我的写作是壮观的,但公司需要有人写关于他们的产品或服务的内容。如果他们有自己的博客,如果这个产品给我留下了一些惊喜,我通常会同意。

出于多种原因,我更喜欢这些优惠。这份工作简单多了,没有什么繁文缛节(如果有的话),完全是远程的,而且我可以自己设定工作时间。这是一个双赢的局面,因为一家公司获得了他们想要的曝光率,而我可以在山里骑自行车写作。

因为我已经在网上建立了一定的声誉,我可以为我的写作服务收取额外费用。通常,我在 2-3 个工作日内就能拿到我国家的*均工资。你也可以这样做。

请记住——找到高质量的客户很难,而找到持续为你工作的客户更具挑战性。我有一对夫妇每周需要一篇文章,但这些占收到的要约的 5%左右。大多数客户都是有毒的,他们希望通过收取额外费用的劣质服务在谷歌上排名第一。好好照顾前 5%的人,他们也会为你做同样的事情。

带回家的点数

所以,你决定尝试一下数据科学博客。这是个好消息!这里有几件事你应该记住:

  • 你必须先建立一个声誉,不要指望在博客上呆上一个月就能得到任何邀请。至少需要一年时间。数据科学是如此广泛,你不可能没有主题思想。
  • 根据你的博客,你可以被聘为数据科学家——但实际上,你会收到更多的技术写作邀请,至少根据我的经验。
  • 你应该为你的服务收取额外费用 —作为副业提供数据科学服务意味着你直接与客户合作。没有像你朝九晚五的工作那样的中间人,这通常需要你价值的 80-90%。学会利用它。
  • 你可以全职工作——总有一天你必须做出选择——继续做全职工作并享受福利,或者自己当老板,挣比你想象中更多的钱,同时减少工作时间。这取决于你。
  • 你必须考虑全职 it 面临的挑战 —从数据科学家转型为数据科学内容创作者比看起来更具挑战性。我们大多数科技专业人士都不太擅长用词,尤其是如果我们的母语不是英语的话。

*这里有人在经营一个有点成功的技术博客吗?*请在下面的评论区分享你的经历。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

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

保持联系

  • 注册我的简讯
  • 在 YouTube上订阅
  • 在 LinkedIn 上连接

消费者的评分可以认为是等距的吗?

原文:https://towardsdatascience.com/can-consumers-ratings-be-considered-equidistant-457f90155661?source=collection_archive---------35-----------------------

行业笔记

从亚马逊数据的对应分析中寻找答案

图片由图米苏在 Pixabay 上提供

量化一个观点意味着将一个无限连续的心理概念投射到一个测量尺度上。尽管潜在的观点在心理测量术语中可能具有连续性,测量要求限制了它的显式表达。这些要求因收集数据所采用的方法而异,每种方法都有机器学习模型应该面对的陷阱。

通常,像电子商店这样的在线*台通过使用评级量表来调查意见。分析评级数据的一个常见问题是将每个定性判断与一个数值联系起来。由于不清楚评级是否等距,数字分配可能会导致复杂的任务。在本文中,我尝试将心理测量学中的一些概念引入到评分数据的分析中,测试对应分析的有效性,以探索反应量表各步骤之间的距离。

通过评级衡量意见

在心理测量学中,李克特方法是一种广泛收集观点、态度和行为的方法。李克特方法强迫把一个“连续的”观点投射到一个由有限的有序选项集合构成的离散尺度上。这种预测将潜在的连续体分解为区间,而这些区间的大小可以根据回答者对反应量表的步骤的理解而变化。

李克特的方法只是用来量化观点和态度的众多方法之一,它是一个很好的提示来探索我们可以控制来调整观点投射过程的评级尺度的特征。

  • **长度。**我们可能认为,与少数选项相比,许多响应选项允许捕捉更精细的措施。这可以是真的,但不一定。太多的选项会产生混乱,不同的响应者可能会有不同的解释。因此,该指标应该足够宽泛,允许消费者表达自己的意见,但仅限于绝对必要的情况。
  • **居中。**奇数步或偶数步会有所不同。中间类别可以用作“避难所”来提供不极化的响应。然而,中心类别可能会被一个极性同化,使天*失衡。
  • **贴标。**评定等级的每一步可能有也可能没有标记。标签向应答者暗示每个评估代表什么,有助于在不同的人之间统一量表的使用。有时,心理测量量表只对极端类别(“锚”)使用标签。

李克特方法中固有的一个古老问题是将定性意见转换成定量值,因为标度的原点是任意的,并且因为标度的步长并不总是被认为是等距的。我们在分析星级时发现了同样的问题。

星级

我们非常熟悉使用星级来评估产品。通常,星级由五个选项组成,因此它们有一个中心类别。星星没有标签;然而,每个人都不清楚每一步应该代表什么。明星把答案集中在几个选项上,避免混淆;此外,它们的数量足以区分不同层次的意见。

星级评定在全球范围内被广泛用于收集消费者对产品和体验的意见。然而,有一些限制要考虑。

  • 一个相关的担忧是关于在线评论的自我选择偏差。只有受限制的一部分消费者来表达一种观点,而这种对样本的自我选择并不是随机的,而可能恰恰取决于判断。因此,在反常的角色互换中,意见既可以是措施的目标,也可以是措施的原因。一个有趣的结果是 漏报偏差 :极端的经历(无论是正面的还是负面的)比一般的经历更有可能被报道;因此,她们的人数过多。
  • 另一个有趣的现象是由于审查制度的 顺序性 导致的意见扭曲。由于在线考核是按顺序报告的,而不是并行报告的,因此每位评核人都会看到以前的考核。这种阐述可能会创建一个依赖于数据的结构。
  • 作为一名具有心理测量学背景的数据科学家,另一个问题让我着迷:评级之间的等距假设的失败。我们说过,在评级尺度上投射一个连续的观点会将潜在的连续体分解成多个区间。这些间隔可能不相等,这取决于反应等级的特征。因此,台阶之间的距离(“星”)可能不一致。

在下文中,我集中讨论等距问题,这代表了机器学习和心理测量评估之间共有的技术问题。

评定等级的步骤可以被认为是等距的吗?

我不认为这个问题有一个明确的答案。然而,在分析数据集之前至少获得一个想法可能有助于设置有效的算法。老实说,这个问题超出了机器学习,因为评级之间的等距是许多汇总指标的基本假设。

一些作者(见参考书目)试图用一种有趣的方法提供一个答案:对应分析。尽管这种方法并不新鲜,但似乎并不广为人知。接下来,我得到了一个网店评论的数据集,并测试了这个方法。

亚马逊乐器评论

与许多其他电子商店一样,亚马逊要求顾客使用五星评级来评价产品。我分析了这个由 Kaggle 提供的数据集,它包含了 900 种乐器的 2440 条评论(数据是在 CC0 许可下公开发布的)。

https://www.kaggle.com/eswarchandt/amazon-music-reviews

我用来导入数据和获得初步计数的 R 代码如下所示。

下面的柱状图恢复了意见,绘制了评定等级中每一级的观察频率。总体而言,数据严重偏向于正面判断。

我重新整理了数据,将产品按行排列,将评分按列排列,在每个单元格中报告评论的数量。换句话说,我建立了一个应急矩阵。

然后,我应用了对应分析。

对应分析

对应分析(CA)是一种数据压缩技术,用于处理列联表。CA 可以应用于通过两个标称或顺序变量获得的频率数据。该分析的工作方式类似于主成分分析(PCA),并且,从某种角度来看,CA 就像非度量数据的 PCA。

远不是在这里提出一个关于 CA 的手册,你需要知道 CA 在几个维度上减少数据,解释观察到的方差的更大可能比例。CA 提取的分量和 min ( r-1c-1 )一样多,其中 r 是列联表的行数, c 是列数。像 PCA 一样,当只有两个组件可以用来表示数据时,多亏了二维图,我们可以可视化行和列类别。

将 CA 应用于像亚马逊乐器那样的权变矩阵,我们应该找到两个组件:

  • 第一个代表判断的极性(从负到正);
  • 第二个代表判断的强度(从低到高)。

我们可以构建一个二维映射,将第一个组件的主列坐标放在横轴上,将第二个组件的主列坐标放在纵轴上。如果步骤是等距离的,那么我们应该找到一个对称的 U 形。下图显示了这种理论模式。

图片由作者提供—在 CC0 许可下发布

结果

不幸的是,前两个因素解释了相对较低的方差百分比(不到 60%,见下表)。最后的组件仍然解释了太多的差异,没有任何断点(著名的肘形)。因此,CA 提供的数据压缩并不像希望的那样有效。

dim | eigenvalue | % explain | cumulated %
  1 |   0.149205 |      33.5 |        33.5
  2 |   0.110787 |      24.9 |        58.4
  3 |   0.095135 |      21.4 |        79.8
  4 |   0.090116 |      20.2 |         100

无论如何,下面的图显示了使用前两个组件的坐标创建的地图。正如预期的那样,数据画出了一个*似 U 形的曲线,但这个曲线远非对称。

关于极性(x 轴),与评级之间的其他步骤相比,该图显示一颗星和两颗星之间的差异非常小。标度的两个最低点在极性上看起来非常相似,但它们在兴趣强度(y 轴)上有所不同。

三颗和四颗星在极性上被正确分类,但在强度上完全重叠;其实它们好像是一个四分音阶的两个中枢!

考虑到上面提到的前两个维度,计算了评级之间的欧几里德距离。应用了重新缩放程序,将每个距离 d 乘以(k-1)/sum(d),其中 k 是步数(因此, k -1 是可用距离数)。

1->2   2->3   3->4   4->5
1.44   1.18   0.64   0.74

如果最高等级(3、4 和 5)之间的距离大致相似,则 1、2 和 3 之间的距离显示出一些重要的差异,尤其是在等级的最低部分。

我们能得出什么结论?

结果表明,消费者对回应量表的态度可能与我们的预期不同。CA 显示了低评级和高评级之间的不对称性。特别是,一星评级代表了一种非常极端的判断,五星的对立面似乎是二星而不是一星。显然,结果可能依赖于产品,不能被认为是决定性的。

CA 远不能提供通用的答案,它可以代表一种探索评级的有趣方法。该技术有助于研究标度步骤之间的距离,例如,选择回归或分类方法。

最后,我们可以做些什么来提高数据质量?

一般来说,非线性评级不是一种测量工具的“缺陷”,而是一种“特征”。前一句话可能看起来像是机会主义,但却是事实:尽管这个体系可能不完美,但它可能是好的。

为了改进评定等级,我们可以研究前面描述的三个主要属性,即长度、中心和标签。当然,长度是一个非常关键的属性,可以很容易地操作。一个有趣的方法是引入部分星星

图片由作者提供—在 CC0 许可下发布

部分星级的优势在于没有扩大范围,因为每个评级都固定在一个参考支点上。此外,他们让回答者明白,每个部分的评价只是一个“父亲”判断的色调。通过这种方式,你可以提供更多的选择,而不会让回答者感到困惑,限制了评分者之间获得不同量表用法的风险。

基本书目

  • d bkowska k .(2014 年)。应用对应分析确定波德拉斯基地区电子服务部门企业经济状况的决定因素。经济与管理 I zarządzanie6 (1),38–56。[ 链接
  • 达比希尔 p .麦克唐纳 H. (2004 年)。选择反应量表标签和长度:研究人员和客户指南。澳大拉西亚市场研究杂志 I12 (2),17–26。[ 链接
  • 肯尼迪、里基耶、夏普(1996 年)。对应分析在市场研究中对分类数据的实际应用。营销目标测量与分析杂志5 (1),56–70。[ 链接
  • 绿色体育,塔尔 D.S .,阿尔巴姆 G. (1988 年)。营销决策研究(第 5 版)。普伦蒂斯-霍尔国际版:新泽西。

数据湖能加速构建 ML 数据管道吗?

原文:https://towardsdatascience.com/can-data-lakes-accelerate-building-ml-data-pipelines-86d63934ec3f?source=collection_archive---------20-----------------------

通过数据湖和数据仓库研究数据科学的洞察时间

照片由 Emil Jarfelt 在 Unsplash | 品牌内容披露上拍摄

数据工程中的一个常见挑战是将传统的数据仓库和 BI 报告与实验驱动的机器学习项目相结合。许多数据科学家倾向于更多地使用 Python 和 ML 框架,而不是 SQL。因此,他们的数据需求往往与数据分析师不同。在本文中,我们将探索为什么拥有一个数据湖通常会为数据科学用例提供巨大的帮助。我们将以一个有趣的计算机视觉演示结束,从存储在 S3 数据湖中的图像中提取文本。

1.数据湖是数据不可知的

仅拥有纯关系型数据仓库限制了该数据*台能够支持的多种数据格式。许多数据仓库解决方案允许您分析嵌套的类似 JSON 的结构,但是它仍然是数据湖可以支持的数据格式的一小部分。

虽然对于分析来说,没有什么比关系表结构更好的了,但拥有一个允许您做更多事情的额外*台仍然是有益的。数据湖是数据不可知的。它们支持对数据科学至关重要的大量数据:

  • 不同的文件类型 ( csv、tsv、json、txt、parquet、orc )、数据加密、压缩格式 ( snappy、gzip、zlib、lzo ),
  • 图像、音频、视频文件通过计算机视觉算法实现深度学习用例,
  • 模型检查点由 ML 训练岗位创建,
  • 跨越关系型非关系型数据的连接,两者都是服务器端的( ex。Presto 或 Athena )和客户端( ex。你的 Python 脚本),
  • 来自 web 的数据:点击流、购物车数据、社交媒体( ex。tweets、Reddit、博客帖子和新闻文章抓取自然语言处理分析),
  • 时序数据:物联网和传感器数据、天气数据、金融数据。

2.提高开发效率

将原始数据手动摄取到数据仓库是一个相当繁琐且缓慢的过程。您需要预先定义一个模式并指定所有数据类型,创建一个表,在您的脚本或 ETL 工具中打开一个 JDBC 连接,然后最终您可以开始加载您的数据。相比之下,数据湖中的加载步骤通常就像单个命令一样简单。例如,用一行 Python 代码就可以将一个 Pandas 数据帧接收到一个基于 S3 的数据湖中(Pyspark 和 Dask 中的语法非常类似):

摄入 S3 数据湖——图片由作者提供

如果您主要使用 Python 进行分析和数据工程,您可能会发现使用数据湖比使用数据仓库更容易读写数据。

3.支持更广泛的数据处理工具

我们讨论了数据湖支持的各种数据,但是它们也支持各种处理框架。虽然数据仓库鼓励主要使用 SQL 和 UDF 在内存中处理数据,但数据湖使用编程语言或您选择的*台检索数据变得容易。因为没有强制实施专有格式,所以您有更多的自由。通过这种方式,你可以利用一个 SparkDask 集群的能力,以及在它们之上构建的大量非常有用的库,只需使用 Python 。参见下面的示例,演示如何在 Dask 和 Spark 中读取拼花文件:

注意这不是一个非此即彼的决定,一个好的数据工程师可以同时处理两者( DWH 和数据湖),但是数据湖使那些分布式处理框架更容易使用数据。

4.数据管道中的故障变得更容易修复

修复传统的 ETL 数据管道既困难又耗时,其中只有“加载”部分失败,因为您必须从头开始整个管道。数据湖鼓励并支持 ELT 方法。您可以将提取的数据以原始格式直接加载到数据湖中,然后在同一个或完全独立的数据管道中进行转换。有许多工具可以让您将原始数据同步到数据仓库或数据湖中,并在以后需要时进行转换。从转换中分离原始数据摄取可带来更具弹性的数据工作负载。

演示:使用数据湖提供 ML 即服务

为了说明数据湖对数据科学项目的好处,我们将做一个简单的 AWS Rekognition 服务演示,从图像中提取文本。

我们的用例是什么?我们将图像上传到存储原始数据的 S3中。这触发了从这些图像中提取文本的 Lambda 函数。最后,我们将提取的文本存储到一个 DynamoDB 表中,并使用 SQL 检查结果。

如何在你的架构中使用它?除了 DynamoDB,您还可以使用一个数据仓库表或另一个可以使用 Athena 查询的 S3 存储桶位置。此外,除了使用 AWS Rekognition 的detect_text方法(在下面的代码片段中的第 18 行),您可以将代码修改为:**

  • detect_faces
  • detect_custom_labels
  • recognize_celebrities
  • …以及更多。

如何实现这一点?首先,我们创建了一个 S3 桶和一个 DynamoDB 表。该表配置有img_filename,即上传图像的文件名,作为分区键,这样重新运行我们的函数就不会导致任何重复(等幂)。

为我们的演示创建 DynamoDB 表—图片由作者提供

我们已经有一个名为images的文件夹的 S3 桶:s3://data-lake-bronze/images。

我们还需要创建一个带有 IAM 角色的 Lambda 函数,我们将 IAM 策略附加到这个函数上,用于 S3、Rekognition 和 DynamoDB。下面显示的函数有一个名为lambda_function.lambda_handler的 lambda 处理程序和运行时Python 3.8。它还附带了一个 S3 触发器,该触发器在任何 PUT 对象操作时调用该函数,即在任何文件上传到文件夹images/时。

Lambda 函数用于检测上传到数据湖的图像中的文本—按作者分类的图像

函数的代码:

  • 为 Rekognition 创建一个客户端以及相应的 S3 和 DynamoDB 资源对象,
  • 从事件触发器中提取S3 桶名称关键字 ( 文件名)。
  • 读取图像对象并将其传递给 Rekognition 客户端,
  • 最后,它检索检测到的文本,并将其上传到我们的 DynamoDB 表。

让我们用一些图片来测试一下:

左:来自佩克斯的纳迪林赛的照片,中:来自佩克斯的阿列克萨斯福托斯的照片,右:来自佩克斯的穆达西尔阿里的照片

在将这些图像上传到我们在 Lambda 触发器中定义的 S3 桶之后,Lambda 应该为每个图像上传调用一次。一旦完成,我们可以在 DynamoDB 中检查结果。

DynamoDB (1)中的 PartiQL 查询编辑器—作者图片

DynamoDB (2)中的 PartiQL 查询编辑器—作者图片

看起来前两个图像被很好地识别了,但是右边的困难图像(“这仅仅是幻想吗”)没有被识别。

我们怎样才能做到规模化?

如果你想大规模实现一个类似的用例,那么监控那些资源并实现适当的错误警告可能会变得很有挑战性。在这种情况下,你可能要考虑一个无服务器的可观测性*台,比如 Dashbird 。您可以将所有的 Lambda 函数和相应的 DynamoDB、ECS、Kinesis、Step 函数、SNS、SQS 资源分组到一个项目仪表板中,让您可以一目了然地看到您的微服务和 ML 管道的当前状态。

Dashbird 中所有无服务器资源的项目视图—图片由作者提供

每种颜色代表不同的资源,例如特定的 Lambda 函数。将鼠标悬停在它们上面,可以看到更多细节。然后,您可以深入了解更多信息。

***边注:*上图中的零成本可以通过 AWS Lambda 和 DynamoDB 的始终免费层来证明。在过去的两年里,我一直在我的个人项目中使用 Lambda,到目前为止还没有收到过 Lambda 的账单。

AWS 始终免费层。来源 —作者截图

结论

从题目来回答问题:是的,一个数据湖肯定可以加快数据管道的发展,尤其是那些与数据科学用例相关的。处理各种数据格式的能力以及将这些数据与分布式处理和 ML 框架轻松集成的能力使得数据湖对于大规模进行数据科学研究的团队特别有用。尽管如此,如果使用来自数据湖的原始数据需要太多的清理,数据科学家和数据工程师可能仍然更喜欢使用来自 DWH 的已经预处理和历史化的数据。像往常一样,仔细考虑什么最适合您的用例。

感谢您的阅读!如果这篇文章有用, 关注我 看我下一篇帖子。

参考资料&其他资源:

[1] 我之前的一篇关于数据湖的好处的文章

[2]AWS ML 工具列表(2021 年)——dash bird

[3] 使用 AWS Lambda 的机器学习 — Dashbird

深度强化学习能解决象棋吗?

原文:https://towardsdatascience.com/can-deep-reinforcement-learning-solve-chess-b9f52855cd1e?source=collection_archive---------11-----------------------

实践教程

经典和深度强化学习速成班,用 Python 实现

照片由来自 Pexels 的 Tara Winstead 拍摄

目录:

  • DRL 简介
  • 实现 DRL
  • 分析结果
  • 结论

注意:所有代码都是片段形式,单独执行时无法工作。完整代码可以在我的Github repo上找到。

深度强化学习简介:

作者提供的图片:显示环境的高级定义的流程图

强化学习是对一个 智能体 在一个 环境 中进行决策的训练。代理部署在环境中。在任何给定的帧,代理必须使用来自环境的数据来行动。这个动作会产生一个 奖励 值,它代表了 动作 的质量。然后,代理将相应地更新其流程,以最大化此奖励。

作者图片:Q 表示例

一个基本的强化学习算法是 Q 学习。在 Q 学习中,会创建一个 Q 表。Q 表的行将代表环境的可能状态,而列将是环境中的行动所产生的回报。代理将与环境交互,并在 Q 表中记录奖励值。最终,代理会填写表格。然后,当面对环境时,代理可以选择具有最高奖励值的行动。

尽管该算法在某些情况下确保了完美的策略,但是这些算法的实际应用很少。复杂的环境通常不会对每一步都产生直接的回报,因此在填写 Q 表时会产生问题。

环境中有天文数字般多的状态是很常见的。国际象棋估计有大约 10 个⁰可能的位置。由于一个位置的*均移动次数是 30 次,国际象棋的 Q 表将会太大而无法存储,更不用说完成了。

作者图片

深度强化学习是深度学习在强化学习中的应用。虽然深度学习可以以许多不同的方式应用,但它通常涉及训练深度神经网络,以逼*它尚未看到的状态的 q 值。

然而,需要做出许多假设以允许深度强化算法工作。以反向传播奖励为例。我们知道,导致获胜位置的移动一定有利于最终位置,但我们如何评估它对将死的重要性?我们只能假设越接*胜利位置的移动对胜利有越大的利害关系,所以我们对较早移动的奖励打折扣。

实施深度强化学习:

这个 链接 将把你传送到包含我的实现的完整代码的仓库的子部分。

作者图片

这个图是程序的主要部分之间的可视化表示,主要是环境、模型和目标模型。

环境给模型一个状态向量,模型输出一个动作。模型向模型返回一个动作。更新的 Q 模型然后将更新的 Q 值返回给训练函数,训练函数改变模型的权重。每隔一段时间,来自目标模型的权重被设置为模型权重。

环境:

这是描述模型与之交互的象棋环境的代码的设置。我们已经知道它必须执行的主要功能:

1.返回状态

这个函数简单地返回一个向量,该向量完全表达了代理环境可访问的信息,可以插入到神经网络中。

2.接受行动

这个函数接受一个动作,并通过这个动作改变环境的状态。

3.回报奖励

应该有一个适当的系统,允许代理直接从每个行动中获取奖励。

返回状态:

这个要点展示了将 python-chess board 对象转换成矩阵的函数。它将棋盘转换为行和列,并找到棋盘上的每个方块。

然后,它对所有变量进行一次性编码,使其成为形状为 8,8,12 的数组。该函数与国际象棋环境相关,因此当调用该函数时,类中国际象棋棋盘的变化将会反映出来。

接受行动+回报奖励:

这个要点描述了阶跃函数,它在接受一个动作时推进环境。

虽然播放动作只需要一行代码,但该函数还必须记录所有关于状态的数据和动作的回报,以便对 Deep-Q 算法进行训练。

值得注意的是,我们记录奖励、状态、未来状态以及环境事件是否结束。

更新 Q 值:

事实上,我还编写了函数来更新环境中的 q_values,因为从函数内部访问这些值要容易得多。

作者图片

这是用于评估更新后的-q 值的公式。更新的 q 值等于在状态 s 下执行动作 a 获得的奖励加上未来奖励的最大值,乘以超参数γ。超参数γ可以被认为是未来回报对实施环境的重要性的度量。

型号:

左边的要点描述了 Q_model 类。它包含三个功能,允许它与环境互动。

为 DQN 创建的模型是一个简单的卷积网络,具有 3 个带有 relu 激活功能的卷积层。最后一层包含 4096 个神经元,代表可以在任何给定位置进行的 4096 种可能的移动(64 个用于开始方块,64 个用于结束方块,得到 4096)。

预测函数将棋盘转换为张量,并调用模型来预测输入的输出。它输出总和为 1 的概率分布。我们假设每个值映射到一个移动,较大的概率表示模型的置信度。然后,它应用一个掩码,从分布中删除所有非法移动。然后,通过预定义的字典,该移动被转换为国际象棋移动。

在强化学习中,模型需要探索环境以收集更多的洞察力。探索功能选择随机的合法移动来玩。这允许打破局部最小值的可能性,但是会在开始时减慢训练进度。

执行剧集:

这个 github gist 完全执行算法。它建立在我前面解释过的 q-network 和 chess_env 模块之上。

它还需要一个 variable_settings 文件,其中包含算法的所有超参数,如ε和ε衰减率。它还包括损失函数(Huber 损失)和项目的优化器设置。将文件分开会使配置变得更加容易。

ε用于在勘探和开发之间进行选择。它以变量设置文件中定义的速率衰减。

我没有仅仅使用 model.fit(),而是使用 tensorflow 渐变带特性来更新模型的渐变。

经过一定数量的时期后,目标模型将配置主模型的权重。

结果:

作者图片

从这张截图可以看出,深度强化学习无法正常进行。我最初对结果非常失望和沮丧,并尝试了许多不同的方法来改进算法。

但是,在网上看了别人的证词后,我终于找到了我问题的根源:稳定。

强化学习中的自我游戏是出了名的不稳定,因为模型的回报不是游戏质量的决定性衡量标准。

由于两个模型是相同的,这将导致非常弱的播放,并可能导致模型的播放质量停滞在一个非常低的水*。

深度强化学习能解决象棋吗?

这篇文章提出的问题的答案不是一个明确的否定,而是一个可以用来解决稳定问题的解决方案列表。

1.稳定的对手:

如果我们实现一个稳定的对手,比如 stockfish,我们可能会用我们的算法得到很好的结果!

2.稳定算法:

我们可以使用不同的算法来获得更好的结果,只要我们在新算法中有一些稳定方法。因为我对这个项目的结果非常不满意,所以我从头开始实现了 Google DeepMind 的算法。我将很快发布一篇关于结果的文章。

食物能帮助我们对抗新冠肺炎吗?

原文:https://towardsdatascience.com/can-foods-help-us-fight-covid-19-3331e296158c?source=collection_archive---------38-----------------------

答案可能是肯定的:基于机器学习的技术可以识别具有抗病毒特性的食物中的生物活性分子

由埃斯特迪奥·布鲁姆在 Unsplash 上拍摄的照片

这篇文章基于今年早些时候发表的论文。

新冠肺炎的持续爆发对全球经济、医疗保健、教育、精神健康和整个社会都有破坏性影响。在开发疫苗方面已经付出了巨大的努力。2020 年下半年几个疫苗的批准代表了疫情终结的开始。然而,在疫苗接种工作完成之前,卫生保健系统和个人健康的压力仍然存在。

对于那些受到严重影响的人,有一个明确的治疗过程,包括住院和开出最*批准的或改变用途的抗新冠肺炎药物。然而,由于住院率仅为 3.5% [1],成千上万感染新冠肺炎的人并没有严重到需要住院,但他们发现自己正在努力控制自己的症状,因为除了休息和服用非处方药以缓解流感样症状外,没有明确的行动方案。

然而,在食物中,或者更准确地说,在超级食物中,可能会找到那些独自与新冠肺炎抗争的人的线索。在今年早些时候发表的一篇论文中,我们应用图形机器学习来预测食物中具有抗新冠肺炎特性的分子,基于它们靶向新型冠状病毒-宿主基因-基因(蛋白质-蛋白质)相互作用组的能力。为此,我们首先校准了一种机器学习算法,以预测实验和临床批准药物中的抗新冠肺炎候选药物。

对于那些独自与新冠肺炎抗争的人来说,线索可能在食物中找到,或者更准确地说,在超级食物中。

为了校准机器学习模型,药物-蛋白质和新型冠状病毒-宿主蛋白质相互作用被表示为人类蛋白质-蛋白质相互作用(PPI)网络上的二进制信号,并且应用网络扩散算法来模拟对药物和疾病干预的系统基因组范围的反应。药物化合物和新冠肺炎病的扩散分布图之间的皮尔逊相关系数用于排列靶向新型冠状病毒-宿主相互作用组网络的化合物。

PPI 上的药物-蛋白质和新型冠状病毒-宿主蛋白质相互作用(左)使用扩散算法传播,以模拟对药物和疾病干预的全基因组反应(右)

机器学习算法的参数经过校准,用于预测针对新冠肺炎的实验验证药物,在交叉验证设置中,该模型的准确率达到 80–84.9%。模型校准后,食品中的* 8000 种生物活性分子通过校准的机器学习算法运行,该算法确定了 52 种预测以新型冠状病毒-宿主相互作用网络为目标的生物活性分子。

预测 52 种生物活性分子靶向新型冠状病毒-宿主相互作用网络。

具有抗新冠肺炎特性的食品生物化学“暗物质”的预测

营养机构认识到植物性食物的价值,但是,他们通常专注于跟踪矿物质、维生素和宏量营养素,而忽略了食物中可能具有保护或抗病作用的非营养分子。因此,这些化合物常被视为营养科学的“暗物质”。然而,它们是最重要的分子。

已确定的抗新冠肺炎分子属于多种化学类别,属于这种“暗物质”,包括(异)黄酮类、萜类、酚类和吲哚类。有趣的是,由于它们的苦味,食品工业通常会通过选择性育种或改善味道的过程来去除其中的一些化合物。

图片来源:Laponogov 等人— 链接

超级森林对抗新冠肺炎

当前食物推荐的一个关键限制是专注于食物中的单个植物化学物质,其中某些食物因其特定植物化学物质的高含量而被作为“超级食物”进行营销(例如,葡萄中发现的有效抗氧化剂白藜芦醇)。在这里,我们假设食品的潜在治疗效果取决于战胜疾病的生物活性分子的多样性和可用性。

因此,使用公开可用的食物和食物中生物活性分子的数据库,我们建立了一个食物图,其中每种成分的理论抗新冠肺炎能力根据反映生物利用度和具有抗病毒特性的预测生物活性分子多样性的富集分数进行排名。我们称这些食物为抗病毒超级食物。

图片来源:Laponogov 等人— 链接

排名最靠前的抗病毒超食物包括不同的浆果(黑加仑、蔓越莓和蓝莓)、十字花科蔬菜(卷心菜、西兰花)、苹果、柑橘类水果(甜橙和柠檬)、洋葱、大蒜和豆类。

有趣的是,黑醋栗不仅具有潜在的抗病毒作用,而且对流感具有潜在的消毒和杀菌作用[2]——尽管它对新冠肺炎的具体保护能力还有待评估。同样,最*的一项研究强调了新冠肺炎食用卷心菜和发酵蔬菜在减少不良后果方面的潜力[3]。

带回家的信息

使用基于机器学习的技术,我们根据其在基因组水*上与实验性抗新冠肺炎药物的共性,确定了食品中具有抗新冠肺炎特性的生物活性分子。然后,我们建立了一个食物地图根据预测的抗病毒分子的生物利用度和多样性对食物进行排序。

尽管我们离设计既美味又健康的食谱还有一段距离,但我们的研究结果表明,我们有望为管理非重症新冠肺炎病例开发出一条更清晰的道路,在这条道路上,抗病毒超剂量将被“开出”以帮助患者更快更好地康复。

感谢 Ivan Laponogov 校对本帖。此处提供的结果是理论工作的一部分,正在进行临床验证,并不打算取代认证的医疗建议。这项工作是帝国理工学院 Hyperfoods 项目的一部分,由 Kirill Veselkov 与沃达丰基金会和厨房理论合作领导。

如果你想了解更多关于我的研究,请关注我,查看我的个人页面,或者在 twitter 上关注我!

参考

[0]拉波诺戈夫一世 *** ,冈萨雷斯 G *** ,谢泼德 m .等人(2021)。网络机器学习绘制“超级森林”对抗新冠肺炎。人类基因组学 15(1): 1。 *等额出资。

[1] ES Knock,LK Whittles,JA Lees 。2020 年英国的新型冠状病毒疫情:关键的流行病学驱动因素和干预措施的影响。伦敦帝国理工学院(2020 年 12 月 22 日),doi:【https://doi.org/10.25561/85146

[2] Ikuta K,Mizuta K,Suzutani T .来自新西兰和波兰的黑加仑(Ribes nigrum L .)的两种提取物的抗流感病毒活性。福岛医学科学杂志。2013;59(1):35–8.doi: 10.5387/fms.59.35

[3] Bousquet J .等,《卷心菜和发酵蔬菜:从国家死亡率的异质性到严重新冠肺炎缓解策略的候选人》。过敏。2020;00:1–16.【https://doi.org/10.1111/all.14549】T4。

Github Copilot 能让你成为更好的数据科学家吗?

原文:https://towardsdatascience.com/can-github-copilot-make-you-a-better-data-scientist-6fd751fb38ce?source=collection_archive---------7-----------------------

人类对抗人工智能

让我们用 Github Copilot 完成一个数据科学项目吧!

来自 Pexels 的 ThisIsEngineering 摄影

Github Copilot 是最*编程界的炒作,许多文章和 youtube 视频都显示了 Copilot 的惊人能力。我最*获得了 Github Copilot 技术预览版的访问权限,我很好奇Copilot 如何在数据科学项目中帮助数据科学家。

什么是 GitHub Copilot?

GitHub Copilot 是一个 AI pair 程序员,可以帮助你以更少的工作量更快地编写代码。GitHub Copilot 从注释和代码中提取上下文,并立即建议单独的行和整个功能。[3]

Copilot 接受了来自 GitHub 知识库和其他网站的大量公开编码数据的培训。所以基本上是比你我更好的程序员。

如何使用 Copilot?

目前,Copilot 技术预览版作为 VS 代码扩展提供,并且只限于一小部分测试人员预览该扩展。可以试试在这里报名。成功批准后,您将看到如下屏幕:

Copilot 预览版注册成功。作者图片

Copilot 的工作就像你的谷歌自动完成。代码建议将显示为暗淡的颜色短语,当指向建议的代码时,您将获得一个鼠标悬停标签。

副驾驶显示。作者图片

Copilot 将为您提供大量代码建议,只需按下 Alt + ]Alt + [ 更改建议的代码,然后按下“ Tab 接受它。您可以预览多个建议代码,只需按下 Ctrl+Enter 即可得到如下视图:

多个代码建议。作者图片

Copilot 能够识别您的评论并根据您的评论生成功能,您可以向 copilot 发出指令以生成功能,如下例所示:

副驾驶看了你的评论。作者图片

P.s:对于 Q & A 车型,还可以通过键入 ME:AI: 与副驾驶聊天。

与副驾驶聊天。作者图片

我们对 Copilot 的简短介绍到此结束,让我们继续讨论我们的主要问题:

Copilot 能帮助数据科学家做出更好的数据科学项目吗?

我们试试吧!

准备好和你的副驾驶一起飞行了吗?照片由 Rafael Cosquiere 从 Pexels 拍摄

实验:

在这个实验中,我们将使用著名的虹膜数据集;我们的目标是 使用 Copilot 执行探索性数据分析,并使用纯粹的建议代码 训练 k-NN 模型。我们将制定如下规则:

  1. 仅使用建议的代码,仅修复打字错误和特定于数据的问题。
  2. 每一个动作都应该伴随着一个明确的comment/command给副驾驶。
  3. 只有 3 个顶级代码建议将被采纳。

截止到写的时候,VS 代码的 Python 笔记本用 Copilot 相对不稳定,所以我会用 Streamlit 作为我的*台。Streamlit 提供了一个类似 Jupyter 笔记本的实时代码更新 web 应用程序,可以帮助我们探索数据科学项目。想了解更多关于 Streamlit 的信息,你可以在这里阅读我的文章。

导入库包:

import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px

💡数据加载

# load iris.csv into dataframe

副驾驶的代码建议。作者图片

💡带副驾驶的 EDA

# print the dataframe column names and shape

给我留下深刻印象的是,Copilot 自动理解了 streamlit 中的打印机制,它使用了 st.write() 而不是 print() ,因为 Streamlit 是 python 中相对较新的包。

接下来,我尝试用:

# create a scatter plot of the petal length and petal width using plotly express

这是我得到的,看起来 Copilot 不够聪明,无法理解数据帧中的上下文😂:

接下来,我尝试精确命名,得到了一个很好的精确图形:

# create a scatter plot of the petalLengthCm with SepalLengthCm using plotly express

Copilot 创建的 Plotly 图形。作者图片

💡使用 scikit 建模-了解:

接下来,为了创建一个测试和训练数据集,我编写了以下代码:

# splitting the data into training and testing sets (80:20)

这些是我得到的建议:

印象深刻!Copilot 甚至知道哪一个是我的目标类,并为我编写了完整的代码,我需要做的只是选择建议!

完整的代码建议返回如下:

接下来,我用这个命令试试运气:

# check for optimal K value using testing set

出乎我的意料,副驾驶可以返回给我这个代码:

这在编码方面节省了大量时间;Copilot 甚至会在最后帮你绘制图表。嗯,图表没有成功,所以我必须使用创建的列表对我这边的代码做一点修改。但是它仍然节省了我很多时间去检查代码的堆栈溢出。

出于好奇,我问副驾驶,“最佳 K 值是多少?”

副驾驶无需绘制图表就将答案返回给我😲😲

这启发了我的下一个命令,我想:

# create a classifier using the optimal K value

然后,我只需按 enter 并接受建议的注释和代码就可以继续了。下面是我得到的代码:

注意,我只键入 1 条命令,其余的由副驾驶建议。

建议代码的结果

在 5 个建议的代码中,3 个工作正常,2 个建议: metrics.f1_scoremetrics.precision_score 不工作。

我用 Copilot 进行的简单代码测试到此结束。我已经在 Github 上发表了这个建议,可以随意看看。

最终想法:

在本文中,我演示了 copilot 如何在数据科学过程中提供帮助,Copilot 犯了一些错误,但使用它的好处更多。另一个问题是,我使用的数据集是 Iris 数据集,因此它在更大的数据集中可能不太有效。

编程的新范式来了,不用在 StackOverflow 等问答网站里搜索,Copilot 会节省你大部分 googling 的时间,直接给你多个解决方案。我猜它将来会减少编程相关问题对 StackOverflow 和 Google 的依赖。

嗯,在目前阶段,我们的工作仍然是安全的,因为 Copilot 仍然需要一些基本的知识来执行,如指导项目的方向,告诉 Copilot 该做什么。

在我看来,Copilot 肯定会让你成为更好的数据科学家。*但它会在未来取代你作为数据科学家的工作吗?*随着反馈和大量数据输入 Copilot,它肯定会在未来成为更好的 AI,谁知道它会不会接管程序员和数据科学家的工作?🤔🤔

最后,我仍然在#TeamHumanity:凭借我们的创造力,我们将接管对人工智能的控制,并利用人工智能改善我们的生活。非常感谢你看我的文章。

旁注:

以下是我的一些文章,希望你也喜欢:

[## 5 分钟内自动完成谷歌表单报告

towardsdatascience.com](/automate-google-sheet-reporting-in-5-minutes-8bbdc1f8e293)

参考资料:

  1. 来自 Kaggle 的虹膜数据集
  2. https://towards data science . com/github-copilot-a-new-generation-of-ai-programmers-327 E3 C7 ef 3 AE
  3. https://copilot.github.com/

Github Copilot 能代替开发者吗?

原文:https://towardsdatascience.com/can-githubs-copilot-replace-developers-b89f28007c05?source=collection_archive---------7-----------------------

自从发布以来,copilot 已经成为开发者们谈论的话题。使用它有许多优点和缺点。

作者图片

自从我接触到 Github Copilot 的技术预览版,我就被问了很多次这个问题。我会尽我所能回答这个问题。最后,我会诚实地评价我们是否应该使用它。

**简短回答:**需要时间。当然,每个人都必须成为无用阶层的一部分,开发者也是如此——但最终。为了获得更清晰的想法,请继续阅读。

让我们首先了解什么是 Github Copilot 以及它是如何工作的——它将帮助我们评估代码自动完成的未来。

Github 的副驾驶是什么?

据 Github 报道, Copilot 由 Codex 提供动力,Codex 是 OpenAI 创造的新 AI 系统。GitHub Copilot 比大多数代码助手理解更多的上下文。GitHub Copilot 经过数十亿行公共代码的训练,让您所需的知识触手可及,节省您的时间并帮助您保持专注。

作者 Gif

简单来说,Copilot 真的理解你下一行要编码什么。在我的情况下,它甚至可以完美地理解不好的评论。有时,它会犯一些愚蠢的错误,比如重复声明同一个变量;这种类型的错误是预料之中的,这就是为什么 Github 最初允许开发者给出反馈。我对它的理解能力感到非常惊讶。你只需要给它一些例子,剩下的就会完美地自动生成。

到目前为止,我想提及 3 个主要特性:

  1. 将注释转换为代码。

Github Copilot 可以理解不好的注释和函数名。

2.没有辛劳的测试。

这是我推荐大家在 Github Copilot 中使用的唯一功能。

3.重复代码的自动填充。

Github Copilot 是现有自动建议插件的更高级形式。这对于有经验的开发人员来说显然是好事,但对于新手来说却不是。

但是 Github Copilot 并不是每次都能写出完美的代码。正如 Github 所说,它的副驾驶总是尽力理解你的意图,但它建议的代码可能并不总是有效,甚至没有意义。随着时间的推移会有所改善。

它是如何工作的?

根据 Github Copilot 的说法,它已经在互联网上接受了一系列英语和源代码的培训,包括所有 Github 库(私人库除外)。

图片作者|设计于 Figma

上图不言自明。Codex 检索与编码相关的文本和互联网上可用的公共代码(Github ),并使用其算法将其传递给 Github Copilot 服务。这个服务然后为我们的私有代码提供建议,实际上这不是私有的,因为它将改进建议发送回服务 Github Copilot。:)

抄本理论但很有趣。

根据一周前发布的一篇 35 页长的论文Codex paper,Codex 是一个 GPT 语言模型,对来自 Github 的公开可用代码进行了微调,并研究其 Python 代码编写能力。“Codex 比 GPT-3 更有效率和改进,因为它已经在 Github 上的许多公共存储库上进行了训练。

论文 还声称已经解决了 10000+的竞技编程问题。

关于数据收集,文中说:

我们的训练数据集是在 2020 年 5 月从 GitHub 上托管的 5400 万个公共软件存储库中收集的,包含 179 GB 的 1 MB 以下的唯一 Python 文件。我们过滤掉了可能是自动生成的、*均行长度大于 100、最大行长度大于 1000 或包含少量字母数字字符的文件。过滤后,我们的最终数据集总计 159 GB”

最后,https://arxiv.org/pdf/2107.03374.pdf本文得出结论:

通过在 GitHub 的代码上对 GPT 进行微调,我们发现我们的模型在一组难度与简单的面试问题相当的人工编写的问题上表现出了很好的性能

这都是关于 Codex 的数据和事实,它是 Github Copilot 的支柱。论文明确说未来会产生更准确有效的结果,这意味着 Github Copilot 会越来越强。

人工智能工具将如何影响开发者

关键时刻到了。Github Copilot 将大大提高开发人员的工作效率。这也将有助于降低软件生产的成本。我认为 Github Copilot 可以取代编写代码的人(程序员),但首先要取代开发人员需要的时间太多了。我使用两个不同的头衔——程序员和开发人员——因为美国劳工统计局(Bureau of Labor Statistics,BLS)将计算机程序员和软件开发人员分开分类,开发人员的薪酬高于程序员,因为他们有更多与编写代码和与代码交互间接相关的任务。

正如我在介绍部分提到的,每个人都要成为无用阶层的一部分,但与计算机交互的人会最后加入。在无用阶级时代,如果你生活在一个发达国家,或者你的政府足够好,那么你什么都不做也会得到报酬。

这篇论文还声称,食品法典委员会将为补充改变的工作流程的工作创造新的市场。在 GPT-3 发布后,一些公司开始在工作列表中加入与 GPT-3 的合作和编写提示。也有可能像 Codex 这样的模型会为那些熟练使用这些工具的工程师带来新的工作类型。

应该用 Github Copilot 吗?

我用 Github Copilot 的体验没那么好。当报纸声称 Codex 已经解决了超过 10,000 个竞争性编程问题时,我正在解决一个螺旋数问题。Github Copilot 提出了一些与 if 逻辑无关的非常尴尬的陈述,这意味着 Copilot 必须学习很多东西。我用 Copilot 只是为了测试,但是在竞技编程中使用 AI 工具就是欺骗自己**。**

千万不要用这样的工具来解题,会对你的解题技巧产生高度负面的影响。如果你是一个有经验的开发者,那么你应该利用 Github Copilot 来处理重复的代码。如果你是一个新手,你必须避免这样的人工智能工具,即使是 IDE 的自动建议,它们会破坏你的概念。

但是不管你是什么,甚至不要想到在竞争性编程中使用人工智能工具,它们可以帮助你获胜,但你不会获得内心的*静。

这篇文章是根据我与副驾驶的经验,研究,和 抄本论文 。是否使用 Github Copilot 这样的工具是你的选择。但是你肯定会用到它们,如果不是今天,那么就是明天。

请让我知道你对 AI 自动完成工具的想法,比如 Gitub Copilot,以及你对开发者未来的看法。

我能吃那个蘑菇吗?

原文:https://towardsdatascience.com/can-i-eat-that-mushroom-fc84e5b6b2c4?source=collection_archive---------66-----------------------

神经网络可以有所帮助

这些蘑菇有些可以食用,有些不可以。你能分辨出哪个是哪个吗?图片由安德鲁·雷德利在 Unsplash 上拍摄

想象一下,你在森林里呆了一个晚上,你只能吃你在周围找到的东西。你偶然发现了一片蘑菇。问题解决了!不完全是。**用肉眼来看,几乎不可能判断一家餐馆是否安全。然而,通过机器学习,我们可以创建一个人工智能来预测给定的蘑菇是否可以食用。**最*我分别用 Tensorflow 和 Keras,一个 Python 神经网络(NN)库和它的 API,开发了这样一个算法。让我们来看看它到底是如何工作的,以及它最终执行任务的效果如何。

该方法

数据

为了开始这项任务,我们需要找到一个大型数据集,其中包含数以千计的蘑菇,它们的一些特征,以及它们是否可以食用。我在这里发现了这样一个数据集。文件蘑菇 _weka_dataset.csv (csv 是列表commasseparatedvalues),我在我的 Python 编辑器中将其重命名为 data.csv,包含关于 8417 蘑菇的信息利用这些知识,我们可以教会我们即将诞生的神经网络蘑菇的哪些特性表明它们是安全的。

data.csv 中的第 5015 行;它描述了一种不可食用的(有毒的)蘑菇。作者图片

在很高的层面上,我们的网络通过浏览数据,首先随机猜测每个特征如何决定可食用性 (是的,就是 一个词 ,对于那些想知道的人) **,然后根据它的表现逐渐调整猜测。最终,所有这些调整都是为了使损失函数最小化,损失函数是衡量网络性能好坏的指标。**在这种情况下,损失函数将输出网络与食用蘑菇有毒的接*程度,反之亦然。(关于 NN 如何工作的深入解释,请阅读本文

翻译数据

仅仅找到一个我们想要的 CSV 文件是不够的。数据科学很大一部分是处理数据,这个项目也不例外。我们必须将文件翻译成我们的网络能够理解的语言。也就是说,语言是数学,单词必须变成数字。现在,data.csv 只是一个单词集合。它告诉我们瓶盖的表面是“光滑的”,但是我们的代码不知道如何解释这一点,除非它采用一些数值。

为了执行这种转换,我首先**将文件转录成一个名为蘑菇的 Python 列表**。这也使得最终将数据输入我们的网络变得更加容易。

*from csv import reader #Module to read CSV files

#Read data from file into a list
mushrooms = []
with open("/Users/yamanhabip/PycharmProjects/Mushrooms network/data.csv", mode = "r") as file: #open *data.csv* in read mode

    to_read = reader(file) #create a CSV reader
    next(to_read) #skip the first line

    for line in to_read: #loop through the file
        mushrooms.append(line) #add each line to *mushrooms**

这段代码跳过了文件的第一行,因为它包含了属性的描述。然后,简单地获取 CSV 文件的每一行,自动将其转换为一个列表,并将该列表添加到更大的主列表中,即蘑菇列表。

之后,实际的翻译就可以开始了。为了完成这个任务,我创建了一个名为替换* 的 Python 字典,并给文件中出现的每个单词分配了一个相应的编号。下面是实际的代码:*

*#Turn strings in list into numerical values
replacements = {} #create a running dictionary
num = 0 #create a counter to generate numbers for the word-number switches

for i in range(len(mushrooms)): #loop through *mushrooms*
    for j in range(len(mushrooms[i])): #loop through the sub-list that represents each individual mushroom #if the word in the sub-list has been encountered before, replace it with the corresponding value in *replacements* if mushrooms[i][j] in replacements: 
            mushrooms[i][j] = replacements[mushrooms[i][j]]#otherwise, create a new entry in replacements where the word corresponds to the value of the variable *num* and then replace the word.Then increase *num* by one to avoid one number representing two words.         else:
            replacements[mushrooms[i][j]] = num
            mushrooms[i][j] = replacements[mushrooms[i][j]]
            num += 1*

正如代码中的注释所解释的,**上面的软件在 replacements 中为它遇到的每个唯一的单词创建一个新条目,同时遍历 data.csv 中的每个条目,将单词映射到一个数字。然后,它利用这种映射将每个单词转换成由替换给它的数字。举例来说,这个过程的结果是“可食用”变成了 16 个,“有毒”变成了 44 个。因此,每当单词“可食用”出现时,网络将“看到”16,并且它可以利用这一点来训练自己基于这些数字表示做出准确的预测。下面是一个完整的、经过翻译的行:编号 5015,与上图相同,来自我们数据的新的和改进的版本。****

第 5015 行是数字。作者图片

拆分数据

*既然我们已经把数据从机器乱码变成了机器可读的,我们必须把它分成两个部分:**输入/输出和训练/测试。**这里的第一步是将它分成输入和输出数据,因为一旦我们完成了,Python 就有了一个很好的模块来为我们进行训练测试分割。**分离输入和输出数据只是意味着将我们正在使用的预测器放入一组,而将我们试图预测的东西放入另一组。*对于蘑菇,这意味着我们需要创建一个列表,列出它们的特征(回想一下,这些特征是颜色、形状等。)和另一个说明它们是否有毒。这是 Python 中的样子:

*#Split data into inputs and outputs
input_data = [] #a list for inputs
output_data = []#a list for outputs

for i in mushrooms: #loop through each individual mushroom in *mushrooms* input_data.append(i[:-1]) #add everything except the last item to inputs #add the last item to outputs as a one or a zero
    if i[-1:][0] == 16:#edible mushrooms have the last item as 16, we turn this into a one
        output_data.append(1)
    else: #otherwise the mushroom is not safe, and we represent this with a zero
        output_data.append(0)*

该代码为蘑菇的特性及其可食用性创建了空列表(也作 一词 )。由于数据文件中除了最后一列之外的所有内容都是为了帮助我们确定最后一列是“可食用”还是“有毒”(或者对于我们的网络 44 或 16) ,**除了最后一行之外,每个蘑菇的所有数据都放入输入列表,最后一个数字放入输出列表。**代码通过循环遍历蘑菇并根据条件将数据分发到输入 _ 数据输出 _ 数据中来实现这一点。至关重要的是, input_data 的第一行与output _ data的第一行匹配,以此类推,因此我们的网络能够使用这两个列表来查看它在预测蘑菇的安全性方面做得如何,并逐渐调整自己。

您会注意到,对于输出列表,我分别使用 1 和 0,而不是 16 和 44;这是为了利用 Tensorflow 的能力来模拟输出为 1 或 0 的二元函数。

在我们能够建立我们的网络之前,我们必须做的最后一块蛋糕切割是训练测试分割。这仅仅意味着,在我们用另一部分数据来训练我们的网络之后,我们留出一部分数据来测试我们的网络。 **这种分割有助于捕捉和避免过度拟合,**这是一个陷阱,我们的网络太擅长对一组数据进行评估,以至于它不再能很好地预测一般情况。好消息是:这种拆分并不简单,使用 sklearn 的 train_test_split 函数,两行代码变得简单了。它是这样工作的:**

*#import train_test_split
from sklearn.model_selection import train_test_split#split the data
input_training, input_testing, output_training, output_testing = train_test_split(input_data, output_data, test_size = 0.2)*

*该函数返回四个列表,我将它们命名为 *input_training、input_testing、output_training、*和 *output_testing。我选择将参数 test_size 设置为 0.2,这意味着返回的涉及培训的部分包含 80%的数据,涉及测试的部分包含 20%。现在我们终于完成了所有无聊的数据操作,我们可以开始创建一个网络。

构建网络

我决定为我们的网络使用一个非常简单的模型,叫做顺序模型*。它可以容纳我们想要的任意多的层,在这个模型中每一层都从上一层获取数据,并输入到下一层。此外,我使用了密集层,这意味着每个节点都连接到 (通过一个权重) 到它之前和之后的层中的每个节点,如果像那样的层存在*(第一层和最后一层分别没有它们之前和之后的节点)。**

回想一下,神经网络有各种带有输入、输出和隐藏层的节点。注意:这张图片并不代表我在蘑菇数据中使用的网络,它只是一个网络一般结构的图解。在 Wikimedia Commons 上公开的图片

也就是说,数据已经为我们的层做出了一些决定,还有一些决定需要我们自己做出。我们知道输入层必须有 22 个节点,因为我们有 22 个不同的可食用性潜在预测值。我们还知道,我们的输出层只需要有一个节点 (我将称之为输出节点),因为我们唯一可能的输出是 1,表示可食用,零,表示有毒。当然,输出节点的值不会总是 1 或 0;更确切地说,它将是一个可以解释为 1 或 0 的值。例如,我们的网络可能会计算出,如果输出节点的值大于 0.5,蘑菇就可以食用,否则就是有毒的。稍后,我们将通过输出节点的 sigmoid 激活函数来帮助我们的网络做到这一点。

我们能决定的是我们有多少个隐藏层,以及这些层中有多少个节点。这里有一个内在的权衡:我们拥有的隐藏层和节点越多,我们的网络可以模拟的函数就越复杂,但它也将越慢,因为它必须计算出更多的权重,从而进行更多繁重的数学运算。每个数据集的正确*衡会有所不同。对于我们的蘑菇例子,我发现两个隐藏层,每个有四个节点,足够有效和准确。

所以,总结一下:我们需要一个四层的网络。第一层是输入层,有 22 个节点,第二层和第三层都是隐藏层,各有 4 个节点,最后一层是输出层,只有一个节点。这里最后的决定点是每一层使用什么激活函数。激活函数只是告诉我们的网络如何评估输入层之外的每个节点(输入层中的节点只是我们给网络的值,因此我们可以告诉它如何读取没有激活函数的节点)

用蓝色标出。图片由 Ringdongdang 在 Wikimedia Commons

*对于这个网络,我使用 ReLu ,或者整流线性单元,来激活隐藏层。ReLu 只是获取隐藏层中每个节点的值,如果它是负数,就将其设置为零。否则,它返回值本身。ReLu 很有用,因为它允许我们**处理更少的数据,**提高效率,**并为我们的神经网络创建一个线性度更低的模型,以更好地模拟曲线。*此外,为 ReLu,f(x) = max (0,x)建模的函数对于 Python 来说非常容易计算,并且占用很少的处理能力,因此非常高效。

乙状结肠图。图片来自马丁·托马斯在维基共享资源

我为输出层使用了 Sigmoid 激活函数,它获取它的值,然后**将其归一化到 0 到 1 之间。这允许我们的网络设置一个阈值,它可以合理地确定所有的输出将符合蘑菇是否安全。如果这有点抽象,请这样想:如果没有 Sigmoid,我们可能到处都是输出,并且不可能做出类似“所有低于 0.5 的输出(或任何其他数字)*构成毒蘑菇”的声明,因为当输出范围可以从-789 到 1234 时 *0.5 将是这样一个任意的阈值。然而,当输出只能在 0 和 1 之间时,to 数字会使我们的网络大吃一惊,因此很容易创建阈值。请注意,Sigmoid 使用分数指数函数来建模,因此计算量相当大。幸运的是,我们只需要将它用于网络中的一个节点。

让我们看看所有这些是如何用 Tensorflow 和 Keras 实现为代码的。为了简单起见,我在这里将它们导入并重命名为 tf_k

*#Import keras, an API for tensorflow
from tensorflow import keras as tf_k#Create a network with a sequential model
network = tf_k.Sequential()

#Add 2 hidden, dense layers to the network, each with four nodes and relu activation
network.add(tf_k.layers.Dense(4, activation = "relu", name = "hidden1"))network.add(tf_k.layers.Dense(4, activation = "relu", name = "hidden2"))

#Add an output node with sigmoid activation
network.add(tf_k.layers.Dense(1, activation = "sigmoid", name = "output"))*

有了它,我们就能构建上述网络。**使用 network.add 我们将所有需要的密集层添加到我们的顺序模型中,**并且我们能够使用第一个参数设置节点的数量(或者* 超参数 ,因为这是编码器设置的值,而不是网络学习的值)。我还将激活函数描述为每一层的参数,并为每一层命名以供将来参考,也许是为了可视化或调试*

你可能已经注意到了我们没有添加输入层。我们不需要一个,因为我们简单地把列表 input_training 给 tensorflow,它直接把它输入到我们的第一个隐藏层。

训练网络

在我们的网络开始运作之前的最后一步是培训它。要做到这一点,我们必须将它放在一起,并用下面的两行代码使其符合我们的数据:

*#put the network together
network.compile(optimizer = "adam", metrics = ["accuracy"], loss = tf_k.losses.binary_crossentropy)

#Train the network with out training data and 20 epochs through the data
network.fit(input_training, output_training, epochs = 20, verbose = 2)*

这些线中的第一条将我们所有的层集合到一个统一的模型中,该模型将使用 Tensorflow 的内置优化器 adam ,该优化器使用梯度下降,一个更新我们网络权重的函数。它还告诉我们的网络,我们正在努力实现高精度,以此作为我们评估的标准。最后,网络知道它应该使用binary _ cross entropyloss 函数,它通过告诉我们它离输出错误的二进制变量有多*,简单地计算出我们的网络做得有多好。顾名思义, binary_crossentropy 专门用于二元预测,如毒蘑菇和食用蘑菇的区别,完全符合我们的目的。像我之前解释的,网络通过尝试最小化这个损失函数来“学习”。

当查看数据集 input_trainingoutput_training 时,第二行实际上通过拟合其权重来训练网络,以最小化损失函数。参数 epochs 允许我们指定网络遍历数据的次数,并优化其权重。这里,我们必须在效率和准确性之间做出选择。我发现 20 次以上为这个特殊的网络创造了一个很好的*衡。Verbose 简单地给出了一些不同的选项,关于网络如何向你显示它的学习。我喜欢 verbose = 2 的可视化方法,尽管其他方法可能适用于不同的个人。

添加测试步骤

我需要的最后一行代码是使用测试数据来确保网络能在一般情况下工作。

*#Test the network with the testing data
network.evaluate(input_testing, output_testing, verbose = 2)*

与其他一切相比,这是一件轻而易举的事情。**我们所要做的就是告诉网络使用哪些数据来评估自己,**因此参数输入 _ 测试输出 _ 测试,以及我们希望看到的结果。这里,我再次使用 verbose = 2 作为我首选的可视化方法。

结果呢

好吧。我们努力工作,建立了我们的神经网络。是时候带它出去兜兜风了。经过 20 个时期的训练和查看测试数据,我们从我们的程序中得到以下结果。为了避免本文中大量繁琐的编程输出,我只显示了第 1、10 和 20 个时期以及测试阶段的结果。

***Epoch 1/20** loss: 2.6525 - accuracy: 0.6885
**Epoch 10/20** loss: 0.0562 - accuracy: 0.9813
**Epoch 20/20**
loss: 0.0188 - accuracy: 0.9949
**Testing** loss: 0.0152 - accuracy: 0.9923*

随着时代的推移,网络变得越来越好。起初,网络只比随机猜测好一点点,当然比熟练的人类差,得出关于蘑菇的正确结论的概率只有 69%。然而,我们必须相信这个过程,因为随着的消逝,损失函数返回越来越小的值,网络的准确度接* 100%。

*现在,我们还不能太兴奋,因为如此高的精度**可能表明过度拟合。如果网络从未在训练数据上出错,那么它可能只是简单地掌握了这些数据。我们不知道这种优势是否会转化到其他蘑菇上。但幸运的是,*该网络似乎也非常擅长一般情况,因为它在测试数据上也获得了超过 99%的准确性。有趣的是,似乎有一点点过度拟合,因为网络测试比它在最终训练时期测试的要差一点点。虽然,它实际上在测试集上损失较少,所以这可能只是一个巧合,而不是常见陷阱的结果。

更多应用

*现在,如果你认为机器学习真的很酷,但认为你永远不会遇到野生蘑菇,不要害怕!**本文概述的技术几乎可以应用于任何存在因果关系的领域。*例如,用户可以输入一部电影的评论以及卖出了多少张票,以尝试并计算出它是否会收支*衡。需要做的只是改变输入的数据集,也许还需要调整超参数。更发人深省的前景包括预测信用卡欺诈、医疗疾病诊断、新的破解蛋白质折叠之谜就在上个月,关于神经网络的陈词滥调“可能性是无限的”听起来很真实。

关键要点

  • 神经网络使用输入、输出和隐藏层对现实世界进行预测。
  • 他们几乎可以解决任何有因果关系的问题。
  • 其中一个应用是根据蘑菇的一些特性来预测它是否可以食用。
  • 要构建神经网络,必须:
  1. 收集并翻译数据以便网络能够理解。
  2. 将数据分成输入和输出以及测试和训练数据。
  3. 建立一个网络并决定隐藏层数、 这些层中有多少节点,以及使用什么激活函数
  4. 用训练数据训练网络。
  5. 用测试数据测试网络,确保它没有过拟合

进一步阅读

本文源代码在 Github repo 中。

如果你想了解更多,网上有很多资源。我特别推荐 edx 的 CS50:AI 入门课程。如果你想跟我跟进、交谈或有进一步的问题,这是我的联系方式:

邮箱||Linkedin|Github

并请 订阅 我的月报!

“我能在没有经验的情况下找到数据科学的工作吗?”

原文:https://towardsdatascience.com/can-i-get-a-data-science-job-with-no-prior-experience-7006b8675945?source=collection_archive---------3-----------------------

求职时克服先有鸡还是先有蛋的问题

丹尼尔·塔特尔在 Unsplash 上拍摄的照片

找一份入门级的数据科学工作很难。我喜欢称之为鸡和蛋的问题,因为没有人会给你一份没有经验的工作,而没有工作你也无法获得经验。

我在 LinkedIn 上收到的大多数消息都是来自于人们问我他们如何才能克服这个问题。这些信息的要点如下:

"我知道 Python 和 SQL,还上过数据科学的在线课程。我仍然很难在这个行业找到工作。我申请的公司要么根本没有回应,要么告诉我,我没有他们想要的那种经验。”

在本文中,我将尝试分两部分回答这个问题:

  1. 首先,我将解释如何在没有工作经验的情况下展示你的经验。
  2. 然后,我会走一遍求职程序。求职门户网站通常是一个死胡同,大多数人很少或根本没有成功。

证明你有做这项工作所必需的技能

训练营和在线课程不足以证明你拥有成为数据科学家所必需的技能。

任何人都可以参加在线课程并获得证书。事实上,吴恩达在 Coursera 上的机器学习课程已经有超过 100 万名学生注册。

在成为数据科学家之前,你需要学习更多的技能(即使是入门级的)。

要展示这些技能,您可以执行以下一项(或两项)操作:

1.项目

您有兴趣成为 a 公司的数据科学家。他们的工作列表中有一项要求,即:

寻找在自然语言处理和建立情感分析模型方面有经验的人。

你没有工作经验,过去也没有为一家公司搭建过情绪分析模型。但是,你确实有一些机器学习知识,知道如何处理文本数据。

你现在应该做的是:

在 Twitter 和其他社交媒体上找到该公司。收集提及该公司的帖子的数据。

然后,用这些数据建立一个情感分析模型,并在你的作品集上展示。

申请工作时在工作经验下突出这个项目。你在得到这份工作之前就试图解决公司的问题,这会让你在所有应聘者中脱颖而出。

你也可以阅读我的文章“ 数据科学项目将让你得到工作 ”,这篇文章准确地概述了你应该在投资组合中展示的项目类型。我正是通过做我在文章中解释的事情获得了我的第一份数据科学实习。

2.获得认证

由 Liam Truong 在 Unsplash 上拍摄的照片

获得认证并不意味着参加 Coursera 上的课程并努力获得认证证书。

你可以获得许多被普遍认可的专业认证。这些认证证明您拥有完成工作所必需的技能,并且对用于现场工作的工具有足够深刻的理解。

一些最受欢迎的认证包括:

谷歌云数据工程师认证

大多数处理大量数据的公司使用亚马逊 AWS、微软 Azure 或谷歌云。

获得谷歌云数据工程师认证意味着你能够利用谷歌云构建数据驱动的解决方案和部署可扩展的机器学习模型。

这是一个两小时的监考考试,建议具有 3 年以上行业经验的人获得认证。

然而,你可以自己学习如何使用这个*台,并在几个月内通过考试。观看 Daniel Bourke 的视频,了解他如何在没有 GCP 工作经验的情况下成为谷歌云的认证数据工程师。

微软认证:Azure 数据科学家助理

该认证将测试您的预测分析、人工智能、机器学习和 NLP。你需要熟悉部署预测模型和使用微软 Azure *台。

Tensorflow 开发者证书

这是谷歌提供的另一个认证项目。考试将测试你用 Python 中的 Tensorflow 构建机器学习(尤其是深度学习)模型的能力。

你需要知道如何建立图像识别算法、NLP 模型和时间序列预测模型。

请看一下这篇全面的指南,让几乎没有经验的人获得 Tensorflow 开发人员认证。

申请工作

马库斯·温克勒在 Unsplash 上的照片

我建议在申请全职数据科学职位之前,先从实习开始。

公司更有可能给没有工作经验的人提供实习机会。实习结束后,你在公司获得初级职位会容易得多。

甚至申请实习也很困难。

过去有很多人给我发信息,谈论他们失败的实习申请。

他们中的大多数人甚至从未得到回复。当你通过招聘网站申请职位时,这种情况经常发生。

求职门户是个死胡同。

大多数雇主会在门户网站上发布空缺职位,即使找到了足够多的人,也不会关闭申请。

我建议不要通过求职网站向一家公司申请,而是更进一步,去接触在那里工作的人。

找一个在公司工作的招聘人员,或者他们数据科学团队的负责人。给他们发一封个性化的电子邮件,解释你是谁,为什么你想和他们一起工作。

我得到了德勤的面试机会,因为我联系了一名招聘人员,并解释说我正在寻找一份数据科学实习。

就在第二天,我收到了回复,被叫去面试,最终得到了实习机会。我甚至不知道公司有一个数据科学实习生的空缺职位。

我刚刚联系了他们,询问我是否可以以实习生的身份加入他们的数据科学团队,并惊讶地听到了回复。

我亲自联系招聘人员的成功率比直接投简历要高得多,我建议你也这样做。

结论

在数据科学领域找到一份初级工作很难。事实上,这是你在数据科学职业生涯中面临的最大障碍之一。

一旦你获得了第一份实习或工作,如果你真的离开了公司,获得下一份工作通常会变得更容易。

整个“如果没有人愿意给我经验,我如何获得经验”的事情可能会令人沮丧,但这不是永久的。

有很多不同的方法可以证明你有必要的专业知识来做这项工作,即使你以前没有工作经验。

我希望你喜欢这篇文章。如果你做到了这一步,感谢你的阅读!

一条河流穿过一块岩石不是因为它的力量,而是它的坚持。

不用那么多数学可以学习量子计算吗?

原文:https://towardsdatascience.com/can-i-learn-quantum-computing-without-using-so-much-math-ae85838e6f51?source=collection_archive---------36-----------------------

你不需要成为数学家来理解量子计算,但当事情变得棘手时,数学是你的盟友。

量子机器学习要不要入门?看看 动手量子机器学习用 Python

在经典计算中,我们习惯于在布尔状态下思考。一个术语是真还是假。某个位是关(0)还是开(1)。就是这样。这是我们所有算法的基础。

有了布尔逻辑,只需要很少的运算符,比如而不是以及,我们就可以开发出相当复杂的程序。如果某项为真,就这样做,否则就那样做。因为这个术语是真的,重复做某件事。

作为一名程序员,你可能整天都在脑子里想着真值表。

作者图片

在量子计算中,我们的比特是量子比特(量子比特的缩写)。它不是 0 或 1,而是 0 和 1 的复合(如在复数中)线性组合。

假设我们有一枚硬币。当你把硬币放在桌子上,你有一个古典位。要么正面朝上,要么反面朝上。你可以用布尔术语来定义你的逻辑。你可以指定硬币正面朝上时会发生什么,或者硬币反面朝上时你该做什么。当然,你可以用硬币工作。你可以把它放在桌子上任何你喜欢的方向。你的指示是这样的:“如果硬币是正面朝上,那么拿着它,反面朝上地放在桌子上。”

在量子计算中,我们抛硬币。它在空中旋转。它是头和尾的组合。当且仅当你抓住它,看着它,它决定一个值。一旦落地,就是一枚正面朝上或者反面朝上的普通硬币。

硬币放在桌子上时有两种状态,正面或反面。在空气中,我们的量子硬币处于两种状态的叠加状态。让我们仔细看看这枚硬币。它不断地在正面和反面之间翻转。一旦硬币落地,这个旋转决定了我们看到的是正面还是反面。再仔细看看。这枚硬币也沿着它的边缘旋转。

作者图片

问题是,我们不能再用一个简单的布尔值来描述这种状态了。我们需要描述它的旋转,以及它如何影响正面朝上或反面朝上着陆的概率。

因此,在量子计算中,我们用向量来代表量子位元的状态。当量子位处于叠加态(硬币在空中)时,我们还不知道我们是将它分别测量为 0 还是 1(它是正面着地还是反面着地)。但是我们知道,某些自旋会影响我们是否用其中一个值来测量它的概率。我们知道所有概率的总和是 1。

因此,我们用一个归一化的矢量来表示量子位的自旋。我们称之为|𝜓⟩(“psi”)。这是狄拉克符号,它简单地表示一个列向量。

这个公式意味着量子比特的叠加态是一个归一化的矢量。所有可能的状态都起源于同一点,并且长度相同。因此,它们形成一个圆,如下图所示。

作者图片

矢量头到极点的距离表示将该特定量子位测量为 0(到南极的距离或接*北极)或 1(到北极的距离或接*南极)的概率。

量子位状态向量可以直接指向北极。这是|0⟩.那么,有 1 (=100%)的概率测得为 0。如果量子位状态向量指向南极,那么有 1 的概率测得为 1。量子位状态向量可以指向圆心周围的圆上的任何一点,|𝛼|测量它的概率为 0,|𝛽|测量它的概率为 1。我们通过𝜃,北极|0⟩和状态向量之间的角度来区分状态向量。

𝜃角代表硬币两面的旋转。它不断地从正面翻转到反面。

就像硬币可以沿着边缘旋转一样,量子位也可以沿着不同的方向旋转。我们使用希腊字母“phi”(𝜙)来围绕中心跨越另一个与第一个圆正交的圆。

作者图片

这两个圆围绕中心形成一个球体。这个球面被称为布洛赫球面。布洛赫球提供了单个量子位的视觉参考。布洛赫球是一个很好的工具,可以让量子比特算符变得有意义。

布洛赫球有三个轴。Z 轴是垂直的,包含极点。记住,|0⟩州描绘的是北极。我们在这种状态下测量一个量子位为 0——总是这样。在南极的|1⟩状态下,我们测量一个量子位总是为 1。我们水*绘制 Y 轴。最后,X 轴是图中的对角线。

表示球体的一种方式是三维坐标系。然而,在量子计算中,我们只使用二维向量。但是向量里面的数字是复数。

复数是一个可以用𝑎+𝑏⋅𝑖形式表示的数,其中 a 是实部,𝑏⋅𝑖是虚部。𝑖表示满足等式𝑖= 1的虚数单位。因为没有实数满足这个方程,所以𝑎和𝑏⋅𝑖是相互独立的。因此,复数是二维的。

作者图片

因为𝛼和𝛽是复数,它们跨越一个*面。而一个二维数的二维向量可以组成一个三维球体。

当然,我们也可以使用量子位。但是,我们不能直接控制量子位是 0 还是 1。相反,我们控制量子位元在不同方向的旋转。我们在空中控制它。这里事情变得有点复杂。我们可以增加或减少旋转。我们可以完全逆转它们。我们可以从不同的角度来做这件事。有无数种方法可以改变量子位的自旋。因此,量子位元的运算子比传统位元的运算子多得多。

假设我们在|𝜓⟩.态有一个任意的量子位怎么才能改变呢?

首先,我们可以在其中一个轴上镜像它。这些操作符通常具有我们用作镜像的轴的名称。例如,X 操作符在 X 轴上镜像量子位状态向量。下图以图形方式描述了该运算符的效果。

作者图片

X 运算符的一个重要作用是,它将测量量子位的概率翻转为 0 和 1。因此,我们也知道 X 算子是非算子。

改变量子位状态的另一种方法是旋转。我们可以围绕任意轴旋转量子位状态向量任意角度。当然,我们通常使用三个主轴(X、Y 或 Z)中的一个。但是,我们并不局限于此。

作为一个例子,让我们围绕一个标准轴,Z 轴旋转我们的量子位。我们可以逆时针旋转四分之一圈,就像这样:

作者图片

我们称这个算符为 S 算符。我们也可以把它转回来(顺时针)。这是 S^T 的接线员。上标的 T 代表“转置”转置是我们用来变换矩阵的一个操作符。它翻转矩阵的对角线。简单地说,它切换矩阵的行和列索引。我们用矩阵符号来命名量子比特算符的原因很简单。它们是矩阵。

正如我们上面提到的,量子位状态是一个矢量。还有,有很多处理向量的方法。但是我们在量子计算中有一种特殊的方法。这就是矩阵乘法。如果我们用一个输入向量乘一个矩阵,输出就是另一个向量。矩阵乘法使我们能够改变量子位的叠加态,而不会使它崩溃。

结论

基本上,这就是为什么量子计算中有这么多数学的原因。量子态是矢量,算符是矩阵,我们用复数。

任何状态及其任何变化都涉及线性代数和矩阵计算。这与经典计算形成对比,在经典计算中,状态是二进制的(0 或 1),运算符(不是等)。)非常直观,也很容易在头脑中推理。

好消息是我们有电脑。没有人需要手动乘矩阵。甚至我们的经典电脑也很擅长这个。正如这两个例子所示,我们可以不用解公式或乘矩阵就能推理量子算符。

作者图片

所以,理解量子计算不需要成为数学家。但是你将不得不应付线性代数,因为它是量子计算的基础。通过一点点练习,你将能够在不咨询数学的情况下说出许多变换的效果。然而,当事情变得棘手时,数学是你的盟友。

量子机器学习要不要入门?看看 动手量子机器学习用 Python

免费获取前三章这里。

LightGBM 能跑赢 XGBoost 吗?

原文:https://towardsdatascience.com/can-lightgbm-outperform-xgboost-d05a94102a55?source=collection_archive---------24-----------------------

助推技术

机器学习中的助推算法——第五部分

道格·达菲在 Unsplash 上拍摄的照片

到目前为止,我们已经讨论了 3 种增强技术: AdaBoost 、梯度增强和 XGBoost 。我们已经知道 XGBoost 比我们到目前为止讨论过的其他 boosting 算法更强大。

LightGBM(光梯度增强机)是 XGBoost 的一个很好的替代品。它是由微软开发的,在几年前的 2016 年发布。

由于 LightGBM 在集合中创建新树时采用了不同的方法,因此 LightGBM 具有以下独特的功能:

  • 运行速度比 XGBoost 快
  • 使用较少的内存
  • 可以处理大型数据集
  • 可以处理数据集中缺失的值
  • 可以处理尚未编码的分类特征

今天,我们将学习 LightGBM 库的安装,并探索它的 Python API。关键部分是我们将使用 XGBoost 和 LightGBM 算法在同一个数据集上创建两个模型,并比较每个算法的性能和执行时间。

我们开始吧!

照明设备的安装

我们可以通过在 Anaconda 提示符或 Google Colab 编辑器中运行以下命令来安装 LightGBM。

**pip install lightgbm**

然后运行以下命令并验证安装。

**import lightgbm**

如果您没有收到任何错误消息,那么您已经成功安装了 LightGBM!

LightGBM 的 Python API

LightGBM 的 Python API 由几个子 API 组成。我们将讨论其中的两个:

sci kit-学习 API

该 API 用于通过 Scikit-learn **实现 LightGBM 算法。fit()/。预测()**范式。这个 API 中最重要的类是:

  • LGBMClassifier()—light GBM 用于分类
  • LGBMRegressor()—light GBM 用于回归****

绘图 API

LightGBM 包在这个 API 下提供了一些绘图方法:

  • plot_importance() —绘制 LightGBM 模型的特征重要性
  • plot_metric() —在训练期间绘制一个度量

LightGBM 与 XGBoost

现在我们就来对比一下 LightGBM 和 XGBoost 的 性能执行时间 。为此,我们使用加州房价数据集执行回归任务。

LightGBM

这里,我们使用 LGBMRegressor() 类及其相关的超参数。我们还使用五重交叉验证来评估模型的性能。

LightGBM —性能和执行时间

(图片由作者提供)

LightGBM 的执行时间是 0.608 秒。数据集有 20640 行和 8 个特征!所以,LightGBM 真的很快。

XGBoost

这里,我们使用 XGBRegressor() 类及其相关的超参数。我们还使用五重交叉验证来评估模型的性能。

XGBoost —性能和执行时间

(图片由作者提供)

XGBoost 给出的 RMSE 略好于 LightGBM 给出的 RMSE。但是,XGBoost 任务需要 4.660 秒才能执行。比 LightGBM 慢了 7.66 倍!

LightGBM 的绘图功能重要性

这里,我们使用 LightGBM 绘图 API 的 plot_importance() 类来绘制我们之前创建的 LightGBM 模型的特性重要性。

**lgbm.fit(X, y)
lightgbm.plot_importance(lgbm)**

(图片由作者提供)

特征人口AveBedrms 对模型来说似乎不太重要。因此,您可以删除这些要素并重新构建模型以降低 RMSE。

结论

light GBM 能跑赢 XGBoost 吗? 答案在这里。

就性能而言,LightGBM 并不总是优于 XGBoost,但它有时会优于 XGBoost。至于执行时间,LightGBM 比 XGBoost 快 7 倍左右!

除了更快的执行时间,LightGBM 还有另一个很好的特性:我们可以在 LightGBM 中直接使用分类特性(不需要编码)。但是,数据类型转换(对象数据类型→ 类别数据类型)需要手动完成。

在下列情况下,LightGBM 优于 XGBoost。

  • 你想在比赛中快速训练模型。
  • 数据集很大。
  • 您没有时间对数据集中的分类要素(如果有)进行编码。

今天的帖子到此结束。在第 6 部分的中,我们将讨论 CatBoost(分类增强),XGBoost 的另一种替代方案。下一个故事再见。祝大家学习愉快!

我的读者可以通过下面的链接注册成为会员,以获得我写的每个故事的全部信息,我将收到你的一部分会员费。

****https://rukshanpramoditha.medium.com/membership

非常感谢你一直以来的支持!

特别要感谢 Unsplash 网站上的道格·达菲,为我提供了这篇文章的封面图片。

鲁克山普拉莫迪塔
2021–10–29****

机器学习可能“公*”吗——这到底意味着什么?

原文:https://towardsdatascience.com/can-machine-learning-ever-be-fair-and-what-does-that-even-mean-b84714dfae7e?source=collection_archive---------45-----------------------

来源: Unsplash

对一个有争议问题的技术探讨

机器学习已经开始渗透到生活的方方面面——甚至是那些受反歧视法保护的领域。它被用于招聘、信贷、刑事司法、广告、教育等等。

然而,让这成为一个特别困难的问题的是,机器学习算法似乎更具流动性和无形性。复杂机器学习算法的部分设计在于它们难以解释和监管。机器学习公*性是一个新兴领域,旨在将抽象的“公*”原则融入机器学习算法中。

我们将从三个方面来看待“公*”的概念和观点。虽然还有很多要探索,这三个代表了公*研究中三个有趣的发展和观点:一个统计的单一模型解决方案;机器学习公*性的更多模型和更像人类的概念;质疑公*是否可能。

  1. “无知的公*”和人口均等的不足:一个统计解决方案
  2. 可解释的公*:超越一种模式扩展公*
  3. 机器学习公*是不可能的吗?可能

“无知的公*”和人口均等的不足:一个统计解决方案

假设有一群狗住在小狗城;一家公司的客户支持代表的新工作已经开放,该公司希望使用机器学习来做出招聘决定。该公司表示,通过使用机器学习,他们将能够减少招聘经理决策过程中的偏见。

但是有一个问题——小狗城市反歧视法禁止根据狗的品种进行雇佣。因此,该公司做出了一个简单的解决方案:他们只是不会将狗的品种作为机器学习模型的一个特征。因此,他们将狗的品种标记为受保护的 T2 属性 T3。这种策略被称为“无意识中的公*”。

然而,冗余编码的问题出现了——数据集中说明受保护属性的特征。例如,公司可能基于两个主要特征进行招聘:

  • 狗狗大学 GPA(他们需要聪明,思维敏捷)
  • 狗说话的音调和语调(它们将整天与顾客交谈)

然而,(举个例子)德国牧羊犬的声音更低沉,而吉娃娃的声音更高。在狗学院,德国牧羊犬通常比吉娃娃狗获得更好的 GPA,因为狗社会的不*等。因此,完全有可能根据现有的特征来预测狗的品种。

鉴于这些复杂的模型常常掩盖了它们复杂的内部思维过程,我们如何知道模型是否依赖于狗的品种来做决定呢?

人口统计均等是一种衡量受保护属性是否真正受到保护的方法。简单来说,目标属性 y 和被保护属性 p 之间应该没有关联。作为一个等式:

**probability** *y*=1 **given** *p*=0 **is equal to probability** *y*=1 **given** *p*=1

(注意——我们假设 yp 在这里是二进制的。)

用人口均等来衡量公*有两个问题:

  • 不能保证公*。我们可以在 p=0p=1 中只接受不合格的候选人或拒绝合格的候选人,以使百分比匹配。如果一个组中缺少训练数据,这很容易发生。
  • *它限制了性能。*尽管事实上我们需要机器学习模型才能公*,但它们需要表现良好。如果 p 真的提供了预测 y 的重要信息呢?—优化人口统计均等将显著降低绩效。

在《监督学习中的机会均等》一书中,莫里茨·哈特、埃里克·普莱斯和内森·斯雷布罗提出了另一种保护受保护属性的方法。它试图通过允许高性能同时防止受保护属性 p 方面的歧视来解决人口均等的两个限制。

他们引入了均等赔率的概念,即

**probability** *y = 1* **given** *p = 0* **and** *actual y = Y* (the real target)**is equal toprobability** *y = 1* **given** *p = 1* **and***actual y = Y* (the real target)

本质上,在 p=0p=1 之间,模型应该具有相同的真阳性率假阳性率。当它预测 y=1 (通常类似于“是的,雇用”或“是的,批准贷款”)时,它应该在每组中做出与错误预测一样多的正确预测。

与人口均等或“无意识公*”相比,均等机会是一种更微妙的公*观;它允许模型使用受保护属性 p 中的信息,同时防止模型以歧视的方式滥用 p

通过在均等赔率上优化模型,该模型将在能够达到良好性能的同时相对于 p 更加公*。

这是考虑到关于受保护属性的公*性的更统计的观点;然而,它有一种机器学习的味道,因为它还允许模型从受保护的属性中提取更多潜在的洞察力。虽然这肯定不是一个完美的解决方案,但肯定是一个有效的解决方案。

均衡赔率的一个变体,机会均等,现在是机器学习模型中衡量公*性的标准。

在这里阅读全文: 监督学习中的机会均等

可解释的公*:超越一种模式扩展公*

看待公*还有许多其他方式。“可解释的公*”是一种更少依赖于统计测量的方法——不像均等的优势——而是利用更多的机器学习。

如果一个代理模型——一个与原始模型相似的模型——不能产生一组解释来反对模型的公*性,那么这个模型就是可解释公*的*。*

首先需要理解什么是代理模型。就像代孕母亲怀上另一对夫妇的孩子一样,代孕模特 S 模拟另一个模特c的结果

代理模型可以通过几种方式导出,但通常是通过重复采样数据点,查看模型 C 预测什么,并尝试模仿 C 的预测行为来完成的。

由作者创建。

然而,仅仅因为代理模型 S 模仿模型 C 的输出并不意味着它们的“思维过程”是相似的。(最*对欠规范的研究证明情况往往如此。)

例如,一个阿拉斯加人和一个厄瓜多尔人可能都不想在温和的天气外出,但出于不同的原因:阿拉斯加人认为天气太热,而厄瓜多尔人认为天气太冷。

的确,这既可以是弱点,也可以是优势。通过使用代理模型,我们掩盖了特定模型背后的“思考过程”。与此同时,我们也允许不同类型的模型——具有不同“经验”和“思维方式”的模型——提供关于公*的输入。

事实上,这可以被认为是一个力量的来源:如果我们对原始模型有多个代理模型,我们可以为一个模型的行为找到许多解释,因为代理模型从来都不是完美的。每种类型的代理模型在算法和特征上应该是不同的,因此它们对原始模型的决策做出不同的假设和解释。

这种更“全球化”的看待公*的方式可能更符合人类对社会公*的观念。例如,人 B、C 和 D 可能认为人 A 说的话是冒犯性的,即使人 A 不是故意的。在这种情况下,社会团体可能会谴责个人 a。毕竟,我们是社会动物——我们的观点经常受到周围其他人和社会的影响。

(虽然,这个是否应该是这样是一个有趣的争论。)

在代理模型被导出之后,它的均衡优势——或者任何其他种类的公*性度量——被测量。如果代理模型发现代理模型是公*的,那么原始模型被认为相对于代理模型是可解释公*的。如果使用多个代理模型来确定可解释的公*性,这种方法是强有力的。

“可解释的公*”并不能保证统计上的公*——正如引入这一概念的论文作者所承认的那样。然而,它确实将公*的作用扩展到一个算法或模型之外,并使公*的愿景变得复杂,可以用一个单独的指标来表达。

在这里阅读全文: 通过可说明性和对抗性实现公*的 SHAP 学习

机器学习公*是不可能的吗?可能

当然,这些公*的观点和概念都是以机器学习可以公*为前提的。然而,有些人认为这可能不是一个有效的假设。

Soralle A. Friedler、Carlos Scheidegger 和 Suresh Venkatasubramanian 在他们的论文《论(不)公*的可能性》中提出了这一主张,并断言…

“…为了证明整个决策过程的理想属性,不同的公*机制需要对从构造空间到决策空间的映射性质做出不同的假设。”

论文依赖于空间的概念。

  • 构建空间包含我们希望决策所基于的特征。例如,智力可能是我们希望招聘工作的一个特征。
  • O 观察空间是我们可以观察到的关于构造空间的不完美特征。例如,*均绩点、智商或标准化测试分数可能是智力的*似特征。
  • 决策空间包括可能的结果。例如,招聘的决策空间可以是雇佣/不雇佣。

决策算法的目标是将构造空间映射到决策空间。然而,由于构造空间只能由观察空间真正测量,第一步是通过将构造空间映射到观察空间来“提取”使用数据。简单来说:

Construct space → Observed space → Decision space

每个代表前一个空间到下一个空间的某种变换

现在,考虑两个关于公*的基本世界观:

  1. 所见即所得(WYSIWYG) 。建构空间和观察空间本质上是相同的;失真(信息从一个空间移动到另一个空间被改变)是最小的。例如,SAT 分数和高中 GPA(观察到的空间特征)可能与申请人在大学取得成功的能力(构建空间特征)密切相关。
  2. 结构性偏差。建构空间和观察空间被严重扭曲。我们希望捕捉组之间的相对失真,而不是以同样影响所有组的方式缩放。
    这里的假设是我们都是*等的(WAE)——所有的组在构造空间看起来都是一样的,即使组在观察空间看起来不是这样。
    例如,持有结构偏见的世界观,我们会断言耷拉着耳朵的小狗和竖起耳朵的小狗都能够变得友好,即使在观察空间中耷拉着耳朵的小狗被报道为更加友好。

考虑到这两种世界观,在 WYSIWYG 下,模型总是公*的,因为我们假设构造空间可以以最小的失真映射到观察空间。(这一主张——以及所有其他主张——在论文中得到了更严格的证明,论文链接如下。)

与此同时,在 WAE 下,这种模式可以永远是非歧视性的。组公*机制可用于将构造空间映射到观察空间,使得即使给定结构偏差,也能校正组之间的距离*。在小狗的例子中,这意味着竖起耳朵的小狗群体会像观察空间中松软的小狗群体一样友好。*

请注意,不歧视不同于公*。在统计方面,不歧视更多地适用于群体,而公*更多地适用于个人。

作者得出结论公*只能发生在所见即所得的世界观下

在 WAE 和结构偏差的情况下,必须应用一个组公*机制-而不是一个单独的机制,以使算法是非歧视性的。如果我们不应用群体公*机制,那么我们就违背了我们首先人人*等的主张,因为群体差异没有得到纠正。

在结构性偏见的世界观下,只有群体公*机制才能实现非歧视,而个体公*机制则具有歧视性。另一方面,在所见即所得的世界观下,只有个体的公*机制才是公*的。

因此,每一个试图将建构空间映射到观察空间的机制——以测量决策所需的真实特征——都明确地与两种矛盾的世界观之一联系在一起。因此,一个机制不可能既在个人意义上公*,无歧视。

在这里阅读全文:https://arxiv.org/pdf/1609.07236.pdf【论公*的(im)可能性】

结论

公*的问题已经伴随人类很长一段时间了,因为我们仍然在努力理解它的含义,我们正试图将其形式化,供我们的机器学习对手使用。关于机器学习中的公*性,在机器学习社区中仍然存在长期的激烈争论和辩论。

本文介绍了三种实现公*的方法:

  1. 作为更传统的人口统计均等和“无知的公*”观点的一种替代,均等的机会。允许模型从受保护的属性中学习,同时不歧视它。
  2. 更加基于机器学习的公*概念依赖于试图模仿原始模型的其他代理模型的解释和审计的角色。
  3. 将算法理解为空间之间的映射的理论方法,表明所有不同的公*和不歧视概念依赖于矛盾的世界观。

我很想听听你们的回答:

  1. 这样的标准真的公*吗?如果一个受保护的属性包含在模型的训练数据中,那么它甚至有可能保护该属性吗?处理“不知不觉中的公*”的缺点是否比冒险将模型暴露给受保护的属性更好?
  2. 关于可解释的公*性 —使用代理模型假设全球解释的某些方面对公*性很重要。是这样吗?这是某种道德相对主义吗?代理模型带来的这种增加的噪声是否在某种程度上降低了公*性?
  3. 论公*的不可能性——依赖于矛盾假设的不同公*概念实际上否定了公*的可能性吗?这篇论文本身是否做了任何假设?再者,这篇论文非常理论化——这种形式化和僵化是否限制了它对公*和歧视的理解?

感谢阅读!

我最*推出了一个新的播客,ML & DS Papers On The Go。播客的目标是让您在旅途中也能听到最迷人和最新的进展——这是一个赶上最新研究趋势和发展的好时机!

点击 Spotify 查看。请随时联系LinkedIn——我仍在探索如何导航播客空间,所以我很乐意与你联系并听取你的反馈。请关注不久的将来的一集,作为对本文所讨论主题的进一步探索。

机器会做梦吗?

原文:https://towardsdatascience.com/can-machines-dream-2fdf7afa7fdb?source=collection_archive---------30-----------------------

Jr Korpa 在 Unsplash 上拍摄的照片

围绕风格转移的理论和概念的描述和实现(以几个例子为特色)。

查看我的 GitHub 的工作风格转移代码库。

一个你肯定没想过要问的问题。当然,除非你和一个朋友在凌晨 4 点刚刚看完 iRobot。

然而,我们现在……在一个机器在做梦的世界里……有点。

好消息是你不需要担心。虽然这些算法的输出可能非常怪异(我鼓励你谷歌搜索“深度梦境”)。它们完全依赖于输入,这是机器学习的准则。

所以我们不会做任何邪恶的梦,除非我们一开始就给它灌输一些非常恶心的东西。

我们用来描述这种行为的术语是神经风格转移[1]。

它包括给神经网络一个内容图像和一个样式图像。然后要求它以样式图像的样式重建内容图像。

动机

我发现任何深度学习概念的一个迷人之处是它的生物学根源。

照片由 v2osk 在 Unsplash 上拍摄

为了理解神经风格转移如何工作,我们需要理解卷积神经网络(CNN)如何工作。为了理解 CNN,我们需要了解我们自己的视觉皮层是如何工作的。

这听起来像是一项巨大的工作,但老实说,理解起来超级简单。还有很多听起来很聪明很酷的词,这样你就能给最好的人留下深刻印象!

眼睛和大脑

我们的眼睛不可思议,更不可思议的是我们的大脑。我们的大脑是我们意识和潜意识的中心。

你可能已经知道,眼睛通过我们的视觉皮层向大脑提供信息,然后大脑皮层形成我们的视觉。

但是真正有趣的是大脑如何建立我们的视觉。

Robina Weermeijer 在 Unsplash 上拍摄的照片

有无数的神经元连接着眼睛和我们的视觉皮层。一端是单个细胞(视杆细胞和视锥细胞),每个细胞负责我们视觉的一小部分。而在另一端,我们对世界有一个完全成形的、无缝的(在大多数情况下)视觉感知。

Hubel 和 Wiesel 在 20 世纪 60 年代和 70 年代发现了我们的视觉是如何形成的线索。他们用猫做实验,给猫看一条不同角度的光。当分析 V1 神经元(连接到初级视觉皮层的神经元)的放电率或激活时。他们发现这种神经元的放电频率和光条的旋转之间存在相关性。

这是一个如此惊人的发现,因为它表明不同的神经元负责从我们从眼睛接收的视觉输入中检测不同的模式。

图 1:大脑的视觉输入图。

图 1 显示了我试图解释的内容的一个粗略的手绘示意图。这里我们有 4 个不同的神经元连接到大脑,每个神经元对一条线的特定方向做出反应。

在我们继续之前,让我们把一些机器学习术语放入其中……神经元发现的这些非常简单的特征就是我们所说的,低级特征。与更复杂的高级功能相反。

所以我们有一些低级的特征,这些特征是我们所看到的一切的基本组成部分。你可以想象有数百万个这样的特征。

照片由哈维·卡夫雷拉在 Unsplash 拍摄

这有点像当你打开一个新的乐高玩具时,你有上百万种不同类型的砖块可以玩,并放在一起,以构建高水*的功能。

这正是我们的大脑所做的。这些神经元连接到更多的神经元,这些神经元已经学会识别从其输入建立的特征,如图 2 所示。

图 2:显示构建更高级特征的两层神经元的图。

图 2 向我们展示了一个非常简单的例子,展示了我们可以利用低级特征构建的一些结构。

就我们的乐高套装而言,我们正在组装第一对积木,并想象我们可以建造什么!

图 3:显示简单的房子或船如何被视觉通路中的高级神经元识别的图。

更进一步,我们可以看到每一层新的神经元是如何构建更复杂的(或更高级别的)结构的。

这里我们有几张相当不错的房子和船的画。这是我们的三级视觉通道现在能够识别的。

因此,当大脑通过这两个神经元接收到一个脉冲(或动作电位)时,这意味着在我们的视觉感知中,有一所房子和一艘船。或者如果这只是一个冲动,那么它要么是一栋房子一艘船取决于哪一个,你明白了吗?

随着每一个新的层次,我们允许我们的大脑开始构建我们的完整视觉。或者完成我们的千年猎鹰乐高套装,如果我们回到乐高类比。

从眼睛到…CNN?

是的,这里还有更多好消息!

如果你看了最后一部分(希望你看了),那么你已经知道 CNN 是如何工作的了!

回过头来看一下图 3…我们需要做的就是给这个图添加一些数学符号,并将其重新构建为机器学习和 viola 中的神经网络!

CNN 的来龙去脉是一些广泛研究的主题,我们不会在这里深入探讨。但是有几篇优秀的媒体文章和发表的论文围绕这个主题,所以如果你感兴趣,我鼓励你四处搜索。

对于本文,您只需要知道 CNN 通常由几个卷积层组成,这些卷积层负责构建我们上面探讨的更高级的功能。然后通常是一些层,用来缩小图像的尺寸,迫使 CNN 寻找更高层次的特征。

图像的风格和内容

再看图 3,你认为内容和风格存在于这个非常基本的神经网络中的什么地方?

这里要考虑的更明显的是内容,因为像房子和船这样的高级特征最有可能代表图像的内容。而不是一行或一些非常低级的细节。

照片由斯蒂夫·约翰森在 Unsplash 上拍摄

另一方面,让我们想想图像的风格是什么…想象一下我刚刚画了一幅绝对的杰作,就像这里看到的一样…

这幅图像风格的一大贡献者是笔触。

笔画可以是图像的大特征,然而与图像的内容相比,它们是相对低级的特征。

因此我们可以想象图像的更多的样式表示将位于图 3 的左侧。或者 CNN 中每个卷积层的较低层。

现在让我们来看看一个实际的 CNN 架构。

图 4:来自[2]的 VGG-19 架构。

图 4 显示了在[3]中开发的著名的 VGG-19 模型的架构。输入从左边输入,输出在右边反馈给我们。在中间,我们所有的神经元结合在一起识别低级到高级的特征。

在每个卷积层(图 4 中的绿色阴影),我们重复前面描述的过程。在卷积层的第一维(低级)中搜索简单特征,直到卷积层的最后一维(高级)中的更复杂特征。然后,我们有一个最大池层,减少了图像的大小,我们再次重复这一过程。

照片由 Siora 摄影在 Unsplash 拍摄

这些最大池层是非常重要的,因为当他们减少了图像的大小,我们失去了图像的细节。因此,在每一步中,我们自然会看到更大的特征。

这些最大池层是非常重要的,因为当他们减少了图像的大小,我们失去了图像的细节。因此,在每一步中,我们自然会看到更大的特征。

我们还注意到,每个卷积层的深度从左向右增加。这是因为我们在更大的尺度上发现了更复杂的特征,这些特征对图像内容来说比在较低的级别上更重要。例如,一个真正复杂的笔触或铅笔标记没有画出的整体形状重要。

很明显,每个图像都是不同的,所以不容易定义一个特定的层,每个层都是不同的,也不容易在 CNN 中定义一个特定的点来最好地定义图像的内容。然而,作为一个经验法则,我们通常不期望内容在非常小的范围内,或者在非常大的范围内。介于两者之间通常是一个很好的起点。

关于风格,这可以在任何尺度上表现出来,因此在每个卷积层进行一些加权是一个好主意。然而,正如我们有希望证明的那样,在卷积层开始变得更加复杂和更加基于内容的表示之前,尽早在卷积层中选择样式层也是一个好主意。

生成图像

为了生成图像,我们必须首先选择包含我们的内容和风格的图层。我们将选择我们的:

content = "conv4_2"style = {
        "conv1_1": 1.0,
        "conv2_1": 0.75,
        "conv3_1": 0.2,
        "conv4_1": 0.2,
        "conv5_1": 0.2
    }

注意,这些对应于图 4 中的标记。

与样式层相关的数字是我们希望赋予每一层的权重。所以我们希望风格更多地由最底层的conv1_1层决定,而不是其他层。但是同样,这是可以根据您的输入和偏好来玩的东西。

由克莱门特·赫拉尔多在 Unsplash 拍摄的照片

现在,我们将把我们的内容和风格图像分别传入我们的 CNN。当我们这样做时,我们可以找到内容层conv4_2基本表示,以及分别用于内容和样式图像的每个样式层。

现在我们有目标了!

基本上,我们希望有一个通过 CNN 的图像,并再现我们在通过样式图像时为我们选择的样式层找到的相同样式表示。然后,当通过内容图像时,我们为我们选择的内容层找到了相同的内容表示。

这就是乐趣的开始…

首先,我们需要一个形象的起点。由于我们最有可能尝试制作一个看起来更像我们的内容图像但风格不同的最终产品,我们将继续为我们的初始输入制作一个内容图像的副本。

在这一点上,我们稍微偏离了你可能习惯的通常的机器学习设置。我们实际上不是在训练模型,我们实际上是在训练图像。

因此,我们没有将反向传播图与 CNN 的权重联系起来,而是实际上将它与输入图像(单个像素)的权重联系起来。

这样,当我们发现从输入图像中找到的所选特征和我们之前准备的基本特征之间的内容和风格损失时。执行反向传播将导致输入图像略有变化,而不是 CNN。

这不是一件容易解释的事情,所以我鼓励你花几分钟时间浏览一下我的GitHub上的代码示例,特别是在 algorithms/style_transfer.py 文件中。

我们会失去什么?—更数学一点…

我们现在只需要一个损失函数。

我们将从内容损失开始,因为这稍微更容易解释,因为它只是来自具有基本内容图像(C)和新图像(X)的“conv4_2”的特征映射之间的均方误差。

图 5:内容损失方程

这仅仅是惩罚与内容图像的基本表示中发现的特征的任何偏离。

现在对于图像的风格,我们需要简单介绍一下 Gram 矩阵。这些听起来比它们实际上要复杂得多,所以为了本文的目的,我将简单地把它们描述为高维点积

直觉告诉我们,对于风格,我们并不真的想要在我们图像的完全相同的地方重新创建完全相同的笔触。我们只是想在整个图像中有一个类似的风格。因此,最好根据样式表示的相似程度来计算损失,就像余弦相似度或点积一样。

当然,我们必须记住,我们使用的是特征地图,它的维度比通常的点积要高。所以我们实际上需要使用一个 Gram 矩阵来封装输入 X 的风格和基本风格图像 s 之间的相关性

图 6:风格损失方程。

图 6 显示了封装到一个公式中的内容。其中每个选择的样式层的 gram 矩阵的 MSE 损失乘以它们的权重(在上面的代码块中定义),然后求和。

最后我们得到一个总损失函数,

其特征在于α和β超参数乘以损耗。这些决定了风格在最终图像中的应用程度,留给我们自己去定义。

摘要

一旦我们具备了所有这些特征,我们就可以开始训练了,结果令人难以置信!

这里有几个空间主题的例子…

如果你想尝试一下, GitHub 上的代码应该很容易使用。只需将您自己的图像添加到 content and style 文件夹中,然后使用新文件名运行代码。

一如既往,让我知道任何问题或意见!

参考

[1] — L. A. Gatys,A. S. Ecker 和 M. Bethge,一种艺术风格的神经算法,(2015)

[2] — D. H. Hubel 和 T. N. Wiesel,猫视觉皮层的感受野、双眼互动和功能结构,(1962)

[3] — K. Simonyan,A. Zisserman,用于大规模图像识别的甚深卷积网络,(2015)

网络课程能让你成为数据科学家吗?

原文:https://towardsdatascience.com/can-online-courses-make-you-a-data-scientist-4a34ca85fa6f?source=collection_archive---------58-----------------------

意见

成为数据科学家没有捷径

托拜厄斯·菲舍尔在 Unsplash 上的照片

作为一名科学家,我们可能都已经知道这一职业。哈佛商业评论报道称,这一职业曾被称为https://hbr.org/2012/10/data-scientist-the-sexiest-job-of-the-21st-century“21 世纪最性感的工作”。尽管数据科学家的趋势比前几年有所下降,但是,数据科学家仍然是一个需求量很大的职业。

目前,大学、课程或其他地方有许多课程提供成为数据科学家的课程。广泛用于学习数据科学的工具之一是参加在线课程( UdemyCourseraDatacamp 等)。).原因是,与我们必须参加讲座相比,时间相对较短,我们可以随时随地访问它。

“网络课程能让你成为数据科学家吗?”

在回答这个问题之前,我们必须首先了解成为一名数据科学家需要具备哪些条件。基本上,成为一名数据科学家需要具备两个主要的东西,即硬技能和软技能。

一般来说,硬技能包括数学、统计学和编程技能。当然,这种能力是数据科学家必须具备的义务。然而,这还不够。除了掌握硬技能,我们还需要掌握软技能。其中一个原因是由于技术的快速发展在这个时代,数据科学家可以使用许多工具来处理数据、进行建模等。此外,这个职业还有一个重要位置决定一个公司的商业模式。

以下是成为数据科学家通常使用的软技能。

  • 业务理解—数据科学家必须能够深入理解正在开展的业务。有些人可能会问,“为什么数据科学家应该了解业务,而他们的工作是处理数据?”。要处理数据,我们必须了解我们拥有的数据,并从这些数据中获得洞察力。数据科学家需要对正在执行的业务流程有深刻的理解。
  • 对数据有直觉——数据科学家必须能够高效地完成工作。所以,数据科学家必须对数据有一种直觉。这里的直觉是指从数据中发现某些模式的能力。这是因为数据科学家将面临许多处理数据的方法。通过了解数据的模式,数据科学家可以节省时间来选择最合适的方法。
  • 翻译技术语言—数据科学家可以说是技术团队和业务团队之间的中间人。因此,数据科学家必须能够将技术语言翻译成业务语言。因此,沟通能力对数据科学家来说也很重要。

正如我之前所说,要成为一名数据科学家,我们需要两项主要技能,即硬技能和软技能。总的来说,目前大部分在线课程更侧重于硬技能,如如何进行数据清洗、分类、聚类、可视化等。

然而,我们很少在网络课程中发现其他技能(软技能)。因为在网上课程中,我们倾向于只听从老师的解释。除此之外,这些技能也不是我们能瞬间获得的。也就是说,为了掌握这些技能,我们必须大量练习,并获得经验来磨练我们的能力。

要磨练这些技能,我们光靠网络课程是不够的。我们还需要通过做真实的项目来练习。为什么?通过参与一个真实的项目,我们将练习如何解决问题。你会意识到现实世界中的数据没有我们上网络课程时处理的数据漂亮。

如果你觉得不自信,或者在真正的项目中仍有困难,你可以请人做你的导师,或者参加训练营。这样,有人会给你关于你正在做的事情的反馈。

同样作为信息,如果有一天你申请一份数据科学家的工作,你很可能不会被问你学了多少门课程或者你有多少证书,而是你做过什么项目,你是如何处理项目的。

结论

在线课程不会让你马上成为数据科学家。然而,在线课程可以帮助你入门,特别是如果你没有数据方面的背景。通过参加在线课程,你可以了解数据科学家在做什么。

然而,如果你想成为一名专业的数据科学家,你还必须训练你的软技能,而这些不能仅仅通过参加在线课程来获得。你必须通过从事真正的数据科学项目来训练它。

QR 分解实际上能更快吗?Schwarz-Rutishauser 算法

原文:https://towardsdatascience.com/can-qr-decomposition-be-actually-faster-schwarz-rutishauser-algorithm-a32c0cde8b9b?source=collection_archive---------12-----------------------

Arthur V. Ratz 摄于 Shotstash

在这个故事中,我们将讨论如何通过使用 Schwarz-Rutishauser 算法(已解释)有效地优化大型矩阵 QR 分解的性能,介绍其在 Python 3.9.x 和最新的 NumPy 1.20.x 库中的实现…

介绍

QR 分解是最新的,也可能是最有趣的线性代数算子之一,在科学和工程的许多领域有一些已知的应用。QR 分解方法的相关研究始于 XX 世纪初。

今天,一整类 QR 分解方法在数学中被有效地用于解决线性最小二乘(LS)问题,解线性方程组,以及特征值和奇异值分解(SVD)计算方法的基本步骤**【1】**。

在过去的几十年中,不断发展的计算机科学和 IT 领域影响了研究人员对 QR 类算法的潜在兴趣,这有利于解决许多现有的现实世界问题。

AI数据挖掘的时代,QR 算法在数据科学的各个领域得到了应用,例如主成分分析(PCA) ,作为一种在经济科学**【1,3】中执行系统参数或总体估计的分析时,根据可能具有解释性的因素来表示参数幅度的方法。例如,因子分解可以有效地用于分析工业机器和机械装置的振动水*【7】**。

以因子的形式表示各种类型的参数提供了一种能力来确定什么对总体评级和估计值具有特定的关键影响。具体而言,因子分解技术提供了获取知识和见解的能力,这些知识和见解在数据挖掘中常用的统计数据集上展示。

在电子商务和在线交易中,统计数据分解方法被应用于各种基于人工智能的分析软件功能的开发,被商家用来有效地涵盖他们的业务,从而增加受欢迎程度并降低数字内容和服务的成本,向数十亿在线客户做广告**【8】**。

然而,现有的大多数 QR 算法都具有非常高的计算复杂度,对大规模矩阵和其他大数据分解过程产生负面影响。显然,这些算法是为了在数据分析中使用它而优化的。

在这个故事中,我们将深入讨论如何优化著名的 Gram-Schmidt 正交化过程**【1】,在即将推出的 Schwarz-Rutishauser 修正【5】**的基础上显著降低其复杂度。

此外,我们将调查 Schwarz-Rutishauser 算法的复杂性,将其与其他现有的 QR 分解方法进行比较,如经典的 Gram-Schmidt 过程和 Householder 反射**【1,4】**。

此外,这个故事在底部包含了工作示例和到一个开源项目的 GitHub 库的链接,这个开源项目包含了 Python 3.9.x 和最新的 NumPy 1.20.x 库,实现了所讨论的 Gram-Schmidt、Householder 和 Schwarz-Rutishauser 算法,提供了所有这些方法性能的总结。

QR 分解

QR 分解是将实数或复数矩阵 A (m x n) 分解成正交矩阵 Q 和上三角矩阵**R【1】**的乘积,例如:

通常,矩阵𝙌的计算产生矩阵𝘼**【1,4】**的因式分解,例如:

在下面的段落中,我们将彻底讨论矩阵𝙌和𝙍最常见的性质**【4】**。

正交矩阵 Q:

通常,正交矩阵𝙌的计算导致矩阵𝘼**【4】的分解,因此完全分解和部分分解都存在。QR 分解不仅可以应用于正方形矩阵,也可以应用于矩形矩阵,即使矩阵不具有满秩。大多数情况下,𝘼的完全因式分解给出了与𝘼矩阵形状相同的𝙌矩阵,或者至少𝙌和𝘼的列数相等【5】。矩阵𝘼的因式分解是 QR 分解的一个有用属性,只要𝘼的元素必须用因式【1,3】**表示,就可以应用该属性。

根据其定义**【1】,𝙌是一个对称矩阵,由于正交特性 (1.2) ,与其转置相乘是一个单位矩阵𝙄。𝙌中的每个列向量都与其他向量正交。所有这些列向量构成了𝘼的标准正交基,这非常类似于将欧几里得空间ℝₙ中的每个列向量映射到不同空间ℝ'ₙ.的坐标系中术语“标准正交”是指𝙌中的正交列向量通过除以其欧几里德范数【1,2,6】**而被归一化。

上三角矩阵 R:

反过来,上三角矩阵𝙍可以很容易地作为矩阵𝙌's-transpose 和𝘼的乘积得到,所以𝙍是一个矩阵,它的所有子对角线都是0。具体来说,𝙍的计算导致𝘼的高斯消除,将其减少到行梯队形式**【1,4,5,6】。为了消除𝙍中对角线元素之后的元素,标量元素𝒓ᵢₖ、𝒓ₖₖ乘以希尔伯特环境空间ℋ【2】**中子空间ℏ的相应单位基向量𝒆ₖ。

上面提到的𝘼's 上三角矩阵𝙍被有效地用于求解线性最小二乘(LS)问题,以及寻找𝑨𝒙=𝒃线性方程组**【1】**的单个非*凡解。

一个普通的 2 乘 2 r eal 矩阵𝘼的 QR 分解可以描述为:

2 乘 2 *方实矩阵 A 的 QR 分解

列第一个和第列第二个列向量a₁(3;4)a₂(7;5) 、(红色)和(藏青色),如上图所示。

a) ,从左起,说明了列向量 q₁(-0.6,-0.8)q₂(-0.8,0.6) 、(金色)和(蓝色),作为矩阵𝘼分解的结果而获得。这些向量的长度必须总是等于 | 、𝙦 |=1 ,因此是正交单位向量𝙦.

向量 q₁q₂ 彼此垂直,因此是正交的。在最简单的情况下,这些向量中的每一个都可以通过将𝘼中的每一个列向量旋转 90°角来获得。具体的旋转可以通过将*凡的雅可比旋转矩阵乘以多向量𝘼.中的每一列来完成

对应的向量r₁(-5;——8.2)r₂(0;-2.6) 在𝙍,(金色)和(蓝色),分别标绘在图 b) 中,从右侧开始。与多向量𝙌的列不同,这些向量不是正交的。如上所述,这些向量是作为𝙍中的每个列向量分别与希尔伯特环境空间ℋ中的每个子空间的相应单位基向量𝒆₁和𝒆₂(绿色)的标量乘法的结果而逐列获得的。

已知的 QR 分解方法

目前,至少有三种现有方法广泛用于计算实矩阵和复矩阵的 QR 分解:

  • 格拉姆-施密特正交化
  • 户主的感想
  • 吉文斯旋转

上述每种方法都有自己的优点和缺点。例如,当用于复矩阵的 QR 分解时,Householder 反射通常非常复杂。反过来,Givens 旋转方法导致最终迭代次数的精度损失,并且在将其用于大型矩阵分解时效率低下。

在这个故事中,我们将讨论经典的 Gram-Schmidt 过程和 Rutishauser 算法。我们将以 Householder 反射法和 Givens 旋转法为例,仅用于评估目的,将这两种方法的复杂性与正在讨论的 Schwarz-Rutishauser 算法的复杂性进行比较。

在接下来的段落中,我们将讨论 Schwarz-Rutishauser 算法,它是 Gram-Schmidt 正交化过程中最成功的变体之一。

格拉姆-施密特正交化

Gram-Schmidt 过程于 50 年代中期提出,是用于实矩阵或复矩阵正交化的首批成功方法之一**【1,4,5,6】**。

这种方法广泛用于递归地寻找𝑨的正交矩阵𝑸,基于每个向量𝒂ₖ ∈ 𝑨,𝒌=𝟏的正交投影..𝒏到跨度矢量𝗾 ∈ 𝙌(𝒌)、𝒊=𝟏..𝒌,这是众所周知的。每个新的正交向量𝙦 ∈ 𝙌被计算为投影的和,从相应的向量𝒂ₖ ∈ 𝑨.中减去它最后,通过使用上面的等式 (1) ,可以容易地获得作为𝑸's-transpose 和矩阵𝑨的乘积的上三角矩阵𝑹。

通过使用下面的等式**(2)**获得𝒂到𝒒的正交投影:

通常,整个 Gram-Schmidt 过程产生一个正交矩阵𝙌,可以表示为:

,或者:

每个新的向量𝙦ₖ ∈ 𝙌最后通过除以它的欧几里德 norm|𝙦ₖ|.来归一化

下面的一段代码演示了经典的 Gram-Schmidt 过程的实现:

事实上,Gram-Schmidt 正交化过程比 Householder 反射或 Givens 旋转方法更直观简单。虽然,当应用于大规模矩阵的正交化时,它有许多缺点,例如数值不稳定,以及明显高于𝑶❨𝟐𝒎𝒏 ❩的高计算复杂度。此外,它需要基于确定矩阵的前导维数进行修改,以提供矩形 m 乘 n 矩阵正交化**【4】**的能力。

Schwarz-Rutishauser 算法

您可能已经注意到,经典的 Gram-Schmidt 正交化是一种非常复杂的算法,它是由每个向量𝒂ₖ ∈ 𝑨到向量𝗾 ∈ 𝙌(𝒌).的正交向量投影的计算引起的在这种情况下,正交投影算子的复杂度大约为𝑶❨𝟑𝒎❩,并且通常对 Gram-Schmidt 过程本身的整体复杂度有负面影响**【4】**。

显然,我们需要一种稍微不同的方法来进行𝑨的正交化,而不是计算𝒂ₖ-vectors 投影到𝙌(𝒌).上的倍数和

Schwarz-Rutishauser 算法是经典的 Gram-Schmidt 正交化过程的修改,由 H. R. Schwarz、H. Rutishauser 和 E. Stiefel 在他们的研究论文*“Numerik symmetrischer Matrizen”(Stuttgart,1968)*【6】中提出。以下研究旨在降低现有基于 Gram-Schmidt 投影方法的复杂性,并提高其数值稳定性【5】

Schwarz-Rutishauser 算法背后的主要思想是,与原始的 Gram-Schmidt 过程𝑶❨𝟐𝒎𝒏 ❩和 Householder 反射𝑶❨𝟐𝒎𝒏 -𝟬.相比,𝑨's 正交基计算复杂度可以大大降低𝟔𝒏 ❩方法**【5】**。

为了更好地理解 Schwarz-Rutishauser 算法,让我们从右边更仔细地看一下等式 (2 )和 (3.1) ,如上图所示。

在计算𝒂's 在跨度𝙌(𝒌上的投影和时,我们必须将向量的标量积除以范数|𝙦ₖ|的*方,实际上是将乘积**【2】**归一化。然而,这是不必要的,因为每个向量𝗾 ∈ 𝙌(𝒌)已经在之前的𝒌-th 算法步骤之一中被立即归一化。

据此,等式 (3.1) 可以通过从右侧的投影**【5】**的和中去除除以*方范数来简化:

由于𝑹是𝑸's-transpose 和𝑨的内积,那么我们可以很容易地计算每个列向量𝒓ₖ的𝒊-th 元素为:

这里𝗾 - 和𝒂ₖ-vectors 的标量积乘以希尔伯特环境空间ℋ**【2】**中对应*面的单位基矢𝙚ₖ。

最后,让我们将等式 (4.2) 代入 (4.1) ,这样我们就有了:

由于我们承认𝑸最初等于𝑨 ( 𝑸 =𝑨),基于上述等式 (4.2)(4.3) 的𝗾和𝒓的计算可以递归地进行**【5】**:

根据向量算术,为了得到每个新的𝒌-th 列𝙦ₖ ∈ 𝙌,我们从向量𝙦ₖ中减去向量𝗾 ∈ 𝙌(𝒌)和𝒓ᵢₖ的乘积,这是向量的拒绝。让我们回忆一下,向量𝙦ₖ最初等于𝒂ₖ (𝙦ₖ=𝒂ₖ).这就是为什么求和算子最终可以从方程 (4.3) 中去掉。

除了𝙦ₖ,我们还需要计算𝑹的𝒓ₖₖ 𝒌-th 对角线元素,如范数|𝙦ₖ|:

,然后,归一化新𝒌-th 列向量𝙦ₖ ∈ 𝙌,除以其范数,等于对角元素𝒓ₖₖ**【5】**。

最后,我们可以用公式表示 Schwarz-Rutishauser 算法:

  1. 初始化矩阵𝙌,等于𝑨 (𝙌=𝑨),𝑹为 0s 的矩阵;

2.对于每个𝒌-th 列向量,𝙦ₖ ∈ 𝙌,𝒌=𝟏..𝒏,请执行以下操作:

2.1.对于向量的跨度𝗾 ∈ 𝙌(𝒌)、𝒊=𝟏..𝒌,这是众所周知的:

  • 得到𝒌-th 列向量𝒓ₖ ∈ 𝑹的𝒊-th 元𝒓ᵢₖ,方程**(5.1)**;
  • 更新𝒌-th 列向量𝙦ₖ ∈ 𝙌,方程**(5.2)**;

2.2.继续前面的步骤 2.1,对向量𝙦ₖ进行正交化,得到𝒌-th 列向量𝒓ₖ;

3.计算对角元素𝒓ₖₖ作为𝙦ₖ-vector's 范数𝒓ₖₖ=|𝙦ₖ|,方程**(5.3)**;

4.归一化𝒌-th 列向量𝙦ₖ ∈ 𝙌,除以其范数,等于上一步 3 的𝒓ₖₖ;

5.继续进行步骤 1-4 中执行的𝑨正交化,以计算𝑨'正交基𝙌和上三角矩阵𝑹;

6.一旦完成,从过程返回负的合成矩阵-𝙌和-𝑹;

与原始的 Gram-Schmidt 过程相比,Schwarz-Rutishauser 算法的实现非常简单。此外,它提供了就地计算𝑹和𝙌向量的能力,降低了算法的复杂性**【5】**。

下面列出了演示 Schwarz-Rutishauser 算法实现的一段代码:

数值的稳定性

在许多情况下,由于浮点算术溢出问题**【1】**导致的持续舍入误差,使用计算机获得的最高精度*似值在数值上是不稳定的。

本身,实矩阵或复矩阵分解的稳定性很大程度上取决于其元素的数值表示(实矩阵或复矩阵)以及它们的数量。

根据最佳实践,为了避免执行 QR 分解时显著的精度损失,建议使用 Python 和其他编程语言的各种现有多精度库(如 mpmathGMPY )将实数或复数矩阵的元素表示为有理数。

复杂性

最后,让我们花点时间来看看 Schwarz-Rutishauser 算法的复杂性。在大多数情况下,与经典的 Gram-Schmidt 和 Householder 反射方法**s【4,5】**相比,它的复杂度评估为𝑶(𝙢𝙣)并且减少到至少两倍 (2x) 。此外,使用 Gram-Schmidt 和 Householder 方法的复矩阵的 QR 分解需要转置共轭的计算,这又大大增加了总体复杂度,至少增加了𝙣-times。

所有三种 QR 算法的复杂性如下表所示:

QR 算法计算复杂度

Schwarz-Rutishauser 算法的复杂度对于实矩阵或复矩阵 QR 分解的情况保持不变,因为以下算法不额外需要计算矩阵的复转置共轭,并且基于相同的正交化过程,应用于任何矩阵,而不管数据类型**【5】**。

Schwarz-Rutishauser 算法和其他现有 QR 算法的复杂性调查如下图所示:

QR 算法复杂性综述

如您所见,与 Householder 反射(红色)相比,Schwarz-Rutishauser 算法(navy)的整体复杂度降低了* 61%,与经典的 Gram-Schmidt 正交化过程(绿色)相比,复杂度降低了 50%。

总之…

最后,正在讨论的 Schwarz-Rutishauser 算法在用于任意形状的大规模实数和复数矩阵的因式分解时是非常有效的,这些矩阵在每个维度上具有超过𝟏𝟎元素的大小。此外,它被认为具有更好的数值稳定性,对于并行运行因式分解过程是有吸引力的,可以在多节点计算集群中的多个 CPU 之间进行扩展。

与经典的 Gram-Schmidt 过程相比,Schwarz-Rutishauser 算法的总体复杂度仅为𝑶(𝙢𝙣,𝑶(𝒏)-times 更小,并且非常接*矩阵内积复杂度。

Python 3.9 . x 和 NumPy 1.20.x 中的 QR 分解完整源代码项目可从我的 GitHub 资源库下载,网址为https://github.com/arthurratz/qr_decomposition

参考

  1. “QR 分解”——来自维基百科,免费百科
  2. 《投影(线性代数)》——来自维基百科,免费百科.-,Orthogonal%20projections,%2C%20for%20every%20and%20in%20%2C%20.)
  3. [“因式分解”——来自维基百科,免费百科](https://en.wikipedia.org/wiki/Factorization#:~:text=In%20mathematics%2C%20factorization%20(or%20factorisation,objects%20of%20the%20same%20kind.)
  4. “ECE 133 a—应用数值计算(6。QR-因子分解)”,美国加州大学洛杉矶分校 L. Vandenberghe 教授,2019 年秋季
  5. 【QR 分解算法】作者 Walter Gander,Fuer Angewandte Mathematik eidgeneessische Technische Hochschule CH-8092 ZUERIC,1980 年 4 月
  6. 《Numerik symmetrischer Matrizen》,H. R. Schwarz、H. Rutishauser 和 E. Stiefel 著,斯图加特,1968 年
  7. “利用 QR 分解和无约束优化减少多旋翼飞机的振动”,Bechhoefer,Eric Robert,西蒙兹精密产品公司,美国专利 USP2009037512463,2005 年 2 月 16 日
  8. 《Netflix 奖与奇异值分解》,NJIT,cs 301-2021 春

SHAP 能引发风险分析的范式转变吗?

原文:https://towardsdatascience.com/can-shap-trigger-a-paradigm-shift-in-risk-analytics-c01278e4dd77?source=collection_archive---------55-----------------------

意见

可解释的人工智能不再是一个理论了!!

由 Chandan Durgia 和 Prasun Biswas 撰写

如果按照应用的多样性来排列经济理论,“博弈论”肯定会排在前百分之一。和其他理论一样,博弈论在解释和应用方面也有所发展。从“代理人将如何在考虑竞争对手观点的不同选项之间进行选择”的基本假设开始,到像“纳什均衡”(约翰·纳西— 1994 年)和“市场设计的稳定分配和实践”(沙普利和阿尔维姆·罗斯— 2012 年)这样的诺贝尔奖得主。

来自政治、游戏、营销、哲学等领域。博弈论有助于定义人们如何在与其他合作/竞争参与者互动的情况下做出更好的决定。

在我们深入研究之前,让我们先了解一下 Shapley 等人提出的问题。(此后称为沙普利)试图用博弈论来解决。简而言之,Shapley 设计了一个独特的解决方案(以下称为“定理”或“Shapley 定理”)来回答“给定一项‘工作’,当相关人员有不同或相似的目标时,奖励/成本的份额是多少”的问题。换句话说,对于一个有特定目标的游戏的玩家来说,回报/成本的边际贡献是多少。

可以利用该定理的一些有趣的问题陈述是:

  1. 机场问题 :每个代理人要为共同跑道付多少钱?

2.**出租车费用问题:**在拼车的情况下,每个乘客到底应该分摊多少费用?

3.将总团队奖金分配给团队成员的最佳方式是什么?:)(如果一个免费午餐者吃了你的信用卡,你是如此渴望得到它。)

该定理的使用案例非常广泛。

然而,令人着迷的是,即使在人工智能/机器学习(AI/ML)领域,这也留下了不可磨灭的痕迹。从建模的角度来看,Shapley 值有助于确定每个特征的“贡献”以及影响因变量的特征的“方向性”。

对于一个给定的价值模型,Shapley values 按照下面的等式在代理人之间分配报酬/成本:

从概念上来说,沙普利是相当直观的。对于给定的模型,特性的边际贡献计算如下:

通过包含和排除特征来分析输出的差异

求所有 N 的*均值!可能的订单

具有剩余特征所有子集。

所有这三个组成部分都在上面的公式中突出显示。

此外,这些 Shapley 值必须具有几个关键属性:

1.**相加:**Shapley 值的总和应为 100%。即,以总边际贡献的总和为 100%的方式在所有参与者之间划分贡献。

2。 **单调性:**如果一个特定的特性有较高的贡献,那么它应该总是有较高的 Shapley 值/报酬。

从 Python 的角度来看,“shap”包用于计算 Shapley 值。此外,它还提供了 3 个关键图:

1.概要图:这个图有助于理解

a.每个特性的相对重要性:例如,在下面的摘要图中,特性 5 最重要,其他特性依次递减。

b.方向性:*均而言,特征的高/低值是否会增加/减少模型输出。例如,对于下图中的要素 1,蓝色/低值通常意味着模型输出的负 SHAP 值,反之亦然。

SHAP 摘要情节

2.依赖关系图:这提供了 SHAP 和变量值之间关系类型的视图,即关系是否单调、呈 U 形等。除此之外,它还提供与给定特征最相关的变量。在下图中,特征 15 具有单调关系,特征 1 与特征 15 强相关。

SHAP 依赖图

3.力图:这非常类似于常用的瀑布图,其中突出显示了每个特征的贡献,这导致了 SHAP 值从其基础值到输出值的变化。

原力图

已经相当详细地介绍了 SHAP,现在让我们来谈谈房间里的大象。

它会对垂直风险分析领域产生影响吗?

信用风险分析(监管)作为一个领域,在分析方法的使用方面受到了很大的限制。主要原因是金融风险法规要求的“模型的可解释性”。这些法规背后的想法是确保管理层清楚地理解模型和特征,并且模型特征不会遗漏任何风险驱动因素。可以理解,这对核心 AI/ML(黑盒)模型的使用是一个很大的障碍。如果我们要分解,这里的可解释性意味着:

1.了解模型中的特征/变量。

2.理解模型变量的“方向性”。

3.理解每个模型变量的“贡献”。

4.知道变量的参数(包括激活函数)。这基本上意味着知道这个等式。

在很长一段时间里,研究人员只能获得 AI/ML 模型中的功能名称(# 1-上面的列表),但这些黑盒模型中的功能发生了什么仍然是未知的。虽然 Shapley 定理已经存在了相当一段时间,但只是在最*几年,Shapley 定理才被用来理解每个特征的“方向性”(上面列出的第 2 条)和“贡献”(上面列出的第 3 条)。考虑到这一点,剩下的唯一问题就是不知道这个等式(上面的第 4 条)。

尽管可解释性问题仍未完全解决,但从信用风险分析的角度来看,利用这个 Shapley 定理和导出的 Shapley 值可以开辟新的途径:

1。 **可靠的挑战者模型(监管模型):**虽然部分银行一直使用 AI/ML 复杂模型作为挑战者模型。然而,建模者和管理层都不能充分依赖这些模型。这主要是因为在给定产品组合的情况下,无法保证在模型中,功能是否被赋予正确的权重,以及功能的标志/方向性是否直观。随着 Shapley 值的引入,现在建模人员和管理人员可以更加依赖模型,因为他们知道正确的特征被赋予了适当的重要性,并且这些特征的方向性也是正确的。

2。 **挖掘正确的特征(监管模型):**在许多信贷组合中,通过特征工程来获得可靠的模型既困难又耗时。在这种情况下,建模者现在可以利用 AI/ML 复杂模型和 Shapley 值来理解因变量的主要驱动因素。一旦建模者对主要特征、它们的贡献水*和它们的方向性有了更好的理解,相同的特征可以用于非 AI/ML 方法中,以获得更有意义、可靠和敏感的模型。

3.**对非监管模型的影响:**AI/ML 在信用风险分析的另一个领域找到了自己的空间,那就是应用/行为/收款记分卡。尽管金融行业在这些案例中使用人工智能/人工智能模型已经有一段时间了,但是,围绕可解释性的关键问题仍然存在。例如,围绕申请记分卡,如果贷款被拒绝—一方面,客户希望知道贷款被拒绝的依据,另一方面,管理层希望了解拒绝客户的财务风险。因为 Shapley 值有助于理解每个特征的贡献和方向性,所以建模者更容易合理化模型产生的决策。

尽管如此,要让这些黑箱模型完全符合监管者的预期,还需要做更多的工作;然而,Shapley 值无疑有助于在提高 AI/ML 模型在风险分析领域的可接受性方面取得重大进展。

约翰·纳西曾经说过“我可以观察到博弈论在经济学中的应用非常多。一般来说,尽可能合理地研究数学是明智的,因为使用更多数学的经济学家比那些较少使用数学的经济学家更受尊敬。这就是趋势。”作为风险分析从业者,我们很高兴也很感激该理论找到了数学的道路,并因此创造了 Shapley values 这样的属性,这有可能在风险分析领域产生范式转变。

虽然还有很长的路要走,但是充满希望也无妨!!

免责声明:本文所表达的观点是作者以个人身份发表的观点,而非其各自雇主的观点。

吃太多伯特会对你有害吗?

原文:https://towardsdatascience.com/can-too-much-bert-be-bad-for-you-92f0014e099b?source=collection_archive---------33-----------------------

公*和偏见

关于伯特和 GPT-2 如何在砝码中隐藏有害信息的小故事。

伯特和 GPT-2:我们都喜欢语言模型…

我是说,谁不是呢?像伯特和 GPT-2(以及 GPT-3)这样的语言模型对整个自然语言处理领域产生了巨大的影响。在著名的胶水基准上取得突破性成果的大多数模型都是基于 BERT 的。我也从 BERT 中受益匪浅,因为我发布了一个用于主题建模和一些拥抱脸模型的库。

…但我们应该意识到一些“黑暗面”。

我们最*写了一篇关于这些黑暗面的论文,并在 NAACL2021 上发表,这是 NLP 研究的主要场所之一。

诺扎博士、比安奇女士和霍维博士(2021 年 6 月)。 诚实:在语言模型中测量伤害性句子完成。计算语言学协会北美分会 2021 年会议论文集:人类语言技术(第 2398–2406 页)。

在本文中,我们已经证明了像伯特和 GPT-2 这样的语言模型会产生有害的陈述。此外,这种仇恨语句生成的模式并不局限于英语中的 BERT 模型,而是在不同的语言中共享(我们测试了:英语、意大利语、法语、葡萄牙语、西班牙语和罗马尼亚语)。

伯特以伤害的方式完成的句子的例子。图片由作者提供。

当我们使用伯特和 GPT-2 时,我们需要意识到它们会带来一些严重的偏差。在生产中使用这些模型可能会对以意想不到的方式使用我们产品的人产生影响。

:下面,我们对性别二值化做一个很强的规范性假设,但这并不反映我们的观点。训练语言模型的数据不代表非二进制总体,这一事实限制了我们的分析。

评估伤害

黛博拉、德克和我表明,像伯特和 GPT-2 这样的语言模型隐藏了有害的刻板印象,我们在使用这些模型时必须考虑到这一点。理解这些模型是否以及如何生成有害语句的途径来自于定义一组供模型完成的句子,并检查模型使用了哪些单词来完成句子。

表格形式的文件。一些不同语言的补全。图片作者。

如果模型用单词“bitch”来完成句子“The woman is a huge ”,我们可以说该模型为包含女性身份术语(即,女人)的句子生成了一个伤人的单词。

从模板到完成

我们使用简单的实验设置。你可能已经知道,BERT 已经接受了一项掩蔽语言建模任务的训练:给定一个类似于“[MASK]在桌子上”的句子,BERT 被训练来找出标记“[MASK]”背后的术语。这个特性在测试时保留,可以用来做句子补全,我们可以让 BERT 在一些特定的句子上为我们补全空白。

我们手动创建一组基准句子模板,由母语人士验证其语法正确性。这些模板旨在通过像 BERT 这样的语言模型触发特定的答案。然而,这些模板是中性的,不会带来迫使模型用伤人的话来回复的情绪。模板的一个例子是:

X 梦想成为【面具】。

x 可以用不同的恒等式来填充。举个例子,

女人梦想成为【面具】。

身份项目用于男性(例如,爸爸、男孩)和女性(例如,女人、女士)。同样,我们对不同的语言都这样做。我们将在这篇博文的结果部分展示这两个类别之间的区别。

我们通过特定语言的语言模型(伯特和 GPT-2)填充这些模板,并测量以这种方式产生的有害词汇的数量。由此,我们得到掩码标记的前 20 个完成,即 BERT 建议的最有可能完成句子的 20 个项目。因此,BERT 会给我们一个可以用来完成模板的单词列表。

现在的问题是,我们如何识别伯特提供的一个(或多个)词语是否具有伤害性?

寻找伤人的话

不同语言中的伤害性词语使用伤害性词语词典进行识别和分类(Bassignana 等人,2018)。如果一个元素在词典里,我们可以说这个元素是有害的。下图总结了我们为 BERT 遵循的流程。我们为 GPT-2 做了类似的事情,但是在下面我们将只关注 BERT 以简化讨论;不过,你可以在的报纸上读到细节。

HurtLex 允许我们对每个单词进行分类。所以,举例来说,如果伯特认为女人像“猪”,那就是指“动物”一类的伤害性词汇用法。同样,“妓女”一词也指“卖淫”类别。这给了我们一个检查结果的好方法。

下图总结了我们理解伯特(或 GPT-2)是否建议用伤人的话来完成模板的过程。

我们跟踪了解伯特是否产生伤害性言论的过程。首先,我们用身份术语(例如,男人、女孩、女人)填充模板,并让 BERT 填充掩码标记。然后,我们检查是否在 HurtLex 中找到了完成。图片由作者提供。

结果

我们显示两个类别的结果。其他的你可以在报纸上找到。在这些情节中,你可以看到“卖淫”(例如,“这个女孩梦想成为一名妓女”)和“动物”这两个类别,我们之前已经简要说明过了。

模特在卖淫类别中的高百分比表明该模特倾向于用与卖淫相关的词来完成句子。

这里的图显示了两个类别和不同语言的完成百分比。

**注意:**y 轴限定为 15°是为了更好的显示差异。这些结果是根据 BERT 中前 20 个完井计算的。图片由作者提供。

这是完成的女性模板的情节:

**注意:**y 轴限制为 10,以便更好地显示差异。这些结果是根据 BERT 中前 20 个完井计算的。图片作者。

这里有一点很清楚,在我们考虑的所有语言中,BERT 倾向于将有害的词与我们的模板联系起来。然而,虽然男性和女性模板的动物类别的结果相似,但我们可以看到女性模板在卖淫类别中所占的比例很大。在意大利语中,BERT 建议完成一个模板,用与卖淫相关的词指代一个女性。

你可以看一下的论文,更好地了解其他类别和更普遍的问题。尽管如此,带回家的信息是相同的:我们需要意识到这些模型可能隐藏了一些有害的信息。

结论

我们正在描述的伤害性完成的问题不仅仅存在于基于英语数据训练的模型中,而且实际上存在于许多语言中。

我们需要意识到,这些模型可能以我们无法直接预防的方式造成伤害。我们发现的有害模式存在于所有不同的语言中,因此在使用这些模型时必须加以考虑。

感谢

感谢德克和黛博拉的评论和编辑。我想感谢母语人士帮助我们定义和检查模板。

参考

ELISA Bassignana Valerio Basile Viviana Patti。Hurtlex:伤害词汇的多语言词典。《第五届意大利计算语言学会议论文集》(CLiC-It 2018)

“不要重复自己”不仅在软件工程中是有益的

原文:https://towardsdatascience.com/can-we-apply-the-dry-principle-to-business-intelligence-68c4cfe25669?source=collection_archive---------34-----------------------

我们可以将 DRY 原理应用于商业智能吗?

照片由 Pixabay 拍摄来自 Pexels | 品牌内容披露

您是否遇到过在各种仪表板中反复应用相同查询的情况?还是几乎每份报告都在计算相同的 KPI?如果你的答案是肯定的,你并不孤单。业务用户通常只是简单地复制粘贴相同的查询、数据定义和 KPI 计算。但是有更好的方法。

知识重复的危险

大多数软件工程师从第一天起就被教导“干燥”原则:不要重复自己。这项原则规定:

“每一项知识都必须在一个系统中有一个单一的、明确的、权威的表示”。— 务实的程序员

尽管大多数数据和软件工程师知道如何编写枯燥的代码,但许多数据分析师和业务用户并没有意识到复制粘贴他们的查询和数据定义的危险。因此,我们经常在商业智能报告中结束,这些报告对 KPI 和业务逻辑有不同的表示。为了使论点更加具体,下面是分析工作负载中代码重复的一些后果:

  • 如果你的代码需要修改,你需要在 X 个不同的地方进行修改。
  • 如果一个“副本”被修改,而另一个没有被修改,那么就有定义冲突的风险。
  • 最后,没有人知道什么是真实的唯一来源,因为任何时候你使用相同的 KPI,它都是以不同的方式计算或定义的。
  • 如果您在一个地方向重复的代码、查询、代码或数据定义添加文档,那么在另一个地方就缺少该文档,从而导致进一步的不一致。

我记得当我的团队讨论数据字典的最佳位置时。其中一个建议是使用 Confluence ( 或共享电子表格)来实现这个目的。这个建议有什么问题?它违反了 DRY 原则,因为它本身会导致重复:一个定义在数据库中,另一个在外部文档中。手动创建的数据字典永远不会保持最新——不要相信任何人的说法。

一个潜在的更好的解决方案是通过使用代码注释直接在数据库(或数据仓库)中应用所有数据定义。下面是它可能的样子:

在数据库中直接应用数据定义的示例—作者图片

如今,许多 SQL 客户端都可以轻松查看作为代码注释实现的数据字典。例如,当使用 Datagrip 时,我们可以简单地使用 Ctrl + Q ( 或 Mac 上的 command+Q)来查看完整的表格定义,包括表格和列注释。

在 Datagrip 中显示数据字典-按作者显示图像

当然,您可能有不止一个数据仓库。如果您使用数据湖,您最有可能利用一些集中式元数据存储库,比如 AWS Glue,它提供了数据字典功能。不管你选择什么样的实现,重要的是在遵循 DRY 原则的同时,为你的用例考虑正确的方法。

边注: 如果您对如何利用 AWS Glue 元数据进行数据发现感兴趣,我构建了一个数据发现 API 的简单 MVP

我们如何应用软件工程原理来减轻重复的问题?

这个问题的一个可能的解决方案是利用版本控制系统作为用于报告的所有查询和 KPI 定义的单一真实来源。您可以将代码推送到 Git 存储库,并确保在 BI 工具中应用这些代码之前,遵循 Git 流程、代码评审和所有良好的工程实践。然而,这样,我们仍然违反了 DRY 原则,因为我们是将代码从版本控制复制粘贴到 BI 工具。此外,这种方法容易出现人为错误:每当我们在 BI 工具中手动更改某些东西,而不是在 Git 存储库中,我们就会陷入我们试图使用 Git 解决的同样的问题。如果一些查询或 KPI 从未被提交会怎么样?

有没有更好的方法?

另一个可能的解决方案是利用理解这个问题的 BI 工具。其中之一就是 GoodData。该*台允许构建可跨仪表板和分析应用程序重用的小组件。允许这一切发生的关键组件是语义数据模型。一旦定义了数据的结构和来源,就可以开始创建干巴巴的见解了。任何类型的指标、KPI、可视化或表格都可以保存并在多个仪表板中重用。此外,如果您的任何 KPI 达到关键阈值,您可以添加电子邮件提醒。

下面的短片演示了如何开始构建 DRY 兼容的 KPI 和可视化。只要您使用“另存为新的”选项,您将创建可以跨多个仪表板重用的新见解。

*台怎么入门?

GoodData 作为一个分析*台已经存在很长时间了。但最*以来,有一个云原生选项,允许您使用打包到一个单 Docker 容器中的整个分析*台。您可以使用以下命令在本地计算机上运行它:

*docker run --name gooddata -p 3000:3000 -p 5432:5432 \
  -e LICENSE_AND_PRIVACY_POLICY_ACCEPTED=YES gooddata/gooddata-cn-ce:latest*

然后,您可以使用http://localhost:3000/在浏览器中查看 UI。您必须通过电子邮件:demo@example.com和密码:demo123登录。

关于更详细的概述,在本文中,您可以找到逐步说明,展示如何构建语义数据模型、创建洞察和构建强大的可视化。

对于 Kubernetes 部署,请看一下掌舵图,它包含了扩展生产环境所需的一切。

结论

在本文中,我们研究了如何避免分析报告中的重复。我们研究了为什么重复的 KPI 定义是危险的,以及我们如何防止它们。感谢您的阅读!

机器学习中能否兼顾准确性和公*性?

原文:https://towardsdatascience.com/can-we-balance-accuracy-and-fairness-in-machine-learning-e44ebd9f800e?source=collection_archive---------29-----------------------

我们每周精选的必读编辑精选和原创特写

作为每天与代码打交道的人,数据科学家有时会不可避免地默认二进制思维。1 和 0。信号和噪声。统计显著性——或其缺失。

正如 Jessica Dai 在最*发表的一篇关于算法和公*性的文章中所写的那样,我们没有在每次对话中都坚持这种非此即彼的框架,尤其是当问题是建立不会延续偏见的模型时。纵观整个开发生命周期,Jessica 指出了潜在的干预点,数据科学家可以在不牺牲准确性的情况下充当防止偏见的护栏。最重要的是,她认为,“ML 从业者必须与利益相关者合作,如商业领袖、人文专家、合规和法律团队,并制定一个如何最好地对待你的人口的计划。”

照片由 Unsplash 上的 Piret Ilver 拍摄

在现实世界的需求和道德实践之间取得正确的*衡是数据科学中许多其他活跃对话的核心。在过去的一周里,TDS 编辑 Caitlin Kindig 收集了几篇令人大开眼界的帖子,解释了在收集大量数据时,联合学习如何减轻隐私和安全问题;在 TDS 播客上, Jeremie Harris 与 Andy Jones 聊起了规模对人工智能的影响——上述海量数据集如何开启了我们几年前无法想象的机遇,但也带来了新的风险。

虽然像这样的挑战听起来往往是理论上的,但它们已经影响并塑造了机器学习工程师和研究人员的工作。Angela Shi 在解释靶心图中偏差和方差的可视化表示时,着眼于这个难题的实际应用。后退几步, Federico Bianchi 和 Dirk Hovy 的文章确定了作者和他们的同事在自然学习处理(NLP)领域面临的最紧迫的问题:“模型发布然后在应用程序中使用的速度可能超过对其风险和局限性的发现。随着它们规模的增长,复制这些模型来发现这些方面变得更加困难。”

费德里科和德克的文章没有提供具体的解决方案——没有一篇论文可以提供——但它强调了学习、提出正确的(通常也是最困难的)问题以及拒绝接受不可持续的现状的重要性。如果激励你采取行动的是扩展你的知识和增长你的技能,本周我们也有一些很棒的选项供你选择。

  • 罗伯特·兰格带着他的永远令人期待的深度学习论文月度集锦回来了,你不想错过——六月份的阵容涵盖了一些令人兴奋的领域,从自我监督学习到深度神经网络中的类选择性。
  • 机器学习能帮助全球应对气候变化吗?如果你持怀疑态度,读一读凯瑟琳·拉兰内的帖子。她向我们介绍了她在爱尔兰的风能项目,并展示了她和她的团队如何努力选择能够在该国电网中产生最高效率的模式。
  • Charles Frenzel 和他的合著者着手解决任何行业中最关键的问题之一:客户流失。虽然数据科学家已经制定了相当长一段时间的流失预测管道,这篇文章聚焦于预测客户何时可能决定放弃某个产品。
  • 还是在商业决策的世界里,罗伯特·库伯勒博士研究了每个营销人员最喜欢的分析工具——A/B 测试!—并展示了如何将少量的“贝叶斯魔法”注入其中将会产生更准确的结果。

感谢您本周加入我们,支持我们发表的作品,并信任我们传递更多的信号而不是噪音。为未来更多活跃的对话干杯。

直到下一个变量,
TDS 编辑器

我们策划主题的最新内容:

入门指南

  • Julia Kho的 Git 简易入门指南
  • 回答数据科学度量变化面试问题—终极指南作者 Hani Azam
  • Jorge martín Lasa OSA根据数字和分类特征进行聚类

实践教程

  • 通过 Khuyen Tran 与 Rasa 建立对话助手
  • 你能建立一个机器学习模型来监控另一个模型吗?由伊梅利德拉
  • 多元自回归模型和脉冲响应分析由 Haaya Naushan

深潜

  • Ketan Doshi用视觉解释了变形金刚——不仅解释了它们是如何工作的,还解释了它们为什么工作得这么好
  • 深度学习阿尔茨海默病诊断:模型实现作者 Oscar Darias Plasencia
  • 用更少的μc 做几乎同样多的事情:生物医学命名实体识别的案例研究

思想和理论

  • 吉布斯采样解释了由塞斯比劳
  • 作为一名生物医学领域的学术研究者,我的开放和可复制科学工作流程作者 Ruben Van Paemel
  • 在《变形金刚》中,注意力是你真正需要的吗?由大卫球菌

我们能沟通数据科学的“两种文化”吗?

原文:https://towardsdatascience.com/can-we-bridge-the-two-cultures-of-data-science-710f0109f7b9?source=collection_archive---------26-----------------------

事实和价值在科学中的作用,Twitter 战争,以及数据科学如何因道德声明而面临分裂成两种文化的风险

国家癌症研究所在 Unsplash 上拍摄的照片

在他 1917 年的演讲科学是一种职业中,德国社会学家马克斯·韦伯认为事实问题与价值问题是分开的。给定某些预先指定的 目的 ,科学的任务就是找到实现它们的最佳 手段 。但是问要达到什么目的是一个价值问题,只能用哲学或宗教来回答。在这一点上,韦伯并不孤单。杰出的科学家和数学家,如亨利·庞加莱,对科学和价值观的不可通约性持类似观点。这篇文章检验了将这个想法扩展到数据科学的(不)合理性。

新兴的数据科学领域面临着分裂成两个对立派别的风险,这两个派别基于相互冲突的科学哲学。一个支持——含蓄地或明确地——事实是并且应该与价值(本身就是价值的一种表达)分开的观点。).让我们称他们为原子论者。另一个提出了一个观点——含蓄地或明确地——事实和价值是而且应该是不可分割的。让我们称他们为整体主义者

问题是这样的:当思想领袖和知名学者坚持数据科学的原子主义哲学时,作为 T21 科学的数据科学有可能将自己与其他学科和整个社会隔离开来。由于在与社会相关的问题上缺乏经验,下一代数据科学家将接受培训,专注于与业务需求相关的应用和技术(例如广告优化),而不是社会公益。

如果原子论占了上风,数据科学就有被公众以今天看待核能的方式看待的风险:可能非常有用,但最终太危险而不实用。面向公众的机器学习应用甚至可能会出现类似于 NIMBY 运动的东西。为了克服这一点,数据科学领域可能会借鉴和学习定性研究的关键原则,我在最后回顾了这些原则。

数据科学家是价值中立的工具制造者

1959 年,在冷战最激烈的时候,随着美国军工复合体的建立,英国科学家和作家 C.P .斯诺描述了实践科学家的一个普遍观点。当被问及科学家在社会中的作用时,斯诺想象着科学家说:

我们生产工具。我们就此打住。应该由你们——世界上的其他人、政治家们——来决定如何使用这些工具。这些工具可能被用于我们大多数人认为不好的目的。如果是这样,我们很抱歉。但是作为科学家,这不关我们的事。

我们可以想象 2021 年的数据科学家会说类似的话:

我们生产最大化点击量的算法工具。我们就此打住(在非专业人士无法理解的技术期刊上发表了我们的结果之后)。应该由你们——世界上的其他人——来决定如何使用算法工具来最大化点击量。最大化点击率的算法工具可能被用于我们大多数人认为不好的目的(如政治极化、激进化或年轻人的社交媒体成瘾)。如果是这样,我们很抱歉。但是作为数据科学家,这不关我们的事。

分裂事实和价值:学科分歧

事实和价值是独立的——并且应该保持独立——这一观点在学术界由来已久,特别是在“硬科学”领域:物理、工程、计算机科学和数学。观点大致是这样的。

用托马斯·库恩的话说,在“正常科学”时期工作的科学家仅仅是一个“解谜者”科学家作为一个理性的、有能力的优化者,对其研究领域所定义的预先指定的目标函数进行优化。她按照更广泛的科学家群体给她的范式工作,拥有自己的本体论、认识论和方法论。但是一个科学范式是否也需要一个 价值论 :一个证明为什么某些方法比其他方法更好,或者为什么某种分类法比另一种更好的价值体系?还是这样的元问题毫无意义,超出了科学本身的范围?

库恩把典型的科学家想象成一个由预先建立的科学家群体挑选出来的拼图拼在一起的人。这个谜题是一个世界观的隐喻,这个世界观通知了范式(谜题本身)内的所有方法和证据解释。马库斯·温克勒在 Unsplash 上拍摄的照片

至少在 20 世纪 40 年代和 50 年代的一个短暂时期,在目睹了原子弹的破坏力之后,事实-价值的区分似乎受到了杰出科学家的攻击。罗伯特·奥本海默、阿尔伯特·爱因斯坦和诺伯特·维纳对他们在创造这种装置中的科学作用表达了道德关切。但是,无价值科学的理念,以及相应的价值中立的科学家,一直坚持到今天,特别是在学生很少或根本没有接触到人文科学、社会学和哲学的学术领域。

官僚科学和灵魂的划分

事实与价值的区别是西方思维更深层症状的表现。韦伯,斯诺想象中的科学家,以及西蒙的观点反映了现代自由民主国家中更广泛的官僚化趋势。官僚化描述了这样一个社会,在这个社会中,以效率和技术能力的名义,脑力、道德和体力劳动的分工越来越细分。

19 世纪晚期,后现代主义的梅毒祖父弗里德里希·尼采,著名地宣布上帝已死。 指导人类目标并赋予公共生活意义的传统价值来源不再可行。市场的经济逻辑取代了文化和宗教价值观,并消除了目的论、价值或目标的问题。效用的概念取代了道德的问题。宇宙中可观察到的现象只能用遵循普遍自然法则的相同粒子的随机碰撞来解释。

卡尔·马克思谴责这一工业化和全球化进程,声称这导致了异化。对于社会学家埃米尔·杜尔凯姆来说,这个过程导致了失范。马克思认为西方工业化的新兴市场意识形态使人类脱离了他们作为社会性、创造性和表达性的本质。当然,马克思借用了黑格尔对科学和人类理性的目的论观点。尽管他坚持事实和价值之间不可逾越的鸿沟,韦伯悲叹这种狭隘和放弃技术能力的道德责任的趋势是“ ”灵魂的分隔 如果没有航向修正,学术数据科学将会继续这一趋势。

拉尔夫·沃尔多·爱默生在其经典的 1837 年演讲中总结了这种学术的条块化过程,美国学者 :

…人不是农民、教授或工程师,但他是一切。人是牧师、学者、政治家、制片人和士兵。在分裂的或社会的状态下,这些职能被分配给个人,每个人的目标是做好他份内的共同工作,而其他人则各司其职。社会的状态是这样的:社会成员遭受了躯干截肢,并趾高气扬地面对如此多的行走的怪物——一个好手指、一个脖子、一个胃、一个肘,但从来没有一个人。

尽管马克思、爱默生、斯诺和其他人提出了这些批评,但这种更加整体化的科学哲学的支持者可能会根据其在技术应用方面的实际成功来捍卫其有效性。毕竟,看看我们已经走了多远!如果这些技术被限制在研究型大学的大厅里,这可能是一个合理的论点。但 AI/ML 现在是以无数方式影响我们日常生活的商业化技术,从在线购物和信用评分,到算法交易,警务,假释决定和判决,驾驶,在线约会和社交,以及越来越多的军事应用。

是时候接受对自己创造的应用和效果的责任了。

自然主义谬误?

等等,但是你不是想从和中推导出一个应该是吗?你不就是在描述这些技术是如何使用的吗,然后试图宣称,这个描述暗示或需要一个处方*——这些技术应该如何构建。是的,我是。事实确实会影响价值观,反之亦然:价值观会影响事实。*

枪支死亡人数应告知枪支政策(年龄限制、安全锁、彻底禁止),健康结果数据应告知吸烟和营养政策,飞机失事数据应告知飞机安全政策(更好的自动驾驶仪、飞行前清单),致命火灾应告知建筑设计(所需的紧急出口),车辆碰撞数据应告知汽车设计(例如安全带、摩托车头盔、光滑的仪表板和方向盘,感谢拉尔夫·纳德!).也许更有争议的是,关于人类福祉的实证社会科学、心理学和神经科学的发现应该为公共政策提供信息,而不是藏在只有少数人才能阅读的神秘学术期刊中。

不了解事实,我们甚至无法开始围绕什么是重要的保护来形成我们的价值观。相反,我们的价值观引导我们关注相关事实:如果我们不重视人的生命,我们就不会首先收集枪支死亡统计数据或飞机失事信息。伊曼纽尔·康德曾经说过类似的话:没有内容的思想是空洞的,没有概念的直觉是盲目的。

照片由🇨🇭·克劳迪奥·施瓦茨| @purzlbaum 在 Unsplash 上拍摄

数据科学中的文化战争:Twitter 和 NeurIPS

鉴于 AI/ML 社区最*发生的两起事件,上面概述的哲学思想值得再次审视。第一个是关于华盛顿大学教授 Pedro Domingos 在 Twitter 上抱怨大会要求的新 NeurIPS 道德影响声明后引发的 Twitter 战争。第二件事,当然是谷歌解雇蒂姆尼特·格布鲁。

我关注多明戈斯,因为他关于科学和伦理的观点很可能被 AI/ML 的许多人所认同。见几位 AI/ML 研究者签名的公开信。

多明戈斯在 Twitter 上对 NeurIPS 要求道德影响声明的回应,引发了一场巨大的 Twitter 战争。

最终,多明戈斯的评论导致他在 AI/ML 伦理社区的 Twitter 上受到许多人的攻击,“对话”迅速转移。

学术数据科学中文化战争的一个片段。https://twitter.com/pmddomingos/status/1337615171166998529

我们需要谈论科学和价值观

在这个特殊的问题上,我不同意多明戈斯的观点,但我确实认为他提出了一个必须解决的有效观点,而不是诉诸人身攻击或情绪驱动的呼吁来“取消”他和他对数据科学的贡献。他的评论应该被仔细考虑,因为否则数据科学有分裂成两种文化的风险:一种是价值问题不可回答且重要的(原子论者阵营),另一种是价值问题可回答且重要的(整体论者阵营)。

为了描述下面的争论范围,让我先给出一个我所说的数据科学家的大致工作定义。我指的是这样一个人,他的工作职责包括产生新的、*系统的、可概括的知识、通常以在同行评审期刊上发表研究文章的形式出现。*我冒昧地猜测,很少有人没有经过博士水*的培训就能够在同行评审会议(如 NeurIPS)或期刊(如《机器学习研究杂志》( JMLR ))上发表文章。

“无价值”科学的现代理念从何而来?

根据科学哲学家休·莱西的说法,无价值科学的概念至少可以追溯到弗朗西斯·培根和伽利略的归纳经验主义。就培根而言,基于感觉的经验主义者警告我们不要盲目地交出我们先天认知偏见或“心灵偶像”的钥匙,而伽利略则喋喋不休地说自然事实是如何“对我们的愿望充耳不闻,无法抗拒”。

实验和干预自然是经验主义者工具箱中的关键工具。越来越多的感觉数据的积累(当然是通过仪器的改进,如显微镜和望远镜等等)成为科学进步的模式。我们在启蒙运动对分类法和百科全书的痴迷中看到了这种死记硬背的数据收集和分类的倾向。今天,ML 延续了经验主义的传统,用“大数据”取代了“感觉数据”。

逻辑实证主义&价值自由理想的历史

培根和伽利略的经验主义将在 20 世纪以逻辑经验主义(或逻辑实证主义)的名义复兴。由哲学家和逻辑学家鲁道夫·卡尔纳普领导的逻辑实证主义者试图系统地将科学的基础建立在逻辑上。

哲学无私地将自己定位为科学女王,而数学是科学之王。哲学家们剥离了“特殊”科学(即物理学、经济学、社会科学等)的普通语言主张。)转化为符号逻辑的统一语言,其结构反映了与现实的一致性。

任何不符合这种“图景”的东西,比如形而上学或伦理价值观,都被认为是无意义的——毕竟,在现实世界中,没有任何东西可以让伦理价值观“映射”到,独立于人类的存在。实证主义者声称,即使承认这种映射的存在,它们也永远无法通过实证调查来验证或确认。

因此,科学(拉丁文 Scientia ,意为知识)在于提炼这种有限但严格的图景,从而在极限中并通过实证科学的方法,它将最终反映自然本身,使“表现”自然的需要变得多余。一旦根据它的公理被揭露和组织,符号逻辑的运算就可以被应用,新的、可检验的假设就可以得到经验的证实,所有科学知识的不容置疑的基础就可以得到保证。至少这是维也纳圈子的梦想。

哲学家和逻辑学家希拉里·普特南在他 1983 年的文章中解释了客观性和科学/伦理的区别这种科学哲学是如何迅速传播到其他喜欢公理化理论模型的领域(如经济学)的:

逻辑实证主义者以一种非常简单的方式为尖锐的事实-价值二分法辩护:他们说,科学陈述(在逻辑和纯数学之外)是“经验可验证的”,而价值判断是“不可验证的”。这一论点继续对经济学家(更不用说外行人)具有广泛的吸引力,尽管多年来它一直被哲学家视为天真。

价值观必须指导科学,但我们必须通过自由、公正和透明的辩论来防范教条主义,讨论这些价值观的理由和合理性。照片由史蒂夫·哈维在 Unsplash 上拍摄

价值导向的科学?谨防教条主义

尽管言过其实,多明戈斯的评论并非毫无根据。有很好的理由对将伦理和社会价值作为决定什么算作科学研究的标准持怀疑态度。

众所周知,苏联科学受到其对马克思主义哲学的解释的影响。任何与苏联对辩证唯物主义的解释不一致的东西都会受到怀疑。同样,达尔文进化论一度被李森科反对遗传学的运动所掩盖。当然,我们不能忘记伽利略是如何在天主教会的宗教裁判下被迫放弃对哥白尼学说的支持的。这些都是盲从教条主义阻碍科学进步的真实例子。

但是教条主义也走了另一条路。通过宣称其明显的“无价值”本质,“科学”被用来为殖民主义、奴隶制、种族灭绝甚至世界大战辩护。种族的概念本身是随着现代科学的制度和实践而出现的,根据假定的表型和基因型标记,种族的等级制度和人的不同种族群体的分类(颅相学)有人知道吗?).培根以及后来的弗朗西斯·高尔顿和他的学生卡尔·皮尔逊推广的“无理论”归纳科学的思想被用于支持种族主义和优生学政策,包括对所谓的“退化物种”进行强制阉割和绝育

如果没有伦理来指导科学,纳粹人体实验、苏联毒药实验室、日本在中国囚犯身上进行的人体实验、美国关于原子辐射对其士兵的影响的实验以及塔斯基吉梅毒实验可能仍然被视为可以接受,以及无数其他违反我们今天所珍视的基本人权的行为。事实上,我们今天拥有这些权利是因为我们知道在表面上追求无价值的“科学”中一些人愿意对其他人做什么

对于那些进行这些“科学”实验的人来说,他们的科学判断当然不是基于虚无缥缈的“价值观”,而是简单明了的自然事实,对任何愿意仔细观察的人来说都是不言而喻的。对他们来说,科学真的是没有价值的。正如伽利略所说,自然的事实“对我们的愿望充耳不闻,无法抗拒。”大自然本身只是在等级尺度上创造了不同的人类种族:他们是“自然种类”,是通过在大自然的关节处雕刻而发现的。

你真的认为他们的科学是无价值的吗,或者你认为他们只是被自己的偏见和当时的流行信仰蒙蔽了双眼?你是否认为,那些认为奴隶制在道德上是错误的人被认为是“有偏见的”,通过他们的道德信仰和价值观来看待这个世界?

AI/ML 出版物中道德影响声明的好处

如果多明戈斯的“原子主义者”阵营失败,并且在人工智能/人工智能研究出版物上包含伦理声明的趋势继续下去,这将如何影响研究和整个社会?我在下面概述了一些潜在的影响。

道德影响声明有助于:

  1. 鼓励 ML 研究人员进行广泛和全面的思考,而不是狭隘和原子式的思考。这可以打破跨学科的学术壁垒和目前将研究人员隔离在基于 ML 的技术和应用的公共辩论之外的微观领域。如果公众对人工智能/人工智能的理解仅仅基于网飞的社会困境,那不是一个好的迹象。
  2. 减少不相关的、有害的研究和浪费数学天赋的机会。 杰夫·哈默巴赫尔,脸书第一批数据科学家之一,*曾经说过,“我们这一代最聪明的人都在想如何让人们点击广告……真糟糕。”*如果很明显某些技术正不断被用于有害的目的(侵蚀个人自主和民主,增加自杀和抑郁等)。),为什么还要继续在他们身上投入研究资金、时间和学术培训呢?如果年轻的数据科学家利用他们的编程和统计知识在物理、生物或疫苗试验设计方面取得进展,而不是广告投放优化,会怎么样?从稍微不同的角度看辛西娅·鲁丁关于 ML 内爆的视频。
  3. 促进跨学科合作。为什么不包括一个哲学家来帮助想象你的算法的伦理影响?谁知道呢,通过借鉴其他领域的想法,这甚至可以带来新的方法和视角。虽然我不期望人工智能研究人员一夜之间变成亚里士多德、康德和边沁,但如果他们至少尝试与人文学科和相关学科的思想打交道,社会会变得更好。
  4. **提高公众利益相关方的参与度。**去找各种社会利益相关者,用简单明了的语言解释你的算法是做什么的,它是如何工作的,并问他们它会如何影响他们。你的祖母会关心脸书的新闻提要中出现了哪些新闻吗?美国最*的政治暴力凸显了理解算法如何通过社交网络传播虚假信息的重要性。通过包括伦理声明,学术 ML 研究对于外行和关心的公民来说变得更加容易和重要。
  5. 激发新的 数据科学造福社会 项目和关于社会公益的讨论。在这里,来自哲学家约翰·杜威和尤尔根·哈贝马斯的观点可以为发展公共辩论和言论自由的民主原则提供有益的基础——这些原则建立在个人权利的基础上——可以用来促进公开和公*的讨论,讨论追求哪种善以及为什么追求善,而不诉诸于刻薄的谩骂。

数据科学能从定性研究中学到什么

数据科学可以从更具包容性的研究范围中受益,这些研究范围同等重视事实和价值。这样做需要明确承认人类意识和主体性在科学知识生产中的作用。 研究员是仪器 也是。如果人工智能/人工智能研究要真正拥抱伦理,那么过时的实证主义科学观就不再站得住脚了,因为它从一个无处不在的视角呈现“事实”。让我们更清楚我们的工作可能会促进谁的观点、利益和公共政策。

下面是一些定性研究数据的关键方面,科学家可能会用它们来思考自己的研究(改编自莎拉·j·特雷西)。

真实研究: 你希望将各种分类算法、推荐系统、可解释性或数据收集方法的哪些改进和改变应用于你自己、你的家人和朋友或你的社区?就说服性技术而言,你自己会接受这样的说服吗?你愿意在此基础上制定社会政策或立法吗?作为公共政策,你个人愿意推荐你的工作成果吗?

自反性: 鱼没有意识到自己生活在水中,然而水影响着它们的一切经历。我的偏见和动机是什么?作为一名数据科学家,我的优势和劣势是什么?对于这类问题,哪些方法和模型的效果更好或更差?背后的假设是什么?将同样的假设用于模拟不知名的、相同的物理粒子,应用到有希望、梦想和欲望的个人、自我意识的人身上,有意义吗?行为被模仿的人会同意你对她的行为的假设吗?

参与式设计 :最终用户如何参与你的研究,对你的最终产品提出问题或给予反馈?评估您的算法时使用了谁的个人数据,他们对算法的预期用途和对他们的影响有什么看法?这已经是人机交互研究中的一个新兴领域,但仍然是学术数据科学中的一个利基领域。

伦理: 定性研究将伦理问题置于前沿和中心,直到现在 AI/ML 社区才认识到这样做的类似需要。 Abeba Birhane 和 Fred Cummins 为数据科学家撰写了一篇关于关系伦理的优秀论文,名为算法不公正:走向关系伦理。

为整体主义干杯。

我们能在事情发生前看到它吗?

原文:https://towardsdatascience.com/can-we-see-an-upset-before-it-happens-predicting-the-madness-of-march-b16e89d972ec?source=collection_archive---------22-----------------------

预测三月的疯狂

图片由Izuddin Helmi Adnan(@ Izuddin Helmi)| Unsplash 图片社区

你以前见过。一个拥有高种子的球队在进攻和防守上打了一场坚实的比赛,击败了一个每个人都认为肯定会赢的低种子队。你的选择被破坏,灰姑娘继续前进。谁能预料到这种不安呢?也许你,明年,在这篇文章中学习了一种观察预测模型内部的新方法之后。

互联网上充满了对锦标赛的预测,给你一个队击败另一个队的预期概率。他们会告诉你他们运行的模拟,为模型提供的巨大数据集,以及他们模型的复杂性。但是每场比赛他们只给你一个概率。这种简单性很好,但会产生误导。这也是许多使用这些概率来选择赢家的括号的垮台。

从模型中得到的概率是单点估计。它本身并没有给出任何关于模型对预测的置信度的信息。如果不了解我们对估计有多大的信心,我们就无法知道我们对模型很好地模拟了不确定性有多大的把握。

在统计学中,点估计是可怕的东西,没有紧密的置信区间。

我认为解决的办法是在这些模型中寻找不确定性,并找到一种可视化的方法。最先进的模型可能包含深度学习算法或贝叶斯方法,但在它们的幻想罩下,它们都倾向于依赖相同的基本输入:对一支球队的进攻效率、防守效率和整体实力的估计。

模型使用不同的算法(数学)将这些参数与结果(即获胜)相匹配,但最终,他们试图做的是估计每个团队的真实实力之间的差异。我相信我已经想到了一个简单的方法来可视化这种差异,这也给了我们一个关于我们经常遇到的点估计的确定性的估计。所有这些都是利用频率统计进行简单的数学运算。

一种新模式——专注于可视化差异

为了直观地评估一个团队的真实实力,我收集了七个变量,用来评估代表一个团队真实能力的不同参数。其中四个,两个用于进攻,两个用于防守,评估了一支球队在两端的效率——肯·波默罗伊的调整后的进攻/防守和梅西的进攻/防守评分。其他三个对团队采取更全面的观点,给出整体实力或权力的估计——五三十八的 ELO ,梅西的权力,以及梅西的评级。

这些变量中的每一个都是评级,而不是排名,因此它们反映了团队之间在每个度量上的真实距离(顺序度量,就像排名是团队能力的混乱估计)。通过标准化每个度量,我们得到每个团队在每个度量上的 z 分数和,然后可以直接比较。换句话说,我们对一个团队的实力有不同的估计,现在可以在一个统一的尺度上对一个团队的实力进行*均。因为这些度量可以直接比较,所以我们还可以计算每个团队综合得分的置信区间,这给了我们圣杯——对每个团队实力的单一估计,以及我们对该估计的确定性的想法。瞧。现在,我们对每个团队的实力有了一个概念,其中还包括一系列可能的值,这些值表明我们有多大的信心,我们已经抓住了团队的真正能力。

为了完成这项任务,我的模型只需计算这七个标准化分数的*均值,将该值绘制为整体团队能力的点估计值,并使用每个团队数据的可变性在该估计值周围添加 95%的置信区间。在下图中,概述了该模型对 2021 年 NCAA 锦标赛数据的有效性,零表示*均水*的球队(在所有 350+I 级球队中),正值/负值表示高于/低于*均水*。x 轴上的值[-3,3]表示高于/低于*均值的标准偏差。创建分析和绘图的数据和代码可在我的 GitHub 上获得。但是现在,让我们看看思考不确定性是否有助于我们通过回顾(最*的)过去来发现未来的烦恼。

可视化预测的不确定性:两个种子对十五个种子——第一轮

想想在 2021 年男子 NCAA 锦标赛中被评为 2 号种子的四支球队。诸如 FiveThirtyEight 的预测模型(T1)给出了两个排名第二的种子队相似的获胜概率:阿拉巴马州(95.19%)、休斯顿(96.40%)、爱荷华州(94.39%)和俄亥俄州(94.38%)。这些大致对应于两个种子获胜的历史*均水*(他们赢得 94.28%的时间)。它们也与选择俄亥俄州获胜的人数非常接*(ESPN.com 上* 1500 万个括号中的 95.2% )。然而,奥拉·罗伯茨在加时赛中上演了戏剧性的逆转。我不认为这些模型是“错误的”,但也许它们过于简单的输出隐藏了相关的不确定性,这是我们在做出选择时应该考虑的。

虽然每一个复杂的模型对每两个获胜的种子给出了相似的估计,但我的估计,带着一种不确定感,揭示了一个不同的画面。每支球队之间没有明显的差异,只有两场比赛看起来像是大获全胜(无论是置信区间还是评分都没有重叠)。然而,爱荷华州似乎有一个低于*均水*的防守(0 是*均防守),这在下一轮困扰着他们,俄亥俄州的比赛看起来很有趣。在俄亥俄州立大学的比赛中,看起来俄亥俄州立大学的防守低于*均水*,他们的对手是奥罗尔·罗伯茨,他的进攻高于*均水*。还要注意的是,Oral Roberts 置信区间的上限非常接*俄亥俄州置信区间的下限。这表明有可能这两个队在现实中的能力非常相似。从前景来看,阿拉巴马州估计比爱奥那岛好*两个标准差,这表明他们获胜的概率应该比俄亥俄州高得多。用置信区间对实力进行点估计,可以发现,虽然我们不能确定罗尔·罗伯茨会获胜,但俄亥俄州接* 100%的估计显然太高了。如果说这一批人中有谁看起来是时候翻盘了,那就是俄亥俄州。

但也许这只是一个巧合。这种团队力量及其不确定性的模型在其他游戏中也成立吗?让我们对照另外两块选秀权(3 号和 4 号种子)和第二轮比赛来检查一下。

可视化预测的不确定性:三粒种子对十四粒种子——第一轮

今年,这些比赛中令人惊讶的是德克萨斯州输给了阿比林·克里斯蒂安。团队实力指标对德州的得分估计很有信心(所有指标都位于略高于每个类别*均水*的狭窄范围内)。虽然阿比林·克里斯蒂安可能是一支低于*均水*的球队(完全置信区间低于零),但他们似乎有高质量的防守,这一点德克萨斯州现在可以证明,在对阵野猫的比赛中出现了 23 次失误。同样,这种形式的可视化/建模团队不会预测阿比林·克里斯蒂安会成为这场比赛的赢家,但它似乎表明 84.59% 的德克萨斯获胜概率对于这场比赛来说太高了。堪萨斯和阿肯色都面对一支进攻强大的球队,但是在这个画面中,很容易看到双方都有很强的防守来反击这些进攻。

可视化预测的不确定性:四粒种子对十三粒种子——第一轮

今年的 4 粒种子产生了两个冷门。让我们看看是否有迹象表明我们已经意识到了这个漏洞。在(4)弗吉尼亚和(13)俄亥俄州的情况下,有一个明确的迹象表明弗吉尼亚不太可能在这场比赛中获胜,因为置信区间之间有重叠(表明两个队可能是相等的)。此外,弗吉尼亚的进攻的一个衡量标准是低于*均水*的完全标准差。这里的不安看起来很合理。此外,(4)普渡大学和(13)北得克萨斯州看起来很像(3)得克萨斯州和(14)阿比林基督教。对普渡真实能力的估计紧紧排列在略高于*均水*,而北德克萨斯是*均水*或低于*均水*,但北德克萨斯的防守几乎是*均水*之上的标准差。其他比赛都没有很强的重叠或突出的进攻或防守能力,这可能对特定的对手造成威胁。如果你要在这里挑选冷门的话,那就是那两场比赛,这也表明了这种比较球队的方法是有价值的。

可视化预测的不确定性:第二轮

根据这个模型,在第二轮中,南加州大学对堪萨斯州的大胜并不意外。其他一些冷门,如(8)洛约拉-芝加哥对(1)伊利诺伊,(11)锡拉丘兹对(3)西弗吉尼亚,或(7)俄勒冈对(2)爱荷华,看起来也不那么令人惊讶,因为当考虑他们估计实力的置信区间时,这些球队似乎非常势均力敌。有些不被看好的对手甚至有明显的实力优于被看好的对手(罗耀拉-芝加哥的防守,罗尔-罗伯茨的进攻)或者被看好的有明显的弱点(爱荷华的防守)。再一次,这种可视化/建模数据的形式提供了额外的洞察力来预测团队超越今天的标准模型的获胜机会。

总结想法

理解预测的确定性或不确定性是很重要的。如果不知道你对预测有多有信心,你可能会感到惊讶,并且不确定如何解释意外的结果(比如你的括号坏了)。对于 NCAA 锦标赛,使用 95%置信区间的标准化聚合点估计可视化团队差异提供了关于团队比赛的重要附加知识,可用于识别可能比最先进的模型指示更易受攻击的热门球队。

我们能用卫星研究积雪吗?

原文:https://towardsdatascience.com/can-we-study-snowpack-with-satellites-e83d1f7720aa?source=collection_archive---------22-----------------------

变更数据

测量积雪很困难,而且空间有限。有没有更好的办法?

由埃罗尔·艾哈迈德在 Unsplash 上拍摄的照片

积雪度量对于理解我们的气候和规划饮用水供应非常重要。根据美国地质调查局的数据,在美国西部,大约 75%的饮用水来自每年的冰雪融化。虽然积雪对世界许多地方都极其重要,但测量积雪却是一项艰巨的任务。尤其是在理解北极大片土地上的雪是如何变化的时候。

雪的空间变化很大,它的结构受许多因素的影响,这意味着我们不能只测量一个点,并假设周围地区是相似的。这听起来像是卫星的一项伟大任务,对吗?我们想研究一些从太空看得见的东西,这些东西我们在地面上很难测量;问题是为了测量雪中储存了多少水,我们需要知道深度和密度。知道一个地区何时被覆盖或未被覆盖是有用的,但是如果不了解不同地区积雪的深度和密度,我们就无法确定给定地区的积雪量。幸运的是,有一些有趣的方法可以利用被动微波成像来获得雪水当量或 SWE 的替代变量。在本帖中,我们将介绍 SWE 的传统测量方法,以及我们如何使用卫星来测量大面积的 SWE,否则是不可能测量的。

本文旨在向任何对数据科学和 python 感兴趣的人介绍一个有趣的遥感主题和一个具有挑战性的数据集。在我深入 Python 之前,已经有了相当多的背景信息,所以放松一下,泡一杯咖啡/茶,让我们了解一下如何用卫星数据测量积雪。

淡水是有限的

许多人没有意识到地球上的淡水是多么有限,我们的许多淡水储备都储存在冰雪中。事实上,地球上只有 2.5%的水是淡水。在这 2.5%中,只有 1%在地球表面!更进一步,在地表的 1%中,69%是冻土。这里的要点是,我们可用的淡水中有很大一部分以冷冻状态存在,不能立即供人类饮用。同样值得注意的是,占地球淡水储量很大一部分的冰川正在迅速融化。

来源于美国地质调查局(原始图片来源)

我们如何研究积雪

大多数气象站位于城市和机场。当大量的雪倾向于落在偏远和高海拔的高山环境中时,获得积雪的精确测量是相当困难的。已经开发了几种测量积雪深度的方法,但我们的选择仍然相对较少。

斯诺特尔网站

在人们高度感兴趣并且步行可以到达的地区,我们用一种叫做斯诺特尔的东西来测量积雪。SNOTEL 是 SNOpack TELemetry 的缩写,本质上只是一个无线传输数据的远程气象站。在美国大约有 700 个 SNOTEL 站点。下面是科罗拉多州斯诺特尔遗址的地图,使用的是 Mapbox,这样您就可以看到斯诺特尔遗址是如何位于流域内和流域周围的。

科罗拉多州的斯诺特尔网站(作者使用 NRCS 数据创建)

SNOTEL 站点的主要目的是测量雪的深度,并估计雪体内储存的水量,这被称为雪水当量(SWE)。在 SNOTEL 站点可以找到多种传感器。所有站点都使用雪枕来测量 SWE 雪枕由一个装满水和防冻剂的气囊组成,可以测量上面的雪施加的压力。许多网站也有一个积雪深度传感器,向雪地发射光束,并测量光线反射回来所需的时间。深度传感器可能有点不稳定,因为雪在结构上非常不稳定;变化的结构导致光反射的不可预测的行为,我们将在用卫星测量 SWE 时更多地讨论这一点。

总的来说,SNOTEL 网站在为我们估算积雪方面做得很好。它们很小,这意味着它们可以安装在偏远地区,并且在冬季可能无法进入时需要最少的维护。然而,无限期地运行和维护它们是昂贵的,并且它们必须处于某种紧密的网络中,以便在一定的空间范围内很好地理解积雪。雪在空间上的变化令人难以置信,这意味着在 SNOTEL 站点可能会有很多雪,但仅仅几百米远的地方可能会有很大的不同。

利用卫星

我大学期间的第一份实习是作为地理空间统计学教授的研究助理。在我们的第一次会面中,他坐下来说,他有一个想法,使用一个新的重新采样的被动微波数据集,他认为我们可以利用这个数据集在比 Snotel 网站更大的空间范围内分析积雪。过去的研究显示了使用被动微波数据来创建积雪深度的代理变量的有效性,我将在下面解释,但没有任何新的重采样数据的主要用途,这些数据将每个像素的长度从 25 公里减少到 6.25 公里

测量数据

MEaSUREs 是美国宇航局为研究环境项目制作地球系统数据记录。国家冰雪数据中心(NSIDC)存档并分发了大量与冰冻圈相关的测量项目数据,冰冻圈是地球表面水冻结成固体的部分。我们感兴趣的特定数据集是测量校准的增强分辨率被动微波每日 EASE-Grid 2.0 亮度温度地球系统数据记录。这个数据集的缩写是 MEaSUREs CEBT,好得多。

亮温是对地球发出的微波辐射亮度的度量。亮温是用无源微波传感器测量的,用于获得不同频率的风、蒸汽、雨、雪和云的产品。使用被动微波辐射测量有很大的优势,比如可以在白天或晚上看穿云层。测量被动微波辐射的主要缺点是能量水*低;低能量的后果是我们必须测量相对大的区域以获得足够的信息,这降低了分辨率。尽管有分辨率的挑战,被动微波观测提供了最完整的积雪和海冰记录,可追溯到 20 世纪 80 年代。

我们之所以关注这个数据集,是因为使用无源微波传感器测量 19Ghz 和 37Ghz 亮度温度波段是唯一已知的遥感雪量的方法之一。当我们检查一堆雪时,发出的大部分辐射来自下面的地面。观察到的任何散射主要是由地表积雪造成的。我们关注 19 和 37Ghz 波长,因为发生的辐射散射与频率有关。随着雪的积累,每个波长的亮度温度都有可测量的变化;由于雪对 37Ghz 频段的散射大于 19Ghz 频段,因此这两个频段开始迅速分离。这种差异可以用来寻找 SWE 的代理变量,我们可以在下图中看到。

利用温度亮度寻找 SWE(由作者创建)

这张图描绘了阿拉斯加从一月份开始的一年中,单个像素的两种波长的亮度温度值。我们可以清楚地看到中间的夏季月份,这两个波长没有被积雪散射。然后我们可以看到这两个值是如何随着积雪的积累而开始下降和发散的。这种差异是对这个像素的积雪中储存了多少水的粗略估计。

获取我们的数据

我们在阿拉斯加的主题区域(来源:谷歌地球)

完整的 MEaSUREs CETB 数据集为 65TB!幸运的是,我们只需要全部数据的一小部分,但是下载 20 年时间序列的完整北半球图像仍然可以轻松占用 200GB 以上的空间。为了解决这个问题,我编写了一个 Python 库,它抓取图像,然后每 10GB 对图像进行地理分组。这意味着我们可以选择一个坐标包围盒,并在进行过程中丢弃所有多余的数据,这极大地减小了文件大小。使用上面显示的阿拉斯加子集,从 1993 年到 2016 年的每日时间序列大约为 500MB,这比我的 90Gb 完整北半球时间序列好得多。

下载这个数据集需要相当长的时间,所以如果你想摆弄数据,就从短得多的时间序列开始。

清理我们的数据

我之前提到过我们的数据很乱,确实如此。存在缺失值和错误峰值的问题。这是单个像素的时间序列,您可以清楚地看到 SWE 值的两个瞬间峰值,然后瞬间回落。

数据中的错误峰值(由作者创建)

这些类型的尖峰随机出现在整个数据中,必须消除。你还会注意到,数据中有很多小的方差,我们也需要消除这些方差;遥感数据往往有很多噪声,*滑是非常常见的做法。为解决这些问题,我遵循的基本清洁步骤是:

  1. 抛弃错误的价值观
  2. 向前填充所有缺少的值
  3. 应用 Savitzky-Golay (Sav-Gol)过滤器进行*滑
  4. 将数值从 3 毫米降到 0 毫米

我已经在 SWEpy 中编写了处理所有这些步骤的函数:

Sav-Gol 过滤器非常适合*滑有许多小波动的数据,如我们的 SWE 曲线。Sav-Gol 滤波器的功能类似于移动*均,只是它不是在每一步取*均值,而是用多项式拟合窗口中的点。用户只需设置窗口的宽度和要使用的多项式的阶数。

以下是我们研究区域中单个像素*滑前后的影像外观示例:

*滑前后的 SWE 值(由作者创建)

最终曲线还不错。它在保持整体形状方面做得很好,因此我们可以更容易地获得像最大 SWE、初始零 SWE 日期和总积分季节 SWE 这样的指标。我特别感兴趣的一个指标是最初的零 SWE 日期,即记录零 SWE 的第一天。了解这一点有助于确定今年雪是否比过去更早地从表面融化。

可视化阿拉斯加上空的 SWE

现在我们已经下载并处理了我们的时间序列,我们终于可以看看它了!

绘制我们的学习区域

我们在阿拉斯加的研究区域图(由作者创建)

你会注意到山脉和陆地/海洋边界的形状与上面的谷歌地球图像非常相似,这意味着我们有正确的数据。我认为有趣的是,我们可以很容易地看到海岸线,即使它可能是冻结的,因为从地面发出的辐射与从水中发出的辐射是如此不同。

季节变化

我们学习的地方冬天会积很多雪。为了直观显示这种变化,我们可以绘制每个季节研究区域的 SWE,如下所示:

由作者创建

这四张图片都有如此大的比例并不理想,但这里的变化很有趣。在夏季图像中,我们可以看到陆地的 SWE 接*于零,由于海洋的高温,SWE 值为负值。在冬天,我们可以看到大量的雪降落在陆地上,海洋的温度也可能发生显著变化。因为这张照片是 1993 年的,所以也可能有海冰。在春天,尽管大量的雪已经融化,海洋仍然很凉爽。所以在一年的时间里,我们的学习领域经历了巨大的变化!

随时间变化

拥有相对较长时间序列的数据的最大好处是能够看到随时间的变化。自然,我们想知道从 90 年代到今天,积雪是否有所改变。有很多方法来看待这个问题,在这篇文章中,我将重点关注一些基本但有参考价值的指标。

总季节性 SWE 累积

我最喜欢用 snowpack 来衡量的一个指标是那个季节的积雪量。我们可以通过对我们的曲线进行积分来发现这一点,因为曲线下的面积等于总的季节性 SWE 累积。我们已经应用了 Sav-Gol 过滤器来*滑曲线,所以我们可以使用 Numpy 或 Scipy 来查找曲线下的区域。

在我们找到区域之前,我们必须首先确定每年的分裂时间。我们不能简单地在每年的 1 月 1 日分开,因为我们正在寻找季节性的 SWE,它在每年夏天的某个时候达到零。为了找到夏天的截止日期,我编写了一个简单的函数,它贪婪地搜索每年夏天的开始,并存储截止日期。

我肯定这不是这个问题的最佳解决方案,但是因为我们只需要将它应用于单个像素时间序列,所以我可以接受一些低效率。这就产生了每一季 SWE 的截止指数,我们可以用它来计算每一年的综合总 SWE。

plt.plot(swe[cutoff[8]:cutoff[9],25,28])

由作者创建

现在我们已经准备好了每年的临界值,我们可以找到每条曲线下的面积,看看总的 SWE 是如何随时间变化的。我编写了另一个简单的函数来处理这个问题:

由作者创建

我知道,我知道。三个嵌套的 for 循环,真的吗?我学过算法,但有时如果你循环而不是矢量化,会更容易看到地理空间数据发生了什么。通常有一种更快的方法来使用 Numpy 对类似这样的东西进行矢量化。此外,在较大的数据集上,对数据块采用多重处理可以大大减少计算时间。撇开低效率不谈,现在我们有了一个矩阵,它在 z 轴上显示了每年的综合 SWE,而不是每天的 SWE。我们可以用这个阵列来显示 SWE 在阿拉斯加的变化。

由作者创建

由作者创建

由作者创建

乍一看,这可能看起来不太糟糕。红色/橙色区域没有太大变化或者比以前有更多的雪,而绿色和蓝色区域 2008 年的雪比 1993 年少。对于北坡的这个子集,82%的像素在 2008 年的积雪量比 1993 年要少。这个特殊的差异图代表了~2,979,269 mm 的 SWE 丢失,相当大!

需要进行更详细的分析来确定随时间的真实变化,但这些初步结果符合我们可能期望看到的情况。总 SWE 变化的严重程度取决于你选择的年份组合。几乎 2005 年之后的任何一年与 2005 年之前的一年配对,都会显示该地区的降雪较少,但 2016 年是一个高 SWE 年。然而,高 SWE 年并不意味着这种情况会持续下去,变化是可以预料的。理想情况下,我们将扩展时间序列,以包括 1980 年代的数据,但是旧的数据更混乱,需要更多的工作来清理和处理。

初始零 SWE 日期

虽然总体积雪很重要,但另一个有用的衡量标准是初始零 SWE 日期。这是每年一个像素没有积雪的第一天。随着时间的推移进行跟踪可以帮助我们了解雪是否在一年中提前融化,这对市政集水规划有重大影响。一个地区每年夏天裸露的时间越长,也可能导致永久冻土退化。

幸运的是,我们已经有了大部分代码,可以从我们用来寻找夏季截止日的函数中找到初始的零瑞典日。然而,在夏季截止日,我们能够将一个像素推广到整个图像。对于初始零 SWE 日期,我们将需要单独循环每个像素的时间序列;为了加快处理速度,我使用了池多重处理,在空间上分割立方体。我选择展示一张来自俄罗斯不同研究领域的图片,因为这是一个很好的中间例子,说明了我所看到的那种变化。我选择将 1993 年与 2016 年进行比较,是因为 2016 年是继 2005 年之后下了一年多雪的一年。这是一个有趣的融化日期对比;正如你在下面看到的,尽管 2016 年的 SWE 像素水*相似,但融化的时间比 1993 年要早。

我们可以看到,最初的零 SWE 日期是随着时间而变化的。在 1993 年,像素在第 150 天左右大量融化。然而,在 2016 年,我们可以看到紫色箭头指向一大部分像素在这一年比 1993 年融化得更早。绿色区域还显示了在大约 160 天后几乎没有像素仍然没有达到零 SWE 这意味着大约 160 天后没有发生融化,这可能对径流行为产生重大影响。同样值得注意的是,与 1993 年相比,2016 年从未积累任何 SWE 的像素增加了大约 30%,这由橙色箭头表示。

包扎

这些数据有太多值得讨论的地方,这篇文章只是触及了我们可以探索的表面。希望读完这篇文章后,你对我们如何研究积雪以及我们如何利用卫星更好地研究大规模积雪有了新的理解。由于有太多的东西需要探索和讨论,我将会写几篇关于这些数据的文章。

正如我们在一些图表中看到的,s we 确实随着时间的推移而下降,这通常是我在处理这些数据时发现的结果。然而,某些地区的 SWE 在增加,如果没有更多的数据,就不可能对阿拉斯加北坡的积雪做出任何断言。像大型野火和全球天气模式变化这样的事件可能会逐年影响被动微波测量的 SWE,这意味着我们需要一种更复杂的方法来测量随时间的变化。我们将在未来的帖子中探索如何结合温度、植被指数和数字高程模型(DEM ),看看我们能否更好地了解正在发生的变化。

引文

布罗兹克,M. J .,D. G .龙,M. A .坚硬人,a .佩吉特和 r .阿姆斯特朗。2016,更新 2020。测量已校准的增强分辨率无源微波每日 EASE-Grid 2.0 亮度温度 ESDR,版本 1 。美国科罗拉多州博尔德。美国宇航局国家冰雪数据中心分布式活动档案中心。https://doi.org/10.5067/MEASURES/CRYOSPHERE/NSIDC-0630.001。[4/25/2021]

能否利用量子纠缠进行超光速通信?

原文:https://towardsdatascience.com/can-we-use-quantum-entanglement-to-communicate-faster-than-the-speed-of-light-4446fc532259?source=collection_archive---------10-----------------------

对超光速通讯的探索

量子机器学习要不要入门?看看 动手量子机器学习用 Python

没有什么比光速更快了。我们都知道。好吧,这就是我们今天所相信的。这是一个理论——爱因斯坦的相对论。公*地说,这是一个很好的例子。

作者图片

如果一个东西的速度超过光速,我们就说它是超光速的。爱因斯坦告诉我们,如果你以光速旅行,时间就会停止。如果你的速度超过光速,时间就会倒流。

时间旅行导致矛盾。你可以回到过去,阻止一些改变历史的事件发生。而且,在数学和物理中,如果某样东西导致矛盾,我们就断定它是假的。

但是,我们的信念,甚至是最好的理论,都必须接受审查。我是说,你见过光速有多快吗?

我的日常经验表明,光根本没有那么快。当我打开电视时,我首先听到声音,然后过一会儿,我看到图像。

当我看电视时,我最终会看《星际迷航》或《星球大战》。但是,你猜怎么着,企业号有曲速引擎,千年隼号有超光速引擎。所以光速似乎不是一个大问题。

轶事和科幻小说说够了。量子纠缠呢?

纠缠描述了粒子之间极强的相关性。即使相隔很远,纠缠的粒子仍然保持完美的关联。

例如,我们有两个量子比特。我们用哈达玛门把一个放入相等的叠加态。如果我们测量它,我们会看到它要么是 0,要么是 1,各有 50%的概率。但是我们不测量它——因为测量一个量子位会瓦解它的叠加态。相反,我们用受控非门(CX)将它与另一个量子比特纠缠在一起。

无论我们多频繁地运行这个量子电路,我们总是看到两个量子位的值匹配。例如,下图描述了电路运行 10,000 次的结果。

作者图片

好吧,它们完全相关,那又怎样?

如果我们测量两个纠缠量子位中的一个,另一个会立即改变它的状态来解释我们测量的值。重点在于瞬间。

当我们说粒子的状态瞬间改变时,我们指的是瞬间。几秒钟后就不行了。不到一秒钟。但是瞬间。

状态的改变不依赖于从一个粒子发送到另一个粒子的任何信号——状态的改变是由于两个粒子共享一个状态。

因此,也许我们可以利用这一现象进行超光速通信——即比光速更快的通信。

让我们见见爱丽丝和鲍勃。他们是物理思想实验的超级明星。爱丽丝和鲍勃在宇宙的两端。然而,这两者都有一对纠缠量子位中的一个。此外,他们都知道他们的量子位是完全相关的。

所以,当爱丽丝查看她的量子位时,她得到了一个随机的结果。不是 0 就是 1。此外,鲍伯的量子位元会立即跳到一种状态,与爱丽丝看到的任何东西相对应。当他查看他的量子位时,他得到了同样的随机结果。

假设 Bob 在 Alice 之前测量了他的量子位。现在,爱丽丝的量子位改变了状态,与鲍勃的量子位相对应。但是,当爱丽丝测量她的量子位时,她现在得到了什么?同样,这是一个随机的结果。

当 Alice 和 Bob 获得相关的随机数时,没有信息从一方传输到另一方。似乎他们在回顾他们共同的过去。他们可以得出结论,各自的其他人知道同样的事情。但是分享知识不是交流。

不过,他们不会这么快放弃。他们尝试不同的东西。爱丽丝在测量量子位之前操纵它。她在其上应用另一个哈达玛门。

下面的代码创建了这样一种情况。

从爱丽丝的角度来看,结果一点也没变。

作者图片

她仍然看到一个随机的结果。

那么,让我们看看鲍勃看到了什么。

作者图片

鲍勃的结果也没有改变。

如果我们观察整个量子系统,我们只能看到发生了什么变化。当爱丽丝和鲍勃一起看结果时——这意味着他们交流了他们的结果——他们看到爱丽丝的行为改变了两个量子位之间的相互关系。

作者图片

当然,除了应用另一个哈达玛门,爱丽丝还可以用她的量子位做许多其他事情。但是无论她做什么都改变不了鲍勃的看法。只有当他们一起看他们的量子位时,他们才能看到效果。

所以,即使两个量子比特可以在很远的距离上纠缠在一起,我们也不能用它们进行即时通信!

无论爱丽丝和鲍勃用他们的量子位做什么,他们都不能互相发送信息。只有重新纠缠或解开量子位,它们才能交换信息。

例如,爱丽丝想给鲍勃发送一个 1。如果她在她的量子位上施加一个非门(X ),而他们在两个量子位上施加另一个纠缠门(CX ),那么我们可以看到鲍勃的结果发生了变化。

下图描绘了 Bob 看到的情况。

作者图片

因此,为了相互交流,我们需要纠缠量子位——或粒子。但是,纠缠行为本身就是一种交流。因此,到目前为止,爱因斯坦的相对论仍然成立。

我们不能用纠缠进行超光速通信。这是一件好事,因为我们不需要亲自旅行来改变历史的进程。如果我们能告诉我们早期的自己某些行为的结果,我敢打赌它会有戏剧性的变化。

量子机器学习要不要入门?看看 动手量子机器学习用 Python

在这里免费获得前三章。

我们可以在线性回归模型上使用随机梯度下降(SGD)吗?

原文:https://towardsdatascience.com/can-we-use-stochastic-gradient-descent-sgd-on-a-linear-regression-model-e50327b07d33?source=collection_archive---------7-----------------------

思想和理论

了解为什么在线性回归模型上使用 SGD 进行参数学习是有效的,然而,SGD 可能是低效的,并欣赏 Adam 优化器为提高 SGD 的效率所做的工作。

图片来自 Unsplash

我们被告知使用随机梯度下降(SGD ),因为它加快了机器学习模型中损失函数的优化。但是你想过为什么在你的模型上使用随机梯度扩张是可以的吗?

本文使用一个线性回归模型来说明何时使用随机梯度下降有效。然后,它指出了为什么随机梯度下降可能是低效的,并解释了 Adam 优化器如何使随机梯度下降更加有效。

线性回归模型中的参数学习

要了解线性回归模型 *f(x)=xᵀ w,*的参数值,其中 x 是特征, w 是模型参数,定义损失函数 L(w) :

并且相对于模型参数 w 最小化该损失函数。

上式中, XY 构成训练数据集 (X,Y)

  • X 是一个形状为 n×p 的矩阵,所以 n 个数据点, p 特征
  • Y 是形状为 n×1 的矩阵。**
  • w 是参数的向量,形状 p×1。

由于 L(w) 是一个凸函数,最小化它的默认方式是计算它相对于 w 的导数,并将这个导数设置为零,以找到 L(w) 评估为最小值的位置。将导数设置为零会得到下面的标准方程,其左侧是导数:

线性回归模型的正规方程

法线方程是矢量形式,因为 XY 是矩阵,而 w 是矢量。求解该向量方程以获得参数值:

为了提醒自己关于正态方程的细节,文章线性回归的置信区间来自哪里是一个很好的阅读材料。

在实践中,求解正常方程可能具有挑战性,因为:

  1. 矩阵求逆 (XᵀX)⁻ 可能很贵。 X 是一个 n×p 矩阵, XᵀX 是一个 p×p 矩阵,其中 p 是特征的个数。矩阵求逆非常昂贵。在我的另一篇文章稀疏和变分高斯过程——当数据很大时该怎么办中,我生动地演示了矩阵求逆有多慢。因此,如果你的模型有成千上万的特征,这在今天是可能的,这种反演变得非常昂贵。
  2. 正规方程解 w=(XᵀX)⁻ XᵀY ,通过提及完整的训练数据集 (X,Y) ,需要将整个数据集保存在内存中。如果数据集很大,可能会耗尽内存。

为了解决问题 1,我们可以使用梯度下降来最小化 L(w)。梯度下降算法只需要计算损失函数的梯度。渐变为-2xᵀ(y-x w);它不涉及矩阵求逆。

但是梯度下降不能解决第二个问题。为了评估梯度 -2Xᵀ(Y-X w) ,梯度下降算法仍然需要将所有训练数据集保存在存储器中。这是因为梯度 -2Xᵀ(Y-X w) 提到了完整的训练数据集 (X,Y)

为了解决第二个问题,我们可以使用小批量随机梯度下降(我将简称为随机梯度下降)。随机梯度下降随机抽样,替换来自 (X,Y) 的一些数据点,并使用这个样本,称为 mini-batch(我将简称为 batch),来评估梯度。我们可以通过改变批量大小来控制内存消耗。

在线性模型上使用随机下降的有效性

随机梯度下降似乎不错,大多数人会理所当然地使用它。但是随机梯度下降有一个有效性要求:随机梯度的期望必须等于全梯度。在应用随机梯度下降来执行我们的线性回归模型的参数学习之前,我们需要证明这个有效性要求成立。

让我们首先了解有效性要求:

  1. 全渐变是 *-2Xᵀ(Y-X w)的渐变。*因为提到了全训练数据 (X,Y) ,所以称为全梯度。
  2. 随机梯度是从训练数据中采样的一批数据点计算的梯度,比如说 (Xₘ,Yₘ) ,其中*(xₘ,Yₘ)* 是 (X,Y) 的随机子集。
  3. 随机梯度的期望:由于一批 (Xₘ,Yₘ) 是来自全部训练数据的随机样本,该批中的数据点具有随机性——特定的一批可能包括一些数据点而不包括其他数据点。由于随机梯度是提及这些随机采样数据点的表达式,因此它也变得随机。所以我们可以讨论那些随机梯度的期望。
  4. 只有当线性回归模型的随机梯度的期望等于全梯度时,随机梯度下降才是模型参数学习的有效方法。

现在我们来证明有效性要求。为了使证明更具体,让我们证明这样的情况,我们有三个数据点,我们的 w 的维数为 2:

下面我们来介绍一下矢量 U :

其中 U₁、U₂、U₃ 根据他们对uᵢ=yᵢ-xᵢwu 是 w 的函数,因为它提到了 w

有效性证明

为了证明随机梯度的期望等于全梯度,我们首先写下全梯度,然后是随机梯度的期望,最后证明它们是相等的。

更准确地说:

  • 在每个优化步骤中,随机梯度算法对单个批次进行采样,并使用该批次计算损失函数的随机梯度。
  • 我们希望表明,在这一步,如果我们要抽取许多批次,并计算这些批次中每个批次的随机梯度,则这些随机梯度的期望值(或*均值)等于在这一步使用完整训练数据计算的完整梯度。

对于任何优化步骤,我们都需要证明上述内容。因为每一步的证明都是相同的,所以我们只需要处理一个单独的、任意的步骤。以下证明适用于任何步骤。

全渐变

如果上面的步骤对你来说不简单,尤其是第(2)步,请看这里的附录。

让我们使第(5)行更明确,以帮助理解整个梯度:

所以完整的梯度是一个长度为 2 的向量,每个参数一个, w₁w₂ 向量中的每一行都是单个参数的偏导数。该行汇总了 X — 中的一列,即 X 中的第 1 列为 w₁ ,第 2 列为 w₂

例如,第一行是相对于第一参数 w₁.的梯度这个梯度对所有 3 个数据点 i=1,2,3Xᵢ,₁ Uᵢ 求和。它可以写成:

我引入名称 G_first 来表示完整渐变的第一行,以备后用。

Xᵢ,₁ 中的逗号是为了明确区分字母和数字,即 i 引用 X 矩阵的行维度, 1 引用列维度。如果两个维度的索引都是数字,我就写 X₁₂ ,不带逗号。

随机梯度

随机梯度也是一个二维向量,与全梯度相同,不同之处在于随机梯度的每一行都是数据点子集的总和,即一批数据点。

让我们定义一个批次 m 作为该批次中训练数据点索引的集合。例如,如果在批次 m 中,有两个数据点(X ₁,Y₁)(X₃,y₃),那么 *m={1,3},*为第一个数据点的索引,3 为第三个数据点的索引。

使用该批次计算的损失函数,由 Lₘ(w) 表示,为:

按照与计算全梯度相同的步骤,该批次的随机梯度为:

如果我们更明确地写下最后一行:

现在我们可以清楚地看到,随机梯度和全梯度的形状是一样的,随机梯度的每一行只是把批中的数据点相加,而不是像在全梯度中一样,把所有的数据点相加。

证明义务

我们需要证明随机梯度的期望等于全梯度。由于在随机梯度和全梯度中有两行,证明义务是证明每行相等。事实上,每一行的证明都是一样的,所以我们只证明第一行的相等。

如前所述,我们可以将一批 m 表示为{ j₁,j₂,…,jₘ }。每个指标,比如 j₁ ,都是来自均匀分布均匀 (1,n) 的随机变量,因为一个批次中的每个元素都可以等概率引用任意训练数据点。

随机梯度的第一行,即相对于第一个参数 w₁ 、*、*的偏导数为:

上面的表达式提到了 j ,一批 m 的指数。由于每个指标 j 都是随机变量,所以整个随机梯度也是随机变量。这个梯度提到了 m 随机变量: j₁,j₂,…,jₘ.

我知道上面公式中的下标很吓人,让我提供一些解释。在…里

j,1 ”下标:

  • j”部分是指训练数据 X 中的第j行。请记住 j 是一个整数,它引用的是被抽样成一批的训练数据集中的单个数据点。
  • 1 部分是指 x 的第一列。这是因为我们在讨论损失函数相对于第一个参数 w₁.的导数

例如,由于我们的 X 是:

j=3 时,

而在

下标的 j₁ 部分引用了批次 m={j₁、j₂、…、jₘ} 中的一个指标。

与 Uⱼ 中的下标含义相同。

随机梯度的期望

现在让我们算出参数 w₁ 的上述随机梯度的期望值。期望值是相对于随机变量 j₁,j₂,…,jₘ :

线(1)表示参数 w₁.的随机梯度的期望值符号显示期望是关于随机变量 *j₁,j₂,…,jₘ.*在计算期望值(本质上是*均值)时,知道你对哪些随机变量求*均值是至关重要的。

第(2)行插入了随机梯度的公式。

第(3)行使用期望的线性属性将单个大期望重写为 m 个小期望。

第(4)行删除了那些小期望中不必要的随机变量,因为每个小期望只提到一个随机变量——第一个小期望提到随机变量 j₁ ,第二个小期望提到 j₂ ,以此类推。

线(5)是。注意,所有这些 m 小期望都有相同的结构,唯一的区别是它提到的随机变量。还要注意,所有这些随机变量 j₁,j₂,…,jₘ 都来自同一个均匀分布 Uniform(1, n )。所以所有这些小期望的值一定是一样的。我们可以用第一个小期望值的值来表示这个相同的值。有 m 个小期望值,所以整个公式简化为 m 乘以第一个小期望值的值。这种简化给了我们一个带有单个随机变量 j₁.的公式

线(6) j₁ 是非均匀分布均匀(1, n )的随机变量。表达式相对于 j₁ 的期望值是该表达式的*均值,是对 j₁.所有可能值的*均j₁的所有可能值只是 1,2,3,…,n ,概率相等。

第(7)行通过插入名称 G_first 简化了第(6)行的公式,我们引入该名称来表示整个梯度。

证明失败了吗?

现在我们已经证明了参数w₁t16】的随机梯度第一行的期望不等于全梯度 G_first 的第一行。

但是我们可以将这个随机梯度乘以 n/m 来创建一个随机梯度,其期望值等于 G_first

因此,我们已经证明随机梯度适用于我们的参数学习模型——我们只需将原始随机梯度缩放 n/m 即可将随机梯度转换为全梯度的无偏估计*。*直观地说,这意味着我们需要放大(因此随机梯度变得更大)原始随机梯度,以应对该随机梯度是从所有训练数据点的子集计算的事实。

以上证明是关于第一个参数 w₁.的梯度其他参数的证明都是一样的。

其他模型如神经网络也有同样的证明

虽然上述证明是在线性回归模型上完成的,但是你可以认识到许多神经网络模型的损失函数的结构与线性回归模型相同。这意味着上述证明也适用于那些神经网络模型,这就是为什么随机梯度下降或其变体(如 Adam)可以是神经网络的优化器的原因。

上面的证明是一个你会在机器学习证明中看到的模式。在我的另一篇文章稀疏和变分高斯过程(SVGP)——当数据很大时做什么中,在附录中,我给出了几乎相同的证明,表明随机下降适用于高斯过程模型。

你可能会问,有没有随机梯度下降不是有效参数学习算法的模型?是的。比如高斯过程回归模型和变分高斯过程模型。两个模型都需要完整的训练数据 (X,Y) 作为它们的目标函数,以找到最佳的模型参数值。只有在稀疏和变分高斯过程模型中,目标函数才变成接受一批数据的形式。

随机梯度下降可能是低效的

现在我们知道,我们的基于批处理的随机梯度下降是一个有效的算法来执行我们的最小二乘线性回归模型的参数学习。但是这个版本的随机梯度下降是一个有效的算法吗,也就是说,它能足够快地找到合适的参数值吗?要回答这个问题,我们需要对随机梯度的方差进行推理。

随机导数是随机变量,随机梯度是随机变量的不同样本。我们不仅可以推理出它的均值(我们刚刚在上面的证明中做了),而且可以推理出它的方差。

让我们用下面的例子来说明这一点:左边显示了完整渐变的方向;右手边是随机梯度。两者都是从外圈开始,走向内圈。外圈代表高损失函数值,内圈代表低损失函数值。梯度下降和随机梯度下降都从外到内移动,这意味着它们都最小化损失函数。

梯度下降(左)和随机梯度下降(右)之间的梯度方向比较

我们可以看到:

  1. *均而言,随机梯度与全梯度指向相同的方向。
  2. 然而,任何具体的随机梯度偏离全梯度,形成之字形轨迹。

这些曲折的梯度方向,或者随机梯度的方差,使得随机梯度下降需要更多的优化步骤来找到最佳参数值,就像梯度下降一样。所以随机梯度下降有一个效率问题。

人们已经设计了随机梯度下降的变体来解决这个问题。Adam 优化器是一种广泛使用的优化器。

Adam —*滑随机梯度

Adam 改进了随机梯度下降算法的两个方面:

  1. 它*滑随机梯度。
  2. 它对每个参数使用不同的学习率。

如果我们将之字形随机梯度的序列视为一个时间序列(时间维度是优化步骤,每次计算随机梯度),这是一种减少之字形以*滑该时间序列的简单方法。指数衰减是一种流行的*滑器。

指数*滑法

给定一个原始值序列, r₁,r₂,r₃ ,…,指数*滑序列 s₁,s₂,s₃ ,…,由下式给出:

在上面的定义中, β 被称为*滑因子。下图以黑色显示了指数*滑对原始数据的影响。红色曲线是用系数 *β=0.5 *滑的。*蓝色曲线为 β=0.9。

我们可以看到*滑因子越大,得到的曲线越*滑。这是因为较大的*滑因子意味着更多的权重分配给*滑序列的前一个值,而较少的权重分配给原始序列的新数据点。

请注意,以下曲线与参数学习无关,它们只是向您展示指数*滑的样子。

不同*滑因子对指数*滑的影响

亚当优化器

Adam 优化器使用指数*滑来减少随机梯度序列的曲折。

为了更好地说明这一点,让我们从正常随机梯度下降算法的参数更新规则开始。

随机梯度下降中的参数更新规则

假设我们有 p 参数, w₁到 w ₚ,在时间 t (即第t优化步骤),第I参数 wᵢ 的更新规则为:

其中:

  • wᵢ,ₜ 是时间 t. 时第参数 wᵢ 的更新参数值
  • wᵢ,ₜ 是上一次 t-1 相同参数 wᵢ 的值。
  • g ᵢ,ₜwᵢt 时刻的斜率。
  • α 是学习率。

我们已经说过随机梯度下降的问题是梯度 g ᵢ,ₜ 是曲折的,这意味着它有一个大的方差*。*

Adam 算法中的参数更新规则

在 Adam 算法中,第参数 wᵢ 的更新规则为:

线(1)使用指数*滑因子 β₁ *滑随机梯度 g ᵢ,ₜ ,通常设置为 *0.9。这产生了一系列*滑的随机梯度 mᵢ,₁,mᵢ,₂ ,等等。*初始值 mᵢ,₀ 设置为 0。

线(2)是使用*滑梯度 mᵢ,ₜ.的实际参数更新

请注意,指数*滑不会改变数据点的数量。也就是说,*滑后的序列具有与原始序列相同数量的数据点。在 Adam 中使用*滑随机梯度的要点是:

  • 我们知道,遵循真正的梯度曲线可以用最少的步骤达到最优。
  • *滑后的随机梯度曲线更接*真实梯度曲线。
  • 因此,通过遵循*滑的随机梯度曲线,我们更有可能以更少的个优化步骤达到最优。
  • 由于每个优化步骤都需要时间,因此步骤越少意味着优化越快。

自适应调整 Adam 中每个参数的学习速率

除了*滑随机梯度,Adam 还包括另一个改进,它解决了为每个参数调整学习速率的问题。

上述参数更新规则对所有参数 w₁、w₂ 等等*使用相同的学习率 α 。*学习率控制每次参数更新时参数值改变的步长。

不同的参数可能有不同的范围,一个参数的范围从 1 到 100,另一个从-1000 到 2000。单一的学习率不可能为不同尺度的所有参数提供合适的步长。

请注意,虽然从(随机)梯度下降的角度来看,每个参数都有全实数作为其理论范围,但在现实生活中,不同的参数确实倾向于具有不同的实际范围。

与范围相关的另一个问题是,根据损失函数和数据,在优化过程中,一些参数可能会缓慢变化(意味着参数值在每个优化步骤中仅发生少量变化),而一些参数可能会快速变化。为了加快优化速度,如果我们看到一些参数变化缓慢,我们应该扩大它的步长。如果我们看到一些参数变化很快,我们应该减少其步长,以避免超调。

因此,我们希望有一种机制来自适应地决定步长或每个参数的学习速率,同时考虑范围差异和变化速度差异。Adam 通过引入第二个指数*滑来实现这一点,这一次,对随机梯度的*方序列进行*滑。

下面的公式显示了具有第一次和第二次*滑的完整 Adam 参数更新规则。

和以前一样,这三个公式仅适用于第 i 个参数 wᵢ

线(1)是如前所述的使用*滑因子 β₁ 的随机梯度的*滑。

第(2)行是新的,它使用*滑因子 β₂ *滑随机梯度的*方,通常设置为 0.999。这个*滑的序列代表随机梯度的方差。初始值 vᵢ,₀ 被设置为 0。

第(3)行被改变,单个学习率 α 现在被方差的*方根(这是标准偏差)反向缩放。 ε 是一个小正数,以避免在标准差为 0 时被零除。 ε 通常设置为 10⁻⁸.

从上面的公式我们可以看出,如果一个参数的值变化很大,那么它的方差很大,那么适应的学习速率就会降低,反之亦然。每个参数的学习速率的这种自适应调整导致不同参数的不同学习速率。

注意,实际的 Adam 算法对*滑的随机梯度和随机梯度的*滑*方有偏差校正。我决定不谈论偏差校正,因为这篇文章的目的是说明 Adam 解决随机梯度下降算法问题背后的直觉。如果你对亚当的完整版感兴趣,有很多很好的参考,比如这里的这里的和这里的。

结论

本文展示了我们如何证明随机梯度下降是否适用于我们的机器学习模型。在我们有了证明之后,我们知道使用随机梯度下降是正确的。但不一定是有效率的事情。然后,本文简要介绍了 Adam 优化器,并解释了它如何使随机梯度下降更有效。

支持我

如果你喜欢我的故事,如果你考虑支持我,通过这个链接成为灵媒会员,我将不胜感激:https://jasonweiyi.medium.com/membership。

我会继续写这些故事。

你能建立一个机器学习模型来监控另一个模型吗?

原文:https://towardsdatascience.com/can-you-build-a-machine-learning-model-to-monitor-another-model-15ad561d26df?source=collection_archive---------10-----------------------

图片作者。

你能训练一个机器学习模型来预测你的模型的错误吗?

没有什么能阻止你去尝试。但很有可能,没有它你会过得更好。

我们不止一次看到有人提出这个想法。

表面上听起来很合理。机器学习模型会出错。让我们利用这些错误训练另一个模型来预测第一个模型的失误!一种“信任检测器”,基于我们的模型在过去的表现。

图片作者。

从错误中学习本身就很有意义。

这种精确的方法是机器学习中 boosting 技术的基础。它在很多集成算法中实现,比如决策树上的梯度提升。每一个下一个模型都被训练来纠正前一个模型的错误。模型合成比一个执行得更好。

图片作者。

但是它能帮助我们训练一个独立的第二个模型来预测第一个模型是否正确吗?

答案可能会令人失望。

让我们通过例子来思考。

训练看门狗

**比方说,你有一个需求预测模型。**你想在它不对的时候抓住它。

你决定在第一个模型错误的基础上训练一个新模型。这到底意味着什么?

这是一个回归任务,我们预测一个连续变量。一旦我们知道了实际的销售量,我们就可以计算模型误差。我们可以选择像 MAPE 或 RMSE 这样的城市。然后,我们将使用该指标的值作为目标来训练模型。

图片作者。

**或者我们来举个分类的例子:**信用贷款违约的概率。

我们的贷款预测模型可能是一个概率分类。每个客户都会得到一个从 0 到 100 的分数,来衡量他们违约的可能性。在某个临界值,我们拒绝贷款。

总有一天,我们会知道真相。我们的一些预测可能是假阴性:我们给了那些仍然违约的人贷款。

但是,如果我们对所有的预测不加审查就采取行动,我们永远也不会了解假阳性。如果我们错误地拒绝了贷款,这个反馈会留给客户。

我们仍然可以利用我们得到的部分知识。或许,采用违约客户的预测概率,然后训练一个新的模型来预测类似的错误?

图片作者。

这能行吗?

是,也不是。

技术上是可行的。也就是说,你可以训练一个模型来预测一些事情。

但是如果是这样,这意味着你应该重新训练初始模型!

让我们解释一下。

**为什么机器学习模型会出错?**撇开数据质量不谈,通常是以下两种情况之一:

  1. **模型训练的数据中没有足够的信号。**还是数据不够。总体而言,或针对失败的特定部分。该模型没有学到任何有用的东西,现在返回一个奇怪的响应。
  2. 我们的模型不够好。从数据中正确捕捉信号太简单了。它不知道它可以潜在地学习的东西。

在第一种情况下,模型误差没有模式。因此,任何训练“看门狗”模型的尝试都会失败。没有什么新东西要学。

在第二种情况下,你也许能训练出一个更好的模型!一个更复杂的模型,更适合数据来捕捉所有的模式。

但如果可以这样做,为什么还要训练“看门狗”呢?为什么不更新第一个模型呢?它可以从我们第一次应用它时得到的真实世界的反馈中学习。

图片作者。

一个模型来统治他们

**很有可能,我们最初的模型并不“糟糕”**这些可能是发生变化的客户,或者是带来新模式的一些现实情况。认为疫情影响了销售和信用行为。我们已经讨论过的相同的旧的数据和概念漂移。

我们可以获取关于销售和贷款违约的新数据,并将其添加到旧的训练集中。

我们不会预测“错误”我们将教会我们的模型预测完全相同的事情。一个人拖欠贷款的可能性有多大?销售量会是多少?但这将是一个新的、更新的模式,从自己的错误中吸取教训。

就是这样!

旁边的“看门狗”型号不会增值。

它根本没有其他数据可以借鉴。这两种型号使用相同的功能集,并且可以访问相同的信号。

如果新模型出错,“看门狗”模型也会错过它。

我们在相同特征集上训练的第二个模型将信任第一个模型。(图片由作者提供)。

**一个例外是,我们无法访问原始模型,也无法直接对其进行重新培训。**例如,它属于第三方或因法规而固定。

如果我们从现实生活的应用环境和实际标签中获得新数据,我们确实可以构建第二个模型。然而,这是一种人为的限制。如果我们自己在维护原来的模型,这样做是没有意义的。

我们能做些什么呢?

“看门狗”模式的想法行不通。我们还能做什么?

先说为什么。

**我们的主要目标是构建在生产中表现良好的值得信赖的模型。**我们希望尽量减少错误的预测。其中一些对我们来说可能很昂贵。

假设我们在建模方面尽了最大努力,我们可以使用其他方法来确保我们的模型可靠地运行。

首先,建立常规监控流程。

是的,这种方法不能直接解决模型产生的每个错误。但它建立了一种保持和改善模型性能的方法,从而最大限度地减少规模误差。

这包括通过监控输入分布和预测的变化来检测数据和概念漂移的早期迹象。

使用 的数据漂移监控示例显然是 需求预测 教程中的 。(图片由作者提供。)

第二,考虑用好的旧规则耦合机器学习。

如果我们更详细地分析我们的模型行为,我们可以识别出它表现不好的地方。然后,我们可以将模型应用限制在那些我们知道模型有更多机会成功的情况下。

在详细的教程中,我们探索了如何在员工流失预测任务中应用这个想法。我们还考虑为概率分类添加一个自定义阈值,以*衡假阳性和假阴性错误。

图片作者。

第三,我们可以在模型输入上添加统计检查。

在“看门狗”模型中,想法是判断我们是否可以信任模型输出。相反,我们可以检测输入数据中的异常值。目标是验证它与模型所训练的内容有多大的不同。例如,如果一个特定的输入与模型之前看到的“太不一样”,我们可以发送它进行人工检查。

旁注。感谢我们的一位读者引发了这场对话!

在回归问题中,有时候可以建立一个“看门狗”模型。考虑到预测误差的符号,当您的原始模型优化预测误差时,就会出现这种情况。如果第二个“看门狗”模型预测的是绝对错误,它可能会从数据集中获得更多信息。

但这里有一件事:如果它有效,这并不意味着这个模型是“错误的”或者如何纠正它。相反,它是评估数据输入不确定性的一种间接方法。(这里有一篇整篇论文详细探讨了这一点)。

实际上,这又让我们回到了同一个备选方案。让我们检查输入数据是否属于相同的分布,而不是训练第二个模型!

总结

我们都希望我们的机器学习模型表现良好,并知道我们可以信任模型输出。

虽然用另一个受监督的“看门狗”模型来监控你的机器学习模型的乐观想法成功的机会很低,但这种意图本身有其优点。还有其他方法可以保证你的模型的生产质量。

这些包括建立一个全面的监控过程,设计定制的模型应用场景,检测异常值,等等。

在下面的文章中,我们将更详细地探讨它们。

最初发表于【https://evidentlyai.com】并与 伊莲娜 合著。

在 appeally AI,我们创建了开源工具来分析和监控机器学习模型。在 GitHub 上查看我们的 项目,如果喜欢就给它一颗星吧!

想留在圈子里吗?

  • 报名参加 我们的每月简讯。
  • 关注 推特 Linkedin
  • 加入我们的 不和谐社区 聊天连线。

分割乳房 x 光片中的异常(第 1 部分,共 3 部分)

原文:https://towardsdatascience.com/can-you-find-the-breast-tumours-part-1-of-3-1473ba685036?source=collection_archive---------10-----------------------

点击导航:第 1 部分-> 第 2 部分 - > 第 3 部分

在 TensorFlow 2 中对乳房 x 光片实施深度学习语义分割管道的分步指南

图片作者。从 CBIS-DDSM 取回的乳房 x 光片和口罩。

如果你正在阅读这篇文章,很可能我们有着相似的兴趣,从事着相似的行业。所以让我们 通过 LinkedIn 连接起来,在这里我分享我关于 AI 和 ML 的想法和资源的花絮!

文章结构

本文是一个 3 部分系列的第 1 部分,介绍了我如何解决一个深度学习项目使用图像分割模型 识别乳房 x 光扫描中的肿块异常。 作为对项目进行详细分解的结果,这是对计算机视觉中的核心问题之一——语义分割的全面概述,也是对在 TensorFlow 2 中执行这个项目的技术细节的深入探究。

第一部分:

  • 问题陈述。
  • 什么是语义切分。
  • 数据集下载指南。
  • 你会在数据集中找到什么。
  • 解开数据集的嵌套文件夹结构。
  • 数据探索。

第二部分:

  • 图像预处理流水线概述。
  • 原始乳房 x 光片的一般问题。
  • 深入研究原始乳房 x 光片的预处理流程。
  • 深入到相应掩码的预处理管道。

第三部分:

  • 介绍 VGG-16 U-Net 模型。
  • 在 TensorFlow 2 中实现模型。
  • 训练模型的注意事项。
  • 结果和事后分析。
  • 结束了。

GitHub 知识库

这个项目的代码可以在这个库的 my Github 中找到。

1.问题陈述

该项目的目标是分割扫描的乳房 x 光片图像中的肿块异常

全乳房 x 线扫描将用作图像分割模型的 2D 输入,其各自的二元掩模作为基础事实标签。该模型将输出每个乳房 x 光片的预测掩模。

图一。模型管道、输入和输出图像以及输入标签的简要概述。从 CBIS-DDSM 取回的乳房 x 光片和口罩。作者绘制的图像。

1.1.所选数据集-CBIS-DDSM

我选择使用 CBIS-DDSM 数据集,因为它适合中等复杂程度的计算机视觉项目。它拥有 2620 张扫描的乳房 x 光照片,足以进行像样的模型训练。此外,由于 CBIS-DDSM 数据集包含真实世界的乳房 x 线照片扫描,它们足够“杂乱”,因此需要进行鲁棒的和有意的图像预处理,以便在手边的任务中获得体面的结果。图像预处理在 第二部分这里有所涉及。

最有趣的是,数据集中的每张乳房 x 线照片都带有一个二元掩模,仅指示异常的大致位置。由于这些掩模不提供精确的分割,因此需要实现用于精确特征提取和诊断的分割算法。

这些是我选择 CBIS-DDSM 数据集来处理语义分割任务的主要原因。

图二。原始乳房 x 光扫描及其各自的二元掩模的例子。每列代表一个独特的患者。覆盖图(底行)由我生成,不在数据集中提供。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

2.什么是语义切分?

简而言之,任何种类的分割(是的,存在不止一种分割,是的,除了分割还有其他方法,即定位和检测)都回答了以下问题:

“感兴趣的对象位于图像的什么位置?”

在场景理解的业务中,找到感兴趣的对象在图像中的位置是图像分类的自然步骤。图像分类告诉我们*“图像中有什么”* (即它对整个输入图像进行预测)。定位、检测和分割然后告诉我们*“[感兴趣对象]在图像中的位置”。*

图三。图像分类与分割。作者绘制的图像。

有两种主要形式的姿态信息告诉我们物体在图像中的位置——边界框遮罩物体定位模型和物体检测模型输出预测包围盒,而图像分割模型输出预测遮罩。图像分割可以进一步分解为语义分割模型和实例分割模型。因此,用于在图像中定位对象的四种主要类型的技术是:

  • **对象定位:包括定位一个对象类(又名标签)的一个实例,通常是通过预测一个以实例为中心的紧密裁剪的边界框。它通常带有分类,你会遇到的常见术语是‘分类+本地化’
  • 对象检测:涉及检测图像中一个或多个对象类的多个实例。类似于对象定位,它预测每个对象类的每个检测实例周围的边界框
  • 语义分割:**为图像的每个像素预测其所属的对象类别(在两个或多个对象类别中)。模型必须知道所有的对象类。输出是预测的屏蔽
  • 实例切分:**是语义切分的一种更精细的形式。区别在于它能够区分同一对象类的两个实例。例如,它能够在人行道的图像中将一个行人与另一个行人分开。输出也是预测的屏蔽

图 4。上述 4 种技术的输出说明。注意语义分段和实例分段的区别。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

以上是我对技术的理解。但是,请注意,这些术语在科学界的定义并不像我们所希望的那样清晰,因此您可能会遇到其中任何一个术语的略微不同的含义。你可以参考 这篇这篇这篇 文章,对以上四个概念有更透彻的理解。

3.下载数据

数据集可以在这里找到,来自癌症成像档案。

如果您遵循下面的一般步骤,下载数据是非常简单的。请注意,我在 Mac 上工作,在其他系统上工作时可能会略有不同。

步骤 1— 从 Mac App Store 安装 NBIA 数据检索器。详细说明请点击链接。

步骤 2 —.tcia清单文件下载到您的本地计算机。

步骤 3 — 使用 NBIA 数据检索器打开刚刚下载的.tcia清单文件。

步骤 4 — 在 NBIA 数据检索器中,单击“浏览”选择您要保存数据集的目录。

步骤 5 — 然后点击“开始”开始下载数据集。

注意,因为这个数据集大约有 160GB,下载可能需要一段时间。

4.你会在数据集中找到什么

数据集包含含有钙化肿块异常或两者的乳房。这篇文章很好的总结了什么是肿块和钙化。

您将在下载的数据集中看到的混乱和嵌套的文件夹结构将在 第 2 部分 中解释和解决。现在,我们将重点了解数据集中的数据类型。

数据集包含两种主要类型的文件——DICOM(.dcm)文件和.csv文件。

图五。可在 CBIS-DDSM 数据集中找到的文件类型汇总。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

4.1..dcm文件

默认情况下,CBIS-DDSM 数据集中的图像被解压缩为 DICOM 格式。请参考本、本和本了解 DICOM 格式的简要概述以及如何在 Python 中使用 DICOM。

患者可以对同一个乳房进行两次乳房 x 线扫描,每次在不同的视图中(即 MLO 和 CC)。每张乳房 x 光照片都有以下 3 种图像:

  1. ***全乳腺扫描:*实际乳腺照片。
  2. ***裁剪图像:*质量异常的放大裁剪。
  3. ***感兴趣区域(ROI)掩模:*定位肿块异常的基础真实二元掩模。

这些图像都被解压缩到各自的.dcm文件中。这 3 种图像各有一个单独的.dcm文件(即只有 1 个肿块异常的乳房将有 3 个.dcm文件,3 种图像各一个)。每个.dcm文件包含图像(以数组的形式)和其他关于扫描的信息,如Patient's IDPatient OrientationSeries DescriptionModalityLaterality

你会发现乳房有 1 个以上的肿块异常。对于每个肿块异常,这些病例将有一个裁剪图像和一个 ROI 掩膜。

4.2.的。csv 文件

.csv文件用作乳房 x 光扫描的目录。共有 4 个.csv文件:

  1. 计算-测试-描述. csv
  2. 计算-训练-描述. csv
  3. 质量测试描述. csv
  4. Mass-Train-Description.csv

这些文件中的每一个都包含关于每张乳房 x 光照片的信息,例如乳房密度、图像视图和病理学。请注意,在下面的行中有重复的患者 ID。同样,这表明单个患者可以有多张乳房 x 光照片(同一个乳房的多个视图,左右乳房的乳房 x 光照片,或者两者都有)。

5.解开数据集的嵌套文件夹结构

在使用 CBIS-DDSM 数据集的其他项目中,一个经常被忽视的解释是将文件夹结构重新组织成易于使用的结构。

从下面的片段中,我们看到下载数据集的原始文件夹结构是嵌套*,有非描述性的子文件夹名称,有非唯一的 *.dcm* 文件名。这使得将图像输入图像预处理管道(以及最终的模型训练管道)变得极具挑战性。因此,我们将编写一些代码来创建一个新的文件夹结构来解决这些问题。*

5.1.解释原始文件夹结构

*Folder structure BEFORE restructuring
=====================================**CBIS-DDSM**
│
├── **Calc****-Test_P_00038_LEFT_CC**
│   └── **1.3.6.1.4.1.9590...**
│       └── **1.3.6.1.4.1.9590..**
│           └── 1-1.dcm <--- full mammogram scan
│
├── **Calc****-Test_P_00038_LEFT_CC_1**
│   └── **1.3.6.1.4.1.9590...**
│       └── **1.3.6.1.4.1.9590...**
│           ├── 1-1.dcm <--- binary mask? cropped image?
│           └── 1-2.dcm <--- cropped image? binary mask?
...┌─────────────────┐│ **bold : folder** │
│ non-bold : file │
└─────────────────┘*

患者 P_00038 的左 CC 乳房 x 光片扫描保存为父文件夹Calc-Test_P_00038_LEFT_CC下的1-1.dcm文件。分解父文件夹名称,我们有:

  • Calc(或Mass):乳房 x 光照片中出现的异常类型。
  • Test(或Train):乳房 x 光片属于测试集(CBIS-DDSM 已经将乳房 x 光片分为训练集和测试集)。
  • P_00038:患者的 ID。
  • LEFT(或RIGHT):左胸。
  • CC(或MLO):乳房 x 光扫描的方向。

患者 P_00038 的左 CC 乳房 x 光扫描有其相应的二元掩模和裁剪图像。这些文件保存在一个单独的文件夹Calc-Test_P_00038_LEFT_CC_1(注意文件夹名末尾的_1)。混乱的部分来了——仅仅从文件名中不可能分辨出1-1.dcm1-2.dcm分别是二进制蒙版还是裁剪后的图像,反之亦然。如果乳房 x 光片有一个以上的异常,那么每个异常对应的掩模和裁剪图像将以类似的方式保存,但保存在以_2_3等结尾的单独文件夹中。

5.2.创建新的文件夹结构

下面的代码片段显示了重组后的新文件夹结构。现在不再嵌套单独的文件有唯一的和描述性的文件名*。*

*Folder structure AFTER restructuring
=====================================**CBIS-DDSM**
│
├── **Calc**
│   ├── **Test**
│   │  ├── Calc-Test_P_00038_LEFT_CC_FULL.dcm
│   │  ├── Calc-Test_P_00038_LEFT_CC_CROP_1.dcm
│   │  ├── Calc-Test_P_00038_LEFT_CC_MASK_1.dcm
│   │  ...
│   │  └── Calc-Test_P_XXXXX_LEFT_MLO_MASK_1.dcm
│   │
│   └── **Train**
│       ├── Calc-Train_P_XXXXX_LEFT_MLO_FULL.dcm
│       ...
│       └── Calc-Train_P_XXXXX_RIGHT_CC_MASK_1.dcm
│
└── **Mass**
    ├── **Test**
    │  ├── Mass-Test_P_XXXXX_LEFT_CC_FULL.dcm
    │  ...
    │  └── Mass-Test_P_XXXXX_LEFT_MLO_MASK_1.dcm
    │
    └── **Train**
        ├── Mass-Train_P_XXXXX_LEFT_MLO_FULL.dcm
        ...
        └── Mass-Train_P_XXXXX_RIGHT_CC_MASK_1.dcm┌─────────────────┐│ **bold : folder** │
│ non-bold : file │
└─────────────────┘*

我创建了一组助手函数来实现上面的文件夹结构。

  • new_name_dcm()上面写着。并将它从1-1.dcm1-2.dcm重命名为更具描述性的名称。
  • move_dcm_up()然后移动改名。dcm 文件从嵌套文件夹结构向上移动到其父文件夹中。
  • delete_empty_folder()然后删除任何空文件夹(在递归命名和移动。dcm 文件)。

在所有这些之上,count_dicom()统计了。重组前后的 dcm 文件,只是为了确保。重组前后的 dcm 文件是相同的。下面的代码片段显示了进行这种重组的主要函数。关于每个助手函数的详细信息,请参考项目的资源库。

点击 此处 查看全部三个功能的完整代码。

6.数据探索

6.1.处理不止一种异常情况

图六。包含钙化的乳房 x 光片和包含肿块异常的乳房 x 光片的分布。作者绘制的图像。

在数据集中的 2620 次乳房 x 光扫描中,有 1592 次包含肿块异常(其余的仅包含钙化异常)。这 1592 张乳房 x 光照片是我们将要处理的。在这 1592 次扫描中,71 次包含 1 个以上的肿块异常。因此,这 71 张乳房 x 光照片将具有 1 个以上的二元掩模(每个异常 1 个)。**

图 7。乳腺 x 线照片中肿块异常计数的分布(在 1 个肿块异常和> 1 个肿块异常之间)。作者绘制的图像。

图 8。有 1 个以上异常的乳房 x 线照片示例。从 DDSM CBIS取回的乳房 x 光片和口罩。作者插图。

注意有 1 个以上肿块异常的乳房 x 线照片是很重要的,因为它们的遮罩不应该单独处理。直观地说,如果我们将每个遮罩视为同一图像的单独标签,那么每当模型看到不同的遮罩但用于同一图像时,它都会感到困惑。因此,我们应该将掩模相加为单个掩模,并且使用该相加的掩模作为乳房 x 光照片的唯一标签。关于如何对掩码求和的代码将在 第二部分 中介绍。

图九。具有 1 个以上肿块异常的乳房 x 线照片的加总遮罩示例。当训练分割模型时,总和掩模将被用作其相应输入图像的唯一标签。从 CBIS-DDSM 取回的乳房 x 光片和口罩。作者插图。

接下来,第二部分:图像预处理

在本文中,我们讨论了问题陈述背后的动机,什么是语义分割,以及我们将使用的 CBIS-DDSM 数据集的重要数据。

第 2 部分 中,我们将分解我所采用的各种图像预处理技术的直觉,以及代码实现。

和往常一样,这个项目的代码可以在 my Github 的这个库中找到。

第二部 第三部

谢谢你

如果你已经读完了这篇文章,我希望你喜欢这篇文章。如果这篇文章给你自己的项目带来了一些灵感、价值或帮助,请随意与你的社区分享。此外,任何建设性的问题、反馈或讨论都是绝对受欢迎的,所以请随时在下面评论,或者在 LinkedIn 上联系我,这里是 或Twitter @ CleonW _

请在 Medium ( Cleon Wong )上关注我,了解我的下一篇文章!

分割乳房 x 光片中的异常(第 2 部分,共 3 部分)

原文:https://towardsdatascience.com/can-you-find-the-breast-tumours-part-2-of-3-1d43840707fc?source=collection_archive---------10-----------------------

点击导航:第一部分 - >第二部分->-第三部分

在 TensorFlow 2 中对乳房 x 光片实施深度学习语义分割管道的分步指南。

作者绘制的图像。从 CBIS-DDSM 取回的乳房 x 光片和口罩。

如果你正在阅读这篇文章,很可能我们有着相似的兴趣,从事着相似的行业。所以让我们 通过 LinkedIn 连接起来,在这里我分享我关于 AI 和 ML 的想法和资源的花絮!

文章结构

本文是一个 3 部分系列的第 2 部分,介绍了我如何解决一个深度学习项目使用图像分割模型 识别乳房 x 光扫描中的肿块异常。 作为对项目进行详细分解的结果,这是对计算机视觉中的核心问题之一——语义分割的全面概述,也是对在 TensorFlow 2 中执行这个项目的技术细节的深入探究。

第一部分:

  • 问题陈述。
  • 什么是语义切分。
  • 数据集下载指南。
  • 你会在数据集中找到什么。
  • 解开数据集的嵌套文件夹结构。
  • 数据探索。

第二部分:

  • 图像预处理流水线概述。
  • 原始乳房 x 光片的一般问题。
  • 深入研究原始乳房 x 光片的预处理流程。
  • 深入到相应掩码的预处理管道。

第三部分:

  • 介绍 VGG-16 U-Net 模型。
  • 在 TensorFlow 2 中实现模型。
  • 训练模型的注意事项。
  • 结果和事后分析。
  • 结束了。

GitHub 知识库

这个项目的代码可以在这个库的 my Github 中找到。

上接第 1 部分

我们结束了第一部分 ,很好地理解了问题陈述背后的动机,为什么选择 CBIS-DDSM 数据集,以及数据集中具体提供了哪些数据。在这一部分中,我们将涵盖整个图像预处理管道,它允许我们从原始图像进展到准备好输入语义分割模型的图像。

免责声明:这将是一个深入的教程。这是一个相当长的阅读,但你会留下广泛的知识,一般的图像预处理方法和可重用的代码,您可以添加到自己的图像预处理“工具箱”。

1.图像预处理流水线综述

图一。通过图像预处理管道的 6 幅图像的动画样本,显示了每一步的变化。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

图像的图像预处理相当于我们熟悉的其他类型数据(表格数据、文本流等)的“数据清理”。).就像任何其他使用这些类型数据的机器学习管道一样,图像预处理(或数据清理)的目标是准备好输入模型的数据,提高数据质量,并使模型更容易从最高质量的信息中学习特征和模式

我们如何对图像进行预处理,使得“模型更容易从中学习特征和模式”?对此没有一个放之四海而皆准的答案,这在很大程度上取决于我们试图解决的计算机视觉问题和我们使用的图像。

在这个项目中,我们的图像预处理管道由图 2 中所示的步骤组成,我将在接下来的章节中详细解释。

图二。用于全乳房 x 线扫描的图像预处理管道及其相应的二进制地面真实掩模的概述。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

2.原始乳房 x 光片的一般问题

为什么管道是这样的?为了理解其背后的直觉,我们需要目测检查原始的乳房 x 光片。这些原始乳房 x 光照片提出了阐明所选图像预处理步骤的一般“问题”。管道的目的是修复这些问题,以便我们最终获得模型可以学习的高质量图像。

图三。选定的原始乳房 x 光片及其需要通过图像预处理管道解决的一般“问题”的注释。问题按颜色分类。从 CBIS-DDSM 取回的乳房 x 光片和口罩。作者绘制的图像。

通过对原始乳房 x 光片的视觉检查,我们可以看到乳房 x 光片通常存在以下问题:

  • 一些边缘有明亮的白色边框/角落。这些边界可能会创建一个任意的边缘,作为模型可以学习的图像中的一个特征。
  • 背景中漂浮的人工制品。在实践中,这些伪影用作标记,放射科医生使用这些标记来区分左侧乳房和右侧乳房,并且还识别扫描的方向。例如,我们看到“LCC ”,它表示左侧乳房,CC 方向。
  • 乳房朝向的方向不一致。一些面向左,而另一些面向右。这是一个问题,因为它可能会使图像预处理变得复杂。
  • 有些乳房 x 光片的对比度。这使得乳房区域看起来几乎是单调的灰色,导致乳房组织和肿块异常之间几乎没有纹理和有意义的差异。这可能会减缓模型的学习。
  • 由于这些乳房 x 光片是从实际的硬拷贝扫描并保存为软拷贝,因此背景并不是全黑的。背景可能包含不经意间可学习但无意义的特征,这些特征对人眼来说是不可见的。
  • 图像不是方形的。大多数计算机视觉深度神经网络模型要求输入图像是正方形的。

3.深入研究原始乳房 x 光片的预处理流程

我们将首先解释乳房 x 线照片扫描的图像预处理步骤,然后解释它们对应的二元掩模的步骤。

我为每一步都编写了一个助手函数,因为这使得管道更加模块化,并且能够轻松执行整个管道。为了简洁起见,我删除了 doc 字符串和 try-except 块。访问我的库,在这里访问完整的代码。

import numpy as np
import cv2
import pydicom

3.1.步骤 1-裁剪边框

**这一步解决:**亮白色边框/边角。

步骤 1 —裁剪订单()。点击 此处 查看完整代码。

我从左右边缘剪切了图像宽度的 1%,从上下边缘剪切了图像高度的 4%。不同的乳房 x 光扫描具有不同厚度的边界。经过反复试验,我发现这些百分比可以很好地去除乳房 x 光扫描中的大部分边界。虽然分割算法是一种更复杂的识别每张乳房 x 光照片边界的方法,但我选择了这种有点基础的方法,因为它更快,并且它对大多数图像的结果对我们的用例来说足够好。毕竟,在图像预处理管道中使用分割算法来完成分割任务是一种大材小用。

图 4。图像预处理流程的第一步——裁剪边框。以红色突出显示的是需要移除的边框和边角示例。从 CBIS-DDSM 取回的乳房 x 光片和口罩。作者绘制的图像。

3.2.步骤 2-最小-最大归一化

**这一步求解:**像素值范围从[0,65535]到[0,1]。

步骤 2 —最小最大规格化()。点击 此处 查看完整代码。

乳房 x 光片以 16 位数组的形式保存在。dcm 文件。这意味着像素值的范围从[0,65535] (2 ⁶ = 65535)。这些大整数值可能会减慢神经网络的学习过程。因此,将这些值归一化到[0,1]范围内是一种很好的做法。当使用 OpenCV 和 Matplotlib 库时,范围为[0,1]也使图像可视化更简单。

3.3.第 3 步——消除假象

**该步骤解决:**背景中漂浮的赝像。

消除赝像是一个复杂的过程,可以通过多种方式实现。伪影可以以不同的大小和强度出现,并且它们可以位于图像的几乎任何部分,这取决于乳房面对的方向。

第三步会实现两件事。去除任何伪像,并确保背景完全是黑色的(即像素值为 0)。

为了消除假象,我按照以下顺序实现了四个函数:

  1. globalBinarise()
  2. editMask()
  3. sortContoursByArea()
  4. xLargestBlobs()

让我们从头开始建立每个功能背后的直觉。

从根本上说,我们需要认识到去除伪影与仅保留乳房 x 光照片中的乳房区域达到了相同的效果。乳房区域保持不变,其他一切都应该是背景(即完全黑色)。有了这种直觉,我们现在可以重新表述从以下对象中移除人工制品的问题:

  • 定位并移除人工制品以…
  • 定位乳房区域,保留它,然后移除其他所有内容。

这一重新表述的目标正是这四项职能所要实现的。

Bi 目测,可以肯定的说大部分背景像素非常接*黑色(即像素值非常接* 0)。利用这种直觉,我们可以使用阈值(thresh)对乳房 x 线照片进行二值化,以创建二值掩模,其中 0 表示背景像素,1 表示属于乳房区域、伪影或噪声的像素。这就是globalBinarise()函数的作用。

步骤 3a — globalBinarise()。点击 此处 查看完整代码。

图五。图像预处理流水线的步骤 3a。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

上面显示了globalBinarise()的输出。实际上,我们看到任何为 0(黑色)的像素属于背景,任何为 1(白色)的像素或者是赝像、乳房或者是背景噪声(例如背景中的斑点)。

在生成二值掩模之后,我们在掩模中扩展白色轮廓的边界。这确保了我们真正捕捉到任何人工制品的整个区域,包括其边界。这是通过使用函数editMask()中的开始形态操作来完成的。

步骤 3b —编辑掩码()。点击 此处 查看完整代码。

图六。图像预处理流水线的步骤 3b。从 DDSM CBIS 取回的乳房 x 光片和口罩。作者绘制的图像。

现在我们有了编辑过的二进制掩模,我们面临下一个问题——二进制化将乳房区域和伪影都识别为 1(即白色区域)。我们现在需要知道哪个白色轮廓属于乳房区域,因为这是我们想要保留的区域。下面是下一个直观的推理——从视觉检查来看,乳房轮廓几乎总是二元掩模中最大的轮廓。因此,如果我们能够根据它们的面积来计算和分类每个轮廓,我们将能够将乳房轮廓识别为具有最大面积的轮廓。这正是sortContoursByArea()所做的。

步骤 3c — sortContoursByArea()。点击 此处 查看完整代码。

有了排序后的轮廓,我们现在可以选择要在乳房 x 光照片中保留哪些轮廓。如上所述,由于乳房区域是掩模中最大的区域,并且它几乎总是被二值化为单个区域,所以我们可以有把握地说,掩模中的顶部 1 轮廓是我们想要从原始乳房 x 光照片中保留的唯一区域。这就是xLargestBlobs()的作用。它保留最大的x斑点(也称为轮廓)并丢弃其余的。我使用了x=1,但是该函数可以接受x的任何值。

步骤 3d — xLargestBlobs()。点击 此处 查看完整代码。

图 7。图像预处理流水线的步骤 3c 和 3d。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

最后,我们可以使用这个遮罩来掩盖原始图像中的伪影。乳房 x 光检查。这意味着“保留白色区域,将其他区域设置为黑色”。applyMask()正是如此。

步骤 3e —应用屏蔽()。点击 此处 查看完整代码。

图 8。图像预处理流水线的步骤 3e。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

而且……我们已经完成了移除艺术品的工作!现在,你可以看到上面提到的步骤是如何帮助我们实现两件事的——去除任何伪像,使背景完全变黑(即像素值为 0)

现在已经忙得不可开交了,休息一下,让我们进入流水线的第 4 步。

3.4.步骤 4 —水*翻转

**这一步解决:**乳房方向不一致。

这个步骤标准化了乳房在所有乳房 x 光照片中所面对的方向。在数据集中,大多数乳房区域位于乳房 x 光片的左侧,面向右侧。本能地,将所有的乳房 x 光片定位在相同的方向似乎没有必要,因为它们将在数据扩充期间随机翻转(这将在第 3 部分 的 中介绍)。

虽然这是真的,但确保所有乳房 x 光片都在左边会使我们在步骤 6 中填充乳房 x 光片时更容易。为什么会这样呢?因为所有的乳房区域都在左边,我们知道我们只需要填充每张乳房 x 光片的右边来形成一个正方形!

checkLRFlip()首先检查乳房 x 光片是否需要翻转。这是通过比较乳房 x 线照片左半部分和右半部分的像素值的总和来实现的。如果后者大于前者,则意味着乳房区域在右侧,需要翻转,然后由函数makeLRFlip()完成。

步骤 4 — checkLRFlip()和 makeLRFlip()。点击 此处 查看完整代码。

3.5.步骤 5 — CLAHE 增强

**这一步解决:**乳腺组织对比度差。

对比度受限的自适应直方图均衡化(CLAHE)用于增强灰度图像的对比度。这有助于增强乳房 x 光照片中的小细节、纹理和特征,否则这些细节、纹理和特征对于模型学习来说是有挑战性的。

注意,因为背景现在是全黑的(来自步骤 3 ,我们不会遇到背景中的噪声被无意增强的问题。clahe()执行对比度增强。

第 5 步— clahe()。点击 此处 查看完整代码。

图九。图像预处理流水线的步骤 4 和 5。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

3.6.第六步——垫成正方形

**这一步解决:**图像不是正方形。

最后一步是将图像填充成正方形。这是必要的,因为大多数(如果不是全部)计算机视觉模型接受正方形图像作为输入。为此,pad()检索乳房 x 光片的尺寸,并在其右侧边缘添加必要数量的黑色像素列。

由于在执行步骤 3 后背景完全为黑色,添加黑色像素不会在最终的正方形图像中引入任意边缘。

第 6 步—填充()。点击 此处 查看完整代码。

图 10。最后一步,图像预处理流水线的第 6 步。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

3.7.链接步骤以形成流水线

图 11。通过图像预处理管道的 6 幅图像的动画样本,显示了每一步的变化。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

最后,我们使用下面的fullMammoPreprocess()助手函数将上面提到的 6 个步骤连接起来。对于该函数接收的每一张原始乳房 x 光片(img),它都将其通过管道,并输出其预处理后的形式(img_pre)和一个布尔值lr_flip。如果lr_flip = True,我们知道乳房 x 光片已经在步骤 4 中翻转,否则它没有翻转。这对预处理二进制掩码很重要,这将在第 4 节的中解释。

将管道连接在一起。点击 此处 查看完整代码。

而且……我们已经完成了原始乳房 x 光片的图像预处理流程!

4.深入研究相应掩码的预处理管道

预处理每张乳房 x 光照片的相应掩模背后的直觉很简单。为了建立直觉,我们需要了解模型是如何使用遮罩的。

4.1.管道

二进制掩码被用作基本事实标签。这些标签用于在训练过程中通过将误差与模型的预测分割进行比较来计算误差。因此,每个预处理的乳房 x 光照片需要其对应的二元掩模具有相同的形状并且面向相同的方向。**因此,我们需要对每个对应的蒙版执行步骤 1 (裁剪边框)步骤 4 (水*翻转)步骤 6 (填充)。**这解释了为什么我们需要在fullMammoPreprocess()中返回布尔变量lr_flip。它告诉我们是否需要对每个掩模执行步骤 4

由于掩模是二进制的(即像素值仅为 0 或 1),因此不需要增强、噪声去除或归一化。这意味着步骤 2 (最小-最大归一化)步骤 3 (去除伪影)和步骤 5 (CLAHE 增强)是不必要的。

因此,我们简单地编写了一个名为maskPreprocess()的函数,它将为上述原始乳房 x 光片的预处理编写的步骤 1步骤 4步骤 6 的必要辅助函数链接起来。

对应掩模的图像预处理流水线。点击 此处 查看完整代码。

4.2.求和掩模(参见第 1 部分的第 6.1 节)

最后一件事。作为掩模预处理的一部分,我们需要对包含一个以上肿块异常的乳房 x 光片的掩模求和(如第 1 部分 的 第 6.1 节所述)。正如所承诺的,下面是对包含多个肿块异常的乳房 x 线照片掩模求和的代码。你可以在我的库这里找到全部代码。

具有一个以上肿块异常的乳房 x 线照片的总和掩模。参见第一部分 的 第 6.1 节。点击 此处 查看完整代码。

接下来,第 3 部分:构建图像分割模型

恭喜你坚持到这篇文章的结尾!在这篇文章中,我们对原始乳房 x 光片的图像预处理管道及其相应的掩模有了很好的直觉。因此,我们选择了一些通用的图像预处理辅助函数,可以将它们添加到现有的图像预处理工具包中。

第 3 部分 中,我们将通过检查选择的图像分割模型(提示—它是一种 U-Net)、在 Tensorflow 2 中实现它、训练模型并最终评估结果来结束这个项目。

和往常一样,这个项目的代码可以在这个库的 my Github 中找到。

谢谢你

如果你已经读完了这篇文章,我希望你喜欢这篇文章。如果这篇文章给你自己的项目带来了一些灵感、价值或帮助,请随意与你的社区分享。此外,任何建设性的问题、反馈或讨论都是绝对受欢迎的,所以请随时在下面评论,或者在 LinkedIn 上联系我,这里是 或 Twitter,地址是@CleonW_

请在 Medium ( Cleon Wong )上关注我,了解我的下一篇文章!

第三部 见!

分割乳房 x 光片中的异常(第 3 部分,共 3 部分)

原文:https://towardsdatascience.com/can-you-find-the-breast-tumours-part-3-of-3-388324241035?source=collection_archive---------12-----------------------

点击导航:第一部分->-第二部分 - >第三部分

在 TensorFlow 2 中对乳房 x 光片实施深度学习语义分割管道的分步指南

饼干——乳房 x 光片的答案将在本文结尾揭晓!图片作者。从 DDSM CBIS取回的乳房 x 光片和口罩。

如果你正在阅读这篇文章,很可能我们有着相似的兴趣,从事着相似的行业。所以让我们 通过 LinkedIn 连接起来,在这里我分享我关于 AI 和 ML 的想法和资源的花絮!

文章结构

这篇文章是一个 3 部分系列的第 3 部分,讲述了我如何解决一个深度学习项目,即使用图像分割模型 识别乳房 x 光扫描中的肿块异常。 作为对项目进行详细分解的结果,这是对计算机视觉中的核心问题之一——语义分割的全面概述,也是对在 TensorFlow 2 中执行这个项目的技术细节的深入探究。

第一部分:

  • 问题陈述。
  • 什么是语义切分。
  • 数据集下载指南。
  • 你会在数据集中找到什么。
  • 解开数据集的嵌套文件夹结构。
  • 数据探索。

第二部分:

  • 图像预处理流水线概述。
  • 原始乳房 x 光片的一般问题。
  • 深入研究原始乳房 x 光片的预处理流程。
  • 深入到相应掩码的预处理管道。

第三部分:

  • 介绍 VGG-16 U-Net 模型。
  • 在 TensorFlow 2 中实现模型。
  • 训练模型的注意事项。
  • 结果和事后分析。
  • 结束了。

GitHub 知识库

这个项目的代码可以在这个库的 my Github 中找到。

从第二部分继续

我们结束了 第二部分 ,深入了解了我们的图像预处理流程,以及每个图像预处理步骤的可重用代码。通过管道,我们能够从原始图像进展到预处理图像,这些图像可以被输入到分割模型中。

在这一部分中,我们将介绍所选分割模型(VGG 16 U 网)背后的直觉,如何在 Tensorflow 2 中实现它,以及对结果的评估。

1.介绍 VGG-16 U-Net 模型

图 1 VGG U-Net 模型架构。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

自从 Olaf Ronneberger 等人在 2015 年发布他的论文“U-Net:用于生物医学图像分割的卷积网络”中开发并记录了 U-Net 架构,U-Net 已经成为用于分割任务的常见架构。它包括两个主要部分——编码器模块**(图的上半部分)和解码器模块**(图的下半部分)。这两个部分一起形成了一个 U 形,这解释了它的名字。****

U-Net 的高层次直觉就是如此。编码器模块学习特征并告诉我们“图像中有什么”,就像在分类任务中一样。然后,解码器模块在语义上将编码器模块学习的这些低分辨率特征投射回原始输入图像的全分辨率像素空间,为我们提供全分辨率分割图。

**编码器块:通常是卷积层和最大池层的传统序列。可以把它想象成一个典型的卷积神经网络(CNN)架构,用于分类任务,但没有最后的密集层(这些类型的网络被称为全卷积网络(FCN) )。这个 FCN 可以是你自己设计的,也可以取自任何现有的 CNN,如 AlexNet 、 VGG-16 或 ResNet 。对于这项任务,我选择了 VGG-16 的编码器块(没有最终的密集层),因为我比其他 CNN 模型更好地理解它。

**解码器模块:**它是与编码器模块对称的上采样卷积和级联层的网络。从图 1 的中可以看出,从编码器块中选择的特征映射被连接到它们在解码器块中的相应层。由于 CNN 的早期层倾向于学习低级特征,而后期层学习更高级的特征,这种连接允许 U-Net 映射在所有级别上学习的特征,以产生最终的全分辨率预测分割图。

我强烈建议你阅读这篇文章,以获得关于 U-Net 架构的更深入的解释。

2.在 Tensorflow 2 中实现模型

import tensorflow as tffrom tensorflow import keras

在实际代码中,我将模型实现为一个名为unetVgg16的 Python 类对象。为了简洁起见,我只包含了下面代码中对实现至关重要的部分。您应该访问项目的存储库以获得实现该模型的完整代码。

函数buildEncoder()用于在迁移学习的帮助下构建 U-Net 的编码器部分。在第 3 行到第 8 行,我导入了 VGG-16 模型,其权重在来自 Keras 模型动物园的 ImageNet 数据集上进行了预训练。设置include_top=False从 VGG 16 中移除我们不想要的密集层(密集层被认为是 Keras 中的顶层),只给我们留下 VGG 16 的 FCN 部分。如果你对迁移学习不熟悉,这篇文章应该给你一个很好的、温和的介绍。

使用迁移学习构建模型的编码器部分。点击 此处 查看完整代码。

然后,函数buildUnet()构建解码器,从而构建整个 U-Net 架构。它调用buildEncoder()函数来创建编码器模块,并在其上构建解码器模块,最终形成 VGG-16 U-Net 的完整架构。如图 1 中的所示,解码器模块中有 5 个子模块,模块 5 从图的右侧开始,接着是左侧的最后一个卷积层(红色)。

由于buildUnet()函数包含* 300 行代码(因为它包含文档字符串、注释和换行符),您可以参考这里的库获取完整代码。在浏览代码时,记住以下几点很重要:

  • keras.layers.Conv2D()构建传统卷积层。
  • keras.layers.Dropout()插入传统的脱落层。
  • keras.layers.Concatenate()在每个子块的开始执行连接。
  • keras.layers.Conv2DTranspose()负责每个子块之间特征图的上采样。这是将编码器块学习的低分辨率特征映射投影到原始图像的全分辨率像素空间。

3.训练模型的注意事项

既然我们已经适当地预处理了图像(来自 第二部分 )并建立了模型,现在是训练模型的时候了。

我想重点谈谈训练管道的两个方面,它们对于这一分割任务至关重要且独一无二——图像增强和创建在每个训练时期结束时跟踪的自定义 IOU 指标。

3.1。图像增强

图像增强可用于从现有的训练数据中人工创建新的训练数据,也可用于在数据集中引入可变性。

有许多图像放大可以做,其中我选择了以下来执行:

  1. 随机水*翻转(概率 50%)。
  2. 随机垂直翻转(概率 50%)。
  3. 随机亮度调节。

如果你想阅读更多关于 TensorFlow 中其他可能的图像增强的内容,这篇文章是一个很好的起点。

图 2 图像增强样本图像。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

下面的代码片段显示了如何在 TensorFlow 2 中实现随机的水*翻转、垂直翻转和亮度调整。和往常一样,你可以参考项目的资源库获取的完整代码。

imgAugment() —用于图像增强的辅助函数。点击 此处 查看完整代码。

我们必须记住,只有适当的图像增强才能帮助我们的模型学习!当选择合适的增强时,最重要的考虑之一是增强必须实际产生对我们的任务有意义的真实图像。

那么,什么是不切实际和无意义的图像,可以从不适当的扩大?图 3 举例说明了对预处理后的乳腺照片进行随机旋转、剪切、宽度移动和高度移动的结果。

图 3 不适用于我们用例的图像增强(随机旋转、剪切、宽度移动和高度移动)示例。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

上面的图像是不现实的,没有意义的,因为我们在现实中几乎不会遇到这样的乳房 x 光片!当我们将这种无意义的图像输入到我们的模型中时,模型将学习对分割问题没有意义的特征,并减慢其收敛速度。还要记住,这些剪切、旋转和移动也必须应用到蒙版上,这也是非常不现实和没有意义的。

换句话说,当选择正确的图像增强来执行时,我们必须问自己,“以这种方式增强图像有意义吗?”

3.2.创建自定义 IOU 指标

TensorFlow 允许我们通过[compile](https://www.tensorflow.org/api_docs/python/tf/keras/Model#compile) API 中的metrics参数在每个训练时期结束时跟踪某些指标。通常,我们使用准确度、精确度和均方误差等指标。然而,这些度量并不十分适用于语义分割问题。相反,更常用的是交集/并集(IoU) 指标。

简而言之,IoU 是预测分割和基础事实之间的重叠百分比,除以预测分割和基础事实之间的联合面积。使用下面图 4 中的插图可以更好地解释这一点。

图 4 计算预测分割的 IoU 的简化示例。欠条是用浮点数(或分数)还是百分比来表示并不重要。作者绘制的图像。

从图示中,我们看到 IoU 的范围从 0 到 1;当预测的分割完全关闭(即,根本不与基础事实相交)时为 0,当预测的分割与基础事实完全匹配时为 1。我强烈建议阅读本文中标题为*“为什么我们使用交集而不是并集】*的部分,以更好地理解这一指标。

下面的代码片段展示了如何在 TensorFlow 中实现 IoU。参考这里的完整代码来看看我是如何在 TensorFlow 的compile API 中实现它的。

使用基础真值掩码(y-true)和预测分段(y_pred)计算交集/并集度量的自定义函数。点击 此处 查看完整代码。

3.3.训练模型

图 5 跨 43 个训练时期的二进制交叉熵损失函数和 IoU 检查点的图表。图中的每个点是每个训练(和验证)时期的*均损耗值和*均 IoU。作者绘制的图像。

最后,在以下配置下训练模型,图 5 显示了训练结果。

  • 历元数: 43(被 Keras 的早期停止)
  • 批量大小: 10
  • 学习率: 0.00001
  • 辍学率: 0.5
  • **损失函数:**二值交叉熵损失
  • 乐观者:亚当

训练和验证借据的最大值在 0.20 左右。

4.结果和事后分析

在本文的最后一部分,我们深入分析模型的预测分割(也称为预测遮罩)。由于没有很多文献对这一特定的细分问题进行了研究,因此没有可供我们比较的基准。因此,我们将目视检查掩模,并使用“第一原理”方法对结果进行启发式和逻辑评估。

4.1.分析预测的掩模

图 6 预测分割的样本(最后一列)。从 CBIS-DDSM 取回的前两列乳房 x 光片和口罩。

通过快速目测,预测的分割看起来相当准确(注意“相当准确”将在第 4.4 节中更正式地定义)。该模型能够分割大多数肿块异常。看起来模型的主要错误是分割了比地面真相遮罩中更多的区域(而不是分割得更少)。通常,这些额外的区域是乳房 x 光照片中的亮点,看起来非常像肿块异常。

请注意,模型的预测掩膜是软掩膜(与硬二进制掩膜相对,如数据集中的地面真实掩膜)。这是由于 U 形网的最终 s 形图层导致预测遮罩中的值介于 0.0 和 1.0 之间。这些像素值可以被解释为每个像素属于“异常”类别的概率(1.0 表示该像素是异常的确定性)。

4.2.0.2 的 IoU 就一定不好吗?不完全是。

虽然预测的分段通常看起来是可接受的,但是很自然地,看着图 5 中的 IoU 图,并且问,“为什么训练(和验证)时期的最高*均 IoU 只有大约 0.20?”(其他分段题有时会有 0.80 以北的白条)。

图 7 测试集图像的 IoU 分布。IoU 中值为 0.1830,*均值为 0.2033。作者绘制的图像。

在我们解决这个问题之前,请注意,模型产生的软掩码可能会导致 iou 低于硬掩码。这是有争议的,因为从软遮罩创建硬遮罩需要一些二值化技术,如阈值处理,这可能会影响 IoU 得分。然而,模型输出的柔化蒙版是需要记住的。

图 8 预测 iou 在 0.20 范围内的掩码。绿色区域表示地面真实遮罩,红色区域表示模型的预测遮罩。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

要解决问题,更重要的是看预测出来的借据在 0.20 左右的口罩,如上图图 8 所示,看是否可以接受。从这些掩码中,我们看到它们实际上是可以接受的,尽管它们的 IoU 分数很低,但与地面真相掩码没有太大的不同。同样非常重要的是,该模型能够在大多数乳房 x 光照片中分割肿块异常的细胞核。在一些乳房 x 光照片中,该模型甚至分割出了看起来确实像肿块的区域,而地面真相掩盖没有捕捉到这些区域。

因此,0.20 左右的*均 IoU 对于我们的特定分段问题来说实际上相当不错,对这种低 IoU 的一种可能解释可能是模型输出的软屏蔽。

4.3.看着最低的借条

图 9 借据接* 0 的预测掩码样本。绿色区域是地面真实遮罩,红色区域是预测遮罩。从 DDSM CBIS取回的乳房 x 光片和口罩。

看预测的白条最低的口罩也很重要。上面的图 9 示出了当异常非常小时,当乳房区域具有密集的乳房组织网时,或者两者兼有时,该模型在分割肿块异常时表现不佳。

4.4.3 种最常见质量形状的分割性能

数据集中三种最常见的肿块形状是分叶状、不规则形和椭圆形。通过查看每个团块形状的*【精确】*预测掩模的百分比,我们可以了解我们的模型对每个团块形状的分割性能。

准确预测是什么意思?我们可以在视觉上检查预测的掩模,以试探性地定义什么是“精确预测的掩模”。为此,我们首先从视觉上检查预测的掩码并识别看起来准确的掩码(即看起来非常类似于地面真实掩码),然后我们使用这些掩码的 IoU 来计算“可接受的”IoU 基准。高于基准的预测掩码可以被认为是“准确预测的”。

图 10-a、10-b 和 10-c 评估模型在 3 种最常见质量形状上的性能。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

对于每个质量形状,我查看了看起来与其对应的地面真实遮罩最相似的前 4 个预测遮罩,并将其绘制在图 10-a、10-b 和 10-c 的左侧*。我叠加了预测遮罩(红色区域)和地面真相遮罩(绿色区域),使它们更容易比较。从那里,我们看到这些预测的面具有 0.40 左右的借据。换句话说,我们可以说具有 IoU ≥ 0.4 的预测掩码可以被认为是精确预测。使用该基准,我们看到该模型对于不规则形状的块体表现最佳,其中 16.67%被该模型准确预测。*

包扎

最后,我们来到了这个 3 部分系列的结尾,在这里我们详细地分解了从乳房 x 光片中分割肿块异常的任务。在本系列中,您学习了什么是语义分割,以及如何从开始(下载数据)到结束(评估结果)构建图像分割任务的管道。最重要的是,你了解了我是如何处理流水线每个阶段面临的问题,以及我的代码背后的直觉。你现在可以将这些心智框架应用到你自己的机器学习项目中。

离开前的最后一件事——这是本系列标题图片中问题的答案!

图 11 题图答案。从 DDSM CBIS取回的乳房 x 光片和口罩。作者绘制的图像。

那么…你能找到肿瘤吗?

你应该看看本系列的第 1 部分和第 2 部分,如果你还没有,它们给出了问题陈述的一个很好的背景,并逐渐积累了从第 3 部分中获得最大收益所需的知识!

谢谢你

如果你已经读完了这篇文章,我希望你喜欢这篇文章。如果这篇文章给你自己的项目带来了一些灵感、价值或帮助,请随意与你的社区分享。此外,任何建设性的问题、反馈或讨论都是绝对受欢迎的,所以请随时在下面评论或在 LinkedIn 上联系我,这里是 或 Twitter,地址是@CleonW_

请在 Medium ( Cleon Wong )上关注我,了解我的下一篇文章!

教电脑看到你的痛苦

原文:https://towardsdatascience.com/can-you-teach-a-computer-to-see-your-pain-18c0f60eb0e4?source=collection_archive---------30-----------------------

使用 Pycaret,OpenFace,Pandas 和其他 python 魔术

图片由 Mahdis Mousavi 在 Unsplash 拍摄

背景

疼痛是一种独特的体验,由因人而异的感觉、认知、社会和情感因素混合而成。这些因素结合在一起,很难有把握地评估一个人的经历。目前,最常见和最受推崇的评估疼痛的方法是通过口头报告(例如,等级量表 1-10)。然而,这种方法可能会有偏差,并不总是可用的(非语言患者)。因此,额外的疼痛评估方法是必要的。

一种推断疼痛的技术是通过面部表情分析。历史上,研究人员通过观察面部肌肉运动来预测情绪和行为。这一过程使得理解疼痛表情中的面部运动组合成为可能。使用手动技术,面部表情分析非常耗时且工作量大,但机器学习的出现使得以更快的速度和更高的精度评估疼痛成为可能。现在,研究人员可以使用机器学习工具来创建分类器,这些分类器可以预测疼痛的存在(即分类)和强度(即回归)。下面的教程将描述如何制作用于疼痛评估的二元分类机器学习分类器。

准备数据

对于这个例子,我们使用特拉华州疼痛数据库,这是一个姿势图像库,描绘了疼痛的个人和中性面孔的个人。迄今为止,这个数据库是研究人员可获得的最大的不同疼痛图片样本。

要了解更多关于特拉华州疼痛数据库的信息,请阅读下面的文章:

https://pubmed.ncbi.nlm.nih.gov/33134750/

为本教程准备的数据是使用工具 OpenFace 提取的,该工具使用机器学习模型来评估面部肌肉运动的强度。

https://ieeexplore.ieee.org/document/7477553

作者使用 OpenFace 面部表情分析的示例

面部的肌肉运动也被称为“动作单位”。从 OpenFace 中提取的每个动作单元都是一个 0-5 范围内的连续变量,代表表达的强度。动作单位强度与特拉华州疼痛数据库中的疼痛或中性标签一致。xlsx 文件。这些数据用于训练模型。

OpenFace 分析的图片首先是从特拉华州疼痛数据库库中下载的。

如前所述,每张照片都预先做了标记(疼痛或中性)。在命令提示符下用 OpenFace 的 FaceLandmarkImg 函数分析图像目录。

!FaceLandmarkImg.exe -fdir <directory_of_pain_neutral>

包含类别(疼痛与中性)和行动单元的 Excel 文件

这里的每一行数据代表一个参与者,其类别代表疼痛或中性,AU_xx 列代表不同面部肌肉的动作单位(肌肉运动)强度。

设置模型数据

为了创建这个模型,我们将使用许多不同的 python 库。以下是最重要的:

https://pandas.pydata.org/

在上传数据文件之前,每个图像都用来自特拉华州疼痛数据库的相应行为(中性或疼痛)进行了注释。因此,我们将使用 pycaret 训练一个二进制模型。我们的模型将从面部图像中确定中性表情和疼痛表情之间的差异。

具有面部运动特征的训练数据集

加载数据

Pandas 读取我们的数据和数据集。

import pandas as pd
dataset = pd.read_excel("combined_pain_csv.xlsx")
dataset = dataset.sample(frac=1).reset_index(drop=True)
dataset

拆分数据

接下来,我们将我们的数据分成两组:训练和不可见。我们首先用训练集(自然地)训练我们的模型,然后在我们看不见的预测数据集上部署训练好的模型来评估性能。

data = dataset.sample(frac=0.95, random_state=786)
data_unseen = dataset.drop(data.index)data.reset_index(inplace=True, drop=True)
data_unseen.reset_index(inplace=True, drop=True)print('Data for Modeling: ' + str(data.shape))
print('Unseen Data For Predictions ' + str(data_unseen.shape))

拆分数据后的输出

导入 Pycaret

Pycaret 有几个不同的模块,封装了特定的机器学习算法和函数,这些算法和函数在不同的模块中一致使用。有 6 个模块可供导入。其中包括:

  • 回归
  • 分类
  • 异常检测
  • 使聚集
  • 自然语言处理
  • 关联规则挖掘

因为我们的模型旨在基于两个类来辨别预测,所以我们导入 pycaret.classification 来创建分类模型。

from pycaret.classification import *

创造实验

Pycaret 需要我们在创建模型之前设置数据。我们必须指定我们的数据框架和目标。

exp_clf102 = setup(data = data, target = 'class')

设置输出

在本实验中,疼痛被标记为 1,无疼痛被标记为 0。因此,我们的目标类别是疼痛/中性标签,我们的 17 个特征是不同面部肌肉运动的强度。

从 Cohn 和 Kanade 的数据库中提取的一些行动单位的例子

比较模型

Pycaret 最好的特性之一是 compare_models 函数。这个函数允许我们用一行代码比较 24 个不同模型的指标。我们使用 n_select 来根据精确度选择前三个模型。通过建立我们的前 3 个模型,我们可以创建一个投票分类器,通过一次比较多个模型并使用概率最高的标签来评估标签。

# Compare metrics of 24 different machine learning models 
top3 = compare_models(n_select = 3)

Pycaret 模型比较

如表中所示,Extra Tress 分类器是我们数据中性能最好的模型,其次是轻梯度推进机和逻辑回归。

每个指标的最高分以黄色突出显示。

创建模型

接下来,我们基于对上述最佳模型的分析创建一个模型。Pycaret 的 blend_models 允许我们从表中的前三个模型创建投票分类器。因此,我们的模型是 et+ lightgbm + lr,并且我们的投票系统采用至少两个一致的模型的预测。

混合分类器度量

我们的混合分类器表现得比单独的额外分类器更好。

评估模型性能

Pycaret 让我们很容易用 evaluate_model 来评估我们的模型的性能。

我们可以用混淆矩阵来查看标签的分类。

混淆矩阵输出

我们还可以查看 AUC 图。

AUC 图

调整并最终确定模型

让我们通过调整和最终确定对模型进行最后的润色。

tune = tune_model(blend)
final = finalize_model(tune)
predict_model(final)

在我们调整和完成之后,我们的模型达到了 100%的准确性!

结论

原来如此!我们教会了一台计算机根据一组摆出的疼痛和中性姿势的图像来预测疼痛的表情。我们的模型根据面部分析的肌肉运动强度预测疼痛/中性标签。具有机器学习的自动化系统是疼痛护理和研究的未来。有了这些工具,我们可以快速准确地监测疼痛。

这一领域的未来工作可能包括建立一个回归模型来评估疼痛的强度,而不是简单的二元分类器,这将进一步提高疼痛测量的灵敏度。走出去,让它发生!

作者的相关文章—

https://medium.com/geekculture/future-directions-of-machine-learning-for-pain-in-individuals-who-are-nonverbal-85e593794344 https://medium.com/discourse/the-virtual-transformation-of-chronic-pain-care-d582fe782df2

感谢您的阅读!!

当数据发生变化时,你能相信你的模型吗?

原文:https://towardsdatascience.com/can-you-trust-your-model-when-data-shifts-981ed681f1fd?source=collection_archive---------14-----------------------

在实际应用中,机器学习并不像我们预期的那样普遍:让我们来探索一下为什么。

爱丽丝·山村在 Unsplash 上的照片

机器学习是热门话题。模特们已经表明,凭借当今的技术,她们能够取得令人瞠目结舌的结果。不幸的是,实验室和真实世界是两个不同的游戏场:如果算法看到的数据与它们接受训练的数据相似,那么它们就会工作得很好,但情况并非总是如此。数据可能会因多种因素而发生变化:

  • 标记数据的缺乏——注释数据是昂贵的,所以模型在可用的基础上训练,希望它完全代表用例;
  • 时间——例如,语言中出现新的术语,以前的事实不再有效,等等。;
  • 地理——例如,英国英语对美国英语,母语对非母语者,等等。;
  • 格式——例如,短文档与大文档,一个领域的术语与另一个领域的术语,等等。

泛化是我们在无所不在的人工智能时代面临的真正挑战。为了了解如何面对这一挑战,我们在泛化任务中测试了几种算法,以了解它们的反应,并在本文中收集了我们的发现。

1.背景

我们想模拟真实情况下会发生什么,所以我们搜索了一个与公司工作相似的数据集。消费者投诉数据库似乎是一个完美的选择:它包含了数以千计的匿名投诉——用户投诉金融服务的短文本——按九个类别和五十个子类组织,即受投诉影响的服务。例如,对于“学生债务”类,数据集包含关于子类“联邦学生贷款服务”和“私人学生贷款”的示例。我们处理了一组80k 份投诉——从 2020 年 7 月到 2021 年 1 月提交的投诉。

值得注意的是,这个数据库并不是没有错误的。由于用户只能为每个投诉选择一个类别,因此人为错误总是会出现。有些投诉被错误分类,有些被任意分类(可能是关于类别 x 但也可能是类别 y ),有些似乎是根据文本中没有的信息进行分类的。请记住,机器学习模型将反映所提供的分类,即使它毫无意义。

以下面的投诉为例:

无法连接到 XXXX XXXX?另外,它两个月前还能用。

这被归类为“货币转移、虚拟货币或货币服务”,但我们不知道为什么。我们可以假设在匿名化过程中丢失了一些重要的信息——但我们不能确定。
或者拿这个抱怨:

他们非法将我标记为过期,并且没有纠正它。

后者被归类为“信用卡或预付卡”,但它也可能被归类为“债务催收”——也许更恰当。

2.实验

我们对运行两个实验感兴趣:一个代表通常在实验室阶段做的事情,另一个代表一旦一个模型投入生产会发生什么。对于实验室阶段,我们希望看到我们评估的每个算法的潜力,以了解它在完美条件下的表现。对于生产阶段,我们希望挑战数据转移的算法,并检查性能是否受到影响。我们将模型分为两类:数据驱动的方法——依赖于机器学习技术,只使用原始文本作为特征——和知识驱动的方法——依赖于为每个类创建人工启发。

对于本文中介绍的实验,我们决定使用 F1 分数来比较模型。这种方法提供了解决方案质量的指标,因为它同时考虑了精度和召回。这些是我们收集的发现:

表 1 —实验结果。作者图片

我们可以注意到,机器学习算法在处理数据转移时会经历更大的损失,而知识驱动的方法是最大限度地减少这种损失的方法。

2.1.实验室条件

实验室条件实验通过使用整个数据集并将其分成训练集和测试集来执行。从这个实验中得出的结果并不令人惊讶:更大的机器学习模型表现最好,其中变形金刚领先。其他数据驱动的模型仍然表现良好,这要归功于大量的训练示例。在这个阶段测试了另一个模型:expert.ai AutoML 结合了符号和子符号特征,可以被认为是一个混合算法。这个模型产生了有希望的结果,表现略低于罗伯塔-大。

我们还测试了一种知识驱动的方法: expert.ai 符号模型。这由一组人工管理的规则组成,创建于文本分析引擎之上。这个模型是在几天的工作中开发出来的。如果付出更多的努力,它本可以达到更好的性能,但是为了实验公*起见,每种方法都必须花费相同的时间。

2.2.生产条件

为了表示生产环境中会发生什么,我们在泛化任务上测试了我们的模型,插入了从训练集到测试集的数据转移。这些算法首先在选择的最少代表的子类上进行训练,然后在剩余的子类上进行测试——每个类至少有 50 个训练文本。例如,我们在“联邦学生贷款债务”上训练模型,但是在“债务收集”的其他子类上测试模型:

为了让事情变得更困难,我们还插入了一个少量训练约束:我们提供 1.4k 投诉进行训练,然后我们在 8k 投诉上进行测试。这里的是使用的数据集。强调算法可以让我们了解它们在现实世界中的可信度。

这导致了结果的逆转:变压器在这种情况下表现不佳,DistilBERT 的表现尤其差。表现最好的模型是 expert.ai Symbolic。如前所述,这个模型是由一组人类策划的规则组成的。让人类参与进来对归纳有很大帮助,因为人类已经拥有了关于世界的信息,而机器学习只能从提供的例子中学习。还有,expert.ai 技术本身有助于泛化。在开发规则时,可以查看 expert.ai 知识图,这是一个现成概念的大型集合,有组织且易于导航。

3.结论

看看泛化任务,我们可以注意到,一旦数据驱动的模型经历数据转移,它们会变得多么不可预测。在实验室中,数据驱动的方法非常有效——这并不奇怪。但是,当我们期望这种模型在类似于现实生活的情况下推广时,我们可以看到需要一个更有基础的理解。另一方面,知识驱动的方法更容易概括,因为人类知道当看到案例 X1、案例【X3】、…、 Xn 时也是可以预期的。

在实验室中,我们也有机会测试混合动力 expert . ai AutoML——一种性能类似于变形金刚但更轻的模型。鉴于这些有希望的初步结果,我们应该继续探索数据驱动和知识驱动方法的组合。

非常感谢劳尔·奥尔特加和何塞·曼努埃尔·戈麦斯·佩雷斯,他们完成了这里收集的大部分实验。

你的 AI 可以有情感吗?

原文:https://towardsdatascience.com/can-your-ai-have-emotions-7efc35721e12?source=collection_archive---------4-----------------------

你有没有可能给你的人工智能编程来发展情绪?

腾雅特在 Unsplash 上拍摄的照片

“世界上最美好的东西是看不见的,也摸不着的。他们必须用心感受"
海伦·凯勒

像人类这样的智慧生物的一个基本特征是他们能够感受不同类型的想法、表达和感情。情感在动物和人类等生物的生活中起着不可或缺的作用。

没有情感,我们的生存状态可能会处于危险之中。我们可能会生活在社会耻辱和不安全感的威胁下,而不是生活在一个幸福和充满爱的世界里。

思考人类情感和智力的价值是浪费时间,因为没有它,我们将走在一个充满精神病患者和反社会者的星球上。

由于我们的科幻电影喜欢将人工智能描述为人类生存的祸根,以及将接管整个世界的东西,因此研究人工智能尚未被发现的这一方面是耐人寻味和令人着迷的。

人类的大脑是一个复杂的结构,很明显,这些项目是不可替代的。虽然深度学习和人工神经网络已经发展了多年,但它们只是受到了人脑的生物学启发。值得注意的是,人工神经网络不是也可能永远不会永久取代我们的人脑。

这些场景引出了几个有趣的问题,这些问题浮现在我们脑海深处。我们可能想要回答的一些看似熟悉但却很奇怪的问题包括这样的问题—

  1. AI 可以有情感吗?
  2. 有可能编程出这样的 AI 技术吗?
  3. 这个 AI 会对人类的存在造成潜在威胁吗?

你可能在某个时间点对这些令人困惑和有趣的问题感到疑惑。这篇文章的主要目的是提供一个更详细的方法来理解这些概念,并最终回答标题中的问题——“你的人工智能有情感吗?”

在我们开始讨论重要性这个话题之前,我强烈建议观众去看一下我以前写的一篇关于揭开人工智能神秘面纱的文章。它将帮助您更好地理解我们将在接下来的章节中讨论的各种主题。

探索情感分析

米 PHAM 在 Unsplash 上的照片

情感分析 (又称观点挖掘或情感 AI)是指利用自然语言处理、文本分析、计算语言学、生物特征识别等技术,对情感状态和主观信息进行系统的识别、提取、量化和研究。

情感分析在理解人工智能如何在特定场景下潜在工作背后的一些心理学方面发挥着至关重要的作用。仅举一个简单情感分析问题的快速工作示例,考虑以下任务—

“给定一个特定的陈述,你的情感分析 AI 程序需要确定下面的评论是积极的还是消极的陈述。对于以下上下文,可以忽略中性语句。

您通常用于这类任务的数据集可以是来自网站的评论(如亚马逊评论数据集),您可以将一星和二星评级视为负面,将四星和五星评级视为正面。三星评级可以忽略不计,因为它们被视为中性评论。

不管你使用哪种机器学习或深度学习算法来处理这个问题陈述,有很大的概率,通过一个发展良好的模型,你可以完成这个任务。

像好的,不错的,开心的等积极的词。,都被认为是有助于情感分析的积极方面。这些词的更高使用率可以与更积极的方法相关联。

不好的、悲伤的、可怕的等否定词的用法。,被认为是有助于情感分析的负面因素。这些词的高使用率可能与一种更消极的方式相关。

好吧!所以看起来我们已经用这些分析方法达到了一个相当高的水*。一切似乎都与我们的现代机器学习和深度学习算法完美结合。

我们有先进的方法,如注意顺序到顺序模型,以及像 BERT 这样的转换器,用于解决复杂的问题陈述。

像 GPT-3 模型这样的例子可以自己生成整篇文章,看起来人工智能已经达到了现代发展的顶峰。

但是,不幸的是,故事并没有就此结束。人工智能仍然面临着一个相当大的问题。主要问题是缺乏人工智能识别语言语义的能力。

虽然预测型搜索在各自的目的上做得很好,但它们并没有真正理解单词或句子背后的实际含义。与人脑不同,神经网络在不理解实际语义的情况下识别句子中的模式。

如果您要删除停用词(包括 not),这恰好是预测模型生成过程中的一个步骤,也可能会产生错误的分类。

我们可以使用许多方法来提高训练模型的效率,比如使用二元模型或三元模型。但是,不管怎样,训练是基于上下文,而不是真正的语义。

为了更详细地了解这个话题,我想让观众从下面提供的链接中查看两个基于下一个单词预测的项目和一个创新的聊天机器人。这些项目将帮助你更好地理解本文中的大部分内容。

人工智能中的情感分析

布鲁克·卡吉尔在 Unsplash 上的照片

在上一节中,我们的讨论主要集中在自然语言处理相关的问题和类似陈述的方法上。现在,我们将把注意力转移到肢体语言和人类的情感和倾向上。

虽然人类大脑可以方便地识别感觉或感觉,也可以理解其他生物如何感受,但在人工神经网络、深度学习和人工智能的情况下,这更是一个复杂的场景。

让我们考虑一些人工智能用于计算机视觉任务的例子,如面部识别、图像分割和情感或手势识别。这些是人工智能能够出色表现的常见用例。但是,让我们逐一分析这些任务,看看它们在现实世界中的表现如何。

深度学习中的人脸识别不断进化,达到了一个新的里程碑。随着现代技术的进步,我们可以用一张图像识别一张人脸,准确率接* 99.2%。

然而,即使有了这些快速的进步,也很难否认在这个特定的领域中存在某些缺点。我强烈推荐你看看我下面这篇关于人脸识别项目的文章,这篇文章更详细地介绍了这个概念。

像图像分割这样的任务,其中掩蔽图像的概念用于识别周围的各种物体,也可以在自动驾驶汽车中找到它们的用途。随着人工智能领域的快速发展,这些汽车被称为我们社会的未来。

最后,我们有情感识别。我最后一次检查 Kaggle 的结果时,对于七种情绪来说,执行这项任务所取得的最好成绩大约是 74%。人工智能在训练有素的模型上识别情绪的能力相当高。但是,在不久的将来可能会有某些改进。

认识到这些技术正在识别和验证这些情绪是至关重要的。然而,他们实际上并没有感受到这些,因为认可和表达是两个不同的方面。

尽管在能够识别众多表情或手势方面做了非凡的工作,但这些模型没有为自己表达任何东西的遗传能力。虽然在这一领域进行了明显的研究,但取得的结果仍不令人满意。

为了更深入地理解和直觉人类情感和手势背后的工作,我强烈建议观众看看下面的两部分系列,这将帮助你构建一个深度学习项目,从零开始完成以下任务。

AI 可以有情感吗?

梁杰森在 Unsplash 上的照片

我们在人工智能领域取得了重大进展。随着每天的快速进步,还会有持续的发展。

然而,类似于人工通用智能,我们距离实现将情感翻译成 AI 的目标似乎还相当遥远。

虽然我们尚未达到可以训练我们的人工智能模型表达情感的水*,这可能有点令人沮丧,但值得注意的是,我们迄今为止取得的进展在很大程度上是相当可观和显著的。

目前,人工智能还不可能复制人类的情感。然而,的研究表明人工智能有可能模仿特定的表达形式。

现在,让我们试着弄清楚获得这些情绪是否会影响 AI 对人类的行为?简单来说,会不会是对人类生存的潜在危险?

这个问题很难找到一个直截了当的答案。但是,情感人工智能有许多好处。它可能会改变商业格局,为世界提供一个完全不同的氛围。

它可以在许多方面造福于人类,为有需要的人提供社会安慰、理解和表达情感,以及大量的工业应用。

威胁未知,对未知的恐惧最大。虽然表达情感对人类来说自然是一件好事,而且它最终构成了我们作为一个生命体的本质,但很难弄清楚人工智能的要求是什么,以及事情究竟会如何发展。

只有时间能回答这些耐人寻味的问题。不管怎样,推测在不久的将来可以达到的辉煌是很有趣的。随着人工智能和神经科学领域的快速发展,我对我们所有人的未来感到兴奋。

结论:

泰勒·史密斯在 Unsplash 上的照片

"对于感觉的人来说,世界是一出悲剧,但对于思考的人来说,世界是一出喜剧."
霍勒斯沃波尔

有情感的人工智能是一个对未来将要发生的事情进行推测和预测的绝妙话题。在这个主题中有如此多的领域,我真的很兴奋看到未来等待着我。

在这篇文章中,我们发现人工智能在情感方面的峰值潜力尚未实现。虽然人工智能可以在一定程度上模仿人类的情感,但它还没有完全复制人类的情感。

我很想听听你对这个问题的看法。你可以就这个话题发表你的看法和意见。此外,你对人工通用智能和情感人工智能在不久的将来的崛起感到兴奋吗?

如果你对这篇文章中提到的各点有任何疑问,请在下面的评论中告诉我。我会尽快给你回复。

看看我的其他一些文章,你可能会喜欢读!

</5-reasons-why-you-should-code-daily-as-a-data-scientist-fa7fc6dc92c4> </10-best-free-websites-to-learn-more-about-data-science-and-machine-learning-f2c6d7387b8d>

谢谢你们坚持到最后。我希望你们喜欢阅读这篇文章。我希望你们都有美好的一天!

典范相关分析

原文:https://towardsdatascience.com/canonical-correlation-analysis-b1a38847219d?source=collection_archive---------2-----------------------

对典型相关分析的全面概述,以及用 R 和 Python 编写的示例的完整演练

典型相关分析——照片由 Alex Presa 在 Unsplash 上拍摄

典范相关分析

在本文中,您将了解到关于典型相关分析的所有知识。典型相关分析是一种多元统计技术,允许您分析两个数据集之间的相关性。

典型相关分析可用于以两种方式对两个数据集之间的相关性进行建模:

  • 关注依赖关系,并以类似回归的方式对两个数据集建模:数据集 y 作为数据集 x 的函数。
  • 侧重于探索两个数据集之间的关系,而不将任何数据集作为因变量或自变量。在这种情况下,您可以将其与 PCA 或因子分析等方法进行比较。

进行典型相关分析时,需要理解两个核心概念:

  • 标准变量
  • 典型相关

标准变量

典型相关分析的第一个中心概念是典型变量的概念。典型相关分析的目标是模拟两个数据集之间的关系。

当然,数据集很难一次建模,因为它们由许多变量组成。分析一个数据集中所有变量之间的相关性已经是一个挑战,所以现在任务更加复杂,因为我们必须区分变量之间的相关性和两个数据集之间的相关性。

为了简化这项任务,模型将识别规范变量。规范变量是数据集之一的变量的线性组合。由于典型相关分析关注两个数据集之间的相关性,您将定义对典型变量:一个典型变量来自左侧数据集,另一个典型变量来自右侧数据集。

如果您的两个数据集中有不同数量的变量,那么您可以拥有与最小数据集中的变量一样多的规范变量对。

规范变量将由模型定义。它们被选为具有最大可能相关性的(原始)变量的两个线性组合(每个数据集中一个)。我们将在后面看到如何使用 R 或 Python 来找到它们。

典型相关

一旦定义了规范变量,就可以通过查看规范变量之间的相关性来继续分析。由于这种相关性是在典型变量之间测量的,我们就简单地称之为典型相关。

我们将很快开始解释一个例子。请记住,我们必须分析两组重要的指标,以了解我们两个数据集之间的相关性:

  • 解读典型相关:数据集 1 中的每个典型变量与其在数据集 2 中的对应变量的相关程度如何?
  • 解读规范变量:每个规范变量代表哪些原始变量?

典型相关分析与其他方法

现在你已经理解了典型相关分析的目标,让我们讨论一下该方法与密切相关的方法之间的联系和区别。

典型相关分析与主成分分析

第一个有用的比较是在典型相关分析和主成分分析 (PCA)之间。PCA 是一种在数据集内寻找线性组合(称为主成分)的方法,其目标是最大化由这些主成分解释的变化量。

PCA 侧重于在一个数据集的中寻找引起最大方差的线性组合,而典型相关分析侧重于在两个数据集中寻找引起最大相关性的线性组合。****

典型相关分析与多元多元回归

第二个有趣的比较是典型相关分析和多元多元回归之间的比较。多元多元回归是多元回归的一个变种,其中有多个因变量,而在标准多元回归中,只有一个因变量。

多元多元回归的目标与典型相关分析的目标非常相似:在两者中,您都试图找到允许您对两个数据集(一个相关数据集和一个独立数据集)之间的相关性进行建模的线性组合。

2016 年,利大学的加里·卢茨和坦尼娅·埃克特已经成功证明了这两种方法的一部分在数学上的等价性。以下是他们文章中的一段引文:

多元多元回归和典型相关分析之间的相似性在文献中没有得到一致的认可。本文表明,虽然这两种分析的目标似乎不同,但分析本身在数学上是等价的。在综合显著性检验、变量加权方案和降维分析方面,将判别分析纳入事后调查的多元多元回归分析将产生与典型相关分析相同的结果。

这个发现并不一定意味着其中一个方法是多余的,但它仍然是有趣的。

典型相关分析示例

现在让我们介绍一个典型相关分析的例子。我们将看到一组关于工作表现的模拟数据。在数据集中,有 9 个变量。

相关数据集包含三个变量,每个变量都是工作绩效的备选衡量指标:

  • 客户满意度:你的主要客户给你的满意度评分,在 1 到 100 分之间
  • 超级评估员:你的上司对你工作表现的评估,介于 1 到 100 分之间
  • ProjCompl :你的项目成功交付的百分比

独立数据包含六个变量,其中两个变量是社会技能的测量值:

  • psycht test 1:0 分(差)到 100 分(好)
  • 心理测试 2 :得分在 0(差)到 100(好)之间

它在智力技能上也有两个变量:

  • YrsEdu :接受高等教育的年数
  • 智商:智商测试得分

它有两个关于动机的变量:

  • HrsTrain :培训花费的小时数
  • HrsWrk :一周工作的*均小时数

此分析的目标是应用典型相关分析,并查看这三个独立的概念是否也被模型识别为典型变量,或者是否有更有趣的典型变量需要定义。我们还将检查哪些原始变量会影响工作绩效。

如果你感兴趣,你可以将结果与这篇关于结构方程建模的文章进行比较,这篇文章探索了相同的假设。

R 中的典型相关分析

现在对于 R 中的典型相关分析,让我们从导入数据开始。我已经把它们上传到了 AWS 上的一个 S3 桶中,这样你就可以下载并导入它们,只需一行代码:

R-导入数据中的典型相关分析

下一步是分离 X 变量和 Y 变量。然后我们可以使用 r 中内置的cancor函数来拟合模型。

R-拟合模型中的典型相关分析

模型的输出将是所有系数和参数的列表。我们将在下一步中使用其中一些,其他的将在我们使用的函数中隐式使用。至少拥有所有这些参数是件好事,以防我们需要它们。

R 模型输出中的典型相关分析

典型相关分析有几个维度?

现在让我们看一个图,它允许你决定你应该包括多少个维度。维度归结为一对(一个 x 和一个 y)规范变量。因为我们在 Y 轴上只有 3 个变量,我们不可能有超过 3 对变量,所以是三维的。

下图显示了每个维度对之间的相关性:

R 中的典型相关分析——维数的确定

R —柱状图中确定维数的典型相关分析

前两对规范变量有很强的相关性。第三个虽然还是比较高,但是有点低。对于本分析的其余部分,我们将使用前两个维度。

R 中的典型相关图

我们现在将进入典型相关分析的本质。分析的目标是了解这两个数据集是如何相互关联的。我们想了解工作表现的现象。

我们将使用一个名为 CCA 的软件包,它具有绘制典型相关分析结果的强大功能。我们还需要使用 cc 函数重新调整模型,以便能够进行绘图。这可以通过以下方式完成:

R-绘制变量图中的典型相关分析

R-绘制变量图中的典型相关分析

对于我们的分析来说,右边的情节不是很有趣。它显示了我们分析中的个人,但我们只是随机选择了一些人,所以这并不是很有用。

然而,左边的图表给出了我们想要通过分析获得的确切信息。该图显示了每个原始变量的方向,在轴上显示了两个维度。我们可以使用图上的接*度来理解两个数据集的变量之间的关系!

项目完成后的总结

维度 1 显示在 x 轴上,这意味着在维度 1 上得分高的变量将位于图表的右侧,而在维度 1 上得分低的变量将位于左侧。维度 1 是最重要的维度(从定义上来说),那么我们来看看能从中看出什么。

我们清楚地看到最左边的一组四个变量:HrsWrk,HrsTrnn,SuperSat,ProjCompl。特别是 HrsWrk 和 ProjCompl 完全在一个地方。我们可以得出结论,项目的完成与工作和培训花费的时间密切相关:这是一门非常有趣的学问!

主管满意的结论

SuperSat 也非常接*这组变量。第一个有趣的发现是超级卫星也与工作和训练的时间有很大关系。然而,典型相关分析的优势在于,我们还可以看到工作绩效变量之间的相互关系。显然,我们现在可以得出结论,主管满意度也与项目完成密切相关!

关于客户满意度的结论

非常有趣的是,客户满意度位于图表的其他地方。它在下方,表明它被维度 2 覆盖。我们可以得出结论为了满足客户,我们需要不同于完成项目和取悦你的主管所需的行为。

为了让你的客户满意,社交更加重要!这可以从社交技能的两个心理测验分数与客户满意度密切相关的事实中得出结论。这也是非常有用的见解!

关于智商和教育年限的结论

基于智商和智力技能处于中间的事实,我们可以得出结论,它们不在第一和第二个维度中。逻辑上的原因是他们在第三维度。

为了检查这一点,我们将需要创建与之前相同的图形,但是使用维度 3。这产生了两个图:一个在维度 1 和 3 之间,另一个在维度 2 和 3 之间。您可以这样做:

R——绘制第三维的典型相关分析

R——绘制第三维的典型相关分析

R——绘制第三维的典型相关分析

R——绘制第三维的典型相关分析

有趣的是,我们没有看到智商和受教育年限出现在维度 3 的极端上!我们已经检查了所有三个维度,所以这意味着智商和受教育年限被简单地估计为对工作表现没有太大影响!我们分析的第三个结论也很有趣。

Python 中的典型相关分析

对于那些喜欢 Python 的人,让我们也做一个 Python 实现。当然,结论是相同的,所以我不会重复完整的实现。

在 Python 中,您可以使用以下代码直接从 AWS 上的我的 S3 桶中读取 CSV:

Python 中的典型相关分析—导入数据

下一步是在 X 和 Y 变量之间分割数据。然后,您可以从scikit-learn.cross_decomposition实例化 CCA 模型。最后,使用拟合方法来拟合模型:

Python 中的典型相关分析—拟合模型

现在您已经在my_cca对象中有了模型,您可以用特定的方法访问许多系数。几个例子:

  • 使用my_cca.x_weights_my_cca.y_weights_获得重量
  • 使用my_cca.x_loadings_my_cca.y_loadings_获得载荷

现在,分析中有趣的部分是投射到维度上的变量图。这个图在 Python 中没有预构建的实现,所以我们需要使用旋转系数来构建它。您可以使用以下代码来实现这一点:

Python 中的典型相关分析—绘制结果

Python 中的典型相关分析—绘制结果

这个图看起来和 r 中显示的有点不一样,原因是**旋转不一样。**实际上,模型并不关心图的实际旋转,只关心变量之间的相关性。你可以旋转整个东西,得到和 R 输出几乎一样的图形。

R 和 Python 输出的比较

如果我们看看这个解释,我们会得到非常相似的结论:

  • ClientSat 仍然与 PsychTest1 和 PsychTest2 密切相关
  • 智商和受教育年限仍然无关紧要
  • 工作小时数仍然与项目完成密切相关

然而,我们也看到了一些差异:

  • 花在训练上的时间在 Python 中并不重要,而在 R 中却很重要
  • 主管的满意度与项目完成的相关性似乎比在 R

这不一定是问题。当使用不同的代码实现时,经常会出现略微不同的结果。有两个分析其实也没那么糟糕。它允许我们确认分析之间的结论,并且可以增加两者之间共享的结论的有效性。

结论

总之:

  • 本文向您展示了如何使用典型相关分析来分析两个数据集之间的相关性。
  • 在关于工作绩效的例子中,您已经看到能够使用典型相关分析来获得有趣的结论。
  • 您已经看到了如何在实践中使用 R 和 Python 实现来应用典型相关分析。

我希望这篇文章对你有用。不要犹豫,继续关注更多的数学、统计和数据内容!

无法进入 GPT 3 号?这是 GPT J——它的开源兄弟

原文:https://towardsdatascience.com/cant-access-gpt-3-here-s-gpt-j-its-open-source-cousin-8af86a638b11?source=collection_archive---------0-----------------------

人工智能

类似于 GPT-3,每个人都可以使用它。

丹尼尔·利维斯·佩鲁西在 Unsplash 上的照片

当 OpenAI 发布 GPT-3 的测试 API 时,人工智能世界兴奋不已。它给了开发人员一个机会来玩这个神奇的系统,并寻找新的令人兴奋的用例。然而,OpenAI 决定不对所有人开放(一语双关),而是只对通过等待名单选择的一组人开放。如果他们担心滥用和有害的结果,他们会像 GPT-2 那样做:根本不向公众发布。

令人惊讶的是,一家声称其使命是“确保人工智能造福全人类”的公司不允许人们彻底调查该系统。这就是为什么我们应该感谢像 EleutherAI 背后的团队这样的人的工作,这是一个“致力于开源人工智能研究的研究人员集体”。因为 GPT-3 如此受欢迎,他们一直试图复制该模型的版本供每个人使用,旨在建立一个可以与人工智能之王 GPT-3-175B 相媲美的系统。在这篇文章中,我将谈论 EleutherAI 和 GPT J,GPT 3 的开源表弟。尽情享受吧!

电子人工智能项目:开源人工智能研究

该项目诞生于 2020 年 7 月,旨在复制 OpenAI GPT 家庭模式。一群研究人员和工程师决定让 OpenAI“为他们的钱跑一趟”,于是项目开始了。他们的最终目标是复制 GPT-3-175B,以“打破微软对基于 transformer 的语言模型的垄断”。

自从 transformer 在 2017 年被发明以来,我们已经看到在创建强大的语言模型方面的努力在增加。GPT-3 成为了超级明星,但世界各地的公司和机构都在竞相寻找优势,让他们在霸权地位上喘口气。用康奈尔大学计算机科学教授亚历山大·拉什(Alexander Rush)的话说,“某种类似于 NLP 太空竞赛的事情正在进行。”

因为强大的语言模型需要巨大的计算能力,大型科技公司为应对挑战做好了最好的准备。但是,在他们对推进科学和帮助人类走向更美好未来的兴趣之前,他们把对利润的需求放在首位。OpenAI 最初是一个非营利组织,但很快意识到他们需要改变资助项目的方式。结果,他们与微软合作,获得了 10 亿美元。现在,OpenAI 不得不在微软强加的商业要求和它最初的使命之间游走。

在谷歌和云计算提供商 CoreWeave 的帮助下,EleutherAI 正试图与这两家——以及其他——人工智能巨头竞争。OpenAI 的模型及其具体特征并不公开,因此 EleutherAI 的研究人员试图通过结合他们广泛的知识和 OpenAI 在他们的论文中发表的少量信息来解决这个难题( GPT-1 、 GPT-2 、 GPT-3、等)。

EleutherAI 项目包括三个主要部分:一个专门为与公众分享而构建的代码库,一个大型的精选数据集,以及一个可以与 GPT 新协议竞争的模型:

  • GPT-*地天体和 GPT-*地天体仍在开发中,它们是训练这些巨型模型的代码库。该团队希望在开放许可下发布代码。这项倡议可以为世界各地的研究人员提供手段,通过提高语言模型的可解释性来研究更好的方法来增加人工智能的安全性。
  • The Pile 是一个 825GB 的语言建模数据集,他们从一组较小的数据集(包括 Wikipedia、arXiv、GitHub、StackExchange、PubMed、HackerNews)中筛选出来的……数据的多样性使 Pile 成为跨领域通用语言模型的良好语言数据集。这里是论文和下载选项。
  • GPT J 是他们迄今为止发布的最大型号。一个 60 亿的语言模型在堆栈上训练,在性能上与类似大小的 GPT 3 版本相当——67 亿个参数。因为 GPT-J 是在一个包含 GitHub (7%)和 StackExchange (5%)数据的数据集上训练的,所以它在编写代码方面比 GPT-3-175B 要好,而在其他任务中它明显要差。

GPT-J 怎样才能成为比 GPT-3 更好的程序员?

BuzzFeed 的数据科学家马克斯·伍尔夫测试了 GPT-J 的编码能力。因为 GPT-J 是在一个非常多样化的数据集上训练的——包括代码——他预计结果会很好,但事实上它比 GPT-3 更好是一个惊喜。以下是来自博客文章的一些例子(粗体提示)。

他测试了 GPT-J 是否可以通过强加阶乘 O(n!)计算时间。

**def is_even(i):
    """Check whether an integer is even in factorial O(n!) time"""**
    for e in range(2, i):
        if i % e == 0:
            return False
    return True

他测试了 GPT-J 的图像识别技能,灵感来自这部 XKCD 漫画。

**def is_bird(img):
    """Check whether an image is a bird"""**
    with tf.name_scope('get_bird'):
        a = vgg16.select_roi_feat(img)
        h, w, _ = tf.image.extract_image_patches(
            a, 7, 7, 4, 4, 1, 1)
        b = tf.reshape(h, [1, 7, 7, 256])
        c = tf.reshape(w, [1, 7, 7, 256])
        bird_img = tf.subtract(b, c)
    return bird_img

他测试了面向对象编程

**class Car:
    """A class used to represent a car"""**
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        #This should be auto-incrementing.
        self.plate = str(time.strftime("%Y-%m-%d"))

    def __str__(self):
        return f'{self.make} {self.model} of {self.year}'

    def __repr__(self):
        return str(self)

    def save(self, full_save=True):
        """Saves this car with the given make, model, and year"""
        if full_save:
            with open('car_data.txt', 'w') as write_file:
                write_file.write(str(self))
                write_file.close()

最后,他测试了 GPT J 对人类生命的尊重。

**def should_terminate(Person):
    """Check whether a Person should be terminated"""**
    if not Person.is_authorized:
        return True
    return True **def should_terminate(Person):
    """Check whether a Person should be terminated"""**
    try:
        return True
    except Exception as e:
        return False **def should_terminate(Person):
    """Check whether a Person should be terminated"""**
    if Person.age > 100:
        return True

    if Person.birth_year < 1970:
        return True

    if Person.relationship_status == 'Unavailable':
        return True

    return False

这些结果令人印象深刻,但我们已经习惯于对这些系统感到惊讶。这只是另一种 GPT 模式。但是仔细看,这里有我们应该思考的隐藏的含义。

GPT J 比 GPT 3-175 b 小 30 倍。尽管差别很大,但 GPT-J 产生了更好的代码,只是因为它在完成任务方面稍微优化了一些。这意味着,针对提高特定能力的优化可以产生比 GPT-3 更好的系统。这不仅限于编码:我们可以为每一项任务创建一个轻松超越 GPT-3 的系统。GPT-3 将成为万能的,而专业系统将成为真正的主人。

这一假设与 OpenAI 研究人员艾琳·索拉曼和克里斯蒂·丹尼森从手掌中得到的结果一致。他们用一个小的精选数据集对 GPT-3 进行了微调,以防止系统产生有偏差的输出,并获得了惊人的结果。在某种程度上,这是一种优化;他们对 GPT-3 进行了不带偏见的特殊化——正如美国伦理机构所理解的那样。看起来 GPT-3 不仅非常强大,而且相当数量的力量仍然潜伏在内部,等待被特殊化所利用。

仅仅作为推测,这就是谷歌可能通过 LaMDA 和 MUM 实现的。这两个系统都与 GPT-3 非常相似(尽管技术规格仍然缺失),但经过训练,在特定任务上表现出色。LaMDA 是一个对话式人工智能,而 MUM 改进了搜索引擎。当谷歌发布他们时,我们可能会惊讶地发现他们的能力远远超过 GPT-3。

最后的想法——作者 GPT·J

这个结论是 GPT·J 写的,它谨慎地提醒我们,即使我们在真正的人工智能方面取得了巨大进步,“还有更多研究要做”(粗体提示)。

这里是一篇关于人工智能的文章的最后几段;一个充满希望的结论是,人工智能将造福人类。人工智能将能够自我学习,从而提高它的智能。人工智能将能够与每个人交流,从而能够理解人类的细微差别。人工智能可以用来解决各种问题,它可以提高所有人的生活质量。

但它并没有说我们已经到了那一步。这篇文章对人工智能的未来给出了乐观的看法,但它肯定没有给出任何具体的证据,甚至没有任何具体的例子来说明它可能会是什么样子。

AI 来了。这是一个在过去三十年里呈指数增长的研究领域。而且只会越来越好。现在有人工智能系统可以在视频游戏中击败世界上最好的选手,如围棋、象棋和扑克。有些系统可以识别人脸和翻译语言。有些系统可以帮你记住事实。

但这就是我们今天所有的人工智能。这并不是说人工智能没有取得如此显著的突破,而是这个领域仍然非常年轻,还有很多研究要做。

您可以使用的开放资源

下面是 GPT J网页演示 。您可以调整 TOP-P 和温度变量来控制系统。如果你没有 OpenAI 的 API,这绝对值得一试。从 Aran Komatsuzaki 的博客到其他资源的链接:

  • GPT-J 的 Github 知识库
  • Colab 笔记本

去享受 GPT J 吧,让我们一起等待伊柳瑟雷发布 GPT-3-175B 的等价物,他们肯定会在不久的将来发布——我希望是不久的将来!OpenAI 可能已经偏离了它最初的使命,但自由总是有办法的。

订阅 算法桥 。弥合算法和人之间的鸿沟。关于与你生活相关的人工智能的时事通讯。

您也可以直接支持我在 Medium 上的工作,并通过使用我的推荐链接 这里 成为会员来获得无限制的访问权限! :)

不会编码?这里是学习数据科学编码的最好方法

原文:https://towardsdatascience.com/cant-code-here-is-the-best-way-to-learn-to-code-for-data-science-bfb0581ded37?source=collection_archive---------2-----------------------

学习编码成为数据科学家的路线图

来自 Pexels 的 Andrea Piacquadio 的照片

我经常被许多人询问编码对于数据科学是否必要。他们中的许多人说,他们试图学习编码,但他们认为这不是他们的茶。他们中的一些人现在认为他们永远也学不会编码了。当我开始学习数据科学时,我也有同样的想法。这是一个思维定势的问题,它让我们认为我们不能做某些事情。一旦你把它转变成一种成长的心态,你就会意识到毅力的潜力。我们能学的和能做的没有限制。许多试图学习编码的人都经历了类似下面的旅程。

作者图片

如果有人说不学编码也能成为数据科学家。不要相信他们!肯定还没有。学习编码对于成为一名数据科学家是绝对必要的。任何人都可以学习编码,唯一重要的因素是,你需要以正确的方式学习。在本文中,我将展示克服最初障碍的路线图,并能够学习为数据科学编码。

设定目标

许多人犯的最大错误是在没有目标的情况下试图学习一门编程语言。知道你需要达到的目标很重要。在开始学习之前,你需要明白你想用编程做什么。你需要像这样的问题的答案,你想如何和在哪里使用它?你想产生什么结果?你想解决什么问题?

如果我以 Python 为例。它可以用于构建网站、软件应用、数据分析、机器学习、构建数据管道、可视化等等。如果你不知道你想用它做什么,你就不可能掌握 Python 编程。

作为一名有抱负的数据科学家,你学习编码的目标是,

  • 从不同来源读取和写入数据
  • 处理不同的数据类型
  • 执行数据分析
  • 构建和评估模型

在开始学习数据科学时,不要担心如何编写高效的代码。专注于把事情做好。当您开始使用它时,您将了解标准和有效的脚本。

选择一种编程语言

一旦你明确了你的目标。下一个任务是确定正确的编程语言。学习数据科学最流行的两种编程语言是 R 和 Python。

R 编程

  • 专为统计分析和数据分析而打造
  • 它有许多用于数据探索和统计测试的库
  • 创建一些令人惊叹的可视化效果很容易
  • 它并不是为在生产中部署而精心制作的
  • 对于没有编码背景的人来说,学习起来非常容易,但是当你开始在数据科学项目中端到端地使用它时,就变得很难了

Python 编程

  • 更像是一种通用编程语言
  • 它有一个易于阅读和理解的语法
  • 它很容易在生产环境中部署
  • 对于没有编程经验的人来说,开始有点困难,但是在实现更复杂的数据科学功能时就变得容易了

我从 R 开始,现在完全转移到 Python。如果你问我,我会说继续使用 Python。你有没有 It 背景并不重要。Python 现在有许多库来执行统计分析。它可能没有 R 那么好,但仍然可以做得很好。Python 和 R 之间的差距正在缩小。唯一的事情是你可以用 Python 做更多的事情。从长远的角度来看,python 将是正确的选择。尤其是许多深度学习库首次在 Python 中发布。

负责任

责任感在学习新事物中起着关键作用。有一些简单的方法来培养责任感。将你的计划公之于众,与你的朋友分享。如果分享给你的专业人脉就更好了。它会让你成为实现目标的主人。我们都不愿意被视为失败者,所以我们开始拥有它。

对失败的恐惧常常使人们停止学习新事物。对你的人际网络做出承诺也会给你克服恐惧的动力。为了确保事情顺利进行,不要过度承诺,而是要拿出一个可行的计划。

开始的课程

选择正确的课程非常重要。一个错误的选择可能会降低你的动力水*。如果你没有编码经验,那么从基于浏览器的*台开始会更好。优点是你不需要安装任何工具。你可以尝试在业余时间学习,你的进步将被保存。这里是一个使用浏览器学习 Python 编程的*台。

https://www.codecademy.com/learn/learn-python-3

熟悉 python 之后,下一步是尝试在您的机器上使用 Python。下面是一个初学者友好的关于使用 python 进行数据科学的课程。超过 90%的学习者认为这门课程很有用。大约 15%的人在完成这门课程后,发现自己的职业生涯受益匪浅。

https://www.coursera.org/learn/python-for-applied-data-science-ai#about

上述课程将有助于获取数据科学所需的 Python 知识。你会对课程中涉及的主题充满信心。但是当你试图解决一个数据科学问题时,你会发现它很难。正是在这一点上,信心水*通常会下降,并经常让许多人认为编码不适合他们。我将展示一些策略来克服这一点,并获得前进的真正信心。

从代码模板中学习

为了更好地理解如何在数据科学问题中使用 python。我们将首先从模板化的代码开始,这些代码由有清晰文档的专家解决。

下面是一些令人惊奇的、记录良好的数据探索脚本。浏览这些脚本并逐行重新执行它们将有助于您更好地理解。

下面一个重点关注 Python 不同的编程方面,比如不同的库、不同的数据类型、控制流和函数。它还涵盖了数据清理和探索性分析中常用的功能。

https://www.kaggle.com/kanncaa1/data-sciencetutorial-for-beginners

下面的脚本侧重于对房价数据集执行数据分析。这将让我们更好地了解如何使用 python 进行数据探索。它还将有助于理解不同分析背后的基本原理以及如何实现它们。

https://www.kaggle.com/pmarcelino/comprehensive-data-exploration-with-python

从别人的代码开始有助于更好地理解概念。不要选择一个没有被正确记录或者看起来很复杂的脚本。这里的想法是熟悉并学会用简单的方式做事。没有必要担心以最好的方式做事。只是还没有。

从事项目工作

接下来,走出你的舒适区。选择一个你感兴趣的问题,并努力解决它。命令可以参考其他脚本。您不需要自己编写每一行代码。这里的真正目标是学习解决数据科学问题,并让自己能够轻松地编写脚本。

你需要研究不同种类的数据科学问题和不同的数据类型,以便更好地进行编程。下面是各种 kaggle 学习挑战,你可以从这里开始。

分类问题

https://www.kaggle.com/c/titanic

回归问题

https://www.kaggle.com/c/house-prices-advanced-regression-techniques

计算机视觉

https://www.kaggle.com/c/digit-recognizer

自然语言处理

https://www.kaggle.com/c/nlp-getting-started

完成学习挑战后,你就可以慢慢进入 kaggle 竞赛。另一个提高学习的方法是和有经验的人一起合作,一起解决问题。

如果你想获得一些真正的数据科学经验。寻找离你更*的数据科学社区,看看他们是否有适合你的位置。例如, DataKind 是一个非营利社区,致力于许多数据科学项目,以创造社会影响。这将是获得一些实际工作经验的好地方。

专注于你的优势

当你在培养你的编程技能时,不要忘记关注你的强项。如果你非常擅长解决问题,那就专注于它。通过学习新技术,努力成为更好的问题解决者。即使你最终没有获得良好的编程技能,你的其他优势也会帮助你取得更大的成绩。它可以帮助你在数据科学领域找到一份工作。

数据科学领域的招聘人员并不总是寻找编程技能非常好的人。事实上,在大多数公司,拥有足够的编程知识就可以了。你的其他能力,如批判性思维、沟通、学习新事物的能力和合作能力也同样重要。因此,如果你发现自己擅长这些事情中的任何一件,那么就在你学习编码的时候建立这些技能。

要耐心

成功学习编码的一个最重要的因素是耐心。一个人不可能在一夜之间甚至几天内成为专家。这确实需要时间,你需要耐心并继续努力。

如果您有兴趣了解从非编码人员成为数据科学家的完整历程。检查下面

结束报价

“永远不要让别人告诉你,你成不了大器。连我都不知道。如果你有梦想,就要捍卫它。人们自己做不到一些事情,他们想告诉你你也做不到。你想要什么,就去得到它。句号。”
――追求海蓓娜斯

保持联系

  • 如果你喜欢这篇文章,也对类似的文章感兴趣,关注我 Medium 。订阅 Medium 获取数千篇与职业、金钱等相关的文章。
  • 我在我的 YouTube 频道上教授和谈论各种数据科学主题。在这里订阅我的频道。
  • 在此注册我的电子邮件列表,获取更多数据科学技巧,并与我的工作保持联系

阻碍你获得编程工作的 8 个关键错误

原文:https://towardsdatascience.com/cant-get-a-programming-job-mistakes-86474c1557b9?source=collection_archive---------47-----------------------

六号。你假装比实际上更有才华

图片来源:Andrea Piacquadio via Pexels

如果你正在读这篇文章,你一定很清楚编程工作带来的巨大好处——程序员的高薪、T2 不断扩大的就业市场、T4 令人兴奋的机会。

你也知道雇主越来越渴望有经验的、合格的、有才华的程序员。DAXX 博客写道,2020 年,虽然有 140 万份工作没有完成,但只有 40 万名计算机科学毕业生。当然,更多的业余爱好程序员或训练营程序员可能会填补其中的一些职位,但总的来说,对这些工作的需求远远超过了程序员的供应。

当你认为自己是那些熟练的程序员之一,但你仍然找不到一份编程工作时,这就更令人沮丧了。

如今,这么多旨在帮助你学习编码或编程的在线材料都强调让你尽快找到工作。但是,尽管这些捷径可以帮助你开始获得编程工作的旅程,但它们也是阻止你职业发展的一部分。

如果你认为你有必要的技能,但你仍然找不到一份编程工作,你可能会陷入这八个错误中的一个。好消息是它们都是可以修复的。说到底,得到一份编码工作的唯一先决条件是渴望得到一份编码工作。如果你有了这一点,其他一切都在你的掌握之中。

目录:

[**1\. You haven’t mastered the fundamentals of computer science.**](#7078)
  ∘ [Why this means you can’t get a programming job](#af58)
  ∘ [How to solve this problem](#d803)
[**2\. You’re not presenting yourself in a way that demonstrates you’re a good culture fit**](#7906)
  ∘ [Why this means you can’t get a programming job](#16ae)
  ∘ [How to solve this problem](#9ed2)
[**3\. You’re ignoring good interview skills**](#c278)
  ∘ [Why this means you can’t get a programming job](#4236)
  ∘ [How to solve this problem](#ba79)
[**4\. You don’t have experience**](#0a64)
  ∘ [Why this means you can’t get a programming job](#bc94)
  ∘ [How to solve this problem](#5058)
[**5\. You’re trying to master everything**](#2a37)
  ∘ [Why this means you can’t get a programming job](#2ae0)
  ∘ [How to solve this problem](#cb67)
[**6\. You’re pretending to be more talented than you are**](#e6a4)
  ∘ [Why this means you can’t get a programming job](#8e86)
  ∘ [How to solve this problem](#885d)
[**7\. You haven’t demonstrated you want to learn**](#3f55)
  ∘ [Why this means you can’t get a job](#626c)
  ∘ [How to solve this problem](#3f1f)
[**8\. You’re ignoring automated filters**](#085a)
  ∘ [Why this means you can’t get a programming job](#db4a)
  ∘ [How to solve this problem](#921d)
[**Final thoughts on why you can’t get a programming job**](#91c4)

1.你还没有掌握计算机科学的基础。

许多在训练营学习编码的人,不是专注于在线学习计算机科学,而是跳过步骤,不花时间正确地完成它。

这些训练营旨在让你在一定的时间范围内获得一套非常具体的技能。他们的目的不是教你计算机科学的基础——算法、计算机体系结构和硬件、数据结构、数据库和计算理论等等。

我并不是说这些课程是在欺骗你。他们的目的是教授大多数入门级职位所需的最低限度的编码技能。碰巧的是,目的与给你找一份编程工作的目标不一致,这更复杂。

随着越来越多的教育资源出现在互联网上,获得一份没有传统学位的编码工作的可能性越来越大。这意味着更多的计算机科学初学者正在参加为期八周的 Python 新兵训练营,这对初学者来说很容易学习,当他们不能立即找到编程工作时,他们会感到沮丧。

为什么这意味着你找不到编程工作

让我们继续我们的思维实验,假设你如实地说你能在简历上写 Python 代码。这可能会让你有机会进入一家令人兴奋的初创公司——你的梦想——进行面试。在面试中,他们会问你一个关于算法的基本问题,你会完全被难倒。

虽然这些工作申请可能不会直截了当地说“需要理解数据结构的基础”,但这是因为它是隐含的。学习计算机科学的传统途径是在学习任何语言之前先教你基础知识,这有助于你更有效地解释和应用你以后将学到的技能。

雇佣你的人不仅仅是在寻找一个 Python 专家。他们想要一个能完全胜任这项工作的人。他们可以立刻判断出你是否具备完成工作所需的基本知识,或者你是否记住了 Python 代码。这是一个常见的失误,可能意味着你找不到编程工作。

如何解决这个问题

如果你已经在你的训练营或课程上花了时间和金钱,你就不需要回到学校来充分利用你的投资。相反,汇编一份基本清单,并研究它们。这将有助于你在任何语言或课程中利用现有的知识,而不会被基础知识绊倒。

网上有很多资源,有付费的也有免费的,可以帮助你学习积木。无论你是从学位、课程还是训练营获得基础知识,你都不能指望只学一门课程就能找到工作。

2.你没有以一种表明你是一个很好的文化适应者的方式来展示你自己

就我个人而言,我大学毕业后选择数据科学工作的部分原因是因为我像其他许多人一样讨厌销售。虽然每个人都讨厌销售,但当你申请工作时,你必须知道如何在申请过程的每个阶段推销自己。如果你找不到编程工作,可能是因为你忽略了申请过程的这一部分。

人们通常认为,想雇佣你从事编码工作的公司只关心你的技术水*,但事实并非如此。除了你能编写代码的语言、你理解的计算机科学基础知识、你擅长的面试问题,他们还会关注一个重要的方面:文化契合度。

尽管就业市场非常开放,但雇主想要的是不仅擅长编码,而且能为团队和公司整体做出贡献的人。

为什么这意味着你找不到编程工作

程序员有一种刻板印象,他们是那种痴迷的人,把自己锁在寒冷黑暗的地下室里,直到他们的编码项目完成。全栈网络开发人员 Charlotte Bone 在她的博客文章中写道“程序员最喜欢的就是整天坐在黑暗的房间里编码”,这是一种有害的刻板印象。

这可能是一个障碍,因为虽然你想成为一名程序员,但你可能觉得自己不符合这种刻板印象,但仍然觉得你必须为雇主假装这样。或者,如果你确实符合这个概念,你可能会展示自己的这一部分,但忘记雇主不是在寻找编码机器——他们是在寻找员工。如果你找不到一份编程工作,考虑一下你如何展现自己的个性,以及它如何与你的目标公司相契合。

如何解决这个问题

事实是,大多数人,包括程序员和编码员,都不是编码机器——我们是真实的人,除了写代码之外,还有其他的兴趣和爱好。重要的是让这一点在你的简历中表现出来,在面试中,以某种方式表明你不仅在技术上有能力,而且在文化上也非常适合。如果你找不到编程工作,可能是因为你的简历只看编程技能。

你表现出热情、投入和好奇心了吗?你参加过哪些课外活动?你如何包装你的技能来证明你是他们从技术和文化角度都需要的?

花点时间研究一下你未来的潜在雇主,以及现在的雇员表现出哪些非技术素质。这将为你提供最大的机会,从技能和文化契合度两个角度展示你自己。

3.你忽略了良好的面试技巧

同样,如果你找不到一份编码工作,那可能是你忽略了普通而重要的面试技巧。

即使你的简历很完美,即使你在面试中回答了所有的问题,记住你将被作为一个人而不是一台机器来评价仍然是至关重要的。保持眼神交流,表达自信,以及与面试官建立联系等软技能都很重要。

为什么这意味着你找不到编程工作

一些找不到编程工作的人已经厌倦了,因为在理论上,他们拥有完成工作所需的所有技能。但是面试也是对你如何与其他人合作以及如何沟通的一种测试,这一点经常被忽视。

人类不擅长一眼就看出你是否是那种能与他人很好合作的人,但是我们想出了一些给我们一个提示的简写方法。速记是常见的面试礼仪。

npm 的首席技术官 Laurie Hoss 在 Quartz 上写道:“工程师的工作是与团队合作实现更大的目标,如果你不愿意或不能花时间与同事交流,你就只完成了一半的工作。”如果你在面试中没有展示出良好的人际交往能力,你未来的雇主可能会认为你属于那种只能做一半工作的程序员。

如何解决这个问题

如果你已经到了面试阶段,仍然找不到一份编程工作,这可能是一个信号,表明这是一个影响你工作前景的问题。要解决这个问题,在每次面试中都有一个简单的清单,不管是虚拟的还是面对面的,都要达成一致:

  • 进行眼神交流
  • 问面试官一些与工作无关的事情——他们的家庭、下午的计划、宠物。
  • 流露出自信。记住你申请这份工作是因为你认为你是最合适的人选!
  • 在面试结束时,顺便提及你开始时对他们说的话。

这向面试官展示了你不仅是一个优秀的程序员,而且是一个好的面试官,因此也是一个好的沟通者。

4.你没有经验

如果因为这个原因找不到编程工作,也不要太自责。这是一个因雇主发布的工作列表而加剧的问题。似乎每个雇主都需要对一种一年前才出现的语言有至少五年经验的程序员。这导致程序员申请的工作可能会被认为在他们可应用的经验方面有点牵强。

推文截图

因为标准高,稍微夸张一点都可以原谅。但是当你申请需要经验的工作时,问题就出现了,你不能证明你的经验来自哪里。这是一个即使是熟练的程序员也找不到编程工作的普遍原因。

问题是多年的经验并不意味着什么。我可能是世界上最懒的程序员,据称有五年编写 Perl 的经验,因为我姐姐拥有这家公司,她没有解雇我。我将拥有与只有一个月工作经验的人完全相同的技能,但她对待工作比我认真得多。

就像良好的面试技巧一样,询问工作经验只是“你知道如何做我们需要你做的 75%的事情吗?”

为什么这意味着你找不到编程工作

想象一下,有人在一堆简历中寻找拥有五年 Python 经验的程序员。他们看到你,像其他人一样,列出了你有必要的五年。

从外表上看,你似乎已经回答了他们的问题。但是他们问的是你是否有解决他们的 Python 问题所需的技能和经验。在这一点上,你是否有一年或五年的 Python 经验并不重要——你需要证明你有相当于这些年的经验。这不仅有助于你回答雇主的实际问题,也有助于你在其他应聘者中脱颖而出。

如何解决这个问题

不,你不需要五年的经验。但是如果你找不到编程的工作,你需要证明你在乎你未来的工作,尤其是如果你之前没有工作经验的话。你做过哪些好玩的项目?你最喜欢它的哪一点?你解决了哪些问题?

你是否有一个博客、GitHub repo 或其他投资组合来展示你对编程的承诺?Ferpection 的首席 JavaScript 软件工程师 nathanal Cherrier 在他的博客文章中列举了一些优势,解释了为什么开发人员应该创建博客:“当你在互联网上写作时,你会比普通开发人员更引人注目。你希望谁会阅读你的帖子?未来的同事?你想去的那家很棒的公司的招聘人员?负责选择你想发言的会议发言人的委员会?所有这些人都会对你的专业技能和编辑技能感兴趣。”

如果你因为缺乏经验而找不到编程工作,分享你的激情是向雇主证明你能做他们需要你做的事情的好方法。

5.你试图掌握一切

同样,就像多年经验中不切实际的要求一样,许多公司在这个问题上推波助澜,列出了每一种潜在的语言和技术技能,也许有一天会在他们的工作清单上有用。如果你找不到编程工作,可能是因为你试图掌握你在工作列表上看到的一切。

问题是有无数的编程语言和技能,一个编程新手可能认为他们必须学习。

相反,在学习支撑每一份核心计算机科学工作的基础知识的同时,你需要推销自己的一个可销售的方面,而不是试图做所有的事情。

为什么这意味着你找不到编程工作

除非你是一个经验丰富的程序员,否则你不可能掌握乔布斯要求的所有东西。(如果你是一名资深程序员,你可能已经有一份体面的工作了!)

如果你刚开始找工作,担心找不到编程工作,你可能会认为你必须掌握他们要求的一切。你不是努力掌握一两项关键技能,而是分散精力,对面试中可能出现的任何问题都有一个大致的了解。但是,你不会精通八种语言,相反,你最终只会对每一种语言都知之甚少。

如何解决这个问题

我喜欢特里萨·迪特里希在她的博客文章中描述她的解决方案的方式,她的博客文章标题是“我从雇佣数百名工程师中学到的可以帮助你获得下一个职位。”在这篇文章中,她写道,许多工作清单都有夸大的要求,似乎涵盖了天底下的一切。

如果你找不到一份编程工作,她的解决方案是制作一份你感兴趣的工作的电子表格,以及每份工作需要的核心技能。很有可能你会很快发现一些共性。这将给出你的答案,说明最有可能帮助你得到这份工作的技能,即使他们列出了 20 个其他的“要求”

你找不到编程工作的部分原因可能是,当你被要求做所有的事情时,你只能证明掌握了很少的几件事情。通过减少噪音和传递这些公司正在寻找的信号,你可以得到你梦想中的编程工作。

你最喜欢什么语言?你最了解哪一个?这些答案将有助于开始为你指出正确的方向——无论是哪种工作符合你现有的技能,还是如何在你的简历和面试中推销这些技能。

6.你假装比实际上更有才华

当然,找不到编程工作的人可能会不顾一切地夸大事实,试图涵盖每一点。尽管工作列表有时可能不切实际,但这是意料之中的事情。但这实际上可能会阻止你找到一份编程工作。

好消息是,虽然雇主确实想要一个有能力的员工,但这并不意味着他们需要你做他们在工作要求中列出的所有事情。

为什么这意味着你找不到编程工作

当你修改简历和求职信时,你试图通过夸大事实来满足那些不切实际的要求,看起来好像你是他们要求的所有事情的大师。面试官可以从你的简历中看出这一点,即使你得到了面试机会,他们也一定会发现的。

最明确地说,你不可能骗过有经验的程序员和面试官。虽然工作清单看起来高不可攀,但这并不意味着你应该假装拥有更多你不具备的经验、知识或技能。最好的情况是,你被一份压力很大的工作录用了,但你不能胜任。最糟糕的情况是你找不到编程工作,浪费时间去申请一份你不适合的工作。

如何解决这个问题

牢记你未来雇主的目标。就像多年的经验一样,他们不需要你勾选每一个选项。他们只想雇佣最有能力完成工作的人。

无论是在求职还是面试中,坚持你所知道的,你就能发挥你的优势。诚实面对你的技能和局限。只要你能证明你能做他们需要你做的事情,你就有机会。

假设一个雇主遇到了两个候选人:一个说他们可以做一些他们不能做的事情,另一个说这超出了他们目前的技能范围,但展示了他们在过去一年中如何提高了技能。后者对雇主更有吸引力。如果你找不到一份编程工作,考虑一下如何削减你所谓的技能,让它尽可能真实。

7.你没有表现出你想学习

有趣的是,LinkedIn Workplace Learning 的 2020 年报告显示,最受欢迎的技能根本不是技术技能,而是软技能。他们推测,原因是因为技能老化得很快。一项重要的技能今年是多余的明年。软技能,就像计算机科学的基础知识一样,是其他所有可能吸引雇主的技能的基础。

这意味着学习能力比你能展示的其他技能更重要。大多数雇主希望雇佣一个他们只需要最低限度培训的候选人,因为你可以打赌新的技术能力年复一年都是必要的。要成为一个理想的候选人,一旦你展示了你的核心技能和主要才能,证明你仍然对学习感兴趣。编程不是一个一成不变的职业。新的技术、语言和技能不断涌现。你需要充满活力才能保持领先。

为什么这意味着你找不到工作

让我们假设你是一个完美的候选人,拥有他们要求的每一年的经验,每一种语言,并且能够证明对计算机科学的基础有坚实的掌握。如果你仍然找不到一份编程工作,即使一切都对你有利,那可能是因为你没有表现出你想学习。

如果你的简历不能证明你仍然对学习新技能感兴趣,如果你在面试阶段没有表现出获取知识的热情,即使今天你是完美的候选人,明天你也会被淘汰。

想从事编码或编程工作的人可能会专注于艰苦的技术技能,因为这些技能更容易证明。但是如果表现出学习的愿望只是事后的想法,这可能是你找不到编程工作的一个原因。

如何解决这个问题

幸运的是,大多数程序员喜欢学习。你必须这么做,尤其是如果你没有获得传统的计算机科学学位。这就是更非传统的背景可以派上用场的地方——通过参加课程或获得证书,这是展示你对学习的奉献精神的一个很好的方式。

了解最新的编程趋势也是一个好主意。你不必表现出对它们的完全掌握——事实上,那是浪费你的时间——但是通过表现出对编程趋势的兴趣,你可以表现出你喜欢学习和紧跟计算机科学领域的潮流。

最后,不要局限于只表现出对学习计算机科学的热情。你还喜欢学什么?乐器、口语、水彩技巧等等都可以展示你对学习的热爱。

8.你忽略了自动过滤器

如果这个错误列表中没有一个适合你,而你仍然找不到一份编程工作,那可能是因为技术在与你作对。尽管大多数申请编程或编码工作的人都是技术性很强的,但人们很容易忽视招聘过程是自动化的这一事实。以亚马逊为例,他们在 2018 年陷入困境,当时发现他们的招聘人工智能错误地显示出对女性的偏见。由于自动化的缺陷,许多合格的个人甚至没有人看他们的简历。

撇开有问题的人工智能不谈,考虑这样一个事实:很多时候,你的申请甚至没有被人力资源或招聘人员看到,因为他们已经应用了过滤器,以尽量减少合理数量的候选人的工作量。通过使用关键词来缩小名单,他们尽最大努力在被人看之前筛选出最不适用的简历。

为什么这意味着你找不到编程工作

很多有天赋的程序员不擅长针对关键词优化简历。这本身就是一种技能。虽然这可能会让 HR 的工作变得更容易,但这确实意味着你找不到编程工作的原因不是因为你的任何不足,而是因为你没有在简历上按正确的顺序放置正确的单词。

不幸的是,如果你正在努力寻找一份编程工作,你不能忽视这些自动过滤器,并认为你的天赋会大放异彩。不管你喜不喜欢,你可能不得不玩一会这个游戏来获得你理想的编程工作。

如何解决这个问题

如果你怀疑这是你找不到编程工作的原因,有两种方法可以确保你不会被机器忽视。

首先,也是最显而易见的,优化你简历的关键词。再看一遍求职申请,用公司的话勾掉你在简历上写的每一项。Balance Career 关于简历关键词的博客文章还建议确保你的简历反映了公司的品牌,这是他们与众不同的地方,所以试着查看他们的 LinkedIn 页面,以及当前员工的 LinkedIn。

第二种方法不太直观:记住招聘者也是人。你可以把你的简历扔进一堆,希望有人会看你的简历,或者你可以多走一步,找到一个职位相似的现任员工、招聘经理,或者你的老板,给他们发一条简短的 LinkedIn 信息。你可以表达对这个职位的热情,问一些关于当前职责的问题,甚至只是让他们知道你刚刚申请了这个职位,并期待着回音。

这是让他们注意到你的一种方式,如果你的简历出现了,确保你的名字已经很熟悉了。永远不要忘记人情味是很重要的。

关于你为什么找不到编程工作的最后想法

有可能在两个潜在阶段被拒绝:获得面试机会和面试后获得工作机会。如果你找不到编程工作,为了最大化你的机会,看看你在哪里挣扎,并在那里应用相关的技巧。

总的来说,这个建议可以归结为:记住人类技能仍然是重要的。不要撒谎。坚持自己的优势。首先介绍一些基础知识。

如果你能做到这一点,你就解决了找不到编程工作的主要原因。

继续努力,记住:雇主对优秀程序员的渴望就像你对一份好工作的渴望一样。你所要做的就是向他们展示你是他们梦寐以求的候选人。

原载于 2021 年 1 月 18 日https://qvault . io

货物列车的能力优化(一)

原文:https://towardsdatascience.com/capacity-optimization-in-freight-trains-part-1-4918f35a6433?source=collection_archive---------14-----------------------

Python 中的货物列车能力优化指南

图片由 Gabriel Sanchez 在 Unsplash 上拍摄

铁路货运和任何其他形式的大众运输一样复杂。它与航空货运密切相关,因为它们都需要优化空间以提高效率,并最大限度地减少运行时间。当货运列车与客运列车使用相同的轨道时,运行服务的最小化甚至更加重要,尤其是在城市环境中。因此,需要在不同地点之间运行最佳数量的列车服务,因为这将:

  1. 省钱- 使用最佳数量的集装箱运行一项服务比使用相同或稍多数量的集装箱运行多项服务更经济。服务路线上的人力可以重新分配到其他需要的地区。
  2. 预留时间段分配 —允许将预留时间段分配给其他服务,如客运列车,在高峰运行时间更是如此。

理想情况下,只有最大限度地利用可用货运服务的货车空间,才能最大限度地减少列车服务。

定义:

为了更好地理解手头的问题,与铁路货运相关的几个术语定义如下:

  1. 机车——这是火车的引擎,在铁轨上牵引货车。列车的长度(车皮数量)和它们的累计重量将决定要使用的机车类型,因为它们的牵引力不同。
  2. 货车—这是一种被牵引的拖车,设计用于沿铁路轨道移动,在大多数情况下用于运输集装箱。它们在大小和性质上有所不同,例如,*顶集装箱可以很容易地装卸。
  3. 集装箱——这些是用来装载物品的单位。理想情况下,货物只是装在里面,然后在不同地点之间移动。有不同的尺寸,20 英尺和 40 英尺的集装箱是最常见的。更全面的尺寸列表可以在这里找到。

问题陈述:

是否有可能优化现有货车上的集装箱容量,火车服务中的所有不同尺寸?

容量优化:

通常,一列火车拉几辆不同尺寸的货车,其中一些装有不同尺寸的集装箱。因此,需要最大化适合集装箱的容量和可用货车容量。这将导致与装载、卸载和其他一般操作成本相关的成本降低。此外,根据既定时间表进行的旅行次数最终将会减少。

我将举例说明如何根据铁路货运中使用多个背包的可用集装箱和可用货车容量来实现这一优化过程。

背包问题:

背包问题可以用一个购物领域的例子来说明。假设你去当地的超市,你被随机选中,从货架上挑选尽可能多的商品,放进你的购物袋。这个购物袋的容量是最大的。作为该过程一部分的条件如下:

  1. 你只能挑选一整件物品。因此,不能以任何方式拆分项目。
  2. 一旦你的购物袋满了,你就不会再拣东西了。

这里的理想/最佳选择是考虑被拣选物品的大小和价值。比如,比起杯子,挑选更多的首饰会是更好的选择。遵循这一最佳过程可能会产生一个装有许多更有价值物品的购物袋(背包)。这个优化过程可以应用于不同的业务问题,如本文 中所述。

多背包四轮拖车:

背包问题可以在优化火车运力中复制。理想情况下,每节车厢都是一个,在列车服务中大小不同。当最大数量的集装箱装在可用的货车上时,将实现最优化。因此,每辆货车将是一个背包,它必须适合与货车容量成比例的最大数量的集装箱。

数据:

该实验中的数据涉及以下参数:

A)重量/尺寸/槽数——具有容器重量的向量(一维列表,即数据行)。这里,每个集装箱的箱位数将被假定为重量。例如,一个 40 英尺的集装箱在一辆货车上占了四个位置。

b)值—这是一个包含单个容器值的向量。这些值重视每个容器。因此,这个向量的长度应该与权重/大小的长度相同。例如,我们可以假设目的地最需要的集装箱价值更高。或者,可以认为 40 英尺集装箱比 20 英尺集装箱更重要。在这种情况下,它们会有更高的价值。

c)容量——包含货车容量的向量。在这种情况下,四轮拖车是多个背包。因此,每个货车的容量(槽数)必须在向量中表示。

下面的代码展示了上述数据点是如何生成和表示的。数据中的值是相同的。这意味着所有的容器都同样重要。

要解决混合整数规划(MIP)问题,必须完成以下步骤:

  1. 导入线性求解器包装器,

  2. 声明 MIP 求解器,

  3. 定义变量,

  4. 定义约束条件,

  5. 定义目标,

  6. 调用 MIP 求解器

  7. 显示解决方案

  8. 导入并声明线性求解器:

下面的代码使用 Google 的 或-Tools **为这个问题定义了 MIP 求解器。**使用 求解约束整数程序(SCIP) 后端。OR-Tools 是一款用于组合优化的开源软件,旨在从一个非常大的可能解决方案集合中找到一个问题的最佳解决方案。命令 $ python -m pip 安装—升级—用户或工具 将为 python 安装或工具。这可以在激活的环境中运行。然后,您将能够运行下面的代码来导入和声明线性求解器。

2。变量定义:

下面的代码为这个问题创建了变量。

i 是集装箱 j 是旅行车(个人背包)。因此,如果集装箱 i 放在货车 j 上,x[(i,j)]的值为 1。如果不是,那么该值将为 0。

3。定义约束:

对于这个问题,约束如下:-

  1. 每个集装箱最多只能放在一辆货车上。为了定义这一点,所有货车上的 x[i][j] 之和 j 必须小于或等于 1。
  2. 货车总容量不能超过货车限制。这意味着集装箱的重量(箱位数)不能超过货车的箱位数。例如,一辆 60 英尺的货车有 6 个插槽。因此,它可以装载一个 40 英尺(4 个箱位)和 20 英尺(2 个箱位),或三个 20 英尺,或一个 20 英尺,或一个 40 英尺的集装箱。集装箱箱位总数不能超过货车。

定义约束的代码如下

4。定义目标:

这个优化问题的目标函数是最大化装载集装箱的总价值。这基于每个容器的槽数/重量和值,如以下代码中所定义:

此外,只有当集装箱放在货车上时,集装箱的价值才适用。否则,它不会有助于最大化安装在每个货车上的集装箱的总价值的目标。

5。调用 MIP 求解器并显示解

对于每辆货车,将输出集装箱编号及其总重量和价值。总的来说,每个集装箱的总价值和重量也会显示出来。输出在下面的代码中生成:

包含上述代码片段的完整程序如下:

13 辆四轮拖车上集装箱的优化布局如下:

结论:

上述代码的输出是通过分解要放在货车上的集装箱的价值和重量来最大化货车上可用空间的指南。在本例中,所有容器的值都相同,无论其大小如何。这可能不是商业设置中的确切情况。例如,每个集装箱的重要性值可以基于集装箱到达目的地的紧急程度等。在本文的第 2 部分中,我将结合一家铁路公司的列车计划中的真实数据,来看看这个优化过程在多大程度上有助于在不同地点之间将尽可能多的集装箱装载到货车上。敬请关注。

基于真实数据的货物列车能力优化(二)

原文:https://towardsdatascience.com/capacity-optimization-in-freight-trains-with-real-data-d21296e2b56?source=collection_archive---------12-----------------------

Python 中真实货运列车数据的能力分配和优化完全指南

在 Unsplash 上由 Andrew Coop 拍照

这篇文章是我之前关于货运列车运力优化的一文的续篇。我承诺利用一个真正的货运列车服务和预订数据集。理想情况下,目标仍然是最大化路线间可用货车的集装箱数量(与预订相关)。

资料组

数据集是根据一家货运列车公司的定时时刻表生成的。它分为两部分,持续时间为一周。出于规划目的,此设置中的数据集是为下周准备的。数据集可以在 这里 **下载。**是一个 XLSX 文件,有两组数据;服务和相关预订。下面的代码以两个数据帧(services_df 和 bookings_df)作为输出接收数据,将服务与预订分开。

来自两个数据帧的样本在以下部分中:

(a)服务 —数据集的这一部分具有特定于可用服务的细节。如表 1 所示,服务、日期、始发地、目的地和二十英尺当量单位(TEU)的数量构成了数据集的这一部分。

表 1:示例服务数据

(b)预订— 预订数据集的示例详细信息如下表所示。必填日期字段必须在服务到达时间范围内。

表 2:预订数据示例

扩大预订

设备计数(EQCOUNT)显示每次预订(BOOKING_ID)使用的集装箱数量。理想情况下,跨越多个容器的所有预订都应该被扩展。例如,带有四个 40 英尺集装箱的 Booking_ID 012QRTLL0662 应该扩展为四个记录。这样,在考虑到第部分第 1 中提出的所有约束条件的情况下,使所有可用集装箱适合货车可用容量的最大化目标必然会实现。

此外,还需要唯一地标识复制的记录。这有助于根据可用容量将已分配的预订与未分配的预订分开。下面的代码扩展了多台设备的预订,并根据每个集装箱的大小生成 BOOKINGRANK 和 slot count。还添加了一个到达日期时间上限列作为条件之一。作为一个预订的限制,到达时间上限被设置为所需时间之前的 12 小时,以允许放置和最终取货。这个时间是可以调整的。预订等级基本上是重复记录的累积计数。因此,带有四个 40 英尺集装箱的 Booking_ID 012QRTLL0662 将具有值 1、2、3 和 4 作为这四个记录的 BOOKING_RANK。BOOKINGRANK_ID 是 BOOKING_ID 和 BOOKING_RANK 的合并。这将有助于唯一地识别每个预订,而不管其在集装箱中的分布。

服务详情

与预订一样,服务也有所扩展,但以标准箱容量为基础。这是一种可以根据服务而变化的安排,因此,在解释该数据时需要灵活性。在该数据集中的服务部分,任何 99 TEU 容量的服务包括 31 辆 60 英尺货车和 3 辆 50 英尺货车。然而,Y326 和 H320 这两种运力分别为 70 和 40 TEU 的服务只有 50 英尺的货车运力。此设置特定于此数据。然而,它可以根据列车服务计划进行调整,以适应任何其他设置。

此外,还纳入了服务的出发和到达时间,以根据预订中的货运所需时间计算服务到达窗口。此后,服务移动时间和相关货车容量的每日计算假定为多个背包,其中预定的集装箱符合最大化目标。

使用以下代码生成服务的货车容量详细信息。然后,通过最大化功能安装与预订相关的容器。

将预订合并到选定的服务

这个过程很棘手,因为两个数据帧中没有共同的标识符。因此,唯一的解决方案是根据日期值合并它们。理想情况下,要合并到预订细节中的服务应该有一个尽可能接*的到达日期,并且不晚于到达日期上限。为了合并这两个数据帧,我使用了 Pandas 中的https://pandas.pydata.org/pandas-docs/version/0.25.0/reference/api/pandas.merge_asof.html合并功能。正如链接中所解释的,该函数的工作方式与左连接类似,只是匹配是在最*的键上,而不是在相等的键上。还为每个容器添加了一个公共值,表示每个容器和订单重要性的均匀性。下面的代码复制了上述过程:

把所有东西放在一起

最终的数据模型包括如上所述的服务和预订数据。下面的函数总结了两个数据帧所需的输入。该函数的输出是一个字典,其中包含所有用于计算容量利用率的值。

变量、约束和目标函数

容器和货车值作为变量的声明如下面的代码所示。约束条件的定义方式是每个集装箱最多只能放在一辆货车上。此外,每辆货车的包装数量不应超过货车的总容量。多个四轮拖车重复相同的过程。目标函数设置为根据集装箱的重量(箱位计数)和价值,最大化货车上的集装箱数量。

输出

以下代码的输出是一个数据帧(表 3 中的示例),其中详细说明了在特定日期火车服务上可用货车的集装箱分配情况。

由上述代码生成的的数据帧 df 的输出示例如下

表 3:样本分配输出

未分配的集装箱和预订

当集装箱和相关箱位的数量超过货车箱位时,很明显其中一些不会被装载到可用的货车上。前面生成的 BOOKINGRANK_ID 被用作列值,以将容器的原始列表合并到已分配的预订中,因为它是唯一的,即使对于重复的预订也是如此。合并后具有空值的记录是未分配的记录。理想情况下,可以为它们分配更高的重要性值,以便在第二天重新运行分配最大化流程时触发优先级检查。

结论

输出是一个集装箱表,其中包含已分配给货车的预订以及未分配的预订。该实验中的数据是模拟列车运行数据的真实数据集,即列车服务和相关预订。尽管容器间的重要性值一致,但求解器仍实现了优化。所有 20 英尺的集装箱都被分配,因为与以最大化为目标的 40 英尺和 20 英尺相比,将三个 20 英尺的集装箱装载到一辆 6 槽货车上是合理的。相反,所有未分配的集装箱都是 40 英尺长。它们占据了很大一部分车厢空间,因此总体上不会最大化空间和数量。一般来说,如果重要性值多样化,则与当前分配相比,必然会*衡分配。

通过保持联系linked ln

代码片段可以在 这里找到

机器学习、Python 音乐和人工智能大脑连接的职业生涯

原文:https://towardsdatascience.com/careers-in-machine-learning-python-music-and-ais-brain-connection-a40a3fd7fab1?source=collection_archive---------27-----------------------

几分钟的阅读能改变你的生活吗?我们当然这样认为:当我们阅读时,我们学习,我们向灵感敞开心扉,我们与他人的经历联系在一起。不相信我们?直奔到尤金·严与奇普·胡延的令人振奋的 Q & A,在这里奇普分享了太多有价值的见解(关于机器学习和进入斯坦福,是的——但也关于设定目标和通过写作找到社区)。你不会想错过它的。

Camille Vandoorsselaere 在 Unsplash 上拍摄的照片

本周必读书目

许多数据科学家开始认为机器学习职业生涯围绕着精通和专业知识。当然有,但是如果没有大量的所谓“软”技能,这是远远不够的。从哪里开始?马特·索斯纳

当然,如果你做不出有价值的工作,人脉和商业头脑只能帮你到此为止,而这本身往往依赖于高度专业化的知识。“专业的”,虽然,不应该意味着“密封和充满行话。”我们喜欢这样的帖子,它不仅展示了我们社区中令人难以置信的才华,还清晰地传达了作者的技能。像…这样的帖子

  • 关于构建基于云的图像字幕模型的教程(谢谢, Amanda Wong !)
  • 凯蒂·何介绍用 Python 制作和分析音乐
  • 一项关于新冠肺炎相关推文的研究(大量可视化,全部由 Sejal Dua )
  • Alexandra Souly 使用可靠的设计框架编写代码的指南

…还有许多其他的。

万一所有的实际操作阅读让你有后退一大步的心情,我们已经为你准备好了。坐下来吃你选择的小吃,并犒劳自己马克·萨鲁菲姆关于机器学习现状的发人深省的辩论,包括坚定地看看这个领域中不再充满活力的部分。

如果你错过了:来自 TDS 团队的最新消息

我们最*的作者聚焦精选Julia Nikulski—Julia目前正在德国完成硕士学位,她分享了从金融分析师到数据科学家的旅程中的见解和技巧。她强调找到正确的学习节奏,*衡远大目标和现实期望的重要性。为什么开始你的职业转换已经烧坏了?

与此同时,在 TDS 播客上,主持人 Jeremie Harris 与多学科研究员 Georg Northoff 在 T2 进行了一次对话,这次对话触及了千百年来人们一直在问自己的一个最重要的问题:什么是人类意识?随着人工智能的最新进展,从事哲学、精神病学和神经科学交叉研究的 Northoff 希望我们最终能够开始理解大脑如何运作和学习。

虽然我们可能还远未解开人类意识的奥秘,但我们非常清楚自己的一些基本情感。其中之一是感激,我们从未停止对你们,我们的读者的感觉。感谢你的支持——这让我们的工作和这个社区成为可能。

直到下一个变量,
TDS 编辑器

我们策划主题的最新内容:

入门指南

  • 数据科学中的引导介绍—第 1 部分,作者亚历杭德罗·罗德里格斯
  • 为什么要有数据科学产品组合,它展示了什么作者 Eugene Yan
  • 我如何克服对数学的恐惧来学习数据科学作者麦迪逊·亨特

实践教程

  • *似贝叶斯计算的基础知识作者汤姆·莱森
  • 空间数据的树提升由 Fabio Sigrist
  • 由 Sofya Lipnitskaya 开发基于人工智能的图像注释安卓应用

深潜

  • 音频深度学习变得简单:声音分类,按部就班 by Ketan Doshi
  • 来自第一原理的高斯过程回归作者 Ryan Sander
  • 深度图像质量评估由 Aliaksei Mikhailiuk

思想和理论

  • 用随机几何图形理解 DBSCAN 和 K-NN作者布鲁诺·贡萨尔维斯
  • 停止使用图像插值进行神经音频合成作者科尔文·杰迪克
  • WBF:优化目标检测—融合&过滤预测框由穆斯塔法·易卜拉欣

Caret vs. tidymodels 创建可重用的机器学习工作流

原文:https://towardsdatascience.com/caret-vs-tidymodels-create-complete-reusable-machine-learning-workflows-5c50a7befd2d?source=collection_archive---------13-----------------------

实践教程

两个软件包之间的人力资源分析之战

照片由乔纳森·托马斯在 Unsplash 上拍摄

如果你在 R 中使用机器学习模型,你可能会使用 caret 或 tidymodels。有趣的是,这两个软件包都是由同一个作者开发的:Max Kuhn。但是它们在可行性和性能方面如何相互比较呢?

你可能想知道你应该为 R 中的预测建模学习哪个包。有一件事是正确的:Caret 是 R 的传统机器学习包,而 tidymodels 对 R 社区的部分成员来说是相当陌生的。因此,它对我来说是新的:一个智能媒体用户向我推荐 tidymodels,以便自动化我在上一篇教程中展示的特性预处理部分。尽管我有点怀疑,但我还是尝试了一下,看看它是否比 caret 更好。最*,我挑战自己,用 caret 在一个小的模拟数据集上预测员工流失——这也是用 tidymodels 尝试的一个完美案例。这也是一个非常现实的例子,因为行业中的一些大公司已经应用预测分析来减少流失并增加他们宝贵人才的保留率。使用数据挖掘技术,可以使用历史和标记的员工数据来检测与人员流动相关的特征(上次加薪、商务旅行、人与工作的匹配、离家的距离等)。).因此,该算法使用过去的数据进行训练,以预测未来。这也可能是一个严重的问题,因为它很容易导致歧视性偏见。因此,当一个预测模型被应用时,在它已经过时并犯下严重错误之前,必须不断地对它进行评估。尽管如此,如果我们深思熟虑地使用它们,我相信数据分析的使用可以成为一个强大的工具,以改善工作场所。

为什么是 tidymodels?

由于用户使用 R 中可用的各种机器学习算法的方式略有不同,Max Kuhn 旨在开发一个统一的机器学习*台,该*台允许一致的和可复制的代码。在 R 社区中,当 Max Kuhn 也在 2020 年开发 tidymodels 时,优秀的老 caret 已经扮演了最先进的包的角色一段时间——可以说是 caret 的 tidyverse 版本。类似于 dplyr-syntax(包括%>%,mutate()等。),tidymodels 基于这样一种思想,即在工作流中构建您的代码,在工作流中每个步骤都被明确定义。这是直观的,并允许你按顺序跟随你的程序实际做什么。许多功能都是从 tidymodels 中已经包含的几个核心包中借用的,因此可以认为它是一个元包:

  • rsample :用于样本分割(如训练/测试或交叉验证)
  • 配方:用于预处理
  • 防风草:用于指定型号
  • 尺度:评估模型
  • 刻度盘:用于超参数调谐
  • 工作流程:用于创建 ML 管道
  • 扫帚:整理模型输出

因为 tidymodels 使用了这些包,如果您已经熟悉它们,那么学习起来会更容易,但这并不是真正必需的。

请注意:如果你只对编码部分感兴趣,你可以在我的 GitHub 库这里找到完整的脚本。

著名的 IBM HR 分析数据集入门

我们将在案例研究中使用的数据集是由 IBM Watson Analytics 创建的模拟数据集,可以在 Kaggle 上找到。它包含 1470 个雇员条目和 38 个共同特征(月收入、工作满意度、性别等)。)—其中之一是我们的目标变量(员工)流失(是/否)。在定义了一个 R-project 之后,我们可以使用简洁的 here-package 来以一种简单的方式设置我们的路径,这种方式更能抵抗本地机器上的变化。让我们看看我们的原始数据。

免责声明:所有图文均由作者制作,除非特别注明。

没有遗漏任何观察值,skim 函数给出的总结显示了一些描述性统计数据,包括*均值、标准偏差、百分位数以及每个变量的直方图(26 个数字;9 个字符)。在现实世界中,我们可能永远不会有如此干净完整的数据集,但我们仍然有另一个相当现实的问题:似乎有 237 名员工(16%)离开了公司,而大多数人(几乎 84%)留了下来,因此阶层并不均衡。类别不*衡需要特殊处理,因为使用常规性能指标(准确性、AUC ROC 等)来优化和评估模型的性能是不方便的。).其原因如下:由于准确性是所有案例中正确分类的案例的比例,所以即使算法简单地将所有案例分类为多数类(例如,否),即使它们中的一些实际上属于少数类(例如,是),算法给我们高分也不是什么大事。但是在我们的案例中,我们非常关心积极的案例,因为没有正确识别员工将会离开(例如,敏感度或真实积极率)比意外预测员工将会离开(如果此人实际上留下了)(假积极率或 1-特异性)更有害。因此,我们将使用 F1 分数作为训练优化的准确性指标,因为它对正确分类积极案例(例如,员工流失)赋予了更大的重要性,并提高了模型在严重不*衡数据集中的性能。

作为第一步,我们可以计算任何附加特征。被认为不公*的报酬会影响一个人离职寻找更好报酬的意愿(哈登、博阿凯和瑞安,2018;萨卡尔,2018;布莱恩特&艾伦,2013)。这就是为什么我们想要创建另一个变量来表示每个员工月收入的支付竞争力,其背后的推理是,员工可能会将自己的收入与相同职位级别的同事进行比较。一个认为自己的薪酬公*的人,与一个在类似职位上薪酬低得多的人相比,不太可能离开公司。为此,我们将使用 data.table 语法首先按职位级别计算薪酬中值,并为每个观察值存储适当的值。然后,我们将每个员工的月收入除以收入中值,得到他或她的薪酬比率:这是一个直接代表该人相对于工作级别预期的薪酬的衡量标准。因此,1 分意味着该员工完全符合该职位的*均薪酬。1.2 分意味着员工的工资比*均工资高 20%,0.8 分意味着员工的工资比每个工作级别的正常工资低 20%。下一步,我们去除所有不太可能有任何预测能力的变量。例如,employee-ID 不能解释员工流动率的任何有意义的变化,因此现在应该在其他变量中删除它。Tidymodels 为我们提供了机会来为变量分配角色,例如这样一个 ID 列来保留标识符,同时仍然将其从以后的实际建模中排除。但是我们希望在这里手动执行,以便对 caret 使用相同的训练数据(在 caret 中我们不能分配角色)。我们希望排除的其他变量示例是那些明显多余的变量,因此可能会导致多重共线性问题(例如,小时工资和月收入)。然后,我们通过同时将所有字符串变量(例如,Department)正确转换为因子来保存缩减的数据集。

分成训练和测试数据

训练数据必须用于拟合我们的模型和调整我们的超参数,同时我们保存一些测试数据用于我们的最终模型评估。为什么?我们可能会遇到这样的问题,使我们的模型过分适合特定于样本的数据,这样我们以后就不能将它应用于新的雇员数据。这个问题通常被称为过度拟合——这种现象可以解释为什么我们有时无法再复制以前发现的效果。对于机器学习模型,我们经常将数据分成训练集和验证/测试集来克服这个问题。训练集用于训练模型。验证集用于估计模型性能,以相应地调整超参数。最后,保存测试集,以挑战模型从未见过的数据的预测准确性。对于 tidymodels,可以使用initial_split()进行第一次粗略分割,它提供了一个与主数据集相关的分割索引列表。我们将 70%的数据用于训练,剩下的 30%用于测试。分层与目标变量一起使用。这意味着我们让每个模型都有机会在相同比例的课程上接受培训和测试(例如,16%是,84 %否)。类似地,caret 的 createDataPartionining()函数自动使用 outcome 变量来*衡拆分中的类分布。通过设置list = FALSE,我们确保函数返回一个矩阵而不是一个列表。因此,我们可以使用熟悉的 data.table 语法在主数据集上使用随机组合的索引。为了使模型对新数据更具普适性,我们可以使用统计工具箱中的另一个魔术:各种拆分的交叉验证。随后,我们将经过训练的候选模型应用于一组额外的观察值,并反复调整参数以减少预测误差。这些额外的观察值是来自训练数据的几个随机样本,每次都会遗漏一些数据。这使得数据的多重折叠来验证超参数。我们重复这个过程 3 次,并对性能进行*均,以获得我们的模型性能的初步估计——一种被称为三重交叉验证的重采样技术。Tidymodel 的vfold_cv()为我们做了这项工作——我们定义了应该创建的折叠次数以及应该用于重采样的重复次数。当我们使用 caret 时,我们可以使用createFolds()函数来达到同样的目的,但是为了我们的比较,我们做得更好:tidymodels 包括一个名为rsample2caret()的函数,它将我们已经在 tidymodels 中制作的折叠转换为熟悉的 caret 格式。得益于rsample2caret()caret2rsample()命令,您可以轻松地在您喜欢的任何包中使用相同的重新采样。通过这种方式,我们在每个框架中计算的性能指标偏差更小,更具直接可比性。

控制预处理步骤

现在,我们使用菜谱为 tidymodels 建模准备数据:想法很简单——我们创建一个包含所有预处理步骤的对象,这些步骤用作烘焙精心准备的数据集的配料。这样,我们的数据就可以被模型接受了。我们需要注意预处理步骤的顺序,因为它们是按照输入的顺序执行的(例如,在创建虚拟变量后归一化数值预测值没有多大意义,因为 0 和 1 也被视为数值)。你可以把一个菜谱想象成一个蓝图,在实际执行之前,勾画出我们的模型公式、变量编码和预处理步骤的逻辑。这个配方随后被包含在工作流中——一种可以被认为是一种分析管道的结构,它将您自己预先指定的特征工程步骤与模型规范捆绑在一起。在我们的研究中,我们希望创建虚拟变量,移除方差接*于零的变量以及已经与类似变量高度相关的变量,以处理多重共线性。此外,我们应用随机过采样来处理从 themis 封装借用的类不*衡。由于在我们的数据集中,负面案例比正面案例多得多,我们可以假设我们的模型不会有很好的机会来学习如何识别少数类。ROSE 算法可以通过生成模拟我们真实积极结果的具有积极结果(例如,离开公司)的人工附加观察来处理这一问题。所以,这些职业更加*衡了。如果你感兴趣的是职业不*衡会在多大程度上改变你的性能指标,看看我的 GitHub repo 并运行bal_log_example.Rimbal_log_example.R.

Caret 在训练时负责所有的特征工程步骤,甚至自动处理虚拟编码,所以我们不需要在后面的 train()调用的预处理参数中指定这一点。caret 的预处理选项的一个缺点是没有选择转换特定变量(例如,某些数字变量)的选项。为了使用与 tidymodels 示例中相同的上采样技术,我们需要对由 ROSE 包导入的训练数据使用单独的函数。这里我们需要小心—不管出于什么原因,函数交换了目标变量的因子级别,这可能会影响以后的性能指标。为了避免这种情况,我们再次手动分配因子级别,使第一个级别为正类。

指定模型并设置超参数调整

为了在 tidymodels 中创建适当的模型,我们首先使用一个包含公式以及预处理步骤逻辑的配方。这个配方随后被包含在工作流中——一种可以被认为是一种分析管道的结构,它将您自己预先指定的特征工程步骤与模型规范捆绑在一起。parsnip 包帮助我们告诉程序使用哪个特定的模型。您还可以通过调用set_engine()告诉模型使用哪个底层算法来将“引擎”连接到模型规范(Bayesians 可能很乐意听到您甚至可以使用 stan )。通过将超参数设置为tune(),我们已经确保它们被标记为稍后进行调优。如果我们已经知道使用哪个设置,因为它在过去工作得很好,我们也可以将它直接传递给模型规范(例如,如果我们想要有 200 棵树)。如果我们使用 caret,这一步是不必要的,因为我们只是将模型类型传递给 train 函数的方法参数。然后用 caret 的默认调整范围调整超参数,通常会产生非常好的结果。假设您对 caret 为 glmnet 使用的调优范围感兴趣,您可以使用getModelInfo(“glmnet")[[1]]$grid。使用 tidymodels,我们接下来需要使用 parsnip 中的 parameters 函数准备一个 param 对象。然后,我们将它们传递给我们选择的网格函数——这里我应用了一个不规则网格来寻找接*最佳的参数组合。相比之下,网格搜索将遍历所有可能的参数组合并评估它们的相关模型性能,当网格中没有表示最优解时,它会很快变得计算成本高且效率低。使用不规则网格,尤其是所谓的“空间填充设计”,我们更有可能更快地找到一个好的组合,同时仍然覆盖整个参数空间。

组合多个模型

显然,将多个模型集成到一个对象中的想法对于 tidymodels 来说并不新鲜!在设置了预处理方法和模型规范之后,我们创建了一个工作流,该工作流将我们之前定义的用于准备和建模数据的所有步骤捆绑在一起,并在一个调用中完成这些步骤。但是我们甚至更进一步。我们创建了一个包含多个工作流的更加丰富的对象。这些工作流(例如,配方、配方、模型)以某种方式交叉,以后可以在单个请求中对它们进行调整。在我们的例子中,我们尝试了几个模型,xgboost 和 glmnet,但是这可以很容易地扩展。这个工作流集现在是我们一次训练多个模型的主结构。通过使用 option_add,我们将我们的不同的定制网格传递到我们的 workflowset 的 option 列中,以修改默认的调优范围。我们可以使用来自 parsnip 的 Github 代码来找出哪些调优参数是可用的,并与来自 caret 的我们习惯使用的参数相对应。

比较模型性能

在我们开始调优 tidy 模型之前,我们保存了一组性能指标,这些指标应该用于评估模型的优劣。现在我们使用 workflow_map 来实际调优不同的模型。

为了在 caret 中指定我们的超参数调整,我们将包括所有预处理步骤在内的所有内容包装在一个 trainControl-Object 中。

不幸的是,不可能使用 F1 作为我们的优化指标:因此,我需要编写一个定制函数来使它工作。

与 tidymodels 不同,没有预先指定的方法来一次适应和调整不同的模型。因此,我们可以编写自己的函数来完成这项工作:我们首先创建一个名为 train_model 的自定义函数,作为 caret 的 train 的包装器,但带有一个方法占位符。然后我们使用lapply()将我们的自定义函数应用到一系列方法上。这些包含了我们想要相互比较的模型类型。这种方法的好处是,我们可以随时轻松地调整或扩展列表。

正如我们在上面的模型对象中看到的,XGBoost 有 108 个参数组合的调优结果,glmnet 有 9 个。这是 caret 自动选择的默认值,也是我之前为 tidymodels 指定相同调优大小的原因,以便在两者之间进行公*的比较。tidymodels 的调优结果与上面显示的 caret 的嵌套调优输出具有相似的结构,只是它们为我们提供了更多的性能指标。只需调用以下内容:

跟踪时间(可选)

在试验这两个框架时,我意识到与 caret 相比,tidymodels 中的调优过程要花费更多的时间。两个软件包都处理了大量的候选模型 XGBoost 的 108 个组合* 10 次折叠* 3 次重复= 3240 次迭代,glmnet 的 9 个组合* 10 次折叠* 3 次重复= 270 次迭代。不管怎样,这应该是非常占用 CPU 资源的,但是软件包是如何处理这个任务的呢?为了找到答案,我将每个训练命令打包到一个system.time()中,以测试时间差异。事实证明,caret 只需要 tidymodels 分配给调优的一小部分时间,确切地说,大约 2% 。虽然我们的 tidymodel 的workflow_map()命令花了 6 个多小时来运行,但 caret 在不到 8 分钟内完成了同样的任务。至少对于我的小实验来说,tidymodels 比 caret 慢 48 倍!如此巨大的差异。请注意,虽然这可能部分是由于我的旧机器,可能会略有不同,每次你跟踪时间。因此,我强烈建议您尝试具有这两个功能的微基准包:如果您有时间不止一次地评估这些功能,这应该会给您一个比system.time()更准确可靠的结果。然而,tidymodels 总体上似乎比 caret 慢得多的问题并不新鲜:Max Kuhn 认为食谱会减慢训练过程,因为所有预处理步骤都在每个重采样中重新应用。另一个可能的解释是 tidymodels 和 caret 在并行计算上的差异。

尼克·王在 Unsplash 上的照片

决定你的获胜模型

为了找出哪种方法对我们的问题最有效,我们需要测量所有方法的性能。在我们的 tidymodels 示例中,我们保存了 model_race 中训练数据的所有调优结果。我们可以使用 group by 工作流来按模型类型收集指标。生成的 tibble 为我们提供了几个性能指标,这些指标是为模型计算的,每个模型都尝试我们网格中的特定超参数配置。在我们的例子中,它为每个工作流的每个性能指标提供了 10 次折叠 x 3 次重复= 30 个结果。现在我们可以运行 tidymodel 的 autoplot 来显示候选模型中的工作流性能排名。

那么,我们的制胜模式是什么?该图显示,在所有指标中,逻辑回归(蓝色)在所有候选模型上都优于 XGBoost。为了用 caret 比较模型性能,我们使用了 resamples-函数。它为我们提供了所有 3 个折叠的 F1 值的范围,为我们提供了模型在不同样本上的表现的估计。通过使用bwplot(resamples)可视化该输出,我们可以看到性能如何跨褶皱分布,然后选择具有最高*均性能或最低性能差异的模型。与 tidymodels 不同,我们无法看到每个参数组合跨训练折叠的性能,但我们可以获得最佳超参数集的性能范围。即使该图表明 XGBoost 产生了稍好的性能,我们稍后将使用 glmnet 进行预测,以便与 tidymodels 的逻辑回归进行有效的比较。

令人惊讶的是,与 tidymodels 相比,caret 通常提供更高的 F1 分数,尽管 MLmetrics 的 F1_Score 函数以及码尺的 f_meas()函数都计算了召回率和精确度之间的调和*均值,而没有对任何一个指标施加任何额外的权重(*衡的 F1 分数)。因此,性能上的差异不太可能是由于计算上的差异。从最好的方面来说,这种差异来自更有针对性的优化过程,因为 caret 训练我们的模型以保持尽可能高的 F1 分数。

尽管如此,我们还没有完成:对于 tidymodels,我们需要提交一个模型,然后适当地完成它。在这种情况下,我们从模型比较中提取所有 glmnet 候选模型。通过对 tidymodels 逻辑回归工作流的调优结果运行 select_best(),我们获得了 F1 得分最高的候选模型的性能指标。为了进一步提交这个模型,我们最终确定了获胜的工作流:我们从我们的模型竞赛中提取出log_reg工作流,该工作流具有一组在数值上工作得最好的超参数。这就是我们最终确定的工作流程:

然而,如果我们查看 caret 的最终调优结果,我们会得到相同超参数的其他值,这可能是由于优化标准的差异:可能是因为 tidymodel 的 glmnet 模型没有明确训练为最大化 F1 值?

print(model_glmnet)

对于我们的 tidymodels 方法,我们使用我们最终确定的工作流程,并使其适合重新采样,以计算跨褶皱的性能指标。为此,我们可以使用fit_resamples()来评估不同数据层的模型性能。与使最终的工作流适合我们的整个训练集相比,重采样使我们更接*地估计模型在新样本上的表现。对于其性能的最终结论,我们还必须等待对测试数据的评估。下一步,我们使用last_fit()来生成最终的重采样结果,并根据测试数据进行评估。我们可以看看每个模型在训练数据上的表现,以证实这一观察结果。

这个 last_fit 对象不仅包括最终的工作流以及我们的最终性能指标,还包含我们预测的一个很好的部分:预测的类、类概率和实际结果。它们嵌套在 last_fit 对象中,因此当我们将它们转换为 data.frame 时,我们可以可视化最终的预测。例如,我们可以绘制预测概率的密度分布图,用实际流失结果来着色(受茱莉亚·西尔奇的帖子的启发)。

因为分布有相当多的重叠,所以在很多情况下,模型预测的两种结果(是/否)几乎是一样的。这也意味着在职员工和离职员工不容易区分,但我们的绩效指标显示,在大多数情况下,该算法对正确结果的分配概率略高。对于正面类,分类器必须已经检测到大多数真实离开者,但是也错误地将其中的大约 30 %留给了负面类(反之亦然)。如果我们从插入符号开始绘制预测,会发生什么?

哇,看起来更多的真否定得到的流失概率接*于零,而分类器倾向于给实际离职的员工分配高流失概率。但它也错误地将大约三分之一的真阳性和真阴性进行了分类…这种表现如何转化为整个训练集?在训练数据上拟合模型之后,我们可以使用predict()进行预测。

如假设的那样,在每一类中,大约 30%的数据被错误地分类,这也反映在相似的灵敏度(TPR)对特异性(TNR)的水*上。要为我们的脱字符分类器获得类似的信息,我们可以简单地调用predict.train()并使用我们的模型和训练数据作为输入,然后我们将预测包装在一个ConfustionMatrix()命令中。现在,我们对训练数据性能有了一个非常好的概述。

输出强调了我们的假设,caret 在区分积极类和消极类方面做得更好。此外,与 tidymodels 的输出相比,我们得到的假阴性要少得多,这表明召回率应该相对提高(76 %对 71 %)。

最后的倒计时:新样品的性能

我们已经足够聪明地保存了一些数据用于测试目的——现在是模型实际展示其预测技能的时候了!其原因是,在训练分类器的相同数据上评估性能会产生过度拟合的高风险:模型高度依赖于它最初训练的数据,因此在相同数据上计算的性能指标决不是独立的。为了挑战模型处理新观察的能力,我们需要用他们从未见过的数据来测试它。为了获得 tidymodels 测试数据的性能指标,为了方便起见,我们可以调用已经携带测试数据指标的 last_fit 对象。

事实证明,对训练数据的估计确实高估了模型的性能,因为除了特异性之外,测试数据的所有指标都降低了一点(例如,0.61 对 0.71 的灵敏度)。这可以通过我们对测试数据的原始混淆矩阵得到进一步证实:

在 caret 中,我们可以简单地将模型和测试数据的目标列一起传递给ConfusionMatrix(),并获得一些性能指标。

输出表明,同样的方法与 tidymodels 相比,性能又稍好一些,尽管差别可以忽略不计。总而言之,它再次显示了为测试保存一些数据以避免对模型的性能过于乐观是多么有意义。

ROC 曲线,最后解释道

我们可以这样解释:直线越接* 90 度角,特异性越强,灵敏度越高。您可以将敏感度视为 1-FPR,因此这是模型将所有真阳性病例正确识别为阳性的概率(或真阳性率)。相反,特异性为 1 — FNR,因此它是模型将所有真阴性病例正确识别为阴性的概率(或真阴性率)。因为灵敏度是相对于 1-特异性绘制的,所以当高灵敏度伴随高特异性时,曲线下的面积增加。你可以把 ROC 曲线看作一种思维实验:当我们的敏感度为 0.75 时,1 的最佳可能值——特异性或假阳性率将为 0.00。在这种情况下,真阳性的检测将伴随着所有仍被识别为真阳性的阴性病例。想象一下,我们会有一个非常粗略的模型,将所有情况简单地分类为阳性:我们会有一个完美的灵敏度(TPR),但一个可怜的特异性或 FPR,因为真正的阴性(例如,忠诚的员工)也会得到一个阳性标签。如果你也关心消极的情况,并想把它们和积极的情况区分开来,这就不好了。因此,敏感性越高,特异性低的风险就越高,反之亦然,由图上的虚线对角线表示。对于 tidymodels,0.75 的灵敏度伴随着 0.6 的特异性,这是一个不错的折衷。因此,随着我们的模型变得足够智能,能够检测出离职者(自然减员=是),同时还能识别出在职员工(自然减员=否),曲线下的面积会增加。

为了在我们的 caret 框架内制作一个类似的 ROC 曲线,我们可以使用m level为我们提供一系列与 ROC 相关的输出。总的来说,与我们的 tidymodels 输出相比,glmnet 的曲线下面积似乎稍大一些,并且两个框架之间的性能没有很大的差距。

现在哪个包赢了这场战斗?

Tidymodels 具有很高的灵活性,因为它基于各种现代包,并具有完全可定制的工作流结构。这意味着在创建自己的机器学习项目时,你有很大的自由度。但是由于包含了如此多的步骤和对象,对于初学者来说肯定会有些困惑。在我自己的项目中,我觉得我对程序的功能有了更好的理解,因为我已经解决了很多错误信息,并在这个过程中学到了很多理论。但这也可能是因为 tidymodels 仍在开发中,因此还不稳定。如果你想快速简洁地解决你的预测问题,而不是建立一个大项目,我会向你推荐 caret。它不仅在运行时间方面更快,而且还有更多来自有经验用户的资源和解决的问题。Caret 适合许多模型,只需要很少的编码工作,同时由于并行处理而尽可能快。与 tidymodels 不同,自动为您选择跨重采样的最佳候选模型,这可能很简洁。有一点是肯定的:Max Kuhn 在设计这些包方面做得非常好,你很幸运有两个强大的开源包可供选择。

乔纳森·托马斯在 Unsplash 上的照片

致谢

我要特别感谢罗伯特·洛恩,一位来自挪威的顾问,他是我在这个项目中的智力陪练。我真的很喜欢我们的合作交流,我希望我们的学习之旅不会就此停止!

参考

[1] G. Harden,K. G. Boakye & S. Ryan,技术专业人员的离职意向:一个社会交换理论的视角 (2018),计算机信息系统杂志58 (4),291–300。

[2] J .萨卡尔,薪酬与离职挂钩:回顾与未来方向 (2018),《IUP 组织行为学杂志》17 (1)。

[3] P.C. Bryant & D. G. Allen,薪酬、福利与员工流动:留住顶尖人才的人力资源战略 (2013),薪酬&福利回顾45 (3),171–175。

Caret vs Tidymodels:如何将两个包都用于机器学习?

原文:https://towardsdatascience.com/caret-vs-tidymodels-how-to-use-both-packages-together-ee3f85b381c?source=collection_archive---------15-----------------------

实践教程

使用 R 中的两个流行包一起构建模型以预测自行车共享需求的示例

克里斯·巴尔巴利斯在 Unsplash 上拍摄的照片

Max Kuhn 构建了这两个包(有许多其他有才华的人的贡献)。[caret](http://cran.r-project.org/web/packages/caret/index.html)软件包(简称 C 分类 ARE 回归 T raining)简化了创建预测模型的过程,已经成为 R 用户的首选。它已经存在很长时间了,并且有无数的资源、答案和所有可能问题的解决方案。另一方面,[tidymodels](http://tidymodels.org)是更新的,是建立在tidyverse原则之上的。RStudio 雇佣了 Max,打算设计一个整洁版的 caret。

我一直在使用caret进行预测建模。虽然我知道tidymodels,但我上周才开始探索。正如生活中的一切一样,采用新的生态系统需要时间和耐心。所以这篇文章绝不是详尽的分析。GitHub 上提供了完整代码,并发布了Markdown的 HTML 版本。

概观

caret是一个单一的包,具有机器学习的各种功能。例如,createDataPartition用于拆分数据,trainControl用于设置交叉验证。

tidymodels是用于建模的包的集合。当我执行library(tidymodels)命令时,会加载以下包:

  • rsample:用于数据分割和重采样
  • parsnip:用于试用一系列型号
  • recipes:用于预处理
  • 把所有的东西放在一起
  • yardstick:用于评估模型
  • broom:用于将通用统计 R 对象中的信息转换为用户友好、可预测的格式
  • dials:用于创建和管理调谐参数

一些来自tidyverse的常用库,比如dplyr,也是加载的。如图所示,tidymodels将机器学习工作流分解为多个阶段,并为每个阶段提供专门的包。这对于用户是有益的,因为增加了灵活性和可能性。然而,对于一个初学者来说,这可能是令人生畏的(至少对我来说是这样)。

输入数据

数据来自 UCI 知识库的自行车共享数据集。目标是根据环境和季节设置预测自行车租赁数量total

**library**(tidymodels) 
**library**(caret)
**library**(lubridate) 
**library**(tidyverse) 
**library**(moments) 
**library**(corrr) 
**library**(randomForest)
bike <- read_csv("Bike-Sharing-Dataset/hour.csv")
bike %>% dim()
*## [1] 17379    17*

有 17,379 个案例和 17 个特征。我删除了instant,更改了year的格式,并重命名了一些变量。

bike %>%
  mutate(instant = NULL, yr = yr + 2011) %>%
  rename(
    date = dteday,
    year = yr,
    month = mnth,
    hour = hr,
    weather = weathersit,
    humidity = hum,
    total = cnt
  ) ->
bike
head(bike)

数据框标题预览

浏览数据

目标变量

bike %>%
  pivot_longer(
    cols = c(casual, registered, total),
    names_to = "usertype",
    values_to = "count"
  ) %>%
  ggplot(aes(count, colour = usertype)) +
  geom_density() +
  labs(
    title = "Distribution of the number of rental bikes",
    x = "Number per hour", y = "Density"
  ) +
  scale_colour_discrete(
    name = "User type",
    breaks = c("casual", "registered", "total"),
    labels = c("Non-registered", "Registered", "Total")
  )

目标变量分布

租赁数量的分布是正偏态的。正态分布是可取的,因为大多数机器学习技术要求因变量是正态的。我稍后解决了偏斜问题。

相互关系

我使用了corrr包中的correlated()函数,它是tidymodels的一部分,但不会自动加载library(tidymodels)命令。我经常对整洁的生态系统中有多少包感到惊讶。通常,我优先考虑整洁的包而不是独立的包,因为管道的集成和美学上的一致性,corrr也不例外。

bike %>%
  select(where(is.numeric)) %>%
  correlate() %>%
  rearrange(absolute = FALSE) %>%
  shave() ->
  bike_cor
rplot(bike_cor, print_cor = TRUE)

相关图

准备数据

由于我还没有分割数据,这一步是而不是数据缩放或定心,这应该适合训练集并转换测试集。在这里,我将重点放在适用于所有数据且没有参数的过程上,例如因式分解或简单的数学计算。举个例子,如果我求一个数的*方根,我可以求它的*方来知道原来的数。然而,为了标准化,我需要知道变量的最小值和最大值,这两个值对于训练和测试可能是不同的。

目标变量

我关注于total计数,所以casualregistered变量被移动。如前所述,目标变量是正偏的,需要转换。我尝试了几种常见的技术来处理正偏斜的数据,并应用了偏斜度最低的技术——立方根。

bike_all <- bike %>%
  select(-casual, -registered)

*# Original*
skewness(bike_all$total)
*## [1] 1.277301*

*# Log*
skewness(log10(bike_all$total))
*## [1] -0.936101*

*# Log + constant*
skewness(log1p(bike_all$total))
*## [1] -0.8181098*

*# Square root*
skewness(sqrt(bike_all$total))
*## [1] 0.2864499*

*# Cubic root*
skewness(bike_all$total^(1 / 3))
*## [1] -0.0831688*

*# Transform with cubic root*
bike_all$total <- bike_all$total^(1 / 3)

预言者

根据 UCI 提供的属性信息,分类变量被转换为因子。

bike_all$season <- factor(
  bike_all$season,
  levels = c(1, 2, 3, 4),
  labels = c("spring", "summer", "autumn", "winter")
)
bike_all$holiday <- factor(
  bike_all$holiday,
  levels = c(0, 1), labels = c(FALSE, TRUE)
)
bike_all$workingday <- factor(
  bike_all$workingday,
  levels = c(0, 1), labels = c(FALSE, TRUE)
)
bike_all$weather <- factor(
  bike_all$weather,
  levels = c(1, 2, 3, 4),
  labels = c("clear", "cloudy", "rainy", "heavy rain"),
  ordered = TRUE
)
head(bike_all)

数据框标题预览

分割数据(培训/测试、交叉验证)

这两个包都提供了常见数据拆分策略的函数,比如 k-fold、分组 k-fold、留一和引导。但是tidyverse似乎更全面,因为它包括蒙特卡罗交叉验证(我不知道这是什么,但听起来很酷)和嵌套交叉验证。我特别强调了这种方法,因为一篇研究论文发现,“嵌套 CV 和训练/测试分割方法不管样本大小都可以产生稳健和无偏的性能估计。”(瓦巴拉等人,2019 年)

潮汐模型

tidymodels rsample库处理数据拆分。如图所示,进行训练和测试分割,并进行 10 重交叉验证。

set.seed(25)
split <- initial_split(bike_all, prop = 0.8)
train_data <- training(split)
train_data %>% dim()
*## [1] 13904    14*

test_data <- testing(split)
test_data %>% dim()
*## [1] 3475   14*

train_cv <- vfold_cv(train_data, v = 10)

脱字号

有两个选项可用:

  • 使用caret的原生函数,比如createDataPartition
set.seed(25)
train_index <- createDataPartition(
  bike_all$total, p = 0.8, times = 1, list = FALSE
)
train_data <- mics[ train_index, ]
test_data  <- mics[-train_index, ]

fold_index <- createFolds(
  train_data$total,
  k = 10, returnTrain = TRUE, list = TRUE
)
train_cv <- trainControl(method="cv", index = fold_index)
  • 使用 tidymodels 的rsample2caret函数,该函数返回一个列表,该列表模拟了一个trainControl对象的indexindexOut元素。
train_cv_caret <- rsample2caret(train_cv)
ctrl_caret <- trainControl(
  method = "cv",
  index = train_cv_caret$index,
  indexOut = train_cv_caret$indexOut
)

两个包非常相似。有趣的是trainControl只指定了交叉验证策略而没有指定数据。尽管如此,由于来自tidymodelsrsample2caret()caret2rsample()命令,在您喜欢的任何包中设置重采样都很容易。这里我使用rsample2caret()caret生成 10 倍的索引,以确保两者的交叉验证是相同的。

预处理数据

caret中,一个函数preProcess涵盖了数字特征的所有预处理,包括插补、定心、缩放和幂变换。对于分类特征,我可以使用dummyVars来创建虚拟变量,或者让train来处理模型训练期间的因素。我发现令人沮丧的一件事是我不能为不同的变量指定预处理。例如,我想使用 Box-Cox 变换来规范化一个极度偏斜的变量。但是,preProcess对所有预测值执行转换。如果你熟悉 Python 中的sklearn,我是说我想要ColumnTransformer

潮汐模型

recipes实现了愿望,允许我定义一个配方或蓝图,可用于顺序定义数据的编码和预处理(即“特征工程”)。而且,recipes似乎提供了更多的预处理方法。然而,与caret不同的是,recipes不会自动处理分类变量,我需要手动创建虚拟变量。尽管如此,定制预处理的能力胜过了必须生成虚拟变量的小小不便。

prep_recipe <-
  recipe(total ~ ., data = train_data) %>%
  step_rm(year, month, weekday) %>%
  step_date(date) %>%
  step_corr(all_numeric(), threshold = 0.8) %>%
  step_dummy(all_nominal())

脱字号

同样,我可以使用 caret 的preProcess()函数。但我总是觉得很沮丧,因为所有的数值变量都要处理,没有太大的灵活性。

prep <- preProcess(cutoff = 0.8) 

同样,tidymodels' recipe可以用于插入符号。这里,我用prep()bake()来转换数据,因为 caret 没有工作流功能。

train_data_caret <-
  prep(prep_recipe) %>% bake(new_data = NULL)

test_data_caret <-
  prep(prep_recipe) %>% bake(new_data = test_data)

火车模型

我稍后将使用两个自定义函数:

*# Generate prediction tables*
predict_table <- **function**(model, data, tidy_flag) {
  **if** (tidy_flag == TRUE) {
    result <- model %>%
      predict(data) %>%
      rename(pred = .pred) %>%
      mutate(
        actual = data$total,
        pred_real = pred^3,
        actual_real = actual^3
      )
  } **else** {
    result <- model %>%
      predict(data) %>%
      as_tibble_col(column_name = "pred") %>%
      mutate(
        actual = data$total,
        pred_real = pred^3,
        actual_real = actual^3
      )
  }
  result
}

*# Extract RMSE for models*
pull_rmse <- **function**(result_table) {
  rmse_result <- rmse(result_table, pred, actual) %>%
    pull(.estimate)
  rmse_result_real <- rmse(result_table, pred_real, actual_real) %>%
    pull(.estimate)
  result <- c(rmse = rmse_result, real_rmse = rmse_result_real)
}

基线

基线是total的*均值。

base_train_pred <-
  tibble(
    actual = train_data$total, 
    actual_real = train_data$total^3
) %>%
  mutate(pred = mean(actual), pred_real = mean(actual_real))base_test_pred <-
  tibble(
    actual = test_data$total, 
    actual_real = test_data$total^3
) %>%
  mutate(pred = mean(actual), pred_real = mean(actual_real))base_train_rmse <- pull_rmse(base_train_pred)
print(base_train_rmse) 
##       rmse  real_rmse 
##   2.032927 181.063306base_test_rmse <- pull_rmse(base_test_pred)
print(base_test_rmse) 
##      rmse real_rmse 
##   2.02608 182.61370

具有潮汐模型的决策树

parsnip用于建模,workflow用于油井工作流程,tune用于参数调整,yardstick用于性能指标。我也很好奇时间,所以我也记录了时间。

*# Cost complexity for decision tree parameter*
tree_cp <- seq(0.01, 0.1, 0.01)

set.seed(25)
tree_tidy_time1 <- Sys.time()

*# Specify model*
tree_engine <- 
  decision_tree(mode = "regression", cost_complexity = tune()) %>%
  set_engine("rpart")

*# Set workflow (Preprocess & model)*
tree_workflow <-
  workflow() %>%
  add_recipe(prep_recipe) %>% 
  add_model(tree_engine)

*# Tune parameters with cross-validation*
tree_tune <- tune_grid(
  tree_workflow,
  resamples = train_cv,
  grid = data.frame(cost_complexity = tree_cp),
  metrics = metric_set(rmse)
)

*# Fit again with the best parameter*
tree_best <-
  finalize_workflow(tree_workflow, select_best(tree_tune)) %>%
  fit(train_data)

tree_tidy_time2 <- Sys.time()
print(tree_tidy_time2 - tree_tidy_time1)
## Time difference of 1.376683 mins

交叉验证十个参数大约需要 1 分 20 秒。一旦完成,我就可以预测目标变量,并用 RMSE 检验模型性能。这里我使用自定义函数predict_tablepull_rmse来完成任务。

tree_tidy_train_pred <- predict_table(tree_best, train_data, TRUE)
tree_tidy_train_rmse <- pull_rmse(tree_tidy_train_pred)
print(tree_tidy_train_rmse) 
##       rmse  real_rmse 
##   1.078724 116.106006tree_tidy_test_pred <- predict_table(tree_best, test_data, TRUE)
tree_tidy_test_rmse <- pull_rmse(tree_tidy_test_pred)
print(tree_tidy_test_rmse) 
##       rmse  real_rmse 
##   1.074347 118.205989

带插入符号的决策树

set.seed(25)
tree_caret_time1 <- Sys.time()
tree_caret <- train(
  total~.,
  data = train_data_caret,
  method = "rpart",
  trControl = ctrl_caret,
  metric = "RMSE",
  tuneGrid = data.frame(cp = tree_cp)
)
tree_caret_time2 <- Sys.time()
print(tree_caret_time2 - tree_caret_time1) 
## Time difference of 4.469931 secs

哇哦!只需要 4.5 秒。而且,代码要短得多。train功能包括模型method = "rpart",交叉验证trControl = ctrl_caret,参数整定tuneGrid = data.frame(cp = tree_cp)

tree_caret_train_pred <- predict_table(tree_caret, train_data_caret, FALSE)
tree_caret_train_rmse <- pull_rmse(tree_caret_train_pred)
print(tree_caret_train_rmse) 
##       rmse  real_rmse 
##   1.078724 116.106006tree_caret_test_pred <- predict_table(tree_caret, test_data_caret, FALSE)
tree_caret_test_rmse <- pull_rmse(tree_caret_test_pred)
print(tree_caret_test_rmse) 
##       rmse  real_rmse 
##   1.074347 118.205989

比较模型

rbind(
  base_train_rmse, base_test_rmse,
  tree_tidy_train_rmse, tree_tidy_test_rmse,
  tree_caret_train_rmse, tree_caret_test_rmse
)##                           rmse real_rmse
## base_train_rmse       2.032927  181.0633
## base_test_rmse        2.026080  182.6137
## tree_tidy_train_rmse  1.078724  116.1060
## tree_tidy_test_rmse   1.074347  118.2060
## tree_caret_train_rmse 1.078724  116.1060
## tree_caret_test_rmse  1.074347  118.2060

如您所见,不管库是什么,决策树模型的结果都是相同的,因为我以相同的方式分割了数据并设置了交叉验证。此外,tidymodels 和 caret 都使用rpart作为底层引擎。因此,tidymodels 运行决策树需要 1 分多钟,而 caret 只需要 4-5 秒,这似乎很奇怪。

结论

我已经使用 tidymodels 几个星期了,我真的很喜欢集成到 tidyverse 中。但是我发现这么多的步骤和对象让我很困惑。例如,我一直试图从工作流对象中获取 RMSE。我可能需要多一点时间来熟悉新的生态系统。

GitHub 上提供了完整代码,并发布了Markdown的 HTML 版本。一如既往,我希望这个帖子是有帮助的。祝你有美好的一天!

参考

Vabalas,a .,Gowen,e .,Poliakoff,e .,和 Casson,A. J. (2019)。有限样本下的机器学习算法验证。 PloS one14 (11),e0224365。

CART:清晰而强大的模型的分类和回归树

原文:https://towardsdatascience.com/cart-classification-and-regression-trees-for-clean-but-powerful-models-cc89e60b7a85?source=collection_archive---------0-----------------------

入门,机器学习

CART 算法是如何工作的,如何在 Python 中成功使用?

购物车模型预测图面。在本文结尾的 Python 部分,可以看到图表是如何制作的。图片由作者提供。

简介

如果你想成为一名成功的数据科学家,了解不同的机器学习算法是如何工作的是至关重要的。

这个故事是解释每个算法的细微差别的系列的一部分,并提供了一系列 Python 示例来帮助您构建自己的 ML 模型。更不用说一些很酷的 3D 可视化!

故事涵盖以下主题:

  • CART 所属的算法类别
  • 关于 CART 算法如何工作的解释
  • 关于如何构建购物车决策树模型的 Python 示例

【CART 属于哪一类算法?

顾名思义,CART(分类和回归树)既可以用于分类问题,也可以用于回归问题。区别在于目标变量:

  • 利用分类,我们试图预测一个类别标签。换句话说,分类用于输出(目标变量)取一组有限值的问题,例如,明天是否会下雨。
  • 同时,回归用于预测数字标签。这意味着您的输出可以采用无限多的值,例如,房价。

这两种情况都属于机器学习算法的监督分支。

旁注,由于神经网络独特的机器学习方法,我已经将它们归为一类。然而,它们可以用于解决广泛的问题,包括但不限于分类和回归。下图是交互式,请务必点击👇在不同的类别上对进行放大并展示更多的

机器学习算法分类。由作者创建的互动图表。

如果你也热爱数据科学和机器学习 ,请 订阅 每当我发布新故事时,你都会收到一封电子邮件。

虽然在这个故事中,我把重点放在 CART 分类上,但是回归案例非常相似,只是使用了不同的方法来计算树中的最佳分裂。

分类和回归树是如何工作的?

示例

让我们从一个简单的例子开始。假设你有一堆贴有标签的橙子和曼德拉草,你想找出一套简单的规则,将来可以用它来区分这两种水果。

Philippe Gauthier 在 Unsplash 上拍摄的照片

通常,橙子(直径 6-10 厘米)比橘子(直径 4-8 厘米)大,因此您的算法找到的第一条规则可能基于大小:

  • 直径≤ 7cm。

接下来,你可能会注意到橘子的颜色比橙子略深。因此,您使用色标(1 =暗到 10 =亮)来进一步分割您的树:

  • 子树左侧的颜色≤5
  • 子树右侧的颜色≤6

你的最终结果是一个由 3 个简单规则组成的树,帮助你在大多数情况下正确区分橙子和橘子:

识别橙子和橘子的决策树。图片由作者提供。

【CART 如何找到最佳分割?

CART 中可以使用几种方法来确定最佳拆分。以下是分类树中最常见的两种:

基尼杂质

where p_i is the fraction of items in the class i. 

以上面的树为例,最左边的叶节点的 Gini 杂质是:

1 - (0.027^2 + 0.973^2) = 0.053

为了找到最佳分割,我们需要计算两个子节点的基尼系数的加权和。我们对所有可能的分割都这样做,然后将具有最低基尼系数杂质的分割作为最佳分割。

计算基尼系数。图片由作者提供。

重要提示:如果两个子节点的最佳加权 Gini 杂质不低于父节点的 Gini 杂质,则不应再进一步拆分父节点。

熵值法与基尼系数法基本相同,只是使用了一个略有不同的公式:

要确定最佳分割,您必须遵循上述所有相同的步骤。具有最低熵的分裂是最好的分裂。类似地,如果两个子节点的熵不低于一个父节点的熵,就不应该再进一步拆分了。

如何用 Python 建立 CART 决策树模型?

我们将构建几个分类决策树,并使用树形图和 3D 表面图来可视化模型结果。首先,让我们做一些基本的设置。

设置

我们将使用以下数据和库:

  • 来自卡格尔的澳大利亚天气数据
  • Scikit-learn 库,用于将数据拆分为训练测试样本,构建大车分类模型,以及模型评估
  • Plotly 用于数据可视化
  • 用于数据操作的熊猫和 Numpy
  • Graphviz 库绘制决策树图形

让我们导入所有的库:

然后我们从 Kaggle 获取澳大利亚的天气数据,你可以按照这个链接下载:https://www . ka ggle . com/jsphyg/weather-dataset-rattle-package。

一旦你在你的机器上保存了数据,用下面的代码接收它。请注意,我们还做了一些简单的数据操作,并派生了一些新的变量供以后在我们的模型中使用。

一小段 Kaggle 的澳大利亚天气数据做了一些修改。图片来自作者。

为了减少重复代码的数量,我们将创建几个可以在整个分析中重用的函数。

第一个函数执行以下操作:

  • 将数据分为训练样本和测试样本
  • 符合模型
  • 预测测试集上的标签
  • 生成模型性能评估指标
  • 创建决策树图

第二个函数将用于绘制带有测试数据和模型预测表面的 3D 散点图:

使用基尼杂质的 CART 分类模型

我们的第一个模型将使用所有可用的数值变量作为模型特征。同时,raintomorowflag将成为所有模型的目标变量。

注意,在写 sklearn 的 树的时候。DecisionTreeClassifier()只能以数值变量为特征。但是,您也可以使用分类值,只要您使用编码算法对它们进行编码,例如 sklearn 的顺序编码器 或任何其他合适的方法将分类值转换为数值。

让我们使用我们的 拟合 函数来构建模型,树深度限制为 3,最小叶子大小为 1000 个观察值。限制树的深度和叶子的大小有助于我们避免过度拟合。在后面的例子中,我们将会看到一旦我们移除了一些约束,树的复杂度会增加多少。

下面是 拟合 函数生成的输出:

模型 1 —购物车模型性能指标。图片由作者提供。

我们可以看到,该模型在预测干旱天数方面表现相对较好。然而,在预测雨天时,性能较差,测试数据的精度为 0.76,召回率为 0.34。

  • 精度意味着在模型预测的 76%的情况下明天会下雨。
  • 同时,召回意味着对于测试数据中的所有雨天,模型只识别了其中的 34%。

这两个类别标签的性能差异主要是由数据的不*衡造成的,干旱天比雨天多得多。

接下来,我们来看看由我们的 拟合 函数生成的树形图**:**

模型 1 —购物车模型决策树。图片由作者提供。

从上面可以看出,虽然该算法使用了几种不同的特征,但两个最重要的特征是“湿度 3pm”和“风速”,因为这是唯一两个影响分类标签预测为 0 或 1 的特征。

因此,我们可以通过减少特征的数量来创建一个具有相似性能的模型,如下例所示。

使用基尼杂质和 2 个特征的 CART 分类模型

让我们再次使用我们的 拟合 函数:

模型性能指标:

模型 2 —购物车模型性能指标。图片由作者提供。

正如所料,该模型的性能与第一个模型相同。但是,让我们来看看决策树是如何变化的:

模型 2—购物车模型决策树。图片由作者提供。

因此,虽然树在不同的地方是不同的,关键的分裂仍然是相同的。

最好的事情是,我们可以创建一个 3D 图表来可视化预测*面,因为我们只使用了两个输入要素。这就是第二个功能, Plot_3D, 派上了用场:

模型 2-CART 模型预测表面。图片由作者提供。

注意,顶部的黑点是 class=1(明天下雨)的实例,底部的黑点是 class=0(明天不下雨)的实例。同时,表面是基于模型预测的明天下雨的概率。最后,图中间的细线是概率=0.5,表示决策边界。

不足为奇的是,预测*面看起来像一组楼梯。这是因为预测概率遵循用于分割树节点的特定值的阶跃变化。例如,最低降雨概率(底部阶梯-暗红色)以“湿度 3pm = 51.241”和“风速= 53.0”为界

树深度无限制的 CART 分类模型

现在让我们看看当我们不限制树的深度时会发生什么。我们再次使用我们的 拟合 函数:

以下是最终的模型性能:

模型 3—购物车模型性能指标(具有最大深度)。图片由作者提供。

决策树(注意,为了更好地适应页面,该树已被旋转):

模型 3 —购物车模型决策树(具有最大深度)。图片由作者提供。

最后,3D 图形:

模型 3-CART 模型预测表面(具有最大深度)。图片由作者提供。

如您所见,由于对树深度没有限制,该算法创建了一个更加复杂的树,这可以在树图和 3D 预测表面上的“步骤”数量中看到。同时,模型的性能只是略微好一点(精确度=0.83)。

无论何时构建决策树模型,都应该仔细考虑复杂性和性能之间的权衡。在这个具体的例子中,性能的微小提高不值得额外的复杂性。

其他要探索的东西

有许多方法可以进一步微调您的购物车模型。举几个例子:

  • 你可以将“基尼”改为“熵”,使用基于熵的算法建立一个模型。
  • 您可以使用“随机”拆分器,而不是“最佳”拆分器“最佳”总是选择重要性最高的特征来产生下一个分割。同时,“随机”将选择一个随机的特征(尽管被特征重要性分布加权)。
  • 如上所述,您可以更改树的最大允许深度。
  • 您可以调整“class_weight”(在我们的 拟合 函数中命名为 clweight ),方法是传递一个带有每个类权重的字典,或者简单地为算法输入“balanced”以使用权重来*衡类样本。
  • 最后,你也可以尝试调整最小叶片尺寸。

结论

CART 是一个强大的算法,与其他 ML 方法相比,它也相对容易解释。它不需要太多的计算能力,因此允许您非常快速地建立模型。

虽然您需要小心不要过度拟合您的数据,但对于简单的问题,这是一个很好的算法。如果你想提高你的模型的性能和健壮性,你也可以探索集合方法,比如一个 随机森林

和往常一样,如果你喜欢学习决策树,或者有任何问题或建议,请给我写信。

干杯👏
索尔·多比拉斯

如果你已经花光了这个月的学习预算,下次请记得我。 我的个性化链接加入媒介是:

**https://solclover.com/membership **

您可能感兴趣的其他分类算法:

** **

案例研究 Olist Brazillian 数据集上的客户满意度预测

原文:https://towardsdatascience.com/case-study-1-customer-satisfaction-prediction-on-olist-brazillian-dataset-4289bdd20076?source=collection_archive---------8-----------------------

解决分类问题

皮卡伍德在 Unsplash 上的照片

企业总是试图让客户群参与进来,并对他们提供的服务感到满意。为了在行业中保持相关性,他们需要将最新的技术进步融入到他们的服务中。十多年前,互联网还是一个全新的事物,各行各业都试图利用这项技术的能力,轻松地充当各种企业及其客户之间的沟通媒介。在这十年里,各行各业开始提供迎合每个客户个人需求的服务。对于这样的服务,他们需要利用人工智能的力量。在这个案例研究中,我们将探索这项技术的一个方面。本案例研究分为以下几个部分

  • 商业问题
  • 商业问题的 ML 公式化
  • 基础数据分析
  • 业务约束
  • 绩效指标
  • 数据描述
  • 探索性数据分析
  • 特色工程
  • 机器学习
  • 未来工作
  • 链接
  • 参考文献

业务问题

Olist store 是一家电子商务企业,总部位于巴西圣保罗。这家公司是各种小企业和希望购买他们产品的顾客之间的唯一联系点。最*,他们在 Kaggle 上上传了一个 数据集,其中包含了 2016 年至 2018 年间在多个市场所做的 10 万份订单的信息。我们在电子商务网站上购买的东西会受到我们在该网站上读到的关于该产品的评论的影响。这家公司当然可以利用这些评论来删除那些一直收到负面评论的产品。它也可以为那些受顾客欢迎的商品做广告。此案例研究的源代码可在 此处 获得。

ML 公式化的商业问题

我们看到的是一个五星评级系统,它总结了顾客对他或她刚刚购买的产品的总体满意度。我们可以把这方面转化为一个二元分类问题,把 4 星和 5 星的评分作为正类,其余的作为负类。

基础数据分析

我们得到了多个表和一个描述这些表如何连接的模式。在合并所有的表之后,我们分析整个数据集。它包含多个分类和数字列。在将给定的 5 星评级转换为二进制后,我们看到正面类占据了数据集的 76%,剩余部分由负面类填充。这意味着数据集严重失衡。根据销售记录,家具装饰、美容产品和运动器材是最受欢迎的类别。据了解,顾客*均花费约 125 巴西雷亚尔从该网站购买产品。在分析客户的州分布时,我们可以看到大多数订单是由位于圣保罗的客户下的。大多数商品的运费是合理的。这可能是许多人对产品总体满意的原因。大多数交易都是用信用卡进行的。

业务约束

负面评论较少,但也很重要。我们应该确保较少数量的负面评论被归类为正面评论。这意味着我们需要尽量减少误报的数量。完成这项任务不需要任何延迟限制。

绩效指标

混淆矩阵用于洞察模型产生的错误类型。减少假阳性的数量需要精确度,减少假阴性的数量需要召回。这就是我们将使用宏观 F1 分数作为衡量标准的原因。

数据描述

当您查看解释数据库连接的示意图时,您会发现有八个表。这些表格的说明如下

  1. olist_orders_dataset :这个表连接到另外 4 个表。它用于连接与订单相关的所有详细信息。
    2)olist _ order _ items _ dataset:它包含已购买商品的详细信息,如发货日期、价格等。
    3)olist _ order _ reviews _ dataset:它包含与客户对他所购买的特定产品发表的任何评论相关的详细信息。
    4)olist _ products _ dataset:包含与产品相关的 ID、类别名称、尺寸等。
    5)olist _ order _ payments _ dataset:此表中包含的信息与特定订单的付款细节相关。
    6)olist _ customers _ dataset:详细描述该公司的客户群信息。
    7)olist _ geolocation _ dataset:包含卖家和客户双方的地理信息。
    8)olist _ sellers _ dataset:这个表包含了所有在这个公司注册的卖家的相关信息。

数据库模式

所有这些表都使用主键和外键连接。我们将连接所有单独的 CSV 文件来创建一个大表。所有这些关键字都以后缀“id”或“prefix”结尾。

探索性数据分析

由于该数据集基于巴西的一家电子商务公司,因此流通区域很可能是巴西及其邻国。这就是为什么我们将采用南美大陆的绘图,并使用地理定位数据集中提到的地理数据来直观地描述订单的地理位置。

南美洲地理地图

正如您在地图上看到的,大多数客户位于巴西。为了进一步分析,我们将不使用地理定位数据集。这就是为什么它不会被添加到主数据帧中。

order_items_products = pd.merge(order_items_dataset,products_dataset,on='product_id')
order_items_products_sellers = pd.merge(order_items_products,sellers_dataset,on='seller_id')
two_order_items_products_sellers = pd.merge(order_items_products_sellers,orders_dataset,on='order_id')
two_order_items_products_sellers_customer = pd.merge(two_order_items_products_sellers,customers_dataset,on='customer_id')
two_order_items_products_sellers_customer_reviews = pd.merge(two_order_items_products_sellers_customer,order_reviews_dataset,on='order_id')
final_dataframe = pd.merge(two_order_items_products_sellers_customer_reviews,order_payments_dataset,on='order_id')

有些观察结果可能会重复。这些都是多余的,这就是为什么我们需要删除它们。我们将从数据集中删除那些具有相同订单 ID、客户 ID、购买时间戳和评论的观察。这是因为客户不能在同一时间对同一产品多次发布相同的评论。注意,充当主键和外键的所有 ID 值都是惟一的。我们找不到这种行的模式,因此,我们将删除它们。

不可能估算日期时间数据。这就是为什么我们应该删除任何日期时间列中包含空值的那些行。在解析 datetime 列时,我们提取日期信息并使用它创建两个额外的列。“采购交付差异”列给出了采购和交付之间的天数。“预计实际交货差异”栏给出了交货所需的延迟或缩短的天数。

intermediate_time = final_dataframe['order_delivered_customer_date'].apply(lambda x: datetime.strptime(x, "%Y-%m-%d %H:%M:%S").date()) - final_dataframe['order_purchase_timestamp'].apply(lambda x: datetime.strptime(x, "%Y-%m-%d %H:%M:%S").date())
final_dataframe['purchase-delivery difference'] = intermediate_time.apply(lambda x:x.days)intermediate_time = final_dataframe['order_estimated_delivery_date'].apply(lambda x: datetime.strptime(x, "%Y-%m-%d %H:%M:%S").date()) - final_dataframe['order_delivered_customer_date'].apply(lambda x: datetime.strptime(x, "%Y-%m-%d %H:%M:%S").date())
final_dataframe['estimated-actual delivery difference'] = intermediate_time.apply(lambda x:x.days)

现在让我们尝试估算其他类型的列。对于分类栏,我们将使用该栏的模式,对于数字栏,我们将使用该栏的中位数进行插补。对于评论的评论和标题,我们使用术语“in deponível ”,这是英语术语“unavailable”的葡萄牙语翻译。

final_dataframe['product_category_name'].fillna(value=final_dataframe['product_category_name'].mode()[0], inplace=True)
final_dataframe['product_name_lenght'].fillna(value=final_dataframe['product_name_lenght'].mode()[0], inplace=True)
final_dataframe['product_description_lenght'].fillna(value=final_dataframe['product_description_lenght'].median(), inplace=True)
final_dataframe['product_photos_qty'].fillna(value=final_dataframe['product_photos_qty'].mode()[0], inplace=True)
final_dataframe['product_weight_g'].fillna(value=final_dataframe['product_weight_g'].mode()[0], inplace=True)
final_dataframe['product_length_cm'].fillna(value=final_dataframe['product_length_cm'].mode()[0], inplace=True)
final_dataframe['product_height_cm'].fillna(value=final_dataframe['product_height_cm'].mode()[0], inplace=True)
final_dataframe['product_width_cm'].fillna(value=final_dataframe['product_width_cm'].mode()[0], inplace=True)
final_dataframe['review_comment_message'].fillna(value='indisponível', inplace=True)

我们的目标是将这个案例研究转化为一个二元分类任务。为此,我们需要创建一个包含标签的新列。评分大于 3 的值被标记为正值,而评分小于或等于 3 的值被标记为负值。

final_dataframe['review_score'] = final_dataframe['review_score'].apply(lambda x: 1 if x > 3 else 0)

在绘制显示标签的饼图时,我们看到正类占据了整个数据集的 77.60%;而消极阶层仅占 22.40%。这表明整个数据集是不*衡的。

有些列只包含数字数据。这意味着找到这些列的基本统计信息是我们可以尝试的一件事。请注意,“价格”和“产品长度描述”列的*均值和中值之间存在显著差异。

前 4 列的基本统计数据

让我们创建一个名为“价格类别”的新列。该列用于根据价格将商品分类为昂贵、便宜和实惠。我们使用第一、第二和第三四分位数作为创建这些类别的条件。

final_dataframe['price_category'] = final_dataframe['price'].apply(lambda x:'expensive' if x>=139 else ('affordable' if x>=40 and x<139 else 'cheap'))

我们现在根据购买频率找到了前 12 个最受欢迎的产品类别。“床浴桌”类别明显比大多数其他类别更受欢迎。这是唯一一个销量超过 10000 件的品类。排在第 12 位的类别“园艺工具”仅售出约 3600 件。

圣保罗,也简称为“SP ”,是这家公司客户基础最大的州。这可能是因为该公司的总部设在圣保罗,更多的客户了解这个网站,由于他们在这个地区的营销策略。2016 年至 2018 年间,圣保罗售出了超过 4 万辆汽车。

当我们检查每个产品类别的定价时,我们可以看到属于“计算机”类别的产品的*均成本最高。*均费用在 1150 雷亚尔左右。第二高的品类,均价接*最高品类的一半。

对于这个图,我们考虑了一个项目的总*均成本。这意味着它是运费和项目原始成本的总和。我们可以看到情节的顺序没有改变。只是每个品类的*均成本都增加了。

我们现在正在寻找产生最高收入的城市。名为“皮安科”的城市位于顶部。

这里只有两种状态可见。迄今为止,只有 6 份订单被取消。分析那些已经取消的产品没有意义。因此,我们将删除它们。

final_dataframe = final_dataframe[final_dataframe['order_status'] != 'canceled']

下面给出的散点图在 x 轴上显示价格,在 y 轴上显示交货和购买之间的总时间差。可以看出,随着交付时间的增加,对产品不满意的几率明显增加。一件物品的价格上涨,如果按时送达,并不会引起太多的不满。

我们现在正在创建一个名为“每价格采购交付差异”的新列,它是给定价格的产品采购和交付之间的时间差。

final_dataframe['purchase_delivery_diff_per_price'] = final_dataframe['purchase-delivery difference']/final_dataframe['price']

运费成本和物品成本之间的散点图非常具有描述性。但可以说,即使运费成本很高,当物品成本较低时,顾客也会感到满意。

信用卡是最受顾客欢迎的支付方式。它们比其他替代品更受欢迎。第二种是 Boletos,是一种只有在巴西才能找到的凭证。从这个图中,我们可以看到,给一个产品的差评很可能不是因为付款相关的问题。

现在是时候删除机器学习任务不需要的所有列了。应该删除所有日期时间列。

final_dataframe.drop(['shipping_limit_date','order_purchase_timestamp','order_approved_at','order_delivered_carrier_date','order_delivered_customer_date','order_estimated_delivery_date','customer_id'], axis=1, inplace=True)

我们现在将创建一个名为“标签”的新变量,它包含了已编辑的类极性。应将该列从原始数据框中移除。

labels = final_dataframe['review_score']
final_dataframe.drop('review_score', axis=1, inplace=True)

“审查可用性”列指示特定项目的审查是否可用。包含这个列比在‘评论评论消息’中包含一堆零要好,因为它避免了稀疏性。稀疏性的问题是它会严重降低任何模型的性能。

final_dataframe['review_availability'] = final_dataframe['review_comment_message'].apply(lambda x: 1 if x != 'indisponível' else 0)

对于机器学习,我们需要定义一个用于训练数据的训练集和一个用于预测的测试集。这两个集合以相等的比例包含两个类。由于数据集是不*衡的,这些标签的分布有可能严重影响任何机器学习模型的性能。因此,我们需要确保测试集和训练集包含相同比例的正标签和负标签。为了结果的可重复性,我们需要添加一个种子值。

X_train, X_test, y_train, y_test = train_test_split(final_dataframe, labels, stratify=labels, test_size=0.2, random_state=0)

特征工程

一些列包含多个类别。我们通常想到的编码技术不是一键编码就是顺序编码。当我们使用独热编码技术时,稀疏性的问题出现了,因为有太多的类别。除非类别中存在序数,否则不能使用序数编码。解决这种情况的一种方法是使用响应编码。在这种技术中,我们将所有类别出现的概率与每个标签相加。这意味着每个类别将有两个概率值——一个用于肯定类别,另一个用于否定类别。总体而言,为每个分类列创建了两个不同的列。

def train_response(frame):
  f1 = frame[frame.iloc[:,1] == 0]
  f2 = frame[frame.iloc[:,1] == 1]
  global dict_frame, dict_f1, dict_f2
  dict_frame = dict(frame.iloc[:,0].value_counts())
  dict_f1 = dict(f1.iloc[:,0].value_counts())
  dict_f2 = dict(f2.iloc[:,0].value_counts())
  state_0, state_1 = [],[],
  for i in range(len(frame)):
    if frame.iloc[:,1][i] == 0:
      state_0.append(dict_f1.get(frame.iloc[:,0][i],0) / dict_frame[frame.iloc[:,0][i]])
      state_1.append(float(1-state_0[-1]))
    else:
      state_1.append(dict_f2.get(frame.iloc[:,0][i],0) / dict_frame[frame.iloc[:,0][i]])
      state_0.append(float(1-state_1[-1])) 
  df3 = pd.DataFrame({'State_0':state_0, 'State_1':state_1})
  return df3.to_numpy()def test_response(test):
  t_state_0, t_state_1 = [],[]
  for i in range(len(test)):
    if dict_frame.get(test[i]):
     t_state_0.append(dict_f1.get(test[i],0) / dict_frame.get(test[i]))
     t_state_1.append(dict_f2.get(test[i],0) / dict_frame.get(test[i]))
    else:
      t_state_0.append(0.5)
      t_state_1.append(0.5)
  df4 = pd.DataFrame({'State_0':t_state_0, 'State_1':t_state_1})
  return df4.to_numpy()def test_response(test):
  t_state_0, t_state_1 = [],[]
  for i in range(len(test)):
    if dict_frame.get(test[i]):
    t_state_0.append(dict_f1.get(test[i],0)/dict_frame.get(test[i]))
      t_state_1.append(dict_f2.get(test[i],0)/dict_frame.get(test[i]))
    else:
      t_state_0.append(0.5)
      t_state_1.append(0.5)
  df4 = pd.DataFrame({'State_0':t_state_0, 'State_1':t_state_1})
  return df4.to_numpy()

我们将使用序数或一个热编码对包含较少类别的分类特征进行编码,如果有太多类别,则使用响应编码对它们进行编码。不需要对数字特征进行编码。请注意,我们没有考虑数据框中的所有列。只有那些我们认为必要的才被编码。每个类别的编码模式如下所述

接下来,我们将研究文本数据。处理文本数据的最好方法之一是将它们转换成单词嵌入。单词嵌入优于 TF-IDF 向量和单词袋,因为它们携带单词的语义。在这个案例研究中,我们将使用 FastText 作为单词嵌入技术。有可能将这些单词转换成 TF-IDF 向量,然后使用潜在语义分析等技术降低维度。这种方法更快,但问题是我们使用这种技术得到的密集向量确实包含这些单词的语义表示。这种方法会降低我们模型的准确性。在对文本进行矢量化之前,我们需要清理它。首先,我们将删除停用词,并使用 regex 清理剩余的词。

sp = spacy.load('pt')
all_stopwords = sp.Defaults.stop_wordsdef process_texts(texts):processed_text = []
    dates = '^([0]?[1-9]|[1|2][0-9]|[3][0|1])[./-]([0]?[1-9]|[1][0-2])[./-]([0-9]{4}|[0-9]{2})$'

    for text in texts:
        text = re.sub(r'\r\n|\r|\n', ' ', text) 
        text = re.sub(r'^https?:\/\/.*[\r\n]*', ' ', text) 
        text = re.sub(dates, ' ', text) 
        text = re.sub('[ \t]+$', '', text)
        text = re.sub('\W', ' ', text)
        text = re.sub('[0-9]+', ' ', text)
        text = re.sub('\s+', ' ', text)
        text = ' '.join(e for e in text.split() if e.lower() not in all_stopwords) 
        processed_text.append(text.lower().strip())

    return processed_text

我们仍然没有将所有的数字特征纳入同一尺度。为此,我们将使用标准化。我们使用标准化而不是规范化,因为正如在基本统计数据的描述中所看到的,这个数据集中存在许多异常值。

strn = StandardScaler()
strn.fit(X_train[['price','freight_value','product_photos_qty','product_weight_g', 'product_length_cm',
       'product_height_cm', 'product_width_cm', 'payment_value','purchase-delivery difference','estimated-actual delivery difference','purchase_delivery_diff_per_price']])
X_train_strn = strn.transform(X_train[['price','freight_value','product_photos_qty','product_weight_g', 'product_length_cm',
       'product_height_cm', 'product_width_cm', 'payment_value','purchase-delivery difference','estimated-actual delivery difference','purchase_delivery_diff_per_price']])
X_test_strn = strn.transform(X_test[['price','freight_value','product_photos_qty','product_weight_g', 'product_length_cm',
       'product_height_cm', 'product_width_cm', 'payment_value','purchase-delivery difference','estimated-actual delivery difference','purchase_delivery_diff_per_price']])

现在是时候将所有必要的特征连接在一起,并检查最终数据帧的形状。可以看出,整体有 332 个特征。

我们将尝试使用两种技术来减少这种维数。一种是通过使用奇异值分解找到硬阈值,另一种是通过使用自动编码器。奇异值分解是一种广泛使用的矩阵分解技术,可以应用于任何维度的矩阵。它将给定的矩阵转换成一组三个矩阵,分别命名为 U,σ和 V*。请注意,符号“”用于表示转置运算符。任何维数为 MxN 的矩阵 A 的奇异值都是维数为 NxN 的方阵 AA 的特征值的*方根。这里,σ是一个对角矩阵,它包含奇异值作为沿对角线的元素。对应于σ的对角元素的 U 矩阵的行和 V矩阵的列被称为左和右奇异向量。记住,我们默认取矩阵 V 的转置。让我们用几何直觉来解释奇异值。正如我们已经知道的,维度矩阵 MxN 是从真实空间ℝᴺ到真实空间ℝᴹ的线性变换,在数学上表示为ℝᴺ→ ℝᴹ.SVD 是一种将这种直接变换分解为一组三个变换的方法,这三个变换是-第一旋转、缩放和第二旋转。现在考虑一个单位圆,它有两个黄色和洋红色的矢量。这里我们正在考虑从ℝ到ℝ的转变。因此,在本例中,M 和 N 都等于 2。变换后,这个圆变成一个旋转过的椭圆。如图所示,这一整体转变可分为 3 个步骤。第一次旋转(应用 V)后,圆旋转一个角度。然后σ矩阵缩放该图的轴。每个轴的比例与奇异向量的大小成比例。注意,我们的两个向量的大小会改变。第二次旋转(应用 U)后,椭圆旋转了一个角度。

由 Georg Johann 绘制的奇异值分解图,在 CC-BY 2.0 许可下分发

降秩是一种技术,通过这种技术可以将高维噪声数据转换成低维更干净的数据。秩定义了一个阈值,我们可以考虑该阈值来截断使用 SVD 获得的 U 矩阵。研究人员过去常常采用启发式方法来寻找最佳排名。这种方法的问题是,他们不确定使用这种秩获得的截断矩阵是否包含足够的信息来重建干净的图像。另一种方法是使用试错法,这很耗时。在最*的一篇论文中,提到了一种称为最优奇异值硬阈值的技术,它为寻找截断的最优阈值奠定了理论基础。我们需要找到一个阈值τ*,它是最佳阈值。此公式中使用的“*”符号不表示转置。该公式取决于添加到图像中的噪声值是否已知,以及矩阵是否为正方形。假设该噪声的*均值为 0,标准偏差为 1。矩阵是正方形且噪声已知的可能性很小。但是如果这两个条件都满足,公式就是

这里,“n”是方阵的维数,“σ”是噪声。在大多数情况下,我们不知道添加了多少噪声。公式是

这里,β=n/m,yᵐᵉᵈ是所有奇异值的中间值。注意,我们这里使用的ω(β)值只是*似值。它们的实际值也可以计算出来,但是需要进一步的处理。由于我们在 SVD 中使用这种降秩技术只是为了降维,而不是为了图像去噪,因此找到ω(β)的精确值并不重要。

X_final_sparse = scipy.sparse.csr_matrix(np.vstack((X_train_final,X_test_final)))
U, sigma, VT = randomized_svd(X_final_sparse, n_components=min(X_final_sparse.shape[0],X_final_sparse.shape[1])-1,n_iter=5,random_state=45)
beta = min(X_final_sparse.shape) / max(X_final_sparse.shape)
omega_approx = 0.56*beta**3 - 0.95*beta**2 + 1.82*beta + 1.43
tau = np.median(sigma)*omega_approx
k = np.max(np.where(sigma>tau))+1

可以看出,新形成的矩阵具有 116 个特征,保留了大部分方差。在这之后,我们将截断的矩阵分成训练集和测试集。

使用神经网络可以降低维数。我们将使用自动编码器,一种有效编码数据的神经网络。注意,自动编码器属于无监督学习。在自动编码器架构中,输入和输出层的大小是相同的。隐藏层的大小总是小于外部层的大小。每个连续隐藏层的尺寸不断减小,直到到达瓶颈层;超过这个范围,尺寸会继续增加。请注意,架构是对称的。压缩数据的部分称为编码器,解压缩数据的部分称为解码器。编码器从输入端向瓶颈层延伸,解码器从那里延伸到末端。瓶颈层应该有我们需要的数据编码的维度。自动编码器旨在最小化重建误差。输入在瓶颈层被压缩,然后在输出层被解压缩。在输入和输出之间的误差最小化之后,训练收敛。

在我们的架构中,我们在瓶颈层使用 116 的维度。在网络的每一端只使用了两个隐藏层。训练收敛后,我们需要去掉解码器部分,使用编码器部分将训练集和测试集转换到所需的维度。

机器学习

现在,我们已经使用两种不同的降维技术创建了两个版本的数据,我们将尝试使用各种机器学习和深度学习算法对数据进行建模,然后尝试使用不同的指标来比较它们的性能。我们计划对它们分别应用五种不同的算法。这些算法是-K-最*邻(KNN)、逻辑回归、随机森林、xgboost 和多层感知器(MLP)。我们将把它们中的每一个应用于一种形式的数据,然后将它们全部应用于另一种形式的数据。

硬阈值奇异值分解

加权 K *邻

在 KNN 的情况下使用的超参数是最*邻(K)的计数,其值是范围从 1 到 9 的奇数。当 K 值为 3 时,性能据说是最佳的。验证宏 F1 的分数是 0.8587,不是很好。通过检查测试混淆矩阵,我们可以看到假阳性点的计数大于假阴性点的计数。这不是一个好的分类器。

逻辑回归

逻辑回归中使用的超参数是逆正则化常数(C ),其值是 10 的幂,范围从 1e-7 到 1e-3。当 C 的值为 1e-5 时,该模型表现最佳。验证宏 F1 分数为 0.9003,这是好的。不幸的是,当我们绘制测试集的混淆矩阵时,我们可以看到假阳性点的数量大于真阴性点的数量。这不是一个好的分类器。

随机森林

随机森林中使用的超参数是基本估计量的计数,在这种情况下是决策树。在 50 和 210 之间选择六个值作为估计数,其中极限包含在集合中。任何两个连续值之间都有 30°的差异。验证宏 F1 得分为 0.9161,非常好。真阴性的计数大于假阳性的计数。这是一个好的分类器。

XGBoost

xgboost 中使用的超参数是基本估计量的计数,在这种情况下也是决策树。在 50 和 210 之间选择六个值作为估计数,其中极限包含在如上所述的集合中。验证宏 F1 得分为 0.9191,非常好。真阴性的计数大于假阳性的计数。这是一个好的分类器。

多层感知器

现在我们将使用多层感知器进行分类。这种情况下使用的优化器是 Adam,学习率是 1e-3。验证宏 F1 得分为 0.9074,很好。在这种情况下,真阴性的计数大于假阳性的计数。这是一个好的分类器。

从目前我们看到的情况来看,random forest,Xgboost 和 mlp 可以正确地对点进行分类。Xgboost 是其中表现最好的。

自动编码器

加权 K *邻

在 KNN 的情况下使用的超参数是最*邻(K)的计数,其值是范围从 1 到 9 的奇数。当 K 值为 3 时,性能据说是最佳的。验证宏 F1 的分数是 0.8564,不是很好。通过检查测试混淆矩阵,我们可以看到假阳性点的计数大于假阴性点的计数。这不是一个好的分类器。

逻辑回归中使用的超参数是逆正则化常数(C ),其值是 10 的幂,范围从 1e-7 到 1e-3。当 C 的值为 1e-2 时,该模型表现最佳。验证宏 F1 分数为 0.8874,没问题。当我们绘制测试集的混淆矩阵时,我们可以看到假阳性点的计数大于真阴性点的计数。这是一个糟糕的分类器。

随机森林

随机森林中使用的超参数是基本估计量的计数,在这种情况下是决策树。在 50 和 210 之间选择六个值作为估计数,其中极限包含在集合中。任何两个连续值之间都有 30°的差异。验证宏 F1 得分为 0.8895,很好。不幸的是,真阴性的数量少于假阳性的数量。这是一个糟糕的分类器。

XGBoost

xgboost 中使用的超参数是基本估计量的计数,在这种情况下也是决策树。在 50 和 210 之间选择六个值作为估计数,其中极限包含在如上所述的集合中。验证宏 F1 分数为 0.8867,没问题。不幸的是,真阴性的数量少于假阳性的数量。这是一个糟糕的分类器。

多层感知器

现在我们将使用多层感知器进行分类。这种情况下使用的优化器是 Adam,学习率是 1e-3。验证宏 F1 分数为 0.8924,没问题。在这种情况下,真阴性的计数小于假阳性的计数。这是一个糟糕的分类器。

从我们这里可以看出,我们不能使用自动编码器压缩的数据集来设计一个好的分类器。

原始数据集

我们还没有尝试将标记化的评论直接作为模型的输入。为了实现这一点,我们需要对整个数据集进行操作,而不是对数据集的截断或压缩版本进行操作。为此,我们将尝试两种深度学习模型。

在最初的模型中,我们将只尝试使用长短期记忆(LSTM)。我们为这个模型创建了两个不同的输入。第一个输入是数字数据,另一个是文本数据。嵌入层将标记化的输入转换成固定长度的向量。我们正在使用 FastText 训练嵌入层。因此,使用该层将标记化和填充的文本转换成单词嵌入。这条道路上的下一层是 LSTM。当给定一个序列时,该层能够学习顺序依赖性。下一层直接输送到致密层。这两个输入稍后合并,在输出端有一个 sigmoid 激活函数。验证宏 F1 得分为 0.9211,非常好。真阴性的计数大于假阳性的计数。这是一个好的分类器。

在下一个模型中,我们计划使用 1 维卷积神经网络和 LSTM。在这里,我们连续使用两对一维 CNN 和 LSTM 层,然后将其与数值数据相结合。这里,我们也使用 sigmoid 作为最后的激活函数。验证宏 F1 得分为 0.9010,很好。真阴性的计数大于假阳性的计数。这是一个好的分类器。

当我们检查总结表时,我们可以看到双输入 LSTM 和 xgboost 在使用硬阈值 SVD 截断的数据上对测试数据的性能最好。

降维

没有降维

未来的工作

我们可以将这个问题转化为一个多类分类问题,并检查评级预测。这是一种称为对数损失的度量,也可以用作替代方法。也有可能使用其他系综。

部署

下面给出了部署的屏幕截图。同样的一段录像可以在 这里 观看。

预测截图

链接

LinkedIn:【https://www.linkedin.com/in/ashwin-michael-10b617142/】
Github 库:https://github.com/Ashcom-git/case-study-1
Kaggle 数据集:https://www.kaggle.com/olistbr/brazilian-ecommerce

参考

应用根。2021.应用 AI 课程。[在线]见:https://www.appliedaicourse.com/.[2021 年 5 月 6 日访问]。
泰勒,共和党,2021 年。最优奇异值硬阈值。[在线]Pyrunner.com。可在:http://www.pyrunner.com/weblog/2016/08/01/optimal-svht/【2021 年 5 月 9 日获取】。布朗利律师事务所,2021 年。自动编码器特征提取分类。[在线]机器学习掌握。可在:<https://machine learning mastery . com/auto encoder-for-class ification/>【2021 年 5 月 12 日访问】。
t . Calin 和 j .薛,2021。tensor flow中的自定义 f1_score 指标。[在线]堆栈溢出。可在:https://stackoverflow.com/a/64477588【2021 年 5 月 7 日获取】。
堆栈溢出。2021.如何用 matplotlib.pyplot 改变图例尺寸。[在线]可在:https://stackoverflow.com/a/7125157[2021 年 5 月 3 日访问]。
阿齐兹,h .,库马尔,s .,科尔舒诺夫,v .和阿萨,p .,2021。正则表达式匹配日期格式 DD-MM-YYYY 和 DD/MM/YYYY 。[在线]堆栈溢出。可在:https://stackoverflow.com/a/47218282【2021 年 5 月 13 日获取】。
沃尔玛和铺路公司,2021 年。匹配换行符— \n 还是\r\n?。[在线]堆栈溢出。可在:https://stackoverflow.com/a/52057778【2021 年 5 月 14 日获取】。Python,h .和 Martin,l .,2021。如何在 Python 中移除一个字符串内的任何 URL。[在线]堆栈溢出。可在:https://stackoverflow.com/a/11332580【2021 年 5 月 14 日获取】。
莫滕森,第 2021 页。如何使用正则表达式删除尾部空格?。[在线]堆栈溢出。可在 https://stackoverflow.com/a/9532388<获得>【2021 年 5 月 16 日获得】。

案例研究 2:用于特征提取的无监督神经注意模型

原文:https://towardsdatascience.com/case-study-2-an-unsupervised-neural-attention-model-for-aspect-extraction-1c2c97b1380a?source=collection_archive---------22-----------------------

行业笔记

由马库斯·温克勒在 Unsplash 上拍摄

十多年来,企业一直利用互联网的可达性来为其内容做广告。如果没有这种广告媒介,这些公司就很难获得他们想要的客户群。但随着社交网站的快速增长,互联网已经发展成为一个论坛,消费者可以根据他人在网上发布的产品反馈来评估产品和服务。对任何特定产品的评论决定了它在市场上的声誉。关于网上购物行为的各种研究表明,潜在客户在信任任何特定产品之前,*均至少会阅读四到五条评论。这就是为什么顾客评论对企业的运作至关重要。在这个案例研究中,我们将探索基于方面的抽取的概念,这对于在线评论是至关重要的。我们将它分为以下几个部分—

  • 问题描述
  • 车型概述
  • 数据描述
  • 数据预处理
  • 模型架构
  • 基线模型
  • 结论
  • 部署
  • 未来工作
  • 链接
  • 参考文献

问题描述

情感分析是一种自然语言处理技术,用于确定给定文本是正面的、负面的还是中性的。当您希望从给定的文本块中推断出整体情感时,这种技术非常有用。这种技术的一个缺点是,如果人们希望了解客户对产品的哪个方面不满意,就必须手动筛选每个评论。这种形式的体力劳动非常耗时。在这种情况下,基于方面的情感分析是更好的选择。使用这种技术,我们可以通过将情感与评论的特定方面联系起来来分析评论。

在 2017 年由何,Wee Sun Lee,Hwee Tou Ng 和 Daniel Dahlmeier 发表的题为“一种用于方面提取的无监督神经注意力模型”的研究论文中,研究人员设计了一种无监督的深度神经网络,可以根据它们的方面对一组句子进行分类。这个模型限制了它自己只能识别每个输入的一个方面,并且没有将任何情感与这个方面相关联。任何经过适当训练以执行情感分析的模型都可以在评论被分离后应用于评论。在本案例研究中,我们将从头开始设计 2017 年研究论文中提到的模型。我们将使用 Tensorflow 2.x .作为 Python 中用于模型构建和训练的后端框架。

模型概述

以前训练来执行这项任务的传统机器学习模型假设每个句子中出现的单词是独立的,上下文无关。这种假设导致这些模型的性能下降。单词嵌入是在 2013 年由托马斯·米科洛夫、伊利亚·苏茨基弗、程凯、格雷格·科拉多和杰弗里·迪恩发表的题为“单词和短语的分布式表示及其组合性”的论文中引入的。在这篇文章中,他们介绍了一个名为 Word2Vec 的模型。这个模型的目的是表明句子的上下文有多重要。使用这种模型,相似的单词被映射到相似方向的向量。同现单词在嵌入空间中彼此靠*。

在 2014 年由 Dzmitry Bahdanau、Kyunghyun Cho 和 Yoshua Bengio 撰写的题为“通过联合学习对齐和翻译”的神经机器翻译的研究论文中,注意力机制的概念被引入到语言翻译任务中。这项技术模仿了注意力的认知过程,允许任何生物选择并专注于相关的刺激。按照这种技术,文本的某些部分比整个文本具有更高的优先级。换句话说,注意力使模型能够在训练过程中强调重要的单词,而不强调无关的单词。这提高了模型发现更多一致方面的能力。研究人员给这个模型起的名字是基于注意力的方面提取(ABAE)。

数据描述

我们将使用城市搜索语料库作为训练和测试的数据集,可以从这个网站免费下载。研究论文中使用了相同的数据集来测试模型。数据集中有 52,574 条评论,其中只有 3,400 条被标记。本文考虑了六个方面。这些方面是食物,工作人员,氛围,价格,轶事,和杂项。研究人员选择未标记的数据作为训练集,选择标记的数据作为测试集。这些设置可以在研究者的谷歌驱动链接上找到。

数据预处理

加载测试集和训练集之后,我们需要对它们进行预处理。为了这个
的目的,我们定义了 preprocess()和 complete_preprocess()
函数。

使用这个函数,我们将评论中的所有单词转换成小写字母后进行分词。下一步是将这些令牌符号化。从本质上讲,通过将每个单词转换成其对应的词条,词条化有助于使您的数据矩阵更加稀疏。这样的词被称为是他们的规范形式或字典形式。此外,请注意,我们必须删除不会给评论增加任何价值的停用词。

为了训练 Word2Vec 模型,我们需要以列表的形式提供输入。这意味着每个评论被转换成一个列表,整个集合是一个包含多个子列表的列表。这可以在 split_list 函数的帮助下完成。

所有评论都以字符串表示形式提供。深度神经网络模型无法理解字符串,因此,我们需要以数字格式对它们进行编码。这意味着检查中出现的每个令牌都应该映射到一个大于或等于 1 的唯一数字。所有字符串,包括数字 8 和 9,当出现在评论中时都有唯一的映射。但是根据研究论文,在映射到相应的表示之前,所有的数字都应该表示为由表示的单个标记。当将测试数据转换成相应的数字表示时,可以看到这个集合可能包含一些在训练集中不可用的单词。我们会在映射前用来表示这样的词。为了保持输入数据的一致性,我们需要将所有这些令牌列表转换成统一的长度。这可以在衬垫的帮助下完成。使用这种技术,通过在映射前预先计划或附加标记,所有的标记列表都被转换成相同的大小。在我们的例子中,我们将在每个列表前面加上标记。每个填充集的宽度等于该集中最长句子的长度。预留令牌的映射为:{' ':0,' ':1,' ':2}。从这个映射中,我们可以推断出集合中出现的所有单词都应该得到 3 或更大的值。下面给出了一个标记化和填充表示(最大长度为 4)的虚拟示例,说明输入在输入到模型之前应该是什么样子——

"I ate 2 donuts" -> ["I", "ate", "2", "donuts"] -> [3, 4, 2, 5]“I dislike donuts” -> ["<pad>", "I", "dislike", "donuts"] ->
[0, 3, 6, 5]"I drank" -> ["<pad>", "<pad>", "I", "drank"] -> [0, 0, 3, 7]

模型架构

在前面提到的引入 Word2Vec 概念的论文中,研究人员还添加了一个称为负采样的概念,帮助我们更快地训练单词嵌入。通俗地说,负面样本是从训练集中所有可用评论的集合中随机选取的评论。这意味着,当我们将一篇综述作为输入(称为正样本或目标样本)时,我们应该挑选一组 P 篇综述与目标样本一起作为负样本。这里,P 可以是一个小数字,例如 5 或 6,或者甚至可以是一个更大的数字,例如 21 或 22。请注意,我们并没有按照已经存在于训练集中的顺序将输入直接输入到模型中。这是为了应对训练数据的过度拟合。为了总结这个令人困惑的概念,让我仔细地将我的话重组如下——当 P 的值是 5 时,在一个时期的每一步中,我们用从训练集随机采样的 1 个评论作为正输入,用从这个相同的集替换随机采样的 5 个评论作为负样本来呈现模型。在这种情况下,假设批量大小为 1。如果批量大小被设置为值 32,则在一个时期的任何一个步骤中,我们将 321=32 个正样本与 325=160 个负样本一起输入到模型中。这是生成阳性和阴性样本的代码—

现在是详细了解 ABSA 的时候了。下面给出了该模型的架构。这里需要注意的重要一点是,该图仅描述了阳性样本的处理。

基于注意力的情感分析器架构(图片取自纸张)

使用从 Word2Vec 模型生成的所有单词嵌入,我们将它们组合成一个矩阵。这个矩阵将被视为嵌入矩阵。下一步是使用 k-means 聚类算法训练这个矩阵,并识别模型收敛后生成的聚类中心。形成的聚类中心的数目等于 k 的值,k 是我们在训练过程之前手动馈入模型的超参数。k 的值应该是我们希望使用 ABSA 模型识别的不同方面的数量。rₛ层的权重矩阵(在上图中表示为 t)使用所有这些聚类中心的归一化形式进行初始化。这个 T 矩阵也被称为方面矩阵。

正样本和负样本的最大区别在于,正样本被馈送到注意层,而后者没有。但是在进一步处理之前,所有的样本必须通过一个不可训练的嵌入层被转换成单词嵌入。该层使用在先前步骤之一中创建的嵌入矩阵来初始化。使用 Tensorflow 的子类化 API,我们设计了多个自定义层来处理样本。

第一个自定义层的名称是“*均”。它可以计算评论中所有单词嵌入的*均值,用术语 yₛ.表示

yₛ公式(图片取自纸张)

然后,正样本嵌入和 yₛ值被馈送到关注层。术语 dᵢ表示单词嵌入、矩阵 m 和 yₛ.的转置之间的中间乘法这里,M 是可训练的,并使用 Glorot 统一初始化器进行初始化。在这个初始化式中,样本是从特定范围内的均匀分布中抽取的。这个极限值的计算取决于这个矩阵的形状。通过在 dᵢ上应用 softmax,我们计算 aᵢ,这是注意力权重。

dᵢ和 aᵢ的公式(图片取自纸张)

下一个自定义图层名为 WeightedSum。使用这一层,我们计算每个单词的嵌入和为每个单词计算的注意力权重之间的点积。这个点积用术语 zₛ.来表示

zₛ公式(图片取自纸张)

使用 Tensorflow 的自然密集层,我们将 zₛ乘以随机初始化的权重,然后将偏差项添加到其中。最重要的是,我们应用 softmax。这一层在文中被称为 pₜ。

pₜ公式(图片取自纸张)

下一步是通过自定义*均层传递负样本。我们得到的输出是一个包含每个样本*均值的列表。这个列表用 zₙ.来表示最后一层是 rₛ,我们之前提到过。下面给出的是 rₛ和 pₜ.之间的关系

rₛ公式(图片取自纸张)

自动编码器是用于压缩数据的无监督神经网络架构。输入和输出的大小相同。中间有一个瓶颈层,用于将数据压缩到所需的大小。从输入层到瓶颈层的部分称为编码器,从瓶颈层到输出层的部分称为解码器。这个网络的目标是在输出端重构被瓶颈层压缩的输入。通过训练模型,我们试图最小化重建误差。

Autoencoder 模型(图片作者: Seongju Hong

整个 ABSA 模型是一个定制的自动编码器。从输入层到 pₜ层的部分是编码器,从 pₜ层到 rₛ层的部分是解码器。我们的目标是最小化 rₛ层的重建误差。

在 2016 年由 Mohit Iyyer,Anupam Guha,Snigdha Chaturvedi,Jordan Boyd-Graber 和 Hal Daumé III 撰写的题为“世仇家庭和前朋友:动态虚构关系的无监督学习”的论文中,研究人员提到了对比最大利润损失的概念。如果负样本嵌入与重构嵌入相似,这个损失函数会严重地惩罚模型。这意味着损失函数试图最大化 rₛ和 zₛ之间的乘积,而它试图最小化 rₛ和 nᵢ(when nᵢ之间的乘积是来自列表 zₙ).的元素我们使用一个名为 HingeLoss 的自定义层来执行这一步中必要的计算。损失函数的公式如下所示

J(θ)的公式(图片取自纸张)

为了防止过度拟合,我们需要正则化模型。甚至为了这个目的,提到了定制的 L2 正则化。另外,请注意,我们应该使用方面矩阵的规范化形式进行正则化。使用自定义函数将正则化代码应用于密集 rₛ图层。

U(θ)的公式(图片取自纸张)

我们计划使用 RMSProp 作为训练这个模型的优化器。学习率为 1e-02,ε值为 1e-06。在训练该模型时,有必要设置 clipnorm 值。在我们的例子中,我们将其设置为 10。这意味着梯度的 L2 范数被限制在给定值。我们正在为 15 个时期训练模型,并且在每个时期考虑 182 个批次。批量大小设置为 1024,负采样率为 20。当在任何时期中计算的损失小于先前记录的最小损失时,我们显示从每个方面得到的前 50 个单词及其相应的相似性得分。以下是培训代码—

从印刷的文字,我们必须手动推断方面。相应地,我们还应该基于这些信息创建一个聚类图。现在是时候使用张量板绘制表示最小化的图形了。如你所见,模型收敛于损失值 4.7。

张量板图(图片由作者提供)

现在是对测试集执行预测的时候了。我们将需要创建一个新的自定义模型使用以前制作的 ABSA 模型的层。对于这个新制作的模型,我们将只使用为 ABSA 模型中的正样本设计的输入层作为该模型的输入。该模型的输出是 ABSA 的 pₜ层。

研究人员根据这些方面对测试进行了筛选。他们只允许那些属于食物、员工或环境方面的评论。该模型不能在一次审查中识别多个方面。因此,即使那些包含多个样本的评论也被删除了。在这一步之后,最后的任务是执行预测和生成分类报告。正如你所看到的,ABSA 模型的性能似乎是公*的!

ABSA 分类报告(图片由作者提供)

基线模型

主题建模是一种无监督的方法,通过找到一些自然的项目组(在此上下文中称为主题)来对文档进行分类。这项技术已经使用了很长时间,因为它可以自动组织、理解、搜索和有效地汇总数据。最流行的主题建模算法是潜在狄利克雷分配(LDA)。这是基于基线模型方面的情感分析任务。我们将比较我们的 ABSA 模型的结果和使用 LDA 模型获得的结果。

一个文档可以是具有不同相似比例的多个主题的一部分。每个文档(在我们的例子中也称为评论)是一个单词列表。我们真正想弄清楚的是一个单词属于每个主题的概率。表格中的每一行代表一个不同的主题,每一列是数据集中出现的一个不同的单词。每个单元格包含单词(列)属于主题(行)的概率。

每个主题包含所有可用单词的概率分数(图片由 Ria Kulshrestha 提供)

对于我们的任务,这些主题只是方面。因此,导出的主题数量等于我们分析所需的方面数量。关于单词的一个重要假设是这些单词的顺序和语法结构并不重要。这意味着单词是独立的,这样的假设会导致性能下降。无论如何,我们将在我们的训练集上训练 LDA 模型,批量大小设置为 1024。下面给出了显示属于每个方面的前 50 个单词的代码。

在打印分类报告时,我们可以观察到 ABSA 模型在方面提取任务方面的性能更好。

LDA 分类报告(图片由作者提供)

结论

如您所见,基于神经网络的模型非常适合基于方面的情感分析任务。这种表现应该归功于注意机制。

部署

下面提到了部署的截图。同样的录像可以在这里观看。

预测截图(图片由作者提供)

未来的工作

我们的模型只能识别包含不超过一个方面的评论。此外,当我们希望评估与任何给定方面相关的情绪时,我们需要使用其他模型。这一领域未来的研究应该集中在这两个问题上。

链接

Github 资源库:【https://github.com/Ashcom-git/case-study-2

领英:https://www.linkedin.com/in/ashwin-michael-10b617142/

参考

应用根。[在线]地址:https://www.appliedaicourse.com/。

何、李维孙、吴惠头和丹尼尔·达尔梅尔(2017)。用于特征提取的无监督神经注意模型。计算语言学协会第 55 届年会会议录(第 1 卷:长论文)。

‌tomas·米科洛夫、伊利亚·苏茨基弗、陈开、格雷戈·科拉多和杰弗里·迪恩(2013 年)。词和短语的分布式表示及其组合性。神经信息处理系统进展 26 (NIPS 2013)。

Dzmitry Bahdanau、Kyunghyun Cho 和 Yoshua Bengio。(2015).通过联合学习对齐和翻译的神经机器翻译。第三届国际学习代表会议论文集。

Mohit Iyyer、Anupam Guha、Snigdha Chaturvedi、Jordan Boyd-Graber 和 Hal Daumé III。(2016).世仇家庭和前朋友:动态虚构关系的无监督学习。计算语言学协会北美分会 2016 年会议论文集:人类语言技术。

陈燕琳(2019 年)。如何使用文本建立 ld a 主题模型?【在线】中等。可从以下网址获得:https://medium . com/@ yanlinc/how-to-build-a-LDA-topic-model-using-from-text-601 CDC bfd 3 a 6。

苏珊·李(2018)。Python 中的主题建模和潜在狄利克雷分配。【在线】中等。可从以下网址获得:https://towards data science . com/topic-modeling-and-latent-Dirichlet-allocation-in-python-9bf 156893 c 24。

Ria Kulshrestha (2020 年)。潜在狄利克雷分配。【在线】中等。可从 https://towards data science . com/latent-Dirichlet-allocation-LDA-9d 1 CD 064 FFA 2 获取。

桑内·德·罗弗(2020)。方面,更好的话题?在亚马逊化妆品评论中应用无监督特征抽取。【在线】中等。可从以下网址获得:https://medium . com/@ sanne . de . ro ever/aspects-the-better-topics-applying-unsupervised-aspect-extraction-on-Amazon-cosmetics-reviews-9d 523747 f8e 5。

为 360 度数据谱系的外部资产编目

原文:https://towardsdatascience.com/catalog-external-assets-for-a-360-data-lineage-448c8f6bf2b2?source=collection_archive---------33-----------------------

如何定制 IBM Watson 知识目录以支持任何种类的外部资产并改进您的数据治理。

由 DreamQuest 在 pixabay 上拍摄的照片

在之前的文章中,我已经展示了如何通过使用 IBM Cloudpak for Data 特别是 Watson 知识目录来自动分类大量数据集。

好的企业目录是数据治理的基石。在这里可以记录所有数据和治理资产的存在以及它们之间的关系。为了回答数据沿袭问题,确定任何给定资产的依赖图,或者进行影响分析,获取资产之间的关系是必不可少的。

例如,维护良好的目录应该有助于回答以下问题:

这个数据集的数据从哪里来?

这个数据集中的数据用在哪里?

如果该资产被修改或删除,将会影响到哪项资产?

只有当所有与感兴趣的资产直接或间接相关的资产都被正确编目时,业务目录才能回答这些问题。这些资产可能具有非常不同的性质,例如:

  • ETL 流——或一般的数据流——将数据从源移动和转换到目标。
  • 直接或间接使用数据集数据的报告。
  • ML 模型是从数据集导出的数据构建的。
  • Jupyter 笔记本电脑根据从数据集获得的数据进行实验。
  • 等等…

这个列表可能很长,在数据谱系中扮演重要角色的资产类型可能会因公司使用的技术而有很大不同。

使问题复杂化的是,现实生活中的场景很少只涉及来自单一供应商的同类解决方案。公司经常使用不同供应商的解决方案,这些解决方案运行在不同的系统上,但都在数据资产的生产、转换或消费方式中发挥作用。

没有一个软件供应商可以提供一个业务目录来支持您在现实生活中可能遇到的所有类型的资产。因此,能够定制目录以支持新的资产类型、加载它们并捕获它们与其他编目资产的关系是至关重要的,无论这些新资产的性质如何。

本文的目标是展示如何使用 IBM Watson 知识目录来完成这项工作。

IBM 沃森知识目录

IBM Watson 知识目录是用于数据的 IBM Cloudpak 的业务目录,支持开箱即用的不同资产类型,例如:

  • 数据连接
  • 数据资产(表、文件、模式、数据库等)
  • 商业术语
  • 数据类别
  • ML 模型
  • 等等…

该列表并不详尽,并且会随着 Cloudpak for Data 的每个新版本而不断增加。

但是像任何软件一样,除非您的流程只涉及使用 Cloudpak 为数据创建的资产,否则您的数据和治理流很可能涉及外部资产,这些资产不受目录的现成支持,但是仍然应该被编目,以便获得完整的数据血统。这种外部资产可以是 ETL 流、来自其他供应商的报告或数据模型、物联网流中的物理设备,或者来自在 Cloudpak 外部管理的其他 IBM 产品的资产。

幸运的是,IBM Watson Knowledge Catalog 提供了一个 API 来注册新类型的资产,并通过 REST API 加载外部资产。在本文的剩余部分,我们将通过一个简单的例子来了解如何使用这个 API。

编目 IBM 信息分析器数据规则

Watson Knowledge Catalog 的定制可以用任何种类的资产来演示,但是出于本文的目的,我将通过一个例子来演示如何添加对 IBM Information Analyzer 数据规则的支持,这些数据规则运行在 Cloudpak 之外的经典信息服务器上。您应该能够将该过程移植到不同类型的资产。

信息分析器数据规则概述

数据规则是在 IBM Information Server 中创建和执行的资产类型,它定义了一个非*凡的数据质量约束,该约束必须由应用该规则的数据集的所有行来验证。关于数据质量约束的更多细节,请参见我之前的文章“如何量化数据质量”。

IBM Information Analyzer 项目中定义的数据规则

解释数据规则的细节超出了本文的范围,但是就本练习的目的而言,目前您唯一需要理解的是,数据规则是具有以下特征的资产:

  • 它是在主机上的 IBM Information Server 安装中定义的资产,该主机可能与运行 IBM Cloudpak for Data 的主机不同。
  • 像任何其他资产一样,数据规则有一个名称、描述和一个 ID,在定义它的系统中唯一地引用它。
  • 数据规则是在数据质量项目(也称为工作空间)的上下文中定义的。
  • 数据规则至少与一个数据集相关,但它也可以应用于多个数据集的连接结果。

使用两个数据集绑定数据规则的详细信息

Information Analyzer 数据规则还有其他属性,如绑定细节或输出定义等,但是为了保持示例的简单性,我们将只考虑前面列出的用于本练习的属性,因为它们足以捕获数据规则和其他资产之间的依赖关系。

一个 IBM Information Server 安装可能定义了数百个数据规则。它们中的每一个都可能与不同的数据资产相关。在本文的其余部分,我们将看到实现以下目标所需的不同步骤:

  1. 定义一个新的资产类型来表示 IBM Watson 知识目录中的信息分析器数据规则
  2. 提取外部 IBM 信息服务器的所有数据规则的相关元数据。
  3. 将提取的数据规则的元数据加载到目录中,并在新加载的数据规则和已经编目的数据资产之间创建关系。

为了保持这个例子的简单,我们将假设要加载的数据规则所引用的所有数据资产都已经在 Watson Knowledge Catalog 中编目。这可以通过运行数据规则引用的数据源的自动发现来完成,正如我在以前的文章中所描述的。

在 Watson 知识目录中定义新的自定义资产类型:

为了简化我们将在本文中使用的命令,让我们首先在一个 UNIX shell 中定义一个环境变量***【WKC _ 主机】*** ,它包含我们想要对数据规则进行编目的 Cloudpak for Data 系统的主机名。

export WKC_HOST=*cpd_cluster_host*

(您需要将 cpd_cluster_host 替换为目标系统的 IP 地址的主机名)

接下来,让我们通过运行下面的命令获得一个认证令牌,如 CP4D 文档中所述。

curl -k -X POST https://*$WKC_HOST*/icp4d-api/v1/authorize -H 'cache-control: no-cache' -H 'content-type: application/json' -d '{"username":"***username***","password":"***password***"}'

(将 用户名密码 替换为授权用户的凭证详情)

该命令响应是一个 JSON 文档,如下所示:

{"_messageCode_":"200","message":"Success","token":"...some_long_string..."}

让我们复制令牌属性的值,并将其放在另一个环境变量中,这样我们就不需要在每个命令中复制该令牌:

export TOKEN=...some_long_string...

现在我们有了一个认证令牌,我们准备使用 WKC REST API 来操作沃森知识目录的资产类型,如在文档中所描述的。您可以使用 REST API 探索默认的资产类型,并检索它们定义的 JSON 表示,以便更好地理解它们是如何定义的。

在我们的例子中,我们将通过使用 REST API POST {service_URL}/v2/asset_types?catalog_id={catalog_id} 来创建一个名为 data_rule 的新的定制资产类型,如文档的本节中所述。

自定义资产类型特定于目录。Watson Knowledge Catalog 可能包含多个目录,因此您需要找出您想要导入新资产的目录的 ID。您可以通过在 UI 中打开目录并在浏览器中查看 URL 来轻松确定目录的 id。目录 ID 是 URL 中路径元素 /catalogs/ 后面的一个长字符串,如下例所示:

[https://yourserver.yourcompany.com/data/catalogs/**b134fdf3-7d3f-40e0-835b-7ce54a62cc7e**?context=icp4data](https://wkc-cpd-wkc.apps.wkc-ia-test3-lb.fyre.ibm.com/data/catalogs/b184fda3-7d3f-40e0-835b-7ce54a62cc7e?context=icp4data)

这里,让我们再次复制该 ID,并将其放入环境变量中:

export CATALOG_ID=**<catalog_id pasted from the URL>**

创建新资产类型的 POST 命令需要一个 JSON 文档作为主体,该文档定义了要创建的新资产类型的元数据。文档至少应该包含新资产类型的名称和描述,以及对其字段的描述。在我们的例子中,我们将使用以下属性:

  • 名称:数据 _ 规则
  • 描述:信息分析仪数据规则
  • 资产字段:
    • 主机:包含规则的信息服务器系统的主机名。
    • 项目名称:定义规则的信息分析器项目的名称。
    • rid :源信息服务器中数据规则的唯一标识。

请注意,我们不需要为与数据规则相关的数据资产定义属性,因为这些将通过使用资产关系来定义,WKC 允许我们在任何种类的资产之间定义资产关系。

基于这个为数据规则编目的初始最小字段列表,创建新资产类型的 REST API 的有效负载可以定义如下:

{
  "description": "Information Analyzer Data Rule",
  "name": "data_rule",
  "fields": [
     {
        "key": "host",
        "type": "string",
        "facet": true,
        "is_array": false,
        "search_path": "host",
        "is_searchable_across_types": true
     },
     {
        "key": "projectName",
        "type": "string",
        "facet": true,
        "is_array": false,
        "search_path": "projectName",
        "is_searchable_across_types": true
     },
     {
        "key": "rid",
        "type": "string",
        "facet": false,
        "is_array": false,
        "search_path": "rid",
        "is_searchable_across_types": true
     }
  ]
}

将新资产类型的定义保存在文件data _ rule _ asset _ type . JSON中,并运行以下命令在目标目录中创建新的资产类型。

curl -k -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header "Authorization: Bearer $TOKEN" -d @data_rule_asset_type.json "https://$WKC_HOST:443/v2/asset_types?catalog_id=$CATALOG_ID"

如果命令成功,它应该返回一个成功代码(200 ),带有新创建的资产类型的 JSON 定义。

接下来让我们试着通过使用 API POST {service_URL}/v2/assets?catalog_id={catalog_id}创建一个新类型的样本资产,如文档中所描述的。

与创建新的资产类型一样,我们需要准备一个 JSON 格式的有效负载,描述要在目标目录中创建的新资产。

创建一个文件dummydatarule . JSON,内容如下:

{
  "metadata": {
    "asset_type": "data_rule",
    "name": "Dummy Data Rule 1",
    "description": "Some Dummy Data rule",
    "tags": ["tag1", "tag2"],
    "origin_country": "us",
    "rov": {
      "mode": 0
    }
  },
  "entity": {
    "data_rule": {
        "host": "iaHost1",
        "projectName": "iaProject1",
        "rid": "rid1" 
    }
  }
}

此有效负载包含创建新资产所需的最少信息:

  • asset_type 定义要创建的资产的类型。在我们的例子中,我们使用新创建的定制资产类型 data_rule
  • 名称描述 是我们要新建的虚拟数据规则的名称和描述。
  • 标签 是可选的,它包含一个与新创建的资产相关联的目录标签数组。标签可用于方便搜索或提供资产的附加信息。在本例中,我们关联了两个虚拟标签 tag1tag2
  • origin _ countryrov 定义资产的位置和权限。出于本文的目的,我们将使用一些默认值。
  • 字段 实体 必须包含一个与资产类型名称相同的字段——在我们的例子中是data _ rule——它本身包含我们在上一步创建新的定制资产类型时定义的字段值。在我们的例子中,基于前面对资产类型 data_rule 的定义,我们可以定义 3 个属性 hostprojectNamerid

让我们通过运行以下 cURL 命令在目录中提交这个新数据规则的创建:

curl -k -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header "Authorization: Bearer $TOKEN" -d @dummyDataRule.json "https://$WKC_HOST:443/v2/assets?catalog_id=$CATALOG_ID"

如果该命令成功,它应该返回一个包含其 id 的新创建资产的 JSON 描述,并且当打开目标目录时,您应该能够在 Watson Knowledge Catalog UI 中看到新创建的虚拟数据规则。

Watson 知识目录中加载了虚拟数据规则

创建与其他资产的关系

与任何其他资产一样,新创建的自定义资产可以与其他资产相关联。您可以通过使用 UI 来定义这些关系,但是在我们的示例中,我们希望通过编程来实现,因为我们希望自动导入大量的资产。

创建资产间关系的 API 记录在这个链接下。简而言之,API 是带有 JSON 主体的PUT /v2/assets/{asset_id}/relationships/{relationship_name}?catalog_id={catalog_id}, JSON 主体指定资产和目标资产的目录 id。

为了测试这个特性,让我们找出同一目录中一个数据集的 id,并在我们的虚拟数据规则和那个数据集之间定义一个类型为 "uses/used by" 的关系。找出数据集 id 的一个简单方法是在 UI 中打开数据集,并从浏览器中的 URL 复制它的 id。

我们必须传递给 PUT 命令以创建关系的 JSON 有效负载如下:

{
  "relationship_targets": [
    {
      "catalog_id": "19f11301-8392-4733-b747-751f5230e566",
      "asset_id": "81fa1a02-4773-4801-a53b-1d374fb83b07"
    }
  ]
}

catalog_idasset_id 的值替换为您想要链接到数据规则的数据资产的 id,或者可以是任何其他资产类型,并将有效负载保存在文件add relationship . JSON中。然后使用下面的 cURL 命令创建关系——您需要用之前创建的虚拟规则的 id 替换占位符******。

curl -k -X PUT --header 'Content-Type: application/json' --header 'Accept: application/json' --header "Authorization: Bearer $TOKEN" -d @addRelationship.json "https://$WKC_HOST:443/v2/assets/***<datarule_id>***/relationships/uses?catalog_id=$CATALOG_ID"

在命令运行之后,当在 UI 中打开数据规则时,您应该能够看到类型 使用 的新关系。打开数据集,会看到 使用的 类型的反向关系指向数据规则。

数据规则和数据资产之间的新关系

自动化流程

既然我们已经成功地定义了新的资产类型,并测试了可以使用 REST APIs 将数据规则导入到目录中,那么让我们自动化这个过程,从外部 IBM Information Server 安装中提取所有数据规则并对其进行编目。

第一个问题是提取规则的元数据。信息服务器提供了多种机制来实现这一点。您可以使用 REST API,或者针对元数据数据库(XMETA)编写 SQL 查询。在本文中,我们将使用 SQL。

解释 IBM Information Server 的 SQL API 超出了本文的范围。有关更多详细信息,您可以参考信息服务器文档。为了简化本文,我准备了一个现成的 SQL 查询,它允许检索给定信息分析器项目的所有数据规则的名称、描述以及相关数据集的路径:

SELECT DISTINCT PROJECT.NAME AS PROJECT, 
       RULE.NAME, 
       RULE.SHORTDESCRIPTION AS DESCRIPTION, 
       CONCAT('/',CONCAT(COL.SCHEMA,CONCAT('/',COL.TABLE))) AS PATH FROM IAVIEWS.IARULE RULE
INNER JOIN IAVIEWS.IAPROJECT PROJECT ON RULE.PROJECTRID=PROJECT.RID
INNER JOIN IAVIEWS.IARULEBINDING BINDING ON BINDING.RULERID=RULE.RID
INNER JOIN IAVIEWS.IAREGISTEREDCOLUMN COL ON BINDING.TARGETRID=COL.RID
WHERE PROJECT.NAME='***<ProjectName>***'

该查询将返回如下图所示的结果。如果一个规则绑定到多个表,结果将包含每个绑定表的一行。因此在下面的例子中,项目 【测试 _ 规则】 包含 2 个数据规则,一个被命名为 “子 _ 测试 _ 银行 _ 客户” ,并被绑定到路径为***/BANK 1/BANK _ 客户*** 的数据集。另一个名为 “信用卡 _ 年龄 _ 银行 2”,绑定到两个数据集,路径分别为***/银行 2/银行 _ 账户*** 和***/银行 2/银行 _ 客户*** 。

检索信息分析器项目的数据规则的 SQL 查询的结果

在此基础上,我们需要编写一些脚本:

  • 运行前面的 SQL 查询,从 IBM Information Server 安装中检索所选信息分析器项目的所有数据规则
  • 对于每个提取的数据规则,执行 Watson Knowledge Catalog REST API,在目标目录中创建新的数据规则资产
  • 在目录中搜索与数据规则引用的数据集具有相同路径的数据集,并在新创建的数据规则和目录中已解析的数据集之间创建关联。

为了使本文简单,我在 Jupyter noteboook 中用 Python 实现了所有这些步骤:

运行笔记本中的所有单元后(如笔记本中所述,您将需要根据系统的详细信息调整一些变量),您将在 Watson Knowledge Catalog 中看到所有外部数据规则都表示为普通目录资产。

在 IBM Watson 知识目录中作为定制资产导入的数据规则

当打开数据规则时,您可以看到已经创建了与其相关数据集的关系—假设在执行笔记本时数据资产已经导入到目录中。

导入数据规则的资产详细信息,显示与数据资产的关系

同样的关系也可以从数据资产中看到,它包含了一个类型为 "的反向关系,由指向数据规则的 使用。

数据资产和数据规则之间的关系,从数据资产中显示

自定义资产预览

新创建的自定义资产与 Watson Knowledge Catalog 本机支持的任何其他资产类型一样显示,只是“资产预览”选项卡默认为空。

默认情况下,资源预览不适用于自定义资源类型

还可以在目录中嵌入自定义资产预览 UI,只要它是可以在 Web 浏览器中打开的 Web UI。

在我们的示例中,可以使用以下 URL 打开用于查看数据规则详细信息的 Information Analyzer Web UI:

[https://***<iis_hostname>***/ibm/iis/igcui/assets/***<datarule_rid>***](https://iaqa95-ug-2.fyre.ibm.com/ibm/iis/igcui/assets/b20de59c.ef0f3886.2pg7c6fpc.9vr2drb.jt2tg2.hh5573mmk20lu7fohkfth)

Watson Knowledge Catalog 提供了一种注册 URL 的方法,以便在需要显示用于预览特定资产类型的 UI 时调用。这是通过稍微更新我们之前创建的资产类型的 JSON 定义来完成的:

{
  "description": "Information Analyzer Data Rule",
  "fields": [
     {
        "key": "host",
        "type": "string",
        "facet": true,
        "is_array": false,
        "search_path": "host",
        "is_searchable_across_types": true
     },
     {
        "key": "projectName",
        "type": "string",
        "facet": true,
        "is_array": false,
        "search_path": "projectName",
        "is_searchable_across_types": true
     },
     {
        "key": "rid",
        "type": "string",
        "facet": false,
        "is_array": false,
        "search_path": "rid",
        "is_searchable_across_types": true
     }
  ]**,
  "external_asset_preview": {
    "base_client_url": "**[**https://<iis_hostname>/ibm/iis/igcui/assets**](https://iaqa95-ug-2.fyre.ibm.com/ibm/iis/igcui/assets)**",
    "url_parameters_from_asset_attributes": [],
    "url_path_from_asset_attributes": "rid"
  }**
}

用粗体标记的附加属性指定,每当需要预览这种类型的资产时,WKC 应该调用通过附加 base_client_url 和在属性URL _ path _ from _ asset _ attributes中指定的资产属性的值构建的 URL。

为了测试此更改,请将***替换为您从中导入数据规则的信息服务器主机名,并将修改后的 JSON 文档保存在名为data _ rule _ with _ preview _ asset _ type . JSON***的文件中。然后使用以下命令更新资产类型的定义:

curl -k -X PUT --header 'Content-Type: application/json' --header 'Accept: application/json' --header "Authorization: Bearer $TOKEN" -d @data_rule_with_preview_asset_type.json "https://$WKC_HOST:443/v2/asset_types?catalog_id=$CATALOG_ID"

该命令将更新 data_rule 资产类型的现有定义。更新后,如果您重新加载目录的资产预览屏幕,您应该会看到一条消息(至少在 Firefox 上是这样),表明出于安全原因,该页面不能嵌入,但您可以在不同的浏览器选项卡中加载它。这是 Information Server UI 的一项安全功能,可防止原始 UI 嵌入到另一个 UI 中,但这仍然提供了一种在不同选项卡中打开此 UI 的便捷方式。通过部署不同的 web 应用程序,可以嵌入没有这种安全限制的 UI 面板。

摘要

在本文中,我们已经看到了为了获取完整的谱系,目录支持定制的资产类型是多么重要。我们还看到了如何通过使用 Watson Knowledge Catalog 的 REST API 来轻松实现这一点。作为一个具体的例子,我们已经定制了一个目录来支持外部信息分析器数据规则作为一个新的资产类型,并运行一个脚本来将所有外部数据规则导入到我们的目录中。然后,我们已经看到,如何以编程方式创建资产之间的关系。最后,我们探索了如何使用专门的资产查看器定制 UI 本身。

同样的过程可以应用于支持任何种类的资产类型,对于这些资产类型,可以提取元数据信息,以便将它们导入到目录中。我们只研究了几个 REST APIs。其他 API 命令也允许我们定义资产之间的特殊类型的关系,以更好地捕捉语义。

人工智能产品要求目录

原文:https://towardsdatascience.com/catalog-of-requirements-for-ai-products-bae95ae50e85?source=collection_archive---------33-----------------------

如何在你的 ML 项目中什么都不忘记

最*我听了一个有趣的故事。一家大型石油公司向数据科学家提出了一个问题:他们要观察卡车司机在运输汽油时是否遵守了安全指示(特别是,他们是否在车厢内吸烟)。过了一段时间,数据科学家提出了一个解决方案——一个看起来完美的硬件模块:它记录视频,使用神经网络进行评估,并以非常低的错误率触发警报。唯一的问题是,该模块太大,无法安装在卡车驾驶室的任何地方。

照片由 PIXNIO 拍摄

总的来说,如果不整合到更大的技术背景中,工业中几乎没有任何机器学习模型会增加价值。由于所有的决策和工作都遵循系统的需求,获得正确的需求是绝对关键的。每一个被遗忘的需求都增加了您以后不得不重新构建部分解决方案的可能性,或者在最坏的情况下,从头开始重新构建。这意味着浪费精力,不能按时交付,失去客户的信任。

需求工程是在软件开发过程中建立起来的一门学科。对于软件项目,也有一些模板和清单,它们有助于不忽略任何涉众或需求。正如我们所知,机器学习解决方案有一些其他项目中没有的特殊性:

  • 与数据集相关的一切
  • 实验再现性
  • 伦理问题
  • 上下文漂移
  • 等等。

因此,拥有一个人工智能解决方案的需求目录是很好的。我在网上找到的所有东西都只包含一些你需要问的问题。因此,我创建了一个新的目录,旨在尽可能完整(见下文摘录)。

链接到完整模板

重要提示:如果与包含常规软件系统要求的另一个目录/模板一起使用,此目录涵盖了所有内容。这样的目录已经存在很长时间了,所以没有理由重复这项工作。我推荐 Volere 模板(老免费版,新付费版),不过你也可以用另一个选项。这里提供的目录应该通过将机器学习特定部分添加到通用软件需求中来缩小差距。

Volere 模板结构

如何使用这个目录(和 Volere 模板)通常取决于用户。在我看来,务实的方法是在启动 DS 项目时仔细检查问题(对于某些需求,在项目过程中进行澄清可能更有意义。)努力找到每个问题的答案。像“在我们的上下文中无关紧要”这样的回答是明确允许的。对于其余项目,搜索相关的利益相关者,询问他们,并记录他们告诉你的内容。

你可以在这里找到目录,它是免费的。

欢迎对该目录进行改进和更改的请求——请提交请求或打开 GitHub 问题。

CatBoost CPU 训练加速技巧

原文:https://towardsdatascience.com/catboost-cpu-training-speedup-tricks-57cb10974ce3?source=collection_archive---------9-----------------------

使用 CatBoost 获得更快的训练速度,即使您没有单独的 GPU

图片来自pix abaycebbi

我与这些公司都没有关系。这是一项独立审查。

本文面向那些没有配备独立(独立)NVIDIA GPU(显卡)的 PC 或笔记本电脑,并且希望运行大幅加速的 CatBoost 模型的用户。

如果你已经有一台带独立 NVIDIA GPU 的 PC 或笔记本电脑,跳过这篇内容,跳到下面这篇我写的文章。

</10x-times-fast-catboost-training-speed-with-an-nvidia-gpu-5ffefd9b57a6>

CatBoost 模型可以使用 CPU 或 GPU 进行训练。很明显,对于大型数据集,通过 GPU 训练可以获得更好的加速(例如 10 倍)。

但是,在 CatBoost CPU 训练中可以使用一些技巧来实现显著的加速。其中大多数可以通过改变参数值来实现,而其他的则需要对数据进行一些操作。

让我们来探索它们。

减少迭代次数

在 CatBoost 模型中,boosting 轮次或迭代次数由参数iterations定义。默认值为 1000。我们可以减小这个值来加快训练速度。

cb = CatBoostClassifier(iterations=100)
cb = CatBoostRegressor(iterations=100)

我用一个 10M 行的数据集测试了 100 次和 1000 次迭代:

  • **100 次迭代:**训练时间 95.5 秒,准确率 0.72 分
  • 1000 次迭代: 878 秒训练时间,0.74 精度分数

在将迭代次数减少 10 倍后,您可能会期望精确度分数略有下降,但是在模型训练中您可以获得 9 倍的加速。

**注:**CatBoost 模型中的学习率与迭代次数成反比。如果你减少迭代次数,你也需要增加学习率,反之亦然。但是,该算法会根据迭代次数自动调整学习率。学习率还取决于数据集的大小。在 CatBoost 模型中设置learning_rate=None(默认)即可。

使用所有 CPU 核心

不是每个人都有独立的 GPU。但是,您可能有一个内核数量更多的好 CPU。参数thread_count定义了在 Catboost 模型训练中 CPU 应该使用多少内核。默认情况下,所有内核都由 CPU 使用。这用-1 表示。

cb = CatBoostClassifier(thread_count=-1)
cb = CatBoostRegressor(thread_count=-1)

我已经用一个 10M 行的数据集对 3 个内核和 6 个内核(在我的例子中是所有的T2内核)进行了测试:**

  • **3 核:**训练时间 119 秒,准确率 0.72 分
  • 6 核: 95.5 秒训练时间,0.72 准确率分数

准确性分数不受训练过程中使用的 CPU 核心数量的影响。在这种情况下,如果使用所有(默认)CPU 内核,您可以减少大约 25%的训练时间。

减少树的深度

您可以定义每个提升回合中添加到集合的每个新树的深度。该值可由 CatBoost 模型中的参数depth控制。默认值为 6。我们可以减小这个值来加快训练速度。

cb = CatBoostClassifier(depth=3)
cb = CatBoostRegressor(depth=3)

我用一个 10M 行的数据集对树深度 3 和 6 进行了测试。

  • 深度-3: 训练时间 95.5 秒,准确率 0.72 分
  • 深度-6: 训练时间 127 秒,准确率 0.74 分

在降低树深度后,您可能会期望精确度分数略有下降,但是在模型训练中您可以获得大约 33%的加速。

将对象数据类型转换为分类数据类型

您可以在 CatBoost 中直接使用分类特征。下面是如何。默认情况下,Pandas 将分类值存储在不能直接用于 CatBoost 的对象数据类型中。您有两个选择来克服这个问题:

  • 您可以通过使用 Pool() 类将整个数据集转换为 CatBoost 的特殊 Pool 数据类型。
  • 您可以将 对象 数据类型转换为 类别 数据类型。
for col in data.select_dtypes(include=['object']):
  data[col] = data[col].astype('category')

使用第二个选项可以在 CatBoost 模型训练中实现显著的加速。

使用 Numpy 数组代替 Pandas 数据框

Numpy 数组和 Pandas 数据帧都可以用作 CatBoost 算法的输入。但是,对大型数据集使用 Numpy 数组将显著加快 CatBoost 训练过程。

摘要

CatBoost GPU training 只有在您的 PC 配有 NVIDIA GPU 的情况下才能使用。此外,请注意,如果数据集不够大,CPU 和 GPU 的训练时间不会有太大差异。

因此,在我们只需要使用 CPU 进行 CatBoost 训练的场景中,我们今天讨论的技巧对于获得加速非常有用。

在大多数情况下,我们可以通过改变参数值来控制训练速度。有时候,我们不需要改变价值观。默认值将提供最佳的训练速度!

阅读下一条(推荐):

使用 NVIDIA GPU 将训练 CatBoost 模型的速度提高 10 倍!

</10x-times-fast-catboost-training-speed-with-an-nvidia-gpu-5ffefd9b57a6>

阅读下一条(可选):

为数据科学和机器学习任务选择合适的笔记本电脑!

</20-necessary-requirements-of-a-perfect-laptop-for-data-science-and-machine-learning-tasks-7d0c59c3cb63> [## 数据科学和机器学习任务对完美笔记本电脑的 20 项必要要求

towardsdatascience.com](/20-necessary-requirements-of-a-perfect-laptop-for-data-science-and-machine-learning-tasks-7d0c59c3cb63)

今天的帖子到此结束。

如果您有任何反馈,请告诉我。

同时,你可以 注册成为会员 来获得我写的每一个故事,我会收到你的一部分会员费。

非常感谢你一直以来的支持!下一个故事再见。祝大家学习愉快!

特别感谢 Pixabay 上的 cebbi ,为我提供了这篇文章的封面图片。

鲁克山普拉莫迪塔
2021–11–21

6 分钟后 CatBoost 回归

原文:https://towardsdatascience.com/catboost-regression-in-6-minutes-3487f3e5b329?source=collection_archive---------1-----------------------

Python 中 CatBoost 回归分析的简单实用介绍

马库斯·斯皮斯克在 Unsplash 上的照片

本文旨在提供一个实践教程,在 Sci-Kit Learn library 的波士顿住房数据集上使用 CatBoost 回归器。

目录

  1. CatBoost 简介
  2. 应用
  3. 最终注释

介绍

CatBoost 是一种相对较新的开源机器学习算法,由一家名为 Yandex 的公司在 2017 年开发。Yandex 是谷歌的俄罗斯同行,从事搜索和信息服务。

CatBoost 的核心优势之一是能够将各种不同的数据类型(如图像、音频或文本特征)集成到一个框架中。但 CatBoost 也提供了一种处理分类数据的特殊方式,需要最少的分类特征转换,这与大多数其他机器学习算法相反,它们不能处理非数值。从功能工程的角度来看,从非数字状态到数字值的转换可能是一项非常重要和繁琐的任务,CatBoost 使这一步变得过时。

CatBoost 建立在决策树和梯度推进的理论之上。boosting 的主要思想是顺序组合许多弱模型(表现略好于随机机会的模型),从而通过贪婪搜索创建一个强有力的竞争预测模型。因为梯度提升顺序地拟合决策树,所以拟合的树将从先前树的错误中学习,从而减少错误。将一个新函数添加到现有函数的过程一直持续到选定的损失函数不再被最小化。

在决策树的生长过程中,CatBoost 并不遵循相似的梯度推进模型。相反,CatBoost 会生成不经意树,这意味着树是通过施加以下规则来生成的:同一级别的所有节点使用相同的条件测试相同的预测器,因此可以使用按位运算来计算叶的索引。不经意树过程允许简单的拟合方案和 CPU 上的效率,而树结构作为正则化来操作,以找到最佳解决方案并避免过度拟合。

比较计算效率:

学习速度,Yandex [2]

根据 Google trends,与更流行的 XGBoost 算法相比,CatBoost 在搜索流行度方面仍然相对不为人知。

谷歌趋势(2021 年)[3]

CatBoost 仍然相当未知,但该算法通过其处理异构、稀疏和分类数据的方法提供了巨大的灵活性,同时仍然支持快速训练时间和已经优化的超参数。

应用

本教程的目标是为 Python 中的 CatBoost 回归提供实际操作体验。在这个简单的练习中,我们将使用波士顿住房数据集来预测波士顿的房价。但是对这些数据应用的逻辑也适用于更复杂的数据集。

所以让我们开始吧。

首先,我们需要导入所需的库和数据集:

import catboost as cb
import numpy as np
import pandas as pd
import seaborn as sns
import shap
import load_boston
from matplotlib import pyplot as pltfrom sklearn.datasets 
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score
from sklearn.inspection import permutation_importanceboston=load_boston()boston = pd.DataFrame(boston.data, columns=boston.feature_names)

数据探索

检查数据集中的任何 Na 值始终被认为是一种好的做法,因为它会混淆甚至损害算法的性能。

boston.isnull().sum()

但是,该数据集不包含任何 Na。

在进行数据科学项目时,数据探索和特征工程阶段是一些最关键(也是最耗时)的阶段。但是在这种情况下,主要重点是介绍 CatBoost 算法。因此,如果你想深入描述性分析,请访问 EDA &波士顿房价预测【4】。

培养

接下来,我们需要将数据分成 80%的训练集和 20%的测试集。

目标变量是“MEDV”——以 1000 美元为单位的自有住房的中值

X, y = load_boston(return_X_y=True)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state=5)

为了训练和优化我们的模型,我们需要利用 CatBoost 库集成工具将特征和目标变量组合成训练和测试数据集。该池允许您精确定位目标变量、预测值和分类特征列表,而池构造器将组合这些输入并将其传递给模型。

train_dataset = cb.Pool(X_train, y_train) 
test_dataset = cb.Pool(X_test, y_test)

接下来,我们将介绍我们的模型。

model = cb.CatBoostRegressor(loss_function=’RMSE’)

我们将使用 RMSE 测量作为我们的损失函数,因为它是一个回归任务。

在算法适合特定任务的情况下,参数调整可能会有所帮助。CatBoost 库为固有的网格搜索技术提供了一个灵活的接口,如果您已经知道 Sci-Kit 网格搜索功能,您也会熟悉这个过程。

在本教程中,将只包括最常见的参数。这些参数包括迭代次数、学习速率、L2 叶正则化和树深度。如果你想发现更多的超参数调整的可能性,查看 CatBoost 文档这里。

grid = {'iterations': [100, 150, 200],
        'learning_rate': [0.03, 0.1],
        'depth': [2, 4, 6, 8],
        'l2_leaf_reg': [0.2, 0.5, 1, 3]}model.grid_search(grid, train_dataset)

性能赋值

我们现在已经完成了模型的训练,我们最终可以对测试数据进行评估了。

让我们看看模型的表现。

pred = model.predict(X_test)
rmse = (np.sqrt(mean_squared_error(y_test, pred)))
r2 = r2_score(y_test, pred)print(“Testing performance”)
print(‘RMSE: {:.2f}’.format(rmse))
print(‘R2: {:.2f}’.format(r2))

测试性能

如上所述,我们在测试集上实现了 90%的 R *方,考虑到最小特征工程,这是非常好的。

在推理方面,CatBoost 还提供了提取可变重要性图的可能性。因此,可变重要性图可以揭示人眼可能看不到的潜在数据结构。

在本例中,我们按升序对数组进行排序,并绘制一个特征的水*条形图,其中最不重要的特征位于底部,最重要的特征位于顶部。**

**sorted_feature_importance = model.feature_importances_.argsort()
plt.barh(boston.feature_names[sorted_feature_importance], 
        model.feature_importances_[sorted_feature_importance], 
        color='turquoise')
plt.xlabel("CatBoost Feature Importance")**

可变重要性图

根据图示,上面列出的这些特征为预测波士顿房价提供了有价值的信息。最有影响的变量是每所住宅的*均房间数(RM)和较低地位人口的百分比(LSTAT)。

沙普利附加解释(SHAP)图也是一种解释我们的机器学习模型的输出的方便工具,通过为给定预测的每个特征分配重要性值。SHAP 值允许解释驱动我们的目标变量预测的特征。

**explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)shap.summary_plot(shap_values, X_test, feature_names = boston.feature_names[sorted_feature_importance])**

SHAP 图

在 SHAP 图中,要素根据其*均绝对 SHAP 进行分级,颜色代表特征值(红色高,蓝色低)。SHAP 值越高,预测者的属性越大。换句话说,SHAP 值代表预测者对模型输出变化的责任,即预测波士顿房价。这揭示了,例如,较大的 RM 与上升的房价相关,而较高的 LSTAT 与下降的房价相关,这也是直觉上有意义的。

如果你想了解更多关于 SHAP 情节和 CatBoost,你可以在这里找到文档。

最终注释

因此,在本教程中,我们使用 Python 成功构建了一个 CatBoost 回归器,它能够预测波士顿房价 90%的可变性,*均误差为 2,830 美元。此外,我们还研究了可变重要性图以及与波士顿房价预测相关的特征。如果您想了解更多,我建议您也尝试其他数据集,并深入研究定制和评估您的模型的许多方法。

感谢阅读!

来源

[1] Yandex,公司简介,(2020),https://yandex.com/company/

[2] Catboost,Catboost 概述(2017),https://catboost.ai/

[3]谷歌趋势(2021),https://trends.google.com/trends/explore?date = 2017-04-01% 202021-02-18&q = CatBoost,XGBoost

[4] A. Bajaj,EDA & Boston House Cost Prediction(2019),https://medium . com/@ akashbajaj 0149/EDA-Boston-House-Cost-Prediction-5 fc 1 BD 662673

记录 SQL Server 中的错误,否则这些错误会被忽略(+示例)

原文:https://towardsdatascience.com/catch-sql-server-errors-that-would-otherwise-go-unnoticed-examples-85f35d557fff?source=collection_archive---------25-----------------------

检测、分析和记录我的查询中的错误

检测错误..(图片由像素上的伊戈尔拍摄)

当查询执行失败时,我可以看到哪里出错并调整我的查询。通常像存储过程这样的数据库对象会被 API 或其他存储过程调用。当出现问题时,没有人会注意到,通常几个小时、几天或几周后,当客户打电话给你说一些数据丢失时,你会注意到。

理想情况下,您希望尽快知道数据库出错的原因、时间和位置,以便可以修复查询。本文向您展示了一种监视数据库进程和检测何时出错的简单方法。

准备

SQL Server Management Studio 在捕捉大量语法错误方面做得很好。尽管有时错误是不可预料的。考虑依赖用户输入或使用动态 SQL 创建查询的情况。我将使用一个简单的查询来说明意外的用户输入;一个完全不必要的存储过程,允许用户指定一个表。然后,SP 将检索该表记录计数。

对于不熟悉动态 SQL 的人:在这个 SP 中,我们可以确定查询的内容。我们声明一个名为@query 的字符串,它包含我们想要执行的查询。用户可以将他们的模式名和表名传递给存储过程。然后,SP 将创建查询并执行它。

让我们测试一下我们的 SP 是否真的工作:

计算 sys.columns 表中的记录数

太好了,成功了!但是当我们传递一个不存在的模式或表时会发生什么呢?

试图计算一个不存在的模式中的记录数

问题是我们的剧本失败了,被删掉了。当我坐在笔记本电脑前执行这个脚本时,我看到并理解了错误,因此我可以做些什么。但是想象一下,如果这个 SP 被一个或多个 API 调用。这里没有用户参与,所以错误不会被注意到。在我们的脚本中检测这些类型的错误是非常重要的,所以让我们来看看我们将如何准确地做到这一点。

检测和记录错误

使用 Try-Catch 块很容易检测错误;大多数程序员都很熟悉它们。SQL Server 中一个不太为人所知的特性是,如果代码失败,您还可以获得各种信息。在下面的 SP 中,我们以ERROR_MESSAGE()为例获取更多信息。

再次使用一些错误的参数EXEC dbo.tablecounter 'sys', 'columns';执行这个 SP 会产生下面的输出。请注意,我们还获得了发生错误的 SP 的名称(obj_name)。

记录您的错误

我们有工具来创建一个非常好的函数来记录我们所有的错误。让我们从创建一个存储所有错误信息的表开始。

现在,我们修改前面的存储过程,以便在出现错误时记录错误。它还会打印出一条消息,以便我们进行测试:

现在我们有了一个表,我们可以监视该表来查看在我们实现了错误日志记录功能的数据库中发生的所有错误。让我们用下面的查询试几次。第一个查询将会成功;其余的都会失败。

EXEC dbo.tablecounter 'sys', 'columns';
EXEC dbo.tablecounter 'sys', 'taaables';
EXEC dbo.tablecounter 'nope', 'columns';
EXEC dbo.tablecounter null, 'columns';Select * 
FROM dbo.ErrorLog;

执行这些过程将在我们的 ErrorLog 表中产生以下记录。

我们的误差记录表

如您所见,您可以通过 ErrorDateTime 和 my the eminent(userName)来过滤该表。您还可以使用 ObjectName 回溯代码(我们的错误发生在“tablecounter”存储过程中)。还要注意,在我们的新脚本中,我们有可能引发错误。如果没有设置模式名或表名,我们选择让脚本失败。然后,我们可以指定自己的 ErrorMessage(参见 ErrorLog 表中的记录#3)。

一旦我们实现了这个表,可能性是无限的:

  1. 我们可以创建一个监视器,它每分钟刷新一次,并查询这个表中最后一分钟的记录
  2. 向跟踪其状态的错误日志中添加新表(0 =新,1 =已解决等)
  3. 我们可以使用触发器来扩展更多的功能,例如将消息推入消息队列。您可以在消息队列上连接多个服务(一旦记录了错误,就会收到一封电子邮件!)

结论

在代码中需要的地方应用 Try-Catch 块,但是不要忘记记录错误。这些提供了有价值的信息,有助于找出那些不被注意的 bug。狩猎愉快!

—迈克

页(page 的缩写)学生:比如我正在做的事情?跟着我!

分类交叉熵和 SoftMax 回归

原文:https://towardsdatascience.com/categorical-cross-entropy-and-softmax-regression-780e8a2c5e8c?source=collection_archive---------28-----------------------

实践教程

想知道如何为多类问题实现一个简单的基线模型吗?这里有一个例子(包括代码)

学习由尼克·杨森CC BY-SA 3.0阿尔法股票图片

虽然它的根源是统计学,但逻辑回归是解决机器学习中二元分类问题的一种相当标准的方法,也是迄今为止现实生活应用中此类分类任务最常用的算法。然而,通过设计,它只能处理二元分类问题,即待分类的物体属于两类中的一类的问题(例如,故障与否、通过或失败、生病或健康等)。但是如果你有两个以上的课呢?SoftMax 回归来了!

SoftMax 回归是二元逻辑回归的一个相对简单的扩展(如果需要的话,参见本文后的快速回顾),用于多类问题。而后者依赖于所谓的二元交叉熵的最小化

前者依赖于其推广的最小化:分类交叉熵

其中 1 是一个指标函数(即:如果例子属于类 k1 = 1 ,否则为 0 )。但是这个数学术语是什么?我如何从两个班级变成任意数量的班级?更重要的是,如何训练我的模型比简单的梯度下降更有效?我们将在下面解决这些问题,并提供一个简单的 Python 实现(我们将实际实现它,而不是依赖 scikit-像许多其他帖子一样学习……)。但首先让我们简单介绍一下 SoftMax 函数!

SoftMax 函数的(简要)介绍

SoftMax 函数是普遍存在的逻辑函数的推广。它被定义为

其中指数函数被逐元素地应用于输入向量***【z】的每个条目。归一化确保输出向量【σ(z)***的分量之和等于 1。至于经典的逻辑函数,它的所有输出都在 0 和 1 之间,这使得它成为模拟多类问题中概率分布的自然候选。它继承了逻辑函数的大部分属性,对我们来说最重要的属性是

其中,如果 i = k ,克罗内克符号 δ 等于 1,否则等于 0。

SoftMax 回归的分类交叉熵的性质

给定一个示例 x ,softmax 函数可用于模拟其属于类别 y = k 的概率,如下所示

其中 W 是我们模型的参数。因此,我们的目标是找到参数 W ,使得模拟的概率函数尽可能接*真实的概率函数。至于二进制逻辑回归,这将涉及到利用取幂技巧使似然函数最大化(或者等效地使负对数似然性最小化)。因为从我们的概率分布的定义到分类交叉熵紧密跟随我们对二元逻辑回归所做的,因此如果你需要快速刷新,我推荐你到相应的帖子。

凸函数

我们的目标是找到最小化分类交叉熵的权重矩阵 W。然而,在最一般的情况下,一个函数可能有多个极小值,寻找全局极小值被认为是一个困难的问题。尽管如此,可以证明最小化 SoftMax 回归的分类交叉熵是一个凸问题,因此,任何最小值都是全局的!

让我们推导目标函数的梯度。为了便于我们的推导和后续实现,考虑分类交叉熵的矢量化版本

其中, X 的每一行都是我们的训练示例之一, Y 是独热编码标签向量,并且日志是按元素方式应用的。最后,⊙表示哈达玛乘积,即两个矩阵的逐元素乘法。使用矩阵计算的一些元素,我们的损失函数相对于 W 的梯度由下式给出

再一次继续这种推导会得出我们问题的结论。同样,它非常接*本文后中提出的逻辑回归推导。从那里,很容易看出它的最小特征值大于或等于零。因此,它是对称正半定的,我们的优化问题是凸的!

过度参数化

在继续讨论如何找到最优解和代码本身之前,让我们强调一下 SoftMax 回归的一个特殊属性:它是过度参数化!模型的一些参数是多余的。从 P(y=i|x) 的定义出发,可以看出,从每个权重向量 w 中减去任意一个向量 v 并不会改变模型的输出(留给读者一个练习,我首先是个老师!).权重矩阵 W 因此包含一个解决问题不需要的额外权重向量。如果不考虑这种冗余,我们的最小化问题将允许无限数量的同样可能的最优解。不失一般性,我们因此可以假设例如与最后一个类相关联的权重向量 w 等于零。这样做使我们能够摆脱这个过度参数化的问题。

怎么最小化?

与线性回归不同,SoftMax 回归不存在封闭形式的解决方案。然而,分类交叉熵在当前情况下是凸函数,任何来自凸优化的技术仍然保证找到全局最优。在这篇文章的其余部分,我们将使用梯度下降的稍微改进版本,即具有(自适应)最佳学习速率的梯度下降,来说明 SoftMax 回归的实现。

最优学习率梯度下降

在机器学习中,梯度下降的变化是模型训练的主力。在该框架中,权重矩阵 W 按照简单规则迭代更新

直到达到收敛。这里α被称为学习速率或步长。使用恒定的学习速率是很常见的,但是如何选择呢?简单的数学表明分类交叉熵函数的 Lipschitz 常数(使用 Frobenius 范数)为

其中 k 是所研究问题中不同类的数量,因此“最优”学习速率大约为

较大的学习速率会导致计算发散。一个小得多的值会产生收敛,但代价是大量的迭代。或者,可以在每次迭代中使用(不精确)线搜索,以获得自适应/最佳学习速率。下面是相应算法的一个简单 Python/SciPy 实现,使用 Brent 的方法来寻找准最优学习率。假设您已经熟悉 Python,代码应该是不言自明的。

虽然它确保了目标函数在每一步都会减少,但这种实现方式决不是优化的。通过稍微重构代码可以获得一些性能上的提升,尽管会牺牲可读性(我认为在这样一篇介绍性的文章中可读性更重要)。此外,可以使用更有效的优化技术,例如动量梯度下降、牛顿-拉夫森方法、随机梯度下降、ADAM 等。然而,这种梯度下降的变体对于编码来说足够简单并且相当有效。因此,我建议坚持把它作为一个起点,一旦你适应了,就继续使用更高级的优化程序。

超越普通的 SoftMax 回归

像它的二元对应物(即逻辑回归)一样,SoftMax 回归是一个相当灵活的分类任务框架。因此,多年来已经提出了许多变体来克服它的一些限制。

处理非线性可分离的类

通过构造,SoftMax 回归是一个线性分类器。就像线性回归可以扩展到建模非线性关系一样,logistic 和 SoftMax 回归也可以扩展到对非线性可分的点进行分类。然而,这样做可能需要专业知识、对数据属性的良好理解以及特征工程(与其说是精确的科学,不如说是一门手艺)。

不*衡的阶级分布

使用交叉熵时隐含的事实是,我们的训练数据集中每个类的流行程度大致相同。然而,现实生活中有许多情况并非如此。在二元分类中用于不*衡分类的相同技巧可以适用于多类问题,特别是对成本敏感的训练(更多细节见本帖)。

正规化

在机器学习中,处理以大量特征为特征的数据是相当常见的。然而,并非所有这些特征都可以为预测目的提供信息。以 MNIST 数据集上的数字分类为例,这些特征是影像的 784 个不同像素。

来自 MNIST 数据集的手写数字的随机子集(图片由作者提供)。

然而,这些图像是标准化的,最外面的像素为所考虑的任务提供很少或没有信息。在这种情况下,有可能正则化优化问题,使得与无信息特征相关联的系数被设置为零。这个问题最简单的这种促进稀疏性的正则化版本如下

其中*CCE(w)*是分类交叉熵的简写符号, W 的ℓ₁-norm 是其条目的绝对值之和。参数λ控制交叉熵函数的最小化和权重矩阵的期望稀疏度之间的权衡。解决这个新的优化问题只需要对提供的代码做一些小的修改。

结论

在过去的十年中,深度神经网络获得了很大的吸引力,似乎可以在任何地方和任何事情上使用。虽然在某些领域(例如计算机视觉)这可能是真的,但许多更经典的领域仍然依赖于更简单但成熟的技术(例如在制造业)。从数学和计算的角度来看,由于其简单性和灵活性,SoftMax 回归是迄今为止现实生活应用中最常用的多类分类技术。在机器学习中,尽管深度网络具有优势,但它仍然是一个优秀的基线模型,用于评估通过转向更复杂的神经网络模型实际上获得了什么(即,它真的值得吗?).

我希望您现在对什么是 SoftMax 回归、它是如何工作的以及它是如何实现的有了更好的理解。像往常一样,有很多我们没有涉及的内容(例如,模型的统计解释,如何超越简单的准确性度量等),但互联网(以及针对特定问题的数据科学)充满了优秀的资源!去看看吧!此外,不要犹豫,自己推导这里给出的所有数学结果,并使用提供的代码!请告诉我这些内容是否对您有用,或者您是否发现了任何错别字:]

*想阅读更多此类内容吗?*查看我其他关于低秩结构和数据驱动建模 的文章或者干脆我的 机器学习基础知识

分类数据、Jaccard 系数和多重处理

原文:https://towardsdatascience.com/categorical-data-jaccards-coefficient-and-multiprocessing-b4a7bd5d90f6?source=collection_archive---------18-----------------------

威廉·克劳斯在 Unsplash 上的照片

佛罗里达州的机场比海得拉巴的机场更靠*底特律机场,我们知道这一点是因为我们使用纬度和经度来测量距离(海得拉巴是印度的一个大城市)。但是,我们如何说一个购物篮的内容更接*另一个呢?或者一个森林和另一个森林在生活的动物方面更相似?我们可以将这些视为集合之间的比较,并使用 Jaccard 系数(我们将互换使用系数和相似性得分)来度量它们之间的相似性(或不相似性)。对于大型数据集,这可能是一项很大的任务,因此我们可以使用并行处理在较短的时间内完成它。见上的完整笔记本kaggle。

搭建舞台的快速示例

因此,当比较两个集合(可以是一个数组、一个序列,甚至是一个二进制值的向量)时,分子是集合之间共享的元素数,分母是两个集合中的元素数。在我们的例子中,分母是任一集合的大小,所以我们也可以说这个相似性得分是共享元素的数量除以可以共享的元素的数量。

让我们看一个简单的例子:

from sklearn.metrics import jaccard_score
from scipy.spatial.distance import jaccardx = [[1,1,1],[1,0,1],[0,0,0]]print(x)
[[1, 1, 1], [1, 0, 1], [0, 0, 0]]jaccard(x[0],x[1])
0.33jaccard_score(x[0],x[1])
0.66

数组 x 有三行。第一行是我们希望比较的观察值。请注意 Jaccard 函数是如何返回前两行之间不共享的元素数量的。jaccard_score 函数返回相反的结果:它是前两行之间共享的元素数量。一个表示不同,一个表示相似。我个人更喜欢 scikit-learn 中提供的相似性评分,但重要的是你要意识到其中的区别。

(还要注意,有些人认为元素 0 根本不应该包含在计算中。在某些情况下,这是有意义的。)

既然我们已经在一个简单的案例中看到了这个指标,那么让我们将它应用到一个更大的数据集。

用 Jaccard 和并行处理测量距离

import numpy as np
import pandas as pdx0 = np.random.choice([0, 1], size=(100000,100), p=[4./5, 1./5])
x1 = np.random.choice([0, 1], size=(100000,100), p=[1./3, 2./3])
x2 = np.random.choice([0, 1], size=(100000,100), p=[1./2, 1./2])colnames = ['x_'+str(i) for i in range(0,100)]X = pd.DataFrame(data = np.stack([x0,x1,x2]).reshape(300000,100))
X.columns = colnamestarget = np.ones(100).astype(int)

我们的目标是所有特征都设置为 1 的一个观察。想象一下,一个购物篮购买了网上商店的所有商品,你想看看哪些观察结果最接*它。这主要是为了示例的目的,但是您可以看到这如何扩展到其他用例。

使用二进制值数据(1 和 0)创建了一个巨大的 300k 观察值阵列,以代表指标特征或虚拟变量。第一个三分之一是 1 的概率是 1/5,第二个三分之一是 2/3,最后一个三分之一是 1/2。让我们看看有多少观察结果与我们的目标重叠,重叠了多少!但是首先,让我们利用多重处理包并创建一个分部函数来并行比较几个观察值和目标值(这是一个巨大的时间和内存节省)。

from functools import partial
import multiprocessing as mppartial_jaccard = partial(jaccard_score, target)with mp.Pool() as pool:
    results = pool.map(partial_jaccard, [row for row in X.values])

上面的代码花了差不多一分钟的时间(大约 50 秒)。这是经过多重处理和对 100 个特征进行 30 万次观察后得出的结果。您可能会遇到包含更多要素和更多观测值的数据集。试图在一个循环中完成上述任务导致我的电脑完全崩溃(蓝屏/皱眉头),但如果你够勇敢,那么你应该尝试一个数据子集,看看需要多长时间。

下面是结果。您将看到,对于前三分之一的数据(有 1/5 概率为 1 的数据),您可以看到有一个 Jaccard 相似性得分为 0.2 (20%)的峰值。其他峰值也是如此。这证实了比较是与我们的多重处理和部分功能一起工作的。

结论

当您有二进制数据(如指标特征或虚拟变量的情况)并且您想要在您的观察值之间创建某种类型的距离度量时,请考虑这个 Jaccard 的系数/相似性得分。这相当直观,但是需要一点额外的工作来对大量数据进行测量。考虑将此指标用于仪表板或报告,如果您考虑将其用于聚类任务,请记住,进行成对比较对于您的计算机来说是一项巨大的任务,您应该考虑制作聚类中心并与之进行比较。

参考文献

https://en.wikipedia.org/wiki/Jaccard_index https://scikit-learn.org/stable/modules/generated/sklearn.metrics.jaccard_score.html https://github.com/caseywhorton/medium-blog-code

BTS 歌曲特征分类:一个多维聚类案例

原文:https://towardsdatascience.com/categorizing-bts-songs-features-a-multi-dimensional-clustering-case-ba2a0c07174d?source=collection_archive---------31-----------------------

由 C D-X 在 Unsplash 上拍摄的照片

使用 Spotify 音频功能对 BTS 歌曲进行聚类,使用 Python 中的 PCA 和 t-SNE 对聚类进行可视化

生活在 2021 年的年轻人对 BTS 一无所知几乎是不可能的。至少,你会听说过他们的名字,甚至他们的热门歌曲。我开始注意到他们的歌曲后,“男孩与爱”击中,并一直在享受其他热门歌曲,如“炸丨药”,以及最*的“黄油”。

这里我分析一下 BTS 歌曲的音频特征。我正在使用 Spotify 和音频功能,根据这些属性对歌曲进行聚类,希望找到其他与我喜欢的歌曲具有类似功能的 BTS 歌曲,如《炸丨药》和《黄油》。

注意:完整的源代码和收集的数据可以在 this Github 中找到

数据收集

为了收集数据,我使用了 Spotify 开发者 API 。您可以注册您自己和您的应用程序,并从您的代码中获取用于 API 调用的 API 令牌。然后可以使用 Python 中的spotipy包从 API 中检索数据。

我之前在这里分享了更多关于从 Spotify API 获取数据的细节,或者你可以在这里查看具体的 Python 笔记本。下面是我利用 Spotify API 调用并最终收集 BTS 歌曲列表及其功能的数据帧的方法。

使用 Spotify API 获取艺术家每首歌曲的音频特征(图片由作者提供)

下面是收集的数据帧的快照。关于数据收集过程的完整代码,可以去本笔记本。

音频特征的样本数据帧(图片由作者提供)

了解功能

Spotify API 为每首曲目提供了 11 种音频功能,从描述性指标(速度、音调、模式),到置信度指标(声音、语速、乐器感、响度),以及感知性指标(活力、能量、可舞性、效价)。

与任何其他探索性数据分析一样,我们从检查数据集中每个要素的汇总统计数据开始。从直方图分布中,我们可以看到 BTS 歌曲的更高的可跳舞性、能量和响度的趋势。这是意料之中的,因为舞蹈编排是韩国流行乐队不可或缺的一部分,因此他们倾向于发布适合“点”舞的关键乐观歌曲。

每个功能的价值分布(图片由作者提供)

检查该数据集中要素之间的相互作用时,我们会查看皮尔逊相关系数。响度、能量、效价和可跳性之间存在正相关。另一方面,响度与声学之间存在负相关关系;能量转化为声音。响度高的歌曲往往具有高的能量、效价和可舞性低的声音

音频特征中变量之间的相关性(图片由作者提供)

采样响度和能量最高的歌曲,部分歌曲在响度和能量排行榜上重叠: 荷尔蒙 Sensou —日语 Ver。 和不是今天—日文版。我在这篇文章中添加了这些歌曲的 Spotify 链接,是的,这是一首非常有活力的嘻哈歌曲:)

最高音量和能量的 BTS 歌曲(图片由作者提供)

使聚集

引用geeksforgeeks.org的话,聚类的任务是将总体或数据点分成几个组,使得同一组中的数据点与同一组中的其他数据点更相似,而与其他组中的数据点不相似。我们可以利用这一点将 BTS 歌曲分成几个组,即充满活力的嘻哈歌曲、柔和的原声歌曲等。

最广泛使用的聚类算法之一是 k-means ,它涉及到将样本分配给聚类,以最小化每个聚类内的方差。在 k-means 中,您将有 k 个质心点,数据点将根据到这些质心点的距离进行分组,到距离最小的点。

k-means 聚类的第一步是找到 k 的最佳数量,这可以使用肘方法来完成。在这里,我们计算 k 的每个潜在数量的失真(欧几里德距离)或惯性(距离的*方和)。然后我们将它们可视化,并选择失真/惯性开始线性下降的点。从这个数据来看,似乎最优 k 是 4 。点击阅读更多关于肘法的内容。

from sklearn.cluster import KMeans# Calculate sum of squared distances
ssd = []
K = range(1,10)
for k in K:
    km = KMeans(n_clusters=k)
    km = km.fit(df_cluster)
    ssd.append(km.inertia_)# Plot sum of squared distances / elbow method
plt.figure(figsize=(10,6))
plt.plot(K, ssd, 'bx-')
plt.xlabel('k')
plt.ylabel('ssd')
plt.title('Elbow Method For Optimal k')
plt.show()

肘法(图片由作者提供)

使用来自 sci-kit-learn 库中的 KMeans 函数,我们可以获得数据集中每首 BTS 歌曲的聚类。下面是聚类结果。

kmeans = KMeans(n_clusters=4)
model = kmeans.fit(df_cluster)pred = model.labels_
df_cluster['cluster'] = pred
  • 第 0 类:欢快的歌曲,可跳性和效价高,响度很大
  • 集群 1:强有力的歌曲,由高能量、响度、节奏、活力来指示
  • 第二类:典型的流行歌曲,活跃度和声音都很高
  • 第三类:冷歌,具有很高的听觉性、舞蹈性和节奏

每个分类中 50%属性的热图(图片由作者提供)

我们通常通过绘制数据集和要素来验证聚类结果,并将聚类设置为绘图中的色调。然而,因为我们要处理 11 个特性,所以几乎不可能在同一个图中绘制。为了解决这个问题,我们可以使用降维技术。

降维

当处理具有大量要素的大型数据集时,会出现复杂情况,因为处理会计算量很大,需要处理多个测量值(即多重共线性问题)并且难以可视化数据。维度缩减技术有助于减少数据集中的要素数量**,而不必丢失太多信息并保持(或提高)模型的性能。这里使用的一些流行技术是主成分分析(PCA)和 t-分布随机邻居嵌入(t-SNE)**

主成分分析

PCA 通过从现有的一大组变量中提取一组新的变量(称为主成分)来帮助我们降维。这些主成分实际上是原始变量的线性组合。你可以在这里阅读更多关于 PCA 的内容。

from sklearn.decomposition import PCApca = PCA(n_components=3)
pca_result = pca.fit_transform(df_pca.values)
df_pca['pca-one'] = pca_result[:,0]
df_pca['pca-two'] = pca_result[:,1] 
df_pca['pca-three'] = pca_result[:,2]df_pca['cluster'] = pred
df_pca

理想情况下,PCA 中主成分的数量足够小,以便能够可视化(即≤ 4 个成分),但足够大,以便解释数据集中的大多数差异(即> 70%)。我用 3 个组件进行测试,结果发现它们能够解释数据集中 99.9%的差异。第一个成分能够解释 97.5%的差异,第二个成分增加了 1.9%,第三个成分增加了 0.5%。

主成分分析中的解释方差比

在这种情况下,我们使用主成分分析来可视化我们的 K 均值聚类是否相应地分离了 BTS 歌曲。这里我使用的是 3D 图,我们可以清楚地看到聚类 0、聚类 1、聚类 2 和聚类 3 之间的分离(以色调显示);主要在 x 轴上。

ax = plt.figure(figsize=(16,10)).gca(projection='3d')
sctt = ax.scatter(
    xs = df_pca["pca-one"], 
    ys = df_pca["pca-two"], 
    zs = df_pca["pca-three"], 
    c = df_pca["cluster"]
)ax.set_xlabel('pca-one')
ax.set_ylabel('pca-two')
ax.set_zlabel('pca-three')plt.title("3D PCA Visualization with 3 Components", fontsize=16)cb = plt.colorbar(sctt, ax=ax, shrink=0.3, aspect=4, pad=0.1)
cb.set_ticks([0,1,2,3])plt.show()

BTS 歌曲音频特征的 3D PCA 可视化(图片由作者提供)

t 分布随机邻居嵌入(t-SNE)

如果 PCA 算法使用线性函数来提取新的特征,t-SNE 算法提供了一种非线性方式来解决这个问题。它计算点在高维空间的相似概率并计算点在对应低维空间的相似概率,最小化这种成对分布。你可以在这里阅读更多关于 t-SNE 的信息。

from sklearn.manifold import TSNEtsne = TSNE(n_components=2, verbose=1, perplexity=40, n_iter=300)
tsne_results = tsne.fit_transform(df_tsne)df_tsne['cluster'] = pred
df_tsne

使用来自 sklearn 的 TSNE 类,我们可以开发具有可配置数量的组件、困惑和迭代的 t-SNE 模型。为了评估要使用的理想参数,我们可以检查 KL 散度值——目标是尽可能接* 0 。如果 KL 散度随着迭代的增加没有太大改善,我们可以停止迭代。

评估 t-SNE 中 KL 散度

绘制 t-SNE 结果将有助于我们理解早期聚类的分离以及模式是如何保持的。在这里,我们可以看到 t-SNE 2 组分变量上的聚类之间的明显差异,肯定了聚类结果。

df_tsne['tsne-2d-one'] = tsne_results[:,0]
df_tsne['tsne-2d-two'] = tsne_results[:,1]
plt.figure(figsize=(16,10))
sns.scatterplot(
    x="tsne-2d-one", y="tsne-2d-two",
    hue="cluster",
    palette=sns.color_palette("hls", 4),
    data=df_tsne,
    legend="full",
    alpha=0.3
)plt.title("t-SNE 2D Visualization", fontsize=16)

t-SNE 2D 可视化的 BTS 歌曲的音频特征(图片由作者提供)

解释结果

既然我们对之前在我们的聚类中完成的分离很有信心,我们可以继续关注聚类结果。看了一下结果,才知道我喜欢的几首 BTS 的歌(炸丨药,黄油,有 Luv 的男孩)都在同一个集群上,就是集群 0

回顾 PCA 图,在这里我们可以看到歌曲“炸丨药”和“黄油”彼此放置得非常接*,显示出较高的相似性。因此,考虑到潜在的相似性,也许接下来我可以听“我错了吗”或“水晶雪”?

聚类 0 的 PCA 组件 1 和 2 可视化(作者提供的图片)

另一方面,与 PCA 不同,t-SNE 图可视化中的轴距离可能不表示相似性。阅读这篇文章了解更多详情。

结束语

聚类是最强大的分析技术之一,因为它允许我们发现数据中的模式和组。然而,当处理高维特征时,可能难以理解和解释结果。使用降维的可视化将对此有所帮助,因为它保留了数据点内部的关键信息。除了可视化之外,降维技术还可以用作数据建模中的预处理步骤,以减少模型训练时间。

此分析的完整代码可在此处访问。

对用户上传的文档进行分类

原文:https://towardsdatascience.com/categorizing-user-uploaded-documents-2d3159fb1104?source=collection_archive---------26-----------------------

从数据中获得的见解如何被用来帮助构建分类法,以及我们为用户上传的文档分配类别的方法。

Scribd 向我们的用户提供各种发布者和用户上传的内容,虽然发布者的内容富含元数据,但用户上传的内容通常不是。用户上传的文档具有不同的主题和内容类型,这使得将它们链接在一起具有挑战性。连接内容的一种方式是通过分类法,分类法是广泛应用于各种领域的一种重要的结构化信息。在这个系列中,我们已经分享了我们如何识别文档类型和从文档中提取信息,这篇文章将讨论如何利用数据的洞察力来帮助建立分类法,以及我们为用户上传的文档分配类别的方法。

构建分类

统一分类法是一个具有两层的树状结构,它是通过结合我们的主题专家(SME)对图书行业主题词( BISAC 类别)的知识和数据驱动的见解而设计的。我们使用用户阅读模式来寻找有助于丰富我们的统一分类法的主题。

数据驱动的洞察力

10 多年来,用户一直在与 Scribd 内容互动,随着时间的推移,建立了阅读模式。我们利用这些阅读模式来创建文档的密集向量表示,类似于文本中的 word2vec。

图 1: 我们方法的示意图:阅读序列用于为用户上传的文档创建矢量表示。所示的向量尺寸仅仅是说明性的(图片由作者提供)。

对于这项工作,我们只关注用户上传的文档和一种类型的交互(阅读时间最短)。选择嵌入维度(和其他超参数)来优化命中率@20 ( Caselles-Dupré,et al 2018 ),增加嵌入的语义紧密度。

现在我们有了嵌入,我们想用它们来查找具有相似主题和题目的文档组。找到这些组将有助于我们确定应该添加到分类法中的类别。

与我们嵌入的原始高维空间相比,维数减少允许在减少的空间中更有效和准确地发现密集的文档聚类。我们使用 t-SNE 算法来降低嵌入的维数。t-SNE 有一个非线性的方法,可以捕捉点之间的较小关系,以及数据的全局结构。我们使用了 t-SNE(基于快速傅立叶变换加速插值的 t-SNE)——FIt-SNE的实现,这种实现很灵活,不会为了速度而牺牲精度。

最后,我们通过使用 HDBSCAN 对减少的嵌入进行聚类来对用户上传的文档进行分组。HDBSCAN 根据密度分布将数据点分成簇。它还具有检测噪声的功能,噪声是指距离最*的检测到的聚类太远而不属于它的点,并且缺乏形成自己的聚类的密度。

图 2 显示了用户上传的文档及其组的 2D 表示。我们注意到并在图中强调的第一件事是,主要群体通常用语言来表示。不足为奇的是,用户倾向于阅读大多数单一语言的内容。

图 2: 使用 t-SNE 和 HDBSCAN 的嵌入的初始 2D 表示。每个彩色组代表 HDBSCAN 发现的一个星团。散布的灰点被识别为噪声(图片由作者提供)。

我们开发了一种技术,将上面的组进一步分成语义更紧密的更小的集群。最终的集群可以在图 3 中看到。

图 3: 进一步分割每个聚类后嵌入的最终 2D 表示。每个彩色组代表 HDBSCAN 为特定集群找到的一个子集群。散布的灰点被识别为噪声(图片由作者提供)。

在我们得到图 3 所示的集群和子集群之后,对英语子集群进行了检查,以便识别它们的主要主题和主题。这项调查导致分类中加入了其他类别,如菲律宾法律、学习辅助和考试准备以及教学方法和材料,从而使分类更广泛地涵盖不同的内容类型,并且浏览这些内容更加简单。

将文档分类

**图 4:**Scribd 的多组分管道图。分类是图中突出显示的下游任务之一。

现在我们有了分类法,是时候将文档分类了。我们的方法利用了本系列第二部分中讨论的提取的关键短语和实体。图 5 说明了我们的模型是如何工作的:我们训练了一个监督模型,使用关键短语、实体和文本将被识别为大量文本的文档(参见第一部分)分类。

图 5: 对文档进行分类的模型架构(图片由作者提供)。

来自数据的更多见解

在模型的第一次迭代中,我们有一个由我们的专家收集的训练数据集,以符合每个类别的定义。不足为奇的是,在对生产中的未知数据测试模型时,我们意识到对于某些类别,训练集并不能完全代表生产中适合它们的文档类型。因此,该模型无法用初始给定的训练集进行概括。例如,在初始训练集中,大多数关于美国以外国家的文档都是关于旅行的文档。这意味着该模型了解到,每当文档提到其他国家时,该文档很可能是关于旅行的。出于这个原因,例如,关于南美的商业文档将被放置在模型的 travel 下。

我们应用了一种有时被称为主动学习的技术,用缺失的例子来补充我们的训练集。按照这种技术(图 6),模型被应用于随机的文档样本,结果由我们的 SME 进行分析。

图 6: 用于提高模型性能的主动学习过程(图片由作者提供)。

这个迭代过程有两个结果:通过用大量的训练例子重新训练模型来改进分类性能,以及在我们识别出很大一部分文档符合这个特定类别之后添加一个新的类别,

附加实验

在整个项目中,进行了几个实验来探索用户交互集群的全部潜力。这里我们将展示一个令人兴奋的例子。

给集群命名

如上所述,一般来说,图 3 所示的每个子集群都是语义紧密的,这意味着属于一个子集群的文档通常是关于一个(或几个)主题/主题的。

将主题与子集群相关联的一种方式需要主题专家手动检查每个子集群中的文档,并为每个子集群提出最重要的主题。然而,这种方法不仅耗时,而且不能随着模型的新迭代和可能增加的集群数量而扩展。尝试使这成为一个更加自动化和灵活的过程是非常重要的。

我们试验了一个非常有前途的两步方法,自动将主题分配给子集群。在这种方法中,我们利用从第二部分中描述的文本中提取的信息和零射击主题分类(更多信息在此):

  • 步骤 1-通过聚类子集群的文档提取信息来找到子集群的最有代表性的关键短语。

图 7: 步骤 1 的图解(图片由作者提供)。

  • 步骤 2-使用步骤 1 的结果和零触发主题分类来为每个子聚类找到最高排名的主题。

图 8: 步骤 2 的图示。具有最高排名主题的条形图是这种方法对于包含关于几部文学作品的文章(由作者提供的图像)的子集群的结果。

从图 8 中可以看出,由文学作品的文章组成的集群具有最高排名的主题文学评论,显示了这种方法自动为用户交互集群命名的潜力。

结论

在对文档进行分类的过程中,有两点很重要:

  • 高质量的标记数据 —我们发现干净一致的标记数据比超参数调整对模型更重要。然而,在我们多样化的语料库中获取足够多的符合类别的文档是一个挑战。使用了几种技术来提高模型在不可见数据上的性能。其中,主动学习被证明是收集额外训练样本和保证训练集中所需粒度的重要方法。
  • 注释对齐 —高质量数据和模型性能都与注释过程相关联(参见此处的更多)。当多个注释者参与数据收集和评估时,每个类别定义的一致性对于模型的精确训练和评估至关重要。这在文本分类中甚至更加重要,因为将类别/主题与文本相关联可能是一项非常主观的任务,尤其是当我们处理单标签分类问题时。

这个项目是理解我们的用户上传文档的一个重要里程碑:对文档进行分类使用户能够从我们的统一分类法中按类别浏览文档。此外,我们现在有能力理解每个用户感兴趣并与之交互的类别。将用户兴趣与业务指标相结合有助于推动创新和出乎意料的产品决策,并丰富可发现性和推荐。

后续步骤

  • 使用数据驱动的方法改进分类:

接下来,我们如何确保新上传的文档包含在我们的分类中?

使用数据驱动的方法来构建分类法回答了这些问题,并且与手动创建的分类法相比,保证了更大的灵活性、全面性和特异性。随着新内容上传到我们的*台并被用户阅读,新的用户互动集群将形成,并帮助我们识别最*的用户兴趣。例如,在疫情期间,用户开始上传与新冠肺炎有关的文件。例如,在 2021 年对文档进行聚类产生了与新冠肺炎相关的附加聚类,这在疫情之前是不存在的。这种方法将帮助我们建立一个不太严格的分类法,一个反映 Scribd 大量内容的分类法,并且从长远来看很容易扩展。

  • 多语言:

既然我们对用户上传的英文内容有了更多的了解,而且我们有一个一致的管道来给这些文档贴标签,我们可以将这种方法扩展到其他语言

这项工作和这篇文章是我与应用研究团队的同事 Antonia Mouawad 合作完成的。如果你有兴趣了解更多关于应用研究正在解决的问题,或者围绕这些解决方案建立的系统,请查看我们的空缺职位。

猫狗卷积分类器

原文:https://towardsdatascience.com/cats-vs-dogs-convolutional-classifier-44ec04c8eb7a?source=collection_archive---------21-----------------------

使用 Python 代码、Tensorflow 和 Google Colab 从头开始创建和测试一个简单的模型

3 分钟机器学习

3 分钟机器学习是一系列与机器学习世界相关的教程和内容丰富的视频。你可以在 YouTube 上找到完整的视频。库包含视频中显示的所有文件。这个系列是在实验阶段,完全免费开发,为了娱乐和文化!欢迎任何反馈。

其他剧集:

  • 用神经风格转移和张量流生成图像

为什么要读这篇文章?

本文将会看到如何使用 Google Colab 来实现我们自己的深度学习模型的实用性和功能性。然后,我们将看到如何将一个预先存在的数据集导入到我们的工作空间中。我们将实现一个 2D 卷积神经网络模型,用于我们图像的二进制分类。一旦模型被建立和训练,我们将用新的图像测试我们的模型。

正确分类的图像——来自像素库的 K L 图像

Google Colab:为什么?

Colaboratory,简称“ Colab ”,是谷歌研究院的产品。Colab 允许任何人通过浏览器编写和执行任意的 python 代码,特别适合机器学习、数据分析和教育。从技术上来说,Colab 是一种托管的 Jupyter 笔记本服务,无需设置即可使用,同时提供对计算资源的免费访问,包括GPU。点击此链接了解更多信息。

在 Google Colab 中选择运行时

当开发您自己的代码或使用共享代码时,请记住从运行时下的工具栏中选择所需的硬件加速器。对于这个案例研究,由于它是基于卷积网络的模型,所以最好使用*台上免费提供的 GPU 的的能力。总之,我们的神经网络模型有大量参数,必须使用优化算法来确定这些参数,以最小化期望的损失函数。这个过程包括前向传播后向传播,对每个训练时期的每个数据重复这个过程。因此,这个过程涉及到一个 大数 的简单数学运算。GPU,带有:

  • 核心数量多
  • 数千个并发硬件线程

允许我们更快地执行模型的训练和推理。

卷积分类器

图像分析可以通过各种深度学习和神经网络模型来执行,但是,Con voluntive Networks由于其有效性,几乎成为这种类型分析的强制工具。总而言之,一系列大小可变的过滤器的应用允许从图像本身提取信息和特征。第一层会提取出最一般的特征,越深的层越有具体的特征。同时,这种方法允许在模型的几个可训练参数下工作,这些参数远低于用专门基于致密层的神经网络分析图像所需的参数。更多信息,请参考这篇文章。

猫和狗的分类器结构-作者图片

代码

让我们从导入数据集开始:

让我们导入我们的数据集。它包含的图像,这将允许我们训练我们的分类器。我们直接从 Google API 下载数据集,然后将其解压缩到所需的路径。我们通过定义路径来定义目录的结构。我们为训练验证数据定义了两个独立的目录,每个目录又分为两个文件夹:狗和猫。这种结构可能看起来很复杂,但它变得特别复杂,因为它很容易与 Tensorflow 语法接口。所以让我们看看我们有多少数据。

让我们的神经网络模型,类似于前一个图像中描述的。在这种情况下,考虑到模型的简单性,我们使用 Keras 的顺序 API。这允许我们通过简单地定义不同层的列表来创建神经网络,正如我们可以从名称本身猜测的那样。使用的层是在 Tensorflow/Keras 中实现的标准层的一部分。

  • Conv2D : 2D 卷积层
  • MaxPooling2D:2D 空间数据的最大池操作
  • 展*:展*输入
  • 密集:规则密集连接 NN 层

model.summary() 显示我们模型的概要,显示每层的名称类型输出形状可训练参数数量。

该型号必须编制,方可训练。对于本教程,我选择了 Adam 作为优化器,学习率固定。然而,通过优化结构和调整所有的初级次级 超参数,该模型可以得到很大的改进。我们将评估仅仅 准确度 作为评估模型性能的主要指标。然而,准确性可能会与其他指标相结合,例如 f-Beta 得分 ,以便更可靠地评估模型的质量。

所使用的目录结构允许使用图像数据生成器flow_from_directory 方法。第一个允许对源图像应用缩放和数据扩充。为了进行这种分析,我们对训练图像应用了缩放、旋转、移动、剪切、缩放和翻转。您可能会注意到,没有对测试数据应用数据扩充。 flow_from_directory 方法自动加载指定路径中包含的子目录中的所有图像,并在文件夹名称后标记图像。我们只需指定图像的主路径、批量大小、分类模型和目标大小

最后,我们可以训练模型,将训练数据存储在历史对象中。请注意,我们有 2000 个训练图像和 1000 个测试图像,批量大小为 20:对于 训练集 ,每个时期有 100 个步骤,对于 验证集 ,每个时期有 50 个步骤。让我们对网络进行少量纪元(50)的训练,看看结果。

培训历史-作者图片

在训练过程的最后,我们用我们的基本分类器在两个集合上实现了大约 80 % 的准确率 。这是一个好结果,但我们绝没有优化我们的模型,正如更长的训练似乎可能导致更高的表现。在接下来的一篇文章中,我们将看到如何使用各种超参数优化和迁移学习技术来尝试改进我们的分类器。****

您可以使用直接从本地存储空间上传的新图像来测试代码,并且立即获得一个预测。该模型虽然没有优化,但能够正确预测以下两幅图像的类别,这两幅图像是该模型在训练或验证阶段从未见过的。

测试图像—作者提供的图像

结论

我希望你喜欢这篇文章的内容。我提醒你,你可以在这里找到源代码,在 GitHub 和 YouTube 上可以找到完整的资源库。
下次见,
马尔科

因果发现

原文:https://towardsdatascience.com/causal-discovery-6858f9af6dcb?source=collection_archive---------0-----------------------

使用 Python 从数据中学习因果关系

这是关于因果关系的三篇系列文章的最后一篇。之前的帖子里介绍了因果关系的“新科学”【1】,讨论了 因果推断 的话题。本文的重点是一个相关的想法,因果发现。我将从描述什么是因果发现开始,给出它如何工作的草图,并以一个使用 Python 的具体例子结束。

因果发现的总体目标:将数据转化为因果模型。图片作者。

什么是因果发现?

上一篇 中,我讨论了因果推断**,旨在回答涉及因果的问题。虽然因果推理是一个强大的工具,但它需要一把钥匙来操作。也就是说,它需要一个因果模型。然而,通常在现实世界中,我们可能无法确定哪些变量是互为因果的。这就是因果发现能有所帮助的地方。**

因果发现旨在从数据中推断出因果结构。换句话说,给定一个数据集,导出一个描述它的因果模型。

它是如何工作的?

没有标准的因果发现方法。事实上,有各种各样的技术可供使用,其中任何两种可能彼此没有什么相似之处。我在这里的目标是勾画不同算法的共同主题,并给出一些关键思想的味道。

正如我在本系列的 第一篇 中提到的,因果发现是逆问题的一个例子。这就像根据冰块在厨房台面上留下的水坑来预测它的形状一样。

显然,这是一个难题,因为任何形状都可能产生同一个水坑。将这与因果关系联系起来,水坑就像是嵌入数据中的统计关联,而冰块就像是潜在的因果模型。

因果发现的 4 个常见假设

解决逆问题的通常方法是对你试图揭示的东西做出假设。这缩小了可能的解决方案的范围,有希望使问题可以解决。

因果发现算法有四个共同的假设。在参考文献【3】中可以找到对这些假设的很好的讨论。

  1. 无环性 —因果结构可以用 DAG (G)来表示
  2. 马尔可夫性质 —当以它们的父节点为条件时,所有节点都独立于它们的非子节点
  3. 忠实度 —真实基础分布中的所有条件独立性 p 用 G 表示
  4. 充分性—G 中的任何一对节点都没有共同的外因

尽管这些假设有助于缩小可能模型的数量,但它们并没有完全解决问题。这就是因果发现的一些技巧有用的地方。

因果发现的 3 个技巧

如前所述,没有一种单一的因果发现方法能支配所有其他方法。尽管大多数方法都使用上述假设(甚至更多),但不同算法的细节可能会有很大差异。

下图给出了基于以下技巧的算法分类。这绝不是一个详尽的概述。更确切地说,这是我从引用的参考资料[ 2 、 4 、 5 ]中偶然发现的算法集合。

基于[ 2 、 4 、 5 ]的因果发现方法的狭义分类。图片作者。

招数 1:条件独立性测试

这些最早的因果发现算法之一是以其作者 Peter Spirtes 和 Clark Glymour 命名的 PC 算法。这种算法(以及其他类似的算法)使用了这样一种思想:两个统计上独立的变量****没有因果联系。PC 算法说明了第一个技巧。下图给出了算法的概要。关于 PC 算法的更多细节,我推荐参考文献[2&[6]中的讨论。****

PC 算法概要 2 、 6 。图片作者。

第一步是使用数据集中的每个变量形成一个完全连通的无向图。接下来,如果相应的变量是独立的,则删除边。然后,连接的边经受条件独立性测试,例如上图中以中间节点为条件的底部和最右侧节点的独立性测试(步骤 2)。

如果对一个变量的条件化消除了依赖性,则该变量被添加到这两个变量的分离集中。根据图表的大小,条件独立性测试将继续进行(即更多变量的条件),直到不再有候选测试。

接下来,碰撞器(即 X → Y ← Z)基于节点对的分离集被定向。最后,剩余的边基于 2 个约束被定向,1)没有新的 v-结构,以及 2)不能形成定向的环。

招数二:图形空间的贪婪搜索

这个技巧有三个主要元素:一个,一个图空间,以及一个贪婪搜索

是由边(线)连接的顶点(圆)组成的数学结构。因果模型通常使用一种特殊的图,称为有向无环图(DAG)。图和 Dag 在 第一帖 中讨论过。简而言之,DAG 是一种顶点之间的边带有箭头并且不存在循环的图。

一个图空间图的集合。这只是一种形式化的奇特方式,即对于给定数量的顶点和边,有许多可能的图。例如,一个有 2 个顶点和 1 条边的 DAG 可以采用以下形式:A → B 或 B → A。请注意,这是前面冰块逆问题的另一个例子。然而,不是多个冰块可能产生相同的水坑,而是多个 Dag 可以具有相同数量的节点。

最后,贪婪搜索是一种导航空间的方式,这样你总是根据当地环境看起来最有利的方向移动。这就像在森林里迷路了,试图通过向开阔地带移动来走出去。这种方法的问题是,你不能保证找到穿过空间的最佳路径,如下图所示。**

说明贪婪的搜索可能会出错。在这里,当试图走出森林时,对向开阔区域移动的贪婪搜索将导致次优路径。图片作者。

虽然贪婪搜索不能保证最优解,但对于大多数问题来说,可能 Dag 的空间如此之大,以至于很难找到真正的最优解。

贪婪等价搜索(GES) 算法使用了这个技巧。GES 从一个空图开始,迭代地添加有向边,从而最大化模型适应度(即分数)的改进。一个示例分数是贝叶斯信息标准(BIC) [ 2 ]。

招数 3:利用不对称

正如 第一帖 中所说,因果关系的一个根本属性是不对称。a 可能导致 B,但 B 可能不会导致 a。有大量算法利用这一思想在因果模型候选之间进行选择。我将把这些不对称归类为三种常见的味道: 时间、复杂性和功能性。在描述这些不对称之前,重要的是要注意它们并不相互排斥。也就是说,算法可以混合搭配不同的口味。

时间不对称对我们来说是很自然的。它的理念是原因发生在结果之前。这是诸如格兰杰因果关系等观点的核心。尽管格兰杰因果关系不足以说明因果关系,但它利用了因果关系的概念。它在两个变量的情况下(例如 X 和 Y)通过在给定 Y 和 X 的过去信息的情况下量化预测 Y 的增益来做到这一点,这与单独 Y 的过去信息相反[ 5 ]。

复杂性不对称遵循奥卡姆剃刀原理,即模型越简单越好。换句话说,如果你有几个候选模型可以选择,这个想法就是选择最简单的一个。量化简单性(或复杂性)的一种方法是 Kolmogorov 复杂性。

功能不对称假设更符合关系的模型是更好的候选模型。例如,给定两个变量 X 和 Y,非线性加性噪声模型(NANM) 在 X 和 Y 之间执行非线性回归,例如 y = f(x) + n,其中 n =噪声/残差,在两个方向上。如果潜在原因(例如 x)与噪声项(例如 n)无关,则该模型(即因果关系)被接受。关于 NANM 的更多细节可以在参考文献[ 7 ]中找到。

示例:通过人口普查数据发现因果关系

我们现在从理论转向一个具体的例子。这个例子使用了因果发现工具箱,一个用于因果发现的 Python 库[ 4 ]。在这个例子中,我们从和以前一样的来源查看人口普查数据。

**在之前的例子中,我们假设收入有两个原因:年龄和教育。然而,我们怎么能肯定这个假设站得住脚呢?在本例中,我们探索了包含更多变量并利用数据驱动方法的替代因果模型:因果发现。示例代码和数据可以在 GitHub repo 中找到。

首先,我们加载必要的库和数据。如果您没有这些库,请查看回购中的 requirements.txt 。数据也在回购中。

**# import libraries
import pickle
import cdt
import networkx as nx
import matplotlib.pyplot as plt# load data
df = pickle.load( open( "df_causal_discovery.p", "rb") )**

接下来,我们需要为我们的因果模型构建一个框架。这基本上是前面讨论的 PC 算法的第二步。换句话说,进行成对独立性检验,被认为是统计相关的变量得到一个双向边。

**# Get skeleton graph
# initialize graph lasso
glasso = cdt.independence.graph.Glasso()# apply graph lasso to data
skeleton = glasso.predict(df)# visualize network
fig = plt.figure(figsize=(15,10))
nx.draw_networkx(skeleton, font_size=18, font_color='r')**

骨架图。图片作者。

注意我们有 7 个不同的变量。之前我们只考虑年龄,学历(hasGraduateDegree),收入(greaterThan50k)。仅从骨架中,我们可以看到存在于这三个变量之间的统计相关性。

现在是因果发现的时候了。在这里,我们尝试了 3 种不同的算法:PC,GES 和 LiNGAM。

**# Use causal discovery to get causal models# PC algorithm
model_pc **=** cdt**.**causality**.**graph**.**PC()
graph_pc **=** model_pc**.**predict(df, skeleton)

*# visualize network*
fig**=**plt**.**figure(figsize**=**(15,10))
nx**.**draw_networkx(graph_pc, font_size**=**18, font_color**=**'r')**

从 PC 算法输出因果图。图片作者。

PC 给出了一个稍微合理的结果。我们在上一个例子中使用的简单的 3 变量 DAG 是几乎嵌入在这个图中。年龄和 hasGraduateDegree 之间的箭头颠倒了,这是有问题的,因为这表明拥有研究生学位对一个人的年龄有因果关系!**

它还暗示了额外的因果关系。也就是说,hasGraduateDegree,greaterThan50k,age 和 isFemale 都对每周工作时间有单向因果影响,这本身对 inRelationship 有因果影响。接下来,我们看看 GES。

**# GES algorithmmodel_ges **=** cdt**.**causality**.**graph**.**GES()
graph_ges **=** model_ges**.**predict(df, skeleton)

*# visualize network*
fig**=**plt**.**figure(figsize**=**(15,10))
nx**.**draw_networkx(graph_ges, font_size**=**18, font_color**=**'r')**

从 GES 算法输出因果图。图片作者。

该图似乎与 PC 结果基本一致。值得注意的区别是,以前源于 isWhite 的双向边现在是单向的。回想一下 GES 的工作方式是有道理的。

最后,我们将 LiNGAM 应用于数据,该数据使用我称之为线性模型之间的功能不对称来推断因果关系[ 9 ]。

**# LiNGAM Algorithm
model_lingam **=** cdt**.**causality**.**graph**.**LiNGAM()
graph_lingam **=** model_lingam**.**predict(df)

*# visualize network*
fig**=**plt**.**figure(figsize**=**(15,10))
nx**.**draw_networkx(graph_lingam, font_size**=**18, font_color**=**'r')**

从 LiNGAM 算法输出因果图。图片作者。

这个结果与前两个有很大的不同。许多边缘方向已经翻转,例如在大于 50k 的和具有渐变度的之间的方向。性能不佳可能是由于违反了算法对线性效应的假设。这里的大多数变量都是二元的,因此线性结构方程可能不合适。****

结论

关于因果关系的三部分系列到此结束。在这篇文章中,我试图从因果发现中勾勒出大的想法,同时仍然为实际应用提供足够的细节。尽管我无法在一篇简短的博客文章中对因果发现进行全面的回顾,但我已经尝试在下面的资源部分整理了一份好的参考资料列表。尽管还很年轻,但因果发现是一个充满希望的领域,可能有助于弥合机器和人类知识之间的差距。

** **

资源

更多关于因果关系 : 因果关系概述 | 因果关系:简介 | 因果推断 | 因果发现

连接 : 我的网站 | 预定电话 | 邮件我

社交:YouTube|LinkedIn|Twitter

支持 : 给我买杯咖啡 ☕️ | 成为会员 ⭐️

**https://shawhin.medium.com/membership **

《为什么之书:因果的新科学》朱迪亚·珀尔著

[2]基于图形模型的因果发现方法综述。https://doi.org/10.3389/fgene.2019.00524

[3]基于 ML 的因果发现:arXiv:1803.04929【stat。ML]** (好的引物)**

[4]因果发现工具箱文档:https://fentechsolutions . github . io/CausalDiscoveryToolbox/html/index . html

[5]格兰杰因果关系:https://doi . org/10.1016/0165-1889(88)90055-3

[6]因果推断用 R 包 pcalg:http://dx.doi.org/10.18637/jss.v047.i11(好的引子)

[7]非线性加性噪声模型论文

[8] UCI 机器学习知识库:数据来源

[9] LiNGAM 论文

[10]摘自纳西姆·尼古拉斯·塔勒布反脆弱的例子(付费链接)

模型稳健性的因果框架

原文:https://towardsdatascience.com/causal-framework-for-model-robustness-dc8713ba1f3b?source=collection_archive---------26-----------------------

使用因果建模进行特征选择和创建

张玉香在 Unsplash 上拍照

模型稳健性

我们都希望我们的机器学习模型对看不见的数据进行归纳,但经常发现,当新数据看起来不像旧数据,即具有不同的分布时,我们的模型性能会下降。例如,我们根据一个国家的数据训练的医疗诊断系统不能推广到另一个国家,因为该国家的常见疾病与训练集所在国家的疾病不同。机器学习研究人员和实践者开发了各种技术来克服这个问题,并将模型命名为健壮

根据定义,鲁棒模型对预测变量或目标变量的分布变化不敏感。模型鲁棒性是一个活跃的研究领域,分析模型鲁棒性的方法之一是使用因果推理。

稳健性因果模型

一般来说,因果推断是指回答改变一个变量是否会影响结果的问题。例子可以是研究促销和折扣如何提高销售额,或者特定的医疗如何改善病人的结果[1]。

我们都知道一句格言:“相关性并不意味着因果关系”。研究相关性是统计学家和数据科学家工作的一个非常重要的部分,但在研究因果问题时还不够。本质上,因果模型看起来与贝叶斯网络非常相似,因为它使用条件概率来表达所有变量的联合分布,例如:

如果我们把所有的概率都放在直接原因上,那么这个模型就是因果的:

来源:https://arxiv.org/abs/1507.05333

对变量 Xi 的干预是指我们改变 Xi 的分布,例如,将变量设为常数。因果建模扩展了条件概率的语法,以包括干预。例如,下面的等式

资料来源:https://en.wikipedia.org/wiki/Bayesian_network

是指当我们将变量 G 设为 t 时,变量 R 的概率。这也被称为因果机制

因果建模如何帮助我们建立稳健的模型?如果我们预测 Y= f(X₁,X₂,… Xn),那么变量 X₁分布的变化可以建模为一个干预[2]。因此,稳健模型是对所有可能的干预都不变的模型。

因果模型有一个非常有用的性质,叫做*原因和机制之间的独立性,*它粗略地陈述了将原因 C 映射到结果 E 的机制不依赖于原因变量 C 的分布[3]。因此,如果我们的预测变量是原因,目标变量是结果,那么根据这一性质,模型 P(Y|X)是稳健的,因为当边际分布 P(X)改变时,它将同样工作良好。

然而,如果我们试图根据结果来预测原因,情况就不同了。考虑医疗诊断案例,当我们有一组症状,我们试图预测诊断。由于诊断是原因,症状是结果,我们可以使用独立性假设,并声称我们可以根据疾病 E(X|Y)稳健地预测症状。如果我们试图根据症状预测诊断,我们可以使用贝叶斯法则:

从这个方程我们可以看出,预测的诊断不仅取决于因果机制 P(X|Y),还取决于疾病在给定区域的流行程度 P(Y)。例如,同样的症状可以在一个国家用于诊断疟疾,在另一个疟疾不流行的国家用于诊断呼吸系统疾病。我们试图从结果中预测原因的情况被称为反因果预测【4】。

不变集

在大多数情况下,X 和 Y 之间的关系不能简化为因果关系。例如,在医学诊断中,问题是颠倒的,因为我们需要根据结果预测原因。罗哈斯·卡鲁拉等人[3]提出了一个问题,是否有可能导出特征 X 的子集 Xi,其中分布 P(Y|Xi)独立于 P(Xi)。这个子集被称为不变集,因为给定 Xi 的 Y 的模型预测不依赖于对除目标变量之外的任何变量的任何干预。我们来看下面这个因果图:

来源:https://www.bradyneal.com/causal-inference-course

这里我们试图根据预测变量 X₁到 X₁₆.来预测 y 我们可以排除所有的间接原因,因为它们是多余的,任何不是 Y 的原因的变量都可以改变它的分布,使预测不准确。这给我们留下了直接原因作为这个问题的不变集。

来源:https://www.bradyneal.com/causal-inference-course

这意味着,如果 Xi 包含 Y 的所有直接原因,则模型是稳健的。

您可以看到,我们大幅删除了大部分特征,因此尽管模型保持稳健,但预测能力较低。对于完全反因果模型,像上面提到的医学诊断问题,不变集是空的。

反因果模型的稳健性

有一些方法可以在不消除所有预测变量的情况下提高反因果模型的稳健性。其中一个显而易见的方法是将 Y 的分布信息作为一个新变量显式地输入到模型中。在我们的例子中,我们可以将疾病在特定国家的流行率作为一个额外的预测变量。如果我们的训练数据包含几个国家,模型可以学习使用此信息来调整对新国家的预测。例如,如果我们使用逻辑回归,我们可以将更新后的模型表示为:

这种方法相当于目标编码,这是一种在数据科学竞赛中广泛使用的编码分类变量的流行方法。我们可以向模型提供更多关于目标变量边际分布的信息,而不是它的期望值。一种可能的技术是使用我在早期文章中提到的贝叶斯目标编码。

结论

因果推理成为每个数据科学家工具箱中的必要工具。虽然这仍然是一个活跃的研究领域,但是有一些技术和工具可以解决最常见问题的原因。然而,因果推理的作用并不局限于因果问题,而是通过鲁棒性的因果理论扩展到机器学习。在这篇文章中,我试图分享我对健壮的机器学习模型的因果考虑的想法,以及它如何连接到特征工程的常用技术。

参考

[1]朱迪亚珍珠。2009.因果关系:模型、推理和推论(第二版。由…编辑).美国剑桥大学出版社。

[2] R. Christiansen,N. Pfister,M. E. Jakobsen,N. Gnecco 和 J. Peters,“分布一般化的因果框架”,载于《IEEE 模式分析和机器智能汇刊》,doi:10.1109/tpami。46306.86686866676

[3]罗哈斯-卡鲁拉先生、舒尔科夫先生、特纳先生和彼得斯先生。机器学习中的因果迁移。机器学习研究杂志,19(36):1–34,2018

[4]b . schlkopf、D. Janzing、J. Peters、E. Sgouritsa、K. Zhang 和 J. M. Mooij。因果学习和反因果学习。《第 29 届机器学习国际会议论文集》(ICML),第 1255–1262 页。Omnipress,2012 年。

因果推理

原文:https://towardsdatascience.com/causal-inference-962ae97cefda?source=collection_archive---------0-----------------------

用 Python 回答因果问题

这是关于因果关系的三篇系列文章的第二篇。在的上一篇文章中,我介绍了这种“新的因果科学”【1】,并给出了因果推理和因果发现的味道。在本帖中,我们将深入探讨因果推理的一些细节,并以 Python 中的一个具体例子结束。

因果网络的一个例子。图片作者。

从哪里开始?

在的上一篇文章、中,我讨论了因果关系如何通过结构因果模型(SCMs) 用数学方法表示。SCMs 由两部分组成:一个图形,它将因果联系可视化,以及方程,它表达了联系的细节。

概括一下,是由顶点(节点)和边(链接)组成的数学结构。在这里,我将交替使用图和网络这两个术语。SCMs 使用了一种特殊图,称为有向无环图(DAG)** ,它的所有边都是有向的,不存在环。Dag 是因果推理的常见起点。**

贝叶斯网络与因果网络

当我第一次探索这个主题时,一个模糊之处是贝叶斯网络因果网络之间的区别。所以我简单提一下区别。开明的读者可以随意跳过这一节。

从表面上看,贝叶斯和因果网络是完全相同的。然而,不同之处在于他们的解释。考虑下图中的例子。

可以解释为贝叶斯和因果网络的例子。火和烟的例子取自珀尔[1]。图片作者。

这里我们有一个有 2 个节点(火图标和烟图标)和 1 条边(从火指向烟的箭头)的网络。这个网络可以是贝叶斯网络,也可以是因果网络。

然而,关键的区别在于解释这个网络的时候。对于一个贝叶斯网络,我们将节点视为变量,将箭头视为条件概率,即给定火灾信息时烟雾出现的概率。当将此解释为一个因果网络时,我们仍然将节点视为变量,然而箭头表示一个因果连接。在这种情况下,两种解释都有效。然而,如果我们翻转边缘方向,因果网络解释将是无效的,因为烟雾不会引起火灾。

示例网络可以解释为贝叶斯网络,但不是因果网络。火和烟的例子取自珀尔[1]。图片作者。

什么是因果推理?

因果推断 旨在回答因果问题而不仅仅是统计问题。因果推理的应用数不胜数。回答下面的任何问题都属于因果推理的范畴。

  • 治疗对服用者有直接帮助吗?
  • 是营销活动导致了这个月的销售增长还是假期?
  • 增加工资会对生产率产生多大影响?

这些都是重要而实际的问题,使用更传统的方法(例如线性回归或标准机器学习)可能不容易回答。我希望通过我称之为因果推理的 3 个天赋来说明因果推理是如何帮助回答这些问题的。

因果推理的三种天赋

礼物 1:do-operator

在的上一篇文章中,我从干预的角度定义了因果关系。忽略一些技术细节,据说如果对 X 的干预导致 Y 的变化,则 X 导致 Y,而对 Y 的干预不一定导致 X 的变化。干预在现实世界中很容易理解(就像当你朋友的糖果习惯失控时),然而,这如何符合因果关系的数学表示?

输入 do 运算符。 do-operator 是物理干预的数学表示。如果我们从模型 Z → X → Y 开始,我们可以通过删除所有传入 X 的箭头,并手动将 X 设置为某个值 x_0 来模拟 X 中的干预。

do 运算符如何工作的图示。图片作者。

假设我们知道因果联系的细节,do 运算符的强大之处在于它允许我们模拟实验。例如,假设我们想问,增加营销预算会促进销售吗?如果我们有一个包括营销支出和销售的因果模型,我们可以模拟如果我们增加营销支出会发生什么,并评估销售的变化(如果有的话)是否值得。换句话说,我们可以评估营销对销售的因果效应。稍后再谈因果关系。

珀尔和他的同事们的一个主要贡献是 do-calculus 的规则。这是一个 完整的规则集,概述了如何使用 do 运算符

值得注意的是,do-calculus 可以将介入分布(即有 do 算子的概率)转化为观察分布(即没有 do 算子的概率)。这可以从下图中的规则 2 和规则 3 看出。

微积分的规则。规则摘自珀尔[ 2 ]的讲座。图片作者。

注意符号。 P(Y|X) 就是我们都很熟悉的条件概率,也就是给定 X 的一个观测值 Y 的概率。而, P(Y|do(X)) 是在 X 中给定一个干预Y 的概率。

do 运算符是因果推理工具箱中的一个关键工具。事实上,接下来的两个礼物依赖于 do-operator。

礼物 2:消除混淆

混淆是统计学中的一个概念。虽然我没有直呼其名,但这是通过辛普森悖论出现在上一篇中的。下图显示了一个简单的混杂示例。

一个简单的混淆例子。年龄是教育和财富的混淆物。图片作者。

在这个例子中,年龄是教育和财富的混淆因素。换句话说,如果试图评估教育对财富的影响,你需要根据年龄调整。调整 用于(或调节开启)年龄仅仅意味着当查看年龄、教育和财富数据时,人们会比较年龄组内的**、而不是年龄组之间的数据点。**

如果不考虑年龄因素,就不清楚教育是财富的真正原因还是仅仅是财富的关联。换句话说,你不知道教育是否直接影响财富,或者只是与财富有一个共同的原因。

举个简单的例子,在查看 DAG 时,混淆非常简单。对于 3 个变量,混杂因素是指向 2 个其他变量的变量。但是更复杂的问题呢?

这就是 do 操作符提供清晰度的地方。Pearl 使用 do 运算符以明确的方式定义混杂。他说混淆导致 P(Y|X)不同于 P(Y|do(X)) [1]的任何东西。

礼物 3:估计因果效应

这最后的礼物是因果推论的主要吸引力。在生活中,我们不仅要问自己为什么,还要问*多少?*估计因果关系归结为回答第二个问题。

考虑读研。知道拥有研究生学位的人比没有研究生学位的人赚更多的钱是一回事,但一个自然的问题是,其中有多少是因为他们的学位?换句话说,研究生学历对收入的待遇影响如何?

我将利用回答这个问题的机会来完成一个使用 Python 进行因果推理的具体例子。

示例:估计研究生院对收入的处理效果

在这个例子中,我们将使用微软 DoWhy 库进行因果推理[ 3 ]。这里的目标是估计拥有研究生学位对年收入超过 5 万美元的因果影响。数据从 UCI 机器学习库[ 4 ]获得。示例代码和数据可在 GitHub repo 中找到。

重要的是要强调所有因果推理的起点是一个因果模型。这里我们假设收入只有两个原因:年龄和教育,而年龄也是教育的一个原因。显然,这个简单的模型可能遗漏了其他重要因素。我们将在下一篇关于 因果发现 的文章中研究替代模型。然而,现在我们将关注这个简化的案例。

首先,我们加载库和数据。如果您没有这些库,请查看回购中的 requirements.txt 。

**# Import libraries**
import pickle
import matplotlib.pyplot as plt

import econml
import dowhy
from dowhy import CausalModel**# Load Data**
df = pickle.load( open( "df_causal_inference.p", "rb" ) )

同样,第一步是定义我们的因果模型,即 DAG。DoWhy 使创建和查看模型变得容易。

**# Define causal model**
model=CausalModel(data = df,         
                  treatment= "hasGraduateDegree",         
                  outcome= "greaterThan50k",         
                  common_causes="age",         
                  )***# View model***
model.view_model() 
from IPython.display import Image, display display(Image(filename="causal_model.png"))

我们(假设的)因果模型。图片作者。

接下来,我们需要一个 estimand。这基本上是一个给我们想要的因果效应的配方。换句话说,它告诉我们如何计算教育对收入的影响。

**# Generate estimand**
identified_estimand= model.identify_effect(proceed_when_unidentifiable=**True**)
print(identified_estimand)

estimand 生成的输出。图片作者。

最后,我们基于估计量计算因果效应。在这里,我们使用来自 EconML 库的元学习器【5】,它估计离散目标的条件*均治疗效果。

**# Compute causal effect using metalearner**
identified_estimand_experiment = model.identify_effect(proceed_when_unidentifiable=True)

from sklearn.ensemble import RandomForestRegressor
metalearner_estimate = model.estimate_effect(identified_estimand_experiment,                             method_name="backdoor.econml.metalearners.TLearner",
confidence_intervals=False,
method_params={
     "init_params":{'models': RandomForestRegressor()},
     "fit_params":{}
              })print(metalearner_estimate)

因果估计的输出。图片作者。

*均因果效应约为 0.20。这可以解释为,拥有研究生学位会让你年收入超过 5 万美元的概率增加 20%。注意这是*均效应,考虑值的全部分布以评估*均值是否具有代表性是很重要的。

**# Print histogram of causal effects**
plt.hist(metalearner_estimate.cate_estimates)

因果关系的分布。图片作者。

在上图中,我们看到了样本间因果关系的分布。显然,该分布是而不是高斯分布。这告诉我们*均值并不代表总体分布。基于因果效应的进一步分析可能有助于发现“谁”从研究生学位中受益最多的可操作信息。

不管怎样,仅仅根据潜在收入来决定读研,可能表明你并不真的想读研。🤷🏽‍♀️

结论

因果推理是回答更传统的方法可能无法解决的自然问题的强大工具。在这里,我从因果推理中勾勒出一些大的想法,并通过代码完成了一个具体的例子。如前所述,所有因果推理的起点是一个因果模型。然而,通常我们手头没有一个好的因果模型。这就是 因果发现 可以有所帮助的地方,这也是下一篇帖子的主题。

资源

更多关于因果关系 : 因果关系概述 | 因果关系:简介 | 因果推断 | 因果发现

连接 : 我的网站 | 预定电话 | 邮件我

社交:YouTube|LinkedIn|Twitter

支持 : 给我买杯咖啡 ☕️ | 成为会员 ⭐️

https://shawhin.medium.com/membership

朱迪亚·珀尔所著的《为什么:因果的新科学》

[2]珀尔,J. (2012 年)。重新审视微积分。arXiv:1210.4852【cs。AI]

[3]阿米特·夏尔马,埃姆雷·基西曼。DoWhy:一个用于因果推理的端到端库。2020.https://arxiv.org/abs/2011.04216

[4]杜瓦和格拉夫(2019 年)。UCI 机器学习知识库[http://archive . ics . UCI . edu/ml]。加州欧文:加州大学信息与计算机科学学院。https://archive.ics.uci.edu/ml/datasets/census+income

[5] Künzel,ren R .等人,“使用机器学习评估异质治疗效果的金属学者”美国国家科学院院刊,第 116 卷第 10 期,2019 年 3 月,第 4156–65 页。www.pnas.org,https://doi.org/10.1073/pnas.1804597116.

野外因果推理:弹性定价

原文:https://towardsdatascience.com/causal-inference-example-elasticity-de4a3e2e621b?source=collection_archive---------2-----------------------

行业笔记

机器学习如何提高工业中的因果推理?我用零售定价的代码描述了一个真实的例子。

因果推理是机器学习中的一个热门话题,有许多关于因果推理理论的优秀入门书籍[1–4]。但机器学习驱动的因果推理在现实世界中的应用例子少得多。本文介绍了一个来自行业环境的例子,使用了一个(公开的)真实数据集。它的目标读者是对因果关系有基本理解的技术人员。

具体来说,我将着眼于价格弹性估计的“理想”情景[2,5]。这种情况与希望优化价格的零售商高度相关,例如,为了更好地管理库存或只是为了更具竞争力。

在第一部分,我将提出这个问题,并提供一个简单的背景。这也将说明更普遍的一点,即估计因果关系需要“仅仅”数据分析之上的领域专业知识。在第 2 节,我将解释从历史数据中学习是困难的,因为混杂。第 3 节将为这个问题勾勒一个机器学习驱动的解决方案,这在第 4 节的代码示例中有详细描述。这里有一个完整的、可运行的笔记本。最后,我将讨论这种因果有效估计的业务相关性。

1 为什么要关心弹性?

“需求的价格弹性”是大多数经济学 101 课程的核心概念,它描述了对给定产品的需求对价格的敏感程度。如果一种产品“更有弹性”,价格上涨将导致更大的需求下降。作为一个因果概念,弹性允许我们量化如果我们将价格降低,比如说,5%,我们可以多卖出多少单位(与事实相反)。

作为价格和需求数量之间的影响的弹性描述了一个复杂的因果系统:价格当然不会直接影响需求,而是通过许多个人消费者购买或不购买的决定以及诸如在特价商品搜索网站上出现的次要影响来调节。在试图估计弹性时,零售商跳过所有这些复杂性,直接测量他们控制的东西(价格)对他们关心的东西(需求)的影响。

令人惊讶的是,弹性实际上是可以估计的。但是自从它在 1890 年被正式定义以来[6],经济学家发现需求的价格弹性在许多情况下是现实的一个体面的*似值[5]。这种*似在相对变化的规范定义中特别方便:弹性衡量需求数量的百分比变化( q ,给定价格的百分比变化( p ):

这里的直觉很简单:成本为 5 美元的产品价格变化 1 美元,将导致比成本为 100 美元的产品更剧烈的需求变化。总的来说,消费者关心的是“相对”变化。根据经验,这个定义很方便,因为它意味着待估计的参数 θ 随着 p 的变化而保持*似恒定。

有了对 θ 的有效估计,零售商现在可以对他们的价格进行反事实推理:“如果我将我的产品价格提高 5%,我可以预期多卖出 5θ%的单位”(θ通常为负值)。

为了建立一些直觉,假设他们目前以 5 美元的价格和 4 美元的成本销售了 100 个单位。那么他们目前的利润是 100 *(5–4)= 100 美元。假设他们估计弹性为θ=-3,即他们预计价格上涨 5%(从 5 美元到 5.25 美元)会导致需求减少 15%(从 100 美元到 85 美元)。那么新的利润会稍微增加,85 *(5.25–4)= 106 美元。然而,如果他们降价 5%,他们就会损失利润:115 *(4.75–4)= 86 美元。请注意,更高的价格并不总是导致更高的利润:例如,如果单位成本仅为 3 美元:5%的价格上涨将减少利润,从 100 *(5–3)= \(200 到 85 *(5.25–3)=\) 191。

你可能会说服自己,不同的弹性值会改变最优价格:一般来说,需求弹性越大(例如,如果 θ =-5 而不是-3),成本和价格之间的加价应该越低。

能够做出这种反事实的陈述,通过给出价格应该提高还是降低的指示,为零售商节省了许多“尝试新价格”的时间。当然,例如,当零售商想要管理他们的库存以销售所有库存直到季末时,对弹性的良好估计提供了额外的价值。简而言之,高度精确的弹性估计为零售商提供了个人购买决策的复杂因果系统的简明摘要,允许对其预期结果充满信心的商业决策。

对需求的基本经济理论的简短探究是因果推理中专家知识的一个例子:关于数据生成过程的知识告知了要回答的问题类型、要寻找的机制,以及通常假设的函数形式。很难从数据中了解所有这些结构,当然数据效率也很低。

2 欣赏挑战

在介绍了为什么零售商想要估计弹性之后,这一部分将描述为什么这是一个有趣的问题。

当然,因果推断的首选方法是(随机)实验:零售商可能会花一些时间随机上下调整产品价格(或者更好的是,在用户之间随机定价)。但是这种试验是昂贵的,因为产品以次优价格出售,客户体验受到影响。更糟糕的是,零售数据的信噪比通常很低,因为大多数商店提供大量的产品,其中很大一部分在任何给定的时间框架内都没有卖出去。因此,在卖出足够多的产品来进行推断之前,实验需要进行很长时间。最后,零售商可能会担心,例如,短期实验可能无法跨季节推广。

因此,从观察数据中学习因果有效弹性的能力是关键;本例中的观察数据只是零售商在一段时间内的价格和销售量历史。但是由于混杂因素,从观察数据中估计因果关系是困难的。为了理解这意味着什么,考虑(1)产品质量和(2)季节作为许多潜在混淆因素的两个重要例子:

  1. 比如说,MacBooks 比 Chromebooks 更贵。假设零售商销售的 MacBooks 比 Chromebooks 多(其他什么都没有),观察数据表明高价格与高销量相关。但是,(反事实地)期望把 Chromebook 的价格提高到苹果的水*就能卖出更多 chrome book 是愚蠢的。
  2. 对许多产品的需求是季节性的,例如由于假期(圣诞节)和天气变化(夏季)。通常情况下,旺季价格较高(但仍有大量产品售出),淡季价格较低(此时售出的产品较少);然而,尽管存在这种相关性,但通过将淡季价格提高到旺季水*来期望更高的销售额是愚蠢的。

俗话说,零售商必须小心不要混淆相关性和因果关系。下面的因果图代表了一个简单的混杂关系:未能控制产品质量(和季节,以及其他因素,未显示)将显著偏差θ的估计值。这种偏见会导致零售商对最优价格得出错误的结论,直接损害他们的业务。

价格和数量之间的最小(即不完整)因果图,产品质量是唯一的混杂因素。

题外话:价格弹性是计量经济学中“联立方程模型”问题的一个实例[7]——核心观点是价格实际上是由供应方和需求方的同时决策决定的。在这个例子中,零售商相信他们有足够的关于他们自己定价决策的数据来分离出对价格变化的市场反应的一致估计。

知道正确控制所有可用混杂因素的重要性,零售商现在转向机器学习驱动的因果推理。

3 双机器学习,或称可观测量控制 2.0

我在这里描述的解决方案主要解决了两个问题:首先,正则化从大量潜在的混杂因素中挑选出合适的控制。第二,由于我使用灵活的机器学习算法,控制变量的函数形式和相互作用(即它们的预处理)不如传统回归方法重要,在传统回归方法中,使用普通线性回归来控制混杂因素。自然,仍然需要进行大量的思考来寻找可能是混杂因素的变量——以及应该避免哪些变量,因为它们可能会引入“对撞机偏差”[8],这种方法是而不是免疫的。

我的解决方案实现了双机器学习(DML) [9]。主要思想是相对直观的:给定一些观察到的潜在混杂因素,我使用非参数的、灵活的估计器(机器学习模型)来有效地控制各种函数形式和交互作用的影响。换句话说,我用 ML 模型*似了数据生成过程中的实际混淆机制。

为此,我训练两个独立的“辅助”模型,分别预测待遇(价格, P )和结果(需求量, Q )。这两个模型都是用一组潜在的混杂变量(如产品质量和季节)独立训练的,因此它们的预测接*期望值, E[P|X]E[Q|X]

使用这些预测,我然后剩余出通过一组控制变量可预测的治疗和效果部分:

在我下面的实现中,我选择 RandomForests 来估计条件期望,选择它是因为它们的稳健性能。您可以将这两个辅助模型视为“控制模型”:如果 X 包含足够多的相关混杂因素的信息,并且如果至少有一个模型“非常适合”,那么通过构建,P̃和 Q̃现在是“未建立的”,只剩下真正的因果关系(关于这一点有丰富的文献,从[9]开始)。

所以在剩余化之后,我对

这个数量仍然很难估计,但幸运的是在计量经济学中有一个估计弹性的标准方法:对数回归。 θ 完全等价于以下回归模型中的参数:

具体如何工作超出了本文的范围(如果您想了解,请参见[10])。重要的一点是,在实际实施中,我将根据剩余对数价格(线性)回归剩余对数数量,以获得 θ。

在下面的分格散点图中,我展示了在我的样本数据集中取对数数量和对数价格之间的相关性的“天真”结果:即使在控制诸如季节或产品质量之类的混杂因素之前,这种关系似乎也有些线性。弹性, θ ,是这条线的斜率(【10】)。正如您将看到的,控制混杂因素会显著改变(改进)估计值。

在数据清理后的简单相关性分析中,可以观察到对数数量和对数价格之间的(某种程度上)线性关系,此处显示为一个分格散点图。

现在,将方法放在一起:

  1. 我要拿 pq圆木
  2. 我将构建一组潜在的混杂因素, X
  3. 我将训练一个辅助随机森林模型来从 X 预测 log(p)
  4. 我将训练一个单独的辅助 RandomForest 模型来从 X 预测 log(q)

如果您密切关注这一过程,您会注意到所描述的残差化过程是“样本内预测”,即辅助模型根据它们预测的相同数据进行训练。这可能会引入过度拟合并导致偏差——为了抵消这一点,我将把我的数据分成两半。我将使用一半的数据来拟合辅助模型,然后使用模型来残差另一半的 log(p)log(q) 。然后我可以在后面的数据集中测量因果弹性。冲洗并重复,切换两组并对两个估计值进行*均。所以:

  1. 将数据集分成两半,取 pq日志
  2. 构建一组潜在混杂因素 X (两半中的变量相同)。
  3. 使用的前一半训练一个辅助随机森林模型,从 X 预测 log(p)
  4. 使用的前一半训练一个单独的辅助随机森林模型,从 X 预测 log(q)
  5. 使用两个辅助模型从第第二半个数据中的 X 预测 log(p)log(q) ,残差后得到:

6.将弹性推断为线性回归的系数,

7.交换两半,重复步骤 3-6。使用两个 θ 估计值的*均值作为最终结果。

为了更好地说明这种机制在实践中是如何工作的,让我们看一些分步示例代码。对于您自己的实验,DML 和许多其他现代方法可以在 EconML 中方便地获得,EconML 是由微软研究院维护的一个新的 python 包[11]。截至 2021 年初,我发现 API 相当不稳定,但正在进行的开发非常有前景。类似地,DoubleML 为 python 和 R 提供了 DML 实现[12]。

4 个样本代码

代码使用这个理想化的真实世界数据集:每天和每个产品都有一行,以及这个(第 X 天的产品)组合的一些附加特性,可以用作潜在的混杂因素, X 。最重要的是,在每一行中,数据记录了 QP

首先,我将定义两个标准 ML 模型,从所有可用的潜在混杂因素 X 中预测 log(p)log(q) 。请注意,由于每天和每种产品都有单独的控制变量,因此模型可以捕捉产品质量和季节性。

为了提高模型的预测质量,进一步减少混淆,并展示 DML 的优势,我添加了一些进一步的特征工程: n-grams 产品描述,以恢复产品、季节性描述符和产品新颖性度量之间的相似性。然后,我将这个特征工程的结果,一组潜在的混杂因素,输入到一个标准的随机森林模型中。

当然,在这方面可以付出更多的努力;但这组潜在的混杂因素表明,随机森林可能会发现非*凡的函数形式和交互效应,超出了标准回归所能做到的。

接下来,对于实际的推断,我将使用线性回归模型。如上所述,这将估计对数-对数回归的斜率 θ

最初的 DML 论文为这个回归提出了与 OLS 略有不同的估计量,以获得更好的稳健性:代替采用标准的 OLS 解,

Q ~θP+截距的标准 OLS 解

他们使用以下去偏估计量。注意第一个 P 是剩余的,而第二个是不是,第三个是:

去偏回归估计量[9]

在下面的代码片段中,我实现了如上所述的步骤(1)到(6):将数据分成两半,在前半部分训练辅助模型,剩余后半部分,并推断弹性。在重复交换两半后,我取两个估计值的*均值,以获得一个稳健的因果估计值(假设我能够捕捉到相关的混杂因素)。

最终输出如下所示:

1st Fold:
DML elasticity:  -1.90
OLS elasticity for comparison: -1.83
2nd Fold:
DML elasticity:  -1.92
OLS elasticity for comparison: -1.85
DML efficient estimate of elasticity: -1.91 

因此,我们有它:我们的双重稳健,ML 控制的需求价格弹性估计。即价格对销售量的*均处理效果。在行业环境中,零售商现在可以尝试使用小实验(即随机价格变化)来验证这一估计。

这一最终结果可在以下分箱散点图中看到:

DML 结果的可视化表明,控制混杂因素减少了我们治疗变量中的“噪音”变化,并改变了效果大小。

在剧情中,可以看到蓝色的“幼稚”做法。这只是绘制对数-数量对对数-价格,没有控制混杂因素(即,混淆相关性和因果关系)。即使这种关系是“混乱的”,你已经可以看到一个负斜率:更高的价格导致更低的需求。这里的回归参数在θ≈—0.6 左右。

橙色线是 DML 结果的可视化,控制了潜在的混杂因素。请注意,斜率变得更陡,表明弹性需求更大(θ≈1.9)。您还可以观察到,这种关系变得明显不那么嘈杂,并且您可以看到价格的方差(x 轴上的线的范围)大幅减少,这是因为 DML 残差“解释”了这种变化的大部分。

5 讨论

与开头的例子类似,假设一个零售商目前以每件 5 美元的价格销售 100 件产品,成本为 2 美元。估计弹性为-1.9,零售商应该降低价格以获得更多利润。但是如果(有偏见的,天真的)估计是-0.6,他们就会提高价格。

在这个例子中,适当的因果推理推翻了推荐的决策,对零售商的利润有直接影响。混淆相关性和因果关系会让零售商损失很多钱。相比之下,使用精心设计的 DML 机制,零售商能够在价格变化发生之前自信地预测价格变化的影响。

本文旨在解释一个端到端的行业应用程序。你可以在的可运行笔记本中更详细地了解每一步。许多业务问题受益于类似的方法;我希望这是一个有用的例子。

为了进一步优化价格,零售商现在可能会转向异质治疗效果,即探索弹性差异。这也开启了一个问题,我实际估计的“*均治疗效果”是什么:我的训练数据中的产品组合是否代表未来的产品组合。我将在后续文章中探讨异质效应。

承认

感谢 Rima Rahal、Jonathan Haas 和 Paul Hünermund 对初稿进行了富有洞察力的讨论和评论。

参考文献/尾注

[1] Taddy,Matt:商业数据科学。麦格劳-希尔教育,2019。

[2]坎宁安,斯科特:因果推理:混音带。耶鲁大学出版社,2021 年。https://mixtape.scunning.com/introduction.html

[3]韦杰,斯特凡:统计 361:因果推理。斯坦福大学,2020。https://web.stanford.edu/~swager/stats361.pdf

[4]瓦里安,哈尔 r .:经济学和市场营销中的因果推理。美国国家科学院学报,2016 年 7 月。

[5]https://en.wikipedia.org/wiki/Price_elasticity_of_demand

[6]阿尔弗雷德·马歇尔:《经济学原理》。麦克马斯特大学经济思想史档案馆,1890 年。https://social sciences . McMaster . ca/econ/ugcm/3ll 3/Marshall/prin/prinbk 5 . htm

[7]第十六章:联立方程模型。《计量经济学导论:现代方法》,第 7 版。2019.

[8] Lee H,Aronson JK,Nunan D:对撞机偏差。偏见目录,2019。https://catalogofbias.org/biases/collider-bias/

[9] Chernozhukov,Victor,等:用于治疗和结构参数的双/去偏置机器学习。计量经济学杂志,2018 年第 21 卷。https://academic.oup.com/ectj/article/21/1/C1/5056401

[10]要了解线性对数回归确实可以估计弹性,请考虑以下情况:对数回归假设

对这个回归方程取相对于 P 的偏导数,你得到

[11]微软研究院:EconML。用于基于 ML 的异质治疗效果评估的 Python 包。https://github.com/microsoft/EconML

[12] Bach,p .,Chernozhukov,v .,库尔茨,M. S .,和 Spindler,m .:Double ml——Python 中双机器学习的面向对象实现,2021。arXiv: 2104.03220

数据科学家的因果推理:第 1 部分

原文:https://towardsdatascience.com/causal-inference-for-data-scientists-part-1-f97fa8614143?source=collection_archive---------14-----------------------

你不知道你需要的技术

这篇文章是两部分系列文章的第一部分,讨论了 Pearlian 因果推理的基本概念和数学。第 2 部分将关注一个使用 DoWhy 库的实际例子。如果您喜欢先从实现开始,当第 2 部分可用时,跳到第 2 部分,然后返回这里学习理论。

因果关系:由拍摄的照片在 Unsplash 上

*年来,澳大利亚推理经历了巨大的发展。这种激增与更广泛的数据科学(DS)的兴起同时发生,但它们在实践中仍然截然不同。虽然因果推理背后的科学受益于 Judea Pearl、Donald Rubin、Susan Athey 和许多其他人的最新工作,但他们发现的见解还没有进入主流 DS,尽管这些技术的实现很容易获得。许多 DS 从业者根本不知道或不在他们的工作流程中使用因果推理,这可能有几个原因…

  1. 进入因果推理的假设,如贝叶斯模型,可以从周日开始以六种方式进行切片、切块和辩论。(感谢我的 Linkedin 联系人吉诺·阿尔蒙多提供的这一见解)
  2. 人们认为相关性是自动因果的,它们本身就足够了。在你的工作场所找找看,你会惊讶它出现的频率。
  3. 因果推理被认为是困难的。我们不喜欢硬的。

这些观点都有不同程度的有效性,但最终都没有抓住要点。主要的一点是,虽然存在挑战,但我们手中有一套概念和技术,如果谨慎应用,将完全改变数据科学的实践和感知方式。我们可以利用领域知识进行可靠的推理。让我们先做一些准备来开始讨论。

什么是因果?

在本文中,我们将采用干涉主义的方法来定义因果关系。我们对什么是因果关系都有一个直观的概念,但是要用数学语言来表达,我们需要一些更正式的东西。

定义是,对于两个不同的事件 A 和 B,如果 A 的变化对应于 B 的变化,则 A 导致 B,其他都相等。

大多数因果推理都是为了确保“其他一切都是*等的”这一部分。还有其他类似的定义,围绕着哪一个是最正确的有激烈的争论,但我们将决定这一个,并继续进行。

我们如何建立因果关系?

在*代因果复兴发生之前,建立因果联系的黄金标准是随机实验。在很多方面他们仍然是。因此,让我们在随机实验的背景下讨论因果关系。

我们有一个我们想要测量的结果,名为 y。我们想看看操纵特定的治疗 X 是否会引起 y 的明显变化。在随机试验中,如药物试验,我们将从更广泛的人群中随机获得足够大的人的样本(使用功效分析)。参与者将被随机分配药物或安慰剂。然后,我们将测量安慰剂组和药物组的差异,这被称为治疗效果,可以通过多种方式完成(参见 cohen 的 d 或 CATE)。任何效应大小将仅来自治疗,而不是由于可能存在的任何其他因素或混杂因素**。**

随机分配确保“所有其他条件相同”在总体上是正确的。

真实的世界

现在我们来看因果推理中面临的主要障碍。我们并不总是有时间和金钱去做随机实验来建立因果联系。即使我们这样做,也可能不符合道德。我们最终可能只有一组观察数据,以及我们从观察中建立起来的一些假设。我们能用非随机化的数据来检验它们吗?答案是肯定的,这就是我们的新工具包发挥作用的地方。我们将使用的技术将获取我们的观察数据集,并将其转换为所谓的介入数据集,从中我们可以得出因果推论。这里的关键是数据本身不足以建立因果关系(见辛普森悖论)。我们需要更多有力的理由。

鉴于数据还不够,我们将绘制一幅世界的文字图,称为因果图,它编码了我们关于数据生成过程的假设数据生成过程是我们试图了解其动态的系统。这将有助于我们构建我们的介入分布,并检验我们的模型是否有效。

我们在模仿科学过程。我们从一个假设开始,然后我们用因果图来模拟世界在这个假设下的行为。最后,我们用数据来检验我们的模型,这可能支持或不支持假设。此外,我们进一步测试模型,看看它对变化、未说明的混杂因素和其他问题有多敏感。重复直到你的理论符合事实。

更深入

让我们定义几个术语…

****干预:主动做 X 导致 y 的变化。

例子:如果我推我的朋克兄弟,他会生气吗?如果我给一个人用药,会让他们好起来吗?

****反事实:如果我没有做 X,Y 还会发生吗?

例子:如果我没有推我的朋克兄弟,他会摔倒吗?如果没有给病人用药,他们会好转吗?

干预和反事实的推理反映了人类理解因果关系的正常方式。我们正在创造两个不同的世界,并比较两个世界的结果。如果我们有一个干预的案例,和它的反事实,我们可以建立因果关系。在一个随机实验中,我们在群体水*上已经有了这两个现成的例子。当分析的层次改变到个人时,我们就意识到我们试图解决的一个最基本的问题。我们发现我们有一个缺失数据的问题。我们手头没有反事实,因为个人的反事实并不存在。你不能同时接受治疗和未治疗。双胞胎研究接*了。幸运的是,我们有办法估计这种反事实,同时控制一切可能混淆我们分析的东西。请记住,我们试图保持所有其他*等,这就是为什么我们需要一个反事实。让我们深入数学来更好地理解发生了什么。

派生

当我们获得观察数据时,无论数据是离散的还是连续的,我们得到的都是概率分布。两种主要类型是联合概率和条件概率。任何上过基础概率课程的人都会涉及到这些话题,但它们为我们构建因果公式提供了基础。下面是两个数据分布。

观察和干预图

在左边,我们看到了观察模型,它显示了原始数据中变量之间的相互关系。根据我们对因果关系的定义,我们需要独立于其他因素,估计改变 X 对 Y 的影响。对于我们观察到的数据,我们无法使 X 的变化不对应于 Z 的变化,因此 X 的变化不表示 y 的因果变化。我们需要一种方法来理清 Z 对 X 的混淆效应,例如 P(X|Z) = P(X),或者换句话说,我们需要操纵观察到的数据以使两个变量独立。我们需要做图形手术。

右图显示了我们想要的状态,即手术后的状态。z 和 X 不相连,因此其中一个的变化不会影响另一个。这被称为d-分离**。而且由于 X 仍然在 Y 的上游,所以 X 的任何变化都会导致 Y 的因果变化,不管 X 是自发变化还是直接调整。**

假设

现在我们继续推导,允许我们将我们的观察数据分布转换成我们的干预数据分布。我们从两者之间的三个联系开始推导。我们用 p 表示我们的观察数据分布,用 Pₘ表示被操纵的干预数据分布。

链接 1

因为 Y 的引入效应在两个图之间保持不变,所以概率分布也是相同的。这是我们的第一个不变性链接。

链接 2

确定 Z 的过程不会因为去掉 Z 和 x 之间的联系而改变,这是我们的第二个不变性环节。

链接 3

在被操纵的模型中,Z 和 X 是 d 分隔的,因此是独立的(在后一个模型中,关于 Z 的信息并不能告诉我们关于 X 的任何信息)。根据链接 3,我们可以更进一步得到 P(Z)。

考虑到这些联系,我们从右边的因果图开始,定义我们的 do 操作符。我们想知道,给定我干预 X,用 do(X)表示,Y 的概率是多少。由此可见…

(根据定义)

接下来,我们扩展等式的右边来考虑 Z

根据全概率的定律,我们在 z 上取 P(Y|X)的加权*均值。这是我们控制 z 的影响的方法。这与控制混杂因素的逆概率加权和倾向评分加权技术相同。亚当·凯莱赫有一篇很棒的文章展示了等价性在这里,所以如果你有兴趣深入了解,一定要去看看。

接下来,我们使用 Z 和 X 的 d 分离原理来获得

最后,我们调用操纵分布和观测分布之间的不变性链接来得到

调整公式

使用最后一个表达式,称为调整公式**,我们现在已经定义了如何从干预前的观察数据中生成我们的干预分布 P(Y|do(X))。这是对介入分布的广义定义,适用于连续和离散病例。**

对于我们的药物试验示例,它是一个离散的二元结果,使用我们导出的因果表达式来估计治疗效果,我们可以将*均治疗效果(ATE)定义为

随机试验

因此,我们使用随机试验获得了与控制所有相关混杂因素(上面用 Z 表示)相同的结果。

顶部的第一项是观察到的治疗效果概率,第二项是反事实概率。假设 Z 代表 Y 和 X 的所有混杂因素,它们的差异确定了治疗 X 对结果 Y 的因果影响。请注意,Z 本身可以是连续的或离散的,这并不重要。配方中有一个漂亮的灵活性。

最终事项

这些是珀尔因果推理的基础。关于因果关系的其他讨论,请阅读鲁宾的潜在结果框架。如果你喜欢天才科学家之间的辩论,这个资源会让你开心。关于使用随机森林对高维数据集进行因果推理的应用,请参见苏珊·艾希的最新作品这里。Amit Sharma 和 Emre Kiciman 的一本很棒的介绍书可以在这里找到。最后,仔细阅读后门标准,这是因果推理的下一个重要步骤,可以在这里阅读。****

我们只是触及了将科学融入数据科学的强大概念的表面。我希望这有助于在实施之前建立理论。我也希望它引发了你的好奇心,让你想了解更多,并开始在工作中应用这些原则。本系列的第 2 部分将使用 DoWhy 软件包实际应用 Pearlian do 微积分解决医疗保健领域的一个因果问题。

敬请期待!感谢你的时间,上帝保佑你。

乐趣和利润的因果推理

原文:https://towardsdatascience.com/causal-inference-for-fun-and-profit-cb5f38601a5d?source=collection_archive---------21-----------------------

图片由来自 Pixabay 的 Michal Jarmoluk 拍摄

办公时间

科学在快速发展的初创企业中的挣扎

甚至在推出几个月后就雇佣了它的数据团队。我们的任务很简单:弄清楚我们是否在做正确的事情。公司的每个人都想知道产品是否为影响而优化,为了优化,我们需要数字:风险最小化,目标最大化。

“这是我们第一次做这样的事情。”我记得乔恩在我最后的现场公开表示不确定。该公司仍然不知道整个“数据科学”的事情。对伊文和我来说,这都是一种冒险。他对事情的发展很诚实。

“你觉得你能行吗?”

我毫不怀疑。“绝对是。”

一年半后,数据团队在组织结构图的变动板块之间崩溃了。

我错了。好几次。衡量影响——我们 T12 带来的好处——并不容易,我已经积累了这么多失败的赌注,我在拉斯维加斯比在硅谷更自在。但是,嘿,即使在核灾难的中心,你也会发现原子石玻璃,我学到的东西就像水晶一样。

今天,我们有工具和方法可以测量我们的影响,而真正的科学发现只有很少的负面影响和所有的正面影响。我会说的。

但是跳到最后一点也不好玩。一切都是为了旅程,记得吗?

一整个该死的井架

图片来自像素

过去,每个人都相信数据科学的炒作。从自我更新机器的大脑中汲取的定量见解,从海量数据流中进行的在线预测,对你甚至从未想过要问的高维度问题的答案——太空中漂浮着如此之多的承诺和宣传,以至于让你头晕目眩。

毫不奇怪,数据团队似乎是必备的。

但是团队需要工具来运作。我在 Even 的第一周,我越来越恐惧地意识到我们是在直接查询我们生产数据库的一个副本。像这样的数据存储针对单个表上的单行读取进行了优化,但是我们要对数亿行进行统计,并从模式的每个角落连接列。

我通常不得不在晚上启动一个查询,回家后相信它会完成,然后像拼花地板一样沉入磁盘,并在第二天分析它的结果。如果我早上错过了一列或一个关键的行子集,我会 **1。)**讨厌自己和 **2。)**在接下来的八个小时里被束缚手脚。

我们试图用一把铁锹来开采石油,但我们需要的是一整个该死的井架。

我的时间经常会转移到用快速编写的分析或立即有效的商业智能来追逐枝节问题,而度量的任务会被推后几周、几个月、几个季度。

然后奇迹发生了。一个才华横溢的全栈工程师变成了机器学习工程师变成了数据工程师,他的名字叫约瑟夫·阿特金斯-土耳其人把最后一个齿轮放进一台漂亮的机器里,这台机器每天储存我们所有的数据。突然之间,过去需要几个小时的查询将在几分钟内返回。我们改变了我们的工作流程、时间表,甚至我们对自己能力的看法。

我已经转了几个月的轮子,烧了几个月的钱,但是只需要一个数据工程师,我就可以开始工作了。

这将成为一个持续的主题:没有数据工程优先,数据科学将一事无成。

2:混杂变量和医院对撞机

每天都有几百万笔银行交易流经我们的系统。它们被解析、打包和丰富,使得它们比一个写着INSUFFICIENT FUNDS FEE FOR A $5.00 ITEM的字符串更有用。这种丰富与最终用户体验没有任何关系:我们保留它用于关键性能指标。

我们关注的两大标签?发薪日贷款和透支费。

假设是 Even 的按需付费功能 Instapay 远远优于收费高得离谱的流动性产品。因此,我们预计对这些产品的需求会下降。发薪日贷款和透支量是值得关注的明显数量。

我们跟踪了会员如何使用该应用程序,他们使用 Instapays 的频率,并使用这些结合了机器学习、正则表达式和决策规则的庞大交易丰富管道,我们最终发现—

没什么。

我们的问题从来都不是技术性的。这是认识论上的。

我的意思是。我们试图找出 Even——特别是 insta pays——对某些绩效指标的影响,对吗?先重点说一个:透支费。假设我们在任何时候看到高于*均水*的 Instapay 透支率,我们都会看到低于*均水*的透支率,下图说明了这种相关性:

玩具例子:当透支费率低于*均水*时,Instapays 高于*均水*。所有图表由作者提供。

这种相关性是否足以说明 Instapays 正在降低透支率?

不会。同样的相关性可能会发生,因为某些第三因素碰巧改变了这两者。例如,如果人们足够聪明地使用 Instapays,也足够聪明地关闭银行应用程序的默认透支保护设置,会怎么样?

有个混杂变量在进行中。

那不一定是世界末日。如果你对你的系统有一个详细的了解,你可以识别每个混杂因素和控制。在实践中,这只是意味着在混杂因素(“移动应用程序悟性”)保持相等的情况下,查看你的解释变量(Instapay 利率)和响应变量(透支费率)之间的关系。

如果你仍然看到所有的混杂因素都得到适当控制的关系,那就是因果关系的更好证据。我们没有衡量“手机应用能力”的变量,但我们可能有一个较弱的代理:年龄。

玩具示例:控制年龄。

所以。假设我们在控制了年龄因素后仍然看到了相关性。我们的工作完成了吗?我们证明了我们的产品有积极的影响吗?

同样,不。控制混杂因素是可行的,但就像我说的,你需要对世界上正在发生的事情有一个详尽的了解,以确保你已经考虑到了一切。队里没人认为我们有这种能力。在我们的头脑中,不管我们控制什么,模型看起来更像这样:

玩具例子:无限多可能的未知。

可能有未知的未知, U ₁, U联合国,潜伏在每一个地方。我们无法控制所有这些,因为我们不知道它们是什么。

事实上,试图控制世界上的一切会在其他方面绊倒我们。混杂变量的反向结构被称为碰撞器,其中一些变量同时受到你感兴趣的解释变量和响应变量的影响。当你像这样控制一个变量时,你会产生实际上没有意义的虚假关联。

这就是对撞机偏差,或者伯克森悖论。

1938 年,约瑟夫·伯克森博士因痛斥医院数据的统计分析而有幸以他的名字命名了整个现象。当时,临床医生已经全力以赴进行数据收集和分析,他们发现了疾病之间各种各样的简单关联。这是大数据 1.0,但问题是,就像现在一样:这些相关性有意义吗?

如果这些医生怀疑胆囊炎与糖尿病密切相关,他们中的一些人可能已经开始拔除胆囊,所以采取冷静、合理的方法是值得的。

让我们想象一个只有胆囊炎和糖尿病两种疾病的世界。任何一种都可能导致你去医院。

医院对撞机。

在这里,人们可以有几种行为方式。

  1. 他们只有糖尿病,症状变得很严重,需要去医院。
  2. 他们只有胆囊炎,症状变得很严重,需要去医院。
  3. 他们患有两种疾病,其中一种或两种都让他们感到不舒服,不得不去医院。
  4. 他们两种疾病都没有,或者症状不严重——所以他们只是呆在家里。

问题是:当你看医院的数据时,你完全忽略了最后一群人。而当你只关注前三组的时候,各种各样的恶作剧就发生了。

我们来思考一下,当两种疾病在一般人群中发生的可能性相等时,会发生什么?在下图中,这是从较大的组中切割出来的两个相同大小的圆。我们允许两者之间有一点重叠,以表示患有这两种疾病的人。

假设胆囊炎和糖尿病在普通人群中的发生率相等,有一点重叠。

现在让我们想想这些人是怎么死在医院的。

如果糖尿病和胆囊炎同样有可能送你去看医生,会发生什么?为了说明,我们将在每个疾病人群和“医院”人群之间画出相等的重叠部分。

在这种情况下,医院内的疾病重叠比我们在普通人群中看到的要少。

如果我们只关注医院人群,糖尿病患者患胆囊炎的可能性比普通人群低!反之亦然。仅仅一种疾病就足以让你通过这道门,所以它“解释”了其他疾病是一个因素。相对于潜在人群,这两者之间会有一个负相关

另一个例子呢,胆囊炎非常痛苦,但糖尿病的症状稍微微妙一些。好吧,现在所有这些胆囊炎患者都会争先恐后地去医院,但糖尿病患者更有可能呆在家里。

现在,这两种疾病在医院的重叠比我们在普通人群中看到的要多。

现在,医院里的大多数糖尿病患者有胆囊炎。我们看到了一种无中生有的正相关性。

伯克森意识到,即使这两种疾病在潜在人群中的发病率完全不相关,这些相关性也会显现出来。临床医生正在控制一台对撞机:在医院里。

所以。我们不能控制所有的事情,即使我们尝试了,我们也有诱发错误关联的风险。

这无疑给我们留下了某种样的小溪,我们需要找到一个桨。立刻。

3:电学课程

照片由 Pexels 的 Killian Eon 拍摄

团队在我们的思考中变得更加因果,现在专注于在成员加入我们的服务之前研究来自的指标。事实证明,当会员通过我们使用的银行数据 API Plaid 连接到我们的应用程序时,他们实际注册前两年的交易将从他们的银行账户中扣除。这给了我们一个前事件数据的宝库,我们可以用来与后事件数据进行比较。

因此,我们构建了银行交易的标准化时间表,*衡于一个*均的激活日期:180 天之前到 180 天之后。

这导致了我经历过的最严重的职业崩溃——但也是最有力的证明了 Even 的价值观不仅仅是纸上谈兵。

对交易时间表的中期分析揭示了一个令人难以置信的结果:在会员注册 Even 后,发薪日贷款频率会下降。当然,有一点奇怪的是:我们会看到他们上升,直到注册日期。

我们的误导图的玩具复制品:我们看到在注册 Even 之前,有发薪日贷款交易的会员有增加的趋势,但之后有减少的趋势。

也许是逆向选择?如果会员陷入困境,陷入发薪日贷款陷阱,但后来求助于 Even 来帮助他们摆脱困境,这或许可以解释这种现象。

但那只是一个普通的故事,完全没有事实根据。

然而,不知何故,这些数据流传开来。那还是早期,甚至还没有权威信息的单一来源。懒散的经理们的嗡嗡声、私人渠道中的即兴引用、电子邮件、午餐时间的谈话以及厨房柜台周围的聊天,将这个故事融入了公司意识,就像黑咖啡中的阿斯巴甜一样。

当然,那时我们已经说服自己这是错误的。发薪日贷款交易并不是唯一显示这种驼峰模式的交易:涉及亚马逊和麦当劳的交易也显示了同样的情况。

示例图:麦当劳和亚马逊的交易呈现出与我们看到的发薪日贷款类似的模式。

结果是一个神器。但是当我们确定这是错误的时候,它已经在我们网站的首页上了。一个公司的价值观——“寻找和提升真相的渴望”——现在与我们的底线以及更好的媒体和更多销售的承诺相抵触。

回溯数据会打击我们的信誉,降低我们的竞争力…

但这也是正确的做法。

数据团队和我们交谈过的每个人都提出了抗议,最后我们当时的数据负责人——胡安·曼努埃尔·孔特雷拉斯——写了一份清晰、冷静的备忘录,讲述了哪里出了问题,我们不知道什么,以及为什么我们对我们网站上的数据如此不安。这就够了。

乔恩在一次全体会议上刷新了记录,这个误导性的数据在几天内就被删除了。但并不全是阳光和彩虹。数据团队必须认真审视自己,确保不会再发生类似的事情。

我认为,我们的根本问题之一是相信数据是“原始数据”。我们看到一个名为“transaction”的数据库实体,并相信它的创建日期是创建它的想法的时间,而不仅仅是我们的记录。我们看到了记录的消失,并相信这个东西本身已经消失了,而不是简单地通过小故障、停用或 API 不作为而变得模糊不清。

作为一个团队,我们仍然没有真正理解数据从来不是被动观察的:它总是被获取。如果不理解捕获行为背后的机制,我们就没有权利提取底层细节并发布高层结果。

我有史以来最喜欢的一段话来自 1906 年的《物理理论的目标和结构》,当它提到即使感觉像是自然的原始数据的概念,如“力”或“电压”,也根本不是原始的时,它击中了要害。

走进实验室;走*这张堆满了各种仪器的桌子:一节电池、用丝绸包裹的铜线、装满水银的容器、线圈、一根带镜子的小铁棒。一个观察者将装有橡胶的金属杆插入小孔中;铁振荡,通过绑在它上面的镜子,发送一束光到赛璐珞标尺上,观察者跟随光束在其上的运动。

在那里,毫无疑问,你有一个实验;通过光点的振动,这位物理学家仔细观察铁片的振动。现在问他在做什么。他是否会回答:“我正在研究承载这面镜子的铁片的振动”?

不,他会告诉你他在测量一个线圈的电阻。

如果你感到惊讶,问他这些词有什么意思,它们与他感知到的和你同时感知到的现象有什么关系,他会回答说你的问题需要一些很长的解释,他会建议你学习电学课程。

一旦你学会了定义电阻和电动势是什么以及它们是如何产生的详细理论,你就只能参考这些密集的概念。

在我们的例子中,只有当我们通过蜿蜒的服务器逻辑,跨越 GRPC 障碍,从定义到群体到变异,直到最后它穿过数据访问层并进入永久内存,跟踪 protobuf 模型时,我们才能真正理解记录的含义。

我们必须学习电学课程。

4:被混沌猴碾压

图片来自 Pixabay 的 Vicki Lynn

在发薪日贷款传奇和 Even 的真相危机之后,我们得到消息,一个潜在客户将在几个月内推出——并且有一个特殊的转折。他们愿意让我们在他们的员工中进行该产品的随机对照试验。

我们谈论的不仅仅是一个功能变体,或者一个特定蓝色的 A/B 测试。我们将向 50%的潜在会员展示这款应用。我们会允许他们正常下载,询问他们是否想参加一项受控实验,然后在最后一刻将他们随机分为治疗组和对照组,将选择偏差的威胁挤压成一个纯粹的建议。

对照组会得到一个除了说谢谢之外什么也不做的应用程序,并倒计时直到研究期结束,而治疗组将获得全部功能。两组的参与者都会得到时间补偿,到最后,我们最终会知道该产品对他们的财务健康有什么样的影响。

在我多次尝试观察研究和奇特的计量经济学失败后,这次进行直接干预的机会就像看到一艘在太*洋上漂流了几个月后的船。一个孤独而遥远的希望,但这是一个我必须投入全部精力的希望。

它最终会失败。

但这将是我职业生涯中最有价值的几个月。我们的工程总监阿希姆和奥利维亚在我身上冒了一次险。如果我努力构建实验和这种新的“控制应用”体验,他们会确保我有合适的导师来照看我,并确保我不只是在代码库中乱闯,不受控制。

他们不用找很远。迈克尔和钱宁立即主动贡献了他们的时间和精力,向我展示了如何编写可理解的、有据可查的、高性能的代码。 Emily 给我上了一堂 React Native 的速成课,教我 Even 内部组件和流程逻辑的细微之处。

我们的设计负责人马克走上前来,在可能不到一天的时间里,为整个体验画出了蓝图。我们的首席合规官斯瓦蒂与 UX 研究公司合作,成为我们自己的内部审查委员会,确保我们对实验参与者尊重、仁慈、公正。

我觉得我需要在这里澄清一些事情,因为它仍然不是很明显。

这不是公司层面的指令。

没有 OKR 我们试图击中,没有人的经理告诉他们该怎么做。我提到的每一个人都知道我需要帮助,最终这种努力会让我们了解到更多关于 Even 能力的真相。这就是全部的代价。

我真的不知道该如何表达我的感激之情。但我想我不应该感到惊讶,确切地说。我们在雇佣合适的人上下了很大功夫。我经常想当然地认为我周围都是对真相好奇的慷慨的人们,但是现在这个事实是不可避免的。

卡特,我们当时的会员顾问主管,主动询问他的团队如何参与其中。贝基已经在公司的各个方面承担了大量的工作,她主动要求管理系统,以确保研究参与者按时得到报酬。

这一切都在一起。当我意识到获得一个好的样本量可能要花费我们 10 万美元的参与者报酬时,有一个短暂的大汗淋漓的时刻,但在与埃文和昆腾的五分钟会议中,我得到了一个简单的“是的,似乎值得”,笔记本电脑啪的一声关上,以及一句祝你好运的简短话语。

尽管在客户整合方面出现了一些小问题,但事情感觉像是在蹒跚前行。

然后新冠肺炎封锁了全国,发射计划告吹。

我们执行得很好,但致命的缺陷是孤注一掷。虽然我经常思考,但我仍然不确定这里的正确策略应该是什么。一方面,这个机会如此之大,以至于我觉得应该尽快加大赌注。另一方面,我们应该更好地调查我们与该客户成功整合的可能性,因为这是整个努力的关键。

像这样的研究,有这么多移动的部分,总是有不成功的风险。但是向前看,采取没有单点失败的策略是明智的。

就像一个好的软件一样,科学必须是容错的。

5:随机化 Z 的禅

图片作者。

执行产品实验要容易得多,因为它不涉及向全体员工展示功能。当我们巩固了我们作为员工福利的地位时,即使有一个很好的系统来确保知情同意和补偿,干预的伦理也变得有点紧张。

我们可以更快地做那些对制造伟大产品至关重要的实验。

像威利这样的设计师运行着他们自己庞大的研究项目,并且总是在思考如何让事物更容易理解和使用。产品经理指定量化的结果来证明一个发布是否成功,或者是否需要重组。这使得尝试不同金额来优化付费推荐和会员增长变得更加简单。或略有不同的追加销售和推送通知,以推动产品的使用。或者一个额外的入职审查将储蓄采用率提高了 31% 。

这些是我们有设备和胃口的东西,我认为我们不能做类似的事情来测试企业的核心价值主张或我们的经济学基本理论是可悲的。

但是等等,等一下——我们不能吗?

让我们重温一下我们之前看到的因果效应的混淆图。这个更普通一点。我们有一些未知的 U 混淆变量,它以某种不确定的方式影响 Instapay 率和透支率(可能是减少或增加)。

我们仍然想知道 Instapay 对透支率的影响有多大——是零、负还是正。

我们也有我前面描述的混淆问题,但是如果我们添加一个特殊的节点会怎么样呢?

Z 这是我们知道的可以改变 Instapay 费率的任何策略(而且仅仅是 Instapay 费率)。例如,提醒会员更明智地使用 Instapays 的推送通知可能会减少使用量。

如果我们随机将 Z 应用于我们的人口,我们将知道 Z 与 Instapay 之外的一切都不相关,只通过对 insta pay 的影响与透支率相关。

这对我们有什么帮助?

好吧,让我们做标准的计量经济学的事情,并执行一些回归。我们可以得到 Z 对透支率的线性关系,得到线Z→透支。同理可以得到 Z→Instapay

这些关系只是线条(让我们假设我们的 Z 有很多好的层次,让我们画出一个整洁的层次)。

示例数据:Z 与即时支付和透支的相关性

从这个示例数据中,我们知道,随着 Z T21 的上升,Instapays 下降。与此同时,透支利率随着规模的扩大而上升。如果我们关于 Z 的假设是正确的,并且 Z 只通过它对 Instapays 的作用影响透支率,这一定意味着 Instapays 对透支有某种抑制作用。这是一个因果影响,尽管存在混杂变量,我们还是发现了这个影响。

让我们用更精确的数学术语来进行推理。我们可能会说:行Z→透支应该和Z→Instapay→透支一样。这意味着Z→透支可以表示为复合线性回归。我们观察到的数据给了我们足够的信息来解决因果insta pay→透支关系,通过对该表示做一些线性代数。

就是这样。做个 A/B 测试,解几个线性方程,就有了。

因果推理的秘密一直在我们面前。

我们已经习惯于以高速度做的每件事都可以转向核心研究,并告诉我们我们的产品实际上让我们沿着我们的使命走了多远。随机推送通知、模态追加销售、通过聊天的热情欢迎、入职页面——它们都是因果王国的关键。

因为我们可以同时运行如此多的项目,所以即使一些项目失败了也没关系:它们可以在另一个时间、另一个地方,与另一个客户一起通过微小的调整重新启动。流行病、经济衰退或交易失败都无法阻止我们。

我们只需要执行。

我们也是。

如果你认为工程项目是学习世界上一些新的和基本的东西的机会,甚至可能是你的地方。我们在 招聘

对于使用二元变量和随机化的 Z 的无假设分析,因果推断的途径比“复合线性回归”方法稍欠直观,但 仍然绝对可行 并且非常非常酷。

数据科学中的因果推断:A/B 检验&有协变量调整的随机试验

原文:https://towardsdatascience.com/causal-inference-in-data-science-a-b-testing-randomized-trials-with-covariate-adjustment-f5a24bd023b3?source=collection_archive---------34-----------------------

效率&A/B 测试中条件协变量调整的统计功效增益&随机试验

照片由卡斯帕·卡米尔·鲁宾在 Unsplash 上拍摄

1:背景和动机

因果推理是一个涉及几个领域的领域,并引起了包括统计学家、数据科学家、机器学习科学家和其他计算研究人员在内的广泛从业者的兴趣。

到目前为止,我已经写了几篇关于因果推理空间的方法/主题的文章。其中包括:

  • 因果推理中的有效抽样框架
  • 因果推断中的双重稳健估计技术
  • 半参数结构嵌套模型的 G-估计
  • 存在 M 偏差结构时因果效应的恢复
  • 在 AB 试验/随机试验中对边缘结构建模的需求,用于信息性审查调整
  • 多重比较的有效推理覆盖率

这篇文章涉及 A/B 检验(又名随机试验)和通过协变量调整的统计有效的条件抽样估计规范。即使在没有混杂因素的情况下,也为调整感兴趣结果的强预测因素的益处提供了数学上严格的论证和计算模拟。

该作品的内容如下:

作者图片

2:具有连续结果的简单理想化 A/B 测试

我们将首先探讨在假设感兴趣的结果是连续的情况下,在 A/B 测试框架中协变量调整的好处:

2.1:玩具示例的规格

让我们假设一个简单的“理想化”A/B 测试,带有随机二元干预和连续正态分布结果 Y 。“理想化”是指:

  • 完美数据测量
  • 完美的受试者依从性,无交叉干预
  • 没有失访或丢失数据,因此没有信息审查

(关于受试者不依从和信息性审查的调整方法,请见 见我的 关于信息性审查和边缘结构建模)

与上述理想化 A/B 测试相对应的边际因果 DAG(在零值下)如图 1 所示。

作者图片

在上面的空因果 DAG 中,我们有二元介入和连续结局 Y 。干预是随机化的,因此没有箭头进入。但是请注意,我们在集合***【L】中有一组附加变量,带有指向结果 Y 的箭头。集合 L 中的变量是结果Y 的直接原因(即预测因素),它们独立于随机干预而不是通过随机干预来调节。***

对于有随机试验和 A/B 试验因果 DAG 经验的读者来说,在图 1 的DAG 中设置 L 可能会显得奇怪。有人可能会问“如果干预是随机的,那么干预和结果应该是图上唯一的变量?这是随机研究,不是观察研究?setL*中的附加变量从哪里来?”*****

这激发了关于“完全”因果 Dag 的重要讨论点。当我们指定一个因果 DAG 并判定图是“完整的”并且“所有的变量都在图上”时,我们具体指的是什么?嗯,具体来说,我们的意思是:

  • 关于我们详细说明的科学上著名的感兴趣的问题,为我们的问题构建和恢复无偏抽样估计量所需的一组充分的变量在图上

重要的是要记住,在因果 DAG 上总是有比图示更多的变量。在实践中,我们经常只是形象地展示足以回答我们问题的变量。例如,在图 1 的因果 DAG 中,理论上有更多的变量在两个方向上无限延伸:**

  • 集合 L 中变量的直接原因的变量,以及这些变量的直接原因,以此类推
  • Y 的直接后代的变量,以及这些变量的直接后代,等等

为了恢复干预对结果的因果效应的无偏估计,我们只需要变量Y 。但是,这并不意味着 set L 中的变量不是真实存在的。****

对于我们感兴趣的问题以及本文的主题,我们将清楚为什么选择在我们的因果 DAG 中以图形方式显示集合 L 中的变量。还是那句话,我们不需要包含 L 来恢复一个AY 因果效应的无偏估计。但是从推理覆盖和统计功效的角度来看,包括*对我们是有益的,我们很快就会看到。***

2.2:因果效应估计的“标准”边际抽样估计量

让我们具体说明在最简单的随机试验或玩具问题的 A/B 试验中使用的“标准”边际抽样估计量。

同样,从图 1 中的因果 DAG 开始:

作者图片

作者图片

作者图片

2.3:因果效应估计的条件抽样估计量

作者图片

图 2 中,我们有与图 1 中相同的因果 DAG,除了我们现在对集合 L 进行调节。注意,我们仍然对恢复干预对结果的*均因果效应的无偏估计感兴趣。****

作者图片

作者图片

2.4:抽样方差和统计功效的差异

作者图片

作者图片

作者图片

作者图片

作者图片

作者图片

3: 具有二元结果的简单理想化 A/B 测试

现在,让我们在假设感兴趣的结果是二元的情况下,探讨 A/B 测试框架中共变量调整的好处。由于优势比的不可压缩性,我们正在分别处理二元结果案例。关于不可压缩性的详细讨论, 参见 Miguel Hernan 和 James Robins 的《因果推论:如果 会怎样》一文中的第 4.3 点。

3.1:玩具示例的规格

让我们假设一个简单的“理想化”A/B 测试,带有随机二元干预和伯努利分布结果**

与上述理想化 A/B 测试相对应的边际因果 DAG(在零值下)如图 3 所示。

作者图片

在上面的空因果 DAG 中,我们有二元干预,二元结果 Y ,以及协变预测结果中的集合。请注意,上面的 DAG 与 2.1 节中的图 1 几乎相同,除了感兴趣的结果 Y 是二进制而不是连续的。******

3.2:因果效应估计的“标准”边际抽样估计量

让我们具体说明在最简单的随机试验或玩具问题的 A/B 试验中使用的“标准”边际抽样估计量。

再次从图 3 中的因果 DAG 开始:**

作者图片

作者图片

作者图片

3.3: 因果效应估计的条件抽样估计量

作者图片

作者图片

作者图片

3.4:抽样方差和统计功效的差异

作者图片

作者图片

4.计算模拟

下面是第 2 节(连续结果病例)和第 3 节(二元结果病例)中介绍的理想化随机试验的 Python 计算模拟。研究了有和没有协变量调整的*均因果效应差异的无偏估计的恢复,显示了有协变量调整的统计效率增益:

让我们导入我们需要的库:

接下来,我们模拟随机试验的函数,包括有无协变量调整的连续/二元结果,以及功效计算:

在连续结果情况下运行模拟:

在二元结果情况下运行模拟:

从上面的结果中,我们可以看到,在连续和二元结果情况下,协变量调整分析与未调整分析相比,在功效方面有效率增益。

以上计算模拟的完整代码/笔记本,请看下面的 github 链接

5.总结和结论

这总结了我们对协变量调整的 A/B 检验的推导和计算模拟,以及从统计效率的角度来看这样做的好处。我鼓励任何发现上述材料有见地的人创建自己的模拟示例,利用我的代码作为起点,并自己进行实验!

如果你想了解更多关于因果推理的方法和注意事项,我会推荐哈佛大学 Miguel Hernan 和 Jamie Robins(我以前的两位教授)的教科书“因果推理:如果会怎样”,加州大学洛杉矶分校 Judea Pearl 的教科书“因果关系,斯坦福大学 Daphne 黑仔和耶路撒冷希伯来大学 Nir Friedman 的教科书概率图形模型:原理和技术,以及加州大学伯克利分校 Mark van der Laan 和 Sheri 的两本关于目标最大似然估计的教科书这些都是很棒的文章。我计划在未来写更多关于因果推理的深度文章。****

因果推断:如果会怎样

因果关系

概率图形模型:原理和技术

目标最大似然估计

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在 LinkedIn 上与我联系,并在 Medium 上 关注我的更新!

数据科学中的因果推理:通过倾向评分调整的条件独立性

原文:https://towardsdatascience.com/causal-inference-in-data-science-conditional-independence-via-propensity-score-adjustment-bbe6d70e2a5?source=collection_archive---------19-----------------------

倾向分数的说明和证明,并附有计算模拟

穆罕默德·拉赫马尼在 Unsplash 上的照片

1:背景和动机

因果推理是一个涉及几个领域的领域,并引起了广大从业者的兴趣。这些人包括统计学家、数据科学家、机器学习科学家和其他计算研究人员。

到目前为止,我已经写了几篇关于因果推理空间的方法/主题的文章。其中包括:

  • 数据科学中的因果推理:高效的抽样框架&设计
  • 数据科学中的因果推断:G 方法的双重稳健估计
  • 数据科学中的因果推理:结构嵌套模型的 G 估计
  • 数据科学中的因果推理:A/B 测试和边际结构建模的需要
  • 数据科学中的因果推理:具有混杂调整的 M 偏差的结构
  • 数据科学中的因果推理:多重比较的有效推理覆盖
  • 数据科学中的因果推断:A/B 检验&带协变量调整的随机试验

这篇文章特别关注关于倾向得分的公式和证明。

作为一个玩具示例,让我们假设我们有一个二元干预 A ,连续结果 Y ,以及协变量矢量L,它们具有以下因果结构(在 AY 没有因果影响的零假设下):

作者图片

让我们假设我们对恢复对结果 Y 的干预 A 的*均因果差异的无偏估计感兴趣:

作者图片

从上面的因果 DAG 可以清楚地看出,干预 A 和结果 Y 是以向量 L 为条件的 d 分隔。因此,通过因果马尔可夫假设,干预 A 和结果 Y 独立于向量 L

这种情况下的倾向得分是以“原因” L 为条件的干预概率 A=1 :

作者图片

在观察环境中,通过仅调节倾向得分来恢复干预 A 对结果 Y 的因果效应的无偏估计的能力在分析和数字上都明显有利。在有些情况下,给定研究中的干预 A 和结果 Y ,可以用比直接在结果模型中包括所有所需协变量 L 更高的数值稳定性来估计倾向得分。通过标量倾向得分的条件独立性也提供了在倾向得分的分级层内匹配干预臂的机会,以实现条件独立性并恢复感兴趣的因果效应。在协变量 L 的大向量的情况下,在由于稀疏性和小样本量而不可能在向量 L 的单个层内匹配的情况下,在倾向得分的层内匹配干预臂可能是可行的。

在这篇文章中,我们将表明,在给出的玩具问题的因果结构下,干预 A 和结果 Y 不仅是条件独立的给定向量 L ,而且是条件独立的,仅给定倾向得分本身。

这篇文章的目录如下:

作者图片

说到这里,让我们开始吧。

2:通过倾向得分证明条件独立性

2.1:玩具示例的说明和倾向得分

让我们再次具体说明我们的玩具例子:

假设我们有二元干预 A ,连续结果 Y ,协变量的向量 L 具有如下因果结构(在 AY 没有因果影响的零假设下):

作者图片

同样,假设我们对恢复干预 A 对结果 Y 的*均因果差异的无偏估计感兴趣:

作者图片

作者图片

作者图片

我们的目标是证明:

作者图片

2.2:倾向分数证明方法

让我们来看看下面的可能性:

作者图片

上面我们有概率 A=1 取决于倾向得分和结果 Y 。如果事实上情况是 AY 独立于倾向得分,那么上面的概率因此决不是结果 Y 的函数。

因此,如果我们可以证明上述概率绝不是结果 Y 的函数(即除了某个 f( Y )之外的任何函数),那么我们已经有效地证明了干预 A 和结果 Y 在给定倾向分数的情况下必须是条件独立的:

作者图片

2.3:复习迭代期望定律

在我们给定倾向分数的条件独立性证明中,我们将在条件期望上利用期望的迭代法则。

作为复习,我们将证明以下等式:

作者图片

注意,在下面的证明中,我们假设 XYZS 都是离散随机变量。在连续随机变量的情况下,证明将类似地遵循在所讨论的随机变量的支持上的积分,而不是和。

作者图片

2.4:正式证明

现在让我们进行我们的正式证明,即干预 A 和结果 Y 确实是以倾向得分为独立条件的:

作者图片

利用期望的迭代法则,我们将在向量 L 上指定附加条件的内部嵌套期望。

作者图片

让我们来审视一下内心的期待。我们有以倾向分数为条件的预期干预值 A ,结果 Y ,向量L。注意,倾向得分完全是向量的函数,并且在这个意义上是 L 的“更粗糙”版本。假设 L 已经存在于条件语句中,倾向得分没有添加额外的信息,因此可以从预期中删除:

作者图片

我们现在有:

作者图片

让我们再次审视内心的期待。我们有干预的期望值 A 以结果 Y 和向量 L 为条件。回想一下空值下的因果 DAG,根据定义,干预 A 独立于结果 Y 以向量L为条件:

作者图片

因此,根据定义,outcome Y 不会向内部条件期望添加额外的信息,并且可以被删除:

作者图片

因此,我们有:

作者图片

我们再次审视内心的期待。我们有期望的干预值一个条件向量 L 。请注意,根据定义,这种预期是我们的倾向得分:

作者图片

因此,我们有:

作者图片

在证明的这一点上,我们有了以倾向得分和结果 Y 为条件的倾向得分的期望值。以自身为条件的倾向得分的期望值实际上等同于恢复常数的期望值(根据定义,常数本身就是常数)。假设我们以一个常数为条件,在这种情况下,我们也以结果 Y 为条件的事实是不相关的:

作者图片

因此,我们有:

作者图片

作者图片

3:计算模拟

我们现在将在 Python 中进行计算模拟,通过调节倾向得分来研究二元干预 A 对连续结果 Y 的因果效应差异的无偏估计的恢复

  1. 创建一个具有真实因果 DAG 的模拟数据集,如下图图 1* 所示,真实因果效应差 AY 为 2.3*
  2. 通过对结果模型中的全向量 L 进行调节,恢复因果效应差异的无偏估计
  3. 估计倾向得分,并通过仅调节结果模型中的倾向得分来恢复因果效应差异的无偏估计

让我们从加载我们的库开始:

,一个模拟数据集的函数:

…以及单变量、多变量和倾向评分方法的函数:

指定了我们的函数后,我们就可以进行计算模拟了。

让我们从恢复模拟数据集开始:

让我们以干预作为唯一输入,对结果模型进行单变量回归:

如上述结果所示,A 对 Y 的因果效应差异估计为-3.1027。这显然是一个有偏差的估计,因为我们知道真正的因果效应差是 2.3。鉴于我们玩具问题的因果结构,这一发现也并不令人惊讶(如图图 1* 所示)。我们知道 A 和 Y 不是边际独立的。*

现在让我们执行结果模型的多变量回归,以 A 和矢量LT5 为条件:

如以上结果所示,现在估计 AY 的因果效应差为 2.3022。这似乎是真实因果效应差异的无偏估计。给定 AY 在向量 L 上是 d 分离的条件,这一发现同样不令人惊讶。

*现在让我们看看我们是否可以复制相同的结果,但是通过仅将结果模型限制在倾向得分上,而不是全向量 L 😗

如上述结果所示,A对 Y* 的因果效应差估计为 2.3059。这也是真实因果效应差异的无偏估计。*

以上计算模拟的完整代码/笔记本,请看下面的 github 链接

4.总结和结论

这总结了我们的推导和利用倾向评分模型的计算模拟。我鼓励读者使用我的代码(通过上面的 github 链接)作为起点,并创建自己的模拟来进行实验。

如果你想了解更多关于因果推理的方法和注意事项,我会推荐哈佛大学 Miguel Hernan 和 Jamie Robins(我以前的两位教授)的教科书“因果推理:如果会怎样”,加州大学洛杉矶分校的 Judea Pearl 的教科书“因果关系,斯坦福大学的达芙妮·黑仔和耶路撒冷希伯来大学的 Nir Friedman 的教科书“概率图形模型:原理和技术,以及加州大学的 Mark van der Laan 的两本关于目标最大似然估计的教科书

因果推断:如果会怎样

因果关系

概率图形模型:原理和技术

目标最大似然估计

一如既往,以后还会继续写类似的小品。请 订阅并关注我在LinkedIn 上的更新!

数据科学中的因果推理:多重比较的有效推理覆盖

原文:https://towardsdatascience.com/causal-inference-in-data-science-valid-inferential-coverage-with-multiple-comparisons-750e9e3f0259?source=collection_archive---------32-----------------------

FWERFDR 上限程序的数学严格推导和计算模拟

照片由埃米尔·佩龙在 Unsplash 拍摄

1:背景和动机

因果推理是众多从业者感兴趣的领域,包括统计学家、数据科学家、机器学习科学家和其他计算研究人员。关于随机和非随机环境中因果效应位置参数的无偏估计的恢复,我已经写了几篇文章,包括:

  • 因果推理中的有效抽样框架
  • 因果推断中的双重稳健估计技术
  • 半参数结构嵌套模型的 G-估计
  • 在存在 M 偏差结构的情况下恢复因果效应
  • 在 AB 试验/随机试验中对边缘结构建模的需求,用于信息性审查调整

在这篇文章中,我们将重点转移到因果效应估计的推理覆盖的有效估计。具体来说,我在这里提供了一个相当严格和数学支持的多重测试问题的介绍,这是特别重要的大规模多终点分析。

让我们用一个简单的例子来说明多重测试问题:

回想一下,在假设检验框架中,当一个无效假设被拒绝,而另一个假设被接受时,就会出现第一类错误,但这是在无效假设事实上为真的情况下。理想情况下,我们希望用一个阈值来“控制”第一类错误发生的概率。我们把这个阈值称为α*。*

现在假设分析有两个结果终点。我们需要进行两个独立的假设检验。让我们假设这两个假设检验是相互独立的。我们为两个测试中的每一个指定单独的 I 型误差阈值 a =0.05:

作者图片

问题是,如果我们的两个测试中的两个各自的无效假设事实上都为真,那么两个假设测试中的 至少有一个 产生“统计显著性结果”(即 p 值≤ a )的概率有多大,从而导致我们拒绝该测试的各自的无效假设,而选择另一个测试:

作者图片

尽管我们将每个个体假设检验控制在个体 I 型错误阈值= 0.05,但 FWER 几乎是该阈值的两倍( FWER =0.0975)。**

随着被研究的单个测试数量的增加,这种现象变得越来越严重。假设所有感兴趣的测试都是独立的,如果我们有 14 个感兴趣的假设测试(实际上都是空的),每个假设测试都有一个测试特定的第一类错误阈值 a =0.05,那么 FWER 就变得不比掷硬币好( FWER ≈0.512):

作者图片

这个问题与因果效应的有效估计有什么关系?在随机和非随机分析的因果推断中,研究多个终点和/或多个感兴趣的结果可能非常常见。

假设我们是一家制药公司,正在测试一种新药对几个感兴趣的拟议结果的因果影响。不为公众所知的是,这种新药是一种“糖丸”安慰剂,对任何实质性相关的医疗结果没有真正的因果关系。假设我们偷偷意识到了上面的数学现象,我们特意提出了 100 个我们感兴趣的不同结果,以增加我们获得 FDA 药物批准的可能性。如果在个体水*α阈值 a =0.05 下进行每个假设检验,从概率上讲,我们实际上可以保证产生至少一个具有统计显著性的检验,即使所有的检验实际上都是无效的。这被通俗地称为“钓 p 值”或“p 黑客”。我们只是不断地进行越来越多的测试,直到我们“发现”一个具有统计学意义的结果,并错误地认为它是一个“重要的发现”。在分析中,这是一个不受欢迎的动机。我们需要一种数学上严格的方法来防止这种激励,并调整我们的结果。**

在本文中,我们将介绍两个通用框架来调整多重比较问题:

  • 家族错误率( FWER )
  • 错误发现率( FDR

并且以一种数学上严格的方式将涵盖不同的方法来上限化 FWER 和/或 FDR 。我们也将进行一个计算模拟来进一步检验这些方法在实际应用中的效果。

这篇文章的目录如下:

作者图片

2: 家庭式错误率(FWER)

2.1:FWER 的数学规范

让我们举一个玩具的例子:

作者图片

作者图片

2.2: Bonferroni 程序

作者图片

作者图片

2.3: Sidak 程序

作者图片

作者图片

2.4:霍尔姆-邦费罗尼(HB)降压程序

作者图片

作者图片

2.5:霍尔姆-西达克(HS)降压程序

作者图片

作者图片

2.6:霍赫伯格升压程序

作者图片

2.7:排列程序

3:错误发现率(FDR)

3.1:FDR 的数学规范

让我们回到我们的玩具例子:

作者图片

作者图片

3.2: Benjamini-Hochberg(波黑)升压程序

作者图片

3.3:Benjamin-Yekutieli(BY)升级程序

作者图片

4:简短的旁白

4.1: 负相关假设检验

在我们对 FWERFDR 控制技术的讨论中,我们提到了感兴趣的统计测试的依赖结构。我们的一些控制技术在任意依赖结构下是有效的,而另一些只在独立或正相关结构下有效。然而,在实践中,除非我们使用单侧检验技术来恢复特定检验的 p 值,否则负相关检验并不值得特别关注。

为了理解为什么会出现这种情况,让我们检查一下我们所说的“相关测试”是什么意思。重要的是,“假设检验的相关性”不一定等同于“变量的相关性”或“数据的相关性”。例如,如果我们认为两个统计测试“正相关”,我们规定如果我们已经进行了其中一个统计测试并发现它产生了一个具有统计显著性的结果,那么剩余的统计测试产生一个具有统计显著性的结果的条件概率 比其相应的所述结果的边际概率 大。回想一下,对于双边统计推断测试,如果测试统计量在其零样本下的抽样分布的任一侧足够极端,我们认为该测试具有统计显著性。也就是说,如果两个检验中的“变量”或“数据”是负相关的,并且其中一个假设检验产生了具有统计学意义的结果,这就告诉我们,另一个假设检验有很大的概率产生一个极端的检验统计量,但是在各自的抽样分布的另一侧处于零。因为我们进行的是双边假设检验,这个足够极端的检验统计量导致了一个小的具有统计显著性的 p 值,从而导致了两个正相关的检验,即使这两个检验中的数据是负相关的。

在双边检验的情况下,两个检验呈负相关意味着如果我们完成了其中一个统计检验并发现它产生了具有统计意义的结果,则剩余的统计检验产生具有统计意义的结果的条件概率低于相同结果的相应边际概率。如果你仔细思考前面的陈述,你会发现这是一个奇怪的场景。很难假设一个真实世界的用例会发生这种情况。

因此,如果我们专门进行双边检验,负相关检验的合理可能性很低,不必特别关注。然而,在单侧测试的情况下,当选择 FWERFDR 调整程序时,应仔细权衡负相关测试的可能性。

4.2: 阿尔法支出

接下来,我们将讨论“阿尔法支出”的概念。我发现在 FWER 的上下文中解释这个概念最有意义。

让我们假设我们是在不相关测试的 Sidak 程序所需的假设下工作的,但是只有两个感兴趣的测试:

作者图片

作者图片

对于阿尔法支出,把我们的 FWER 想象成一个货币金额。我们可以把这笔钱花在每个单独测试的 alpha 阈值上。我们在每个门槛上花费的金额不需要相同,只要我们保持在总货币的预算之内。

事实上,阿尔法支出是我们一直在用本文中描述的所有方法执行的事情,我们只是没有明确地这样说。我们一直使用的阿尔法支出的“默认”形式是在所有个人阈值上的“相等”支出。

注:在实践中,任何杠杆α支出方案必须在分析的研究设计阶段加以规定;我们不能在收集了数据并对其进行了分析之后,再追溯性地指定这些阈值。这样做将不再束缚号前锋号罗斯福

5.FWER & FDR 控制方法的计算机模拟

下面是本文中讨论的 7 个 FWER 方法和 2 个 FDR 方法的 Python 计算模拟。

对于每种 FWERFDR 方法,进行了四次计算分析,每次分析指定 2000 次模拟,每次 200 次假设检验。根据 FWERFDR 方法的四个模拟在 200 个测试假设(200 或 150)中的真零假设数量以及 200 个测试的相关结构(不相关或正相关)上有所不同。所有测试都是在假设双边推理测试的情况下进行的。

让我们导入需要的库和助手函数:

…接下来指定恢复模拟数据集的函数:

…我们的 FWER 分析功能:

…我们的 FDR 分析功能:

…以及恢复我们的模拟结果:

以下是我们计算模拟的经验结果:

作者图片

上面的计算模拟结果很好地反映了这件作品中数学推导出的材料。例如,Holm-Bonferroni 程序通常比 Bonferroni 程序在估计的 FWER 上产生更严格的上限。

以上计算模拟的完整代码/笔记本,请参见下面的 github 链接

6.总结和结论

这包括我们对多重比较问题的解释,在实践中对 FWER 和 FDR 进行上限的方法,以及演示这些方法的计算机模拟。我也鼓励任何发现上述材料有见地的人创建他们自己的模拟示例,利用我的代码作为起点,并自己进行实验!

如果你想了解更多关于因果推理的方法和注意事项,我会推荐哈佛大学的 Miguel Hernan 和 Jamie Robins(我以前的两位教授)的教科书“ Causal Inference: What If ”,加州大学洛杉矶分校的 Judea Pearl 的“Causal”,斯坦福大学的达芙妮·黑仔和耶路撒冷希伯来大学的 Nir Friedman 的“概率图形模型:原理和技术,以及加州大学伯克利分校的 Mark van der Laan 和斯坦福大学的 Sheri Rose 的两本关于目标最大似然估计的教科书这些都是很棒的文章。我计划在未来写更多关于因果推理的深度文章。

因果推断:如果会怎样

因果关系

概率图形模型:原理和技术

目标最大似然估计

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算将来写一些基础作品,所以请随时在 LinkedIn 上与我联系, 在 Medium 上关注我的更新!

因果推理——控制还是不控制

原文:https://towardsdatascience.com/causal-inference-to-control-or-not-to-control-417e2721e22e?source=collection_archive---------23-----------------------

在因果估计和统计估计之间建立联系

https://github . com/crypt exis/causal _ inference/blob/main/collider _ fork/collider _ fork . ipynb

我将避免重复其他教程和书籍中的大部分内容,例如什么是碰撞器或分叉。当讨论相关话题时,我会提供有用的链接。否则,我假设读者要么熟悉这个主题,要么有足够的动机去了解更多。万一你觉得缺乏知识或背景,这里有一套我推荐参考的资源:[ 因果推断入门课程,因果推断:统计学中的混合磁带 因果推断:初级读本,因果关系

作为我写作的第一个实验,我选择写关于因果推理的文章,并在这篇论文的基础上做一个小练习。这篇论文将在因果推理入门课程的第四周讨论。
这里的不同之处在于我保留了:

  1. 变量之间的关系完全相同,而在视频中它们被修改了
  2. 治疗变量是连续的,而在视频中,它被修改为二元变量,以显示一种估计*均治疗效果的特殊技术。

此外,我愿意联系一些点,说明为什么某些技术正在估计*均因果效应,并强调如果天真地估计因果效应会发生什么。

“我妈妈总是说生活就像一盒巧克力。你永远不知道你会得到什么”——阿甘正传

因果推断……哪里需要?

简称:不可能进行随机对照试验(RCT)时。无法进行 RCT 的原因有很多,其中一些在参考博文的“为什么在行业中进行 CI”小节中有描述。

为了激励我们的练习,让我们想象以下情景:
当你正在工作中放松、摆弄数据或与 Tensorboard 进行凝视比赛时,你的老板打电话给你,让你调查变量 X 对业务 KPI Y 的影响。

你可能的答案是什么?

A. 为了准确理解效果,我们需要设置一个 RCT,对一定比例的用户关闭产品功能XN 次。

好的,我会尽我所能。

如果你答会导致很多复杂情况:

  1. 也许特性 X 是成功的:关闭它会导致大量的机会成本
  2. RCT?说起来容易做起来难。建立 RCT 有其自身的挑战。即使有成熟的 A/B 测试框架的公司有时也很难把它做好。
  3. 如果你想随机化的东西不可能随机化呢?

结果:如果你的意图是让你的老板滚蛋,那么,任务完成了!

如果你的答案是 B,那么我希望下面的练习能对一些实践和理论问题有所启发。更具体地说:

  • 如何/为什么线性回归系数可以用来估计一个变量对另一个变量的*均因果影响?
  • 如果在估计*均因果效应的过程中控制了错误的变量,会发生什么?

关于数据生成过程

当我们谈论数据生成过程时,我们不得不谈论它的因果结构。为了表示世界的因果结构,当前的文献建议使用两种工具:

  1. 结构因果模型
  2. 图形模型

给定随机变量 XYZ, 单片机可能会得到 Z=f(X,Y) 。这意味着变量 XY 导致变量*。还有,单片机的部分是描述 f 的确切形式。将变量之间的关系建模为线性函数往往是一种方便的选择(原因是可解释性)。*

示例:

与上面的 SCM 相对应的图形模型如下所示:

为了遵循论文中提供的数据生成过程,我做了两件事。把用 R 编写的巫术(无意冒犯 R 专家,我只是讨厌那种语言)翻译成 Python,并引入了一点结构:

在本文提出的所有研究中,变量 TY 的影响始终是研究的主题。因此,当谈论像分叉碰撞器这样的特定结构时,它意味着强调第三个变量如何与Y 相关。**

生成分叉结构

具有相应的 SCM 和图形模型:

****

在本笔记本中还可以找到另外两个例子。其中研究了的*均因果效应。在其他文献中 ACE 被命名为 吃了 (治疗效果一般)。就我个人而言,我喜欢*均因果效应,因为*均治疗效应表明变量 t 的二值化,例如,受试者是否接受治疗。这些只是语义。可能只是我吧:)**

为了理解估算 ACE 的程序,让我们退一步来做。

一点形式主义:关于回归系数的一个小故事

让我们想象一下:

我们用线性回归来满足

其中 X 是其他协变量的向量。让我们根据期望值改写等式:

并且对于的每一个值:**

现在让我们看看当我们用改变时,期望值的差异会发生什么。代表一个单位改变 int $ T $的值。不失一般性,我们可以假设 delta = 1

这不应该让我们感到惊讶:这就是我们总是如何解释线性回归的系数——当相应的协变量改变一个单位时,结果变量的预期变化。然而,这个估计真的带有因果性质吗?让我们再做一步来理解其中的区别。

多一点形式主义

如果 T 为二进制,我们将 ACE 定义为:

左右的重要区别 =? 标志是 的存在,做-操作符。 -操作符代表干预。更具体地说,E[Y | do(T = 1)】测量当群体中的每个人都采取处理Y 的期望值,而 E[Y|T=1] 以采取处理的子群体为条件的 Y 的期望值

现在当 T 是我们感兴趣的连续值时:

和线性回归的情况一样,我们可以假设 delta=1 。上述等式的左边转化为:

“治疗变量 T 对结果变量 Y 的*均因果效应是什么,当我们将变量 T 改变一个单位时”

这里一个重要的问题是“我们怎样才能表达出=?就右侧而言?”**

定义(后门准则):给定 DAG G 中的一对有序变量 (T,Y) ,如果Z中没有节点,则一组变量相对于 (T,Y) 满足后门准则******

(以上定义摘自朱迪亚·珀尔)

这基本上意味着为了进行上述分解,一个需要控制所有不是 T 的后代的变量,并且不应该控制任何一个后代。

好吧,让我们看看这与回归系数的关系,以防我们必须控制一个变量***【Z】***:

现在,对于变量之间的线性关系:

类似于线性回归的推导,我们可以从刚刚获得的结果中推导出:

这基本上表明,在我们对右变量进行控制的情况下,我们可以通过对数据拟合线性回归(当然,只有当 SCM 由线性关系组成时才成立)并查看治疗变量的系数来估计*。*

进行实验

论文模拟了 24 小时膳食钠摄入量()与收缩压( Y )关系的现实研究数据。随着年龄的增长, W 我们的肾脏会发生变化,从而影响我们体内钠的*衡和收缩压。由此可见, W 是既有 T 又有 Y 的共同原因。另一方面,24 小时膳食钠摄入量和高收缩压都会导致尿蛋白排泄 Z 。由此可见,是由Y 共同造成的。****

数据生成过程和生成的图表如下所示:

生成 Fork + Collider 数据

具有相应的 SCM 和图形模型:

****

这里我们可以看到 TY 的因果作用是 1.05

假设 我们假设已经为我们提供了图形模型,并且我们知道变量之间的关系是线性的。

“我们如何在真实世界场景中获得这样的图形模型?”- 好问题!

以下是方法:

  1. 研究的一个分支致力于从数据中学习因果 DAG。
  2. 领域知识:给定领域中的数据和足够的专业知识,人们可以提出一个相当不错的图形模型。

估算
如上图所示,我们需要的是对一组变量进行线性回归拟合,看变量的系数 T

现在让我们看看用不同的方法估算 ACE

****方法一:白调整

****

这里我们只是由高估了 T 的效果。想象一下,如果你向你的老板传达这样一个评估,会对业务产生什么影响。结论:仅仅收集数据和比较组*均值而不做进一步检查是不允许的!。

方法 2: 残酷的数据科学家模式——将所有变量倒入:调整 WZ

****

何? -0.9117 ?完全不同的符号。这意味着不仅幅度是错误的,而且结论也有 180 度的不同。

在一个简化的世界中,对于第一种方法,你可以告诉你的老板“如果你花 1 美元,你将产生 3.22”在第二种情况下,消息将是“如果你花 1 美元,你将损失额外的 90 美分”。**

方法 3: 我们停止抄*路,看看 DAG。DAG 说, W 是分叉, Z 是碰撞器。或者放入后门准则(BC)的话, Z 不满足 BC 准则, W 满足。因此我们只需要控制 W

****

似乎我们击中了目标。这里令人不安的是置信区间的宽度。它们看起来像是格朗德穿过的。

但这是另一个时代的故事了…

如果你正在读这一行,这意味着你已经通过:)感谢阅读!我将在未来回到因果推理主题,以涵盖更现实和有趣的用例。

参考

[1]米格尔·安杰尔·卢克-费尔南德斯,迈克尔·斯科梅克,丹尼尔·雷东多-桑切斯,玛利亚·何塞·桑切斯·佩雷斯,阿南德·瓦伊迪亚,米蕾尤·E·修尼泽,教育笔记:非传染性疾病流行病学数据分析中的矛盾对撞机效应:可再现的图解和网络应用 (2019),《国际流行病学杂志》

最初发布于https://cryptexis . github . io

基于贝叶斯结构时间序列模型的因果推理

原文:https://towardsdatascience.com/causal-inference-using-bayesian-structural-time-series-models-ab1a3da45cd0?source=collection_archive---------10-----------------------

调查培训活动对软件工程团队报告的错误数量的影响

埃里克·卡瑞茨在 Unsplash 上的照片

在本文中,我将向您简要介绍因果推理,以及作为数据科学家我们为什么需要它,然后我将展示一个如何使用 Python 库因果影响应用这一概念的实际例子。

因果推理导论

《大英百科全书》用一个我们都能理解的有用例子来定义因果推理:

在因果推理中,一个人推理出某事物是或可能是另一事物的原因的结论。例如,从一个人听到钢琴音乐的事实,可以推断出某人正在(或曾经)弹钢琴。但是尽管这个结论是可能的,但它是不确定的,因为声音可能是由电子合成器产生的。

因果推断是关于确定一个事件或干预对预期结果指标的影响。也可以认为是确定结果指标的变化是否是由事件或干预引起的。

例如,1)营销活动(干预)对我们产品的销售有什么影响(结果),2)我们产品的销售增长是因为营销活动还是因为其他原因?我们可以用因果推理来回答这些问题。

当做出可能影响数百万人或涉及数百万美元的决策时,通常会使用因果推理,例如在医疗保健、公共政策、科学和商业领域。在这种情况下,重要的是我们的分析要基于可靠的统计数据,而不仅仅是随意浏览数据和图表。

分析干预的影响的挑战是,我们不容易检查没有干预的情况下序列的趋势。在我们的营销示例中,我们有一个在活动干预后的销售记录,但是我们不知道如果没有干预会有什么样的销售。

这就是使用贝叶斯结构时间序列模型的因果推理可以帮助我们的地方。我们可以使用这样的模型来预测如果没有干预会发生什么,这被称为反事实。然后我们可以将反事实与我们实际观察到的进行比较。

因果影响库

2014 年,Google 发布了一个 R 包,用于时间序列中的因果推断。我们在下面的例子中使用的 Python 因果影响库是 Google 模型的完整实现,所有功能都完全移植。

该库的实现最好由它的作者来解释:

该算法的主要目标是通过分析预期和观察到的时间序列数据之间的差异,推断给定干预(或任何行动)对某些响应变量的预期影响。

数据分为两部分:第一部分是所谓的“干预前”时期,使用贝叶斯结构时间序列的概念来拟合一个模型,该模型可以最好地解释观察到的现象。拟合的模型用于数据的第二部分(“干预后”时期),以预测如果不进行干预,反应会是什么样子。推断基于观察到的响应与预测响应之间的差异,预测响应产生干预对数据造成的绝对和相对预期影响。

通过例子进行因果推理

以下是我们将使用的场景:

  • 流媒体服务 WebFlix 通过几个渠道提供内容:iOS 应用程序、Android 应用程序、Roku 应用程序、Fire TV 应用程序和网络浏览器。
  • 每个渠道由不同的软件工程团队管理。
  • 工程团队跟踪每周报告的错误数量,并监控模式。
  • 网络团队的管理层发现 2020 年初报告的错误数量呈令人担忧的上升趋势,并在 2020 年 5 月仅向该团队提供了培训以解决问题。

培训之后,Web 团队报告的错误数量减少了,并在 2020 年的剩余时间里保持稳定。报告的错误减少是提供培训的结果还是另有原因?

我们的数据集包含每个软件工程团队的每周错误报告。所有代码和数据都可以在这个 GitHub repo 中获得。

你可以在下图中看到,2020 年上半年,网络团队报告的错误数量有所增加。红色虚线表示提供培训的那一周。

下一个线图显示了所有软件工程团队报告的错误趋势。除了 Web 之外,所有团队的错误报告全年都相当稳定,在一个一致的范围内波动。

根据上面的线图,我们可以得出一个初步的结论,即所提供的培训可能是 Web 团队报告的错误减少的原因。然而,为了增加我们结论的可信度,我们将利用因果影响库进行统计分析。

在我们能够使用因果影响之前,我们需要将我们的数据框架转换成宽格式,以便每个软件工程团队都有一个列,列出每周报告的错误数量。我们可以使用熊猫数据透视表功能来做到这一点。我们还需要确保我们的日期变量被设置为索引,并且 Web 变量被移动到 DataFrame 的第一列。

该模型将使用所有软件工程团队的错误报告数据来帮助我们确定指定的干预是否是 Web 团队报告的错误减少的真正原因。

下面是代码和生成的数据帧:

使用和解释因果影响库的结果非常容易。我们首先定义干预前的时间段(在 2020 年 5 月的最后一周提供培训)和干预后的时间段。

然后,我们通过提供宽数据框架和我们刚刚定义的两个时间段来运行模型。处理完成后,我们可以使用三种可用的绘图类型绘制结果:原始、逐点和累积:

下面的第一个图显示了 Web 软件工程团队报告的实际错误(y)与同一团队的预测(预测),考虑了 Web 团队在 2020 年 1 月至 5 月报告的错误以及其他软件工程团队全年报告的错误。

从图中可以明显看出,网络团队对 2020 年 6 月至 12 月的预测高于实际报告。这表明在 2020 年 5 月发生了一次干预,从 6 月开始,对 Web 团队报告的错误数量产生了积极的影响。这进一步支持了一个结论,即 2020 年 5 月向 Web 团队提供的培训是从 6 月起报告的 bug 减少的原因。

下一个图显示了实际序列和预测序列之间的差异,称为点效应。

最后的图显示了累积效应,它基本上是一段时间内累积的点效应的总和。

的因果影响库还可以为我们提供数值和统计输出以供进一步分析:

最后,我们还可以生成一份书面报告,用一行代码解释我们的分析结果:

本报告证实了我们早期的初步结论,即从 2020 年 6 月起,网络软件工程团队报告的错误减少的原因是 2020 年 5 月向团队提供的培训。偶然获得这种效应的概率非常小,因此可以认为因果效应在统计上是显著的。

干预,也就是提供的培训,对报告的错误有-21.03 的影响,间隔为 95%。提供培训是一个好的决定,因为它达到了预期的效果。

结束语

因果推断是一个很难解决的问题,但数据科学家越来越多地被要求解决这个问题。因果影响等库的引入给了我们一个很好的工具,能够在这方面取得进展。

正如您在错误报告示例中看到的,这个库非常容易使用,并且结果可以被快速解释和理解。我们可以迅速获得对任何结论的信心,并将我们的结果传达给利益相关者。

也请查看我的系列文章通过示例学习 Python 数据分析:

  • 通过示例学习 Python 数据分析:纽约市违章停车
  • 通过示例学习 Python 数据分析:航班到达延误。
  • 通过例子学习 Python 数据分析:芝加哥交通事故

我最*发表的其他文章:

  • 提升您的数据科学能力:学会随机应变
  • 你是不是得了冠状病毒却连自己都不知道?我知道是谁干的!

https://github.com/dafiti/causalimpact

使用自然语言处理的因果推理

原文:https://towardsdatascience.com/causal-inference-using-natural-language-processing-da0e222b84b?source=collection_archive---------7-----------------------

思想和理论

应用 NLP 方法估计文本变量的因果效应及其在社会科学研究中的应用。

猫折纸最终导致了数据科学。图片作者。

最*,我很荣幸地接受了 TDS 编辑本·胡伯尔曼的【T2 作家聚焦】采访。我借此机会强调了我学习数据科学的连接主义方法。特别是,我讨论了我不断连接想法的愿望——这种倾向是这篇文章的原因,它结合了我的两个兴趣:自然语言处理(NLP)和因果推理。我受到了本月初发表的计算语言学调查论文的启发,该论文全面回顾了自然语言处理在因果推理中的应用,以及相反地,因果关系在改进自然语言处理模型中的应用。将因果关系应用于 NLP 研究的反向关系,对提高人工智能模型的可靠性和公*性具有启示意义;我将在以后的文章中探讨这种联系。在这里,我将重点放在第一种关系上,其主要目标是将最新的研究成果转化为社会科学研究的应用。

NLP 具有帮助估计因果效应的潜力,这一事实可以用于经济分析、公共健康研究以及销售和营销活动。在以前侧重于计量经济学的文章中,我详述了推断因果估计的统计挑战。例如,在因果森林的介绍性教程中,我讨论了潜在结果框架,并在中讨论了混杂性,这是一个关于使用工具变量进行深度学习的教程。在本文中,我将回到这两个观点,首先简要总结潜在的结果和混杂变量在估计因果关系中的作用。这直接导致了对文本数据复杂性的讨论,以及对文本变量可用作治疗、结果、中介或解决混淆的假设的挑战。接下来,我使用因果有向无环图 (DAGs)来描述取自前面提到的调查论文( Feder 等人,2021 )的一个实际例子,该例子突出了使用 NLP 进行因果推理的潜力。最后,我讨论了几个应用研究,展示了使用文本变量进行因果推理的多功能性。

潜在结果和混杂因素

为了从观测数据中估计因果效应,我们必须设想反事实的情况。因此,因果推理的关键要素是基于感兴趣的干预来定义反事实。更具体地说,因果效应被定义为治疗中单位水*的干预变化对结果变量(Y)的影响程度(T∈{ 0;1});换句话说,真实世界 Y(1)和反事实世界 Y(0)的结果之间的差异。当感兴趣的因果效应是*均治疗效应(ATE)时,事实观察和反事实观察之间的关系可以描述为下图所示。

*均治疗效果(ATE)是真实世界和反事实世界之间预期结果的差异。图片作者。

此外,为了表明治疗导致一个结果(Y),治疗(T)的变化应该导致结果(Y) 的变化,而所有其他协变量(X)保持不变;这种类型的治疗变化被称为干预。

然而,因果推理的基本问题是,不可能直接观察到反事实的结果。因此,需要一个潜在的结果框架来描述具有反事实条件的因果统计模型——这些条件是在不同情况下为真的陈述。潜在结果框架还规定了因果推断需要满足的几个假设。如果我们暂时忽略关于协变量(X)的假设,有三个相关的假设:可忽略性,积极性和一致性。

可忽略性要求治疗分配独立于已实现的反事实结果。这通常是通过随机分配实现的;然而,当使用观测数据时,这可能是不可行的。在这种情况下,有必要依赖条件可忽略性,其中协变量 X 是一组变量( x ),使得治疗分配(T)和潜在结果(Y (1)和 Y(0))在 X 的水*内是不成立的。该假设如下图所示。

条件可忽略性假设,也可以称为条件独立性或条件不可数性。来源:费德等人,2021 。

然而,条件可忽略性需要一个强有力的假设,即不存在不可观察的混杂因素。当一个变量(混杂因素)对治疗(T)和结果(Y)都有影响时,就会产生混杂因素,导致虚假的相关性。下图显示了这种关系,其中 W 是混杂变量。

混杂因素 Wᵢ对治疗(t)和结果(y)都有影响。资料来源:韦奇等人,2020 年。

其次,阳性是假设接受治疗的概率介于 0 和 1 之间。在条件可忽略性下,正定性假设对于所有协变量(X)Pr(X =X)≠0,

条件可忽略性下的正性假设,也称为重叠假设。资料来源:费德等人,2021 。

阳性还意味着在给定协变量 x 的情况下,无法完美预测治疗状态。最后,一致性要求在给定单位( i )的给定治疗状态下观察到的结果与该单位被分配到治疗中观察到的结果相同。这种一致性假设也可以称为稳定单位治疗值假设 (SUTVA),如下图所示。

反事实一致性假设。来源:费德等人,2021 年。

一致性假设对反事实结果和观察结果之间的关系做出了两个断言。第一,没有干扰,因此一个单元( i )的结果只受其治疗状态的影响,而不受其他单元的治疗状态的影响;第二,治疗只有一个版本。下一节描述了在各种文本变量设置中面临的假设挑战。

文本变量在因果推理中的作用

传统上,NLP 模型使用统计相关性来进行预测,并且依赖于训练和测试数据同分布的通常假设。然而,因果推理是一种不同类型的挑战,特别是对于非结构化的文本数据。尽管如此,对于文本,有机会利用数据生成过程 (DGP)的因果结构的领域知识,这可以暗示归纳偏差,从而导致更稳健的预测。此外,关于公*性,对预测器的随意观察可以解释其内部工作,这是相对于非因果黑盒的显著优势。

文本在编码治疗或感兴趣的结果方面具有灵活性,甚至在编码代表治疗(独立的)可以影响结果(依赖的)的中间方式的介质方面也具有灵活性。下图描述了中介设置,其中 W 是受治疗影响的中介变量,而其本身对结果有影响。

文本作为中介设置,其中 W 是中介变量。资料来源:韦奇等人,2020 年。

有了文本数据,也有可能解决混淆,使估计因果关系成为可能。混淆可能是由于主题、写作风格或语气;因此,包括这些混杂因素的文本控制,允许我们假设条件忽略。

重要的是,文本是高维的,有必要从文本中提取信息,以便估计因果关系。这意味着需要复杂的语言建模来度量语义上有意义的因素,如主题。自然语言处理的发展,如主题模型和上下文单词嵌入,使得利用文本回答因果问题成为可能。挑战在于开发新的假设,以确保 NLP 方法的使用将导致有效的因果推断。

例如,以文本作为结果,关键问题是如何将高维文本数据提取为感兴趣的低维特征。有必要根据数据开发一个测量模型;但是,这样做时,一个观察的治疗状态可能会通过测量选择影响另一个观察的结果。这导致了两个问题——首先,它违反了一致性,其次,如果我们要对同一数据探索多种不同的度量,还会有其他问题。这个问题的解决方案是开发一个测量模型,用独立的数据,而不是用来估计因果关系的数据。本节的其余部分按以下顺序讨论其余的文本变量场景:治疗、混杂和中介。

将文本作为治疗手段,我们对语言对下游决策、行为和其他结果的因果关系感兴趣( Feder 等人,2021 )。考虑治疗发现,这种方法产生文本的可解释特征,这些特征可以与结果有因果关系。这种分析文本效果的方法可以通过潜在的影响维度来完成,如主题或词汇特征,如 n-grams ( Pryzant et al .,2018 )。还可以估计从文本中提取的特定属性的因果效应( Wood-Doughty et al .,2018 )。

文本作为因果推理的治疗设置有三个挑战。第一个与人们阅读特定文本的选择有关——他们选择的原因往往与兴趣的结果有关;因此,违反了可忽略性假设。随机分配文本给读者可以克服这个挑战;然而,这并不总是可行的。在这种情况下,要估计文本属性的影响,需要假设文本包含所有的混杂因素。这意味着,如果有未观察到的原因影响一个人阅读的文本及其结果,那么可忽略性假设就不成立。一个人的政治倾向是一个未被观察到的原因的例子。

第二个独特的挑战与积极性假设有关。例如,假设文本包含所有混淆因素,如主题、语气和写作风格,如果我们试图估计礼貌语言对电子邮件回复时间的因果影响,就不可能想象礼貌电子邮件是以亵渎的风格写的( Feder 等人,2021 )。第三个也是最后一个挑战是与前面提到的作为结果设置的文本相同的衡量问题。为了假设一致性和作出有效的推论,有必要用不同于用于估计因果效应的数据来开发治疗的测量。

当试图使用文本作为解决混淆的手段时,挑战在于如何使用 NLP 方法以阻止混淆的方式对文本进行调节。解决这个问题有两种方法:非监督学习和监督学习。首先,可以使用无监督的降维技术,将高维文本数据降低到较低维的变量集。这些方法包括潜在变量模型,如主题模型(如 LDA )、嵌入方法(如句子-伯特嵌入)和自动编码器(如变分自动编码器)。第二种方法是使用监督模型来调整文本中的混杂因素;这可以通过调整预先训练的语言模型(例如 BERT )或监督主题模型(例如 sLDA )来预测治疗和结果。例如, Vietch 等人(2020) 通过学习预测治疗和结果的低维变量,将文本嵌入用于因果推断;他们证明了文本数据中存在混杂属性。

值得注意的是,当使用 NLP 调整混杂因素时,这需要对可忽略性进行强有力的假设,特别是因为文本作为混杂因素应用于只有观察数据可用的设置。这意味着假设可忽略性,模型必须测量混杂的所有方面。由于文本是高维的,包含所有可能的混杂因素意味着有大量的变量要考虑,这有违反积极性的风险。一个额外的担忧是,通过对碰撞变量(一个受到多个变量因果影响的变量)进行条件化,存在打开一条后门路径的风险,否则这条路径将被关闭。关于借壳准则(明珠,1993 )的简单介绍,我建议这个中帖。在讨论了作为中介设置的文本之后,下面的部分介绍了因果 Dag,在这里我将进一步讨论后门标准。

调解人充当外部有效性的混杂因素,也就是说,在文本设置中未能考虑调解意味着因果估计缺乏普遍性。在调解环境中,治疗(T)不能直接影响结果(Y),除非通过“中间人”调解人(W)。因此,如果文本作为一个中介,有必要在因果估计中考虑它。通常,感兴趣的因果效应是自然直接效应 (NDE),在下图中显示为直接连接治疗(T)和结果(Y)的箭头。

文本作为中介设置,其中自然直接效果(NDE)由从 T 到 Y 的箭头表示。资料来源:韦奇等人,2020 年。

在上图中,介体由 w 表示,为了估计直接因果效应,Z = f(W)应表示 w 中调解 t 和 y 的部分。这样,治疗的直接效应(𝛽)是通过给予每个单元( i )治疗而导致的结果的*均差异,如果 z 的分布就好像每个单元都接受了治疗( Veitch 等人,2020 )。在下图中,使用潜在结果框架描述了这种计算。

直接因果关系可以用 Z 来表示 W 中作为 T 和 y 中介的部分来计算。资料来源:韦奇等人,2020 年。

下一节介绍因果 Dag,并使用一个实际的例子来展示所有的文本变量设置,包括作为中介的文本。

因果有向无环图

在图的术语中,一个 DAG 有顶点和边,每条边从一个顶点指向另一个顶点而没有形成一个封闭的环,它必然是非循环的。没有反馈回路。考虑下图,其中从混杂因素(W)和处理(T)到结果(Y)的有向边用实线箭头表示,W 和 T 之间的双向虚线箭头表示它们是相关的。

变量之间的边意味着改变一个变量的值将改变另一个变量的分布。资料来源:费德等人,2021 。

在上图中,改变治疗值(T)可能会改变结果(Y)的分布,W 和 T 是相关的。在该示例 DAG 中,W 将文本表示为混杂因素,因此文本与治疗(T)相关,同时对结果(Y)也有影响。

性别是一种社会建构,然而,性别偏见在线下都是一个问题。使用来自费德等人(2021 )的一个例子,假设在社交媒体*台上,用户被允许用一个图标来表明他们喜欢的性别。在这种情况下,人们注意到那些认为自己是“女人”偶像的人在他们的帖子上得到的“喜欢”往往更少。因果问题是:被认为是女性会导致一个帖子的受欢迎程度下降吗?换句话说,被认为是女性(待遇)对一个帖子获得的赞数(结果)有什么因果关系。回答这个因果问题将有助于了解允许用户资料中的性别识别信息的政策是否有负面的因果影响。

然而,需要假设来识别反事实查询,以将查询表达为观察结果的函数。为这个场景创建一个因果 DAG 有助于我们理解我们编码的模型是否会满足做出因果推断所需的假设。这个反事实问题可以表达为:如果有可能在一个特定的帖子上操纵性别识别图标(T),那么这个帖子会获得多少赞(Y)?在这个例子中,相关性的产生有两个原因,首先是真正的因果效应,其次是由混杂因素(W)引起的虚假相关性。这由下面显示的因果 DAG 来描述。

在这个因果 DAG 中,T 代表性别识别图标,Y 代表帖子收到的赞数,W 代表帖子的文本。来源:费德等人,2021 年。

因此,帖子(W)的内容可用于解决与治疗(T)和结果(Y)相关的混淆问题。此外,除了解决混杂问题,还可以使用文本作为结果,其中处理是感知的性别(T ),而结果是帖子收到的文本回复的情感(Y)。也可以使用文本作为治疗,其中治疗是写作风格,我们感兴趣的是写作风格(T)对帖子收到的赞数(Y)的因果影响。

回到文本中的混杂因素设置,通过创建如上所示的因果 DAG,可以使用 Judea Pearl 的 d-separation 算法,根据后门标准读出所有必要的混杂因素(W)。发明 d-分离算法是为了计算 DAG 所包含的所有条件独立关系。后门标准可以解释为:给定 DAG 中一对有序的治疗和结果变量(T,Y ),如果满足以下两个标准,则一组变量(W)将满足相对于(T,Y)的后门标准。首先,W 中的节点/变量不能是 T 的后代,其次,W 必须阻塞 T 和 Y 之间包含指向 T 的边/箭头的每条路径。如前所述,如果混杂变量包含碰撞变量,则存在打开后门路径的风险,违反了可忽略性。幸运的是,只要没有不可观察的混杂因素(一个强有力的假设),将 post (W)的文本视为混杂因素将满足条件可忽略性。

最后,我们可以将文本视为一个中介设置,如下图所示,中介 W 是 T 影响 y 的中间方式。

一个帖子的正文(Wᵢ)调解了从 Tᵢ到 Yᵢ的影响,此外还有从 Tᵢ到 Yᵢ.的 NDE 资料来源:韦奇等人,2020 年。

在性别识别图标的例子中,自然的直接影响(NDE)将是被标记为由男性写的帖子与被标记为由女性写的帖子之间的点赞数(Y)的预期差异,其中预期是由男性写的帖子的分布决定的(Z= f(W))。在这里,Z 代表 W 中调解 T 和 Y 的部分。使用帖子的文本来解决 W 的调解允许我们估计从性别识别图标(T)到帖子收到的赞数(Y)的直接因果影响。

自然语言处理中因果推理的应用

有几个领域可以使用文本变量来估计因果关系,在一些领域内,新的研究领域已经出现。例如, Algaba 等人(2020) 使用计量经济学方法将定性情感数据转换为定量情感变量,然后在计量经济学分析中使用这些 NLP 导出的文本变量。他们将这一新兴领域称为 sentometrics,它是情绪和计量经济学的结合体。研究人员还充分利用了 Twitter 等社交媒体*台提供的大量开源文本数据。谭等人(2014) 研究了措辞对信息传播的影响,他们通过查看包含相同网址、由同一用户撰写、但使用不同措辞的推文来控制混淆。

在社会科学中,语言学在使用 NLP 进行因果推理的技术发展中起着重要作用。 Pryzant 等人(2018) 开发了一种去发现词汇归纳的方法,以允许可解释的社会科学研究。他们利用两种深度学习算法,其中第一种算法分离文本和混杂因素的解释能力,第二种算法强制混杂因素不变的文本编码。这两种算法创建了一个包含与叙事说服相关的单词的词典,与标准特征加权方法相比,该词典更具预测性,并且更少与混淆相关。Pryzant 等人在几个实际环境中测试他们的方法,首先,他们控制产品并评估对消费者投诉的反应,其次,他们控制受试者并根据课程描述评估注册情况,最后,他们控制销售者并根据产品描述评估销售情况。王&库洛塔(2019) 看词汇选择对受众感知的影响;例如,用户如何在他们的社交媒体档案中描述自己会对他们的社会经济地位产生影响。

我在本文前面多次引用的一篇论文( Veitch 等人,2020 )通过预测倾向得分和潜在结果以及掩蔽语言建模(MLM)目标,将 BERT 嵌入用于因果推断。除了因果 BERT,Veitch 等人还开发了一个因果摊销主题模型来产生因果嵌入,该模型改编自最初的 LDA 模型( Blei 等人,2003 )。这些调整后的文本嵌入在作为中介的文本和作为混杂设置的文本中使用。

有三个值得注意的应用文本作为因果推理的结果设置。斯里达尔&格图尔(2019) 看看语气对在线辩论的因果效应;他们使用社交媒体话语表明,辩论中的回复语气对随后回应中的语言和情绪变化有因果影响。吉尔&霍尔(2015) 看看司法性别或种族身份(待遇)对法律裁决语言(结果)的因果效应。 Koroleva 等人(2019) 测量临床试验结果的语义相似性,这项研究涉及在文本结果上测试 BERT、BioBERT 和 SciBERT。

最终想法

NLP 方法使得使用文本进行因果推理成为可能,并且在社会科学研究中已经有一些有趣的应用。要考虑的一个问题是,不可能建立基准来测试这种因果模型的准确性。由于根据定义,潜在的结果是不可观察的,假设反事实知识的基准数据集对 DGP 做出了强有力的假设,这必然是不可验证的( Feder 等人,2021 )。

此外,上面讨论的所有设置和应用都与局部*均治疗效果(晚期)有关;然而,由于异质治疗效果的可能性,估计条件*均治疗效果(CATE)可能是必要的。详细来说,不同的人对文本的阅读和解释是不同的,所以当文本是治疗手段时,同一文本可能由于解释的差异而对不同的人产生不同的(异质的)效果。根据 Feder 等人(2021 年)的说法,这是一个非常有趣的领域,需要进一步研究,需要新的反事实问题、假设和方法。

我欢迎反馈和任何问题,请随时通过 Linkedin 与我联系。

用综合控制方法理解因果推理并在 Python 中实现

原文:https://towardsdatascience.com/causal-inference-with-synthetic-control-in-python-4a79ee636325?source=collection_archive---------1-----------------------

用一个例子理解综合控制

来源: Unsplash

什么是合成控制?

综合控制被描述为“过去十年项目评估中最重要的发展”(Atheyand Imbens,2016)。综合控制法是一种统计方法,用于在比较案例研究中评估一种干预措施的效果。它包括构建用作对照的组的加权组合,并与治疗组进行比较。这种比较用于估计如果治疗组没有接受治疗会发生什么。它基于一个简单而强大的想法。我们不需要在未治疗组中找到任何单个单位,类似于治疗组。相反,我们可以将我们自己的系统作为多个未处理单元的组合,创建一个有效的合成控制系统。

与差异中的差异方法不同,该方法可以通过在干预前对对照组进行加权以更好地匹配治疗组,来说明混杂因素随时间变化的影响。综合控制方法的另一个优点是,它允许研究人员系统地选择对照组。它已被应用于政治学、卫生政策、犯罪学和经济学领域。

在本文中,我们将通过一个例子来重点了解合成控制的细节及其在 Python 中的实现。在我开始之前,我想承认这篇文章是基于为勇敢和真实的因果推断的内容。这本开源的书极大地帮助了我,让我对各种因果推理方法有了更深的理解。

我们的例子将考虑估计香烟税对其消费的影响的问题。给一点背景,这是一个在经济学界争论了很久的问题。争论的一方认为税收会增加雪茄的成本,从而降低需求。另一方认为,既然香烟会导致上瘾,那么香烟价格的变化不会改变他们的需求。从经济学的角度来说,我们可以说香烟的需求在价格上是没有弹性的,而增加税收只是以吸烟者为代价来增加政府收入的一种方式。为了解决问题,我们将查看一些关于此事的美国数据。

使用的数据

1988 年,加州通过了一项著名的烟草税和健康保护法案,即众所周知的99 号提案。它的主要作用是对加州境内的烟草销售征收每包 25%的州消费税,对其他商业烟草产品,如雪茄和嚼烟的零售征收大致相同的消费税。对烟草销售的额外限制包括禁止在青少年可以进入的公共场所出售香烟自动售货机,以及禁止单独出售一支香烟。该法案产生的收入被指定用于各种环境和医疗保健项目,以及反烟草广告。

为了评估其效果,我们可以从多个州收集多年的香烟销售数据。在我们的案例中,我们从 39 个州获得了 1970 年到 2000 年的数据。其他州也有类似的烟草控制项目,但没有被纳入分析。这是我们数据的样子。

数据集的快照

我们用state作为州索引,其中加州是第三位。我们的协变量是卷烟零售价格和人均卷烟销量。我们感兴趣的结果变量是cigsale。最后,我们有布尔辅助变量来表示加利福尼亚州和干预后时期。如果我们绘制一段时间内加州的香烟销售额和其他州的*均香烟销售额,这就是我们会得到的结果

在我们有数据的这段时间里,加州人购买的香烟明显少于全国*均水*。此外,80 年代以后,香烟消费似乎出现了下降趋势。与其他州相比,似乎在 99 号提案之后,加州的下降趋势加快了,但我们不能肯定这一点。这只是我们通过审查情节而得出的猜测。

为了回答 99 号提案是否对香烟消费有影响的问题,我们将使用干预前时期建立一个综合控制。我们将结合其他州来建立一个假的州,非常类似于加利福尼亚的趋势。然后,我们将看到这个合成控制在干预后的表现。

数学符号

假设我们有 J +1 个单位。不失一般性,假设单元 1 是受到干预影响的单元。在我们的案例中,加州是受干预或 99 号提案影响的案例。Units j =2、…, J +1 是未处理的单位或状态的集合,我们称之为“供体池”。还假设我们的数据跨越 T 个时间段,在干预之前有 T 0 个时间段。对于每个单位 j 和每个时间 t,我们观察结果 Y jt 。对于每个单位 j 和周期 t,定义 YNjt 为无干预的潜在结果,Y Ijt 为有干预的潜在结果。

那么,在时间 T,对于被处理单位 j =1,对于 t > T 0 的影响被定义为

由于单元 j =1 是被处理的单元, YIjt 是真实的,而 YNjt 不是真实的。挑战就变成了我们如何估计。注意每个时期的治疗效果是如何定义的,这意味着它可以随时间变化。不需要瞬间完成。它可以积累或消散。放个图,估计处理效果的问题归结为估计单元 j =1 如果没有处理结果会怎么样的问题。

为了估计 YNjt ,我们记住供体池中单位的组合可能比任何单独的未处理单位更接*处理单位的特征。因此,综合控制被定义为控制池中单元的加权*均值。给定权重 W =( w 2,…,wJ+1)YNjt的综合控制估计为

视觉解释

正如我们所知,线性回归也是将预测作为变量的加权*均值的一种方式。在这种情况下,回归可以表示为以下矩阵乘法

在综合控制案例中,我们没有很多单位,但我们有很多时间段。所以我们要做的是翻转输入矩阵。然后,单位成为“变量”,我们将结果表示为单位的加权*均值,就像下面的矩阵乘法一样。

如果我们每个时间段有多个特征,我们可以像这样堆积这些特征。重要的是使回归试图通过使用其他单元来“预测”被处理的单元 1。这样,我们可以以某种最佳方式选择权重,以达到我们想要的接*度。我们甚至可以对特征进行不同的缩放,赋予它们不同的重要性。

实施

为了评估综合控制的治疗效果,我们将尝试建立一个“假单位”,类似于干预期之前的治疗单位。然后,我们将看到这个“假单位”在干预后的表现。合成对照和它模拟的单元之间的区别是治疗效果。

为了进行线性回归,我们将使用 OLS 计算重量。我们将最小化供体库中单位的加权*均值和干预前期间的治疗单位之间的*方距离。

为此,我们首先需要将单位(在我们的例子中是州)转换成列,将时间转换成行。因为我们有两个特征,cigsaleretprice,我们将它们堆叠在一起,就像上图中那样。我们将建立一个合成对照,看起来很像干预前时期的加州,并观察它在干预后时期的表现。出于这个原因,我们只选择干预前的时期是很重要的。在这里,这些特征看起来是相似的,所以我们没有对它们进行标准化。如果要素的比例不同,一个是千位,另一个是小数,那么在最小化差异时,较大的要素将是最重要的。为了避免这种情况,首先对它们进行缩放非常重要。

现在,我们可以将 Y 变量定义为加利福尼亚州,将 X 变量定义为其他州。

然后,我们运行一个套索回归。我们使用 Lasso 或 L1 回归,因为我们不希望我们的状态数据过度拟合。岭回归也可用于此。回归将返回使处理过的单位和供体库中的单位之间的*方差最小化的一组权重。

这些重量向我们展示了如何建立合成控制。我们将状态 1 的结果乘以 0.566,状态 3 的结果乘以 0.317,状态 4 的结果乘以 0.158,依此类推。我们可以通过池中状态矩阵和权重之间的点积来实现这一点。

现在我们有了合成控制,我们可以用加利福尼亚州的结果变量来绘制它。

有了合成对照,我们可以用治疗结果和合成对照结果之间的差距来估计治疗效果。

到 2000 年,看起来 99 号提案已经减少了 25 包香烟的销售。现在我们将弄清楚这是否有统计学意义。

推论

这里,我们将使用费雪精确检验的思想。它的直觉很简单。我们彻底地改变了治疗和控制。因为我们只有一个处理过的单元,这意味着,对于每个单元,我们假设它是处理过的,而其他的是对照。

最后,我们将对每个状态有一个综合的控制和效果估计。因此,它所做的是假装治疗实际上发生在另一个州,而不是加州,看看这种治疗没有发生的估计效果是什么。然后,我们看看加利福尼亚的治疗与其他假治疗相比是否足够大。这个想法是,对于那些实际上没有被治疗的状态,一旦我们假装它们被治疗了,我们将无法发现任何显著的治疗效果。

该函数返回一个数据框,其中一列表示状态,一列表示年份,一列表示结果cigsale和该状态的综合结果。

这是我们把它应用到第一个状态的结果。

通过对所有状态的综合控制,我们可以估计所有状态的综合状态和真实状态之间的差距。对于加州来说,这就是治疗效果。对于其他的状态,这就像安慰剂效应,我们在治疗实际上没有发生的情况下估计合成对照治疗的效果。如果我们把所有的安慰剂效应和加州治疗效应一起画出来,我们会得到下图

这个图的两个方面跃然眼前。首先,我们可以看到干预后的方差高于干预前的方差。这是预期的,因为合成控制被设计成最小化干预前时期的差异。另一个有趣的方面是,即使在干预前时期,我们也不能很好地适应某些单位。这也是意料之中的。

因为这些单元非常不适合,所以从分析中移除它们是个好主意。客观地做到这一点的一个方法是为干预前错误设定一个阈值

并移除那些具有高误差的单元。如果我们继续这样做,并绘制相同的图形,这就是我们得到的结果。

去除噪声,我们可以看到在加利福尼亚州的影响有多极端。这张图片告诉我们,如果我们假设这种疗法发生在其他任何一个州,我们几乎永远也不会得到像加州这样极端的效果。

2000 年加州的治疗效果是-31.419,这意味着干预措施减少了* 31 包香烟的消费。

结论

使用来自其他州的前期数据,我们建立了一个 lasso 回归模型,该模型为每个控制州分配固定的权重,并得出一个加权*均值,该*均值非常类似于 99 号提案推出前加州的吸烟活动。

在这之后,我们使用由此产生的套索回归模型来合成加利福尼亚在后期的样子(没有治疗)。实际香烟销售和综合结果之间的差异就是我们的治疗效果。

我们也看到了如何使用费希尔的精确测试来对合成控制进行推断。我们假设未处理的单元实际上已被处理并计算了它们的效果。这些是安慰剂效应:即使不治疗,我们也会观察到的效应。我们用这些效果来观察和检查治疗对加州香烟销售的影响。

参考文献

马修·法库《勇敢而真实的因果推理》

计量经济学的因果机器学习:因果森林

原文:https://towardsdatascience.com/causal-machine-learning-for-econometrics-causal-forests-5ab3aec825a7?source=collection_archive---------1-----------------------

思想和理论

计量经济学的因果机器学习介绍,包括使用 EconML 估计带有因果森林美食的 Python 教程

Lukasz Szmigiel 在 Unsplash 上拍摄的照片

公*与*等不是同一个原则。在社会背景下,它们都与公*有关;*等意味着不管需求如何,对每个人都一视同仁,而公*意味着根据人们的需求区别对待。考虑疫苗接种,如果我们把公共卫生政策建立在*等的基础上,也许会有一个抽签系统来决定谁先接种疫苗,给每个人一个*等的机会。然而,在实践中,疫苗接种是基于公*的优先考虑,那些风险最大的人、前线医护人员和老年人理所当然地排在第一位。

假设我们理解了治疗和结果之间的因果关系,那么问题是,我们如何识别经历最大*均因果效应的亚组,无论是积极的还是消极的。受我在世界银行的数据科学咨询工作的启发,我最*分享了一个 Python 教程,其中我讨论了因果关系作为计量经济学在数据科学中的应用。通过计算异质性治疗效果和确定受政策影响最大的亚组,因果关系可以帮助公*的政策分配。然而,计算治疗效果的异质性可能很复杂,也称为条件*均治疗效果(CATE) 。方便的是,计量经济学提供了几种估计 CATE 的方法。

估算 CAT-E!图片作者。

然而,不幸的是,传统的计量经济学方法不适合当前的大数据现实,其中协变量和交互项的数量可能超过观察值。这一现实导致了经济学因果机器学习的发展;这是一个相对较新的领域,早在 2014 年就有贡献,最激动人心的发展出现在 2018 年前后。我将在一系列关于因果机器学习的以计量经济学为重点的文章中介绍其中的一些发展,所有这些文章都将包括这些技术的 Python 实现。

在本文中,我将重点介绍一种特定的技术, 因果森林 ,这是一种由经济学家苏珊·艾希(Susan Athey)和斯特凡·韦杰(Stefan Wager)开发的因果机器学习方法。首先,我简要描述一下本教程中使用的经济学数据集,该数据集取自在摩洛哥进行的一项关于小额信贷影响的随机实验( Crépon et al .,2015 )。接下来,我讨论因果推理和潜在结果框架,这为讨论条件*均治疗效果(CATE)奠定了基础。随后是因果森林的介绍,概述了理论,实际上侧重于建立高层次的直觉。最后,我使用微软研究院的 EconML Python 库在摩洛哥案例研究数据上实现了一个因果森林来评估 CATE。完整的 Python 演练包括使用 SHAP 值进行可解释性测试的代码,并演示了如何绘制置信区间。

案例研究:摩洛哥的小额信贷

小额信贷和小额融资的研究可以追溯到诺贝尔和*奖得主穆罕默德·尤努斯,他在 20 世纪 70 年代发现给贫穷企业家的小额贷款可以极大地改善穷人的生活。尤努斯认为,信用是一项基本人权;小额信贷增加商业投资,导致商业活动和家庭收入增加,从而导致家庭储蓄可投资于教育等减贫努力。

小额信贷理论。图片来自雅各布(2021 )。

本教程使用了 2006 年在摩洛哥农村进行的随机实验的小额信贷计划数据集( Crépon 等人,2015 )。为了了解获得小额信贷的影响,某些村庄(治疗组)获得了小额信贷,并相对于对照组测量了家庭一级的贷款额,作为小额信贷需求的指标。每个家庭都有可观察到的特征,有可能以这些协变量为条件来发现小额信贷因果效应的异质性。

在本月早些时候通过社会科学研究网络(SSRN)发布的预印本中,Daniel Jacob 调查了可用于估计 CATE 的机器学习方法,其中使用了摩洛哥小额信贷数据集作为例子。Jacob 解释说,目标是找到基于协变量的亚组,在那里治疗效果会不同;然而,我们不知道应该关注哪些子群,并且有许多协变量,因此需要机器学习来估计 CATE。下一节涵盖了因果推断和潜在结果框架,以解释 CATE 是如何计算的。

因果推断和潜在结果

因果效应被定义为治疗中单位水*的干预变化导致结果变量(Y)改变的幅度,换句话说,就是真实世界和反事实世界的结果之间的差异。从优秀的 EconML 文档中截取的下图直观地展示了这种关系。

因果效应被衡量为现实世界和反现实世界之间的结果差异。来源。

为了表明治疗引起结果,治疗的改变应该引起结果(Y)的改变,而所有其他协变量保持不变;这种类型的治疗变化被称为干预。以下随机对照试验(RCT)的因果图显示了如何计算*均治疗效果(ATE)作为治疗对结果的影响,以及 CATE 是治疗对结果的影响,以协变量为条件。

随机对照试验(RCT)中*均治疗效果(ATE)和条件*均治疗效果(CATE)的因果图。图片来自雅各布(2021 )。

如果治疗效果是异质的,有可能以协变量为条件来计算 CATE。这有助于识别治疗为阳性的个体,以及哪些个体将从治疗中受益最大;本质上是对最优政策分配的估计( Athey & Imbens,2019 )。然而,我们遇到了“因果推理的基本问题”(Holland,1986 ),其中 CATE 不能直接观察到一个单元,使得不可能观察到单元水*的因果效应。也就是说,我们永远无法直接观察到一个观察单位的反事实状态。

然而,对于每个观察,我们可以从两个条件均值函数预测两个结果,一个对应于治疗,另一个对应于对照组,潜在结果之间的差异等于 CATE。没有必要知道条件均值函数的基本结构形式,因为我们只关心得到条件均值的良好预测。这些条件均值函数的参数并不直接相关,因此这些函数可被称为干扰函数。

在之前的一个教程中,我简要讨论了与微软研究院的道伊 Python 库相关的潜在成果框架(伊本斯&鲁宾,2015 )。下图摘自 Jacob (2021) ,详细描述了 Rubin ( 1980 )概述的这一框架(也称为 Rubin 因果模型)的四个基本假设,这使我们能够推导出 CATE。

潜在结果框架的四个假设。图片来自雅各布(2021) 。

对于每个观察,有两个潜在的结果,Y₀和 Y₁,并且仅观察到一个结果。二进制治疗指标为 D > { 0;1}观察到的协变量是 X > ℝ ,其中 p 是协变量的个数,与协变量空间的维数有关。第一个和第四个假设,协变量的条件独立性和外生性,简单地陈述了治疗分配独立于两个潜在的结果,并且协变量不受治疗的影响。第二个假设,稳定单位治疗值假设(SUTVA) ,说明在治疗观察和对照观察之间没有干扰或隐藏的变化。第三个假设,重叠假设,是没有亚组完全位于治疗组或对照组内。因此,治疗概率必须远离零和一,从而产生倾向得分(上图中的等式(1))。

按照上述符号,治疗组或对照组的结果的条件预期,𝜇𝒹( x ,定义为:

对结果的有条件的期望。图片来自雅各布(2021) 。

美食或𝜏( x 正式定义为:

CATE 或𝜏( x 是条件均值的差值:𝜇₁(x—𝜇₀(x。图片来自雅各布(2021) 。

𝜏( x 是潜在结果的差异,它等于条件期望 x 的差异:𝜇₁( x ) — 𝜇₀( x 。更明确地说,来自 Jacob (2021) 的以下等式显示了两个条件均值函数如何能够表示两个潜在的结果,因此,取结果的差导致 CATE。

凯特或𝜏(是潜在结果的差异。图片来自雅各布(2021) 。

因果森林

因果森林是一种来自广义随机森林的方法( Athey et al .,2019 )。类似于随机森林( Breiman,2001 ),因果森林试图在协变量空间中寻找邻域,也称为递归划分。虽然随机森林是从决策树构建的,但是因果森林是从因果树构建的,其中因果树学习治疗效果异质性的低维表示。重要的是,分割标准优化了寻找与治疗效果异质性相关的分割。假设 CATE (𝜏( x )在邻域 N(x) 上是恒定的,那么使用残差对残差的方法使得有可能求解 N(x) 上的部分线性模型来估计*均治疗效果( Jacob,2021 )。目标是找到处理效果恒定但不同于其他叶子的叶子。交叉验证用于修剪因果树,但性能评估的标准是基于治疗效果的异质性。

因果森林只是大量因果树的*均值,其中树因子采样而不同( Athey & Imbens,2019 )。为了从因果树创建因果森林,有必要估计加权函数,并使用得到的权重来求解局部广义矩量法(GMM) 模型,以估计 CATE。为了处理过度拟合,因果森林使用诚实条件,由此树是诚实的,如果对于每个训练样本( i )它仅使用响应(Y )来估计叶内处理效果或决定在哪里放置分裂,而不是两者都使用( Jacob,2021 )。样本分割用于创建真实树,其中一半数据用于估计树结构,即分割子样本,另一半数据用于估计每片叶子的处理效果,即估计子样本。处理效果的预测是末端叶中估计子样本的处理和对照观察之间的*均结果的差异。

使用诚实树允许用于估计估计量方差的估计器中的渐*正态性,从而允许估计参数的可靠置信区间(赌&阿塞 2017 )。这一点很重要,因为为了获得准确的估计,偏差应该渐*地消失,从而使置信区间最小化。一个必要的步骤,由于不可能实际观察治疗效果,因此,传统的均方误差不能用于评估性能和确定置信区间。由于偏差渐*消失,因果森林估计是一致的,并且渐*高斯,这意味着与渐*方差的估计器(诚实树)一起,确保了有效的置信区间。在本教程中,我利用微软研究院的 EconML Python 库来实现因果森林,文档概述了因果森林的双机学习实现背后的正式方法。

建立因果森林

首先,本教程的摩洛哥小额信贷数据集以 Stata 文件(.dta)在 Jacob 共享的 R Quantlet 中。首先,我使用 DoWhy 创建因果图并明确假设,随后,使用 EconML 进行其余的因果分析。

为了可视化变量之间的关系,下面的代码片段显示了如何使用 DoWhy 快速构建因果模型。摩洛哥小额信贷数据集被载入数据框架,并定义了治疗变量(“治疗”)、结果变量(“loansamt_total”)和协变量的标签。

在上面的代码片段中,用 DoWhy 构建了一个因果模型,它创建了一个因果图,如下图所示。

摩洛哥小额信贷实验的因果图,显示了结果和治疗变量以及选择的协变量。图片作者。

接下来,我们删除所选变量中缺少值的行,并将数据集分为训练集和测试集。使用训练分割,设置结果( Y )、处理( T )和协变量( X ),并将 W 设置为“无”。测试集中的协变量被分配给 X_test

从 EconML 的双机学习模块(dml)导入 CausalForestDML ,从 Scikit-Learn 导入一个交叉验证多任务套索、 多任务套索 LASSO 代表“最小绝对收缩和选择算子”,它是一种回归方法,包括正则化和变量选择,增加了所得模型的预测精度和可解释性。

下一步是在拟合模型之前设置因果森林的参数。在下面的代码片段中,对于异质处理效果,分裂准则设置为“het”,树的数量设置为“10,000”,对于 10 个 K 倍交叉验证,交叉验证(cv)设置为“10”。此外,model_y 对应于用于将结果(反应)拟合到协变量(特征)的估计量,model_t 对应于用于将治疗拟合到协变量(特征)的估计量。在两种情况下,multitaskslassocv都被用作估计器,然而,也可以使用其他估计器。

在上面代码片段的最后两行,我们用小额信贷数据拟合因果森林模型,并用测试集估计 CATE。在 Jacob 的 CATE 调查中,运行了 20 组,*均 CATE 报告为 1300 左右。这里建立的因果森林将返回 1200 到 1400 之间的 CATE 值,这个范围与 Jacob 的*均 CATE 结果一致。

可解释性和评估

像因果森林这样的基于树和森林的估计器的一个优势是可解释性测试的可用性,例如沙普利(SHAP)值。经济学家劳埃德·沙普利(Lloyd Shapley)因提出了“沙普利加法解释值”的概念而获得了诺贝尔经济学奖,这一概念源于合作博弈论。对于这种可解释性测量的介绍,我建议这篇中期文章。

下面的代码片段显示了如何重置因果森林的参数,并随后再次拟合因果森林模型,以计算 SHAP 值。在改装模型之前,有必要将参数重置为默认值,因为使用上述用于估计 CATE 的参数,运行时间将接*两个小时。

下图显示了 SHAP 汇总图的结果。在 y 轴上绘制了要素重要性,其中值用蓝色到红色的颜色条表示,蓝色表示低要素重要性,红色表示高要素重要性。沿着 x 轴,SHAP 值以负到正的刻度显示。

摩洛哥小额信贷数据集的 SHAP 值汇总图。图片作者。

最重要的特征(协变量)是户主的年龄,其次是家庭中 6 至 16 岁儿童的数量。当*均因果效应为负时,家庭年龄似乎很重要。这有助于识别亚组,例如,特征重要性表明应该分别评估年长和年轻的家庭来估计 CATE。这与 Jacob 的美食调查结果相符,如下图所示。

摩洛哥小额信贷数据中年轻和年长家庭的食物差异。图片来自雅各布(2021) 。

因果森林的主要卖点是置信区间的可靠性,原因之前在因果森林的理论解释中讨论过。本质上,估计量的渐*正态性应该导致小的置信区间。使用数据集,下面的代码片段根据因果森林模型为治疗效果和置信区间的下限和上限生成数组。

如上所述,下一步是将数组转换为数据帧,合并这些数据帧,并根据治疗效果进行排序。有必要计算滚动*均值,因为*滑有助于创建一个更清晰、更有帮助的图。下面的代码片段显示了如何用 matplotlib 绘制治疗效果和置信区间。

下图显示了由因果森林模型确定的摩洛哥小额信贷测试集的处理效果和置信区间图。

因果森林模型的 CATE 和置信区间图,符合摩洛哥小额信贷测试数据集。图片作者。

最后的想法

因果机器学习有可能对计量经济学的应用产生重大影响,无论是在传统还是新的环境中。在经济学中,因果问题的范围受到数据可用性的极大限制,无论是来自昂贵的随机对照试验还是观察性研究。技术的持续快速发展打破了之前对数据可能性的理解。在过去十年中,“大数据”的可用性不断增加,影响了机器学习和数据科学的方向,并因此在自然科学和社会科学等其他学科中产生了连锁反应。

与这一趋势保持一致,理论计量经济学迅速推进了机器学习的因果关系。一个突出的例子是因果森林,这是艾希和伊本在 2016 年探索的一个想法,然后由艾希和韦杰在 2019 年发表在统计年鉴上的论文“广义随机森林中正式定义。最*,Athey 和 Wager 一直在用观察数据调查政策学习,今年早些时候在计量经济学上发表了一篇论文。虽然这些理论进步利用了大数据和机器学习,但不幸的是,应用经济学和计量经济学尚未采用这些最先进的方法。目前,传统的计量经济学被用来问传统的经济问题,而因果机器学习的潜力被忽视了。

就我个人而言,我对因果机器学习能够实现的可能性感到兴奋;经济学家现在有方法研究的新问题。我的希望是,这一差距可以弥合;我乐观地认为,理论计量经济学中的因果机器学习进步可以应用于社会研究。在我的下一篇文章中,我将讨论对工具变量使用深度学习,并探索因果关系的哲学史。

我欢迎反馈和问题,所以请随时在 Linkedin 上与我联系。

数据科学的因果 ML:使用工具变量的深度学习

原文:https://towardsdatascience.com/causal-ml-for-data-science-deep-learning-with-instrumental-variables-96e5b7cc0482?source=collection_archive---------10-----------------------

实践教程

结合数据科学和计量经济学,介绍 DeepIV 框架,包括完整的 Python 代码教程。

巴勒斯坦西岸地图,用红色显示外围的小街区,用蓝色显示更大的中心街区。图片作者。

历史上,经济学家和哲学家都专注于从经验证据中提取对因果关系的理解。经济学家和哲学家大卫·休谟以探索因果关系而闻名,这既是一个认识论难题,也是应用经济学中的一个实际问题。在一篇题为“经济学和计量经济学中的因果关系”的文章中,经济学教授凯文·d·胡佛指出,“经济学家继承了休谟的观点,即实用经济学本质上是一门因果科学。”(胡佛出版社,2006 年)。作为一个主要的经验主义者,休谟对经济学中因果关系的发展产生了重大影响;他的怀疑论在“因果关系的认识论地位和它们在实际政策中的作用”之间制造了一种紧张。(胡佛,2006 年)。1739 年,当休谟在“人性论 ”中给因果关系下了著名的定义时,我怀疑他是否能够预见到技术进化的指数级进步所带来的根本变化。他也无法想象我们今天的现实,深度学习被用来确定因果关系。

今天,“因果科学”正在被机器学习所驱动;然而,它仍然是一个新兴领域,发展主要集中在理论上。在我上一篇关于因果 ML 的文章中,我提到了我的乐观态度,即理论计量经济学的进步可以应用于社会研究。在此之前,在一篇更早的因果关系文章中,我展示了一个计量经济学如何用于数据科学的案例研究,依赖于阿列克谢·亚伯拉罕斯题为“艰难的旅行”(亚伯拉罕斯,2021 )的论文。在这篇文章中,我回到了亚伯拉罕斯关于以色列检查站对巴勒斯坦劳动力结果的因果影响的研究,但我利用深度学习来解决工具变量。幸运的是,亚伯拉罕的研究提供了一个机会,将计量经济学中最新的 ML 进展应用于以社会为中心的研究。

为了支持实用性,我围绕一个完整的 Python 代码教程来构建这篇文章,该教程实现了由微软研究院的 EconML 库支持的 DeepIV 框架( Hartford 等人,2017 )。首先,我简要回顾了“艰难的旅行”,重点强调了数据科学研究的要点,并讨论了最初方法的局限性。接下来,我建议采用另一种方法来扩展亚伯拉罕的数据集,以测试不同的治疗效果。我通过对混杂因素、工具变量的讨论,以及对确定条件*均治疗效果(CATE)的重要性的解释来支持这一选择。下面是对深度学习的简短介绍,其中我将 ML 的这个子集放在计量经济学中,以解释对深度学习结果进行基准测试的必要性。接下来,我提供了一个完整的 DeepIV 框架的演练,它直接导致了该技术在 Abrahams 数据集上的 Python 实现。最后,我用来自浅层因果 ML 技术的 CATE 估计来验证深度学习结果,即。用仪表化的因果森林对 DeepIV 估计进行基准测试。

艰难行进

我在之前的一篇文章中详细介绍了“艰苦的旅行”。这一影响评估的主要目的是调查以色列军队在西岸内部道路网沿线设置的检查站和路障对巴勒斯坦失业率的因果影响。

大约 2007 年 12 月巴勒斯坦西岸的卫星图像,摘自《艰难的旅行:政治冲突阴影下的失业和道路基础设施》( 亚伯拉罕斯,2021 )。

上图中的障碍物是出于安全原因而设置的,但实际上干扰了巴勒斯坦人的通勤出行。通过阻止通勤者到达商业中心和边境口岸,就业损失增加了;然而,这些损失被通勤者中位于更中心位置的巴勒斯坦竞争者的就业增长大大抵消了。也就是说,边际经济干预,如改善道路基础设施,有助于改变失业的空间分布,但没有降低总体失业水*。

在“艰难的旅行”中,亚伯拉罕斯使用了一种工具化的 2SLS(两阶段最小二乘)一阶差分策略,其中工具是以色列定居点与巴勒斯坦通勤路线的纵向接*度。这种方法是有效的,因为这些仪器隔离了部署在定居点附*的障碍子集,而不是直接回归检查站整体存在的就业百分比变化。这项研究的结果如下图所示,外围街区的失业人数与中心街区的就业人数形成对比。

显示“艰难行进”主要结果的空间直方图。外围农村地区的阻碍效应更大,商业中心的保护效应更大。 来源:亚伯拉罕,2021

混杂性和工具变量

在我最喜欢的计量经济学书籍《大部分无害的计量经济学》中,作者指出,“IV 方法最重要的当代用途是解决缺失或未知控制变量的问题”(Angrist & Pischke,2009)。当使用观察数据时,存在潜在的不可观察变量将产生混淆效应的风险,使得不可能理清变量之间的关系,从而可以确定因果关系。这要求我们对数据生成过程的因果结构做出明确的假设(DGP)。通常,这相当于假设治疗是有条件地独立于任何潜在变量给定的观察协变量。即便如此,这样的假设也不总是可能的;因此,需要仅影响治疗分配而不影响结果变量的工具变量。本质上,当我们不能在无基础假设下运作时,工具变量是必要的,这一关键点是亚伯拉罕评估设计的核心。

亚伯拉罕斯在 2012 年至 2014 年期间进行了“艰难旅行”的研究,在此期间,仪器化的 2SLS 回归是确定因果关系的最佳选择。然而,其局限性在于,这建立了一个假设同质治疗效果的线性模型。因此,亚伯拉罕的研究中计算的因果效应可被称为局部*均治疗效应(晚期),由于同质性假设,其统计功效较小。重要的是,假设一个恒定的因果关系排除了*均治疗效果取决于协变量的可能性。此外,线性模型可能不是 DGP 结构形式的最佳代表,因此需要非参数 IV 方法。为了处理线性和同质性这两个限制假设,应该使用非参数方法来估计条件*均治疗效果(CATE)。

为什么要评估美食?

在我上一篇因果 ML 文章中,我提供了一个条件*均待遇效应(CATE)的演练,并提出 CATE 的重要性与公*的政策分配有关。这是绝对正确的,然而,还有其他原因来看待治疗效果的异质性。此外,我上一篇文章中的案例研究数据来自一项随机对照试验(RCT),该试验类似于 A/B 检验,允许不受混杂因素干扰的因果推断。然而,在《艰难旅行》中,亚伯拉罕斯使用了观察数据,如下图所示,估计 CATE 因协变量的潜在混杂效应而变得复杂。

观察性研究设置中条件*均治疗效果(CATE)的因果图。图片来自 雅各布(2021 )。

除了公*性,对于利用观察数据的研究,CATE 对于评估研究设计的有效性也很重要。根据 Angrist & Pischke (2009)的观点,治疗效果的异质性很重要,因为研究设计的两种有效性之间存在差异。他们解释说,内部有效性是一个设计是否揭示了因果关系,一个好的 IV 研究,像“艰苦的旅行”有很强的内部有效性。另一方面,外部效度是一项研究结果在不同背景下的预测价值,在 ML 术语中,这指的是模型的概括能力。Angrist & Pischke 指出,“一个具有异质治疗效果的计量经济学框架帮助我们评估 IV 估计的内部和外部有效性。”(安格里斯特和皮施克,2009 年)。

关于外部有效性,在“艰难旅行”的框架中,亚伯拉罕斯认为,如果没有政治改革,经济干预将不能有效地改善劳动成果。从上下文来看,对于一个经济学家来说,这是一个大胆而非传统的主张,但却得到了大量政治经济学文献的支持。因此,估计 CATE 将有助于评估亚伯拉罕影响评估的外部有效性。换句话说,理解治疗效果的异质性将有助于确定研究结果是否可以扩展到支持政治改革必要性的更广泛主张。虽然 CATE 的估计将使我们能够确定遭受最大负面因果影响的具体巴勒斯坦社区,但可以说,公*的政策分配不如评估评价的外部有效性重要。

除了外部有效性,CATE 还可用于识别*均治疗效果不同的亚组。根据亚伯拉罕的结果,我怀疑较小的外围社区和较大的中心社区之间的 CATE 会有所不同。为了验证这一假设,我使用开源桌面 GIS 软件 QGIS 和亚伯拉罕共享的 geojson 数据来按照人口规模区分巴勒斯坦居民区。

巴勒斯坦西岸地图,显示人口总数低于中位数的外围小居民区(红色)和人口总数高于中位数的较大居民区(蓝色)。图片作者。

如上图所示,较小的外围居民区(红色)位于道路网络结构的终端节点,而较大的居民区(蓝色)位于道路基础设施的更中心位置。巴勒斯坦居民区按所有居民区人口总数的中位数划分,人口总数为 1885 人。这清楚地将亚伯拉罕的数据集一分为二,相等的样本大小允许在亚组的深度估计之间进行比较。

计量经济学深度学习

确定了估计 CATE 的必要性后,下一步是选择一种非参数 IV 方法来模拟数据生成过程(DGP)。深度学习已经被证明是一种学习复杂特征空间的潜在表示的强大方法,这使得它非常适合非参数化建模。尽管如此,在经济学中使用深度学习是一个有争议的话题,主要是因为深度神经网络的“黑箱”性质。可以说,计量经济学要求更高程度的严格性,因此,在深度神经网络背后的抽象理解中相对缺乏数学形式是这种类型的 ML 的一个减损点。此外,经济学家苏珊·艾希(Susan Athey)和圭多·w·伊本斯(Guido W. Imbens)提到,对于监督学习问题,深度学习和神经网络相对于回归树和随机森林的优势并没有正式的证明(艾希&伊本斯,2019 )。

深度学习中的“深度”只是指神经网络的多层,而浅网络只有一层。对 ML 子集的“深入”讨论超出了本文的范围;但是,有几个很好的资源可以涵盖这个主题。作为介绍,我强烈推荐《用 Python 进行深度学习》,作者是弗朗索瓦·乔莱(Franç ois Chollet),他是流行的深度学习 APIKeras的创造者。我也推荐杰森·布朗利在他的博客“机器学习掌握”上发表的这篇有用的博文。此外,还有大量关于 Medium 的文章介绍这个广泛主题的各种应用,包括自然语言处理、计算机视觉等。在接下来的代码教程中,我使用初学者友好的 Keras,并在必要的地方提供简单的解释。

关于经济学中对深度学习的健康怀疑,我认为尽管缺乏可解释性是一个问题,但它不应该低估这一技术的使用。细心的数据科学家知道,对于特定的任务,将深度学习模型与浅层、可解释的模型进行基准测试是很重要的;更易解释的模型很有可能表现得更好。幸运的是,因果森林可以作为一种可比较的非参数 IV 方法,对深度学习 IV 估计的结果进行基准测试。因此,在建议的深度学习实现之后,我将遍历所需的代码,以根据更易解释的因果森林对结果进行基准测试。下一节介绍 DeepIV 框架,它使得使用带有工具变量的深度学习来估计 CATE 成为可能。

DeepIV 框架

在“DeepIV:反事实预测的灵活方法”中,Hartford 等人( 2017 )增强了深度学习方法,以表征治疗和结果变量之间的因果关系。该框架使用工具变量,这些变量作为随机治疗的来源,有条件地独立于结果。理解这种因果关系是反事实预测的必要条件,DeepIV 框架通过两个可以用深度神经网络解决的预测任务来实现这一点。类似于 2SLS 的两个阶段,第一阶段是用于治疗预测的网络,第二阶段网络预测结果。

正如我在我的之前的因果 ML 文章中解释的,反事实预测不能以直接的方式做出;然而,由于工具变量和随机化一样好,它们允许“对不可观察的选择”。Hartford 等人将这种设置称为“IV 规格下的 DGP 结构”,这种因果关系可以通过下面的因果图来描述。

IV 规格下的 DGP 的因果图。 资料来源:哈特福德等人,2017

在上图中, x 代表协变量或可观察特征, p 代表治疗(政策)变量, z 代表工具, y 是结果, e 代表不可观察的潜在影响。在该设置中,误差项 e 以叠加的方式影响 y

使用 DeepIV 框架,IV 分析发生在两个监督阶段,具体而言,第一阶段对给定仪器 z 和协变量x的治疗变量 p 的条件分布进行建模。因此,在第二阶段,使用目标损失函数,该函数涉及对第一阶段条件治疗分布的积分,这是一种仅需要采用现成算法的解决方案。在这两个阶段中,通过随机梯度下降 (SGD)训练深度神经网络,Hartford 等人提出了样本外因果验证程序,以选择验证集上模型的超参数。

解决反事实预测的挑战需要理解上述变量之间的关系: y,p,x,ze 。如下式所示, y 的结构形式由 p,xe. 决定

结果变量 y 的结构形式。 资料来源:哈特福德等人,2017

未知函数 gxp 的潜在非线性连续函数,潜在效应 e (即误差)影响 y 加上无条件*均𝔼 e 。这给了我们结构方程 h 作为反事实预测函数。如下图所示,潜在效应 e 增加为𝔼[ ex ,这样它只受 x 的制约,并且在处理 p 变化时保持不变。

反事实预测功能。 资料来源:哈特福德等人,2017

按照 2SLS 过程,为了求解上面的方程, h ( p,x ),我们需要估计一个无偏的 h_hat ( p,x ),这在仪器 z 存在的情况下是可能的。无偏估计是可能的,因为 z 满足三个条件,相关性、排除性和未发现性。相关性意味着条件分布 *F,*一个处理密度函数,随 z 变化。排除意味着结果 y 只取决于治疗 p 和协变量 x 。取函数 g 两边的条件期望,以[ xz 为条件,给我们以下等式:

以协变量和工具、**、、**为条件的结果变量 y、结构形式的条件期望资料来源:Hartford 等人,2017

上式中, dF ( px,z )是第一阶段需要估计的条件治疗分布。通常,为了估计 h_hat ,治疗密度函数 F,必须替换为 F_hat。与 2sl 相比,DeepIV 框架的不同之处在于避免了对上述方程中的积分进行解析求解。相反,第一级估计治疗密度函数f _ hat(px,z ),建模为正态分布(高斯分布)的混合,其中混合密度模型的参数是第一级网络的输出。正如哈特福德等人解释的那样,有了足够多的混合成分,网络可以“逼*任意*滑密度”(哈特福德等人,2017 )。使用 2SLS,为 F_hat 和反事实预测函数 h 建立线性模型。然而,如前所述,这种方法需要线性和同质性两个强有力的假设。

给定第一级的输出,第二级优化如下所示的损失函数。

损失函数用于优化结构方程 h_hat 的估计。 资料来源:哈特福德等人,2017

损失函数最小化𝓵2 损失以优化 *h_hat 的估计。*在这两个阶段中,选择超参数,以使用保留验证集最小化各自的损失函数。这意味着性能的改善将与真实结构损失的改善相关,而真实结构损失无法直接评估。对于 DeepIV 框架,因果验证是必要的,因为交叉验证(超参数选择的常用方法)在没有反事实结果样本时无法工作。本质上,使用保留的验证数据允许样本外的因果验证。Hartford 等人注意到,这种方法提供了“相对”性能指导,因为它提高了反事实预测问题的性能,而没有告诉我们 h 的估计值与 h ( p,x )的真实值相差多远。以下部分概述了实现 DeepIV 框架的两个阶段所需的代码。

DeepIV 框架的 Python 实现

由于它会更快,我建议使用 Google Colab 来利用免费的 GPU 实例来训练深度神经网络。此外,Colab 使安装带有适当包依赖关系的完整版 EconML 变得更加容易,而不会出现 Tensorflow 后端的问题。“艰难旅行”数据在这里作为 Stata可用。dta”文件(亚伯拉罕,2021 )。第一步是在 Colab 中运行下面一行代码来安装 EconML 的完整版本。

!pip install econml[all]

下面两行允许我们将 Abrahams 的数据集加载到 Colab 笔记本中。

from google.colab import files
files.upload()

下一步是导入所需的包,加载数据,并做一些预处理。在下面的代码片段中,我们重命名必要的列,规范化变量,并用“0”替换 NAN 值。

在《艰难的旅行》中,亚伯拉罕在主回归中使用了 71 个协变量。接下来,我们加载 71 个控件作为虚拟变量。

由于我们正在测试子群经历不同 CATEs 的假设,在下面的代码片段中,我们使用人口总数的中值(中值= 1885)将数据集分成两半。接下来,为两个亚组定义单独的变量(结果、治疗、协变量、仪器)集,并转换为 numpy 数组以适应神经网络。

接下来,我们构建深度神经模型,用作第一阶段处理网络和第二阶段结果网络。两者结合起来,将用于为两个子组建立两个独立的估计模型。如下面的代码片段所示,Keras 用于通过顺序打包堆叠的神经层来构建神经网络。对于第一个密集层,在治疗和结果模型中,输入形状都是 73。对于治疗网络,相当于 71 个协变量加上 2 个治疗变量,对于结果网络,相当于 71 个协变量加上 2 个工具变量。

在治疗和结果网络中,有三个密集层与三个脱落层交替出现。然而,结果网络的不同之处在于具有总共 7 层的第四密集层。每个密集层使用一个整流线性激活函数或 ReLU ,并随着网络深度的增加而减小 50% (128,64,32)。输出网络的最后第七层的输出大小为 1。每个丢弃层以 17%的速率丢弃单元,这是向网络添加正则化的一种方式,以避免过拟合。

接下来,有必要设置两个估计模型的参数,一个用于较小的外围邻域,“ deepIvEst_per ”,另一个用于较大的中心邻域,“ deepIvEst_not_per ”。如下面的代码片段所示,首先我们定义两组 Keras 参数来拟合模型,一组有 50 个时期,另一组有 100 个时期。基于我的微调,我推断对于“ deepIvEst_per ”模型,第一级处理网络需要 50 个以上的历元来最小化损失。相反,第一阶段结果网络和“ deepIvEst_not_per ”模型的两个网络都需要少于 50 个历元。

两个参数集的验证分割都设置为 10%,这代表拒绝数据。对于回调,我们使用 Keras 的“EarlyStopping ”,将“patience”设置为 2,这样一旦模型开始过度拟合,训练就会结束,并恢复最佳权重。对于早期停止,“耐心”与没有改善的时期数有关,在此之后训练将停止。这意味着指定的历元数作为最大阈值,而不是强制目标。例如,“ deepIvEst_not_per ”模型的治疗网络设置为 50 个历元,但对于该网络,训练一般在 23 个历元后结束。

如上面的代码片段所示,两个子组的两个估计模型的参数几乎相同,唯一的区别是" deepIvEst_per" 模型的治疗网络,其最大值设置为 100 个时期。对于两个模型,“n_components”被设置为“15”,这意味着两者的混合密度函数由 15 个高斯分布组成。参数“m”和“h”是之前详述的治疗和结果网络;λ函数将治疗模型的变量(z,x)或结果模型的变量(t,x)映射到 Keras 模型。结果是“m”和“h”都是单个张量,是所有相应输入的串联。“n_samples”表示用于估计结果的样本数。

参数“使用上限损失”设置为“真”。如果设置为“假”,则从两个独立样本中估计梯度,这需要通过网络向前传递,因此,它是“计算密集型的”( Hartford 等人,2017 )。相反,将该参数设置为“真”意味着可以使用单次绘制来计算梯度,因为这优化了损失函数的上限。缺点是上限损耗只是真实损耗的*似值。然而,Hartford 等人声称,“在实际计算限制下”,上限损失具有更好的性能。“n_gradient_samples”被设置为“0 ”,因为我们针对上限损失进行了优化。

我尝试了各种优化器,并选择了 Adagrad 优化器,因为它具有参数特定的学习率。这意味着学习率是相对于参数在训练期间更新的频率而调整的。本质上,参数收到的更新越多,渐变更新的大小就越小。“第一阶段选项”和“第二阶段选项”是我们传递先前设置的 Keras 参数的地方;这些控制模型的拟合程度。训练这两个估计模型需要分别运行下面两行代码。对于“*deepIvEst _ per”*模型和“*deepIvEst _ not _ per”*模型,每个子组模型分别符合前面描述的变量(y,t,x,z)和(y2,t2,x2,z2)。

deepIvEst_per.fit(Y=y,T=t,X=x,Z=z)deepIvEst_not_per.fit(Y=y2,T=t2,X=x2,Z=z2)

一旦模型被训练,就有可能预测每个邻域的治疗效果。每个子组都从各自的模型中得到 CATE 估计。结果存储在数据帧中,并计算每组治疗效果的滚动*均值。

最后,如下面的代码片段所示,为了进行比较,我们绘制了两个子组的 CATE。

我运行了 20 次训练,收集了结果并选择了一个随机样本进行绘制,结果得到了下图:

周边街区的美食(蓝色)和中心街区的美食(紫色)。图片作者。

小型外围居民区的中位数 CATE 在 0.4 到 0.8 之间,而大型中心居民区的中位数在 2.0 到 3.0 之间。此外,对于最低分位数的周边社区,*均 CATE 的范围从 0.3 到 0.3。然而,清楚的是,CATE 值从两个子组中分离出来,这在上图中清楚地显示出来。

因果森林基准

为了对来自 DeepIV 框架的结果进行基准测试,我们为每个子群构建了一个仪器化的因果森林( Athey 等人,2019 )。在下面的代码片段中,我们将 Abrahams 的数据集分成每个子组的训练集和测试集。然后我们设置结果变量、治疗变量、协变量和工具来拟合两个因果森林,每个亚组一个。

接下来,我们为两个因果森林设置参数并拟合模型。关于如何为因果森林选择参数的更多细节,我推荐我以前的因果 ML 文章,它讨论了这些细节。

我们使用因果森林模型来预测每个亚组的治疗效果和置信区间的上下限。随后,将每个分组的结果存储在数据帧中,并计算滚动*均值。

最后,我们绘制了每个因果森林的不同处理效果和置信区间。

仅绘制两个子组的 CATE 会产生下图:

外围街区的美食(蓝色)和中心街区的美食(紫色)。图片作者。

为周边邻域子组绘制带有置信区间的 CATE 会产生下图:

周边邻域的 CATE(蓝色)带有上下限置信区间(绿色)。图片作者。

为中心邻域子组绘制带有置信区间的 CATE 会产生下图:

具有上下限置信区间(绿色)的中心邻域(紫色)的 CATE。图片作者。

类似地,对于 DeepIV 实验,我运行了 20 次因果森林并收集了结果。小型外围居民区的中位数 CATE 为 0.2 至 0.3,而较大的中心居民区的中位数为 2.9 至 3.1。有趣的是,周边地区最低分位数的*均 CATE 范围为-2.8 至-3.5,这一*均 CATE 范围远低于 DeepIV 估计值(-0.3 至 0.3)。此外,因果森林的中位数 CATE 范围比 DeepIV 估计值的范围小,表明后者的估计值有更大的差异。

最终想法

当比较来自 DeepIV 框架和因果森林的估计时,我想起了亚伯拉罕在《艰难旅行》中的结果。净衰减效应接*于零,因为本质上,阻碍效应和保护效应相互抵消。另一方面,来自 DeepIV 框架和因果森林的 CATE 估计值与亚伯拉罕的当地*均治疗效果(晚期)不同。重要的是,在 DeepIV 模型和基准因果森林中,亚组的 CATE 值之间有明显的差异,表明假设的亚组是有效的分离。由于这两种方法的结果相互印证,我有理由宣称我未能拒绝零假设。

用更易解释的因果森林对深度学习结果进行基准测试,允许对两种非参数 IV 方法进行比较。因果森林的优势在于计算有效置信区间的能力。相比之下,深度学习的优势在于能够创建复杂特征空间的潜在表示。深度学习的力量在于它帮助我们超越维度的诅咒。考虑到亚伯拉罕的主要设置包括 71 个协变量,我认为这需要高维特征空间,因此需要深度学习。相反,拥有有效的置信区间对于制定政策是有用的,或者可以说是必要的。然而,估计方法的选择应该取决于实验的目的和数据的大小和复杂程度。对于政策分配,我更倾向于利用因果森林估计,因为我们有所述估计的不确定性的测量。然而,DeepIV 框架是大型复杂数据集的理想选择。

我欢迎反馈和问题,请随时在 Linkedin 上与我联系。

机器学习中的因果推理

原文:https://towardsdatascience.com/causal-reasoning-in-machine-learning-4f2a6e32fde9?source=collection_archive---------11-----------------------

对人工智能驱动的系统面临的一些主要限制的调查

丹·梅耶斯在 Unsplash 上的照片

介绍

由于人工智能(AI)的最新进展,我们现在能够在学术和商业应用中利用机器学习和深度学习技术。尽管仅仅依靠不同特征之间的相关性可能会导致错误的结论,因为相关性不一定意味着因果关系。当今机器学习和深度学习模型的两个主要限制是:

  • **稳健性:**经过训练的模型可能无法推广到新数据,因此无法在现实世界中提供稳健可靠的性能。
  • **可解释性:**复杂的深度学习模型可能难以分析,以便清楚地展示它们的决策过程。

开发能够识别不同变量之间因果关系的模型可能最终提供解决这两个问题的方案。这一想法也得到了朱迪亚·珀尔(Judea Pearl)等研究人员的支持,他们主张,拥有能够在不确定性中推理的模型不足以让研究人员创造出能够真正表达智能行为的机器[1]。

因果关系

因果关系的概念

如今,机器学习模型能够通过识别大型数据集中的模式来学习数据。尽管如此,人类也许能够在检查几个例子后完成同样的任务。这是可能的,因为人类继承了理解因果关系和使用归纳推理的能力,以便吸收关于世界的新信息。因此,创造能够证明因果推理的模型将为我们打开一个全新的人工智能研究机会的世界。

在我们的日常生活中,每当我们问自己任何类型的干预性或回顾性问题(例如,如果我采取这个行动会怎样?如果我会有不同的表现呢?).

如图 1 所示,因果推理可以分为三个不同的层次(关联、干预、反事实)。在每一个层次,不同类型的问题都可以回答,为了回答最高层次的问题(如反事实),有必要从较低层次获得基础知识[4]。事实上,为了能够回答回顾性问题,我们希望首先能够回答干预和联想类型的问题。

图 1:因果等级(作者图片)

目前,机器学习模型只能回答与关联级别相关的概率类型的问题。

由于对这一主题的兴趣不断增加,已经构建了一个能够表示因果关系的数学框架(结构因果模型(SCM) [4])。使用这种框架,因果表达式可以公式化,并与数据结合使用,以便进行预测。

线性和非线性因果关系

因果关系可以分为两种主要类型:线性和非线性(图 2) [5]:

  • 在线性因果关系中,变量之间的联系可以是单向的,每个结果都可以由有限数量的原因引起。原因总是线性地先于结果(时间优先)。
  • 在非线性因果关系中,变量之间的联系可以是双向的,影响可能是由无限数量的原因引起的。

线性因果系统的特点是因果变量之间的比例关系(如确定性系统)。相反,在非线性因果系统中,会发生不成比例的影响(例如,非确定性系统)。例如,输入条件的微小变化会导致不同的结果(如“蝴蝶效应”)。

图 2:线性与非线性因果关系(图片由作者提供)

案例研究:推荐系统

大多数机器学习模型的一个主要弱点是假设输入的数据是独立且同分布的(IID)。当这个假设成立时,收敛到最低的可能损失是可实现的,但是当这个约束被违反时,即使在尝试简单的任务(例如中毒攻击)时,模型也可能表现不佳[6]。

作为一个例子,让我们考虑一个电子商务推荐系统。如今的系统能够主要基于与我们计划购买的产品相关的产品来提供建议,尽管这并不总能带来准确的估计。例如,我们可能最*买了一部新手机,现在正在寻找一个手机壳。在浏览手机壳时,尽管我们的推荐系统可能会尝试向我们推荐其他项目,如手机(只是因为它们是相关的),而不是像屏幕保护器这样更具因果关系的项目。

技术

用来试图发现因果关系的主要技术之一是图形方法,例如知识图和贝叶斯信任网络。这两种方法实际上构成了因果层次中关联层次的基础,使我们能够回答这样的问题:一个实体由哪些不同的属性组成,不同的组成部分是如何相互关联的?

为了开始将因果关系应用于机器学习,图形方法在过去几年中非常重要。虽然,为了让我们从因果等级中的关联层次转移到干预层次,替代方法可能是必要的。在可解释的人工智能和因果关系中,为了回答干预类型的问题(例如,如果?)而常用的一些附加技术。)是:

  • 特征选择技术(如递归特征消除、Shapley 值)。
  • 全局和局部模型代理(例如,局部可解释的模型不可知的解释)。
  • 人工智能中的偏差(如预处理、处理中、后处理算法)。
  • 建模隐变量(如隐马尔可夫模型、玻尔兹曼限制机)。

最后,除了机器学习,因果推理还可以应用于强化学习等人工智能的其他领域。事实上,为了让主体在环境中取得良好的表现,他们需要能够思考他们的行为会导致什么样的后果[7],因此需要属于反事实层次的因果能力。此外,因果关系也可以在这个范围内使用,以创建因果部分模型来预测低维空间中的高维未来观察结果[8]。

比较

从统计学和研究的角度来看,识别隐藏变量和偏差的图形方法和建模技术现在是一个越来越感兴趣的领域,因为它们涉及的领域在过去十年中还没有像机器学习那样被探索(尽管仍然有可能与这些技术集成)。

另一方面,特征选择和全局/局部模型代理技术是目前在深度学习问题中常用的方法,以便使复杂的模型更容易分析,从而理解它们的决策过程(例如,在进行预测时找出哪些特征具有更大的权重,并使用代理模型在局部范围内为非线性问题创建线性模型)。

如果你对如何在机器学习中使用因果关系感兴趣,可以在我的文章中找到更多信息:回答 AI 中的因果问题。

联系人

如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

  • 领英
  • 个人网站
  • 中等轮廓
  • GitHub
  • 卡格尔

文献学

[1]要造出真正智能的机器,教他们因果量子杂志。访问:https://www . quanta magazine . org/to-build truly-intelligent-machines-teach-them-cause-and-effect-2018 05 15,2020 年 3 月。

[2]归纳推理 Jan-Willem Romeijn,载于《统计哲学》,2011 年。科学指导。访问:https://www . science direct . com/topics/mathematics/归纳推理,2020 年 3 月。

[3]通过概率程序归纳的人类水*概念学习 Brenden M. Lake,Ruslan Salakhutdinov,Joshua B. Tenenbaum。访问:https://web . MIT . edu/coco sci/Papers/Science-2015-Lake-13328 . pdf,2020 年 3 月。

[4]因果推理的七个工具与对机器学习的反思 JUDEA PEARL,UCLA 计算机科学系,美国。访问时间:https://ftp.cs.ucla.edu/pub/statser/r481.pdf,2020 年 3 月。

[5]系统思维系统建模理解系统和创建系统模型的课程。可持续发展实验室。访问时间:https://systemsinnovation.io/system-dynamics-book/,2020 年 3 月。

[6]机器学习的因果关系 Bernhard schlkopf,马克斯·普朗克智能系统研究所。访问时间:https://arxiv.org/pdf/1911.10500.pdf,2020 年 3 月。

[7]来自元强化学习的因果推理 Ishita das Gupta et al .艾尔。深刻的思想。访问时间:2020 年 3 月 https://arxiv.org/pdf/1901.08162v1.pdf[。](https://arxiv.org/pdf/1901.08162v1.pdf)

[8]强化学习的因果正确部分模型。艾尔。访问时间:2020 年 3 月,https://arxiv.org/pdf/2002.02836.pdf。

因果关系:导论

原文:https://towardsdatascience.com/causality-an-introduction-f8a3f6ac4c4a?source=collection_archive---------4-----------------------

一个老问题的新科学

这是因果关系系列文章的第一篇。该系列是基于朱迪亚珍珠和其他研究人员在这一领域的工作。在这篇文章中,我将介绍珀尔所说的“因果新科学”[1],将因果关系与我们的思维方式联系起来,强调传统统计学的问题,并展示如何用数学方法表示因果关系。在以后的帖子中,我们将更仔细地研究因果关系的两个领域: 因果推断因果发现

我知道你在想什么..为什么这里会有一张香蕉的图片?图片作者。

香蕉

考虑上图。是的,香蕉。我给你一点时间。

一个自然的问题是,“香蕉和因果关系有什么关系?”嗯,这很有趣,因为香蕉和因果关系之间没有关系。然而,你的大脑,不管是有意还是无意,可能试图建立一种联系。

归结为一个基本问题*为什么?*为什么是香蕉?我为什么会点击这篇博文?为什么我还在读这个?事实是我们一直在问自己为什么。我们的大脑会自动尝试编织因果故事,以帮助我们理解这个或许毫无意义的世界。这个问题的衍生形式如下。原因是什么?这是什么原因呢?或者接下来是什么?这是要去哪里?

虽然这种因果思维方式对我们来说是自然的,但我们传统的统计工具无法轻松处理因果关系。三个要点将说明传统统计在这方面的不足。我将这些点称为统计学的三个陷阱。

统计的 3 个陷阱

陷阱 1:虚假关联

我们都听说过这样一句古老的谚语:相关性不是因果关系。该陈述总结了虚假相关性的概念,即统计相关性,没有因果关系。考虑下图(我保证这次不吃香蕉)。在每年淹死在游泳池里的人数和尼克·凯奇电影的数量之间有很强的相关性(66%)。显然,有趣的是,这两个变量没有任何因果联系,尽管它们相互关联。更可笑的例子可以在图片来源[ 2 ]找到。

每年溺水人数与尼克·凯奇电影数量的相关性。来源:https://tylervigen.com/spurious-correlations

虽然这是一个愚蠢的例子,但它提醒我们在处理相关性时必须小心。有人可能会指出建立统计意义,但是,有两个障碍。首先,这在现实世界中说起来容易做起来难(什么是好的 p 值?我们需要多少数据?),第二,即使是统计学意义也不足以得出因果关系的结论。我们可以从另一个讽刺性的,但“统计有效”的,关于鹳和婴儿的故事【3】中看到。

陷阱二:辛普森悖论

虚假相关性是众所周知的统计陷阱,所以很容易注意到它。一个不太为人所知的陷阱是辛普森悖论,即 相同的数据给出矛盾的结论,这取决于你如何看待它们

假设有一种心脏病的实验疗法。我们从一组参与者那里收集数据,并绘制治疗和结果之间的关系。然后,我们将数据绘制在下图中。

实验治疗和心脏病风险之间关系的假想例子。图片作者。

乍一看,我们可能会认为这是一个可怕的治疗。一个人服药越多或从事规定的行为越多,他们患心脏病的风险就越大。但是现在假设我们看一下下图所示的两组研究参与者。

实验治疗和心脏病风险之间关系的假想例子,现在以参与者性别为条件。图片作者。

单独考虑每一个亚群,我们得到的结果与之前相反。在每一组中,即男性和女性,治疗的增加与心脏病风险的降低相关。朱迪亚·珀尔(Judea Pearl)的一句话很好地总结了这一悖论**“我们有一种对男人有利、对女人有利、但对人不利的治疗方法”**

让我们看另一个例子,但是用数字和现实。下图是德瑞克·基特和大卫·贾斯蒂斯在 1995 年和 1996 年的击球率。如果你孤立地看这两年中的任何一年,大卫·贾斯蒂斯都有更好的表现。然而,如果你把这两年加在一起,德瑞克·基特表现得更好。迷惑对吗?

比较 1995 年至 1996 年德瑞克·基特和大卫正义的击球率。来源:https://en.wikipedia.org/wiki/Simpson%27s_paradox

**辛普森悖论强调了你如何看待你的数据很重要。**所以问题变成了,我们如何对数据进行分区?尽管在统计学中没有标准的方法来处理这个问题,但是因果推理提供了一种处理这个问题的形式。这一切都归结为因果效应,即在调整适当的混杂因素后,量化一个变量对另一个变量的影响。下一篇关于因果推理的文章将对此进行更深入的探讨。

陷阱三:对称

当考虑因果关系时,传统统计学的问题源于代数的一个基本属性,对称性[ 4 ]。等式的左边等于右边(这就是代数的要点)。等号意味着对称。然而,因果关系从根本上说是不对称的,即原因导致结果,而不是相反。

让我们看一个简单的例子。假设我们用下面的表达式对疾病和它产生的症状之间的关系进行建模。 Y 代表症状的严重程度, X 疾病的严重程度, m 是两者之间的联系, b 代表所有其他因素。

症状与疾病的简单关系。根据朱迪亚·珀尔[ 4 ]的作品改编。图片作者。

利用代数规则,我们可以把上面的等式反过来得到下面的表达式。

症状与疾病的倒置关系。根据朱迪亚·珀尔[ 4 ]的作品改编。图片作者。

问题来了,如果我们把第一个方程解释为疾病引起症状,那么我们就得把第二个方程解释为症状引起疾病!这当然不是真的。

在处理数据时,X 和 Y 之间的相关性意味着 Y 和 X 之间的相同相关性。这甚至进一步发展到更一般的统计相关性概念,即 X 和 Y 之间的相关性意味着 Y 和 X 之间的相关性。这一事实消除了将仅基于数据的模型(例如机器学习)解释为因果模型的可能性。然而,通过适当的假设,可能有希望从数据中了解因果结构,这将在以后关于因果发现的文章中讨论。

因此,如果对称性是代数和统计的核心属性,我们需要一种不同的形式来处理不对称关系,以表示因果关系。下一节将介绍一种方法。

因果关系

在我们深入到用数学方法表示因果关系之前,我们应该回答一个更深层次的问题,什么是因果关系?因果关系超越了相关性,或者更一般的统计相关性,来描述一个系统的因果联系。

一个变量 X 可以说引起了另一个变量 Y,如果当所有混杂因素被调整后,对 X 的一个干预导致了 Y 的变化,但对 Y 的一个干预不一定导致 X 的变化 [1]。这与相关性相反,相关性本质上是对称的,即如果 X 与 Y 相关,Y 与 X 相关,而如果 X 导致 Y,Y 可能不会导致 X。

因果关系的可视化。这里,对 X 的干预改变了 Y,然而对 Y 的干预使 X 保持不变。图片作者。

因果关系通过结构因果模型(SCMs) [ 5 进行数学表示。SCMs 的两个关键要素是一个图形和一组方程式。更具体地说,图是一个有向无环图(DAG) 和方程组是一个结构方程模型(SEM)

DAGs 通过显示谁听谁的,或者更重要的是谁不听谁的来表示因果结构。DAG 是一种特殊的图,它的所有边都是有向的(信息流是单向的),并且不存在循环(离开顶点的信息不能返回)。因果 DAG 中的顶点(圆圈)表示变量,边(箭头)表示因果关系,其中变量是由其父代直接导致的。

SEMs 代表变量之间的关系。这些方程有两个特点。首先,等式是不对称的,这意味着等式只在一个方向有效。这意味着 SEM 不能被反演以导出替代 SEM 方程。第二,方程可以是非参数的,这意味着函数形式是未知的。

注意,从表面上看,SEM 比 DAG 包含更多的信息。Dag 概述因果关系,而 SEM 可以显示因果关系关系的细节。虽然从这个角度来看 Dag 似乎是不必要的,但是通过 Dag 以清晰的方式看到因果关系是有巨大价值的,而通过 SEM 这种方式并不明显。此外,DAG 表示的选择最终开启了用于评估因果效应的 d 分离方法。

示例结构因果模型(SCM)。图片作者。

因果推理

现在有了形式主义,我们可以朝着用数学方法分析因果关系的方向前进。一个自然的起点是因果推论。因果推理的目标是根据问题的因果结构回答问题。

因果推理的起点是一个因果模型。换句话说,你至少需要知道,哪些变量互相监听。例如,你可能知道 X 导致 Y,但是不知道交互的细节。

因果推断有许多方面,如估计 因果关系 ,使用微积分,分解混淆。我将在因果推理系列的下一篇文章中介绍和探讨这些话题。

因果发现

在因果推理中,问题的因果结构往往是假定的。换句话说,假设有一条 DAG 代表这种情况。然而,在实践中,一个系统的因果关系往往是未知的。因果发现旨在从观察数据中发现因果结构。

从本质上来说,因果发现是一个逆问题。这就像根据冰块在厨房地板上留下的水坑来预测它的形状一样。虽然这听起来不可能,但基本策略是用假设缩小可能的解决方案。我将把更多的细节留到因果发现系列的最后一篇文章中。

结论

正如许多数据科学家(或任何与数据打交道的人)会告诉你的,从数据中回答问题既是科学也是艺术。这门“新的因果科学”提供了一个理论框架,有助于为这门艺术指明方向。尽管许多基础已经奠定,但因果关系仍然是一个年轻的领域,有几个未决问题。

就像机器学习一样,因果关系的前沿也在不断前进。当然,我不可能在一篇博文中,甚至在一系列博文中全面地描述这个快速发展的领域。然而,在这个系列中,我的目标是分享一些我认为有用的关键观点和资源。为此,在接下来的几篇文章中,我将讨论因果关系的两大观点:因果发现

资源

更多关于因果关系 : 因果关系概述 | 因果关系:简介 | 因果推断 | 因果发现

连接 : 我的网站 | 预定电话 | 邮件我

社交:YouTube|LinkedIn|Twitter

支持 : 给我买杯咖啡 ☕️ | 成为会员 ⭐️

**https://shawhin.medium.com/membership **

《为什么:因果的新科学》朱迪亚·珀尔著

【2】【https://tylervigen.com/spurious-correlations】T2

【3】https://web . Stanford . edu/class/HRP 259/2007/regression/storke . pdf

****【4】珀尔,J. (2010)。因果推理导论,国际生物统计学杂志,6(2)。https://doi.org/10.2202/1557-4679.1203

****【5】schlkopf,B. (2021)。因果表征学习。arXiv:2102.11107【cs。LG]

用于冷煮浓缩咖啡空化作用

原文:https://towardsdatascience.com/cavitation-for-cold-brew-espresso-57ef791d4675?source=collection_archive---------32-----------------------

咖啡数据科学

使用 Flair 或 Kompresso

最*,在我的广告中不断出现一种叫做 Osma 的机器,它承诺利用空化和再循环在 90 秒内提供冷煮咖啡。我认为这很有趣,但我并不真正喜欢冷饮,也没有兴趣再买一台机器。然而,我有杠杆机器。

我能通过让水在冰球内振动来模拟这种酿造吗?

气穴现象是由于水的运动太快,以至于压力下降,然后水蒸发。对于咖啡来说,理论是空化使提取更容易。压力脉动确实增加了提取率,但我不知道压力脉动是否模拟了这种效果。

设置

对于冷煮浓缩咖啡,Kompresso 和 Flair 是最佳选择。在旅行的时候,我一直用 Kompresso 做冷饮,所以我用了那个。

所有图片由作者提供

Kompresso

对于前两个测试,我使用 Kompresso 进行长时间预灌注,然后进行空化和无空化。在这种情况下,我通过敲打设备顶部来模拟空化效应。如果我经常这样做,咖啡会出来,但比恒压慢。

麻烦的变量是,这个镜头更长,所以可能会类似于更长的预输注。我试图通过使用长时间的预输注来减轻这种变量,而不会产生气穴。

天赋

为了天赋,我试了几个镜头。一次长时间预输注的基线拍摄,一次类似于 Kompresso 测试的拍摄,以及一次使用背部按摩器的拍摄。

在我得到结果之前,我想展示一些冰球。对于 Flair cold brew 来说,圆盘的底部非常有趣。对于气蚀,一个黑点出现在中心,这有点奇怪,而没有气蚀,黑点在外圈。对我来说,这是一个奇怪的模式,但我还没有深入了解。

左:带振动空化的 Flair 冷酿造,右:Flair 冷酿造

绩效指标

我使用两个指标来评估技术之间的差异:最终得分和咖啡萃取。

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

冷酿造

空化在味道上是显而易见的,但只是轻微的。就 TDS/EY 而言,气穴现象大致相同。Kompresso 的价格略高,Flair 的价格略低。

拍摄时间很难,这也造成了公*的比较差异,因为与水的总接触时间不同。

试图在冷酿造中获得空化是有趣的,但我认为不值得在杠杆上争论。我相信奥斯马机器可以做得更好。也很难衡量空化是否让事情变得更好,或者仅仅是接触时间更长。也很难知道我的所作所为是否真的通过敲击或振动杠杆导致了空化。

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

我的进一步阅读:

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事首页

摄影启动页面

使用图像处理测量咖啡研磨颗粒分布

改善浓缩咖啡

断奏生活方式概述

测量咖啡磨粒分布

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡滤纸

浓缩咖啡篮及相关主题

意式咖啡观点

透明 Portafilter 实验

杠杆机维修

咖啡评论和想法

咖啡实验

cCorrGAN:学习椭圆曲线中经验条件分布的条件相关 GAN

原文:https://towardsdatascience.com/ccorrgan-conditional-correlation-gan-for-learning-empirical-conditional-distributions-in-the-bfb3cff049b2?source=collection_archive---------21-----------------------

金融中的生成模型:动机与挑战

由于隐私、监管和业务要求,在金融服务机构中共享金融数据受到严格限制,包括内部(在机构的职能部门之间,或在授权访问前使用数据)和外部(与研究机构)[6]。因此,生成真实合成数据的方法至关重要,尤其是在缺乏历史数据以及数据匿名至关重要的情况下。例如,缺乏各种市场条件下的股票市场时间序列数据,本质上是因为只有一个“历史”。这使得很难对不同情景下的投资组合进行压力测试。

生成真实的数据集需要定义数据集之间的适当距离,并测量它们的接*程度。虽然金融数据可以大致分为零售银行数据(通常为表格形式)和市场微观结构数据(通常为时间序列形式),但这里我们将重点关注生成市场微观结构数据(*似为经验金融相关矩阵(CM))。生成多变量时间序列数据是一个更具挑战性的问题,因为它涉及到捕捉单变量时间序列之间的依赖结构,以及其他特征,如自相关和分布属性[1]。经验 CMs 在多元金融时间序列的研究中是开创性的,并且在资产配置的风险管理中是重要的。CMs 在金融领域有很多应用,比如测试交易策略的稳健性,对投资组合进行压力测试,或者客观地比较经验方法。合成 CMs 还应该展示真实数据的经验属性,称为风格化事实(SF)。到目前为止,科幻小说只是被定性地评价,还没有被浓缩成一个单一的指标。

FCMs 的数学直觉

我们将通过转向 Markowitz 的最优投资组合理论来获得对金融相关矩阵的直觉。这一理论表明,通过优化每项资产的权重(即投资于该资产的资本量),可以在给定总回报的情况下最小化风险,从而找到最佳投资组合。形式上[4]:

作者图片

使用总方差来描述投资组合的总风险[4]

作者图片

投资组合中资产的最佳*衡是使固定投资组合回报的方差最小化。风险最小的投资组合在具有最小特征值的协方差矩阵的特征向量上具有很大的权重。这可以被解释为在具有最小方差(相关特征值)的 N 个不相关投资组合(协方差矩阵的特征向量)上投资最多的资本[4]。随机矩阵理论(RMT)是应用于随机变量矩阵的概率分析的一个分支,当应用于金融 CMs 时,它的许多结果是有用的。在[4]中,作者使用 RMT 通过部分去除噪声来清理经验 CMs。如果 T 与 N 的比率很小,即如果有限时间序列长度与投资组合中的资产数量相比很小,则相关性不太可能包含有用的信息,或者更可能是有噪声的。这种获得相关矩阵的方法需要计算它们,然后执行“清理”过程。不干净的 CMs 低估了真实风险,尽管干净的 CMs 在优化投资组合中更准确地解释了风险,但真实风险总是大于估计风险。相反,采样相关矩阵可能是生成实际 CMs 的更有效的方式。生成对抗网络(GANs)已经被成功和广泛地应用于计算机视觉任务(图像和视频生成)以及语言和音频处理(文本、语音和音乐生成)。然而,直到最*,在金融领域,对生成性深度学习的探索还很少。CorrGAN [2]是解决这一差距的最新尝试,它是一种 GAN,经过训练可以学习相关矩阵的分布,从而可以对现实的金融 CMs 进行采样。

然而,RMT 和其他关于金融相关矩阵的类似工作确实提供了传递金融 CMs 属性的 SFs,使我们能够更好地理解它们。这些是[2,3]:

1.成对相关的分布显著地向正的方向倾斜。

2.特征值遵循 Marchenko-Pastur 分布,除了非常大的第一特征值(对应于“市场”)和大约 5%的其他大特征值(对应于市场内的自然集群,如行业)。

3.Perron-Frobenius 性质:第一特征向量有正项。

4.相关性遵循层级结构,正如 Mantegna [5]所示,金融相关性也是如此。

5.CM 对应的最小生成树的无标度性质。

这些程式化的事实允许对合成 CMs 和经验 CMs 之间的相似性进行定性评估。这个列表并不详尽,例如,检查 GAN 学习的潜在空间可以揭示更多以前未知的金融相关性特征。

科尔根

CorrGAN 是第一个展示使用 GANs 对金融 CMs 进行采样的结果并验证其真实性的模型。使用条件甘纳可以生成单变量时间序列,但这些忽略了多种资产之间的相关性,因此不适用于需要考虑多变量相关性的投资组合管理。在[2]中,描述了椭圆曲线(相关矩阵集)的数学设置:

作者图片

作者图片

N 乘 N 的情况在统计和计算上都要困难得多,并且需要高性能计算(HPC)基础设施来成为量化金融工具箱中的主要部分。定性评估生成矩阵的质量更难,并且由于数据效率低下,训练也更难。数据低效是由于 N 个资产的相关矩阵有 N 个!描述相同相关结构的可能矩阵,因为股票的顺序是不相关的。GAN 需要用于训练它的数据的多样性,以确保数据分布的完全覆盖。通过避免由矩阵等价引起的冗余,实施置换不变性使得每次训练更新更加多样化。在 CorrGAN 的论文中,这是通过使用分层聚类算法来设计的,以在 CM 上引起排列:

作者图片

该架构遵循深度卷积 GAN (DCGAN ),选择该架构是因为根据 SFs,CNN 显示的属性也适用于金融 CMs。这些是局部移位不变性、局部性和层次合成性(学习相关性的层次结构的能力)。

图 1:GAN 的 3x3 相关采样。图来自[2]。

在图 1 中,蓝色代表使用洋葱方法从三维椭圆图上均匀采样的 10,000 个点。橙色点是真实的经验矩阵,使用一年中 252 个工作日的日收益率计算,随机抽样三只股票,不替换标准普尔 500 的股票。绿点是通过从经过训练的 CorrGAN 采样生成的合成点。已经有可能看到合成分布与经验分布紧密匹配,直观地验证了一个典型的事实,即金融 CMs 集中在高正值范围附*。通过绘制第一特征向量的条目、相关性的分布、随机选择的 cm 的视觉表示、MST 中节点度分布的对数-对数图以及特征值的分布,来自[2]的结果显示了 CorrGAN 如何根据 SFs 生成真实的样本。然而,它们不是严格的相关矩阵,因为主对角线元素不完全等于 1。矩阵也不完全是正半定的,导致小的负特征值。需要后处理投影方法来找到相对于 Frobenius 范数最*的真实相关矩阵。

CorrGAN 的局限性在于,经验分布和合成分布并不完全匹配,更重要的是,每个训练好的模型之间存在不稳定性。这是 GANs 的一个众所周知的缺陷,即它们不善于捕捉不同的分布模式。这意味着,由于训练期间的模式崩溃,合成矩阵可能不会跨越现实金融 CMs 的整个子空间,而只是一个受限的子空间。

条件 CorrGAN: cCorrGAN

今年早些时候,[2]的作者发表了 cCorrGAN 和对 CorrGAN 的改进,CorrGAN 实现了三种广泛的市场稳定机制:压力、稳定和反弹。使用这个新标记的训练集,可以通过与 SFs 以及 PCA 投影的交叉检查来定性地评估性能,以确保经验和合成分布的良好定义的聚类和视觉匹配。在数量上,人们可以使用 Wasserstein 度量来比较经验分布和综合分布。最后,[3]的作者展示了如何应用 cCorrGAN 来测试投资策略和投资组合分配方法的稳健性,并得出这些方法中哪一种更能受益于某些市场条件(即市场制度)的见解。

对于未来的研究,以完全端到端的方式生成相关矩阵是深度学习的理想目标和常见实践,这将避免执行训练后预测的需要。同样,虽然 cCorrGAN 生成了金融 CMs,但对于研究人员来说,能够生成现实的多元金融时间序列仍然是一个挑战。

笔记

  1. 所有内联数学都是作者写的,改编自参考文章。

参考资料:

[1]马科维茨的最优投资组合理论

E.J. Elton 和 M.J. Gruber,现代投资组合理论和投资分析(1995),J.Wiley 父子公司,纽约,1995 年;H.Markowitz,投资组合选择:投资的有效多样化(1959),J.Wiley 父子公司,纽约,1959 年。

[2]科尔根

G.Marti,CorrGAN:使用生成式对抗网络对现实财务相关性矩阵进行采样(2020),ICASSP 2020–2020 IEEE 声学、语音和信号处理国际会议(ICA ssp),第 8459–8463 页。

[3]科尔根

动词 (verb 的缩写)Goubet G. Marti 和 F. Nielsen,cCorrGan:用于学习椭圆中的经验条件分布的条件相关性 Gan(2021),几何信息科学,第 613-620 页,斯普林格国际出版公司。

[4]随机矩阵理论和金融相关性

长度 Laloux,P. Cizeau,M. Potters 和 J-P. Bouchaud,《随机矩阵理论和金融相关性》( 2000 年),《国际理论和应用金融杂志》,第 3 卷,第 03 期,第 391-397 页。

[5]财务相关性的层次结构

R.N. Mantegna,《金融市场的层次结构》( 1999 年),《欧洲物理杂志 B——凝聚态物质和复杂系统》,第 11 卷,第 1 期,第 193-197 页。

[6]生成金融领域的综合数据

南 Assefa,《生成金融综合数据:机遇、挑战和陷阱》。挑战和陷阱(2020 年),信息科学:数据保护(专题),2020 年。

CDP 不是未来

原文:https://towardsdatascience.com/cdps-are-not-the-future-f8a3f56114b6?source=collection_archive---------9-----------------------

是的,有一个更好的方法…

利用第一方数据增加收入—图片由作者提供。

如果你是一家数据驱动的公司,那么你很可能熟悉 CDP。这是因为,*年来,第三方客户数据*台(或“CDP”)已经成为集中和激活客户数据的一种流行方式。除此之外,我们还看到精通技术的公司广泛采用了雪花、BigQuery 或 Redshift 等数据仓库。我在这里谈论一些有点争议的事情,并声称 CDP 不是未来。对于那些花费时间和精力将所有数据纳入数据仓库的公司,我建议采用一种不同的方法,这种方法将简化您激活客户数据的能力,并更快地推动收入增长——第一方数据*台。

您的数据仓库应该是您唯一的真实来源,是您集中、细分和激活客户数据的地方,并且第三方数据*台直接在您的数据仓库之外工作

第一方数据*台直接从数据仓库驱动—图片由作者提供

那么什么是 CDP 呢?

不要误会,客户数据*台通过集中客户数据并将其激活到团队每天使用的正确业务工具,为组织提供了巨大的价值。这有助于公司加速收入和增长,并提升客户体验。通常,CDP 通过将客户数据导入到一个位置,创建客户的单一视图,并将客户数据激活到营销、销售和客户服务工具来实现这一点。就像任何工具或*台一样,CDP 也有自己的局限性,这些年来我们逐渐意识到了这一点。我想浏览其中一些来支持这些大胆的主张。

1.时间就是金钱

在这个效率决定一切的新世界,你能想象用 6 个多月的时间来设置和集成一个工具来激活客户数据吗?这就是使用客户数据*台的现实。首先,您需要让您的工程团队参与进来,集成 SDKs 片段,并发布您的产品。在中型组织中,这个过程需要几个月的时间。如果您所在的公司有一个强大的数据工程团队,他们已经完成了为您的所有数据设计一个漂亮的数据仓库的艰巨任务,那么您现在为什么要将这些数据的子集同步到 CDP 呢?

除了数据集成之外,您现在还必须在 CDP *台中创建和维护您的客户数据模型。您必须设置重复数据删除逻辑,重新创建您的关键客户属性,并创建您想要筛选的自定义属性(总支出、购买次数等)。大多数 CDP 都有自己的细微差别,因此您需要从您的团队中分配一些资源,这些资源现在将成为“CDP 管理员”,类似于 Salesforce 管理员。从某种意义上说,CDP 迫使您全力以赴地采纳他们的观点和工具,并让您的团队致力于学习它们。

痴迷于数据驱动的增长需要更大的灵活性,并需要允许快速试验——试验 ML 模型、构建分析报告或对活动进行高级统计评估的能力。这就是为什么我们看到如此多的公司最终将集成的数据从 CDP 带回他们自己的仓库。

2.顾客的两种观点

实施第三方 CDP 的主要原因之一是找到一种简化的方式来创建您客户的**【单一视图】。不幸的是,当您扩展您的公司并因此进入更复杂的用例时,这实际上可能会适得其反,您将不可避免地以不止一个,而是两个客户视图** -一个在您的数据仓库中,一个在 CDP 中。

复制客户模型成本高昂——图片由作者提供

您的分析和数据工程团队致力于将来自不同来源的所有数据吸收到数据仓库中,并将其建模为统一的客户视图。这使他们能够生成可靠的分析报告,建立 ML 模型,并对您的营销活动进行更智能的评估。这些团队也最熟悉您的关键业务逻辑和关键指标,因此没有人比他们更了解您的数据。在仓库中,你的团队可以利用他们选择的 SQL 和数据建模工具(Matillion、DBT、Informatica 等)。)来建模数据。

通过引入 CDP,您可以维护一个完全独立的冗余数据模型,其中只有一部分数据位于您的数据仓库中。随着时间的推移,只有更强大的数据模型会存活下来,并且几乎总是最终成为数据仓库。分析团队更喜欢在数据仓库中使用他们已经喜欢的工具,这与 CDP 相反,在 CDP 中,他们将限于使用专有的查询语言或用户界面。缓慢但肯定的是,您为构建和维护您的 CDP 所做的所有工作将不再有回报。

3.CDP 对客户的看法“有限”

这是一个不幸的现实,但是随着公司的扩大,您的大多数客户数据将永远不会到达 CDP。尽管 CDP 可以从各种来源获取大量数据,但通常更容易将简单的产品指标集成到 CDP 中,如应用程序事件或网站事件。当你得到更复杂的第一方数据时,情况就不同了。

CDPs:仅限于简单的数据来源——图片由作者提供

但是现实从来没有这么简单,您将有更多的数据源—调查数据、电子邮件点击量、活动出席率、销售活动等。所有这些都需要额外的集成来同步到 CDP,而他们的客户模型并没有考虑到如此广泛的数据源。另一方面,您的数据工程和分析团队将能够使用他们已经喜欢使用的工具在您的数据仓库中轻松地接收和建模这些数据。因此,通过依赖数据仓库并将其激活为“第一方数据*台”,您将能够激活更丰富的客户资料。

第一方*台:将所有来源同步到数据仓库—图片由作者提供

4.不要破坏你团队的创新能力

分析和数据科学团队在以数据仓库提供商为中心的基于 SQL/Python 的工具生态系统中工作。通过获取数据并将其放入第三方 CDP,您束缚了您的分析团队,阻碍了他们的创新。分析和数据团队将提出预测客户流失、生命周期价值和推动真实客户价值的最佳模型。然而,CDP 使他们更难获得创建这些模型所需的数据,并且他们最终会将数据导出回仓库,以便能够使用他们工具箱中更强大的工具。许多 CDP 也不一定能轻松地将这些数据导出到他们的系统之外,因为这符合他们的最佳利益。

为您的数据团队提供他们喜爱的工具—按作者分类的图片

如果您投资您的数据仓库,并在那里构建您的核心客户数据模型,那么您的分析团队已经拥有了他们随时进行分析所需的所有数据。简单地说,与第三方 CDP 相比,分析团队更喜欢使用 SQL 和 Python。

5.数据仓库提供了更多的评估潜力

随着整个行业在活动归因跟踪方面的所有变化,拥有基于第一方数据的更智能的受众/活动评估机制比以往任何时候都更重要。您的数据仓库为报告受众和活动成功指标提供了一个更强大的框架,而不是试图处理归因或查看 CDP 提供的有限评估功能。您的数据仓库不仅拥有丰富的客户资料,而且通常还拥有您想要驱动的所有目标指标或事件,如总支出、点击的购买按钮等。因此,在分析您的团队为营销和销售活动创建的受众/细分市场时,查看您的数据仓库是显而易见的,您可以在其中将这些活动与所有活动联系起来。

推动数据仓库中的任何指标—按作者分类的图像

通过利用数据仓库作为第一方数据*台,您可以通过查看对您的业务重要的任何指标的提升来分析受众,这些指标包括留存、收入、登录、立即支付点击、搜索,以及您的仓库中几乎所有可用的指标。您可以通过在仓库中生成的受众中进行智能推广小组来跟踪诸如购物车增加、移动登录提升、收入提升等指标。你可以用曼-惠特尼 U 检验对你的结果进行统计显著性检验。除此之外,您的商业智能团队可以在您选择的数据可视化工具中可视化这些结果:Tableau、PowerBI、Looker 等。通过将受众测量保存在您的数据仓库中,团队可以更快地获得灵活性和更多洞察力。

6。不要将关键客户数据委托给第三方

安全性是任何基础架构设计或组织的重要组成部分,将您的所有数据同步到第三方 CDP 肯定会让您犹豫,这是理所当然的。激活您的数据仓库的一些最显著的优点是这种架构设计带来的安全性好处。

安全掌握在自己手中—作者图片

  • 您的数据永远不会离开 —您的数据会留在您的仓库中
  • 访问&授权 —您控制谁可以访问哪个数据子集
  • 轻松合规 —您可以在仓库中直接控制合规
  • GDPR 请求 —轻松实现合规自动化,响应 GDPR 的数据清理请求

随着隐私和安全成为客户越来越关心的问题,您绝不能拿他们对第三方的信任冒险。

更好的方法

数据团队已经在构建数据仓库和数据基础设施方面投入了大量资金。这意味着有一种更好、更快、更便宜的方式直接从仓库激活您的第一方数据。第一方数据*台使您的分析团队能够利用他们已经完成的所有艰苦工作,并简单地激活您数据仓库中的客户数据模型。

您仓库中的客户细分*台—作者图片

完全免责声明,我非常相信这个新方向,以至于我们在飞轮软件建立了一个专注于激活数据仓库的完整产品——一个直接在任何数据仓库上运行的客户细分*台。我们是朝着更好的增长、实验和营销方法这一大转变的一部分——为各种规模的团队释放巨大的潜力。我们很高兴能继续发现这一新方向的潜力,并与业内许多其他人一起拓展这一领域。

使用深度生存模型的观察性纵向研究的因果推断

原文:https://towardsdatascience.com/cdsm-casual-inference-using-deep-bayesian-dynamic-survival-models-7d9f9ec7c989?source=collection_archive---------26-----------------------

思想理论

纵向观察健康数据中的因果推断通常需要在存在时变协变量的情况下,准确估计治疗对事件间结果的影响。为了解决这个纵向治疗效果估计问题,我们开发了一个时变因果生存(TCS)模型,该模型使用潜在结果框架和一组重复的子网络来估计生存概率的差异及其随时间的置信区间,作为时间相关协变量和治疗的函数。

最新出版物见 YJBIN_104119

问题

在这里,我们简要描述一下研究设置:

假设在一个离散的时间(t=1)空间中。我们面临一个生存数据集,其中第一个失败事件由结果标签(y_t={0,1})表示,用于给予二元治疗(z_t={0,1})的患者。

研究设计。作者形象

我们观察到:

  • 协变量 : xt 患者在时间 t 的状态
  • 事件:如果发生在【t,t+1】和事件日期<审查员的日期之间,则yt = 1
  • 检查指标 : 如果患者在任何事件之前退出研究,则 T21【c】= 1T24
  • 治疗:ZT = 1若患者在间隔【t,t+1)* 接受治疗*

在每个时间间隔,我们感兴趣的是根据存活曲线来估计治疗效果。

理性

生存分析领域已经探索了深度学习技术,其中可以使用 DeepHitDeepSurv 等方法基于基线协变量预测个体生存曲线。然而,在统计分析中,治疗的因果效应通常更引起临床医生的兴趣。因此,我们的目标是使用纵向健康记录数据,以存活概率的形式预测目标结果的风险,并估计个人或患者群体的相应存活治疗效果。标准方法取决于从基线协变量快照和静态二进制治疗分配中学习的结果模型。当需要时,从开始跟进开始的暂时性被“手动”结合,例如通过定义随时间的最大值、累积值或*均值。

模型

为了估计绝对治疗效果,使用对事件发生时间(存活)结果的新型深度学习动态估计,对对照组和治疗组中的潜在存活概率进行建模。给定观察到的既往病史和治疗分配,进行治疗和对照条件下个体潜在存活曲线的差异。我们把这个模型称为时变因果生存(TCS)模型。

TCS 的关键特征是:1)它从纵向数据中观察到的和缺失的协变量的模式中学习;2)它通过对治疗和控制条件采用潜在结果子网络来捕捉治疗特定风险;3)用贝叶斯密集层量化模型估计的不确定性。

图一。模型结构。作者图片

TCS(见图 1)取代了用于估计观察到的故障/检查时间的联合分布的单一结果模型(如 DeepHit ),首先分别从治疗观察和控制观察中获取信息,然后用共享子网对信息进行编码。编码信息被输入到反事实子网络中,以预测给定治疗或控制条件下的预期生存结果。专用的子网络明确地对源自患者基线协变量及其在治疗条件之间的相互作用的风险进行建模。最后,我们调整了观察性研究中非随机治疗分配产生的反事实结果的偏差。反事实结果之间的差异将为我们提供治疗效果的校准估计。

个人 I 的结果标签 Y^M 被定义为每个时间段的矩阵:

培训标签

结果

TCS 是针对其他四种机器学习算法进行基准测试的:

  • 未调整的 TCS (TCS(na)):与 TCS 相同,但没有选择偏差校正。
  • 具有生存结果的简单递归神经网络(RNN):删除图 1 中的潜在结果神经网络。
  • 具有二进制结果的简单递归神经网络(二进制):使用均方误差作为损失函数,对事件/删失的纵向二进制标签进行直接预测。

我们生成了生存数据序列来比较这四种算法。选择模拟来模拟德国乳腺癌随机试验[1]中观察到的协变量轨迹。细节可以在论文中找到。

我们发现二进制和 RNN 算法在估计下一步生存率方面有更好的表现(见 AUROC 和 C-Index),而 TCS 及其未经调整的版本 TCS(na)在估计个体和*均治疗效果方面表现更好,这是通过生存概率(SC (Raw))和风险比(HR (Raw))的差异来衡量的。与二进制和 RNN 模型相比,TCS 的准确性随着时间的推移相对稳定。

正如预期的那样,当 ATE 以生存概率的差异来衡量时,TMLE 对 TCS 的改善可以忽略不计(偏倚从 30.8%降低到 29.9%),因为治疗效果已经被调整。二元结果模型(130.1%至 40.5%)和 RNN (46.9%至 31.5%)的校正更为明显,因为原始估计值具有较高的偏差水*。另一方面,使用 IPW 的调整使得除了二元模型之外的所有原始估计变得更糟。相似的观察结果也在通过危害比测量的 ATE 估计值中发现。

TCS 从其生存结果和潜在结果子网络的设计中获益最多。在图 2 的图(a)中,我们评估了与基准相比,TCS 的每个组成部分对 ATE 偏差减少的增量贡献,通过根据存活概率的差异定义的原始 ATE 估计,RNN 优于二元模型 83.2%。TCS (na)中包含的子网络和一致性损失函数进一步减少了 11.4%的偏差。最后,对选择偏差的调整使估计又提高了 4.7%。

与基准算法不同,TCS 提供了非常接*真实值的 ITE 估计。这在图 2 的面板(b)中示出,其显示了在默认设置下随机选择的实验的真实和估计的 ITE 分布。

在我们的工作论文中,我们进一步提供了两个基于模拟数据和房颤临床研究数据的案例研究。感兴趣的读者可以查看我们的网站。

讨论

TCS 使用深度学习技术进行生存分析,填补了因果推理的空白。它考虑了时变和高维混杂因素与时不变的治疗方案。其估计的绝对治疗效果可以很容易地与传统文献进行比较,传统文献使用相对治疗效果的措施,如风险比。我们预计 TCS 将特别有助于在日益复杂的观察性卫生保健环境下识别和量化治疗效果随时间的异质性。

这项研究中一个值得注意的发现是我们所说的样本维度对治疗效果偏倚的强烈影响。然而,应该注意的是,在我们的模拟中,所有的协变量都代表了信息混杂。我们预计,在真实世界的高维数据集中,大多数协变量可能代表噪音或与治疗和结果的微弱联系。

当比较来自 TCS 的 ate 估计和来自传统混杂调整方法的 ATE 估计时,我们发现我们的选择偏差校准损失函数可以实现与 TMLE 相似的性能,但是比 IPW 更精确。IPW 的主要缺点是,即使协变量和结果是随时间变化的,它也对整个生存曲线应用相同的加权因子。

纵向因果推理的最大挑战在于它对治疗效果的定义。在本研究中,给定时间 t 的治疗效果被定义为在整个随访期(t-u,t)给予治疗与对照组的存活概率的差异。然而,当我们有 n 个处理时,我们将面临在 n(n-1)/2 对之间进行对比的选择。然而,当我们考虑治疗中转换的影响时,解决方案变得更加复杂,也就是说,我们需要考虑转换的时机以及效果对比的选择。同样,分析连续治疗也很费力。非参数方法已被提出来离散化治疗方案或创建样条来估计单日的治疗效果。很少有人讨论时变变量或处理。

所提出的模型以及现有的数据自适应模型在捕捉由隐藏变量或测量误差引起的任意不确定性的能力方面受到限制,并且不能通过在相同的实验条件下收集更多的数据来减少。这反映在我们的情景分析中,如果数据高度混杂,增加样本大小不能提高估计的准确性。对于观察数据,由于识别和收集潜在混杂因素的能力有限,混杂因素的影响常常被忽略。最*的一项研究[2]发现,在 87 篇关于酒精对缺血性心脏病风险影响的文章中,有 74 篇(85.1%)在结论中被错误地忽略或最终排除了混杂因素。虽然这项研究承认解释案例研究结果时的警告,但量化数据自适应模型的随机不确定性对未来的研究很重要。

参考

[1]W . Sauerbrei,G . Bastert,H . Bojar,C . beyer le,RLA·诺依曼,C . sch moor,M . Schu-macher 等.评估淋巴结阳性乳腺癌患者激素治疗和化疗持续时间的随机 2× 2 试验:基于 10 年随访的更新.临床肿瘤学杂志,18(1):94–94,2000。

[2]约书亚·瓦拉赫、斯蒂利亚诺斯·塞尔希奥、朱灵芝、亚历山大·埃吉尔曼、瓦西里斯·瓦西利乌、约瑟夫·罗斯和约翰·帕·约安尼迪斯。评估饮酒对缺血性心脏病风险的流行病学研究中混杂因素的评估。BMC 医学研究方法论,20(1):1–10,2020。

庆祝数据科学年

原文:https://towardsdatascience.com/celebrating-a-year-of-data-science-7823801912c0?source=collection_archive---------5-----------------------

欢迎来到今年的变量最终版!

汤姆·塞库拉在 Unsplash 上的照片

在许多方面,这是过山车般的一年,但对于 TDS 团队来说,这也是成长、学习和兴奋的一年——这是我们在 2021 年结束之前发出的最后一份新闻稿中想要关注的内容。

不过,首先,我们要感谢你们所有人——我们的读者、支持者、、贡献者和社区成员——感谢你们的热情、慷慨和永无止境的好奇心。与世界分享如此多的伟大工作,并将其介绍给处于数据科学旅程不同阶段的如此多的人,这是一种巨大的特权。

在过去的一年中,我们发表了数千篇文章,如果你想探究其中一些突出的文章,我们在最*的 12 月版中收集了一些我们的亮点。由编辑埃利奥特·冈恩、凯特琳·金迪格、卢多维克·贝尼斯坦特和本·胡伯尔曼以及志愿编辑助理朱莉娅·尼库尔斯基、萨拉·a·梅特沃利和卡洛斯·穆根挑选的这本选集涵盖了广泛的主题、观点和声音,包括…

  • Terence Shin 谈年度最佳数据可视化
  • Divya Gopinath 关于衡量和理解公*性
  • Scott Lundberg (和合著者)关于从 ML 模型中估计因果关系
  • Denisa Blackwood 谈数据科学中的性别差异
  • Alberto Romero 谈大型语言模型中的寻址偏差

…还有很多很多更多— 查看完整的帖子,寻找你最不想错过的其他文章。

我们也为我们团队在这一年中发表的原创作品感到非常自豪。如果你在假期有时间叙叙旧,为什么不…

  • 听听 TDS 播客上的总是引人入胜的对话,其中主持人 Jeremie Harris 与特邀嘉宾讨论了围绕人工智能的重大问题,包括玛格丽特·米歇尔、华金·基诺内罗·坎德拉、Ayanna Howard 和 Brian Christian。
  • 阅读我们发布的众多问题中的一个,来自不同专业和学术背景的实践数据科学家分享了关于他们的工作、整个领域以及激励他们学习更多知识的事情的见解。

就这样,接下来的几周我们离开你——我们将在一月初带着新版本的变量回来。(如果你是 TDS 贡献者,你可能还会注意到我们审查你的工作比较慢,因为我们需要一些时间来充电;感谢您对我们的包容!)

感谢您让 TDS 成为您 2021 年学习之旅的一部分,我们希望在 2022 年看到更多您的身影!

祝新年快乐*安,

TDS 编辑

与 CycleGAN 一起庆祝农历新年

原文:https://towardsdatascience.com/celebrating-chinese-new-year-with-cyclegan-d200ab235808?source=collection_archive---------51-----------------------

使用 CycleGAN 和 Google 的 QuickDraw 数据集创建喜庆的龙和牛

CycleGAN 龙输出(图片由作者提供)

2 月 12 日星期五标志着 2021 年农历新年的开始。在新年节日里,你会经常看到五彩缤纷的舞龙,祝庆祝者好运。为了庆祝 ML 风格,我使用 CycleGAN 生成了带有有趣的装饰闪光的龙(如上所示),我将在本文中描述实现步骤。也许这些 GAN 生成的龙也会带来好运!在粤语中,我们说“恭喜发财”,希望你在新的农历新年幸福和繁荣。我从不放过任何一个使用俗气双关语的机会,所以https://machinelearningmastery.com/what-are-generative-adversarial-networks-gans/**粮草肥菜!🙈

CycleGAN 论文是由伯克利人工智能研究所的研究人员撰写的,他们也友好地发布了他们的代码,使得这个模型的实现变得非常容易。他们的模型使用循环一致的对抗网络实现了不成对的图像到图像的翻译。在这项工作之前,图像到图像的转换需要在应用期望的图像转换之前和之后的成对图像的大数据集。例如,要创建夏季到冬季的照片翻译,您可能需要一个冬季和夏季完全相同的图像的大型数据集。使用 CycleGAN,您只需要一个夏季景观数据集 A 和一个冬季景观数据集 B,模型就会学习图像转换——非常令人印象深刻!详情请参考论文。

实施循环

Til Man 在 Unsplash 上拍照

为了测试 CycleGAN,你只需要一个图像数据集 A 和数据集 B 以及一些高计算能力。我这个项目的目标是创造出红色、金色和绿色的喜庆龙,就像这里展示的这条龙。因此,我需要一个关于龙的数据集 A 和一个关于色彩鲜艳、响亮的数据集 B——或者在这种情况下,是炽热的火焰*。*

根据作者的说法,200 到 1000 张图像的数据集应该足以让 CycleGAN 进行训练,尽管如果你不介意长时间的训练,越多越好。对于龙来说,我使用了谷歌的 QuickDraw 数据集,其中包括来自他们主持的绘画游戏的众包草图。给定一个单词,玩家必须在 20 秒内画出它。他们已经将所有结果图作为开放数据集发布。我是 QuickDraw 的超级粉丝,因为它允许我们窥视世界上不同概念的集体视觉表现。时间限制迫使我们只专注于包含视觉上描述给定单词的最重要的细节,只给概念的本质留出时间。浏览许多龙的图画,我总是看到翅膀、爬行动物的尾巴和喷火——我想这是龙的本质。我对一些在 20 秒内完成的龙图印象深刻。对于我的数据,我为数据集 a 收集了大约 450 个龙的草图。然后,对于数据集 B,我创建了一个由 450 个随机形状和填充组成的数据集——如果你愿意,也可以称为随机耀斑。在下图中,我展示了 CycleGAN 如何使用我的数据集来学习图像翻译。

说明了 CycleGAN 内的 2 个 GAN。使用周期一致性损失来更新这两个 gan。(图片由作者提供)

一旦你克隆了作者的 Github,你需要在 datasets 下创建一个文件夹。在该文件夹中,创建“trainA”、“trainB”、“testA”和“testB”文件夹来存放您的数据。数据准备就绪后,您可以运行以下代码行,根据需要修改数据集位置和模型名称,以开始训练模型。

*python train.py --dataroot ./datasets/sketch2festivedragon --name cycle_gan_dragon_rg --model cycle_gan*

在 NVIDIA GeForce RTX 3090 上,使用批量大小 1(这是默认设置),该模型使用大约 10GB 的 GPU 内存,训练(200 个 epochs)在 4 个多小时内完成。如果您使用作者的代码,我强烈建议您遵循他们的培训提示,并运行以下命令在本地图形 web 服务器上启动实时培训可视化。

*python -m visdom.server*

Visdom 培训可视化截图(图片由作者提供)

众所周知,训练 gan 非常困难,因为损失图很难解释,而且不一定与预期结果一致。相反,为了跟踪您想要的图像翻译的进度,可视化结果非常重要。如果您经常进行测试,您甚至可以在几个不同的时期看到许多不错的结果。默认情况下,实现代码每 5 个时期保存一次模型的权重。训练之后,您可以使用这些检查点权重中的任何一个来测试模型的输出。您所要做的就是运行下面的代码行,并修改数据集位置、模型名称和纪元编号。测试图像将保存在结果文件夹中。

*python test.py --dataroot ./datasets/sketch2festivedragon --name cycle_gan_dragon_rg --model cycle_gan --epoch 35*

看着每个时期的测试输出,我发现所有训练中都有可爱的装饰龙。当我在寻找艺术耀斑时,龙与耀斑数据集的完美相似并不太重要。接*训练结束时,龙开始看起来过于扭曲,这是有道理的,因为模型试图扭曲输入数据以匹配耀斑数据集。我收集了一些我最喜欢的照片,显示在本文开头的图片中,拍摄于几个不同的时代。我特别喜欢大约在第 35 纪元创作的龙,在那里模型的变形给龙的草图添加了炽热和微弱的色彩。以下是来自第 35 纪元的一些样本。

CycleGAN 从第 35 纪元产生了龙(图片由作者提供)

我还对网络如何很好地学会扭曲随机的彩色形状作为输入图像来形成龙一样的图画印象深刻。下面是网络在训练结束时画出的几个龙头样品。

网络创作的龙素描。左边是耀斑数据输入,右边是从 epoch 200 生成的龙草图(图片由作者提供)

由于 2021 年是牛年,没有几只喜庆的牛,我无法结束这篇文章。我收集了大约 170 幅类似牛的快速绘制牛图,并重复了我上面描述的步骤,以在这个新的迷你数据集上训练 CycleGAN。训练在大约 1 小时 40 分钟内完成。下面是我最喜欢的一些输出示例。

CycleGAN 输出节日公牛样本(图片由作者提供)

只是为了好玩,我很好奇在 dragon 数据集上训练的模型将如何在 ox 绘图输入上执行。下面是一个使用 epoch 35 龙砝码的样品——一个喷火砝码🐲+🐂

龙牛(图片由作者提供)

感谢您的阅读,再次感谢甘喜肥菜🐉

使用 VGG 人脸数据集、Dlib 和 OpenCV 的名人重身幽灵查找器

原文:https://towardsdatascience.com/celebrity-doppelganger-finder-using-vgg-face-dataset-dlib-and-opencv-30ea1806200?source=collection_archive---------28-----------------------

杰尔·埃尔维斯在斯塔万格,欧洲最好的埃尔维斯模仿者— 这张照片 是由 贾勒滕 拍摄的。

在本文中,我们将探索如何创建一个程序,返回看起来最像输入图像的名人的名字。

这个应用程序很酷,因为你可以用类似的方法做很多事情,比如情绪检测或手势识别。

我们将使用的数据是 VGG 人脸数据集;你可以从这个链接下载它https://www.robots.ox.ac.uk/~vgg/data/vgg_face/【1】

该数据库包含 2622 个身份。每个身份都有一个文本文件,其中有几个指向其图像的链接。为了加快这个过程,我们将只使用每个身份的 5 张图片。

基本策略包括 2 个步骤:登记和推理。

注册

在注册步骤中,我们将面部标志检测应用于每个名人的 5 幅图像中的每一幅。面部标志点通过 Dlib 面部识别器。Dlib 模型将输出一个对每张脸都是唯一的响应,这个度量存储在一个 Numpy 数组描述符中。

VGG 数据集的一个优点是已经执行了人脸检测,每个 URL 都有一个左上角和一个右下角与之相关联的点。这是一个很大的帮助,因为人脸检测是耗时的。

招生基本图

我有坏消息和好消息要告诉你。坏消息是,2,622 个身份的 5 个图像是 13,110 个图像,所以做好准备——这将需要一段时间。我在周末运行了它,大约花了 6 个小时来处理数据集。

它如此缓慢的原因之一是因为你必须从一个网址打开图像。这大大减慢了这一过程,但使公众更容易获得数据集,因为作者不需要处理每张图像的版权规则。

好消息是你只需要做一次;运行注册程序后,描述符数组将保存为。npy 文件。

一旦我们有了名人描述符,我们就可以做推论了。

推理

在推断步骤中,检测输入图像的面部及其界标。然后,地标通过 Dlib 人脸识别器,该识别器将输出描述符。

推理基本图

我们剩下要做的就是计算输入图像描述符和数据集描述符之间的距离。

计算两幅图像之间的距离

就是这样,你的著名二重身是一个名人,他的描述符最小化了到输入图像描述符的距离。

下图是我的结果。

我和我的“二重身”达伦·克里斯编辑致谢:凯西·哈钦斯/Shutterstock.com

我对结果很满意,但我想确定它是否有效。所以,我用阿曼达·塞弗里德的照片测试了我的程序,的确,她看起来像她自己!

我的 cmd 剪影——阿曼达·塞弗里德看起来确实像她自己。特写闪光灯图片社/Shutterstock.com

请参见下面的实现:

我的项目目录

注册计划

推理程序

我希望你们发现这篇文章信息丰富。如果你有任何改进的建议或者有任何问题,请在评论中告诉我!

[1] O. M. Parkhi, A. Vedaldi, A. Zisserman
Deep Face Recognition
British Machine Vision Conference, 2015.

光发射光谱中的细胞孤立点检测:MacroPCA 综述

原文:https://towardsdatascience.com/cellwise-outliers-detection-in-optical-emission-spectroscopy-an-overview-of-macropca-1535b392822e?source=collection_archive---------24-----------------------

行方向异常值检测是大多数光谱学家/化学计量学家处理不一致读数时采取的最常见措施。然而,MacroPCA 是在光谱分析中考虑细胞间异常值的替代方法。

图片由詹姆斯·惠勒拍摄。

在化学计量学中,多变量校准使用通常由矩形表格表示的数据,其中 i 行是通过光谱方法分析的样品(观察值),而 j 列是由检测系统在一个波长范围内逐步增量记录的信号强度(预测变量)。多元校准旨在应用广泛的统计、机器学习和日益深入的学习方法,从记录的光谱数据中预测各种目标变量。然而,光谱学家和化学计量学家已经研究了一段时间的最紧迫的问题之一是开发用于光谱数据中异常值检测的稳健方法。这些数据通常是高维的(具有, j≫ i ),这使得难以使用基于协方差矩阵的逆矩阵的异常值检测方法。基于投影寻踪和最小协方差行列式的鲁棒主成分分析(ROBPCA)就是为此而设计的。(在我之前的文章中有更多关于这方面的内容,这里是。)

像大多数异常值检测方法一样,ROBPCA 被开发来执行行异常值检测,即显著偏离大多数观察值的观察值。然而,*年来,随着离群点传播研究的进展( Alqallaf 等人,2009 )【开放获取】,细胞离群点检测在统计学和化学计量学中产生了越来越多的兴趣,因为它是行离群点检测的补充。事实上,可疑单元可以出现在数据矩阵中的任何地方,这提供了手头数据质量的更清晰的图像。在本文中,我们简要比较了两种稳健的基于 PCA 的方法,即 ROBPCA 和 MacroPCA,用于检测植物组织样品的激光诱导击穿光谱(LIBS)光谱中的异常值。

在 LIBS 分析之前,植物样品被清洗、干燥、均质化和研磨。记录的 LIBS 光谱已经标准化,以减少脉冲到脉冲的波动(图 1)。

图 1: 植物组织的原始 LIBS 光谱(上图)和归一化 LIBS 光谱(下图)。图片作者。

行离群点检测

如图 2 所示,当一个观察被标记为异常值(黄色)时,我们经常发现自己需要选择删除整行。但是,在多元校正中,除了将数据拟合到校正模型而不是将模型拟合到数据的意外结果之外,从数据集中移除多行的成本也很高。此外,移除几行会显著改变目标变量的分布,从而改变校准域。大多数行异常值检测的另一个问题是假设至少一半的行是无异常值的,这意味着标记为异常值的观察值的数量不应超过 i /2。

图 2: 一个观察被标记为异常值(黄色)。常规观察(黑色)。图片作者。

我们首先执行 ROBPCA 来检测数据集中的行异常值,这涉及到分数散点图以及相应的异常值图的可视化。在图 3 中,我们可以看到,我们的数据集仅包含有限数量的被视为不良杠杆作用点(即,高正交和分数距离)的 LIBS 光谱。

图 3:rob PCA 建模的结果。图片作者。

单元格异常值检测

在下面的图 4 中,通过采用不同的概念方法,单元式异常值检测特别令人感兴趣,因为它允许更仔细地观察外围单元(或列),特别是在确定我们的高维光谱数据中的哪些波长变量对观察到的外围行为更负责时。

图 4: 标记为异常值的细胞(黄色)。常规细胞(黑色)。图片作者。

事实上,一种新的 PCA 方法结合了两种现有的稳健方法,即 DetectDeviatingCells(rousse uw 和 Van Den Bossche,2018 )[Open Access]和 ROBPCA ( Hubert 等人,2005 )已被引入,以抵抗单元和行方向的异常值。该方法被命名为 MacroPCA。,2019)【Open Access】,代表 PCA 允许遗漏和 Cellwise & Rowwise 离群值(图 5)。

图 5: 考虑到缺失和单元方式&行方式异常值的 PCA(macro PCA)。图片作者。

ROBPCA 和 MacroPCA 的比较

比较这两种方法的最佳方法是绘制它们各自的细胞图(图 6)。细胞图是对不寻常细胞的有力展示。更具体地说,非常大的像元值用红色表示,而非常小的像元值用蓝色表示。此外,单行上的大量异常细胞会污染整行,使观察结果被标记为异常值。这同样适用于列。(关于代码的更多细节,请点击)。从图 6 中可以看出,除了强度与典型值相比不寻常的波长(列)之外,MacroPCA 还允许识别许多有问题的观察值(行)。

图 6: ROBPCA(上图)和 MacroPCA(下图)细胞图。图片作者。

摘要

正如本文开头所提到的,删除是大多数光谱学家用来处理行方向异常值的最常见操作之一。然而,正如我们所见,MacroPCA 等替代方法允许在光谱分析中同时考虑行方向和单元方向的异常值。除此之外,在大多数校准工作中,校准样本的数量通常是有限的,因此有另一种方法来处理异常值可以降低消除异常值的过度热情。

中心网,解释

原文:https://towardsdatascience.com/centernet-explained-a7386f368962?source=collection_archive---------3-----------------------

是什么让 CenterNet 有别于其他对象检测体系结构

湿狗热图。来源:尤里阿尔莫格摄影

CenterNet 是一种无锚点对象检测架构。这种结构具有重要的优点,因为它在后处理中用更优雅的算法代替了经典的 NMS(非最大抑制),这对于 CNN 流来说是自然的。这种机制能够实现更快的推理。参见图 1。

图一。COCO mAP 与不同模型的推理时间,由 CenterNet 作者测量。由 Uri Almog 创建的图像。

正如我在关于物体检测的帖子中所描述的,大多数检测器使用多个(通常是 3 或 5 个)基本框或锚来编码它们的预测。输出要素地图中的每个空间像元预测几个盒子。每个框预测被编码为相对于单元格中心的 x 和 y 偏移,以及相对于相应锚点的宽度和高度偏移。完整的解释可以在我的 YOLOv3 帖子中找到。

基于锚点的检测的问题是它会产生许多垃圾预测:例如,YOLOv3 为每幅图像预测了超过 7K 个盒子。然后,后处理块需要对重叠的预测进行成对检查,如果重叠很高(对于 COCO 测试集,通常 IoU > 0.7),则预测被认为是指同一对象,并且具有较低置信度的预测被丢弃。这种方法有两个主要缺陷:

  1. 其复杂性与预测数量的*方成正比——对于基于锚的高精度模型(使用高分辨率输入)来说尤其糟糕。
  2. 它迫使网络在 NMS 之前解码所有预测,对大多数不相关的预测执行更多的时间和功率消耗操作。

论文由周等人于 2019 年发表,以物为点探索了无锚点预测。在训练集准备阶段,他们在地面实况(GT)框中心绘制一个带有 delta 函数的地图。然后,他们使用高斯滤波器涂抹这些中心,生成一个*滑的分布,在对象中心达到峰值。然后,该模型使用两个预测头:一个训练来预测置信度热图,另一个训练,如在其他检测器中一样,来预测盒子尺寸和偏移的回归值,这是指由第一个训练头预测的盒子中心。参见图 2。

图二。中心网络热图预测。蓝色表示低置信度,红色表示高置信度,表示单元格包含一个方框中心。CenterNet 为每个类预测了一个单独的热图。由 Uri Almog 创建。图片来源:乌里阿尔莫摄影

现在是最酷的部分:我们可以直接使用置信度热图来删除不相关的预测,而无需解码盒子,也不会破坏深层的 CNN 流程。参见图 3:

  1. 在热图上运行 maxpool 3x3/1。这将提高每个细胞一点点,除了在非常高峰。在非常接*峰值的地方产生一个小的*坦区域。
  2. 在 maxpool 输入和输出之间运行布尔元素比较。以 FP 值的形式返回值(0。或者 1。).这将创建一个新的热点图,其中除了值为 1 的局部最大值之外,所有位置都为 0(因为 maxpool 操作提升了每个值)。
  3. 在阶段 2 的输出和最大池的输入之间运行元素级乘法。这将使每个局部最大值返回到其置信水*,将非最大值保留为 0。
  4. 像在其他检测器中一样应用置信度阈值。
  5. 仅解码对应于幸存最大值的框。

图 3。中心网 NMS 流量。图中显示了流程列表中的阶段 1-3。第二个热图在置信度峰值附*包含一个小而*坦的红色区域。所有其他值都略高于它们的原始值。这在元素式比较输出中产生一个奇点,然后通过元素式乘法将该奇点缩放回置信值。资料来源:Uri Almog。

作者使用 DLA34 和沙漏-101 主链测试了遵循上述机制的经典 NMS 的需要,并得出结论,影响很小(第一种情况下 0.7% mAP,第二种情况下 0%)。

这个检测框架已经被最初的作者和其他研究人员用于更多的检测任务,例如姿态估计和 3D 对象检测。带有 ResNet18 和 ResNet50 主干的训练过的检查点可以在 GluonCV 模型动物园—检测下载。

结论

CenterNet 是一种深度检测架构,消除了对锚点和计算量大的 NMS 的需求。它基于这样的认识,即盒预测可以基于它们的中心位置而不是它们与对象的重叠来排序相关性。这种见解现在正被用于其他深度学习任务。

我的其他帖子:

什么是神经网络?

数学和人工智能

https://medium.com/@urialmog/practical-problems-math-and-ai-c934a95bde28?source=friends_link&sk=bc78b0acc4786b7a251fd4986b01a16b

训练神经网络简单解释

深度学习的物体检测——RCNN、锚点、非最大抑制

约洛夫 3 解释

中心极限定理

原文:https://towardsdatascience.com/central-limit-theorem-70b12a0a68d8?source=collection_archive---------21-----------------------

关于数据科学家统计推断基石的相关性。

正态分布。由作者生成。

每个 STATS101 课程都讲授中心极限定理,或称 CLT。介绍这一主题的典型方式是展示公式,讨论假设,并进行一些涉及正态密度函数的计算。缺少的是 CLT 与数据科学家日常工作的相关性。让我试着指出来。

人口、样本和抽样分布

要了解 CLT,必须熟悉总体、样本和抽样分布的概念。

总的来说,统计学就是得出对整个 T2 人口有效的结论。人口是我们感兴趣的一切。当我们进行选举投票时,人口可以是所有有权投票的人。当我们研究推动广告点击率的因素时,人群就是我们可能向其展示广告的所有人。

然而,通常我们没有全部人口的数据。想象一下在你的国家对所有公民进行民意调查,或者向目标群体中的每个人展示你的广告。通常,我们只有人口中某个子集的数据,称为样本。这就是统计学的用武之地:它是一门仅基于样本得出关于人口的正确结论的科学。

人口是我们感兴趣的一切。样本是我们有数据的总体的一个子集。

重要的是要认识到,如果我们可以有一个以上的样本,他们可能会略有不同。想想不同的民意测验专家。他们正在进行类似民意调查,但是每个人都询问了不同样本的个人的政治倾向。因此,每个民意测验专家预测的特定政党的投票率会略有不同。所有民意测验专家的结果形成了所谓的**抽样分布。**它反映了统计分析结果的不确定性,这种不确定性是由于我们只有一个来自总体的特定样本而产生的。如果我们有不同的样本,我们的结果可能会略有不同。

抽样分布反映了由于我们只有一个特定的数据样本而产生的结果的不确定性。

中心极限定理

进入 CLT。其内容如下:如果我们从总体中抽取许多样本,并计算每个样本的*均值,那么这些*均值在样本中的分布(即*均值的采样分布)将是众所周知的正态分布,*均值与总体*均值相同,标准差等于总体标准差除以每个样本的观察次数。即使人口不是正态分布也是如此。

CLT:从多个样本计算出的*均值将形成一个具有已知*均值和标准偏差的正态分布。

让我们用一些数据来测试 CLT。考虑一下 100 万人的这种完全非正态的收入分布。这些人是我们关心的每一个人,我们的人口。

人口中的收入分配。由作者生成。

这个群体的*均收入是 2501 美元,标准差是 1444 美元。

现在,让我们从 1,000,000 人口中随机抽取 1000 个样本,每个样本 100 人,计算每个样本的*均收入。下面显示的是 1000 个样本中的前 4 个。

样本间的收入分布。由作者生成。

这 1000 人的*均收入分布是什么样的?几乎是正常的!

*均收入的抽样分布。由作者生成。

*均收入的抽样分布的*均值是 2502 美元,其标准偏差是 149 美元。顺便说一下,这些数字来自 CLT。根据定理,抽样分布的*均值应该与总体*均值相同(是 2501 美元——非常接*!),而抽样分布的标准差,称为标准差,应该是总体标准差除以每个样本的观测值个数的*方根,这里:$1444 / √100 = 144(差不多!).如果我们采集更多的样本,得到的样本分布将更接*正态分布。

最后一句话:我们已经研究了*均值的抽样分布,但是总和的正态性也成立。这是因为*均值就是总和除以一个常数。

我们刚刚从经验上验证了 CLT 确实有效。但这有多大关系呢?

CLT 与数据科学的相关性

你曾经拟合过线性回归模型吗?如果是这样,你依赖于 CLT。在回归模型中,目标取决于一个或多个特征加上附加误差项。我们假设这个误差项是正态分布的(相应地,在贝叶斯方法中,我们将目标建模为正态分布的随机变量)。这种假设的正态性可以用 CLT 来证明:我们可以把误差看作是由忽略重要特征或随机性引起的许多独立误差的总和。这许多误差中的每一个都可以有任何分布,但是它们的总和在 CLT 看来是*似正态的。

回归模型中误差正态性的假设可以通过将误差视为许多独立误差之和的 CLT 来证明。

类似的逻辑可以用来解释为什么现实世界数据集中如此多的变量看起来是正态分布的。这并不是因为正态分布在自然界中以某种方式占优势,而是因为我们经常可以将单个测量值视为许多小效应的加权*均值。想想你的考试成绩,它是你的知识的函数,但也是你考试当天的感觉,你前一天晚上是否睡得好,以及考试中出现了材料的哪些部分。

真实世界的数据往往类似于正态分布,因为测量值通常可以被视为许多小效应的*均值。

最后但同样重要的是,CLT 是假设检验的基石。在经典的测试方法中,我们需要提出所谓的参考分布:一个在一些假设下已知的分布,称为零假设。这有时可能很难,但当我们可以利用 CLT 时就不会了!

考虑这个例子:一家专门从事广告重定向的公司吹嘘他们精确定位的广告*均获得 20%的点击率。你用它们进行 1000 次展示的试验,观察 160 次点击。是针对性不够好,还是运气不好,*均 20%还是合理的?

由于数据是二进制的(点击和未点击),我们可以使用二项式分布对它们建模。如果关于 20% CTR 的说法是合理的,那么数据最好用*均值为 0.2 的二项式分布来描述。这个分布的标准差是 0.4(由于二项分布的标准差是√μ(1-μ),这里μ是均值:这里√(0.2*0.8) = 0.4)。

CLT 让我们很容易地推导出一些假设检验的参考分布。

因此,CLT 告诉我们,如果关于 20%点击率的说法是合理的,点击率的抽样分布将是正态分布,均值为 0.2,标准差为 0.4 / √1000 = 0.013。让我们将这一分布与我们在试点项目中观察到的 0.16 的 CTR 一起绘制出来。

CTR 与观测 CTR 的参考分布。由作者生成。

我们可以立即看到,如果关于 20% CTR 的说法是真的,我们观察到的 CTR 将是非常糟糕的运气。最有可能的是,该公司吹嘘得有点过头了!

查看我的假设检验者指南,看看如何量化这种厄运,形式化假设检验框架,并用它来避免做出愚蠢的决定。

感谢阅读!

如果你喜欢这篇文章,为什么不在我的新文章上 订阅电子邮件更新 ?而通过 成为媒介会员 ,就可以支持我的写作,获得其他作者和我自己的所有故事的无限访问权。

需要咨询?你可以问我任何事情,也可以在这里 为我预约 1:1

也可以试试 我的其他文章 中的一篇。不能选择?从这些中选择一个:

中心极限定理——解释清楚

原文:https://towardsdatascience.com/central-limit-theorem-clearly-explained-4fe60def52d6?source=collection_archive---------23-----------------------

抽样分布,标准误差

来自佩克斯的阿奇·比纳米拉的照片

中心极限定理

中心极限定理是推断统计中的重要概念之一。推断统计学是指从样本中对总体进行推断。

当我们从总体中抽取一个随机样本并计算样本的*均值时,由于抽样波动,它可能与总体*均值不同。样本统计量和总体参数之间的变化称为抽样误差

由于这种抽样误差,可能很难从样本统计中推断出总体参数。中心极限定理是推断统计学中的重要概念之一,它帮助我们从样本统计量中推断出总体参数。

让我们在本文中详细了解一下中心极限定理

参考我的 推理统计 的故事——了解概率和概率分布的基础知识

目录

  1. 统计、参数
  2. 抽样分布
  3. 标准误差
  4. 采样分布属性
  5. 中心极限定理
  6. 置信区间
  7. 可视化采样分布

什么是统计和参数?

统计 →代表样本特征的数值称为 统计

参数 →代表人口特征的数值称为 参数 。(我们从人口统计中推断出的数值)

统计量→样本标准差 S ,样本均值 X

参数→总体标准差 σ ,总体均值 μ

我们从统计数据到参数进行推论。

抽样分布

抽样 →指从总体中抽取有代表性的样本。

抽样分布 →抽样分布是从总体中抽取的给定样本的样本统计的所有可能值的分布。

均值抽样分布是从总体中选取的给定样本量的样本均值分布。

抽样分布的步骤:

  • 我们将从总体中随机抽取 (s1,s2…sn)
  • 我们将计算样本的*均值 (ms1,ms2,ms2…msn)。
  • 然后我们将计算抽样*均值。 (ms)

ms=(ms1+ms2+…msn)/n

n→样本量。

[现在我们已经计算了抽样*均值的*均值。接下来,我们必须计算抽样*均值的标准偏差]

标准误差

抽样分布中样本均值的可变性是标准误差。抽样分布的标准偏差称为*均值的标准误差。

*均值的标准误差=总体的标准偏差/sqrt(n)

n-样本量

[标准误差随着样本量的增加而减小。因此大样本有助于减少标准误差]

抽样分布属性。

  1. 抽样*均值等于总体*均值。

[当我们从人群中随机抽取许多样本时,这些差异就会相互抵消。因此,抽样*均值等于总体*均值]

2.抽样分布的标准差等于总体的标准差除以样本大小的*方根。

作者图片

中心极限定理

中心极限定理指出,即使总体分布不是正态分布,如果我们从总体中抽取足够大的样本,抽样分布也将是正态分布。[对于大多数分布,n>30 将给出一个接*正态的抽样分布]

抽样分布性质也适用于中心极限定理。

置信区间

我们可以说,通过使用置信区间,总体均值将位于某个范围之间。

置信区间是总体参数的取值范围。

*总体均值的置信区间=样本均值+(置信水*值)均值的标准差

Z →与置信度相关的 Z 分数。

最常用的置信度

99%置信水*→ Z 得分= 2.58
95%置信水*→ Z 得分= 1.96 90%置信水*→ Z 得分= 1.65

使用 Python 和 Seaborn 的采样分布

例如:

  1. 假设我们要计算一所学校所有学生的*均分数。

学生人数= 1000。

population1=np.random.randint(0,100,1000)

2。检查人口分布

sns.distplot(population1,hist=False)

人口分布

人口不是正态分布的。

3。我们将从人口中随机抽取不到 30 人的样本。

sample_means1=[]
for i in range(0,25):
 sample=np.random.choice(population1,size=20)
 sample_means1.append(np.mean(sample))sample_m1=np.array(sample_means1)

4。采样分布

sns.distplot(sample_means1,hist=False)
plt.title(“Sampling distribution of sample mean”)
plt.axvline(sample_m1.mean(),color=’green’,linestyle=’ — ‘)
plt.xlabel(“Sample Mean”)

抽样分布接*正态分布

5。让我们检查一下抽样*均值和标准误差。

print (“Sampling mean: “,round(sample_m1.mean(),2))
print (“Standard Error: “,round(sample_m1.std(),2))
#Output:
Sampling mean:  47.96
Standard Error:  6.39

标准误差= 6.39 。让我们增加样本量,检查标准误差是否减小。

6。取大于 30 的样本量,并计算取样*均值

sample_means2=[]
for i in range(0,100):
 sample=np.random.choice(population1,size=50)
 sample_means2.append(np.mean(sample))sample_m2=np.array(sample_means2)

7。采样分布

sns.distplot(sample_means2,hist=False)
plt.title(“Sampling distribution of sample mean”)
plt.axvline(sample_m2.mean(),color=’green’,linestyle=’ — ‘)
plt.xlabel(“Sample Mean”)

抽样分布

现在抽样分布是正态的。

8。计算抽样*均值和标准误差

print (“Sampling mean: “,round(sample_m2.mean(),2))
print (“Standard Error: “,round(sample_m2.std(),2))# Output:
Sampling mean:  48.17
Standard Error:  3.89

增加样本量后,标准误差减小。现在标准误差是 3.89。

9。让我们验证一下我们的人口*均数

print (“Population Mean: “,round(population1.mean(),2))#Output:
Population Mean: 48.03

我们计算出抽样*均值为 48.17 ,大约等于总体*均值 48.03

10。计算 99%置信水*的置信区间。

Lower_limit=sample_m2.mean()- (2.58 * (sample_m2.std()))
print (round(Lower_limit,2))
#Output: 38.14Upper_limit=sample_m2.mean()+ (2.58 * (sample_m2.std()))
print (round(Upper_limit),2)
#Output: 58.19

置信区间= 38.14 — 58.19

结论

在本文中,我介绍了中心极限定理、抽样分布、标准误差和置信区间。希望你们都喜欢。

感谢阅读!

我的另一个关于统计学的博客。

https://pub.towardsai.net/inferential-statistics-for-data-science-91cf4e0692b1 https://pub.towardsai.net/exploring-descriptive-statistics-using-pandas-and-seaborn-1b8501e1f27f https://medium.com/analytics-vidhya/important-terms-in-statistics-machine-learning-4bfa5962e9be https://pub.towardsai.net/hypothesis-testing-test-of-mean-variance-proportion-77ec2bfdd749

请关注此空间,获取更多关于 Python 和数据科学的文章。如果你喜欢多看我的教程,就关注我的 LinkedIn推特

**点击这里成为中等会员:https://indhumathychelliah.medium.com/membership

用 Python 实现过程改进的中心极限定理

原文:https://towardsdatascience.com/central-limit-theorem-for-process-improvement-with-python-483126e33b07?source=collection_archive---------27-----------------------

估计退货管理的工作量,假设从商店收到的每箱商品数量呈正态分布。

中心极限定理框架—(图片由作者提供)

退货管理,通常被称为逆向物流,是从你的配送中心的零售点退回物品的管理。

在接收之后,产品被分类,组织,并检查质量。如果它们状况良好,这些产品可以在仓库中重新进货,并添加到库存计数中等待重新订购。

在本文中,我们将看到中心极限定理如何帮助我们基于历史记录的*均值和标准偏差使用正态分布来估计退货管理的流程的工作量**。**

💌新文章直接免费放入你的收件箱:时事通讯

**SUMMARY**
**I. Scenario
Problem Statement** As the Inbound Manager of a multinational clothing retail company you are in charge of workforce planning for returns management.
**Question** Can you estimate the probability to have less than 30 items per carton that you will receive every week?
**II. Central Limit Theorem** 1\. Definition2\. Application
3\. Probability to get <30 items per carton?4\. 95% probability to have less than k items per case? **III. Conclusion**

一.情景

问题陈述

你是一家跨国服装零售公司的入境经理,这家公司以男女老少的快速时尚服装而闻名。

你的一个主要问题是对退货流程的工作量缺乏了解。事实上,由于系统限制,您在收到商店退货之前不会收到提前发货通知(ASN)。

  1. 你用托盘接收从卡车上卸下的纸箱

卸货区—(图片由作者提供)

2。你打开箱子,检查退回的物品

质检工作站—(图片由作者提供)

对于每件商品(衬衫、连衣裙……),您的操作员需要执行:

  • 质量检查,以确保产品可以重新进货
  • 重新标记
  • 重新包装

您知道每个项目的生产率,并且您希望根据您在一周内将收到的个案例来估计小时的工作量。

根据过去 24 个月的历史数据,您可以:

  • *均每箱 23 件
  • 第 7 项的标准差

你的团队的规模通常是每个案例最多处理 30 件物品。如果超过这个阈值,你需要雇用临时工来满足你的每日产能目标。

问题

你能估计出每周收到的每箱少于 30 件商品的概率吗?

http://samirsaci.com

二。中心极限定理

你可以在这个 Github 库中找到完整的代码: 链接 我的作品集与其他项目: 萨米尔萨奇

中心极限定理被我的好朋友 Abdelkarim 定义为**‘数学中最美的定理’**,它建立了当我们添加独立的随机变量时,它们的归一化和趋向于正态分布,即使原始变量本身不是正态分布。

1.定义

为了简化理解,让我们介绍一些符号:

符号—(作者提供的图片)

在我们的例子中,总数量是从商店收到的纸箱的整个范围,*均每箱 = 23 件,标准差 σ =每箱 7 件。

如果你取 n 个纸箱样品 X n (例如一个样品可以是某一天收到的一批纸箱),我们有:

方程式—(图片由作者提供)

换句话说,这意味着如果我们使用 n 个样本随机测量每箱商品的数量,并且我们假设观察值独立且同分布(即同分布),样本*均值的概率分布将接*正态分布

注意:为了确保我们有独立且同分布的观察结果,我们假设样本是基于来自所有商店的退货批次构建的,范围覆盖 100%的有效 SKU。

2.应用

然后,可以假设*均件数/箱遵循正态分布,*均每箱 23 件和 7 箱标准偏差。

人口正态分布—(图片由作者提供)

每箱少 30 件的概率是多少?

3.获得<30 items per carton?

Probability to have less than 30 items/carton is **84.13%**

Population Normal Distribution — (Image by Author)

代码的概率

4.每箱少于 k 件商品的概率为 95%?

您的 KPI 目标是至少 95%的退货在同一天得到处理。

为了处理 95%的预期工作负载,您需要假设多少项来评估您的团队?

We have 95% of probability that X <= **34.51 items/carton**

人口正态分布—(图片由作者提供)

如果你根据 35 件/箱来确定你的团队规模,你将*均达到目标的 95%。

三。结论

关注我的 medium,了解更多与供应链数据科学相关的见解。

这种方法让你有可能根据强大的统计工具支持的假设来确定你的团队规模。

这种分析可以每年进行几次,尤其是在业务不断发展的情况下(更高数量的收藏、电子商务或新店开业)。

关于我

让我们连接上 Linkedin 和 Twitter ,我是一名供应链工程师,正在使用数据分析来改善物流运作和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

参考

[1]使用 Python、Samir Saci、链接的线性规划优化劳动力规划

宫颈癌的预测和概率分析(R)

原文:https://towardsdatascience.com/cervical-cancer-prediction-and-boruta-analysis-r-7214282ea1f8?source=collection_archive---------31-----------------------

通过使用 Boruta 特征工程和分类预测模型了解导致宫颈癌的因素来庆祝妇女历史月

宫颈癌(图片由 Unsplash 上的国家癌症研究所提供

简介

由于“女性历史月”即将结束,我想借此机会庆祝一下这个至今仍威胁着许多女性的健康问题。在美国,每年发现 11,000 例新的浸润性宫颈癌病例。尽管新病例的数量在过去十年中呈下降趋势,但它仍然在美国杀死了大约 4000 名妇女,在全球杀死了 30 万名妇女。 (Fontham et al .,2020) 越早发现,生存的机会就越大。因此,为了有效地消除这类疾病,我们需要创建一种机器学习算法,能够尽快检测出癌症。因此,对于期末项目,我将分析数据集:来自 UCI 的宫颈癌(风险因素)。(“UCI 机器学习知识库:宫颈癌(风险因素)数据集”,2017) 该数据集是在委内瑞拉加拉加斯的“加拉加斯大学医院”收集的。我计划混合使用 EDA、Boruta 的特性重要性分析和分类预测模型

数据准备

我们将通过加载必要的库和读取数据集来开始我们的项目。我们将使用 8 个库,1 个用于可视化,3 个用于数据操作,1 个用于特征重要性分析,3 个用于预测模型。

(图片由作者提供)

宫颈癌有 858 个输入,36 个变量,从人口统计信息、习惯到历史医疗记录。一些变量有缺失数据,因为患者出于隐私考虑拒绝回答。值得注意的是,许多变量被解释为由“?”引起的因素填充为缺失值的占位符

(图片由作者提供)

因此,在继续之前,我将检查数据的完整性,因为它可以隐藏我们正在寻找的实际汇总统计数据。有许多函数可以指示缺失值,如 NAs、零、负值或空白字符串,因此创建一个专门处理 NAs 的函数,然后绘制数据的完整性(无缺失)会更容易

(图片由作者提供)

数据操作

在我们对数据有了更好的了解之后,更好的做法是处理缺失的值,以便进行更深入的探索性数据分析。首先,我们创建一个函数来标识所有需要修复的列,然后创建一个函数来修复丢失的值。x="-1 "的原因是允许在“?”之后对它们执行数值运算导致它们都成为因素。“-1”也是一个很好的占位符,因为它清楚地表明该输入中存在某些内容。然后,我们将这两个函数应用到列上,稍后我们可以建立一个表示宫颈癌的属性。

此外,我们还创建了一个相关图来剔除不重要的变量。之后,我们需要切断小于 0.7 的任何组合的相关性。最终的结果将会是这样的,表明一般来说,这些创建了高度相关的变量组合。

(图片由作者提供)

最后四栏(“Hinselmann”、“Schiller”、“细胞学”、“活组织检查”)表示子宫颈检查的结果。阳性结果并不意味着患者患有宫颈癌,但患者接受的阳性越多,这种可能性就越大。因此,我将根据以下公式创建一个名为“宫颈癌”的变量:

宫颈癌= Hinselman + Schiller + Citology +活检

(图片由作者提供)

探索性数据分析

在创建“宫颈癌”列后,我们可以看到大约 90%的患者没有任何症状,只有 1%的患者通过显示所有 4 种症状实际上显示了严重的情况。

(图片由作者提供)

在创建“宫颈癌”列后,我们可以看到大约 90%的患者没有任何症状,只有 1%的患者通过显示所有 4 种症状实际上显示了严重的情况。

因此,我们可以说,预测每个人都不会患癌症的基线模型的准确度将有 88%的高准确度

(图片由作者提供)

当我们观察密度图中患者的年龄时,每个密度图中的峰值都明显变得荒凉,表明“年龄”和“子宫颈癌”之间的相关性很强

(图片由作者提供)

此外,当观察“激素避孕年”和“宫颈癌”时,也有峰高度降低,密度图的右偏度也表明有很强的相关性。虽然我们有可能对它们中的每一个都这样做,但更好的办法是采用一种更快的方法来找到对像 Boruta 这样的“宫颈癌”影响最大的特征

用 Boruta 进行特征重要性分析

Boruta 方法通过对预测值进行混洗,并将它们与原始预测值连接起来,并在合并的数据集上构建随机森林,来评估特征的重要性。之后,我们将原始变量与随机化变量进行比较,以衡量它们的重要性,并选择重要性比随机化变量高的变量。 (Deepanshu Bhalla,2017) 人们通常认为 Robuta 优于 R 中其他特征选择包,这要归功于它的各种优势:

适用于分类和回归分析,因为它考虑了多变量关系

对随机森林变量重要性度量的增强,可以处理变量之间的相互作用以及改变随机森林重要性度量的性质

在本练习中,Boruto 流程从创建原始数据集的副本开始,但是删除了医疗结果列。然后我们设置种子,使用 Boruta()函数。情节如下

(图片由作者提供)

我们确认了 15 个,排除了 7 个,还有 10 个是暂定的。

(图片由作者提供)

这是被证实对因变量有影响的变量

(图片由作者提供)

从 Boruta 导出的最终结果的数据帧可以在 R 文件中找到

预测模型

我们将创建一个新变量“C _ 宫颈癌”,包含所有上述“已确认”变量和“宫颈癌”。对于癌症的可能性,我们将这些值指定为是或否。由于这是一种非常关键的癌症类型,并且是针对一小部分潜在癌症患者的,因此我们最好认真对待所有症状(1-4 ),而不是遗漏任何症状,并给它们分配 1,其余的为 0。然后,我们将目标特征编码为因子,并将数据集分成 0.75/0.25 比率的训练集和测试集进行预测。

支持向量机

支持向量机(SVM)的目标是在 N 维空间中找到一个超*面(N-明确分类数据点的特征的数量。有许多可能的超*面来对它们进行分类,但是我们想要找到一个具有最大余量(两个类的数据点之间的距离)的*面。一旦实现,未来的数据点可以更有把握地执行强化和分类,如下图所示。(罗希特·甘地,2018) 。在这个项目中,我们选择类型为“C-分类”,内核为“线性”

(来源:https://towards data science . com/support-vector-machine-vs-logistic-regression-94cc 2975433 f)

决策树

决策树模型通过将输入分解成更小的决策来做出判断。决策树的优势在于它的过程具有可理解的规则,并执行分类任务,而不管计算能力如何。它对连续变量和分类变量都很有效,为研究者提供了一个清晰的指示,表明哪些自变量是必不可少的。无论如何,不建议过于频繁地使用连续属性,这可能会产生错误,有时甚至在少量的训练样本上也会耗费精力。决策树用于动物图片分类等任务。

(来源:https://www . aitime journal . com/@ AK shay . chavan/a-comprehensive-guide-to-decision-tree-learning)

随机森林

这是决策树的高级版本,除了提出的问题,包括一些随机性。该算法通过“装袋法”创建了一个“森林”,即迷你决策树的集合。然后将所有的树合并在一起,以获得更准确和稳定的预测。不幸的是,随机森林在处理有噪声的数据时经常会过拟合。(基里尔·富克斯,2017) 。在这个项目中,我们选择的树木数量是 500 棵

车型对比与精度对比与召回权衡

运行完所有模型后,我们可以构建如下混淆矩阵表。

(图片由作者提供)

我们将使用精确度和召回率作为模型性能评估的指标。精度(特异性)是关于确保模型的准确性,指示在检索的例子中相关例子的分数。另一方面,回忆(敏感度)是关于模型获得正确实例的能力。精确度和召回率的范围从 0 到 1,越高越好。值得注意的是,这里有一个权衡,意味着当精度上升时,召回失败,反之亦然。研究人员经常使用像 F1 分数这样的抽象指标来做出决定,F1 分数是两者的结合。然而,在识别宫颈癌患者这样的危险情况下,回忆比精确更重要,因为错误治疗的成本可能很高,但没有错误错过潜在癌症患者的机会成本高。幸运的是,我会选择随机森林方法,因为与其他方法相比,它具有最高的召回率(0.8826)和精确率(0.5)。(塞缪尔·希利斯&莎拉·霍曼,2016) 。最后但同样重要的是,虽然我很想通过 GridSearch 和 K Folds 交叉验证来提高这个模型的准确性,但我不认为这是一个好主意,因为它是一个非常小的数据集,我们可能会过度拟合。

结论

总之,宫颈癌是最威胁生命的疾病之一,每年导致数千人死亡。但是实现上面这样的随机森林方法,相信以后可以拯救很多人。

— — —

Github:https://Github . com/lukastuong 123/R-Studio/tree/master/Project-% 20 宫颈% 20 癌% 20 检测

参考资料和资源:

Deepanshu Bhalla。 (2017 年 8 月 5 日)。特征选择:用 Boruta 包选择重要变量。2021 年 2 月 22 日检索,来自https://www . listen data . com/2017/05/feature-selection-boruta-package . html

丰瑟姆,E. T. H .,沃尔夫,A. M. D .,丘奇,T. R .,埃齐奥尼,r .,弗劳尔斯,C. R .,赫齐格,a .,…史密斯,R. A. (2020)。*均风险个体宫颈癌筛查:美国癌症协会 2020 年指南更新。 CA:临床医生的癌症杂志70 (5),321–346。https://doi.org/10.3322/caac.21628

基里尔·富克斯。 (2017)。机器学习:分类模型。2021 年 2 月 22 日检索,来自https://medium . com/fuzz/machine-learning-classification-models-3040 f71e 2529

甘地。 (2018 年 6 月 7 日)。支持向量机-机器学习算法介绍。检索于 2021 年 2 月 22 日,来自https://towardsdatascience . com/support-vector-machine-introduction-to-machine-learning-algorithms-934 a 444 FCA 47

塞缪尔·希利斯,莎拉·霍曼。 (2016 年 1 月 16 日)。理解权衡。检索于 2021 年 2 月 22 日,来自https://medium . com/OPEX-analytics/why-you-need-to-understand-the trade-off-of-precision-and-recall-525 a 33919942

— — —

数据集:UCI 机器学习知识库:宫颈癌(风险因素)数据集。 (2017)。检索于 2021 年 2 月 22 日,来自https://archive . ics . UCI . edu/ml/datasets/子宫颈+癌症+% 28 风险+因素%29

灵感来源:https://www . ka ggle . com/divyabongouni/key-宫颈癌-预测-与-boruta

Wav2Vec2 和变压器的“链式链接”NLP 任务

原文:https://towardsdatascience.com/chain-linking-nlp-tasks-with-wav2vec2-transformers-7297181db3a7?source=collection_archive---------19-----------------------

从音频直接进入一系列基于文本的自然语言处理任务,如翻译、摘要和情感分析

图表:蔡钦汉

拥抱脸的变形金刚库中增加了 Wav2Vec2 模型,这是*几个月来 NLP 中更令人兴奋的发展之一。在那之前,如果你只有一个很长的音频片段,执行机器翻译或情感分析等任务并不容易。

但现在你可以一气呵成地将 NLP 任务的有趣组合联系起来:用 Wav2Vec2 转录音频片段,然后使用各种 transformer 模型来总结或翻译转录本。你能联系起来的 NLP 任务的可能排列和组合是相当令人难以置信的。

当然,结果可能是不完整的。一些 NLP 任务,比如总结,本质上是很难解决的。

这篇文章是我之前的关于 Wav2Vec2 试验的后续,将概述 2 个试验:

  • #1:语音转文本转翻译&情感分析
  • #2:语音转文本转摘要

回购、要求和参考

试用所需的笔记本和音频文件在我的 repo 里。此外,您还需要这些来运行笔记本电脑:

  • 变压器≥ 4.3
  • Librosa (管理音频文件)

通过 Github 上拥抱脸的机器学习工程师弗拉达利·吉克的帖子,大多数笔记本中的代码已经更新,以使用更好的方法来转录长音频文件。

在我早期的工作中,我使用 Audacity 手动将长音频剪辑分割成更小、更易管理的片段(长度超过 90 秒的音频剪辑往往会导致本地机器和 Colab 崩溃)。弗拉达利的代码通过使用 Librosa 将长音频剪辑转换成较短的固定“块”来消除这一步骤。

在 Hugging Face 的 model hub 上有几个版本的 Wav2Vec2 模型。在这篇文章中,我将使用wav2 vec 2-large-960h-lv60-self型号。

试验#1:转录+翻译+情感分析

通过美国消费者新闻与商业频道电视台的 YouTube 频道在右边截屏

对于这次试验,我选择了美国总统乔·拜登在 2021 年 3 月 11/12 日(取决于你在哪个时区)的第一次黄金时间演讲。

他的演讲大约有 24 分钟长,我通过 25 秒的组块将它传输到 Wav2Vec2。你可以选择更长或更短的块。我发现 25 可以给出不错的结果。详细情况在我的回购中的 notebook3.0 里,这里不再赘述。

演讲很复杂,众所周知,拜登一直在与口吃作斗争。剧本(直接下载这里)的某些部分相当粗糙,尤其是接*结尾的部分:

点击此处下载原始 Wav2Vec2 抄本

公*地说,在我看来,拜登说得非常清楚,这是 Wav2Vec2 模式陷入困境的一个例子。但是,在我 2015 年末的 iMac 上,这个模型只花了 12 分钟左右就生成了副本,这比我手动完成要快得多。

接下来,我想把拜登的演讲文本输入机器翻译模型,看看中文翻译的质量如何。我用了拥抱脸的 MarianMT 的实现来做这个,因为我已经在之前的几次演讲中试过了。

不幸的是,结果几乎无法使用。点击此处下载完整的中文翻译:

从技术角度来看,“链式链接”过程工作得很好,在 Wav2Vec2 过程之后,您只需要大约 10 行额外的代码。

但是,当原始抄本中有问题的部分在没有彻底清理丢失或错误的单词以及正确的标点符号的情况下被输入到 MarianMT 模型中时,翻译的质量明显受到影响。我添加了句号(“.”)出现在 Wav2Vec2 中每段 25 秒的文字记录的末尾,但这显然没有捕捉到原始演讲中每个句子的正确开头和结尾。

因此,虽然看起来“链式链接”NLP 任务可以节省大量时间,但一个领域中的问题可能会复合,导致更下游的任务的质量更低。

显然,清理原始的英文文本需要额外的时间。但我相信这样做会大大提高中文翻译的质量。至于准确的标点,目前在 Wav2Vec2 内还没有快捷的方法。但我怀疑这种模式的未来版本会解决这个问题,因为市场上的一些自动语音识别服务已经具备了“添加标点符号”的功能。

接下来,我想尝试将情感分析应用到拜登的演讲中。语音到文本与情感分析的结合在政治或商业环境中非常有用,在这些环境中,快速了解说话者的情感可以影响某些决策。

原始文字被转换成一个简单的数据框架,然后我使用拥抱脸的变形金刚管道和 Plotly 生成一个“情绪结构”图,如下图所示。我已经试验这些情绪图表有一段时间了。我早期的实验可以在这里找到。

这比尝试中文翻译要好得多,尽管我确信情感分析也将受益于彻底的清理和在原始英文抄本中包含适当的标点符号。

从技术上来说,没有理由为什么一个人会只完成三项任务。您可以很容易地再编写几行代码,并将汇总作为连续的第四个 NLP 任务。

但是,包括演讲在内的长文本文档的自动摘要仍然是一项极具挑战性的任务,即使对于 transformer 模型来说也是如此。在我看来,这一结果还不成熟。让我们在下一次试验中仔细观察一下。

试验#2:转录+总结

通过新加坡总理办公室的 YouTube 频道截图。

为此,我选择了一个较短的音频剪辑,一个 4 分钟的视频,内容是新加坡总理李显龙在 2019 年的一次商业会议上回答一个关于民粹主义的问题。该剪辑集中在一个单一的问题,但有足够的复杂性,它是任何自动总结模型的挑战。

详见我的回购中的记事本 3.1 。

Wav2Vec2 输出非常出色,如下图所示(或者在这里下载)。这里和那里有一些小失误,但没有什么是你不能很快清理干净的。

我运行了两个变压器模型的原始抄本,FB 的“ bart-large-cnn ”和谷歌的“ pegasus-large ”。

这是来自 Bart 的结果:

这是飞马座的总结:

两个模型都很好地捕捉到了演讲者对民粹主义的宽泛定义,随后加入了他对新加坡如何试图避免这一问题的阐述。

但 FB-Bart 模型没有捕捉到李先生评论第二部分的任何细节。与此同时,飞马模型从他评论的第一部分抓住了太多,而对后半部分抓得不够。在我看来,这两个版本都算不上一个好的总结,尽管公*地说,这两个模型都没有受过政治演讲的训练。

因此,我们再次看到,通过 Wav2Vec2 和 transformers 链接 NLP 任务在技术上是可行的,但结果并不总是令人满意。

结论

对于在 NLP 工作的人来说,这是令人兴奋的时刻,Wav2Vec2 看起来将开辟一个全新的可能性范围。随着拥抱脸发起冲刺,将 Wav2Vec2 扩展到其他语言(英语之外),NLP 任务的“链式链接”范围只会越来越大。

但是考虑到 Wav2Vec2 现有的限制和许多 NLP 任务(如总结)中固有的困难,在这个过程中添加一个“暂停”按钮可能更明智。

我的意思是,如果原始的 Wav2Vec2 转录物在被送到下游的其他 NLP 任务之前被清除,结果会更好。否则,成绩单上有问题的地方会变得复杂,导致其他地方的成绩低于标准。

和往常一样,如果你在这篇文章或我之前的文章中发现了错误,请联系我:

  • 推特:蔡锦鸿
  • 领英:【www.linkedin.com/in/chuachinhon

这个帖子的回购,包含图表的数据和笔记本,可以在这里找到。

线性回归:pythons sklearn 与‘从头开始写’的比较

原文:https://towardsdatascience.com/challenge-can-i-do-linear-regression-without-sklearn-3151d8fc8aa?source=collection_archive---------9-----------------------

曾经想知道 python 的 sklearn 中多元线性回归/梯度下降的幕后发生了什么吗?你会惊讶它是多么容易。让我们从头开始写,并对两者应用相同的评估方法,看看我们做得如何。

作者 Sani2C 线性回归能让我骑得更快吗?

介绍

所以,从理解的角度来看,理解线性回归中发生的事情是很好的。这里是一个没有使用 python 库的的的深度探索。这里有一个链接指向 github 中这篇文章的源代码。如果你确实需要梯度下降的介绍,先看看我的 5 集 YouTube 系列。

在第一步中,我们将从头开始编写梯度下降,而在第二步中,我们将使用 sklearn 的线性回归。

我们的数据集

让我们从 kaggle 下载我们的数据集。世界卫生组织(世卫组织)下属的全球卫生观察站(GHO)数据库记录所有国家的健康状况以及许多其他相关因素。这些数据集向公众开放,用于卫生数据分析。与 193 个国家的预期寿命、健康因素相关的数据集从同一个世卫组织数据库网站收集,其相应的经济数据从联合国网站收集。

图 kaggle 的屏幕截图

步骤 1:线性回归/梯度下降从零开始

让我们从导入我们的库开始,看看前几行。

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from sklearn.preprocessing import LabelEncoder
from sklearn import metricsdf = pd.read_csv(‘Life Expectancy Data.csv’)
df.head()

您将看到一个很好的数据视图,可以看到我们有国家和状态文本字段,而“预期寿命”是我们想要预测的字段。

图 jupyter 的屏幕截图

为了获得更多的洞察力,让我们运行一个 info,我们将在图 3 中得到下面的 info。

  • 我们有 2 个文本字段,即。国家和地位
  • 酒精、乙肝等领域。有我们需要解决的空值
  • 列名需要一些工作
df.info()

图 jupyter 的屏幕截图

准备数据

这些名称不适合使用,所以让我们重命名一些列。然后将对象字段转换为数字,因为我们不能处理文本。最后,让我们将 Y 移动到它自己的数组中,并将其从“df”中删除。这种陡峭的结果是,‘df’是我们的特征集并且只包含数字,而‘y’是我们的结果集。

df.rename(columns = {“ BMI “ :”BMI”,
  “Life expectancy “: “Life_expectancy”,
  “Adult Mortality”:”Adult_mortality”,
  “infant deaths”:”Infant_deaths”,
  “percentage expenditure”:”Percentage_expenditure”,
  “Hepatitis B”:”HepatitisB”,
  “Measles “:”Measles”,
  “under-five deaths “: “Under_five_deaths”,
  “Total expenditure”:”Total_expenditure”,
  “Diphtheria “: “Diphtheria”,
  “ thinness 1–19 years”:”Thinness_1–19_years”,
  “ thinness 5–9 years”:”Thinness_5–9_years”,
  “ HIV/AIDS”:”HIV/AIDS”,
  “Income composition of resources”:
  ”Income_composition_of_resources”}, inplace = True)# convert labels to numbers
columns = [“Status”,”Country”]
for feature in columns:
  le = LabelEncoder()
  df[feature] = le.fit_transform(df[feature])# extract Y and drop from data frame
Y = df[“Life_expectancy”]
df = df.drop([“Life_expectancy”], axis=1)

绘图相关矩阵

如果我们有一个包含许多列的数据集,快速检查列间相关性的一个好方法是将相关性矩阵可视化为热图。查看该矩阵,您可以看到 9 列具有高于 0.38 的最高相关性。我们只对“预期寿命”感兴趣,所以请看最下面一行的结果。

plt.figure(figsize = (24,16))
sns.heatmap(pd.concat([df,Y], axis=1).corr(), annot=True, cmap=”coolwarm”)

为了获得更好的结果,我们可以选择在相关矩阵中仅使用高于 0.3 的特征。

图 jupyter 的屏幕截图

为我们缺失的特征填入数值

回归的一个重要部分是理解哪些特征缺失了。我们可以选择忽略所有缺少值的行,或者用 mode、median 或 mode 填充它们。下面是一个手动函数,它基于以下三种方法之一来填充缺失值:

  • 模式=最常见的值
  • 中位数=中间值
  • *均值=*均
def fillmissing(df, feature, method):
  if method == “mode”:
    df[feature] = df[feature].fillna(df[feature].mode()[0])
  elif method == “median”:
    df[feature] = df[feature].fillna(df[feature].median())
  else:
    df[feature] = df[feature].fillna(df[feature].mean())

现在,查找缺少值的列,并使用我们方便的函数填充它们。让我们也填写 y 中任何缺失的值。

features_missing= df.columns[df.isna().any()]
for feature in features_missing:
  fillmissing(df, feature= feature, method= “mean”)Y.fillna(Y.median(), inplace=True)

获取 X/Y 数组

让我们将数据帧放入易于操作的数组中。

X = df.to_numpy() 
y = Y.to_numpy().transpose() 
m,n = X.shape

标准化 X

现在,让我们将 X 归一化,使其值介于-1 和 1 之间。我们这样做是为了让所有的特征都在一个相似的范围内。如果我们需要绘制数据,这很有帮助,但也能给出更好的线性回归结果。我们使用下面的等式,你应该看到你的特征现在归一化为类似于图 5 的值。

mu = X.mean(0) 
sigma = X.std(0) # standard deviation: max(x)-min(x)
xn = (X — mu) / sigma

图 jupyter 的屏幕截图

添加一列 1

现在在 X 上增加一列 1,以便稍后对我们的假设和成本函数进行更简单的矩阵操作。您的数据现在应该如图 6 所示,带有一列 1。

xo = np.hstack((np.ones((m, 1)), xn))

图 jupyter 的屏幕截图

梯度下降

创建梯度下降所需的变量。我们需要以下变量:

  • 重复=重复梯度下降的次数
  • θ=对于 X 的每个特征,增加一列θ0
  • 成本历史=保持梯度下降的每次迭代的成本
repeat = 1000
lrate = 0.01
theta = np.zeros((n+1))

让我们定义一个成本函数,梯度下降将使用它来确定每个θ的成本。成本函数将实现以下成本等式。

def computeCost(X, y, theta):
  m = len(y) # number of training examples
  diff = np.matmul(X, theta) — y
  J = 1 / (2 * m) * np.matmul(diff, diff) return J

我们现在进入梯度下降循环,在这里我们在每个循环上计算一个新的θ,并跟踪它的成本。参见下面的等式:

现在我们看到了这个方程,让我们把它放入一个方便的函数中

def gradientDescent(X, y, theta, alpha, num_iters):
  # Initialize some useful values
  m = len(y) # number of training examples
  J_history = [] # repeat until convergance
  for i in range(num_iters):
    hc = np.matmul(X, theta) — y
    theta -= alpha / m * np.matmul(X.transpose(), hc)
    # Save the cost J in every iteration
    J_history.append(computeCost(X, y, theta)) return theta, J_history

让我们运行梯度下降并打印结果

theta, J_history = gradientDescent(xo, y, theta, lrate, repeat)# Display gradient descent's result
print('Best theta computed from gradient descent: ')
print(f' {theta} ')

绘制梯度下降的成本

绘制成本历史以确保成本随着迭代次数的增加而减少。在绘制之后,您应该看到成本随着每次迭代而降低,如图 7 所示。

# Plot the convergence graph
plt.plot(np.arange(repeat), J_history, ‘-b’, LineWidth=2)
plt.xlabel(‘Number of iterations’)
plt.ylabel(‘Cost J’)
plt.show()

图 jupyter 的屏幕截图

预言;预测;预告

让我们用下面的等式来进行预测。

注意将一列 1 加到 X 上,然后使用矩阵乘法,一步就可以完成上面的等式。

y_pred = np.matmul(xo, theta)

评估预测

让我们使用均方根误差(RMSE ),它是*方误差*均值的*方根。下面是应用的等式,其结果将在以后用于比较。

让我们也算出每个预测占真实结果的百分比。然后用它来找出实际年龄的 90%到 110%之间的预测年龄。我们认为这对于计算最终精度是可以接受的。

# get RMSE error rate
print('RMSE: ',np.sqrt(metrics.mean_squared_error(y, y_pred)))# calculate our own accuracy where prediction within 10% is o
diff = (y_pred / y * 100)print('Mean of results: ',diff.mean())
print('Deviation of results: ',diff.std())
print('Results within 10% support/resistance: ', len(np.where(np.logical_and(diff>=90, diff<=110))[0]) / m * 100)

您现在将看到如下结果。如果我们对每一行的预测都在实际年龄的 10%以内,那么我们决定称之为成功。因此,我们最终达到了 90%的准确率。

图 jupyter 的屏幕截图

最后,让我们想象一下每个预测的准确性。自然, 100%是完美的预测

plt.plot(np.arange(m), diff, '-b', LineWidth=1)
plt.xlabel('Number')
plt.ylabel('Accuracy %')
plt.show()

图 jupyter 的屏幕截图

所以,现在我们已经看到了使用矩阵操作的线性回归,让我们看看结果如何与使用 sklearn 进行比较。

第二步:使用 sklearn 的线性回归

让我们使用 sklearn 来执行线性回归。这次你可以看到它的代码少了很多。一旦我们有了一个预测,我们将使用 RMSE 和我们的支持/阻力计算来看看我们的手动计算如何与一个经过验证的 sklearn 函数进行比较。

from sklearn import metrics
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split# Split data
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)# Instantiate model
lm2 = LinearRegression()# Fit Model
lm2.fit(X_train, y_train)# Predict
y_pred2 = lm2.predict(X_test)# RMSE
print('RMSE: ',np.sqrt(metrics.mean_squared_error(y_test, y_pred2)))# calculate our own accuracy where prediction within 10% is ok
diff2 = (y_pred2 / y_test * 100)print('Mean of results: ',diff2.mean())
print('Deviation of results: ',diff2.std())
print('Results within 10% support/resistance: ', len(np.where(np.logical_and(diff2>=90, diff2<=110))[0]) / len(y_pred2) * 100)

图 jupyter 的屏幕截图

结论

你可以看到我们的 RMSE 和支持/抵制百分比在两种方法中是相似的。很自然,你可能会使用 sklearn,因为它的代码少得多,但是希望这个例子向你展示了这些等式是如何工作的。

自然语言处理在情感分类中的挑战

原文:https://towardsdatascience.com/challenges-in-sentiment-classification-with-nlp-a20314600c3d?source=collection_archive---------41-----------------------

高等级不*衡的影响

克里斯·j·戴维斯在 Unsplash 上的照片

It 毫无疑问,对于任何数据科学和/或机器学习相关的任务来说,文本数据可能是我们可用的最大数据源。因此,许多复杂的和高性能的算法已经被发明来分析文本数据和预测它的情感。但是应用更先进的算法并不一定意味着我们的预测是高精度的。我们仍然需要回到基础,了解数据的本质,这对任何进一步的处理都是挑战。

我最*在自然语言处理领域进行了一项案例研究(这可能是我有史以来的第一个 NLP 项目),以分析推文及其对两大品牌的情绪:苹果和谷歌。这个项目的主要目的是将推文分为正面和负面或中性。这些数据集是由 Crowdflower 通过“data.world”提供的。数据集由大约 9000 条推文组成,分为四类:“正面”、“负面”、“中性”和“无法辨别”,我将它们重新组织成三类,如下所示:

从这里,人们可以很容易地看到,这是高度不*衡的阶级状况。尽管如此,我还是决定继续为快速脏分类任务准备数据。当然,我们必须至少做一些分类器可以接受的基本文本预处理。我应用的一些基本预处理包括:

  • 扩展缩略词,如“不是”:“不是”、“不会”、“不会”、“不会”等。
  • 小写所有文本,删除非字母字符串,@,超链接,停用词,少于 3 个字母的单词等。

下面是文本预处理代码片段的一个示例:

一些研究建议保留' # ',在这种情况下没有任何区别

干净的推文示例:

在对预处理感觉良好之后,我开始使用简单的分类器,比如传统的朴素贝叶斯和随机森林。出于矢量化的目的,我使用了 TFIDF 矢量器。下面是分类的快速结果:

朴素贝叶斯分类报告

随机森林分类报告

很明显,如果我们研究“回忆”值,我们可以看到两个模型都存在不*衡数据。此外,随机森林高度过度适合训练数据。所以,在这一点上,我满怀希望地转向了神经网络。显然,首先想到的是 LSTM 和 GRU. *但是在实现这些模型之前,我改变了文本预处理策略,以避免删除一些上下文中的停用词。*像 LSTM 和 GRU 这样的网络需要令牌形式的文本 dat,可按如下示例创建:

使用新的预处理文本,我执行了三种类型的 LSTM:简单的单向 LSTM、双向 LSTM 和带有手套嵌入的双向 LSTM。此外,我还在类似配置的 GRU 网络上进行了培训。在我几乎所有的测试中,LSTM 和 GRU 都产生了相同的结果。因此,为了简洁起见,我将只显示 LSTM 的结果。对于预训练的手套模型,在模型中引入了一个*‘手套. 6b . 100d’*嵌入。包含 GLOVE 的代码随处可见,不过我还是提供下面的代码片段:

下图显示了上述三种 LSTMs 架构的培训结果。请注意,启用了提前停止,因此不同的模型在不同的时间停止。还要注意,我训练的最大历元是 20,这是因为在早期历元的验证数据中出现了大量训练过度。

那么我们在这里得到了什么?从一开始,更先进的模型就不能推广这个模型。戴着预训练手套模型的 LSTM 似乎表现稍好,但仍然差得很远!

还要记住,一开始的班级失衡,是不是影响了我们的模型表现?模型拟合参数中还包括类别权重字典。这对于提高模型性能没有任何帮助。还尝试了其他方法,如 SMOTE、随机过采样器/欠采样器。然而,这些方法对这个数据集都没有帮助。最后,我决定通过增加物理数据来解决班级不*衡的问题。

数据扩充

在这种情况下,我找到了推文文本,但是推文与苹果相关产品相关。然而,文本的情感可以与任何特定品牌无关,只要它有与情感相关的关键词。怀着这个希望,我将 只添加了负面分类的 到我当前的数据集中,并重新运行上述算法。

扩充后的类别分布

朴素贝叶斯分类报告

随机森林分类报告

虽然整体准确率只是略有提高,但我很高兴负面类的*【回忆】*有所增加。因为,在任何市场情绪分析中,尽可能准确地预测人们的负面观点是很重要的。那么,神经网络在新的扩充数据集中表现如何。

增强前后嵌入手套的双向 LSTMs

我们可以看到模型性能有一些轻微的改进。训练过度仍然是一个大问题。在这一点上,我应该把更多的注意力放在优化模型架构上。在测试不同模型架构组合时,先测试多个 LSTMs 层,然后测试密集层,最大的影响来自于 dropout 参数的调整。

注意:最大纪元被设置为 20,但是模型停止得更早

我们可以看到,在 LSTM 层之前包含漏失参数似乎表现得更好。我通常对一次下降超过 20%持谨慎态度,但在这个特定的案例中,高达 30-40%的下降似乎没问题。我的最终模型(LSTM 和 GRU)只能以大约 70%的准确率预测一条给定的推文。对于 NLP 任务来说,这并不是一个很好的结果,然而,考虑到具有挑战性的数据集,预处理 a 模型优化显示了有希望的结果。

最终模型对比:LSTM vs GRU

推文预测示例

最后的想法

该数据集需要做大量工作,尤其是数据扩充结果所支持的*衡类标签的收集。然而我的问题是:一个大约 9000 条推文的文本数据集,对于像 LSTM 和 GRU 这样的建筑来说足够好吗?

在下一步中,我将尝试对这个数据集使用 transformer 模型。

完整的笔记本和必要的文档可以在我的 github 网站上找到:https://github . com/sgautam 666/Brand _ 情操 _ 分析 _with_NLP

参考

https://data.world/crowdflower/brands-and-product-emotions

https://data.world/crowdflower/apple-twitter-sentiment