TowardsDataScience-博客中文翻译-2020-二十九-
TowardsDataScience 博客中文翻译 2020(二十九)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
数据科学家面临的 8 种认知偏见
原文:https://towardsdatascience.com/cognitive-biases-facing-data-scientists-86489e99dea8?source=collection_archive---------27-----------------------
通过放弃不合理的思维模式来提高你的效率
由来自像素的上的声音拍摄
作为数据科学家,我们帮助公司做出最佳决策。
但是认知偏差,潜意识的非理性思维模式,会导致我们自己做出糟糕的决定。
我将分享我在作为软件工程和数据科学家的职业生涯中遇到的 8 个认知偏见和例子。
1.承诺升级
经济学中称之为【沉没成本谬误】。
承诺升级是一种人类行为模式,在这种模式下,个人或团体面对因决策、行动或投资而产生的越来越多的负面结果时,仍然会继续这种行为,而不是改变方向。
- 维基百科
这是一种趋势,即尽管有证据表明剩余成本大于收益,但仍继续向现有项目投资资源,因为已经投入了大量资源。
一不做,二不休。
在对一个新的 NLP 管道工作了一个月之后,我了解到它只会比现有的模型稍微好一点。
新模型还需要一周才能完成,而且还有其他项目需要我的技能。尽管如此,我有强烈的愿望去完成当前的项目,因为我已经投入了这么多时间。这是“承诺升级”。
照片由 Miles Iwes 从 Pexels 拍摄
从逻辑上讲,如果从事其他工作的边际收益更高,你应该去做。
也就是说,这种认知偏见可能在一个组织中根深蒂固,以至于你别无选择,只能完成当前的项目,即使只是为了光学(又名。这样就不难看了)。
2.规划谬误
低估一个项目需要多长时间才能完成。
计划谬误是一种现象,在这种现象中,对完成未来任务所需时间的预测显示出一种乐观偏见并低估了所需时间。
- 维基百科
众所周知,软件工程师和数据科学家大大低估了构建东西所需的时间。
来自 Pexels 的启动股票照片
我的技术人员在我的公司工作期间低估了完成每一个功能的时间。尽管在一对一的会议上,我明确地告诉他们要加倍他们的估计(但没有用),这样他们就不会在管理层看来很糟糕。
我个人的经验是将我的项目时间表延长两倍。有趣的是,这更接*实际需要的时间。
3.确认偏差
确认偏好是指以确认或强化个人先前的信念或价值观的方式搜索、解释、偏好和回忆信息的倾向。
- 维基百科
确认偏差是无意中挑选与给定假设一致的信息。
我有几个同事被一位经理告知要找到更好的证据来支持一个特定的论点(而不是采取适当的样本)。虽然这个方向可能来自高层,但它也可能在你寻找证据来支持/否定你想要构建的新特性时下意识地显现出来。
根据我的经验,避免确认偏差的最好方法是在开始工作之前决定如何评估一个实验/特征。
4.知识的诅咒
知识的诅咒是一种认知偏差,当一个人与其他人交流时,不知不觉地认为其他人有理解的背景,这种偏差就会发生。
- 维基百科
在某个领域有很强能力的人可能很难向缺乏技术背景的人解释相关概念。
来自 Pexels 的 ThisIsEngineering 摄影
我曾经遇到过一个非常好奇的非技术主管,他会突然问我一些技术问题。单词嵌入是如何工作的?波斯特格雷的 XYZ 指数是什么?
作为那种说话前需要思考的人,我经常笨手笨脚地试图找出如何向没有背景的人解释。这是知识的诅咒。
我最初开始在媒体上写作是为了帮助我理清思路,提高我的解释能力。
5.盲点偏差
偏见盲点就是认知偏见认识到偏见对他人判断的影响,而看不到偏见对自己判断的影响。
我们认识到其他人的偏见,但不是我们自己。
在多次失败的实验中,我对无监督学习产生了强烈的厌恶,因为它没有解决给定的问题。
当偏见导致我在头脑风暴会议期间否决无监督学习解决方案而没有真正考虑它们的优点时,这就成了问题。
过去的经验不应该妨碍正确的分析,否则会错过宝贵的机会。看到自己的偏见需要大量的自省(或真正诚实的同事)。
6.集体思考
群体思维是一种心理现象,发生在一个人群中,群体中对和谐或从众的渴望导致了一个非理性或功能失调的决策结果。
- 维基百科
潜意识中对达成一致的渴望压倒了理性的决策。
从包括 Techstars 在内的多个创业加速器毕业后,我得出的结论是,这是创业公司内部的常态。
在之前的一家公司,联合创始人(包括我自己)经历了一波自我强化的乐观主义,最终走向了失败。作为一个团队,我们低估了开发的复杂性,高估了客户的接受度。
许多有趣的研究和文章都是关于群体思维的,包括美国宇航局的挑战者号灾难。
7.票据法律
被称为乐器定律的概念,或者被称为锤子定律、【1】马斯洛的锤子(或木槌)或金锤子、【a】是一种认知偏差,涉及到对一种熟悉工具的过度依赖。
- 维基百科
偏向于使用熟悉的工具,即使它们对某项任务来说可能不是最佳的。
如果你只有一把锤子,所有的东西看起来都像钉子。—亚伯拉罕·马斯洛
当我第一次进入机器学习的时候,我唯一感到舒服的库是 sklearn。所以每次有新任务出现,我就琢磨怎么用 sklearn 解决。
在我深入研究 NLP 之前,这种方法一直工作得很好,因为 NLP 有许多更合适的包。当我试图用我所知道的破解解决方案而不是探索更好的选择时,时间被浪费了。
现在,我试图在每个问题上从头开始,评估现有的工具,以及研究新的工具。
8.从众情绪
跟风效应是一种现象,在这种现象中,信仰、想法、时尚和趋势被他人采纳的速度越快。
- 维基百科
以某种方式做某事是因为你反复听到别人这么做,而不是自己进行客观的评估。
我们把它扔给神经网络吧。
我听说过在太多情况下使用神经网络的建议,当时一个不太复杂的模型就足够了。我把这归咎于跟风效应和人们不断在新闻中听到神经网络。
有趣的是,我猜想大多数“人工智能驱动”的产品都不是由深度学习驱动的。但是阅读《麻省理工科技评论》或《T2 科技危机》时,你会得到相反的印象。
Imgflip
结论
我们生活在一个极其复杂的世界里,不可能分析每一条信息。我假设我们发展了这些偏见来减少与日常活动相关的精神负担。
一些启发是有帮助的。有些不是。但是根据定义,如果我们能够减少这些经过充分研究的负面偏见对我们自己的影响,我们就能够成为组织中更有效的决策者。
认知计算。它能用来做什么?
原文:https://towardsdatascience.com/cognitive-computing-what-can-it-be-used-for-8af4721928f5?source=collection_archive---------30-----------------------
计算机还会以任何方式让我们吃惊吗?一些令人惊讶的潜力可能存在于认知计算中——一套被广泛认为是人工智能最重要的表现的技能。
早在我的大学时代,后来在我职业生涯的开始,我写软件。我挣了作为程序员的第一份薪水。我经常熬夜,甚至通宵纠正无尽的代码错误。有时候,我写的代码终于开始做我想让它做的事情,服务于它的预期目的。随着时间的推移,这样的时刻变得越来越频繁。我经常想程序员是否会被取代。但是怎么做,用什么做?我喜欢的科幻文学充斥着机器人、人工智能和自学技术的故事,它们超越了自己的界限,开始违反规则、程序和算法。这些技术设法从错误中学习并积累经验。那时候都是科幻小说。一个除了程序员分配给它的任务之外还能做任何事情的计算机程序?真是错觉。但是后来我又碰到了其他概念,比如自学习机器,神经网络。
事实证明,一个计算机程序可以积累经验,并用它来修改自己的行为。实际上,机器从经验中学习,这些经验要么是它们自己直接获得的,要么是植入它们记忆中的。我了解了模拟人脑的算法。他们在寻找特定问题的最佳解决方案时进行自我调整。我了解了认知计算,我想在这篇文章中分享我对这个主题的思考。
当电脑处理数字时,它会观察我的脸
所有现有的认知计算定义都有一些共同的特征。一般来说,这个术语指的是主要来自对人脑功能的研究的技术集合。它描述了各种人工智能和信号处理的结合。两者都是机器意识发展的关键。它们体现了先进的工具,如机器的自我学习和推理,这些机器可以得出自己的结论,处理自然语言,产生语音,与人类互动等等。这些都是人机协作的方面。简而言之,认知计算一词指的是一种模仿人脑处理信息的方式并增强人类决策的技术。
认知计算。它能用来做什么?
认知计算模仿人类思维。它增加了使用它的设备,同时增强了用户自身的能力。认知机器可以主动理解这种语言,并对从自然语言交互中提取的信息做出反应。它们还能识别物体,包括人脸。它们的复杂程度是人类历史上任何产品都无法比拟的。
诺贝特,该吃点心了
本质上,认知计算是一组使机器变得更加智能,同时也更加人性化的特性和属性。认知计算可以被视为技术游戏规则的改变者,以及连接人和他们操作的机器的一种新的、微妙的方式。虽然它既不是情感的也不是精神的,但这种联系肯定不仅仅是主体和客体之间的关系。
由于这一特性,Siri(苹果公司)等电脑助手必然会逐渐变得更像人类。开发这些功能的努力将集中在计算机技术开发者面临的最大挑战上。这是为了让机器准确理解人类,即不仅理解人们提出的问题,还理解他们的潜在意图和来自用户的有意义的暗示,这些用户正在处理给定的问题。换句话说,机器应该考虑人类行为的概念和社会背景。一个例子?向电脑助手提出一个关于一天中的时间的简单问题,可能很快就会得到一个就事论事的回答,然后是一个真诚的建议:“现在是下午 1:30。休息一下,吃点点心怎么样?你说呢,诺贝特?”
亲爱的机器——请给我建议
我想在这里停一会儿,让读者参考我以前的机器学习文章。在这篇文章中,我说机器技术使计算机能够学习,从而更有效地分析数据。机器学习增加了计算机的整体“经验”,它通过执行任务来积累这些经验。例如, IBM 的沃森,我在许多场合提到过的计算机,理解自然语言问题。为了回答这些问题,它搜索了各种各样的大型数据库,无论是商业、数学还是医学数据库。随着每一个连续的问题(任务),计算机磨练它的技能。它吸收的数据越多,接受的任务越多,它的分析和认知能力就越强。
机器学习已经是一项复杂的、尽管非常基础的机器技能,其与人脑相似。它允许基于经验的各种自我改进。然而,直到认知计算进入画面,用户才能真正享受与实际智能技术的交互。该机器不仅提供结构化信息的访问,还能自主编写算法并提出问题的解决方案。例如,一名医生可能希望 IBM 的沃森不仅要筛选数十亿条信息(大数据)并使用它来得出正确的结论,还要为解决手头的问题提供思路。
在这一点上,我想提供一个来自日常经验的例子。车载汽车导航系统依赖于大量的地形数据,它分析这些数据以生成地图。然后显示地图,包括从所请求的 A 点到 B 点的路线,并适当考虑用户的旅行偏好和先前的路线选择。这依赖于机器学习。然而,直到机载机器建议了一条避开繁忙交通的特定路线,同时融入了我们的习惯,它才开始接*认知计算。
数字运算并不代表一切
所有这些都很好,但是今天的工程师们是从哪里得到这样的想法,计算机不应该只是快速处理数字?IBM 阿尔马登研究中心(Almaden Research Center)的负责人杰弗里·韦尔泽(Jeffrey Welser)花了* 50 年的时间开发人工智能,他给出了这个简单的答案:“人类的大脑不能很好地处理数字,但它可以很好地处理其他事情,如玩游戏、策略、理解谜语和自然语言,以及识别人脸。所以我们研究了如何让计算机做到这一点”。
使用算法和自我学习来开发一台帮助人类决策的机器的努力已经产生了惊人的效果。在设计沃森的过程中,IBM 显著提高了技术世界的标准。
我们现在如何应用它?
对人脑的研究已经成为推进信息技术的跳板,毫无疑问,它将对我们的生活产生更广泛的影响,影响到商业、安全、安保、营销、科学、医学和工业等领域。“看到”理解自然语言和识别物体的计算机可以帮助每个人,从普通的学校教师到寻找癌症治疗方法的科学家。在商业领域,随着时间的推移,这项技术应该有助于更有效地利用人力资源,找到获得新能力的更好方法,并最终放松因坚持传统管理模式而导致的僵化的公司规则。在医学领域,已经有很多关于医生对优秀分析工具——IBM 的 Watson——的希望的文章。在医疗保健领域,Watson 将即时浏览患者的病史,帮助诊断健康状况,并使医生能够即时访问以前无法在要求的时间范围内检索到的信息。这可能成为诊断和治疗尚不能治愈的疾病的重大突破。
沃森已经引起了肿瘤学界的极大兴趣,其成员对计算机快速搜索巨型癌症数据库(这对癌症治疗至关重要)并为医生提供重要提示的能力寄予厚望。
与量子计算相结合,这将成为解决复杂技术问题的强大工具。即使在今天,营销专家也认识到认知计算系统的价值,它在自动化、客户关系和服务个性化方面发挥着越来越重要的作用。数据处理、战略规划和建模非常重要的人类活动的每个领域,最终都将受益于这些技术突破。
第三个机器时代
有些人甚至宣称认知计算将开启第三个 IT 时代。20 世纪早期,计算机仅仅被视为计数机器。从 20 世纪 50 年代开始,他们开始依赖庞大的数据库。在 21 世纪,计算机学会了看、听和思考。由于人类思维是一个复杂的过程,其结果往往是不可预测的,也许我们可以假设,人类和机器的认知联盟将很快导致现在难以预见的发展。
未来的机器必须改变人们获取和拓宽知识的方式,以实现“认知”加速。然而,不管未来会带来什么,今天,随着其更有效的思维,计算机正变得越来越令人兴奋。
相关文章:
- 只有上帝才能数得那么快——量子计算的世界
——机器学习。计算机时代的到来
- 根据我们的电脑…你不存在
图片来源:Shutterstock
科恩的卡帕
原文:https://towardsdatascience.com/cohens-kappa-9786ceceab58?source=collection_archive---------1-----------------------
理解科恩的卡帕系数
我第一次在 Kaggle 上看到 Cohen 的 kappa 是在数据科学碗比赛期间——尽管我没有积极参加比赛,而且指标是二次加权 Kappa,但我还是用一个内核来试验这个指标,看看它是如何工作的,因为我以前从未见过它。利物浦大学离子交换竞赛的启动为我提供了另一个更好地理解这一指标的机会,尽管这一次我将积极参赛,因为这是我告诉自己今年将做得更多的事情。既然我已经让自己对公众负责,让我们来打破科恩的卡帕。
对于那些关注我的帖子的人,你会知道我喜欢把我的帖子分成更小的部分来理解,然后把它们连接起来。这篇文章也不例外,到最后,你将能够:
- 区分信度和效度
- 解释科恩的卡帕
- 评估科恩的卡帕
效度和信度
在进入科恩的 Kappa 之前,我想先奠定一个关于有效性和可靠性的重要基础。当我们谈论有效性时,我们关心的是测试在多大程度上测量了它声称要测量的东西,或者换句话说,测试有多准确。另一方面,可靠性更关心的是测试在一致的条件下产生相似结果的程度,或者换句话说,测试的精确度。
利用离子转换竞争问题,我将把这两种测量方法放在一起看,这样我们就知道如何区分它们。
利物浦大学的问题是,当离子通道打开时,现有的检测方法既慢又费力,因此他们希望数据科学家采用机器学习技术来快速自动检测原始数据中的离子通道当前事件,因此他们为我们提供了激动人心的离子切换比赛。有效性将测量所获得的分数是否代表离子通道是否打开,可靠性将测量所获得的分数在识别通道打开或关闭时是否一致。
图 1:可靠性和有效性的飞镖靶示例。《研究方法知识库》,第二版。互联网 WWW 页面,网址:【https://www.socialresearchmethods.net/kb/ (截至 2020 年 1 月 30 日的最新版本)。
为了使实验结果有用,实验的观察者必须对其解释达成一致,否则观察者的主观解释就会起作用,因此良好的可靠性是很重要的。然而,信度可以分为不同的类型,评分者内信度和评分者间信度。
评分者内部的可靠性与同一个人所做的不同测量之间的一致程度有关。
图 2:评分者内部信度示意图
评分者之间的可靠性与两个或更多评分者之间的一致程度有关。
图 3:评分者间信度示意图
什么是科恩的 Kappa?
Cohen 的 kappa 测量两个评分者之间的一致程度,他们将 N 个项目分成 C 个互斥的类别。
一个简单的想法是,科恩的 Kappa 是对评价同一事物的两个评价者的可靠性的定量测量,根据评价者偶然同意的频率进行了校正。
评估科恩的 Kappa
kappa 的值可以小于 0(负值)。0 分意味着评分者之间随机达成一致,而 1 分意味着评分者之间完全一致。因此,小于 0 的分数意味着一致性小于随机机会。下面,我将向你展示解决这个问题的公式,但重要的是,你要熟悉图 4,以便有更好的理解。
图 4:用于解释评定者结果的 N×N 网格
我突出显示两个网格的原因将在一会儿变得清楚,但是现在,让我分解每个网格。
A = >两位评分者都说正确的例子总数。评分者们意见一致。
B = >评定者 2 认为不正确,但评定者 1 认为正确的实例总数。这是一个分歧。
C = >评定者 1 认为不正确,但评定者 2 认为正确的实例总数。这也是一个分歧。
两个评分者都说不正确的情况总数。评分者都同意。
为了计算出 kappa 值,我们首先需要知道一致的概率(这解释了为什么我突出了一致对角线)。这个公式是通过将评分者同意的测试次数相加,然后除以测试总数得出的。使用图 4 中的例子,这意味着(A + D)/(A + B+ C+ D)。
图 5:达成一致的可能性
完美!下一步是计算出随机一致的概率。使用图 4 作为指导,期望值是评价人 1 说正确的总次数除以实例总数,乘以评价人 2 说正确的总次数除以实例总数,加上评价人 1 说不正确的总次数乘以评价人 2 说不正确的总次数。这需要考虑很多信息,所以在图 6 中,我用上面的网格列出了这个等式。
图 6:推导随机一致概率的公式
最后,Cohen 的 Kappa 公式是一致概率去掉随机一致概率除以 1 减去随机一致概率。
图 7:科恩的卡帕系数公式。
太好了!你现在能够区分可靠性和有效性,解释科恩的 kappa 并对其进行评估。这个统计非常有用,尽管自从我理解了它是如何工作的,我现在相信当优化算法到一个特定的度量时,它可能没有被充分利用。此外,科恩的 kappa 也很好地衡量了多类别和不*衡的类别问题。
附言如果你想让我报道一些与数据科学有关的事情,你可以直接在 Twitter 上给我发消息 @KurtisPykes 或者回复这个帖子。
维基百科定义。科恩的卡帕头。https://en.wikipedia.org/wiki/Cohen%27s_kappa
薄荷 TMS 教程由基督教霍尔曼。(2015 年 4 月 5 日)。卡帕系数。https://www.youtube.com/watch?v=fOR_8gkU3UE
查尔斯·赞恩茨。科恩的卡帕。http://www . real-statistics . com/reliability/inter rater-reliability/cohens-kappa/
科恩的卡帕:它是什么,什么时候使用它,以及如何避免它的陷阱
原文:https://towardsdatascience.com/cohens-kappa-what-it-is-when-to-use-it-and-how-to-avoid-its-pitfalls-e42447962bbc?source=collection_archive---------33-----------------------
当整体准确性有偏差时的替代方案,但不要盲目相信统计数据
由马瑞特威德曼
介绍
科恩的 kappa 是一个常用于评估两个评分者之间的一致程度的指标。它还可以用来评估分类模型的性能。
例如,如果我们有两个银行家,我们要求他们将 100 名客户分为两类进行信用评级,即好和坏,基于他们的信用价值,我们可以通过科恩的 kappa 来衡量他们的同意程度。
类似地,在分类模型的背景下,我们可以使用 Cohen 的 kappa 来比较机器学习模型预测和人工建立的信用评级。
像许多其他评估指标一样,科恩的 kappa 是基于混淆矩阵计算的。然而,与计算整体准确性相反,科恩的 kappa 考虑了类别分布的不*衡,因此解释起来可能更复杂。
在本文中,我们将指导您计算和解释 Cohen 的 Kappa 值,特别是与总体精度值进行比较。我们将表明,在由于类别分布的巨大不*衡而导致整体准确性失败的情况下,Cohen 的 kappa 可能会提供对模型性能的更客观的描述。一路上,我们还将介绍几个在解读科恩的 kappa 价值观时需要牢记的小技巧!
衡量不*衡数据集上的性能改进
让我们使用由 UCI 机器学习库提供的德国信用数据来关注银行贷款的分类任务。在该数据集中,根据银行的标准,银行客户被分配了“坏”信用评级(30%)或“好”信用评级(70%)。出于本文的目的,我们通过 bootstrapping 夸大了目标类信用评级的不*衡,给出了 10%的“坏”信用评级和 90%的“好”信用评级:这是一个高度不*衡的数据集。夸大不*衡有助于我们在这篇文章中更清楚地区分“整体准确性”和“科恩的 kappa”。
让我们在目标列上使用分层抽样将数据划分为训练集(70%)和测试集(30%),然后训练一个简单的模型,例如决策树。鉴于这两个阶层之间的高度不*衡,该模型的表现不会太好。然而,让我们将它的性能作为本次研究的基准。
图 1 显示了这个基线模型的混淆矩阵和准确性统计。该模型的总体精度相当高(87%),暗示该模型的性能是可接受的。然而,在混淆矩阵中,我们可以看到,该模型在 30 个信用评级不佳的信用客户中,只能正确地对 9 个进行分类。这也可以从“坏”类的低敏感度值(仅为 30%)看出。基本上,决策树对大多数“好”客户进行了正确分类,而忽略了少数“坏”客户的必要表现。类别先验概率中的不*衡补偿了分类中的这种草率。现在让我们注意一下,Cohen 的 kappa 值仅为 0.244,在其范围[-1,+1]内。
图 1:基线模型的混淆矩阵和准确性统计,即在高度不*衡的训练集上训练的决策树模型。总体准确率相对较高(87%),尽管该模型只检测到少数信用评级不佳的客户(敏感度仅为 30%)。
让我们通过强迫模型承认少数类的存在来改善模型性能。我们这次在训练集上训练相同的模型,其中少数类已经使用 SMOTE 技术过采样,两个类的类比例都达到 50%。
为了提供关于该模型的混淆矩阵的更多细节,具有“坏”信用评级的 30 个客户中的 18 个被该模型检测到,导致新的敏感度值为 60%,而不是之前的 30%。对于该模型,Cohen 的 kappa 统计值现在是 0.452,与之前的值 0.244 相比有显著的增加。但是整体的准确性呢?对于第二个模型,它是 89%,与之前的值 87%没有太大区别。
当总结时,我们得到两个非常不同的图片。从整体精度来看,模型性能根本没有太大变化。然而,根据科恩的 kappa 很多都变了!哪种说法是正确的?
图 2:改进模型的混淆矩阵和准确性统计。决策树模型在更*衡的训练集上训练,其中少数类已被过采样。总体准确性几乎与基线模型相同(89%对 87%)。然而,Cohen 的 kappa 值显示出从 0.244 到 0.452 的显著增加。
从混淆矩阵中的数字来看,似乎 Cohen 的 kappa 对模型在使用不*衡数据时的表现有更现实的看法。为什么科恩的 kappa 更关注少数民族阶层?实际是如何计算的?我们来看看吧!
科恩的卡帕
Cohen 的 kappa 通过以下公式计算[1]:
其中,p_0 是模型的总体精度,而 p_e 是模型预测和实际类值之间的一致性的度量,就好像是偶然发生的一样。
在像我们这样的二元分类问题中,p_e 是 p_e1 和 p_e2 的和,p _ E1 是预测值偶然与第 1 类(“好”)的实际值一致的概率,p _ E2 是预测值偶然与第 2 类(“坏”)的实际值一致的概率。假设两个分类器(模型预测和实际类值)是独立的,这些概率 p _ e2 和 p_e2 是通过乘以实际类的比例和预测类的比例来计算的。
将“坏”视为阳性类别,基线模型(图 1)将 9%的记录(假阳性加真阳性)归入“坏”类别,将 91%的记录(真阴性加假阴性)归入“好”类别。因此 p_e 为:
因此科恩的 kappa 统计数据:
该值与图 1 中报告的值相同。
实际上,科恩的 kappa 排除了分类器和随机猜测一致的可能性,并测量了它做出的无法用随机猜测解释的预测的数量。此外,Cohen 的 kappa 试图通过考虑随机猜测的正确分类来纠正评估偏差。
科恩卡帕的痛点
在这一点上,我们知道 Cohen 的 kappa 在处理不*衡数据时是一个有用的评估指标。然而,科恩的卡帕也有一些缺点。让我们一个一个来看看。
全范围[-1,+1],但不相等
如果目标阶层分布均衡,则更容易达到更高的科恩卡帕值。
对于基线模型(图 1),预测类的分布紧密跟随目标类的分布:27 个预测为“差”对 273 个预测为“好”,30 个实际为“差”对 270 个实际为“好”。
对于改进的模型(图 2),两个类别分布之间的差异更大:40 预测为“差”对 260 预测为“好”,30 实际为“差”对 270 实际为“好”。
如最大 Cohen kappa 的公式所示,预测和实际目标类别的分布差异越大,最大可达 Cohen kappa 值越低。最大 Cohen kappa 值表示混淆矩阵中假阴性或假阳性的数量为零的边缘情况,即所有具有良好信用评级的客户,或者所有具有不良信用评级的客户都被正确预测。
其中,p_max 是给定目标类和预测类的分布时,模型可达到的最大总精度:
对于基线模型,我们得到 p_max 的以下值:
而对于改进的模型,它是:
Cohen kappa 的最大值是基线模型的:
对于改进的模型,它是:
结果表明,实际目标类别和预测目标类别之间的分布差异较大的改进模型只能达到高达 0.853 的 Cohen kappa 值。而基线模型可以达到值 0.942,尽管性能更差。
对于*衡的数据,Cohen 的 kappa 更高
当我们计算 Cohen 的 kappa 时,我们强烈假设目标类和预测类的分布是独立的,并且目标类不影响正确预测的概率。在我们的例子中,这意味着具有良好信用评级的信用客户与具有不良信用评级的信用客户获得正确预测的机会相等。然而,因为我们知道我们的基线模型偏向于大多数“好”类,所以违反了这个假设。
如果这个假设没有被违反,就像在目标类*衡的改进模型中一样,我们可以达到更高的 Cohen kappa 值。这是为什么呢?我们可以把 Cohen 的 kappa 公式改写为正类概率的函数,当正类概率为 0.5 时函数达到最大值[1]。我们通过将相同的改进模型(图 2)应用于不同的测试集来测试这一点,其中积极的“坏”类的比例在 5%和 95%之间变化。我们通过引导原始测试数据为每个类分布创建 100 个不同的测试集,并根据结果计算*均 Cohen kappa 值。
图 3 显示了*均 Cohen 的 kappa 值与正类概率的对比——是的!当模型应用于*衡数据时,Cohen 的 kappa 确实达到了最大值!
图 3。Cohen 的 kappa 值(在 y 轴上)是在测试数据(在 x 轴上)中具有不同正类概率的相同模型中获得的。y 轴上的 Cohen kappa 值被计算为所有 Cohen kappa 的*均值,该*均值是通过对固定类别分布的原始测试集进行 100 次自举而获得的。该模型是在*衡数据上训练的决策树模型,在文章开始时介绍过(图 2)。
科恩的 kappa 很少提到预期的预测准确性。
Cohen 的 kappa 的分子,(p_0 - p_e),讲的是模型的观测整体精度和偶然可以得到的整体精度的差别。公式的分母(1- p_e)表示这个差值的最大值。
对于一个好的模型,观测差和最大差接*,Cohen 的 kappa 接* 1。对于一个随机模型来说,整体的精度都是因为随机的偶然性,分子是 0,科恩的 kappa 是 0。科恩的 kappa 理论上也可能是负数。那么,模型的整体准确性将会比通过随机猜测获得的更低。
鉴于上面的解释,科恩的 kappa 不容易按照预期的准确性来解释,并且通常不建议遵循任何口头类别作为解释。例如,如果您有 100 个客户和一个总体准确率为 87 %的模型,那么您可以预期正确预测 87 个客户的信用评级。科恩的 kappa 值 0.244 并没有给你提供这么容易的解读。
摘要
在本文中,我们解释了如何使用和解释 Cohen 的 kappa 来评估分类模型的性能。虽然 Cohen 的 kappa 可以在处理不*衡数据时纠正整体准确性的偏差,但它有一些缺点。因此,下次您查看模型的评分标准时,请记住:
- 在处理不*衡数据时,Cohen 的 kappa 比整体准确性更能提供信息。在比较或优化分类模型时,请记住这一点!
- 看看混淆矩阵中的行和列的总数。目标/预测类的分布相似吗?如果不是,最大可达 Cohen kappa 值将会更低。
- 同一个模型对于不*衡的测试数据会给出比*衡的测试数据更低的 Cohen kappa 值。
- 科恩的 kappa 很少提到单个预测的预期准确性
这项研究使用的工作流程如图 4 所示。在工作流程中,我们训练、应用和评估两个决策树模型,这两个模型预测信用客户的信用价值。在顶部分支中,我们训练基线模型,而在底部分支中,我们使用 SMOTE 技术在自举训练集上训练模型。该工作流程可从 KNIME Hub 上的 Cohen 的 Kappa 评估分类模型页面下载。
图 4:这个 KNIME 工作流训练了两个决策树来预测客户的信用评分。在顶部分支中,基线模型根据不*衡的训练数据进行训练(90%“好”对 10%“坏”的类记录)。在底部分支中,在新的训练数据集上训练改进的模型,其中少数类已经过采样(SMOTE)。用于评估分类模型的工作流 Cohen's Kappa 可在 KNIME Hub 上获得。
参考
[1]布兰德,马丁。"科恩的卡帕"约克大学健康科学系https://www-users . York . AC . uk/~ mb55/MSC/clin met/week 4/kappa _ text . pdf。【2020 年 5 月 29 日访问】 (2008)。
如最初发表于 的《新闻报》 。
类固醇上的 Colab:带 SSH 访问和 Visual Studio 代码服务器的免费 GPU 实例
原文:https://towardsdatascience.com/colab-free-gpu-ssh-visual-studio-code-server-36fe1d3c5243?source=collection_archive---------17-----------------------
一步一步地引导 SSH 进入 Google Colab 提供的免费 GPU 实例,并安装 Visual Studio Code Server。
正如你们大多数人已经知道的,谷歌研究提供了免费的 Jupyter 笔记本环境实例,带有 T2 图形处理器和 TPU,完全在云中运行。该*台名为(简称“Colab”),当你想进行快速实验或构建新的机器学习模型时,它是一个很好的资源,因为不需要设置:你需要的只是一个浏览器!
图片作者。与 GPU 的 Colab 会话
然而,当事情变得棘手时,一个简单的 Jupyter 笔记本界面可能会相当有限:我们可能需要有一个 SSH 会话!我们开始吧!
第一步。从 ngrok 获取令牌
在 ngrok 上免费注册,从左侧的认证设置中获取一个 Authtoken。
图片作者。从 ngrok 获取免费令牌。
第二步。在 Colab 上安装并运行 ngrok
在 Colab 的一个笔记本单元格内,复制并粘贴下面的代码,插入来自 ngrok 的令牌并运行单元格。
# Install useful stuff
! apt install --yes ssh screen nano htop ranger git > /dev/null# SSH setting
! echo "root:carbonara" | chpasswd
! echo "PasswordAuthentication yes" > /etc/ssh/sshd_config
! echo "PermitUserEnvironment yes" >> /etc/ssh/sshd_config
! echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
! service ssh restart > /dev/null# Download ngrok
! wget -q -c -nc [https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip](https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip)
! unzip -qq -n ngrok-stable-linux-amd64.zip# Run ngrok
authtoken = "PUT_YOUR_TOKEN_HERE"
get_ipython().system_raw('./ngrok authtoken $authtoken && ./ngrok tcp 22 &')
! sleep 3# Get the address for SSH
import requests
from re import sub
r = requests.get('[http://localhost:4040/api/tunnels'](http://localhost:4040/api/tunnels'))
str_ssh = r.json()['tunnels'][0]['public_url']
str_ssh = sub("tcp://", "", str_ssh)
str_ssh = sub(":", " -p ", str_ssh)
str_ssh = "ssh root@" + str_ssh
print(str_ssh)
图片作者。用 ngrok 在 Colab 中启动一个 SSH 会话。
作为输出,您应该会收到如下内容(地址和端口可能不同):
ssh [root@0.tcp.ngrok.io](mailto:root@0.tcp.ngrok.io) -p 14407
将它复制并粘贴到您喜欢的终端模拟器中,当需要密码时插入 carbonara 并享受您的 SSH 会话!当然,你可以随心所欲地修改密码!
图片作者。SSH 会话:在 Colab 实例内部
不习惯 Linux 命令行?查看这篇文章:每个数据科学家都应该知道的基本 Linux 控制台命令。
第三步。运行 Visual Studio 代码服务器
SSH 很好,但是直接在浏览器中拥有一个完整的代码编辑器更好!现在让我们看看如何在 Colab 实例中安装 Visual Studio 代码。
首先,我们需要安装我们的 Google Drive。
# Mount Google Drive and make some folders for vscode
from google.colab import drive
drive.mount('/googledrive')
! mkdir -p /googledrive/My\ Drive/colabdrive
! mkdir -p /googledrive/My\ Drive/colabdrive/root/.local/share/code-server
! ln -s /googledrive/My\ Drive/colabdrive /
! ln -s /googledrive/My\ Drive/colabdrive/root/.local/share/code-server /root/.local/share/
系统将提示您通过插入在第二个页面上生成的令牌来授权访问。
图片作者。在 Colab 上安装 Google Drive
现在,让我们下载、安装并运行 Visual Studio 代码的服务器版本。
! curl -fsSL [https://code-server.dev/install.sh](https://code-server.dev/install.sh) | sh > /dev/null
! code-server --bind-addr 127.0.0.1:9999 --auth none &
图片作者。在 Colab 上下载并安装 Visual Studio 代码服务器
让我们用端口转发启动另一个 SSH 会话(用您的地址和端口替换 ngrok 地址和端口):
ssh -L 9999:localhost:9999 [root@0.tcp.ngrok.io](mailto:root@0.tcp.ngrok.io) -p 14407
然后在打开浏览器 http://127.0.0.1:9999
图片作者。运行在 Colab 上的 Visual Studio 代码服务器
由于我们之前已经安装了 Google Drive,设置、Visual Studio 代码的扩展和项目文件(如果保存在/colabdrive 下)将通过会话保持不变。
享受 Colab 中的 Visual Studio 代码!
参考
- https://gist . github . com/yashkumaratri/204755 a 85977586 cebb 58 DC 971496 da
- https://stack overflow . com/questions/48459804/how-can-I-ssh-to-Google-co laboratory-VM
- https://medium . com/@ meet _ Patel/how-to-ssh-into-Google-colab-and-run-scripts-from-terminal-notebook-3931 f 2674258
联系人: LinkedIn | Twitter
Colab Pro:物有所值吗?
原文:https://towardsdatascience.com/colab-pro-is-it-worth-the-money-32a1744f42a8?source=collection_archive---------0-----------------------
10 美元有多大作用?我们做了测试。你做阅读。
Google Colab 已经推出有一段时间了,但最*我们有一个升级到 Pro 版本的选项,这可能会让你获得更快的 GPU、更长的运行时间和更多的 RAM。但是差别有多大呢?值 10 美元/月吗?让我们找出答案。
我们已经写了关于 Google Colab(免费版)的文章,所以如果你还没有:
[## Google Colab:它与支持 GPU 的笔记本电脑相比如何?
Colab 简介、运行时、性能比较…以及疑难解答
towardsdatascience.com](/google-colab-how-does-it-compare-to-a-gpu-enabled-laptop-851c1e0a2ca9)
为了进行测试,我们使用了免费版和专业版的服务,在肺炎数据集上执行深度学习任务。数据集由大约5000 张肺部 x 光图像组成,非常适合这类任务。
这篇文章的结构如下:
- 一般差异
- GPU 比较
- RAM 比较
- 案例:模型训练时间比较
- 判决
所以事不宜迟,让我们开始吧!
一般差异
本节的目标是讨论免费版和专业版服务之间的一般差异,如 CPU、可用磁盘空间和运行时。我不认为这 3 个会对你的购买决定产生太大影响(也许最后一个除外),因为我在免费版中没有遇到过这些问题。
话虽如此,以下是 CPU 之间的比较:
- Colab(免费) —英特尔至强 CPU @ 2.20GHz
- Colab (Pro) —英特尔至强 CPU @ 2.30GHz
所以在这里没有太大的区别——但是再一次,你可能没有使用 Colab 作为它的 CPU,所以这部分真的没有那么重要。
至于磁盘大小,我在两者上都获得了相同的 34GB 可用内存——这有点奇怪——但这对于 99.99%的用户来说已经足够了。运行时间可能会让你吃惊。以下是谷歌的官方声明:
使用 Colab Pro,您的笔记本电脑可以保持连接长达 24 小时,空闲超时相对宽松。尽管不能保证持续时间,但空闲超时有时可能会有所不同。[1]
对于免费版本,我们最多有 12 个小时的运行时间,空闲超时更严格。尽管有避免这种情况的方法,本文中描述了一种可能的解决方案。
好了,我们现在知道了一些基本的区别。在接下来的部分中,我们将探索 RAM 和 GPU 的不同之处,之后,我们还将在真实数据集上比较训练持续时间。
GPU 比较
Google Colab 最重要的一个方面是 GPU。无论您的笔记本电脑有多强大,您都可以使用现代化的强大 GPU。下面是您可以在免费层和专业层使用的 GPU:
- Colab(免费) —特斯拉 K80
- Colab (Pro) —特斯拉 P100-PCIE-16GB
如果你不知道这些 GPU 之间有什么不同,那也没关系。这就是为什么我们准备了一张图表来比较可用的 GPU 内存:
不要担心高 RAM 运行时,这将在下一节讨论。从这一点上,你可以看到,使用 Pro 层,你可以获得大约 5GB 更多的 GPU 内存,这在理论上意味着神经网络训练过程应该更快(我们会看到这一点)。
RAM 比较
Colab 的 Pro 版本将让您访问一个高 RAM 运行时环境。理论上,这个运行时应该给我们更多的内存,以防标准的 12GB 不够用。我的大部分深度学习工作都是在“玩具”例子上,数据集只有几个 GB 大小,所以我从来没有遇到过 RAM 问题。
如果您需要更多的工作内存,您可以转到运行时—更改运行时类型:来更改运行时
但是 Pro 版默认给你的 RAM 多吗?
我很高兴你问了。让我们看看下一个可视化:
在启用高 RAM 环境之前,Pro 和免费版本完全相同。在你的项目中请记住这一点,但我发现 12.8GB 对于大多数情况来说已经足够了。
案例:模型训练时间比较
现在是你期待已久的时候了。在这里,我们将最后比较谷歌 Colab 的免费和专业层的培训时间的差异。如前所述,该模型是在肺炎数据集上训练的。
为同一个数据集准备了两种架构,第一种是自定义 CNN 架构,第二种是 DenseNet201 预训练网络,最后一层修改为输出两个类。您可以在下面看到自定义架构:
此外,以下是一些您可能会觉得有用的附加规范:
- 图像尺寸: 224x224
- 批量大小: 32
- 学习率: 0.001
- 历元: 20
- 优化器:亚当
- 标准:斜视
所以这里的一切都很标准,但我想分享这些信息,以防你想复制结果。
在训练期间,我记录了训练持续时间,该信息显示在下图中:
正如你所看到的,在免费版本中, DenseNet201 架构的培训过程持续了 50%的时间,而定制架构的培训时间减少并不显著。请记住这一点,因为您将在大多数时间使用预先训练的架构。
我想现在你已经有了做决定所需的所有信息。下一节我来说说我的看法。
判决
我们看到,在免费版本中,预构建架构的培训过程持续时间延长了 50%。 但这对你真的有意义吗?
请记住,即使是专业版,您最多只能运行 24 小时。对于一些企业来说,24 小时仍然不够,因为培训过程要持续几天甚至几周。
如果你是一个仍在学习数据科学和深度学习的人,那么我认为专业版没有实际好处,因为免费版将处理你会遇到的所有数据集。专业版将提供速度改进,但对大多数用户来说并不显著。
如果你绝对需要提高速度,那就去做吧——每月只需 10 美元。如果没有,把钱存起来做别的事情——你不会错过任何特别的事情。
你有什么想法?你们国家的 Pro 版速度快吗? 通知我。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
参考
[1]https://colab.research.google.com/signup#
数据科学家 GitHub:提交
原文:https://towardsdatascience.com/collaborate-on-github-like-a-pro-commit-d832e613b109?source=collection_archive---------65-----------------------
GitHub 的权威指南:提交
了解提交的组成部分、提交、重置或删除提交。
路易斯·尤西比奥(https://unsplash.com/@lceusebio)的照片
本文是 GitHub 协作后续系列的一部分。本文将尝试详细理解提交,比如提交的组成部分,在推送之前和之后删除提交,或者重置提交。
对于初学者来说,强烈推荐快速阅读这篇文章,像 Pro: Part1 一样在 GitHub 上协作。
这个系列,像 pro 一样在 GitHub 上协作,关注特定的主题:
- GitHub 入门 : 像 Pro 一样在 GitHub 上协作: Part1
- 分支: 像 Pro 一样在 GitHub 上协作: Part2
- 提交:像 Pro 一样在 GitHub 上协作:提交
什么是提交?
提交是用 git commit 命令创建的,用于捕获项目的状态。Git 存储一个提交对象,该对象指向快照暂存内容(已索引)。请参见下面红框中突出显示的提交阶段。
提交流程图
提交的组成部分:
让我们看一下提交对象,如下所示。提交中的三个主要组件包括哈希、头、和分支(主),如下所述。
提交对象
散列:每次提交都会为各自的提交创建一个唯一的散列。稍后使用这些散列恢复到以前的版本,或者查找有关提交的详细信息。只需要前七个字符来查找各自的提交。
头:显示当前工作分支。在上图中,头指向主分支,这意味着当前的工作分支在主分支上。
分支:默认情况下,开发的第一行(分支)命名为主。不同分支上的所有先前的工作被合并到 master。
要进一步理解这个概念,请参考这篇博客的帖子。
三次提交后主分支
切换到特定提交
基于用例,有多种方法可以检验特定的提交,比如进行临时或永久的切换,后退几步添加一个特性。
临时开关
要临时切换到第一次提交(7d8d1af)并从特定提交进行少量提交,请运行以下命令。
$ cd autos/ (git project root)
$ git checkout 7d8d1af (Use hash if you know it, else)
$ git checkout HEAD~3 (Use number of commits to go back, our case 3)$ git checkout -b new-branch 7d8d1af (create new branch on the commit)
$ git checkout branch_name (to go back to respective branch)
当签出提交时,头被分离。分离的头意味着该头没有指向最*的提交;相反,它指向签出时的提交。
临时提交签出流程
永久开关
要永久删除提交,使用 Git reset 。Git 复位主要有五种模式:软、混合、合并、硬、保持。有关详细信息和不同的解决方案,请参考堆栈溢出。
- Git reset — hard 将更改磁头、索引(阶段)和工作目录。记得运行 git status 来检查工作树是否干净,否则所有未提交的更改都将丢失。
- Git 复位—软将改变磁头,不改变索引(阶段)或工作目录。这是最安全的选择。
例如,我们希望重置到第一次提交(7d8d1af)。处理这种情况有两种方法。
- 提交未推送到远程
总是运行 git status 来检查工作树是否干净。要仅删除当前提交,但保留文件并对其进行索引,请使用 soft。
$ cd autos/ (git project root)
$ git reset --soft HEAD~3
“工作树是干净的”意味着没有你可以失去的未提交的工作。在这种情况下,安全地使用硬。
$ cd autos/ (git project root)
$ git reset --hard 7d8d1af (Use hash if you know it, else)
$ git reset HEAD~3 (Use number of commits to go back, our case 3)
在“工作树是而不是干净的”的情况下,你知道如果你直接使用 hard 可能会丢失一些未提交的工作,在命令 hard 之前运行“stash”来保存你的本地更改。
$ cd autos/ (git project root)
$ git stash
$ git reset --hard 7d8d1af
$ git stash pop
2。提交推送到远程
$ git revert --no-commit 7d8d1af HEAD
$ git commit
$ git push# To abort the above steps
git revert --abort
要了解更多关于 git 重置/恢复和返回到 Git 中先前状态的信息,请参考这篇写得很好的博客,有关代码,请参考 GitHub 库。
参考:
https://stack overflow . com/questions/4114095/how-do-I-revert-a-git-repository-to-a-previous-commit/4114122 # 4114122
面向数据科学家的 GitHub:第 1 部分
原文:https://towardsdatascience.com/collaborate-on-github-like-a-pro-part1-8d11ccf12084?source=collection_archive---------53-----------------------
权威 GitHub 指南:Git 添加— Git 提交— Git 推送
了解版本控制、git 配置、创建和克隆存储库以及提交。
本文是 GitHub 协作后续系列的第一部分。本文旨在解释两个或更多的人如何在 GitHub 上为数据科学项目协作、版本控制和校对他们的代码。
我们将讨论特定主题,如:
- GitHub 入门:像 Pro 一样在 GitHub 上协作: Part1
- 分支: 像 Pro 一样在 GitHub 上协作: Part2
- 提交: 像 Pro 一样在 GitHub 上协作:提交
在这些文章中,我们将有两个人在 GitHub 上合作。让我们给他们取两个假名,Sofi 和 Alec。
目录:
- 什么是版本控制
- 首次 Git 配置
- 创建一个本地知识库
- 克隆现有存储库
- Git 拉取—添加—提交—推送
计划的任务
由于这不是一篇关于数据清理的文章,我们将重点写几个函数来看看协作和版本控制是如何工作的。我们将使用二手车数据集。点击从下载数据集。
**Sofi and Alec**: *are working on a data cleaning project named “autos“. Sofi takes the initiative of gathering data, creating required .py, .ipynb files for the project.*
这篇文章展示了该项目的 EDA。这个项目的任务是基于 EDA 报告构建的。在本文中,我们将只看三个任务。
Sofi 创建一个项目文件夹(…/autos),其中包含两个文件:auto.csv 和 autos_analysis.ipynb。
现阶段 Sofi 的工作目录
**Sofi and Alec**: *Before starting the project, they browse through the different version control systems to find the one suitable for their project.*
版本控制系统(VCS)
在 软件工程 , 版本控制 (也称为 修订控制 , 源代码控制 ,或 源代码管理 )是一类负责管理变更的系统版本控制是 软件配置管理 的一个组件。
有许多版本控制系统。通常它们被分为两类:“集中式”和“分布式”。
【CVCS】
CVCS 基于这样的想法,即在某个地方(可能在服务器上)有一个项目的单一“中心”副本,程序员将他们的更改“提交”到这个中心副本。最受欢迎的 CVCS 是颠覆。
中央版本控制系统
【DVCS】
DVCS 不一定依赖中央服务器来存储项目文件的所有版本。相反,每个开发人员都“克隆”一个存储库的副本,并在他们自己的硬盘上拥有该项目的完整历史。这个副本(或“克隆”)具有原始副本的所有元数据。Git 和 Mercurial 是最流行的 DVCS。
分布式版本控制系统
****Sofi and Alec**: They decide to go *ahead with the popular distributed version control system GitHub. With the distributed system, branching and merging are much easier to achieve, and connecting to the network is not required.***
开源代码库
GitHub 的核心是 Git,这是一个由 Linux 创建者 Linus Torvalds 发起的开源项目。GitHub 是一个 Git 存储库托管服务,但是它增加了许多特性。虽然 Git 是一个命令行工具,但 GitHub 提供了一个基于 Web 的图形界面。它还提供了访问控制和一些协作功能,例如 wikis 和每个项目的基本任务管理工具。
****Sofi and Alec**: They configured Git following the below steps. Sofi created a git repository for Alec to clone.**
首次 Git 配置遵循以下步骤
**$ git config --global user.name "Sofi Sue"
$ git config --global user.email "sofi.sue@examplemail.com"
$ git config --global color.ui auto
$ git config --global core.editor VimAfter configuring git check settings:
$ git config --list**
Sofi:创建本地 git 存储库
**Add below files in the project folder (../autos/)1) **'.gitignore'** with the list of file names of the files to be ignored
2) **'ReadMe'** file as plain text or Markdown describing the project**
运行以下命令。
**$ cd autos/
$ git init
$ git add . *(adds all the files except the ones listed in .gitignore)*
$ *git commit — m ‘add a comment’***
如果没有要忽略的文件,则保留。git 忽略文件空白,随着项目的进展添加文件名。
现阶段 Sofi 的工作目录
恭喜你完成了你的第一次承诺!
犯罪
提交是用 git commit 命令创建的,用于捕获项目的状态。当您提交时,Git 存储提交对象,该对象包含指向您暂存的内容快照的指针。在上面的提交对象映像中,我们可以看到三个主要组件,hash、master 和 head。
提交对象
Hash :每次提交都会为各自的提交创建一个惟一的 Hash。在后面的阶段使用这七个字符作为这些散列,以恢复到该版本并找到提交的详细信息。
Master: 默认情况下,开发第一线(分支)的名称为 Master。不同分支上的所有先前的工作被合并到 master。
头:显示当前工作分支。上面的图像头指向主分支,这意味着当前的工作分支是主分支。
要进一步理解这个概念,请参考这篇博客帖子。
第一次提交后。Alphanum 是第一次提交的哈希的前 7 个字符。
在这个阶段,Sofi 决定将另一个文件 autos.py 添加到她的工作目录中。请注意,此文件不会被暂存,将显示为未跟踪的文件。要将它添加到存储库中,运行 git add autos.py。
现阶段 Sofi 的工作目录
Sofi:将本地 git 存储库连接到 GitHub
按照此处给出的说明在 GitHub 帐户中创建一个存储库。不要创建。gitignore”或“ReadMe”文件,因为我们已经在项目文件夹中创建了它。将链接复制到 git repo,然后返回到终端,用下面的命令将您的本地存储库连接到 Github。在这里找到 GitHub 库。
**$ git remote add origin [https://github.com/snehalnair/collaborate-github.git](https://github.com/snehalnair/collaborate-github.git)
$ git push -u origin master**
恭喜你,你第一次推送了远程 GitHub 服务器!
添加→提交→推送
下面的流程图总结了项目到目前为止所遵循的步骤
git-log —显示提交日志
每次提交后,根据用例检查提交细节。例如,要查看所有提交摘要,运行 git log-online。下面提到的是一些有用的 git 命令,它们可以在您或合作者每次提交后方便地检查细节。这里给出了详细的解释。
**$ git show
$ git log
$ git log —oneline
$ git log —stat
$ git log -p
$ git log -p --stat
$ git log --decorate**
Alec:将 git 存储库克隆到他的本地机器上
要获得现有 Git 存储库的副本,请在终端中运行下面的命令。
**$ git clone [https://github.com/snehalnair/collaborate-github.git](https://github.com/snehalnair/collaborate-github.git) autos
$ git pull**
该命令创建一个名为…/autos 的目录,在其中初始化一个. gitdirectory,从该存储库的最新版本中提取所有数据。导航到文件夹…/autos,查找存储库中的所有文件。
亚历克克隆的工作目录。注意,Alec 的工作目录只包含被跟踪的文件。autos.py 文件不是 Alec 目录的一部分,因为 Sofi 没有添加、提交和推送该文件。
****Sofi to Alec**: I forgot to add autos.py and the ReadMe file. Let me push autos.py file to the server first and then create a ReadMe file**Alec to Sofi**: I have worked on the ReadMe file already. Let me add it to the folder and push, and you can push autos.py in the after.**
Alec :运行以下命令创建并提交自述文件
**$ cd autos/
$ touch ReadMe
$ git pull
$ git add ReadMe
$ git commit -m ‘add ReadMe file’$ git push -u origin master**
在第二次提交后
Sofi :运行以下命令提交并推送 autos.py 文件
**$ cd autos/
$ git pull
$ git add autos.py
$ git commit -m ‘add autos.py file’$ git push -u origin master**
第三次提交后
工作目录
上述活动显示了在添加和推送文件之前运行 git pull 的重要性。Git pull 确保您拥有最新的存储库。这是 Sofi 和 Alec 当前的工作目录。
****Sofi and Alec**: The repository is ready for us to work. But we need to isolate our work, else we will start overwriting each others work/codes. Lets learn about branches before we proceed.**
对于接下来的步骤,请参考本文的下一部分,Sofi 和 Alec 将创建分支,并为他们的项目选择合适的分支工作流。参考 GitHub 库获取代码。
要了解更多关于 GitHub 的信息,请阅读这个博客。
参考:
https://www . atlassian . com/blog/software-teams/version-control-centralized-DVCs
https://en.wikipedia.org/wiki/Software_engineerin克
面向数据科学家的 GitHub:第 2 部分
原文:https://towardsdatascience.com/collaborate-on-github-like-pro-part2-26a6790e8f93?source=collection_archive---------57-----------------------
了解分支,使用 git 的不同分支工作流。
照片由诺亚·罗森菲尔德(https://unsplash.com/s/photos/noah-rosenfield)拍摄
这是 GitHub 协作后续系列的第二部分。在《T2》第一部中,两个同事 Sofi 和 Alec 开始着手一个数据清理项目,他们在彼此之间分配任务,创建和克隆存储库,并首次提交。
我们将讨论特定主题,如:
- GitHub 入门 : 像 Pro 一样在 GitHub 上协作: Part1
- Git 分支:像 Pro 一样在 GitHub 上协作: Part2
- 提交 Git: 像 Pro 一样在 GitHub 上协作:提交
在这些文章中,我们将有两个人在 GitHub 上合作。我们给他们取两个假名吧,Sofi 和 Alec。
目录:
- 分枝
- Git 上不同的分支工作流
- 拉动请求
- 合并冲突
**Sofi and Alec**: The repository is ready for us to work. But we need to isolate our work, else we will start overwriting each others work/codes. Lets learn about branches before we proceed.
分支
在进入分支工作流之前,让我们试着理解分支的概念。分支获取它所分支的提交的最新版本的副本。因此,您可以在一个隔离的环境中处理您的任务,而无需直接在主分支中进行更改。一旦任务完成,这个分支就可以合并到主分支中。让我们创建一个分支来更好地理解这个概念。
创建分支
要创建一个新的分支(test-branch ),运行下面的命令。
$ git branch test-branch
git 分支测试-分支命令增加了一个新的分支测试-分支
结账处
运行上面的命令添加了一个新的分支,但是,要移动到该分支,也就是说,要将头指向该分支,您必须运行 checkout git 命令。
$ git checkout test-branch
头指向测试分支
在一个命令中创建和检出新分支。
git checkout -b test-branch
强制删除分支
让我们删除这个分支,因为它们只是为了我们的理解。除非运行如下所示的强制删除命令,否则不能删除标题所指向的分支。
$ git branch -D test-branch
签出并删除分支
要删除一个分支而不强制删除,请签出到其他分支并运行 delete 命令。
$ git checkout master
$ git branch -d test-branch
**Sofi and Alec**: Now that we have a better understanding of branching technique. Lets find out if there is a suitable branching workflow that we can use.
Git 的分支工作流
对于 Git 用户来说,有许多流行的分支工作流适合他们各自的开发周期。
以下是最受欢迎的工作流程:
- Git 流
- GitHub 流
- GitLab 流程
- 一个流程
要了解更多关于这些分支工作流的信息,请阅读这篇[博客文章](http://4 branching workflows for Git)。
GitHub 流
这是最适合我们用例的分支工作流。GitHub flow 是一个轻量级的、基于分支的工作流,支持定期进行部署的团队和项目。要了解有关这一特定工作流程的更多信息,请参考此链接。
GitHub 流程:所有的提交都在特性分支上进行,并合并到主分支上。主分支总是可部署的。
那么它是如何工作的呢?
master
分支中的任何东西都是可部署的- 为了做一些新的事情,创建一个描述性命名的
master
分支(例如:new-oauth2-scopes
) - 在本地提交到那个分支,并定期将您的工作推送到服务器上相同的命名分支
- 当您需要反馈或帮助时,或者您认为该分支机构已经准备好进行合并时,打开一个拉动请求
- 在其他人已经审查并签署了该特性之后,您可以将它合并到 master 中(git merge master)
- 一旦它被合并并被推送到“主节点”,你可以并且应该立即部署(git push -u origin master)
使用 GitHub Flow 工作流开始协作
概述项目状态:Sofi 和 Alec 正在进行一个名为“autos”的数据清理项目。基于初步的分析,他们之间分配了以下任务。
**Sofi and Alec**: Lets create task based branches based on the GitHub Flow workflow instructions.
Sofi runs the below command in her computer
$ git checkout -b numcols-2-numdtypeAlec runs the below command in his computer
$ git checkout -b find-outliers
这就是分支在现阶段 Sofi 和 Alec 的电脑上的样子。它们看不到彼此的分支,因为它们尚未推送至服务器。
Sofi :在 autos.py 文件中输入以下功能
def numcol2numdtype(data, cols):
for col in cols:
data[col].str.replace('[^0-9]', '').astype('float')
return data
在更新了 autos.py 文件之后,是时候提交并提出一个拉请求了。注意:提交前和推送前总是运行 git pull 将最新版本的文件推送到存储库中。
$ git pull
$ git commit -m 'remove non-numeric from numCol, convert to num dtype'
$ git pull
$ git push --set-upstream origin numcols-2-numdtype
您只需要在第一次从新分支推送时添加参数---set-upstream origin my-branch
。
拉取请求
将更改推送到新分支后,您可以在 GitHub 页面上看到分支和 compare & pull 请求,如下所示。点击“比较和提取请求”,这将带您到另一个页面,写评论,如果有的话,然后点击“提取请求”。
请求将发送给 repo 维护者或所有者进行代码审查,在我们的例子中,repo 维护者或所有者可以在 Sofi 和 Alec 之间交替进行代码审查。回购维护者或所有者将审查代码,并将其合并到主分支,在我们的例子中是主分支。
将出现 Alec 的 pull 请求,这可以在下面的步骤中处理。
Alec :在 autos.py 文件中输入以下函数
def outliers_IQR(data, col):
lower_quartile = data[col].quantile(0.25)
upper_quartile = data[col].quantile(0.75)
IQR = upper_quartile - lower_quartile
outlier_thresh = 1.5 * IQR
return data[data[col].between((lower_quartile - outlier_thresh), (upper_quartile + outlier_thresh))]
完成上述步骤后,运行以下命令。
$ git add autos.py
$ git commit -m 'remove outliers based on IQR technique'
$ git pull
$ git push --set-upstream origin find-outliers
创建一个拉取请求:由于 Sofi 和 Alec 正在处理同一个文件,他们已经覆盖了彼此的代码,产生了合并冲突(如突出显示的)。
合并冲突
将出现 sofi 的拉取请求。因为存在合并冲突,所以需要在合并之前解决它。
要解决冲突,请单击上面突出显示的解决冲突,这将带您进入解决页面。
合并冲突指示器说明
编辑器具有以下合并冲突指示器:
<<<<<<< find-outliers
从这条指示线到下一条指示线显示当前分支上的代码=======
是原始行的结尾,随后的所有内容(直到下一个指示器)是正在合并的分支上的内容>>>>>>> master
是正在被合并的分支(在本例中是master
分支)的结束指示器
解决合并冲突
检查代码,修复冲突,删除合并冲突指示器,点击“已解决”,然后点击“提交合并”。
我会推荐你像 Pro:part 1****f一样阅读 Collaborate on GitHub 或者更好的理解这个练习。代码可以在 GitHub 库中找到。
要了解更多关于 GitHub 的信息,请点击这里。
参考文献
http://help.github.com/send-pull-requests/
无需 web 开发技能,就可在 R 生成的结果上进行协作
原文:https://towardsdatascience.com/collaborate-on-r-generated-results-without-web-development-skills-62a510316f14?source=collection_archive---------44-----------------------
介绍 dstack,一种发布、跟踪和共享数据的工具
对于统计计算来说,r 是一种漂亮的编程语言。它支持一组扩展的库,这些库支持允许用户探索特定领域数据分析的统计算法。r 还提供了广泛的图形工具,允许用户构建丰富的动态可视化。出于这些原因以及更多原因,R 是统计学家、分析师和数据科学家的热门选择,尤其是在构建统计模型和仪表板的原型时。
然而,当涉及到与组织或客户的其余部分共享和协作结果时,R 用户仍然面临许多问题。为了让非技术用户参与到数据中来,许多用户依赖于使用本地网络驱动器或电子邮件来分享他们的结果的繁琐过程。即使有了 Shiny 之类的 R 包,用户仍然需要熟悉 CSS 主题、HTML 小部件和 JS 动作。此外,组织必须承担额外的成本来维护支持应用程序的后端基础设施,如果您不熟悉 r,这将更加繁琐。
dstack 提供的解决方案正是为了解决这些问题。在这篇博文中,我们将展示 R 的用户如何使用 dstack.ai 的特性在 R 生成的数据可视化和数据集的结果上进行协作
- 发布和共享数据可视化和数据集
- 跟踪已发布数据的修订
- 协作处理您发布的数据
入门指南
让我们从建立一个档案开始。这需要您在 https://dstack.ai. 创建一个帐户。一旦您有了帐户,您就可以登录并从设置中复制您的令牌。令牌和您的 dstack 用户名用于通过命令行实用程序配置您的配置文件。
您可以通过使用 install.packages()函数从 CRAN 访问 dstack 包。
install.packages("dstack")
一旦您安装了软件包,您应该配置您的配置文件。这可以通过包中的configure
函数来完成:
dstack::configure(user = "<USER>", token = "<TOKEN>", persist = "global")
现在可以使用数据堆栈库了。
与其他人共享您的交互式可视化和数据集
一旦您准备好代码,dstack 提供 API 来发布您的结果,这些结果可以方便地共享,也可以对每个修订进行跟踪。一般来说,你会
- 使用 dstack APIs 发布结果。
- 使用 dstack UI 分享结果。
这些 API 支持 R 中最流行的库,包括 tidyverse、ggplot2 和 Plotly。这些 API 也可以在任何地方使用——笔记本、脚本或应用程序。通过这种方式,您不需要将您的报告嵌入到 HTML 报告中以通过电子邮件共享,或者自己承担学习服务器端脚本的麻烦。
假设您有一个数据集,在这种情况下,是美国中西部各县的人口统计数据,您希望分析人口密度,并以数据可视化的形式与他人共享您的结果。
您可以在 docs.dstack.ai 了解更多关于使用其他可视化库的信息
注意,在这个例子中,您使用了 dstack 库中的三个方法。
- create_frame 定义一个值“中西部 _ 分析”
- 提交,它包含可视化数据所需的参数
- 按下,将可视化推至 dstack UI
可以通过 URL 访问发布的图表
[https://dstack.ai/<username>/](https://dstack.ai/riwaj/plotlyR)Midwest_analysis
请注意缩放、滚动等功能是如何巧妙实现的。也可以在可视化中使用
注意 URL 和函数 create _frame 都包含一个值“Midwest_analysis”,我们称之为堆栈。
本质上,
- 堆栈是一种独特的数据流,它可以有许多帧,但指向被推送到发布的最新帧。
- 框架是对已发布数据的修订,可以由一系列附件组成。
- 附件可以是绘图、图表或图形,甚至可以是具有自己的参数集的数据框。
现在,如果您还想与他人共享数据集,以实现刚刚共享的数据可视化,该怎么办呢?
堆栈、框架和附件等 dstack 抽象结构使您能够以发布数据可视化的相同方式提交数据集。
添加参数(View="Data ")允许您在同一堆栈中的数据集和可视化之间切换
这样,您可以在同一个堆栈中获得交互式数据集和可视化。
您可以在dstack.ai/riwaj/Midwest_analysis?a=1查看发布的堆栈
发布堆栈后,现在您可以使用 URL、用户名或通过电子邮件地址发送邀请,与您的同行和客户共享堆栈。
任何人都可以通过链接查看公共堆栈
使用其他人的数据集
设想一个场景,您希望使用由其他人托管在 dstack 上并可供您使用的数据集。在这种情况下,您有两种选择来获取数据集以使用它。
- 从 dstack UI 下载数据集作为 CSV 文件
- 使用 dstack API 将数据集作为数据框提取
登录 dstack web 应用程序,通过 dstack API 下载或获取数据集
作为一名 R 用户,您可能会发现简单地使用 dstack API 来获取数据集很方便。下面是一个使用 pull API 获取 dstack 上托管的数据集的代码片段。
跟踪结果的修订
现在这里有一个很酷的部分!可以使用 dstack web 应用程序上的一个按钮来获取已发布堆栈的每个修订版及其所有参数。通过这种方式,您可以获得您的堆栈在工作过程中如何发展的历史记录,而不管它是可视化还是数据集。
本质上,这就是它的工作方式。
- 使用 dstack APIs 将栈的每个新版本推送到同一个栈。
- 登录到 dstack web 应用程序,并转到您的堆栈的 URL 地址。
- 在堆栈名称的下方,例如 Midwest_analysis,您会看到小部件。
- 点击它可以找到数据集的所有版本,以及最新的一个,称为 Head。
每个修订历史由时间戳表示
协作处理您的结果
dstack 是为协作数据探索而构建的。
发布的数据集和可视化可以通过 URL 与其他人轻松共享,即,即使非技术用户也可以使用 web 浏览器在 dstack.ai 托管的前端应用程序上查看和访问发布的堆栈。发布不存在多租户问题,即多个并发用户可以在同一时间就您发布的报表进行交互和协作,而不需要修改代码。
评论功能可以让你参与讨论(想想脸书的 Instagram)。要添加注释,您必须登录到您的 dstack.ai 帐户,并拥有在 dstack 中发布数据集的人在堆栈上进行协作的权限。
在 dstack 中,共享和评论权限的管理方式如下。
- 每个用户都可以使用设置菜单来选择默认情况下是将一个新堆栈设为私有还是公共。
2.发布堆栈后,发布者可以选择共享堆栈的对象。或者,即使默认设置被选择为私有,堆栈也可以被公开。
您不需要 dstack 帐户来查看公共共享的堆栈,但是您需要一个帐户来进行注释
如果您登录 dstack,您将会看到自己创建的堆栈和其他人共享给您的堆栈。
数据堆栈帐户中堆栈的概述,包括自己创建的堆栈和他人共享的堆栈
所有的服务也可以从移动电话上获得,以方便地查看更新的堆栈。
立即尝试!
dstack.ai 可以在您的笔记本、脚本、工作甚至应用程序中使用,我们免费提供上述所有服务。
你认为我们错过了一些用例和特性吗?这是我们的产品路线图,您可以投票选出您希望在未来看到的功能。
https://trello.com/b/CJOnEjrr/public-roadmap
请注册并给我们反馈和建议。我们很想听听你的想法。
谢谢您们。
反馈调查:【https://forms.gle/6MSLAGaHJFvvpB5Q6
报名:【https://dstack.ai/auth/signup
了解更多 https://dstack.ai
文档: docs.dstack.ai
反馈邮件: team@dstack.ai
免责声明和限制:
- 数据集管理功能处于测试版,欢迎早期用户尝试。
- 除非法律要求,否则我们不会与第三方共享数据。
- 我们不强制检查数据的真实性和来源,而是依赖用户。如果您发现侵权案件,请向我们报告。
- 如果我们发现数据结果的共享损害了任何一方或违反了任何法律,我们将有义务立即删除这些数据。
- 您可以保护对数据的访问,例如,通过更改堆栈设置或更改帐户设置的默认值,将数据限制为选定的用户。
在 GitHub 上合作
原文:https://towardsdatascience.com/collaborating-on-github-68f8dd953bb8?source=collection_archive---------46-----------------------
数据科学家必须了解的工具
照片由 Richy Great 在 Unsplash 上拍摄
在的最后一个教程中,我们学习了 GitHub 的基础知识。在本教程中,所有这些基础知识将汇集在一起,我们将体验 GitHub 的真正力量,它来自于协作。请注意,在本教程中,我们将频繁使用像克隆,推,拉,分支,大师等词。因此,如果你对这些都不清楚,请先通读上一篇教程。
定义协作
要理解解决方案,重要的是理解问题。通读以下内容,理解 GitHub 可以派上用场的场景。
你是一名首席数据科学家,与一组初级数据科学家一起从事机器学习项目。由于您是项目所有者,因此您负责维护项目代码的“ 主”版本。
在您的团队中,每个数据科学家都在独立工作,以改进模型预测。因此,他们创建了自己的本地版本或主版本的备用分支。
让我们假设你已经对你的代码的""版本做了一些编辑***,并且你的团队中的一个成员拿出了他自己的编辑版本**,并且声称他已经极大地改进了模型预测。这个场景的视觉效果如下:*
示例场景(图片由作者提供)
你现在想更新" master "版本的代码,但是可能会出现一些冲突。下面举几个例子:
- 您对"" master "版本所做的编辑可能不在您的团队成员的分支版本中
- 与“ 【主】 代码相比,分支版本可能有一些不同的变量处理
这意味着简单地用代码的分支版本覆盖主代码可能不符合项目的最佳利益。为了解决这样的冲突,GitHub 派上了用场**
求解时间
我确信上面的场景一定让你意识到了眼前的问题。问题是,GitHub 将如何提供帮助?
重要的事情先来
在我们开始讨论解决方案之前,让我们先了解一些我们将在本教程中使用的基本术语:
- ****合作者——被正式添加到项目存储库并被授予推送访问权限(修改存储库内容的访问权限)的开发人员被称为贡献者或合作者
- Fork — 在 GitHub 中 Forking 就像把别人的库复制到你的账户中。一般来说,当你想使用某个其他开发者创建的开源项目并且你不是贡献者时,你派生**它并获得对他们的库的访问权。**
- 分支 —通常开发者使用不同的分支来维护项目的不同模块。另一个允许使用分支的常见场景是当团队的多个成员想要处理同一段代码时。这时每个人都可以有自己的分支。默认情况下,每个新创建的存储库都有一个名为 主 分支的中央分支。
- **拉取请求——创建一个拉取请求,将一个分支与“主”分支合并。请求直接发送给项目所有者,他/她可以与分支贡献者一起接受/拒绝编辑。
情节
为了解决上面定义的问题,我们将介绍两个场景,您在 GitHub 上积极协作时会遇到这两个场景:
- 在第一个场景中,我们假设您想要对一个存储库(项目)做出贡献,而您没有被添加为贡献者。在这个场景中,我们将假设在您分叉了项目之后,没有对主分支进行任何编辑(在上面显示的示例场景图中,版本 2 和 3 的黄色框不存在)。****
- 第二个场景假设您是项目组的一部分,并且作为贡献者被添加到项目存储库中。在这个场景中,我们将假设在您创建了自己的分支之后,对“主”分支进行了编辑(在上面显示的示例场景图中,版本 2 和 3 的黄色框存在)。
让我们来看看上述场景的工作流程。
情景 1 —不是贡献者
当你不是一个库的贡献者时,你不被允许从你的本地系统推送编辑到 GitHub。在这种情况下进行协作的工作流程步骤如下:
- 派生存储库— 因为我们不是存储库的合作者,我们将首先派生存储库。要派生存储库,请登录您的帐户并搜索您感兴趣的存储库。进入资源库 GitHub 页面,点击 叉按钮 ,如下图所示:
分叉(作者图片)
在上面的 4 张截图中,我们正在搜索资源库** (D2WAP/Test)。我们转到存储库页面,并按下右上角的叉按钮。分叉过程发生了,我们的账户中的库被分叉。**
- 克隆存储库— 完成后,您可以克隆分叉的存储库,使其内容在您的系统上可用。这一过程在上一个教程中有解释。由于分叉库是你的帐户的一部分,你将有推送权限,你可以将你的编辑推送到分叉库。请注意,在这种情况下,克隆应该在分叉之后完成,因为如果在分叉之前完成,您的本地克隆库将指向其他开发者的帐户,在那里您将没有推送访问权限。
- 修改代码,提交并推送 —下一步是编辑克隆库中的代码,提交更改,和将它们推送到您的分叉库。假设你有一个分支,你可以直接将编辑推送到“主”分支或者也可以创建一个新分支。建议我们只在新的分支中进行编辑,但是为了简化这个场景,我们将编辑直接推送到“ 主 ”分支。我们将在场景 2 中查看新分支的创建。为了演示这个过程,我编辑了分叉库的 read me 文件 。从下面的截图可以看出分叉的存储库和原始存储库之间的区别:
编辑自述文件(图片由作者提供)
- 创建新的拉取请求— 现在您已经对代码进行了必要的编辑( read me file 在我们的例子中),是时候创建一个拉取请求了。**点击拉动请求选项**,进入拉动请求屏幕。在屏幕右上方点击 新拉取请求。**
创建新的拉取请求(作者图片)
- 选择基地和头库 —点击 新拉取请求 ,将进入选择基地和头库以及对应分支的页面。将 base 视为目的存储库,将 head 视为分叉存储库。由于我们已经直接对分叉存储库的“”主分支进行了编辑,因此对于头分支和基础分支都选择“”。一旦做出选择,GitHub 将向您展示您试图合并的两个版本之间的比较。再次点击 创建拉式请求。****
选择源和目标存储库(按作者排列的图片)
- 添加注释 —一旦您点击了“ 创建拉式请求 ,您将到达注释页面,在这里您可以为源代码库开发人员添加适当的注释。再次**点击创建拉取请求,你的拉取请求将被发送给源开发者。注意来自 GitHub 的消息说没有冲突。这验证了我们的假设,即在我们分叉存储库之后,没有在源代码中进行任何编辑。
评论部分(作者图片)
- 按作者合并 —一旦您提交了拉请求,作者就会收到,如果没有冲突,他/她可以立即批准。要合并,作者将转到“拉请求”选项卡,并单击“ 合并拉请求”。就这样,您已经成功地对源存储库做出了贡献
合并审批流程(作者图片)
场景 2 —你是一名贡献者
因为在这个场景中,我们假设您被存储库所有者添加为贡献者,所以您将拥有将编辑内容直接推送到源存储库的访问权限。基于这一假设,我们来看一下工作流程:
- ****克隆——因为你现在可以直接将编辑推送到主存储库,所以不需要分叉。继续克隆存储库。这个过程在上一个教程中有解释
- 源文件被编辑 —参考下面的截图,查看对源文件和分支文件的编辑。出于演示目的,我们正在修改 自述文件 。
编辑自述文件(图片由作者提供)
- 拖拽&放下 —假设你已经做了必要的编辑,你可以到 GitHub 上的原始存储库页面,拖拽&放下页面上编辑过的文件。添加截图供您参考:
拖放(作者图片)
- 创建新分支 —一旦您将编辑过的文件放到存储库页面上,您将获得直接编辑“ 主 ”分支或创建新分支的选项。在这个场景中,我们将按照推荐的方法创建一个新的分支。当相应的单选按钮将被选中时,GitHub 将要求您命名分支。一旦命名,点击 提出修改 。每当你想备份或版本控制你的工作,你可以做这一步。只要确保如果您在生成 pull 请求之前继续对编辑进行版本控制(在下一步中解释),您是在同一个分支上进行的。截图补充如下,供大家参考:
创建新分支(作者图片)
- ****创建新的拉式请求——一旦您提出了变更,您就可以像场景 1 中解释的那样创建一个拉式请求。请注意,因为我们已经直接对源存储库进行了编辑,所以您不需要选择基本存储库和主存储库,而只需要选择要合并的分支。此外,由于这两个分支在合并时被并行编辑,GitHub 引发了冲突。添加截图供您参考:
有冲突的拉取请求(图片由作者提供)
- 解决冲突 —这是存储库所有者和分支协作者可以进行讨论并一起解决冲突的地方。在 GitHub 上,这可以通过点击“ 解决冲突 来完成,并且可以由存储库所有者或分支所有者发起。在下面的截图中,请注意导致冲突的编辑。哪些编辑要保留,哪些要拒绝,可以通过相互讨论来解决。编辑完成后,点击屏幕右上角的标记为已解决。添加截图以供参考:
解决冲突(作者图片)
- 合并拉取请求 —冲突解决后,您将进入拉取请求屏幕,冲突消息将被合并拉取请求所取代。点击" 【合并拉取请求】 ,然后点击" 【确认合并 】以及任何想要记录的信息。就这样,你的编辑被合并到“ 主 ”分支中。添加截图供您参考:
合并拉取请求(作者图片)
- 重新检查"主"分支**-一旦合并,您将看到""分支随着分支的编辑而更新。**
结束语
git & GitHub 还有很多其他相关的功能,但那是以后的事了。
有了这些知识,与你的项目团队合作,把版本控制的烦恼留给 GitHub。希望这篇教程对你有所帮助,并且你学到了一些新的东西。
会在以后的教程中尝试并带来更多有趣的话题。
快乐学习!!!
协作将释放人工智能的商业价值
原文:https://towardsdatascience.com/collaboration-will-unlock-ais-business-value-658a41fff973?source=collection_archive---------78-----------------------
对于人工智能来说,协作就是今天,相当于 20 世纪 60 年代的计算能力
亚历山大·奈特在 Unsplash 上拍照
1990 年,经济学家保罗·大卫在他的文章《美国经济评论》中分享了-
由于充分利用技术需要补充投资,生产率的提高需要很长时间。~保罗·大卫
对于我们这个世纪的技术机遇——人工智能(AI),他的见解在今天同样真实。为了从人工智能驱动的创新中为社会和商业带来最大利益,开发必要的补充是至关重要的。这些补充之一是在数据上的合作,甚至是竞争对手之间的合作。
竞争格局已经彻底改变。
对数据的竞争非常激烈,因为它是推动机器学习和人工智能增长的原材料。电信运营商不再仅仅与其他此类运营商竞争。它与谷歌和脸书等公司争夺消费者数据;它与零售业竞争消费者在哪里购物等数据。大家都是做数据生意的,我们都是竞争对手。然而,在这场积累和分析越来越多数据的竞赛中,数据越多就越好吗?我认为并非如此。数据的边际收益递减。更多的数据不一定会转化为新的信息。相反,它有时可能会掩盖信息,或者只是用来证实现有的偏见。那么,我们到哪里去寻找更好的、更新鲜的、令人惊讶的见解呢?
跨行业洞察是下一个前沿。
关键是要超越行业孤岛,寻找新的数据和见解。毕竟我们都在为同一个客户服务。我有一次在多伦多参加年度机器学习会议。我在寻找与其他行业组织的潜在合作伙伴,提议我们将他们来自电信行业以外的数据集与我们的移动使用数据集相结合,共同执行高级分析,跨越我们的行业孤岛。出乎意料的是,我发现自己在和著名的物理学家和作家杰弗里·韦斯特教授交谈。就在他的主题演讲前,我无意中提到他的弦理论背景,“通常,解决方案都在学科的交叉点上,不是吗?”他温和地纠正了我——“解决方案总是跨学科的。”
解决方案总是跨学科的。~杰弗里·韦斯特
合作的三大支柱
在实践中实现这种合作需要三大支柱——数据评估、隐私机制和长期思考。
估值
在我工作的过程中,我对一个框架进行了广泛的调查,这个框架可以让组织评估他们的数据集值多少钱?然而,在大多数情况下,这种方法是启发式的。那么,组织如何评估与第三方共享的数据的价值呢?例如,开发预测客户流失的机器学习模型的人工智能初创公司仍然必须在专有数据上训练他们的算法。数据在特定环境中的价值直接影响到这些第三方合作的性质,包括从供应商关系到合资企业的所有形式。在没有这种模型的情况下,组织只能模糊地了解哪些数据集可能最有价值。从商业角度来看,高度受限的数据集并不总是最有用的。
隐私
即使我们可以对数据进行价值评估,为跨行业分析而共享这些数据的实际挑战依然存在。这方面的大部分工作来自法律学科。然而,我更感兴趣的是探索隐私背后的经济理论,以及允许在数据共享中保护隐私的模型。有必要探讨一些问题,如隐私是否是一项普遍权利,以及是否所有人口统计数据都同样重视隐私。例如,哈佛大学伯克曼·克莱恩中心研究员 Velislava Hillman 关于嵌入式人工智能的观察将学生从他们热爱的职业推向他们擅长的职业。
允许这种共享的隐私模型是需要的——诸如差分隐私和加密方法(私有集合交集、分散分析)的方法。以统计和加密方法为补充的隐私法律框架将允许在跨组织共享数据时保护隐私。有时,当数据不共享时,这些是必要的,但仍然要以分散的方式进行分析。
长期思考
除了在那些以数据为主要收入来源的科技巨头中,该行业的其他公司都过度青睐那些能直接提高盈利能力或节省成本的模型或方法。因此,大多数公司最终只使用最基本和最明显的模型。由于这些也很容易被业内其他人获得,它们无论如何都没有提供什么竞争优势。然而,如果这种与商业目标的联系需要一点点信心,决策者往往会回避。这种商业决策的传统视角不适合推动先进机器学习和人工智能的长期发展,即使这些发展将为行业带来巨大利润。我们不仅要跳出框框思考,还要超越我们有限的时间范围。
简而言之,每个公司都必须认识到数据是一种战略资产。在这个独特的竞争环境中,与和我们有共同道德观的人合作,将会比传统的竞争带来更大的收益。系统地评估这一资产,确保其安全性和质量,并超越短期目标,将推动必要的合作,以释放我们这个世纪的技术——人工智能——的全部价值。不这样做很可能会把我们带回 20 世纪 60 年代,当时缺乏必要的补充,廉价的计算能力使人工智能创新陷入停滞。
利用 dstack.ai 探索新冠肺炎对空气质量的影响
原文:https://towardsdatascience.com/collaborative-exploration-of-covid-19-effect-on-air-quality-with-dstack-ai-2094ef8c83bd?source=collection_archive---------59-----------------------
来源https://unsplash.com/photos/3LsocYqXWpM
作为一名被禁闭的数据科学家,我决定花一些时间进行数据探索和尝试新事物。我想知道格里塔·图恩伯格和其他人是否会感谢冠状病毒通过让人们呆在家里来清洁我们的空气。
我想做得又快又脏,看看实际的趋势,并轻松地与人们分享。以下是我得到的信息:
https://dstack . ai/oti pita/d/2710328 b-393 a-456 a-907 a-0595761 af 188
一开始有两个问题——用什么数据来评估空气状况,用什么工具来可视化。大家来翻翻我的回答和整体开发流程。
数据收集
我一直在寻找有关空气状况的“实时”信息,以便以一种良好的格式轻松获取数据,几乎可以随时进行分析。世界上有十几个数据库,每个国家都有不同的信息,但大多数数据库获取和整合数据的时间都有很大的延迟。通常情况下,他们会在第二年的第一季度发布上一年的信息,这不是我想要的。所以当我发现 https://waqi.info/的时候我很开心。该网站有许多国家的信息,这些信息一天更新几次,涵盖广泛的指标。尽管他们有一个可用的 API,但也发布了为可能的新冠肺炎分析提取的历史数据。一个只需要电子邮件验证,就可以获得从 2015 年到目前为止 22 个指标的国家每日数据。虽然少数国家报告了一些指标,但几乎所有国家都有 10 项指标。我们列出了一氧化碳、露水、二氧化氮、臭氧、PM10、PM25、二氧化硫的测量指标,并删除了温度、湿度和压力等其他指标。
技术堆栈
我通常使用 Python、Excel、Power BI 或 Tableau 进行数据可视化。在这个分析中,我选择了 Python,因为我想要一个完全开放的堆栈。所以我用 pandas 进行数据收集和处理,Plotly 进行可视化。
分析数据后的最后步骤是:
- 将我的所有视觉效果合并到一个仪表板中
- 在线发布仪表板并共享它
- 组织反馈以进一步改进仪表板
我想知道如何又快又容易地做这件事。最*,我了解到一个新工具可以如何帮助我的视觉效果组合、部署、共享和进一步协作。我决定试一试。
发展
dstack.ai 仪表板由两部分组成:滤镜面板和视觉效果(堆栈)。数据预处理和转换见 Jupyter 笔记本。
我们可以将数据按国家分组,以检查 2019 年 1-5 月、2020 年 1-5 月的中值指标衡量,以及这两个时期的实际差异。所以我从 2020 年和 2019 年的 NO2 差异图开始绘制。
2020 年 1 月至 5 月空气中二氧化氮日均值与 2019 年的差异
def map_plot(data, kpi, year, title):
data = data[(data["Specie"]==kpi)]
fig = px.choropleth(data, locations="Country3",
color=year,
hover_name="CountryName",
color_continuous_scale=px.colors.diverging.Geyser)
return figfig = map_plot(data_grouped, 'o3', 'difference', 'World map')
fig.show()
一旦我绘制出了想要的可视化效果,dstack.ai 的使用比 GitHub 更容易。为了将可视化发布到 dstack 前端,它提供了三种方法,即创建-提交-推送。
# Creation of map stack
frame = create_frame("world_map")for kpi in kpis:
for year in ['median2020', 'median2019', 'difference']:
frame.commit(map_plot(data_grouped, kpi, year, 'Air Indicator Map'), f"World map colored by {kpi}", {"Air Indicator": kpi, "Measure": year})frame.push()
另一种观察空气质量的方法是在雷达图上一次标出特定国家的所有指标。我第一次尝试是在中国。2020 年与 2019 年相比没有太大变化,除了 PM25 和 PM10 指标。
def radar_plot(data, country):
data = data[(data["CountryName"]==country)]
fig = px.line_polar(data, r="median", theta="Specie",
color="Year", line_close=True,
hover_name="CountryName",
color_discrete_sequence=["#3deb34","#eb4034"])
return figfig = radar_plot(data_grouped_time, 'China')
fig.show()
要创建带有国家参数的堆栈,我们需要重复帧创建-提交-推送操作:
# Creation of radar stack
frame = create_frame("radar_chart")for country in data_grouped_time['CountryName'].sort_values().unique():
frame.commit(radar_plot(data_grouped_time, country),
f"Air quality measure for {country}", {"Country": country})frame.push()
我还创建了一个折线图来查看 2020 年与 2019 年的每日动态,以及一个条形图,显示指标下降的主要国家。你可以在 GitHub 查看完整代码。
用 dstack 将视觉效果组合成一个仪表板非常容易。您只需选择要添加到仪表板中的堆栈,对它们重新排序,然后选择所需的布局/标题。瞧,动态仪表板几分钟后就准备好了。
对我来说,最大的惊喜是在单个可视化上设置的参数/过滤器会在需要时自动组合(没有重复)。此外,一旦我在单个堆栈中做了一些更改,它们就会随着最新的更新出现在仪表盘上。此外,每个堆栈可以最大化为全屏视图。
在协作特性方面,我发现任何被允许在 dstack 前端查看图表的人都可以留下他们对图表的反馈。我喜欢这种直观的协作方式。我必须说,现在没有太多花哨的功能,但它非常适合我的需要,并以一种方便的方式加快了我“准备就绪”的时间,以获取其他人的想法。
结果
经过几个小时的工作,我能够与我的朋友和同事分享我的仪表板,并开始探索仪表板。有一些有趣的发现,肯定需要进一步探索,以了解原因。
与 2019 年相比,除沙特阿拉伯和伊朗外,大多数国家 2020 年 1 月至 5 月的所有指标都略有下降。
一些国家如丹麦、瑞典、挪威、斯洛伐克在减少空气中二氧化硫和二氧化氮方面名列前茅,没有在疫情期间引入严格的封锁。
查看你所在的国家的空气状况,保持健康,并通过 dstack.ai 轻松分享可视化效果。
Pyspark 中的协同过滤
原文:https://towardsdatascience.com/collaborative-filtering-in-pyspark-52617dd91194?source=collection_archive---------27-----------------------
入门
基于交替最小二乘(ALS)算法的协同过滤及其在 Pyspark 中的实现
诺贝特·布杜茨基在 Unsplash 上的照片
你有没有想过 Spotify 是如何每周在“发现周刊”上发布一个歌曲列表,而你最终因为喜欢这些歌曲而将其中一些添加到你的播放列表中的?因为你昨天看了一个特别的节目,网飞推荐给你的那些节目怎么样?这些科技巨头怎么这么聪明?答案是推荐系统。
推荐系统基于用户的历史行为,如观看、搜索或购买历史,进行预测。推荐系统的两种常见方法是基于内容的 和协同过滤,本文将深入探讨后者。
什么是协同过滤?
协作过滤是一种数学方法,用于根据其他相似用户的评级来预测用户如何对特定项目进行评级。典型的协同过滤包括 4 个不同的阶段:
- 数据收集—收集用户行为和相关数据项
- 数据处理—处理收集的数据
- 建议计算—根据处理的数据计算推荐
- 结果推导-提取相似性并返回前 N 个结果
显性和隐性反馈
那么,在协同过滤的第一阶段,收集的是什么类型的数据呢?有两种不同类别的数据(称为反馈),可以是显性或隐性。
显式反馈的一个例子是用户给出的评级,网飞收集这些评级是为了在客户对他们观看的电影进行评级后向他们提供建议。隐式反馈不那么直接,因为它基于用户与*台的互动,包括点击、观看、喜欢和购买。Spotify 利用隐式反馈来实现它的推荐系统。
计算相似度
一旦收集和处理了数据,就需要一些数学公式来进行相似性计算。两种最常见的方法是:
- 欧几里德距离——两个用户之间偏好的距离。如果距离小,则两个用户之间的相似性高
- 皮尔逊相关-如果两个用户之间的余弦值(入射角)一致,则两个用户之间的相似性很高
作者图片—余弦和欧几里德距离向量空间
Pyspark 中的实现
库包 spark.ml 目前支持基于模型的协同过滤,其中用户和产品由一小组潜在因素描述,这些因素可用于进行预测。它使用交替最小二乘(ALS)算法来学习这些潜在因素。
我们将使用来自 https://www.last.fm/api/的数据集,其中包含 3 个文件:
- user_artist_data.txt 3 列:userid artistid playcount
- artistid artist_name
- artist_alias.txt 2 列:badid,goodid[已知拼写错误的艺术家和正确的艺术家 id]
首先,我们用下面的代码设置 Spark。
# import librariesfrom pyspark import SparkContext
from pyspark.ml.recommendation import ALS
from pyspark.sql import SparkSession ,RowappName="Collaborative Filtering with PySpark"
# initialize the spark session
spark = SparkSession.builder.appName(appName).getOrCreate()
# get sparkcontext from the sparksession
sc = spark.sparkContext
然后,我们定义数据结构并将弹性分布式数据帧转换成数据帧。
from pyspark.sql.types import StructType,StructField,IntegerType,StringType,LongType
from pyspark.sql.functions import col#Define the schema for the datasets
schema_artist = StructType([StructField("artistId",StringType(),True),StructField("artistName",StringType(),True)])schema_user_artist = StructType([StructField("userId",StringType(),True),StructField("artistId",StringType(),True),StructField("playCount",StringType(),True)])schema_alias = StructType([StructField("badId",StringType(),True),StructField("goodId",StringType(),True)])#Convert RDDs into Dataframes
artistRDD = rawArtistData.map(lambda k: k.split("\t"))artist_df = spark.createDataFrame(artistRDD,schema_artist,['artistId','artistName'])userArtistRDD = rawUserArtistData.map(lambda k: k.split())user_artist_df = spark.createDataFrame(userArtistRDD,['userId','artistId','playCount'])aliasRDD = rawArtistAlias.map(lambda k: k.split())alias_df = spark.createDataFrame(aliasRDD,['badId', 'goodId'])#First for convenience, we can create aliases for each dataframes
ua = user_artist_df.alias('ua')
ub = artist_df.alias('ub')
一旦数据集被处理,我们可以继续训练我们的 ALS 模型。在此之前,我们应该将数据集分成训练和测试数据,这样我们就可以知道我们的模型执行得有多好。
# dataset split into training and testing set
(training, test) = ua.randomSplit([0.8, 0.2])# training the model
als = ALS(maxIter=5, implicitPrefs=True,userCol="userId", itemCol="artistId", ratingCol="playCount",coldStartStrategy="drop")
model = als.fit(training)# predict using the testing datatset
predictions = model.transform(test)
predictions.show()
作者图片—测试预测的 Pyspark 输出
我们可以尝试使用该模型来找到为每个用户推荐的顶级艺术家。我们可以使用 ALS 模型中的recommended for allusers函数来获取每个用户的首选推荐列表。
下面的函数将 userId 和 limit 作为输入。对于给定的用户 Id ,它获得当前最受欢迎艺术家的列表(基于播放计数)。让我们尝试为用户(2062243)显示最喜欢的艺术家。
def currentLikes(ua,ub,userId,limit):
df = ua.join(ub,ua.artistId==ub.artistId)\
.filter(ua.userId==userId)\
.sort(ua.playCount.desc())\
.select(ua.userId,ua.playCount,ub.artistName)\
.limit(limit)
return df# display top 10 liked artists for user 2062243
currentLikes(ua,ub,2062243,10).show(truncate=False)
按作者分类的图片 Pyspark 为用户 2062243 输出的最受欢迎的艺术家
然后,下面的函数使用该模型为每个用户给出艺术家的最佳推荐。我们试着为同一个用户(2062243)显示推荐的艺术家。
def recommendedArtists(userId,limit):
test = model.recommendForAllUsers(limit).filter(col('userId')==userId).select("recommendations").collect()
topArtists = []
for item in test[0][0]:
topArtists.append(item.artistId)
schema = StructType([StructField("artistId",IntegerType(),True)])
artists = spark.createDataFrame(topArtists,IntegerType())
final=artists.join(ub,artists.value==ub.artistId).select(ub.artistId,ub.artistName)
return final# display top 10 recommended artists for user 2062243
recommendedArtists(2062243,10).show(truncate=False)
按作者分类的图片-为用户 2062243 推荐的艺术家的 Pyspark 输出
摘要
在这篇文章中,我们介绍了什么是协同过滤,以及它的 4 个不同阶段。协同过滤收集的两类数据,主要是隐式和显式反馈,使用欧氏距离或皮尔逊系数计算相似度。最后,简要介绍了使用 spark 中内置的交替最小二乘(ALS)算法在 Pyspark 中实现协同过滤的过程。希望你们对推荐系统的工作原理有一个简单的了解,下次在网上冲浪和使用 Spotify/Amazon 时,看到好的推荐,不要感到惊讶,干杯!
Pytorch 中的协同过滤
原文:https://towardsdatascience.com/collaborative-filtering-in-pytorch-6e50515f01ae?source=collection_archive---------30-----------------------
构建用于电影推荐的嵌入神经网络
图片由亨利&公司在 Unsplash 拍摄
协同过滤是公司越来越多地使用的工具。网飞用它来推荐节目给你看。脸书用它来推荐你应该和谁交朋友。 Spotify 用它来推荐播放列表和歌曲。它在向顾客推荐产品时非常有用。
在这篇文章中,我构建了一个嵌入的协同过滤神经网络来理解用户对某些电影的感受。由此可以推荐电影给他们看。
数据集取自此处的。这段代码大致基于 fastai 笔记本。
首先,让我们去掉烦人的复杂用户 id。我们可以用普通的旧整数来凑合。它们更容易处理。
import pandas as pd
ratings = pd.read_csv('ratings.csv')
movies = pd.read_csv('movies.csv')
然后我们将对电影 id 做同样的事情。
u_uniq = ratings.userId.unique()
user2idx = {o:i for i,o in enumerate(u_uniq)}
ratings.userId = ratings.userId.apply(lambda x: user2idx[x])
我们需要获得用户数量和电影数量。
n_users=int(ratings.userId.nunique())
n_movies=int(ratings.movieId.nunique())
首先,让我们创建一些随机权重。我们需要打电话。这允许我们避免显式调用基类。这使得代码更易于维护。
这些权重将在 0 和 0.05 之间均匀分布。uniform_
末尾的_
操作符表示在位操作。
接下来,我们添加我们的嵌入矩阵和潜在因素。
我们正在为我们的用户 id 和电影 id 创建一个嵌入矩阵。嵌入基本上是一种数组查找。当我们将我们的一次性编码用户 id 乘以我们的权重时,大多数计算都取消了0
(0 * number = 0)
。我们只剩下权重矩阵中的某一行。这基本上就是一个数组查找。
所以我们不需要矩阵乘法,也不需要独热编码数组。相反,我们可以只做一个数组查找。这减少了内存使用并加速了神经网络。它还揭示了分类变量的内在属性。这个想法在最*的一次 Kaggle 比赛中得到了应用获得了第三名。
这些嵌入矩阵的大小将由 n 个因子决定。这些因素决定了数据集中潜在因素的数量。
潜在因素在我们的网络中非常有用。它们减少了对特征工程的需求。比如User_id
554
喜欢Tom cruise``Tom cruise
出现在一部电影里。用户554
可能会喜欢这部电影。出现在电影中会是一个潜在的特征。我们在培训前没有具体说明。它就这么出现了。我们很高兴它做到了。
最后,我们需要添加我们的forward
函数。
正如这个类的名字所暗示的,我们正在做嵌入矩阵的点积。
给我们一个用户和电影的小批量。我们只看嵌入的分类变量。conts
指连续变量。
这个小批量大小将由您设置的批量大小决定。根据这篇文章,大批量实际上会损害模型的质量。但是根据这篇论文,大批量增加了模型的质量。目前还没有达成共识。许多人都在报道矛盾的结果。所以你可以随意选择批量大小进行实验。
从这个迷你批处理中,我们想要在我们的嵌入矩阵中进行数组查找。
允许我们进行数组查找。这种查找比一位热码编码矩阵和加权矩阵矩阵乘法计算量小。
(u*m).sum(1).view(-1, 1)
是用户和电影嵌入的叉积,返回一个数字。这是那部电影的预测分级。
接下来,我们需要创建一个ColumnarModelData
对象
那我就设置一个乐观器。对此我将使用随机梯度下降法。optim.SGD
实现随机梯度下降。随机梯度下降在计算上不如梯度下降密集。这是因为当选择数据点计算导数时,我们引入了随机性。
我们也可以使用optim.Adam
。实现 rmsprop 和动量。反过来,这导致了自适应的学习速率。但是这篇论文表明从 SGD 得到的解比从 Adam 得到的解更一般化。另外,反正训练也不需要那么长时间,所以 SGD 也不是个坏选择。
然后我们适合一个3
时代。
fit(model, data, 3, opt, F.mse_loss)
MSE 损失就是简单的均方误差损失。这是自动计算的。
Fastai 在幕后自动创建一个神经网络。您可以调用一个[collab_learner](https://docs.fast.ai/collab.html#collab_learner)
,它会自动创建一个用于协同过滤的神经网络。Fastai 还可以通过这个协作学习器引入偏差和辍学。
偏见是很有用的。我们需要找到用户偏见和电影偏见。用户偏见可以解释那些对每部电影都给予高评价的人。电影偏见可以解释那些倾向于给某类电影高评级的人。Fastai 自动添加偏差。
使用 fastai,我们可以轻松创建协作学习者:
偏见是很有用的。我们需要找到用户偏见和电影偏见。用户偏见可以解释那些对每部电影都给予高评价的人。电影偏见可以解释那些倾向于给某类电影高评级的人。Fastai 自动添加偏差。
有趣的是,fastai 指出你应该稍微增加y_range
。 sigmoid 函数用于确保最终输出在y_range
中指定的数字之间。问题是一个 sigmoid 函数似乎。所以我们需要稍微增加我们的y_range
。Fastai 建议增加0.5
。
图片来自 ResearchGate
作者图片
我这里用的是建议的学习率,有少量的重量衰减。这是我发现非常有效的组合。
作者图片
我们可以多训练一些
作者图片
作者图片
我们终于得到了一个0.784105
的 MSE。但这是一段非常颠簸的旅程。我们的损失上下波动很大。也就是说0.784105
实际上比 LibRec 系统的协同过滤得分更高。他们得到了 MSE。
它实际上也比 fastai 在他们的协作过滤课程中创建的模型略好。他们越来越小。
丰富
- 我们可以通过发送一个名为
emb_szs
的字典来调整嵌入的大小。这可能是一个需要调整的有用参数。 - 基于内容的推荐。协同过滤只是建立推荐系统的一种方法。其他方法可能更有用。基于内容的系统是我一直铭记在心的。它可以查看演员、工作人员、流派和导演等元数据来做出推荐。我认为某种混合解决方案将是最佳的。这将结合基于内容的推荐系统和协作过滤系统。
- 协同过滤在很大程度上被冷启动问题所破坏。为了克服这个问题,我们可能会查看用户元数据。例如,我们可以查看诸如:性别、年龄、城市、他们访问网站的时间等。只是他们在报名表上输入的所有内容。在这些数据的基础上建立一个模型可能会很棘手,但是如果效果好的话,它可能会很有用。
原载于 2020 年 7 月 12 日https://spiyer 99 . github . io。
基于 fastai2 的动漫数据集协同过滤
原文:https://towardsdatascience.com/collaborative-filtering-on-anime-dataset-using-fastai2-130ae32fe433?source=collection_archive---------46-----------------------
去看或去看什么
这篇文章旨在描述什么是协同过滤(在整篇文章中简称为 CF ),并随后阐述如何使用 fastai2 构建一个模型来执行这项任务。本帖涵盖的主题如下
- 简介
- CF 背后的基本直觉
- CF in fastai2
-嵌入点偏差模型
-神经网络模型 - 模型解读&提出建议
- 参考文献
单击主题,导航到相应的部分。
查尔斯·德鲁维奥在 Unsplash 上拍摄的照片
介绍
在当今世界,数据就是石油,利用数据的一种方式是为个人执行建议/推荐任务。在这个快节奏的世界里,内容以惊人的速度被创造出来,观众喜欢看到与他们以前看过的内容相似的内容。
为了做到这一点,选择,喜欢,口味等。以评级或分数的形式记录用户,通常限定在一个有限的范围内(最常见的是 0-5 或 0-10),其中 0 表示用户非常不喜欢该内容,5 或 10 表示用户认为该内容非常有趣并符合他的喜好。
使用这些数据来找出下一步向用户建议什么是协同过滤的全部内容。代替用户动画或用户电影的可以是任何东西,比如消费产品或用户新闻文章或用户社交媒体帖子等等。
从用户那里获得的反馈越多,建议就变得越相关,因为算法能够更好地理解个人的口味。
有几种方法来执行协同过滤,今天,我们将讨论其中的两种。我们将使用 fastai2 ,这是一个由西尔万·古格和杰瑞米·霍华德构建的库,这是一个基于 PyTorch 构建的令人敬畏的界面,用于执行深度学习实验。所以,事不宜迟,我们先从理解 CF 背后的直觉开始。
协同过滤背后的基本直觉
为了执行协同过滤,用户/订户/消费者和项目/物品/产品都被表示为矩阵。(这里的术语是特定于应用程序的,但是因为我们处理的是动画数据,所以我们将分别把用户称为查看者,把项目称为动画。)
更准确地说,每个用户都被表示为一个数值向量,每个动画也是如此。这些值由算法学习以最小化损失函数,该损失函数通常是均方误差损失(MSE)。
为用户和动画向量学习的值对应于抽象的 n 维空间,实际上没有人类解释的意义。但是为了理解到底发生了什么,我们可以这样想。考虑我们正在处理的数据集,即观众-动画数据集。
罗曼·杰尼申科在 Unsplash 上拍摄的照片
假设每部动漫都由 5 个部分组成——爱情、喜剧、生活片段、后宫和动作。那么动画可以在 5 维的向量空间中表示,每个维度是上述维度之一。
在那个五维世界里,Oregairu 和 Hyouka 会离得更*,而东京食尸鬼会离他们相对远一些。因此,这种方法创建了一个 n 维空间,其中所有具有相似组件的动画将比具有不同组件的动画更接*地分组。
现在,想想观众。另一方面,观众向量将表示每个维度中用户所重视的部分。假设用户是浪漫和生活切片的粉丝,那么该用户的向量表示将沿着那些维度具有高数值,并且沿着剩余维度具有较小的数值。
为了整合来自观众和动画的信息,我们求助于使用点积,这是沿着各自的向量维度的简单乘法,然后是聚合。让我用上面我们挑剔的这三部动漫的例子来解释一下。
图片由 Vinayak 提供
这些列表示动画的名称,并且它们中的每一个都被表示为一个 5 维向量,每个分量/维度表示一个特定的类型,如上所示。
正如我们所看到的,Hyouka 和 Oregairu 在所有维度上都有相似的值,而东京食尸鬼在所有维度上都有非常不同的值。
图片由 Vinayak 提供
观众 1 更喜欢动作和生活片段,而不是其他部分,所以,让我们计算观众 1 与所有三部动画的点积。我将在下面手动演示一次计算,您可以类似地计算其他点积。
图片由 Vinayak 提供
我们取两个向量 Oregairu 和观众 1,并将各自的分量相乘,如上面的快照中所示,即,将 Oregairu 的浪漫维度与观众 1 的浪漫维度相乘,将 Oregairu 的喜剧维度与观众 1 的喜剧维度相乘,等等。最后,通过求和将这些乘积聚合成一个值。
一旦我们对所有三部动画都这样做,我们观察到观众 1 的点积分别是 29.2、26 和 31.8。这意味着观众 1 最喜欢东京食尸鬼,这确实是高行动。
另一方面,观众 2 喜欢浪漫和后宫。他和这三部动漫的点积分别是 47.5,35.5,22.5,这意味着他最喜欢《俄勒冈》这部青少年爱情喜剧!由纪之下,汤滨,伊希基,甚至他的老师静香,似乎都对八幡很感兴趣;你敢告诉我你在这部动漫里忽略了后宫…
在宅男话题之后,回到手头的主题,我们可以看到如何将观众和动漫表示为一个向量,这可以证明有助于确定观众对所有动漫的喜欢程度或哪些用户会喜欢特定的动漫,这是网飞等流媒体公司正在利用的非常有价值的洞察力。
对于观众和动画载体来说,还有一个额外的因素叫做偏见。它是一个量,用来分别表示特定用户或特定动漫的唯一信息。因此,如果有一个用户*均给所有动漫都打了高分,或者有一部动漫是所有/大多数观众最喜欢的,而不管他们通常的口味如何,这样的信息就被称为偏见。所以,每一个观众和每一部动画都用一个 n 维向量和一个偏差项来表示。
fastai2 中的协同过滤
fastai2 提供了一个包含 CF 可以利用的函数的子包fastai.collab
,在你的系统上安装 fastai2 之后(这里的指令,你可以按照下面的步骤进行操作。
图片由 Vinayak 提供
大多数情况下,数据是以这种方式存储或表示的。虽然这不是一种非常直观的方式,但它是一种非常有效的存储数据的方式。这是因为大部分观众没看过大部分动漫。
在这种情况下,如果我们试图将其存储为观众 v/s 动画的矩阵,将会有很多零。这样的矩阵称为稀疏矩阵。也有有效的方法来存储这样的矩阵,但是我们暂时让它过去。让我们现在专注于手头的任务。
这里的-1 代表用户看过动漫但没有评价。这是一个常见的场景,主要是因为在现实中,那些看动画的人并不一定会给动画评分。有数据总是比估算好,但是因为我们现在没有数据,我们可以删除有这种评级的行或者估算相同的值。有两种方法可以进行插补:
- 用用户的*均评分估算评分。
- 用动漫的*均评分来估算评分。
两者都有不同的解读。当我们根据一个用户的*均评分进行估算时,我们没有注意到该动漫与特定用户看过的其他动漫相比的相对特征,同样,当我们根据该动漫的*均评分进行估算时,我们忽略了该用户相对于其他用户的相对评分。这可能会在我们的观察中引入轻微的偏差,但我们会接受,因为评级有回归均值的趋势。如果我们选择忽略这些条目,我们最终会丢弃大量对分析有害的数据。
我们将选择估算动漫的*均评分,而不是观众,因为我们已经在 anime.csv 文件中获得了每部动漫的*均评分。这是收视率的最终分布情况
维纳亚克动漫的用户评分
我们可以看到,*均而言,人们倾向于慷慨地为动漫提供评级。他们中的大多数人给出了 7 分或更高的评分,这给我们留下了一个左偏分布,如上图所示。
现在,我们需要加载特定格式的数据,以便将其输入神经网络。fastai 的collab
子包包含一个名为CollabDataLoaders
的模块,我们可以使用它来加载数据。
特别是因为我们正在从 pandas dataframe 加载数据,我们将使用from_df
工厂方法来加载数据。
所以我们在上面创建了一个数据加载器。因为列的名称可能是特定于应用程序的,所以我们需要分别指定用户、项目和评级列的名称。
参数 valid_pct 代表验证数据百分比。一旦我们建立了一个模型,它的实际神圣性是由它在这些数据上的表现来衡量的。我们的模型将使用 90%的可用数据进行训练,并在这 10%的从未见过的验证数据上进行测试。只有当我们的模型在训练集和验证集上都表现良好时,我们才能说我们已经做得很好了。
有了这个dloader
物体,我们可以看到它所包含的一切。
Vinayak 的图像查看器数据加载器的统计数据
在数据集中有许多动漫只有很少甚至没有人给它们评分。不包括这些动漫是有道理的,因为它们弊大于利。这是因为它们已经非常稀疏,这意味着相对于它们的更新非常少,因此学习也很少。很自然地,为这样的动画生成的嵌入将是不合标准的,因此保存它们没有任何意义。
嵌入点偏差模型
这个模型是一个简单的模型,就像我们在上面的The basis
部分讨论的一样。观众和动画都被表示为向量,我们得到相同的矩阵,因为有许多观众和动画。接下来,我们对它们进行点积,并使用我们旨在减少的损失函数均方误差,将它们与我们的实际观众评级进行比较。最终,这个模型将变得善于在这个 n 维空间中表现观众和动画。
让我们创建一个简单的嵌入点偏差模型并训练它。
Vinayak 的学习率查找器
fastai2 的学习者对象的lr_find
方法真的很方便。我们可以使用它来计算出我们应该在培训中使用的学习率。它与元组的含义相同。第一个值是最小 lr,这将确保进行一些训练,第二个值是 LR,即损失下降最大的地方。在建议的 lr 中选择一个最接* lr_min 的 lr 是很好的,最好稍微低一点以保守(个人观察)。
Vinayak 的培训总结
在训练模型之后,我们应该看到每次迭代的损失都在减少。如果遇到过度拟合的迹象,我们可以求助于早期停止(这里可能有一个,因为在第五个时期,训练损失增加了),所以保持时期的初始数量较小是好的。一旦你看到了训练和验证失败的趋势,你就可以决定是继续训练还是结束训练。
神经网络模型
在嵌入点偏差模型的基础上,我们可以通过添加完全连接的层来构建 MLP,以提高模型的复杂性。基本上,用户和电影向量被连接在一起,并在获得最终点积之前通过一系列神经网络。虽然在大多数情况下,前者表现得相当好,但这种神经网络模型在一些其他情况下也确实工作得很好。
这是一个执行试验和寻找最佳执行网络评估验证数据的问题,我们可以得出哪个模型执行得更好的结论。让我们也使用神经网络建立一个模型,并测试它的性能。
Vinayak 的学习率查找器
学习率查找器返回有些类似的结果,但是由于我们增加了深度,我们可以看到所需的 min_lr 已经下降。根据我的经验,当我们增加网络的深度时,可以观察到建议的 lr_min 降低。对于更深的网络,我们通常必须更加保守,因为收敛更容易受到学习速率值的影响。
Vinayak 的培训总结。
培训日志放在一边。似乎在最后添加两个 FC 层真的没有什么不同,因为与嵌入点偏差模型相比,损耗进一步增加了。
模型解释和提出建议
现在我们已经有了一个模型,让我们试着解释它,使用它,并提出一些建议/推荐。
理解动漫偏见和权重/嵌入
让我们试着理解嵌入点偏差模型的动画嵌入。首先,让我们看看模型中的所有层是什么。
learn.model
图片由 Vinayak 提供
如前所述,观众和动画分别有两个分量,一个是矢量,另一个是偏差项。
让我们按排名最高的动画排序(不是排名很高,而是排名最高,即观众观看并评价了动画)。
图片由 Vinayak 提供
让我们检查这些动画的偏见,并与这些动画的评级进行比较。同样,让我们检查评分最低的动画的偏见,并将它们与相同的评分进行比较。为了便于理解,我们来比较一下这其中排名前 5 位和后 5 位的情况,看看结果。
bias_rating_data.sort_values(by = ["Ratings"], ascending = False).head()bias_rating_data.sort_values(by = ["Ratings"], ascending = True).head()
Vinayak 评出的“收视率最高的动漫”
评价高的动漫通常有很高的偏见。这与上面的观点是一致的,即所有观众都喜欢动漫,而不管他们的品味如何。
Vinayak 的“评价最低的动画”
评级低的动漫一般偏向性很低。这与上面的观点是一致的,即对于所有观众都不喜欢的动画,不管他们的品味如何,这种偏见是很小的。
接下来,正如我们所讨论的,权重只不过是模型学习到的向量。让我们找出前 100 名动画的权重,对它们应用主成分分析以减少它们的维度,然后在二维图上进行视觉比较。PCA 是一种用于压缩向量/矩阵的降维技术,特别是当我们必须可视化大规模数据时,或者当我们面临具有大量特征或列的数据集中的维数灾难问题时,通常会用到它。
用主成分绘制动画
可以看出,像《东京食尸鬼》和《攻击泰坦》这样动作性很强的动漫高于 y=0.5 线,而像《Clannad》、《K-On》、《Ouran Host Club》这样的爱情/生活片段动漫则低于 y = 0.5 线,尽管有一些例外。
此外,沿着 x 轴向右,浪漫和生活片段似乎越来越占主导地位,例如,Clannad After Story 位于 Clannad 和 K-on 的右侧,Ouran Host Club 位于右侧。
这是数据的压缩版本,因此这里没有描述大量丢失的信息。我们已经将嵌入向量的维数从 60 减少到 2,但是我们仍然可以看到数据的一些结构,这是非常棒的。由于人类只能感知三维的物质世界,我们无法想象 60 维的嵌入空间,因此有了这个*似值。
现在我们已经收到了所有动漫的嵌入(真嵌入),让我们来比较一下 Oregairu,东京食尸鬼和 Hyouka 之间的距离。
维纳亚克的《东京食尸鬼》、《兵库》与《奥雷盖鲁》之比较
我们可以确认,正如我们之前讨论的,Hyouka 和 Oregairu 确实彼此更接*,因为它们的点积在三者中是最高的。此外,Hyouka 和 Oregairu 与东京食尸鬼的点积距离几乎相等。这意味着该算法做了一件相当不错的工作,尽管它并不真正知道现实中的三部动画属于哪种类型。
了解用户权重/嵌入
为了理解用户权重,我们将从我们的集合中随机抽样一个用户,然后在剩余的语料库中,根据称为余弦相似性的特定距离度量,挑选一个离这个随机抽样的用户最*的用户和一个最远的用户。
基本上,我们将在整个用户语料库的跨度中取那个用户、离他*的用户和离他最远的用户的点积,然后查看各自的动画以查看差异。
维纳亚克的《比较用户》
我们发现,我们随机抽样的用户喜欢动作和虚构成分高的动漫,并涉及一些戏剧/爱情/生活片段的元素。最相似的用户也喜欢高度动作和虚构的类型。
可以看出,最相似的用户选择了几乎所有的动漫,这些动漫与那个随机的家伙喜欢的动漫相同,而最不同的动漫具有更高程度的剧情/生活片段。
CF 的一个缺点&潜在的解决方案
现在,我们看了数据库中已经存在的用户推荐。如果我们有一个新用户进来,我们没有任何建议给他,因为他没有评价任何动画/电影。
这就是通常所说的冷启动问题。
为了解决这个问题,新用户被问了几个问题,这些问题与他对我们目录中的动漫的喜欢和不喜欢有关。这使得系统推荐一些动漫,并且随着用户更频繁地参与*台并给出反馈,推荐变得越来越精炼,以适合观众的口味和喜欢。
协作过滤或推荐系统已经存在,并帮助观众/用户/消费者/订户获得适合他们喜好和品味的内容。希望这篇文章能帮助你快速了解快乐学习!如果你想深入研究,我在参考资料部分推荐了一些文章。
参考资料和进一步阅读
- fastai 中的协同过滤
- 推荐系统深度指南
- Github 回购本文使用的所有代码
- Kaggle 上的动漫推荐数据集
- 杰瑞米·霍华德在 Youtube 上解释协同过滤
collatz——你不完全理解的最简单的程序
原文:https://towardsdatascience.com/collatz-the-simplest-program-that-you-dont-fully-understand-30b223c6fd8c?source=collection_archive---------32-----------------------
用 Wolfram 语言进行计算探索
大约 10 分钟后,一个人看着 Collatz 程序的照片,由 Unsplash 上的 Sebastian Herrmann 拍摄
我喜欢认为自己无所不知,尤其是在编程方面。而且,很长一段时间以来,我认为如果我观察一段代码足够长的时间,我就能够完全理解它的行为。只需逐行阅读代码,并仔细考虑 if 语句和 for 循环的可能情况。只要有足够的时间和耐心,所有代码都是完全可以理解的。
然而,我写的代码并没有像预期的那样运行。事实上,这种情况发生了很多。通常情况下,我写一段新代码的前十次尝试中,有九次都是谦逊编码的经历。但是,我仍然把这归因于输入错误、编写不完整的代码,以及在输入实际代码之前不耐烦和没有充分考虑事情。
有一天,有人向我展示了一段实现了 Collatz 算法的 Wolfram 语言代码,这一切都改变了。这个想法非常简单:编写一个接受正整数作为唯一参数的函数。如果数字是 1,就完成了,从函数中返回 1。如果数字大于 1,则有两个分支:如果数字是偶数,则除以 2 并返回该数字。如果数字是奇数,则返回该数字的三倍加 1。
collatz[1] = 1
collatz[n_Integer /; n>1 ] := If[ EvenQ[n], n/2, 3n+1 ]
到目前为止,一切顺利。你可以用不同的整数试一下,一切都很好:
collatz[5] --> 16
collatz[8] --> 4
但是当你写一个程序来计算下面的序列时,曲线球就出现了:
collatz[16] --> 8
collatz[8] --> 4
collatz[4] --> 2
collatz[1] --> 1 (* done! *)
在 Wolfram 语言中实现这一点的一个简单方法是使用 NestWhileList :
collatzSequence[n_Integer /; n > 0] :=
NestWhileList[collatz, n, # != 1 &]
n=16 的例子给出:
collatzSequence[16] --> {16, 8, 4, 2, 1}
这看起来很简单,但是有一个小问题:当你遇到一个奇数的时候,下一个数字将会大三倍(加一)。下一个数字也将是偶数,这意味着之后的数字将再次减半。这里有一个例子,当你从一个奇数开始:
collatzSequence[17] --> {17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1}
数字序列首先上升到 52,但随后又迅速回落到 1。显然,这最终会发生在每一个数字上?不幸的是,我们不得不考虑这样一种可能性,即有些数字产生的序列永远不会达到 1。例如,可能有一个序列,其中的数字随着时间的推移慢慢反弹,变得越来越大。阅读代码在这里没有太大帮助。下面是一个起始数的示例,其中序列不会快速变为 1:
collatzSequence[63728127]
(图片由作者提供)
这是这个数列的图表:
(图片由作者提供)
尽管我们可以阅读代码并理解任何数字的每一步会发生什么,但我们无法知道程序是否会终止(甚至不知道给定数字的序列长度)。仔细研究过这个问题的人推测(但没有证明)每个数字都有一个以 1 结尾的序列。这个猜想被称为科勒兹猜想以第一个提出这个问题的洛萨科勒兹命名。
对于这个问题,人们已经有了很多有趣的发现和可视化,而没有实际解决猜想本身。一个非常有趣的视觉效果是一个由许多起点以及这些序列如何最终相遇并融合在一起的图:
(图片由作者提供)
或者一个更简单的图形显示不同的 Collatz 序列如何合并并最终在数字 1 处相遇:
(图片由作者提供)
我得到的教训是,即使是最简单的程序也不一定能理解。因此,当我看到一个文档记录很差的巨大的源代码文件时,我也不会感觉很糟糕。在许多情况下,你所能做的最好的事情就是运行一个有许多不同输入的程序来开发直觉和推测,并使用它来迭代你的代码到一个点,在这个点上它的行为大部分是你所期望的。也许有一天,有人会为 Collatz 序列找到一个不以零结尾的起始数。但我觉得这就是那种可能永远解不开的编程难题!
收集和可视化新冠肺炎数据
原文:https://towardsdatascience.com/collect-and-visualize-covid-19-data-336e4dc9ead?source=collection_archive---------39-----------------------
网络抓取和探索性数据分析初学者指南
不用说,每个人都很清楚新冠肺炎对整个世界的毁灭性影响。有数不清的数据集可用于捕捉这种病毒在全球传播的趋势。
就我个人而言,我更感兴趣的是分析我的家乡宾夕法尼亚州(美国)的新冠肺炎案例。我偶然发现了宾夕法尼亚州卫生部网站,该网站公布了宾夕法尼亚州按县分列的每日新冠肺炎病例。不幸的是,每天的更新都以 HTML 表格的形式呈现在单独的部分中。当我们浏览这个网页时,很难在脑海中形成每日趋势的图像。因此,我决定接受挑战来解决这个问题。我开始了一个周末迷你项目来实施解决以下问题的方法:
- 从网页中提取数据
- 执行数据分析
- 创建数据可视化
结果显示在我的 GitHub Repo 中的 Jupyter 笔记本中。不幸的是,GitHub 无法渲染交互式数据图,如果您希望查看,请访问 Jupyter NBViewer 。
事不宜迟,我们开始吧!我将向你详细介绍我的学习历程。
我们将从如何将 html 表格转换成数据集开始,然后是数据操作、绘图和图表。最后,我们将创建一个交互式地图,按县显示确诊病例。
通过网络抓取提取数据
我想简单介绍一下我是如何从每天更新的 PA 卫生部网页中提取数据集的。当您滚动页面时,您会注意到每个每日部分都以日期标题开始(例如:2020 年 4 月 8 日)。我对汇总以下两个表中的数据感兴趣,即总计数表和按县的总计数表。
总计数表:显示迄今为止的阴性、阳性病例和死亡总数。
County Total Counts by County 表:显示宾夕法尼亚州各县迄今为止的阳性病例和死亡总数。
下面是网络抓取策略的概要,完整的源代码可以在我的 GitHub 库中找到。
您需要安装这些依赖项:
pip install beautifulsoup4
pip install lxml
第一步。提取< h4 >标题之间的日期并存储一个列表。
第二步。提取每个总计数表中的数据,并将其与步骤 1 中的日期匹配。输出文件的示例如下所示。
**pa_summary.csv:** Date,Negative,Positive,Deaths
2020–04–08,82299,16239,309
2020–04–07,76719,14559,240
第三步。 提取各县总计数表中的数据,并将其与步骤 1 中的日期进行匹配。输出文件的示例如下所示。
**pa_county.csv:** Date,County,Cases,Deaths
2020–04–08,Adams,33,0
2020–04–08,Allegheny,720,1
第四步。调用 MapQuest 地理编码 API 获取各县的纬度和经度。你可以建立一个每月 15K 交易的免费账户。从 MapQuest 获取 API 密钥,并更新 data_extractor_pa.py 中的 API_KEY 值。输出文件的示例如下所示:
**pa_county_geolocation.csv**
County,Latitude,Longitude
Bradford,41.774669,-76.526461
Butler,40.861021,-79.895225
第五步(可选)。如果您希望获得最新数据,请运行提取程序重新生成 CSV 文件。
python data_extractor_pa.py
进行探索性数据分析
有了这三个数据集,让我们启动 Jupyter 笔记本。
首先,导入这些依赖项:
import datetime as dt
import matplotlib.pyplot as plt
from matplotlib import style
import pandas as pd
将汇总数据集加载到 Panda 数据框架中:
df = pd.read_csv("pa_summary.csv")
df.head(5)
计算测试总数和阴性/阳性/死亡百分比:
df['Tested'] = df['Positive'] + df['Negative']
# Percentages
df['Positive_Percent'] = round(100*df['Positive']/df['Tested'], 1)
df['Negative_Percent'] = round(100*df['Negative']/ df['Tested'], 1)
df['Death_Percent'] = round(100*df['Deaths']/ df['Tested'], 3)
# sort by date
df = df.sort_values('Date', ascending = True)
df.head(5)
绘制迄今为止的总测试数、阳性数、阴性数和死亡数:
源代码
测试人群中阳性与阴性的百分比是多少?
源代码
也许观察每天的变化更有意义。
以下代码片段显示了如何利用 panda 中可用的 diff 函数来计算案例的每日变化。注意,我们需要在第一行填入 0 以避免得到 NaN。
源代码
看着县细目
df_counties = pd.read_csv("pa_county.csv")
df_counties.head()
费城的确诊病例趋势如何?
# Filter Data for a County
county_name = 'Philadelphia'
df_county = df_counties[df_counties['County']== county_name]
df_county = df_county.sort_values('Date', ascending = True)# Line Plot
style.use('ggplot')
ax = plt.gca()
df_county.plot(kind='line',x='Date',y='Cases', color='green', ax=ax, figsize=(20,10))
plt.title('Number of Cases In ' + county_name +' County')
plt.xlabel('Date')
plt.ylabel('Cases')
plt.show()
创建交互式数据地图
让我们开始准备一个数据框架,以便在交互式地图中按县显示确诊病例。
我们如何在地图上指出每个县?
首先,加载包含每个县的纬度/经度对的县地理定位数据集
df_geo = pd.read_csv("pa_county_geolocation.csv")
df_geo.head()
执行左外连接,将 lat/long 列添加到 county 数据框架中。
df_county_with_geo = df_counties.merge(df_geo, how='left', on=['County'])
df_county_with_geo.head()
最后,我们只想保留最新日期的记录。
df_latest_county = df_county_with_geo[df_county_with_geo['Date'] == df_county_with_geo['Date'].max()]# drop unnecessary columns
del df_latest_county['Date']
del df_latest_county['Deaths']df_latest_county.head()
我们已经准备好创建一个交互式地图
我选的是 Folium,它有丰富的渲染交互式地图的功能。这不是一个关于叶子的教程。请访问这里了解更多信息。
在继续之前,您需要安装 need。
pip install folium
只需几行代码,我们就可以构建一个非常棒的交互式数据地图,显示宾夕法尼亚州各县的新冠肺炎确诊病例。
源代码
让我们走一遍我们正在做的事情
- 将地图置于某个位置的中心,以便在查看区域内可以看到大多数数据点。
- 函数 get_icon_color()根据正例的值确定在地图上显示的图标的颜色。
- 创建一个具有中心点和适当缩放级别的地图。
- 将每个县的数据点装饰成彩色编码的图标和弹出文本,以显示计数和县的名称。
- 创建图例部分以显示颜色的含义。这篇关于如何给叶子地图添加图例的博客文章值得称赞。
那都是乡亲们!!
这篇文章的代码可以在 GitHub 上找到。我希望这能激励你走出你的舒适区去学习新的东西。直到下一次,继续学习,每天都变得更好。
资源:
- 熊猫数据框架 API 参考
- Matplotlib 文档
- Beautifulsoup 文档
- 树叶文档
- 为树叶地图创建一个图例
- Map Quest 地理编码 API
使用 Python 和 Ally Financial API 轻松收集股票和期权数据— 3 个示例查询
原文:https://towardsdatascience.com/collect-stock-and-options-data-easily-using-python-and-ally-financial-api-3-example-queries-45d162e4f055?source=collection_archive---------15-----------------------
简短的备忘单
由 pikrepo 提供
尝试交易
在我生命中的一段时间里,我痴迷于金融市场,想成为一名日间交易者。我晚上工作,所以早上很容易被电脑显示器包围,显示器上显示着从股票、期权、新闻到交易聊天室的一切。剧透…我放弃了日内交易,但没有放弃投资。最终,我知道我喜欢分析数据胜过交易,然后我让自己走上了学习数据分析和进入数据科学的道路。
当我在探索收集股票和期权数据的方法时,我查看了我的一个经纪人 Ally Financial 提供的 API。它可以免费使用并且易于编码。这是我为使用 Ally Financial API 收集以下信息而整理的备忘单:
- 股票的时间和销售
- 期权市场深度
- 选项扩展报价
如果你不熟悉 API,看看这些资源。通过它们的 API 实现交易自动化是可能的,但我从未深入研究过。探索文档中的所有功能。
[## Ally Invest API 文档
构建您的应用程序,连接到我们的投资*台和与之相连的 250,000 名交易者…
www.ally.com](https://www.ally.com/api/invest/documentation/getting-started/)
你可以在文章底部或者我的 GitHub 上找到完整的备忘单!
[## bend game/Ally-API-备忘单
Ally Financial API 入门。通过创建一个帐户,为 bendgame/Ally-API-Cheat-Sheet 开发做出贡献…
github.com](https://github.com/bendgame/Ally-API-Cheat-Sheet)
继续编码!
导入依赖项
连接到 API 使用 OAuth1 。你可以在 OAuth 网站这里找到 OAuth 客户列表。我使用 OAuth 库 requests_oauthlib 。根据需要使用 pip 安装请求-oauthlib 。
import requests
from requests_oauthlib import OAuth1
from config import (api_key, secret, oath_token, oath_secret)
import pandas as pd
import sqlalchemy
import numpy as np
import sqlite3
from sqlite3 import Error
import matplotlib.pyplot as plt
import datetime as dt
注意,我使用一个配置文件来导入 api_key、secret、oath_token、oath_secret 。这样,我就不需要在代码中包含那些个人令牌。
*#authentication*
auth = OAuth1(api_key, secret, oath_token, oath_secret)
我把进口令牌递给oauth 1。这将在我们向 API 发出请求时使用。
股票的时间和销售示例
这个 API 调用将根据作为查询参数传递的符号返回时间和销售报价数据。有关所有查询参数的列表,请查阅文档。示例 URL 由 基础 url 、 api 路由 和 查询 组成。
基础网址:https://api.tradeking.com/
路线:v1/market/timesales . JSON
查询:?symbols=MSFT &开始日期= 2019–05–03&间隔= 1 分钟
文档:https://www . ally . com/API/invest/Documentation/market-timesales-get/
*#url call to the api*
url = 'https://api.tradeking.com/v1/market/timesales.json?symbols=MSFT&startdate=2019-05-03&interval=1min'*#api request*
response = requests.get(url, auth = auth).json()
注意,我将 URL 和 oAuth 值传递给请求,并将响应作为 json 返回。这是一个响应示例:
我将报价数据放入 Panda 的数据帧中,并格式化数据类型。
*#send to data frame and format data types*
df = pd.DataFrame(response["response"]["quotes"]["quote"])
df = df.sort_values(['datetime'], ascending = **False**)
df['date'] = pd.to_datetime(df['date'])df['datetime'] = pd.to_datetime(df['datetime'], utc=**False**).dt.tz_convert('US/Central')df['hi'] = df["hi"].astype(float)
df['incr_vol'] = df["incr_vl"].astype(float)
df['last'] = df["last"].astype(float)
df['lo'] = df["lo"].astype(float)
df['opn'] = df["opn"].astype(float)
df['vl'] = df['vl'].astype(float)df.head()
示例数据
日期时间值需要转换,以便能够对其进行重新采样。重采样允许您操纵时间序列的频率。根据文档,对象必须有一个类似于 datetime 的索引( DatetimeIndex 、 PeriodIndex 或 TimedeltaIndex ),或者将类似于 datetime - 的值传递给 on 或 level 关键字。
*#resample the time value to be greater than 1 min as needed. Example: 30 min resample for last price*
df.set_index(df['datetime'], inplace = **True**)
df.head()
df_resample30 = df.resample(rule = '30min', label = 'right').last()
df_resample30.head()
重采样数据帧
请注意, 日期时间 在重采样后增加了 30 分钟,而不是 1 分钟。
选项搜索示例
由 pxfuel 提供
这个 api 调用为选项提供了市场深度。该调用将返回给定符号的可用选项击的完整列表。虽然这种请求类型是 GET,但是也可以使用 POST,并且推荐用于较长的查询。
文档:https://www . ally . com/API/invest/Documentation/market-options-search-get-post/
基地网址:https://api.tradeking.com/
路线:v1/market/timesales . JSON
查询:?symbol = MSFT&query = xy ear-eq % 3a 2019% 20 and % 20x month-eq % 3a 06% 20 and % 20 strike price-eq % 3a 140
查询细分:
到期年份等于 2019 年 :
xyear-eq%3A 2019
和:
%20 和% 20
到期月份等于 06 :
xmonth-eq%3A 06
和执行价格等于 140:
%20 和% 20 执行价格-eq%3A 140
操作员:
lt :小于
gt :大于
gte :大于等于
lte :小于等于
eq :等于
url = 'https://api.tradeking.com/v1/market/options/search.json?symbol=MSFT&query=xyear-eq%3A2019%20AND**%20x**month-eq%3A06%20AND**%20s**trikeprice-eq%3A140'#api call
response = requests.get(url, auth = auth).json()#load the response into the dataframe
df = pd.DataFrame(response["response"]["quotes"]["quote"])
df
扩展报价示例(可选)
这条路线适用于股票,但这是一个期权看涨的例子,因为它们有点复杂。该调用将返回作为查询参数传递的符号或符号列表的引号。
文档:https://www . ally . com/API/invest/Documentation/market-ext-quotes-get-post/
基础网址【https://api.tradeking.com/】:
路线:v1/market/ext/quotes . JSON
查询:?symbols=MSFT190607C00140000
选项符号命名约定:
图片来自文档
基础符号— MSFT
2 位到期年份— 19
2 位到期月份— 06
2 位到期日—07
“C”代表买入或“P”代表卖出— C
8 位执行价格— 00140000
根据需要使用 fids 在查询中指定所需字段:
即 fids=ask、bid、vol
尽管命名约定有几个组成部分,但通过几个例子就可以看出它相当简单。同时,使用文档或备忘单中提供的示例图像!
url = 'https://api.tradeking.com/v1/market/ext/quotes.json?symbols=MSFT190607C00140000'#api call
response = requests.get(url, auth = auth).json()#load the response into the dataframe
df = pd.DataFrame(response["response"]["quotes"]["quote"], index = [0])
df
扩展报价示例
将这些点连接起来
使用 Pandas,很容易将数据保存到 CSV 或 SQL 数据库中。如果你不熟悉 SQLite ,它非常容易使用。引用文档:
SQLite 是一个 C 库,它提供了一个轻量级的基于磁盘的数据库,不需要单独的服务器进程,并允许使用 SQL 查询语言的非标准变体来访问数据库。
conn = sqlite3.connect('stockdata.sqlite')
df.to_sql(table_name, conn)
由 Flickr 提供
完全码
使用这三个查询,很容易开始使用 Ally Financial API 收集股票和期权数据。将数据放入 Panda 的 dataframe 中可以很容易地理解 JSON 信息并将数据存储为 CSV 或 SQLite 文件。如果您想探索股票数据的其他 API,也可以查看一下 Alphavantage 。
在我的 github 上找到包含文档的备忘单!
import requests
from requests_oauthlib import OAuth1
from config import (api_key, secret, oath_token, oath_secret)
import pandas as pd
import sqlalchemy
import numpy as np
import sqlite3
from sqlite3 import Error
import matplotlib.pyplot as plt
import datetime as dt*#authentication*
auth = OAuth1(api_key, secret, oath_token, oath_secret)*#url*
url = 'https://api.tradeking.com/v1/market/timesales.json?symbols=MSFT&startdate=2019-05-03&interval=1min'*#api request*
response = requests.get(url, auth = auth).json()*#send to data frame and format data types*
df = pd.DataFrame(response["response"]["quotes"]["quote"])
df = df.sort_values(['datetime'], ascending = **False**)
df['date'] = pd.to_datetime(df['date'])
df['datetime'] = pd.to_datetime(df['datetime'], utc=**False**).dt.tz_convert('US/Central')
df['hi'] = df["hi"].astype(float)
df['incr_vol'] = df["incr_vl"].astype(float)
df['last'] = df["last"].astype(float)
df['lo'] = df["lo"].astype(float)
df['opn'] = df["opn"].astype(float)
df['vl'] = df['vl'].astype(float)
df.head()*#resample the time value to be greater than 1 min as needed. Example: 30 min resample for last price*
df.set_index(df['datetime'], inplace = **True**)
df.head()
df_resample30 = df.resample(rule = '30min', label = 'right').last()
df_resample30.head()#Options Search Exampleurl = 'https://api.tradeking.com/v1/market/options/search.json?symbol=MSFT&query=xyear-eq%3A2019%20AND**%20x**month-eq%3A06%20AND**%20s**trikeprice-eq%3A140' response = requests.get(url, auth = auth).json()
df = pd.DataFrame(response["response"]["quotes"]["quote"])
df.head()#Extended Quote Exampleurl = 'https://api.tradeking.com/v1/market/ext/quotes.json?symbols=MSFT190607C00140000'response = requests.get(url, auth = auth).json()df = pd.DataFrame(response["response"]["quotes"]["quote"], index = [0])
df.head()
谢谢大家!
- 如果你喜欢这个, 跟我上 Medium 了解更多
- 通过订阅 获得完全访问权限并帮助支持我的内容
- 我们连线上LinkedIn
- 用 Python 分析数据?查看我的 网站
—埃里克·克莱本
查看我的其他教程,了解更多 python 和 sql!
[## 学习 SQL 技术:在 SQL Server 中选择数据和更多内容
SQL 语句介绍和查找重复数据的查询。学习 SQL
medium.com](https://medium.com/@erickleppen01/learn-sql-techniques-selecting-data-and-more-in-sql-server-624f81dd16b2) [## Python 中的仪表盘,适用于初学者和使用 Dash 的其他人
使用 Python 中的 Dash 初学者教程构建一个基本的和高级的仪表板
medium.com](https://medium.com/swlh/dashboards-in-python-for-beginners-and-everyone-else-using-dash-f0a045a86644)
为自定义对象检测收集数据
原文:https://towardsdatascience.com/collecting-data-for-custom-object-detection-e7d888c1469b?source=collection_archive---------6-----------------------
用于训练您的自定义检测模型的 5 种数据收集技术
在过去的十年里,深度学习在计算机视觉中的使用越来越多。在过去的几年中,计算机视觉应用,如人脸检测和车辆检测已经成为主流。原因之一是预训练模型的可用性。
被深度学习在这些应用上的成功所说服,企业现在已经开始使用深度学习来解决自己的问题。
但是如果可用的预先训练的模型不适合您的应用程序呢?
假设您有一个家禽养殖场,想要使用物体检测来将好鸡蛋与坏鸡蛋进行分类,这样您就可以在包装过程中自动剔除坏鸡蛋。
包装中的 5 个好鸡蛋和 1 个坏鸡蛋(图片由 Caroline Attwood 在 Unsplash 上拍摄)
一个预先训练的模型也许能够检测鸡蛋,但它肯定不会区分好鸡蛋和坏鸡蛋,因为它从未被教会这样做。
那你会怎么做?
获取大量好鸡蛋和坏鸡蛋的图像,并训练一个定制的检测模型。
创建良好的定制计算机视觉模型的一个常见挑战是训练数据。深度学习模型需要大量的数据来训练其算法,正如我们在基准模型中看到的那样,如 MaskRCNN 、 YOLO 和 MobileNet ,这些模型是在现有的大型数据集 COCO 和 ImageNet 上训练的。
如何获取用于训练自定义检测模型的数据?
在本帖中,我们将探讨 5 种收集数据的方法,用于训练您的自定义模型来解决您的问题。
1.公开可用的开放标记数据集
如果你幸运的话,你可能会在网上得到你想要的带标签的数据集。
这里有一个免费的计算机视觉图像数据集列表,你可以从中选择。
ImageNet:ImageNet 数据集包含总共约 1400 万张图像,涉及 21,841 个不同类别的对象(截至 2020 年 2 月 12 日的数据)。ImageNet 中一些流行的对象类别是动物(鱼、鸟、哺乳动物、无脊椎动物)、植物(树、花、植物)和活动(运动)。
ImageNet 数据集中的图像示例(来源)
【COCO】:COCO 是一个大规模的对象检测、分割和字幕数据集。它包含大约 330,000 幅图像,其中 200,000 幅图像被标记为 80 种不同的物体类别。
COCO 数据集的图像示例(来源)
Google 的开放图像 : 开放图像是一个约 900 万张图像的数据集,标注有图像级标签、对象边界框、对象分割遮罩和视觉关系。它包含 1.9M 图像上 600 个对象类的总共 16M 的边界框,使其成为具有对象位置注释的最大现有数据集。
开放图像数据集的图像示例(来源)
MNIST 手写数据集 :该数据集总共有 70,000 个手写数字图像,是可从 NIST 获得的更大集合的子集。数字已经过大小标准化,并在固定大小的图像中居中。
来自 MNIST 数据集的图像示例(来源)
Cityscapes 数据集 : 该数据集专注于城市街道场景的语义理解。它包含 30 个不同类别的大约 20,000 张带注释的图片。
来自 Cityscapes 数据集的注释图像示例(来源)
注意:这些只是我找到的几个,还有很多其他的数据集你可以在网上找到。此外,请确保在使用这些数据集之前检查其许可。
2.刮网
另一个选择是在网上搜索图片,然后手动选择下载。由于需要大量数据,这种方法效率不高。
注意:网络上的图片可能受版权保护。在使用这些图片之前,一定要记得检查它们的版权。
谷歌图片中的图片搜索示例
另一种方法是编写一个程序来抓取网页并下载你想要的图片。
一个这样的程序是下载所有图片,一个谷歌 Chrome 的扩展,允许你一次下载一堆图片。在这篇博文中, Arun Ponnusamy expalins 介绍了如何使用下载所有图片来下载戴头盔的人的图片。
注意:图像的版权使用权可能不允许使用批量下载的图像。在使用之前,一定要检查每张图片的版权。
3.拍照
如果您找不到您想要的对象的图像,您可以通过单击照片来收集它们。这可以手动完成,即通过自己点击每张图片或众包,即雇佣其他人为你拍照。另一种收集真实世界图像的方法是在你的环境中安装可编程的摄像机。
张小姐在 Unsplash 上的照片
4.数据扩充
我们知道深度学习模型需要大量的数据。当你只有一个很小的数据集时,可能不足以训练一个好的模型。在这种情况下,您可以使用数据扩充来生成更多的训练数据。
诸如翻转、裁剪、旋转和*移等几何变换是一些常用的数据扩充技术。应用影像数据扩充不仅可以通过创建变化来扩展数据集,还可以减少过度拟合。
左边是一只狗的原始图像,右边是围绕中心水*翻转的图像(来源
猫的原始和随机裁剪图像(来源)
猫的原始和旋转图像(来源
网球的原始图像和翻译图像(来源
5.数据生成
有时,真实数据可能不可用。在这种情况下,可以生成合成数据来训练您的自定义检测模型。由于其低成本,合成数据生成在机器学习中的使用越来越多。
生成对抗网络(GANs)是用于合成数据生成的许多技术之一。GAN 是一种生成性建模技术,其中人工实例是以保留原始集合的相似特征的方式从数据集创建的。
甘的现代艺术(来源)
摘要
收集训练数据集是训练您自己的定制检测机模型的第一步。在这篇文章中,我们看了一些用于收集图像数据的技术,包括搜索公共开放标签数据集、抓取网页、手动或使用程序拍照、使用数据增强技术和生成合成数据集。
在下一篇帖子中,我们将看看训练您的自定义检测器的下一步,即 为您的数据集 贴标签。敬请关注。
您使用什么技术来收集图像数据集? 在下面留下你的想法作为评论。
原载于www.xailient.com/blog。**
找一个预先训练好的人脸检测模型。点击这里下载。
查看这篇文章了解更多关于创建一个健壮的物体检测模型的细节。
更多故事:
在你的 App 上集成人脸检测
在计算受限的设备上运行深度学习计算机视觉的挑战
树莓上挣扎运行的物体检测
你现在需要从云计算转移到边缘计算!
关于作者
Sabina Pokhrel 在 Xailient 工作,这是一家计算机视觉初创公司,已经建立了世界上最快的边缘优化物体探测器。
资源:
Roh,y .,Heo,g .,& Whang,S. (2019 年)。机器学习的数据收集调查:大数据-人工智能集成视角。IEEE 知识与数据工程汇刊,1–1。土井指数:10.1109/tkde。58606.88868688666
* [## 为训练 YOLO 对象检测器准备自定义数据集
2019 年 10 月 6 日 Arun Ponnusamy 来源:Tryo labs 在之前的帖子中,我们看到了如何使用 OpenCV 来使用预训练的 YOLO 模型…
www.arunponnusamy.com](https://www.arunponnusamy.com/preparing-custom-dataset-for-training-yolo-object-detector.html) [## 如何为计算机视觉用例创建训练数据|阿彭
对于简单的计算机视觉项目,如识别一组图像中的模式,公开可用的图像…
appen.com](https://appen.com/blog/how-to-create-training-data-for-computer-vision-use-cases/) [## 为计算机视觉建立训练数据的权威指南
谷歌、微软、亚马逊和脸书等科技巨头已经宣布了他们以人工智能为先的产品战略…
hackernoon.com](https://hackernoon.com/a-definitive-guide-to-build-training-data-for-computer-vision-1d1d50b4bf07)*
如何从《纽约时报》收集任何时期的数据
原文:https://towardsdatascience.com/collecting-data-from-the-new-york-times-over-any-period-of-time-3e365504004?source=collection_archive---------21-----------------------
Python 中的简单指南
来源:JJ·古恩,via Adobe Stock
假设我们想知道在一段时间内,《纽约时报》中的话语是如何演变的。这些天来,分析这一点会很有趣,因为每当我们访问头版时,都会被关于冠状病毒的新闻淹没。疫情是如何塑造了美国最受欢迎的报纸之一的头条新闻的?
要回答这样的问题,我们需要从纽约时报收集文章元数据。这里我描述了如何用 Python 来做这件事。
目录:
- 在哪里可以找到《纽约时报》的文章元数据
- 如何从纽约时报请求文章元数据
在哪里可以找到《纽约时报》的文章元数据
纽约时报提供了一个由几个API组成的开发者网络,让非员工向他们索取文章和元数据,这对于这种分析来说超级方便。
实际上,没有多少报纸这么做。维护一个 API 需要做很多工作。对于不提供 API 的报纸,我们需要一种不同的方法来获得它们的标题。还是有可能的,只是没那么容易。
开始使用纽约时报API:
在这里创建一个免费的开发者账户。打开验证电子邮件中的链接后登录。进入开发者的主页。
纽约时报开发者网络的主页。
在您的开发者帐户中注册一个新应用。
- 点击右上角的电子邮件地址。
- 在出现的下拉菜单中选择应用。
- 在您的应用程序页面选择+新应用程序。
- 输入任何名称和描述。
- 激活存档 API。
- 选择创建。
记下您刚刚注册的应用程序的 API 密钥。这是我们需要从《纽约时报》获取数据的唯一信息,我们很快就会需要它。
您的应用的 API 密钥。
如何从纽约时报请求文章元数据
我们将使用归档 API 来获取去年的所有文章元数据。这段代码可以在 1851 年到今天的任何时间内修改。
归档 API 概述。
加载依赖项。
import os
import json
import time
import requests
import datetime
import dateutil
import pandas as pd
from dateutil.relativedelta import relativedelta
指定日期范围。
end = datetime.date.today()
start = end - relativedelta(years=1)
列出属于这个范围的月份,即使只是一部分。我们需要这些信息来调用归档 API,因为它一次只能运行一个月。
months_in_range = [x.split(' ') for x in pd.date_range(start, end, freq='MS').strftime("%Y %-m").tolist()]
范围内的月份
我编写了一些代码来请求和处理来自归档 API 的文章元数据。这段代码一次只能运行一个月,以实现最佳的内存管理。我们向 API 发送给定月份的请求,接收并解析响应,然后用每篇文章的一些详细信息填充数据框,包括其出版日期、主要标题、章节、主题关键字、文档类型和材料类型。最后,我们将数据帧保存为 CSV 文件,并继续下一个月,直到到达所需时间范围的末尾。
从纽约时报存档 API 请求和处理任意时间段的文章数据的代码。
注意,每个 API 有两个速率限制:每天 4000 个请求和每分钟 10 个请求。为了避免达到每分钟的速率限制,我们在两次通话之间睡眠 6 秒钟。
不要忘记用你的 API 键在第 4 行切换出 YOUR_API_KEY 。
运行代码以获取并处理来自 months_in_range 的文章。
我们已经收集了去年 80,460 篇文章的元数据!每个月都被保存到 headlines 目录下的 CSV 文件中。
让我们看看我们处理的上个月的响应是什么样子的,它仍然在内存中。
response
还有很多。文档告诉我们那里都有什么。
看看这个月的 CSV 文件是什么样子的。
df
正如在数据框中看到的,偶尔会有一致性问题需要注意。有时一个月的第一天被认为是前一个月的一部分。有时数据会缺失,比如 1978 年 9 月和 10 月,原因是多工会罢工。
我们可以利用我们现在的 headlines 目录中的所有文章元数据做很多事情。我们可以做的事情之一是探索《纽约时报》在过去一年的报道中是如何演变的,重点是疫情冠状病毒。这将是有趣的,因为我们不仅考虑发生了什么,而且考虑媒体如何讨论它。
完整的笔记本是这里。
如果你想阅读更多我的文章或探索数百万篇其他文章,你可以注册一个中级会员:
[## 通过我的推荐链接加入 Medium-briena Herold
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
brienna.medium.com](https://brienna.medium.com/membership)
您还可以订阅我的电子邮件列表,以便在我发布新文章时得到通知:
[## 每当布蕾娜·赫罗尔德发表。
每当布蕾娜·赫罗尔德发表。通过注册,您将创建一个中型帐户,如果您还没有…
brienna.medium.com](https://brienna.medium.com/subscribe)
你可能会对我的其他一些故事感兴趣:
[## 如何免费下载 Twitter 好友或关注者
Python 中的简单指南
towardsdatascience.com](/how-to-download-twitter-friends-or-followers-for-free-b9d5ac23812) [## 总统竞选中服用维柯丁:用马尔可夫链制造假头条
在讽刺和现实之间游走
towardsdatascience.com](/zonked-on-vicodin-in-the-presidential-race-generating-fake-headlines-with-markov-chains-87f06cccd866) [## 如何批量获取 arXiv 全文预印本
使用 Python3 和 MacOS X 命令行
towardsdatascience.com](/how-to-bulk-access-arxiv-full-text-preprints-58026e19e8ef)
使用 Python 通过 RSS/Atom 提要收集新闻文章
原文:https://towardsdatascience.com/collecting-news-articles-through-rss-atom-feeds-using-python-7d9a65b06f70?source=collection_archive---------5-----------------------
新闻捕手
或者如何停止依赖数据提供商
由 Unsplash 上的Cup 先生/杨奇煜·巴拉拍摄的照片
在我之前的一篇文章中,我谈到了如何只用 5 行代码就能搜集和分析新闻文章:
[## 用 5 行 Python 代码抓取并总结新闻文章
好的程序员写代码,伟大的先搜索 github。
towardsdatascience.com](/scrape-and-summarize-news-articles-in-5-lines-of-python-code-175f0e5c7dfc)
这次我将向您展示如何设置一个管道来自动收集几乎所有新闻提供商(如纽约时报、CNN、彭博等)发布的所有新文章。)
为了实现这个目标,我将向您展示如何使用 feedparser Python 包自动收集新闻,该包有助于规范 RSS/Atom 提要。
这篇文章是写给谁的?
面向可能希望收集自己的数据并练习构建数据管道的数据工程师和数据科学家。
什么是 RSS 和 Atom?
RSS 是一种 XML 格式的纯文本,提供一些内容提供商(新闻、播客、个人博客等)最*发表的文章的简要摘要。)
RSS 最常见的生产者是新闻出版商。
RSS 提要的存在是为了提供对最新新闻的访问(例如,对于新闻聚合器和新闻辛迪加)。
RSS 提要不包含整篇文章的文本(在大多数情况下),但提供一些基本信息,如作者、标题、描述、发表时间等。
Atom 是另一种 XML 格式,是作为 RSS 提要的替代而开发的。Atom 似乎比 RSS 更先进,但是我不会在这篇文章中比较这两种格式。
RSS XML 的一个例子:
<?xml version="1.0" encoding="UTF-8" ?>
**<rss** version="2.0"**>**
**<channel>**
**<title>**RSS Title**</title>**
**<description>**This is an example of an RSS feed**</description>**
**<link>**http://www.example.com/main.html**</link>**
**<lastBuildDate>**Mon, 06 Sep 2010 00:01:00 +0000 **</lastBuildDate>**
**<pubDate>**Sun, 06 Sep 2009 16:20:00 +0000**</pubDate>**
**<ttl>**1800**</ttl>** **<item>**
**<title>**Example entry**</title>**
**<description>**Here is some text containing an interesting description.**</description>**
**<link>**http://www.example.com/blog/post/1**</link>**
**<guid** isPermaLink="false"**>**7bd204c6-1655-4c27-aeee-53f933c5395f**</guid>**
**<pubDate>**Sun, 06 Sep 2009 16:20:00 +0000**</pubDate>**
**</item>****</channel>**
**</rss>**
通过 RSS 端点抓取新闻
所以,剩下的唯一事情就是收集我们感兴趣的新闻发布者的所有 URL(端点)。
对于本文,我采用纽约时报提要端点。为此,我不得不:
- 去看https://www.nytimes.com/
- “检查”页面的源代码
- 搜索“rss”术语
- 抓取第一个结果
纽约时报页面的源代码
让我们抓住那个链接,检查它是否像我们需要的东西。
https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml
好的,正如我们所看到的,这是“NYT>头条新闻” RSS。
在 <频道> 部分,您可能会找到关于提要本身的一般信息——描述、构建时间、语言等。
此 RSS 下的每个 <条目> 代表文章。第一个项目代表标题( < title > )称为 的文章“特朗普打赌他能孤立伊朗,迷倒朝鲜。没那么容易。”
如果我们拿这个 <项下的> 链接( <链接> )我们会被转发到一篇文章的原始页面:
https://www . nytimes . com/2020/01/01/us/politics/trump-Iran-north-Korea . html?emc=rss & partner=rss
RSS 不会给我们一篇文章的全文,但它会建议一个简短的 <描述> 来代替。
Feedparser
现在,当我们知道什么是 RSS 以及如何使用它时,我们可以尝试自动获取新文章。
RSS/Atom 提要的主要缺点是它们没有被规范化。根据维基百科页面,RSS/Atom 只有几个必填字段(链接、标题、描述)。
https://en.wikipedia.org/wiki/RSS
这意味着,如果您想存储来自不同新闻出版商的数据,您应该考虑所有可能的键-值对,或者使用一些无模式技术(例如,elasticsearch)。
探索 feedparser 包
pip install feedparser
import feedparser
feed = feedparser.parse('[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'))
现在我们的提要被加载到了feed
变量下。在.feed
属性下,我们可以找到关于提要元数据本身的主要信息。
**feed.feed**Out[171]:
{‘title’: ‘NYT > Top Stories’,
‘title_detail’: {‘type’: ‘text/plain’,
‘language’: None,
‘base’: ‘[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'),
‘value’: ‘NYT > Top Stories’},
‘links’: [{‘rel’: ‘alternate’,
‘type’: ‘text/html’,
‘href’: ‘[https://www.nytimes.com?emc=rss&partner=rss'](https://www.nytimes.com?emc=rss&partner=rss')},
{‘href’: ‘[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'),
‘rel’: ‘self’,
‘type’: ‘application/rss+xml’}],
‘link’: ‘[https://www.nytimes.com?emc=rss&partner=rss'](https://www.nytimes.com?emc=rss&partner=rss'),
‘subtitle’: ‘’,
‘subtitle_detail’: {‘type’: ‘text/html’,
‘language’: None,
‘base’: ‘[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'),
‘value’: ‘’},
‘language’: ‘en-us’,
‘rights’: ‘Copyright 2020 The New York Times Company’,
‘rights_detail’: {‘type’: ‘text/plain’,
‘language’: None,
‘base’: ‘[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'),
‘value’: ‘Copyright 2020 The New York Times Company’},
‘updated’: ‘Thu, 02 Jan 2020 15:03:52 +0000’,
‘updated_parsed’: time.struct_time(tm_year=2020, tm_mon=1, tm_mday=2, tm_hour=15, tm_min=3, tm_sec=52, tm_wday=3, tm_yday=2, tm_isdst=0),
‘published’: ‘Thu, 02 Jan 2020 15:03:52 +0000’,
‘published_parsed’: time.struct_time(tm_year=2020, tm_mon=1, tm_mday=2, tm_hour=15, tm_min=3, tm_sec=52, tm_wday=3, tm_yday=2, tm_isdst=0),
‘image’: {‘title’: ‘NYT > Top Stories’,
‘title_detail’: {‘type’: ‘text/plain’,
‘language’: None,
‘base’: ‘[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'),
‘value’: ‘NYT > Top Stories’},
‘href’: ‘[https://static01.nyt.com/images/misc/NYT_logo_rss_250x40.png'](https://static01.nyt.com/images/misc/NYT_logo_rss_250x40.png'),
‘links’: [{‘rel’: ‘alternate’,
‘type’: ‘text/html’,
‘href’: ‘[https://www.nytimes.com?emc=rss&partner=rss'](https://www.nytimes.com?emc=rss&partner=rss')}],
‘link’: ‘[https://www.nytimes.com?emc=rss&partner=rss'](https://www.nytimes.com?emc=rss&partner=rss')}}
最重要的字段是copyright
和published
。
Feedparser 会小心地为这些属性分配正确的值,这样您就不必浪费时间自己对它们进行规范化。
标准化文章
与提要一样,您可能会在.entries
属性下找到关于每篇文章的信息。
feed.entries[0].titleOut[5]: 'Trump Bet He Could Isolate Iran and Charm North Korea. It’s Not That Easy.'
这样,我们将知道提要中每个元素的基本信息。
如果你想要这篇文章的全文,你必须带着网址,使用报纸。检查一下我的另一篇文章,我已经把它嵌入了这篇文章的开头。
进一步的工作
试着想想如何构建一个数据管道来收集新文章,并对数据库中已经看到的文章进行重复数据删除。此外,在顶部增加一个 NLP 管道可能会带来很多有用的见解( spaCy python 包非常适合这一点)。
在我的个人博客中,我讲述了我如何构建新闻捕捉器——一个从最受欢迎的新闻出版商那里获取新闻数据的 API。如果你想知道如何将我上面描述的内容扩展成成千上万的内容,请关注我的媒体博客,并收听我的推特。
COVID 期间大学足球旅行的图表
原文:https://towardsdatascience.com/college-football-travel-during-covid-1ced0164840e?source=collection_archive---------48-----------------------
利用 NetworkX 对 2020 年大学足球赛程的网络分析及对大学足球艰难决策的思考
在 Unsplash 上 NeONBRAND 拍摄的照片
当圣母大学在 8 月 17 日暂停面对面学习时,这是对新冠肺炎阳性病例激增的回应。我质疑,如果校园对学生关闭,这一举措将如何影响足球活动的继续。令人欣慰的是,在回到现场学习后,圣母大学仪表盘上的数字显示阳性测试已经下降并保持稳定。然而,另一个集群的威胁仍然存在,特别是当班级和足球呈现出正常的味道。其他足球强国没有采取如此迅速的行动。例如,阿拉巴马大学塔斯卡卢萨分校(又名阿拉巴马)继续通过一个主要的集群进行个人学习。普遍获得系统发布了一份报告,对每周病例的下降有些乐观。这是一个好消息,希望这种趋势继续下去,然而,阿拉巴马州 6.1%的学生已经被检测为阳性。那太多了。对于学校的管理者来说,迫切的问题是多少阳性测试足以关闭校园?
阿拉巴马州(和其他州)将在秋季学期后转向远程教育
阿拉巴马州已经宣布允许 20%的主场足球比赛容量。超过 2 万人!!我相信许多学校无法证明在足球比赛上招待球迷是合理的,而学生被限制在校园内和远程学习。所以,学校会有两种选择;让球迷离开主场比赛,或者不管爆发的规模如何,坚持亲自学习。你认为学校管理者会喜欢哪一个?
足球的费用
大学橄榄球教练的费用随着收入的增加而增加。如果要求学生支付足球教练的薪水,那么在阿拉巴马,每个学生每年至少要支付 441.38 美元。该数字不包括与项目其他部分相关的成本,包括体育场维护、其他员工、差旅或奖学金成本。
[## 探索大学足球薪酬
按州和会议列出的每个学生的价格
medium.com](https://medium.com/swlh/exploring-college-football-salaries-dc472448684d)
足球是许多体育院系的生命线,作为校园体验的一部分,它吸引了许多学生。与 COVID 相关的成本也是一个严重的问题。虽然大学年龄人口的死亡率相对于一般人群来说较低,但 COVID 可能会产生严重的长期影响。大约 15%的患有冠状动脉疾病的大学生运动员患上了心脏病,这是一种潜在的长期健康疾病。有多少学生会出现类似的情况?
旅行的风险
我们知道高风险活动,如航空旅行和足球,会增加感染 COVID 的可能性。这个赛季有多少场联盟外和州外的比赛?本文使用 NetworkX 创建网络来找出答案。完整的 2020 赛季时间表可以使用下面的命令从 collegefootballdata.comAPI 下载:
curl -X GET “[https://api.collegefootballdata.com/games?year=2020&seasonType=regular](https://api.collegefootballdata.com/games?year=2020&seasonType=regular)" -H “accept: application/json”
本赛季 FBS 游戏总数为 413。参加 FBS 比赛的有 91 支队伍(包括部分 FCS 队伍)。为了构建网络,我们使用了 NetworkX 和 matplotlib。本赛季有 322 场会议赛对 91 场非会议赛。这个赛季谁在打非联盟赛?为了找到答案,我们过滤了会议游戏中的所有内容,然后创建了一个图形对象,并根据团队的会议应用了颜色。
边表示由会议着色的团队之间的游戏。图片作者。
在上面的网络中,FBS 独立队今年玩了最多的会议外游戏(这并不奇怪)。有趣的是,圣母大学仍然被归类为 FBS 独立,尽管打了 ACC 赛程,使南佛罗里达成为唯一的非大会比赛。
随着一些州成为感染热点,今年去其他州旅行可能会成为一个大问题。不同州的球队之间打多少场比赛?原来 86.2%或 356 场比赛需要一个团队跨越州界。我们过滤掉来自同一个州的球队之间的比赛,而不是创建一个图形对象,并根据球队的区域应用颜色。
优势表示位于两个不同州的球队之间的比赛。图片作者。
各州之间有很多旅行。哪个州跨州参赛的队伍最多?那就是佛罗里达,它正在打败德克萨斯,来自 16 个不同州的球队来到阳光之州进行足球比赛。所有的代码、数据和图表都可以在项目 GitHub 上找到。
结论
大学足球的前景是不确定的,球迷、学生和球员的涌入可能会在今年秋天成为 COVID 的热点。我希望在足球赛季结束后,许多目前亲自去的大学会去偏远地区或混合地区。提前去看这些比赛的成本意味着要把球迷从主场比赛中赶走。一些体育部门和学校管理人员根本不能失去足球收入来资助他们的教练人员的年薪,有些高达数千万美元。我相信 COVID 将导致许多运动员质疑业余模式,因为学校似乎将足球美元看得比学生健康更重要。这里希望这个季节能够继续下去,不要在团队或学生群体中爆发任何重大疫情。
附言:带回 NCAA 足球电子游戏!!!
我叫科迪·格利克曼,可以在 LinkedIn 上找到我。一定要看看我下面的其他文章:
[## 探索大学足球薪酬
按州和会议列出的每个学生的价格
medium.com](https://medium.com/swlh/exploring-college-football-salaries-dc472448684d) [## 一个幻想草案秩序彩票使用 R 闪亮
作为 web 应用程序编写的 NBA 风格的彩票系统
towardsdatascience.com](/a-fantasy-draft-order-lottery-using-r-shiny-6668a5b275d2) [## 刮胡子,还是不刮胡子,这是个问题
使用深度学习对有胡须和无胡须的照片进行年龄分类
towardsdatascience.com](/to-beard-or-not-to-beard-that-is-the-question-b46864d7e003)
大学排名不靠谱
原文:https://towardsdatascience.com/college-rankings-are-unreliable-8bc49e4fddd7?source=collection_archive---------36-----------------------
我们来看看数据。
瓦迪姆·谢尔巴科夫在 Unsplash 上拍摄的照片
大学排名没有兑现诱人的承诺。他们接受了决定在哪里学习或教学的丑陋的复杂性,并用一种客观性的幻觉来取代它们。
如果你像我一样,你会从数据中寻求清晰和指导。不幸的是,这些数据有时掩盖了对重大决策至关重要的细微差别。(谎言,可恶的谎言等。)
抛开上哪所大学是否重要的宏观问题不谈,我认为排名的主要来源是不可靠的。利用《泰晤士报高等教育》、《美国新闻》和 QS 的数据,我提出了三个论点:
- 排名不一致
- 排名是不相关因素的集合
- 排名不够
排名不一致
这就是大学排名不靠谱的最简单的原因。我从三个主要来源整理了全球十大大学的排名:
比较泰晤士高等教育、美国新闻和 QS 的 2020 年排名
排名之间的*均标准差为 7.1 。这一数字无疑因一些异常值而增加,如华盛顿大学,它勉强进入了美国新闻排名的前十名,但在美国和 QS 分别排名第 26 位和第 68 位。
六所大学在这三份榜单中都进入了前十名,但即使是这一组也显示出巨大的差异。例如,牛津大学是世界上最好的大学之一,但是在另外两个榜单中并没有进入前三名。
为了更加仁慈,我决定限制我的搜索范围。这三个来源都按学科提供全球大学排名。我选择了经济学的排名,尽管应该注意的是,它将该主题列在“经济学和商业”之下,这与《美国新闻》和 QS 的“经济学和计量经济学”的分类略有不同。
2020 年经济学排名对比
特定经济学排名的*均标准偏差为 3.5 ,约为未指定主题时标准偏差的一半。这似乎表明,在顶尖大学中,当受学科限制时,排名更加一致。
当然,如果受到个人因素的限制,如引用或教学声誉,他们也会更加一致。进一步缩小我的搜索标准将会偏离对大学排名的关注,因为它们通常被认为是(也因为它们出现在新闻中)。
我能想到两个反对以这种方式交叉比较排名的理由:
- 就数量级而言,大学排名仍然是可靠的——排名第 1、#10、#100 和#1000 的大学之间有明显的区别。
- 每份榜单使用不同的标准对大学进行排名,因此结果大相径庭也就不足为奇了。
我同意第一种反对意见。第二个问题揭示了一个更大的问题:
排名是不相关因素的集合
总体排名中使用的大多数标准都是不相关的。需要明确的是,师生比、研究生产率和引用率(都被使用)等维度是大学总分的合理组成部分。然而,任何给定的利益相关者都不应该关心考虑的大多数因素。
例如,学生不会因为他们的教授被大量引用而明显受益。至少,引用不值得占总分数的 30%,因为它们在列表中。也就是说,它的目标是比《美国新闻》更能代表教学质量,后者完全专注于研究成果。
另一方面,学者可能对薪水、职场文化和福利感兴趣。这些类别都没有直接包含在我检查过的列表中。
有人可能会说,排名是衡量一所大学声誉的标准。有趣的是,它包括一项声誉调查,衡量“教学机构的感知声望”,作为其总分的一部分。这意味着他们的“教学”类别本身并不是教学声誉的衡量标准。
这一观点也与排名的交叉比较相矛盾。加州理工学院在非特定学科排行榜上一直排在耶鲁之上,然而人们很难认为耶鲁是这两所大学中更不出名的一所。
这并不是说考虑的所有因素都是合理和重要的。美国和 QS 都将国际学生的比例作为排名的一部分。我明白了为什么拥有一个多元化的学生群体可以提升学生体验,或者表明一个模范的全球声誉。然而,如果不考虑国际学生在某个大学学习的原因,把这个因素包括进去似乎是有问题的。
例如,迪拜的美国大学(排名第 600-650 位)和 T2 的伦敦经济学院(排名第 49 位)吸引了许多海外学生,这可能有不同的原因。在 QS 世界排名中,这两所大学的国际学生比例都是 100 分。
照片由乔舒亚·戈德在 Unsplash 拍摄
我最*听到一句话,“垃圾进,垃圾出”适用于机器学习模型。这在这里同样相关。如果指标本身一开始就有缺陷,那么仔细组合几十个指标不会让大学排名更可靠。
排名不够
等等,什么?
首先,我要说的是,更多的全球大学排名出版物并不一定会增加可信度。然而,目前排名数量太少,无法对每个大学形成准确的看法。
让我们假设每一份名单都像同行评议研究一样严谨。即使在这种情况下,少数具有矛盾结果的研究也没有给我们提供多少新知识。在将研究结果用于决策之前,通常建议等待形成某种程度的共识;我不明白为什么我们要在这种情况下破例。
除了大量的数据,更集中的分析是必要的。比如哪些大学导致毕业生工资涨幅最高?校园文化哪里更有利于心理健康?在一个给定的机构中,不同系之间的教学质量如何不同?
这些问题没有一个有助于产生全面的分数,但它们最终会对学生、教师和私营部门组织产生影响。这些问题也可以由负责编制大学排名的研究人员来回答。
是时候离开年度新闻周期了,在这一周期中,我们浏览大学排名,就好像它们是体育排行榜一样。在那些给许多雄心勃勃的学生提供过度安慰的组织有序的清单下面,有一个相关的和必要的故事要讲述。
共线性度量
原文:https://towardsdatascience.com/collinearity-measures-6543d8597a2e?source=collection_archive---------22-----------------------
减轻线性回归模型多重共线性的度量和方法
特征选择是选择对目标变量的预测/分类贡献最大的预测变量的过程。在线性回归模型的特征选择中,我们关注与变量有关的四个方面。作为助记“线”,这些是:
- 不*等。所选变量与目标变量具有线性关系。
- I 预测变量的不依赖性。所选变量相互独立。
- 常态。残差通常遵循正态分布(*均值为零)。
- E 方差质量。残差在预测变量的值之间通常是一致的(即,同方差)。
如果选定的预测变量不是相互独立的,我们将无法确定或归因于各种预测变量对目标变量的贡献——模型系数的可解释性成为一个问题。
特征选择的一种方法是通过使用 p 值;其中 p 值高于某个阈值(通常为+/- 0.05)的变量表现为对目标变量没有显著贡献,因此可以删除以降低模型复杂性。然而,当预测变量之间存在多重共线性时,这种方法具有挑战性,正如 sklearn 中的波士顿住房数据集所示。
# Original (full) set of variables
X_o = df_wdummy[['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'CHAS_1.0']]
X_o = sm.add_constant(X_o)
y_o = df_wdummy['MEDV']
# Baseline results
model_o = sm.OLS(y_o, X_o)
results_o = model_o.fit()
results_o.summary()
OLS 回归结果 1,注意 0.05 以上的 p 值(图片由作者提供)
基于 p 值,我们移除变量 INDUS 和 AGE,并检查更新的 p 值。
# Remove Age -> Remove INDUS, based on p-values.
X_r0 = df_wdummy[['CRIM', 'ZN', 'NOX', 'RM', 'DIS', 'RAD', 'TAX',
'PTRATIO', 'B', 'LSTAT', 'CHAS_1.0']]
X_r0 = sm.add_constant(X_r0)
y_r0 = df_wdummy['MEDV']
# results
model_r0 = sm.OLS(y_r0, X_r0)
results_r0 = model_r0.fit()
results_r0.summary()
更新的 OLS 回归结果;请注意,p 值均不超过 0.05(图片由作者提供)
尽管所有 p 值都低于 0.05,但多重共线性仍然存在(在 TAX 和 RAD 变量之间)。)多重共线性的存在可能会掩盖各变量对目标变量的贡献的重要性,从而使 p 值的可解释性变得具有挑战性。我们可以使用相关性度量和矩阵来帮助可视化和减轻多重共线性。这种方法是好的,直到我们需要使用不同的相关措施(即 Spearman,Pearson,Kendall)由于变量的固有属性。在上面的例子中,变量 RAD(放射状公路可达性指数)是一个顺序变量。税收(每 10,000 美元的全价值财产税税率)是一个连续变量(非正态分布)。使用不同的相关性度量和矩阵,人们可能会忽略不同类别变量之间的相关性。
另一种识别多重共线性的方法是通过方差膨胀因子。VIF表示每个变量系数的方差膨胀百分比。从值 1(无共线性)开始,介于 1-5 之间的 VIF 表示中度共线性,而大于 5 的值表示高度共线性。在某些情况下,高 VIF 是可以接受的,包括使用相互作用项、多项式项或虚拟变量(具有三个或更多类别的标称变量)。相关矩阵能够识别变量对之间的相关性,而 VIF 能够全面评估多重共线性。大多数连续变量的相关矩阵如下所示,以突出各种共线变量对。可以使用 statsmodels 软件包计算 VIF;下面的代码块显示了包含(左)和移除(右)共线变量的 VIF 值。
连续变量的相关矩阵;肯德尔系数(图片由作者提供)
# Setting the predictor variables
X_o = df_wdummy[['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'CHAS_1.0']]
X_r1 = df_wdummy[['CRIM', 'ZN', 'INDUS', 'RM', 'AGE', 'DIS', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'CHAS_1.0']]#
from statsmodels.stats.outliers_influence import variance_inflation_factorvif = pd.Series([variance_inflation_factor(X_o.values, i) for i in range(X_o.shape[1])], index=X_o.columns,
name='vif_full')
vif_r = pd.Series([variance_inflation_factor(X_r1.values, i) for i in range(X_r1.shape[1])], index=X_r1.columns,
name='vif_collinear_rvmd')
pd.concat([vif, vif_r], axis=1)
预测变量的 VIF 值(图片由作者提供)
VIF 值对应于相关矩阵;例如,可变对 NOX 和 INDUS,相关系数在 0.5 (0.61)以上,各自的 VIF 值在 5 以上。共线变量 RAD 和 NOX 的去除改善了 VIF 图。仅仅根据最高的 VIF 数删除共线变量并不能保证构建出性能最佳的模型,这将在下一节中详述。
我们通过删除相关矩阵(如上所示)中确定的所有共线变量来构建基线模型,下一步将删除待定税和 RAD。
# Baseline variables
X_bl = df_wdummy[['INDUS', 'RM', 'AGE', 'RAD', 'TAX', 'PTRATIO', 'LSTAT']]
y_bl = df_wdummy['MEDV']# Explore mitigating multi-collinearity
vif_bl = pd.Series([variance_inflation_factor(X_bl.values, i) for i in range(X_bl.shape[1])], index=X_bl.columns,
name='vif_bl')X_noTAX = X_bl.drop(['TAX'],axis=1)
X_noRAD = X_bl.drop(['RAD'],axis=1)
vif_noTAX = pd.Series([variance_inflation_factor(X_noTAX.values, i) for i in range(X_noTAX.shape[1])],
index=X_noTAX.columns, name='vif_noTAX')
vif_noRAD = pd.Series([variance_inflation_factor(X_noRAD.values, i) for i in range(X_noRAD.shape[1])],
index=X_noRAD.columns, name='vif_noRAD')
pd.concat([vif_bl, vif_noTAX, vif_noRAD], axis=1)
评估基线模型中预测变量的 VIF 图(图片由作者提供)
虽然基于 VIF 放弃税收变量似乎更好,但谨慎的方法是通过调整后的 R *方度量进行检查(根据预测因素的数量进行调整,只有当下一个添加的变量对模型的改善程度超过偶然的预期时,度量才会增加)。
# Without TAX
model = sm.OLS(y, sm.add_constant(X_noTAX)).fit()
print_model = model.summary()
print(print_model)
模型指标摘要(不含税)(图片由作者提供)
# Without RAD
model = sm.OLS(y, sm.add_constant(X_noRAD)).fit()
print_model = model.summary()
print(print_model)
模型指标摘要(无 RAD)(图片由作者提供)
从更高的调整后的 R *方数字,我们可以推断出模型在 RAD 变量被删除的情况下表现得更好!多重共线性问题解决后,下一步可能是探索增加交互项以潜在地提高模型性能。
总之,多重共线性的存在会掩盖预测变量对目标变量的重要性。相关矩阵和 VIF 的使用有助于识别相关变量对并评估所选变量(要素)之间的多重共线性。虽然仍然需要一些迭代来评估模型性能,但有了 VIF 和相关矩阵,我们将能够为特征选择做出更明智的决策。
代码托管在这里:https://github.com/AngShengJun/petProj/tree/master/eda_viz
参考资料:
- 相关方法 1https://data science . stack exchange . com/questions/64260/Pearson-vs-spearman-vs-Kendall
- 相关方法 2https://support . minitab . com/en-us/minitab-express/1/help-and-how-to/modeling-statistics/regression/supporting-topics/basics/a-comparison-of-the-the-Pearson-and-spearman-correlation-methods/
使用 NLTK 库的自然语言处理中的搭配
原文:https://towardsdatascience.com/collocations-in-nlp-using-nltk-library-2541002998db?source=collection_archive---------13-----------------------
一棵树的两根树枝美丽地并列在一起。来源:像素
搭配是包含多个单词的短语或表达,这些单词很可能同时出现。比如——‘社交媒体’、‘学校假期’、‘机器学习’、‘新加坡环球影城’等。
为什么需要搭配?
想象一下,有一个需求,您希望了解客户留下的文本评论。你想了解行为洞察,比如谁是你的顾客,有多少人光顾你的店,他们对什么感兴趣,他们买什么,他们参加什么活动,等等。
为了更简单,让我们假设你有一家餐馆,你有几千条评论。因此,如上所述,作为餐馆老板,你需要了解顾客的行为。
使用命名实体识别,我在人、事件、日期、产品类别中提取了某些有趣的实体。例如日期中的“星期六”。然后我想知道人们在“星期六”前后在他们的评论中写了什么!
因此,我缩小了几个广泛的主题,如“家庭”、“夫妇”、“假日”、“早午餐”等。搭配帮助我找到了两三个很有可能围绕这些主题同时出现的词。这两个或三个词一起出现,也被称为二元和三元。
搭配与常规的二元或三元组有何不同?
作为二元模型共现的两个单词的集合,以及作为三元模型共现的三个单词的集合,可能不会给我们有意义的短语。例如,句子“他应用了机器学习”包含二元词:“他应用了”、“应用了机器”、“机器学习”。“他应用”和“应用机器”没有任何意义,而“机器学习”是一个有意义的二元模型。仅仅考虑同现单词可能不是一个好主意,因为像‘of’这样的短语可能会频繁地同现,但实际上没有意义。因此,需要 NLTK 库中的搭配。它只给我们有意义的二元模型和三元模型。
一个搭配怎么比另一个好?
哦!所以你基本上想知道评分是如何进行的?嗯,我用了点态互信息或 PMI 分数。讨论什么是 PMI 以及它是如何计算的不是这篇博客的范围,但是这里有一些很棒的文章,你可以阅读来了解更多:第一条和第二条。我使用 PMI 分数来量化和排列搭配库产生的二元模型和三元模型。
如何实现搭配?
正如我前面提到的,我想知道人们围绕某些主题写些什么,比如一些特定的日期、事件或人物。因此,从我的代码中,你将能够看到特定单词周围的二元模型、三元模型。也就是说,我想知道除了我选择的“特定单词”之外,很可能形成的二元模型、三元模型。这个特定的词就是我们从命名实体识别中得到的主题。
import nltk
from nltk.collocations import *bigram_measures = nltk.collocations.BigramAssocMeasures()# Ngrams with 'creature' as a member
creature_filter = lambda *w: 'kids' not in w ## Bigrams
finder = BigramCollocationFinder.from_words(
filtered_sentences)
# only bigrams that appear 3+ times
finder.apply_freq_filter(3)
# only bigrams that contain 'creature'
finder.apply_ngram_filter(creature_filter)
# return the 10 n-grams with the highest PMI
# print (finder.nbest(bigram_measures.likelihood_ratio, 10))
for i in finder.score_ngrams(bigram_measures.likelihood_ratio):
print (i)
二元搭配代码的示例结果
结果显示,人们在评论中会写“儿童菜单”、“儿童跑步”、“儿童餐”。现在让我们看看“孩子”周围的三元组。
## Trigrams
trigram_measures = nltk.collocations.TrigramAssocMeasures()# Ngrams with 'creature' as a member
creature_filter = lambda *w: 'kids' not in w finder = TrigramCollocationFinder.from_words(
filtered_sentences)
# only trigrams that appear 3+ times
finder.apply_freq_filter(3)
# only trigrams that contain 'creature'
finder.apply_ngram_filter(creature_filter)
# return the 10 n-grams with the highest PMI
# print (finder.nbest(trigram_measures.likelihood_ratio, 10))
for i in finder.score_ngrams(trigram_measures.likelihood_ratio):
print (i)
三元组搭配代码的示例结果
代码输出让我们对上面挖掘的二元模型有了更深入的了解。因此,“儿童菜单可用”和“伟大的儿童菜单”是“儿童菜单”的延伸,这表明人们为有儿童菜单的餐厅鼓掌。同样,“孩子跑”与“孩子尖叫着跑”这一负面含义联系在一起。这意味着,当有孩子跑来跑去尖叫时,餐馆里的客人可能没有好好享受他们的时光。
这就结束了我对 NLTK 库提供的 NLP 中搭配应用的演示和解释。我希望这个博客对你有帮助。请让我知道你是否使用了不同的方法来评分或提取搭配。
感谢您的阅读,我也写过其他与软件工程和数据科学相关的帖子。你可能想看看这里的。您也可以订阅我的博客,直接在收件箱中接收相关博客。
数据可视化中的颜色:少一些“如何”,多一些“为什么”
原文:https://towardsdatascience.com/color-in-data-visualization-less-how-more-why-348514a3c4d8?source=collection_archive---------10-----------------------
太多时候,我们把颜色作为一种工具来制作漂亮的图片,而它应该被用来告诉我们的观众。
如果我们在可视化中使用颜色遵循五个 w(和一个 H) ,我们在如何上花了太多时间,而在为什么上花的时间不够。当色彩应该被用来传达给我们的观众时,它却常常被看作是一种制作精美图片的工具。
举个例子,看看这个来自营销网站的“色彩情感指南”点击(当你在🧐).谷歌搜索“数据可视化中的色彩”时,这是最热门的结果之一
这里隐含的建议是我们应该使用颜色——无论何时何地——来捕捉某种形式的情感。不仅这种特定的分类相当奇怪(怪物能量饮料是和*的,维珍移动体现了“大胆的兴奋”,哈雷戴维森摩托车只是喊着“愉快的友好”)🤩),导致新手从业者认为,应该只是为了用色而用色。
无端使用颜色的例子比比皆是。
这些例子说明了我的论点:当我们应该问为什么我们使用颜色的时候,我们经常问我们如何在我们的可视化中使用颜色。
1)默认的软件设置,2)对漂亮的调色板的痴迷,以及 3)缺乏对仔细的颜色考虑的重视,这些因素的结合导致了我们在一些最流行的数据可视化中对颜色的草率使用。
我看到的最常见的错误之一是过度使用颜色。例如,在上面的图表中,很明显有太多的颜色,没有明显的原因
很多时候,那些创建可视化的人会争辩说他们必须在他们的图表中包含 14 种颜色,因为数据集有 14 个数据点!一些最流行的数据 viz 工具(如 Excel)的默认设置是将分类变量映射到颜色,这并没有帮助。
然而,实际情况是,如果您的图表中需要多种颜色,您可能会以不同的方式呈现数据。从 Datawrapper 中取出这个例子:
外卖?当你强调一切时,你最终会什么都不强调。这就是为什么我们停止不加批判地问如何在图表中使用颜色是很重要的。
如果不能告知查看者,数据可视化只不过是一幅美丽的图画。如果你的图表显示了 14 个不同的数据点,它们都被映射成不同的颜色,那么它在讲述什么样的故事呢?我非常喜欢苹果数据可视化从业者 Elijah Meeks 的这句话:
当你有如此多的维度时,不要试图找到不可能的 20 色调色板,停止使用颜色。这是难以区分的,令人困惑的,你只是把复杂性和决策权交给了你的读者。
这就是为什么颜色应该更少地使用和更周到地使用。颜色是我们视觉化的最重要的部分之一,然而它们目前的使用太多时候是不必要的和压倒性的。**
那么,你应该如何运用色彩呢?
颜色不是敌人。更确切地说,对颜色的滥用和误用才是。那么,如何才能正确使用色彩呢?这取决于你视觉化的目的,作为推论,也取决于颜色的目的。你应该问:我为什么要用颜色?****
1)颜色区分
颜色的一个用途是引起人们对感兴趣的数据点的注意。这种颜色的使用属于解释性可视化的范畴,与其探索性的对应物相反。如果您已经探索、分析和探查了您的数据,现在您需要将这些见解传递给其他人(主管、客户或好奇的朋友)。向他们展示你所做的所有探索性工作是浪费时间,这就是为什么你的展示应该利用颜色来突出你的发现。
正如实践者安迪·基尔克所说,在这个展示阶段的可视化实践者应该让格雷成为他们最好的朋友。这是因为没有色彩,而不是过度使用色彩,有助于描绘一幅图画和讲述一个故事。通过在可视化中使用灰色作为主要颜色,我们自动地将我们的观众的眼睛吸引到任何不是灰色的地方。这样,如果我们有兴趣讲述一个关于一个数据点的故事,我们可以很容易地做到。
这是我不久前在 R 做的一个简单的例子:
可视化的目的不是向我们的观众展示德克萨斯州每个县的幼儿园疫苗接种率。取而代之的是强调最低比率——特里县。这种可视化利用每隔一个酒吧的灰色填充,立即将观众的目光吸引到特里县。因为我们只使用了两种颜色,所以我们还可以突出字幕中的文本,让观众看起来更加清晰。颜色——如果谨慎使用的话——会让我们的视觉效果更容易理解,信息量更大。
现在,想象一下,如果我用下面的方式可视化同样的数据:
或者更糟的是:
看了那些碍眼的东西,你是不是很庆幸我们在最初的剧情中有节制地使用了色彩?
或许你对 2016 年各县选举结果的概览感兴趣。尽管你可能会忍不住根据特朗普/克林顿的分歧给所有县编码,但这比有见地更美好。相反,如果我们专注于那些在 2012 年至 2016 年间从一个政党转向另一个政党的著名县,会怎么样?摘自基兰·希利的书数据可视化:
正如我们在这里看到的,更多的县从 2012 年的多数民主党转向 2016 年的多数共和党。因为我们只关注所有数据点的一小部分,我们也可以观察到趋势:大多数翻转的县都有少量的黑人人口。没有一个县的黑人人口超过 53%(我自己的注释):
我们还注意到,翻转方向可能与人口规模相关:几乎所有对数人口低于 10 万的翻转县都转向了共和党,而如果对数人口超过 10 万,则所有翻转县中更大比例的人转向了民主党。
颜色可以,也应该被用来关注你的视觉效果中你想让你的观众看到的关键部分。通过有策略地使用颜色,我们可以减少理解可视化所描绘的内容所需的认知负荷。 Kalyuga 等人发现颜色编码“改善了注意力分散效应,从而降低了感知难度。”其他研究人员报告称,当给实验参与者提供颜色编码时,认知负荷会降低。
过度使用颜色会产生相反的效果。在 2019 年的一篇论文中,研究人员发现“与任务无关的数字颜色信息只会在触发与基本代码单词的语义属性冲突的情况下阻碍学习过程。”这是什么意思?如果颜色编码与它所代表的对象相冲突,就会阻碍学习,削弱理解。你不必理解这一切意味着什么(我并不完全理解)。这一点简单来说明:我们应该关心颜色。颜色可能会令人困惑和复杂,这就是为什么它的使用应该是有意的和最小的。它应该被用来引起对我们图表中重要部分的注意。
2)色彩探索
颜色不一定要和普通的灰色形成对比。它还可以用作一种工具来展示映射到不同颜色的各种数据点。重要的是,这种用法应该节省。鉴于我们之前的例子,我们肯定不想要这样的情节(来自 Claus Wilke 的数据可视化基础 的第 19 章):
一个更合适的替代方案可能是这样的:
这样,观众仍然可以看到数据中的一般模式,但他们不必像对待查找表一样对待填充图例!最理想的情况是,这个图表应该具有一定的交互性,这样用户就可以将鼠标悬停在某个点上来查看其相应的数据。
在这样的例子中,我们是在探索而不是解释,我们把探索留给了我们的用户;他们可以看到他们想看的东西,我们给他们所需的信息。
颜色的另一个常见用途是显示梯度上的数据级数(例如,从低到高、从差到好、从冷到暖)。
这些例子在 choropleth 地图中最常见,其中给定州(或县或地区)的颜色阴影对应于感兴趣的值。作为一个例子,这里有一个我用 D3.js 创建的 choropleth 地图,它可视化了美国阿片类药物过量死亡的情况:
从地图上我们可以看出,“铁锈地带”各州遭受阿片类药物危机的程度比西方各州要大得多。Choropleth 地图利用颜色显示地区差异,并说明颜色阴影的力量,以代表给定变量的严重性或范围。
然而,在这种情况下,颜色也可能被误用。可以根据分类色标或彩虹色标绘制数据,这使得很难看到进展。Claus O. Wilke 的图表是一个好(坏)的例子:
这张图表很漂亮!当彩虹秤被用于媒体或其他地方时,可能是因为它们的创造者问“我如何才能用颜色来制作一幅漂亮的画?”但是这种非单调色标的使用意味着难以检测数据点之间差异的相对大小。举个例子,看看你回答这个问题需要多长时间:用上面的图例,这个颜色和这个颜色的百分比差是多少?(答案是~70%。)
2019 年,一组研究人员要求气候科学家评估描绘气候变化的地图,其中地图要么是彩虹状的(类似于上面的得克萨斯州地图),要么是单调的(如早先的阿片类地图)。研究人员发现,当这些地图用单调亮度标度而不是传统的彩虹标度编码时,对这些地图中量值差异的评估明显更准确。其他研究一致发现彩虹色既有害又受欢迎。所有这些都是为了说明:颜色很重要。
所以,颜色可以用于探索的目的。也就是说,颜色不一定要专门用于焦点,它可以用在除了灰色以外的其他颜色的图表中!但是探索性的颜色使用(和所有的颜色使用一样)需要谨慎。
结论
颜色很棘手。虽然它可以让你的情节更上一层楼,但也可能毁了它。区别?我们问的问题。我们是否在质疑你如何运用色彩;使用众多调色板中的哪一个,以及我们如何在变量间映射它们?这些都是重要的问题,但是它们必须以为什么我们首先使用颜色这个问题为前提。如果颜色不能起到告知、澄清或引导观众的作用,它还有什么作用呢?
https://twitter.com/CL_Rothschild
原载于 我的博客 。
使用 BodyPix 和 TensorFlow.js 的颜色流行效果
原文:https://towardsdatascience.com/color-pop-effect-using-bodypix-and-tensorflow-js-a584ddc48a02?source=collection_archive---------18-----------------------
在 Unsplash 上发现的女孩照片
O 谷歌照片应用程序中我最喜欢的小功能之一是它的彩色流行效果。颜色流行(也称为颜色飞溅)效果使主体(通常是人)从图像的其余部分中突出出来。主体保持彩色,但背景变成灰度。在大多数情况下,这给人一种愉快的感觉。
彩色流行效果示例。原稿左侧,彩色弹出右侧
虽然这项功能非常好用,但 Google 相册只将这种效果应用于一些它认为容易检测到人类的图像。这限制了它的潜力,并且不允许用户手动选择图像来应用这种效果。这让我思考,有没有什么方法可以达到类似于的效果,但是用我选择的图片?
大多数应用程序不提供自动化解决方案。它需要用户手动在他们的图像上绘制这种效果,这既耗时又容易出错。我们能做得更好吗?像 Google 相册这样的智能东西?是啊!😉
了解了如何手动实现这种效果,我发现以下两个主要步骤:
- 在图像中的人物周围创建一个遮罩(也称为分段)。
- 使用遮罩保留人物的颜色,同时使背景灰度化。
从图像中分割出人
这是这个过程中最重要的一步。一个好的结果很大程度上取决于分割掩模创建得有多好。这一步需要一些机器学习,因为它已经被证明在这些情况下工作良好。
从零开始建立和训练一个机器学习模型会花费太多时间(不了解 ML 的人说😛),所以我搜索了一下有没有预先训练好的模型可以用。快速搜索将我带到了 BodyPix ,这是一个 Tensorflow.js 模型,用于人物分割和姿势检测。
[## Tensorflow.js 的 BodyPix 模型
这个包包含一个名为 BodyPix 的独立模型,以及一些演示,用于运行实时人和身体…
github.com](https://github.com/tensorflow/tfjs-models/tree/master/body-pix)
创作者提供的 BodyPix 现场演示。在这里尝试一下
正如你所看到的,它在检测图像中的一个人(包括多人)方面做得很好,并且在浏览器上运行相对较快。彩虹色的区域就是我们需要的分割图。🌈
让我们用 Tensorflow.js 和 BodyPix CDN 脚本建立一个基本的 HTML 文件。
<html>
<head>
<title>Color Pop using Tensorflow.js and BodyPix</title>
</head>
<body>
<!-- Canvas for input and output -->
<canvas></canvas>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.2"></script>
<!-- Load BodyPix -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/body-pix@2.0"></script>
<!-- Color Pop code-->
<script src="colorpop.js"></script>
</body>
</html>
在画布中载入图像
在分割之前,理解如何在 JavaScript 中操作图像的像素数据是很重要的。一个简单的方法是使用 HTML Canvas。Canvas 使得读取和操作图像的像素数据变得很容易。还兼容 BodyPix,双赢!
function loadImage(src) {
const img = new Image();
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
// Load the image on canvas
img.addEventListener('load', () => {
// Set canvas width, height same as image
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// TODO: Implement pop()
pop();
});
img.src = src;
}
正在加载 BodyPix 模型
BodyPix 的 README 很好地解释了如何使用该模型。加载模型的一个重要部分是您使用的architecture
。ResNet 更准确,但速度较慢,而 MobileNet 不太准确,但速度较快。在构建和测试这个效果时,我将使用 MobileNet。稍后我将切换到 ResNet 并比较结果。
注意:最好加载一次模型,并多次重复使用它进行分段,因为每次加载模型时都必须下载架构。在下面的例子中,每次对图像应用颜色弹出效果时,都会加载模型(以保持主要功能清晰)。
async function pop() {
// Loading the model
const net = await bodyPix.load({
architecture: 'MobileNetV1',
outputStride: 16,
multiplier: 0.75,
quantBytes: 2
});
}
执行分段👥
BodyPix 具有多种功能来分割图像。一些适合于身体部分分割,而另一些适合于单人/多人分割。所有这些都在他们的自述文件中有详细解释。segmentPerson()
将在这种情况下工作,因为它在一个单独的地图中为图像中的每个人创建一个分割地图。此外,它比其他方法相对更快。
segmentPerson()
接受一个画布元素作为输入图像,以及一些配置设置。internalResolution
设置指定分割前输入图像尺寸调整的因子。我将使用full
进行设置,因为我想要清晰的分割图。我强烈建议你阅读一下其他的设置,并尝试一下。
async function pop() {
// Loading the model
const net = await bodyPix.load({
architecture: 'MobileNetV1',
outputStride: 16,
multiplier: 0.75,
quantBytes: 2
});
// Segmentation
const canvas = document.querySelector('canvas');
const { data:map } = await net.segmentPerson(canvas, {
internalResolution: 'full',
});
}
分割后的结果就是一个物体(如下图)。结果对象的主要部分是data
,它是一个将分割图表示为一个数字数组的Uint8Array
。我已经用 ES6 析构把data
拿出来当map
。这将用于应用颜色流行到图像!
{
width: 640,
height: 480,
data: Uint8Array(307200) [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, …],
allPoses: [{"score": 0.4, "keypoints": […]}, …]
}
制作背景灰度
准备好分割数据后,下一部分涉及使用分割图实现颜色弹出,以使背景灰度化并保留图像中人物的颜色。为此,需要对图像进行像素级的操作,这也是 canvas 元素大放异彩的地方。getImageData()
函数返回ImageData
,其中包含 RGBA 格式的每个像素的颜色。在下面的代码中,我使用了析构来提取有用的data
作为imgData
async function pop() {
// ... previous code
// Extracting image data
const ctx = canvas.getContext('2d');
const { data:imgData } = ctx.getImageData(0, 0, canvas.width, canvas.height);
}
应用效果
所有的材料都准备好了,这就是色彩流行魔法发生的地方!让我们从创建新的图像数据开始。createImageData()
创建一个新的图像数据,我们对实际图像数据的所有修改都将存储在这里。
接下来,我们遍历地图中的像素,其中每个元素都是 1 或 0。
- 1 表示在该像素处检测到人。
- 0 表示在该像素处没有检测到人。
为了提高代码的可读性,我使用析构将颜色数据提取到r
g
b
a
变量中。然后使用 RGB 值,使用亮度方法计算适当的灰色。有各种方法来计算灰度值。这篇文章有一个很好的列表,列出了其中的一些转换公式。
最后,基于分割图值(0 或 1 ),可以将灰度或实际的 RGBA 颜色分配给新的图像数据。请注意,RGB 中对应的灰色是通过为所有三个通道分配相同的灰度值来计算的。
处理完每个像素后,使用putImageData()
功能在画布上绘制新的图像数据。
async function pop() {
// ... previous code
// Creating new image data
const newImg = ctx.createImageData(canvas.width, canvas.height);
const newImgData = newImg.data;
// Apply the effect
for(let i=0; i<map.length; i++) {
// Extract data into r, g, b, a from imgData
const [r, g, b, a] = [
imgData[i*4],
imgData[i*4+1],
imgData[i*4+2],
imgData[i*4+3]
];
// Calculate the gray color
const gray = ((0.3 * r) + (0.59 * g) + (0.11 * b));
// Set new RGB color to gray if map value is not 1
// for the current pixel in iteration
[
newImgData[i*4],
newImgData[i*4+1],
newImgData[i*4+2],
newImgData[i*4+3]
] = !map[i] ? [gray, gray, gray, 255] : [r, g, b, a];
}
// Draw the new image back to canvas
ctx.putImageData(newImg, 0, 0);
}
可以看到具有彩色 pop 效果的最终图像应用于原始图像。耶!🎉
探索其他架构和设置
我对 ResNet 和 MobileNet 架构进行了一些测试。在所有示例图像中,图像的一个维度(宽度或高度)的大小为 1080px。请注意,分割的内部分辨率被设置为full
(分割期间图像不缩小)。
对于我的测试,我在加载 BodyPix 模型时使用了以下设置。
// MobileNet architecture
const net = await bodyPix.load({
architecture: 'MobileNetV1',
outputStride: 16,
quantBytes: 4,
});
// ResNet architecture
const net = await bodyPix.load({
architecture: 'ResNet50',
outputStride: 16,
quantBytes: 2,
});
测试 1 —单人
这里两个模特都发现了照片中的女孩。与 MobileNet 相比,ResNet 更好地分割了该图像。
从左至右:原始样本、MobileNet、ResNet
测试 2 —多人
这是一个有点棘手的问题,因为它有许多人在图像周围摆着不同的姿势和道具。ResNet 再次准确地分割了图像中的所有人。MobileNet 也很接*,但错过了一些边缘。
两者都错误地分割了坐垫的一部分。
从左至右:原始样本、MobileNet、ResNet
测试 3 —面朝后
另一个棘手的问题是,照片中的女孩面朝后。老实说,我期待着对图像中女孩的不准确检测,但 ResNet 和 MobileNet 在这方面都没有问题。由于 dupatta,两种架构中的分段都不准确。
从左至右:原始样本、MobileNet、ResNet
测试的结论是📋
从测试中可以明显看出,ResNet 比 MobileNet 执行更好的分段,但代价是更高的时间。两者都很好地检测了同一幅图像中的多人,但有时由于服装的原因无法准确分割。由于 BodyPix 打算在浏览器(或 Node.js) 中与 Tensorflow.js 一起运行,所以当使用正确的设置时,它的执行速度令人印象深刻。
这就是我如何能够创造受谷歌照片启发的彩色流行效果。总而言之,BodyPix 是一个很棒的人物细分模型。我很想在我未来的一些项目中使用这个和 Tensorflow.js。你可以在这里找到源代码和现场工作版本:https://glitch.com/~color-pop-effect
我已经为这个颜色的流行效果创建了一个 Firebase 云函数。它在 Node 上使用 Tensorflow.js,这使得它比在用户的浏览器上运行要快得多。您可以检查颜色弹出🌈在这里投影。我迫不及待地想看到你的❤️和对它的贡献!
使用克雷奥拉颜色为图像着色(Python)
原文:https://towardsdatascience.com/coloring-an-image-using-crayola-colors-python-31ca1c7edb9d?source=collection_archive---------50-----------------------
我如何使用 cython 和 OpenCV 编写了一个 python 代码来将图像转换为好像它们是使用 Crayola 颜色着色的。
作者图片
创建一个颜色数组。首先,我为一个 120 色蜡笔蜡笔盒选择相应的 RGB 值,并将它们复制到一个列表中。
colorsFile = open("colors.txt","r")
colors = []for line in colorsFile.readlines():
colorset = line.strip().split(" ")
rgbFormat = [int(x) for x in colorset[2].split(",")]
colors.append(rgbFormat)
其次,我从挑选一张图片并把它调整到较小的尺寸开始。这主要是为了减少运行时间。此外,我注意到较小的图片似乎更好地带出预期的效果。
import cv2
import os
for imageFile in os.listdir("TestImages"):
img_rgb = cv2.imread("TestImages/" + imageFile)
img_rgb = cv2.resize(img_rgb, (0, 0), fx = 0.7, fy = 0.7)
原始图像(作者)
接下来,我运行了一个双边滤波器,它*滑了图像,但保留了边缘。边缘是很重要的,因为大多数蜡笔画都有强烈的、非常真实的、轮廓分明的边缘。OpenCV 中的双边滤镜由两个主要因素控制,sigmaColor(值越高,混合的远距离颜色越多)和 sigmaSpace(值越高,混合的远距离像素越多)。
#alpha = 6 Repeatedly running the filter with small values brought better results than a single run with a larger filter
for _ in range(alpha):
img_rgb_smooth = cv2.bilateralFilter(img_rgb, d=9, sigmaColor=9, sigmaSpace=7)
运行双边过滤器后
运行双边过滤器后,我识别了图像中的边缘。首先,我将图像转换成灰度。主要是因为我们将使用自适应阈值方法来识别边缘,这种方法只适用于灰度。我们基本上是在制作一个二进制图像,其中每个像素不是黑就是白。为创建这个二进制图像设置一个单一的阈值会遇到麻烦,比如图像上的光照不均匀。因此,最好是使用局部阈值,这将带来更好的结果。根据图像调整块大小会产生更好的结果。
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY)
img_edge = cv2.adaptiveThreshold(img_gray, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY,
blockSize=11,
C=2)
边缘提取
然后,我把固体边缘放回我们的图像上。我们可以使用逐位 and 算术运算符,对带有边缘的图像和 RGB 图像进行逐像素运算。
img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2RGB)
img_rgb_edges = cv2.bitwise_and(img_rgb, img_edge)
叠加边缘
然后我用调色板中最接*的颜色替换了每个像素的颜色。我花了很长时间才把它做好,这很容易成为本模块的核心步骤。我首先使用了当前颜色和调色板中每种颜色之间的纯欧几里德距离。输出不像我希望的那样真实。它通常会显示出与预期颜色的显著偏差。使用这里提供的堆栈溢出解决方案缓解了这个问题,它用我们感知颜色的灵敏度来增强公式。其他的建议是基于色调距离,然而,我觉得它并没有比欧几里得更好的表现。所以最初,我用 python 写了一个 for 循环来操作每个像素。
for x in range(0,width):
for y in range(0,height):
channels_xy = img_rgb_edges[y,x]
colorSwapping(x,y,channels_xy)def colorSwapping(x,y,rgbArray):
r1,g1,b1 = rgbArray
shortestDistance = None
sol = None
for color,value in colors.items():
r2,g2,b2 = value
d = pow(((r2-r1)*0.30),2) + pow(((g2-g1)*0.59),2) + pow(((b2-b1)*0.11),2)
if(shortestDistance == None or d < shortestDistance):
shortestDistance = d
sol = value
img_rgb_edges[y,x] = sol
然而这真的很慢,然后我尝试使用线程。那也没多大帮助。Python 有一个叫做的全局解释器锁,它不允许在一个数组上并发运行。经过进一步的搜索,我发现 cython 可以帮助大大加快这个过程。在我的例子中,将像素操作逻辑转移到 cython 有助于将速度提高 20 倍。
import cythoncode
img_rgb_edges = cythoncode.coloringImage(img_rgb_edges, colors)
cv2.imwrite("Output/"+imageFile ,img_rgb_edges)
cython 功能,
#cythoncode.pyx
cpdef coloringImage(img,colors):
cdef int height = img.shape[0]
cdef int width = img.shape[1]
for x in range(0,width):
for y in range(0,height):
pixelSwap(img,x,y, colors)
return img
cpdef pixelSwap(img,x,y,colors):
channels_xy = img[y,x]
cdef int shortestDistance = -1
sol = []
cdef length = len(colors)
for index in range(0,length):
d = distanceCalculator(channels_xy,colors[index])
if(shortestDistance == -1 or d < shortestDistance):
shortestDistance = d
sol = colors[index]
img[y,x] = solcpdef int distanceCalculator(color1, color2):
cdef int r2 = color1[0]
cdef int g2 = color1[1]
cdef int b2 = color1[2]
cdef int r1 = color2[0]
cdef int g1 = color2[1]
cdef int b1 = color2[2]
return int(((r2-r1)*0.30)**2 + ((g2-g1)*0.59)**2 + ((b2-b1)*0.11)**2)
Cython 就像 Python 的一个超集,具有来自 c 的函数。由于我对 cython 相对陌生,所以我只将简单的组件(如距离计算器)转移到 cython,这纯粹是计算。将 python 图像对象转换成数组可能有助于进一步提高速度。
Setup.py 构建模块,
from setuptools import setup
from Cython.Build import cythonize
setup(
name='Cython Pixel Manipualtion Code',
ext_modules=cythonize("cythoncode.pyx"),
zip_safe=False,
)
切换到最接*的克雷奥拉颜色
如你所见,最合适的颜色并不总是在图像中挑选。但是,仍然产生了相当好的卡通化效果。
这是我运行代码的更多图片,
在 Pixel 3 上拍摄多张照片,然后使用代码进行转换
将印度染成红色、橙色和绿色:Covid19 Chloropleth 地图
原文:https://towardsdatascience.com/coloring-india-red-orange-and-green-covid19-choropleth-map-fc21a00f005f?source=collection_archive---------33-----------------------
基于 Bokeh 的绘图/地图,显示印度不同地区的新型冠状病毒的实时数据和爆发严重程度
从 Freepik 创建的图像,请参见最后的致谢
注 : 走向数据科学 是以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
新冠肺炎或新型冠状病毒已使世界各国政府强制全国封锁,以对抗这种致命的病毒。这种病毒现在已经感染了全球 400 多万人,并导致 30 万人死亡。
印度在 5 月 4 日实施了为期两周的第三次封锁,可能正在计划第四次封锁。一些人认为这是世界上最大的封锁,有* 13 亿人被困在家中。印度开始根据疾病传播的严重程度,将 733 个地区用颜色划分为红色、橙色和绿色区域。
红色:案件量最高的区,占各州案件量的 80%以上,或者加倍率少于 4 天的区。
绿色:一个超过 28 天没有报告任何病例的地区。
橙色:既不属于红色也不属于绿色的地区
政府试图利用国家的联邦结构来绘制和隔离疫情,建立限制级别,有效地分配资源,并追究责任。
在经济时报和今日印度阅读更多内容
作为一个呆在禁闭室内的极客,我试图用 Python 来绘制这些区域,这篇博客就是关于这个的。
目标:这个博客展示了为印度各区创建一个 choropleth 地图的步骤,并用它们的颜色标记出来。该地图是一种交互式绘图,它还显示每个地区受 Covid19 影响的人数。
代码已经内置在 Jupyter 笔记本中,可以在我的 Github repo 上找到:[https://github.com/yatharthaggarwal/CovidIndia]。我一直在为基于 Python 的项目使用 Anaconda 工具包,并向其他人推荐同样的工具包。
套餐:
- geo pandas:是一个帮助用户处理地理空间数据的开源包。我们将关注的一个依赖项是 shapely ,GeoPandas 依赖于它来执行几何运算。在我们的例子中,印度每个地区的形状将通过 shapely 包编码为多边形或多多边形。然后通过 GeoPandas 来理解地理空间数据。
- 散景 : 它可以让我们创作出更复杂的剧情。Bokeh 是一个多功能的开源软件包,旨在帮助用户创建漂亮的交互式可视化效果。
导入数据集
1。新冠肺炎患者数据
首先,我们需要在地区级别加载 COVID 19 数据。印度政府/邦政府没有按地区提供数据。因此,我们需要依靠基于众包的门户网站,比如 https://www.covid19india.org/。
甚至他们提供的数据也有很大一部分是不正确的。他们在“未知”部分推送了大量数据。但是,我们将选择提到地区的行。下图是加载数据集的代码片段,我们感兴趣的是已确认、活动、已恢复和已死亡的列。确诊病例是另外三个的总和。
districtdata = pd.read_csv ('[https://api.covid19india.org/csv/latest/district_wise.csv'](https://api.covid19india.org/csv/latest/district_wise.csv'))
districtdata.head()
2。印度地区形状文件
为了创建一个地图,你需要一个形状文件。shp)。该文件告诉 Geopandas 我们正在绘制什么形状。在我们的例子中,我们需要一个概述每个地区的文件。我们使用一个 geometry 列,以便 Geopandas 包知道在哪里寻找每个州的形状信息。
一个优秀的更新 shapefile 可以在这里找到:https://hub . ArcGIS . com/datasets/esriindia 1::India-districts-boundary。人们可以从这里下载并使用它。虽然有很多拼写错误,我已经在数据清理部分纠正了。请参见下面的代码片段:
df1 = gpd.read_file('India_Districts/c44c9b96-f570-4ee3-97f1-ebad64efa4c2202044-1-1rb4x6s.8xx6.shp')
df1.head()
我们可以利用绘图功能来查看 shapefile 中的内容。如果有人能找到任何官方文件,请做评论。这张地图不包含 2020 年的行政区,但出来的地图很漂亮。
# showing the India map based on the shapefile... See the districts boundary
df1.plot(figsize = (8,8))
shapefile 中的印度地区地图
3。逐区分区数据
该数据已由卫生和家庭福利部公布。我已经直接从 https://www.kaggle.com/xordux/india-corona-severity-zones下载到工作目录下了。请参见下面的代码片段:
zones = pd.read_csv('Zones in india.csv')
zones.head()
数据清理
数据清理部分是任何基于数据的项目非常必要的一部分,因为它提供了纠正/删除数据值、处理 NaN 值和格式化整个数据集的方法。我没有把代码片段放在这里,因为它只是纠正了大量的拼写错误。直接检查存储库中的代码部分,这里再次链接了。
数据预处理
用上面显示的所有数据创建一个公共数据框架。
在 df1 (shapefile)中,我们根据地区和州合并了 Covid19 患者的数据,然后类似地合并了 Zones 数据帧。一些不必要的栏目也被删除。在印度,不同的邦经常保留一个相似的区名,因此在' merge' 函数中我们需要同时检查[ District ',' States']。参见代码片段,其中包括几何图形、区域和患者数据以及区名和州名:
newdf = df1.merge(districtdata[['State', 'District', 'Confirmed', 'Active', 'Recovered', 'Deceased']], on = ['District', 'State'])newdf = newdf.merge(zones[['State', 'District', 'Zone']], on = ['District', 'State'])newdf = newdf.drop(columns = ['statecode', 'state_ut', 'distcode', 'countrynam'])
newdf.head()
现在,数据已经转换为适当的格式,我们可以按照以下步骤绘制地区的 choropleth 地图:
- 创建体形对象
- 将面片渲染器添加到图形中
- 创建显示患者数据的悬停工具
- 展示图
导入散景库并创建数据类型格式
import json
from bokeh.io import show
from bokeh.io import output_file, save
from bokeh.models import (CDSView, ColorBar, ColumnDataSource,
CustomJS, CustomJSFilter,
GeoJSONDataSource, HoverTool,
CategoricalColorMapper, Slider)
from bokeh.layouts import column, row, widgetbox
from bokeh.io import output_notebook
from bokeh.plotting import figure
散景使用 GeoJSON 格式,用 JSON 表示地理要素。GeoJSON 将点、线和多边形(在散景中称为面片)描述为要素的集合。因此,我们将合并后的文件转换为 GeoJSON 格式。
此外,还创建了一个分类颜色映射器,用于将红色区域映射为红色,绿色和橙色区域也是如此。
a)用我们的初始数据创建 GeoJSONDataSource 对象
geosource = GeoJSONDataSource(geojson = newdf.to_json())
b)定义要使用的调色板并映射到区域的分类值
palette = ['red', 'orange', 'green']
color_mapper = CategoricalColorMapper(palette = palette, factors = ['Red', 'Orange', 'Green'])
Choropleth 地图
以下代码创建 figure 对象(包括缩放和*移工具),添加渲染的修补程序(包括带列区域的 geosource 和 mapping 颜色映射器),并创建悬停工具以显示特定地区的已确认、活动、已恢复和已死亡病例。
最后,以“HTML”格式保存绘图。现在经过上述步骤:
- 在创建一个人物对象时,我们可以为情节设置标题、高度、宽度和交互工具。
p = figure(title = 'Red, Green and Orange Distric of Covid19: 19 May 2019',
plot_height = 700 ,
plot_width = 650,
toolbar_location = 'right',
tools = "pan, wheel_zoom, box_zoom, reset")
2.补丁渲染器是我们输入数据源和颜色映射器的主要地方。
states = p.patches('xs','ys', source = geosource,
fill_color = {'field' :'Zone',
'transform' : color_mapper},
line_color = 'black',
line_width = 0.25,
fill_alpha = 1)
3.悬停工具允许我们将想要显示的数据放入绘图中。
p.add_tools(HoverTool(renderers = [states],
tooltips = [('District','[@District](http://twitter.com/District)'),
('State','[@State](http://twitter.com/State)'),
('Zone','[@Zone](http://twitter.com/Zone)'),
('Confirmed cases','[@Confirmed](http://twitter.com/Confirmed)'),
('Active cases','[@Active](http://twitter.com/Active)'),
('Recovered cases','[@Recovered](http://twitter.com/Recovered)'),
('Deaths','[@Deceased](http://twitter.com/Deceased)')
]))
4.最后是 HTML 格式的情节。这是一个巨大的 150 兆字节。我需要看看我如何能减少尺寸。保存功能将它保存在当前目录中。
output_file('plot.html', mode='inline')
save(p)
show(p, notebook_handle = True)
显示印度所有地区的 Choropleth 地图,工具位于右侧
恭喜你。!我们已经成功地创建了我们的 Choropleth 地图。人们可以在任何浏览器中简单地打开 plot.html 文件来查看其内容。或者只执行下面的命令,在新的选项卡中查看图形。
我制作了一个展示互动地图的小视频。
https://www.youtube.com/watch?v=JuF4cNeWKzc
Choropleth 地图工作
在这里可以直接看到代码。
如果你对我们如何进一步增强情节或代码有任何意见或建议,我很乐意听到!
跟我连线:noobdatascientist@gmail.com
感谢阅读!
第一张图片(也充当缩略图)是使用 Freepik 的: 印度地图 , 日冕感染
用生成对立网络给照片着色
原文:https://towardsdatascience.com/coloring-photos-with-a-generative-adversarial-network-a435c4403b5d?source=collection_archive---------22-----------------------
用深度学习把黑白照片带到现在。
自从我开始学习数据科学和机器学习以来,一直有一种算法不断吸引我的注意力:生成敌对网络(GANs)。以至于我写的第二篇博客详细介绍了这些模型是如何工作的以及它们能创造什么。当我第一次了解它们时,大多数文章(包括我自己的)只报道了它们如何能够接受随机噪声向量并产生逼真的照片。
在我写完那篇博客文章后不久,我偶然发现了周而复始的(朱等),它允许图像到图像的翻译。这意味着我们能够传入一个图像作为输入,并接收一个修改过的副本作为输出。这包括绘制梵高等艺术家的风格,将照片从夏天变成冬天,或将斑马变成马。
来源:朱俊彦
在我写了前面提到的博文之后,我觉得我对 GANs、它们的工作方式以及它们的变体已经足够满意了,于是我决定创建自己的 GANs。然而,有这么多的应用程序可供选择,我很难决定我想创造什么。一天晚上,当我还在考虑不同的选择时,我看了彼得·杰克逊的他们不会变老 ,这是一部通过图像重建和重新着色创作的一战纪录片。这一点,结合我对迁移学习的了解,启发我创建了一个可以将黑白照片转换为彩色的模型。
(对于那些不熟悉生成性敌对网络的人,我建议在继续之前阅读我的第一篇博客
创建 GAN 的步骤:
- 检索数据
- 预处理图像
- 创造建筑
- 训练、监控和调整参数
获取数据:
在我开始编码或规划我的模型架构之前,我需要找到一个数据集来使用。我了解到,当谈到图像翻译时,GANs 在理解照片的纹理和对称性方面比他们在识别复杂的几何图形方面更有效率。这意味着,举例来说,他们能够比一个人或一只狗更容易地创作风景照片。这促使我收集了 2 个不同的数据集:
- 麻省理工学院计算视觉库数据集:只使用了海岸照片,因为它们包含简单的风景。
- MPII 人体姿态数据集:进行各种活动的人的图像。
我第一次尝试从麻省理工学院的数据集开始,因为这些图像更容易建模,这使我可以专注于创建我的第一个架构和所有必要的预处理,然后再处理更大的 MPII 数据集。一旦我获得了所有的数据,我终于可以开始编码了。
下面是 Github 供参考。
图像预处理:
由于 gan 的计算量非常大,因此限制图像的大小非常重要;我选择了 256x256 的图片尺寸。麻省理工学院的海岸照片已经是这个尺寸了,所以不需要对数据集中的照片做任何处理。另一方面,MPII 数据集图像的大小不一,大于 256x256,因此需要调整大小,这可以使用 Numpy 轻松完成。
我的第一个想法是将每张图像简单地转换为灰度,并将其传递到生成器中,使用标准 RGB(红绿蓝)颜色通道(其正常值为 0-255)创建全彩色图像。我很快意识到这种方法非常低效,为了转换我的图像,我需要使用一些不同的方法,而不是一个简单的解决方案。
资料来源:Photoscreenprint.com
在我的研究过程中,我仔细检查了研究人员试图给黑白照片上色的例子,并注意到其中的一种模式;许多人将图像从 RGB 颜色值转换为 LAB 颜色值。与 RGB 不同,RGB 合并红色、蓝色和绿色值来创建彩色图像,LAB 由一个光敏通道和两个颜色通道组成。L 通道包含照片的感光度信息,相当于黑白版本。A 和 B 是颜色通道,其中 A 控制绿-红权衡,B 控制蓝-黄权衡。Python 的 Scikit-Image 库提供了一个很好的方法,允许我们轻松地将 RGB 照片转换到实验室。
我最初的方法是尝试创建所有三个颜色通道,现在我决定将 L 通道作为输入通过生成器,并输出新的 A 和 B 颜色通道。最后,一旦我将图像转换到 LAB,我需要进行归一化,因为它们的像素值对于我的模型来说是一个非常低效的范围。我决定将像素值从-1 缩放到 1,这样我可以很容易地用 tanh 激活来复制它。
创建架构:
为了创建模型,我使用了 Keras,这是 Python 的深度学习库。首先,我分别创建了生成器和鉴别器;然后我把两者连接起来,这样生成器就可以根据它欺骗另一个模型的程度来学习。
发电机
资料来源:i2tutorials.com
发生器可以分为两部分:编码器和 T2 解码器。原始图像,在我的情况下是 L 通道,通过卷积层缩小,直到达到所需的特征图大小。再次放大图像之前的这组特征图被称为图像的潜在空间表示。从这里,我执行所谓的转置卷积或反卷积,这允许我对我的图像大小进行上采样;这里的动画链接展示了一个很好的例子,展示了这是如何工作的。我重复这个过程,直到我回到原来的大小,然后输出新的图像,A 和 B 通道。
我的生成器的编码器由四个卷积层组成,步长为 2,这样我可以缩小图像。我从 64 个特征地图开始,并将每一层的地图数量增加一倍,以便在我到达潜在空间表示(即网络的中间)时,我最多有 512 个地图,每个地图的大小为 16x16。然后,每层的输出经过批量标准化,最后是泄漏 ReLU 激活。解码器几乎是一个反向拷贝,因为它有四个去卷积层,其输出经过批量归一化和 ReLU 激活。最后一层是具有两个输出通道(A 和 B 颜色通道)的单步卷积,具有 tanh 激活,以匹配我们之前在预处理图像时设置的-1 到 1 比例。
鉴别器
鉴别器是一个比其对应的生成器简单得多的模型,因为它是一个标准的卷积神经网络(CNN),用于预测 AB 通道是真是假。它有四个 2 步卷积层,每一层都包括丢失、泄漏 relu 激活,以及除第一层之外的批量归一化。像其他 CNN 一样,我把最后一层弄*,然后通过一个 s 形管来预测图像是真是假。
初始化模型
两个模型都将使用二进制交叉熵作为损失函数和 Adam 优化器。与我读到的一切相反,我需要对发电机使用更高的学习率,以防止它被压制。首先,初始化鉴频器,然后我创建并链接发电机的损耗到鉴频器的输出。
训练、监控和调整参数:
在完成了上面解释的过程之后,我准备好训练模型了,或者说我是这样认为的。当我在笔记本电脑上运行这个模型时,我收到了“内核死亡”的消息。对我的笔记本电脑来说,内存和计算需求太大了。在 CPU 上训练一个 GAN 也可能需要几天时间,这让我明白了两件事:我需要一台强大的计算机/实例和一个 GPU。为此,我去 AWS SageMaker 租了一个 GPU 实例,它为我提供了足够多的功能。
我做的最后一个调整是将我的历元大小限制为只有 320 个,而不是训练几百个历元,而是训练几千个。我用半个时期的真实图像和半个时期的虚假图像来训练鉴别器。最后,生成器生成一个完整时期的图像,并将其传递给鉴别器,如果图像被标记为假的,则生成器会受到惩罚。GANs 很难训练,因为与大多数其他深度学习算法不同,它不会最小化或最大化任何损失函数。相反,我寻找一个*衡点,或者说鞍点,在这个点上,两个网络保持竞争,并继续相互依赖。从下面的损失图可以看出,这是一个非常零星的训练周期。
可能需要多次尝试才能使模型稳定,但一旦你这样做了,耐心是很重要的,因为在 GPU 实例中可能需要 6-12 个小时来训练模型。帮助我控制长时间训练和模糊指标的两件事是经常打印图像和以一半的频率保存模型。为了查看照片,只需按比例缩小到原始像素值并转换为 RGB。
结果
左:原始|右:重新着色
左:原始|右:重新着色
正如你从上面的图片中看到的,模型有时会偏向某些颜色,特别是最后一张图片,倾向于绿色和红色以及一些渗色。
后续步骤
这个项目肯定仍在进行中,我的下一步是建立一个自我关注层,以帮助模型更好地理解照片中的几何图形。一旦我建立了新的模型,我的目标是在 Imagenet 数据集上训练它,这样它就可以推广到更多的照片,并创建一个 web 应用程序,允许任何人立即给他们的照片着色。
用深度学习给视频上色
原文:https://towardsdatascience.com/colorize-a-video-with-deep-learning-15b30da3b57c?source=collection_archive---------8-----------------------
零本地设置/解密/ Colab 笔记本
一个用户友好的版本,可以将黑白视频转换成彩色视频,并免费自动导出到 Google Drive。
“Haal Hai Jana ab Ka”宝莱坞歌曲— 1958 年和“美丽的黑白好莱坞电影镜头集”
按照我的目标轻松做事,我想尝试去锁定一遍又一遍地将 B & W 视频内容转换成音频,而不必因为 Google Colab 上的免费资源会话超时而改变代码或丢失进度。
以下是步骤——大约 10 次点击,让你做到这一点!请记住,我只测试了免费硬件资源的短视频(5 分钟)。
打开存储库中的 Colab 笔记本链接。这篇文章也可能让你熟悉 Colab 的力量,为你下一篇激动人心的人工智能论文做准备。
https://colab . research . Google . com/github/ojjsaw/video-processing/blob/master/Custom _ deol dify _ video colorizer _ colab . ipynb
首先,确保通过登录分配一个空闲的 GPU 资源。点击运行时菜单上方的> 改变运行时类型>GPU>保存然后点击右上方的连接。
第一步
登录后,再次点击连接,然后将网址更新为你从 YouTube 视频的分享图标上获得的视频链接。默认网址是卢米埃尔兄弟的电影 101 历史 1895 中标志性的“火车到达”片段。
您可以选择修改默认的 google drive 导出目录路径。
点击左边的运行图标!每次打开这个页面(会话),都会要求你授权 google drive 挂载到你当前的会话。
第二步
复制粘贴授权码,点击进入。点击 Setup t ext 部分将其聚焦,并点击页面顶部 Runtime 菜单中的 Run After 选项。
第三步
坐着别动,去喝杯咖啡!只要确保你的机器正在运行,浏览器保持活跃。
处理需要一段时间,但是成功转换后,源和结果视频将会上传到您选择的路径下的 google drive。
同样,以上是最简单的转换方法,不需要花里胡哨。更多定制,请看一下原装笔记本。
在未来的帖子中,我们将尝试增加视频的每秒帧数以获得更*滑的剪辑,甚至可能将视频升级到更高的分辨率,以满足当代显示设备的要求。
如果你想尝试更多从头到尾的快速 AI 实验,请访问我的上一篇帖子: 训练神经网络对图像进行分类&在 10 分钟内优化 CPU 推理
人工智能给黑白照片上色。
原文:https://towardsdatascience.com/colorize-black-and-white-photos-by-ai-cc607e164160?source=collection_archive---------31-----------------------
利用 Fastai 的生成性对抗网络(GAN)使黑白照片变得丰富多彩
(左)百老汇在纽约州萨拉托加温泉市的美国酒店(https://www.loc.gov/pictures/item/2016818127/)(右)彩色照片
介绍
当我看到历史黑白照片时,我总是想知道真实的颜色是什么,摄影师在拍照时看到了什么。
发现 B&W 照片的确切颜色并不容易,但根据经验和想象给照片上色是可能的。这可以通过调查照片中物体的可能颜色来实现,例如,衣服、建筑物、树木、汽车等的颜色。,并用 Photoshop 等软件手工上色。
另一种方法是通过提供大量彩色照片来训练计算机理解不同物体的颜色,然后要求计算机通过识别检测到的物体的似乎合理的颜色来着色。由于深度学习的发展,它可以通过使用生成对抗网络(GAN)来完成。
生成对抗网络
生成性对抗网络的思想非常简单,它包含两个神经网络,生成器和鉴别器。生成器的工作是根据黑白照片预测颜色,然后生成彩色照片。然后,鉴别者的工作是判断生成的照片与真实照片相比是否足够真实。
如果鉴别器能轻易分辨出照片是生成的,说明生成器不够好,生成器需要更多的训练。当发生器正在改进并且鉴别器不能再分辨出差别时,鉴别器将被更多地训练以分辨出差别。
在这项工作中,我以杰森·安蒂克的 deol dify(【https://github.com/jantic/DeOldify】)为参考,用 fastai 训练了一个 GAN。
资料组
我使用 ImageNet 作为我的训练数据集。然而,由于计算限制(Colab 上 12 小时的运行时间限制),使用所有的图像并不容易,所以我最终只使用了其中的 5000 张图像。
训练数据集的一部分
制作黑白照片
首先,我需要把彩色图像变成黑白的来进行训练。我还添加了一点噪点,给这些图片一些旧照片的感觉。
(左)ImageNet 中的一幅图像(右)带噪声的黑白图像。
预训练发电机
现在我已经准备好了数据集,可以开始训练了。我为生成器创建了 U-Net 学习器,并在 GAN 之前对其进行了预训练。fastai 库可以轻松完成。
我从小尺寸(64 像素)开始,所以我可以用更大的批量更快地训练它。
用 64 像素图像进行生成器预训练。
然后我把尺寸加大到 128 和 256。随着时代的增加,我开始看到一些好的结果。
使用 128 像素图像进行生成器预训练。
使用 256 像素图像进行生成器预训练。
训练前鉴别器
在生成器预训练之后,我使用生成器从黑白数据集生成彩色照片。然后我用这些生成的照片和原始照片来训练鉴别器。
在 10 个时期之后,鉴别器能够以 85%的准确度辨别图像是否被生成。
开始
现在是把它们放在一起的时候了。Fastai 为创建 GAN 提供了一个非常有用的工具,结合了预先训练的生成器和鉴别器。经过 50 个时代的训练,我得到了初步的结果。
甘在训练的时候。
结果
我下载了一些黑白照片,这些照片是模特以前没有见过的,用来测试。以下是一些结果。
这个模型能够给树和草上色。它也做了很好的着色人类的皮肤。
(左)纳特。我是。芭蕾舞,8/20/24(https://www.loc.gov/pictures/item/2016838246/)(右)彩色照片
(左)9 月 24 日,罗莎莉·琼斯开始拉福莱特的竞选之旅(【https://www.loc.gov/pictures/resource/cph.3c15477/? 】)co=ggbain )(右)彩色照片
(左)拳击(【https://www.loc.gov/item/2016878085/】)(右)彩照
(左)裁判看着纽约扬基队球员在与华盛顿(https://www.loc.gov/pictures/resource/cph.3c35415/)的棒球比赛中滑入垒位
(左)土路上的乡村商店。周日下午。注意右边的煤油泵和左边的汽油泵。粗糙、未加工的木柱被用来支撑门廊屋顶。黑人正坐在门廊上。店主的兄弟站在门口。北卡罗来纳州戈登顿(https://www.loc.gov/pictures/resource/fsa.8b33922/)(右)彩色
(左)路易斯·阿姆斯特朗的肖像,水族馆,纽约,加利福尼亚州。1946 年 7 月(https://www.loc.gov/item/gottlieb.00201/)(右)彩色照片
(左)马里兰州安蒂特姆,林肯总统和乔治·b·麦克莱伦将军在将军的帐篷里(https://www.loc.gov/pictures/resource/cwpb.04351/)(右)彩色照片
有些颜色不是很真实,但仍然很有说服力。
(左)费城运动家队的宾·米勒在一场棒球比赛中被华盛顿国民队的捕手“泥巴”鲁埃尔在本垒板标记出局(【https://www.loc.gov/pictures/item/2005685880/】)(右)彩色照片
(左)购买复活节鲜花,联合广场。纽约州(右)彩色照片
请注意,这是仅由 5000 幅图像训练的,并没有很多历元,它可能会通过更密集的训练得到进一步改善。
网络应用
使用 Streamlit 可以快速创建 web 应用程序原型。它不需要大量的 HTML 和 Java 技能,所以它对像我这样的 web dummy 真的很有帮助。
Streamlit 构建的 Web 应用程序
[## 生成性对抗网络:构建一个用 Streamlit 给 B&W 照片着色的 web 应用程序
使用 Streamlit 快速将生成式对抗网络模型转换为 web 应用程序,并部署到 Heroku
towardsdatascience.com](/generative-adversarial-network-build-a-web-application-which-colorizes-b-w-photos-with-streamlit-5118bf0857af)
感谢阅读,欢迎提出建议和反馈。
更多示例:
草地网球选手可能在波斯顿地区(https://www.loc.gov/resource/ppmsca.53290/)
茱莉亚·欧贝尔,国家妇女党总部的信使(https://www.loc.gov/resource/cph.3d01840/)
周日骑自行车的人在华盛顿特区的东波托马克公园(https://www.loc.gov/resource/fsa.8c34879/)
弗朗西丝·班杰明·庄士敦,装扮成假胡子男人的全身自画像,骑着自行车,面朝左(https://www.loc.gov/resource/ppmsc.04884/)
一名男子和一名男孩骑着自行车,一只狗骑在男子的肩膀上,靠* https://www.loc.gov/resource/ppmsca.38847/的美国国会大厦倒影池
托尼·皮索(https://www.loc.gov/resource/npcc.01561/)
更换场地,14 年 8 月 14 日(网球)(https://www.loc.gov/resource/ggbain.16897/)
爱丽丝大理石在森林山打网球;展示她发球和反手击球的八张照片的合成(【https://www.loc.gov/resource/cph.3c15631/】T2
华盛顿特区,伍德罗·威尔逊高中足球队成员在场边观看比赛(【https://www.loc.gov/item/2017863035/】T4)
杜克大学-卡罗莱纳州足球赛当天高速公路沿线的汽车队。杜伦,杜克大学体育馆附*。北卡罗来纳州达勒姆县(https://www.loc.gov/item/2017801879/)
修补网球网——水手的舒适港湾(https://www.loc.gov/resource/ggbain.16850/)
柱状商店——何时/如何/为什么?
原文:https://towardsdatascience.com/columnar-stores-when-how-why-2d6759914319?source=collection_archive---------1-----------------------
揭开行与列大数据存储的神秘面纱(Parquet、Postgres、Avro 等)
照片由 Unsplash 上的 Skyler Gerald 拍摄
很久以前,数据存储很简单——堆文件和 b 树,仅此而已。今天的选择是压倒性的——ORC、Parquet、HDFS 或 S3 上的 Avro 或者像 Postgresql、MariaDB 这样的 RDBMS 解决方案,或者像 Oracle 和 DB2 这样的商业解决方案。甚至在 RDBMS 引擎和云服务中也有很多选择!
本指南是对广阔的存储领域的“随机漫步”。
样本数据集
我调出了芝加哥公务员的工资信息。你知道公务员的工资是以每个人的真实姓名公布的吗?查找你最喜欢的警察或专员的工资(不幸的是,它不包括加班、津贴或贿赂)。
我添加了一些虚拟的人——Foo & Bar 家族。否则它的真实数据。
面向列与面向行
首先是数据的基本存储机制。行列方向。
面向行将每个单独的记录存储在一起,Doug Foo 的完整记录,然后是 Jane Foo 的完整记录,依此类推。
[Doug,Foo,Foostack,程序员,M,120000] [Jane,Foo,Foostack,程序员,F,110000] [Doug,Bar,…]..
列或 列 将所有列数据存储在一起—因此所有的名字(Doug、Jane 等),然后是所有的姓氏、头衔等等,最后是所有的薪水。
[道格、简、道格、简……][福、福、吧、吧……][程序员、程序员……][M、F、M、F……][120000、110000、100000、130000……]..
数据通常以 KB(或 MB/GB)为单位从磁盘中读取,因此对 1 条记录的单次读取会带来比您想要的更多的数据。
典型块大小[*1]:
- HDFS: 128MB(块)
- 谷歌文件系统:64MB(块)
- 亚马逊 AWS S3: 128KB
- Oracle 数据仓库:32KB
- Postgres 数据库:8KB
- Linux 和 Windows 文件系统:4KB
薪水记录非常小~ 50chars ( <50 bytes). An 8KB block with metadata could easily store 100+ 行导向 记录【8192 / 50 = 163】)。因此,对包含“Doug Foo”的记录的块的一次读取包括更多内容。
对于列块读取—读取因列大小而异。例如,对于 8KB 数据块:
- 名字可能*均为 10 个字节,意味着大约 800 个以上的名字。
- 薪水可以放入一个 32 位的 Int(4 字节)中,产生大约 2000 个条目!
- 性别是 M/F/?—可以存储为 1 个字节,甚至半个半字节~ 8000!
在我们稍后进行更多分析时,记住这一点非常重要。
数据转换
我想添加一个 M/F 属性,所以我合并到一个婴儿名字数据库中,然后写出各种熊猫支持的格式(JSON、CSV 和 Parquet)。
基本熊猫性别数据
注意同等磁盘格式的文件大小差异 (38k 记录) :
- 不带头文件的 CSV 为 2.526 MB
- 压缩后的拼花(柱状)为 606 KB(CSV 的 1/4)
- JSON 为 4.615 MB(比 CSV 大 90%,比 Parquet 大 700%)
拼花地板是一种二进制压缩格式,因此需要一些努力来快速浏览——稍后将讨论细节。
注意一些奇怪的事情,它只显示了道格和简一次,尽管我们有两个道格和两个简。名字聚集在一起。
为什么不存储为 CSV 或 JSON?
显而易见,但让我们把它拼出来:
- 空间利用率差(字符串形式的数字浪费空间)
- 没有类型或结构检查(字符可能会出现在数字字段中)
- CSV —无元数据/标题信息,JSON —重复的元/格式
- 没有重复值的本机压缩
- 没有本地索引/搜索能力
注意 CSV 和 JSON 具有非常容易阅读的明显优势,因此有时是很好的交换格式。
深入探究 Postgres 格式(RDBMS)
Postgres 是一个全功能的开源数据库,既有传统的基于行的存储(有时称为“堆文件”),也有列存储扩展(cstore_fdw)。
我创建了一个模式并将工资数据加载到两个变量中,一个是标准的行和列版本。
查询 38k 记录时两者之间的一些基本统计/比较:
- 选择计数(*) →列存储略快(7.9 毫秒对 10.9 毫秒),并且“成本”较低(480 毫秒对 873 毫秒)(假设这是估计操作/读取的指标)。理论上,我们使用列存储读取少于的块,因为您只需要扫描一列来获得计数,并且它是压缩的。
count(*)测试,只是在列上快一点
- Select sum(salary) →这应该是柱形图的一个经典案例,我们只需要扫描一列或一系列块,而基于行的需要扫描所有块,以便从每行中提取薪金。但是没有我们预期的那么快。成本便宜了 493 vs 873,但是计时是 14.1ms vs 17.1ms。
38k 行,即使在一个单独的列上,速度也快不了多少。
3.更大的数据集— 我将它提升到 380 万行,并重新运行 sum 查询。变化不大——有点令人惊讶!理论上,这应该比 20-30%的涨幅要快得多。其实柱状往往是缓存 生效后 变慢!(公*地说,您确实需要比您的内存缓存更大的 GB 到 TB 数据集才能获得真正的收益) **[2] 。***
3.8 米的行,还是没有快很多。
在阅读了一些 bug 报告和开发者笔记之后,我可以猜测作为一个扩展,它不如标准行存储健壮。例如,本机行格式提供多核处理和缓冲区缓存。我可能应该与本地列存储数据库进行比较…
请注意我加载 3.8m 行时的文件大小:
- 标准行格式: 321 MB
- 柱状/压缩格式: 72 MB
巨大的空间节省(几乎 4 倍)!注意磁盘上的行和列的原始数据转储(在 linux/wsl2 上使用“xxd -c 32”):
行方向非常简单
纵列由带有压缩子串的纵列展开
镶木地板——最受欢迎的?
Parquet 来自 Twitter 和 Cloudera (Hadoop ),作为 Apache 项目维护。这是 Spark 的实际格式,因此最受欢迎。(之前流行的格式包括 ORC 和 RCFile)。
Python/Pandas 本身也支持它,并提供多种压缩格式。基本的文件格式是一个由行组成的列,存储一个中央模式&组级元数据,以允许并行和部分读取。
对原始文件的适度深入研究显示:
类似于 Postgres CStore —列被分批分组并压缩,这样 Doug,Jane 在整个文件中只出现一次。
AVRO —面向行的模式进化
与 Parquet 竞争激烈的是 Avro,它不仅仅是一种存储格式,但我们将只关注存储方面。这也是一个 Apache 项目。 [*3] 拼花地板的两个主要区别:
- 更好的模式进化
- 面向行的存储
模式和更改(新行和旧行的默认值)嵌入到文件中。添加新列只需要定义默认值,这使得渐变维度(SCD)和更改更容易处理。
请注意,它是面向行的,因此您不会获得像使用 Parq 那样的一些优势,例如压缩和性能——假设您的用例更多地是关于列聚合,而不是逐记录处理。
Avro 代码和数据文件示例:
其他存储选项(MongoDB、Kafka、KDB 等)
NoSQL — 像 MongoDB、AWS Dynamo 和 Cassandra 这样的名值对象存储通过不同的键存储整个 JSON(或任意)对象。该 API 使用基本的键值存储(put/get)语义,非常简单。高水*+/-:
- +简单的编程接口
- +快速启动并运行您的应用
- -加载多个或复杂数据的效率低下
- -索引和查询/搜索不灵活
- -模式演变挑战
日志结构化商店(和日志结构化合并树)和它们的创新用途是一个迷人的领域——卡夫卡是领导者和创新者(不要被愚弄了,它不仅仅是消息传递,它真正关于 日志**根据联合创作者 Jay Kreps* 。 [4]
- +简单的编程接口
- +实时消息存储和数据库的可扩展替代方案
- -复杂的集群管理
最后,KDB 值得一提,他是列式、实时和时序内存数据库的先驱。最初编写于 90 年代,即使在今天也拥有无与伦比的单核性能。不幸的是,这是一种昂贵的利基产品,因此最*被出售给一级衍生品,很可能会失血而死…
- +超快和低占用空间(800kb)适合 L1/L2 缓存
- +利用矢量/SIMD CPU 指令
- -不超过 1 台机器(不需要?)
- -成本和晦涩的语言(K/Q)使大多数消费者望而却步。
Apache Arrow(内存列格式和串行器)和 OLAP 理工大学也是值得研究的两个领域。
总结:首要考虑事项
- 列式是否适合您的典型用例(在几列上频繁聚合)?
- 您现有的数据库是否提供像列存储这样的存储选项?
- 模式演变/改变是常见的,也是一个关键的考虑因素吗?
- 存储空间/容量是一个关键考虑因素吗?
仔细考虑一下,试运行一下。关系数据库在缓存和索引方面已经有了很大的改进,这在某些情况下可能会降低其必要性。
参考资料、脚注和灵感
- 对于文件系统/操作系统、数据库和大数据存储,如 S3/GFS,块大小在概念上是不同的。在每种情况下,它都是一个逻辑单元。AWS EBS 使用 4K,S3 是一个对象存储,但它的最小分配是 128KB。
- 【2】-列性能仅在冷启动/清除缓存时更快。一旦数据库填满了它的缓存,Postgres 上的传统行存储总是更快。但是,列存储适用于大数据~TB 大小的数据集,这些数据集大于内存,会表现出冷缓存行为。
- 【3】——更混乱的是,Avro 的序列化代码可以写入 Parquet 文件格式。它既是竞争对手,也是合作者。
- 【4】——大多数人认为 Kafka 只是下一个 MQ,但它是一个根本不同的方法,以提交/事务日志*为中心,这是一个伪数据库。*
- *Postgres c store——【https://github.com/citusdata/cstore_fdw *
- Parquet 上的好读物—https://medium . com/swlh/insights-into-Parquet-storage-AC 7 e 46 b 94 FFE
- Avro—https://www . perfectlyrandom . org/2019/11/29/handling-Avro-files-in-python/
- LSM 树 vs B 树—https://blog . yugabyte . com/a-busy-developers-guide-to-database-storage-engines-the-basics/
- 关于 LSM 树的更多信息—https://www . slide share . net/ConfluentInc/power-of-the-log LSM-append-only-data-structures
- 克雷普斯 ♥ 日志(卡夫卡)—https://www . confluent . io/ebook/I-heart-logs-event-data-stream-processing-and-data-integration/
- 阿瑟·惠特尼对 KDB &的完整改写——https://kx.com/blog/small-core-code-and-hp-apl/
- 源数据集—https://Data . cityofchicago . org/Administration-Finance/Current-Employee-Names-salary-and-Position-Title/aned-ke5c
- 本文 GitHub——https://github.com/dougfoo/fileformats
多元时间序列预测的 LSTM 和 VAR 组合方法
原文:https://towardsdatascience.com/combine-lstm-and-var-for-multivariate-time-series-forecasting-abdcb3c7939b?source=collection_archive---------3-----------------------
多步训练过程在时间序列预测领域的应用
照片由 Unsplash 上的尼克·费因斯拍摄
在经典的时间序列预测任务中,建模时的第一个标准决策涉及采用统计方法或其他纯机器学习模型,包括基于树的算法或深度学习技术。这种选择与我们正在解决的问题密切相关,但总的来说:当我们面临一个自回归问题,而未来只与过去相关时,统计技术就足够了;而机器学习模型适用于更复杂的情况,也可以组合多样化的数据源。
在这篇文章中,我试图将统计方法从经验中学习的能力与深度学习技术的推广相结合。我们的任务是一个多变量时间序列预测问题,所以我们使用 ARIMA 的多变量扩展,称为 VAR,和一个简单的 LSTM 结构。我们不生产一个集合模型;我们使用 VAR 的能力来过滤和研究历史,并在预测未来时为我们的神经网络提供益处。
我们的工作流程可以总结如下:
- 根据我们的训练数据正确估计 VAR
- 提取 VAR 学到的知识,并将其用于改进执行两步培训的 LSTM 模型的培训流程。
我们会发现我们的结果并不明显,因为按照这个步骤,我们必须与灾难性遗忘的问题作斗争。
数据
我们实验的数据包含嵌入在空气质量多传感器设备中的金属氧化物化学传感器的每小时*均响应,该设备位于意大利城市污染严重地区的场地。记录了一年的数据,包括一氧化碳、非后生碳氢化合物、苯、总氮氧化物(NOx)和二氧化氮(NO2)的实际小时*均浓度。此外,还提供了外部变量,如天气状况。存在大量 nan,因此在继续之前需要进行线性插值(排除训练数据中 nan 超过 50%的序列)。
由我们支配的时间序列的例子(图片由作者提供)
VAR 建模
对于 ARIMA,我们使用每个变量的过去值来预测未来。当我们有多个时间序列可供支配时,我们也可以从它们的关系中提取信息,这样 VAR 就是 ARIMA 的多元推广,因为它理解并使用几个输入之间的关系。这有助于描述数据的动态行为,并提供更好的预测结果。
要正确开发风险值模型,必须满足拟合 ARIMA 时遇到的相同经典假设。我们需要给予*稳性并利用自相关行为。这些先决条件使我们能够开发一个稳定的模型。我们所有的时间序列*均都是*稳的,显示出每日和每周的模式。
我们所掌握的一些时间序列的自相关例子(图片由作者提供)
在这些初步检查之后,我们准备好拟合我们的 VAR。最佳滞后阶数的选择是根据 AIC/BIC 准则自动进行的。我们用 AIC 来操作选择:我们需要做的就是递归拟合我们的模型,改变滞后阶数,并标注 AIC 分数(越低越好)。可以仅考虑我们的列车数据来执行该过程。在我们的例子中,27 是最好的延迟顺序。
用 AIC 方法进行 VAR 滞后阶数选择(图片由作者提供)
将 VAR 和 LSTM 结合起来
现在我们的范围是使用我们拟合的 VAR 来改善我们神经网络的训练。VAR 已经了解了我们的多变量数据源的内部行为,调整了疯狂的值,纠正了异常的趋势,并正确地重建了 NaNs。所有这些信息都存储在拟合值中,它们是模型在训练过程中处理过的原始数据的*滑版本。换句话说,我们可以将这些值视为原始列车的一种增强数据源。
我们的策略包括应用两步训练程序。我们使用 VAR 产生的拟合值,开始为我们的 LSTM 自动编码器提供数据,用于我们处理的所有序列的多步预测(多变量输出)。然后,我们用原始数据结束训练,在我们的情况下,它们是我们之前用来拟合 VAR 的相同数据。通过我们的神经网络,我们还可以结合外部数据源,例如,天气状况或一些时间属性,如我们循环编码的工作日、小时和月。
我们希望我们的神经网络可以从两个不同但相似的数据源中学习,并在我们的测试数据上表现得更好。我们的方法听起来很棒,但这不是“免费的午餐”。在进行多步训练时,我们必须注意 灾难性遗忘 的问题。灾难性遗忘是很多模型和算法面临的问题。当在一个任务上训练,然后在第二个任务上训练时,许多机器学习模型“忘记”如何执行第一个任务。这被广泛认为是神经网络的一个严重问题。
为了避免这个繁琐的问题,整个网络的结构必须进行适当的调整,以提供性能方面的好处。根据这些观察,我们保留了之前培训的最后一部分作为验证。
从技术上讲,网络非常简单。它由一个 seq2seq LSTM 自动编码器构成,可以提前 N 步预测未来可用的传感器。使用keras-hype tune执行训练程序。该框架以非常直观的方式提供了神经网络结构的超参数优化。对所有三个涉及的训练(对 VAR 拟合值的拟合、对原始数据的微调拟合和直接对原始数据的标准拟合)都进行了这一步。
最后,我们可以将根据 VAR 的拟合值加上原始数据训练的模型与仅根据原始训练数据训练的相同结构进行比较。在大多数情况下,当我们执行两个训练步骤时,误差较低。我们还报告了使用基线获得的性能,该基线由最*可用观察的简单重复组成。该程序是验证预测是否不是重复的当前值(即不是有用的预测)的良好实践。
测试台上的 RMSE(图片由作者提供)
摘要
在本文中,我们尝试使用 VAR 模型获得的信息来完成一项多变量时间序列任务,以提高经过训练的预测未来的递归神经网络的性能。我们实施了两步训练程序,解决了灾难性遗忘的问题,并提高了整体表现。
查看我的 GITHUB 回购
保持联系: Linkedin
参考文献
基于梯度的神经网络中灾难性遗忘的实证研究
结合贝叶斯神经网络和集成技术
原文:https://towardsdatascience.com/combining-bayesian-neural-networks-and-ensemble-techniques-a4a3a9072e79?source=collection_archive---------28-----------------------
通过利用不确定性使机器学习变得有意义
在机器学习领域,追求越来越大的准确性推动了创新。然而,要使机器学习实用,一个同样重要的特征是能够定义给定预测的不确定性。在本文中,我们将讨论实现这些目标的各种技术,并在文献中给出实践示例,其中选择了这些技术并取得了成功。一般格式是贝叶斯深度学习框架的格式,该框架寻求将集合预测的准确性和稳健性与贝叶斯建模中可用的不确定性估计统一起来。因此,我们将把这一条分成:
技术
地图
集成技术
贝叶斯神经网络
随机地图采样
高斯混合模型
例子
' '用于系外行星大气反演的贝叶斯神经网络集合'
'神经网络中的不确定性:*似贝叶斯集合'
'使用堆叠来*均贝叶斯预测分布'
术语
fᵂ(X) —神经网络模型
p(W|X,y)—nn 权值 w 给定数据 x,Y
p(Y|X,w)—nn 权值 w 来自数据 x,Y
p(W)的最大似然—nn 权值的先验概率
p(Y|X) —数据的边际概率
~N(μ,σ ) —均值为μ且方差为σ的正态分布
N —训练样本大小
M —集合大小
(下面显示的所有等式)
技术
地图
表示为 fᵂ(X 的神经网络(NN)模型由一组相互连接的权重 w 组成,允许我们从输入 x 预测输出 y。这是通过使用梯度下降和使用损失函数 l 的反向传播优化权重来实现的。在统计术语中,这导致给定数据 p(Y|X,w)的权重的频率最大似然估计(MLE)。
最大后验概率估计 使用神经网络的另一种方法是最大化最大后验概率(MAP)估计。换句话说,这就是找到最好地解释我们的数据的参数, p(W|X,Y) 。这可以使用贝叶斯规则来发现:p(W|X,Y) = p(Y|X,W)p(W)/p(Y|X)。如果我们针对 p(W|X,Y)进行优化,我们可以忽略归一化的 p(Y|X)并将其重新表述为针对 p(W|X,Y) 进行优化,这相当于针对 p(Y|X,W)p(W)进行优化。我们必须对 p(W)部分的权重进行先验分布,这是我们的先验信念(如果这是一致的,我们可以观察到我们的 MAP 和 MLE 估计是相同的)。在实践中,这相当于在我们的损失函数中增加正则化项来训练神经网络(L2 项相当于高斯先验,L1 相当于拉普拉斯先验),如这里的所示。这给了我们地图点估计预测。*
集成技术
集成技术包括训练多个模型(弱学习者)来解决同一问题,然后将这些模型组合起来以获得更好、更稳健的预测,这些预测具有更低的方差和/或更低的偏差。它们可以大致分为三种不同类型训练过程:装袋,助推和堆叠。
打包包括在 N 个不同的子数据集上不同次数地训练相同的基础模型 N 。这些子数据集是使用自举采样方法从初始数据集生成的。这有效地随机采样具有替换的初始较大数据集(确保采样的子数据集的大小足够小于初始数据集)。根据模型,从初始数据集中选择用于训练的特征也可以进行引导采样。为了对输入进行预测,这 N 个不同的模型都根据输入进行各自的预测,然后将得到的 N 个不同的预测进行*均。
Boosting 类似于 bagging,但是由顺序训练 N 个(相同基础)模型组成。每一个连续的模型都集中在先前模型错误预测的数据上。最终的集合由所有弱学习者组成,每个弱学习者根据他们的表现被适当地加权。例子包括 adaboost 和梯度增强。
Bagging 并不昂贵,因为它可以并行训练,而 boosting 由于其持续改进而导致较低的偏差。
堆叠包括训练不同的基础模型,然后通过将它们传递到另一个“元模型”来组合它们的预测,从而产生我们的最终预测。我们将初始数据集分成一个用于训练弱学习者的数据集和另一个弱学习者预测的数据集,元模型训练弱学习者的预测,以最终输出单个预测。
详细的精彩讲解可以在这里找到。
贝叶斯神经网络
在神经网络中进行回归预测时,典型的用例是点估计。然而,对此的一个非常有用的补充扩展是,也能够衡量我们在预测中的自信或不确定程度。为此,我们利用了贝叶斯神经网络(BNN)。
不确定性类型 我们先来讨论一下不确定性的不同类型。有两种类型的不确定性:任意的和认知的。随机不确定性来自于数据集中固有的噪声,因此对于给定的 x 值,我们可能会得到多个 y 值(y 值的分布)。随机不确定性可分为两种类型:不确定性水*在所有 x 值上保持不变(同方差)或不确定性水*在 x 值上变化(异方差),如下所示。
还存在认知上的不确定性,这种不确定性来自于我们建模的不足。这可以通过更好的建模和更多的数据来改善。
不同类型不确定性的完整解释可以在这里找到。
对认知不确定性建模 为了对认知不确定性建模,我们使用了一个 BNN,我们现在将对其进行解释。这类似于神经网络,除了代替精确的参数,我们的权重 W 现在被建模为分布。
现在在常规的神经网络中,我们首先初始化我们的权重,然后求解一个优化任务来得到我们的最终权重。然而,在 BNN(我们也将表示为 fᵂ(X))中,最初我们在我们的权重上放置一个先验分布(通常是高斯先验),p(W)。然后,我们执行贝叶斯推断,从贝叶斯定理中找到权重 p(W|X,Y)的后验分布,如下所示。
注意这里 p(Y|X,W)是我们的可能性。为了得到 p(Y|X ),我们需要在所有可能的权重上*均我们的可能性(边缘化),从而得到积分。
然而,在 BNN 中获得后验分布 p(W|X,Y)通常是困难的,因此我们使用*似方法来尝试解决这个问题。变分推理就是这样一种方法。这包括将由θ参数化的简单分布 q(W)拟合到后验分布。因此,这用简单分布参数的优化任务代替了难以处理的边缘化,该优化任务最好地最小化 q(W)和真实模型后验 p(W|X,Y)之间的 KL 散度。
一个示例实现方法是丢弃变分推断。这里,为了*似后验分布,我们建立了 NN 模型,以在每个权重层中包括丢失单元 ⁴(这将权重随机设置为 0 或 1)。然后正常训练神经网络。然而,对于预测,我们再次使用 dropout(称为 monte carlo dropout)将一些权重随机设置为 0,这让我们可以从*似的后验样本中进行采样。这里的和 ⁵表明,像这样使用漏失等价于对 q*(W)使用伯努利分布的变分推断。这种情况下的损失函数是:
这里 N 是数据点的数量,漏失概率用 p 表示,θ是简单分布参数。我们的权重是从我们的简单分布 Wᵢ ~ q*(W)中抽取的。
建模异方差随机不确定性 为了建模随机不确定性,我们可以只使用一个正常的神经网络。然而,我们不是仅仅预测我们的输出 Y,而是通过将我们的输出改变为我们的*均值μ(本质上是正常的神经网络预测)和我们的方差σ来预测分布。分布方差σ让我们了解不确定性的水*。对于异方差,这个方差取决于输入,σ(Xᵢ).我们像往常一样用修正的损失函数训练神经网络:
还可以添加重量衰减 L2 正则化项。
要注意的一个关键点是,我们只是在这里执行正常的优化,而不是变分推理。这产生了我们的模型权重 W 的地图点估计,而不是之前看到的分布 q*(W)。
建模认知和随机不确定性 在这种情况下,我们将使用异方差神经网络,并将其转化为 BNN,或者换句话说,我们将神经网络的权重建模为分布。我们的模型需要推断权重的后验分布,该分布将我们的输入 X 映射到输出(预测 y/μ和方差σ)。我们用损失函数训练这个 BNN:
这类似于纯粹的任意神经网络。d 是样本数,yᵢ是实际产量,戴帽子的 yᵢ是预测产量,戴帽子的σᵢ是预测方差。当实现这个损失函数时,我们对其进行处理,以使我们预测 sᵢ而不是σᵢ:= logσᵢ为:
这是因为该损失函数在训练时被证明在数值上更加稳定,因为它避免了被零除。损失由两部分组成:第一部分是利用参数的不确定性通过模型输出的随机样本获得的均方残差,第二部分是不确定性正则化。我们不需要指定不确定性标签,因为模型从成本函数中隐含地学习了这一点。第二项防止网络预测无限的不确定性,因此零损失。
因此,我们得到[y,σ ]的 T 个样本,每个样本从*似分布 q(W)中抽取权重 W~q(W ),总方差由下式给出:
一个很好的讨论可以在这里 ⁶.找到
随机地图抽样
在随机地图抽样中,我们的目的是尝试使用神经网络的集合来预测后验分布,并对认知不确定性进行建模。我们可以像往常一样想象我们的神经网络,我们称之为 fᵂ(X).然而,为了找到我们的模型权重,不是仅仅使用正常的映射损失函数(通常是 L2 正则化损失函数)来训练神经网络,我们还将噪声添加到我们的损失项中。
我们使用噪声损失函数的每个不同实例来训练多个模型,这为每个模型提供了不同的优化权重。因此,当使用所有模型进行预测时,我们得到了一个地图解的分布,它估计了我们的真实输出分布。现在,我们必须考虑如何将噪声添加到我们使用马尔可夫链蒙特卡罗(MCMC)程序的问题中。
首先让我们陈述这个问题。为了便于解释,我们将假设一个多元正态 n(μₚᵣᵢₒᵣ,σₚᵣᵢₒᵣ),n(μₗᵢₖₑ,σₗᵢₖₑ).的先验分布和概率在这种情况下,为了求解μₚₒₛₜ,存在一个标准解:
我们必须添加噪声,以使约束 var(μₚₒₛₜ=σₚₒₛₜ得以实施,或者换句话说,我们的输出分布的均值方差等于输出分布的方差。实际上,我们通过将μₚᵣᵢₒᵣ(我们先前分布的*均值)建模为随机噪声变量θ₀来注入这种噪声,导致损失函数如下:
对于足够宽的 NN,这里显示了⁷,我们的符合约束的随机噪声变量可以有效地建模为θ₀~ n(μₚᵣᵢₒᵣ,σₚᵣᵢₒᵣ).
高斯混合模型
高斯混合模型(GMM)是一种在整个数据集中参数化正态分布子集的方法。因此,这是一种无监督学习的形式。在我们的情况下,我们可以考虑两种不同的情况。
这方面的一个例子是考虑男性和女性的一组正态分布的权重。仅给出体重数据而不给出性别归属,我们可以发现总体分布是两个缩放(方差变化)和移位(均值变化)正态分布的总和,这是 GMM 模型的一种形式。因此,我们的 GMM(数学模型如下所示)由两种类型的值参数化:分量权重和分量均值和方差。
图片取自https://brilliant.org/wiki/gaussian-mixture-model/
我们的 GMM 概率记为 p(x)。在上面的第一行中,我们可以看到这被建模为多个正态分布(我们的组件)的加权和。第二行只是定义了经典的正态分布公式,第三行给出了我们对权重的约束,这样它们加起来就是一。
GMM 建模的任务是计算其成分权重ϕᵢ、成分均值、μᵢ和成分方差σᵢ.如果组件权重未被学习,则它们可以被视为组件上的先验分布,如 p(由组件 Cₖ生成的 x)= ϕₖ.如果它们是已知的,那么它们就是给定数据的分量概率的后验估计。
为了学习模型的权重,我们使用了最大似然技术,称为期望最大化。EM 算法如下所示:
图片取自 https://brilliant.org/wiki/gaussian-mixture-model/
作为算法的开始,我们从数据集中随机分配样本,不替换我们的分量均值估计μ₁….μₖ并将所有分量方差估计值设置为样本方差:
我们还将所有组件权重设置为均匀分布= 1/K,其中 K 是组件的数量。
然后,在如上所述的期望步骤中,我们找到给定其当前参数 p(Cₖ|xᵢ,ϕᵢ,μᵢ,σᵢ).的每个数据点的每个分量的期望然后,在最大化步骤中,我们根据模型参数ϕᵢ、μᵢ和σᵢ.最大化这些期望值
这个概念在这里⁸.得到了更充分的解释
例子
用于系外行星大气反演的贝叶斯神经网络集成
摘自论文 Cobb et al. 2019 ⁹的一个例子显示了上述实施的各种技术的组合,证明是成功和最先进的。在论文中,他们试图说明认知和随机的不确定性。
首先,他们使用输出均值和协方差矩阵的 BNN(以模拟随机不确定性),其架构为 4 个密集的混凝土脱落层,每层由 1024 个单元组成。批量大小为 512,使用了 adam 优化程序。负对数似然损失函数与训练期间保存的早期停止和最佳检查点一起使用。这些模型中的 5 个然后被用于整体*均过程。
让我们讨论一些细微差别。首先,在 BNN 的权重上假设高斯先验。在训练过程中,蒙特卡罗下降*似用于变分推断,这允许宽 NN 层。在预测阶段,它们通过网络向前传播 T 次,以获得 T 个预测,形成我们的经验输出分布,该分布封装了我们的认知不确定性。使用混凝土脱落层,这是一种技术,此处⁰解释了这种技术,它有效地优化了每层中要脱落的单元的比例。
然后将其整合到 5 个模型(5 个通过经验性能选择)的集合中,以增加其对权重初始化和优化路径的鲁棒性。当每个集合预测一个分布时,通过使用元高斯混合模型将它们组合在一起,其中每个分量的权重等于 1/M,其中 m 是给出最终输出分布为σₑₙₛ).θₑₙₛ~n(μₑₙₛ的模型的数量通过*均所有分量的*均值,并使用总方差的定律,可以得到μₑₙₛ,σₑₙₛ为:
‘神经网络中的不确定性:*似贝叶斯集合’
摘自论文 Pearce et al. 2018 ⁴的一个例子展示了应用集成方法来模拟贝叶斯技术的能力。总的来说,集成方法不遵循任何正式的贝叶斯建模技术。
第一步是将我们的机器学习从 MLE 重新表述为映射问题,这将我们引向正则化的损失函数:
然后,我们实现上述随机 MAP 采样方法,其中我们假设我们将噪声添加到我们的先验分布中,从而得到上述锚定损失函数。
这种随机映射采样方法是用 100 个单元的单层神经网络运行的。少量的神经网络就足够了,因为我们在参数空间而不是输出空间进行推理,输出空间需要相对较少数量的集成神经网络。在论文测试中,随机地图抽样被证明是黄金标准(高斯过程和哈密顿蒙特卡罗)贝叶斯推断的良好*似。与不考虑相关性的*均场变分推断或 MC 丢失相比,它有过度预测方差的趋势,但在捕捉插值区域的不确定性方面表现更好。对于实际的图和结果,请参考上面的文章链接。
这证明了该方法的有效性,特别是其简单性及其与神经网络正常工作的相似性,增加了围绕来自先验分布的值进行正则化和使用集成技术进行重新采样的复杂性。
‘使用堆叠来*均贝叶斯预测分布’
摘自 Yao 等人 2018 的一个例子试图将点估计文献中通常使用的叠加方法与预测分布的贝叶斯建模相结合,并将其有效性与通常的贝叶斯模型*均(BMA)进行比较。
问题公式化如下,给定遵循多维分布的数据集 X,然后我们可以从一系列候选模型中生成一个新模型,该模型将预测尽可能接*真实输出数据生成分布的输出分布 Y。这个问题包括三种不同的情况。
- M-closed:真正的数据生成模型存在于我们的候选模型列表中, M = (M₁,….,Mₖ).
- M-complete:真实的输出数据生成分布不在我们的列表中,但是我们知道这一点并选择我们的候选模型,因为真实的模型是难以处理的。
- M-open:真正的数据生成模型对我们来说是未知的,因为它可能在概念上或计算上太困难了。
作为对最基本的 BMA 类型的一行总结,对于一个给定的数据点,它从一系列候选模型中挑选一个能最好地预测它的模型。然而,这通常是浪费知识和不稳定的,并且适合于 M-闭的情况。
堆叠使用候选模型列表, M ,并获得每个模型的每个数据点的 LOO 预测(留一预测:在除一个数据点之外的所有数据点上拟合一个模型,并在其上进行预测)。然后,通过获得所有模型预测的加权和,将这些模型组合起来进行预测。通过最小化 LOO 评分规则来确定为每个模型生成的权重:
k 迭代模型,I 迭代数据点。这个等式表明,我们找到了使模型的加权和与实际输出之间的残差最小化的最佳权重。然后,预测由模型的加权和给出:
为了将此转化为预测分布的叠加,我们需要首先提出一个评分规则。
评分规则 评分规则是作用于概率空间和整数的一些函数,并返回关于概率空间预测整数的程度的值。评分规则的例子包括:二次评分、对数评分、连续排名概率评分、能量评分以及取决于分布的一阶和二阶矩的评分规则。二次和对数计分的分数由下式给出:QS(p,y)= 2p(y)-||p||₂和 LogS(p,y) = log(p(y))。
广义堆叠问题可以表述为:
根据分布和它试图估计的点之间的一些评分规则标准,预测 C 是最优的,并且遵循模型权重总和应该为 1 并且模型权重必须为非负的约束。
在我们的例子中,我们通过用 LOO 预测分布替换预测分布 p(yₒᵤₜ|y,Mₖ来使用评分规则的 LOO 版本。我们可以这样做,因为对于样本大小→ ∞,LOO 预测分布和完全预测分布的得分之间的 L2 误差趋于零,因此证明堆叠渐进地给出了权重的最佳组合。然而在实践中,LOO 仍然过于繁重,因此使用了 PSIS-LOO ( 帕累托*滑重要性采样 ⁴)。
举一个例子,如果我们将此应用于一种情况,例如试图预测一个形式为 y~n(3.4,1)的真实基础模型,该模型具有形式为 n(μₖ,1(1≤k≤8)的 8 个候选解。BMA 会在 k = 3 时选择单一模型,叠加总会给我们 1/nσⁿᵢ₌₁yᵢ.对于预测分布结果的叠加,我们需要根据损失和约束条件优化权重:
该论文表明,这完全优于均方误差训练点估计预测。这表明在 KL 散度上接*的两个分布在每个时刻都是接*的,而反之则不一定。这说明了匹配分布而不是匹配矩(如均值)的必要性。
结论
总的来说,这篇文章试图展示一种不同的方法在处理机器学习问题上的理论可能性和实践合理性。
[1] J. Brownlee ,《机器学习的最大后验概率(MAP)的温柔介绍》(2019),https://machinelingmastery . com/Maximum-A-posterior-estimation/
【2】j . Rocca,《集成方法:装袋、助推和堆叠》(2019),https://towardsdatascience . com/Ensemble-methods-bagging-boosting-and-stacking-c 9214 a10a 205】劳曼《贝叶斯神经网络中的不确定性告诉你什么》(2019)https://towards data science . com/What-unabilities-tell-you-in-Bayesian-Neural-Networks-6 FBD 5 f 85648 e
【4】C。Ranjan ,用背后的简化数学理解辍学(2019),https://towardsdatascience . com/Simplified-Math-behind-Dropout-in-Deep-Learning-6d 50 F3 f 47275
【5】y . Gal, Z. Ghahramani ,带伯努利*似变分推理的贝叶斯卷积神经网络(2016),https://arxiv.org/abs/1506.02158
(2017),https://arxiv.org/abs/1703.04977
【7】t .皮尔斯,M .扎基,a .尼利,贝叶斯神经网络系综(2018),http://bayesiandeeplearning.org/2018/papers/78.pdf
j .麦戈纳格, G .皮林, A .多布尔,【2020】,https://brilliant.org/wiki/gaussian-mixture-model/
【9】科布,亚当 系外行星大气反演的贝叶斯神经网络集成(2019 年),https://arxiv.org/abs/1905.10659
【10】y . Gal, J. Hron , A. Kendall ,Concrete Dropout(2017 年),https://arxiv.org/abs/1705.07832
【11】全方差直觉定律 (2016 年),https://math . stac A. Vehtari , D. Simpson , A. Gelman ,https://arxiv.org/abs/1704.02030
【14】a . Vehtari, D. Simpson , A. Gelman , Y .姚,
使用 Pandas 合并数据帧
原文:https://towardsdatascience.com/combining-dataframes-using-pandas-b9e2e83b9869?source=collection_archive---------13-----------------------
关于 concat 和 merge 函数的完整教程
照片由派恩瓦特在 Unsplash 上拍摄
Pandas 是一个高效且广泛使用的数据分析工具。Pandas 的核心数据结构是DATA frame,它以表格的形式表示数据,带有标记的行和列。DataFrame 有许多强大而灵活的功能和方法,可以简化和加快数据清理和分析过程。
注意:键入“DataFrame”可能不是正确的英语,但它在 Pandas 语法中作为 DataFrame 存在。因此,在这篇文章中,我将把它写成 DataFrame,这样你就会习惯了。如果您将其键入为“dataframe”或“Dataframe ”,将会出现错误。
数据科学项目通常需要我们从不同的来源收集数据。因此,作为数据准备的一部分,我们可能需要组合数据框架。在这篇文章中,我将解释组合数据帧的不同方法。
让我们首先创建两个数据帧:
串联
组合或连接数据帧的一种方法是 concat() 函数。通过改变轴参数,它可用于沿行或列连接数据帧。axis 参数的默认值为 0,表示沿行组合。
正如您在上面的第一张图中所看到的,保留了各个数据帧的索引。为了改变它并重新索引组合数据帧, ignore_index 参数设置为真。
concat()函数的 join 参数决定如何组合数据帧。默认值为“outer ”,返回两个数据帧中的所有索引。如果选择了' inner '选项,则只返回具有共享索引的行。我将改变 df2 的索引,以便您可以看到“内部”和“外部”的区别。
join =“内部”vs join =“外部”
Pandas 还提供了标记数据帧的方法,以便我们知道哪个部分来自哪个数据帧。我们只是使用键参数按顺序传递组合数据帧列表。
它还使得方便地访问数据帧的不同部分变得更加容易:
关于 concat()函数的一个重要注意事项是,它制作了数据的副本。为了防止进行不必要的复印,需要将复印参数设置为假。默认值为 True。
append() 函数也用于组合数据帧。它可以被看作是 concat()函数的一个特例(axis=0,join='outer '),所以我不会详细讨论它,而只是给出一个例子来展示语法。
合并
组合数据帧的另一个广泛使用的函数是 merge() 。Concat()函数只是将数据帧一个接一个地相加或并排相加。它更像是附加数据帧。Merge()根据共享列中的值组合数据帧。与 concat()函数相比,Merge()函数提供了更多的灵活性。看到例子就更清楚了。
让我们先来看看初始数据帧:
上的参数选择用于合并的列或索引级别。
列名不必相同。我们关注的是列中的值。假设两个数据帧在一个列中有共同的值,您希望使用该列来合并这些数据帧,但是列名不同。在这种情况下,可以使用 left_on 和 right_on 参数,而不是 on 参数。为了显示差异,我将在 df2 中更改列名,然后使用 merge:
尽管 column_a 和 new_column_a 中的返回值是相同的,但由于具有不同的名称,合并的数据帧包括这两个列。
您也可以将多个值传递给参数上的。返回的数据帧只包括在所有传递给参数上的的列中具有相同值的行。
df1 和 df2 是根据 column_a 中的公共值合并的,是时候介绍一下howmerge()的参数了。顾名思义,表示你想怎么组合。how 的可能值为“内部”、“外部”、“左侧”、“右侧”。
- 内部:只有在参数上的指定的列中具有相同值的行(如何参数的默认值)
- 外部:所有行
- 左侧:左侧数据帧中的所有行
- 右侧:右侧数据帧中的所有行
“如何”的概念在下图中更加清晰。如果您熟悉 SQL,其逻辑与 SQL 连接相同。
下面的数字更清楚地代表了参数的概念。
outer ',' left '和' right '选项包括不在其中一个数据帧中的数据。缺少的零件自动用 NaN 值填充。NaN 是熊猫缺失价值观的典型代表。
如何= '内在'
how 的默认值是“inner ”,因此您不必在函数中显式编写。“Inner”只返回 column_a 中具有公共值的行。
如何= '外部'
当 how 参数选择' outer '时,合并的数据帧包括两个数据帧中 column_a 的所有值。但是,公共值(column_a = 1 和 column_a = 2)不会重复。
怎么= '左'
当 how 参数选择' left '时,合并数据帧包括左侧数据帧中所有行。如果 column_a(传递给 on 参数的列)中的值不在右数据帧中,则右数据帧中的列将填充 NaN 值。很少使用“right”选项,因为您只能在 merge 函数中更改数据帧的顺序(而不是(df1,df2)使用(df2,df1))。
您可能已经注意到,两个数据帧中相同的列名会添加一个后缀。区分哪一列来自哪一个数据帧是很有用的。您可以使用后缀参数指定要添加的后缀。
感谢您的阅读。如果您有任何反馈,请告诉我。
我的其他帖子
- 朴素贝叶斯分类器——解释
- 支持向量机—解释
- 决策树和随机森林——解释
- 梯度增强决策树—解释
- 用熊猫处理缺失值
- 用机器学习预测二手车价格
- 数据清理和分析,附带奖励故事
结合逻辑回归和决策树
原文:https://towardsdatascience.com/combining-logistic-regression-and-decision-tree-1adec36a4b3f?source=collection_archive---------19-----------------------
安杰伊·西曼斯基
降低逻辑回归的线性度
逻辑回归是最常用的机器学习技术之一。它的主要优点是结果清晰,并且能够以简单的方式解释从属特征和独立特征之间的关系。它需要相对较少的处理能力,并且通常比随机森林或梯度增强更快。
然而,它也有一些严重的缺点,主要是它解决非线性问题的能力有限。在本文中,我将演示如何通过将决策树合并到回归模型中来改进非线性关系的预测。
这个想法与证据权重非常相似,这是一种在金融领域广泛用于构建记分卡的方法。WoE 采用一个特征(连续的或分类的),并将其分成多个带,以最大限度地区分商品和坏商品(正面和负面)。决策树执行非常类似的任务,将数据分成节点,以实现积极和消极之间的最大隔离。主要区别在于,WoE 是为每个特征单独构建的,而决策树的节点同时选择多个特征。
我们知道决策树善于识别从属和独立特征之间的非线性关系,因此我们可以将决策树的输出(节点)转换为分类变量,然后通过将每个类别(节点)转换为虚拟变量,将其部署在逻辑回归中。
在我的专业项目中,在 1/3 的情况下,在模型中使用决策树节点会优于逻辑回归和决策树结果。然而,我一直在努力寻找任何可以复制它的公开数据。这可能是因为可用的数据只包含少数预先选择和清理的变量。根本没多少可挤的!当我们有成百上千的变量可供支配时,找到从属特征和独立特征之间关系的其他维度就容易得多。
最后,我决定使用来自银行活动的数据。使用这些数据,我已经设法得到了一个次要的,但仍然是一个改进的组合逻辑回归和决策树超过这两种方法单独使用。
导入数据后,我做了一些清理。本文使用的代码是 GitHub 上的可用的。我已经将清理后的数据保存到一个单独的文件中。
由于频率较小,我决定使用 SMOTE 技术对数据进行过采样。
import pandas as pd
from sklearn.model_selection import train_test_split
from imblearn.over_sampling import SMOTEdf=pd.read_csv('banking_cleansed.csv')
X = df.iloc[:,1:]
y = df.iloc[:,0]os = SMOTE(random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
columns = X_train.columns
os_data_X,os_data_y=os.fit_sample(X_train, y_train)
os_data_X = pd.DataFrame(data=os_data_X,columns=columns )
os_data_y= pd.DataFrame(data=os_data_y,columns=['y'])
在接下来的步骤中,我构建了 3 个模型:
- 决策图表
- 逻辑回归
- 具有决策树节点的逻辑回归
决策树
如果你想和逻辑回归结合,保持决策树深度最小是很重要的。我希望决策树的最大深度为 4。这已经给出了 16 个类别。太多的类别可能会导致基数问题,并使模型过拟合。在我们的示例中,深度 3 和 4 之间的可预测性增量很小,因此我选择最大深度= 3。
from sklearn.tree import DecisionTreeClassifier
from sklearn import metrics
from sklearn.metrics import roc_auc_scoredt = DecisionTreeClassifier(criterion='gini', min_samples_split=200,min_samples_leaf=100, max_depth=3)
dt.fit(os_data_X, os_data_y)
y_pred3 = dt.predict(X_test)print('Misclassified samples: %d' % (y_test != y_pred3).sum())
print(metrics.classification_report(y_test, y_pred3))
print (roc_auc_score(y_test, y_pred3))
下一步是将节点转换成新的变量。为此,我们需要编写决策树规则。幸运的是,有一个程序可以帮我们做到这一点。下面的函数产生了一段代码,它是决策树拆分规则的复制。
现在运行代码:
tree_to_code(dt,columns)
输出如下所示:
现在,我们可以将输出复制并粘贴到下一个函数中,用它来创建新的分类变量。
现在,我们可以快速创建一个新变量(“节点”)并将其转移到虚拟变量中。
df['nodes']=df.apply(tree, axis=1)
df_n= pd.get_dummies(df['nodes'],drop_first=True)
df_2=pd.concat([df, df_n], axis=1)
df_2=df_2.drop(['nodes'],axis=1)
添加节点变量后,我重新运行 split 来训练和测试组,并使用 SMOTE 对训练数据进行过采样。
X = df_2.iloc[:,1:]
y = df_2.iloc[:,0]os = SMOTE(random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
columns = X_train.columns
os_data_X,os_data_y=os.fit_sample(X_train, y_train)
现在,我们可以运行逻辑回归,并比较虚拟节点对可预测性的影响。
排除虚拟节点的逻辑回归
我已经创建了一个所有功能的列表,不包括虚拟节点:
nodes=df_n.columns.tolist()
Init = os_data_X.drop(nodes,axis=1).columns.tolist()
并使用初始化列表运行逻辑回归:
from sklearn.linear_model import LogisticRegression
lr0 = LogisticRegression(C=0.001, random_state=1)
lr0.fit(os_data_X[Init], os_data_y)
y_pred0 = lr0.predict(X_test[Init])print('Misclassified samples: %d' % (y_test != y_pred0).sum())
print(metrics.classification_report(y_test, y_pred0))
print (roc_auc_score(y_test, y_pred0))
带节点虚拟模型的逻辑回归
在下一步中,我重新运行回归,但是这次我包含了节点虚拟对象。
from sklearn.linear_model import LogisticRegression
lr1 = LogisticRegression(C=0.001, random_state=1)
lr1.fit(os_data_X, os_data_y)
y_pred1 = lr1.predict(X_test)print('Misclassified samples: %d' % (y_test != y_pred1).sum())
print(metrics.classification_report(y_test, y_pred1))
print (roc_auc_score(y_test, y_pred1))
结果比较
具有虚拟节点的逻辑回归具有最好的性能。尽管增量改进并不巨大(尤其是与决策树相比),但正如我之前所说,很难从只包含少量预选变量的数据中挤出任何额外的东西,我可以向您保证,在现实生活中,差异可能会更大。
我们可以通过使用模型提升来比较正面和负面在十分位数分数上的分布,对模型进行更多的审查,我在我的上一篇文章中已经介绍过了。
第一步是获得概率:
y_pred0b=lr0.predict_proba(X_test[Init])
y_pred1b=lr1.predict_proba(X_test)
接下来我们需要运行下面的函数:
现在我们可以检查这两个模型之间的差异。首先,我们来评估一下没有决策树的初始模型的性能。
ModelLift0 = lift(y_test,y_pred0b,10)
ModelLift0
在应用决策树节点之前提升模型…
…接下来是带有决策树节点的模型
ModelLift1 = lift(y_test,y_pred1b,10)
ModelLift1
具有决策树节点的模型的前 2 个十分位数的响应有所改善,Kolmogorov-Smirnov 测试(KS)也是如此。一旦我们将提升转化为财务价值,这种最小的增量改进可能会在我们的营销活动中产生可观的回报。
总的来说,逻辑回归和决策树的结合不是一个众所周知的方法,但它可能优于决策树和逻辑回归的单独结果。在本文给出的例子中,决策树和第二逻辑回归之间的差异可以忽略不计。然而,在现实生活中,当处理未加工的数据时,结合决策树和逻辑回归可能会产生更好的结果。这在我过去管理的项目中相当常见。节点变量可能不是魔棒,但绝对是值得了解和尝试的东西。
结合医学和数据科学来预测心脏病
原文:https://towardsdatascience.com/combining-medicine-and-data-science-to-predict-heart-disease-f2e0ad92485f?source=collection_archive---------54-----------------------
裘德·贝克在 Unsplash 上的照片
介绍
这个项目的目的是结合数据科学和医学的原理,开发一个可以预测心脏病的模型。这种模型的优势在于它易于解释,并且与医学文献同步,不像其他机器学习模型产生不可解释的结果。采用这种方法帮助我建立了一个模型,通过筛查 34%的人口就可以预测 84%的心脏病发病率。
根据世卫组织的数据,心脏病(广泛称为心血管疾病或心血管疾病)每年夺去约 1790 万人的生命,占全球死亡人数的 31%。这将心血管疾病列为全球头号死因。[1]
现在,如果我们可以建立一个有意义的模型,仅仅根据一些参数就可以预测病人患心脏病的可能性,会怎么样?这里的‘有意义’这个词很重要。我们不一定想要一个能给我们最高准确率的模型,而是一个包含重要特征并能从医学角度解释的模型。对于这个项目,我使用 Google Colab 来开发我的模型。
资料组
我使用了来自 Kaggle 的“UCI 克里夫兰心脏病”数据集(该数据集最初由 UCI 发布在他们的 ML 知识库中,标题为“心脏病数据集”)。Kaggle 数据集包含 297 名患者的数据、13 个特征和 1 个称为“条件”的二元目标变量(0 =无心脏病,1 =有心脏病)。所有 14 个属性的详细描述已经包含在这里。
第一步:医学文献要说什么?
医学研究强调 5 个因素对预测心脏病最有影响。
- 年龄——年龄增长会增加患心脏病的风险[2]
- 性别——男性比绝经前的女性患心脏病的风险更高。男性和绝经后女性的风险相当。[3]
- 血清胆固醇水*——血清胆固醇水*升高有助于心脏病的发展。[4]
- 血压——高血压或高血压是心脏病发展的巨大风险因素。[5]
- 胸痛——大约 25–50%的心脏病患者患有无症状心肌缺血(SMI),这意味着他们不会感到任何胸部不适。因此,即使没有胸痛也可以表明存在心脏病。[6]
幸运的是,上述所有 5 个因素都作为变量包含在我们的数据集中!让我们快速看一下它们是如何分布的。
图一。顶行:分别为年龄、性别和胆固醇(chol)分布;底部一行:分别为静息血压(trestbps)和胸痛(cp)的分布
观察
- 患者年龄分布广泛,*均约 55 岁。
- 总的来说,在这项研究中,男性(类别= 1)比女性(类别= 0)多。从这个图中可以明显看出,男性比女性更容易患心脏病。患心脏病的男性比不患心脏病的男性多。相反,患心脏病的女性比不患心脏病的女性少得多。
- 血清胆固醇水*分布广泛,*均约为 250 mg/dl。
- 静息血压的分布相当不规律,*均约为 130 毫米汞柱。
- 在患有心脏病的人中,大多数患者是无症状的(类别= 3)。因此,数据支持医学文献。典型心绞痛(类别= 0)、非典型心绞痛(类别= 1)和非心绞痛(类别= 2)形式的胸痛主要由没有心脏病的患者报告。
第二步:用所有 13 个特征运行逻辑回归模型。
我的第一直觉是运行一个包含所有 13 个特征的逻辑回归模型,以检查最具包容性的模型是否也是最具医学意义的模型。我选择了逻辑回归,因为它很容易解释。该模型对测试数据的总体准确率为 86.7%,并能够正确预测 82.9%的患者存在心脏病(预测类别= 1)。很好,对吧?当我看到每个变量的系数时,我非常失望。
图二。13 特征逻辑回归模型结果
第一个系数(-0.03121)对应于年龄变量。就在几分钟前,我们讨论了医学文献如何表明年龄增长会增加患心脏病的风险。既然如此,年龄不应该有一个正系数吗?类似地,空腹血糖的系数为负(-0.41832)。根据医学文献,当 fbs > 100 mg/dL 时(在这种情况下,如果 fbs >120 mg/dL,class = 1;如果 fbs < 120 mg/dL,class = 0),心脏病的风险大大增加[7]。因此,理想情况下,系数的符号应为正。
从医学角度来看,接受一个变量符号不正确的模型是不正确的,即使它是高度准确的。
步骤 3:根据医学文献运行新的逻辑回归模型
既然我已经建立了一个完全基于机器学习的模型,我决定尝试一个更有意义的模型。我想构建一个包含 13 个特征子集的模型,只包括那些符合医学文献的特征。因此,我最终得到了一个逻辑回归模型,根据医学文献,该模型具有 5 个最重要的特征— 年龄、性别、血清胆固醇水*(chol)、静息血压(trestbps)和胸痛(cp) 。
该模型对测试数据的总体准确率为 74.4%,并能够正确预测 75.6%的患者存在心脏病(预测类别= 1)。模型的特征系数和截距如下所示。
图三。五特征逻辑回归模型结果
所有的系数都是正的,正如我们所料!虽然这个模型可能不是最准确的,但它是有意义的,并且可以被任何医疗从业者容易地解释。
第四步:如何使新模型更加可靠?
具有变量子集的新的逻辑回归模型是有意义的,但是低于 13 特征模型的预测能力(82.9%对 75.6%)。
为了克服这些缺点,我们必须用另一个包含所有 13 个特征的 ML 模型来补充它。这种结合将更好地预测病人是否患有心脏病。
我开发了具有所有 13 个特征的 5 ML 模型,下表总结了它们的性能。
图四。所有五个 13 特征模型的结果汇总
虽然逻辑回归恰好是五个模型中最准确的,但基于上面概述的原因(变量的非直观迹象),我有意识地忽略了它。我们最好的选择是选择随机森林模型,该模型对测试数据的总体准确率为 83.33%,并正确预测 78.05%的患者存在心脏病(预测类别= 1)。随机森林(RF)要素重要性图表如下所示。
图 5。随机森林模型特征重要性图表
有趣的是,根据 RF,前 4 个变量是达到的最大心率(thalach)、胸痛(cp)、荧光透视着色的主要血管数量(ca)和心脏缺陷(thal),而我们的逻辑模型的重要特征(年龄、性别、胆固醇、静息血压)则位于底部。这告诉我们,随机森林模型本身不应该被信任,而应该与我们的 5 特征逻辑回归模型结合使用,以获得良好的预测结果。
步骤 5:结合两个模型和最终建议
这一部分讲述了我结合两个分数得出最佳预测的方法。我创建了一个表格,比较模型预测和我们测试数据集中所有真正患有心脏病的患者的实际情况。我在本节中使用的符号也在下面进行了描述。
图 6。使用的符号
图七。比较所有真正患有心脏病的患者的组合模型预测和实际状况的表格
有意思!如果我们仅仅依靠我们的逻辑模型来正确预测心脏病(LH),我们将得到 31/44 或 70.5%的准确率。另一方面,如果我们只依赖我们的随机森林模型(RH),我们将得到 31/36 或 86.11%的准确度分数。RF 得分很高,因为 100%出现在 LLRH 类中,这可能是该类样本量小的结果,即只有 5 名患者。
如果我们依赖两个模型的组合(LHRH),我们最终只选择了 31 名患者(31/90 =我们测试样本的 34%),他们的心脏病发生率是 26/31 或 84%。因此,我们已经能够将命中率从 50%(发现心脏病的几率为 50-50%)提高到 84%,同时确保医学文献的神圣性。该模型是有效的,并且做了很好的预测。
至于逻辑模型和 RF 模型给出冲突预测的类别(LHRL 和 LLRH),需要更多的研究。
结论
在医学领域,最精确的模型可能不是最有意义的,反之亦然。像这样的模型是我们可以将机器学习模型形式的数据科学原理与医学文献相结合的方式的一个例子,以给我们提供可能的最佳结果。这种模型的优点是易于解释,并且与医学文献同步。关于心脏病的准确预测,它已经能够将只筛查 34%人口的命中率从 50%提高到 84%。这种模式可以用于远程医疗,特别是在没有心脏病专家的不发达国家。未来的努力可能需要与心脏病专家合作,在其他医学数据集上工作,并检查这个模型的神圣性。
这个项目的代码可以在这里找到。
参考
《心脏病克利 UCI》数据集上https://www.kaggle.com/cherngs/heart-disease-cleveland-uci?select = heart _ Cleveland _ upload . CSV
数据集原始来源:【https://archive.ics.uci.edu/ml/datasets/Heart+Disease】T4
[1] 心血管疾病世卫组织 (2020 年),https://www . who . int/health-topics/cardio vascular-Diseases/# tab = tab _ 1
[2] R. Dhingra 和 R.S. Vasan,年龄作为心血管危险因素 (2012),https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3297980/
[3] J.L. Sullivan,铁与心脏病风险的性别差异 (2003),https://www . science direct . com/science/article/ABS/pii/s 0140673681924636
[4] W.B. Kannel,W.P. Castelli,T. Gordon 和 p . m . mcn amara,血清胆固醇、脂蛋白和冠心病的风险 (1971),https://www . ACP journals . org/doi/ABS/10.7326/0003-4819-74-1-1
[5] C. Rosendorff,H.R. Black,C.P. Cannon,B.J. Gersh,J. Gore,J.L. IzzoJr,N.M. Kaplan,C.M. O'Connor,P.T. O'Gara 和 S. Oparil,缺血性心脏病预防和管理中的高血压治疗 (2007 年),https://www . aha journals . org/doi/full/10.1161/circulation ha
[6] A.H. Ahmed,K.J. Shankar,H. Eftekhari,M.S. Munir,J. Robertson,A. Brewer,I.V. Stupin 和 S.W. Casscells,无症状心肌缺血:当前观点和未来方向 (2007),https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2359606/
[7] C. Park,E. Guallar,J.A. Linton,D. Lee,Y. Jang,D.K. Son,E. Han,S.J. Baek,Y.D. Yun,S.H. Jee 和 J.M. Samet,空腹血糖水*与动脉粥样硬化性心血管疾病事件的风险 (2013),https://pubmed.ncbi.nlm.nih.gov/23404299/
在深度神经网络中结合数字和文本特征
原文:https://towardsdatascience.com/combining-numerical-and-text-features-in-deep-neural-networks-e91f0237eea4?source=collection_archive---------11-----------------------
如何使用 Keras 多输入模型为文本和数字数据训练一个端到端的深度神经网络
马里乌斯·马萨拉尔在 Unsplash 上的照片
在应用机器学习中,数据通常由多种数据类型组成,例如文本和数字数据。为了建立一个结合两个领域特征的模型,有必要将这些特征堆叠在一起。这篇文章展示了在 Keras(端到端学习)的一个单一模型中结合自然语言处理和传统功能的不同解决方案。
真实世界的数据是不同的
科学数据集通常仅限于一种数据,例如文本、图像或数字数据。这很有意义,因为我们的目标是将新的模型和现有的方法进行比较。在现实世界的场景中,数据通常更加多样化。为了利用端到端学习神经网络,而不是手动堆叠模型,我们需要在神经网络内部组合这些不同的特征空间。
假设我们想要解决一个文本分类问题,并且我们的语料库中的每个文档都有额外的元数据。在简单的方法中,我们的文档由一个单词包向量表示,我们可以将元数据作为附加单词添加到向量中,这样就完成了。但是当使用像单词嵌入这样的现代方法时,就有点复杂了。
特殊代币
简单的解决方案是添加我们的元数据作为额外的特殊嵌入。类似于语言模型中的特殊标记,如 BERT ,这些嵌入是可以像单词一样出现的标记。它们是二元的,因此我们没有连续的值空间。我们需要通过宁滨或一键编码将数据转换成分类特征。在我们确定了我们需要多少额外的特征之后,我们可以根据额外特征的数量来扩展词汇表,并将它们视为额外的单词。
我们的字典有 100 个单词,我们还有 10 个额外的功能。
该图显示了每个序列是如何以编码为特殊嵌入的特征开始的
嵌入序列现在总是从元数据特征(特殊标记)开始,因此我们必须将序列长度增加 10。这 10 个特殊嵌入中的每一个都代表了一个增加的特性。
这种解决方案有几个缺点。我们只有分类特征,没有连续值,更重要的是,我们的嵌入空间混合了文本和元数据。
多输入模型
为了构建一个可以处理连续数据和文本数据而没有这些限制因素的模型,我们来看看模型内部数据的内部表示。在某些时候,每个神经网络都有数据的内部表示。通常,这种表示就在涉及网络的最后(全连接)层之前。对于 NLP 中的递归网络(例如 LSTMs ),这种表示是文档嵌入。通过用我们的附加特征扩展这种表示,我们克服了限制。
在这样的模型中发生的事情是,我们基本上将两个模型堆叠在彼此之上,但是保留由相同的目标标签同时训练的能力。因此,它被称为端到端模型。
举例:
在 Keras 中,这对于多输入模型是可能的。我们又有了 100 个单词和 10 个附加特征。
nlp_input = Input(shape=(seq_length,))
meta_input = Input(shape=(10,))
emb = Embedding(output_dim=embedding_size, input_dim=100, input_length=seq_length)(nlp_input)
nlp_out = Bidirectional(LSTM(128))(emb)
concat = concatenate([nlp_out, meta_input])
classifier = Dense(32, activation='relu')(concat)
output = Dense(1, activation='sigmoid')(classifier)
model = Model(inputs=[nlp_input , meta_input], outputs=[output])
我们使用双向 LSTM 模型,并将其输出与元数据相结合。因此,我们定义了两个输入层,并在不同的“数据路径”中处理它们( nlp_input 和 meta_input )。我们的 NLP 数据经过嵌入变换和 LSTM 层。元数据正在进行一些规范化,所以我们可以直接将它与 LSTM 输出连接起来( nlp_out )。这个组合的向量现在是我们输入的完整表示,并且可以最终被分类在完全连接的层中。
一个简单的多输入模型的结构
这个概念可用于任何其他领域,其中来自 RNNs 的序列数据与非序列数据混合。更进一步,甚至可以将图像、文本和序列混合到一个单一的模型中。
这篇文章最初发表在我的博客上。
在 Tensorflow 中结合众多艺术风格
原文:https://towardsdatascience.com/combining-numerous-artistic-styles-in-tensorflow-6e12a99b103f?source=collection_archive---------61-----------------------
神经类型转换在 Tensorflow 中非常容易,但只有一种类型。了解如何对图像应用多种样式。
安妮·斯普拉特在 Unsplash 上的照片
去年,发布了一篇关于使用 Tensorflow Lite 的艺术风格转换的文章,其中内容图像的风格根据您喜欢的任何风格进行更改。这是超级有趣,非常容易使用。你只需要指定图片的路径就可以了。它使用两个 TfLite 模型,一个用于预测样式,另一个用于转换。
一些图片风格转换的例子。来源。
因此,它在将单一样式传递到内容图像方面非常有效,但是我们如何传递多种样式呢?这就是你将在这篇文章中发现的。
目录
- 艺术风格转移阐释
- 组合样式
- 等量地
- 一个的样式和一个的颜色
- 一个支配另一个
艺术风格转移阐释
在这一节中,我将解释风格转换是如何工作的。如果你已经了解它,只是想结合不同的风格,请随意进入下一部分。进行必要的导入,如 TensorFlow、NumPy 和 Matplotlib。设置内容和样式图像的路径,并下载所需的 Tensorflow Lite 模型。
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['figure.figsize'] = (12,12)
mpl.rcParams['axes.grid'] = False
import numpy as npcontent_path = content.jpg
style_path = style.jpgstyle_predict_path = tf.keras.utils.get_file('style_predict.tflite', 'https://tfhub.dev/google/lite-model/magenta/arbitrary-image-stylization-v1-256/int8/prediction/1?lite-format=tflite')
style_transform_path = tf.keras.utils.get_file('style_transform.tflite', 'https://tfhub.dev/google/lite-model/magenta/arbitrary-image-stylization-v1-256/int8/transfer/1?lite-format=tflite')
加载图像和模型后,我们需要对它们进行预处理。图像应该是 RGB 格式的 float32 值,像素值需要在 0 和 1 之间。样式图像的尺寸应为(1,256,256,3),内容图像的尺寸应为(1,384,384,3)。在 Tensorflow 博客中,宽度和高度的较小维度分别根据样式或内容图像等于 256 或 384,然后在中央裁剪。
# Function to load an image from a file, and add a batch dimension.
def load_img(path_to_img):
img = tf.io.read_file(path_to_img)
img = tf.io.decode_image(img, channels=3)
img = tf.image.convert_image_dtype(img, tf.float32)
img = img[tf.newaxis, :] return img# Function to pre-process by resizing an central cropping it.
def preprocess_image(image, target_dim):
# Resize the image so that the shorter dimension becomes 256px.
shape = tf.cast(tf.shape(image)[1:-1], tf.float32)
short_dim = min(shape)
scale = target_dim / short_dim
new_shape = tf.cast(shape * scale, tf.int32)
image = tf.image.resize(image, new_shape) # Central crop the image.
image = tf.image.resize_with_crop_or_pad(image, target_dim, target_dim) return image# Load the input images.
content_image = load_img(content_path)
style_image = load_img(style_path)# Preprocess the input images.
preprocessed_content_image = preprocess_image(content_image, 384)
preprocessed_style_image = preprocess_image(style_image, 256)print('Style Image Shape:', preprocessed_style_image.shape)
print('Content Image Shape:', preprocessed_content_image.shape)
现在,我们需要使用加载的模型来预测样式图像上的样式。如果你想知道如何在 Python 中使用 Tensorflow Lite,你可以看看这篇文章。创建模型的解释器并获取其输出。样式模型输出一个样式瓶颈,它有一个(1,1,1,100)的形状,我们将对它进行修改以组合多种样式。
# Function to run style prediction on preprocessed style image.
def run_style_predict(preprocessed_style_image):
# Load the model.
interpreter = tf.lite.Interpreter(model_path=style_predict_path) # Set model input.
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
interpreter.set_tensor(input_details[0]["index"], preprocessed_style_image) # Calculate style bottleneck.
interpreter.invoke()
style_bottleneck = interpreter.tensor(
interpreter.get_output_details()[0]["index"]
)() return style_bottleneck# Calculate style bottleneck for the preprocessed style image.
style_bottleneck = run_style_predict(preprocessed_style_image)
print('Style Bottleneck Shape:', style_bottleneck.shape)
在这之后,我们需要在我们的内容图像上应用这个样式瓶颈来改变它的样式,所以我们使用另一个加载的模型。
# Run style transform on preprocessed style image
def run_style_transform(style_bottleneck, preprocessed_content_image):
# Load the model.
interpreter = tf.lite.Interpreter(model_path=style_transform_path) # Set model input.
input_details = interpreter.get_input_details()
interpreter.allocate_tensors() # Set model inputs.
interpreter.set_tensor(input_details[0]["index"], preprocessed_content_image)
interpreter.set_tensor(input_details[1]["index"], style_bottleneck)
interpreter.invoke() # Transform content image.
stylized_image = interpreter.tensor(
interpreter.get_output_details()[0]["index"]
)() return stylized_image# Stylize the content image using the style bottleneck.
stylized_image = run_style_transform(style_bottleneck, preprocessed_content_image)# Visualize the output.
stylized_image = tf.squeeze(stylized_image, axis=0)
plt.imshow(stylized_image)
plt.title('Stylized Image')
这篇文章中的流程图最好地概括了这个过程。
来源
组合样式
我将要处理的图像如下所示。
前两张是文章中的相同图片,第三张取自这里。
任何人对组合它们的第一个猜测都是先应用一种样式,然后在生成的图像上应用第二种样式。让我们看看我们通过它得到的结果。
前两张图片是个人风格。在第三幅图像中,样式 2 应用于第一幅图像
在第三个图像中,样式 1 应用于第二个图像
这样的结果不太好。结果看起来有点笨拙,只有应用于它的最终样式的颜色。所以,让我们来研究一下风格瓶颈,看看会发生什么。
等量地
为了给两种风格以同等的权重,我们可以采用风格瓶颈的*均值。
style_bottleneck = style_bottleneck1.copy()
for i in range(100):
style_bottleneck[0, 0, 0, i] += style_bottleneck2[0, 0, 0, i]
style_bottleneck[0, 0, 0, i] /= 2
通过手段结合他们的风格瓶颈后的结果。
这看起来比我们之前得到的结果更好,而且颜色组合得更好。
一个的样式和一个的颜色
这个结果完全出乎意料,是瞎混的结果。这并不是说其他风格不会像我们获得的第一个结果那样对图像的颜色有任何发言权,在此之后我们继续进行风格瓶颈,但这将是微妙的,并淡化其他风格。将您想要的颜色样式放在所有偶数索引处,将您想要的纹理样式放在奇数索引处。
style_bottleneck = style_bottleneck1.copy()
for i in range(100):
if i % 2 == 0: # change 0 to 1 for second image
style_bottleneck[0, 0, 0, i] = style_bottleneck2[0, 0, 0, i]
第二种款式的颜色和第一种的质地。
第一款的颜色和第二款的质地。
一个支配另一个
我们知道风格瓶颈的大小是(1,1,1,100)。因此,如果我们取一种风格的前 50 个值,取另一种风格的后 50 个值,那么取前 50 个值的风格应该更占优势。
style_bottleneck = style_bottleneck1.copy()
for i in range(50, 100): #change to (50) for second image
style_bottleneck[0, 0, 0, i] = style_bottleneck2[0, 0, 0, i]
风格 1 优于风格 2
风格 2 优于风格 1
我尝试在一张图片中结合两种风格。你可以试着把两个以上的组合起来,看看是什么样子。完整的代码如下所示。
如何使用 SQL 连接表以组合数据集
原文:https://towardsdatascience.com/combining-tables-using-sql-f6ddfd5f8b6f?source=collection_archive---------0-----------------------
在保持社交距离的同时学习数据科学
使用 SQL 关键字 UNION、UNION ALL、INNER JOIN、LEFT OUTER JOIN 和 RIGHT OUTER JOIN 找出澳大利亚哪里的喜鹊最危险
照片由大流士 K 在 Unsplash 上拍摄
介绍
在过去的 4 周里,我和我的朋友们在保持社交距离的同时互相帮助学习新技能。我们正在以在线学习小组的形式学习数据科学。我们几乎完成了 SQL 部分。我为每个人的努力和他们尝试新事物的意愿感到骄傲。
在过去的几周里,我的父母甚至决定尝试一下我的课程。他们只有几周的时间来补上,所以听听他们的想法会很有趣。
前一课
上周,我们利用辣妹组合发行的三张专辑的数据来判断哪张专辑是最好的。我们使用 GROUP BY 关键字这样做,以便我们可以聚合每个专辑的统计数据。
这一课
现在我们知道了如何分组和聚合表中的数据,本周我们将学习如何将表连接在一起。
能够组合数据集是有帮助的。尤其是如果每个表中有不同的细节。通过将它们连接在一起,你可以进行一些计算。或者,您可以创建一个新表,在一个数据集中包含所有不同的详细信息。
为了合并表,我们将使用 UNION、UNION ALL、INNER JOIN、LEFT OUTER JOIN 和 RIGHT OUTER JOIN 关键字。
主要学习内容
- 使用关键字 UNION 堆叠没有重复值的数据集
- 使用关键字 UNION ALL 来堆叠具有重复值的数据集
- 使用关键字 INNER JOIN 将两个表连接在一起,只获得重叠的值
- 使用关键字 LEFT OUTER JOIN 将两个表连接在一起,并且不会丢失左表中的任何数据,即使那些记录在右表中没有匹配项
- 使用关键字 RIGHT OUTER JOIN 将两个表连接在一起,并且不会丢失右表中的任何数据,即使是那些在左表中没有匹配项的记录
- 理解 UNION 和 UNION ALL 关键字的区别
- 理解内部连接、左外部连接和右外部连接之间的区别。
问题是
每个人都知道澳大利亚充满了危险的动物。然而,一种鲜为人知的食肉动物是喜鹊。这种鸟猛扑向毫无防备的受害者,锋利的喙装备精良,可以挖出一只眼睛。我们想知道澳大利亚各州喜鹊攻击事件有多普遍。哪里要戴防护帽?😜
弗兰克·布施在 Unsplash 上的照片
数据
为了解决我们的问题,我们有几个数据表。
首先是一个表格,根据网站喜鹊警报,包含了澳大利亚各州报告的喜鹊攻击数量。需要注意的是,这个网站的数据是众包的。当人们被喜鹊袭击时,他们会自我报告。因此,根据网站最受欢迎的地方,可能会有一些偏差。
喜鹊攻击表
我们的第二组数据是 dropbear 攻击的表格。北极熊是另一种凶猛的澳大利亚动物。我们可以将此表与喜鹊攻击数据进行比较。
免责声明: dropbears 不是真的,所以数据是我编造的😃
Dropbear 攻击表
除了关于动物袭击的两个表格,我们还有我从维基百科获得的澳大利亚各州的数据。我们可以使用这个表来标准化我们的动物攻击表,以反映各州之间的人口或地区差异。
澳大利亚州和地区表
组合表格的语法
将两个表组合在一起的最简单的方法是使用关键字 UNION 或 UNION ALL。这两种方法将一批选定的数据堆积在另一批数据之上。
SELECT
name_column_one,
name_column_three
FROM
name_of_table_one
UNION
SELECT
name_column_one,
name_column_three
FROM
name_of_table_two
;
这两个关键字之间的区别在于 UNION 只接受不同的值,而 UNION ALL 则保留所有选中的值。两者使用相同的语法。
SELECT
name_column_one,
name_column_three
FROM
name_of_table_one
UNION ALL
SELECT
name_column_one,
name_column_three
FROM
name_of_table_two
;
如果您想根据匹配值合并表,该怎么办?
有几种不同的方法可以根据值匹配来组合表。它们包括内部连接、完全外部连接、左外部连接和右外部连接。
在不同版本的 SQL 语言中,可用的连接略有不同。我们一直在学习 MySQL。因此,我们将只关注 MySQL 中可用的连接。在 MySQL 中可以使用内连接、左外连接和右外连接,但不能使用全外连接。
如果你想学习如何做一个完整的外连接,我的另一篇关于 SQL 中的内连接和外连接的区别的文章中有介绍。
如果您只想要两个表都包含匹配值的数据,该怎么办?
如果要执行的联接只包含两个表在指定列中包含匹配值的数据,则可以使用内部联接。
内部连接图:内部连接的结果将只包含 Table_1 和 Table_2 重叠的黄色部分
内部联接只返回两个数据集重叠的部分。这样,只有在两个表中要连接的列中有匹配值时,才会返回记录。内部联接的语法如下所示:
SELECT *
FROM
name_of_table_one
INNER JOIN
name_of_table_two
ON
name_of_table_one.name_column_one = name_of_table_two.name_column_one
在上面的示例中,表一和表二的记录都将被返回,但前提是表一第一列中的值与表二第一列中的值匹配。内部联接不会返回任何没有匹配值的记录。
我们在前面的课程中没有遇到的连接语法的一部分是通过表名和列名来引用列。这在连接表时很重要,因为两个表可能有同名的列。如果在选择同名列时不包括表名,程序将不会知道您引用的是哪一个。
为了避免混淆,我们使用由句号分隔的表名和列名来为每一列创建唯一的标识符。
如果您想连接一个匹配值,但只想保留左侧表中的所有数据,并且只保留右侧表中匹配的记录,该怎么办?
要基于列匹配连接两个表而不丢失左表中的任何数据,可以使用左外连接。
左外部连接图:左外部连接的结果将包含 Table_1 和 Table_2 重叠的黄色部分,以及包含 Table_1 其余部分的黄色部分
当您希望从一个表中获取所有值,但只从右表中获取与左表匹配的记录时,可以使用左外连接。
SELECT *
FROM
name_of_table_one
LEFT OUTER JOIN
name_of_table_two
ON
name_of_table_one.name_column_one = name_of_table_two.name_column_one
在上面左侧的外部连接示例中,将返回表一中的所有行,以及表二和表一中基于每个表中的列一共有的行。
左外连接和右外连接有什么区别?
右外连接图:右外连接的结果将包含 Table_1 和 Table_2 重叠的黄色部分,以及包含 Table_2 其余部分的黄色部分
右外连接的语法与左外连接的语法相同。两者之间唯一的区别是右边的表,在我们的示例表 2 中,将保留它的所有记录。而在左边的表中,表 1 将只保留其第一列和表 2 的第一列匹配的记录。
SELECT *
FROM
name_of_table_one
RIGHT OUTER JOIN
name_of_table_two
ON
name_of_table_one.name_column_one = name_of_table_two.name_column_one
现在让我们试一试
- 前往https://www.db-fiddle.com/
- 在左栏中,将 CREATE TABLE 和 INSERT 放入下面的查询中
CREATE TABLE magpie_attacks(
state_code varchar(255),
state_name varchar(255),
animal varchar(255),
number_of_attacks int(255)
);INSERT INTO magpie_attacks(
state_code,
state_name,
animal,
number_of_attacks
)
VALUES
('SA', 'South Australia', 'magpie', 154),
('VIC', 'Victoria', 'magpie', 972),
('TAS', 'Tasmania', 'magpie', 0),
('NSW', 'New South Whales', 'magpie', 823),
('QLD', 'Queensland', 'magpie', 1141),
('WA', 'Western Australia', 'magpie', 287),
('ACT', 'Australian Capital Territory', 'magpie', 668);CREATE TABLE dropbear_attacks(
state_code varchar(255),
state_name varchar(255),
animal varchar(255),
number_of_attacks int(255)
);INSERT INTO dropbear_attacks(
state_code,
state_name,
animal,
number_of_attacks
)
VALUES
('SA', 'South Australia', 'dropbear', 21),
('VIC', 'Victoria', 'dropbear', 67),
('TAS', 'Tasmania', 'dropbear', 30),
('NSW', 'New South Whales', 'dropbear', 19),
('QLD', 'Queensland', 'dropbear', 40),
('WA', 'Western Australia', 'dropbear', 37)
;CREATE TABLE australian_states(
state_code varchar(255),
state_name varchar(255),
population int(255),
area_km2 int(255)
);INSERT INTO australian_states(
state_code,
state_name,
population,
area_km2
)
VALUES
('SA', 'South Australia', 1751693, 1044353),
('VIC', 'Victoria', 6594804, 237657),
('TAS', 'Tasmania', 534281, 90758),
('NSW', 'New South Whales', 8089526, 809952),
('QLD', 'Queensland', 5095100, 1851736),
('WA', 'Western Australia', 2621680, 2642753),
('ACT', 'Australian Capital Territory', 426709, 2358),
('NT', 'Northern Territory', 245869, 1419630)
;
3.在右栏中输入您的查询,并使用左上角的“运行”按钮运行它们
4.运行下面的查询,看看它是否会返回您所期望的结果:
SELECT
*
FROM
magpie_attacks
UNION
SELECT
*
FROM
dropbear_attacks
;
5.运行下面的查询,看看它是否会返回您所期望的结果:
SELECT
state_code,
state_name
FROM
magpie_attacks
UNION
SELECT
state_code,
state_name
FROM
dropbear_attacks
;
6.运行下面的查询,并将结果与之前的查询进行比较:
SELECT
state_code,
state_name
FROM
magpie_attacks
UNION ALL
SELECT
state_code,
state_name
FROM
dropbear_attacks;
7.运行下面的查询,看看它是否会返回您所期望的结果:
SELECT
magpie_attacks.state_code,
magpie_attacks.number_of_attacks AS magpie_attacks,
dropbear_attacks.number_of_attacks AS dropbear_attacks
FROM
magpie_attacks
INNER JOIN
dropbear_attacks
ON
magpie_attacks.state_code = dropbear_attacks.state_code;
8.运行以下查询,并将结果与之前的查询进行比较:
SELECT
magpie_attacks.state_code,
magpie_attacks.number_of_attacks AS magpie_attacks,
dropbear_attacks.number_of_attacks AS dropbear_attacks
FROM
magpie_attacks
LEFT OUTER JOIN
dropbear_attacks
ON
magpie_attacks.state_code = dropbear_attacks.state_code;
9.运行下面的查询,并将结果与前两个查询进行比较:
SELECT
magpie_attacks.state_code,
magpie_attacks.number_of_attacks AS magpie_attacks,
dropbear_attacks.number_of_attacks AS dropbear_attacks
FROM
magpie_attacks
RIGHT OUTER JOIN
dropbear_attacks
ON
magpie_attacks.state_code = dropbear_attacks.state_code;
10.运行下面的查询,并将结果与前两个查询进行比较:
SELECT
magpie_attacks.state_code,
magpie_attacks.number_of_attacks AS magpie_attacks,
dropbear_attacks.number_of_attacks AS dropbear_attacks,
dropbear_attacks.number_of_attacks / magpie_attacks.number_of_attacks * 100 AS 'dropbear_attacks_as_percentage_of_magpie_attacks'
FROM
magpie_attacks
INNER JOIN
dropbear_attacks
ON
magpie_attacks.state_code = dropbear_attacks.state_code
;
练习 1: 使用我们在本课中学到的每一种不同的 union 和 join 方法,组合 magpie_attacks 表和 australian_states 表。为了运行查询,您可以根据需要随意选择任意多或任意少的列。
练习 2: 写一个查询,找出澳大利亚哪个州的喜鹊攻击次数占该州人口的百分比最高。提示:如果需要,您可以使用步骤 10 中的查询作为参考。
学习回顾
学完本课后,你应该知道:
- 如何使用关键字 UNION 来堆叠没有重复值的数据集
- 如何使用关键字 UNION ALL 来堆叠具有重复值的数据集
- 如何使用关键字 INNER JOIN 将两个表连接在一起,并且只获得重叠的值
- 如何使用关键字 LEFT OUTER JOIN 将两个表连接在一起,并且不丢失左表中与右表不匹配的任何数据
- 如何使用关键字 RIGHT OUTER JOIN 将两个表连接在一起,并且不会丢失右表中与左表不匹配的任何数据
- 理解 UNION 和 UNION ALL 关键字的区别
- 理解内部连接、左外部连接和右外部连接之间的区别。
下一课
下一课将回顾我们在过去 5 课中学到的关于 SQL 的知识。我总是认为练习新技能来巩固课程是个好主意。希望复习课也能让我们以一种更独立的方式使用在课上学到的所有技能。到目前为止,这些练习与之前的例子非常相似。然而,我希望下节课我们将学到的部分内容是如何选择使用什么方法来解决问题。
除了数据,我的另一个爱好是绘画。你可以在 www.katemarielewis.com 找到我的野生动物艺术
社交距离学习数据科学(LDSWSD)系列中的所有课程
[## Ldswsd —走向数据科学
阅读《走向数据科学》中关于 Ldswsd 的文章。共享概念、想法和代码的媒体出版物。
towardsdatascience.com](https://towardsdatascience.com/tagged/ldswsd)
将基于树的模型与线性基线模型相结合以改进外推
原文:https://towardsdatascience.com/combining-tree-based-models-with-a-linear-baseline-model-to-improve-extrapolation-c100bd448628?source=collection_archive---------38-----------------------
实践教程
编写自己的 sklearn 函数,第 1 部分
这篇文章是一个简短的介绍,介绍如何结合不同的机器学习模型以达到实用的目的,在它们的优缺点之间找到一个好的*衡。在我们的例子中,我们将集成一个随机森林,一个非常强大的非线性、非参数的基于树的全能者,一个经典的线性回归模型,一个非常容易解释并且可以使用领域知识验证的模型。
对于许多问题来说,梯度推进或随机森林是最常用的模型。他们经常胜过许多其他模型,因为他们能够学习几乎任何线性或非线性关系。然而,树模型的一个缺点是,它们不能很好地处理新数据,它们通常推断得很差——阅读更多关于这个的内容。出于实际目的,这可能会导致不期望的行为,例如在预测时间、距离或成本时,稍后将对此进行概述。
我们可以快速验证随机森林模型的 sklearn 实现可以很好地学习给定范围(0 到 50)的标识,但是对于训练数据范围之外的值却很失败:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as snsfrom sklearn.ensemble import RandomForestRegressormodel = RandomForestRegressor()X = np.arange(0, 100).reshape(-1, 1)
y = np.arange(0, 100)# train on [0, 50]
model.fit(X[:50], y[:50]);# predict for [0, 100]
## RandomForestRegressor()
plt.ylim(0, 100);
sns.lineplot(X.reshape(-1,), model.predict(X));
plt.show()
树模型很难预测样本外的图像。
与树模型相比,线性模型以不同的方式处理新数据。他们可以很容易地推断预测,但当然也有只学习线性关系的缺点。此外,线性模型允许一个简单的解释,简单地通过查看回归系数,我们实际上可以将其与领域知识进行比较,并实际验证它。
因此,对于一些回归问题,将这两种方法结合起来是有意义的,我们可以用一个例子来详细说明:假设我们想要使用历史数据(包含车辆类型、距离和行驶时间的数据集)来估计不同车辆相对于行驶距离的行驶时间。我们可能会考虑使用线性或非线性模型,这也取决于我们的预期。如果我们的目标是估计自行车的旅行时间,距离的增加会导致时间的比例变化(如果你骑自行车的时间增加一倍,你可能会旅行两倍的距离)。如果我们训练一个线性模型,它将是一个很好的拟合,并且系数表达了距离和时间之间的比例。
但是线性模型的一个缺点是,它可能很难了解其他车辆类型(如汽车)的时间与距离的关系。如果开车旅行的距离增加,我们可能会走高速公路,而不是更短的距离,所以旅行时间的增加可能不再是线性比例的。在这种情况下,非线性模型会表现得更好。然而,如果我们在观察到的行驶汽车距离上训练非线性树模型,它将在新数据上表现不佳,即看不见的距离:如果我们的训练数据仅包含 100 公里的汽车行程,则 200 公里的估计将非常糟糕,而线性模型仍将提供良好的外推估计。
为了解决这个问题,我们可以通过以下方式用线性模型支持树模型:如果树模型的预测离我们的基线线性模型的预测太远,我们默认使用线性模型预测。因此,对于我们的示例:如果 200 公里汽车行驶的非线性模型预测是 2 小时(因为它只看到了 2 小时的汽车行驶),但线性模型预测是 3 小时,我们默认为 3 小时。然而,如果非线性模型的预测与线性模型的验证预测相差不太远(比如说小于 25%),我们就坚持它(因为我们预期它通常会表现得更好)。
编写您自己的组合估计器
在sklearn
中,我们可以通过创建我们自己的估计器以下面的方式实现这一点。请注意,这第一个实现还不符合 sklearn API 标准——我们将在本文末尾根据接口改进这个版本。
我们简单地拟合两个估计量,并使用两个估计量进行预测。然后,我们可以比较两种预测,并相应地调整我们的预测。如果在线性预测的一定范围内,我们将采用树模型预测。除了比较两个模型并选择更合理的预测,我们还可以取两个预测的*均值或以不同方式混合它们。此外,我们可以使用网格搜索优化参数upper
和lower
(为此,我们将需要实现一些进一步的方法,如get_params
和set_params
)。
让我们使用非线性函数f(x)=x+sqrt(x)+rnorm(0, 3)
生成一些样本数据来评估模型:
import pandas as pddef f(x):
if isinstance(x, int):
return np.sqrt(x) + np.random.normal(0, 3)
else:
return np.sqrt(x) + np.random.normal(0, 3, len(x))def generate_data(n=100, x_max=100):
x = np.random.uniform(0, x_max, n)
return pd.DataFrame.from_records({'x': x}), f(x)
我们现在可以在我们的小样本数据集上训练三个不同的模型:RandomForestRegressor
、LinearRegression
和我们的定制CombinedRegressor
。
from sklearn.metrics import mean_absolute_errornp.random.seed(100)
X, y = generate_data(n=100)for model_name, model in models.items():
print(f'Training {model_name} model.')
model.fit(X, y);
print(f'Training score: {model.score(X, y)}')
print(f'In-sample MAE: {mean_absolute_error(y, model.predict(X))} \n')
## Training tree model.
## RandomForestRegressor()
## Training score: 0.8620816087110539
## In-sample MAE: 1.081361379476639
##
## Training linear model.
## LinearRegression()
## Training score: 0.28917115492576073
## In-sample MAE: 2.586843328406717
##
## Training combined model.
## CombinedRegressor()
## Training score: 0.35418433030406293
## In-sample MAE: 2.3593815648352554
如果我们观察所有三个模型预测和真实值的图(见下文),我们可以很快看到最初讨论的问题:树模型不能真正外推
正如所料,随机森林模型在样本内*均绝对误差方面表现最佳。现在,如果我们评估样本外(150,而不是训练数据中的最大值 100),事情看起来会有所不同:
np.random.seed(101)x = [150]
X_new, y_new = pd.DataFrame({'x': x}), f(x)for model_name, model in models.items():
y_pred = model.predict(X_new)
print(f'Testing {model_name} model.')
print(f'y_new: {y_new}, y_pred: {y_pred}')
print(f'Test MAE: {mean_absolute_error(y_new, y_pred)} \n')
## Testing tree model.
## y_new: [20.36799823], y_pred: [7.81515835]
## Test MAE: 12.552839880512696
##
## Testing linear model.
## y_new: [20.36799823], y_pred: [13.39757247]
## Test MAE: 6.970425764867624
##
## Testing combined model.
## y_new: [20.36799823], y_pred: [13.39757247]
## Test MAE: 6.970425764867624
由于不能外推,树模型做得不好,线性模型做得更好,因此由线性回归支持的集合模型做得更好。同时,它仍将在样本内表现良好,并且如果我们大幅增加范围,它将表现良好(仅比树模型好,比线性回归差):
np.random.seed(102)X_new, y_new = generate_data(n=100, x_max=200)for model_name, model in models.items():
y_pred = model.predict(X_new)
print(f'Testing {model_name} model.')
print(f'Test MAE: {mean_absolute_error(y_new, y_pred)} \n')
## Testing tree model.
## Test MAE: 3.67092130330585
##
## Testing linear model.
## Test MAE: 2.5770058863460985
##
## Testing combined model.
## Test MAE: 2.6143623109839984
我们还可以绘制一些随机数据(训练样本内外)的单个预测,并快速查看之前未看到的 x 值和树模型的初始讨论问题,该问题变*了。线性模型继续趋势,组合版本有不愉快的颠簸,但一旦树模型偏离太多,至少跟随趋势。
我们不同模型的外推行为——图片由作者完成。
Sklearn 兼容性
如果我们想实现完全 sklearn 兼容性(型号选择、管道等。)并使用 sklearn 的机载测试工具,我们必须对估计器进行一些修改:
- 我们需要为参数添加 setters 和 getters(我们使用 sklearn 的约定,用名称和两个下划线作为参数的前缀,即
base_regressor__some_param
) - 随机状态的一致处理
这可以通过以下方式实现:
然后,我们可以在我们的自定义估计器上运行超参数网格搜索:
我们还可以使用sklearn.utils.estimator_checks
工具来检查我们的估计器:
在某些情况下,您可能无法满足特定的验证,例如,在这种情况下,您可以将特定检查的返回值伪造为 true:
import mockfrom sklearn.utils.estimator_checks import check_estimatorwith mock.patch('sklearn.utils.estimator_checks.check_estimators_data_not_an_array', return_value=True) as mock:
check_estimator(CombinedRegressor())
包裹
如果我们有一个模型,它对一组特定的输入非常有效,但是一旦输入变得更加奇特,我们就会失去信心,那么这种方法就非常有用。在这种情况下,我们可以通过使用更透明的(例如线性)方法,我们可以很容易地与领域知识同步,并保证特定的行为(例如外推、比例增量)。
除了使用组合估计器,我们还可以使用具有更好外推行为的非线性模型,如神经网络。另一种替代方法是向训练数据集添加一些人工样本,以增加支持的响应范围。
最初发表于【https://blog.telsemeyer.com】。
喜剧还是戏剧?
原文:https://towardsdatascience.com/comedy-or-drama-d8f30c31552c?source=collection_archive---------62-----------------------
教机器幽默感的尝试
查尔斯·德鲁维奥在 Unsplash 上拍摄的照片
如果你是 YouTube 或网飞的用户,你一定知道在你观看每个视频后会弹出的‘推荐给你’视频。这是一个商业如何使用自然语言处理(NLP)技术开发数据驱动产品的经典例子。无论是有监督的还是无监督的 NLP 变体,都一直吸引着我去深入挖掘和研究这些黑箱模型。作为一个了解更多的实验用例,我试图开发一个流派分类器(版本 1.0.0 ),根据其情节/剧情简介预测电影是喜剧还是戏剧。让我们开始吧。
数据
我把这个项目建立在 IMDB 数据集上。原始数据集包含了从电影语言到演员细节的大量信息。对于我目前的用例,我将只局限于电影的情节和类型。原始数据集包含 26 个流派,然而,我决定一步一步来,目标是首先在 2 个类别上安装二元分类器,即喜剧和戏剧。这是我的原始数据的样子:
我从来没有听说过的电影情节!
预处理和设计
第一项任务是将文本转换成机器能够理解的语言。这包括很多步骤,比如标记化和嵌入,每一步都有不同的风格。如果你是 NLP 新手,这篇文章将带你快速了解处理 NLP 问题的一般技术。
作为 Keras 库的热心用户,使用 Keras 对文本进行了处理和标记。对于我的单词嵌入,我选择了手套。虽然 Keras 嵌入为您提供了使用多个单词嵌入的灵活性,但预训练手套嵌入带来的性能提升是无与伦比的。
任何数据科学项目的一个重要要点是 GIGO(垃圾输入,垃圾输出),再多的模型开发也无法弥补垃圾数据。这个 Kaggle 内核将向您展示选择正确的文本预处理和单词嵌入如何对最终模型产生影响。一旦我们准备好数据,我们就可以继续进行模型构建。
在几个世纪的时间里,我尝试了不同的排列和组合,最终构建了一个双向 LSTM 神经网络,它给了我一个合理的性能(在测试集上有 85%的准确率)。
最终模型
最终密集层中的 softmax 激活函数返回潜在结果的概率分布。因此,例如,如果模型返回 70%喜剧和 30%戏剧的概率分布,则电影情节将被分类为喜剧。
图片胜过千言万语!
观察和结果
现在,事情变得有趣了。我在一些我最喜欢的电影的不同情节上尝试了我的模型。因为有太多的模特,我把模特表现特别好的那些列入了候选名单。先说我最喜欢的一部喜剧电影的节选。
婚礼前两天,道格和三个朋友开车去拉斯维加斯参加一个疯狂而难忘的男性聚会。事实上,当三个伴郎第二天早上醒来时,他们什么都不记得了;他们也找不到道格。时间不多了,三个朦胧的伙伴试图重新追踪他们的脚步,找到道格,这样他们就可以让他及时回到洛杉矶,走上红毯。
正如一些人可能已经猜到的,这是《宿醉》的梗概。我的模型对这个情节做出了如下预测。
“宿醉”的预测
在我的另一部最爱,莱昂纳多迪卡普里奥的戏剧电影《血钻》上尝试,产生了以下结果。
随着 20 世纪 90 年代塞拉利昂内战的爆发,两个男人,一个南非雇佣兵和一个门德渔民加入了一个共同的追求,寻找一种能够改变他们生活的稀有宝石。在一名美国记者的帮助下,这些人踏上了穿越叛军领地的危险旅程,以实现他们的目标。”
“血钻”的预测
这些都是相当准确的预测。然而,它并不总是阳光和彩虹,因为模型远非完美!。NLP 模型的驱动引擎是词汇表及其与其他相似单词的相应空间关联。而且,就像人类的大脑一样,这个引擎必须经过调整和训练,才能理解单词的上下文。这是我的模型无法清晰描述的。当它看到脱离上下文的单词时,它会有一点挣扎。比如电影‘小丑’。
失败的喜剧演员亚瑟·弗莱克永远独自在人群中,当他走在高谭市的街道上时,他寻求联系。亚瑟戴着两个面具——一个是他为日常工作画的小丑面具,另一个是他徒劳地试图感觉自己是周围世界的一部分的伪装面具。受到社会的孤立、欺凌和忽视,弗莱克开始慢慢陷入疯狂,他变成了被称为小丑的犯罪大师。
“小丑”的预测
可能是受到了单词‘喜剧演员’,的影响,这个模型把上面的错误归类为‘喜剧’,而这部电影,实际上,完全相反。
从好的方面来看,有一些先进的技术可以处理这个问题,我将在接下来构建多类分类器的过程中探索这些技术。非常感谢您的阅读。我将很快上传一个记录在案的 Colab 笔记本,所以你可以以此为基础来改进它和/或尝试你的想法。
Python 的空间科学:彗星——来自远方的游客
原文:https://towardsdatascience.com/comets-visitors-from-afar-4d432cf0f3b?source=collection_archive---------60-----------------------
用 Python 进行空间科学
系列教程的第 7 部分“用 Python 进行空间科学”将开始一个小的科学项目,在那里我们将熟悉冰冷的宇宙访客:彗星
艺术家对来自另一个恒星系的星际访客“Oumuamua”彗星的印象。鸣谢:ESA/哈勃,NASA,ESO,m . Kornmesser;许可: 知识共享署名 4.0 国际许可
前言
这是我的 Python 教程系列“用 Python 进行空间科学”的第 7 部分。这里显示的所有代码都上传到了GitHub上。尽情享受吧!
介绍
每一代都有它的“大彗星”。从地球上肉眼可见的彗星,以其模糊的外观和长长的尾巴在夜空中闪耀数周或数月。对我来说,它是 20 世纪 90 年代末的海尔-波普彗星。我的父母给我买了一个望远镜,从我们公寓的阳台上,一个终生的激情诞生了。
从远处看,彗星经常被称为“肮脏的冰球”。固体“球”就是所谓的原子核。如果这样一个核靠*太阳,它就会升温,释放出气体和尘埃粒子。气体和尘埃大量释放出来,在彗星的核心部分形成了三个结构。这三个部分是:
- 彗发:围绕着原子核的球形大气状结构,包含气体和尘埃/冰粒
- 尘埃尾:尘埃粒子沿着彗星的轨道/路径分布
- 离子尾:由于太阳的辐射,气体粒子带电,并受到太阳磁场和太阳风(太阳发射的带电粒子)的强烈影响。离子尾径向远离太阳
除了水和矿物质,我们知道彗星还含有氨基酸和其他重要的生命构成元素。这些科学见解只有通过向这些宇宙流浪者发送机器人航天器才有可能实现。未完成的任务有:
- 乔托:1980 年末欧洲航天局对哈雷彗星的探测任务
- 星尘:美国国家航空航天局的一项任务,15 年前从 81P / Wild 2 号彗星的尾部收集尘埃颗粒并将其送回地球
- Rosetta :欧空局对彗星 67P/Churyumov-Gerasimenko 的任务。经过 10 年的旅程,飞船于 2014 年抵达彗星,并部署了一个名为菲莱的着陆器
但是彗星是从哪里来的?为什么有些出现的频率更高?他们是威胁还是我们都认识他们?()*
在本节课和接下来的几节课中,我们将仔细研究这些数据。我们将确定彗星的起源,并计算一些基本属性来回答这些问题。
现代空间科学和天体物理研究与数据科学和机器学习密切相关。但是作为任何数据科学工作,我们需要从数据工程部分开始,在那里我们收集数据并为我们未来的工作做准备。
小行星中心
在我们开始使用数据之前,我们需要看一下我们现在使用的库。就像在我们上次的会议中一样,我们需要像 datetime (用于日期时间解析)、 numpy 和 pandas 这样的库来进行数据准备和工程。我们稍后使用 pathlib 创建一个子目录,并加载 spicepy 以使用 NASA 的 SPICE 工具包来执行空间科学任务。
上次我们创建了一个函数,允许我们从互联网下载文件(例如,SPICE 内核文件)并将其存储在本地目录中。该功能存储在名为 _auxiliary 的新主文件夹中。目前,我们只有一个公共函数,不需要为一个任务创建单独的 Python 库。因此,使用包 sys 和函数 sys.path.insert (第 12 行和第 13 行),我们从_ 辅助文件夹(第 14 行)添加脚本和内容。
第 1/10 部分
已知彗星的详细列表由小行星中心 (MPC)提供。MPC 收集所有居住在我们太阳系的小天体的信息。我们下载以压缩 JSON 格式提供的数据,并将它们存储在一个名为 raw_data 的文件夹中。(第 3 + 4 行定义文件夹和 MPC URL 第 7 行调用下载函数,该函数创建子目录并存储文件cometels.json.gz。MPC 提供了文件内容的详细描述。我们一会儿就需要这些信息。
第 2/10 部分
出于测试目的,我们将在下一节计算彗星的状态向量。这样就加载了一个 SPICE 内核元文件…
第 3/10 部分
…路径指向 gm_de431.tpc (包含其他行星常数)和 naif0012.tls (包含时间和闰秒信息)内核。
\begindataKERNELS_TO_LOAD = (
‘../_kernels/pck/gm_de431.tpc’
‘../_kernels/lsk/naif0012.tls’,
)
现在,压缩的 JSON 文件被加载。 pandas 函数 read_json 直接读取压缩文件并创建数据帧。
第 4/10 部分
让我们看看提供的数据。该文件包含轨道要素、彗星名称、参考文献等。和:2 个不同的日期时间;根据文档:
**Columns F77 Use**
[...]
15 - 18 i4 Year of perihelion passage
20 - 21 i2 Month of perihelion passage
23 - 29 f7.4 Day of perihelion passage (TT)
[...]
82 - 85 i4 Year of epoch for perturbed solutions
86 - 87 i2 Month of epoch for perturbed solutions
88 - 89 i2 Day of epoch for perturbed solutions
基于轨道元素,我们想要计算状态向量。对于这个计算,我们将应用 SPICE 函数 二次曲线 。该函数需要一个天体的*均异常值和相应的星历时间,称为历元。*均异常是使用*日点方向作为参考方向的角度。因此,“年”、“月”和“*日点通过日”是需要的日期时间。与*日点通过的日期时间相对应的*均异常是(根据定义)0 度!
让我们基于三个日期列(第 10 到 14 行)创建一个 UTC 时间戳。应用 lambda 函数,将年、月和日字符串合并为格式为年-月-日的日期。日期是以十进制数给出的。例如,15.5 对应于 UTC 第 15 天的 12:00:00。“十进制时间”需要转换成适当的时间格式。首先(第 18 行),我们定义一个占位符日期,它可以与第 23 到 26 行中的datetime . time delta函数一起使用。将十进制的日期和时间添加到占位符日期(第 25 行),并使用 strftime 函数将得到的日期时间对象转换为小时:分钟:秒(第 26 行)。
现在,日期和时间在第 29 到 32 行合并,并且相应的星历时间(ET)可以在第 35 行使用 SPICE 函数 utc2et 计算。
第 5/10 部分#
我们现在准备计算一个用于测试的状态向量,看看我们是否正确地处理了数据。
伟大的海尔波普
大彗星 C/1995 O1 的图像(海尔-波普)。上世纪末,这颗彗星有一年多的时间是可见的。蓝色的尾巴是所谓的离子尾,主要受太阳风的影响。灰/白尾巴由沿着彗星轨道分布的尘埃和冰粒组成。信用:ESO/e . Slawik;许可: 知识共享署名 4.0 国际许可
对于测试用例,我们选择海尔-波普彗星。不得不承认,我个人的喜好是选择这颗特殊彗星的原因。
对于 圆锥曲线 函数,我们需要轨道元素(存储在数据帧 c_df 中)以及太阳的 GM* 参数。第 4+5 行使用 SPICE 函数 bodvcd 从对应的行星内核中提取并定义 GM* 常数。第 8 行创建了一个 Hale-Bopp 数据帧。代码部分…
c_df[‘Designation_and_name’].str.contains(‘Hale-Bopp’)
…使用 Designation_and_name 列,搜索包含 Hale-Bopp 的子串。通过 loc 功能,分配相应的 Hale-Bopp 数据帧行。
第 13 行到第 21 行定义了一个输入数组,该数组包含了 二次曲线 函数的正确格式的所有数据(距离以 km 为单位,角度以弧度为单位,*均异常等于 0 度)。
第 6/10 部分
彗星的状态向量是为协调世界时 2020 年 5 月 5 日(午夜)计算的(第 2+3 行)。我们使用 NASA 地*线网络接口来计算参考状态向量,以便与(**)进行比较:
第 7/10 部分
结果如下所示。可以看出,基于 MPC 轨道数据的结果与 NASA HORIZONS 数据非常一致。
Comparison of the computed state
vector with the NASA HORIZONS results
==========================================
X in km (Comp): 5.347972e+08
X in km (NASA): 5.348377806424425E+08
==========================================
Y in km (Comp): -2.702078e+09
Y in km (NASA): -2.702225247057124E+09
==========================================
Z in km (Comp): -5.904119e+09
Z in km (NASA): -5.904425343521862E+09
==========================================
VX in km/s (Comp): 6.856500e-01
VX in km/s (NASA): 6.857065492623227E-01
==========================================
VY in km/s (Comp): -3.265125e+00
VY in km/s (NASA): -3.265390887669909E+00
==========================================
VZ in km/s (Comp): -4.968756e+00
VZ in km/s (NASA): -3.265390887669909E+00
科学数据库
我们从 MPC 下载了彗星数据。我们通过比较计算出的状态向量和 NASA 地*线系统的结果来检查数据的一致性。因此,我们为进一步的彗星研究打下了坚实的数据基础!
我们创建了一个 SQLite 数据库,而不是重新加载数据帧和解析 JSON 文件。SQLite 允许生成一个存储在一个文件中的全功能 SQL 数据库。这种嵌入式解决方案用于例如移动设备上。甚至更大的数据集也可以存储在这个嵌入式解决方案中,而不需要专用服务器或分布式文件系统(轶事:在我的硕士论文和后来的博士研究中,我一直使用 SQLite。我创建并使用了大小约为 250 GB 的 SQLite 数据库,令人惊讶的是,它们具有良好的性能。
但是首先,让我们增加两个参数,我们可以很容易地从轨道元素中得到:半长轴(第 2 到 5 行)和远日点(第 8 到 11 行)。我们只计算偏心率小于 1 的闭合轨道的值。
第 8/10 部分
在教程的主文件夹中,为(comets)数据库创建了一个新目录(第 3 行)。第 6 行连接(分别创建)一个 SQLite 数据库,第 7 行设置一个游标。现在,创建了一个名为 comets_main 的表(第 11 到 25 行)。主键是彗星的指定名称。整数或分类主键更好更快,例如,在不同的表之间创建连接。在我们的例子中,我们只有几百行和几列。这场演出对我们的目的来说足够好了。此外,一切都保持“人类可读”。第 20 行添加了*均异常,并设置默认值为 0 度,因为*均异常不是由 MPC 数据提供的(只有*日点通过时间)。
第 9/10 部分
我们现在使用命令执行命令将数据写入数据库。我们现在为进一步的科学工作做好了准备!
第 10/10 部分
结论与展望
今天我们开始了我们的彗星科学之旅。我们从小行星中心下载了数据,分析了数据,并使用海尔-波普数据来验证内容。在接下来的教程中,我们的分析将基于创建的 SQLite 数据库。数据工程、准备和清理是数据科学以及任何其他科学领域的关键要素。
下一次,我们将熟悉数据,并从 800 颗彗星中获得科学见解(),例如,什么是 C 或 P 轨道类型?)。我们将学习一些基本的 SQL 命令。如果你想看一下数据库,我建议你使用一个 SQLite 浏览器,比如 SQLiteBrowser 。由于数据库相当小,它也被上传到 GitHub 上。
托马斯
脚注
()彗星、小行星、流星体、行星、矮行星等等……这些天体有什么区别?有什么不同吗?*除了“Python 的空间科学”系列,我还想在一些“补充空间科学文章”中与您分享一些空间科学知识。
(**) NASA HORIZONS 只是许多其他伟大工具中的一个工具。无论是作为网络界面还是桌面应用程序:“补充空间科学文章”也可以涵盖有用工具和程序的附加信息。
请让我知道如果一些简短的补充空间科学文章将不胜感激。
常见的激活功能以及为什么你必须知道它们
原文:https://towardsdatascience.com/common-activation-functions-and-why-you-must-know-them-ec90e54a7079?source=collection_archive---------51-----------------------
对常用激活功能的实现、额外好处、注意事项和使用的总结
激活函数是神经网络的基本构件。然而,在人们能够有效地使用它们之前,必须仔细地研究它们。这是因为激活函数有活动区域和死亡区域,使得它们在模型中要么学习要么行动死亡。让我们一个接一个地讨论它们的正确使用和它们的缺点。
Sigmoid 函数
Sigmoid 函数或 logistic 函数或软阶跃函数是研究神经网络性能的共同出发点。从数学上讲,这个函数及其导数可以表示为图 1 所示。
图 1 Sigmoid 函数和导数(图片由作者提供)
该函数可以如图 2 所示绘制。
图 2 Sigmoid 函数(图片由作者提供)
我们可以看到该函数只能在大致-4 到 4 的范围内帮助训练。这是因为,在任何一侧超过这些限制,梯度都不显著。让我们看看图 3 所示的梯度曲线。
图 3 sigmoid 函数的导数(图片由作者提供)
我们可以看到,在绿线和红线所示的[-4,4]的限制之外,梯度并不那么显著。这就是所谓的消失渐变的问题。由于这个原因,在深层网络中使用 sigmoid 函数是不理想的。此外,如果你想把更小的值(< 1)不断相乘,你最终会得到非常小的值。这在深层网络中是不利的条件。所以 sigmoid 根本就不是深度学习想要的激活。 ReLU 是克服 sigmoid 函数不良结果的第一个变通方法。
虽然 sigmoid 函数不用于隐藏层,但它是输出层的理想选择。这是因为 sigmoid 给出了[0,1]范围内的值,这可以帮助我们训练一个用于二进制编码输出的网络。这应当连同一个 二元交叉熵 损失函数一起完成。
ReLU ( R 有效 L 线性单位)函数
ReLU 只是简单地输出一个神经元的非负输出。在数学上,这可以表示为如图 4 所示。
图 4 ReLU 函数和导数(图片由作者提供)
我们可以绘制函数及其导数,如图 5 所示。
图 5 ReLU 及其衍生产品(图片由作者提供)
如图 5 所示,导数永远不会死在正区域。此外,由于值是在没有任何阻尼的情况下输出的,因此值不会像我们在 sigmoid 函数中看到的那样消失。因此, ReLU 成为深度学习的理想候选。然而,正如你可能已经注意到的, ReLU 根本不存在于负空间中。这通常是可以的,因为神经网络的输入值和输出值是正的。然而,如果你有范围[-1,1]内的标度值或标准化值,这可能会杀死一些无法恢复的神经元。这种现象被称为垂死的 ReLU 。虽然这不是人们应该担心的事情(可以通过使用最小-最大缩放器进行缩放来避免),但了解变通方法是值得的。注意,由于值通过 ReLU 网络的爆炸性质,通常不希望在输出层中使用 ReLU 。此外,爆炸值会导致爆炸梯度的现象。然而,使用适当的 剪裁 和 规则化 可以有所帮助。
ReLU 变量和其他线性单位函数
ReLU 有几个变种,有助于克服死 ReLU 的问题。
PReLU(参数 ReLU)和泄漏 ReLU
参数化 ReLU 试图将负输入参数化,从而使垂死 ReLU 恢复。然而,该参数是一个可学习的参数,但 Leaky ReLU 除外,它为负分量使用一个固定参数。通常这个参数被选择为一个小值,因为网络的典型输出被认为是正的。
图 6 PReLU 和衍生工具(图片由作者提供)
对于给定的𝛂值(0.1),我们绘制了如图 7 所示的图表。这是漏 ReLU 的场景,0.1 为负乘数。
图 7 ⍺=0.1 的泄漏 ReLU(图片由作者提供)
注意,负区域中的梯度是细微的,但不为零。还有,节点面对太多负面数字也不会死。
ELU(指数线性单位)函数
在该函数中,负分量使用指数表示法建模。然而,我们仍然有可学习的参数𝛂.
图 8 ELU 函数(图片由作者提供)
我们可以将其绘制成图 9 所示。这里,为了更好的可视性,我们假设𝛂=0.5。
图 9 ELU 函数及其导数(图片由作者提供)
既然我们已经讨论了深度网络中使用的几个重要函数,那么让我们来看看一些常见但不那么复杂的函数。
Tanh 函数
谭是 LSTM 网络背后的驱动力。这有助于避免 RNNs 的缺点。
图 10 双曲正切函数和导数(图片由作者提供)
我们可以将其绘制成图 11 所示。
图 11 双曲正切函数和导数(图片由作者提供)
更多的激活功能
- 恒等函数:这是
f(x)=x
带导数f'(x)=1
的朴素函数。 - Softmax 函数:该函数保证输出加起来为 1 的层的值。这主要用于使用 分类交叉熵 作为损失函数的分类分类,并且主要用于输出层。
笔记
激活函数的设计主要考虑导数。这就是为什么你会看到一个很好的简化的导数函数。
必须通过查看输入值的范围来选择激活函数。然而, ReLU 或 PReLU 是一个很好的起点,带有s 形或 softmax 到输出层。
具有可学习参数的激活功能通常被实现为单独的层。这更直观,因为参数是通过相同的反向传播算法学习的。
希望你喜欢阅读这篇文章。
干杯!😃
常见 Pipenv 错误及解决方法:为什么不能锁定?!
原文:https://towardsdatascience.com/common-errors-and-how-to-solve-them-why-wont-it-lock-8f5e57111f23?source=collection_archive---------3-----------------------
Pipenv 无法锁定时该怎么办
作者:爱德华·克鲁格和道格拉斯·富兰克林。
本文是众多介绍 Python 包和使用 Pipenv 进行环境管理的文章之一。在这里,您将学习如何解决 Pipenv 安装和锁定问题。有关 Pipenv 或环境的更多信息,请查看这篇 中型文章 !
马科斯·迈尔在 Unsplash 上的照片
Pipenv 是什么?
Pipenv 将软件包管理和虚拟环境控制结合到一个工具中,用于安装、删除、跟踪和记录您的依赖关系;以及创建、使用和管理您的虚拟环境。Pipenv 本质上是将 pip 和 virtualenv 包装在一个产品中。
当您使用 Pipenv 开始一个项目时,该工具会自动创建一个虚拟环境、一个 Pipfile 和一个 Pipfile.lock。当您用pipenv install
安装一个包时,Pipfile 会自动用新的依赖项更新。
锁定问题:Pipfile 包含对不存在的包的引用
当 Pipfile 试图安装不存在的软件包,即错别字时,它不会锁定。
例如:
pipenv install panadas
Pipenv 查找您指定的包,不管它是否存在。当包不存在或由于其他原因找不到时,您会在终端中看到以下错误和更多错误。现在,我们将把重点放在这两个方面。
安装错别字
Pipenv 找不到 Panadas 的版本
锁定失败!请注意,“panadas”被添加到 Pipfile 的包中。这种打字错误将成为一个问题,因为现在我们的 Pipfile 包含一个错误,任何使用这个 Pipfile 的人都会遇到锁定和依赖错误。请注意,“安装成功”警报是不真实的;没有要安装的 Panadas。所发生的只是将“panadas”添加到 Pipfile 中。Pipfile 中的拼写错误是锁定失败的最常见原因。
只要 Pipfile 中存在这种输入错误,安装一个包,不管存在与否,都会导致锁定失败。您需要在文本编辑器中修复 Pipfile。我用的是纳米。你可以使用任何你觉得舒服的编辑器;Sublime,VS 代码,Atom 等。只需将 Panadas 改为 Pandas,然后pipenv install.
现在让我们看看锁定失败时控制台中出现的其他一些错误消息。
注意建议pipenv install --skip-lock
。这应该只在极端或因果编程环境中使用,因为它绕过了 Pipfile。锁的主要用途;锁定软件包版本并创建安装环境依赖项的公式。
pip 文件管理:指定版本
锁定失败的第二个最常见的原因是我们试图安装一个预发布版本的包。您可以通过在安装中添加--pre
标志来解决预发布版本冲突。
pipenv install --pre
在这个命令之后,您的 Pipfile 有了一个新变量; allow_prereleases = true
。请注意,这将允许在您的环境中安装任何预发行软件包。现在是固定特定包版本有用的时候了。固定版本是一个很好的习惯,可以防止将来出现依赖问题。
请注意上面“要求”部分下的 Pipfile 图像;你看python_version = 3.7
。Pipfile 在这里指定了 Python 版本。
要使用特定的 Python 版本构建 Pipfile 或环境,请使用以下语法。
pipenv --python 3
需要时还可以指定包版本。
pipenv install django=1.11.10
结论
通过 Pipenv 和 Pipfile,您向其他人展示了一种安装项目依赖项以及测试和开发需求的标准化方法。任何拥有您的 Pipfile 副本的人都可以使用下面的命令重新创建您的环境。
pipenv install
这将创建一个由 Pipfile 指定的环境。确保 Pipfile 没有打字错误,并且在共享之前指定了正确的包和 Python 版本!
如果这不是您正在寻找的 pipenv 解决方案,请查看这篇中型文章以获得有关其他 Pipenv 错误的帮助!
[## 常见 Pipenv 错误
Pipenv 错误及其解决方案的集合。
towardsdatascience.com](/common-pipenv-errors-3a6f8ce81562)
我的通用 Git 命令备忘单
原文:https://towardsdatascience.com/common-git-commands-cheat-sheet-9cd8efcabd17?source=collection_archive---------51-----------------------
照片由汉娜·约书亚在 Unsplash 上拍摄
在这篇博客中,我记录了一些我经常使用或者为了特定目的使用过几次的常用 git 命令。这肯定不是一个详尽的列表,但更全面,是为了快速参考。
初始化/克隆 GIT 存储库
照片由丹妮尔·麦金尼斯在 Unsplash 上拍摄
要创建新的本地 git 存储库:
git init
要从本地 git 存储库复制:
git clone /path/to/repository
要从本地 git 存储库复制:
git clone username@host:/path/to/repository
从远程存储库更新本地存储库
要实现(合并)从远程存储库到本地存储库的更改,请执行以下操作:
git pull
或者
git fetch
git merge <branch_name>
NB: git pull 只不过是应用了自动分支策略的 git 获取和合并分支。
Git 配置
要配置本地存储库的用户名和电子邮件:
git config user.name "your_name"
git config user.email "your_email_address"
要为所有提交配置用户名和电子邮件:
git config --global user.name "your_name"
git config --global user.email "your_email_address"
分支
照片由蒂姆·约翰逊在 Unsplash 上拍摄
要创建新的分支和交换机:
git checkout -b <branch_name>
要切换到现有分支:
git checkout <branch_name>
要查看工作分支:
git branch
要删除分支:
git branch -d <branch_name>
将变更添加到本地存储库中
- 对文件进行更改。
- 验证已更改文件的文件列表以及尚未转移或提交的文件:
git status
3.将文件添加到暂存/索引:
git add <file_name>
4 .将阶段性更改提交给 head:
git commit -m "Your_message_about_the_commit"
要提交已添加到暂存中的任何更改以及此后更改但尚未暂存的文件,请执行以下操作:
git commit -a "Your_message_about_the_commit"
5.要将更改推送到分支:
git push origin <branch_name>
6.要将更改推送到母版:
git push origin master
理想情况下,在协作软件开发环境中拉请求用于批准对主所做的更改。因此,我们应该将我们的变更推送到我们的工作分支,并打开一个拉请求来合并变更。
使用 Git Stash
要记录工作目录和索引的当前状态并返回到干净的工作目录:
git stash save "your_message"
“您的消息”使您更容易在存储列表中找到存储状态。
要获得隐藏的工作目录的有序列表:
git stash list
输出是一个编号列表,如 stash@{0}、stash@{1}等。
要清除所有存储状态:
git stash clear
要删除选定的存储树,在这种情况下,是倒数第二个存储状态:
git stash drop stash@{1}
默认—最后一次隐藏状态
要从隐藏列表中删除所选的隐藏状态并应用于当前工作树状态,请执行以下操作:
git stash apply stash@{1}
默认—最后一次隐藏状态
从隐藏列表中删除选定的隐藏状态,并应用于当前工作树状态之上。此外,它删除弹出的存储状态。
git stash pop stash@{1}
默认-上次隐藏状态
GIT 命令的日志和历史记录
丹尼尔·利维斯·佩鲁西在 Unsplash 上的照片
要检查 git 命令历史记录(仅 HEAD):
git reflog [show]
要检查 git 命令历史记录:
git reflog show --all
要检查所有 git 命令的历史记录:
git reflog --date=iso
要检查所有“特定命令”(如拉/提交/存储)命令历史记录,包括时间:
git reflog --date=iso|grep specific_command
要查看分支中的提交日志:
git log origin/master
刘汉宁·奈巴霍在 Unsplash 上的照片
我的链接: 中|LinkedIn|GitHub
感谢光临。希望这有帮助!
每个数据科学家都需要知道的通用 Git 命令
原文:https://towardsdatascience.com/common-github-commands-every-data-scientist-needs-to-know-e7d5d9c4f080?source=collection_archive---------50-----------------------
通过使用 Git 和 GitHub 成为更好的数据科学家的指南
马库斯·温克勒在Unsplash【1】上的照片。
目录
- 介绍
- GitHub 设置
- 命令
- 摘要
- 参考
介绍
对于软件工程师、数据工程师、机器学习工程师和数据科学家来说,GitHub 是一个非常有价值和有用的工具。起初,作为一名学生,甚至是一名专业的数据科学家,我倾向于远离 GitHub,因为它令人困惑,而且似乎不是我作为一名数据科学家需要了解的东西。但是,随着时间的推移,我逐渐意识到,为了扩展您的代码和模型,尤其是如果涉及到不止一个人(,通常是),以及采用精确的版本控制,Git 和 GitHub 是必不可少的。虽然您可以选择在 Jupyter 笔记本上完成大部分工作,但是一旦您的模型准备好进行部署,文件的数量就会增加,因为。py 文件很可能都是面向对象的,其中的代码不是以研究为中心,而是像软件工程师一样高效地编码,GitHub 将是这一过程的解决方案。下面,我将讨论 GitHub 及其非常有用的 Git 命令,它们将帮助您成为更好的数据科学家。
GitHub 设置
作者截图[2]。
在这种情况下,GitHub[3]是数据科学家通过使用 Git 进行协作和使用版本控制的工具。它可以用于研究目的,但主要分配给机器学习模型的部署代码。使用它的最佳方式是通过使用拉请求。这有助于确保多个人(这是一个可编辑的字段)审查和批准您的代码更改。上图是创建第一个存储库的一般设置。我不会过多地关注这一点,因为我们将讨论有用的 Git 命令,但是需要注意的是,在使用所描述的命令之前,这是整个过程的第一步。
在这里可以找到从您的终端创建存储库的设置代码:
echo "# article" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/mprzybyla123/article.git
git push -u origin master
命令
照片由 Yancy Min 在Unsplash【4】上拍摄。
一旦建立了存储库,就可以按照这些有用的 Git 命令在终端中移动存储库。由于许多人将在同一个存储库上工作,所以创建分支是很重要的,这将是您的工作空间,一旦拉请求被批准,它将最终合并到主存储库中。以下是常见数据科学命令的代码示例及其相关信息。
git branch
这个分支命令返回您的存储库的所有分支,以后可能会超过 20 个,所以这个命令将以绿色突出显示,而其他分支是白色的,这是您当前所在的分支。这个命令非常重要,这样您就不会意外地将不正确的代码推送到您的主分支——通过确保您不在主分支上。
git branch name_of_branch
要复制主分支并创建自己的分支,请使用上面的 branch 命令。这确保了您在一个单独的分支上工作,在 pull 请求被批准后,该分支也可以与新的代码变更合并在一起。将分行名称更改为您想要的分行名称。
git pull
在检查您的分支,并切换到主分支时,这个命令将获取所有新的代码更改,您的主分支将完全更新。建议您经常执行此 pull 命令。
git status
一旦你真正进入了你的仓库,在文件之间切换并创建变更,你将需要知道你改变了什么。在对主分支进行新的代码更改之前,检查您的更改状态是非常有用的。
接下来的 4 个命令将是连续的命令,以便添加更改、提交更改并将其推送到您的 GitHub respiratory,它将与您的主分支进行比较,最终在获得批准后合并。
git add folder_name/folder_name/folder_name/file.py
上面的 add 命令是三个文件夹目录的一个例子,这三个文件夹包含了你要添加的文件,所以你可以随意用你实际文件夹的名字替换那些文件夹的名字,也可以把文件. py 改成你实际的文件夹。py 文件。
git commit -m “Added file change”
commit 命令是这个过程中的第二步,它不仅命名您所做的更改,还提交代码更改。
git push
要将前面的所有步骤一起编译,您将使用 push 命令将文件及其更改发送到存储库。注意:您不必在之后执行拉请求,但这通常是大多数人在这个过程中会采取的步骤。
git push --set-upstream origin name_of_branch
如果您一直在本地处理您的分支机构,并且这是您第一次将它托管为共享和公共的(在您的公司分支机构内),您将必须使用这个推送命令,它将作为一个建议被自动提示。分支的名称将替换为您已经命名的分支。
虽然这段代码很简单,但它非常强大,可以让您成为一名数据科学家,在代码中使用带有检查和*衡的受控系统。现在,您可以将您的代码更改与同样在同一模型上工作的其他数据科学家或软件工程师进行比较。最后,您将看到一个绿色图标,询问您是否要'创建一个拉取请求。然后,您将能够创建、可视化和查看您的代码与主代码相比如何。在代码被比如说两个人批准之后,您可以将您的更改合并到 master 中,并删除您的分支。
摘要
由迦勒·怀特在 Unsplash 上拍摄的照片。
本文描述了如何快速设置您的存储库,以便在本地计算机上使用,同时还能够应用于整个主分支,该分支将存放您的数据科学或机器学习模型的生产级代码。
使用所讨论的通用 Git 命令,您将能够成功地将代码更改应用到您的 data science GitHub 存储库中。
- 检查你在哪个分支——git 分支
- 从您的主分支创建一个新的分支—git branch branch _ name
- 提取主分支,使其保持最新— git 提取
- 检查您的文件(代码)变更— git 状态
- 添加您的文件(代码)从您的分支— git 添加
- 从您的分支提交您的更改—git commit-m " Added change "
- 从你的分支推送你的变更— git 推送
参考
[1]马库斯·温克勒在 Unsplash 上拍摄的照片,(2020)
[2] M.Przybyla,GitHub 的截图,(2020 年)
[3] GitHub, GitHub 主页,(2020)
[4]照片由 Yancy Min 在Unsplash(2019)上拍摄
[5]照片由凯勒·怀特在Unsplash(2019)拍摄
常见的图论问题
原文:https://towardsdatascience.com/common-graph-theory-problems-ca990c6865f1?source=collection_archive---------12-----------------------
图论简化版
这篇文章旨在使用图论给出一组广泛而直观的问题陈述和可能的解决方案。
我们每天遇到的许多问题都可以被解释为一个图问题或者一个*似的子问题。因此,需要对不同的图形变体及其应用有所了解。如果你想重温一下图论的基础知识,你一定要去参观一下这个。后者将让你对不同类型的图及其表示有一个简要的了解。
最短路径问题
最常见的图形问题之一就是最短路径问题。给定一个加权图,我们必须找出从节点 A 到 g 的最短路径。所有可能路径中的最短路径肯定是优化成本函数的路径。
作者照片
例如,考虑上面给出的图中的节点是世界上不同的城市。如果您仔细观察该图,我们可以看到与每个边缘相关的成本。所以这是一个有向加权图。回到我们的直觉,与每对城市相关联的权重被认为是城市间旅行的成本。为了方便起见,让我们将每个成本乘以 100 美元,得到一个真实的数字。因此,在城市 A 和 B 之间旅行的费用是 300 美元,B 和 F 之间的费用是 600 美元,以此类推。如果我们想在两个城市之间计划一次划算的旅行,我们应该参考这张图表来估算总成本。两个城市之间可能有多条路径,我们最寻求的路径应该是成本最低的路径。这是最短路径问题的一个非常基本但可以理解的例子。
幸运的是,有一些算法可以以最小的代价把我们从节点 A 引导到节点 B。 广度优先搜索 , 迪杰斯特拉的 , 贝尔曼-福特 , 弗洛伊德-沃肖 , A* 还有很多算法可以用来解决最短路径问题。
连通性
顾名思义,连通性是图论中的一个大问题,它表示从节点 A 到 B 是否存在一条路径。需要注意的一点是,我们不关心最小成本,只关心路径。
作者照片
解决这个问题的最基本方法是进行广度优先搜索或深度优先搜索。
负周期
有时我们的图会有负边,这可能会破坏图的整个流。我要说的是,负面循环是一个永无止境的陷阱。因此,我们检查,是否存在任何一对节点之间的负加权边,如果是这样,它如何形成一个循环。
作者照片
在给定的图中存在负边。显然,它对负面循环的形成有所贡献。一个这样的循环是【B,C,D】。如果我们循环通过这些边缘,我们将永远以最小的成本进行下去。然而,在某些情况下,负面循环扮演了天使的角色。例如,如果我们运行一个从一种货币到另一种货币再到另一种货币的货币兑换游戏,我们可以使用这样一个负图,这反过来可能会产生一些成本效益。这只是一个假设,可能会也可能不会成为事实,因为货币汇率不会保持不变这么久。有某些算法如 贝尔曼-福特 和 弗洛伊德-沃肖尔 来检测负周期。
强连通分量
这些是有向图中的独立循环,因此循环中的每个节点都可以到达同一循环中的所有其他节点。
作者照片
重要的是要看是否有强连接的组件。红色方框内的循环就是这些组件的示例。用于检测这些组件的不同算法是 Tarjan 的和 Kosaraju 的算法。
旅行推销员问题
如果没有听过这个学期,没有人会完成他们的计算机科学学位。如果你没有,我很抱歉。但是它非常容易理解,并且有很多实际应用。
图片来自文章公司的博客
该问题的结构是给定一个城市列表和每对可能的城市之间的成本或距离。然后,销售人员必须在相同的节点开始和结束,但必须以最小的成本或距离访问轨迹中的每个城市一次,这取决于目标函数。这个问题看起来非常简单,并且在路径估计和成本优化问题中得到了广泛的关注。诸如分支定界和 hold-Karp 的几种算法可用于解决这个问题。这仍然是一个计算上具有挑战性但研究仍在继续的问题。
布里奇斯
桥是图中的边,移除桥可以增加图中连通分量的数量。网桥非常重要,因为它们代表了图中的漏洞和瓶颈。
照片由onion-router.net拍摄
移除连接节点 G 和 N 的边将导致两个单独的组件被连接。如果那是一座真的桥,拆除它将会导致两个孤立的城市。所以,桥总是一个弱点,因为它的断开会造成额外的麻烦。
类似地, 关节点 是一个节点,其移除导致连接的组件的总数增加。
最小生成树
最小生成树是连接所有顶点以形成最小成本树的边的子集。
照片由萨尔萨克·阿加瓦尔通过commonlounge.com拍摄
正如你所看到的,给定的图形是加权的和无向的。粗边表示连接所有顶点的最小成本生成树,但代价最小。我们将不同的问题,如路线规划、电路设计和更多的问题公式化为最小生成树,这些问题可以通过 Kruskal 的和 Prim 的算法来解决。
最大网络流量
顾名思义,这些问题可以用来估计一个图所能容纳的最大体积(取决于问题)。例如,如果我们将电网视为我们的图形,将电线杆视为图形中的不同节点。我们可以假设在不影响电网的情况下,有多少电力可以通过网络发送。另一个例子是移动网络,其中每个用户充当图中的一个节点。与前一个示例一样,我们可以计算出在没有网络流量的情况下可以保持在线的最大用户数量。
作者照片
这个公式可以回答所有问题中的最大值,并预测潜在的瓶颈。使用的不同算法有 福特-富尔克森 和 埃德蒙兹卡普&迪尼奇的算法。
我们已经讨论了图论中几乎所有的问题。我们将在接下来的文章中讨论这里提到的每一个算法。我非常兴奋能和你们分享所有的这些。在那之前,再见!
Python 中常用的图像处理技术
原文:https://towardsdatascience.com/common-image-processing-techniques-in-python-e768d32813a8?source=collection_archive---------31-----------------------
使用 PIL 和 OpenCV 学习简单而强大的图像处理技术
在这篇文章中,你将学习
- 使用 PIL 和 OpenCV 的常见图像处理技术,如将 RGB 图像转换为灰度图像、旋转图像、去除图像噪声、检测图像边缘以及裁剪图像中的感兴趣区域
- 使用 OpenCV 的模板匹配在图像中搜索物体
必需的库:
PIL、OpenCV 和 imutils
为什么需要学习图像处理技术?
深度学习用于分析、识别和生成对图像中对象的智能理解。一些常见的应用是图像分类、对象检测、实例分割、等。因此,必须对图像处理技术有深入的了解,如图像增强,包括裁剪图像、去除图像中存在的噪声或旋转图像等。,以建立更好的训练数据集。
图像处理技术同样有助于光学字符识别(OCR)
图像处理技术通过帮助识别关键特征或从图像中读取文本来增加图像的可解释性,以分类或检测图像中存在的对象。
照片由缺口缺口在缺口处拍摄
此处提供代码和图片
导入所需的库
**import cv2
from PIL import Image**
让我们先用 OpenCV 和 PIL 显示图像
使用 OpenCV 读取并显示图像
# Reading and Displaying the file
**image = cv2.imread(r'love.jpg')
cv2.imshow("Image", image)
cv2.waitKey(0)**
如果图像太大,那么显示图像的窗口将不适合屏幕。
那么我如何在屏幕上显示完整的图像呢?
默认情况下,当显示超大图像时,您会看到裁剪后的显示。要查看完整图像,您将使用 OpenCV 的 namedWindow(name,flag) 创建一个新窗口。第一个参数, name, 是窗口的标题,将被用作标识符。当您将 标志 设置为 cv2 时。WINDOW_NORMAL,然后显示完整图像,您可以调整窗口大小。flag 参数还有其他选项。
# Resizing the image for the user to resize the window
**image = cv2.imread(r'love.jpg')
cv2.namedWindow('Normal Window', cv2.WINDOW_NORMAL)
cv2.imshow('Normal Window', image)
cv2.waitKey(0)**
调整图像大小
当我们调整图像大小时,我们改变图像的高度和/或宽度,并保持纵横比。图像的宽高比是图像的宽高比。
**image= cv2.imread(r'taj.jpg')**
**scale_percent =200** # percent of original size
**width = int(image.shape[1] * scale_percent / 100)**
**height = int(image.shape[0] * scale_percent / 100)
dim = (width, height)
resized = cv2.resize(image, dim, interpolation = cv2.INTER_AREA)
cv2.imshow("Resize", resized)
cv2.waitKey(0)**
使用 PIL 读取并显示图像
您将使用 open() 加载图像,然后使用 show() 进行显示。
形象。show()创建一个临时文件。
**pil_image= Image.open(r'love.jpg')
pil_image.show("PIL Image")**
如果你对识别图像中的边缘或其他特征感兴趣怎么办?
灰度图像用于识别边缘。灰度图像还有助于理解图像中存在的对比度或阴影梯度,以及理解它们在分析图像特征中的作用。
与灰度图像的 2D 通道相比,RGB 图像有三个通道:红色、绿色和蓝色。与彩色图像相比,灰度图像的每像素信息更少,因此灰度图像的处理时间更快。
利用 OpenCV 实现彩色图像的灰度化
我们正在使用 cvtColor(), 将彩色图像转换为灰度图像,这将把图像从一个色彩空间保存到另一个色彩空间。
#Converting image to grayscale
**image = cv2.imread(r'love.jpg')
gray_image= cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
cv2.namedWindow('Gray Image', cv2.WINDOW_NORMAL)
cv2.imshow('Gray Image', gray_image)
cv2.waitKey(0)**
使用 PIL 对彩色图像进行灰度缩放
【convert()返回此图像的转换副本;灰度使用“L”模式,彩色使用“RGB”模式。
# Gray image using PIL
**pil_image= Image.open(r'love.jpg')
gray_pil=pil_image.convert('L')
gray_pil.show()**
使用 OpenCV 进行边缘检测
使用 canny 边缘检测器检测图像中的边缘。Canny 边缘检测器通过多阶段算法使用灰度图像。
Canny() : 第一个参数是输入图像,第二个和第三个参数是 threshold1 和 threshold2 值。
强度梯度大于阈值 2 的边缘被认为是边缘,而低于阈值 1 的边缘被认为是非边缘。非边缘将被移除。两个阈值之间的任何梯度强度值基于它们的连通性被分类为边缘或非边缘。
**image= cv2.imread(r'taj.jpg')
cv2.namedWindow("Edge", cv2.WINDOW_NORMAL)
denoised_image = cv2.Canny(image, 100,200 )
cv2.imshow("Edge", denoised_image)
cv2.waitKey(0)**
Canny 边缘检测器
如果图像有歪斜或轻微旋转,想对图像进行纠偏怎么办?
倾斜文本的 OCR 效果不好,因此我们需要进行倾斜校正。可以使用 OpenCV 和 PIL 的 rotate() 对图像进行纠偏。
使用 OpenCV 旋转图像
rotate() 将根据 rotationCode,旋转图像,该代码为旋转函数的第二个参数。
旋转码的值为
- cv2。顺时针旋转 90 度,
- cv2。逆时针旋转 90 度
- cv2。旋转 _180 度
#Rotating the image
**image = cv2.imread(r'love.jpg')
cv2.namedWindow("Rotated Image", cv2.WINDOW_NORMAL)
rotated_img= cv2.rotate(image,cv2.ROTATE_90_CLOCKWISE )
cv2.imshow("Rotated Image", rotated_img)
cv2.waitKey(0)**
使用 OpenCV 顺时针旋转 90 度的图像
如果我想只旋转图像一个特定的角度怎么办?
根据特定角度旋转图像
在下面的代码中,使用 imutils 的 rotate() 将图像旋转 60 度
**import imutils
import numpy as np****image = cv2.imread(r'love.jpg')**# loop over the rotation angles
**for angle in np.arange(0, 360, 60):
cv2.namedWindow("Rotated", cv2.WINDOW_NORMAL)
rotated = imutils.rotate(image, angle)
cv2.imshow("Rotated", rotated)
cv2.waitKey(0)**
使用 imutils 以 60 度为增量旋转图像
使用 PIL 旋转图像
这里的图像使用 PIL 旋转了 110 度
# Rotate image using PIL
**pil_image= Image.open(r'love.jpg')
rotate_img_pil=pil_image.rotate(110)
rotate_img_pil.show()**
使用 PIL 旋转 110 度的图像
当图像质量因噪声的存在而变差并影响图像分析时,如何增强图像质量?
利用 OpenCV 实现图像去噪
噪声是不想要的信号,就图像而言,它是颜色的随机变化。
使用 OpenCV 最小化图像中的噪声。
**image= cv2.imread(r'taj.jpg')
cv2.namedWindow("Noised Image", cv2.WINDOW_NORMAL)
cv2.imshow("Noised Image", image)
cv2.waitKey(0)**
OpenCV 中有不同的方法来去除图像中的噪声。下面用的是cv . fastnlmeansdenoisingcolored(),就是去除彩色图像中的噪点。
fast nimeans 降噪方法的常见参数有
- src :来源图片
- dst :输出与 src 相同大小和类型的图像
- h :调节过滤强度。较高的 h 值完美地去除了图像细节中的噪声,较小的 h 值将保留图像细节和一些噪声。
- hForColorComponents :与 h 相同,但仅用于彩色图像,通常与 h 相同
- templateWindowSize :应该是奇数。(推荐 7)
- searchWindowSize :应该是奇数。(推荐 21)
**image= cv2.imread(r'taj.jpg')
cv2.namedWindow("Denoised Image", cv2.WINDOW_NORMAL)
denoised_image = cv2.fastNlMeansDenoisingColored(image,None, h=5)
cv2.imshow("Denoised Image", denoised_image)
cv2.waitKey(0)**
如何从一幅图像中提取某些感兴趣的区域?
裁剪图像
裁剪图像可让您提取图像中感兴趣的区域。
我们将裁剪泰姬陵的图像,只保留泰姬陵,并删除图像中的其他细节。
使用 OpenCV 裁剪图像
OpenCV 中的裁剪是通过对图像数组进行切片来完成的,我们通过 y 坐标的起点和终点,然后是 x 坐标的起点和终点。
图像【y_start:y_end,x _ start:x _ end】
**image= cv2.imread(r'taj.jpg')
resized_img= image[15:170, 20:200]
cv2.imshow("Resize", resized_img)
cv2.waitKey(0)**
使用 PIL 裁剪图像
PIL 的 crop() 允许我们裁剪图像的一个矩形区域,参数 crop() 是 左坐标、上坐标、右坐标和下像素坐标。
# Opens a image in RGB mode
**pil_image = Image.open(r'taj.jpg')**
# Get the Size of the image in pixels
**width, height = pil_image.size**
# Setting the cropped image co-ordinates
**left = 3
top = height /25
right = 200
bottom = 3 * height / 4**
# Crop the image based on the above dimension
**cropped_image = pil_image.crop((left, top, right, bottom))**
# Shows the image in image viewer
**cropped_image.show()**
使用 PIL 裁剪图像
模板匹配
您可以提供一个模板,并使用 OpenCV 的match template()在图像中搜索该模板并提取其位置。
模板像卷积神经网络一样在整个图像上滑动,并试图将模板与输入图像匹配。
minMaxLoc() 用于获取最大/最小值,它将是矩形的左上角连同宽度和高度。
有 6 种方法可用于模板匹配
- cv2。TM_SQDIFF
- cv2。TM_SQDIFF_NORMED
- cv2。TM_CCORR
- cv2。TM_CCORR_NORMED
- cv2。TM_CCOEFF
- cv2。TM_CCOEFF_NORMED
在下面的例子中,我从主图像中裁剪了一小部分来创建模板。
用于模板匹配的方法是 TM_CCOEFF_NORMED。匹配的阈值设置为 0.95。它定位具有大于 95%的较高匹配概率的位置,然后在对应于匹配的区域周围绘制矩形。
import cv2
**import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread(r'love.jpg',0)****cv2.imshow("main",img)
cv2.waitKey(0)****template = cv2.imread(r'template1.png',0)
cv2.imshow("Template",template**)
**cv2.waitKey(0)****w, h = template.shape[::-1]
methods = [ 'cv2.TM_CCOEFF_NORMED']****for meth in methods:
method = eval(meth)**# Apply template Matching
**res = cv2.matchTemplate(img,template,method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
threshold=0.95
loc=np.where(res>threshold)
if len(loc[0])>0:**# If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
**if method in [ cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
bottom_right = (top_left[0] + w, top_left[1] + h)****cv2.rectangle(img,top_left, bottom_right,100,20)****plt.subplot(121),plt.imshow(res,cmap = 'gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img,cmap = 'gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.suptitle(meth)****plt.show()
else:
print("Template not matched")**
结论:
我们已经讨论了最常见的图像处理技术,这些技术可用于图像分类、对象检测以及 OCR 的图像分析。
参考资料:
[## OpenCV:模板匹配
在本章中,您将学习模板匹配是一种搜索和查找模板位置的方法…
docs.opencv.org](https://docs.opencv.org/master/d4/dc6/tutorial_py_template_matching.html) [## 参考—枕头(PIL 叉)3.1.2 文件
编辑描述
pillow.readthedocs.io](https://pillow.readthedocs.io/en/3.1.x/reference/)
https://opencv-python-tutroals.readthedocs.io/en/latest/
引用完整性经常被忽略,但却很重要
原文:https://towardsdatascience.com/common-issues-founded-with-referential-integrity-fc05e93693a1?source=collection_archive---------27-----------------------
让我们来看看数据完整性的一个关键组成部分的常见情况。
法比奥在 Unsplash 上的照片
引用完整性的重要性
引用完整性是一个简单但强大的工具。在数据湖、个性化推荐和深度数据分析工具的世界里,基本概念有时会被遗忘。但是我们不能放弃。当我们设计数据模型时,这个概念应该一直在我们的脑海中。它是数据系统中数据完整性的支柱。
我假设本文的所有潜在读者都知道如何实现它,但是简单的提醒总是有用的。引用表(数据集,数据实体)的外键仍必须引用和被引用表中的有效行。参照完整性确保两个表之间的关系在执行更新和删除指令期间保持同步。
在左边的一般情况下—在右边的特定示例情况下
当然,在标准生活应用中,设计越来越复杂,结构具有嵌套和圆形形式:
虽然我将要提出的清单并不详尽,但它代表了现实世界的问题。注意,这些问题都是我在职业生涯中发现的。没有猜测,也没有二手故事。我知道有些用户案例和项目不需要引用完整性(但我认为大多数生活应用程序需要引用完整性)。让我们一起来回顾一下这些令人痛心的案例:
引用完整性不适用
这是最糟糕的情况,不仅仅是因为后果(数据丢失、重复、数据丢失、内部不一致等),还因为它意味着:
- 缺乏知识
最初的开发者 d 根本不知道引用完整性。我在不止一个初创企业和小企业中看到过这个问题。通常,造成这种混乱的罪魁祸首是来自不同业务部门的人,他们做得很快,或者是非开发人员重新转变为开发人员。 - 完全不小心
对我来说,这是最痛苦的。而肇事者知道如何正确实施,却不去做。最典型的借口是:这是一个订单,我想缩短上市时间,或者这只是一个概念证明。
参照完整性的设计错误
也许这可以包括在缺乏知识这一点中,但是在这种情况下,开发/数据人员知道引用完整性。尽管如此,由于执行不力,最终结果是错误的。这些是我经常发现的情况:
- 忘记添加两个或多个表之间的关系。
- 忘记添加确保级联更新和删除的触发器。
- 应用了错误的数据完整性类型。最常见的是在部分完整性是正确选择时使用弱完整性(反之亦然,这很常见)。但是我也看到了不同组合的错位:弱完整代替强,部分完整代替强,强完整代替部分,等等。
引用完整性由应用程序应用,而不是由数据库引擎应用
让我明确这一点:如果可能的话,依靠数据库引擎。这样做,你就可以避免将来的问题。这是一个明显的重新发明轮子的场景:在最好的情况下,你的开发会像预期的那样工作。在最坏的情况下,您将不得不处理一个巨大的混乱,混合和丢失的数据。客户、合作伙伴、同事和经理会对你大喊大叫,要求你提供一个很可能是不可能的解决方案。
请记住,即使有一个好的初始设计和完美的实现,在未来的开发迭代中,总有添加 bug 的风险。当我们谈到数据完整性时,一个小错误可能会产生相当大的影响,以后可能会有一个很难解决的问题。此外,其他部门可能会访问原始数据,并由于数据库引擎中缺乏一致性而产生问题。
此外,DB 引擎一直以提供最佳性能而著称。投入时间和资源来达到 DB 默认提供的相同结果是一个非常糟糕的主意。
数据库引擎没有引用完整性功能
一个很好的例子是在 MongoDB 版本 4 之前的实现。我听过几次断言在非 SQL 数据库中不需要添加参照完整性。我完全不同意这样的肯定。虽然引用完整性对任何关系数据库都是至关重要的,但它对非 SQL 数据库也很有用。
我将用一个例子来说明这一点。首先,我们来看下面这个集合:
这样的设计将对应于一个希望以最快的方式提供 Book 元素的系统,就像在一个高需求的 GET RESTful 端点中所需要的那样。
现在来看看这两个系列:
该模型将允许执行更*滑的聚合操作和更好的性能。它还可以在作者之间提供更有效的查询。这并没有放弃第一个解决方案的面向文档的设计(但是检索书籍的性能较低)。最后,我的观点是,对于使用非纯关系数据库,当需要引用完整性时,您不应该放弃它。
Python 中常见的机器学习编程错误
原文:https://towardsdatascience.com/common-machine-learning-programming-errors-in-python-5d76de85e975?source=collection_archive---------28-----------------------
机器学习中常见的 Python 错误
马库斯·斯皮斯克在的照片
在这篇文章中,我将回顾我在 python 建模和开发过程中遇到的一些最常见的错误。出于演示目的,我们将使用在 Kaggle 上可以找到的身高/体重数据。数据包括性别、身高(英寸)和体重(磅)。
根据我的经验,最常见的错误如下:
进口
- 名称错误
- ModuleNotFoundError
- 属性错误
- 导入错误
读取数据
6.FileNotFoundError
选择列
7.键盘错误
数据处理
8.值错误
我们将构建一个简单的线性回归模型,并修改代码以显示上述错误在实践中是如何出现的。
首先让我们使用 pandas 导入数据并打印前五行:
import pandas as pd
df = pd.read_csv("weight-height.csv")
print(df.head())
如你所见,数据集非常简单,有性别、身高和体重三列。接下来我们可以使用 matplotlib 和 seaborn 来可视化数据:
import matplotlib.pyplot as pltplt.scatter(df['Weight'], df['Height'])
plt.xlabel("Weight")
plt.ylabel("Height")
plt.show()
从体重与身高的散点图中我们可以看出,这种关系是线性的。
接下来,让我们定义我们的输入(X)和输出(y ),并为训练和测试拆分数据:
from sklearn.model_selection import train_test_split
import numpy as npX = np.array(df["Weight"]).reshape(-1,1)
y = np.array(df["Height"]).reshape(-1,1)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42, test_size = 0.33)
然后,我们可以定义线性回归模型,拟合我们的训练数据,对测试集进行预测,并评估模型的性能:
from sklearn.linear_model import LinearRegression
reg = LinearRegression()
reg.fit(X_train, y_train)
y_pred = reg.predict(X_test)
print("R^2 Accuracy: ", reg.score(X_test, y_test))
我要讨论的第一个错误是 NameError ,例如,如果我忘记导入一个包,就会出现这个错误。在下面的代码中,我删除了“import numpy as np”:
from sklearn.model_selection import train_test_splitX = np.array(df["Weight"]).reshape(-1,1)
y = np.array(df["Height"]).reshape(-1,1)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42, test_size = 0.33)
如果我试图在缺少该行代码的情况下运行脚本,我会得到以下错误:
我会收到类似的消息,因为我忽略了 seaborn、matplotlib 和 pandas 的导入语句:
另一个问题是意外地试图导入一个由于拼写错误而不存在的包,这导致了一个 ModuleNotFoundError 。例如,如果我将“pandas”拼错为“pandnas”:
import pandnas as pd
或者,如果我忘记了 matplotlib 散点图导入中的“pyplot ”,我们会得到一个 AttributeError :
import matplotlib as plt
类似地,如果我忘记了 sklearn 导入中的 linear_regression 和 model_selection 属性,我将得到一个 ImportError :
from sklearn import LinearRegression
from sklearn import train_test_split
在读取文件方面,如果我拼错了文件名,我会得到一个 FileNotFoundError :
df = pd.read_csv("weight-heigh1t.csv")
此外,如果我试图从 pandas 数据框中选择一个不存在的列,我会得到一个 KeyError :
plt.scatter(df['Weight1'], df['Height'])
如果我忘记将 pandas 系列的“体重”和“身高”转换成 numpy 数组,我会得到一个值 Error 。这是因为 sklearn 方法只接受 numpy 数组。我经常发现自己忘记了从 pandas 系列转换到 numpy 数组的简单步骤:
X = df["Weight"]
y = df["Height"]
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42, test_size = 0.33)reg = LinearRegression()
reg.fit(X_train, y_train)
或者,如果我忘记将 numpy 数组整形为一个二维数组,我也会得到一个值 Error :
X = np.array(df["Weight"])
y = np.array(df["Height"])
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42, test_size = 0.33)reg = LinearRegression()
reg.fit(X_train, y_train)
导致值错误的另一个常见原因是在进行列车试运行时。我经常忘记 X 和 y 数组的顺序:
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42, test_size = 0.33)
其中我切换 X_test 和 y_train:
X_train, y_train, X_test, y_test = train_test_split(X, y, random_state = 42, test_size = 0.33)
这在拟合时给出了以下误差:
最后,当试图拟合与特定类别或人群相对应的模型数据时,我经常会遇到没有足够数据的问题。让我们过滤我们的数据框架来重现这个问题。让我们过滤数据,只包括“权重”等于 241.893563 的记录。这将产生恰好一行数据:
df = df[df['Weight'] == 241.893563]
如果我们尝试构建我们的模型,我们会在拆分数据的行中得到以下错误:
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42, test_size = 0.33)reg = LinearRegression()
reg.fit(X_train, y_train)
y_pred = reg.predict(X_test)print("R^2 Accuracy: ", reg.score(X_test, y_test))
如果我们试着去适应,我们会得到下面的错误:
#X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42, test_size = 0.33)reg = LinearRegression()
reg.fit(X, y)
最后,如果数据有缺失值或无穷大值,fitting while 将抛出一个错误。让我们用“nan”(非数字)值重新定义 weight 列,以生成以下错误:
df['Weight'] = np.nanX = np.array(df["Weight"]).reshape(-1,1)
y = np.array(df["Height"]).reshape(-1,1)X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42, test_size = 0.33) reg = LinearRegression()
reg.fit(X_train, y_train)
我们会得到相同的错误消息,其中包含无限个值:
df['Weight'] = np.infX = np.array(df["Weight"]).reshape(-1,1)
y = np.array(df["Height"]).reshape(-1,1)X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42, test_size = 0.33)reg = LinearRegression()
reg.fit(X_train, y_train)
在这篇文章中,我们回顾了用 python 开发模型时出现的不同错误。我们回顾了与导入包、读取文件、选择列和处理数据相关的错误。在生产机器学习代码时,对开发机器学习模型时出现的不同类型的错误有扎实的知识会很有用。了解这一点可以防止错误发生,并在错误发生时通知可用于捕捉这些错误的逻辑。
我每天都会遇到更多的错误,但我在这篇文章中列出的错误是我经验中最常见的。我希望这篇文章有用。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!
常见 Pipenv 错误
原文:https://towardsdatascience.com/common-pipenv-errors-3a6f8ce81562?source=collection_archive---------14-----------------------
Pipenv 错误及其解决方案的集合。
作者: Edward Krueger 数据科学家兼讲师和 Douglas Franklin 助教兼开发者倡导者。
在本文中,我们将讨论 Pipenv 虚拟环境,在您的机器上的什么地方使用它们,如何利用 Pipfile 和 Pipfile.lock 特性,以及当这些操作不正确时可能出现的一些问题。我们从为什么环境对于数据科学和软件开发至关重要开始。
开发者最好的朋友:照片由 Timothy Dykes 在 Unsplash 上拍摄
有关 Pipenv 环境或入门的更多信息,请查看本文
数据科学和部署问题
数据科学家通常是跨学科的,他们还没有开发出编码技能来与其他人合作并将项目推向生产。因此,通常缺乏环境和依赖性管理技能。这给代码可复制性和项目协作带来了困难。其他人可以轻松地重新创建、修改和运行的数据科学项目是可复制的数据科学项目
正确执行的环境管理实践减少了项目之间的依赖版本冲突,并防止开发环境变得臃肿和不可管理,从而帮助用户创建可重复的项目。
Pipenv 是什么?
Pipenv 将软件包管理和虚拟环境控制结合到一个工具中,用于安装、删除、跟踪和记录您的依赖关系;以及创建、使用和管理您的虚拟环境。Pipenv 将 pip 和 virtualenv 结合成一个产品。有关 Pipenv 或虚拟环境的更多信息,请查看本文!
Pipenv 将包管理和虚拟环境控制结合到一个工具中,使其成为数据科学家和开发人员的绝佳工具。
Pipenv 基于每个项目来管理依赖项,因此最好在项目目录中使用 Pipenv。要安装软件包,请转到您的项目目录并运行:
$ cd myproject
$ pipenv install requests
当您使用 Pipenv 开始一个项目时,该工具会自动创建一个虚拟环境、一个 Pipfile 和一个 Pipfile.lock。Pipfile 存储运行项目代码所需的包或依赖项。对于那些使用 pip 开发的人来说,Pipfile 非常类似于 requirements.txt 文件。Pipfile.lock 存储特定的依赖版本,这些版本支持环境的确定性构建。当您使用pipenv install
来获得一个新的依赖项时,Pipfile 和 Pipfile.lock 会自动用这个新的依赖项进行更新。在上面的例子中,您的 Pipfile 将包含包“requests”,而您的 Pipfile.lock 将包含已安装的版本。
常见问题:虚拟环境和 Pipfile 位置
使用 Pipenv,您需要为每个项目创建一个新目录。这允许您隔离依赖项及其关联的文件。这通常是一个好的实践,尤其是在创建隔离的开发环境时。
> mkdir new_project> cd new_project> pipenv install pandas matplotlib
完成上述命令后,您将拥有一个需要 Python、Pandas 和 Matplotlib 的项目的基础设施。这个基础结构由目录 new_project、包含已安装包的 Pipfile 和包含它们的特定版本的 Pipfile.lock 组成。
为每个项目创建一个新的目录和 Pipenv 环境将使您的机器保持有序,并允许从一个项目到另一个项目的无缝转换。要参与项目,请切换到一个新目录,并通过运行以下命令激活该目录的环境:
> pipenv install> pipenv shell
丢失的 pip 文件
假设出于某种原因,你在一个奇怪的地方有一个 Pipfile,比如在根目录下。当你使用
> pipenv install
例如,在一个较低的目录~/Desktop/new_project
中,Pipenv 将找到并使用根目录下的 Pipfile。这实际上阻止了您使用该包来管理依赖项。在本例中,在根目录下有一个 Pipfile,它为您在较低目录下创建的所有 Pipenv 虚拟环境提供资源。如果您遇到这种情况,您必须删除导致问题的杂散 pip 文件。
现在我们将重新创建这个错误。下面是一个没有 Pipfile 放在根目录那么极端的例子,但是将说明相同的概念,在路径的一个级别上有一个 Pipfile,然后尝试在该路径的较低级别上创建另一个 Pipfile。
这里我们已经创建了目录 pipenv_nesting_test 并运行pipenv install pandas
。请注意,这将在该目录中创建 Pipfile 和 Pipfile.lock。
更高级目录中的 Pipfile
请注意,Pipfile 与 nested_directory 处于同一级别。现在我们将导航到这个目录并运行pipenv install matplotlib
。
安装 matplotlib
注意,在运行ls
之后,没有生成 Pipfile 或 Pipfile.lock。这是因为 Pipenv 找到了路径中较高位置的 Pipfile,并修改了这些文件中的数据以包含 matplotlib。下面我们使用cat ../Pipfile
来可视化 matplotlib 确实已经被添加到路径中更高的 Pipfile 中。
包含熊猫和 matplotlib 的 Pipfile
将 pip 文件保存在它们的项目目录中是避免在您的机器上出现不明确或不确定的 pip 文件的最好方法。此外,当您在一个在线项目存储库中有一个 pip 文件时,例如 Github,其他用户可以很容易地克隆您的 repo,从 pip 文件重新创建您的环境,并运行您的代码!
常见问题:锁定失败
锁定失败!
Pipfile.lock 是做什么的?
当您使用命令pipenv install
时,会创建一个 Pipfile.lock 文件。此外,命令pipenv lock
可以用来创建一个Pipfile.lock
,它在最新可用版本中声明项目的所有依赖项(和子依赖项),并存储下载文件的当前散列。这意味着依赖项和子依赖项的所有特定版本都存储在 Pipfile.lock 中。这确保了可重复的,最重要的是, 确定性的 构建。然而,许多不良做法可能导致锁定失败。下面我们将介绍一些避免和解决这个问题的方法。
命令pipenv install
首先尝试从 Pipfile.lock 构建虚拟环境,如果 Pipfile.lock 不可用,Pipenv 将从 Pipfile 创建虚拟环境,然后创建 Pipfile.lock。
锁定问题:Pipfile 包含对不存在的包的引用
Pipfile.lock 在尝试安装不存在的软件包(即错别字)时不会锁定。
pipenv install panadas
Pipenv 查找您指定的包,不管它是否存在。当包不存在或由于其他原因找不到时,您会在终端中看到以下错误以及更多错误。现在,我们将把重点放在这两个方面。
安装错别字
Pipenv 找不到 Panadas 的版本
锁定失败!请注意,“panadas”被添加到 Pipfile 的包中。这种打字错误将成为一个问题,因为现在我们的 Pipfile 包含一个错误,任何使用这个 Pipfile 的人都会遇到锁定和依赖错误。请注意,“安装成功”警报是不真实的;没有要安装的 Panadas。所发生的只是将“panadas”添加到 Pipfile 中。Pipfile 中的拼写错误是锁定失败的最常见原因。
只要 Pipfile 中存在这种输入错误,安装一个包,不管存在与否,都会导致锁定失败。您需要在文本编辑器中修复 Pipfile。我用的是纳米。你可以使用任何你觉得舒服的编辑器;Sublime,VS 代码,Atom 等。简单地把 Panadas 改成熊猫然后pipenv install.
现在让我们看看锁定失败时控制台中出现的其他一些错误消息。
注意建议pipenv install --skip-lock
。这应该只在极端或因果编程环境中使用,因为它绕过了 Pipfile。锁的主要用途;锁定软件包版本并创建安装环境依赖项的公式。
当在另一台机器上克隆存储库时,可能会遇到 Pipfile.lock 不兼容问题。这是因为 Pipfile.lock 是特定于系统的。如果合作开发人员使用不同的系统,即 macOS 和 Windows,最好删除 Pipfile.lock,让每个系统解决其依赖性。在这种情况下,确保每个人都使用相同版本的包,方法是手动将它们固定在 Pipfile 中。
锁定失败的另一个常见原因是,如果 Pipfile 中的包只作为预发布版本存在。要允许预发布软件包,您必须在 install 命令中添加— pre 标志,否则锁定将会失败。
pipenv install --pre black
您可以通过在安装命令pipenv install --pre
中添加 pre 标志来解决预发布版本冲突。在这个命令之后,您的 Pipfile 有了一个新变量;allow_prereleases = true。请注意,这将允许在您的环境中安装任何预发行软件包。现在是固定特定包版本有用的时候了。固定版本是一个很好的习惯,可以防止将来出现依赖问题。
允许 Pipfile 中的预发布
Pipfile 管理:指定 Python 版本
请注意上面“要求”部分下的 Pipfile 图像;你看 python_version = 3.7。Pipenv 可用于指定 Python 版本和包版本。
要使用特定的 Python 版本构建 Pipfile 或环境,请使用以下语法。
pipenv --python <path>
#or
pipenv --python python3
注意:需要时可以指定包的版本。
展示 pip 文件的样子,并说明您也可以直接在 pip 文件中修改它
pipenv install flask1.1.1
注意,这个版本被固定在下面的 Pipfile 中。
您可能还想直接编辑您的 Pipfile 来更改版本。
常见问题:在虚拟环境中运行 Jupyter
许多数据科学家使用 Jupyter 进行探索性数据分析和模型选择。Jupyter 可能很难与包管理器一起使用。但是,我们可以很容易地用 Pipenv 创建一个环境,并用一个内核将其连接到 Jupyter。
在 Jupyter 中,您可以访问指向虚拟环境的 Jupyter 内核。虚拟环境是用 Pipenv 创建的。
Pipenv 自动将项目映射到其特定的虚拟环境。命令pipenv shell
指向你计算机上的一个虚拟环境。虚拟环境以项目根目录的名称加上项目根目录的完整路径的散列(即my_project-a3de50
)进行全局存储。因此,如果您更改项目的路径,就会破坏这样的默认映射,Pipenv 将不再能够找到并使用项目的虚拟环境。
在使用下面的命令之前,您需要知道您的 Python 版本并安装 Jupyter。设置指南可在“Pipenv 工作流教程:Jupyter”标题下的另一篇文章、、、中找到。
将 Pipenv 虚拟环境连接到 Jupyter 内核。首先,运行pipenv shell.
,然后在 shell 中创建 Jupyter 内核,使其指向虚拟环境。
python3.7 -m ipykernel install --user --display-name matpltlib --name matpltlib
当让内核指定一切时,为了安全起见。一些计算机的内核总是被命名为 Python 3,当--display-name
或--name
没有通过时,会覆盖其他虚拟环境。我们建议对--name
和--display-name
使用相同的名称,以避免混淆。
如果你只有一个版本的 Python,你应该可以使用python
而不是上面的python3.7
。如果您使用的是 Mac,默认情况下您将拥有 Python 版本。如果您不确定您使用的是哪个 Python 版本,请查看:
python --version
#and/or
python3 --version
在 Jupyter 中选择内核
完成上述操作后,您现在应该能够运行:
jupyter notebook
或者您更喜欢实验室用户界面和附加功能。
jupyter lab
在 Jupyter Notebook 中,选择“新建”查看下拉列表,查看可用内核列表。请注意,上面第 3 步中创建的“example_env”是内核的名称。
选择笔记本中的内核
在 Jupyter Lab,你必须点击右上角的内核框来访问内核列表。或者,您可以单击“内核”选项卡,然后选择“更改内核”来访问同一个下拉菜单。
实验室中选择内核的两个位置
测试导入
在一个新的。ipynb 文件,尝试在单元格中运行以下代码。
import pandas
如果成功的话,你正在改进你的开发工作流程!
如果出现任何问题,请确保您选择了正确的内核,在连接内核和运行jupyter lab
或jupyter notebook
之前,您已经运行了pipenv shell
。
结论
Pipenv 是开发人员和数据科学家的优秀工具。然而,在学习这些工具和方法时,我们会遇到一些常见的错误。对于 Pipenv,Pipfile.lock 在默认情况下固定特定的版本;然而,由于提到的锁定问题和其他复杂性,当在开发人员之间共享时,锁可能会失败。因此,将您的依赖项固定在 Pipfile 中用于生产是一个最佳实践,并且在从 Pipfile.lock 构建环境时要小心。此外,在共享 Pipfile 或使用它来构建环境之前,您需要检查您的 Pipfile 是否有拼写错误!
Jupyter 笔记本是学习代码或制作使用代码创建可视化的报告的有用工具。在 Pipenv 虚拟环境中使用 Jupyter 可以让您将所有环境依赖项导入笔记本,从而简化依赖项管理。将虚拟环境连接到 Jupyter 内核可能会很棘手,但是如果您按照上面的步骤操作,应该没有任何困难!
作为数据科学家和开发人员,正确的开发、打包和虚拟环境管理实践都是需要学习的关键技能。使用 Pipenv 来管理虚拟环境可以加速生产,并允许您创建确定性的构建来复制代码和将项目推向生产。
将 pip 文件保存在它们的项目目录中是避免在您的机器上出现任何含糊不清或杂乱无章的 pip 文件的方法。此外,当您在一个在线存储库中有一个 Pipfile 时,例如 Github,其他用户可以很容易地克隆您的 repo,重新创建您的环境,并使用您的代码。通过 Pipenv 和 Pipfile,您向其他人展示了一种安装项目依赖项以及测试和开发需求的标准化方法。任何拥有您的 Pipfile 副本的人都可以使用以下内容重新创建您的环境。
pipenv install
这个命令创建一个由 Pipfile 指定的环境。在分享它之前,只要确保它没有打字错误,并且指定了正确的包和 Python 版本就可以了!
我们希望这是信息丰富和有帮助的。祝你好运,继续编码!
常见实践—第 1 部分
原文:https://towardsdatascience.com/common-practices-part-1-6a7c1b2eb6d4?source=collection_archive---------41-----------------------
FAU 讲座笔记关于深度学习
优化者和学习率
FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座
这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!
航行
上一讲 / 观看本视频 / 顶级 / 下一讲
欢迎大家来到今天的深度学习讲座!今天,我们想谈谈常见的做法。你需要知道的在实践中实现一切的东西,
接下来几节课的概述。 CC 下的图片来自深度学习讲座的 4.0 。
因此,我对接下来的几个视频和我们将关注的主题有一个小的概述。因此,我们将思考我们目前面临的问题以及我们已经走了多远。我们将讨论训练策略、优化和学习率,以及一些调整策略、架构选择和超参数优化。一个真正有用的技巧是集合。通常人们不得不处理阶级不*衡,当然,也有非常有趣的方法来处理这个问题。最后,我们来看看评估,以及如何得到一个好的预测器。我们还评估网络的实际运行情况。
神经网络训练概述。 CC 下的图片来自深度学习讲座的 4.0 。
到目前为止,我们已经看到了如何训练网络的所有细节。我们必须完全连接卷积层、激活函数、损失函数、优化、正则化,今天我们将讨论如何选择架构、训练和评估深度神经网络。
只有在我们设置了关于培训过程的所有其他重要选项之后,才会查看测试数据。来自深度学习讲座的 CC BY 4.0 下的图片。
第一件事就是测试。“理想情况下,测试数据应保存在保险库中,仅在数据分析结束时取出。”哈斯蒂和他的同事们正在讲授统计学学习的要素。
过拟合神经网络很容易实现。因此,我们必须谨慎地做出许多选择。 CC 下的图片来自深度学习讲座的 4.0 。
所以,首先,神经网络很容易过度拟合。记住 ImageNet 随机标签。当您使用测试集进行模型选择时,真正的测试集误差和泛化能力可能会被大大低估。因此,当我们选择架构时——通常是模型选择中的第一个元素——这永远不应该在测试集上进行。我们可以对数据的一个较小的子集进行初步实验,试图找出什么有效。当你做这些事情的时候,千万不要在测试集上工作。
使用数字渐变检查您的渐变实现。 CC 下的图片来自深度学习讲座的 4.0 。
让我们来看看几个训练策略:在训练之前,检查你的梯度,检查损失函数,检查自己的层实现,它们正确地计算结果。如果您实现了自己的图层,请比较解析梯度和数值梯度。你可以用中心差分来表示数字渐变。你可以用相对误差代替绝对差异,并考虑数字。使用双精度进行检查,暂时调整损失函数,如果观察到非常小的值,适当选择您的 h 作为步长。
梯度调试的更多提示。 CC 下的图片来自深度学习讲座的 4.0 。
然后,我们有几个额外的和建议:如果你只使用几个数据点,那么损失函数的不可微部分的问题会更少。您可以在短时间内训练网络,然后再执行梯度检查。可以先查梯度,再用正则项。所以,你首先关闭正则项,检查梯度,最后用正则项。此外,关闭数据增强并退出。因此,您通常在相当小的数据集上进行这种检查。
也检查你的初始化。来自深度学习讲座的 4.0CC 下的图片。
初始化的目标是对层进行正确的随机初始化。因此,您可以在关闭正则化的情况下计算未训练网络上每个类的损失,当然,这应该会给出一个随机分类。所以在这里,我们可以将这种损失与随机选择课程时的损失进行比较。它们应该是相同的,因为你是随机初始化的。重复多次随机初始化,以检查初始化是否没有问题。
训练前测试训练设置。 CC 下的图片来自深度学习讲座的 4.0 。
我们去训练吧。首先,您检查架构是否总体上能够学习任务。因此,在使用完整数据集训练网络之前,您需要数据的一个小子集。也许 5 到 20 个样本,然后尝试使网络过载以获得零损失。用这么少的样本,你应该能够记住整个数据集。尽量做到零损失。然后,你知道你的训练程序实际上是有效的,你真的可以降到零损失。或者,您可以关闭正则化,因为它可能会阻碍这种过度拟合过程。现在,如果网络不能过度拟合,你可能在实现中有一个 bug,或者你的模型可能太小。因此,您可能希望增加参数/模型容量,或者只是模型可能不适合此任务。此外,首先要了解数据、丢失和网络的行为。
损耗曲线有助于识别爆炸和消失梯度。来自深度学习讲座的 CC BY 4.0 下的图片。
记住,我们应该监控损失函数。这些是典型的损失曲线。确保没有爆炸或消失的渐变。你想要有适当的学习率,所以检查学习率以识别学习曲线中的大跳跃。如果您有非常嘈杂的曲线,尝试增加批量大小。噪音损失曲线可能与过小的小批量有关。
监控验证损失将有助于您在训练期间发现过度拟合。 CC 下的图片来自深度学习讲座的 4.0 。
接下来,获取验证数据集并监控验证损失。你记得,这个图像:随着时间的推移,你的训练损失当然会下降,但是测试损失会上升。当然,您从来没有在测试数据集上计算过,但是您将验证集作为测试损失的替代。然后,您可以确定您的网络中是否出现过拟合。如果训练和验证有分歧,你有过度拟合。所以,你可能想增加正则化或尝试早期停止。如果训练和验证损失很接*,但非常高,您可能有欠拟合。因此,减少正则化并增加模型大小。您可能想要保存中间模型,因为您可以在以后的测试中使用它们。
查看经过训练的卷积核可以帮助识别噪声模式检测器。 CC 下的图片来自深度学习讲座的 4.0 。
此外,在训练期间,监控重量和激活。跟踪权重更新的相对幅度。他们应该在一个合理的范围内,也许是 10⁻。在卷积层中,您可以检查前几层的滤波器。它们应该朝着*滑和规则的过滤器发展。你可能想检查一下。你需要像这里一样的过滤器,在右手边。左手边的那些包含相当多的噪声,并且这可能不是非常可靠的特征。你可以从这里开始建造一个噪音探测器。所以这可能是个问题。此外,检查大量饱和激活。请记住,死亡可能会发生。
小费选择优化。来自深度学习讲座的 CC BY 4.0 下的图片。
所以让我们看一下优化和学习率。你想选择一个优化器。现在批量梯度下降需要大内存,太慢,更新太少。所以人们追求的是典型的随机梯度下降。这里,损失函数和梯度变得非常嘈杂,特别是,如果你只使用你的一个样本。你想要小批量的。小批量是两全其美的。它具有频繁但稳定的更新,并且梯度的噪声足以避开局部最小值。因此,您希望根据您的问题和优化调整小批量大小,以产生更*滑或更嘈杂的梯度。此外,您可能希望使用动量来防止振荡并加速优化。超参数的影响相对简单。我们的建议是你从小批量、梯度下降和动量开始。一旦你有了一个好的参数集,你就可以使用 Adam 或者其他优化器来优化不同的权重。
时刻关注亏损曲线。 CC 下的图片来自深度学习讲座的 4.0 。
记住观察损失曲线。如果你的学习速率设置不正确,你在网络的训练中就有麻烦了。对于几乎所有基于梯度的优化器,你必须设置η。所以,我们经常直接在损失曲线中看到,但这是一个简化的视图。因此,我们实际上希望有一个自适应的学习速率,然后逐步用更小的步骤找到最优。正如我们已经讨论过的,你需要调整学习速度。
关于如何提高学习速度的提示。来自深度学习讲座的 CC BY 4.0 下的图片。
现在,学习率衰减是你必须以某种方式设置的另一个超参数。你要避免振荡以及过快的冷却。所以,有几个衰变策略。逐步衰减每 n 个时期,你以某一因子降低学习率,如 0.5,常数值如 0.01,或者当验证误差不再降低时,你降低学习率。在每个时期都有指数衰减,你可以用这个指数函数来控制衰减。还有 1/t 衰减,在时间 t,你基本上用 1 / (1 + kt )来缩放初始学习速率。逐步衰减是最常见的,超参数也很容易解释。二阶方法目前在实践中并不常见,因为它们不能很好地扩展。这么多关于学习率和一些相关的超参数。
在这个深度学习讲座中,更多令人兴奋的事情即将到来。来自深度学习讲座的 CC BY 4.0 下的图片。
下一次在深度学习中,我们将进一步研究如何调整我们刚刚发现的所有超参数。你会发现这些提示对你自己的实验非常有价值。非常感谢大家的聆听,下节课再见!
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。
参考
[1] M. Aubreville,M. Krappmann,C. Bertram 等,“用于组织学细胞分化的导向空间转换器网络”。载于:ArXiv 电子版(2017 年 7 月)。arXiv: 1707.08525 [cs。简历】。
【2】詹姆斯·伯格斯特拉和约舒阿·本吉奥。“随机搜索超参数优化”。在:j .马赫。学习。第 13 号决议(2012 年 2 月),第 281-305 页。
【3】让·迪金森·吉本斯和 Subhabrata Chakraborti。“非参数统计推断”。载于:国际统计科学百科全书。斯普林格,2011 年,第 977-979 页。
[4]约舒阿·本吉奥。“深度架构基于梯度训练的实用建议”。《神经网络:交易的诀窍》。斯普林格出版社,2012 年,第 437-478 页。
[5]·张,Samy Bengio,Moritz Hardt 等,“理解深度学习需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。
[6]鲍里斯·T·波亚克和阿纳托利·B·朱迪斯基。“通过*均加速随机逼*”。摘自:SIAM 控制与优化杂志 30.4 (1992),第 838-855 页。
【7】普拉吉特·拉马钱德兰,巴雷特·佐夫,和阔克诉勒。“搜索激活功能”。载于:CoRR abs/1710.05941 (2017 年)。arXiv: 1710.05941。
[8] Stefan Steidl,Michael Levit,Anton Batliner 等,“所有事物的衡量标准是人:情感的自动分类和标签间的一致性”。在:过程中。ICASSP 的。电气和电子工程师协会,2005 年 3 月。
常见实践—第 2 部分
原文:https://towardsdatascience.com/common-practices-part-2-23dad51e2aae?source=collection_archive---------44-----------------------
FAU 讲座笔记关于深度学习
超参数和集合
FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座
这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!
航行
上一讲 / 观看本视频 / 顶级 / 下一讲
欢迎大家来深度学习!因此,今天我们想进一步了解常见实践,特别是在本视频中,我们想讨论架构选择和超参数优化。
记住:测试数据还在保险库中! CC 下的图片来自深度学习讲座的 4.0 。
请记住,测试数据仍在保险库中。我们不碰它。然而,我们需要以某种方式设置我们的超参数,你已经看到有大量的超参数。
许多超参数与我们的训练过程相关。 CC 下的图片来自深度学习讲座的 4.0 。
您必须选择架构、层数、每层的节点数、激活函数,然后您拥有优化中的所有参数:初始化、损失函数等等。优化器仍然有选项,如梯度下降的类型、动量、学习率衰减和批量大小。在正则化中,有不同的正则化 L2 和 L1 损失,批量归一化,辍学,等等。你想以某种方式算出这些不同种类的程序的所有参数。
架构的选择对您的系统至关重要。来自深度学习讲座的 CC BY 4.0 下的图片。
现在,让我们选择一个架构和损失函数。第一步是考虑问题和数据。特征看起来像什么?你期望什么样的空间相关性?什么样的数据增强有意义?课程将如何分配?关于目标应用程序,什么是重要的?然后,你从简单的架构和损失函数开始,当然,你做你的研究。首先尝试知名车型。它们正在被出版,并且有如此多的论文在那里。因此,没有必要事事亲力亲为。在图书馆呆一天可以节省数小时、数周甚至数月的实验时间。做研究。它真的会节省你的时间。通常他们只是不发表论文,但在非常好的论文中,不仅仅是科学结果,他们还分享源代码,有时甚至是数据。试着找到那些文件。这对你自己的实验有很大帮助。因此,您可能需要改变架构,使其适应您在文献中发现的问题。如果你改变了什么,找到好的理由为什么这是一个合适的改变。有相当多的论文似乎将随机变化引入到架构中。后来,事实证明,他们所做的观察基本上是随机的,他们只是运气好,或者在自己的数据上做了足够多的实验,以获得改进。通常,也有一个合理的理由来解释为什么特定的变化会提高性能。
超参数搜索的搜索策略。 CC 下的图片来自深度学习讲座的 4.0 。
接下来,您需要进行超参数搜索。所以你记得学习率衰减,正规化,辍学,等等。这些都要调音。尽管如此,网络可能需要几天或几周的时间来训练,你必须搜索这些超参数。因此,我们建议使用对数刻度。例如对于η,这里是 0.1,0.01 和 0.001。你可以考虑网格搜索或随机搜索。所以在网格搜索中,你会有相等的距离步长,如果你看参考文献[2],他们已经表明随机搜索比网格搜索有优势。首先,它更容易实现,其次,它对影响很大的参数有更好的探索。所以,你可能想看看,然后相应地调整你的策略。所以超参数是高度相互依赖的。您可能希望使用从粗到细的搜索。你在开始时在一个非常粗糙的尺度上进行优化,然后使它变得更精细。你可以只训练网络几个时期,然后将所有的超参数带入合理的范围。然后,您可以使用随机和网格搜索进行细化。
集成旨在融合多个独立的分类器。来自深度学习讲座的 CC BY 4.0 下的图片。
一个非常常见的可以给你一点点性能提升的技术是集成。这也能真正帮助你获得你仍然需要的额外的一点点性能。到目前为止,我们只考虑了单个分类器。集成的想法是使用许多这样的分类器。如果我们假设 N 个分类器是独立的,执行正确预测的概率将是 1 — p。现在,看到 k 个错误的概率是 N 选择 k 乘以 p 到 k 的幂次(1 — p 到的幂次(N — k )。这是一个二项分布。所以,多数意为 k > N /2 错的概率是 N 选择 k 乘以 p 到 k 乘以(1 — p )的幂( N — k )之和。
分类器的集合比单个分类器更强。 CC 下的图片来自深度学习讲座的 4.0 。
所以,我们在下面的图中想象一下。在这个图表中,你可以看到如果我采用更多的弱分类器,我们会变得更强。让我们把他们出错的概率设为 0.42。现在,我们可以计算这个二项分布。在这里,你可以看到,如果我选择 20,我得到的概率约为 14%,多数是错误的。如果我选择 N=32,我得到小于 10%的概率多数是错误的。如果我选择 70,超过 95%的情况下大多数将是正确的。因此,你可以看到,对于较大的 n,这个概率是单调递减的,如果 n 接*无穷大,那么精度将趋向于 1。这里最大的问题当然是独立性。因此,通常情况下,我们会遇到从相同的数据中生成独立分类器的问题。所以,如果我们有足够的数据,我们就可以训练许多独立的弱分类器。那么,我们如何把它作为一个概念来实现呢?我们必须以某种方式产生 N 个独立的分类器或回归器,然后我们通过多数或*均来组合预测。我们如何实际生产这样的组件?
不同的局部最小值产生不同的模型。 CC 下的图片来自深度学习讲座的 4.0 。
嗯,你可以选择不同的型号。在这个例子中,我们看到了一个非凸函数。显然,它们有不同的局部极小值。因此,不同的局部最小值会导致不同的模型,然后我们可以将它们结合起来。此外,你可以尝试一个循环学习率,然后随着学习率上下波动,以避开某些局部极小值。这样,您就可以尝试找到不同的局部最小值,并存储它们以进行组合。
创建不同的或多或少独立的分类器或回归器的一些想法。来自深度学习讲座的 CC BY 4.0 下的图片。
这样,您还可以在优化的不同点提取不同的模型检查点。稍后,您可以重新使用它们进行组装。此外,权重的移动*均 w 可以生成新模型。你甚至可以走这么远,结合不同的方法。所以,我们仍然有传统机器学习方法的完整目录,你也可以训练它们,然后将它们与你的新深度学习模型相结合。通常,如果您只需要一点点,这是一个简单的性能提升。顺便说一下,这也是最终帮助人们打破网飞挑战的想法。前两队差点打破挑战,他们组队训练合奏。这样他们一起打破了挑战。
在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。
因此,下一次在深度学习中,我们将讨论课堂失衡,这是一个非常常见的问题,以及如何在您的培训过程中处理这一问题。非常感谢您的收听,再见!
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。
参考
[1] M. Aubreville,M. Krappmann,C. Bertram 等,“用于组织学细胞分化的导向空间转换器网络”。载于:ArXiv 电子版(2017 年 7 月)。arXiv: 1707.08525 [cs。简历】。
【2】詹姆斯·伯格斯特拉和约舒阿·本吉奥。“随机搜索超参数优化”。在:j .马赫。学习。第 13 号决议(2012 年 2 月),第 281-305 页。
【3】让·迪金森·吉本斯和 Subhabrata Chakraborti。“非参数统计推断”。载于:国际统计科学百科全书。斯普林格,2011 年,第 977-979 页。
[4]约舒阿·本吉奥。“深度架构基于梯度训练的实用建议”。《神经网络:交易的诀窍》。斯普林格出版社,2012 年,第 437-478 页。
[5]·张,Samy Bengio,Moritz Hardt 等,“理解深度学习需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。
[6]鲍里斯·T·波亚克和阿纳托利·B·朱迪斯基。“通过*均加速随机逼*”。摘自:SIAM 控制与优化杂志 30.4 (1992),第 838-855 页。
【7】普拉吉特·拉马钱德兰,巴雷特·佐夫,和阔克诉勒。“搜索激活功能”。载于:CoRR abs/1710.05941 (2017 年)。arXiv: 1710.05941。
[8] Stefan Steidl,Michael Levit,Anton Batliner 等,“所有事物的衡量标准是人:情感的自动分类和标签间的一致性”。在:过程中。ICASSP 的。电气和电子工程师协会,2005 年 3 月。
常见做法—第 3 部分
原文:https://towardsdatascience.com/common-practices-part-3-f4853b0ac977?source=collection_archive---------75-----------------------
FAU 讲座笔记关于深度学习
阶级不*衡
FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座
这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!
航行
上一讲 / 观看本视频 / 顶级 / 下一讲
欢迎回到深度学习!今天,我们想继续谈谈我们的常见做法。我们今天感兴趣的方法是关于阶级不*衡的。因此,一个非常典型的问题是,一门课——尤其是非常有趣的一门课——并不经常上。所以,这是对所有机器学习算法的挑战。
今日问题:如何应对阶层失衡? CC 下的图片来自深度学习讲座的 4.0 。
让我们以欺诈检测为例。在 10,000 笔交易中,9,999 笔是真实的,只有一笔是欺诈性的。所以,如果你把所有东西都归类为正品,你会得到 99.99%的准确率。显然,即使在不太严重的情况下,如果你有一个模型,它会从一百个交易中错误地分类出一个,那么你最终只能得到一个准确率为 99%的模型。这当然是一个很难的问题。特别是,在筛选应用程序时,你必须非常小心,因为仅仅将所有东西归类到最常见的类别中仍然可以获得非常非常好的准确性。
为了评估癌症的侵袭性,有丝分裂细胞是重要的。 CC 下的图片来自深度学习讲座的 4.0 。
不一定是信用卡,比如这里检测有丝分裂细胞就是一个非常类似的问题。有丝分裂细胞是正在进行细胞分裂的细胞。正如我们在引言中所听到的,这些细胞非常重要。如果你计算处于有丝分裂状态的细胞,你就会知道相关的癌症是如何迅速增长的。所以这是一个非常重要的特征,但是你必须正确地检测它们。它们只占组织中细胞的很小一部分。所以,这个类的数据在训练期间被看到得少得多,并且像准确度、L2 范数和交叉熵这样的度量没有显示出这种不*衡。所以,他们对此反应不是很强烈。
欠采样是对抗类不*衡的第一个想法。来自深度学习讲座的 CC BY 4.0 下的图片。
你可以做的一件事是,比如重新采样。这个想法是,你通过对类进行不同的采样来*衡类的频率,所以,你可以理解这意味着你必须丢弃很多最频繁类的训练数据。这样你就可以训练一个分类器来*衡这两个类。现在他们几乎和其他班级一样频繁地出现。这种方法的缺点是,您没有使用所有看到的数据,当然,您也不想丢弃数据。
过采样是处理类不*衡的另一种策略。 CC 下的图片来自深度学习讲座的 4.0 。
另一种技术是过采样。你可以更多地从代表性不足的班级中取样。在这种情况下,您可以使用所有的数据。缺点当然是它会导致对不太常见的例子的过度拟合。欠采样和过采样的组合也是可能的。
SMOTE 是在深度学习中执行重采样的一种相当不常见的方法。更常见的是,您会发现对数据扩充的巧妙使用。来自深度学习讲座的 CC BY 4.0 下的图片。
这就产生了先进的重采样技术,试图避免合成少数过采样的欠采样缺点。在深度学习中相当少见。由欠采样引起的欠拟合可以通过在每个时期之后采用不同的子集来减少。这很常见,你也可以使用数据扩充来帮助减少对代表性不足的类的过度拟合。所以,你实际上增加了更多你不常看到的样本。
一个很常见的选择是根据上课频率调整损耗。 CC 下的图片来自深度学习讲座的 4.0 。
当然,除了固定数据之外,你还可以尝试调整损失函数,使其相对于类别不*衡保持稳定。在这里,您可以选择一个与类别频率相反的损失。然后,您可以创建加权交叉熵,其中您引入了一个额外的权重 w,它被简单地确定为逆类频率。分割问题中更常见的是基于骰子系数的骰子损失。在这里,您将评估测量区域重叠的 dice 系数的损失。这是一种非常典型的用于评估分段而不是类别频率的方法。权重也可以根据其他考虑因素进行调整,但我们不会在本次讲座中讨论它们。
在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。
这已经把我们带到了这一部分的结尾,在通用实践的最后一节,我们现在将讨论评估的方法以及如何恰当地评估我们的模型。所以,非常感谢大家的收听,再见!
如果你喜欢这篇文章,你可以在这里找到更多的文章,在这里找到更多关于机器学习的教育材料,或者看看我们的深度 学习 讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube、Twitter、脸书、LinkedIn 或 T21。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。
参考
[1] M. Aubreville,M. Krappmann,C. Bertram 等,“用于组织学细胞分化的导向空间转换器网络”。载于:ArXiv 电子版(2017 年 7 月)。arXiv: 1707.08525 [cs。简历】。
【2】詹姆斯·伯格斯特拉和约舒阿·本吉奥。“随机搜索超参数优化”。在:j .马赫。学习。第 13 号决议(2012 年 2 月),第 281-305 页。
【3】让·迪金森·吉本斯和 Subhabrata Chakraborti。“非参数统计推断”。载于:国际统计科学百科全书。斯普林格,2011 年,第 977-979 页。
[4]约舒阿·本吉奥。“深度架构基于梯度训练的实用建议”。《神经网络:交易的诀窍》。斯普林格出版社,2012 年,第 437-478 页。
[5]·张,Samy Bengio,Moritz Hardt 等,“理解深度学习需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。
[6]鲍里斯·T·波亚克和阿纳托利·B·朱迪斯基。“通过*均加速随机逼*”。摘自:SIAM 控制与优化杂志 30.4 (1992),第 838-855 页。
【7】普拉吉特·拉马钱德兰,巴雷特·佐夫,和阔克诉勒。“搜索激活功能”。载于:CoRR abs/1710.05941 (2017 年)。arXiv: 1710.05941。
[8] Stefan Steidl,Michael Levit,Anton Batliner 等,“所有事物的衡量标准是人:情感的自动分类和标签间的一致性”。在:过程中。ICASSP 的。电气和电子工程师协会,2005 年 3 月。
常见做法—第 4 部分
原文:https://towardsdatascience.com/common-practices-part-4-70c08fce3588?source=collection_archive---------56-----------------------
FAU 讲座笔记关于深度学习
性能赋值
FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座
这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!
航行
上一讲 / 观看本视频 / 顶级 / 下一讲
最后,我们可以深入研究测试数据。 CC 下的图片来自深度学习讲座的 4.0 。
欢迎大家进入深度学习的下一部分!今天,我们想结束对常见实践的讨论,特别是,我们想看一下评估。当然,我们需要评估到目前为止我们已经训练过的模型的性能。现在,我们已经设置了训练,设置了超参数,并配置了所有这些。现在,我们想要评估之前未见过的数据的泛化性能。这意味着测试数据,是时候打开保险库了。
请记住,我们正在处理的大多数类别都是人造的。其中一些定义可能远不如乍看上去那样清晰。 CC 下的图片来自深度学习讲座的 4.0 。
记住“万物的尺度是人”。因此,数据由人工标注和标记,在训练期间,所有的标记都被认为是正确的。当然,犯错是人之常情。这意味着我们可能有模棱两可的数据。您实际上希望您的数据的理想情况是,它已经由多个人类投票者进行了注释。然后你可以采取*均或多数投票。还有一篇由 Stefan Steidl 在 2005 年发表的非常好的论文。它引入了一种基于熵的测量方法,考虑了人类参考标签的混淆。这在标签不清楚的情况下非常有用。特别是,在情感识别中,这是一个问题,因为人类有时会混淆愤怒和烦恼等类别,而他们不太可能混淆“愤怒”和“快乐”,因为这是一个非常明显的区别。有不同程度的快乐。有时候你只是有点开心。在这些情况下,真的很难区分开心和中立。这对人类来说也很难。在原型中,如果你让演员扮演,你会得到超过 90%的情感识别率。如果你有真实的数据情绪,如果你有日常生活中发生的情绪,那就很难预测了。这也可以在标签和标签的分布中看到。如果你有一个原型,所有的评分者都会同意这个观察显然是这个特殊的类。如果你有细微差别和不那么明确的情绪,你会发现我们的评分者在标签上的分布也不太明显,甚至是均匀的,因为他们也不能评估特定的样本。因此,如果人类也混淆了同一个类,分类器的错误显然不那么严重。这正是 Steidl 基于熵的度量所考虑的。
两类问题的典型评价措施。来自深度学习讲座的 CC BY 4.0 下的图片。
现在,如果我们研究绩效评估,您需要考虑典型的分类评估。它们通常围绕假阴性、真阴性、真阳性和假阳性而建立。从二进制分类问题,你可以计算真和假阳性率。这通常会产生一些数字,比如准确率,即正的数量加上负的数量除以正的数量和负的数量。然后是精确度或阳性预测值,计算方法是真阳性的数量除以真阳性加上假阳性的数量。有一种所谓的召回,它被定义为真阳性与真阳性加上假阴性之比。特异性或真负值是真阴性除以真阴性加上假阳性。F1 分数是混合这些指标的中间方式。你有真正的正值乘以真正的负值,除以两个正值和真正的负值之和。我通常推荐接收机工作特性(ROC)曲线,因为你在上面看到的所有测量都依赖于阈值。如果你有 ROC 曲线,你基本上评估了所有不同阈值的分类器。这将为您分析它在不同场景下的表现。
多类问题的典型措施。来自深度学习讲座的 CC BY 4.0 下的图片。
此外,在多类分类中还有性能测量。这些是上述措施的变通版本。top- K 误差是真实类别标签不在具有最高预测分数的 K 估计中的概率。常见的实现是前 1 名和前 5 名错误。例如,ImageNet 通常使用 top-5 错误。如果你真的想了解多类分类中发生了什么,我建议看看混淆矩阵。混淆矩阵对 10 到 15 个班级很有用。如果你有一千个类,混淆矩阵不再有任何意义。尽管如此,如果您在类较少的情况下查看混淆矩阵,您可以对正在发生的事情有更多的了解。
交叉验证是估计样本外误差的常用工具。 CC 下的图片来自深度学习讲座的 4.0 。
现在,有时你只有很少的数据。因此,在这些情况下,您可能希望选择交叉验证。在 k 倍交叉验证中,您将数据分成 k 倍,然后使用 k-1 倍作为训练数据,并在 k 倍上进行测试。然后,重复 k 次。这样,你在评估数据中看到了所有的数据,但是你是在独立数据上训练的,因为你在训练的时候拿出来了。这在深度学习中相当少见,因为这意味着非常长的训练时间。你必须重复整个训练 K 次,如果你训练 7 天,这真的很难。如果你有七次交叉验证,你知道你可以做数学,这将需要很长时间。如果用于超参数估计,就得嵌套。不要只对所有数据进行交叉验证,选择超参数,然后对相同的数据进行测试。这会给你带来乐观的结果。你应该始终确保,如果你选择了参数,你在你想要测试的地方拿出了测试数据,所以有将交叉验证嵌套到交叉验证中的技术,但这也会在计算上变得非常昂贵,所以如果你想嵌套交叉验证,那就更糟了。你必须记住的一点是,结果的方差通常被低估了,因为训练授权不是独立的。你还需要注意 通过合并架构选择和超参数选择,可能会引入额外的偏差,因此这应该在不同的数据上进行,如果您正在使用交叉验证,即使没有交叉验证,这也是非常困难的。训练是一个高度随机的过程,因此如果您选择随机初始化,您可能需要使用不同的初始化来多次重新训练您的网络,然后报告标准偏差,以确保您的训练实际执行得有多好。
两个识别率之间的差异可能是训练过程的统计性质的产物。来自深度学习讲座的 CC BY 4.0 下的图片。
现在,你想比较不同的分类器。问题是:“我 91.5%准确率的新方法比 90.9%的最先进方法好吗?”当然,训练一个系统是一个随机过程。因此,仅仅比较这两个数字会产生有偏差的结果。你要问的实际问题是:“分类器之间有显著的差异吗?”这意味着您需要为每种方法运行多次培训。例如,只有这样,您才能使用 t-test 来查看结果的分布是否有显著差异(参见链接部分)。t 检验比较两个方差相等的正态分布数据集。然后,您可以确定均值在显著性水*α(即随机性水*)方面存在显著差异。你经常会在文献中发现 5%或 1%的显著性水*。所以,如果这个观察结果是随机的,概率小于 5%或 1%,你就有了显著的不同。
针对相同数据的多次测试需要进行统计校正,如 Bonferroni 校正。来自深度学习讲座的 CC BY 4.0 下的图片。
现在,如果您在相同的数据上训练多个模型,请小心。如果你多次询问相同的数据,你实际上必须修正你的重要性计算。这被称为 Bonferroni 校正。如果我们比较多个分类器,这将引入多个比较,然后您必须对此进行校正。如果你进行了显著性水*为α的 n 次测试,那么总风险为 n 乘以α。因此,为了达到α的总显著性水*,对于每个单独的测试,调整后的α’将是α除以 n 。因此,对相同的数据运行的测试越多,需要除以的次数就越多。当然,这假设了测试之间的独立性,这是一种对显著性的悲观估计。但在这种情况下,你想要悲观,只是为了确保你不是在报告一件偶然产生的事情。仅仅因为你测试的次数足够多,而且你的测试是一个随机的过程,可能会有一个非常好的结果碰巧出现。更准确,但非常耗时的是排列测试,相信我,你可能想用 Bonferroni 校正来代替。置换一切将比我们之前看到的交叉验证方法花费更长的时间。
深度学习常用实践总结。 CC 下的图片来自深度学习讲座的 4.0 。
好的,让我们总结一下我们之前所看到的:在训练之前检查你的实现,梯度初始化,持续监控训练过程,训练,验证损失,权重,和激活。在重新发明轮子之前,坚持已建立的架构。使用少量数据进行实验,并在评估之前保持评估数据的安全。随着时间的推移,学习率逐渐下降。随机搜索,而不是网格搜索超参数。执行模型集合以获得更好的性能,当然,当您检查您的比较时,您希望进行显著性测试以确保您没有报告随机观察。
在这个深度学习讲座中,更多令人兴奋的事情即将到来。来自深度学习讲座的 CC BY 4.0 下的图片。
因此,下一次在深度学习中,我们实际上想看看神经网络架构的演变。所以从深层网络到更深层的网络。我们想看看稀疏和密集的连接,我们将介绍许多常见的名称,到处都可以听到的名称,LeNet、GoogLeNet、ResNet 等等。因此,在接下来的系列讲座视频中,我们将了解许多有趣的最新方法。所以,非常感谢大家的收听,下期视频再见!
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。
链接
- 在线 t-test
- 用于比较识别率的在线测试
- 比较相关性的在线测试
参考
[1] M. Aubreville,M. Krappmann,C. Bertram 等,“用于组织学细胞分化的导向空间转换器网络”。载于:ArXiv 电子版(2017 年 7 月)。arXiv: 1707.08525 [cs。简历】。
【2】詹姆斯·伯格斯特拉和约舒阿·本吉奥。“随机搜索超参数优化”。在:j .马赫。学习。第 13 号决议(2012 年 2 月),第 281-305 页。
【3】让·迪金森·吉本斯和 Subhabrata Chakraborti。“非参数统计推断”。载于:国际统计科学百科全书。斯普林格,2011 年,第 977-979 页。
[4]约舒阿·本吉奥。“深度架构基于梯度训练的实用建议”。《神经网络:交易的诀窍》。斯普林格出版社,2012 年,第 437-478 页。
[5]·张,Samy Bengio,Moritz Hardt 等,“理解深度学习需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。
[6]鲍里斯·T·波亚克和阿纳托利·B·朱迪斯基。“通过*均加速随机逼*”。摘自:SIAM 控制与优化杂志 30.4 (1992),第 838-855 页。
【7】普拉吉特·拉马钱德兰,巴雷特·佐夫,和阔克诉勒。“搜索激活功能”。载于:CoRR abs/1710.05941 (2017 年)。arXiv: 1710.05941。
[8] Stefan Steidl,Michael Levit,Anton Batliner 等,“所有事物的衡量标准是人:情感的自动分类和标签间的一致性”。在:过程中。ICASSP 的。电气和电子工程师协会,2005 年 3 月。
机器学习学生和从业者在 LinkedIn 上问的常见问题
原文:https://towardsdatascience.com/common-questions-machine-learning-students-and-practitioners-ask-on-linkedin-51bedcdea82c?source=collection_archive---------55-----------------------
由 Unsplash 上的 inlytics 拍摄
经验
本文中的答案可以为您的机器学习之旅节省一些时间和麻烦
介绍
LinkedIn 多年来越来越受欢迎,它已经成为专业人士的社交网络空间。
我见过许多专业人士以各种方式利用 LinkedIn。一些人把它作为个人品牌建设的工具,而另一些人把它作为潜在客户和营销的工具。
LinkedIn 的一个突出用途是联系个人寻求职业和学术建议。这些人可能在物理上无法接触到,因此 LinkedIn 是一个沟通渠道,它弥合了个人之间的物理距离。
使用 LinkedIn 作为建议*台是本文的重点。个人已经阅读了我的文章,并通过 LinkedIn 联系我,以获得更多关于特定主题的信息和建议,所有这些都与机器学习相关。
在这篇文章中,我将包括机器学习从业者和学生提出的一些常见问题,我还将包括我提供的相应答案。
我已经从问题中删除了任何姓名和个人信息,以保护联系过我的个人的身份。
如何阅读这篇文章
个人提出的问题将遵循您正在阅读的这份特定陈述的格式 。
“我的声明看起来像这样”
答案将遵循以下格式:
回答:
包含对问题的回答的段落
问题 1(在线学习)
问题:
你好,Richmond,我正在学习计算机视觉,如果你有任何对我有帮助的课程链接/文章/电子书,我将不胜感激。谢谢!
这是好奇的人问的一个常见问题,他们希望获得一些关于机器学习相关主题的基础知识。我倾向于引导新学员使用我利用的免费资源。我认为,在花钱购买课程和参加证书课程之前,最好先了解一下学科领域和主题。
回答
要学习计算机视觉,你必须了解机器学习、神经网络和图像处理的基础知识。
神经网络
在机器学习中,理解线性代数、微积分和偏微分等主题是必不可少的。
在神经网络中,理解基本概念和思想是至关重要的。理解诸如反向传播、消失梯度下降和不同的神经网络架构(例如卷积神经网络(CNN))的概念也很重要;深度神经网络(deep)和递归神经网络(RNN)。
3Blue1Brown 神经网络视频
斯坦福计算机视觉讲座
在了解 ML 和神经网络的基础知识之后,您可以深入斯坦福大学的一些学术内容,这些内容解释了一些标准的计算机视觉技术、理论和算法。
斯坦福计算机视觉视频
深度蜥蜴机器学习&深度学习
如果你对神经网络和一些机器学习算法背后的理论和数学有坚实的掌握,你可以继续使用标准的机器学习库,如 PyTorch ,进行一些实际的项目和网络实现。
深度蜥蜴机器学习&深度学习
深蜥蜴神经网络编程
有了你积累的所有知识,你应该能够开始你的个人项目,并拥有获得入门级计算机视觉工作职位所需的专业知识。
我建议你创建自己的项目,并参加一些竞赛。此外,如果你尝试在媒体上写作,展示你对计算机视觉和机器学习的主题和概念的理解,也会有所帮助。
[## 学习计算机视觉的 5 种方法
本文列出了一些可以用来学习计算机视觉的方法,这是一个机器学习相关领域
towardsdatascience.com](/5-ways-you-can-learn-computer-vision-6dae3f312686)
问题 2(博士与硕士)
问题:
我最*开始了我作为毕业生的第一份人工智能工作,特别是在计算机视觉方面。我有计算机工程学士学位,但我正在考虑在大学里开始非全日制人工智能硕士课程,我会在工作时间之外的业余时间做这些。只是想知道,你有没有考虑过读博士,或者你觉得在人工智能领域工作一个硕士就足够了?
回答:
直接回答你的问题,我觉得一个硕士对于在 AI 领域工作来说绰绰有余。
高级资格证书的好处是,它提供了学术权威,也向潜在雇主表明你已经花时间专攻某一特定领域。
在进行求职时,我看到一些机器学习和人工智能职位要求申请人获得博士学位,但大多数职位要么非常专业,要么在公司的研究部门内。
博士学位向雇主表明,你可以在某个领域的某个特定领域投入时间,成为某种程度上的专家,并为该领域的发展做出贡献。对于行业中的大多数机器学习角色来说,这并不完全必要。
我会说,你应该去攻读硕士学位,并全力以赴,或许如果你在机器学习领域找到了自己感兴趣的领域,那么你可以攻读博士学位。
目前,我没有考虑读博士,因为我想在机器学习和计算机视觉领域建立一个坚实的五年职业生涯。
也许我会在 7 年左右的时间里评估我的决定。
[## 该不该考机器学习的博士?
探索攻读机器学习博士学位的好处
towardsdatascience.com](/should-you-take-a-phd-in-machine-learning-79530e1cb01c)
问题 3(机器学习研究与工程)
问题:
我希望从事这样一份工作:一半时间研究新的、令人兴奋的东西,一半时间阅读、写论文和编写代码,同时管理人员,解决现实世界的问题(我知道解决现实世界的问题是研究的一部分)。我不确定这样的角色是否存在。我觉得我正处于职业生涯的一个重要阶段,我需要做出重要的决定。考虑到你的经历,如果你能给我以上的建议,那就太神奇了。
回答:
关于寻找一个在工程和研究之间保持 50/50 *衡的角色,我将诚实地告诉你,并不是很多工作角色都能提供这种*衡,甚至不能在工作角色描述中定义正确的*衡。
正如我在我的文章中提到的,有很多工程师进行研究,反之亦然。但是我没有提到的一个关键点是,ML 研究人员角色和工程角色的*衡可以基于当前的需求和业务要求。
我发现在你为公司工作期间,工程和研究变化之间的*衡是基于公司当前的目标和重点。
以我为例,我申请了现在的职位,在工作描述和面试中,并没有提到我将进行任何深入的研究。但是在头两个月,我做的研究比工程多,但是头两个月后到现在,我做的工程比研究多。
我的建议是你继续尽你所能从人群中脱颖而出。使用最先进的机器学习方法的工程工具,还可以培养阅读和撰写研究论文的技能。
当你到了申请角色的阶段,一定要问清楚工程和研究之间的*衡是什么。
你会发现很难找到一个完美的 50/50 *衡的角色,但有一些工作机会,你可以定义你想要的*衡类型,尽管它们很少,但它们仍然存在。
问题 4(机器学习职业可能性)
问题:
我一直在想我是否有可能成为一名计算机视觉工程师。我不是博士,也没有硕士学位,我只是一名毕业生。你有什么建议?
回答
我建议看看你所在的地方对计算机视觉工程师的工作角色要求。
确定你需要了解哪些技能、技术、算法、编程语言和工具,并确保你正在获取它们。
接下来,为了弥补资格的不足,我建议如果可以的话,考虑攻读硕士学位。但如果你无法追求机器学习的高级学位,那么你可以考虑以下选项:
- 参加在线计算机视觉相关课程,完成后提供证书。 Udacity 适合这个:
2.拥有 3-5 个令人印象深刻的计算机视觉/机器学习项目的项目组合。
3.看看如何完成 Kaggle 挑战。
结论
我希望您已经从这篇文章的内容中发现了一些价值。
有人将我的经验和专业知识视为一个学习点,这非常令人羞愧。如果你有任何问题想问我,或者你可能更喜欢我更详细地阐述一些问题的答案,那么你可以像往常一样通过 LinkedIn 联系我。
我不愿意回答机器学习相关的问题或疑问,因为我知道这个领域有多困难和具有挑战性,所以请不要羞于问任何紧迫的问题。我会尽力提供合适的答案。
我希望这篇文章对你有用。
要联系我或找到更多类似本文的内容,请执行以下操作:
- 订阅我的 邮件列表 获取每周简讯
- 跟我上中型
- 通过 LinkedIn 联系我
Python 中常用的时间序列数据分析方法和预测模型
原文:https://towardsdatascience.com/common-time-series-data-analysis-methods-and-forecasting-models-in-python-f0565b68a3d8?source=collection_archive---------14-----------------------
使用 ARIMA 和 LSTM 模型分析用于预测的时间序列数据
作者照片
时间序列是以相等的时间间隔按时间顺序获取的数据样本序列。时间序列包括来自金融、医学、科学研究(如全球变暖、语音分析、地震)等不同领域的多种真实实验数据。[1][2].时间序列预测在各个领域都有很多实际应用,例如商业预测(如销售、股票)、天气、死亡等[1]。
给定用于预测的监督机器学习的传统(时间顺序独立)数据集,在可以执行特征工程之前需要数据探索和预处理,并且在可以选择机器学习模型并将其应用于工程特征以进行预测之前需要完成特征工程。
与传统数据集类似,给定一个时间序列数据集,在可以分析时间序列数据之前,需要进行数据探索和预处理,并且在可以选择时间序列预测模型并将其应用于所分析的数据集以进行预测之前,需要进行时间序列数据分析。
在本文中,我使用 Kaggle [2]的全球变暖数据集来演示 Python 中一些常见的时间序列数据预处理/分析方法和时间序列预测模型。演示包括以下内容:
- 时间序列数据预处理
- 时间序列数据分析
- 时间数列预测法
1.时间序列数据预处理
如前所述,对于时间序列数据,在进行数据分析之前,需要进行数据预处理。
1.1 加载数据
数据预处理的第一步是从 csv 文件加载数据。
时间顺序在时间序列数据分析和预测中起着至关重要的作用。特别是,时间序列中的每个数据样本必须与唯一的时间点相关联。这可以在 Pandas DataFrame/Series 中通过使用 DatetimeIndex 类型的值作为其索引值来实现。
一旦 Kaggle [2]中的地球表面温度数据集被下载到本地机器上,数据集 csv 文件可被加载到 Pandas 数据帧中,如下所示:
df_raw = pd.read_csv('./data/GlobalTemperatures.csv', parse_dates=['dt'], index_col='dt')
df_raw.head()
选项 parse_dates 是告诉 Pandas 将 dt 列中的字符串值解析为 Python datatime 值,而选项 index_col 是告诉 Pandas 将 dt 列的解析值转换为 DatatimeIndex 类型,然后将它们用作索引。
为了简单起见,我提取了 LandAverageTemperature 列作为 Pandas 系列,以便在本文中进行演示:
df = df_raw['LandAverageTemperature']
1.2 处理缺失数据
与传统数据集类似,时间序列数据中经常出现缺失数据,在对数据进行进一步预处理和分析之前,必须对其进行处理。
以下代码可以检查缺少多少数据条目:
df.isnull().value_counts()
地球表面温度时间序列中有 12 项缺失数据。在不破坏过去的时间相关性的情况下,这些丢失的值不能简单地被移除或设置为零。有多种方法可以恰当地处理时间序列中的缺失数据[3]:
- 向前填充
- 反向填充
- 线性内插法
- 二次插值法
- 最*邻居的*均值
- 季节对比*均值
我使用向前填充来填充本文中缺少的数据条目:
df = df.ffill()
2.时间序列数据分析
一旦数据预处理完成,下一步就是分析数据。
2.1 可视化数据
作为一种常见的实践[1][3][4],时间序列数据分析的第一步是将数据可视化。
以下代码使用 Pandas DataFrame/Series 内置绘图方法绘制地球表面温度时间序列:
ax = df.plot(figsize=(16,5), title='Earth Surface Temperature')
ax.set_xlabel("Date")
ax.set_ylabel("Temperature")
图 1: 地球表面温度。
上图显示,地球表面的*均温度大约在[5,12]的范围内,总体趋势是缓慢上升。由于不同时间序列成分(如基准水*、趋势、季节性)和其他成分(如误差和随机噪声)的混合,图中没有显示其他明显的模式[1][3]。时间序列可以分解成单个的部分,以便进一步分析。
2.2 将数据分解成组件
为了将一个时间序列分解成组件以供进一步分析,可以将该时间序列建模为基准水*、趋势、季节性和误差(包括随机噪声)的加法或乘法[3]:
- 加法时间序列 :
数值 = 基数 + 趋势 + 季节性 + 误差 - 乘法时间序列 :
数值 = 基数水* x 趋势 x 季节性 x 误差
本文将地表温度时间序列建模为相加时间序列;
additive = seasonal_decompose(df, model='additive', extrapolate_trend='freq')
选项extrapolate_trend='freq'
是处理时间序列开始时趋势和残差中的任何缺失值[3]。
理论上,通过将选项模型=‘加法’替换为模型=‘乘法’,可以很容易地将相同的数据集建模为乘法时间序列。然而,乘法模型不能应用于该特定数据集,因为数据集包含零值和/或负值,这在乘法季节性分解中是不允许的。
加法分解的结果分量可以被提取以形成如下的熊猫数据帧:
additive_df = pd.concat([additive.seasonal, additive.trend, additive.resid, additive.observed], axis=1)
additive_df.columns = ['seasonal', 'trend', 'resid', 'actual_values']
additive_df.head()
下面的代码是可视化的相加分解成分:趋势、季节和残差(即,基础水*+误差)。
plt.rcParams.update({'figure.figsize': (10,10)})
additive.plot().suptitle('Additive Decompose')
图 2: 时间序列分解。
对于地表温度时间序列数据,我们最感兴趣的是其长期趋势,可提取如下:
trend = additive.trend
图 3: 地表温度趋势。
3.时间数列预测法
一旦数据预处理和分析完成,时间序列预测就可以开始了。
本节介绍了将两种常见的时间序列预测模型应用于地球表面温度趋势数据的结果:
- ARIMA (自回归综合移动*均)
- LSTM (长短期记忆)
3.1 ARIMA 模式
ARIMA 模型[1][4]由三个参数决定:
- p :自回归顺序
- d :使时间序列*稳的差分顺序
- 问:均线下单
ARIMA 模型由三部分组成[4]:自回归(AR)、移动*均(MA)和一个常数:
ARIMA =常数+ AR + MA
在哪里
AR =过去时间点的 p 连续值的线性组合(即滞后)
MA =线性组合 q 过去时间点的连续预测误差(即滞后预测误差)
AR 和 MA 都只能应用于*稳的时间序列,这是通过 ARIMA 差分实现的。
3.1.1 确定差分 d 的阶数
一个时间序列是(弱)*稳的如果它的均值是常数(与时间无关)并且它的 自协方差 在时间序列的两个不同时间点 s 和 t 之间的函数只取决于时间间隔|s - t|(即滞后),而不是特定的时间点[1]。
时间序列预测仅对*稳时间序列有效,因为只有*稳时间序列的行为是可预测的。
我们可以使用 ADF 检验(扩展的 Dickey Fuller 检验 ) [4]来检验一个时间序列是否是*稳的。例如,下面的代码将检查地球表面温度时间序列的*稳性:
from statsmodels.tsa.stattools import adfullerresult = adfuller(trend.values)
print('ADF Statistic: %f' % result[0])
print('p-value: %f' % result[1])
测试的 p 值为 0.012992。
ADF 检验的默认零假设是时间序列是非*稳的。由于上述 ADF 测试的 p 值小于 0.05 的显著性水*,我们拒绝零假设,并得出时间序列是*稳的结论(在这种情况下只有趋势*稳)。
一般来说,要使时间序列*稳,需要做以下工作:
- 移除会随时间改变均值和/或协方差的不规则行为
- 去除可能随时间改变均值和/或协方差的常规行为,如趋势和季节性
差分是一种常用的数据转换方法,用于消除非*稳行为(尤其是趋势)。
以下代码用于对地表温度时间序列进行一阶和二阶差分:
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf# Original Series
fig, axes = plt.subplots(3, 2, sharex=True)
axes[0, 0].plot(trend.values); axes[0, 0].set_title('Original Series')
plot_acf(trend.values, ax=axes[0, 1]).suptitle('Original Series', fontsize=0)# 1st Differencing
diff1 = trend.diff().dropna()
axes[1, 0].plot(diff1.values)
axes[1, 0].set_title('1st Order Differencing')
plot_acf(diff1.values, ax=axes[1, 1]).suptitle('1st Order Differencing', fontsize=0)# 2nd Differencing
diff2 = trend.diff().diff().dropna()
axes[2, 0].plot(diff2.values)
axes[2, 0].set_title('2nd Order Differencing')
plot_acf(diff2.values, ax=axes[2, 1]).suptitle('2nd Order Differencing', fontsize=0)
下图显示一阶差分足以消除趋势。二阶差分没有任何改进。因此,在本文中,差分顺序 d 被设置为 1。
图 4: 一阶和二阶差分。
3.1.2 确定自回归阶数 p
通过分析时间序列数据[1][4]的一阶差分的 PACF ( 偏自相关函数)的结果,可以确定自回归阶数 p :
plt.rcParams.update({'figure.figsize':(9,3), 'figure.dpi':120})size = 100fig, axes = plt.subplots(1, 2, sharex=True)
axes[0].plot(diff1.values[:size])
axes[0].set_title('1st Order Differencing')
axes[1].set(ylim=(0,5))
plot_pacf(diff1.values[:size], lags=50, ax=axes[1]).suptitle('1st Order Differencing', fontsize=0)
我们可以观察到 PACF 滞后 1 远远高于显著性线(灰色区域)。因此,自回归顺序 p 在本文中被设置为 1。
图 5: 一阶差分 PACF。
3.1.3 确定移动*均顺序 q
移动*均阶数 q 可以通过分析时间序列数据的一阶差分的自相关函数(ACF)的结果来确定[1][4]:
plt.rcParams.update({'figure.figsize':(9,3), 'figure.dpi':120})size = 100fig, axes = plt.subplots(1, 2, sharex=True)
axes[0].plot(diff1.values[:size])
axes[0].set_title('1st Order Differencing')
axes[1].set(ylim=(0,1.2))
plot_acf(diff1.values[:size], lags=50, ax=axes[1]).suptitle('1st Order Differencing', fontsize=0)
我们可以观察到 ACF 滞后 1 远远高于显著性线(灰色区域)。因此,在本文中,移动*均顺序 q 也被设置为 1。
图 6: 一阶差分的 ACF。
3.1.4 培训 ARIMA 模型
以下代码首先将地表温度趋势时间序列分为训练和测试子序列,然后使用训练数据训练一个 ARIMA 模型,其确定值为 p =1, d =1, q = 1。
传统的数据集通常被随机分为训练和测试子集。但是,这对时间序列无效,因为它打破了顺序时间依赖性。为了避免这个问题,温度趋势时间序列数据通过保持其原始顺序来划分。
from statsmodels.tsa.arima_model import ARIMAtrain = trend[:3000]
test = trend[3000:]# order = (p=1, d=1, q=1)
model = ARIMA(train, order=(1, 1, 1))
model = model.fit(disp=0)
print(model.summary())
从上面的模型训练结果可以看出,p>|z|列中 AR1 和 MA1 的 P 值是高度显著的(<< 0.05). This indicates that the choices of p =1 and q =1 are appropriate.
The code below is to plot the residuals.
# Plot residual errors
residuals = pd.DataFrame(model.resid)
fig, ax = plt.subplots(1,2)
residuals.plot(title="Residuals", ax=ax[0])
residuals.plot(kind='kde', title='Density', ax=ax[1])
The plot of the residuals shows no patterns (i.e., with constant mean and variance) except for the first 20% of the time series. This indicates that the trained ARIMA model behaves appropriately.
图 7: 残差分布。
3.1.5 使用训练好的 ARIMA 模型进行预测
下面的代码使用经过训练的 ARIMA 模型来预测 192 个(可以是任何正整数)温度值,然后将它们与测试时间序列进行比较:
# Forecast: 192 forecasting values with 95% confidence
fc, se, conf = model.forecast(192, alpha=0.05)# Make as pandas series
fc_series = pd.Series(fc, index=test.index)
lower_series = pd.Series(conf[:, 0], index=test.index)
upper_series = pd.Series(conf[:, 1], index=test.index)# Plot
plt.figure(figsize=(12,5), dpi=100)
plt.plot(train, label='training')
plt.plot(test, label='actual')
plt.plot(fc_series, label='forecast')
plt.fill_between(lower_series.index, lower_series, upper_series,
color='k', alpha=.15)
plt.title('Forecast vs Actuals')
plt.legend(loc='upper left', fontsize=8)
图 8: 利用 ARIMA 进行气温预报。
上述预测结果表明,经过训练的 ARIMA 模型预测的温度往往低于实际温度。
3.2 LSTM 模式
本节介绍将著名的 LSTM 模型应用于地球表面温度趋势时间序列的结果。
3.2.1 准备数据集
与[6]类似,下面的代码从温度时间序列中生成特征向量对(过去时间点的温度值序列)和标签对(当前时间点的目标温度),用于 LSTM 模型训练和评估。
from numpy import array
from keras.models import Sequential
from keras.layers import LSTM
from keras.layers import Densedef split_sequence(sequence, n_steps):
X, y = list(), list()
for i in range(len(sequence)):
# find the end of this pattern
end_ix = i + n_steps
# check if we are beyond the sequence
if end_ix > len(sequence)-1:
break
# gather input and output parts of the pattern
seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
X.append(seq_x)
y.append(seq_y)
return array(X), array(y)# define input sequence
raw_seq = trend.tolist()
# choose a number of time steps
n_steps = 12
# split into samples
X, y = split_sequence(raw_seq, n_steps)
为了简单起见,在本文中,我使用过去 12 个月的温度来预测下个月的温度。以下是生成的数据集的两个示例:
生成的数据集分为两部分:前 3000 个数据集用于模型训练,其余数据集用于模型测试:
X_train = X[:3000]
y_train = y[:3000]
X_test = X[3000:]
y_test = y[3000:]
3.2.2 选择 LSTM 型号
以下 LSTM 模型[6]将一系列温度值作为输入,并生成一个目标温度作为输出。由于温度预测是一个回归问题,LSTM 模型的输出可以取任何值,因此没有相关的激活函数。
n_features = 1X_train = X_train.reshape((X_train.shape[0], X_train.shape[1], n_features))# define model
model = Sequential()
model.add(LSTM(50, activation='relu', input_shape=(n_steps, n_features)))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
# fit model
model.fit(X_train, y_train, epochs=200, verbose=1)
3.2.3 培训 LSTM 模型
以下是模型训练的结果:
3.2.4 使用训练好的 LSTM 模型进行预测
一旦模型训练完成,经过训练的 LSTM 模型就可以应用于测试时间序列来预测温度:
X_test = X_test.reshape((X_test.shape[0], X_test.shape[1], n_features))
y_pred = model.predict(X_test, verbose=0)
下面的代码将预测温度与测试时间序列中的实际温度进行了对比:
def plot_forecosting(df1, df2, line_stype1='b-', line_stype2='r--', title="", xlabel='Date', ylabel='Temperature', dpi=100):
plt.figure(figsize=(16,5), dpi=dpi)
plt.plot(df1.index, df1, line_stype1, label='actual')
plt.plot(df2.index, df2, line_stype2, label='forecast')
plt.gca().set(title=title, xlabel=xlabel, ylabel=ylabel)
plt.title('Forecast vs Actuals')
plt.legend(loc='upper left', fontsize=8)
plt.show()y_pred_1 = y_pred.reshape((y_pred.shape[0]))
y_pred_series = pd.Series(y_pred_1)
y_test_1 = y_test.reshape((y_test.shape[0]))
y_test_series = pd.Series(y_test_1)plot_forecosting(y_test_series, y_pred_series, title='Land Average Temperature')
图 9: 利用 LSTM 进行气温预报。
预测温度与整个温度趋势时间序列的关系如下:
X_all = X.reshape((X.shape[0], X.shape[1], n_features))
y_pred_all = model.predict(X_all, verbose=0)
y_pred_all_1 = y_pred_all.reshape((y_pred_all.shape[0]))
y_pred_all_series = pd.Series(y_pred_all_1)
y_all = y.reshape((y.shape[0]))
y_all_series = pd.Series(y_all)
plot_forecosting(y_all_series, y_pred_all_series, title='Land Average Temperature')
图 10: 利用 LSTM 进行全时间序列的温度预报。
上述预报结果表明,预报温度与实际温度非常接*。
4.摘要
在本文中,我使用了 Kaggle [2]的全球变暖数据集来演示一些常见的时间序列数据预处理/分析实践,以及 Python 中两个广泛采用的时间序列预测模型 ARIMA 和 LSTM。
从第 3 节可以看出,ARIMA 模型的性能严重依赖于数据预处理和分析,以使时间序列*稳,而 LSTM 可以用最少的数据预处理和分析来处理时间序列(例如,在 LSTM 模型中不需要通过差分来消除趋势)。
本文中使用的所有源代码都可以在 Github [7]中找到。
参考
- R.Shumway 和 D. Stoffer,时间序列分析及其应用,Springer,第 4 版,2017 年
- 气候变化:地表温度数据
- 南 Prabhakaran,Python 中的时间序列分析—带示例的综合指南
- 南普拉巴卡兰, ARIMA 模型 Python 中时间序列预测的完整指南
- J.Brownlee,如何用 Python 中的差分变换去除趋势和季节性
- J.Brownlee,如何开发用于时间序列预测的 LSTM 模型
- Y.张 Github 中的 Jupyter 笔记本
您是否有效地传播了您的数据?
原文:https://towardsdatascience.com/communicating-and-building-excitement-in-your-data-practice-52e3c7a554ea?source=collection_archive---------46-----------------------
你可能听说过,数据已经成为一种东西。这个空间迅速成长,它的受欢迎程度和兴趣从未如此之大。
然而,尽管对数据的需求很大,你可能会惊讶地发现,为了有效地交流结果,你需要为你的数据和分析(DNA)实践建立多大的兴奋度。有效地宣传你的团队的使命和成果应该是一个关键的焦点领域,以便给你的工作带来它需要的曝光率。您现在可能没有想到这一点,但您的部分职责是教育人们如何使用数据,并管理围绕数据的对话。
这里有一些有用的提示,告诉你如何做到这一点。
仪表板丰富多彩。
好吧,也许不多。你不希望有太多的仪表板,但是你做的那些仪表板应该既引人注目又能提供信息。仪表板的主要目的是自动化您收到请求的任何机械报告。然而,次要目的是可见性。
仪表板是您的团队工作的最直接和可见的表示。甚至在你的团队下班回家后,它们仍然可以被访问,而且,正如在许多组织中越来越受欢迎的那样,它们可以被打开并显示在分散在你办公室的监视器上,就像在交易大厅一样。考虑到它们的可见性,花些时间设计它们,以便它们能抓住你的观众的注意力,并传达具有清晰、明确和有价值的目的的信息,同时展示数据在你的组织内是如何被使用的。
走老派路线——用模拟方式交流,以建立关系
我相信高质量的人际交往有很多价值。在一个一切都是数字化的世界,一个极大地促进了您的工作的世界,找到识别和增强模拟通信通道的方法会有很大的好处。如果你想传福音,面对面做是有好处的。
做到这一点的一个方法是找到鼓励人们提交工作请求或问题陈述或假设的方法,他们希望你亲自解决,而不是通过数字方式。这有很多好处。首先,他们会见到你和你的团队。其次,你会发现,当提交问题需要花费更多努力时,人们会更严谨地思考问题。像这样一个简单的改变可以提高你开始收到的问题的质量。最后,你能够开始对话,并直接从源头获得有价值的背景信息。对话的流程可能会向多个方向发展,让你和你的对手更好地了解情况,这是所有相关方的双赢。
发现像这样的小块机会将会提高你的团队的可见性和有效性。
未知的未知
随着许多组织的数据急剧增长,非数据人员很难跟上可用的数据。不管你是否知道,你的一部分职责是教育人们什么样的数据在那里,以及如何使用。存在的数据越清晰,你的涉众的思维就会越快开始思考,并为你的团队设计要解决的问题。这意味着您将获得更多的参与度和知名度!把这些数据公之于众,激发人们的好奇心,以此来激励非技术人员。
这可以通过在前面提到的仪表板上突出它们来实现。也可以通过展示来自其他业务部门的见解来实现,这样你的受众就可以了解哪些数据正在被使用,哪些问题正在被组织的其他部门解决,而不是他们自己的部门
请谈谈你的数据。
使用数据语言交谈的人越多越好。优秀的数据科学家的职责之一(在一些组织中是完全独立的角色)是成为优秀的数据翻译者。如果翻译的东西少了,这项工作会变得容易些。所以,定期向非数据人员传授你的方法,这是你自己的责任。花点时间谈谈你所使用的方法,以及你在这个过程中所做的任何选择的原因——而不仅仅是你所取得的结果。明确指出你所做的工作应该如何被使用,它意味着什么,包括它可能会被误解。实际上,你是在总结自己的工作——让别人更容易理解。
因此,在传达团队成果时,要像产生这些成果一样认真对待自己的角色。确保由你来主导对话,因为这有助于确定数据在您的组织内的使用效率
这个故事最初出现在这里
基于朋友社区特征的 R 语言社区检测
原文:https://towardsdatascience.com/community-detection-in-r-using-communities-of-friends-characters-2161e845c198?source=collection_archive---------39-----------------------
每个角色都有自己的迷你网络,但是它是什么样子的呢?
在本文中,我将使用 R 中的igraph
包中的社区检测功能来展示如何检测网络中的社区。在文章结束时,我们将能够看到 Louvain 社区检测算法如何将朋友角色分成不同的社区(忽略六个主要角色的明显社区),如果你是该剧的粉丝,你可以决定这个分析对你是否有意义。
读者注意: 如果你发现在中等格式的环境中很难理解代码,你也可以在这里 以降价格式 重新阅读。
用于组合朋友角色网络的数据
在我之前的文章中,我展示了如何使用迭代编程为《老友记》的整个系列生成一个网络边缘列表。网络边列表是一个简单的数据集,包含以下内容:
from
和to
列为了确定我们的(无向)网络中字符对之间的连接,每个字符将是一个节点,每个连接将是一条边。- 一个
weight
列(这是边的一个属性),表示线对之间的连接强度。在这种情况下,这是由这对搭档一起出现在不同场景中的次数决定的。
我使用的 edgelist 是使用前两篇文章中的技术生成的,并在这个项目的 repo 中加载到 Github。我现在将所有十个季节的数据集拉下来,我们可以看看它。
library(tidyverse)
library(readr)
library(igraph) # get friends full series edgelist
edgefile_url <- "https://github.com/keithmcnulty/friends_analysis/blob/master/data/friends_full_series_edgelist.RDS?raw=true" download.file(edgefile_url, "edgelist.RDS")
edgelist <- readRDS("edgelist.RDS") knitr::kable(edgelist %>% head(10))
这看起来和我们预期的一样。所以我们准备开始一些工作。
在igraph
使用鲁文算法寻找社区
现在,首先,我们要假装六个主要人物彼此不认识,并删除我们网络中他们之间的所有边。这是因为我们对其他角色如何围绕主要角色形成社区感兴趣。如果我们让主要角色的联系保持完整,我们知道他们会在他们之间形成一个非常强大的社区,这当然是这部剧的全部意义。
friends <- c("Phoebe", "Monica", "Rachel", "Joey", "Ross", "Chandler") edgelist_without <- edgelist %>%
dplyr::filter(!(from %in% friends & to %in% friends))
现在,我们将把新的 edgelist 转换成一个矩阵,然后用它来构建一个 graph 对象,该对象将weight
列作为边的属性:
edgelist_matrix <- as.matrix(edgelist_without[ ,c("from", "to")]) friends_graph <- igraph::graph_from_edgelist(edgelist_matrix, directed = FALSE) %>%
igraph::set.edge.attribute("weight", value = edgelist_without$weight)
我们现在可以快速浏览一下我们的朋友图表:
真是一团糟
好吧,真是一团糟——考虑到这个网络中有 650 个顶点(字符)和 2961 条边(连接),这并不奇怪。我们将不得不在稍后为一些好的情节做一些格式化。但是现在我们准备要求 Louvain 算法将这个网络分成不同的社区。该算法将尝试最大化社区内部的连接强度,并最小化不同社区之间的连接。
# run louvain with edge weights
louvain_partition <- igraph::cluster_louvain(friends_graph, weights = E(friends_graph)$weight) # assign communities to graph
friends_graph$community <- louvain_partition$membership # see how many communities there are
unique(friends_graph$community) ## [1] 4 6 1 7 3 8 5 2
看起来算法找到了 8 个社区。但是我们不知道谁在里面。我们可以做一些事情来更好地了解每个社区。
- 我们可以看看每个社区有多大。有时,社区可能很小,代表着网络中几乎完全不相连的部分(就像一些角色之间的随机场景,再也不会出现)。
- 我们可以看看每个社区中“最重要”的人(顶点)。这样做的一种方式是寻找具有最高中间中心性的顶点,即连接该社区中最多角色的人。
communities <- data.frame() for (i in unique(friends_graph$community)) { # create subgraphs for each community subgraph <- induced_subgraph(friends_graph, v = which(friends_graph$community == i)) # get size of each subgraph
size <- igraph::gorder(subgraph) # get betweenness centrality
btwn <- igraph::betweenness(subgraph) communities <- communities %>%
dplyr::bind_rows(data.frame(
community = i,
n_characters = size,
most_important = names(which(btwn == max(btwn)))
)
)
} knitr::kable(
communities %>%
dplyr::select(community, n_characters, most_important)
)
好的——我们看到有几个社区看起来很小,可能很不相关(我们将在附录中查看这些社区),但主要的六个社区都围绕着六个朋友,这是我们所期望的。这证实了六个角色中的每一个,尽管他们彼此很接*,但也在整个系列中培养了相当独立的社区。
我们可以通过查看每个社区(不包括小社区)中最重要的五个角色来了解这些社区。这一次,我们将着眼于一个更简单的性能指标——每个角色拥有的连接数,或者他们在网络中的度。
top_five <- data.frame() for (i in unique(friends_graph$community)) { # create subgraphs for each community
subgraph <- induced_subgraph(friends_graph, v = which(friends_graph$community == i)) # for larger communities
if (igraph::gorder(subgraph) > 20) { # get degree
degree <- igraph::degree(subgraph) # get top five degrees
top <- names(head(sort(degree, decreasing = TRUE), 5)) result <- data.frame(community = i, rank = 1:5, character = top)
} else {
result <- data.frame(community = NULL, rank = NULL, character = NULL)
} top_five <- top_five %>%
dplyr::bind_rows(result)
} knitr::kable(
top_five %>%
tidyr::pivot_wider(names_from = rank, values_from = character)
)
我们在这里看到一些通用的角色名字,如“男”或“女”。如果我们忽略这些,我们可以看到以下人物群体:
- 菲比和她生命中的男人:她最终的丈夫迈克,她吸毒成瘾的按摩客户史蒂夫,以及她同父异母的弟弟弗兰克(也是她父亲的名字)
- 莫妮卡,她的父母和男朋友们:钱德勒在这里失踪了,当然是因为施工!
- 钱德勒和珍妮丝:在《六人行》之外,钱德勒限制了与珍妮丝之外的重复角色的联系。
- 乔伊和他的演艺人脉:除了巩特尔——他属于乔伊的圈子——乔伊大部分时间都和导演和经纪人在一起。
- 瑞秋,她的孩子和她的妹妹:瑞秋的社区主要围绕着她在第八季的孩子的出生。
- 罗斯、卡罗尔和苏珊:罗斯的社区被他的前妻卡罗尔和她的女友苏珊,以及他的古生物学教授女友查理·惠勒的场景所占据。
可视化社区
我们现在可以试着把这些社区想象成整个网络的一部分。为了更容易理解,我们将去掉除了六个朋友以外的所有人的标签,然后我们将按社区对顶点和边进行颜色编码。
# give our nodes some properties, incl scaling them by degree and coloring them by community V(friends_graph)$size <- 3 V(friends_graph)$frame.color <- "white" V(friends_graph)$color <- friends_graph$community V(friends_graph)$label <- V(friends_graph)$name V(friends_graph)$label.cex <- 1.5 # also color edges according to their starting node edge.start <- ends(friends_graph, es = E(friends_graph), names = F)[,1]
E(friends_graph)$color <- V(friends_graph)$color[edge.start] E(friends_graph)$arrow.mode <- 0 # only label central characters v_labels <- which(V(friends_graph)$name %in% friends) for (i in 1:length(V(friends_graph))) {
if (!(i %in% v_labels)) { V(friends_graph)$label[i] <- "" }
}
现在我们可以绘制图表了。“最漂亮”的地块可能是球形布局:
l1 <- layout_on_sphere(friends_graph)
plot(friends_graph, rescale = T, layout = l1, main = "'Friends' Network - All Seasons")
球形布局
但是为了更好地从视觉上区分社区,武力导向的情节是合适的:
l2 <- layout_with_mds(friends_graph)
plot(friends_graph, rescale = T, layout = l2, main = "'Friends' Network - All Seasons")
力导向布局
第二张图片更有帮助,因为它暗示乔伊和罗斯可能会过着更“独立”的生活,与其他四个角色相比,他们有更多自己的社区,因为力导向算法使他们与其他人的距离更远。
附录:谁是较小的社区?
让我们看看在我们之前的分析中出现的两个较小的社区。我们来看看这些社区都有哪些人。
small_communities <- data.frame() for (i in unique(friends_graph$community)) { # create subgraphs for each community
subgraph <- induced_subgraph(friends_graph, v = which(friends_graph$community == i)) # for larger communities
if (igraph::gorder(subgraph) < 20) {
# get degree
degree <- igraph::degree(subgraph) # get top ten degrees
top <- names(sort(degree, decreasing = TRUE)) result <- data.frame(community = i, rank = 1:length(top), character = top)
} else {
result <- data.frame(community = NULL, rank = NULL, character = NULL)
} small_communities <- small_communities %>%
dplyr::bind_rows(result)
} knitr::kable(
small_communities %>%
tidyr::pivot_wider(names_from = rank, values_from = character)
)
有趣的是,我们的算法似乎已经选取了几个特定的剧集,并将其中的场景视为它们自己的断开网络。
- 第一个社区似乎来自雷莫尔博士去世的地方
- 第二个似乎是来自在我做之后的那个
最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在LinkedIn或Twitter上找我。也可以看看我在drkeithmcnulty.com上的博客。
Neo4j 图形数据科学对世界各国的社区检测
原文:https://towardsdatascience.com/community-detection-of-the-countries-of-the-world-with-neo4j-graph-data-science-4d3a022f8399?source=collection_archive---------15-----------------------
使用 Neo4j 图形数据科学库进行网络分析,包括要素缩减技术、相似性网络推理和社区检测
在我等待发面的时候,我想,消磨时间的最好方式是使用 Neo4j 图形数据科学库进行网络分析。嗯,也许还可以试着画一幅丙烯画,但我不会让你厌烦的。如果这是你第一次听说 GDS 图书馆,我可以推荐一些我以前的博客文章,试图解释基本知识:
- GDS 原生投影
- GDS 赛佛投影
- GDS 多图投影
如果你准备好了,是时候戴上我们的图形数据科学的帽子,进入正题了。
要求:
- Neo4j
- Neo4j APOC 插件
- Neo4j 图形数据科学插件
图表模式
我们将使用由 Fernando Lasso 在 Kaggle 上提供的世界各国数据集。看一下致谢,数据来源于中情局的世界概况。不幸的是,贡献者没有提供数据汇编的年份。我的猜测是 2013 年,但我可能是错的。该数据集包含各种指标,如面积大小、人口、婴儿死亡率以及世界上约 227 个国家的数据。
图表模式
图表模式由标记为国家的节点组成,这些节点将它们的特征存储为属性。一个国家也是一个地区的一部分。
图形导入
首先,我们需要下载数据集,并将其复制到$Neo4j/import
文件夹中。出于某种原因,CSV 文件中的数字使用逗号作为浮点,而不是点( 0,1 而不是 0.1 )。我们需要对数据进行预处理,以便能够将数字转换为 Neo4j 中的浮点数。在 APOC 过程apoc.cypher.run
的帮助下,我们可以在一个 cypher 查询中预处理和存储数据。apoc.cypher.run
允许我们在主 cypher 查询中运行独立的子查询,非常适合各种用例。
LOAD CSV WITH HEADERS FROM "file:///countries%20of%20the%20world.csv" as row
// cleanup the data and replace comma floating point with a dot
CALL apoc.cypher.run(
"UNWIND keys($row) as key
WITH row,
key,
toFloat(replace(row[key],',','.')) as clean_value
// exclude string properties
WHERE NOT key in ['Country','Region']
RETURN collect([key,clean_value]) as keys",
{row:row}) YIELD value
MERGE (c:Country{name:trim(row.Country)})
SET c+= apoc.map.fromPairs(value.keys)
MERGE (r:Region{name:trim(row.Region)})
MERGE (c)-[:PART_OF]->(r)
识别缺失值
另一个有用的 APOC 程序是apoc.meta.nodeTypeProperties
。有了它,我们可以检查图的节点属性模式。我们将使用它来确定国家的每个要素有多少个缺失值。
// Only look at properties of nodes labeled "Country"
CALL apoc.meta.nodeTypeProperties({labels:['Country']})
YIELD propertyName, propertyObservations, totalObservations
RETURN propertyName,
(totalObservations - propertyObservations) as missing_value,
(totalObservations - propertyObservations) / toFloat(totalObservations) as pct_missing_value
ORDER BY pct_missing_value DESC LIMIT 10
结果
看起来我们没有太多缺失的值。然而,为了简单起见,我们将在进一步的分析中忽略缺失值超过四个的特性。
高相关滤波器
高相关滤波是一种简单的数据降维技术。具有高相关性的特征可能携带相似的信息,并且更加线性相关。使用具有相关信息的多个特征会降低各种模型的性能,可以通过删除两个相关特征中的一个来避免。
// Only look at properties of nodes labeled "Country"
CALL apoc.meta.nodeTypeProperties({labels:['Country']})
YIELD propertyName, propertyObservations, totalObservations
WITH propertyName,
(totalObservations - propertyObservations) as missing_value// filter our features with more than 5 missing values
WHERE missing_value < 5 AND propertyName <> 'name'
WITH collect(propertyName) as features
MATCH (c:Country)
UNWIND features as feature
UNWIND features as compare_feature
WITH feature,
compare_feature,
collect(coalesce(c[feature],0)) as vector_1,
collect(coalesce(c[compare_feature],0)) as vector_2
// avoid comparing with a feature with itself
WHERE feature < compare_feature
RETURN feature,
compare_feature,
gds.alpha.similarity.pearson(vector_1, vector_2) AS correlation
ORDER BY correlation DESC LIMIT 10
结果:
有趣的是出生率和婴儿死亡率密切相关。死亡率也与婴儿死亡率密切相关,因此我们将降低出生率和死亡率,但保持婴儿死亡率。手机数量和净移民似乎与国内生产总值相关。我们也将放弃这两项,保持 GDP 不变。我们还将减少人口,保留面积和人口密度,这两者携带类似的信息。
特征统计
至此,我们只剩下八个特征。我们将用apoc.agg.statistics
函数来检验它们的分布。它计算数值统计,例如一组值的最小值、最大值和百分位数。
// define excluded features
WITH ['name',
'Deathrate',
'Birthrate',
'Phones (per 1000)',
'Net migration',
'Population'] as excluded_features
CALL apoc.meta.nodeTypeProperties({labels:['Country']})
YIELD propertyName, propertyObservations, totalObservations
WITH propertyName,
(totalObservations - propertyObservations) as missing_value
WHERE missing_value < 5 AND
NOT propertyName in excluded_features
// Reduce to a single row
WITH collect(propertyName) as potential_features
MATCH (c:Country)
UNWIND potential_features as potential_feature
WITH potential_feature,
apoc.agg.statistics(c[potential_feature],
[0.5,0.75,0.9,0.95,0.99]) as stats
RETURN potential_feature,
apoc.math.round(stats.min,2) as min,
apoc.math.round(stats.max,2) as max,
apoc.math.round(stats.mean,2) as mean,
apoc.math.round(stats.stdev,2) as stdev,
apoc.math.round(stats.`0.5`,2) as p50,
apoc.math.round(stats.`0.75`,2) as p75,
apoc.math.round(stats.`0.95`,2) as p95,
apoc.math.round(stats.`0.99`,2) as p99
结果
密克罗尼西亚联邦的海岸与面积之比为 870,令人印象深刻。另一方面,世界上共有 44 个国家的海岸线为零。另一个有趣的事实是,格陵兰有 56361 名居民和 2166086 *方英里的人口密度约为每*方英里 0。这可能是一个进行社交距离的好地方。
我们可以观察到,大多数特征似乎是描述性的,除了其他的(%),大多数在 80 到 100 之间。由于低方差,我们将在进一步的分析中忽略它。
填充缺少的值
我们只剩下七个特征,我们将用它们来推断国家之间的相似性网络。在此之前,我们需要做的一件事是填充缺失的值。我们将使用一种简单的方法,用国家所在地区的*均值来填充要素的缺失值。
UNWIND ["Arable (%)",
"Crops (%)",
"Infant mortality (per 1000 births)",
"GDP ($ per capita)"] as feature
MATCH (c:Country)
WHERE c[feature] IS null
MATCH (c)-[:PART_OF]->(r:Region)<-[:PART_OF]-(other:Country)
WHERE other[feature] IS NOT null
WITH c,feature,avg(other[feature]) as avg_value
CALL apoc.create.setProperty(c, feature, avg_value)
YIELD node
RETURN distinct 'missing values populated'
最小最大归一化
最后但同样重要的是,我们必须将我们的特征标准化,以防止任何单一特征由于较大的规模而支配其他特征。我们将使用标准化的简单的最小最大方法在 0 和 1 之间重新调整特征。
UNWIND ["Arable (%)",
"Crops (%)",
"Infant mortality (per 1000 births)",
"GDP ($ per capita)",
"Coastline (coast/area ratio)",
"Pop. Density (per sq. mi.)",
"Area (sq. mi.)"] as feature
MATCH (c:Country)
// Calculate the min and the max value for each feature
WITH max(c[feature]) as max,
min(c[feature]) as min,
feature
MATCH (c1:Country)
WITH c1,
// define property name to store back results
"n_" + feature AS newKey,
// normalize values
(toFloat(c1[feature]) - min) / (max - min) as normalized_value// store results to properties
CALL apoc.create.setProperty(c1, newKey, normalized_value)
YIELD node
RETURN distinct 'normalization done'
余弦相似的相似网络
我们已经完成了数据预处理,可以专注于数据分析部分。分析的第一步是借助于余弦相似性算法推断相似性网络。我们基于所选特征为每个国家构建一个向量,并比较每对国家之间的余弦相似性。如果相似性高于预定义的阈值,我们以相似节点对之间的关系的形式存储回结果。定义一个最佳阈值是艺术和科学的结合,通过实践你会做得更好。理想情况下,您想要推断一个稀疏图,因为社区检测算法在完整或密集图上表现不佳。在这个例子中,我们将使用 0.8 的similarityCutoff
值(范围在-1 和 1 之间)。除了相似性阈值,我们还将使用topK
参数来仅存储前 10 个相似的邻居。我们这样做是为了确保图形更稀疏。
MATCH (c:Country)// build the vector from features
WITH id(c) as id, [c["n_Arable (%)"],
c["n_Crops (%)"],
c["n_Infant mortality (per 1000 births)"],
c["n_GDP ($ per capita)"],
c["n_Coastline (coast/area ratio)"],
c["n_Pop. Density (per sq. mi.)"],
c["n_Area (sq. mi.)"]] as weights
WITH {item:id, weights: weights} as countryData
WITH collect(countryData) as data
CALL gds.alpha.similarity.cosine.write({
nodeProjection: '*',
relationshipProjection: '*',
similarityCutoff:0.8,
topK:10,
data: data})
YIELD nodes, similarityPairs
RETURN nodes, similarityPairs
图形数据科学图书馆
借助 Neo4j 的图形数据科学库,我们可以直接在 Neo4j 中运行 30 多种不同的图形算法。算法被公开为密码程序,类似于我们上面看到的 APOC 程序。
GDS 使用存储图形的投影,这完全是在内存中实现更快的执行时间。我们可以利用gdn.graph.create
过程来投影存储图的视图。关于 GDS 图形投影的更多细节,请查看我在之前的博文。在本例中,我们将投影标签为 Country 且关系类型为 SIMILAR 的节点。
CALL gds.graph.create('similarity_network','Country','SIMILAR');
弱连通分量
通常,我们用弱连接成分算法开始图形分析。这是一种社区检测算法,用于在我们的图中找到断开的网络或孤岛。因为我们只对断开组件的计数感兴趣,所以我们可以运行算法的stats
变体。
CALL gds.wcc.stats('similarity_network')
YIELD componentCount, componentDistribution
RETURN componentCount,
componentDistribution.min as min,
componentDistribution.max as max,
componentDistribution.mean as mean,
componentDistribution.p50 as p50,
componentDistribution.p75 as p75,
componentDistribution.p90 as p90
结果
该算法在我们的图中只找到了一个组件。这是一个有利的结果,因为断开的岛会扭曲各种其他图算法的结果。
卢万算法
另一种社区检测算法是 Louvain 算法。用基本术语来说,密集连接的节点更有可能形成社区。它依靠模块化优化来提取社区。模块化优化分两步进行。第一步包括局部优化模块化。在第二步中,它将属于同一社区的节点聚合到单个节点中,并从这些聚合的节点构建新的网络。这两个步骤反复重复,直到获得最大的模块化。这些迭代的一个微妙的副作用是,我们可以在每次迭代结束时查看社区结构,因此 Louvain 算法被视为分层社区检测算法。要包含分层社区结果,我们必须将includeIntermediateCommunities
参数值设置为 true。
CALL gds.louvain.write('similarity_network',
{maxIterations:20,
includeIntermediateCommunities:true,
writeProperty:'louvain'})
YIELD ranLevels, communityCount,modularity,modularities
结果
我们可以通过ranLevels
值观察到,Louvain 算法在我们的网络中发现了两个层次的社区。在最后一层,它发现了八个组。我们现在可以检查最后一级的提取社区,并比较它们的特征*均值。
MATCH (c:Country)
RETURN c.louvain[-1] as community,
count(*) as community_size,
avg(c['Arable (%)']) as pct_arable,
avg(c['Crops (%)']) as pct_crops,
avg(c['Infant mortality (per 1000 births)']) as infant_mortality,
avg(c['GDP ($ per capita)']) as gdp,
avg(c['Coastline (coast/area ratio)']) as coastline,
avg(c['Pop. Density (per sq. mi.)']) as population_density,
avg(c['Area (sq. mi.)']) as area_size,
collect(c['name'])[..3] as example_members
ORDER BY gdp DESC
结果
Louvain 算法在相似性网络中找到了八个不同的社区。最大的组织有 51 个成员国,*均 GDP 最高,接* 22,000 美元。它们在婴儿死亡率和海岸线比例上位居第二,但在人口密度上遥遥领先。有两个社区的*均 GDP 在 2 万美元左右,然后我们可以观察到第三名的 GDP 急剧下降到 7000 美元。随着 GDP 的下降,我们还可以发现婴儿死亡率的上升几乎是线性的。另一个有趣的发现是,大多数更贫困的社区几乎没有海岸线。
使用 PageRank 查找社区代表
我们可以使用 PageRank 算法来评估最终级别社区的顶级代表。如果我们假设每个相似的关系都是国家间相似度的投票, PageRank 算法会给社区内最相似的国家分配最高分。我们将对每个社区分别执行 PageRank 算法,并且只考虑给定社区中的节点和关系。这可以通过密码投影轻松实现,无需任何额外的变换。
WITH 'MATCH (c:Country) WHERE c.louvain[-1] = $community
RETURN id(c) as id' as nodeQuery,
'MATCH (s:Country)-[:SIMILAR]->(t:Country)
RETURN id(s) as source, id(t) as target' as relQuery
MATCH (c:Country)
WITH distinct c.louvain[-1] as community, nodeQuery, relQuery
CALL gds.pageRank.stream({nodeQuery:nodeQuery,
relationshipQuery:relQuery,
parameters:{community:community},
validateRelationships:False})
YIELD nodeId, score
WITH community, nodeId,score
ORDER BY score DESC
RETURN community,
collect(gds.util.asNode(nodeId).name)[..5] as top_5_representatives
结果
使用 Gephi 实现网络可视化
优秀的可视化胜过千言万语。Gephi 是一个创建网络可视化的伟大工具。正如我们现在可能预期的那样,APOC 提供了一个方便的程序apoc.gephi.add
,可以将网络数据从 Neo4j 无缝地传输到 Gephi。在文档或我的前一篇博文中找到更多信息。
节点颜色表示社区,节点大小表示 GDP,文本大小表示社区 PageRank 值
正如我们之前观察到的,我们的网络中有八个不同的社区。*均 GDP 最高的社区在右上角,*均 GDP 最高到最低的国家按顺时针方向排列。我发现一个有趣的三角形正好位于俄罗斯、中国和巴西形成的图像中间。此外,如果你仔细观察,你会发现巴拿马是红色社区的一部分,但位于中间。这是因为它与大多数社区中的一两个国家有类似的关系,但与红色社区中的三个国家有关系,因此属于红色社区。
基于 Louvain 算法的层次社区
我们之前提到过,Louvain 算法可用于查找带有includeIntermediateCommunities
参数的分层社区,在我们的示例中,它找到了两个级别的社区。我们现在将考察第一层次的国家集团。一条经验法则是,较低级别的社区将更细粒度、更小。
MATCH (c:Country)
RETURN c.louvain[0] as community,
count(*) as community_size,
avg(c['Arable (%)']) as pct_arable,
avg(c['Crops (%)']) as pct_crops,
avg(c['Infant mortality (per 1000 births)']) as infant_mortality,
avg(c['GDP ($ per capita)']) as gdp,
avg(c['Coastline (coast/area ratio)']) as coastline,
avg(c['Pop. Density (per sq. mi.)']) as population_density,
avg(c['Area (sq. mi.)']) as area_size,
collect(c['name'])[..3] as example_members
ORDER BY gdp DESC
结果
不出所料,第一层的社区数量几乎是第二层(也是最后一层)的两倍。一个激动人心的社区由*均 GDP 排在第二位。它只包含五个国家,这些国家很小,*均面积只有 364 *方英里。另一方面,他们有很高的人口密度,大约每*方英里 10000 人。例如澳门、摩纳哥和香港。
Neo4j Bloom 的图形探索
另一个非常好的网络可视化工具是 Neo4j Bloom 。它提供了定制图形透视图和搜索查询的能力,没有任何 cypher 查询语言技能的人可以使用它来探索和搜索图形中的见解。如果你有兴趣了解更多,可以查看威廉·里昂写的这篇博文。
我们将看看最后一组 GDP 最高的国家。它是一个由 51 个国家组成的共同体,在第一层级上有四个不同的共同体。
节点颜色表示一级社区,节点大小表示 GDP
之前,我们提到了一个令人兴奋的社区,由五个人口密度极高的小国组成。在这个图像中,它们被涂成红色。蓝色社区的*均 GDP 比黄色社区高 25%左右,婴儿死亡率几乎是黄色社区的一半。另一方面,黄色社区*均比蓝色社区有更多的海岸线。
结论
Neo4j 生态系统非常适合执行和可视化网络分析。图形数据科学库是生态系统的一个实用补充,允许我们运行各种图形算法并执行图形分析,而没有太多麻烦。你可以在你的电脑上试用,也可以创建一个 Neo4j 沙盒账户,几分钟内就可以开始使用。
和往常一样,代码可以在 GitHub 上获得。
紧凑预测树
原文:https://towardsdatascience.com/compact-prediction-tree-af8d23b6b9a0?source=collection_archive---------22-----------------------
实践教程
有限字母表上精确序列预测的无损模型
图片来自 Pixabay 的 Bela Geletneky
什么是序列预测问题?
序列预测问题包括仅通过查看序列的项目来查找有序序列的下一个元素。
这个问题涵盖了各种领域中的许多应用。它包括产品推荐、预测和网页预取等应用程序。
许多不同的方法被用来解决这个问题,流行的方法包括 PPM(部分匹配预测),马尔可夫链,以及最*的 LSTM(长短期记忆)。
紧凑预测树(CPT)是 2015 年发布的一种方法,旨在通过对整个训练集进行无损压缩来匹配精度并超越流行算法的性能(训练和预测的时间)。
我们现在将详细介绍训练和预测的方法,以及这种方法的优缺点。
紧凑预测树定义
在进入如何使用它进行预测的细节之前,让我们描述一下组成紧凑预测树(CPT)的不同元素:
- 一个 trie ,用于序列的有效存储。
- 一个倒排索引,用于恒定时间检索包含某个单词的序列。
- 一个查找表,用于从序列 Id 中检索序列。
特里
trie 通常称为前缀树,是一种基于有序树的数据结构,用于存储序列(如字符串)。序列的元素存储在边中,因此给定节点的每个后代都有相同的前缀。
在这个众所周知的例子中,我们希望存储["tea", "ten", "inn"]
。我们先把“茶”放在空树上。这棵树的每一根树枝对应一个字母。然后我们添加“ten”:因为“tea”和“ten”共享同一个“te”前缀,所以我们只是在“te”前缀之后创建一个新的分支。最后,我们将“inn”添加到与前两个序列没有共同前缀的树中。
Trie 通常用于获取,对每个以前缀开头的单词进行树搜索。在我们的例子中,我们使用它来压缩和有效地存储我们的训练集。
倒排索引
倒排索引是用于存储从元素到其位置的映射的索引。这里我们用它来存储从序列元素到序列 id 的映射。
再次考虑我们之前的示例,我们注意到“T”出现在序列 0 和 1 中,“E”出现在序列 0 和 1 中,“A”出现在序列 0 中,“N”出现在序列 1 和 2 中,而“I”仅出现在序列 2 中。
因此,我们有以下反向索引:
{
"T": [0, 1],
"E": [0, 1],
"A": [0],
"N": [1, 2],
"I": [2]
}
为了提高效率,我们将使用位集来存储倒排索引(这也有助于高效地找到“相似序列”)。
查找表
查找表是一种数据结构(通常是一个数组),用于存储每个序列的最后一个节点(叶)的指针。
这种数据结构对于迭代给定序列的元素来说是必不可少的。
例如,如果我们想要检索 id 为 0 的序列,我们可以简单地迭代它的父序列。在我们的例子中,id 0 序列的叶的父代与“A”链接,然后与“E”链接,最后与“T”链接。这倒过来给了我们第一个序列:“茶”。
紧凑预测树使用
训练
训练时间与训练集中的序列数成线性关系。
对于每个训练序列,我们需要执行 3 个步骤:
- 在 trie 中插入序列。
- 添加倒排索引中的元素。
- 添加查找表中最后一个节点的位置。
一张图胜过千言万语,这里是一个经过充分训练的紧凑预测树一步一步来。
预测
为了预测序列 S,我们需要做这三个步骤:
- 寻找相似序列(包含 S 的每个元素的序列)。
- 计算每个相似序列的后续序列(从与 S 相同的最后一项之后开始的子序列)。
- 计算每个元素在所有后续序列中的出现次数。
对于这一部分,让我们举一个稍微复杂一点的例子,我们的模型在["ABC", "ABD", "BC", "BAC"]
进行训练。我们应该将算法训练成:
让我们试着预测一下"AB"
之后会发生什么。
首先,让我们计算相似的序列。
与 S 相似的序列是包含 S 中任意顺序、任意位置的每一项的序列。为了计算相似的序列,我们可以简单地使用我们的倒排索引并计算交集。对于我们的例子,我们需要相交[0, 1, 3]
(A 出现的序列的 id)和[0, 1, 2, 3]
(B 出现的位置)。这就给了[0, 1, 3]
。
然后,我们需要计算consequent sequences
。
序列 Y 相对于序列 S 的后件是从与 S 相同的最后一项之后开始直到 Y 结束的 Y 的子序列。
我们例子的后件序列应该是"C"
、"D"
和"C"
。(对于我们相对于"AB"
的序列 0、1 和 3)。
最后,我们简单地计算每个元素在所有后续序列中出现的次数,并预测出现次数最多的字母。
在我们的例子中是"C"
(2 次出现)。
紧凑预测树性能
测试框架
简而言之,作者用几种算法(包括 CPT、依赖图、类马尔可夫算法……)在几个公共数据集上预测了下一个元素。
要看结果(要慎用),建议你看一下原论文, 紧凑预测树:精确序列预测的无损模型 。
另一篇论文, 从智能卡数据预测火车行程:序列预测问题的现实应用 ,展示了解决序列预测问题的步骤。从字母表的构建到模型的选择。在这篇论文中,Hoekstra 博士将 CPT 与 PPM 和 AKOM 等不同方法进行了比较。根据您的需要,它还显示 CPT 可以是一个具有相对较好准确性的相关解决方案。
利弊
紧凑预测树的优点是:
- CPT 是一种无损存储来自训练集的所有数据的算法。
- 该算法是高度可解释的(容易追溯相似序列,后续序列…)
- 快速预测。一些基准可以在原论文或者这里找到。
紧凑预测树的缺点是:
- CPT 忽略序列中的顺序,因此 CPT 倾向于预测最频繁出现的项目。(如果您准备好了考虑顺序的稍微慢一点的预测。我建议你去看看由一个共同作者开发的子序列算法。)
- CPT 对噪音相当敏感。如果一个新元素在要预测的序列中,CPT 将无法找到任何相似的序列。CPT+已经解决了这个问题,您可以在“更进一步”一节中找到详细信息。
走得更远
Python 示例
对于这个小例子,我们将使用这个实现。在合著者之一的官网上引用为 CPT 的实现。还包括了降噪等 CPT+的一些特性。
from cpt.cpt import Cptmodel = Cpt()# training
model.fit([['hello', 'world'],
['hello', 'this', 'is', 'me'],
['hello', 'me']
])# predictions
model.predict([['hello'], ['hello', 'this']])# Output: ['me', 'is']
有关predict
方法的参数或超参数的更多信息,您可以查看文档。
进一步阅读
如果你对这个主题感兴趣,我强烈建议你阅读以下论文:
- 【CPT+】:降低紧凑预测树的时间/空间复杂度 这增加了噪声降低技术和训练集策略的两次压缩。
- 基于序列预测和 Pagerank 算法改进网页访问预测本文的思路是增加一个 Pagerank 算法,只在相关序列上训练 CPT。总体上有很好的改善。
- 简洁的基于 BWT 的序列预测(subseq) CPT 的合著者之一开发的算法。这种算法需要更多的时间来预测,需要更多的空间来存储整个训练集,但更重视序列的顺序。你可以看看这个实现。
特别感谢约瑟夫·罗卡的所有帮助。感谢我的朋友们也校对了这篇文章。
使用 Python 的概率模型进行公司估值
原文:https://towardsdatascience.com/company-valuation-using-probabilistic-models-with-python-712e325964b7?source=collection_archive---------16-----------------------
采用蒙特卡洛模拟确定上市公司的股权价值
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
在一个完全可预测的世界中,我们将拥有关于企业未来增长率和现金流的准确信息,这将导致该公司单一准确的内在价值。然而现实中,事情的不确定性更大。事实上,虽然一些分析师给出了准确的股价目标,但金融模型的各种输入实际上是随机分布的变量。由此产生的复杂性加剧了寻找合适的公司价值的挑战。虽然在随机输入的情况下不再有“单一版本的真相”,但如果我们的输入遵守某些规则,就有可能找到可能包含我们公司真实*均值的一系列值。在编写下面的模型时,我借鉴了 NYU 大学教授 Aswath Damodaran 在他关于使用概率方法进行公司估值的论文[1]中提供的见解。
一.统计迂回
假设我们只有四个随机变量作为股票估值模型的输入:收入 CAGR、EBIT 利润率、加权*均资本成本(WACC)和公司的长期增长率(假设微软)。我们可以进一步假设这些值有一个确定的*均值,并且是正态分布的。这需要这些变量的分布遵循一套规则,例如,关于它们的传播。
鉴于这些随机变量,有一些“真正的”*均公司价值,我们试图确定。这个真实均值是基于我们随机输入变量的无限多内在价值预测的均值。因为不可能找到这个精确的总体*均值,所以我们需要限制自己创建一个值的单一样本,并从这个样本中推断总体*均值。
I.1 抽样分布
为了理解样本相对于公司价值总体的表现,首先设想一个假设场景是有意义的,在这个场景中,我们知道真实的*均公司价值及其标准差。如果我们现在从公司价值总体中抽取重复样本,这些样本的*均值将遵循一个抽样分布,该分布可以用正态分布来*似。该分布的*均值是公司价值的真实*均值,其标准偏差是公司价值的标准偏差除以样本中观察值数量的*方根。利用这个标准差,我们可以预测某些事件发生的概率。例如,我们知道 68%的样本均值将落在总体均值的一个标准差内,大约 95%将落在两个标准差内,等等。
I.2 推断
那么这对我们有什么帮助呢?如果我们知道总体均值及其抽样分布的标准差,我们就可以从理论上生成一个样本,并推断出真实的总体均值。例如,如果我们取样本的*均值,并创建一个从该*均值向任一侧延伸两个标准差的范围,我们可以有 95%的把握认为真正的*均值将位于该区间内。唯一的问题是我们不知道总体标准偏差。
事实证明,我们可以将样本标准差作为真实总体值的*似值,并通过扩大置信区间的宽度(通过使用 t 值)来说明这一点。如果从总体中抽取足够大的样本,这将提高我们总体标准差估计的准确性,因此我们可以使用 z 分数来代替。
本质上,所有这些意味着我们可以预测我们公司的价值一定次数,这将导致从公司价值的人口样本。然后,我们可以为真实*均值创建 95%的置信区间,以获得真实*均值(基于四个随机输入变量)可能位于何处的指示。
二。用 Python 实现
尽管基础理论有些复杂,但用 Python 实现该模型实际上相当简单,这将在随后的章节中解释。
II.1 计算公司的公允价值
使用 yahoo_fin 库,可以获得上市公司的财务数据。我们可以使用此信息来导出在以下模拟中使用的正态分布变量的*均值。在模拟的每次迭代中,我们根据随机变量的值预测一个特定的公司价值。我用来获取这个值的代码和我前段时间写的代码很相似(除了 yahoo_fin 让我不用手动抓取所有的财务数据)。因为这里的重点是从蒙特卡罗模拟生成的样本数据中进行推断,所以我不会详细讨论代码和它背后的简化假设。重要的是,在给定公司收入 CAGR、EBIT 利润率、WACC 和长期增长率的特定输入的情况下,下面的代码块将(希望)返回对公司内在价值的较为准确的估计。
from yahoo_fin import stock_info as si
from matplotlib import pyplot as plt
import pandas_datareader as dr
import numpy as np
import pandas as pd
'''----// General input variables //----'''
company_ticker = 'MSFT'
market_risk_premium = 0.059
debt_return = 0.01
long_term_growth = 0.01
tax_rate = 0.3
iterations = 1000
'''----// Get financial information from yahoo finance //----'''
income_statement_df = si.get_income_statement(company_ticker)
pars_df = income_statement_df.loc[['totalRevenue', 'ebit']]
input_df = pars_df.iloc[:, ::-1]
'''----// Calculate average revenue CAGR & EBIT margin //----'''
def get_cagr(past_revs):
CAGR = (past_revs.iloc[0,3]/past_revs.iloc[0,0])**(1/4)-1
return(CAGR)
def get_average_margin(past_ebit):
margin = 0
margin_lst = []
for i in range(len(past_ebit.columns)):
margin = past_ebit.iloc[1,i]/past_ebit.iloc[0,i]
margin_lst.append(margin)
return(sum(margin_lst)/len(margin_lst))
mean_cagr = get_cagr(input_df)
mean_margin = get_average_margin(input_df)
'''----// Create forecast function through which random variables will flow //----'''
def get_forecast(input_df, cagr, margin, long_term_growth):
forecast_lst = []
for i in range(6):
if i < 5:
forecast_lst.append(input_df.iloc[0,3]*(1+cagr)**(i+1)*margin)
else:
forecast_lst.append(input_df.iloc[0,3]*(1+cagr)**(i)*(1+long_term_growth)*margin)
return forecast_lst
'''----// Get WACC and net debt //----'''
def get_wacc(company_ticker, market_risk_premium, debt_return, tax_rate):
risk_free_rate_df = dr.DataReader('^TNX', 'yahoo')
risk_free_rate = (risk_free_rate_df.iloc[len(risk_free_rate_df)-1,5])/100
equity_beta = si.get_quote_table('msft')['Beta (5Y Monthly)']
equity_return = risk_free_rate+equity_beta*(market_risk_premium)
balance_sheet_df = si.get_balance_sheet(company_ticker)
short_term_debt_series = balance_sheet_df.loc['shortLongTermDebt']
long_term_debt_series = balance_sheet_df.loc['longTermDebt']
cash_series = balance_sheet_df.loc['cash']
net_debt = short_term_debt_series.iloc[0] + + long_term_debt_series.iloc[0] - cash_series.iloc[0]
market_cap_str = si.get_quote_table(company_ticker)['Market Cap']
market_cap_lst = market_cap_str.split('.')
if market_cap_str[len(market_cap_str)-1] == 'T':
market_cap_length = len(market_cap_lst[1])-1
market_cap_lst[1] = market_cap_lst[1].replace('T',(12-market_cap_length)*'0')
market_cap = int(''.join(market_cap_lst))
if market_cap_str[len(market_cap_str)-1] == 'B':
market_cap_length = len(market_cap_lst[1])-1
market_cap_lst[1] = market_cap_lst[1].replace('B',(9-market_cap_length)*'0')
market_cap = int(''.join(market_cap_lst))
company_value = market_cap + net_debt
WACC = market_cap/company_value * equity_return + net_debt/company_value * debt_return * (1-tax_rate)
return WACC
def get_net_debt():
balance_sheet_df = si.get_balance_sheet(company_ticker)
short_term_debt_series = balance_sheet_df.loc['shortLongTermDebt']
long_term_debt_series = balance_sheet_df.loc['longTermDebt']
cash_series = balance_sheet_df.loc['cash']
return short_term_debt_series.iloc[0] + long_term_debt_series.iloc[0] - cash_series.iloc[0]
mean_wacc = get_wacc(company_ticker, market_risk_premium, debt_return, tax_rate)
net_debt = get_net_debt()
'''----// Discount EBIT figures to arrive at the PV of the firm's cash flows //----'''
def discount(forecast, discount_rate, long_term_rate):
discount_lst = []
for x,i in enumerate(forecast):
if x < 5:
discount_lst.append(i/(1+discount_rate)**(x+1))
else:
discount_lst.append(i/(discount_rate-long_term_rate)*(1/(1+discount_rate)**5))
return sum(discount_lst)forecast = get_forecast(input_df, cagr, margin, long_term_rate)
present_value = discount(forecast, discount_rate, long_term_rate)-net_debt
其思想是使用循环反复预测公司价值,并将结果模型输出存储在一个列表中,该列表稍后用于确定样本均值和标准差。
II.2 用 Python 生成正态分布的随机变量
我通过假设这些变量的过去值是未来值的准确预测值,得出了*均 CAGR 值、EBIT 边际值和 WACC 值。公司的长期增长率更难确定,应根据具体情况输入。四个变量的标准差也是如此。给定四个变量中每一个的*均值和标准偏差,很容易用 numpy 从随机分布中得出结论。实际上,导入库后我们只需要一行代码。
cagr = np.random.normal(mean_cagr, 0.01)
对 EBIT 边际利润、WACC 和长期增长率做同样的处理,我们可以用得到的数字来计算公司价值。这样做一次需要从公司价值观中抽取一个单一的价值观。使用一个循环,我们可以重复这个过程几次(在本例中是 1000 次),并将结果公司值存储在一个列表中。
'''----// Run simulation //----'''
hist_lst = []
for i in range(iterations):
cagr = np.random.normal(mean_cagr, 0.01)
margin = np.random.normal(mean_margin, 0.005)
long_term_rate = np.random.normal(long_term_growth, 0.001)
discount_rate = np.random.normal(mean_wacc, 0.001)
forecast = get_forecast(input_df, cagr, margin, long_term_rate)
hist_lst.append(discount(forecast, discount_rate, long_term_rate)-net_debt)
hist_array = np.array(hist_lst)
使用 numpy,我们可以很容易地找到这个列表的均值和标准差。随后,可以计算出我们 95%置信区间的上下界。
mean = hist_array.mean()
standard_error = hist_array.std()/(iterations**(1/2))
lower_bound = mean-1.96*standard_error
upper_bound = mean+1.96*standard_error
二. 3 绘制产出图
使用 matplotlib,我们还可以图形化地显示样本数据。这有助于更好地理解样本数据的分布,也使我们能够验证推断的正态性假设。
plt.hist(hist_array, bins=50, align='mid', color = 'steelblue', edgecolor='black')
plt.title('Sample Distribution ' + company_ticker, {'fontname':'Calibri'})
plt.xlabel('Equity Value in $', {'fontname':'Calibri'})
plt.ylabel('Frequency', {'fontname':'Calibri'})
plt.show()
图 1:预测公司价值的分布直方图。由于数据*似正态分布,我们能够如上所述计算置信区间。
II.4 模型性能
为了了解模型的表现,我计算了不同公司真实*均值的置信区间,并随后将区间与实际公司市值进行了比较。结果如下所示。
图 2:AAPL 的模型输出(实际市场。cap = 19.41 亿美元)和 MSFT(实际市场。上限= 1,554 美元)
图 3:WMT 的模型输出(实际市场。cap = 388 b 美元)和 PG(实际市场。上限= 3400 亿美元)
图 4:NKE 的模型输出(实际市场。cap = 179 亿美元)和 MRK(实际市场。上限= 211 亿美元)
当将置信区间与公司的实际市值进行比较时,该模型似乎有些偏差。虽然该程序肯定不是真实世界的完美代表,但我们仍然必须考虑到置信区间为公司的真实均值 值提供了一个范围,而不是为单个点估计提供了一个范围。
三。结束语
像我之前建立的计算公司公允价值的模型一样,这个程序也做了几个简化的假设。例如,我隐含地假设四个随机输入变量的过去值是它们未来总体均值的适当*似值。然而,这种假设可能是没有根据的,即使允许这些输入变量有一些随机性也不能解决这个问题。尽管如此,我相信将随机性纳入模型会使它更接*于成为真实世界动态的充分代表。
III.1 免责声明
该模型和代码只是将 Python 编程应用于公司估值的一个练习。因此,该代码显然不应用于投资决策。此外,从雅虎财经获得的信息不应用于任何商业目的。
III.2 最终代码
下面是运行模拟并从结果样本数据中得出推论所需的全部代码。它的工作只需要 Python(我用的是 3.7.8)和几个包,即 yahoo_fin、matplotlib、pandas-datareader、numpy 和 pandas。
from yahoo_fin import stock_info as si
from matplotlib import pyplot as plt
import pandas_datareader as dr
import numpy as np
import pandas as pd
'''----// General input variables //----'''
company_ticker = 'MSFT'
market_risk_premium = 0.059
debt_return = 0.01
long_term_growth = 0.01
tax_rate = 0.3
iterations = 1000
'''----// Get financial information from yahoo finance //----'''
income_statement_df = si.get_income_statement(company_ticker)
pars_df = income_statement_df.loc[['totalRevenue', 'ebit']]
input_df = pars_df.iloc[:, ::-1]
'''----// Calculate average revenue CAGR & EBIT margin //----'''
def get_cagr(past_revs):
CAGR = (past_revs.iloc[0,3]/past_revs.iloc[0,0])**(1/4)-1
return(CAGR)
def get_average_margin(past_ebit):
margin = 0
margin_lst = []
for i in range(len(past_ebit.columns)):
margin = past_ebit.iloc[1,i]/past_ebit.iloc[0,i]
margin_lst.append(margin)
return(sum(margin_lst)/len(margin_lst))
mean_cagr = get_cagr(input_df)
mean_margin = get_average_margin(input_df)
'''----// Create forecast function through which random variables will flow //----'''
def get_forecast(input_df, cagr, margin, long_term_growth):
forecast_lst = []
for i in range(6):
if i < 5:
forecast_lst.append(input_df.iloc[0,3]*(1+cagr)**(i+1)*margin)
else:
forecast_lst.append(input_df.iloc[0,3]*(1+cagr)**(i)*(1+long_term_growth)*margin)
return forecast_lst
'''----// Get WACC and net debt //----'''
def get_wacc(company_ticker, market_risk_premium, debt_return, tax_rate):
risk_free_rate_df = dr.DataReader('^TNX', 'yahoo')
risk_free_rate = (risk_free_rate_df.iloc[len(risk_free_rate_df)-1,5])/100
equity_beta = si.get_quote_table('msft')['Beta (5Y Monthly)']
equity_return = risk_free_rate+equity_beta*(market_risk_premium)
balance_sheet_df = si.get_balance_sheet(company_ticker)
short_term_debt_series = balance_sheet_df.loc['shortLongTermDebt']
long_term_debt_series = balance_sheet_df.loc['longTermDebt']
cash_series = balance_sheet_df.loc['cash']
net_debt = short_term_debt_series.iloc[0] + + long_term_debt_series.iloc[0] - cash_series.iloc[0]
market_cap_str = si.get_quote_table(company_ticker)['Market Cap']
market_cap_lst = market_cap_str.split('.')
if market_cap_str[len(market_cap_str)-1] == 'T':
market_cap_length = len(market_cap_lst[1])-1
market_cap_lst[1] = market_cap_lst[1].replace('T',(12-market_cap_length)*'0')
market_cap = int(''.join(market_cap_lst))
if market_cap_str[len(market_cap_str)-1] == 'B':
market_cap_length = len(market_cap_lst[1])-1
market_cap_lst[1] = market_cap_lst[1].replace('B',(9-market_cap_length)*'0')
market_cap = int(''.join(market_cap_lst))
company_value = market_cap + net_debt
WACC = market_cap/company_value * equity_return + net_debt/company_value * debt_return * (1-tax_rate)
return WACC
def get_net_debt():
balance_sheet_df = si.get_balance_sheet(company_ticker)
short_term_debt_series = balance_sheet_df.loc['shortLongTermDebt']
long_term_debt_series = balance_sheet_df.loc['longTermDebt']
cash_series = balance_sheet_df.loc['cash']
return short_term_debt_series.iloc[0] + long_term_debt_series.iloc[0] - cash_series.iloc[0]
mean_wacc = get_wacc(company_ticker, market_risk_premium, debt_return, tax_rate)
net_debt = get_net_debt()
'''----// Discount EBIT figures to arrive at the PV of the firm's cash flows //----'''
def discount(forecast, discount_rate, long_term_rate):
discount_lst = []
for x,i in enumerate(forecast):
if x < 5:
discount_lst.append(i/(1+discount_rate)**(x+1))
else:
discount_lst.append(i/(discount_rate-long_term_rate)*(1/(1+discount_rate)**5))
return sum(discount_lst)
'''----// Run simulation and plot distribution of model forecasts //----'''
hist_lst = []
for i in range(iterations):
cagr = np.random.normal(mean_cagr, 0.01)
margin = np.random.normal(mean_margin, 0.005)
long_term_rate = np.random.normal(long_term_growth, 0.001)
discount_rate = np.random.normal(mean_wacc, 0.001)
forecast = get_forecast(input_df, cagr, margin, long_term_rate)
hist_lst.append(discount(forecast, discount_rate, long_term_rate)-net_debt)
hist_array = np.array(hist_lst)
plt.hist(hist_array, bins=50, align='mid', color = 'steelblue', edgecolor='black')
plt.title('Sample Distribution ' + company_ticker, {'fontname':'Calibri'})
plt.xlabel('Equity Value in $', {'fontname':'Calibri'})
plt.ylabel('Frequency', {'fontname':'Calibri'})
plt.show()
mean = hist_array.mean()
standard_error = hist_array.std()/(iterations**(1/2))
lower_bound = mean-1.96*standard_error
upper_bound = mean+1.96*standard_error
print(lower_bound)
print(upper_bound)
参考资料:
[1] A. Damodaran,直面不确定性:在估值中使用概率方法 (2018),SSRN
不*衡数据过采样技术的比较分析
原文:https://towardsdatascience.com/comparative-analysis-of-oversampling-techniques-on-imbalanced-data-cd46f172d49d?source=collection_archive---------35-----------------------
关键词 -不*衡数据,过采样,对比分析
由卢克·切瑟在 Unsplash 上拍摄的照片
简介
对不*衡数据建模是我们在训练模型时面临的主要挑战。我的项目的主要目标是找到最佳的过采样技术,我将应用于五个与老化相关的 bug 问题相关的数据集。我会用七个机器学习分类模型来训练模型。
不*衡数据通常指的是分类问题,其中每个类别的观察值数量不是均匀分布的;通常,一个类别(称为多数类别)会有大量数据/观察值,而一个或多个其他类别(称为少数类别)的观察值会少得多。
数据
我使用的数据集与老化相关的错误(ARB)有关,这些错误发生在长期运行的系统中,是由于内存泄漏或未释放的文件和锁等问题的积累而导致的错误条件。与衰老有关。在软件测试过程中,bug 很难被发现,复制起来也很困难。下面是表 1 中每个数据集的描述。
表 1:实验数据集描述
使用的*衡方法
1。类别重量
首先,我使用了一种最简单的方法来解决类不*衡的问题,即简单地为每个类提供一个权重,这个权重更多地强调少数类,这样最终的结果是一个分类器可以从所有类中*等地学习。
2.过采样
其次,我使用了三种过采样技术来消除这种不*衡。对于过采样,少数类将增加少数观察的数量,直到我们达到一个*衡的数据集。
2.1 随机过采样
这是最简单的过采样方法。它随机采样少数类,并简单地复制采样的观察值。通过这种技术,我们人为地减少了数据集的方差。
2.2 SMOTE
然而,我们也可以使用现有的数据集为少数类综合生成新的数据点。合成少数过采样技术(SMOTE)是一种通过在原始数据集中的观测值之间进行插值来生成新观测值的技术。
对于给定的观测值 xi,通过在 k 个最*邻之一 xzi 之间进行插值来生成新的(合成)观测值。
xnew = Xi+λ(xzi Xi)xnew = Xi+λ(xzi Xi)
其中λ是在[0,1][0,1]范围内的随机数。这个插值将在 xi 和 xzi 之间的线上创建一个样本。
2.3 ADASYN
自适应合成(ADASYN)采样与 SMOTE 相同,但是,为给定 xi 生成的样本数量与附*与 xi 不属于同一类别的样本数量成比例。因此,ADASYN 在生成新的合成训练样本时往往只关注离群值。
使用的分类模型
- K 最*邻— 首先,我使用了一个简单的分类模型,即 KNN 分类器。在这个模型中,分类是根据每个点的 k 个最*邻的简单多数投票来计算的。
2。逻辑回归- 其次我用的是逻辑回归。在该算法中,描述单次试验可能结果的概率使用逻辑函数(即 sigmoid 函数)建模。
3。朴素贝叶斯- 接下来我使用了朴素贝叶斯算法,它基于贝叶斯定理,假设每对特征之间是独立的。朴素贝叶斯分类器在许多现实情况下工作良好,例如文档分类和垃圾邮件过滤。
4。决策树- 然后我用了决策树分类器。决策树产生一系列可用于对数据进行分类的规则。这个分类器易于理解和可视化,可以处理数字和分类数据。
5。随机森林-接下来我用的是随机森林分类器。它是一种元估计器,可以在数据集的各种子样本上拟合许多决策树,并使用*均值来提高模型的预测准确性,并控制过度拟合。子样本大小始终与原始输入样本大小相同,但样本是替换绘制的。
66。支持向量机-接下来我用的是 SVM。它将训练数据表示为空间中的点,这些点被尽可能宽的明显间隙分成不同的类别。然后,新的例子被映射到相同的空间,并根据它们落在差距的哪一边来预测属于哪个类别。
7。山脊 CV- 最后我用的是山脊 CV。该分类器首先将目标值转换为{-1,1},然后将问题视为回归任务(多类情况下的多输出回归)。
观察分析
1。调谐模式
我超调了每个数据集上的每个模型,以找到模型可以预测的最佳精度。我使用 GridSearchCV 和 K-Fold 来优化模型。我将不同的 K 值设置为 5、10、15 和 20,发现 10 倍的效果最好。
你可以在文章末尾我提供的 GitHub 链接中看到代码
2。技术相对比较
我使用了 AUC 指标来比较模型,因为当我们必须比较分类模型时,ROC AUC 是最好的。AUC 值越大,模型越好。从我的结果中,我发现*均 AUC 值,即 0.89 的 随机抽样 与其他不*衡学习策略相比是最好的。 SMOTE 和 ADAYSN 的*均 AUC 值次之,为 0.88。 类权重 t 的*均 AUC 值为 0.58。精度和 f 值显示出相同的趋势。根据 f-measure 值和精确度两者, 随机超过采样器 性能最好,其次是和 ADASYN 。
我们还推断出 脊分类器 是最好的,并且具有 0.93 的*均 AUC 值。其次是*均 AUC 值为 0.83 的 随机森林 和*均 AUC 值为 0.80 的 决策树KNN各为 0.80。 Logistic 回归 和 SVM 的*均 AUC 值各为 0.79。 朴素贝叶斯 表现最差,*均 AUC 为 0.76。根据 F-测度,脊分类器的*均 F-测度值为 0.916。决策树和随机森林的*均 F-测度值分别为 0.90 和 0.91,高于 SVM 和 Logistic 回归的*均 F-测度值 0.85。朴素贝叶斯表现最差,*均 F 值为 0.81
此外,我绘制了条形图,显示了过采样技术和分类模型的比较。从可视化结果中,我们还可以看到,在大多数情况下,由绿色条表示的随机过采样技术比其他技术高。
你可以在文章末尾提供的我的 GitHub 链接中查看可视化代码。
AUC 分数的条形图
准确性得分条形图
F1-度量的条形图
结果
在这篇文章中,我通过应用 7 种机器学习算法,对 5 个老化相关错误的不*衡数据集进行了过采样技术的比较分析。从我的项目,我们得出结论,随机过采样器被证明是最好的过采样技术相比,其他和岭分类器,最好的机器学习算法。
我的 GitHub 链接-https://github.com/vanisinghal0201/Comparative_Analysis
我也将很快在geeks forgeeks上发表。**
参考文献
[1] Lov Kumar,Ashish Sureka,实验结果,结论,针对老化相关错误预测的类不*衡问题的特征选择技术,2018
[2]双吉,预测职称分类中的等级关系,2020
[3]从不*衡数据中学习。检索自 https😕/www . Jeremy Jordan . me/unbalanced-data/
[4]不*衡数据https://github . com/vanising Hal 0201/unbalanced Data/blob/master/Learning % 20 from % 20 unbalanced % 20 Data . ipynb
ML 系统的比较案例研究:Tensorflow 与 PyTorch
原文:https://towardsdatascience.com/comparative-case-study-of-ml-systems-tensorflow-vs-pytorch-a554dce5f585?source=collection_archive---------33-----------------------
张杰瑞在 Unsplash 上拍照
在这篇文章中,我将对 TensorFlow:一个用于大规模机器学习的系统和 PyTorch:一个命令式的高性能深度学习库的背景架构进行一个小的比较研究
下面提到的信息是从这两篇论文中摘录的。
我选择了 TensorFlow 和 PyTorch 来进行比较研究,因为我已经使用了这两个系统,理解它们的基本设计原理让我着迷。我想知道这些系统如何在幕后处理模型,使它们成为行业标准。解决以行业为中心的机器学习问题所需的速度和复杂架构很难实现,这两个系统都设法做到了这一点。
这篇文章旨在提供两个系统的架构差异。为了更深入地了解每个人的背景工作,请阅读他们的学术论文!它们信息量大,易于阅读。
张量流
好处:
数据流图: Tensorflow 是对dist faith的改进,它是以前使用参数服务器模型的 Google ML *台。Tensorflow 结合了数据流的高级编程模型和参数服务器的低级效率,因此比它的前身强大得多。它结合了在基于参数服务器的架构中由单独的工作线程完成的计算和状态管理。它还使用在提供性能方面比 CPU 和 GPU 更好的 TPU。这使得研究人员开发复杂(和新颖)的深度学习模型变得相对容易。
数据流图是一个神经网络,由占位符和更新规则组成。它可以用于确定操作的顺序,以估计内存消耗等。
高 GPU 利用率:它提供了一个单语言*台来开发新的 ML 架构,速度很快,并使用单个数据流图来表示算法中的所有计算和状态。通过推迟执行直到程序完成,它提高了整体执行性能,即高 GPU 利用率。Tensorflow 的主要功能在于并发和分布式执行整个图的重叠子图。
社区支持: Tensorflow 也有巨大的社区支持,在生产中表现相当不错。所以很多大公司像 Google,Twitter,Airbnb,Open AI 等等。为他们的 ML 项目使用 Tensorflow 后端。
移动接口:它还提供跨集群的分布式执行和动态工作流,允许复杂的 ML 程序在 CPU、GPU 和 TPU 上运行,同时在移动设备上拥有一个接口。Tensorflow-Lite 的推出考虑到了移动设备。
大规模 ML: 对于密集的大规模任务,如图像分类和语言建模,Tensorflow 提供了一个非常容错、分布式和优化的架构,可用于训练非常大的 ML 模型,如通过谷歌的 ML 聚焦应用程序可见。
Tensorflow 架构(来源)
缺点:
陡峭的学习曲线: Tensorflow 有一个学习曲线,旨在使研究人员更容易开发 ML 模型,它增加了理解其架构的难度。它也不像 Spark 的 RDDs 那样为单个操作提供容错。
调试和动态执行:调试 ML 程序的容易程度并不是 Tensorflow design 关注的重点。它也不支持早期的动态计算图,模型只能在已经定义了计算图的情况下运行。尽管它在最新版本中增加了对此的支持。
虽然它的架构非常可扩展和高效,但随着 Python 用户花一些时间来习惯它,可以做出更多努力来改善用户体验。
来源:活动状态
PyTorch
好处:
易用性: PyTorch 是一个专注于 python 的 ML 框架,开发它是为了让用户牢记在心。它侧重于维护性能,同时保持最终用户的高易用性。PyTorch 的“一切都是程序”的方法使它成为一个非常用户友好的*台。
C++核心:由于大多数深度学习研究人员都熟悉 python,所以它的开发者开发了这个 python 库,尽管它的核心是用 C++编写的,以提高速度和性能。与 Tensorflow 不同,它不使用静态数据流方法,因此为了克服 Python 的全局解释器锁(确保一次只有一个线程运行)问题,它的核心“libtorch”库(用 C++编写)实现了张量数据结构、自动 diff 集成等。多线程环境中的功能。
Python 库支持: PyTorch 保持简单高于性能,因此做出了折衷。所有的 Python 功能:打印语句、调试器、Numpy、Matplotlib 等的使用。使用 PyTorch 轻松工作。
从论文本身来看:
用 10%的速度换取一个简单得多的模型是可以接受的;100%不是。
CPU-GPU 同步:它具有高度的互操作性和可扩展性,可以很好地与其他使用库的 GPU 配合使用。它使用 CUDA 在 GPU 上异步执行操作符,这有助于获得高性能,即使对于 Python 这样的语言也是如此。这样,它通过 CPU 在 Python 中运行模型的控制流,并在 GPU 上运行张量运算,一切都在 CPU-GPU 同步中进行。
多重处理:它使用多重处理模块(torch.multiprocessing)来允许并发线程加速程序。它还通过引用计数(计算每个张量的使用次数)和删除不再使用的张量来仔细管理内存。
PyTorch 中的一个简单神经网络程序(来源
动态执行: PyTorch 还支持动态计算图,这有助于用户随时开发和运行模型。这在像 RNN 这样使用运行时可变长度输入的模型中非常有用。
缺点:
性能:由于 PyTorch 是为 Python 打造的,所以不得不在性能上做一些取舍。它不使用其他 ML 系统中流行的数据流图,如 TensorFlow、Theano 等。以提高性能著称。
依赖:它还必须依赖许多其他独立的库来克服 Python 的限制,比如使用 CUDA 流。由于 CUDA 流遵循 FIFO 方法,PyTorch 需要保持 CPU 和 GPU 周期之间的同步,因为它遵循“每个流一个池”的设计。这可能会导致碎片,同步开销和一些奇怪的角落情况,但 PyTorch 确保用户可能永远不会遇到它们。
共享的共同特征
- 这两个系统都使用高效的 C++内核来实现高性能。由于计算损失函数的梯度,而使用 SGD 是由所有 ML 程序完成的,PyTorch 和 Tensorflow 都提供了有效的自动微分算法。
- 两者都利用工作线程/子计算中的分布式执行和多重处理来提高性能。这两个系统都是开源的,在 ML 研究社区中很受欢迎。两者都使用异步参数更新来执行算法。
差异
py torch 比 TensorFlow 来得晚,它覆盖了 tensor flow 的很多弱点。
- PyTorch 提供了数据并行性以及调试功能,而这两者对于 TensorFlow 来说都是一个问题。相比 Tensorflow,PyTorch 对研究人员来说更容易学习。
- PyTorch 保持了控制和数据流之间的分离,而 Tensorflow 将其合并到一个数据流图中。
- PyTorch 执行反向模式自动微分,TensorFlow 也执行反向微分,尽管区别在于 Tensorflow 提供的消除开销的优化算法。
- TensorFlow 利用延迟执行直到整个程序可用,而这在 PyTorch 的情况下是不可能的,因此使用其他方法来提高效率,如自定义缓存张量收集器和引用计数。
结论
总的来说,PyTorch 在很多方面都比 Tensorflow 表现得更好,包括易用性,同时又不牺牲性能。
考虑到 PyTorch 论文中的基准测试,它比 Tensorflow 实现所有主要的 ML 算法(如 AlexNet、VGG-19 等)的性能都要好。尽管对于大规模生产系统,Tensorflow 由于其社区支持和强大的架构仍然是主要选择。
没有一种方法可以设计大型系统。每个 ML *台在设计其特性时都考虑到了一些核心方面。对于 TensorFlow,它是性能,而对于 PyTorch,它是用户体验。
【http://adityarohilla.com】原载于 2020 年 4 月 11 日。
使用 Numpy 的深度学习优化算法的性能比较
原文:https://towardsdatascience.com/comparative-performance-of-deep-learning-optimization-algorithms-using-numpy-24ce25c2f5e2?source=collection_archive---------46-----------------------
在本文中,我们将通过计算二次凸函数的最优点,从数值上比较主要深度学习优化算法的性能。
简介:
深度学习被称为人工智能的未来。如今,神经网络被称为通用函数逼*器,即它们有能力表示这个宇宙中的任何复杂函数。计算这个具有数百万个参数的通用函数背后的想法来自优化的基础数学。优化可以通过多种方式完成,但对于本文,我们将重点关注基于梯度下降的优化技术。
非凸函数的优化是主要的研究领域。多年来,不同的科学家提出了不同的优化算法来优化神经网络的成本函数。这些算法中的大多数都是基于基于梯度的方法,只是稍加修改。在这篇文章中,我们将讨论五个主要的基于下降的算法-梯度下降,动量,Adagrad,RMSprop,Adam。
进场-
为了了解每个算法在实际中是如何工作的,我们将使用一个凸二次函数。我们将每种算法运行固定的迭代次数(20 次),以比较它们在达到最佳点时的收敛速度和轨迹。下面给出了该任务所选函数的方程,以及使用 Matplotlib 绘制的该函数的三维图形和水*集。
函数方程
功能的 3D 图
3D 绘图的数字实现
二次函数的水*集
最初,我们将从最基本的算法梯度下降开始,然后我们将跟随他们发展的趋势,以支持每个算法发展背后的思想。所以趋势会是这样的-
1-梯度下降
2-动量
3-阿达格勒
4-RMSprop
5-亚当
因为所有这些算法在更新规则的每次迭代中都需要梯度。因此,下面给出了函数的梯度,它将用于在每次迭代中更新两个变量。对于所有算法,我们将使用学习率的固定值=0.4。
渐变矢量
1-梯度下降:
梯度下降是寻找最优解的最传统的技术。在该算法中,使用当前梯度(gt)乘以某个称为学习率的因子来更新当前权重, α。更新规则的等式如下所示。
更新梯度下降规则
梯度下降的数值实现
轨迹使用梯度下降
正如我们在上面的图中看到的,梯度下降经历了许多振荡,收敛非常缓慢。因此,在后面的部分,我们将研究梯度下降的修改,帮助我们实现稳定和更快的收敛。
2-势头:
带动量的梯度下降是一种非常常用的优化器,它消除了由标准梯度下降引起的振荡,并加速了收敛到最佳点。当它加速水*方向时,它减慢垂直方向。在这种杰出行为的帮助下,它使我们在学习率方向上迈出了一大步。除此之外,动量比标准梯度下降稳定得多。
它不是在当前时间步长计算梯度,而是通过参数动量更新权重,动量是当前和过去梯度的指数移动*均值的集合。下面给出的等式解释了更新规则
动量更新规则
Numpy 实现的动量
梯度下降 vs 动量
3-阿达格拉德
自适应梯度下降算法是一种学习梯度下降算法。它的主要区别是 Adagrad 根据网络中参数的重要性对每个权重使用不同的学习率。换句话说,当不必要的参数以较高的学习率训练时,重要的参数以较小的学习率训练以更稳定地收敛。这导致在不允许失真的情况下加速算法。更新公式类似于动量公式,这里每一步的动量都是用先前的动量和梯度的*方来计算的。下面的等式显示了 Adagrad 中的更新规则。
这里,Gt 是由过去梯度的*方和组成的对角矩阵, ϵ是*滑项。此外,⊙表示矩阵-矢量积运算。
Adagrad 的 Numpy 实现
动量 vs 阿达格拉德
从上图可以看出,虽然阿达格拉德呈现出*滑的运动,没有振荡,但是收敛能力不足。为了解决这个问题,Geoffrey Hinton 引入了一个更有效的优化器 RMSprop。
4-RMSprop
Rmsprop 是由著名计算机科学家 Geoffrey Hinton ( Hinton et al .,2012 )提出的另一种高效优化算法。这种算法的工作原理与 Adagrad 相似,只是稍加修改。我们采用这些梯度的指数移动*均值,而不是像 AdaGrad 那样采用梯度*方的累积和。使用指数*均的原因是,较新的梯度更新比不太新的梯度更新更重要。下面的等式显示了 Rmsprop 的更新规则。
RMSprop 的 Numpy 实现
动量 vs 阿达格拉德 vs RMSprop
可以明显看出,当向最优点收敛时,梯度下降算法在垂直方向上产生巨大的振荡,RMSprop 限制垂直方向的运动并加速水*方向的运动。此外,尽管动量减少了振荡,RMSprop 提供了更可靠和更快的收敛。
5-亚当
自适应矩估计是为每个参数计算自适应学习率的另一种类型的优化器。与其他优化器相比,它表现得更加鲁棒和可靠,因为它基本上结合了动量和 RMSprop(即,类似梯度的动量的移动*均和使用*方梯度来调整类似 RMSprop 的学习速率)。更准确地说,Adam 算法执行如下
Adam 的 Numpy 实现
动量 vs Adagrad vs RMSprop 和 Adam 收敛期间的轨迹
如最后一幅图所示,Adam 优化器在直线路径上实现了最快的收敛。对于 Adam,它通过累加之前梯度的总和来抑制振荡,并且由于与 RMSprop 类似的*方梯度项,它遵循一条直线。这导致了一个明显的结论,即 Adam 是 momentum 和 RMSprop 的组合版本。从上图我们不难看出,为什么 Adam 是深度学习中最受欢迎的优化器。即使从远离最优(-6,-6)的点开始,Adam 也能以最少的迭代收敛得最快。
如需了解详情,请访问—https://github.com/Saket-Uoft/Deep-Learning-Optimizers
感谢阅读!
如果你喜欢我的工作,想支持我。支持我的最好方式是在媒体上关注我。
参考资料:
https://medium . com/@ sdoshi 579/optimizer-for-training-neural-network-59450d 71 caf 6
比较 Amazon Textract 和 tesserract OCR—OCR 和 NLP 用例
原文:https://towardsdatascience.com/compare-amazon-textract-with-tesseract-ocr-ocr-nlp-use-case-43ad7cd48748?source=collection_archive---------12-----------------------
用于光学字符识别(OCR)和自然语言处理的两种已知引擎的比较
图片由菲利克斯·沃尔夫从皮克斯拜拍摄
OCR 到底是什么,为什么这么热门?人工智能(AI)使具有人类智能(us)的实体能够大规模处理数据——更快、更便宜。毫无疑问,很大一部分数据是以数字形式保存的,易于阅读和分析。然而,有很大一部分数据存储在物理文档中,既有打字的也有手写的。如何分析这类数据?这就是引人入胜的光学字符识别(OCR)技术的用武之地。使用 OCR,您可以将文档转换为适合编辑和搜索的文本格式的数据。这就是 OCR 能够做到的。
图片由 Gerd Altmann 从 Pixabay 拍摄
在本文中,我们将关注两个众所周知的 OCR 框架:
- Tesseract OCR —在 Apache 许可下发布的自由软件,版本 2.0——自 2006 年以来一直由谷歌赞助开发。
- Amazon Textract OCR — 来自 Amazon 的完全托管服务,使用机器学习来自动提取文本和数据
我们将比较这两个框架的 OCR 能力。让我们从一个简单的图像开始,如下图所示:
作者图片—typewritten.jpg
$ git clone https://github.com/mkukreja1/blogs.git
下载并安装笔记本 blogs/ocr/OCR.ipynb
!pip install opencv-python
!pip install pytesseract
!pip install pyenchantimport cv2
import pytesseract
import re
from pytesseract import Outputimg_typewritten = cv2.imread('typewritten.jpg')
custom_config = r'--oem 3 --psm 6'
txt_typewritten=pytesseract.image_to_string(img_typewritten, config=custom_config)
print(txt_typewritten)
使用镶嵌 OCR 的 OCR 输出:
最佳影片福特 V 法拉利
爱尔兰人
乔乔兔子
小丑
小女人
婚姻故事
1917
从前……在好莱坞
寄生虫
使用 Amazon Textract OCR 的 OCR 输出:
两个框架的表现完全相同。让我们看看手写文本是如何比较的。
作者图片—handwritten.jpg
img_handwritten = cv2.imread('handwritten.jpg')
txt_handwritten=pytesseract.image_to_string(img_handwritten)
print(txt_handwritten)
使用镶嵌 OCR 的 OCR 输出:
<>
疮
&&.一)
哎哟!NS ané
Lp 房地产集团
大使 ATH。远离|房地产
洛美服务
我很高兴今天能和我见面,我也很高兴听到我的声音。再见
AA aiv Go|干杯|
梅根·欧文斯,房产经纪人 402–689–4984www。ForSalebyMegan 。
多媒体短信服务
com
使用 Amazon Textract OCR 的 OCR 输出:
作者图片
对于手写文本,亚马逊 Textract OCR 的表现略好于 Tesseract OCR 。
现在我们将尝试一个繁忙的图像。
作者图片—invoice-sample.jpg
img_invoice = cv2.imread('invoice-sample.jpg')
custom_config = r'--oem 3 --psm 6'
txt_invoice=pytesseract.image_to_string(img_invoice, config=custom_config)
print(txt_invoice)
使用镶嵌 OCR 的 OCR 输出:
http://mrsinvoice.comi7
贵公司 LLC 地址 123,州,我的国家 P 111–222–333,F 111–222–334
收单人:
P:111–222–333,F:111–222–334 a . z
cient @ eromplent
联系电话 101–102–103
f:122–222–334 应付金额:4170 美元
office@example.net
无产品/服务数量/费率/单位金额
小时:价格
1 赞成 2 20 美元 40 美元
2 |方向盘 5 10 美元 50 美元
3 |机油 10 美元 15 美元 150 美元
4 |刹车片 24 美元 1000 美元 2400 美元
小计 20 美元
使用 Amazon Textract OCR 的 OCR 输出:
作者图片
亚马逊 Textract 识别文档中的表格和表单。这是整齐的。
作者图片
高级功能—拼写检查
OCR 扫描的结果通常被输入到 NLP 模型中。因此,结果文本的高度准确性非常重要。我们可以用两种方式处理:
通过拼写检查模块像附魔传递每一个作品
选项 1 —如果拼写检查失败—从结果文本中屏蔽/删除该单词
选项 2——如果拼写检查失败——使用拼写检查建议并编辑结果文本
Python 中经常使用 Enchant 模块来根据字典检查单词的拼写。除了拼写检查之外,enchant 还可以给出纠正单词的建议。
img = cv2.imread('invoice-sample.jpg')
text = pytesseract.image_to_data(img, output_type='data.frame')
text = text[text.conf != -1]
lines = text.groupby('block_num')['text'].apply(list)
print(lines[25])
[‘‘感谢’,‘你’,‘为’,‘你的’,‘生意。]
请注意,第一个单词似乎有拼写问题。
import enchant
dict_check = enchant.Dict("en_US")for word in lines[25]:
if (dict_check.check(word)):
print(word+ ' - Dictionary Check Valid')
else:
print(word+ ' - Dictionary Check Valid Invalid')
print('Valid Suggestions')
print(dict_check.suggest(word))
【感谢—字典检查有效无效
有效建议
【感谢】
你—字典检查有效
为—字典检查有效
你—字典检查有效
业务。—字典检查有效
请注意,enchant 发现第一个单词无效,并能够提供替代建议。
为 NLP 使用正则表达式
我在 IT 行业的早期(大约 25 年前)充满了起起落落。有一天,我会学到一些新的东西,感觉自己站在世界之巅。其他日子就没那么多了。我记得有一天,我的经理让我解决一个模式匹配问题。我必须在 Oracle 中对数据进行模式匹配。因为我以前从来没有这样做过,所以我请求他指点一下。我得到的答案是“使用 REGEX 可以非常容易地做到这一点”。我是一个很好的追随者,除了使用正则表达式模式匹配并不容易。我过了一会儿才意识到我的经理是在开玩笑。
我仍然害怕使用正则表达式,但无法逃避它…..它仍然广泛应用于数据科学,尤其是 NLP。学习正则表达式需要时间。我经常使用像 https://regex101.com/这样的网站进行练习。
例如,如果您想从文档中提取所有日期字段。
d = pytesseract.image_to_data(img, output_type=Output.DICT)
keys = list(d.keys())date_pattern = '^(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[012])/(19|20)\d\d$'n_boxes = len(d['text'])
for i in range(n_boxes):
if int(d['conf'][i]) > 60:
if re.match(date_pattern, d['text'][i]):
(x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])
img_date = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
print(d['text'][i])
产出:2001 年 12 月 12 日
您甚至可以突出显示给定文档中的日期字段
cv2.imwrite('aimg_date.png', img_date)
作者图片
我希望这篇文章有助于启动您的 OCR 和 NLP 知识。像这样的主题是由 Datafence 云学院提供的 AWS 大数据分析课程的一部分。课程是周末自己在网上教的。
比较哪种机器学习模型性能更好
原文:https://towardsdatascience.com/compare-which-machine-learning-model-performs-better-4912b2ed597d?source=collection_archive---------17-----------------------
自信地比较机器学习模型
图像来源
一旦您理解了要解决的业务问题并确定了可用的数据集,您是否曾经对使用哪种机器学习技术感到困惑?
说真的,有这么多机器学习技术可用:线性模型,如逻辑回归,非线性模型,如基于树的,神经网络,支持向量机,在线和强化学习,贝叶斯模型,图形模型等。即使我们能够决定一个,也有大量的特征工程是可能的,这使得一个模型与其他模型非常不同。有一些可用的集成技术试图结合所有世界(模型)的精华,但它们是有成本的。这里的成本可能是时间、精力和把事情复杂化。一个好的机器学习建模者总是喜欢保持事情简单。
这个帖子是关于如何在高置信度的机器学习模型之间进行比较
方案
假设我们建立了两个机器学习模型,模型‘A’和模型‘B’。这两个模型都在验证集上进行了适当的训练和测试。现在,企业想知道哪种模式性能更好,因为在计算和时间方面资源有限。
经理给你分配了这个任务,挑选置信度较高的更好模型,假设置信度为 90%或 显著性水* (α=0.10) 。或者报告,如果很难宣布一个明确的赢家,集合似乎是唯一的办法。你的策略是什么?
战略
模型每周都会生成值。我们有 10 周的时间来得出结论。我们开始注意模型预测的准确性和未来 10 周的实际情况。下表总结了这两种模型的准确性得分。
模型在 10 周时间内的准确性
设μ表示均值σ表示方差。
μ(A) = 73.70,σ(A)= 6.90[RVA】的均值和方差]]
μ(B) = 75.80,σ(B)= 5.51[RVB 的均值和方差]]
从两个随机变量的*均值和标准偏差来看,似乎模型‘B’表现更好。 但是我们有多大的信心或把握呢?
创建假设检验框架
让我们首先定义无效假设和替代假设。
- H₀:“两款车型表现同样出色。”
- h₁:“b 型表现更好。”
继续之前快速复习一下概念(可选)
- 中心极限定理:抽样分布的样本均值,给定我们取足够的样本(n ≥ 30),无论总体遵循什么分布,都将具有正态分布。
此外,对于采样分布
μ(X̄) = μ(X)和σ(X̄) = σ(X)/√n
这里,x 是表示总体的随机变量,X̄表示抽样分布,μ表示*均值和σ标准差(√方差)
- Z-Score/Z-statistics:
“Z-Score 是一种数值度量,用于统计一个值与一组值的*均值(*均值)之间的关系,根据*均值的标准偏差进行测量。如果 Z 分数为 0,则表明数据点的分数等于*均分数。Z 值为 1.0 表示该值是*均值的一个标准差。z 分数可以是正值,也可以是负值,正值表示分数高于*均值,负值表示分数低于*均值。(此处抄袭此处)
一旦我们有了 Z 分数,我们就可以查看 Z 表并对事件的发生赋予正确的置信度。
z 分数计算公式
- T-score/T-statistics/T-distribution
“T 分布,又称学生 T 分布,是一种概率分布类型,类似于正态分布,具有钟形,但尾部较重。t 分布比正态分布出现极值的机会更大,因此尾部更厚。”(从这里复制)
t-score 的公式与 z-score 类似,不同之处在于,它在样本量< 30.
- 增加随机变量时使用
对于任意两个随机变量 X 和 Y,这些变量之和的期望值将等于它们的期望值之和。
E(X+Y)=E(X)+E(Y)对于任意两个随机变量 X 和 Y,这些变量之和的方差等于方差之和加上协方差的两倍。
Var(X+Y)= Var(X)+Var(Y)+2Cov(X,Y)如果 X 和 Y 是独立的,那么
Var(X+Y)= Var(X)+Var(Y)
回到真正的问题
我们创建了假设框架
H₀ =这两种型号的表现一样好。
H₁ =模型的表现不一样(模型 b 表现更好)。
E(B-A)= E(B)-E(A)=μ(B)-μ(A)= 2.09
Var(B-A)= Var(A)+Var(B)=σ(A)+σ(B)= 12.41
对于,H₀为真,E(B-A)应该为 0
使用 CLT,我们可以计算抽样分布的样本均值的 t 得分,即它为 0 的可能性有多大。
t 得分= 0-E(B-A)/√(Var(B-A)/n)
这里 n = 10,E(B-A) = 2.09,Var(B-A)= 12.41
t-score =-2.09/√( 12.41/10)=-1.87,自由度= 10-1 = 9
- 自由度总是 n-1。(为什么?参考此
接下来,我们可以看看 t 表。为了达到 90%的置信度或显著性水* (α=0.10),即两个模型在自由度= 9 的情况下表现相同,我们的 t 得分应≥ -1.833。但是,事实并非如此,t 值为-1.87 ( < -1.833)
t 表(单侧)和 90%置信度 t 分数值
t 分布,90%的置信度得分和我们的 t 分布得分
我们有 90%以上的把握 0 不在这个区间内下跌。换句话说,在 90%的置信度下,模型 B 和模型 A 的*均准确度之差大于 0。因此,我们拒绝零假设,并赞成替代假设。
结论
我们可以通知经理和企业,我们已经从统计上发现 B 型比 A 型表现得更好,因此我们可以继续生产 B 型。
在这里,我们证明了模型 B 优于 A,但如果让我们以 90%的置信度证明模型 B 至少比 A 好 2%,你的策略会是什么?你会在假设框架上做哪些改变?请评论您的想法:)
我的 Youtube 频道获取更多内容:
[## 阿布舍克·蒙戈利
嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…
www.youtube.com](https://www.youtube.com/channel/UCg0PxC9ThQrbD9nM_FU1vWA)
关于作者-:
Abhishek Mungoli 是一位经验丰富的数据科学家,拥有 ML 领域的经验和计算机科学背景,跨越多个领域并具有解决问题的思维方式。擅长各种机器学习和零售业特有的优化问题。热衷于大规模实现机器学习模型,并通过博客、讲座、聚会和论文等方式分享知识。
我的动机总是把最困难的事情简化成最简单的版本。我喜欢解决问题、数据科学、产品开发和扩展解决方案。我喜欢在闲暇时间探索新的地方和健身。在 中 、Linkedin或insta gram关注我,查看我以前的帖子。我欢迎反馈和建设性的批评。我的一些博客-********
- 以简单&直观的方式分解时间序列
- GPU 计算如何在工作中真正拯救了我?
- 信息论& KL 分歧第一部分和第二部分
- 使用 Apache Spark 处理维基百科,创建热点数据集
- 基于半监督嵌入的模糊聚类
比较各种朴素贝叶斯分类算法
原文:https://towardsdatascience.com/comparing-a-variety-of-naive-bayes-classification-algorithms-fc5fa298379e?source=collection_archive---------6-----------------------
数据科学模型
文本分类公式的综合列表
在 Unsplash 上 Leone Venter 拍摄的照片
N aive Bayes 算法是著名的监督分类算法之一。它基于贝叶斯定理,速度非常快,对于文本分类来说足够好。我认为没有必要描述背后的理论,尽管如此,我们将介绍一些概念,然后将重点放在不同实现的比较上。
1.概念
首先,我们采用贝叶斯公式本身:
这是什么意思?既然可能会混淆,我们就换个眼神。我们将从垃圾邮件的角度讨论事件的类别。所以现在我们有两类事件:垃圾邮件和非垃圾邮件。
让我们将 A 改为收到垃圾邮件的事件( y ),将 B 改为由一组单词(x1,x2,…)组成的消息。所以:
现在更明显了:包含单词(x1,x2,…)的消息是垃圾邮件的概率等于收到垃圾邮件的一般概率,乘以垃圾邮件包含上述单词的概率,再除以任何传入消息包含给定单词的概率。
朴素贝叶斯定理说,集合(x1,x2,…)中所有事件的概率可以被视为独立的,所以:
这仍然是一个有点复杂的公式,但我们可以简化它。显然,我们需要计算邮件是垃圾邮件的概率和邮件不是垃圾邮件的概率。因为我们需要比较这两个值,而且它们在同一个字段中,并且具有相同的除法器( P(x1,x2,…) ),所以我们只能使用分子:
我们可以从分布中找到从数据集获取垃圾邮件的一般概率。所以,主要的问题是找到每个单词出现在垃圾消息中的条件概率( P(xi | y) )。这几乎是朴素贝叶斯算法实现之间的唯一区别。
2.履行
我已经从头开始构建了一个算法的实现:
[## 如何建立和应用朴素贝叶斯分类进行垃圾邮件过滤
有效模型的简单实现
towardsdatascience.com](/how-to-build-and-apply-naive-bayes-classification-for-spam-filtering-2b8d3308501)
不过,现在让我们研究一下 sklearn 库的能力。出于我们的目的,我们将使用 Tiago A. Almeida 和 José María Gómez Hidalgo 收集的短信。它是免费的,可以从UCI 机器学习库下载。它包含 5572 条不同消息的记录以及 747 条垃圾消息。
我们将每条信息拆分成一组单词,并对标签进行编码。之后,我们将数据集分为训练和测试部分。
下一步是最重要的:我们将训练部分转向词汇,并计算每个消息中每个词汇的重复次数(在训练和测试部分):
现在数据集已经为模型创建做好了准备。
2.1.高斯朴素贝叶斯
这种方法建立在概率正态分布的假设上。也就是说,垃圾邮件和非垃圾邮件类别的消息中,词汇的出现频率符合高斯定律:
该公式基于消息类中每个词的频率的*均值( μ 和贝塞尔校正方差( σ )。
cl_gauss = **sklearn**.naive_bayes.**GaussianNB**()
res_gauss = cl_gauss.fit(X_train_voc, y_train).predict(X_test_voc)
metrics.accuracy_score(y_test, res_gauss) * 100
结果是模型精度 91.03% 。这已经足够好了,但是说明了单词并不完全是高斯分布。
2.2.多项式朴素贝叶斯
多项式分类最适合离散值,如字数。所以我们希望它能表现出最好的准确性。在这种情况下,每个事件的概率分布基于以下公式:
Ny 是事件的特征总数 y (所有垃圾短信中的总字数) Nyi —每个特征的计数(一个词在所有垃圾短信中重复的汇总数) n —特征数(词汇中的字数) α 是一个*滑拉普拉斯参数,用于丢弃词汇中不存在的词的影响。同样的公式也适用于非垃圾邮件消息集。
cl_multi = **sklearn**.naive_bayes.**MultinomialNB**()
res_multi = cl_multi.fit(X_train_voc, y_train).predict(X_test_voc)
metrics.accuracy_score(y_test, res_multi) * 100
模型精度 99.19% ,是(剧透)包括定制款在内的测试模型中最高的。
2.3.互补朴素贝叶斯
这种方法几乎与多项式相同,尽管现在我们计算一个单词在该类补集中的出现次数。例如,对于垃圾邮件,我们将计算每个单词在所有非垃圾邮件中的重复次数:
Nc —相反类别中的总字数(对于垃圾邮件参数—非垃圾邮件字数),Nci —相反类别中某个单词的重复次数(对于垃圾邮件中的某个单词—在所有非垃圾邮件中的重复次数)。我们也使用相同的*滑参数。计算基本值后,我们开始处理实际参数:
它是 k 个单词的消息中每个单词的权重。最终决策由以下公式计算得出:
因此,分类结果是邮件中每个单词的权重之和的最小值。
cl_compl = **sklearn**.naive_bayes.**ComplementNB**()
res_compl = cl_compl.fit(X_train_voc, y_train).predict(X_test_voc)
metrics.accuracy_score(y_test, res_compl) * 100
我们得到了 98.12%的正确预测,这是一个非常高的结果。
2.4.伯努利朴素贝叶斯
伯努利公式接*于多项式公式,尽管输入是一组布尔值(该词是否出现在消息中)而不是一组频率。
因此,该算法明确地惩罚特征的不出现(消息中的单词在词汇表中不存在),而多项式方法对不存在的值使用*滑参数。sklearn
伯努利算法将输入值二进制化,因此无需额外操作。
cl_bern = **sklearn**.naive_bayes.**BernoulliNB**()
res_bern = cl_bern.fit(X_train_voc, y_train).predict(X_test_voc)
metrics.accuracy_score(y_test, res_bern) * 100
我们已经得到了 98.30% 的正确预测
2.5.分类朴素贝叶斯
分类朴素贝叶斯适用于分类值-无论示例是否具有特征集。在我们的例子中,这意味着词汇表被视为一组特征,而一个单词在消息中的出现被视为与该特征的匹配。所有公式都与多项式方法相同,只是出现次数不同于重复次数。
由于算法需要分类值,我们将单词的频率转换为单词的存在:1-消息包含该单词,0-该单词不在消息中。
X_train_voc_cat= X_train_voc.applymap(**lambda** el: 1 **if** el > 0 **else** 0)
X_test_voc_cat = X_test_voc.applymap(**lambda** el: 1 **if** el > 0 **else** 0)
现在,我们将模型应用于更新的数据集:
cl_cat = **sklearn**.naive_bayes.**CategoricalNB**()
res_cat=cl_cat.fit(X_train_voc_cat,y_train).predict(X_test_voc_cat)
metrics.accuracy_score(y_test, res_cat) * 100
准确率相当高: 98.30% 。
在本文中,我们熟悉了几种朴素贝叶斯算法,理解了它们背后的数学原理,并测试了公式。结果自说自话。您可以在我的 Github 上找到包含所有工作模式的 Jupyter 笔记本:
[## 中级/中等 _jupyter_notes
permalink dissolve GitHub 是 4000 多万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/Midvel/medium_jupyter_notes/blob/master/scikit_bayes/scikit-bayes.ipynb)
此外,看看一个自定义算法的实现,从头开始,没有任何带模型的库:
[## 如何建立和应用朴素贝叶斯分类进行垃圾邮件过滤
有效模型的简单实现
towardsdatascience.com](/how-to-build-and-apply-naive-bayes-classification-for-spam-filtering-2b8d3308501)
机器学习模型的 AUC 与德隆检验的比较
原文:https://towardsdatascience.com/comparing-aucs-of-machine-learning-models-with-delongs-test-21a88bed9a56?source=collection_archive---------40-----------------------
根据卡洛斯·德尔加多的照片修改。此处有原始照片。
你有没有想过如何证明一个机器学习模型的测试集性能与另一个模型的测试集性能有显著差异?本文将描述如何使用 DeLong 检验来获得一个模型的 AUC 是否与另一个模型有显著差异的 p 值,其中 AUC 是指受试者操作特征下的面积。这篇文章包括一个手工计算的例子来说明德隆对一个小数据集测试的所有步骤。它还包括 DeLong 测试的一个示例 R 实现,以支持大型数据集上的高效计算。
德隆测试的一个用例:模型 A 预测心脏病风险,AUC 为 0.92,模型 B 预测心脏病风险,AUC 为 0.87,我们使用德隆测试证明模型 A 的 AUC 与模型 B 有显著差异,p < 0.05.
参考
伊丽莎白·雷·德隆是杜克大学的统计学家和教授。1988 年,她发表了一项测试,以确定两个模型的 AUC 在统计学上是否有显著差异。这个测试被称为“德隆测试”
这篇文章的主要参考资料是:
- Elizabeth DeLong 等人,“比较两条或多条相关接收机工作特性曲线下的面积:一种非参数方法。”生物统计学 1988 年。
- 孙旭等人,“德龙算法的快速实现,用于比较相关接收机工作特性曲线下的面积。”IEEE 信号处理快报 2014。
方便的是,两篇论文都使用了相似的符号,这也是我们将在本文中使用的符号。
灵敏度和特异性的定义
为了理解德隆的测试是如何工作的,我们需要从一些符号开始。我们将通过用它来定义敏感性、特异性和 AUC 来习惯这种符号。
考虑这样一种情况,我们建立了一个模型来预测一个人是否患有疾病。我们对总共有 N 名患者的测试数据集进行预测,其中 m 名患者真正患病,而 n 名患者真正健康。我们的模型为第位患病患者产生预测概率 X ,为第位健康患者产生预测概率 Y :
使用这种符号,我们可以写出灵敏度和特异性的定义:
敏感度也称为回忆率或真实阳性率。它是被模型正确识别为阳性(患病)的真阳性(患病人)的比例。我们将特定决策阈值 z 下的灵敏度定义如下:
特异性也被称为真阴性率。是真阴性(健康人)被模型正确识别为阴性(健康)的比例。我们将特定决策阈值 z 下的特异性定义如下:
这意味着当我们改变决策阈值 z 时,我们将改变灵敏度和特异性。
AUC 的定义和经验 AUC 的计算
受试者工作特性(ROC)提供了不同阈值 z 的灵敏度和特异性汇总。我们通过改变阈值 z 并在每个 z 值处绘制灵敏度对(1 —特异性)的曲线来构建 ROC 曲线。
ROC 曲线下的面积(或 AUC)提供了一个数字来总结模型在所有不同决策阈值下的表现。
在的论文中,DeLong 等人描述了一种方法,其中经验 AUC“通过对构成 ROC 曲线的连接点下方形成的梯形面积求和来计算”(参考)。
就上下文而言,DeLong 的经验 AUC 方法不同于二项式 AUC 方法。二项式 ROC 曲线是“基于对应于阳性条件的诊断测试分数和对应于阴性条件的分数均可由正态分布表示的假设”而构建的(“T18”参考)。
经验 AUC 方法比二项式 AUC 方法更受欢迎,因为经验 AUC 不依赖于二项式 AUC 所要求的强正态假设。
我们可以使用梯形规则计算经验 AUC(表示为“theta hat”),如下所示:
AUC 的这一定义具有直观意义:
- 当 Y < X, this means that the predicted disease probability of a healthy individual is less than the predicted disease probability of a sick individual, which is good: we want actually healthy people to have lower predicted disease risk than actually sick people. So, we reward the model for its good prediction and make a contribution to the model’s AUC of +1/mn.
- When Y = X, this means that the predicted disease probability of a healthy individual is equal to the predicted disease probability of a sick individual, which isn’t awesome but isn’t horrible, so we make a contribution to the model’s AUC of (+1/2)/mn.
- When Y > X 时,这意味着健康个体的预测疾病概率大于患病个体的预测疾病概率,这是不好的:该模型认为实际健康的人比实际患病的人具有更高的疾病风险。在这里,我们不对模型的 AUC 添加任何东西(+0)。
函数 psi(X,Y)也称为heav iside 函数(具有半最大值约定)。
关于敏感性、特异性以及如何构建 ROC 曲线的更多背景信息,请参见这篇文章。
AUC 和 Mann-Whitney 统计之间的联系
在之前的一篇文章中,我描述了 AUC 如下:
AUROC 告诉您您的模型是否能够正确地对示例进行排序:对于临床风险预测模型,AUROC 告诉您随机选择的经历了某个事件的患者比随机选择的未经历该事件的患者具有更高的预测风险评分的概率。
事实证明,这个定义是正确的,因为经验 AUC 等于 Mann-Whitney U 统计量。引用德隆等人的话,
当使用梯形法则计算时,包含经验 ROC 曲线的点下的面积等于比较两个样本值分布的 Mann-Whitney U 统计量。[……]Mann-Whitney 统计估计从 C2[健康人]代表的人群中随机选择的观察值小于或等于从 C1[病人]代表的人群中随机选择的观察值的概率θ。
用另一种方式表述同一观点,维基百科将曼-惠特尼 U 检验描述为:
零假设的非参数检验,即从一个总体中随机选择的值小于或大于从第二个总体中随机选择的值的可能性相等。
因此,总结一下,
请注意:
比较两种模型 AUC 的德隆试验
示例设置
既然我们已经完成了经验 AUC 和所有符号的定义,我们可以继续描述德隆检验如何确定一个模型是否具有与另一个模型在统计上显著不同的 AUC。
这是一个玩具测试集,由五名患者组成,预测来自两个模型。我们将在工作示例中使用这个玩具测试集:
该数据集包括两名真正健康的患者和三名真正患病的患者,他们的健康状况是以某种明确的方式确定的,因此我们可以将其视为“基本事实”模型 A 的列显示了根据模型 A 预测的所有患者的疾病概率。按照前面介绍的符号,这些预测概率由健康患者的 a Y 和患病患者的 X 表示。模型 B 的列显示了根据模型 B 预测的所有患者的疾病概率
请注意,模型 A 是一个具有完美 AUC 的分类器(稍后将明确演示),因为所有健康患者的患病概率都低于所有患病患者。模型 B 没有完美的 AUC。
根据论文的注释,正在考虑的模型总数是 1 <= r <= k where k = 2 (because we are only considering 2 models here.) n = 2 (the number of healthy patients) and m = 3 (the number of sick patients.)
德隆测试的目标
我们想知道就 AUC 而言,模型 A 还是模型 B 更好,其中θ-hat(A)是模型 A 的 AUC,θ-hat(B)是模型 B 的 AUC。为了回答这个问题,我们将计算一个 z 分数:
引用孙等人的话,
在零假设下, z 可以很好的*似为标准正态分布。因此,如果 z 的值偏离零太多,例如z1.96,则认为显著性水* p <为 0.05 的[theta(A) > theta(B)]是合理的。
换句话说,如果 z 偏离零太多,那么我们可以得出结论,模型 A 与 p <为 0.05 的模型 B 具有统计上不同的 AUC。
为了找到 z 分数,我们需要计算经验 AUC、方差 V 和协方差 c。以下部分将展示如何计算这些量。
(旁注:此处“z 得分”中“z”的使用与前面讨论“z 作为决策阈值”中“z”的使用完全无关。)
计算模型 A 和模型 B 的经验 AUC
根据前面提供的经验 AUC 的定义,我们计算模型 A 的经验 AUC:
类似地,我们计算模型 B 的经验 AUC:
注意,模型 A 的 AUC 为 1.0,因为它完美地将所有患病患者归类为比所有健康患者具有更高的患病概率。模型 B 的 AUC 为 2/3,因为它不能完美地对所有患者进行排序。
结构部件 V10 和 V01
德龙测试需要的下一步是计算 V10 和 V01,它们被孙等人称为“结构组件”。
V10 和 V01 将帮助我们找到计算 z 分数所需的方差和协方差。V10 和 V01 定义如下:
回想一下,“r”代表我们正在考虑的型号,因此我们对 r = A(型号 A)和 r = B(型号 B)有不同的结构组件计算。
对于我们的小示例数据集,模型 A 和 B 的结构组件计算如下:
矩阵 S10 和 S01
接下来,我们将使用结构成分 V10 和 V01,结合我们的经验 AUC,来计算矩阵 S10 和 S01,其定义如下:
矩阵 S10 和 S01 是 k×k 矩阵,其中 k 是我们正在考虑的模型总数。因为我们只考虑两个模型(模型 A 和模型 B ),所以每个矩阵都是 2 x 2。
以下是矩阵 S10 中条目的计算:
结果,对于矩阵 S10,除了(B,B)项之外,所有的项都是零。
以下是矩阵 S01 中条目的计算:
矩阵 S01 以该特定示例的所有零条目结束。
计算方差和协方差
现在,我们将使用 S10 和 S01 来获得矩阵 S,其中矩阵 S 包含我们需要的方差和协方差,以便获得德隆测试的 z 分数。我们所要做的就是将 S10 和 S01 相加,分别基于 1/ m=3(患病人数)和 1/ n=2(健康人数)进行加权:
从上面的计算中可以看出,我们最终的 S 矩阵包含模型 A 的经验 AUC 方差、模型 B 的经验 AUC 方差以及模型 A 和 B 的 AUC 协方差。这些是我们获得 z 分数所需的关键量。
Z 分数的计算
为了计算 z 得分,我们插入刚刚计算的经验 AUC、方差和协方差的值:
使用 Z 分数获得 P 值
我们算出来的 z 分数是 1。我们如何由此获得 p 值?
我们正在进行“双尾检验”,因为我们试图宣称模型 A 的 AUC 不同于(“不等于”)模型 b 的 AUC。
我们可以使用一个 z 统计量的双尾 P 值的查找表。在表中,在“十分之一”(垂直)下我们定位为 1.0,在“百分之一”(水*)下我们定位为 0.00,因为我们的 Z 值是 1.00。表中这个位置的条目是 0.31731,这是我们的 p 值。
或者,为了避免在一大堆数字中搜索,我们可以使用像这样的在线计算器。我们需要选择“双尾假设”并输入我们的 z 得分 1,这将产生 p 值 0.317311(与我们从查找表中得到的结果一致。)
计算 R 中的德龙测试
手工计算对于微小的玩具数据集来说很好,但对于任何真实的数据集,我们都希望使用软件来计算德龙的测试。一种选择是使用 r 中的 pROC 包。
使用 pROC 包,我们首先使用 roc 函数创建两条 ROC 曲线进行比较。roc 函数可以作为 roc(响应,预测值)在“响应”(基本事实)和“预测值”(预测概率)上调用。
对于我们的模型 A 和模型 B 示例,我们有:
- 响应
- modela
- modelb
- roca
- rocb
Now that we have built our ROC curves, we can apply the pROC roc.test 函数比较两条 ROC 曲线的 AUC。
输出:
两条相关 ROC 曲线的德隆检验
数据:roca 和 rocb
Z = 1,p 值= 0.3173
替代假设:AUC 的真实差异不等于 0
样本估计:
roc 1 的 AUC roc 2 的 AUC
1.0000000 0.666667
这与我们上面手动获得的结果相匹配。
R 中德隆测试的另一个例子
下面是德隆在 R 中的测试的另一个例子,显示了当使用不同的基本事实和预测概率时,结果是如何不同的:
响应 modela < -c(0.1,0.2,0.05,0.3,0.1,0.6,0.6,0.7,0.8,0.99,0.8,0.67,0.5)
modelb < -c(0.3,0.6,0.2,0.1,0.1,0.9,0.23,0.7,0.9,0.4,0.77,
roc.test(roca,rocb,method=c("delong "))
两条相关 ROC 曲线的德隆检验
数据:roca 和 rocb
Z = 1.672,p 值= 0.09453
替代假设:AUC 的真实差异不等于 0
样本估计:
roc 1 的 AUC roc 2 的 AUC
0.9642857 0.7380952
总结
- 德隆检验可用于显示两个模型的 AUC 在统计上显著不同。
- ROC 曲线总结了不同决策阈值下的敏感性和(1-特异性)。AUC 是 ROC 曲线下的面积。
- 使用 ROC 曲线上的梯形规则计算经验 AUC。
- 德隆检验需要计算经验 AUC、AUC 方差和 AUC 协方差。
- pROC 包中的 R 实现可以快速计算 DeLong 的测试。
关于特色图片
特色图片是一只埃及秃鹰。最初的秃鹫照片是由 Carlos Delgado CC-BY-SA 拍摄的,可以在维基百科这里找到。这篇文章中显示的照片已经被修改,以包括 AUC 图和与德隆测试相关的方程。修改后的照片在与原始照片相同的许可下分发。
原载于 2020 年 2 月 4 日http://glassboxmedicine.com。
葡萄酒质量预测分类模型的比较
原文:https://towardsdatascience.com/comparing-classification-models-for-wine-quality-prediction-6c5f26669a4f?source=collection_archive---------12-----------------------
选择监督机器学习模型预测葡萄酒质量的项目演练
Matthieu Joannon 在 Unsplash 上拍摄的照片
目录
- 简介
- 探索性分析
- 数据预处理
- 验证和模型选择
- 结论
简介
这是我的第一篇博文!由于我决定将职业从化学工程转向数据科学,所以我将自己置于一个持续的、永无止境的学习过程中,我决定以博客帖子的形式分享我在项目中所学到和应用的东西。
在这个项目中,我想比较几个分类算法来预测葡萄酒质量,得分在 0 到 10 之间。由于我更喜欢白葡萄酒而不是红葡萄酒,我决定通过使用来自 UCI 机器学习库的 winequality-white.csv 数据来比较和选择一种算法,以找出是什么造就了一种好酒。该数据集中的属性包括:
- 固定酸度
- 挥发性酸度
- 柠檬酸
- 残糖
- 氯化物
- 游离二氧化硫
- 二氧化硫总量
- 密度
- pH 值
- 硫酸盐化
- 酒精
- 质量
探索性分析
探索性数据分析是一个非常重要的步骤,有助于了解数据集是什么样的,以及我们需要做什么样的修改。我开始导入库和模块,并将我将使用的数据读入 pandas dataframe。
导入库和模块
import matplotlib.pyplot as plt
from scipy import stats
import seaborn as sns
import pandas as pd
import numpy as np
from sklearn import metrics
读取数据
white_wines = pd.read_csv('winequality/winequality-white.csv')
理解数据
为了理解这些数据,我查看了前几行。它看起来很干净,但是它有 4898 行数据,仅仅通过查看来检查所有的行以确定数据是否有问题是不明智的。所以我将在下一步中立刻检查所有丢失的值。
print(white_wines.shape)
white_wines.head()
检查缺失值
数据中没有缺失值,因此可以进行分析,但在建模步骤之前,必须首先检测并消除异常值。
white_wines.isnull().any() fixed acidity False
volatile acidity False
citric acid False
residual sugar False
chlorides False
free sulfur dioxide False
total sulfur dioxide False
density False
pH False
sulphates False
alcohol False
quality False
dtype: bool
检测异常值
我应用了 df.describe()方法来了解数据集的描述性统计信息。对数据集中的问题有一个直观的了解是一个非常好的方法。快速浏览一下,我可以看到有一些异常值。
让我们看看‘残糖’一栏。 count 表示这一列有 4898 行。表示,STD分别表示该列的*均值和标准偏差值,其中 25% 小于 1.70, 75% 小于 9.90。有趣的是,*均值为 6.39,最小值为 0.60,最大值为 65.80。它看起来像一个离群值。
white_wines.describe()
我使用箱线图来可视化“残余糖”列中的值的分布,以获得更好的洞察力。实际最大值约为 20,大于该值的值为异常值,因为它们不包括在观察范围内。
sns.boxplot(white_wines[‘residual sugar’])
使用 Z 值消除异常值
大多数时候,删除离群值很重要,因为它们很可能会影响机器学习模型的性能。但是假设你的数据集有 30%是异常值。那么将它们全部移除可能是不明智的,因为可能有更多的问题需要进一步检查。为了找到并去除异常值,我使用了 z-score。
z 分数的数学公式
它的解释是取数据点或观察值,减去总体的*均值,然后除以标准差。它表示一个数据点距离*均值有多少标准差。离*均值太远的数据点被认为是异常值。在大多数情况下,异常值检测的阈值是 z 得分> 3 或 z 得分
z = np.abs(stats.zscore(white_wines))
white_wines = white_wines[(z < 3).all(axis=1)]
white_wines.shape(4487, 12)
检查属性之间的相关性
当我检查列之间的相关性时,我可以看到一些特性与质量有很强的相关性,而另一些则没有。
plt.subplots(figsize=(15, 10))
sns.heatmap(white_wines.corr(), annot = True, cmap = ‘coolwarm’)
检查班级不*衡
作为探索性数据分析的最后一步,我想检查班级的不*衡。似乎存在着严重的阶级不*衡,少数阶级的代表性低于多数阶级。这将是后面步骤中建模的关键部分。
white_wines[‘quality’].value_counts()6 2038
5 1309
7 855
8 161
4 124
Name: quality, dtype: int64
数据预处理
在这一步的分析中,我定义了训练和测试机器学习模型的特征以及预测“质量”的目标。然后我对这些特征进行了标准化(也称为 z 分数标准化),因为不同规模的特征可能会影响机器学习模型的性能。为此,我使用了 Scikit-learn 中定义的 StandardScaler()函数。最后,我将数据集分成 80%的训练集和 20%的测试集。
定义特征和目标
# Define features X
X = np.asarray(white_wines.iloc[:,:-1])# Define target y
y = np.asarray(white_wines[‘quality’])
标准化数据集
from sklearn import preprocessingX = preprocessing.StandardScaler().fit(X).transform(X)
训练和测试集分离
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=0)
print (‘Train set:’, X_train.shape, y_train.shape)
print (‘Test set:’, X_test.shape, y_test.shape)Train set: (3589, 11) (3589,)
Test set: (898, 11) (898,)
验证和模型选择
在这一部分中,我训练了几种分类算法,以找到最适合我所使用的数据集的算法。
k-最*邻
我从 K-最*邻分类算法开始。该算法所做的是获取一个数据点,并在训练数据中选择 K 个最接*该数据点的观察值,然后根据来自 K 个最*邻居的最受欢迎的响应值来预测该数据点的响应。
KNN精准剧情
我画了一个图,看看精度是如何随着 k 的数量而变化的。
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score# Number of k from 1 to 26
k_range = range(1, 26)k_scores = []# Calculate cross validation score for every k number from 1 to 26
for k in k_range:
knn = KNeighborsClassifier(n_neighbors=k)# It’s 10 fold cross validation with ‘accuracy’ scoring
scores = cross_val_score(knn, X, y, cv=10, scoring=’accuracy’)
k_scores.append(scores.mean())%matplotlib inline# Plot accuracy for every k number between 1 and 26
plt.plot(k_range, k_scores)
plt.xlabel('Value of K for KNN')
plt.ylabel('Cross-validated accuracy')
交叉验证为 KNN
我决定用 k=19,因为用它可以获得最高的精度。并用不同的验证方法对模型进行训练并计算精度。
# Train the model and predict for k=19knn = KNeighborsClassifier(n_neighbors=19)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)from sklearn.metrics import accuracy_score
from sklearn.metrics import roc_auc_score# classification report for test set
print(metrics.classification_report(y_test, y_pred, digits=3, zero_division = 1))# Calculate cv score with 'accuracy' scoring and 10 folds
accuracy = cross_val_score(knn, X, y, scoring = 'accuracy',cv=10)
print('cross validation score',accuracy.mean())# Calculate cv score with 'roc_auc_ovr' scoring and 10 folds
accuracy = cross_val_score(knn, X, y, scoring = 'roc_auc_ovr',cv=10)
print('cross validation score with roc_auc',accuracy.mean())# Calculate roc_auc score with multiclass parameter
print('roc_auc_score',roc_auc_score(y_test,knn.predict_proba(X_test), multi_class='ovr'))
KNN 的分类表和验证分数
当我查看分类报告时,我立即发现训练时没有考虑类别 4 和类别 8,因为它们的回忆结果为零。这意味着,在所有第 4 类和第 8 类成员中,它没有正确预测任何一个。所以,对于我们的数据集来说,这不是一个好的模型。
逻辑回归
逻辑回归实际上是一种二元分类算法,可用于是/否、真/假等问题。
在这种情况下,它允许我们将它用于多类分类问题,如我们的问题。因为在我们的数据集中,有 5 类质量被预测为。为了将其用作多类分类算法,我使用了 multi_class= '多项式',solver = '牛顿-cg '参数。
考虑到这是一个多类分类问题,我在计算交叉验证分数时使用了“roc_auc_ovr”评分参数,而不是“准确性”。我还用 multi_class='ovr '参数计算了 roc_auc_score。我将在后面的结论中解释这些。
# import module
from sklearn.linear_model import LogisticRegression# Train and fit model
logreg = LogisticRegression(multi_class=’multinomial’,solver =’newton-cg’)
logreg.fit(X_train, y_train)# Predict out-of-sample test set
y_pred = logreg.predict(X_test)# classification report
print(metrics.classification_report(y_test, y_pred, digits=3, zero_division = 1))print(‘accuracy’,accuracy_score(y_test, y_pred))# Calculate cv score with ‘roc_auc_ovr’ scoring and 10 folds
accuracy = cross_val_score(logreg, X, y, scoring = ‘roc_auc_ovr’,cv=10)
print(‘cross validation score with roc_auc’,accuracy.mean())# Calculate roc_auc score with multiclass parameter
print(‘roc_auc_score’,roc_auc_score(y_test,logreg.predict_proba(X_test), multi_class=’ovr’))
逻辑回归的分类表和验证分数
即使交叉验证分数稍微高一点,一些召回结果仍然是零。让我们看看如果我们添加一些多项式特征会发生什么。
向逻辑回归添加多项式特征
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline# Add polynomial features to the logistic regression modeldef PolynomialRegression(degree=2, **kwargs):
return make_pipeline(PolynomialFeatures(degree),
LogisticRegression(multi_class=’multinomial’,solver =’newton-cg’, **kwargs))
现在,我尝试向逻辑回归模型添加三次多项式特征。
# Train and fit the 3rd degree polynomial regression model
poly = PolynomialRegression(3)
poly.fit(X_train,y_train)# Test out-of-sample test set
y_pred = poly.predict(X_test)# Classification report
print(metrics.classification_report(y_test, y_pred, digits=3))# Calculate cv score with 'roc_auc_ovr' scoring and 10 folds
accuracy = cross_val_score(poly, X, y, scoring = 'roc_auc_ovr',cv=10)
print('cross validation score with roc_auc_ovr scoring',accuracy.mean())# Calculate roc_auc score with multiclass parameter
print('roc_auc_score',roc_auc_score(y_test,poly.predict_proba(X_test), multi_class='ovr'))
三次多项式回归的分类表和验证分数
最后,在预测时,我有一些少数类的代表,但它们非常低,交叉验证分数也比以前低。
决策图表
决策树是数据科学领域中最常用的分类算法之一。当我将其应用到我的数据集时,召回结果有所增加,但交叉验证分数下降了。
from sklearn.tree import DecisionTreeClassifier# Train and fit the Decision Tree Classification model
tree = DecisionTreeClassifier(random_state=0)
tree.fit(X_train, y_train)# Evaluate the model with out-of-sample test set
y_pred = tree.predict(X_test)# Classification report
print(metrics.classification_report(y_test, y_pred.round(), digits=3))# Calculate cv score with ‘roc_auc_ovr’ scoring and 10 folds
accuracy = cross_val_score(tree, X, y,scoring = ‘roc_auc_ovr’,cv=10)
print(‘cross validation score with roc_auc_ovr scoring’,accuracy.mean())# Calculate roc_auc score with multiclass parameter
print(‘roc_auc_score’,roc_auc_score(y_test,tree.predict_proba(X_test), multi_class=’ovr’))
决策树的分类表和验证分数
随机森林
随机森林是一种集成学习方法,它构建多个决策树,然后根据大多数决策树的预测结果进行预测。我喜欢把它想象成为了一个健康问题去看多个医生,然后根据大多数医生的意见决定你是否应该做手术。
所以让我们看看随机森林模型的结果。
from sklearn.ensemble import RandomForestClassifier# Train and fit the Random Forest Classification model
forest = RandomForestClassifier(n_estimators=100,random_state = 0)
forest.fit(X_train, y_train)# Test out-of-sample test set
y_pred = forest.predict(X_test)# Classification report
print(metrics.classification_report(y_test, y_pred.round(), digits=3))# Calculate cv score with 'roc_auc_ovr' scoring and 10 folds
accuracy = cross_val_score(forest, X, y,scoring = 'roc_auc_ovr',cv=10)
print('cross validation score with roc_auc_ovr scoring',accuracy.mean())# Calculate roc_auc score with multiclass parameter
print('roc_auc_score',roc_auc_score(y_test,forest.predict_proba(X_test), multi_class='ovr'))
决策树的分类表和验证分数
是目前为止最好的!roc_auc_score 非常好,交叉验证分数是目前为止最好的,甚至对于少数类也有一些召回结果。但这还不够。因此,可以提高召回率的一个方法是过度采样少数类。为此,我使用了随机森林算法和 SMOTE 算法实现。
添加 SMOTE 算法
SMOTE(合成少数过采样)算法创建合成少数类样本,以增加少数类的代表性。
# Import SMOTE module
from imblearn.over_sampling import SMOTE# Create model and fit the training set to create a new training set
sm = SMOTE(random_state = 2)
X_train_res, y_train_res = sm.fit_sample(X_train, y_train.ravel())# Create random forest model
forest = RandomForestClassifier(n_estimators=100,random_state = 0)# Fit the model to the new train set
forest.fit(X_train_res, y_train_res.ravel())# # Test out-of-sample test set
y_pred = forest.predict(X_test)# Classification report
print(metrics.classification_report(y_test, y_pred.round(), digits=3))# Calculate cv score with 'roc_auc_ovr' scoring and 10 folds
accuracy = cross_val_score(forest, X, y,scoring = 'roc_auc_ovr',cv=10)print('cross validation score with roc_auc_ovr scoring',accuracy.mean())# Calculate roc_auc score with multiclass parameter
print('roc_auc_score',roc_auc_score(y_test,forest.predict_proba(X_test), multi_class='ovr'))
SMOTE 随机森林的分类表和验证分数
即使准确率几乎与前一个相同,少数民族班级的召回结果也显著增加。
结论
在这个项目中,我使用了 K *邻、多项式特征的逻辑回归、决策树和随机森林。利用 Scikit-learn 中的roc_auc_score
,我计算了每个模型的 AUC 分数。同样使用cross_val_score
方法,我通过传递roc_auc_ovr
参数使用交叉验证方法找到 AUC 分数。尽管它通常用于二进制分类中的性能评估,但通过一对多的方法,我将其应用于多类分类问题。当存在高等级不*衡时,用这种方法评估模型是有利的。也不需要设置分类阈值。
如果我们比较所有模型的交叉验证分数和召回结果,我们可以看到使用随机森林分类器和 SMOTE 方法得到的结果最好,交叉验证分数为 0.7565。由于我们的班级高度不*衡,SMOTE 创建了合成少数抽样来*衡样本。并训练模型,就好像我们的数据集中有*衡的类一样。
尽管我们得到了最高的交叉验证分数,大约为 0.75,但它仍然不是一个理想的模型,因为召回结果对于任何类别都没有足够的代表性。在这种情况下,为了改进模型,我们需要更多的数据来训练它。
感谢您的阅读!
如果您有任何反馈或更正,请随时通过我的 LinkedIn 联系我!
比较冠状病毒对各国经济和健康的影响
原文:https://towardsdatascience.com/comparing-coronavirus-economic-and-health-impacts-across-nations-ef8e4ea52741?source=collection_archive---------34-----------------------
Covid 疫情的简单多元分析
粘土银行在 Unsplash 拍摄的照片
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
几周前,国际货币基金组织发布了 2020 年 6 月的《世界经济展望》( T23 ),这份报告令人沮丧。该机构预测,今年全球国内生产总值(GDP)将下降 4.9%。我们应该关心吗?毕竟,人们一直批评 GDP 是衡量一个国家健康状况的糟糕指标。当人们生病或濒临死亡时,GDP 的下降真的重要吗?
幸运的是,我们并不局限于根据单一变量来分析全球健康状况,甚至经济学家也意识到了这一事实。他们现在有另一个度量到轨道。像我们一样,国际货币基金组织的工作人员可能每天早上都会打开仪表板,记录冠状病毒感染和死亡人数。正如 2007 年金融危机让每个人都成了业余经济学家一样,这场危机让我们都成了业余流行病学家。而且,就像一个国家的股市或 GDP 一样,冠状病毒感染率可以代表一个国家的实力和健康。
我们今天跟踪哪个指标?—由奥斯汀·迪斯特尔在 Unsplash 上拍摄
为了更好地了解世界是如何面对这种病毒的,我收集了各国的经济和卫生数据。一个主要的输入将是以每 100 万人感染人数衡量的病毒传播。另一个是一个国家的经济增长率,以 GDP 增长的百分比来衡量。很简单,让我们开始吧。
1 —收集数据
2020 年 4 月全球 GDP 增长预测—https://www . IMF . org/external/data mapper/NGDP _ RPCH @ WEO/OEMDC/ADVEC/WEO world/WEQ
年的经济数据来自国际货币基金组织。该组织于 4 月在 T2 发布了每个国家的增长预测,并于 6 月再次发布了大多数国家的增长预测。当然,这些只是投射,在*时很难做出。不能保证它们会实现,但这是我能找到的最好的了。
作为参考,我还抓取了 2019 年 10 月的经济预测,在 Covid 袭击之前。在那些*静的日子里,美国国内生产总值预计增长 2%,失业率为 3.7%,创历史新低。我将所有这些预测放入一个简单的表格中,如下图所示。
对于冠状病毒病例,数据更容易获得,有几十个好的来源。我选择了来自 worldometers 的漂亮的表格记录,因为它们是最新的,并且格式良好,如下所示。
2016 年 7 月的数据
2——增加一些有趣的变量
我知道我说过我只看 GDP,但是我忍不住为这个分析添加了一些其他的数据。最好留着它们,以防我们需要。
失业
IMF 也在今年 4 月公布了预期就业数据。它们甚至比 GDP 数据更加黯淡。利用国际货币基金组织的网站,我们可以导出 2020 年每个国家的失业率的表。
国内生产总值总额
每个国家的 GDP 总量也是由国际货币基金组织发布的,它有助于了解 GDP 增长/损失的大小。
全球区域数据
最后,我想我可能想要比较世界上不同的地区,所以我也从 statisticstimes.com 获取了地区数据
3-合并数据源
用多个数据源做任何有趣的事情都意味着将它们放入一个单一的数据框架。幸运的是,python Pandas 库允许轻松合并不同的数据集。在这种情况下,我只用 4 行代码就可以合并不同国家的表!
import pandas as pdimf_data = pd.read_csv(‘imf_merged.csv’, sep=’,’)
corona_data = pd.read_csv(‘corona.csv’, sep=’,’)
inner_merged_total = pd.merge(imf_data, corona_data, on=[“Country”])
inner_merged_total.to_csv( “merged_data.csv”)
就是这样。在清理了国家名称(例如“大韩民国”与“韩国”)后,我们可以合并任意多的数据源。
合并后,一切都在一个整洁的数据框架中,包含了分析所需的所有关键信息。数据帧的示例如下所示。
最终数据帧的一部分
4 —分析结果
我喜欢用 R 进行分析和探索,因为它是交互式的,并且允许数据操作而不需要太多代码。下面是一个简单的代码片段。我们用 python 生成的 csv 文件。很容易用任何变量来排序,比如国家人口
dt = read.csv(“all_data2.csv”, strip.white=TRUE)dt = dt[order(dt$Population, decreasing=TRUE),]
有了干净的数据,就很容易调查病毒的经济影响问题。下面是其中的一些问题。
富裕国家能更好地应对病毒吗?
看待国家财富和新冠肺炎之间关系的一种东方方式是将这两个变量对立起来。使用 R ggplot 包完成这项工作的代码如下所示。
dt$gdp_per_capita = as.numeric(as.character(dt$X2020.01.01.Gdp.US.billions))/dt$Population * 1000000000p = ggplot(dt, aes(y = Tot.Cases.per.1M.pop, x = gdp_per_capita)) + geom_point(aes(color = region, size=Total.Cases))
p = p + theme_classic()
p = p + theme(legend.position = "none")
p = p + labs(title="Infections vs GDP per Capita")
p = p + geom_text(aes(label=CountryChart),hjust=0, vjust=0,size=4.5)
p = p + theme(axis.text=element_text(size=14,face="bold"), axis.title=element_text(size=18))
p = p + xlab("GDP per Capita") + guides(fill=FALSE)
p = p + ylab("Total Cases per 1M People") + guides(fill=FALSE)
当绘制 Covid 病例(每 100 万人)与国家财富(人均 GDP)的对比图时,一个观察结果引人注目。看起来富裕国家并不比贫穷国家更好地应对危机。事实上,一些最富裕的国家,如卡塔尔、美国、瑞典和新加坡的感染率非常高。事实上,国家人均国内生产总值和人均感染之间的关系是正相关的。
correlation = cor(dt$Tot.Cases.per.1M.pop, dt$gdp_per_capita)
每百万人口超过 5000 例的国家人均 GDP 高达 36233.19 美元,远远高于贫困国家。计算代码如下。
high_cases = dt[dt$Tot.Cases.per.1M.pop > 5000,]
mean(high_cases$gdp_per_capita)
富裕国家测试的多吗?
富裕国家结果不佳的一个可能解释是更好的 Covid 测试。事实上,川普总统已经声称美国的大量病例完全是因为优越的检测制度。如果我们将总测试数(每 100 万人)与总案例数(每 100 万人)进行对比,我们会发现相关性并不完美。事实上,像美国这样的国家并没有比许多欧洲国家测试更多的人。
蓝线是一个简单的线性回归,它给了我们一个很好的指标,表明哪些国家测试得很好。贫困线以下的国家应该进行更多的检测,以跟上具有相似财富/感染率的国家。在 R 中,线性回归线很容易用单个语句添加。请参见下面的粗体行。
p = ggplot(dt, aes(x = Tot.Cases.per.1M.pop, y = Tests.per.1M.pop)) + geom_point(aes(color = region, size=gdp_per_capita))
p = p + theme_classic()
p = p + labs(title="Tests vs Cases")
p = p + theme(axis.text.x = element_text(angle = 90))
***p = p + geom_smooth(method='lm', formula= y~x, se = FALSE)*** p = p + geom_text(aes(label=CountryChart),hjust=0, vjust=0,size=2.5)
ggsave(filename = "tests_vs_cases.png" , plot=p, width=12, height=9)
哪些地区受灾最严重?
在绘制冠状病毒病例与 GDP 的对比图时,有一点很突出,那就是东亚国家的表现。在第一张图中,这些国家用挂在 y 轴下方的大绿点表示。也许更容易的方法是按地区做一个柱状图,以确切了解病毒是如何影响世界各地的。下面是条形图的 r 代码。
# Aggregate by region
regions = aggregate( Tot.Cases.per.1M.pop ~ region, dt, mean )# Create Factor for plotting
regions$region = factor(regions$region, levels = regions$region[order(regions$Tot.Cases.per.1M.pop, decreasing=FALSE)])p = ggplot(regions, aes(x=region, y=Tot.Cases.per.1M.pop, fill="#1dcaff")) + geom_bar(stat="identity")
p = p + ggtitle("Average Number of Coronavirus Cases per 1M Population")
p = p + theme(plot.title = element_text(hjust = 0.5))
p = p + theme(axis.text=element_text(size=13,face="bold"), axis.title=element_text(size=13), axis.title.y=element_blank())
p = p + theme(plot.title = element_text(size=14,face="bold"))
p = p + ylab("Cases per 1M Population") + guides(fill=FALSE)
p = p + coord_flip()
按地区绘制*均感染率图,我们确认东亚国家(中国、日本、韩国、台湾等)的*均感染率非常低。相比之下,西亚(或中东)国家受到的冲击最大。最后,南欧(西班牙、意大利等)、南美(巴西、智利等)和北美(美国)的人均 Covid 病例数最多。
Covid 病例与经济衰退相关吗?
好的,所以富裕国家通常比贫穷国家(东亚除外)有更多的感染者。一个简单的问题是,这场健康危机是否会在遭受重创的国家转化为经济危机。或者,全球经济是如此相互关联,以至于每个国家都面临衰退?将 2020 年各国的预计 GDP 与其冠状病毒病例(每百万人)进行对比,没有明显的相关性。许多病例较少的国家今年仍有望大幅萎缩。
上面的图使用 GDP 来确定点的大小。因此,我们可以看到 2020 年中国的病例很少,增长率为 1%。我们也看到美国有许多病例,预计经济将收缩 8%。
p = ggplot(dt, aes(x = Tot.Cases.per.1M.pop, y = X2020.GDP.Growth.Projected.06_2020)) + geom_point(aes(color = Country, size=X2020.01.01.Gdp.US.billions))
当然,以 2019 年 10 月份所做的经济预测作为参考,再检查一遍可能会更好。如果我们从冠状病毒袭击前的预测中减去 2020 年 6 月的预测,我们可以得到一个更好的指标,我称之为“GDP 损失”。
dt$june_gdp_loss = dt$X2020.GDP.Growth.Projected.06_2020 - dt$X2020.GDP.Growth.Projected.10_2019
这个图也好不到哪里去,但我们确实看到,像英国、美国和西班牙这样大规模爆发的国家现在受到了更大的打击。总的来说,不管目前的感染率如何,东亚以外的每个地区在 2020 年都将经历重大的经济影响。这可能是由于对未来疫情的预期,或者是因为今年全球需求(尤其是来自美国的需求)将非常低迷。
Covid 病例与失业相关吗?
从失业数据中可以更清楚地看出冠状病毒造成的经济损失。下面,我从 2020 年 4 月的测量数据中减去了 2020 年的预期失业数据(2019 年 10 月的数据)。在这方面,更明显的是,受冲击最严重的国家失业率上升幅度更大。
dt$uneployment_loss = dt$X2020.Unemployment.Projected.04_2020 - dt$X2020.Unemployment.Projected.10_2019
最后的想法
在我生活的美国,新冠肺炎危机令人遗憾地将许多人分成对立和激进的阵营。一些人认为必须不惜一切代价控制病毒,还有一些人认为我们应该考虑 T2 因长时间关闭造成的人员和经济损失。不幸的是,这些意见已经沿着政党路线分裂,并导致了阻碍美国政治的同样愚蠢的二分法和基本思想。
就我个人而言,我一直渴望一份从医学和经济两方面考虑一个国家健康状况的分析报告。尽管国际货币基金组织的经济预测并不完美,但它们可以开始表明受 Covid 影响的国家遭受了重大的经济损失。为了全世界的利益,抗击和控制这种病毒符合所有国家的利益。
比较数据版本控制工具— 2020 年
原文:https://towardsdatascience.com/comparing-data-version-control-tools-2020-c11ef1c80ea7?source=collection_archive---------18-----------------------
Alexander Schimmeck 在 Unsplash 上的照片
无论您使用逻辑回归还是神经网络,所有模型都需要数据来进行训练、测试和部署。管理和创建用于这些模型的数据集需要大量的时间和空间,并且由于多个用户更改和更新数据,可能会很快变得混乱。
这可能导致意想不到的结果,因为数据科学家继续发布新版本的模型,但针对不同的数据集进行测试。许多数据科学家可能在相同的几组训练数据上训练和开发模型。这可能会导致对数据集进行许多微妙的更改,一旦部署了模型,这可能会导致意想不到的结果。
这篇博客文章讨论了管理数据带来的许多挑战,并概述了用于机器学习和数据版本控制的顶级工具。
汇总表—请进一步阅读,了解更详细的比较。作者图片
数据管理的挑战
管理数据科学和机器学习模型的数据集和表格需要数据科学家和工程师投入大量时间。从管理存储、数据版本到访问,一切都需要大量的手动干预。
储存空间
训练数据会占用 Git 存储库的大量空间。这是因为开发 Git 是为了跟踪文本文件中的变化,而不是大型二进制文件。因此,如果一个团队的训练数据集涉及大型音频或视频文件,这可能会给下游带来很多问题。对训练数据集的每次更改通常会在存储库的历史中产生一个重复的数据集。这不仅创建了一个大的存储库,而且使得克隆和重置非常慢。
数据版本管理
当试图管理版本时,无论是代码还是 ui,都有一种普遍的趋势——甚至在技术人员中——通过在文件名的末尾添加版本号或单词来“管理版本”。在数据的上下文中,这意味着项目可能包括 data.csv、data_v1.csv、data_v2.csv、data_v3_finalversion.csv 等。这个坏习惯已经不是老生常谈了,事实上大多数开发人员、数据科学家和 UI 专家都是从坏的版本控制习惯开始的。
照片由斯蒂夫·约翰森在 Unsplash 上拍摄
多用户
在生产环境中工作时,最大的挑战之一是与其他数据科学家打交道。如果您在协作环境中没有使用某种形式的版本控制,文件将被删除、更改和移动;你永远不会知道谁做了什么。此外,很难将您的数据恢复到原始状态。这是管理模型和数据集的最大障碍之一。
数据版本化是团队机器学习模型开发自动化的关键之一。虽然如果你的团队试图开发自己的系统来管理过程会非常复杂,但情况并非如此。
让我们探索六个伟大的开源工具,您的团队可以使用它们来简化数据管理和版本控制。
DVC
DVC ,或数据版本控制,是许多可用的开源工具之一,可以帮助简化您的数据科学和机器学习项目。该工具采用 Git 方法,因为它提供了一个简单的命令行,只需几个简单的步骤就可以设置好。顾名思义,DVC 不仅仅关注数据版本。它还帮助团队管理他们的管道和机器学习模型。最后,DVC 将帮助提高你的团队的一致性和你的模型的再现性。
赞成的意见
- 轻量级、开源,可用于所有主要的云*台和存储类型。
- 灵活,格式和框架无关,易于实现。
骗局
- DVC 版本控制与管道管理紧密结合。这意味着如果你的团队已经在使用另一个数据管道工具,就会有冗余。
- DVC 是轻量级的,这意味着您的团队可能需要手动开发额外的功能,使其易于使用。
三角洲湖
Delta Lake 是一个帮助改进数据湖的开源存储层。它通过提供 ACID 事务、数据版本化、元数据管理和管理数据版本来实现这一点。
该工具更接*于数据湖抽象层,填补了大多数数据湖有限的空白。
赞成的意见
- 提供了许多您当前的数据存储系统中可能没有的功能,例如 ACID 事务或有效的元数据管理。
- 减少了手动数据版本管理和处理其他数据问题的需要,使开发人员能够专注于在其数据湖之上构建产品。
骗局
- 对于大多数项目来说,Delta Lake 往往是多余的,因为它是基于 Spark 和大数据开发的。
- 需要使用专用的数据格式,这意味着它不太灵活,并且与您当前的格式无关。
- 工具的主要目的是更像一个数据抽象层,这可能不是你的团队所需要的,可能会让开发人员需要一个更轻便的解决方案。
吉特 LFS
Git LFS 是由许多开源贡献者开发的 Git 扩展。该软件旨在通过使用指针来消除可能添加到您的存储库中的大文件(例如,照片和数据集)。
指针较轻,指向 LFS 商店。因此,当您将回购放入主存储库时,更新时间不会太长,也不会占用太多空间。
对于管理数据来说,这是一个非常轻量级的选项。
赞成的意见
- 轻松集成到大多数公司的开发工作流程中。
- 利用与 Git 存储库相同的权限,因此不需要额外的权限管理。
骗局
- Git LFS 需要专门的服务器来存储你的数据。反过来,这最终会导致您的数据科学团队陷入困境,并增加工程工作量。
- Git LFS 服务器不像 DVC 那样可以扩展,它将数据存储到更通用的易于扩展的对象存储器中,比如 S3。
- 非常具体,可能需要在数据科学工作流的其他步骤中使用许多其他工具。
迟钝的人
Pachyderm 是该榜单上为数不多的数据科学*台之一。Pachyderm 的目标是创建一个*台,通过管理整个数据工作流,轻松再现机器学习模型的结果。在这方面,厚皮动物是“数据的码头工人”。
Pachyderm 利用 Docker 容器来打包您的执行环境。这使得重现相同的输出变得容易。版本化数据和 Docker 的结合使得数据科学家和 DevOps 团队可以轻松部署模型并确保它们的一致性。
Pachyderm 致力于其数据科学权利法案,该法案概述了该产品的主要目标:可再现性、数据来源、协作、增量、自治和基础设施抽象。
这些支柱驱动了它的许多特性,并允许团队充分利用这个工具。
赞成的意见
- 基于容器,这使得您的数据环境可移植,并易于迁移到不同的云提供商。
- 健壮,可以从相对较小的系统扩展到非常大的系统。
骗局
- 由于有如此多的移动部件,比如管理 Pachyderm 的免费版本所需的 Kubernetes 服务器,所以需要更多的学习曲线。
- 由于各种各样的技术组件,很难将 Pachyderm 集成到公司现有的基础架构中。
傻瓜
就数据版本化而言,Dolt 是一个独特的解决方案。与其他一些简单的版本数据不同,Dolt 是一个数据库。
Dolt 是一个具有 Git 风格版本的 SQL 数据库。与 Git 不同,在 Git 中,您可以对文件进行版本控制,而 Dolt 则是版本表。这意味着您可以更新和更改数据,而不必担心丢失更改。
虽然这款应用还是新的,但有计划在不久的将来让它 100%兼容 Git 和 MySQL。
赞成的意见
- 轻量级和部分开源。
- SQL 接口,与更模糊的选项相比,使数据分析师更容易访问它。
骗局
- 与其他数据库版本选项相比,Dolt 仍然是一个成熟的产品。
- Dolt 是一个数据库,这意味着您必须将您的数据迁移到 Dolt 中才能获得好处。
- 为版本控制表而构建。这意味着它不包括其他类型的数据(例如图像、自由格式的文本)。
莱克夫斯
LakeFS 让团队构建可重复的、原子的和版本化的数据湖操作。这是一个新来的人,但它有很强的冲击力。它提供了一个类似 Git 的分支和版本控制模型,旨在处理您的数据湖,扩展到数 Pb 的数据。
与 Delta Lake 类似,它为您的数据湖提供 ACID 合规性。然而,LakeFS 支持 AWS S3 和谷歌云存储作为后端,这意味着它不需要使用 Spark 来享受所有的好处。
赞成的意见
- 为易于使用的云存储(如 S3 和 GCS)提供高级功能,如 ACID 事务,同时与格式无关。
- 易于扩展,支持非常大的数据湖。能够为开发和生产环境提供版本控制。
骗局
- LakeFS 是一个相对较新的产品,因此与其他解决方案相比,其特性和文档可能会变化得更快。
- 侧重于数据版本化,这意味着您将需要为数据科学工作流的其他步骤使用许多其他工具。
你真的需要数据版本控制吗?
尽管数据版本化有诸多好处,但您并不总是需要在管理数据方面投入大量精力。例如,大部分数据版本控制都是为了帮助跟踪随时间变化很大的数据集。
照片由艾米丽·莫特在 Unsplash 拍摄
有些数据,如网络流量,只是附加到。这意味着添加了数据,但很少更改。这意味着创建可重现结果所需的数据版本是开始和结束日期。注意这一点很重要,因为在这种情况下,您可能能够避免上面提到的所有工具的设置。您仍然需要管理开始和结束日期,以确保您每次都测试相同的数据,以及您正在创建的模型。然而,在这些情况下,您不一定需要将所有数据提交到您的版本控制系统。
摘要
管理数据版本是数据科学团队避免输出不一致的必要步骤。
无论您使用 Git-LFS、DVC,还是其他讨论过的工具,都需要某种数据版本控制。这些数据版本化工具有助于减少管理数据集所需的存储空间,同时还有助于跟踪不同团队成员所做的更改。如果没有数据版本控制工具,随叫随到的数据科学家可能会在凌晨 3 点起床调试由不一致的模型输出导致的模型问题。
然而,所有这些都可以通过确保您的数据科学团队实施数据版本管理流程来避免。
原载于 2020 年 10 月 31 日【https://dagshub.com】。
R 中留一交叉验证法比较因变量变换
原文:https://towardsdatascience.com/comparing-dependent-variable-model-transformations-by-leave-one-out-cross-validation-in-r-b63945b73b2?source=collection_archive---------52-----------------------
通过转换因变量和利用交叉验证优化线性回归模型的预测能力。
在决定因变量变换以实现最佳预测能力时,一个关键问题是 R *方值(通常用于测量不同模型的预测拟合度)不再具有可比性。由于 R *方是因变量中方差的比例,该比例由自变量的变化来解释,通过对因变量进行变换,我们也变换了它们的方差结构。因此,我们不再能够通过比较它们的 R *方值来洞察不同模型的相对预测能力。
Box-Cox 幂变换
虽然可以使用 Box-Cox 幂变换来指示哪种变换将有助于我们的模型拟合数据,但这种方法不会帮助我们衡量变换后的模型在预测方面的表现,也不会指示在倒带变换时使用*均值或中值预测值是否会产生最佳预测。以下示例通过采用留一交叉验证来计算可比较的预测能力度量,突出了过于依赖 Box-Cox 变换本身的问题。
留一交叉验证
交叉验证可作为一种手段,用于比较不同的因变量转换。交叉验证的留一法使用样本数据集中的一个观察值作为验证数据,使用其余的观察值作为训练数据。每个模型用于通过拟合训练数据来预测验证数据点的值,然后通过从验证数据观测值中减去预测值来计算预测误差。
为了确保我们获得可比较的测量值,必须将转换模型产生的拟合值转换回“水*”形式,以获得与原始观察数据单位相同的预测值。使用不同的方法进行这种转换能够比较*均值和中位数预测值。重复该过程,直到来自原始样本的每个观察值都被用作验证数据点,然后通过对预测误差的绝对值*求和,我们获得所讨论的转换模型进行样本外预测的程度的度量。
一旦为每个变换(和适用的预测器类型)计算了交叉验证度量,则产生最低度量的模型被认为具有最大的预测能力。
*人们可能希望使用预测误差的*方和来计算比较。
工作示例
借助所附的 mazda.csv 数据集,我们希望开发一个模型,在给定车龄的情况下,预测汽车的价格。根据初步观察,确定将年龄*方项作为模型中的第二个变量将有助于减轻非线性问题。然后产生以下诊断图。
型号: 价格=α+β年龄+δ年龄**
# LOAD & ORGANISE DATA #####################################
original_data <- rio::import("mazda.csv")
data <- original_data
names(data) <- c("Year", "y", "x")
# Inclusion of Age^2 variable
x_sq <- data$x^2
data <- tibble::add_column(data, x_sq, .after = 100)
# MODEL DEVELOPMENT ########################################
reg1 <- glm(y ~ x + x_sq,
data = data)
fitted.1 <- stats::fitted(reg1)
resid.1 <- stats::resid(reg1)
stu.resid.1 <- MASS::studres(reg1)
leverage.1 <- sur::leverage(reg1)
norm_lev.1 <- (nrow(data)*leverage.1)/(length(coef(reg1)))
# Diagnostic Plots
par(mfrow = c(2, 2))
plot(fitted.1, data$y, main = "Actual vs Fitted", ylab = "y", xlab = "Fitted")
plot(fitted.1, stu.resid.1, main = "Studentised Residuals vs Fitted", ylab = "Student Residuals", xlab = "Fitted")
plot(norm_lev.1, stu.resid.1, main = "Studentised Residuals vs Normalised Leverage", ylab = "Student Residuals", xlab = "Normalised Leverage")
abline(v=2, col="blue")
abline(h=3, col="red")
abline(h=-3, col="red")
qqnorm(stu.resid.1, , main = "Normal quantile plot of Studentised Residuals",
xlab = "Inverse Normal", ylab = "Studentised Residuals",
plot.it = TRUE, datax = FALSE,)
qqline(stu.resid.1 , col="red")
par(mfrow=c(1, 1))
尽管包含此项有助于将诊断图线性化,但我们仍有两个问题,即较大拟合值的方差增加(异方差)和非正态残差。我们知道,这两个问题都可以通过转换因变量来解决,并执行 Box-Cox 幂转换来查看哪种类型的因变量转换可能是合适的。
Box-Cox 幂变换
上面的 Box-Cox 幂变换图表明,通过对数变换来变换我们的价格变量是合适的(因为 0 位于λ, λ 的 95%置信区间内)。然而,我们知道*方根变换也有助于减轻异方差,并获得更接*正态分布的残差。因此,我们决定使用留一交叉验证来测试价格的对数转换和*方根转换(以及作为控制的初始线性模型),以确定哪个模型可能产生最佳的样本外拟合。
# BOX-COX TRANSFORMATION ###################################
box_cox <- MASS::boxcox(reg1, optimise = T, lambda = seq(-1,1, by=.1), main = "Box-Cox Power Transformation")
lamda_bc <- box_cox$x[which.max(box_cox$y)]
roundlamda_bc <- plyr::round_any(lamda_bc, .5) # We see the Box-Cox transformation suggests a Log-transformation is most appropriate
# However lamda is close enough to 0.5 to also consider a square-root transformation.
使用附带的 R 脚本,我们为三个模型执行 LOO 交叉验证。为了确保我们的交叉验证方法的可比性,我们必须将预测值转换回它们的“水*”值(即 ln (价格)对价格和 sqrt (价格)对价格),然后将它们与用作验证数据的原始观察值进行比较。这里我们可以选择均值或中值预测值。对于没有进行变换的模型,均值和中值预测值将是相同的,但是对于对数和*方根模型,它们是不同的。因此,当我们将拟合值转换回“水*”预测值时,我们也可以通过交叉验证来测试这些,以查看哪个预测值通过使用以下公式获得了最低的交叉验证测量值。随附的 R 脚本在计算可比预测功效指标时,在相应的交叉验证循环中执行这些转换。
日志转换:
- *均预测值(对数)=预期值(拟合值)*预期值(1/2 *均方误差)
- 中位数预测值(对数)=预期值(拟合)
*方根变换:
- *均预测值(sqrt) =(拟合)+ MSE
- 中位数预测值(sqrt) =(拟合)
*拟合的是我们的预测值,MSE 是模型的均方误差。
然后,我们可以比较计算出的测量值,看哪个模型和预测值在交叉验证方面表现最好。从下表中,我们可以看到,实际上*方根转换模型在交叉验证方面表现最佳,中值预测值获得了最低的 LOOCV 度量。
# LEAVE-ONE-OUT CV #########################################
dep.cv.glm <- function(x, data, mean.pred = TRUE, trans = "no"){
if(trans == "no"){
devn.1 <- list()
for(i in 1:nrow(data)) {
reg1.cv <- glm(formula(x),
data = dplyr::slice(data,-i))
fitted.cv1 <- predict(reg1.cv, newdata = data)
devn.1[i] <- ((data$y[i])-(fitted.cv1[i]))
}
devn.1 <- as.numeric(devn.1)
devn.1 <- abs(devn.1)
cv.lin <- mean(devn.1)
cv.lin
}
else if((mean.pred == TRUE) & (trans == "log")){
devn.1 <- list()
for(i in 1:nrow(data)) {
reg1l.cv <- glm(formula(x),
data = dplyr::slice(data,-i))
logfitted.cv1l <- predict(reg1l.cv, newdata = data)
mse <- summary(reg1l.cv)$dispersion
fitted.cv1l <- exp(logfitted.cv1l)*exp(0.5*mse)
devn.1[i] <- ((data$y[i])-(fitted.cv1l[i]))
}
devn.1 <- as.numeric(devn.1)
devn.1 <- abs(devn.1)
cv.log.mean <- mean(devn.1)
cv.log.mean
}
else if((mean.pred == FALSE) & (trans == "log")){
devn.1 <- list()
for(i in 1:nrow(data)) {
reg1l.cv <- glm(formula(x),
data = dplyr::slice(data,-i))
logfitted.cv1l <- predict(reg1l.cv, newdata = data)
mse <- summary(reg1l.cv)$dispersion
fitted.cv1l <- exp(logfitted.cv1l)
devn.1[i] <- ((data$y[i])-(fitted.cv1l[i]))
}
devn.1 <- as.numeric(devn.1)
devn.1 <- abs(devn.1)
cv.log.mean <- mean(devn.1)
cv.log.mean
}
else if((mean.pred == TRUE) & (trans == "sqrt")){
devn.1 <- list()
for(i in 1:nrow(data)) {
reg1s.cv <- glm(sqrt(y) ~ x + x_sq,
data = dplyr::slice(data,-i))
sqrtfitted.cv1s <- predict(reg1s.cv, newdata = data)
mse <- summary(reg1s.cv)$dispersion
fitted.cv1s <- ((sqrtfitted.cv1s)^2)+mse
devn.1[i] <- ((data$y[i])-(fitted.cv1s[i]))
}
devn.1 <- as.numeric(devn.1)
devn.1 <- abs(devn.1)
cv.sqrt.mean <- mean(devn.1)
cv.sqrt.mean
}
else if((mean.pred == FALSE) & (trans == "sqrt")){
devn.1 <- list()
for(i in 1:nrow(data)) {
reg1s.cv <- glm(sqrt(y) ~ x + x_sq,
data = dplyr::slice(data,-i))
sqrtfitted.cv1s <- predict(reg1s.cv, newdata = data)
mse <- summary(reg1s.cv)$dispersion
fitted.cv1s <- ((sqrtfitted.cv1s)^2)
devn.1[i] <- ((data$y[i])-(fitted.cv1s[i]))
}
devn.1 <- as.numeric(devn.1)
devn.1 <- abs(devn.1)
cv.sqrt.median <- mean(devn.1)
cv.sqrt.median
}
}# RESULTS ##################################################
MSE.LOO.cv <- list()
MSE.LOO.cv[1] <- dep.cv.glm(y ~ x + x_sq, data, mean.pred = TRUE, trans = "no")
MSE.LOO.cv[2] <- dep.cv.glm(log(y) ~ x + x_sq, data, mean.pred = FALSE, trans = "log")
MSE.LOO.cv[3] <- dep.cv.glm(log(y) ~ x + x_sq, data, mean.pred = TRUE, trans = "log")
MSE.LOO.cv[4] <- dep.cv.glm(sqrt(y) ~ x + x_sq, data, mean.pred = FALSE, trans = "sqrt")
MSE.LOO.cv[5] <- dep.cv.glm(sqrt(y) ~ x + x_sq, data, mean.pred = TRUE, trans = "sqrt")
names(MSE.LOO.cv) <- c("Linear", "Log-Median", "Log-Mean", "Sqrt-Median", "Sqrt-Mean")
MSE.LOO.cv
最后看一下首选模型的诊断图,我们可以看到*方根变换大大减轻了我们对异方差和非正态残差的担忧。因此,我们可以使用*方根转换模型和中值预测值来相对轻松地生成预测和预测区间。
型号: sqrt(价格)=α+β年龄+δ年龄**
# PREFERRED MODEL ##################################################
reg1 <- glm(sqrt(y) ~ x + x_sq,
data = data)
fitted.1 <- stats::fitted(reg1)
resid.1 <- stats::resid(reg1)
stu.resid.1 <- MASS::studres(reg1)
leverage.1 <- sur::leverage(reg1)
norm_lev.1 <- (nrow(data)*leverage.1)/(length(coef(reg1)))
# Diagnostic Plots (Preferred Model)
par(mfrow = c(2, 2))
plot(fitted.1, sqrt(data$y), main = "Actual vs Fitted", ylab = "sqrt(y)", xlab = "Fitted")
plot(fitted.1, stu.resid.1, main = "Studentised Residuals vs Fitted", ylab = "Student Residuals", xlab = "Fitted")
plot(norm_lev.1, stu.resid.1, main = "Studentised Residuals vs Normalised Leverage", ylab = "Student Residuals", xlab = "Normalised Leverage")
abline(v=2, col="blue")
abline(h=3, col="red")
abline(h=-3, col="red")
qqnorm(stu.resid.1, , main = "Normal quantile plot of Studentised Residuals",
xlab = "Inverse Normal", ylab = "Studentised Residuals",
plot.it = TRUE, datax = FALSE,)
qqline(stu.resid.1 , col="red")
par(mfrow=c(1, 1))
结论
本指南概述了在比较因变量的不同变换的模型时,比较 R *方值无效的原因。该指南建议使用 Box-Cox 幂变换可以帮助确定因变量的合适变换,但是,Box-Cox 变换本身并不能确保我们的模型在进行样本外预测时表现最佳。本指南和随附的 R 脚本将使用户能够执行留一法交叉验证,以测试和比较因变量不同转换的模型的预测能力,并指出*均值或中位数预测值是否最合适。
感谢一路阅读到文章结尾!很想听听大家对以上的评论。欢迎随时留言,或者通过LinkedIn联系我。
附件 A —马自达. csv 数据文件
[## 马自达. csv
用于示例分析的数据文件](https://drive.google.com/file/d/1REMXRT8wvyR3pPgpbIjdSRr2GtwjGgsh/view?usp=drive_open&usp=embed_facebook)
附件 B — R 包装清单
# Packages #############################pacman::p_load(pacman, dplyr, MASS, plyr, rio, tidyverse)
比较 Grakn 和语义 Web 技术—第 1/3 部分
原文:https://towardsdatascience.com/comparing-grakn-to-semantic-web-technologies-part-1-3-3558c447214a?source=collection_archive---------31-----------------------
探索共同的概念和差异
观看本次网络研讨会,了解更多信息
本文探讨了 Grakn 与语义 Web 标准的比较,特别关注 RDF、XML、RDFS、OWL、SPARQL 和 SHACL。这两套技术之间有一些关键的相似之处——主要是因为它们都植根于符号人工智能、知识表示和自动推理领域。这些相似之处包括:
- 两者都允许开发人员表示和查询复杂和异构的数据集。
- 两者都提供了向复杂数据集添加语义的能力。
- 两者都使用户能够对大量数据进行自动演绎推理。
然而,这些技术之间存在核心差异,因为它们是为不同类型的应用程序设计的。具体来说,语义网是为 Web 而构建的,不完整的数据来自许多来源,在这里任何人都可以对信息源之间的定义和映射做出贡献。相比之下,Grakn 不是为了在网络上共享数据而构建的,而是作为封闭世界组织的交易数据库。正因为如此,比较这两种技术有时感觉就像比较苹果和橘子。
这些差异可以总结如下:
- 与语义网相比, Grakn 降低了复杂性,同时保持了高度的表达能力。有了 Grakn,我们不必学习不同的语义 Web 标准,每个标准都有很高的复杂性。这降低了进入的门槛。
- Grakn 为处理复杂数据提供了比语义网标准更高层次的抽象。使用 RDF,我们用三元组来建模世界,这是一个比 Grakn 的实体-关系概念级模式更低级的数据模型。对高阶关系和复杂数据的建模和查询是 Grakn 的原生功能。
- 语义网标准是为网络而建立的,Grakn 适用于封闭世界系统。前者旨在处理开放网络上不完整数据的链接数据,而 Grakn 的工作方式类似于封闭环境中的传统数据库管理系统。
该文档显示,这两种技术在如何提供知识表示和自动推理工具方面有很大的重叠,并且在高层次上涵盖了最重要的概念,而没有涉及太多的细节。目标是帮助具有 RDF/OWL 背景的用户熟悉 Grakn。
语义网栈
语义网开始于 20 世纪 90 年代末,用一层形式语义来扩展 Web 的现有架构。它由许多标准组成,这些标准共同构成了语义 Web 栈。本文涉及的技术包括:XML、RDF、RDFS、OWL、SPARQL 和 SHACL。
- RDF 是一种在 web 和 XML 上交换数据的标准。
- RDFS 提供了一个模式和一些基本的本体论结构。
- OWL 用描述逻辑的构造进一步增强了这一点。SPARQL 是查询和插入 RDF 数据的语言。
- SHACL 提供了一组验证约束来逻辑验证数据。
除了这些标准,还有不同的库和实现可供用户选择,以便在实践中真正使用这些标准。例如,有几个库允许用户使用 RDF 或 SHACL(仅对于 Java,您可以在这两个库中选择: TopBraid 和 Apache Jena ),但是它们都与标准略有不同,并且有各自的细微差别。
然而,尽管有很多可用的教育材料,语义网还没有在学术界之外被广泛采用。由于用户需要学习大量的技术,再加上它们固有的复杂性,用户在开始学习之前要花很长时间在语义网上自学。进入的门槛很高。这让大部分开发者很难入门。
相反,Grakn 只为用户提供了一种可以替代语义网中许多标准的技术(在本文中,我们将介绍 RDF、RDFS、OWL、SPARQL 和 SHACL)。这意味着,例如,构建应用程序的用户不需要学习使用什么类型的推理机、什么验证系统或什么查询语言。有了 Graql,所有这些都发生在同一技术中,用户只需要学习一次。
Grakn 工作在更高的层次,更容易学习,降低了进入门槛,使数百万开发者能够接触到以前无法接触到的语义技术。在 Grakn 中,易用性是首要原则。
我们用 Grakn 和 Graql 代替 RDF、SPARQL、RDFS、OWL 和 SHACL。
简而言之,Grakn 是一个知识图形式的分布式逻辑数据库,它实现了概念级的模式。该知识表示系统然后由自动推理引擎解释,该自动推理引擎在查询运行时执行自动演绎推理。查询、模式和推理都是通过 Grakn 的查询语言 Graql 进行的。
Grakn 的概念级模式的正式基础由超图提供,它与关系数据库的关系模型、语义网中的有向图以及图形数据库的属性图起着相同的作用。超图概括了边是什么的一般概念。在 RDF 和属性图中,边只是一对顶点。相反,超图是顶点的集合,它可以被进一步结构化。有向图模型的优势包括:
- 以关系方式将相关信息分组的自然机制,这在很大程度上迷失在有向图中。
- 统一处理所有 n 元关系,与有向图相反,在有向图中,与两个以上角色的关系需要对建模方法(n 元)进行彻底的改变。
- 一种表达高阶信息的自然方式(关系之间的关系,信息的嵌套),在有向图中需要专门的建模技术(即具体化)。
无线电测向
RDF 三元组
RDF 是一个对数据建模并在网络上分发数据的系统。它是由带标签的有向多重图构成的,有顶点和带标签的边。这些由 URIs(事物)、文字(数据值)和空白节点(虚拟节点)组成。
RDF 以主-谓-宾的形式存储三元组,即一个接一个声明的原子语句。下面是一个人“Peter Parker”的例子,他知道另一个人“Aunt May”的 XML 符号。
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<foaf:Person>
<foaf:name>Peter Parker</foaf:name>
<foaf:knows>
<foaf:Person>
<foaf:name>Aunt May</foaf:name>
</foaf:Person>
</foaf:knows>
</foaf:Person>
</rdf:RDF>
正如我们所看到的,RDF 放弃了它在灵活性上获得的紧凑性。这意味着它可以是富于表现力的,同时又是极其精细的。数据点之间的每个关系都是显式声明的——关系要么存在,要么不存在。与传统的关系数据库相比,这使得合并不同来源的数据变得更加容易。上面的三元组构成了这个图:
RDF 三元组的图形表示。
Grakn 不支持三元组。相反,它公开了一个概念级的实体关系模型。因此,Grakn 不是以主-谓-对象的形式建模,而是在更高的层次上用实体、关系、角色和属性来表示我们的数据。对于上面的例子,我们会说有两个person
实体,它们具有name
属性,并且通过knows
关系相关联。
$p isa person, has name "Peter Parker";
$p2 isa person, has name "Aunt May";
($p, $p2) isa knows;
具有两个实体(“Peter Parker”和“May 阿姨”)和一个关系(“knows”)的 Grakn 模型。
超关系
如前所述,Grakn 的数据模型是基于超图的。在 RDF 中,边只是一对顶点,而超边是一组顶点。Grakn 的数据模型的正式基础基于三个前提:
- 超图由一组非空的顶点和一组超边组成
- 超边是顶点的有限集合(通过它们在超边中扮演的特定角色来区分)
- 超边本身也是一个顶点,并且可以由其他超边连接
注意:虽然 Grakn 利用了超边缘,但是 Grakn 实际上并没有暴露边缘或者超边缘。相反,它与关系或超关系一起工作。下图描述了这是如何工作的。该示例显示了两个超级关系:
- 婚姻,描述了分别扮演丈夫和妻子的鲍勃和爱丽丝之间的二元婚姻关系
- 离婚申请描述了一个三元离婚申请关系,涉及三个角色的角色扮演者认证婚姻,申请人和答辩人
Grakn 中的超关系示例。
超关系可以简单地看作任意基数的角色和角色扮演者对的集合。由于超关系不能在带标签的有向图中自然地表示,RDF 中的上述例子可能看起来像这样:
RDF 中超关系的表示。
如图所示,Grakn 中的每个超关系都可以映射到 RDF 模型中相应的有向图。例如,在这个模型中,实体和关系类型也被显式编码为 RDF 风格的 RDF 资源。因此,超关系可以在 RDF 三元组存储上实现。因此,就建模而言,超关系提供了一种非常自然和直接的数据表示形式,允许使用实体关系图在概念层次上建模。
然而,不同之处在于,在 Grakn 中,超关系成为一流的建模构造。这一点很重要,因为在现实生活中,当完整的概念模型在开始时不能完全预见时,实际的建模结果可能会产生许多不必要的复杂性。此外,与二进制有向边相比,本地模拟超关系导致查询规划和查询优化的改进,因为在相同结构“容器”中分组在一起的数据也经常由用户和应用程序在类似分组中检索。并且通过在查询之前确认它们的结构,可以更好地计划和执行检索过程。
名称空间
由于 Web 的公共性质,RDF 使用名称空间来解释和识别不同的本体,通常在文档的开头给出名称空间,以使其更具可读性。RDF 中的每个资源都有一个唯一的标识符。标签告诉它这是一个 RDF 文档:
rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#
由于 Grakn 不在网络上运行,因此不需要 URIs。一个相关的概念是keyspaces
,它们是 Grakn 实例中逻辑上独立的数据库。与 RDF namespace
不同的是,它们不能互相交谈。
连载
用文本形式表达 RDF 有很多种方法。一种常见的方法是用 XML 格式表示三元组(W3C 推荐):
<http://example.org/#spiderman>
<http://www.perceive.net/schemas/relationship/enemyOf>
<http://example.org/#green-goblin> .
<http://example.org/#green-goblin>
<http://www.perceive.net/schemas/relationship/enemyOf>
<http://example.org/#spiderman> .
然而,由于 XML 可能变得难以阅读, Turtle 也可以用作更紧凑的序列化(其他流行的序列化格式包括 JSON-LD 和 N-triples)。有了海龟,我们用 qnames 代替本地 URIs。下面的例子代表了来自foaf
名称空间的两个Person
:“绿魔”和“蜘蛛侠”。它们通过来自rel
名称空间的一个叫做enemyOf
的关系连接在一起。
@base <http://example.org/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rel: <http://www.perceive.net/schemas/relationship/> .<#green-goblin>
rel:enemyOf <#spiderman> ;
a foaf:Person ;
foaf:name "Green Goblin" .<#spiderman>
rel:enemyOf <#green-goblin> ;
a foaf:Person ;
foaf:name "Spiderman" .
在 Grakn 中,我们不需要在多个序列化之间进行选择,而是使用 Graql。这个例子可以这样表示:
$g isa person, has name "Green Goblin";
$s isa person, has name "Spiderman";
(enemy: $g, enemy: $s) isa enemyship;
这里,我们有两个person
实体,属性为name
“绿魔”和“蜘蛛侠”。它们通过类型enemyship
的关系连接在一起,两者都扮演enemy
的角色。
高阶关系
给定三元组的主语/谓语/宾语形式,RDF 中的建模在表示更高阶的关系时会变得有限。举个例子,让我们看看这个三元组:
lit:HarryPotter bio:author lit:JKRowling .
这表明 JK 罗琳写了《哈利·波特》。然而,我们可能想通过说 JK 罗琳在 2000 年写了《哈利波特》来修饰这个说法。在 RDF 中,要做到这一点,我们需要经历一个称为具体化的过程,为每个语句创建一个三元组,其中三元组的主题是同一个节点:
bio:n1 bio:author lit:JKRowling .
bio:n1 bio:title "Harry Potter" .
bio:n1 bio:publicationDate 2000 .
在 Grakn 中,考虑到它的概念级模式,具体化的需要并不存在,我们可以自然地表示更高阶的关系。 JK 罗琳写的《哈利·波特》会这样表述:
$a isa person, has name "JK Rowling";
$b isa book, has name "Harry Potter";
(author: $a, publication: $b) isa authorship;
然后,如果我们想限定这一点,说 JK 罗琳在 2000 年写了《哈利·波特》,我们可以简单地给关系添加一个属性:
$a isa person, has name "JK Rowling";
$b isa book, has name "Harry Potter";
(author: $a, publication: $b) isa authorship, has date 2000;
空白节点
有时在 RDF 中,我们不想给出 URI 或字面量。在这种情况下,我们处理的是空白节点,即没有 Web 标识的匿名资源。一个例子是这样一种说法:哈利·波特的灵感来自于一个住在英国的人
lit: HarryPotter bio:name lit:"Harry Potter" .
lit:HarryPotter lit:hasInspiration [a :Man;
bio:livesIn geo:England] .
由于 Grakn 并不存在于 web 上,所以空白节点的概念并不能直接转化为 Grakn。虽然在 RDF 中我们使用空白节点来表示没有 URI 的事物的存在,但是在 Grakn 中有多种方法可以做到这一点。如果像上面的例子一样,我们使用一个空白节点来表示我们除了知道这个人住在英国之外,对他的其他情况一无所知,我们就这样表示:
$b isa book, has name "Harry Potter";
$m isa man; ($b, $m) isa inspiration;
$l isa location, has name "England";
($m, $l) isa lives-in;
我们可以看到的是,变量$m
被分配给实体类型man
,除了他通过一个lives-in
关系类型连接到实体类型location
和name
“英国】之外,没有给出进一步的信息。
在第 2 部分( 链接此处 ),我们看看 Grakn 是如何比较 SPARQL 和 RDFS 的。要了解更多信息,请务必通过 此链接 参加我们即将举办的网络研讨会。
比较 Grakn 和语义 Web 技术—第 2/3 部分
原文:https://towardsdatascience.com/comparing-grakn-to-semantic-web-technologies-part-2-3-4602b56969fc?source=collection_archive---------42-----------------------
探索共同的概念和差异
这是比较语义网技术和 Grakn 的第二部分。在 第一部分中, 我们看了 RDF 与 Grakn 的比较。在这一部分中,我们将特别关注 SPARQL 和 RDFS。如果你还没看完第 1 部分,跟着 这个链接 。
要了解更多信息,请务必通过 此链接 参加我们即将举办的网络研讨会。
SPARQL
什么是 SPARQL
SPARQL 是一种 W3C 标准化语言,用于从数据库中查询可以映射到 RDF 的信息。与 SQL 类似,SPARQL 允许插入和查询数据。与 SQL 不同,查询不仅限于一个数据库,还可以跨多个 HTTP 端点进行联合。
作为 Grakn 的查询语言,Graql 是等价的查询语言。和 SPARQL 一样,Graql 允许插入和查询数据。然而,鉴于 Graql 不是作为开放的 Web 语言构建的,它不允许跨多个端点进行本地查询(这可以通过 Grakn 的一个客户端驱动程序来实现)。因此,Graql 更类似于 SQL 和其他传统的数据库管理系统。
使用 SPARQL 插入数据
为了将数据添加到默认的图形存储中,这个代码片段描述了如何使用 SPARQL 插入两个 RDF 三元组:
PREFIX dc: <http://purl.org/dc/elements/1.1/>
INSERT DATA
{
<http://example/book1> dc:title "A new book" ;
dc:creator "A.N.Other" .
}
在 Graql 中,我们以insert
语句开始,声明要插入数据。变量$b
被分配给实体类型book
,它有一个值为“一本新书”的title
和一个值为“A.N.Other”的creator
。
insert
$b isa book, has title "A new book", has creator "A.N.Other";
使用 SPARQL 查询
在 SPARQL 中,我们首先声明我们想要从中检索数据的端点,我们可以将这些端点附加到某个前缀上。在陈述我们想要返回的数据之前,实际的查询从SELECT
开始。然后,在WHERE
子句中,我们说明了 SPARQL 将找到匹配数据的图形模式。在这个查询中,我们使用名称空间foaf
和vCard
查找“Adam Smith”认识的所有人:
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX vCard: <http://www.w3.org/2001/vcard-rdf/3.0#>SELECT ?whom
WHERE {
?person rdf:type foaf:Person .
?person vcard:family-name "Smith" .
?person vcard:given-name "Adam" .
?person foaf:knows ?whom .
}
在 Graql 中,我们以match
语句开始,声明我们想要检索数据。我们匹配类型为person
的实体,它有一个family-name
“史密斯”和一个given-name
“亚当”。然后,我们通过一个knows
关系类型将它连接到$p2
。因为我们想知道“亚当·斯密”认识谁,所以我们希望返回到$p2
,这在get
语句中声明:
match $p isa person, has family-name "Smith", has given-name "Adam";
($p, $p2) isa knows;
get $p2;
让我们来看一个不同的查询:给我詹姆斯·迪恩演过的导演和电影,其中也有一个女人演过角色,并且那个女人在约翰·福特导演的电影中演过角色。下面是 SPARQL 代码和这个遍历类型查询的可视化表示。
PREFIX movie: <http://example.com/moviedb/0.1/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?director ?movie
WHERE{
?actor rdf:type foaf:Man ;
movie:name "James Dean" ;
movie:playedIn ?movie .
?actress movie:playedIn ?movie ;
rdf:type foaf:Woman ;
movie:playedIn ?anotherMovie .
?JohnFord rdf:type foaf:Man ;
movie:name "John Ford" .
?anotherMovie movie:directedBy ?JohnFord .
}
Sparql 遍历查询的可视化表示。
在 Grakn,我们可以这样问同样的问题:
match
$p isa man, has name "James Dean";
$w isa woman;
(actor: $p, actress: $w, casted-movie: $m) isa casting;
(actress: $w, casted-movie: $m2) isa casting;
$d isa man, has name "John Ford";
($m2, $d) isa directorship; get $d, $m;
这里,我们将具有属性name
和值“James Dean”的实体类型man
分配给变量$p
。然后我们说$w
是实体类型woman
。这两个与movie
以称为casting
的三向关系连接。woman
也在另一个casting
关系中起作用,其中movie
实体通过directorship
关系连接到与此movie
相关的“John Ford”。
在上面的例子中,Grakn 中的超级关系casting
表示 SPARQL 中的两个playedIn
属性。然而,在 SPARQL 中我们只能有两条边将woman
和“詹姆斯·迪恩”与movie
连接起来,而不能在它们之间。这显示了 Grakn 中的建模与 RDF 中的建模有多么根本的不同,因为 RDF 具有超图建模的能力。Grakn 允许在一个关系中自然地表示 N 个角色扮演者,而不必具体化模型。
示意性地,这是上面查询的可视化表示方式(注意三元关系casting
):
Grakn 中查询的可视化表示。
否认
在 SPARQL 中,我们还可以使用关键字NOT EXISTS
在查询中指定某些数据不存在。这将找到一个只有在子图不匹配时才匹配的图模式。在下面的例子中,我们寻找曾出演电影《巨人》但尚未去世的演员:
PREFIX movie: <http://example.com/moviedb/0.1/>SELECT ?actor
WHERE {
?actor movie:playedIn movie:Giant .
NOT EXISTS {?actor movie:diedOn ?deathdate .
}
使用封闭世界假设,Grakn 支持否定。这是通过使用关键字not
后跟要求反的模式来完成的。上面的例子表示如下:
match
$m isa movie, has name "Giant"; ($a, $m) isa played-in;
not {$a has death-date $dd;}; get $a;
在这里,我们寻找一个名为“Giant”的实体类型movie
,它通过类型played-in
的关系连接到$a
和actor
。在not
子查询中,我们指定$a
不能有带有任何值的death-date
类型的属性。我们接着get
演员$a
。
RDF 模式
由于 RDF 只是一种数据交换模型,它本身是“无模式的”。这就是为什么引入 RDF Schema (RDFS)来用基本的本体论语义扩展 RDF。例如,这些允许 RDF 数据上的简单类型层次。在 Grakn 中,Graql 被用作它的模式语言。
RDFS 班级
RDFS 扩展了 RDF 词汇表,允许描述类和属性的分类法。RDFS 类将 RDFS 资源声明为其他资源的类。我们可以用rdfs:Class
来简化它。使用 XML,创建一个带有子类horse
的类animal
,如下所示:
<?xml version="1.0"?><rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xml:base="http://www.animals.fake/animals#"><rdfs:Class rdf:ID="animal" />
<rdfs:Class rdf:ID="horse">
<rdfs:subClassOf rdf:resource="#animal"/>
</rdfs:Class>
</rdf:RDF>
要在 Grakn 中做同样的事情,我们应该这样写:
define
animal sub entity;
horse sub animal;
RDFS 还允许Properties
的子类型:
<?xml version="1.0"?><rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xml:base="http://www.animals.fake/animals#"><rdfs:Class rdf:ID="mammal" /><rdfs:Class rdf:ID="human">
<rdfs:subClassOf rdf:resource="#mammal"/>
</rdfs:Class><rdfs:Property rdf:ID="employment" /><rdfs:Property rdf:ID="part-time-employment">
<rdfs:subPropertyOf rdf:resource="#employment"/>
</rdfs:Property></rdf:RDF>
在 Grakn 中是这样的:
mammal sub entity;
human sub mammal;
employment sub relation;
part-time-employment sub employment;
如示例所示,RDFS 主要描述了对象类型的构造(Classes
)、相互继承(subClasses
)、描述对象的属性(Properties
)以及相互继承(subProperty
)。这种子类型行为可以通过 Graql 的sub
关键字获得,该关键字可用于创建 Grakn 中任何thing
( entities
、relations
和attributes
)的类型层次结构。
然而,在 Grakn 中的class
到entity
或者在 Grakn 中的property
到relation
之间创建一对一的映射,尽管它们看起来很相似,但不应该总是这样做。这是因为 RDF 中的模型是使用较低级别的数据模型构建的,以三元组工作,而 Grakn 能够在较高级别建模。
多重遗传
Grakn 和语义网之间一个重要的建模差异是关于多重继承。在 RDFS,一个类可以有许多命名的或逻辑推断的超类。让我们举这个例子:
company rdf:type rdfs:Class
government rdf:type rdfs:Classemployer rdf:type rdfs:Class
employer rdfs:subClassOf company
employer rdfs:subClassOf government
这将一个employer
建模为类company
和government
。然而,尽管这看起来可能是正确的,问题是多重继承,作为一个建模概念,经常没有以正确的方式使用。多重继承应该对事物进行分组,而不是对“类型”进行子类化,其中每个类型都是其他事物的定义。换句话说,我们不想表示数据的实例。这是一个常见的错误。
Grakn 支持单一类型继承,而不是多重继承,在这种情况下,我们应该分配role
而不是多重类。一个role
在一个relation
的上下文中定义了一个thing
的行为和方面,我们可以将多个role
分配给一个thing
(注意,当类型继承另一个类型时,角色被继承)。
比如一个government
可以雇佣一个person
,一个company
可以雇佣一个person
。有人可能会建议创建一个继承了可以使用person
的government
和company
的类,并以子类化这两者的employer
类结束(如上例所示)。
然而,这是对继承的滥用。在这种情况下,我们应该创建一个角色employer
,它与一个employment
关系相关联,并将一个company
或government
如何参与到该关系中联系起来(通过扮演employer
的角色)。
company sub entity,
plays employer;government sub entity,
plays employer;employment sub relation,
relates employer;
rdfs:域和 rdfs:范围
rdf:property
的两个常用实例包括domain
和range
。这些用于分别声明属性的成员或值是一个或多个类的实例。下面是一个rdfs:domain
的例子:
:publishedOn rdfs:domain :PublishedBook
这里,rdfs:domain
将类Person
分配给hasBrother
属性的主题。
这是一个rdfs:range
的例子:
:hasBrother rdfs:range :Male
这里,rdfs:range
将类Male
分配给hasBrother
属性的对象。
在 Grakn 中,没有直接实现range
和domain
。从它们中得出的基本推断要么已经通过使用role
在 Grakn 数据模型中被本地表示,要么我们可以创建rule
来表示我们想要推断的逻辑。
但是,请记住,在 Grakn 中使用规则可以提供更多的表达能力,允许我们表示我们想要进行的推理类型。简而言之,将range
和domain
翻译成 Grakn 应该根据具体情况进行。
在上面的例子中,rdfs:domain
可以翻译成 Grakn,即当一个实体有一个属性类型published-date
时,它在一个publishing
关系类型中扮演published-book
的角色。这体现在 Grakn 规则中:
when {
$b has published-date $pd;
}, then {
(published-book: $b) is publishing;
};
可以使用以下 Grakn 规则创建rdfs:range
的示例,该规则添加值为“男性”的属性类型gender
,前提是在任何siblingship
关系中,a person
扮演角色brother
,其中其他兄弟的数量为 n
when {
$r (brother: $p) isa siblingship;
}, then {
$p has gender "male";
};
我们再来看另一个例子。在海事环境中,如果我们有一艘DepartingVessel
级的船只,它具有指定的属性nextDeparture
,我们可以声明:
ship:Vessel rdf:type rdfs:Class .
ship:DepartingVessel rdf:type rdfs:Class .
ship:nextDeparture rdf:type rdf:Property .
ship:QEII a ship:Vessel .
ship:QEII ship:nextDeparture "Mar 4, 2010" .
通过下面的rdfs:Domain
,任何指定了nextDeparture
的船只将被推断为DepartingVessel
类的成员。在这个例子中,这意味着 QEII 被分配了DepartingVessel
类。
ship:nextDeparture rdfs:domain ship:DepartingVessel .
为了在 Grakn 中做同样的事情,我们可以编写一个规则,找到所有具有属性next-departure
的实体,并将它们分配给一个扮演departing-vessel
角色的关系departure
。
when {
$s has next-departure $nd;
}, then {
(departing-vessel: $s) isa departure;
};
然后,如果该数据被摄取:
$s isa vessel, has name "QEII", has next-departure "Mar 4, 2010";
Grakn 推断 QEII 号船在departure
关系中扮演departing-vessel
的角色,相当于本案例中的nextDeparture
级。
在 web 环境中使用rdfs:domain
和rdfs:range
非常有用,在 web 环境中,联邦数据经常会被发现是不完整的。由于 Grakn 不存在于 web 上,所以对这些概念的需求减少了。此外,这些推断数据的大部分已经在 Grakn 的概念模型中进行了本地表示。这很大程度上是由于它的高层模型和规则的使用。因此,在 Grakn 中将rdfs:range
和rdfs:domain
直接映射到一个概念通常是幼稚的,会导致冗余。相反,将这些概念转换成 Grakn 应该使用规则和角色根据具体情况来完成。
在最后的第 3 部分( 链接此处 ),我们看看 Grakn 是如何比较 OWL 和 SHACL 的。要了解更多信息,请务必通过 此链接 参加我们即将举办的网络研讨会。
比较 Grakn 和语义 Web 技术—第 3/3 部分
原文:https://towardsdatascience.com/comparing-grakn-to-semantic-web-technologies-part-3-3-cb2fb233fbd5?source=collection_archive---------40-----------------------
探索共同的概念和差异
这是比较语义网技术和 Grakn 的第三部分。在前两部分中,我们研究了 RDF、RDFS 和 SPARQL 与 Grakn 的比较。在这一部分,我们特别关注 OWL 和 SHACL。如果你还没看完第 1 部分,跟着 这个链接 ,或者第 2 部分上 这个链接 。
要了解更多信息,请务必通过 此链接 参加我们即将举办的网络研讨会。
猫头鹰
猫头鹰和 Grakn
OWL 是一种基于描述逻辑(DL)的本体语言,它在 RDFS 的基础上增加了本体结构来表达条件和推导新的事实。为了有意义地使用它们,OWL 提供了不同的风格:OWL QL、OWL RL、OWL DL,用户需要决定哪一个最适合他们的用例。
另一方面,Grakn 自带内置的本地推理功能。这是一个重要的区别,因为 OWL 假设用户对逻辑领域有很好的理解,而使用 Grakn 不需要用户对这个领域有广泛的研究。
结果是 OWL 在表达性和复杂性之间努力保持令人满意的*衡。仅仅为了推理两个简单的约束:每个父母都有一个孩子和每个孩子都是一个人需要使用成熟的 OWL DL 推理器。此外,OWL 不适合复杂关系的推理。它的正式基础基于树模型属性,这使它更适合树形数据,但对于更复杂的数据伸缩性较差。
OWL 采用开放世界假设,而不是 Grakn 的封闭世界假设。这意味着在 OWL 有约束的例子中:每个父母必须至少有一个孩子,如果我们有一个人没有孩子,这仍然符合约束,因为我们可能还不知道 John 的孩子。然而,根据 Grakn 的封闭世界假设,如果没有实际提到约翰的孩子,这意味着他真的没有任何孩子,也不是父母。
开放世界的假设非常适合于开放式网络,它包含来自多个来源的不完全信息,这就是为什么 OWL 提供了许多概念来管理和处理这种不完全性。然而,由于这种开放世界的假设,OWL 很难验证数据的一致性。这就是关系数据库维护模式约束以保证数据质量的原因。Grakn 结合了两种类型的推理:本体类型的开放世界推理和模式类型的封闭世界约束检查。
所有的东西放在一起,OWL 对于非逻辑学家来说有着非常高的入门门槛。由于它基于描述逻辑,开发人员避免使用 OWL,因为理解这种语言及其预期行为非常重要。正因为如此,Grakn 的知识表示形式仍然是轻量级的,为比 OWL 更多的受众提供了语义能力。换句话说,Grakn 比 OWL 更容易使用。
在这里,我们看看 OWL 中的一些常见公理,并将它们与 Grakn 进行比较。这不是一个详尽的列表,提供它是为了帮助用户理解如何考虑迁移到 Grakn。
限制
OWL 的一个关键功能是定义限制类(owl:Restriction
)。这些未命名的类是基于该类的某些属性值的限制而定义的。OWL 允许对某个类的某些成员需要具有某些属性的情况进行建模。限制允许区分适用于一个类的所有成员的东西。通过给出一个描述来定义一个限制,该描述限制了关于该类成员的事情的种类。
一个例子是限制AllValuesFrom
,它声明在特定类的上下文中,属性的范围应该总是特定的类。例如,如果AllValuesFrom
已经被申请为Person
类,并且这被应用到具有Person
的hasParent
的范围,那么它们只能有Person
父类,而Animal
不能有Person
父类。下面的例子也表明只有Animal
s 可以有Animal
-parents。
:Person
a owl:Class ;
rdfs:subClassOf
[ a owl:Restriction ;
owl:onProperty :hasParent ;
owl:allValuesFrom :Person
] .:Animal
a owl:Class ;
rdfs:subClassOf
[ a owl:Restriction ;
owl:onProperty :hasParent ;
owl:allValuesFrom :Animal
] .
为了在 Grakn 中实现这一点,在模式定义中表示了限制。创建person
和animal
实体类型和两个带约束的关系:person-parentship
和animal-parenthship
。前者仅与person
相关,后者与animal
相关。
person sub entity,
plays person-child,
plays person-parent;animal sub entity,
plays animal-child,
plays animal-parent;parentship sub relation, abstract;person-parentship sub parentship,
relates person-child,
relates person-parent;animal-parentship sub parentship;
relates animal-child,
relates animal-parent;
传递属性
OWL 中一个常见的推论是传递性。这说明关系 R 被说成是传递的,如果 A 用 R(a,B)连接到 B,B 用 R(b,C)连接到 C,这暗示 A 用 R(a,C)连接到 C。构造owl:TransitiveProperty
用于此目的。下面的例子可以推断国王十字车站位于欧洲。
:isLocated rdf:type owl:TransitiveProperty.:KingsCross isLocated :London.
:London isLocated :UK.
:UK isLocated :Europe.
在 Grakn 中,将创建一个规则来表示传递性:
when {
$r1 (located: $a, locating: $b);
$r2 (located: $b, locating: $c);
}, then {
(located: $a, locating: $c);
};
一旦定义了规则,如果加载了此数据:
insert
$a isa city, has name "London";
$b isa country, has name "Uk";
$c isa continent, has name "Europe";
(located: $a, locating: $b); (located: $b, locating: $c);
如果我们接着查询:
match
$b isa continent, has name "Europe";
(located: $a, locating: $b); get $a;
这不仅会产生与continent
“欧洲”有直接关系的country
“英国”,而且还会产生与continent
“欧洲”有过渡关系的city
“伦敦”。
等效属性
OWL 还提供了一个构造来模拟等价的属性。这表明两个属性具有相同的属性扩展。一个例子:
:borrows owl:equivalentProperty :checkedOut .
这可以用 Grakn 中的规则来表示,其中可以推断出如下新关系checked-out
:
when {
(borrower: $x, borrowing: $y) isa borrowing;
},
then {
(checking-out: $x, checked-out: $y) isa checked-out;
};
对称属性
对称关系表示一种具有自身反向属性的关系。例如,如果 Susan 通过一个hasSibling
属性与 Bob 相关,那么可以推断 Bob 也通过一个hasSibling
属性与 Susan 相关。
:hasSibling rdf:type owl:SymmetricProperty .
在 Grakn 中,对称性可以通过简单地在一个或多个关系中重复角色来建模:
(sibling: $p, sibling: $p2) isa siblingship;
换句话说,在 OWL 中需要显式构造的东西是 Grakn 模型固有的,也就是说,对称性规则不需要显式。然而,这也是 OWL 和 Grakn 比较困难的地方,因为两者服务于不同的用例。特别是,鉴于 Grakn 的封闭世界假设,OWL 中的许多问题根本不存在。
功能属性
这就是我们如何建模更多 OWL 结构的方法。owl:FunctionalProperty
表示如下:
hasFather rdf:type owl:FunctionalProperty .
在 Grakn 中,可以使用一个规则:
when {
(father: $x, child: $ y) isa fatherhood;
(father: $d, child: $ y) isa fatherhood;
},
then {
(father: $x, father: $y) isa same-father;
};
的交叉
如果我们在这个例子中使用owl:intersectionOf
:
:Mother rdfs:subClassOf [ owl:interesctionOf ( :Female :Parent ) ]
如果资源既是:Female
又是Parent
,那么这将分配类:Mother
。在 Grakn 中,我们可以选择使用包含连接条件的规则来表示这一点:
when {
$p isa person, has gender "female";
(mother: $p) isa motherhood;
},
then {
(parent: $p) isa parenthood;
};
工会联合会
如果我们有这个owl:unionOf
的例子:
:Person owl:equivalentClass [ owl:unionOf (: Woman :Man ) ]
如果资源是类:Woman
或:Man
,则分配类:Person
。在 Grakn 中,如果我们想达到同样的目的,一种方法是使用类型继承:
person sub entity;
man sub person;
woman sub person;
散列值
owl:hasValue
限制可以规定红葡萄酒应该具有颜色“红色”作为其color
属性的值:
:RedWine
a owl:Class ;
rdfs:subClassOf
[ a owl:Restriction ;
owl:onProperty :color ;
owl:hasValue "red"
] .
在 Grakn 中,可以使用一个规则来表示这一点:
when {
$w isa red-wine;
},
then {
$w has color "red";
};
哈斯尔夫
限制可以说明自恋者爱自己。
:Narcissist rdfs:subClassOf
[ owl:hasSelf true ; owl:onProperty :loves ]
这可以用 Grakn 表示:
when {
$n isa narcissist;
},
then {
(loving: $n) isa loves;
};
如前所述,Grakn 不是为 OWL 的相同用例而构建的。因此,无法进行一对一的直接映射。例如,当处理多个类时,需要考虑建模决策:在 Grakn 中,哪些成为实体,哪些成为角色。
向 SHACL 核实
传统上,RDF 不能确保接收的数据符合一组条件——即模式。这就是 SHACL 标准的作用,它在提交之前检查 RDF 是否与模式逻辑一致。还有其他检查逻辑验证的方法,只是实现略有不同。
像 SHACL 一样,Grakn 也检查有效性,并强调与数据质量有关的问题。但是尽管 SHACL 只是一个验证模式,Grakn 却实现了一个语义模式。
使用验证模式时,如果被摄取的数据源包含模式冲突,事务将失败。然后,我们会查看来源,对其进行筛选,并再次摄取。使用语义模式,我们可以加载数据,验证数据,并标记数据是否违规。然后我们可以在它们被载入的时候在线处理它们。
从这个意义上说,语义模式为您提供了额外的保证,即所有获取的数据都符合您的模式。这意味着数据库中的所有数据都与已定义的模式一致。
SHACL 中的代码片段显示了数据需要如何遵守某些限制:
:Person a sh:NodeShape, rdfs:Class ;
sh:property [
sh:path schema:worksFor ;
sh:node :Company ;
] .:Company a sh:Shape ;
sh:property [
sh:path schema:name ;
sh:datatype xsd:string;
] .
在 Grakn 中,这种验证发生在 Graql 的模式语言中。Person
实体定义为在employment
关系中只扮演employee
的角色,通过employer
的角色与company
实体相关联,包括类型name
和值string
的属性。
define
person sub entity,
plays employee;
company sub entity,
has name,
plays employer;
employment sub relation,
relates employer,
relates employee;
name sub attribute, value string;
结论
总之,我们已经看到了:
- 与语义网相比,Grakn 降低了复杂性,同时保持了高度的表达能力。有了 Grakn,我们不必学习不同的语义 Web 标准,每个标准都有很高的复杂性。这降低了进入的门槛。
- 与语义网标准相比,Grakn 为处理复杂数据提供了更高层次的抽象。使用 RDF,我们用三元组来建模世界,这是一个比 Grakn 的实体-关系概念级模式更低级的数据模型。对高阶关系和复杂数据的建模和查询是 Grakn 的原生功能。
- 语义网标准是为网络构建的,Grakn 适用于封闭世界系统。前者旨在处理开放网络上不完整数据的链接数据,而 Grakn 的工作方式类似于封闭环境中的传统数据库管理系统。
Grakn 为我们提供了一种语言,这种语言为我们提供了概念级模型、类型系统、查询语言、推理引擎和模式验证。用语义 Web 标准做同样的事情需要多种标准和它们各自的实现,每种标准都有自己固有的复杂性。特别是,OWL 的特性非常丰富,这导致了高度的复杂性,使它不适合大多数软件应用程序。相反,在处理知识表示和自动推理时,Grakn 提供了复杂性和表达性之间的适当*衡。
这种比较旨在提供两种技术之间的高层次的相似性和差异,但是,当然,Grakn 和语义 Web 还有比我们在这里试图展示的更多的东西。
要了解更多信息,请务必通过 此链接 参加我们即将举办的网络研讨会。
比较 Graql 和 SQL —第 1/2 部分
原文:https://towardsdatascience.com/comparing-graql-to-sql-part-1-2-ead496130a0c?source=collection_archive---------39-----------------------
探索共同的概念和差异
自 20 世纪 70 年代以来,SQL 一直是处理数据库的事实语言。作为一种声明式语言,编写查询和构建强大的应用程序非常简单。然而,关系数据库在处理互连的复杂数据时会遇到困难。在 SQL 中处理这类数据时,尤其是在数据的建模和查询方面会出现挑战。
Graql 是在 Grakn 中使用的查询语言。就像 SQL 是关系数据库中的标准查询语言一样,Graql 是 Grakn 的查询语言。SQL 和 Graql 都是声明式查询语言,抽象出了低级操作。两者都是:
- 尝试可读性和可理解性的语言
- 试图在更高层次上提问的语言
- 系统计算出如何进行底层操作的语言
实际上,这意味着那些原本无法接触到这些语言的人群可以接触到这些语言。在本文中,当我们查看特定的通用概念时,我们将重点比较和探索这两种语言之间的差异。
SQL 和关系模型的起源
1970 年,一位牛津毕业的数学家名叫 Edgar Codd ,也就是所谓的“ted ”,发表了一篇论文,在论文中,他引入了两种语言——一种关系代数和一种关系微积分来表达极其复杂的查询。当它们问世时,被认为是一种奇怪的数学符号。为了将这些想法构建到数据库管理系统中,Ted 创建了一个名为 System R 的研究小组,该小组基于圣何塞的 IBM 研究机构。
那时,数据库主要基于导航、网络和层级模型,在我们能够编写描述我们的查询的导航计划之前,我们需要知道物理数据层。然而,Ted 看到了其中固有的复杂性,并希望使编写数据库查询变得更容易。
然而,由于 Ted 的想法是基于数学符号和数学象征的,它们很难理解,大多数人也不太容易理解,所以两位 System R 成员通过创建一种简单的查询语言来解决这个问题 based。由于这种新语言完全基于英语单词,这成为一个突破,使人们更容易理解 Ted 的简单思想。
到 20 世纪 70 年代末,关系数据库越来越受欢迎,世界开始接受 SQL 和关系模型比它的前辈优越。此后的故事众所周知——随着世界进入数字革命,关系数据库已经成为构建软件的标准。
SQL 和 Graql 的本质
在理解 Graql 时,看看创建 SQL 的基本思想是很有用的,因为它们在概念上是密切相关的。Graql 和 SQL 的本质可以总结如下:
- 一种可以直观阅读和理解的语言。当一种语言看起来简单、可维护并且与自然文本有一定程度的相似性时,我们说它满足这些标准。
- 一种能够提出更高层次问题的语言。这里我们指的是一种允许用户在新的和更高的语义层次上描述操作的语言。
- 一种语言,在这种语言中,系统计算出如何进行低级操作。当用户描述更高层次的操作时,系统会处理这些操作,而无需用户去想它们。
从这个意义上说,SQL 和 Graql 都是抽象低级操作的语言。实际上,这意味着那些原本无法接触到这些语言的人群可以接触到这些语言。这意味着它们能够创造价值,而那些已经可以使用它们的人现在可以更快地做事。Python 也有类似的情况,例如,它是一种高级编程语言,使数百万程序员能够构建软件,而不必担心被抽象掉的低级操作。
建模和定义模式
首先,让我们看看 SQL 和 Graql 之间的数据建模有何不同。我们使用实体关系图 (ER 图),因为它是最常用的建模工具。基本模型由实体类型和它们之间可能存在的关系组成。下面是一个 ER 图示例。我们称之为概念模型。
ER 图示例。正方形是实体,菱形是关系,圆形是属性。
SQL 建模
如果我们在关系数据库中实现这个模型,我们首先要经历一个规范化过程。我们从第一范式 (1NF)开始,通过寻找诸如函数依赖和传递依赖之类的东西,我们最终得到我们想要的第三范式 (3NF)。
从 1NF 归一化到 3NF。
在这个规范化过程之后,我们在 3NF 中得到我们的逻辑模型,并在关系数据库中实现它。我们已经从概念模型(ER 图)发展到逻辑模型(3NF),甚至不需要深入到数据库的物理层。这正是关系模型带给我们的突破——抽象出物理层次。我们称之为数据的物理独立性。
SQL 给了我们数据的物理独立性。
Graql 建模
现在让我们来看看它与 Graql 有何不同。我们可以将任何 ER 图直接映射到我们如何在 Graql 中实现它,这意味着我们不需要经过规范化过程。下面我们可以看到早期 er 图的特定部分是如何建模的。我们避免了进行任何标准化的需要,因为 Graql 使我们能够创建一个带有实体、关系、属性和角色的 ER 图的直接映射,以便我们稍后在代码中实现它。这与 SQL 不同,在 SQL 中,我们需要在模型上强加一个表格结构作为逻辑层(如上所述)。
ER 图(左)到 Graql 模型(右)。
这意味着我们完全跳过了 SQL 中所需的规范化过程,我们继续在概念模型上工作。换句话说,Graql 抽象出了逻辑和物理模型。从这个意义上说,SQL 给了我们数据的物理独立性,而 Graql 给了我们数据的逻辑独立性。
通过在概念层面建模,Graql 为我们提供了逻辑模型的抽象。
在 SQL 和 Graql 中定义模式
现在我们来看一些真实的数据。任何学习过 SQL 的人可能都熟悉 Northwind 数据集。它包含虚构的专业食品进出口公司 Northwind Traders 的销售数据。
北风模式。
我们如何在 Graql 和 SQL 中定义上面显示的products
表?下面我们看到 Graql 语法定义了product
实体,以及相应的relation
。这也显示了创建新表的SQL
语句和相应的属性。
Graql
结构化查询语言
几个要点:
- 这里我们可以看到 SQL 表有三个属性,每个属性都有自己的数据类型,我们也可以在 Graql 中定义。其中一个属性是
primary key
,我们在 Graql 中使用key
关键字定义了它。 - 在 SQL 语句中,还有一个
foreign key
,根据我们的模型,我们将其建模为 Graql 中的相关relation
。我们通过使用角色product-assignment
将product
实体连接到assignment
关系来做到这一点。 - 在 Graql 中,没有
null
值的概念。如果一个概念没有属性,它就真的没有属性。这是因为在图上下文中,空属性被简单地从图中省略了。 - 最后,重要的一点是,在 Graql 模型中,属性是一等公民,不像在 SQL 中。
总结一下:
- 将 ER 图建模为 SQL 包含一个从 1NF 到 3NF 的规范化过程
- ER 图自然地映射到 Graql,不需要执行任何类型的规范化
在第 2 部分中( 链接此处 ),我们看看如何读/写数据,以及我们应该如何在 Graql 中利用超图和自动推理进行更高级别的建模。
比较现代可扩展超参数调整方法
原文:https://towardsdatascience.com/comparing-modern-scalable-hyperparameter-tuning-methods-dfe9661e947f?source=collection_archive---------23-----------------------
随机搜索、使用超点的贝叶斯搜索、结合异步超带的贝叶斯搜索和基于群体的训练的比较
来源—https://pix abay . com/photos/挖掘机-铲斗-车轮-挖掘机-1050501/
在本帖中,我们将比较以下超参数优化方法。
- 随机搜索
- 使用超点的贝叶斯搜索
- 结合异步超带的贝叶斯搜索
- 基于人口的培训
实验
我们将在 MNIST 数据集上训练一个简单的 DCGAN,并优化模型以最大化初始得分。
我们将使用 Ray Tune 来执行这些实验,并在 W&B 仪表板上跟踪结果。
我还在我的频道上做了一个视频,深入解释了这个实验-
链接到实时仪表盘
搜索空间
为了使比较公*,我们将对所有实验使用相同的搜索空间。
随机搜索
让我们在搜索空间中执行随机搜索,看看它的优化效果如何。这也将作为我们比较的基准指标。我们的实验设置有 2 个 GPU 和 4 个 CPU。我们将在多个 GPU 上并行化操作。如果您指定了resources_per_trail
,光线调节会自动为您执行此操作。
让我们看看结果
作者图片
推理
正如所料,我们得到了不同的结果。
- 一些型号确实优化了,因为调谐器运气好,选择了正确的超参数集
- 但是一些模型的初始得分图仍然是*坦的,因为它们由于不好的超参数值而没有优化。
- 因此,当使用随机搜索时,您可能最终会达到最优值,但是您最终肯定会在不增加任何价值的运行中浪费大量资源。
超点贝叶斯搜索
贝叶斯超参数调整背后的基本思想是在选择超参数时不是完全随机的,而是使用来自先前运行的信息来选择下一次运行的超参数。Tune 支持实现贝叶斯搜索算法的 HyperOpt。这是你怎么做的。
结果看起来是这样的
作者图片
推理
- 与之前的运行相比有显著的改进,因为只有一条*曲线。
- 这意味着搜索算法基于先前运行的结果选择超参数值。
- *均而言,运行比随机搜索表现更好
- 可以通过更早地终止不良运行来避免资源浪费。
异步超带贝叶斯搜索
异步超带的想法是消除或终止表现不佳的运行。将这种方法与贝叶斯搜索结合起来是有意义的,看看我们是否可以在没有优化的运行中进一步减少资源的浪费。我们只需要在代码中做一点小小的改动来适应 Hyperband。
现在让我们看看这是如何执行的
作者图片
推理
- 20 次运行中只有 2 次在规定的时期内执行,而其他运行则提前终止。
- 所达到的最高精度仍然略高于没有 Hyperband 调度程序的运行。
- 因此,通过在训练过程的早期终止不良运行,我们不仅加快了调优工作,还节省了计算资源。
基于人口的培训
图片来源—https://wandb . ai/wandb/distroopt/reports/Modern-Scalable-Hyperparameter-Tuning-Methods-VmlldzoyMTQxODM
我们将讨论的最后一个调优算法是由 Deepmind research 引入的基于群体的训练(PBT)。通俗地说,算法背后的基本思想是:
- 对于给定的时间步长(或迭代次数)t,对一些样本运行优化过程
- 在每 T 次迭代之后,比较运行,并将良好运行的权重复制到不良运行,并改变它们的超参数值以接*良好运行的值。
- 终止表现最差的运行。尽管算法背后的想法似乎很简单,但从头开始构建它需要大量复杂的优化数学。 Tune 提供了 SOTA PBT 算法的可扩展且易于使用的实现
现在让我们看看结果。
作者图片
推理
结果看起来相当令人惊讶。这些结果有许多独特的因素。
- 几乎所有的运行都达到了最佳点
- 最高分(6.29)是由一次跑步获得的
- 随着实验的进行,开始时表现不佳或异常的运行也收敛了。
- 没有运行具有*坦的初始得分图
- 一些表现不佳的运行在过程中被停止
- 因此,没有资源被浪费在不良运行上
PBT 是如何优化从错误的超参数值开始的运行的?
答案是由 PBT 调度程序完成的超参数突变。在每一个T
时间步之后,该算法还变异超参数的值,以最大化期望的度量。下面是 PBT 调度程序在这个实验中是如何改变参数的。
超参数突变
现在让我们看看超参数是如何被 PBT 算法调整来最大化初始得分的
作者图片
作者图片
推理
- 超参数值在整个实验过程中不断调整。
- 以坏的超参数值开始的运行很快被更新。
- PBT 根据探索和利用方法运行,探索良好参数值的空间,并通过更新不良运行来利用。
减少运行次数
我们现在将运行次数减少到 5 次,以便给 PBT 制造困难。让我们看看它在这种受限的情况下表现如何。
作者图片
推理
- 即使将运行次数减少到 5 次,PBT optimizer 仍然优于随机搜索和贝叶斯优化。
- 正如预期的那样,表现不佳的运行在训练过程的早期就被终止了
比较各次运行的*均初始得分
以下是*均盗梦分数的最终比较结果。我们对 5 次运行集进行了*均:
- 随机搜索— 10 次运行(作业类型—随机)
- 贝叶斯搜索— 10 次运行(工作类型—mnist-hyperpt)
- 使用 Hyperband 的贝叶斯搜索-20 次运行(工作类型-mnist-SHA2-hyperpt)
- PBT 调度程序— 10 次运行(作业类型— mnist-pbt2)
- PBT 调度程序— 5 次运行(作业类型— mnist-pbt3)
作者图片
结尾注释
如果你喜欢读这篇文章,你可以在推特上关注我,获取更多更新。我还在我的 youtube 频道上制作深度学习视频。
比较熊猫的数据结构
原文:https://towardsdatascience.com/comparing-pandas-dataframes-to-one-another-c26853d7dda7?source=collection_archive---------3-----------------------
伊洛娜·弗罗利希在 Unsplash 上的照片
我将演示几种方法,并解释每种方法的优缺点
数据框架是数据科学的主力。虽然它们不是该领域最迷人的方面,但如果你让我挑选一个数据科学家掌握的最重要的东西,那就是熟练构建和操作数据框架的能力。
在过去的一篇文章中,我将数据帧描述为部分 Excel 电子表格和部分 SQL 表,但是具有 Python 的所有通用性和分析能力。老实说,我还不是一个专业的熊猫用户,但我的目标是成为一个。这就是为什么每当我学到一些新的有用的东西,我都会试着把它记录在这里。
今天的主题是比较*等(或不*等)的数据框架。通常,当处理存储在数据帧中的数据时,我们需要知道它们是否相同。如果不是,则突出显示差异。使用案例包括:
- 根据主拷贝快速检查您的数据帧。
- 如果您下载了现有数据集的更新版本,您可能希望标识任何新行或更新的单元格。
方法 1:使用。eq 方法
熊猫数据框自带便利。eq 法。它可以让您快速比较两个数据帧,并突出显示任何不同的单元格。例如,假设我们有一些 NBA 球员的数据和他们赢得的冠军数(戒指)。
现在我们假设一个朋友正在做一个关于篮球的研究项目,并要求我们检查他的数据(他比我们更少是一个 NBA 球迷)。我们的数据在 array_1 和 df_1,朋友让我们查的数据在 array_2 和 df_2:
*# Our data*
array_1 = np.array([['LeBron',3],
['Kobe',5],
['Michael',6,],
['Larry',3],
['Magic',5],
['Tim',4]])
df_1 = pd.DataFrame(array_1,
columns=['Player','Rings'])*# Data from friend*
array_2 = np.array([['LeBron',3],
['Kobe',3],
['Michael',6,],
['Larry',5],
['Magic',5],
['Tim',4]])
df_2 = pd.DataFrame(array_2,
columns=['Player','Rings'])
我们可以使用。快速比较数据帧的 eq 方法。的产量。eq 列出了每个单元格位置,并告诉我们该单元格位置的值在两个数据帧之间是否相等(注意第 1 行和第 3 行包含错误)。
**In:**
df_1.eq(df_2)**Out:
** Player Rings
0 True True
1 True False
2 True True
3 True False
4 True True
5 True True
我们可以使用布尔索引和。all 方法打印出有错误的行。布尔索引使用一组条件来决定打印哪些行(布尔索引等于 True 的行被打印)。
**In:** *# .all returns True for a row if all values are True*df_1.eq(df_2).all(axis=1)**Out:** 0 True
1 False
2 True
3 False
4 True
5 True*# Above the rows marked True are the ones where all values equal.
# We actually want the rows marked False***In:** *# Note that we specify the axis to let Pandas know that we care* # *about equality across all the columns in a row*df_2[df_1.eq(df_2).all(axis=1)==False]**Out:
** Player Rings
1 Kobe 3
3 Larry 5
我们发现我们朋友关于科比和拉里的数据都是错的(科比其实就是 5 环的那个)。因为我们正在寻找值不相等的单元格,所以我们实际上可以使用更简洁地完成这项工作。ne 方法(。ne 代表不相等)和。任何:
**In:** # *.any returns true for row if any of the row's values are True*df_2[df_1.ne(df_2).any(axis=1)]**Out:
** Player Rings
1 Kobe 3
3 Larry 5
突出的一点是。情商和。当我们比较相同维数的数据帧时,效果更好。但是如果他们不是呢?比如说我们朋友的 dataframe 行数比我们多(加了 KG 和 Charles)。
*# Data from friend*
array_3 = np.array([['LeBron',3],
['Kobe',3],
['Michael',6,],
['Larry',5],
['Magic',5],
['Tim',4],
['KG',1],
['Charles',0]])
df_3 = pd.DataFrame(array_3,
columns=['Player','Rings'])
现在,让我们使用。需要找出不同之处。的。ne 方法已确定第 1、3、6 和 7 行中的差异。
**In:**
df_1.ne(df_3)**Out:**
Player Rings
0 False False
1 False True
2 False False
3 False True
4 False False
5 False False
6 True True
7 True True
如果我们试图在 df_1 上使用布尔索引来打印差异,Python 会给我们一个警告(因为我们的布尔索引比 df_1 长),并且只打印 Kobe 和 Larry 的行(我们最初识别的差异)。它没有打印出 KG 和 Karl,因为它们不在 df_1 中。为了打印所有的文件,我们需要在 df_3 上使用布尔索引:
**In:**
df_3[df_1.ne(df_3).any(axis=1)]**Out:**
Player Rings
1 Kobe 3
3 Larry 5
6 KG 1
7 Charles 0
如果指数不同呢?
所以当数据帧长度不同时,它也能工作。但是如果指数不同呢?索引是数据帧的关键部分,它基本上是一行的名称,以及我们需要获取数据时如何引用该行。当两个数据帧之间的索引不同时(即使单元格中的实际内容相同),则。eq 方法将它们视为不同的实体。让我们用字母索引代替数字索引来创建一个新的数据框架:
**In:**
# Array with alphabetical index
df_4 = pd.DataFrame(array_3,
index=['a','b','c','d','e','f','g','h'],
columns=['Player','Rings'])
print(df_4)**Out:
** Player Rings
a LeBron 3
b Kobe 3
c Michael 6
d Larry 5
e Magic 5
f Tim 4
g KG 1
h Charles 0
现在让我们试试。eq。输出是一个长而无用的数据帧。它的行数与我们的两个数据帧 df_1 (6 行)和 df_2 (8 行)的总和一样多。这样做是因为即使单元格内容相同,索引也不相同。等式假设两个数据帧之间没有什么是相同的。
**In:**
df_1.eq(df_4)**Out:**
Player Rings
0 False False
1 False False
2 False False
3 False False
4 False False
5 False False
a False False
b False False
c False False
d False False
e False False
f False False
g False False
h False False
让我们看看如何解决这个问题。
比较具有不同索引的数据帧
最简单的方法就是重置索引。在这种情况下,我们只需要重置 df_3 的索引(它将从字母回到从 0 开始的数字)。不要忘记删除索引,这样在重置后就不会出现额外的列。
正如你所看到的,由于重置了索引,输出回到了错误的条目(科比和拉里)以及新的条目(KG 和查尔斯)。
**In:**
*# Reset index first and drop the original index*
df_3_reset = df_3.reset_index(drop=True)*# Use boolean indexing and .ne method on reset index*
df_3_reset[df_1.ne(df_3_reset).any(axis=1)]**Out:**
Player Rings
1 Kobe 3
3 Larry 5
6 KG 1
7 Charles 0
不算太糟吧?这种方法的一个问题是,它要求第二个数据帧的索引(post reset)与第一个数据帧的对齐。换句话说,df_1 和 df_3 中重叠的球员一定是相同的(而且顺序相同),他们是——勒布朗、科比、迈克尔、拉里、魔术师、蒂姆。
但如果他们不是呢?相反,假设我们下载了一些新数据,我们希望将它们合并到我们的数据集中。不幸的是,新的数据与我们现有的数据有一些冗余,即勒布朗,迈克尔和魔术师。
*# New data to add to our dataset*
array_new = np.array([['LeBron',3],
['Michael',6,],
['Magic',5],
['KG',1],
['Charles',0],
['Stephen',3],
['Patrick',0]])
df_new = pd.DataFrame(array_new,
columns=['Player','Rings'])
新数据如下所示。注意迈克尔的指数在 df_1 里是 2 但是在这里是 1,魔术师的指数在 df_1 里是 4 但是在这里是 2。
Player Rings
0 LeBron 3
1 Michael 6
2 Magic 5
3 KG 1
4 Charles 0
5 Stephen 3
6 Patrick 0
让我们使用之前的方法来比较数据帧。eq 和. ne .首先让我们用。eq(和。all)来查看新数据和现有数据之间的相同之处:
**In:**
df_new[df_1.eq(df_new).all(axis=1)]**Out:
** Player Rings
0 LeBron 3
它说只有勒布朗的条目是相同的,即使迈克尔和魔术师的数据也是一样的。正如我们已经知道的,问题在于不同的指数。如果我们使用。ne(和。any)来标识新的或不同的行,我们会得到一个很长的列表,其中包括我们不想放在那里的行—我们不想错误地将多余的 Michael 和 Magic 条目插入到我们的数据中。
**In:**
df_new[df_1.ne(df_new).any(axis=1)]**Out:
** Player Rings
1 Michael 6
2 Magic 5
3 KG 1
4 Charles 0
5 Stephen 3
6 Patrick 0
使用合并
在这种情况下,最好的方法(据我所知)是使用。合并方法(我在这里写了一篇关于合并的文章,所以如果你需要背景知识,可以看看这篇文章。合并。这有点绕弯,但是通过使用 merge,我们可以只比较每个条目的值,而不考虑索引。
使用 Player 和 Rings 列进行合并允许我们匹配现有数据帧和新数据帧中具有相同值的行(同时忽略数据帧索引中的差异)。我们需要重命名新数据帧中的 Rings 列,使它作为两个独立的列输出(旧的 Rings 和新的 Rings_new)。一旦我们检查了输出,您就会明白为什么。
# Need to rename Rings since we are merging on it but we want
# it to show as different columns post-merge
temp = df_new.rename({'Rings': 'Rings_new'}, axis=1)merged = temp.merge(df_1, how='left',
left_on=['Player','Rings_new'],
right_on=['Player','Rings'])
我已经打印了名为“合并”的数据框的内容。NaN 就是我们要找的东西(这也是为什么我们需要两栏都显示)。因为我们进行了左连接,所以输出包括 df_new 中的每一行——我们在 df_1 中已经有数据的球员在 Rings 列中有数值。新玩家在“环”列中用 NaN 值表示,这是我们唯一想添加到数据集的玩家。
Player Rings_new Rings
0 LeBron 3 3
1 Michael 6 6
2 Magic 5 5
3 KG 1 NaN
4 Charles 0 NaN
5 Stephen 3 NaN
6 Patrick 0 NaN
我们可以通过对数据帧进行切片来分离出新的条目,只对环中具有 NaN 值的行进行切片:
**In:**
df_new[merged['Rings'].isna()]**Out:**
Player Rings
3 KG 1
4 Charles 0
5 Stephen 3
6 Patrick 0
并像这样连接到我们的数据帧:
final_df = pd.concat([df_1,
df_new[merged['Rings'].isna()]],
axis=0)
最后,我们得到了我们想要的。final_df 的内容如下所示:
Player Rings
0 LeBron 3
1 Kobe 5
2 Michael 6
3 Larry 3
4 Magic 5
5 Tim 4
3 KG 1
4 Charles 0
5 Stephen 3
6 Patrick 0
请注意,如果在新数据中有一个现有球员(如[LeBron,0])的错误条目,它也会被插入,因为我们合并了球员和戒指(因此,为了匹配条目,姓名和戒指数需要相同)。如果我们不想要这种行为,那么我们可以只在玩家列合并。这也可能引起问题,因为可能会有另一个同名但戒指数不同的球员(比如迈克尔·库帕有 5 枚戒指,而迈克尔·乔丹只有 6 枚)。当然,对于一个真实的数据集,我们将包括足够多的字段,以便我们可以唯一地识别每个球员(例如,名字,姓氏,出生日期)。
希望这是有见地的,祝你的数据框架好运!干杯!
如果你总体上喜欢这篇文章和我的写作,请考虑通过我的推荐链接注册 Medium 来支持我的写作。谢谢!
比较 Q 级咖啡:地区、年份和加工
原文:https://towardsdatascience.com/comparing-q-grades-of-coffees-regions-years-and-processing-84f3c676f093?source=collection_archive---------42-----------------------
咖啡数据科学
使用 Q 等级特征检查匹配分数
之前,我观察了 Q-grade 的每个子指标与总分的关联程度,一些有趣的记录出现在某些年份和地区。现在,我的目的是看看如何将子指标用作特征描述符,并相互比较。这是否揭示了咖啡在地区、年份或加工方法上的相似之处?
类似
为了计算相似性得分,使用均方根将 10 个子指标的每个向量与所有其他向量进行比较:
这些分数是针对所有咖啡和所有咖啡计算的,如下图所示,按分数着色并按国家排序:
本文中的所有图片均由作者提供。
然而,在下面的细目分类中,我将每个图表调整到 0%到 100%之间。100%不代表完全匹配,0%也不代表不匹配。它相对于每个图表中的数据,其中 100%是最大相似度(最相似),0%是最小相似度(最不相似)。
按地区
我们可以从查看每个地理区域开始。非洲咖啡豆比其他任何地方的咖啡豆都更像南美咖啡豆。中美洲的豆子似乎非常独特,与其他地区的豆子不同,但是南美洲的豆子与其他地区的豆子有最多的共同点。
这可以按国家进一步细分,这有助于我们更好地了解这些地区。这并不是说非洲的咖啡豆和它们自己的相比不好,而是南美的咖啡豆和非洲的相比要好得多。一些中美洲的豆类比非洲的一些国家好。
结果很有趣,有多少品种和多少咖啡是彼此相似的。主要的区别在于巴布亚新几内亚和美国,它们不能与多种咖啡相提并论。
我希望这张表能有所帮助,作为参考,甚至在人们做杯子的时候进行比较。我很好奇哪些咖啡是杯装在一起的,因为这可能会影响体验。
按年份
在我之前使用相关性进行的分析中,2015 年脱颖而出。在这种情况下,2010 年和 2017 年似乎是疯狂的一年,因为相对而言,它们与其他年份并不相似。2018 年比什么都好,因为在这个数据集中只有 8 种 2018 年的咖啡。
我们也可以按年查看地区,看看是否有任何有趣的趋势,因为一年中的天气对考虑作物结果很重要。这是一个非常高的水*,只有颜色编码,但如果有人好奇,我会很高兴地分享这些表进行更深入的检查。
南美似乎是多年来最相似的地方,我怀疑这是因为更多的咖啡被清洗,而不是自然或干燥加工。中美洲似乎是 2010 年和 2017 年是怪异年份这一概念的关键角色。
通过加工
看看加工过程,我们看到了在品尝豆子时所看到的,清洗豆子在某些方面使味道变得均匀。洗豆比其他工艺更类似于其他豆类。天然加工的豆子最不像自己。
我们可以将这一过程按地区进行细分,以帮助了解它们是如何相似的。正如你所看到的,湿加工的咖啡豆在地域上比干加工的咖啡豆更相似。干加工的非洲咖啡豆似乎与其他地区/加工过程最不相似。
在计算干与干、干与湿、湿与湿的*均相似性时,可以看到下表的简化。
在某些情况下,干加工的分数比湿加工的好,而不是其他干加工的。这有点令人惊讶,但一个未知的变量是其他豆子在同一时间被分级。如果一个人同时给多个豆子评分,分数可能会受到类似的影响。
所以我们来看看分级协会!
分级员
每个分级员都属于一个分级协会,人们可以假设在一个协会内,分级员对咖啡的分级会更加相似。一些评分者有非常相似的分数,理想情况下,每个人都会给豆子打相同的分。问题总是不同的咖啡产区用不同的分级体。
我们可以通过移除 10 级或以下咖啡的分级员来压缩这张桌子。看看这个,我们可以看到一些评级机构与其他机构非常不同,但这也可能是他们对咖啡进行评级的类型。
大多数协会对自己的评分和对彼此的评分相似。有一些异常值,他们的评分和其他人不一样。
这是在使用现代数据科学和模式识别技术来帮助理解咖啡如何相互分级以及通过等级来确定咖啡有多相似的方向上迈出的又一步。q-分级是主观的,但目的是有一个共同的语言,以比较/对比的方式谈论咖啡。希望随着数据在咖啡供应链中变得更加完整,看到这种类型的比较不仅会变得更加普遍,而且它们将成为影响我们制作咖啡的工具。
如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。
我的进一步阅读:
按地区、工艺、等级和价格分类的咖啡
家庭烘焙咖啡的经济学
咖啡豆脱气
解构咖啡:分割烘焙、研磨、分层以获得更好的浓缩咖啡
浓缩咖啡的预浸:更好的浓缩咖啡的视觉提示
咖啡的形状
搅拌还是旋转:更好的浓缩咖啡体验
香辣浓缩咖啡:热磨,冷捣以获得更好的咖啡
断续浓缩咖啡:提升浓缩咖啡
用纸质过滤器改进浓缩咖啡
浓缩咖啡中咖啡溶解度的初步研究
断奏捣固:不用筛子改进浓缩咖啡
浓缩咖啡模拟:计算机模型的第一步
更好的浓缩咖啡压力脉动
咖啡数据表
比较最佳免费金融市场数据 API
原文:https://towardsdatascience.com/comparing-the-best-free-financial-market-data-apis-158ae73c16ba?source=collection_archive---------9-----------------------
作为一名数据科学家、交易员或投资者,如果你想分析金融市场数据——股票市场或加密数据,从这里开始吧。
克里斯·利维拉尼在 Unsplash 上的照片
在我们的世界里,很少有东西像金融市场和数据这样紧密相连。金融市场的整个功能是基于其参与者对可用信息和从所述信息中综合的知识采取行动;目标是以他们认为有利的价格购买或出售资产。
这种机制设定了市场价格,进而赋予市场另一个关键属性——数据来源。不管有效市场假说的有效性,以及价格的客观正确性,很少有东西能像市场数据那样捕捉到集体情绪。
此外,可用数据的粒度随着时间的推移而增加,现在可以捕捉个人情绪以及集体情绪。其结果是,如此丰富、如此广泛、拥有如此多市场历史的任何数据源都很少有相似之处。
照片由 Aditya Vyas 在 Unsplash 拍摄
例如,纽约证券交易所自 1792 年就已经成立了。)而如今,据说仅美国的纽约证券交易所这样的主要交易所*均每天就产生大约 300 亿个市场事件。
鉴于这些市场涉及大量资金,以及不断寻求优势的猫鼠游戏,寻求更多更好的数据并不奇怪。
虽然这些天来市场通过销售其数据产品获得了可观的收入,但市场数据分析领域仍然有许多优秀的、免费的切入点。这些 API 中的一些还提供关于加密资产以及来自股票市场的信息。
因此,在本文中,我比较了几个顶级金融市场数据 API 的自由层。我希望它们对你有用。
API 比较—概述
IEX 云
IEX 是一家初创股票交易所,其联合创始人布拉德·山因迈克尔·刘易斯的书《闪光男孩》而出名
IEX 的价值主张是,它的目标是成为一个交易所“,消除行业中一些最糟糕的做法“ ( 文章濒临破产)。 IEX 云(网站)是 IEX 的数据 API 分支,提供如下免费层:
IEX 云免费层(截至 2020 年 3 月 9 日)
廷戈
它们从 2014 年就已经存在了(见这篇关于 2015 年 HackerNews 的讨论),如果没有别的,存活这么久可能是其可靠性和可行性的一个好迹象。
他们的自由层功能概述如下:
Tiingo 自由层(截至 2020 年 3 月 9 日)
Quandl
Quandl 自 2013 年以来一直存在,现在是纳斯达克的一部分。
他们的使命不仅仅是收集股票市场数据,因此他们从大量广泛的来源提供各种不同领域的数据集。虽然不是所有的数据产品都是免费的,但是他们的财务数据 API 是免费的,有以下限制:
Quandl 自由层(截至 2020 年 3 月 9 日)
有趣的是,Quandl 似乎还提供了为 R、Python 和 Excel 编写的原生工具,旨在使下载数据更容易。
阿尔法优势
除了这种相对宽泛的简介,Alpha Vantage 网站上关于他们成立的时间、他们是谁以及该组织代表什么的信息相对较少。
关于 Alpha Vantage ( 链接)
尽管如此,他们确实提供了一个如下的免费层,并且看起来使用相对广泛。
Alpha Vantage 自由层(截至 2020 年 3 月 9 日)
WorldTradingData
他们的网站(链接)同样包含很少的关于他们是谁的信息,但与其他网站类似,他们提供一个免费层,并因此相对知名。
详细的自由层比较
每个网站上的信息布局使得产品比较非常困难,所以下面是我的尝试:
有用数据
幸运的是,所有这些 API 似乎都提供了历史和当日美国股票价格,以及外汇数据。因此,就数据可用性而言,任何这些服务都可能满足您的大部分需求。
对于加密货币数据,IEX、Quandl 和 Tiingo 提供这些数据,而 Alpha Vantage 和 WorldTradingData 则没有。
如果你在 API 访问额外(非价格)信息后,IEX 也提供 API 访问基本面和新闻数据。Quandl 的部分数据源也是免费的。
自由层数据限制
因为它有点复杂,让我们把 IEX 留到最后,看看其他的:
- Tiingo :每月 500 个唯一符号,500 个请求/小时,20000 个请求/天,5gb/月(来源)。
- Quandl : 300 个请求/10 秒,2000 个请求/10 分钟,50000 个请求/天,如果经过认证(来源)。(每 10 分钟 20 个电话,如果匿名,每天 50 个电话)
- Alpha Vantage : 5 个请求/分钟,500 个请求/天(来源)。
- WorldTradingData : 250 个请求/天(25 个当天请求/天)(来源)。
现在,让我们来看看 IEX。他们有每月 50,000 条核心“消息”的自由层限制。每种类型的请求将使用不同数量的消息,因此数据越多,使用的消息就越多。
50,000 条消息并不是一个很大的数目。*均来说,不太可能有 Tiingo 和 Quandl 那么多数据(虽然这取决于使用情况),所以我会建议明智地使用它们。
该计算器将为您提供使用特定数据端点的每个月将使用多少“消息”的估计。
[## 定价计算器| IEX 云
IEX 云是构建金融科技应用最简单、最容易实现的方式。
iexcloud.io](https://iexcloud.io/calculator/)
令人高兴的是,IEX 是唯一一个提供沙盒测试模式的公司,这种模式将返回“虚拟”或随机数据。沙盒模式可以用来测试和优化你的代码,看看你在真实的、实时的模式下会使用多少消息,对个人来说这是一个很大的好处。
证明文件
总的来说,我发现 IEX 云文档是我看过的所有文档中最全面的。
以下是他们文档的链接:
[## IEX 云 API | IEX 云
IEX 云是构建金融应用程序最简单的方式。
iexcloud.io](https://iexcloud.io/docs/api/)
例如,IEX 文档清楚地显示了历史价格请求的响应属性:
IEX 文档—响应属性(链接)
IEX 文档包括请求示例、参数列表、响应示例和属性,以及版本、错误代码和安全说明等其他方面。
据我所知,IEX 是名单中最大的组织,这在这里的全面性上得到了体现。
这并不是说其他人的文件是缺乏的,更多的是 IEX 的文件是非常全面的。
Tiingo 的文档在这里:
[## 股票市场工具| Tiingo
一个金融研究*台,致力于为所有人创造创新的金融工具,同时采用座右铭…
api.tiingo.com](https://api.tiingo.com/documentation/general/overview)
Tiingo 文档—响应属性(链接
Quandl 在这里:
[## Quandl 文档
获取您的免费 API 密钥,开始使用我们的数据。开始使用我们强大的数据 API 分析所需的一切…
docs.quandl.com](https://docs.quandl.com)
Quandl 文档—响应属性(链接)
这两个都非常详细,有示例请求和参数,以及响应示例和参数。虽然可能不如 IEX 文档那样令人印象深刻,但这些仍然相当可靠。
最后,我将把 Alpha Vantage 和 WorldTradingData 文档放在最后一层。
[## Alpha Vantage API 文档
Alpha Vantage 的 API 文档。Alpha Vantage 为实时和历史股票和权益提供免费的 JSON APIs
www.alphavantage.co](https://www.alphavantage.co/documentation/) [## API 文档|世界贸易数据
我们的 API 通过我们的 API 提供对 JSON 或 CSV 格式的实时和历史股票数据的有效访问…
www.worldtradingdata.com](https://www.worldtradingdata.com/documentation)
虽然它本身没有遗漏任何信息,但它们显然不像其他的那样完整或有解释力。
根据你对编程和 API 的经验水*,你可能会从 IEX / Tiingo 和 Quandl 的更全面的文档中获益更多。
结论
我试图在这里给出顶级免费金融市场数据 API 的简要概述。
上面列出的五个 API 都是非常惊人的数据服务,尤其是考虑到它们的运行是免费的。如上所述,历史数据或当天数据等常见数据类型可从所有提供商处获得,选择哪种服务在很大程度上取决于个人选择。
说到这个,作为金融界的爱好者,我个人更喜欢 IEX。对于像我这样的临时用户,我希望学习曲线越浅越好,他们的大量文档会非常有帮助,就像他们的沙盒模式一样。不过,如果我需要更多的数据,Quandl 或 Tiingo 似乎也是不错的选择。
不过,总的来说,我(非专家)的观点是,所有这些似乎都是进入金融市场数据分析世界的非常可靠的切入点,您可能希望选择一个最适合自己的。
我希望你觉得这是有用的,如果你有任何意见,或者我犯了什么错误,请告诉我!
在接下来的几周里,我将使用来自一个或多个 API 的数据进行分析。
(如果你想知道为什么我没有包括雅虎!,这是因为它已被官方弃用——尽管许多人似乎仍在使用它)
- 注意:这篇文章包含一个亚马逊联盟链接,这意味着在你没有额外费用的情况下,如果你购买,我会得到一小笔佣金。
如果你喜欢这个,比如说👋/关注推特,或点击此处获取更新。如果你错过了,看看这篇关于可视化时间序列数据的文章。
[## 随着时间的推移有效地可视化数据,以讲述更好的故事
使用 Python 和 Plotly 构建清晰易读的时序数据可视化,以支持您的叙述。
towardsdatascience.com](/effectively-visualize-data-across-time-to-tell-better-stories-2a2c276e031e)
这是关于用 Plotly Dash 建立一个网络数据仪表板。
[## 使用 Python 在几分钟内构建一个 web 数据仪表板
通过将您的数据可视化转换为基于 web 的仪表板,以指数方式提高功能和可访问性…
towardsdatascience.com](/build-a-web-data-dashboard-in-just-minutes-with-python-d722076aee2b)
比较预报模式的性能:霍尔特-温特斯与 ARIMA
原文:https://towardsdatascience.com/comparing-the-performance-of-forecasting-models-holt-winters-vs-arima-e226af99205f?source=collection_archive---------7-----------------------
如何评估模型性能以及如何选择合适的模型
菲尔·德福斯在 Unsplash 拍摄的照片
这是我写的关于时间序列预测模型的系列文章中的第三篇。第一篇文章是时间序列预测在现实世界中的应用,我用美国住房市场数据做的,目的是展示预测是如何实施和解释的。在第二篇文章中,我概述了建立预测模型的 5 个简单步骤,目标是从未做过预测的初学者。在今天的文章中,我将展示如何将两种不同的技术应用于同一数据集,以及如何评估和比较它们的性能。
在众多不同的预测技术中,我选择了两个模型来评估:ARIMA 和霍尔特-温特斯指数*滑法。在继续之前,我将简要描述它们是什么以及它们在概念上有什么不同。
ARIMA(自回归综合移动*均) : ARIMA 可以说是预测中最流行、最广泛使用的统计技术。顾名思义,ARIMA 有 3 个部分:a)一个自回归部分模拟序列和它的滞后值之间的关系;b)移动*均组件预测作为滞后预测误差的函数的未来值;c)集成组件使系列静止。
ARIMA 模型——表示为 ARIMA(p,q,d)——采用以下参数:
- 定义滞后数量的 p;
- d 指定使用的差异数;和
- q 定义移动*均窗口的大小
霍尔特-温特斯:这是另一套同样使用历史值的技术。然而,一个关键的区别特征是所谓的“指数*滑”。
如果分解,时间序列将分解成 3 个部分:趋势、季节性和白噪声(即随机数据点)。出于预测目的,我们可以预测可预测的组成部分(即趋势和季节性),但不能预测以随机方式出现的不可预测的项目。指数*滑可以通过消除白噪声来处理序列中的这种可变性。移动*均值可以*滑训练数据,但它是通过对过去的值取*均值并对它们进行*均加权来实现的。另一方面,在指数*滑中,过去的观察值以指数递减的顺序加权。也就是说,最*的观测值比远处的值具有更高的权重。
现在让我们开始实施、比较和评估这两种预测技术。
数据准备
我做这个练习的方式是,你不必寻找外部数据集。我已经在你下面包括了美国住宅数据的一个子集——一个真实世界和最*的数据集,所以你可以在你的程序中复制它们。你应该能够跟上并从这里到结尾很好地复制一切。
我在 R 编程环境中用 Rob J. Hyndman 开发的fpp2
预测包实现了这个功能。
# required package
library(fpp2)# data
values = c(92.1, 92.6, 89.5, 80.9, 95.6, 72.5, 71.2, 78.8, 73.8, 83.5, 97.9, 93.4, 98.0, 90.2, 96.7, 100.0, 103.6, 74.6, 78.9, 92.0, 83.4, 98.1, 109.9, 102.2, 102.1, 96.2, 106.9, 95.1, 113.4, 84.0, 88.6, 94.9, 94.7, 105.7, 108.6, 101.9, 113.9, 100.9, 100.2, 91.9, 99.6, 87.2, 92.1, 104.9, 103.4, 103.3, 103.9, 108.5)# time series
time_series = ts(values, start = 2015, frequency =12)
时间序列分解
时间序列分解意味着将序列解构并可视化为这些组成部分—趋势、季节性和随机成分。
趋势和季节性在时间序列中是可预测的,并且易于预测。我对随机部分最感兴趣,因为这个部分实际上决定了预测的不确定性。随机性越小,预测性能越好。
# decomposition
autoplot(decompose(time_series)) + ggtitle("Decomposition of the series") + theme(plot.title = element_text(size=8))
时间序列分解
造型:ARIMA 和 HW
你可以用许多不同的方式参数化 ARIMA 和霍尔特-温特,但我保持简单。fpp2
包有auto.arima()
功能,可以优化参数本身,当然你也可以随意调整参数。在霍尔特-温特斯技术中,我需要说明季节性是增加的还是增加的。在这两种情况下,我都是在预测未来 60 步(h = 60),也就是未来 5 年。
# ARIMA
forecast_arima = auto.arima(predictor_series, seasonal=TRUE, stepwise = FALSE, approximation = FALSE)
forecast_arima = forecast(forecast_arima, h=60)# Holt-Winters
forecast_hw = hw(predictor_series, seasonal="multiplicative", h=60)
预测
运行模型后,您就可以检查预测结果了。你可以用数据图表来检查结果,或者用图形来显示。
fpp2
模型具有内置的可视化功能authoplot()
,可以创建时间序列数据和预测值的ggplot
样式图形。它们使您可以直观地检查和确定模型的性能。
# ARIMA
autoplot(predictor_series, series=" Historical data") +
autolayer(forecast_arima, series=" ARIMA Forecast") +
ggtitle(" ARIMA forecasting") +
theme(plot.title = element_text(size=8))# HW
autoplot(predictor_series, series=" Historical data") +
autolayer(forecast_hw, series="Holt-Winter forecast") +
ggtitle("HW Exponential Smoothing") +
theme(plot.title = element_text(size=8))
用模型预测:ARIMA
用模型预测:Holt-Winters
模型评估
模型评估时间到了。对上述预测数字的直观检查并没有显示出预测结果的很大差异,这可能是因为可预测的季节性和趋势成分。然而,Holt-Winters 确实显示出(至少在视觉上)预测值的不确定性较高。
但是我们可以超越视觉检查,使用量化指标来评估性能。如果您查看模型描述并调用accuracy()
函数,就会弹出一堆信息。在下表中,我总结了一些您可能用来评估模型的关键指标。
# ARIMA
forecast_arima['model']
accuracy(forecast_arima)# HW
forecast_hw['model']
accuracy(forecast_hw)
需要仔细解读这些指标。在本案例研究中,在训练数据的 RMSE 测量中存在一些差异,但是在 MAE 中的差异并不显著。就 AIC 而言,ARIMA 似乎是一个更好的模式。注意:虽然 AIC 非常擅长比较同级别车型(如 ARIMA 车型),但它不应用于比较两个非常不同的车型级别(如 ARIMA 与硬件)。我在这里展示它们只是为了告诉大家它在实际实现中是什么样子。
尽管如此,最终确定一个合适的模型需要根据定量的模型选择标准以及使用领域知识来仔细判断和选择。
结论
本文的目的是展示使用相同数据集的不同预测模型实现,并演示如何评估模型性能以及选择适合问题空间的模型。在这里,我比较了两个模型——ARIMA 和霍尔特-温特斯——但是还有一整套其他的预测技术——T2——可以应用于给定的数据集。我鼓励你去找一个不同的数据集,尝试不同的预测模型,看看它们在不同的实现中表现如何。
TensorFlow 中全连接、简单 CNN 和 ResNet50 用于二值图像分类的性能比较
原文:https://towardsdatascience.com/comparing-the-performance-of-fully-connected-simple-cnn-and-resnet50-for-binary-image-5dae3cea034?source=collection_archive---------41-----------------------
使用 TensorFlow/Keras 比较 3 个二值图像分类器模型的精确度、ROC 曲线和 AUC。你认为哪个表现最好?
梅丽莎·迪·罗科在 Unsplash 上的照片
在机器学习的世界中,有三种模型可以用来执行二进制图像分类:全连接网络、卷积神经网络,或预训练网络,如应用了迁移学习的 MobileNet】。在我以前的故事中,我展示了如何实现这些模型来构建一个图像分类器,该分类器可以对蒲公英和草进行分类,并通过计算它们的准确性、ROC 曲线和 AUC 分数来评估它们的性能。在这个故事中,我将并排比较这些模型,并比较它们的性能。如果您想跟踪这些模型的整个培训、评估和比较,请跟踪本笔记本。您可以通过转到文件- >保存副本来保存您自己的副本,从而运行代码。
你认为哪种型号性能最好?
模型架构概述
首先,让我们看一下这三种模型架构,看看它们有什么不同:
FULLY-CONNECTED MODELLayer (type) Output Shape Param # ================================================================= flatten (Flatten) (None, 120000) 0 _________________________________________________________________ dense (Dense) (None, 128) 15360128 _________________________________________________________________ dense_1 (Dense) (None, 1) 129 ================================================================= Total params: 15,360,257 Trainable params: 15,360,257 Non-trainable params: 0CONVOLUTIONAL NEURAL NETWORK MODELLayer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 198, 198, 16) 448 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 99, 99, 16) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 97, 97, 32) 4640 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 48, 48, 32) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 46, 46, 64) 18496 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 23, 23, 64) 0 _________________________________________________________________ conv2d_3 (Conv2D) (None, 21, 21, 64) 36928 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 10, 10, 64) 0 _________________________________________________________________ conv2d_4 (Conv2D) (None, 8, 8, 64) 36928 _________________________________________________________________ max_pooling2d_4 (MaxPooling2 (None, 4, 4, 64) 0 _________________________________________________________________ flatten (Flatten) (None, 1024) 0 _________________________________________________________________ dense (Dense) (None, 512) 524800 _________________________________________________________________ dense_1 (Dense) (None, 1) 513 ================================================================= Total params: 622,753 Trainable params: 622,753 Non-trainable params: 0MOBILENET w/ TRANSFER LEARNINGLayer (type) Output Shape Param # ================================================================= mobilenetv2_1.00_224 (Model) (None, 7, 7, 1280) 2257984 _________________________________________________________________ global_average_pooling2d (Gl (None, 1280) 0 _________________________________________________________________ dense (Dense) (None, 1) 1281 ================================================================= Total params: 2,259,265 Trainable params: 1,281 Non-trainable params: 2,257,984
请注意,全连接模型的可训练参数数量最多,其次是 CNN 模型,最后是 MobileNet 模型。在 FC 模型中,展*层中的每个连接都连接到密集层中的每个连接,从而产生更多的参数。在 CNN 中,需要的参数更少,因为每个卷积层通过卷积运算降低了输入的维数。与这两个模型相比,MobileNet 模型使用所谓的迁移学习:它不在预训练层上训练,只训练最终的密集层。它利用预训练层的特征提取能力来训练最后一层,因此只需要很少的参数来训练模型。
比较精确度
对于每个模型,我使用相同的数据集,并用 15 个时期训练模型。让我们将结果汇总在一起,并排进行比较,从精度开始:
FC accuracy: 0.5987
CNN accuracy: 0.7197
MobileNet accuracy: 0.8917
MobileNet 模型的准确性最高,其次是 CNN 模型,再其次是全连接模型。
比较 ROC 曲线和 AUC
ROC 曲线的组合图
准确性不是比较模型性能的最佳方式。分类任务的更好的度量包括 ROC 曲线和 AUC,它们测量我们的模型能够在多大程度上区分我们的两个类别,蒲公英和草。AUC 越高,我们的模型在分类上就越好。在上图中,MobileNet 在 AUC 中得分最高,其次是 CNN,然后是 FC。
以下是这些比较的要点:
- 就准确性和 ROC 曲线/AUC 而言,MobileNet 模型是一个优越的模型,尽管它没有最多的参数。这显示了迁移学习在强大的训练模型上的力量。
- CNN 模式排在第二位。卷积神经网络在二值图像分类上比全连接网络表现得更好,具有更少的参数,因为它们的共享权重结构和*移不变性特征。
- 在二值图像分类中,全连接模型比机会模型表现得更好,但它不是这样做的最佳模型。
贷款申请预测的 ML 模型比较与优化
原文:https://towardsdatascience.com/comparison-and-optimization-on-ml-models-for-loan-application-prediction-675923d83d04?source=collection_archive---------30-----------------------
深入研究常见的机器学习模型,以进行模型选择、验证和优化
来自 Pixabay 的 Img 通过链接
在本文中,我们将使用在线贷款申请数据详细阐述 ML 模型的选择、验证和优化。你将学习如何创建、评估和优化 ML 模型。具体来说,我们将重点介绍逻辑回归、支持向量机和随机森林。它分为 7 个部分。
- 商业挑战
- 数据审查
- 电子设计自动化(Electronic Design Automation)
- 数据处理
- 模型结构
- 模型验证
- 参数调谐
- 外卖食品
现在,让我们开始旅程🏃♀️🏃♂️.
1。商业挑战
我们被一家贷款公司委派预测优质申请人的任务。这项工作是开发一个模型,通过分析申请过程中输入的申请人数据来预测申请人的兴趣。如果申请人感兴趣,他或她将对产品进行电子签名,否则不会。
2。数据回顾
快速查看视频中显示的数据,您会发现有 21 列 17,908 行。有了这么多特性,让我们为每个变量的解释创建一个摘要,如图 1 所示,以增强我们的理解。
视频原始数据的简要视图
图 1 变量定义汇总
3。EDA
EDA 是任何数据处理之前必须要做的一步。通常,它包括数据清理、数据可视化和相关性分析。这里我就不细说 EDA 了。如果你想熟悉 EDA 的步骤,请随意阅读这篇文章。
4。数据处理
1)数据工程
在 EDA 数据可视化过程中,您可能会发现,对于变量' months_employed ',大多数申请人的就业时间为 0 个月。这似乎不正确,所以我们将删除这个不可靠的列。
第二,可以将两列'个人账户 m' 和'个人账户 y ',组合成一个新的变量来表示申请人账户的总月数。具体来说,
dataset = dataset.drop(columns = [‘months_employed’])dataset[‘personal_account_months’] = (dataset.personal_account_m + (dataset.personal_account_y * 12))dataset = dataset.drop(columns = [‘personal_account_m’, ‘personal_account_y’])
2)一键编码
我们需要将分类变量转换成数字变量。只有一个分类变量' pay_schedule' 。具体来说,
dataset = pd.get_dummies(dataset)
以上将'付薪时间表'转换为 4 列,付薪时间表 _ 双周','付薪时间表 _ 月',付薪时间表 _ 半月',付薪时间表 _ 周'。因为每一列都是互斥的,所以我们必须删除一列,使它们线性独立。具体来说,
dataset = dataset.drop(columns = [‘pay_schedule_semi-monthly’])
3)数据分割
为了给模型准备好数据,我们将自变量和响应变量分成测试集和训练集。
response = dataset[“e_signed”]
users = dataset[‘entry_id’]
dataset = dataset.drop(columns = [“e_signed”, “entry_id”])from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(dataset, response,test_size = 0.2, random_state = 0)
4)特征缩放
最后,我们需要缩放自变量。
from sklearn.preprocessing import StandardScalersc_X = StandardScaler()
X_train2 = pd.DataFrame(sc_X.fit_transform(X_train))
X_test2 = pd.DataFrame(sc_X.transform(X_test))
X_train2.columns = X_train.columns.values
X_test2.columns = X_test.columns.values
X_train2.index = X_train.index.values
X_test2.index = X_test.index.values
X_train = X_train2
X_test = X_test2
注意,从 scaler 得到的数据是一个 Numpy 数组,我们将它转换为 Dataframe 以保留索引和列名。同样,我们用 X_train 训练定标器,用训练好的定标器直接转换测试数据。
5。模型构建
首先,让我们试验不同的模型,找出最好的一个。
1)逻辑回归
让我们先创建一个线性模型。具体来说,
from sklearn.linear_model import LogisticRegression
classifier = LogisticRegression(random_state = 0, penalty = ‘l1’)
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
上面的代码块将对逻辑回归模型进行定型和测试。注意我们使用了 L1 套索正则化来惩罚模型的系数。如果你想了解更多的细节,请查看这篇关于正规化的文章。
最终我们得到了 56%的准确率,57%的准确率,70%的召回率。这意味着在所有积极的预测中,只有 57%是正确的,而这些正确的预测占实际预测的 70%😆。
2) SVM(线性核)
让我们建立一个基于支持向量机的分类器。
SVM 的一个关键概念是内核。使用核进行数据转换,使得当前数据空间中不可分的数据可以在更高维空间中分离。它接收数据作为输入,并根据选择的内核将其转换成所需的形式。显然,选择正确的内核至关重要,因为错误的转换会使模型表现不佳。如果你想深入了解 SVM 的细节,请随意阅读这篇文章和这篇文章。
首先,让我们训练一个线性核 SVM。通常,当数据集是线性可分的,即使用单线可分时,使用线性核。它比其他任何内核都快。具体来说,
from sklearn.svm import SVC
classifier = SVC(random_state = 0, kernel = ‘linear’)
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
最终我们得到了 57%的准确率,58%的准确率,73%的召回率。与逻辑回归模型相比,这是一个稍好的性能🤪。
3) SVM 银行
径向基函数是 SVM 中使用的非线性核。与线性核相比,RBF 不是一个参数模型,其复杂性随着数据的大小而增加。因此,训练模型以及进行预测的成本更高。此外,超参数越多,复杂模型越容易过度拟合。
具体来说,要实现 RBF,
classifier = SVC(random_state = 0, kernel = ‘rbf’)
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
同样,经过训练和测试,我们获得了 59%准确率、60%的精确度和 69%的召回率。与线性核相比没有太大的改进😒。
4)随机森林
随机森林通过构建大量个体决策树并输出分类问题的模式类或回归问题的均值预测来运行。运行许多决策树的潜在逻辑是,最优决策来自群体的智慧,简单而强大。
为了实现 RF,具体地说,
from sklearn.ensemble import RandomForestClassifier
classifier = RandomForestClassifier(random_state = 0, n_estimators = 100, criterion = ‘entropy’)
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
如上所述,我们创建了 100 棵决策树。最终我们得到了 62%的准确率,64%的准确率,67%的召回率。总结图 2 中的所有模型性能,我们发现 RF 的性能最佳😁。
图 2 模型性能总结
6。模型验证
在优化随机森林模型之前,我们先验证一下它的性能。这里,我们使用训练数据应用 K 重交叉验证。具体来说,
from sklearn.model_selection import cross_val_score
accuracies = cross_val_score(estimator = classifier, X= X_train, y = y_train, cv = 10)
最后,我们得到了 63%的准确率和 3%的标准偏差。这表明随机森林模型对于训练集一直表现良好😎。
7。参数调谐
因为我们知道随机森林与其他模型相比性能最佳,所以让我们通过使用参数调整来优化随机森林模型。
随机森林分类器有几个参数,包括:
- e _ estimators】:树的数量
- 判据 ”:衡量分割质量的判据
- " max_depth ":每棵树的最大层数
- "min _ samples _ split":拆分一个节点所需的最小样本数
- " max_features ":寻找最佳分割时要考虑的最大特征数
- " min_samples_leaf ":一个叶节点需要的最小样本数
- " bootstrap ":数据点采样的一种方法(有替换或无替换)
在这里,我们选择下面的参数,并为每个参数设置搜索范围。
parameters = {“**max_depth**”: [3, None],“**max_features**”: [1, 5, 10],‘**min_samples_split**’: [2, 5, 10],‘**min_samples_leaf**’: [1, 5, 10],“**bootstrap**”: [True, False],“**criterion**”: [“entropy”]}
我们使用网格搜索来遍历所有不同的参数组合以及每个组合的交叉验证。我们也可以使用随机搜索。具体来说,
from sklearn.model_selection import GridSearchCVgrid_search = GridSearchCV(estimator = classifier, param_grid = parameters, scoring = “accuracy”, cv = 10, n_jobs = -1)grid_search = grid_search.fit(X_train, y_train)
请注意,我们使用 10 重交叉验证。最后,网格搜索发现最佳参数如下图 3 所示,准确率为 63%😃。
图 3 使用“熵”的网格搜索第一轮结果
这样,我们可以使用这些参数在测试数据集上测试模型,或者执行第二轮网格搜索来微调参数。如果你想要第二轮,试试下面的参数。
parameters = {“max_depth”: [None], “max_features”: [3, 5, 7], ‘min_samples_split’: [8, 10, 12],‘min_samples_leaf’: [1, 2, 3], “bootstrap”: [True], “criterion”: [“entropy”]}
最终,在相同的参数下,我们得到了同样的 63%的准确率。这意味着我们从第一轮得到的结果已经是最佳的了👌。
图 4 使用“熵”的网格搜索第二轮结果
最后,让我们在测试数据上使用优化的模型。最后,我们得到了图 5 中的结果。巨大的成果。
图 5 基于熵优化射频的模型性能总结
注意上面我们使用熵作为分裂标准。你也可以用'基尼'。熵和基尼系数是衡量一个节点不纯程度的指标。有多个类的节点是不纯的,而只有一个类的节点是纯的。一般来说,决策树是通过递归分割变量或响应变量的特征来工作的。它旨在通过最大化每个节点的纯度来优化每个拆分。熵旨在最大化每次分裂所获得的信息内容,并且期望从分裂节点获得的信息越多,分裂就越好。另一方面,基尼系数衡量的是贴错标签的可能性。根据使用的标准,决策树结果可能会有所不同。如果你需要更多关于这个话题的细节,请随意阅读这篇文章。
现在让我们使用“G ini 作为标准执行相同的网格搜索,保持其余参数不变。第一轮之后,我们获得了 64%的准确率。
图 6 使用“基尼”的网格搜索第一轮结果
如果我们执行第二轮来微调上述参数,我们使用下面的最佳参数再次获得了 64%的准确度。
图 7 使用“基尼”的网格搜索第二轮结果
有了微调的参数,我们来测试模型。如图 8 所示,基于熵和基尼的模型之间存在微小的性能差异。
图 8 基于基尼系数优化射频的模型性能总结
8。外卖
我们使用相同的数据测试了 4 个不同的模型,逻辑回归、SVM(线性)、SVM (RBF)和随机森林。随机森林被证明具有 63%的准确率。使用网格搜索,我们将模型性能提高了 1–3%。
从商业角度来说,利用该模型的一种方法是针对那些预测不会签署定制入职流程贷款的人。这将有助于公司赢得更多客户,改善业务。
太好了!如果你觉得这篇文章有帮助,请随意点击👏s!如果您需要源代码,请随时访问我的Github页面🤞🤞🤞。
CPU 和 GPU 的集群性能比较
原文:https://towardsdatascience.com/comparison-of-clustering-performance-for-both-cpu-and-gpu-3f47fb3de872?source=collection_archive---------23-----------------------
一个基准:Scikit-Learn 和 TensorFlow-GPU 的 K 均值算法
(来源)
当你想对一个现象有更深的理解时,一种方法是将他们分组,这样更容易理解。例如,您可能想按标题观看电影,而另一个人可能想按类型观看。你决定如何对它们进行分组会引导你对它们有更多的了解。
在机器学习中,将数据点分成一定数量的组称为聚类。这些数据点没有初始标签。因此,聚类是将未标记的数据点分组,以更有意义的方式找出它们。
要深入了解聚类技术,请访问 麻省理工学院-edu 笔记。
在这篇文章中,目的是通过的执行时间来比较 Scikit-Learn (random,k-means++) 和 TensorFlow-GPU (k-means++,Tunnel k-means) 算法的集群性能,并通过提供相应的系统规格将它们打印在比较矩阵中。由于数据的内容不是本次基准研究的重点,因此所需的数据集将随机生成。
* [## CPU 和 GPU 的集群性能比较
当你想对一个现象有更深的理解时,一种方法是把他们分成小组来做…
www.commencis.com](https://www.commencis.com/thoughts/comparison-of-clustering-performance-for-both-cpu-and-gpu/)
k 均值聚类
k 均值聚类 的目的是以不重叠的方式将一些数量的观察值 n 划分成 k 数量的质心。数据点的数量在集群内部应该尽可能的一致,在集群外部应该尽可能的不同。更多理论解释,请访问本网页。
在这篇文章中,将测试三个不同的环境 (2 个不同的 CPU 驱动系统,1 个 GPU 驱动系统)。系统规格添加如下。
第一个 CPU 供电的系统规格:
处理器:英特尔(R)酷睿(TM)i7–8850h
处理器速度: 2.60 GHz
物理核心: 6
逻辑处理器: 12
物理内存(RAM): 64 GB第二 CPU 供电系统规格:
处理器:英特尔(R)酷睿(TM)i9–10900
处理器速度: 3.70 GHz
物理核心: 10
逻辑处理器: 20
物理内存(RAM): 256 GB (8 个 32GB DDR4 3000 MHz)GPU 驱动的系统规格:
处理器:英特尔(R)酷睿(TM)i9–10900
处理器速度: 3.70 GHz
图形处理器(GPU):NVIDIA GeForce RTX 2080 ti 352 位 11GB GDDR6 内存(2)
1.基于 CPU 的 K-均值聚类
中央处理器(CPU)是计算机的关键部件,大部分处理和计算都在其中进行。
对于进一步的编码部分,我们将使用 Python 编程语言(3.7 版 ) 。 PyCharm 和 Jupyter 笔记本 都可以用来运行 Python 脚本。为了便于使用,可以安装 Anaconda ,因为它本身包含了所有必需的 IDE 和重要包。
作为第一步,我们将安装 CPU 实施所需的软件包。
pip install psutil
pip install numpy
pip install matplotlib
pip install scikit-learn
安装完psutilnumpymatplotlibsk learn我们将导入**
***import platform
import time
import psutil as ps
import platform
from datetime import datetime
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans***
在开始集群之前,可以使用下面的代码片段检查 CPU 信息及其当前的 CPU 使用百分比。
***print("Physical cores:", ps.cpu_count(logical=False))
print("Logical cores:", ps.cpu_count(logical=True),"\n")
print("CPU Usage Percentages:", "\n")
for i, percentage in enumerate(ps.cpu_percent(percpu=True)):
print(f"CPU {i}: {percentage}%")
print("\n")
print(f"Current CPU Usage in Total: {ps.cpu_percent()}%")***
第一个 CPU 系统信息(图片作者提供)
第二 CPU 系统信息(图片由作者提供)
在带有参数 "init= random" 或 "init=kmeans++" 的函数中存在两种类型的 k-means 算法。下面首先测试“init = random”,代表随机选择 k 个观测值。****
“n _ clusters”参数代表算法将分割成的聚类数。当我们将“n _ clusters”分配到“100”中时,向算法发出信号,将所有数据点分配到最合适的 100 个质心中。为了能够控制每次运行的随机性,应将“ random_state ”参数设置为整数;否则,每次运行都会选择不同的随机组,这将很难与之前的输出进行比较。**
**kmeansRnd = KMeans(n_clusters=100, init='random',random_state=12345)**
设置集群参数后,生成 5 列 500 K 行的随机数。
**CPU_Test_1 = np.random.normal(size=(500000,5))**
现在,我们有 5 列和 500 K 行随机生成的数据。使用“ fit_predict ”函数,将通过输入名为“ CPU_Test_1 ”的数据来计算每个数据点的聚类中心和聚类指数。
**kmeansRnd.fit_predict(CPU_Test_1)**
使用 python 的“ plotly ”包添加样本的可视化和聚类数。在描述数据点和聚类的同时,该绘图脚本的结果被添加到帖子的后续部分中基于系统的结果的末尾。
**plt.scatter(CPU_Test_1[:,0], CPU_Test_1[:,1], s=1)plt.scatter(kmeans.cluster_centers_[:,0], kmeans.cluster_centers_[:,1], s=5, c="r")plt.title("K-means (Random) with Scikit Learn", "\n")plt.show()**
通过在我们的算法之外添加以下代码行,可以跟踪算法的执行时间。
**start_time = time.time()# ... *clustering* *code block* end_time = time.time()
print(end_time - start_time)**
1.1.使用 Scikit-Learn 的 k 均值(随机)聚类
sci kit Learn K-means—random算法以随机方式选择第一个中心聚类,与 k-means++算法相比,这可能会导致更高的聚类内方差。
第一个 CPU 驱动的系统结果:
算法执行时间: 2505.26 秒
聚类可视化:蓝点(数据点),红点(聚类)
Scikit Learn,K-means(随机)聚类 100 个聚类(图片由作者提供)
第二次 CPU 供电系统结果:
算法执行时间: 1395.10 秒
聚类可视化:蓝点(数据点),红点(聚类)
Scikit Learn,K-means(随机)聚类 100 个聚类(图片由作者提供)
1.2.使用 Scikit-Learn 的 K-means (kmeans++)聚类
sci kit Learn K-means—K means++算法以更符合逻辑的方式选择第一个中心聚类,这可以导致之后更快的聚类性能。
第一次 CPU 供电系统结果:
算法执行时间: 2603.74 秒
聚类可视化:蓝点(数据点),红点(聚类)
Scikit Learn,K-means (kmeans++)聚类 100 个聚类(图片由作者提供)
第二次 CPU 供电系统结果:
算法执行时间: 1384.73 秒
聚类可视化:蓝点(数据点),红点(聚类)
Scikit Learn,K-means (kmeans++)聚类 100 个聚类(图片由作者提供)
2。基于 GPU 的集群
tensor flow库是为海量数值计算而开发的。根据您环境中安装的版本,它支持 CPU 和 GPU。如果您希望启用您的 GPU,需要安装的版本是tensor flow-GPU。
**pip install tensorflow-gpu**
为了能够通过使用 TensorFlow 库来测试 GPU 信息的可用性,可以使用下面的代码片段。
**import tensorflow as tfconfig = tf.compat.v1.ConfigProto()
tf.config.list_physical_devices('GPU')**
(图片由作者提供)
使用以下脚本查看 GPU 信息后,可以打印更详细的设备信息,包括 CPU。
**from tensorflow.python.client import device_lib as dev_libprint (dev_lib.list_local_devices())**
(图片由作者提供)
2.1.使用 TensorFlow-GPU 进行 KMeansTF (kmeans++)聚类
tensor flow k-means算法通过迭代优化类内方差,路由随机产生的初始质心的负面影响。
通过安装以下 kmeanstf 包,可以使用支持 GPU 的 Tensorflow k-means 算法。
**pip install kmeanstf**
在安装了所需的包之后,下面的算法将在基于 GPU 的环境中运行。结果添加在系统规格之后。
**from kmeanstf import KMeansTFstart_time = time.time()kmeanstf = KMeansTF(n_clusters=100, random_state=12345)
GPU_Test = np.random.normal(size=(500000,5))
kmeanstf.fit(GPU_Test)end_time = time.time()
print('Kmeans++ execution time in seconds: {}'.format(end_time - start_time))**
GPU 驱动的系统规格:
算法执行时间: 219.18 秒
聚类可视化:蓝点(数据点),红点(聚类)
KMeansTF(kmeans++)100 个聚类的聚类(图片由作者提供)
2.2。 TunnelKMeansTF 使用 TensorFlow-GPU 进行聚类
隧道k-means算法具有在聚类之间实现非局部移位的能力,以为每个数据点找到最佳质心。
***start_time = time.time()kmeansTunnel = TunnelKMeansTF(n_clusters=100, random_state=12345)
GPU_Test = np.random.normal(size=(500000,5))
kmeansTunnel.fit(GPU_Test)end_time = time.time()
print('Tunnel Kmeans execution time in seconds: {}'.format(end_time - start_time))***
GPU 驱动的系统规格:
算法执行时间: 107.38 秒聚类可视化:蓝点(数据点),红点(聚类)**
100 个聚类的 TunnelKMeansTF 聚类(图片由作者提供)
3。最终比较矩阵
为了更清楚地理解算法的输出,生成了一个矩阵表。
系统特性与算法运行时间(图片由作者提供)
正如我们在比较矩阵中所观察到的,GPU 驱动的系统在执行时间方面具有独特的性能优势。
完整的实现代码和 Jupyter 笔记本在我的 GitHub 上都有。
非常感谢您的提问和评论!*
参考文献:
- Scikit 学习 K-means
- TensorFlow-GPU
- Python 包
来自不同地点的新冠肺炎数据的比较:正常化-展示-编程
原文:https://towardsdatascience.com/comparison-of-covid-19-data-from-different-locations-normalization-showcase-programming-93e7c222c56d?source=collection_archive---------49-----------------------
数据科学—新冠肺炎—可视化—编程
照片由 Thuy Chung Vuong 拍摄
有多少感染者还在我们附*的环境中,在我们国家,以及更远的邻国?
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
新冠肺炎疫情看起来像一场世界大战,波及全球 213 个国家和地区[worldometer.info],给世界带来死亡、疾病、恐惧、悲伤、灾难、混乱。每天都有大量的新冠肺炎数据流作为信息从与我们看不见的敌人——新型冠状病毒病毒斗争的前线流向我们。从这些数据中,我问了自己一个问题:
“有多少感染者还在我们附*的环境中,在我们的国家,以及更远的邻国?”
目前受感染患者的数量很重要;它有助于我们的生活、规划、工作和预防。出于这个动机,我将我的研究兴趣从数据的可视化,以及对未发现感染病例的估计,扩展到不同地点的活跃感染病例的比较。
在这篇文章中,我想和你分享我的方法“累积活跃案例的规范化”来分析来自多国的数据。
因为我的数据资源提供来自许多国家的数据,我可以在“高水*”上工作:比较来自世界各国的数据。然而,您也可以使用我的方法和我用 Python 编写的开源软件包来分析来自其他地理位置的数据。
我在这里展示了一些例子来展示我的开发方法。它们不是专业报告(如在、世卫组织、 CDC 、 RKI 中发现的),但它可能有助于我们理解新冠肺炎·疫情在海量数据之外正在发生的事情。
比较哪些新冠肺炎数据很重要?
在我们进行数据的比较之前,我想先介绍一下不同类型的新冠肺炎数据。它们是:
- 每日确诊感染病例数,即“新病例数”。
- 目前被感染的病人数量,即“活跃病例”(这里是“T7”)
- 估计的活动案例数,包括未发现的案例,可以通过我的 Vuong 算法或其他算法进行估计。
- 康复/出院患者人数。
- 死亡案例。
- 等等。
这些数据将显示为以下图表:
每日数据
累积数字
日数 y(t)是离散值,所以函数 y(t)是一个“时间序列”。我在这里使用 y[x]而不是 y (t),因此 x 是日期时间(参见 Python 文档:" DateTime 模块")。这使得以后的编程和绘图更加容易。
{y[x] / x =x0,x1,…,xn,…xN;xn 是日期时间}
累计数 s[k],是 y{x]的 k 个数之和。
表 1 以 y[x]为例,每日新增病例数及其累计数
表 1:y[x],s[k]的示例
累计活跃人数是当前感染患者的人数,重要信息,用于我们的计划、工作和预防感染。
这些数字很难找到,因为它们取决于许多参数:感染人数,由于无症状患者的问题,很难准确地检测到感染人数,康复病例和死亡病例,也很难准确地找到。但是我们可以通过多种方式获得累积的活动案例数:
- 这些数字直接来自专业机构的报告,如测试中心、医疗保健中心、疾病预防控制中心
- 可以使用 SIR 模型(例如,Brian Collins,新冠肺炎的动态建模)从感染病例中间接估计这些数字,或者使用我的模拟器和 Vuong 算法从每日确诊的新病例和死亡人数中估计感染病例。
如何比较不同国家的数据?
让我们来看看图 1 中的图表!
图 1:不同国家的活动累积案例图表。数据来源:【https://ourworldindata.org/coronavirus-source-data
它显示了来自不同国家的活动累积案例的图表。如果要把它们放在一起比较,有以下几个问题:
- 这看起来就像你在比较一头大象(世界数据)和一只熊(美国数据)或者一只兔子(德国数据)。这是比较的主要问题。
- 信号的振幅是未知的。2020 年 2 月 4 日,累计感染病例数增至 100 万,2020 年 4 月 15 日增至 200 万,2020 年 9 月 5 日增至 400 万,2020 年 6 月 15 日增至 800 万!
- 传染病例的产生是一个非线性系统。
- 每个县的 COVID 感染传播情况都不一样。
因此,我提出了一种对相关数据进行分析的方法:对累积的活动案例数据进行规范化。
对累积的活动案例数据进行规范化
该概念有以下步骤:
第一步:
每个国家的数据系列必须在同一时期,例如从 2020 年 1 月到 2020 年 6 月 30 日。
第二步:
对于每个国家,我们都会:
-我们存储累积数据字段 s[]。
我们搜索 s[k]的局部最大值 A
A = max (s[k],k =0,…N), N=域 s[k]的元素个数,range (s[])
-然后我们计算原始的标准化数据
sn[k] = s[k] /A
-我们可以使用原始计算 sn[k],但我建议使用百分比计算 sp{n],这样更容易理解。
sp[n] = 100 s[k] /A*
表 2 是一个示例,显示了对来自两个国家的 s[k]进行归一化的计算,因此来自 A 国的 S[k]的最大值为 10,来自 B 国的 S[k]的最大值为 500。
表 2:两个国家数据的计算
使用 covid 19-vuongsulator 进行数据分析
为了便于交流,我想打电话
“归一化活动案例数据图”到“归一化活动案例”,
“使用 Vuong 算法估计的活动案例的归一化数据的图表”到“归一化的 V-活动案例”,
为了解释标准化数据的图形,我使用多国模式(s .vuongsulator 命令)用 vuongsulator 生成了两个展示。
- 展示 1:来自一个国家的标准化活跃案例
- 展示 2:来自多国的标准化活跃案例:德国、意大利、瑞典、美国和世界。
展示 1:来自一个国家的标准化 V-active 案例
您可以从展示区 1“一个国家的标准化 V-活性病例”中了解以下信息(见图 2):
- 在 2004 年 4 月 1 日,活动案例相对于其最大值的百分比。
- 一个国家感染的爆发日期是图表达到最大值 100%的日期时间(见图 2)
- 在最*的日期和时间,你可以读到目前感染的病人的百分比,仍然存在于该国,14%。
图 2:展示案例 1:新冠肺炎数据分析【德】,数据来源:https://ourworldindata.org/coronavirus-source-data
**VuongSimulator comand for showcase 1:****./data/vmodel_testlist.csv
Germany** **$ python ./covid19-VuongSimulator.py -c ‘World’ -o test.png -n ./data/new_cases.csv -d ./data/new_deaths.csv -g 0.98 -r 14 -t 7 -s 76**
展示 2:来自多国(德国、意大利、瑞典、美国和世界)的标准化虚拟活动案例
您可以从展示区 2(图 3)获得以下信息:
- 不同国家的现行案例现已正常化。每个图在 100%时具有相同的最大值。
- 每个国家/地区的活动案例与其所在国家/地区的百分比最高为 100%。
- 我们可以在任何时间比较每个国家与其他国家的“地位”,当然只能用百分比来表示。
- 我们可以探索每个国家的突破日期,在那里图形达到最大值 100%。
- 我们可以发现减少的趋势,德国减少了 14%,意大利减少了 34%。百分比数字更容易理解为绝对值。
- 我们可以发现趋势待机,处于*台期,74%是美国。
- 我们可以发现瑞典突破的开始,因为图形在最*的日期时间达到了 100%的最大值。
- 我们看到世界图表在四月中旬有一个局部最大值,图表向上增加,在图表的最后一天达到 100%。我们可以期待下一个最大值,未来的第二波。
使用Vuong-Simulator,您可以根据您想要的国家列表比较不同国家的数据;有 212 个国家被感染来比较!(本文中的“安装和启动”)。
图 3:展示案例 2:新冠肺炎数据分析【多国】,数据来源:https://ourworldindata.org/coronavirus-source-data
**VuongSimulator comand for showcase 2:****./data/vmodel_testlist.csv
World,Germany,Italy,Sweden,United States****$ python ./covid19-VuongSimulator.py -c 'World' -o test.png -n ./data/new_cases.csv -d ./data/new_deaths.csv -g 0.98 -r 14 -t 7 -s 76**
多国标准化模式的 covid 19-vuongsulator
我已经在covid 19-vuongssimulator . py中实现了来自多国的归一化累积活动案例。模拟器只有命令行来减少对话框。项目的 wiki 中描述了命令参数。
VuongSimulator 需要一个国家列表来生成多图输出图表。这个列表是 CSV 文件。/data/vmodel_testlist.csv
默认设置:
**./data/vmodel_testlist.csv
World,Germany,France,Belgium,Sweden,United Kingdom,Russia,Brazil,United States**
要对其他国家的数据进行分析,您必须用普通的文本编辑器编辑国家列表
安装并启动
VuongSimulator 在我的帖子[ 1 、 2 ]和项目tavuong/covid 19-datakit的 wiki 中有详细的描述,所以我想在这里写一个简单的安装和快速的开始来制作我所做的 showcase,这可能会给你带来动力。
**$ github clone** [**https://github.com/tavuong/covid19-datakit.git**](https://github.com/tavuong/covid19-datakit.git)**$ pip install numpy****$ pip install Matplotlib****$ cd ~/covid19-datakit/****$ python ./covid19-VuongSimulator.py [by PC]****$ python3 ./covid19-VuongSimulator.py [by Raspberry PI]**
快速启动
为了在安装后快速启动,您可以使用下面的命令。它将显示一个橱窗,展示来自多国的标准化累积活动案例(图 4)。要制作另一个 showcase,您需要编辑 country-list 并重新启动命令。CSV 文件(。\data\new_cases 和。\data\new_deaths.csv)在文件夹里。\data ,从开源下载( 此处 )。
**VuongSimulator comand for Quick Start:****./data/vmodel_testlist.csv
World,Germany,France,Belgium,Sweden,United Kingdom,Russia,Brazil,United States****$ python ./covid19-VuongSimulator.py -c 'World' -o test.png -n ./data/new_cases.csv -d ./data/new_deaths.csv -g 0.98 -r 14 -t 7 -s 76**
图 4:快速入门:新冠肺炎数据分析【多国】,数据来源:https://ourworldindata.org/coronavirus-source-data
摘要
根据用于分析的 Vuong 算法的开发,以及对新冠肺炎数据的估计,我编写了具有多国新闻功能的软件包,从而开发了一种用于将累积的活跃感染病例的数据标准化的方法,人们可以比较来自不同地点的数据,并估计病毒的地理传播。如果我提出的方法能引起不同专业甚至专业机构用户的兴趣,那就太好了。
请不要犹豫,联系我咨询当前的开发,也许可以通过 Github 将您的模块贡献给我的开源和麻省理工学院许可的项目TAV uong/covid 19-datakit。
玩得开心!
综述鸣谢:简范博士教授
感谢支持和咖啡蛋糕的动力:我的妻子 Thi Chung Vuong
逻辑回归、决策树和随机森林模型预测中国红葡萄酒质量的比较
原文:https://towardsdatascience.com/comparison-of-the-logistic-regression-decision-tree-and-random-forest-models-to-predict-red-wine-313d012d6953?source=collection_archive---------11-----------------------
照片由金莎·艾利斯在 Unsplash 上拍摄
有监督机器学习模型预测红酒质量的比较
在接下来的项目中,我应用了三种不同的机器学习算法来预测葡萄酒的质量。我在项目中使用的数据集叫做 葡萄酒质量数据集 (具体来说就是“winequality-red.csv”文件),取自 UCI 机器学习库。
该数据集包含 1,599 个观察值和 12 个与葡萄牙“Vinho Verde”葡萄酒的红色变体相关的属性。每行描述了一瓶葡萄酒的物理化学性质。前 11 个自变量显示了关于这些特征的数字信息,最后一个因变量根据感官数据以 0(质量差的葡萄酒)到 10(质量好的葡萄酒)的范围揭示了葡萄酒的质量。
由于结果变量是有序的,我选择了逻辑回归、决策树和随机森林分类算法来回答以下问题:
- 哪种机器学习算法能够根据葡萄酒的理化性质最准确地预测葡萄酒的质量?
- 红酒的哪些理化性质对其品质影响最大?
对于下面的项目,我使用 R 编程语言来探索、准备和建模数据。
导入数据集
一旦工作目录设置好,数据集下载到我们的计算机,我就导入数据。
#Importing the dataset
data <- read.csv('winequality-red.csv', sep = ';')
str(data)
srt()函数的结果
使用 str() 函数,我们可以看到所有的变量类型都是数字,这是正确的格式,除了结果变量。我继续将因变量转换成二元分类响应。
#Format outcome variable
data$quality <- ifelse(data$quality >= 7, 1, 0)
data$quality <- factor(data$quality, levels = c(0, 1))
我选择的修改结果变量水*的任意标准如下:
- 大于或等于 7 的值将被更改为 1,表示优质葡萄酒。
- 另一方面,小于 7 的数量将被转换为 0,表示质量差或一般。
此外,我将变量“quality”的类型修改为 factor,表示变量是分类的。
探索性数据分析
现在,我着手开发一个基于数据的 EDA,以找到基本的见解,并确定变量之间的特定关系。
首先,我开发了一个描述性分析,其中我通过使用 summary() 函数收集了数据的五个数摘要统计信息。
#Descriptive statistics
summary(data)
数据中每个变量的五位数汇总值
该图显示了数据中每个变量的五位数汇总值。换句话说,使用该函数,我获得了数值变量的最小值和最大值、第一个和第三个四分位数、*均值和中值。此外,摘要显示了因变量级别的频率。
接下来,我开发了一个单变量分析,包括分别检查每个变量。首先,我分析了因变量。
为了分析结果变量,我开发了一个柱状图来可视化分类水*的频率计数。此外,我生成了一个频率表,以了解每个类别中不同级别的确切数量和价值百分比。
#Univariate analysis
#Dependent variable
#Frequency plot
par(mfrow=c(1,1))
barplot(table(data[[12]]),
main = sprintf('Frequency plot of the variable: %s',
colnames(data[12])),
xlab = colnames(data[12]),
ylab = 'Frequency')#Check class BIAS
table(data$quality)
round(prop.table((table(data$quality))),2)
分析因变量的频率图
在分析该图时,我声明数据集有大量的 0 值,这表明数据中有更多的行表示葡萄酒质量差。换句话说,数据是有偏差的。
此外,通过分析这些表,我声明数据中有 1,382 行被认为是劣质酒,217 行被认为是优质酒。同样,数据集包含大约 86%的 0 结果值和 14%的 1 结果值。
从这个意义上说,有必要考虑数据集是有偏差的。这就是为什么在将数据分成训练集和测试集时,必须遵循分层抽样方法的原因。
现在,我开始分析独立变量。为了进行分析,我选择为每个变量创建箱线图和直方图。这些可视化将帮助我们识别五个数字汇总值的位置、它拥有的异常值以及变量遵循的分布。
#Independent variable
#Boxplots
par(mfrow=c(3,4))
for (i in 1:(length(data)-1)){
boxplot(x = data[i],
horizontal = TRUE,
main = sprintf('Boxplot of the variable: %s',
colnames(data[i])),
xlab = colnames(data[i]))
}#Histograms
par(mfrow=c(3,4))
for (i in 1:(length(data)-1)){
hist(x = data[[i]],
main = sprintf('Histogram of the variable: %s',
colnames(data[i])),
xlab = colnames(data[i]))
}
用于分析数字自变量的箱线图
正如我们所见,箱线图显示了每个变量的均值、中值和四分位数测量值的位置,以及每个变量的取值范围。
通过分析箱线图,我得出结论,所有的变量都有异常值。此外,变量“残余糖”和“氯化物”是具有最大量异常值的变量。正如我们所看到的,在*均值和中间值附*有一个集中值,这反映在一个非常小的四分位范围(IQR)。
当我继续评估异常值时,这些信息将在数据准备阶段派上用场。
直方图用于分析数字自变量
可视化直方图,我确定了每个变量的模式。正如我们所看到的,在大多数分布中有一个右偏度。然而,变量“密度”和“pH”显示它们遵循正态分布。此外,我可以提一下,变量“残余糖”和“氯化物”的值范围很广,大多数观察结果都集中在图表的左侧。这种现象表明变量有大量的异常值。
最后,我开发了一个双变量分析来理解变量之间的关系。
#Bivariate analysis
#Correlation matrix
library(ggcorrplot)
ggcorrplot(round(cor(data[-12]), 2),
type = "lower",
lab = TRUE,
title =
'Correlation matrix of the red wine quality dataset')
相关矩阵来分析数值变量之间的关系
在图像中,我们可以看到自变量之间的正负关系。如矩阵所示,在“固定酸度”变量和变量“柠檬酸”和“密度”之间存在 0.67 的正相关。换句话说,随着“固定酸度”变量的增加,“柠檬酸”也会增加。同样,同样的概念也适用于“游离二氧化硫”和“总二氧化硫”变量之间的关系。
此外,我可以声明变量“固定酸度”和“pH”具有负线性相关性-0.68。这种关系表明,当葡萄酒的固定酸度增加时,葡萄酒的 pH 值降低。这个假设是正确的,因为我们知道这样一个事实,当一种成分的 pH 值降低时,意味着该元素变酸了。
数据准备
一旦我完成了 EDA,我就开始准备数据来开发预测模型。在项目的这一步,我集中精力寻找丢失的数据并评估异常值。
#Missing values
sum(is.na(data))
数据中缺失值数量的结果
既然我已经确定数据集不包含任何缺失值,我将继续处理异常值。
首先,我确定了每个变量的异常值数量。为了完成这一步,我创建并应用了一个识别异常值的特定函数。然后,我生成了一个数据帧来存储信息。此外,我使用 for 循环来收集和存储信息。
#Outliers
#Identifing outliers
is_outlier <- function(x) {
return(x < quantile(x, 0.25) - 1.5 * IQR(x) |
x > quantile(x, 0.75) + 1.5 * IQR(x))
}outlier <- data.frame(variable = character(),
sum_outliers = integer(),
stringsAsFactors=FALSE)for (j in 1:(length(data)-1)){
variable <- colnames(data[j])
for (i in data[j]){
sum_outliers <- sum(is_outlier(i))
}
row <- data.frame(variable,sum_outliers)
outlier <- rbind(outlier, row)
}
离群数据框架
正如我们所看到的,数据中的所有变量都有异常值。为了评估这些值,我遵循了一个标准,该标准规定我将接受在数据集的所有观察中异常值少于 5%的变量。
有必要提及的是,我并没有放弃离群值,因为它们代表并携带了关于数据集的必要信息。删除异常值会使我们的模型结果产生重大偏差。
#Identifying the percentage of outliers
for (i in 1:nrow(outlier)){
if (outlier[i,2]/nrow(data) * 100 >= 5){
print(paste(outlier[i,1],
'=',
round(outlier[i,2]/nrow(data) * 100, digits = 2),
'%'))
}
}
异常值百分比等于或大于 5%的变量
通过上面显示的代码,我能够识别出变量“残余糖”和“氯化物”分别有大约 10%和 7%的异常值。
此外,我继续输入这些变量的异常值。我选择用变量的*均值来改变异常值,因为正如我们在直方图中看到的,两个变量在*均值以下都有很大的集中值。因此,通过输入*均值,不会对数据的本质产生重大影响。
#Inputting outlier values
for (i in 4:5){
for (j in 1:nrow(data)){
if (data[[j, i]] > as.numeric(quantile(data[[i]], 0.75) +
1.5 * IQR(data[[i]]))){
if (i == 4){
data[[j, i]] <- round(mean(data[[i]]), digits = 2)
} else{
data[[j, i]] <- round(mean(data[[i]]), digits = 3)
}
}
}
}
建模
现在,我正确地排列了数据集,我开始开发预测红酒质量的机器学习模型。第一步是将数据分为训练和测试。由于数据是不*衡的,我着手开发一个分层抽样。我使用了 80%的代表优质葡萄酒的观察值(“质量”变量的一个结果)来*衡训练集。换句话说,在训练集中,因变量将具有相同数量的观察值 0 和 1。
#Splitting the dataset into the Training set and Test set
#Stratified sample
data_ones <- data[which(data$quality == 1), ]
data_zeros <- data[which(data$quality == 0), ]#Train data
set.seed(123)
train_ones_rows <- sample(1:nrow(data_ones), 0.8*nrow(data_ones))
train_zeros_rows <- sample(1:nrow(data_zeros), 0.8*nrow(data_ones))
train_ones <- data_ones[train_ones_rows, ]
train_zeros <- data_zeros[train_zeros_rows, ]
train_set <- rbind(train_ones, train_zeros)table(train_set$quality)#Test Data
test_ones <- data_ones[-train_ones_rows, ]
test_zeros <- data_zeros[-train_zeros_rows, ]
test_set <- rbind(test_ones, test_zeros)table(test_set$quality)
训练和测试集的因变量表
正如我们在图中看到的,训练集包含的观察值比测试集少。然而,训练集将被*衡以有效地训练模型。
现在我已经完成了这一步,我继续开发模型,并确定哪个模型可以准确预测红酒的质量。
逻辑回归
#Logistic Regression
lr = glm(formula = quality ~.,
data = training_set,
family = binomial)#Predictions
prob_pred = predict(lr,
type = 'response',
newdata = test_set[-12])library(InformationValue)
optCutOff <- optimalCutoff(test_set$quality, prob_pred)[1]y_pred = ifelse(prob_pred > optCutOff, 1, 0)
一旦使用训练集创建了模型,我就开始使用测试集数据预测值。
由于逻辑回归将提供概率值,我继续计算最佳分界点,这将把结果值分类为 1 或 0。
然后,利用获得的预测值,我继续开发一个混淆矩阵,我们可以用逻辑回归模型的预测值来可视化测试集值。
#Making the confusion matrix
cm_lr = table(test_set[, 12], y_pred)
cm_lr#Accuracy
accuracy_lr = (cm_lr[1,1] + cm_lr[1,1])/
(cm_lr[1,1] + cm_lr[1,1] + cm_lr[2,1] + cm_lr[1,2])
accuracy_lr
逻辑回归的混淆矩阵
可视化该表时,我声明该模型准确预测了 1,208 个值,这意味着该模型对 45 个观察值进行了错误分类。此外,我得出结论,该模型的准确率为 96.41%。
#ROC curve
library(ROSE)
par(mfrow = c(1, 1))
roc.curve(test_set$quality, y_pred)
逻辑回归的 ROC 曲线
此外,我继续开发一个 ROC 曲线,以了解该模型区分结果类别的能力。最后我发现曲线下面积(AUC)是 51.1%。
决策图表
现在我按照和以前一样的步骤。一旦使用训练集创建了模型,我就开始使用测试集数据预测值。
#Decision Tree
library(rpart)
dt = rpart(formula = quality ~ .,
data = training_set,
method = 'class')#Predictions
y_pred = predict(dt,
type = 'class',
newdata = test_set[-12])
此外,我继续生成混淆矩阵,在这里我们可以看到测试集值和决策树模型的预测值。
#Making the confusion matrix
cm_dt = table(test_set[, 12], y_pred)
cm_dt#Accuracy
accuracy_dt = (cm_dt[1,1] + cm_dt[1,1])/
(cm_dt[1,1] + cm_dt[1,1] + cm_dt[2,1] + cm_dt[1,2])
accuracy_dt
决策树的混淆矩阵
可视化该表后,我声明该模型准确预测了 873 个观察值,表明该模型错误分类了 380 个值。此外,我发现该模型的准确率为 69.67%。
#ROC curve
library(ROSE)
roc.curve(test_set$quality, y_pred)
决策树的 ROC 曲线
然后,根据 ROC 曲线,我得到了曲线下面积(AUC ),其值为 81%。
随机森林
最后,我继续使用训练集创建随机森林模型,并使用测试集数据预测值。
#Random forest
library(randomForest)
rf = randomForest(x = training_set[-12],
y = training_set$quality,
ntree = 10)#Predictions
y_pred = predict(rf,
type = 'class',
newdata = test_set[-12])
现在,我通过创建一个混淆矩阵,用随机森林模型的预测值来可视化测试集值。
#Making the confusion matrix
cm_rf = table(test_set[, 12], y_pred)
cm_rf#Accuracy
accuracy_rf = (cm_rf[1,1] + cm_rf[1,1])/
(cm_rf[1,1] + cm_rf[1,1] + cm_rf[2,1] + cm_rf[1,2])
accuracy_rf
随机森林的混淆矩阵
通过评估该表,我证明了该模型准确预测了 991 个值,这意味着该模型错误分类了 262 个观察值。此外,还得出了该模型的准确率为 79.09%。
#ROC curve
library(ROSE)
roc.curve(test_set$quality, y_pred)
随机森林的 ROC 曲线
最后,通过 ROC 曲线,我获得了 83.7%的 AUC 值。
可变重要性
此外,我通过计算具有最高精确度的模型的变量重要性来回答项目的第二个问题。换句话说,我计算了逻辑回归模型的变量重要性。
#Variable importance
library(caret)
varImp(lr)
逻辑回归的可变重要性
通过分析结果,我宣布这个模型最重要的变量是“酒精”,其次是变量“硫酸盐”和“固定酸度”。
此外,我进行了一项调查,以了解这些成分对红酒质量的影响。我发现硫酸盐是葡萄酒中的一种成分,这种成分决定了饮料的新鲜度。从这个意义上来说,不含硫酸盐或含少量硫酸盐的葡萄酒通常保质期较短。换句话说,硫酸盐对葡萄酒的寿命有更多的控制,因为它有助于确保葡萄酒在打开时保持新鲜和干净。另一方面,酒精成分对葡萄酒的质量也起着重要的作用。酒精将有助于*衡葡萄酒的坚硬和酸的味道,使葡萄酒的坚硬和柔软的特性相互联系。
正如我们所分析的,逻辑回归模型解释了实际的理论事实。关于优质葡萄酒的基本成分的调查包括了模型中必要的变量。出于这个原因,变量“酒精”和“硫酸盐”对模型非常重要,因为这些元素将是指示葡萄酒质量好坏的重要组成部分。
结论
在获得不同机器学习算法的结果后,我声明逻辑回归模型在预测红酒质量方面显示出更高的准确性。该模型的准确率为 96.41%,能够正确预测 1209 个值,这意味着该模型的误分类误差为 3.59%。
另一方面,通过分析 ROC 曲线,我声明模型表现不如预期。通过评估曲线下面积(AUC = 51.1%),我将 ROC 曲线标记为失败曲线。换句话说,该模型不能识别不同的类别,这表明该模型具有低性能。出于这个原因,我得出结论,即使该模型在预测测试集值方面有很好的准确性,但它在快速识别真正的正值方面的速度很慢。
此外,通过分析其他 ROC 曲线,我发现随机森林确实具有最佳性能,获得了 83.7%的曲线下面积。这意味着尽管随机森林模型在三个模型中没有显示出最高的准确性,但它通过比逻辑回归更好地检测因变量的不同类别而具有最佳性能。
此外,通过逻辑回归模型,我进一步确定了哪些理化性质对红酒的质量影响最大。我发现“酒精”、“硫酸盐”和“固定酸度”是模型中影响最大的变量。就此而言,如果这些变量之一发生变化,模型的结果将受到强烈影响。
使用 Python 进行数据采集和分析
原文:https://towardsdatascience.com/competitive-price-data-scraping-and-analysis-using-python-a1f34758155?source=collection_archive---------27-----------------------
使用数据收集的竞争性定价
数据 抓取是一种从互联网上检索大量数据的技术。这个技巧在竞争 定价中非常有用。为了确定我们产品的最佳价格,我们可以比较市场上的类似产品。这些价格变化很大。因此,在这篇博客中,我将展示我们如何丢弃关于特定产品的数据。
最常见的数据抓取技术是使用 BeautifulSoup 。它提取页面的 html 并将其存储为非结构化数据。我们必须把它转换成结构化的格式。
让我们导入我们将需要的所有必要的库:
import requests
from fake_useragent import UserAgent
import pandas as pd
import bs4
我们提取的数据是非结构化数据。所以我们将创建空列表,以结构化的形式存储它们,
products=[] #List to store name of the product
prices=[] #List to store price of the product
ratings=[] #List to store rating of the product
specifications = [] #List to store specifications of the product
df=pd.DataFrame()
创建用户代理。参考此链接https://pypi.org/project/fake-useragent/
user_agent = UserAgent()
将产品名称作为输入。提取的数据将与该产品相关。
product_name = input("Product Name- ")
为了从产品列表的多个页面中提取数据,我们将使用一个 for 循环。该范围将指定要提取的页数。
for i in range(1,11):
url = "[https://www.flipkart.com/search?q={0}&page={1](https://www.flipkart.com/search?q={0}&page={1)}" url = url.format(product_name,i) ## getting the reponse from the page using get method of requests module
page = requests.get(url, headers={"user-agent": user_agent.chrome}) ## storing the content of the page in a variable
html = page.content ## creating BeautifulSoup object
page_soup = bs4.BeautifulSoup(html, "html.parser") for containers in page_soup.findAll('div',{'class':'_3liAhj'}):
name=containers.find('a', attrs={'class':'_2cLu-l'})
price=containers.find('div', attrs={'class':'_1vC4OE'})
rating=containers.find('div', attrs={'class':'hGSR34'})
specification = containers.find('div', attrs {'class':'_1rcHFq'})
products.append(name.text)
prices.append(price.text)
specifications.append(specification.text) if type(specification) == bs4.element.Tag else specifications.append('NaN')
ratings.append(rating.text) if type(rating) == bs4.element.Tag else ratings.append('NaN')
df = pd.DataFrame({'Product Name':products,'Price':prices, 'specification':specifications, 'Rating':ratings})
为了从 soup 中提取数据,您需要指定要从中检索数据的 html 标签。你可以在网页上使用 inspect 元素。
上述代码将以结构化格式存储数据。当您打印 df 时,您将获得:
df.head()
清理数据
因为所有的产品都是一样的,我们可以把它们写成“瓶子”。
df['Product Name'] = 'bottle'
df.head()
同样,我们可以找到不同产品的数据。
现在,我们将从 Price 中删除符号,并清理 specification 列。
df[‘Price’] = df[‘Price’].str.lstrip(‘₹’)
df[‘Price’] = df[‘Price’].replace({‘,’:’’}, regex=True)
df.head()
df[‘Pack’], df[‘color’] = df[‘specification’].str.split(‘,’, 1).str
del df[‘specification’]
df.head()
我们得到的数据的一些基本分析
绘制箱线图
import numpy as np
import seaborn as sns
df[‘Price’] = df[‘Price’].astype(np.float)
sns.boxplot(x=df[‘Price’])
正如我们所看到的,在价格范围非常高的地方有一些异常值。
绘制条形图
sns.barplot(x=df[‘Price’], y=df[‘color’])
我们可以观察到某种颜色的价格是如何变化的。多种颜色的行是成包的,如 4 个一包或 6 个一包等。
df[‘Rating’] = df[‘Rating’].astype(np.float)
sns.barplot(x=df[‘Rating’], y=df[‘color’])
我们还可以观察到,颜色对产品的评级几乎没有影响。
sns.barplot(x=df[‘Rating’], y=df[‘Price’])
sns.lineplot(x=df[‘Rating’], y=df[‘Price’])
从这里我们可以得出结论,价格较低的产品在某种程度上有较高的收视率。
谢谢大家,我希望你们对我们如何使用数据收集来获得有竞争力的价格有所了解。除了博客中提到的,你还可以尝试不同的 EDA 技术。
所有高效网络模型的完整架构细节
原文:https://towardsdatascience.com/complete-architectural-details-of-all-efficientnet-models-5fd5b736142?source=collection_archive---------0-----------------------
让我们深入探究所有不同高效网络模型的架构细节,并找出它们之间的不同之处。
乔尔·菲利普在 Unsplash 上的照片
我在一次 Kaggle 竞赛中翻阅笔记本,发现几乎每个人都在使用 EfficientNet 作为他们的主干网,这是我之前从未听说过的。它是由谷歌人工智能在这篇论文中介绍的,他们试图提出一种如其名称所示更有效的方法,同时改善艺术效果的状态。一般来说,模型做得太宽、太深,或者分辨率太高。增加这些特征最初有助于模型,但是它很快饱和,并且所制作的模型只是具有更多的参数,因此效率不高。在 EfficientNet 中,它们以更有原则的方式进行扩展,即逐渐增加所有内容。
模型缩放。(a)是一个基线网络示例;(b)-(d)是仅增加网络宽度、深度或分辨率的一个维度的传统缩放。(e)是我们提出的复合缩放方法,它以固定的比例统一缩放所有三个维度。
不明白发生了什么?别担心,一旦你看到这个建筑,你就会明白的。但首先,让我们看看他们用这个得到的结果。
模型尺寸与 ImageNet 精度
由于参数数量少得多,模型系列是有效的,并且还提供了更好的结果。现在我们已经看到了为什么这些可能成为标准的预训练模型,但是缺少了一些东西。我记得莱米·卡里姆的一篇文章,他展示了预训练模型的架构,这对我理解它们和创建类似的架构帮助很大。
[## 插图:10 个 CNN 架构
普通卷积神经网络的编译可视化
towardsdatascience.com](/illustrated-10-cnn-architectures-95d78ace614d)
由于我在网上找不到这样的一个,我决定理解它并为你们所有人创建一个。
共有的事物
首先,任何网络都是它的主干,然后开始所有的架构实验,这在所有八个模型和最终层中都很常见。
此后,它们中的每一个都包含 7 个块。这些模块还包含不同数量的子模块,随着我们从效率 0 提高到效率 7,子模块的数量也会增加。要查看 Colab 中模型的层,请编写以下代码:
!pip install tf-nightly-gpuimport tensorflow as tfIMG_SHAPE = (224, 224, 3)
model0 = tf.keras.applications.EfficientNetB0(input_shape=IMG_SHAPE, include_top=False, weights="imagenet")tf.keras.utils.plot_model(model0) # to draw and visualize
model0.summary() # to see the list of layers and parameters
如果你计算一下 EfficientNet-B0 中的总层数,总数是 237,而在 EfficientNet-B7 中,总数是 813!!但是不要担心,所有这些层都可以由下面显示的 5 个模块和上面的茎制成。
我们将使用 5 个模块来构建架构。
- 模块 1 —用作子模块的起点。
- 模块 2 —该模块用作除第一个模块之外的所有 7 个主模块的第一个子模块的起点。
- 模块 3 —该模块作为跳接连接至所有子模块。
- 模块 4 —用于组合第一个子块中的跳跃连接。
- 模块 5 —每个子模块以跳接方式连接到其前一个子模块,并使用该模块进行组合。
这些模块被进一步组合以形成子块,这些子块将以某种方式在块中使用。
- 子块 1 —仅用作第一个块中的第一个子块。
- 子块 2 —它被用作所有其它块中的第一个子块。
- 子块 3 —用于所有块中除第一个以外的任何子块。
到目前为止,我们已经指定了将被组合以创建高效网络模型的所有内容,所以让我们开始吧。
EfficientNet-B0
高效网络架构-B0。(x2 表示括号内的模块重复两次)
效率网络-B1
高效网络架构-B1
B2 效率网
其架构与上述模型相同,它们之间的唯一区别是特征图(通道)的数量不同,这增加了参数的数量。
B3 效率网
高效网络架构-B3
高效网络-B4
高效网络架构-B4
高效网络-B5
高效网络 B5 的架构
B6 效率网
B6 高效网络的架构
B7 效率网
B7 高效网络的架构
很容易看出所有模型之间的差异,他们逐渐增加了子块的数量。如果你理解这些架构,我会鼓励你选择任何一个模型,打印出它的概要,并浏览一遍以更彻底地了解它。下表显示了卷积运算的内核大小以及 EfficientNet-B0 中的分辨率、通道和层。
内核大小、分辨率、通道和层数信息。
此表包含在原始文件中。这个决议对整个家庭来说是一样的。我不知道内核大小是变化还是保持不变,所以如果有人知道,请回复。层数已经在上面的图中示出。频道数量各不相同,它是根据从每个型号的摘要中看到的信息计算出来的,如下所示()如果您使用的是移动设备,则需要在横向模式下查看。)
╔═══════╦══════╦══════╦══════╦══════╦══════╦══════╦══════╗
║ Stage ║ B1 ║ B2 ║ B3 ║ B4 ║ B5 ║ B6 ║ B7 ║
╠═══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣
║ 1 ║ 32 ║ 32 ║ 40 ║ 48 ║ 48 ║ 56 ║ 64 ║
║ 2 ║ 16 ║ 16 ║ 24 ║ 24 ║ 24 ║ 32 ║ 32 ║
║ 3 ║ 24 ║ 24 ║ 32 ║ 32 ║ 40 ║ 40 ║ 48 ║
║ 4 ║ 40 ║ 48 ║ 48 ║ 56 ║ 64 ║ 72 ║ 80 ║
║ 5 ║ 80 ║ 88 ║ 96 ║ 112 ║ 128 ║ 144 ║ 160 ║
║ 6 ║ 112 ║ 120 ║ 136 ║ 160 ║ 176 ║ 200 ║ 224 ║
║ 7 ║ 192 ║ 208 ║ 232 ║ 272 ║ 304 ║ 344 ║ 384 ║
║ 8 ║ 320 ║ 352 ║ 384 ║ 448 ║ 512 ║ 576 ║ 640 ║
║ 9 ║ 1280 ║ 1408 ║ 1536 ║ 1792 ║ 2048 ║ 2304 ║ 2560 ║
╚═══════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╝
Medium 没有任何制作表格的格式,所以如果你想创建如上的表格,你可以从这个站点创建 ASCII 表格。
在结束之前,我再次附上了其研究论文中的另一张图片,该图片显示了其相对于其他先进技术的性能,并且还减少了所需的参数数量和触发器数量。
来源
如果您想创建像这样的高级 CNN 架构,或者在理解所使用的任何层或术语方面有问题,请不要担心,我已经写了一篇文章来解决这些问题。
[## 超越 Tensorflow 2 中的标准 CNN
使用复杂的架构生成更深层次的模型,并了解不同的层,从而使模型更好。
towardsdatascience.com](/beyond-the-standard-cnn-in-tensorflow-2-a7562d25ca2d)
你想看看 EfficientNet 如何在 Kaggle 挑战赛上与模特们一较高下吗,你可以看看这篇文章。
[## EfficientNet 应该是 goto 预训练模型或…
比较不同预训练模型的时间和准确性,并最终创建一个集成来提高结果。
towardsdatascience.com](/efficientnet-should-be-the-goto-pre-trained-model-or-38f719cbfe60)
完整的数据工程师词汇
原文:https://towardsdatascience.com/complete-data-engineers-vocabulary-87967e374fad?source=collection_archive---------10-----------------------
阿里安·达尔维什在 Unsplash 上拍摄的照片
数据工程
数据工程师必须知道的 10 个单词以内的概念
更新—建议由 乔治*阿克塞尔【弗尔兰】 和 妮莎 。最*更新—2020 年 7 月 15 日*
这些年来,我使用了许多这样的技术处理数据库、数据仓库、构建数据管道、使用 ETL 框架和处理大数据——甚至处理电子表格。所有这些技术都需要数周的学习和数月的实践来完善。
我认为用 10 个字来总结或介绍一项技术会非常有趣。我在这里列出了大约 150 个概念和技术,以及不超过 10 个字的解释。显然,这个列表受限于我的领域知识,但我认为如果你想在 2020 年成为一名数据工程师,这是一个很好的列表。
几乎所有的链接都指向该技术的主页或者一篇有趣的博客文章。使用名称中嵌入的链接。开始了。
A a
—交易强制执行数据库属性;原子性、一致性、隔离性、耐久性
原子性——如果(多步任务中的)一步失败,则整个事务失败
Avro —紧凑、面向行、基于 JSON 的数据格式
阿兹卡班 — LinkedIn 的 Hadoop 作业批处理调度器
气流——Airbnb 基于 DAG 的可编程作业调度器。非常受欢迎的 Apache 项目
解析 函数 —对一组行进行运算的聚合函数
B b
大数据 —大到传统系统无法处理的程度
BI —从数据中获取最佳信息的技术和流程
—一次完成多项任务,即加载 100M 条记录******
BigQuery —谷歌的无服务器数据仓库,与 Redshift 和 Azure DW 竞争
BigTable —由 Google 提供的千兆级 NoSQL 数据库
C c
Cassandra —分布式 NoSQL 数据库因其列存储功能而广受欢迎
CTE —可以在 SQL 中通过名称引用的结果集缓存
缓存 —暂时存储数据以备将来再次使用
面向列的数据库 —在磁盘上连续存储列值的存储器
云作曲 —谷歌的气流实现
立方体 —多维数据;数据仓库中使用的术语
目录 —具有管理和搜索能力的元数据的组织
云功能 —谷歌的无服务器计算选项,如 AWS Lambda
D d
DynamoDB—Pb 级键值,AWS 文档数据库
德鲁伊 —分布式柱状数据存储
Drill —用于 Hadoop、NoSQL 数据库中非关系、JSON、嵌套数据的 SQL
—谷歌大规模专有互动查询引擎****
分布式处理 —在不同的计算单元上拆分任务和处理,以获得更快的结果
DataFrame —关系数据库表,类似编程语言中的构造
DW —用于业务报告和分析的真实数据存储的单一来源
DAG —没有循环依赖关系的依赖关系图—在编排引擎中使用
数据流 —谷歌托管数据流水线解决方案
data prep—Google 的数据准备(清理、扯皮等。)解决方案
Dataproc —谷歌完全托管的 Spark/Hadoop 产品
仪表板 —用于跟踪绩效、KPI 等的可视化设置。
数据字典 —揭示数据源结构和用途的深度元数据
数据停机 —数据不完整、错误、丢失或不准确的时间
数据集市 —数据仓库的子集,通常用于特定的业务功能
维度 —数据的描述符或分类器
—SRE 关于数据库可靠性的一个分支****
数据保管人 —万物数据的拥有者
DataVault —数据仓库设计方法论
DBT —基于 SQL 的数据流水线和工作流解决方案
Docker —OS 级虚拟化成型容器
E e
elastic search—事实上的全文搜索引擎
EMR—AWS 上的 MapReduce
丰富 —用更多数据丰富数据的过程
—从源提取,转换,加载到目的地****
ELT —从源提取,加载到目的地并转换
ER 图 —可视化数据库实体间关系的图
麋鹿 —事实上的开源应用日志处理&监控解决方案
F f
水槽 —面向事件流数据的大规模数据流水线
—数据流分布式处理引擎****
*面文件——通常是文本或二进制文件
事实 —业务流程的度量,例如总销售额
故障转移 —从故障机器转移到正常工作的机器
G g
胶水—AWS 的大规模无服务器 ETL、数据流水线解决方案
金录 —单一来源的真相
H h
Hadoop —由 MapReduce、YARN 和 HDFS 组成的大数据处理框架
Hive —类似 SQL 的查询引擎,用于访问存储在 Hadoop 生态系统上的数据
HBase —运行在 Hadoop 之上的非关系型分布式数据库
HDFS — Hadoop 的分布式文件系统
我我
influx db—非常流行的时间序列数据库
摄取 —将数据插入系统,即数据摄取
集成 —汇集多个数据源
—内存存储,内存计算,即不在磁盘上****
J j
JSON—互联网上事实上的数据传输格式
K K
卡夫卡 — LinkedIn 的分布式流媒体框架
Kinesis — AWS 的托管卡夫卡式流媒体服务
—ETK 堆栈中的监控&可视化解决方案****
键值存储 —数据存储在类似字典或散列表的结构中
Kubernetes——谷歌的容器编排服务,爱称 K8s
L L
Looker —谷歌最新基于浏览器的商务智能工具收购
Luigi—Spotify 的作业编排引擎
—原始存储的所有业务数据****
λ——AWS 的 FaaS 发售——非常受欢迎
Logstash —记录 ELK 堆栈中的分析解决方案
谱系——从原始到加工、再加工到最终的旅程
米米
MySQL——非常流行的开源关系数据库
【MongoDB——非常流行的开源 NoSQL 数据库
MariaDB —原 MySQL 团队维护的 MySQL 的 fork
MapReduce —分布式计算的编程模型;Hadoop 的基石
MLlib — Spark 的机器学习库
元数据库 —流行的开源数据可视化解决方案
MDM —对关键业务数据进行单点管理
MDX—MS SQL Server 对 OLAP 查询的特性
测量 —参见**事实**
物化视图 —查询结果集作为数据库对象持久存储在磁盘上
MPP —大量处理器并行协同计算
元数据 —参见**目录**
N n
NoSQL——一组数据库技术,不仅仅是关系数据库
Neo4j —事实上的面向图形的数据库
Nomad —哈希公司的调度解决方案
接*实时——几乎实时,仅因物理限制而有延迟
规范化 —关系数据库中的组织概念
O o
ORC —高性能开源柱状存储格式
Oozie —基于 DAG 的 Hadoop 作业工作流调度程序
OLAP —没有事务的分析处理,通常用于数据仓库
OLTP —事务处理,具有 ACID 属性
ODS —运营数据存储,目的类似于 DW
P p
PostgreSQL —程序员最爱的开源数据库
PostGIS—PostgreSQL 中地理空间数据支持的扩展
Percona —提供 MySQL、MongoDB 等的分支。具有高级功能
—事实上的开源柱状存储格式****
Protobuf —
py Spark—Spark 上的 Python 包装器
Presto —脸书开源分布式查询引擎
Plotly —数据科学家& ML 工程师事实上的可视化库
流水线 —转换&传输数据的一系列过程&计算
分区 —将一张表拆分成多个部分,以查询更少的数据
熊猫—Python 中事实上的数据处理库
发布/订阅 —发布、订阅事件流处理的模型
Python —数据工程、数据科学的事实语言
问
查询引擎 —对数据集执行查询的软件
查询优化器 —优化器&重写 SQL 查询的数据库组件
查询计划 —查询引擎执行查询的执行计划
查询成本 —运行一个查询在处理方面的成本
R
RDS—AWS 的托管关系数据库服务
【RBAC】—基于工作角色和某人权限的系统访问
RabbitMQ —事实上的消息代理。
红移 —最受欢迎的托管、Pb 级数据仓库解决方案
Redis —面向应用的流行缓存解决方案
Redash —用于基本报告和分析的出色可视化工具
复制 —制作数据库的冗余副本,用于故障转移、负载分配
—火花内主要加工构造。了解更多在这里。****
面向行的数据库——数据记录/行级数据连续存储在磁盘/内存中
S s
S3 —最受欢迎的云存储服务,由 AWS 提供
SQL — 数据说的语言
Sqoop —与 Hadoop 之间的批量数据传输
爽快 —谷歌的压缩器/解压器
Spark —事实上的 SQL 支持的大数据处理引擎
风暴 —开源、实时计算引擎
超集 — Airbnb 基于网络的数据可视化& BI 工具,孵化于 Apache
分片 —在多台机器上拆分和存储一个数据库
存储引擎 —数据库的数据存储操作层
星型模式 —流行的数据仓库设计方法论。在这里阅读更多
雪花模式 —流行的数据仓库设计方法论。在这里阅读更多
SCD —随时间缓慢变化的数据类别值,如居住城市
单一真实来源 —被认为反映业务真实情况的数据源
结构化数据 —遵循某种预定义模式或格式的数据
半结构化数据 —不遵循正式结构,但仍包含其他标记
SRE——谷歌对可靠性工程师 DevOps 的重塑
T t
terra form——哈希公司事实上的基础设施即代码产品
—支持跨语言开发的框架****
U u
非结构化数据 —没有模式或预定义结构的数据
V v
Vertica——相当流行的数据仓储 so
VoltDB —具有序列化事务的内存数据库
金库 —哈希公司的秘密经理
视图—由 SQL 查询表示的未持久化的数据库对象
W w
—清理数据,为分析做好准备****
窗口函数 —与当前行相关的多行 SQL 计算
X x
这里什么都没有。或许有。
Y y
YARN—Hadoop 生态系统的资源管理器(用于 MapReduce 和 Spark)
Z z
—集中配置管理服务****
完整的数据科学项目:业务理解
原文:https://towardsdatascience.com/complete-data-science-project-part-1-business-understanding-b8456bb14bd4?source=collection_archive---------8-----------------------
完整的数据科学项目
根据全球管理挑战预测在证券交易所上市的生产公司订单数量的项目。
由卢克·切瑟在 Unsplash 上拍摄的照片
这是数据科学项目系列的第一篇文章。我想介绍一个机器学习世界的指南。我将描述基本的理论假设以及实际的解决方案。无论你是一个初学者,你只是对人工智能的主题感兴趣,还是你已经是一名数据科学家,我认为我的文章将会影响到你们每个人,并激励你们继续工作。根据跨行业数据挖掘标准流程 :
1 的方法,每篇文章都被划分为数据科学流程阶段。业务理解 —你在这里
2。数据理解
3。数据准备
4。造型
5。评价
6。部署
数据科学项目生命周期,图片由作者提供,灵感来自来源
数据挖掘的跨行业标准流程没有任何硬性框架。这个过程是高效的、迭代的,当我们发现我们犯了错误或者没有考虑到某些事情时,我们总是可以回到前面的步骤。你会在 GitHub 上找到整个项目。
BATMAJA 团队和全球管理挑战徽标,图片由作者提供,GMC 徽标由来源提供,经作者许可编辑
该项目基于国际全球管理挑战竞赛,预测在证券交易所上市的生产公司的订单数量。我代表 BATMAJA 学生队,和他们一起进入了全国决赛。这是一个基于商业模拟的竞赛。这些团队被分成不同的小组,投资结果(即市场价值和支付的股息)最高的团队进入下一阶段。该公司在欧洲市场、北美自由贸易区和互联网上生产和销售 3 种不同的产品。所有的团队都是从同一个故事开始的。许多因素会影响这些市场的订单数量。
将业务理解作为数据科学项目生命周期的一个阶段,图片由作者提供,灵感来自来源
业务理解 —这个阶段包括对问题的非常精确的说明,以及评估目标实现情况的方法。
Problem➜模型➜解
我们的目标是创建一个问题模型,然后用它来寻找解决方案。模型应该足够精确,以使解决方案有意义,否则,我们会做太多的假设和*似,这将使解决方案远离真实和无意义。需要补充的是,模型并不等同于问题,而只是现实的一种表象。因此,模型应该足够精确以找到解决方案,并且应该足够通用以不包括不相关的变量[ 1 ]。问题的正确解决涉及到对问题的正确认识。真正的商业问题很少是显而易见的。因此,为了使解决方案被认为是可接受的,有必要对项目采用迭代方法,对各个阶段进行多次重复。数据科学家应该有创造力和领域知识来正确地表述问题。我们应该问自己问题,这将导致预期的价值。
~确切的商业目的是什么?
创造一个机器学习模型本身并不是目的。该模式应该为企业增加价值,创造新的利润或降低成本。如果有任何解决方案,应该核实这个问题目前是如何解决的。提出的问题可以公式化为一个或多个机器学习模型:分类、回归或其他[ 2 ]。最后,有必要决定将使用哪些指标来评估模型。该指标还允许您比较模型,并确定模型是欠拟合还是过拟合。好了,这不是过程的结束,还有一步。写下所有的假设并检查它们。这将允许您在设计的早期阶段就发现错误。
GMC 的基本规则,授权图像
让我们继续了解全球管理挑战。参赛队伍被分成小组,最多有 8 支队伍参赛。每个小组从相同的场景开始,这些是公司在前 5 个季度的活动报告。然后,团队根据他们公司的历史,决定公司下一季度的运营方式。做出决策后,每个团队都会收到一份报告,其结构与历史报告相同。在训练阶段团队做出 3 个决定,在每个后续阶段已经 5 个决定。在比赛的第第一阶段中,两支最佳队伍进入下一阶段。在比赛的第二阶段有 8 个小组和最佳小组来自每个小组进入全国决赛。最佳队伍进入世界决赛。
表格-你的决定,作者图片
让我们转到报告结构,团队以电子表格的形式收到报告。报告的第一部分包含根据团队决策在上个季度做出的决策,除非并非所有决策都是可能的,并且被系统纠正(标记为*)。团队在截止日期前在专用*台上做出决策。
工作表—资源和产品,按作者分类的图片
报告的下一部分涉及资源和产品,因此公司在工厂和销售部门的活动。右边是这些市场的产品销售信息。这里有一个预测订购产品数量的问题。如果公司生产了太多的产品,就需要储存这些产品,这就带来了成本,或者说是为生产那些未来才销售出去的产品买单。此外,这种情况会在未来造成进一步的问题,因为必须生产的产品比以前设想的要少。问题比较多,但是这样的情况降低了公司的营业利润。相反的例子是相对于订单数量而言,生产的产品太少。客户将不得不等待产品,这将导致公司形象的损失。
工作表—财务报表,按作者分类的图像
然后我们有财务报表,类似于上市公司的财务报表。在这一点上,我们看到了这种竞争的要求有多高,以及它与管理层做出的实际决策有多接*。决策必须结合生产、广告、销售和财务的共同利益。
工作表-按作者分组信息、图像
报告的最后一部分是集团的信息。我们会发现在这个虚构的世界里情况是怎样的,在群体里情况又是怎样的。关注我们竞争对手的行动,包括他们产品的价格,这很重要。只要额外付费,我们就可以收到关于每个球队的市场份额和广告的信息。我们已经有了一些竞争的基础。
按作者分类的业务理解类型、图像
这不是我第一次参加比赛,所以我有一种直觉(经验)订单数量取决于什么。此外,我的团队成员拥有经济、金融、管理和生产或证券交易所运作的领域知识。我们使用了组织者网站上的手册和国际博客中包含的信息,其中提出了解释变量。在下一篇文章中,我将介绍这个项目选择了哪些变量。一个现实的项目远不是一门课程的一部分,也不是 Kaggle 上的一场比赛。在这里,我们没有给定的变量,我们经常感觉自己好像是在雾里去目标。这很令人兴奋,这也是我热爱数据科学的原因。
下期 帖子 见!
参考
M. Michalewicz,Z. Michalewicz,基于难题的学习:批判性思维、数学和问题解决导论(2008),混合出版社
[ 2 ] F. Provost,T. Fawcett,商业数据科学(2013),O'Reilly,
[ 3 ] A. Geron,使用 Scikit-Learn、Keras 和 TensorFlow 进行机器学习(2017 年),O'Reilly Media。
Adam 优化完全指南
原文:https://towardsdatascience.com/complete-guide-to-adam-optimization-1e5f29532c3d?source=collection_archive---------4-----------------------
Adam 优化算法从定义到实现
拉斐尔·比斯卡尔迪在 Unsplash 上拍摄的照片
在 20 世纪 40 年代,数学规划是最优化的同义词。一个优化问题包括一个目标函数,通过从一组允许值【1】中选择输入值,该目标函数将被最大化或最小化。
如今,优化是人工智能中一个非常熟悉的术语。具体来说,在深度学习问题上。而深度学习问题最值得推荐的优化算法之一就是 亚当 。
免责声明:对神经网络优化的基本了解。如梯度下降和随机梯度下降是阅读前的首选。
在这篇文章中,我将强调以下几点:
- Adam 优化的定义
- 亚当之路
- 随机优化的 Adam 算法
- 亚当和其他优化者之间的视觉比较
- 履行
- 亚当的优点和缺点
- 结论和进一步阅读
- 参考
1.Adam 优化的定义
Adam 算法首先在 Diederik P. Kingma 和 Jimmy Ba 的论文 Adam:一种随机优化方法【2】中介绍。Adam 被定义为“一种高效随机优化的方法,其中只需要一阶梯度,几乎不需要内存”[2]。好,让我们把这个定义分解成两部分。
首先,随机优化是在随机性存在的情况下,优化一个目标函数的过程。为了更好地理解这一点,让我们考虑随机梯度下降(SGD)。当我们有很多数据和参数时,SGD 是一个很好的优化器。因为在每一步,SGD 都从数据(小批量)的随机子集计算梯度的估计值。不像梯度下降在每一步都考虑整个数据集。
与 GD 相比,SGD 导致许多振荡。然而,SGD 要快得多,因为它不会遍历整个批处理(来源: deeplearning.ai )
第二,Adam 只需要一阶梯度。也就是说,亚当只需要参数的一阶导数。
现在,算法的名字亚当来源于自适应矩估计。随着我们对算法的研究,这一点将变得显而易见。
2.亚当之路
Adam 基于并结合了以前算法的优点。为了理解 Adam 算法,我们需要快速了解之前算法的背景。
我。带动量的新币
物理学中的动量是运动中的物体,比如一个球沿着斜坡加速下降。因此,带动量的 SGD【3】结合了之前更新步骤的梯度,以加速梯度下降。这是通过在相关方向上采取小而直接的步骤来实现的。
SGD 通过计算一个的梯度移动*均值来实现,然后用它来更新你的参数****【权重,偏差】。**********
计算指数加权*均值(移动*均值),然后更新参数
- 贝塔项( 𝛽 )控制着均线。β的值是[0,1],一个常见的值是𝛽 = 0.9,这意味着我们对最后 10 次迭代的梯度进行*均,旧的梯度被丢弃或者被遗忘。因此,较大的β值(比如𝛽 = 0.98)意味着我们在更多的梯度上求*均值。
- Alpha ( α )是决定每次迭代步长的学习率。
左 : SGD,右:带动量的 SGD(来源:动量和学习率适应)****
二。相关工作(AdaGrad 和 RMSProp)
好的,在我们讨论亚当之前,有两个算法需要了解。 AdaGrad (自适应梯度算法)【4】和 RMSProp (均方根传播)【5】都是 SGD 的扩展。这两种算法与 Adam 有一些相似之处。事实上,亚当结合了两种算法的优点。
三世。自适应学习率
AdaGrad 和 RMSProp 也都是自适应梯度下降算法。意思是,对于参数 (w,b)中的每一个,学习率 (α) 被适配。简而言之,学习率是按参数来维持的。**
为了更好地说明这一点,下面是对 AdaGrad 和 RMSProp 的解释:
- 阿达格勒
阿达格拉德的每参数学习率帮助增加稀疏参数的学习率。因此, AdaGrad 适用于稀疏梯度,例如在自然语言处理和图像识别应用中【4】。****
- RMSProp
RMSProp 是由 Tielemen 和 Hinton 提出来加速小批量学习的。在 RMSProp 中,学习率基于 最*梯度的幅度的移动*均值来调整 。****
也就是说,RMSProp 保持最*梯度*方的移动*均值,用(v)表示。因此,给予最*的梯度更多的权重。
这里,术语β(𝛽)被引入作为遗忘因子(就像在具有动量的 SGD 中一样)。**
计算最*梯度*方的移动*均值
简而言之,在更新 θ (比如 w 或 b )时,将 θ 的前一个值的梯度除以该参数的最*梯度的*方的移动*均值,然后乘以 α**
某些参数的更新步骤 θ
此外,RMSProp 在大的和冗余的数据集(例如噪声数据)上工作良好[5]。
*术语( 𝜖 ) 用于数值稳定性(避免被零除)。
以下是我们目前所学内容的视觉对比:
围绕鞍点的不同优化器(来源: Imgur 亚历克·拉德福德
在上面的 gif 中,你可以看到动量在找到正确的路径之前四处探索。至于 SGD,AdaGrad,和 RMSProp,都是走的差不多的路,但是 AdaGrad 和 RMSProp 显然更快。
3.随机优化的 Adam 算法
好了,现在我们已经得到了算法所需的所有部分。
正如吴恩达所解释的,亚当:自适应力矩估计是动量和 RMSProp 的简单组合。
亚当算法(来源:亚当:随机优化的方法[2])
下面是优化目标函数 f(θ) 的算法,参数 θ (权重和偏差)。
Adam 包括超参数: α ,𝛽 1 (来自动量),𝛽 2 (来自 RMSProp)。
初始化:
- m = 0,这是第一个力矩矢量,按动量处理
- v = 0,这是第二个力矩矢量,在 RMSProp 中处理
- **t:0
在迭代 t 时:
- 更新 t,t := t + 1
- 得到 g 相对于 t 的梯度/导数,这里的 g 相当于T25【分别为 dw 和 db**
- 更新第一时刻 mt
- 更新二阶矩 vt
分别更新 mt 和 vt
- 计算偏差修正后的 mt ( 偏差修正后的对移动*均值给出了更好的估计)
- 计算偏差校正后的 v t
分别为偏差校正的 mt 和 vt
- 更新参数θ
更新参数
就这样!循环将继续,直到 Adam 收敛到一个解。
4.优化器之间的视觉比较
识别前面提到的优化算法之间的差异的更好的方法是查看它们的性能的视觉比较。
不同优化者的培训成本比较[2]
上图来自亚当的论文。它展示了超过 45 个时期的训练成本,你可以看到 CNN 的 Adam 比 AdaGrad 收敛得更快。也许值得一提的是,AdaGrad 对应于一个版本的 Adam,其超参数(α, 𝛽1,𝛽2 )为特定值[2]。为了避免混淆,我决定从这个帖子中删除 AdaGrad 的数学解释,但是如果你想了解更多,这里有 mxnet 的一个简单解释。
Gif 作者使用【7】
在上面的 gif 中,你可以看到亚当和 RMSProp 以相似的速度收敛,而阿达格拉德似乎在努力收敛。
Gif 作者使用【7】
同时,在这张 gif 图中,你可以用动量将 Adam 和 SGD 收敛到一个解。而 SGD、AdaGrad 和 RMSProp 似乎陷入了局部最小值。
5.履行
在这里,我将展示将 Adam 合并到您的模型中的三种不同方法,分别是 TensorFlow、PyTorch 和 NumPy 实现。
-
TensorFlow 实现:
-
PyTorch 实现:
-
仅用 NumPy 实现:
这个实现可能不太实用,但它会让您更好地理解 Adam 算法。
但正如你所猜测的,代码相当长,所以为了更好地查看,给出了要点。
6.亚当的优点和缺点
与其他算法相比,Adam 是最好的优化器之一,但它也不是完美的。所以,下面是亚当的一些优点和缺点。
优势:
- 可以处理噪声数据集上的稀疏梯度。
- 默认的超参数值在大多数问题上都做得很好。
- 计算效率高。
- 需要很少的内存,因此内存效率高。
- 适用于大型数据集。
缺点:
- Adam 在某些领域没有收敛到最优解(这是 AMSGrad 的动机)。
- Adam 可能会遇到体重下降的问题(这在 AdamW 中有所论述)。
- 最*的优化算法已经被证明更快更好[6]。
7.结论和进一步阅读
这就是 Adam 的全部内容:自适应矩估计!
Adam 是 SGD 的扩展,它结合了 AdaGrad 和 RMSProp 的优点。Adam 也是一种自适应梯度下降算法,因此它保持每个参数的学习速率。并且它跟踪梯度的第一和第二时刻的移动*均值。因此,使用第一和第二矩,Adam 可以给出参数更新的未缩放的直接估计。最后,尽管出现了更新的优化算法,Adam(和 SGD)仍然是一个稳定的优化器。****
进一步阅读(和观看)的绝佳资源:
- 梯度的定义【Denis Auroux 教授(麻省理工学院)
- 带有动量的随机梯度下降作者 Vitaly Bushaev
- 深度学习的 Adam 优化算法简介作者 Jason Brownlee
- 吴恩达(deeplearning.ai)的深度学习专业化,也可以在 YouTube 上找到
- 亚当——深度学习优化的最新趋势维塔利·布沙耶夫
8.参考
- 斯蒂芬·j·赖特,优化 (2016),大英百科全书
- Diederik P. Kingma,Jimmy Ba, Adam:一种随机优化方法 (2015),arxiv
- 通过错误传播学习内部表征 (1986),鲁梅尔哈特,辛顿和威廉姆斯,美国计算机学会
- 杜奇等人,在线学习和随机优化的自适应次梯度方法 (2011),斯坦福
- Geoffrey Hinton 与 Nitish Srivastava Kevin Swersky,用于机器学习的神经网络(讲座 6) (2012),UToronto 和 Coursera
- 陈志强,最*梯度下降算法的最新概述 (2020),GitHub
- kuroitu S,优化方法比较 (2020),Qiita
在生产中构建和部署 Tweet Generator 应用程序的完整指南
原文:https://towardsdatascience.com/complete-guide-to-build-and-deploy-a-tweet-generator-app-into-production-5006729e583c?source=collection_archive---------37-----------------------
学习使用代码从零开始构建一个 Tweet Generator 应用程序,从 Twitter 下载数据,在 Google Colab 上训练 GPT-2 模型,并在 AWS 上部署
🇨🇭·克劳迪奥·施瓦茨| @purzlbaum 在 Unsplash 上拍摄的照片
快速链接
app:【http://botbaby.in/】T4GitHub:https://github.com/nikhilno1/bot-baby
目录:
- 背景与目的
- 大局
- 构建数据集
- 模型训练
- 在 AWS 上部署
- 前端
- 分析-结果
- 挑战
背景和目标
作为一个痴迷于数据分析的 twitter 用户,我一直想开发应用程序来分析 twitter 数据。我关心的是社交媒体话语演变的方式,尤其是。在推特上。假新闻、钓鱼、仇恨信息、虚假趋势、机器人等的扩散令人担忧,我总是有这种冲动去做些什么。
我也一直希望获得现实世界的工作经验,我相信这对我的下一份工作会有帮助。在我一年的职业生涯中期,我还有 3 个月的休息时间。由于时间不多(因为我也在找工作),我想挑选一个不太关注 ML 算法的问题,但可以让我花足够的时间学习大规模部署 ML 生产模型。
我决定开始为左翼(LW)和右翼(RW)的印度推特建立一个推特生成器应用程序。该应用背后的想法是突出两个阵营的两极分化和使用的语言。在我看来,以此为起点的好处是:
- 允许我建立一个下载/传输 twitter 数据的框架。
- 开发一个语言模型,我可以稍后用于其他下游任务。
- ML 模型培训允许我在大约一个月内建立完整的应用程序。
- 完成 MLOps 生命周期,包括数据和模型的版本控制。
- 使用 Elasticsearch 添加搜索功能,以获得其他有趣的见解。
- 建立解决其他问题(假新闻/趋势、机器人、仇恨信息等)的基础
有了明确的目标后,我开始着手工作,用了大约 3 周的时间完成了这个应用。
现在让我们来看看所有的细节。
大局
这是我们将涉及的所有构建模块的快速快照。
构建数据集
为了生成 LW & RW tweets,我需要两个语言模型,它们分别在自己的数据集上进行训练。在这种情况下,数据集是来自两个阵营的人的推文。
现在获得一份 LW & RW 帐户的列表可能有点困难,因为这些信息不会在任何地方公开。每个人都认为自己是中间派。😃
起初我想建立某种社交图或聚类算法,但后来我发现我不需要做任何复杂的事情。以下是我最后做的事情:
- 我从少数几个经常被贴上 LW 或 RW 标签的客户开始。
- 我利用了 Twitter 自己的推荐引擎,即“与 X 相似”的功能来寻找更多像他们一样的句柄。
- 通过这个,我为每一方建立了一个 35-40 名用户的列表,我称他们为领导者。
- 然后我下载了所有领导人的追随者名单。
- 我合并了关注者列表,并按频率排序。
- 这个想法是,任何追随大多数“领导者”的人都很可能属于同一个阵营。
- 通过这种方式,我获得了双方排名前 15 万的 twitter 账户列表,并删除了两个列表中的共同账户。
- 然后,我会下载所有这些用户的推文,这些推文将成为我的数据集。
从 twitter 上下载数据是一项痛苦的工作,因为存在各种速率限制。我不想冒应用程序被阻塞的风险,创建一大堆节点并下载。所以我公*地使用单个节点来下载数据。
不幸的是,当我开始构建数据集时,我并不知道 twint。我知道了 tweepy ,后来又知道了 GetOldTweets3 图书馆。由于这两个一起满足了我的要求,我与它滚动。但如果让我再来一次,我最有可能选择 twint 。
注:Tweepy vs GetOldTweets3
Tweepy: 7 天,每 15 分钟窗口 18000 条推文。3200 条最*的推文,每条推文都有丰富的信息。
GetOldTweets3:没有授权,信息更少,获取旧的推文
下载推文数据的步骤:
- 使用 tweepy,我首先下载了所有的追随者 id。获得关注者 id 而不是用户名的好处是速度提高了 15 倍。id 的速率限制是 45000,而用户名的速率限制是 3000。
- 一旦我有了所有的追随者 id,我就把它们合并,按降序排列,最后删除重复。
- 然后我使用 twitter 的 HTTP GET 请求将 id 转换成用户名,这个请求没有任何速率限制。这一步是必需的,因为 GetOldTweets3 只对用户名有效,对 id 无效。
- 最后,我使用 GetOldTweets3 为每个用户下载推文,时间可以追溯到 2014 年。为什么是 2014 年?那是选举年,许多人在那段时间开始活跃在 twitter 上。
- 在下载了足够的数据后,我执行文本预处理,以删除超链接、非英语字符(因为我的语言模型只理解英语)和极短的推文。我将所有这些推文收集在一个文本文件中(LW 和 RW 分开),这给了我最终的训练数据集。
模型训练(在 Google Colab 上)
当我开始开发这个应用程序时,我首先从零开始训练自己的语言模型。我在谷歌云上的 TPU 训练了一个 GPT-2 模型。但是结果并不像 Max Woolf 的笔记本那样吸引人。它开箱即用,效果极佳,所以我坚持使用它。为了减轻训练的痛苦,我甚至注册了 Colab Pro 订阅,这太便宜了。在 TPU 上进行一天的培训,我花了 100 多澳元,但 Colab Pro 每月花费我 10 美元。我鼓励每个人利用它。它给你更高的超时和内存。
我培训用的笔记本在这里。这与马克斯的原作十分相似。我用的是 GPT-2 的 355 米模型。根据我的数据集的大小,我训练了 2000 到 6000 步,直到我看到*均损失下降。对于我的大约 300 MB(每边)的训练数据集,我训练了 6000 步。
训练完成后,大约需要一个小时,模型输出一堆文件,很好地打包在一个归档文件中,您可以将它复制到 Google Drive 进行进一步分发。
在 AWS 上部署
我最初的计划是在谷歌新发布的 AI *台管道上做生产部署。它看起来就像是一个全面的产品。然而,当我偶然看到这个博客,它提供了在 AWS 上部署的详细说明,我想为什么我不先这样做。当你独自工作时,获得经常性的激励是很重要的。没有比尽早发布你的应用更好的激励了。所以我决定首先在 AWS 上部署它,然后再考虑在人工智能*台管道上通过适当的工作流程大规模部署它。
正如在的博客中所解释的,我们不能完全没有服务器,因为每个型号都接* 1.5GB,所以我需要至少 3 GB 的内存,仅用于这些型号。另外,我需要进行批量推理,为此我需要一个 GPU 实例。
以下是当前部署架构的样子:
主持:
该网站是静态托管在亚马逊 S3,这是一个真正的廉价和快速的方式把你的网站推向世界。
API 网关:
这将创建一个 API 端点,它将接收来自前端应用程序的传入 HTTP 请求,并调用已配置的 Lambda 函数。
步骤 1)创建一个 API 端点
步骤 2)创建路线
步骤 3)配置 CORS
步骤 4)为 Lambda 函数配置更高的超时
任何集成的默认超时是 3 秒,因此如果您需要进行任何需要更长时间的推理,那么您需要相应地增加这个超时。
λ函数:
Lambda 函数从 API 网关接收 HTTP GET 请求,并执行以下操作:
- 检查提示是否已经存在于 DynamoDB 中。如果是,那么读取记录并返回响应。此操作需要几毫秒才能完成。
- 如果是新的提示,那么将请求添加到 SQS FIFO 队列中,并启动 EC2 g4dn.xlarge 实例。
- 一旦实例启动,继续轮询 DynamoDB 以检查是否有新的提示可供读取。在这种情况下,它读取新添加的记录并将响应返回给 API 网关。
- Lambda 函数在返回响应之前做了一个额外的步骤。它选择生成的 tweets 中的大多数情绪,并只返回这些情绪。例如,如果数据库返回 10 条推文,其中 7 条是正面的,2 条是负面的,1 条是中性的。那么 lambda 函数将返回 7 条正面推文,因为这表明了大多数人的观点。请记住,语言生成本质上是概率性的,因此显示多数输出是有意义的。
像在 API 端点上一样,我们也需要增加 Lambda 上的超时。
λ超时配置
提示:利用 TestEvent 来测试你的 Lambda 函数。您可以按如下方式配置测试事件:
{
“queryStringParameters”: {
“model”: “left”,
“prompt”: “Test prompt”,
“num_samples”: “20”,
“length”: “80”,
“temperature”: “0.7”,
“top_p”: “0.9”,
“top_k”: “40”
}
}
简单队列服务(SQS):
为了序列化传入的 HTTP 请求,我使用了 SQS FIFO 队列。Lambda 函数将传入的请求排入该队列,并启动 EC2 GPU 实例。GPU 实例在启动时从该队列中读取数据,并逐个运行推理。这允许我用一个 EC2 实例以高性价比的方式处理并发请求。
SQS 先进先出队列
EC2 GPU 实例:
对于推理,我使用最*推出的高性价比的 G4 实例(准确地说是 g4dn.xlarge)。G4 实例以每小时 0.58 美元的价格为按需主机提供最新一代的英伟达 T4 GPU。使用 spot 实例可以进一步降低成本。在使用 G4 实例之前,您需要提出一个服务请求来增加 vCPU 限制。
在原始代码中,作者在 EC2 实例上启动了一个 python 脚本。然而,这意味着每次推理都需要额外的 15 秒钟来将模型加载到内存中。我修改了它,改为运行一个网络应用程序(基于 Starlette)。下面是 EC2 实例从头到尾发生的所有事情。
- Lambda 函数触发 EC2 实例的启动
- 两个单独的 web 应用程序作为系统启动的一部分(作为 systemd 服务)运行(每个型号一个),并开始监听端口 8081 和 8082。
- 另一个服务在启动时运行,监视 SQS 队列。每当有新请求进来时,该服务都会处理它,并使用 CURL 调用适当的 GET 请求,这会触发后端 web 应用程序上的推理。
- 后端 web 应用程序收到请求后,调用 GPT2 API 批量生成 20 条 tweets。
- 然后,它会进行清理,保留最合理的推文。它首先删除不必要的字符,如换行符和引号。然后,它使用 NLTK 的 sent_tokenize()函数删除最后一个可能不完整的句子。有时,生成的推文包含重复的单词或句子序列,因此它会删除唯一单词数量较少的推文。
- 然后,网络应用程序使用 AWS 领悟服务对剩余的推文进行情感分析。它保留了得分最高的前 10 条推文。这个想法是,在任何类别(正面、负面或中性)中得分高的推文往往比得分分布更均匀的推文更连贯。
- 然后,前 10 条推文按照排序顺序存储在 DynamoDB 中。
- 如果超过 15 分钟没有收到新的请求,那么 EC2 实例将被关闭以节省成本。
- 作为关闭过程的一部分,会调用一个脚本,该脚本会将新添加的提示更新到 S3 上的一个文件中。这用于在 UI 上提供自动完成功能。
前端
前端使用 HTML、CSS & Javascript 开发。为了复制 twitter 的用户界面,安迪·勒沃伦兹的让我们来构建:利用顺风 CSS——Tweet就像天赐之物。它提供了显示单条推文的基本 UI,稍后我可以扩展它(在马南的帮助下)来显示推文的并排视图。
如前所述,该网站静态托管在亚马逊 S3。
自动完成: 考虑到新提示的推理需要 30-60 秒,而如果用户输入一个现有的提示,那么在大约 250 毫秒内就会得到结果,鼓励用户更多地使用现有的提示是有意义的。因此,添加自动完成功能变得很重要,这样用户可以从列表中选择一个,而不是输入他/她自己的。
在实现一些极其简单的东西之前,我考虑了一些复杂的解决方案(使用 Elasticsearch 或 AWS 云搜索)。
由于我的网站位于 S3,我修改了我的前端代码,以读取来自 S3 的“提示”文件。该文件包含所有现有提示的列表。在用户对新提示进行推理之后,每当实例关闭时,S3 上的提示文件就会更新。有一个小的滞后,但除此之外,这个简单的解决方案工作得非常好。
分析学
我想获得使用统计数据,并为用户提供一个选项来给出他们对应用程序的反馈。
这些是我为此添加的一些东西:
- 向 DynamoDB 添加了一个“已访问”计数器,这样每次读取记录都会触发该计数器的(原子)增量。我可以用它来显示流行的查询。
- 在 API 端点上启用了“详细路由度量”收集。我可以用它来获得更多关于 AWS 内的访问者数量,位置等细节。
- 与谷歌分析集成,以获得更详细的使用统计数据
- 与 mopinion 整合以获得用户反馈。
对于(3)和(4),您只需要将它们提供的几行代码复制到您的 HTML 中。
结果
我尝试了几个温度、top_p 和 top_n 的设置,最终选择了这些能给出最佳结果的设置。这些也是推荐的默认值。
“temperature”: “0.7”,
“top_p”: “0.9”,
“top_k”: “40”
其中,
温度:温度越高,文本越疯狂
top_k :将生成的猜测限制为前 k 个猜测
top_p :核采样:将生成的猜测限制为累积概率
以下是一些结果:
挑战
这一部分列出了我一路上面临的一些挑战。希望它能帮助面临类似问题的人。
(注:我没有做好记录我所面临的所有问题/挑战的工作,所以这些是凭记忆提供的。我会根据我的记忆不断补充。)
-
用命令
nltk.download(‘punkt’)
安装 NLTK 数据 -
app.py
代码取自GPT-2-云运行。我在安装 ujson 包时遇到了构建错误。这个错误是由于缺少g++
库造成的。
运行 -
安装使用 GPU 的正确 tensorflow 1.x 版本时出现问题。我认为正确的安装方法是运行
pip install tensorflow-gpu==1.15
-
SSM 代理存在没有正确权限/策略的问题。始终验证 SSM 代理是否工作正常,并且能够连接到可用的实例。确保您已经在 AWS 控制台上完成了“系统管理器快速设置”。
-
我遇到了一个问题,推理发生在 CPU 上,而不是 GPU 上。这被证明是环境变量问题。LD_LIBRARY_PATH 设置不正确。过了一会儿,我注意到系统日志中有一个错误。参考 gp T2-app-[型号]。正确设置它的服务文件。
-
如果遇到任何问题,请始终查看/var/log/syslog。大多数情况下,错误会被记录在那里。
-
有时,由于可用性区域中的容量不足,GPU 实例将不会运行。您需要尝试不同的 AZ。
下一步怎么样
这个应用程序是为了让我尝试使用 twitter 数据并学习 MLOps。所以我肯定想转移到谷歌的 AI *台管道,进行更完整的 ML 工作流部署。我还希望有一个易于使用的框架来下载和存储 twitter 数据,所以我将探索 twint 。一旦我有了这个想法,就可以更容易地去想其他的想法了。如果你有任何关于 twitter 的想法/建议,请在下面评论让我知道。
从零开始构建深度学习聊天机器人的完整指南
原文:https://towardsdatascience.com/complete-guide-to-building-a-chatbot-with-spacy-and-deep-learning-d18811465876?source=collection_archive---------0-----------------------
亚历山大·奈特在 Unsplash 上拍照
实践教程
spaCy 用于实体提取,Keras 用于意图分类,等等!
在过去的一个月里,我想寻找一个包含整个数据科学端到端工作流的项目——从数据管道到深度学习,再到部署。它必须具有挑战性,但不是毫无意义的——它仍然必须是有用的东西。这需要一点构思和发散思维,但当制作个人助理的想法出现时,没多久我就选定了它。会话助手无处不在。甚至我所在的大学目前也在使用聊天机器人医生来跟踪其成员的健康状况,以此作为监控当前疫情的有效方式。这很有意义:聊天机器人更快,更容易交互,特别是对于我们只想快速响应的事情来说,非常有用。在这个时代,能够向机器人寻求帮助开始成为新的标准。我个人认为机器人是未来,因为它们让我们的生活变得更加容易。聊天机器人也是机器人流程自动化的关键组成部分。
现在我要介绍EVE bot,我的机器人旨在为 Twitter 上的苹果支持团队增强虚拟参与(见我在那里做的)。虽然这种方法是用来支持苹果产品的,但老实说,它可以应用到任何你能想到聊天机器人有用的领域。
这是我给 EVE 的演示视频。(这是我的 Github 回购这个项目)
演示片段—询问 EVE 如何更新我的 MacBook Pro。图片作者。
图片作者。
为了使演示简洁明了,它对我的工作进行了一个高层次的、不太技术性的概述。但是,如果您想了解我是如何做到的,这正是本文其余部分的目的!
我也希望这篇文章能为那些需要一些关于如何从头构建自己的机器人的结构的人提供指导——从某种意义上说,你只使用众所周知的通用软件包,如 Keras 和 spaCy,而不是专门为聊天机器人设计的大型 API,如 Rasa API。
EVE 是一个基于上下文的机器人,由深度学习提供支持。基于上下文的机器人是你很久以前可能见过的简单的、基于关键字的聊天机器人之上的一步(见:伊莱扎机器人)。虽然我确实有一些灵感,而且它确实与行业中的做法有相似之处,但我提供了一些方法,这些方法是我自己思考如何在 2020 年制作聊天机器人的。
我在这篇文章中展示的这种方法利用了与亚马逊这样的大公司的聊天机器人相同的逻辑,即他们的 Lex conversational AI 服务。
外面有什么?
在我进入技术工作之前,重要的是要知道你想以什么样的粒度来制作聊天机器人。聊天机器人就像煮意大利面条。你可以从生番茄开始,或者从别人已经为你做好的罐装番茄开始。相似之处还在于有许多不同的组件—您有:
- 框架:你的机器人根据顾客的话语决定如何回应他们。您可以为您的框架使用更高级别的工具,如 DialogFlow(由 Google 提供)、 Amazon Lex 和 Rasa 。与我将在本文中展示的基于 Python 的工作相比,这些更高级别的 API 需要您做的工作更少,但是您可能对后台发生的事情没有信心。我的选择是 Tensorflow、spaCy 和 Python 的白盒方法。
- 对话管理:这是你的机器人的一部分,负责对话的状态和流程——在这里你可以提示用户你需要的信息等等。
- 部署接口:你可以用 Messenger API 建立一个接口,你可以把它部署在 WhatsApp Business 上(收费),或者任何地方,比如你自己的网站或应用程序,如果你有的话。我在 Streamlit 上部署了我的工具,作为一个非常快速的演示工具。
我的聊天机器人框架的目标应该是什么?
好了,你已经决定做自己的框架了。现在告诉你怎么做。
你的目标是双重的——而这两个都很重要:
- 实体提取
- 意图分类
当开始制作一个新的机器人时,这正是你首先要解决的问题,因为它指导你想要收集或生成什么样的数据。我建议你从你的意图和实体的基本概念开始,然后在你越来越多地测试它的时候迭代地改进它。
实体提取
实体是预定义的名称、组织、时间表达式、数量和其他有意义的通用对象组的类别。
每个聊天机器人都有不同的应该被捕获的实体集合。对于一个披萨递送聊天机器人,您可能希望捕获不同类型的披萨作为一个实体和递送位置。在这种情况下,奶酪或意大利辣香肠可能是披萨实体,而厨师街可能是递送位置实体。在我的例子中,我创建了一个苹果支持机器人,所以我想捕捉用户正在使用的硬件和应用程序。
硬件实体“macbook pro”被标记。其他硬件可能包括 iPhone 和 iPads。图片作者。
捕捉到的应用程序实体“garageband”已被标记。其他应用实体可能包括 Apple Music 或 FaceTime。图片作者。
为了获得这些可视化,使用了 displaCy,这是 spaCy 用于命名实体识别的可视化工具(他们还有更多可视化工具用于其他事情,如依赖解析)。
意图分类
意图就是客户想要做的事情。
他们想问候你吗?他们是想和代表谈吗?如果你是机器人,他们会挑战你吗?他们在尝试更新吗?
意图分类仅仅意味着找出用户话语的用户意图。下面是我在 Eve bot 中想要捕捉的所有意图的列表,以及每个意图各自的用户话语示例,以帮助您理解每个意图是什么。
- 问候:嗨!
- 信息:你们现有的最薄的 MacBook 是什么?
- 忘记密码:我忘记了我的登录信息,你能帮我找回吗?
- 发言代表:请问我能和人类说话吗
- 挑战机器人:你是人类吗
- 更新:我想将我的 MacBook Pro 更新到最新的操作系统
- 付款:我昨天在百思买买的 iPhone X 被双倍收费
- 位置:离我最*的苹果店在哪里?
- 电池:我的电池持续耗尽,一小时后就没电了
- 再见:谢谢伊芙,再见
意图和实体基本上是我们解读客户想要什么以及如何给客户一个好的答复的方式。我最初认为我只需要给出一个没有实体的答案的意图,但这导致了很多困难,因为你不能对你的客户做出细致的回应。如果没有多标签分类,也就是给一个用户输入分配多个类别标签(以准确性为代价),就很难得到个性化的响应。实体有助于使你的意图仅仅是意图,并根据用户的细节个性化用户体验。
有了这两个目标,我把我的过程归结为五个步骤,我将在这篇文章中逐一分解:
图片作者。
1.数据预处理
我做数据预处理的笔记本是这里。
我提到的第一步是数据预处理,但实际上这 5 个步骤并不是线性完成的,因为你将在整个聊天机器人创建过程中预处理你的数据。
但是,即使在数据预处理之前,您究竟从哪里获得数据呢?
这真的取决于你的聊天机器人的领域。
数据指南
- 你必须找到能最好地涵盖客户可能会问你的问题以及你想尽可能多地回答的数据。****数据应该包含你希望能够回答的所有意图。这可能是一项非常艰巨的任务,但是要知道你的数据不一定是完美的,它可以来自多个来源,只要它们在同一个通用域内。
- 对于每一个意图,你应该有相当数量的例子,这样你的机器人将能够了解该意图的性质。
- 如果你真的没有任何数据,就像我在我的下一个项目中想到的那样(它不是一个英语聊天机器人),我试图通过制作一个谷歌表单来解决这个问题,让人们向我的机器人提问。整个要点是获得最接*真人将要问你的机器人的问题的数据。
但回到 Eve bot,因为我正在制作一个 Twitter 苹果支持机器人,我从 Kaggle 上的客户支持推文中获得了我的数据。一旦获得了正确的数据集,就可以开始对其进行预处理。这个初始预处理步骤的目标是为我们进一步的数据生成和建模做好准备。
首先,我通过一些 Pandas merge 语句以入站和出站文本的格式获取数据。对于任何类型的客户数据,您都必须确保数据的格式能够区分客户对公司的话语(入站)和公司对客户的话语(出站)。保持足够的敏感,以这样一种方式争论数据,你的客户可能会问你一些问题。
不久之后,我应用了一个 NLP 预处理管道。包括哪些步骤取决于你的用例(比如你想要支持的语言,你想要你的机器人有多口语化,等等。).我的包括:
- 转换为小写
- 使用 NLTK 的 Tweet 标记器进行标记
- 删除标点符号和 URL 链接
- 纠正拼写错误(利维坦距离)
- 删除停用词
- 扩张收缩
- 用 spaCy 删除非英语推文
- 词汇化(您可以选择词干作为替代)
- 移除表情符号和数字(如果您的模型可以读取表情符号,并且如果您计划进行表情符号分析,您可以保留表情符号)
- 将每条推文的长度限制在 50(为了简洁)
我将所有这些步骤编译成一个名为tokenize
的函数。在每一个预处理步骤中,我可视化数据中每个记号的长度。我还提供了每一步的数据头,以便清楚地显示每一步正在进行的处理。
我的整个记号赋予器函数。
我从 106k Apple Suppourt inbound Tweets 开始。这是预处理这些数据之前我的令牌长度的直方图。
图片作者。
在第 10 步之后,我还剩下大约 76k 条推文。一般来说,像删除停用词这样的事情会使分布向左移动,因为我们在每个预处理步骤中的标记越来越少。
图片作者。
这里你可以看到这一步的结果。我让我的数据从左边的青色变为中间的已处理入站列。我还将出站数据放在右边,以防我需要查看 Apple 支持如何回复他们的查询,这将用于我实际回复客户的步骤(这称为自然语言生成)。
我的苹果头支持预处理前后的 Twitter 数据。图片作者。
最后,作为一个简短的 EDA,这里是我在数据集中的表情符号——可视化很有趣,但我最终没有将这些信息用于任何真正有用的东西。
我的数据集中的表情符号:大多数客户表现出负面情绪(愤怒和失望的表情符号排在第二位)。图片作者。
2.数据生成
我生成训练数据的完整脚本是这里的,但是如果你想要一步一步的解释,我这里还有一个笔记本。
是的,你没看错——数据一代。你可能会想:
为什么我们需要生成数据?为什么我们不能只使用在上一步中预处理过的数据呢?
这是一个很好的问题。答案是因为数据还没有被标注。而意图分类是一个有监督的学习问题。这意味着我们需要每个数据点的意图标签。
如果您已经有了一个包含您想要分类的所有意图的带标签的数据集,我们不需要这一步。但更多的时候,你不会有这些数据。这就是为什么我们需要做一些额外的工作来将意图标签添加到我们的数据集。这是一个相当复杂的过程,但我相信我们能做到。
我们的目标是:
在这一步,我们希望将推文分组,以代表一种意图,这样我们就可以给它们贴上标签。此外,对于我们的数据中没有表达的意图,我们要么被迫手动添加它们,要么在另一个数据集中找到它们。
例如,我的推文中没有任何一条推文问“你是机器人吗?”这实际上非常有意义,因为 Twitter 苹果支持是由真正的客户支持团队回答的,而不是聊天机器人。因此,在这些情况下,由于在我们的数据集中没有表达挑战机器人意图的文档,我在它自己的组中手动添加了这种意图的示例来表示这种意图。我将在第 4 步中详细解释我是如何做到这一点的。
因为我计划使用一个相当复杂的神经网络架构(双向 LSTM)来对我的意图进行分类,所以我需要为每个意图生成足够多的例子。我选择的数字是 1000——我为每个意图生成 1000 个示例(例如,1000 个问候示例,1000 个遇到更新问题的客户示例,等等)。).我将每一个意图都精确地定义为 1000 个例子,这样我就不用担心以后建模阶段的类不*衡了。一般来说,对于你自己的机器人,机器人越复杂,你需要的训练例子就越多。****
嵌入技术
这就是如何发挥作用的地方,我们如何找到每个意图的 1000 个例子?首先,我们需要知道在我们的数据集中是否有 1000 个我们想要的意图的例子。为了做到这一点,我们需要一些推文之间的距离概念,如果两条推文被认为彼此“接*”,它们应该具有相同的意图。同样,两条相距“更远”的推文在含义上应该是非常不同的。
为此,我们使用一种称为 Doc2Vec 的编码方法。嵌入方法是将单词(或单词序列)转换成可以相互比较的数字表示的方法。我用 Streamlit 创建了一个训练数据生成器工具,将我的推文转换为 20D Doc2Vec 表示的数据,其中每个推文可以使用余弦相似性进行相互比较。
(左)Twitter 数据(右)Doc2Vec 20D 矢量化数据。图片作者。
下面的图表说明了 Doc2Vec 可以用来将相似的文档组合在一起。文档是一系列的标记,而标记是一系列的字符,它们被组合在一起作为一个有用的语义单元进行处理。对于这一数据生成步骤,我也用 gloVe 进行了试验,但是它们只在每个单词级别进行了矢量化,如果您想尝试另一种单词嵌入(也许它更适合您的领域),请确保它在文档级别进行了矢量化。
展示距离如何工作的玩具示例。图片作者。
在这个玩具示例中,我们将每一个话语转换为 3D 矢量(可以在每个短语下面的 3 个数字的粉色数组中看到)。这些 3D 向量中的每一个都是该文档的数字表示。例如,“Hi there”在数值上表示为[3.333,0.1125,-0.4869]。
当我们在这个玩具示例中比较 top 两条意思相似的推文时(两者都要求与代表交谈),我们得到的虚拟余弦相似度为 0.8。当我们比较底部两条不同含义的推文(一条是问候,一条是退场)时,我们得到-0.3。
履行
至于实现,我用的是 gensim 的 Doc2Vec。你必须训练它,这类似于你如何训练一个神经网络(使用历元)。
这就是问题所在。在训练 Doc2Vec 矢量器之前,提前了解您想要的意图是很重要的。一旦你知道了你想要什么样的意图,你就可以应用这个程序来获得你的前 N 组意思相似的推文:
- 简单地想出你在这个意图中能想到的最重要的关键词,然后把它作为一行附加到你的训练数据的末尾(所以对于问候,这一行可以是“嗨,你好,嘿”)。
- 您添加的代表各自意图的额外行将被矢量化,这是一个好消息,因为现在您可以用余弦相似性将其与其他每一行进行比较。
- 通过训练 Doc2Vec 矢量器进行矢量化,然后用额外的行来拟合您的数据。
- 您已经成功地使用关键字来表示一种意图,从这种表示中,您将找到与之相似的前 1000 条推文,以便使用 Gensim 的
model.docvecs.most_similar()
方法为该意图生成您的训练数据。
额外的行是 0-5,它们附加在我的 Tweets 训练数据的顶部——0 代表电池意图,1 代表支付意图,等等。图片作者。
请注意,在训练矢量器之前,我们必须将新的 intent 关键字表示附加到训练数据,因为 Gensim 的实现只能比较作为训练数据放入 Doc2Vec 矢量器的文档。此外,它只能访问每条 Tweet 的标签,所以我不得不在 Python 中做额外的工作,根据 Tweet 的内容找到它的标签。
一旦你生成了你的数据,确保你把它存储为两栏“话语”和“意图”。注意,话语被存储为一个标记化列表。这是你会经常遇到的事情,这没关系,因为你可以在任何时候用Series.apply(" ".join)
把它转换成字符串形式。
这就是培训数据格式应该的样子。图片作者。
您也可以在我的 Streamlit 应用程序的侧边栏上访问我的培训数据生成器工具,作为其中一个页面。图片作者。
我尝试了其他一些方法来添加意图标签
我想到要做的第一件事就是聚类。然而,在我尝试了 K-Means 之后,很明显聚类和无监督学习通常产生不好的结果。现实是,尽管它作为一种技术很好,但归根结底它仍然是一种算法。你不能指望算法按照你想要的方式对你的数据进行聚类。
t-SNE 可视化显示 K-Means 聚类失败,因为数据不在自然聚类中。图片作者。
我还尝试了像 gloVe 这样的单词级嵌入技术,但是对于这个数据生成步骤,我们需要文档级的东西,因为我们试图在话语之间进行比较,而不是在话语中的单词之间进行比较。
3.建模
意图分类
我的意图分类笔记本是这里的。
有了我们的数据标签,我们终于可以进入有趣的部分了——实际上是对意图进行分类!我建议你不要花太长时间试图事先得到完美的数据。试着以合理的速度达到这一步,这样你就可以先得到一个最小的可行产品。这个想法是首先得到一个结果作为基准,这样我们就可以迭代地改进数据。
有许多方法可以进行意图分类,例如 Rasa NLU 允许您使用许多不同的模型,如支持向量机(SVMs),但在这里,我将演示如何使用具有双向 LSTM 架构的神经网络进行分类。
我们试图将一个用户话语(它只是一个符号序列)映射到我们指定的 N 个意图之一。我们开始的数据应该只有一个话语和一个意向基础事实标签作为列。这个过程的顺序如下(关于实现,请查看 my Github 上提供的意图分类笔记本):
- 训练测试拆分(是否应该让总是先走,我的导师在我的脑海里钻过这一点)
- Keras 标记器
- 标签编码目标变量(意图)
- 初始化嵌入矩阵(我使用手套嵌入,因为它们有一个在 Twitter 数据上训练的特殊变体)
- 初始化模型架构
- 初始化模型回调(解决过度拟合的技术)
- 拟合模型并保存它
- 加载模型并保存输出(我推荐字典)
对于嵌入层(步骤 4),需要记住一些事情:
- 这些预先训练的嵌入本质上就是如何将进入模型的文本转换成数字表示。当您比较不同文档的数字表示的余弦相似性时,它们之间应该有有意义的距离(例如,“king”和“man”之间的余弦相似性应该比“king”和“women”更接*)。
- 选择适合聊天机器人领域的正确的预训练嵌入非常重要。如果你有一个基于 Twitter 的聊天机器人,你可能不希望在维基百科上训练嵌入。
- 我还建议您查看一下,您想要涵盖的所有词汇是否都在您预先训练的嵌入文件中。我检查了我的 gloVe Twitter 嵌入是否包含苹果特有的词,例如“macbook pro ”,幸运的是它包含了。
用 grep 检查“macbook”这个词是否在我的手套嵌入中(结果是!).图片作者。
对于模型架构(步骤 5),需要记住一些事情:
- 确保输出图层为 softmax(如果要进行多标签分类,则使用 sigmoid)。
- 确保输出图层的维数与要分类的意图数相同,否则会遇到形状问题。
- 如果您没有标记 encode,那么您对
model.predict()
使用可能会不准确,因为您输出的最终字典(其中的键是意图,值是表达意图的概率)不会被正确映射。 - 当您部署您的机器人时,您不应该重新运行模型。相反,我编写了一个脚本,从读取保存的模型文件开始,并从那里进行预测。
结果
结果是有希望的。损失收敛到一个低水*,我的模型对看不见的数据的准确率是 87%!
图片作者。
图片作者。
如果您将意图分类的输出可视化,这是话语“我的 iphone 电池停止工作了!”:
图片作者。
防止过度拟合
为了防止我的模型过度拟合,我还以 Keras 回调的形式设置了一些其他设置:
- 学习率调度——在学习率超过某个时期数后,减慢学习率
- 提前停止-一旦验证损失(或您选择的任何其他参数)达到某个阈值,就提前停止训练
最后,在我运行模型之后,我将它保存到一个 h5 文件中,这样我就可以在以后初始化它,而不需要使用模型检查点重新训练我的模型。代码如下:
*# Initializing checkpoint settings to view progress and save model*
filename = 'models/intent_classification_b.h5'
*# Learning rate scheduling*
*# This function keeps the initial learning rate for the first ten epochs*
*# and decreases it exponentially after that.*
**def** scheduler(epoch, lr):
**if** epoch < 10:
**return** lr
**else**:
**return** lr * tf.math.exp(-0.1)
lr_sched_checkpoint = tf.keras.callbacks.LearningRateScheduler(scheduler)
*# Early stopping*
early_stopping = tf.keras.callbacks.EarlyStopping(
monitor='val_loss', min_delta=0, patience=3, verbose=0, mode='auto',
baseline=**None**, restore_best_weights=**True**
)
*# This saves the best model*
checkpoint = ModelCheckpoint(filename, monitor='val_loss', verbose=1,
save_best_only=**True**, mode='min')
*# The model you get at the end of it is after 100 epochs, but that might not have been*
*# the weights most associated with validation accuracy*
*# Only save the weights when you model has the lowest val loss. Early stopping*
*# Fitting model with all the callbacks above*
hist = model.fit(padded_X_train, y_train, epochs = 20, batch_size = 32,
validation_data = (padded_X_val, y_val),
callbacks = [checkpoint, lr_sched_checkpoint, early_stopping])
实体提取
这是我完整的关于实体提取的笔记本。
对于 EVE bot,目标是提取符合硬件或应用程序类别的特定于苹果的关键词。像意图分类一样,有许多方法可以做到这一点——根据上下文的不同,每种方法都有其优点。Rasa NLU 使用条件随机场(CRF)模型,但为此我将使用 spaCy 的随机梯度下降(SGD)实现。
第一步是创建一个字典,存储您认为与您的聊天机器人相关的实体类别。然后您会看到 spaCy 是否默认拥有它们。很可能他们不会。因此,在这种情况下,您必须训练自己的自定义空间命名实体识别(NER)模型。对于苹果产品来说,实体是客户正在使用的硬件和应用程序是有意义的。您希望对询问 iPhone 和询问 Macbook Pro 的客户做出不同的回应。
{'hardware': ['macbook pro',
'iphone',
'iphones',
'mac',
'ipad',
'watch',
'TV',
'airpods'],
'apps': ['app store',
'garageband',
'books',
'calendar',
'podcasts',
'notes',
'icloud',
'music',
'messages',
'facetime',
'catalina',
'maverick']}
一旦在字典中存储了实体关键字,您还应该有一个基本上只在句子中使用这些关键字的数据集。幸运的是,我已经有了一个我一直在使用的来自 Kaggle 的大型 Twitter 数据集。如果您输入这些示例并指定哪些单词是实体关键字,您实际上就有了一个带标签的数据集,spaCy 可以了解这些单词在句子中使用的上下文。
为了标注数据集,您需要将数据转换为 spaCy 格式。这是一个样本,我的训练数据应该看起来像是能够被送入 spaCy,用于使用随机梯度下降(SGD)训练您的自定义 NER 模型。我们制作了一个 offsetter,并使用了 spaCy 的 PhraseMatcher,所有这些都是为了更容易地将其转换成这种格式。
TRAIN_DATA = [
('what is the price of polo?', {'entities': [(21, 25, 'PrdName')]}),
('what is the price of ball?', {'entities': [(21, 25, 'PrdName')]}),
('what is the price of jegging?', {'entities': [(21, 28, 'PrdName')]}),
('what is the price of t-shirt?', {'entities': [(21, 28, 'PrdName')]})
]
抵消器
*# Utility function - converts the output of the PhraseMatcher to something usable in training*
**def** offsetter(lbl, doc, matchitem):
*''' Converts word position to string position '''*
one = len(str(doc[0:matchitem[1]]))
subdoc = doc[matchitem[1]:matchitem[2]]
two = one + len(str(subdoc))
*# This function was misaligned by a factor of one character, not sure why, but this is my solution*
**if** one != 0:
one += 1
two += 1
**return** (one, two, lbl)# Example
# offsetter(‘HARDWARE’, nlp(‘hmm macbooks are great’),(2271554079456360229, 1, 2)) -> (4, 12, ‘HARDWARE’)
我在更一般的函数中使用这个函数来“指定”一行,这个函数将原始行数据作为输入,并将其转换为 spaCy 可以读取的标记版本。我不得不修改索引定位,在开始时移动一个索引,我不知道为什么,但它工作得很好。
然后我还创建了一个函数train_spacy
来输入 spaCy,它使用nlp.update
方法来训练我的 NER 模型。它对任意数量的 20 个时期进行训练,其中在每个时期,训练样本被预先打乱。尽量不要选择太高的历元数,否则模型可能会开始“忘记”它在早期阶段已经学习过的模式。因为你是用随机梯度下降来最小化损失,你可以想象你在不同时期的损失。
每次迭代都丢失硬件实体模型。图片作者。
每次迭代都丢失应用程序实体模型。图片作者。
我没有找到一种方法将我训练的所有不同的模型组合到一个 spaCy pipe 对象中,所以我将两个单独的模型序列化到两个 pickle 文件中。同样,这是我上面演示的显示可视化——它成功地将 macbook pro 和 garageband 标记到正确的实体桶中。
硬件实体“macbook pro”被标记。其他硬件可能包括 iPhone 和 iPads。图片作者。
捕捉到的应用程序实体“garageband”已被标记。其他应用实体可能包括 Apple Music 或 FaceTime。图片作者。
从您保存的 pickle 文件中,您可以通过循环 doc 对象的 ents 属性将所有提取的实体存储为一个列表,如下所示:
**def** extract_app(user_input, visualize = **False**):
*# Loading it in*
app_nlp = pickle.load(open("models/app_big_nlp.pkl", "rb"))
doc = app_nlp(user_input)
extracted_entities = []
*# These are the objects you can take out*
**for** ent **in** doc.ents:
extracted_entities.append((ent.text, ent.start_char, ent.end_char, ent.label_))
**return** extracted_entities
4.循环
通过迭代,我真正的意思是改进我的模型。我把它变成了自己的阶段,因为这实际上比你想象的要花更多的时间。我通过以下方式改进我的模型:
- 选择更好的意图和实体
- 提高我的数据质量
- 改进您的模型架构
你不需要像我在步骤 2 中那样生成数据。把它想象成你能够创建完美数据集的工具箱之一。
您输入意图分类器的数据的目标是使每个意图范围广泛(意味着意图示例充分穷尽了用户可能说的话的状态空间和世界)并且彼此不同。
这样,神经网络就能够对以前从未见过的用户话语做出更好的预测。以下是我如何努力实现这个目标的。
手动示例
除了使用 Doc2Vec 相似性来生成训练示例之外,我还在。我从我能想到的几个例子开始,然后我循环这些相同的例子,直到它达到 1000 个阈值。这将决定你的模型有多好。如果您知道某个客户很有可能会写一些东西,您应该将它添加到培训示例中。
关键词探索调优
我们如何选择包含哪些意图和示例?为了帮助做出更有数据依据的决定,我做了一个关键词探索工具,告诉你有多少条推文包含该关键词,并让你预览那些推文实际上是什么。这有助于探索您的客户经常向您询问的问题以及如何回应他们,因为我们也有可以查看的出站数据。
基于关键字过滤推文,以探索我的数据中的主题。图片作者。
我还找到了一种方法来估计我的 Twitter 数据中意图或主题的真实分布,并绘制出来。很简单。你从你的意图开始,然后你想代表那个意图的关键词。
{"update":['update'],
"battery": ['battery','power'],
"forgot_password": ['password', 'account', 'login'],
"repair": ['repair', 'fix', 'broken'],
"payment": ['payment'}
图片作者。
我也鼓励你查看 2 个、3 个甚至 4 个关键词的组合,看看你的数据是否自然地包含了同时具有多种意图的推文。在下面的例子中,您可以看到* 500 条推文同时包含了更新、电池和维修关键词。很明显,在这些推文中,客户希望解决他们的电池问题,这可能是由他们最*的更新引起的。
图片作者。
请记住,这一切都是为了让你的意图桶与众不同,范围广泛。
5.发展
至于这个开发方面,这是您实现您认为最适合您的上下文的业务逻辑的地方。我喜欢用“这解决你的问题了吗”这样的肯定语来重申一个意图。
出于演示的目的,我使用了 Streamlit。它不是部署的理想位置,因为很难动态显示对话历史,但它可以完成工作。实际上,您将部署在一个消息*台上。例如,您可以使用 Flask 在 Facebook Messenger 和其他*台上部署您的聊天机器人。你也可以使用 api.slack.com 进行整合,并在那里快速构建你的 Slack 应用。
对话界面是一个全新的话题,随着我们走向未来,它有着巨大的潜力。有很多指南可以帮助你设计这些对话式界面的 UX 设计。
下一步是什么?
在本文中,我将向您展示如何进行数据生成、意图分类和实体提取。这三个步骤对于制作聊天机器人是绝对必要的。然而,要让聊天机器人功能齐全、感觉自然,还有很多工作要做。这主要取决于你如何将当前的对话状态映射到聊天机器人应该采取的行动——或者简而言之,对话管理。
如果需要回答特定的意图,机器人需要准确地学习何时执行像倾听这样的动作,以及何时询问重要的信息。
以天气机器人为例,当用户询问天气时,机器人需要能够回答该问题的位置,以便它知道如何进行正确的 API 调用来检索天气信息。因此,对于天气检索这一特定目的,将位置保存到内存中的一个槽中是很重要的。如果用户没有提到位置,机器人应该会问用户用户在哪里。要求 bot 对世界上每个城市的天气进行 API 调用是不现实的,也是低效的。
我推荐看看这个视频和 Rasa 文档,看看 Rasa NLU(用于自然语言理解)和 Rasa 核心(用于对话管理)模块是如何被用来创建智能聊天机器人的。我谈了很多关于 Rasa 的事情,因为除了数据生成技术,我还从他们的大师班视频中学到了我的聊天机器人逻辑,并理解了如何使用 Python 包来实现它。他们的框架提供了很多可定制性,以便在聊天机器人的不同阶段使用不同的策略和技术(例如是否使用 LSTMs 或 SVMs 进行意图分类,甚至当机器人对其意图分类没有信心时如何后退的更细粒度的细节)。
此外,我想使用一个元模型来更好地控制我的聊天机器人的对话管理。一个有趣的方法是为此使用变压器神经网络(参考 Rasa 就此发表的论文,他们称之为变压器嵌入对话策略)。这基本上有助于你有更多的自然感觉的对话。
最后,扩展我的聊天机器人也很重要。这只是意味着扩展我的聊天机器人能够响应的意图和实体的领域,以便它覆盖最重要的领域和边缘情况。记住我做的这个框架可以移植到任何其他聊天机器人上是很有帮助的,所以我希望将来也能支持其他语言!
感谢阅读!
当然,这是我在过去一个月里通过观看 NLP 讲座、git 克隆许多 Github repos 亲自动手研究它们是如何工作的、YouTube 视频搜索和文档搜索所了解到的。因此,如果你有任何关于如何改进我的聊天机器人的反馈,或者如果有比我目前的方法更好的做法,请评论或联系我!我总是努力做出我能提供的最好的产品,并且总是努力学习更多。
Python 数据可视化完全指南
原文:https://towardsdatascience.com/complete-guide-to-data-visualization-with-python-2dd74df12b5e?source=collection_archive---------3-----------------------
让我们来看看使用 Python 进行数据可视化的主要库,以及可以使用它们完成的所有类型的图表。我们还将看到在每种情况下推荐使用哪个库,以及每个库的独特功能。
我们将从直接查看数据的最基本的可视化开始,然后我们将继续绘制图表,最后,我们将制作交互式图表。
数据集
我们将使用两个数据集,它们将适应我们在文章中展示的可视化效果,数据集可以在这里下载。
它们是关于人工智能相关的三个术语(数据科学、机器学习和深度学习)在互联网上的搜索热度的数据。它们是从一个著名的搜索引擎中提取出来的。
有两个文件 temporal.csv 和 mapa.csv 。我们将在本教程的大部分内容中使用的第一个术语包括这三个术语在一段时间内的流行度数据(从 2004 年到现在,2020 年)。此外,我还添加了一个分类变量(1 和 0)来演示带有分类变量的图表的功能。
文件 mapa.csv 包含按国家划分的流行度数据。我们将在文章的最后一部分使用它来处理地图。
熊猫
在我们进入更复杂的方法之前,让我们从最基本的数据可视化方式开始。我们将简单地使用 pandas 来查看数据,并了解数据是如何分布的。
我们必须做的第一件事是可视化一些例子,看看有哪些列,它们包含什么信息,值是如何编码的…
import pandas as pd
df = pd.read_csv('temporal.csv')
df.head(10) #View first 10 data rows
使用 describe 命令,我们将看到数据是如何分布的,最大值、最小值、*均值…
df.describe()
使用 info 命令,我们可以看到每一列包含什么类型的数据。我们可能会发现这样一种情况,当使用 head 命令查看某列时,该列看起来是数字,但是如果我们查看后续数据,就会发现值是字符串格式的,那么该变量将被编码为字符串。
df.info()
默认情况下,pandas 限制它显示的行数和列数。这通常会困扰我,因为我希望能够可视化所有的数据。
使用这些命令,我们增加了限制,并且可以可视化整个数据。对于大数据集,请小心使用这个选项,我们可能会在显示它们时遇到问题。
pd.set_option('display.max_rows', 500)
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1000)
使用 Pandas 样式,我们可以在查看表格时获得更多信息。首先,我们定义一个格式字典,以便数字以清晰的方式显示(有一定数量的小数、相关格式的日期和小时、百分比、货币……)不要惊慌,这只是一个显示,不会改变数据,您稍后处理它不会有任何问题。
为了给出每种类型的示例,我添加了货币和百分比符号,尽管它们对该数据没有任何意义。
format_dict = {'data science':'${0:,.2f}', 'Mes':'{:%m-%Y}', 'machine learning':'{:.2%}'}#We make sure that the Month column has datetime format
df['Mes'] = pd.to_datetime(df['Mes'])#We apply the style to the visualization
df.head().style.format(format_dict)
我们可以用颜色突出最大值和最小值。
format_dict = {'Mes':'{:%m-%Y}'} #Simplified format dictionary with values that do make sense for our data
df.head().style.format(format_dict).highlight_max(color='darkgreen').highlight_min(color='#ff0000')
我们使用颜色渐变来显示数据值。
df.head(10).style.format(format_dict).background_gradient(subset=['data science', 'machine learning'], cmap='BuGn')
我们也可以用条形显示数据值。
df.head().style.format(format_dict).bar(color='red', subset=['data science', 'deep learning'])
此外,我们还可以结合上述功能,生成一个更复杂的可视化。
df.head(10).style.format(format_dict).background_gradient(subset=['data science', 'machine learning'], cmap='BuGn').highlight_max(color='yellow')
点击这里了解更多关于熊猫的可视化样式:https://Pandas . pydata . org/Pandas-docs/stable/user _ guide/style . html
熊猫简介
Pandas profiling 是一个使用我们的数据生成交互式报告的库,我们可以看到数据的分布、数据的类型以及可能存在的问题。它非常容易使用,只用 3 行代码我们就可以生成一个报告,我们可以发送给任何人,即使你不懂编程也可以使用。
from pandas_profiling import ProfileReport
prof = ProfileReport(df)
prof.to_file(output_file='report.html')
你可以看到从文章中使用的数据生成的交互报告,这里。
你可以在这篇文章中找到更多关于熊猫简介的信息。
Matplotlib
Matplotlib 是图形化可视化数据的最基本的库。它包括了许多我们能想到的图表。仅仅因为它是基本的,并不意味着它不强大,我们将要谈到的许多其他数据可视化库都是基于它的。
Matplotlib 的图表由两个主要部分组成,轴(界定图表区域的线条)和图形(我们在这里绘制轴、标题和轴区域之外的东西)。现在让我们创建一个尽可能简单的图表:
import matplotlib.pyplot as plt
plt.plot(df['Mes'], df['data science'], label='data science') #The parameter label is to indicate the legend. This doesn't mean that it will be shown, we'll have to use another command that I'll explain later.
我们可以在同一个图形中制作多个变量的图形,从而进行比较。
plt.plot(df['Mes'], df['data science'], label='data science')
plt.plot(df['Mes'], df['machine learning'], label='machine learning')
plt.plot(df['Mes'], df['deep learning'], label='deep learning')
不是很清楚每种颜色代表哪个变量。我们将通过添加图例和标题来改进图表。
plt.plot(df['Mes'], df['data science'], label='data science')
plt.plot(df['Mes'], df['machine learning'], label='machine learning')
plt.plot(df['Mes'], df['deep learning'], label='deep learning')
plt.xlabel('Date')
plt.ylabel('Popularity')
plt.title('Popularity of AI terms by date')
plt.grid(True)
plt.legend()
如果您正在从终端或脚本使用 Python,在使用我们上面编写的函数定义图形之后,使用 plt.show()。如果您正在 jupyter 笔记本上工作,请在文件的开头内联添加%matplotlib,并在制作图表之前运行它。
我们可以在一个图形中制作多个图形。这非常适用于比较图表,或者使用单个图像轻松共享多种图表类型的数据。
fig, axes = plt.subplots(2,2)
axes[0, 0].hist(df['data science'])
axes[0, 1].scatter(df['Mes'], df['data science'])
axes[1, 0].plot(df['Mes'], df['machine learning'])
axes[1, 1].plot(df['Mes'], df['deep learning'])
我们可以为每个变量的点绘制不同风格的图形:
plt.plot(df['Mes'], df['data science'], 'r-')
plt.plot(df['Mes'], df['data science']*2, 'bs')
plt.plot(df['Mes'], df['data science']*3, 'g^')
现在让我们来看几个我们可以用 Matplotlib 做的不同图形的例子。我们从散点图开始:
plt.scatter(df['data science'], df['machine learning'])
条形图示例:
plt.bar(df['Mes'], df['machine learning'], width=20)
直方图示例:
plt.hist(df['deep learning'], bins=15)
我们可以在图形中添加一段文字,用我们在图形中看到的相同单位来表示文字的位置。在文本中,我们甚至可以在 TeX 语言之后添加特殊字符
我们还可以添加指向图上特定点的标记。
plt.plot(df['Mes'], df['data science'], label='data science')
plt.plot(df['Mes'], df['machine learning'], label='machine learning')
plt.plot(df['Mes'], df['deep learning'], label='deep learning')
plt.xlabel('Date')
plt.ylabel('Popularity')
plt.title('Popularity of AI terms by date')
plt.grid(True)
plt.text(x='2010-01-01', y=80, s=r'$\lambda=1, r^2=0.8$') #Coordinates use the same units as the graph
plt.annotate('Notice something?', xy=('2014-01-01', 30), xytext=('2006-01-01', 50), arrowprops={'facecolor':'red', 'shrink':0.05})
图库示例:
在此链接:https://matplotlib.org/gallery/index.html我们可以看到可以用 Matplotlib 完成的所有类型图形的示例。
海生的
Seaborn 是一个基于 Matplotlib 的库。基本上,它给我们的是更好的图形和函数,只用一行代码就可以制作复杂类型的图形。
我们导入这个库,并用 sns.set()初始化图形的样式,如果没有这个命令,图形仍然具有与 Matplotlib 相同的样式。我们展示一个最简单的图形,一个散点图
import seaborn as sns
sns.set()
sns.scatterplot(df['Mes'], df['data science'])
我们可以在同一张图中添加两个以上变量的信息。为此,我们使用颜色和大小。我们还根据类别列的值制作了一个不同的图表:
sns.relplot(x='Mes', y='deep learning', hue='data science', size='machine learning', col='categorical', data=df)
Seaborn 提供的最受欢迎的图形之一是热图。通常使用它来显示数据集中变量之间的所有相关性:
sns.heatmap(df.corr(), annot=True, fmt='.2f')
另一个最流行的是 pairplot,它向我们展示了所有变量之间的关系。如果您有一个大型数据集,请小心使用此函数,因为它必须显示所有数据点的次数与列数一样多,这意味着通过增加数据的维度,处理时间会呈指数增长。
sns.pairplot(df)
现在让我们做一个 pairplot,展示根据分类变量的值划分的图表
sns.pairplot(df, hue='categorical')
一个非常有用的图表是联合图,它允许我们看到散点图和两个变量的直方图,并看到它们是如何分布的:
sns.jointplot(x='data science', y='machine learning', data=df)
另一个有趣的图形是小提琴图:
sns.catplot(x='categorical', y='data science', kind='violin', data=df)
我们可以在一个图像中创建多个图形,就像我们使用 Matplotlib 一样:
fig, axes = plt.subplots(1, 2, sharey=True, figsize=(8, 4))
sns.scatterplot(x="Mes", y="deep learning", hue="categorical", data=df, ax=axes[0])
axes[0].set_title('Deep Learning')
sns.scatterplot(x="Mes", y="machine learning", hue="categorical", data=df, ax=axes[1])
axes[1].set_title('Machine Learning')
例子图库:
在这个链接中,我们可以看到用 Seaborn 可以做的一切事情的例子。
散景
Bokeh 是一个允许你生成交互式图形的库。我们可以将它们导出到一个 HTML 文档中,与任何拥有网络浏览器的人共享。
当我们有兴趣在图形中寻找东西,并且希望能够放大和移动图形时,它是一个非常有用的库。或者当我们想要分享它们,并给另一个人探索数据的可能性时。
我们首先导入库并定义保存图形的文件:
from bokeh.plotting import figure, output_file, save
output_file('data_science_popularity.html')
我们画出我们想要的并保存在文件中:
p = figure(title='data science', x_axis_label='Mes', y_axis_label='data science')
p.line(df['Mes'], df['data science'], legend='popularity', line_width=2)
save(p)
你可以通过点击这里看到文件data _ science _ popularity . html的样子。它是交互式的,你可以随意移动和放大图片
将多个图形添加到单个文件:
output_file('multiple_graphs.html')s1 = figure(width=250, plot_height=250, title='data science')
s1.circle(df['Mes'], df['data science'], size=10, color='navy', alpha=0.5)
s2 = figure(width=250, height=250, x_range=s1.x_range, y_range=s1.y_range, title='machine learning') #share both axis range
s2.triangle(df['Mes'], df['machine learning'], size=10, color='red', alpha=0.5)
s3 = figure(width=250, height=250, x_range=s1.x_range, title='deep learning') #share only one axis range
s3.square(df['Mes'], df['deep learning'], size=5, color='green', alpha=0.5)p = gridplot([[s1, s2, s3]])
save(p)
点击可以看到文件 multiple_graphs.html 的样子。
示例图库:
在这个链接中https://docs.bokeh.org/en/latest/docs/gallery.html你可以看到用散景可以做的所有事情的示例。
阿尔泰尔
在我看来,Altair 并没有给我们已经讨论过的其他库带来任何新的东西,因此我不会深入讨论它。我想提一下这个库,因为也许在他们的示例库中,我们可以找到一些可以帮助我们的特定图形。
范例库:
在这个链接里你可以找到所有你能用 Altair 做的范例库。
薄层
Folium 是一个允许我们绘制地图和标记的库,我们也可以在上面绘制我们的数据。让我们选择地图供应商,这决定了地图的风格和质量。在本文中,为了简单起见,我们只将 OpenStreetMap 视为一个地图提供商。
使用地图是相当复杂的,值得单独撰写一篇文章。在这里,我们只看一些基础知识,并用现有的数据画几张地图。
让我们从基础开始,我们将画一个简单的地图,上面什么也没有。
import folium
m1 = folium.Map(location=[41.38, 2.17], tiles='openstreetmap', zoom_start=18)
m1.save('map1.html')
我们为地图生成一个交互式文件,你可以随意移动和缩放。这里可以看到。
我们可以在地图上添加标记:
m2 = folium.Map(location=[41.38, 2.17], tiles='openstreetmap', zoom_start=16)folium.Marker([41.38, 2.176], popup='<i>You can use whatever HTML code you want</i>', tooltip='click here').add_to(m2)
folium.Marker([41.38, 2.174], popup='<b>You can use whatever HTML code you want</b>', tooltip='dont click here').add_to(m2)m2.save('map2.html')
您可以看到交互式地图文件,您可以通过点击此处点击标记。
在开始展示的数据集中,我们有国家名称和人工智能术语的流行程度。快速可视化后,您会发现有些国家缺少其中一种价值观。我们将把这些国家排除在外,以便于操作。然后,我们将使用 Geopandas 将国家名称转换为可以在地图上绘制的坐标。
from geopandas.tools import geocode
df2 = pd.read_csv('mapa.csv')
df2.dropna(axis=0, inplace=True)df2['geometry'] = geocode(df2['País'], provider='nominatim')['geometry'] #It may take a while because it downloads a lot of data.
df2['Latitude'] = df2['geometry'].apply(lambda l: l.y)
df2['Longitude'] = df2['geometry'].apply(lambda l: l.x)
现在我们有了用纬度和经度编码的数据,让我们在地图上表示它。我们将从一张泡泡地图开始,我们将在这些国家上画圈。它们的大小将取决于术语的流行度,并且它们的颜色将是红色或绿色,这取决于它们的流行度是否高于某个值。
m3 = folium.Map(location=[39.326234,-4.838065], tiles='openstreetmap', zoom_start=3)def color_producer(val):
if val <= 50:
return 'red'
else:
return 'green'for i in range(0,len(df2)):
folium.Circle(location=[df2.iloc[i]['Latitud'], df2.iloc[i]['Longitud']], radius=5000*df2.iloc[i]['data science'], color=color_producer(df2.iloc[i]['data science'])).add_to(m3)m3.save('map3.html')
点击这里可以查看互动地图文件。
在任何给定的时间使用哪个库?
有了这么多种类的库,您可能想知道哪个库最适合您的项目。快速的答案是库,让您可以轻松地制作您想要的图形。
对于一个项目的初始阶段,随着熊猫和熊猫概况,我们将快速可视化,以了解数据。如果我们需要可视化更多的信息,我们可以使用简单的图表,我们可以在 matplotlib 中找到散点图或直方图。
对于项目的高级阶段,我们可以在主要库(Matplotlib、Seaborn、Bokeh、Altair)的图库中搜索我们喜欢并适合项目的图形。这些图形可用于在报告中给出信息,制作交互式报告,搜索特定值,…
Python 线性回归完全指南
原文:https://towardsdatascience.com/complete-guide-to-linear-regression-in-python-d95175447255?source=collection_archive---------23-----------------------
在本文中,我们将使用 sklearn 在波士顿房价数据集上理解和实现线性回归
Emil Widlund 在 Unsplash 上的照片
什么是线性回归?
线性回归是一种有监督的机器学习算法。它根据给定的因变量(x) 预测自变量(y) 之间的线性关系。使得自变量(y)** 具有最低成本。**
应用于数据的线性回归,作者提供照片
线性回归工作
为了解释线性回归的工作原理,我们首先必须假设我们有一些数据,当我们在散点图上绘制这些数据时,我们会得到一个类似这样的图。
数据散点图,作者照片
现在,如果我们将线性回归应用于它,那么它将计算数据之间的关系/线,使得线是距离数据中的所有点最*的。换句话说,它会计算出温度(x) 和冰淇淋(y) 销量之间的关系,并告诉我们在什么温度下销量会大于销量以及在什么温度下销量会小于。********
我们如何找到我们数据之间的这条线/关系?
现在,在我们深入探讨这个问题之前,我们应该先了解一些术语。
- 假设表示
- 成本函数
- 梯度下降
假设表示
假设表示是我们的线的方程,我们用来表示给定的数据之间的关系。
假设表示公式,作者照片
现在,这个方程一开始可能会令人困惑,有些人可能很难把它想象成直线的方程。但是如果我们考虑直线的方程,那就是 y = mx + c 。
在线的方程中, m 对应的是斜率, x 是具有某值的变量 , c 是一个常数。
在假设表示中, θ1 对应斜率, x 为具有某值的变量, θ0 为常数。
所以这里的 θ0 & θ1 都是的参数,它们的初始值是我们手动设置的,但之后又进一步修改为线在数据中完美设置。
价值函数
现在,每当我们第一次绘制数据和计算线/关系时,我们都必须选择一些参数,如那条线的起点****和线的斜率。因此,首先,我们不知道任何这些东西的值,我们假设两个参数的值,然后对我们的数据应用成本函数来检查误差(点和我们的线的距离 b/w)。****
现在首先我会给你看我们的成本函数的数学版本,然后我会在下面解释它。
*方误差成本函数,作者照片
重要符号:
- m 代表训练样本总数****
- x(i) 代表输入变量 (x(1)表示第一个训练示例)****
- y(i) 代表输出变量****
所以在这个成本函数中,(hθ(x)-y)项用我们的给定值 (y) 减去预测值 ( x) ,这样我们就找到了我们的线和给定点之间的误差(距离)。然后我们取答案的*方,以防得到的值是一个负数。之后,我们对所有训练示例和求和并将乘以 1/2m ,取*均值作为我们训练示例误差。
我们的假设和给定数据之间的误差,中等
【细化 1 / 2m(可选)
现在,我们在这里看到的是这个等式被乘以 1/2m 。这里的 m 是取我们误差的均值/*均值,这里的 2 是因为当我们取成本函数的导数时,在更新时使用参数在坡度下降时,即 2 在功率****
梯度下降
现在,当我们对成本函数 & 假设表象有了更好的理解,由此我们走向第三项,梯度下降。
所以,现在我们已经成功地实现了成本函数,并且得到了一些成本(误差)> > 0 。为了减少这个成本(误差)我们应用梯度下降,其中我们更新参数θ0 & θ1 的值,并且保持更新它们,直到我们的成本(误差)几乎等于 0 。因此,梯度下降的数学公式如下****
梯度下降公式,中等
重要符号:
- m 代表**训练样本总数**
- α 代表α也叫**学习率**
- x(i) 代表输入变量 (x(1)表示第一个训练样本)
- y(i) 代表**输出变量**
好了,现在深入这个公式,我们可以看到 θ0 & θ1 在不断变化,直到成本函数达到其最小值。它的意思是,我们将继续改变 θ0 & θ1 的值,直到我们的参数达到值,其中 c ost(误差)将是最小的。****
现在,如果你看到我们在 α 之后有一个类似于成本函数的等式,那是因为梯度下降是成本函数的导数。
突出成本函数的导数,中
这里我们将我们的成本函数的导数 (*方误差成本函数)乘以 α ,从当时的 θ 的当前值中减去α,得到一个新值 theta (θ) 。
选择α的值
我们总是选择 α 的一个非常小的值,因为每次迭代后 θ 值的变化取决于 α 的值(如等式所示)。因此,通过选择 α 的非常小的值,我们的假设采取非常小的步骤并达到其最低成本。通过使用大值的 α ,我们可能开始采取大的步骤,并且可能错过全局最小值,其中我们的成本(误差)将是最低的。
使用小值的 α 与使用大值的 α,作者照片
澄清第二方程中的 x
现在有些人可能会奇怪,在第二个方程中,一个额外的 x(i) 正被乘以我们的方程,而在第一个方程中什么也没有。这里有一个 x(0) ,是用乘以得到的等式,但是我们没有写下来,因为这是偏差,并且总是等于 1。****
梯度下降作业
现在梯度下降所做的是它采取小婴儿步骤并且在每个步骤中,它将假设(线)向位置收敛,在那里我们的成本(误差)将会是最小。
假设收敛到全局最小值,图像来自介质
从 这里 阅读更多关于成本函数和梯度下降。****
应用线性回归的步骤:
现在我们对假设表示、成本函数、和梯度下降有了很好的理解。因此,让我们将线性回归应用于我们的数据集。
****线性回归可应用于以下步骤:
- 绘制我们的数据(x,y)。
- 取随机值 θ0 & θ1 并初始化我们的假设。
- 在我们的假设上应用成本函数,并计算其成本。
- 如果我们的花费> > 0** ,那么应用梯度下降和更新我们的参数θ0 & θ1 的**值。****
- 继续计算第 3 步和第 4 步,直到我们的成本接*等于 0 或最小。
- 如果我们的成本已经达到它的全局最小值,那么我们停止应用成本函数和梯度下降,现在我们已经成功地训练了我们的算法来预测我们的数据之间正确的关系。
对我们的数据集应用线性回归
现在,当我们很好地理解了线性回归的工作原理后,让我们使用 Python 的著名的机器学习库、 Scikit-learn 将其应用于一个数据集。
什么是 Scikit-learn?
Scikit-learn (又称 sklearn )是一个针对 Python 的机器学习库。它包括各种分类、回归、和聚类算法以及支持向量机(SVM) 、随机森林、梯度提升、、 k -means 和 DBSCAN ,并且被设计为与类似**的 Python 库一起工作**
使用 Sklearn 进行线性回归
****线性回归是一种非常直接且易于使用的算法。特别是在这个 Scikit learn 库的帮助下,它的实现和使用变得相当容易。现在,我们开始使用 Sklearn 。
首先我们需要一些数据对其应用线性回归。因此,我们将使用来自 sklearn 的波士顿房价数据集。
在 Python 中导入波士顿数据集
from sklearn.datasets import load_boston
boston = load_boston()
在 Python 中导入其他库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
检查内容我们的数据集
print(boston.keys())
打印输出(波士顿['target'])代码
这些键中的每一个都包含了大量的信息和数据。
- ' data '键包含我们将提供给模型的数据,它也可以被假定为输入(x)变量。可以使用
boston.data
代码进行访问。 - ' target '键包含我们的模型应该预测的输出数据(y)。可以使用
boston.target
代码访问它。 - ' feature_names '键包含我们的数据的列/特征的名称。也可以使用
boston.feature_names
代码访问它们。 - ' DESCR '键将为我们提供关于数据集的所有信息,其中的列数,甚至每一列的细节/描述。我们可以使用
print(boston['DESCR'])
代码获取这些信息。 - “文件名键给了我们这个(波士顿房价)文件的位置。我们可以使用
print(boston['filename'])
代码获得位置。
创建数据帧
现在,为了向前推进并以一种有组织的和可行的方式查看我们的数据,我们将使用 Pandas 创建一个数据框。
bostondf = pd.DataFrame(boston.data, columns=boston.feature_names)
在我们的数据框架被创建并且我们的数据被组织之后。我们使用bostondf.head()
检查数据集的头部。这为我们提供了数据集的整体清晰度/图像。
我们数据框的头
现在,如果我们不明白每一列代表什么,我们可以使用我们之前讨论过的print(boston['DESCR'])
代码来检查每一列的细节。
现在,在对我们的数据做了一些特征工程**之后,当我们觉得我们的数据现在是可以传递给我们的模型的正确格式时,我们就向我们的下一步前进。
注意:我不是在这个数据集上做特征工程。**
将我们的数据集分割成训练、测试值
现在,当我们的数据准备好传递给我们的模型时,我们的第一步是将数据集分成两组,即训练集和测试集。
from sklearn.model_selection import train_test_split
X = bostondf
y = boston['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
这里,X = bostondf
中的 X 包含所有的特征/输入数据(x)** ,我们提供给我们的模型来预测的房价(y),y = boston['target']
中的 y 包含房价。所以现在我们数据的 67% 属于 training_set 而的 33% 属于 test_set 因为 test_size 被设置为 0.33 。**
导入线性回归()
在成功地将我们的数据分成测试和训练集之后,我们将使用 sklearn 和**fit**
将线性回归导入到我们的模型中,然后我们将预测我们的模型从我们的训练数据中学习得有多好。
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_train, y_train)
lr.score(X_test, y_test)
好了,我们在这两个步骤中所做的是,我们导入了 LinearRegression( ) 类,并创建了一个名为 lr 的 LinearRegression 对象。然后我们将我们的训练数据lr.fit(X_train, y_train)
拟合到模型中,为其提供输入特征(X_train)** 和输出值(y_train) 。在模型根据我们的训练数据对进行了训练之后,我们使用lr.score(X_test, y_test)*100
代码来检查我们的模型与我们的训练数据的拟合程度。它会根据 X_test 中提供的特征来预测房屋的**价格,然后将这些价格与 y_test 中给出的实际价格进行交叉核对。然后它会给我们一个 1-100 之间的浮点值,告诉我们模型的精度。****
该模型的精度**为 72.45 %。**
重要提示
现在,在检查了精度之后,如果我们的精度看起来不是很激励,我们应该继续到我们对我们的数据集进行特征工程的部分,并做一些更多的特征工程。这肯定会提高的结果。****
恭喜!我们已经在波士顿房价数据集上成功训练了我们的线性回归模型。
学习成果
到目前为止,我们已经了解了什么是假设表示、代价函数、梯度下降以及它们是如何工作的。此外,我们还学习了如何从 scratch 在数据集上实现线性回归,以及如何使用 Python 著名的机器学习库即 Scikit-learn 构建机器学习模型。****
到目前为止,我们已经了解了什么是假设表示、成本函数、梯度下降以及它们是如何工作的。此外,我们还学习了如何从 scratch 在数据集上实现线性回归,以及如何使用 Python 著名的机器学习库即 Scikit-learn 构建机器学习模型。****
零售业机器学习和深度学习完全指南
原文:https://towardsdatascience.com/complete-guide-to-machine-learning-and-deep-learning-in-retail-ca4e05639806?source=collection_archive---------61-----------------------
商店还没有死
这里有更多有趣的图表!
商店在变化。我们看到它在我们眼前发生,即使我们并不总是意识到这一点。渐渐地,它们正成为日益复杂的顾客旅程中的一个额外步骤。得益于数字化和零售自动化,商店本身不再是目的,而是服务于整个品牌需求的手段。体验的质量、归属感和认同感、购买的舒适度……所有这些参数现在都与每*方米的销售额一样重要,因此必须服从数据科学及其“智能算法”(又名机器学习和深度学习形式的人工智能)规定的优化。
首先,人工智能的使用是竞争的需要。事实上,电子商务玩家不会等待任何人:例如,注意在线搜索结果对最终客户的调整,或者基于数字档案的推荐。这两个方面是砖头和砂浆做不到的(目前来说)。但是,实体商业有自己的优势。嗅觉、视觉、听觉等。数据可以用来给消费者一种体验某种独特的、专为他们制造的东西的感觉。除了改善客户关系,人工智能还使寻求解决长期以来一直是零售商负担的问题成为可能:更好的库存管理、商店空间的优化、员工时间的优化…
我们在下面展示了深度学习/机器学习用例的完整视图,这些用例是为了创建未来的商店而实现的,并有现实生活中的例子支持。
1.调整商店及其库存,以便更好地为顾客服务
众所周知,电子商务参与者可以使用动态统计数据实时优化他们的网站。这使他们能够根据可用资源和预定义的客户细分来定义最有效的策略。像任何物理空间一样,商店没有这种奢侈。
然而,这并不妨碍物理空间的周期性优化,这要归功于从智能算法中收集的洞察力。回到过去(不到 20 年前),我们会雇佣学生跟踪和清点商店特定区域的顾客。谢天谢地,这些时代已经过去了。热图、*均路线图、在屏幕上花费的时间、与总出席率相关的各种比率、相关性……商店里的摄像头和计算机视觉算法现在提供了基于图像的可操作工具。如今,热图和活动识别解决方案不仅有助于定位促销活动,还能帮助制定整体营销策略,并衡量每个部门的绩效以及产品植入的绩效。像 RetailFlux 这样的公司提供的解决方案可以分析商店视频,为零售商提供他们商店里的人数、他们进去后走的路以及他们在哪里逗留的数据。这有助于营销人员确定受欢迎的地点,使他们能够改变家具、展示、广告或员工的布局,以更好地服务他们的客户并增加收入。
随着技术的发展,我们也开始听说“人口统计识别”:这些由初创公司 DeepVision AI 、 MyStore-e 、retail dep和 RetailNext 创造的工具,让我们能够估计从摄像头前走过的人的年龄和性别,从而让商店能够进入这一点对营销人员和品类经理的理性化至关重要。
虽然这些摄像头经常挂在天花板上,但情况并非总是如此: Walgreens (与 Cooler Screens 合作),例如,最*将摄像头、传感器和数字屏幕集成到其商店的冷却器门中,以创建一个“智能”显示器网络,品牌可以使用它来针对特定类型的客户发布广告。这些门可以作为一个数字销售*台,以最佳方式展示食品和饮料,也可以作为一个店内广告牌,根据大致年龄、性别和当前天气等变量,向正在靠*的消费者展示广告。连接的冷却器内的摄像头和传感器还可以确定买家已经拿起或查看了哪些商品,让广告商了解他们的促销活动在屏幕上的效果,并在产品缺货时迅速通知零售商。
因此,关键问题从“在哪里”和“多少”变成了“谁”、“什么时候”、“多长时间一次”、“吃多少饼干?”。
2.增加利润的预测
这些数据与来自结账和忠诚度计划的数据相结合,是预测需求和创建商店集群的关键,从而改善零售商的供应链。通过更好地预测哪些产品将在某个领域表现良好,来自诸如Symphony RetailAI等初创公司的机器学习算法可以减少呆滞库存,帮助优化定价(和利润),并提高客户忠诚度(人们显然倾向于喜欢在最*的商店找到正确的产品组合)。
事实上,未售出的库存可能是零售业最大的障碍之一:未使用的库存每年给美国零售商造成大约 500 亿美元的损失。减少这一数字是该行业长期生存的关键:花在成为死库存的东西上的每一美元都是宝贵的钱,可以用来培训人才,更好的研发,或者,最明显的,全新的智能算法。
预测也有助于零售商优化他们的促销活动:仓库里的死库存越少,促销就越有战略意义,而不仅仅是被动的。许多定价爱好者会特别欣赏这一点,因为这将使他们的工作容易得多,也不那么吃力不讨好。
3.提升店内体验的个性化
与网站可以实时适应最终用户的方式一样,商店也可以增加计算机视觉的粒度,使其能够针对个人。然而,这些算法基于比上述更多的元素,因此更复杂/更不可靠。为了在个人层面上工作,这些算法需要结合人口统计识别、忠诚度代码识别和增强现实,通常集成到镜子等智能物体中。
尽管这些解决方案无法大规模实施,但它们体现了商店销售方式的深刻变化。我们正从销售产品转向销售体验,在这种情况下,实物产品变成了副产品。这就是shopertainment的概念。对顾客来说,低廉的价格和丰富的目录已经不够了,他们可以在网上找到这样的价值主张。真实的品牌体验成为生存的关键:商店是吸引人的体验、想法和互动的仓库。
用例当然是众多的(即使它们经常与人工智能赤道的科幻技术术语边接壤):在 2019 年的 NRF ,谷歌展示了一个连接视觉识别数据和商店产品数据库的连接镜子。例如,在眼镜店的情况下,镜子可以识别测试的模型,并显示关于它的产品或营销信息。卖家还实时统计了镜子的使用情况:他们知道尝试某种类型眼镜的人已经在那里有一段时间了,或者在两副眼镜之间犹豫不决。这方便了销售人员的工作,他们可以向顾客推荐他们真正感兴趣的产品。
就其本身而言,H & M 已经与微软联合测试了一面通过语音指令进行自拍的镜子,而 Lululemon 的镜子则更像是一块板子,鼓励其客户参与该品牌创建和维护的社区。
智能镜子当然可以放置在购买过程的不同时间间隔: 拉夫·劳伦的位于试衣间,以改变试穿衣服时经常令人沮丧的体验。买家可以与镜子互动,改变试衣间的照明,并可以为自己的服装选择不同的尺寸或颜色,员工将获得这些。《镜报》还推荐了与正在尝试的食物相匹配的其他食物。
化妆品公司也采用了这些解决方案: 丝芙兰智能镜子使用一种智能算法,混合看镜子的人的性别、年龄、外貌和风格,以便提出建议。它甚至声称可以区分穿着中性或明亮颜色、大胆或保守风格以及带有花卉和几何图案的衣服的人。
通过深度学习,我们也看到了一项新技术的出现:情感计算。它是计算机识别、解释并可能激发情感的能力。确实有可能识别头部和身体运动等手势,同时声音的语气也能充分说明一个人的情绪状态。这些见解可用于商店,以免给显然不需要帮助或麻烦的顾客带来不便。这些技术仍然是新的(只有 可发布 提供零售用例)和侵入性的:因此最好不要评论未来的用例。
4.让顾客的购物体验更加顺畅
镜子、增强现实、虚拟现实……它们很少回应零售商及其客户的真正痛点。我们对这些痛点了如指掌:结账长度、快速产品本地化和库存管理……这些应该是商店寻求使用机器学习和深度学习解决方案的优先事项。
减少结账时的摩擦
例如,在中国,某些肯德基的顾客可以通过支付宝技术、将他们的面部图像与数字支付系统或银行账户关联后,坐在装有摄像头的 POS 机前进行购物。美国连锁店 Caliburger 也在它的一些餐厅测试了面部识别的想法:顾客第一次使用店内售货亭点餐时,他们被邀请使用(NECs)neo face的面部识别软件将他们的脸与他们的账户联系起来,以便从众多优势中受益。银行卡支付仍然是必要的,但如果初步测试阶段成功,该公司打算改用面部识别支付。
然而,对网络安全的担忧可能会阻止这种解决方案大规模问世。事实上,顾客越来越嫉妒他们的个人数据(这是正确的):根据 Wavestone 的一项研究,只有 11%的消费者准备在商店接受面部识别。对于移动应用程序的识别,这个数字上升到 40% 。
因此,人们正在考虑其他更可行的方法,利用计算机视觉让结账更加流畅。到目前为止,我们都很熟悉亚马逊 Go 的自动化商店(不太熟悉,希望是),它允许拥有 Prime 账户的顾客用手机上的代码进入商店,购物,然后离开商店,而不经过收银台。一种“跟踪”顾客的算法,购买的金额自动记入借方,发票通过电子邮件发送。这项技术的测试也正在与 XXII 合作在赌场 进行。
这个空间里有很多初创公司: 标准认知ZippinTrigo Vision……都声称帮助公司消除客户的结账。与此同时,中国正在通过欧尚的 宾果盒随意地改造商店的概念。
减少缺货
所有这些摄像头可以用来看的不仅仅是顾客:很多监控货架的解决方案确实出现了。他们提出在出现短缺的情况下向员工发送警报,以便迅速做出反应。
这对商店来说很关键:缺货代表北美每年超过 1290 亿美元的销售损失(约占收入的 4%)。不仅如此,缺货还会积极地将顾客推向竞争的怀抱:亚马逊 24%的收入来自在当地零售商那里经历过缺货的顾客。这样的解决方案有很多例子:在法国, 安格斯艾 与Les mousequetaires合作。在美国,沃尔玛自去年以来一直致力于这一概念,拥有 聚焦系统 的 ABInbev 也是如此。有趣的是, Yoobic 的解决方案提供了类似的过程,但相机掌握在个人手中,以便拍摄将由算法分析的照片。与此同时,在中国, Hema ( 阿里巴巴的未来商店)比世界上任何其他地方都更能推进扩张商店的边界。
通过语音技术提供购物建议
当然,图像不是商店里唯一可以分析的东西;语音在简化客户旅程方面也发挥着作用。这种不太受欢迎的购物方式将迎来一场小小的革命:根据 C 战略咨询公司的数据,2017 年,13%的美国家庭拥有智能音箱。这个数字预计到 2022 年将上升到 55%。
亚马逊(Amazon)也是语音技术的领导者,这一事实表明了这家西雅图巨头对其实体统治的重视程度(已经征服了虚拟空间)。该品牌于 2019 年推出的 Echo Buds 与 Alexa 合作,在客户移动时回答它理解的任何问题。对于零售业来说,更有趣的是,它还会通知用户最*的全食超市(亚马逊拥有全食超市)是否有顾客正在寻找的商品。一旦他们被告知并进入商店,回声芽可以指引他们到正确的通道。你可以想象 Alexa 不仅会引导你找到一件商品,而且如果你告诉它你想做千层面,它还会引导你逛商店,让你以最快的方式挑选所有必要的配料。未来是耳朵** ( 懂了吗?)。**
虚拟助手确实在崛起。例如,玛氏公司已经与美国零售商 BevMo 合作。到测试 SmartAisle ,数字威士忌采购助理。通过混合人工智能、声控技术和货架上的 LED 灯, SmartAisle 帮助买家选择完美的威士忌酒瓶。快速交谈后推荐三瓶,相关货架亮起,引导顾客找到喜欢的瓶子。如果顾客心中已经有了一个品牌,店员可以推荐其他品牌或具有相似风味的瓶子。整个体验不超过 2 分钟。语音助手使它成为一种愉快和有益的体验,混合了戏谑和有用的信息。
从 NLP 到虚拟助理,上面的两个例子表明,如果使用得当,语音技术可以节省更多的员工时间,并为零售商提供关键数据。
机器人自动化
如果没有围绕机器人技术的讨论,关于改进和简化流程的讨论将是不完整的。这些长期以来被归入科幻小说的物品,现在在世界各地的商店中显示出它们的实用性。虽然机器人本身不是人工智能的一个子类,但在过道上漫游的机器人使用了计算机视觉和 NLP 的概念。就像亚马逊,沃尔玛在这里也处于技术的前沿: 【波沙·诺瓦】 机器人(被称为“Auto-S”)被设计用来扫描货架上的商品,以帮助价格准确性和重新进货,已经出现在他们的 1000 家商店中。这些六英尺高的设备每个都包含 15 个摄像头,可以扫描货架并实时向员工发送警报。这将员工从可重复、可预测的手动任务中解放出来,让他们有时间专注于销售和客户服务。
沃尔玛还推出了机器人,这些机器人可以清洁地板,从卡车上卸载和分拣物品,并在商店里接订单。有趣的是,这个利基市场正迅速变得极具竞争力, Simbe 的机器人已被部署在美国各地的 Schnuck 商店,其价值主张与波沙·诺瓦相同,而 Lowe 在 2016 年推出了一款可以理解并回答简单客户问题的机器人。几乎可以肯定的是,机器人技术的发展将在未来几个月加速。
5.预防损失的措施
“缩水”(盗窃)成本巨大:在欧洲范围内,€每年 490 亿欧元(占分销行业年营业额的 2.1%),对已经饱受价格战压力的分销商利润造成沉重负担。因此,安全成为一种迫切的需要。因为成本,自动化也是如此。这可以采取多种形式。例如,增强摄像头可以识别产品是否被隐藏,并提醒人们。然而,这将产生大量的假阳性,因为一个无所不知的摄像机在物理上是不可能的。诸如 Vaak 或 DeepCam AI 等公司声称,只有当访客的行为高度可疑时,才能通过向某人发出警报来避免这个问题。像 StopLift 这样的解决方案还可以检测“甜心交易”(员工假装进行交易,但实际上是在没有付款的情况下向熟人赠送产品)。重要的是要记住很大一部分商店盗窃是通过员工进行的。这些解决方案的投资回报率很容易计算:商店确切地知道他们因盗窃和错误而损失了多少。因此,这个用例可能是最先实现的用例之一。
结论
鉴于所有这些发展,尽管它们对零售商和客户都有许多好处,但客户向零售商询问谁有权访问数据以及如何使用数据是至关重要的。不言而喻,透明度必须是任何个人数据使用的口号,以保证消费者的私人生活得到保护。
如果你渴望开始你自己的公司人工智能项目,我建议直接跳到我关于这个问题的最新文章:你自己的公司人工智能项目的 10 个步骤。
这篇文章 原本是我的博客, 的 Pourquoi Pas。过来打个招呼。
媒体行业机器学习完全指南
原文:https://towardsdatascience.com/complete-guide-to-machine-learning-in-the-media-industry-714dc5b9908e?source=collection_archive---------67-----------------------
点击此处查看更多有趣的图表!
在过去的几年里,顾客旅程的日益数字化和云技术和计算能力的指数级提升邀请媒体集团重新思考他们做生意的方式。如果听起来我用了很长的词来说“数字颠覆”,请相信你的直觉。许多中断都集中在媒体集团可以访问的大量数据上,以及人工智能(AI)(更具体地说是机器学习)可以用这些数据做什么。事实上,尽管人工智能已经被过多的纯玩家( Spotify 、网飞、 Buzzfeed 、迪士尼……)完全接受,但传统玩家仍然落后,现在他们将这项技术视为实现急需的新增长的捷径。
下面是世界各地的老一代卫道士目前正在实施的用例的详细情况。
1.创建流程优化
元数据创建/索引自动化
使用机器学习,人工智能既可以翻译数据,也可以使用图像识别来自动创建所有类型内容的元数据(例如,描述一张图像,以便更容易通过谷歌找到)。这使得内部和外部的利益相关者能够更容易地发现内容,允许以更好的标准进行搜索,以获得更精确的结果。自动索引(以及多种数据格式的转换)加快了记者的工作速度,方便了事实的验证,并使人类能够专注于更有附加值的任务。福克斯、纽约时报、BBC……数十家媒体公司已经在其运营中实施了这些解决方案。
文章写作和视频创作的自动化
我们也看到了自动化低附加值文章写作工具的出现,从而使记者能够从事需要更多调查和更专业知识的主题。例如,Syllabs 为记者提供自动处理选举结果的机器人:他们的 Data2Content 工具在信息到达内政部网站后立即生成文本。《华盛顿邮报》的Heliograf从 2016 年开始就在体育方面做的差不多了。其他此类工具通过使用语音识别将音频信息转换为文本,可以大大加快文章写作或视频创作的速度。然后,这些文本被直接“重新编码”到视频中,这使得查找、验证和潜在的修改变得更加容易。
请注意,我们讨论的是非常简单的任务:大多数超越事实报告的机器学习测试都失败了(通常很搞笑)。
发现新趋势
第一个披露新闻故事的记者得到了所有的荣誉,故事就是这样。因此,最重要的是控制和预测信息流动,同时实时跟踪其传播,以便从竞争对手中脱颖而出。为此,路透社新闻机构的 R&D 团队开发了 新闻追踪器 工具,该工具通过一种算法识别 Twitter 上的重大事件。该工具为这些事件分配了一个“媒体分数”,这使得主要关注最重要的事件成为可能。新闻追踪专家也能够对这些事件的真实性产生信心。**
这最后一点特别重要,因为它符合媒体对信息可靠性的最高要求。
事实核查
事实上,一些算法也可以帮助记者验证社交网络上发布的图像和视频的可靠性和准确性。 ClaimBuster 和 FactMata 为例,是两家利用智能算法打击虚假信息和深度假货的初创企业。这是通过根据终端用户提供的数据为内容分配置信度指数来实现的。
2.内容的分发、个性化和推荐
尽管上述机会确实会对媒体市场产生破坏性影响,但它们只是机器学习为媒体行业提供的机会的一小部分。虽然科幻爱好者热切期待内容创作的自动化,但人工智能的主要影响将通过内容改编和呈现给观众的过程来实现。
随着市场产生大量质量和吸引力各不相同的内容,有效的配对是将这些内容转化为一套适合每个最终消费者或最终消费者群体的价值主张。这种粒度有多种变化方式:****
它意味着在正确的地方有正确的内容
以 Buzzfeed 和它的 400 个分销渠道为例。利用人类的智慧将正确的内容放在正确的地方将是耗时的,并且任何优化都是非常不完美的。因此,该公司使用人工智能来告知一篇文章的病毒式传播概率,并在最适合公众的频道上推广它,使公众有最大的欣赏机会。这个概率是产品、社交媒体、工程和数据科学团队共同努力的产物,他们基于高性能内容的历史数据开发了一个机器学习模型。
它意味着在正确的时间选择正确的内容
死人复活了。瑞士杂志 Le Temps 使用的机器学习解决方案Zombie ,能够通过交叉引用其档案与来自 Chartbeat (向全球出版商提供数据和分析)和 Google Analytics 的数据来识别该杂志的最佳文章。然后,该算法根据定性指标(阅读时间、受众历史、社交网络上引起的参与度和辩论……)分配相关性分数,并建议重新发布和接触新受众的最佳时间。这给了内容第二次生命,随之而来的收入可以直接到达底线。
它意味着为合适的人群提供合适的内容
Business Insider 的内容比任何人能(或想)阅读或观看的都多。得益于初创企业 Sailthru 的解决方案,出版商因此根据消费内容的历史(由 cookies 跟踪)创建了简档。根据他们的个人资料,网站和电子邮件都会为读者提供合适的内容。这种对读者细分的投资使得 Business Insider 和的点击率分别提高了 60%和 150% 。此外,返回网站的流量跃升了 52% 。
****这里最重要的是要注意,这些工具通过提供与现有观点一致的内容,非常有能力进一步分化我们的社会,它们在媒体中的使用不应被轻易接受。
它不能(还)意味着正确的内容适合正确的人
一种算法可以基于上下文数据和客户旅程做出决策,但几乎无法理解每一个客户的偏好:喜欢和不喜欢很少是稳定的,通常是高度上下文相关的。人类口味的多样性暂时仍困扰着机器。因此,任何个人层面的个性化目前都必须由策展人协助。然而,许多这样的角色只是推迟了看似不可避免的事情:根据路透社 T2 的一项研究,几乎四分之三(72%)的媒体玩家计划积极尝试人工智能,以改善推荐并提高制作效率。
3.货币化
由于货币化是传统媒体生存的最重要杠杆之一,从客户参与到广告空间,许多用例开始在这一领域出现。
付费墙
许多主要出版物都以某种形式使用付费墙(一种限制付费用户访问网站的系统)。它通常以在阅读有限数量的文章后阻止内容的形式出现。在这里,人工智能也提供了一个更具活力、更少胁迫的价值主张。以瑞士报业集团Neue zürcher Zeitung为例,该集团使用一种结合了 100 个标准的算法来确定互联网用户最有可能在什么时候触发他的付费参与。一旦发现合适的时机,就会为潜在客户显示个性化的登录页面。三年内转化率乘以 5,结果令人信服。
实时竞价
我们可以想象,当智能算法支持时,实时竞价(RTB)将找到新的维度,特别是在供应商方面:机器学习算法可以优化申请人的选择,管理数据传输的成本,提高绩效的可见性,避免欺诈,甚至检查广告的质量。然而,这样的例子在今天的市场上仍然非常罕见。
结论
A.我将影响媒体价值链的所有部分,帮助内容创作者更具创造性,帮助内容出版商更具生产力,帮助消费者找到符合他们兴趣的内容。
然而,人工智能只是业务优化战略连续性逻辑的一部分,因此,不应被视为一场革命。这一事实以现在的方式最大限度地减少了实现背后的工作:正如科学家 Peter Skomoroch 去年提到的那样:“你可以预计你的公司向机器学习的过渡比你向移动设备的过渡要困难大约 100 倍。
这个故事 本来是为我的博客写的, 这个 Pourquoi Pas。过来打个招呼。
Python 交叉验证的完整指南及示例
原文:https://towardsdatascience.com/complete-guide-to-pythons-cross-validation-with-examples-a9676b5cac12?source=collection_archive---------2-----------------------
Sklearn 的 KFold,洗牌,分层,以及它对训练集和测试集中数据的影响。
sklearn 交叉验证的示例和用例,解释了 KFold、洗牌、分层以及训练集和测试集的数据比率。
使用两个折叠的源数据的示例性分割,图标由 Freepik 提供
交叉验证是机器学习中的一个重要概念,它在两个主要方面帮助了数据科学家:它可以减少数据的大小并确保人工智能模型足够健壮。交叉验证是以消耗资源为代价的,所以在决定使用它之前,理解它是如何工作的是很重要的。
在本文中,我们将简要回顾交叉验证的好处,然后我将使用流行的 python Sklearn 库中的各种方法向您展示详细的应用。我们将学习:
- 什么是折叠、洗牌折叠和分层折叠,看看它们有什么不同
- 如何使用 cross_validate 和 cross_val_score 方法在没有 KFold 的情况下交叉验证您的模型
- 其他的分割选项是什么——重复折叠、离开和离开,以及分组折叠的用例
- 考虑目标和特征分布有多重要
好处 1:减少数据量
通常你把数据分成三组。
- 训练:用于训练模型,优化模型的超参数
- 测试:用于检查优化后的模型对未知数据的作用,测试模型的泛化能力
- 验证:在优化过程中,关于测试集的一些信息通过您选择的参数泄露到模型中,因此您对完全未知的数据执行最终检查
在流程中引入交叉验证有助于减少对验证集的需求,因为您可以对相同的数据进行训练和测试。
五重交叉验证数据分割示例。
在最常见的交叉验证方法中,您使用部分训练集进行测试。这样做几次,以便每个数据点在测试集中出现一次。
好处 2:强大的流程
尽管 sklearn 的 train_test_split 方法使用分层分割,这意味着训练和测试集具有相同的目标变量分布,但您可能会意外地在不反映真实世界的子集上进行训练。
想象一下,你试图通过一个人的身高和体重来预测他是男是女。有人会认为,更高更重的人更愿意是男性;尽管如果你非常不幸,你的训练数据将只包含矮个子男人和高个子亚马逊女人。由于交叉验证,您可以执行多个 train_test 分割,虽然一个折叠可以获得非常好的结果,但另一个折叠可能表现不佳。任何时候一个分割显示出不寻常的结果,就意味着你的数据有异常。
如果你的交叉验证分割没有达到相似的分数,你已经错过了一些重要的数据。
Python 中的交叉验证
你总是可以编写自己的函数来分割数据,但是 scikit-learn 已经包含了 10 种分割数据的方法,这让你可以处理几乎任何问题。
让我们开始编码吧。你可以在 github 上下载完整的例子。
首先,让我们创建一个简单的数字范围,从 1,2,3 … 24,25。
# create the range 1 to 25
rn = range(1,26)
那么我们就启动 sklearn 的 Kfold 方法不洗牌,这是如何拆分数据最简单的选择。我将创建两个 Kfolds,一个将数据分割 3 次,另一个进行 5 次折叠。
from sklearn.model_selection import KFoldkf5 = KFold(n_splits=5, shuffle=False)
kf3 = KFold(n_splits=3, shuffle=False)
如果我将我的范围传递给 KFold,它将返回两个列表,包含属于训练集和测试集的数据点的索引。
# the Kfold function retunrs the indices of the data. Our range goes from 1-25 so the index is 0-24for train_index, test_index in kf3.split(rn):
print(train_index, test_index)
KFold 回报指数
KFold 返回索引,而不是真正的数据点。
因为 KFold 返回索引,如果你想看到真实的数据,我们必须在 NumPy 数组中使用np.take
或者在 pandas 中使用.iloc
。
# to get the values from our data, we use np.take() to access a value at particular indexfor train_index, test_index in kf3.split(rn):
print(np.take(rn,train_index), **np.take**(rn,test_index))
您必须使用 np.take(index)来定位真正的数据点
KFold 如何拆分数据?
为了更好地理解 KFold 方法是如何划分数据的,让我们用图表来展示它。因为我们已经使用了shuffled=False
,第一个数据点属于第一个折叠中的测试集,下一个也是。测试和训练数据点排列得很好。
未折叠的 KFold 具有 5 和 3 个折叠,在 github 上显示代码
重要的是,折叠的数量会影响测试集的大小。对 33%的数据进行 3 次折叠测试,而对 1/5(相当于 20%的数据)进行 5 次折叠测试。
每个数据点在测试集中出现一次,在训练集中出现 k 次
洗牌折叠
您的数据可能遵循特定的顺序,按出现的顺序选择数据可能会有风险。这可以通过将 KFold 的 shuffle 参数设置为True
来解决。在这种情况下,KFold 将随机选取将成为训练和测试集一部分的数据点。或者准确地说,不是完全随机的,random_state
影响每组中出现的点,并且相同的random_state
总是导致相同的分割。
具有不同随机状态的 5 倍混洗分裂
使用真实数据集的折叠
在处理实际问题时,很少会有一个小数组作为输入,所以让我们看看使用众所周知的 Iris 数据集的实际例子。
鸢尾(CC BY _ SA 3.0)海滨鸢尾 ( CC BY_SA 4.0 )和杂色鸢尾 ( CC BY_SA 3.0 ),来源维基百科
鸢尾数据集包含 3 种鸢尾花的花瓣和萼片大小的 150 个测量值——50 个鸢尾、50 个海滨鸢尾和 50 个杂色鸢尾
熊猫虹膜数据集样本
当 KFold 交叉验证遇到问题时
在 github 笔记本中,我只使用一个折叠进行了测试,在训练集和测试集上分别达到了 95%和 100%的准确率。当三重分割的结果正好是 0%的准确度时,我感到很惊讶。你读得很好,我的模型没有选择一朵花是正确的。
i = 1
for train_index, test_index in kf3.split(iris_df):
X_train = iris_df.iloc[train_index].loc[:, features]
X_test = iris_df.iloc[test_index][features]
y_train = iris_df.iloc[train_index].loc[:,'target']
y_test = iris_df.loc[test_index]['target']
#Train the model
model.fit(X_train, y_train) #Training the model
print(f"Accuracy for the fold no. {i} on the test set: {accuracy_score(y_test, model.predict(X_test))}")
i += 1
机器学习模型的准确率在每次折叠时为 0%。为什么?
还记得 unshuffled KFold 按顺序挑选数据吗?我们的数据集包含 150 个观察值,前 50 个属于一个物种,51-100 个属于另一个物种,剩下的属于第三个物种。我们的 3 折模型非常不幸,总是选择两个虹膜的尺寸,而测试集只包含模型从未见过的花。
First fold 未能识别测试集中的鸢尾,因为它在 virginica 和 versicolor 上进行了训练,所以从未见过该测试集。
shuffled KFold 是理想的吗?
为了解决这个问题,我们可以改变shuffled=True
参数并随机选择样本。但这也遇到了问题。
这些组是不均衡的,有时我们在测试很多版本的时候会在很多场景下训练
各组仍然不*衡。在测试不同类型的样本时,您通常会对一种类型的大量样本进行训练。让我们看看我们能做些什么。
分层折叠
在许多情况下,在训练集和测试集中保持相同的样本分布是很重要的。这是通过分层折叠来实现的,分层折叠可以再次洗牌或不洗牌。
样本在第三次洗牌和未洗牌的 StratfiedKFold 中的分布
每个折叠中的训练集和测试集的大小—分层*衡分布
你可以看到 KFold 把数据分成了几组,每一组都保持了相应的比率。StratifiedKFold 反映了目标变量的分布,即使某些值在数据集中出现得更频繁。但是,它不评估输入测量值的分布。我们将在最后详细讨论这个问题。
我需要每次都拆分我的数据吗?
要享受交叉验证的好处,您不必手动分割数据。Sklearn 提供了两种使用交叉验证的快速评估方法。cross-val-score
返回模型分数列表,cross-validate
也报告训练次数。
# cross_validate also allows to specify metrics which you want to see
for i, score in enumerate(cross_validate(model, X,y, cv=3)["test_score"]):
print(f"Accuracy for the fold no. {i} on the test set: {score}")
交叉验证函数的结果
其他 sklearn 拆分选项
除了上面提到的功能之外,sklearn 还提供了一系列其他方法来帮助您解决特定的需求。
重复的 Kfold 将创建多种组合的训练测试分割。
常规折叠和重复折叠的比较
虽然常规的交叉验证可以确保您在测试集中看到每个数据点一次,但是 ShuffleSplit 允许您指定在每个折叠中选择多少个特征进行测试。
Kfold 将每个数据点放入测试集中一次,而使用 ShuffleSplit,您可以设置%的数据进行测试。这里设置为 50%。
LeaveOneOut 和 LeavePOut 解决了其他特殊情况下的需要。第一种方法总是只在测试集中留下一个样本。
LeaveOneOut 在每个文件夹中只将单个值放入测试集。
一般来说,大多数作者和经验证据表明,5 倍或 10 倍交叉验证比 LOO 更可取。— sklearn 文档
集团 Kfolds
当您从同一个主题获取多个数据样本时,GroupKFold 就有了用武之地。例如来自同一个人的不止一次测量。来自同一组的数据很可能表现相似,如果你在一个测量上训练,在另一个上测试,你会得到一个好的分数,但这并不能证明你的模型概括得很好。GroupKFold 确保整个组要么去训练,要么去测试集。在 sklearn 文档中阅读更多关于组的信息。
时序数据
涉及时间序列的问题对数据点的顺序也很敏感。根据现有知识猜测过去通常比预测未来容易得多。因此,在预测较新的数据时,总是向时间序列模型提供较旧的数据是有意义的。Sklearn 的 TimeSeriesSplit 正是这么做的。
分层是否考虑输入特征?
还有最后一件事需要强调。你可能认为分层分裂会解决你所有的机器学习问题,但这不是真的。StratifiedKFold 确保在训练集和测试集中保持相同的目标比率。在我们的例子中,每种类型的虹膜有 33%。
为了证明这一点,在一个不*衡的数据集上,我们将看看流行的 Kaggle 泰坦尼克号竞赛。你的目标是训练一个人工智能模型,预测泰坦尼克号沉没时乘客是死是活。让我们看看 StratiffiedKFold 如何在每个折叠中划分数据集中的幸存者和受害者。
训练集和测试集中的目标变量比率相同
看起来不错,不是吗?但是,您的数据仍可能被不正确地拆分。如果您查看关键特征的分布(我特意选择这种分布来证明我的观点,因为通常只需对数据进行洗牌就可以获得更加*衡的分布),您会发现您通常会尝试基于不同于测试集的训练数据来预测结果。例如,如果你观察训练集和测试集中的性别分布。
女性更有可能从船上的悲剧中幸存下来。当第一个折叠学习一些雌性并试图预测许多的存活时,第三个折叠做相反的事情。
交叉验证至少有助于你认识到这个问题,以防模型的分数对于每个折叠有显著的不同。想象一下,你是如此不幸,只使用了一个完全符合你的测试数据的分割,但是在现实世界中却灾难性地失败了。
*衡数据是一项非常复杂的任务,这样就可以根据理想分布进行训练和测试。许多人认为这是不必要的,因为模型应该足够好地概括未知数据。
尽管如此,我还是鼓励你考虑一下特性的分布。想象一下,你有一家商店,顾客大多是男性,你试图使用针对女性的营销活动的数据来预测销售额。这对你的店来说不是最好的模式。
结论
训练-测试分离是许多机器学习任务中的一个基本概念,但如果你有足够的资源,可以考虑对你的问题应用交叉验证。这不仅有助于你使用更少的数据,而且不同文件夹上不一致的分数表明你已经错过了数据中的一些重要关系。
Sklearn 库包含一堆方法来拆分数据,以适应您的人工智能练习。你可以创建基本的 KFold,打乱数据,或者根据目标变量对它们进行分层。您可以使用额外的方法,或者只使用cross-validate
或cross-val-score
测试您的模型,而不需要手动拆分数据。在任何情况下,你的结果分数应该显示一个稳定的模式,因为你不希望你的模型依赖于“幸运”的数据分割来表现良好。
所有数据、图表和 python 处理都总结在 github 上的笔记本中。
[## 用 Plotly 可视化。快递:综合指南
一个数据集和 70 多个图表。交互性和动画通常只需一行代码。
towardsdatascience.com](/visualization-with-plotly-express-comprehensive-guide-eb5ee4b50b57)
# did you like the tutorial, check also* [Pandas alternatives - Vaex, Dash, PySpark and Julia - and when to use them](/is-something-better-than-pandas-when-the-dataset-fits-the-memory-7e8e983c4fe5)
* [Persist pandas in other formats than CSV](/stop-persisting-pandas-data-frames-in-csvs-f369a6440af5)
* [Read CSV in Julia, an alternative to python](/read-csv-to-data-frame-in-julia-programming-lang-77f3d0081c14)
* [How to turn list of addresses or regions into a map](/pythons-geocoding-convert-a-list-of-addresses-into-a-map-f522ef513fd6)
* [Various application of anomaly detection](https://medium.com/@vdekanovsky/machine-learning-saving-machines-cbb715de70b7)
* [How to deal with extra whitespaces in CSV using Pandas](/dealing-with-extra-white-spaces-while-reading-csv-in-pandas-67b0c2b71e6a)
OpenCV 中的完整图像增强
原文:https://towardsdatascience.com/complete-image-augmentation-in-opencv-31a6b02694f5?source=collection_archive---------10-----------------------
这是一篇详尽的文章,通过使用 Python 中的 OpenCV 的自定义数据生成器,涵盖了所有的图像增强功能。
斯蒂夫·约翰森在 Unsplash 上拍照
答几天前,我在写一篇关于使用不同色彩空间作为 CNN 输入的文章,为此,我不得不使用一个定制的数据生成器。这意味着我不能使用 Tensorflow 的内置图像数据生成器进行图像放大。我在网上搜索并找到了一些文章,但找不到任何全面涵盖这个主题的内容,所以我决定写一篇。
目录
- 水*移动
- 垂直移位
- 聪明
- 一款云视频会议软件
- 频道转换
- 水*翻转
- 垂直翻转
- 旋转
- 填充模式
如果你想知道这些是如何工作的,你可以看看这篇文章。为了形象化,我将使用下面的凯旋门图片。
测试图像
水*移动
水*移动或*移是根据定义最大移动量的比率向左或向右移动图像。默认情况下,Keras 使用一种叫做“最*”的填充模式来将图像的尺寸调整回原始尺寸。
填充模式“最*”的结果
我觉得这会使那部分图像变得无用,因此我会简单地将它们调整到原来的大小。因此,要做到这一点,我们需要生成一个随机数,然后使用索引向左或向右移动图像。
import cv2
import randomimg = cv2.imread('arc_de_triomphe.jpg')def fill(img, h, w):
img = cv2.resize(img, (h, w), cv2.INTER_CUBIC)
return img
def horizontal_shift(img, ratio=0.0):
if ratio > 1 or ratio < 0:
print('Value should be less than 1 and greater than 0')
return img
ratio = random.uniform(-ratio, ratio)
h, w = img.shape[:2]
to_shift = w*ratio
if ratio > 0:
img = img[:, :int(w-to_shift), :]
if ratio < 0:
img = img[:, int(-1*to_shift):, :]
img = fill(img, h, w)
return imgimg = horizontal_shift(img, 0.7)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
水*移动
垂直移位
在我们知道如何实现水*移动之后,实现垂直移动就相当容易了。
import cv2
import randomimg = cv2.imread('arc_de_triomphe.jpg')def fill(img, h, w):
img = cv2.resize(img, (h, w), cv2.INTER_CUBIC)
return imgdef vertical_shift(img, ratio=0.0):
if ratio > 1 or ratio < 0:
print('Value should be less than 1 and greater than 0')
return img
ratio = random.uniform(-ratio, ratio)
h, w = img.shape[:2]
to_shift = h*ratio
if ratio > 0:
img = img[:int(h-to_shift), :, :]
if ratio < 0:
img = img[int(-1*to_shift):, :, :]
img = fill(img, h, w)
return imgimg = vertical_shift(img, 0.7)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
垂直移位
聪明
这很容易,因为我已经写了一篇关于创建不同的图像过滤器漫画,夏天,冬天等,它已经包括亮度功能。
[## 使用 OpenCV 设计图像滤镜(第 1 部分)
我们都编辑过我们的图像,也许是为了改善白*衡,增加温暖,使用不同的滤镜,甚至…
medium.com](https://medium.com/dataseries/designing-image-filters-using-opencv-like-abode-photoshop-express-part-1-8765e3f4495b)
我们利用 HSV 色彩空间来完成这项任务。饱和度和值矩阵的值越多,亮度就越大。因此,要增加亮度,请将它们乘以一个大于 1 的值,要降低亮度,请乘以一个小于 1 的值。在 Tensorflow 中,指定了一个范围,并在其中选择了一个随机值,所以这就是我们如何创建它。
import cv2
import random
import numpy as npimg = cv2.imread('arc_de_triomphe.jpg')def brightness(img, low, high):
value = random.uniform(low, high)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
hsv = np.array(hsv, dtype = np.float64)
hsv[:,:,1] = hsv[:,:,1]*value
hsv[:,:,1][hsv[:,:,1]>255] = 255
hsv[:,:,2] = hsv[:,:,2]*value
hsv[:,:,2][hsv[:,:,2]>255] = 255
hsv = np.array(hsv, dtype = np.uint8)
img = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
return imgimg = brightness(img, 0.5, 3)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
聪明
一款云视频会议软件
在 Tensorflow 中,缩放函数采用一个范围,并在该范围之间使用随机值。如果这些值小于 1,它会放大图像,如果值大于 1,它会缩小图像并“最*”填充图像。然而,当我们调整图像的尺寸时,我们只取小于 1 的值。例如:值为 0.6 意味着取整个图像的 60%,然后我们将把它调整回原始大小。
import cv2
import randomimg = cv2.imread('arc_de_triomphe.jpg')def fill(img, h, w):
img = cv2.resize(img, (h, w), cv2.INTER_CUBIC)
return imgdef zoom(img, value):
if value > 1 or value < 0:
print('Value for zoom should be less than 1 and greater than 0')
return img
value = random.uniform(value, 1)
h, w = img.shape[:2]
h_taken = int(value*h)
w_taken = int(value*w)
h_start = random.randint(0, h-h_taken)
w_start = random.randint(0, w-w_taken)
img = img[h_start:h_start+h_taken, w_start:w_start+w_taken, :]
img = fill(img, h, w)
return imgimg = zoom(img, 0.5)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
一款云视频会议软件
频道转换
在通道偏移中,随机数量的值被添加到从指定范围中选择的图像的所有通道中。它的结果有点像亮度函数。
import cv2
import random
import numpy as npimg = cv2.imread('arc_de_triomphe.jpg')def channel_shift(img, value):
value = int(random.uniform(-value, value))
img = img + value
img[:,:,:][img[:,:,:]>255] = 255
img[:,:,:][img[:,:,:]<0] = 0
img = img.astype(np.uint8)
return imgimg = channel_shift(img, 60)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
频道转换
水*翻转
我认为这不需要任何解释。它采用一个布尔变量来定义是否要执行水*翻转。OpenCV cv2.flip
中有一个内置函数就是用来执行这个操作的。
import cv2img = cv2.imread('arc_de_triomphe.jpg')
def horizontal_flip(img, flag):
if flag:
return cv2.flip(img, 1)
else:
return imgimg = horizontal_flip(img, True)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
水*翻转
垂直翻转
像水*翻转一样,使用cv2.flip
来执行,但是它的第二个参数应该是 0。
import cv2img = cv2.imread('arc_de_triomphe.jpg')
def vertical_flip(img, flag):
if flag:
return cv2.flip(img, 0)
else:
return imgimg = vertical_flip(img, True)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
垂直翻转
旋转
要在 OpenCV 中执行旋转,我们需要创建一个旋转矩阵,然后对其应用仿射变换。
import cv2img = cv2.imread('arc_de_triomphe.jpg')
def rotation(img, angle):
angle = int(random.uniform(-angle, angle))
h, w = img.shape[:2]
M = cv2.getRotationMatrix2D((int(w/2), int(h/2)), angle, 1)
img = cv2.warpAffine(img, M, (w, h))
return imgimg = rotation(img, 30)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
旋转
填充模式
上面我提到了“最*的”填充模式,我说过我不会使用它,而是调整图像的大小。我决定向你展示如何在 OpenCV 中创建填充模式,因为我试图创建一个完整的列表,所以如果你想执行一个,你不会有任何问题。来自 Tensorflow 的文档:
**fill_mode**
:为{“常数”、“最*”、“反射”或“换行”之一。默认值为“最*”。根据给定模式填充输入边界外的点:' constant ':kkkkkkkkk | ABCD | kkkkkkkk(cval = k)
' nearest ':aaaaaaaa | ABCD | dddddddd
' reflect ':abcddcba | ABCD | dcbaabcd
' wrap': abcdabcd|abcd|abcdabcd
我会让它们水*移动。cv2.copyMakeBorder
可用于灌装。它接受图像、顶部、底部、左侧、右侧和模式等参数。上、下、左、右是边框的大小。
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('arc_de_triomphe.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)def fill_mode(img, left, right):
nearest = cv2.copyMakeBorder(img, 0, 0, left, right, cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, 0, 0, left, right, cv2.BORDER_REFLECT)
wrap = cv2.copyMakeBorder(img, 0, 0, left, right, cv2.BORDER_WRAP)
constant= cv2.copyMakeBorder(img, 0, 0, left, right, cv2.BORDER_CONSTANT,value=(255, 0, 0))
plt.subplot(221),plt.imshow(nearest,'gray'),plt.title('NEAREST'),plt.axis('off')
plt.subplot(222),plt.imshow(reflect,'gray'),plt.title('REFLECT'),plt.axis('off')
plt.subplot(223),plt.imshow(wrap,'gray'),plt.title('WRAP'),plt.axis('off')
plt.subplot(224),plt.imshow(constant,'gray'),plt.title('CONSTANT'),plt.axis('off')def horizontal_shift_mode(img, ratio):
if ratio > 1 or ratio < 0:
print('Value for horizontal shift should be less than 1 and greater than 0')
return img
ratio = random.uniform(-ratio, ratio)
h, w = img.shape[:2]
to_shift = int(w*ratio)
if ratio > 0:
img = img[:, :w-to_shift, :]
fill_mode(img, to_shift, 0)
if ratio < 0:
img = img[:, -1*to_shift:, :]
fill_mode(img, 0, -1*to_shift)horizontal_shift_mode(img, 0.8)
填充模式
这就是这篇文章的全部内容。如果你想知道如何创建一个自定义的数据生成器,那么你可以看看我下面的文章。
[## 不同的色彩空间作为 CNN 的输入
找出通过自定义数据生成器在 CNN 中使用不同的色彩空间是否会导致更好的结果…
towardsdatascience.com](/different-colorspaces-as-inputs-to-cnns-406ae62d1bd6)
编辑
莱昂纳多·米兰达让我注意到了两个很棒的图像增强库,分别叫做 imagaug 和albuminations。它们可用于 pip 和 conda 安装。它们提供了从基础到非常高级的大量图像增强。我发现关于它们最好的部分是甚至对于分割和边界框也有增强。我鼓励每个人去看看他们的自述,他们太棒了。
PySpark 完整介绍-第 2 部分
原文:https://towardsdatascience.com/complete-introduction-to-pyspark-part-2-135d2f2c13e2?source=collection_archive---------39-----------------------
使用 PySpark 进行探索性数据分析
马库斯·斯皮斯克在 Unsplash 上的照片
探索性数据分析
探索性数据分析是最关键的部分,无论我们何时处理数据集,都要从它开始。它允许我们分析数据,并让我们探索数据的初始发现,如有多少行和列,不同的列是什么,等等。EDA 是一种方法,在这种方法中,我们使用不同的方法主要是可视化来总结数据的主要特征。
让我们使用 PySpark 启动 EDA,在此之前,如果您还没有安装 PySpark,请访问下面的链接并在您的本地机器上配置它。
[## PySpark 完整介绍
第 1 部分:从头开始在 Windows 上安装 PySpark
medium.com](https://medium.com/python-in-plain-english/complete-introduction-to-pyspark-part-1-7d16d7c62cc9)
导入所需的库和数据集
一旦我们在机器上配置了 PySpark,我们就可以使用 Jupyter Notebook 开始探索它。在本文中,我们将使用 PySpark 执行 EDA 操作,为此我们将使用可以从 Kaggle 下载的波士顿数据集。让我们从导入所需的库和加载数据集开始。
#importing Required Libraries
import findspark
findspark.init()import pyspark # only run after findspark.init()
from pyspark.sql import SparkSession
from pyspark.sql import SQLContext#Creating a pyspark session
spark = SparkSession.builder.getOrCreate()#Importing Dataset
df = spark.read.csv('Boston.csv', inferSchema=True, header=True)
df.show(5)
波士顿数据集(来源:作者)
启动 EDA
pyspark 定义了不同的函数,我们可以使用它们进行探索性的数据分析,让我们探索其中的一些函数,看看它们有多有用。
- Schema Schema 类似熊猫 dataframe 的 Info()函数。它向我们显示了数据集中所有列的信息。
df.printSchema()
模式(来源:作者)
2。Describe
Describe 函数用于显示数据集中所有列的统计属性。它向我们展示了*均值、中间值等数值。对于所有的列。在 PySpark 中,每次我们需要显示信息时,我们都需要调用 show()函数,它的工作方式就像 python 的 head()函数一样。
df.describe().show()
统计属性(来源:作者)
类似地,我们也可以按列使用 describe 函数。
df.describe('AGE').show()
按列描述(来源:作者)
3。filter filter 函数用于使用不同的自定义条件过滤数据。让我们看看如何相应地使用它。
#Filtering data with Indus=7.07
df.filter(df.INDUS==7.07).show()
过滤器 1(来源:作者)
类似地,我们可以在一行代码中使用多个过滤器。
df.filter((df.INDUS==7.07) & (df.MEDV=='High')).show()
过滤器 2(来源:作者)
4。分组和排序 PySpark 内置函数可以根据用户需求对数据进行分组,也可以根据需要对数据进行排序。
df.groupBy('MEDV').count().show()
GroupBy(来源:作者)
df.sort((df.TAX).desc()).show(5)
排序(来源:作者)
5。select&Distinct select 函数用于选择不同的列,Distinct 函数可用于选择该列的不同值。
df.select('MEDV').distinct().count()
选择和区分(来源:作者)
6。with column
T5【with column】函数用于通过为新列提供一定的条件并定义新列的名称来创建新列。
#Creating New column with values from Age column divided by 2
df.withColumn('HALF_AGE', df.AGE/2.0). select('AGE','HALF_AGE') .show(5)
WithColumn(来源:作者)
在本文中,我们介绍了 PySpark 下定义的一些主要函数,我们可以使用这些函数进行探索性的数据分析,并理解我们正在处理的数据。
继续,用不同的数据集尝试这些函数,如果您遇到任何问题,请在响应部分告诉我。
在你走之前
感谢 的阅读!如果您想与我取得联系,请随时通过 hmix13@gmail.com 或我的 LinkedIn 个人资料 联系我。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
PySpark 完整介绍-第 3 部分
原文:https://towardsdatascience.com/complete-introduction-to-pyspark-part-3-9c06e2c5e13d?source=collection_archive---------57-----------------------
使用 PySpark 对数据集执行 SQL 操作
弗兰基·查马基在 Unsplash 上拍摄的照片
什么是 SQL(结构化查询语言)?
SQL 是一种用于对数据执行不同操作的语言,如存储、操作和检索。它在关系数据库上工作,在关系数据库中数据以行和列的形式存储。
根据属性,SQL 命令可以分为三种类型:
- DDL(数据定义语言)
顾名思义,DDL 命令用于定义数据。DDL 中包含的命令有创建、插入、截断、删除等。
2。DML(数据操作语言)
数据操作命令用于根据用户要求改变和更新数据。DDL 下定义的一些命令是 ALTER、UPDATE、DELETE 等。
3。数据控制语言
在这种情况下,定义的命令用于控制对定义的数据库的访问。其中定义的一些命令有 GRANT、REVOKE 等。
将 PySpark 用于 SQL 操作
为了使用 PySpark 执行 SQL 操作,我们需要在本地机器上安装 PySpark。如果你已经安装了它,我们就可以开始了,或者通过下面的链接来安装 PySpark,并使用 PySpark 在 DataFrame 上执行一些基本操作。
[## PySpark 完整介绍
第 1 部分:从头开始在 Windows 上安装 PySpark
medium.com](https://medium.com/python-in-plain-english/complete-introduction-to-pyspark-part-1-7d16d7c62cc9) [## PySpark 完整介绍-第 2 部分
使用 PySpark 进行探索性数据分析
towardsdatascience.com](/complete-introduction-to-pyspark-part-2-135d2f2c13e2)
加载所需的库
在我们的机器上安装了 pyspark 并对其进行配置之后,我们将打开一个 jupyter 笔记本来启动 SQL 操作。我们将从导入所需的库和创建 PySpark 会话开始。
import findspark
findspark.init()import pyspark # only run after findspark.init()
from pyspark.sql import SparkSession
from pyspark.sql import SQLContext
spark = SparkSession.builder.getOrCreate()
加载数据集
为了执行 SQL 操作,我们需要一个数据集。在本文中,我们将使用波士顿数据集,它可以使用 Kaggle 轻松下载,并将使用 PySpark 加载它。
df = spark.read.csv('Boston.csv', inferSchema=True, header=True)
df.show(5)
数据集(来源:作者)
现在,让我们开始对数据集执行 SQL 操作,我们将首先创建一个表和一个 SQLContext 对象,它将用于在该表上运行查询。
1。正在创建表格
为了创建一个表,我们需要使用 PySpark 的 register 函数。类似地,我们还将创建一个 SQLContext 对象,用于在表上运行查询。
df.registerTempTable('BostonTable')
sqlContext = SQLContext(spark)
2.选择查询
选择查询用于根据用户需求选择数据。我们可以使用“*”选择整个表,或者我们可以传递用“,”分隔的列的名称,这是我们想要看到的。
#Select Whole Table(only three records because we used show(3))
sqlContext.sql('select * from BostonTable').show(3)
选择表格(来源:作者)
#Select column using column names
sqlContext.sql('select _c0, CRIM, ZN, INDUS, CHAS from BostonTable').show(3)
选择列(来源:按作者)
3.聚合函数
SQL 中定义了一些预定义的聚合函数,可用于根据用户需求选择数据。这些功能是:
a.min()
b . max()
c . count()
d . sum()
e . var()
等。
下面给出了下列函数的语法。
#Using max functions
sqlContext.sql('select max(AGE) from BostonTable').show()
max 函数(来源:作者)
同样,我们可以根据用户需求使用其他函数来显示输出。
4.条件查询
通过使用条件查询,我们可以生成符合用户传递的特定条件的输出。使用最多的条件表达式是“where”。
sqlContext.sql('select CRIM, NOX, B from BostonTable where B = 396.9').show(3)
条件数据(来源:作者)
我们可以在条件查询中使用不同的支持函数,这有助于更具体地了解输出,并有助于在单个查询中运行多个条件。这些功能是:
a.具有
b .和
c .或
d .然后
e .(用于范围)
等。
sqlContext.sql('select CRIM, NOX, B, RAD from BostonTable where RAD > 2 and B = 396.9').show(3)
条件表达式(来源:作者)
类似地,我们可以使用上面给出的相同语法来使用不同的函数。
5.嵌套查询
我们可以在同一行代码中运行多个查询,这通常称为嵌套查询。这是一种复杂的查询形式,我们根据用户需求传递不同的条件来生成输出。下面给出了一个嵌套查询的例子。
sqlContext.sql('select * from BostonTable where AGE between 40 and 50 and TAX not in (311,307)').show(3)
嵌套查询(来源:作者)
同样,您可以根据需要的输出尝试不同的嵌套查询。
本文为您提供了关于使用 PySpark 进行 SQL 查询的基本信息。继续尝试这些,如果你遇到任何困难,请在回复部分告诉我。
在你走之前
感谢 阅读!如果你想与我取得联系,请随时在 hmix13@gmail.com 上联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 阅读我写过的与数据科学相关的不同文章。
PySpark 完整介绍-第 4 部分
原文:https://towardsdatascience.com/complete-introduction-to-pyspark-part-4-62a99ce3552a?source=collection_archive---------14-----------------------
使用 PySpark 执行数据可视化
威廉·艾文在 Unsplash 上的照片
数据可视化
数据可视化在数据分析中起着重要的作用,因为只要人眼看到一些图表或图形,他们就会试图在该图形中找到模式。
数据可视化是使用不同的图/图形/图表直观地表示数据,以找出模式、异常值以及数据集不同属性之间的关系。它是数据的图形表示。
使用 PySpark 实现数据可视化
我们可以使用 PySpark 执行数据可视化,但在此之前,我们需要在本地机器上设置它。为了在您的本地机器上安装 PySpark 并对 PySpark 的工作原理有一个基本的了解,您可以浏览下面的文章。
[## PySpark 完整介绍
第 1 部分:从头开始在 Windows 上安装 PySpark
medium.com](https://medium.com/python-in-plain-english/complete-introduction-to-pyspark-part-1-7d16d7c62cc9) [## PySpark 完整介绍-第 2 部分
使用 PySpark 进行探索性数据分析
towardsdatascience.com](/complete-introduction-to-pyspark-part-2-135d2f2c13e2)
安装 PySpark 之后,让我们从打开 jupyter 笔记本并加载所需的库开始。
加载所需的库
我们将从加载所有需要的库和创建 PySpark 会话开始。
import findspark
findspark.init()import pyspark # only run after findspark.init()
from pyspark.sql import SparkSession
from pyspark.sql import SQLContextimport seaborn as sns
import matplotlib.pyplot as pltspark = SparkSession.builder.getOrCreate()
加载数据集
在本文中,我们将使用 PySpark 执行数据可视化,为此我们将使用波士顿数据集,该数据集可从 Kaggle 下载。让我们加载数据并开始可视化。
df = spark.read.csv('Boston.csv', inferSchema=True, header=True)
df.show(5)
数据集(来源:作者)
创建饼图
在创建可视化之前,我们需要使用 SQL 创建一个数据集的表,以便了解更多关于使用 PySpark 的 SQL 操作。
使用 SQL 创建一个表,并运行所需的查询来相应地生成一个饼图。
#Creating Table
df.registerTempTable('BostonTable')
sqlContext = SQLContext(spark)#Running Query
df1 = sqlContext.sql("SELECT * from BostonTable").toPandas()
df2 = sqlContext.sql("SELECT AGE, TAX from BostonTable where LSTAT < 2").toPandas()#Creating Visualization
fig = plt.pie(df2['AGE'], autopct='%1.1f%%', startangle=140,labels=df2['AGE'])
plt.title('No of age group where lstat < 2')
plt.show()
饼状图(来源:作者)
类似地,我们可以对不同的输出运行不同的查询,因此我们可以改变饼图的可视化。
相关矩阵
相关矩阵用于分析和可视化数据集不同列之间的关系。让我们看看如何使用 PySpark 创建一个相关矩阵。
df1.corr().style.background_gradient(cmap='coolwarm').set_precision(2)
相关性(来源:作者)
类似地,我们可以创建不同类型的可视化,如盒状图、小提琴图、条形图等。下面给出了这些图的一些例子。
#box plot
plt.boxplot(df2)
plt.show()
方框图(来源:作者)
#Scatter Plot
df3 = sqlContext.sql("SELECT PTRATIO, TAX from BostonTable").toPandas()
fig=plt.figure()
ax=fig.add_axes([0,0,1,1])
ax.scatter(df3['TAX'],df3['PTRATIO'], color='r')
ax.set_xlabel('TAX')
ax.set_ylabel('PTRATIO')
ax.set_title('scatter plot')
plt.title('PTRATIO Vs TAX')
plt.show()
散布(来源:作者)
#Violoin Plot
df5 = sqlContext.sql("SELECT RM from BostonTable").toPandas()
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
bp = ax.violinplot(df5['RM'])
plt.title('Average number of rooms per dwelling')
plt.show()
小提琴情节(来源:作者)
#3d Scatter Plot
df6 = sqlContext.sql("SELECT CHAS, NOX, RM from BostonTable").toPandas()
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.scatter(df6['CHAS'], df6['NOX'], df6['RM'])
ax.set_title('CHAS Vs NOX Vs RM')
plt.show()
3D 绘图(来源:作者)
本文为您提供了关于使用 PySpark 进行数据可视化的基本信息。继续尝试这些,如果你遇到任何困难,请在回复部分告诉我。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
使用 Github 完成将您的 SDE 连接到 GCP 的演练
原文:https://towardsdatascience.com/complete-walkthrough-to-connect-your-sde-to-gcp-with-github-bc39eec0db9e?source=collection_archive---------38-----------------------
使用云实例增强您的工作流程!
伊恩·巴塔格利亚在 Unsplash 上拍摄的照片
在数据科学家的日常工作中,当处理不断增长的数据集和更复杂的模型架构时,处理和计算是一个持续关注的问题。然而,我没有考虑到这样一个事实,即您获得了预算来更新具有更好的内存、CPU 和 GPU 的最新硬件。数据科学家似乎不可避免地会寻找这些问题的解决方案。一个比升级硬件更便宜的解决方案是通过云虚拟机。
虚拟机是云服务,允许根据需要对计算能力类型进行定制配置。简单来说,它是一台云电脑,当你需要更多的计算能力和内存来完成重型任务时,你可以升级它。然而,通常 VMs 不像我们的本地操作系统那样提供易用性,如果你想在 Linux 系统中走自己的路,还有一点学习曲线。因此,本教程将提供一个解决方案,将您的虚拟机连接到您的本地 SDE,如 VSCode,同时设置 Github 到您的虚拟机,以允许可视化管理。事不宜迟,我们开始吧!
步骤 1:在云上设置一个实例(GCP)
在本教程中,我将使用的云服务是谷歌云*台(GCP),我很喜欢它的免费信用。
- 在 GCP 获得一个账号,登录控制台。
- 启用计算引擎 API ,默认应该是启用的。
- 在控制台中导航到计算引擎,并单击虚拟机实例下的创建。
计算引擎(图片由作者提供)
4.选择实例名称、区域、和机器配置。也可以在侧边栏中查看您的选择的价格。我选择最便宜的,因为我只想演示它是如何工作的。
5.为实例设置启动盘。我使用的是 ubuntu 16.04 LTS,但你可以选择各种可用的公共图像。对于防火墙,启用 HTTP/HTTPS 流量。
步骤 2:从 VSCode 连接虚拟机
这一步有两个关键部分:创建一个 SSH 密钥文件,并使用 VSCode 中的远程 SSH 扩展将您连接到 VM。为此,我们需要使用本指南中概述的第三方连接方法。我还将介绍用 VSCode 设置它的过程。
1。安装 gcloud
要安装 gcloud,可以在终端上使用以下命令。或者参考官方指南。
2。使用 gcloud 认证登录
设置完成后,在 VSCode 中使用新的终端窗口登录
gcloud auth login
它将引导您进入登录页面。登录并允许 SDK 访问,您可能会在终端中看到登录消息。如果显示项目信息缺失,用gcloud config set project <Project_ID>
配置项目 id。项目 id 可以在您的控制台中找到。
红框中的项目 ID
3。在 gcloud 中启用操作系统登录
要启用操作系统登录,基本上就是在项目或您正在使用的 VM 实例中添加元数据。查看此页面了解更多信息。但是由于我们已经用终端登录,使用下面的命令来快速设置。
gcloud compute project-info add-metadata --metadata enable-oslogin=TRUE
4。在终端中创建一个 SSH 密钥对
有许多方法可以生成密钥对。对于 Mac/Linux,在终端中使用以下命令:
ssh-keygen -t rsa
您将看到如下所示的内容。密码是可选的。
5。通过 gcloud 将 SSH 密钥对添加到用户帐户
现在我们已经生成了 SSH 密钥对,我们需要将密钥添加到用户帐户。在您的终端中使用以下命令和 gcloud:
gcloud compute os-login ssh-keys add \
--key-file <key-file-path> \
--ttl <expire-time>
<key-file-path>
是你的公钥文件以.pub
结尾。
<expire-time>
可能是以下任何一种。确保在它之前有数字,例如10d
的过期时间设置为 10 天。
s
为秒m
持续分钟h
数小时d
一连几天- 将值设置为
0
表示没有到期时间。
该命令的输出将类似于以下内容。这里的关键信息是你的用户名。将它保存在记事本中的某个地方,稍后您将使用它进行连接。
6。使用密钥对连接到主机
在从 VSCode 直接连接到您的实例之前,建议在终端中使用ssh
命令测试连接。
ssh -i <PATH_TO_PRIVATE_KEY> <USERNAME>@<EXTERNAL_IP>
<PATH_TO_PRIVATE_KEY>
:我们已经在前面的步骤中生成了这个文件,文件路径看起来像/user/.ssh/id_rsa
<USERNAME>
:这是我们在输出中获得的用户名。<EXTERNAL_IP>
:在控制台找到这个信息。
一旦连接成功,您将看到 VM 终端如下所示:
此时,我们可以继续连接 VSCode。使用exit
离开远程机器。
7。使用远程 SSH 连接虚拟机
Remote-SSH 是 VSCode 的一个扩展,用于使用 VSCode 连接到远程机器。您可以很容易地在扩展标签中搜索和安装它。
远程 SSH
单击窗口左下角的绿色图标(或按 F1 键并搜索 Remote-ssh)。选择连接到主机。
并且添加一个新的 SSH 主机
现在粘贴用于测试连接的确切的ssh
命令,然后按回车键。
VSCode 将打开一个远程连接的新窗口。您将 VSCode 连接到 GCP 实例。
连接到虚拟机的虚拟代码
步骤 3:设置与 Github 的 SSH 连接
现在你已经在 VSCode 中支持了 VM,我们可以开始在 Github 中的一些项目上工作了。为了将工作流与 Github 无缝集成,我们可以设置一个到 Github 的 SSH 连接来启用所有 git 命令。Github 正在提供一个全面的指南关于如何设置它。但是,我仍然会在本教程中介绍这个过程。
正如我们之前提到的,我们还需要一个 Github 密钥对。在 VSCode 中打开一个新的终端,使用如下命令生成一个 SSH 密钥对。但是用你在 Github 注册的邮件来代替。
ssh-keygen -t id_rsa -C "*your_email@example.com*"
现在我们有了一个ssh
密钥文件,我们需要将它添加到 SSH-Agent 中。要在后台启动它,请使用以下命令:
eval "$(ssh-agent -s)"
>> Agent pid 59566
现在将私钥添加到代理中:
ssh-add ~/.ssh/id_rsa
我们还需要在 GitHub 中添加密钥。用你的账号登录 Github ,在设置下找到 S SH 键和【GPG】T7 键。点击 新建 SSH 密钥 如快照所示。
在终端中,找到公钥文件并复制它。
vi ~/.ssh/id_rsa.pub
现在粘贴并创建 SSH 密钥。
测试终端中的 GitHub 连接。粘贴以下命令:
ssh -T git@github.com
第一次连接会看到这样的东西。继续设置就好了。
> The authenticity of host 'github.com (IP ADDRESS)' can't be established.
> RSA key fingerprint is SHA256:xxxxx.
> Are you sure you want to continue connecting (yes/no)?
现在你已经有了一个与 Github 的 SSH 连接。使用git clone
你在 Github 中的 repo 到 VM。使用code .
,你将有一个新的工作空间为你的回购开放。
现在你有了完全相同的体验,就好像你在本地计算机上工作一样!
对您的实例有用的资源
这里有一些有用的资源,可以安装到用 VSCode 安装的 Linux 实例中
- 自制
- Pyenv
- Github CLI
感谢您的关注!享受🥳
Python NumPy 中数组生成函数全集
原文:https://towardsdatascience.com/complete-works-of-array-generating-functions-in-python-numpy-67c7eb244fdf?source=collection_archive---------34-----------------------
Alicja 在 Pixabay 上的照片
从等差数列到几何数列及定制生成函数
如果你用过 Python,我相信你一定用过 NumPy 库,所以我想我不必介绍这个库。
因为 NumPy 就是这样一个为数值和维度数组计算而创建的库,所以它的一个典型使用场景就是根据定义的规则生成维度数组。
在本文中,我将介绍 NumPy 中所有优秀的内置函数,让我们可以按照一定的规则生成 n 维数组。请注意,随机数组可以是一个单独的主题,因此它们不会包含在本文中。我确信您一定知道我将在后面的章节中介绍的一些甚至大部分功能,但是强烈建议您浏览一下这篇文章。我敢肯定,你可能会发现一些你不知道的功能,但可能非常有用。
NumPy 为什么这么快?
照片由神果在 Pixabay 上拍摄
在介绍函数之前,我想提一下 NumPy 为什么这么快。简单的回答是,因为它不是 Python。
你可能会惊讶为什么 NumPy 不是 Python。事实上,NumPy 是用 C 编程语言实现的,在大多数情况下,它在性能方面胜过 Python。所以,我们写 Python 代码用 NumPy,但是引擎盖下是 c。
我们可以做一个简单的实验来比较性能。假设[1,2,3]
这样的“list”是一个纯 Python 对象,我们可以用 list 和 NumPy 数组做同样的事情来比较运行时间。
当然,我们需要在一切之前导入 NumPy 库。
import numpy as np
然后,让我们生成一个包含 100 万个整数的 Python 列表,然后计算列表中每个数字的*方。
ls = list(range(1000000))
ls_square = [i**2 for i in ls]
同样,让我们使用 NumPy 做同样的事情。
arr = np.arange(1000000)
arr_square = arr ** 2
可以看出 NumPy 比 Python 列表快了差不多 100 倍。这也是为什么大多数其他用于数据分析(如 SciPy、Pandas)、机器学习(如 Sci-kit Learn)和数据可视化(如 Matplotlib)的库通常依赖于 NumPy。
在范围内生成数组
由 SparrowsHome 在 Pixabay 上拍摄的照片
让我们开始生成一定范围内的 NumPy 数组。
np.arange()
第一个,当然是np.arange()
,我相信你可能已经知道了。
要生成一个数组,从一个数字开始,以一定的步长在一个数字处停止,我们可以很容易地做到如下。请注意不包括停车号码。
np.arange(start=1, stop=10, step=1)
有时,如果我们希望数组从零开始,我们不需要指定起始数,因为它默认为零。此外,默认步长为 1。所以,如果我们想生成一个数组,从 0 开始,在 10 处停止(需要指定),步长等于 1,下面的代码就可以了。
np.arange(10)
大概值得一提的是,step 也可以是 float 类型。这是与 Python 内置函数range()
的比较,因为后者不支持浮点数作为步长。
np.arange(start=1, stop=5, step=0.5)
尽管可能不常用,但步长也可以是负数。因此,数组将按降序排列,其中起始数大于终止数。
np.arange(start=10, stop=1, step=-2)
如果要生成某种类型的数组,可以显式指定。
arr = np.arange(10, dtype=float)
np.linspace()
这个功能比np.arange()
更强大一点。它的名字“linspace”代表“线性空间”。因此,它用于生成数字具有线性关系的数组。
主要区别在于linspace()
不依赖于步长。相反,我们需要指定在起始号码和终止号码之间有多少个号码。
np.linspace(start=1, stop=10, num=10)
在上面的两个例子中,开始和结束数字是相同的,但是生成的数组是不同的,因为我们要求第二个数组多一个数字。因此,该函数生成一个严格意义上的算术序列数组。
您可能还会注意到,这一次停止编号是包含性的,但是我们可以显式地将其排除。
np.linspace(1, 10, 11, endpoint=False)
我们还可以显式地指定数组所需的数据类型。然而,在将整数指定为数据类型时要小心,因为数字将被floor而不是 rounded 。
np.linspace(1, 10, 11, dtype=int)
np.logspace()
你可能会好奇,我们有“线性空间”,但还有其他的“空间”吗?是的,我们也有“日志空间”,它不是线性的。我相信这个函数并不为大多数开发者所知,但它是一种非常优雅的生成几何序列数组的方式。
np.logspace(start=1, stop=10, num=4, base=2)
看这个例子,同样,我们有起始号和终止号。第三个参数“num”是我们希望数组中有多少个数字。最后一个参数“base”是我们想要的基数。
事实上,该函数生成了以下 4 个数字:
它们也是严格的几何序列,如下所示:
需要提到的是,默认情况下“基数”是 10。因此,如果我们希望“基数”等于 10,我们不需要明确指定它。
np.logspace(1, 5, 3)
生成具有特定值和形状的数组
由 saulhm 在 Pixabay 上拍摄的照片
因为 NumPy 在计算多维数组(矩阵)方面很强大,所以我们也需要生成多维数组。
全 0 或全 1 生成
很常见的情况是,我们需要生成一个所有值都为零的特定维数的数组。例如,图像以 1024 * 768 * 3 的阵列表示,其中轴 3 表示 RGB 通道。如果我们想过滤只有一个颜色通道的图像,我们需要其他两个通道的值都为零。在这样的用例中,np.zeros()
函数非常有用。
如果我们想生成一个 2(行)乘 3(列)的 2D 数组,下面的代码就可以了。
np.zeros((2,3))
不仅仅是 0,我们也可以生成 1 的数组。
np.ones((2,3))
需要注意的是,我们使用np.zeros()
和np.ones()
生成的数组是浮点型的,从点0\. (float)
可以看出它不是0 (int)
。如果我们需要它们是 int,这有时不太方便。幸运的是,我们可以显式地指定数据类型。
np.zeros((2,3), dtype=int)
用定制的数字生成
如果我们既不想要 0 也不想要 1,而是想要其他数字呢?在这样的场景中,我们可以使用np.full()
。例如,如果我们想要生成一个具有特定维度的数组,并且它的所有值都应该是 255,只需执行以下操作。
np.full((2,3), 255)
另外值得一提的是np.full()
不仅可以用来生成数值数组,还可以生成字符串等其他数据类型。
np.full((2,3), 'abc')
基于其他数组生成
为了方便起见,NumPy 还允许我们从其他数组生成数组。也就是说,复制另一个数组的形状及其数据类型。
例如,让我们显式地创建一个样本数组。
sample_arr = np.array([
[1,2,3],
[4,5,6]
])
该示例数组的维数为 2 * 3,数据类型为整数。
如果我们想要生成一个具有相同维度和数据类型的数组,但是值都是零,我们可以使用np.zeros_like()
。
np.zeros_like(sample_arr)
同样,我们也可以生成所有的 1。
np.ones_like(sample_arr)
和定制号码。
np.full_like(sample_arr, 255)
当然,如果你愿意,你可以使用np.zeros()
来实现同样的事情,但是不要忘记,默认情况下它会创建一个 float 类型的数组。所以我们需要明确指定我们想要整数。
np.zeros_like(sample_arr)# is equivalent to np.zeros(sample_arr.shape, dtype=sample_arr.dtype)
如果我们不知道样本数组的类型呢?例如,这是在另一个函数的循环中。然后,我们不得不在那些情况下使用np.zero_like()
。
生成单位矩阵和对角矩阵
图片由 YouComMedia 在 Pixabay 上拍摄
在某些场景下,我们还需要生成一些特殊的数组,比如单位矩阵和对角矩阵。
为了生成单位矩阵,我们使用np.eye()
,只需指定矩阵所需的行数/列数。
np.eye(5)
当我们想生成对角矩阵时,可以使用np.diag()
。我们需要传入一个值应该在对角线上的列表。
np.diag([1,2,3,4,5])
从定制功能生成
照片由在 Pixabay 上的免费照片拍摄
最后但并非最不重要的,我想介绍如何生成一个自定义函数的多维数组。
函数np.fromfunction()
有两个必需的参数:
- 用户定义的函数,接受一个元组,该元组包含所有维度轴的索引
- 数组的维数
让我们看一个例子。假设我们想生成一个 6 乘 5 的矩阵。每个数字的行号为十位,列号为一位。我们可以把这个函数定义如下。
def gen(row, col):
return (row+1)*10 + (col+1)
然后,我们可以将函数传入np.fromfunction()
来生成我们想要的数组。
A = np.fromfunction(gen, (6,5))
摘要
照片由 stevepb 在 Pixabay 上拍摄
在这篇文章中,我已经介绍了为什么 NumPy 是首选,为什么它这么快。然后,我们重点讨论了如何使用 NumPy 生成多维数组。我相信这些都是你需要知道的函数,以便于你在 Python 中进行数据分析、数据挖掘、机器学习和数据可视化工作。希望有帮助。
本文使用的所有代码都可以在我的 Google Colab 笔记本中找到。
[## 主 Numpy 数组生成
所有多维数组生成函数
colab.research.google.com](https://colab.research.google.com/drive/1Eo-m4kKQLR8ymdtaQHOBwKkwdygY9Qkp?usp=sharing)
人生苦短,用 Python!
[## 通过我的推荐链接加入 Medium 克里斯托弗·陶
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@qiuyujx/membership)
如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)
用 10 个步骤完成你的第一个机器学习项目
原文:https://towardsdatascience.com/complete-your-first-machine-learning-projects-in-10-steps-29e9456a5759?source=collection_archive---------42-----------------------
你永远不会出错
大约一年前,当我开始告诉人们我已经完成了核心课程,其中一门是硕士学位的机器学习(ML)课程时,许多人对这个主题感到好奇。有些人问我是什么让我开始的,有些人只是想听听我的建议。我得到的最常见的建议是如何开始学习 ML?
照片由坦吉·索文在 Unsplash 拍摄
我对这个问题的回答是拿起一个简单的 ML 问题并解决它们。这样你会学得更快更好。但后来我意识到,我从未真正向他们展示过管理这些项目的方法。我可能会在我们的非正式谈话中粗略地讨论一下,但我从来没有机会写下来。
这就是我写这篇文章的原因。在这里,我将解释如何用 10 个步骤完成你的第一个 ML 项目。
如果你是一个初学者,在开始你的第一个 ML 项目之前,你可能想继续阅读本文的其余部分。享受吧。
1。机器学习项目的目的
你需要回答的第一个问题是,你的 ML 项目是一次性的努力还是一个持续的过程?如果是一次性的模型构建工作&剩下的只是管理模型性能的工作,那么您可以粗略地计划完成它所需的时间。最好的项目是有清晰用例的项目。这就是为什么在定义了目的之后,你可能想弄清楚谁将使用这些结果以及它们有多大用处。就像任何项目一样,如果不了解如何消费输出,您的 ML 项目将会以不完整而告终。在实践中,结果被用于不同类型的分析,包括为生产计划做出预测,寻找产品中的漏洞或客户对产品的看法,或者只是更好地了解您的数据。
2。 采集数据
许多人在听到 ML 如何解决他们的问题时都很兴奋,但他们很少知道 ML 只是引擎,真正的燃料是数据。收集数据是项目最关键的方面,因为收集数据的价值和大小将决定我们的 ML 模型的性能。问问你的公司是否允许你在工作中使用每天处理的数据。如果他们说不,你仍然可以在互联网上找到来自开源*台的数据,比如 Kaggle 或 Github *台。
由 Lukasz Szmigiel 在 Unsplash 上拍摄的照片
3。 数据的预处理
每个 ML 模型都有不同类型的输出,这取决于数据需求。每个模型都需要不同类型的数据。一些模型需要数字数据,或者一些需要文本数据。例如,一个特定的算法需要数字特征,而一些算法需要将文本拆分成单词,这可能会给像普通话这样的语言带来复杂性。
当我们收集数据时,他们会遇到诸如打字错误、拼写错误、重复和缺少值等问题。缺少值的可能不同之处是(' None ',' NA ',' NaN ','','?').可以通过这两种方法处理缺失数据。
如果您正在处理聚类问题,并且面临异常值,请尝试使用中位数。
分类 NANs 表示用最频繁出现的值替换数据。
4。特征工程
特征工程也称为降维。这是一个改变数据以获得更好的 ML 模型性能的过程。这是一项耗时的任务,你可能需要领域知识来完成。所以,我的建议是在你熟悉的领域或主题中选择一个项目。移除不必要的特性和添加一些基于领域知识的特性也可能是这个步骤的一部分。
5。机器学习类别选择
根据剑桥出版社出版的一本名为“理解机器学习”的书,在根级别有三种类型的类别,如下:
a)监督学习
b)无监督学习
c)强化学习
a)监督学习 包括分类和回归。分类是指欺诈检测、图像分类、垃圾邮件和诊断系统。回归支持风险评估和分数预测。
b)无监督学习 解决城市发展或目标营销等聚类问题。
c)强化学习 有助于预测输出,如机器人导航或库存管理
之前,您已经确定了项目的目的。现在是你根据以上所述来决定你的 ML 任务类别的时候了。
6。数据切片
这是当你正在执行一个监督 ML 项目。从同一组数据中,您需要将它们分为训练、验证和测试。不同的数据需要不同的分割比例。训练数据是用于训练模型和验证模型技能的数据验证的原始数据。验证数据检查模型参数和验证模型技巧。测试数据在真实数据上运行并计算输出。
7。采用 ML 技术
有数以千计的方法可供选择,它们都很棒,但要找到一个适合您的数据的合适模型才能产生最佳结果。已经有一些既定的指导方针来帮助你选择适合你的模型。仅给你一些例子,如果你的项目处理连续值的预测或预报,你可能想采用线性回归或神经网络。如果您正在处理一个涉及多类分类的项目,那么随机森林模型可能是最佳选择。你去拿钻头。
照片由黛安·阿尔凯尔在 Unsplash 上拍摄
8。参数调整
通过调整参数,可以增强您的训练数据。在复杂模型中,初始条件更为关键。这些条件或设置被称为超参数。超参数调整将有助于训练期间参数的更新和学习过程。这些设置,如随机搜索或网格搜索,将确保您产生更好的结果。
9。结果解释
输出是否给了我们想要的东西?答案是,我们可以分析准确性、精确度和召回率等性能指标形式的输出。这些措施将帮助我们认识到我们的模型失败或成功的根本原因。一旦完成,模型就可以部署了。
10。快速部署
数据科学家团队可以构建一个预测模型,但主要是供最终用户使用。快速简单的开发是必要的,以使模型在企业环境中易于使用,包括机器学习模型本身、应用程序接口(API)以及如何可视化预测输出。我们可以说所有的处理都将在后端完成。后端服务器以 JSON 的形式接收来自客户端的请求。随后,该输入向模型发送请求进行处理,并以在 web 浏览器上执行的 TensorflowJS 结束。
感谢您的阅读。对于任何想法或反馈,请随时通过给我的 Linkedin 发送消息来与我分享!
https://www.linkedin.com/in/faizfablillah/➡️
完全免费的机器学习阅读清单
原文:https://towardsdatascience.com/completely-free-machine-learning-reading-list-eab0c8990c54?source=collection_archive---------7-----------------------
克里斯汀·休姆在 Unsplash 上拍摄的照片
如果你正在学习机器学习,10 本免费书籍可供阅读
有许多学习数据科学和机器学习的免费在线课程。我之前在这篇文章中提到了我的前五名。然而,书籍是学习这些学科背后的细节和理论的非常有用的工具。
幸运的是,如果你足够努力,你会发现网上有大量完全免费的书籍,涵盖了你需要学习的大多数主题和概念。
这是我最喜欢的十个列表。
1.想想统计数据
艾伦·b·唐尼著
[## 想想统计 2e
艾伦·b·唐尼。下载 PDF 格式的这本书。代码示例和解决方案可从这个 GitHub 资源库获得…
greenteapress.com](https://greenteapress.com/wp/think-stats-2e/)
这本书可以在网上阅读或在这里下载 pdf。它涵盖了数据科学的许多核心统计概念,包括数据分析、分布和概率。它还严重倾向于用 python 编写的编码示例,而不是数学方程,我认为这对没有高等数学学位的人来说更容易理解。
重点话题:统计学。
读者等级:初学者。
编程语言: python
2.黑客的贝叶斯方法:贝叶斯推理的概率规划
卡梅隆·戴维森-皮隆
[## 黑客的贝叶斯方法
贝叶斯方法是推理的自然方法,但它隐藏在慢…
camdavidsonpilon.github.io](https://camdavidsonpilon.github.io/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers/)
这本书试图弥合理论贝叶斯机器学习方法和它们在概率编程中的实际应用之间的差距。
它用一种实用的第一方法为贝叶斯推理提供了一个非常好的介绍。与 think stats 类似,它更倾向于 python 示例,而不是繁重的数学公式和解释。
关键话题:机器学习的贝叶斯方法。
读者水*:初学者。
编程语言: python
3。用 Python 进行自然语言处理
作者史蒂文·伯德、伊万·克莱恩和爱德华·洛珀
[## NLTK 图书
用 Python 进行自然语言处理——用自然语言工具包分析文本
www.nltk.org](http://www.nltk.org/book_1ed/)
这是学习 python 自然语言处理的精彩介绍。重点是使用 NLTK 工具包来处理、分析、分类和挖掘文本数据。这是一个非常全面的介绍,包括对理论的解释以及许多编码的例子。
重点课题:自然语言处理和文本挖掘。
读者等级:初学者。
编程语言: python
4.r 代表数据科学
哈德利·威克姆和加勒特·格罗勒蒙德
[## r 代表数据科学
这本书将教你如何用 R 做数据科学:你将学习如何把你的数据放入 R,把它放入最…
r4ds.had.co.nz](https://r4ds.had.co.nz/)
这本书是数据科学学习 R 的最佳入门书籍之一。这本书,而不是试图涵盖数据科学的 R 的所有方面,侧重于在最常用的工具给出一个坚实的基础。
它涵盖了导入和处理数据、可视化和构建模型等主题。
关键主题:r 中数据的导入、转换、可视化和建模。
读者等级:初学者。
编程语言: R
5.机器学习向往
作者:吴恩达
[## 机器学习向往- deeplearning.ai
人工智能正在改变众多行业。来自吴恩达的免费电子书《机器学习向往》教你如何…
www.deeplearning.ai](https://www.deeplearning.ai/machine-learning-yearning/)
这本书借鉴了吴恩达领导谷歌大脑团队的工作,涵盖了成功的机器学习项目的实际步骤和框架。有一些非常有用的章节讲述了拆分数据进行验证、诊断错误以及如何在复杂的环境中建立机器学习模型。
关键话题:构建成功的机器学习系统。
读者水*:中级。
编程语言:无。
6。使用 Scikit-learn 和 Tensorflow 进行机器实践学习
作者奥雷连诺
[## 使用 Scikit-Learn 和 TensorFlow 进行机器实践学习
这本书里的图表是黑白印刷的。通过最*的一系列突破,深度学习已经…
www.oreilly.com](https://www.oreilly.com/library/view/hands-on-machine-learning/9781491962282/)
Scikit-learn 和 Tensorflow 是机器和深度学习中使用最广泛的两个 Python 库。这本书从总体上很好地概述了机器学习过程,但也涵盖了这两种工具的实现。大量漂亮的图表和编码的例子使这非常容易理解。这本书的 pdf 可以在这里获得。
重点话题:机器与深度学习。
读者等级:初学者。
编程语言: python。
7。预测:原理与实践
罗布·H·海曼和乔治·阿萨纳索普洛斯
[## 预测:原理与实践
购买印刷版或下载版欢迎来到我们的预测在线教材。这本教科书旨在提供…
otexts.com](https://otexts.com/fpp2/)
这本书提供了一个非常全面的预测方法概述。它非常详细,涵盖了非常广泛的工具和方法。包括线性和非线性回归、ARIMA 模型、神经网络等技术以及一些实际应用技巧。
重点话题:预测。
读者等级:初级到高级。
编程语言: R。
8。深度学习
伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔
[## 深度学习
深度学习教材是一个资源,旨在帮助学生和从业人员进入机器领域…
www.deeplearningbook.org](https://www.deeplearningbook.org/)
这本书介绍了机器学习,但它的主要焦点是深度学习。它涵盖了现代深度学习技术,包括正则化,卷积网络和序列建模。它不包括编码的例子,而是侧重于理论。它的目标是学生和从业者,所以初学者可以消化。
重点话题:深度学习。
读者等级:初级到高级。
编程语言:无。
9.线性代数
吉姆·赫夫龙著
[## 免费线性代数教科书
线性代数是美国第一个本科线性代数课程的教材。你可以把它作为正文,作为…
joshua.smcvt.edu](http://joshua.smcvt.edu/linearalgebra/)
线性代数是机器学习领域的关键数学基础之一。这本书是一本免费的教科书,涵盖了典型的本科课程中通常会涉及的基本概念。除了理论,还包括贯穿始终的练习。
重点题目:线性代数。
读者等级:初学者。
编程语言:无。
10。用 Python 介绍机器学习
作者安德里亚斯·c·穆勒和萨拉·圭多
[## Andreas C. Müller,Sarah Guido -用 Python 介绍机器学习 _ 数据指南…
编辑描述
drive.google.com](https://drive.google.com/file/d/10Vrml277NCOa6SS9GV10m847jtPynt_n/view)
这本书侧重于机器学习技术的实际应用,而不是涵盖该领域背后的数学。它包括机器学习,数据处理,模型评估和典型的机器学习工作流程的基本概念的详细解释。它提供了许多使用 scikit-learn 的编码示例。
关键话题:机器学习。
读者等级:初学者。
编程语言: python。
这个阅读清单只包括研究机器学习的免费书籍。然而,还有许多伟大的机器学习书籍不能完全免费阅读。这是一个在 Github 上整理的更全面的机器学习书籍列表。
如果你正在寻找更多免费学习数据科学的资源,请参见我以前的帖子— 如何免费学习数据科学。
感谢阅读!
我每月发一份时事通讯,如果你想加入,请通过此链接注册。期待成为您学习旅程的一部分!