释放分析和实验力量的实用方法
我们不能通过雇佣分析师来“打开”分析文化。它需要对整个组织进行积极的监控和指导,以产生真正的影响!
来自 Unsplash 的海蒂·芬(Heidi Fin)拍摄的照片(链接)
如果没有决策要做,就没有分析的需要,导致没有数据的需要,从此没有价值要用数据来创造!
在当前的时代,每个人都是数据驱动的,每个组织策略都围绕着数据,每一次炒作都是关于人工智能/ML 的魔杖。然而,大多数企业都难以从数据中获取价值并建立分析文化。仔细观察实际情况就会发现,对分析的期望往往与组织对做出数据驱动决策的承诺不相符合。
我们经常听到从数据中创造价值的说法。但在现实中,如果没有决策要做,就不需要分析,导致不需要数据,从此没有价值要用数据来创造!如果不产生实际的数据需求,它可能会成为另一种没人关心的僵尸资产。数据驱动型业务的基本重点是如何做出决策。
当业务从一无所知的、基于意见的决策转变为知情的、基于证据的科学决策时,分析成熟度自然会到来。后者自然需要数据和相关的专业知识。
分析领导者在全新环境中的典型旅程(作者插图)
本文将分析的范围定义为“从数据或统计的系统分析中获得的见解”,主要是决策支持。
在过去的十年里,我在从大公司到初创公司和咨询公司的各种业务中建立了多个数据团队。我目睹并参与了许多挖掘数据潜力的尝试。如上图所示的旅程有许多平行的线索,总是从乐观的投资观点开始,到证明投资的影响和回报结束。如果管理层确信,就会投入更多的投资,循环就会重复。
…当数据驱动的决策成为组织中每个成员的习惯时,分析文化就形成了
根据我的经验,这个周期中最关键的部分总是衡量和展示分析的影响。没有它,周期会变慢,分析变得更像一项服务,而不是“变化的引擎”。
分析主要是一个决策支持角色,需要整个组织与之合作。因此,这样一个功能的成功更多的是朝向科学过程而不是结果。正如 Sudaman (安联比荷卢经济联盟的区域首席数据和分析官)在数据框架播客中提到的,当数据驱动的决策成为组织中每个成员的习惯时,分析文化就形成了。
我在跟踪和测量分析文化方面的研究总是会导致许多带有定性指标的分析成熟度阶段的广泛和抽象的定义。这些可能有利于 CXO 在大型组织的层面上做出战略投资决策,但对我来说几乎毫无用处。通常,管理顾问用这一点为大老板指出分析成熟度的未来之路。
但作为一名现场分析领导者,我想关注实际影响的问题:“我应该做些什么来帮助团队朝着基于数据的决策的正确方向前进?”有没有简单的方法来跟踪和监控团队如何利用基于数据的决策?这是否可行,以便领导可以积极使用这些指标来识别瓶颈?
在这里,我提出了一种可量化和可操作的方法来跟踪分析和实验在一个组织中是如何使用的,以及如何释放其潜力。
分析影响漏斗!
分析影响漏斗由作者概念化并呈现
是的,你是对的。上面的漏斗看起来太熟悉了。这是我们在互联网上看到的标准创新漏斗。我只是将这些应用于分析和实验。让我们通过每个阶段和指标来跟踪,以确保漏斗性能。
漏斗顶端
领导者应该引导团队成员发现需要解决的问题,并开始创建实验、测试和学习的积压工作。这里的关键是不断填充漏斗并保持分析能力。随着分析成熟度的提高,我们经常会看到指数级增长,导致分析团队能力耗尽,利益相关者要求更多的见解!没有任何分析项目可以交付,就证明影响而言,这场战斗已经失败了。
分析项目的机会可能来自任何人:无论是从事产品工作的人、查看数据的人、用户研究人员、最终用户反馈等。分析团队应该有一种机制来捕捉这些机会,根据业务目标标记和组织它们。这些可以是标准的请求表格,或者使用吉拉等工具。每一个商业机会都应该以同样的真诚对待,以确保我们不会以一种狭隘的思维结束,也不会不适当地拒绝一个好主意。
科学的优先顺序框架(由作者提交,链接此处
任何提出想法的成员都应该使用第一原则方法详细阐述商业价值和影响。对于一个组织来说,这是最好的标准化。
获得首肯
…一个高度集中的组织是一个联合的团队代表其业务领导思考的地方
这些想法经过了商业领袖的验证,他们会考虑赞助这些想法。尽管创意的产生需要“跳出框框”的思维,但它们应该在很大程度上与业务目标保持一致。当一切顺利时,一个高度集中的组织就建立起来了,在那里,一个联合的团队代表其业务领导进行思考。
很明显,一个更好的联盟将有更高的机会让商业领袖赞助提议的项目。项目赞助的水平代表了战略一致性。为了跟踪这一点,我们可以使用战略一致性分数,这是赞助想法与提交的提案总数的比率。由于此分数是在战略和愿景层面上衡量的,因此应该在更广泛的范围内(跨部门或业务单位)进行衡量,而不是在特定的团队层面。
当得分较低时,高层和中层经理有责任找出缩小差距的方法。造成这种差距的通常原因是业务/战略团队和技术/运营团队之间缺乏联系。这通常是由于缺乏与高层管理人员的沟通和接触造成的。组织需要充满激情的人,他们是不可思议的工作狂。但是如果不对齐,这些马就会朝各个方向拉!
说服团队
…分析和实验的核心目的是增加企业的可选性!
选择性被定义为“可供选择但不是强制性的品质”。说白了,分析和实验的核心目的是增加企业的可选性。但是,只有当企业有能力行使它们时,可选性才是有用的。主要的问题往往是克服惰性,走向探索,而不仅仅是利用已知的问题。
虽然企业领导赞助一个项目,但基层团队可能有不同的优先级。为“可能”受益的项目提取资源可能是一场艰难的对话。分析领导者应该具有情境同理心,以理解团队的每个优先事项,并相应地对实验进行排序。
当一切顺利的时候,这些团队会很乐意接受赞助的实验。这可以通过业务接受率来衡量,业务接受率被定义为实际接受的实验数量与受资助项目总数的比率。较低的接受率可能意味着错过机会或不同团队之间在业务优先级上缺乏一致性。造成这种情况的原因可能是业务发起人没有认识到优先级,也可能是执行团队没有足够的能力。
做出决定
…我们应该绝对区分实验的方式和实验的结果
艰难的部分已经完成了。现在,进行实验,分析结果,并提出选择。但是,它导致了具体的决定吗?
让我非常明确地说:我们应该绝对地区分实验的方式和实验的结果。一个不正确的实验是一个有缺陷的过程,导致不确定的结果,阻止具体的决策。即使一个完美的实验,负面或无影响的结果是可以预期的。
理想情况下,我们希望每个实验或分析概念验证都能产生建议和决策。我们可以通过有效性得分来衡量这一点,有效性得分被定义为进行的实验数量与做出的结论性决策之间的比率。分数少了,我们就需要自省为什么一个实验没有结论。
实验没有做好可能有很多原因。这包括不清楚的问题定义和范围,不充分的样本大小和统计能力,错误的计算,错误的测量,没有考虑次要影响,错误的时间安排等。
接受决定
每一个决定都应该有一个与之相关的行动和结果。当团队完全相信决策时,会立即采取行动,表明对决策的信任。我们可以通过接受分数来衡量信任程度,接受分数被定义为采取的行动与做出的决定的比率。
缺乏后续行动可能意味着对实验或决策缺乏信任。如果决策的背景和团队的关注点之间存在脱节,也会出现这种情况。由于计划和进行实验需要合理的时间,业务优先级的频繁变化会破坏实验的流程和行动的相关性。因此,在将实验转化为行动的过程中,企业和组织的稳定性至关重要。
漏斗底部
在大多数组织中,这是一个经常被忽略或不完整的关键部分。根据我的观察,漏斗通常会在记录下所采取的行动后停止。然而,我们应该继续监测结果并量化预期的影响。
…不承担风险的过于谨慎的团队或不惜一切代价避免失败的团队可能会破坏成功的衡量标准
业务影响可能有多种形式,如运营改善、销售提升、利润提高、客户参与度等。关键是使用通用指标(通常以货币形式)量化这种影响。有了这些信息,我们就可以将成功率定义为积极的净结果与采取的行动总数的比率。虽然高比率是可取的,但成功的度量可能会被不承担风险的过于谨慎的团队或不惜任何代价避免失败的团队所破坏。因此,还应该注意高成功率。
最后一个指标是投资回报率,它是通过各种实验产生的总商业价值与分析领域总投资的总和。实验&的实施是跨团队跨职能的努力。因此,应采用可接受的方式计算归属于分析的回报部分。建议有一个比复杂模型更粗糙的&有意义的归属。我们只需要耐心等待归因模型的进化。
提前计划
从长远来看,任何企业都应该看到这个漏斗发展和稳定。虽然更多的投资会导致漏斗顶端更胖,但也会给净收益和投资回报率带来压力。另一方面,缺乏投资或能力不足会使漏斗变得更细,表明机会成本的积累。
该漏斗是一种很好的方式,可以证明单靠分析团队无法创造奇迹并推动数据成熟。完善一个没有业务承诺的分析团队会导致失望和期望的不匹配。
同时,还应避免挪用其他团队职能的预算来推动对分析的更多关注。没有推向市场的产品,数据就不会产生,分析也不会有意义。
从分析和实验文化起步的组织可能会更好地拥有自上而下的授权,为这些漏斗设定最低 KPI。这些不仅仅是分析 KPI,而是对组织在其核心推动分析和实验方面的成熟度的总体衡量!
关于作者
Shyam 是数据领域的公认领导者,在建立技术和数据领域的全功能团队方面拥有丰富的经验。他目前在 Yara 领导全球数字解决方案的数据科学和分析团队。他热衷于战略和通过数据、分析和人工智能/人工智能创造切实的商业价值。
请在 LinkedIn 这里 随意连接和联系聊天。
参考
https://shyamdsundar.medium.com/prioritising-the-scientific-way-507d4200b6b8 https://www.forbes.com/sites/forbestechcouncil/2020/11/11/optionality-part-i-what-is-it-and-why-is-it-crucial/?sh=7bcae3a864b0 https://www.linkedin.com/posts/shyamdsundar_insights-datascience-analytics-activity-6717605677487017984-z5t1
阿特鲁(扩张的)和深度方向可分卷积的初级读本
思想和理论
什么是萎缩/扩张和深度方向可分卷积?与标准卷积有何不同?它们的用途是什么?
凭借权重共享和平移不变性等属性,卷积层和 CNN 在使用深度学习方法的计算机视觉和图像处理任务中变得无处不在。考虑到这一点,本文旨在讨论我们在卷积网络中看到的一些发展。我们特别关注的两个发展:阿特鲁(扩张)卷积和深度方向可穿透卷积。我们将看到这两种类型的卷积是如何工作的,它们与普通的卷积有什么不同,以及为什么我们可能要使用它们。
卷积层
在进入正题之前,我们先快速提醒一下自己卷积层是如何工作的。从本质上来说,卷积滤波器只是简单的特征提取器。以前手工制作的特征过滤器现在可以通过反向传播的“魔法”来学习。我们有一个在输入特征图上滑动的核(conv 层的权重),在每个位置,执行逐元素乘法,然后对乘积求和,以获得标量值。在每个位置执行相同的操作。图 1 显示了这一过程。
图 1:一个 3×3 卷积滤波器的作用[1]。
卷积过滤器通过在输入特征图上滑动来检测特定的特征,即,它在每个位置寻找该特征。这直观地解释了卷积的平移不变性。
阿特鲁(扩张)卷积
为了理解 atrous 卷积与标准卷积有什么不同,我们首先需要知道什么是感受野。感受野被定义为产生每个输出元素的输入特征图的区域的大小。在图 1 的情况下,感受野是 3×3,因为输出特征图中的每个元素看到(使用)3×3 输入元素。
深度 CNN 使用卷积和最大池的组合。这样做的缺点是,在每一步,特征图的空间分辨率减半。将所得的特征图植入到原始图像上导致稀疏特征提取。这种效果可以在图 2 中看到。conv。滤镜将输入图像缩减采样为原来的两倍。上采样和在图像上施加特征图表明,响应仅对应于 1/4 的图像位置(稀疏特征提取)。
图 DCNN 中的稀疏特征提取[2]。
阿特鲁(扩张)卷积解决了这个问题,并允许密集特征提取。这是通过一个叫做的新参数® 实现的。简而言之,atrous 卷积类似于标准卷积,除了 atrous 卷积核的权重被间隔开或个位置,即,扩展卷积层的核是稀疏的。
图 3:标准与膨胀的内核。
图 4:3×3 阿特鲁(扩张)卷积的作用[1]。
图 3(a)示出了标准内核,图 3(b)示出了具有比率 r = 2 的扩大的 3×3 内核。通过控制速率参数,我们可以任意控制 conv 的感受野。层。这使得 conv。过滤以查看更大的输入区域(感受野),而不降低空间分辨率或增加内核大小。图 4 示出了运行中的扩展卷积滤波器。
图 5。使用扩张卷积进行密集特征提取[2]。
与图 2 中使用的标准卷积相比,在图 5 中可以看出,通过使用比率 r=2 的扩展核来提取密集特征。只需将膨胀参数设置为所需的膨胀速率,即可轻松实现膨胀卷积。
扩展卷积:pytorch 实现
深度方向可分离卷积
深度方向可分离卷积是在例外网[3]中引入的。图 6 示出了标准卷积操作,其中卷积作用于所有通道。对于图 6 所示的配置,我们有 256 个 5x5x3 内核。
图 6:应用于 12x12x3 输入的标准 5x5 卷积。
图 7(a)示出了深度方向卷积,其中滤波器被应用于每个通道。这就是深度方向可分离卷积与标准卷积的区别。深度方向卷积的输出具有与输入相同的通道。对于图 7(a)所示的配置,我们有 3 个 5x5x1 内核,每个通道一个。通道间混合是通过将深度方向卷积的输出与所需数量的输出通道的 1×1 内核进行卷积来实现的(图 7(b))。
图 7:5×5 深度方向的可分离卷积,接着是 1×1 conv。
为什么选择深度可分卷积?
为了回答这个问题,我们来看看执行标准卷积和深度可分卷积所需的乘法次数。
标准卷积 对于图 6 中指定的配置,我们有 256 个大小为 5x5x3 的内核。计算卷积所需的总乘法:
256553(8*8 个位置)= 1228800
深度方向可分离卷积 对于图 7 中指定的配置,我们有 2 个卷积运算:
- 3 个大小为 5×5×1 的核。这里,所需的乘法次数是: 553(8*8 个位置)= 4800* 2) 256 个大小为 1x1x3 的核用于 1x1 卷积。所需乘法次数: 256113(8*8 个位置)= 49152 深度可分卷积所需乘法总数: 4800 + 49512 = 54312。
我们可以非常清楚地看到深度方向卷积比标准卷积需要更少的计算。
在 pytorch 中,深度方向可分离卷积可以通过将组参数设置为输入通道的数量来实现。
注意:py torch 中的组参数必须是 in_channels 参数的倍数。这是因为在 pytorch 中,通过将输入特征分成组=g 组来应用深度卷积。更多信息点击这里。
结论
这篇文章深入研究了两种流行的卷积类型:atrous(扩张)卷积和深度可分卷积。我们看到了它们是什么,它们与标准卷积运算有何不同,也看到了它们相对于标准卷积运算的优势。最后,我们还看到了如何使用 pyTorch 实现 atrous(扩张)和深度方向可分离卷积。
参考文献
[1]卷积运算(https://github.com/vdumoulin/conv_arithmetic)
[2]陈,梁杰,等,“Deeplab:基于深度卷积网、atrous 卷积和全连通条件随机场的语义图像分割” IEEE 模式分析与机器智能汇刊40.4(2017):834–848。
[3]弗朗索瓦·乔莱。"例外:具有深度可分卷积的深度学习."IEEE 计算机视觉和模式识别会议论文集。2017.
对话式人工智能入门
自然语言处理笔记
了解对话式人工智能及其如何帮助人类
介绍
我敢肯定,我们都曾试图联系我们的银行,但在我们与助理交谈之前,我们必须通过某种自动化系统。当这些系统根本无法理解我们时,这有多烦人?在几分钟的来回和努力理解系统后,我们找到一个真人来处理我们的问题,并带我们经历完全相同的过程。
真令人沮丧!
如果我们要与计算机对话,我们至少希望它尽可能地复制人类的互动,否则有什么意义呢!我们需要计算机像我们一样交流和说话,但我们知道这不是计算机真正的工作方式——除非你教它们…
什么是对话式 AI?
对话式人工智能(AI)由一系列技术组成,这些技术支持聊天机器人等自动消息工具和语音助手等语音应用。用户可以与这些技术对话,因为它们是为了在计算机和人类之间提供类似人类的互动而创建的。
这些技术通常利用大量数据、机器学习(ML)和自然语言处理(NLP)来帮助模仿类似人类的交互,包括识别语音和文本,然后翻译它们的意思。
然而,我们习惯的对话 AI 类型被称为弱 AI (或狭义 AI 在某些圈子中,但这些术语可以互换)。弱,不是因为它缺乏能力,而是因为我们习惯的工具只实现了大脑的有限部分——换句话说,它们专注于执行另一个领域的任务。
另一方面,有强大的人工智能或人工一般智能(AGI)。强人工智能通常是科幻电影中描述的——好吧,没有那么夸张;这种人工智能(AI)仍然是一个理论概念,维基百科将其描述为“智能代理理解或学习人类可以完成的任何智力任务的假设能力。”【来源 : 维基百科】。
用例
如前所述,尽管被称为弱,但弱人工智能正在被各种企业采用——事实上,如果我们看这项技术帮助企业盈利的能力,我们可能不会认为它是弱的。企业中对话式人工智能的一些例子包括:
- 客户支持通常是相当重复的,因此它被在线聊天机器人所取代,可以在客户旅程中帮助客户
- 降低文本到语音转换技术的准入门槛,反之亦然
- 提高医疗保健的运营效率
- 亚马逊的 Alexa、苹果 Siri 和谷歌 Home 等物联网(IoT)设备
- 优化大部分人力资源(HR)流程
对话式人工智能的优势
有许多因素使对话式人工智能对企业有吸引力,因此,如果我们在未来各种行业的企业中看到某种形式的对话式人工智能,我不会感到惊讶。
提高生产力—借助对话式人工智能,自动化支持可全天候处理简单请求。反过来,这一壮举将 up 客户服务代表解放出来,将他们的注意力转移到对话式人工智能无法触及的更复杂的客户问题上。
**降低客户服务成本——**客户服务的运营成本非常高,但有了对话式人工智能,客户的请求可以得到更高的处理量,比电话那头的人还要高。因此,可以更快地向客户提供相关和有用的信息。
**交互式品牌信息——**苹果、微软、谷歌和亚马逊等公司已经通过各自的语音助手很好地做到了这一点。虚拟助理可以让你将你的品牌人格化,让你在客户喜欢的地方与他们见面,这超越了展示广告、社交媒体和其他网络资源。
为员工提供更好的体验— 如前所述,琐碎的任务可以从人类代理那里拿走,并委托给虚拟助理,他们永远不会厌倦重复做同样的事情(事实上,他们会变得更好)。这给人们留下了空间,让他们专注于更复杂的任务,并发展他们的人际技能,以建立新的或巩固现有的客户关系。
包裹
尽管大多数对话式人工智能应用程序目前在解决问题的技能方面受到限制,但它们仍然是非常有效的工具,能够在重复的任务(如客户交互)中减少时间并提高成本效率。进一步补充,对话式人工智能是一个很好的工具,可以用来解放员工,使他们可以更加专注于为企业带来更多价值的任务以及需要更多参与的与客户的互动。
总的来说,对话式人工智能应用程序已经表明,它们能够有效地模仿类似人类的对话体验,从而使客户更加满意。
感谢阅读…
相关文章
</5-ideas-for-your-next-nlp-project-c6bf5b86935c> https://pub.towardsai.net/7-free-online-resources-for-nlp-lovers-26b1e0bba343
梯度下降入门
直观地探索梯度下降,将其可视化,并使用 Python 中精彩的 SymPy 库实现一个示例
阿曼德·库利在 Unsplash 上拍摄的照片
为什么我们需要知道什么是梯度下降?
让我们首先定义什么是优化问题。在优化问题中,我们首先列出一个成本,它是可变参数的函数。这些参数的取值范围很大,最终这些值决定了成本。我们在处理这些问题时的目标是找到一组 值,它们将最小化成本函数。梯度下降有助于我们系统地这样做,而不是通过随机选择参数值来随意尝试这样做。
直觉
在 Unsplash 上tefan tefaník拍摄的照片
假设我们在山上徒步旅行,正沿着一个斜坡往下走。现在我们被告知下降时必须闭上眼睛。我们会怎么做?很简单,闭上我们的眼睛,用我们的脚去感觉我们站的地方周围有什么,在我们感觉到一个轻微向下的斜坡的地方走一步。这正是我们在梯度下降中要做的。我们向下迈出的这一步被称为更新步骤。现在,我们当中一些感觉更有冒险精神的人会迈出更大的一步,甚至可能是向下迈出一大步!我们迈出的一步的大小被称为学习率**,它决定了我们到达底部的速度。**
梯度——数字感知的方式
我们谈到了人类是如何轻松定位迈出一步的,但是数字是如何做到这一点的呢?向下的方向是多少?
来源:datahacker.rs
上图中,我们有一个成本 J,它只是一个参数 w 的函数。该函数可以用一个 w 表示的等式来表示。为了更新 w 以减少 J,我们首先从 w 的随机值开始,然后使用该等式来更新该值。
来源:塞缪尔·特伦德勒
这里,α是我们谈到的学习速率。那么到底发生了什么?首先让我们再来看一下图表。在全局最优值(最小成本)右边的任何地方,函数的偏导数都是正的。现在,通过查看图表我们知道,如果我们降低 w 的值,我们就会降低成本。因此,使用上面的等式,我们从当前值 w 中减去一个正数,这反过来使成本最小化。阿尔法决定了我们减去多少。类似地,对于全局最优值左侧的任何 w,该 w 处的梯度为负,因此使用该等式,我们得到比之前更高的值 w,这再次最小化了成本。这总结了一个步骤。
我们按照这个简单的步骤进行固定次数的迭代,或者直到我们看到我们的成本已经收敛并且不会再进一步降低。
为什么要用 SymPy?
SymPy 是一个非常方便的库,它有很多我们可以使用的数学函数。我们将使用它来定义成本函数并计算给定方程的梯度。我们可以很容易地通过 SymPy 计算偏导数。
让我们把手弄脏吧
让我们尝试并优化成本函数 cost = x + y,看看梯度下降是否给出 x 和 y 的最佳值(x=0 且 y=0 时成本=0)。
- 导入必要的库(我在 Google Colab 上运行),如果你想在本地运行,请安装这些库。
2.创造符号,让 SymPy 发挥它的魅力&定义一个成本函数
3.可视化成本函数,我们可以看到在 x=0 和 y=0 时最小值为 0
成本函数(向下滚动)
4.使用带有接头的 sympy.evalf 计算成本
5.计算给定点 x,y 处参数的偏导数
6.肉!这是梯度下降函数,它迭代更新梯度并返回最佳参数值和最小化成本。
7.随着算法的进展,可视化我们的成本函数的变化。
学习率大的问题
好吧,那我们为什么要等这么多次迭代呢?为什么不迈出巨大的一步,降低成本。问题是梯度和学习率的乘积变得非常大,我们的成本直线上升。我们所有的努力都被冲走了,这可能是我们的成本不断飙升,永远不会收敛。
这些图表说明了为什么学习速度如此重要
来源:走向数据科学
让我们看看实际情况,如果我们将学习率提高到 1.1,就会发生这种情况。
我在代码里加了一个条件,如果代价开始射击,不会收敛,会自动降低学习率。
非凸成本函数的问题
由于这是一个入门,我选择了一个非常简单的成本函数,但实际上我们的成本函数可能是非凸的,并且有多个局部最小值。在这种情况下,我们可能会陷入局部最小值,永远不会达到全局最小值。
资料来源:vitalflux.com
如图所示,我们得到了一个错误的印象,即算法已经最小化了成本和收敛,而实际上我们陷入了一个远离全局最小值的局部最小值。
处理这些问题
因为这是给初学者的,我用了简单的梯度下降。我将写一篇关于更复杂的变体的文章,这些变体收敛得更快,并且避开了前面提到的问题。这些包括
- 使用随机梯度下降/批量梯度下降
- 使用 RMSProp 或 Adam。
- 使用指数递减的学习速率。
如果你想让我写这些话题,请在评论中提及。
结尾部分
我们了解了如何使用梯度下降优化成本函数,以及 SymPy 如何轻松地为我们完成所有的计算和繁重的工作。这是对惊人算法的温和介绍,该算法被广泛用于优化机器学习和深度学习模型。
我很想听一些关于这方面的反馈,如果你想要一篇更高级的文章来解释上面提到的调整,也请告诉我。
查看我的 github 的一些其他项目和完整代码。可以联系我 这里 。 感谢您的宝贵时间!
EM 算法的初级读本
克里斯蒂安·祖尼加博士
图一。用于混合模型的 EM 模型示例[1]
期望最大化(EM)算法是机器学习中用于估计模型参数的主要算法之一[2][3][4]。例如,它用于估计混合模型中的混合系数、均值和协方差,如图 1 所示。其目标是最大化似然 p(X|θ),其中 X 是观测数据的矩阵,θ是模型参数的向量。这是最大似然估计,实际上对数似然 ln p(X| θ)是最大的。最大化该函数的模型参数被认为是正确的模型参数。EM 是梯度下降的有用替代,并且可能具有几个优点。
1 它更自然地实施约束,例如保持协方差矩阵正定。
2.在许多情况下,例如对于混合模型,它可能收敛得更快。
3.它提供了一种处理缺失数据的方法。
不幸的是,EM 算法对初学者来说可能不容易理解。EM 算法的第一步是假设存在帮助生成数据的隐藏变量 Z。只有数据 X 被直接观察到。隐藏变量有助于将问题分成两个步骤,有时更简单,期望和最大化。通过对联合分布 p(X,Z | θ)进行边缘化,可以将可能性写成隐藏变量 Z 的形式。总和是 z 的所有可能值。
推导 EM 算法需要理解三个主要概念:两个以上变量的 Bayes 定理、凹函数的 Jensen 不等式以及比较概率分布的 Kullback-Leibler 散度。
贝叶斯定理在 em 算法中起着重要的作用。许多人都熟悉两个变量的定理,但是如上所示,三个变量会发生什么呢?虽然形式更复杂,但条件概率的定义仍然适用,它可以用联合分布 p(X,Z,θ)来表示。
无论变量的顺序如何,联合分布都是相同的,这是操纵所有条件概率的基础。在 EM 算法中,将使用 X 和θ来估计 Z,因此条件概率 p(Z | X,θ)很重要。使用上式中的联合分布,Z 的后验分布可表示如下。
方程可以简化为 p(X | θ) = p(X,θ)/p(θ)。
詹森不等式是获得 EM 算法所需的第二个结果。对于凹函数 f(x),f(x)的期望 E[f(x)],小于或等于先应用函数再取期望 f(E[x])。简洁地说,E[f(x)] ≤ f(E[x])。
像对数一样,凹函数是那些向外“凸出”的函数,如图 2 所示。该函数总是大于或等于弦。数学上,对于 x 和 y 之间的任意点 p,f§ ≥ L§其中 L§是在 p 处评估的线的值。点 p(或 x 和 y 之间的任意点)可以通过 p = w1 x + w2 y 表示为 x 和 y 的加权组合。权重大于零,总和为 1。利用直线的方程,值 L§可以写成 L§ = w2 f(y) + (1- w2) f(x)。所以对于凹函数f(w1 x+w2 y)≥w2 f(y)+(1-w2)f(x)。
图 2 凹函数位于任意弦之上。
显示詹森不等式的下一步如下,因为期望可以被认为是一个加权和,概率分布给出了权重。一般来说,概率会给出两个以上的权重,但前面的结果可以归纳为许多权重。
要理解的最后一个概念是 Kullback-Leibler 散度,它是两个概率分布 q(z)和 p(z)之间不相似性的度量。当两个分布相等时,KL 散度总是大于或等于零,q(z) = p(z)。它不是对称的,KL(p||q) ≠ KL(q||p),所以它不是距离测度。当真实分布是 p(z)时,它可以被解释为使用分布 q(z)编码数据所需的额外比特数,反之亦然。
掌握了这 3 个概念,EM 算法就更容易理解了。隐藏变量 Z 也具有分布 q(Z)。将 q(z)作为 q(z)/q(z) = 1 引入对数似然中,并利用对数函数是凹的这一事实,詹森不等式给出了关于分布 q(z)的期望。
这个不等式给出了对数似然的一个下界。对数似然和 L(q,θ)之间的差异可以看作是 q(z)和 p(Z|X,θ)之间的 KL 散度。用 p(X,Z| θ) = P(Z|X,θ)P(X| θ)的展开式来证明这一点。
当 KL 散度为零时,或者当 q(z) = p(Z|X,θ)时,完全相等。
最大化对数似然可以通过最大化 L(q,θ)来间接实现。有两种方法可以最大化 L,即改变 q 或改变参数θ。独立地改变每一个更简单。顾名思义,EM 算法有两个步骤,期望和最大化,并迭代进行。首先初始化参数。分布 q(z)在期望步骤中更新,保持参数θ固定为θold。这仅仅涉及到设置 q(z) = p(Z|X,θold)。然后更新参数θ以最大化 L(q,θ),保持在最大化步骤中固定的 q(z)。
期待
设 q(z) = p(Z|X,θold)代入 L。
最大化
保持 q(z)不变,改变θ,最大化 L(p(Z|X,θold),θ。
这两个步骤保证总是增加可能性并且至少收敛到局部最大值。最大化步骤可以根据分布的形式以不同的方式进行。例如,在高斯混合模型中,最大似然估计的修改给出了分析结果。在其他情况下,可能没有解析解,但是求解最大化步骤可能仍然比原始问题简单。
参考文献
[1]https://en.wikipedia.org/wiki/期望% E2 % 80 %最大化 _ 算法
【2】邓普斯特;莱尔德,n . m .;鲁宾,D.B. (1977)。“通过 EM 算法不完整数据的最大可能性”。 《英国皇家统计学会杂志》,B 辑 。39(1):1–38。JSTOR2984875
[3] Bishop 模式识别和机器学习 Springer 2006
[4]墨菲机器学习从概率角度看麻省理工学院出版社 2012 年
机器学习数据挖掘中偏差的来源
尽管通过大数据实现的自动化水平不断提高,但大部分数据挖掘和机器学习过程仍然依赖于人的干预,从而引入了不同的偏见。
在过去几十年中,生成的结构化和非结构化数据的数量呈指数级增长,并且在未来几年还将继续增长。“大数据”分析可能会克服企业和政府几个世纪以来在决策时面临的众多挑战:缺乏足够的数据来制定政策(例如,针对特定社会群体的政策)或检查市场或消费者预期(例如,推荐系统)。由大数据范式驱动的描述性和预测性建模可以帮助决策者获得对个人、商业或集体收益的宝贵见解。
然而,现代数据收集过程和算法仍然容易受到数据挖掘偏见的影响。如果不采取适当的措施,大数据可能会放大现有社会问题(如种族歧视)的负面影响,使研究结果变得毫无价值,甚至适得其反[1],[2]。本博客的目的是探索在数据挖掘过程中以及大数据项目的特征工程阶段可能引入的偏差的潜在来源。
垃圾进垃圾出—大数据也是如此
大数据有可能克服数据可用性的限制,这是一个困扰传统统计分析几十年的问题,但这种分析的价值也容易受到数据质量和数据应用不当的影响。随着数字设备的日益普及,收集各种数据变得比以往任何时候都更加容易。例如,智能手机有能力实时记录你在哪里,你在做什么,你如何花费你的时间和金钱,你和谁见面,多长时间,以及许多这样的个人细节。尽管存在隐私和监控问题,但这些信息已经改变了经济和我们的生活方式。
尽管如此,就像老派的数据分析一样,新数据范式的成功也取决于相同假设的有效性——目标人群包括与被调查问题相关的所有成员;样本反映了统计总体;并且建模变量的选择是适当的。违反任何假设都会导致有偏见的结论,从而降低机器学习解决许多现实世界问题的价值。
图 1 描绘了机器学习练习中的典型步骤序列,并显示了不同的错误如何强化现有的问题。虽然谨慎使用将提供有效的解决方案并减少我们的问题,但任何错误都可能延续或恶化现有的问题(差异、歧视或其他)。
图片由作者根据[2]中的信息提供
第一部分:确定目标人群
数据分析练习的早期步骤之一(如果不是第一步的话)是询问谁或哪些成员最有可能拥有我们需要的信息或熟悉我们试图解决的问题。这组成员是我们期望的群体(姑且称之为问题群体)来考虑样本收集。训练数据样本的代表性必须仅针对与问题有直接联系的问题群体进行测量。
例如,假设一个道路维护部门想要使用众包(通过智能手机)来监控整个城市的道路状况[1]。虽然似乎居住在该地区的所有人都应该是目标人群,但只有在该地区的道路上行驶的人(作为乘客或司机)才是真正的目标人群(我们的问题人群)。来自不旅行或不开车的人的设备的加速度计数据不会增加任何价值。同样,对于招聘目标,所有潜在合格(满足强制性资格要求)的员工都是抽样人群,而不是所有毕业生或求职者。另一个明显的例子是衡量谁会赢得选举的抽样人口。大多数青少年的意见在民意测验中并不重要,因为只有选民(在大多数国家是 18 岁以上的人)才构成选举调查的人口。有多少年轻人被调查并不重要;调查结果或任何基于这种信息的预测模型将是无用的。
虽然在大多数情况下,完成这一步对于适当描述的问题来说可能是微不足道的,但是任何无意的错误都可能对我们工作的准确性和相关性产生巨大的影响。在我们的例子中,在定义了所有驾车者的目标人群后,道路部门现在必须设计一个策略来从一个有代表性的,即使是少量的道路使用者那里收集数据(暂时不包括骑自行车的人和步行的人)。
第二部分:确保有代表性的培训数据
任何小数据或大数据应用的价值取决于训练数据描述问题群体的准确程度。虽然大数据意味着一个巨大的数据集,但它很少代表整个问题群体,并且只捕获其中的一部分,这增加了代表性采样的重要性。创建不反映潜在问题群体的组成的训练数据集将强调某些成员而不代表其他成员。维基百科有一个长长的采样偏差列表,包括选择偏差、排除偏差、报告偏差、检测偏差,这个列表还可以继续下去。事实上,一个小的,但有代表性的样本可以产生比一个大的,有偏见的数据集更可靠的结果[3]。
例如,在上述道路监控项目中,如果该部门依靠智能手机中的加速度计来收集信息,则缺乏此类高科技设备或充足互联网接入的低收入群体可能无法成为样本的一部分[1]。有偏见的数据可能导致纳税人的钱不公平地分配给道路开发和维修,导致一个城市内道路基础设施质量的系统性差异。互联网接入不畅也会限制职位候选人名单,或者简历中的用词会导致招聘中的性别偏见。
第三部分:选择代表性特征
预测因子的选择也会影响模型中如何考虑不同的人群成员。即使我们正确地识别了问题人群,并为训练抽取了一个代表性的样本,输入变量中仍然存在某些差异。可能有许多特征捕捉到群体中某些成员的不完整图像,并且对有偏见的预测者赋予更大的权重将产生不期望的结果。因此,尽管样本很好地描述了所有的人口阶层,但特征工程会间接低估或高估某些群体,并影响模型的公平性。
例如,表面上中性的特征之间的小相关性会产生不公平的结果。如果好斗的司机和老年人都更喜欢红色汽车,对红色汽车收取更高的保险费来惩罚糟糕的司机的决定将间接地对老年人有偏见[2]。
如[2]中所引用的,“被错误代表的群体与已经存在社会偏见(如偏见或歧视)的社会群体相吻合,甚至“无偏见的计算过程也可能导致歧视性的决策程序”。此类风险适用于采样和特征选择步骤。
例如,雇佣好员工取决于“好”的定义,这可以基于过去工作的平均时间或证明的成就记录。使用任期长度作为一个特征会不成比例地排斥在高招聘周转率(或流失率)行业工作的某些人[1]。虽然它是衡量员工忠诚度的理想替代指标,但将其不必要地纳入模型可能会产生主导影响,并延续大数据被认为正在缩小的差异。因此,尽管尽了最大努力来定义人口和收集良好的数据,但选择错误的要素可能会在结果中引入系统性偏差,从而导致问题的出现。
最后的想法
大数据分析有可能克服由个人和人类决策产生的许多偏见,并呈现合理的、有代表性的人口状况。这篇博客的目的是介绍偏见如何成为机器学习建模练习的一部分。在执行数据挖掘和进行机器学习项目时,分析师必须意识到以下三个可能会削弱机器学习项目功效的原因:
未能正确识别与问题相关的统计(问题)人群
使用非代表性训练数据进行预测建模
用于预测目标变量的特征的有偏选择
常言道,“能力越强,责任越大”,在数据挖掘和特征工程方面的任何疏忽都可能使现有问题恶化,而这些努力将会适得其反。只有大数据、其易访问性和明智的数据挖掘的综合效应才有可能彻底改变我们的日常生活,实现环境可持续、社会公平和经济充满活力的世界。
参考
[1] S. Barocas 和 A. D. Selbst,“大数据的不同影响”,《加州法律评论》,第 104 卷,第 3 期,第 671–732 页,2016 年 2 月。
[2] E. Ntoutsi 等,《数据驱动的人工智能系统中的偏差——一项介绍性调查》, WIREs Data Min。知道了。Discov。,第 10 卷第 3 期,第 e1356 页,2020 年 5 月。
[3]j . j . farage 和 N. H. Augustin,“当小数据打败大数据”, Stat。可能吧。列特。,第 136 卷,第 142–145 页,2018 年。
[4] J. Manyika、J. Silberg 和 B. Presten,“我们如何应对人工智能中的偏见?," 2019.【在线】。可用:https://HBR . org/2019/10/what-do-we-do-about-the-bias-in-ai。
带 R 的贝叶斯可加回归树入门
传统集成算法的贝叶斯方法
简介
在 XGBoost、Lightgbm 和 catboost 在几次高调的 kaggle 竞赛和机器学习研究中取得巨大成功之后,梯度增强机器(GBM)/集成算法成为许多涉及结构化数据的机器学习问题的主力。GBM 如此成功的原因之一是它可以同样好地处理数值和分类数据。然而,这些传统的基于集成的方法的问题是,它们给我们一个点估计,因此,我们没有办法估计该特定估计有多可信。通过量化经验风险,即 rmse、对数损失等。,我们可以得到一种模型不确定性的感觉(认知不确定性);然而,对于迭代主动学习或更好的风险管理(对于高风险情况),随机不确定性或个体预测不确定性也是非常重要的。为了缓解这个问题,Chipman 等人发表了这篇论文,这是由系综方法的相同精神所激发的;然而,它需要贝叶斯方法来识别模型参数,其中我们可以对我们关于树的形状和总体结构的先验信念进行编码。然后,基于该数据,它将使用 MCMC 反向拟合算法更新先验。在他们的文章中,他们声称在 42 个数据集(包括模拟和药物发现数据)上,它优于其他传统的集成方法。在这篇文章中,我的目的是用波士顿住房数据集上的一个说明性例子来证明这种说法。
树木的集合
系综树的想法来自于这样一种想法,即通过组合比随机猜测稍好的弱学习者的集合,我们可以得到一个强学习者。这些个体学习者中每一个都是低偏差-高方差模型。当组合在一起形成一个集合时,这些树形成一个中等偏差-中等方差模型,该模型在理论和实践上都具有极好的样本外预测性能。
做出推论的一般问题可以写成:
在集成算法中,未知函数被近似为树的和 h(x)。树和模型是一个以多元成分为核心的加性模型,与广义加性模型相反,它可以自然地包括交互作用效应。此外,它还可以包括单棵树无法获得的附加效果。由于这些优异的性质,系综方法吸引了大量的注意力,并导致了 boosting [ Friedman,2001 ]、random forest [ Breiman,2001 ]和 bagging [ Breiman,1996 ]的发展。随机森林使用特征子集来构建每棵树,然后将所有这些单棵树的预测进行组合。相比之下,bagging 使用数据的子集来构建每棵树。Boosting 与其他两种不同之处在于,它按顺序形成模型,其中每棵树都试图适应前一棵树无法解释的数据变化。贝叶斯加性回归树(BART)类似于 Boosting 算法,因为它结合了顺序弱学习者的贡献来进行预测。
贝叶斯加性回归树
在 BART 中,类似于梯度提升的反向拟合算法用于获得树的集合,其中一棵小树与数据拟合,然后该树的残差与另一棵树迭代拟合。然而,BART 在两个方面不同于 GBM,1 .它如何通过使用先验来削弱单个树,以及 2 .它如何在固定数量的树上使用贝叶斯反向拟合来迭代拟合新树。
拟合单棵树(信用:https://www.youtube.com/watch?v=9d5-3_7u5a4&ab _ channel = PutnamDataSciences
在 GBM 中,存在巨大的过度拟合风险,因为我们可以不断迭代,直到我们的经验风险在训练集示例上最小化(此时,所有这些树中存在的比特如此之大,以至于它本质上记住了所有的训练点,而不是概括)。在传统的 GBM 中,限制树深或提前停止等。来规范算法。相比之下,BART 使用智能先验系统地学习树木的收缩量或深度。先验是这样选择的,1。树很小,2。与每个树终端节点相关联的参数值趋向于零(限制灵活性),以及 3。残留噪声的标准差较小。有趣的是,树的数量没有被控制在先验范围内,因为这将导致优化过程中巨大的计算成本。相反,它被设置为默认值 50,这对于大多数应用程序来说已经很不错了。在获得上述三个参数的后验分布后,通过从模型空间(三个参数的后验)连续抽取样本,用反拟合算法进行推断。通过取所有这些图的平均值,我们可以得到任何试验数据的点估计。类似地,相应的分位数给出了测试数据的不确定性区间。
现在是使用 BART 建立预测模型的时候了。对于这部分,我们使用 r 中可用的 bartmachine 包,程序的核心是用 java 编写的。BART 的原作者的本机实现( bayestree )是用 C++编写的,但是它有几个限制(如下所列)。
信用:【https://arxiv.org/pdf/1312.2171.pdf】T4
在本练习中,我们将使用波士顿住房数据,这些数据在 R 中不可用,但我们可以通过 mlbench 软件包轻松获得。在下面的代码中,我们将数据加载到 R:
接下来,我们使用 caret 包将数据分为训练集和测试集:
接下来,我们绘制目标变量的直方图,它是一组特征的房价中值:
中间价直方图
要查看数据中每个要素之间的相关性,我们可以查看相关图:
相关图
看起来在一些特征之间有一些高相关性,这对于其他 ml 算法可能是一个问题,但是对于基于树的集成,我们可以安全地忽略它们。现在,我们可以初始化 bartmachine:
对于大约 400 个数据点和 13 个特征来说,它非常快(只需要大约 2-3 秒)。训练数据的均方根误差为 1.4,考虑到目标值范围在 4-50 之间,这已经相当不错了。夏皮罗-维尔克检验的 p 值表明数据是异方差的。
使用 rmse_by_num_trees 函数,我们可以很容易地找到最佳的树数,而不是使用默认的 50。
基于 rmse 对树数量的图,我们用 65 棵树重新训练该模型,并绘制收敛诊断图。
会聚诊断图
我们可以看到,MCMC 采样在大约 200 次迭代时达到收敛。到 2010 年,它仍在波动。跑更长的时间和更多的磨合是有益的。然而,对于这个练习,这种收敛行为可以被认为是可接受的。
接下来,我们可以使用内置函数查看剩余属性:
残差或多或少在零附近波动,但总体上残差看起来呈正态分布。现在,我们通过绘制预测中值价格与实际中值价格的平价图来说明该算法在训练集和测试集上的性能。
列车数据的奇偶图
测试数据的奇偶图
这令人印象深刻,因为我们现在能够给出每个数据点的(95%预测区间)预测范围,其准确度约为 90%。我们还可以在测试集上计算 rmse 和其他指标。
测试集上的 rmse 为 3.52,r 平方值为 0.89,pearson r 为 0.94。现在,让我们检查一下作者们的说法是真是假。我们用 python 对波士顿住房数据运行了 XGBoost 算法:
这两种实现之间只有微小的差别。通过一些超参数优化,结果可能会改变(我也对训练和测试集使用随机 80–20 分割)。总之,bartmachine 的性能令人印象深刻,因为它也可以给我们一些内在的估计不确定性。
我们还可以使用 bartmachine 中可用的函数来绘制特性重要性:
特征重要性图
摘要
- BART 是一种非常复杂的算法,能够提供与用于构建模型的参数相关的内置不确定性估计。
- 对于各种各样的现实世界机器学习问题,BART 是一个很好的选择。
- 它可以用于设计空间的迭代探索(贝叶斯主动学习),以最小化收集昂贵数据的成本。
大型复杂系统入门
图片来自 Pixabay 的 WikiImages 。
航天飞机、电信网络,甚至新的高科技创业公司都是大型复杂系统的家园。这些系统雇佣了不同团队的数千名软件开发人员。尽管大系统没有一个确切的科学定义,我们将包含多个服务的系统称为“大系统”通过大量的维基百科链接提供了额外的清晰度,但整体结构的灵感来自于马丁·凯普曼的“设计数据密集型应用
这些系统可以容错,这意味着一个部分偏离预期行为不一定会削弱系统的其余部分。它们还可以自我修复,即在某些意外情况下,系统服务可以自动恢复,无需人工干预。它们也可以是幂等的,这意味着在系统中多次运行输入不会比第一次运行相同的输入改变系统的状态。这些系统可以是无状态的,这意味着服务的任何实例都可以处理任何输入,或者相反是有状态的,这意味着一些实例专用于处理特定的输入。推荐无状态,因为它使我们的组件从令人头疼的协调中解脱出来,这将在后面讨论。
这些系统的输入满足一些先决条件。如果执行成功终止,它们的输出必须满足一组后置条件。这被称为合同设计,是系统所有正确性测试的基础。
这些系统满足功能需求,这意味着系统应该做它应该做的事情。以 Airbnb 为例;列出西雅图所有的海滨别墅,点击应用程序的按钮时预订正确的海滨别墅是两个功能需求。
这些大系统也满足非功能性需求。非功能性需求依赖于应用程序的业务需求;它们包括(但不限于)可用性、可伸缩性、可靠性、一致性和性能(无论是响应时间、吞吐量,还是另一个度量)。例如,预订海滨别墅应该在可接受的时间内(可能不到 5 秒),并且网站应该整天都在运行。
术语
- 节点是网络上的单台计算机(或设备)。
- 系统状态是指系统跟踪的元数据。
- 读请求是在不改变系统状态的情况下从数据库中获取的一条信息。
- 写请求导致系统状态改变。
微服务的炒作
在本文中,我们讨论“无共享”架构,即那些依赖于水平伸缩的架构。这些系统通过一起添加更多节点来扩展,而不是用额外的资源(如 CPU、内存和硬盘)来增强同一个节点。这是业内使用的主要模式,并在云计算中使用。
到目前为止,我们将系统的不同部分称为组件。业内使用的术语是微服务(早期面向服务架构的更名)。很像面向对象编程中的类,微服务应该有一个单一的职责。我们不应该仅仅因为方便就把不相关的功能聚集到一个微服务中。
应用程序架构应将数据节点与控制节点(即数据库中的数据)和“计算”节点中的控制逻辑分开。数据确实比代码更长寿,所以如果我们需要修改系统,混合关注可能是一场噩梦。通常,代码应该准备好处理向后和向前兼容性,这有点棘手。
这些不同的微服务使用网络调用或队列进行交互,以满足功能需求。它们应该是模块化的和可维护的。这些微服务应该是可扩展的,即能够在系统变化最小的情况下提供 10 倍的流量,并且在纵向扩展系统时几乎没有明显的性能差异。
设计一个微服务很像设计一个应用编程接口(API) 。微服务应该在稳定且相对简单的抽象背后隐藏大量的实现细节。他们应该不惜一切代价避免意外的复杂性。
现在,这些微服务使用队列、数据库、缓存和协调服务来完成它们的工作。就像在编写程序时导入库一样,使用数据库或队列使设计服务变得更容易,因为您依赖于数据库或队列提供的保证。
数据库
我们使用术语“数据库”作为一个包罗万象的术语。使用这样的定义,几乎每个数据节点都可以被认为是一个数据库。数据库有不同的类型和风格,从关系数据库到文档数据库,从图形数据库到分布式缓存。一些人认为,即使是队列也是一种特殊的数据库。
通常,数据库的选择是根据应用程序中涉及的实体、它们的关系以及预期的加入流量来进行的。例如,一个图形数据库可以用一个关系模型来表示,该模型在各行之间有大量的连接,这降低了开发人员的工作效率和数据库的性能。
将密钥映射到硬盘的数据库模块称为存储引擎。通常使用日志结构合并树(LSM) 或 B 树来实现。不管索引是如何实现的,数据库都使用预写日志(WAL) 将事务写入磁盘,然后再将它们应用到数据库。它是用来在系统崩溃时恢复系统的。
一些数据库为事务提供 ACID (原子、一致性、隔离和持久性)保证。原子的意思是“要么全部要么什么都没有”一致性高度依赖于应用程序对它的定义。隔离意味着一个事务独立于所有其他事务执行。持久性意味着在向应用程序确认成功之前,更改被持久保存在磁盘上(或复制到不同的节点)。
隔离级别
数据库异常源于应用程序的使用和隔离级别(数据库的保证)。对于某些应用程序,这些异常永远不会发生。异常情况的例子包括:
- 脏读:一个事务读取一个已经被另一个事务修改过但还没有提交的记录。
- 脏写:一个事务写入一个已被另一个事务修改但尚未提交的记录。
- 不可重复读取:一个事务读取同一个记录两次,在整个事务中得到不同的结果。
- 幻影读取:在交易过程中,记录被添加/删除。
- 丢失更新:一种竞争条件,其结果是由于一系列不受控制的事件造成的。例如,几个事务可能同时执行,因此一个写操作会覆盖另一个。
- 写偏斜:基于陈旧数据的更新事务。
为了处理上面提到的一些异常情况,学术界和工业界的工程师提出了隔离级别。尽管这些隔离级别是标准的,但在尝试使用它们之前,最好多读几遍特定数据库的文档:
- 提交读:允许无脏读和无脏写。
- 快照隔离:写不阻塞读,读不阻塞写。每个事务都基于数据库的一致快照。
- 可串行化:即使使用了多线程,也能模拟串行执行。这种隔离模式处理所有数据库异常。实现方式有:串行执行,悲观锁:两阶段锁,或者乐观锁。
缩放比例
扩展包括复制和分区。我们专门为每一个小节。
分身术
图片由来自 Pixabay 的 Herbert Bieser 提供。
分布式系统的第一条规则是节点失效。他们突然地、出乎意料地失败了。为了防止节点故障时数据丢失,我们使用复制,因为它提供了冗余。如果数据只存在于一个节点上,那么我们将需要手动干预来恢复数据并解除阻止试图从故障节点访问其帐户信息的用户。人工干预不利于非常理想的自愈。人工干预需要几个小时,自我修复只需几秒钟。
防止单点故障(SPOF) 的一种方法是将所有数据从一个节点复制到其他节点。复制还有助于提高读取流量性能,因为读取可以定向到更多节点,从而减轻了每个节点的压力。虽然复制是有益的,但它的困难在于保持数据与写请求同步。我们简要讨论三种复制模型。
单头复制
由于相对简单,这是主要的模型。这是在 PostgreSQL 、 MySQL 和 MongoDB 以及其他许多应用中使用的模型。
读取请求可以定向到系统中的任何节点(称为读取副本)。另一方面,写请求必须指向在较早的时间点选出的领导者(或主机)。然后,领导者将更改流(复制日志)传递给其他节点。复制日志可以使用不同的方法实现,如预写日志或基于语句的复制。
一些系统使用主动反熵或读取修复在不同的节点上复制数据。主动反熵通过比较节点间的 Merkle 树、哈希的树来计算出哪些子树需要从一个节点复制到另一个节点。读取修复仅依赖于读取流量来复制不同节点上的数据。如果记录从未被读取,那么数据将无限期地保持陈旧。Riak 为用户提供了两种选择。
与我们之前讨论的 ACID 模型相比,复制滞后产生了 BASE(基本可用、软状态、最终一致性)。基本可用意味着读写流量尽可能可用。软状态意味着读取副本之间的状态可能略有不同。最终一致性意味着最终(在没有额外的写入流量之后),状态将在所有读取副本中保持一致。
非领导者并不重要,它的失败不会影响系统的状态。然而,领导者故障转移并不简单,必须小心实施。在检测到领导者的失败时,读取复制品应该选举新的领导者来接管。选举新领导人的过程被称为达成共识,我们将在本文稍后讨论。
多领导者复制
网络分区确实会发生,而且发生的范围很广。网络分区是指系统中的一些节点与网络中的其他节点断开连接。当单个领导者模型发生这种情况时,写入会被阻止。
这产生了多领导者架构,其中少数领导者可以处理写流量。这些系统更加复杂,需要领导者之间的协调。缺点是写入需要其他节点的一致同意。
无领导复制
对于无领导复制,没有节点是特殊的。我们必须写入许多节点(w;写仲裁)和从许多节点(r;read quorum ),其中 w + r > n(节点数),以获得一致的数据。
分割
Nuno Silva 在 Unsplash 上拍摄的照片。
如果我们有一个包含数百万条记录的大型数据库,不可能将所有数据存储在一个节点上。我们必须按照我们坚持的“水平扩展”方法,在多个节点上以某种方式分割数据。每个节点可以有一个(或多个)分区。
有两种流行的分区方案:
按键分区
- 简单且易于实施
- 产生“热点”,其中大部分流量只被定向到一些节点
- 范围查询很简单
通过关键字的散列进行分区
- 不同版本之间的哈希函数必须一致
- 通过将节点更均匀地分散到多个节点,减少了“热点”
- 范围查询被传递给所有分区,就像在 MongoDB 中,对于其他数据库,像 Couch 和 Riak,它们不支持范围查询
复制和分区一起进行
在一个大系统中,复制和分区是齐头并进的。节点将有不同的分区副本,如下图所示。
该图来自“设计数据密集型应用程序”
大系统中的协调
协调不是系统的功能需求,而是设计选择。一些系统可以将协调问题外包给缓存、数据库、分布式锁管理器或 Zookeeper。
协调问题包括:
- 选举领导服务器(共识)
- 管理组成员资格
- 崩溃检测:跟踪可用的服务器
- 服务发现
- 将工作分配给节点
- 管理元数据,如分区和故障转移
- 分布式锁管理
尽管有处理共识的算法,如 Paxos 和 Raft ,但它们并不简单。实现很容易导致错误。外包给第三方系统(如 Zookeeper)只有在牢记第三方系统不可用时产生的运营开销时才有意义。
网络问题
文章开头提到,我们依靠商品硬件和网络来构建所谓的大系统。这种选择不是没有权衡的。网络不可靠,会导致以下问题:
- 消息延迟和网络分区:没有好的方法来区分网络延迟、网络分区、过载节点或节点崩溃。我们能使用的最好方法是心跳超时,假设一个节点关闭。
- 时钟漂移:即使使用网络时间协议(NTP) ,节点也永远无法确定正确的时间。时钟漂移会导致各种各样的问题,从领导者不更新其领导地位,到拥有过期锁的节点认为它仍然有效。
在单领导者架构中,领导者认为自己是领导者,而它不再是领导者(由于网络分区或时钟漂移),这可能导致裂脑,从而导致数据损坏。在这种情况下,可以使用击剑令牌。
过时的上限定理
尽管已经过时了,CAP 定理指出人们只能从两个事物中选择一个,即一致性或可用性,因为网络分区一直在发生。一致性一般是一个模糊的术语,所以我们用单词“可线性化”来代替,一个非常强的一致性模型。
可线性化意味着如果操作 B 在操作 A 完成后开始,操作 B 必须将相同状态的系统视为完成 A 或更新的状态。它不同于 serializable,因为它不假设并发事务。
系统可以是 CP 或 AP;它们可以是一致的(可线性化的)或可用的,但不能同时是一致的和可用的。社交媒体等一些系统牺牲线性化来获得高可用性,而银行等其他应用牺牲可用性来获得线性化。
注意 CA 不可用,只有 CP 和 AP 模式可用。来源:亚斯敏·穆萨提供。
在本文中,我们讨论了具有“无共享”架构的大型系统。我们描述了我们希望在分布式系统中看到的期望属性,如可用性、可靠性和可伸缩性。我们还描述了不同类型的数据库及其隔离级别。然后,我们讨论了扩展系统的一些注意事项,如分区、复制和一致性。
构建一个大的复杂系统是令人兴奋的努力;现在你正在理解,甚至建立你自己的道路上。
这篇文章最初发表在项目 Nash 上。
你最后一次网飞狂欢的概率
随机过程的解析和数值/模拟分析
本文采用分析的方法来分析最近流行的网飞系列中的一款游戏——乌贼游戏。我们将制作陈述来描述游戏中涉及的概率,并将使用模拟分析来确认结果。
剧透警报:
这篇文章揭示了网飞的鱿鱼游戏系列中的一些游戏的细节。我还将从总体上谈论剧情,这可能会揭示一些你只有在几个小时的紧张阅读之后才能了解的信息。如果你打算以后看乌贼游戏,我建议你把这篇文章收藏起来,只有在你看完之后再回来看。
美丽的秋天。由 Marek Piwnicki 在 Unsplash 上拍摄的照片。
《鱿鱼游戏》
到今天为止,乌贼游戏仍然是网飞有史以来最受关注的系列。这部最近上映的韩国电视剧以一场比赛为特色,456 名深陷金融危机的玩家互相对战,争夺赢得约 10 亿₩45 奖金的机会。这场比赛包括 6 个主要的致命游戏,在此期间,不同数量的玩家被淘汰和死亡。我们后来发现,奖金和游戏,据说是通过投注金额放置的贵宾,一个秘密小组的外国人谁一直在游戏和球员打赌。
为了使 VIP 的下注过程尽可能令人兴奋,游戏被设置为玩家需要各种技能和力量来通过每场游戏。例如,体力和策略在第三款拔河游戏中扮演着重要的角色,在这款游戏中,失败的一方将从一个高高竖立的建筑物上跌落并摔死。或者在第一场比赛中,一场敏捷和专注的比赛,玩家需要快速和良好的平衡来逃避死亡。
第五场比赛
但也许唯一一个玩家的命运完全由机会决定,运气是唯一决定因素的游戏是第五个游戏,玻璃垫脚石。在这款游戏中,玩家需要穿过一座连接两个高架在地面上方的平台的桥梁。这座桥由几个部分组成,每个部分由两块并排放置的玻璃面板组成。玩家需要从一个区域跳到下一个区域,每次跳跃时,他们需要跳到两个玻璃面板中的一个上,要么是右边的,要么是左边的。这两块面板看起来完全一样。然而,一种是普通玻璃,会在玩家将它们送向灭亡的重量下破碎,另一种是钢化玻璃,更坚固,可以承受玩家的重量。每一个正确的跳跃到钢化玻璃面板上,并且每一次消除向剩余的玩家展示该部分的钢化玻璃。在游戏开始之前,通过随机过程给每个玩家分配一个等级。等级决定了他们登上舰桥的顺序。除此之外,所有玩家都被集体给予一定的时间过桥,否则将面临灭顶之灾。这个游戏显然对玩家不利,玩家一开始就去。但是他们比后面的玩家差很多吗?这就是我们在本文中要量化和衡量的。这个 YouTube 视频展示了游戏的 VR 版本。
一座由五部分组成的桥。玩家无法分辨面板(图片由作者提供)。
在实际的系列赛中,在游戏的这一点上,只剩下 16 名玩家,每个人随机分配一个从 1 到 16 的数字,这决定了他们踩桥的顺序。这座桥由 18 部分组成(每部分有两块玻璃板)。任何成功通过所有 18 个部分而没有被淘汰的玩家走上平台并被拯救(暂时的!).
分析
我碰到一个 Python 模拟,计算每个玩家的生存概率,我觉得很有趣。我还编写了我的小 Python 模拟,并获得了类似的结果(见下一节)。然而,我决定对概率进行分析建模,为每个生存概率生成封闭形式的表达式,以便可以计算任意数量的玩家和区域的概率。在我们存在之前,让我们把我们的假设列表放在一起。
假设:我假设,
- 一旦一个步骤中的钢化玻璃被识别出来,它将被所有还没有到达那个步骤的玩家记住。
- 除了踩在玻璃板上,没有什么能显示这是普通玻璃还是钢化玻璃。
- 玩家根据他们的等级进行游戏,而不用走到另一个玩家站着的面板上。
符号:这里是我用来模拟概率的符号。
从首先站在桥上的不幸选手开始,1 号选手。让我们找出她生存的概率和她在任何阶段被淘汰的概率。
这意味着,对于参与人 1,被淘汰的概率,以及安全过桥的概率是,
对于参与人 2 来说,在阶段 m 被淘汰的概率是一个条件概率。
通过归纳,我们可以得出参与人 2 的如下一般陈述。
这意味着,对于参与人 2 来说,被淘汰的概率,以及安全过桥的概率是,
使用条件概率,通过归纳,我们可以发现 3 号和 4 号玩家在阶段 k 被淘汰的概率如下。
通过归纳,我们可以发现玩家等级 r 在阶段 m 被淘汰的概率如下。基于此,可以推导出玩家 r 在任一阶段被淘汰的概率,以及玩家 r 安全到达另一平台的概率。
证明:上述说法很容易用归纳法证明,假设 r=K-1 的概率,并在此基础上推导出 r=K 的概率,从而证明该说法。该证明的大致要点是,对于在第 m 段失败的玩家 r (其中 m 至少等于 r ),我们需要让所有的 r-1 玩家在 m-1 阶段的某处失败。发生这种情况有 (m-1)C(r-1) (二项式系数)种情况,每种情况的概率为 2 的 -m 。详细证明联系我!
基于以上结果,玩家 r 在任一阶段失败,并成功过桥的概率为,
2F1(a,b;c;z) 函数是超几何函数,它是广义超几何函数的一种特殊形式,描述如下:
要了解更多关于 Hypergoemetric 函数的信息,请参见此链接。
幸存者人数
我可以想象,当组织者为贵宾们安排比赛时,预期的幸存者人数一定发挥了作用。让我们定义离散随机变量 X 来表示每轮游戏中幸存的玩家数量。为了找到 E(X) ,我们需要计算出它的概率质量函数。对于 N=16 和 *K=18,*的博弈,可以推导出,
对于 *X、*的其他结果的概率,我们先来回顾一下结果 X=1 和 X=2 的概率,然后再进行推广。
总的来说,我们可以说,
**证明:**证明可以用归纳法构造。一般来说, X=0 、 X=N 和 X > N 的概率是不言自明的。对于剩下的选项,记住幸存的事件玩家 k 是幸存的事件玩家 k+1 的子集,以及被淘汰的事件玩家 k+1 是被淘汰的事件玩家 k 的子集是有益的。利用样本空间和事件的概率,你可以得出上面的结论。
幸存玩家的预期数量将会是,
这简化为,
换句话说,幸存玩家的期望数量是所有玩家成功概率的总和。在下一节中,我们将对上述结果进行数值分析。
数值分析
基于上面的闭合表达式,我们可以找到每个参与者的生存概率,其中有 16 个参与者,桥有 K=18 个阶段。Python 脚本如下所示。
当有 K=18 个区域时,每个玩家的结果如下所示。是的,前面的玩家比后面的玩家要差得多。最后 4 名队员生还概率高于 90%。
使用分析结果的 N=16 和 K=18 的生存概率。
这是当 K=18 时,16 个玩家中每一个的生存概率的可视化。
N=16,K=18 的生存概率(图片由作者提供)。
下面你可以看到 16 名玩家( N=16 )生存概率的相同可视化,但是是针对不同数量的部分( K )。请注意,随着桥上增加更多的部分,概率会迅速下降。
N=16 和不同 K 值的生存概率(图片由作者提供)
对于这个具有 N=16 和 K=18 (16 个玩家和 18 个区域)的特定游戏,以下是随机变量 X 的概率质量函数,代表幸存玩家的数量。
我们可以看到,该模式在 X=7 处,代表 7 个玩家以大约 0.185 的概率幸存。也许并不奇怪(注意对称性),这个特定游戏中幸存玩家的预期数量也大约是 7,或者确切地说 E(X)=7.000076294 。如果贵宾们期望幸存玩家的数量在 7 左右,他们一定会惊讶地发现只有 3 名玩家在第 5 场比赛中幸存。
下表显示了不同场景下的 E(X) 的值,以及不同玩家数量和区域的值( N 和 K )。
不同 N 和 K 值下的预期幸存者人数(图片由作者提供)
以下可视化了不同的 N 和k值下幸存玩家的期望值趋势( E(X)
不同 N 和 K 值下的预期幸存者人数(图片由作者提供)
观察该图,我们可以看到,对于任何给定的玩家数量,增加阶段的数量将减少幸存玩家的预期数量。正如所料,对于相同数量的部分,更多的玩家意味着更高的幸存玩家数量。
生存模拟
有了足够多的迭代次数,我们还可以用不同的值 N 和 K 来创建一个模拟,以找到玩家存活的概率以及存活玩家数量的期望值。下面是我写的一个简单的函数,用来计算每个玩家的生存概率。
在对 16 个玩家、18 个区域和 1,000,000 次迭代(游戏回合)运行该函数后,我计算出的 16 个玩家的生存概率与我分析得出的结果几乎相同。
使用模拟的 N=16 和 K=18 的生存概率。
我只模拟了 N=16 和 K=18 情况下的预期幸存者人数。结果非常接近我上面的分析结果。我对 1,000,000 次复制的模拟产生了预期的 6.997991 个幸存者,而分析结果给出了 7.00076294。我没有模拟寻找其他值 N 和 K 的幸存玩家的预期数量,但我认为它们应该也非常接近。
分析结果与模拟
我们得出了不同的 N (玩家数量)和 K (阶段数量)的生存概率和期望生存人数的分析结果。我们还使用数值/模拟分析证实了这些结果。但是哪种方法更有效呢?
一般而言,分析结果往往比模拟结果更受青睐。分析结果特别有用,因为它们提供了分析中的通用性、计算速度和效率。除此之外,分析结果非常有助于产生数值结果和敏感性分析。然而,封闭形式的表达式并不总是可用或容易导出。在这些情况下,模拟可以提供相当准确的结果。在这个特定的模型中,相对容易得出分析结果。然而,如果以随机事件或玩家之间复杂交互的形式给系统增加更多的复杂性,那么导出封闭形式的概率表达式来捕捉生存概率和期望值将变得越来越困难。在这些情况下,模拟可以帮助我们更容易地获得结果。
异常值检测和监控的生产就绪方法
一种从生产数据集中检测(并移除)异常值的方法。
介绍
威尔·梅尔斯在 https://unsplash.com 拍摄的照片
ML 项目中的生产数据经常受到异常(也称为离群值)的污染。这些异常值可能是由过程中的错误引起的,或者只是数据集的一部分。识别并纠正它们非常重要,因为它们会干扰您对数据的建模/解释。
在本文中,我们将介绍一种生产就绪的方法,以便检测和监控异常值,使您能够节省一些宝贵的时间来构建您的 ML 管道。
第一步,我们将展示一种使用四分位间距(IQR)检测列异常值的简单有效的方法。
第二步,我们将从多维角度(多列)处理离群值,并使用隔离林自动检测它们。
最后,我们将展示一种使用 pandera(一个统计数据验证工具包)监控数据库的有效方法。
本项目中使用的数据集可在 data demo outliers 获得。这是一个虚构的数据集,表示圣保罗的房地产数据。它包含 6 列,分别代表房间(房间数量)车库(车库数量)有用面积(单位面积)价值(单位价格)室内质量(单位室内质量)上市时间(出售单位所需时间)。我在 6 个专栏中介绍了几个异常,以展示下面介绍的方法的有效性。
这篇文章的代码可以在这个 github 库上找到。
包括每个部分的 jupyter 笔记本示例()。/demo/Explore _ outliers _ per _ column . ipynb,
。/demo/Explore _ outliers _ multi _ columns . ipynb,。/demo/Monitor _ outliers _ pandera . ipynb
使用 IQR 轻松检测列方向的异常值
Jhguch 的照片来自 en.wikipedia
四分位数间距(IQR)是统计离差的一种度量,等于第 75 个和第 25 个百分点之间的差值,
或者相当于上下四分位数之间的差值,IQR = Q3 Q1。
它可用于从我们的数据中提取每一列的最异常值。
一种方法是将 Q1-1.5 * IQR,Q3 + 1.5 * IQR 范围之外的每列数据视为潜在的异常值。
对于每一列,我们可以查看包含所有值的分布与排除这些异常值的分布。
当分布具有非常不同的形状时,它会突出显示列中异常值的存在,如下图所示。
IQR
在这里,我们可以在第一行看到市场上价格、面积和时间的完整分布。在第二行,我们在
绘制分布图之前应用了 IQR 滤波:
我们可以看到,在没有过滤的情况下,分布是高度偏斜的,突出了异常值的存在。
过滤后的图更能代表真实的数据分布。根据这些图和我们对数据的了解,我们可以决定每列可以接受的数据范围。
对于本例,我们预计价格不会超出 50 000–10 000 000 雷亚尔的范围,面积不会超出 20–850 平方米的范围,上市时间不会超出 0–400 天的范围
。我们可以为我们的每一列执行这种类型的异常值 EDA。这将有助于使用 pandera 为
部分中的每一列设置我们的业务规则,以便进行异常值监控。
隔离林用于检测多列中的异常值
隔离林不同阈值的 PCA 图
在很多情况下,需要从多维角度检测异常值。例如,您的模型可能依赖于许多特征。在这种情况下,检测每个特征的异常值(对于结构化表格数据是每个列)是不够的。你想要做的是多维度地对待异常值。隔离森林是识别这些异常点的理想工具。
隔离森林属于无监督学习算法的范畴。它将异常观察与样本的其余部分隔离开来,因为它们在特征空间中显得很遥远。这是一种建立在决策树基础上的树集成方法。该算法递归地生成分区,首先随机选择一个特征,然后在所选特征的最小值和最大值之间选择一个随机分割值。该过程继续进行,直到单个点被隔离或者达到指定的最大深度。一旦该算法遍历了整个数据,它就认为异常数据点比其他数据点采取的步骤更少而被隔离(需要更少的分裂来隔离它们)。
对于这个项目,我使用了来自 Scikit-Learn 库中的隔离林实现。训练之后,可以调用预测方法来了解特定样本是否是异常值。正常样本标记为 1,异常值标记为-1。为了可视化我们的高维数据,可以将 PCA 应用于特征以降低数据的维度(根据方差)。然后,我们可以绘制前三个组件,突出显示绿色正常数据和红色异常值。我们可以看到异常有远离主数据的趋势。这是对隔离森林算法的应用进行质量控制的一种有用的方法。识别异常和生成 PCA 图的代码可以在下面找到(更多细节可以在 github 库获得)。
在某些情况下,控制您的异常阈值或您希望被视为异常的数据点的最大数量可能会很有用。为此,调用 score_samples 方法来获得数据集每个点的异常值是很有用的。然后,您可以在箱线图中显示这些分数(下图示例),以便选择不同的阈值。分数越低,数据点就越不正常。选择较低的阈值将允许减少要检测的异常点的数量。
异常分值的箱线图
您甚至可以决定您希望被视为异常的数据集的百分比。所有这些行为的例子都在 jupyter 的笔记本上演示过。/demo/Explore _ outliers _ multi _ columns . ipynb,使用中创建的函数。/demo/outliers_util.py 。
我们为不同的异常阈值生成了 3D PCA 散点图,以创建 gif 插图。我们可以看到,对于异常值检测,我们可以决定更保守或更保守。
这是在您的 ML 管道中使用的一个非常强大的工具,因为数据集中异常的存在会干扰您的模型行为/性能。
通过使用隔离林自动检测和移除最异常的数据点,您可能会提高您的整体模型性能。特别是,如果您的生产数据包含大量样本(高维),移除 0.5%最异常的样本(几乎没有额外成本)将是一个很好的生产实践。
用 pandera 监控你的数据:熊猫的统计数据验证工具包
在生产环境中,数据库会定期更新,并且应监控异常情况。现在我们已经了解了检测和消除生产数据中异常值的技术,我们将了解如何定期监控您的数据库,并使用 Pandera 执行统计验证检查。Pandera 提供了一个灵活且富有表现力的数据验证工具包,帮助用户对 pandas 数据结构进行统计断言。
基于您对数据的了解,您可以轻松地使用 Pandera 来实施规则,以检查要素中的类型和可接受范围。作为下面的例子,我们为演示数据集创建了一些规则。正如我们在异常值 EDA 中看到的,列有用区域应该是一个浮点值,我们不希望值超出 20–850 m2 的范围。
同样,我们为剩余的列 value (价格) rooms 、 garages 、 time_on_market 和 interior_quality 创建了规则。例如,列 interior_quality 应该包含 1、2、3、4 或 5 范围内的整数值。下面是我们演示数据集的代码示例。
基于数据集知识定义规则后,您可以定期运行 pandera 代码来识别数据库中的新异常。如果一些新数据点不遵守您定义的规则,它将输出一些警告消息,突出显示需要纠正的问题。这是确保数据库在不同时间段的数据质量的一种强大而简单的方法。
下面是一个例子,说明在我们没有从数据集中移除异常值的情况下,输出会是什么样子。
输出 Pandera 警告
结论
我们提出了一种从生产数据集中检测(和去除)异常值的方法。
首先,对于每一列,IQR 可用于探索、识别和移除异常数据点,如果您的分布形状受到异常值的影响,则使用分布图进行质量控制。
其次,从多列的角度,我们已经看到了如何使用隔离森林来自动检测特征空间中的异常观察值。在训练您的模型之前移除这些异常将提高您的 ML 管道的稳健性。
然后,我们提出了一种方法来监控您的生产数据,并在不同的时间段检测新的异常。Pandera 使统计数据验证变得容易,确保您的数据库定期无异常。
所有这些技术都有助于确保更好的数据质量,使您能够通过关注 ML 管道的其他领域来提高工作效率。
参考
刘、范晓东、丁肇中、、周志华。“基于隔离的异常检测。”《美国计算机学会数据知识发现汇刊》6.1 (2012): 3。
[https://cs . nju . edu . cn/Zhou zh/Zhou zh . files/publication/tkdd 11 . pdf刘、范晓东、丁肇中、、周志华。“隔离林。”数据挖掘,2008。08 年的 ICDM。第八届 IEEE 国际会议。
[https://cs . nju . edu . cn/Zhou zh/Zhou zh . files/publication/ICD m08 b . pdf?q =隔离森林[https://towards data science . com/outlier-detection-theory-visualizations-and-code-a4fd 39 de 540 c]
[https://www . pyo pensci . org/blog/pandera-python-pandas-data frame-validation]
[https://towards data science . com/how-automated-data-validation-make-me-more-productive-7d6b 396776]
处理大于内存的数据集的 PySpark 示例
一个关于如何使用 Spark 对大于内存的数据集执行探索性数据分析的分步教程。
使用 Jupyter 笔记本和 Pandas 数据框分析大于可用 RAM 内存的数据集是一个具有挑战性的问题。这个问题已经解决了(例如这里的这里的或者这里的这里的),但是我在这里的目标有点不同。我将介绍一种对大型数据集进行探索性分析的方法,目的是识别和过滤掉不必要的数据。希望最终熊猫可以处理过滤后的数据集进行剩余的计算。
这篇文章的想法来自于我最近的一个项目,涉及对开放食品事实数据库的分析。它包含在世界各地销售的产品的营养信息,在撰写本文时,他们提供的 csv 出口量为 4.2 GB。这比我在 Ubuntu 虚拟机上的 3 GB 内存还大。然而,通过使用 PySpark,我能够运行一些分析,并且只从我的项目中选择感兴趣的信息。
为了在 Ubuntu 上设置我的环境,我采取了以下步骤:
- 安装 Anaconda
- 安装 Java openJDK 11: sudo apt-get 安装 openjdk-11-jdk。Java 版本很重要,因为 Spark 只能在 Java 8 或 11 上运行
- 安装 Apache Spark(3 . 1 . 2 版本为 Hadoop 2.7 此处)并配置 Spark 环境(将 SPARK_HOME 变量添加到 PATH)。如果一切顺利,你应该可以在你的终端上启动 spark-shell 了
- 安装 pyspark:conda install-c conda-forge pyspark
如果你有兴趣阅读 Spark 的核心概念,这是一个好的开始。如果没有,您可以打开 Jupyter 笔记本,导入 pyspark.sql 模块并创建一个本地 SparkSession:
我使用 sc.read 从我的 SparkSession 中的大型 csv 文件读取数据。尝试在只有 3 GB RAM 的虚拟机上加载 4.2 GB 文件不会出现任何错误,因为 Spark 实际上不会尝试读取数据,除非需要某种类型的计算。
结果是 pyspark.sql.dataframe 变量。重要的是要记住,此时数据并没有真正载入 RAM 存储器。只有在对 pyspark 变量调用一个操作时,才会加载数据,这个操作需要返回一个计算值。例如,如果我要求计算数据集中产品的数量,Spark 很聪明,不会为了计算这个值而尝试加载全部 4.2 GB 的数据(将近 200 万个产品)。
我使用 pyspark 的 printSchema 函数来获取一些关于数据结构的信息:列及其相关类型:
为了开始探索性分析,我计算了每个国家的产品数量,以了解数据库的组成:
BDD_countries 也是 pyspark 数据框架,其结构如下:
我可以过滤这个新的数据框,只保留数据库中记录了至少 5000 种产品的国家,并绘制结果:
例如,从这里我可以过滤掉所有在法国买不到的产品,然后在一个更小、更容易处理的数据集上执行其余的分析。
本文介绍了一种在 Python 中处理大于内存的数据集的方法。通过使用 Spark 会话读取数据,可以执行基本的探索性分析计算,而无需实际尝试将完整的数据集加载到内存中。当我们希望能够获得数据的第一印象并寻找识别和过滤掉不必要信息的方法时,这种类型的方法会很有用。
R markdown 的 python 等价物
R markdown 是分享见解的强大工具。在这篇文章中,我们将展示如何用 python 编写类似的报告。
R markdown 是一个与利益相关者分享见解的强大工具。您可以编写生成图的 R 代码片段。然后可以将其编译成 HTML 或 pdf 文件,与非技术相关人员共享。
这在 python 中没有这么简单。是的,Jupyter 笔记本是与其他开发人员共享分析的一种很好的方式。但是编译成 HTML/pdf,去掉代码片段,对于非技术利益相关者来说已经很不错了,我发现使用 Jupyter 笔记本很笨拙。R markdown 也有很棒的工具来生成好看的表格,而不仅仅是绘图。
不过,我一直在和一个 python 重型团队一起工作,所以一直在试图弄清楚如何生成 R markdown 风格的文档。在这篇文章中,我将概述我用 python 生成的 HTML 报告,这些报告看起来很好,足以与非技术利益相关者分享。这个过程使用一些工具。
卢克·切瑟在 Unsplash 上拍摄的照片
步骤 1:在 HTML 中嵌入绘图
第一步是将图嵌入到一个静态 HTML 中,然后可以与他人共享。一个很好的工具是 plotly 。Plotly 有一个[to_html](https://plotly.com/python-api-reference/generated/plotly.io.to_html.html)
函数(我的一个了不起的同事发现了这个),它将把图形写成 HTML 字符串,然后你可以把它写到一个文件中。
Plotly 图形看起来像零件,它们允许用户将鼠标悬停在点上,以查看值是多少;我发现这很受顾客欢迎。
有时用户需要可以复制粘贴的图形。在这种情况下,我推荐使用 python 更标准的绘图库,如 seaborn 或 matplotlib 。要将图像嵌入到 HTML 中,而不需要 HTML 引用的单独的图像文件,这就有点复杂了。但是您可以通过将图像编码为 base64 并直接写入您的 HTML 来实现。只需按照这个 stackoverflow 帖子中的说明。
照片由 Pankaj Patel 在 Unsplash 上拍摄
步骤 2:设置 HTML 文档的布局
太好了,现在你可以在 html 中嵌入图形了,实际上如果你关闭了 plotly 的to_html
函数中的full_html
选项,你就可以通过添加字符串来编写任意多的 plotly 图形到 HTML 文件中。
但是布局、评论和数据表呢?这就是我使用 python 的 HTML 模板库的地方——它允许您使用 python 从模板生成静态 HTML 文件。这种技术非常强大,用于 python 后端开发库,如 flask 和 django 。学习起来很快,但是需要一些 HTML 知识。
我使用 Jinja 库来生成我的 HTML 报告(这是 python 中最流行的 HTML 模板库之一)。
第三步:让报告看起来漂亮
对于任何以前使用过 HTML 的人来说,你会知道做任何看起来像样的东西都需要很长时间。
我不想在这上面花太多时间,因为我想尽快生成报告。所以我用了 bootstrap CSS 库。这个工具可以让你在很短的时间内让你的报告看起来很漂亮(我倾向于做的就是用<div class="container">
把所有的东西都包起来,可能还会添加一些填充)。
Bootstrap 基本上是一组预建的 HTML 类,可以用来格式化 HTML。例如,让一个 HTML 表格在 bootstrap 中看起来漂亮,就像<table class="table">
一样简单(在标准 HTML 中,表格看起来很难看)。您可以通过添加<h1 class="pt-1">
在标题元素的顶部添加填充。
思想
正如你所看到的,这是一个比 R markdown 更复杂的过程(如果有人有更好的方法,请联系我们!).但是学习这些工具很有用,尤其是 Jinja 和 bootstrap,它们是 web 开发的标准工具。一旦你学会了这些库,并且准备好了一些预制的模板,这个过程会变得很快。
原载于 2021 年 5 月 4 日【https://jackbakerds.com】。
一个 Python 框架来检索和处理来自 TRIOS 传感器的超光谱场测量(MDSA 格式)
思想和理论
介绍
随着技术的快速发展,遥感在不同学科中有着广泛的用途,从森林火灾测绘到水质评估、三维表面建模等等。通过在一定距离上测量一个区域的反射和发射辐射来获得该区域的物理特性有许多优点。然而,实地测量与遥感数据同样重要,这样才能开展研究,将远距离“看到”的东西与地面真实情况联系起来。就多光谱遥感图像而言,重要的是使用高光谱传感器进行实地测量,以便校准最终结果。
语境
2021 年初,我的论文导师告诉我,我们需要恢复一些超光谱场测量数据。这些测量已经在世界各地的各种古代地形战役中完成。目标似乎很简单。我应该从 3 个现场传感器(辐照度和辐射度——上升流和天空传感器)检索测量值,以计算最终的反射率(方程式。1).所有的现场测量都是通过使用众所周知的传感器完成的,并且结果被存储在 Microsoft Access 文件中。mdb)。因为有专门的软件来管理。mdb 文件从制造商的传感器,称为 MDSA XE,我认为这将是一个“小菜一碟”。我大错特错了。
情商。1:遥感反射率公式,其中:Rrs =遥感反射率,Lu =上升辐射亮度,Ld =下降辐射亮度或天空辐射亮度,Ed =辐照度。
德国人以他们的工业和设备质量而闻名。那是毫无疑问的。然而,当谈到系统、用户界面或可用性时,似乎总是缺少一些东西。在 MSDA 的例子中,缺少了很多东西。即使像打开文件这样简单的任务也是一个奇怪的操作,需要重启应用程序。我不能依靠它来完成我的任务。
为此,我开发了一个名为RadiometryTrios
的“非官方”框架,可用于 Python,这将使事情变得容易得多,不仅可以访问这种数据,还可以从中创建整个数据库。
框架
如前所述,该框架负责使用 TRIOS 设备处理来自野外活动的超光谱辐射测量数据。
操纵包括:
- 从 MSDA/TRIOS 格式的
.MDB
文件中提取辐射测量值。 - 辐射测量分析、数据清理和图表绘制
- 波长插值
- 反射率生成(来自辐射和辐照度测量)
- 不同格式的输入/输出
图 1 显示了RadiometryTrios
框架的模式。
图 1:辐射测量 Trios 包模式。图片作者。
包中声明的类有:
- BaseRadiometry :这个类拥有一些其他类通用的功能,比如绘图和插值功能。这个类的方法被声明为“静态的”,可以作为简单的函数使用。
- TriosMDB :这个类负责连接到 access。mdb 文件并从中提取辐射度。可以过滤值,以便提取与感兴趣的测量值相对应。
- 辐射度:该类表示来自特定测量(单个传感器,但多次)的辐射度。它允许数据清理,过滤和绘图。
- 辐射测量组:如上所述,为了获得反射率,需要使用来自 3 个不同传感器的值。在这方面,RadiometryGroup 类存储了许多辐射度,并使同时对所有辐射度应用过滤器变得更加容易。它还支持绘图功能。
- RadiometryDB :最后,最后一个类负责创建和维护一个辐射测量数据库,这个数据库来自于已经处理过的许多测量数据。
安装
这个包可以在下面的 GitHub 库中找到:https://github.com/cordmaur/RadiometryTrios
存储库包含关于安装和依赖项的详细信息,但是,总而言之,只需要克隆项目并安装它。
git clone https://github.com/cordmaur/RadiometryTrios.git
cd RadiometryTrios
pip install -e .
注意:
-e
选项将在开发者模式下安装这个包,这样可以更容易地对源代码(在项目文件夹中)进行修改,并且这些修改会自动应用,不需要重新安装。
要检查它是否安装正确,请在 python shell(或 Jupyter 笔记本)上运行以下命令:
import RadiometryTrios
RadiometryTrios.__version__
'0.0.1'
包装使用
一旦我们成功安装了这个包,是时候学习如何使用它的许多功能了。
TriosMDB
将涉及的第一类是TriosMDB
类。在nbs/
文件夹中的笔记本00_TriosMDB.ipynb
详细描述了如何使用它。
需要注意的是,TriosMDB
类负责幕后的 ODBC 连接。这意味着您不必手动处理它,唯一的要求是安装pyodbc
包,这是强制性的。让我们看看如何打开连接并显示摘要:
{'FileName': WindowsPath('../mdbs/trios_test.mdb'),
'Records': 937,
'IDDevice': "['IP_c090', 'SAM_83AE', 'SAM_83ba', 'SAMIP_5078', 'SAM_83B0', 'SAM_83BA']",
'IDDataType': "['Inclination', 'Pressure', 'SPECTRUM', 'SAMIP']",
'MethodName': "['SAMIP_5078', 'SAM_83AE', 'SAM_83B0', 'DoubleSpecCalc_2', 'SAM_Calibration_Station', None]",
'IDMethodType': "['SAMIP Control', 'SAM Control', 'DoubleSpecCalc', 'SAM Calibration Station', None]",
'Comment': "['Ed deck', 'Lu deck', 'Ld deck', 'reflectance', None]",
'CommentSub1': "[None, 'factor 0.028']",
'CommentSub2': '[None]'}
一旦一个TriosMDB
对象被创建,它就用来自tblData
表的所有内容填充一个熊猫DataFrame
。这可以通过.df
属性来访问。tblData
是三重奏/MSDA 格式的默认表格。要访问内容:
mdb.df.head(3)
分析 MDB 文件最基本的操作可能是执行查询。函数exec_query
以列表或 pandas 数据帧的形式返回查询结果。exec_query
也可用于检查 MDB 文件中的其他表格。让我们检查一下**tblData**
(主表)的内容。结果输出可以是数据帧或列表,其中每一项都是一个表示表行的元组。
mdb.exec_query("select top 1 * from tblData", output_format='pandas')
或者结果可以显示为列表:
results = mdb.exec_query("select top 1 * from tblData", output_format='list')
results[0][:6]('2572_2015-11-14_14-29-21_188_038',
1,
'IP_c090',
'Inclination',
'Calibrated',
None)
从 MDB 中选择辐射度
要检索 MDB 文件的测量值,必须指定所需辐射测量类型应满足的条件。这些条件可以是不同列/值的组合,并且必须在字典中指定。每个条件的组合将与一种辐射测量类型相关,也称为 **r 型。**例如,在这个 MDB 中,我们可以看到已经计算了反射率。检查 ACCESS 中的 MDB,我们可以看到这些反射率与一些 id 设备相关联:
要访问所需的辐射测量,我们首先需要创建一个字典,其中包含每种辐射测量类型的条件,如下所示。一旦select_radiometries
被成功调用,如果逻辑= ‘和’,或者如果逻辑= ‘或’,它将检索与所有类型一致的时间,或者在 MDB 上找到的所有时间。每个辐射测量数据帧将被载入.measurements
属性。这将在访问测量值部分进行解释。
DatetimeIndex(['2015-11-14 14:39:45', '2015-11-14 14:39:55',
'2015-11-14 14:40:05', '2015-11-14 14:40:15',
'2015-11-14 14:40:25', '2015-11-14 14:40:35',
'2015-11-14 14:40:45', '2015-11-14 14:40:55',
'2015-11-14 14:41:05', '2015-11-14 14:41:15',
'2015-11-14 14:41:25', '2015-11-14 14:41:35',
'2015-11-14 14:41:45', '2015-11-14 14:41:55',
'2015-11-14 14:42:05', '2015-11-14 14:42:15',
'2015-11-14 14:42:25', '2015-11-14 14:42:35',
'2015-11-14 14:42:45', '2015-11-14 14:42:55',
'2015-11-14 14:43:05', '2015-11-14 14:43:15',
'2015-11-14 14:43:25', '2015-11-14 14:43:35',
'2015-11-14 14:43:45', '2015-11-14 14:43:55',
'2015-11-14 14:44:05', '2015-11-14 14:44:15',
'2015-11-14 14:44:25', '2015-11-14 14:44:35',
'2015-11-14 14:44:45', '2015-11-14 14:44:55',
'2015-11-14 14:45:05', '2015-11-14 14:45:15',
'2015-11-14 14:45:25', '2015-11-14 14:45:35',
'2015-11-14 14:45:45', '2015-11-14 14:45:55'],
dtype='datetime64[ns]', freq='10S')
将辐射度可视化
TriosMDB 类的目标基本上是从 Trios/MSDA mdb 中搜索和导出测量值。对于更高级的操作,如插值、反射率计算或数据清理,辐射测量类更合适。尽管如此,TriosMDB 还是提供了一些基本的绘图功能,以确保导出的内容有意义。
mdb.plot_radiometry('reflectance', min_wl=380, max_wl=950)
mdb.plot_radiometries(cols=2, min_wl=380, max_wl=950)
导出辐射测量
最后一步是将辐射度量导出到文本文件。输出是 Trios/MSDA 格式的. txt 文件(类似于。
create_measurement_dir
标志表示是否必须创建子目录。子目录名遵循 YYYYMMDD-mmss 格式,并且是RadiometryDatabase
类使用的格式。
请记住,这种格式不容易被操纵。它旨在保持与 MSDA 输出文件的兼容性。
为了获得更加用户友好的格式,建议使用由Radiometry
类提供的插值输出。
out_dir = mdb.export_txt(create_measurement_dir=True)Saving output file to ..\mdbs\20151114-1439
将返回输出目录。将它存储在一个变量中是一个很好的实践,因为它将用于打开Radiometry
类。现在让我们检查一下已经保存的文件:
[file for file in out_dir.iterdir()]
[WindowsPath('../mdbs/20151114-1439/Ed_interpolated.bak'), WindowsPath('../mdbs/20151114-1439/Ed_interpolated.csv'), WindowsPath('../mdbs/20151114-1439/Ed_spectrum_LO.bak'), WindowsPath('../mdbs/20151114-1439/Ed_spectrum_LO.txt'), WindowsPath('../mdbs/20151114-1439/Fig_20151114-1439.png'), WindowsPath('../mdbs/20151114-1439/Ld_interpolated.bak'), WindowsPath('../mdbs/20151114-1439/Ld_interpolated.csv'), WindowsPath('../mdbs/20151114-1439/Ld_spectrum_LO.bak'), WindowsPath('../mdbs/20151114-1439/Ld_spectrum_LO.txt'), WindowsPath('../mdbs/20151114-1439/Lu_interpolated.bak'), WindowsPath('../mdbs/20151114-1439/Lu_interpolated.csv'), WindowsPath('../mdbs/20151114-1439/Lu_spectrum_LO.bak'), WindowsPath('../mdbs/20151114-1439/Lu_spectrum_LO.txt'), WindowsPath('../mdbs/20151114-1439/reflectance_spectrum_LO.txt'), WindowsPath('../mdbs/20151114-1439/Rrs_interpolated.bak'), WindowsPath('../mdbs/20151114-1439/Rrs_interpolated.csv')]
检查反射文件的内容。我们可以在记事本或任何其他文本编辑器中打开它:
如前所述,我们可以看到,这种格式对于在 Excel 或 Pandas DataFrame 中打开是不友好的。辐射测量类提供的interpolated .csv
输出更适合这些目的。
笔记本
在/nbs/00_TriosMDB.ipynb
笔记本上可以找到包含更多示例的所有代码:
结论
在第一部分中,我们已经看到了如何使用TriosMDB
类从。MSDA/Trios 格式的 mdb 文件。提供了基本的过滤功能来定位内部的精确测量值。mdb 文件并将其导出到文本文件。更高级的操作功能,如数据清理、过滤、插值等。由Radiometry
和RadiometryGroup
类提供,但是它们将在下一部分中讨论。
谢谢,到时见。
如果你喜欢这篇文章,并且想继续无限制地阅读/学习,可以考虑成为 中等会员 。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
https://cordmaur.medium.com/subscribe
消除共线性的 Python 库
一个处理共线变量的简单 Python 库
作者图片
共线性是机器学习项目中非常普遍的问题。它是数据集特征之间的相关性,它会降低我们模型的性能,因为它增加了方差和维数。当你不得不处理无人监督的模型时,情况变得更糟。
为了解决这个问题,我创建了一个移除共线要素的 Python 库。
什么是共线性?
共线性通常称为多重共线性,是一种当数据集的要素显示彼此高度相关时出现的现象。通常用皮尔逊相关系数来衡量。如果相关矩阵显示出绝对值较高的非对角元素,我们就可以讨论共线性。
共线性是一个非常大的问题,因为它增加了模型方差(特别是对于线性模型),它增加了维数而没有增加信息,此外,它扭曲了我们解释模型的能力。如果两个要素共线,则不应将它们放在一起考虑,只应考虑信息最丰富的要素。
我多年来一直在处理共线性问题,最终决定创建一个 Python 库来帮助像我一样的其他数据科学家高效地处理这个问题。
如何消除共线性
首先,我们必须为相关系数的绝对值定义一个阈值。适当的探索性数据分析可以帮助我们在我们的数据集中确定这样一个阈值,但对于一个通用项目,我的建议是使用 0.4。它适用于多种类型的关联,尽管我再次建议执行适当的 EDA 来找到适合您的数据集的值。
一旦设置了阈值,我们需要相关矩阵只包含绝对值小于该阈值的非对角线元素。
对于无监督的问题,想法是计算相关矩阵,并移除所有那些产生绝对值大于该阈值的元素的特征。我们可以从不太相关的对开始,并且只要考虑阈值,就继续添加特征。这给了我们一个不相关的数据集。
对于有监督的问题,我们可以使用例如单变量方法来计算特征重要性。我们可以考虑最重要的特征,然后按照它们的重要性不断添加特征,从最重要的特征到不太重要的特征,只有在考虑阈值约束的情况下才选择它们。
这个想法是,通过添加一个特征,我们在相关矩阵中添加了一个新行和一个新列,所以我们必须小心。这就是为什么我创建了我的图书馆。
“共线性”包
我们可以使用 pip 轻松安装我的“共线性”库。
!pip install collinearity
让我们看看 Python 中的动作。
首先,我们需要导入共线性包的选择非共线性对象。
from collinearity import SelectNonCollinear
这是执行特性选择和实现 sklearn 对象的所有方法的对象。
现在,让我们导入一些有用的库和波士顿数据集。
from sklearn.feature_selection import f_regression
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn.datasets import load_boston sns.set(rc={'figure.figsize':(12,8)})
让我们从无监督方法开始,在这种方法中,我们不知道目标变量,只想减少聚类问题的特征数量,
让我们导入数据集并计算关联热图。
X,y = load_boston(return_X_y=True)
features = load_boston()['feature_names']
df = pd.DataFrame(X,columns=features)
sns.heatmap(df.corr().abs(),annot=True)
作者图片
如我们所见,我们有几个共线的变量(即热图中颜色较浅的变量)
我们现在可以创建一个 SelectNonCollinear 对象的实例,并将阈值设置为 0.4。
selector = SelectNonCollinear(0.4)
与每个 scikit-learn 对象一样,我们有 fit 、 transform 和 fit_transform 方法。我们还有 get_support 方法,它为我们提供了所选特性的数组掩码。
让我们来拟合对象,并获取所选特征的蒙版。
selector.fit(X,y)
mask = selector.get_support()
现在,我们可以只考虑选定的功能,并再次绘制关联热图:
df2 = pd.DataFrame(X[:,mask],columns = np.array(features)[mask])
sns.heatmap(df2.corr().abs(),annot=True)
作者图片
所选要素现在显示出比原始集合更低的共线性,并且没有系数如预期的那样大于 0.4。
对于有监督的方法,我们需要设置得分函数,该函数用于计算一个特性相对于给定目标的重要性。对于像这样的回归问题,我们可以使用 f_regression 。对于分类问题,我们可能要用 f_classif。
我们需要在实例的构造函数中设置这个值。然后我们可以重新安装我们的选择器。
selector = SelectNonCollinear(correlation_threshold=0.4,scoring=f_regression) selector.fit(X,y) mask = selector.get_support()
我们现在可以计算新的热图,在这个例子中,它与无监督的情况相同。
df3 = pd.DataFrame(X[:,mask],columns = np.array(features)[mask])
sns.heatmap(df3.corr().abs(),annot=True)
作者图片
如果我们只想过滤我们的数据集,我们可以很容易地调用转换方法。
selector.transform(X)
# array([[ 0\. , 15.3 , 396.9 , 4.98],
# [ 0\. , 17.8 , 396.9 , 9.14],
# [ 0\. , 17.8 , 392.83, 4.03],
# ...,
# [ 0\. , 21\. , 396.9 , 5.64],
# [ 0\. , 21\. , 393.45, 6.48],
# [ 0\. , 21\. , 396.9 , 7.88]])
这允许我们在 sklearn 的管道中使用 SelectNonCollinear 对象。
pipeline = make_pipeline( SelectNonCollinear(correlation_threshold=0.4,scoring=f_regression), LinearRegression() )
pipeline.fit(X,y)
这样,我们可以毫不费力地在 ML 管道中实现这个对象。
结论
我实现了这个库来消除无监督和有监督机器学习项目的共线性。阈值的值应该根据适当的 EDA 来设置。对于像本例中使用的数据集这样的数据集,可能会出现这样的情况:在无监督和有监督方法之间,所选的要素是相同的。我的建议是根据我们的问题使用正确的方法。
如果您有任何意见、问题或建议,请随时使用我的 GitHub repo:https://github.com/gianlucamalato/collinearity
原载于 2021 年 6 月 28 日 https://www.yourdatateacher.com*。*
迷宫搜索算法的 Python 模块
Python 迷宫世界 pyamaze
【pyamaze 模块是为方便随机迷宫的生成而创建的,可以有效地应用不同的搜索算法。
这个模块 pyamaze 的主要思想是帮助创建可定制的随机迷宫,并能够在此基础上工作,就像轻松应用搜索算法一样。通过使用这个模块,你不需要编写 GUI 程序,也不需要面向对象的程序,因为这个模块会为你提供支持。这个模块使用 Python 内置的 Tkinter GUI 框架,使用这个模块你不需要安装任何框架。
关于该模块的详细信息如下所示,在本视频中也有解释
安装软件包:
在命令提示符下运行以下命令:
pip install pyamaze
或者你可以访问 GitHub 链接并将模块代码复制为 Python 文件,命名为 pyamaze.py
以下是如何使用模块的详细说明
生成迷宫:
要简单地生成一个迷宫,你需要创建迷宫对象,然后应用 CreateMaze 函数。最后一条语句将应用函数 run 来运行模拟。
from pyamaze import mazem=maze()m.CreateMaze()m.run()
一个随机的 10x10 迷宫将会这样生成:
随机生成一个 10x10 的迷宫
左上角的单元格是迷宫的目标,我们可以通过多种方式将目标更改为任何单元格。此外,默认情况下,会生成一个完美迷宫,这意味着迷宫的所有单元都是可访问的,并且从任何单元到目标单元都有且只有一条路径。因此,任何单元格都可以被视为起始单元格,因此不会突出显示。在内部,最后一个单元,即最后一行和最后一列单元被设置为起始单元。所以,总的任务是找到从右下角的单元格到左上角的单元格的路径。
我们可以在创造迷宫的时候改变它的大小。例如,5x5 迷宫可以生成为:
from pyamaze import mazem=maze(5,5)m.CreateMaze()m.run()
随机的 5x5 迷宫
CreateMaze 函数的第一个参数是行号,第二个参数是列号。要生成大小为 15x20 的迷宫,您应该使用 m.CreateMaze(15,20)函数。
为了在程序中使用迷宫参数,了解这些参数是很重要的。首先,迷宫的单元有两个索引,一个用于行,另一个用于列。之前生成的 5x5 迷宫的指数如下所示:
迷宫细胞的指数
create maze 的可选参数:
为了定制生成的迷宫,我们可以使用不同的可选输入参数。
目标(x 和 y): 要将目标单元格从(1,1)更改为其他单元格,我们可以提供可选参数 x 和 y 作为目标。例如,为了使单元格(2,4)成为目标,我们将使用函数 CreateMaze(2,4)
**图案:**我们可以生成一个水平(或垂直)的图案迷宫。水平模式迷宫意味着与垂直线相比,迷宫将具有更长的水平线,类似地,对于垂直模式,垂直迷宫线将更长。我们可以将可选的参数模式设置为 h 或 H 用于水平模式,将 v 或 V 用于垂直模式。
例如,要生成一个目标为单元格(5,5)的垂直图案 5x5 迷宫,我们将使用如下函数:
m.CreateMaze(5,5,pattern=’v’)
样本生成的迷宫是:
垂直模式迷宫
多路径迷宫:
默认情况下,生成的迷宫是完美迷宫,这意味着从任何单元格到目标单元格只有一条路径。但是,我们可以通过将可选参数 loopPercent 设置为某个正数来生成一个具有多条路径的迷宫。 loopPercent 设为最高值 100 表示迷宫生成算法将最大化多条路径的数量,例如:
m.CreateMaze(loopPercent=100)
生成的迷宫如下所示:
多路径迷宫(环路)
保存生成的迷宫:
也有可能保存任何生成的迷宫供将来使用。为此,我们需要将可选参数 saveMaze 设置为 True 。随机生成的迷宫将作为 CSV 文件保存在工作文件夹中。CSV 文件将包含迷宫内所有单元格的信息以及东西南北方向打开和关闭的墙的信息。1 表示路径在该方向打开,0 表示路径关闭。
通过使用 loadMaze 选项并提供 CSV 文件,我们可以稍后使用 CSV 文件生成相同的旧迷宫。
有了这个特性,我们还可以通过更改 CSV 文件来手动定制迷宫。要从迷宫中添加或删除一面墙,我们应该更改 CSV 文件的两个值。
从 CSV 文件加载迷宫时,创建迷宫时迷宫的大小无关紧要,因为关于大小的信息也是从 CSV 文件加载的。
主题:
迷宫的默认主题是黑暗主题,我们可以通过使用参数 主题 并将其设置为光明主题,将其更改为光明主题。我们在 pyamze 模块中也有一个 COLOR 类来管理不同的颜色。要将主题设置为 light,我们可以将其设置为一个 COLOR class 对象,如下所示:
m.CreateMaze(theme=COLOR.light)
或者我们也可以提供字符串形式的值,如下所示:
m.CreateMaze(theme=”light”)
将代理放入迷宫:
我们可以在迷宫中放置代理(一个或多个)。一个代理可以被认为是一个像机器人一样的物理代理,或者它可以简单地用于在迷宫中突出或指出一个细胞。
为此,我们在 pyamaze 模块中有 代理 类。导入代理类后,我们可以创建代理对象,我们应该提供父迷宫作为第一个输入参数。默认情况下,代理将被放置在迷宫的起始单元格(最后一个单元格)上。
下面是在默认大小的迷宫上创建一个带有灯光主题的代理的完整代码:
from pyamaze import maze,COLOR,agentm=maze(10,10)m.CreateMaze(theme=COLOR.light)a=agent(m)m.run()
灯光主题迷宫中的代理人
现在让我们看看代理类的不同可选参数。
**代理的位置:**代理的默认位置是迷宫的开始单元,即迷宫的右下角。您可以通过设置单元格的值 x 和 y 来更改位置。
代理对象有两个属性 x 和 y ,您可以在创建代理后访问和设置这些属性。此外,代理将属性 位置 设置为元组 (x,y) ,该元组提供完整的 x 和 y 信息作为一个参数。您也可以将其设置为其他值来更改代理的位置。
**代理的目标:**代理的默认目标是迷宫的目标,这意味着代理的目标是到达迷宫的目标。但是,如果要改变代理的目标,可以在创建代理时设置参数 目标 来实现。应该将二值元组指定为代理的目标。
**代理的大小:**默认情况下,代理的大小小于单元格的尺寸。您可以将参数 填充 设置为 真 ,代理将填充整个单元格。
代理的形状:默认情况下,代理为方形,还有第二个形状选项箭头,可以设置为 形状 参数,代理将为箭头形状。这将区分代理的正面和其他面。如果形状设置为箭头,参数 填充 无效。
看脚印:当你要实现一些搜索算法,智能体要在迷宫中移动的时候,可以要求可视化完整的路径轨迹。为此,我们可以将可选参数footprint**更改为 True 并且每当代理改变其位置时,脚印的印象将被强加到先前的位置上。脚印只是代理的形状,但颜色不同。查看这段代码的输出:
from pyamaze import maze,COLOR,agentm=maze(5,5)m.CreateMaze()a=agent(m,shape=’arrow’,footprints=True)a.position=(5,4)a.position=(5,3)a.position=(5,2)m.run()
迷宫类的其他属性:
为了实现某种搜索算法,您应该知道迷宫类的一些属性:
行数: m.rows 给出迷宫的行数 m 。
列: m.cols 给出迷宫的列数 m 。
网格: m.grid 是从(1,1)到最后的所有单元格的列表。
**迷宫地图:**随机生成一个迷宫。知道迷宫的不同打开和关闭的墙壁的信息是重要的。该信息在属性 迷宫 _ 地图 中可用。它是一个字典,其中键作为迷宫的单元格,值作为另一个字典,其中包含该单元格在四个方向上的四面墙的信息;东西南北。
您可以看到该属性的值,并使用生成的迷宫确认这些值,如下所示:
print(m.maze_map)
生成的示例迷宫和 迷宫 _ 地图 的值如下所示:
示例迷宫和迷宫 _ 地图如下所示
maze_map = {(1, 1): {‘E’: 1, ‘W’: 0, ’N’: 0, ‘S’: 0}, (2, 1): {‘E’: 0, ‘W’: 0, ’N’: 0, ‘S’: 1}, (3, 1): {‘E’: 0, ‘W’: 0, ’N’: 1, ‘S’: 1}, (4, 1): {‘E’: 0, ‘W’: 0, ’N’: 1, ‘S’: 1}, (5, 1): {‘E’: 1, ‘W’: 0, ’N’: 1, ‘S’: 0}, (1, 2): {‘E’: 0, ‘W’: 1, ’N’: 0, ‘S’: 1}, (2, 2): {‘E’: 0, ‘W’: 0, ’N’: 1, ‘S’: 1}, (3, 2): {‘E’: 1, ‘W’: 0, ’N’: 1, ‘S’: 0}, (4, 2): {‘E’: 1, ‘W’: 0, ’N’: 0, ‘S’: 1}, (5, 2): {‘E’: 0, ‘W’: 1, ’N’: 1, ‘S’: 0}, (1, 3): {‘E’: 1, ‘W’: 0, ’N’: 0, ‘S’: 1}, (2, 3): {‘E’: 0, ‘W’: 0, ’N’: 1, ‘S’: 1}, (3, 3): {‘E’: 0, ‘W’: 1, ’N’: 1, ‘S’: 0}, (4, 3): {‘E’: 1, ‘W’: 1, ’N’: 0, ‘S’: 1}, (5, 3): {‘E’: 1, ‘W’: 0, ’N’: 1, ‘S’: 0}, (1, 4): {‘E’: 1, ‘W’: 1, ’N’: 0, ‘S’: 0}, (2, 4): {‘E’: 0, ‘W’: 0, ’N’: 0, ‘S’: 1}, (3, 4): {‘E’: 0, ‘W’: 0, ’N’: 1, ‘S’: 1}, (4, 4): {‘E’: 0, ‘W’: 1, ’N’: 1, ‘S’: 0}, (5, 4): {‘E’: 1, ‘W’: 1, ’N’: 0, ‘S’: 0}, (1, 5): {‘E’: 0, ‘W’: 1, ’N’: 0, ‘S’: 1}, (2, 5): {‘E’: 0, ‘W’: 0, ’N’: 1, ‘S’: 1}, (3, 5): {‘E’: 0, ‘W’: 0, ’N’: 1, ‘S’: 1}, (4, 5): {‘E’: 0, ‘W’: 0, ’N’: 1, ‘S’: 1}, (5, 5): {‘E’: 0, ‘W’: 1, ’N’: 1, ‘S’: 0}}
从起点到目标的路径:****py amaze模块**(递归回溯器)**中使用的迷宫生成算法,不仅仅是生成一个随机的迷宫,还具有从起点到目标的路径信息。这些信息可以在迷宫的属性路径中作为字典获得。路径的关键是一个单元格,而值也是一个单元格,表示为了达到目标而从关键单元格到值单元格的移动。
在一条路径上移动代理:在创建一个迷宫和迷宫内的代理(一个或多个)后,我们可以让代理在特定的路径上移动。最好将代理移动到迷宫的路径 * *属性上。为此,我们在迷宫类中有一个名为 tracePath 的方法,它将一个字典作为输入参数。字典的关键字是代理,值是我们希望代理遵循的路径。 tracePath 方法将模拟代理在路径上移动。
运行这段代码并亲自查看模拟。
from pyamaze import maze,agentm=maze(20,20)m.CreateMaze(loopPercent=50)a=agent(m,filled=True,footprints=True)m.tracePath({a:m.path})m.run()
我们有三种方法可以指定代理要遵循的路径。
**作为字典的路径:**如上所示,路径可以是一个字典,其中的键-值对表示从键-单元格到值-单元格的移动。
**路径作为列表:**也有可能提供路径作为单元格列表。然后,代理将遵循从列表中的第一个单元格到最后一个单元格的路径。
tracePath 方法中的可选参数:
对于 tracePath 方法,还有几个可选的参数。
**击杀代理:**在代理完成路径后可以击杀代理。通过设置参数 杀死 到 真 ,代理将在完成路径后 300 毫秒后被杀死。
**移动速度:**我们可以使用参数*控制代理的移动速度,默认值为 300 毫秒。它是代理的移动步骤之间的时间延迟。
**标记一些单元格:**对于不同的演示,可能需要标记一些单元格。为此,有一个 显示标记 的选项可以设置为 真 ,如果代理经过迷宫 标记单元格 列表中出现的任何单元格都会被标记。
**不同路径上的多个代理:*也有可能在各自的路径上移动多个代理。为此,我们可以在输入字典中为 tracePath 方法提供更多的代理路径信息。将会针对字典中提供的所有代理路径对进行移动。
而且,我们可以多次使用 tracePath 方法。在这种情况下,首先第一次提供的所有代理-路径将完成它们的路径,然后第二次在 tracePath 中提供的其他代理-路径对将开始它们的移动,依此类推。
用键盘控制代理
最后,还有用键盘按键控制代理的可能性。为此,您可以使用迷宫类方法enable arrow key并作为输入参数,用箭头键提供要控制的代理。同样,可以使用 enableWASD 方法通过按键 WASD 来控制代理。
观看此视频了解更多细节。
结论:
创建这个模块的主要想法是为了方便生成任何大小和不同图案的迷宫。此外,我们可以在迷宫上放置代理并控制它们。这将有助于实现不同的迷宫搜索算法,你的重点将是搜索算法,而不是努力生成和显示迷宫。您可以实现任何迷宫搜索算法,如深度优先搜索、宽度优先搜索、最佳优先搜索、A-star 搜索、Dijakstra 算法、一些强化学习、遗传算法或任何您能想到的解决迷宫的算法。
这是使用 pyamaze 模块实现不同迷宫搜索算法的播放列表。
季节性库存计划的 Python 或-Tools 模型
如何在 SCIP 求解器中使用 Google 的 ortools python 包进行数学优化
内森·莱蒙在 Unsplash 上拍摄的照片
为什么会有季节性库存?
生产设施可能没有能力在重要季节生产季节性产品。在换季前建立额外的库存通常比购买额外的工具和空间更便宜。例如:
- 如果季节性产品是制造商业务的重要组成部分,那么在淡季安排生产可以在更长的时间内平衡资源。这使得工厂能够配备全职员工,而不是依赖季节性劳动力。
- 即使这些设施能够激增产能以满足需求,也可能导致额外的管理费用,包括加班费。将产品储存在库存中的成本可能低于这一增加的成本。
采用季节前构建方法时,有几个问题需要回答:
- 在季节开始之前,要生产的产品数量是多少?
- 假设随着时间的推移,随着生产计划的顺利进行,库存会逐渐增加,那么制造业需要在什么时候开始生产过剩的库存来为旺季储存呢?
虽然可以用纸和笔设计出一个简单的模型,但这个模型提供了一个可扩展的框架,可以在竞争能力有限的情况下为多种产品提供基础。
模型设置
在创建此多期库存模型之前,请使用 pip 安装或工具。
pip install ortools
接下来,导入包并使用数据设置模型。该模型的数据表示从 2021 年 7 月到 2022 年 6 月的月份。
- 产品需求累计至每月周期
- 对每月能生产的产品数量的[生产能力]限制
- 生产和储存成本
- 初始库存,尽管库存通常会被建模为变量
使用 python 和 ortools 的优化模型
Google 有很好的文档和对 python 和其他一些语言的介绍。该模型遵循该框架,但对多期库存模型进行了更详细的描述。
声明是大多数优化模型的第一步。我们声明要使用的求解器( SCIP )和算法用来确定最优解的决策变量。
一般来说,编写比“p”代表产量,“b”代表期初库存,“e”代表期末库存更多的描述性变量是一种好的做法,但格式化代码使代码不换行也是一种好的做法。因此,没有一种风格适合所有情况。
产量是决策变量,期初和期末库存变量受产量和需求的影响。
输出:
Number of variables = 36
接下来是约束条件。这个模型着眼于 12 个月,从 2021 年 7 月到 2022 年 6 月。库存模型的细微差别是将本期的期末库存与下一期的期初库存联系起来。其他约束条件是标准供应链约束条件,用于:
- 在不超出产能的情况下满足客户需求
- 从一个时期到下一个时期的平稳生产水平(对于该模型,0.8 的 alpha 用于将每月的变化限制在 20%以内)
输出:
Number of constraints = 70
模型的最后一部分是目标函数,以最小化总成本。总成本是生产成本和库存储存成本的总和。
输出:
Total cost = 29812
Solver wall time = 4134680
Problem solved in 40 iterations
分析结果
该模型的最优值是总成本 29812。这有意义吗?
如果将 12 个月的总需求(减去初始库存)乘以 10,预测需求的最低生产成本为 27,400,这是单位生产成本。然而,额外的限制,如最低库存水平、生产平稳性和库存持有成本会导致更高的成本。所以 29812 是合理的。
要查看解决方案,让我们格式化熊猫数据框中的数据。
输出:
这张表可以让你很容易地找到许多问题的答案。除了看到变量(期初库存、产量、期末库存),下面也很容易看到:
- 根据要求,库存没有减少到 50 件以下
- 需求得到了满足。如果由于模型的当前公式而导致需求未得到满足,则该模型将不可行。
- 最大容量在 12 月的高峰期得到了充分利用,但也可以追溯到 11 月、10 月和 9 月。
因此,在 8 月份开始生产过剩库存可能是明智的,这是为了预防一切都不尽如人意的情况。如果生产落后于 8 月份以后,就不可能赶上了。虽然这是一个很好的快速工具,用于调整和战略讨论,但对于战术或运营计划,每周和每天的视图将是必不可少的。
模型限制
这种库存计划模型有许多局限性。这里有几个例子。
- 该模型直到 12 月需求高峰时都有效。模型中使用的数据旨在帮助理解在旺季之前需要建立多少季节性库存。如您所见,在提供的数据结束时,结果将库存减少到零。由于在 12 月份达到高峰之前,该模型不用于对季节性库存准备之外的生产进行建模,因此建议只显示 12 月份的结果。
- 该模型不包括通过加班增加产能的可能性,尽管可变成本结构旨在缓解这种情况下的过渡。
- 该模型没有考虑需求的不确定性。
- 该模型不考虑库存能力、吞吐量能力或装货码头能力。这个模型只考虑了生产能力。
结论
Google 的 ortools 是一种很好的方式来扩展数学优化问题,以便与 SCIP 这样的开源解决方案一起使用。使用 python 进行优化建模还有其他选择,比如 pulp 或 pyomo。这位作者发现,根据不同的模型,哪种方法效果最好存在差异。每一个都有特别吸引人的特性,比如带有 ortools 约束编程的 NextSolution 功能。
优化建模通常用于有大量节约成本机会的复杂问题。但是随着开源选项和易用性的增长,优化也可以用于扩展和自动化更简单的问题。
Python 熊猫对 Excel 用户的介绍
从 Excel 迁移到 Python 之前您需要知道的核心概念
Bruce Hong 在 Unsplash 上拍照
Pandas 可能是用 Python 进行真实世界数据分析的最佳工具。它允许我们清理数据、争论数据、进行可视化等等。
你可以把熊猫想象成一个超级强大的微软 Excel。你可以在 Excel 中完成的大多数任务也可以在 Pandas 中完成,反之亦然。也就是说,熊猫在许多领域表现出色。
在对 Pandas 的介绍中,我们将比较 Pandas 数据框架和 Excel 电子表格,学习创建数据框架的不同方法,以及如何制作数据透视表。
注意:在学习熊猫之前,你应该知道至少了解 Python 的基础知识。如果你是 Python 的新手,看一下我做的这个指南,马上就能开始使用 Python。
**Table of Contents** 1\. [Why Excel Users Should Learn Python/Pandas](#f35d)
2\. [Pandas DataFrames & Excel Spreadsheets](#7ef2)
3\. [How to Create a Dataframe](#e7d4)
- [Creating a dataframe by reading an Excel/CSV file](#aed5)
- [Creating a dataframe with arrays](#1740)
- [Creating a dataframe with a dictionary](#dfa2)
Excel 用户为什么要学习 Python/Pandas
数据清理、数据标准化、可视化和统计分析等任务可以在 Excel 和 Pandas 上执行。也就是说,Pandas 比 Excel 有一些主要优势。仅举几个例子:
- 大小限制:Excel 可以处理大约 100 万行,而 Python 可以处理数百万行(限制在于 PC 的计算能力)
- 复杂的数据转换:Excel 中的内存密集型计算会导致工作簿崩溃。Python 可以处理复杂的计算,没有任何大问题。
- 自动化:Excel 不是为自动化任务而设计的。你可以创建一个宏或使用 VBA 来简化一些任务,但这是极限。然而,Python 可以超越这一点,提供数百个免费库。
- 跨平台能力:在 Excel 上,你可能会发现 Windows 和 macOS 中的公式不兼容。当与不将英语作为其 Microsoft Excel 版本默认语言的人共享 Excel 文件时,也会发生这种情况。相比之下,不管计算机上的操作系统或语言设置如何,Python 代码都保持不变。
在向您展示如何用 Pandas 替换 Excel(创建数据透视表、可视化等)之前,我将向您解释 Pandas 的核心概念。在整个指南中,我将提到 Excel 来提供一些示例,并将其与熊猫进行比较。Excel 是最流行的电子表格,所以一些类比将帮助你快速掌握熊猫的概念。
我们开始吧!
熊猫数据框架和 Excel 电子表格
Pandas 中的两个主要数据结构是序列和数据帧。第一个是一维数组,第二个是二维数组。
作者图片
在熊猫中,我们主要处理数据帧。熊猫数据框架相当于 Excel 电子表格。熊猫数据框架——就像 Excel 电子表格一样——有两个维度或轴。
数据帧有行和列(也称为系列)。在数据框架的顶部,您将看到列的名称,在左侧是索引。默认情况下,熊猫的索引从 0 开始。
行和列的交集称为数据值或简称为数据。我们可以存储不同类型的数据,如整数、字符串、布尔值等等。
这是一张显示美国各州人口排名的数据图表。稍后我将向您展示创建这样一个数据帧的代码,但现在让我们来分析这个数据帧。
作者图片
列名(州、人口和邮政)也称为特征,而每个行值称为观察值。我们可以说有 3 个特征和 4 个观察值。
请记住,单个列应该具有相同类型的数据。在我们的示例中,states
和postal
列只包含字符串,而 population 列只包含整数。当试图将不同的数据类型插入到一个列中时,我们可能会得到错误,所以要避免这样做。
总结一下,这就是熊猫和 Excel 之间的术语翻译。
到目前为止,我们还没有谈论太多关于空单元格的内容,但是知道在 Python 中缺失数据用NaN
表示是有好处的,它代表“不是一个数字”。只要数据帧中有空值,就会看到一个NaN
。
如何创建数据框架
创建数据帧有多种方法。我们可以通过读取 Excel/CSV 文件、使用数组以及字典来创建数据帧。
但是在创建数据框架之前,要确保已经安装了 Python 和 Pandas。如果你是 Python 的新手,你可以通过观看这个视频来安装它。
要安装熊猫,在终端或命令提示符下运行命令pip install pandas
。如果您有 Jupyter 笔记本,您可以通过运行!pip install pandas
从代码单元安装它
通过读取 Excel/CSV 文件创建数据帧
毫无疑问,这是在熊猫身上创建数据帧最简单的方法。我们只需要导入 pandas,使用 read_csv()方法,并将 Excel/CSV 文件的名称写在括号内。
让我们来读一个包含世界各国 GDP 数据的 CSV 文件(你可以在这个链接上找到这个文件)
**import pandas as pd**
df_gdp **=** pd**.**read_csv('gdp.csv')
df_gdp
在上面的代码中,我们将 pandas 重命名为“pd”这只是给熊猫命名的惯例。运行上面的代码后,您将看到下面的数据帧。
作者图片
这就是创建数据框架所需的全部内容!现在你可以通过观看我下面的视频教程开始从这个数据框架创建一个数据透视表。
用数组创建数据帧
要创建带有数组的数据帧,我们需要首先导入 Numpy。让我们导入这个库,并用随机数创建一个数组。
**import numpy as np**
data = np.array([[1, 4], [2, 5], [3, 6]])
也就是说,如果您还不习惯使用 Numpy,您可以使用列表符号创建相同的数组。在下一步创建数据帧时,结果将是相同的。
data = [[1, 4], [2, 5], [3, 6]]
为了创建一个数据帧,我们导入 pandas 并使用.Dataframe()
方法。在括号内,我们可以添加index
和columns
参数来指定名称。
**import pandas as pd**
df = pd.DataFrame(data, index=['row1', 'row2', 'row3'],
columns=['col1', 'col2'])
df
是数据帧的标准名称。如果我们打印这个df
对象,我们得到如下结果:
作者图片
用字典创建数据帧
我们也可以从字典中创建一个数据框架。这是我最喜欢的选择,因为字典可以让我们正确地组织数据。您可能还记得,字典由一个键和值组成。我们可以将列表设置为数据值,将键设置为列名。
让我们在使用字典之前创建一个人口数据框架。首先,我们创建两个列表:州和人口。
# data used for the example (stored in lists)
states = ["California", "Texas", "Florida", "New York"]
population = [39613493, 29730311, 21944577, 19299981]
现在我们创建一个字典,将字符串States
和Population
设置为键,将之前创建的列表设置为数据值。
# Storing lists within a dictionary
dict_states = {'States': states, 'Population': population}
一旦创建了字典,创建 dataframe 就像使用.Dataframe()
方法一样简单,但是这次我们不需要指定列参数,因为它已经在键中指定了。
df_population = pd.DataFrame(dict_states)
如果你打印df_population
,你会得到这个数据帧:
作者图片
https://frankandrade.ck.page/bd063ff2d3加入我的电子邮件列表,与 3000 多人一起获取我在所有教程中使用的 Python for Data Science 备忘单
如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑报名成为一名媒体成员。每月 5 美元,让您可以无限制地访问数以千计的 Python 指南和数据科学文章。如果你使用我的链接注册,我会赚一小笔佣金,不需要你额外付费。
**https://frank-andrade.medium.com/membership **
用几行代码实现数据处理、分析和 ML 自动化的 Python 工具
dabl 图书馆基本指南
图片来自皮克斯拜的拉胡尔·潘迪特
数据科学模型开发管道涉及各种组件,包括数据收集、数据处理、探索性数据分析、建模和部署。在训练机器学习或深度学习模型之前,必须清理或处理数据集,并使其适合训练。处理缺失记录、移除冗余要素和要素分析等过程是数据处理组件的一部分。
通常,这些过程是重复的,并且涉及大部分的模型开发工作时间。各种开源的 Auto-ML 库在几行 Python 代码中实现了整个流水线的自动化,但是它们中的大多数表现得像一个黑盒,并且没有给出关于它们如何处理数据集的直觉。
为了克服这个问题,我们有一个名为 dabl 的开源 Python 库——数据分析基线库,它可以自动化机器学习模型开发管道的大部分部分。本文将介绍 dabl 包的实际实现,包括数据预处理、特性可视化和分析,然后是建模。
dabl:
dabl 是一个 数据分析基线库 ,它使监督机器学习建模对于初学者或没有数据科学知识的人来说更加容易和容易。dabl 的灵感来自 Scikit-learn 库,它试图通过减少样板任务和自动化组件来民主化机器学习建模。
dabl 库包括各种特性,使得用几行 Python 代码处理、分析和建模数据变得更加容易。
开始使用:
dabl 可以从 PyPI 安装,使用
**pip install dabl**
我们将使用从 Kaggle 下载的 Titanic 数据集来实现这个库。
(1.)数据预处理:
dabl 用几行 Python 代码自动化了数据预处理管道。dabl 执行的预处理步骤包括识别缺失值、移除冗余特征以及了解特征的数据类型,以便进一步执行特征工程。
dabl 检测到的特征类型列表包括:
***The list of detected feature types by dabl includes:***
1\. **continuous
2\. categorical
3\. date
4\. Dirty_float
5\. Low_card_int
6\. free_string
7\. Useless**
dabl 使用一行 Python 代码将所有数据集要素自动分类为上述数据类型。
**df_clean = dabl.clean(df, verbose=1)**
(按作者分类的图片),每个功能的自动检测数据类型
原始泰坦尼克号数据集有 12 个特征,它们被 dabl 自动分类为上述数据类型,以进行进一步的特征工程。dabl 还提供了根据需求改变任何特性的数据类型的能力。
**db_clean = dabl.clean(db, type_hints={"Cabin": "categorical"})**
用户可以使用**detect_types()**
功能查看每个特征的指定数据类型。
(图片由作者提供),自动检测每个要素映射的数据类型
(2.)探索性数据分析:
EDA 是数据科学模型开发生命周期的重要组成部分。Seaborn、Matplotlib 等是执行各种分析以更好地理解数据集的流行库。dabl 使 EDA 变得非常简单,节省了工作时间。
**dabl.plot(df_clean, target_col="Survived")**
dabl 中的**plot()**
功能可以通过绘制各种图来实现可视化,包括:
- 目标分布条形图
- 散点对图
- 线性判别分析
dabl 自动对数据集执行 PCA,并显示数据集中所有特征的判别 PCA 图。它还显示通过应用 PCA 保留的差异。
(3.)造型:
dabl 通过在训练数据上训练各种基线机器学习算法来加速建模工作流,并返回性能最佳的模型。dabl 做出简单的假设,并为基线模型生成指标。
使用 dabl 中的**SimpleClassifier()**
函数,一行代码就可以完成建模。
(图片由作者提供),使用 dabl 进行基线建模的性能指标
dabl 几乎很快就返回了最佳模型(决策树分类器)。dabl 是最近开发的库,提供了模型训练的基本方法。
结论:
Dabl 是一个方便的工具,使监督机器学习更加容易和快速。它用几行 Python 代码简化了数据清理、要素可视化和开发基线模型。dabl 是最近开发的库,需要很多改进,不推荐用于生产。
参考资料:
[1]dabl GitHub:https://github.com/amueller/dabl
感谢您的阅读
解决熄灯问题的量子变量
“量子熄灯求解器”——解决组合问题的独特方法
图 1:https://pixabay.com/images/id-567757/
我们正在见证“量子计算”这个时髦词汇的空前激增。这种炒作驱动的好奇心始于 2019 年谷歌在量子世界创造历史之时。它声称并展示了基于超导架构的 53 量子位量子处理器 Sycamore 的量子优势。这是量子计算机第一次胜过经典计算机。从那天起,这个领域见证了算法优化、硬件增强和基于光子学的体系结构的演变的巨大发展。
那么什么是量子计算呢?
量子计算是对量子设备进行编程,使得不需要的状态相消干涉,而需要的状态相长干涉,给出它们作为输出。为了达到这个目的,三个不可或缺的性质被用来操控量子位元的状态。这些就是叠加,纠缠,干涉。
- 量子叠加:量子叠加是量子力学中的一个基本性质。在经典力学中,波可以表示为多个频率的叠加。同样,在量子力学中,叠加态可以代表所有不同量子态的线性组合。
- 量子纠缠:两个或两个以上的量子比特在不能表示为独立状态时纠缠在一起。当量子比特纠缠在一起时,它们之间存在一个特殊的键。一个状态的结果直接取决于另一个状态的测量。当纠缠对中的一个量子位被测量时,它会导致另一个量子位瞬间坍缩到可以根据第一个量子位的状态 100%确定预测的状态。即使相隔更远的距离,他们也遵循这一原则。这个想法遭到了有史以来最杰出的科学家的强烈批评。爱因斯坦也厌恶这个想法,表达了一句警句“幽灵般的超距作用”。他著名的 EPR 悖论也完全否定了这种现象的存在。在那个时期,这个概念只是理论上的,没有任何实际证明。然而,今天量子纠缠是一个被精确证实的和公认的概念。
- 量子干涉:量子态可以经历类似经典波的干涉。当两个或两个以上的波同相时,它们的振幅增加,而当它们相差 180 度时,它们的振幅相互抵消;因此,量子计算就是设计一种算法,使得所有不太可能的解的振幅相消干涉,而正确的解相长干涉,从而给出正确的答案。
这三个性质构成了任何量子算法不可或缺的一部分。
图 IBM 量子计算系统内部。鸣谢:IBM(来源https://www . Flickr . com/photos/IBM _ research _ Zurich/50252942522/size/k/)
量子算法解决了大量的问题,如蛋白质折叠,药物开发,组合游戏,如数独,国际象棋等等。熄灯就是这种可以用量子计算机解决的组合问题之一。本文描述并阐述了算法,称为“量子熄灯解算器”,它利用量子现象来解决量子设备上的熄灯问题。它成功地将问题转化到量子域中,并提供了问题的有效解决方案。它利用了一个反直觉的概念称为格罗弗算法,使用叠加和振幅放大技巧有效地解决了这个问题。但在进入算法之前,让我们先熟悉一下熄灯问题。
熄灯
熄灯问题是一个经典的组合问题,由 Tiger Electronics 于 1995 年开发。它由一块板组成,灯固定在 n*m 网格的方形瓷砖上。在开始位置,随机的灯被打开,我们的最终目标是关闭网格上的所有灯。这个游戏的规则是:
- 按下任何一个方块将会切换该方块上的灯以及相邻方块上的灯。这里,相邻的瓦片指的是顶部、底部、左侧、右侧的瓦片。对角瓷砖不被视为邻居。此外,切换意味着改变灯光的状态,而不考虑当前状态。例如,如果灯是开着的,它将被关闭,反之亦然。下图显示了按下图块(3,2)时的电路板配置。
- 按两次按钮相当于根本不按。因此,对于任何给定的配置,我们只需要考虑每个按钮按下不超过一次的解决方案。
- 解决方案状态与路径无关。因此,压瓷砖的顺序并不重要。
图 3:按压(3,2)瓷砖后的电路板配置
对上述情况的解决方案概括如下。瓷砖中心的圆点表示解决方案(即待压瓷砖)。
图 4:图 3 中问题的解决方案
习惯了问题之后,我们再推进到实际的算法。我会尽量把数学放在一边,集中精力解决熄灯问题。
量子熄灯解算器
该算法使用 IBMs Qiskit 编程语言。IBMQ 有各种各样的量子设备可以在他们的云上使用。唯一的问题是,量子计算机的最大可能量子位是 15。这些量子设备不能用于执行该算法,因为该算法期望 26 个量子位和 9 个经典位来求解 33 板配置。因此,该算法在一个名为 ibmq_qasm_simulator(版本 0.1.547)的量子模拟器上执行。它最多支持 32 个量子位。因此,使用建议的算法,我们可以使用模拟器解决 33 板配置问题。对于 4*4 板配置,根据该算法需要 40 个量子位和 16 个经典位,这远远超出了 Qasm 模拟器的能力。
最近,IBMQ 又向云添加了一些量子设备模拟器,即稳定器模拟器和扩展稳定器模拟器,最大量子位容量可达 5000 量子位。但是,如果算法由具有许多非 Clifford 门的较小电路组成,那么状态向量方法可能会比扩展稳定器表现得更好。由于所提出的算法包含许多非 Clifford 门,当考虑计算精度时,扩展的模拟器可能不是更好的选择。虽然,在扩展模拟器上解算法还是值得一试的。更大的板配置可以使用更多的量子位来解决。因此,我们将暂时坚持使用 Qasm 模拟器来解决 3*3 板排列的问题。
在深入研究该算法之前,让我们先回顾一下 Grovers 算法如何帮助找到问题的正确解决方案的基本思想。如果你不熟悉 Grovers 算法或者幅度放大和 oracle 函数,强烈建议你去过一次。
在经典算法中,我们一次一个状态地搜索解空间,当我们遇到正确的状态时,我们输出解。有很多不同的技术可以达到这种最终状态。与经典算法相反,Grover 算法使用称为 Hadamard 门的叠加门同时搜索所有可能的输出状态。正确的门标有相位翻转,这意味着将负号加到正确状态的幅度上。由于所有的状态都是同时访问的,所以到这个阶段为止算法的复杂度是 O(1)。现在,你会质疑为什么此时不输出标记的状态?我们还不能输出标记的状态。如果我们测量这一刻的量子态,会得到任意一个态作为输出。这是因为某个状态的输出概率是振幅的平方。例如,考虑 1/2 和-1/2 是两个状态的振幅。1/2 的平方等于-1/2。因此,即使期望状态具有负振幅,两个状态也具有相同的输出概率。由于这个原因,绝对幅度值需要增加,而不仅仅是符号翻转。我们的下一个任务是增加期望状态的幅度,减少不期望状态的幅度。这是通过振幅放大技巧,利用甲骨文和扩散电路实现的。完整的电路在下面的 GitHub 链接上。
用于解决该问题的算法框图如下所述。
图 5:解决熄灯问题的框图
该算法主要分为 3 个阶段:
- 初始化块:
该块接受用户输入,即 33 问题中所有 9 个区块的初始配置。用户以 0 和 1 的字符串的形式提供该输入,其中 0 表示灯关闭,1 表示灯打开。在解释算法的同时,让我们同时解决一个 33 的问题,以便更好地理解。作为算法输入的字符串是 101010101。该字符串表示如下所示的板配置,
图 6:算法的输入
在上图中,黄色表示开启,灰色表示关闭状态。除了为算法提供初始棋盘条件,所有需要的量子位和经典位都被初始化。总共 26 个量子位和 9 个经典位用于计算。在这 26 个量子位中,9 个用于接受用户输入作为板条件,在框图中显示为“初始板条件”。其他 9 个量子位用‘H’表示的叠加态初始化。这意味着阿达玛门应用于这些量子位。这将量子位设置为叠加态。这一点的重要性将在下一阶段解释。被称为‘Oracle-qubit’的单量子位被声明,它从所有可能的状态中标记出正确的状态。剩余的 7 个量子位(在框图中未示出)是用于辅助目的的临时量子位。
2.甲骨文和扩散函数;
在这个模块中有两个关键的部分,它们是,预言电路和扩散电路。Oracle circuit 在给定的输入状态下同时执行所有可能的操作(即执行所有可能的瓷砖翻转)。这是可能的,因为在 9 个量子位上应用了哈达玛门。检查所有这些翻转的输出是很重要的。让所有灯熄灭的那组动作是我们解决问题的方法。检查这种状态,然后使用 Oracle 量子位标记负振幅。如上所述,在这一点上,我们不能测量叠加态。因此需要振幅放大。这是在扩散回路中完成的。
在扩散电路中,被标记状态的幅度被放大,从而减小了其他不期望状态的幅度。在这篇文章中,我不打算探究他的放大是如何工作的。这本身可能就是一个完整的主题。
这两个电路结合起来就形成了这个模块。整个块重复一定的次数(在我们的例子中,17 次)。这是我们想要的 3*3 板配置的最佳可能数量。这个数字取决于用来表示解空间的量子位的数量。在我们的例子中,它是 9 个量子位。因此,要执行的迭代次数计算如下:
π/4 * √2⁹ ∼ 17.27 ∼ 17
每当我们重复这个方块时,振幅就会增加一点。最后,在 17 次迭代之后,与其他状态相比,期望输出的幅度急剧增加。因此,如果我们在这个阶段测量叠加,我们将以非常高的概率(99.95%)得到想要的状态。下图显示了初始化模块、Oracle 和扩散电路的电路。
图 7:左边是初始化电路,中间表示 Oracle 函数,右边方框表示扩散。
3.测量:
该模块测量输出量子位,并将该值复制到 9 个经典位进行可视化。
与确定性的经典计算不同,量子计算本质上是概率性的。因此,强烈建议对大于 100 的镜头执行此算法。Shots 是运行时给量子器件的参数,表示电路执行了多少次。例如,如果 shots=1000,则该电路被执行 1000 次,并且输出被记录该次数。为了执行这个算法,我已经使用了 8188 个镜头。执行该算法后的结果如下图所示。
图 8:8188 个镜头的输出用直方图表示
可以看出,8188 个镜头中,8184 次正确状态是输出(111111111)。但是有 4 次,输出不是要求的状态。因此,该算法在 99.95%的情况下输出正确的状态。
结果和讨论
- 这种搜索算法将搜索解空间的时间复杂度从 O(N)降低到 O(√N)。
- 由于量子世界是概率性的,大多数时候,确定性的答案并不总是可能的。因此,该算法在 99.95 %的情况下输出正确的状态。
量子电路的完整代码可在 GitHub 上获得。
参考文献
- https://qi skit . org/documentation/locale/FR _ FR/tutorials/simulators/6 _ extended _ stabilizer _ tutorial . html
- 卡米洛·萨帕塔,肖扬,“格罗弗的算法”,苏黎世联邦理工学院演讲[在线],数据:2016 年 8 月
- L.K. Grover,“用于数据库搜索的快速量子力学算法”,第 28 届 ACM 计算理论年会论文集,1996 年,arXiv:quant-ph/9605043v3
- IBM Quantum,“使用 Qiskit 学习量子计算:Grover 的算法”[在线]可用:https://qiskit.org/textbook/ch-algorithms/grover.html
- A.B. Mutiara,R.Refianti,“Grover 算法量子搜索在经典计算机中的模拟”,(IJCSIS)《国际计算机科学与信息安全杂志》,第 8 卷第 9 期,日期:2010 年 12 月
- “维基百科:熄灯(游戏)”,2021 年 1 月,[在线]可用:https://en。wikipedia.org/wiki/Lights_Out_(游戏)
一个价值一千个模型的查询
实践教程
尝试从结构化查询搜索中构建分类器
数据科学家面临的最大问题是什么?
为了回答这个问题,我们可能会争论一整天。虽然有很多候选,但对我来说最重要的是访问新用例的标记数据。
举个例子,一个经理打电话来说:
“我们需要能够自动识别收到的邮件是应该转到应收帐款部门还是客户服务部,这样我们就可以降低管理成本。”
数据科学家:
“我能拿到他们放在每个桶里的邮件吗?”
经理:
“没有”
数据科学家:
*smh
几乎所有的数据科学家都以某种形式面临这个问题。事实上,这个问题如此之大,以至于整个行业都在致力于帮助数据科学家解决这个问题。最近的一份报告估计该行业的收入在“13.077 亿美元”的范围内。是的,再读一遍那个数字。不是大,是巨。
这个行业如此之大,部分是因为人类很昂贵。因此,人工标记数据也很昂贵。当然,公司已经尝试使用免费劳动力来解决这个“昂贵的人力”问题的某些方面。不,我不是在说奴役人民。我在这里指的是验证码。如果你没有意识到,验证码不仅仅是用于安全,它们也是公司让人们免费标记他们数据的一种方式。
但是,如果有一种方法,我们可以提供一个更自动化的方法来标记数据呢?如果我们可以使用现有的数据和为我们提供这些数据的智能作为代理来创建标签,然后用于训练模型,会怎么样?
在本文中,我尝试了一种自动标记数据的方法,来训练一个可以用来对新数据进行评分的模型。剧透警报,使用 Google I 背后的智能开发结构化查询来获取训练数据和训练标签。一个查询抵得上一千个模型吗?让我们来了解一下!
问题空间
在这次演示中,我们将尝试对文本进行分类。更具体地说,我们希望能够对网站文本进行分类,以识别公司网站是否涵盖感兴趣的特定主题。
假设你有一个客户对更好地识别企业社会责任项目感兴趣。目标是确定公司可能在其网站上描述 CSR 计划的地方。问题是,尽管大多数财富 500 强公司确实使用某种类型的网址来提供有关其 CSR 计划的信息,但细节却很难确定。
以微软为例。他们的企业社会责任网站通常被称为“……企业责任”但进一步审查后,我们看到他们的登录页面链接到几个不同的,更详细的计划。现在想象一下为财富 500 强的所有 500 家公司做这件事。可能需要一分钟。
为了节省一些时间并测试出解决这个问题的数据科学解决方案,我利用谷歌来捕获训练数据,并将它们分配给标签,这些标签可用于训练一个模型来对新文本进行评分,以进一步对该网站文本的内容进行分类。以下是该解决方案的简要概述:
1.从结构化查询中获取前 N 名的 Google 页面结果
2.从每个登录页面抓取文本数据
3.从查询中为每个登录页面创建分类标签
4.训练多类分类模型
5.保存模型并在财富 500 强公司的页面上评分,以确定具体的 CSR 计划
6.可视化结果
从结构化查询构建标记数据
为了测试我们的解决方案,我们首先需要构建训练数据,并将它们与标签相关联。在这种情况下,我们对作为标签的 CSR 类别感兴趣。快速的网络搜索和这篇研究论文给了我一些寻找不同潜在类别的想法。
作者图片
这里,我们重点关注以下 CSR 类型,作为我们数据的标签:
人权
使用条件
环境
腐败
披露信息
公司治理
消费者利益
性别平等
职业融合
赋税
计算环境
Windows 10 操作系统
Python 3.7
图书馆
用 Carbon.now 创建的代码图像
密码
第一组代码使用了 python 中可用的 googlesearch-python 库。我们从 googlesearch-python 库中导入“search ”,并构建一个传递查询字符串并返回前 50 个结果的函数。请注意,这 50 个结果可以根据您的需要进行调整,但该函数的默认设置是返回前 50 个 Google 搜索链接。
import pandas as pd
import numpy as np
from googlesearch import searchdef Gsearch(query, num_res = 50):
results = []
for i in search(query=query,tld=’co.in’,lang=’en’,num=num_res,stop=num_res,pause=5):
results.append(i)
return results
在定义了我们的搜索函数之后,我们开发代码来迭代每个 CSR 类型以构造一个查询,我们将这个查询传递给 googlesearch API,返回一个包含 CSR 标签和前 50 个结果列表的元组。
#develop queriescsr = [‘human rights’,’working conditions’,’the environment’,’corruption’,
‘disclosing information’,’corporate governance’,’consumer interests’,
‘gender equality’,’occupational integration’,’taxes’]results = [(c, Gsearch(‘corporate responsibility and ‘+c)) for c in csr]
内脏检查
这是一般的思考过程,因为 Google 擅长返回与查询相关的信息,通过传递一个特定的和结构良好的查询,我们应该能够返回与我们的查询所代表的标签更具体相关的数据。通过提供一些不同的查询,我们应该能够训练一个模型,该模型能够识别语言数据何时更好地表示一个类而不是另一个类。
返回代码
一旦我们的搜索代码完成了,下一步就是把所有的东西放入熊猫的数据框架中,以便可视化我们到目前为止的结果。有用的“explode”方法允许我们将每个链接结果放到数据帧中它自己的行中。
但是链接本身并不足以训练一个模型。下一步是访问每个链接,从登录页面中抓取文本。为了完成下一步,我们使用 Python 中的“requests”和“bs4”(beautiful soup)库(注意:这一部分可能需要一段时间)。
df = pd.DataFrame(results, columns=[‘label’,’links’]).explode(‘links’)#get website text
import requests
from bs4 import BeautifulSoup
import redef website_text(URL):
#USER_AGENT = “Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:65.0) Gecko/20100101 Firefox/65.0”
#headers = {“user-agent” : USER_AGENT}
headers = {‘User-Agent’: ‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36’,’Accept-Encoding’: ‘gzip, deflate, br’,’Accept-Language’: ‘en-US,en;q=0.9,hi;q=0.8’} try:
resp = requests.get(URL, headers=headers)
if resp.status_code == 200:
soup = BeautifulSoup(resp.content, “html.parser”)
for script in soup([“script”, “style”]):
script.extract()
text = soup.get_text()
lines = (line for line in text.splitlines())
chunks = (phrase for line in lines for phrase in line.split(“ “))
text = ‘ \n’.join(chunk for chunk in chunks if chunk)
clean_output = re.sub(r’<.+?>’, ‘ ‘, text)
else:
clean_output = ‘failed to retreive text’
except:
clean_output = ‘failed to retreive text’
return clean_outputdf[‘website_text’] = df[‘links’].apply(website_text)
df = df.loc[df[‘website_text’] != ‘failed to retreive text’]
现在我们有了一个包含标签、链接和这些链接的文本的数据框架。下一步是获得网站文本的“肉”,以提高我们捕捉有意义的语言数据的机会。此外,我们还希望快速清理文本数据,以增加至少一个基本的标准化级别。以下代码使用“nltk”库对句子进行标记化,删除任何少于 7 个单词的句子,并执行一些轻量级清理(例如,小写、删除停用词、删除字符/数字)。
#clean the website text
import nltk
from nltk.corpus import stopwords
stop_words = set(stopwords.words(‘english’))def clean_sentences(text):
sent_text = nltk.sent_tokenize(text)
sentences = [s for s in sent_text if len(s.split()) > 6]
if sentences:
sentences = ‘ ‘.join(sentences)
low = sentences.lower()
no_num = re.sub(r’\d+’, ‘’, low)
no_char = re.sub(r’[\W_]+’, ‘ ‘, no_num)
tokens = nltk.word_tokenize(no_char)
stop_words = set(stopwords.words(‘english’))
no_stop = [i for i in tokens if not i in stop_words]
return no_stopdf[‘clean_text’] = df[‘website_text’].apply(clean_sentences)
df = df.dropna(subset=[‘clean_text’])
快到了。
现在我们需要训练一个模型。在这种情况下,我们将利用流行的“scikit-learn”库来训练一个简单的文本分类模型。由于我们有一个多类输出问题,我们将利用随机森林模型。
这里,我们遵循使用语言数据进行模型训练的标准步骤;使用 term-frequency-inverse-document-frequency(tfi df)过程构建将单词映射到整数的 vocab,将数据分成训练和测试数据集,将模型拟合到训练数据,并检查测试数据的准确性。
#set up data for ML
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifierdef dummy_fun(doc):
return doctfidf = TfidfVectorizer(max_features=600, tokenizer = dummy_fun,
preprocessor=dummy_fun, token_pattern=None,
ngram_range=(1,2))X = tfidf.fit_transform(df[‘clean_text’])
y = df[‘label’]X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.33, random_state=42)clf = RandomForestClassifier(max_depth=3, random_state=0)
clf.fit(X_train, y_train)y_pred_test = clf.predict(x_test)
print('Accuracy: '+str(accuracy_score(y_pred_test, y_test))
>>> 'Accuracy: 0.60'
我们表现如何?
准确性不好,但这只是冰山一角。我们可以采取许多额外的步骤来进一步优化我们的方法并提高模型性能。这里只是将这个解决方案提升到下一个级别的一些附加想法;
使用更精确查询语言,
包括单词嵌入作为特征,
对词类应用更详细的清理过程,
尝试不同的模型类型,
打开一瓶威士忌,站在我们的头上,让 60%的准确率看起来像 90%的准确率。
要获得更详细的信息,我们可以利用 scikit-learn 提供的分类报告,该报告有助于我们更好地评估我们的模型在哪些方面表现良好,在哪些方面表现不佳。下面是在对整个数据集(训练+测试)的模型进行评分后,我们如何将报告放入一个易于阅读或保存的 Pandas 数据框架中:
y_pred = clf.predict(X)
report = classification_report(y, y_pred, output_dict=True)
r = pd.DataFrame(report).transpose()
我们当前解决方案的细节显示,我们在识别人权方面有相当好的表现,但在工作条件方面不太好。
作者图片
考虑到 60%的总体准确率并不可怕,我们采取下一步措施,在新的网站实例上对模型进行评分,以对财富 500 强公司的 CSR 计划进行分类。为了做到这一点,我们拉出财富 500 强的登陆页面,使用与上面类似的代码,我们抓取每个链接,访问这些链接,并拉出相关的文本。这有助于为我们的模型创建数据集,数据集的设置方式与我们的训练数据的设置方式相同。
一旦 dataframe 设置了公司名称列、链接列和网站文本列,我就可以用这个模型给每个网站打分了。为了实现评分,我将数据预处理和模型评分打包到一个简单方便的函数中,该函数输出预测的标签以及与该标签相关联的概率。
def score_csr_model(text, tfidf_model, model):
clean = clean_sentences(text)
tfidf = tfidf_model.transform([clean])
pred = model.predict(tfidf)
pred = pred[0]
pred_proba = np.amax(model.predict_proba(tfidf))
return pred, pred_probadf[‘predicted’] = df[‘website_text’].apply(score_csr_model,
args = [tfidf,clf])
在最后一步,我根据每类公司的平均预测概率,从公司样本中构建一个热图,以估计每家公司包含与每项 CSR 计划相关的信息的程度。为了生成热图,我首先需要根据公司名称和我们模型中该页面上确定的 CSR 计划类型对数据进行分组。作为此代码的一部分,我对模型中每个标签的预测概率进行了平均。
import seaborn
import matplotlib.pyplot as plt#unpack predicted column into two columns
df[[‘predicted’,’proba’]] = pd.DataFrame(df[‘predicted’].tolist(),index=df.index).drop(columns = [‘predicted’])dfsub = df[['label','predicted','proba']].groupby(['label','predicted'])['proba'].mean().reset_index()
dfsub= dfsub.pivot(index='label', columns='predicted', values='proba')figure, ax = plt.subplots(figsize=(10,10))
ax.xaxis.tick_top() # x axis on top
ax.xaxis.set_label_position('top')
ax.set_xticklabels(list(dfsub.columns), size=14)
ax.set_yticklabels(list(dfsub.index.values), size=14)
#sns.set(font_scale=5)
svm = sns.heatmap(dfsub, mask=(df_sub==0), center=0, cmap='Greens', cbar=False,
xticklabels=True, yticklabels=True, linewidths=.1,ax=ax)figure = svm.get_figure()figure.savefig('path/to/save/csr_svm_conf.png', orientation='landscape',
transparent=True,format='png', pad_inches=.1)
调查结果中最明显的一点是,在消费者利益和工作条件方面,覆盖面似乎存在很大差距。在模型中,我们预测工作条件和消费者兴趣的准确性都很低,所以我们可能只是看到了这里表现的模型性能差。然而,有趣的是,我们的模型在识别人权倡议方面表现更好,但似乎更少的公司在其 CSR 沟通中关注人权倡议。
作者图片
尽管只是一个演示,这里收集和分析的数据可能有一些有价值的用途。
对于企业来说,也许你想与这些大公司中的一家合作,来领导与 CSR 类别之一相关的推广工作或产品。了解这些公司如何与这些努力保持一致,可以用来帮助关注最合适的人选。
对于消费者来说,知道哪些公司符合你的价值观有助于我们知道我们想要支持哪些公司并向其购买产品。
对于股东来说,投资于具有强大企业社会责任的盈利性公司的资金需要知道这些优先事项得到了有效的沟通。
对于监管者来说,了解企业社会责任倡议在不同行业的差异可能有助于支持那些需要更多关注企业社会责任倡议的行业的政策变化。
结论
构建包含模型标签的训练数据是一项挑战,自该行业诞生以来一直困扰着数据科学家。在这个演示中,我使用 Google 搜索查询来帮助建立训练数据和相关联的标签,而不需要人工干预。
无论采用哪种方法,这篇文章都代表了一种尝试为分类任务自动标记有价值的训练数据的可能方法。
比如参与学习更多关于数据科学、职业发展或糟糕的商业决策的知识?加入我。