TowardsDataScience 博客中文翻译 2020(三百零九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

数据科学项目的设计和结构

原文:https://towardsdatascience.com/design-and-the-structure-of-data-science-projects-c1bc5f745d17?source=collection_archive---------19-----------------------

作为数据科学家,我们必须学会处理不确定性。我们可以借用其他学科的技术来帮助我们做到这一点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

信不信由你,这些不是设计师的首选工具。

与和你完全不同的人一起工作会是一次非常有益的经历。如果你幸运的话,你最终会改变对世界的看法,并因此成为一个更好的人。对我来说,这种改变发生在第一次与 设计师 合作的时候。

“设计师”,我听到你语无伦次!“他们对数据科学项目了解多少?他们不就是给东西上色吗?”

部分原因是,当他们大三刚开始的时候。然而,好的人会设法把他们的蜡笔留在线内**【1】**。在这一点上,他们被提升为高级设计师,必须做一大堆我们称之为 真正的设计 的东西。我认为这种 真实设计 的过程在数据科学项目中非常有用。

我保证,过一会儿我会回到这个设计过程。然而,独立于实现它们的人的流程是我最讨厌的事情之一。对不起 Scrum/敏捷/prince 2/看板的人。首先,让我们思考一下这种心态,它来自哪里,以及它与科学家和工程师通常接受的培训方式有何不同。

设计思维的根源

“一个物体是由其性质定义的。为了使它正常工作,我们必须首先研究它的性质。为了使它完美地服务于其目的,它必须以实际的方式履行其职能。” 瓦尔特·格罗皮乌斯,包豪斯的创始人

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

包豪斯思维无处不在。

包豪斯是现代设计的发源地,在德国蓬勃发展,直到邪恶的纳粹将其关闭。历史上积累的垃圾将被扔掉,物品将按照其本质核心进行制作。还记得米开朗基罗对教皇说,为了创作他的雕塑杰作,“他只是移走了所有不是大卫的东西”吗?这是第一次艺术感受被应用到日常生活中。从这里开始的智力思维延伸到了 iPhone 的设计。【2】

我们已经可以看到我所说的不同的思考方式。作为科学家或工程师,我们被训练来提供解决方案。通常在计划中,我们会抓住一个问题并立即开始解决它。但是考虑一下格罗皮乌斯的引用。设计师要做的第一件事就是理解这个东西的功能和目的。他们最终会找出问题所在,然后才知道如何解决。

现在,您参与过多少数据科学项目,因为解决了一个并不符合客户需求的问题而放弃了大量工作?有办法避免这种情况吗?在这之前,我们必须离开关于“事物本质”的神秘陈述,转而…

实用主义在美国

在 30 年代,设计运动跨越了大西洋——那是在美国建墙之前的日子。瓦尔特·格罗皮乌斯最终成为了哈佛大学的教授。一个新的包豪斯在芝加哥开张了。

在美国,围绕设计的思考变得不那么神秘了,设计师们开始制作对我们其他人有用的工具包。像“设计科学”这样的短语开始被使用。斯坦福大学的 D-School 成立了,他们围绕自己创造的设计流程,推出了一家咨询公司 IDEO。我发现这个过程在数据科学项目中非常有用。设计师们非常习惯走进一个定义不清的项目,拼命想弄清楚这些人到底想要什么,然后想出一些让他们的客户满意的方法。

听起来熟悉吗?“就给我数据科学。它必须有效,其他所有人都在这么做……”

数据科学和设计过程

我在设计师的工具箱里找到的最有用的东西,是英国设计委员会称之为双钻石的东西。据我所知,这似乎与斯坦福大学 D-School 的设计过程密切相关。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来自英国设计协会

时间在左右轴上。上下轴,即钻石的高度,应该代表你对这个项目的确定性。因此,当你从左向右移动时(即随着时间的推移),你会逐渐变得不确定,然后变得更确定,然后变得不确定,最后在项目结束时又变得确定。运气好的话。

基本思想是,在第一个菱形中,你要找出问题,在第二个菱形中,你要找出答案。即使在这个高层次上,我们也能看到设计师的训练方式和我作为科学家的训练方式之间的差异。首先,不确定性被认为是这个过程中不可避免和令人满意的一部分!乏味的中年男人——我可以这么说,我就是一个——对事情发表意见是坚决不鼓励的。其次,我们的科学训练是这样的,“这里有一个假设,现在做所有这些详细而仔细的工作,最好是用复杂而巧妙的方法,并找出假设是否正确”。大部分时间都花在了细致和仔细的工作上,因为这是理性和聪明的。假设本身被认为是凭空变出来的,好像我们都为灵感过程的不合理性感到尴尬。另一方面,设计师已经仔细考虑了这个过程,虽然灵感不能保证,但你可以积累对你有利的机会。

记住这一点,让我们来看看这个过程的四个阶段。

1。发现

凭借在工业界和学术界 20 年的数据科学经验,我可以有把握地说,对于一个被培养成科学家的人来说,这是最令人沮丧的阶段。然而,这也是最必要的,尤其是在处理许多不同的利益时。每个人,我是说每个人,都会对这个项目有看法。这一阶段的想法是梳理出问题的统一“本质”——还记得包豪斯吗?你将会参加很多会议。很多人都会议论纷纷。如果你是某种类型的人,你可能会对人们不同的方向感到不知所措和困惑。如果你是另一种人,你可能会觉得其他人都是白痴,应该马上停止说话*。如果你是第一种人,那就不用担心。如果你是第二个,那么冷静下来。记住这是钻石的加宽阶段。我们在这里是为了得到关于问题是什么的许多观点,而那些观点将会是矛盾的和不完整的,因为,嗯…人类。*

2。定义

但是你不能永远困惑下去。在这个过程中的某个时刻,应该开始形成一系列的想法。你应该能够看到一些你可以做的有用的事情。关于这一点,你应该开始感到兴奋,因为你开始看到(a)这些人想从你这里得到什么,以及(b)你可以帮助他们的所有很酷的数据科学。这太棒了。请记住,回到您的最终用户身边,检查您认为他们真正想要的是什么。如果你正确地完成了第一步,应该没问题。对吗?

3。开发

没错。现在你已经弄清楚了你应该做什么,是时候开始着手做了。厉害!在这一点上,你可能会感觉如释重负。然而,你也会撞向现实。你先试的方法行不通。会有你没有想到的外在因素。数据会被弄乱(总是这样)。你可能开始认为这个白痴可能不是阶段 1 中的任何人。那个白痴可能住得离家近一点。幸运的是,这是你的训练和经验发挥作用的地方。相信我,你会没事的。

4。交付

嗬哼。这一期限即将到来。如果运气好的话,一些清晰的东西将会形成,并且你已经解决了这个问题——至少在某种程度上你的解决方案足够好。你可能只是希望这一切早点发生。你可能也有一个满脑子想做的很酷的事情。小心点。这是个陷阱。先找出可行的解决方案。

这就是英国设计委员会的四个阶段。作为一名数据科学家,我会增加第五个。

5。展开

现在只需“直播”您的解决方案。

哈哈哈哈哈哈哈。

在地球上,你的解决方案可能是一堆 SQL、python 脚本和 Jupyter 笔记本,用信念粘在一起。现在,你需要努力将所有这些变成类似专业产品的东西。在这个阶段,你现在会 100%确定地意识到那个白痴实际上就是你,你会乞求这一切结束。我打赌你现在希望使用源代码控制,嗯?

我对此有点厚脸皮的原因是,“部署”是一个至少和其他阶段加起来一样长和复杂的阶段。制作一个真正的实时系统包括代码和科学的同行评审,测试,集成,更多的测试,部署,甚至更多的测试,监控以及模型本身的持续改进。这不是一件小事,我们将在晚些时候回到这个主题。

这就是设计过程:找出问题,然后找出解决方案。如你所知,我真的很喜欢和设计师一起工作。当然,这可能会有些过头。以设计为导向的思维很容易变成只有设计师的思维,其他人只是执行一个自称为“创意的想法。呕吐。设计师有他们自己的一套偏见,所以你最终只能得到一个漂亮但成本低,几乎不起作用的原型,不可能投入生产。

但是你怎么看?认识这些阶段吗?你的应对策略是什么?请在评论中告诉我们!

脚注

***【1】*明确一点,对于我亲爱的做设计师的朋友们,这是一个笑话。我也见过你们用钢笔。

【2】https://www . Smithsonian mag . com/arts-culture/how-Steve-jobs-love-of-simplicity-fueled-a-design-revolution-23868877/

***【3】*参见例如:司马贺的《人工科学》

为我的家乡州创建 COVID 仪表板的设计决策

原文:https://towardsdatascience.com/design-decisions-in-creating-a-covid-dashboard-for-my-home-state-545a24238952?source=collection_archive---------71-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最近,我利用业余时间为我的家乡澳大利亚新南威尔士州开发了一个新冠肺炎仪表板。这样做的主要动机是因为我感兴趣的某些数据要么不可用,要么在日常粒度上不可用,要么没有以我认为有价值的方式呈现。仪表板可在此处找到:

设计仪表板是一个数据项目,也是一个设计决策。需要做出的决策包括:需要哪些指标,最终用户将如何使用该工具,如何添加适合于指标的上下文,如何在仪表板中导航或添加“流程”元素以增强用户体验。在本文中,我将在创建新冠肺炎仪表板时讨论其中的一些选择。

我应该做一个仪表板吗?

我需要做的第一个编辑决定是是否要做一个仪表板。由于对新冠肺炎知之甚少,而且许多数据来源不完整,我认为,如果使用一个检测能力不足的国家报告的数字,这项工作将是徒劳的。幸运的是,澳大利亚和新南威尔士州拥有一些世界领先的人均检测数据,因此它可以有一定程度的信心说,它正在识别社区内的绝大多数 Covid 病例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

事实上,全国领先的传染病研究中心之一在他们的研究中表明,大多数有症状的病例都有可能被检测出来,其中新南威尔士州在检测覆盖面方面表现尤为突出。(https://www . Doherty . edu . au/uploads/content _ doc/Estimating _ changes _ in _ the _ transmission _ of _ 新冠肺炎 _April14-public-release.pdf )

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

鉴于这种强有力的测试立场,以及对州当局捕获和报告的数据点在识别病例的能力方面可能是全面的高度信心,我认为,由于数据的潜在准确性和完整性,制作仪表板是可行的。此外,我决定只关注新南威尔士州(澳大利亚人口最多的州,也是我居住的州)。原因很简单,各州的数据各不相同(https://the conversation . com/how-much-have-much-much-much-much-much-much-much-much-u-we-keep-better-records-we-don-know-136252)为了 Covid 的目的,澳大利亚的 6 个州可以被视为独立的民族国家,因为它们的地理位置(和面积)以及在州一级政策实施方面的差异。

我应该使用什么工具来构建控制面板?

基本上,我把范围缩小到了 3 个比较有名的可视化工具,它们要么是免费的,要么有一个免费增值服务选项来满足我的目的:Tableau、微软的 Power BI (PBI)和谷歌数据工作室(GDS)。我还对专门针对数据新闻的工具做了一些研究,比如 fluore 和 DataWrapper。然而,尽管它们显示了很大的潜力,我还是决定在未来的项目中使用它们,因为我是一个新手,可能会面临更陡峭的学习曲线,这会消耗我的执行时间。

三名候选人各有弱点。虽然我喜欢使用 PBI 进行快速和肮脏的分析,它有一些最好的开箱即用的可视化以及最强大的开发者附加软件生态系统,但我并不热衷于他们用于公开共享工作的云平台。另一方面,GDS 在实际获取该工具所需的数据量方面存在限制,因为他们更喜欢用户使用 google sheets,google sheet 随后在表格尺寸方面存在限制,并且与其他两种工具相比,缺乏其他服务的数据连接器。

这让我有了 Tableau,我很高兴使用它,因为我对这个软件最有经验,我知道我设想的报告应该包含的内容(见下文)在 Tableau 中很容易执行,不需要太多的修改或代码繁重的工作区。在 Tableau 中,我需要做的最复杂的事情是一个大约 15 行的 case 语句,用于按州按年龄组对人口细分进行编码。在一个理想的世界里,我可能会选择 GDS,因为我觉得它在风格上是最强的,特别是当谈到他们的发布平台和分享工作的能力时,然而 Tableau Public 虽然不太引人注目,但却有强大的产品和大量的观众,以及允许我及时执行的所有必要功能。

报告应该包括什么

下一个问题是仪表板中应该包括哪些措施。在项目开始的时候,我对我想看的东西有一个很好的看法。这在一定程度上是因为我做仪表板的动机是因为我很难找到定期发布的信息,如同期病例增长率,或检测阳性百分比,或者如果它们被发布,信息在每天的粒度上是不可用的(医院/ ICU 入院的情况)。

除了我希望看到的措施之外,我还希望报告保留一些关于 Covid 管理的关键领域的结构(或者至少是具有可靠的公开可用数据的关键领域——联系人追踪除外),如测试、社交距离实践等。这就产生了最初设计的想法,为每个领域(以及案例和“主页”)设计一个工作表,以便用户可以在工作簿中简单地导航,找到他们需要的信息。这些部分可以在我创建的导航“功能区”中找到,每个部分都指向这些特定指标的指定控制面板。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一旦我对类别有了清晰的认识,接下来的问题就是找到合适的度量来跟踪,以及这些度量的可视化。这些决定中的大部分是由获得这些信息所获得的效用以及它们与市场上其他可视化的区别所驱动的。这使我能够确定一些主要的与众不同的特征,包括:

a)通过使用从州卫生当局的每日媒体发布中收集的公开可用信息,绘制住院人数、ICU 住院人数和使用呼吸机的患者人数的图表,实现“拉平曲线”可视化。然后,根据已知和假设的容量进行映射(假设来源于建议澳大利亚政府响应的主要建模者,他们在规划资源时使用 50%的床位专用于非 covid 患者假设)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

b)我在图表上覆盖了新南威尔士州的人口分布,这些图表用于跟踪按年龄段划分的病例(和测试)分布,以便快速识别代表过多/不足的人口。这解决了不断回顾和查看人口普查数据的需要,以了解年龄分层的传播是如何在社区内表现出来的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

c)我使用运动图来显示当地政府区域随时间的传播情况,以便于显示疫情和“热点”。数据也按传播源进行了删减,以表明相对于从海外司法管辖区传入的传播,有多少是在社区内发生的(新南威尔士州和全澳大利亚的大多数病例都是如此)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

d)最后,我覆盖了最近发布的 IOS 数据,这些数据显示了苹果地图用户选择使用案例后移动数据的变化。查看同一 IOS 数据集按星期几的移动性变化,加上不同时间段的变化,以及所提供的三类变量(步行、驾驶和交通)的行为差异

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

苹果 IOS 数据强调移动性的变化和社交距离措施的地面流动效应

我还花了一些时间反复思考报告中不应该包含的特性,或者因为无法扩展而不实用的特性。例如,这导致决定按地理位置绘制病例爆发的热图,而不是像著名的约翰·霍普斯金仪表板那样的气泡图,因为这将更有效地扩展。尽管 JH 的仪表盘上会有大量难以辨认的相互重叠的圆圈,但热图可以使用彩色阴影来显示每个邮编案件数量之间的相对差异。这种可视化比气泡图更有效,如果案例数是 500 或 5000,也同样有用。

使用仪表板使我能够遵循我感兴趣的指标,并以可消费的方式组织公开可用的数据。一旦 Covid 通过,我希望做更多的工作,并为其他健康指标重新调整该模板。Covid 疫情带来的对数据的兴趣可以转化为对更多仪表板的需求,将数据融入背景并提供给乐于接受和感兴趣的公众,仪表板是数据重要性和可见性持续增长的最明显表现。

在这里可以找到【https://datandi.com/projects】并每日更新

有用的资源

我发现并参考的其他有用的可视化报告工具包括:

https://www.covid19data.com.au/

每日联邦政府仪表板https://www . health . Gov . au/resources/publications/coronavirus-新冠肺炎一览

流行病计算器:【https://gabgoh.github.io/COVID/index.html (哇,这个做得很好,向开发者致敬!)

《悉尼先驱晨报》最近公布的数据 viz 工具https://www . smh . com . au/national/新冠肺炎-data-centre-coronavirus-by-the-numbers-2020 04 01-p54g 4 w . html

实验基础的设计:如果你建造了它们,它们就会出现

原文:https://towardsdatascience.com/design-of-experiment-basics-if-you-build-them-they-will-come-cc6a227a0543?source=collection_archive---------22-----------------------

入门

用 Python 蒙特卡罗模拟从基本概率论解释实验概念的设计

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

网上已经有成千上万的来源解释 p 值和与统计显著性检验相关的概念。为什么要再写一个?我一次又一次地看到统计测试被用作获取 p 值和应用“黄金法则”的“黑箱”:如果 p 值小于 0.05,那么结果是显著的。通常,这是盲目进行的,没有真正理解 p 值实际显示了什么,没有显示什么,以及如何正确设计和解释实验。我写这篇文章的目的不是提供一个解决具体问题的方法,而是描述与假设检验相关的基本概念以及我们如何得到它们。

我相信,任何概念只有在以下情况下才能被学习和理解:(1)这些概念与我们已经非常熟悉和非常了解的其他概念有着直观的联系(2)当我们在实践中尝试这些新概念时。

在这篇博文中,我将只使用基本的概率论来回顾统计显著性测试和实验设计的主要原则。我们将不使用任何统计测试,相反,我们将从概率基础一步一步地建立一个统计显著性测试过程:从基础到概念,如统计测试、p 值、显著性水平、最小可检测效应、I/II 型错误、测试的功效和实验基础的设计。

为了说明实践中的所有概念,我将在整篇文章中使用抛硬币的例子,并将蒙特卡洛模拟应用于一个问题:如何测试硬币是公平的还是有偏见的?这是顶级科技公司在面试中经常问的一个著名问题。它也足够出名,甚至有自己的维基百科页面。抛硬币实验和二项分布是任何人都明白的安全起点。让我们开始吧。

简单硬币示例和 p 值

假设我们有一枚硬币,正面概率 P(正面)= 0.5。假设我们翻转 20 次,得到 13 个正面和 7 个反面。我们应该断定硬币是有重量的还是有偏差的?有没有一种方法可以估计这种结果发生的可能性有多大?为了解决上面的问题,我们需要计算我们的结果的概率,即观察 20 次投掷中的 13 次正面。它由二项式分布给出(等式。1,也是我们在这篇文章中需要用到的唯一等式):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

等式 1。在中观察头数 H 的概率 n 在次独立试验中,给定头数 P(头数)= p 的概率。

将这些数字代入等式,我们可以计算出我们观察到的结果的概率为Bin(H=13n toses= 20, p = 0.5) = 0.074。仅仅是结果的概率不足以评估我们的结果有多不可能。例如,从 52 副牌中抽取任意一张特定随机牌的概率约为 0.019,但所有可能的结果都是同样可能的。除非我们考虑所有可能的结果及其相应的概率,否则我们无法回答某一特定观察的可能性有多大。

计算特定观察结果不太可能的一种方法是计算看到任何同样可能或不太可能的结果的总概率。回到我们的硬币例子,我们需要计算 20 次抛硬币的所有可能结果的概率(图 1)。接下来,我们计算获得相同或不太可能的结果的几率(图 1 中概率分布的红色区域),得出 0.19:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图一。假设硬币是公平的,P(正面)= 0.5,20 次抛硬币的所有可能结果的概率分布。函数由等式表示。1 带参数 Bin ( Hn toses= 20, p = 0.5)。红色区域对应于观察到同等或不太可能结果的总概率,称为 p 值。

我们刚刚计算的值叫做 p 值。更正式的定义:给定一个观察值(在我们的例子中是掷硬币系列的结果),以及一个关于系统属性的基本假设(也称为零假设,在我们的例子中我们假设硬币是公平的),p 值是看到相同或不太可能的观察值的总概率。例如,在一副牌的例子中,观察任何特定牌的 p 值是 1,假设该副牌被洗牌。

我们总结一下。仅使用基本的概率理论,我们刚刚推导出一个硬币的统计测试。这基本上是所有统计测试所做的事情:给定关于系统的观察和基本假设(假设没有影响),提供 p 值——获得与实际观察到的结果同样可能或更不可能的结果的概率。

显著性水平,I 类误差

既然我们知道 p 值是什么,并且我们已经推导出硬币公平性的统计测试,让我们做一个计算实验。让我们想象一下,我们有 1000 枚公平硬币,我们将每枚硬币抛 1000 次。在完成一系列硬币投掷后,我们将使用上述方法计算每枚硬币的 p 值。接下来,我们将所有 1000 个获得的 p 值绘制成直方图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图二。1000 枚金币的 p 值分布。计算出的 p 值形成均匀分布(在我们的硬币示例中,连续值完全均匀,接近均匀)。

从直方图中可以看出,当零假设为真时(所有测试的 1000 枚硬币实际上都是公平的),实验的 p 值本质上是一个随机变量,它描述了观察结果的不相似性。在上面的例子中,当硬币是公平的 p 值导致接近均匀分布。

假设将来我们想测试一个未知硬币是否公平。我们可以为 p 值选择一个阈值,低于这个阈值,我们将拒绝硬币是公平的假设。但这样的阈值也有一个权衡:由于公平硬币的 p 值是均匀分布的,选择 0.05 作为阈值将导致 5%的机会得出公平硬币有偏差的结论(图 2,红色区域)。在我们有 1000 枚公平硬币的模拟示例中,我们会错误地得出 56 枚硬币有偏差的结论(大约占测试硬币总数的 5%)。

p 值的选定阈值称为显著性水平,通常表示为𝛂.现在应该清楚的是,𝛂对应于我们错误地拒绝零假设的频率,并得出结论,当我们获得的观察结果实际上是由于随机机会时,我们有影响。这种类型的误差称为I 型误差

最小可检测效应(MDE)和 II 型误差

现在让我们考虑一个问题,我们有一袋硬币,但我们不知道哪些硬币是公平的 P(人头)= 0.5 或有偏见的 P(人头)≠ 0.5。我们如何从统计学的角度来处理这个问题呢?让我们设计一个实验来测试硬币的公平性。

首先,我们需要定义什么是有偏见的硬币。我们需要设置一个阈值,来衡量我们认为硬币有偏差的概率应该与 0.5 有多大的不同。为了便于说明,假设我们只考虑 P(正面)> 0.6 或 P(正面)< 0.4, in other words, if the heads probability differs from the fair coin by 20% or more (this value is called 最小可检测效应MDE 的硬币有偏差。为了测试硬币,让我们将每枚硬币投掷 Ntosses = 100 次,并数出总数。我们可以在 20%的选定最小可检测水平下,为公平硬币和有偏差硬币绘制 100 次投掷中正面总数的预期分布图(图 3)。请注意,有两个铃铛,因为一个有偏向的硬币可以有两种偏向。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3。公平硬币(顶部)和有偏差硬币(底部)的 100 次投掷中正面总数的概率分布。红色填充区域对应于 I 类错误率;蓝色填充区域对应于第二类错误率。

接下来我们需要选择一个显著性水平,𝛂——称一枚公平的硬币有偏见的可接受几率是多少?为了说明的目的,在这个例子中,我们将𝛂 =0.1。现在,我们有了足够的信息来确定我们需要获得的 100 次投掷中正面总数的范围,以得出硬币是公平的结论,或者拒绝硬币是公平的无效假设并得出硬币是有偏差的结论。公平硬币概率分布的这些边界之外的区域应该等于 0.1(图 3,顶部图形的红色区域),这给出了一个范围42,58。如果投掷 100 次后,硬币的正面少于 42 或多于 58(换句话说,p 值小于𝛂),我们将拒绝零假设,并得出硬币有偏差的结论。

很简单吧?然而,我们能用这种方法正确识别所有真正有偏差的硬币吗?一枚有偏向的硬币经过 100 次试验后,最终正面总数在 42 到 58 之间的几率有多大?要回答这个问题,我们需要看看有偏差硬币的预期概率分布(图 3,下图)。42 和 58 之间的蓝色区域是 0.38,这意味着在 38%的情况下,一枚有偏见的硬币实际上会被称为公平的。这被称为第二类误差,其概率通常被表示为𝛃.让我们用一个实际的模拟来说明所有这些概念。

实验的功效,错误发现率

让我们从一袋 1000 枚硬币开始,其中 500 枚硬币是公平的,500 枚硬币是有偏差的(最低可检测水平为 20%)。假设我们不知道哪些硬币是公平的和有偏见的,我们想执行我们的统计测试来找出它。为了测试,现在让我们将每个硬币投掷 100 次,计算 p 值,将其与我们选择的显著性水平𝛂 = 0.1 进行比较,并决定该硬币是否有偏差。这种实验的结果如图 4 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4。1000 枚硬币公平性测试的随机模拟结果。每枚硬币被翻转n 次 = 100 次,将获得的 p 值与显著性水平𝛂 = 0.1 进行比较,以得出硬币是有偏差还是公平的结论。

只有在 62%的情况下(1- 𝛃),我们能够正确地得出结论,一个真正有偏见的硬币是有偏见的。这个值称为测试的功率。我们还可以注意到,在所有 310 + 56 = 366 个识别出的有偏见的硬币中,只有 310 个实际上是有偏见的,56 个实际上是公平的硬币。不正确发现的有偏向硬币的数量与总发现的有偏向硬币的数量之比称为错误发现率,在上面的例子中是 15%。如图 5 所示,如果我们获得更多的数据,我们可以提高测试的功效。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5。投掷硬币的次数如何影响统计测试的功效。在每种情况下,选择最小可检测效应 MDE = 10%,显著性水平为𝛂 =0.05。

非常重要的是要明白,得到统计上无关紧要的结果并不意味着我们没有效果,或者换句话说,它没有证明我们的零假设。我们的测试可能只是低功率和数据不足以拒绝零假设。

在 A/B 测试中经常看到的另一个常见错误是运行实验,直到 p 值变得低于显著性水平,而不是等待预先确定的观察次数(除非你知道你在做什么,并执行顺序或贝叶斯测试)。这种“随走随看”的方法极大地增加了 I 型错误率以及错误发现率。为了说明这一点,我们可以重复图 4 中的计算实验,其中我们需要测试 1000 枚硬币的偏差,但这次我们将检查“我们进行的”显著性,在每次翻转后计算 p 值。如果满足两个条件中的一个,我们就停止实验:p 值小于𝛂(并断定硬币有偏差)或达到最大翻转次数n 次数(断定硬币是公平的)。图 6(红色数据)显示了 I 型错误率和错误发现率与t 损失的函数关系。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6。与图 4 中的实验相同,但 p 值是在“进行中”计算的(红色数据)。选择显著性水平𝛂 = 0.1。

如果仅在收集预定数量的观察值后进行测试,I 型错误率保持不变,并且接近选定的显著性水平𝛂,与观察值长度无关(图 6,蓝线)。当我们“在进行中”计算 p 值时,这是非常不同的,当我们继续观察时,I 型错误率急剧增加。这个模拟演示了在 A/B 测试过程中得出结论时常见的陷阱。

汇总在一起进行统计实验设计

在实践中,我们经常从定义期望的显著性水平𝛂、最小可检测效应和功效(对我们来说不遗漏效应是多么重要)开始。例如,在 A/B 测试的设计过程中,每个实验通常从以下问题开始:

1)我们希望能够可靠地检测到的影响有多小(这将给我们最小的可检测影响)?

2)我们在生产中实施实际上没有效果的变更的可能性有多大?这是显著性水平𝛂或 I 型错误率。

3)我们检测不到实际有用的变化的可能性有多大?这给了我们第二类错误率𝛃.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7。对于任何假设检验实验,图上的四个值总是相互关联的。这意味着,对于一个给定的测试和关于被测系统的基本假设(零假设),如果给定四个值中的任何三个值,您总是可以计算出第四个值。

有了这三个值,我们就可以计算测试所需的观察次数(图 7)。非常重要的是,我们需要在停止实验和做出结论之前收集所有需要的观察结果,否则我们可能会增加错误发现率(图 6)。或者,我们可以使用收集的数据(已知的观察值)、固定的显著性水平和功效,来计算在我们选定的功效下我们可以检测到的最小真实效应大小。任何统计检验的一个重要的普遍概念是,如果我们知道四个值中的三个:显著性水平、功效、观察次数和最小可检测效应,我们就可以计算第四个值。

结论

最后,我想再次强调,这篇文章不是任何特定统计测试或实际应用的秘诀。我的目标是描述与假设检验相关的基本概念,以及我们如何得到它们。本质上,这是我自学假设检验的方法。理解了基本原理之后,你可以阅读许多实用的指南,但是要有概念背后的直觉,而不是把它们当作“黑箱”。记住:

“如果你需要统计数据来证明什么,那很可能不是真的.”

(引自 wpi.edu)。

链接 Github

【领英:https://www.linkedin.com/in/anatoly-zaytsev/

推特:https://twitter.com/zaytsev_anatoly

设计优化:结合进化算法和张拉整体

原文:https://towardsdatascience.com/design-optimization-combining-evolutionary-algorithms-and-tensegrity-e7ec0ac5e7fb?source=collection_archive---------27-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片编辑自 Steve Collis 的照片 Kurilpa 桥。

实践教程

如何使用 Python 和物理引擎来寻找张拉整体结构的最佳设计

一切都始于几周前,当时我无意中发现了一个张拉整体表格的视频。一个看似不可能的结构,却完全真实可行。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

在这里,结构的中央绳索支撑着所有的重量,而侧面的绳索作为悬挂绳索提供平衡。

这种原理被称为tense integrity或 tensional integrity,基于张力和压缩的组合来产生机械稳定性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

这个术语是由巴克明斯特·富勒在 20 世纪 60 年代创造的,这个概念经常被应用在艺术装置中,但偶尔也会出现在建筑中。一个值得注意的例子是澳大利亚布里斯班的 Kurilpa 桥。

我很惊讶,并决定尝试建立一个自己的小张拉整体表。

当我开始思考创作过程时,我心中的工程师开始提出这样的问题:

  • 可以使用的最小电缆数量是多少?
  • 提高稳定性的最佳比例是多少?
  • 我如何对不同的配置进行基准测试并找到最佳配置?

和往常一样,Python 是我寻找所有这些答案所需要的工具。然而,由于没有专门用来模拟张拉整体结构的库,我不得不从头开始。

我搜索了允许在 Python 中执行物理模拟的库,并选择了 PyChrono,这是一个可以模拟几乎任何东西的物理引擎库。

机电系统、有限元分析和流体固体相互作用只是可以用这个库建模的一些事情。

在 PyChrono 中构建张拉整体表

第一步是使用 PyChrono 构建一个 tensegrity 表,从现在开始我称它为 tensortable。为了简单起见,我选择了一个长方体结构,将平行六面体连接在一起来构建刚性组件。

添加电缆有点困难,需要 pychrono.fea 模块。该模块使用有限元分析来模拟柔性部件,如电缆、电线、轮胎、气囊甚至生物力学组织。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

构建过程:每个组件必须按程序设计,指定位置和尺寸(图片由作者提供)。

tensortable 是以编程方式实现的。给定一些输入参数,一个函数生成每个块的位置和尺寸。这在以后会非常方便,因为它允许轻松地部署不同的配置。

可以配置的参数有:

  • x_basez_base :基座平行六面体的宽度和深度。
  • x_topz_top :顶部平行六面体的宽度和深度。
  • y_pole :垂直杆的高度。
  • x_beam :立柱后水平横梁的长度(第二根横梁为 x_base 和 x_beam 之差)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

tensortable 的不同配置(图片由作者提供)。

创建稳定性测试

唯一缺少的是评估这些十种分类的稳定性的方法。在模拟中加入地震是一种简单而有趣的方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

PyChrono 的一场地震和一些立方体(图片由作者提供)。

一个简单的地震可以用作用在地板上的正弦函数来模拟。这个正弦函数的参数是:

  • 频率:我们每秒钟有多少次振荡。
  • 振幅:振荡的振幅。
  • 方向:x 轴、z 轴或两者的组合。

我们将使用这些参数来调整地震的强度。

测试不同的配置

到目前为止,已经有可能意识到物理引擎正在正确地工作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

如果没有施加力,只有三根缆索的张力腿平台能够站立,但是一旦有小的摆动,平衡就失去了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

相反,有了五根电缆,即使施加外力,它也能够站立。

寻找最佳设计

此时,我本可以手动模拟十几种配置,找出最佳配置,然后就此收工。但是由于模拟器运行良好,我决定更进一步,创建一个搜索算法,它可以以智能和自主的方式找到最佳配置。

这似乎是使用进化算法将十种物品进化到最佳形状的绝佳时机。

进化算法简介

进化算法是一类受生物进化启发的优化算法。正如在物种的生物进化中一样,像选择、繁殖和突变这样的概念是这些算法的基石。

这个想法非常直观:十个可排序的群体将被测试稳定性,最好的将存活下来并被用作新世代的父母,然后这个过程被迭代。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

进化过程图:只有最优秀的个体才会把自己的特征传递给下一代。在进化算法中,并不强制父母双方都要生育后代。

实际上,进化算法的步骤如下:

  • 随机化: 我们从第 1 代开始进化过程,这是一个由 100 个随机的十个可排序的群体。
  • 体能评估:
    我们对人群进行体能测试,这个测试将评估每个个体的好坏。在这种情况下,测试将经受住一系列逐渐增强的地震。每个十个可排序表保持稳定的时间越长,其适合度得分就越高。
    首先,我们计算上半部分的实际位置和目标位置之间的偏差(在完全平衡的情况下,目标位置应该在哪里)。那么稳定性分数可以定义为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 选择:
    只有最优秀的十种被选择出来,把它们的特性传给后代。十个可排序的项目按体能分数排序,100 个中最好的 10 个被选中。这些个体会自动延续到下一代,除此之外,它们还会被用来产生后代。

  • 突变和重组 :
    突变和重组用于使种群向更好的配置进化。突变在于对双亲的参数应用一个变量。重组指将两个或两个以上亲本的参数组合起来,生成新的亲本。

    在这种情况下,只使用突变就足够了:每个父代将被用于创建 9 个新的 tensortables。将高斯随机样本添加到父母的参数中,获得孩子的参数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每次更新后,所有参数都被限制在最小值和最大值之间,从而避免负面措施。

此时该过程可以迭代,简单地重复适应度评估、选择和变异的步骤。每一代都将仅仅基于上一代中最优秀的个体,逐渐进化到更好的稳定性。

我们现在可以让程序运行并收集结果了!

结果呢

在这里,我使用了有五根电缆的模型。它已经站得很好,但我想看看什么是最佳比例。

我们可以看到进化向十个短且基数大的可排序对象收敛,这在稳定性方面是完全有意义的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

进化过程:最佳个体的得分和群体的平均值(图片由作者提供)。

收敛很快就实现了,这也是我们从这个问题的适度复杂性中所能期待的。

在这里,我们可以享受到在更强烈的地震面前,最终结构的稳定性增加,上半部分几乎不动。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

所以现在我们有了它:一种能够以自主方式找到最佳配置的算法。

最后…

我也造了一个实体的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

一些木头,螺丝,一点耐心来校准电缆和结构是站起来的。具有讽刺意味的是,在完成所有这些工作后,我仍然选择了我脑海中的最初设计:对称的五根电缆。平衡感很好,但也很悦目。

最终,好的设计不仅仅是功能性的,还包括优雅和外观。

我相信数据科学也是如此。

我一直有意忽略数学和代码,但是如果你对技术方面感兴趣的话,不要担心,我会添加一个代码链接(只要我清理干净!).

有问题吗?随时联系!

用 Python 中的 Ax 进行设计优化

原文:https://towardsdatascience.com/design-optimization-with-ax-in-python-957b1fec776f?source=collection_archive---------10-----------------------

人类在联合优化非线性、高维函数方面很糟糕。这是事实。在机器学习的时代,计算机可以为我们做决定,有工具可以触及如此多的工程领域。在本教程中,我将重点介绍脸书的工具 Ax ,它将使用贝叶斯优化来优化用户定义的高维非线性目标。Ax,自适应实验平台,是脸书的一个开源工具,用于优化复杂的非线性实验。这真的很尖锐,让我们开始吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源—作者。

数学总结

该代码使用贝叶斯优化来迭代地探索状态空间,并将高斯过程拟合到底层模型(实验)。如果你只是想看代码结构,跳过这一部分。注意— Ax 可以使用其他模型和方法,但是我只关注最适合我的问题的工具

高斯过程—建模

高斯过程(GP)是一种非线性近似工具。这是跨函数空间的回归。它所做的是获取一个特征向量(x)和一组结果 f(x ),并在两者之间拟合一个连续函数。利用这样的分布,预测是在对特征进行调节的情况下完成的。但是它的名字高斯过程是怎么来的呢?

“高斯过程是高斯概率分布的推广”——卡尔·爱德华·拉斯姆森。

公式是回归问题的概率估计。不确定性估计仍然在这里—现在函数 f(x) 被一个 GP(m(x),k(x,x’))均值 (m(x)=E[f(x)])和协方差 (k(x,x '))函数捕获。用于映射两个变量之间的协方差的函数(在高斯分布中,这只是一个数字),是它正在建模的概率分布。美妙之处在于,通过智能选择插值函数,您可以从有限采样中获得状态空间中所有潜在点的平滑近似值

推荐阅读—拉斯姆森,卡尔·爱德华。"机器学习中的高斯过程."关于机器学习的暑期学校。施普林格,柏林,海德堡,2003。

贝叶斯优化—学习

贝叶斯优化(BO)是一种优化非线性问题的工具。它会给你一组设计参数,让你在下一次迭代中尝试。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

它是怎么做到的?有两个关键点:1)它迭代地训练一个 GP 模型,2)它使用一个采集函数对一组点采样的潜在增益进行建模。最常用的获取函数(抽样函数)是期望改善(EI)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

该函数基于预期比当前最佳值( x* )提高最多的参数,对下一组参数( x )进行采样。最终发生的是,EI 将在高不确定性(潜在高回报)区域的勘探与回报接近最优的微调区域之间取得平衡。 BO 将在每次迭代中训练一个新的模型,看看哪里有改进的潜力,评估模型(功能),然后重新训练。

推荐阅读——Shahriari,Bobak 等人的《把人带出循环:贝叶斯优化综述》IEEE 会议录 104.1(2015):148–175。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来自作者的 BO 的简单说明。

Python 教程

本教程基于设计一个微机电系统(MEMs)跳跃机器人,我的代码可以在这里找到。这个项目有两个方面:

  1. 根据一组约束方程优化设计——一个从第一原理导出的分析模型——可能与非线性交织在一起。在 sim.py 中找到,教程对此进行了解释。
  2. 通过拟合真实世界中发生的事情的模型来改进实验建模和设计效率。真实世界的实验数据显示在 example.py. 中,可以对其进行改进,以给出实验数据符合分析模型的概率可能性。

[## natolambert/mems-bo

微机电系统设计的贝叶斯优化。在 GitHub 上创建一个帐户,为 natolambert/mems-bo 开发做出贡献。

github.com](https://github.com/natolambert/mems-bo)

代码

现在我将介绍如何用 python 实现这种优化。请打开这个文件并跟随:https://github.com/natolambert/mems-bo/blob/master/sim.py(注意,代码可能比教程更新得更快,但核心元素仍然保留)。

属国

我的例子利用了脸书的两个工具,python ≥3.7。

  1. Ax,适应性实验平台(https://ax.dev/)。这将为我们处理所有的数学问题,优化一个复杂的函数并将结果可视化。
  2. Hydra,一个优雅地配置复杂应用的框架(https://hydra.cc/)。这将通过改变一个简单的配置文件来处理任何设计问题。

这是 python 文件头的样子——没有太多的依赖关系。

from ax import *
import numpy as np
import pandas as pd

from models import jumper

import os
import sys
import hydra
import logging

# A couple requirements for running Hydra 
sys.path.append(os.getcwd())
log = logging.getLogger(__name__)

定义优化问题

优化问题必须采取特定的形式,并且是每个新项目需要编写的唯一代码。我们需要的是一个模型,它接受一个字典的参数,并返回一个字典的度量,其中的项目是试验的平均值和标准误差度量。注意— 标准误差是可选的,只是很好地融入支持建模的不确定性估计。下面是跳跃机器人的一个例子,它设置了 3 个设计参数 w,N,L*(w:弹簧宽度, N :弹簧折叠数, L :弹簧长度),它返回 3 个指标: 储能,*,以及**

**def jumper(parameters):
    rho = 2300
    E = 170e9
    T = 550e-6
    lamb = 13.75
    w = parameters["w"]
    x_max = 5e-3
    N = parameters["N"]
    L = parameters["L"]

    k = 8 * (E * w ** 3 * T) / (N * L ** 3)
    x = x_max
    x_cant = x / (4 * N)
    F_required = k * x
    strain = (3 / 2) * (x_cant) * w / (L / 4) ** 2
    U_stored = 0.5 * k * x ** 2

    return {"Energy": (U_stored, 0.0),
            "Strain": (strain, 0.0),
            "Force": (F_required, 0.0)}**

程序化地生成状态空间

这是我们利用九头蛇的地方。Hydra 将为我们加载这个 config.yaml,并从命令行将其与主要的实验配置交织在一起,因此我们可以轻松地更改我们的问题、搜索空间或约束。

优化问题由三部分定义:

  1. ****状态空间:状态空间可以在变量范围、固定设计变量或离散选择变量上定义。对数比例和数据类型工具通过投影到更均匀的空间来帮助模型拟合。
  2. 约束: Ax 支持两种类型的约束——结果约束和参数约束。结果约束(如下所示)将结果限制在某个值之上或之下,在本例中,力和应变受到约束,因此物理设备可以运行而不会破碎。可添加参数约束以确保设计变量在相互关系内。
  3. ****目标度量:度量决定了模型中要优化的目标(最大或最小)。Ax 可以处理联合优化。

这里是 jumper.yaml

**problem:
  space:
    N:
      type: range
      bounds: [1,6]
      value_type: int
      log_scale: false
    L:
      type: range
      bounds: [5e-4, 1.9e-3]
      value_type: float
      log_scale: true
    w:
      type: range
      bounds: [4.0e-5, 4.0e-4]
      value_type: float
      log_scale: false
  constraints:
    Strain:
      type: LEQ
      value: 0.5e-2
    Force:
      type: LEQ
      value: 15.0e-3
  metric:
    name: Energy
    minimize: false**

git 上有用于将配置转换成 Ax 对象的函数。Ax 的框架然后使用一个实验性的 API,该 API 将用于其余的代码——所有的优化过程都浓缩到这个对象中。

**exp = SimpleExperiment(
    name="MEMS Optimization",
    search_space=SearchSpace(search_space),
    evaluation_function=jumper,
    objective_name="Energy",
    minimize=False,
    outcome_constraints=outcome_con,
)**

优化循环

这里有两个重要的参与者:

  1. SOBOL:这是一个用于准随机搜索的搜索范例,它比纯粹的随机搜索产生更均匀的覆盖范围。
  2. GPEI:这是贝叶斯优化器的高斯过程模型,内置了预期改善获取功能。

优化循环运行一个搜索阶段,以确保模型的均匀覆盖,然后 GPEI 将快速优化模型参数到最佳值。

进行搜索。

**sobol = Models.SOBOL(exp.search_space)
num_search = cfg.bo.random
for i in range(num_search):
    exp.new_trial(generator_run=sobol.gen(1))
    exp.trials[len(exp.trials) - 1].run()**

训练一个模特。

**# data = exp.fetch_data()
gpei = Models.BOTORCH(experiment=exp, data=exp.eval())**

迭代改进。

**num_opt = cfg.bo.optimized
for i in range(num_opt):
    print(f"Running GP+EI optimization trial {i + 1}/{num_opt}...")
    # Reinitialize GP+EI model at each step with updated data.
    batch = exp.new_trial(generator_run=gpei.gen(1))
    gpei = Models.BOTORCH(experiment=exp, data=exp.eval())**

结果呢

高斯过程之上的贝叶斯优化产生了奇妙的、可解释的结果。在这里,我们将展示模型如何覆盖设计空间,以及优化器如何改进目标。

设计空间

通过一个简单的函数,Ax 可以可视化多个变量中 GP 的先验。这给了我们一个可视化设计权衡的好方法。

**plot_contour(model=gpei,
                    param_x="N",
                    param_y="w",
                    metric_name="Energy",
                    lower_is_better=cfg.metric.minimize)**

下面我们将看到的是显示不同空间的 GP 均值和协方差的图。直观地说,平均值是目标的估计值(在这种情况下是能量**)。标准误差是协方差估计值——不确定性估计值,它与预期改善的抽样有关。**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

春季褶皱宽度与褶皱数量模型景观。左边是预测储存能量的平均值,右边是模型的不确定性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传****外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

左:N 对 L 模型景观。右:左对右模型景观。

曲线显示,NvL 和 LvW 空间中有非常特定的区域可以创建功能性设备。这对应于物理约束。检查模型在探索过程中如何演变并向最终景观收敛也很有用,这可以通过将相同的绘图代码添加到学习循环中来完成。

学习曲线

迭代解决问题最重要的部分是改进。如果工具除了随机抽样之外没有显示进展,那还有什么意义呢?有了 Ax,我们可以很容易地观察到学习进度随时间的变化,方法单一。

**optimization_trace_single_method(
    y=objective_means.T, ylabel=cfg.metric.name,
    model_transitions=[cfg.bo.random], trace_color=(114, 110, 180),
)**

下面是迭代与储存能量的关系图(通过机器人质量标准化以最大化跳跃高度)。垂直虚线的左边是随机 SOBOL 迭代,右边是 GPEI 迭代。很明显,系统正在学习,最终,在最优区域的预期改善如此之低,以至于回报下降(它正在探索状态空间的其他不确定区域。)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

希望您能看到这个工具的威力,以及将它应用于各种问题是多么容易。Ax 框架非常强大,我已经在多个项目中使用它(学习机器人控制器是 MEMs 设计的另一个方面)。

有人可能会问,为什么我们不能用当今最流行的回归工具——神经网络来做这样的迭代更新呢?答案在于近似平滑度和数据覆盖范围。GPs 的强大之处在于,该模型在测量点之间拟合出平滑的近似值,从而在标记的训练集之外给出惊人、稳定的预测。试图用神经网络来做这件事是非常危险的,因为神经网络在训练分布之外发散。这又是何时使用哪种机器学习模型的另一个例子。****

当正确的工具应用于结构化问题时,机器学习效果最佳——而不是当任意工具被扔向任何问题时。

更多?订阅我关于机器人、人工智能和社会的时事通讯!

** [## 自动化大众化

一个关于机器人和人工智能的博客,让它们对每个人都有益,以及即将到来的自动化浪潮…

robotic.substack.com](https://robotic.substack.com/)**

机器学习培训工作流程的设计模式

原文:https://towardsdatascience.com/design-pattern-for-machine-learning-training-work-flow-1945da4d3b05?source=collection_archive---------40-----------------------

作为一名数据科学家,我做很多快速实验。在这篇文章中,我解释了如何使用高阶函数和装饰器来管理我的 Python 实验。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来自爆发莎拉·普弗卢格的照片

我相信我所有的读者都会在他们的数据集上尝试多种训练算法,以找到性能最佳的模型。我已经多次这样做了,在整个练习结束时,我的工作空间会是这样的—

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

经过几轮实验后,我的工作区

最终,我会忘记我在每个文件中做了什么,甚至为了记住最佳型号,我将不得不浏览每个笔记本文件来检查性能。当我邀请合作者参与这个项目时,系统变得更加复杂。我和我的合作者将有我们自己的训练代码,我们每个人都将用他们自己的代码创建一个 Python 文件/笔记本。这整个设置变成了一个令人头疼的维护问题。

我已经学会了通过实现一个叫做“策略”的设计模式来降低复杂性。我一启动项目就设置了这种模式,并提高了项目代码的可维护性和可重用性。

在阐述策略之前,我需要引入高阶函数和装饰器的概念。如果您已经了解了这一点,请跳过接下来的两个部分。

高阶函数

Python 将函数视为一级对象。这个想法很深刻,很细致。在这篇文章中,我无法公正地对待这个复杂的话题。相反,我将敦促你们所有人向那些写了多篇关于“一流”文章的大师们学习。相反,我将展示两个将函数视为一级对象的例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这个例子中,我们创建了一个函数来计算阶乘,Python 解释器在0x103d6b430注册了这个函数。第一类自然允许我-

  1. 将阶乘赋值给一个名为fact的新变量,并使用该变量计算阶乘。而且,
  2. factorial作为参数传递给函数accumulate

函数accumulate是一个高阶函数,因为它将一个函数作为输入。高阶函数在数据科学(以及整个 Python)中很流行。我确信所有的数据科学家都使用过像df.apply(np.mean)这样的模式来构建他们的熊猫数据框架。np.mean是一个函数,由于apply将其作为输入,apply是一个高阶函数。

装修工

装饰器也是高阶函数,它接受另一个函数(称为装饰函数)作为参数,并返回或替换该函数。我将集中讨论一个最简单的装潢师的例子。

def decorator(func):
	'''do something'''
	return func@decorate
def my_function():
	'''Interesting code'''# The above is equivalent to - 
decorate(my_function)

装饰者利用 Python 中函数的一级性质。

战略设计模式

设计模式描述了一个具有模式的问题,然后提出了该问题的解决方案。在我的情况下,问题是在合作进行机器学习的快速实验时减少混乱。

引用维基百科-

计算机编程中,策略模式(也称为策略模式)是一种行为 软件设计模式,能够在运行时选择算法。代码不是直接实现单个算法,而是接收运行时指令,以决定使用哪一组算法。【1】

我使用的策略模式包括使用装饰器来跟踪和获取模型。实现如下图所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

模型训练代码的脚手架

  1. 我已经初始化了一个空列表来存储我感兴趣的所有模型。
  2. 我创建了一个register装饰函数来注册我的模型。装饰器接受任何函数,并将该函数添加到列表中models
  3. 我使用@register关键字来注册我的模型
  4. 我将每个模型训练代码作为一个独立的函数来编写。但是它们都实现了标准的返回类型。在这个例子中是 F1 分数和训练模型。
  5. 现在best_model(data)获取所有注册的模型,并返回性能最好的模型。

每当我的合作者添加一个新的模型训练函数时,她都会用关键字@register来修饰这个函数,新的模型就会被集成到我的训练运行中。

这种模式允许我们以灵活和简单的方式开发 ML 模型。该模式在运行时选择最佳模型。我可以添加一个新的模型训练代码,并且可以运行模型训练功能的全部或特定子集。要移除任何函数(模型训练代码),我可以只注释掉@register装饰器。

结论

随着许多人尝试不同的技巧,协作机器学习变得复杂和混乱,您的开发环境变成了陈旧代码和笔记本文件的复杂混乱。我推荐的模式可以帮助开发人员灵活地设计新代码,并允许维护人员保持代码库的整洁。该策略在开发人员中强制执行纪律,以编写标准的可重用代码。这个策略帮助我和我的团队缩短了代码开发时间,减少了代码中的错误。

MongoDB 的设计模式

原文:https://towardsdatascience.com/design-patterns-for-mongodb-894767315905?source=collection_archive---------6-----------------------

每个全栈开发人员在构建 MongoDB 模式时需要做出的设计决策

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

自从计算出现以来,数据一直在增长,这对存储、处理和分析技术的需求产生了直接影响。在过去的十年中,开发人员已经从 SQL 数据库转移到 NoSQL 数据库,MongoDB 作为企业应用程序世界中的运营数据存储库,在受欢迎程度方面占据了主导地位。

如果你读过我最近的文章或者亲自了解我,你可能会意识到我是多么重视软件架构和模式。大多数人认为它们只适用于服务器端。我真的相信后端设计不应该是事后的想法,而是架构的关键部分。糟糕的设计选择明显影响了解决方案的可伸缩性和性能。

因此,今天我将向您介绍一些实用的 MongoDB 设计模式,任何全栈开发人员在使用 MEAN 均值技术集合时都应该了解这些模式:

❗️**Assumption:** Basic familiarity with MongoDB is necessary, so is some understanding of relational modelling (because we will refer to SQL as a contrasting approach).

宏伟的计划(或模式😄)的东西

通常,我们认为 MongoDB 是一个无模式数据库,但这并不完全正确!它确实有模式,但是它是动态的,也就是说,该模式不在相同集合的文档上实施,相反,它具有改变和变形的能力;这就是为什么它被称为多态模式。这意味着不同的数据集可以存储在一起,这是蓬勃发展的非结构化大数据的竞争优势。

遗传和多态性

特别是当涉及到面向对象编程(OOP)和继承时,MongoDB 的多态功能变得非常方便,因为开发人员可以将同一层次结构(父子)的不同类的实例序列化到同一集合中,然后将它们反序列化为对象。

这在关系数据库中不是很直接,因为表有固定的模式。例如,考虑一个交易系统:一个Security基类可以派生为StockEquityOption等。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在 MongoDB 中,我们可以将派生类型存储在一个名为Security的集合中,并在每个文档上添加一个鉴别器(_t),而在关系数据库中,我们有以下建模选择:

  • 包含StockEquityOption字段联合的单个表,产生一个稀疏填充的模式。
  • 三个表,分别对应StockEquityOption的具体实现,导致冗余(因为Security属性有重复的基础信息),以及检索所有类型证券的复杂查询
  • 一个表用于Security的公共内容,三个表用于StockEquityOption,它们将有一个SecurityID,并且将只包含各自的属性。这个选项解决了冗余问题,但是查询仍然会变得复杂。

如您所见,这里包含的代码比多态 MongoDb 集合中的多得多!

图式进化

生活中唯一不变的事情就是变化——这当然适用于数据库模式,当涉及到传统的关系数据库系统时,它经常会带来挑战和一些麻烦。一个表格模式的致命弱点是,对一个表的小改动会引起整个数据库的连锁反应,并且会影响到服务器端的应用程序代码。

典型的方法是停止应用程序,进行备份,运行复杂的迁移脚本以支持新模式,发布新版本的应用程序以支持新模式,然后重启应用程序。由于持续部署(CD)负责该版本的应用程序方面,需要长时间停机的最耗时任务被限制在数据库迁移上。一些在大表上执行的ALTER命令甚至需要几天才能完成…

然而,在 MongoDB 中,向后兼容性是现成的,所以开发人员在服务器端代码本身中考虑这些变化。一旦应用程序被更新以处理缺少字段的情况,我们就可以在后台迁移正在讨论的集合,同时应用程序还在运行(假设涉及不止一个节点)。当整个集合被迁移时,我们可以替换我们的应用程序代码来真正忘记旧字段。

数据库设计不是一成不变的,在遗留的表格数据库中,模式更改可能会令人烦恼(如果不是瘫痪的话),所以 MongoDB 的多态特性确实非常强大。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

嵌入还是不嵌入:这是个问题!

如果你有任何 OOP 经验,你一定在你的职业生涯中遇到过 Eric Evan 的经典著作领域驱动设计,它介绍了集合模型。聚合是我们作为一个单元进行交互的数据集合,通常比传统的行/记录具有更复杂的结构,即它可以包含嵌套列表、字典或其他复合类型。

仅在单个聚合的内容中支持原子性;换句话说,聚集形成了一个 ACID 操作的边界(阅读 MongoDB 手册中的)。处理聚合间的关系比聚合内的关系更困难:连接在内核中不被直接支持,而是在应用程序代码中或者用有点复杂的聚合管道框架来管理。

本质上,在是否将相关对象嵌入另一个相关对象或者通过 ID 引用相关对象上有一个很好的平衡,并且作为建模中的大多数事情,没有关于如何做出这个决定的一站式解决方案。它在很大程度上是特定于上下文的,因为它取决于应用程序如何与数据交互。

在我们继续之前,我们需要了解嵌入的优势是什么:

🔴 The main reason for embedding documents is read performance which is connected to the very nature of the way **computer disks** are built: when looking for a particular record, they may take a while to locate it (high latency); but once they do, accessing any additional bytes happens fast (high bandwidth). So collocating related information makes sense as it can be retrieved in one go.🔴 Another aspect is that it reduces the **round trips** to the database that we had to program in order to query separate collections.

现在,让我们根据两个实体之间的关系类型,探讨一些在设计 MongoDB 模式时需要考虑的问题:

1:1

一对一关系是一种描述两个实体之间关系的基数类型,其中实体 A 中的一条记录与实体 b 中的一条记录相关联。它可以通过两种方式建模:将关系嵌入为子文档,或者链接到单独集合中的文档(没有强制外键约束,因此关系只存在于应用程序级架构中)。这完全取决于应用程序访问数据的方式、频率以及数据集的生命周期(例如,如果实体 A 被删除,实体 B 是否仍然存在?)

**Golden Rule #1:** If an object B needs to be accessed on its own  (i.e. outside the context of the parent object A) then use reference, otherwise embed.

1:N

一对多关系是指两个实体 A 和 B 之间的关系,其中一方可以有一个或多个到另一方的链接,而相反的是单边的。像 1:1 关系一样,它也可以通过利用嵌入或引用来建模。
以下是需要考虑的主要因素:

如果对象的嵌套数组将不受控制地增加,则不建议嵌入,因为:

  • 每个文档不能超过 16MB。
  • 需要为不断增长的文档分配新的空间,还需要更新索引,这会影响写入性能。

在这种情况下,引用是优选的,并且实体 A 和 B 被建模为独立的集合。然而,一个代价是我们需要执行第二次查询来获得实体 B 的细节,因此读取性能可能会受到影响。一个应用级连接来拯救我们:通过正确的索引(用于内存优化)和使用投影(用于减少网络带宽),服务器端连接比推送到 DB 引擎的连接稍微贵一些。应该很少需要$lookup操作符。如果我们需要它很多,有一个模式气味!

另一种选择是使用预聚合集合(充当 OLAP 立方体)来简化其中一些连接。

**Golden Rule # 2:** Arrays should not grow without bound.
- If there are less than a couple of hundred narrow documents on the B side, it is safe to embed them;
— If there are more than a couple of hundred documents on the B side, we don’t embed the whole document; we link them by having an array of B objectID references;
— If there are more than a few thousand documents on the B side, we use a parent-reference to the A-side in the B objects.

**Golden Rule # 3:** Application-level joins are common practice and not to be frowned upon; in these cases indexing selection makes or breaks the querying performance.

❗️Denormalisation: 使我们的文档非规范化的两个因素是:

  • 更新将不再是原子性的;
  • 高读写比(即经常被读取且很少被更新的字段是反规范化的良好候选)。

男:男

多对多关系是指两个实体 A 和 B 之间的关系,其中双方可以有一个或多个到另一方的链接。在关系数据库中,这些情况用连接表建模,然而在 MongoDB 中我们可以使用双向嵌入,所以我们查询 A 来搜索 B 对象的嵌入引用,然后用$in操作符查询 B 来找到这些返回的引用(反过来也是可能的)。反之亦然。

这里的复杂性来自于在 A 和 B 之间建立一个平衡,因为 16MB 的阈值也可能被打破。在这些情况下,建议使用单向嵌入。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

推荐阅读

收场白

所有这些的结果是,MongoDB 使我们能够设计我们的模式来满足我们的应用程序的需求,这样我们就可以充分利用它们。这种灵活性非常强大,但是这种力量需要根据我们在应用程序中使用的模式来加以利用。—我们需要记住,性能问题通常是由糟糕的模式设计引起的,因此,第一次就把它做好是至关重要的。

感谢阅读!

我经常在媒体上写关于领导力、技术&的数据——如果你想阅读我未来的帖子,请‘关注’我

医疗环境中数据可视化的设计原则

原文:https://towardsdatascience.com/design-principles-for-data-visualisation-in-a-healthcare-setting-ef9bf2954a58?source=collection_archive---------37-----------------------

向更广泛的受众展示医疗保健数据时,需要以用户为中心的迭代设计

医疗保健产生了大量的数据和数据分析的潜力。在进行任何分析或比较之前,充分理解数据以及如何使用数据是很重要的。作为由健康基金会资助的数据可视化项目的一部分,东北质量观察站制定了七个设计原则。

虽然项目的重点是将平面文件格式转换成交互式工具,但我们有大量的变化;包括数据来源和输出类型。在项目过程中,我们发现起草一些指导方针来帮助工具的开发是有益的。作为项目的一部分,在简短的文献回顾和与临床医生的互动之后,这些被进一步发展以产生七个设计原则:

  1. 临床医生参与了整个过程的每一步
  2. 用正确的临床问题引导
  3. 使数据及时和相关
  4. 用户没有学习曲线
  5. 没有必要重新发明轮子
  6. 数据是灵活的和可共享的
  7. 适合这项工作的工具

设计原则 1。临床医生全程参与

最终用户(临床医生)在设计阶段的参与对于获得适合他们的交互式数据可视化(DV)工具/仪表板的功能并确保可接受性至关重要。

对于用于通知质量改进的 DV 工具/仪表板,它需要被最终用户(在这种情况下是临床医生)接受。如果用户参与设计阶段,可接受性会增加。让临床医生参与设计阶段可以探索他们或他们团队的成员将如何使用 DV 工具/仪表板,因此在功能上不基于开发团队的假设。由于相互竞争的优先事项和临床承诺,与临床医生的接触必须适应临床模式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

临床医生对数据可视化工具的要求和关键组件

这一原则是针对医疗保健项目制定的,但也适用于许多领域——最终用户应该参与设计流程的每一步,因为这将确保工具中的功能如预期的那样存在,并且工具的使用是有效的。设计一个不适合目的的工具是对资源的滥用,因此不经常使用。

设计原则 2。以正确的临床问题开始

明确最终用户的主要临床问题,并据此设计 DV 工具/仪表板。

当处理大型数据集时,有一种尝试和回答没有被问到的问题的诱惑。这可能导致数据过载,有可能导致关键信息丢失。仪表板或数据可视化工具应该“过滤噪音”,以便在所有信息中更容易找到关键的“信号”。

最终,如果必要,一个临床问题可以集中在一些后续问题上。当最终用户希望对其临床单位有一个总体了解时,他们会问一组不同的问题,而不是在浏览数据以找到关于质量不同方面的深入信息时。因此,理想情况下,家庭暴力工具/仪表板的设计应考虑到根据所提问题的不同详细程度;应该可以获得一个部门或医院如何运作的概况,以及回答对实际护理质量的不同方面的深入询问。

设计原则 3。使数据及时相关

数据应尽可能更新(并考虑排除太旧而无法回答问题的数据)。

如果数据“陈旧”,它可能会失去一些功能,变得无关紧要。关于护理质量的决定应该基于被认为有用的最新可用数据。排除基于临床医生认为太旧而无法提供有用见解的基础数据的指标可能是值得的。这是一种理想化的情况。本项目中使用的数据基于公开的国家审计。进行这些审计需要时间来收集、清理和分析数据,因此自然会有延迟。现有的最新数据可能在某种程度上已经过时。在临床设置中,可以收集实时数据,但是在这种情况下,很少有或没有机会进行数据清理或聚合,因此可能会妨碍临床单位或护理质量的比较。

设计原则 4。用户没有学习曲线

确保 DV 工具/仪表板对最终用户来说一目了然,易于使用和导航。

最终用户应该不需要很高的 IT 技能就能使用该工具或仪表盘。最终用户学习如何使用新工具的时间有限。为了最大限度地利用,这些工具及其导航需要一目了然,并且不需要 IT/计算方面的资格认证,以便能够在很短的准备时间内与数据进行交互。应该不需要传统的用户手册就能够与数据进行交互。为了帮助使用仪表板,在这个项目中,我们能够在可视化中加入详细的“如何做”部分。这些说明了该工具如何在不妨碍显示的情况下工作,并同样增强了 DV 工具/仪表板的易用性。使用浮动的“how to”也可以用来提供说明文字;解释数据显示了什么以及如何最好地解释它。

在 DV 工具中导航是直观的,这一点很重要。指标的顺序和流程应该对临床医生有意义。任何链接的目的地都应该是预期的。最终用户在设计阶段的参与应该有助于这个导航过程,给出一个用户如何接近产品的指示。重要的是,用户能够将他们的时间集中在数据和它所讲述的故事上,而不是试图浏览 DV 工具/仪表板。

设计原则 5。没有必要重新发明轮子

了解公认的视觉设计原则。在需要解释的地方加入解释性的叙述,确保你避免“忙碌”的视觉效果和信息超载。

布局和格式很重要——需要在视觉复杂性和信息实用性之间取得平衡。如果整个 DV 工具/仪表板不一致,那么用户可能会不知所措。同样,颜色需要在视觉上吸引人,适合色觉缺陷(CVD ),并且没有意想不到的含义;例如,使用红色和绿色,但不要在低俗的情况下使用。导航元素应该是一致的(相同的地方,看起来一样,清晰的标签),它们应该看起来像是相关的或者是集合的一部分。一旦在一个 viz(vizualization)上设置了功能,用户希望所有其他 viz 都具有相同的功能和感觉。

仪表板/DV 工具的开发人员应了解 PARC 原则(接近、对齐、重复和对比)和格式塔原则;不管模式存在与否,寻找模式是人的天性。如果两个项目看起来相似,就会认为它们的功能相似。当创建显示多个指标和图表的仪表板时,人的本性决定了那些靠近的将是关联的指标。

当感觉需要解释性叙述时,这需要足够有帮助并提供答案,而不会使观想过于复杂而无法提供问题的简单答案。重要的是,任何仪表板上的可视化是清晰的,而不是杂乱的不必要的文本。

设计原则 6。数据灵活且可共享

确保 DV 工具/仪表板能够提取输出内容,以纳入用户自己的报告和演示。

数据召回的概念是早期设计原则((设计原则 4)(设计原则 5) )中提到的导航的基础。DV 工具/仪表板的一个关键特性是,工具首次使用时所做的任何选择都会保留在整个产品中。这改进了导航并确保可视化被正确解释。

为了最大限度地提高交互式仪表板和最终用户的工作效率,用户应该能够设置自己对软件中保存的数据的查询。然后可以定期共享或重新运行。能够保存查询确保了在下一个时间点被询问的问题没有变化,并且这将有助于验证结果和突出任何问题(例如,作为异常值)。

重要的是,数据和数据可视化可以共享,这也提供了一种提高护理质量的方法,其中数据可以突出任何问题或加强任何积极的改进。因此,重要的是,任何产品都必须能够提取输出内容,以包含在用户自己的报告和演示中。应该可以保存单个图表,并且图表的布局有利于提取(即任何解释文本都不会与图表重叠)。然后,图表应该以允许共享的格式保存,无论是通过电子邮件还是通过将它们插入不同的文档或演示文稿。

设计原则 7。适合工作的工具

静态和交互式仪表板都很有用,因为可能仍然需要静态报告来提供护理质量的概述,并且可能需要交互式 DV 工具/仪表板来实现数据的“深度挖掘”。

交互式数据可视化工具的产生并不意味着不再需要静态产品。两种类型的报告(静态的和交互式的)都有不同的作用,这对临床医生都有好处。虽然静态报告的内容有限,因为提问的问题是预先确定的,不能更改,但它们提供的内容实际上掌握在最终用户手中。由于可能在国民医疗服务体系(NHS)内运行的过时/受限的 IT 系统,一些临床医生似乎不愿意使用在线工具,并准备为了稳定性和可靠性而牺牲 DV 工具的交互性。

所使用的互动软件还应在输出方面提供稳定性和可靠性,但也应允许对数据提出的问题进行讨论和变化。假设底层计算机硬件和网络供应,为正确的工作选择正确的工具将是有益的;静态报告提供数据和高级分析的概述,以及允许进一步调查更具体问题的交互式工具。

结论

这些设计原则是作为一个项目的一部分制定的,该项目旨在调查交互式数据可视化是否有助于临床医生改善患者护理。虽然它们旨在与家庭暴力工具和仪表板相关,但总体原则可以推广到任何报告系统。类似地,设计原则可以应用于医疗保健之外的其他领域,在这些领域中,客户的参与将有利于测量结果的工具的设计。

采用这些设计原则可能会鼓励对产品的吸收;最终用户的指导和他们在设计阶段的参与可能会使产品更具吸引力,因为它更“切合目的”。最终,这些原则应该支持和加强一个有用的产品的设计,这个产品需要很少的交付时间,并且像预期的那样运行。

人工智能项目的设计思维

原文:https://towardsdatascience.com/design-thinking-for-artificial-intelligence-projects-87c4bc920c03?source=collection_archive---------30-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Daria Nepriakhina 在 Unsplash 上拍摄的照片

IBM 如何采用设计思维原则来构建人工智能项目的工作流程

为什么要看这篇文章?

IBM 为人工智能项目使用了一个有趣的工作流程,该流程基于设计思维原则,在 Coursera 的专题中有详细展示。这是一个很长的 MOOC,它深入研究了实现人工智能应用程序的细节,如果你有时间和技术知识,这是值得一读的。如果你只对学习工作流以及如何在 AI 项目上实现感兴趣,这篇文章可以帮助你。

什么是设计思维?

设计思维是一种在开发设计概念时使用的思维类型(例如在设计新建筑或技术产品时),它试图从最终用户的角度理解产品。这不仅是通过与用户产生共鸣,也是通过在头脑风暴会议中产生多个想法、原型,然后测试这些想法。因此,这是一个迭代和实践的方法。该过程的主要阶段有:感同身受定义构思原型测试。我不会进入产品创造的设计思维的细节,而是将重点放在这个过程如何适应人工智能项目。

工作流程

IBM 为 AI 项目呈现的工作流如下,在设计思维中有相应的名称:

  • 数据收集 ( 感同身受)
  • 探索性分析 ( 定义)
  • 转化 ( 构思)
  • 造型 ( 原型)
  • 测试 ( 测试)

现在,让我们进一步了解这些步骤的细节。

数据收集

这是数据科学家与最接近数据的人交谈的地方,以阐明业务机会并将其转化为可测试的假设。它包括定义时间表、成本、可行性等。最后,您继续为项目收集数据。

  1. 尽可能接近数据的来源,通常是通过采访相关人员
  2. 识别业务问题
  3. 阐明业务问题,列举可能的问题,并根据领域知识、可行性和影响确定优先顺序(影响可以使用背面的 ROI 计算来衡量)。
  4. 获取所有相关的数据
  5. 将业务问题转化为一个或多个可测试的假设

探索性数据分析

此时,您尝试可视化您的数据,检查丢失的值(并决定如何处理它们),并可能测试假设。这部分由数据可视化假设检验组成。

在构建完整的数据摄取管道之前,从简单的 csv 文件开始分析,以确保您的模型有价值。

数据可视化

检查缺失的数据,了解哪些特征和观察值有缺失值,以及原因(返回“移情”并与客户交谈)

与其他观察值相比,看看缺失的观察值如何表现:

  • MCAR(完全随机缺失):就特征矩阵而言,缺失病例平均来说与非缺失病例相同。完整的病例分析(从数据集中移除那些观察值)将降低分析的功效,但不会影响偏倚
  • MAR(随机缺失):缺失数据通常对测量值有一定的依赖性,模型可用于帮助估算可能的数据。例如,在 MLB 的一项调查中,在回答所有问题时可能存在性别偏见
  • MNAR(非随机缺失):缺失数据依赖于未测量或未知变量。没有可用的信息来解释这一缺失。

如果需要,尝试一些不同的插补方法,但一定要在建模阶段回来重新评估它们,知道哪种方法产生的结果最好。尝试不同插补方法的过程称为多重插补。

  • 单变量插补:缺失特征的平均值或中值
  • 多变量插补:使用其他变量预测缺失特征

创建可视化摘要,详细说明数据,包括缺失值、异常值、不平衡问题分类,并尝试确定对您的特定业务问题有用的因素,并开始制定假设。

使用图表和表格创建第一个演示文稿或报告,讲述与您的业务问题相关的故事(确保所有内容至少有一两行解释主要观点/结论)。最后是结论和对后续步骤的建议。

转换

其目标是转换您的数据,使其可供模型使用。这是所有特性工程魔法发生的地方。

造型

在这一点上,您定义了一个评估标准,并针对您的问题比较了不同的模型。从简单的模型开始,然后逐步建立。

测试测试

这里的目标不仅仅是对你的代码进行单元测试,还包括对你之前所做的选择进行批评,如果需要的话再回头看(通常是这样的)。它以所选解决方案的部署而告终,这也要经过测试:即使是运行的模型也要经过审查和持续的性能测试。

如果您有兴趣了解有关数据科学项目的工作流和项目管理工具的更多信息,您可能也会喜欢这篇文章:每个数据科学家都应该知道的项目管理工作流

设计 3D 医疗保健网络图

原文:https://towardsdatascience.com/designing-a-3d-healthcare-network-graph-291e4f75e9a5?source=collection_archive---------62-----------------------

使用 TigerGraph、Python 和 JavaScript 对医疗保健数据建模的一种很酷的方式

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

三维力导向网络图

介绍

正如我们所知,图形数据库已经彻底改变了世界。在过去的十年里,他们已经在大量的案例中证明了他们的有用性,从社交媒体网络到欺诈检测再到推荐引擎。图形数据库的真正优势是能够有效地表示信息片段之间的关系。这尤其适用于高度关联的数据,如医院记录。

在这篇博客中,我将介绍一个例子,说明我们如何将存储在图形数据库中的医疗保健数据以 3D 形式直观地展示出来。由于大量的连接,2D 网络图可能很快变得混乱和不可读;然而,这些问题可以通过改变我们的视角来解决。在 2D 选项失败的情况下,3D 图形提供了更容易看到的数据的扩展视图。

因为数据存储在图形数据库中,所以用图形可视化才有意义。这样,我们所要做的就是将数据库中已经存在的连接转换成可见的东西。

有了这样的背景,让我们开始制作我们的 3D 图形杰作吧!

这个博客的完整代码可以在我的 Github 上找到。

设计图形数据库模式

我在这个项目中使用的图形数据库是建立在 TigerGraph 的基础上的,使用的是由一个叫做 Synthea 的整洁的开源程序生成的合成病人数据。如果你对 Synthea 不熟悉,可以看看我写的这个短博客或者看看他们的网站

如果你有兴趣看看我用来设计这个医疗网络的过程,可以看看我的 上一篇博文

否则,请随意设计您自己的图表或使用预制的图表。TigerGraph 有大量的教程和例子可以帮助你设计自己的图形。或者,你可以参考我写的一篇文章,这篇文章将带你了解一般的图形设计过程。

从这一点开始,我提到的一切都可以用任何图形来完成。

访问图表

为了访问我们的图表,我们将使用由 Parker Erickson 创建的 pyTigerGraph Python 连接器。安装并导入软件包后,您可以使用以下代码连接到您的图形服务器:

连接到 TigerGraph

如果您没有令牌,您可以创建一个带有密码的令牌。

接下来,运行一个已安装的查询来从图表中获取数据。

运行 GSQL 查询

以下是查询。它会抓取所有患者以及与这些患者直接相关的所有边和顶点。

CREATE QUERY grab_All_3d_demo() FOR GRAPH MyGraph { 

 ListAccum<EDGE> @@edgeList;

 Seed = {Patient.*}; data = SELECT s FROM Seed:s -(ANY:e)-ANY:t ACCUM @@edgeList +=e;
 other = SELECT t FROM Seed:s -(ANY:e)-ANY:t;

 print data;
 print other;
 print @@edgeList;
}

格式化数据

当我们运行查询时,它会返回大量信息。我们可以尝试绘制所有进来的数据(本质上是绘制这些患者的大多数医疗保健接触点),但我们的图表最终会看起来非常混乱。因此,我们将只获取数据的一部分。

我选择了这些病人,他们的地址,以及他们一生中的任何过敏反应或影像学研究。

解析传入数据

这段代码可能有些混乱,所以让我们仔细分析一下到底是怎么回事。

  1. 首先,提取与 GSQL 查询中的 3 个 print 语句相对应的 3 个列表。
  2. 接下来,创建两个名为节点链接的列表。这些将包含我们的三维图形的顶点和边。
  3. 现在,抓取代表患者、地址、过敏或成像研究的所有节点。对于每个节点,我们添加三个属性: id描述id 是图形用来建立连接的标识符。描述是当鼠标悬停在节点上时出现的文本,而用于给节点着色。
  4. 对于每个环节,我们也有三个属性:目标属性再次对应于着色。目标属性对应于该边的源和目标顶点的 id。
  5. 最后,将这两个列表添加到 JSON 格式的字典中。这一步非常关键,因为我们的 JavaScript 函数无法识别其他格式的数据。

这样,数据现在就可以使用了!

用 Flask 传递数据

为了让我们的 JavaScript 函数实时接收来自 Python 的图形数据,我们需要设置一个服务器。我们将使用烧瓶来完成。我们所要做的就是将我们已经创建的函数包装在 Flask web 服务器结构中。完整的 Python 代码现在看起来应该是这样的:

最终 python 代码

这个项目的 python 部分现在已经完成了!

创建图表

这个可视化的核心是 3D 力图包。这个包建立在 ThreeJS 和 WebGL 之上,使得生成力定向图变得非常简单。

像大多数 web 应用程序一样,这个网络图可视化是使用 HTML、JavaScript 和 CSS 构建的。让我们分别看一下这些组件。

超文本标记语言

这个项目的 HTML 非常简单。

网站的 HTML

关键部件:

—三维力图包

— CSS 样式表

— JavaScript 代码(dataset-loader . js)

半铸钢ˌ钢性铸铁(Cast Semi-Steel)

这里没什么特别的。

网站的 CSS 文件

Java Script 语言

生成图表的 JavaScript 代码

让我们再次将这段代码分解成更小的步骤。

  1. 使用 fetch 语句从我们的 Flask 服务器获取数据
  2. 使用 3D-Force-Graph 软件包生成我们的图形
  3. 指定图形属性(即按组着色,将悬停数据设置为“描述”)
  4. 创建一个循环,使图形旋转。为什么?因为旋转图太牛逼了!

CORS 问题

如果您试图按原样运行这段代码,很可能会遇到 CORS 错误。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

CORS 误差

你可以在这里阅读关于 CORS 问题的文章。要解决这个问题,您需要指定允许数据流动的响应头。我用谷歌浏览器的 Moesif Origin 和 CORS 转换器扩展解决了这个问题。如果您在本地运行该程序,这将非常有用。然而,如果您想要部署该图,您将需要在 FlaskJavaScript 上配置适当的设置。

有趣的东西

这是所有的代码。现在,我们剩下要做的就是运行服务器,欣赏它的辉煌。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

通过不多的代码,我们收集了存储在图形数据库中的大量数据,并创建了一个令人惊叹的 3D 可视化来显示这些数据。我们使用 TigerGraph 来存储医疗保健信息,使用 Python 来提取和处理我们的数据,使用 JavaScript 和 HTML 来创建 3D 视图。这个过程并不复杂,但会产生非常酷的结果。这篇博客中展示的方法也可以用在医疗行业之外。任何处理高度关联数据的领域都可以从图形中受益,利用图形数据库存储信息的能力和 3D 网络图显示信息的能力。

我希望你喜欢阅读这个博客,并学到一些新的东西!让我知道你的想法,并在 LinkedIn 上与我联系。

[## 阿卡什·考尔-数据科学实习生-未来学家学院| LinkedIn

查看阿卡什·考尔在全球最大的职业社区 LinkedIn 上的个人资料。阿卡什有 5 个工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/akash-kaul-6a8063194/) [## akash-kaul/3d 网络图可视化

在 GitHub 上创建一个帐户,为 akash-kaul/3d 网络图可视化开发做出贡献。

github.com](https://github.com/akash-kaul/3d-network-graph-visualization.git)

使用 Python 设计聊天机器人:一种改进的方法

原文:https://towardsdatascience.com/designing-a-chatbot-using-python-a-modified-approach-96f09fd89c6d?source=collection_archive---------20-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

亚历山大·奈特Unsplash 上拍照

机器如何解释人类语言?

在当今时代,聊天机器人已经变得非常流行。高度发达的聊天机器人,如 Siri、Cortana 和 Alexa,已经让人们对其智能和能力感到惊讶。聊天机器人实际上被定义为:

聊天机器人可以像简单的程序一样简单,用一行响应回答简单的查询,也可以像数字助理一样复杂,在收集和处理信息的过程中学习和发展,以提供越来越高的个性化水平。

在很多文章中,我看到过一个基本的评论-回复模型。我的尝试是看看我们是否可以更进一步,在更广泛的基础上修改用户评论,并可能使用简单的 web 请求、自动化和抓取为聊天机器人提供其他功能。

在我们开始之前,我想让你知道一些事情,我们在看什么。我们不会看到像 Siri 这样超级智能的聊天机器人,因为它需要丰富的经验和专业知识。现在,如果我们认为,如果我们的聊天机器人可以帮助我们预订酒店,为我们播放歌曲,告诉我们天气预报,等等,这将是非常酷的。我们将尝试在我们的聊天机器人中使用一些基本的 python web 处理库来实现所有这些功能。我们将使用 NLTK 或 Python 的自然语言工具包库。那么,我们开始吧。

聊天机器人根据其设计主要有两种类型

  1. 基于规则
  2. 自学的

我们将使用两者的组合版本。通常,在基于规则的方法中,设置了一组基本规则,聊天机器人只能以受限的方式对这些规则进行操作。对于自学版本,神经网络用于训练聊天机器人根据一些交互训练集来回复用户。对于任务部分,我们将使用基于规则的方法,对于一般的交互,我们将使用自学的方法。我发现这种结合的方法比完全自学的方法更有效。

NLTK 图书馆的工作

在进入应用程序之前,让我们看看 NLTK 是如何工作的,以及它是如何在自然语言处理中使用的。自然语言处理有 5 个主要组成部分。它们是:

  • 词法和词汇分析
  • 语法分析
  • 语义分析
  • 话语整合
  • 语用分析

**词法和词法分析:**词法分析描绘了对单词结构的分析、识别和描述。它包括将文本分成段落、单词和句子。

**句法分析:**单词通常被认为是最小的句法单位。句法是指支配任何一种语言的句子结构的原则和规则。句法关注单词的正确顺序,这可能会影响其含义。

**语义分析:**该组件将单词的线性序列转换成结构。它显示了单词之间的联系。语义学只关注单词、短语和句子的字面意义。

**语篇整合:**指对语境的感知。任何一个句子的意思取决于这些句子。它还考虑了下面这句话的含义。

语用分析:语用分析研究整体的交际和社会内容及其对口译的影响。它意味着抽象或推导出语言在各种情况下的有意义的用法。

现在,让我们来谈谈用于实现这五个组件的方法或函数:

标记化:标记化是将大量文本分割成称为标记的较小部分的过程。它接受一个句子,并将其分解成最小的可提取单元或单词。

**词性标注:**在自然语言处理中是非常有用的工具。我们知道,各种词类,如动词、名词、形容词等等。现在,如果能标记出一个单词属于哪个词类,我们就很容易理解句子的上下文了。

**词汇化:**这个操作是 NLP 的另一个非常有用的工具。使用这种操作,具有相同含义但根据上下文或句子有一些变化的单词被带到它们的词根。这对模式匹配和基于规则的方法非常重要。

所有这些工具都是由 python 的 NLTK 库提供的。现在,让我们来看看自学习算法是如何工作的。

自学习算法的工作原理

我们使用单词包算法来训练我们的模型。我们有一个包含所有意图和输入模式的文件。看起来像是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到,这里有一个“标记”字段,它实际上描述了意图。意图通常是术语,是给定句子背后的实际主题或动机。例如,这里有像“介绍”、“感谢”、“问候”和“再见”这样的意图,它们基本上是动机。其次,我们有一个“模式”字段,它实际上描述了具有相应动机的句子的模式或类型。然后我们有 responses 字段,其中包含一些响应,如果检测到相应的动机,这些响应可能是机器人的响应。例如,对于“标记”或意图的“问候”模式,检测到的可以是“你好”,“你好”,相应的回应可以是“你好”,“你好”。

现在,我们从模式中一个接一个地挑选出所有独特的单词,将它们词条化,转换成小写,然后附加到它以创建一个单词列表。这个列表看起来会像这样:

【‘嗨’,‘那里’,‘怎么样’,‘是’,‘你’,…………………】。什么’,‘能’,‘做’]

这将是我们模型训练的词汇包。现在,我们需要对列表进行一次性编码,以创建编码向量,然后将这些向量作为训练集拟合到模型中。

然后,我们有标签,也放在一个列表中。看起来是这样的:

[‘问候’,‘再见’,‘谢谢’……………………]

这也是一个创建列表的热编码,该列表将作为我们训练模型的目标数据。现在,我们该怎么做呢?

首先,我们获得过滤的单词列表包。在我们的例子中,单词列表的长度是 47。现在,我们创建一个大小为 47 的列表,并用 0 标记所有的索引。然后,我们将对应于输入句子中出现的单词的索引标记为 1。例如,输入句子是“你好”。那么列表就变成了:

[1,1,0,0,0,…………….]

只有对应于“hi”和“there”的索引是 1,而所有其他的都是 0。这些编码的向量是从我们批处理中的所有输入语句中获得的。因此,如果批量大小为 n,我们有 n x 47 个列表,它是训练集的 X 值的输入维度。

同样,我们也设定了目标。我们有 7 个标签。因此,我们创建一个大小为 1 的列表。对应于由输入语句表示的标签的标签索引是 1,而所有其他的都是 0。例如,在我们的训练数据集中,“你好”的标签是“问候”。因此,对应于问候标签的索引是 1,所有其他的索引是 0。因此,如果批量大小为 n,我们有 n x 7 个列表,它是 Y 值的输入维度或训练集的目标值。

所有意图模式中出现的每个句子构成了我们的总数据集。在这些数据集的基础上训练该模型。

**用途:**现在当用户输入一个句子或语句时,它也被标记化,词条化,转换成小写。然后,在对来自用户的数据进行预处理之后,我们使用我们的词汇表对用户数据进行编码,并形成 47 长度的编码向量。我们用这个向量来拟合我们的模型,这给了我们用户语句的预测标签。然后,我们从响应列表中找到对用户声明的随机响应。

应用

让我们直接进入代码:

from nltk.tokenize import word_tokenize
import nltk
from nltk.stem import  WordNetLemmatizer
import re
lem = WordNetLemmatizer()def filter_command(phrase):
 tokens=[]
 tok=word_tokenize(phrase)
 for t in tok:
  tokens.append(tok.lower())
 tags = nltk.pos_tag(tokens)work=[]
 work_f=[]
 subject=[]
 number=[]
 adj=[]
 query=[]
 name=0
 for tup in tags:
  if "VB" in tup[1]:
   work.append(tup[0])
  if "CD" in tup[1]:
   number.append(tup[0])
  if "JJ" in tup[1]:
   adj.append(tup[0])
  if "NN" in tup[1]:
   subject.append(tup[0])
  if "W" in tup[1] and "that" not in tup[0]:
   query.append(tup[0]) 
 for w in work:
  work_f.append(lem.lemmatize(w.lower()))
 if query:
  if "you" in tokens or "your" in tokens:
   task=0
  elif 'weather' not in tokens or 'news' not in tokens or 'headlines' not in tokens: 
   task=1
 elif 'play' in work_f or 'song' in subject or 'play' in subject:
  task=2
 elif 'book' in work_f or 'book' in tokens[0]:
  task=3
 elif 'weather' in subject:
  task=4
 elif 'news' in subject or 'headlines' in subject:
  task=5
 else:

  if '?' in tokens and 'you' not in tokens and 'your' not in tokens:
   task=1
  else:
   task=0 

 return task,work_f,subject,number,adj,query

这是我们的主库代码,它是我们基于规则的学习和自学之间的融合区域。用户发送一条消息,该消息被该代码接收,并且该代码对该消息进行分类。换句话说,它告诉我们该语句是分配了一些任务,还是只是一个普通的随意对话。

这里我们将首先标记语句,然后标记词性。现在,如果它是一个问题,就会有一个问号,或者有一个‘wh’术语。如果检测到这些特征,则该语句被分类为查询,并采取相应的动作。同样,如果我们想要天气或新闻,这些术语将作为语句的主题出现。如果语句不是已定义的查询或任务,则任务被赋值为 0,并由我们的自学者模型接管,该模型现在将尝试对语句进行分类。

from create_response import responseflag=0
while(flag==0):
        user_response = input()
        flag=response(user_response)

这是我们的呼叫模块。它在 while 循环中运行,直到响应函数将标志定义为 1。

import json
from preprocess_predicted import predict_c
from lib import filter_command
import random
from support import search_2,play,book,get_weather,get_news_update,scrapedef get_res(res):
 with open('intents.json') as file:
  intents=json.load(file)
 tag = res[0]['intent']
 all_tags = intents['intents']
 for tags in all_tags:
  if(tags['tag']== tag):
   result = random.choice(tags['responses'])
   break
 return result,tagdef response(phrase):
 flag_1=0
 task,work_f,subject,number,adj,query=filter_command(phrase)
 if task==0:
  res_1=predict_c(phrase)
  result,tag=get_res(res_1)
  if tag=="noanswer":
   results="Here are some google search results"
   search_2(subject,phrase)
  if tag=='goodbye':
   flag_1=1elif task==1:
  scrape(phrase)
  result="Here are some results"elif task==2:
  play(phrase,subject)
  result="Here you go"elif task==3:
  book(phrase)
  result="Here are some results"

 elif task==4:
  get_weather()
  result="Here are the results"elif task==5:
  get_news_update()
  result="Here are the results"else:
  result="Sorry, I don't think i understand"
 print(result)
 return flag_1

这是我们的驱动响应创建器代码。它从调用者那里接收用户语句。然后调用 filter_command()返回是否检测到任何分类任务。这里我们有 6 个任务(0-5)。0 表示未检测到任务。任何带有“?”的“wh”查询或语句由 scrape()代码段处理。类似地,任务 2 是播放 youtube 视频,任务 3 是预订机票或房间,任务 4 是天气新闻。最后,5 是新闻更新。0 调用自学习模型。

所有任务处理程序都在支持文件中定义。他们主要使用 Selenium automation 和 web scraping。让我展示其中的三个。

def play(message,subject):
    result=message
    ext="[https://www.youtube.com/results?search_query=](https://www.youtube.com/results?search_query=)"
    messg=result.replace(" ","+")
    msg=ext+messgdriver = webdriver.Chrome()
    wait = WebDriverWait(driver, 3)
    presence = EC.presence_of_element_located
    visible = EC.visibility_of_element_locateddriver.get(msg)
    wait.until(visible((By.ID, "video-title")))
    names=driver.find_elements_by_id("video-title")
    i=0
    for name in names:
        print(name.text)
        if len(subject)==2:
         s=subject[1]
        else:
         s=subject[0]
        if s not in name.text.lower():
            i+=1
            continue
        else:
            break#driver.quit()
    print(i)
    driver.find_elements_by_id("video-title")[i].click()
    url = driver.current_url
    time_prev= int(round(time.time()))
    #video=pafy.new(url)
    #print((driver.find_elements_by_xpath("//span[[@class](http://twitter.com/class)='ytp-time-duration']")[0]).text)
    s=driver.find_elements_by_xpath("//html/body/ytd-app/div/ytd-page-manager/ytd-search/div[1]/ytd-two-column-search-results-renderer/div/ytd-section-list-renderer/div[2]/ytd-item-section-renderer/div[3]/ytd-video-renderer[1]/div[1]/ytd-thumbnail/a/div[1]/ytd-thumbnail-overlay-time-status-renderer/span")[0].text
    #s="10:00"
    time_k=int(s.split(':')[0])*60+int(s.split(':')[1])
    boo=True
    while boo:
        time_now=int(round(time.time()))
        if time_now-time_prev==int(time_k+2):
            driver.quit()
            boo=False

这是 youtube 自动化。它搜索视频,并挑选视频标题。它在标题中搜索邮件的主题。这样做是为了避免广告视频出现在推荐视频列表的顶部。因此,我们需要注意在语句中提供正确的名称。另一个问题是“s”值。这应该使用 Xpath 来保留视频长度,以便我们可以在视频结束后关闭驱动程序。但是由于 Youtube 经常改变其源代码,这有时会产生错误。它可以通过 API 解决,但是我不喜欢使用它们。

下一个是新闻刮刀:

def get_news_update():
    url="[https://www.telegraphindia.com/](https://www.telegraphindia.com/)"
    news = requests.get(url)
    news_c = news.content
    soup = BeautifulSoup(news_c, 'html5lib')
    headline_1 = soup.find_all('h2', class_="fs-32 uk-text-1D noto-bold uk-margin-small-bottom ellipsis_data_2 firstWord")headline_2 = soup.find_all('h2',class_="fs-20 pd-top-5 noto-bold uk-text-1D uk-margin-small-bottom ellipsis_data_2")headlines=[]
    for i in headline_1:
        h=i.get_text()[1:]
        headlines.append(h)
    for i in headline_2:
        h=i.get_text()[1:]
        headlines.append(h)
    for i in headlines:
        l=i.split()
        new_string = " ".join(l)
        print(new_string)

这是头条新闻刮板代码。我们用《电讯报》作为我们新闻标题的来源。它有两种类型的标题,以两类为标志。我们把两者都刮了下来,在汤的帮助下,我们提取出了代码。

接下来,最后,让我们看看查询应答器代码。也是刮刀的一种。

def scrape(phrase):
    flag=0
    ext="[https://www.google.com/search?q=](https://www.google.com/search?q=)"
    links=search(phrase, num=5, stop=5, pause=2)
    msg=phrase.replace(" ","+")
    url=ext+msg
    i=0
    for link in links:
        i+=1
        if 'wikipedia' in link:
            flag=1
            l=link
            breakif flag==1:
        wiki = requests.get(l)wiki_c = wiki.content
        soup = BeautifulSoup(wiki_c, 'html.parser')
        data=soup.find_all('p')
        print("Source:wikipedia")print(data[0].get_text())print(data[1].get_text())
        print(data[2].get_text())
        print(data[3].get_text())

    else:
        print("wikipedia Source not available")
    print("Providing searanch results")
    webbrowser.open(url,new=1)
    time.sleep(3)

在这里,我们从 google 搜索中获得结果选项,如果维基百科页面在搜索结果中,我们抓取它以提供该页面的前 4 段。如果找不到维基链接,我们只需进行基本的谷歌搜索。

现在,让我们转到自学模型部分。

这里,首先是数据预处理部分:

import nltk
from nltk.stem import WordNetLemmatizer
lem = WordNetLemmatizer()
import json
import pickledef preprocess():
 words=[]
 words_f=[]
 tags=[]
 docs=[]
 ignore_words = ['?', '!',',','.']
 with open('intents.json') as file:
  intents=json.load(file)for i in intents["intents"]:
  for pattern in i['patterns']:
   w=nltk.word_tokenize(pattern)
   words.extend(w)docs.append((w, i['tag']))if i['tag'] not in tags:
    tags.append(i['tag'])for w in words:
  if w in ignore_words:
   continue
  else:
   w_1=lem.lemmatize(w.lower())
   words_f.append(w_1)
 words_f = sorted(list(set(words_f)))pickle.dump(words_f,open('words.pkl','wb'))
 pickle.dump(tags,open('tags.pkl','wb'))
 return words_f,tags,docs

此代码用于预处理。众所周知,在所有标签下检测到的 all_patterns 中的所有模式都被标记化了。将标记化后的单词放入一个列表中。所以,这些列表有重复的值。相应的标签也保存在“标签”列表中。文档列表正在以(tokenized_words,tag)格式保存元组。所以,它被保存为例如([‘hi ‘,’ there’],’ greeting ')。

现在,word_f 列表是一个更纯粹的列表版本,没有重复的单词。

from preprocessing import preprocess
from nltk.stem import WordNetLemmatizer
lem = WordNetLemmatizer()
import numpy as np
import randomdef data_creator():
 words,tags,docs=preprocess()out_array=[0] * len(tags)
 train=[]for doc in docs:bag_of_words=[]
  patt=doc[0]
  patt_f=[]
  ## Accessing the first part of a tuple (word,tag)for pat in patt:
   p=lem.lemmatize(pat.lower())
   patt_f.append(p)for word in words:
   if word in patt_f:
    bag_of_words.append(1)else:
    bag_of_words.append(0)# Creating vector of wordsoutput_req=list(out_array)
  output_req[tags.index(doc[1])] = 1
  #print(len(bag_of_words))
  #print(len(output_req))
  train.append([bag_of_words, output_req])
 random.shuffle(train)
 train=np.array(train)
 X_train=list(train[:,0])
 Y_train=list(train[:,1]) 
 print("1")
 np.save('X_train.npy',X_train)
 np.save('Y_train.npy',Y_train)

这里,形成了单词或编码向量的包。这个片段在我们的文档中挑选单词标记化的部分来创建编码的向量,这些向量是我们形成的 X 训练集的一部分,并且它们相应的标签也被编码以形成我们训练集的 Y 训练或目标值。

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation, Dropout
from tensorflow.keras.optimizers import Adam
import numpy as np
from training_data_creation import data_creator
def model_c():
 data_creator()
 X=np.load('X_train.npy')
 Y=np.load('Y_train.npy')
 model = Sequential()
 model.add(Dense(32, input_shape=(len(X[0]),), activation='relu'))
 model.add(Dropout(0.2))
 model.add(Dense(64,activation='relu'))
 model.add(Dropout(0.3))
 model.add(Dense(128, activation='relu'))
 model.add(Dropout(0.3))
 model.add(Dense(len(Y[0]), activation='softmax'))adam=Adam(lr=0.001)
 model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])
 return model,X,Y

我们的模型以及训练数据的训练(X)和目标(Y)集由函数返回。我们的模型有两个隐藏层。它使用分类交叉熵作为损失函数,并在最后一层激活 Softmax。我们在这里使用了“亚当”优化器。

import tensorflow as tf
from model import model_cdef train():
 callback=tf.keras.callbacks.ModelCheckpoint(filepath='chatbot_model.h5',
                                           monitor='loss',
                                           verbose=1,
                                           save_best_only=True,
                                           save_weights_only=False,
                                           mode='auto')
 model,X,Y=model_c()
 model.fit(X, Y, epochs=500, batch_size=16,callbacks=[callback])train()

我们的模型在 500 个历元时被训练,只保存最佳权重。

import nltk
from nltk.stem import WordNetLemmatizer
lem = WordNetLemmatizer()
import numpy as np
import pickle
import tensorflow as tf
import randomdef preprocess(phrase):
 words=nltk.word_tokenize(phrase)
 words_f=[]
 for word in words:
   w=lem.lemmatize(word.lower())
   words_f.append(w)
 #print("****************")
 #print(words_f)return words_fdef bag_of_words(phrase,words):
 obt_words=preprocess(phrase)bag_of_words=[0]*len(words)for o in obt_words:
  for w in words:
   #print(o)
   #print(w)
   if o==w:
    #print("A")
    bag_of_words[words.index(w)]=1b_n=np.array(bag_of_words)
 return b_ndef predict_c(phrase):
 model=tf.keras.models.load_model('chatbot_model.h5')
 words = []
 with (open("words.pkl", "rb")) as openfile:
  while True:
   try:
    words.append(pickle.load(openfile))
   except EOFError:
    break
 tags = []
 with (open("tags.pkl", "rb")) as openfile:
  while True:
   try:
    tags.append(pickle.load(openfile))
   except EOFError:
    break
 #print(words)
 #print(tags)
 #print(phrase)
 to_pred=bag_of_words(phrase,words[0])
 #print(to_pred)
 pred=model.predict(np.array([to_pred]))[0]
 threshold=0.25
 results = [[i,r] for i,r in enumerate(pred) if r>threshold]
 results.sort(key=lambda x: x[1], reverse=True)
 return_list = []
 for r in results:
  return_list.append({"intent": tags[0][r[0]], "prob": str(r[1])})
 return return_list

上述代码用于模型预测的新用户语句的预处理。它涉及到转换成小写和词汇化。然后,使用我们的词汇形成编码向量,并将其发送到模型进行预测。机器人响应取决于预测的标签。

这就是我们 Bot 运作的整体流程。

结果

短片展示了我们的机器人的使用和动作。我想我的设备中的 CUDA 存在一些版本问题。所以,我收到了一些警告,但我认为这没什么好担心的。

挑战

该领域存在一些缺点和挑战。例如,词性标注,在标注‘玩’字的同时,有时标注为名词,有时标注为动词。类似地,这个问题也存在于“书”的问题中,这里我已经处理了异常,但是在真实世界的大场景中,这些事情会很重要。如果我们使用自我学习模型,情况不会太糟。自学模型面临的挑战是,它们需要一个庞大的训练集,需要手动设计。所以,这就是为什么聊天机器人通常是为特定目的服务的,比如处理前台客户的投诉和互动,并记录问题。但是,目前它们正以非常快的速度发展。希望,不久我们将会看到更多进化的机器人。

结论

在这篇文章中,我们谈到了一种方法,一个基本的计划聊天机器人可以被赋予一些功能。我希望这有所帮助。

这里是 Github 链接

设计数据科学竞赛是一种很好的学习方式

原文:https://towardsdatascience.com/designing-a-data-science-competition-is-an-excellent-way-to-learn-69e6fd582702?source=collection_archive---------51-----------------------

意见

我们让学生们创造 ML 挑战,这就是他们所学到的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

在过去的几年里,作为国际合作的一部分,我们探索了让学生参与组织和参与挑战作为一种教学工具的好处。参与竞赛的设计和解决可以被视为学习适当的实验设计和分析以及更深入地理解机器学习的其他方面的动手手段。南巴黎大学(法国巴黎)的研究生参与的班级项目,创建端到端的挑战,从定义研究问题、收集或格式化数据、创建启动工具包,到实现和测试网站。数据的应用领域和类型极其多样:医学、生态学、市场营销、计算机视觉、推荐、文本处理等。由此产生的挑战然后被用作本科生的课堂项目,他们必须解决这些问题,无论是在南巴黎大学还是在伦斯勒理工学院(RPI,美国纽约),以提供大规模的丰富学习体验。今年,学生们参与了由“AI for good”激发的挑战,并将创建可重复使用的模板来激励其他人为了人类的利益而创造挑战。

教学动机

在过去的几年里,挑战在教学中变得无处不在。例如,ka ggle“in class”有数百场比赛。在教学中使用竞赛的好处包括激励学生和促进评分。然而,到目前为止,很少让学生参与竞赛的设计和实施。显然,这是一项更加困难的任务,最复杂的挑战可能需要几年的成熟和成熟研究人员的参与。然而,相对简单的竞赛,其难度水平可用于训练本科生,研究生可以很容易地设计和实施,作为课堂项目的一部分(通常是分类和回归问题,偶尔也解决推荐和强化学习问题)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这使他们能够获得实验设计的实际操作,并通过定义油井任务和指标、收集和准备数据(确保有足够的样本且不存在偏差或数据泄漏)、准备基线方法,以及提出他们的挑战以吸引尽可能多的参与者来解决这些问题,来克服这些困难。

在这个过程中,学生还学习团队工作,满足严格的截止日期,并获得 Python 的编程技能,包括掌握 scikit-learn 和 Keras 等工具包,以及良好的编码实践,包括使用 Github 进行版本控制和使用 dockers。重点放在创建一个完全工作的端到端“产品”(一个挑战),然后由真正的“客户”(本科生)使用。通过让研究生制作一个简短的广告视频,并在课堂上向本科生展示他们的挑战,本科生可以选择其中一个作为他们的项目,也强调了沟通的质量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

自 2016 年以来,我们一直在开展这种类型的教育项目。每年有 30 至 40 名研究生在数据科学硕士项目中提出挑战,约 100 名二年级本科生在 12 周的项目期内解决这些挑战。因此,我们已经通过这个项目培训了 500 多名学生。我们已经招募了几位校友作为更大研究挑战的共同组织者,这些挑战被选为 NeurIPS 竞赛计划的一部分,如 TrackML 粒子物理挑战AutoDL 挑战

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

社区影响

让研究生参与挑战的设计具有重要而深远的影响。随着当前人工智能研究和应用的快速增长,既有前所未有的机遇,也有对其潜在滥用的合理担忧。在这种情况下,提高学生对与研究设计和建模相关的良好数据科学方法的认识非常重要。认识到没有好的数据就没有好的数据科学,我们希望教育他们进行适当的数据收集和准备。我们的目标是灌输良好的实践,以减少因数据偏差或因缺乏数据导致的不可再现结果而导致的问题。我们还鼓励通过使用软件用真实的合成数据代替真实数据来保护数据的机密性或隐私。这有助于拓宽本科生接触具有商业价值或可能伤害个人的机密或私人数据的渠道。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

codalab.lri.fr 和【codalab.lri.fr】的学生竞赛

今年,我们教育项目的一个新的补充方面是使用占位符数据(例如,如上所述的合成数据),将已设计的挑战转化为简化的模板,并包括现成的入门解决方案。这种模板将展示各种各样的数据驱动的人工智能应用,以引发全球研究人员的想象力,而无需特定的人工智能专业知识。通过简单地克隆模板和替换数据,组织可以立即获得基线结果,并最终通过将挑战作为内部或外部竞赛来完善它们。为了促进这一进程,我们将免费提供我们的开源挑战平台 Codalab ,并将根据挑战组织者的优点和需求,在该平台上提供额外的计算资源。

除了便于其他讲师重复使用我们的挑战,传播我们的挑战模板也将有利于渴望将人工智能解决方案引入新领域的低预算企业家。最后,想要为“AI for good”做贡献的志愿者将有一个平台,通过克隆挑战模板来快速整合应用程序。我们相信这将是对 AI 民主化的重要贡献。

结论

教学生组织和参与机器学习竞赛,为他们成为数据科学家做好准备,同时帮助我们培养一个具有良好实践的挑战组织者社区,并传播挑战模板,这可以有助于传播 AI for all 和 AI for good。

承认

许多人参加了这个项目。伊莎贝尔·盖恩和克里斯汀·贝内特担任教师;迪维扬·卡兰塔恩和李生·孙·霍索亚为助教。我们非常感谢 Eric Carmichael 和 Tyler Thomas 开发和维护挑战平台 Codalab 以及教学工具 ChaLab 和 Chagrade,并感谢助教刘正英和巴尔萨扎·多农以及包括 Magali Richard、Guillaume Charpiat 和 Antoine Marot 在内的班级导师。该项目由 ChaLearn、Isabelle Guyon 的巴黎萨克莱大学“大数据”主席、欧盟 HADACA 项目(EIT Health)和联合卫生基金会(煽动项目,RPI,纽约)提供部分资助。

a .帕瓦奥、d .卡兰塔恩、l .孙-霍索亚、k .贝内特和 I .盖永。实验设计与分析:教学中的挑战方法。 CiML 工作坊,NeurIPS 2019。

用 Python 设计要素选择管道

原文:https://towardsdatascience.com/designing-a-feature-selection-pipeline-in-python-859fec4d1b12?source=collection_archive---------9-----------------------

用 PYTHON 进行机器学习

如此强大,以至于你的奶奶会试着用它来代替她那经验丰富的铸铁锅

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

汉斯·维维克在 Unsplash上的照片

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**目的:**用 Python 设计开发特征选择流水线。

**材料和方法:**使用 Scikit-learn,我们为一个分类任务生成一个 Madelon 样的数据集。我们的工作流程的主要组成部分可以总结如下:(1)生成数据集(2)创建训练集和测试集。(3)应用特征选择算法来减少特征的数量。

硬件:我们在配备英特尔酷睿 i7–8700 处理器(12 个 CPU,3.70 Ghz)和英伟达 GeForce RTX 2080 的工作站上训练和评估我们的模型。

**注意:**如果你是从零开始,我会建议你按照这篇文章安装所有必要的库。最后,假设读者熟悉 Python、 PandasScikit-learn 。这篇文章的全部内容可以在我的 GitHub 上找到。欢迎你来叉它。我不得不提到一些特征选择方法是从 Will Koehrsen 的文章中得到启发的。

符号:粗体文本将用于表示 Python 对象,例如列表、字典、元组、数据帧,或者将引用一个图形或脚本。This notation will be used to represent classes and function parameters as well as Python packages.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

特征选择

特征选择是从更大的群体中识别特征的代表性子集的过程。用户可以选择手动选择功能,也可以应用多种自动方法中的一种。手动选择特征的困难在于它需要关于手边数据的专业知识。例如,在放射肿瘤学中,放射治疗计划(其中每个体素代表一个特征的 3D 图像)被简化为一系列手工制作的特征,并且被几十年的放射治疗研究和合作临床调查所支持。这些特征中的每一个都量化了放射治疗计划的具体特征,这些特征已经被证明与患者的临床结果相关。令人欣慰的是,用于特征选择的自动化方法已经被开发出来,并且可以很容易地用于减轻这项任务;然而,我们必须有保留地应用这些自动化方法,因为它们可能会导致错误的结论。根据我的经验,我认为应用特性选择方法的最佳方式是使用领域知识和自动化方法来确定一个有代表性的特性子集。

在机器学习的背景下,人们从特征选择中获得的优势是很多的。例如,找到最具描述性的特征可以降低模型的复杂性,使找到最佳解决方案变得更容易,最重要的是,它减少了训练模型所需的时间。此外,如果你理解了典型特征的含义,你将对你所面临的问题有更深的理解。在某些情况下,可以获得轻微的性能提升。必须注意的是,通过从系统中删除特性,您的模型的性能可能会稍微差一些(因为您试图用更少的信息进行预测)。

通常情况下,我们没有多余的时间来对我们的数据进行彻底的研究,以确定要制作什么功能以及如何使用它们。面对超过 1000 个特征的数据集,确定特征的代表性子集的任务似乎令人生畏,但幸运的是,冗余是我们的数据可以成为我们的朋友。通常,当面对具有+1000 个特征的数据集时,您会注意到很大一部分特征高度相关(冗余),与结果无关,或者只是噪声。从开始的+1000 个特征中,您可能最终会有 10 个特征“充分地”代表了整个数据集。

在本文中,我们将讨论以下特征选择算法及其局限性:

  • 一种过滤方法,可移除可变性很小的要素
  • 移除高度相关要素的过滤方法
  • 递归特征消除(RFE ),用于确定最大化模型性能所需的特征子集
  • 确定与结果相关的特征子集的 Boruta 方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

安装必要的软件包

在深入本文之前,让我们安装必要的包。我们将假设读者已经安装了以下包的 Anaconda:NumpySeabornMatplotlibPandasSklearn

你可能遗漏的唯一一个包是BorutaPy,所以让我们来处理它。打开您的终端(如果您在 Mac 上)或 Anaconda 提示符(如果您在 Windows 机器上)。激活您的环境并运行以下命令:

conda install -c saravji boruta

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用 Mac 终端在名为 PythonFinance 的 Anaconda 环境中安装 BorutaPy。

你需要访问我的 GitHub 这里并下载工具文件夹。本文的全部内容都在名为 FeatureSelectionPipe.py 的文件中

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

把 tools 文件夹放在你的工作目录下,你就设置好了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以在我们开始之前,让我们导入所有的包。

脚本 1 —导入所有必需的包。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据

我们将创建多组合成特征,以探索不同特征选择算法的性能和有效性。首先,我们将生成一个类似 Madelon 的合成数据集。Madelon 数据集(我们不会使用)是一个人工数据集,它包含放置在边长为 1 的五维超立方体顶点上的 32 个簇。聚类被随机标记为 0 或 1 (2 类)。我们将生成的类似马德隆的数据集将包含 100 个特征,其中 10 个特征将提供信息,50 个将是冗余的(但提供信息),25 个将重复,15 个将是无用的,因为它们将充满随机噪声。总共,我们将有 1000 个样品。为了给数据增加一点噪声,我们将随机翻转 5%的标签。第二组功能将包含 3 个关键的重要功能。通过自动特征选择算法来选择设计的关键重要特征应该是具有挑战性的。最后,最后一组特性只是将类似 Madelon 的特性和关键特性添加到一个更大的数据集中。

我们现在准备创建类似 Madelon 的数据。在脚本 2a 的第 4–9 行,我们定义了我们希望从每种类型中获得的特征数量(信息性的、冗余的、重复的、无用的)。之后,在第 12–16 行,我们创建列标签。从第 19–23 行开始,我们创建数据和标签。在第 27 行,我们将 numpy 数组转换成 pandas 数据帧。

脚本 2a —创建类似 Madelon 的数据集。

接下来,我们将创建我们至关重要的特性。这里,我们将假设经过几十年的理论、数值和经验研究,这三个特征已经被确定为对分类过程特别重要。为了更清楚地说明这一点,让我给你举个例子。在放射肿瘤学中,传递到器官的最大辐射可以与接受放射疗法治疗的患者所经历的毒性相关联。因此,为了确保对患者的安全治疗,考虑传送到每个器官的最大辐射量是至关重要的。为了便于说明,让我们假设在患者开始出现中毒症状之前,可以传递到膀胱的最大辐射可以是 100。所以我们的数据可能看起来像这样:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 1 —输送到膀胱的最大剂量。

因为医生知道对膀胱的大量辐射会导致并发症,所以产生的大多数辐射治疗计划将满足建立的最大辐射标准。然而,在表 1 中,6 号患者未能满足膀胱接受少于 100 次辐射的标准。换句话说,95%的数据符合标准,只有 5%不符合。因此,如果您要实现一种自动选择功能的方法,如果您不采取适当的预防措施,这种方法很可能无法识别膀胱的最大剂量至关重要。尽管如此,我们知道这样的特征是非常重要的,为了病人的安全,应该总是考虑到。因此,将极其重要的特征引入我们的数据集中以测试自动特征选择方法的效率的动机。

为了创建 3 个关键的重要特征,将从三个不同的高斯分布中提取,每个分布以不同的值为中心。这些特征将由我在 StackOverFlow 中找到的以下辅助函数生成:

脚本 2b :生成关键重要特征的辅助函数。

脚本 2c 的第 5–10 行,我们设置了关键特性分布的参数。然后在第 13–25 行,我们运行一个 for 循环,创建三个关键特性,然后存储在一个列表中(第 25 行)。我想指出的是,在第 15 行,我们修复了种子,这样我们就可以使用相同的发行版。

脚本 2c :创建三个关键特征。

在我们将这些关键特性添加到数据集**、之前,我们需要定义 y_critical 目标。在脚本 2d** 的第 5–7 行中,我们通过设置阈值来确定真假情况,从而为每个关键特性定义一个目标。选择这些阈值,使得每个关键特征包含 95%的阳性病例和 5%的阴性病例。最后,在第 10 行,我们通过乘以关键特性的目标来定义 y_critical

脚本 2d :创建每个关键特征的标签和 y_critical 标签。 y_critical 应该有 74 个阳性病例。

作为健全性检查,让我们可视化关键特性的分布。

脚本 2e :可视化关键特征。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1 —关键特征分布。绿色区域代表阳性类别,红色区域代表阴性类别。

图 1 中,您会注意到有三种不同的高斯分布。最左边的分布代表第一关键特征,最中间的分布代表第二关键特征,最右边的分布代表第三关键特征。标记为绿色的区域表示每个要素中的阳性类别,标记为红色的区域表示阴性类别。

我们现在准备把所有东西放在一起。在脚本 2f 的第 12 行,我们连接了 X_madelonX_critical 。然后在第 15–16 行,目标 y_all 被定义为 y_madelony_critical 的逐元素乘法。

脚本 2f :加入 X_madelonX_critica l 创建 X_all 和创建 y_all

在我们继续之前,让我们回顾一下我们已经创建的一组功能:

X_madelon: 这是一组使用make_classification()类创建的合成特征。原则上,从该组中选择的最佳特征数量应该是信息特征(总共 10 个)。

X_critical: 关键特性一共 3 个。每个都具有不同平均值的高斯分布。每个关键特征包含 90 %的肯定案例和 10 %的错误案例。通过构造,这些特征可能很难通过自动化方法来选择;然而,对于一个对手头数据有领域知识的人来说,这些数据很容易被确定为对结果很重要。

X_all: 这是一组包含了 X_madelonX_critical 特性的特性。该数据集的列将按如下顺序排列:

  1. 信息特征—第 1–10 列:这些特征与结果高度相关,理想情况下应该是您选择的特征。
  2. **冗余特征—第 11–60 列:**这些特征通过线性组合具有不同随机权重的信息特征而形成。您可以将这些视为工程特性。
  3. 重复特征—第 61–85 列:这些特征是从信息特征或冗余特征中随机抽取的。
  4. **无用特征—列 86–100:**这些特征充满了随机噪声。
  5. 关键重要特征—101–103 列:这些特征具有高斯分布,我们将要求它们绝对需要包含在所选特征中。

在我们做任何其他事情之前,让我们分割我们的数据。对于每组功能,我们将使用 70/30 分割创建一个训练和测试集。

脚本 2g —将数据分割成 70 个训练/ 30 个测试分割。随机状态/种子被设置为 42。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

探索性数据分析

在本节中,我们将可视化数据,以确认我们已经知道的内容。我们将从探索我们特征之间的相关性开始。在脚本 3a 中,我们首先计算斯皮尔曼相关矩阵,其值在-1 到 1 的范围内(第 5 行)。值 1 表示强正相关,值-1 表示强负相关。当相关值接近零时,这意味着特征之间不存在相关性。由于负相关和正相关只是相关,我们然后取相关矩阵的绝对值(第 5 行)并使用seaborn包创建热图(第 14 行),参见图 2

脚本 3a—可视化 Spearman 相关矩阵。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2 —斯皮尔曼相关矩阵可视化为热图。注释是用 PowerPoint 添加的。

图 2 中,浅色表示低相关性,深蓝色表示高相关性。请注意,信息特征之间的相关性很低(左上角)。冗余特征开始显示更高的相关性(热图在该区域变得更蓝),就像我们预期的那样。此外,有些重复与我们预期的其他特征高度相关。最后,无用特征和关键特征与其他特征不相关。我们知道无用的特征充满了随机噪声,不应该与结果相关联。另一方面,关键特征与结果相关,尽管它们与其他特征没有相关性。

接下来,让我们使用箱线图来可视化每个特征的分布。箱线图显示了数据集的四分位数,并允许我们确定数据中的任何异常和异常值。在脚本 3b 中,我们首先设置图形样式,这样我们的图形(第 5–8 行)就不会有难看的灰色默认seaborn背景。然后,我们为特性 X_all_ 系列创建一个方框图(第 14 行)。

脚本 3b —用箱线图可视化特征分布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3 —特征矩阵方框图。

图 3 中,我们可以看到大多数特征都包含离群值。此外,所有类似马德隆的特征都以零为中心,并且大多数似乎具有高斯分布。关键特征以不同的平均值为中心,就像我们之前在图 1 中展示的那样。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

特征选择

在本节中,我们将使用FeatureSelector,这是一个应用以下四种特征选择方法的工具:

  1. 一种过滤方法,可移除具有给定比例重复值的要素。
  2. 一种基于皮尔逊或斯皮尔曼系数移除相关要素的过滤方法。
  3. 一种带有交叉验证的递归要素消除算法,用于对要素进行排序并确定最大化模型性能的要素。
  4. 选择与结果相关的特征的 Boruta 方法。

该工具设计用于在给定的序列中应用不同的特征选择方法。例如,您可以首先移除相关要素,然后使用递归要素消除来进一步减少所选要素的数量。

移除大部分常数值的特征

有人可能会说,当你改变样本时,一个特性表现出的变化很小或者没有变化,对于一个模型来说是不太有用的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 2 —特征 3 显示可变性很小的样本数据集。

例如,如果您的数据看起来像右侧的表,则选择要素 1、要素 2、要素 4 并删除要素 3 是合理的。这是因为特征 3 的值在不同的样本之间变化不大。保留特性 3 会增加模型的复杂性,并且保留它很可能不会观察到任何预测性能。然而,最后一种说法需要经验验证。要建立阈值来标记包含大量常数值的要素,以便移除它们,您需要进行实验。仅仅因为一个特性在 90%的时间里包含相同的值,并不意味着它对一个模型没有用。

脚本 4a 中,我们从导入特征选择工具开始。在第 7 行,我们定义了一个名为 step1 的字典,其中我们指定了要应用的特性选择方法及其参数。例如,要删除具有大部分常量值(95 %或更多)的特性,我们将键设置为'Constant Features',将值设置为{'frac_constant_values': 0.95}。在第 10 行,我们将步骤 1 保存在一个名为步骤的列表中,然后我们启动一个FeatureSelector的实例(第 13 行)。FeatureSelector有一个fit()transform()方法,很像 Sklearn transformer。fit()方法学习从训练集中选择哪些特征(第 16 行),而transform()方法将数据集减少到仅选择的特征(第 19 行)。fit()方法将以下内容作为输入:

  • X_all_train :熊猫数据帧
  • y_all_train :一个 numpy 数组
  • **步骤:**字典列表

transform()方法将以下内容作为输入:

  • 一个熊猫的数据帧

脚本 4a —移除大部分常数值的特征。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4 —在 IPython 控制台中执行的脚本 4a。执行时间不到一秒钟。

fit的输出将被打印到被移除特征的控制台上。在这种情况下,您可以看到显示一个空列表,这表示在此步骤中没有删除任何功能。

移除相关特征

让我们假设,如果一组特征高度相关,我们可以随机选择其中一个,丢弃其余的,而不会丢失太多信息。为了衡量特征之间的相关性,我们将使用 Spearman 的相关系数。为了移除相关特征,我们将再次使用FeatureSelector。在脚本 4b 中,我们首先定义一个描述特征选择方法及其参数的字典。例如,在这种情况下,我们将键设置为'Correlated Features',将值设置为{'correlation_threshold': 0.95}。该算法将对相关值大于或等于 0.95 的要素进行分组。然后,对于每组相关的特征,选择一个特征,其余的被丢弃。在第 8 行,我们将步骤 1 保存在一个列表中,然后初始化FeatureSelector的一个实例(第 11 行)。最后,我们拟合FeatureSelector,并转换我们的数据。

脚本 4b —移除高度相关的特征。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5 —在 IPython 控制台中执行的脚本 4b。执行时间不到一秒钟。

注意fit()的输出显示所有的重复特征被移除。在我们继续之前,让我们通过检查X_selected中的特征类型来结束这一部分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6——从 X_all_train 中去除高度相关特征后所选特征的条形图。

在图 6 的中,请注意没有删除任何多余或无用的功能。换句话说,如果您仅从群组中移除相关特征,预计仍会有冗余和无用的特征。从积极的方面来看,我们看到 10 个信息性特征和 3 个关键性特征是所选特征的一部分。

确定相关特征

我们已经表明,简单的特征选择方法可以快速执行,并可以从我们的队列中删除大部分特征;然而,其余的特征不一定与结果相关或者可能是多余的(见图 6 )。为了克服这个限制,开发了 BorutaPy 算法。简而言之,它使用基于树的模型的要素重要性属性来确定携带可用于预测的信息的要素。然而, Terrence Parr 和其他人对基于树的模型的特征重要性属性的有效性提出了关注。

为了选择相关特征,我们首先定义一个基于树的 Sklearn 估计器(一个具有feature_importances_属性的随机森林分类器额外树分类器梯度提升分类器)。在我们的例子中,我们将使用随机森林分类器,参见脚本 4c 中的第 5–7 行。接下来,在第 10–15 行,我们定义了一个名为 step1 的字典,带有一个键'Relevant Features''Relevant Features'的键值是一个字典,指定交叉验证结果的次数(第 10 行)和 BorutaPy 参数。对于每个训练文件夹,建立相关的特征。然后,在每个训练文件夹中被认为相关的特征被选择作为训练集中的相关特征。在第 15 行,我们修复了random_state,以便获得确定性的结果。至此,脚本的其余部分应该不言自明了。

脚本 4c —确定与结果相关的特征。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7 —在 IPython 控制台中执行的脚本 4c。执行大约需要 5 分钟。

脚本 4c ,大约花了 5 分钟执行。如果你要增加cvn_estimatorsmax_iter,期待时间的增加。此外,包含更多样本或特征的大型数据集将增加找出相关特征所需的时间。您在图 7 的中看到的进度条将跟踪每次在训练文件夹中确定相关特征时的进度。所以,如果你一开始没有看到它填满,请耐心等待。

我们准备检查所选特性的内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8——在 X_all_train 中确定相关特征后所选特征的条形图。在这种情况下,估计量是随机森林分类器。

在图 8 的所示的条形图中,注意所有无用的功能都被删除了。这就是我们对 Boruta 算法的期望。尽管如此,我们仍然有 20 个冗余、9 个重复、5 个信息性和 2 个关键特征。这意味着我们的 Boruta 算法的实现不能去除所有冗余的特征,保留一些重复的特征,去除一半的信息特征,并丢弃一个关键特征。图 8 表明我们不能盲目相信自动化特征选择方法的结果。记住,我们要求所有三个关键特性都必须包含在我们选择的特性中。失去其中一个会导致致命的预言!此外,如果我们使用不同的估计器,例如额外的树分类器,所选择的特征将会不同(见图 9** )。**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9 —使用额外树分类器和 Boruta 算法确定相关特征后,所选特征的条形图。

当使用 Boruta 算法选择特征时,重要的是要记住被选择为相关的特征只对被检查的特定模型有意义。此外,当用于对特征进行排序的模型具有过度拟合的能力时,很可能特征的排序是误导的。为了演示过拟合随机森林的缺陷,我们训练了一个模型,并评估了它在训练集和测试集中的性能,参见脚本 4d

脚本 4d —训练一个过度适应的随机森林。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

脚本 4d 的输出

这里我们可以观察到,训练集中随机森林的训练准确率为 100%。当评估测试集中的性能时,我们看到准确率下降到 80 %(显然我们过度拟合)。检查过拟合随机森林的特征重要性,发现许多无用特征(随机噪声)的等级高于有用和冗余特征,见图 10 。理想情况下,无用的功能应该排在最低的位置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 10 —一个过度生长的随机森林的特征重要性。

鉴于过度拟合模型的排名特征不可靠,我建议首先调整您的模型,交叉验证结果,并评估其在训练和测试集中的性能,参见脚本 4e 。最小化过度拟合后,使用模型选择特征。

脚本 4e —调整分类器。要将 GridSearchCV 使用的折叠数更改为 10,请在第 19 行设置 cv = 10。同样,你也可以改变得分。执行大约需要 6 分钟。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

脚本 4e 的输出

结果表明,训练集的准确率为 96%,测试集的准确率为 81%。他妈的,我们还是太合适了!让我们检查一下调整后的随机森林是如何排列特性的,参见图 11

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11 —显示了调整后的随机森林的重要性。

有意思!我们得到了比预期好得多的结果。尽管调整后的随机森林过度拟合,但它在排列特性方面做得更好。例如,我们可以看到,关键的功能排名很高,而大多数无用的功能排名垫底。

要确定已调优随机森林的相关特性,请运行脚本 4f

脚本 4f —确定与优化随机森林的结果相关的功能。执行大约需要 5 分钟。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 12 —用调整随机森林的 Boruta 算法确定的相关特征的条形图。

图 12 中,我们可以看到所选特征包含了对我们非常重要的三个关键特征。此外,请注意,与使用失调随机森林获得的结果相比,您可以更信任这些结果。

现在,我们将只使用选定的功能来训练一个随机森林,参见脚本 4g 。我们将随机森林的参数设置为之前在脚本 4e 中确定的参数。让我提一下,使用选择的特性来调整随机森林是一个好主意。记得当我们在脚本 4e 中调整随机森林时,我们使用了所有 103 个特性。现在选的特征大概有 35 个。然而,我们将跳过这一步,但你应该这样做。最后,我们将评估它在训练集和测试集中的性能。

脚本 4g —使用所选功能评估模型的性能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

脚本 4g 的输出

在我们讨论结果之前,让我提醒你我们开始的内容。当训练具有所有特征的失调随机森林时,我们在训练集中获得了 100 %的准确度,在测试集中获得了 80 %的准确度。让我们称之为我们的基线。在“调优”随机森林(使特征排序更加可靠),用 Boruta 算法选择特征,然后用选择的特征训练随机森林之后,我们在训练集中获得了 94%的准确率,在测试集中获得了 83%的准确率(见上面的脚本 4g 的输出)。我们可以从这些结果中得出几个结论:

  • 调整你的模型以减少过度拟合。
  • 经过优化的模型可以更准确地对功能进行排序。
  • 应用特征选择方法有助于减少过度拟合并提高模型的性能。

尽管我们仍然有相当多的过度拟合,但我们已经在性能上取得了一些进展,我们减少了过度拟合,并且降低了模型的复杂性。我会说这是一场胜利,但还不够好。

确定最大化模型性能的特征

我们还可以通过应用递归特征消除(RFE)算法来选择特征。RFE 方法确定最大化模型性能所需的最小要素子集。然而,你冒着丢掉有意义的特性的风险——所以记住这一点。因此,如果您的任务是确定对结果重要的相关特征,那么使用 RFE 可能不合适。算法基本上是这样工作的。首先,训练一个可以使用数据集中所有可用要素对要素进行分级的模型。其次,衡量模型的性能。第三,对特征进行排序,并移除排序最低的特征。重复步骤 1 至步骤 3,直到所有功能都用尽。通过在跟踪模型性能的同时迭代移除特征,您可以确定实现最高性能所需的特征数量。

为了确定将最大化模型性能的特征,我们首先定义一个基于树的 Sklearn 估计器(一个随机森林分类器额外树分类器梯度提升分类器),具有feature_importances_coef_属性。确保您的基本估计值不会过度拟合您的数据。在我们的例子中,我们将使用一个随机森林分类器,带有在脚本 4e 中找到的调整参数,参见脚本 4h 中的第 5–8 行。接下来,在第 11–15 行,我们定义了一个名为 step1 的字典,其中包含一个关键字'RFECV Features''RFECV Features'的键值是一个字典,指定交叉验证结果的次数(第 11 行)和其他 RFECV 参数。RFECV 对象是 RFE 方法的 Sklearn 实现,其中结果被交叉验证。至此,脚本的其余部分应该不言自明了。

脚本 4h —确定最大化分类器性能的特征。这将需要大约 5 分钟来运行。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 13 —使用递归消除算法确定的最大化随机森林分类器性能的选定特征的条形图。结果是交叉验证的。

图 13 显示了由 Sklean RFECV 方法确定的选定特征。不幸的是,我们仍然有很多冗余和重复的功能。FeatureSelector类有一个rfecv属性,保存适合的 RFECV Sklearn 对象。通过检查拟合的 RFECV 对象的内容,可以更深入地了解 RFE 特征的结果。

脚本 4f —可视化 RFECV 的结果。所有这些代码都是为了做一个图形。呸!如果更改数据集或基本估计量,可能需要调整 xlim()、ylim()和 ax.axhline()。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 14 —作为特征数量函数的精度。该模型的性能峰值约为 40 个特征。

图 14 中,显示了模型的性能与多个特征的函数关系。如您所见,性能峰值约为 40 个特征,精度约为 0.80。由于所选特征的数量约为 50(见图 13 ),我们可以得出结论,RFECV Sklearn 对象高估了我们最大化模型性能所需的最小特征数量。在我看来,如果你简单地选择排名前 13 位的特征,模型的准确率大约为 79%,你会更好。然而,RFECV Skelarn 对象确实为您提供了这些信息。如果你急于知道排名前 13 位的特性是什么,你将需要编写你自己版本的 RFE 算法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

构建特征选择管道

在上一节中,我们了解到我们需要谨慎和警惕自动特征选择方法的危险。通过应用它们,然后盲目地相信结果,你可能最终会犯下可怕的错误。此外,没有一个单一的特征选择算法产生了我们想要的结果——只选择了信息和关键的特征。

为了改进我们的特征选择,我们可以将特征选择算法作为一系列步骤来应用。例如,我们可以首先移除中度到高度相关的特征(第 11 行),然后应用 RFE 方法,如脚本 5a 所示。

脚本 5a —特征选择管道。首先,移除中度到高度相关的特征。然后,确定最大化模型性能的特征。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 15 —使用递归消除算法确定的最大化随机森林分类器性能的选定特征的条形图。这一次,我们首先移除中度到高度相关的特征,然后应用 RFE 方法。

这一次,在所选功能中,我们有 8 个信息性功能、所有 3 个关键功能和 20 个冗余功能。这些是迄今为止我们得到的最好的结果,但是让我们再深入研究一下。请记住,FeatureSelector对象将适配的 RFECV 对象保存在其rfecv属性中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 16 — 作为特征数量函数的精度。该模型的性能峰值约为 20 个特征。

因此,我们已经可以从性能曲线中看到,模型的性能在 20 个特性附近达到峰值。此外,我们可以得出结论,15 个特性将足以获得高性能。现在,我们使用脚本 5b 中的选定功能来评估模型的性能。

脚本 5b —具有选定特征的模型评估。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

脚本 5b 的输出

脚本 5b 的输出中,我们可以看到我们将训练集中的准确率提高到了 84%。我们缓慢但确实取得了进展。您可以使用脚本 4e 再次调优该模型,看看您是否能获得更多的性能增益。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结束语

那么,我们究竟如何设计一个特征选择管道,以产生所有的信息和关键特征,而没有多余或无用的特征呢?嗯,简单的回答是我不知道。如果你想解决这个问题,你可以把你的算法带到银行去。你应该问的问题是,“我真的需要确定最有用的特征,还是我想用最小的特征子集来训练模型?”如果你的答案是“确定最有用的特性”,那么这里介绍的方法将有助于你寻找最佳特性。然而,如果你只关心用较小的特征子集训练最好的可能模型,这里给出的特征选择算法将完成这项工作。

如果您想使用特征选择工具,请确保您的工作目录中有该工具,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

my Github 下载功能选择工具。

在使用它选择特征之前,请确保满足以下条件:

  • 加载数据并对所有分类变量进行编码。
  • 注意任何缺失值或异常值。如果不这样做,您可能会得到一个严重的错误。
  • 将特征矩阵 X 存储到 pandas DataFrame 对象中。目标变量 y 应该是一个 numpy 数组。

准备好数据后,您可以使用脚本 6a 来指导您的特性选择过程。您将需要试验来确定应用什么特征选择算法。在脚本 6a 中,我们首先调整我们的模型(第 5–29 行),然后我们定义四种特征选择方法并应用它们(第 32–56 行)。然后,我们使用选定的特征来训练模型并评估其性能(第 59–75 行)。

脚本 6a —模型调整、特征选择、模型训练和评估。

LinkedIn 找到我。下次见!小心每天编码!

[## 弗兰克·塞瓦洛斯

图表

www.frank-ceballos.com](https://www.frank-ceballos.com/) [## Frank Ceballos -威斯康星医学院博士后| LinkedIn

我是威斯康星医学院的博士后研究员,在那里我分析高维复杂的临床数据…

www.linkedin.com](https://www.linkedin.com/in/frank-ceballos) [## 弗兰克-塞瓦洛斯-概述

在 GitHub 上注册你自己的个人资料,这是托管代码、管理项目和构建软件的最佳地方…

github.com](https://github.com/frank-ceballos)

设计医疗保健机器学习工作流程

原文:https://towardsdatascience.com/designing-a-healthcare-machine-learning-workflow-2f95852a8b80?source=collection_archive---------28-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来自格鲍尔公司

只需 5 个步骤即可构建和运行机器学习项目

随着机器学习、云计算和机器人流程自动化等创新在医疗领域不断产生影响,结构化(即电子医疗记录)和非结构化(即医学图像、生物信号等)的需求不断增加。)公众可访问的医疗保健数据。由于工业界和学术界的许多个人和组织都在尝试创建学习模型,因此了解如何设计一个适合您正在处理的数据和问题类型的合适的机器学习工作流至关重要。这导致一个有组织的,有效的产品,产生预期的结果。

第一步:理解问题

在争论数据和构建模型之前,定义问题是很重要的。大多数缺乏经验的数据科学家希望快速获得数据,执行一些基本的 EDA,然后解决他们想要解决的问题。在行业和学术环境中,明确定义的问题和操作计划为项目的其余部分奠定了基础。为了知道你是否应该处理平衡的数据或者寻找异常值,拥有一些领域的专业知识是很重要的。

[## 贝叶斯决策理论简介

机器学习的统计方法

towardsdatascience.com](/introduction-to-bayesian-decision-theory-1532376ef986)

医疗保健领域的机器学习问题有三个主要类别:诊断、预测和建议。虽然机器学习中有许多类型的问题,但这三个问题包含了医疗保健中的大多数问题。

诊断

医疗保健 ML 中最常见的应用是诊断,也称为分类。这种受监督的学习方法能够在给定一组描述其症状的特征的情况下,确定患者是否患有特定疾病。这些特征可以以表格数据、医学图像、文本或信号的形式呈现。在某些情况下,目标是在两个类别之间进行诊断(即二元分类);然而,有时需要考虑多个类别(即多类别分类)。

预言;预测;预告

另一种监督学习方法,预测寻求回答与数量、可能性和任何其他连续结果相关的问题。与如何进行诊断类似,预测会尝试拟合训练数据,以确定最佳可能答案。这一类别可以进一步扩展到生存分析、线性回归和时间序列预测等主题。

推荐

这一类别近年来越来越受欢迎。它利用组合学的力量向给定系统的用户推荐感兴趣的项目。健康推荐系统能够根据患者的症状和情况提出最佳的行动计划。建议的范围可以包括服用何种药物、去看医生或去哪家医院。这是一个非常强大的工具,但它没有与上述类别相同的评估标准。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 ScienceSoft

第二步:收集数据

一旦问题确定下来,计划开始实施,就该讨论适当的数据了。医疗保健行业每天都会产生大量的数据。临床数据是大多数健康和医学研究的主要资源。它要么是在持续的患者护理过程中收集的,要么是正式临床试验计划的一部分。最常见的例子是电子健康记录(EHR),它从多个来源收集有关患者健康的信息。EHR 包括测试结果、临床观察、诊断、当前健康问题、患者服用的药物、他们经历的程序。同样,文本和图像数据也开始在深度学习应用中发挥深远的作用。例子包括医学图像、手写处方和医生笔记。

由于医疗保健数据生态系统极其复杂和强大,无论您决定使用什么数据,都可能会有很高的存储要求。在你简单地从网站上下载一个随机的 CSV 文件之前,一定要检查你正在使用的文件的大小。聪明的方法是利用云。有许多公司提供廉价、用户友好的软件即服务(SaaS ),可以部署云数据库。现在,您所要做的就是从您正在使用的 IDE 中提取信息。

步骤 3:探索性数据分析(EDA)和预处理

数据清理

由于许多 EHR 系统仍然是手动创建和更新的,因此存在人为错误和数据质量问题。花时间清理您的数据将最终为您节省大量处理、培训、测试和评估问题的时间。正确的数据清理管道包括通过删除或修改不正确、不完整、不相关、重复或格式不正确的数据来为分析准备数据。许多初级数据科学家只是删除不干净的数据。相反,尝试操纵和扩充数据,以尽可能多地保存数据。

电子设计自动化(Electronic Design Automation)

在开始构建 ML 模型之前,创建信息可视化、统计测试和针对数据和手头问题的关系矩阵是很重要的。EDA 是了解关键特征的一个窗口,如类不平衡、特征分布和相关系数。虽然有些人认为这是浪费时间,但成功的工作流具有支持模型输出的可视化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

相关矩阵

特征抽出

既然您已经了解了要素之间以及要素与目标要素之间的关系,那么就应该选择能够最好地包含数据中的差异而又不会显著增加模型复杂性的要素。有许多方法可以选择最佳特性,但这超出了本文的范围。

步骤 4:构建和培训

决定采用哪种模式并不是一个容易的决定,它需要大量的试验和错误。每个模型都是独一无二的,需要在复杂性和效率之间取得平衡。根据没有免费的午餐定理,没有一个模型对所有可能的情况都是最好的,所以最好尽可能多的测试。

“没有一种模式能适用于所有可能的情况”

即使某个模型适用于您以前的项目,也并不意味着相同的模型将是您当前项目的最佳选择。最重要的是,数据科学家首先是科学家。因此,尝试各种可能的方法是我们工作的一部分。一旦你对自己的选择有了信心,就该在测试集上运行它了。

监督学习

到目前为止,监督学习(SL)模型是最常见的类别,它使用带有精确标签的先验数据进行训练。因此,模型应该理解底层的类条件特征空间。一些常见的 SL 算法包括逻辑回归、K-最近邻、支持向量机和随机森林。

无监督学习

使用未标记的数据,无监督学习(UL)模型被迫寻找数据中的自然关联。这消除了对训练阶段的需要,而是使用数学过程来推导分组、不同的表示和层次。常见的 UL 算法包括 K 均值、降维、层次聚类和基于密度的聚类。

半监督学习

灰色区域与之前的类别相比,半监督学习(SSL)模型使用标记和未标记数据的混合来进行分类或预测。这是因为模型需要正确理解已标记数据的结构,以理解未标记数据。SSL 方法的一个常见应用是欺诈检测。由于欺诈很难发现,而且我们不知道谁是欺诈性的,因此模型需要了解非欺诈实体的复杂性,以便发现异常实体。

步骤 5:评估模型

根据您要解决的问题的类型,可以使用特定的评估指标来深入了解您的模型的运行情况以及可能需要调整的超参数。评估一个模型是一个整体的方法,并不仅仅基于高准确性。根据您在步骤 1 和 2 中定义的问题和执行的分析,可能还有其他更重要的指标。

分类指标

  • 准确性:在我所有的预测中,有多少是正确的?
  • 精确度:在我对某个类所做的所有预测中,有多少是正确的?
  • 回忆:正确识别某一类的比例是多少?
  • 受试者工作特征(ROC)曲线:显示不同分类阈值下模型性能的图。曲线下面积(AUC)代表模型整体性能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

具有 AUC 值的 ROC 曲线

回归度量

  • 均方差(MSE):预测值和实际值之间的平方差
  • 均方根误差(RMSE):MSE 的平方根
  • 平均绝对误差(MAE):预测值和实际值之差的绝对值

排名指标

  • 平均倒数排名(MRR):基于第一个相关项目位置的平均值
  • 平均精度(MAP):对于每个相关项目,根据该项目的位置计算精度,然后对所有用户进行平均
  • 标准化贴现累积收益(NDCG):假设一些项目比其他项目更相关,计算加权平均值。

结论

为医疗保健环境开发和实现机器学习不是一个快速的过程,但我希望这篇文章为您了解可能会遇到的障碍奠定了基础。请记住,即使您构建了模型并且运行良好,您仍然需要部署它。虽然部署机器学习系统在实践中非常简单,但医疗法规和控制要求您采取某些措施来确保标准化和质量保证。

相关文章

[## 检测医疗欺诈(第一部分)——数据采集和预处理

了解医疗事故的特点以及需要什么技术来检测欺诈的医生

medium.com](https://medium.com/swlh/detecting-medical-fraud-part-1-data-acquisition-preprocessing-e8f3206b9bac) [## 检测医疗欺诈(第 2 部分)—在 PyTorch 中构建自动编码器

学习如何使用神经网络发现腐败的医生

medium.com](https://medium.com/swlh/detecting-medical-fraud-part-2-building-an-autoencoder-in-pytorch-5ef64b7979ef)

设计实用且引人注目的数据可视化

原文:https://towardsdatascience.com/designing-a-practical-and-compelling-data-visualization-dbf2446ba083?source=collection_archive---------48-----------------------

现实世界中的数据科学

你不需要成为 Tableau 或 PowerPoint 超级用户。

数据可视化是向技术和非技术受众传达数据的最有力的方式。这也是分析中最“理所当然”的部分。很少有分析师接受过数据可视化最佳实践的正式培训。

更糟糕的是,像 PowerPoint 和 Excel 这样的应用程序的默认选项设计得很差;当它们应该被视为一个起点时,它们被视为可接受的或首选的。

数据可视化的目的是让查看者快速和轻松地从数据中提取最重要的信息。我发现很难找到一个非教科书式的资源,专注于利用心理学和人类行为知识的数据可视化的实用的、以业务为中心的最佳实践。大部分内容都是平面设计或者是为口头表达而设计的。

然而,对于当今的分析专业人员来说,这种差距就是大多数演示文稿存在的地方——您的内容需要做的不仅仅是“看起来不错”,必须足够直观,能够在幻灯片或仪表板中独立存在,并且应该足够清晰,能够快速提取出正确的信息。

我最近完成了我的商业分析硕士项目中的一门课程,重点是视觉影响。其目的是弥合上述差距。它是关于如何通过设计获得关注,并将其应用到商业展示中。

为了说明最佳实践,我将从默认的 PowerPoint 图表和表格开始,回答一个简单的问题:2019 年世界上哪个地区最幸福?

删除默认设置的所有内容

你曾经(或通常)见过类似这样的幻灯片吗?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

默认 PowerPoint 图表和表格

图表和表格包含了回答问题所需的所有信息,但什么也没有弹出。有一个平淡无奇的条形图,不伦不类的标题,和文本表格。为了回答哪个地区最幸福,我需要直观地比较澳大利亚、北美和西欧,然后参考右边的表格来比较数值。

让我们也考虑几个其他项目:

  • 为什么我们需要一个标有每个数字的 y 轴?没有数字低于 4,我们在右边有数字值。
  • 既然我们只有一组值,我们还需要默认添加的颜色图例吗?
  • 倾斜区域值呢?对于第一次看图表的人来说,这是一个很高的认知负荷。
  • 为什么值按字母顺序排列?
  • 背景网格线是有帮助还是分散注意力?

几个简单的清理步骤解决了上述问题,并开始改进图表设计。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

y 轴被移除,并且值被添加到每个条的顶部。通过在顶部添加标签,我们可以删除右边的表格,增加的空间允许我们加宽图表并删除倾斜的部分,而不减小字体大小。图例也被删除,图表标题也有所改进。总之,除了酒吧本身和国名,所有东西都被拿走了。

现在回答我们的问题更容易了,但并不容易。

减少认知负荷

收集正确的数据和选择正确的图表是交流数据的关键步骤,但我们可以做得更多。我们将添加预先注意属性,这是我们可以对可视化进行的微妙改变,以使我们最重要的信息“流行”。我们还将调整图表,使其具有反映我们思维方式的更传统的顺序,即从左到右。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意使用的预先注意的属性:颜色/阴影、粗体、文本大小

上图有几个重要的变化:

  • 对于色觉缺陷的人来说,蓝色的默认颜色是具有挑战性的。包容性设计意味着我们应该假设至少有一个观众会受到影响。如果你公司的品牌指导方针允许的话,宁可选择非蓝色。
  • 我们通过颜色的预先注意属性将注意力吸引到最高平均分上。就我个人而言,我觉得一种颜色在灰色值的映衬下会很流行。还要注意,除了澳大利亚以外,数据标签的颜色都是灰色的。
  • 接下来,仍然在标签上,澳大利亚的数据标签的大小已经增加,以显示除了粗体以外的层次结构,以吸引对值的进一步注意。

查看图表的观众知道应该看哪里,即使他们还不知道正在回答的问题。

把它带到终点线

信息弹出,我们已经创建了一个逻辑顺序。最后,请记住,我们试图告诉某人 2019 年哪个地区最幸福。这不是一个盛大的信息发布会,所以当我们可以把信息和数据一起给他们时,我们为什么要依赖他们来回答这个问题呢?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以给出一个信息性的标题,而不是描述性的图表标题。对于标题,这意味着数值代表平均幸福分数,所以我们可以删除图表标题。我还将除澳大利亚和新西兰之外的所有地区都变灰了,因为我们对哪个地区是第二、第三等等不感兴趣。

你可能会问,如果我们给出了答案,为什么还要包括其余的数据,这是公平的。它为澳大利亚的价值提供了背景,当信息呈现在观众面前时,观众往往会对答案感到更舒服,而不是认为你给出的答案是理所当然的。

我在底部添加了一个来源,因为我们并不总是知道谁会收到我们的数据,以及他们想用这些数据做什么;添加源减少了您以后可能会收到的额外问题。即使对于内部演示文稿和数据,从何处收集信息也可以帮助您的受众(也可以帮助您在将来的某个时候再次引用这些数据)。

把它放在一起

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

之前和之后

这个例子既戏剧化又非常真实。看看你最近看过的演示文稿。它看起来更像顶部视觉还是底部?你会对你最近看过的视频做哪两项改进?

我能给的最重要的建议是删除默认添加到视觉效果中的每一条额外的信息和图表设计,并添加最少量的信息来传达你的信息。然后,使用颜色、大小、粗体、间距和其他预先注意的属性来增强你的信息。

仔细检查你创造的每一个视觉效果是需要努力的,但是看到它所产生的改进的讨论和你工作的改进的结果也是非常令人满意的。

对数据可视化感兴趣?你有什么想法要分享吗?欢迎在 LinkedIn 上与我联系,或者在 jordan@jordanbean.com 给我发邮件。

设计关系数据库并创建实体关系图

原文:https://towardsdatascience.com/designing-a-relational-database-and-creating-an-entity-relationship-diagram-89c1c19320b2?source=collection_archive---------1-----------------------

【Craig Dickson 的 SQL 教程

学习使用 SQL 和免费开源软件创建、更新和查询您自己的全功能关系数据库—第 1 部分

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由麦克默里朱莉皮克斯拜 | 领证

这是由 3 部分组成的系列文章的第 1 部分,从零开始,带您了解设计、编码、实现和查询关系数据库的过程。参见第 2 部分(使用 MySQL 编码和实现关系数据库) 此处 ,以及第 3 部分(MySQL 中的数据分析—关系数据库中的运算符、连接等) 此处

本教程的所有代码和信息都可以在相关的 GitHub 资源库 中找到。我使用了lucid chart来制作文章中显示的图表。

当我第一次开始在工作中使用数据库和编写 SQL 查询时,我总是有点害怕会不小心删除我公司所依赖的所有生产数据。因此,我对自己做了哪些查询和做了什么非常犹豫。随着时间的推移,我学到了更多关于如何使用不同的风格的结构化查询语言 (SQL 对它的朋友来说)。

在这一系列文章中,我将分享我所学到的知识,从头开始讲述使用 MySQL(和 MySQL 服务器)创建关系数据库的过程,并希望在开始构建自己的数据库的过程中能够充分阐明一些事情,并确信不会意外删除所有数据!

我们首先来看看关系数据库到底是什么以及它是如何工作的,然后浏览构建一个关系数据库的过程,从思考我们希望数据库做什么(或者从同事或客户那里收到解释他们希望它做什么的需求),到规划表及其关系,到编写 SQL 代码来创建和填充数据库本身。最后,我们将在编写查询时获得一些乐趣!

什么是关系数据库?

根据甲骨文的说法,关系数据库是“一种数据库,它存储并提供对彼此相关的数据点的访问”。好,听起来不错!

我们可以使用关系数据库管理系统( RDBMS )在我们的关系数据库中创建、读取、更新和删除(任何数据库的基本功能)信息。RDBMSs 例子包括 Oracle微软 SQl ServerMySQLPostgreSQL 等等。每一种都有其优点和缺点(就像任何与编码相关的东西一样,它们的在线超级支持者),并且 SQL 在每一种中的实现方式都不完全相同。概念是相同的,但是语法关键字可能略有不同,因此通常不太可能在不做一些修改的情况下使用为 Microsoft SQL Server 中的 PostgreSQL 编写的 SQL 代码。

我们将使用 MySQL 社区服务器,因为它是免费的、强大的和开源的,但是其他的也是不错的选择。

在关系数据库中,记录存储在表格中(如果你熟悉 Excel 电子表格的话,可以想一想),其中每一列是一个属性(如产品名称、购买成本、零售价格),每一行代表一个记录(T21)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

例如,类似这样的事情

在这个非常简单的商店示例中,“product_id”、“brand”、“product_name”、“unit_cost”和“unit_sales_price”都是属性,每一行都是特定产品的记录(“酷品牌Luft Extreme 运动鞋”、“竞争品牌Aero Maxima 运动鞋”等)。****

主关键字

这里的每个产品都有一个“产品 id”字段,在上图中显示为红色。这就是所谓的“主键”。数据库中每个表中的每条记录都必须有一个唯一标识它的属性(或属性组合),这就是所谓的主键。

在我们的例子中,一个任意的“product_id”被分配给每个记录。还可以使用由例如“产品名称”和“产品类型”属性组成的“组合键,假设这些属性唯一地标识一个产品(即,酷品牌等从不发布另一个同名产品)。使用哪一个取决于数据的性质——重要的是每个表都有一个主键,它必须是唯一的,并且不能为空。

让关系数据库成为关系数据库的是,您可能不会惊讶地了解到,存储在表中的数据之间的关系。例如,连接到我们上面的产品表,我们可能有一个进一步的表,其中包含我们商店中销售的所有品牌的所有详细信息。****

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我们有两个表,每个表对应一个特定的实体——我们店里销售的产品,以及生产这些产品的品牌。在我们的品牌表中,品牌名称是主键——每条记录的唯一标识符。

外键

我们可以通过将品牌数据库中的主键作为“外键”包含在产品数据库中来表达这些实体之间的关系(在这种情况下,品牌是产品的生产者)。这意味着每个产品都可以与我们数据库中的适当品牌相关联。

这非常有用,因为这意味着这些表格以一种有意义的方式联系在一起,例如,我们可以很容易地找到负责“Luft Extreme 运动鞋”的联系人的姓名。在本系列的后面,我们将看看如何使用 SQL 代码来实现这一点。

在我们的示例中,我们可以让 products 表中的 brand 属性作为外键来存储这两个表之间的关系。

在这种情况下,有可能(事实上很有可能)每个品牌都有多个相关产品。也有可能每个产品都与一个和一个品牌相关联(这里我们将忽略跨品牌协作)。这意味着我们在这些实体之间有 1 对 N 的关系——一个品牌可能有 N 个产品与之相关联(N 只是表示任何数字),一个产品可能有 1 个品牌与之相关联。**

关系的这个属性,一个实体可以与多少个其他实体有关系,被称为关系的基数。其他关系还有 1 对 1N 对 M (多对多)。我们稍后将讨论这些。

因为每个产品可以有且只有一个品牌,所以将该品牌的唯一标识符(在我们的例子中,品牌名称)存储为该产品的属性是非常合理的。这意味着当我们想要查找存储在品牌表中与特定产品相关的信息时,我们可以很容易地使用品牌列(Cool Brand、Rival Brand 等)的值来“查找”品牌表中的相关信息。****

通过这种方式,product 表中的 brand 列可以说是打开其他(“foreign”)表中信息的“钥匙”。

如果我们试图将产品的键存储在 brand 表上,我们必须为每个产品都有一条记录——这使得数据分离毫无意义,并在数据库中产生了不必要的冗余。这就是我们将外键存储在 1 对 N 关系的 N 端的表上的原因。

我们的数据库可能会变得非常复杂,因为我们开始拥有多个彼此具有不同关系的表,但是这里需要关注的基本原则是:

  • 每个表都有一个唯一标识表中每个记录的主键,并且不能为空。
  • 对于表 A 与另一个表的每个关系,它需要一个外键作为表 A 中的属性来定义该关系。

这就是我们如何定义关系数据库中 1 对 N 关系中的数据之间的关系。

设计数据库

一如既往,它将帮助我们在这里浏览一个真实的例子。让我们根据自己的需求设计一个数据库吧!

定义需求

创建数据库时首先要考虑的是我们想要它做什么。这似乎是显而易见的,但值得明确说明。不同的需求将导致不同的信息结构、关系、设计和实现。

同样重要的是要注意,相同的需求可以通过不同的设计和实现来成功地满足,并且不总是有一个最佳的实现来解决特定的问题。肯定有比其他解决方案更好和更差的解决方案,但是我将把这些争论留给堆栈溢出上的线程!

那么我们的用例是什么呢?我们将为德国柏林的一所语言学校创建一个相对简单的数据库。我在柏林当了一段时间的英语教师,所以这是一个让我很感兴趣的例子。而且你知道他们说什么, 写你知道的

写下您的需求是一个好主意,或者如果您正在为客户工作或创建一个数据库供公司的另一个部门使用,请从数据库的最终用户那里获得书面形式的需求。

他们想存储什么信息?我们需要为哪些类型的实体创建表(客户、订单、产品、课程、网站点击、数据下载等)?正如任何利用数据的事情一样,为了使我们的工作最有效,我们需要考虑用例是什么,我们的用户在寻找什么。

下面是我们的示例数据库的要求:

国际语言学校是一所语言培训学校。

它为公司客户提供语言课程,可以根据客户的喜好在学校或办公室进行。学校雇佣教师,每个教师可以教授多门课程。

学校有客户,每个客户都可以通过学校提供多门课程。客户向他们的员工提供课程,员工可以选择参加。

每个课程由一个客户提供。每门课在任何时候都有一个老师。

课程的参与者是客户公司的雇员,即他们为客户公司工作。每个参与者一次只能被一家公司雇用。参与者可以注册一门以上的课程。

请记住,真正的需求文档可能会比这更长更复杂,但这份文档将为我们提供构建示例数据库所需的信息。

根据需求制定计划

首先要做的是仔细阅读需求文档,记下可能成为我们数据库中实体的东西,以及它们之间可能的关系。

在这个阶段,提出问题以阐明需求是很重要的。对于每天与某些东西打交道的人来说,很自然地会认为某些事情是“常识”或显而易见的,而对于来自工作领域之外的人来说,这些事情可能并不明显。此外,人们有时可能不习惯以创建数据库所必需的严谨性来考虑他们工作的这些方面。

这就是我们软技能的用武之地,促进技术型和非技术型员工之间清晰沟通的能力是最有价值的。我们真的不想花很多时间设计、编码和实现一个巨大的数据库,却发现我们假设每个参与者只能选一门课,而事实上他们可以选多门课。规划很重要!**

在获取需求和用 SQL 实现我们的数据库之间的一个非常有用的中间步骤是创建一个实体关系图 (ERD)。正如您所预料的,这是一个图表,它映射了我们将构建到数据库中的实体之间的关系。将此图表放在一起的过程可以帮助我们理顺关系,并在过程中识别重要的见解或冗余属性。

有些人可能会跳过这一步,直接进行编码,但是创建一个 ERD 来确保我们在构建数据库本身之前已经计划好了一切,这是最佳实践,也是强烈推荐的。

识别实体

让我们检查一下需求,看看我们是否能够识别我们的实体。这些通常是人、事物、事件或地点。

只要看一下需求文档的第一段,我们就可以看到客户、办公地点、教师和课程是我们数据库的可能实体。文件的其余部分向我们提供了关于这些实体之间关系的各种信息,还提到了参与者(客户的雇员,但从学校的角度来看,这些是语言课程的参与者)。

所以我们有候选实体:

  • 客户
  • 办公地点
  • 教师
  • 课程
  • 参与者

这些都很重要,我们必须在数据库中处理每一个。出于本文的考虑,我将做一个简化的假设,即每个客户有一个办公室,课程在那里进行(如果它们不在学校本身进行)。在现实生活中,一个客户可能有多个办公室,或者他们可能有一个大型设施,在多个地点开设不同的课程。我们可以使用 RDBMS 轻松地处理这个问题,但是为了降低复杂性,我们将假设每个客户端都有一个存放它们的类的位置。

这意味着我们将为以下实体创建表格:客户、教师、课程和参与者。好东西!

我们想要存储哪些属性?

我们的下一步是考虑我们希望为每个实体存储哪些属性。这可能会在我们的需求文档中详细说明,或者可能需要数据库开发人员更加谨慎。

先说教师实体。我们将希望存储教师的姓名,可能是他们的出生日期,他们的联系信息,税收或法律信息,以及—因为这是一所语言学校—他们教授的语言。这可能会给我们一个这样的开始。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个简单的实体,详细描述了我们希望为 ERD 的教师存储的数据

在现实生活中,我们可能会存储更多的详细信息(例如,教师的地址、他们在学校的开始日期、他们的教学支付率等),但对于我们的目的来说,这就足够了。

请注意,我们在这里创建了一个任意的‘teacher _ id’作为我们的主键。我们可以尝试使用名和姓的组合来获得一个自然键,但是如果我们的学校将来雇佣了两个同名的老师,该怎么办呢?或许不太可能,但绝对不是不可能。这些是我们在计划阶段需要考虑的事情。

我们对每个实体重复这个过程,考虑哪些信息是相关的。在这个过程中,我们经常会发现,我们所认为的属性可能更好地表示为它自己的表,或者我们可能会注意到相同的信息被冗余地存储在两个表中。这些都是通过在数据库构建过程中创建 ERD 而获得的见解,通过尽早发现可能的问题,为我们节省了时间。

让我们对剩下的实体也这样做,从客户端实体开始。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们 ERD 所代表的客户实体

这里,我们存储了客户名称、地址和行业属性,以及唯一的客户 id。

现在对于课程实体:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们的 ERD 所代表的课程实体

这里,我们再次使用 course_id 作为任意主键,同时使用一些非常重要的属性,如课程名称、语言和级别、开始日期和持续时间、课程教师、客户,以及课程是在学校还是在客户的办公室进行。

现在请注意,这里有一个教师字段和一个客户字段。我们也有教师和客户的实体。这就是我们的关系数据库变得相关的地方!

我们想要做的是将实体(以及数据库中相应的表)相互连接起来,我们可以使用这些属性作为外键来实现这一点。为了更清楚地理解这一点,让我们更详细地看看教师课程关系。

映射关系

在我们的需求文档中,说明了每门课程一次只能有一个老师,这在这种情况下是有意义的。还澄清了一名教师可能教授多门课程(这也是有道理的,一名教师很难支付每周只教一门课的费用)。所以我们这里有一个 1 对 N 的关系!

我们可以在我们的 ERD 中这样建模:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

教师和课程实体之间的关系,如我们的 ERD 中所模拟的

在 ERD,我们通过关系将这些联系起来。这通常(但不总是)用动词来建模。在我们的例子中,我们可以说老师教一门课,或者反过来说,一门课是由老师教的。把这种关系想象成基于动词‘teachers’是有道理的。请注意,图中的“教师”字段现在是绿色的,以提醒我们该属性是一个外键,它引用教师实体中的 teacher_id 属性。

这里的单线和双线是指关系中实体的参与级别。双线表示完全参与,这意味着表中的每个实体都必须参与到关系中——在我们的例子中,这意味着每门课程都必须有一名教师。单线表示部分参与,因此在我们的例子中,可能存在一些教师,他们还没有或目前没有教授任何课程。这里的是对这种区别的一个稍微长一点的解释,如果你想读更多的话。

我们可以做同样的事情来模拟客户和课程之间的关系。每个客户可以在整个学校提供多门课程,但是每门课程最多只能与一个客户相关联,所以我们还是有一对多的关系。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

客户和课程实体之间的关系,在我们的 ERD 中建模

这种关系两边的实体有双线,表示这种关系两边的全部参与。这是有意义的,因为国际语言学校只代表客户公司向那些客户的员工提供课程。因此,每个课程必须与一个客户相关联,并且每个客户必须与至少一个课程相关联是有意义的。

我们要建模的最后一个实体是我们的参与者表,其中存储了参与者的姓名、电话号码、作为主键的 participant_id 以及雇佣该参与者的客户的姓名:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们的 ERD 所代表的参与实体

你可以看到客户端是绿色的,希望你现在知道为什么了。如果您说“因为客户字段被用作外键来存储客户和参与者之间的关系”,那么您就赢了!(奖品是你从学习中获得的温暖感)。

同样,这是一个 1 对 N 的关系——客户机可能雇用多个参与者,参与者可能只为一个客户机工作——由于每个参与者只能为一个客户机工作,所以外键存储在参与者表中。

如果我们将所有这些放在一起,再加上一点点工作(我们将马上完成),我们就可以创建最终的、完整的实体关系图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

凝视它!漫威!

请注意,参与者实体和课程实体之间的关系,这里建模为“takes”(即参与者参加课程,课程由参与者参加),是多对多或 N 对 M 的关系。N-to-M 关系不能简单地通过使用外键来处理,而是需要我们在数据库模式中构建一个单独的表。我们将在第 2 部分中详细讨论这一点。

在本文中,我们介绍了什么是关系数据库以及它如何工作的基本概念,讨论了一些不同的可用 RDBMS 包,并经历了创建实体关系图来描述我们想要基于需求文档构建的数据库的整个过程。太多了!

在本系列的下一部分使用 MySQL 编码和实现关系数据库、中,我们将更进一步,实际上使用 MySQL 社区服务器完全实现这个数据库。那里见!

非常感谢您抽出时间陪我踏上这段旅程。我随时欢迎您的反馈——请通过我的网站与我联系,让我知道我该如何更有效地做这件事!我总是乐于接受建设性的批评,或者你的任何意见。

下次见!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

更像这样?访问craigdoedata . de

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值