TowardsDataScience-博客中文翻译-2020-一百-
TowardsDataScience 博客中文翻译 2020(一百)
强化学习—第 1 部分
FAU 讲座笔记关于深度学习
顺序决策
FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座
这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。 自己试试吧!如果您发现错误,请告诉我们!
航行
欢迎回到深度学习!所以今天,我们想讨论强化学习的基础。我们将研究如何教会一个系统玩不同的游戏,我们将从顺序决策的第一次介绍开始。
只有几次强化学习的迭代,训练出来的智能体还处于初级水平。使用 gifify 创建的图像。来源: YouTube 。
这里,我有几张幻灯片给你们看。你看,我们的主题是强化学习,我们想继续讨论顺序决策。在本课程的后面,我们还将讨论强化学习及其所有细节。我们还将研究深度强化学习,但今天我们只研究了顺序决策。
比较容易的游戏之一:多臂大盗。 CC 下的图片来自深度学习讲座的 4.0 。
好吧。顺序决策!嗯,我们想玩几个游戏。你能想到的最简单的游戏就是拉几个杠杆。如果你试图形式化这一点,那么你最终会陷入所谓的多臂土匪问题。所以,让我们做几个定义:我们需要一些动作,我们将其形式化为在时间 t 从一组动作 A 中选择一个动作 a 。所以,这是我们可以采取的一系列可能的行动。如果我们选择一个动作,那么这就有一些含义。如果你选择了一个特定的行动,那么你将会产生一些奖励。行动和奖励之间的关系是概率性的,这意味着有一个可能不同的、未知的概率密度函数来描述行动和奖励之间的实际关系。所以,如果你想到你的多臂强盗,你有几个吃角子老丨虎丨机,你拉其中一个杠杆,这产生一些奖励。但也许,所有这些老丨虎丨机都是一样的。或许他们不是。所以,你可能拉的每一只手都有不同的概率产生某种回报。现在,您希望能够选择一个动作。为了做到这一点,我们定义了一个所谓的政策。策略是一种形式化如何选择动作的方法。它本质上也是一个概率密度函数,描述了选择某种行为的可能性。政策本质上是我们想要影响游戏的方式。所以,政策是掌握在我们手中的。我们可以定义这个策略,当然,我们希望这个策略在游戏中是最优的。
玩这个游戏完全是为了预期的回报。来自深度学习讲座的 4.0CC 下的图片。
那么,关键要素是什么呢?那么,我们想要实现什么呢?我们希望获得最大的回报,特别是,我们不仅仅希望在游戏的每一个时间点都有最大的价值。相反,我们想计算一段时间内的最大预期回报。因此,我们对将要产生的回报进行了估计。我们计算了一个平均值,因为这让我们可以估计如果我们玩这个游戏很长时间,哪些行为会产生什么样的回报。这和监督学习是不同的,因为在这里,我们不是说做这个动作或者做那个动作。相反,我们必须通过我们的训练算法来决定选择哪些动作。显然,我们可能会犯错误,我们的目标是选择能够随着时间的推移产生最大预期回报的行动。所以,如果我们在一步中输了,如果平均来说,我们仍然可以获得高平均回报,这并不重要。所以,这里的问题是,当然,我们对回报的期望值是不知道的。所以,这就是强化学习的实际问题。我们想尝试估计这个预期回报和相关的概率。所以,我们能做的是,我们可以把我们的 r 下标 t 公式化为一个热编码向量,它反映了 a 的哪个动作实际上导致了奖励。
行动价值函数 Q(a)描述了该行动的平均预期回报。来自深度学习讲座的 4.0CC 下的图片。
如果我们这样做了,我们就可以使用奖励的平均值在线估计概率密度函数。我们把它称为函数 Q(a ),这就是所谓的作用值函数,它基本上随着我们观察到的每一个新信息而变化。那么,我们如何做到这一点呢?有一种增量的方法来计算 a 的 Q 下标 t,我们可以很容易地展示出来。我们定义 Q 下标 t 为所有时间步长的和。所以,Q 下标 t+1 等于所有时间步 t 和所得报酬的总和。当然,你除以 t,现在,我们可以证明这是可以分开的。所以,我们可以取出总和的最后一个元素,也就是 t,然后让总和从 1 运行到 t-1。如果我们这样做,那么我们也可以引入 t-1 项,因为如果你在这里引入它,除以 1/(t-1),这将抵消。所以,这是一个完美的陈述。然后,我们看到在右边部分,除了 Q 下标 t,我们基本上没有别的了,所以,前面的 Q 下标 t,这是我们已经确定的。然后,我们可以稍微重新排列一下,在最后一行,你可以看到,我们可以将 Q 下标 t+1 更新为旧的 Q 下标 t+1/t 乘以 r 下标 t 减去 Q 下标 t,因此,我们可以得到一个增量式的动作值函数更新公式。这非常有用,因为我们不必存储所有的奖励,但我们可以通过迭代的方式来实现。
探索与开发的困境。来自深度学习讲座的 CC BY 4.0 下的图片。
现在,如果我们继续,那么我们可以考虑为了训练这样一个系统,我们必须做的所有不同的步骤。你最终会遇到所谓的探索-开发困境。所以,当然,我们想最大化我们的回报。我们试图以一种方式选择我们的政策,使我们能够从我们的行动价值函数中获得最大的回报。如果你已经有了一个好的计划,这将会起作用。所以,如果你已经知道事情是怎样的。所以,让我们说你正在寻找一个比萨饼的配方,你已经看到了一些。你已经喜欢的披萨。然后,你可以再次生产同样的比萨饼,你知道这个食谱是好的。所以,我会得到我的奖励,这将是决定性的,如果你使用所谓的贪婪行动选择,你总是选择最大值。你总是产生同样的动作,给出同样的输入。这导致了一个问题,我们也需要对我们的回报进行抽样,因为我们不知道最佳配置是什么,因为我们只是在剥削。所以,如果我们只遵循贪婪的行动选择,那么我们将永远不会做出任何新的观察。我们将永远生产同样的比萨饼。也许有更好的披萨。也许有我们更喜欢的披萨。所以,只有探索才能发现。所以时不时地,我们必须尝试新的食谱,因为否则,我们不知道应该如何混合配料。或许,我们会找到一个比我们已经吃过的更好的披萨。这意味着有时,我们不得不做一些不会产生最大回报的举动。从没有产生一个好的回报,我们至少可以知道,这个特殊的举动不是一个非常好的。所以,如果你训练这样一个系统,那么,在开始的时候,你要更多地关注探索,找出哪些动作是好的,哪些动作不是那么好。然后,你可以越来越多地利用它,以便专注于在某些情况下有效的策略。
不同的行动选择策略。 CC 下的图片来自深度学习讲座的 4.0 。
那么,我们如何做到这一点呢?一种非常简单的行为抽样形式是均匀随机分布。所以,在均匀随机分布中,你不需要任何关于系统的知识。你只是随机选择行动,并且以相等的概率选择它们。所以,你只需选择一些行动,所有的行动都是同样可能的。每个动作的可能性是一个可能动作集的基数。嗯,这可能有利于探索,但你可能会犯很多错误。所以,有一点好一点的。这被称为ε-贪婪方法。所以在这里,你选择行动给定这个概率密度函数。你可以看到我们选择 1 — ε。假设ε是 0.1。然后,我们以 90%的概率选择使我们的行动价值函数最大化的行动,即产生最大预期回报的行动。在 10%以上 n — 1,其中 n 是行动的数量,即对于所有其他行动,我们以此概率选择它们。所以,你可以看到,在大多数情况下,我们会选择,当然,产生最大预期回报的行动,但我们仍然可以切换到其他行动,以便也做一些探索。当然,你选择的ε越高,你就越有可能探索你的行动空间。然后,还有其他的变种。例如,您也可以使用 softmax 并引入一些温度参数τ。这里,τ的用法与我们刚才使用ε的方法相似。所以在这里,我们找到了一个不同的公式,我们可以使用这个温度,然后慢慢降低温度,这样我们就开始主要关注产生最大预期回报的行动。那么,这本质上是一个更柔和的版本吗,因为这里我们也考虑到了其他行为也可能引入不同的奖励。所以,如果你有两个奖励几乎相同的行动,最大奖励版本当然只会选择真正产生最大奖励的那一个。如果你的奖励是 10 和 9,那么 softmax 函数也会相应地拆分这个分布。
我们当前观察的总结。来自深度学习讲座的 CC BY 4.0 下的图片。
到目前为止我们看到了什么?到目前为止,我们已经看到,我们可以在一个被称为多臂土匪问题的环境中进行顺序决策。我们可以看到,我们找到了一个函数 Q——所谓的行动价值函数——它能够描述我们的行动有哪些预期回报。然后,我们可以用它来选择我们的行动。例如,对于贪婪行为选择,这将总是选择产生最大预期回报的行为。所以,我们也看到,如果你只做贪婪的选择,那么我们会有点卡住,因为我们永远不会观察某些星座。如果我们错过了星座,我们可能会错过赢得游戏或在游戏中产生大量奖励的非常好的食谱或非常好的策略。所以,我们也需要探索。否则,我们就无法找出最佳策略。到目前为止,我们还没有看到的是,我们的奖励实际上取决于世界的状态。因此,在我们的场景中,我们的一切都只与动作相关。行动是决定性因素。但这是一种简化。当然,一个世界有一个状态。这是我们在讨论强化学习和马尔可夫决策过程时要考虑的。此外,我们的时间没有影响奖励。所以,在当前的星座中,先前的动作完全独立于随后的动作。这也是一种广泛的简化,在实际应用中可能并不如此。
在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。
这就是我们下次真正讨论强化学习的原因。在接下来的视频中,我们将介绍所谓的马尔可夫决策过程。我们将研究强化学习到底是什么。所以,这只是一个关于我们在玩游戏时可以期待什么的小玩笑。但在下一个视频中,我们将真正了解 constellation,其中世界确实有一个状态,然后我们还对不同动作之间的依赖关系进行建模。所以,会稍微复杂一点。但是你应该已经在这个视频中学到了,重要的是,你找到了一个描述特定动作值的函数。这是一个会再来的概念。您还应该记住的概念是,您可以使用不同的策略。所以,你可以有贪婪行动选择,ε-贪婪行动选择,或者均匀随机策略。所以,请记住这些。在未来的视频中,当我们谈到强化学习时,它们也很重要。非常感谢您的收听,希望在下一段视频中见到您。再见!
在接下来的讲座中,我们将看到如何训练深度强化学习系统。使用 gifify 创建的图像。来源: YouTube 。
如果你喜欢这篇文章,你可以在这里找到更多的文章,在这里找到更多关于机器学习的教育材料,或者看看我们的深度 学习 讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube、Twitter、脸书、LinkedIn 或 T21。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中生成文字记录,试试自动博客。
链接
链接到萨顿 2018 年草案中的强化学习,包括深度 Q 学习和 Alpha Go 细节
参考
1大卫·西尔弗、阿贾·黄、克里斯·J·马迪森等,“用深度神经网络和树搜索掌握围棋”。载于:自然 529.7587 (2016),第 484–489 页。
【2】大卫·西尔弗、朱利安·施利特维泽、卡伦·西蒙扬等人《在没有人类知识的情况下掌握围棋游戏》。载于:自然 550.7676 (2017),第 354 页。
【3】David Silver,Thomas Hubert,Julian Schrittwieser,等《用通用强化学习算法通过自玩掌握国际象棋和松木》。载于:arXiv 预印本 arXiv:1712.01815 (2017)。
[4] Volodymyr Mnih,Koray Kavukcuoglu,David Silver 等,“通过深度强化学习实现人类水平的控制”。载于:自然杂志 518.7540 (2015),第 529-533 页。
【5】马丁·穆勒。《电脑围棋》。摘自:人工智能 134.1 (2002),第 145-179 页。
6理查德·萨顿和安德鲁·g·巴尔托。强化学习导论。第一名。美国麻省剑桥:麻省理工学院出版社,1998 年。
强化学习—第二部分
FAU 讲座笔记关于深度学习
马尔可夫决策过程
FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座
这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是讲座视频&配套幻灯片的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。 自己试试吧!如果您发现错误,请告诉我们!
航行
强化学习 PacMac。使用 gifify 创建的图像。来源: YouTube 。
欢迎回到深度学习!所以,今天我们想讨论一下这个所谓的马尔可夫决策过程,它是强化学习的基础。
多臂土匪的局限性。 CC 下的图片来自深度学习讲座的 4.0 。
我给你带了几张幻灯片。我们可以在这里看到我们实际上在谈论什么。现在的主题是强化学习。真的,我们想学习如何玩游戏。关键要素将是马尔可夫决策过程。因此,我们必须扩展我们在前面的视频中谈到的多臂土匪问题。我们必须引入一个状态世界。所以,世界现在有了一个状态。奖励也取决于行动和单词的状态。因此,根据世界的状况,行动可能会产生非常不同的回报。我们可以用概率密度函数对其进行编码,就像你在这张幻灯片上看到的那样。还有什么?这个场景现在被称为语境强盗。在完全强化学习问题中,行为也会影响状态。所以,我们会看到无论我采取什么行动,它都会对状态产生影响,这也可能是概率性的。
马尔可夫决策过程。来自深度学习讲座的 CC BY 4.0 下的图片。
所以,我们可以用另一个概率密度函数来描述。这就把我们引向了所谓的马尔可夫决策过程。马尔可夫决策过程,它们采取以下形式:你有一个代理,在上面的代理正在做动作 a 下标 t。这些动作对环境有影响,然后产生奖励,就像在多臂强盗问题中一样。它也改变了状态。所以现在,我们的行为和国家是相互关联的,它们当然是相互依赖的。因此,我们有一个状态转移概率密度函数,它将导致状态根据先前的状态和采取的行动而改变。这种转变也产生了一种回报,这种回报现在取决于国家和行动。否则,它与我们已经在多臂土匪问题中看到的非常相似。当然,我们需要策略,而策略现在也依赖于状态,因为你想了解状态以选择你的行动,而不仅仅是依赖于先验知识来选择独立于状态的行动。所以,都是相应展开的。现在,如果所有这些集合都是有限的,这就是有限马尔可夫决策过程。如果你看这个图,你会发现这是一个非常抽象的描述整个情况的方式。代理本质上是选择动作和设计动作的系统。环境就是一切。因此,举例来说,如果你要控制一个机器人,机器人本身可能是环境的一部分,因为机器人的位置也编码在状态中。代理所能做的一切仅仅是设计动作。关于当前情况的知识被编码在状态中。
网格世界中一个简单游戏的例子。 CC 下的图片来自深度学习讲座的 4.0 。
让我们看一个更简单的例子,而不是马上控制机器人。我们将研究一个简单的游戏。你看这是一个伟大的游戏。一个网格世界,我们有几个方块,然后我们的代理人可以在这些方块之间移动。当然,代理人的职位也是国家的一部分。你可以这样表述: s 是我们当前所在的字段。现在,我们的特工可以向四个方向移动。所以,我们可以上下左右移动。任何引导网格的动作都有一个概率等于狄拉克δ函数,这个函数总是产生先前的状态。所以,你不能离开网格。每当你试图离开棋盘的时候,你就会回到你试图离开棋盘的原始位置。此外,你会得到-1 的确定性奖励。所以,试图离开董事会将会受到负回报的惩罚。还有什么?好吧,每当我们到达一个不同于 A '和 B '的牌,这必然导致奖励为 0。所以,所有的瓷砖都没有奖励。全面行动对你没有任何好处。唯一能产生奖励的牌是当你到达 A '或 B '时。为了产生奖励,你必须移动到位置 A 或 B。在这些位置上,你可以选择任何动作不管你做什么,但你会被传送到 B '或 A ',这取决于你是在 A 还是 B 上。你在那里神秘地为 A 产生+10 的奖励,为 B 产生+5 的奖励。所以,这是我们的游戏,游戏非常简单。
我们网格世界例子的统一随机策略。来自深度学习讲座的 CC BY 4.0 下的图片。
当然,如果你想玩这个游戏或关卡,你想产生大量的奖励。策略应该引导你到方块 A 和 B,然后在 A '和 A 或 B '和 B 之间来回循环,所以这可能是玩这个游戏的好策略,对吗?好吧。所以现在,我们必须以某种方式编码我们的状态和位置。因为我们可以在 25 个潜在的不同位置上,我们的行动也必须乘以这个棋盘游戏中潜在位置的数量。那么,让我们来看一个示例策略。该策略现在依赖于动作和状态。状态或多或少是这个网格中的位置,动作当然是,正如我们所说的上、下、左、右。那么现在,我们来看看统一随机政策。它可以用这里显示的方式来可视化。所以,不管我们在棋盘的哪个位置,我们总是以相等的概率选择四个行动中的一个。在这个网格世界的例子中,我们可以在这个简单的图形中可视化我们的整个状态动作空间。所以,这对于可视化非常有用,你可以很好地理解这个例子。所以在这个统一随机政策下。当然,没有理由认为这是一个非常好的策略,因为我们会尝试走出棋盘,当然,我们偶尔也会碰到 A 和 B,但这不是一个非常好的策略。
怎样才能得到更好的政策? CC 下的图片来自深度学习讲座的 4.0 。
所以现在的问题是“我们如何才能制定更好的政策?”或者“我们如何评估好的政策?”。这里你要问的关键问题是你要问“什么是好政策?”。所以,我们必须非常精确地定义什么是好的。本质上,我们必须区分两种不同的任务。有些偶发的任务是有结束的。所以它们像一集一样有开头和结尾。有无限长的连续任务。所以,如果你有一个无限长的任务,那么这是一个不同的情况。实际上,您可以通过在情节任务中选择一个终端状态来统一这两者,该状态只转换到它们自己,并产生确定性的零回报。所以,你可以通过到达一个最终状态,将你的阶段性任务变成一个无限的任务,而这个最终状态继续产生零回报。这样,我们就不用再区分两者了。我们如何衡量什么是好政策?我们希望未来的回报最大化。因此,这是非常重要的,与我们的多臂强盗问题相反,我们只是简单地平均或计算我们的回报的期望值,我们现在感兴趣的是最大化未来回报。所以,如果你看这个值 g 下标 t,你可以看到,这当然取决于政策。因此,我们寻求最大化我们对政策的预期未来回报。
在 80 年代的玩具中,通过范例进行训练已经成为可能。使用 gifify 创建的图像。来源: YouTube 。
我们用下面的方法来计算它:所以,我们从 t + 1 开始,遍历整个序列,直到 T 是最后一个元素。所以,T 也可以是无穷大,如果你去做一个无限长的任务。我们要计算在游戏结束前的所有未来时间步骤中产生的奖励。现在,如果我们不考虑离下一次奖励还有多远,这就有点不公平了。例如,在前面的游戏中,我们可能会试图找到到达 A 和 B 的最短路径,以获得奖励。如果我们不忽略这一点,那么如果我们有一个很高但在未来很遥远的奖励,它对我们来说可能没有我们能很快产生的奖励重要。这就是为什么我们在这里引入了这个贴现因子γ。γ的(k — t — 1)次方用于贴现遥远未来的报酬。如果我们这样做,我们就会含蓄地倾向于短的解决方案,而不是长的。所以,我们想摆脱随机移动的解决方案,因为我们想选择最短的路径直接获得回报。这可以通过引入这个贴现因子来实现。我们看到我们现在能够描述一项政策的优点或价值。现在的问题是,当然,我们想要优化这个政策的预期未来回报。在这个等式中,你甚至看不到政策,因为政策是产生我们奖励的决定性因素。你必须记住的一点是,你要在 0 和 1 之间选择你的贴现因子。只要你的序列不是无限长,值 1 实际上是允许的。在这种情况下 T 不可能有无穷大。如果您有无限长的序列,那么您必须选择一个小于 1 的折扣因子。好吧。现在,我们讨论了最基本的内容,如何定义马尔可夫决策过程,以及如何评估保单的价值。
在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。
当然,我们仍然缺少的和我们下次在深度学习中讨论的,是这一点的实际含义。因此,我们希望能够确定好的政策,我们真的希望进入学习部分。因此,我们希望更新政策,以便在每一步都做得更好。这个概念被称为策略迭代。所以,我希望你喜欢这个视频,你学习了马尔可夫决策过程的基本概念,以及在这样一个马尔可夫决策过程中对政策的评估。这是对预期未来回报的评价。因此,这与我们的多臂强盗问题相比有很大的不同,在多臂强盗问题中,我们只考虑最大的预期回报。现在,我们要考虑到,我们要最大化未来的回报。到目前为止,我们所做的一切不仅仅是重要的,而是为未来的步骤奠定基础,以便找到赢得比赛的途径。非常感谢您的收听,希望在下一段视频中见到您!再见!
后来的强化迭代学会了吃豆人。使用 gifify 创建的图像。来源: YouTube 。
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中获得文字记录,试试自动博客。
链接
链接到萨顿 2018 年草案中的强化学习,包括深度 Q 学习和 Alpha Go 细节
参考
1大卫·西尔弗、阿贾·黄、克里斯·J·马迪森等,“用深度神经网络和树搜索掌握围棋”。载于:自然 529.7587 (2016),第 484–489 页。
【2】大卫·西尔弗、朱利安·施利特维泽、卡伦·西蒙扬等人《在没有人类知识的情况下掌握围棋游戏》。载于:自然 550.7676 (2017),第 354 页。
【3】David Silver,Thomas Hubert,Julian Schrittwieser,等《用通用强化学习算法通过自玩掌握国际象棋和松木》。载于:arXiv 预印本 arXiv:1712.01815 (2017)。
[4] Volodymyr Mnih,Koray Kavukcuoglu,David Silver 等,“通过深度强化学习实现人类水平的控制”。载于:自然杂志 518.7540 (2015),第 529-533 页。
【5】马丁·穆勒。《电脑围棋》。摘自:人工智能 134.1 (2002),第 145-179 页。
6理查德·萨顿和安德鲁·g·巴尔托。强化学习导论。第一名。美国麻省剑桥:麻省理工学院出版社,1998 年。
强化学习—第 3 部分
FAU 讲座笔记关于深度学习
策略迭代
FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座
这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。 自己试试吧!如果您发现错误,请告诉我们!
航行
此外,马里奥并没有从强化学习中解脱出来。使用 gifify 创建的图像。来源: YouTube 。
欢迎回到深度学习!所以今天,我们想深入探讨强化学习。我们今天要解释的概念是政策迭代。它告诉我们如何制定更好的策略来设计赢得比赛的策略。
价值函数模拟了我们的水晶球。 CC 下的图片来自深度学习讲座的 4.0 。
那么,让我们来看看我给你们准备的幻灯片。这是我们讲座的第三部分,我们想谈谈政策迭代。现在,在我们有这个行为价值函数之前,这个函数可以评估一个行为的价值。当然,这现在还取决于状态 t。这本质上是我们的——你可以说是甲骨文——试图预测未来的回报 g 下标 t。它取决于遵循特定的政策,该政策描述了如何选择行动和结果状态。现在,我们也可以在这里找到一个替代的公式。我们引入了状态值函数。所以,以前我们有行动价值函数,它告诉我们某个行动有多有价值。现在,我们想引入状态值函数,它告诉我们某个状态有多有价值。在这里,你可以看到它以非常相似的方式被形式化。同样,我们对未来的回报有一些期望值。当然,这现在取决于国家。所以,我们有点抛开了对动作的依赖,我们只关注状态。你现在可以看到,这是相对于国家的未来回报的期望值。所以,我们想边缘化的行动。我们不关心行动的影响是什么。我们只想弄清楚某个状态的值是多少。
记住网格世界。现在,我们可以计算每个状态的状态值函数。来自深度学习讲座的 4.0CC 下的图片。
我们实际上可以计算这个。因此,我们也可以在网格示例中这样做。如果你还记得这一个,你会记得我们有一个简单的游戏,你有一个 A 和 B,基本上是网格上的位置,然后将你传送到 A '和 B '。一旦你到达 A 和 B,你会得到奖励。对 A 来说是+10,对 B 来说是+5。每当你试图离开董事会,你会得到一个负的奖励。现在,我们可以玩这个游戏,计算状态值函数。当然,我们可以在统一随机策略下这样做,因为我们不必了解游戏的任何内容。如果我们玩随机统一策略,我们可以简单地选择行动,玩这个游戏一段时间,然后我们能够根据之前的定义计算这些状态值。你可以看到边缘的瓷砖,特别是在底部,它们甚至有一个负值。当然,他们可以有负值,因为如果你在边缘瓦片,我们发现-1.9 和-2.0 和底部。在角落瓷砖,有 50%的可能性,你会尝试离开网格。在这两个方向上,你当然会产生负回报。所以,你可以看到我们有更有价值的状态。你可以看到如果你看 A 和 B 所在的位置,它们有一个非常高的值。所以 A 的预期未来回报是 8.8,而 B 的预期未来回报是 5.3。所以,这些都是非常好的州。所以,你可以说,有了这个状态值,我们在某种程度上对我们的游戏有所了解。所以,你可以说“好吧,也许我们可以用这个。”我们现在可以对这个状态值使用贪婪操作选择。让我们定义一个策略,这个策略现在总是选择导致更高值状态的动作。如果你这样做,你有一个新的政策。如果你玩这个新政策,你会发现你有一个更好的政策。
行动价值函数估计每个状态下每个行动的预期未来回报。 CC 下的图片来自深度学习讲座的 4.0 。
因此,我们现在可以将它与我们之前使用的动作值函数联系起来。我们以类似的方式引入了状态值函数。因此,我们现在可以看到,我们可以引入一个动作值函数,它是 s 和 a 的 Q 下标策略,即状态和动作的 Q 下标策略。这基本上说明了转移概率。所以,你现在可以计算你的状态和行为的 Q 政策,作为给定状态和行为的未来回报的期望值。你可以用类似的方法来计算。现在,你得到了每个状态和每个行为的预期未来回报。
只能有一个 V*。 CC 下的图片来自深度学习讲座的 4.0 。
所有这些价值函数都是相等的吗?不能。只能有一个最优状态值函数。我们可以在不提及具体政策的情况下表明它的存在。因此,最优状态值函数就是具有最佳策略的所有状态值函数的最大值。因此,最佳政策总是会产生最优的状态-价值函数。现在,我们还可以定义最优行动值函数。这现在可以与我们的最优状态值函数联系起来。我们可以看到,最佳行动价值函数是下一步的预期回报加上我们的贴现因子乘以最佳状态价值函数。因此,如果我们知道最优状态值函数,那么我们也可以导出最优动作值函数。所以,他们是有关系的。
均匀随机 V 和 V*的状态值函数。来自深度学习讲座的 CC BY 4.0 下的图片。
这就是均匀随机政策的状态值函数。我可以给你看最优 V*,也就是最优状态值函数。当然,您会看到它的价值要高得多,因为我们一直在为此进行优化。您还观察到最优状态值函数是严格正的,因为我们在这里处于确定性设置中。所以,非常重要的观察:在确定性设置中,最优状态值函数将严格为正。
如何才能订购保单? CC 下的图片来自深度学习讲座的 4.0 。
现在,我们还可以订购保单。我们必须确定什么是更好的政策。我们可以用下面的概念对它们进行排序:当且仅当π的状态值都高于用π'得到的状态值时,更好的策略π优于策略π'。如果这样做,那么任何返回最优状态值函数的策略都是最优策略。所以,你可以看到只有一个最优状态值函数,但是可能有不止一个最优策略。因此,可能有两个或三个不同的政策导致相同的最优状态值函数。因此,如果你知道最优状态值或最优动作值函数,那么你可以通过贪婪动作选择直接获得最优策略。所以,如果你知道最优状态值,如果你完全了解所有的行动等等,那么你总是可以通过贪婪的行动选择得到最优策略。
对状态值的贪婪行为选择。 CC 下的图片来自深度学习讲座的 4.0 。
那么,让我们看看这在政策方面会产生什么样的结果。现在,对最优状态值函数或最优行为值函数的贪婪行为选择将导致最优策略。你在左边看到的是在均匀随机状态值函数上的贪婪行为选择。我们之前在视频中计算的。当然,你可以选择你的行动,你的下一个状态是一个更高价值的状态,你最终得到这种策略。现在,如果你对最优状态值函数做同样的事情,你可以看到我们基本上出现了一个非常相似的政策。你会看到一些不同之处。事实上,你不必总是像左边显示的那样向上移动。所以,在很多情况下,你也可以向左或向上移动。实际上,你可以在这些方块中的每一个上选择行动,这些方块用多个箭头以相等的概率表示。所以,如果有一个向上和向左的箭头,你可以选择任何一个行动,你仍然会有一个最优的政策。因此,这将是由最优状态值函数上的贪婪动作选择创建的最优策略。
贝尔曼方程。来自深度学习讲座的 CC BY 4.0 下的图片。
现在,最大的问题是:“我们如何计算最优价值函数?”我们还必须确定这个最佳状态值函数和最佳动作值函数。为了做到这一点,有贝尔曼方程。它们本质上是值函数的一致性条件。这是状态值函数的例子。您可以看到,您必须总结由您的策略决定的所有不同的操作。所以,我们想边缘化实际行动的影响。当然,根据你选择的行动,你会产生不同的状态和不同的回报。所以,你也可以对不同的状态和相应的奖励进行求和,然后将这些状态的概率乘以实际奖励加上下一个状态的贴现状态值函数。这样,你就可以确定状态值函数。你可以看到,在这个计算中,当前状态和下一个状态之间存在这种依赖性。
贝尔曼方程也可以解释为更新规则。 CC 下的图片来自深度学习讲座的 4.0 。
这意味着你可以把它写成一个线性方程组,然后用小问题来解决它。但更好的是,您可以通过将贝尔曼方程转化为更新规则来迭代解决这个问题。所以,你现在可以看到,如果我们简单地应用贝尔曼方程,我们可以为当前状态生成一个新的值函数 k+1。所以,我们必须计算所有不同的行动。我们必须实际评估给定状态下的所有不同行为。然后,我们确定所有下一个未来状态和下一个未来奖励,并根据我们之前的状态-值函数更新它。当然,我们对所有的状态都这样做,然后,我们有一个更新的状态值函数。好吧。所以,这是一个有趣的观察。如果我们有一些策略,我们实际上可以运行这些更新。
政策是可以改进的。来自深度学习讲座的 CC BY 4.0 下的图片。
这就引出了政策改进的概念。这个政策迭代是我们在这个视频中真正想要谈论的。所以,我们现在可以用我们的国家价值函数来指导我们寻找好的政策。然后,我们更新策略。因此,如果我们使用贪婪动作选择来更新状态值函数,那么这也意味着我们同时更新我们的策略,因为如果我们改变状态值,对我们的状态值的贪婪动作选择将总是导致不同的动作。因此,在贪婪动作选择的情况下,状态值的任何改变或更新也将意味着更新的策略,因为我们将它们直接链接在一起。这意味着我们可以在我们的状态值函数上迭代评估一个贪婪策略。如果我们的策略停止改变,我们就停止迭代。这样,我们可以更新状态值,随着状态值的更新,我们也可以立即更新我们的策略。这真的能保证有效吗?
政策改进定理。 CC 下的图片来自深度学习讲座的 4.0 。
这是政策改进定理。如果我们考虑改变一个单一的行动 a 下标 t 和状态 s 下标 t,遵循一个政策。那么,一般来说,如果我们有一个更高的动作值函数,所有状态的状态值都会增加。这意味着我们有了更好的政策。因此,新政策是更好的政策。这也意味着我们也获得了更好的状态值,因为我们在所有的状态下都产生了更高的未来回报。这意味着状态值函数也必须增加。如果我们只贪婪选择,那么我们总会产生比收敛前状态值更高的动作值。因此,我们使用贪婪动作选择来迭代地更新状态值,这确实是一个有保证的概念,以便改进我们的状态值。如果政策不再改变,我们就终止。最后一句话:如果我们不为策略评估遍历状态空间中的所有状态,而是直接更新策略,这就叫做值迭代。好吧。你已经在这个视频中看到了,我们如何使用状态值函数,来描述一个特定状态的预期未来回报。我们已经看到,如果我们对状态-值函数进行贪婪的动作选择,我们可以用它来生成更好的策略。如果我们遵循更好的政策,那么我们的国家价值函数也会增加。所以如果我们遵循这个概念,我们最终会得到政策迭代的概念。因此,随着状态值函数的每次更新,当您找到更高的状态值时,您也会找到更好的策略。这意味着我们可以通过策略迭代的概念来逐步改进我们的策略。好吧。这是强化学习概念中的第一个学习算法。
在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。
但当然,这并不是一切。有几个缺点,我们将在下一个视频中讨论更多关于如何改善我们政策的概念。还有几个。因此,我们将介绍它们,并谈一谈不同版本的缺点。所以,我希望你喜欢这个视频,我们将在接下来的几个视频中更多地讨论强化学习。所以,敬请期待,希望在下一段视频中见到你。拜拜。
强化学习超级马里奥赛车 64。使用 gifify 创建的图像。来源: YouTube 。
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中获得文字记录,试试自动博客。
链接
链接到 Sutton 2018 年草案中的强化学习,包括深度 Q 学习和 Alpha Go 细节
参考
1大卫·西尔弗、阿贾·黄、克里斯·J·马迪森等,“用深度神经网络和树搜索掌握围棋”。载于:自然 529.7587 (2016),第 484–489 页。
【2】大卫·西尔弗、朱利安·施利特维泽、卡伦·西蒙扬等人《在没有人类知识的情况下掌握围棋游戏》。载于:自然 550.7676 (2017),第 354 页。
【3】David Silver,Thomas Hubert,Julian Schrittwieser,等《用通用强化学习算法通过自玩掌握国际象棋和松木》。载于:arXiv 预印本 arXiv:1712.01815 (2017)。
[4] Volodymyr Mnih,Koray Kavukcuoglu,David Silver 等,“通过深度强化学习实现人类水平的控制”。载于:自然杂志 518.7540 (2015),第 529-533 页。
【5】马丁·穆勒。《电脑围棋》。摘自:人工智能 134.1 (2002),第 145-179 页。
6理查德·萨顿和安德鲁·g·巴尔托。强化学习导论。第一名。美国麻省剑桥:麻省理工学院出版社,1998 年。
强化学习—第 4 部分
FAU 讲座笔记关于深度学习
替代方法
FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座
这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。 自己试试吧!如果您发现错误,请告诉我们!
航行
刺猬索尼克也被看作是关于强化学习的。使用 gifify 创建的图像。来源: YouTube 。
欢迎回到深度学习!今天,除了您在之前的视频中看到的策略迭代概念,我们还想讨论一些其他的强化学习方法。让我们看看今天我为你们带来了什么。我们将研究其他解决方法。
政策迭代的局限性。 CC 下的图片来自深度学习讲座的 4.0 。
您可以看到,在我们之前讨论的策略和值迭代中,它们需要在学习期间更新策略,以获得我们的最佳状态值函数的更好近似。这些被称为策略算法,因为你需要 n 个策略。该政策正在更新。此外,我们假设状态转换和奖励是已知的。因此,产生新状态和新奖励的概率密度函数是已知的。如果他们不是,那么你不能应用以前的概念。所以,这很重要,当然有方法可以让你放松。因此,这些方法的主要区别在于它们如何执行策略评估。那么,让我们来看几个替代方案。
蒙特卡洛技术。来自深度学习讲座的 CC BY 4.0 下的图片。
我想给你们看的第一个是基于蒙特卡罗技术的。这仅适用于偶发任务。在这里,这个想法是不符合政策的。因此,您可以通过遵循任意策略来了解最佳状态值。你用什么策略并不重要。所以这是一个武断的政策。可能是多份保单。当然,你仍然有探索/开发的困境。所以你要选择真正覆盖所有州的政策。您不需要关于环境动态的信息,因为您可以简单地运行许多临时任务。你试图到达所有可能的状态。如果您这样做,那么您可以使用一些策略来生成这些剧集。然后,你反向循环一集,积累预期的未来回报。因为你一直玩游戏到最后,所以你可以在这一集的时间上倒退,累积已经获得的不同奖励。如果一个州还没有被访问过,你可以把它添加到一个列表中,然后使用这个列表来计算状态值函数的更新。所以,你可以看到这只是特定状态下这些列表的总和。这将允许您更新您的状态值,这样您就可以迭代,以实现最佳的状态值函数。
时间差异学习。 CC 下的图片来自深度学习讲座的 4.0 。
现在,另一个概念是时间差异学习。这是一种符合政策的方法。同样,它不需要关于环境动态的信息。这里的方案是,你循环并遵循一定的策略。然后,您使用策略中的一个动作来观察奖励和新状态。您可以使用先前的状态值函数加上α来更新您的状态值函数,α用于加权新观察的影响乘以新奖励加上新状态的旧状态值函数的折扣版本,然后减去旧状态的值。这样,你可以生成更新,这实际上会收敛到最优解。这种方法的一个变体实际上估计了动作值函数,然后被称为 SARSA。
q 学习。来自深度学习讲座的 CC BY 4.0 下的图片。
q 学习是一种脱离政策的方法。这是一种时间差分类型的方法,但它不需要关于环境动态的信息。这里的想法是,你循环并遵循从你的动作值函数中导出的策略。例如,您可以使用ε-贪婪型方法。然后,你使用策略中的动作来观察你的奖励和你的新状态。接下来,您使用前一个行动值加上某个加权因子,再乘以观察到的奖励,更新您的行动值函数,再乘以贴现行动,该贴现行动将从生成的状态减去前一个状态的行动值函数,得出您已经知道的最大行动值。所以这又是一种时间差异,你在这里用它来更新你的行动值函数。
使用通用函数逼近器的 q 学习。 CC 下的图片来自深度学习讲座的 4.0 。
好吧,如果你有通用函数逼近器,那么用权重和一些损失函数来参数化你的策略怎么样?这就是所谓的政策梯度。这种情况称为加强。所以,你用你的策略和权重生成一集。然后,你在你的剧集中从时间 0 前进到时间 t-1。如果你这样做,你实际上可以计算相对于重量的梯度。您使用这个渐变来更新您的权重。与我们之前在学习方法中看到的非常相似。你可以看到,这个在策略上使用梯度的想法,给了你一个如何更新权重的想法,也是一个学习率。我们现在离我们早期的机器学习想法已经很近了。
在这个深度学习讲座中,更多令人兴奋的事情即将到来。来自深度学习讲座的 CC BY 4.0 下的图片。
这就是为什么我们在下一个视频中谈论深度 Q 学习,这是一种强化学习的深度学习版本。所以,希望你喜欢这个视频。现在,您已经看到了如何实际确定最佳状态值和动作值函数的其他选项。这样,我们已经看到,有许多不同的想法不再需要关于如何产生未来状态和如何产生未来回报的确切知识。有了这些想法,你也可以进行强化学习,尤其是政策梯度的想法。我们已经看到,这与我们在这门课早些时候看到的机器学习和深度学习方法非常一致。我们将在下一个视频中讨论这个想法。非常感谢大家的收听,下期视频再见。拜拜。
对于今天的强化学习方法来说,Sonic 仍然是一个挑战。使用 gifify 创建的图像。来源: YouTube
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中获得文字记录,试试自动博客。
链接
链接到萨顿 2018 年草案中的强化学习,包括深度 Q 学习和 Alpha Go 细节
参考
1大卫·西尔弗、阿贾·黄、克里斯·J·马迪森等,“用深度神经网络和树搜索掌握围棋”。载于:自然 529.7587 (2016),第 484–489 页。
【2】大卫·西尔弗、朱利安·施利特维泽、卡伦·西蒙扬等人《在没有人类知识的情况下掌握围棋游戏》。载于:自然 550.7676 (2017),第 354 页。
【3】David Silver,Thomas Hubert,Julian Schrittwieser,等《用通用强化学习算法通过自玩掌握国际象棋和松木》。载于:arXiv 预印本 arXiv:1712.01815 (2017)。
[4] Volodymyr Mnih,Koray Kavukcuoglu,David Silver 等,“通过深度强化学习实现人类水平的控制”。载于:自然杂志 518.7540 (2015),第 529-533 页。
【5】马丁·穆勒。《电脑围棋》。摘自:人工智能 134.1 (2002),第 145-179 页。
6理查德·萨顿和安德鲁·g·巴尔托。强化学习导论。第一名。美国麻省剑桥:麻省理工学院出版社,1998 年。
强化学习—第 5 部分
FAU 讲座笔记关于深度学习
深度 Q 学习
FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座
这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是讲座视频&配套幻灯片的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。 自己试试吧!如果您发现错误,请告诉我们!
航行
突破很难学。使用 gifify 创建的图像。来源: YouTube
欢迎回到深度学习!今天,我们想谈谈深度强化学习。我有几张幻灯片给你们看。当然,我们希望建立在我们在强化学习中看到的概念之上,但我们今天谈论的是深度 Q 学习。
怎样才能学会玩雅达利游戏? CC 下的图片来自深度学习讲座的 4.0 。
一个非常著名的例子是通过深度强化学习的人类水平的控制。在[4]中,这是由 Google Deepmind 完成的。他们展示了一个能够玩雅达利游戏的神经网络。因此,这里的想法是使用深度网络直接学习动作值函数。输入基本上是来自游戏的三个连续的视频帧,这由深度网络处理。它会产生最佳的下一步行动。因此,现在的想法是使用这个深度强化框架来学习最佳的下一个控制器动作。他们在卷积层进行帧处理,然后在全连接层进行最终决策。
所用网络概述。 CC 下的图片来自深度学习讲座的 4.0 。
在这里,你可以看到建筑的主要思想。所以有这些卷积层和 ReLUs。这些处理器处理输入帧。然后,你进入完全连接的层,再进入完全连接的层。最后,你直接产生输出,你可以看到在 Atari 游戏中,这是一个非常有限的集合。所以你可以什么都不做,然后本质上有八个方向,有一个发射按钮,有八个方向加上发射按钮。这就是你能做的所有不同的事情。所以,这是一个有限的领域,你可以用它来训练你的系统。
成功的学习实际上需要更多。来自深度学习讲座的 CC BY 4.0 下的图片。
嗯,是直接应用 Q-learning 的深度网络。游戏的状态本质上是当前帧加上前三帧作为图像堆栈。所以,你有一个相当模糊的方法来整合记忆和状态。然后,您有 18 个与不同动作相关联的输出,每个输出估计给定输入的动作。你没有一个标签和一个成本函数,但是你可以根据未来回报的最大化来更新。游戏分数增加时奖励+1,游戏分数减少时奖励-1。否则就是零分。它们使用ε-贪婪策略,在训练期间ε减小到一个低值。他们使用 Q 学习的半梯度形式来更新网络权重 w ,并且再次使用小批量来累积权重更新。
目标网络的权重更新。 CC 下的图片来自深度学习讲座的 4.0 。
因此,他们有了这个目标网络,并使用以下规则对其进行更新(见幻灯片)。你可以看到,这与我们在之前的视频中看到的非常接近。同样,你有权重,你根据奖励更新它们。当然,现在的问题是,这个γ和最大 q 函数的选择又是权重的函数。所以,你现在有一个依赖于最大化的权重,你试图更新。所以,你的目标随着我们想要学习的重量同时改变。这实际上会导致你的体重摆动或分散。所以,这不是很好。为了解决这个问题,他们引入了第二个目标网络。在 C 步骤之后,他们通过将行动-价值网络的权重复制到一个复制网络中并保持固定来生成这一点。于是,你用目标网络的输出 q 条作为目标,稳定之前的最大化。你不使用 q hat,你正在尝试学习的函数,但是你使用 q bar,它是一种固定的版本,你用它来进行几次迭代。
经验回放有助于保持学习的正轨。来自深度学习讲座的 CC BY 4.0 下的图片。
他们使用的另一个技巧是体验回放。这里的想法是减少更新之间的相关性。因此,在对图像堆栈执行了一个下标 t 的操作并收到奖励后,您将它添加到重放内存中。你在这个重放记忆中积累经验,然后用从这个记忆中随机抽取的样本而不是最近的样本来更新网络。这样,你可以稳定下来,同时不要太专注于游戏中的某个特定情况。你试着记住游戏中所有不同的情况,这消除了对当前重量的依赖,增加了稳定性。我给你举个小例子。
240 小时的训练很有帮助。使用 gifify 创建的图像。来源: YouTube
所以,这是雅达利突破游戏,你可以看到,在开始时,代理人的表现不是很好。如果你反复训练它,你会发现这个游戏玩得更好。所以这个系统学习如何用球拍跟随球,然后它能够反映球。你可以看到,如果你一次又一次地迭代,你可以争辩说,在某些时候,强化学习系统也找出了游戏的弱点。特别是,如果你设法把球带到砖块后面,然后让他们在那里跳来跳去,你就可以得到很多分。它将被边界而不是球拍所反映,它将产生一个很大的分数。所以,这是一个声明,系统已经学会了一个好的策略,只踢左边的砖块。然后,它需要让球进入其他砖块后面的区域。
游戏快进 Lee Sedol vs. AlphaGo。使用 gifify 创建的图像。来源: YouTube
当然,我们需要在这个视频里说说 AlphaGo。我们想了解它实际上是如何实现的一些细节。你已经听说过这个了。所以是出自《用深度神经网络掌握围棋博弈》这篇论文。
围棋比国际象棋难多了。来自深度学习讲座的 CC BY 4.0 下的图片。
所以,我们已经讨论过,围棋比国际象棋更难,因为它有很多可能的走法。由于可能会出现大量可能的状态,所以想法是黑方与白方争夺对棋盘的控制权。它有简单的规则,但有非常多的可能的移动和情况。由于这个问题在数值上的高度复杂性,要达到人类玩家的表现被认为是多年以后的事。因此,我们可以蛮力下棋,但人们认为这是不可能的,直到我们有更快的计算机——快几个数量级的计算机。他们可以证明他们真的可以用这个系统打败人类围棋专家。所以,围棋是一个完美的信息游戏。没有隐藏信息,也没有机会。因此,理论上,我们可以构建一个完整的博弈树,并用最小-最大遍历它,以找到最好的移动。问题在于大量的法律诉讼。所以在国际象棋中,你大约有 35 个。在围棋中,你可以在游戏的每一步中走 250 种不同的棋。
2002 年,解决围棋问题被认为是几十年后的事情。 CC 下的图片来自深度学习讲座的 4.0 。
此外,游戏可能涉及许多步骤。所以大约有 150 人。这意味着穷举搜索是完全不可行的。当然,如果你有一个精确的评估函数,搜索树是可以被修剪的。对于国际象棋来说,如果你还记得深蓝,这已经非常复杂,并且是基于大量的人工输入。对于 2002 年的围棋,“永远找不到简单而合理的围棋评价。”是 2016 年和 2017 年最先进的油井;AlphaGo 击败了世界上最强的两名选手 Lee Sedol 和 Ke Kie。有一种方法可以解决这个博弈。
AlphaGo 使用了几种聪明的方法。来自深度学习讲座的 CC BY 4.0 下的图片。
这篇论文中有几个非常好的想法。它是由 Silver 等人开发的。它也是 Deepmind,并且是多种方法的结合。当然,他们使用深度神经网络。然后,他们使用蒙特卡罗树搜索,并结合监督学习和强化学习。与全树搜索相比,第一个改进是蒙特卡罗树搜索。他们使用网络来支持通过树的有效搜索。
蒙特卡罗树搜索综述。 CC 下的图片来自深度学习讲座的 4.0 。
那么,什么是蒙特卡罗树搜索?嗯,你通过寻找不同的未来可能的移动来扩展你的树,你寻找产生非常有价值的状态的移动。你将有价值的状态扩展到未来。然后,你还要看这些状态的值。所以你只查看几个有价值的状态,然后一遍又一遍地展开几个步骤。最后,您可以找到一种情况,其中您可能有一个更大的状态值。所以,你试着展望一下未来,跟随可能产生更高状态值的移动。
实际的蒙特卡罗树搜索算法。 CC 下的图片来自深度学习讲座的 4.0 。
因此,您从当前状态的根节点开始。然后,您迭代地这样做,直到您扩展搜索树以找到最佳的未来状态。算法是这样的:从根节点开始,用树策略遍历到一个叶节点。然后,展开并向当前叶添加一个或多个子节点,这些子节点可能具有有价值的状态。接下来,根据您的展开策略,从当前或子节点模拟带有动作的剧集。所以,你也需要一个政策来扩展这里。然后,您可以备份并通过树向后传播收到的奖励。这允许您找到具有较大状态值的未来状态。所以,你重复这个动作一段时间。最后,你停下来,根据累积的统计数据从根音符中选择动作。下一步,你必须根据你的对手实际采取的行动,用一个新的根音重新开始。
让 AlphaGo 运行起来的更多技巧。来自深度学习讲座的 CC BY 4.0 下的图片。
因此,树策略指导成功路径的使用程度和查看频率。这是一个典型的勘探/开采权衡。当然,这里的主要问题是,普通的蒙特卡罗树搜索对于围棋来说不够精确。AlphaGo 的想法是用神经网络来控制树的扩展,以找到有希望的动作,然后通过神经网络来改善值的估计。所以,在扩展和评估方面,这比搜索一棵树更有效,这意味着你最好放手。
在 AlphaGo 中我们实际上需要三个网络。 CC 下的图片来自深度学习讲座的 4.0 。
他们是如何使用这些深度神经网络的?他们有三个不同的网络。他们有一个策略网络,为扩展建议叶节点中的下一步移动。然后,他们有一个价值网络,查看当前的董事会情况,并计算基本上获胜的机会。最后,他们有一个部署策略网络来指导部署操作的选择。所有这些网络都是深度卷积网络,输入是当前棋盘位置和其他预先计算的特征。
这是政策网络。它有 13 个卷积层,围棋棋盘上的每个点有一个输出。然后,一个巨大的人类专家动作数据库,有 3000 万个。他们从监督学习开始,训练网络来预测人类专家游戏的下一步。然后,他们通过与旧版本的自我比赛,用强化学习来训练这个网络,并且他们会因为赢得比赛而获得奖励。当然,所有的版本都避免了相关性不稳定性。如果你看看训练时间,有三个星期在 50 个 GPU 上用于监督部分,一天用于强化学习。所以,实际上这里涉及了相当多的监督学习,而不是强化学习。
价值网络。来自深度学习讲座的 CC BY 4.0 下的图片。
这是价值网络。这与策略网络具有相同的架构,但是只有一个输出节点。这里的目标是预测赢得比赛的概率。他们再次在强化学习的自我游戏上训练,并对来自这些游戏的 3000 万个位置使用蒙特卡罗策略评估。在 50 个 GPU 上训练时间为一周。
政策推广网络。 CC 下的图片来自深度学习讲座的 4.0 。
然后,他们有了部署策略网络,可以在部署期间使用该网络来选择移动。当然,这里的问题是推理时间相对较长,解决方案是在数据子集上训练一个更简单的线性网络,以非常快速地提供动作。因此,与策略网络相比,这导致了大约 1000 倍的速度提升。因此,如果您使用这种推广政策网络,那么您的网络会更细,但速度会更快。所以,你可以多做模拟,多收集经验。所以,这就是为什么他们使用这个推广政策网络。
AlphaGo Zero 不再需要任何人类棋手。 CC 下的图片来自深度学习讲座的 4.0 。
现在,这里涉及了相当多的监督学习。那么,我们来看看 AlphaGo zero。现在,AlphaGo zero 已经不需要人类下棋了。所以,这里的想法是,然后你只玩强化学习和自我游戏。它具有更简单的蒙特卡罗树搜索,并且在蒙特卡罗树搜索中没有部署策略网络。同样,在自我游戏中,他们也引入了多任务学习。因此,政策和价值网络共享初始层。这就导致了3和扩展也能够玩国际象棋和 shogi。所以,并不是只有代码才能解决围棋。有了这个,你也可以在专家的水平下象棋和松木。好吧。这总结了我们在强化学习中所做的。当然,我们可以在这里看很多其他的东西。然而,没有足够的时间。
在这个深度学习讲座中,更多令人兴奋的事情即将到来。来自深度学习讲座的 CC BY 4.0 下的图片。
下一次深度学习,我们要讲的是连奖励都没有的算法。所以,完成无人监督的训练,我们也想学习如何从对手那里获益。我们会看到有一个非常酷的概念,叫做生成对抗网络,它能够生成各种不同的图像。另外,这是一个非常酷的概念,我们将在下一个视频中讨论,然后我们将研究执行图像处理任务的扩展。所以,我们越来越倾向于应用。
嗯,一些综合问题:什么是保单?什么是价值函数?解释开发与探索的困境,等等。如果你对强化学习感兴趣,我绝对推荐你看看理查德·萨顿的《强化学习》这本书。这真的是一本很棒的书,你会学到很多我们只能在这些视频中粗略了解的东西。所以,你可以更深入地了解强化学习的所有细节,以及深度强化学习。关于这一点,实际上还有很多要说的,但我们暂时只能停留在这个水平。嗯,我还给你带来了链接,我也把链接放到了视频描述中。所以请欣赏这本书,它非常好,当然,我们有很多进一步的参考。
非常感谢你们的聆听,我希望你们现在至少能理解一点强化学习和深度强化学习中发生的事情,以及执行游戏学习的主要思想。所以,非常感谢你观看这个视频,希望在下一个视频中见到你。拜拜。
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中获得文字记录,试试自动博客。
链接
链接到萨顿 2018 年草案中的强化学习,包括深度 Q 学习和 Alpha Go 细节
参考
1大卫·西尔弗、阿贾·黄、克里斯·J·马迪森等,“用深度神经网络和树搜索掌握围棋”。载于:自然 529.7587 (2016),第 484–489 页。
【2】大卫·西尔弗、朱利安·施利特维泽、卡伦·西蒙扬等人《在没有人类知识的情况下掌握围棋游戏》。载于:自然 550.7676 (2017),第 354 页。
【3】David Silver,Thomas Hubert,Julian Schrittwieser,等《用通用强化学习算法通过自玩掌握国际象棋和松木》。载于:arXiv 预印本 arXiv:1712.01815 (2017)。
[4] Volodymyr Mnih,Koray Kavukcuoglu,David Silver 等,“通过深度强化学习实现人类水平的控制”。载于:自然杂志 518.7540 (2015),第 529-533 页。
【5】马丁·穆勒。《电脑围棋》。摘自:人工智能 134.1 (2002),第 145-179 页。
6理查德·萨顿和安德鲁·g·巴尔托。强化学习导论。第一名。美国麻省剑桥:麻省理工学院出版社,1998 年。
强化学习:利用动态规划求解马尔可夫决策过程
#解决马尔可夫决策过程
前两个故事是关于理解 马尔可夫-决策过程 和 定义最优政策的贝尔曼方程和价值函数 。在这一篇中,我们将讨论这些马尔可夫决策过程是如何求解的。但在此之前,我们将定义解决马尔可夫决策过程的概念,然后,看看不同的动态规划算法,帮助我们解决它们。所以,在我们开始之前,让我们看看这个故事中我们要和谈些什么:
- 什么是 动态编程?
- 解决 马氏决策过程
- 什么是 政策评估?
- 动态编程 算法 1:策略迭代
- 修改 策略迭代
- 动态编程 算法 2:数值迭代
所以,给自己冲杯咖啡,保持清新,因为普通和非凡的区别就在于那一点点额外的东西。🤙
什么是动态编程?
动态编程很像分而治之的方法,将一个问题分解为子问题,但唯一的区别是,不是独立地解决它们(像在分而治之中),子问题的结果用于类似的子问题。动态编程的思想是你不需要解决一个你已经解决的问题。如果一个问题满足两个性质,则可以使用动态规划来解决该问题:
- 最优子结构:这意味着一个问题可以被分成子问题,如果我们找到这些子问题的最优解,那么我们可以使用这个最优解来找到整个问题的最优解。
- 重叠子问题:前面说过,如果一个问题有相似的子问题,就用动态规划。一个子问题的解决方案被保存,然后用于解决类似的子问题。
但是等等,马尔可夫决策过程有这两个性质吗?
对于第一个性质,我们有一个贝尔曼方程。 但是,如何?
回想一下,贝尔曼方程定义如下:
贝尔曼方程
记住贝尔曼方程所说的,一个状态的价值等于我们的代理人离开该状态得到的直接回报加上下一个状态的价值。所以,这个等式是分解的过程通过把一个状态分成子问题来寻找这个状态的价值函数。
其次,对于重叠子问题,我们有价值函数。 如何?
看,值函数已经存储了一个特定状态有多好,所以我们不需要一次又一次地重新计算那个状态的值。 例如,假设有两个 状态(s1和 s[2]),我们处于状态 s1,并且我们已经计算了状态 s[2]的值,因此当计算状态 s1的值时,我们将不会重新计算状态 s[2]的值。(s1的值依赖于状态 s[2])
求解马尔可夫决策过程的概念
当我们说要解决一个马尔可夫决策过程时,我们的意思是什么?
这意味着我们要找到满足贝尔曼方程的值函数。一旦我们找到了最优值函数,那么我们就可以用它来寻找最优策略。
这个过程分为两个部分:
- 预测 :假设我们有一个定义为(S,A,P,R,gamma)的马尔可夫决策过程,给定某个策略π。我们在预测中的工作是找到价值函数。我们通过使用贝尔曼期望方程评估一个策略来找到价值函数。
- 控制 :这个过程涉及到优化值函数,我们在预测过程中计算。我们为我们的 马尔可夫决策过程 找到最优值函数和最优策略。
说到这里,我们来谈谈我们的第一个构建模块,即政策评估。
政策评估
***同步备份:*这意味着我们将在计算状态值的马尔可夫决策过程中考虑每个状态。
政策评估意味着我们的代理人通过遵循特定的政策π将获得多少奖励。 但是我们如何评价一个政策π?
我们使用贝尔曼期望方程来评估给定的策略π。回想一下,贝尔曼期望方程告诉我们的代理人在遵循政策π的情况下将获得多少报酬,它被定义为:
贝尔曼期望方程
现在,为了评估一个策略,我们要以迭代的方式使用这个等式。也就是说,我们将通过备份前一次迭代中当前状态的值来计算下一个状态的值。让我们通过一个例子来理解这一点:
请看下面的备份图:
计算根节点值函数的备份图
我们知道,根节点[s]的值是由我们采取行动[a]得到的回报加上状态[s']的值给出的。现在,我们正在做的是,我们在动态规划中以迭代的方式使用贝尔曼期望方程。也就是说,当我们计算状态 s 的值时,我们将使用来自前一次迭代的树叶值(这里是状态[s'])来计算状态[s]的值。这在每次迭代中都会发生。现在,对于第二次迭代,我们将使用上一次迭代中计算的状态值 v [k+1]来计算下一个状态的值,即 v [k+2]。
注意:最初我们开始把我们每个状态的值函数初始化为零。
让我们借助网格世界来理解这一点:
小网格世界
在这个网格世界中,我们每进行一次转换(我们采取的行动)都会得到-1 的奖励。我们可以采取的行动是上下左右。我们的代理遵循一些随机策略π,每个动作的权重-年龄为 0.25。
现在,让我们用这个网格世界来跟踪策略评估:
如前所述,我们从将每个状态的值初始化为零开始:
每个状态的起始值为零
然后在下一次迭代中:我们将使用如上所述的贝尔曼期望方程作为迭代方式,我们最终得到每个状态值函数 be -1(回想一下,-1 是我们采取每项行动得到的奖励):
使用贝尔曼期望方程的首次迭代
让我们以用红色突出显示的状态为例:首先,从这个状态到另一个状态的回报是-1。现在,前一次迭代中的下一个状态的值,被我们初始化为 0。所以,应用贝尔曼期望方程,我们得到这个状态的值为-1。因为我们使用同步备份,所以我们要考虑代理可以进入的每个状态,也就是这里的四个状态。
让我们看看下一次迭代会发生什么:
状态的第二次迭代值
再一次,让我们看看状态的值是-2(红色):所以,我们也在做同样的事情。首先,我们会因为离开状态而得到-1 的奖励,然后从上一次迭代中取下一个状态的值(也就是-1),那么这个状态的值就变成了-2。因为它是同步备份,所以我们对代理可以到达的每个状态都进行同步备份,并对其进行规范化,这样我们就可以得到该状态的值为-2。
我们来说说终端状态旁边的状态:
第二次迭代时的终端状态
让我们来看看红色的状态:因此,我们也可以采取四种行动,但唯一的区别是,终端状态的值始终为 0。因此,从此状态开始的每隔一步,都会产生-2 的值,但在终止状态,会产生-1 的值。将它们相加得到-7,然后用 4 归一化(因为这是同步备份),得到该状态的值为-1.75。
现在,如果我们继续迭代过程,我们最终得到的状态值如下:
迭代次数第三次
迭代次数十次
迭代直到收敛到最优值函数
在最后一次迭代中,我们得到了每个状态的最优值函数(我们稍后将讨论收敛)。
我们的迭代评估过程到此结束。现在, 如果我们贪婪地对待这些国家的价值观会怎么样?
表现贪婪意味着在我们的代理可以达到的所有状态中,它会选择一个比其他状态价值更高的状态。
事实证明,如果我们对国家的价值开始变得贪婪,我们最终会得到一个最优的政策。
现在,记住这两点,让我们看看我们的第一个动态编程算法,即策略迭代。
策略迭代
该算法将前面描述的过程分为两个部分。
首先,我们将使用前一节中描述的贝尔曼期望方程来评估一个策略,比如说π,然后我们将对这个评估值函数执行贪婪操作,以找到一个最优策略。我们将重复这个过程,直到我们得到真正的价值函数。
策略迭代的思想分为两步:
- 政策评估(如前所述)
价值函数计算
- 对评估值函数表现出贪婪,从而产生优于前一个策略的策略
对这个功能表现出贪婪
我们迭代这两个过程,直到它收敛到最优值函数和最优策略。
当评估一个策略后(使用贝尔曼期望方程以迭代的方式计算价值函数),我们对该价值函数表现出贪婪,因为我们表现出贪婪,这使得我们的策略具有确定性。
让我们更深入地理解这一点:(在该图中,向上的箭头表示政策评估,向下的箭头表示我们对价值函数贪婪)
政策迭代思想
该图传达的意思是,我们从每个状态的随机值(带零)和一个随机策略开始,然后我们使用之前描述的贝尔曼期望方程来评估该策略,然后对值函数采取贪婪的行为,这为我们提供了一个新策略。然后我们再次评估这个新政策,然后再次对新的价值函数表现出贪婪。我们继续这个过程,直到我们找到最优值函数和我们的马尔可夫决策过程的最优策略。
现在,让我们更深入地探讨一下如何改进我们的政策..
行动贪婪意味着选择一个行动,比如说在一个特定的状态下能给我们带来最大价值的 a。我们可以这样定义:
贪婪的政策
回想一下,qπ (s,a)告诉我们在状态 s 中采取行动 an 有多好,或者在状态 s 中采取行动 an 将获得多少价值,对 qπ (s,a)取 arg-max 意味着我们选择状态 s 中的行动,使 q 值[qπ (s,a)]最大化或产生最大 q 值[qπ (s,a)]。
那么,这是否使我们的政策更好呢?
所以,我们在问,采取贪婪的行动[π']是否比一直遵循我们的政策π更好。是,先迈出贪婪的第一步【π’(s)】,然后跟随政策π,比一直只跟随政策π要好或相等。
这可以表示为:
这里左边先走我们贪婪的一步[π'(s)]然后跟随我们的政策π。这相当于采取可能的最佳行动(具有最大 q 值)。右手边只是自始至终在遵循一个政策π,等于说一个国家的价值函数。现在, 你可能在想为什么它比一直遵循π政策要好或者等于π?
看,当我们在下一步采取贪婪步骤(π’(s))时,我们选择了可以从状态 s 采取的最佳行动。现在,在右侧,我们没有采取任何贪婪步骤或确定性步骤,因此我们的代理可能会选择最佳行动,或者可能最终选择产生的价值低于贪婪行动的行动。
上述想法可以应用到每一步:
政策改进定理
所以,这个策略每走一步都会变得更好,唯一停止的时候是π成为我们的最优策略的时候。如果改进停止,则贪婪动作值等于状态的当前值:
改进停止
因此,如果价值函数 Vπ (s)等于贪婪价值函数 qπ (s,π'(s)),则满足贝尔曼最优方程:
贝尔曼最优方程
我们已经在第 2 部分详细讨论了上面的等式。所以如果这个满足,那么我们的策略π就是最优策略。
所以,这都是关于政策迭代。首先,我们使用贝尔曼期望方程来评估我们的策略,然后对这个评估的值函数采取贪婪的行为,我们已经证明它在迭代上改进了我们的策略。
修改策略迭代
这是基于我们是否需要等到我们的政策评估需要收敛于 Vπ的想法。 我们是不是应该早点收手?
如果你记得在政策评估中,我们首先评估政策,然后表现出对它贪婪的尊重。事实证明,经过几次迭代之后,我们已经实现了我们的最优策略。我们不需要等待我们的价值函数收敛。因此,我们引入了提前停止条件。
知道何时停止的一个方法是,如果我们的价值函数在评估过程中更新了很少的值。所以,我们可以说,如果价值函数的更新量很小,比如说小于一个ε,那么我们可以停止这个过程。
另一种方法是我们可以在 k 次迭代后手动停止策略评估过程。
现在,我们来看另一种动态规划算法:值迭代。
最优性原理 :
在我们深入研究之前,让我们重新定义一下最优行为的定义。因此,最佳策略可以细分为两个部分:
最佳的第一步,比如说
然后遵循下一个状态的最优策略,比如说
如果在我们采取了一个最优的步骤,比如行动 a 之后,一个策略的行为是最优的,那么这个策略就是最优的。
价值迭代
在策略迭代中,我们看到,首先,我们评估一个策略,即找到价值函数,然后对它表现出贪婪,以构造一个新的策略。但是,在值迭代中,我们并不为每个中间值函数计算策略。一旦我们找到了最优值函数,我们就可以从最终的最优值函数中计算出最优策略。
值迭代是策略迭代的特例。当策略评估过程在一个步骤后停止时。
数值迭代采用贝尔曼最优方程。我们从某个随机值函数(比如零)开始,然后使用贝尔曼最优方程迭代这个过程。也就是说,我们通过在贝尔曼最优方程中插入先前迭代的值来计算状态的新值函数。我们迭代这个过程,直到它收敛到最优值函数,然后从这个最优值函数计算最优策略。
我们以迭代的方式使用贝尔曼最优方程进行数值迭代。这可以表示为:
值迭代更新规则
我们用一个例子来理解一下:
价值迭代的备份图
因为我们使用同步备份,所以我们的马尔可夫决策过程中的每个状态都是根。就像之前我们第一次使用贝尔曼最优方程计算根的值一样[在之前的博客中详细讨论过]。然后在迭代 k+1,通过插入来自前一次迭代 V [k (s')]的值来更新状态 s 的值。因此,我们以迭代的方式使用贝尔曼最优方程。这样做,我们的价值函数收敛到最优价值函数。
这可以表示为:
贝尔曼最优方程
所以,这都是关于价值迭代。
同步动态规划算法
所以,总结一下我们之前看到的,这是大卫·西尔弗讲座的摘要:
算法概述
太棒了!🤩
至此,我们结束了对马尔可夫决策过程的讨论。用了三篇长文总结。在下一篇文章中,我们将讨论无模型学习(独立于模型动力学),如蒙特卡罗学习和我最喜欢的时间差异学习。
希望这个故事能增加你对马尔可夫决策过程的理解。如果你喜欢它,请鼓掌让我知道👏。我对评论区的任何讨论都持开放态度。我很乐意在# Instagram 上与你联系。
关于马尔可夫决策过程的第 1 部分、第 2 部分和第 3 部分:
- 强化学习:马尔可夫决策过程(第一部分)
- 强化学习:贝尔曼方程与最优性(下)
- 强化学习:用动态规划求解马尔可夫决策过程(第三部分)
- 强化学习:蒙特卡罗学习
参考资料:
待深
强化学习与捕食者猎物球游戏可视化
米卡·鲍梅斯特在 Unsplash 上的照片
这是上一篇文章的后续,在这篇文章中,我们看了一个简单的强化学习(RL)游戏,其中一个绿色的球学会在 200 步内到达画布中心的一个小圆圈。我们编写了一个 Q-learning 算法,并使用基于 Tkinter 的 GUI 将其可视化。
我们现在给绿球一个稍微复杂一点的挑战。这一次的目标是学会在 200 步内到达中心,但现在有另一个球,一个红色的球,绿色的球必须避开。红球从圆圈附近开始,随机移动。如果绿色和红色的球相撞,游戏结束。
绿色球学会到达圆
红色的球就像一个喝醉了的掠食者,四处乱跑,希望抓住绿色的球。我当然意识到故事中喝醉的部分使我们的 RL 实现变得更容易些:)要记住的关键是绿球只是学习如何通过不碰到红球来避开它。然而,如果碰巧红球接住了绿球,绿球也无能为力,游戏就结束了。
所以现在绿球必须同时学习两件事。它必须明白到达中心是最有意义的事情,它必须明白如何远离红球。
正如你可能已经想到的,这个 RL 的状态空间比单个绿球场景增长了 2 倍(上图)。最佳行动的决定(可能采取的步骤)不仅取决于绿球本身的位置,还取决于红球的位置。动作空间保持不变,因为绿球可以走的步数没有改变。
好了,让我们看看如何修改上一篇文章中的代码来实现这一点。
可能的步骤现在被声明为
mov_list = [-40,-20,20,40]
而不是我们之前用过的[-20,-10,10,20]。通过加倍步长,我们将单个球的搜索空间缩小了 4 倍。所以对于 2 球系统,我们的搜索空间小了 16 倍。即使在这之后,我们的搜索空间也是 202500,而不是之前的 1800。
然后我们介绍球碰撞的检查和碰撞的惩罚。
# Check if green ball hit the red ballif (pos_x1 == pos_x2) and (pos_y1 == pos_y2):
collision = 1
reward = -200
print("green collision", pos_x1, pos_y1, pos_x2, pos_y2)
green_collision_count += 1
到达圆圈的奖励是 100。我最初将冲突的惩罚设置为-25。没有任何学习,碰撞发生了 40%次。大约 20%是因为绿球踩到了红球(GBC,绿球碰撞),而另外 20%是红球撞到了绿球(RBC)。对我们来说,绿色球击中红色球是重要的统计数据。即使在 100,000 场比赛后,gbc 仍约为 15%。为什么避免碰撞的学习如此缓慢?
我很快发现,绿色球的动机完全是因为它追求到达中心,这是因为与碰撞惩罚相比,奖励要高得多。啊哈!GBCs 从 20 下降到 15%的唯一原因是因为球快速到达中心,而不是随机移动,因此随机击中红球的机会较少。所以在下一步中,我们将冲突的惩罚设置为-200。
对于红细胞,没有处罚规定。随着新的罚分,GBCs 在 20,000 场比赛内降至 0% 。它可能会更快完成,但我只在 20k 步后检查。我很乐观,但没有这么乐观!
我们看到了如何将简单的单球问题扩展到双球问题,从而大大增加了算法的复杂性。大多数真实生活场景要复杂得多,Q 表方法不再实用。
在另一篇文章中,我们将尝试使用 DQN 来实现这个游戏。
使用 Python 进行深度强化学习|第 1 部分|创建环境
左 Gif:游戏规则说明| |右 Gif:一个人玩的游戏
在本系列教程中,我们将介绍构建一个能够玩游戏的专家强化学习(RL)代理的每一个步骤。
本系列分为三个部分:
- 第一部分:游戏环境的设计和搭建。在这一部分中,我们将构建一个游戏环境并对其进行定制,以使 RL 代理能够在其上进行训练。
- 第二部分 :构建并训练深度 Q 神经网络(DQN)。在这一部分,我们定义和建立 DQN 的不同层次,并训练它。
[## 使用 Python 的深度强化学习|第 2 部分|使用深度 Q 创建和训练 RL 代理…
在第一部分,我们经历了制作游戏环境,并逐行解释。在这一部分,我们是…
towardsdatascience.com](/deep-reinforcement-learning-with-python-part-2-creating-training-the-rl-agent-using-deep-q-d8216e59cf31)
- 第三部分 :测试,玩游戏。
我们也可以尝试制作另一个简单的游戏环境,并使用 Q-Learning 来创建一个可以玩这个简单游戏的代理。
动机:
激励我开始这个系列的视频
有一次我在 YouTube 的兔子洞里,这个视频被推荐给我,它是关于人类婴儿的自我意识,看完视频后,一个类似的问题出现在我的脑海里*“我能开发一个足够聪明的智能代理,它能感知自己的身体,并有能力改变它的特征来完成某项任务吗?”*
这个系列是我回答这个问题的方式。
设计环境:
对于这种环境,我们希望代理人发展对其身体的感觉,以及如何改变其身体特征以避免输掉游戏。
第一:环境的要素:
环境
1- 字段包含所有其他元素。我们在代码中用名为“Field”的类来表示它,如下所示:
字段属性:
- 宽度【int】**:**字段的宽度(不以像素为单位)
- height (int:字段的高度(不以像素为单位)
- 体 (np.array) : 保存游戏元素(玩家和墙壁)的数组表示。这个数组被传递给 DQN ,也用于使用 pygame 绘制界面。
字段方法:
- update_field (自己、墙壁、玩家) :更新字段。
2-墙壁:
那堵墙
墙壁属性:
穿墙方法:
- create _ hole(self):在墙上创建一个宽度= self 的洞。孔 _ 宽。
- move (self):垂直移动墙壁(每次调用时,墙壁向下移动 n 步(n = self.speed))
3-玩家:
玩家属性:
玩家方法:
- 移动 (自身,领域,方向= 0):移动玩家:
-方向= 0 →不变
-方向= 1 →向左
-方向= 2 →向右
- change _ width(self,action = 0):
action = 0 →无变化
action = 3 →缩小一个单位
action = 4 →加宽一个单位
环境类:
这个类促进了环境和代理之间的通信,它被设计成与一个 RL 代理或一个人类玩家通信。
RL 代理所需的主要组件:
1- 环境 _ 形状属性:由 DQN 用来设置输入层的形状。
2- ACTION_SPACE 属性:由 DQN 用来设置输出层的形状。
3- 惩罚和奖励:设置惩罚和奖励的值,用来训练代理(我们用这些值来告诉代理它之前的行为是好是坏)。
4- 重置 方法:重置环境。
5- 步骤 方法:以一个动作为自变量,返回 **下一个状态,奖励,**一个名为 game_over 的布尔变量,用来告诉我们游戏是否结束(玩家输了)。
很明显,这个环境并没有什么不同,它包含了所有需要的组件甚至更多。
环境属性:
环境方法:
- _ _ init _ _(self):通过初始化一些属性,调用 reset 方法来初始化环境。
- 重置 (自身) :重置环境,重置后返回游戏场状态。
- print_text (self,WINDOW = None,text_cords = (0,0),center = False,text = ",color = (0,0,0),size = 32):打印给定 pygame.display (WINDOW)中具有给定特征的文本。
+步 (自我,行动):
1-调用玩家的 move 方法来移动玩家。
2-调用播放器的 change_width 方法移动播放器。
3-将墙移动一步。
4-更新字段。
5-检查玩家是否成功通过了一堵墙。如果是这样,给予玩家奖励并增加其耐力。
6-检查三个失败的条件:如果这三个条件中至少有一个满足,玩家就会输掉游戏。
当玩家输了,返回的 奖励 的值将等于惩罚,游戏状态的指示器( game_over )由假变真。
7-检查当前墙是否触及场地底部,当发生这种情况时,超出范围的墙将被新墙取代。
8-返回 下 _ 状态 正常化, 奖励 , 游戏 _ 结束
+ render(自身,窗口=无,人类=假):
论据:
- 窗口 (pygame.display):游戏将要渲染的 pygame.display。
逐行渲染 方法解释:
1-检查玩家是否是人类。如果是,获取按下的键并将其转换为相应的动作(例如:如果按下了右箭头,则设置 action = 2,这意味着向右移动上一步的玩家),然后调用 步骤 方法来执行选择的动作。
2-更新区域,然后开始将墙壁和玩家画成方块。
3-打印分数和球员的耐力。
4-最后,更新显示以显示渲染的屏幕。
最后:把它们放在一起
现在我们将使用我们解释过的所有东西来玩这个游戏:
以下代码重复游戏,直到玩家通过获得高于或等于 winning_score、 的分数获胜或退出游戏。
你可以在这里得到完整的代码。
** [## 使用 Python 的深度强化学习|第 2 部分|使用深度 Q 创建和训练 RL 代理…
在第一部分,我们经历了制作游戏环境,并逐行解释。在这一部分,我们是…
towardsdatascience.com](/deep-reinforcement-learning-with-python-part-2-creating-training-the-rl-agent-using-deep-q-d8216e59cf31) [## 使用 Python 进行深度强化学习|第 3 部分|使用 Tensorboard 分析训练好的模型
在前面的部分中:
towardsdatascience.com](/deep-reinforcement-learning-with-python-part-3-using-tensorboard-to-analyse-trained-models-606c214c14c7)
你可以在推特上关注我 @ModMaamari
您可能还喜欢:
- 深度神经网络用于回归问题
- AI 生成泰勒斯威夫特的歌词
- 用 Python 介绍随机森林算法
- 带 TensorFlow APIs 的机器学习速成班汇总
- 如何用 Tensorflow 和 Keras 制作一个 CNN?
- 如何选择最好的机器学习模型?**
使用张量流代理的强化学习—教程
用这个简单的教程试试 TF-Agents for RL,它以 Google colab 笔记本的形式发布,所以你可以直接从你的浏览器上运行它。
几周前,我写了一篇文章,列举了可以用来在项目中实现强化学习(RL)的不同框架,展示了每个框架的盛衰,并想知道是否有任何一个框架会在某个时候统治所有框架。从那以后,我开始知道了 TF Agents ,这是一个基于 TensorFlow 的 RL 库,并得到了其社区的全力支持(注意,TF Agents 不是 Google 的官方产品,但它是作为 Github 上的官方 TensorFlow 帐户的存储库发布的)。
我目前正在一个项目中使用 TF 代理,由于它的良好文档,包括教程,开始使用它很容易。它定期更新,有许多贡献者,这使我认为我们有可能在不久的将来看到 TF 代理作为实现 RL 的标准框架。正因为如此,我决定写这篇文章给你一个快速的介绍,这样你也可以从这个库受益。我已经发布了这里使用的所有代码,作为一个 Google colab 笔记本,所以你可以很容易地在线运行它。
你可以在这里找到 Github 的所有代码和文档。你不需要克隆他们的库,但是有官方的 Github 作为参考总是有用的。我实现了下面的例子,部分遵循他们的教程(1_dqn_tutorial ),但我进一步简化了它,并在本文中用它来玩 Atari 游戏。让我们动手吧。
安装 TF 代理和依赖项
如前所述,TF-Agents 运行在 TensorFlow 上,更具体地说是 TensorFlow 2.2.0。此外,如果您还没有以下软件包,您需要安装它们:
pip install tensorflow==2.2.0
pip install tf-agents
为 CartPole 实现 DQN 代理
我们将实现一个 DQN 代理( Mnih et al. 2015 ),并将其用于经典控制问题 CartPole。如果你想解决一些更令人兴奋的事情,比如说,一个 Atari 游戏,你只需要从所有可用的 OpenAI 环境中选择一个你想要的环境名。
我们从所有必要的进口开始。正如你在下面看到的,我们从 TF-Agents 实现了相当多的对象。这些都是我们可以为我们的实现定制和切换的东西。
from __future__ import absolute_import, division, print_functionimport base64
import IPython
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tffrom tf_agents.agents.dqn import dqn_agent
from tf_agents.drivers import dynamic_step_driver
from tf_agents.environments import suite_gym
from tf_agents.environments import tf_py_environment
from tf_agents.eval import metric_utils
from tf_agents.metrics import tf_metrics
from tf_agents.networks import q_network
from tf_agents.replay_buffers import tf_uniform_replay_buffer
from tf_agents.trajectories import trajectory
from tf_agents.utils import common
环境
OpenAI 健身房的翻筋斗环境[GIF from 积谷康/RL-翻筋斗。]
现在,我们开始创造我们的环境。在 CartPole 中,我们有一个顶部有一根杆子的推车,代理的任务是学习保持杆子,左右移动推车。请注意,我们将使用已经包含在 TF-Agents 中的 suite_gym 中的 e 环境,这是 OpenAI Gym 环境的一个稍微定制(并针对其与 TF-Agents 的使用进行了改进)的版本(如果您感兴趣,可以查看与 OpenAI 的实现这里的差异)。我们还将为我们的环境使用一个名为 TFPyEnvironment 的包装器,它将用于状态观察、操作和奖励的 numpy 数组转换为 TensorFlow 张量。在处理张量流模型(即神经网络)时,我们使用张量,因此通过使用这个包装器,我们可以节省一些转换这些数据所需的工作。
env = suite_gym.load('CartPole-v1')
env = tf_py_environment.TFPyEnvironment(env)
代理人
TF 中有不同的药剂——我们可以使用的药剂: DQN 、增援、 DDPG 、 TD3 、 PPO 和 SAC 。如上所述,我们将使用 DQN。代理的一个主要参数是它的 Q(神经)网络,它将用于计算每一步中动作的 Q 值。q_network 有两个强制参数:定义观察形状和动作形状的 input_tensor_spec 和 action_spec。我们可以从我们的环境中得到这一点,因此我们将我们的 q_network 定义如下:
q_net = q_network.QNetwork(env.observation_spec(),
env.action_spec())
正如你在这里看到的,我们可以为我们的 q_network 定制更多的参数,但是现在,我们将使用默认的参数。代理还需要一个优化器来查找 q_network 参数的值。让我们保持经典,用亚当。
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=0.001)
最后,我们用以下参数定义并初始化我们的代理:
- time_step_spec,它是我们从环境中获得的,定义了我们的时间步长是如何定义的。
- action_spec,与 q_network 相同。
- 我们之前创建的 Q 网。
- 我们之前创建的优化器。
- TD 误差损失函数,类似于神经网络中的损失函数。
- 列车步数计数器,这只是一个 0 阶张量(也称为标量),它将计算我们在环境中的步数。
train_step_counter = tf.Variable(0)agent = dqn_agent.DqnAgent(env.time_step_spec(),
env.action_spec(),
q_network=q_net,
optimizer=optimizer,
td_errors_loss_fn=
common.element_wise_squared_loss,
train_step_counter=train_step_counter)agent.initialize()
辅助方法:平均累积回报和收集数据
我们还需要一些辅助方法。第一个将在环境中迭代若干集,应用策略来选择要遵循的操作,并返回这些集中的平均累积奖励。这将有助于评估我们的代理了解到的策略。下面,我们也在我们的环境中尝试该方法 10 集。
def compute_avg_return(environment, policy, num_episodes=10):
total_return = 0.0
for _ in range(num_episodes):
time_step = environment.reset()
episode_return = 0.0 while not time_step.is_last():
action_step = policy.action(time_step)
time_step = environment.step(action_step.action)
episode_return += time_step.reward
total_return += episode_return avg_return = total_return / num_episodes
return avg_return.numpy()[0]# Evaluate the agent's policy once before training.
avg_return = compute_avg_return(env, agent.policy, 5)
returns = [avg_return]
我们还将在培训我们的代理时实现一种收集数据的方法。DQN 的突破之一是经验回放,我们将代理人的经验(状态、动作、奖励)存储起来,用它在每一步批量训练 Q 网络。这通过使学习更快和更稳定来改进学习。为了做到这一点,TF-Agents 包含了 TFUniformReplayBuffer 对象,它存储了这些经验以便以后重用,所以我们首先创建这个我们以后会用到的对象。
在这种方法中,我们采用一个环境、一个策略和一个缓冲区,采用由它的状态观察和奖励形成的当前时间步长、策略选择的动作以及下一个时间步长。然后,我们将它存储在重放缓冲区中。注意,重放缓冲区存储了一个名为 Trajectory 的对象,所以我们用前面命名的元素创建了这个对象,然后使用 add_batch 方法将它保存到缓冲区。
replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
data_spec=agent.collect_data_spec,
batch_size=env.batch_size,
max_length=100000)def collect_step(environment, policy, buffer):
time_step = environment.current_time_step()
action_step = policy.action(time_step)
next_time_step = environment.step(action_step.action)
traj = trajectory.from_transition(time_step,
action_step,
next_time_step)# Add trajectory to the replay buffer
buffer.add_batch(traj)
列车代理
我们终于可以训练我们的特工了。我们定义了我们在每一次迭代中的步数,在这个步数之后,我们将在每一次迭代中训练我们的代理,修改它的策略。现在让我们每次迭代只使用一步。我们还定义了我们的 Q 网络将被训练的批量大小和一个迭代器,以便我们迭代代理的经验。
然后,我们将为缓冲器收集一些经验,并从常见的 RL 环路开始。通过对环境采取行动、培训政策和重复来获得经验。我们另外打印损失,并分别每 200 和 1000 步评估代理的性能。
collect_steps_per_iteration = 1
batch_size = 64
dataset = replay_buffer.as_dataset(num_parallel_calls=3,
sample_batch_size=batch_size,
num_steps=2).prefetch(3)
iterator = iter(dataset)
num_iterations = 20000
env.reset()for _ in range(batch_size):
collect_step(env, agent.policy, replay_buffer)for _ in range(num_iterations):
# Collect a few steps using collect_policy and save to the replay buffer.
for _ in range(collect_steps_per_iteration):
collect_step(env, agent.collect_policy, replay_buffer) # Sample a batch of data from the buffer and update the agent's network.
experience, unused_info = next(iterator)
train_loss = agent.train(experience).loss step = agent.train_step_counter.numpy() # Print loss every 200 steps.
if step % 200 == 0:
print('step = {0}: loss = {1}'.format(step, train_loss)) # Evaluate agent's performance every 1000 steps.
if step % 1000 == 0:
avg_return = compute_avg_return(env, agent.policy, 5)
print('step = {0}: Average Return = {1}'.format(step, avg_return))
returns.append(avg_return)
情节
我们现在可以画出当我们训练代理人时,累积的平均回报是如何变化的。为此,我们将使用 matplotlib 制作一个非常简单的绘图。
iterations = range(0, num_iterations + 1, 1000)
plt.plot(iterations, returns)
plt.ylabel('Average Return')
plt.xlabel('Iterations')
《DQN 特工》5 集的平均回报率。随着代理变得更有经验,您可以看到性能是如何随着时间的推移而提高的。
完全码
我已经把本文中的所有代码作为 Google Colab 笔记本进行了分享。你可以直接运行所有代码,如果你想改变它,你必须把它保存在你自己的 Google drive 账户上,然后你可以做任何你想做的事情。如果你愿意,你也可以下载它在你的本地计算机上运行。
从这里去哪里
- 你可以跟随 Github 上 TF-Agents 库中的教程
- 如果你想查看 RL 的其他好框架,你可以在这里看到我以前的帖子:
从头开始编程你自己的强化学习实现可能会有很多工作,但是你不需要做…
towardsdatascience.com](/5-frameworks-for-reinforcement-learning-on-python-1447fede2f18)
- 你也可以在我前段时间写的另一篇文章的中查看其他可以尝试 TF-Agents(或者任何你选择的 RL 算法)的环境。
老规矩,感谢阅读!请在回复中告诉我你对 TF-Agents 的看法,如果你有任何问题或发现任何问题,也请告诉我🐛在代码中。
重塑办公室之外的工作场所
如何在家中舒适地高效工作
佩吉·科迪在 Unsplash 上拍摄的照片
在过去的几十年里,技术承诺将我们从工作场所中解放出来,并使我们能够在任何地方工作。然而,这从未成为现实,因为企业不愿放松对员工的控制。然而,疫情的崛起让雇主别无选择。这立即成为一个生死存亡的问题,不适应的公司面临倒闭的风险。
幸运的是,我们生活在一个科技发达的世界,将工作转移到网上相当容易。第一个也是最明显的要求是良好的互联网连接,因为这将成为我们所有数字服务的网关。考虑到西方国家平均有 85%的家庭宽带普及率,这一要求在西方国家不成问题。在其他国家,有各种技术提供了替代方案,如通过手机访问互联网,或通过谷歌的 Loon 气球动力互联网获得直播链接,为偏远地区提供服务。第二个基本要求是能够连接互联网的数字设备,如笔记本电脑或平板电脑。
一旦满足了这两个要求,现在就该转向必要的应用程序了。这些应用程序大多数都是免费的,可以通过浏览器访问,所以它们倾向于独立于硬件。一个人所要做的就是去他们的网站并使用该应用程序。以下是需要开始使用的应用程序列表。
- 一个在线日历对于安排和组织会议是必不可少的。它可以从位于任何地方的任何设备访问。
- 与同事或客户的快速聊天可以通过电子邮件或各种消息应用程序进行,如 WhatsApp、Messenger、Slack 和无数其他应用程序。
- 对于更长时间的会议,人们可能需要一个视频会议应用程序,如 Skype 或 Zoom。其中大多数是免费的,允许多人在一个虚拟的房间里会面。
- 为了执行复杂的项目,像 Trello 这样的应用程序通过将任务细分为子任务并分配给不同的团队成员来帮助人们管理任务。分配给特定任务的最后期限会让人们受到约束。
- 与不同地点和时区的人一起工作可能会很棘手。正因为如此,像谷歌的 G Suite 和微软的 Office 365 这样的工具帮助团队成员同时协作处理各种文档。这些套件支持最流行的生产力应用程序,如 Word、Excel、Powerpoint 或它们的变体(100%兼容)。他们还为用户提供云存储,从而确保文件安全地保存在远程位置。
- 在当今快速发展的世界中,跟上新的概念是非常重要的。像 Coursera、Udemy 和 edX 这样的网站提供免费在线课程,其中一些课程得到了顶尖大学的认证。他们允许员工在自己舒适的家里用自己的时间学习,从而让他们有更好的职业前景。
- 最后,由于在家里可能仍然需要访问办公室电脑,Chrome 远程桌面帮助用户从任何设备安全地访问他们的机器。
有了所有这些应用程序,您马上就可以开始工作了。经过几次尝试后,人们开始意识到,远程工作最终与在办公室工作没有太大区别。人们仍然可以组织一对一会议、小组会议、共享文档或寻求建议。
杰佛逊·桑托斯在 Unsplash 上的照片
然而,远程工作也带来了以下一些缺陷:
- 办公时间有了全新的含义。人们可以在白天和晚上的任何时间工作,因为办公室现在只有一米远。过度的自由当然是不健康的,因为人们下班后需要拔掉电源。因此,设定时间限制是至关重要的,这样可以避免过度工作并最终耗尽精力。
- 在家工作可能会感到孤独和无聊,因为在网上组织办公室笑话很有挑战性。尽管这些东西不会直接提高组织的生产率,但它们有助于员工团结、建立信任,并更好地合作。因此,通过聊天或虚拟活动保持一个开放的渠道是至关重要的,在虚拟活动中,员工可以分享有趣的东西,如他们的生活片段、模因、有趣的视频或其他社交内容。
- 中介沟通不一定是自然而然的。许多人在视频会议期间感到不舒服,因为它往往会淡化人与人之间的互动暗示。人们说话时通常会看着某人的眼睛,但在视频会议中不会发生这种情况,因为他们正在看着摄像机。其他人也倾向于打手势,但这在视频通话中减少了几次。所以有时候,视频通话对人们来说很尴尬,在这种情况下,如果让他们感到不舒服,人们应该可以选择关闭相机。
- 呆在办公室里也带来了偶然的交流,人们可以通过这种交流非正式地了解一个项目的更多细节。这种形式的交流通常发生在走廊或休息时间。尽管许多组织试图阻止这种情况,转而支持更结构化的沟通渠道,但事实是这种情况仍然存在,并有助于员工理解不同的观点。当然,在家工作时不会发生这种情况,员工可能不了解特定情况的整个背景。在这种情况下,公司应该推行透明的议程,让所有团队成员在有组织的聊天中分享关于特定项目的一切。
- 起床上班,从床上滚下来,发现自己在家庭办公室里,这是不健康的。早晨的习惯对于保持某种正常感是必不可少的(特别是当远程工作是一种强加而不是一种选择的时候)。最好的事情是从事一些身体活动,花时间冥想,吃一顿健康的早餐,打扮一下,开始工作。当然,每个人都有自己理想的完美早间作息模式,保持这种模式对保持动力至关重要。
- 最后,我们不要忘记家是所有干扰的中心。毛毛猫可能会在键盘上跳来跳去以引起注意,孩子们开始从另一个房间大喊大叫,大脑思考着神话般的网飞系列的结局,餐具室每 5 分钟就叫你拿一份点心。这么多事情可以浪费你的时间!不幸的是,分心在每个环境中都是现实;我们必须接受它们,学会与它们共处,并尽可能设定界限。
布鲁克·拉克在 Unsplash 拍摄的照片
但是即使在家工作有它的挑战,它也能提供各种各样的好处;
- 通勤变得不存在,从而节省了人们的旅行时间,交通相关的挫折和汽车费用。想想看,一个人每天多花一个小时,省下几百欧元,能做些什么!
- 每人每年可以减少至少 2.3 公吨二氧化碳的碳足迹。
- 在家也意味着一个人可以完全控制自己的饮食。因为同伴压力而做出的不健康选择将成为过去——再也没有借口吃快餐了,因为厨房里没有微波炉。选择完全取决于个人!
- 公司根据他们的品牌方针设计他们的办公室,同时优先考虑功能性和互动性。但是家庭办公室是不同的;它反映了员工的个人主义风格。这个人是一个风水怪胎,喜欢在北极的温度下工作,但被热带植物包围,还是一个被锁在黑暗房间里的地下地下城主,这完全取决于个人。这些选择使家庭办公室成为一个有趣的空间,帮助员工提高生产力。
- 最后,远程工作不一定要在家里进行。如果没有健康限制(就像疫情实施的那样),员工可以在咖啡店、共同工作空间甚至大自然中舒适地工作。如果想更进一步,他也可以在一个或几个国家工作。这些人通常被称为数字游牧者,因为他们使用技术谋生,同时过着游牧生活。
艾玛·马修斯数字内容制作在 Unsplash 拍摄的照片
本文试图描绘一幅远程工作的真实画面。该系统远非完美,但它确实提供了各种优势,足以满足现代工作场所的需求。有一点是肯定的,当健康紧急情况消退时,我们不能回到我们的旧习惯,但我们必须进一步投资,改善远程工作实践。我们永远不知道下一次疫情什么时候会袭击我们,它可能比我们想象的要快。当它到来时,我们必须做好准备。从现在开始,远程办公不应该成为我们在需要时公开的秘密武器,而是我们当前工作实践的延伸。在家工作应该是我们的第二天性。只有这样,当下一次疫情袭击我们时,我们才能不受干扰地继续工作。
本文原载于【会计师】。请在下面留下你的想法评论。如果你喜欢这篇文章,请跟我来🐦推特,🔗 LinkedIn ,📷 Instagram 或者😊脸书
正如我们所知,人工智能正在如何改变汽车保险
towardsdatascience.com](/killing-the-motor-underwriter-cb11317cda98) [## 依靠人工智能
利用人工智能在新的十年里重塑银行业
towardsdatascience.com](/banking-on-ai-27d4d39bda1c) [## 在 2020 年推动您的小型企业
毫无疑问,2019 年是人工智能(AI)年。我们听说了很多,但很多人不确定…
towardsdatascience.com](/boosting-your-small-business-in-2020-6ae3529cbfb0)
Alexei DingliProf 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他出版了几本同行评审的出版物,并且是马耳他的一员。由马耳他政府成立的人工智能工作组,旨在使马耳他成为世界上人工智能水平最高的国家之一。*
使用 SciPy 层次聚类重塑传统篮球位置
使用 python 中的等级聚类分析查看五个位置的函数如何随时间变化
波士顿凯尔特人队教练布拉德·史蒂文斯说:“我再也没有这五个位置了。”。“现在可能只有三个位置,你要么是控球者,要么是边锋,要么是大个子。”在过去的 10 年里,我们已经看到了大前锋和中锋的功能的演变,从被期望去低位完成利用他们的身高和力量得分,他们被期望去伸展地板和击倒三分。我想调查截至 2018-19 赛季的位置变化。
雪莉·胡利
调查指南
我要做的第一件事是收集 NBA 所有现役球员的赛季平均数据。我用的代码如图 本文 **。**这给了我关于 这一页 关于basketball-reference.com的所有统计数据。
图片来自 Basketball-Reference.com
我将对这些数据进行的操作称为层次聚类。也被称为分层聚类分析,这是一种根据相似的统计数据对对象(在这种情况下是球员)进行聚类的算法。我使用了一个名为 SciPy 的模块来做这件事。我用的参数是 FG,FGA,FG%,3P,3PA,3P%,2P,2PA,2P%,eFG%,FT,FTA,FT%,ORB,DRB,TRB,AST,STL,BLK,TOV,PF,PTS。所有其他的数据都与调查无关,但是我确实使用了比赛次数,每场比赛的时间以及分数来过滤掉低价值的球员。我剔除了所有场均得分低于 10 分、每场比赛上场时间低于 20 分钟的球员(这大约是一场比赛的 42%),以及那些在赛季中出场少于 50 场的球员(这是可用比赛的 61%)。
进行调查
我要做的第一件事就是收集数据。这是比较容易的部分,因为我只是使用了前面文章中的代码。返回熊猫数据框中的统计数据。这样做的第一个问题是,球员的数据是以字符串的形式存储的,而我需要它们以浮点数的形式存储,所以我在将它们放入数据框之前对它们进行了更改,它们是一个二维数组。
forbidden =[0,1,3]
for x in player_stats:
i=0
while i<len(x):
if i in forbidden or x[i] == **''**:
pass
else:
x[i] = float(x[i])
i+=1
“禁止”是数据框中字符串的索引(姓名、位置和球队),而“球员统计”是二维数组。
然后我需要过滤掉统计数据。一些球员丢失了数据,例如科斯塔斯·安特托昆波斯·3P %丢失了,所以我不得不删除所有数据为空的球员。这只发生在百分比上。
来自 basketball-reference.com
stats = pd.DataFrame(player_stats, columns = headers)
stats.head(10)
data = stats.drop(columns=**"Pos"**)
data = data.drop(columns=**"Tm"**)
nan_value = float(**"NaN"**)
data.replace(**""**, nan_value, inplace=True)
data.dropna(subset = [**"2P%"**], inplace=True)
data.dropna(subset = [**"FT%"**], inplace=True)
data.dropna(subset = [**"3P%"**], inplace=True)
data.dropna(subset = [**"FG%"**], inplace=True)
data.dropna(subset = [**"eFG%"**], inplace=True)
data = data.dropna()
这将创建数据框,移除职位和团队(与调查无关)并用“NaN”(一个常见的占位符)替换任何空值,然后从数据框中删除具有此占位符的任何行。然后,我需要删除不符合我之前指定的标准的行。
data = data[data[**'G'**] > 50]
data = data[data[**'PTS'**] > 10]
data = data[data[**'MP'**] > 10]
然后我需要做最后的准备。我需要删除球员的名字,游戏和游戏开始了。所有这三个字段对调查来说都是不必要的,所以我只是将它们放入一个新的数据框中,因为我想保留 树状图 (输出的图形)的名称。
ds = data.drop(columns =**"Player"**)
ds = ds.drop(columns =**'G'**)
ds = ds.drop(columns = **'GS'**)
然后,我需要获得一个 NumPy N 维数组 中的名字,因为这是树状图标签需要传递到层次聚类函数中的格式。
namesarray = data[**'Player'**].to_numpy()
最后,我必须设置绘图大小和分辨率,给树状图一个标题,然后剩下要做的就是将这些参数传递给 SciPy 层次聚类函数,然后显示树状图
plt.figure(figsize=(10, 7), dpi = 300)
plt.title(**"Redefining positions"**)
dend = shc.dendrogram(shc.linkage(ds, method=**'ward'**), labels=namesarray)
plt.show()
得出的结论
从生成的树状图中,我设法推断出 5 个不同的位置。请记住,这些结果来自 2018-19 NBA 赛季,并不反映球员的整个职业生涯。
传统大人物
哈桑·怀特塞德和鲁迪·戈贝尔分别代表波特兰开拓者队和犹他爵士队。史蒂夫·米切尔-今日美国体育
传统的大男人是一个濒临灭绝的品种。他们被期望更多的伸展地板,而不是背对篮筐。他们的篮板和篮筐保护令人惊叹,但他们在现代比赛中投篮能力的缺乏限制了他们的得分量。这些球员有很高的 FG%但是低到没有 3PA。这些参与者包括:
- 鲁迪·戈贝尔
- 哈桑·怀特塞德
- 贾维尔·麦基
双向全方位威胁
勒布朗詹姆斯和科怀·伦纳德分别为洛杉矶湖人队和洛杉矶快船。林浩伟/美联社
这些玩家在游戏的几乎所有领域都表现出色。篮板,抢断,得分,助攻,同时也有一个很好的(不是很好的)3 分投篮。这些类型的球员通常都是联盟中的佼佼者。这些参与者包括:
- 科怀·伦纳德
- 勒布朗·詹姆斯
- 乔尔·恩比德
持球者
朱·霍勒迪和凯里·欧文分别代表新奥尔良鹈鹕队和布鲁克林篮网队。图片来自美联社图片/Mary altafer
控球手是…嗯,控球手。他们的得分量可以有很大的不同,但有一点是他们都有很高的助攻数。尽管没有在本次调查中进行测量,但它们的使用率都很高。这些参与者包括:
- 朱·霍勒迪
- 凯里·欧文
- 卢卡·东契奇
伸展四肢(和四肢)
多伦多猛龙队的帕斯卡尔·西亚卡姆。卡洛斯·奥索里奥/美联社
伸展四人组是拥有 3 分投篮的大前锋。他们可以有效地冲向篮筐,但在接球投篮 3 种情况下也很有效。他们通常也有很高的篮板数和很低的助攻数,但也有例外。其中包括的一些玩家是:
- 杰森·塔图姆
- 帕斯卡尔·西亚卡姆
- 卡尔-安东尼·唐斯
三点专家
詹姆斯·哈登和克莱·汤普森分别代表休斯顿火箭队和金州勇士队。特洛伊·陶尔米纳/今日美国
虽然这些球员可能不仅仅局限于三分球,但他们确实有尝试很多三分球的天赋,而且成功率很高。这些球员都是出色的得分手,他们既可以创造自己的投篮机会,也可以用接球投篮得分。这些参与者包括:
- 克莱·汤普森
- 詹姆斯·哈登
- 布拉德利·比尔
结束语
首先,我想说调查结果是 而不是 100%正确,你不应该相信我的话。从这些数据中你只能推断出这么多。使用率、拍摄地点以及游戏风格等其他因素都没有考虑在内。虽然有很大的改进空间,但在我看来,这是有一定道理的。不过,随你怎么想吧。所有的代码和最终的树状图都在这里链接的一个 GitHub 库中。
关系和机器学习:它们有什么共同点?
【剧透预警】答案过拟合
照片由 Geran de Klerk 在 Unsplash 上拍摄
我一直认为过度适应相当于一对已经在一起很长时间的夫妇的机器学习。
也许用这种说法来开始一篇文章有点过了,所以如果这听起来很奇怪,检查一下图片中的几只斑马。让我们称他们为迪克和简,并假设他们已经在一起一段时间了。事实上,时间太长了,以至于他们对另一只斑马了如指掌,甚至知道它如何说话、思考,甚至在打斗即将爆发前会发生什么(顺便说一句,这是自我保护的关键信息)。因此,迪克和简感到舒适,并开始认为这种关系/情侣的事情很容易,他们已经成为“阅读”面部斑马表情的艺术专家,用斑马语言解释单词,甚至肢体语言,如尾巴摆动;它们知道另一只斑马什么时候高兴、悲伤或生气,甚至知道该说什么或做什么来达到自己的目的。迪克和简是关系游戏的大师,对吗?
不对。证据呢。在一起多年后,他们分手了,是时候再次回到约会游戏中了(对你们中的一些人来说,约会是一件如此严肃的事情,几乎不能称之为“游戏”)。但是我们的小斑马朋友发现这其实很难。也许他们并不像自己想象的那样擅长约会/恋爱。你猜怎么着?他们可能不是(你也不是)。那么,为什么迪克和简曾经认为他们是关系的主人呢?
因为他们正在做一些好的旧的过度配合(关系风格)!是的,他们建立了一个基于单一斑马的关系学习模型,并认为它适用于所有斑马。举例来说,迪克认为因为他的小把戏对简起了作用,它们也会对他未来的夫妇起作用,但后来他发现不同的斑马实际上是互不相同的。惊讶吗?欢迎来到过度合身的危险世界。
机器学习中的过拟合
所以,动物王国到此为止。过度拟合通常发生在监督学习中,当您仅基于实例的特定样本构建模型时。基本上,您的模型“记忆”样本中个体的目标变量的属性和值,然后,当您要求对同一样本中的一个个体进行预测时,模型会简单地吐出之前记忆的该个体的目标变量的值,并将其称为“预测”。听起来很熟悉?这是应该的,因为这正是 Excel 的 VLOOKUP 公式所做的:您给它输入一个值,它在表上查找该值所在的行,然后返回同一行的另一列的值。我想我们都同意 VLOOKUP 公式不是一个机器学习模型,即使在它最疯狂的梦想中也不是。
这就好比你对你的浪漫伴侣太了解了,你知道当他/她扬起左眉的时候,一场争斗就要开始了。嗯,这对这个特定的人来说很好,但也许当你有了新的伴侣,你会发现,对这个新人来说,扬眉实际上是一种**“让我们浪漫起来”**(如果你知道我的意思)的标志。
虽然这听起来很傻,但这是数据科学中常见的错误。你建立了一个模型并爱上了它,因为它完美地预测了你的训练集的每一个实例。你把它推销给你的老板,组织一个团队会议来展示你的大想法,在问答环节的 30 秒内,你的 it 经验丰富的同事否决了它,因为它似乎不能很好地推广到其他情况。所以现在你只是在大家面前看起来像个傻瓜…
非常严重的是,公司有时会花费数百万美元来建立简单记忆数据集的模型,并称之为“预测模型”。基本上,你只是花了一堆钱做了一些你本可以在 30 秒左右完成的事情(还记得那个 VLOOKUP 公式吗?)
那么,我们如何避免过度拟合的危险呢?
很高兴你问了。这里有三个总的想法要记住,而发动战争过度拟合。
训练/测试集拆分
这是经典的。我不打算深究,因为它已经在教科书和 YouTube 视频中被远比我更有趣、更感同身受的人解释过无数次了。让我告诉你这个想法:如果你是一个三年级的数学老师,你不会用你给学生的练习作为实际测试的练习。为什么不呢?嗯,因为仅仅记住练习页后面的答案并在考试中重复它们太容易了,所以几乎没有数学学习在进行。如果你明白这一点,你就明白了训练/测试拆分在机器学习模型构建中的重要性。这里的教训很简单:永远不要用你用来构建模型的相同数据来测试模型,否则它会欺骗你,就像你的学生一样。
交叉验证
比方说,你喜欢烹饪,你想出了一个全新的食谱来制作一个世界上从未尝过的美味香蕉面包。你想找到一种方法来客观地确定你的食谱是否好,或者只是你神奇的烹饪技巧使它尝起来很棒(我会称之为烹饪过度)。所以你召集了十个想一起去的烹饪专家。你把食谱给他们中的八个人,他们准备面包,然后让剩下的两个人试一试,并从 1 到 10 打分。你和同样的十位专家重复这个实验,但是这次你让不同的一对夫妇来尝试并评分。你再这样做三次,你的香蕉面包就有了五个不同的等级,每个等级都来自不同的烹饪专家。为了得到你的食谱有多好的最终等级,你平均五个等级,你就完成了。
简单来说,这就是交叉验证。为了了解机器学习模型到底有多好,您将数据分成训练集和测试集几次,始终保持相同的比例(在本例中为 80/20 ),但旋转测试准确性的实例。在十个实例的数据集中,它看起来是这样的:
作者图片
在左边,完整的数据集(每根香蕉都是一个实例);在右侧,同一个数据集,只是现在我们已经执行了五个不同的训练/测试分割,称为折叠:对于每个分割,黄色香蕉是用于构建模型的实例,绿色香蕉代表我们将用于测试它的实例。这就是“x-fold 交叉验证”这个名字的由来。在这种情况下,这是一个 5 重交叉验证,因为我们有 5 个不同的分裂,但 10 重交叉验证也很常见。
现在,剩下要做的就是在每个不同的折叠上测试模型的准确性,计算一些总体准确性的总度量,我们就完成了。这个总得分应该为我们提供模型预测目标变量能力的可靠量化,并且它还应该为我们提供过度拟合可能性的良好提示。请记住:总是要找到客观的方法来衡量你的模特的表现和过度拟合的倾向。
复杂性控制
作者图片
是的,那就是我,试图成为一个写歌英雄,顺便说一句,这从来没有发生过。伙计,那东西太难了。你知道当你写一首歌,但它是如此的无聊和简单,以至于没有人有兴趣听它?所以你试图让它变得更复杂和有趣,人们开始喜欢它,所以你让它变得更复杂,但每个人仍然喜欢它。然后你开始想“伙计,我是个不错的歌曲作者。歌曲越复杂,效果就越好”。
只是实际上并不是这样。当你的歌曲过于复杂,只能吸引音乐专家时,你就会失去大部分听众(倒 U 型曲线的一个很好的例子)。我的朋友,这个叫做复杂性控制,它也适用于机器学习模型。
基本上,过于简单的机器学习模型不会很好地捕捉数据中的模式。因此,它会对你的目标变量做出非常模糊的预测,精确度可能非常低。就像你对你的歌所做的那样,你可能会增加它的复杂性(也许是通过增加更多的解释变量,例如在线性回归的情况下)以使预测更加准确。然而,就像你的歌一样,这只会在一定程度上起作用,之后…不出所料,你的模型开始过度拟合训练数据,其性能水平下降。所以,简而言之,不要太纠结于复杂性,否则它会让你所有的粉丝远离你,回到布鲁诺·马斯的那首歌(反正肯定比你的好)。
这些只是许多想法中的一些非常普遍的想法。这里的要点是让你对过度拟合的危险有一个全面的认识,并找到一些线索去寻找解决方案。对于那些有兴趣深入了解的人来说,YouTube 上有很多很棒的频道,有着令人惊叹的相关内容。你会在这里找到几个和这里的。
斑马,重访
还记得我们的朋友迪克和简吗?我想告诉你他们复合了,但事实是他们没有。事实上,他们做了一些更好的事情:他们每个人都开发了更聪明的关系学习模型,广泛适用于更多的斑马,并使它们不仅能够找到新的伴侣,还能显著增加非洲大草原上斑马的数量。我想我们都是赢家,不是吗?
相对重要性分析:交流多元回归结果的更好方法
任何行业客户都关心推动结果(Y)的因素(X 变量)的相对重要性。员工流动的最强预测因素是什么?哪些客户最有可能给我们带来回头客?服务体验的哪些方面与客户满意度联系最紧密?
回答这些问题的传统方法是回归分析。然而,没有统计背景,很难解释这种分析的结果。很难解释其中一个预测因子的单位变化与 y 的比例变化相关联。系数可能有时会产生关于 X 变量重要性的误导性结果。
另一种方法是将这种分析的结果解释为百分比,代表每个预测因子的相对重要性。这是一种更直接的方式来传达这样的发现。
已经有几种计算相对重要性的方法被提出来了(关于综述,请参见 Johnson & LeBreton,2004 和 Tonidandel & LeBreton,2011 ),但是我将概述一种相对简单的方法。这种方法的优点是它可以很容易地从回归和协方差表的结果中计算出来,并且不需要任何进一步的计算。此外,它直接对应于多重 R-Square,并考虑了预测因子的共线性。它也不受任何预测因子的重新标度的影响。
一个例子
为了说明这种方法,假设您受一家餐馆老板的委托来确定客户满意度的最重要驱动因素,并且您在 500 名客户中进行了一项调查来回答这个问题。
你确定的三个潜在因素包括对以下方面的满意度:(1)物有所值,(2)食物质量,(3)客户服务。让我们假设物有所值是用 1(物有所值极差)到 10(物有所值极好)的尺度来衡量的,但另外两个是用 1(非常不满意)到 5(非常满意)的尺度来衡量的。
结果变量是一个净促进者分数。(在 0 到 10 分的范围内,您向朋友或同事推荐这家餐厅的可能性有多大?)
生成该数据集的 R 代码如下所示:
load.package <- function(x)
{
if (!require(x,character.only = TRUE))
{
install.packages(x,dep=TRUE)
if(!require(x,character.only = TRUE)) stop("Package not found")
}
}# Load the MASS package
load.package("MASS")# Generate a dataset using MASS----
dimnames <- c("Value for money", "Quality of food", "Customer service", "Net Promoter")
covMat <- matrix(data = c(1,-0.2, 0.01, 0.4,
-0.2, 1, 0.10, 0.4,
0.01, 0.10, 1, 0.5,
0.4, 0.4, 0.5, 1), nrow = 4, ncol = 4, dimnames = list(dimnames, dimnames))
dataset.standardized <- mvrnorm(n = 500, mu = c(0,0,0,0), Sigma = covMat, empirical = TRUE)# Rescale the variables----
dataset <- dataset.standardized
for (a in 1:dim(dataset.standardized)[2]) {
dataset_min <- min(dataset[,a])
dataset[,a] <- dataset.standardized[,a] - dataset_min
dataset_max <- max(dataset[,a])
dataset[,a] <- dataset[,a] / dataset_max
}
dataset[,1] <- dataset[,1] * 9 + 1
dataset[,2] <- dataset[,2] * 4 + 1
dataset[,3] <- dataset[,3] * 4 + 1
dataset[,4] <- dataset[,4] * 10# Convert each matrix to a data frame
dataset.standardized <- as.data.frame(dataset.standardized)
dataset <- as.data.frame(dataset)
已经创建了两个数据集:一个数据集的变量是原始度量,另一个(标准化)数据集的每个变量都经过了重新调整,方差为 1。
描述性统计(平均值、标准偏差和变量间的相关性)如下所示:
表 1。描述统计学
回归分析的代码如下所示。我提出了非标准化和标准化(β)系数(并省略了标准误差、 t 统计和 p 值):
# Fit regression model----
regmodel <- lm(`Net Promoter` ~ `Value for money` + `Quality of food` + `Customer service`, data=dataset)
regmodel.std <- lm(`Net Promoter` ~ `Value for money` + `Quality of food` + `Customer service`, data=dataset.standardized)coefs <- data.frame("Unstandardized" = regmodel$coefficients[2:4],
"Beta" = regmodel.std$coefficients[2:4])coefs
回归的结果是:
表二。回归结果
估计相对重要性的一个简单而相当常用的方法是将每个回归系数表示为系数总和的百分比。对于非标准化系数和贝塔系数,我在下面介绍了这种方法:
# Relative importance: traditional method----
coefs$`RI Traditional` <- coefs$Unstandardized / sum(coefs$Unstandardized)
coefs$`RI Traditional (std)` <- coefs$Beta / sum(coefs$Beta)
coefs
表 3。相对重要性的传统衡量标准
查看结果,我们可以立即发现一些问题。首先,非标准化和标准化的解决方案给出了截然不同的结果。换句话说,该方法不考虑变量的缩放方式。
第二个(不太明显的)问题是,该方法没有考虑每个 X 变量之间的相关性。尽管在此分析中不存在问题,但也不清楚如何处理负回归系数,尤其是那些由预测值的高度共线性引起的系数。(实际上,一些研究人员会将此类变量报告为 0%,但这歪曲了他们的贡献。)
另一种(基于模型的)方法
用每个 X 变量在 Y 变量中所占的方差比例来表示相对重要性会更好。在回归分析中,这就是 R 平方统计向我们展示的。但是怎么才能把 R-Square 分解成各个预测器解释的比例呢?
首先,解释一下 R 平方是如何计算的是很有用的。r 平方由以下公式给出:
其中 X 代表每个预测值, Y 代表结果变量, j 是模型中 X 个变量的个数, B 是每个回归系数,SD 代表每个变量的标准差。如果变量是标准化的,我们可以简单地用 1 代替每个 SD。
将此公式应用于我们的示例,R 平方等于:
分子代表每个 X 变量的方差。扩展分子得到以下等式:
其中 Var 代表每个变量的方差(标准差的平方),Cov 代表两个变量之间的协方差(两个变量的联合可变性)。如果这两个变量是标准化的,协方差就相当于一个相关性。
这个方程划分了 X 变量的方差,指出了哪些预测因子是最重要的。
前三项——0.413 Var(X1)、0.919 Var(X2)和 1.206 Var(X3)是明确的,因为它们是与 Y 变量直接相关的方差。然而,等式第二行的协方差项更难解释,因为它们代表共同的可变性。我们应该将这个共享方差分配给哪个变量?
从我们的例子中,让我们检查 X2(食品质量)和 X3(客户服务)。这些变量的协方差为 0.038(相关性为 0.100)。如果我们将每个预测值和共享区域所占的方差可视化,它看起来会是这样的:
红色区域代表食物质量的差异;蓝色区域代表由客户服务计算的差异。中间的紫色区域代表不能分摊给 X2 或 X3 的共同差异。在某些方面,这就像是国家之间的领土争端。
如何划分(并征服)共享区域
我的建议是,根据每个变量直接解释的方差大小,按比例划分共享方差。
因此,对于食品质量和客户服务,分配给双方的共享差异为:
在这种情况下,因为变量之间的相关性很小,所以两个变量所占的共享可变性也很小。因此,没有太多可以分割的。然而,对于高度相关的变量,这个区域要大得多。
该解决方案具有几个吸引人的特征:它考虑了每个变量的范围,它考虑了每个变量和结果之间的关系的强度,它不产生越界结果(例如,负方差解释),它可以适应负系数,它可以使用分析的输出直接计算,并且它考虑了预测值之间的相关性。
在 R 中,实现这种方法的语法如下:
# First, we create a matrix depicting the variance accounted for by each variable. The diagonal shows the variance directly attributable to each variable. The off-diagonal shows the shared variance attributable to both variables.var.exp <- matrix(data = NA, nrow = dim(coefs)[1], ncol = dim(coefs)[1])
for (y in 1:dim(coefs)[1]) {
for (x in 1:dim(coefs)[1]) {
var.exp[y,x] = cov(dataset)[y,x] * coefs$Unstandardized[y] * coefs$Unstandardized[x]
}
}coefs$`Var accounted for` <- 0
for (y in 1:dim(coefs)[1]) {
for (x in 1:dim(coefs)[1]) {
if (x == y) {
coefs$`Var accounted for`[y] = coefs$`Var accounted for`[y] + var.exp[y,y]
}
else {
coefs$`Var accounted for`[y] = coefs$`Var accounted for`[y] + var.exp[y,x] * (var.exp[y,y] / (var.exp[y,y] + var.exp[x,x]))
coefs$`Var accounted for`[x] = coefs$`Var accounted for`[x] + var.exp[y,x] * (var.exp[x,x] / (var.exp[y,y] + var.exp[x,x]))
}
}
}coefs$`RI (new method)` <- coefs$`Var accounted for` / sum(coefs$`Var accounted for`)coefs
这种方法的结果如下所示:
表 3:相对重要性的新衡量标准(最后一栏)
相对重要性的新度量产生了与以前的方法相当不同的结果。尽管 beta 系数最大,但就相对重要性而言,性价比被认为是最低的。这个结果有一个有趣的原因,它与 X 变量之间的相关性有关。
X 变量之间的相关性如何影响相对重要性?
这种方法似乎意味着高度相关的变量比不相关的变量更重要。相反,负相关的变量就不那么重要了。为什么会这样呢?
对预测因子之间正相关的一种解释是相互因果关系。例如,如果餐馆老板通过更多的员工培训来改善顾客服务,它也可以提高食物的质量(如果厨师的技能和能力提高的话)。或者,改善食物可能会导致顾客忽略糟糕的顾客服务。每个预测因素都更重要,因为改善其中一个因素会对另一个因素产生积极的影响。
相反,变量之间的负相关往往代表某种情境约束。在我们的例子中,如果餐馆老板决定提高他们饭菜的质量,很可能需要提高价格。同样,如果餐馆老板决定降低价格,这可能意味着在其他方面节省成本,例如使用低质量的原料。因此,每个预测因子都不那么重要,因为提高一个会以牺牲另一个为代价。换句话说,共享方差是从直接归因于其他变量的方差中减去。
一些事后的想法和警告
你可能会想:当谈到共享方差时,为什么不简单地在每个变量之间对半分呢?这似乎是一个吸引人的解决方案,但它会引起一些问题。特别是,如果两个变量负相关,并且由一个变量解释的方差非常低,那么它会导致负方差。
从因果关系的角度来看,推荐的解决方案假设 X 变量之间的相关性代表相互影响。事实上,X 变量之间存在关联还有其他可能性。X 变量中的一个可能是第二个的原因。可能有第三个(省略)变量负责相关。这些不同的情景可能会对每个变量的相对重要性产生影响。
参考
j . w . Johnson 和 j . m . LeBreton(2004 年)。组织研究中相对重要性指数的历史和使用。组织研究方法,7(3),238–257。土井: 10.1177/1094428104266510
s .托尼丹德尔和 J. M .勒布雷顿(2011 年)。相对重要性分析:回归分析的有益补充。商业和心理学杂志,26(1),1-9。doi:10.1007/s 10869–010–9204–3
LVQ 的相关更新
学习矢量量化是一种简单而强大的分类算法。使用训练数据,该算法试图使原型适合每个类,使得每个原型最佳地代表它们各自的类。为了符合原型,必须使用一些相似性度量。最常见的是使用简单的老式欧几里德距离:
对于训练过程,为每个类初始化原型。每个类可以配置多个原型。然后,训练算法会尝试移动这些原型,使它们最好地代表它们各自的类。对于训练集中的每个数据点,训练算法使用给定的距离度量找到最接近的原型,如果类别标签不同,则推开该原型,如果类别标签匹配,则吸引该原型。它对训练数据集中的每个点都这样做,如果需要的话,多次扫过整个数据集以达到收敛。下面的动画演示了简单数据集的训练过程。类别 1 由 2 个原型(大圆圈)表示,因为它被分成两个集群。收敛后,通过计算新数据点到所有原型的距离并选择最近的原型的类别来进行新的预测。
然而,有一个问题:欧几里德距离度量对每个输入维度进行同等加权,这通常是不期望的。要素的缩放比例可能不同,或者一个要素可能非常嘈杂。这些特征提供很少的辨别能力,但是对计算的距离有同等的贡献。举个例子:假设我们正在尝试构建一个分类器,根据一个人头发的长度和一个人的身高来区分男人和女人。然而,我们正在处理一个数据集,其中每个人的头发长度都相似。在这种情况下,头发长度并不是一个非常有用的区分男女的特征。当然,我们可以使用基本的统计分析自己得出这个结论,但通常情况下,这些事情非常微妙。如果有什么能帮我们解决这个问题,那不是很好吗?原来是有的!我们可以改变欧几里德距离度量,使得每个输入维度根据某个因子进行加权:
加权欧几里德距离
向量λ也被称为相关性向量。它通过一些因素来衡量每一个输入,这样,如果我们正确地选择λ的值,它将帮助我们摆脱歧视性较小的维度。
然而,这并没有解决问题:我们如何量化每个特征的区分能力?好消息是我们根本不需要做任何特别的事情!我们所要做的就是调整算法,让它自己更新相关向量。是不是很棒!?然后在训练之后,相关向量λ代表每个特征的重要性。不太重要的特征对距离度量的权重降低,而具有良好辨别能力的特征被提供高值。
因为相关性(λ)向量在算法过程中改变,所以上述距离度量也可以被称为自适应距离度量。负责这一切的算法被称为相关性学习矢量量化(RLVQ)。
太酷了!我们如何做到这一点?
RLVQ 算法实际上非常类似于常规 LVQ,我们只需要用相关向量更新规则来扩充它。根据以下规则,关联向量与原型一起被更新:
如果当前特征向量与最近的原型具有相同的类别(下标 i 代表每个向量中的第 i- 个元素)。
如果当前特征向量与最近的原型不具有相同的类别。
上述更新规则适用于相关性向量λ中的所有元素 i 。 α 表示相关性学习率。在每次更新相关性向量之后,它必须被归一化,使得它的元素之和为 1。此外,相关性向量的任何元素都不允许为负。如果相关性向量的任何分量在训练期间变成负的,则它必须被设置为零。另一方面:相关性向量不必是全局的。您可以为每个原型或每个类使用不同的相关性向量。原型和 lambda 向量同时更新。
这些更新规则可能看起来有些随意,但是可以被激励如下:如果特征向量被错误地分类,那么如果特征向量的第 l 个分量接近原型的第 l 个分量,则相关性向量的那些分量 l 仅略微增加。越接近意味着它们对特征向量的不正确分类的贡献越大。另一方面,如果特征向量的第 l 分量远离第 l 分量,则相关性向量中的该分量 l 显著增加。如果特征向量被正确分类,可以使用类似的动机。底线:该算法减少了导致特征向量被错误分类的那些λ分量,并且增加了导致特征向量被正确分类的那些特征向量分量。
那是一大堆理论。你就不能给我看看代码吗?
我以为你不会问了!关于这个理论更精确的定义,我参考了这篇论文。让我们来看看 Python 中的一个实现:
没有一些实验,这些代码当然没有任何意义,所以让我们在一些样本数据上尝试一下。
我们尝试的第一个数据集是一个人工数据集。它包括 2 个类,每个类有 50 个训练样本和 2 个特征。第一个特征呈正态分布,第一类的均值等于 2,第二类的均值等于 1。在两种情况下,方差都等于 0.5。第二个特征也是正态分布,均值等于 0,方差等于 0.5,并且在类之间没有差异。下图显示了上述人工数据集的曲线图。
人工数据集
如果我们分开来看每一个特性,很容易看出,仅仅用特性 2 是不可能把这两个类分开的。我们可以很容易地删除这个特征,并获得相同的分类性能。然而,有趣的是,RLVQ 是否可以识别这一点,而无需通过显式编程来忽略该特性。
训练 RLVQ 系统最困难的任务是将参数设置为最佳值。通常,为了找到正确的值,建议使用某种验证程序,但是为了这次演示的目的,我只是尝试了几个值,并决定将原型学习率和相关向量学习率都设为 0.01。通常相关向量学习率应该小于原型学习率,但在这种情况下,它工作得很好。
在人工数据集上运行该算法之前,我将特征向量进行了洗牌,并留出 10 %的集合作为验证集。在几个训练时期之后,RLVQ 在验证集上实现了大约 0.2 的误差。相关性向量得出特征 1 的相关性为 0.9,特征 2 的相关性为 0.1。很明显,它认为特征 2 对成功区分这两个类别没有太大帮助。由于这个问题仍然很简单,LVQ 得到了相似的分数。
让我们看看 RLVQ 在一些真实数据上的表现!在这种情况下,我使用了来自 UCI 机器学习库的钞票认证数据集。产生二元分类问题的这个数据集包含大约 1000 个具有 4 个特征的训练样本。和以前一样,数据集的 10 %被留出以验证模型。0.01 用于原型学习率,0.001 用于相关性向量学习率(可能不是最佳值)。RLVQ 产生约 14%的误差。这明显优于验证误差约为 30 %的常规 LVQ。
谢谢,还有别的吗?
与 LVQ 相比,RLVQ 的优势在于,它可以滤除非歧视性特征,同时仍然是易于理解的相当简单的算法。相关性向量还提供了对数据底层分布性质的一些洞察。因此,RLVQ 可以用作特征选择工具,为其他更复杂的算法预处理数据。
用 Python 进行可靠性分析
面向工业工程师的 Python
全面生产维护
可靠性
可靠性是一个项目在给定的一段时间内,在特定的操作条件下,执行所需的功能的概率**。换句话说,它是一段时间内无故障的概率。**
可靠性侧重于产品投入使用后继续发挥作用的时间(即产品的生命周期)。可靠性可以被视为进入时间域的质量。其公式表示为:
其中 f ( t )是给定分布的概率密度函数。
计算在时间 t 的产品/部件可靠性
计算特定时间的产品/部件可靠性需要多个步骤:
- 步骤#1:获取故障时间 — 定义样本量,获取每个产品/部件故障前的工作时间。
- 步骤#2:确定最符合数据的分布 —为收集的数据创建直方图,拟合多个概率分布,并确定最能描述数据的分布。
- 步骤#3:获取分布参数——获取所选分布的位置、尺度和附加参数,以确定其概率密度函数。
- 步骤#4:获得概率 —使用累积密度函数获得时间 t 之前的故障概率,使用生存函数获得时间 t 之后的可靠性。
对于下面的例子,让我们考虑一个工程师对分析一个特定产品的可靠性感兴趣。工程师获得了 1000 个样本的故障时间(以周为单位),并预计该产品至少在 40 周内完全可用。让我们来看看 Python 代码!
步骤#1:获取故障次数
第二步:确定最符合数据的分布
数据拟合了六种不同的分布:α、β、指数、γ、正态和瑞利分布。从上图可以看出,beta 分布是最符合数据的分布(这是显而易见的,因为样本是根据已知的 beta 分布生成的)。
步骤#3:获取分布参数
贝塔分布参数:
- a = 6.193
- b =1.978
- 位置= -1.035
- 比例=50.908
步骤#4:获得概率
根据结果,更有可能的是,该产品不会如预期的那样持续至少 40 周,因为其在 40 周之前的故障概率为 57.32%(即,其在 40 周之后继续起作用的概率为 42.68%)。
总结想法
在时域中,可靠性是产品质量的一个重要组成部分。客户希望产品在发生故障后补货前能持续一段时间。如果产品的功能时间不能满足客户的要求,在制造过程中必须对其设计规格进行更改。
本指南涵盖了如何使用多个 Python 库分析可靠性的分步教程。考虑到 Python 在专业人士和学者中的高受欢迎程度,Python 代表了一个能够执行统计分析的伟大工具。虽然有其他程序和统计软件能够分析可靠性(如 Minitab、R、Microsoft Excel),但质量和工业工程师应根据其编码和分析技能决定使用哪一种,同时遵守组织的目标和客户的规范。
— —
如果你觉得这篇文章有用,欢迎在 GitHub 上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 个人资料 来浏览我以前的文章。感谢阅读。
——罗伯特
关于宗教的文本挖掘推文
使用 Python 的主题建模、情感分析和仇恨言论检测模型
有人声称科技革命的光芒将会削弱宗教在人类生活中的存在。然而,现在是 2020 年,有一件事似乎是不可避免的,宗教仍然在这里,并且会一直存在下去!也就是说,值得研究一下现代公众对宗教的看法。
这篇文章全面介绍了如何使用 Python 来提取、预处理和分析关于宗教的推文。该分析是关于实现主题建模(LDA)情感分析 (Gensim)和仇恨言论检测 (HateSonar)模型。下面的分步教程与代码和结果一起展示。
感谢 Johannes Schneider 博士和 Joshua Handali 理学硕士在列支敦士登大学指导这项工作。完整的代码可以在 GitHub 的这里找到。
列支敦士登瓦杜兹城堡
数据提取&预处理
为了获取 tweets,我们使用了一个公共 python 脚本,该脚本能够捕获旧的 tweets,从而绕过 Twitter API 的 7 天期限限制。该脚本是免费的,可以在 GitHub 的这里找到。你所需要做的就是调整搜索过滤器并运行程序。在我们的研究中,我们提取了包含短语*“宗教是”的推文*为了减少某些影响对宗教感受的孤立事件(如《查理周刊》袭击)的偏见,我们将时间范围延长至大约五年。我们从 2015 年 1 月开始到 2019 年 10 月,每月提取 1000 条推文。这产生了大约 57,351 条推文,然后被加载到数据帧中,准备进行预处理。
以下是整个分析过程的示意图
分析步骤
预处理
这些是执行预处理阶段所必需的包。
**import** pandas **as** pd
**import** numpy **as** np
**import** re# Plotting
**import** seaborn **as** sns
**import** matplotlib.pyplot **as** plt# Gensim
**import** gensim
**from** gensim.utils **import** simple_preprocess# NLTK
**import** nltk
**from** nltk.corpus **import** stopwords**from** collections **import** Counter
**from** wordcloud **import** WordCloud**import** warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)%matplotlib inline
数据加载
df = pd.read_csv('full_data.csv', index_col=[0])
df.head()
数据概述
在任何进一步的步骤之前,我们删除重复的内容,因为在 twitter 上,人们复制粘贴不同的引用并转发某些内容是很常见的。删除重复后,我们总共得到 53,939 条独特的推文。
**# DROP DUPLICATES**
df.drop_duplicates(subset=['tweet_text'], keep='first',inplace=**True**)
df.shape
Out: (53939, 1)
接下来,我们生成一些一般的描述性统计数据:
描述统计学
Twitter 允许通过“@”符号在推文中包含用户名。这些对我们的分析没有任何价值;因此,使用函数将它们从数据集中移除。
**# REMOVE '@USER'
def** remove_users(tweet, pattern1, pattern2):
r = re.findall(pattern1, tweet)
**for** i **in** r:
tweet = re.sub(i, '', tweet)
r = re.findall(pattern2, tweet)
**for** i **in** r:
tweet = re.sub(i, '', tweet)
**return** tweetdf['tidy_tweet'] = np.vectorize(remove_users)(df['tweet_text'], "@ [\w]*", "@[\w]*")
规范化,一种将所有 tweets 转换成小写的方法,这样“token”和“Token”就不会被认为是两个不同的单词。
**# NORMALIZATION**
df['tidy_tweet'] = df['tidy_tweet'].str.lower()
与用户名一样,标签也被认为对主题建模分析没有重要价值,因此被移除。
以上是该数据集的前 25 个标签,我们注意到 #islam 是使用最多的标签,这表明它是讨论最多的宗教。使用以下函数移除标签:
**# REMOVE HASHTAGS**
**def** remove_hashtags(tweet, pattern1, pattern2):
r = re.findall(pattern1, tweet)
**for** i **in** r:
tweet = re.sub(i, '', tweet)
r = re.findall(pattern2, tweet)
**for** i **in** r:
tweet = re.sub(i, '', tweet)
**return** tweetdf['tidy_tweet'] = np.vectorize(remove_hashtags)(df['tidy_tweet'], "# [\w]*", "#[\w]*")
接下来要删除的是 URL:
**# REMOVE LINKS**
**def** remove_links(tweet):
tweet_no_link = re.sub(r"http\S+", "", tweet)
**return** tweet_no_linkdf['tidy_tweet'] = np.vectorize(remove_links)(df['tidy_tweet'])
使用与链接相同的功能,我们还删除了*收集词,*那些首先用于过滤推文的词,在这种情况下:宗教,“宗教”
之后,需要去掉数字、标点符号(仅用于主题建模),以及特殊字符(@、&、#、%).
**# REMOVE Punctuations, Numbers, and Special Characters**
df['tidy_tweet'] = df['tidy_tweet'].str.replace("[^a-zA-Z#]", " ")
然后,从数据集中移除少于三个字符的单词(短单词),从而简化用于分析的特征提取。
**# REMOVE SHORT WORDS**
df['tidy_tweet'] = df['tidy_tweet'].apply(**lambda** x:' '.join([w **for** w **in** x.split() **if** len(w)>3]))
预处理的一个基本步骤被称为*标记化。*它是根据空格分割文本的过程,每个单词和标点都保存为单独的标记。我们使用来自 Gensim 的 simple_preprocess 方法来执行这个步骤。
**# TOKENIZATION**
**def** tokenize(tweet):
**for** word **in** tweet:
**yield**(gensim.utils.simple_preprocess(**str**(word), deacc=**True**)) df['tidy_tweet_tokens'] = **list**(tokenize(df['tidy_tweet']))
接下来,我们删除没有分析价值的停用词,通常是冠词、介词或代词,例如,“a”、“and”、“the”等。默认列表可以根据需要进行调整和扩展。我们向包含 179 个单词的自然语言工具包(NLTK)的预定义列表中添加了一些新单词。
**# Prepare Stop Words**
stop_words = stopwords.words('english')
stop_words.**extend**([*'from', 'https', 'twitter', 'religions', 'pic','twitt'*,])**# REMOVE STOPWORDS**
**def** remove_stopwords(tweets):
**return** [[word **for** word **in** simple_preprocess(str(tweet)) **if** word **not** **in** stop_words] **for** tweet **in** tweets]df['tokens_no_stop'] = remove_stopwords(df['tidy_tweet_tokens'])
在预处理的最后一步,我们删除少于三个令牌的 tweets 这导致总共有 49,458 条推文需要在分析阶段进一步考虑。对于主题建模和情感分析,具有少于三个标记的文档不适合生成足够的信息。
**# REMOVE TWEETS LESS THAN 3 TOKENS**
df['length'] = df['tokens_no_stop'].apply(**len**)
df = df.drop(df[df['length']<**3**].index)
df = df.drop(['length'], axis=**1**)
df.shapedf.reset_index(drop=True, inplace=**True**)
现在,出于识别和可视化数据集的最常用单词的说明性目的,我们生成 200 个最常用单词的单词云。
Wordcloud (250 字)
预处理阶段的效果如下图所示,清理后的 tweets 长度大大减少。如图所示,大多数推文在预处理后都不到 10 个单词,不像原始推文那样有大约 20 个单词。在第二组图表中,随着推文长度从大部分推文的大约 150 个字符变为清理阶段后的大约 50 个字符,效果更加明显。这一阶段至关重要,因为它减少了维度,并为模型产生了非常有价值的表征,这将在接下来的部分中解释。
清洁效果
最后,我们将预处理后的数据帧保存为 pickle ,然后用于主题建模阶段。
df.to_pickle('pre-processed.pkl')
主题建模
这些是实现 LDA (潜在狄利克雷分配)算法所需的包。
**# IMPORTS**
**import** pandas **as** pd
**import** numpy **as** np
**import** networkx **as** nx
**import** itertools
**import** collections
**import** spacy
**from** pprint **import** pprint# Plotting
**import** matplotlib.pyplot **as** plt
**import** seaborn **as** sns
**import** pyLDAvis
**import** pyLDAvis.gensim# Gensim
**import** gensim
**import** gensim.corpora **as** corpora
**from** gensim.utils **import** simple_preprocess
**from** gensim.models **import** CoherenceModel
**from** gensim.models.wrappers **import** LdaMallet# NLTK
**from** nltk **import** bigrams
**from** nltk.stem **import** PorterStemmersns.set(font_scale=**1.5**)
sns.set_style("whitegrid")**import** warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)**%**matplotlib inline
我们不打算深入解释 LDA 是如何工作的;详细内容可在1的原始论文中找到。LDA 算法的核心思想可以理解为一个生成过程,其中文档由一组主题 *T、*的概率分布定义,而离散单词的概率分布反过来建立每个主题。说到这里,我们加载预处理的数据:
df = pd.read_pickle('pre-processed.pkl')
df.head()
预处理数据概述
数据加载后,我们继续添加二元模型和三元模型。表达特定意思时经常一起出现的一系列单词。N 个单词的序列被称为 N 元语法,因为理论上 N 可以是任意长度;最常见的是成对的单词(二元单词)和一系列三个单词(三元单词)。首先,我们需要对 no_stop_joined 列进行标记化,并将其转换为一个包含每条 tweet 的标记的列表;我们将这个列表命名为 data_words ,如下所示:
**# TOKENIZE**
**def** sent_to_words(sentences):
**for** sentence **in** sentences:
yield(gensim.utils.simple_preprocess(str(sentence), deacc=**True**)) # deacc=True removes punctuationsdata_words = list(sent_to_words(data))
现在我们准备将二元模型和三元模型添加到我们的语料库中。
**# Build the bigram and trigram model**
bigram = gensim.models.Phrases(data_words, min_count=10, threshold=100)
trigram = gensim.models.Phrases(bigram[data_words], threshold=100)# Faster way to get a sentence clubbed as a bigram
bigram_mod = gensim.models.phrases.Phraser(bigram)
trigram_mod = gensim.models.phrases.Phraser(trigram)**def** make_bigrams(texts):
**return** [bigram_mod[doc] **for** doc **in** texts]**def** make_trigrams(texts):
**return** [trigram_mod[bigram_mod[doc]] **for** doc **in** texts]**# Form Bigrams**
data_words_bigrams = make_bigrams(data_words)
下图显示了我们数据集中的二元模型。我们可以注意到伊斯兰-和平-和平、耶稣-基督、科学-气候变化等的组合。
二元模型可视化
下一步是词汇化,这是许多文本挖掘应用的基本步骤。词汇化考虑了上下文,并将单词转换为其基本形式;例如,术语“拥抱”被转换为“拥抱”,最好的”被转换为“好的”对于词汇化任务,使用的包是 *spaCy,*一个开源库,其中有许多用于自然语言处理的预建模型。
**# LEMMATIZATION
def** lemmatization(tweets, allowed_postags=['NOUN', 'ADJ', 'VERB', 'ADV']):
"""[https://spacy.io/api/annotation](https://spacy.io/api/annotation)"""
tweets_out = []
**for** sent **in** tweets:
doc = nlp(" ".join(sent))
tweets_out.append([token.lemma_ **for** token **in** doc **if** token.pos_ in allowed_postags])
**return** tweets_out**# Initialize spacy 'en' model, keeping only tagger component
# python3 -m spacy download en**
nlp = spacy.load('en', disable=['parser', 'ner'])# **Lemmatization keeping only noun, adj, vb, adv**
df['lemmatized'] = pd.Series(lemmatization(data_words_bigrams, allowed_postags=['*NOUN*', '*ADJ*', '*VERB*', '*ADV*']))
在这一步之后,我们再次删除了重复项,因为由很少几个标记组成的短 tweets 在被词条化后可能会导致重复行。在这一步之后,我们有 48'013 个唯一的行。
另一个有用的技术是词干,这是将一个单词转换成其词根形式的过程。与前面提到的词干化不同,词干化是一种更激进的方法,因为后缀剪切经常导致无意义的英语单词。例如,单词“动物”将被词条解释为“动物”,但是搬运工斯特梅尔给出了“动画”我们决定实现这两者来帮助降维。
**# STEMMING**
stemmer = PorterStemmer()
df['stemmed'] = df['lemmatized'].apply(**lambda** x : [stemmer.stem(y) **for** y **in** x])
在构建 LDA 模型之前,我们必须创建两个主要输入:字典和语料库,它们是使用 Gensim 包中的函数创建的。
**# Create Dictionary**
id2word_stemmed = corpora.Dictionary(df['stemmed'])
**IN:** print(id2word_stemmed)
**OUT:** Dictionary(26748 unique tokens: ['also', 'bless', 'blood', 'deed', 'fact']...)\**# Create Corpus**
tweets_stemmed = df['stemmed']
**IN:** df['stemmed'][1]
**OUT:** ['piti', 'antonym', 'disast', 'human', 'live', 'piti']
以下是语料库的样子,它的长度为 48'013:
Gensim 给每个单词分配一个唯一的 Id,然后将语料库表示为一个元组 (word_id,word_frequency )。
**# Term Document Frequency**
corpus_stemmed = [id2word_stemmed.doc2bow(tweet) for tweet in tweets_stemmed]
例如,下面这条未经处理的推文:
@ wagner_claire 宗教和怜悯是反义词。一个是灾难,另一个是人性。我们可以没有宗教,但不能没有怜悯。然而我们拥抱着……”
在语料库中预处理之后,将呈现为元组列表:
[(11, 1), (12, 1), (13, 1), (14, 1), (15, 2)]
建立 LDA 模型
现在是我们初始化话题数量 *k=10,*的时候了,这些话题将会被调整。
**# Build LDA model**
lda_model_stemmed = gensim.models.ldamodel.LdaModel(corpus=**corpus_stemmed**,
id2word=**id2word_stemmed**,
num_topics=**10**,
random_state=**100**,
update_every=**1**,
chunksize=**100**,
passes=**15**,
alpha='**auto**',
per_word_topics=**True**)
在此步骤之后,我们可以直接生成主题或搜索最佳模型,使用一致性分数作为具有不同主题数量的每个模型的度量。
**# OPTIMAL MODEL**
**def** compute_coherence_values(dictionary, corpus, texts, limit, start=2, step=3):
coherence_values = []
model_list = []
**for** num_topics **in** **range**(start, limit, step):
model = gensim.models.wrappers.LdaMallet(mallet_path, corpus=corpus_stemmed, num_topics=num_topics, id2word=id2word_stemmed)
model_list.append(model)
coherencemodel = CoherenceModel(model=model, texts=texts, dictionary=dictionary, coherence='c_v')
coherence_values.append(coherencemodel.get_coherence())**return** model_list, coherence_valuesmodel_list, coherence_values = compute_coherence_values(dictionary=id2word_stemmed, corpus=corpus_stemmed, texts=df['stemmed'], start=**2**, limit=**26**, step=**3**)
下面是生成的每个模型的一致性分数,我们选择的最佳模型有 k=8 个主题。
建立模型并运行最佳模型后,我们将讨论以下主题:
解释:
Topic [0] 宗教&政治 不言而喻是用政治、控制、政府、民族、川普等术语来表示的。,这说明了宗教是一个敏感的方面,它的作用与政治有关。
主题【1】基督教 由包含基督教作为讨论主题及其代表性关键词(如教会、天主教、基督教等)的推文组成。对于主要属于西方世界、以基督教为主要宗教的说英语的观众来说,这样的话题是意料之中的。
话题【2】宗教&科学 关注的是宗教与科学之间永无止境的争论,这场争论在由技术革命引领的现代世界愈演愈烈。
话题【3】宗教教义,【6】个人信仰,【7】众说纷纭 以关键词为基准,似乎彼此更接近。
话题【5】伊斯兰教 是以伊斯兰教为主要讨论主题的推文集合。从标签数量和词频统计可以看出,伊斯兰教因其不同方面在社交媒体上受到高度讨论,引发了人们的不同反应。
下面给出了推文在各主题中的分布,我们可以注意到前三个主题更占主导地位:
情感分析(VADER)
该零件所需的包装如下:
**# IMPORTS
import** pandas **as** pd
**import** numpy **as** np
**import** seaborn **as** sns
**import** matplotlib.pyplot **as** plt
**import** spacy
**import** re
**from** pprint **import** pprint**import** nltk
nltk.download('vader_lexicon')
**from** nltk.sentiment.vader **import** SentimentIntensityAnalyzer
**from** nltk.corpus **import** stopwords**from** collections **import** Counter
**from** wordcloud **import** WordCloud**import** warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)**%**matplotlib inline
VADER 代表用于情感推理的效价感知词典,由[2]开发为基于规则的情感分析模型。关于如何开发该模型及其特征的详细信息可在原始文件中找到(见参考文献)。它考虑到了标点符号,大写,程度修饰语,连词,在分配情感值时前面的三个字母:消极,积极,中性。这些特性使得 VADER 情感分析器在对推文等社交媒体文本进行分类时取得了显著的效果,并使其成为进行我们分析的合适工具。
由于 VADER 情感分析器的特性,预处理阶段与主题建模阶段略有不同,下面列出了所采取的步骤,而代码与预处理阶段相同。也可以在这里 访问所有代码 。
情感分析的预处理步骤
删除不必要的列后的数据概览
VADER 模式
**# Create an object of Vader Sentiment Analyzer**
vader_analyzer = SentimentIntensityAnalyzer()negative = []
neutral = []
positive = []
compound = []**def** sentiment_scores(df, negative, neutral, positive, compound):
**for** i **in** df['tweet_text_p']:
sentiment_dict = vader_analyzer.polarity_scores(i)
negative.append(sentiment_dict['neg'])
neutral.append(sentiment_dict['neu'])
positive.append(sentiment_dict['pos'])
compound.append(sentiment_dict['compound'])**# Function calling**
sentiment_scores(df, negative, neutral, positive, compound)**# Prepare columns to add the scores later**
df["negative"] = negative
df["neutral"] = neutral
df["positive"] = positive
df["compound"] = compound**# Fill the overall sentiment with encoding:
# (-1)Negative, (0)Neutral, (1)Positive**
sentiment = []
**for** i **in** df['compound']:
**if** i >= 0.05 :
sentiment.append(1)
**elif** i <= - 0.05 :
sentiment.append(-1)
**else** :
sentiment.append(0)
df['sentiment'] = sentiment
将模型应用于我们的数据后,我们为每条推文分配了以下情感分数。最后一列表示最终分类( 1 -正, 0 -中性, -1 -负)。
下图给出了推文对情感类别的总体分类结果,其中 42.2% (20'512)的推文被归类为正面。* 41.1% (19'957)被归类为负面,,其余 16.7% (8'109)的推文被认为是中性(既不正面也不负面)。就社交媒体上关于宗教讨论的情绪而言,公众意见似乎是平衡的。*
根据情感对推文进行分类
此外,我们可以使用词云来查看负面和正面的推文,以说明每个类别的主导词。
字云正面推文
最常见的词是与领域相关的词,如伊斯兰教、穆斯林、基督教、基督教*,而一些与情感相关的词是:爱、和平、支持、伟大、尊重、善良等。,这自然意味着该推文的正面情绪得分。*
词云负面推文
在负面推文的情况下,除了与领域相关的词之外,一些携带负面情绪的词有:、杀戮、仇恨、攻击、愚蠢、暴力、问题、邪恶、操、狗屎、等..
由于积极和消极情绪的观点几乎各半,积极的推文除了轻微的数字优势外,在复合得分方面也有微小的负差异,如下图所示。正面推文的平均值为 0.525122,而负面推文的平均值为-0.541433。
复合得分分布
当谈到具体的宗教时,大多数讨论都是针对伊斯兰教的,推文数量最高,经过预处理步骤后有 679 条推文,其次是基督教,有 127 条推文,然后是其他流行的宗教,如印度教、佛教和犹太教。
讨论最多的宗教
伊斯兰教是社交媒体上讨论最多的宗教。因此,我们特别仔细地观察了对伊斯兰教的看法。对谈论伊斯兰的推文进行情感分析得出了以下结果:
对伊斯兰教的感悟
使用相同的方法(VADER)对推文进行分类,分析结果显示 44.2% (295 条)的推文是正面的,而 38.7% (258 条)的推文是负面的,而 17.0% (113 条)被认为是中性的。
下表列出了关于伊斯兰教正面和负面推文中最常见的词汇。
基于伊斯兰情感的词频
现在,我们呈现 10 条最积极的推文:
十大正面推文
上面显示的推文被高度评为正面,其中第 10 条推文的复合得分为 0.9810,第 1 条推文的复合得分为 0.989。分类器产生了正确的标签,因为推文显然是积极的,没有隐藏潜在的讽刺或讽刺模式,这些模式破坏了句子的意思。有趣的是,在 10 条推文中,只有 4 条提到了上帝,这个词,而爱这个词在 10 条最积极的推文中有 7 条被提到了 16 次。一条是关于伊斯兰教的,两条是关于基督教的。其余的是关于宗教的一般观点,集中在与他人的关系上,即彼此相爱是一个人应该遵循的核心宗教原则。大部分推文(6/10)的评分为负 0.000;其他推文的负分非常小,因为这些词:教条、种族、不请自来的等。个人正面得分最高的推文是第 4 条,得分为 0.683,因为它七次提到了和平这个词,在不包含否定词的同时增加了句子的正面度。
同样,以下是最负面的 10 条推文及其各自的得分:
**
上面显示的推文被评为非常负面(负面意义上),其中第 10 条推文的复合得分为-0.982,第 1 条最负面的推文的复合得分为-0.988。很明显,分类器产生了正确的标签,因为推文是负面的,表达了对宗教或宗教团体(即穆斯林)的拒绝、厌恶和负面情绪。这张表上的一些主导词及其各自的频率是死亡(8)、伊斯兰教(6)、强奸(4)等。被提及最多的宗教是伊斯兰教,在表达负面情绪时,10 条推文中有 8 条关注伊斯兰教,而一条是关于基督教,另一条是关于印度的佛教/印度教。
仇恨言论检测(声纳)
用于对讨论宗教的推文进行分类的模型是基于3工作的预训练模型。这个模型被认为对我们的任务有用,调查关于宗教的推特上仇恨言论的存在,并对其进行测量。这将有助于对在线环境中的宗教景观有一个总体的了解。
此任务所需的软件包有:
***# IMPORTS**
**import** pandas **as** pd
**import** numpy **as** np
**import** seaborn **as** sns
**import** matplotlib.pyplot asplt**from** hatesonar **import** Sonar # This is the hate speech detection library**import** warnings
warnings.filterwarnings('ignore')*
该过程从在笔记本上加载数据帧格式的数据开始。这些数据由大约 48,500 条推文组成,这些推文没有经过预处理,因为模型被训练来处理输入以提取必要的特征。模型中使用的一些预处理步骤有:移除标签、移除链接、移除提及、标记化和使用波特斯特梅尔的词干化。
数据概述
声纳型号
现在,我们将这个分类模型应用于我们的数据:
***# Create an object of Sonar Hate Speech Detection**
sonar = Sonar()Class = []
hate = []
offensive = []
neither = []**def** hate_speech_classifier(df, Class, hate, offensive, neither):
**for** i **in** df['tweet_text']:
sonar_dict = sonar.ping(text=i)
Class.append(list(sonar_dict.values())[1])
hate.append(list(list(sonar_dict.values())[2][0].values())[1])
offensive.append(list(list(sonar_dict.values())[2][1].values())[1])
neither.append(list(list(sonar_dict.values())[2][2].values())[1])**# Function calling**
hate_speech_classifier(df, Class, hate, offensive, neither)**# Prepare columns to add the scores later**
df["Class"] = Class
df["hate"] = hate
df["offensive"] = offensive
df["neither"] = neither*
生成的数据帧如下所示:
结果概述
*模型应用后,由 48'528 条推文组成的数据集被拆分为三类 *仇恨言论、攻击性语言、既不 (表示既不仇恨也不攻击)。下图中的第一个图表给出了推文在这些类别中分布的总体结果。仇恨和攻击性的推文加在一起总共产生了 3802 条推文,占数据集的 7.83%。因此,没有问题的推文总共有 44726 条,占数据集的 92.16%。第二张图表显示了所谓的有问题推文的分布情况,仇恨言论导致了总共 232 条推文(占有问题推文的 6.10%),因为攻击性语言在这一类别中占主导地位,共有 3,570 条(93.89%)。
仇恨言论检测结果
有趣的是观察情感特征如何与仇恨言论分类结果相关联。下图显示了仇恨言论、攻击性语言、和【非 负面、正面、或中性等分类的推文分布。正如预期的那样,仇恨言论更多地出现在负面推文中,从数字上讲,60%(232 条中的 145 条)包含仇恨言论的推文是负面的。在攻击性推文的情况下,比例类似于仇恨言论,正如习惯上预期的那样,大多数推文:58.8%(3570 条推文中的 2089 条)包含负面情绪。从其余部分来看,1106 条或 30.98%是正面的,375 条或 10.50%被归类为冒犯性的推文是情绪中性的。**
通过情绪检测仇恨言论
下图显示了基于复合情绪得分的仇恨推文的分布。与负面推文相对应的左侧人口更多(60%的推文),这使得使用仇恨言论的推文在情绪上是负面的。
仇恨言论按复合情绪评分
现在我们呈现十大最可恶的推文:
**
十大最可恶的推文
在被归类为仇恨言论的 232 条推文中,上述推文的仇恨得分最高,第 10 条推文的仇恨得分为 0.676,第 1 条推文的仇恨得分为 0.870。从一般的人工分析来看,我们看到这些推文被攻击性的词语占据,如推文编号[4]。该模型被训练为通过关注仇恨词汇来克服攻击性语言和仇恨言论之间的细微界限。仇恨最主要的方面是种族。10 条最可恶的推文中有 8 条提到了白人,使用了像白人女权主义者、美国白人种族主义者、白人、白人民族主义、欧洲白人血统、白人男性和白人男孩俱乐部这样的词语。第[2]条推文表达了对穆斯林的仇恨,称他们的宗教过时、性别歧视、愚蠢、而第[7]条和第8条推文提到了犹太人。第 6 条推特是带有种族主义动机的仇恨言论,指的是黑人使用俚语词 niggas。
同样,我们也展示最具攻击性的推文:
**
十大最具攻击性的推文
*冒犯性语言评分在榜单中占据主导地位,因为第一条推文的评分从 96.9%到 98.9%不等。只有第 10 条推文提到了伊斯兰教,第 5 条推文使用了希伯来语,但没有明确的证据表明提到了犹太教。攻击性的推文中充斥着大量攻击性的词语,如 *bitch,出现在列表中 10 条推文中的 8 条。Tweets [3,5,6]包含强烈的性相关词汇,而只有 tweets [1,2]以比喻的方式使用短语“是我的宗教”。
结论
在清理和预处理步骤之后,数据被提取到 LDA 算法以执行主题建模。这一阶段旨在调查公众关心的与宗教相关的话题,从而调查宗教的多维性是如何在网上讨论中体现的。然后使用 VADER 情绪分析工具对这些推文进行情绪分析,以揭示公众对宗教的情绪,无论是负面、正面、还是中立*。最后,声纳是一种仇恨言论检测工具,用于调查和测量宗教讨论中是否存在仇恨言论和攻击性语言。*
结果显示,与宗教相关的公共讨论最相关的话题是宗教&政治*、宗教&科学、基督教和伊斯兰教。情绪分析显示,公众对宗教的情绪存在分歧,42.2% (20'512)的推文被归类为积极的。41.1%(19957 例)为阴性,其余为中性。这些结果可以用来论证现代社会已经接受的世俗化和宗教归属的水平。仇恨言论检测工具提供的证据表明,社交媒体上确实存在以宗教为动机的仇恨言论和攻击性语言。总共有 3802 条推文或 7.83%的数据集包含仇恨言论(232 条推文)或攻击性语言(3570 条推文)。这表明宗教是一个公众意见分歧的领域,可能会在他们的讨论中激发仇恨和攻击性语言。因此,社交媒体平台应该做出更多努力来防止他们的用户在他们的在线讨论中的这种滥用行为。*
谢谢你
参考文献
1布莱博士,Ng,A. Y .,&乔丹,M. I. (2003 年,第 1 期)。潜在狄利克雷分配。(拉弗蒂编辑。)机器学习研究杂志,993–1022。
[2]休顿,C. J .,&吉尔伯特,E. (2014 年)。VADER:基于规则的社交媒体文本情感分析的简约模型。第八届 AAAI 网络日志和社交媒体国际会议。密歇根州:AAAI 出版社。
3t .戴维森、d .瓦姆斯利、m .梅西和 I .韦伯(2017 年)。自动仇恨言论检测和攻击性语言问题。第十一届 AAAI 国际网络和社交媒体会议。蒙特利尔:AAAI 出版社。
重塑我们自己
我从人文学科走向工程的道路
这是一篇长长的、详细的、非常诚实的文章,在这篇文章中,我讲述了挑战我的失败,以及我所做的正确选择,我对此心存感激。这是写给一小群朋友和熟人的自我反省和自我冥想。如果你,一个亲爱的陌生人,在我的作品中找到任何灵感或安慰,我会感到巨大的喜悦和成就感。
我写这封信不是为了让许多人看,而是只为了让你看:因为我们彼此都是对方的听众。
–伊壁鸠鲁
TL;速度三角形定位法(dead reckoning)
没有相关的大学学位背景,在软件工程领域开始职业生涯是具有挑战性的。这当然是一条有回报的道路,但正如我的故事所表明的那样,我们必须有信念,极其努力地工作,每天学习,设定正确的期望,并继续重塑自己,以便在幸运降临时抓住机会。无论我们想做什么样的职业支点,成功的关键是通过不断的学习和大量的试错,找到我们的激情和市场需求之间的甜蜜点。
感谢硅谷,软件工程是 21 世纪最(过分)荣耀的工作之一。每天越来越多的人对进入其他领域的软件感到好奇。
2016 年 4 月开始编程。2020 年 4 月开始软件实习。2020 年 7 月,我正式成为一名初级软件工程师,加入了终身学习者的行列,他们在一个最具活力、不断变化的领域中玩耍和劳作。
这篇博文主要是写给自己的。从我最亲密的朋友那里得到的反馈,我希望它代表了我所面临的所有失败、我所采取的正确行动,以及我在寻求职业成就的过程中所表现出的个性的真诚、坦率的陈述。
如果这篇文章有任何外部动机,那么它将分享我的信念,无论你对什么职业感兴趣,学习如何通过在不熟悉的领域获取知识和学习新技能来重塑我们自己是我们今天应该学习的最重要的技能之一。
换句话说,拥抱你感兴趣的知识,不管你是不是为了学位而学的。
回到原点
我的故事开始于 2006 年秋天,当时我以优异的成绩进入中国福建一所最负盛名的高中。在我所在城市的一年一度的高中入学考试中,我在我的中学排名第一,并且是前 30 名最好的学生之一。我的血液充满了自信,我觉得自己是一个聪明的饼干,注定会变得伟大。
黑客和画家:启发我编程的第一本书之一
大约在这个时候,我在阅读了 Eric S. Raymond 的博客文章的中文翻译,如何成为一名黑客和保罗·格拉厄姆的黑客和画家的几个翻译不好的章节后,对黑客产生了钦佩。Raymond 和 Graham 的作品揭示了黑客的个性和品质,以及黑客社区的精英性质,这与我当时尚未形成的价值观产生了深刻的共鸣。(注:史蒂文·利维的《黑客:计算机革命英雄》是我十几年后才接触到的一本很棒的书。)。
在我高中时已经懂编程的好朋友的鼓励下,我报名参加了高中提供的周末 Pascal 速成班。在一个灾难性的、潮湿的周六早晨,当我走进一个满是蓝色 DOS 屏幕的房间时,我吓坏了。
我生长在一个不允许我花太多时间玩电脑的家庭,那时候我甚至不能用五个手指正确地打字,更不用说使用 DOS 和用一种叫做 Turbo Pascal 的可怕语言写if-else
语句或for-loops
了!更糟糕的是,除了我之外的所有人似乎都能跟上速成班的节奏。
Turbo Pascal 的 DOS 和它的语法让我十年没有编程了(无意冒犯 Pascal!)
出于某种原因,盯着那个蓝色的屏幕,我无法理解计算机是如何思考的。我也不能写下任何一行代码来执行超过一个标准:
program Hello;
begin
writeln ('Hello, world.');
end.
我感到紧张,头上冒汗。老师让我们解决一些更基本的问题,但我的大脑感觉像一锅煮过头的粥。我坐在那里,呆若木鸡,呆若木鸡,而其他所有的学生都在埋头苦读,互相分享他们的兴奋。
到了午休时间,我偷偷溜出教室,回家了。在我所在城市的一些最好的学生中,我觉得自己非常愚蠢。
在接下来的几周里,我尝试了Java
、C
和C++
,这些语言是我表哥为了他在一所大学的计算机科学课程而学习的。然而,每次我都不知道如何在父亲的 Windows 电脑上安装这些语言的软件。我试着在纸上写代码,但即使是最简单的#include <stdio.h>
对我来说也太复杂了,更不用说冗长的Java
。
然后,迟早有一天,我放弃了,并得出结论,我不是编程的料。从那一刻起,编程成了那个尴尬、屈辱的早晨的痛苦回忆,我脆弱的自我不允许承认我没有自己想象的那么聪明。
我是如何开始学习 Python 的
时间快进到 10 年后的 2016 年,我已经获得了德克萨斯 A&M 大学的历史学士学位,并获得了久负盛名的优等成绩和 Phi Beta Kappa 荣誉社团的钥匙。我不知道该如何生活,也不喜欢准备法学院入学考试(LSAT),于是在瑞士圣加仑一所著名的商学院攻读学士学位。
在那里,在那个美丽的瑞士小镇,我进入了一生中最艰难的两年。当我的同学在瑞士联合银行、高盛和麦肯锡等公司面试时,我在瑞士或德国都找不到商业实习机会。事实上,从我发出的众多申请中,我只得到一次面试机会,而公司录用了另一位候选人。
哪儿也不去。卡住了。我知道我错过了什么,但我不知道是什么。在德克萨斯 A&M 成为明星后,我觉得自己在瑞士是个彻头彻尾的失败者。
完全出于运气,我联系到了一位法兰克福的价值投资者,这位校友好心地给了我一些时间和我聊天。我们在 St. Gallen's Altstadt 喝咖啡时进行了愉快的交谈,然而,在此期间,他很快就认定我缺乏在他的基金中担任实习生所需的所有财务和会计知识。
感觉到他敏锐而准确的判断,我绝望地问道:
"我应该学习哪些对你的基金有价值的技能?"
他回答道:
你可以考虑学习 Python 和 编程 进行机器学习。如今,技术也开始进入价值投资领域。”
我觉得我的胃马上打结。当我走回家时,言语无法形容我的沮丧和失望。我当时含着眼泪打电话给我的女朋友,向她抱怨说,我在这个世界上最不想做的事情就是再次学习如何编程,这位投资者毫不夸张地告诉我,我应该学习编程的 Python 。我被打败了,那天很早就上床睡觉了,但却无法入睡。
第二天早上,我仍然心不在焉,我咬咬牙,在网上搜索可以教我Python
的课程。我找到了一些免费资源,设法在我的 Windows 笔记本电脑上安装了Python
,并开始编程。
立刻,我意识到事情有所不同:我没有像和Pascal
、C
或C++
在一起时那样目瞪口呆。文本编辑器中没有神秘的、不可思议的脚本代码。很简单。我的 hello world 程序(用Python2
语法)只有一行:
print "Hello, world."
我内心仍然充满不确定和恐惧,我告诉自己,这一次,我可能真的会带着Python
到达某个地方。这就是我开始编程的真实故事。
多编码遇到深度学习
我想真诚地感谢吉多·范·罗苏姆和所有的核心开发人员,因为他们创造了一种美丽的语言,吸引了我们这些被 T8 吓到的人。
在通过在线书籍艰难地学习 Python和 Coursera 的 Python for Everybody 学习了基本的 Python 语法和一些编程概念后,我对编程有了一些信心。我把我的操作系统从 Windows 换成了 Ubuntu,这是一个流行的 Linux 发行版,作为一种将编码作为一种生活方式的姿态。
我还没有爱上编程。有时候,当我遇到一个我无法理解的新概念时,我从 2006 年开始对电脑的恐惧会再次出现,我必须给自己时间冷静下来,回到电脑屏幕前。
但是对于一个陷入自怜和停滞不前的职业道路的学生来说,编程是一种奇怪的解放。因此,即使是在终端制作一个无用的、错误的基于文本的游戏,对我来说也是一种很好的消遣,让我从枯燥的经济学考试中解脱出来,我必须记住这些考试。
没有任何刻意的目的,我学到了越来越多的东西,比如如何双启动 Ubuntu 和 Windows,如何使用终端和命令行,如何写一个小脚本来从 YouTube 上报废搜索结果,下载 YouTube 视频。我写得越多,编程就变得越有趣。我知道没有人会使用我写的任何程序,但不管怎样,我为它们感到骄傲。
到 2016 年秋天,我经过深思熟虑,决定不在圣加仑完成学业,而是开始在斯德哥尔摩经济学院攻读硕士学位。一方面,我想结束异地恋,另一方面,我希望斯堪的纳维亚能为我停滞不前的职业发展提供机会。
作为我的项目中唯一能够用通用编程语言编写脚本的学生,我越来越深入其中。当我的同学在研究咨询案例时,我在学习如何模块化我的代码的同时,黑进了我的文本编辑器和终端来渲染一个 Hangman 游戏。当我的同学在晚上聚会和社交时,我坐在地下室继续学习在线数学和编程课程。作为一群商科学生中唯一对计算机的魔力有所了解的人,我感到很自豪。
在我的编程之路上,最有影响力的在线课程之一是哈佛的 CS50。(来源: CS50x 在维基媒体共享许可下)
大约在这个时候,我完成了麻省理工的 6.00.1x 和 6.00.2x ,开始做哈佛的 CS50 课程,最终完成了其中 70%的作业。我爱 CS50 和它的人民。直到今天,它仍然是所有在线课程中最好的,我把它推荐给我所有想学习编程的好朋友。
不久之后,我也发现了 Udacity 关于深度学习的新节目。由于不知道什么是深度学习,我报名参加了这个课程,因为它听起来很酷(现在你可以通过像 fast.ai 这样的免费资源学习)。我学习了反向传播、卷积神经网络、图像分类、长短期记忆(LSTM)和生成对抗网络(GAN)。所有这些都不容易,我肯定无法独自完成所有的事情。哇哦!我可以训练一个“神经网络”来识别图像中的数字!
与我最早的编程经历非常相似,我经常对深度学习感到目瞪口呆,但我坚持了下来,因为这个主题很有趣,也因为我认为我没有其他竞争优势。
一次又一次的失败,直到幸运降临
为了更好地消化我的知识,我开始写博客。我很荣幸我写的两篇关于深度学习基础的文章(帖#1 和帖#2 )总共邀请了超过 24 万的浏览量。(注:我从来没有找到时间和精力来完成关于反向传播的第三篇博客。这里有一篇来自 Christoph Olah 的关于反向传播 的惊人的 帖子。
这些小小的成功增强了我的信心,我决定寻找有趣的人工智能初创公司,申请在柏林的产品、营销或 bizdev 实习。在读了林恩·鲁特向工程转型的故事后,我想过申请工程职位,但我退缩了。不管怎样,我联系了当时能找到的所有创业公司。
这个循环又重复了一遍。我不是被拒绝就是被忽视。
我记得我申请的一家初创公司回信说,他们没有适合我的职位,但一个月后我发现他们从圣加仑聘请了另一个我感兴趣的人。这在那一刻伤害了我的自尊心,但事后看来,我从来没有把这些决定放在心上。初创公司往往缺乏大型人力资源团队来消化所有的申请,有时,没有被错误的雇主聘用是一件好事。
在我沮丧的时候,福尔图娜夫人降临在我身上。我联系了莫里茨,一个完全陌生的人,他当时是一家深度学习初创公司 TwentyBN 的产品所有者。那时,我几乎已经放弃了在柏林找实习的机会,只是因为莫里茨的情况与我相似,我想我可以为自己的职业道路寻求一些建议。我点击了他 LinkedIn 个人资料上的按钮,发了一条短信。
一条简单的 LinkedIn 信息改变了我的职业生涯
我不知道这条消息让我得到了一份实习和全职工作,最终允许并鼓励我转向软件开发。(注:2017 年 10 月,在我开始在 TwentyBN 实习之前,我曾短暂地参与了一个开源项目OpenMined,试图获得更多的软件经验。那次经历也让我害怕,因为我不理解 Git、Github、单元测试和 CI/CD。我以工作为借口暂停了它,直到 2020 年 4 月,我成为 TwentyBN 的一名软件实习生。)
对职业道路不满意
我做了两年的产品营销人员,但没有一天我觉得这是我的使命。我接受这份工作是因为我完全相信 TwentyBN 的员工和我们的技术,但我不喜欢社交媒体。我想为公司的成功做出贡献,但从未改变对社交媒体营销的想法。在这个职位上,我没有什么长进,也从未感到满足。
在这段时间里,我经历了一次友好的分手,但还是伤了我的心。而且,我暗暗感到自己的位置在公司里被边缘化了。我的薪水增加了,但在我内心深处,我对自己不能扮演一个更有意义的角色感到沮丧。我在瑞士体验到的那种压抑的感觉似乎又在上升。
虽然我的一部分继续沉迷于一些偶尔晚上的编码会议和书呆子编程语言活动,但我不认为软件对我来说是可能的。我觉得我已经太老了,不能再回到初级职位重新开始。
在我对职业道路不满意的那段时间,我尝试了很多事情,包括为我的公司经营一份名为 Embodied AI 的时事通讯
在工作中,我开始撰写和编辑我们公司的简讯 Embodied AI 。私下里,我开始在一份名为 Plutarch 的时事通讯中把我的阅读清单变成关于领导力的书评和分析。
怀着为我的作品建立声誉的愿望,我开始尝试并试图吸引人们注册这两份时事通讯。我尝试了各种营销渠道,被多个 Reddit 子网站封杀,最终为 Embodied AI 管理了大约 500 名订户,为我的个人通讯管理了大约 100 名订户。
就我自己而言,我采纳了朋友克里斯的建议,克服了我对健身房的恐惧,开始尝试举重和健美操,这完全超出了我的舒适区。
健身给了我多巴胺和睾丸激素。但是我的通讯尝试没有给我带来满足感。在将近一年的时间里,我继续进行了各种各样的小型实验。然而,我对职业的不满仍在继续。
转行不嫌老
2019 年底,我对工作的长期不满表现为一场存在主义危机(2020 年的冠状病毒加剧了这一危机)。
我得出了一个严峻的结论:如果我再继续做 10 年的产品营销,我会恨自己没有采取任何行动。
我脑海中的这个声音再次暗示了软件。
早在 2018 年,我就想向 TwentyBN 申请深度学习工程实习生的实习机会,但我缺乏信心,无法晋级。到 2019 年底,我从熟人那里听到了足够多的成功故事,他们在训练营后找到了软件工作,这让我重新燃起了探索软件工程作为职业生涯的愿望。
在我回中国的圣诞节假期中,我花了整整 3 周的时间和哈佛的 CS50W 一起学习 web 开发,从早上 8 点一直编码到晚上 1 点或 2 点。我想用这种密集的体验来测试自己,看看我是否有能力成为一名程序员,或者这只是一个阶段。学习曲线很陡,防火长城阻止我轻松访问 Google 和 StackOverflow。但是我管理了两个 bug 项目,学到了一些Flask
、Django
、Javascript
和WebSocket
。
黑客新闻上的这个帖子让我相信,我仍然可以转行,而且我还不算太老
在这三周里,最具变革性的是,在将近 14 年的时间里,我第一次感觉到自己又回到了第九区。我全神贯注于编程。一整天我都在思考如何解决这些项目和问题。我甚至做了 2-3 个梦,在梦里我找到了代码的解决方案。
编程比产品营销更适合我。从本质上来说,市场营销是一项非常困难的工作。病毒营销和增长营销是研究得很透彻的话题,但没有人能 100%肯定地说,一个产品或一家公司的成功是否是由某个单一的策略或行动造成的。
然而,编程是致命的逻辑。我被它迷住了,因为我喜欢这种即时的满足感,因为有时,即使一行代码的改变也会导致巨大的视觉差异。当我最终调试了我的代码并巩固了我的学习成果时,虽然有时单调乏味和令人沮丧,但也给了我巨大的回报。这比我过去两年做的好多了!
最后,在那几周我工作非常努力,直到我从中国回到柏林才听说了 COVID19。
回到工作岗位后,我认为自己还不算太老,不适合尝试软件工程。我成功说服了我的老板 Moritz、我的 Python 团队领导以及我的 CTO Ingo 给了我三个月的带薪实习。又是一个不眠之夜,无数次的头痛。减薪是可以控制的,但是我对没有成功的紧张和我的冒名顶替综合症给我的心灵增加了很多压力。
然而,到现在为止,我的编程经验教会了我什么是我的学习模式,我对自己也变得更有耐心了。我稳步学习,解决门票,寻求帮助,最终,实习变成了一个新的全职职位。
重塑我们的“自我”
有一个无条件支持我的家人和好朋友帮助了我。有重视教育并在我最糟糕的时候慷慨支持我的父母帮助了我。接受一个陌生人的建议很有帮助。学过编程和深度学习有帮助。学过历史专业并有良好的写作技巧对此有所帮助。与我公司的管理层和同事们志趣相投,这帮助了我。所有这些帮助都是必要的。
但同样重要的是,我还必须感谢福尔图娜夫人,是她把我塑造成了这样一个人,他有学习新的、看似令人畏惧的技能的动力,用自律和坚韧重塑自我。如果没有这种不断学习的习惯,我不可能取得我想要的成就。
您可能已经知道,我作为软件学徒的学习之旅才刚刚开始。软件工程是一个充满活力的领域,有许多有才华的人和优秀的想法。我仍在学习如何编写好的软件,以及如何跨多个团队工作。
这是我日复一日工作的一群了不起的人
四月,我重新联系上了开源项目 OpenMined 的创始人。我开始再次贡献我有限的能力,以便让自己更多地接触其他编程语言,磨练我作为开发人员的整体技能。这并不容易,但 OpenMined 社区是一个了不起的团体。
此外,我必须弥补一些知识缺口,比如架构设计、模式设计,以及众所周知的算法和数据结构。我很清楚这些差距,并将继续努力。毕竟我报了一个只有继续学习才有效果的职业。
拉芬
我们中的大多数人不会有像火箭一样一帆风顺的职业生涯。我们大多数人注定会在生活中的某个时刻遭遇职业僵局。我们大多数人都有能力做些什么。
对我来说,那包括了近十年的转专业和思考我会对哪一行工作充满热情。
在我穿越美国和欧洲的旅途中,每一站都要面对挫折和拒绝。这是我人生中第一次没有通过工商管理专业的考试和两门考试。这包括对我的职业道路不满两年。
但就像狄更斯写的那样,这是最坏的时代,但也是最好的时代。感谢所有现在或曾经在我生命中的人,我活了下来。失败挑战了我对自己优点和缺点的认识,但没有一次失败摧毁了我。
每次我被击倒,我都会哭一会儿,然后站起来,从学习新知识和获得新技能中寻找安慰。没有放弃。
今天我在这里。一个新的旅程刚刚开始,我对我将在旅程中学到的所有令人兴奋的事情感到兴奋。我非常有信心,各种各样的失败和拒绝将继续向我走来。我确信我会有弱点和挫败感的时候。但是我已经经历了很多,我知道我足够强大,足以承受所有这些,并继续重塑我自己和我的生活。
在过去的几年里,我对别人隐瞒了大部分的失败。我的一部分仍然为他们感到羞耻。但我决定把它们写下来,作为自我反省的一种形式。此外,我知道有人正在经历类似的经历。也许这些话会有帮助。
所以给你。这个故事是给你的,我希望,尽管它很长,我的历史能引起你的共鸣或启发你,这样你最终也能重塑你的生活。祝你好运,永不放弃。
欢迎联系我或在 Twitter 上关注我!
星球大战第四集(1977 年)重新制作
一个深度学习管道来重新制作被删除的场景
图片由阿格尼耶斯卡·科瓦尔茨克在 Unsplash 上拍摄
TLDR
这是模型的输出。左边是重制输出。右为原创视频。
用于训练和跑步推理的完整 Jupyter 笔记本可在 Github 上获得
被删除场景的新希望
我是《星球大战》的超级粉丝。和许多星战迷一样,我也迷上了卡通频道和迪士尼+的《星球大战:克隆人战争》。这是一场非凡的演出。
但是当我看旧的东西时,我总是对视频质量的下降感到恼火。例如,这里是从《星球大战:第四集:新的希望》(1977)中删除的场景。这是第一部被创作出来的星球大战。
视频由马塞洛·祖尼加
这些奇怪的黑色眼镜不断出现。难怪这些是被删除的场景。
显然那些奇怪的规格被称为提示符号。它们是胶片上划痕留下的痕迹。《星球大战》是一部很棒的剧集,但它也很古老。
深度学习最近被用于视频恢复。结果非常有希望。例如,Deoldify 允许用户给旧视频和图像着色。 NVIDIA 的 Noise2Noise model 可以让人们将旧图像恢复到曾经的辉煌。
但到目前为止,据我所知,还没有什么东西能专门去除旧胶片上的“记号”和粒状斑点。所以让我们来建造它吧!
创建数据集
创建数据集很棘手,但仍然可行。我是这么做的。我从 youtube 上下载了高质量的视频。然后我毁了他们。我添加了黑色眼镜,降低了视频的分辨率。Ffmpeg 在这方面非常有用。
首先,我们将下载视频。
youtube-dl --format best -o seinfeld.mp4 [https://www.youtube.com/watch?v=nEAO60ON7yo](https://www.youtube.com/watch?v=nEAO60ON7yo)
我在用这个视频。我用的是《T2》中宋飞的一个片段。为什么不呢?
视频由系列制作
那我们就要毁了它。为了做到这一点,我从 youtube 上下载了一个颗粒状的电影叠加。然后我用 ffmpeg 叠加视频,混合设置为柔光。找到正确的混合设置需要大量的试验和错误。ffmpeg 文档没有很多例子。
现在我们有两个视频。一个质量很好,另一个质量很差。
作者提供的视频
作者提供的视频
现在我们将从每个视频中提取帧。最初,我采用了一种天真的方法来做这件事。我会在 python 中浏览视频并单独抓取每一帧。但这花了太长时间。我最终意识到,我们可以在这里使用多处理来真正加快速度。这是根据海登·福尔克的剧本改编的。
太好了。现在我们有两个数据集。一个劣质图像(取自受损视频)和一个优质图像(取自高质量视频)。为了让这些垃圾图片更垃圾,我会缩小它们(虽然这不是必要的步骤)。
def resize_one(img, size): targ_sz = resize_to(img, size, use_min = True)
img = img.resize(targ_sz, resample = PIL.Image.BILINEAR).convert('RGB')
return img
这就是现在蹩脚的正常图像的样子。旁注:这是《宋飞正传》中一个很棒的场景。
作者图片
作者图片
快速检查显示,我们有大约10014
个文件的数据集。非常好。
神经网络
让我们通过使用转换来充分利用这些10014
文件。
我添加了水平和垂直翻转,缩放变化,灯光变化和旋转变化。使用 Fastai,这真的很容易做到。
以下是一些图像转换。
作者图片
还不错!
我们将在这些数据上使用 fastai 和 jason antic 首创的 NoGAN 网络。这个代码的灵感来自 fastai 课程的第 7 课。
我在 google colab 的免费 GPU 上训练了这个模型。他们是一个伟大的资源,我不能相信他们是免费的。
培养
fastai 推荐的有趣的事情是逐渐增加你的图片的尺寸。
因此,首先,你在小尺寸图像上训练,然后你升级你的图像,在大图像上再训练。这会节省你很多时间。相当聪明。
首先,我们将在大小为 128x128 的图像上进行训练。因为图像太小了,我可以把批量增加到 64 张。
我为此选择了一个1e-2
的学习率。我想要一些有攻击性的东西,但仍然是安全的爆炸。这已经被证明非常有用。
作者图片
网络将在训练期间打印结果。输入在左边,预测在中间,目标在右边。结果看起来很有希望!
作者图片
我调整了尺寸,再次训练。再一次。每次我把尺寸调整得比以前稍微大一点。我将视频帧的尺寸从 128x128 改为 480x480。
作者图片
这是最后一班火车。为此我使用了pct_start = 0.3
。我想在培训期间减少 70%的学习时间。在微调模型时,我更喜欢较低的学习率。这次训练的结果看起来非常好。
作者图片
推论:适用于星球大战
一旦这个网络训练完毕,我就进行推理。这比我原先想的要复杂得多。
我必须下载星球大战删除的场景(使用 youtube-dl ),然后提取这个视频中的所有帧。我提取帧使用相同的方法之前。
作者图片
然后我不得不在视频的每一个单独的帧上运行来自学习者的推断。那需要很长时间。
我在这里添加了一些黑客。
首先,我添加了渲染因子。这是从解密中截取的。这个想法是,我缩小图像,并将其转换为一个正方形。然后我对那张图片进行推理。该模型更容易接受正方形的图像。这已经被显示为大大减少了“故障”。
在正方形图像上运行推理后,我将它转换回原始形状。我发现这可以减少故障,通常会导致更平滑的视频输出。我将render_factor
设置为40
,虽然如果我们想要更高的分辨率输出,它可以更高。不过,我可能需要更大的内存。
第二,我调节亮度。这不是真正的黑客。似乎更像是一个错误,我是正确的手动。出于某种原因,模型推断导致图像亮度非常低。
我怀疑这与我们之前用于 ffmpeg 的softlight
过滤器有关。但是我必须在这里手动更正。我需要进一步调查此事。
第三,我使用 matplotlib 的保存功能。我发现 fastai 的保存图像功能给了我非常奇怪的结果(Luke 的衣服是荧光蓝色和红色)。但是奇怪的是,matplotlib 的保存功能给了我很好的结果。我需要调查这件事。我怀疑我可能会损失图像的质量,因为我正在使用 matplotlib 的savefig
功能。
这是模型的一些输出。
作者提供的图片
作者图片
作者图片
然后我不得不把所有这些画面拼接在一起,制作一个视频。为了做到这一点,我最初使用 ffmpeg,但我结束了我的 RAM 超载。相反,我用了 opencv2 的VideoWriter
。
这是最终的输出。
作者提供的视频
和原始视频
视频由马塞洛·祖尼加
丰富
- 天空需要更多的工作。但是我喜欢背景的活力。这是一个有趣的(完全没有计划的)效果。目标是从视频中删除“提示标记”(恼人的黑色规格)。我认为在这方面已经做得很好了——但是还有更多的事情要做。
我喜欢网络是如何强化了阳光的。当比格斯说他要加入反抗军时,卢克和比格斯之间的场景完全改变了。
原始帧(左)。网络输出(右侧)
2.在22
秒标记周围出现了一条奇怪的横条线。我没有在训练集中添加任何水平条,所以完全可以理解网络根本没有删除它。但是在未来,我需要在我的训练集中增加更多的单杠来解决这些问题。
3.我也在考虑对视频做更多的超分辨率处理。高质量地展示一个年轻的卢克·天行者会很不错。为了做到这一点,我可以在进一步训练之前调整图像的大小。我已经缩小了图像,但我还可以进一步缩小。
或者,为了实现 superres,我可能会使用现成的升级工具,比如 VapourSynth 。这可能是最好的选择,因为原始视频的质量已经很差。
4.推论也是一个问题。它会导致内存过载和崩溃。结果是,42
秒是我在这个视频中能得到的最长时间。我不完全确定如何解决这个问题。但是如果我要进一步使用它,我需要解决它。
这么多事要做!
完整代码可从 Github 获得
原载于 2020 年 6 月 19 日https://spiyer 99 . github . io。
远程数据科学团队
提高远程团队效率和效力的 5 个关键
由于降低新冠肺炎传播的努力,绝大多数数据科学团队现在都在远程工作。
不幸的是,许多团队不习惯远程工作,因此不知道在远程数据科学团队工作时需要考虑的挑战。
最重要的是——团队需要使用充分理解和沟通的流程!因此,如果需要,请查看www.datascienceprocess.com获取数据科学特定流程培训的帮助。
有了定义良好的流程,并关注下面概述的 5 个关键点,团队可以有效地提供所需的可操作的洞察力。
1:考虑多变的工作环境
与工作环境相比,有些人的家庭工作环境效率较低(例如,家里有孩子)。考虑到这一点,为了实现同步协调,需要平衡人们在“正常”时间工作的部分时间与人们在最适合他们的时间工作的灵活性..
对一些人来说,在家工作时很难被激励(因为有无数的可能分心的事物)。因此,某种结构——就预期的可交付成果和沟通而言,可以帮助团队成员保持专注。
3:关注项目协调
为了帮助确保一个项目能够得到有效的协调,需要有效地确定任务的优先次序、分工并分享成果。
- 确定任务的优先顺序:直观地传达任务的优先顺序(例如看板)有助于确保团队在最重要的任务上保持一致,并有助于保持项目发起人/利益相关者/产品所有者的参与。
- 划分工作:团队应该确保每个人都了解如何在数据科学团队中有效地划分工作,以及如何在团队中有效地整合工作。
- **分享结果:**分享在执行任务时获得的知识,通常需要的不仅仅是分享生成的代码或解释生成的可视化效果,还需要分享生成的更高层次的见解(如发现不应进一步探究的死胡同)
4:促进讨论和交流
当数据科学团队远程工作时,有些事情,比如能够走过去和某人交谈,是不可能的。团队可以复制这些类型的交互,但这些交互需要更多的思考,因为在远程工作之前,它们可能不是团队当前文化和常规的一部分。因此,团队应该:
- 组织团队沟通:同步更新很重要(例如,每天的单口相声对远程团队非常有效)。但是正在进行的讨论也很重要,也需要被促进(例如,通过 slack 的异步讨论)
- 继续集思广益:集思广益是数据科学项目的一个重要方面,但当每个人都远程时,很容易被忽视,因此需要鼓励团队在每个人都远程时进行集思广益(例如,潜在的可行见解、潜在的新数据源)。利用所需远程工作的一种方法是,例如,在会议之前使用异步投票,以获得一些最初的头脑风暴想法,然后可以进行讨论。虽然这种方法(以及其他方法)对于同处一地的团队也是可行的,但是由于团队成员可能会脱离,因此更加有意识地思考如何让团队参与进来会给远程团队带来更多好处。
5:不要忘记团队文化
由于每个人都很疏远,很难保持团队文化(态度、社区等),在这种情况下,随着一切的进行,团队很容易疏远,团队文化也很容易消失。因此,应该付出额外的努力来帮助确保积极的文化,团队应该明确地决定重要的文化问题(可能会被隐含地决定),例如:
- 一天中应该有多少时间是同步 vs 异步?
- 工作日需要多少重叠?
有关其他数据科学项目管理的见解,请查看www.datascience-pm.com。最后,为了帮助团队建设,我最近启动了远程欢乐时光(每个人都带着自己喜欢的饮料参加视频会议,在会上人们讨论与工作无关的事情)。
远程开发变得简单
图片来自 Unsplash 上的 @domenicoloia 。
PyCharm 提示和技巧
对我来说,PyCharm 中的< 5 minutes!
Configure once, then connect each time! Image created by the author.
P ycharm 是一个很棒的 IDE——拥有促进有效编程的特性,一个致力于分享聪明的插件的社区,以及我最喜欢的特点专业许可证对学生免费。有了它, JetBrains toolbox 及其许多 ide(一种最现代的计算语言)可供学生免费使用(没有任何附加条件)。好样的,脑残!对学生免费是更多产品应该拥抱的服务。
至此,让我们进入正题——通过 PyCharm 远程工作。
随着冠状病毒成为国际关注的焦点,很大一部分专业人士必须远程工作(包括我自己)。随着我设置一台 iMac(即本地机器)与运行 Ubuntu 的 PC(即远程主机)同步工作,下一步就是配置 PyCharm 在本地编辑,远程运行。这样做有很多原因——我的动机是用 GPU 将作业部署到远程主机。这不是我第一次经历这个过程,每次都要回忆。我认为这值得做笔记并在媒体上分享。尽情享受吧!
注: 以下步骤描述了使用 JetBrain 的 PyCharm 进行远程设置。然而,对于所有 JetBrain 产品(例如,【web storm】、【IntelliJ】以及作为 JetBrains 一部分的其他产品)来说,这是相同的过程。
设置远程主机
通过 PyCharm 的部署工具设置远程主机非常简单(也就是说,PyCharm 提供的大多数特性都是如此)。对此,几句话就够了。尽管如此,在本教程中准备了详细的步骤,以确保清晰。我们开始吧!
具体来说,我们的目标是建立一个 SFTP 连接,一个运行在 SSH 协议上的安全文件传输模式。为此,我们必须知道以下几点。
- 通过ifconfigbash 命令可以访问主机的 IP 地址。
- 主机上的用户名(在(1)中相应的 IP 地址上)
- 密码或一个 SSH 密钥(为了简单起见,这里将使用密码——未来的博客可能在 SSH 密钥上)。
现在,有了 1–3 的知识,我们在本地机器上配置 PyCharm。
从这里开始,gif 值 1000 个单词:
从菜单栏的 工具 *中打开 配置… *。作者创造的形象。
随着展开窗口打开:
创建新的 SFTP 连接。作者创造的形象。
设置配置(即,参见上面的 1–3)。作者创造的形象。
将映射设置为主机上项目的根目录。注意远程浏览器(左)用绿色突出显示映射的文件(即,相同名称的文件,相对于映射根,被假定为映射)-由作者创建的图像。
通过最底部的工具面板查看远程主机,其中保存的更改被确认传输到主机—作者创建的图像。
N ow,修改可以自动上传,如下图所示。
设置 【自动上传(总是) 【开】 —图片由作者创作。
N 注意,现在*自动上传(总是)*选项被取消。
自动上传截图(总是) 切换“开” —图片由作者创作。
答或者,手动处理同步有多种方式。
浏览远程主机并右键单击要同步的文件(无论是与主机同步还是从主机同步)。请注意,上面截图中显示的复选标记不再显示——图片由作者创建。
瞧啊。就这样,我们都被设置为远程工作!
概括起来
免责声明。 Pycharm 是 2016 年从 MATLAB 过渡时最有意义的偏好(即,相似的外观和感觉)。也就是说,还有其他有希望的替代方案,其他人可能会认为更好(例如, Atom 、 Visual Studio 、 Spyder 等等)。参见2020 年 11 个最佳 Python ide根据guru 99——不,我没有选择这个列表仅仅是因为 Pycharm 被列为第一;)在下面的评论中分享你最喜欢的 IDE。
最后一点——我花了很多时间学习 PyCharm,因为它是我日常使用的工具。那么,了解一种提高生产率的新手段是否值得呢?它不仅值得,而且势在必行——vim、Emacs 等等。,非常适合快速访问远程文件;然而,现在是 2020 年,人们,让我们利用我们所掌握的技术;)
旁注
像 PyCharm 这样的工具隐藏了许多基本概念:初级研究人员不会为了节省几分钟的时间而损害深刻的理解。不要学习 PyCharm 的来龙去脉,除非知道 Python 的基础知识,并且正在并行理解一个中级知识。否则,总有一天,像 PyCharm 这样强大的图形界面不是一个选择。一个人必须能够执行 still(相信我,如果这对你来说不明显,那么这意味着你可能应该学习构建 python 项目和系统路径的基础)。这里列出了其他一些值得一读的博客:
- 如何构建一个 Python 项目,作者米沙·贝里恩。
- Jeff Hale撰写的《成功建立 Python 项目的 10 个步骤。
- 千篇一律的学习和发展——过去对我来说很有效。
有大量关于上述主题的信息。因此,如果你寻找的答案不在一个或多个参考文献中,那么评论和链接会被提供。如果没有链接,那么将创建一个博客——童子军的荣誉。
我希望这有所帮助。对这个或未来应该涉及的话题提出意见、建议或问题!如果有什么特别好的地方(例如,gif 相对于文本和图像的使用)或不好的地方(例如,细节太少),请让我知道,以便更新它,并让我在构建未来的博客时考虑。
感谢您的阅读:)
在 LinkedIn 、 Twitter 、脸书上关注罗宾逊博士
Joseph P. Robinson 在 Vicarious Surgical 从事外科机器人研究……Robinson 博士获得了东北大学电气和计算机工程学士学位(2014 年)和计算机工程博士学位(2020 年)。
www.jrobsvision.com。](https://www.jrobsvision.com/)
阅读更多由约瑟夫·罗宾逊博士在媒体上发表的文章
个人最喜欢的一句俏皮话
towardsdatascience.com](/pandas-tips-tricks-need-for-speed-54e217cc6aa0) [## 对图像数据集进行重复数据删除的绝佳方式
生产中的命令行工具
towardsdatascience.com](/a-great-tool-for-image-datasets-cb249663ca45) [## 减少杂乱,适应空间
变得有条理、高效甚至舒适的 3 个技巧
jvision.medium.com](https://jvision.medium.com/reduce-the-clutter-adapt-the-space-6daeef2e2ca9)
远程工作——新标准?
数据驱动分析,更好地了解远程工作
我们真的需要去办公室吗?(照片由阿维·理查兹在 Unsplash 上拍摄)
我花了三个月远程工作。可能还会持续好几个月。我以为我会讨厌它。但是……不一样!谷歌宣布了 2020 年剩余时间的在家工作政策。脸书采取了类似的政策。Twitter 告诉其员工他们可以无限期地继续远程工作。在我们生活的时代,阻止病毒的唯一方法是在我们的生活中嵌入社交距离。大多数员工最近都开始在某种程度上远程工作。在家工作可以让员工更快乐,并为员工和雇主省钱。远程工作是新的标准吗?
人们可能会有关于远程工作的紧迫问题,以及有什么比揭示数据告诉我们什么更好的方式来回答这些问题。所以我找到了 2019 年由 Stack Overflow 进行的年度开发者调查的公开数据,其中包括大约 88K 开发者的回复。因此,这里的背景基本上与在软件/IT/数据科学行业工作的人相关。以下是我在数据中发现的一些有趣的事实。
远程工作的开发人员对工作更满意吗?
对我来说,这是最重要的问题,要了解远程工作的人对他们的工作有多满意。
工作满意度分布
事实上,大多数全职远程员工对他们的工作非常/稍微满意!从非远程员工到全职远程员工,非常满意的员工有明显增加的趋势。此外,我将这些回答转换为 5 分制的李克特量表,得出平均工作满意度分数。远程工作文化对工作满意度有很强的正相关性。
工作满意度得分上升趋势
因此,有了在任何地方工作的灵活性,开发人员似乎对他们的工作更满意了!我们真的需要去办公室吗?
远程工作者挣得多吗?
由于全球疫情,全球大部分地区的员工都被降薪,因此在做出任何决定之前了解收入情况非常重要。让我们比较一下远程工作的开发人员和其他人的工资水平。
开发人员的平均年薪
有趣的发现是,可以在去办公室和远程工作之间做出选择的员工平均收入最高。远程工作者的收入明显高于他们的同事。
远程工作面临的最常见挑战是什么?
我们的发现告诉我们,远程工作实际上更好——但肯定会有一些相关的挑战。在我远程工作的几个月里,我确实遇到了一些问题,但是像往常一样,我们不要做任何假设,而是看看我们的数据告诉我们什么。
远程工作面临的挑战
远程工作面临的最常见的三大挑战是会议、分散注意力的工作环境和非工作任务。非工作承诺包括必须照看孩子和做家务。我当然更喜欢面对面的会议,在家里会感到心烦意乱。然而,随着各种视频会议工具及其功能的日益流行,分析下一年的年度调查将会很有意思。
远程工作在什么类型的组织中受欢迎?
到目前为止,如果你已经下定决心要找一份远程工作,让我们问一下数据,你应该寻找哪种类型的组织。
当我们分析数据时,我们意识到远程工作文化在小型组织中很普遍。相当比例(大约 70%)的远程工作者在员工少于 100 人的组织中工作。所以你远程工作的最佳选择是加入一个小组织或者自己创业!
这里的发现是观察性的,是我从数据中发现的,不是正式研究的结果。所以真正的问题仍然是:
远程工作——新标准?
如果你已经走了这么远,谢谢你的阅读。我上面所做的是巧妙地应用了 CRISP-DM ,这是一种处理数据科学问题的流行方法。让我们来揭示这个简单的方法是如何应用到这个项目中的。结束时,你也可以开始应用它了!
乌达城的描述性图片
- 业务理解—当我开始远程工作时,我想了解与此相关的几个因素,这促使我提出这些问题。大多数数据科学问题源于一系列基本问题,首先识别这些问题至关重要。
- 数据理解—查找或收集可以回答您的业务问题的数据。我怎么强调花足够的时间从里到外理解数据都不为过。这对以下所有步骤的帮助比你想象的要大。
- 数据准备——从来没有现成的原始数据可供使用。虽然堆栈溢出为我们提供了基本的数据清理,处理异常值,丢失值,分类值是强制性的。
- 分析/建模——探索性数据分析足以回答我们的问题。然而,一些复杂的问题可能需要进一步建模,以获得预测洞察力。
- 评估—可以使用几种统计测试来评估和获得结果。在建模的情况下,评估指标通常用于评估所提议的解决方案的性能。
- 部署——一些问题需要部署某种产品,而另一些问题需要将洞察力传达给利益相关者*(这正是这篇博客所做的!).从现在起,也许我会对全职远程角色更加开放?*
这篇博客有意省略了包括代码在内的复杂而详细的分析,把它们留给了 GitHub 库,如果你需要进一步理解的话。您是否从远程工作的数据中发现了其他有趣的见解?或者这已经说服你去尝试远程工作了?我很乐意听到各种反馈!
从时间序列数据中移除非线性趋势
有时需要从时间序列数据中移除趋势,为后续步骤做准备,或者作为数据清理过程的一部分。如果你能确定一个趋势,然后简单地从数据中减去它,结果就是去趋势数据。
如果趋势是线性的,你可以通过线性回归找到它。但是如果趋势不是线性的呢?一会儿我们会看看对此我们能做些什么。
但是首先,简单的例子。
线性趋势
以下是有趋势的时间序列数据:
https://raw . githubusercontent . com/FlorinAndrei/misc/master/qdata . CSV
让我们加载它,看看它看起来像什么:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error, r2_scoreser = pd.read_csv('qdata.csv', index_col=0, squeeze=True)
serx
0 473.917764
1 75.324825
2 -306.969479
3 53.271476
4 372.966686
...
95 4650.550473
96 4604.573344
97 4891.704638
98 5265.948162
99 5618.909339
Name: y, Length: 100, dtype: float64plt.plot(ser)
plt.show()
好吧,这是一个趋势。让我们假设它是线性的——让我们进行线性回归并找出答案。这是线性回归的直接应用。上面导入的 sklearn 库有我们做回归所需的一切。
X = ser.index
X = np.reshape(X, (len(X), 1))
y = ser.valuesmodel = LinearRegression()
model.fit(X, y)
trend = model.predict(X)plt.plot(y)
plt.plot(trend)
plt.legend(['data', 'trend'])
plt.show()
似乎很合适,但可能不太合适。让我们从数据中减去趋势,看看去趋势后的数据是什么样的:
detr = [y[i] - trend[i] for i in range(0, len(y))]
plt.plot(detr)
plt.title('data detrended in a linear fashion')
plt.show()
不太有说服力。数据中仍有一个凹趋势。或许最初的趋势并不是线性的。
让我们计算数据和我们提取的趋势之间的 RMSE 和 R 值。我们稍后将回到这些数字。
r2 = r2_score(y, trend)
rmse = np.sqrt(mean_squared_error(y, trend))
print('r2:', r2)
print('rmse', rmse)
r2: 0.8782399672701933
rmse 553.6078593008505
多项式瞧
如果趋势不是线性的,我们可以尝试用多项式曲线来拟合。但是事情是这样的:即使我们拟合的曲线是一个高次多项式,它仍然是线性回归,将被用来找到它。怎么会这样
好吧,考虑这个二次表达式:
y = a + bx + cx
我们寻找的值是 a、b 和 c,它们都是线性的(1 的幂)。忘了 x 的幂,我们看的是 a,b,c 的幂,还记得为什么广义线性模型叫“线性”吗?因为系数是线性的,所以 x 值可以有不同的幂。
所以是线性回归——只是碰巧我们必须一次做多维的线性回归。
让我们假设我们的数据有一个二次趋势。然后我们需要将 X 转换成二次形式:
pf = PolynomialFeatures(degree=2)
Xp = pf.fit_transform(X)
Xp
看起来像这样:
array([[1.000e+00, 0.000e+00, 0.000e+00],
[1.000e+00, 1.000e+00, 1.000e+00],
[1.000e+00, 2.000e+00, 4.000e+00],
[1.000e+00, 3.000e+00, 9.000e+00],
[1.000e+00, 4.000e+00, 1.600e+01],
[1.000e+00, 5.000e+00, 2.500e+01],
[1.000e+00, 6.000e+00, 3.600e+01],
...
[1.000e+00, 9.600e+01, 9.216e+03],
[1.000e+00, 9.700e+01, 9.409e+03],
[1.000e+00, 9.800e+01, 9.604e+03],
[1.000e+00, 9.900e+01, 9.801e+03]])
第一列是 X 的 0 次幂。第二列是 X。第三列是 X 的 2 次方。这就好比上图所示的二次表达式(y = a + bx + cx)。
现在,我们将使用二次形式来拟合数据,并生成二次趋势。使用线性回归找到二次表达式的参数。
md2 = LinearRegression()
md2.fit(Xp, y)
trendp = md2.predict(Xp)
趋势是什么样的?
plt.plot(X, y)
plt.plot(X, trendp)
plt.legend(['data', 'polynomial trend'])
plt.show()
很合身,不是吗?现在让我们看看去趋势数据:
detrpoly = [y[i] - trendp[i] for i in range(0, len(y))]
plt.plot(X, detrpoly)
plt.title('polynomially detrended data')
plt.show()
这显然更好。那里没有留下任何可以视觉识别的趋势。但是让我们看看数字是怎么说的:
r2 = r2_score(y, trendp)
rmse = np.sqrt(mean_squared_error(y, trendp))
print('r2:', r2)
print('rmse', rmse)
r2: 0.9343217231542871
rmse 406.5937924291518
与线性趋势相比,多项式趋势 R 增加,RMSE 减少。两者都是好的改变。两个平均多项式比线性拟合更好。
高次多项式
您可以选择任意阶的多项式,只需在此处为 N 指定不同的值:
pf = PolynomialFeatures(degree=N)
一般来说,使用较低的 N 值。如果 N 值增加,但变化不大,则返回较小的值。
有一个弯曲的曲线可能可以用二次函数来描述。有两个弯曲的曲线可以用三次函数来描述。诸如此类。N-1 次弯曲需要一个 n 次幂的表达式。
如果你增加 N 很多,最终你的“最佳拟合”曲线将开始跟随数据中的噪声,而不是拟合趋势。你过度拟合了曲线,现在已经没有意义了。要么减少 N,要么增加更多的数据点。
移除 ML 操作中的“墙”
ML Ops 试图为机器学习提供一个持续改进的过程
越来越多的团队正在寻求采用一种叫做 ML Ops 的方法。ML Ops 得名于十年前出现的 DevOps 运动,它试图为机器学习提供一个持续改进的过程。随着 Dev Ops 现在被早期采用者相当好地建立起来,并且它所提供的商业价值的证据变得越来越清晰,将 DevOps 的解决方案直接应用到机器学习团队是很有诱惑力的。
然而,为了成功实施这种方法,有必要了解开发运维服务早期的经验教训以及它试图解决的问题的性质。
在 DevOps 之前——“墙”
在 DevOps 运动之前,开发传统上由开发团队组成,在将大的包中的变更交付给运营团队进行测试和部署之前,开发团队独立地处理特性。
这两个团队是自我隔离的,拥有不同的目标和技能集;开发团队致力于开发新的特性,而运营团队致力于提高系统的整体性能。
将团队想象成具有不同目标和活动的独立实体,在他们之间建立了一堵隐喻墙,阻止每个人理解另一个团队的挫折和障碍。你看不到的,你无法理解或寻求补救。
是什么促成了 DevOps
为了转变这种方法,实现我们称为 DevOps 的更具凝聚力的运营方法,需要改变思维方式。墙的两边都有共同的参照点。尽管在工作实践和技能组合上存在差异,但是两个团队都希望更顺利的部署和发布过程,并希望通过改进的反馈与业务目标更紧密地联系在一起。
在两个团队之间建立这种共同点导致了实践中的变化,DevOps 就是这个变化的同义词。
团队之间的墙的拆除允许更好地理解系统的整体性,以及允许反馈和改进在团队之间容易地传播。用户也从这一变化中受益,因为两个团队的员工现在更能响应他们的需求。
例如,使数据库运行更慢的特性以前会被视为操作问题,但在 DevOps 的思维模式下,它变成了每个人的问题,并被协作解决。
来自 2018 和 2019 的开发运营报告表明,开发运营思维的改变直接提供了可衡量的业务价值,因为它对内部和外部需求给予了同等的重视。这两个团队之间的技能集现在有大量的重叠,开发、测试和生产环境变得几乎相同。
ML 操作的情况
在机器学习领域,目前只有大约 10%的项目真正交付了商业价值,显然有必要进行类似的革命。术语 MLOps 自 2017 年以来才被广泛使用,因此没有像 DevOps 那样得到很好的记录或定义,但本质上,MLOps 的目的是为机器学习提供与 DevOps 对开发和运营同样的价值。
对于我们这些从事机器学习的人来说,我们可能渴望一个和谐的未来,在这个未来,我们将拥有一个全自动的机器学习 CI/CD 系统,拥有多技能的员工,能够理解彼此的需求和目标,并平等对待他们。
更重要的是,我们希望机器学习能够通过快速适应需求来推动业务价值,并快速发现问题。在我们的未来愿景中,一个装备精良的 MLOps 团队应该能够很容易地识别和解决数据/算法/模型中的问题,并通过一个易于使用的 ML 平台快速适应业务需求和数据偏差。
为了达到这个目标,团队需要欣赏 DevOps 所涉及的相互理解之旅,不要试图跳到上面列出的快乐结局。与此同时,还有更大的障碍需要克服,不花时间去理解“墙”的真正本质,直接跳到一个解决方案上,将无法解决根本问题。首先,我们需要识别现有的问题,这样我们就可以避免潜在的陷阱并交付。
通常,在机器学习项目中,需要许多团队和技能。我们可以大致将其分为两组,每组都有不同的需求和目标,就像我们之前将开发人员和运营专家分开一样。
研究人员和数据科学家希望利用企业收集的数据来解决复杂的问题。他们关心的是解决方案的性能,包括诸如精确度和召回率、模型大小或培训成本等指标。
开发人员和工程师更加传统,通常按照我们之前制定的 DevOps 原则工作。他们的主要关注点是吞吐量、减少延迟、降低成本、增强功能等目标。
上面的墙可以以多种不同的形式存在。任何阻碍研究兴趣和开发/运营兴趣之间融合的事情都会造成这堵墙。例如:
进入生产系统
面向工程师的代码分叉/存储库
数据访问/操作
团队之间缺乏信任
沟通障碍
寻找共同点
通常,这两个团队的业务目标是相同的。与 DevOps 一样,两个团队都希望在为业务开发和部署解决方案时减少挫折。也就是说,将更多的时间用于创造商业价值的项目,减少令人沮丧的管理费用。
机器学习的共同点一般归结为两点:数据和代码。
数据
数据是迄今为止最重要的资产,任何试图利用机器学习的公司都需要很好地处理它。整个公司可能会因为他们处理数据的方式而消失。使用数据作为公共基础是一个棘手的过程,通常需要难以理解的单一数据湖或复杂模式。
然而,没有这种统一会在研究团队和工程团队之间建立一堵墙。如果来自生产系统的数据不能容易地以相同的格式流入训练数据,那么完全实现 MLOps 将变得越来越复杂。
密码
类似地,代码库可能会成为一堵墙,威胁到 MLOps 解决方案的进展。将“实时”和“研究”的存储库分开,将存储库分成不同的分支,所有这些都会导致完全采用 MLOps 的问题比它们在短期内解决的问题更多。这在很大程度上归结于研究人员和工程师之间不同的标准。当研究人员需要快速迭代、测试假设和创建最小解时,工程师希望看到健壮的、可伸缩的、经过良好测试和组织的代码。
你必须找到一个公司所有成员都同意的中间立场,这样整个公司的标准才是一致的。这有一个额外的好处,可以减少团队之间的挫折感,因为他们无疑会认为自己的标准比交给他们的代码“更好”。这造成了团队之间的敌意,从而强化了这堵墙。
系统访问
我们经常听说不允许研究人员访问工程资源、参与讨论或访问完整的生产驱动数据。类似地,工程师不能参与概念讨论,也不能访问培训系统,因此在面对已决定的解决方案时,他们也不能接受。最终,这归结为信任。你相信你的员工和团队成员会做正确的事情吗?他们觉得能够在不被斥责或忽视的情况下提问吗?
第一步
我将在以后的文章中更详细地介绍其中的一些,但是现在,我们可以总结一下更容易过渡到 MLOps 所必需的重要步骤。
- 采用开放、统一的元数据层,在整个管道中共享。
- 创建一个普遍认可的标准,并确保团队按照这个标准一起工作。
- 考虑将其他团队的资源嵌入到您的项目中。
- 像信任自己的团队一样信任其他团队成员。
- 利润!(或者,更准确地说,不断改进这一过程……)
在熊猫数据帧中渲染图像
有没有想过在数据帧中渲染图像?我很高兴你这么做了!
照片由 艾米莉·莫特
我能看到 问号(?) 在你的大部分脸上。因为在发现我们也可以在数据帧中渲染图像之前,我也有一个。相信我,这很简单,你所需要知道的就是 创建一个数据框架,然后我会从那里 接你。
要遵循的步骤
- 导入
**pandas**
**HTML**
两个必要的库。 - 创建一个你选择的熊猫数据帧,并存储在变量
**df**
中。 - 创建一个名为
**country**
的列表,然后存储您想要渲染的图像的所有路径。 - 将
**country**
列表分配给现有的数据帧**df**
。这将作为一个新列附加到现有数据帧中。 - 写一个函数,把给定的图片路径转换成 HTML 标签。
- 将 dataframe 呈现为 HTML 表,然后调用 HTML 方法来显示呈现的图像。
奖金
此外,我将向你们展示“ ”保存数据帧为 HTML 页面 ”更像一个网页。
密码
按照上面的步骤 1-6 成功渲染数据帧中的图像。我也将在这里重复这些步骤。不必每次都向上滚动阅读。同样,完整的代码可以在我的 GitHub 资源库 下面找到:
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/Tanu-N-Prabhu/Python/blob/master/Rendering_Images_inside_a_Pandas_DataFrame.ipynb)
导入**pandas**
**HTML**
两个必要的库。
导入**pandas**
库的原因是为了在数据帧中创建和存储数据。类似地,**HTML**
库用于呈现 dataframe 中的图像(HTML 标签)。
**# Importing the necessary libraries**import **pandas** as **pd**
from **IPython.core.display** import **HTML**
不需要使用
**pip**
命令手动安装,只需导入即可******
创建一个你选择的熊猫数据帧,并存储在变量 **df**
中。
这一步很简单,因为几乎每个人都知道如何创建数据帧。如果没有,那么别忘了在这里浏览一下这篇 文章 。我将通过从world ometers . info*获取 COVID19 数据来创建 dataframe。请记住这个数据每小时都在变化。我将制作五个不同的列,如**Total Cases**
**Total Deaths**
**Total Recovered**
**Total Tests**
**Population**
。对于行,我会选择**USA**
**Brazil**
**Russia**
**India**
**Peru**
。*************************
****# Create a dataframe using pandas library**df = pd.**DataFrame**([[2768571, 130655, 1155027, 34713051, 331002277], [1448753, 60632, 790040, 3070447, 212558178], [654405, 9536, 422931, 19852167, 145934619], [605216, 17848, 359891, 8826585, 1379974505], [288477, 9860, 178245, 1699369, 32969875]], **columns** = ['Total Cases', 'Total Deaths', 'Total Recovered', 'Total Tests', 'Population'])**
创建一个名为 **country**
的列表,然后存储你想要渲染的图像(标志)的所有路径。
这一步是显而易见的,为了保持一致,我们将创建一个列表,其中包含上面列出的所有国家的国旗路径。国旗来源可以在这里 找到 。
****# Create a list named country to store all the image paths**country= ['https://www.countries-ofthe-world.com/flags-normal/flag-of-United-States-of-America.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Brazil.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Russia.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-India.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Peru.png']**
将 **country**
列表分配给现有的 **df**
数据帧。这将作为一个新列附加到现有数据帧中。
这是最简单的步骤之一,因为您需要将名为**country**
的列表分配给 dataframe 名为**Country**
的新列。
****# Assigning the new list as a new column of the dataframe**df['Country'] = country**
当你打印数据帧**df**
时这样做。你会得到下面的结果。
塔努·南达·帕布拍摄的照片
编写一个函数,将图片(链接)的给定路径转换成 HTML 标签
这里你需要写一个将链接转换成标签的函数,正如你在前面的结果(Dataframe)中看到的,Country 列有所有的链接,所以这一步是必要的。
****# Converting links to html tags**def **path_to_image_html**(path):
return '<img src="'+ **path** + '" width="60" >'**
该函数的返回类型是传统的**img**
标签,我们用它来呈现网页上的图像。如果你不知道我在说什么请看 这个 。这样做的原因是,如果所有的路径都被转换成图像标签,那么最后在一个内置的 HTML 方法的帮助下,所有这些都将被呈现为图像。
将数据帧渲染为 HTML 表格,然后调用 HTML 方法显示渲染后的图像
我们将使用**to_html**
方法将数据帧转换成 HTML 表格。有一些参数我们需要处理,首先是**escape = False**
,转义 HTML 标签,我们需要调用**path_to_image_html**
方法,将其转换成一个字典,并将其分配给 formatters 内置变量。欲知此法详情,请访问 此处 。
****# Rendering the dataframe as HTML table**df.to_html(escape=False, formatters=dict(Country=path_to_image_html))**
通过执行这个操作,您将得到一个您熟悉的 HTML 表格。下面我将只提供第一个表行快照:
塔努·南达·帕布拍摄的照片
而最后要做的就是调用内置的**HTML**
方法,将整个 dataframe 作为参数传递。
****# Rendering the images in the dataframe using the HTML method.****HTML**(df.to_html(escape=False,formatters=dict(Country=path_to_image_html)))**
最后,当你执行这个,你会得到你想要的。
塔努·南达·帕布拍摄的照片
奖金
正如我所承诺的,我将向你们展示如何将数据帧保存为 HTML 页面。当你想给你的老板或任何人发送大量带有图像的数据帧时,这通常会很有帮助。
****# Saving the dataframe as a webpage**df.**to_html**('webpage.html',escape=False, formatters=dict(Country=path_to_image_html))**
如上所述,你只需要提供保存网页的路径,因为我用的是我的 Google Colab ,它会保存在我的笔记本环境中,打开它你会看到如下所示的结果。
塔努·南达·帕布拍摄的照片
完整代码
本教程的完整代码可以在下面找到:
****# Importing the necessary libraries** import pandas as pd
from IPython.core.display import HTML**# Create a dataframe using pandas library** df = pd.DataFrame([[2768571, 130655, 1155027, 34713051, 331002277],
[1448753, 60632, 790040, 3070447, 212558178],[654405, 9536, 422931, 19852167, 145934619],[605216, 17848, 359891, 8826585, 1379974505],[288477, 9860, 178245, 1699369, 32969875]], columns = ['Total Cases', 'Total Deaths', 'Total Recovered', 'Total Tests', 'Population'])**# Create a list named country to store all the image paths** country = ['https://www.countries-ofthe-world.com/flags-normal/flag-of-United-States-of-America.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Brazil.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Russia.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-India.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Peru.png']**# Assigning the new list as a new column of the dataframe** df['Country'] = country**# Converting links to html tags** def path_to_image_html(path):
return '<img src="'+ path + '" width="60" >'**# Rendering the dataframe as HTML table** df.to_html(escape=False, formatters=dict(Country=path_to_image_html))**# Rendering the images in the dataframe using the HTML method.** HTML(df.to_html(escape=False,formatters=dict(Country=path_to_image_html)))**# Saving the dataframe as a webpage** df.to_html('webpage.html',escape=False, formatters=dict(Country=path_to_image_html))**
写这篇文章的主要灵感来自于这个关于堆栈溢出的论坛。特别感谢chitown 88。
假设我有一个想要导出为 PDF 的数据帧。在数据框中,我有以下几列:代码,名称,价格…
stackoverflow.com](https://stackoverflow.com/questions/53468558/adding-image-to-pandas-dataframe)
谢谢大家,这就是这个教程,我希望你们今天学到了一些新的东西。如果你们对代码有任何意见或担忧,请明智地使用评论部分。敬请关注更多更新,直到那时再见。保持安全和快乐的编码!****
在 Binder 和 Google Colab 上渲染 OpenAI 健身房环境
关于解决一个乏味(但重要)问题的笔记
在 Google Colab 或 Binder 中远程渲染 OpenAI envs 很容易(一旦你知道了配方!).
我目前正在使用我的新冠肺炎强制隔离来扩展我的深度学习技能,完成了来自 Udacity 的 深度强化学习纳米学位 。当在远程服务器上训练时,我几乎立刻就遇到了让我的模拟正确渲染的乏味问题。
特别是,让 OpenAI Gym 环境在远程服务器上正确渲染,比如那些支持流行的免费计算设施的服务器,如 Google Colab 和 Binder 比我预期的更具挑战性。在这篇文章中,我列出了我的解决方案,希望我可以节省其他人的时间和精力来独立解决这个问题。
Google Colab 序言
如果你希望使用 Google Colab,那么这个部分就是为你准备的!否则,您可以跳到活页夹前言的下一节。
安装 X11 系统依赖项
首先,您需要安装必要的 X11 依赖项,特别是 Xvfb ,它是一个可以在没有显示硬件和物理输入设备的机器上运行的 X 服务器。您可以在 Colab 笔记本中安装系统依赖项,方法是在 install 命令前面加上一个感叹号(!
),它将在自己的 Bash shell 中运行该命令。
**!**apt-get install -y xvfb x11-utils
安装其他 Python 依赖项
现在您已经安装了 Xvfb,您需要安装一个 Python 包装器pyvirtualdisplay
,以便在 Python 中与 Xvfb 虚拟显示交互。你还需要为 OpenGL : PyOpenGL 和 PyOpenGL-accelerate 安装 Python 绑定。前者是实际的 Python 绑定,后者是一组可选的 C (Cython)扩展,为 PyOpenGL 3.x 中的常见操作提供加速。
**!**pip install pyvirtualdisplay**==**0.2.* \
PyOpenGL**==**3.1.* \
PyOpenGL-accelerate**==**3.1.*
安装开放式健身房
接下来,你需要安装 OpenAI 健身房包。请注意,根据您感兴趣的健身房环境,您可能需要添加额外的依赖项。因为我要在下面的演示中模拟 LunarLander-v2 环境,所以我需要安装box2d
extra 来启用依赖于 Box2D 物理模拟器的健身房环境。
**!**pip install gym**[**box2d**]==**0.17.*
为了简单起见,我将所有的软件安装步骤收集到一个代码块中,您可以将其剪切并粘贴到您的笔记本中。
%%bash*# install required system dependencies*
apt-get install -y xvfb x11-utils*# install required python dependencies*
pip install gym**[**box2d**]==**0.17.* \
*pyvirtualdisplay***==**0.2.* \
*PyOpenGL***==**3.1.* \
PyOpenGL-accelerate**==**3.1.*
在背景中创建虚拟显示
现在已经安装了所有需要的软件,您可以创建一个虚拟显示器(即在后台运行的显示器),OpenAI Gym Envs 可以连接到该显示器进行渲染。您可以通过确认DISPLAY
环境变量的值还没有被设置来检查当前是否没有显示。
**!***echo* *$DISPLAY*
下面单元格中的代码在背景中创建了一个虚拟显示,您的健身房 env 可以连接到该显示进行渲染。您可以随意调整虚拟缓冲区的size
,但在使用 Xvfb 时必须设置visible=False
。
这个代码只需要在你的笔记本上运行一次就可以开始显示。
使用 pyvirtualdisplay 启动 Xvfb 虚拟显示
在笔记本上运行上述代码后,您可以再次回显环境变量DISPLAY
的值,以确认您现在有一个正在运行的显示。
**!***echo* *$DISPLAY # should now be set to some value*
为了方便起见,我将上述步骤收集到两个单元格中,您可以复制并粘贴到您的 Google Colab 笔记本的顶部。
活页夹序言
如果您希望使用活页夹,那么这一部分就是为您准备的!
不需要额外安装!
不像 Google Colab,使用 Binder 你可以烘焙所有需要的依赖项(包括 X11 系统依赖项!)放入绑定器实例所基于的 Docker 映像中。这些配置文件可以位于 Git repo 的根目录中,也可以位于一个binder
子目录中(这是我的首选)。
binder/apt.txt
需要定义的第一个配置文件是用于安装系统依赖项的apt.txt
文件。您可以创建一个适当命名的文件,然后列出您想要安装的依赖项(每行一个)。经过一段时间的反复试验,我发现了下面的成功组合。
freeglut3-dev
xvfb
x11-utils
binder/environment.yml
第二个配置文件是用于定义 Conda 环境的标准environment.yml
文件。如果你对 Conda 不熟悉,那么我建议你看看我最近写的关于Conda和 使用 Conda 管理特定项目环境的文章。
*name: null channels:
- conda-forge
- defaults dependencies:
- gym-box2d=0.17
- jupyterlab=2.0
- matplotlib=3.2
- pip=20.0
- pip:
- -r file:requirements.txt
- python=3.7
- pyvirtualdisplay=0.2*
binder/requirements.txt
最后需要的配置文件是 Conda 使用的requirements.txt
文件,用于安装任何额外的 Python 依赖项,这些依赖项不能通过使用pip
的 Conda 通道获得。
*PyOpenGL==3.1.*
PyOpenGL-accelerate==3.1.**
如果你有兴趣学习更多关于 Binder 的知识,那就去看看 BinderHub 的文档,这是 Binder 项目背后的底层技术。
在背景中创建虚拟显示
接下来,您需要在背景中创建一个虚拟显示器,健身房 env 可以连接到该显示器进行渲染。您可以通过确认DISPLAY
环境变量的值尚未设置来检查当前是否没有显示。
***!***echo* *$DISPLAY**
下面单元格中的代码在背景中创建了一个虚拟显示,您的健身房 env 可以连接到该显示进行渲染。您可以随意调整虚拟缓冲区的size
,但在使用 Xvfb 时必须设置visible=False
。
这段代码只需要在每个会话中运行一次就可以开始显示。
启动 Xvfb 虚拟显示与使用 Google Colab 完全一样!
运行上面的单元格后,您可以再次回显DISPLAY
环境变量的值,以确认您现在有一个正在运行的显示。
***!***echo* *$DISPLAY**
演示
只是为了证明上面的设置像宣传的那样有效,我将运行一个简短的模拟。首先我定义了一个Agent
,它从一组可能的动作中随机选择一个动作,然后定义一个函数,它可以用来创建这样的代理。然后我将代码打包,模拟一个开放的人工智能健身房环境中的一集。注意,实现假设所提供的环境支持rgb_array
渲染(不是所有的健身房环境都支持!).
模拟“代理”与支持 RGB 数组渲染的 OpenAI Gym 环境交互
目前,在模拟过程中似乎有相当数量的闪烁。不完全确定是什么导致了这种不良行为。如果你有任何改进的想法,请在下面留下评论。如果我找到一个好的解决方法,我一定会相应地更新这篇文章。
使用 Python 渲染视频文本
使用 moviePy 库的动手机器学习项目
雅各布·欧文斯在 Unsplash 上的照片
在这篇文章中,我将向你展示如何使用 Python 向你的视频添加文本。乍一看,这听起来很难,但是相信我,这比你想象的要容易得多,而且很酷。这将是一个简单的练习,我们将能够看到机器学习如何在现实生活中使用。如果你看看我的其他文章,你会发现我喜欢动手做项目。我觉得这是练习我们编码技能,提升自己的最好方式。当你做一点研究时,你会在网上找到一些项目想法。但是我强烈建议你自己进行头脑风暴,写下你个人的项目想法,然后开始研究如何实现它们。让我们回到我们的项目。
目录
- 入门
- 第一步:导入库
- 第二步:定义你的视频
- 第三步:创建你的文本
- 最后一步:在视频上渲染文字
入门指南
正如你可以理解的标题,这个项目,我们将需要一个视频记录文件。它甚至可以是你对着镜头说话的录音。使用名为 *MoviePy,*的库,我们将向视频记录中添加文本。
首先,我们将导入库,我将向您展示如何安装它们。在第二步中,我们将定义我们将用于项目的视频,它可以是一个短视频。在第三步中,我们将定义一个文本变量,它将是添加到视频中的文本。最后,我们将渲染视频记录上的文本。如果您准备好了,让我们从安装库开始吧!
图书馆
我们将为这个项目使用一个库,但要进行文本渲染,我们还需要安装另一个模块。该库名为 MoviePy,安装方法如下:
pip install moviepy
你可以从官方文档页面了解更多关于 moviepy 的信息。
我们需要安装的第二个模块叫做 ImageMagick。如果没有此模块,您可能会在将文本渲染到视频录制时出现错误。为了安装 ImageMagick,我使用了 Homebrew,这是一个用于 macOs 和 Linux 设备的软件包管理器。如果您使用不同的操作系统,可以在线搜索“如何安装 ImageMagick”。
brew install imagemagick
你可以从官方的文档页面了解更多关于 imagemagick 的信息。
MoviePy 是一个可以读写所有最常见的音频和视频格式的库,包括 GIF。如果您在安装 MoviePy 库时遇到问题,请尝试安装 ffmpeg。Ffmpeg 是一个领先的多媒体框架,能够解码、编码、转码、复用、解复用、流式传输、过滤和播放人类和机器创造的几乎任何东西。
现在,我们应该开始在代码编辑器中编写代码了。我们将从导入库开始。
步骤 1-导入库
import moviepy.editor as mp
是的,这就是我们完成任务所需要的。抓紧时间,让我们进入下一步。
第二步——定义你的视频
在这一步,我们将定义一个名为“my_video”的变量。然后使用 moviepy 库的特殊方法,我们将定义我们的视频文件。此外,我想保留视频的音频,这就是为什么视频的值为 True。
my_video = mp.VideoFileClip(“data/video_test.mov”, audio=True)
顺便说一下,有许多视频格式,其中一些可以被列为:
- MP4 (mp4、m4a、m4v、f4v、f4a、m4b、m4r、f4b、mov)
- 3GP (3gp、3gpp2、3g2、3gpp、3gpp 2)
- OGG (ogg、oga、ogv、ogx)
- WMV (wmv、wma、asf*)
请确保您的路径正确,并且您的视频格式工作正常。如果您在此步骤中遇到问题,请尝试将您的视频转换为不同的格式。
在我们进入下一步之前,让我们定义视频的宽度和高度。我们将需要这些渲染成视频文本。别担心,这很容易。
w,h = moviesize = my_video.size
第三步——创建你的文本
在这一步,我们将为我们的文本定义一个新的变量。我把它叫做“我的文本”。使用 TextClip 方法,我们将能够创建文本。
my_text = mp.TextClip(“The Art of Adding Text on Video”, font=’Amiri-regular’, color=’white’, fontsize=34)
如你所见,我们甚至可以玩参数。我们可以自定义我们的文本,这真的很酷。文本字体、文本颜色和字体大小可以根据您的喜好进行更改。
现在,我们将定位视频中的文本。我们也可以为我们的文本设计一个背景。您可以试验参数,看看它是如何工作的。背景颜色、背景不透明度和文本位置是一些参数。
txt_col = my_text.on_color(size=(my_video.w + my_text.w, my_text.h+5), color=(0,0,0), pos=(6,’center’), col_opacity=0.6)
最后一步—在视频上渲染文本
太好了!你坚持到了最后一步。这一步就是奇迹发生的地方。
动画
首先,我们将定义一个名为“text_mov”的新变量,我们可以在其中添加一些动画。文本在视频上的移动。玩参数就能找到自己喜欢的结果。这是我们制作动画的代码行:
txt_mov = txt_col.set_pos( lambda t: (max(w/30,int(w-0.5*w*t)),max(5*h/6,int(100*t))) )
翻译
最后,是时候渲染我们视频上的文本了。多亏了 moviepy 库,我们将使用名为“CompositeVideoClip”的方法为我们进行渲染。如前所述,如果你在这一行遇到错误,我强烈推荐安装 imageMagick 和 ffmpeg 模块。这是让奇迹发生的台词:
final = mp.CompositeVideoClip([my_video,txt_mov])
导出您的结果
差不多了,看看最后的效果如何,我们导出视频吧。我们将把它保存为一个新的视频文件。导出真正酷的是你可以调整视频格式,甚至每秒帧数。下面是导出渲染视频的前 5 秒的代码:
final.subclip(0,17).write_videofile(“data/text_add_result.mov”,fps=24,codec=’libx264')
分享结果
恭喜你。你已经创建了一个程序,在不使用任何视频编辑软件的情况下,在视频上呈现自定义文本。看到机器学习如何应用在我们的日常生活中,这真的很酷。希望你喜欢阅读这篇文章并参与这个项目。如果你今天学到了新东西,我会很高兴。从事像这样的动手编程项目是提高编码技能的最好方式。
如果您在执行代码时有任何问题,请随时联系我。
相关内容
使用 Google 语音识别 API 的简单实用项目
towardsdatascience.com](/extracting-speech-from-video-using-python-f0ec7e312d38) [## Python 中的简单人脸检测
如何使用 OpenCV 库检测图像中的人脸
towardsdatascience.com](/simple-face-detection-in-python-1fcda0ea648e)
重新排序熊猫数据框列:否定标准解决方案
图片来源:“Via Design Pickle”——更多关于属性。
简化更改数据帧列顺序过程的解决方案
更新,2021 年 2 月,请看下面 YouTube 上的教程。
介绍
成千上万的博客文章、stackoverflow.com 线程、quora.com 文章或其他资源展示了在 Pandas 数据框架中移动列(改变它们的顺序)的类似标准方法。
本文首先提供了示例数据。根据示例数据,文章传达了两个好的 但不完美的标准解决方案。本文讨论了这些好的但不完美的标准解决方案的局限性。最后,有一个修正的解决方案,它避免了标准解决方案中固有的一些限制。
示例数据
import pandas as pd# Write some example data
df = pd.DataFrame({'names':['Al','Myke','Lovie','Dash'],
'Grade': [6,7,6,6],
'Teacher':['Ogna','Hayes','Stoltz','Edens'],
'Score':['A+','A-','B','C'],
'Room':['Green','Red','Blue','Yellow'],
'Hobby':['Coins','Stamps','Coins','Cards']})
示例数据帧
标准解决方案(好)
以新的所需顺序显式列出列
对最常发布的列进行重新排序的解决方案是将 DataFrame 设置为等于其自身,但以新的所需顺序显式命名列:
# Reset DataFrame with columns in desired order
df = df[['names','Score','Room','Grade','Teacher','Hobby']]
或者简单地评估具有以新的期望顺序明确命名的列的数据帧:
# Evaluate the DataFrame with columns in desired order
df[['names','Score','Room','Grade','Teacher','Hobby']]
除非有几十或几百列,否则这种标准解决方案工作得很好。假设您有一个包含数十或数百列的数据框架,而您只希望移动一列。为了移动一列而显式列出所有列是低效的。列出所有列也是有问题的,因为对相关代码库的其他方面的更改可能会导致错误。对其他列名的添加、删除或修改会破坏标准解决方案的早期实现。
利用简便的熊猫方法
的另一个标准解决方案是将pd.drop()
和pd.insert()
方法配对。此选项的主要限制是,它仅在一次将一列移动到特定位置时有效。
mid = df['Hobby']
df.drop(labels=['Hobby'], axis=1, inplace = True)
df.insert(1, 'Hobby', mid)
df
爱好从索引位置 5 移动到索引位置 1。
修订的解决方案(更好)
仍然不完美,但对于许多用例来说,可能是更好的选择。
如果您有许多列,它们彼此不相邻,并且您想要将它们全部移动到另一个特定列之后的新位置,该怎么办?也许您还想同时对列进行重新排序。以下是完成该任务的解决方案。
def movecol(df, cols_to_move=[], ref_col='', place='After'):
cols = df.columns.tolist() if place == 'After':
seg1 = cols[:list(cols).index(ref_col) + 1]
seg2 = cols_to_move
if place == 'Before':
seg1 = cols[:list(cols).index(ref_col)]
seg2 = cols_to_move + [ref_col]
seg1 = [i for i in seg1 if i not in seg2]
seg3 = [i for i in cols if i not in seg1 + seg2]
return(df[seg1 + seg2 + seg3])
实施:
df = movecol(df,
cols_to_move=['Score','Grade'],
ref_col='Room',
place='After')
df
“分数”和“等级”列都颠倒了它们的顺序,移到了“房间”后面的索引位置。
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
adamrossnelson.medium.com](https://adamrossnelson.medium.com/membership)
结论
概括地说,数据管理很难。在合并多个数据源之后,拥有一个可以快速排序和重新排序列的方法是很方便的。
这样做是对未来审查你的工作的科学家的一种常见的礼貌。如果我们把最重要的栏目放在左边,其他人会花更少的时间寻找必要的信息来理解我们的工作。当我们知道我们将返回到我们的工作中以供将来参考时,这个额外的步骤对我们自己也是有帮助的。
感谢阅读
如果你喜欢我要说的话,可以在:adamrossnelson.medium.com找到更多。
感谢阅读。把你的想法和主意发给我。你可以写信只是为了说声嗨。如果你真的需要告诉我是怎么错的,我期待着尽快和你聊天。推特:@ adamrossnelson| LinkedIn:亚当·罗斯·纳尔逊 |脸书:亚当·罗斯·纳尔逊。
视频教程
重新排序列,YouTube 上的教程。2021 年 2 月新增。
在疫情期间修复损坏的模型(或不修复)
当你有一个基于多年工作的惊人模型,突然被全球疫情破坏了,你会怎么做?
在如此多的系统中出现如此巨大的中断,很难知道如何处理现有的模型。这里有一些适应的方法——以及一些你可能而不是尝试修复那些模型的原因。
当你有一个惊人的,甚至获奖的,基于多年工作的模型,突然被一个全球性的疫情破坏了,你会怎么做?
听起来熟悉吗?
好吧,如果你在卡内基梅隆大学的德尔菲研究小组,你会振作起来,继续创造性地思考下一个大问题。
2019 年,美国疾病控制和预防中心(CDC)将德尔福集团命名为国家流感预测卓越中心,此前三年,他们的预测系统在 CDC 创建的流感预测挑战中赢得了最高的准确性。但在 3 月份,鉴于流感模型将受到新冠肺炎疫情的显著影响,CDC 要求研究人员将注意力从流感上转移,转而尝试预测新冠肺炎的传播。德尔福小组已经以多种方式进行了调整,包括重新考虑他们模型中的“社交焦虑”信号,以及他们对未来几周的预测能力。(阅读更多关于他们的改编这里和这里。)
传染病模型并不是现在唯一需要重新发明的。任何试图对零售、供应链、医疗保健、教育或几乎任何行业进行预测的人都面临着数据中突然出现的戏剧性行为。有时这是积极的方向:例如,视频游戏行业的人们可能会对他们现在看到的用户和游戏时间的创纪录数字感到非常满意。有时候,数据的变化并不那么积极。
那么,如何修复一个破碎的模型来应对这些戏剧性的转变呢?在我们的 Alteryx 社区和社交媒体的上,已经有一些关于这个挑战的有趣讨论。在这里,我将讨论已经出现的几种可能的策略,每一种都有其自身的复杂性,再加上一种应该会让我们对人类的世界观感觉良好的策略。
添加新的模型特征并使用实时数据
尝试将当前情况整合到模型中的一种方法是添加尝试说明疫情现实情况的要素。也许这是一个捕捉一个城市在社交距离指令下的天数的特征,包括学校和企业关闭。也许这是一个已知感染新冠肺炎病毒的城市人口百分比的特征(承认这些数据是不完整的,因为测试和未知或无症状病例的不一致)。然而,这些可能很难选择、定义和保持更新,因此它们的价值可以忽略不计;随着这些变化的出现,现在也很难验证它们的有用性。
另一个策略是获取尽可能接近实时的数据。当然,这可能也是说起来容易做起来难。但是想象一下,很快有一天,一些不准确的社交媒体模因传播说一种受欢迎的食物治愈了新冠肺炎,并且对该产品产生了抢购。如果你不立即知道突然流行,你将无法维持供应。此时,拥有可重复的自动化工作流程对于帮助您跟上事件的发展速度非常重要。
调整预测方法
在许多领域,为 2019 年夏季生成的预测对于截然不同的 2020 年夏季不会非常有用。对于那些处理时间序列数据和预测的人来说,一种在预测中更重视最近数据的方法目前可能是合适的。例如,如果对一种产品的需求突然上升,最近的增长不会立即消失,但随着消费者行为慢慢恢复正常,更有可能会随着时间的推移而逐渐减少。
例如,Prophet 是一个针对 R 或 Python 的免费公开的预测包。这篇文章和 Alteryx 工作流程展示了一个使用 Prophet 预测工具和在 Alteryx 中配置趋势变化点的例子。变点被定义为时间序列值突然改变的时刻。确定这些对数据有重大影响的时刻,并将它们合并到您的模型中是至关重要的。(请注意,根据 Prophet 文档,“默认情况下,仅为时间序列的前 80%推断变点,以便有足够的跑道来预测未来趋势,并避免在时间序列结束时过度拟合波动。”这种行为可以用最初的 Prophet 参数中的changepoint_range
来改变,但是如果你使用上面提供的宏,不需要进一步定制,你必须确保你的改变点在你的时间序列的前 80%之内。)
另一种可能性是尝试用卡尔曼滤波器平滑时间序列数据,这也许可以更好地处理由这一重大经济事件的“外源冲击”引起的波峰和波谷。R 中的[KFAS](https://cran.r-project.org/web/packages/KFAS/index.html)
包可用于该目的,如本例所示。然而,即使是这种方法也不足以适应如此戏剧性的转变。
使用模拟
经济建模者有时使用衰退和复苏的 V-U-L 曲线来考察未来的可能性。《哈佛商业评论》最近的一篇文章展示了这些模型在过去的大流行中是如何应用于经济的,并可能在今天发生。这是想象可能未来的一种方式,尽管思考悲观的“L”情景是困难的。
从左到右,可视化 V、U 和 L 衰退和复苏。图片来自 维基媒体
这些情景可以为开发模拟不同可能性的模型提供一个框架。虽然多年来模拟在计算上是昂贵和令人生畏的,但现在不再是这样了。正如这些研究人员所指出的:
…我们现在拥有(并且可以轻松执行)有效的统计程序,实际上消除了我们的结果精度的任何令人苦恼的不确定性;毕竟,由于真实系统本身大多是随机的,所以模拟可以以现实的方式捕捉系统的变化,同时仍然可以产生所需的精确结果。
疫情可能比这些作者考虑的大多数情况更加极端,但是模拟可能仍然有一些用处,即使它们不能“消除”不确定性。
模拟可以包含关于疫情对您的情况的影响的不同假设,然后比较评估它们的不同结果。Alteryx Designer 中的模拟采样工具可用于以多种方法采样或模拟数据。引导一个时间序列——模拟多个与原始数据相似的时间序列——可以帮助解释更大的不确定性。对这些序列中的每一个拟合一个模型将产生不同的估计参数和随机误差项。结合这些模型的预测将创建更大的预测区间,并显示更大范围的可能结果。
蒙特卡洛模拟在这一时刻的效用也是最近 Reddit 帖子讨论的主题,讨论如何应对疫情对预测的挑战,受访者对其潜在价值有分歧,特别是因为蒙特卡洛方法假设数据均匀分布。这个[PyMC3](https://github.com/pymc-devs/pymc3)
包提供了一个 Python 工具包(这里有一个教程)。r 也有许多模拟工具,包括包[MonteCarlo](https://cran.r-project.org/web/packages/MonteCarlo/index.html)
,它有一个有用的插图。
无论你尝试什么方法,预测都不会像通常那样有用。围绕你的预测传达大量的不确定性是个好主意。你的听众需要意识到这些置信区间比平常更加重要。
选择你前进的道路
唉,在这样一个不确定的时期,没有单一的解决方案来修复一个曾经被珍视、现在已经破碎的模型,或者产生完美的预测。但这一时刻证明了人类的智慧和敏感性——以及领域专业知识——在数据分析中的重要性。
现在,精心设计一个新模型的每一个参数可能不是对你的时间和精力的最好利用。现在有如此多的未知,依靠有根据的、深思熟虑的人类预测可能更有效。
这一时刻使人的投入在开发分析策略中的重要性变得更加明显。如果工具只是被输入相同的数据,并按照正常情况下的相同方式设计,它们将会失灵。正如麦吉尔大学组织行为学助理教授 Matissa Hollister 最近在世界经济论坛博客上写的:
人类可以辨别算法可能失败的地方和历史训练数据可能仍然与解决关键和及时的问题相关的情况,至少在更多的当前数据可用之前。…尽管新冠肺炎的特殊性质是独特的,并且劳动力市场的许多基本规则不运行,但仍然有可能确定应用人工智能工具的有价值的途径,尽管可能受到小心限制。
正如霍利斯特所建议的,我们仍然可以谨慎地使用我们的建模技能。即使是最好的模型也不知道这个奇怪的新时代的许多微妙之处。例如,毫无疑问,现在不仅人们购买的食物种类发生了变化,而且他们购买食物的具体地点也发生了变化。在一个小的,不太繁忙的社区杂货店购物可能比在高速公路上的巨型超市与大众混在一起更有吸引力。这两种环境对害怕疾病的顾客的相对吸引力很难量化并整合到一个模型中。
我们可能经常觉得人类不太擅长相互理解,但在这次疫情中,我们可以识别模型可能忽略的数据中的情感和生活方式的细微差别。因此,虽然我们可以调整我们的数据选择和模型设计,但也是时候利用人类的同情心和专业知识来指导决策和创造解决方案。
这篇文章名为 ,最初发表于 Alteryx 社区数据科学博客 。在 Alteryx 数据科学门户 找到更多资源。
变分自动编码器中的“重新参数化”技巧
在本文中,我们将学习“重新参数化”技巧,它使变分自动编码器(VAE) 成为反向传播的合格候选。首先,我们将简要讨论自动编码器及其普通变体带来的问题。然后,我们将直接跳到文章的核心——“重新参数化”技巧。
注意 :这篇文章是 而不是 一个教你关于自动编码器的指南,所以我会在需要的时候简单介绍一下。如果你想了解更多关于 Autoencoders 的知识,那么你可以查看这些文章。
一个变分自动编码器( 来源 )
自动编码器:它们做什么?
自动编码器是一类生成模型*。它们允许我们 压缩 一个大的输入特征空间到一个小得多的空间,这个空间以后可以被重建。一般来说,压缩对学习质量有很大的影响。*
我们人类有惊人的压缩能力——我们能够学习简洁的东西,以后我们可以在需要时轻松地扩展它们。例如,通常情况下,你不需要记住一个特定概念的所有细节;你只需要记住关于它的特定点,然后你试着在这些特定点的帮助下重建它。
因此,如果我们能够在一个低得多的维度空间中表示高维数据,并在以后重建它,这对于许多不同的场景都非常有用,如数据压缩、低维特征提取等。
普通自动编码器
用一些代码来解释更容易—
浅层自动编码器网络
我们有一个非常基本的网络:
- 将一个 784-d 向量输入网络。
- **将矢量压缩成 32 维矢量(编码器)。
- **从 32-d 矢量重建原始的 784-d 矢量(解码器)。
下图可能会让这个想法更加清晰——
浅层自动编码器网络示意图
就结果而言,这个网络在良好的旧 MNIST 数据集上训练时,可以产生以下结果(笔记本可在此处获得):
当在 MNIST 图像上训练时来自上述网络的预测
输出看起来没那么糟糕,但是这个网络容易出现一些问题
- 网络的编码器无法知道它应该如何将输入数据点编码成潜变量*(读取压缩)。这迫使潜在变量的表示以 不在乎 关于输入数据点的结构多。当然,在网络的末端有一个损失函数(典型地, L2 )告诉它预测与原始数据点有多远。但是它仍然没有考虑输入数据点应该被压缩的方式。因此,潜在变量中非常小的变化都可能导致解码器产生非常不同的输出。*
- 确定潜在变量的维数是另一个考虑因素。在这种情况下,我们使用 32-d。用一个更高维的向量来表示潜在变量,我们可以提高生成的图像的质量,但只能提高到一定程度。第一个问题仍然存在。
第一个问题似乎比第二个问题更有问题,因为我们可以用不同的维度进行实验,并观察预测的质量。那么,如何解决这个问题呢?
可变自动编码器:编码、采样、解码和重复
VAE 的语义学( 来源 )
为了缓解普通自动编码器中存在的问题,我们转向变型编码器。它引入网络的第一个变化是,输入数据点被映射到 多元正态分布,而不是直接将输入数据点映射到潜在变量。 这种分布限制了编码器在将输入数据点编码成潜在变量时的自由裁量权。同时,它在网络中引入了,因为我们现在是从一个概率分布中的个采样点。**
正态分布由均值(𝜇)和方差(𝜎)参数化,这与变分自动编码器的情况完全相同(有一些“变化”)。所以,一步一步——
- VAE 中的每个数据点将被映射到均值和 log_variance 向量,这些向量将定义该输入数据点周围的多元正态分布。
- 从这个分布中抽取一个点作为潜在变量返回。
- 这个潜在变量被馈送到解码器以产生输出。
这使得网络被迫学习更平滑的表示。它 还确保潜在变量的微小变化不会导致解码器产生大不相同的输出,因为现在我们是从连续分布中采样。另一方面,由于这种采样过程本质上是随机的,解码器输出开始变得更加多样。
下面是一个浅 VAE 的示意图
浅 VAE 示意图
**如图所示,我们在网络中引入了另一个中间密集层。穿着 VAE。mean
和log-variance
是可学习的参数。上图中的Lambda
层代表采样操作,定义如下:
在 TensorFlow 中编码 VAE 的采样操作
因此,如果输入数据点要通过采样(在通过神经网络后)映射到潜在变量𝑧,它必须遵循以下等式:
哪里,𝑠𝑖𝑔𝑚𝑎=𝑒𝑥𝑝(𝑧_𝑙𝑜𝑔_𝑣𝑎𝑟/2).
通过对方差取对数,我们迫使网络具有自然数的输出范围,而不仅仅是正值(方差只有正值)。这使得潜在空间的表现更加平滑。
你一定在质疑这个小术语epsilon
,它在这里有什么意义?我们一会儿会处理这件事。
现在,在我们最终讨论“重新参数化”技巧之前,我们需要回顾一下用于训练 VAE 的损失函数。这是因为我们最终反向传播损失函数的梯度,并且当在 VAE 中发生时,“重新参数化”技巧实际上有助于反向传播过程。
VAE 损失
回想一下上一节,VAE 试图了解潜在空间的分布。因此,除了考虑解码器产生的重构输出,我们还需要确保潜在空间的分布是良构的。摘自用 Python 进行深度学习(作者 Franç ois Chollet)(第一版,300 页)—
通过两个损失函数训练 VAE 的参数:迫使解码样本匹配初始输入的重建损失,以及帮助学习良好形成的潜在空间并减少对训练数据的过拟合的正则化损失** 。**
**正则化损失通过 **Kullback-Liebler 发散来处理。在 GANs in Action (作者 Jakub Langr 和 Vladimir Bok)(第一版,第 29 页)中可以找到对 KL 背离的出色解释
[……]kull back–lei bler 散度(KL divergence),又名相对熵**,是两个分布的交叉熵与其自身熵之差**。对于其他人,想象画出两个分布,它们不重叠的地方将是与 KL 散度成比例的区域。****
对于 KL 散度的选择,这里有一个更精确的数学处理,你可能会发现这个讲座是有用的
对于重建损失,我主要看到了以下两种选择—
- L2 损失
- 二进制交叉熵(用于将数据点的每个特征与重构输出中的值进行比较)
现在,我们可以继续讨论我们一直期待讨论的“重新参数化”技巧。
用反向传播训练 VAE
能够更新的参数。使用反向传播的 VAE,我们需要考虑到里面的采样节点本质上是随机的。我们可以计算采样节点相对于mean
和log-variance
矢量的梯度(采样层中使用了mean
和log-variance
矢量)。
一小部分来自我们的 VAE 网
还记得取样层的小家伙epsilon
吗?那实际上 重新命名了 我们的 VAE 网。这允许mean
和log-variance
向量仍然作为网络的可学习参数,同时仍然通过epsilon
保持整个系统的随机性。
VAE 网络有无“重新参数化”的伎俩( 来源 )
其中,𝜙代表了网络试图了解的分布。
epsilon
仍然是一个具有非常低值的随机变量(从标准正态分布中采样),从而不会导致网络从真实分布中偏离太多。这里可以肯定地重申,网络仍在学习分布𝜙(由 *mean*
和 *log-variance*
向量参数化)。这种想法实际上允许 VAE 以端到端的方式进行训练,是由金玛等人在他们名为自动编码变分贝叶斯的论文中提出的。
结论
所以,文章到此结束,感谢你的阅读!自动编码器是生成模型的第一等成员,甚至在开发 GANs 中找到它们的应用(开始)。解开 VAEs 在强化学习领域也非常相关( DARLA:改善强化学习中的零投迁移)。VAEs 是一种将贝叶斯推理与深度学习结合起来的发现,鼓励不同的研究方向。
以下是我用来写这篇文章的参考资料,如果你有兴趣了解更多关于自动编码器的知识,你一定要去看看
- 生成性深度学习作者大卫·福斯特
- 雅各布·朗格和弗拉迪米尔·博克
- 用 Python 进行深度学习Fran ois Chollet
- 深度生成建模| MIT 6。S191
- Arxiv Insights 的变型自动编码器
你可以通过推特( @RisingSayak )和我联系。
用 GPT-3 取代我的 git 备忘单
像 git 一样,学习驾驶手动变速器会很困难(图片 shutterstock.com)
使用 GPT-3 从我想做的事情的英文描述中生成 git 命令
有些基本技能,如果你年轻时就学会了,会很容易,但如果你不得不在以后的生活中掌握它们,就会变得莫名其妙。例如,对于一个学习驾驶自动档汽车的人来说,驾驶手动档汽车似乎异常困难。然而,如果您不是伴随着 git 成长起来的,那么与掌握 git 命令行界面相比,“驾驶操纵杆”的挑战就相形见绌了。在本文中,我将描述如何利用 OpenAI 的 GPT-3 从英语语言描述中生成 git 命令。
git 的伟大之处(和不那么伟大之处)是什么
Git 是一项基础技术,也是对现代软件开发的杰出贡献。它还有一组命令,这些命令看起来似乎是故意随意和不一致的。
“尽管 Git 有很多优点,但我一直对命令行中除了最简单的操作之外的任何操作都缺乏清晰度感到沮丧。见鬼,即使是最简单的动作也比实际需要的要难。”出自丹尼尔·埃克伦德的。
我到了晚年才明白。在我在 IBM 的职业生涯中,我使用过各种代码控制/版本控制系统,包括古老的 CMVC 和 Clearcase,它们相当容易使用,但仍然是那个时代 IBM 软件中的神秘事物。这两个系统都没有让我为 git 的精彩世界做好准备。
面对 git 语法的挑战,我做了 21 世纪任何有自尊的软件开发人员都会做的事情。我将我最常用的 git 命令保存在一个 Word 文档中,并描述了这些命令的作用。当我需要重复一个特定的 git 咒语时,我可以查看这个 Word 文档,看看我以前是否做过,并尝试找出语法。听起来很棒,对吧?不幸的是,我现在遇到了在个人和工作环境中保持这个文档同步的问题,随着它变得越来越大,我冒着失去更基本的 git 命令的风险。
如果有什么方法可以用一个智能助手代替我的 git 备忘单,将我的英语语言描述翻译成 git 命令就好了…
GPT-3 和吉特:天作之合
当我尝试使用 GPT-3 将简单的 COBOL 函数转换成 Python 时(没有成功),我简直是在摆弄我那愚蠢的 git 备忘单。我仍然认为这是一个好主意,但我已经忘记了太多的 COBOL,无法拿出像样的例子。因此,如果 COBOL 到 Python 不是 GPT-3 的一个好用例,那么什么是呢?如果有一个实际的问题,我必须用英语作为输入,用一些命令作为输出来解决…
答案就在我眼前——使用 GPT 3 将英语描述翻译成 git 命令。
git assistant——一个简单的 Python 程序,用于从英文描述中获取 git 命令
我写了一个简单的 Python 程序, git assistant ,让 GPT-3 提供与我想要 git 做的事情的英语描述相对应的 git 命令。该程序由一个循环组成,该循环提示用户输入,用输入调用 GPT-3 API,并返回 GPT-3 对相应 git 命令的预测:
GPT-3 得到一个英文描述并返回一个 git 命令
为了启动这个泵,我向 GPT-3 提供了一小组英文文本描述的例子和相应的 git 命令:
下面是一个运行 git assistant 的会话示例。GPT-3 的响应列在“输出:”之后
与 git 助手的会话
结果并不完美。例如,对“将更改合并到当前分支”的响应重复了 3 次。也就是说,git assistant 足够好,我可以退休我的 git 备忘单了。
结论
Git 是一个使用非常广泛的应用程序的例子,它的语法有些晦涩难懂。我在本文中已经展示了,通过一些提示,GPT-3 可以很好地从英语语言描述中生成 git 命令。我现在使用这个简单的 git 助手来提醒我 git 语法,让我不必参考 git 命令的静态备忘单。
您可以在本报告中找到本文中描述的代码:
- https://github.com/ryanmark1867/git_assistant[。](https://github.com/ryanmark1867/git_assistant)
- ***注意:*要运行代码,你需要访问 GPT-3 测试版,并用你自己从https://beta.openai.com/developer-quickstart得到的秘密密钥更新配置文件 gpt_assistant_config.yml 中 gpt_key 参数的值
你可以在这里找到一段视频,演示本文中描述的代码:https://www.youtube.com/watch?v=MoLfVG-8Z5A&t = 13s
用 R 替换 PowerPoint
如果你正在做一个分析性的演示,用 R Markdown 创建的演示来代替 PowerPoint 是一个好主意,原因有三。
- 交互性:R Markdown 使您能够生成交互式幻灯片。拥有交互式图表更有趣,应该会让你的演示对象参与进来。
- 文档:您编写的用于生成分析的代码可以存储在幻灯片中(它可以打开/关闭),并作为您的分析方法的文档。没有必要编写您的方法或包含您用来创建可视化的数据截图,因为 R 会为您呈现它们。
- 自动化:如果您必须频繁地使用新数据(如月报或周报)进行相同的演示,那么您可以将相同的代码应用于不同的数据,从而节省您的时间和精力。
创建演示文稿
要用 R 创建一个演示文稿,您需要 R Studio IDE,如果您有,就可以开始使用。要开始点击文件>新建文件> R 降价,这将生成下面的弹出窗口。
创建新的 R Markdown 文件
在左侧面板选择“演示”后,您会看到 4 个演示类型选项(如果您使用的是 R Studio 1.0,您将看不到 PowerPoint)。虽然这篇文章是关于不使用 PowerPoint 的,但是结合 R 使用它仍然是一个巨大的进步。只有 HTML 输出允许交互结果,所以在我看来,这是最好的选择,尽管如果你选择制作 PowerPoint 或 PDF,文档和自动化的好处是不变的。在这个例子中,我将选择 Slidy。
在您创建的新 R Markdown 文件中,前几行是 YAML,这是一种用于声明环境或配置变量的文件格式。这个 YAML 将告诉我们关于演示文稿的事情——标题、作者、日期和输出。我将把标题改为“财务报告”,日期改为“r 系统”。Date()` "将使报告始终具有当前日期。
YAML 降价
写作降价
Markdown 是一种轻量级的标记语言,它基本上意味着文本的格式与文本写在同一个文档中。这类似于 HTML 的工作方式。以下是减价的原则,涵盖了你需要的大部分东西。HTML 和 CSS 可以应用到您的文档中进行进一步的定制。
幻灯片:新的幻灯片将以一些标签开始。单个#生成一个
标记,##生成一个
标记,###生成一个
标记,依此类推。
链接:可以包含在链接文本中
图像:要插入图像,请键入!备选文本
加粗:要使文本加粗,把它放在星号之间,像这样:加粗的单词
斜体:要将文本设为斜体,请将其放在两个星号之间:*斜体文本 *
列表:无序列表可以用*来创建,用+来创建。只需输入“1”就可以创建有序列表,这在您必须向列表中插入新项目时很有帮助,因为您不必重新编号。
块引号:要包含块引号,只需在段落开头加上>。
编写代码
您的代码将以内联或代码块的形式编写。内联代码可以和你的 markdown 一起写,我们在写 r Sys 的时候已经看到了一个例子。日期()`在 YAML。要使用内联代码,只需确保将 R 代码写在反勾号内,而不是撇号内,反勾号与大多数键盘上的波浪号共享同一个键。
代码块是编写大部分代码的地方。每个代码块都以三个反斜杠和一组大括号开始,其中设置了编程语言、代码块名称和显示选项。一个代码块将以三个反斜线结束。以下是您可能需要的主要显示选项:
- echo:隐藏代码。
- eval:不运行代码。
- 包含:运行代码,但不显示代码或输出。常见的用例是在一个块上加载包并隐藏它。
- error:隐藏错误消息。
- 缓存:缓存结果以供将来渲染。如果您经常在幻灯片之间切换,这很有用。
- 图形宽度:调整图形宽度。
- 身材高度:调整身材高度。
呈现演示文稿
要呈现您的演示文稿,请单击屏幕顶部的“编织”。这将生成您的演示文稿,以及可以在浏览器中打开的幻灯片的 HTML 文件。记住,作为一个 HTML 文档,你可以根据自己的需要编写 CSS 样式,比如改变字体或背景颜色。
经过渲染的演示
插入交互式可视化效果
交互性是 R Markdown 在 PowerPoint 上最明显的优势。虽然自动化和文档化可能会节省您的时间,并使您的工作更清晰,但交互性是演示时真正令人惊叹的因素。
使用下面的 quantmod 和 highcharter 包,我在一个有一些交互功能的图上显示谷歌的股票价格。这比您可能在 Excel 中对同一图表进行截图并复制/粘贴到 PowerPoint 中要令人印象深刻得多。它也比你期望的用传统的数据软件花费更少的工作,下面两行单独渲染了这个图。
x <- getSymbols("GOOG", auto.assign=FALSE) highchart(type="stock") %>% hc_add_series(x)
HIghcharter 烛台图表
添加更多高级交互功能(例如,允许您更改正在查看的股票),需要您学习 R package Shiny,它可以帮助您快速构建 web 应用程序。如果你希望你的演示文稿需要大量关于类似数据的图表或幻灯片,添加 Shiny 可以解决这个问题,但使用 htmlwdigets 包可以快速实现基本的交互功能。
用 Detectron2 复制 Airbnb 的舒适度检测
成分:1 个检测器 2,38,188 个开放图像,1 个 GPU。模特培训时间:18 小时。人类时间:127 小时。
计算机视觉驱动的舒适性检测的工作流程示例。图片来源:https://www.airbnb.com/rooms/2151100
几个月前,我在读到了 Airbnb 工程团队的一篇文章,描述了他们如何使用计算机视觉来检测照片中的便利设施。
这篇文章读起来像一个食谱。机器学习的秘诀。
像任何初露头角的厨师(或机器学习者)一样,我决定复制它,并加入一些我自己的味道。
等等。
什么是便利设施?
想想房间里有用的东西。比如厨房里的烤箱或者浴室里的淋浴。
为什么在图像中检测这些会有帮助?
这就是业务用例出现的地方。你会经常看到在 MNIST(手写数字的照片)等数据集上建立的计算机视觉模型教程,但很难将这些问题转化为商业用例(除非你是从事检测手写数字业务的邮政服务人员)。
如果你看过 Airbnb 的网站,那里有很多房子和住宿的照片。除了这些地方,还有基于文本的描述细节的细节。比如你看的房子里有没有按摩浴缸。
举个例子怎么样?
假设你想在 Airbnb 上列出你的家。你可以上传一些照片,并填写一些细节。但是很有可能,因为你非常了解自己的位置,你可能会错过一些东西。
这就是自动舒适度检测可以发挥作用的地方。
当你将图片上传到 Airbnb 时,计算机视觉机器学习模型会查看这些图片,试图找到每张图片中的关键设施,并将它们自动添加到你的清单中。
当然,它可以在实际运行之前向您验证它的预测是否正确。但是让它自动发生将有助于确保每个列表上的信息尽可能地被填写。
拥有尽可能详细的信息意味着人们可以根据特定的标准来搜索地点。因此,这对年轻夫妇在按摩浴缸和壁炉前度过一个美好的周末后,可以找到他们想要的东西。
A note to the reader, treat this article as a high-level narrative of what happened mixed with a splash of tech. For the nerds like me, the code is available in the [example Google Colab Notebook](https://dbourke.link/airbnbcode).
为期 42 天的项目:边做边学
在开始这个项目之前,我就像一个拿着一套没动过的刀的厨师。或者在我的情况下,一个还没有使用过检测器 2 、权重&偏差、流线或者大部分 PyTorch 的机器学习工程师(这些都是机器学习工具)。
我发现在建造东西的时候,我对事物了解得最多。你可能也一样。
所以我打开了一个概念文档,写下了一些标准,并在我的白板上列出了一个 6 周的大纲。
从左到右:一个简单的 42 天项目模板我放在我桌子前面的墙上,所有的日记风格的项目笔记在观念和我的松散绘制的白板指南。
为什么是 6 周?
因为 42 天看起来足够完成一件有意义的事情,但又不至于占据你的生活。
总之。
我想我会花 6 周左右的时间(每天 3 个小时)用我一直想尝试的工具复制 Airbnb 的便利设施检测。
最坏的情况是,我学了一些东西,如果都失败了,也就 6 周。
最好的情况是,我学到了一些东西,并开发了一个非常酷的机器学习应用程序。
不管怎样,都会有一个故事要讲(你正在读它)。
分解它
这个有趣的小图形打破了实验中的主要步骤。
我用来复制 Airbnb 舒适度检测的配方,从数据收集和预处理开始,然后是建模和实验跟踪,最后是应用程序的构建和部署。
有时文字比充满其他图像的图像更容易阅读。
用 Detectron2 复制 Airbnb 的舒适度检测方法:
- 使用 downloadOI.py(用于从打开的图像中下载特定图像的脚本)收集数据。
- 使用 preprocessing.py(一个自定义脚本,具有将打开的图像图像和标签转换为 Detectron2 样式数据输入的功能)预处理数据。
- 检测器 2 的模型数据。
- 使用权重和偏差跟踪建模实验。
- 使用 Streamlit 创建面向用户的应用程序。
- 部署应用程序和模型与 Docker,GCR(谷歌容器注册)和谷歌应用引擎。
我们将使用这些来驱动文章的其余部分。让我们开始吧。
数据收集:从打开的图像中下载 Airbnb 目标图像和标签文件
- 成分: 1 个下载脚本,4 个标签文件,38,000+ x 个打开的图像
- 时间: 1 周
- 费用: $0
- 器皿 : Google Colab,本地机
像所有机器学习项目一样,它从数据开始,也从数据结束。
Airbnb 的文章提到,为了建立他们的概念证明,他们使用了 32k 公共图像和 43k 内部图像。
唉,第一个路障。
当然,除了 2016 年对一个技术支持角色的电话面试,我与 Airbnb 内部没有任何联系,所以内部图像不在讨论范围内。
好消息是他们使用的 32k 公共图片来自 Open Images (一个巨大的免费开源资源,包含来自 600 多个不同类别的数百万张图片)。
然而,如果你打开图片,你会发现有超过一百万张不同的图片。
那交易是什么?
Airbnb 为什么只用 32k?
好问题。
这是因为他们只对与其业务用例相关的图像感兴趣(包含公共设施的房间的图像)。
Airbnb 的目标类别(30 种便利设施类型,摘自原始文章)与来自 600 个不同类别的 190 多万张图像的开放图像数据库。
我想,知道了 Airbnb 最关心的目标类别,肯定有办法只从你关心的开放图像中下载图像(而不是整个 190 万+500 GB+的数据集)。
原来是有的。
经过一番搜索,我从 LearnOpenCV 找到了一个关于如何从目标类列表中下载图片的很好的指南。
具体来说,是一个名为 downloadOI.py 的脚本,它允许您定义您要查找的类以及来自哪个数据集。
让我们看一个例子。
!python3 downloadOI.py --dataset "validation" --classes "Kitchen & dining room table"
这一行写着,“从开放图像的验证集中获取包含厨房和餐厅桌子的图像。”
运行上面的代码行将目标类中的所有图像下载到与目标数据集同名的文件夹中。
# What your image folder(s) look like after using downloadOI.pyvalidation <- top file
│ kitchen_&_dining_room_table_image_1.jpg <- image 1
│ kitchen_&_dining_room_table_image_2.jpg <- image 2
| ... <- more images...
LearnOpenCV 脚本中最初的 downloadOI.py 运行得非常好,它甚至可以在下载图像时生成标签。但是经过一点试验,我发现这些标签与 Detectron2 不兼容。
因此,我取消了下载时的标签创建,并将脚本修改为只下载图像。我决定编写自己的标签创建代码。
能够下载图像:检查。
现在来看看标签。
开放图像标签更容易访问,可以通过点击开放图像下载页面上的特定下载链接或运行以下代码来下载(花絮:滚动到下载页面的底部查看关于标签的信息)。
# Open Images training dataset bounding boxes (1.11G)
!wget https://storage.googleapis.com/openimages/2018_04/train/train-annotations-bbox.csv
# Open Images validation dataset bounding boxes (23.94M)
!wget https://storage.googleapis.com/openimages/v5/validation-annotations-bbox.csv
# Open Images testing bounding boxes (73.89M)
!wget https://storage.googleapis.com/openimages/v5/test-annotations-bbox.csv
# Class names of images (11.73K)
!wget [https://storage.googleapis.com/openimages/v5/class-descriptions-boxable.csv](https://storage.googleapis.com/openimages/v5/class-descriptions-boxable.csv)
数据收集的第一阶段获得了以下文件。
- 来自开放图像训练、验证和测试集的 1 类(咖啡机)图像。
- 训练(
train-annotations-bbox.csv
)、验证(validation-annotations-bbox.csv
)和测试(test-annotations-bbox.csv
)设置包围盒图像标签。 - 不同打开图像类别的描述(
class-descriptions-boxable.csv
为什么只有 1 节课?
我的计划是从小处着手。获取数据预处理和使用 1 个类的 Detectron2 模型,然后在需要时扩展。
数据准备:将打开的图像数据和标签输入到 Detectron2 样式的输入中
- 成分: 5 个预处理功能,4 个标签文件,38,000+ x 个打开的图像,Detectron2 文档
- 时间: 1 周+/- 1 周
- 成本: $0
- 器具 : Google Colab,本地机器
这里的技巧是将我的数据文件(一些标签 CSV 和几个图像文件夹)重新混合到 Detectron2 样式标签中。
我发现如果你想在 Detectron2 中使用你自己的自定义数据,你需要把它转换成一个字典列表。其中每个字典是与 1 幅图像相关联的信息。
让我们看一个例子。
Detectron2 将一个字典列表作为输入。如果您想使用自己的自定义数据,您必须将标签格式化为这种样式。
现在,这些字段分别是什么意思?
annotations
(列表):一幅图像上的所有注释(标签),一幅图像可能有不止一个。对于对象检测(我们的用例),它包含:bbox
(int 列表):边界框的像素值坐标。bbox_mode
( 枚举)bbox
、中像素值的顺序和比例详见文档。category_id
(int):物体类别在bbox
内的数值映射,例子{'coffeemaker':0, 'fireplace':1}
。file_name
(str):目标图像的字符串文件路径。height
(int):目标图像的高度。width
(int):目标图像的宽度。image_id
(int):唯一图像标识符,在评估期间用于识别图像。
如果你想用 Detectron2 建立你自己的物体检测模型,你需要为你的每一张图片安装一个。
正如我们将在后面看到的,我对这个项目的第一个主要目标是获得一个运行在定制数据上的小模型(总是从小模型开始)。
从小处着手意味着为 1 类图像(咖啡机)编写数据准备功能,并确保它们与 Detectron2 一起工作。
获取图像 id
从开放图像下载数据的好处是每个图像都有一个唯一的标识符。
例如,1e646e27c250cd56.jpg
是一张咖啡机的图片,其唯一标识符1e646e27c250cd56
不同于开放图像中的所有其他图像。
所以我写了一个名为get_image_ids()
的函数,它将遍历一个文件夹并返回该文件夹中所有唯一图像 id 的列表。
这意味着我知道我正在处理的所有图像。
格式化现有注释文件
为什么拥有唯一图像 id 列表会有所帮助?
原因如下。
当您从打开的图像下载标签文件并使用 pandas 导入它们时,它们看起来像这样。
打开图像的验证标签的示例。参见 Colab 上的完整代码和示例笔记本。
看到 ImageID 列了吗?在那里,我们可以匹配从打开的图像中下载的图像 id 列表。
但是等等。
为什么要这么做?
两个原因。
首先,我们需要额外的信息,比如 XMin、XMax、YMin 和 YMax 坐标(我们很快就会看到这样的例子)。
第二,从打开的图像中下载注释文件会导致我们获得数据库中每个图像的注释,但是我们只对目标图像的注释感兴趣。
您可能已经注意到 LabelName 列有一些奇怪的值,如/m/0cmf2
和/m/02xwb
,事实证明,这些也是代码。
这就是神秘的class-descriptions-boxable.csv
发挥作用的地方。
让我们来看看。
开放图像标签代码到人类可读类名的映射。
我不知道你怎么想,但是这个名字看起来比/m/0cmf2
和/m/02xwb
好多了。
有了这些以及一个目标类列表,在我的例子中,只有咖啡机,开始时,我有了创造format_annotations()
所需的所有材料。
在一个冗长的句子中,format_annotations()
从打开的图像中下载一个现有的注释文件,比如,[validation-annotations-bbox.csv](https://storage.googleapis.com/openimages/v5/validation-annotations-bbox.csv)
向其中添加一些有用的信息(比如人类可读的类名和每个类的数字分类 ID)并删除不需要的行(我们不关注的图像)。
来看一个小亮点。
运行 format_annotations()函数会添加 ClassName 和 ClassID 列,并删除不需要的标签行(查看更改后的索引值)。参见 GitHub 上的完整代码和示例笔记本。
运行这个函数负责标签字典的category_id
部分。至于删除所有非咖啡机行,validation-annotations-bbox.csv
从 303980 行减少到 62 行。
我们正在取得进展,但还没有完成。
将边界框像素值从相对值转换为绝对值
你可能想知道标签字典中的bbox_mode
是什么意思。
如果没有,我会告诉你我是如何处理的。
bbox
和bbox_mode
是舞伴。
再看一下打开的图像标签,您会看到 XMin、XMax、YMin 和 YMax 列。这些是图像上每个边界框的相对像素坐标。
相对像素坐标意味着要找到目标边界框的每个角出现的实际像素值,必须将 XMin、XMax 值乘以图像的宽度,将 YMin 和 YMax 值乘以图像的高度。
打开的图像带有 XMin、XMax、YMin 和 YMax 的相对像素值坐标。由于边界框是矩形或正方形的,知道左下角和右上角的坐标就足够了。
了解这一点很重要,因为 Detectron2 目前仅支持绝对像素值(相对像素值乘以高度或宽度的结果)。
顺序也很重要。
打开图像边界框的顺序为 XMin、XMax、YMin、YMax,但 Detectron2 需要 XMin、YMin、XMax、YMax。
这就是函数rel_to_absolute()
的用武之地。
它使用图像的高度、宽度和现有边界框坐标,并使用它们将开放图像样式坐标转换为 Detectron2 样式坐标。
一旦我们完成了转换,bbox
参数就会以bbox_mode
( BoxMode.XYXY_ABS
)的形式出现。
创建图像词典(检测器 2 样式标签)
到目前为止,我们已经创建了一些辅助函数。是时候把所有的东西放在一起了。好消息是,我们已经完成了大部分繁重的工作。
倒数第二个(倒数第二个,是的,还有一个)助手函数是get_image_dicts()
。
它采用一个目标图像文件夹、一个相关的注释文件和一个目标类列表,然后使用上面的函数、get_image_ids()
、format_annotations()
和rel_to_absolute()
加上一点自己的逻辑来创建 Detectron2 样式标签(一个字典列表)。
哇哦。那是一口。
在这一点上,提醒读者如果你想看到这一点,检查的例子谷歌 Colab 笔记本。
现在,我们将继续这个故事。
哦,对了,关于get_image_dicts()
还有一件事你应该知道,一旦它创建了图像字典列表,它会将它们保存到一个 JSON 文件中。这确保了我们以后可以使用它们。
get_image_dicts()将打开的图像和标签转换为 Detectron2 样式标签的示例用法(词典列表)。参见 GitHub 上的完整代码和示例笔记本。
我所说的稍后,是指当你用 Detectron2 注册一个数据集的时候。
出于某种原因,当您用 Detectron2 注册数据集时,数据集需要一些预处理,预处理必须用 lambda 函数完成,因此只能接受一个参数。
进入load_json_labels()
,这是最后一个助手函数,它从目标图像文件夹中导入一个 JSON 文件(记住我们是如何保存它们的,以备后用)。
这里你要注意的技巧是,确保如果你将图像字典保存到文件并重新导入它们,你要确保bbox_mode
被格式化为 Detectron2 风格的 BoxMode。
BoxMode 是一个 Python 枚举类型,一个特殊的类型,根据我的经验,它不能很好地保存到 JSON 中(你也许能在这里启发我)。
嘣。
数据预处理完成。我们所要做的就是用 Detectron2 注册我们的数据集,然后我们就可以开始建模了。
等等,为什么我们需要用 Detectron2 注册数据集?
现在,我不完全确定这一点。但是一旦这样做了,注册的数据集就变成了半不可变的(不能轻易改变)。
这似乎是一个防止未来数据集不匹配的好主意。
一个叫DatasetCatalog.register()...
的小家伙,还有MetaDataCatalog.get()
...(这是使用load_json_labels()
的地方)然后我们出发去建模站。
建模和实验:从小处着手,不断迭代
- **成分:**开放图像的小子集(3 类),开放图像的 10%子集(所有类)
- 时间: 2 周+/- 2 天
- 成本: $0
- 器具:谷歌实验室,砝码&偏差,探测器 2 模型动物园
我们已经谈了很多了。但好消息是,一旦你准备好了数据集,Detectron2 会让建模阶段变得非常有趣。
在我开始之前,我必须提醒自己机器学习的第一条规则:从小处着手,经常实验,需要时扩大规模。
这看起来像什么?
还记得标签创建是如何从只为一类图像创建标签开始的吗?模特界也是如此。
为什么从小处着手?
你知道俗话说得好。如果船朝着错误的方向行驶,再用力划船也无济于事。
因此,我开始用 1 个类(咖啡机)获得一个 Detectron2 模型。
一旦成功了,我就把它扩大到 2 个班,然后是 3 个班。您必须知道,每次我这样做时,我都会发现我的预处理函数哪里出了问题,需要改进。其中一个主要问题是确保标签只为目标类创建,而不是来自开放图像的所有类。
在让探测器 2 和 3 个班级一起工作后,下一步是开始认真做模型实验。
你看,我在 Airbnb 的文章中读到,他们开始进行迁移学习,但没有取得多大成功,之后他们转向了谷歌的 AutoML。AutoML 工作,但他们说,限制是不能下载模型。
由于我的标准之一是避免使用 Google 的 AutoML(以修复模型可访问性限制),所以我没有使用它。
相反,我参考了 Detectron2 的模型动物园,这是一个与 COCO(上下文中的常见对象)数据集相关的模型集合,并发现已经有一些对象检测模型准备就绪。
太美了。
我的想法是,我将尝试每个预训练的对象检测模型,利用他们从 COCO 数据集学习的模式,用我自己的数据(一个小数据集)升级模式,看看它是否有效。
我照做了。
我从我想尝试的 Detectron2 模型动物园中定义了一个模型字典。
做了一个小实验。
# My first modelling experiment in pseudocode
for model in models_to_try:
with random_seed x
do 3000 iterations
on classes coffeemaker, bathtub, tree house
save results to Weights & Biases
这个实验的目的是看哪个 Detectron2 对象检测模型在我的数据集上表现最好。我假设我可以通过控制除了模型之外的所有东西(因此是随机种子)来解决这个问题。
现在你可能想知道,你是如何决定这些模型的?
问得好。我看了模型动物园网页,选了它们。
好吧,那么,你是如何追踪你的实验结果的?
很高兴你问了。这就是权重&偏差出现的原因。weights&bias 是一个追踪深度学习实验的非凡工具,如果你还没有使用过,你应该使用它。
发生了什么事?
我做了实验。由于权重和偏见,结果是美丽的。
为什么?
因为模型显示他们正在学习一些东西(平均精度,一种评估物体检测模型的度量标准正在提高),并且每个模型之间没有任何奇怪的差异(意味着实验控制有效)。
我第一次重大实验的结果。每一根棒线都是权重和偏差的“运行”。实验名称可以在左侧看到,每个实验名称对应于 models_to_try 中不同模型的结果。你可以看到关于重量&偏差的完整项目实验。
然后呢?
为了缩小范围,看看我应该使用哪个模型来建立一个大狗模型(一个拥有所有数据并训练更长时间的模型),我假设了另一个实验。
我会从我的第一个实验中选取前两个模型,retina net _ R _ 50 _ FPN _ 1x(细雾-37 )和retina net _ R _ 101 _ FPN _ 3x(earthly-cloud-39),在一个更大的数据集(占所有数据的 10%)上训练它们一段合理的时间(大约 1000 次迭代),然后比较结果。
# My second modelling experiment in pseudocode
for model in top_2_models:
with random_seed x
do 1000 iterations
on 10% of the total data
save results to Weights & Biases
然后,无论哪一个模型脱颖而出,都将成为大狗模型。
必须知道的是,由于我在自己设定的期限内(整个项目 42 天),快速试验是最重要的。
在 Airbnb 的文章中,他们提到他们一次训练他们的模型 5 天和 3 天。因为我总共花了 10 天时间做模特,所以我只有一次机会训练一个大狗模特。
到这个阶段,我已经从开放图像下载了完整的训练、验证和测试数据集。为了运行第二个主要实验,这次我决定在整个数据集的一部分上比较两个性能最好的模型(所有 30 个目标类,而不是只有 3 个类)。
数据集状态:
- 34,835 张训练图像
- 860 张验证图像
- 2,493 张测试图像
当对小部分数据进行建模实验时,小部分数据与完整数据具有相同的分布是很重要的。
换句话说,如果您要对 10%的数据进行建模实验,请确保这 10%的数据与整个数据集具有相同的类分布。在 Airbnb 数据集的情况下,如果完整的数据集有大量楼梯的图像,但没有很多葡萄酒架的图像,则较小的版本应该反映这种关系。
我通过从完整的数据集中随机选择示例,并确保类的分布看起来相似,来拆分 10%的训练数据。
# Get 10% of samples from train dataset
small_dataset = full_dataset.sample(frac=0.1)
创建与原始训练集具有(大致)相同分布的训练数据的 10%子集。这样做意味着实验可以在较小的规模上运行,但仍然可以代表整个数据集可能发生的情况。对测试数据集进行了同样的处理。
我最后还将来自开放图像的验证和测试集合并成一个数据集val_test
。这是因为 Airbnb 提到他们使用 10%的测试数据分割进行评估(75k 总图像、67.5k 训练图像、7.5k 测试图像)。
数据集状态:
- 34,835 张训练图像
- 3,353 个测试图像(原始验证和测试集图像合并)
准备好较小的代表性数据集后,我开始了第二个主要实验,确保跟踪权重和偏差方面的一切。
事实证明,两个模型都表现良好,这意味着应该上升的指标(平均精度)在上升,应该下降的指标(损失)在下降。尽管班级数量增加了 10 倍,但我的模型在学习(这是件好事)。
比较retina net _ R _ 50 _ FPN _ 1x(sleek-sound-45)和retina net _ R _ 101 _ FPN _ 3x(stilled-space ship-46)在 1000 次迭代中对总数据的 10%进行训练的结果。比仅在 3 个类上训练模型的结果更差(预期),但平均精度上升是一件好事。
基于我的第二个主要实验的结果,我最终决定retina net _ R _ 101 _ FPN _ 3x(高跷-飞船-46 )将升级为大狗模型状态。
训练大狗模型(根据所有数据训练的模型)
- **成分:**38000+公开图片(Airbnb 的所有目标类)
- **时间:**人类时间 3 天,计算时间 18 小时
- 成本:$ 150–175 美元(每小时 1.60 美元 P100 GPU +多重故障+未充分利用的实例)
- 器具:砝码&偏差,检测器 2retina net _ R _ 101 _ FPN _ 3x
Detectron2 的预训练模型是在大盆(一台有 8 个 GPU 的大狗电脑)上训练的。我没有 8 个 GPU(图形处理器,一种能够快速计算的计算机芯片),迄今为止,我所做的一切都是在谷歌 Colab (1 个 GPU)或我的本地计算机(没有 GPU)上完成的。
根据我之前的实验,用 10%的数据进行 1000 次迭代的训练,我知道使用 1 个 GPU 对整个数据集进行 100,000 次以上迭代的完整训练运行(摘自 Airbnb 的文章和 Detectron2 模型配置文件)需要大约 15 到 20 个小时。
有了这个信封背面的时间线计算,我想我真的只有一次机会来训练一只大狗模型。
最初,我打算做一些超参数调整(调整模型设置以获得更好的结果),但由于限制,没有像我希望的那样在这里花太多时间。
所以我决定只关注几个:
- 学习率(模型在任一时刻试图提高其知识的程度)。
- 小批量(模型一次看多少张图片)。
根据我的经验,除了模型本身的结构(图层等,反正已经由 Detectron2 决定了),这两个设置对性能影响最大。
我偶然发现了线性学习率缩放规则,读了更多关于它的内容,并决定将其应用于retina net _ R _ 101 _ FPN _ 3x模型的基础设置。
线性学习率比例规则说,你的批量大小和学习率应该随着你使用的 GPU 的数量而增加和减少。
例如,由于我使用的是 1 个 GPU,而不是 Detectron2 最初的 8 个 GPU,如果遵守规则,我应该将最初的学习速率和小批量大小除以 8。
# Linear learning rate scaling rule
new_learning_rate = old_learning_rate/(new_num_gpus * old_num_gpus)
我相应地调整了设置,由于我使用的是迁移学习(不是从头开始训练),我将新的学习率除以 10。
为什么?
我在 Airbnb 的文章中读到,当他们尝试迁移学习时,他们将学习除以 10,作为一种预防措施,以免在新模型学习时,原始模型模式丢失得太快。
这在直觉上对我来说是有意义的,但是,我肯定有更好的方法或者更好的解释。如果你知道,请告诉我。
在 8 个 GPU 上训练的原始 Detectron2 RetinaNet 设置和从头开始更新,以反映在 1 个 GPU 上训练的线性学习率调度规则(较低的学习率和批量大小)并使用迁移学习(增加迭代次数和再次降低学习率)。
怎么样了?
好吧,18.5 小时,34,834 幅训练图像和 180,000 个训练步骤在 P100 GPU 上完成后,我的模型在保留的测试集上以 mAP(平均精度)得分 43.297% 结束。
在 P100 GPU 上使用预训练的检测器 2 retinanet_R_101_FPN_3x 模型进行 18 小时迁移学习的最终结果。AP 指标越高越好。请注意,有些类的结果比其他类高,这与它们在数据集中的示例数量相关(示例越多,得分越高)。参见完整训练跑步、设置和更多关于重量&偏差的内容。
低于 Airbnb 使用谷歌 AutoML 的 68%地图的结果,但高于他们使用迁移学习的结果。
不过应该指出的是,这些指标(我的和 Airbnb 的)实际上没有可比性,因为我们使用了不同的数据集,我只能访问公共数据,Airbnb 有公共和内部图像数据。
但是计量是计量,对吗?
对计算机视觉模型的真正测试是在实际图像上。让我们看看测试集中的几个(记住,模型以前从未见过这些)。
迁移学习训练的 Detectron2 模型的示例,根据开放图像对不可见图像进行舒适度预测。从左到右:厨房里的便利设施被收拾得很好,洗衣机很快就被发现,最后的酒架也被发现。注意:由于这些图像来自开放图像,其中许多不同于标准的 Airbnb 风格的图像。
我的卧室和厨房提供的一些定制图片怎么样?
经过充分训练的模型对我家周围的一些图像进行预测的例子。从左到右:我的床收拾得很好,模特也找到了厨房里的大多数便利设施,但很难从我的工作站中挑选出合适的东西(注意:右图中的许多物品不在培训集中)。
看到机器学习模型在股票数据上工作:嘿,这太酷了…
看到一个机器学习模型在自己的数据上工作:OMG 这是什么魔法???
建模完成后(在时间允许的情况下),是时候让它上线了。
应用构建和部署:Jupyter 中的定制模型很酷,但在网络上直播更酷
- **成分:**完全训练好的定制机器学习模型
- 时间: 4 天
- 成本: $14 托管每天(我知道,我需要解决这个问题)
- 器具 : Streamlit,Docker,Google 容器注册,Google 计算引擎
机器学习模型部署似乎仍然有点像黑暗艺术。
首先,在 Jupyter 笔记本上编码和写 Python 脚本是不一样的。然后你就有了你需要的不同的包,从数据科学库到 web 框架。然后你必须围绕你的模型建立某种用户可以与之交互的界面。一旦你做到了这一点,你在哪里举办呢?
对于任何初露头角的机器学习工程师来说,所有这些挑战都值得接受。
毕竟,如果一个模型只存在于 Jupyter 笔记本中,那么它是否存在呢?
如果你像我一样是一个 Jupyter 笔记本战士,好消息是,Streamlit 和 Docker 可以帮助你。
Streamlit 帮助你为你的机器学习和数据项目建立一个用户界面。更好的是,它也是用 Python 写的。如果你从未尝试过,花半天时间浏览所有的教程,你就可以搞定了。
现在码头工人。Docker 可以帮助你将所有文件(Streamlit 应用、机器学习模型和依赖项)打包成一个漂亮的小包(称为 Docker 映像)。一旦你得到了这个包,你可以把它上传到一个云服务器(例如 Google Cloud ),一切正常,它应该完全像在你的本地系统上那样运行。
所以你让一个训练有素的模型在笔记本上做预测?您部署它的工作流程可能是这样的(我就是这样做的):
- 创建一个类似于
app
的文件夹。这是您的 Streamlit 应用程序(一个 Python 脚本)、模型工件和所有其他所需文件的位置。 - 在新文件夹中创建一个全新的 Python 环境。您需要安装准系统依赖项,以便您的应用程序在此环境中运行。在我的例子中,我需要 Streamlit 和 Detectron2 的依赖项。
- 围绕您的模型构建一个 Streamlit 应用程序(Python 脚本)。
- 让 Streamlit 应用程序在本地工作。这意味着你可以在电脑上互动和查看应用程序的工作情况。
- 为您的环境和应用程序文件夹创建 Docker 映像。
- 将您的 Docker 图片上传到 Docker Hub 或 Docker 托管服务,如 Google Container Repository。
- 使用云提供商,如 Heroku、Google Cloud 或 AWS 来托管和运行您的 Docker 映像。
如果一切顺利,您应该会得到一个指向您托管的应用程序的 URL。
由于我使用了谷歌的应用引擎,我的结果是这样的:airbnb-amenity-detection.appspot.com
我的 Streamlit 应用程序在我的床的图像上运行的(加速)演示。参见 YouTube 上的全面部署和应用构建视频。
我们非常快速地介绍了应用程序的构建和部署。但是如果你有兴趣了解更多,我会查看以下资源(按顺序)。
- Docker 如何帮助你成为更高效的数据科学家作者 Hamel Husain
- 简化部署参考 (AWS、Heroku、Azure)
- 如何将 Streamlit 应用部署到 Google 云平台JarvisTech
标准和评估:比较我的模型和 Airbnb 的
我以一系列我想要达到的标准开始了这个项目。
我们来复习一下。
- **✅的用户可以通过移动设备访问该应用。**这种做法可行,但不可行。尽管如此,它还是会滴答作响。
- **🚫击败或至少等同于 Airbnb 的 50% mAP 的 MVP。**我的所有型号都没有达到或超过这个门槛。所以这是一个失败。
- ✅修复了 Airbnb 使用的 AutoML 模型无法下载的痛点。我训练有素的 Detectron2 模型可供下载,任何人都可以使用。滴答。
- 🚫通过某种方式找到模型最不确定的图像/类。你可以通过查看评估指标打印输出来做到这一点,但我想更多的是一个可视化功能,以实现对表现不佳的类/图像的主动学习方法。失败。
- 💰**运行该模式的成本效益如何?**对于这一个,让我们拿出记事本。
在 Airbnb 看了一个关于机器学习的视频后,有人提到他们在网站上有超过 5 亿张图片(是的,超过 5 亿张)。对于我们的计算,让我们假设我们想要运行我们的模型跨越所有这些。
使用我训练的 retinanet_R_101_FPN_3x 模型和我使用的GPU(英伟达 P100)对每张图像进行预测大约需要 0.2s。
- GPU 成本:1.46 美元/小时(美国中部 GPU),0.0004 美元/秒
- 推断时间:0.2s/张,5 张/秒
- 图像总数:5 亿
- 总推理时间:100,000,000 秒(500,000,000/5)
- 每幅图像的推理成本:0.000081 美元
- 推理总成本:40,555.55 美元
- 总推理时间(1 个 GPU):27778 小时(1160 天)。
当然,还需要更多的计算来看这个模型能增加多少价值。但是看到这些会让你知道 Airbnb 的所有图片需要多少概念证明。
很明显,在目前的状态下,在 Airbnb 的 5 亿多张图片上使用该模型可能是不可行的。
然而,这些数字也是使用谷歌云上 1 个租用的 GPU 计算出来的。如果一台本地机器有多个 GPU,成本(和时间)可以大大减少。
最后值得一看的对比是 Airbnb 在他们的文章中使用的最后一个。他们开始了他们的项目,作为一种建立他们自己的定制计算机视觉模型的方式,这将使他们免于使用第三方舒适性检测服务。
他们注意到,第三方舒适度检测服务只显示置信度超过 0.5 的预测结果(得分越高,模型对其预测越有信心)。所以为了进行公平的比较,他们修改了他们的 Google AutoML 模型来做同样的事情。
这样一来,Airbnb 的 Google AutoML 模型的结果从 68% 的地图变成了 46% 。看到这一点,我用我的模型做了同样的事情,发现结果从 43.2% 到 35.3% 。
从左到右:Airbnb 的 Google AutoML 模型图在置信度 0.5 截断,第三方模型 Airbnb 试图以置信度 0.5 截断开始(来源:原创 Airbnb 舒适度检测文章),我训练的 Detectron2 模型在置信度 0.5 截断。**注意:**这些模型不能完全比较,因为我的模型是在不同的数据集上训练的(没有内部图像)。这个形象只是为了给出一个发人深省的对比。注 2: 至于我的条形图(最右边),我想我已经非常接近复制原件了,你不觉得吗?
扩展、潜在改进和要点
当然,这个项目并不完美。但我没想到会是这样。我是厨师,不是化学家。
我本想在 42 天结束前多做几件事,比如:
- **超参数调谐。**尽管我的模型表现很好,但我并没有像我希望的那样做太多的超参数调整。如果我要这么做,我可能会求助于权重&偏差扫描(一种用于尝试、调整和跟踪超参数的工具)。有了调整后的超参数,谁知道呢,也许我的模型可以提高 1-5%。
- **减少了推断时间。**正如在计算模型的业务用例成本时所看到的,为了大规模运行(在 Airbnb 的所有图像上),推理时间将需要大幅减少或使用更多的处理能力(更多的 GPU)。在进行这个项目 EfficientDet 时,发布了一个高效的对象检测算法。所以这可能是我接下来要尝试的。
- **下载时创建的标签。**预处理 Open Images 数据以使用 Detectron2 需要几个步骤,这些步骤在下载图像时可能会自动执行。
- 一个不那么花哨的应用(是我的错,不是 Streamlit 的)。我仍然习惯于部署我在 Jupyter 笔记本上写的代码。将来,我还想拥有自己的服务器,可以将 Docker 容器推送给其他人并与其他人共享。
- 再培训渠道。如果添加了更多图像或类别,我如何轻松地重新训练模型?现在,这几乎需要重新运行整个项目。
- **检验功能。**如果我想检查数据并查看厨房&餐桌的所有图像或预测低于某个置信度阈值的所有图像,我不能。这些类型的可视化功能对于进一步的数据探索是至关重要的(也许应该从一开始就构建)。
- **哪些图像中有人物?**因为我用的是开放图片,所以很多图片里面都有人物。级联模型可以用来过滤掉不想要的图像风格,只关注与 Airbnb 用例相关的图像。
综上所述,这个项目实现了它的主要目标:边做边学。
我学到了一些我以前从未使用过的工具,更重要的是,我可以如何构建未来的项目。
主要的收获是,实验,实验,实验。
看看是怎么做的
尽管这篇文章很长,但它只是我在这个项目中采取的实际步骤的一个简短概述。
如果你想看到它们全部展开,你可以阅读观念中的我的项目笔记(日志风格)。
或者观看我创建的 YouTube 系列来配合它。
我创建的 YouTube 系列的第 8 部分是为了配合这个项目。
使用机器学习来预测衰退
复制“衰退的机器学习预测”(亚兹达尼,2020 年)
可爱的北极熊在打招呼——在金融市场上,熊通常没那么可爱
包含所有代码的笔记本可以在这里找到。
我最近发现了一个关于从经济数据中预测美国衰退的有趣的演示。虽然我对这个话题并不完全惊讶,但吸引我眼球的是他们的模型的绝对难以置信的准确性。
最佳模型是 AUC 为 95 %的随机森林!!!
你看那个随机森林的 ROC 曲线!
我们谈论的是曲线下 95 %的区域,完美的灵敏度,和近乎完美的特异性。当然,他们一定犯了错误?文章本身是在付费墙后面的。尽管如此,这种表达提供了足够的信息用于复制。
他们是怎么做到的?
根据陈述,他们使用了非常基本的经济指标(联邦基金利率的差异,失业率等。)以及作为整体市场指标的 SP500(美国 500 家最大公司)月度价格差异。他们有时使用对数差异,因为这些差异更可能遵循正态分布。
这些是所使用的预处理步骤和特性
在他们的研究中,他们使用了 1959 年 1 月至 2019 年 12 月的月度数据。
我从哪里获得数据的快速总结:
Quandl:
- 由 GDP 推断的衰退
- 联邦基金利率
- 工业生产指数
- 非农工资
- 失业率
# you can download the data like this -> might require API key
recession_data = quandl.get("FRED/USRECQP", collapse="monthly") fed_funds_data = quandl.get("FRED/FEDFUNDS", collapse="monthly")
indpro_data = quandl.get("FRED/INDPRO", collapse="monthly")
nonfarm_payroll_data = quandl.get("FRED/PAYEMS", collapse="monthly")
unemploy_data = quandl.get("FRED/UNEMPLOY", collapse="monthly")
市场观察
- 500 先令
宏观趋势
- 10 年期国债
关于宏观趋势,只有 1962 年开始的数据可用。因此,我将只考虑 1962 年开始的数据。
# load in merged data
data = pd.read_csv("../data/replication_data.csv", index_col=0)# fill missing recession data
data["recession"] = data["recession"].fillna(method='ffill')
这是我们的目标——根据 GDP 推断的衰退
准备数据
数据准备非常简单。我们计算对数差和差。此外,我们在测试集上划分序列中的数据,从 1962 年开始,但在其他方面坚持演示中建议的结束日期。
# calculate logarithmic differences
def log_diff(v):
log_diff = np.log(v/v.shift(1))
return log_diff# preprocessing
data["slope_yc"] = (data["ty10"] - data["fedfunds"]).diff()
data["fedfunds"] = data["fedfunds"].diff()
data["indpro"] = log_diff(data["indpro"])
data["nonfarm"] = log_diff(data["nonfarm"])
data["SP500"] = log_diff(data["SP500"])
data["ty10"] = (data["ty10"]).diff()
data["unemploy"] = log_diff(data["unemploy"])
data["recession"] = data["recession"].shift(1)
我们的列车周期是从1962–02 到 2006–12。
我们的测试周期为 2007 年 1 月至 2019 年 12 月。
# get x and y
X = data.drop(['recession'], axis=1)
y = data["recession"]# divide in train test according to paper
X_train, y_train = (X.loc["1962-02-28":"2007-01-01"], y.loc["1962-02-28":"2007-01-01"])
X_test, y_test = (X.loc["2007-01-01":], y.loc["2007-01-01":])
处理阶级不平衡
鉴于他们文章的完整标题是“衰退的机器学习预测:不平衡的分类方法”——衰退是一个非常罕见的事件,这一事实应该在充分拟合模型的过程中发挥主要作用。
首先,我们可能会问自己,这些衰退月份在数据中出现的频率有多高?
print(data["recession"].value_counts())0.0 612
1.0 83
Name: recession, dtype: int64
少数民族阶层只占 13.56 %!
那么你如何处理阶级不平衡呢?
有两种主要策略:
- 欠采样按顺序
使用欠采样,您从多数类中采样样本以匹配少数类。由于演示没有提到使用了哪种方法,我使用了随机欠采样。
2.过采样
通过过采样,您可以将数据综合添加到少数类中,以匹配多数类。 SMOTE 是一种常用的过采样技术。
我将对训练数据使用过采样和欠采样来帮助拟合我们的模型,并将它们与原始数据进行比较。
## Sampling techniques
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler
# oversample using SMOTE
sm = SMOTE(random_state=42)
X_train_smote, y_train_smote = sm.fit_resample(X_train, y_train)
# undersample randomly
rus = RandomUnderSampler(random_state=42)
X_train_rnd, y_train_rnd = rus.fit_resample(X_train, y_train)
我们得到了三组不同的火车。原始训练数据,一个带有 SMOTE 的过采样版本和一个随机欠采样版本。
train_test_pairs = {"Normal":(X_train, y_train),
"SMOTE":(X_train_smote, y_train_smote),
"Undersampling":(X_train_rnd, y_train_rnd)}
由于论文标题强调了这样一个事实,即这是一个不平衡数据的问题——幸运的是,衰退是一种罕见的事件——我预计这些抽样方法的得分会有很大不同。
符合我们的模型并进行评估
所以让我们比较三种采样方法——拟合一个随机森林,看看性能。
fig = go.Figure()
fig.add_shape(
type='line', line=dict(dash='dash'),
x0=0, x1=1, y0=0, y1=1
)
for label, pair in train_test_pairs.items():
clf = RandomForestClassifier(max_depth=10, n_estimators=100, class_weight = "balanced_subsample", random_state=0)
clf.fit(pair[0], pair[1])
y_pred= clf.predict(X_test)
fpr, tpr, thresholds = metrics.roc_curve(y_test, clf.predict_proba(X_test)[:,1])
auc = metrics.roc_auc_score(y_test, clf.predict(X_test))
name = f"{label} (AUC={auc:.2f})"
fig.add_trace(go.Scatter(x=fpr, y=tpr, name=name, mode='lines'))
fig.update_layout(
xaxis_title='False Positive Rate',
yaxis_title='True Positive Rate',
yaxis=dict(scaleanchor="x", scaleratio=1),
xaxis=dict(constrain='domain'),
width=900, height=700
)
fig.show()
请击鼓……
击鼓!照片卢兹·门多萨在 Unsplash 上拍摄
不同抽样方法的 ROC 曲线
不错!我们可以看到,取样方法对报告的 AUC 分数有很大的影响。欠采样比 SMOTE 执行得更好,本文中也使用了欠采样。总的来说,我认为复制是成功的— 考虑到我丢失了前三年的数据,并且我没有调优任何超参数。
那么,假设我们能够预测衰退,我们能利用这些信息做什么呢?
衰退期间你应该把钱投到哪里
我想到了几个策略。为了研究这些策略,我将使用我们的模型中的预测来拟合训练期。
1)仅限间谍
SP500 指数将作为我们的基准,因为它通常被认为是美国市场的良好代表。
2)间谍减去衰退
在经济衰退期间,人们可能想减少风险,把钱拿出来放在一边——也许藏在枕头下?
3)间谍和 GLD
黄金似乎总是一个安全的选择。在衰退期间,人们可能会观察到挤兑。
4)间谍和 VIX
VIX 是根据 SP500 期权计算的波动指数。它通常也被称为恐惧指数,更高的波动性意味着不稳定的时期。
比较这些交易策略,并使用我们模型的预测,我们得到了以下测试期的图表:
根据测试集上的预测返回不同的策略
这一时期的主要衰退是在 2008 年到 2010 年之间。我们看到,与流行的观点相反,投资黄金实际上不是一个好主意。黄金似乎很容易受到市场总体走势的影响。在经济衰退期间将我们的资金撤出市场是好的,但这并没有给我们带来真正的优势。另一方面,对被动投资者来说,投资于波动指数(VIX) 似乎是真正的游戏规则改变者。随着经济衰退的到来,恐惧和波动增加,利润也增加。
未来一个月会出现经济衰退吗?
为了确定是否会出现衰退,我们可以获取更多类似这样的最新数据。
# features
fed_funds_data = quandl.get("FRED/FEDFUNDS", collapse="monthly")
indpro_data = quandl.get("FRED/INDPRO", collapse="monthly")
nonfarm_payroll_data = quandl.get("FRED/PAYEMS", collapse="monthly")
unemploy_data = quandl.get("FRED/UNEMPLOY", collapse="monthly")
spy = yf.Ticker("^GSPC").history(period='1d', start='2019-1-1').Close.resample("M").mean()
ty10 = yf.Ticker("^TNX").history(period='1d', start='2019-1-1').Close.resample("M").mean()# subsetting recent data
data = pd.DataFrame()
data["fedfunds"] = fed_funds_data.loc["01-01-2020":].Value
data["nonfarm"] = nonfarm_payroll_data.loc["01-01-2020":].Value
data["indpro"] = indpro_data.loc["01-01-2020":].Value
data["SP500"] = spy.loc["01-01-2020":]
data["ty10"] = ty10.loc["01-01-2020":]
data["unemploy"] = unemploy_data.loc["01-01-2020":].Value
# preprocessing
data["slope_yc"] = (data["ty10"] - data["fedfunds"]).diff()
data["fedfunds"] = data["fedfunds"].diff()
data["indpro"] = log_diff(data["indpro"]).fillna(method="ffill") # no recent data
data["nonfarm"] = log_diff(data["nonfarm"])
data["SP500"] = log_diff(data["SP500"])
data["ty10"] = (data["ty10"]).diff()
data["unemploy"] = log_diff(data["unemploy"])
我们可以使用我们的模型来估计我们的模型在预测中的置信度。
data.dropna(inplace=True)
data["recession_proba"] = clf.predict_proba(data)[:,1]fig = go.Figure()
fig.add_scatter(x= data.index, y=data["recession_proba"], mode='lines', name="SPY long")
fig.update_layout(title_text="Probabilities of a Recession according to the model")
fig.show()
根据我们对训练数据的随机森林拟合,对衰退的信心
截至 9 月,我们的模型确信未来一个月不会出现衰退。我们可以看到,由于杰罗姆鲍威尔美联储利率的变化以及失业人数的上升,我们实际上在 4 月和 3 月遇到了更高的信心水平。
如果你发现任何错误,有任何问题,或者想要合作,请随时在 Linkedin 上联系我。
参考
亚兹达尼(2020)。衰退的机器学习预测:不平衡分类方法。《金融数据科学杂志》。演示幻灯片检索自:https://FDP institute . org/resources/Documents/webinars % 20 thought leadership % 20 pieces % 20 etc/Al % 20 yaz dani % 20 webinar % 20 July % 208,%202020.pdf
RepNet:计算视频中的重复动作
用于计数重复动作和估计视频中周期的最新模型的方法
克里斯·贾维斯在 Unsplash 上的照片
虽然我们大多数人都可以在锻炼或测量脉搏时计数,但如果能有一些东西为我们计数,甚至提供关于重复动作的有价值的信息,那就太好了。特别是对于周期较长的动作,如行星周期,或者周期太短的动作,如制造带。
谷歌研究和 DeepMind 团队最近在 2020 年 CPVR 发表的一篇名为计算时间:野外不可知视频重复计数的论文解决了这个有趣的问题。
他们采用一种非常“简单”的方法来识别和计数重复的动作,并最终预测动作的周期性。但作者发现的主要障碍是管理足够大的数据集来做到这一点。因此,本文1的主要贡献在于:
- 释放计数:一个新的视频重复计数数据集,它比先前最大的数据集大 90 倍
- 发布 RepNet :一种用于计数和测量“野外”视频中重复周期的神经网络架构1,使其优于之前的最先进方法
- 使用合成的、无标签的剪辑并生成可用于训练的增强视频
Countix 数据集
Countix 中的样本来自1
首先,作者提出了一个新的、巨大的带有重复动作的带注释视频数据集——因为现有的重复数据集太小了。
请看上图,它比较了新数据集: Countix 和现有的“基准测试”(只有 100 个样本!).Countix 有从野外拍摄的视频(如 YouTube ),团队通过众包收集注释。标注器“分割包含具有明确计数的有效重复的视频部分”1。并且它们也继续添加计数值。一个漂亮的过程最终产生了一个比之前的数据集大 90 倍的带注释的数据集。
你可以在这里下载 Countix
在这里看一看动力学
又一个数据集
除了 Countix(其剪辑来自 、动力学 )之外,作者还提出了一种很酷的方式,即从类似真实重复视频的普通视频中生成合成视频。
简而言之,他们所做的是:
- 从运动训练集中的真实视频中截取短片,并重复该视频片段一定次数。这固定了一个计数、周期,并产生一个重复的视频。
- 为了保持“真实度,他们在重复片段前后预挂起并附加非重复片段。例如,一个女孩可以走进视频帧,进行一次旋转(就像在结果可视化部分的图像 1 的帧 3 中),然后走开。因此,这种方法将导致重复单次旋转的片段多次——保持开始和结束时的行走片段完好无损。
- 请看下图中的第二帧。这种奇怪的变换是将摄像机运动增强应用于视频的结果。正如我们所知,在图像中,我们可以通过旋转、倾斜、通道转换二维图像来轻松执行图像增强。类似地,作者以时间方式对这些视频应用旋转、平移和缩放变换。时间时尚本质上意味着应用于每一帧的变换不是随机的,并且当播放视频时,它在变换的顺序和流程方面仍然有意义。这个确保了我们在第二帧中看到的一个流畅的、看似动画的视频
摄像机运动增强来自[2]
让我们训练吧
布莱恩·苏曼在 Unsplash 上拍摄的照片
模型架构由以下部分组成:
- 编码器:包括一个特征提取器(基于 ResNet-50),一个 3D 卷积层(检测重复运动的不同部分),以及使用全局 2D 最大池的维数减少
- **时间自相似性矩阵:**计算两个帧之间的成对相似性(或者,更准确地说,两个帧的编码嵌入)
- **周期预测器:**使用相似矩阵来预测每帧的周期长度和周期性。该预测器由 32 个 3D conv 层、多头注意力转换器层和作为分类器的 2 个 FC 层组成
模型架构来自1
这款内容丰富的 Colab 笔记本 带你经历在本地视频和你的现场网络摄像头上执行模型和测试的每一步
可视化结果
图一。重复计数的应用[2]
速度和周期性来自[2]。这表明该模型甚至能够捕捉不同频率的重复运动;这可以告诉主体是减速还是加速。
接下来呢?
你能想出这种方法需要解决的事件或角度吗?这在现实世界中哪里可以工作?哪里没有?
本文提供了 RepNet 的以下实际应用:
- 运动追踪:计数、速度等。
- 依靠心电图视频
- 天文和地球物理变化,如一天的长度或分析天体事件的卫星图像
参考资料:
1Dwibedi,Debidatta 等,“计算时间:野外的类不可知视频重复计数。”2020 年,IEEE/CVF 计算机视觉和模式识别会议论文集。
[2]RepNet1的项目网页:https://sites.google.com/view/repnet
感谢您从头到尾的阅读!您可以通过 LinkedIn联系我,获取任何信息、想法或建议。
报告太长无法阅读?使用 NLP 创建摘要
塞巴斯蒂安·赫尔曼在 Unsplash 上的照片
创建个人文本摘要的指南
你是否曾经有过多的报告需要阅读,而你只是想快速总结每份报告?你有没有遇到过这样的情况,每个人都只想读一份摘要而不是一份完整的报告?
在 21 世纪,摘要已经成为解决数据过载问题的一种非常有用的方法。在这个故事中,我将向您展示如何使用 Python 中的自然语言处理(NLP)创建您的个人文本摘要。
前言:创建个人文本摘要并不困难——初学者很容易做到!
什么是文本摘要?
这基本上是一个任务,生成一个准确的总结,同时保持关键信息,不失去整体意义。
有两种常见的总结类型:
- 抽象概括 > >从原文生成新句子。
- 摘录摘要 > >识别重要的句子,并使用这些句子创建摘要。
我应该使用哪种总结方法,为什么?
我使用提取摘要是因为我可以将这种方法应用于许多文档,而不必进行大量(令人生畏的)机器学习模型训练任务。
除此之外,提取摘要比抽象摘要给出更好的摘要结果,因为抽象摘要必须从原始文本生成新的句子,这是比数据驱动的方法更难提取重要句子的方法。
如何创建自己的文本摘要?
我们将使用单词直方图来排列句子的重要性,然后创建摘要。这样做的好处是,您不需要训练您的模型将它用于您的文档。
文本摘要工作流
下面是我们将遵循的工作流程…
导入文本> > > >清理文本并拆分成句子> >移除停用词> >构建词直方图> >排列句子> >选择前 N 个句子进行汇总
(1)样本文本
我使用了一篇名为**苹果以 5000 万美元收购人工智能初创公司的新闻文章中的文字来推进其应用程序。**你可以在这里找到原来的新闻文章。
也可以从 my Github 下载文本文档。
(2)导入库
# Natural Language Tool Kit (NLTK)
import nltk
nltk.download('stopwords')
nltk.download('punkt')# Regular Expression for text preprocessing
import re# Heap (priority) queue algorithm to get the top sentences
import heapq# NumPy for numerical computing
import numpy as np# pandas for creating DataFrames
import pandas as pd# matplotlib for plot
from matplotlib import pyplot as plt
%matplotlib inline
(3)导入文本并进行预处理
有很多方法可以做到这一点。这里的目标是有一个清晰的文本,我们可以把它输入到我们的模型中。
# load text file
with open('Apple_Acquires_AI_Startup.txt', 'r') as f:
file_data = f.read()
在这里,我们使用正则表达式来做文本预处理。我们将(A)用空格(如果有的话)替换参考号,即1、[10]、[20],(B)用单个空格替换一个或多个空格。
text = file_data
# replace reference number with empty space, if any..
text = re.sub(r'\[[0-9]*\]',' ',text) # replace one or more spaces with single space
text = re.sub(r'\s+',' ',text)
接下来,我们用小写字母(没有特殊字符、数字和额外的空格)形成一个干净的文本,并将其分割成单个单词,用于单词得分计算和单词直方图的形成。
形成干净文本的原因是算法不会将例如**“理解”和理解**视为两个不同的单词。
# convert all uppercase characters into lowercase characters
clean_text = text.lower()# replace characters other than [a-zA-Z0-9], digits & one or more spaces with single space
regex_patterns = [r'\W',r'\d',r'\s+']
for regex in regex_patterns:
clean_text = re.sub(regex,' ',clean_text)
(4)将文本分割成句子
我们使用 NLTK sent_tokenize() 方法将文本分割成句子。我们将评估每个句子的重要性,然后决定我们是否应该在总结中包含每个句子。
sentences = nltk.sent_tokenize(text)
(5)删除停止字
停用词是对句子没有多大意义的英语单词。可以安全地忽略它们,而不会牺牲句子的含义。我们已经在“(2)导入库”部分下载了一个带有英文停用词的文件。
这里,我们将获得停用词列表,并将其存储在 stop_word 变量中。
# get stop words list
stop_words = nltk.corpus.stopwords.words('english')
(6)建立单词直方图
让我们根据每个单词在整篇文章中出现的次数来评估它的重要性。
我们将通过(1)拆分 clean_text 中的单词,(2)删除停用词,然后(3)检查每个单词在文本中出现的频率。
# create an empty dictionary to house the word count
word_count = {}# loop through tokenized words, remove stop words and save word count to dictionary
for word in nltk.word_tokenize(clean_text):
# remove stop words
if word not in stop_words:
# save word count to dictionary
if word not in word_count.keys():
word_count[word] = 1
else:
word_count[word] += 1
让我们绘制单词直方图,看看结果。
plt.figure(figsize=(16,10))
plt.xticks(rotation = 90)
plt.bar(word_count.keys(), word_count.values())
plt.show()
啊啊啊啊……看剧情有点难。让我们将其转换为水平条形图,并只显示前 20 个单词,下面有一个帮助函数。
# helper function for plotting the top words.
def plot_top_words(word_count_dict, show_top_n=20):
word_count_table = pd.DataFrame.from_dict(word_count_dict, orient = 'index').rename(columns={0: 'score'})
word_count_table.sort_values(by='score').tail(show_top_n).plot(kind='barh', figsize=(10,10))
plt.show()
让我们展示前 20 个单词。
plot_top_words(word_count, 20)
从上面的剧情中,我们可以看到**‘ai’和‘apple’**这几个字出现在顶部。这很有意义,因为这篇文章是关于苹果收购一家人工智能初创公司的。
(6)根据分数对句子进行排序
现在,我们将根据句子得分对每个句子的重要性进行排名。我们将:
- 删除超过 30 个单词的句子,认识到长句子并不总是有意义的* *;
- 然后,将构成句子的每个单词的得分(计数)相加,形成句子得分。
得分高的句子将构成我们的顶级句子。上面的句子将构成我们以后的总结。
** **注:**以我的经验来看, 25 到 30 之间的任何字数都应该给你一个很好的总结。
# create empty dictionary to house sentence score
sentence_score = {}# loop through tokenized sentence, only take sentences that have less than 30 words, then add word score to form sentence score
for sentence in sentences:
# check if word in sentence is in word_count dictionary
for word in nltk.word_tokenize(sentence.lower()):
if word in word_count.keys():
# only take sentence that has less than 30 words
if len(sentence.split(' ')) < **30**:
# add word score to sentence score
if sentence not in sentence_score.keys():
sentence_score[sentence] = word_count[word]
else:
sentence_score[sentence] += word_count[word]
我们将 sentence_score 字典转换成数据帧,并显示句子和分数。
注意 : dictionary 不允许你根据分数对句子进行排序,所以你需要将 dictionary 中存储的数据转换成 DataFrame。
df_sentence_score = pd.DataFrame.from_dict(sentence_score, orient = 'index').rename(columns={0: 'score'})
df_sentence_score.sort_values(by='score', ascending = False)
(7)选择排名靠前的句子进行总结
我们使用堆队列算法选择前 3 个句子并存储在 best_sentences 变量中。
通常 3-5 句话就足够了。根据你的文档的长度,随意改变要显示的顶部句子的数量。
在这种情况下,我选择了 3 ,因为我们的文本是一篇相对较短的文章。
# display the best 3 sentences for summary
best_sentences = heapq.nlargest(**3**, sentence_score, key=sentence_score.get)
让我们使用循环函数的 print() 和来显示我们的总结文本。
print('SUMMARY')
print('------------------------')# display top sentences based on their sentence sequence in the original text
for sentence in sentences:
if sentence in best_sentences:
print (sentence)
这里是 我的 Github 的链接,来获取这个 Jupyter 笔记本。
下面是完整的 Python 脚本,您可以立即使用它来总结您的文本。
让我们来看看算法的运行情况!
以下是一篇题为苹果以 5000 万美元收购 AI 初创公司以推进其应用 的新闻文章的原文(原文可在此处找到**):
*In an attempt to scale up its AI portfolio, Apple has acquired Spain-based AI video startup — Vilynx for approximately $50 million.Reported by Bloomberg, the AI startup — Vilynx is headquartered in Barcelona, which is known to build software using computer vision to analyse a video’s visual, text, and audio content with the goal of “understanding” what’s in the video. This helps it categorising and tagging metadata to the videos, as well as generate automated video previews, and recommend related content to users, according to the company website.Apple told the media that the company typically acquires smaller technology companies from time to time, and with the recent buy, the company could potentially use Vilynx’s technology to help improve a variety of apps. According to the media, Siri, search, Photos, and other apps that rely on Apple are possible candidates as are Apple TV, Music, News, to name a few that are going to be revolutionised with Vilynx’s technology.With CEO Tim Cook’s vision of the potential of augmented reality, the company could also make use of AI-based tools like Vilynx.The purchase will also advance Apple’s AI expertise, adding up to 50 engineers and data scientists joining from Vilynx, and the startup is going to become one of Apple’s key AI research hubs in Europe, according to the news.Apple has made significant progress in the space of artificial intelligence over the past few months, with this purchase of UK-based Spectral Edge last December, Seattle-based Xnor.ai for $200 million and Voysis and Inductiv to help it improve Siri. With its habit of quietly purchasing smaller companies, Apple is making a mark in the AI space. In 2018, CEO Tim Cook said in an interview that the company had bought 20 companies over six months, while only six were public knowledge.*
…文本摘要如下:
*In an attempt to scale up its AI portfolio, Apple has acquired Spain-based AI video startup — Vilynx for approximately $50 million.
With CEO Tim Cook’s vision of the potential of augmented reality, the company could also make use of AI-based tools like Vilynx.
With its habit of quietly purchasing smaller companies, Apple is making a mark in the AI space.*
结论…还有最后一个提示
恭喜你!
您已经用 Python 创建了自己的文本摘要器。我希望这份总结看起来相当不错。
需要注意的是,我们在文档中使用了词频来对句子进行排序。使用这种方法的优点是,它不需要任何事先培训,可以处理任何文本。另一个技巧是,您可以根据自己的喜好进一步调整汇总器,基于:
*(1) **顶句数量:*这里简单的经验法则是,摘要的长度不要超过原文的 1/4——可以是一句话,一段话,也可以是多段话,取决于原文的长度和你获取摘要的目的。如果你要总结的文字比较长,那么可以增加顶句的数量;或者
*(2) **句子长度:*平均来说,今天一个句子的长度在 15 到 20 个单词.)之间。因此,限制你的总结者只采用长度超过 25-30 个单词的句子就足够了;但是,可以随意增减字数。
谢谢你读了这个故事。在 medium 上关注我,获得更多关于数据科学和机器学习的分享。
用 Python 表示分层数据
用 anytree 库解析简单的 JSON 表示
Edvard Alexander lvaag 在 Unsplash 上拍摄的照片
在计算机科学中,处理层次分类数据是非常常见的。应用范围从维基百科的类别到由聚类算法(如 HDBSCAN)生成的数据的层次结构,等等。
在这篇文章中,让我们从我的工作领域中的一个例子开始:如何正确分类连接到网络的设备。从“设备”的一般概念出发,我们可以定义两大类设备,称为“网络”和“计算机”。第一类可以进一步细分为“路由器”、“交换机”和“防火墙”(当然,为了简单起见,我省略了其他几类)。数据可以这样表示:
用于对联网设备进行分类的分类示例。
这种在层次结构中表示分类数据的方式——其自然适合的数据结构是一个树——在技术上被称为 分类法 ,这个术语最初在生物学中用于对物种进行分类。分类的每个元素都是一个分类节点。
如果想用人类可读的格式(如 JSON)来表示分类法,最常用的表示方法如下:
这种表示暴露了树的递归性质,但是随着分类的增长,由于大量的嵌套层次,它很快变得难以修改。在这篇文章中,我将展示 JSON 中的另一种表示,以及序列化它的 Python 代码。
分层数据的简单 JSON 表示
通过避免任何嵌套结构并将所有对象表示为按每个分类级别划分的平面列表,可以获得表示分类数据的另一种方法。这样,我们之前使用的分类示例如下所示:
和以前一样,每个节点可以包含任意数量的属性。上面的表示很容易在应用程序中解析和修改。然而,相对于前一个,它有一些缺点:
- 它没有显示底层树的递归性质,因此部分地失去了人类的可读性。
- 由于每个分类节点存储了父字段,因此它占用了更多内存。
在为分层数据选择正确的表示法时,请考虑这些缺点。现在让我们看看如何用 Python 解析上面的分类法表示。
用 Python 解析分层数据
您肯定知道,说到可用库,没有哪种语言比 Python 更好。因此,有几个适合处理分类法的库就不足为奇了:
- 最受欢迎的是
[networkx](https://networkx.github.io/documentation/stable/)
。尽管它是为更复杂的图结构而设计的,networkx
很容易适应分类法,这只是图的一个特例。 - 另一个不太受欢迎的图书馆是
[anytree](https://anytree.readthedocs.io/en/latest/)
。它实现了一个简单但功能丰富的树数据结构,并且经过了实战测试(它达到了版本 2.8.0,对于 Python 库来说并不常见)。这是我为这篇文章选择的库。 - 其他库包括
[binarytree](https://github.com/joowani/binarytree)
just for 二叉树、 TreeSwift 等等。
现在让我们构建一个 TaxonomyParser 类的最小版本,用于反序列化 JSON 表示,并使用惟一的节点标识符在分类法中进行搜索。
这个类唯一需要的属性是root_key
——用于快速检索根节点——和包含所有树节点的字典nodes
,这些树节点由它们唯一的name
索引。由于 JSON 文件中的平面表示,反序列化分层数据的代码(read_from_json
方法)非常简单。
如果需要在分类法上实现更复杂的搜索条件,该怎么办?例如,假设每个节点包含一个带有正则表达式列表的regex
属性。给定一个输入关键字,您希望查找正则表达式与该关键字匹配的所有节点。听起来很复杂?得益于anytree
灵活的界面,这可以通过几行代码实现:
最后,如果您想将图形导出到标准。点格式或作为 PNG 图像,anytree
提供了所有你需要的:
总之,有了anytree
库,解析和操作本文中呈现的平面表示中存储的分层数据变得非常容易。完整的代码可以在我的 Github 上找到。如果你喜欢这篇文章,并且有任何问题或意见,请不要犹豫,通过 LinkedIn 联系我。
使用 leav 表示您的地理空间数据
使用 python 可视化地图的过程
作为数据科学社区的一部分,地理空间数据是最重要的数据类型之一。这些应用程序非常简单,比如“我的外卖订单现在在哪里?”和“送货员的最佳路径是什么?”一样复杂
是什么把我带到了叶城?
我最近在研究一个涉及大量 gps 坐标的数据科学问题。显然,这是一个非常基本的问题——我如何在我的 jupyter 笔记本上的地图上表示这些坐标?虽然我们知道 plotly 、 geopy 和底图完成了工作,但这是我第一次遇到leaf并决定试一试!
本文是一个关于使用 folium 表示数据的分步教程。
介绍
Folium 主要用于为浏览器生成交互式地图(在笔记本内或网站上)。它使用了 leaflet.js ,这是一个用于交互式地图的 javascript 库。
用一行程序实现它:用 Python 处理数据,然后通过 leav 在活页地图上可视化。
第一步: 在电脑上安装叶子,导入必要的包。
!pip install foliumimport numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import preprocessing
import scipy## for geospatial
import folium
import geopy
我们将使用来自太空的火:澳大利亚数据集。
第二步: 加载并检查数据集。
df = pd.read_csv("fire_archive_M6_96619.csv")
第三步: 找到坐标开始。
我们可以从数据集本身选取一组坐标,也可以使用 geopy 来实现这一目的。在这里,我们正在谈论澳大利亚的野火,所以我从墨尔本开始参考。
city = "Melbourne"
# get location
locator = geopy.geocoders.Nominatim(user_agent="My app")
city = locator.geocode(city)
location = [city.latitude, city.longitude]
print(city, "\n[lat, long]:", location)
第四步: 在地图上绘图。
在地图上绘制点就像盖房子一样。你奠定了基础(这是你的背景地图),然后你在它的表面上添加点。
我们将首先奠定基础。
map_ = folium.Map(location=location, tiles="cartodbpositron",
zoom_start=8)
map_
你也可以通过参考这里的来玩 tileset 和 zoom。
现在我们在地图上标出这些点。我们将根据属性“类型”进行颜色编码,并根据火的“亮度”确定大小。所以让我们先把这些属性按顺序排好。
# create color column to correspond to type
colors = ["red","yellow","orange", "green"]
indices = sorted(list(df["type"].unique()))
df["color"] = df["type"].apply(lambda x:
colors[indices.index(x)])
## scaling the size
scaler = preprocessing.MinMaxScaler(feature_range=(3,15))
df["size"] = scaler.fit_transform(
df['brightness'].values.reshape(-1,1)).reshape(-1)
我们最后用叶子在地图上添加点。
df.apply(lambda row: folium.CircleMarker(
location=[row['latitude'],row['longitude']],
popup=row['type'],
color=row["color"], fill=True,
radius=row["size"]).add_to(map_), axis=1)
最后,我们向地图添加图例。我使用这个参考来添加一个图例。还有许多其他方法,但这是我发现的最简单的方法。
legend_html = """<div style="position:fixed;
top:10px; right:10px;
border:2px solid black; z-index:9999;
font-size:14px;"> <b>"""+color+""":</b><br>"""
for i in lst_elements:
legend_html = legend_html+""" <i class="fa fa-circle
fa-1x" style="color:"""+lst_colors[lst_elements.index(i)]+"""">
</i> """+str(i)+"""<br>"""
legend_html = legend_html+"""</div>"""
map_.get_root().html.add_child(folium.Element(legend_html))#plot
map_
这是整段代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import preprocessing
import scipy
## for geospatial
import folium
import geopydf = pd.read_csv("fire_archive_M6_96619.csv")city = "Melbourne"
# get location
locator = geopy.geocoders.Nominatim(user_agent="My app")
city = locator.geocode(city)
location = [city.latitude, city.longitude]
print(city, "\n[lat, long]:", location)map_ = folium.Map(location=location, tiles="cartodbpositron",
zoom_start=8)# create color column to correspond to type
colors = ["red","yellow","orange", "green"]
indices = sorted(list(df["type"].unique()))
df["color"] = df["type"].apply(lambda x:
colors[indices.index(x)])
## scaling the size
scaler = preprocessing.MinMaxScaler(feature_range=(3,15))
df["size"] = scaler.fit_transform(
df['brightness'].values.reshape(-1,1)).reshape(-1)df.apply(lambda row: folium.CircleMarker(
location=[row['latitude'],row['longitude']],
popup=row['type'],
color=row["color"], fill=True,
radius=row["size"]).add_to(map_), axis=1)legend_html = """<div style="position:fixed;
top:10px; right:10px;
border:2px solid black; z-index:9999;
font-size:14px;"> <b>"""+color+""":</b> <br>"""
for i in lst_elements:
legend_html = legend_html+""" <i class="fa fa-circle
fa-1x" style="color:"""+lst_colors[lst_elements.index(i)]+"""">
</i> """+str(i)+"""<br>"""
legend_html = legend_html+"""</div>"""
map_.get_root().html.add_child(folium.Element(legend_html))
#plot
map_
也可以在我的 Github 上找到。希望这篇文章有所帮助。
RDF*和 LPG 知识图上的表示学习
超越三元组的 GNNs
超关系公斤比三公斤编码更多的知识。我们采用了图 ML 的最新进展,并提出了一个 GNN 编码器和一个新的基准。
图片作者。
K 知识图(KGs)是现代自然语言处理和人工智能应用的基石——最近的工作包括问答、实体&关系链接、语言建模、信息提取,甚至用强化学习播放文本 RPG。此外,知识管理已经在行业中被广泛采用,例如最近的知识图表会议(KGC)中的系列作品
三胞胎大战世界
传统上,kg 被编码为 <主语、谓语、宾语> (RDF)三元组,许多公开可用的 kg,如 DBpedia 和 YAGO 最初遵循这种由表达逻辑形式支持的范式(还记得 DL 引用描述逻辑的时代吗?👵)和 RDF、OWL 之类的标准。
三重事实。爱因斯坦同时在两所大学上学吗?图片作者。
使用三元组,上面描述阿尔伯特·爱因斯坦上过哪些大学的例子可以编码为两个三元组:
*Albert Einstein, educated at, ETH Zurich
Albert Einstein, educated at, University of Zurich*
嗯,对于简单的应用程序来说,这看起来还不错,但事实证明我们的世界有点复杂,要把所有东西都放进三元组里。例如,两个三是不是意味着阿尔伯特·爱因斯坦同时在两个地方接受教育?或者他们授予他同样的学位?
事实上,爱因斯坦在苏黎世联邦理工学院获得了数学专业的学士学位,而在苏黎世大学获得了物理学专业的博士学位。
我们能有一种机制来更详细地表达事实吗?
**是的!**在 KG 世界中,至少有两种方法可以做到这一点——RDF *图和标签属性图(LPG) 。它们都允许通过将辅助键-值(关系-实体)对附加到 KG 中的边来进一步实例化每个事实。并且这两者都已经得到了图形数据库市场上主要供应商的支持👍。
在 LPG 世界中,节点和边自然都可以有键值属性。 Neo4j 大概是 LPG 家族里最大牌的了。您可以使用(打开)密码查询 lpg。最近的新冠肺炎 KG 可作为 Neo4j 转储。
RDF最初由 Olaf Hartig 提出(他的博客是了解 RDF和相关技术的一个很好的起点),旨在缓解声名狼藉的 RDF 具体化机制的许多问题(查看 Frey 等人的调查以全面了解具体化),同时保留与 RDF 图相关的推理能力。在坚实的理论基础的支持下,RDF提供了一些用更多细节来丰富三元组的方法。您可以使用 SPARQL (SPARQL 的扩展,用于处理 RDF)查询 RDF图。 Apache Jena 、 RDF4J 、 N3.js 、 Blazegraph 、 AnzoGraph 、 Stardog 、 GraphDB 支持 RDF和 SPARQL
我们在 RDF*语法中的例子可以是这样的:
*<< Albert_Einstein educated_at ETH_Zurich >>
academic_degree Bachelor ;
academic_major Maths .
<< Albert_Einstein educated_at University_of_Zurich >>
academic_degree Doctorate ;
academic_major Physics.*
超关系图还是超图?
对于这些 kg,什么是合适的术语?直到 Rosso 等人在他们最近的 WWW'20 工作中建议使用“超关系图”之前,一直有一个小的词汇缺口。尽管如此,术语“超图”还是有一个常见的误用。我们也想提倡“超关系”图。🤝
主要区别在于对事实的表述。超图假设有一个(命名的)超边统一几个实体:
*education(Albert Einstein, ETH Zurich, Bachelor, Mathematics)
education(Albert Einstein, University of Zurich, Doctorate, Physics)*
每个超边由 4 个节点组成。注意,我们丢失了与学术专业和学术学位相关的谓词。图片作者。
看起来像 n 元关系,对吗?🤨我们这里有几个问题:
- 我们丢失了分别与学士/博士和数学/物理相关的类型关系
academic_degree
和academic_major
。相反,超边缘的类型是一种抽象(或者是一种相当奇怪的语义混合🤯)的educated_at
、academic_degree
和academic_major
。如果一个事实还包含一个辅助谓词academic_supervisor
呢?我们需要定义一个新的超边,比如说, education1() ,混合 4 那些随着谓词和限定词的数量呈指数级增长的关系。📈
2.此外,我们还失去了学位和专业的辅助特征,即它们旨在描述它们的主三元组。例如,学士和数学是辅助工作阿尔伯特·爱因斯坦和苏黎世联邦理工学院,因此,应该以这种方式对待。超边中的实体元组假定其元素同等重要。
也就是说,在接下来的部分中,我们将坚持使用超关系方法。
野外的超关系知识图
在 2020 年,大多数开放域知识群广泛使用超关系事实。 Wikidata 及其 Wikidata 语句模型是超关系 KG 的一个很好的例子。Wikidata 中的每个事实都是一个语句,包含一个主三元组和一组辅助限定符——实体关系对。使用 Wikidata 语句,我们的 Albert Einstein 示例可以像下面这样简单地建模:
超相关事实。图片作者。
在那些语句中,*(学术 _ 学位,学士)**(学术 _ 专业,数学)*是三重 <阿尔伯特·爱因斯坦,学历 _at,苏黎世联邦理工学院> 的限定词。
值得注意的是,Wikidata(通常是超关系范式)并不区分只在主三元组或限定符中使用的实体和谓词,即,
所有的谓词和实体都可以在三重术语或限定词中使用
(尽管在当前的 Wikidata 版本中,有些实体和关系只能在限定符中看到)。我们将在以下几节中使用该属性。
至于其他 kg,从 2018 年开始,DBpedia 的新版本包含类似于 Wikidata 中的具体化声明。YAGO 4 也采用了事实的 RDF*编码。🙌
Freebase 怎么样?🤔好吧,2020 年你可能不应该练习🧟♂️死灵术,因为免费基础不再被支持和更新。然而,Freebase 中的复合值类型(CVT)节点确实类似于三元组的具体化[但看起来更像 n 元关系]
图形表示学习
我们在这里的任务是学习超关系图的表示。
对于表示,我们指的是实体(节点)和关系(类型化边)嵌入。然后,嵌入可以用于下游任务,如链接预测、节点分类、实体对齐,以及更多可以用于 NLP、CV 和其他人工智能领域的任务。🍀
图形表示学习(GRL)是发展最快的领域之一🚀在机器学习领域,有一些文章(Michael Bronstein 的一系列帖子,【20】的评论( mine ,Sergey’s)和neur IPS’19的论文)、书籍(作者、、马和唐)、课程( CS224W ,COMP 766😉)涵盖基础和高级主题。
在编码器-解码器范例中,编码器通常是 GNN(图形神经网络),而解码器是嵌入的函数,其返回与某个下游任务相关的值或向量,例如,实体成为给定的 <主语、谓语> 对的对象的概率。
三基 kg 有什么?
挺多的!😍
编码器:多关系 GNN 编码器家族,如 R-GCN ( Schlichtkrull 等人,ESWC 2018 )和 CompGCN ( Vashishth 等人,ICLR 2020 ),在消息传递框架内扩展了原有的图卷积网络(GCN) 算法。
解码器:实际上,传统的 KG 嵌入算法如 TransE、ConvE、RotatE 等都是用于链路预测任务的解码器的很好例子。最初,它们也可以被训练为直接端到端优化的仅解码器模型👉关于链路预测任务。
超关系 kg 有什么?
嗯,没那么多🤔(截至 2020 年秋季)
编码器:???
解码器:铰链 Rosso 等人提出的基于 CNN 的端到端超关系图上链接预测模型。
嗯,我们无法应对 GNN 编码器部分中如此耀眼的深渊🕳,并在我们最近的 EMNLP'20 论文“超关系知识图的消息传递”中提议⭐️凝视⭐️,该论文与 普里扬什·特里维迪 、 高拉夫·马赫什瓦里 、 里卡多·乌斯贝克 和 延斯·莱曼 一起撰写
StarE 是一个多关系 GNN 编码器,它为超关系 kg 扩展了 CompGCN。
这个名字的灵感来自 RDF*😊StarE 的设计考虑了以下特点:
StarE 中聚合限定符的一个例子。图片作者。
- 关系的显式建模,包括限定关系;
- 限定词中的辅助实体和关系与主三元组中的实体和关系的分离;
- 然而,任何实体和任何关系仍然可以用在主三元组以及限定词中;
- 限定词顺序的排列不变性—它们不显示任何特定的顺序,可以自由地重新排列。也就是说,对于主三联 < <阿尔伯特·爱因斯坦来说,受教育于,苏黎世联邦理工学院> > 无论*(学术学位,学士)是在(学术专业,物理)*之前还是之后。
给爱好者一点数学知识👩🔬
让我们追踪关系感知 GNN 编码器在其邻域聚合方案中的演变:
消息传递算法。图片作者。
在 StarE 中,出现在节点u
和v
之间的主三元关系h_r
通过函数gamma()
用限定符h_q
的聚合向量来扩充,该函数可以是加权和、乘法、串联或任何其他二元函数(我们使用加权和)。
我们通过以下方式获得向量h_q
:
也就是说,我们首先通过复合函数phi_q()
将限定符关系和实体嵌入h_{qr}
和h_{qv}
分别汇集到单个向量中,复合函数phi_q()
可以是来自 KG 嵌入族的评分函数,例如 RotatE。然后,我们应用一个排列不变的聚合函数(sum,尽管我们也探讨了乘法)将任意数量的限定符汇集成一个向量,并最终通过一个转换矩阵将其投影W_q
。
由于所有的实体和关系通常可以在主三元组以及限定词中看到,W_q
旨在学习实体和关系的限定词特定的表示。
我们仍然保留 CompGCN 组件:phi_()
是一个类似于phi_q()
的复合函数,但是现在它合并了一个具有丰富边表示的节点。W_{\lambda}
是传入、传出和自循环关系的权重参数。
超关系 kg 的稀疏编码
出于效率原因,gnn 在稀疏矩阵上操作。对于基于多关系三元组的 kg,以下示例为三元组
*Q937, P69, Q11942
Q937, P69, Q206702*
可以用首席运营官格式表示为一个[2, num_edges]
张量,并为边缘类型增加一行
[Q937, Q937]
[Q11942, Q206702]
[P69, P69]
带有限定符的超关系事实可以写成如下形式:
*Q937, P69, Q206702, P812, Q413, P512, Q849697
s, r, o, qr1, qv1, qr2, qv2, …, qrN, qvN*
其中前三个条目总是表示“主”三元组,随后的对是没有特定顺序的限定符(记住 Wikidata 中的顺序不变性)
在首席运营官矩阵的每个“列”可能有任意数量的限定符的情况下,超关系 kg 的稀疏表示是什么?在论文中,我们提出以下编码:
超关系知识的稀疏编码。图片作者。
也就是说,我们有两个首席运营官矩阵:
- 带有隐式列索引 k 的普通“三重”首席运营官
- 形状
[3, num_qualifiers]
的“限定符”首席运营官,其中第一行包含“三元”首席运营官中各列的索引,第二行包含限定符关系,第三行包含限定符实体。索引行将一列限定符连接到主三元组。也就是说,共享相同索引 k 的“限定符”首席运营官中的列属于“三元”首席运营官矩阵中的相同的第 k 个三元组。这允许我们在内存中为 KG 中的限定符的数量准备 O (q ),并且总内存为o(| edges |+| qualifiers |)⚖.️
我们需要谈谈数据集
我们简要地谈到了将超关系事实编码为一系列实体和关系。但是,是否已经有可靠的数据集来对这些千克进行实验了呢?传统上,KG 嵌入是在链接预测任务上评估的,而图 ML 任务包括节点分类、图分类、实体匹配等等。
到目前为止,只有两个链接预测数据集:由关等人提出的维基百科(wikipeople)——它是一个描述,嗯,人的维基数据的转储,以及由免费提供的 jf17k(T12)然而,我们发现了主要的缺点😞有了这两个人:
- 维基人有太多带有文字(年份)的限定符。将文字视为另一种实体是不可取的,因为数字是连续的值,应该以这种方式处理(嗯,这是 KG 嵌入文献中文字的一个普遍问题🤔).也就是说,在大多数情况下,这样的限定符被简单地丢弃了。这导致数据集只有 2%的事实有限定符,而 80%的事实只有一个限定符对:/
- JF17K 有测试装置泄漏。事实上,作者自己也发现了很多冗余的三联体,不推荐在实验中使用。HINGE 最初更多的是一个 n 元数据集,它通过辅助谓词将其转换成一种超关系格式。我们进行了进一步的研究,发现超过 40%的测试语句共享与训练集中相同的 (s,r,o) 主三元组。也就是说,在主体/客体预测任务中,简单的三重试探法可以胜过🏆我们在论文中展示的所有以前的超关系方法。
由于这两个数据集都不太适合评估超关系方法,我们根据以下准则对 Wikidata 中的 WD50K 进行了采样:
图片作者。
- 保留类似 Wikidata 的限定符分布。在普通的 WD50K 中,大约 13%的语句有限定符(接近 Wikidata 中全部语句的 17%)
- 所有限定符都是实体关系对,没有文字
- 实体和关系可以在主三元组和限定词中看到
- 99%的语句最多有 6 个限定符对
为了进一步的实验,我们采样了 3 个额外的数据集:
- WD50K (33) —大约 33%的语句有限定符
- WD50K (66) —大约 66%的语句有限定符
- WD50K (100) —所有语句都有限定符
自然,这些数据集比原来的 WD50K 小,具有更多限定符特有的实体和关系。
凝视链接预测
在这一步,我们最终有了一个 StarE 编码器和合适的链路预测数据集用于实验。我们的主要研究问题是:
限定词有助于预测超关系事实的主语和宾语吗?
用于链路预测的 StarE +解码器。图片作者。
也就是说,给定主语、谓语和所有限定词,我们预测宾语,反之亦然。为此,我们将给定的事实线性化为如图所示的序列,并使用具有 avg 池和最终 FC 层的 2 层转换器作为解码器。
转换器还允许我们使用屏蔽的填充标记来输入不同长度的序列👺从自我关注的计算中。
为了进行比较,我们在同一任务中应用了仅解码器铰链和 2 层变压器,以测量 StarE 编码器是否带来任何好处。
事实证明的确如此。🎆
各种 WD50K 数据集上的主/客体预测精度。限定符越多,收益越大!图片作者。
我们观察🕵:
- 与只有解码器的方法相比,StarE 极大地提高了链路预测性能;
- 当数据集中有更多的限定符时,StarE 甚至更有效(性能差距更大);
- 超关系方法确实有助于更好地预测给定限定符的主体和客体。
你需要多少限定词才能看到质量的提高?两个就够了😉
仅仅 2 个限定符就能带来明显的性能提升。图片作者。
我们的实验程序用特定的数字和交互式图表报告,这里用权重&偏差T4📈
所以外卖🔖致 KG 社区:
- 寻求将描述性限定词分配给图中更多的三重事实——越多越好
- 如果您指定了限定符,请添加 2 个或更多!
结论和资源
- 超关系图比简单的三元组更接近现实,更详细地描述事实
- RDF*和 LPG 提供了构建超关系知识库的方法
- 超关系图不同于超图
- 超关系 KGs 已经在使用了——无论是在开放领域 KGs 还是在工业领域
- RDF*激励的 StarE——一种用于超关系 kg 的 GNN 编码器,可以与用于下游任务的解码器配对
- 与只有解码器的方法相比,StarE 改进了链路预测
- WD50K 数据集系列更好地捕捉了超关系 kg 上的链接预测的挑战
您可以在以下网址找到更多信息:
Our EMNLP'20 paper : 消息传递为超关系知识图 (arxiv 预打印)
代码 : Github Repo
数据集:Zenodo page
权重&偏向 Repor t: 此处
提高随机森林分类器的可解释性
如果随机森林中的底层树形成集群,我们可以从每个集群中提取一棵树来表示随机森林
对于数据科学家来说,可解释性通常与结果同样重要。面对可解释性与准确性的权衡,我们经常避免部署深度学习模型和复杂的集成。基于决策树的随机森林分类器就是这样一种强大且常用的方法。这个想法是通过平均它们的结果来减少几个噪声决策树的预测中的方差。在可解释性方面,大多数人将其置于常规机器学习模型和深度学习之间。许多人认为这是一个黑箱。
尽管被广泛使用,随机森林通常仅用特征重要性和邻近图来解释。这些可视化非常有用,但还不够。许多研究人员正试图确定使用决策树来表示随机森林的方法。一个有趣的方法是近似一个单一的决策树,如周和胡克1和温伯格[2]所解释的。
在这篇文章中,我提出了一个替代的和新颖的解决方案。我证明了随机森林中的底层决策树可以形成集群,这使我们能够从每个集群中提取代表性的决策树,并使用它们进行解释。
底层决策树会形成聚类吗?
对于这个分析,我使用了随机森林分类器的 Scikit-learn 实现,对于二进制分类问题,n_estimators = 20,max_depth = 10。该数据有 75,800 个观察值和 372 个特征3。
训练模型后,第一步是提取底层决策树,并在所有深度级别(0 到 10)对其进行后期修剪。随机森林的 Scikit-learn 实现允许使用。评估者 _。然而,我们需要为后期修剪编码,利用决策树的二叉树结构。这个过程产生了 11 X 20 = 220 个独立的决策树。
接下来,使用每个决策树预测测试集的输出概率,以获得预测概率的[220 X(测试集大小)]矩阵,并对该矩阵执行相关性分析、t-SNE 和层次聚类,以识别聚类。
- 关联
下图描绘了每棵树在不同深度级别的预测之间的相关性。在低深度,随机森林中的树木往往是相似的,所以我们看到了高度的正相关。随着深度的增加,相关性降低,因为树在不同的特征上开始分裂。重要的是,我们看到的模式表明,在每一个深度水平的集群的潜在形成。
基础决策树预测中的相关性。轴代表树的 ID。
2。t-SNE
t-SNE 是一种非线性降维算法,对于可视化高维数据非常有用。下图显示了结果,其中每个数据点代表一个决策树,标签代表该树的 ID。结果还显示了在不同深度水平上的集群形成。
底层决策树预测的 t-SNE 表示。
3。层次聚类
最后,让我们来看看凝聚集群。相关分析和 t-SNE 映射可以给我们提供关于最佳聚类数的有用信息。在这个特殊的例子中,我选择了两个集群。对于高维矩阵来说,在二维中可视化分层聚类是不可能的。然而,由于这是一个二进制分类问题,我们可以通过在其接收器操作特性(ROC)曲线上对每棵树进行颜色编码聚类分配来可视化结果。下面的结果也验证了簇的形成。
聚类分配颜色编码的决策树 ROC 曲线
观察这三个图中的树 id,您可以观察到这三种方法的聚类是相当一致的,并且树停留在不同深度级别的相同聚类中。
结论
总的来说,我想从上面的分析中展示的关键思想是随机森林中的底层决策树可以展示集群。一旦我们对集群有了信心,最后一步是从每个集群中挑选一棵有代表性的未修剪的树,并将其呈现给客户。代表树可以是最靠近聚类中心的树,也可以是聚类中 AUC 最高的树。需要注意的是,修剪只是为了演示集群。最后一步,你只需要未修剪的树。
1周逸尘和贾尔斯·胡克。2016.通过单树近似解释模型。arXiv 预印本 arXiv:1610.09036 (2016)。
[2] Weinberg AI,Last M .从用于快速大数据分类的决策树模型集合中选择代表性决策树。j 大数据。2019;6(1):23
[3]https://www . ka ggle . com/c/Santander-customer-satisfaction/data
表示图形数据结构
图表和数据科学
真的都是边缘问题。
当你表示一个图结构 G 时,顶点 V 非常容易存储,因为它们是一个集合,可以直接这样表示。例如,对于 5 个顶点的图形:
V = {0,1,2,3,4}
当你开始存储边缘时,事情变得更有趣了。这里有三种常见的结构可用于表示和导航边集:
- 边缘列表
- 邻接矩阵
- 邻接表
我们将看一看一个简单的图形,并遍历它的每个表示。我们将根据其空间复杂度和邻接复杂度来评估每一个。
但是首先一些术语
- 一个图 G ( V , E )是由一组顶点( V )和一组边( E )定义的数据结构。
- 顶点 ( v )或节点是一个不可分割的点,由下图中的字母组件表示
- 一条边 ( vu )将顶点 v 和顶点 u 连接在一起。
- 顶点 v 的度 d ( v ),就是连接到它的边数。
- 空间复杂度显示为θ(G),表示需要多少内存来保存给定的图形
- 邻接复杂度**用表示 O(G) 是找到一个给定顶点的所有邻接顶点所需要的时间 v 。
边缘列表
**给定带有顶点集的图 G 😗*
V = {0,1,2,3,4}
现在让我们给 G 一些边,使它成为一个合适的图形:
图一。g,都长大了
G 的边列表是边的文字列表,其中每条边是它连接的顶点的列表,在这种情况下:
E = [[0,1],[0,2],[0,4],[3,4]]
赞成的意见
- 简单!
- 大 s 步距复杂度ofθ(G)= | E |
骗局
- O(G)= | E |的邻接复杂度。这里的 |E| 是一个很差的值。你必须查看每一个边缘,以便将它们全部排除。从某些方面来说,这是最糟糕的成绩。
邻接矩阵
G 的邻接矩阵是每个 v 都有对应的列和行的方阵。如果两个顶点 v,u 共享一条边,那么在相应的位置有一个 1,否则是一个 0。
图二。三个不同 4 点图的邻接矩阵
对于我们的图来说,G 是:
G = [[0,1,1,0,1],
[1,0,0,0,0],
[1,0,0,0,0],
[0,0,0,0,1],
[1,0,0,1,0]]
赞成的意见
- 高度可解释性。即它是对称的,除非它是一个有向图,你可以在每个矩阵条目中整齐地存储边值。
- 体面的邻接复杂度**的 *O(G) = |V|。*为了找到与 v、相邻的所有顶点,我们需要用邻接矩阵扫描它们的整行。
骗局
- 可怕的 s 步调复杂度的θ(G)= | V |。这里我们存储了长度为 2 的每个可能的顶点排列,包括每个与其自身配对的顶点。这是可能组合的最大顶点集的两倍多,( |V| choose 2)
邻接表
G 的邻接表是另一个链表。这一次,我们将为 g 中的每个 v 创建一个空列表,而不是列出每个单独的边。
E = [[],[],[],[],[]]
这里,每个列表元素的索引代表其对应的顶点。现在我们需要遍历并添加每个顶点的相邻邻居列表。
图三。又回来了!
E = [[1,2,4],[0],[0],[4],[0,3]]
虽然这是一个最简单的列表,但我也发现把它想象成一个字典很有帮助,其中每个顶点都是一个键。
E = {0:[1,2,4],
1:[0],
2:[0],
3:[4],
4:[0,3]}
优点:
- 就像一本字典!
- **S 步距复杂度ofθ(G)= | V |+2| E |我们有一个每个顶点的列表,这些列表总共将存储 2 个 |E| 元素,因为每个边将出现在两个顶点列表中。
- 极大的邻接复杂度。对于给定的顶点 v , O(G) 等于d(v)v的度数。当寻找所有相邻的邻居时,这实际上是这里的最佳可能值。
最佳表示
选择最佳数据结构来表示给定的图 G 实际上取决于 G 中的边密度。这可以大致概括如下。
- 如果 |E|≈|V| ie 的边数与顶点数一样多,那么 G 被认为是稀疏的并且邻接表是优选的。****
- 如果 |E|≈ ( |V|选择 2) ie 接近 G 中的最大边数,则认为密集**,邻接矩阵优先。**
边列表很少被使用,因为它们的邻接复杂度很低。
来源
数据科学中的再现性
它的意义超乎你的想象
作为一种追求,科学的核心一直是可复制性。毕竟,如果一个关于物质世界的主张被提出,而证据并不支持这样的主张,不管这个想法有多少意识形态或既得利益推动它,你都没有理由相信它。在我们生活的这个看似后真相的世界里,政客、媒体和社交媒体上的声音传播着各种不诚实的信息,让可复制声明对你的诚信有利。作为一名数据科学家,这是你工作的一部分。
我认为数据科学中的再现性不如更成熟的科学领域中的再现性那样容易理解。例如,一项研究可以阐明一个或两个与测试两个或更多组之间的平均差异有关的简单主张。例子包括…
- 治疗 A 与安慰剂治疗 B 相比有统计学显著差异吗?
- 暴露在不同长度刺激下的群体会表现出不同的结果吗?
- 治疗的效果有多大?
由于通常存在对统计显著性结果的发表偏见,如果一些研究的目标是重复其他研究已经完成的内容,那么这些研究就不会被发表。然而,当它们被执行时,如果它们在相似的输入下没有得出相同的结论,那么它就对最初的声明产生了怀疑。这项研究没有被复制。
在结构工程(我的第一个职业)领域,我们使用一种可再现的形式来验证其他人完成的设计。通常一个工程师会负责设计一座桥梁,这是一个非常复杂的混凝土和钢块。如果你从来没有出去过,这里有一张照片。
克里斯托弗·伯恩斯在 Unsplash 上拍摄的照片
看起来很复杂吧?那位工程师的设计在交给承包商施工之前经过了多次仔细审查。通常在检查过程中,另一个工程师会给出相同的初始输入,进行平行设计,然后他们交换意见。相同的潜在现象,但由两个独立的工程师得出。任何差异通常都突出了原始设计中的低效率,或者关于桥梁应该如何建模的分歧点。目标是通过再现性达成共识。
什么是再现性?
与我们讨论的简单获得相同结果相比,再现性有更多的维度。掌握了所有这些方面,你的工作就更有可能对人们有用,并被用来影响更高层次的决策。让我们探索一下
相同的代码
您的代码应该被很好地记录,并且应该实际运行。去想想。这里有两个成功的主要因素
- 依赖管理——你如何管理第三方软件包,它们是否被主动维护,版本是否被锁定?您对系统级依赖关系有强大的控制吗?
- 环境管理 —你用什么语言版本构建你的产品?应用程序环境会使用相同的吗?
在数据科学咨询角色中,很多时候这两个部分被忽略了,后来当客户交付变得更加重要时才被添加进来。这两者都是至关重要的,因为您应该预料到分析将在不同于编写代码的机器上运行,或者在其他人精心设计的环境中执行,并且您如何保证他们具有与您相同的包需求、系统依赖性和语言版本的历史?
相同的数据
数据版本化 越来越流行了。c ookie cutter 数据科学框架内置了一个松散版本。例如,在 cookie cutter 中,数据被分为来自第三方来源的原始数据、中间数据、已处理数据和外部数据。这种分割数据的直观方式可以帮助您讲述数据转换的故事,从原始格式转换成可以分析的格式。使用数据版本化围绕任何数据转换构建一个叙述将允许您与利益相关者一起验证您的逻辑是合理的,您的数据是可信的。这种分析可以扩展,甚至可以根据需要恢复,这允许您拥有与 git 提供的代码相同的敏捷性,但现在是在数据中。
相同的随机数
你在你的机器学习管道中使用随机种子吗?它们允许在构建管线时快速解决问题,因为它们在模型输出中引入了再现性。当你使用带有随机效果的学习算法时,这一点尤其重要,比如神经网络或随机森林。当训练/测试分割、交叉验证或优化发生时,随机数将始终是机器学习工作流的一部分。你可以用种子号来控制它们。把这些种子数字想象成控制一个混杂变量,随机误差。如果你不使用种子,那么你不知道模型输出的变化,标准误差,重要性等等。是由于随机效应还是由于超参数的变化。为了确保这种随机性在您构建产品时至少是暂时一致的,那么设置随机种子可以控制和消除您的 ML 管道中的随机偏差。
相同的故事
现在我们已经完成了上述所有步骤,我们希望确保我们的工作产生持久的影响。我们希望确保我们得出的结论能够在利益相关者的头脑中复制和持续。我们不希望我们的观众只是点点头,而不采取任何行动。是什么让这些想法以一种有效的方式坚持下来?
故事。无论是你的主管、客户还是首席执行官,围绕数据构建一个令人信服的故事是实现这一目标的最有效方式。我们的祖先通过这种方式传递知识,因为它是有效的。什么都没变,还能用。
这也是再现性和可解释性之间的联系。围绕你的数据和模型讲述一个故事,并解释它为什么做出预测(例如使用特征重要性或 SHAP 值)会让你的结论在人们的脑海中重现。这种想法之所以能站住脚,是因为你传达了一个令人信服的故事,人们知道他们为什么应该关注它,将复杂的数学提炼为丰富和可操作的东西。这是科学的艺术。当所有这些结合在一起时,这真是一个美丽的组合。
概括起来
可复制性的意义何在?不仅能让人们运行相同的代码并得到相似的结果,还能让他们得出相同的结论,并让这些结论在磁盘上和人类记忆中持续存在。不要把可再现性仅仅局限于虚拟环境,甚至分析结论,这是一个更丰富、更重要的概念。
需要思考的事情:如何在自己的项目中引入更多的可复制性?
感谢您阅读本文!我希望它能让你大开眼界,增长见识。如果你有任何问题或者只是想拓展你的人脉,请随时在 Linkedin 上与我联系。
Azure 机器学习的可复制环境
甚至不知道如何创建 docker 文件
图片作者。
码头工人
几年前,Docker 开始流行起来。每个人都声称这个工具为他们节省了大量的时间。要解决构建、部署和管理应用程序的混乱过程,您唯一需要的就是 Docker。就像天堂一样。
但是…这样美好的事情可能是真的吗?事实证明一切都是真的。天堂的一小部分可能错误地落到了地球上?。可能是,也可能不是,但正因为如此,如今如果你被迫为可复制环境选择明星球员,你的答案肯定会以“D”开头,以“ocker”结尾。
机器学习的再现性
此外,你可能已经知道,在任何专业的机器学习项目中,可重复性都是必须的。问题是实现这一点并不总是一件容易的事情。
数据科学家喜欢在他们的本地机器上工作,学习 Docker 可能会分散他们的主要任务:pip 安装所有东西。
如果你是其中之一,我在这里不只是批评你。我带来了一个解决方案。开发 Azure 机器学习的人知道,制造可复制的 Python 环境是捕捉数据科学家的金矿。他们提供了一种解决方案来处理 Jupyter 笔记本电脑中的环境。
Azure 机器学习
所以,万一你对 Azure 机器学习一无所知,我简单给你解释一下。Azure ML 是一个旨在将与机器学习生命周期相关的每个步骤集中在一个地方的地方:安全的工作空间、存储、模型管理、计算、模型再现性等等。
从我的 Azure ML 工作区捕获。图片作者。
在左侧栏中,您可以看到提供的各种选项。但这并不是对 Azure ML 的概述,所以我将直奔主题:可管理的环境。
在高层次上,启动 Azure 机器学习工作空间后,可以创建一个环境对象。您可以使用不同的选项来配置您的环境。尽管如此,大多数 commons 启用 Docker,分配 Conda 依赖项,以及您喜欢的 PyPi 包。
正如您在下图中所看到的,您可以在您的工作空间中创建一个托管 Docker 环境,以满足您的包需求。
图片作者。
作为 Azure 机器学习提供的标准服务,可以注册。这使我们有可能在没有一堆没人能理解的文件的情况下对我们的环境进行版本化。
有三种类型的环境可用:
- 策划环境:这些是预安装包的列表。它们由缓存的 Docker 映像提供支持,减少了运行准备工作,实现了更快的部署。
- **系统管理的环境:**是 Azure 采用的默认环境。在这里你可以让 Conda 来处理你的依赖关系。如果您想要个性化的产品包,并且希望避免自己管理环境,这是最佳选择。
- 用户管理的环境:在这里,您负责安装代码运行所需的软件包。这里唯一的 Azure 要求是你必须在你的 pip 依赖项之间列出 azureml-defaults 包。
但是足够的概念,一点动手不会伤害你。
使用 Azure ML
我们将会看到前两种环境类型的例子,因为它们对于没有太多知识的你来说更容易工作。
为了今天的工作,你可以在你的 Azure ML 工作空间中的“计算”选项中创建一个实例,或者只是设置你的本地环境。万一你选择了第一种,而你不知道怎么做,我最近在下面的链接里做了一个教程:
读完这篇文章后,你会明白 Azure ML 是如何处理数据的,MLOps 是如何关联的,并学习如何通过…
towardsdatascience.com](/data-versioning-in-azure-machine-learning-service-acca44a3b3a1)
策划环境
让我们先尝试一个策划的环境。您可以使用以下代码检查 Azure 给出的选项。
注意:如果你在本地使用它,确保有 JSON 配置文件。
运行代码后,您将看到许多环境可能性,每一个都有自己的包和依赖项。因此,您可以选择满足您要求的任何一个。
假设你喜欢这个环境*azure ml-Scikit-learn-0 . 20 . 3。*这里显示了代码和部分输出,只是为了让你检查包。
图片作者。
如你所见,环境已经为你准备好了,只要叫它的名字就行了!你甚至可以在不了解 pip 和 Conda 的情况下使用它。
系统管理的环境
假设您没有在任何最后的列表中找到您的特殊包。或者您的软件包在那里,但是您需要使用的组合不可用。
对于系统管理的环境来说,这是一个完美的场景。您可以在这里指定您想要的 Conda 和 pip 依赖项。
首先,您应该为您的环境指定一个名称。然后,可以将 python 用户管理的依赖项设置为 False,最后,让 Docker 创建可重用的可缓存映像。
假设我们的项目需要 scikit-learn 0.23.2 版本。那么,我在哪里指定我的需求呢?嗯,上一个要点中引入的 CondaDepdencies 不仅仅是为了好玩。在那里你可以定义你的软件包的确切版本,并决定是 Conda 还是 pip 安装它们。
另一个功能是您可以存储环境变量。如果你正确使用它们,它会帮你解决一些头疼的问题。
设置好环境后,您可以将它注册到您的工作区,我们已经在最后一行代码中完成了。注册环境将使我们有机会检索我们想要的任何版本。现在想象一下,你忘了列出博鲁塔包裹。嗯,那没问题。您可以更新您的 pip_packages 列表并再次注册环境。
厉害!但是假设您的代码上周投入生产,没有 Boruta 包,您需要知道环境是如何配置的。又来了!很简单。正如您将在输出标题中看到的,您的第一个版本与您注册的版本完全相同。
图片作者。
难以置信!现在你的团队中的每个人都可以在不知道任何命令的情况下享受 Docker 获得的好处!
正如您所看到的,我们实际上并没有使用我们刚刚创建的环境。为什么?因为要理解如何训练我们的模型,我需要先解释一下什么是估计量。这已经足够复杂,可以再写一篇文章来解释估值器了。
后续步骤
如果你现在想训练你的模型,不要担心,下一篇文章很快就要来了,在那里你会明白估计器是如何工作的。
我真的希望你喜欢或发现这篇文章有用!如果你喜欢这个内容让我知道!我们可以更详细地回顾 Azure 机器学习服务的其他组件。
关于作者:我对数据科学、云基础设施、商业问题和写作充满热情。我最近获得了 DP-100 Azure 数据科学家助理认证,我喜欢一拿到就分享所有的知识。
如果你喜欢,请在媒体和 Linkedin 上关注我。如果你想给我写信,我最近在推特上。我很乐意与你交谈!
如果你想多读一点,看看我最近的一些帖子:
[## 想成为 Azure 数据科学家助理(DP-100)吗?让我们
读完本文后,您将对云认证和 DP-100 有更深刻的理解
towardsdatascience.com](/thinking-about-becoming-an-azure-data-scientist-associate-dp-100-lets-32f8766df21e) [## 具有两个以上特征的聚类?尝试用这个来解释你的发现
使用 Plotly 的 line_polar 将向我们展示一种令人兴奋的聚类解释方法。此外,我们将看到…
towardsdatascience.com](/clustering-with-more-than-two-features-try-this-to-explain-your-findings-b053007d680a)
可再生机器学习
向开放和可访问的 ML 研究迈进了一步
NeurIPS (神经信息处理系统)2019 年会议标志着他们年度再现性挑战的第三年,也是他们的计划委员会首次有再现性主席。
那么, 机器学习 中的再现性是什么?
再现性是被重新创造或复制的能力。在机器学习中,再现性是指能够重新创建一个机器学习工作流,以达到与原始工作相同的结论。
为什么这很重要?
一个来自新研究的算法,如果没有可重复性,可能很难研究和实现。随着我们越来越依赖 ML 和 AI 系统进行决策,集成一个没有完全理解的模型可能会产生意想不到的后果。
成本和预算限制是受再现性影响的另一个方面。如果没有硬件、计算能力、训练数据和超参数调整等更细微的方面的细节,采用新算法可能会遇到巨大的成本和大量的研究工作,只会导致不确定的结果。
再现性,建立值得信赖的 ML 的一个因素(作者照片)
如何识别一个 ML 模型/研究是否符合重现性标准?
这篇文章探讨了研究论文中提出的两种建立再现性的方法:
构建可复制的机器学习流水线 提出了评估可复制的机器学习流水线的清单。
作者认为信息缺失是所有再现性问题的根本原因。丢失的信息可能是有意的(商业秘密)或无意的(未披露的假设)。他们专注于纠正阻碍再现性的非故意问题的方法。
影响再现性的因素和建议的解决方案总结如下:
训练数据 : 一个模型对不同的训练集产生不同的结果。解决这个问题的一个方法是采用一个记录训练数据变化的版本化系统。然而,对于大型数据集来说,这可能不切实际。使用记录了时间戳的数据是一种变通方法。另一种选择是定期保存数据散列,并记录计算方法。
特征 : 特征可以根据它们被选择和生成的方式产生不同的结果。应该对生成特征的步骤进行跟踪和版本控制。其他最佳实践包括:I)保持单个特性生成代码相互独立;ii)在对某个特性进行 bug 修复的情况下,创建一个新特性。
模型训练 : 记录模型如何被训练的细节将确保可重复的结果。特征变换、特征顺序、超参数和选择它们的方法、集成的结构都是需要维护的重要模型训练细节。
**软件环境:**所使用的软件版本和包也在复制原始 ML 模型中看到的结果中发挥作用。可能需要使用精确匹配的软件。因此,即使有软件更新,最好还是使用最初训练模型的版本。
向量化可独立再现的机器学习研究迈出一步 试图量化研究论文中可再现性的因素。
在这里,作者试图独立地复制(不使用原作者的代码)255 篇论文。他们记录研究论文的属性,并使用统计假设检验分析再现性和属性之间的相关性。
他们在每张纸上总共使用了 26 个属性。
明确的(不需要解释):作者数量、是否有附录(或补充材料)、页数(包括参考文献,不包括任何附录)、参考文献数量、论文发表的年份、首次尝试实施的年份、地点类型(书籍、期刊、会议、研讨会、技术报告),以及具体的发表地点(如 ICML neur IPS)。
轻度主观:表格数量、图表数量、等式数量、证明数量、指定的精确计算、指定的超参数、需要的计算、可用的数据、伪代码。
主观:概念化数字的数量,使用范例玩具问题,其他数字的数量,严谨性与经验性,论文可读性,算法难度,主要话题,看起来吓人。
结果和重要关系
为了确定显著性,作者对数字特征使用非参数Mann–Whitney U 检验,对分类特征使用带连续性校正的卡方检验。
在 26 个属性中,有 10 个与再现性显著相关。
作者回答说,这些是表格数量、方程、所需计算、伪代码、指定的超参数、可读性、严谨性与经验性、算法难度、主要主题。
关于重要属性的信息越多,复制一篇论文就越容易。然而,方程式数量与再现性负相关。这看起来确实与直觉相反,作者提供了两种理论来解释原因: 1)拥有大量方程会使论文更难阅读,因此更难复制;2)拥有更多方程的论文对应着更复杂和困难的算法,自然更难复制。
研究局限性
本研究的作者根据个人兴趣选择论文。主题不是随机挑选的,因此引入了选择偏差。此外,研究结果应考虑到作者不是他们所选主题的专家。
第三,有许多主观属性是重要的,需要制定与主观因素相关的客观措施。例如——测量论文可读性或算法难度。
结论
第一项研究采用自下而上的方法,而第二项研究采用自上而下的方法。这两者共同提供了对复制机器学习管道和再现原始结果所必需的因素的洞察。从两种方法的结果来看,模型超参数和计算资源/软件环境是影响再现性的两个重要因素。
一般来说,通过文档和版本控制来记录构建模型的每个步骤是很重要的。毕竟,许多机器学习系统都是黑盒,考虑再现性使研究开放、可访问和可再现。
具有权重和偏差的可重复模型
生产中的机器学习
探索简单的技术,使您的 ML 实验尽可能具有可重复性。
查看互动仪表盘 此处 。
机器学习中有不同层次的随机性。有时他们正在对数据集进行采样,而其他时候则是在机器学习模型(特别是神经网络)本身中。虽然随机性在模型训练中带来了许多优点,但它也引入了一些与可重复性有关的棘手问题。
代码在这里可用。
在这份报告中,我们将回顾一些有望使我们的机器学习实验更具可重复性的方法。在我们进入实质之前,我们将讨论确保我们的机器学习实验可重复的一些动机。
我们开始吧!
我们为什么要关心再现性?
为了开始这一节,我将借用 Joel Grus 的话 再现性作为工程最佳实践的载体 。
Joel 提出了许多非常重要的观点,说明为什么 ML 中的再现性是必要的。这是其中一些-
- 再现性确保了正确性。如果社区里的研究员不能重现你声称的结果,那么你的实验设置可能有问题。
- 有了再现性,您就能在 ML 实验的不同方面获得一种稳健感。例如,数据集的代表性、模型在数据集的任何特定子集上的行为,等等。
- 你会希望能够运行你的 ML 模型,并且在将来仍然得到相同的结果。
- 其他人也希望能够做同样的事情。它为合作、基线评估和更新的实验提供了机会。
最重要的是(从乔尔的上述讲话中)
软件工程的最佳实践会让你成为更好的研究者。
老实说,虽然我知道可再现性,但只有在我看过乔尔的《甲板》之后,我才能真正理解对可再现性的迫切需求。
本报告的重点是开发可再现的模型,这反过来又解决了由不可再现性引起的大部分问题。
开发可复制的模型
在一份报告中满足所有的 ML 模型和框架并谈论可重复性几乎是不可能的。所以,我们只关注一对——神经网络和张量流。请注意,这些概念中的大部分仍然适用于其他框架。
在我们编写任何代码之前,我们需要确保我们的硬件/软件基础设施是统一的。当你在一个团队中工作时,这尤其有用。
涵盖的方法概述
- 统一的硬件和软件设置
- 随机种子+固定(初始)权重
- 可再生数据管道
- 超参数优化
- 保持理智的版本控制
- 确保正确性的测试
- 模型检查点及其他
地面设置和 CUDA-cuDNN
出于“可复制性”的考虑,我准备用以下配置为我的机器托管一台谷歌云平台 AI 平台笔记本——
n1-standard-4vCPUs-15GB
- 特斯拉 V100
- 预配置映像:TensorFlow 2.1(采用英特尔 MKL-DNN/MKL 和 CUDA 10.1)
遵循基础设施一致性的另一个非常重要的考虑是 cuDNN 和 CUDA 的行为(你不会想要在 CPU 上训练你的大型神经网络)。有许多有效的方法来计算神经网络中涉及的操作,并且它们并不总是每次都产生相同的结果,因为这些结果是近似的。
ML 库通常利用 CUDA 和 cuDNN 提供的这些高效的实现。在这样做的同时,它们引入了随机性(这些实现与上面提到的很接近)。另一个原因是 cuDNN 在运行时确定要使用的实现类型。因此,当使用 TensorFlow (2.1)和兼容的 NVIDIA-GPU 时,为了避免潜在的再现性危机,最好在代码中做任何其他事情之前做以下事情
这个实践来自于张量流确定性存储库。感谢 Sebastian Raschka 的 L13 卷积神经网络介绍(第二部分)1/2 讲座,CUDA 和 cuDNN 部分的灵感来源于此。请务必查看由 Duncan Riach所做的这一精彩演示,以了解更多关于深度学习中的决定论的知识。
我们现在可以关注代码的可再现性。
在代码级别对抗不可再现性
我将再次从上面提到的演讲中借用乔尔的一些观点,以及从我自己的经历中得到的一些发现。许多 ML 算法本质上是随机的,并且当算法中存在本质上不恒定的配置时,这种随机性的大部分被引入。例如,根据定义,我们初始化神经网络权重的方式应该是随机的。
随机种子+固定(初始)权重
这里有两个明显的解决方案-
- 修复随机数生成器种子,这样每次尝试生成随机数时,都会得到完全相同的结果。我建议对您在实验中使用的所有库(支持修复种子)都这样做。在 NumPy 和 TensorFlow 中,可以这样做-
还应该注意的是,这段代码应该放在代码的顶部,也就是说,在你开始任何实验之前。
- 另一个解决方案是在开始训练网络之前序列化网络的权重。这样,我们就可以访问网络的初始权重,并且每次训练网络时,我们都可以使用它们来帮助我们产生相同的结果(使用相同的配置)。
现在,当然,神经网络的其他部分也可能引入非确定性——丢弃层、采样层(还记得 VAEs 吗?),潜在载体等等。他们引入的非决定论是好的,因为它通常有助于神经网络表现得更好。我们可以在这些层中多次运行我们的训练数据,并测量每个结果的平均偏差。如果没有任何问题,偏差不会很高。
对抗数据的不可再现性
很多随机性可以来自机器学习模型的更好的一半——数据!通常,在训练模型时,我们提供不同的训练和验证分割。这当然会导致每次不同的模型性能结果。一个更好的方法是在我们训练模型之前修复训练和验证分裂。
如果数据拆分的序列化很困难,那么我们仍然可以在每次拆分数据时提供种子参数。例如,当使用 scikit-Learn 的train_test_split
方法时,我们可以指定seed
参数。这里的想法是修复每次运行函数时会产生不同分裂的所有变量。
常见的例子包括-
- 洗牌训练例子。
- 使用像
glob
这样的库来读取文件,因为它不维护文件路径的顺序。
作为一般提示,在调整训练数据点时要非常小心。您不会希望单独打乱要素及其标注。当您执行数据扩充时,总会有一些随机性。在这种情况下,建议尽可能指定种子。
超参数,到处都是超参数!
基地形象来自这里
超参数仍然是神经网络的核心,超参数调整是一个非常复杂的过程。因此,当您使用相同的网络架构运行不同的实验,但使用不同的超参数配置时,可能很难跟踪这些配置中设置的值。
对于不同的网络架构,事情变得更加复杂,每个架构都有一组不同的超参数设置。这正是权重和偏见真正闪光的地方。无论您是在运行超参数优化还是只想将超参数配置存放在安全的地方,W & B 都能满足您的需求。
对于超参数调优,只需按照以下方式定义您想要测试的值,然后让 W&B 将其清除 (完整代码请参见本笔记本)
只需几行代码,我们就可以生成如下所示的扫描报告。
在此与此表互动
在指定了用于定义模型的超参数之后,您只需通过config
字典(例如config.epochs
)在代码中访问它们。这里有一个端到端的例子。即使您没有进行任何超参数调整,记录您的超参数值也是一个好的做法,您可以通过在调用wandb.init()
时指定config
参数来轻松记录它们的权重和偏差。参见这里的示例(检查config_defaults
变量)。
保持理智的版本控制
想象一个场景,您修改了当前的数据输入管道,并且在这样做的时候,您意识到您在模型中引入了一个 bug。你想恢复到以前的版本,但你已经没有了。你可能会发现自己处于许多不同风格的类似的、潜在的灾难性情况中。
答案很简单——“对所有包含代码的东西使用版本控制系统!”
当你用 W&B 同步你的 ML 实验时,它获取最新 git 提交的 SHA,并给你一个来自 GitHub repo 的代码版本的链接。这里的见示例。
在机器学习中,模型和数据版本同样重要。数据版本化比模型版本化要复杂得多。查看此处以更好地编辑您的数据。
要进行模型版本控制,我们可以遵循一些简单的步骤:
- 经常检查模型,以便在需要时完全控制它们的状态
- 模型架构可以因为许多原因而改变。对于几乎所有的
tf.keras
型号,W & B 记录它们的架构,如下所示(可通过运行页面的型号选项卡获得):
人们可以在 Netron live 上预览他们的网络架构
确保正确性的测试
调试机器学习系统非常困难,这里是的原因。那么,您如何确保您的模型没有错误呢?正如乔尔·格鲁什和杰瑞米·霍华德认为的那样——确保这一点的最好方法是从一开始就不犯任何错误。这就是编写好的测试可以真正帮助您确信您的模型正在以您期望的方式工作的地方。
乔尔,在上面提到的演讲中,为一个 ML 模型整理了一套通用的测试场景-
尽管测试用例会因场景而异,但上面的这些无疑给了您一个很好的起点。因此,长话短说,单元测试有助于确保模型的正确性,从而使它们更具可重复性。
模型检查点及其他
想象一下,在训练你的神经网络期间,对于一个特定的时期,网络表现出良好的泛化行为,而就在那个时期之后,它又开始发散。如果您可以设置检查点,在每个时期后保存网络快照,或者在一系列时期内保存网络的最佳快照,岂不是更好?
如果最好的模型中途崩溃或者你失去了重量,那就更糟了。好消息是 Weights and Biases 可以自动为你做到这一点——也就是说,它会自动将你的网络的最佳版本保存到该模型的 runs 页面。
目前对于tf.keras
模型,W & B 可以以.h5
格式序列化同步最好的模型。对于定制模型(不支持序列化为 [.h5](https://www.tensorflow.org/guide/keras/save_and_serialize#part_ii_saving_and_loading_of_subclassed_models)
格式),您需要手动完成。你可以在本教程中看到。下面我将使用 W & B -设置模型检查点并保存
模型完成训练后,检查点文件将自动上传到相应的 W&B 运行页面。
这使得跨分布式团队的合作变得更加容易,因为您团队中的任何人都可以复制您的模型——他们可以访问权重和代码(因为 W&B 将您的 GitHub 提交与您的训练运行相链接)。
这里的每次运行(图例)指的是单独的实验,权重和偏差向您显示了与每次运行相关的性能指标
结论
本报告旨在提供一些简单但有用的方法,帮助您构建可重复的模型。这绝不是一份详尽的清单。我调查了一些机器学习专家关于他们对再现性的想法,以下是他们的回答:
- 尽可能分享公开数据集的结果。当这不可行时,包括一个公共可用的数据集,你的实验结果可以扩展到这个数据集。
- 在可能的情况下,分享在合理预算范围内可获得的计算水平上培训的结果。对于大多数人来说,使用 100 个 TPU v3–2028s 演示的结果不容易重现。
感谢 Mat 、 Aakash 和 Souradip 的贡献。作为 ML 从业者,除了 SOTA 结果之外,最大的再现性应该是我们的目标。
我很想知道你使用什么再现工具/方法。如果你对这份报告有任何反馈,请不要犹豫,发微博给我,地址是 @RisingSayak 。
为回归任务重新利用传统的重采样技术
阿列克谢·耶什金在 Unsplash 上的照片
想象一下这样一个场景,你参加了一个涉及回归任务的数据科学竞赛,你发现目标变量是偏斜的。由于没有一个参与者能够在排行榜上获得较低的误差,您意识到训练数据是不平衡的,一些快速重新采样可以解决您的问题。但是等等!这不是一项分类任务,您无法从一套欠采样和过采样技术中进行选择。这是一项回归任务,尽管有一些重采样算法,但您的选择是有限的。如果我们可以简单地将所有基于分类任务的重采样方法重新用于回归任务,这不是很好吗?如果你的答案是肯定的,也应该是,那么你来对地方了!
短信
如果你只是想平衡你的回归数据,然后继续前进,那么我们已经建立了一个 python 包,目前正在运行。对于那些想了解这一想法背后的工作原理以及通过这种方法可以实现什么的人,请继续阅读。
这个想法
偏斜目标变量的 Seaborn 图
上图是来自 AnalyticVidhya 的 Big Mart 销售预测挑战的目标变量的直方图。其偏斜值为 1.1773,而真正的正态分布的偏斜值为 0。由于数据集的性质,目标变量不能小于零,这会导致正的偏斜值。
从图中可以清楚地看到,与其他箱相比,某些箱具有大量的样本。为了使用传统方法对数据进行重采样,我们需要类的存在。对于回归任务,可以通过宁滨数据来实现。例如,在这种情况下,我们可以说 0–3000 范围内的所有样本都属于第 0 类,3000–6000 属于第 1 类,依此类推。这将最终为我们提供伪的、不平衡的类,然后我们可以使用它们来执行欠采样和/或过采样。我们可以使用 pandas cut 函数得到这些伪类。
这将每个样本放在一个类中
一旦样本被分配到它们各自的类,我们可以将整个数据集,包括连续的目标变量,连同生成的基于类的变量一起,传递给重采样包,例如 imblearn 。
这会导致目标变量中出现新值的过采样示例。
使用自定义采样策略应用 SMOTE 后相同目标变量的 Seaborn 图。偏斜值现在已经减少到 0.22
一份申请
让我们看看这种再利用方法在现实世界中的表现。我们将使用如上所述的相同比赛的数据。AnalyticsVidhya 还为每个相应的提交提供了真实世界的排名,这有助于了解我们在现已冻结的排行榜上的位置。
资料截图
数据中有许多分类变量。我们将首先对这些特性中的每一个执行标签编码,填充任何缺失的值,并使用 lightgbm 进行快速的基线提交。
数据预处理
火车。预测。提交一份文件
这使我们在排行榜上排名前 2500,得分为 1194(越少越好)。考虑到有 35000 名参与者,这还不算太坏!现在,我们通过使用我们的 reg_resampler 包 ,在数据集的过采样版本上重新训练我们的 lgbm 模型。我们使用来自 imblearn 的 SMOTE 作为我们的过采样器。
附注:我们还使用 KFold CV 进行了细微的参数调整,这里没有显示。如果你想了解如何使用我们的包以正确的方式执行交叉验证,那么我们在 GitHub 上为你准备了几个教程。
重新训练。预测。提交一份文件
这使我们在排行榜上排名前 30(第 26 位),得分为 1140!这是一个巨大的飞跃!!请注意,我们没有进行任何预处理,甚至没有为此进行任何特征工程。
还可以使用宁滨方法,通过将生成的箱用作回归任务的类,来执行分层 kfold 交叉验证。这让我比在 MachineHack 的二手电子产品价格预测挑战赛中简单的折叠更接近实际的排行榜,在那里我最终排名第一。
分析
我对性能提高背后原因的假设是,宁滨为我们提供了基于类别的数据视图,并通过生成具有不同预测值的新样本,帮助模型更好地对新样本进行概括。
最终消息
我希望你已经发现这是有用的。如果您有任何问题和/或批评,请随时联系我的 Linkedin 和 Gmail 账户。
reg_resampler 软件包是与才华横溢、能力出众的 Venkata Sai Krithik 一起开发的。你也可以在 Linkedin 和 Gmail 上找到他。如果你使用这个包,那么请启动 GitHub 库。
1:托戈、路易斯、丽塔·里贝罗、伯恩哈德·普法林格和保拉·布兰科。"为回归而击打。"在葡萄牙人工智能会议中,第 378–389 页。施普林格,柏林,海德堡,2013。
谢谢大家!
A/B 测试所需的样本量
本文描述了计算 A/B 测试所需最小样本量的一些流行方法。本文中描述的方法并没有什么新颖之处。然而,它将为初入该领域的数据科学家提供实用指南(严谨)。它还将帮助求职者在数据科学面试中脱颖而出。此外,这篇文章还揭示了一些流行的在线样本量计算器背后的数学原理。本文使用的公式来自生物统计学基础(第 8 版)。
为什么要计算所需的样本量?
在 A/B 测试中,我们通常感兴趣的是测试治疗组与对照组在某个成功指标(如转化率)上是否有显著差异。无效假设是没有显著差异。
当我们拒绝不应该拒绝的零假设时,第一类错误就发生了。一类错误率是一类错误发生的概率,也称为显著性水平或 alpha。α的常见值是 0.05。
当我们在应该拒绝零假设的时候没有拒绝零假设时,第二类错误就发生了。第二类错误率也称为β。
统计功效是测试在应该拒绝零假设时拒绝零假设的概率。基本上是 1 减去β。统计功效的常见值是 0.80(因此β是 0.20)。
为了获得有意义的结果,我们希望我们的测试有足够的统计能力。并且,样本大小影响统计功效。例如,在比较两个平均值时,可以使用下面的公式来计算统计功效。随着样本量的增加,统计功效增加。因此,为了使我们的测试具有理想的统计功效(通常为 0.80),我们需要估计所需的最小样本量。
(摘自《生物统计学基础》)
接下来,我们将通过一个假设的例子来理解所需样本量的计算。
例如:电子商务网站的转换率
假设一个电子商务网站想要测试实现一个新功能(例如,布局或按钮)是否会显著提高转换率(购买次数除以会话/访问次数)。我们可以随机向 50%的用户展示新网页。然后,我们有一个测试组和一个控制组。一旦我们有了足够的数据点,我们就可以测试治疗组的转化率是否明显高于对照组(单侧测试)。无效假设是两组的转换率没有显著差异。
比较两个平均值的样本量
进行测试的一种方法是计算治疗组和对照组的每日转化率。由于某一天一组中的转化率代表的是单个数据点,所以样本量实际上就是天数。因此,我们将测试测试期间每组每日平均转换率之间的差异。
估计最小样本量公式如下:
(摘自《生物统计学基础》)
对于我们的示例,让我们假设过去 6 个月的平均每日转化率为 0.15,样本标准差为 0.05。随着新功能的推出,我们预计转化率会有 3%的绝对增长。因此,治疗组的转化率为 0.18。我们还假设两组样本的标准差相同。我们的参数如下。
- mu1 = 0.15
- mu2 = 0.18
- σ1 =σ2 = 0.05
假设α= 0.05,β= 0.20(幂= 0.80),应用该公式,所需的最小样本量为 35 天。这与来自这个网络计算器的结果一致。
比较两个比例的样本量
双均值方法将每一天+组视为一个数据点。但是如果我们把重点放在个人用户和访问上呢?如果我们想知道测试需要多少次访问/会话呢?在这种情况下,一个组的转换率基本上是所有购买除以该组中的所有会话。如果每个会话是伯努利试验(转换或不转换),每个组遵循二项式分布。为了测试治疗组和对照组之间转化率的差异,我们需要两个比例的测试。估计所需最小样本量的公式如下。
(摘自《生物统计学基础》)
假设五五分成,我们有以下参数:
- p1 = 0.15
- p2 = 0.18
- k = 1
使用α= 0.05 和β= 0.20,应用该公式,所需的样本量为每组 1,892 个会话。这与来自这个网络计算器的结果一致。这也接近使用优化的样本量计算器计算转化率的结果。
推理分析的重采样方法
当你有一个样本,但你想了解人口
大多数时候,我们被要求得出对整个群体都有效的结论。但通常我们拥有的是来自样本的数据集,样本是我们收集数据的特定群体。
在理想世界中,样本是随机选取的和代表人群的子集。使用示例实际上有很多好处,比如实用性、成本效益、节省时间和可管理性。
尽管有这些优势,我们需要小心的是 采样误差 **!**🚨
抽样误差是总体参数和根据样本计算的统计值之间的差异(如总体平均值和样本平均值之间的差异)。因为样本是总体的子集,所以它们不包括总体的所有成员。因此,从样本计算的统计数据(如平均值、中值、标准差、分位数等)通常不同于真实的总体参数。
考虑到样本被确定为代表整个总体,样本和总体统计之间的差异被认为是误差。
为了克服采样误差,我们可以遵循以下重采样方法。
- 拔靴带
- 刀切重采样
- 排列测试
在阅读本文的同时,我鼓励您查看我的 GitHub 上的 Jupyter 笔记本以获得完整的分析和代码。
1.拔靴带
自举是一种从原始样本创建样本并替换的方法。由于使用替换 完成了 操作,每个数据点随后被选取的概率相等。我们可以引导 n 次(比如 1000 次),计算并记录这 n 个样本中每一个的期望估计值(即平均值)。最后,我们可以找到期望估计值的分布。
作者图片
📢bootstrapping 的一般使用案例是寻找置信区间的稳健估计、总体参数的标准误差,如平均值、中值、相关系数、回归系数等。
为了说明 Python 中的自举,我将使用来自 Kaggle 的鱼市场数据集。该数据集由鱼市场销售的 7 种常见的不同鱼类组成,我将重点关注“蟑螂”鱼。我还将选择“长度 1”作为属性。
data = pd.read_csv('./Fish.csv')
data = data.loc[data["Species"] == "Roach"]["Length1"]pd.DataFrame({'values': data.describe()}).reset_index()
如上所述,我们可以用np.percentile(data, [2.5,97.5]).
的 95%置信区间data.mean(),
计算样本均值
然而,通过从样本分布到总体分布,我们做了几个隐藏的假设,例如:“长度 1”值的分布是正态分布,置信区间是对称的。在大多数情况下,这些假设可能不正确。
mean = data.mean()
confidence_int = np.percentile(data, [2.5, 97.5])
样本均值= 20.65,95%置信区间= [14.61,27.36]
具有 95%置信区间的长度 1 值的分布
因此,我们应该使用 bootstrap 来寻找均值和置信区间。👇
mean_lengths, n = [], 1000for i in range(n):
sample = np.random.choice(data["Length1"],
replace=True,
size=len(data))
sample_mean = sample.mean()
mean_lengths.append(sample_mean)
boot_mean = np.mean(mean_lengths)
boot_ci = np.percentile(mean_lengths, [2.5, 97.5])
自助平均值= 20.60,95%置信区间=[19.22±22.07]
具有 95%置信区间的自举样本均值的分布
2.刀切重采样
刀切重采样技术基于通过系统地 在原始数据集中留下一个观察值 来创建样本。我们应该计算每个样本的期望值,然后找出所有值的分布。
作为一个例子,如果给定一个大小为 n 的样本,那么重叠估计是通过合计每个 (n-1) 样本的估计统计量得到的。
作者图片
📢刀切重采样的一般用例是寻找方差和偏差。
mean_lengths, n = [], len(data)
index = np.arange(n)for i in range(n):
jk_sample = data[index != i]
mean_lengths.append(jk_sample.mean())mean_lengths_jk = np.mean(np.array(mean_lengths))
jk_variance = (n-1)*np.var(mean_lengths)
平均值的重叠估计= 20.64
方差的重叠估计= 0.59
3.排列测试
排列检验是一种统计显著性检验,它试图在不对数据做出强假设的情况下获得检验统计量的分布(在零假设下)。
假设我们有两个样本,我们想测试这两个样本是否有不同的特征(即平均值)。我们可以计算两个样本的平均值,并决定它们是否不同。但是用这种方法分析没有统计学意义,因为我们没有整个人口的数据,只有其中的一部分。
相反,我们可以执行置换测试,其工作方式如下:
- 将两个样本合并成一个数据集。
- 混洗合并的数据集,并将其随机重新采样为 2 个数据集(大小与之前的样本相同)。
- 计算测试统计数据(即平均值之间的差异)并记录数值。
- 重复上述步骤 n 次(比如说 10000 次)。
- 将原始检验统计量与记录值进行比较,如果原始检验统计量与置换记录吻合得很好,那么检验统计量确实没有不同,样本均值之间的差异仅是由于偶然因素造成的**。如果原始统计位于最大置换记录之外,则意味着两个样本之间存在显著差异。**
为了说明 Python 中的置换测试,我将再次使用 Kaggle 的鱼市场数据集。这一次,我将通过选择“长度 1”&“长度 2”属性来关注“蟑螂”鱼。
💬我将调查这两个值的平均值是否有显著差异,或者是由于偶然因素。
数据集中的前 5 行
data["Length1"].mean()
data["Length2"].mean()
长度平均值 1: 20.65
长度平均值 2: 22.27
我们正在研究两个样本均值(-1.62)之间的差异是偶然的还是统计上显著的。
--> Step 1: Combine datasets
sample1 = data["Length1"]
sample2 = data["Length2"]
data = np.concatenate([sample1, sample2])--> Step 2: Shuffle and randomly resample into 2 datasets
perm = np.array([np.random.permutation(len(sample1) + len(sample2)) for i in range(10000)])
permuted_1_db = data[perm[:, :len(sample1)]]
permuted_2_db = data[perm[:, len(sample1):]]--> Step 3: Calculate the test statistics
samples = np.mean(permuted_1_db, axis=1) - np.mean(permuted_2_db, axis=1)--> Step 4: Repeat it n times
Done in step 2 with for loop--> Step 5: Compare the original test stat with the recorded values
test_stat = np.mean(sample1) - np.mean(sample2)
p_val = 2*np.sum(samples >= np.abs(test_stat))/10000
print("p-value = {}".format(p_val))
test_statistic = -1.62
p 值= 0.15
p 值告诉我们,在 15%的情况下,我们应该期望在两个样本之间达到相似的平均差异。
如果你想了解更多关于排列检验和假设检验的知识,你也可以阅读我的文章a/b 检验指南(附 below)⚡
用 Python 实现
towardsdatascience.com](/a-guide-to-a-b-testing-how-to-formulate-design-and-interpret-f820cc62e21a)
奖金
如果您正在执行相关性分析以了解数据集中变量之间的关系有多强,那么分析中包括的一个好东西是相关系数的自举置信区间。
为了用 Python 展示,我将再次使用鱼市场数据集,通过选择“length 1”&“Weight”属性来关注“Roach”鱼。
💬我将研究这两种属性之间的关系。
数据中有代表性的两行
在用data.corr()
引导之前,我们可以计算属性之间的相关系数。
看起来在我们的样本中,“长度 1”和“重量”之间有 90%的正相关。但是正如我们之前讨论的,这 90%代表了当前的样本,而不是整个人口。因此,我们可以计算 1000 次 bootstrapped 样本的 95%置信区间。
data_size, lw_corr = data.shape[0], []for i in range(1000):
tmp_df = data.sample(n=data_size, replace=True)
lw_corr.append(tmp_df["Weight"].corr(tmp_df["Length1"]))corr_ci = np.percentile(lw_corr, [2.5, 97.5])
相关系数置信区间:[0.77,0.98]
这意味着在 95%的自举样本中,“长度 1”和“重量”之间的相关系数保持在 0.77 和 0.98 之间。
总结
在本文中,我们介绍了三种重采样方法来消除分析中的采样偏差问题。通过这样做,我们不仅可以提取关于总体参数的更精确的估计,而且可以量化我们估计中的不确定性,例如增加置信区间。利用我们今天拥有的计算能力,我们可以在几行代码中对初始样本进行多次重采样。
我希望你喜欢阅读这篇文章,并发现它对你的分析有用!
如果你喜欢这篇文章,你可以 在这里阅读我的其他文章和 关注我上媒如果有任何问题或建议,请告诉我。✨
喜欢这篇文章吗? 成为会员求更!
研究领域 11:缺失的数据科学学科
上个月末,麻省理工学院出版社发表了一篇文章,向学术数据科学社区提出了 10 个研究课题。作为一名与许多数据科学家密切合作的数据工程师,我从未想过我自己也可能是一名数据科学家。我当然不认为自己是一个学者,但是本文中提出的大部分研究领域比我的数据科学同事更接近我作为数据工程师的工作。这篇文章启发我重新考虑我自己的工作如何与学术学科相适应。一路走来,我意识到数据工程自动化中的巨大漏洞,以及最终这篇文章,是我想了很多(可能太多)的东西。
随着数据爱好者将数据引入公司的生态系统,您的数据工程师的效率和支持他们工作的技术会对您公司的其他数据专业人员产生下游影响。作为数据工程师目前面临的最大挑战,研究领域 11 最终是当今以数据为中心的公司面临的最大障碍。
研究领域 11:数据映射自动化
有什么问题?
数据科学家经常开玩笑说,他们 90%的工作涉及准备数据以供分析。他们开玩笑,但这是真的。数据集的准备非常耗时,充满了错误,并且是费力的手动操作。这就是为什么大公司雇佣数据工程师,专注于将原始数据流转化为分析友好的数据库。将这项工作从获得博士学位的数据科学家身上卸下,使他们能够专注于他们花了数年时间完善的分析技术。这一转变是整个行业令人难以置信的进步。
数据工程师是数据科学家转变为软件工程师,或者软件工程师转变为数据科学家,他们的大脑预先忙于处理最杂乱的数据,并将其转换为逻辑和内容相关的数据结构。数据工程师不断应对极其复杂的挑战。虽然有一些数据集成工具可以帮助存储和查询非常大的数据,还有一些工具有助于向分析师公开数据,但数据工程师的大部分工作负载都不受任何现有工具的支持。不幸的是,他们的大部分工作都是手工的。
为什么会这样?
如果我们可以获取原始数据,并将其输入到一个可以理解其内容并将其重塑为您的数据模型的工具中,这难道不可思议吗?所有的数据都需要整合和规范化,而且没有任何技术可以自动完成这一关键步骤。构建这种自动化技术的障碍是缺乏对这种工具所需的复杂数据科学技术的关注和认可。
这个学科的重点是什么?
整合和规范化需要对数据的含义有一个人类层面的理解,即语义。
假设我们有两个数据集,它们具有以下编码方案:
例 1
婚姻状况:已婚、单身、离婚、与重要的其他人同居
has_partner: TRUE,FALSE
这些数据没有完全重叠,前者提供了更细粒度的数据。如果我们要规范化这两列,我们将把列 1 转换成列 2;值 1 和 4 表示真,而其他值将被编码为假。这个挑战花了我几秒钟就解决了,但是更复杂的情况呢?
例 2
故障 _ 睡眠:真,假
睡眠质量:非常差,有点差,有点好,非常好
我们不仅需要定义希望合并的列之间的映射,还需要确保我们只在包含相同信息的列之间创建映射。在匆忙中,您可能会试图通过将包含单词“bad”的值转换为 TRUE,将包含单词“good”的值转换为 FALSE 来转换后者。我自己最近也差点这样做,但最终还是决定咨询一位同事,他让我相信这两个属性虽然相关,但实际上是两个不同的概念。比方说,一个人在睡眠方面很专业,但是在早上感觉很糟糕。他们睡眠质量很差,但绝对没有睡眠问题。
不用说,跨数据库映射概念是极其微妙的。如果您的数据科学小组着手处理非常简单的数据集或很少获得新的数据流,这种手动工作在小范围内是可以管理的,但这项任务在不断扩大的数据公司中会迅速放大。
这样的自动化会做什么?
为了实现这种类型的自动化,新数据集需要经历一个逐步的过程。
模式合成
所有数据都有预先确定的结构。模式对数据的表名(如果适用)、属性名、属性类型、数据类型、引用规则(如果适用)以及是否需要空值进行分类。当这些信息可用时,它提供了一个很好的起点。通常情况下,该模式不可用或已过期。
如果缺少这些信息还不够的话,标准模式缺少很多最相关的信息。例如,文本字段是用最少的规则手写的自由形式的文本,还是种族或性别等分类属性?它是否是有序字段,如五分制?只有 1 和 0 的数字列是布尔值吗?
麻省理工学院的学生旨在创造一种检测关系模式的方法,你可以在这里找到他们的期末论文。
语义数据类型化
模式包含丰富的信息,但很少揭示数据所表达的含义。您可能会从“婚姻状况”和“睡眠问题”等信息性短语中得到一些提示,但是如果表名和列名像“msta”和“tsbool”这样毫无意义,该怎么办呢?如果遇到过大的规范化字典引用表怎么办?突然间,您的属性现在包含不止一个概念。
语义数据类型采用一系列类别标签和一系列示例值,在夏洛克的情况下,应用神经网络将新数据归类到这些预定义的类别中。在医疗保健等行业,数据旨在遵循一套标准的代码,像夏洛克这样的机器学习方法有着巨大的前景。
映射语义紧密度
回想一下我上面的例子,计算机是如何计算出已婚或与一个重要的人同居意味着某人有伴侣的呢?当两个数据库以相同的方式存储数据时,映射很容易,但是当它们以不同的方式存储时,我们如何自动检测相似的信息呢?更重要的是,我们如何对这些映射进行评分,以确保关于同一主题的不同信息不会被错误地合并?像 GloVe 嵌入这样的技术旨在用数学方法表示单词的概念接近度。像阿莱格拉和沙丁胺醇这样的词,它们都是用于不同情况的药物。
数据映射自动化是任何早期数据生命周期自动化的关键步骤;这是一个真实且始终存在的限制因素,影响着公司将输入数据纳入其分析资产的速度。目前没有多少数据集成工具可以帮助您的公司克服这一障碍。自动数据映射是自然语言处理技术的一个特殊应用,需要独特的考虑。因此,我认为这是它自己的数据科学研究领域。
研究数据策略
框架和激励因素
科学已经进入了大数据时代。几乎任何研究领域都受益于大量实验数据的可用性。典型的例子包括但不限于生物信息学、天文学、粒子物理学和地质学。然而,数据领域的许多创新都发生在技术领域。谷歌和亚马逊等公司在机器学习和云计算等领域进行了大量投资。新的工作方式也有进步,比如精益和敏捷开发。即使在科技公司以外的行业领域,数据密集型技术的采用率也仍然很低。对于像这样的大规模组织,已经开发了“数据策略的概念。研究机构可以从中受益匪浅,本文旨在介绍其科学变种:“研究数据策略”(RDS)。
TL;DR:跳到图 2 的数据策略框架。
数据战略与数据管理
需要注意的第一个重要点是数据策略和数据管理之间的区别。管理研究数据并不是一个新问题,它已经存在了几十年。研究数据管理领域一直在解决这个问题;因此,澄清差异非常重要,如下图 1 所示:
图 1:数据策略和数据管理的区别(图片由作者提供)。
理解区别的诀窍就在于名称:数据管理更多的是关于“管理”组织的数据,而“策略”就是“策略”。创新就发生在这个层面。
我们可以将 RDS 定义为**,一个通过应用数据和分析来交付研究价值的框架**。
元素
在大型管理咨询公司(如麦肯锡(McKinsey)和波士顿咨询公司(BCG ))的领导下,已经做出了大量努力,以创建一个统一的结构来实现数据战略,但没有达成普遍共识。我提议的元素如下图 2 所示。
图 2:数据策略的元素(图片由作者提供)。
这在很大程度上取决于研究用例、资源限制和现有的计划。我们来看看主要的。
准备
成功的 RDS 对其成功有一些严格的要求:
- 与整体研究战略保持一致
- 利益相关者买入
- 专门的战略所有权
这些都是说起来容易做起来难,但是有了它们,下游的一切都会变得容易得多。总结道格·兰尼的《信息经济学》一书背后的主要思想:
将您的数据视为真正的组织资产,而不仅仅是 IT 流程的副产品。
当前状态分析
要找到去哪里,我们需要知道我们在哪里。对于一个研究机构来说,这是通过对关键人物进行采访并记录调查结果来完成的。以下是一些常见的激励性问题(分为两类):
数字成熟度评估
- 当前有哪些与数据收集、存储和使用相关的计划?
- 谁是数据的生产者、所有者和消费者?
- 处理数据的人的技能水平如何?
数据尽职调查
- 当前的数据生成流程是什么?
- 数据质量如何?
- 在数据架构方面有好的实践吗?
进行这样的面试并不容易——它需要领域知识、沟通技巧和技术专长。
差距分析
有了 CSA 的结果,RDS 的下一个顺序要素是差距分析。在这里,战略设计者需要与组织中的关键决策者一起决定目标水平。这在很大程度上取决于组织的研究领域的状态和其他限制。差距分析结果是数据策略路线图部分的重要组成部分,也许是其最重要的交付成果。
数据管理和治理
在理想情况下,研究机构中的数据以类似于图 3 的方式进行管理:
图三。研究机构中的集中式数据管理(图片由作者提供)。
通常情况下,它会更加分散,形成孤岛。无论这是以隐藏在个人贡献者机器上的数据集的形式,还是关于数据安全性的混乱,问题经常存在。这部分数据策略在学术界研究得比较充分,我们就不多赘述了。
解决方案架构和技术
这个元素通常与数据管理捆绑在一起。尽管如此,由于它对下游高级分析用例至关重要,因此值得在 RDS 中单独关注。为了理解现代数据基础设施的复杂性,请看图 4:
图 4:示例数据架构(在马特·博恩施泰因、马丁·卡萨多和李昕晢、 URL 之后修改,图片由作者提供)。
它有许多不同的方面,即使一个研究组织是从零开始,技术选择和需求收集也是非常困难的。RDS 通过仔细检查有什么(CSA 的一部分)和记录潜在的使用案例(下面讨论)来帮助指导这个过程。
运营模式
RDS 中更难做到的一部分是对组织的现有运营模式进行必要的更改。典型的步骤包括改变团队运作(图 5),雇佣(或提升)首席数据官,以及通过数据研讨会提升技能。
图 5:不同的可能研究数据团队模型(图片由作者提供)。
用例识别
这是识别具体用例的步骤。它建立在其他元素之上,使其可用。在这里,研究领域的专家与数据策略设计人员密切合作,以确定要进行哪些项目,并为他们准备需求(在数据管理、架构和团队资源方面)。这可以通过从设计思维中借用方法的互动工作坊来完成。
然后可以对这种会议的结果进行优先排序,例如,使用 2x2 影响-努力矩阵。
规划和路线图
RDS 的最终交付成果是计划和路线图。毫无疑问,设计一个数据策略是很难的(这通常是一个耗时耗力的过程,持续数月),但这是工作的起点。RDS 可以以不同的形式交付,最常见的是业务变体;它包含在幻灯片和相关文档中。这些需要包含所有先前元素的结果,以及优先的后续步骤,以及时间计划和资源分配(在人员和预算方面)。有几种方法可以实现这一点,比如责任分配矩阵(【RACI】)。
结论
这篇博文只触及了如何设计研究数据策略的表面。这是一个正在积极开发的主题,并且随着时间的推移必将得到改进。重要的部分是要认识到,有一些策略胜过一点都没有,这是现代研究需要的高级分析用例的必备要求。
【https://osf.io/e6ycp/】注:这篇帖子后面的纸是 OSF 上的预印本。
资源
- dalle mule l .和 T. H. Davenport。2017.“您的数据策略是什么?”哈佛商业评论 95(3):112–121。
- 兰妮,D. B. 2017。信息经济学:如何将信息货币化、管理和衡量为竞争优势的资产。劳特利奇。
- 休伊特,E. 技术战略模式(奥莱利媒体)
- RDS 示例: NIH 数据策略, NASA 数据策略
研究设计+统计测试
调整研究设计和统计分析
从我坐在本科“研究方法”课上盯着 SPSS 输出的第一天起,我就知道我找到了自己的使命。我仍然记得我的第一篇研究论文。看着我的完成的调查进来,勤奋地清理数据,祈祷有重大的结果。尽管我的成绩并不显著,但我知道我找到了激情。
尽管我全神贯注于这个话题,但我发现将研究设计与统计分析结合起来特别困难。随着术语的出现(即 t 检验、方差分析、效应大小、IV、方差分析、协方差分析、回归、R 等。)我变得更加困惑和沮丧。设计实验、分析和解释结果时使用的大量术语可能是一个令人生畏的现实。
尽管要完全描述每个研究设计的深度本质以及适当的统计模型,我们需要一本冗长的教科书,但我希望提供一个简明的摘要。下面是研究设计原则和用于分析数据的适当统计模型的高度概括。
变量
一个实验要被认为是真正的实验,需要一些操作。换句话说,我们需要强加给我们的研究参与者,并衡量这种强加的效果。这就是自变量和因变量发挥作用的地方。
- 自变量(IV): 被研究者主动操纵的变量。根据研究设计,我们可以有多个静脉注射,每个静脉注射可以有多个“水平”,参与者必须接受这些水平。比如,教学风格的类型是否影响学生的考试成绩?这项研究的唯一 IV 将是教学风格,它将有 3 个独特的水平(即。专制的、权威的、放任的)。
- 因变量(DV): 假设受 IV 影响的变量。这也是研究测量的变量,以确定静脉注射有什么影响,如果有的话。在我们的例子中,学生的考试成绩将是唯一的 DV。
测量标度
任何研究的基础都是数据的收集和分析。根据研究设计、假设和数据收集方法,我们可以有四种类型的定量数据。每一种衡量尺度都有不同的属性,这些属性决定了特定统计分析的使用。
分类变量
- **名义的/分类的:**简单标记或分类的数据,没有顺序或可测量的意义。可以采用字符串和/或数字格式。(即。地点:芝加哥、旧金山、亚特兰大或性别:1,0)。
- 有序:有标签的测量数据,可以按顺序排列,但我们不能用数字区分每次测量之间的间隔。可以排序和分级的分类数据(即你的最高学历是什么?(A)低于 HS,(B) HS,(C)某些学院,(D)学士学位,(E)研究生学位)
连续变量或数值变量
- 区间:经过标记和排序的数字数据,其中类别之间的距离可以比较,但零的概念不存在,每个值之间的距离相等(即。李克特等级量表:非常同意=5,同意=4,中立=3,不同意=2,非常不同意=1)
- Ratio :标记和排序的连续数据其中类别之间的距离可以比较,零的概念存在,可以包含负值(即。你多大了?10、22、23、50 等。)
组间与组内
- 组间设计将研究参与者分成不同的组或条件(即对照或一个治疗组)。在整个实验中,参与者只能属于一个组。每个参与者只接受静脉注射的一个级别。
- 组内设计将相同的研究参与者放入 IV 的所有水平。通常被称为“重复措施”设计。
参数与非参数
为实验选择合适的统计检验的主要参数是数据分布的形状。正态或高斯分布遵循一个钟形曲线,如下图所示。
钟形曲线
- 参数测试假设数据呈正态分布,并包含区间或比率数据。
- 非参数检验对数据的分布不做任何假设,并且包含序数或名义数据。
- 直方图和 QQ 图是可视化数据分布以确定正态性的好方法
参数测试
- **皮尔逊 r 相关:**衡量两个变量之间的线性关系。静脉注射和静脉注射都必须成比例(即连续)。
- **回归:**回归有两个主要目的。首先,它用于评估 DV 和一个或多个 iv 之间的关系强度。它可以通过帮助我们确定每个 IVs 对 DV 的影响程度来推断因果关系。预测值是它的第二个目的。根据 IVs 和 DVs 的类型以及数据的参数质量,有多种回归类型。线性回归用于预测连续变量(即工作表现)只有一个 IV。逻辑回归用于预测二元结果(即是/否)与多个静脉注射。多元回归用于预测连续的结果(即工作表现)与多个 iv(即智商测试成绩,性格测试成绩等。).
- **单样本 t 检验:**将样本的平均值与已知或假设值(通常是已知总体平均值)进行比较,以确定它们是否有显著差异。
- 独立样本 t 检验: *组间设计。*比较两组独立研究参与者的平均 DV 分数,每组参与者仅暴露于静脉注射中的一个组/水平,而静脉注射仅具有 2 个组/水平。DV 是连续的。比如教学风格对学生考试成绩有什么影响。选择两组随机选择的学生。第一组由威权老师授课,第二组由权威老师授课。我们比较平均 DV(即测试分数)来确定它们是否显著不同。为了检验方差的均匀性,我们可以使用 Levene 检验。
- 配对 t 检验: *组内设计。*比较随机选择的受试者在静脉注射时暴露于两个组/水平的平均 DV 分数,静脉注射只有两个组/水平,且只有一个静脉注射。通常,使用前/后测试设计。有时也称为“从属样本 t 检验”。例如,在一个学期的课程中,相同的学生被两种类型的老师(权威型和独裁型)教过。将第一位教师所教材料的学生平均考试分数与第二位教师的平均考试分数进行比较。这种设计通常利用 DV 设计的治疗前/后测量。除了直方图和 QQ 图,夏皮罗维尔克检验也可用于确定正态性。
- 单因素方差分析 : *组间设计。*比较随机选择的参与者的平均 DV 分数,每个参与者仅签署了 IV 中的一个组/级别。IV 有 2 个以上的组/级别,而我们只有一个 DV。例如,选择三组随机选择的学生。第一组由权威型教师授课,第二组由权威型教师授课,第三组由宽容型教师授课。单因素方差分析比较了所有三种教学风格的学生分数。通常称为“组间方差分析”。DV 是一个区间或比率(即连续)。单因素方差分析是一种综合检验,因为 p < 0.05 拒绝零假设,以确定组间存在显著差异。然而,为了确定差异的具体位置及其大小,我们进行了专门的测试(即图基,邓尼特)
- 重复测量方差分析: *组内设计。*比较参与者的平均 DV 分数,这些参与者都暴露于多于 2 组/水平的一个 IV,而我们只有一个 IV。例如,不是两个老师,我们现在有三个老师教所有的学生。重复测量方差分析是一个综合检验,因为 p < 0.05 拒绝零假设,以确定至少两组之间存在显著差异。Bonferroni 特别测试将确定差异所在。DV 是区间或比值(即连续)并测量 n 次,其中 n = IV 级条件的数量。
- 双因素方差分析: *组间设计。*比较随机选择的参与者的平均 DV 评分,这些参与者仅接受了一组/一个级别的静脉注射,而我们接受了不止一次静脉注射。三向方差分析有三个 iv。双向方差分析试图确定一个以上静脉对静脉的影响。这也是一个很好的测试来确定两个 iv 的相互作用是否会影响 DV。双向 ANOVA 的结果将分别定义每个 IV 和 DV 之间的主要效应,然后是 DV 上的交互效应。例如,我们随机选择了几组学生。我们的第一个 IV 是教师类型(即。专制的,权威的,放任的)我们的第二个 IV 是学生是否在白天或晚上被教导。这是一个 3x2=6 析因设计,因为我们有三种教师类型和两种教学时间条件。每个学生只被安排到六个条件中的一个条件下,比较平均测试分数以确定六个组之间是否有显著差异。
- 单向方差分析: *组间设计。*比较随机选择的参与者的多个平均 DV 分数,这些参与者仅暴露于静脉注射的一个组/水平。我们有一个静脉注射,但我们有两个或更多的静脉注射。例如,教学风格(专制、权威、放任)对学生成绩和旷课有什么影响?每个学生被分配到四年级的三个小组/级别中的一个,并对他们的考试成绩和旷课情况进行测量。教学风格是我们有三个级别的一个 IV,但我们有两个 dv,学生的分数和旷课。
- 双向方差分析: 组间设计。比较随机选择的参与者的多个平均 DV 评分,这些参与者仅暴露于静脉注射的一个组/水平,我们有多个 DV。例如,教学风格(专制、权威、放任)和学习时间(白天或晚上)对学生成绩和旷课有什么影响?这是一个 3x2=6 的设计,因为我们在第一个 IV 上有三个组/级,在第二个 IV 上有两个组/级。在教学风格 IV 和学习时间 IV 之间,每个学生只接触六个组/级别中的一个,并测量他们的考试成绩和缺勤率。教学风格是 IV,学习时间是第二个 IV,我们有两个 dv,学生成绩和旷课。该试验还将确定所有 iv 和两个 dv 之间相互作用的影响。
- 单向重复测量方差分析: *组内设计。*比较暴露于超过 2 组/水平的 one IV 的参与者的多个平均 DV 评分,我们有多个 DV。每个学生都接触到教学风格 IV 中的所有三个组/级别,并测量他们的考试成绩和缺勤率。教学风格是 IV,我们有两个 dv,学生成绩和旷课。
- 双向重复测量方差分析: *组内设计。*每个学生都接触到所有 6 个组/级别(教学风格 IV 中的三个组/级别和研究时间 IV 中的两个组/级别),并测量他们的考试成绩和缺勤率。教学风格是第一个 IV,学习时间是我们的第二个 IV,我们有两个 dv,学生的分数和旷课。
- ANCOVA :用于控制一个或多个变量对 DV 的影响。比如在控制年龄的情况下,教学风格对学生考试成绩有什么影响?换句话说,我们知道考试分数受到几十个甚至几百个变量的影响,但我们无法测试所有的变量。因此,我们对一些特定变量如教学风格形成假设,但如果我们想消除年龄对考试成绩的任何影响,我们使用 ANCOVA。为了消除年龄的影响,我们需要记录每个研究参与者的年龄。
非参数检验
- **Spearman 秩相关:**两个变量之间单调关系的度量,可以是序数,也可以是比值。单调关系表示变量倾向于以相同或相反的方向移动,但不一定以相同的速率移动。
- 曼-惠特尼检验: 组间设计和非参数版本的独立样本 t 检验。DV 要么是区间,要么是比值(即连续)。
- Wilcoxon 符号秩检验 : 组内设计和非参数版本的相关样本 t 检验,有时称为“配对 t 检验”。DV 要么是区间,要么是比值(即连续)。
- Kruskal-Wallis 检验: 组间设计和非参数版本的单因素方差分析。DV 要么是序数要么是比率(即。连续)。Kruskal-Wallis 检验是一个综合检验,Mann-Whitney U 检验将有助于确定存在显著差异的地方。
- Friedman 检验: 组内设计和重复测量方差分析的非参数版本。为了确定差异存在于何处,我们必须对 IV 水平的所有独特组合进行 Wilcoxon 符号秩检验。
- 卡方检验: *组间设计。*使用两个分类变量之间的观察值的频率表来确定变量之间的关联。例如,我们希望确定数据科学家的性别与他们使用 python 还是 r 之间是否存在关联。使用 python 或 r 的男性和女性频率的交叉表)。如果“皮尔逊卡方”p 值小于 0.05,我们可以拒绝零假设,并得出结论:性别与使用 python 和 r 之间存在关联。用于评估分类变量之间的关联而非因果关系。
定量研究与定性研究
从最宏观的角度来看,我们有两个截然不同的研究类别;定量和定性。在这篇文章中,我们将把重点放在定量研究上,但是理解两者之间的区别是很重要的。
- 定量研究处理通过评估收集的数字数据,使用统计方法进行分析,以比较实验组和推论。 使用数字 确认/测试
- 定性研究遵循探索性方法,希望探索思想、理论和假设。其数据采用观察、一对一访谈、焦点小组、开放式调查项目、历史记录和案例研究(即主要是文字不是数字)。数据分析试图总结、分类和解释主题,而不是因果推理。 理解使用词语
定量研究设计
一般来说,有 4 种类型的定量研究设计:
- 描述的
- 比较
- 准实验性的
- 实验的
描述性研究设计
- 描述性的或探索性的(即。数据挖掘)在本质上,描述性设计旨在根据频率、趋势、类别/比较和人口统计学来描述一种现象。它希望对的内容、时间、地点和方式有所了解,但提供的因果关系证据非常薄弱。为什么)。
- 研究者可以控制研究参与者的取样策略
- 不包含变量操作(即。自变量和因变量)
方法
- 描述性研究依赖于向参与者询问与研究主题相关的问题。
- 调查或问卷(李克特、频率、配对比较、星级评定、行为锚定评定)
- 观察收集的数字数据(即。多久,多少,什么日期,年龄,性别,体重等。)
分析
- 描述性统计,如计数、百分比、平均值/众数/中位数、标准差
- 使用图表和可视化来传达见解
样本研究问题:
- 在过去 2 年中,员工参与度发生了怎样的变化?
- 主动离职的主要原因是什么?
- 员工更喜欢培训 X 而不是培训 Y 吗?
- 高绩效者和低绩效者之间的平均工资差异是什么?
- 哪些招聘来源带来了高质量的候选人和大多数雇员?
- 在我们的服务人员中,脱离有多普遍?
比较研究设计
- 有时被称为“相关性”研究。
- 旨在定义两个或多个结构之间的统计关系。(即。一个变量的变化与其他变量的变化有什么关系?)
- 变量之间的关系在本质上是历史性的,因为它们可能在未来发生变化。
- 很像描述性设计,它也提供了趋势和模式。
- 虽然在提供因果证据方面强于描述性设计,但总体而言仍然较弱。
- 绝对没有直接变量操作(即。因变量和自变量)。
方法:
- 调查和问卷(李克特、频率、配对比较、星级评定、行为锚定评定)
- 观察收集的数字数据(即。多久,多少,什么日期,年龄,性别,体重等。)
分析:
- 相关性计算变量之间的关系。
- 相关性:正,负,零,曲线,多重相关性,部分相关性
- 皮尔逊相关:在连续的线性相关结构中使用最广泛的相关。
- Spearman 等级和 Kendall Tau 等级相关性:类似于 Pearson 相关性,但对变量之间的非线性关系更稳健
样本研究问题:
- 工作绩效和认知能力有什么关系?
- 年轻员工辞职的可能性更大还是更小?
- 培训评估分数越高,工作表现越好吗?
准实验设计
- 通常被称为“自然实验”,因为它们是在自然环境中进行的。
- 它们通常涉及某种治疗(IV ),该治疗被假设为影响 DV。
- 自变量存在于研究设计中,但通常没有被研究者操纵。
- 研究者测量自变量对因变量的影响。
- 研究组和对照组的参与者都在场,但都是自然形成的,因此不存在随机分配。
- 研究组和对照组之间可能的差异引入了未知的混杂变量,这些变量可能会调节或调节结果。
方法:
- 非等效组设计:组间设计(即参与者仅被分配到一个研究组、实验或控制组),其中参与者不被随机分配到这些组。
- 前测-后测设计:在治疗前测量因变量以获得基线,然后在治疗后再次测量以确定自变量对因变量的影响。时间量(即混杂变量)对我们的独立变量影响因变量的置信度有很大的影响。历史:测试前/后之间发生的事件;成熟:研究对象的自然成长/学习)。
分析:
- 使用哪种统计检验取决于研究的设计(静脉注射次数、静脉注射水平、静脉注射次数、组间或组内等)。
- t 检验,方差分析,回归,相关性
样本研究问题:
- 患者保护与平价医疗法案的引入对员工缺勤有影响吗?
- 男性的离职率更高还是女性更高?
真实实验
- 有些人会说,我们永远无法真正确定因果关系,但真正的实验设计最接近于建立因果关系。
- 真实实验的主要区别在于将研究参与者随机分配到研究组。随机分配是建立平等参与者群体的最彻底的方式。这有助于我们对可能影响 DV 的可能混杂变量进行控制。
- 根据研究设计,一个真正的实验可以有多个 iv,所有 iv 都可以有多个水平。
- 根据研究设计,一个真实实验可以有多个 dv。
- 使用不接受实际治疗的参与者对照组。
- 根据学生的设计,会使用同盟者或假装成参与者的研究人员。
方法:
- 前测后测对照组设计:所有的研究参与者都被给予前测以建立 DV 的基线评分。实验将静脉注射/操纵强加给参与者。最后,进行后测试以确定静脉注射对静脉注射是否有任何影响。
- 仅后测对照组设计:类似于上述设计,但省略了前测。通过比较治疗组和对照组之间的 DV 评分来确定静脉注射对 DV 的影响程度。
- 所罗门四组设计:上述设计的组合。第一组参与者接受了前测/干预/后测。第二组进行前测和后测,但不进行干预。第三组接受干预和后测,但不接受前测。最后,第四组只接受后测。
分析:
- 使用哪种统计检验取决于研究的设计(静脉注射次数、静脉注射水平、静脉注射次数、组间或组内等)。
- t 检验、方差分析、回归、相关性等。
样本研究问题:
- 各种级别的加薪是如何影响员工满意度的?
- 药物 X 能降低抑郁程度吗?
摘要
我们当然可以将这篇文章无限延伸,因为统计学和研究设计的领域相当广泛。我真的希望这是对统计分析和研究设计的有益总结。
机器学习项目的研究指南
有一个简单的目标,但有多种方法来实现它的重要性。
机器学习项目可以分两个阶段交付。第一阶段被称为研究,是关于回答这样一个问题:我们能从这堆数据中制造出一个机器学习模型来满足客户的需求吗?可交付成果是一个概念验证或一个可行性研究。第二阶段被命名为开发,它是关于承诺交付一个机器学习产品。这个阶段的可交付成果是一个机器学习产品。
在研究阶段,当项目资源有限且时间紧迫时,我认为有两个主要方面是相关的:首先是定义问题范围的重要性,其次是使用短迭代测试模型的重要性。
范围
这个阶段最困难的任务之一是确定你努力的范围。例如,考虑使用文件;您可以选择使用实时数据(与实时数据库连接)或直接从文件中读取数据。使用数据库意味着你需要访问基础设施,处理认证,以及依赖于公司可以延迟项目开始的事情;另一方面,您可以请求转储数据,并在第二天开始工作。
关于范围界定练习的好(坏)的一面是它缩小了你所有可能的行动。在某种程度上,这很好,因为您去掉了交付概念证明不必要的所有东西:
- 关注单一问题。如果问题太大,把大问题分成许多小问题(各个击破)。例如,如果你的问题是全球性的,那么重新确定你的问题的范围,将其扩展到整个大陆,或者只关注一个国家。你也可以通过重新规划问题的时间跨度来降低复杂性(例如,关注特定的日期范围:去年、十年等等)。
- 范围不是一成不变的,你应该对它保持敏捷。当你深入业务领域并获得更多处理数据的经验时,有时你会转移你的范围。这是我在研究中使用看板而不是 Scrum 的原因之一,因为它更灵活。
- 直到你有了零模型(解释如下),你才知道你是否有足够的数据。但我要告诉你一个秘密:在机器学习中,你永远不会有太多的数据,但你可能会有有偏差或不具代表性的数据,这可能会给你的推论带来一些问题。如果你有太多的数据,你总是可以缩减采样你的数据集;但是如果你的样本太少,上采样(增强)技术可能会给你的数据集增加一些不必要的变化。总而言之,如果你有很多选择,那么选择最大的一个。
- 这个问题应该可以用一台计算机来解决。除非,如果你正在使用深度学习模型,那么你需要在计算机中添加一个或多个 GPU。您可以使用自己的机器,也可以使用客户端 VNET 中的虚拟机(当数据敏感时推荐使用)。如果您需要 spark 集群来转换您的数据,请再次考虑您的问题范围。
- 向客户传达验收标准。这一点是关于与客户协商什么将是项目的**可交付成果。**重点:这还不是一个 ML 产品,而是一个概念验证,例如,你真的需要一个蓝绿部署?也许您更愿意使用
flask
将模型部署为 REST API?或者只是将模型的预测保存在一个 excel 文件中,以便以后由业务专家审查,这样做是否有效? - 验收标准是您的积压工作(Jupyter 笔记本或 python 模块、docker 或本地部署、项目日志、模型工件、模型预测等)的驱动因素之一。最终,客户还应该解决指标和/或条件标准(如何评估您的解决方案的良好性)(在下一节中会有更多相关内容)。
- 这种关注应该提高简单性,因为它减少了时间和精力。研究阶段的目标应该是尽快找到 ML 产品可行性的答案。在决定范围和验收标准时,请记住这个问题。
- 概念验证不同于一次性原型。这个阶段投入的所有努力,都应该是未来产品的一部分。大多数情况下,数据科学家的经验不仅对重用学到的知识,而且对重用源代码和基础架构都有影响。机器学习工程师应该帮助解决这些问题(例如,实施最佳实践)。
- 如果还不够清楚的话,我在这一节重复了五次“专注”这个词(现在这是第六次)。现在有意义吗?
模型检验
免责声明:大多数人认为构建模型是 ML 项目中最复杂的部分。但事实并非如此。并不是因为很有可能你需要的 ML 算法已经在 sklearn、h2o 或者 pycaret 这样的库中实现了。我甚至不打算提及 autoML 技术或像 R 或 Julia 这样的语言中可用的 ML 库。
坚持基础;这些会解决你 90%的项目。一旦你理解了基础知识,你就可以大胆地使用更复杂的 ML/DL 算法。一旦你使用了算法,就更容易掌握它们的理论和基本原理,所以不要认为你需要完全理解它们才能使用它们。这是杰瑞米·霍华德在他们的课程中使用的学习技巧,我认为对于像我这样的非博士来说,这是一个极好的学习方法。
那么,如果建立模型不是最难的部分,那是什么呢?ML 模型的其余部分,如特征工程、服务模型等。
所有这些其他部分的大部分都超出了本文的范围(其中一些属于研究阶段之后的开发阶段)。
迭代方法
在你的模型的零迭代期间,我建议你尽快建立你的模型并收集它的预测。争取最快的胜利,例如:减少你的特征工程,只把非数值特征转换成数值特征,建立一个简单的模型。你想要得到的理想结果是,这个零模型预测优于随机选择或汇总度量(均值、中值等)数字,这是最基本的预测(不涉及机器学习,只是纯算术)。
PS:如果第一次尝试没有成功,不要沮丧。这只是漫长旅途的第一步。
模型检验
你在迭代 0 的前半部分获得的模型,我称之为零模型。在迭代 0 的另一半期间,您将通过更新训练数据集来构建更好的模型(例如,更积极地预处理数据或优化您的模型超参数等)。我把第二个模型叫做零模型*。*
在接下来的迭代中,您将构建替代模型,扮演空模型的对等物。这个过程类似于你做假设检验时,你弄清楚你是否在正确的轨道上相互比较模型。我的工作方式是,我尽量完成 至少两次迭代,测试两个不同的模型。但是俗话说“越多越好”,你只受你可支配时间的限制。
韵律学
根据您使用的 ML 模型,您将最终使用一个度量标准。例如,对于回归问题,可以使用 RMSE ,对于分类问题,可以使用精度。此外,度量用于跟踪 ML 模型的进展,因此您可以测量数据/模型超参数的变化如何影响模型的预测。你的实验应该总是由度量驱动的。选择正确的指标和选择模型本身一样重要,你应该知道“天下没有免费的午餐”。你需要试验并检查什么对你的问题更有效。
大多数时候,涉众对 RMSE(或任何其他 ML 度量)一无所知;但是你有责任向他展示所选的指标与业务目标一致。在这种情况下,您有两个选择:a)如前所述,解释 ML 指标的含义并证明其重要性,或者 b)开发一个平行的业务指标。业务指标是以业务领域单位表示的指标。例如,在网上服装店的推荐者的情况下,业务指标可以评估模型推荐与被推荐人性别相同的产品的情况。业务度量更容易被涉众理解,最终,它将成为你的模型的重要驱动力。
每次迭代/实验都需要被记录。您需要记录的最低限度是您的培训结果:结果指标。为此,Jupyter 笔记本可以作为一个简单的日志。从那里,您可以使用更优雅的解决方案,这将允许您不仅跟踪指标,而且跟踪用于训练或生成的模型的数据(以及用于获得它的超参数): mlFlow ,weights&bias,…
研究阶段有三个成果:
研究阶段成果
在有希望的结果,但不足以满足条件标准的情况下,最好的选择是扩展概念证明;为了改善您的模型结果,您可以尝试更改数据预处理和/或机器学习模型。最好的结果是,模型满足条件标准,从而进入开发阶段;在这种情况下,最好的做法是开发与概念验证相分离的实际产品,同时改进当前的概念验证。当当前模型不满足条件标准时(例如,缺少数据,或者缺少更好的机器学习算法来对问题建模),您可以暂停案例,直到案例的上下文发生变化。
如果你对这类问题感兴趣,我向你推荐这本书:管理机器学习项目,来自亚马逊的机器学习大学。
下一篇帖子将更具技术性,我将深入研究我在研究阶段使用的一些工具和技术。敬请关注。
发展背景下的研究:研究人员观察世界的视角
实证主义和建构主义。
图片由 Pixel2013 到 Pixabay
我从来没有真正理解过研究范式的概念,以及它对做研究有多重要(当我试图理解这一点时,我真的很紧张),直到我不得不为我的硕士后研究做一个与这个术语相关的作业。我希望这篇文章可以帮助你们中的一些人。
作为一套基本信念的研究范式
你是否曾为制定一份研究计划而苦苦挣扎?理解你自己的信念是发展研究方法的第一步。为什么?因为它将指导你的研究设计,决定你如何收集数据,并影响你解释研究结果的方式。
从这个意义上说,理解研究范式的概念是至关重要的,研究范式被定义为“一套基本信念[……]提出了一种世界观,并规定了[……]世界的性质”(Guba & Lincoln,1994,第 107 页)。用简单的语言来说,我们可以将**范式描述为一个概念透镜,通过它我们可以观察世界并指导我们如何解决问题。**范式基于三个哲学假设/组成部分,包括本体论、认识论和方法论。在本文中,我将着重解释两种主要研究范式的本体论和认识论假设,包括实证主义和建构主义。
得到💬任何数据科学或编程问题的 GPT 式答案。为成千上万的人生成摘要和学习笔记📚只需一次点击即可获得学习资源。👉
[## 面向数据科学家和开发人员的免费学习资源。精选的博客、教程、书籍和…
机器学习和人工智能工程师的培训课程、黑客马拉松、活动和工作
aigents.co](https://aigents.co/learn)
本体作为现实的本质
Guba 和 Lincoln (1994)认为,本体论哲学是指关于现实的信念,这涉及到关于现实本质的问题。
实证主义在本体论上被假定为“天真的现实主义”,这意味着存在一个独立于人类思维并受宇宙法则支配的现实,等待被发现 (Guba & Lincoln,1994)。换句话说,现实既不是我们头脑中的东西,也不受制于我们的经验。研究的作用是通过数据和科学来揭示这一真相。实证主义者声称,一件事可以是真实的,不管背景、文化和研究者的观点如何。另一方面,后实证主义理论确认了现实的存在和可观察性,但在给本体论贴标签方面迈出了一大步,这就是“批判实在论”(Sumner and Tribe,2004)。具体来说,后实证主义者认为存在一个现存的现实,然而作为人类,研究者的智力是有限的,这使得他无法完全和完美地理解现实。因此,观测结果可能会有误差,而事实是可以修改的。
从不同的角度看问题。来源
建构主义的本体论哲学与实证主义相去甚远。本体论被贴上了“相对主义”的标签,它假定不存在超越和独立于人类经验的单一现实。现实是由人类的主观思想和感知构建而成的。单独构建,可以有多种真理,而且同样有效。因此,研究者在研究过程中必须意识到不同的背景、文化和他们的个人价值观。前几天,我从我的一次演讲中听到了一句名言。它说“你是对的并不意味着我是错的。你只是没有从我的角度来看生活。”而且有时候对错的界限很细,没有上下文,很难说。
以贫困的概念为例。实证主义者声称贫困作为一个独立的现实存在,并被认为是基本需求的未能实现。与此同时,建构主义者认为客观贫困本身并不存在。人在一定背景下是贫穷的,只有通过背景和人之间的适当互动才能理解贫穷。实证主义和建构主义如何界定贫困的一个具体例子可以在这两项研究中找到:Dollar 和 Kraay (2002 年)进行的增长对穷人有好处(实证主义方法)和 Narayan (2002 年)实施的穷人之声(建构主义方法)。纳拉扬研究中使用的贫困定义是一个更广泛的贫困定义,包括非经济层面,包括安全、脆弱性和赋权。与此同时,Dollar 和 Kraay (2002)只研究了贫困的经济概念,或者说收入贫困。
人在一定背景下是贫穷的,只有通过背景和人之间的适当互动才能理解贫穷
作为知识本质的认识论
“认识论”这个术语听起来确实很奇特,但是用简单的语言来说,认识论解决了这个问题**“我们如何认识事物?”,“我们如何认识现实?”**
如萨姆纳和部落(2004)所述,认识论是哲学的一个分支,关注知识的性质和范围。实证主义通过假设检验,将知识验证为可以通过可靠的数据和工具进行实证检验的事实。Posivitism 研究者构建假设并收集数据,通过可靠的设计,验证假设和知识。因此,实证主义的认识论观点被称为“二元论/客观论”。它再次在于相信人类的思想和物质是分开存在的,无论研究人员是谁,研究结果都保持不变。
相比之下,建构主义认为知识是主观的,因为它是社会建构的,并且依赖于心智(Creswell,2003)。建构主义的认识论被贴上“主观主义”的标签,并强调研究者的感知是解释他或她的经验的有用工具,因此也解释了真理。在这种情况下,理论从研究者的经验中浮现,被称为演绎推理。
也就是说,在上面提到的贫困例子中,实证主义认为,所有研究人员需要做的就是收集数据,比如说收入,并从中得出关于贫困状况的结论。然而,建构主义认为,贫困与收入和一个人划定的界限无关。它与人们对生活的感受以及驱动他们体验的因素有关。为了理解这一点,在调查过程中,研究人员需要与人互动,将自己置于环境中,了解文化,以理解贫困在社会环境中的真正含义。
个人价值的位置在哪里?
关于价值在探究过程中的作用,实证主义提倡无价值研究,这是其“主观主义”认识论立场的结果。价值观被视为混淆变量,会影响研究结果的主观性,因此在研究过程中没有地位。
建构主义的假设;相比之下,要特别强调研究人员给调查过程带来的价值。建构主义者将价值观视为形成研究成果的核心角色,特别是在社会研究中,因为在建构主义社区中,人们相信不同的研究者对世界的看法和体验是不同的。
Eyben (2014,第 164 页)建议,研究者应该有反思性实践,这鼓励他或她“对照观察来测试不同的解释模型”。然而,人们应该非常小心,因为反身性在某种意义上是棘手的,个人价值观和地位会对人们感知和选择感知事物的方式产生巨大影响。当进行研究时,这可能会导致偏见,因为研究人员可能会选择性地看待这个问题。他或她可能不会客观地解释事情,而是以一种支持他或她自己先前信念的方式来解释。
汇总表——作者插图
我在哪个信仰体系中定位自己?
本体论和认识论立场的结合将使你对你如何看待现实和你理解知识的方式有一个整体的看法。一旦你确定了这一点,你将能够开发最适合你的信念的研究方法和设计,这将肯定有助于提高你的研究质量和一致性。
也就是说,我进行研究的方法符合后实证主义的假设。本体论的立场是迄今为止将我的研究方法与建构主义区分开来的最合乎逻辑的理由。本体论的概念在我心中提出了这个问题:作为研究者,我们是在创造现实还是在寻找现实?这是驱动我的研究方法的特殊点。在我看来,现实有待发现,研究人员的角色是通过基于良好数据和证据的科学获得真相。然而,在过去几年里,我也认识到,事情可能非常复杂,数据有时会掩盖复杂性。我仍在学习看到生活的灰色地带,而不是只看到事物的黑白。
感谢您的阅读!
参考文献
Eyben,R. (2014 年)。国际援助和创造一个更美好的世界。反身实践(第 154-172 页)。伦敦&纽约:劳特利奇。
古巴和林肯(1994)。定性研究中的竞争范式。在 N.K. Denzin & Y.S .,Lincoln(编),《定性研究圣人手册》(第 105-117 页),千橡市,加州:圣人。
坎布尔和谢弗(2007 年)。认识论、规范理论和贫困分析:实践中 Q 平方的含义,世界发展, 35 (2),183–196。
谢文思(2003 年)。《伦理问题》,载于:Scheyvens,R. & D. Nowak 《发展实地工作:实践指南》。伦敦:鼠尾草。
萨姆纳和部落,M. (2004 年)。发展研究中认识论和方法论的本质:我们所说的严谨是什么意思?,会议论文发表于:DSA 年度会议,连接研究与政策,伦敦。
c .瓦格纳、b .卡乌利希和 m .加纳(编辑。).(2012).做社会研究:全球背景。纽约:麦格劳-希尔高等教育。
Youtube 视频阿姆加德巴德维:https://www.youtube.com/watch?v=kf8wGvunyG8
用于灾难响应的机器学习研究:什么构成一篇好论文?
2021 年,一个主要的自然语言处理会议将首次有一个专门讨论灾难响应的轨道。也是第一个有这个赛道的机器学习或者语言学大会!计算语言学协会欧洲分会第 16 次会议(EACL 2021)有一个关于“紧急情况和危机管理的 NLP 应用”的专题。
我很高兴成为这条赛道的高级区域主席!我在机器学习和灾难应对领域工作了 20 年,我很高兴现在有更多的人在研究机器学习如何在最关键的时候帮助人们。
计算语言学协会欧洲分会第 16 届会议邀请提交…
2021.eacl.org](https://2021.eacl.org/calls/papers/)
一篇关于机器学习用于灾难应对的论文的大部分内容应该与应用科学中的任何其他论文相同:可重复的方法,这些方法明确地推进了我们关于如何部署和评估机器学习技术的知识。
然而,灾害应对的某些方面使得科学的某些方面变得更加重要,还有一些方面是灾害应对所独有的。有些是从事医疗保健工作的研究人员所熟悉的,但有些来自国际发展。这里总结了本文中涉及的要点:
- 大多数救灾工作是帮助受危机影响的社区自助。因此,增强受灾社区能力的工具是最有价值的,尤其是使用低资源语言的人。
- 对于专业救灾人员来说,信息管理是一个比信息发现更大的问题。
- 专注于灾难应对机器学习的论文不应该在科学上走捷径。
- 研究实验室建立的论文推广系统在灾难应对中没有地位。
- 在灾难期间不可能完全评估数据的敏感性,因此对正在发生的灾难的响应应该默认为私有数据实践。
- 救灾经常被用来掩盖侵犯人权的行为,特别是在独裁政权下,因此应该拒绝来自独裁政权的可能侵犯人权的研究。
- 研究人员不应该与非运营援助组织合作,应该知道如何发现运营和非运营组织之间的差异。
- 英语社交媒体处理对于灾难响应者来说并不有趣或有用。
- 忽略任何依赖发表在“ISCRAM”上的研究。
- 应用“无害”原则来评估影响。
当我对每一个进行扩展时,我将分享我自己经验中的例子。
1.灾难应对主要是社区自助
对于任何大的灾难,我们根本没有资源来直接帮助大多数人。在森林火灾发生前,你自己为你的财产所做的准备可能会比专业消防员有时间提供的任何准备产生更大的影响。在疫情期间,你将直接负责社交距离和卫生。地震后,你的邻居比专业搜救队更有可能把你从倒塌的房子里拉出来。
支持这些社区的最重要方式是清晰的沟通。说低资源语言的人更有可能成为自然和人为灾难的受害者。因此,任何有助于将信息传递给不同语言群体的技术都将在灾难中帮助他们。事实上,我相信,我所做的帮助大公司用更多语言部署技术的工作,比我为联合国在难民营工作的时间更能对灾难应对产生影响。
世界上大部分的语言多样性和大部分的(陆地)生态多样性,包括病原体,都发生在同一个热带地区。当大多数疾病爆发首次被讨论时,它很可能是在一种低资源语言中。来源:http://Robert Munro . com/research/unite _ for _ sight _ languages _ Munro . pdf
因此,如果你正在改善机器翻译或搜索引擎和在线商店等设备和应用程序的语言支持,那么你已经在解决灾难应对中机器学习最重要的问题。它帮助救灾人员与受影响的社区沟通,并帮助社区在网上搜索合适的资源来帮助自己。
就像我在 Gretchen McCulloh 最近的 Wired 文章中分享的那样,“新冠肺炎是历史上最大的翻译挑战”,我已经多次看到了这种错误的负面影响。比如,在埃博拉危机期间的塞拉利昂,一家国际通讯社在一个讲泰姆语的地区播放了曼德语公告,造成了不信任,因为曼德语被视为当时执政的政党的语言。因此,说泰姆尼语的人更有可能避开医疗诊所。
我与援助机构合作,得出了一个令人震惊的结论:每一个感染埃博拉病毒的人,就有十个人因为避开诊所而死于其他可预防的疾病。富裕国家的恐惧被当地媒体放大,对当地语言关注太少,导致的死亡人数比埃博拉病毒本身还多。
从积极的一面来看,做好这件事会产生很大的影响。例如,2010 年地震后,我招募并管理了 2000 名海地克里奥尔语使用者来翻译紧急信息。翻译人员的工作拯救了许多生命。它还支持用于灾害应对的机器学习研究,其数据用于 2011 年(WMT11)在举行的机器翻译共享任务研讨会,并作为现在广泛使用的多语言灾害应对数据集的一部分。
任何专注于低资源语言的论文都可以证明它将有助于灾难应对,因为它可以成为基础技术的一部分,使受灾人口能够更容易地交流和获取信息和服务。
2.信息管理是专业救灾人员面临的最大问题。
灾难响应的大部分工作是后勤工作,大多数灾难响应专业人员通过电子表格和非结构化文档共享信息。灾难期间的分析和机器学习主要集中在预测下一个“热点”将在哪里,这是一个神话(来自太多电影)。这些用例是存在的,但是很少。
例如,负责规划饮用水分配的灾难响应领导可能会收到来自不同机构或地区的数百份报告,每份报告都包含估计总体需求所需的信息。需要从这些报告中可靠地提取信息。
因此,如果您可以开发机器学习系统,从电子表格和 PDF 文档中的半结构化表格和表单中提取信息,那么您正在解决支持灾难响应专业人员的最重要问题之一。
10 年前的一个很好的例子仍然适用,那就是由邝琛、Joseph M. Hellerstein 和 Tapan S. Parikh 撰写的“设计自适应反馈以提高数据输入的准确性”。该论文评估了机器学习辅助技术,以帮助专业数据录入员将来自乌干达农村诊所的患者数据数字化,从而支持大量刚果难民。
3.不要在科学上走捷径
你可能已经在《新冠肺炎新闻》上看到,传染病专家反对广泛使用未经适当测试的疫苗。如果人们记忆中最广泛的疫情病毒的疫苗可以等待科学,那么你的机器学习研究也可以。
4.来自研究实验室的系统演示论文在灾难响应研究中没有一席之地
丰田陆地巡洋舰在援助界已经是老生常谈了:它们是我在一些救援情况下见过的大多数车辆。
丰田陆地巡洋舰:用于预测性和可靠性。来源:https://commons . wikimedia . org/wiki/File:World _ Food _ Programme _ land cruiser . jpg
陆地巡洋舰不一定是最完美的援助车辆,但它们是最可靠和可预测的。当他们确实有问题时,会有很多知道如何修理他们的人和很多合适的替换零件可用。
一个学术研究实验室能设计出更适合灾难应对的车辆吗?毫无疑问。这些车辆真的应该在紧急情况下部署吗?绝对不行。备件将很难获得,唯一的专家将是少数学者,他们将很快转向其他工作,无法帮助解决机械问题。因此,来自该实验室的科学可能会影响未来的发展,但他们不应该制造实际的车辆。
这同样适用于任何软件。软件原型可以为科学提供信息,并在非关键时期用于受控环境中,尤其是在有重要测试的人机交互(HCI)组件的情况下。然而,机器学习研究人员不具备创造可扩展技术的技能,也不具备在未来几年继续支持该软件的能力。援助机构没有工程能力采用一个学术系统,并通过大量的开发和测试使其可扩展和可靠。在学术演示中,作者声称他们的技术应该用于实际的关键数据,这是毫无用处的。
即使当我在斯坦福大学(可以说是最专注于行业的技术大学)时,当我需要作为灾难响应者快速开发工具时,我也不会与那里的同事一起工作。我与商业软件解决方案合作,因为可靠性比创新更重要,只有在回应之后,我才领导了关于机器学习如何改善未来回应的研究。
5.默认为私有数据惯例。
在正在发生的灾难中,不可能确定今天看起来不敏感的数据以后是否会变得敏感。所以,不要在灾难期间发布任何个人数据,包括已经开放的社交媒体。相反,等到受影响的人群不再有风险,然后让隐私专家来帮助决定什么可以共享,什么不可以共享。
即使对于被视为开放的数据,如果您在新的上下文中重新发布该数据,重新发布该数据也会变得敏感,并且聚合数据(包括机器学习模型)会变得比其单个数据点更敏感。
例如,在阿拉伯之春期间,我看到许多人在推特上谈论他们当地的情况:道路封锁、难民等。虽然它们是“公开”的推文,但这些推文显然是为少数几个追随者写的,他们没有意识到报道道路封闭也有助于描绘部队移动的画面。作为一个不应该做的例子,其中一些推文被复制到联合国控制的网站并重新发布,没有任何机制让原作者将它们从联合国网站上删除。中东和北非的许多参与者将联合国视为负面的外国影响(或入侵者),因此发推文的人被视为合作者——他们不在乎这些人是否只想与少数追随者分享信息。
所以,你需要问自己:将数据或模型重新文本化,使其现在由我自己或我的组织发布,会有什么效果?
6.救灾往往被用来掩盖侵犯人权的行为
虽然在灾难发生后,犯罪率通常会整体下降,但少数掠食者和机会主义者会试图从混乱中获得优势。这一点在暴虐的政府中尤为明显,他们利用灾难作为掩护来识别和压制批评他们的人。
如果您是一名考虑研究个人信息(包括种族、宗教、性别或政治偏好)的评论家或研究人员,那么您应该考虑使用案例,以及它是否会被用于侵犯人权,尤其是被专制政权所利用。作为指导,看看经济学人智库(EIU)编制的民主指数:https://en.wikipedia.org/wiki/Democracy_Index。
他们将国家分为四类:完全民主、有缺陷的民主、混合政体和威权政体。这一点很重要,因为:独立的研究机构不可能存在于独裁政权中。
如果存在敏感的用例,比如识别在社交媒体上抱怨政府或表达政治偏好的人,那么这方面的研究就不能被信任。这种情况经常发生。在去年我在 KDD 的演讲中,我谈到了一些国家是如何利用最近的 COVID 疫情(SARS-CoV-1)作为识别异议者的掩护。
一个为独裁政权工作的研究人员并不独立于他们的政府,就像一个民主国家的公共机构的研究人员独立于他们的政府一样。研究人员的身份或国籍不是问题:他们的雇主或资助者才是问题所在。因此,机器学习会议的项目主席应该立即拒绝由独裁政权资助的具有人权影响的研究。那些研究人员没有防止负面用例的独立性,不管他们的个人意图是什么。
有很多用例可以帮助应对灾难,最重要的用例不需要敏感数据:对低资源语言的一般研究和从半结构化文档中提取信息。因此,没有什么可以阻止一个出生在威权体制下的研究人员,或者选择受雇于威权体制的研究人员,为灾难应对机器学习研究做出贡献。
请注意,民主指数高的国家仍然可以侵犯人权,所以这并没有给这些国家的研究一张通行证。EIU 的民主指数主要集中在国家内部因素上。对于任何国家来说,灰色地带的一个很好的例子就是军事。世界上的军队也是最大的灾难应对组织,因此这使得复杂的评估通常必须在个案的基础上进行调查。
有些情况是明确肯定的。例如,2012 年,我们中的一小群人(非军事救灾人员)参加了由海军研究生院主办的演习,在那里我们旨在发现更好的方法,在灾难发生后通过航空图像进行损失评估。我们与民用航空巡逻队(美国军方的一部分)合作,他们飞越灾难现场拍摄图像,并与联邦应急管理局(国土安全部的一部分)合作,后者利用这些图像进行损害评估,以帮助应对。仅仅几个月后我们使用我们的新技术帮助应对飓风桑迪。毫无疑问,这是完全积极的。
然而,就像我在 2010 年海地地震的事后报告中所说的,有一种令人不安的紧张局势,因为许多海地人将美国军队视为前占领者。在其他情况下,喜欢与联合国儿童基金会合作支持西非的孕产妇健康,我们选择不与任何美国政府机构合作,因为这将被视为在帮助其他国家时缺乏独立性。因此,无论研究人员的雇主是谁,政府参与的伦理都需要在每篇论文的个案基础上加以考虑,尤其是当灾难和响应者来自多个不同的国家时。
7.不要与非运营援助组织合作
大多数向研究机构寻求帮助的国际发展组织实际上并没有从事灾难应对工作。为了给援助行业一个非常高层次的介绍,这里有一个图表显示了许多援助组织如何在灾难响应中工作:
援助组织结构的高级概述。少数在国家或国际一级提供援助的大型组织被称为“业务组织”,但大多数组织在实际救灾工作中使用当地的“执行伙伴”。一些地方援助组织可能是完全独立或联合独立的,并帮助更大的组织。“非运营型组织”是最小的,但可能会让人误以为它们很大,而且在运营。来源:https://www . kdnugges . com/2020/04/5-ways-data-scientists-can-help-covid-19 . html
如果有人请你帮忙,你怎么知道他们是否真的在回应?最好的帮助组织是在当地运作的组织。你当地的医院或难民食品配送中心需要帮助吗?从他们开始。
非运营组织通常规模较小,利用灾难作为筹资和宣传的机会。请注意,他们谈论的是与像世卫组织这样的大组织的“伙伴关系”,但没有一个地方说他们是“执行伙伴”。这通常是“实际上不是响应的一部分”的代码。如果他们联系你,很有可能你就是产品,他们会告诉潜在的资助者类似于“看,我们有来自一所著名大学的研究人员给灾难应对带来了创新。”
像联合国难民署,联合国儿童基金会,红十字会,无国界医生组织这些运营组织都有自己的技术创新团队,所以没有必要与非运营组织合作。非运营组织的激励措施与隐私并不一致,因为他们需要宣传来继续吸引资金。举个例子,看看一个不起作用的联合国组织是如何在 2011 年乌干达爆发埃博拉疫情后编辑我的视频采访的:他们编辑了我的声明,即需要更多的隐私,而不是说我们需要更少的隐私,这样他们就可以访问这些数据:
medium.com](https://medium.com/@robert.munro/tracking-epidemics-with-natural-language-processing-and-crowdsourcing-4df0bc37168c)
如果没有行动援助机构或实施伙伴需要你的帮助,那么我建议研究灾难响应的基本构件,如支持低资源语言和从半结构化文档中提取信息。
就像名字中带有“民主”的国家往往不是民主国家一样,类似的经验法则也适用于名字中带有“灾难”的组织。运营组织以他们所帮助的人或他们所提供的服务命名:无国界医生组织、世界卫生组织、联合国儿童基金会等。如果一个组织的名称中有“危机”、“灾难”或“人道主义”的字眼,它可能不会做灾难应对:没有人想从一个名字会让他们想起自己的创伤的组织那里获得援助,这些组织的名字是为了最大限度地宣传和资助,而不是应对。
8.英语社交媒体处理对灾难响应者没有用
更广泛地说,在 NLP 中,我们知道我们的模型的纯英语结果很少告诉我们其他语言工作得如何。英语国家往往已经拥有资金最充足的灾难应对组织,因此这是英语的不相关性被放大的一个领域。
最佳实践是将社交媒体用作灾难应对组织与受危机影响的人群沟通的广播媒体,并且开放的社交媒体不应用作受灾难影响的人群的直接沟通渠道。这一结论是在上述利比亚事件后的灾难响应社区中得出的,是对 2010 年巴基斯坦洪水的响应,在那里公开讨论的援助营地受到恐怖分子的威胁,以及对海地响应的分析,其中发现尽管许多媒体文章称赞社交媒体,但开放的社交媒体不是响应中的重要因素。
英国和独裁政权之间也存在交叉问题。暴虐的政权经常针对被视为政治对手的知识分子。说英语通常标志着一个人受过更多的教育,并且是一个对国际听众说话的人。无力应对灾难会让一个政府看起来软弱无力,这尤其暴露了一个通过展示实力来领导的威权领导人。例如,2013 年台风“海燕”袭击菲律宾时,菲律宾少数批评政府应对措施的说英语的人被认为有遭到政府报复的危险。因此,我们认为将英语社交媒体数据作为灾难响应数据集的一部分发布是不道德的。
我的博士论文展示了将英语社交媒体传播应用到灾难中的其他领域是多么困难,这也在我的博士导师 Christopher Manning 与人合著的一篇论文中为国际发展社区做了总结。因此,没有理由忽视这一点,只进行英语研究,声称它有帮助。
如果这项研究是针对灾难应对者的而不是,而是旨在支持相关专业人士,那么就有更强有力的论据可以证明。例如,有一项有趣的研究是利用机器学习帮助心理健康专家理解在线论坛上对灾难的社会反应。然而,你不能在 Twitter 上直接编码人们的医疗保健信息。自 2018 年以来,对包括健康状况在内的敏感信息进行编码已被禁止,对于学者来说,这也违反了 ACM 的道德准则。
9.忽略任何依赖于“ISCRAM”研究的东西
每个科学子领域都有一个被拒绝的论文被一群伪匿名的研究人员接受的地方,这些研究人员接受彼此的工作。对于应用于灾难响应的机器学习工作,这是“危机响应和管理的信息系统”(ISCRAM,我们这些实际从事灾难响应工作的人发音为“I-SCAM”)。
2013 年,我写了一篇关于“顶级 NLP 会议”的文章,以灾难应对研究为例:
medium.com](https://medium.com/@robert.munro/the-top-10-nlp-conferences-f91eed97e950)
在那篇文章中,我注意到 ISCRAM 发表了被主流 NLP 会议拒绝的垃圾科学文章。大约一年后,我发表的每一篇关于实际救灾工作的论文都在 ISCRAM 上被一个独裁政权的造纸厂剽窃为“模拟”,作为他们试图粉饰其系统的一部分,而这些系统实际上是为侵犯人权的使用案例而建造的。
仅仅依靠 ISCRAM 发表的研究的论文是不可信的,也不应该被主流科学机构接受。
10.评估影响时应用“无害”原则
医学和灾难响应界的“无害”原则应该应用于评估机器学习研究。如果被杀死的人本来不会死,组织不会部署一种杀死的人是它拯救的人的 50%的疫苗。对于大多数包含个人数据的用例来说也是如此,即使这些数据已经公开:是否存在可以用来伤害那些本来不会受到伤害的人的用例?
机器学习研究人员不应该认为他们的研究有净利益,他们可能没有资格评估,无论如何。如果研究中有一个明显的负面用例会对那些不会受到伤害的人产生负面影响,那么这篇论文应该基于伦理的理由被拒绝。
我应该如何开始研究用于灾难响应的机器学习?
如果你想在正在发生的灾难中提供帮助,而你又没有经验,记住人们在灾难中训练你的时间最少*。如果你最有价值的技能是数据清理或其他不会产生研究论文的技能,不要惊讶。如果你没有经过任何医学训练就去医院帮忙,如果他们把拖把和水桶放在你手里,你不应该抱怨。这同样适用于救灾。请参阅我最近的一篇文章,了解更多关于如何提供帮助以及应该避免什么的信息:数据科学家可以帮助应对新冠肺炎的 5 种方式以及应该避免的 5 种行动。*
如果你没有经验,并且想做一些可以在科学场所发表的东西,考虑用例,比如支持低资源语言和从半结构化文本中提取信息。这些用例还可以帮助其他领域的影响,如医疗保健和环境。因此,潜在影响很大,但无意中造成伤害的可能性却小得多。
研究基于内容的新闻提要过滤
使用分类算法探索个性化新闻源的效果
随着新闻消费变得越来越数字化,新闻平台不得不努力转移和保留他们的用户群。维持和增加任何数字平台的用户群的一个行之有效的方法是应用个性化技术。目前,新闻平台倾向于人工选择应该在首页推广的文章。这部分是因为他们一直是这样工作的,但也是因为他们根本没有意识到将个性化技术应用到他们的新闻提要的真实世界的影响。随着这些新闻提要成为他们与客户的主要交互方式,他们对尝试这项技术的犹豫是可以理解的。通过这项研究,我们旨在通过对基于内容的过滤对新闻提要的影响提供一些有价值的见解,消除这种犹豫。
这个博客为我的学士论文提供了一个研究方向。它是与 Max Knobbout 合作编写的,在 Triple 领导人工智能。
我们将解释技术概念,实验设置和最重要的结论。最初的研究是使用一个数据集完成的,该数据集包含来自荷兰一个地区新闻平台的文章。在技术分析中,我们将使用开源替代方案。
目录
技术概念:作为分类的建议
在本节中,我们将解释如何将推荐相关新闻文章的问题视为一个分类问题。一般来说,有两类推荐算法:
- 基于的协同过滤:在这种向用户推荐商品的方式中,我们利用给定平台内所有用户与所有商品的交互来预测单个用户可能喜欢什么。例如,在决定你是否会喜欢一个特定的项目时,我们可以寻找有相似品味的用户,看看他们对那个项目的想法。
- 基于内容的:在基于内容的推荐中,我们仅使用项目的特性(特征)来确定您是否喜欢某个项目。我们不使用其他用户的互动。
协同过滤的优势在于,我们可以使用非常少的数据来为新用户创建相当准确的简档。然而,缺点是我们需要用户-项目交互数据。换句话说,协同过滤遭受所谓的“冷启动”问题。在这篇博客中,我们将探讨如何将推荐问题作为一个分类问题。这种方法是基于内容的,因此不会遇到冷启动问题。更具体地说,我们将创建一个数据集,并在一组预定义的文章上为的每个用户训练一个 ML 模型。这个模型能够预测每个用户对任何看不见的文章的评价。
在本节中,我们将解释并执行以下步骤来创建我们的分类建议框架:
- 我们将为新闻文章集提取相关特征。
- 从所有新闻文章的集合中,我们将提取一小部分训练文章。在我们的实验中,我们选择了 30 篇独特的文章。
- 然后,这些文章被呈现给用户,用户选择“喜欢”或“不喜欢”(类似 Tinder 的滑动流)。然后,这被用作我们的监督分类问题的标记训练集。
- 我们将使用这些文章来训练一个模型,该模型能够预测对未看到的文章的喜欢/不喜欢。为了演示我们所做的,我们将使用在 Kaggle 上找到的“所有新闻”数据集的子集,可以在这里下载:【https://www.kaggle.com/snapcrack/all-the-news
1。特征提取
我们方法中的第一个主要挑战是特征提取的问题。在自然语言处理领域,对大量文本建模的一种流行方法仍然是词袋(BoW)表示法。本质上,文本的 BoW 表示可以通过简单地计算文档中出现的所有单词来获得。然后,每个单词的计数被用作一个特征,允许我们将每个文档表示为某个 N 维空间中的一个向量(其中 N 是在所有新闻文章中找到的唯一单词的数量)。换句话说,我们失去了一些意义,因为我们不记得单词的顺序,但我们获得了将文章表示为数字向量的能力。有许多教科书和在线知识库更深入地解释了 BoW 模型。
一旦获得了文档的这种弓形向量,以某种相关的方式对它们进行加权通常是一个好主意,尤其是在 NLP 领域。这背后的直觉是,一些词比其他词更不相关,以描述一篇文章的主题。例如,像“the”、“a”和“an”这样的词是非常常见的词,但通常不传达任何意思。相反,一个在一些文档中很常见,但在其他文档中很少见的单词(例如像“Trump”这样的名字)通常会为文档传递很多含义。这一观察结果是 TF-IDF 加权方案的基础。总的想法如下:
- 我们缩小整个数据集中常见的特征。这些词通常没有什么意义。
- 我们放大了某些文档中常见的特征,但在整个数据集上却很少见。这些词通常传达很多意思。
一旦向量被我们的 TF-IDF 加权方案加权,我们仍然面临着一个主要的问题/挑战。这就是数据集中有太多要素的挑战。简单地创建一个 BoW 模型,并根据 TF-IDF 方案对它们进行加权,并删除一些罕见的特征,仍然可以为超过 5000 个维度的的每篇新闻文章提供一个矢量表示。也就是说,如果我们要在仅 30 篇新闻文章上训练我们的分类模型,并且每篇新闻文章具有超过 5000 个特征,那么任何分类模型如何能够决定哪些特征是相关的,哪些是不相关的?每当特性的数量(5000 以上)接近或大于实例的数量(30)时,我们几乎不可避免地会使结果模型过拟合。为了避免这一点,我们将需要执行一些特征约简,在机器学习中通常称为降维问题。
假设你没有任何机器学习的先验知识,你的任务是对输入空间进行一些相关的降维。也就是说,现在每篇新闻文章都被表示为一个长度大于 5000 的 TF-IDF 向量,我们希望将这个长度减少到某个较小的数字(比如说 16),同时又不会损失太多这些文章内容的含义。也就是说,如果两篇文章是关于相似的主题,我们希望得到的向量靠得很近,如果文章是关于完全不同的主题,我们希望它们离得很远。
你会如何处理这样的问题?通过查看 TF-IDF 向量,您可能会得出这样的结论:一些术语经常在一些文档中一起出现,而另一些术语经常在不同的文档中出现。例如,“唐纳德”一词可能经常与“特朗普”一起出现,但在谈论“天气”时,这两个词可能都不常见。您可能会想到的想法是将一些高阶项(称为“组件”)建模为一些单个项的线性组合。例如,一个组件可以为诸如“唐纳德”、“特朗普”、“怀特”、“豪斯”等术语分配高权重。而另一个组件可以为诸如“天气”、“晴天”、“雨天”之类的术语分配高权重。
给定这些组件及其各自的权重,我们就可以将每篇文章表示为组件的某个向量。这是“奇异值分解”(SVD)背后的代数直觉(也有从更多几何角度对该技术的解释)。虽然我们还没有谈到这些组件是如何确定的,但为了获得技术背后的直觉,我们根本不需要这样做。
BoW 提取,与 TF-IDF 加权方案一起,然后使用 SVD 选择最佳组件来描述文章中的主题,通常一起被称为“潜在语义分析”(LSA)算法。关于这项技术的更多信息可以在维基百科的文章中找到:https://en.wikipedia.org/wiki/Latent_semantic_analysis
让我们用代码来执行这项任务!让我们首先下载 csv 文件并将其加载到 pandas 中。
然后,我们将使用 Python 中的 scikit-learn 来执行上述步骤。出于演示的目的,我们将创建一个管道,该管道由 TfidfVectorizerfollowed 后跟一个 TruncatedSVD 组成。TfidfVectorizer 结合了 BoW 表示(在 scikit-learn 中称为 CountVectorizer)和 TF-IDF 加权方案(在 scikit-learn 中称为 TfidfTransformer)。
作为 TF-IDF 步骤的一个超参数,我们给出了一组我们想要包含的停用词(从 nltk 库中获得)(只是为了安全起见),并且我们告诉矢量器我们想要 0.5%的最小文档频率(min_df)。这意味着我们只对出现在所有文章中至少 0.5%的单词感兴趣,这使得我们可以排除超级罕见的单词或拼写错误。
TruncatedSVD 步骤创建了低维向量,其中每个维度(称为“分量”)是我们前面描述的这些项的线性组合。超参数 n_components 决定了我们想要保留多少这样的组件;我们保留的越多,我们保留的原始数据的信息就越多(注意:保留的信息量通常是通过计算“解释方差”来计算的);原始数据集中存在的差异仍然可以用低维表示来解释)。在我们的代码示例中,我们只选择了 16 个组件。对于 LSA 来说,这个值特别低,我们肯定会丢失一些信息。然而,由于我们只想在 30 篇文章的基础上构建我们的推荐系统,并且我们不想过度适应这个模型,所以我们需要特征的数量很低。
(50000, 16)
从上面的输出可以看出,我们已经成功地将每篇文章转换成了一个 16 维的分量向量。验证这些组件代表什么通常不是一个坏主意。请记住,每个组件都是作为一个线性组合的条款计算的。通过检查这些项中的哪些项对于给定的分量具有高权重(数学上我们将这些权重称为“系数”),我们可以了解这些分量代表什么。这些项的系数存储在变量pipe.named_steps.svd.components_
中,因此通过检查这个矩阵,我们可以用自定义函数提取系数最高的项。
['trump', 'clinton', 'hillary', 'donald', 'campaign']
换句话说,第一部分(16 个部分中的)绝对是关于唐纳德·特朗普和希拉里·克林顿以及他们的竞选活动。让我们检查另一个:
['comey', 'fbi', 'house', 'investigation', 'white']
第七部分是关于解雇詹姆斯·科米。这意味着大量重要的新闻文章都是关于这个特定的话题。请注意,这都是为我们自动计算的,我们不需要设计任何功能。这就是无监督机器学习的力量!
2.提取 30 篇相关文章
所以我们成功地提取了我们新闻文章的相关特征。请记住,我们希望向每个用户呈现 30 篇独特的文章,以确定他们的口味。但是我们选择哪些文章呢?一般来说,我们希望选择 30 篇文章,它们很好地代表了整个数据集。换句话说,我们想要那种“覆盖”整个数据集的文章。如果我们有 30 篇非常接近数据集的文章,我们可以对用户的总体品味做出更好的估计。
为了做到这一点,我们可以执行以下两个步骤:
- 首先,我们对 16 维 LSA 向量执行 K 均值聚类(其中 K=30)。这将在新闻文章居中的 16 维空间中计算 30 个点(称为“质心”)。
- 对于每个质心,我们计算一个最佳匹配的文章。最佳匹配的物品是到质心的距离最低的物品。
然后将得到的 30 篇文章显示给用户,以便创建数据集。现在让我们来计算一下吧!
因此,结果是一个 30 长度的数组,其中在每个索引i
处,文章best_matching_articles[i]
到质心i
的距离最小。相应的条款有:
图由 Michel Wijkstra (2020)提供
3.创建训练集
我们现在向每个用户展示这 30 篇文章,用户必须选择like
(向右滑动)或dislike
(向左滑动)。我们将假设结果是一个 30 长度的列表。为了便于演示,可以按如下方式生成随机选择:
4.训练模型
我们现在准备用 30 篇最佳匹配文章的 16 维 LSA 向量的输入数据训练一个分类器,标签为like
或dislike
。换句话说,我们现在离开了无监督 ML 的区域,进入了有监督 ML 的区域。对于我们的模型,我们有许多选择,但是我们通常希望选择一个能够处理少量实例的模型。为此,我们选择最近邻分类模型。该模型所做的是,对于每个看不见的实例,查看哪些已知文章是最近的(称为“最近邻居”)。基于这些最近的邻居,分类器然后决定是否将未见过的文章评级为like
或dislike
。
例如,如果所有邻居都是like
,显然我们也想将未看到的文章评级为like
。这是最近邻分类法背后的直觉。让我们用代码来看看!
我们可以选择两个有趣的超参数来抵消过度拟合。参数n_neighbors
告诉我们想要考虑多少个邻居来分类一个看不见的实例。很明显,如果我们把它做得很小(例如1
),我们很容易过度拟合,因为我们只对 1 个邻居做了决定,如果我们要看更多的邻居,这可能是一个“异常值”。例如,最近的邻居可能会说“喜欢”,但如果我们观察更多的邻居,我们会发现他们会说“不喜欢”。相反,如果我们使邻居的数量太高,我们可能会使分类器不足,因为我们只是简单地取所有邻居的平均值。
distance
超参数告诉我们,邻居越近,它在决定我们是否想要对一篇看不见的文章进行喜欢/不喜欢评级时的权重就越大。
使用这个分类器,我们可以预测新闻文章的整个数据集的评级:
array(['dislike', 'like', 'like', ..., 'like', 'like', 'like'],
dtype='<U7')
剩下的最后一个问题是:这个分类器有多好?验证这一点的一种方法是使用某种形式的交叉验证。由于实例数量非常少,交叉验证的一个好方法是使用“留一个”(LOO)交叉验证策略。在我们的例子中,这将在 29 篇文章上训练模型,并查看最后一篇文章是否被正确分类。每篇文章重复 30 次,这将为我们赢得一个分数(正确预测,也称为“准确性”)。因为我们没有用户的实际评级,所以我们不能在这里这样做,但是验证最终的模型总是一个好主意。在 scikit learn 中,LOO 是在sklearn.model_selection.LeaveOneOut
中实现的。
真实世界实验
现在我们已经有了技术实现,我们可以进行实验了。实验包括两个阶段;在第一阶段,我们将收集关于回答者兴趣的信息来训练算法,在第二阶段,我们将使用训练好的算法来推荐文章。我们有 126 位受访者帮助我们。
第一阶段:
为了使用我们的算法推荐文章,我们首先需要有每个回答者的个人资料。这就是我们面临一个重要决定的地方:使用大量的数据点会提高档案的质量,但是在这个阶段花费太多时间可能会导致回答者失去兴趣。我们最终决定使用 30 篇文章。我们觉得这是模型质量和收集数据时间之间的一个很好的平衡。
在最初的研究中,确定每个回答者进行实验的时间不应超过 6 分钟。这是荷兰消费数字新闻的平均时间。
为了只用 30 篇文章创建最好的个人资料,我们需要一个尽可能多样化的选择。为此,我们利用 K-means 创建了 30 个聚类。从每个聚类中,我们选择离质心距离最小的文章。
选定的文章以刷卡的形式呈现给受访者,这是一个从 Tinder 等应用程序借鉴来的成熟概念。对于那些不熟悉这个概念的人来说,文章显示得就像一副扑克牌。回答者可以向左刷卡表示不喜欢这篇文章,向右刷卡表示喜欢。我们选择这种设计是因为它简单快捷。在浏览完所有 30 篇文章后,收集了必要的信息,第一阶段结束。
第二阶段
既然我们已经有了受访者的资料,我们可以开始收集行为数据。在这一阶段,受访者接触到 30 个新闻视图,包含不同数量的个性化文章。这个数量在 10%到 70%的个性化内容之间变化。每个回答者都被要求选择一篇他们想读的文章。对于每个提供的新闻综述,我们都存储了文章,无论它们是否是个性化的,以及回答者的选择。我们的结论是基于这些储存的数据。
左:第一阶段刷卡界面,右:第二阶段新闻反馈|图由 Michel Wijkstra (2020)提供
结论
从收集的数据中,我们设法得出了一些有趣的结论。首先,我们应该注意到,我们根据受访者的兴趣“广度”将他们分成了 3 组。这导致了有狭隘、平均和广泛兴趣的回答者群体。分类是通过计算第一阶段喜欢的文章数量,并在每个第 33 百分位上划分集合来完成的。这项研究得出了两个有趣的结论,将在下面讨论。
个性化内容的效率提高了 20%到 40%
第一个有趣的发现是个性化内容的消费增加了 20%到 40%。兴趣较窄的一组显示出 20%到 30%的个性化改善,而兴趣一般和广泛的一组达到 40%。在图中,我们看到兴趣广泛的那组也有 60%左右的峰值,但我们无法发现为什么会出现这种效应。
个性化内容的消费|图由 Michel Wijkstra (2020)
个性化内容的有效性从 50%降低到 70%
我们发现的第二个效应更出乎意料。在实验的开发过程中,普遍的期望是在某个时候只消费个性化的内容,而不接触所有非个性化的内容。然而,结果证明这是错误的。令我们惊讶的是,消费的个性化内容的数量从 50%开始下降,当我们达到 70%的个性化内容时,甚至下降到我们预期的基线以下。这似乎表明,当有太多个性化内容被推送到新闻提要时,某种过饱和开始出现。这最终似乎导致受访者寻求多样化,将个性化内容的消费降至基线以下。效果显示如下。
计算有效性的方法是最初研究的一部分,但超出了这篇博文的范围。
每个个性化级别的有效性|图由 Michel Wijkstra 提供(2020)
一锤定音
我们的结论表明,有限的个性化将有利于您的网站。如果你是新闻平台的一员,我们希望这篇文章能启发你给个性化一个机会。如果你决定实现它,我们很想知道你的结果!
否则,我们希望你已经学到了一些东西,并享受阅读。如果您有任何问题,请随时联系麦克斯或本人。
使用 Python 中的 melt 重塑熊猫数据框—教程和可视化
PYTHON 熊猫数据帧重塑
使用 pd.melt 将宽转换为长
如何在 Python 中使用 pd.melt()将 pandas 数据帧由宽变长(此处运行代码)
有许多不同的方法可以将熊猫的数据帧从宽 T7 变成长 T8。但是melt()
方法是最灵活的,并且可能是你一旦学好就需要使用的唯一方法,就像你只需要学习一种方法 [pivot_table()](/reshape-pandas-dataframe-with-pivot-table-in-python-tutorial-and-visualization-2248c2012a31)
就可以从**长到宽进行整形(**见下面我的另一篇文章)。
[## 用 Python 中的 pivot_table 重塑熊猫数据框—教程和可视化
使用 pd.pivot_table 将 long 转换为 wide
towardsdatascience.com](/reshape-pandas-dataframe-with-pivot-table-in-python-tutorial-and-visualization-2248c2012a31)
本教程将带你通过使用与熊猫数据帧相关的pd.melt()
或melt
方法来重塑数据帧。在像 R 这样的其他语言中,melt 也被称为 gather。另外,R 也有一个melt
函数,以同样的方式工作。
你唯一需要的函数和教程
towardsdatascience.com](/reshape-r-dataframes-wide-to-long-with-melt-tutorial-and-visualization-ddf130cd9299)
我强烈建议您在阅读本文时尝试一下 Python 中的代码。打开我的 DeepNote 笔记本 (你只能运行但不能编辑这个笔记本),边看这篇文章边运行单元格。
另外,你可能想看看官方的熊猫文档和我的 numpy 重塑教程:
[## 在 Python 中重塑 numpy 数组—一步一步的图形教程
本教程和备忘单提供了可视化效果,帮助您理解 numpy 如何重塑数组。
towardsdatascience.com](/reshaping-numpy-arrays-in-python-a-step-by-step-pictorial-tutorial-aed5f471cf0b)
宽与长数据帧
如果我们观察一个宽的数据帧并将其与一个长的数据帧进行比较,就很容易理解它是什么或者看起来是什么样子。
可以使用 pd.melt()(运行代码此处)来熔化/堆叠宽熊猫数据帧
下面是相应的数据帧(具有相同的信息),但以长的形式:
可以使用 pd.pivot_table()来“解除”Long pandas 数据帧(本文未涉及)
在开始我们的pd.melt
教程之前,让我们用pd.DataFrame
用 Python 重新创建上面的宽数据帧。
import pandas as pd# create wide dataframe
df_wide = pd.DataFrame(
{"student": ["Andy", "Bernie", "Cindy", "Deb"],
"school": ["Z", "Y", "Z", "Y"],
"english": [10, 100, 1000, 10000], # eng grades
"math": [20, 200, 2000, 20000], # math grades
"physics": [30, 300, 3000, 30000] # physics grades
}
)
熔体实施例 1
我们通过id_vars
指定标识符列来融合数据帧。“剩余的”非标识符列(英语、数学、物理)将被融合或堆叠成一列。
将创建一个新的指示器列(包含值英语、数学、物理),我们可以通过var_name
重命名这个新列(类)。我们也可以通过value_name
重命名包含所有实际成绩的列(gRaDe)。
print(df_wide)
> student school english math physics
Andy Z 10 20 30
Bernie Y 100 200 300
Cindy Z 1000 2000 3000
Deb Y 10000 20000 30000df_wide.melt(id_vars=["student", "school"],
var_name="cLaSs", # rename
value_name="gRaDe") # rename> student school cLaSs gRaDe
0 Andy Z english 10
1 Bernie Y english 100
2 Cindy Z english 1000
3 Deb Y english 10000
4 Andy Z math 20
5 Bernie Y math 200
6 Cindy Z math 2000
7 Deb Y math 20000
8 Andy Z physics 30
9 Bernie Y physics 300
10 Cindy Z physics 3000
11 Deb Y physics 30000
从宽到长:新的指示器列“等级”+熔化/堆积值“等级”列(运行代码此处为)
熔体实施例 2
你可以用value_vars
来指定你想把哪些列融掉或者堆到列里(这里我们排除了物理列,所以value_vars=["english", "math"]
)。我们也从id_vars
中删除了学校一栏。
print(df_wide)
> student school english math physics
Andy Z 10 20 30
Bernie Y 100 200 300
Cindy Z 1000 2000 3000
Deb Y 10000 20000 30000df_wide.melt(id_vars="student",
value_vars=["english", "math"],
var_name="cLaSs", # rename
value_name="gRaDe") # rename> student cLaSs gRaDe
0 Andy english 10
1 Bernie english 100
2 Cindy english 1000
3 Deb english 10000
4 Andy math 20
5 Bernie math 200
6 Cindy math 2000
7 Deb math 2000
宽到长:原栏目学校和物理已被删除(运行代码此处)
熔体实施例 3
最后,让我们看看如果我们只指定学生列作为标识符列(id_vars="student"
)而不指定您想要通过value_vars
堆叠哪些列会发生什么。因此,所有非标识符列(学校、英语、数学、物理)将被堆叠到一列中。
产生的长数据帧看起来是错误的,因为现在 cLaSs 和 gRaDe 列包含了不应该在那里的值。这里的重点是向你展示pd.melt
是如何工作的。
print(df_wide)
> student school english math physics
Andy Z 10 20 30
Bernie Y 100 200 300
Cindy Z 1000 2000 3000
Deb Y 10000 20000 30000df_wide.melt(id_vars="student",
var_name="cLaSs", # rename
value_name="gRaDe") # rename> student cLaSs gRaDe
0 Andy school Z
1 Bernie school Y
2 Cindy school Z
3 Deb school Y
4 Andy english 10
5 Bernie english 100
6 Cindy english 1000
7 Deb english 10000
8 Andy math 20
9 Bernie math 200
10 Cindy math 2000
11 Deb math 20000
12 Andy physics 30
13 Bernie physics 300
14 Cindy physics 3000
15 Deb physics 30000
宽到长:学校列不是标识符列(运行代码此处为)
结束语
我希望现在你对pd.melt
如何重塑数据帧有了更好的理解。期待大家的想法和评论。
如果你觉得这篇文章有用,请关注我并访问我的网站获取更多数据科学教程和我的其他文章:
使用枚举和压缩编写更好的 Python 循环
towardsdatascience.com](/two-simple-ways-to-loop-more-effectively-in-python-886526008a70) [## 4 个键盘快捷键,可高效编辑文本并提高工作效率
高效地在文本中导航和移动光标
medium.com](https://medium.com/better-programming/4-keyboard-shortcuts-to-edit-text-efficiently-and-improve-productivity-66894c8d51b8) [## 真实或虚假的关联:你约会的有魅力的人更令人讨厌
使用 Python 模拟数据、测试直觉并提高数据科学技能
towardsdatascience.com](/real-or-spurious-correlations-attractive-people-you-date-are-nastier-fa44a30a9452) [## 使用终端多路复用器 tmux 提高编码和开发效率
简单的 tmux 命令来提高您的生产力
medium.com](https://medium.com/better-programming/code-and-develop-more-productively-with-terminal-multiplexer-tmux-eeac8763d273) [## 新冠肺炎危机期间的免费在线数据科学课程
像 Udacity、Codecademy 和 Dataquest 这样的平台现在免费提供课程
towardsdatascience.com](/free-online-data-science-courses-during-covid-19-crisis-764720084a2)
更多帖子, 订阅我的邮件列表 。
用 Python 中的 pivot_table 重塑熊猫数据框—教程和可视化
PYTHON 熊猫数据帧重塑
使用 pd.pivot_table 将 long 转换为 wide
如何在 Python 中使用 pd.pivot_table()将 pandas 数据帧由长变宽(此处运行代码)
有许多不同的方法可以将熊猫的数据框从长的变成宽的。但是pivot_table()
方法是最灵活的,并且可能是你一旦学好就需要使用的唯一方法,就像你只需要学习一种方法 [melt](/reshape-pandas-dataframe-with-melt-in-python-tutorial-and-visualization-29ec1450bb02)
就可以从宽到长进行整形(下面的见我的另一篇文章)。
[## 使用 Python 中的 melt 重塑熊猫数据框—教程和可视化
想象一下 pd.melt 是如何将熊猫数据帧从宽到长进行整形的
towardsdatascience.com](/reshape-pandas-dataframe-with-melt-in-python-tutorial-and-visualization-29ec1450bb02)
本教程将带你通过使用与熊猫数据帧相关的pd.pivot_table
或pivot_table
方法来重塑数据帧。在 R 等其他语言中,pivot 也被称为 spread 或 dcast。
我强烈建议您在阅读本文时尝试一下 Python 中的代码。尝试在我的共享 DeepNote 笔记本 上运行本教程(只能运行不能编辑本笔记本)。
此外,你可能会感兴趣的类似教程,描述了与pd.melt
和我的 numpy 整形教程相反(从宽到长的整形)。
[## 在 Python 中重塑 numpy 数组—一步一步的图形教程
可视化 numpy 如何重塑数组
towardsdatascience.com](/reshaping-numpy-arrays-in-python-a-step-by-step-pictorial-tutorial-aed5f471cf0b)
长与宽数据帧
如果我们观察一个长数据帧并将其与宽数据帧进行比较,就很容易理解长数据帧是什么或看起来像什么。
可以使用 pd.pivot_table()(运行代码此处)旋转或“取消融化”Long pandas 数据框架
下面是相应的数据帧(具有相同的信息),但采用宽形式:
可使用 pd.melt() 熔化/堆叠宽熊猫数据帧
在开始我们的pd.pivot_table
教程之前,让我们用pd.DataFrame
用 Python 重新创建上面的宽数据帧。请记住,您也可以跟随我的共享笔记本。
df_long = pd.DataFrame({
"student":
["Andy", "Bernie", "Cindy", "Deb",
"Andy", "Bernie", "Cindy", "Deb",
"Andy", "Bernie", "Cindy", "Deb"],
"school":
["Z", "Y", "Z", "Y",
"Z", "Y", "Z", "Y",
"Z", "Y", "Z", "Y"],
"class":
["english", "english", "english", "english",
"math", "math", "math", "math",
"physics", "physics", "physics", "physics"],
"grade":
[10, 100, 1000, 10000,
20, 200, 2000, 20000,
30, 300, 3000, 30000]
})
示例 1
我们经常希望保持标识符列不变(index=["student", "school"]
),但是基于另一列(columns="class"
)旋转或“拆分”一列的值(values="grade"
)。比较下面的原始数据框架和旋转数据框架,你就会明白这意味着什么。
df_long.pivot_table(index=["student", "school"],
columns='class',
values='grade')
长到宽:等级中的值被分割/旋转到三个独立的列中(运行代码此处为)
class 列中的每个唯一值将成为 pivoted/wide 数据框架中的一个新列(英语、数学、物理)。我们还可以为columns
参数提供一个列表。
要消除多重索引,请使用reset_index()
。
示例 2
您还可以通过指定margins=True
(默认为False
)来聚合每个结果行和列。
df_long.pivot_table(index=["student", "school"],
columns='class',
values='grade',
margins=True, # add margins
aggfunc='sum') # sum margins (rows/columns)
在这里,我们通过aggfunc='sum'
(默认'mean'
)计算总和来进行聚合。
长到宽:包括边距(运行代码此处)
您可以使用许多其他聚合函数(例如,'median'
'sum'
'max'
)。您也可以将多个功能指定为一个列表(如aggfunc=['mean', 'sum']
)。
示例 3
如果我们不通过columns
、指定任何列,所有剩余的非标识符数字列(在此数据框架中只有等级)将被旋转(从长到宽)。
df_long.pivot_table(index=["student", "school"])
Long to wide:所有非标识符数字列都被旋转(运行代码此处为)
在原始 long 数据中,每个学生有四个成绩(英语、数学、物理),然而在上面的pivot_table
示例中,每个学生在旋转后只有一个成绩。
为什么以及如何工作?如果你还记得上面的例子,缺省值是aggfunc='mean'
。因此,该函数所做的是将数据按学生和学校分组(通过index=["student", "school"]
,并计算每组的平均值。
如果您使用与 pandas 数据帧相关的groupby
方法,您将得到与上面相同的结果。
df_long.groupby(['student', 'school']).mean().reset_index() student school grade
0 Andy Z 20
1 Bernie Y 200
2 Cindy Z 2000
3 Deb Y 20000
如果你改变默认的聚合函数(如aggfunc='max'
,你会得到不同的结果。下面的例子向您展示了如何指定不同的聚合函数,也向您展示了如何使用groupby
来执行相同的透视。
请注意,您还会看到与每个“最大”和“第一”值相关联的类。
df_long.pivot_table(index=["student", "school"],
aggfunc=['max', 'first'])# groupby equivalent
# df_long.groupby(["student", "school"]).agg(['max', 'first']) max first
class grade class grade
student school
Andy Z physics 30 english 10
Bernie Y physics 300 english 100
Cindy Z physics 3000 english 1000
Deb Y physics 30000 english 10000
实例 4
最后一个示例向您展示了透视多个列(columns=['school', 'class']
)时会发生什么,您还可以通过用另一个值替换NaN
值来处理透视后丢失的值(在下面的示例中为-5)。
df_long.pivot_table(index="student",
columns=['school', 'class'],
values='grade',
fill_value=-5) # replace NaN with -5
长到宽:缺失值替换为-5(默认 NaN)(运行代码此处为)
NaN
值是预期值,因为每个学生只属于一所学校(Y 或 Z)。例如,Andy 在学校 Z,因此在 Y 列中没有成绩。
结束语
我希望现在你对pd.pivot_table
如何重塑数据帧有了更好的理解。期待大家的想法和评论。
如果你觉得这篇文章有用,请关注我并访问我的网站获取更多数据科学教程和我的其他文章:
[## 使用 Python 中的 melt 重塑熊猫数据框—教程和可视化
想象一下 pd.melt 是如何将熊猫数据帧从宽到长进行整形的
towardsdatascience.com](/reshape-pandas-dataframe-with-melt-in-python-tutorial-and-visualization-29ec1450bb02) [## 在 Python 中更有效地循环的两种简单方法
使用枚举和压缩编写更好的 Python 循环
towardsdatascience.com](/two-simple-ways-to-loop-more-effectively-in-python-886526008a70) [## 4 个键盘快捷键,可高效编辑文本并提高工作效率
高效地在文本中导航和移动光标
medium.com](https://medium.com/better-programming/4-keyboard-shortcuts-to-edit-text-efficiently-and-improve-productivity-66894c8d51b8) [## 真实或虚假的关联:你约会的有魅力的人更令人讨厌
使用 Python 模拟数据、测试直觉并提高数据科学技能
towardsdatascience.com](/real-or-spurious-correlations-attractive-people-you-date-are-nastier-fa44a30a9452) [## 使用终端多路复用器 tmux 提高编码和开发效率
简单的 tmux 命令来提高您的生产力
medium.com](https://medium.com/better-programming/code-and-develop-more-productively-with-terminal-multiplexer-tmux-eeac8763d273)
更多帖子, 订阅我的邮件列表 。
利用熔体重塑宽到长的 R 数据帧——教程和可视化
你唯一需要的函数和教程
R 中的 melt()如何工作的总结
在 R 语言中,如何将一个数据帧从宽格式变成长格式?melt()
函数如何重塑 R 中的数据帧?本教程将引导您使用 r 中的melt
函数重塑数据帧。
如果你正在用 Python 重塑数据帧或数组,看看我下面的教程。
[## 使用 Python 中的 melt 重塑熊猫数据框—教程和可视化
想象一下 pd.melt 是如何将熊猫数据帧从宽到长进行整形的
towardsdatascience.com](/reshape-pandas-dataframe-with-melt-in-python-tutorial-and-visualization-29ec1450bb02) [## 用 Python 中的 pivot_table 重塑熊猫数据框—教程和可视化
使用 pd.pivot_table 将 long 转换为 wide
towardsdatascience.com](/reshape-pandas-dataframe-with-pivot-table-in-python-tutorial-and-visualization-2248c2012a31) [## 在 Python 中重塑 numpy 数组—一步一步的图形教程
本教程和备忘单提供了可视化效果,帮助您理解 numpy 如何重塑数组。
towardsdatascience.com](/reshaping-numpy-arrays-in-python-a-step-by-step-pictorial-tutorial-aed5f471cf0b)
为什么融而不融其他功能?
这种从宽到长的转换的常用术语是熔化、旋转、逆旋转、聚集、堆叠和整形。已经编写了许多函数来将数据从宽格式转换为长格式,来自data.table
库的melt()
是最好的。参见melt()
文档此处。为什么?
- Python 的 pandas 库也有类似的
melt
函数/方法,以同样的方式工作(参见我的 pandas melt 教程这里) - 独自一人通常足以完成你所有的从宽到长的转换;你不必学习
pivot_longer
或gather
- 像
gather
和pivot_longer
这样的其他函数通常只是melt()
或reshape()
的包装函数——这些其他函数简化了melt
,通常不能处理更复杂的转换。 melt
比其他函数更强大,但并不复杂。data.table
包对melt
的实现,非常强大——比重塑库的melt
功能高效强大得多。来自文档:
数据表的 melt 和 dcast 函数分别用于宽到长和长到宽的整形;这些实施是专门针对大内存数据(例如 10Gb)而设计的。
**提醒:**我们使用的是来自data.table
库的melt
,而不是reshape
库!将两个库中的melt
函数文档进行比较,找出差异:?data.table::melt
和?reshape::melt
宽与长数据帧
如果我们观察一个宽的数据帧并将其与一个长的数据帧进行比较,就很容易理解它是什么或看起来像什么。
下面是相应的数据帧(具有相同的信息),但是是以长的形式:
在我们开始我们的melt
教程之前,让我们重新创建上面的宽数据框架。
df_wide <- data.table(
student = c("Andy", "Bernie", "Cindey", "Deb"),
school = c("Z", "Y", "Z", "Y"),
english = c(10, 100, 1000, 10000), # eng grades
math = c(20, 200, 2000, 20000), # math grades
physics = c(30, 300, 3000, 30000) # physics grades
)df_wide
student school english math physics
1: Andy Z 10 20 30
2: Bernie Y 100 200 300
3: Cindey Z 1000 2000 3000
4: Deb Y 10000 20000 30000
注意,我喜欢用data.table
而不是data.frame
,因为data.table
对象更强大。如果您的数据不是 data.table(通过在您的控制台中运行class(your_dataframe)
来检查),我强烈建议您将其转换为data.table
。
class(df_wide) # data.table and data.frame
[1] "data.table" "data.frame"
只需加载data.table
库,并使用data.table
库中的setDT
函数将任何data.frame
转换为data.table
。
setDT(df_wide) # no reassignment required!
熔体实施例 1
我们通过id.vars
来指定标识符列。“剩余的”非标识符列(英语、数学、物理)将被融合或堆叠成一列。
将创建一个新的指示器列(包含英语、数学、物理值),我们可以通过variable.name
重命名这个新列(类)。我们也可以通过value.name
重命名包含所有实际成绩的列(gRaDe)。
df_long <- melt(data = df_wide,
id.vars = c("student", "school"),
variable.name = "cLaSs",
value.name = "gRaDe")
df_long
student school cLaSs gRaDe
1: Andy Z english 10
2: Bernie Y english 100
3: Cindey Z english 1000
4: Deb Y english 10000
5: Andy Z math 20
6: Bernie Y math 200
7: Cindey Z math 2000
8: Deb Y math 20000
9: Andy Z physics 30
10: Bernie Y physics 300
11: Cindey Z physics 3000
12: Deb Y physics 30000
熔体实施例 2
你可以用measure.vars
来指定你想把哪些列融掉或者堆到 column 里(这里我们排除了 physics 列,所以measure.vars = c("english", "math")
)。我们也放弃了id.vars
的学校专栏。
df_long <- melt(data = df_wide,
id.vars = "student",
measure.vars = c("english", "math"),
variable.name = "cLaSs",
value.name = "gRaDe")
df_long
student cLaSs gRaDe
1: Andy english 10
2: Bernie english 100
3: Cindey english 1000
4: Deb english 10000
5: Andy math 20
6: Bernie math 200
7: Cindey math 2000
8: Deb math 20000
从宽到长:原来的学校和物理专栏被删除
熔体实施例 3
最后,让我们看看如果我们只指定 student 列作为标识符列(id.vars = "student"
)而不指定要通过measure.vars
堆叠哪些列会发生什么。因此,所有非标识符列(学校、英语、数学、物理)将被堆叠到一列中。
产生的长数据帧看起来是错误的,因为现在 cLaSs 和 gRaDe 列包含了不应该在那里的值。这里的重点是向你展示melt
是如何工作的。
df_long <- melt(data = df_wide,
id.vars = "student",
variable.name = "cLaSs",
value.name = "gRaDe")
df_long
student cLaSs gRaDe
1: Andy school Z
2: Bernie school Y
3: Cindey school Z
4: Deb school Y
5: Andy english 10
6: Bernie english 100
7: Cindey english 1000
8: Deb english 10000
9: Andy math 20
10: Bernie math 200
11: Cindey math 2000
12: Deb math 20000
13: Andy physics 30
14: Bernie physics 300
15: Cindey physics 3000
16: Deb physics 30000
这个表看起来是错误的,因为df_wide
中的school
列不属于— school
应该是另一个标识符列(参见上面的 Melt 1)。melt 函数还返回了一条警告消息,告诉您您的列(gRaDe
)有不同类型的值(即字符型和数值型)。
宽到长:学校列不是标识符列
结束语
我希望现在您对melt
如何执行宽到长转换有了更好的理解。期待大家的想法和评论。
如果你觉得这篇文章有用,请关注我并访问我的网站获取更多数据科学教程和我的其他文章:
[## 用于统计测试的新 Python 库—比 statsmodels 更简单,比 scipy.stats 更丰富
统计建模变得更简单
towardsdatascience.com](/new-python-library-for-statistical-tests-simpler-than-statsmodels-richer-than-scipy-stats-ff380d4673c0) [## 连续 15 天使用 Vim 后,我学到了什么
从 Vim noob 到业余爱好者的旅程
towardsdatascience.com](/what-ive-learned-after-using-vim-15-days-straight-ceda7e773a6d)
更多帖子, 订阅我的邮件列表 。
用熊猫重塑数据
Python 数据字节
它是数据化的!— Python 剧本
嘿,各位#皮托尼斯塔!在这里,我与一个专栏分享一些用 Python 处理数据的超酷技术。作为参考,我会在每篇文章的结尾通过 Azure 笔记本分享完整的一步一步的代码。
所以事不宜迟,让我们深入研究 Pandas 库中可用的数据整形功能!
我们将在这篇文章中使用的数据源是样本超市数据集。大多数人可能已经熟悉它了,因为它是 Tableau 中提供的默认数据源。你也可以从我的 Azure 笔记本上下载。
数据集的形状
首先,你可能会想:我所说的数据集的形状到底是什么?
数据集排列成行和列的方式称为数据的 形状 。
首先,让我们使用 Python 将数据导入 Pandas 数据框。
从样本-超市 Excel 文件导入到 Pandas 的数据
检查完整的数据集是否已经成功地从我们的数据源导入到 Pandas 数据框中,这是一个很好的做法。这可以通过检查行数和列数(即数据框的形状属性)来完成。
熊猫数据帧的形状特征
因此,我们已经成功地将 9994 行和 21 列按照 excel 表导入到我们的 Pandas 数据框中。
数据形状——长数据还是宽数据?
垂直或长数据中的每一行代表属于特定类别/实例的一个观察值,因此更容易用于分析目的,因为它本质上是粒状的。因此,我们可以推断我们的数据是垂直或长的形状。
长数据中的观察值
每个列被认为是一个变量,具有多个不同的值,通过这些值,我们可以从我们的数据集中获得某些见解并准备报告。
长数据中的变量
为了理解水平或宽范围的数据,让我们开始分析各种变量的数据,并改变数据的形状。
透视表
让我们首先通过创建一个数据透视表来缩短我们的数据框架,以便只保留几列来进行进一步的分析。
我创建了一个列列表,并创建了另一个更小的数据框,我们可以在其上重塑我们的数据并做进一步的分析。这是一种方便的技术,可以让我们专注于需要进一步分析的列,并防止不必要的处理负载。
具有选定列的数据框架
**用例:**考虑一个用例,我们必须准备所有地区和部门的报告,汇总每个地区和部门的销售额、折扣、利润和数量。
我们可以像在 excel 中一样使用数据透视表来轻松地准备它。Pandas 库提供了一个 pivot_table()函数,该函数对现有的数据帧进行操作,并接受某些参数,通过这些参数进行聚合。我们来试试吧!
注意:默认情况下,数据透视表计算所有数值列的平均值。
数据透视表
这里我们有一个简洁的数据透视表,正如我们的用例所需要的。现在让我们检查它的形状。
嗯,真奇怪,为什么只显示 4 列,而我们可以看到 6 列?!这是因为我们选择了两列 Region 和 Segment 作为数据透视表的索引,现在我们有了一个多级索引。要重置索引,我们可以使用 reset_index()函数。
注意: inplace=True 意味着我们将更新数据框本身,而不仅仅是检查我们想要的转换的输出。因此,仅当您确定要根据正在进行的变换更新数据框本身时,才使用它。
重置索引后的数据透视表
现在我们有了一个数据集,它不再在每一行都有单独的观察值,而是不同变量的集合。这是适用于报告或演示目的的水平或宽数据形状。
用例:如果我想查看平均利润最高的地区和部门,该怎么办?
在这种情况下可以使用 sort_values() 函数。
注意:我已经使用了 reset_index()。对于排序后的值,它将从 0 到 11 重新开始索引值,因此我们可以清楚地识别平均利润的排名。由于我没有使用 *inplace=True,*这个变化不会影响实际的数据帧。
如果需要,我们还可以通过将它们单独或作为列表传递给 aggfunc 选项来执行其他数学聚合,如 sum 或 size(出现的频率)。让我们试一试。
aggfunc 参数的使用
我们现在可以看到,它产生了一个多索引数据帧,每个数字列都有平均值和总和的计算。**
融化
**用例:**现在,如果我们有数据透视表形式的数据,但我们想将它重新整形为长数据形状,以便我们可以在其中执行一些分析,该怎么办?
熊猫融化功能随时为您服务!
让我们将之前创建的数据透视表重塑为长数据形状,每行代表一个观察值。
在 Melt 函数中,我们传递一个列表作为标识符变量,即 id_vars ,所有其他列都被视为测量变量,列在变量和值列下。也可以根据需要传递变量和值的自定义列名。
熔化并向下流动
维奥拉。我们取消了数据透视,或者将数据融合到数据透视表中。
拆垛
让我们再次考虑我们已经创建的带有区域和分段多级索引的数据透视表。
**用例:**如果我想在列级别查看每个细分市场的每个指标,即折扣、销售额、利润和数量,该怎么办?
Unstack 通过将行值从最内部的索引级别(即段到列)放置来帮助我们实现这一点。让我们看看它的实际效果。
完美的叠放
这只是根据我们以更宽的格式呈现数据的要求来重塑数据的另一种方式。
堆栈
让我们再玩一会儿,使用 Unstack 的另一个自我,即堆栈功能!正如 Unstack 将最里面的索引行值移动到列中一样,stack 将最里面的列值移动到行中。让我们在未堆叠的数据框架上尝试一下。
背叠!
注意:堆叠和拆分仅适用于多级索引数据框。
枢轴
最后,我们将使用 Pivot 函数,这是另一个方便的工具,可以将我们的数据从长到宽。它能够处理非数字列,并且它基本上做的是无聚集的旋转。
在调用 pivot 之前,我们需要确保我们的数据没有包含指定列的重复值的行,即一个索引/列对。另一方面,数据透视表函数能够处理重复值,因为默认情况下数值是聚合的。
因为 Pivot 函数不能处理指定列的重复值,所以我将引用我们之前创建的 Pivot Table — pivot_table_df 来演示它的用法。
**用例:**考虑一个用例,我希望在报告中看到跨地区和部门的销售额,在另一个报告中看到跨地区和部门的利润。让我们使用 Pivot 函数从我们之前创建的数据透视表中导出它们。
在这里,我们有两个报告,在广泛的形状使用枢纽功能,如所愿!
要了解更多,这里是 Pandas 文档页面的官方链接,用于重塑数据函数。
[## 重塑和透视表- pandas 1.0.1 文档
数据通常以所谓的“堆栈”或“记录”格式存储:对于好奇的人来说,这是如何创建的:为了…
pandas.pydata.org](https://pandas.pydata.org/pandas-docs/stable/user_guide/reshaping.html)
链接到我的 Azure 笔记本:https://notebooks . Azure . com/pav neet-Singh/projects/shaping-data-with-python
暂时就这样吧!请随意发挥周围的功能和快乐的重塑,直到下次!
《入门级程序员成功的 3P 战略》作者 pav neet Singhhttps://towards data science . com/3p-Strategy-to-be-successful-for-entry-level-programmers-bbf 5 dbbcb 981
"让我们在画面中弹出这些过滤器!"作者帕夫尼特·辛格【https://link.medium.com/R4o2U6Fok4
帕夫尼特·辛格https://link.medium.com/zcBzu2Jok4
重塑熊猫的数据框架
用 python 重塑数据帧的终极指南
介绍
Pandas 无疑是 python 中使用最多的包之一。对于阅读本文的大多数人来说,这可能并不奇怪。许多人用熊猫来做不同种类的数据分析等等。但是,在某些情况下,我们可能希望以不同于最初提供的格式来重塑或可视化数据。这可能是由于各种原因。这可能是因为人们发现不同的表达方式更容易理解。这也可能是因为你想有一个特定的格式来运行你的代码。无论原因是什么,重塑数据框架可以被视为我们大多数人在作为数据科学家/分析师的旅程中所做的一项常见任务。本文将简要介绍一些有用的函数,这些函数可以用来重塑熊猫的数据帧。
作者图片
我喜欢认为重塑函数有两种类型。第一类功能简单的改造现有的数据框架。例如,它们将列更改为行,将行更改为列。第二种类型的功能将聚合信息并对其进行重组。在大多数真实情况下,我们会使用第二种类型的函数,因为它可以根据需要让我们看到更高级别的汇总或聚合。
类型 1:没有聚集的重整
理想情况下,没有聚合的重组可以而且应该应用于存在唯一选择组合的数据。否则,他们很可能会对某些函数抛出错误。
为了解释没有聚集的重整,我们将首先声明一个数据框架。声明和数据框架如下:
使用这个数据框架,我们可以看到一些对改造/整形有用的功能。
在枢轴上转动
Pivot 方法通常用于创建数据的透视样式视图,用户可以在其中指定行(在 python 中称为索引)和列。这两个参数将为视图提供一个结构,而要填充的信息将来自用于创建 pivot 的数据。也可以使用 values 参数有选择地填充信息。现在让我们看一些例子来更好地理解它。
df.pivot(index='Date', columns='Class', values='Numbers')
作者图片
正如我们从上面所看到的,一旦指定了索引、列、值,就形成了新的透视样式数据帧的结构,并相应地填充了索引、列对的组合所特有的信息。
请记住,建议始终填充索引和列参数,因为这将决定最终数据帧/视图的结构。让我们看看如果不声明 values 参数会发生什么。
df.pivot(index='Date', columns='Class')
作者图片
如果我们不指定 values 参数,pandas 将创建所有各种可能的视图,同时将所有列名与上面指定的索引和列分开。因此,对于具有多个列的大型数据集,建议也指定 value 参数。
然而,使用上面的代码并稍微调整一下,还有另一种方法来提取关于一列的信息。这将是如下。
df.pivot(index='Date', columns='Class')['Numbers']
作者图片
如果我们提到上面给出的列名,而没有指定 values 参数,那么结果输出将是相同的。这样做的唯一缺点是需要更长的时间来执行。需要注意的是,列名声明类似于数据帧子集的语法。这是因为我们确实正在这样做。使用上面的代码,pandas 首先获得所有列的结果,然后使用括号中指定的列名,pandas 对数据帧进行子集化并显示出来。这也是为什么这个方法的执行时间比我们使用 values 参数的方法要长。
注意:使用 pivot 函数时,如果行*列的组合有多个条目,该函数将抛出一个错误,因为 pivot 不会进行任何类型的聚合。
熔化
Melt 是一个用于将列转换为行的函数。这意味着当用户希望将一列或多列信息放入行中时,这个函数非常有用。该函数将通过删除除 id_vars 参数中提到的列之外的所有其他列来创建两个新列,并在一列中显示列名,在另一列中显示其值。让我们看一个例子来更好地理解它。
df.melt(id_vars=['Date','Class'])
作者图片
在数据帧 df 中,我们有四列,其中在 id_vars 参数中提到了日期和类别。这将给我们留下列号和列号 2。正如我们在上面看到的,该函数创建了两个名为 variable 和 value 的新列,并用列名和 Date+class+列名组合的唯一值填充它们,同时删除列号和 Numbers2。
如果只有特定的列要以这种方式转换,而不是所有的列,那么参数 value_vars 将帮助我们实现这一点。
df.melt(id_vars=['Date','Class'], value_vars=['Numbers'])
作者图片
正如我们所看到的,当 value_vars 参数中提到特定的列名时,只有该列的信息会根据需要进行融合。还有两个额外的参数 value_name 和 var_name,它们将通过参数中提到的字符串来重命名列 value 和 variable。让我们看一个例子来更好地理解这一点。
df.melt(id_vars=['Date','Class'], value_vars=['Numbers'], value_name="Numbers_Value", var_name="Num_Var")
作者图片
正如我们所看到的,列被重命名为参数中指定的列。
堆叠和取消堆叠
Stack 和 Unstack 分别执行列到行和行到列的操作。这两个功能肯定是熊猫整形中较少使用的功能之一,因为人们会使用 pivot 来实现他们大多数时间想要的结果,因此不需要它。我们仍将研究它们,以了解它们是如何工作的,因为它们在一些特定的场景中可能是有用的。
stack 和 melt 之间的主要区别是 stack 需要将 id_vars 设置为 index,而不是必须单独将它们作为参数传递。让我们看一下 stack 来理解它做什么。
df.set_index(["Date","Class"]).stack()
作者图片
正如我们所观察到的,它具有与 melt 相同的功能,将列转换为行。
另一方面,拆分与堆叠正好相反。它将行带到列,像堆栈一样,它需要索引才能按预期运行。
df.set_index(["Date","Class"]).stack().unstack()
作者图片
正如我们所看到的,如果没有输入,unstack 基本上会撤消堆叠操作。当更改拆分括号内的数字输入时,输出会有所不同。如果你对这个话题感兴趣,这将是一个很好的话题。
类型 2:通过聚合进行改革
与类型 1 函数不同,类型 2 函数提供了信息的汇总视图。如果用户想要对数据进行某种类型的汇总,这将非常有用。我们将使用用于类型 1 函数的相同数据框架来研究类型 2 函数。
为了解释没有聚集的重整,我们将首先声明一个数据框架。声明和数据框架如下:
使用这个数据框架,我们可以看到一些对改造/整形有用的功能。
分组依据
Group by 是我使用最频繁的函数,超过了本文中提到的任何其他函数。这是因为,它使用起来非常直观,并且具有非常有用的参数,可以帮助用户查看不同列的不同聚合。让我们通过语句来研究一个简单的组。
df.groupby('Date')["Numbers"].mean()
作者图片
在 group by 语句中,我们在第一个括号内指定需要对数据进行分组的一列或多列。这里,我们既可以给出一个单独的字符串,也可以给出与列名相关的字符串列表。下一个括号是指定要聚合的数据,最后我们调用聚合应该使用的方法。在上面的例子中,我们使用平均聚合来聚合日期的列数。
请注意,输出不是数据帧,而是看起来类似于熊猫系列。要将其转换为 dataframe,我们可以使用 reset_index 方法,或者也可以使用 group by 语句中可用的参数。我将使用后者。
df.groupby('Date', as_index=False)["Numbers"].mean()
作者图片
如上图所示,as_index 参数可用于将 group by 的结果转换为 dataframe。
让我们再看一个例子,在这个例子中,我们使用一种方法对多个列进行聚合。
df.groupby(['Date','Class'], as_index=False)["Numbers"].mean()
作者图片
正如我们在上面看到的,我们可以使用一个字符串列表(列名)在多个列上聚合多个列,而不是指定一个字符串(列名)。但是,我们也可以对不同的列使用不同的聚合函数。让我们看一下下面的例子,以了解如何做到这一点。
df.groupby(['Date'], as_index=False).aggregate({"Numbers":"sum", "Numbers2":"mean"})
作者图片
在上图中,我们用 sum 函数聚合日期列上的数字列,同样,我们用 mean 函数聚合日期列上的数字 2 列。
数据透视表
数据透视表的功能与透视表相同。然而,pivot table 有一个额外的重要参数,它指定了我们将用来聚合数据的聚合函数。让我们看下面的例子来更好地理解它。
让我们从一个简单的数据透视表开始。
df.pivot_table(index="Date", columns="Class")
作者图片
注意,pivot table 的方法调用是 pivot_table,它不同于 pivot 的 pivot。如果未指定聚合函数,将使用默认函数 mean 来聚合信息。
df.pivot_table(index="Date", columns="Class", aggfunc="sum")
作者图片
但是,如果用户想要指定一个特定的函数,他们可以在参数 aggfunc 中这样做,如上图所示。
交叉表
本文中的最后一个函数是交叉表。默认情况下,该函数会给出两个不同列的值之间出现的次数或频率。让我们看一个例子。
pd.crosstab(df.Date, df.Class)
作者图片
上面的视图意味着在 1A 班级和 2019-02-02 日期的组合中有两个不同的条目可用。类似地,其他信息也可以被解释。
在代替出现频率的情况下,如果用户希望有一些其他的聚合函数,可以使用 aggfunc 参数。
pd.crosstab(df.Date, df.Class, values=df.Numbers, aggfunc='sum')
作者图片
pd.crosstab(df.Date, df.Class, values=df.Numbers, aggfunc='mean')
作者图片
上面的图片给人一种如何使用它的感觉。即使输出看起来与数据透视表相似,但实现的方式是不同的。但是人们更喜欢使用数据透视表而不是交叉表函数。
结论
我们已经在本文中看到了多个函数,并理解了各种参数及其用法。
总之,每个人都知道实践使人完美。这句话也适用于技术领域,对吗?为了让你更容易实践我们在本文中讨论的多个概念,我创建了一个 Jupiter 笔记本,你可以在这里下载。练习的好时光!!!
如果有任何疑问、建设性的批评和任何反馈,请随时联系我这里的。
重塑熊猫数据框架
熔化、堆叠和旋转功能
Pandas 是一个非常强大的 Python 数据分析库,可以加速项目的预处理步骤。Pandas 的核心数据结构是 DataFrame ,它以表格的形式表示数据,带有标记的行和列。在这篇文章中,我将尝试解释如何通过修改行列结构来重塑数据帧。
由保罗·斯科鲁普斯卡斯在 Unsplash 上拍摄
有多种方法可以重塑数据帧。我们可以选择最适合手头任务的一个。重塑数据帧的函数:
- 融化
- 堆叠和拆分
- 枢轴
一如既往,我们从进口熊猫开始:
import pandas as pd
import numpy as np
融化
Melt 用于将宽数据帧转换为窄数据帧。我所说的宽是指具有大量列的数据帧。一些数据帧的结构是连续的测量值或变量用列来表示。在某些情况下,将这些列表示为行可能更适合我们的任务。
考虑以下数据帧:
df1 = pd.DataFrame({'city':['A','B','C'],
'day1':[22,25,28],
'day2':[10,14,13],
'day3':[25,22,26],
'day4':[18,15,17],
'day5':[12,14,18]})
我们有三个不同的城市,在不同的日子进行测量。我们决定用一列中的行来表示这些日子。还会有一列显示测量结果。我们可以通过使用熔化功能轻松实现这一点:
df1.melt(id_vars=['city'])
默认情况下,变量和值列的名称是给定的。我们可以使用 melt 函数的参数 var_name 和 value_name 来指定新的列名。如果我们按城市列对数据进行排序,效果会更好:
df1.melt(id_vars=['city'], var_name = 'date', value_name = 'temperature').sort_values(by='city').reset_index(drop=True)
堆叠和拆分
堆栈函数增加了数据帧的索引级别。我所说的提高水平是指:
- 如果 dataframe 有一个简单的列索引,stack 返回一个系列,其索引由原始 dataframe 的行列对组成。
- 如果数据帧有多级索引,stack 增加索引级别。
用例子解释更好。考虑以下数据帧:
df1 有 3 行 6 列,具有简单的整数列索引。如果将 stack 函数应用于 df1,它将返回 3 x 6 = 18 行的序列。序列的索引将是[(0,'城市'),(0,'第 1 天'),…,(2,'第 5 天')]。
让我们也检查一下形状和指数:
df1.shape
(3,6)df1.stack().shape
(18,)df1.stack().index[0] #multilevel index
(0, 'city')
栈和非栈功能更常用于具有多级索引的数据帧。让我们创建一个具有多级索引的数据框架:
tuples = [('A',1),('A',2),('A',3),('B',1),('A',2)]index = pd.MultiIndex.from_tuples(tuples, names=['first','second'])df2 = pd.DataFrame(np.random.randint(10, size=(5,2)),
index=index, columns=['column_x', 'column_y'])
如果我们对该数据帧应用堆栈功能,索引级别将会增加:
df_stacked = df2.stack().to_frame()
df_stacked
现在,列名(column_x 和 column_y)是多级索引的一部分。因此得到的数据帧有一列和一个 3 级多索引。
len(df_stacked.index.levels)
3len(df2.index.levels)
2
拆垛与垛正好相反。如果我们对堆叠的数据帧应用拆分,我们将得到原始的数据帧:
df_stacked.unstack().index
MultiIndex(levels=[['A', 'B'], [1, 2, 3]],
codes=[[0, 0, 0, 1, 1], [0, 1, 2, 0, 1]],
names=['first', 'second'])df2.index
MultiIndex(levels=[['A', 'B'], [1, 2, 3]],
codes=[[0, 0, 0, 1, 1], [0, 1, 2, 0, 1]],
names=['first', 'second'])
支点
Pivot 函数也可以被认为是从不同的角度看待数据帧的一种方式。它通过允许以不同的格式表示数据来探索变量之间的关系。
考虑以下数据帧:
我们想看看城市名对的值是如何变化的。我们可以用城市名称和列的索引来创建这个数据帧的新表示。
如果城市名对不存在,则用 NaN 填充相应的单元格。
我们不必一次看到所有的值。可使用值参数过滤数据框中的值:
我认为熊猫的成功和流行来自于其多功能、强大且易于使用的操作和分析数据的功能。和熊猫一起完成一项任务几乎总是有多种方式。由于花在数据科学项目上的大部分时间都花在数据清理和预处理步骤上,所以非常鼓励学习 Pandas。
感谢阅读。如果您有任何反馈,请告诉我。
ResNet:计算机视觉时代最流行的网络
计算机视觉工作者的必备知识
使用计算机算法对图像进行分类似乎很有挑战性。令人惊讶的是,最近在计算机视觉领域的一项研究取得了成功,在名为 ImageNet 的数据集上出现了 1.3%的前 5 名错误。2020 年,最先进的图像分类技术变成了由谷歌研究团队发布的 EfficientNet。然而,在很长一段时间内,名为 ResNet 的网络在图像分类领域表现出色。此外,许多研究人员使用 ResNet 作为他们的网络主干,以提高他们的性能。这篇文章将帮助你直观地理解什么是 ResNet 以及它是如何被激发的。
链接:https://papers with code . com/sota/image-class ification-on-imagenet
退化问题
深度神经网络在学习过程中遇到许多困难。计算机视觉研究人员提出了它们的解决方案,例如用批量标准化解决消失/爆炸梯度问题。(【https://arxiv.org/pdf/1502.03167.pdf】T4)ResNet 论文介绍了一个具有挑战性的问题,名为“退化问题”在阅读之前,我们先思考一下下面的问题。
层数越多,准确度越高?
在网络上添加图层会扩大输出的多样性,这似乎很直观。如果每个添加的图层都是身份映射,则新网络可以输出与原始网络相同的值。因此,训练有素的网络层数越多,分类精度越高,这是有说服力的。不幸的是,事实并非如此。
当您使用普通网络(在 ResNet 之前)估计精度时,随着模型复杂性的增加,其精度会迅速下降。这个问题是一个退化问题。这不是一个过度拟合的问题;然而,随着模型复杂性的增加,网络的性能下降。作者声称平面网络不适合近似身份映射;因此,添加层并不保证添加层的网络能够表达添加层之前网络的所有值。ResNet 的动机是建立一个适合身份映射的网络。
快捷连接
为了使身份映射适用于网络,作者使用了一个名为的快捷连接的方法。这种方法的主要直觉是与其学习函数 F(x),不如学习函数 F(x) + x .学习一个恒等式映射更容易;由于层权重都调整为 0,它将产生一个身份映射,而不是零映射。此外,它是可区分的,因此端到端是可训练的。
快捷连接的另一个考虑是在恒等式中增加投影。由于快捷方式连接的层之间的尺寸可以不同,因此有三个考虑因素。a)在增加的尺寸上补零,B)投影快捷方式仅用于尺寸改变的部分,C)所有快捷方式都是投影。下表是对每种情况的估计。(ResNet-34 后面的 A、B 和 C 表示在 ResNet-34 中应用的 A)、B)和 C)
关注第二行框
结果显示在身份上进行投射并不会严重影响绩效。改变参数的数量使得与普通网络的比较更加困难。因此,作者简单地在网络中使用了身份映射。
整体主干
要参考网络的详细结构,请参考论文。
链接:【https://arxiv.org/pdf/1512.03385.pdf
实验
他们比较了两个网络:普通网络和 ResNet。两个网络使用相同的层;然而,只有 ResNet 具有快捷连接。他们在两个数据集上进行了实验:ImageNet 和 CIFAR-10。下面的图表是实验的结果。
(细曲线表示训练错误,粗曲线表示验证错误)
ImageNet 上平面网络的性能
从图中可以看出,训练误差随着层数的增加而增加。这意味着普通网络正遭受退化问题。ResNet 怎么样?
ResNet 在 ImageNet 上的性能
不再有退化问题 。随着层数的增加,它们的训练误差减小。
ImageNet 上的实验结果
作者在 ResNet 中添加了更多层,以制作更复杂的模型。正如所料,增加层数可以提高性能。当在 CIFAR-10 上进行实验时,这种趋势是相似的。
CIFAR-10 的实验结果
但是,我们可以观察到,在网络上使用 1202 层,性能会显著下降。论文认为这是由于过度拟合造成的。即使性能有显著下降,它仍然优于原始方法。
结论
ResNet 的动机是解决退化问题。通过直观的方法,他们设计了适合身份映射近似的网络。实验表明, **ResNet 很好地解决了退化问题,**然而,它对于极深的网络工作不佳。
我很感激对我的文章的任何反馈,对于任何讨论,欢迎你给我发电子邮件。如果有什么不对或者误解的地方,请告诉我。:)
联系我:jeongyw12382@postech.ac.kr
进一步阅读
D2 匹配解释:
用冯·米塞斯的随机性公理解决圣彼得堡悖论
在这篇文章中,我们将提出一个全新的观点来解决博弈论中一个最重要的悖论。所用的方法源于对非遍历系统的研究。这种情况可能会造成结果之间的依赖性,而这种依赖性通常极难检测和量化,例如在金融领域。因此,从可能相关的数据中获得的预期增益具有难以确定的统计值,因此不能用于决策目的。因此,在这种情况下,必须找到在决策过程中使用的替代参数。解决方案开发通过利用关于系统的有用信息,将焦点从结果转移到以认知方式操作的策略能力。为了从数学的角度确定一个策略是否是认知的,我们使用冯米塞斯的随机性公理。基于这个公理,有用信息的知识因此产生不能随机复制的结果。在这种情况下,有用的信息可以被看作是接收者当前或未来决策过程的重要数据。总之,这个悖论中的无限行为可以被看作是一个能够使预期收益不能用于决策目的的因素。结果,我们被迫用不同的观点来面对这个问题。为了做到这一点,我们通过利用关于系统的有用信息,将焦点从结果转移到策略以认知方式操作的能力。最后,通过从这个新的角度来解决这个悖论,我们将证明一个趋向于无穷大的预期收益并不总是认知和非随机策略的结果。因此,这个结果引导我们定义了决策中的价值等级,其中认知方面,其统计结果是与随机行为的背离,被证明比预期收益更重要。
介绍
圣彼得堡悖论是博弈论中最重要的悖论之一。用于求解的经典解决方案使用实现边际效用概念的特殊效用函数1、[2]、3。这种方法受到了强烈的批评,因为效用函数试图从数学的角度将社会学行为形式化,这就是为什么效用函数总是带有主观性的原因。此外,许多行为经济学研究[4],[5]强调了人们的行为通常是非理性的。因此,解决这一矛盾仍然是一个公开的挑战,正如我们将看到的,寻找替代解决方案可能有助于我们改善战略评估期间的决策过程。
为了理解本文提出的解决圣彼得堡悖论的方法,我们必须首先解释这个方法的起源。开发这种方法是为了研究在非遍历系统上运行的策略。特别是,主要应用领域的特点是研究金融市场上的定量交易算法。非遍历条件可以使结果相互依赖。因此,在这种情况下,数据之间会产生依赖性,就像在金融领域一样,难以检测和量化。
为了向你解释这种情况在决策层面上可能产生的后果,我提出下面的例子:想想对一枚硬币的一百次投掷下一百次赌注,赢了一百次。在这种情况下,你将获得一百个彼此独立的胜利,这些胜利将与一个非常高的预期收益相关联。因此,你会得出正确的结论,即用来预测抛硬币的策略很可能是正确的。现在让我们改变开始的场景,假设我们在一次掷硬币中下 100 次相等的赌注,获得 100 次胜利。显然,由于赌注完全相互依赖,在这种情况下,它们不能用于计算预期收益。事实上,这基本上就像我们做了一个单一的赌注。现在让我们想象一下,作为第三个也是最后一个场景,你看不到抛硬币的人:如果我们赢了所有的 100 次,我们不知道他们是相互依赖还是相互独立。第三种情况产生了一个非常重要的决策问题,因为如果我认为结果是独立的,而它们不是,我就有高估策略的风险。这种错误的评估会导致我做出使用无用策略的非理性选择。在金融学中,结果的非独立性产生了一种叫做聚类的统计现象。这种统计特征决定了高收益组与低收益组的交替形成。换句话说,这意味着回报不是均匀分布的,而是趋向于聚集在一起。聚集现象在金融领域有着灾难性的影响,因为当你经历成功阶段时,你会被引导去考虑那些彼此独立的操作。这意味着从我们错误地认为是独立的数据中计算出来的预期收益被高估了,因此对策略的评估也将是不正确的。因此,这种行为会让我们面临意想不到的风险。关于这个话题,我们提出了一个悖论,我们称之为“职业交易者悖论”。这个名字来源于这样一个事实,即我们倾向于认为我们的操作总是独立的,因此当我们面对一系列赢的赌注时,我们倾向于高估所使用的策略。
总之,从可能不独立的数据中获得的预期增益不能用于决策目的,因为它具有难以确定的统计值。因此,从这个例子中我们了解到,在某些情况下,比如在非遍历系统中,预期增益不再是可靠的参数。因此,我们可以认为,其他情况可能存在,如在这种悖论的无限行为的情况下,预期收益是一个不能用于决策的数据。
我们开始理解,解决圣彼得堡悖论的问题可能源于考虑预期收益及其变体(效用函数),作为评估战略的唯一可能的观点。所以,我们要问自己的问题是:有没有一个参数比预期增益更好?
我们对这个问题的回答是,从统计学的角度来看,如果一个策略通过利用系统中有用的信息以一种认知的方式运作,我们就能够理解。在这种情况下,有用的信息可以被看作是经过分析的数据,使其对接收者现在或将来的决策过程具有重要意义。为了从数学上确定一个策略是否是认知的,在刚才描述的意义上,我们利用了冯米塞斯的随机性公理。公理定义了必须有一个序列才能被认为是随机的统计特征。公理如下:“将一个序列定义为随机序列的基本要求在于,完全没有任何规则可以成功地应用于改进对下一个数的预测”。
这个公理的含义如下:当我们理解一个数字序列服从的一组规则时,我们可以获得结果,作为对序列的下一个数字的预测,随着预测次数的增加,随机再现的概率趋于零。
因此,用一种游戏策略获得的结果,实现了对提高我们获胜概率有用的信息,产生了不能随机再现的结果。基本上,与使用有用信息的认知策略相比,使用随机策略获得更好结果的概率随着预测次数的增加而趋于零。
这个公理实际上是一种统计方法,用于评估所获得的结果,而不考虑预期增益的绝对值。事实上,这种方法仅仅基于这样一个事实,即能够区分结果是通过随机策略获得的,还是通过执行系统服从的一组规则的认知策略获得的。
通过这种方式,我们在分析一类特殊的零和博弈的策略时获得了一个基本结果,在这类博弈中,参与者之间存在一种平衡。平衡意味着没有一个玩家相对于其他玩家有明显的优势。著名数学家丹尼尔·伯努利将这类特殊的游戏定义为:“数学上公平的机会游戏”。
这类博弈在博弈论中起着特别重要的作用,因为它代表了金融等各种利益领域中非常频繁的情况。
如果我们分析通过大量重复圣彼得堡悖论中描述的机会游戏所获得的结果,在下一段中,我们将证明通过使用随机策略,可以以接近 50%的概率获得更好的利润。在实践中,一个纯随机博弈策略的结果往往相对于从悖论中描述的策略中得出的预期理论收益对称分布。这一结果表明,每次输钱后的双倍下注策略没有利用任何有用的信息,因此它是一种完全非认知的游戏方法。因此,通过将认知方面作为一个用于决策的参数,并证明了在策略中的完全缺失,我们能够通过证明博弈方法的不合理性来解决悖论。
在本文中,我们想介绍认知方面,即通过利用关于系统的有用信息以非随机方式行动的意义,作为改进决策理论的基本要素。事实上,这个悖论有助于让我们理解,关于系统的有用信息的知识,能够增加我们的胜利概率,总是涉及预期收益的增加。然而,反之则不成立:一个趋于无穷大的预期收益并不意味着策略利用了关于系统的知识,因此是认知的而不是随机的。因此,就产生了一个价值层次,在这个层次上,对于决策来说,认知方面比预期收益更重要。
圣彼得堡悖论的解决
在这一段中,我们将通过证明每次输掉赌注后的双倍下注策略是一种非认知策略来解决圣彼得堡悖论,这种策略没有实施任何可用于提高成功概率的有用信息。
为了做到这一点,我们必须定义随机策略,我们将使用它来计算获得比悖论中定义的赌博方法更好结果的概率。事实上,如前一段所述,如果被评估的策略是实现有用信息的认知策略,这种概率应该趋于零。首先,我们定义一些参数,这些参数是表征我们的随机参考策略的基础。
我们需要的第一个参数是每次赌输后使用双倍下注策略得到的博弈的期望值 EV。假设掷骰次数等于 L,赢的概率为 50%,第一次下注的价值等于 1,我们有:
第二个参数是平均赌注 AB。通过进行价值为 Bn 的 L 次下注,我们得到:
已知第一次下注 B1 等于 1,并且在每次下注失败后加倍下注,并且当我们赢得下注时返回到值 1,我们有:
此时,随机游戏策略将被定义如下:给定等于 L 的翻转次数,将进行 AB 常数值的 L 次下注,随机选择每次下注是正面还是反面。要计算这种类型的策略与悖论的策略的期望值 EV 相比是否能获得更好的结果,只需使用二项式分布公式。
P =获胜的概率
K =获胜次数
L =投掷次数
通过使用二项式分布公式,给定 L 值,我们可以获得使用上述随机策略获得更好结果的概率。范围从 10 到 200 的 L 值的结果如图 1 所示。看这个图,我们看到概率是如何渐近地趋向于 50%的。因此,我们有 50%的机会得到更好或更坏的结果。基本上,悖论中描述的策略逐渐趋向于随机策略。因此,双倍下注策略结果证明是一种不执行有用信息来提高我们获胜可能性的策略。因此,使用认知方面作为评估方法已经证明了该策略的不合理性。
我们使用非常相似的方法,将被评估的策略与金融领域中的等效随机策略进行比较,以分析交易策略产生的结果[7],8。
图 1:给定范围从 10 到 200 的 L 次投掷次数,用随机策略获得更好结果的概率。
结论
在本文中,我们使用圣彼得堡悖论来引入一个与战略的认知方面相关的参数,作为一个基本元素来帮助我们在预期收益被证明是一个不可靠参数的所有情况下做出决策。这种方法是通过研究非遍历系统开发的。在这种情况下,结果可能是非独立的,因此预期增益变成了具有难以确定的统计值的参数。因此,它不能用于决策,需要找到一个新的参数。选择的参数与策略以认知方式运行的能力相关(认知术语表示策略通过利用关于系统的有用信息以非随机方式运行的能力,能够使我们增加胜利的概率)。
为了从数学上确定一个策略是否是认知的,我们使用了冯·米塞斯的随机性公理。基于这个公理,实现关于系统的有用信息的策略产生不能随机再现的结果。因此,我们从总下注价值的角度比较了悖论策略和完全随机但等价的策略。从这个比较中,我们证明了随机策略得到更好的结果,随着投掷次数的增加,概率趋向于 50%。基本上,这个策略倾向于收敛到一个随机策略,而不是像我们从认知策略中预期的那样发散。事实上,如果一个策略在系统上实现了有用的信息,随机地
获得更好的结果趋向于零。这一结果表明,每次输掉赌注后的双倍下注策略不是利用关于系统的有用信息的认知策略,因此,通过将认知方面作为评估参数,我们已经解决了悖论。
总之,圣彼得堡悖论告诉我们,趋于无穷大的预期收益并不总是意味着认知和非随机策略的存在。因此,知识,意味着利用有用的信息,能够使我们增加胜利的概率,总是意味着预期收益的增加,但反之则不然;在缺乏系统知识的情况下,也可以获得趋于无穷大的期望增益。因此,从决策方面来看,我们可以创建一个价值等级,其中知识比预期收益更重要。事实上,在非遍历系统的情况下,胜利的期望可能难以估计,或者如果所开发的策略具有高度的过度拟合,则胜利的期望可能是无用的数据。在所有这些情况下,随机获得相同结果的概率的计算成为更可靠的参数,因为该数据仅受我们对系统的真实了解的影响,而不受噪声的影响。事实上,一个统计数据并不代表一个有用的信息,只有当它有可能证明它不是以随机的方式获得时,它才成为一个有用的信息。实际上,随机获得相同结果的概率必须非常低,才能认为该结果是有用的。
参考
1保罗·萨缪尔森,(1977 年 3 月)。《圣彼得堡悖论:被切割、剖析和历史描述》。经济文献杂志。美国经济协会。15 (1): 24–55.JSTOR 2722712。
[2]罗伯特·J·奥曼(1977 年 4 月)。“圣彼得堡悖论:对最近一些评论的讨论”。经济理论杂志。14 (2): 443–445.doi:10.1016/0022–0531(77)90143–0。
3罗伯特·马丁(2004 年)。“圣彼得堡悖论”。在爱德华·n·扎尔塔。斯坦福哲学百科全书(2004 年秋季版。).加州斯坦福:斯坦福大学。ISSN 1095–5054。检索于 2006 年 5 月 30 日。
[4]丹尼尔·卡内曼和阿莫斯·特沃斯基(1979)“前景理论:风险下的决策分析”,计量经济学,47(2),263–291。
[5] Hersh Shefrin,(2002)“超越贪婪和恐惧:理解行为金融学和投资心理学”。牛津大学出版社。
6安德烈·贝尔东迪尼,《职业交易者的悖论》,(2018 年 11 月 20 日)。在 https://ssrn.com/abstract=3287968.的 SSRN 有售:
[7] Andrea Berdondini,“冯·米塞斯的随机性公理在关于由数字序列描述的非平稳系统的动力学的预测上的应用”(2019 年 1 月 21 日)。可在 https://ssrn.com/abstract=3319864[或 http://dx.doi.org/10.2139/ssrn.3319864.](https://ssrn.com/abstract=3319864)[的](http://dx.doi.org/10.2139/ssrn.3319864.)SSRN 买到
8 Andrea Berdondini,“来自经济物理学的方法论描述作为财务战略的验证技术”,(2017 年 5 月 1 日)。在 https://ssrn.com/abstract=3184781\. SSRN 有售:
我希望在开始从事数据科学时就知道的资源
蒂姆·莫斯霍尔德在 Unsplash 上的照片
面向严肃数据科学家的强大学习指南
数据科学可能会让人不知所措。有很多人会告诉你,为了成为一名数据科学家,你必须学习繁重的数学和计算机科学——统计学、微积分、线性代数、分布式计算、聚类等等。
很容易感觉自己像一只被车灯困住的羚羊——不知道从哪里开始。
我理解你的感受——不久前我也处于你的处境。
这篇文章是献给我作为数据科学初学者所希望拥有的资源的。我希望在这篇文章中分享我的经验将使你走上追求数据科学职业的正确道路,并使你的学习之旅更加愉快。
如果你想开始深度学习,这里有一个 1.5 小时的免费速成课程:
数据科学适合你吗?
照片由 Isaac Smith 在 Unsplash 上拍摄
在你前进之前,你需要分析数据科学是否适合你。数据科学很性感——薪水很高,随之而来的是巨大的声望。
问问你自己:这是你转向数据科学的原因吗?
如果是,马上转回来!数据科学不适合你。
数据科学的问题是,即使你对它充满热情,你也不能强迫自己热爱这个过程。如果你不喜欢数据科学带来的感觉,那么从长远来看,你很难保持动力。
我给你的建议是:做你的研究
在你下定决心之前,研究,研究,研究!
观看视频,阅读关于数据科学家日常生活的文章。
数据科学家的一天 —霍马理工大学
数据科学:现实与期望 —马特·特兰
开始的时候,做一点调查,会对你做出正确的选择大有帮助。
PS:这是玛丽维尔大学的一份方便的数据科学职业指南,你可以用它来衡量你的兴趣!
强大的学习途径
如果你正在读这篇文章,你可能已经决定继续从事数据科学。恭喜你!
学习数据科学是巨大的。吃大象的唯一方法是一次咬一口。
这与任何其他具有挑战性的任务没有太大的不同。取决于你从哪里开始,你可能需要吃更多的东西,但是这并没有什么魔力;没有捷径。只是一次吃一口。
下面的学习路径包括两个主要部分——数学和技能。从数学开始是个好主意,这样你就可以判断数据科学是否适合你。对于一些人来说,数学可能令人望而生畏,因为数据科学主要使用许多数学概念。一开始就认识到这一点,可以避免你以后后悔。
总而言之,
从数学开始
第一部分:数学
3 数据科学中最重要的主题是线性代数、微积分和统计学。但是对于大多数任务,您可以只使用统计数据。即便如此,我还是在这三个概念下链接了有用的资源,如果你想了解更多的话。
线性代数
线性代数在数据科学中(几乎)无处不在。在大多数计算中,你的计算机会用到大量的线性代数。在神经网络中,网络的表示和处理使用线性代数。很难想象有哪个模型不是用这个数学分支实现的。
但是这看起来很重要,在大多数情况下,你不会在你的数据集中应用矩阵变换的手写代码。你真正需要的是对其核心原则的良好直觉。
如果您看到此消息,这意味着我们在网站上加载外部资源时遇到了问题。如果你是…
www.khanacademy.org](https://www.khanacademy.org/math/linear-algebra)
如果你想学习线性代数的理论并在代码中应用这些理论,请使用下面的资源:
线性代数也许是计算科学中最重要的数学分支,包括机器…
www.udemy.com](https://www.udemy.com/course/linear-algebra-theory-and-implementation/)
结石
像线性代数一样,微积分也在数据科学中发挥着重要作用,特别是在机器学习中使用的算法。同样,和前者一样,你不需要成为微积分大师才能掌握数据科学。你需要的是理解它的核心原则,以及这些原则如何影响你的模型。
从国家研究型大学高等经济学院学习机器学习线性代数的第一步…
www.coursera.org](https://www.coursera.org/learn/first-steps-in-linear-algebra-for-machine-learning)
统计与概率
统计和概率是一个**你真的不得不学习的话题。**这将占用你大量的时间,但好消息是这些概念并没有那么难,所以你没有理由不掌握这个主题。
如果您看到此消息,这意味着我们在网站上加载外部资源时遇到了问题。如果你是…
www.khanacademy.org](https://www.khanacademy.org/math/statistics-probability)
数学中的其他主题
作为一名初学数据的科学家,你可能不会在日常生活中用到这些话题,但如果你想提高自己的水平,它们会特别有用。
- 图论
“图论是对关系的研究。给定一组节点——可以用来抽象从城市到计算机数据的任何东西——图论以非常深入的方式研究它们之间的关系,并为许多安排、联网、优化、匹配和操作问题提供答案。它的力量在于能够用来抽象出如此大量的实际问题。”— 弗兰克·汉纳里
如果您希望为物流公司建立优化路线的模型,或者建立欺诈检测系统,基于图的方法有时会优于其他解决方案。
我们邀请你进入图论的迷人旅程-一个连接绘画的优雅和…
www.coursera.org](https://www.coursera.org/learn/graphs)
2。离散数学
离散数学是数学的一个分支,它研究的对象只能具有不同的、分离的值。离散对象通常可以用整数来描述,而连续对象则需要实数。
一旦你开始在机器上使用数学,你就进入了离散数学的世界,在这个世界里,每个数字只能用有限的“比特”来表示。
[## 什么是离散数学?
连续数学与离散数学数学世界可以大致分为两个领域:连续数学和离散数学
cse.buffalo.edu](https://cse.buffalo.edu/~rapaport/191/S09/whatisdiscmath.html) [## 计算机科学离散数学导论| Coursera
为你的 IT 职业打下基础。掌握驱动我们生活的数学,为你的软件工程师或…
www.coursera.org](https://www.coursera.org/specializations/discrete-mathematics)
如果你害怕数学,无视数学方程,你就不会有作为数据科学家的乐趣。然而,如果你愿意花时间来提高你对概率和统计的熟悉程度,并学习微积分和线性代数的基本原理,数学不应该成为你成为专业数据科学家的障碍。
PS:数学真的很有趣。随着你对数学的深入研究,你也将分享数据科学家对数学无拘无束的热情。
第 2 部分:技术技能
现在到下一个/稍微更有趣的部分。每天产生 2.5 艾字节的数据(1 艾字节= 10 ⁸字节),如果不使用计算机来分析这些数据的一小部分(称为“大数据”),那将是荒谬的。
“数据科学需要多少编程,尤其是统计分析和机器学习?”
很多。实际上,大多数数据科学工作都需要您编写代码,原因如上所述,还因为大多数公司都需要一些数据清理、实施和产品化,以及使算法适应他们自己的特定目的。如果你不能将自己的解决方案应用到产品中,那么你就不是一个有用的员工。(来源)
计算机编程语言
Python 是迄今为止世界上在数据科学中使用最广泛的编程语言。在 JetBrains 2016 年的调查中,几乎五分之四的开发人员表示 Python 是他们的主要语言。
我建议你专注于 Python,同时也花一点时间在 R 上。
** [## 学习 Python——Python 的搭便车指南
Learnpython.org 是介绍 Python 的一种简单而不吓人的方式。该网站采用了相同的方法…
docs.python-guide.org](https://docs.python-guide.org/intro/learning/) [## 面向所有人的编程(Python 入门)| Coursera
从密歇根大学学习面向所有人的编程(Python 入门)。本课程旨在教授…
www.coursera.org](https://www.coursera.org/learn/python) [## 学习 Python 3 | Codecademy
学习世界上最流行的编程语言的最新和最棒的版本!
www.codecademy.com](https://www.codecademy.com/learn/learn-python-3)
稀有
Python 将满足您的大多数数据科学项目,但是要真正被称为全面的数据科学家,您的工具包中需要有 R。在 R 和 Python 中不一定要成为宗师。选择一个,学习另一个的基本原理。
权威指南 R 是一种编程语言和环境,通常用于统计计算、数据分析…
www.datamentor.io](https://www.datamentor.io/r-programming/)
使用 Python 进行数据分析(Numpy、Pandas 和 Matplotlib)
如果你专门为了数据科学而学习 Python,你需要知道如何分析数据,特别是如何加载、操作和可视化数据。
[## Python Numpy 教程(有 Jupyter 和 Colab)
本教程最初由贾斯廷·约翰逊提供。我们将使用 Python 编程语言进行所有…
cs231n.github.io](https://cs231n.github.io/python-numpy-tutorial/)
用 Python 进行机器学习
机器学习算法是数据科学的核心。投入一些时间来掌握它们的理论和应用。
[## amueller/introduction _ to _ ml _ with _ python
这个库包含了 Andreas 即将出版的书《Python 机器学习入门》的代码…
github.com](https://github.com/amueller/introduction_to_ml_with_python) [## 机器学习速成班|谷歌开发者
学习和应用基本的机器学习概念的速成课程,获得现实世界的经验与…
developers.google.com](https://developers.google.com/machine-learning/crash-course)
结构化查询语言
SQL,或者结构化查询语言,对于数据科学家来说是极其重要的。数据建模的一个基本过程是首先提取数据。这通常会涉及到对数据库运行 SQL 查询。
面向专业开发人员的一站式 SQL 备忘单
medium.com](https://medium.com/swlh/want-to-learn-sql-heres-everything-you-need-baffadc89291) [## SQL 备忘单(2020)| websitesetup.org
在本指南中,您将找到一个有用的备忘单,它记录了一些更常用的 SQL 元素,甚至…
websitesetup.org](https://websitesetup.org/sql-cheat-sheet/)
生产系统
如果你在工作,你将利用公司的计算资源来提取、转换和分析数据。使用单台机器来执行这些任务是不够的。
值得花时间专门了解这些工具,因为它们在当今的行业中被广泛使用。
SQL 是当今使用的工具之一。像亚马逊网络服务(AWS) 、谷歌云和微软 Azure 这样的云计算平台被大量企业广泛使用。
另一个有用的技能是 版本控制 。
获得实践经验
遵循我上面提到的资源只会给你带来一半的好处。为了应用你刚刚学到的知识,你需要通过练习来应用这些知识!
要真正掌握这些概念,您需要在一些项目中使用这些技巧,这些项目非常类似于现实世界中的应用程序。你将会遇到问题——这是不可避免的——去处理诸如错误的数据,并在数据科学方面发展真正深厚的专业知识。
这里有几个好地方,你可以从那里获得这种实践经验(免费):
卡格尔
机器学习竞赛服务于许多目的。它们是解决问题和集思广益的渠道。 Kaggle 是最知名的数据科学平台之一。这是应用你新学到的技能的好方法。
这里列出了 10 个数据科学竞赛,供您磨练技能:
这里有一个网站列表,供您练习数据科学技能,参加在线黑客马拉松和…
towardsdatascience.com](/10-data-science-competitions-for-you-to-hone-your-skills-for-2020-32d87ee19cc9)
UCI 机器学习知识库
UCI 机器学习库是一个公共可用数据集的大型来源,你可以用它来组合你自己的数据项目。
值得注意的是,在 Github 上公开存储你的项目是一个好主意,因为这可以创建一个展示你的技能的作品集,用于未来的工作申请。
UCI ML 知识库
为开源做贡献
一个可以考虑的好选择是为开源项目做贡献。有许多 Python 项目依靠开发者社区来维护。Github 是一个很好的起点。
Numfocus 是这类项目的一个很好的例子。
结束语
在的这篇文章中,我描述了一条学习路径,它将引导你踏上数据科学之旅。
黄金法则,
比一般的数学家更擅长编程。
比一般程序员更擅长数学
数据科学是多个领域的混合体。你不应该只在一件事上努力做到最好,而是在每件事上都做得足够好。
牢记大局。
我想指出的是,如果你不愿意投入时间,这些资源不会为你工作。数据科学是一场马拉松,而不是短跑。前面还有很长的路要走。如果你遵循这条道路,你进入数据科学的道路将会更加顺畅,而不是更加容易,你将会在数据科学的道路上继续你的职业生涯。
快乐学习!
直到下一次…**
立即开始机器学习和人工智能之旅的资源
立即开始您的数据科学之旅
数据是新的石油,今天我们有大量的数据。我们需要一些更好的资源来学习人工智能和机器学习技术,以及更好的计算机器来训练和评估我们的模型,以便更好地利用数据和使用该模型。对于一个技术相关的人来说,了解数据科学是很有必要的,因为在未来,大多数工作都是关于数据科学技能的。
本文将分享一些学习数据科学的更好资源,以及我们如何开始为成为数据科学家做准备。从数据科学开始,首先,我们必须选择一种编程语言来帮助我们建立数据科学的模型。我们发现,大多数数据科学家在他们的数据科学项目中使用 python,因为有大量的社区和资源可供 python 使用。
This article contains some resources for which the author may get some part of the product's commission. [Learn more](https://www.amazon.com/gp/help/customer/display.html?ie=UTF8&nodeId=508088)
用于数据科学的 Python
在开始我们的数据科学之旅之前,我们必须熟悉 python 编程及其强大功能。有本书叫用 Python 把枯燥的东西自动化;这对初学者有好处。它使用门外汉的方法让你在更短的时间内成为 python 编程的专家。
用 Python 自动化枯燥的东西——作者 Al Sweigart
数据科学统计
统计在数据科学中扮演着重要的角色。每个机器学习算法都使用统计原理。它有助于数据科学中的决策,这在获得更好的模型准确性方面起着重要作用。有一本名为统计学习的要素的书以一种更好的方式展示了统计学。
统计学习的要素——作者特雷弗·哈斯蒂(Trevor Hastie)、罗伯特·蒂伯拉尼(Robert Tibshirani)、杰罗姆·弗里德曼(Jerome Friedman)
数据科学的机器学习
机器学习充满了帮助处理不同类型数据的算法。有一本书叫 Python 机器学习用 Python 搭配机器学习来演示不同的机器学习算法。
Python 机器学习——Sebastian rasch ka(作者)、Vahid Mirjalili(作者)
面向数据科学的深度学习
如今,我们更喜欢使用深度学习来处理大量的图像、视频、文本和音频数据。它使用人工神经元试图复制人类大脑的结构。 Grokking 深度学习是我能建议的最好的一本书,可以更好地理解深度神经网络。
探索深度学习——作者安德鲁·特拉斯克(Andrew Trask)
GPU 和数据科学机器
我们一般用 TensorFlow 做深度学习项目。并且,TensorFlow 使用英伟达GPU。为了更好的深度学习体验,建议至少使用英伟达 GTX 1050 Ti GPU。一些配备英伟达显卡的好笔记本电脑有戴尔 I 7577–7425 blk-PUS Inspiron和 Razer Blade 15 游戏笔记本电脑 2019 。它们都配备了英伟达 GTX 1060 显卡。
结论
开始您的数据科学之旅永远不会太晚。如果你对探索新事物有热情,那会有所帮助。在本文中,我们讨论了作为初学者学习数据科学的一些更好的资源,我们还讨论了一些更好的显卡 enabled-machine 来构建深度学习模型。
继续享受数据科学吧!
开始数据科学之旅的资源
开启数据科学之旅的全面资源列表
图片来源: Pixabay
互联网上与数据科学相关的内容如此之多,以至于对于任何打算开始这一领域之旅的人来说,在学习内容上做出正确的选择都变得有点困难。
根据我过去 5 年在这一领域的经验,以及我的数据科学家朋友&同事的建议,我列出了我在 2016 年开始旅程时开始参考的资源。
博文议程:
- 数据科学基础
- 机器学习和深度学习的资源
- 通过参加数据科学竞赛和黑客马拉松来学习。
- 获得免费的 GPU 计算!(新增)
- 在线硕士课程的详细信息。
- 最后的想法。
数据科学基础
由 Mirko Blicke 拍摄的图像,在取消绘制
“你不可能在薄弱的基础上建造一座伟大的建筑。如果你要有一个强大的上层建筑,你必须有一个坚实的基础。
以上引用适用于任何领域。我已经列出了几门课程,并指向了下面的 YouTube 频道,这些频道将帮助任何人从事数据科学的基础方面的工作。
帕德海四分之一实验室
PadhAI 是 IIT 马德拉斯的初创公司“四分之一实验室”(One-Fourth Labs)的一项举措,该公司致力于为印度提供负担得起的高质量在线课程,为印度进入人工智能时代做好准备。数据科学基础课程在他们的网站上,内容涵盖了 Python 编程、统计学、概率和 T21 的基础知识。如果你是学生,你可以通过提供有效的身份证来获得折扣!
在线报名参加 PadhAI 的数据科学课程,加速您作为数据科学家的职业生涯。接受 IIT·马德拉斯的训练…
padhai.onefourthlabs.in](https://padhai.onefourthlabs.in/courses/data-science)
3 蓝色 1 棕色
3Blue1Brown 是格兰特·桑德森创建的 YouTube 数学频道。该频道提供了许多高级数学概念的惊人的视觉视角。下面我列出了线性代数&微积分 YouTube 播放列表的链接,这些链接在开始学习不同的机器学习算法之前非常重要。
链接到线性代数播放列表。
链接到微积分播放列表
【Coursera 的机器学习数学
机器学习专业的数学来自伦敦帝国学院,由 3 门课程组成多元微积分、线性代数和降维 : PCA,每周有测验,也有少量编码作业。Coursera 的优势在于,你可以随时旁听课程,免费获取课程内容。如果你是一名学生,你可以提供有效的理由申请经济援助,并获得课程内容,包括测验,作业和免费获得证书。
从伦敦帝国理工学院学习机器学习的数学。对于很多机器方面的高级课程…
www.coursera.org](https://www.coursera.org/specializations/mathematics-machine-learning)
机器学习和深度学习的资源
计算机科学家、Coursera 顶级讲师 Andrew NG 教授的机器学习和深度学习课程。
这两门课程都非常有名,都涉及每周的测验和编码作业。对于机器学习课程,作业在 Octave/Matlab 中(语法非常类似于 python 中的 NumPy 库),对于深度学习课程,作业在 TensorFlow 中。
机器学习是让计算机在没有明确编程的情况下行动的科学。在过去的十年里…
www.coursera.org](https://www.coursera.org/learn/machine-learning) [## deeplearning.ai 的深度学习| Coursera
从 deeplearning.ai 学习深度学习,如果你想打入人工智能(ai),这个专精…
www.coursera.org](https://www.coursera.org/specializations/deep-learning)
FastAI
机器学习和深度学习课程由杰瑞米·霍华德、Kaggle 特级大师和三藩市大学教授主讲。这些课程的好处是免费提供,杰瑞米·霍华德采用自上而下的方法解释各种 ML/DL 概念。
程序员机器学习入门!
欢迎来到程序员机器学习入门!由杰瑞米·霍华德教授(卡格尔 2 年来的头号竞争对手…
course18.fast.ai](http://course18.fast.ai/ml)
程序员实用深度学习!
欢迎光临!如果你是所有这些深度学习的新手,那么不要担心-我们将带你一步一步地完成它…
course.fast.ai](https://course.fast.ai/)
通过参加数据科学竞赛和黑客马拉松来学习
数据科学竞赛托管平台。
一旦你熟悉了基础概念+各种机器学习/深度学习概念,是时候通过参加数据科学竞赛或黑客马拉松来弄脏你的手了。
我看到许多人说,做 Kaggle 或 Analytics Vidhya 竞赛没有多大用处,因为大多数竞赛没有描述真实世界的数据/真实世界的问题。但我要说,这些平台肯定提供了接触各种问题陈述的机会,而这些问题陈述在学生生活或公司世界中可能没有机会得到。
- 摇摇晃晃:【https://www.kaggle.com】T2
- 【https://datahack.analyticsvidhya.com 分析】维德希亚:
- Crowdanalytix:https://www.crowdanalytix.com/community
- **黑客帝国:**https://www.hackerearth.com
获得免费的 GPU 计算!!
图片来源:https://www.nvidia.com/en-in
是的,你没看错!!谷歌实验室和 Kaggle 向他们所有的用户提供免费的 GPU 计算。如果你有一个庞大的数据集,并希望训练一个深度学习模型,只需将数据集上传到这两个平台中的任何一个,你就可以轻松地将你的 DL 模型的训练时间从几天减少到几个小时!!
Google Colab 上的 GPU 内存
每周在 Kaggle 上,人们可以获得 30 小时的免费 GPU 计算,它配备了 P100 GPU 和 16GB 的 GPU 内存。最近这两个平台都开始免费提供 TPU 计算!!在 Kaggle,一个人每周可以使用 30 个小时的 TPUs,一次最多可以使用 3 个小时。现在是你探索更多的时候了:)
在线硕士课程
如果有人想在日常工作之外继续攻读硕士课程,以增强他们在数据科学方面的知识,我列出了一些大学,这些大学提供相当于校园课程的 MS 学位 ,而没有在学位证书上提及“在线”交付模式,并且还提供职业服务!!
佐治亚理工学院的 OMSCS 项目:
[## 主页| OMSCS |佐治亚理工学院|佐治亚州亚特兰大
跳转到内容主页你准备好获得计算机科学硕士学位但不准备停止工作了吗?你想要…
www.omscs.gatech.edu](http://www.omscs.gatech.edu/)
单门课程(3 学分)持续时间: 4 个月(需要完成 10 门这样的课程)
单科费用: $510 +每学期 $310。
所以这个学位的总花费不会超过 8200 美元。这里可以看到详细的计算。
亚利桑那州立大学 MCS 项目:
[## 在线计算机科学硕士(MCS) | ASU 在线
在线计算机科学硕士(MCS)计划,提供了一个创新的合作伙伴关系,亚利桑那州立大学的…
asuonline.asu.edu](https://asuonline.asu.edu/online-degree-programs/graduate/computer-science-mcs/)
单门课程(3 学分)时长: 2 个月(需完成 10 门此类课程)
单次课程费用: $1500。
因此,这个学位的总费用是 15000 美元。
参考以下链接其他硕士课程的详细信息,您可以参考以下链接:
探索一流大学的在线硕士学位,其价格仅为校园课程的一小部分…
www.edx.org](https://www.edx.org/masters) [## 顶尖大学的在线硕士和学士学位
Coursera 提供数据科学、计算机科学、信息技术、工程、工商管理硕士等在线硕士学位
www.coursera.org](https://www.coursera.org/degrees)
相信我,如果求职者没有硕士学位,某些组织会直接拒绝他们的简历。我个人认为,只看他/她拥有的学位而不是他/她拥有的技能来做决定是不正确的。但无论如何,拥有一个学位将会增加你的知识,并抓住这个非常重要的主题。
最终想法
我希望这篇文章有助于提供一个全面的资源列表,以开始您的数据科学之旅。
他们中的许多人可能仍然会说"难道我们不能仅仅通过知道如何使用 sklearn、Keras、TensorFlow、PyTorch 等库来在数据科学领域生存吗?而忽略任何机器学习或深度学习算法背后的基本概念或数学??"
我对他们的回答是一个大大的不。只要您的模型按预期工作,拥有库级别或包级别的理解就可以工作,但是如果模型没有按预期工作呢?你如何修理它??
如果您有任何想法或问题,请随时在下面留下评论,不要忘记点击👏如果你喜欢博客的内容。
我以前的一些博客:
关注我 中 阅读更多此类博客。
[## Rajesh Shreedhar Bhat - Medium
阅读 Rajesh Shreedhar Bhat 在媒体上的文章。数据科学家-沃尔玛实验室| Kaggle 竞赛专家|…
medium.com](https://medium.com/@rajesh_bhat)
应对大规模紧急事件和中断:人工智能和决策优化可以有所帮助
安全、快速、无浪费地重新分配您的资源
照片由埃德温·胡珀在 Unsplash 上拍摄
什么是应急响应?
在写这篇文章的时候,我们正在深入新冠肺炎疫情。医院、超市和政府机构等都被对服务的巨大需求所淹没,同时试图管理他们有限的资源和资产,同时努力保证人们的安全。现在应该如何分配资源以便它们正好用在病人和医生最需要的地方?如何根据不断变化的需求和地理位置,在遵守安全法规和出行限制的同时,随着时间的推移重新分配呼吸机?不管这意味着什么,一旦一切开始恢复“正常”,我们该如何安全地重返工作岗位?**
由于其前所未有的性质,像新冠肺炎疫情这样的事件的自动化决策是复杂的,需要仔细的分析,准确的数据可能不容易获得,更不用说任何政治和行政方面的考虑。
这种真实而大规模的中断正在吞噬着这个世界,但这只是需要快速而准确的响应、管理有限资源并确保运营成本不会飙升的紧急情况的一个例子。 正如我们将看到的,高效的应急响应需要人工智能技术的结合,特别是机器学习和决策优化。
本文中讨论的方法可以应用于处理各种类型的大规模中断。我们将特别关注天气突发事件,如暴风雪,因为它们的影响可能是毁灭性的。根据国家环境信息中心和 NOAA Climate.gov的数据,自 1980 年以来,美国已经遭受了 258 次天气和气候灾害。这 258 个事件的累计成本超过了 1.75 万亿美元。
示例:应对大规模天气事件
埃里克·麦克莱恩在 Unsplash 上拍摄的照片
当恶劣天气事件即将发生时,无论是暴风雪、洪水还是地震,一个州或地区的运营经理都必须迅速决定如何最好地满足对资源和资产(如扫雪机、水、警察和救援车辆)的需求。
让我们具体看看如何应对暴风雪。对扫雪机的需求取决于降雪预报,一些地区可能会比其他地区受到更严重的影响,当风暴来袭时,需要更多的扫雪机。机器学习模型可以预测每个县的卡车需求,同时考虑所有相关信息,如降雪预测、安全指南和过去的暴风雪历史(图 1)。
首先,我们需要准确的需求预测
图 1:机器学习预测每个时间段每个县对扫雪机的需求
然后,我们需要决定如何将这些资产从低影响地区重新分配到高影响地区,例如,将多少资产从 C1 和 C2 县转移到 C3、C4 和 C5 县,确保每个县都有足够的扫雪机来满足需求。
然而,我们不要忘记,降雪预报每隔几个小时就会发生变化,因为暴风雪会穿过该州,所以我们需要不断移动卡车,同时考虑到天气预报和当时的积压水平(积雪)。
我们需要一种有效的方法来重新分配扫雪机和其他资产
为什么预测资源需求是关键,但不足以解决应急响应问题?
如果我们一次考虑一个县,并且没有冲突的优先事项,我们的机器学习模型生成的预测可能足以做出决定。然而,一旦我们开始引入一些现实生活中的复杂性、依赖性和有限的资产,确定最佳的重新分配计划就变得更加具有挑战性。
例如,如果该州相对两侧的两个县在风暴开始时预计会收到最多的降雪,该怎么办?在这种情况下,如果我们没有足够的雪犁来满足所有需求,我们应该把雪犁送到哪里,送多少?
预测不会告诉我们如何分配有限的资源
在风暴开始时,C1 县最需要资源,但几个小时后,该州另一边的 C2 和 C3 也需要资源,这种情况会怎样?我们会把扫雪机搬到 C1 吗,即使在它们被暴风雪袭击之前把它们运到 C2 和 C3 是不可能的?这种延迟会如何影响积雪和道路安全?
我们所做的决定是相互依赖的,因此我们必须一起做出决定
为了创建一个可行的计划,我们在风暴开始时做出的关于如何分配资产的决策需要与风暴后期的重新分配决策结合起来。此外,我们不能孤立地为一个县和其他县做出决策,因为它们都在争夺同样有限的资源。
最后,有几个决定?例如,让我们考虑 2000 台扫雪机和 60 个县。假设我们考虑在 24 小时的暴风雪中每 4 小时重新分配它们。有多少种重新分配的可能性?在 6 个时间段中的任何一个时间段,我们可以决定从 60 个县中的任何一个县向 60 个县中的任何一个县移动 0-2,000 台扫雪机。在不考虑距离、可用性、积雪积压、需求约束和多种资产类型的情况下,做一个非常粗略的估计,我们可能需要考虑的选项数量是 60 * 60 * 2000 * 6 = 43200000!没有人能够手动确定这些决策中的哪一个是最佳的。
涉及重新分配的决策很容易需要评估 43,000,000 多个选项!没有人能够人工确定这些选项中哪一个是最好的。
人工智能和决策优化有什么帮助?
决策优化使用来自机器学习的见解来做出最佳决策
决策优化使用非常专业的算法和技术来有效地搜索和评估数以百万计的潜在解决方案,而无需一一列举。
虽然机器学习可以考虑所有可用的数据和过去的历史,以预测每个县或地区在任何给定时间对扫雪机和其他资源的需求,但决策优化(DO)可以更进一步,并生成在整个规划范围内对整个州最优的计划,受限于有限的资源(例如,扫雪机)其他约束和依赖性(可用资源的类型和数量, 每个扫雪机的当前位置、行驶距离和时间)和优化指标(最小化总成本、最大化安全性/客户满意度、最小化卡车总行驶距离)。 它不仅为我们提供了有价值的见解,而且还生成了一个可操作的时间表或计划(图 2)。**
图 2:结合机器学习和决策优化的力量进行应急响应
与任何决策支持解决方案一样,仅仅创建一个模型是不够的。我们的最终目标应该是在业务用户和决策者手中交付一个解决方案。构建这样一个解决方案通常需要几个关键部分(图 3):
- 一个强大的数学优化引擎,如 CPLEX,它可以运行和求解决策优化模型,找到一个最优解决方案
- 构建人工智能模型(机器学习和决策优化)的高效建模环境
- 假设场景分析和仪表板,用于为业务用户测试模型、分析场景和原型可视化
- 一种将模型作为 web 服务部署到决策支持应用程序中的机制,以便规划者可以实时运行场景
图 3:使用 IBM 数据和 AI 平台的决策优化应用程序开发和部署
更具体地说,将上述内容应用到我们实施应急响应计划解决方案的具体示例中,该过程可以总结为以下三个步骤:
步骤 1 :建立一个机器学习模型,按地点和时间段预测对资源(扫雪机)的需求。
第二步:建立一个决策优化模型,在暴风雪来临之前和期间,根据需求和可用性,确定如何最佳地重新分配资源。该模型将业务需求转化为数学优化引擎可以使用的术语。
第三步:部署模型,并将它们嵌入到您的规划应用程序中
让我们更详细地看看这三个步骤。无论使用什么技术,方法都是相似的。在这里,作为一个例子,我们概述了如何使用 IBM 数据和人工智能平台来构建一个紧急响应解决方案。
第一步:建立一个机器学习模型来预测需求
这可以通过多种方式实现,具体取决于您使用的工具。例如,IBM 数据和人工智能平台(IBM Cloud Pak for Data 或 IBM Watson Studio Cloud 中的 IBM Watson Studio)包括 AutoAI,它可以自动选择正确的算法,构建机器学习管道,执行超参数优化(HPO)和特征选择,并根据指定的评估指标确定最佳模型(图 4)。另一种选择是使用 SPSS Modeler 的拖放界面来创建自己的机器学习管道。如果您喜欢从头开始构建您的模型,您可以使用开源包(如 scikit-learn)用 R 或 Python 实现它们。一旦模型被训练、验证和测试,它就可以被部署为在线模型,使用 REST APIs 进行访问。
图 4: AutoAI 体验:自动生成预测扫雪机需求的最佳模型
步骤 2:建立一个决策优化模型来重新分配资源
决策优化模型的关键要素是决策变量、优化指标和约束。**
需要做出的决策(建模为决策变量)决定了在每个时间段内要在每对县之间重新分配的资产(例如扫雪机)的类型和数量。这些值不是我们输入数据的一部分,而是由优化引擎自动确定的。**
优化指标定义了我们优化的目标(最小化/最大化)。在紧急响应的情况下,这些指标可以是以下指标的任意组合:
- 最小化重新分配卡车的成本(基于重新分配的总次数,以及基于行驶里程的可变成本)
- 最小化未降雪
- 最大限度提高安全性
- 最大化客户/通勤者满意度
最后,优化模型需要考虑许多约束条件,包括:
- 在给定的时间段内,在一个位置可用的任何现有的积雪和铲雪能力与对铲雪机的预测需求(ML 模型的输出)相平衡
- 任何重新分配的决定必须是可行的,也就是说,在任何给定的时间和地点,我们移动的卡车数量都不会超过可用的数量
决策优化仪表板显示我们 DO 模型的输入和输出。关键输入是雪犁的需求预测和初始分配(图 5):
图 5:决策优化仪表板场景输入:雪犁的预测需求和初始分配
这里我们看到了按时间和位置(ML 模型的输出)对扫雪机的需求,以及资产的当前分布,即按位置的数量。
然后,我们创建三种不同的假设情景:
- 方案 S1(基准方案):不执行任何重新分配(无优化,仅计算 KPI)
- 场景 S2(风暴前重新分配):重新分配一次资产,为暴风雪做准备(局部优化)
- 场景 S3(风暴期间重新分配):随着暴风雪的推进,每隔几个小时重新分配资产(完全优化)
在解决了这三个场景之后,我们在 DO 仪表板中并排比较结果(图 6):
图 6:决策优化仪表板:假设分析
我们可以清楚地看到,优化程度最高的场景,即 S3 场景,产生的积压最少(是没有优化的基准场景 S1 的 1/4,或者是部分优化的场景 S2 的 1/2)。当然,这是需要评估成本的。情景 S3 的成本最高(176,324 美元),因为重新分配的次数最多,相比之下,情景 S2 为 51,061 美元,情景 S1 为 0 美元(无重新分配)。
比较这三种情况,计划者将评估较小的积雪积压与较高的重新分配成本的优势。如果需要,总成本也可以表示为这里使用的两个优化指标的加权和,即每个场景的总积压和重新分配成本的组合。规划者可能还想在做出最终决定之前运行几个额外的场景,例如,她可以看看从附近的州借几台扫雪机是否会产生明显更好的解决方案。
步骤 3:部署模型并将它们嵌入到您的规划应用程序中
一旦模型准备好并经过测试,它们就可以作为 web 服务进行部署,并嵌入到我们的规划应用程序中。如果使用 IBM 数据和人工智能平台,在沃森机器学习中部署模型只是点击几次的事情。然后,每个模型通过 REST API 端点变得可用。最后一步是构建和部署 web 应用程序(例如 Node.js 或 R Shiny),或者在现有的应用程序中嵌入服务,并通过访问已部署的 ML 和 DO 模型来生成我们的优化重新分配计划。
这个演示是使用一个 R Shiny 应用程序实现的(图 7):
图 7:注入了 ML 和 DO 模型的示例应急响应计划应用程序
当雪地作业经理 Alex 登录到她的应急计划门户网站时,她需要掌握所有必要的信息来做出决策。她看了看纽约州,迅速评估了实时更新的降雪预报,并用地图上的颜色表示。颜色越深,对应的县预计降雪量越大。右上角的滑块可用于选择不同的时间段,以查看情况如何随时间变化。
Alex 注意到 Chautauqua 预计在风暴开始时会有最多的雪,他在地图上选择了该县以查看更详细的信息,例如确切的积雪英寸数、可用的扫雪机数量与预测的需求量以及预期的积压量。预测需求是从我们部署的 ML 模型中实时获得的。
然后,Alex 选择了一个即将到来的箭头,并观察到 20 辆卡车正在从利文斯顿县重新分配。这很有道理,因为目前那里的降雪量很小。
Alex 将时间滑块向右移动,以查看建议的卡车重新分配,这些卡车重新分配对应于因暴风雪席卷整个州而不断变化的需求。下表中也提供了相同的卡车重新分配建议。它们是使用我们部署的决策优化模型实时获得的。
如果亚历克斯对推荐的计划感到满意,她可以继续批准它。她可能还会选择运行一些假设场景,尝试潜在地增加一些可用的扫雪机,或者手动指定一些重新分配。在解决了这些额外的情况并比较了由此产生的变动和相应的 KPI 后,Alex 将对如何继续做出最终决定…
当然,这只是一个使用 IBM 数据和 AI 平台、决策优化和 R Shiny 实现的演示的简单示例。至于你能做什么以及如何在你自己的应用程序中呈现信息,这种可能性是无穷无尽的。
摘要
应对大规模紧急情况和干扰是一个关键问题,需要立即采取行动。使用有效的应急响应解决方案的好处是巨大的,包括但不限于:
- 减少规划/调度时间和工作量
- 提高安全性和合规性
- 降低运营成本
- 提高资源利用率
- 提高客户满意度
创建最佳资产重新分配计划是一个具有挑战性的问题,最好使用机器学习和决策优化的组合能力来解决。虽然机器学习可以考虑所有可用的数据和过去的历史,以预测在给定时间每个位置对资源的需求,但决策优化可以更进一步,生成对一组位置最优的计划,该计划受有限资源、其他约束和依赖性以及优化指标的限制。优化不仅能提供有价值的见解,还能生成可操作的时间表或计划。**
有效应对大规模中断需要为业务用户提供有效的决策工具。即使我们建立了伟大的人工智能模型,它们的力量也只能通过将它们放在计划者和决策者的手中来加以利用。嵌入了嵌入式人工智能模型的应用程序允许决策者在实施最终决策之前试验各种场景并并排比较收益,所有这些都不需要理解人工智能模型背后的实施细节。
如果您的组织正在寻找更好的方法来优化对中断的响应,分配和重新分配资源,或者解决其他预测和优化挑战,请不要犹豫,寻求帮助。IBM 数据科学精英团队的使命是帮助我们的客户在他们的人工智能之旅中取得成功,作为这一使命的一部分,我们免费提供初始启动服务。我们很高兴在数据科学/人工智能项目上与您合作。更多信息,请参考ibm.co/DSE-Community。
附加链接
* [## 2010-2019:美国数十亿美元天气和气候灾害的标志性十年| NOAA…
2019 年,美国经历了 14 次独立的灾害,每次损失至少 10 亿美元。自 1980 年以来,258…
www.climate.gov](https://www.climate.gov/news-features/blogs/beyond-data/2010-2019-landmark-decade-us-billion-dollar-weather-and-climate) [## 数据科学精英——IBM 数据科学社区
www.ibm.com](https://www.ibm.com/community/datascience/elite/) [## 紧急响应加速器(IBM 云包数据)
community.ibm.com](https://community.ibm.com/community/user/cloudpakfordata/viewdocument/emergency-response-management?CommunityKey=c0c16ff2-10ef-4b50-ae4c-57d769937235&tab=librarydocuments) [## 决策优化
IBM Decision Optimization 是一个产品系列,旨在使用规范性分析来改进优化,以…
www.ibm.com](https://www.ibm.com/analytics/decision-optimization) [## IBM Cloud Pak for Data -概述
IBM Cloud Pak for Data 是一个数据平台,它统一并简化了数据的收集、组织和分析
www.ibm.com](https://www.ibm.com/products/cloud-pak-for-data) [## 沃森工作室-概述
了解更多关于 Watson Studio 的信息。通过为您的团队提供一个最佳的工作环境来提高工作效率…
www.ibm.com](https://www.ibm.com/cloud/watson-studio)*
负责任的人工智能:在采用人工智能驱动的工具之前,企业应该知道什么
AI 会好到不真实吗?商业用户应该问的问题。
过去,我们预计机器学习支持决策的唯一广泛使用的地方是科技公司。我们知道亚马逊已经使用人工智能来帮助筛选简历,网飞使用机器学习驱动的推荐系统来猜测你还想看什么节目。这种情况正在改变。
机器学习模型现在以自动贷款 assessments⁴的形式嵌入到我们的银行系统中,并通过生成风险分数来通知 sentencing⁵.,嵌入到我们的刑事司法系统中除了这些定制的模型,从 enforcement⁵法律到 retail⁶,更多的组织正在购买由人工智能默默驱动的软件。
随着这些工具被广泛采用,商业领袖需要向他们的软件提供商、数据科学家和机器学习专家提出正确的问题。
当设计、部署和集成不当时,机器学习工具可能会产生严重的后果。
严重后果?比如什么?
如果你的人工智能驱动工具的应用程序对人或社区进行评估或决策,歧视性偏见就会发生。在你没有意识到的情况下,机器学习算法可以从训练数据中学习偏差。在过去,这导致恢复了对妇女有偏见的筛选工具或犯罪预测模型,导致对 communities⁵.族裔的过度监管
即使出于最好的意图,这种情况也会发生。你是一所试图利用机器学习更好地瞄准招聘活动的大学吗?您是否是一家利用大数据来识别需要资助的社区的非营利组织?如果历史对某一特定人群有偏见,那么你用来训练模型的数据就反映了这种偏见的结果。如果你不小心,你可能会使历史偏见永久化,即使是出于最好的意图。
概念漂移发生在支撑你的机器模型的条件发生变化,导致你的预测不再准确的时候。我们工作的世界瞬息万变,人类会根据这些变化的条件来调整我们的决策。如果我是一名企业校园招聘人员,我可以根据我对大学课程变化的了解来调整我的简历筛选标准,这些变化会导致不同的 GPA 分布。
受过训练的模型会忽略这些差异。随着时间的推移,模型被定型时的世界和模型进行预测时的世界之间的差异会扩大。在最好的情况下,业务用户会注意到差异,并相应地进行调整。最坏的情况是,一家企业可能会因为将核心功能委托给过时的模式而失去竞争力。
每个模型(或模型集)都有其局限性,因为它们在某些情况下高度准确,而在其他情况下可能是随机猜测。通常,当有大量训练数据可供学习模式时,模型表现良好,而在与之前看到的差异太大的示例中,模型表现不佳。
不知道在您的环境中,一个模型在什么情况下工作得好,什么情况下工作得差,意味着您不能构建考虑其缺点的业务流程。例如,如果我们知道某个算法在我们从未招聘过的大学可能表现不佳,那么让我们手动筛选来自新大学的候选人。
作为企业用户,我可以做些什么来准备我的组织?
在采用人工智能驱动的工具之前,请与您的人工智能专家进行讨论。
- **询问模型或工具在准确性之外的性能指标。**有时候,你会关心不同群体的准确性,比如少数民族是否得到与多数民族相似的预测。在其他情况下,您可能不太关心准确性,而更关心我们没有遗漏任何潜在的案例(回想一下)。
- **为模型部署后的监控制定一个计划,并确定重新评估和潜在重新训练模型的触发因素。**情况会发生变化,除非您积极监控情况,否则您和您的组织可能不会注意到这一点。确定指标以监控基础人群的分布。实现反馈机制来监控模型的准确性(或其他性能指标)。定期检查这些反馈,并积极主动地维护您的模型。
- 了解你的模型的局限性,并在周围业务流程的设计中解决它们。在不同条件下对你的模型进行压力测试。你的模型表现如何?例如,如果它是一个影响客户的工具,在这些情况下的性能是否可以接受?如果没有,通过在需要的地方进行人工干预来计划这些限制。
Monique 是一名前管理顾问,也是一名训练有素的数据科学家。你可以在 medium.com/@monique_wong 的查看她关于数据科学和商业的其他文章
1杰弗里·达斯廷。(2018 年 10 月 9 日)。https://www . Reuters . com/article/us-Amazon-com-jobs-automation-insight/Amazon-scraps-secret-ai-recruiting-tool-show-bias-against-women-iduskcn 1 MK 08g
[2]利比·普卢默。(2017 年 8 月 22 日)。https://www . wired . co . uk/article/how-do-Netflix-algorithms-work-machine-learning-helps-to-predict-what-viewers-will-like
3詹姆斯·文森特。(2018 年 1 月 12 日)。https://www . the verge . com/2018/1/12/16882408/Google-种族主义者-大猩猩-照片-识别-算法-ai
4 凯瑟琳·瓦尔希。(2019 年 7 月 26 日)。https://www . Forbes . com/sites/Douglas Merrill/2019/04/04/ai-is-coming-to-take-your-mortgage-disease/# 195 ee2b 87567
[5]郝凯伦。(2019 年 1 月 21 日)。https://www . technology review . com/2019/01/21/137783/algorithms-criminal-justice-ai/
【6】AI 创业公司。(2020 年 3 月 12 日)。https://www.ai-startups.org/top/retail/
用 R 实现可靠的流行病数据可视化
告知来激发意识,而不是恐惧。
马库斯·斯皮斯克在 Unsplash 上的照片
D 与任何其他分析不同,与疫情相关的数据可视化会带来无数风险,从在公众中虚假传播恐惧到甚至误导决策当局。最近强调了许多明智和负责任的数据可视化措施。最著名的是来自丽莎·夏洛特·罗斯特、阿曼达·马库雷克和埃文·佩克的。让我们深入采纳他们的一些建议,并使用 R 软件生成类似的适当的可视化。
步骤 1:获取和提炼数据
让我们从两个来源获取数据— 约翰·霍普斯金大学新冠肺炎存储库和牛津大学政府响应跟踪系统(OxCGRT) 。
df<-read.csv('Cases.csv') **#Data from John Hopkins** df2<-read.csv('Database2.csv') **#Data from Oxford CGRT**
第一个数据库给出了国家和日期的确诊、痊愈和死亡。一个单独的现役列是通过从中减去已康复中的数字和从中减去死亡中的数字计算出来的。让我们检查数据库的前几行和前几列。
head(df)[,1:15]
第二个数据库看起来像:
head(df2)
很明显,第二个数据库需要一些改进和重塑,如下所示:
**#Convert the Date column from numeric to datetime type** df2 <- transform(df2, Date = as.Date(as.character(Date), "%Y%m%d"))**#Combine Confirmed Cases and Deaths into a single column for labels**
df2<-gather(df2,Case_Type,Cases,ConfirmedCases:ConfirmedDeaths) **#Modified database:**
head(df2)
第二步:基本可视化
最基本和最常见的新冠肺炎可视化是累积条形图。
很容易通过使用 R 中的 ggplot2 包获得—
ggplot(data=dfsumcases, aes(x = Date, y = ConfirmedCases))+ geom_bar(stat = 'identity')
在全球累计确诊病例图表中,我们可以看到病例从 1 月底开始出现(数据库限制:我们知道这不是真的,因为中国的病例比那早得多。数据库中没有 Jan 的数据记录)。
注意到病例数量的突然增加了吗?
在最初的两个月中,案例总数达到了 70 万(1k=1000),但随后在不到一个月的时间里,几乎翻了一番,达到了 200 万。
在死亡人数上也可以观察到同样的模式。
然而,除了死亡人数相对于确诊病例明显较低之外,很难解释这两个图表之间的差异。
这让我们想到了下一个问题——我们真的需要把死亡人数单独想象成一个看起来可怕的指数增长吗?公共卫生专家阿曼达非常恰当地放下笔 —
“新冠肺炎不是死刑,我们的观想需要反映这一点。包括恢复的案例是可视化案例编号的一个重要背景。”
第三步:前进,负责任的观想
我们必须清楚地传达数据向我们揭示了什么—
- 死亡的部分作为总确诊病例的子集。
- 强调恢复的数量作为总确诊病例的子集。
资深数据科学家罗伯特·伍德在这方面做得很好。在我们的例子中,使用第一个数据库可以解决这两点,如下所示—
df %>%
filter(!grepl('Confirmed', Case_Type)) %>%
group_by(DateTime, Case_Type) %>%
summarise(Cases = Total/1000) %>%
ggplot(aes(x = DateTime, y = Cases, fill = Case_Type))+
geom_bar(stat = 'identity')+
theme(axis.title.x=element_blank())+
scale_fill_manual("legend", values = c("Active" = "steelblue4", "Deaths" = "black", "Recovered" = "goldenrod3"))
确诊病例总数分为 3 部分——活动期、死亡期和恢复期
马上我们可以看到,这不仅在视觉上吸引人,而且更适合这个敏感的场景,因为它迎合了上述两个重点。
注意手动颜色填充的故意使用?原因?
不幸的是,已经有许多与 COVID 相关的死亡。然而,不要用令人担忧的红色来呈现这些案例,而是采用不同的颜色,比如黑色(表示尊敬)。
现在,如果我们想获得 3 个组件中每一个的估计值,我们可以将位置参数设置为减淡,在几何 _ 条内
df %>%
filter(!grepl('Confirmed', Case_Type))%>%
group_by(DateTime, Case_Type)%>%
summarise(Cases = Total/1000)%>%
ggplot(aes(x = DateTime, y = Cases, fill = Case_Type))+
geom_bar(stat = 'identity', position = 'dodge')+
theme(axis.title.x=element_blank())+
scale_fill_manual("legend", values = c("Active" = "steelblue4", "Deaths" = "black", "Recovered" = "goldenrod3"))
与新冠肺炎相关的全球活跃、康复和死亡的累计登记病例
如果我们想在一个国家接一个国家的基础上观察同样的情况呢?我们可以利用 facet_wrap 选项—
df2 %>%
filter(grepl('China|Korea|United States|United Kingdom|Italy|Spain',CountryName) & Date > '2019-12-31') %>%
group_by(Date, Case_Type, CountryName)%>%
summarise(Cases = sum(Cases))%>%
ggplot(aes(x = Date, y = Cases, fill = Case_Type))+
geom_bar(stat = 'identity', position = 'dodge')+
scale_fill_manual("legend", values = c("ConfirmedCases" = "steelblue4", "ConfirmedDeaths" = "black"))+
facet_wrap(~CountryName)
注意到上图的一些问题了吗?
- 很难单独观察确诊病例和确诊死亡病例,这是因为美国的病例数量非常高。
- 显示的国家好像没有顺序(最好是最大案例降序排列?)
让我们使用 ggpubr 包中的 ggarrange 函数来解决这些问题。但首先,让我们按照确诊病例的降序排列数据库。
maxconfirmed <- df2 %>% filter(Case_Type=="ConfirmedCases") %>% group_by(CountryName) %>% arrange(-(Cases)) %>% distinct(CountryName, .keep_all = TRUE)head(maxconfirmed)
现在,我们可以在面网格中选择这些排名靠前的国家。然而,对于 ggarrange,我们需要每个国家都有单独的 ggplot 对象。让我们首先创建一个函数来完成这项工作。然后把它应用到所有想要的国家。
countryplot <- function(x) {
df2 %>%
filter(CountryName == x & Date > '2019-12-31')%>%
group_by(Date, Case_Type)%>%
ggplot(aes(x = Date, y = Cases/1000, fill = Case_Type))+
geom_bar(stat = 'identity', position = 'dodge')+ggtitle(x)+
theme(plot.title = element_text(hjust = 0.5),
plot.margin=unit(c(0.1,0.1,0.1,0.1), "cm"),
axis.title.x=element_blank(), axis.title.y=element_blank(),
axis.text.x = element_text(angle = 45))+
scale_fill_manual("legend", values = c("ConfirmedCases" = "steelblue4", "ConfirmedDeaths" = "black"))}pus<-countryplot('United States')
pit<-countryplot('Italy')+ coord_cartesian(ylim = c(0, 180))
psp<-countryplot('Spain')+ coord_cartesian(ylim = c(0, 180))
pge<-countryplot('Germany')+ coord_cartesian(ylim = c(0, 180))
pfr<-countryplot('France')+ coord_cartesian(ylim = c(0, 180))
puk<-countryplot('United Kingdom')+ coord_cartesian(ylim = c(0, 180))
pch<-countryplot('China')+ coord_cartesian(ylim = c(0, 180))
既然我们已经有了所有国家的单独 ggplot 对象,我们就可以使用 ggarrange 了。让我们在左边分开,在右边跟随 6 个国家作为 3x2 矩阵。
plc1<-ggarrange(psp,pit,pge,ncol = 3,legend = "none")
plc2<-ggarrange(pfr,puk,pch,ncol = 3, legend = "none")
plc3<-ggarrange(plc1,plc2,nrow = 2, legend = "none")
plc4<-ggarrange(pus,plc3,widths = c(1,3),common.legend = TRUE, legend = "bottom")annotate_figure(plc4,bottom = text_grob("Data source: The Oxford COVID-19 Government Response Tracker (OxCGRT)", color = "blue", hjust = 1, x = 1, face = "italic", size = 10),left = text_grob("Cases (in thousands)", color = "black", rot = 90))
所有这些真的算不上什么进步。因此,第 4 步:真正的交易
之前的观想非常简单。我们必须做得更多。但是这些都是细微的差别,我们必须小心谨慎—
- 如果我们想安全地更深入地挖掘数据,而不仅仅是显示累计数字,该怎么办?
- 如何看待每个国家都经历了病例和死亡的增加?而这同时又不受与数据记录相关的不确定性的可能威胁?
- 我们能否利用对数标度来获得改进的感觉?
流行病概况是指数曲线,随着曲线的上升,很难看到和捕捉重要的(可能有用的)细节。世界经济论坛的资深作家肖恩·弗莱明精彩地强调了这种对数标度的好处,以获得疫情数据背后的更大图景。这些进一步反映在丽萨在 datawrapper 的优秀的疫情可视化页面上。
让我们看看对数刻度能得到什么。然后嘣——
y 轴是累计确诊病例,用对数标度的七天滚动平均值平滑。否则,该刻度上的直线对应于指数增长。
在疫情的情况下,我们必须把微观水平的数据分析和解释留给流行病学家。此外,我们必须注意每个国家的所有数据收集和记录的不确定性。这促使使用七天滚动平均值来平滑累积确诊病例的概况。可以使用滚动平均函数计算滚动平均值—
df3<-df2[df2$Case_Type == "ConfirmedCases", ]
df3<-df3[order(df3$CountryName,df3$Date),] %>%
group_by(CountryName) %>%
mutate(roll_mean = rollmean(Cases, 5, na.pad = T))
此外,请注意,x 轴对应于自每个国家登记第 100 例病例以来的天数。因此,在有条件地删除案例数小于 100 的行之后,让我们创建一个单独的列作为日计数器(dc)。这将使所有国家的确诊病例配置文件从第和 天开始= 100 。
*df3<-df3[!(df3$Cases<10),]
df3<-df3 %>% group_by(CountryName) %>% mutate(dc = row_number())*
最后,让我们用两个变量,breaks 和 minor_breaks,在对数标度上表示滚动平均值与直流的关系。
*breaks <- 10^(-10:10)
minor_breaks <- rep(1:9, 21)*(10^rep(-10:10, each=9))
ggplot() +
geom_line(data=df4,aes(x=dc, y=roll_mean, group=CountryName),color="gray68") +
geom_line(data=df4 %>% filter(CountryName =='United States'),aes(x=dc, y=roll_mean),color="steelblue4",size=1) +
geom_line(data=df4 %>% filter(CountryName =='Italy'),aes(x=dc, y=roll_mean),color="darkseagreen4",size=1) +**#(Repeat the geom_line() step to bold as many countries as you want)** scale_y_log10(breaks = breaks, minor_breaks = minor_breaks) +
annotation_logticks(sides=c("l")) +
coord_cartesian(xlim = c(0, 60)) +
theme_bw()*
同样,由于国与国之间确诊病例总数的不确定性,最好对死亡总数进行同样的可视化,以衡量每个国家的表现。复制以上死亡的所有步骤给我们—
现在,如果我们想观察数字的变化率,比如 5 天内的变化,我们可以从数据中获得更多的见解。我们可以使用 lag()函数来获取以前的实例值。
*df7<-df2[df2$Case_Type == "ConfirmedCases", ]
df7<-df7[order(df7$CountryName,df7$Date),]
growth_rate = df7 %>% group_by(CountryName)%>%
mutate(Cases_1 = lag(Cases),
Cases_2 = lag(Cases_1),
Cases_3 = lag(Cases_2),
Cases_4 = lag(Cases_3),
Cases_5 = lag(Cases_4),
Diff_growth = Cases - Cases_5,
Rate_percent = ((Diff_growth/5)/Cases * 100))*
我们这次使用 3 天滚动平均值平滑增长率,增长率与日计数器图给出了—
y 轴是 5 天期间的病例变化率(%),用 3 天滚动平均值平滑
我们可以立即注意到变化率的正弦曲线行为,虽然增长率总体下降,但印度和日本等一些国家比其他国家更容易出现增长率上升。
同样,想象死亡案例总是分析新冠肺炎行动的一个更安全的赌注。因此,对死亡人数重复同样的步骤会给我们—
y 轴是 5 天期间死亡率(%)的变化率,用 3 天滚动平均值平滑
我们在这里看到一些惊人的启示。同样,死亡人数的变化率普遍下降。然而,日本的情况令人担忧,在过去的近 10 天里,变化的速度越来越快。同样,美国也开始经历变化率的增加。
关键要点
在疫情的情况下,数据可视化需要高度的正念和谨慎。我们必须意识到,通过在公共领域分享作品,我们冒着误导人们和在大众中煽动恐惧的风险。否则,目标应该是让人们意识到并帮助决策,以在危机情况下实现最佳的健康、福祉和经济繁荣。以下是收集到的一些关键点—
- 数据一下载, 探索 it, 理解 it,获取 上下文 。想象一下如何最好地利用它来迎合你心目中的基于数据的调查。在我的分析工作中,我使用了两个不同的数据库来帮助我。
- 注意图表的装饰方面,如颜色、形状、数字和大小。最好将 【死亡】**【恢复】**当前活跃病例 作为 总确诊病例 的子集显示,避免选择红色作为颜色强加不必要的警报和恐惧。在我的分析中,我展示了如何满足这些观点。
- 在试图汇总数据以发明任何指标度量时要小心谨慎。计算和分析 病死率 很诱人,但是,没人知道分母有多精确?确诊病例总数是否包括所有有症状的病例?确诊病例占总感染病例的比例是多少?因此,除了简单的增长率之外,我的工作中没有应用任何汇总。
- 由于不同国家有不同的数据收集方法、获得护理的机会和护理质量以及检测包的可获得性,因此不一致,跨国比较可能有风险。此外,平均人口年龄,免疫力和空气质量,以及健康习惯加在一起造成了不一致。在我的研究中进行的跨国分析试图忽略一些外部因素,因为我们只是在 n 个病例已经登记后才开始可视化,所有国家都来自一个共同的点。对数据进行了平滑处理,以进一步减少不一致性。
所有这些图形和数据库的源代码都可以在我的 github 库中找到。
免责声明
迈向数据科学 是一份主要基于数据科学和机器学习研究的媒体出版物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
餐馆收入预测
开发预测餐馆收入的经典模型
餐馆是一个国家经济和社会的重要组成部分。无论是为了社交聚会,还是为了吃快餐,我们大多数人都至少经历过一次拜访。随着最近弹出式餐馆和快餐车的兴起,企业主必须弄清楚何时何地开设新餐馆,因为这样做需要花费大量的时间、精力和资金。这就带来了寻找开一家新餐馆的最佳时间和地点的问题。拥有许多大型连锁餐厅的 TFI 在 Kaggle 上提供了他们餐厅收入预测的人口统计、房地产和商业数据。这里的挑战是建立一个健壮的模型,能够预测餐馆的收入。
数据
看了一下数据,训练集中有 137 个样本,测试集中有 10 万个样本。这非常有趣,因为数据的分布通常是相反的。这里的目标是基于训练集中的 137 个样本对收入进行建模,并查看该模型在测试集中的 100,000 个样本上的表现如何。每个样本的数据字段包括样本中每个餐厅的唯一餐厅 ID、餐厅的开业日期、城市、城市组、餐厅类型、几个非任意 P 变量以及作为目标变量的收入。对这个带有噪声的小训练数据集使用复杂模型将导致模型过度适应数据集。为了防止这种情况发生,肯定需要使用线性回归的正则化技术。
空值
简单查看一下训练数据后,似乎没有空值,这是一件好事。然而,对于 P 变量,情况可能并非如此,我们将在后面的数据探索中看到这一点。
数据预处理和探索特性
类型
上面的两个图显示了训练集和测试集中餐馆类型的数量。仔细看,在训练集中似乎没有出现一个“MB”类型。“MB”标牌代表流动餐馆,“DT”标牌代表得来速餐馆。由于移动餐馆与免下车餐馆的关系比直营餐馆和美食广场更密切,因此测试集中的“MB”样本被替换为“DT”类型。
城市集团
“城市组”功能似乎不需要任何更改。训练集的“大城市”样本略多于“其他”样本,但这在我们创建模型时应该不成问题。这也应该是直观的,餐馆在城市的收入比其他地区。
城市
(df['City'].nunique(), test_df['City'].nunique())
Out[10]: (34, 57)
对于“城市”功能,测试集中似乎存在不在训练集中的城市。还值得注意的是,一些非任意 P 变量已经包含地理位置信息,因此两个数据集都删除了整个“城市”特征。
开业日期
import datetime
df.drop('Id',axis=1,inplace=True)
df['Open Date'] = pd.to_datetime(df['Open Date'])
test_df['Open Date'] = pd.to_datetime(test_df['Open Date'])
launch_date = datetime.datetime(2015, 3, 23)
*# scale days open*
df['Days Open'] = (launch_date - df['Open Date']).dt.days / 1000
test_df['Days Open'] = (launch_date - test_df['Open Date']).dt.days / 1000
df.drop('Open Date', axis=1, inplace=True)
test_df.drop('Open Date', axis=1, inplace=True)
开业日期是餐馆第一次开业的日期。这在预测收入方面没有多大用处,但知道餐馆从开业之日起营业了多长时间会很有用。出于这个原因,我决定使用 2015 年 3 月 23 日作为比较日期来计算餐厅已经营业的天数。然后,我选择将开放的天数缩减 1000 倍,以略微提高模型性能。
P-变量
该数据有 37 个 p 变量,它们都是混淆数据。根据 Kaggle 竞赛页面上的数据字段描述,这些要素包含人口统计数据、房地产数据和商业数据。
最初,我认为 p 变量是数字特征,但在阅读了比赛中的一些讨论后,发现其中一些特征实际上是使用整数编码的分类数据。更有趣的是,这些特性的大部分值为零。再一次,在深入讨论之后,人们得出结论,这些零值实际上是空值,如上图所示。通过链式方程(也称为 MICE)的多变量插补用于替换这些特征中的缺失值。它的工作方式是使用整个可用数据集来估计缺失值。
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
imp_train = IterativeImputer(max_iter=30, missing_values=0, sample_posterior=True, min_value=1, random_state=37)
imp_test = IterativeImputer(max_iter=30, missing_values=0, sample_posterior=True, min_value=1, random_state=23)
p_data = ['P'+str(i) for i **in** range(1,38)]
df[p_data] = np.round(imp_train.fit_transform(df[p_data]))
test_df[p_data] = np.round(imp_test.fit_transform(test_df[p_data]))
分别对训练集和测试集的所有 p 变量使用估算器。在估算者取平均值之前,缺失值被估算几次。在将这些平均值输入模型之前,需要将其四舍五入为最接近的整数。
一个热编码
为了处理数据中的对象类型,将使用一种热编码来将这些特征转换成可以提供给机器学习模型的数字形式。虚拟编码也可用于避免冗余。将被编码的要素是“类型”和“城市组”,因为它们是数据集中仅有的对象类型。
columnsToEncode = df.select_dtypes(include=[object]).columns
df = pd.get_dummies(df, columns=columnsToEncode, drop_first=False)
test_df = pd.get_dummies(test_df, columns=columnsToEncode, drop_first=False)
目标变量分布
从分布来看,收入是右偏的。似乎也有异常值,这将导致模型训练中的问题。由于我们将试验线性模型,目标变量将被转换为正态分布,以改进模型解释。目标变量已进行了对数变换,因此最终预测将需要进行指数运算,以将结果重新调整回正常值。
模型实验
我决定尝试的模型是几种不同的线性模型,KNN,随机森林和梯度增强模型。这里的目标是找到最好的超调模型来集成最终模型。在我们训练任何模型之前,我们将把训练集分成训练集和验证集。
df['revenue'] = np.log1p(df['revenue'])
X, y = df.drop('revenue', axis=1), df['revenue']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=118)
岭线性模型
岭回归是一种正则化的线性模型。如前所述,需要使用正则化技术来防止过度拟合,特别是因为我们的训练集非常小。在我们在训练上训练一个脊模型之前,我们需要找到模型的最优参数。为了做到这一点,网格搜索和 k-fold 交叉验证被用来寻找导致最佳分数的最佳参数。
然后,使用训练集和测试集将最佳参数用于模型评估。这里的 RMSE 实际上是 RMSLE,因为我们已经取了目标变量的对数。
套索线性模型
现在我们对套索模型重复同样的步骤。套索模型的工作方式不同于岭模型,因为它缩小了不太重要的要素的系数。这可以在稍后的特征重要性图中看到。
我们可以看到,lasso 模型比仅使用“开放天数”特征的 ridge 模型概括得更好。它能够实现与使用所有特征的岭模型几乎相同的测试误差,这显示了这些正则化技术的真正潜力。
弹性网
ElasticNet 是一个结合了 ridge 和 lasso 正则化技术的线性模型。我们将使用 ElasticNetCV 通过交叉验证来选择最佳的混合模型。
使用弹性网模型几乎没有改善。我们可以看到线性模型之间的训练分数和测试分数都差不多。
在特征重要性方面,弹性模型减少了 72%的特征。即使有这种减少,该模型似乎也没有给出相对于脊或套索模型的改进的分数。这可能是由于小数据集和线性模型倾向于过度拟合。
KNN
对于 KNN,我们将使用 sklearn 的 KNeighborsRegressor。我们应用相同的过程来寻找最佳邻居参数。
令人惊讶的是,在测试集上,KNN 模型似乎比线性模型表现得好一点。
随机森林
随机森林是非常强大的模型,与袋装决策树略有不同。与袋装树不同,随机森林会随机选择一个要素子集,并在每个节点找到要分割的最佳要素,而袋装树则考虑在每个节点使用所有要素进行分割。随机森林还提供独特的超参数来减少过度拟合。我们将基于这些超参数中的几个来调整我们的模型。
我们可以看到,与上面使用的线性模型和 KNN 相比,训练分数有了显著提高。该模型还能够使用几乎所有的数据来实现这一点,如下面的特征重要性图所示。
LightGBM
LightGBM 为决策树提供了增强功能。它是 XGBoost 的一个很好的替代品,我们将在后面测试它。
根据训练分数,由于测试分数没有提高,模型似乎过度适应了训练集。稍后在我们的系综中包含这个模型可能不是最佳的。
XGBoost
XGBoost 是决策树的另一种提升算法。让我们来看看在优化超参数之后它与 LightGBM 相比如何。
该模型似乎没有 LightGBM 那样过度拟合。训练和测试分数似乎也低于随机森林模型。这解释了为什么这个模型在任何问题设置中都被大量使用。
在增强模型中很容易过度拟合,因此我们将添加早期停止参数以减少过度拟合。这给了我们一个更好的模型,仍然能够很好地概括测试集。
组装
根据上述模型的实验,很明显,线性模型和 KNN 不是该数据集的最佳模型。因此,它们不会被用作合奏的一部分。正如我们从上面的训练和测试错误中看到的,集成的最佳模型是随机森林和 XGBoost 模型。我决定使用随机森林集合,因为在这个场景中,boosting 模型有过度拟合的趋势,如 LightGBM 模型所示。对于合奏,我决定使用堆叠合奏。这样做的好处是创建一个单一的模型,该模型具有几个基本模型的良好性能。基本模型是不同的调整随机森林模型,元模型将是一个简单的模型,如线性回归。
我在整个数据集上拟合了堆叠模型,并根据 Kaggle 私人排行榜进行了测试。这款车型表现惊人,以 1741680.77896 的 RMSE 分数在私人排行榜上排名第四。作为参考,私人排行榜的第一名解决方案是 RMSE 1727811.48553。
得分
挑战和经验教训
最初,我没有为这个项目计划很多事情。在我阅读 Kaggle 竞赛中的一些讨论之前,我假设 p 变量实际上是数值。考虑到这一点,我对这些变量进行了对数转换,最终使线性模型更好地预测了目标变量。这是有意义的,因为每个特征都是归一化的,使得线性模型更容易预测。在发现 p 变量是有许多缺失值的分类变量后,插补是一个好得多的方法。这带来了一个教训,即理解您正在处理的数据非常重要,尤其是如果它是一个小数据集。我也试验过许多模型,手动调整超参数,直到我发现网格搜索在寻找最佳模型时节省了时间和精力。这些只是我在处理这个数据集时学到的一些东西。未来可能尝试的几件事是根据相关特征拟合模型,并包括更多样化的模型集合。
参考
Python 中的 RESTful APIs
什么是 RESTful APIs 和在 Python 中实现 GET
API 是两个软件之间的假想契约。Web APIs 使得跨语言应用程序能够很好地工作。
应用程序编程接口通常用于从远程网站检索数据。为了向远程 web 服务器发出请求并检索数据,我们使用了提供 API 的 URL 端点。每个 URL 被称为一个请求,被发回的数据被称为一个响应。
RESTful API 是一个应用程序接口,它使用 HTTP 请求来获取、上传、发布和删除数据。基于 REST 的交互使用熟悉 HTTP 的任何人都熟悉的约束。并且交互使用标准的 HTTP 状态代码来传达它们的状态。
为什么使用 API 而不是可以下载的静态数据集?
- 数据是不断变化的
- 您想要更大的数据池中的一小部分
API 请求
API 托管在 web 服务器上。
当我们在浏览器的地址栏中键入www.google.com时,计算机实际上是在向www.google.com服务器请求一个网页,然后它将这个网页返回给浏览器。
API 的工作方式非常相似,除了不是网络浏览器请求网页,而是程序请求数据。
这些数据以 JSON 格式返回。
为了获得数据,我们向 web 服务器发出请求。然后,服务器用数据进行回复。在 Python 中,我们利用requests
库来做这件事。
“请求”
最常用的请求是 GET 请求,用于检索数据。GET 请求将是本文的重点。
端点/路由
根端点是我们请求的 API 的起点。它完成了确定被请求的资源的路径。例如-https://www.google.com/maps。
/地图 是终点,是起始网址。
方法
- 获取—从服务器获取资源。
- POST —在服务器上创建新资源。
- 上传、修补—更新服务器上的请求。
- 删除—从服务器中删除资源。
状态代码
- ***1xx:信息:*传达传输协议级信息。
- ***2xx:成功:*客户的请求被成功接受。
- ***3xx:重定向:*客户端必须采取一些额外的动作来完成它们的请求。
- ***4xx:客户端错误:*客户端错误。
- ***5xx:服务器错误:*服务器端错误。
JSON 数据
JSON 是数据在 API 之间来回传递的主要格式,大多数 API 服务器将以 JSON 格式发送响应——包含一个 JSON 对象的单个字符串。
JSON 是一种将列表和字典等数据结构编码成字符串的方法,以确保它们易于被机器读取。
因此,列表和字典可以转换成 JSON,字符串可以转换成列表和字典。
JSON 看起来很像 Python 中的字典,存储了键值对。
进入 Python
我们将实现一个单一案例场景,它弥补了大多数 GET 请求的场景。
进口货
*import json
import requests
import urllib.parse*
一些 GET 请求由端点组成,这些端点具有不可选的路径参数,并且是端点的一部分,例如-**/volunteer//badge/****
需要将 volunteerID 和 badgeID 传入完整的 URL,以完成 GET 请求。
这就是我们利用urllib.parse
的地方。
假设我们在一个 JSON 文件中有一个 volunteerIDs 和 badgeIDs 的列表,我们希望将它输入到端点中,调用 API 并获得结果信息。
***#reading in the JSON file**
with open(‘volunteer_data.json’, ‘r’) as text_file_input:
data=text_file_input.read()**#loading that file as a JSON object**
obj = json.loads(data)*
下一步是设置 URL。
*API_ENDPOINT = ‘https://registeredvolunteers.xyz.com/volunteer/{}/badge/{}'*
现在,让我们运行一个for
循环来调用 API。
***#we pass on the arguments volunteerID and badgeID**
for i in obj:
r=requests.get(API_ENDPOINT.format(urllib.parse.quote(
i[‘volunteerID’]),
i[‘badgeID’])
)
print(r.text)**#outside for loop**
text_file_input.close()*
注意,如果你期待一个 JSON 输出,r.text
会给你一个由 JSON 对象组成的字符串。为了从中提取 JSON 对象,我们:
*output_json = json.loads(r.text)**#or directly use** r.json()*
要获得请求的状态代码和状态代码的原因,
*r.status_code
r.reason*
最终意见
上面的场景涵盖了 GET 请求的不同情况——是否需要传递 URL 参数,以及传入的这些参数是否存储在文件中;以及 GET 请求的不同属性,您可以研究这些属性来理解接收到的数据。
获得 REST APIs 的领先优势!
恢复多维空间的直觉
尝试使用数学和 python 来理解 N 维空间在对机器学习有用的上下文中的行为。
我见过的最强大的极光。马尔维克 2019。(私人图片)
如果我们不诅咒事物,我们就不是人类。作为被限制在三维世界中的生物,每当我们在可视化扩展到三维以上的数据方面遇到问题时,我们往往会责怪空间。从科学书籍和期刊论文到简单的博客文章和评论,“维度诅咒”这个术语像咒语一样不断重复,几乎让我们相信,任何物体,只要其本质不仅仅是“3D”,我们的大脑就无法触及。
本文既不讨论数据可视化,也不试图符合高维空间不可理解的普遍观点。
恰恰相反:高维空间不是不可理解的。这很奇怪,也不太直观。幸运的是,利用一些数学工具,把它们作为一张“免费票”来获得更多的直觉。更准确地说,我们将展示三条“路线”,我们可以用它们来更好地感受“第二空间”中的事情是如何进行的
可能性的空间
我们经常听说优化问题中的一个可能的失败发生在优化器“陷入局部最小值”的时候。想象我们的任务只是最小化一个变量的函数,我们只能向两个方向移动:向左或向右。如果试图向任何方向移动都会使函数增大,我们会发现自己处于局部最小值。除非这也是一个全球最小值,否则我们有点不走运。
现在,考虑给空间增加一个维度。在二维空间中,即使我们在其中一个轴上找到了局部最小值,也总有机会在另一个轴上取得进展。空间中特定点的函数值达到极值(最小值或最大值)的情况称为临界点。如果这个点在一个轴上是最小值,但在另一个轴上是最大值,它被称为鞍点。
(全局)最小值(左)和鞍点(右)的示例。
鞍点为优化器提供了一个“逃跑”方向。虽然给定一个维度时不存在,但给定更多维度时,任何给定临界点是鞍点的可能性应该会增加。
为了说明这一点,让我们考虑所谓的 Hessian 矩阵,它是 f 关于所有自变量的二阶导数的矩阵。
由于 Hessian 矩阵是对称矩阵,我们可以对角化它。
临界点最小的条件是海森矩阵是正定的,这意味着 h₁,h₂,…,hₙ > 0。
假设 f 是一个复杂的函数,不偏向任何正值或负值,我们可以假设对于任何临界点, P(hᵢ) > 0 ,以及 *P(hᵢ) < 0,*为 *1/2。*此外,如果我们假设 hᵢ 不依赖于任何其他 hⱼ ,我们可以将 p(hᵢ) 视为独立事件,在这种情况下:
类似地,对于最大值:
我们的临界点是鞍点的可能性是,它既不是最大值也不是最小值。因此,我们可以看到:
因此,高维空间似乎是可能性的空间。维度的数量越多,就越有可能感觉到鞍点为优化器的工作提供了方向。
当然,因为我们可以找到不符合这个陈述的函数的例子,所以这个陈述不是证明。然而,如果函数 f 对它的自变量有某种复杂的依赖性,我们至少可以预期,维数越高,空间就越“宽容”(平均而言)。
超级大球
圆形、球形或超球形——对这些物体的数学描述都很简单。
这个方程描述的只是一组点到原点的距离小于或等于一个常数的点(不考虑维数)。可以看出,对于任意数量的维度,该物体的总体积(或超大体积)可以使用以下公式来计算:
观察它与 n 的比例关系,我们可以看到:
如果我们尝试为任意维数的单位超球( r = 1)绘制这个方程,会发生一件有趣的事情:
单位半径超球的体积。
正如我们所看到的,在最初的几秒钟里,球体的体积增加了。但是,一n5,就迅速下降到一个很小的数字。
单位超球在失去质量是真的吗?为了了解质量的去向,让我们定义一个密度参数:
其中ε用于定义任意厚度的“壳”。同样,将 r 设为 1,将ε从 0 扫到 1,我们可以得出一个有趣的观察结果:
N 维球的体积浓度。
随着维度数量的增长,事实证明几乎所有球的质量都集中在它的边界周围。
如果我们考虑从属于高维空间的某个邻域中抽取样本,那么高维空间的这一特性就特别重要。在电脑上,和马克·库利提供了有趣的插图,试图展示当 N 变高时会发生什么。感觉就好像空间的维度使空间发生了偏转,使得被限制的点想要逃离或者推向终点,就好像它们试图探索可用的额外自由度一样。
多维蛋糕
让我们考虑一个立方体蛋糕,我们想把它切成 N 片 N 片来创建一些小块。如果我们的蛋糕是一个三维立方体(我们现在将使用 K 来描述维度),我们可以将它分成的最大数量由以下序列描述:
在哪里
是二项式系数。
和以前一样,我们可以将数学扩展到更多的维度。
有一个尺寸为 K 的多维蛋糕和一把用于切片的多维刀,使用( K-1 )维超平面,计算“超块”的数量:
其中后一个公式是完全等价的,但是更容易计算。
现在,让我们看看超级件数将如何与 N 和 K 成比例。
import numpy as np
import pandas as pd
form itertools import productdef cake(n, K):
c = 0
for k in range(K + 1):
term = [(n + 1 - i) / i for i in range(1, k + 1)]
c += np.array(term).prod()
return cN = 10 # cuts
K = 10 # dimensions
p = list(product(range(1, N + 1), range(1, K + 1)))
X = pd.DataFrame(pd.DataFrame((p,)).to_numpy().reshape(N, K)
X.index = range(1, N + 1)
X.columns = range(1, K + 1)
C = X.applymap(lambda x: cake(x[0], x[1])).astype(int)
ns = X.applymap(lambda x: x[0])
ks = X.applymap(lambda x: x[1])
C_normed = C / (nx * ks)
N,K——蛋糕数(左):显示使用 N 次切割的 K 维空间的最大切片数。标准化蛋糕数 C/(N * K)显示了添加尺寸或切割时切片数的比例。
看左图,我们看到上面公式的直接结果。尽管它看起来接近指数,它仍然是一个多项式表达式。直觉上,维度越多或切得越多,我们能从蛋糕中产出的部分就越多。
但是,如果我们将 C 除以 N * K 的乘积进行归一化,我们可以看到,对于某些固定的切割次数,具有 N 的切片数量的增加不再那么快。换句话说,似乎空间被分割成更独特的区域的潜力在某种程度上是饱和的,并且对于任何数量的切割 K ,存在一个“最佳”维数 N ,空间“更喜欢”被分割。
考虑到,例如,对于密集的神经网络层,输出状态通过以下向量矩阵乘法获得:
其中 g 为激活函数,且
N 和 K 都可以操作。正如我们之前看到的,增加 K (也就是 x 的特征数量)或 N (也就是超平面的数量)会导致更多区域的定义,这些区域会对与这些片段相关联的 y 的独特“触发”模式做出贡献。我们拥有的片段越多,我们应该期望的性能越好,但同时增加 N 和 K 也意味着更多的操作和更大的内存占用。因此,如果对于给定的 N ,每增加一个额外维度的切片数量不再增长,那么就资源消耗而言,保持密集层较小可能是有利的?
结论
在这篇文章中,我们探讨了空间多维性的三个方面。由于我们无法将它可视化(我们甚至没有尝试…),我们利用一些数学机制来更深入地了解这个世界的奇怪行为。尽管没有任何终极证据的支持,但我们希望刚刚提出的数学推理能够激发一些灵感、直觉和想象力,这是在处理 N 维度时经常需要的东西。
如果你有你的想法或观点(或者你想指出一些不一致的地方),请在下面的评论中分享。
还会有更多…
我计划把文章带到下一个层次,并提供简短的视频教程。
如果您想了解关于视频和未来文章的更新,订阅我的 简讯 。你也可以通过填写表格让我知道你的期望。回头见!
利用深度学习恢复旧航拍图像
以感知损失函数和真实图像作为输入的超分辨率
介绍
在超分辨率的帮助下,我给我居住的城市的旧航拍照片带来了生命。使用高分辨率图像训练的神经网络,我能够创建细节,使旧的航空图像看起来质量更高。
原始图像在顶部,预测图像在底部。图片:马尔默市
超分辨率
超分辨率的工作原理是放大图像数据,并为其提供比使用双线性或最近邻插值放大时更多的细节。我相信你们中的很多人都尝试过在 Photoshop 中放大照片,并看到了模糊的结果。超分辨率和升迁完全不同。它以一种非常令人信服的方式编造从未有过的细节。
为了训练一个超分辨率模型,你需要一对描绘同一事物的图像,一个低分辨率,一个高分辨率。创建训练数据的常用方法是从模型中用作目标的高分辨率图像中生成低分辨率输入图像。这为您提供了具有相应像素的图像对——良好的训练数据。
我决定用一种稍微不同的方式来尝试。也许有更简单的方法?由于地理数据与地面上的位置相关,因此也与所有其他地理数据相关,我想我不必创建自己的训练数据,我已经有了我需要的数据。
由于我的数据是 1998 年拍摄的图像,而我从 2017 年开始在同一地区拍摄分辨率更高的图像,所以我已经有了“降级”的图像和目标。
这样我就可以得到所有我想修复的缺陷,包括那些我没有想到的或者那些我不能手工复制的缺陷。通过使用来自同一来源的数据,我后来想增强,我得到了所有自然发生的缺陷——模糊,色偏等。这可以让我不费吹灰之力就获得现成的训练数据。
如前所述,地理数据的一大优势是,一切都与地面上的一个点相关,并用坐标来描述它。这使得从不同数据集中剪切出具有完全相同范围的部分变得容易。在这种情况下,这意味着创建覆盖城市中同一区域的输入和目标图像。使用航空影像时会有一些潜在的问题,我将进一步讨论这些问题。
我使用的过程是基于 fast.ai 的 MOOC v3 的工作实例。最大的不同是数据扩充部分,在这里我使用了一组变换,这些变换以前给了我很好的航空影像效果。
数据
正射影像
正射影像是由飞机或无人机拍摄的几张重叠照片组成的图像。它经过校正,以创建类似地图的图像,可用于测量精确的距离和角度,就像在地图中一样。图像中的一切似乎都是从垂直的自上而下的视角拍摄的。
潜在的问题
正射影像的问题在于它们并不总是正交的。航空图像,尤其是旧的,没有足够的重叠。正是这种重叠使得每张照片的中心部分,也就是垂直于地面的部分,被用于制作最终的照片。缺少重叠,物体从某个角度被描绘。这是一个问题,尤其是对于其中有高层建筑的图像,导致屋顶从覆盖区偏移,建筑的立面变得可见。有时这是想要的效果,但大多数时候不是。在我的例子中,它导致输入图像的内容与目标图像不同,特别是在有高楼的区域。
来源:Pieter Kuiper,维基共享(公共领域)
当使用真实的低分辨率图像而不是生成的图像训练模型时,内容的差异仍然是一个问题。房屋被建造、拆除、道路被重绘、树木被种植等等。一个城市在 19 年里发生了很多事情,使得目标与投入不同。不过,这并没有引起我想象的那么大的问题。我的总体印象是,尽管存在差异,但该模型做得很好。
在为我的训练集选择区域时,我很小心地选择了这样的区域:a)存在于 1998 年,b)自那以后变化不大。
原始数据:
输入 1998 年的航拍影像(正交镶嵌图)(25cm/像素)
输入 2017 年的目标航拍影像(正交镶嵌图)(10cm/像素)
训练数据:
1 万对图像瓦片
每个瓦片为 500 x 500 像素,覆盖地面 50 x 50m = 10cm/像素
共 25 km
~ 5 GB 的数据
模型和培训
我不会详细讨论感知损失的概念,因为许多其他人对此做得更好:
贾斯廷·约翰逊等人关于感知损失的原始论文
Christopher Thomas 的深入文章
简而言之,对于像超分辨率这样的任务,感知损失函数是使用 GAN 的替代方案。它的相似之处在于,它使用第二个模型来决定第一个模型的表现——“它创造的东西像我们想要的东西吗?”。不同的是,第二个模型,鉴别器,在这个过程中没有被训练。在我的例子中,模型是在 ImageNet 上预先训练的用于图像分类的神经网络,VGG16。
来源:实时风格转换和超分辨率的感知损失:https://arxiv.org/abs/1603.08155
在这种情况下,主模型是 U-Net,其中编码器部分是预训练的 resnet34 架构。通过 VGG 获取预测值和目标值来拟合模型。然后,在 VGG 内部,我们比较它们的激活并计算损失。通过这种方式,我们可以得到模型表现如何的数字,例如,在应该有草地的地方创建一个草地,或者模型在生成一个有尖角的房子方面做得不好。
损失取决于模型如何预测特征和风格,而不仅仅是比较像素值。这有助于我们的模型知道什么是重要的。例如,一个建筑角可能不会占据图像中的许多像素,但对于图像的感知却非常关键。感知损失函数认识到这些像素的重要性。
超高分辨率使屋顶更清晰、更分明。左边是原始图像,后面是预测图像和目标图像。注意输入和目标之间的差异,以及模型如何模仿目标图像的风格,而不是内容。图片:马尔默市
在一个 16GB 的 GPU 上,10,000 个图像对的数据集花费了大约两个小时来训练总共 20 个时期。
结果和后处理
结果显示更明确的屋顶线和更少的噪音。植被通常显示更多细节,但有时看起来模糊不清。在带有大面积灰色区域(如道路)的图像拼贴中,颜色通常看起来有点淡。当创建一个用于推理的自动化工作流程时,我会加入一些基本的图像处理来给它们更多的对比度。
我相信有很多方法可以让模型表现得更好。如果有什么可以帮忙的,请随时通知我!
不幸的是,由于版权和隐私问题,我不能展示很多例子,但如果你是高分辨率航空影像的幸运拥有者,我建议你尝试一下。下面是这个项目中使用的代码的链接。
推断是使用与原始输入相同大小和分辨率的图块进行的。在创建它们的时候,我还做了一个空间参考文件(。wld)。
将预测图像保存为与。在 GIS 软件中使用时,wld 将预测图像与地面相关联。结果是一个与空间相关的超分辨率航空影像,可用作 web 地图或任何其他应用程序的背景。
结论
这太有趣了!1998 年的画面以一种我从未见过的方式鲜活起来。当然,它不是真实的,因为你无法提取从一开始就不存在的细节,而是它可能看起来的样子的再现。请记住,当模型进行预测时,它不知道目标是什么,只是知道或了解详细的航拍图像应该是什么样子。剩下的就是模特有资格的猜测或者说是幻觉/代入缺失的细节。这不是真的,但看起来很像。
我很惊讶这个模型表现得如此之好,尽管输入图像和目标图像之间的差异比用降级方法创建的要大得多。几乎没有进行任何预处理,只是将两个图像集的子集切割成小块。感知损失函数的使用有助于缩短训练时间,从而有望使更多拥有大量地理数据的市政当局或其他组织能够使用这样的项目。
我不知道内容的偏斜度和差异对模型的效率有多大影响。如果两个图像集都是真正正交的,或者如果我有早些年的高分辨率图像并在两个图像集之间获得较短的时间跨度,可能需要的训练数据会更少。不可避免的是,图像之间的东西会有所不同,即使是在建筑物保持不变的区域。我发现,在 1998 年和 2017 年,很少有汽车停在同一个地方。
Kaggle 上的笔记本链接:
https://www . ka ggle . com/peterahlstrom/super-resolution-aerial-images-fastai
作为电影评论推荐系统的受限玻尔兹曼机(下)
关于如何使用 Pytorch 创建用于电影分级预测的 Boltzmann 机器的技术演练
通过链接改编自 unsplash 的 Img
本文是如何构建一个受限波尔兹曼机器(RBM)作为推荐系统的第 2 部分。
在第一部分中,我们专注于数据处理,这里的重点是模型创建。你将学到的是如何从头开始创建一个 RBM 模型。它分为三个部分。
- 模型结构
- 模特培训
- 模型检验
📣📣这是一篇技术驱动的文章。现在让我们开始旅程🏃♀️🏃♂️.
- 模型构建
本质上,RBM 是一个概率图形模型。
为了构建模型架构,我们将为 RBM 创建一个类。在类中,定义 RBM 的所有参数,包括隐藏节点的数量、权重以及可见节点和隐藏节点的概率偏差。
有 4 个函数,第一个函数是初始化类,第二个函数是在给定可见节点的情况下采样隐藏节点的概率,第三个函数是在给定隐藏节点的情况下采样可见节点的概率,最后一个函数是训练模型。
1.1 init 函数
**在 init 函数中,我们将初始化所有需要优化的参数。**注意, nv 和 nh 分别是可见节点数和隐藏节点数。W 是可见节点和隐藏节点的权重。我们使用平均值为 0、方差为 1 的正态分布来初始化权重和偏差。 a 是给定可见节点时隐藏节点概率的偏差, b 是给定隐藏节点时可见节点概率的偏差。注意我们为批处理添加了一个维度,因为我们将在 Pytorch 中使用的函数不能接受只有一维的向量。
class RBM():
def __init__(self, nv, nh):
self.W = torch.randn(nh, nv)
self.a = torch.randn(1, nh)
self.b = torch.randn(1, nb)
1.2 隐藏节点采样功能
这个函数是关于在给定可见节点概率的情况下对隐藏节点进行采样。我们为什么需要这个?因为我们需要概率来采样隐藏节点的激活。
假设我们有 100 个隐藏节点,这个函数将对隐藏节点的激活进行采样,即按照一定的概率 p_h_given_v 激活它们。 p_h_given_v 是给定 v 的值,隐藏节点等于 1(激活)的概率。
注意,该函数接受参数 x ,这是可见节点的值。我们用 v 来计算隐藏节点的概率。记住, h 给定v(p _ h _ 给定 _v )的概率就是 v 的 sigmoid 激活。因此,我们将可见节点的值乘以权重,再加上隐藏节点的偏差。我们扩展了偏置 a 的尺寸,使其与 wx 具有相同的尺寸,从而将偏置添加到 wx 的每一行。
def sample_h(self, x):
wx = torch.mm(x, self.W.t())
activation = wx + self.a.expand(wx)
p_h_given_v =torch.sigmoid(activation)
reutrn p_h_given_v, torch.bernoulli(p_h_given_v)
注意返回的是 p_h_given_v ,以及采样的隐藏节点。这里,我们做了一个伯努利 RBM,因为我们预测了一个二元结果,即用户喜欢或不喜欢一部电影。假设有 100 个隐藏节点, p_h_given_v 是 100 个元素的向量,每个元素为每个隐藏节点被激活的概率,给定可见节点的值(即用户对电影的评分)。但问题是如何激活隐藏节点?这里我们使用伯努利采样。假设,对于一个隐藏节点,它在 p_h_given_v 中的概率是 70%。我们取 0 到 1 之间的一个随机数。如果低于 70%,我们将不会激活隐藏节点。通过对 p_h_given_v 中的所有隐藏节点重复伯努利采样,我们得到 0 和 1 的向量,其中 1 对应于要激活的隐藏节点。
这是吉布斯采样✨✨.需要的第一个函数
1.3 可见节点采样功能
**遵循同样的逻辑,我们创建了对可见节点进行采样的函数。**给定隐藏节点的值(1 或 0,激活与否),我们估计可见节点的概率 p_v_given_h ,即每个可见节点等于 1(被激活)的概率。
因为有 1682 个电影和 1682 个可见节点,我们有 1682 个概率的向量,每个概率对应于等于 1 的可见节点,给定隐藏节点的激活。我们使用伯努利采样来决定是否对这个可见节点进行采样。最后,函数返回可见节点的概率 p_v_given_h ,以及一个 1 和 0 的向量,其中 1 对应于要激活的可见节点。
def sample_v(self, y):
wy = torch.mm(y, self.W)
activation = wy + self.b.expand(wy)
p_v_given_h =torch.sigmoid(activation)
reutrn p_v_given_h, torch.bernoulli(p_v_given_h)
1.4 对比散度函数
RBM 是一个基于能源的模型,这意味着我们需要最小化能源函数。
能量函数取决于模型的权重,因此我们需要优化权重。另一方面,RBM 可以被视为一个概率图形模型,它需要最大化训练集的对数似然性。显然,对于任何神经网络,为了最小化能量或最大化对数似然,我们需要计算梯度。这里我们使用对比散度来近似似然梯度。
对比分歧是关于近似对数似然梯度。代替需要大量计算资源的梯度的直接计算,我们近似梯度。在训练过程中,我们朝着能量最小化的方向调整重量。类似于通过梯度下降最小化损失函数,其中我们更新权重以最小化损失,唯一的区别是我们使用对比散度算法来近似梯度。
具体来说,我们从输入向量 v0 开始,基于 *p_h_given_v,*的概率,我们在第一次迭代时采样第一组隐藏节点,并使用这些采样的隐藏节点来采样可见节点 v1 与 p_v_given_h. 重复这个过程 K 次,这就是关于 K 步对比发散的全部内容。
在这个函数中,我们将使用本文概述的算法更新权重、可见节点的偏差和隐藏节点的偏差。我强烈推荐这本RBM paper 如果你喜欢更深入的了解。
在函数内部, v0 是包含用户对所有电影的评级的输入向量。 vk 是从可见节点到隐藏节点进行 k 采样后得到的可见节点。 ph0 是给定 v0 的第一次迭代时隐藏节点概率等于 1 的向量。 phk 是给定可见节点 vk 在第k 次迭代时隐藏节点的概率。
def train(self, v0, vk, ph0, phk):
self.W += torch.mm(v0.t(), ph0) — torch.mm(vk.t(), phk)
self.b += torch.sum((v0 — vk), 0)
self.a += torch.sum((ph0 — phk), 0)
1.5 RBM 对象创建
为了初始化 RBM,我们创建一个 RBM 类的对象。首先我们需要可见节点数,也就是电影总数。隐藏节点的数量对应于我们想要从电影中检测的特征的数量。很难确定最佳的功能数量。但是这个参数是可调的,所以我们从 100 开始。我们还定义了批量大小,这是我们用来更新权重的一批中的观察次数。我们再次从 100 开始。
nv = len(training_set[0])
nh = 100
batch_size = 100
rbm = RBM(nv, nh)
2.模特培训
祝贺你通过了第一部分,因为这是最难的部分👍👍。现在让我们来训练 RBM 模型。
我们首先将 nb_epoch 设置为 10。对于每个时期,所有观测值将进入网络,并在每批数据通过网络后更新权重。最后,我们得到最终的可见节点,这些节点对最初没有评级的电影有了新的评级。在每一批中,我们将进行 k 步对比散度来预测随机行走 k 步后的可见节点。因此,我们将有 3 个循环,一个用于历元迭代,一个用于批量迭代,最后一个用于对比发散。
对于损失函数,我们将测量训练集中预测评级和真实评级之间的差异。有几个选项,包括 RMSE,它是预测收视率和实际收视率之间的平方差的均值的根,以及预测收视率和实际收视率之间的绝对差。我们在这里取一个绝对的差值。
在批处理循环中,我们有输入向量 vk ,它将通过对比散度进行更新,并在随机行走 k 步后作为 Gibbs 采样的输出。但开始时, vk 是一批用户所有评分的输入批次。 v0 是将与预测值进行比较的目标值,预测值是该批用户已经评定的等级。 ph 0 是给定可见节点 v0 时隐藏节点的初始概率。
在对比发散循环中,我们将进行吉布斯采样。基本上,它包括建立 Gibbs 链,这是从可见节点到隐藏节点的几次往返。在每一轮中,可见节点被更新以获得良好的预测。从可见节点 vk 开始,我们用伯努利采样法对隐藏节点进行采样。在 10 次随机行走结束时,我们得到第 10 个采样的可见节点。请注意,我们不会对 RBM 进行等级为-1 的培训,这些等级在开始时并不作为真实等级。
利用 v0 、 vk、ph0、phk ,我们可以应用训练函数来更新权重和偏差。最终,与电影特征最相关的概率将获得最大的权重,从而导致正确的预测。在每一批结束时,我们记录训练损失。同样,我们只记录已经存在的评级损失。
nb_epoch = 10
for epoch in range(1, nb_epoch+1):
train_loss = 0
s = 0.
for id_user in range(0, nb_users — batch_size, 100):
vk = training_set[id_user: id_user+batch_size]
v0 = training_set[id_user: id_user+batch_size]
ph0, = rbm.sample_h(v0)
for k in range(10):
_, hk = rbm.sample_h(vk)
_, vk = rbm.sample_v(hk)
vk[v0<0] = v0[v0<0]
phk, _ = rbm.sample_h(vk)
rbm.train(v0, vk, ph0, phk)
train_loss += torch.mean(torch.abs(v0[v0>0]-vk[v0>0]))
s += 1
print(‘epoch: ‘+str(epoch)+’ loss: ‘+str(train_loss/s))
经过 10 个历元迭代的训练,我们得到了一个 0.15 的损失。相当准确的✌✌.
3.模型测试
与训练循环相比,我们去除了历元迭代和批量迭代。我们将通过 RBM 循环每个观测值,并逐个进行预测,累积每次预测的损失。
注意下面,我们使用训练集作为输入来激活 RBM,同样的训练集用于训练 RBM。但不同的是,在测试阶段,我们没有删除用户最初没有评级的评级,因为这些是用于测试目的的模型的未知输入。还要注意,我们没有像在训练阶段那样进行 10 步随机行走。这是因为对于获得最佳预测的测试,1 步优于 10 次迭代。
test_loss = 0
s = 0.
for id_user in range(0, nb_users):
v_input = training_set[id_user: id_user+1]
v_target = test_set[id_user: id_user+1]
if len(v_target(v_target>=0)):
_, h = rbm.sample_h(v_input)
_, v_input = rbm.sample_v(h)
test_loss += torch.mean(torch.abs(v_target[v_target>0]-
v_input[v_target>0]))
s += 1
print(‘test loss: ‘ +str(test_loss/s))
太好了。我们获得的损失为 0.16 ,接近训练损失,表明轻微过度拟合。
仅此而已。希望这能让你了解如何创建一个 RBM 作为推荐系统。如果需要源代码,请访问我的 Github 页面🤞🤞。
作为电影评论推荐系统的受限玻尔兹曼机器创造(上)
关于受限波尔兹曼机器的直观介绍以及使用电影分级数据进行模型训练的详细数据处理步骤
通过链接改编自 unsplash 的 Img
这是如何建立一个受限波尔兹曼机器(RBM)作为推荐系统的第一部分。这里重点是数据处理。
您将学习如何将原始电影分级数据转换为准备训练 RBM 模型的数据。它分为三个部分。
- RBM 简介
- 问题陈述
- 数据处理
现在让我们开始旅程🏃♂️🏃♀️.
- RBM 简介
首先,让我们从玻尔兹曼机(BM)说起。BM 是一种无监督的神经网络。如图 1 所示,BM 有三个明显的特征。
- 没有输出图层
- 连接之间没有方向
- 每个神经元彼此紧密相连,甚至在输入节点(可见节点)之间也是如此
图 1 玻尔兹曼机器图(作者创建的 Img)
为什么 BM 这么特别?从根本上说,BM 并不期待投入。相反,它自己生成模型的状态或值。因此,BM 是一个生成性模型,而不是确定性模型。BM 不区分可见节点和隐藏节点。可见节点只是我们度量值的地方。
然而,BM 有一个问题。随着节点数量的增加,连接的数量呈指数增长,这使得不可能计算完整的 BM。因此,建议采用 RBM,如图 2 所示。
图 2 受限玻尔兹曼机器图(作者创建的 Img)
与完全 BM 相比,RBM 不允许隐藏节点之间的连接和可见节点之间的连接。这是唯一的区别📣📣。
通过训练过程,我们向 RBM 输入大量数据,RBM 学会了如何分配每个隐藏节点来表示电影的特征,如流派、演员、导演等。换句话说,调整每个节点的权重,使得隐藏节点更好地反映特征。
具体来说,RBM 将接受从可见节点到隐藏节点的输入。它尝试基于隐藏节点值来重构输入值。如果重构值不正确,则调整权重,RBM 再次重构输入。最后,RBM 被训练成最能代表生成所有数据的系统。好处是所有权重都经过优化,RBM 可以了解系统的正常和异常情况。
2.问题陈述
给出大量的电影分级数据来建立 RBM。任务是预测一个用户喜欢一部电影是 1,不喜欢是 0。
3.数据处理
数据 MovieLens 100K 电影收视率来自群镜头研究这里。简单看一下图 3 中的数据, Movies 数据包含电影的名称和类型, Ratings 数据包含用户 ID、电影 ID、从 0 到 5 的用户评级和时间戳, User 数据包含用户 ID、性别、年龄、工作代码和邮政编码。
图 3 源数据集片段
3.1 导入数据
数据集包含 80,000 行训练集和 20,000 行测试集。让我们读一读。具体来说,
training_set = pd.read_csv(‘ml-100k/u1.base’, delimiter = ‘\t’)
training_set = np.array(training_set, dtype = ‘int’)test_set = pd.read_csv(‘ml-100k/u1.test’, delimiter = ‘\t’)
test_set = np.array(test_set, dtype = ‘int’)
**注意,我们将 Dataframe 转换为 Numpy 数组,因为我们将使用 Pytorch 张量,它需要数组作为输入。**图 4 显示了训练/测试集,包括用户 ID、电影 ID、评级和时间戳(对于模型训练是不可逆的)。
图 4 训练和测试数据集片段
3.2 数据结构创建
**为了准备训练/测试数据,我们需要以数组格式创建训练/测试集,每行代表一个用户,行中的每个单元格代表每部电影的评级。**这是 RBM 的预期输入。
为此,我们需要将用户总数作为行号,将电影总数作为列号。
nb_users = int(max(max(training_set[:, 0]), max(test_set[:, 0])))
nb_movies = int(max(max(training_set[:, 1]), max(test_set[:, 1])))
我们创建了一个数据转换函数,它返回一个列表列表。每个子列表代表一个用户对所有电影的评级。如果用户没有对电影进行分级,则将分级初始化为 0。
def convert(data):
new_data = []
for id_users in range(1, nb_users + 1):
id_movies = data[:,1][data[:,0] == id_users]
id_ratings = data[:,2][data[:,0] == id_users]
ratings = np.zeros(nb_movies)
ratings[id_movies — 1] = id_ratings
new_data.append(list(ratings))
return new_data
通过上面的转换,我们转换了训练集和测试集。
training_set = convert(training_set)
test_set = convert(test_set)
图 5 显示了最终的训练集。同样,每行包含用户对所有电影的评级。
图 5 最终训练数据集的片段
最后,我们将 list 类型的列表转换为张量**,因为我们将使用 Pytorch 构建 RBM。**
training_set = torch.FloatTensor(training_set)
test_set = torch.FloatTensor(test_set)
3.3 二进制数据转换
我们的任务是预测用户是否喜欢电影为 1,不喜欢为 0。RBM 将采用用户的电影评级,并试图预测未被用户评级的电影。因为要预测的评级是根据原始输入计算的,所以我们必须以一致的方式保持输入评级和预测评级。
具体来说,先前设置为 0 的评级被重置为-1,给出 1 或 2 的电影被设置为 0(不喜欢),评级超过 3 的电影被设置为 1(喜欢)。
training_set[training_set == 0] = -1
training_set[training_set == 1] = 0
training_set[training_set == 2] = 0
training_set[training_set >= 3] = 1test_set[test_set == 0] = -1
test_set[test_set == 1] = 0
test_set[test_set == 2] = 0
test_set[test_set >= 3] = 1
太好了。我们成功地将原始评级数据转换为二进制评级数据,准备好训练模型。
太好了!这就是第 1 部分的全部内容。接下来的 篇 将一步步走完如何打造一个 RBM。如果需要源代码,请访问我的Github页面🤞🤞。
为了更大的利益重组社交媒体平台
如果我们通过从零开始重新构建算法来重组社交媒体空间,以实现更好、更健康的公共辩论,会怎么样?
来源:艾琳娜·阿布拉热维奇/Shutterstock.com
从俄罗斯影响美国选举的虚假信息运动到假新闻和过滤泡沫,许多人认为社交媒体平台不再有利于健康的公共话语。
结果,数百家公司现在联合抵制价值数百万美元的脸书广告。抵制的目的?坚持认为社交媒体平台在监控仇恨言论方面做得更好。
这些公司和其他个人一样,认为这些社交媒体平台在我们的国家辩论中发挥着关键作用。随着这种强大的力量而来的是以积极的方式引导这些辩论的责任。
推荐引擎如何鼓励极端主义
这里有一个想法:如果我们通过从头开始重建算法来重组空间呢?
我们已经写了算法的公平性和组织如何在收集数据的早期阶段最好地避免有偏见的数据分析。但是现在我们要特别关注一个算法:推荐引擎。
根据许多媒体专家的观点,推荐引擎是社会两极分化的罪魁祸首。他们应该节省时间和寻找“正确选择”的书籍或文章阅读的焦虑。但通常它们最终会限制我们的选择和世界观。脸书和谷歌的个性化引擎并不是真正针对每个人的个性化。“为你推荐”是根据与你行为相似的用户提出推荐的算法。他们开发的目的不是真正的个性化,而是广告优化和推动收入。这是一个重要的区别。
这就是个性化引擎受到限制的原因。例如,一个纯粹出于对脸书的好奇而追随白人至上主义者的用户,将会在随后的一个月里获得充满极端主义内容的提要。或者真正想要阅读超出他们通常阅读习惯的内容的用户只能根据过去的偏好来阅读。或者为他的侄子买了婴儿礼物的用户现在被婴儿用品的日常销售淹没,尽管那些广告对他的日常生活没有用。
支持新算法的高质量网络数据
制造更好的个性化引擎的一个解决方案是收集高质量的网络数据并开发新的算法。
这里有几个例子:
- 耶鲁大学的一个团队设计了一个个性化引擎,目标是最小化两极分化的影响。他们的个性化引擎结果包括来自政治光谱两边的同等数量的文章。他们用来开发这种算法的数据集包括过去 30 天从 Webhose 的新闻 API 收集的新闻文章。
- 海是一个推荐引擎,它不像大多数推荐引擎那样从一个领域收集数据。相反,它整合了来自网飞、Hulu、Spotify 等一系列应用的数据集。它还使用人工智能根据你的个人品味和偏好进行推荐,而不是“与你相似的用户也喜欢什么。”
西蒙弗雷泽大学的另一组研究人员更进一步。他们决定尽可能地消除两极分化的内容——甚至在推荐引擎建议之前。他们在数据的帮助下建立了自己的算法,将真实的新闻文章与虚假的进行比较。这些假新闻来自俄罗斯互联网研究机构,而来自 Webhose 的真实新闻文章包括来自总共 172 个新闻来源的 2500 个数据项。研究的结果?一个假新闻检测器,可以在虚假信息发布之前识别出来。
努力让人们团结起来
像脸书和 Twitter 这样的社交媒体平台归根结底是受利润驱动的,它们的个性化引擎并不符合公众的最佳利益。但是健康的民主需要健康的空间——以及更健康的社交媒体平台——来进行公共辩论。对于 Webhose 来说,这意味着向组织提供网络数据,以便他们可以建立更公平的推荐引擎,将人们聚集在一起,而不是分裂他们。
如何建立一个像求职者跟踪系统(ATS)一样的简历推荐系统
一个人头。1000 份简历。先看哪个?
图片由经由 Shutterstock.com拍摄
2014 年,谷歌在其职业网站上有 7000 个职位空缺,在这些职位空缺中,该公司当年也收到了 300 万份简历。
现在,有很多简历需要筛选,只有不到 1%的申请人!毫无疑问,招聘是劳动密集型的,候选人越多,就越难筛选出最合格的候选人。随着公司的扩张和增长,招聘团队也随着公司的发展而增长,这可能会变得低效和昂贵。我们如何优化这种筛选这无数简历的劳动密集型过程?
目标
我们可以创建一个推荐系统,根据你的工作列表推荐最匹配的简历!
为此,我们将使用自然语言处理(NLP)技术来处理简历和工作列表,并按余弦相似度降序排列简历,以创建这个终极简历筛选工具!
自然语言处理是人工智能的一个分支,它允许计算机阅读、理解人类语言并从中获取意义。
图片由赖特工作室通过 Shutterstock.com 提供
方法
1.数据收集和简单 EDA
该数据集是在 Kaggle 上找到的,共有 8653 个求职者经历条目和 80000 个职位列表。请注意,这些申请人经历并不专门针对任何工作列表。
摘要
为了用这些数据制作一份简历,我将所有的工作经历按申请人 ID 连接起来。职位/经历不完整的简历被删除,以确保有足够的文本供以后建模。例如,对于applicant_id
10001,其工作描述显示为前三行的Nan
,因此这些观察值将被删除,不会在数据集中考虑。
employer
和salary
对我们的推荐引擎没有帮助,所以我们也将它们移除。
工作说明
对于工作描述,为了简单起见,我只在工作列表的数据框中保留了job_title
和job_description
。正如你在上面的栏目列表中看到的,有很多关于工作地点的信息(city
、State.Name
、State.Code
、Address
、Latitude
、Longitude
),我们不会用这些信息来推荐简历。其余的专栏要么似乎没有为我们的用例增加很多价值,要么有很多缺失的价值。
2.文本预处理
文本预处理是清理和准备文本数据的实践。使用 SpaCy 和 NLTK,简历和工作描述将进行如下预处理:
- 停止单词删除
- 词性标注
- 词汇化
- 仅字母字符
因为经过预处理后,长度较短的简历变得更短,也就是少于 20 个单词。我已经决定删除少于 23 个单词的简历,以便在数据集中仍然有至少 1000 份简历,确保有足够的文本供模型训练。
3.矢量器
为什么选择词频-逆文档频率(TF-IDF)而不是计数矢量器(又称词频)?
Count Vectorizer 让流行词占据主导地位。有些词可能在一份简历中和所有简历中被多次提及,这使得这些词成为“流行”词。篇幅较长的简历也更有可能不止一次包含这些“流行”词汇。Count Vectorizer 得出结论,简历中提到的这些“流行”词彼此更相似,因为它更强调这些流行词,即使它们在我们的上下文中可能并不重要。
**TF-IDF 更看重生僻字。**没有在所有简历中提及,但只在这两份简历中出现的单词——表明这些文档可能比其他文档更相似。
在清理完所有文本后,将 TF-IDF 放在简历上以比较简历之间的相似性。我们已经设置了 2 个单词和 3 个单词的短语(二元和三元),每个短语需要在至少 12 个文档中出现,以便在以后作为主题出现。
4.主题建模(降维)
我尝试了 3 种不同的主题建模技术:潜在狄利克雷分配(LDA),潜在语义分析(LSA)和非负矩阵分解(NMF)。
一开始,我使用 LDA 和 pyLDAvis 来衡量简历中合适的主题数量、放入 TF-IDF 中的 grams/terms 数量以及包含 grams/terms 的最小文档数量。然后,对于每种主题建模技术,我创建了一个 UMAP,并检查了每个主题中的术语。似乎 LDA 对于主题具有最好的可分性。
下面是使用 PyLDAvis 创建的图表,它呈现了我们的主题建模的全局视图。
皮尔戴维斯图表
如何解读 pyLDAvis 生成的图表?
在左侧面板上,是包含 8 个圆圈的主题间距离图,这表明我们的简历数据集中有 8 个主题。每个主题都由最相关/最重要的术语组成,显示在图表的右侧面板中。右侧面板显示了与每个主题最相关的前 10 个术语。对于主题 2,一些最相关的术语是“销售助理”、“客户服务”、“回答问题”和“收银机”,这听起来像是零售业中潜在的销售角色。最后,蓝色条表示总的术语频率,而红色条表示该主题中的估计术语频率。
PyLDAvis 图表的目标是什么?
简而言之,您希望您的 PyLDAvis 图表看起来与我们这里的相似。
主题间距离图(左)— 请注意,每个圆圈的间距相当大,大小也差不多,这意味着每个主题几乎均匀地分布在文档(简历)中,并且这些主题都有自己独特的术语。然而,由于人们可以有不同层次的经验,例如,3 年后从管理员到数据科学家,主题仍然不可避免地有很少的术语相互重叠。
与主题 2(右)最相关的前 10 个术语— 您可以看到红色条非常接近填满蓝色条,这意味着这些术语大多在该主题中,与其他主题几乎没有重叠。
5.基于余弦相似度的推荐系统
最后,我们需要在工作描述和简历之间找到某种相似性。我在争论是用点积还是余弦相似度。见下面我的思维过程。
**余弦相似度是两个向量之间夹角的余弦,它决定了两个向量是否大致指向同一方向。**在我们的案例中,这些术语(我们之前在 TFIDF 中定义的二元和三元语法)是否同时出现在简历和职位描述中。
点积是两个向量的欧几里得幅度与它们之间夹角的余弦的乘积。除了术语出现,简历中出现术语的频率也会提升匹配度。
我们应该使用哪种相似性度量?
点积听起来像是一个双赢的局面,我们将考虑这些术语是否出现以及在每个文档中出现的频率。这听起来可能是一个好主意,但回想一下,这是我们之前试图避免的缺点(TF vs . TF-IDF)——把重点放在这些经常提到的词上。
想象一下 a 和 b 之间的点积,就好像我们正在将 a 投影到 b 上(反之亦然),然后取投影长度为 a ( | a |)与长度为 b (| b |)的乘积。
- 当 a 与 b 正交时,点积为零。*a到 b 的投影产生一个零长度的向量,因此零相似度。*****
- 当 a 和b指向同一方向时,点积产生的最大值*。*****
- 当 a 和 b 指向相反方向时,点积产生最低值。****
点积将 大小 考虑在内,因此点积随着向量长度的增加而增加。为了归一化点积,然后将其除以归一化向量。输出是余弦相似度,它对于缩放是不变的,并且将值限制在-1 和 1 之间。余弦值为 0 表示这两个向量互成 90 度(正交)且不匹配。余弦值越接近 1,角度越小,向量之间的匹配度越大。
从上面的公式中可以看出, cos θ实际上就是两个向量的点积除以两个向量的长度(或幅度)的乘积。一般来说, cos θ根据矢量的方向来表示相似性。随着维数(也称为向量,也称为术语)的增加,这仍然成立,因此 cos θ是多维空间中一个有用的度量。**
例子
这是我找到的一份工作清单,“旧金山史泰博零售销售助理”。
********
未来的工作
将来,如果有更多的时间和对公司数据的访问,我愿意做以下事情来改进推荐引擎。
- 获取关于职位描述、候选人简历和其他内部信息的公司数据,例如,该角色的工作级别是什么?这是人事经理的角色吗?
- 一次对一个工作类别或角色的文本数据建模。由于该项目基于一个简历数据集,该数据集涉及广泛的工作职能,只有 1000 个观察值,因此主题主要是工作职能的更高层次的细分。当只对一个工作角色建模时,我们可以缩小主题范围,使其更具体地针对该角色,这可以带来更好的推荐引擎。
- 与招聘人员合作应用监督学习技术,使用筛选过的简历作为一个指标,表明这份简历是一份好的推荐。
- 与工程部门合作,应用用户反馈循环来持续改进推荐引擎。
用 Python 恢复筛选
Python 用于文本分析
分析空缺职位的候选人简历
图片由斯科特·格雷厄姆拍摄,可在 Unsplash 获得
介绍
写一份简历不是一件小事,尤其是在正确选择关键词的时候。人们花费数小时撰写和格式化完美的简历,希望它能被人才招聘专家阅读,并最终帮助他们获得工作面试。不幸的是,大约 75%提交的简历从未被人看到过。
由于大量的申请人和简历提交到职位发布,对于人才招聘专业人员来说,手动简历筛选过程变得繁琐、低效且耗时。因此,标准化的自动化筛选方法是必要的,以便根据背景、教育和专业经验更快地将合格的与不合格的候选人进行分类,从而以更高的效率和更准确的结果简化招聘流程。
筛选程序中的人工智能
人工智能以及文本挖掘和自然语言处理算法可以用于开发程序(即申请人跟踪系统),这些程序能够在几分钟内客观地筛选数千份简历,并根据阈值、特定标准或分数无偏见地确定最适合某个职位空缺的简历。
这些程序通常寻找特定的关键字;他们对简历进行分类和排名,以确定招聘人员应该进一步审查的工作申请。虽然每个公司可能都有自己的简历筛选系统,但对于候选人来说,了解他们如何根据他们申请的职位空缺来改进他们的关键词选择是至关重要的。
工程师简历筛选示例
由于我是工业和系统工程师,下面这个例子就落地在这个专业领域吧。在工业和系统工程领域,有广泛的集中领域,包括但不限于质量保证、运营管理、制造、供应链、物流、项目管理、数据分析和医疗保健系统。其中每一个都有相关的关键术语和概念,在工业和系统工程领域内众所周知。
尽管工业工程师必须具备每个集中领域的知识和背景,但通常建议他们在该领域的特定集中领域从事职业。此外,考虑到我们目前正处于专业化时代,招聘经理更有可能优先考虑在特定领域拥有强大背景、知识和经验的候选人,而不是“多面手”候选人。不幸的是,在候选人之间存在一种误解,即“擅长并精通”每一件事和在某一特定主题上“专业且高度熟练”。
对于以下示例,让我们构建一个简历筛选 Python 程序,该程序能够将关键字分类到六个不同的集中领域(例如,质量/六西格玛、运营管理、供应链、项目管理、数据分析和医疗保健系统),并确定工业和系统工程师简历中具有最高专业水平的一个。让我们在我的简历上测试一下,看看结果吧!
Python 代码
下面的 Python 代码将分为六个主要步骤。包含的注释行提供了简短的解释,并指导您完成编码过程。
步骤#1: PDF 文件打开、阅读和文本提取
步骤#2:文本清理
步骤#3:按区域设置的关键术语字典*
*免责声明:本词典每个领域中包含的关键术语是通过研究工业和系统工程职位招聘中最常见的关键术语获得的。该词典可以根据招聘经理的标准定制添加/删除关键术语。
步骤#4:计算每个区域的分数
步骤#5:用于最终分数创建的排序数据帧
分数汇总数据框
步骤#6:饼图创建
最终结果
简历筛选结果
成果解读
有意思。根据我的简历筛选结果,我的主要工业和系统工程集中领域是运营管理,其次是与数据分析相关的质量/六西格玛。结果显示了一定程度的医疗保健和项目管理角色的经验。
有两种可能的方法来分析这些结果。通过查看分数汇总数据框,招聘经理可以确定给定列表中每个集中区域包含了多少关键术语。另一方面,通过查看饼状图,招聘经理可以确定我的主要专注领域,并确定我在多大程度上可以被考虑从事与其他领域相关的工作。分数会受到每个集中区域的关键字数量的很大影响,这就是为什么强烈建议均匀分布关键字以避免对结果产生不希望的偏差。
如前所述,由招聘经理和人才获取专业人员来定义阈值、指标和分数,以确定候选人对于给定工作类型的资格。
现在轮到你了
试试看!在这里下载 Python 代码,加载 PDF 格式的简历并运行代码。根据简历找出你最强的工业和系统工程专长领域!
总结想法
在本教程中,我们已经经历了人工智能和文本挖掘在简历筛选程序中的许多可能应用之一。真正的申请人跟踪系统比这里内置的程序要复杂和先进得多;他们不仅浏览简历内容,还浏览简历格式。对于候选人来说,了解简历筛选系统如何击败他们,并让他们的简历被人才招聘专业人员查看是至关重要的。
科技使求职过程变得越来越容易和困难。大量的申请人和有限的机会迫使候选人写出能够击败“机器人”的优秀简历。强烈建议应聘者对简历关键词进行优化,以体现自己的软硬技能,避免包含流行语。不要放弃!努力完善你的简历,对你的技能和专业能力充满信心。祝你在求职过程中一切顺利!
— —
如果你觉得这篇文章有用,欢迎在 GitHub 上下载我的个人代码。也可以直接发邮件到rsalaza4@binghamton.edu找我,在LinkedIn找我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 个人资料 来探索我以前的文章。感谢阅读。
——罗伯特
简历—总结和匹配
艾玛·马修斯数字内容制作在 Unsplash 拍摄的照片
仅仅在17 周内,将近 5100 万美国人申请失业保险——这比大萧条期间申请失业保险的人数还要多。随后,找到一份符合自己兴趣的合适工作并不容易。因为企业已经将业务转移到网上,从而造成了机会的匮乏。
显而易见,如果你在这里,你正在努力增加获得梦想工作的机会。然而,在 indeed.com、LinkedIn.com 或其他招聘网站上寻找新工作却是一项艰巨的任务。这种寻找需要没完没了地阅读职位描述,不断更新简历以适应感兴趣的组织需求。
我向你提交这个,如果有一种方法可以让机器总结并匹配你的简历和职位描述,会怎么样?而且,它给你提供了一个方向,你需要在这个方向上付出额外的努力。
让我们看看这是可能的还是只是一个想法。
总结
“说说你自己吧?”——这是一个臭名昭著的问题,但在招聘人员中很流行。一位招聘人员要求(或者至少已经要求我)更多地了解候选人的兴趣,并评估你是否适合这个角色。在这种情况下,一个人想要总结他们的简历,而不是按时间顺序背诵你的简历。
让我们在 Jupyter 笔记本中导入一些库。
# Import summarize from gensim
from gensim.summarization.summarizer import summarizefrom gensim.summarization import keywords# Import the library# to convert MSword doc to txt for processing.import docx2txt
现在让我们阅读和理解你和你的有趣的立场。
# Store the resume in a variableresume = docx2txt.process(“babandeep.docx”)text_resume = str(resume)#Summarize the text with ratio 0.1 (10% of the total words.)summarize(text_resume, ratio=0.1)
丰富的有监督和无监督机器学习模型经验-回归:线性,逻辑,套索,岭,分类器:SVM,K-NN,决策树,感知器,随机梯度下降生成:朴素贝叶斯,LDA,集成:随机森林,XgBoost,GBM,无监督:K-means,DBSCAN,分层聚类,深度学习:CNN,RNN (LSTM,比尔斯特姆)。\ n 利用 python 中的 SVM、决策树、k-NN、逻辑回归(使用 t 检验、卡方检验、单变量和双变量分析)\ n 利用朴素贝叶斯分类器、集成(随机森林)、回归(决策树、逻辑)和分类器(SVM、k-NN),在 r 中具有 87%的准确性
听起来很有希望:它很好地概括了我的简历的要旨和我所具备的重要的解决问题的能力。
这里我用了 机器学习工程师 来试试这个。
text = input(“ Enter Job description : “) # Prompt for the Job description.# Convert text to string formattext = str(text)#Summarize the text with ratio 0.1 (10% of the total words.)summarize(text, ratio=0.1)
输出:
“Triplebyte 每月筛选和评估数千名工程师,为我们的合作伙伴公司寻找最佳候选人。\作为一名机器学习工程师,您将负责设计和运行实验的端到端流程,以便为大规模生产模型提供服务。\ n 我们的一些管道使用现成的组件,但我们也在实施来自最新研究论文的自定义模型和技术。\ n 我们的最终目标是收集最大的数据集,并以此建立世界上最好的技术招聘流程。”
有趣的是,这是我正在调查的事情,只需一秒钟,我就可以了解这家公司以及他们的期望。
相称的
所以,现在我知道这家公司在期待什么,这就引出了下一个令人困惑的问题:我符合他们对理想候选人的描述吗?
# recycle the text variable from summarizing# creating A list of texttext_list = [text_resume, text]from sklearn.feature_extraction.text import CountVectorizercv = CountVectorizer()count_matrix = cv.fit_transform(text_list)
CountVectorizer:将一组文本文档转换成一个令牌计数矩阵。该实现使用 scipy.sparse.csr_matrix 生成计数的稀疏表示。如果您不提供先验词典,并且不使用进行某种特征选择的分析器,那么特征的数量将等于通过分析数据找到的词汇大小。
余弦相似度是什么?
余弦相似性是一种度量标准,用于衡量文档的相似程度,而不考虑其大小。在数学上,它测量的是在多维空间中投影的两个向量之间的角度余弦。余弦相似性是有利的,因为即使两个相似的文档相距欧几里德距离很远(由于文档的大小),它们仍有可能更靠近在一起。角度越小,余弦相似度越高。
from sklearn.metrics.pairwise import cosine_similarity# get the match percentage
matchPercentage = cosine_similarity(count_matrix)[0][1] * 100matchPercentage = round(matchPercentage, 2) # round to two decimalprint(“Your resume matches about “+ str(matchPercentage)+ “% of the job description.”)# outputYour resume matches about 33.33% of the job description.#keywordsprint(keywords(text, ratio=0.25))
# gives you the keywords of the job description
哦!我不是很匹配这份工作(33.33%或只有 1/3),即使我有所有需要的库和调制的经验。我最初认为这是成为一名机器学习工程师的核心要求,然而,现在我知道我必须专注于什么才能在 TripleByte 获得面试机会。
这种情况下我能做什么?
到目前为止,我想到了两种方法:
- 要么用职位描述的总结来更新我的简历。
- 使用关键字并将其纳入我的简历中,使我的相似度得分达到 80%以上。
后面的部分为我节省了更多的时间,这也是本文的主旨。
如果这种方法在任何方面对你有帮助,或者如果你有任何我们可以从中得出的见解,请随意留下评论。
在接下来的任务中,我计划将复制粘贴职位描述的过程自动化为爬行并节省更多时间,并且只显示最匹配的职位描述。
参考资料:
- https://sci kit-learn . org/stable/modules/generated/sk learn . feature _ extraction . text . count vectorizer . html
- https://www . machine learning plus . com/NLP/Cosine-similarity/#:~:text = Cosine % 20 similarity % 20 is % 20a % 20 metric,in % 20a % 20 multi % 2d dimensional % 20 space。
零售分析:寻找替代品和补充品的新颖而直观的方式
零售分析:零售数据科学
零售(弗兰克·科尔多瓦在 Unsplash 上拍照)
零售业向顾客出售商品和服务。有了大量可用的消费者购买历史,我们可以应用数据分析来正确预测库存需求、供应链移动、商品放置、推荐商品之间的关系等,这就创造了零售分析这一术语。
零售分析的一个重要部分是找到面包和黄油搭配以及牙膏和牙刷搭配等物品之间的关系。替代品是用于同一目的的不同品牌的替代产品。替代品的例子可以是茶和咖啡或不同品牌的牙膏(Pepsodent 和高露洁)。这几项基本都是彼此的竞争对手。另一方面,补品是一起购买和使用的物品。这些商品有助于提升客户购物篮中彼此的销售额。补充的例子可以是面包和黄油或航班和出租车服务等。
了解这种关系有助于做出有数据支持的决策。确定替代物和补充物后的可能优势是-
- 商店中的物品摆放。互补物品可以放在一起/更近。
- 在电子商务网站中,每当购买物品时,推荐其赠品,因为这些是一起购买的物品。
- 在一个项目不可用时,推荐它的替代品。
- 提供该商品及其补充品的组合报价,以提高销售额或清理库存。
- 每当某个商品的价格上涨/下跌时,监控对其替代品的销售/需求的影响。这有助于做出有意识和有计划的定价决策。
关联规则挖掘是数据挖掘技术的一个分支,它引入了像支持度、置信度、提升度、确信度、先验算法这样的概念,有助于发现这样的关系。通过这篇博文,我打算提出一种替代的、直观的方法来寻找项目关系。因此,一个人不需要有任何先验知识,因为这是一种新颖的方式,没有任何先决条件。
为了演示算法的工作和有效性,我们将在 Kaggle 的 Instacart 数据集上运行所提出的方案。使用的代码可以从这里下载。
寻找补充
补充品是通常一起购买的物品“X”和“Y”。找到这种商品对的一种策略是,在所有顾客购物篮中,找到一起购买“X”和“Y”的次数与购买“X”和“Y”的次数的比率。
补码比率= (X ∩ Y)/(X ⋃ Y)
对于要成为补码的项目“X”和“Y ”,补码比率需要尽可能高。它的上限为 1。在所有的项目对中,我们将找到称赞率最高的项目对。
同样,从集合论中,我们知道,
集合 A 和集合 B 的并集(图像源
我们将从 Instacart 数据集找到跨部门的补充。我们先来看看数据集。
订单表快照
总共有 320 万份订单,这些订单中订购了 3240 万件商品。
产品表的快照
共有 49.6K 个不同的项目。
部门表快照
总共有 21 个部门。
接下来,我们将执行 orders 表的交叉连接,以查找商品一起购买的次数。我们还将它与 product 和 department 表连接起来,以查找产品的详细信息。按补码比率降序排列的最终输出表如下所示
结果快照(算法建议的补充)
让我们看看算法建议什么作为补充:
结果看起来真的很好。人们用碱化水购买甜叶菊透明甜味剂是有道理的,因为当与水混合时,几滴甜味剂会给它带来良好的味道。
类似地,人们更喜欢吃配有能量饮料的比萨饼和配有鹰嘴豆泥或洋葱蘸酱的皮塔饼或薯片。
寻找替代品
替代品是用于同一目的的不同品牌的替代产品。如果商品“X”和“Y”是彼此的直接竞争对手,并且人们通常会购买其中之一,那么它们就是替代品。一种商品价格的上涨或下跌不太可能以相反的方式影响其替代销售。
替代率=(X∩Y)/最小值(X,Y)
对于要替代的两个项目‘X’和‘Y’,我们倾向于替代率越低越好。
为什么公式中有最小值函数?
一些像香蕉或苹果这样的东西会很受欢迎,是许多篮子的一部分。最小函数有助于消除这种偏差,并使比较达到公平的标准。
我们将从 Instacart 数据集中找到同一部门的替代者。我们将执行 orders 表的交叉连接,以查找一起购买的商品与分开购买的商品的次数。我们还将它与 product 和 department 表连接起来,以查找产品的详细信息。按补码比率升序排序时,最终输出表如下所示
结果快照(算法建议的替代)
结果看起来不错。人们大多购买大型露天鸡蛋或有机大型棕色鸡蛋是有道理的。
同样,人们购买 2%的低脂牛奶或含有维生素 D 的有机牛奶或脱脂牛奶。
结论
通过这篇博文,我们找到了一种替代和直观的方法来寻找替代和补充。这些简单的指标给了我比寻找支持、信心、提升、信念或其他关联规则挖掘算法更好的结果。同样,这些指标非常直观,并且易于大规模实施。结果支持这些指标的良好性。数据集可以从 Kaggle 的 Instacart 数据集下载。使用的代码可以从这里下载。请点击这里查看我在零售分析上的另一篇有趣的帖子。
我的 Youtube 频道获取更多内容:
嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…
www.youtube.com](https://www.youtube.com/channel/UCg0PxC9ThQrbD9nM_FU1vWA)
关于作者-:
Abhishek Mungoli 是一位经验丰富的数据科学家,拥有 ML 领域的经验和计算机科学背景,跨越多个领域并具有解决问题的思维方式。擅长各种机器学习和零售业特有的优化问题。热衷于大规模实现机器学习模型,并通过博客、讲座、聚会和论文等方式分享知识。
我的动机总是把最困难的事情简化成最简单的版本。我喜欢解决问题、数据科学、产品开发和扩展解决方案。我喜欢在闲暇时间探索新的地方和健身。在 中 、Linkedin或insta gram关注我,查看我以前的帖子。我欢迎反馈和建设性的批评。我的一些博客-****
- 统计决定胜负的力量
- 以简单&直观的方式分解时间序列
- 挑哪个?GPU 计算 vs Apache Spark 扩展您的下一个大任务
- GPU 计算如何在工作中真正拯救了我?
- 信息论& KL 分歧第一部分和第二部分
- 使用 Apache Spark 处理维基百科,创建热点数据集
- 一种基于半监督嵌入的模糊聚类
- 比较哪个机器学习模型表现更好
零售分析:寻找季节性商品的排序
零售分析:零售数据科学
Aj Povey 在像素上拍摄的照片
零售业向顾客出售商品和服务。我有在零售行业工作的经验,也写过一些关于零售分析的博客,可以在这里找到。
零售分析通过分析客户的购买历史来做出基于数据的决策。在这篇博文中,我想强调影响销售的因素,并对最受这些因素影响的项目进行排名。
这些商品的销售受到各种因素的影响,比如-
雨伞的销量在雨季会更多,而冰淇淋的销量在夏季会更多。同样,促销/折扣或一些特殊事件,相同的百分比折扣可能导致项目“X”和“Y”的不同销售,这取决于它们的季节性。通过这篇博客,我打算建议一种根据季节性给物品排序的方法。这不是一件小事,它有自己的挑战。我会列出挑战和应对方法。敬请期待,阅读愉快。
为了证明该方法的工作和有效性,我们将在 Kaggle 的商店商品需求预测挑战赛上运行提议的方案。使用的代码可以从这里下载。
根据季节性对项目进行排序的挑战
1.销售规模
第一个挑战是不同商品的销售规模。商品“X”在正常季节的销量可能达到 10 件,在最有利的季节可能达到 100 件。而另一方面,在正常到最有利的季节中,一些其它商品“Y”的销售可能从 100 到 1000 不等。
2.不同项目的季节不同
不同的项目有不同的有利季节。例如,雨伞的最佳季节是雨季,而冰淇淋的最佳季节是夏季。同样,毛毯在冬天卖得更多,火鸡在感恩节卖得更多。
我们的目标是想出一种方法,能够解决所有这些挑战,并根据它们随季节的变化对项目进行排序。我们打算最终根据物品的季节性对它们进行排序。
季节性项目的排序方法
方法是-
- 首先,为每个项目找到一个月度季节指数。月指数是用月销售额除以平均销售额得到的。作为这一步的结果,我们得到每个月每个项目的 12 个值。由于月度季节性指数是比率,因此可以跨项目进行比较。
- 接下来,为每个项目计算季节指数的方差/标准差。作为这一步的结果,我们将得到每个项目的一个值,即每月季节性指数的方差/标准差。
- 根据项目的方差/标准差对项目进行排序。方差/标准差最大的项目是季节性最强的项目。
此外,由于这一点,我们得到了一个根据季节性排序的项目。
实施和测试该方法
我们将在 Kaggle 的商店商品需求预测挑战上测试该方法。我们先来看看数据集。
资料组
该数据集由 2013 年 1 月至 2017 年 12 月的商店商品销售数据组成。总共有 50 个项目和 10 个商店。
在本练习中,我们将筛选与商店 1 和 2017 年相对应的数据。过滤后的数据如下所示。
1 号店和 2017 年的数据
接下来,我们计算每个项目的月度季节指数。
用于合计销售额并计算商品月度季节性指数的 Python 代码
某项商品的月度季节性指数看起来像-
项目 1 的月度季节性指数
接下来,我们计算所有 50 个项目的月度指数的方差和标准差。按方差/标准差降序排列的项目的最终排名如下
根据每月季节性指数的变化对所有 50 个项目进行排名
该方法建议列表中的 项 47 最具季节性(易出现高方差) 项 5 最不具季节性。让我们把结果可视化来检查一下
销售&项目 5 月度季节性指数
第 5 项的销售额如何变化
销售&第 47 项月度季节指数
第 47 项的销售变化
从图中可以明显看出,第 47 项的销售偏离比第 5 项更大。与项目 5 的平坦曲线相比,项目 47 具有更多的峰值和谷值。此外,项目 47 的最低和最高月销售额之间有 101.9%的涨幅(最低 451 个单位,最高 911 个单位),而项目 5 的最低和最高月销售额之间只有 71.7%的涨幅(最低 407 个单位,最高 699 个单位)。因此,该算法在根据季节性对项目进行排序方面做得很好。该方法中季节性最强和最弱商品的图表和销售数据也表明了同样的情况。
我的 Youtube 频道获取更多内容:
嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…
www.youtube.com](https://www.youtube.com/channel/UCg0PxC9ThQrbD9nM_FU1vWA)
结论
在这篇博客文章中,我们设计了一种根据季节性对物品进行排序的方法。存在挑战,但这种方法能够解决这些问题。通过该方法得到的季节性最强和最弱商品的图表和销售数据证明了该方法的有效性。该数据集可从 Kaggle 的商店商品需求预测挑战中下载。使用的代码可以从这里下载。
关于作者:
Abhishek Mungoli 是一位经验丰富的数据科学家,拥有 ML 领域的经验和计算机科学背景,跨越多个领域并具有解决问题的思维方式。擅长各种机器学习和零售业特有的优化问题。热衷于大规模实现机器学习模型,并通过博客、讲座、聚会和论文等方式分享知识。
我的动机总是把最困难的事情简化成最简单的版本。我喜欢解决问题、数据科学、产品开发和扩展解决方案。我喜欢在闲暇时间探索新的地方和健身。在 Medium 、 Linkedin 或 Instagram 关注我,查看我的以前的帖子。我欢迎反馈和建设性的批评。我的一些博客-
- 零售分析:寻找替代品和补充品的新颖而直观的方式
- 统计决定胜负的力量
- 以简单直观的方式分解时间序列&
- 挑哪个?GPU 计算 vs Apache Spark 扩展您的下一个大任务
- GPU 计算如何在工作中拯救了我?
- 信息论& KL 分歧第一部分和第二部分
- 使用 Apache Spark 处理维基百科,创建热点数据集
- 一种基于半监督嵌入的模糊聚类
- 比较哪种机器学习模型表现更好
零售客户分析
在线零售商客户细分和分析
介绍
在本文中,我们将对一个在线零售店数据集进行探索性分析,以了解其客户。让我们假设,我们拥有一家经营得非常好的零售店,我们想找到一种高效和有效地扩展业务的方法。为了做到这一点,我们需要确保我们了解我们的客户,并根据我们客户的特定子集定制我们的营销或扩展工作。在这种情况下,主要的业务问题是“我如何以最有效的方式扩展我目前做得非常好的业务?”。支持主要业务目标的子问题可能是“为了获得最佳投资回报,我们可以为每个客户执行什么类型的营销计划?”。
关于数据
数据集是一个非常常见的数据集,可以在许多公开可用的数据源中找到,旨在用作在线零售商店数据的示例。每个变量的描述都是简单明了的。
数据收集和清理
缺少 1454 个“描述”和 135,080 个“客户 ID”值。保留缺失的“描述”值不会对分析产生任何影响,因为我们将专注于了解我们的客户。基于每个缺失的“CustomerID”代表一个新客户的假设(意味着缺失的“CustomerID”值对于数据集是唯一的),我们还可以假设缺失的“CustomerID”值也不会对我们的分析产生任何影响。
我们注意到“InvoiceDate”数据类型是 object,需要更新为 Date 数据类型。我们还可以从“InvoiceDate”变量中获取月份和年份,并创建带有“InvoiceMonth”和“InvoiceYear”的新列。
我们加载了在线商店数据集,并对其进行了少量清理。我们可以进一步分析客户。
数据探索
最初,我们将执行基本的探索性统计分析,以了解变量分布。此外,我们将了解我们在客户中的收入情况。谈到在线零售商店的商业模式,收入是最常见和最重要的指标之一。我们希望确保我们的收入增长,因为我们正在定义我们业务的可扩展性。
当我们查看月度收入增长时,我们意识到我们的数据集从 2010 年 12 月开始,一直到 2011 年 12 月。我们注意到收入在 2011 年 12 月左右下滑。我们需要了解这是由于客户没有购买我们的商品,还是与数据集中的问题有关。
根据 2011 年 12 月的数据,我们了解到该数据集不包括 2011 年 12 月 9 日之后的任何购买。我们需要确保在我们的分析和结论中考虑到这一点。
单独说明;我们可以看到,从 2011 年 9 月到 2011 年 12 月,收入稳步增长,11 月是收入最好的月份。
正如预期的那样,每月售出的商品、每月活跃用户和每月平均收入与每月收入增长呈正相关。
在大多数情况下,除了级别之外,我们看到新客户和现有客户的正收入增长和负收入增长是一致的。然而,当我们查看 2011 年 1 月至 2 月和 10 月至 11 月的收入时,我们发现即使现有客户收入增长,新客户收入却下降了。
客户细分
我们根据收入、活动、新客户和现有客户的月收入分析了我们的客户,我们肯定有一些可以采取行动的见解。我们还可以对客户进行细分,以便根据我们正在努力解决的主要业务问题来确定我们的行动目标。
我们将使用 RFM(近期、频率和货币价值)策略来分析和评估每个客户的价值,并相应地进一步细分他们。通过查看最近发生的事情,我们可以了解客户购买的时间、频率以及购买的频率,而货币价值可以让我们了解他们消费的频率。
我们将客户分为 4 个不同的类别,从 0 到 4。集群 0 中有 524 个客户,集群 1 中有 2157 个客户,集群 2 中有 632 个客户,集群 3 中有 1059 个客户。当我们比较最近时,聚类 0 是表现最好的客户集,而聚类 1 是表现最差的客户集。
我们可以进一步考察频率,并根据客户的购买频率对他们进行细分。
根据频率,分类 0 的客户最多,分类 2 的客户最少。基于这种划分,我们看到聚类 0 的客户频率最低,但客户数量最多。
最后,我们可以根据客户的货币价值对他们进行细分。
结论
通过新近性、频率、货币价值细分和我们对客户的探索性分析,我们可以进一步决定我们产品的购买周期,确定我们营销活动的优先顺序和定义。例如,我们可以查看我们当前的营销活动、库存购买策略和 1 月和 10 月的运营,看看我们是否可以吸引更多的新用户,以便将新用户的负收入增长转变为正收入增长。我们可以调查历史营销活动,以了解它们对每个新近性和频率群集的影响。我们可以进一步将此应用于我们的主要业务目标,以扩大业务规模。我们还可以为 RFM 的每个类别分配 1-10 分。例如,如果客户一年没有购物,他们的最近得分为 1,如果他们在上个月购物,他们的最近得分为 10。我们可以进一步将每个类别的所有分数相加,并为每个聚类创建一个客户价值。这些行动将极大地有助于我们在业务可扩展性方面取得成功。
零售预测(天气的影响)
为您的企业提供一些方便的基于 R 的统计数据
我最近和一个潜在的零售客户通了电话,他们表示怀疑天气影响了他们的销售。“完全正确,”我想,“人们对不同的天气会有不同的反应。当然可以。”这当然不是他们的主要关注点,更多的是好奇,但我仍然想知道我将如何着手调查这个问题(并通过快速转身产生一个有意义的答案)。
从他们的 POS 上可以很容易地获得汇总的销售数据,每天的天气数据也是可用的,按位置,从 BOM (每小时会更好,所以我们可以知道天气事件是发生在之前还是在工作时间内*——但现在保持事情简单)。*
很明显,这是一个统计学问题,而我这个数学呆子热衷于研究这个问题。但是,当然,在我们去那里之前,我必须思考“那又怎么样?”问题:
他们在此类调查中的投资会有什么回报?
这一知识能为哪些业务行动提供信息?
也许意识到他们可能会忙一天,可以让他们安排一个额外的员工。相反,在一个安静的日子里,他们可能会在展示中少放一些易腐的“小玩意”。
天气的影响(我们现在主要关注降雨)只是他们对导致销售波动的原因的更广泛理解的一个方面。每一个“位”信息,指导他们的业务优化,减少“惊喜”。这个特定“位”的即时值实际上取决于所发现的效应大小。因此,快速,低预算的调查将是出路。
我继续进行并生成了一些虚拟数据,供我们进行一个假想的(但仍然真实的)调查。
让我们首先保持我们的焦点非常简单。在下图中,每一天都是一个点。
“最佳拟合线”显示出非常轻微的上升趋势。我们可以通过统计来确定这一趋势。
在一年的时间里,平均日销售额增加了 20 (0.0539 * 365 = 19.6)。好样的。
但这种上升趋势可能只是因为有或多或少的雨天(以及对客户的相应影响),而不是你所有的辛勤工作!
在上图中,很难说雨天和非雨天是否有明显的区别。在下面的图表中,多雨的分布似乎稍微向右移动了一点(表明更多的销售)。
下图向我们展示了差异确实存在。
一般来说,雨天更有利于销售。我们可以通过另一个简单的回归来检测这是否具有“统计显著性”。
是的(p.value < 0.05).
If we were going to guess the number of sales, our results would certainly be more accurate if we included our rainy day feature. The trend (from the day_index) has also stayed significant -so we can say that the increasing trend is independent of the rate of rainy days.
It looks like rain adds 34.5 extra sales to a day. We could bring in the standard error measurement to qualify that statement a bit, by saying that, 大部分时间 (~95%的时间),下雨会给一天增加 23 到 45 的额外销售额(34 +/- 1.96*5.71)。
但是这种“额外的降雨”可能会被其他一些我们已经知道的因素减轻,比如一周中的某一天。
我们可以看到一个非常一致的模式。每一天都有不同的表现;而且,在这些天里,我们可以看到更高值的雨天。除了星期五。
下面的回归向我们展示了影响。
对于这些数字,我们的基本估计是一个不下雨的星期一(在我们时间线的开始)。我们可以看到,即使给定了一周中的某一天以及我们在时间轴上走了多远,雨仍然会产生“显著”的影响。
周二的销售额通常比周一多 21.9 倍。
周三通常比周一多 48.7 英镑,等等……
……无论哪一天下雨,通常都会增加 41.2 英镑的额外销售额。
所以现在,我们对下雨影响的猜测从 34.5 变成了 41.2 额外销售。
但是上面的模型没有考虑到这样一个事实:星期五**,下雨有不同的影响。我们需要添加一个工作日/雨天的“互动”。**
这里我们可以看到模型中的重要术语。
星期几系数略有变化。我们可以看到 rain 现在为任何一天增加了 56.2 的销售额。周五除外,周五导致销售额下降约 43.8(56.2–100)。
太棒了。
所以,这代表了我可以舒服地向客户展示的复杂程度。这也代表了“虚拟”销售数据中的全部效果(因为是我自己在编写数据时放进去的)。
还有更复杂的模型和更有趣的“特征”有待研究:
- 降雨量(或何时下雨)有影响吗?
- 连续几天下雨有影响吗?
- 忙碌的一天会影响第二天的销售吗?
此外,还有要问的“如果”问题,例如“如果我们在雨天叫一个额外的员工怎么办?这有什么影响?”
简单模型的好处是,你可以非常快速和(相对)容易地对你正在处理的效果大小有一个清晰的认识。
从那里,更容易确定增加调查是否可能导致更有利可图的商业决策,从而值得额外的投资。
通常,业务的其他方面也需要类似的基本可见性。
对于那些好奇的人,我的代码可以在下面找到。
通过在 GitHub 上创建一个帐户,为 Tadge-Analytics/天气对零售销售的影响的发展做出贡献。
github.com](https://github.com/Tadge-Analytics/weather-impact-on-retail-sales)**
原载于 2020 年 6 月 27 日 https://tadge-analytics.com.au。****
重新思考数据科学的持续集成
数据科学软件工程
软件工程中广泛使用的实践应该在我们的领域中有自己的风格
前奏:数据科学中的软件开发实践
随着数据科学和机器学习得到更广泛的行业采用,从业者意识到部署数据产品会带来高昂的(往往是意想不到的)维护成本。正如斯卡利和合著者在他们著名的论文中所说:
(ML 系统)具有传统代码的所有维护问题,外加一组 ML 特有的问题。
矛盾的是,尽管数据密集型系统比传统的软件系统有更高的维护成本,但是软件工程的最佳实践却常常被忽视。根据我与其他数据科学家的交谈,我认为这种做法被忽略了,主要是因为它们被视为不必要的额外工作,原因是动机不正确。
数据项目的最终目标是影响业务,但是这种影响在开发过程中很难评估。仪表板会产生多大的影响?预测模型的影响如何?如果产品尚未投入生产,则很难估计业务影响,我们不得不求助于代理指标:对于决策工具,业务利益相关者可能会主观判断新的仪表板在多大程度上可以帮助他们改善决策,对于预测模型,我们可以根据模型的性能进行粗略估计。
这导致工具(例如仪表板或模型)被视为数据管道中唯一有价值的部分,因为它是代理指标所依据的。结果,大部分时间和精力都花在了尝试改进这个最终的可交付成果上,而所有之前的中间步骤得到的关注较少。
如果项目进入生产阶段,根据整体的代码质量,团队可能需要重构大量的代码库以准备投入生产。这种重构的范围可以从做小的改进到彻底的检修,项目经历的变化越多,就越难重现最初的结果。所有这些都可能严重推迟或危及发射。
一个更好的方法是始终让我们的代码随时(或几乎随时)准备好部署。这需要一个工作流来确保我们的代码得到测试,并且结果总是可重复的。这个概念被称为持续集成,是软件工程中广泛采用的实践。这篇博文介绍了一个经过修改的 CI 过程,它可以通过现有的开源工具有效地应用于数据项目。
摘要
- 将您的管道组织成几个任务,每个任务将中间结果保存到磁盘
- 以可以参数化的方式实现管道
- 第一个参数应该对原始数据进行采样,以便进行快速的端到端测试
- 第二个参数应该改变工件的位置,以分离测试和生产环境
- 在每次推送时,CI 服务都会运行单元测试来验证每个任务内部的逻辑
- 然后使用数据样本执行流水线,集成测试验证中间结果的完整性
什么是持续集成?
持续集成(CI)是一种软件开发实践,在这种实践中,小的变化被持续地集成到项目的代码库中。每一项变更都会被自动测试,以确保项目在生产环境中按照最终用户的预期运行。
为了对比传统软件和数据项目之间的差异,我们比较了两个用例:一个在电子商务网站上工作的软件工程师和一个开发数据管道的数据科学家,该管道输出每日销售额报告。
在电子商务门户用例中,生产环境是实时网站,最终用户是使用它的人;在数据管道用例中,生产环境是运行日常管道以生成报告的服务器,而最终用户是使用报告为决策提供信息的业务分析师。
我们将数据管道定义为一系列有序的任务,其输入是原始数据集,中间任务生成转换后的数据集(保存到磁盘),最终任务产生数据产品,在这种情况下,是具有每日销售额的报告(但这也可以是其他东西,如机器学习模型)。下图显示了我们的每日报告管道示例:
作者图片
每个蓝色块代表一个管道任务,绿色块代表一个生成最终报告的脚本。橙色块包含原始源的模式。每个任务生成一个产品:蓝色块生成数据文件(但也可以是数据库中的表/视图),而绿色块生成带有图表和表格的报告。
数据科学的持续集成:理想的工作流
正如我在序言中提到的,数据管道中的最后一个任务通常是最受关注的(例如,机器学习管道中的训练模型)。毫不奇怪,现有的关于数据科学/机器学习的 CI 的文章也关注这一点;但是为了有效地应用 CI 框架,我们必须考虑整个计算链:从获取原始数据到交付数据产品。不承认数据管道具有更丰富的结构,会导致数据科学家过于关注最末端,而忽略其余任务中的代码质量。
根据我的经验,大多数错误都是在这个过程中产生的,更糟糕的是,在许多情况下,错误不会破坏管道,但会污染您的数据并损害您的结果。每一步都应该同等重要。
让我们通过描述提议的工作流来使事情更加具体:
- 数据科学家推动代码变更(例如,修改管道中的一个任务)
- 推送触发 CI 服务端到端地运行管道,并测试每个生成的工件(例如,一个测试可以验证
customers
表中的所有行都具有非空的customer_id
值) - 如果测试通过,接下来是代码审查
- 如果审阅者批准了更改,则合并代码
- 每天早上,“生产”管道(主分支中的最新提交)端到端运行,并将报告发送给业务分析师
这种工作流程有两个主要优点:
- 早期缺陷检测:缺陷是在开发阶段检测到的,而不是在生产阶段
- 总是生产就绪:由于我们要求代码更改在集成到主分支之前通过所有测试,我们确保我们可以通过在主分支中部署最新的提交来持续部署我们最新的稳定特性
这个工作流程就是软件工程师在传统软件项目中所做的。我称之为理想的工作流程,因为如果我们能够在合理的时间内完成端到端的管道运行,我们就会这么做。由于数据规模的原因,这对于很多项目来说是不正确的:如果我们的管道需要几个小时来端到端地运行,那么每次我们做一个小的改变时都运行它是不可行的。这就是为什么我们不能简单地将标准 CI 工作流(步骤 1 至 4)应用于数据科学。我们将做一些改变,使它对于运行时间是一个挑战的项目是可行的。
软件测试
CI 允许开发人员通过运行自动化测试来持续集成代码变更:如果任何测试失败,提交将被拒绝。这确保了我们在主分支中总是有一个工作项目。
传统的软件是在小的、很大程度上独立的模块中开发的。这种分离是很自然的,因为组件之间有明确的界限(例如注册、计费、通知等)。回到电子商务网站用例,工程师的待办事项列表可能是这样的:
- 人们可以使用电子邮件和密码创建新账户
- 可以通过向注册的电子邮件发送消息来找回密码
- 用户可以使用以前保存的凭据登录
一旦工程师编写了支持这种功能的代码(甚至更早!),他/她将通过编写一些测试来确保代码工作,这些测试将执行被测试的代码并检查它是否如预期的那样运行:
但是单元测试不是唯一的测试类型,我们将在下一节看到。
测试级别
软件测试有四个级别。理解这些差异对于为我们的项目开发有效的测试是很重要的。在这篇文章中,我们将关注前两个。
单元测试
我在上一节中展示的代码片段被称为单元测试。单元测试验证单个单元工作。对于单元没有严格的定义,但是它通常等同于调用一个单独的过程,在我们的例子中,我们正在测试create_account
过程。
单元测试在传统的软件项目中是有效的,因为模块被设计成在很大程度上相互独立;通过分别对它们进行单元测试,我们可以快速查明错误。有时,新的变化破坏测试不是因为变化本身,而是因为它们有副作用,如果模块是独立的,它给我们保证我们应该在模块的范围内寻找错误。
拥有过程的效用在于,我们可以通过使用输入参数定制它们的行为来重用它们。我们的create_account
函数的输入空间是所有可能的电子邮件地址和所有可能的密码的组合。组合的数量是无限的,但是可以合理地说,如果我们针对有代表性的数量的情况来测试我们的代码,我们就可以得出结论,这个过程是可行的(如果我们发现一个不可行的情况,我们就修正代码并添加一个新的测试用例)。在实践中,这归结为针对一组代表性案例和已知边缘案例的测试过程。
假设测试以自动化的方式运行,我们需要一个通过/失败的标准。在软件工程术语中,这被称为测试 oracle 。提出好的测试预言对测试来说是必不可少的:测试在评估正确结果的程度上是有用的。
集成测试
第二个测试级别是集成测试。单元测试有点简单,因为它们独立地测试单元,这种简化对效率是有用的,因为不需要启动整个系统来测试它的一小部分。
但是当输入和输出跨越模块边界时,有时会出现错误。尽管我们的模块在很大程度上是独立的,但它们仍然必须在某个点上相互交互(例如,计费模块必须与通知模块对话才能发送收据)。为了在这个交互过程中捕捉潜在的错误,我们使用集成测试。
编写集成测试比编写单元测试更复杂,因为需要考虑更多的元素。这就是为什么传统的软件系统被设计成松散耦合的 T2,通过限制交互的数量和避免跨模块的副作用。正如我们将在下一节中看到的,集成测试对于测试数据项目是必不可少的。
有效测试
编写测试本身就是一门艺术,测试的目的是在开发过程中尽可能多地捕捉错误,这样它们就不会出现在产品中。在某种程度上,测试是模拟用户的行为,并检查系统是否如预期的那样运行,因此,有效的测试是模拟现实场景并适当评估系统是否做了正确的事情。
有效的测试应该满足四个要求:
1。当用户与系统交互时,系统的模拟状态必须代表系统
测试的目标是防止生产中的错误,所以我们必须尽可能接近地表现系统状态。尽管我们的电子商务网站可能有几十个模块(用户注册、账单、产品列表、客户支持等),但它们被设计成尽可能独立,这使得模拟我们的系统更容易。我们可以说,当新用户注册时,有一个虚拟数据库就足以模拟系统,任何其他模块的存在或不存在都不会对被测试的模块产生影响。组件之间的交互越多,就越难在生产中测试真实的场景。
2。输入数据代表真实的用户输入
当测试一个过程时,我们想知道给定一个输入,这个过程是否做了它应该做的事情。由于我们不能运行每一个可能的输入,我们必须考虑足够多的情况来代表常规操作以及可能的边缘情况(例如,如果用户使用无效的电子邮件地址注册会发生什么)。为了测试我们的create_account
过程,我们应该传递一些常规的电子邮件帐户和一些无效的帐户,并验证是否创建了帐户或显示了适当的错误消息。
3。适当的测试甲骨文
正如我们在上一节中提到的,测试 oracle 是我们的通过/失败标准。要测试的程序越简单越小,就越容易想出一个。如果我们没有测试出正确的结果,我们的测试就没有用。我们对create_account
的测试意味着检查数据库中的 users 表是评估我们函数的一种合适的方式。
4。合理运行时间
测试运行时,开发人员必须等待结果返回。如果测试很慢,我们将不得不等待很长时间,这可能会导致开发人员完全忽略 CI 系统。这会导致代码变更越来越多,使得调试更加困难(当我们更改 5 行代码时,比更改 100 行代码时更容易发现错误)。
数据管道的有效测试
在前面的章节中,我们描述了软件测试的前两个层次以及有效测试的四个属性。本节讨论了如何将测试技术从传统的软件开发应用到数据项目中。
数据管道的单元测试
与传统软件中的模块不同,我们的流水线任务(图中的块)不是独立的,它们有一个逻辑执行。为了准确地表示我们系统的状态,我们必须尊重这样的顺序。因为一个任务的输入依赖于上游依赖项的输出,所以错误的根本原因可能在失败的任务中,也可能在任何上游任务中。这对我们没有好处,因为它增加了搜索 bug 的潜在位置的数量,在更小的过程中抽象逻辑并对它们进行单元测试有助于减少这个问题。
假设我们的任务add_product_information
在加入产品销售之前执行一些数据清理:
我们将清理逻辑抽象为两个子过程clean.fix_timestamps
和clean.remove_discontinued
,任何子过程中的错误都会传播到输出,从而传播到任何下游任务。为了防止这种情况,我们应该添加一些单元测试,单独验证每个子过程的逻辑。
有时,转换数据的管道任务仅由对外部包(例如 pandas)的几个调用组成,几乎没有自定义逻辑。在这种情况下,单元测试不会非常有效。想象您管道中的一个任务如下所示:
假设您已经对清理逻辑进行了单元测试,那么就没有太多关于转换的单元测试了,为这样简单的过程编写单元测试并不是一个很好的时间投资。这就是集成测试的用武之地。
数据管道的集成测试
我们的管道传递输入和输出,直到产生最终结果。如果任务输入预期不真实(例如列名),这个流程可能会中断,此外,每个数据转换都编码了我们对数据做出的某些假设*。集成测试帮助我们验证输出正确地流经管道。*
如果我们想要通过上面显示的转换来测试组,我们可以运行流水线任务,并使用输出数据来评估我们的期望:
这四个断言写起来很快,并且清楚地编码了我们的输出期望。现在让我们看看如何详细地编写有效的集成测试。
系统状态
正如我们在上一节中提到的,管道任务有依赖关系。为了在我们的测试中准确地表示系统状态,我们必须遵守执行顺序,并在每个任务完成后运行我们的集成测试,让我们修改我们的原始图表来反映这一点:
作者图片
测试甲骨文
测试管道任务的挑战是没有唯一正确的答案。当开发一个create_user
过程时,我们可以说为新用户检查数据库是成功的一个适当的度量,但是清理数据的过程呢?
没有唯一的答案,因为干净数据的概念取决于我们项目的具体情况。我们能做的最好的事情就是明确地将我们的输出期望编码为一系列的测试。要避免的常见情况包括分析中的无效观察、空值、重复、意外的列名等。这种期望是集成测试的良好候选,以防止脏数据泄漏到我们的管道中。即使是提取原始数据的任务也应该进行测试,以检测数据变化:列被删除、重命名等。测试原始数据属性有助于我们快速识别源数据何时发生了变化。
即使我们不编写测试,一些更改(如列重命名)也会破坏我们的管道,但显式测试有一个很大的优势:我们可以在正确的位置修复错误,避免多余的修复。想象一下,如果重命名列会破坏两个下游任务,每个任务由不同的同事开发,一旦他们遇到错误,就会试图在代码中重命名列(两个下游任务),而正确的方法是修复上游任务。
此外,破坏我们管道的错误应该是我们最不担心的,数据管道中最危险的错误是偷偷摸摸的;它们不会破坏您的管道,但会以微妙的方式污染所有下游任务,这可能会严重破坏您的数据分析,甚至推翻您的结论,这是最糟糕的情况。正因为如此,我不能强调将数据期望编码作为任何数据分析项目的一部分有多重要。
管道任务不一定是 Python 过程,它们通常是 SQL 脚本,您应该以同样的方式测试它们。例如,您可以使用以下查询测试某一列中没有空值:
对于输出不是数据集的过程,提出一个测试 oracle 变得更加棘手。数据管道中的常见输出是人类可读的文档(即报告)。虽然技术上可以测试图形输出,如表格或图表,但这需要更多的设置。第一种(通常也是足够好的)方法是对生成可视化输出的输入进行单元测试(例如,测试为绘图而不是实际绘图准备数据的函数)。如果你对试验田感兴趣,点击这里。
现实输入数据和运行时间
我们提到过,真实的输入数据对于测试非常重要。在数据项目中,我们已经有了可以在测试中使用的真实数据,但是,传递完整的数据集进行测试是不可行的,因为数据管道有计算开销很大的任务,需要花费很多时间来完成。
为了减少运行时间并保持输入数据的真实性,我们传递了一个数据样本。如何获取样本取决于项目的具体情况。目标是获得一个具有代表性的数据样本,其属性类似于完整的数据集。在我们的例子中,我们可以随机抽取昨天的销售额。然后,如果我们想要测试某些属性(例如,我们的管道正确处理 NAs),我们可以在随机样本中插入一些 NAs,或者使用另一种采样方法,例如分层采样。采样只需要发生在提取原始数据的任务中,下游任务将只处理来自上游依赖项的任何输出。
仅在测试期间启用采样。确保您的管道被设计为容易关闭该设置,并保持生成的工件(测试与生产)被清楚地标记:
上面的代码片段假设我们可以将管道表示为“管道对象”,并使用参数调用它。这是一个非常强大的抽象,使您的管道可以灵活地在不同的设置下执行。任务成功执行后,您应该运行相应的集成测试。例如,假设我们想要测试我们的add_product_information
过程,一旦这样的任务完成,我们的管道应该调用下面的函数:
请注意,我们将数据的路径作为参数传递给函数,这将允许我们轻松地切换加载数据的路径。这对于避免管道运行相互干扰非常重要。例如,如果你有几个 git 分支,你可以在一个名为/data/{branch-name}
的文件夹中按分支组织工件;如果您与同事共享一个服务器,每个人都可以将其工件保存到/data/{username}
。
如果您正在使用 SQL 脚本,您可以应用相同的测试模式:
除了采样,我们还可以通过并行运行任务来进一步加速测试。尽管我们能做的并行化是有限的,这是由流水线结构决定的:我们不能运行一个任务,直到它们的上游依赖完成。
我们的库 Ploomber 支持参数化管道和任务执行时执行测试。
数据科学中的测试权衡
数据项目比传统软件有更多的不确定性。有时候我们甚至不知道这个项目在技术上是否可行,所以我们必须投入一些时间来给出答案。这种不确定性不利于好的软件实践:因为我们想要减少不确定性来估计项目的影响,好的软件实践(比如测试)可能不会被认为是实际的进展而被忽视。
我的建议是随着你的进步不断增加测试。在早期阶段,关注集成测试是很重要的,因为它们可以快速实现并且非常有效。数据转换中最常见的错误很容易使用简单的断言检测出来:检查 id 是否唯一、没有重复、没有空值、列是否在预期的范围内。你会惊讶地发现,用几行代码就能发现多少错误。一旦你看了数据,这些错误是显而易见的,但甚至可能不会破坏你的管道,它们只会产生错误的结果,集成测试防止了这一点。
第二,尽可能利用现成的软件包,尤其是对于高度复杂的数据转换或算法;但是要注意质量,喜欢维护包,即使它们不能提供最先进的性能。第三方软件包自带测试,可以减少您的工作量。
也可能有不太重要或者很难测试的部分。绘图过程是一个常见的例子:除非您正在生成一个高度定制的绘图,否则测试一个只调用 matplotlib 并稍微定制 axis 的小绘图函数没有什么好处。重点测试进入绘图功能的输入。
随着项目的成熟,您可以开始专注于增加您的测试覆盖范围并支付一些技术债务。
调试数据管道
当测试失败时,就是调试的时候了。我们的第一道防线是日志记录:无论何时运行管道,我们都应该生成一组相关的日志记录供我们查看。我建议您看看 Python 标准库中的[logging](https://docs.python.org/3/library/logging.html)
模块,它为此提供了一个灵活的框架(不要使用print
进行日志记录),一个好的做法是保存一个文件,其中包含每次管道运行的日志。
虽然日志可以提示您问题出在哪里,但是设计易于调试的管道是至关重要的。让我们回忆一下我们对数据管道的定义:
输入为原始数据集的一系列有序任务,中间任务生成转换数据集(保存 到磁盘 ),最终任务生成数据产品。
将所有中间结果保存在内存中肯定更快,因为磁盘操作比内存慢。但是,将结果保存到磁盘会使调试更加容易。如果我们不将中间结果保存到磁盘,调试意味着我们必须再次重新执行我们的管道来复制错误条件,如果我们保留中间结果,我们只需重新加载失败任务的上游依赖项。让我们看看如何使用标准库中的 Python 调试器来调试我们的add_product_information
过程:
由于我们的任务是相互隔离的,只通过输入和输出进行交互,所以我们可以很容易地复制错误条件。只需确保您向函数传递了正确的输入参数。如果您使用 Ploomber 的调试功能,您可以很容易地应用这个工作流程。
调试 SQL 脚本更加困难,因为我们没有 Python 中的调试器。我的建议是将您的 SQL 脚本保持在一个合理的大小:一旦一个 SQL 脚本变得太大,您应该考虑将它分成两个独立的任务。使用WITH
组织您的 SQL 代码有助于提高可读性,并且可以帮助您调试复杂的语句:
如果您在这样组织的 SQL 脚本中发现一个错误,您可以将最后一个SELECT
语句替换为类似SELECT * FROM customers_subset
的语句,以查看中间结果。
在生产中运行集成测试
在传统的软件中,测试只在开发环境中运行,它假设如果一段代码进入生产环境,它一定已经被测试并正常工作。
对于数据管道,集成测试是管道本身的一部分,由您决定是否执行它们。这里起作用的两个变量是响应时间和最终用户。如果运行频率很低(例如,每天执行的管道)并且最终用户是内部的(例如,业务分析师),您应该考虑将测试保持在生产中。机器学习训练管道也遵循这种模式,它的运行频率很低,因为它是按需执行的(每当你想训练一个模型时),最终用户是你和团队中的任何其他人。这一点很重要,因为我们最初是用数据样本运行测试的,如果我们的采样方法没有捕捉到数据中的某些属性,那么用整个数据集运行测试可能会得到不同的结果。
另一个常见的(通常不可预见的)场景是数据更改。让您自己了解上游数据的计划变更(例如,迁移到不同的仓库平台)是很重要的,但是在您通过管道传递新数据之前,您仍然有机会发现数据变更。在最好的情况下,您的管道将引发一个您能够检测到的异常,在最坏的情况下,您的管道将正常执行,但输出将包含错误的结果。因此,保持您的集成测试在生产环境中运行是非常重要的。
底线:如果你可以允许一个管道延迟它的最终输出(例如每日销售报告),保持测试在生产中,并确保你被适当地通知,最简单的解决方案是让你的管道给你发一封电子邮件。
对于需要经常快速输出的管道(如 API),您可以改变策略。对于非关键错误,您可以记录而不是引发异常,但是对于关键情况,如果您知道失败的测试会阻止您返回适当的结果(例如,用户为“年龄”列输入了负值),您应该返回一条信息性的错误消息。处理生产中的错误是模型监控的一部分,我们将在接下来的帖子中介绍。
重新审视工作流程
作者图片
我们现在根据前面章节的观察重新审视工作流。在每次推送时,首先运行单元测试,然后使用数据样本执行管道,在每次任务执行时,运行集成测试来验证每个输出,如果所有测试都通过,则提交被标记为成功。CI 流程到此结束,应该只需要几分钟。
假设我们持续测试每个代码变更,我们应该能够随时部署。这种持续部署软件的想法被称为持续部署,它值得一个专门的帖子,但这里是摘要。
因为我们需要生成每日报告,所以管道每天早上运行。第一步是(从存储库或工件存储中)提取可用的最新稳定版本,并将其安装在生产服务器中,对每个成功的任务运行集成测试,以检查数据预期,如果这些测试中的任何一个失败,将发送通知。如果一切顺利,管道会将报告通过电子邮件发送给业务分析师。
实施细节
本节提供了使用现有工具实施 CI 工作流的一般指南和资源。
单元测试
为了在每个数据管道任务中单元测试逻辑,我们可以利用现有的工具。我强烈推荐使用 pytest 。它对基本用法的学习曲线很小;随着你对它越来越熟悉,我建议你探索它的更多特性(例如夹具)。成为任何测试框架的超级用户都有很大的好处,因为您将投入更少的时间来编写测试,并最大限度地提高它们捕捉 bug 的效率。坚持练习,直到编写测试成为编写任何实际代码之前的第一步。这种首先编写测试的技术被称为测试驱动开发(TDD) 。
运行集成测试
集成测试有更多的工具需求,因为它们需要考虑数据管道结构(按顺序运行任务)、参数化(用于采样)和测试执行(在每个任务之后运行测试)。最近工作流管理工具激增,在某种程度上有助于做到这一点。
我们的库 Ploomber 支持实现该工作流所需的所有特性:将您的管道表示为 DAG ,分离开发/测试/生产环境,参数化管道,在任务执行时运行测试功能,与 Python 调试器集成,以及其他特性。
外部系统
许多简单到中等复杂的数据应用程序是在单个服务器上开发的:第一个管道任务从仓库中转储原始数据,所有下游任务将中间结果输出为本地文件(例如 parquet 或 csv 文件)。这种架构允许在不同的系统中轻松地包含和执行管道:要在本地测试,只需运行管道并将工件保存在您选择的文件夹中,要在 CI 服务器中运行管道,只需复制源代码并在那里执行管道,不依赖于任何外部系统。
然而,对于数据规模是一个挑战的情况,管道可能只是作为一个执行协调器,几乎不做任何实际的计算,例如一个纯粹的 SQL 管道,它只向分析数据库发送 SQL 脚本并等待完成。
当执行依赖于外部系统时,实现 CI 会更加困难,因为您依赖于另一个系统来执行您的管道。在传统的软件项目中,这是通过创建模拟来解决的,它模仿另一个对象的行为。想想电子商务网站:生产数据库是一个支持所有用户的大型服务器。在开发和测试期间,不需要如此大的系统,一个有一些数据(可能是真实数据甚至是虚假数据的样本)的较小系统就足够了,只要它准确地模仿生产数据库的行为。
这在数据项目中通常是不可能的。如果我们使用一个大的外部服务器来加速计算,我们很可能只有那个系统(例如一个公司范围的 Hadoop 集群),模仿它是不可行的。解决这个问题的一个方法是将管道工件存储在不同的“环境”中。例如,如果您为您的项目使用一个大型的分析数据库,那么将生产工件存储在一个prod
模式中,将测试工件存储在一个test
模式中。如果您不能创建模式,您也可以为所有的表和视图添加前缀(例如prod_customers
和test_customers
)。参数化管道可以帮助您轻松切换模式/后缀。
CI 服务器
为了自动化测试执行,您需要一个 CI 服务器。每当您推送到存储库时,CI 服务器将针对新提交运行测试。有许多选项可用,验证您工作的公司是否已经有 CI 服务。如果没有,您将不会得到自动化的过程,但是您仍然可以通过在每次提交时本地运行您的测试来实现它。
扩展:机器学习管道
作者图片
让我们修改之前的每日报告管道,以涵盖一个重要的用例:开发机器学习模型。假设我们现在想要预测下个月的日销售额。我们可以通过获取历史销售额(而不仅仅是昨天的销售额)、生成特征和训练模型来做到这一点。
我们的端到端过程有两个阶段:首先,我们处理数据以生成训练集,然后我们训练模型并选择最佳模型。如果我们在整个过程中对每个任务都遵循同样严格的测试方法,我们将能够从进入我们的模型中捕获脏数据,记住:垃圾入,垃圾出。有时,实践者通过尝试许多花哨的模型或复杂的超参数调优模式,过于关注训练任务。虽然这种方法肯定是有价值的,但在数据准备过程中通常会有很多容易实现的结果,这些结果会对我们模型的性能产生重大影响。但是为了最大化这种影响,我们必须确保数据准备阶段是可靠的和可重复的。
数据准备中的错误导致好得不真实(即数据泄露)的结果或次优模型;我们的测试应该解决这两种情况。为了防止数据泄漏,我们可以测试训练集中是否存在有问题的列(例如,只有在我们的目标变量可见后才知道其值的列)。为了避免次优性能,验证我们的数据假设的集成测试起着重要作用,但我们可以包括其他测试来检查我们最终数据集中的质量,例如验证我们有跨所有年份的数据,并且被认为不适合训练的数据不会出现。
获取历史数据会增加 CI 的总体运行时间,但数据采样(正如我们在每日报告管道中所做的)会有所帮助。更好的是,您可以缓存数据样本的本地副本,以避免每次运行测试时都提取样本。
为了确保完整的模型再现性,我们应该只使用从自动化过程中生成的工件来训练模型。一旦测试通过,流程可以自动触发完整数据集的端到端管道执行,以生成训练数据。
保留历史工件也有助于模型的可读性,给定一个散列提交,我们应该能够定位生成的训练数据,此外,从同一个提交重新执行管道应该产生相同的结果。
模型评估是 CI 工作流程的一部分
我们当前的 CI 工作流使用数据样本测试我们的管道,以确保最终输出适合培训。如果我们也能测试训练程序,那不是很好吗?
回想一下,CI 的目的是允许开发人员迭代地集成小的变更,为了有效,反馈需要快速返回。训练 ML 模型通常需要很长的运行时间;除非我们有办法在几分钟内完成我们的训练程序,否则我们将不得不考虑如何快速测试。
让我们分析两个微妙不同的场景,以了解如何将它们集成到 CI 工作流中。
测试训练算法
如果您正在实现自己的训练算法,您应该独立于管道的其余部分来测试您的实现。这些测试验证了您的实现的正确性。
这是任何 ML 框架都会做的事情(scikit-learn,keras 等)。),因为他们必须确保对当前实现的改进不会破坏它们。在大多数情况下,除非您正在处理一个非常数据饥渴的算法,否则这不会带来运行时间问题,因为您可以用一个合成/玩具数据集对您的实现进行单元测试。这个逻辑同样适用于任何训练预处理程序(比如数据缩放)。
测试您的培训渠道
实际上,培训不是一个单一阶段的过程。第一步是加载您的数据,然后您可能会做一些最后的清理,如删除 id 或热编码分类特征。之后,您将数据传递到一个多阶段训练管道,该管道涉及分割、数据预处理(例如标准化、PCA 等)、超参数调整和模型选择。这些步骤中的任何一步都可能出错,尤其是如果您的管道具有高度定制的过程。
测试你的培训渠道是困难的,因为没有明显的测试预言。我的建议是,通过利用现有的实现(scikit-learn 为这个提供了惊人的工具)来减少要测试的代码量,从而尽可能地简化您的管道。
在实践中,我发现相对于之前的结果定义一个测试标准是很有用的。如果我第一次训练一个模型,我得到的精度是 X,那么我保存这个数字,并把它作为参考。后续实验应在 X 的合理范围内失败:性能的突然下降或上升会触发警报以手动查看结果。有时这是好消息,这意味着性能正在提高,因为新功能正在工作,但有时这是坏消息:性能的突然提高可能来自信息泄漏,而性能的突然下降可能来自数据处理不当或意外删除行/列。**
为了保持运行时间的可行性,请使用数据样本运行训练管道,并让您的测试将性能与使用相同采样过程获得的指标进行比较。这比听起来更复杂,因为如果你用更少的数据训练,结果差异会增加,这使得得出合理范围更具挑战性。
如果上述策略不起作用,您可以尝试在您的 CI 管道中使用一个代理模型,它可以更快地训练和增加您的数据样本大小。例如,如果您正在训练一个神经网络,您可以使用一个更简单的体系结构进行训练,以使训练更快,并增加 CI 中使用的数据样本,以减少 CI 运行中的差异。
下一个前沿:数据科学光盘
CI 允许我们在短周期内集成代码,但这并不是故事的结尾。在某些时候,我们必须部署我们的项目,这就是连续交付和连续部署的用武之地。
部署的第一步是发布我们的项目。发布是指获取所有必要的文件(即源代码、配置文件等),并将其转换成可用于在生产环境中安装项目的格式。例如,发布一个 Python 包需要将我们的代码上传到 Python 包索引中。
持续交付保证了软件可以随时发布,但是部署仍然是一个手动过程(即必须有人在生产环境中执行指令),换句话说,它只是自动化了发布过程。持续部署包括自动化发布和部署。现在让我们从数据项目的角度来分析这个概念。
对于产生人类可读文档(例如报告)的管道,连续部署是简单的。在 CI 通过之后,另一个过程应该获取所有必要的文件并创建一个可安装的工件,然后,生产环境可以使用这个工件来设置和安装我们的项目。下次管道运行时,它应该使用最新的稳定版本。
另一方面,ML 管道的连续部署要困难得多。管道的输出不是唯一的模型,而是几个候选模型,应该对它们进行比较以部署最佳模型。如果我们已经有了生产中的模型,事情会变得更加复杂,因为没有部署可能是最好的选择(例如,如果新模型没有显著提高预测能力,并且带来了运行时间的增加或更多的数据依赖性)。
一个比预测能力更重要(也更难)评估的属性是模型公平性。必须评估每个新部署是否偏向敏感群体。想出一个自动的方法来评估一个模型的预测能力和公平性是困难和有风险的。如果你想了解更多关于模型公平性的知识,这是一个很好的起点。
但是 ML 的持续输送仍然是一个可管理的过程。一旦提交通过了带有数据样本(CI)的所有测试,另一个进程就会运行带有完整数据集的管道,并将最终数据集存储在对象存储中(CD 阶段 1)。
然后,训练过程加载工件,并通过调整每个选定算法的超参数来找到最佳模型。最后,它将最佳模型规范(即算法及其最佳超参数)与评估报告一起序列化(CD 阶段 2)。完成所有工作后,我们查看报告并选择部署模型。
在上一节中,我们讨论了如何在 CI 工作流中包含模型评估。所提出的解决方案受到 CI 运行时间要求的限制;在 CD 过程的第一阶段完成后,我们可以通过使用完整数据集训练最新的最佳模型规范来包含更健壮的解决方案,这将捕获导致性能下降的错误,而不是必须等待第二阶段完成,因为第二阶段具有更长的运行时间。CD 工作流程如下所示:
作者图片
从成功的 CI 运行中触发 CD 可以是手动的,数据科学家可能不希望为每个传递的提交生成数据集,但在给定提交哈希的情况下,应该很容易做到这一点(例如,通过单击或命令)。
允许手动执行第二阶段也很方便,因为数据科学家经常通过定制训练管道使用同一个数据集来运行几个实验,因此,单个数据集可能会触发许多训练工作。
在 ML 管道中,实验再现性至关重要。在提交、CI 运行和数据准备运行(CD 阶段 1)之间存在一对一的关系,因此,我们可以通过生成数据集的提交散列来唯一地标识数据集。我们应该能够通过再次运行数据准备步骤并使用相同的训练参数运行训练阶段来重现任何实验。
结束语
随着数据科学的 CI/CD 流程开始成熟和标准化,我们将开始看到简化实施的新工具。目前,许多数据科学家甚至不考虑将 CI/CD 作为他们工作流程的一部分。在某些情况下,他们只是不知道,在其他情况下,因为有效地实施 CI/CD 需要一个复杂的重新利用现有工具的设置过程。数据科学家不应该担心设置 CI/CD 服务,他们应该专注于编写代码、测试和推送。
除了专门为数据项目定制的 CI/CD 工具,我们还需要数据管道管理工具来标准化管道开发。在过去的几年里,我看到了很多新项目,不幸的是,其中大多数都专注于调度或扩展等方面,而不是用户体验,如果我们希望模块化和测试等软件工程实践被所有数据科学家接受,这是至关重要的。这就是我们构建 Ploomber 的原因,以帮助数据科学家轻松、渐进地采用更好的开发实践。
缩短 CI-开发人员反馈循环对 CI 的成功至关重要。虽然数据采样是一种有效的方法,但是通过使用增量运行,我们可以做得更好:通过重用先前计算的工件,在管道中更改单个任务应该只触发最少量的工作。Ploomber 已经提供了一些限制,我们正在试验改进这个特性的方法。
我认为 CI 是数据科学软件堆栈中最重要的缺失部分:我们已经有很好的工具来执行 AutoML、一键式模型部署和模型监控。CI 将缩小这个差距,允许团队自信地、持续地训练和部署模型。
为了推进我们的领域,我们必须开始更加关注我们的开发过程。
在这篇文章中发现一个错误?点击这里让我们知道。
最初发布于 ploomber.io
视网膜图像具有奇怪的预测性
请密切关注深度学习的这些发展
如果你曾经去看过眼科医生,你可能经历过一个常规的程序,专家会给你的眼球后部拍一张照片。
听说视网膜图像对诊断眼疾相当方便,你不会感到惊讶。然而,你可能没有想到,它们还可以提供许多关于一个人患心血管疾病风险的见解。视网膜成像是一种检查某人血管状况的非侵入性方法,这可能预示着此人更广泛的心血管健康状况。
如果你以前见过这些视网膜图像中的一张,你可能会指出视盘和各种血管(如果你没有,请尝试在谷歌上搜索“视网膜图像”——或“眼底”,这是眼睛后部的医学术语)。
医生将能够更进一步,通过识别异常并建议可能需要进一步调查或治疗的特征。
然而,把它喂给一台机器,它就能预测:
- 你多大了;
- 你的性别;
- 你的种族;
- 无论你是否吸烟;甚至
- 那天早上你吃了什么?
好吧,最后一条可能是我编的,但值得注意的是,其余的都是真的。毫无疑问,视网膜图像有着怪异的预测能力。
眼睛有
谷歌的研究人员在 2017 年写了一篇论文阐述了一项关于深度学习如何用于从视网膜图像中预测一系列心血管风险因素的调查。论文简要解释了医学发现的更传统的方法:首先观察潜在风险因素和疾病之间的联系和相关性,然后才设计和测试假设。Ryan Poplin 等人接着演示了深度学习架构如何在没有被告知要寻找什么的情况下,自己获取这些关联。
我相信我们都在某个时候听说过这样的断言,即某些医学专家将被人工智能算法取代,人工智能算法将能够在识别医学图像中的异常方面胜过他们。这项研究将事情引向一个稍微不同的方向——不寻求在现有的任务中胜过医生,而是看看新的信息机器可以从这些特定的图像中收集到什么。
在研究的早期,该团队发现他们的模型非常擅长预测年龄和性别等变量——以至于他们最初认为这是模型中的一个错误(Ryan 向我们介绍了该项目是如何在 TWiML talk 112 上开发的)。但是随着他们对事物的深入研究,他们发现这些都是真实的预测。不仅如此,它们也是令人难以置信的强健——例如,年龄可以被成功预测,平均绝对误差为 3.26 年。
发现了许多其他关联,结果表明,该团队可以获得比他们的基线模型更好的预测能力,包括血压、血糖水平甚至种族——所有心血管疾病的风险因素。
观察这些结果后,研究小组推断,如果心血管风险因素的范围可以预测得如此之好,那么该模型甚至可以在识别哪些患者未来最有可能患主要心血管事件(如中风或心脏病发作)时具有预测能力。尽管他们的训练数据存在一些限制,但仅在视网膜图像上训练的模型(因此没有明确给定的风险因素)能够实现 0.70 的 AUC(浏览本文的 ROC/AUC 部分,以了解更多关于 AUC 作为性能指标的信息)——这与另一个现有风险评分系统获得的 0.72 相比变得尤其令人印象深刻,该系统利用了更多的输入变量。
不仅仅是心灵的窗户
利亚姆·韦尔奇在 Unsplash 上的照片
在前面提到的 TWiML 播客中,Ryan 推测了一种可能的未来,即视网膜图像被用作生命体征,以提供患者整体健康状况的图片,而不仅仅是用于诊断眼部疾病。正如我们所见,这不仅仅是幻想——这种简单的非侵入性程序可以提供比我们之前预期的更广泛的患者健康快照。
总结一下——心血管疾病仍然是全世界死亡的主要原因,但是 80%的过早心脏病和中风是可以预防的。像上面讨论的论文这样的研究可以帮助我们更好地了解谁是心血管疾病的高危人群,以及如何最好地管理这些人群——适当的早期干预可以在很大程度上延长和改善人类生活质量。
学分和更多信息
Andrew Hetherington 是英国伦敦的一名见习精算师和数据爱好者。
论文讨论:R. Poplin 等人,“使用深度学习从视网膜眼底照片预测心血管风险因素”,DOI10.1038/s 41551–018–0195–0,https://arxiv.org/abs/1708.09843v2。
nrd 和 Liam Welch 在 Unsplash 上的照片。
RetinaNet:用 5 行代码进行自定义对象检测训练
使用 Monk,低代码深度学习工具和计算机视觉的统一包装器,使计算机视觉变得简单。
室内物体检测
在之前的文章中,我们已经使用和尚的 EfficientDet 构建了一个自定义的对象检测器。在本文中,我们将使用和尚的 RetinaNet 构建一个室内物体检测器,构建于 PyTorch RetinaNet 之上。
如今,从自动驾驶汽车到监控摄像头等等,计算机视觉无处不在。要开始学习计算机视觉,我们必须学习各种深度学习框架,如 TensorFlow、PyTorch 和 Mxnet,这是一个乏味的过程。
借此机会,我想向您介绍一下 Monk ,这是一个功能齐全、低代码、易于安装的对象检测管道。
[## 镶嵌成像/Monk_Object_Detection
低代码、易于安装的对象检测管道的一站式存储库。
github.com](https://github.com/Tessellate-Imaging/Monk_Object_Detection)
我们开始吧!!
目录
- 数据收集
- 转换为 COCO 格式
- 培训模式
- 检测对象检测器
数据收集
这里我们使用的是 OpenImages 。使用 OIDv4_ToolKit 收集数据。我从数据集中选择了 25 个类,你可以随意选择。
用于收集数据的命令示例
python main.py downloader --classes Apple Orange --type_csv validation
打开命令提示符,运行以下命令从整个数据集中收集 Alarm_clock 类。您可以使用这个过程来下载其他类。
$ git clone [https://github.com/EscVM/OIDv4_ToolKit](https://github.com/EscVM/OIDv4_ToolKit)
$ cd OIDv4_ToolKit
$ python main.py downloader --classes Alarm_clock --type_csv train
$ mv OID/Dataset/train/Alarm\ clock OID/Dataset/train/Alarm_clock
您可以使用直接下载格式化的数据集
$ wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=1bXzK3SYRCoUj9-zsiLOSWM86LJ6z9p0t' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/**\1\n**/p')&id=1bXzK3SYRCoUj9-zsiLOSWM86LJ6z9p0t" -O OIDv4_ToolKit.zip && rm -rf /tmp/cookies.txt
转换为 COCO 格式
COCO 格式
./ (root_dir)
|
|------Dataset (coco_dir)
|
|------Images (set_dir)
| |
| |----Alarm_clock
| |
| |---------img1.jpg
| |---------img2.jpg
| |---------..........(and so on)
|
| |-----Curtain
| |
| |---------img1.jpg
| |---------img2.jpg
| |---------..........(and so on)
|
| |-----...........(and so on)
|
|
|
|------annotations
|----------|
|--------------------instances_Images.json (instances_<set_dir>.json)
|--------------------classes.txt
- instances_Train.json →正确的 COCO 格式
- classes.txt →按字母顺序排列的类列表
对于列车组
- root _ dir = " oid v4 _ ToolKit/OID/";
- coco _ dir = " Dataset
- img_dir = "。/";
- set _ dir = " Images
注意:注释文件名与 set_dir 一致
我们通过 Monk 格式转换成 COCO 格式
1.从当前格式转换为 Monk 格式。
2.从 Monk 格式转换为 COCO 格式
运行 classes.txt
对于。“json”文件运行
培训模式
我们选择“resnet50”来进行这个实验。您可以按照代码中的建议设置超参数。如果你使用的是 GPU,那么设置 use_gpu=True,默认为 False。我们使用 4 个 GPU,所以 gpu_devices=[0,1,2,3]。如果您使用的是一个 GPU,请更改 gpu_devices=[0]。用'设置时期数和型号名称。pt '分机。
正如标题中提到的,我们只需要 5 行代码进行训练,这里是 Train.py
检测物体探测器
在训练模型之后,我们可以得到权重文件。加载重量并开始预测。
一些形象的推论,你可以看到:
推论 1
推论 2
你可以在 Github 上找到完整的代码。如果你喜欢蒙克,给我们 GitHub 回购⭐️。
在这个实验中,我们使用 Retinanet 创建了一个自定义对象检测,只需要基本的编程技能,甚至不需要了解架构和 PyTorch 框架。
有关自定义对象检测的更多示例,请查看
[## 镶嵌成像/Monk_Object_Detection
github.com](https://github.com/Tessellate-Imaging/Monk_Object_Detection/tree/master/example_notebooks)
有问题可以联系 Abhishek 和 Akash 。请随意联系他们。
我对计算机视觉和深度学习充满热情。我是 Monk 库的开源贡献者。
你也可以在以下网址看到我的其他作品:
阅读阿库拉·赫曼思·库马尔在媒介上的作品。计算机视觉爱好者。每天,阿库拉·赫曼思·库马尔和…
medium.com](https://medium.com/@akulahemanth)
照片由 Srilekha 拍摄
检索、分析和可视化地理参考数据
使用叶地图和标准 Python 库
在地理数据科学中,往往很难得到准确可靠的数据进行分析和展示。地理数据来自不同的来源,在不同的时间通过不同的技术收集,因此,人们总是关注用于从地理空间数据中获取信息的数据的质量和可靠性1。获取地理空间数据是每个地理信息系统(GIS)项目的关键步骤。据估计,获取阶段通常会消耗花费在 GIS 项目上的 70%到 80%的时间和金钱。
有两种类型的地理空间数据捕获:原始数据捕获(PDC)和二次数据捕获(SDC)。PDC 指的是直接数据采集,通常与使用全球定位系统( GPS )或全站仪【2】的现场勘测相关。在这一类别中,我们包括来自卫星、无人驾驶飞机、飞机和其他类型的太空、空中或手持传感器的遥感数据。
SDC 涉及检索地理空间数据的间接方法。有大量的在线资源允许我们为我们的地理空间项目挖掘在线资源。这些来源包括来自国际机构、政府、大学、商业网站和数据仓库的数据。这些类型的数据通常是免费的,并且格式与许多 GIS 软件兼容。在这一类别中,我们还包括可以从非数字格式检索的其他地理空间信息来源,例如纸质地图[2]。
在本文中,我们将讨论获取地理空间数据的 SDC 方式。具体来说,我们将简要展示如何检索、分析和可视化自 1964 年以来斐济附近地震的地理参考数据。为此,我们写了一套三本木星笔记本:
- reading_dataset :包含读取数据集集合并查找包含单词 纬度 或 经度 的数据集链接的代码。
- db _ seismics从选择的数据集创建一个数据库,并计算一些空间统计数据。
- 地图 _ 地震获取数据库数据并使用叶子包创建网络地图。
我们不会给你很多关于我们使用的代码的细节。如果你想访问整个库,点击这里或者这篇文章的末尾。
读取数据集
我们使用了来自数据集的可用数据集列表。CSV 格式的列表被导入、打开和阅读。然后,我们在每个数据集的 HTML 代码(网页抓取)中寻找单词latitude
或longitude
。最后,从结果列表中,我们选择了一个用于创建数据库和地图的数据集。
# open the collection dataset
with open('datasets.csv', newline='') as csvfile:
reader = csv.DictReader(csvfile)
# append in a list all the content of the Doc column
for row in reader:
url_list.append(row['Doc'])
for url in url_list:
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
r = requests.get(url)
if r.status_code == 200:
html = urlopen(url, context=ctx).read()
soup = BeautifulSoup(html, "html.parser")
for item in soup:
# find latitude or longitude word
if soup.find_all(text=re.compile(r'\blatitude\b | \blongitude\b', flags=re.I | re.X)):
sel_list.append(url)
else:
continue
else:
continue
for item2 in sel_list:
if item2 not in sel_list2:
sel_list2.append(item2)
print('List of datasets containing the terms latitude or longitude: \n', sel_list2)
从 1340 个数据集中,我们获得了 20 个包含单词纬度或经度的 HTML 链接,接下来我们为接下来的步骤选择了一个数据集。
print('The selected dataset is: ', sel_list2[8])
所选数据集是:
创建数据库和计算空间统计数据
我们使用了所选数据集的 CSV 文件。该数据集包含自 1964 年以来斐济附近发生的地震事件的位置数据、深度和震级。然后,我们创建了一个数据库,并使用这个 CSV 文件填充它。最后,我们查询数据库并计算一些统计数据。
我们创建了一个轻量级的 SQLite 数据库和一个名为quakes
的表,与所选数据集具有相同的列名。为此,我们使用了 SQL CREATE TABLE 语句。
*# create database*
conn = sqlite3.connect('eartquakes.sqlite')
cur = conn.cursor()*# create table*
cur.execute('''CREATE TABLE IF NOT EXISTS quakes (id INTEGER PRIMARY KEY, lat REAL, lon REAL, depth INTEGER, mag REAL, stations INTEGER)''')
接下来,我们用地震数据填充数据库。我们检索 URL 的数据集,并使用这些数据填充数据库。然后,我们丢下一些行代码和 SQL 语句来计算:总地震、平均震级和深度、最强和最小地震。
*# get and read data (on line)*
**with** closing(requests.get(url, stream=**True**)) **as** r:
f = (line.decode('utf-8') **for** line **in** r.iter_lines())
reader = csv.reader(f, delimiter=',', quotechar='"')
next(reader)
*# populate the database*
list = []
**for** row **in** reader:
list.append(row)
**for** item **in** list:
cur.execute('INSERT OR IGNORE INTO quakes (id, lat, lon, depth, mag, stations) VALUES ( ?, ?, ?, ?, ?, ?)', ( item[0],item[1],item[2],item[3],item[4],item[5], ) )
conn.commit()
*# total earthquakes*
cur.execute("SELECT COUNT(*) from quakes")
**for** row **in** cur:
count = row[0]
*# average magnitude*
cur.execute("SELECT AVG(mag) from quakes")
**for** row **in** cur:
magAvg = row[0]
*# average depth*
cur.execute("SELECT AVG(depth) from quakes")
**for** row **in** cur:
depAvg = row[0]
*# strong and first minor earthquake in the dataset*
cur.execute("SELECT MAX(mag), id, lat, lon, depth FROM quakes")
**for** row **in** cur:
mag = row[0]
id = row[1]
lat = row[2]
lon = row[3]
depth = row[4]
cur.execute("SELECT MIN(mag), id, lat, lon, depth FROM quakes")
**for** row **in** cur:
mag2 = row[0]
id2 = row[1]
lat2 = row[2]
lon2 = row[3]
depth2 = row[4]*# id and magnitude dictionary*
cur.execute("SELECT id, mag FROM quakes")
dict = {rows[0]:rows[1] **for** rows **in** cur}
cur.close()
当打印结果时,我们得到在我们的研究区域有 1000 次地震,平均震级为 4.6,平均深度为 311.37 千米。此外,我们计算出最强地震的震级为 6.4,深度为 127 公里,而最小地震的震级为 4.0,深度为 649 公里。
接下来,我们计算了最大和最小震级之间的距离。为了做到这一点,我们使用了计算两个坐标之间最短距离的哈弗辛公式。这与欧几里德距离非常相似,除了它允许我们考虑地球的球形形状【3】。
*# Haversine distance formula*
**import** **math**
x_dist = math.radians(lon2-lon)
y_dist = math.radians(lat2-lat)
y1_rad = math.radians(lat)
y2_rad = math.radians(lat2)
a = math.sin(y_dist/2)**2 + math.sin(x_dist/2)**2 \
* math.cos(y1_rad) * math.cos(y2_rad)
c = 2*math.asin(math.sqrt(a))
distance = c * 6371 *# kilometers*
print()
print("Distance between the strongest earthquake (ID:"+str(id) +") and weakest earthquake **\**
(ID:"+str(id2)+"): "+str(round(distance,2))+" km.**\n**")
我们的结果显示,最强地震(ID:152)和最小地震(ID:5)之间的距离为 1609.06 公里。
最后,我们根据麦卡利烈度表对地震进行了震级分类。我们遍历了之前创建的包含每个事件的 id 和震级数据的字典,然后根据麦卡利等级阈值过滤这些事件,并计算发生的百分比。
*# dictionary length*
dictLen= len(dict)*# calculate percentage mercaly intensity I*
mer_I = [item **for** item, occurrences **in** dict.items() **if** occurrences < 2.0]
merIPerc = round((len(mer_I)/dictLen)*100, 2)*# calculate percentage mercaly intensity II*
mer_II = [item **for** item, occurrences **in** dict.items() **if** occurrences >= 2.0 **and** occurrences <= 2.9 ]
merIIPerc = round((len(mer_II)/dictLen)*100,2)*# calculate percentage mercaly intensity III*
mer_III = [item **for** item, occurrences **in** dict.items() **if** occurrences >= 3.0 **and** occurrences <= 3.9 ]
merIIIPerc = round((len(mer_III)/dictLen)*100,2)...
根据我们的结果,研究区内 80%的地震属于麦卡利烈度表 IV-V 。这些类型的事件被分类为轻度到中度地震。许多人在室内都能感觉到。轻),几乎每个人都感觉到了(中等)[4]。
绘制地震事件图
在我们系列笔记本的最后一部分,我们使用了在第 2 部分中创建的数据库,其中包含自 1964 年以来在斐济附近发生的地震事件的位置数据(经度和纬度)、深度和震级。从那个数据库中,我们通过叶子地图库提取了一些构建地震事件网络地图所需的数据。该 web 地图包含一个基础图层、地震事件位置和两个热图:地震的震级和深度。
我们阅读了我们的数据库并提取了以下数据:地震事件的纬度、经度、震级和深度。这些数据存储在列表对象中。为此,我们使用了嵌入在 Python 代码中的 SQL 语句。Python 有自己的内置模块来连接 Python 程序和数据库。
**# read dataset*
conn = sqlite3.connect('eartquakes.sqlite')
cur = conn.cursor()*# create a list of latitude, longitude, mag and depth*
lats=[]
lons =[]
mags =[]
depths =[]
cur.execute("SELECT lat, lon, mag, depth FROM quakes")
**for** row **in** cur:
lat = row[0]
lon = row[1]
mag = row[2]
depth = row[3]
lats.append(lat)
lons.append(lon)
mags.append(mag)
depths.append(depth)
cur.close()*# get a list of latitude and longitude values*
locations = list(zip(lats, lons))*# get a list of magnitude and depth values*
magdepth = list(zip(mags, depths))*
我们使用了的地图库来建立我们的地震事件网络地图。首先,我们配置了一个弹出窗口来显示每个地震的震级和深度。接下来,我们建立了 Cartodb 正电子作为底图。我们利用标记聚类技术来制作地震事件的动画点聚类可视化。最后,我们创建了地震震级和地震深度的热图。更多关于热图技术的信息请点击。
**# configure map popup*
popups = ['magnitude:**{}**<br>depth:**{}**'.format(mags, depths) **for** (mags, depths) **in** magdepth]*# create basemap*
map = folium.Map(
location=[np.mean(lats), np.mean(lons)],
tiles='Cartodb Positron',
zoom_start=5
)*# create marker clusters*
marker_cluster = MarkerCluster(
locations=locations,
popups=popups,
name='Earthquake Locations',
overlay=**True**,
control=**True**,)
marker_cluster.add_to(map)*# create heatmap of earthquake magnitude*
data_heat_mag = list(zip(lats, lons, mags))
mag_hm = plugins.HeatMap(data_heat_mag,
name='Heatmap of Earthquake Magnitudes',
overlay=**True**,
control=**True**,
show=**False**
)
mag_hm.add_to(map)*# create heatmap of earthquake depth*
data_heat_depth = list(zip(lats, lons,depths))
dep_hm = plugins.HeatMap(data_heat_depth,
name='Heatmap of Earthquake Depths',
overlay=**True**,
control=**True**,
show=**False**
)
dep_hm.add_to(map)*# add map control layer*
folium.LayerControl(collapsed=**False**).add_to(map)*
这是我们的最终地图
点击此处获取网络版(图片作者)
结论
尽管使用像 pandas 和 geopandas 这样的专业库也有可能达到我们在这里提出的相同目标,但是我们演示了(可能更详细),通过 Folium 和标准 Python 库检索、分析和可视化地理参考数据是可能的。一如既往,欢迎任何与此相关的反馈!
参考
1 Gervais,m .,Bédard,y .,Andree Levesque,m .,Bernier,e .,Devillers,R. (2009 年)。数据质量问题和地理知识发现。在米勒,h,韩,j。)地理数据挖掘和知识发现(第 99–115 页),美国纽约:泰勒&弗朗西斯集团。
3https://en.wikipedia.org/wiki/Haversine_formula。哈弗辛公式。
[4]https://en . Wikipedia . org/wiki/Modified _ Mercalli _ intensity _ scale。改良麦卡利烈度表。
检索、分析和可视化 1964 年以来斐济附近地震的地理参考数据
github.com](https://github.com/acoiman/mapping_earthquakes)*
机器学习的投资回报
与其问“我们如何获得 100%的准确率?”,正确的问题是“我们如何最大化投资回报率?”
在一个不确定的世界里,你仍然可以保持一致。由micha Parzuchowski在 Unsplash 拍摄的照片
机器学习处理概率,这意味着总有出错的可能。这种内在的不确定性导致许多决策者对实现机器学习感到不舒服,并使他们陷入对神奇的 100%准确性的无休止的追逐中。当我与迈出智能自动化第一步的公司合作时,对错误的恐惧几乎总是会出现,有人问我“如果算法做出错误的预测怎么办?”
如果这个问题得不到解决,公司很可能会在机器学习上花费大量的资源和数年的开发时间,而不会获得投资回报。在本文中,我将向您展示一个简单的等式,我用它来缓解这些担忧,让决策者对不确定性更加放心。
机器学习什么时候值得
就像任何投资一样,机器学习的可行性归结于它产生的价值是否大于它的成本。这是一种正常的投资回报(ROI)计算,在机器学习的背景下,它将产生的价值与错误和准确性的成本进行权衡。因此,与其问“我们如何获得 100%的准确率?”,正确的问题是“我们如何最大化投资回报率?”
确定预期回报非常简单。我通常通过用数学术语比较机器学习的好处和潜在成本,来开始打开机器学习实现的商业案例。这可以形式化为一个等式,基本上就是“在考虑了错误的成本之后,所产生的价值还剩下什么?”解这个简单的方程让我们可以估计不同情况下的利润。
让我们看看变量:
- 返回:每次预测产生的净值或利润
- value :每次预测生成的新值(例如,将文档分配到正确的类别现在需要 0.01 秒,而不是 5 分钟,因此节省了 5 分钟)
- 精度:算法预测的精度
- 错误成本:错误预测导致的额外成本(例如,有人需要 20 分钟来纠正系统中的错误)
通过翻转等式并将回报率设为零,我们得到了产生净值所需的最低精确度。这被称为盈亏平衡精度:
在图表中绘制时,等式变得更加直观:
图中的盈亏平衡点
假设每个预测为你节省了 5 分钟的工作时间,但是要修正一个错误的预测却需要 20 分钟的额外工作时间。我们现在可以计算出盈亏平衡准确度为*1–5/20 =*75%。此后的任何改进都会带来具体的利润。
上面的等式假设我们盲目地接受算法做出的任何预测,然后修正错误。听起来很冒险?我们可以做得更好,用置信度分数来扩展等式,以降低风险。
优化投资回报率
一个机器学习算法(做对了)不仅仅会喷涌出预测,它还会告诉我们它对每一个预测有多有信心。大多数错误发生在算法不确定其答案时,这使我们可以将自动化集中在最高确定性的预测上,同时手动审查最低确定性的预测。尽管人工审查确实要花费一些人力,但通常比以后修复错误要便宜得多。
让我们选择一个阈值,挑选出 10%最不自信的预测进行人工审查。剩下的 90%会自动处理。这个比例叫做置信分割。由于许多错误出现在小的不自信括号中,高自信括号中的准确度现在将会好得多。这将我们引向扩展方程。它说“在考虑了错误和人工审查的成本之后,所产生的价值还剩下什么?”
看起来很可怕,但一旦你知道它包含什么,它就很简单:
- 返回:每次预测产生的净值或利润
- 值:每次预测产生的新值
- 置信精度:高置信区间的预测精度
- 错误成本:错误预测所产生的额外成本
- 置信度分割:高置信度预测的比率(在我们的例子中是 90%)
- 人工审核成本:人工审核预测的成本
我们可以再次翻转等式,通过将回报设置为零来计算盈亏平衡精度,如下所示:
我们将使用以下变量来求解:
- 价值=节省了 5 分钟
- 错误的代价= 20 分钟
- 人工审核的成本= 5 分钟
- 置信区间= 0.9
现在新的盈亏平衡精度是 78% 。等等,这比更简单的方程要高,是不是变得更糟了?不完全是!请记住,许多错误都出现在低置信度类别中,这大大提高了高置信度类别的准确性。即使盈亏平衡的最低精度要求变得更高,现在也更容易实现。
计算运行中的机器学习算法的盈利能力,可以让你找到最佳的准确性。不,不是 100%。正如我在我的上一篇文章中所讨论的,任何系统的开发成本都是指数增长的,而回报却是递减的。有了上面的等式,您可以估计一个现实的 ROI,并计算在您选择的时间框架内,准确性的提高比回报的增加产生更多开发成本的点。这是 ROI 优化的精度。
实际例子
让我们来看一个真实世界的场景,并贯穿整个过程。假设您的应付账款团队每个月要处理 5000 张发票,并且您已经有了自动化部分流程的想法。更具体地说,拟议的自动化将对收到的发票进行分类,以匹配复杂的内部供应商代码,目前这是手工完成的。你需要弄清楚一种机器学习方法是否值得花力气来解决这个任务。
就数据而言,以下是您将要处理的内容。您有以前处理过的发票的历史记录以及每张发票的正确“供应商代码”值。任务是为任何新发票预测正确的“供应商代码”。你可以在这里 找到原来的数据集 。
先睹为快
首先,使用您喜欢的任何机器学习库或工具,并对数据进行基本的准确性测试。我使用的是 aito.ai ,经过 4000 行的训练和 1500 行的测试,我的准确率达到了 78%。如果我们使用和以前一样的价值和成本,我们可以用第一个等式计算月回报:
使用忽略置信度分数的简单方法,算法以 78%的准确率做出的每个预测平均为您节省 0.59 分钟的工作,或 35 秒。这意味着通过处理 5000 张发票,每个月可以节省将近 50 个小时的工作时间。还不错。
现在让我们来看看考虑置信度得分的等式。我将每个预测的结果和可信度分数整理成一个简洁的表格,如下所示,这样我们就可以将它们分为高可信度和低可信度两类。在这种情况下,任何置信度低于 0.21 的预测都将被手动审核。这个阈值给了我们 90/10 的置信区间。
预测结果
在我们的高信心等级中,准确率达到了令人印象深刻的 84%,而在低信心等级中,准确率只有区区 22%。这使得利用置信度得分的影响非常明显。现在,当信心和人工审查成本成为等式的一部分时,我们可以计算新的回报:
扩展的方法几乎使回报翻倍!每次预测平均节省 1.15 分钟。现在,处理你每月 5000 张发票的工作量减少了 95 个小时,即使算上错误成本和人工审核 10%的预测。太棒了!
现在你知道你目前可以达到的盈利水平。更好的是,您现在有了一个工具来确定进一步机器学习开发的可行性。例如,使用该等式,您可以计算假设 90%准确率的回报,并发现回报为每月节省 183 小时。将它与达到 90%准确率的估计开发成本进行比较,您将有事实数据来决定进一步的开发是否值得投资。
总结一下
正如你所看到的,机器学习应该像任何其他投资一样进行。不可避免的错误只是做生意的成本,它们是我们计算中的正常变量。有了这些等式,你就知道什么时候开始收获机器学习的好处,而不是玩猜谜游戏,并且你可以更早地将算法投入生产。从永无止境的追求 100%准确度的苦差事中解脱出来,并开始创造价值。
做得比完美更好。
我在aito . ai为不同平台开发机器学习集成,让机器学习的好处大众化。
修改我的音高质量标准
从头到尾对 Ethan 改进后的新指标进行了全面分析
作者注:本文(QOP)讨论的度量在未来的工作中将被称为 xRV(预期运行值)。
有关 QOS+的信息,一个本文中描述的姐妹指标, 点击此处 或滚动到本文底部。
今年早些时候,我创建了一个模型,试图量化一个 MLB 项目的质量。这个想法是,每个音高都可以根据它的区域位置、释放点和一些音高特性来给定一个预期的运行值。虽然我最初对我的度量结果(最初在这里介绍了)和我能够做的后续分析(这里的、这里的、这里的和这里的)感到满意,但我承认从建模的角度来看还有改进的空间。
在过去的几天里,我决定使用一个更具统计学意义的模型构建过程,彻底重建我的音高质量指标。本文将详细描述这个过程,并附有我的可复制代码,在这里找到。
问题
对于这个项目,我首先问
在 2020 赛季的每一场比赛中,我们期望得到多少分?
为了回答这个问题,我决定使用线性权重框架,它给出了每一个投球结果(球、好球、一垒打、本垒打、出局等)。)基于该事件在先前游戏中的价值的运行值。这个想法是,投出更多可能得到好结果(比赛中球的全垒打和出局)的投手应该得到奖励,而投出更多可能导致坏结果(比赛中球和球的跑垒员)的投手应该受到惩罚。
以前的方法问题
以前的度量标准,期望运行值(xRV)有什么问题,以至于我不得不改变它?一些事情。首先,它是使用一种叫做 k-最近邻的模型制作的,这种模型对于像这样的大型高维模型来说不是非常严格。在那个模型中,我使用了 100 个最近邻,这是一个任意的值,我没有特别的理由就选择了这个值。我没有进行特征选择,只使用了视觉测试来评估这个指标是否足够好。我的结论是,它的糟糕的 RMSE 分数证明了我是错的。这是很好的第一步,但我知道我可以做得更好,所以我做了。结果是一个改进的度量,其蓝图完全包含在本文中。
新方法
在进入杂草之前,我想概述一下这个新的度量,我称之为音高质量(简称 QOP),是如何计算的。我根据投手惯用手、击球手惯用手和投球类型,将本赛季的每一次投球分为 16 类。稍后我将详细介绍这些群体。对于每一组,我在该类别的一个音高子集上制作了一个单独的随机森林模型,确认该模型是有用的,然后将该模型应用于该类别的所有音高。数据集中的每个音高只属于一个类别,因此只能从 16 个模型中的一个得到预测。
最后,我将所有 16 个模型的预测汇总在一起,并通过均方根误差(RMSE)评估模型的质量。这个模型比我最初在三月份做的这个度量的第一次迭代有了显著的改进。
我们走进杂草中。
数据采集
本项目使用的所有数据都来自于通过比尔·佩蒂的 baseballR 包公开提供的BaseballSavant.com,使用了以下函数和参数:
data = scrape_statcast_savant(start_date = “2020–07–23”,
end_date = “2020–09–05”, player_type = “pitcher”)
这种方法往往一次只能获取 40,000 个音高,所以我将它分解成更多日期范围更小的函数调用,并使用 rbind()命令将所有数据帧合并成一个。
数据清理和特征创建
不幸的是,这个公开可用的数据集不包括每个事件的线性权重值,就像我需要回答我的研究问题一样,所以我从头开始计算线性权重。我确信 2020 年的线性权重值存在于互联网上的其他地方,我可以找到并加入数据集,但我已经有了以前项目的代码,除了初始数据采集之外,我不希望在这个项目的任何部分依赖任何外部来源。公平的警告,这段代码,也可以在我的 GitHub 这里找到,有点乱,但最终完成了工作。
我想指出的是,我选择了将导致三振的投球赋予与典型三振相同的跑垒值(不是三振),而导致保送的投球被赋予典型球的跑垒值。因为这个指标是上下文无关的,击球次数不会成为这个模型的一个特征,所以我觉得这个改变是必要的。
一旦我获得了数据中每一行的线性权重值,我就根据下表将所有音高分组为四个音高类型组:
所有其他球场类型的球场,如指关节球、椭圆球等。已从数据集中删除。在这一步中,大约有 250 个球丢失了,我只剩下大约 170,000 个。(注:本文使用的数据是通过 9 月 5 日玩的游戏)
最后,我创造了三个新的变量来量化每一个速投和投手的平均快速球速度和移动之间的速度和移动差异。我这样做是因为我希望在以后的最终模型中包含这些变量,如果它们被证明是有用的话。
特征选择和重要性
如我之前所说,这个指标实际上是 16 个不同随机森林模型的组合。2020 年的每一次投球都属于 16 个类别之一,如下所示:
虽然我总共创造了 16 个模型,但是只有两个模型方程式:一个是快速球,一个是慢速球。
快速球特征选择
在筛选出恰到好处的快速球和恰到好处的快速球并随机抽取 10%的数据后,我用所有可能的特征运行了 Boruta 特征选择算法。(使用所有的数据会花费太多的时间,并且会产生相似的结果,所以我使用这个较小的子集来代替。)Boruta 是一种基于树的算法,特别适用于随机森林模型中的特征选择。
library(Boruta)Boruta_FS <- Boruta(lin_weight ~ release_speed + release_pos_x + release_pos_y + release_pos_z + pfx_x + pfx_z + plate_x + plate_z + balls + strikes + outs_when_up + release_spin_rate,
data = rr_fb_data_sampled)print(Boruta_FS)
该算法发现,除了一局中的球、击球和出局之外,上述所有变量在 0.01 水平上都是显著的,这是有意义的,因为我的上下文中性方法计算线性权重,即响应变量。
所以在我最终的快速球模型中的特征是投球速度、释放点、旋转速度和球板位置。因为我使用的是随机森林,所以我不需要担心运动和旋转速率等特征之间的潜在协方差。以下是模型中的最终特征,根据 Boruta 根据其对线性重量游程值预测的重要性进行排序。
用简单的语言来说,这些是对快速球质量最重要的变量。垂直运动是第一名,速度是第二名,伸展是第三名,这不应该是一个惊喜,而且肯定通过了嗅觉测试。
对于偏速模型,我遵循了一个非常相似的程序,为了特征选择的目的,子集化到随机的 10%的右对右偏速音高。我再次使用了具有相同潜在特性的 Boruta,但这次也包括了我之前创建的变量:每个投球和投手典型快速球之间的速度和运动差异。
Boruta_OS <- Boruta(lin_weight ~ release_speed + release_pos_x + release_pos_y + release_pos_z + pfx_x + pfx_z + plate_x + plate_z + balls + strikes + outs_when_up + release_spin_rate + velo_diff + hmov_diff + vmov_diff, data = rr_os_data_sampled)print(Boruta_OS)
结果如下:
我要做一个决定。保持原始的速度和移动值,还是使用基于投手快速球的值?该表显示,我们选择哪一个并不重要,因为两组变量具有非常相似的重要性分数。因此,我将使用包含原始值的变量。这里是个人偏好选择,但同样,与备选方案相比,它不应该对指标的准确性产生太大影响。
此外,即使博鲁塔发现罢工非常重要,我还是要排除这个变量,因为在我看来,它在我们的环境中立的情况下没有什么意义。所以偏离速度方程的最终变量是…
…除了释放延伸之外,与快速球方程式中的变数相同。很高兴事情是这样发展的。请注意不同重要性顺序的不同。到目前为止,移动似乎是变速球最重要的特征,这也是有道理的(特别是因为它混合了变速球、滑球和曲球)。
模型验证和评估
正如敏锐的观察家指出的,我完全没有验证我最初的音高质量模型,这是一个问题!我怎么知道它好不好?我几乎没有。我不会再犯同样的错误了!回顾过去,我之前的指标的 RMSE 是 0.21。考虑到 0.21 是响应列的标准偏差,线性权重,这是不好的。我希望通过这个新的指标,用一个更小的最终 RMSE 来改善这个数字。
为了验证这一指标,我使用了一种以前从未使用过的方法,将模型嵌套在一个数据框架中,一次性训练和测试我的所有 16 个模型。我从这篇 StackOverflow 帖子中大量借用了这篇文章,我的代码版本可以在我的 GitHub 这里看到。
按照惯例,我用 70%的数据训练每个模型,并将其应用于另 30%的数据,即我的测试集。
快速球训练和验证
#Fastball Training and Validating
fbs_predictions <- fb_nested %>%
mutate(my_model = map(myorigdata, rf_model_fb))%>%
full_join(new_fb_nested, by = c("p_throws", "stand", "grouped_pitch_type"))%>%
mutate(my_new_pred = map2(my_model, mynewdata, predict))%>%
select(p_throws,stand,grouped_pitch_type, mynewdata, my_new_pred)%>%
unnest(c(mynewdata, my_new_pred))%>%
rename(preds = my_new_pred)rmse(fbs_predictions$preds, fbs_predictions$lin_weight)
超速训练和验证
os_predictions <- os_nested %>%
mutate(my_model = map(myorigdata, rf_model_os))%>%
full_join(new_os_nested, by = c("p_throws", "stand", "grouped_pitch_type"))%>%
mutate(my_new_pred = map2(my_model, mynewdata, predict))%>%
select(p_throws,stand,grouped_pitch_type, mynewdata, my_new_pred)%>%
unnest(c(mynewdata, my_new_pred))%>%
rename(preds = my_new_pred)rmse(os_predictions$preds, os_predictions$lin_weight)
我对快速球模型的验证 RMSE 是 0.105,对慢速球模型的验证 RMSE 是 0.099,这两个指标都比我预期的好得多,表明这个指标在准确性和预测能力方面比我以前的指标有了真正的改善。
知道了我们对模型在验证集上的表现的了解,我对将这些模型应用到 2020 年迄今为止的每一场比赛感到很舒服。在这样做的时候,我给了 2020 年的每一个音高它的预期运行值。
当我这样做并结合预测时,我最终的总体 RMSE 是 0.145,比我之前的 0.21 RMSE 有了很大的提高!
我可以自信地说,这个模型在量化 MLB 音高的预期运行值方面优于我以前的音高质量模型。
限制
我想重申这个模型的目的和功能,以便揭示它的缺陷。正如乔治·博克斯的名言所说,“所有的模型都是错的,但有些是有用的。”这个模型根据 2020 年 MLB 赛季中每一场比赛的结果在真空中的可能性为每一场比赛赋值。虽然它看起来做得相当好,但这个指标没有考虑到
- 音高排序,以前的音高对当前音高的影响
- 对方击球手的强项和弱项
- 比赛情况(得分、局数、投球数)
- 击球情况(计数、跑垒员、出局数)
与任何模型一样,理解限制和适当的用例与理解模型本身的机制一样重要。也许在未来的迭代中,这些特性中的一些可以被集成到模型中,并且有可能提高它的性能。
结果
与我过去的一些文章不同,这些文章包括了以前的音高质量模型的结果的完整分析,我将保持这一部分的简短,以便将重点放在这一指标的创建过程上,而不是对其最终排行榜的争论。
也就是说,这里有一些来自这个模型的有趣的见解。请记住,QOP 的所有单位都是“每 100 场比赛阻止的预期得分”,所有排行榜都是准确的,直到 9 月 5 日的比赛。
快速球 QOP 2020 年迄今领先
2020 年迄今换台 QOP 领导人
滑块 2020 年 QOP 领导人至今
QOP 2020 年迄今领先
顺便提一下,里奇希尔排名第 11
写下来并公开代码对我来说真的很重要,算是结束了我这个非常活跃的研究夏天。我希望有人将能够采取这一点,并改善它,以进一步了解棒球比赛在公共领域!
一如既往,感谢您的阅读,如果您有任何问题、反馈或理想的工作机会😅,请在推特上告诉我 @Moore_Stats !
QOS+详情
东西的质量+(简称 QOS+)与本文概述的度量标准密切相关,QOP。我与《运动》杂志的 Eno Sarris 合作,为他的双周刊《材料与命令》撰写了这一指标。
以下是 QOS+和 QOP 的相关区别:
- QOS+不包括板位置作为其快速球或偏速模型方程的特征,以隔离投手的“材料”对其投球的预期跑分值的影响
- QOS+使用速度和移动值,相对于投手在其越速模式下的典型快速球
- QOS+的标度与 QOP 不同,100 是联盟平均水平,110 是比联盟平均水平高一个标准差
QOS+和 QOP 的排行榜预计会有所不同,QOS+排行榜更倾向于拥有好“东西”的投手,而不是 QOP,这也是投手的指挥。
逆向工程谷歌的技术,以赢得 95%以上的准确性
等等,你没看错😃让我们像专业人士一样设计神经网络吧!
我们看到谷歌如何提出许多突破性的科学构建,即使是在深度学习时代的早期阶段。他们拥有世界上最好的资源,硬件、软件和工程师。我们将研究如何对谷歌的一项新服务进行逆向工程,以获得惊人的结果。
我想给你讲一个故事。两年前,谷歌提出了一个想法,即开发一个平台,任何人都可以在这个平台上开发自己强大的深度学习模型,而无需事先有编码经验。这个平台的早期版本只允许用户使用他们的网络摄像头创建分类模型。这个想法很简单,走到讲台上,打开你的相机,给它看几张不同班级的照片。这个模型是在谷歌的计算机中训练出来的。所有这些事情的发生只是时间问题。该平台的最初版本非常简单。最近,谷歌更新了平台,为多个类别、姿势估计、音频分类、不同格式的下载模型等提供了巨大的支持。谷歌称之为 可教机器 。当前版本支持以下内容。
- 根据图像数据训练模型
- 根据音频数据训练模型
- 根据姿势数据训练模型(像在 Posenet 中)
- 将您自己的数据集上传到训练模型
- 每个模型培训 3 个以上的班级
- 禁用类别
- 保存您的 TensorFlow.js 模型
- 下载您的模型
- 部署您的模型以用于您自己的项目(网站、应用程序、物理机器等)。)
怎么样?对我来说,太棒了。
为了更好地了解这个平台,请观看下面由 Google 制作的视频。
谷歌可教机器视频
这个逆向工程任务是如何工作的?
我们要逆向工程的服务不过是 可教的机器 。首先也是最重要的,我们去平台,输入一些不同类别的图片。我选择了 摇滚 - 纸 - 剪刀 。您可以使用网络摄像头实时捕捉图像,或者上传您自己的自定义数据集。为了说明,我使用网络摄像头的方法。
截图取自https://teachablemachine.withgoogle.com/
如您所见,数据集已经准备好了。每个类由 200 幅图像组成。接下来就是训练模型了,我们只要点击 训练模型 选项就可以开始训练模型了。
截图取自https://teachablemachine.withgoogle.com/
我们的模特不到一分钟就能完成训练。剩下的是,我们必须看看我们的模型在现实世界中的表现。为此,我们可以使用现场演示选项。下面是一张 GIF 图,展示了我们训练的模型的结果。
截图取自https://teachablemachine.withgoogle.com/
一切正常,对吧?精度栏每次都打到 100。我做的每个测试都得到了几乎相似的结果。这只是一个例子,你可以用更复杂的数据集来尝试。对于这个解决方法的主要部分,我们必须将模型导出为某种格式。在这里,我使用了 Keras 模型的变体。如果您愿意,可以在相同的 Tensoflow.js 或 Tensorflow Lite 版本之间进行选择。
截图来自https://teachablemachine.withgoogle.com/
我们已经完成了模型训练部分。现在,我们必须开始问题的核心部分,即逆向工程。我们将要看到的是 模型是如何建立的 ,所有的层配置都使用了什么,有多少层,内核大小是什么,前馈网络的维数等等。为此,我们使用一个叫做netron的工具。深度学习模型不是一堆简单的层,对吗?
Netron 是一个开源工具,我们可以用它来看看深度学习模型是如何设计的以及相关的权重。我们必须访问他们的网站,并安装基于操作系统的客户端应用程序。我一直在用 Ubuntu,所以我下载了它的 Linux 版本。这个项目的主页将如下所示。
截图取自https://github.com/lutzroeder/netron
我们最后要做的就是用 netron app 打开下载的模型。抓住你了!我们成功了。
截图来自 netron app
你在上图中看到的是我们模型的架构。这是一个非常长的设计,不能放在一张截图里。放大后,我们得到了下面的图片。
截图来自 netron app
我们可以看到一些熟悉的层,对不对?在右侧,也给出了模型权重和超参数。如果我们可以通过查看层配置从零开始创建相同的模型,那就太棒了。我们可以在下一个项目中尝试这种配置。谷歌应该做了很多功课。所以采用同样的方法应该会有回报。
这是一种新的深度学习方法,可以极大地改善最终结果。希望这对您有所帮助。干杯,大家。
逆向工程图卷积网络
让我们对 GCN 进行逆向工程。在 Unsplash 上拍摄的 ThisisEngineering RAEng
这篇博客文章将总结“简化图卷积网络【1】”这篇文章试图对图卷积网络进行逆向工程。因此,让我们向后发展图卷积网络。
图是结构的普遍模型。它们无处不在,从社交网络到化学分子。各种事物都可以用图表来表示。然而,将机器学习应用于这些结构并不是我们直接想到的。机器学习中的一切都来自于一个小的简单的想法或模型,它根据需要随着时间变得复杂。举个例子,最初,我们有发展成多层感知的感知机,类似地,我们有发展成非线性 CNN 的图像滤波器,等等。然而,图卷积网络,被称为 GCN,是我们直接从现有的想法中衍生出来的,并有一个更复杂的开始。因此,为了揭穿 GCNs,本文试图对 GCN 进行逆向工程,并提出一种简化的线性模型,称为简单图卷积(SGC)。 SGC 在应用时可提供与 GCNs 相当的性能,甚至比快速 GCN 还要快。
基本符号
图卷积网络的输入是:
1。节点标签
2。邻接矩阵
**邻接矩阵:**邻接矩阵 A 为 **n x n,**矩阵其中 n 为节点个数,若节点 I 与节点 j 相连则 a(i,j) = 1 否则 a(i,j) = 0。如果边是加权的,那么 a(i,j) =边权重。
**对角矩阵:**对角矩阵 D 是 n×n 矩阵,d(i,i) =邻接矩阵的第 i 行之和。
输入特征: X 是大小为 n x c 的输入特征矩阵,c 为类别数。
在逆向工程之前,让我们看看 GCNs 实际上是如何工作的。
图卷积网络在行动
当我们通过 CNN 层输入图像时,会发生什么?它使用一个像素及其相邻像素来给出特定索引的输出。同样的行为在 GCNs 中也很普遍。对于每一层,我们传播一个新的特征:
正向传播步长
此外,该步骤可以矩阵形式表示为:
第 k 个输出通过将 S 乘以前一个输出获得
归一化邻接矩阵
因此,每下一步都可以表示为 S 与 H(i-1)的稀疏矩阵乘法
这就是平滑局部隐藏的表示。怎么会?每一步都从邻居传播特征。因此,在第一步之后,节点 x 具有其自身以及其邻居的信息。在第二步之后,它再次从它的邻居那里获取信息,但是他们已经有了它的 2 步远邻居的信息,所以这些添加到节点 x 上。同样,信息是在每一跳收集的。现在,将结果乘以权重矩阵 W ,并且应用逐点非线性函数(ReLU)来获得下一个特征矩阵。
非线性激活函数
由此获得的结果可以被输入到 softmax 层以获得分类概率。
使用 GCNs 分类(等式 1)
图卷积网络可以用下图来概括:
简单图形卷积:GCN 简化
让我们回忆一下 MLP 和 CNN。在 CNN 的节目中,每一层都有一个局部的感知,形成了我们的特征地图,随着我们越走越深,每个值都比以前有更多的接收。类似地,GCNs 从每一跳的邻居获得信息,因此每一层之后,每个节点都有更多关于整个网络的信息。这是从邻居提取特征的部分。
然而,每一层都有一个非线性函数,但它不会增加网络的接收能力。因此,除去非线性部分,我们得到一个简单的模型:
线性 GCN 被称为 SGC,在去除了 GCN 的非线性功能之后
简化的 SGC 方程(相当于线性化的方程 1)
这是简单图形卷积的方程。我们可以清楚地看到,这个模型被简化为一个简单的预处理步骤,采用直接多类回归。多酷啊!需要注意的一点是,当 S 和 X 都是输入时,上面的等式有一个可学习的参数θ。所以 S ᵏ X 可以重写给 x ':
X (输出)相当于作者的特征工程化输入|图像
得到的分类器方程
因此,我们可以在下图中看到,我们如何对 GCNs 进行逆向工程,并实现删除非线性层,这有助于我们理解跳跃只不过是机器学习中的一个特征工程步骤。这部分的实现可以在 GitHub 上找到。此外,SGC 可以总结为下图所示。
图形卷积网络的数学基础
这一部分将解释 GCNs 的数学流程,给出图卷积网络的半监督分类【3】
- 图拉普拉斯:
矩阵是表示图形的好方法。我们将图拉普拉斯算子及其归一化版本定义为:
图拉普拉斯(D =对角矩阵,A =邻接矩阵)
标准化形式
- 特征分解
每个半定矩阵都可以分解成以下形式:
特征分解
其中 U 包括标准正交特征向量,λ是以特征值作为其对角元素的对角矩阵。
现在,你有正交向量,我们能定义关于它们的图形傅立叶变换吗?绝对是!阅读关于 DFT 的内容。我们把 x 的傅立叶变换写成:
傅里叶变换
和逆变换为:
逆变换
- 根据傅立叶变换的图形卷积
现在,我们从信号和系统知识中知道,我们可以把任意两个信号的卷积写成它们在傅里叶变换中的乘积!使用这个我们得到:
滤波器与输入的卷积
这里 G 是以对角线作为滤波器系数的对角矩阵(你要学习的参数)
最后,我们使用一个使用 k 阶多项式拉普拉斯的近似来给出:
G 是大括号内的近似值!!
- 最终表情
上述近似通过使用(导致一阶切比雪夫滤波器)进一步近似:
给予
基本 GCN 卷积运算
此外,矩阵 I + D^(-1/2)AD^(-1/2 可写成:
其中 A' = A + I,D' = D + I。
简单图形卷积和低通滤波
我们导出的传播矩阵 S 是一阶切比雪夫滤波器。根据归一化拉普拉斯算子,它可以写成:
因此,第 k 阶滤波器系数变为:
Cora 数据集上不同传播矩阵的特征(红色)和过滤器(蓝色)光谱系数|来自 SGC 论文 1的结果
如图所示,K 值越大,滤波器系数爆炸并过度放大信号。
归一化的 S 给出了归一化的拉普拉斯算子,其进一步影响特征值
这就是在 GCN 帮助中使用重正化技巧的地方。通过重正化,滤波器系数变成重正化传播矩阵的多项式。
此外,添加自环γ > 0 后,归一化图拉普拉斯的最大特征值变小
结论
gcn 是神经网络复兴的结果,神经网络直接进化为复杂的网络来研究。在这里,GCN 被简化成它可能的前身 SGC。首先,我们研究了 GCNs 的工作原理,然后将其逆向工程为一个简化的回归模型,并通过特征工程增加了复杂性*。*进一步使用 GCNs 的数学表达式,网络被表示为切比雪夫滤波器!从而简化了网络!
接下来呢?
关于 SGC 和 GCNs 实现和比较更多细节,可以在参考文献[2]中找到作者实现。我在 CORA 数据集上实现的 SGC 可以在 GitHub 上找到。
参考文献:
- 图卷积网络|图论 2020
- 吴,费利克斯,等,“简化图卷积网络” arXiv 预印本 arXiv:1902.07153 (2019)。
- 实现可以在 GitHub 上找到
- 作者编写的简单图形卷积的代码可在 Github 上获得
- 基普夫、托马斯·n 和马克斯·韦林。"图卷积网络的半监督分类." arXiv 预印本 arXiv:1609.02907 (2016)。
对您进入数据科学的道路进行逆向工程
如何组织你的自学之旅并获得你梦想中的角色
自学成为数据科学家似乎是一项几乎不可能完成的任务。有太多的东西要学,太多的东西要理解,因此,关于如何成为一名数据科学家,互联网上不乏各种观点。如果没有一些指导,很难判断你是否在朝着正确的方向前进。
别害怕。自学路线比你想象的要容易管理得多。用正确的策略武装自己的技能,你可以学习如何成为一名非常受欢迎的数据科学家,并获得你梦想的角色。
在这篇文章中,我将向您展示如何通过逆向工程实现您梦想中的数据科学角色。我们都是从某个地方开始我们的旅程的,我希望为你进入这个行业提供第一块垫脚石。
逆向工程路径——定义你的目标
逆向工程是把一个物体拆开,看看它是如何工作的,以便复制或增强所述物体。这里的目标将是你的最终目标,定义你梦想中的角色是什么。你梦想的数据科学角色是什么?请考虑以下情况:
- 你想从事什么领域的工作?你想解决什么样的商业问题?你想贡献什么样的工作?
- 你认为自己会使用哪些技术?你很想了解哪些技术?为什么?
- 你想要什么样的工作文化?你是想从一家规模较小的初创公司开始,还是想从一家已经很有名气的公司开始?或许介于两者之间?
一旦你有了想成为哪种数据科学家的想法,就很容易逆向开发你需要学习的技能来实现你的目标。记住你的最终目标会随着你旅程的进展而改变。随着学习的进展,你会发现你喜欢使用哪种数据和技术。
如果你还不完全确定你的理想角色是什么,不要担心。对你来说,列出你不想要的角色可能是个更好的主意。这样你就可以集中精力探索你可能喜欢的技术和行业。
所有这一切的关键是你的旅程是一个迭代的过程,它永远不会是完美的。一旦你开始并开始前进,道路就会变得越来越清晰。
找到你的垫脚石
既然你已经对自己想成为什么样的数据科学家有了一些大致的了解,我们现在需要找到你有一天真的想成为的真正角色。然后,我们将需要提取所需的技能,以获得面试机会,从而获得上述职位。
根据你刚刚为自己定义的理想角色,找到 5 个符合你要求的职位。哪 5 份工作会让你欣喜若狂?
一旦你有了 5 分,是时候让我们为你建立一个技能清单,让你在自学之旅中掌握。这一部分可能有点棘手,因为某些招聘信息对他们想要的技能非常模糊,而其他的则非常具体。在任何情况下,单独通读每一条招聘信息,记下雇主正在寻找的特定技术和非技术技能。
然后你要比较和对比这些技能列表,寻找它们之间的共性。你最常看到的共性是“必须学习”的技能,你需要首先掌握的技能。该技能出现得越频繁,该角色的日常操作就越需要它。
那些不太常见的技能将会是更“专业”的技能,这些技能你将会优先考虑最后掌握。这些技能也很重要,但它们更适合特定的角色和行业。
让我们来看看 LinkedIn 上的一些招聘信息,我会告诉你如何提取你需要的信息,为你的旅程制作一份技能清单:
X 公司数据科学家的工作要求
我们可以从 X 公司的招聘启事中获得什么信息?
这一职位的强有力候选人似乎需要具备以下条件:
- 对统计学有很好的理解,具有优秀的批判性思维技能和定量问题解决技能
- 非常强的沟通和数据可视化技能
- 精通编程语言(最好是 Python)
- 精通 SQL
- 精通数据清理、操作和可视化
- 深度学习和机器学习
- 有大数据、云平台和计量经济学模型的经验更好(但不是必需的)。
这是一个非常好的技能列表,事实上,大多数核心数据科学家技能都列在第一个列表中。但是,让我们来看看另一家公司的第二份招聘启事,这样你就能明白我的意思了:)在阅读过程中,请注意与第一份工作描述的一些相似之处:
Y 公司数据科学家职位的工作描述
我们可以从 Y 公司的招聘启事中获得什么信息?
这一职位的强有力候选人似乎需要具备以下条件:
- 对统计学有很好的理解,具有优秀的批判性思维能力
- 非常强的沟通和数据可视化技能。
- 编程语言(最好是 Python,因为它是最流行的)
- 结构化查询语言
- 数据清理和数据操作。
- 机器学习(对特定模型有不同的侧重)
- 时间序列分析(预测)
- 对于这一特定角色,销售背景将受到高度重视
第二个角色比第一个角色更专业,但是你看到两者之间的所有相似之处了吗?使用这种逆向工程策略可以消除在计算成为数据科学家需要学习哪些技能时的猜测。雇主实际上是在告诉你他们想让你知道的事情。想象一下,通过 5 个职位,你将能够收集到多少额外的信息,非常令人兴奋。
一旦你完成了最常见和最特殊的技能的汇总,你就为你的学习创造了“检查点”,为了成功,你必须带你去那里。现在,我们实际上可以构建您自己的行业发展道路
建设你的道路
现在你知道了什么是踏脚石,你可以开始规划你想如何开始你的学习。没有正确或错误的方法,但理想情况下,您会希望首先专注于数据科学家的核心技能,从学习 Python 语法开始。我建议在学习熊猫、Numpy 和 SciPy 之前先学习属性(或者你可以一起学习:)
大多数职位招聘都需要以下技能(我也提到了与之相关的 Python 库):
- 统计数据(熟悉使用 SciPy 和 Numpy 来分析关于数据的统计数据)
- Python 编程(免费学习 Python 基础知识这里
- 数据清理、争论和形状操纵(Numpy 和 Pandas)
- 数据可视化(Pandas、Seaborn、Matplotlib、Pyplot 等等)
- 监督和非监督机器学习(Scikit Learn)
学习上面的 Python 包的一个很好的资源是Python 数据科学手册以及搜索文档的特定库
学习策略
作为给你的临别礼物,我强烈推荐看看这篇关于基于项目的学习的文章。因为您有如此多的东西要学,有如此多的技能要掌握,所以您会希望通过创建不同的项目来开发您在真实世界数据上的技能,从而在真实世界的场景中实践它们。
通过使用基于项目的学习,你不仅可以更容易地单独掌握每项技能,还可以开发将多项技能结合使用的方法,以从数据中获得强大的洞察力。如果您需要访问真实世界的数据资源,请点击这里查看这篇文章。随着你完成越来越多的项目,并进一步发展你的技能,你可以随时回到你以前的项目,并对它们进行修改,使它们成为你简历中的最佳分析。
好吧,那对我来说就够了。非常感谢您花时间阅读我的文章,我希望我能够为您的数据科学之旅提供一点帮助。下次再见,祝你这周过得愉快!
我叫 Kishen Sharma,是一名数据科学家,在旧金山湾区工作。我的使命是教授和激励全世界有抱负的数据科学家。
请随时在 Instagram 上与我联系,并在这里查看我的附加内容。你也可以在这里查看我的其他文章。
综述:药物发现中的深度学习
深度学习算法已经在许多不同的任务中实现了最先进的性能。卷积神经网络(CNN)可用于在图像分类、对象检测和语义分割任务中实现出色的性能。递归神经网络(RNNs)及其后代,如 LSTMs 和 GRUs 以及 transformers,是人们首先想到的解决神经语言翻译、语音识别等问题的方法,甚至可以用来生成新的文本和音乐。
药物发现是可以从深度学习的成功中受益匪浅的领域之一。药物发现是一项非常耗时且昂贵的任务,深度学习可以用来使这一过程更快、更便宜。
最近,围绕这个主题发表了许多论文,在这篇文章中,我将详细回顾一下如何在这个领域使用深度学习。
我可以将深度学习在药物发现中的应用主要分为三个不同的类别:
- 药物性质预测
- 从头药物设计
- 药物-靶标相互作用(DTI)预测
图 1:深度学习可以帮助和促进药物发现的三个领域。
在下文中,我试图详细阐述每一类并讨论一些相关的论文。
药物性质预测
机器学习问题大致分为三个子组:监督学习、非监督学习(自我监督学习)和强化学习。药物性质预测可以被框架化为监督学习问题。算法的输入是药物(化合物),输出是药物性质(例如,药物毒性或溶解度)。
- 输入:一种药物(小分子)
- 输出:0–1 个标签,表示药物是否具有某些特性。它也可以被设计为多标签分类或回归任务。
图 2:表示分子的不同方式。
因此,有不同的方法来表示一种药物(化合物):
- 分子指纹
- 基于文本的表示(例如,微笑、InChIKey、自拍)
- 图形结构(二维或三维图形)
分子指纹
在机器学习框架的输入管道中表示药物的一种方式是分子指纹。最普遍的指纹类型是一系列二进制数字(位),代表分子中特定亚结构的存在或不存在。因此,药物(小化合物)被描述为 0 和 1 的向量(阵列)。
图 3:如何用二元向量表示一个分子。
它在文献中被广泛使用1。但是,很明显,将分子编码为矢量不是一个可逆的过程(这是一个有损变换);也就是说,我们不能从指纹中完全重建一个分子,这表明在这个操作过程中丢失了许多信息。
代表一个小分子有许多不同的指纹。你可以跟随这份指南【2】去了解更多。
微笑代码
另一种表示分子的方式是将结构编码成文本。它是将图形结构数据转换为文本内容并在机器学习管道中使用文本(编码字符串)的方式。标准之一和最流行的代表是简化的分子输入行输入系统(SMILES)。转换后,我们可以使用自然语言处理(NLP)文献中的强大算法来处理药物,例如,预测属性、副作用,甚至化学-化学相互作用。孙英权【3】。
图 4:如何用 SMILES 代码表示一个分子。
如果你有兴趣了解更多关于微笑的知识,你可以点击这个链接【4】。虽然 SMILES 在化学家和机器学习研究人员中非常流行,但它不是唯一可用于表示药物的基于文本的表示。InChIKey 是另一个你可以在文学作品中找到的流行代表。 Mario Krenn 等人 [5]提出的自拍照(自引用嵌入字符串),基于乔姆斯基 type-2 语法。我在从头药物设计部分更多地谈论它们(优点)。
图形结构数据
对图结构数据进行深度学习的流行,如图卷积网络[ Thomas Kipf ] 6,使得直接使用图数据作为深度学习管道的输入成为可能。
例如,化合物可以认为是一个图,其中顶点是原子,原子之间的化学键是边。我们已经看到在图形神经网络领域取得了显著的成功
,并且有诸如深度图形库、 PyTorch-Geometric 、 PyTorch-BigGraph 等库专门致力于这项工作。
药物-靶标相互作用预测
蛋白质在生物中起着核心作用;即蛋白质是生物细胞内外大多数功能的关键角色。例如,有一些蛋白质负责凋亡、细胞分化和其他关键功能。另一个重要的事实是,蛋白质的功能直接依赖于它的三维结构。即改变蛋白质的结构可以显著改变蛋白质的功能,这是药物发现的重要事实之一。许多药物(小分子)被设计成与特定的蛋白质结合,改变它们的结构,从而改变功能。此外,至关重要的是要注意到,仅改变一种蛋白质的功能就能对细胞功能产生巨大影响。蛋白质直接相互作用(例如,你可以看到蛋白质-蛋白质网络),而且一些蛋白质充当转录因子,这意味着它们可以抑制或激活细胞中其他基因的表达。因此,改变一种蛋白质的功能可以对细胞产生巨大的影响,并可以改变不同的细胞途径。
图 5:胶原粘附素和胶原复合物结构。
因此,计算药物发现中的一个重要问题是预测特定药物是否能与特定蛋白质结合。这是一个被称为药物-靶标相互作用(DTI)预测的概念,近年来受到了极大的关注。
我们可以按如下方式构建 DTI 预测任务:
- 描述:预测化合物和蛋白质结合亲和力的二元分类(它可以形式化为回归任务或二元分类)
- 输入:化合物和蛋白质表示
- 输出:0–1 或[0–1]中的实数
冯庆元等【7】提出了一个基于深度学习的药物-靶标相互作用预测框架。大多数用于 DTI 预测的深度学习框架都将化合物和蛋白质信息作为输入,但区别在于它们使用什么表示来输入神经网络。正如我在上一节中提到的,化合物可以用多种方式表示(二进制指纹、微笑代码、从图形卷积网络提取的特征),蛋白质也可以有不同的表示方式。根据输入表示,可以使用各种架构来处理 DTI 预测。
例如,如果我们要对化合物和蛋白质使用基于文本的表示(化合物和氨基酸的 SMILES 代码或蛋白质的其他基于序列的描述符),首先想到的就是基于 RNNs 的架构。
Matthew Ragoza 等人提出了一种利用卷积神经网络进行蛋白质配体评分的方法【8】。他们利用蛋白质配体的三维(3D)表示,而不是基于文本的表示。因此,他们决定使用卷积神经网络,该网络可以作用于这种 3D 结构,并提取有意义的适当特征来预测蛋白质配体结合亲和力。
最近, Bo Ram Beck et al. 建议采用分子转换器药物靶点相互作用(MT-DTI)来识别可作用于 2019-nCoV 病毒蛋白的市售药物。
虽然提出深度学习算法用于计算机模拟 DTI 预测已经成为一种趋势,并且在某些情况下取得了令人印象深刻的结果,但这些论文非常相似,我在其中发现的唯一创新是输入表示的选择,以及随后对输入进行操作的架构。因此,我可以将这项任务总结如下:
- 查找包含化合物和目标信息的数据库,以及它们是否相互作用(例如,缝合数据库)。
- 最常见的是,在 DTI 预测中,网络将一对化合物和蛋白质作为输入。
- 你应该选择你认为适合化合物和蛋白质的表示法。我回顾了其中一些,但还有其他的表述。
- 根据您选择的表示,您应该考虑合适的神经网络架构来处理输入。根据经验,在基于文本的输入表示的情况下,可以使用基于 RNNs 的架构(GRU、LSTM……)和转换器,在图像或 3D 结构的情况下,可以使用卷积神经网络。
- 该问题可以被认为是二元分类(化合物是否与靶结合)或回归(预测化合物和蛋白质之间的亲和力强度)。
所以,这就是 DTI 预测。起初,这可能看起来是一个困难和具有挑战性的任务,但是我读过的论文使用了非常简单的技术和策略来解决这个问题。
从头药物设计
到目前为止,我们只是观察了判别算法;即,给定一种药物,算法可以预测副作用和其他相关属性,或者给定化合物-蛋白质对,它将预测它们是否可以结合。然而,如果我们对设计一种具有某些特性的化合物感兴趣呢?例如,我们希望设计一种化合物,它可以结合特定的蛋白质,修饰某些途径,并且不与其他途径相互作用,还具有某些物理性质,如特定的溶解度范围。
我们不能用我们在前面章节中介绍的工具包来解决这个问题。这个问题最好在生成模型的领域中实现。
生成模型,从自回归算法、归一化流、变分自动编码器(VAEs)到生成对抗网络(GANs),已经在机器学习社区中变得普遍和广泛。然而,在重新设计药物的任务中利用它们的尝试并不是很早。
问题是,产生一种化合物,给定某些期望的性质。显而易见,这比我们在上一节中讨论的另外两个问题更难。
可能的化学分子空间非常大,在这个空间中寻找合适的药物非常耗时,几乎是不可能完成的任务。我看到了应用生成模型设计化学分子的最新趋势。虽然文献中有一些有希望的结果,但这一领域还处于起步阶段,需要更成熟的方法。在这里,我将回顾我在这一领域读过的一些最好的论文。
你可以在文献中找到很多论文,这些论文把微笑作为输出,最后,把微笑转换成化学空间。
Rafael Gomez-Bombarelli 等人提出了一种利用数据驱动的分子连续表示进行自动化学设计的方法【9】。
图 5:使用变分自动编码器生成具有期望属性的化合物。来源:拉斐尔·戈麦斯-邦巴里等人。
他们使用 VAEs 来产生分子。输入表示是 SMILES 代码,输出也是 SMILES 代码。
本文中的巧妙之处在于使用潜在空间(连续空间)中的高斯过程来达到具有期望属性的点。
然后,使用解码器将潜在空间中的该点转换(解码)为 SMILES 码。论文写得很好,绝对值得推荐阅读。
然而问题是,SMILES 码和分子之间并不是一一对应的。即,不是所有产生的代码都可以转换回原始(化学)空间,因此,产生的 SMILES 代码通常不对应于有效分子。
微笑是非常受欢迎的表示,但是它们有一个很大的缺点:微笑不是健壮的表示。即,改变微笑中的一个字符(字符突变)可以将分子从有效变为无效。
Matt J. Kusner 等人提出了语法 VAE 来专门解决这个问题(产生与有效分子不对应的微笑代码)[10]。
他们不是将 SMILES 字符串直接输入网络并生成 SMILES 代码,而是将 SMILES 代码转换成解析树(通过利用 SMILES 上下文无关语法)。使用语法,他们可以生成更多语法上有效的分子。此外,提交人指出:
令人惊讶的是,我们表明,我们的模型不仅更经常地生成有效输出,它还学习了一个更连贯的潜在空间,其中附近的点
解码为类似的离散输出。
最近,Mario Krenn 等人提出了另一种基于 VAE 和自拍表现的方法[5]。自拍的主要优点是结实耐用。
但是,这些都是深度学习领域产生小分子的作品的小样本。基于化合物的表示(微笑、自拍、图形……)和生成算法(、甘、标准化流、遗传算法),您可以在文献中找到不同的方法(下表)。
结论
在这篇文章中,我试图回顾深度学习在药物发现中的一些应用。显然,这篇综述并不完整,我也没有时间覆盖更多的领域(我也不想让这篇文章更长),但我试图为好奇的读者提供参考。我希望这篇文章能鼓励你为这个领域做出贡献,让药物发现变得更便宜,更简单。
参考
- 数据库指纹(DFP):一种表示分子数据库的方法, Eli Fernández-de Gortari 等人
- RDKit 中的指纹
- DeepCCI:用于化学-化学相互作用预测的端到端深度学习, Sunyoung Kwon
- OpenSMILES 规范。链接
- 自拍:语义约束图的鲁棒表示,以及在化学中的示例应用, Mario Krenn 等人
- 图卷积网络,托马斯·基普夫
- PADME:基于深度学习的药物-靶点相互作用预测框架,冯庆元等
- 用卷积神经网络进行蛋白质-配体评分, Matthew Ragoza 等人
- 使用数据驱动的连续分子表示进行自动化学设计, Rafael Gomez-Bombarelli 等人
- 语法变分自动编码器,马特 j .库斯纳等人
- 针对序列生成模型的目标增强型生成对抗网络(ORGAN), Gabriel Guimaraes 等人
- 用于分子图生成的连接树变分自动编码器,晋文公等
- 深度学习能够快速识别有效的 DDR1 激酶抑制剂, Alex Zhavoronkov 等人
- 用深度神经网络增强遗传算法以探索化学空间, AkshatKumar Nigam 等人
- 寻找可合成分子的模型,约翰·布拉德肖等人。
回顾:纽维尔·ECCV 16 年和纽维尔·POCV 16 年——堆叠沙漏网络(人体姿势估计)
使用堆叠沙漏网络的自下而上和自上而下的重复处理,胜过了 DeepCut 、 IEF 、汤普森 CVPR 15和 CPM 。
多重堆叠沙漏网络
在这个故事里,16 级的纽维尔·ECCV 和 16 级的纽维尔·POCV,由密执安大学创作,回顾。在纽维尔·POCV 的 16 中,仅使用了 2 个堆叠沙漏网络,而在纽维尔·ECCV 的 16 中,使用了 8 个堆叠沙漏网络。ECCV 的版本更详细,引用了 1500 多次。因此,这里介绍 ECCV 的情况。( Sik-Ho Tsang @中)。
概述
- 网络架构
- 中间监督
- 一些训练细节
- 消融研究
- 与 SOTA 方法的比较
- 进一步分析
1。网络架构
单个“沙漏”模块(不包括最后的 1×1 层)。每个盒子对应于如下剩余模块。
一个剩余模块。
- 卷积层和最大池层用于处理低至极低分辨率的特征。
- 达到最低分辨率后,网络开始自上而下的上采样序列和跨尺度的特征组合。
- 对于上采样路径,完成较低分辨率的最近邻上采样**,随后是两组特征的逐元素相加**。
- 在达到网络的输出分辨率后,应用两轮连续的 1×1 卷积来产生最终的网络预测。
- 最终设计大量使用了剩余模块。
- 从不使用大于 3×3 的过滤器。
2.中间监督
中间监督
- 网络分裂并产生一组热图(蓝色轮廓),其中可以应用损失。
- 1×1 卷积重新映射热图以匹配中间特征的通道数量。这些要素与前面沙漏中的要素一起添加。
- 在最终的网络设计中,使用了八个沙漏。
3.一些训练细节
- FLIC : 5003 张图片(3987 次训练,1016 次测试)取自电影。
- MPII 人体姿态 : 25k 带注释的图像,供多人使用,提供 40k 带注释的样本(28k 训练,11k 测试)。
- 约 3000 个样本的验证集。
- 然后,所有输入图像的大小都被调整为 256×256 像素。我们进行数据扩充,包括旋转(30 度)和缩放(0.75-1.25 度)。
- Torch7,在 12GB 的 NVIDIA TitanX GPU 上训练需要 3 天左右。
- 使用批量标准化。
- 为了生成最终的测试预测,我们通过网络运行原始输入和图像的翻转版本,并将热图平均在一起。
示例输出(从左到右:脖子、左肘、左手腕、右膝盖、右脚踝)
- 如上所示,网络的最终预测是给定关节的热图的最大激活位置。
4。消融研究
4.1.变体
随着培训的进展验证准确性
- HG-Half :表现最差的单个沙漏。
- HG: 单个长沙漏,性能更好。
- HG-Int :单个长沙漏,中间监督,性能更好。
- HG-Stack :两个堆叠沙漏但没有中间监管,性能类似。
- HG-Stack-Int :两个堆叠沙漏中间监督,性能最佳。
4.2.沙漏数
- 左:示例验证图像,说明从中间阶段(第二个沙漏)(左)到最终预测(第八个沙漏)(右)的预测变化。
- 右:比较不同堆叠方式下网络中间阶段的验证精度。
- 从 87.4%到 87.8%再到 88.1 %的每一次叠加,最终性能都会有适度的提高。
5.与 SOTA 方法的比较
5.1.警察
- 99%的 PCK@0.2 精度在肘部,97%在腕部。
- 所提出的方法优于 SOTA 的方法,例如 DeepPose 、汤普森 CVPR 15和 CPM 。
5.2.MPII
- 所提出的方法优于 SOTA 的方法,包括 DeepCut 、 IEF 、汤普森 CVPR和 CPM 。
- 在像手腕、肘部、膝盖和脚踝这样的困难关节上,所提出的方法在 SOTA 结果的基础上平均提高了 3.5% (PCKh@0.5),平均错误率从 16.3 %下降到 12.8%。
- 最终肘关节准确率为 91.2%,腕关节准确率为 87.1 %。
MPII 的一些例子
6.进一步分析
6.1 多人
多个人靠在一起甚至重叠
- 检测多人超出了本文的范围。但是作者仍然分析它。
- 通过轻微平移和改变输入图像的比例,检测到不同的人或没有人。
6.2.闭塞
左图 : PCKh 曲线,验证比较仅考虑可见(或不可见)接头时的性能。右:显示预测一个关节是否存在注释的精确度的精确召回曲线。
- 在仅考虑可见关节的情况下,腕部准确度从 85.5%上升到 93.6%(验证性能略差于测试集性能 87.1 %)。另一方面,在完全闭塞的关节上的性能是 61.1 %。
- 对于肘部,对于可见关节,准确率从 90.5%到 95.1%,对于遮挡关节,准确率下降到 74.0%。
- 在存在注释的情况下,获得了 AUC 为 92.1%的膝盖和 AUC 为 96.0%的脚踝。这是在 2958 个样本的验证集上完成的,其中 16.1%的可能膝盖和 28.4%的可能脚踝没有地面真实注释。
参考
【2016 ECCV】【纽维尔·ECCV’16用于人体姿态估计的堆叠沙漏网络
【2016 POCV】【纽维尔·POCV’16用于人体姿态估计的堆叠沙漏网络
(我已经下载了但是抱歉现在找不到链接。这是一篇只有 2 页的论文,还不如看 ECCV 版,哈哈。)
我以前的评论
图像分类[lenet][alexnet][max out][in][znet][] [ 感受性-v3 ] [ 感受性-v4 ] [ 异常][mobile netv 1][resnet][[预活化 ResNeXt ] [ 致密 ] [ 金字塔网][drn][dpn][残馀关注网络【t】
物体检测 [ 过食 ] [ R-CNN ] [ 快 R-CNN ] [ 快 R-CNN][MR-CNN&S-CNN][DeepID-Net][CRAFT][R-FCN][离子 [G-RMI][TDM][SSD][DSSD][yolo v1][yolo v2/yolo 9000][yolo v3][FPN[retina net[DCN
语义分割 [ FCN ] [ 解码网络 ] [ 深层波 1&][CRF-rnn][] [fc-denne][idw-CNN][说][sdn][deep labv 3+
生物医学图像分割[][【T2/DCA】][【u-net】[【CFS-fcn】 [ 注意 u-net][ru-net&r2u-net][voxrsnet][致密电子数码 ][ UNet++
实例分割 [ SDS ] [ 超列 ] [ 深度掩码 ] [ 清晰度掩码 ] [ 多路径网络 ] [ MNC ] [ 实例中心 ] [ FCIS
超分辨率[SR CNN][fsr CNN][VDSR][ESPCN][红网][DRCN][DRRN][LapSRN&MS-LapSRN][SRDenseNet][【T20
人体姿势估计深层姿势][tompson nips’14][tompson cvpr’15][CPM[fcgn
后处理编码解码器【arcnn】][【Lin DCC ' 16】][【ifcnn】][【Li icme ' 17】[vrcnn【t】
生成对抗网络 [ 甘
从求职者的角度看“在数据科学领域建立职业生涯”
艾米莉·罗宾逊和杰奎琳·诺利斯写得很好的这本书的前半部分带来了新的积极和展望
自 3 月初以来,我一直在积极申请西雅图的数据科学工作。我刚刚在 Flatiron 完成了我的数据科学训练营,我非常兴奋能够去那里找到我梦想中的工作。不幸的是,3 月初也是美国新冠肺炎危机的开端。这场危机极大地抑制了数据科学家的就业市场,但幸运的是没有其他职业那么糟糕。然而,现在我几乎已经找了三个月的工作,却没有真正的机会来展示自己作为一名职业生涯早期的数据科学家,我尽最大努力保持乐观,同时想办法确保我给人留下最好的印象。
Emily Robinson 和 Jacqueline Nolis 的提示“在数据科学领域建立职业生涯!几个月前,这本书出现在我的 LinkedIn 时间轴上,但当时我非常乐观,不认为我需要投资一本自助书来让我继续找工作。然而,随着工作前景停滞不前,我开始认真考虑更多的资源来帮助我获得竞争优势,我记住了这本书。事实上,几年前,当我开始考虑在数据科学领域发展时,我有幸见到了 Jacqueline。Jacqueline 和她的妻子 Heather(我的高中同学)是一个数据科学梦之队,我和他们一起喝了一杯内容丰富、令人鼓舞的午后咖啡。因此,我决定买杰奎琳的书,如果没有别的,只是为了支持诺利斯一家!
在这篇文章中,我将回顾这本书的前半部分,这本书由四部分组成,重点是培养数据科学所必需的技能以及如何获得你的第一份工作。(后半部分讨论了如何在找到工作后推进你的职业发展,所以我现在不打算回顾这一部分。不过,一旦我找到第一份工作,我肯定会回来的!)我将总结每一章,并讨论我从每一章中获得的宝贵观点。
如果你没有通读我的整篇文章,让我至少这样说:如果你对如何寻找数据科学工作感到迷茫,请阅读这本书!
“在数据科学中建立职业生涯”写得非常好,清晰,引人入胜,并为有抱负和已建立的数据科学家提供了很多很好的建议。它的目的不是教你在数据科学领域工作所需的技能,而是教你如何在这个新的快速变化的领域追求和发展你的职业生涯。每章涵盖职业生涯建设中的不同主题,并包括与一位知名数据科学家的简短访谈,该访谈提供了该章中给出的信息的真实示例。如果你正在考虑数据科学,寻找数据科学方面的工作,或者甚至试图推进你目前的数据科学职业生涯,这本书正适合你。
第 1 部分:数据科学入门
“在数据科学领域建立职业生涯”的前四章介绍了该行业,并就如何发展数据科学工作所需的技能以及建立展示这些技能的投资组合给出了建议。当我第一次翻阅这本书时,我并不认为我会在这一部分学到很多东西,但事实证明它真的提供了很多信息,并极大地改变了我在求职申请中考虑“推销自己”的方式。
第 1 章—什么是数据科学?
第一章给出了当今数据科学领域的概述。如果你对数据科学工作做过任何研究,你可能已经意识到这个领域非常广泛,角色可能会因招聘公司的不同而有所差异(更多信息请见第二章)。Robinson 和 Nolis 通过将该领域呈现为一个三角形来提供一些组织,在三角形的每个角上都有领域知识、数学和统计、编程和数据库方面的技能。根据连接的两个角,您有不同类型的数据科学工作。连接领域知识和数据库的三角形边代表数据分析工作。这些工作人员可能具有商业、经济或统计背景,并且将大部分时间花在开发工具上,例如仪表板,以汇总并向利益相关者呈现数据趋势和报告。将编程/数据库与数学和统计联系起来的一方代表机器学习工程师,他们致力于开发和部署机器学习模型。这些人通常有软件工程或计算机科学的背景,他们的工作与软件开发人员非常相似。连接领域知识与数学和统计学的三角形的最后一边代表决策科学家。这些工作人员能够制定适当的数据分析和开发预测模型,然后根据业务目标解释并向利益相关者展示结果。作者还讨论了商业智能分析师和数据工程师等相关工作,但将他们排除在数据科学领域之外。最后,他们讨论如何选择适合你自己经验和技能的子领域。
我发现这种数据科学工作的分类非常有用。在我自己的求职过程中,我一直很困惑什么样的工作需要什么样的技能。我知道我在科学交流和研究、数学和统计方面有很强的背景,我知道我的技能在某种程度上适合数据科学,但不确定具体要找什么样的工作!现在我知道决策科学工作可能是最适合我的,我计划开始专门寻找这些工作。
第 2 章—数据科学公司
本章根据行业、公司年龄和规模描述了几个假设公司的数据科学。这些描述了你期望在这些公司从事什么样的工作,那里的文化是什么样的,以及你在那里工作时可能面临的挑战和自由。从大型科技公司,如微软、苹果和脸书,到小型创业公司,这些描述让你了解哪种类型的公司适合你自己的工作方式、目标和经历。
虽然这些是对每种公司类型的概括,它们不会对属于这一类别的每家公司都准确,但这些信息让你在与公司员工进行信息面试和申请工作时记住一些东西。我对这一章的唯一批评是,作者没有讨论基于合同的工作,如咨询公司的工作。也许这是西雅图成熟的数据科学市场的产物,但这些代表了我看到发布的许多入门级职位,我与之交谈的许多人在能够获得 FTE 的中高级职位之前都经历过这种类型的职位。我很想看看作者对这些公司和职位的看法!
第 3 章——获得技能
本章重点介绍如何培养您从事数据科学职业所需的技能,无论您刚刚获得学士学位,拥有数据分析或研究方面的研究生经验,还是正在尝试从一个数据职业过渡到另一个职业。他们为学习数据科学技能提供了四种不同的选择:(1)数据科学学位,如硕士学位,(2)数据科学训练营,(3)通过在线课程和出版材料自学,或(4)在职学习,如果您当前的工作可以支持的话。他们给出了非常务实和合理的建议,解释了为什么你会根据自己的背景和时间选择一条路线。
对于刚刚开始数据科学之旅的人来说,这将是一个伟大的篇章。虽然我已经完成了一个训练营,但它并没有给我提供太多关于我自己找工作的见解,但它确实给了我信心,让我相信考虑到我的经历,我选择了正确的道路。
第 4 章——建立投资组合
根据你的背景,你可能没有任何与工作相关的数据科学经验可以写进简历。本章强调了拥有一个作品集来展示你努力学习的技能的重要性。作者提出了适当范围的项目,如何为他们找到数据,如何使他们脱颖而出,以及展示他们结果的最佳方式。他们讨论维护博客的好处(比如我的!)向各种受众清晰传达数据科学项目。这一章对于开发你自己的投资组合项目从开始到传播是一个很好的指导。
第二部分:找到你的数据科学工作
“在数据科学领域建立职业生涯”的第二部分是我最感兴趣的部分。这是如何在求职中取得成功的关键,从寻找空缺职位到参加面试和协商工作机会。这四章给出了很多关于完善你的申请和在这个过程中保持自我价值完整的建议。
第 5 章——寻找:找到适合你的工作
现在,您已经具备了从事数据科学工作所需的技能,并且有了突出这些技能的作品集,下一步就是找工作了!本章主要讲述如何找到一个适合你在公司寻找的职位,以及如何解读一份招聘启事,这样你就知道对这个职位有什么期望,以及公司对一个成功的应聘者有什么期望。作者给出了一些建议,告诉你应该避免什么类型的工作列表,比如臭名昭著的“独角兽”职位,以及你应该把精力放在什么类型的申请上。他们给出了如何找到工作的建议,比如参加聚会和使用社交网络。
我认为本章给出的建议真的很棒,尤其是在就业市场强劲的时候,但现在你可能不会像作者鼓励的那样有选择性。我打算在自己的求职中应用的两点是:(1)不要每天找工作,(2)拓宽你的搜索范围。我已经开始在每个工作日查看求职公告板,但是一周查看 2-3 次已经足够了,可以帮助我专注于求职的其他部分。我也将开始考虑更多不是“数据科学家”的职位,希望我能找到适合我的技能和目标的工作。
第六章——申请:简历和求职信
这一章是关于确保你的技能和经验的书面陈述足够好,以引起招聘人员的注意,并使他们相信他们找到了一个适合他们空缺职位的合适人选。有简历和求职信的样本,以及优化它们的方法的描述。作者给出了如何突出你的数据技能的建议,即使是以前与数据科学无关的职位。他们讨论了为该职位定制文件的重要性,以及如何巧妙地获得推荐。
就我个人而言,我很欣赏关于如何充分利用你以前的经历的建议。虽然我以前听说过,但我也需要提醒你根据职位量身定制申请材料。本章建议不要试图“玩数字游戏”,而是把更多的精力放在申请你认为最适合你的工作上。
第七章——面试:期待什么以及如何应对
我将要描述的最后两章涵盖了我几乎没有经验的工作申请过程,但我希望能尽快将理论付诸实践!这一章是关于面试过程的,可能是最可怕和最伤脑筋的部分。作者给出了许多公司面试过程的一般描述,从最初的电话面试,到现场面试,样本项目和最终面试。它们不仅描述了如何完成每一步,从而证明你能胜任这份工作,并且你会很好地与之共事,还描述了如何获得关于你是否想同时为该公司工作的信息。他们提供了如何在面试中回答技术和行为问题的建议,另外还有一个练习用的样题附录!
第 8 章——提议:知道接受什么
这一章涵盖了一个非常令人兴奋的前景:如何谈判你的工作机会!假设你成功通过了面试,现在是时候制定你的工作细节了。本章讨论何时以及如何协商你的薪水、福利等。招聘人员/招聘经理。它还讲述了如何在两个竞争的报价之间进行权衡和选择(如果你足够幸运处于那个位置的话!).
这一章给像我这样的人提供了很多好的建议:在问我想要什么时胆怯,患有冒名顶替综合症,在谈判工作机会方面缺乏经验。它甚至有一个专门关于处理冒名顶替综合症的小广告——我可能会经常提到它!希望我(和其他阅读这篇文章的人!)将很快使用这些技术!
最后的想法
结束这篇相当长的帖子(对不起大家!),不得不说总体来说到目前为止我对这本书印象非常深刻。这真的是一种资源,当我需要信心提升或关于下一步该做什么的建议时,我可以看到自己在参考。它已经帮助我重新考虑如何解决我自己的求职问题,我相信这本书的后半部分将在我找到工作并希望不断提升时指导我。
显然,这本书是在疫情对我们的经济造成损害之前写就并出版的。我很想听听罗宾逊和诺利斯对这个新的在家工作、早期职业机会有限的就业市场有什么建议。例如,我们应该如何以及何时考虑一个完全遥远的职业与一个我们可以选择(希望很快)与同事在办公室工作的职业?我们怎样才能说服公司考虑我们或者把我们记在心里,即使他们现在不招人?在等待招聘再次增加的同时,我们能做些什么来保持前进?
最后,我要感谢艾米丽和杰奎琳写了这本书。这是一个奇妙的资源,我期待着将他们的建议应用到我自己的职业生涯中。希望这篇文章也能说服你去读这本书!像往常一样,随时留下评论或问题!
表格数据的 GANs
我们非常了解 GANs 在现实图像生成方面的成功。但是,它们可以应用于表格数据生成。我们将回顾和检查一些最近的论文,关于表格式甘在行动中。关于最终结果和源代码,可以去 Github 仓库。
看看我的机器和深度学习博客https://diyago.github.io/
甘是什么
GAN 由两个深层网络组成:发生器和鉴别器【1】。两人同时训练。通常,模型结构和训练过程是这样表示的:
GAN 培训管道。什么是生成性敌对网络?【1】
****发生器的任务是产生样本,样本不会被鉴别器从真实样本中区分出来。我不会在这里给出太多细节,但如果你想深入研究它们,你可以阅读媒体帖子和伊恩·j·古德费勒的原文。
最近的架构,如 StyleGAN 2,可以产生出色的照片级逼真图像。
由 StyleGAN 2,SsourcearXiv:1912 . 04958 v2[7]生成的人脸精选示例
问题
虽然人脸生成似乎不再是一个问题,但我们仍有许多问题需要解决:
- 训练速度。对于训练 StyleGAN 2,您需要 1 周和 DGX-1 (8x NVIDIA Tesla V100)。
- 特定领域的图像质量。最先进的网络在其他任务上仍然失败。
StyleGAN 2 生成的汽车和猫的精选示例,来源 arXiv:1912.04958v2 [7]
表格甘斯
由于不平凡的数据分布和高度的对象类型多样性,对于 GANs 来说,即使是生成猫狗也是一项繁重的任务。除此之外,图像背景也变得很重要,这是 GANs 通常不能产生的。
因此,我一直在想 GANs 在表格数据上能达到什么样的效果。可惜文章不多。接下来的两篇文章似乎是最有希望的。
TGAN:使用生成对抗网络合成表格数据 arXiv:1811.11264v1 3
首先,他们提出了几个问题,为什么生成表格数据有自己的挑战:
- 各种数据类型(整数、小数、类别、时间、文本)
- 不同形状的分布(多模态、长尾、非高斯……)
- 稀疏的一次性编码向量和高度不平衡的分类列。
任务形式化
假设表 T 包含 n_c 连续变量和 n_d 离散(分类)变量,每一行都是 C 向量。这些变量具有未知的联合分布P。每一行都是从 P 中独立采样的。目标是训练生成模型M。M应生成新的合成表 T_synth ,其分布类似于 P. 在 T_synth 上学习的机器学习模型应在真实测试台上 T_test 上达到类似的精度,在 T. 上训练的模型也是如此
预处理数值变量。"**使用tanh"【3】,神经网络可以有效地生成以(1,1)为中心的分布值。然而,他们表明,网络不能产生多模态数据合适的数据。因此,他们通过使用和训练高斯混合模型( GMM )对每个 C 使用 m (m=5)个分量来聚类一个数值变量。
使用平均值和标准偏差的 GMM 归一化。来源 arXiv:1811.11264v1 3
最后,使用 GMM 归一化 C 得到 V. 此外,他们计算 C 来自每个 m 高斯分布的概率作为向量 U.
****预处理分类变量。由于基数通常较低,他们发现可以使用 softmax 直接生成概率分布。但是必须将分类变量转换为带有噪声的一位热编码表示,将二进制变量转换为二进制变量
前置后,它们将带有 n_c + n_d 列的 T 转换为 V,U,D 向量。该矢量是发生器的输出,也是 GAN 中鉴别器的输入。“甘没有获得的参数”3。
发电机
他们分两步生成一个数字变量。首先,生成值标量 V ,然后生成聚类向量 U ,最后应用 tanh 。使用 softmax 在所有可能标签上生成概率分布的分类特征。使用注意机制生成所需的行 LSTM。为 LSTM 在每一步中输入的是随机变量 *z、*加权上下文向量与先前隐藏的和嵌入向量。****
鉴别器
使用具有 LeakyReLU 和 BatchNorm 的多层感知机(MLP)。第一层使用中的级联向量 (V,U,D) ,具有来自 LSTM 的特征向量的小批量分集。损失函数是具有和序数对数损失函数的输入变量的 KL 散度项。
使用 TGAN 生成简单人口普查表的示例。生成器逐个生成 T 个特征。鉴别器将所有特征连接在一起。然后使用具有 LeakyReLU 的多层感知器(MLP)来区分真假数据。来源 arXiv:1811.11264v1 3
结果
在真实和合成训练集上训练的机器学习模型的准确性。(贝叶斯网络,高斯连接函数)。来源 arXiv:1811.11264v1 3
***他们在两个数据集 KDD99 和 *covertype 上评估模型。出于某种原因,他们使用了没有 boosting 的弱模型(xgboost 等)。无论如何,TGAN 表现得相当好和稳健,胜过贝叶斯网络。真实数据和合成数据之间的平均性能差距为 5.7%。
使用条件 GAN 对表格数据建模(CTGAN)arXiv:1907.00503 v2[4]
与以前的 TGAN 相比,主要的改进是应用模式特定的归一化来克服非高斯和多峰分布。然后使用条件生成器和抽样训练来处理不平衡的离散列。
任务形式化
最初的数据与在 TGAN 时一样。然而,它们解决不同的问题。
- 健身的可能性。 T_syn 中的列是否遵循与 T_train 相同的联合分布
- ****机器学习功效。当训练模型使用其他列作为特征来预测一列时,从 T_syn 学习的这种模型在 T_test 上能否达到与在 T_train 上学习的模型相似的性能
预处理
离散列的预处理保持不变。
对于连续变量,使用变分高斯混合模型( VGM )。它首先估计模式的数量 m ,然后拟合高斯混合。在我们将初始向量 C 归一化后,它几乎和在 TGAN 时一样,但是它的值在每种模式下都是归一化的。模式表示为一热向量斗鱼([0,0,.., 1, 0]).Alpha 是 C 的归一化值。
特定于模式的规范化示例。来源 arXiv:1907.00503v2 [4]
因此,我们将初始行表示为“一键”离散列的串联,并具有上面讨论的连续变量的表示:
预处理行。来源 arXiv:1907.00503v2 [4]
培训
“最终解决方案由三个关键要素组成,即:条件向量、发电机损耗和采样训练法”[4]。
CTGAN 模型。条件生成器可以根据离散列之一生成合成行。通过采样训练,根据每个类别的对数频率对 cond 和训练数据进行采样,因此 CTGAN 可以均匀地探索所有可能的离散值。来源 arXiv:1907.00503v2 [4]
条件向量
表示所有离散列的串联“一键”向量,但仅指定了一个选定的类别。例如,对于两个离散的列,D1 = {1,2,3}和 D2 = {1,2},条件(D2 = 1)由掩码向量 m1 = [0,0,0]和 m2 = [1,0]表示;所以 cond = [0,0,0,1,0]" [4]。
发电机损耗
“在训练期间,条件生成器可以自由产生任何一组独热离散向量”[4]。但是他们强制条件生成器产生 d_i ( 生成的离散独热列) = m_i (掩码向量)是通过增加它们之间的交叉熵来惩罚它的损失,在批处理的所有实例上平均。
抽样训练
“具体来说,目标是以这样一种方式有效地进行重新采样,即在训练过程中对离散属性的所有类别进行均匀采样,从而在测试过程中获得真实的数据分布”[4]。
换句话说,条件生成器产生的输出必须由评价者评估,评价者估计学习的条件分布 P_G(row|cond) 和真实数据上的条件分布 P(row|cond) 之间的距离。“真实训练数据的采样和 cond vector 的构造应符合帮助评论家估计距离的要求”[4]。对 cond 向量和训练数据进行适当采样可以帮助模型均匀地探索离散列中所有可能的值。
模型结构如下,与 TGAN 相反,没有 LSTM 层。用梯度惩罚的 WGAN 损失训练。
发电机。来源 arXiv:1907.00503v2 [4]
鉴别器。来源 arXiv:1907.00503v2 [4]
此外,他们提出了一个基于变分自动编码器(VAE)的模型,但这超出了本文的范围。
结果
提出的网络 CTGAN 和 TVAE 优于其他方法。正如他们所说,TVAE 在一些情况下优于 CTGAN,但 GAN 确实有几个有利的属性。与 TVAE 不同,GANs 中的生成器在整个训练过程中无法访问真实数据。
基准结果超过三组实验,即高斯混合模拟数据(GM Sim。),贝叶斯网络模拟数据(BN Sim。),以及真实数据。他们报告每个指标的平均值。对于真实数据集(f1 等)。来源 arXiv:1907.00503v2 [4]
此外,他们在 GitHub 上公布了源代码,稍加修改后将在本文中进一步使用。
应用 CTGAN 生成用于增加列车(半监督)的数据
这对我来说是一种香草梦。在简单了解了 GAN 的最新发展后,我一直在思考如何将它应用到我日常工作中解决的一些问题上。这是我的想法。
任务形式化
假设我们有 T_train 和 T_test (分别为 train 和 test set)。我们需要在 T_train 上训练模型,在T _ test上进行预测。但是,我们将通过由 GAN 生成新数据来增加训练,在某种程度上类似于 T_test ,而不使用它的地面真实标签。
实验设计
假设我们有 T_train 和 T_test (分别为 train 和 test set)。 T_train 的尺寸较小,可能有不同的数据分布。首先我们在 T_train 上用地面真值标签 step 1 训练 CTGAN,然后生成附加数据T _ synth*(step 2)**。**其次,我们在串联的 T_train 和 T_synth (目标设置为 0)与 T_test (目标设置为 1) ( 步骤 3 & 4 ) **上以对抗的方式训练 boosting。**目标是应用新训练的对抗性增强来获得更像 *T_test 的行。注意——原始地面真相标签不用于对抗训练。因此,我们从 T_train 和 T_synth 中取出按照与 T_test 的对应关系排序的顶行(步骤 5 & 6 )。最后,对它们进行新的增压,并在 T_test 上检查结果。
实验设计和工作流程
当然,出于基准测试的目的,我们将测试没有这些技巧和另一个原始管道但没有 CTGAN 的有序训练(在步骤 3 中,我们不会使用 T_sync )。
代码
实验代码和结果发布为 Github repo 此处。管道和数据准备基于基准分类编码器的文章及其报告。我们将遵循几乎相同的流水线,但是为了速度,只选择了单一验证和 Catboost 编码器。由于 GPU 内存不足,一些数据集被跳过。
数据集
所有数据集来自不同的领域。他们有不同数量的观察,几个分类和数字特征。所有数据集的目标都是二元分类。数据集的预处理很简单:从数据集中删除所有基于时间的列。其余的列要么是分类的,要么是数字的。另外,在对训练结果进行采样的同时 T_train — 5%、10%、25%、50%、75%
数据集属性
结果
从第一眼的角度来看,就度量和稳定性(std)而言,GAN 显示出最差的结果。然而,对初始训练进行采样,然后应用对抗训练,我们可以获得最佳的度量结果和稳定性( sample_original )。为了确定最佳采样策略,对每个数据集的 ROC AUC 评分进行了缩放(最小-最大缩放),然后在数据集之间进行平均。
不同的采样结果,平均值越高越好(ROC AUC),标准差越低越好(100% —每个数据集的最大 ROC AUC)
我们可以看到 GAN 在两个数据集上的表现优于其他采样类型。而在 7 个数据集的 3 个中,来自原始数据的采样优于其他方法。当然也没有太大区别。但是这些类型的取样可能是一种选择。当然也没有太大区别。但是这些类型的取样可能是一种选择。
不同数据集的采样结果,越高越好(100% —每个数据集的最大 ROC AUC)
让我们定义 same_target_prop 等于 1,那么训练和测试的目标比率相差不超过 5%。因此,我们在培训和测试中有几乎相同的目标比率无和样本 _ 原始更好。然而,gan 的表现开始明显好于目标分布变化。
same_target_prop 等于 1,则训练和测试的目标比率仅相差 5%
参考
1乔纳森·惠。甘— 什么是生成性敌对网络甘? (2018),中条
[2]伊恩·古德菲勒、让·普热-阿巴迪、迈赫迪·米尔扎、徐炳、戴维·沃德-法利、谢尔吉尔·奥泽尔、亚伦·库维尔、约舒阿·本吉奥。生成性对抗网络(2014)。arXiv:1406.2661
3徐磊 LIDS,Kalyan Veeramachaneni。使用生成式对抗网络合成表格数据(2018)。arXiv:1811.11264v1 [cs。LG]
[4]徐磊、玛丽亚·斯科拉利杜、阿尔弗雷多·单面山-因方特、卡莉安·维拉马查涅尼。使用条件 GAN 对表格数据建模(2019)。arXiv:1907.00503v2 [cs。LG]
[5]丹尼斯·沃罗廷采夫。基准分类编码器 (2019)。中等职位
6英萨夫·阿什拉波夫。甘换表 (2020)。Github 仓库。
[7] Tero Karras、Samuli Laine、Miika Aittala、Janne Hellsten、Jaakko Lehtinen、Timo Aila。StyleGAN(2019)arXiv:1912.04958 v2[cs。简历]
***8 Insaf Ashrapov,机器与深度学习博客,【https://diyago.github.io/ ***
LeNet-5 述评:如何设计 CNN 的架构
整合知识以定制 CNN 的架构
这篇文章是对一篇旧的、困难的、鼓舞人心的论文的评论:基于梯度的学习应用于文档识别【1】由 Yann LeCun 作为第一作者。你可以找到这篇论文的许多评论。他们中的大多数只关注卷积神经网络( CNN ) LeNet-5 的架构。然而,我想谈谈其他一些有趣的问题:
- 从反向传播的角度看全局可训练系统的概念
- 如何在神经网络的设计过程中整合知识
事实上,本文中提到了 2 个网络。第一个是 CNN ,名为 LeNet-5,第二个叫图变网络( GTN )。在这篇文章中,我只谈论 LeNet-5。
1.全球可训练系统
什么是全球可培训系统?
一个系统通常包括几个模块。从反向传播的角度来看,如果所有的模块都是可微的,模块之间的连接也是可微的,换句话说,梯度的反向传播可以从末端的损失函数回溯到输入,这是一个全局可训练的系统。有时,我们也称之为机器学习问题的端到端解决方案。
我举个例子:我们想在一个图像中标注所有人脸的性别?第一种解决方案是检测所有人脸的位置,然后用只有一张人脸的子图像进行性别分类。第二种解决方案是创建一个模型,该模型将图像作为输入,输出人脸的定位以及相应的性别。在第一种解决方案中,来自定位的误差影响性别分类的性能。但是如果这两个模块是分开的,我们不能使用性别分类的损失函数来优化定位的性能。在第二种端到端解决方案中,定位和性别检测是全局优化的。
全球可培训系统的优势是什么?
如前所述,我们一起优化所有模块。如果我们有足够的数据,相对于非全局可训练系统,该系统可以实现更好的性能。
另一个更重要的优势是:让机器从数据中学习。如果你熟悉 CNN ,你大概听说 CNN 的前几个隐层可以学习图像的强局部模式。以下是论文【2】中的图片 1 中的一些例子。
图 CNN 图层的可视化
一个训练过的 AlexNet 的第一个 CONV 图层(左)和第二个 CONV 图层(右)上的典型滤镜。(来自https://cs231n.github.io/understanding-cnn/
在传统的解决方案中,我们经常给机器学习模型输入手工设计的特征,如筛、拱、*等。*借助全球可训练系统,我们可以让数据告诉我们,对于某项任务,哪些是最重要的特征。
2.用知识设计 CNN
为了从神经网络中获得自学习特性,我们必须为神经网络设计一个好的结构。Yann LuCun 在他的论文中指出,如果没有关于任务的最少量的先验知识,任何学习技术都不可能成功。….整合知识的一个好方法是根据任务定制架构。现在让我们关注在设计一个 CNN 的架构时如何与知识结合。
1962 年,Hubel 和 Wiesel3揭示了猫视觉系统中的局部敏感、方向选择性神经元。在局部连接的约束下,神经元可以学习一些基本的视觉特征,这些特征可以在下一个神经元中被重用或分组以形成新的特征。卷积核可以很好地实现感受野的这种约束。
在此之前,我们找到了一个很好的工具——卷积核来模拟局部敏感的方向选择性神经元。那么如何才能克服图像分类的一些常见困难:平移、尺度、畸变不变性。
让我们首先检查人类是如何实现图像分类的。我们可能会这样做:
- 用一些视觉模式扫描图像,找到一些特征
- 找出特征之间的关系
- 在我们大脑的模式数据库中搜索关系模式
- 找到最相似的一个
为了实现步骤 1,我们可以为同一个特征图固定卷积核的权重,并生成几个特征图。
为了实现步骤 2,我们认为该特征的确切位置不如该特征相对于其他特征的位置重要。因此,我们可以逐步降低空间分辨率(子采样)。然而,当降低图像分辨率时,我们丢失了信息。这就是为什么我们需要增加特征图的数量,尽可能的保留有用的信息。
有了这些知识,我们就有了设计 CNN 的一般原则。
- 使用卷积核
- 共享权重
- 子采样和增加特征图的数量
3.LeNet 架构
3–1.LeNet-5
图 2:LeNet-5 的架构(来自http://vision . Stanford . edu/cs 598 _ spring 07/papers/le Cun 98 . pdf)
图 21显示了 LeNet-5 的架构。
3–2.增强 LeNet-4
LeNet-4 是 LeNet-5 的简化版。它包含 4 个一级特征图,后面是 16 个子采样图。我们认为 LeNet-4 与 LeNet-5 相比是一个较弱的分类器。Yann LuCun 将助推技术应用于 LeNet-4 ,标记为 boosted LeNet-4 。boosting 方法达到了比 LeNet-5 更好的性能精度。
4.其他有趣的地方
在机器学习的研究领域,我们总是提到开发新方法的三个关键方面。Yann LuCun 在他的论文中也提到了这些:
- 高计算能力的机器成本低
- 大型数据库可用
- 强大的机器学习技术是可用的
我们自己的产品也要考虑这些因素。
5.结论
在这篇文章中,我分享了我对如何设计神经网络的理解。我相信这对实现和修改一个 CNN 的实践是有帮助的。
总而言之:
- 在开始机器学习项目之前,检查计算能力、可用数据库、技术支持。
- 一旦项目开始,尽可能多地获取关于项目的先验知识。
- 利用这些知识来设计您自己的网络。
参考
1 LeCun,Yann and Bottou,Léon and Bengio,Yoshua and Haffner,Patrick 基于梯度的学习应用于文档识别 IEEE,1998
[2] 理解和可视化卷积神经网络
3 D. H. Hubel,T. N. Wiesel,猫视觉皮层中的感受野、双眼互动和功能结构《生理学杂志》,1962 年
跳板数据科学职业生涯回顾
根据我在全职工作期间完成跳板数据科学课程的经验
迪伦·诺尔特在 Unsplash 上的照片
今年早些时候,当我完成了跳板数据科学职业跟踪课程时,许多人联系我,希望了解更多关于该计划、课程和我的体验。这篇文章基于我的个人经历,回顾了我在跳板数据科学课程中的经历。对于一个 TL 来说;版本博士,请随意跳到最后列出的赞成和反对意见。
如今,对于想要向数据科学进行职业转型或只想发展额外技能的工作专业人士来说,在线上有几个免费和付费的选择。我希望这篇文章能帮助那些考虑参加正式数据科学课程的人,了解他们能从跳板项目中得到什么。这应该有助于那些考虑正式项目的人更好地比较跳板和其他项目,并就它是否符合他们的学习目标做出明智的决定。请注意,这篇评论是基于我在 2019 年底/2020 年初参加的“跳板数据科学职业生涯”计划的个人经历。
在开始课程概述之前,我将先介绍一下我的一些背景以及我报名参加这个项目的动机。希望这能让我的观察更准确。当我参加这个项目时,我拥有机械工程博士学位,并在半导体制造行业做了两年左右的工艺工程师。在这一点上,我完成了几个项目,这些项目向我介绍了机器学习,并使我认识到基于人工智能的制造业改进的巨大潜力。因此,我决定发展我的数据科学技能,并更多地接触该领域。我选择了跳板,因为它比完成各种 MOOC 或从在线教程中学习更严格和全面,同时也不像全日制学位那样需要投入太多(也更便宜),此外,我可以在全职工作的同时按照自己的节奏完成它。在这种背景下,让我们进入该计划的概述
计划概述
一旦你注册了这个项目,第一件事就是你将可以通过你的跳板账户访问这个项目的课程。您可以从一开始就访问初始学习模块(除了那些属于专业的模块)。您还可以访问课程跟踪和其他有用的信息,如社区论坛、导师电话通知和其他学生资源。该计划提供了多种资源和工具来帮助您充分利用它。
在整个计划中,课程设计旨在确保您同时在技术模块、职业发展模块和顶点项目上取得进步。最后,一对一的导师支持是跳板最强的卖点之一。接下来,让我们分别看一下这些。
技术课程模块
对于技术课程,springboard 不开发自己的材料,而是组织和提供对网络上其他资源的访问,包括免费和付费的。我觉得这些单元组织得很有逻辑,材料也安排得很好。材料从基本的数据科学技能开始,包括数据解析、数据操作、可视化和基本统计,然后转到不同的机器学习主题。
我发现关于机器学习的材料很好地概述了不同类型的模型,并有助于建立对模型如何工作的直观理解。总的来说,这些材料似乎旨在介绍各种模型,培养对它们如何工作的直觉,并让您使用 python 中的模型库。但是,如果您正在寻找关于特定算法的深入数学理论或实现细节,您可能在课程中找不到。
作为一个职业跟踪计划,该课程很好地涵盖了数据科学家所需的额外技能,包括良好编码实践、测试和调试代码以及生产数据科学模型的模块。
最后,该计划提供了三个专业之间的选择,每个专业在课程的最后 30%都有不同的模块。可用的专业是数据科学通才、深度学习和自然语言处理。我选择 NLP 作为我的专业,并没有直接查看其他专业的材料质量。然而,根据与其他学生的交谈,我了解到通才跟踪更详细地涵盖了推荐系统等模型。我的观察是基于我选择的 NLP 专门化。
顶点工程
我发现顶点计划对于应用我在技术课程中学到的技能非常有帮助。这是发展数据科学投资组合的好机会,这在求职过程中非常有帮助,尤其是如果你打算从一个不同的领域过渡到数据科学工作。
您应该尽早选择第一个顶点项目,并在技术课程的项目上取得进展。除了守则之外,你还需要将你的发现记录成报告,并作为最终提交报告的一部分。
如果您对将数据科学应用于特定领域感兴趣,projects 将允许您从同一领域中选择数据集,以便您可以熟悉该领域中的数据以及数据争论和功能选择的常用策略。
导师支持
跳板的主要卖点之一是一对一的指导。当你报名参加这个项目时,Springboard 会根据你的喜好和你对课程的期望为你安排一个导师。在课程期间,你将定期与导师进行 30 分钟的交流。导师是你的主要资源,用于跟踪你的进展,在你遇到困难时帮助你理解主题,并对你的作业和顶点项目进行评分和提供反馈。
根据跳板网站上的导师简介,我发现导师可以有不同的背景,包括那些拥有数据科学相关领域的高等学位的人,以及那些成功过渡到数据科学的非 STEM 背景的人。我建议你在给导师偏好之前,先想想你的职业目标,以及你期望从导师那里得到什么。从技术上讲,你不能直接选择你的导师。相反,跳板会根据你的喜好和空闲时间为你指派一名导师。然而,我发现跳板团队有助于理解我的偏好,并在项目早期改变指定的导师。
除了指定的导师,您还将获得无限的一次性导师电话。我发现,如果你需要别人给你一个不同的观点,或者如果你发现自己在一周的中途卡住了,不想等到下一次预定的导师电话才能畅通无阻,这些都是有帮助的。
职业发展模块和职业指导电话
该计划的职业发展课程模块穿插在技术模块之间,您需要同时学习这些模块。包含的材料与常见的职业发展主题相关,如更新 Linkedin 个人资料、简历写作和信息面试。由于求职的一个重要部分是建立关系网,你将被鼓励通过信息面试、参加见面会以及接触你所选择的公司或职位描述中的其他联系人来发展你的关系网。
你还将安排与职业教练之一的通话,他们可以查看你的求职材料和策略,并给出个性化的反馈。作为计划的一部分,只要你积极寻找工作,你将有机会获得职业指导,并可以在计划结束后的六个月内安排模拟面试。
其他工具和资源
除了前面提到的,你还可以参加每周的办公时间,观看其他学生的顶点项目演示或询问一般性问题。您还可以访问论坛或参加同龄人学习小组,这是与其他学生交流和集思广益项目想法的良好资源。他们还在旧金山湾区举办了一场名为“跳板崛起”的面对面会议/社交活动。
最后,总结一下,对于任何想要发展自己的数据科学技能并转向数据科学职业的人来说,Springboard 提供了一个全面且精心策划的计划。您可以利用多种资源进行职业发展和人际交往,同时发展您的技术技能和创建项目组合。然而,预期的时间承诺显然高于典型的 MOOC,你需要通过初步的技能评估才能加入该项目。
利弊
优点
- 与 MOOC 课程相比,课程更加广泛和全面。所以,这可能更可信,尤其是对于那些无法重返校园的人来说
- 本课程有机会参加论坛、同行学习小组和面对面的交流活动,这有助于了解更多关于数据科学社区的信息,并与其他可能也想进入该领域的同行建立联系
- 课程是有条理地策划和组织的。非常适合那些刚进入该领域并试图快速建立数据科学各方面基础的人
- 你将承担责任。有一个跟踪器,以及每周检查与导师。这会让你更容易在缺乏动力的时候保持一致
- 选择专业的能力。对于最后几个模块,你将能够根据兴趣和职业目标专攻三个方向中的一个:自然语言处理、深度学习和多面手机器学习
缺点
- 价格昂贵。虽然你确实以这个价格获得了很多资源,但是如果你不太可能使用所有的资源,可能会有更好的选择
- 课程主要使用 Python 及其库开发。如果你喜欢或想学习 R 或其他编程语言,这可能不适合你
- 与导师相处的经历可能会有所不同。网站上列出的导师具有广泛的背景,从基于机器学习的学科的博士到过渡到数据科学的非 STEM 专业的学生。一定要让跳板团队知道你的偏好和你在寻找什么,这样你就可以找到最能帮助你的人
加州大学伯克利分校信息与数据科学硕士(MIDS)项目述评
是否值得你 2 年的时间和 7 万美元的积蓄
我花了 2.5 年时间从加州大学伯克利分校获得了信息和数据科学硕士学位,同时还全职工作(2017 年 8 月-2019 年 12 月)。网上似乎没有足够全面的评论,所以我想分享我的经验,以帮助那些对申请或参加该计划感到不确定的人。
**免责声明:**我写这篇文章是出于我的真实想法,我没有从任何第三方那里得到任何报酬来提供这样的评论。
目录
- 计划概述(以及该计划面向谁)
- 学费和费用
- 课程结构和内容(以及我对其中一些的选择)
- 计划利弊
节目概述
我第一次听到 MIDS 节目是在我还是一名大专学生的时候。当时,我相信一个神话,即像 MIDS 这样的非全日制在线硕士学位不是一个“真正的学位”。直到进入真正的工作环境几年后,我才意识到兼职项目的无与伦比的好处——很难为了获得硕士学位而牺牲工资以及几年宝贵的工作经验。在我被录取的几个项目中,我选择了 MIDS 大学,因为它的声誉很好。
MIDS 的班级简介(链接这里)是动态的。学生们来自各种不同的行业:农业、航空航天、建筑、零售、制药、保险、金融、科技……应有尽有。我的大多数同学都是作为兼职学生加入的,少数人是全日制的。但是几乎每个人都有几年的工作经验。当聆听他们的项目演示并了解数据科学如何应用于不同行业时,这绝对是一次大开眼界的经历。另一个优势是与其他在职专业人士建立联系——我们有学生分享他们当前公司职位空缺的松散渠道,我们中的许多人很乐意做内部推荐。人脉绝对是一个可以也应该被明智使用的东西。
总的来说,我认为 MIDS 适合那些确定要成为一名数据科学家的人(毕竟这不是一个便宜的项目),那些准备好弄脏自己的手(涉及大量编程)的人,以及那些有一份他们想要保留的日常工作的人。
学费和费用
这是一个 27 个单元的项目(3 个单元/课程= 9 门课程)。每个单位的现行费率是 2573 美元。除此之外,你还需要支付每个春季或秋季学期 728.5 美元的校园费(是的,校园费,即使是在线项目),以及每个夏季学期 349 美元的夏令营费。完成该项目的总成本约为 7 万美元。一些经济援助和融资方案可供选择,详情见此处。
课程结构
那么 7 万美元能换来什么呢?这是我从复制的课程列表,这个链接,红色的复选标记是我选择的:
每个人都需要基础课程和顶点课程。但是如果你以前有 Python 编程的知识,你可以请求跳过“数据科学编程入门”并节省 3 个学分来选择一门更高级的课程。
每周你被要求观看一系列预先录制的视频并完成一些阅读,这是一种标准的“翻转课堂”方法。然后每周将有 1.5 小时的在线直播讲师课程,每节最多 15 名学员。作业通常每 2 ~ 3 周进行一次,助教的办公时间会不时安排。大多数课程都需要一个你可以和其他同学合作的期末项目。
以下是我对我参加的每门课程的看法。如果你对完整的课程描述感兴趣,请点击链接。
**免责声明:**学校不断重组课程内容,所以自从我参加以来,事情可能已经发生了变化。
- 数据科学编程入门
这是一个纯 Python 编程类。对我来说,花费 7719 美元仅仅是为了学习一门你可以通过其他免费资源熟悉的语言,这听起来有点疯狂,但是因为无论如何都需要 27 个单元才能毕业,所以对于那些想要结构化指导的人来说,学习 Python 仍然是有价值的。如果你已经知道什么是面向对象编程,熟悉动态类型、可变/不可变(仅举几个例子)等概念,并且了解如何编写函数、类、装饰器、列表理解等,你可以安全地跳过本课程。否则,这是一门建立坚实编程基础的伟大课程(这对其余课程来说超级重要)。
- 数据与分析的研究设计与应用
课程名称可能有点误导,因为这门课没有教你,比如假设检验,或者计算研究样本大小的数学公式。相反,这是一门讨论一般主题的课程,如决策和研究论文中的偏见,讲故事和数据可视化的原则等。尽管指定的阅读材料有时会很有启发性,但许多学生认为这是最“没用”的课。我也不太喜欢这门课,但它确实帮助我培养了一些商业头脑。
- 数据科学统计
这是 MIDS 项目中第一门真正的数据科学课程,它涵盖了统计领域中最基本的概念,包括概率论、假设检验和线性回归。如果你有统计学背景,你可以参加一个豁免考试来跳过这门课。
- 数据工程基础
我相信这门课在我上完之后已经重新组织过了,但是它背后的基本概念是帮助你理解一些基本的数据工程术语和工具。这些知识可能是必不可少的,因为全栈数据科学家将与数据工程师密切合作,因此应该熟悉数据基础设施管道。本课程为您提供了一个很好的起点:它教授命令行编程、使用 docker、Kafka 等的基础知识,以及 Google BigQuery 中的 SQL 语法。
- 应用机器学习
这绝对是我最喜欢的课程之一!我的导师是一位知识渊博的数据科学家,在各种科技公司有 10 多年的工作经验。该课程涵盖了最常用的数据科学算法(带有代码示例),如 KNN、K-means、朴素贝叶斯、树模型(决策树、随机森林、梯度推进)、神经网络(非常基本的概念),以及一些特定的主题,如社交网络模型和推荐系统。这门课程节奏很快——毕竟在一个学期内完成所有这些主题不是一件容易的事情。所以不要期望在这门课之后成为所有这些算法的专家。这门课只是为了让你直接进入数据科学的世界。
- 云端和边缘的深度学习
这是数据工程基础的高级课程。该课程讲授使用 IBM Cloud 和 NVIDIA Jetson 设备在 GPU 上运行深度学习包(如 OpenCV)的基本概念。对于那些没有软件工程背景的人来说,无疑有一点陡峭的学习曲线。由于课程更侧重于尝试不同的工具,而不是解释深度学习背后的概念,所以它不会让你成为深度学习专家。相反,它给了你一个窥视计算机视觉世界的机会。
- 机器大规模学习
这是另一门介绍大数据概念的精彩课程。它不仅教你并行计算、MapReduce 图和 Hadoop 系统的基本思想,还为你提供了大量练习 PySpark 编程的机会。唯一的小缺点是,它过于关注 PySpark RDD,而对 PySpark 数据框架关注太少,这意味着您需要花一些时间自己填补知识漏洞。
- 自然语言处理与深度学习
这是 MIDS 项目中最难最耗时的课程,我希望他们能把 NLP 和深度学习分成两个不同的班级!应用机器学习课程向你介绍了神经网络的粗浅想法,这门课很快就跳到了 CNN 和 RNN 背后的复杂概念。幸运的是,导师是斯坦福大学 NLP 小组的博士后,他为我们提供了很好的材料来浏览这些主题。此外,还有大量的助教工作时间。但是,如果你想掌握这个话题,还是要准备好把你所有的空闲时间都投入到课堂中。此外,Tensorflow 在整个课程中被大量使用,讲师花了很大的努力来确保我们对 Tensorflow 操作感到舒适。我相信如果他们选择 Keras 而不是 Tensorflow,课程可能会更容易一些。但总的来说,这是一门非常值得推荐的课程,你肯定会从中学到很多。
- 顶点
在顶点课程中,学生组成 3 或 4 人小组,提出自己的数据科学项目。我的团队的顶点项目是语音情感分析,我们开发了一个应用程序来部署我们的模型——实际上,你会发现团队建立网站或应用程序来托管他们的模型是非常常见的,你会惊讶地发现,你的许多同学都有能力进行前端/后端开发。Capstone 提供了一个很棒的沙盒环境,不仅可以思考现实世界中数据科学知识的用例,还可以实践产品开发和模型部署。我班上的两位导师都有很强的背景——一位是风投,另一位是一家财富 500 强咨询公司的董事。
- 沉浸
上面的列表中没有显示的一件事是一个 3 天的沉浸式项目。这是一次必修课,但是学生可以自由选择他们想参加的学期。在沉浸式学习期间,将围绕数据和领导力相关主题举行不同的讲座和工作会议。学生们也可以参加一份名单中的两家公司的参观,但这些公司通常是中等规模的。顺便说一句,你负责支付机票和酒店费用,以参加浸泡。
利弊
我在前面的章节中已经提到了很多优点。总的来说,我认为 MIDS 计划涵盖了大多数重要的数据科学概念。大多数教师都有很强的背景,所以你会真正得到专家的指导(教师简介可以从这里查看)。与此同时,MIDS 非常重视学生的意见,我看到他们根据调查反馈更换教师和重新安排课程内容。
对于缺点:首先,没有课程介绍非参数统计,如贝叶斯统计或蒙特卡洛。其次,有些课程没有达到我希望的深度,因此需要大量的自学。第三,我发现有些课程的预录视频很混乱,很干涩。在某个时候,我完全放弃了观看预先录制的视频,转而观看吴恩达的机器学习课(链接此处),并认为这是对我时间的更好利用。最后,MIDS,说到底,是一个服务于繁忙职业的在线项目。与常规的体育项目相比,很难与你的同学和讲师建立亲密的友谊。
MIDS 不是一个会教你每个算法背后的数学公式的程序。相反,它非常强调编程和数据科学工具和库的实际用例。它为你打开了数据科学世界的大门,但之后的路还很长。
希望这篇文章对你有所帮助。如有疑问和评论,我们连线 Linkedin 和 Twitter 。
外部链接
- **班级简介:**https://datascience.berkeley.edu/experience/class-profile/
- 学费和助学金:https://data science . Berkeley . edu/admissions/tufty-and-Financial-Aid/
- 课程概况:https://cdn 2 . data science . Berkeley . edu/content/a9aa 839d 412d 4c 4 e 9d 5225 a2 e 46 f 18 f 6/UCB-MIDS _ MKTGWEB-36794 _ One-Pager _ General _ 2020-02 _ WEB _ 1 . pdf?_ ga = 2.2458225669-256986536367
- 课程简介:http://guide.berkeley.edu/courses/datasci/
- 教员简介:https://www.ischool.berkeley.edu/people?role=122
回顾:SAS Cortex 分析模拟竞赛
借助 SAS Enterprise Miner 了解预测分析
SAS 和 HEC Montréal 的 Cortex Analytics 模拟
2020 年 4 月底至 5 月初,我参加了由 SAS (ANZ)与 HEC Montréal 合作举办的Cortex Analytics Simulation竞赛。该比赛面向所有人,特别是学生,他们希望探索预测分析在现实世界中的应用。
我不会对游戏进行过多的描述,因为我不想透露未来比赛的可能答案,但我想说,使用 SAS Enterprise Miner 学习预测分析是一次很好的体验。
如果你遇到了比赛,并想了解更多,这篇文章介绍了游戏场景、说明和我在整个比赛中的个人经历。
方案
你正在为一个拥有 100 万会员的非营利慈善组织进行筹款活动。基金会决定在其营销活动清单中增加一项直接联系活动。我们的目标是在给会员打电话的情况下筹集最多的捐款。这将通过使用预测建模软件(SAS Enterprise Miner)来完成,以预测活动中的目标人数和目标人群。
您将获得潜在捐赠者的数据集。您将根据捐赠者以前的行为拟合不同的模型,对捐赠者进行评分以预测今年的捐赠。利用这个结果,决定有多少潜在的捐赠者。上传您的 id 列表,该列表将根据运营盈余:捐款总额-致电总成本对提交的 id 进行排名。我创建了一个表格,列出了下面给出的一些信息。
表 1:列出了一些变量,表 2:联系成员的成本
每日网络研讨会和说明
由于这是一个介绍性的比赛,参与者将获得详细的游戏说明,并可以参加每天 1 小时的网络研讨会(由 SAS 提供)。
这些网络研讨会包括讲解说明的演示和问答环节。我们有两种不同的建模方法:
- “1 阶段建模”:一个简单的模型,根据捐赠者的预计捐赠金额对其进行评分。
- “两阶段建模”:一个更复杂的模型,既考虑了给予的概率(接触与否)又考虑了预测金额。
当然,两阶段建模过程更有效。它通常被称为提升建模,其中提升是通过计算预测金额之间的差异来计算的,该差异考虑了联系或不联系某人时的捐赠概率。
我强烈建议您参加这些网络研讨会,因为它们有助于您更好地浏览 SAS Enterprise Miner,学习不同的建模技术,并提出您可能有的任何问题。
竞争
竞赛是通过 SAS 虚拟机/实验室完成的。你有总共 20 个小时的时间在 5 天内测试不同的模型并上传你的结果。因为它是在云中的一个虚拟机上,所以你需要预订,这需要大约 25 分钟的启动时间。你提交答案的次数也有限制(大约 30 次)。
在比赛期间,你的目标是测试不同类型的机器学习模型,以预测概率或捐款金额。SAS Enterprise Miner 的布局一开始可能会很吓人,这就是为什么最好按照网上研讨会的说明进行操作。
SAS Enterprise Miner 使用一个简单的拖放系统,您可以添加不同的节点并将它们连接到其他节点。这使得学习如何使用软件和测试新模型变得很容易。图的大部分已经为您完成,您的主要任务是测试不同的模型并调整它们的属性。
一些模型包括决策树、回归、神经网络和梯度推进。他们还拥有高性能(HP)数据挖掘节点,这些节点使用了传统方法中没有使用的几种技术(这些可能需要更长的运行时间)。您将花费大部分时间放置不同的模型,并放置模型比较节点来检查哪个模型执行得最好(平均平方误差最低)。
图表流程(类似于 SAS Enterprise Miner)
上面显示了我在 SAS Enterprise Miner 中创建的一般图表:
- 初始数据准备:合并数据。
- 数据分区:数据被分成训练集和验证集。
- 建模:添加不同的模型,修改其属性(这里我们展示的是回归和决策树)。如果您使用复杂的模型(比如 HP 节点),这个阶段可能需要几分钟甚至几个小时。
- 型号对比:对比各型号并显示其性能。
- 评分数据准备:根据使用的模型对新数据进行评分。
- SAS 代码:将预测导出到 Excel 文件。
收到 Excel 文件输出后,您的工作是对数据进行排序,收集您想要使用的 id 数,并提交结果。你会马上看到你提交的潜在捐赠者名单的表现。
我发现特别有用的是,看看竞争中的其他参与者瞄准了多少捐助者,这样你就可以知道你可能收集到多少钱。您大部分时间都在摆弄不同的模型,所以最好添加不同的模型变体来找到性能最佳的模型。例如,您可以使用逻辑回归代替线性回归,或者增加决策树的复杂性。您可以尝试的其他方法是移除或转换变量。
结论
最终,我在比赛中获得了第三名,与 1000 澳元的最高奖金失之交臂。我认为,如果您想更多地了解 SAS Enterprise Miner 以及如何将其用于预测分析,参加 SAS Cortex Analytics 模拟竞赛可能是一个很好的开始。尽管你必须付费才能参加比赛,但如果你错过了第一名,你可以在网上(或通过面试)分享你的经验,并在 Acclaim 上展示你的参与者徽章。
我的皮层参与者徽章发出喝彩
感谢阅读!
欢迎在 LinkedIn 上联系我,或者在 Medium 上关注我。我希望发布更多与数据科学相关的内容。
在 Udacity 上查看 Google 的 A/B 测试课程
阅读了解谷歌是如何进行 A/B 测试的。
A/B 测试是在线实验,用于测试网站或移动应用程序的潜在改进。这个实验需要两组——控制组和实验组。控制组的用户看到的是现有的网站,而实验组的用户看到的是改变后的网站。然后对结果进行比较,并对数据进行分析,以确定变革是否值得启动。谷歌与 Udacity 合作的 A/B 测试课程解释了分析时需要考虑的各种指标,如何利用统计的力量来评估结果,以及最终是否必须启动变革。本课程不深入研究统计概念,而是解释这些测试的商业应用。
A/B 测试被许多公司广泛使用。例如,亚马逊用它来测试用户推荐功能,谷歌广泛使用它,他们曾经用它来测试 UI 中 41 种不同深浅的蓝色!虽然这个术语是最近才出现的,但这种方法已经在实践中使用了很长一段时间。农民用它来判断哪种方法能获得最好的收成,医生用它来进行临床试验,以检查药物的有效性。
贷项: Unsplash
政策与道德:
在进行 A/B 测试之前,必须考虑几件事。
- 风险:参与者在参与测试时承担什么风险。最小风险被定义为参与者在日常生活中可能遇到的伤害的概率和程度。如果风险超过这一限度,则必须告知参与者。
- 益处:能够陈述完成研究的益处是很重要的。
- 备选方案:用户可能拥有的其他备选服务,以及在时间、金钱、信息等方面的转换成本。
- 数据敏感性:指所收集的数据,是否会泄露个人身份,为保护数据所采取的安全措施,以及数据公开后可能对个人产生的影响。
选择和表征指标:
这些指标可以分为两类。不变的度量是那些应该在两个组中保持相同的度量。例如,两组中的人数,基于人口统计学的分布。评估标准是你用来衡量实验有效性的标准。例如,如果您正在测试点击“开始按钮”的用户数量的变化,点击率(点击的独立访问者数量/独立访问者总数)可以作为您的评估指标。执行健全性检查是为了检查您选择的不变指标是否正确。可以执行 A/A 测试来检查这一点。
还必须考虑灵敏度和鲁棒性。该指标既不应该过于敏感,也不应该过于稳健。均值可能对异常值过于敏感,而中值可能过于稳健而无法捕捉变化。第 90 或第 99 个百分位数被认为是注意变化的良好指标。为了在灵敏度和鲁棒性之间找到良好的平衡,可以进行 A/A 测试,使用以前实验的数据或对日志进行回顾性分析。
设计实验:
分流单位 用于定义实验中的一个人。
- 用户 id :如果一个人登录了账户,我们可以用用户 id 作为转移的单位来跟踪活动。
- Cookie :是一个网站发来的一小段数据,在用户浏览的时候,由用户的网页浏览器保存在用户的电脑上。Cookies 是特定于浏览器的,也可以由用户清除。
- 基于事件的分流:任何动作,比如重新加载页面,都可以被认为是一个事件。这些主要用于用户不可见的更改。例如,等待时间变化。
**人群:**你还必须考虑你将要进行实验的人群,是整个人群,还是来自某个特定地区或某个特定部门的人群。
**规模:**人口规模也是一个重要因素。它受显著性水平(α)、灵敏度(1-β)以及分析单位是否等于分流单位等参数的影响。
**持续时间和曝光:**指您想要运行实验的时间段。此外,确定何时进行实验也非常重要。例如,在周末或工作日,假日或非假日季节。一般来说,在两者之间取得平衡是有好处的,这样你可以更好地理解趋势和季节性效应。暴露程度基本上是您想要将新功能暴露给的人群的比例。
分析结果:
健全性检查:在你拿到实验结果后,你要做的第一件事就是检查你的不变指标在两组中是否相同,比如人口分布是否正确。
**单一指标:**要检查单一不变指标是否在可接受的范围内,您必须计算合并的标准误差,并将其乘以 Z 值(95%置信区间为 1.96),然后找出误差范围。然后找到下限和上限,并检查特定指标值的差异是否在范围内。
您还应该对评估度量执行测试,以检查结果是否在统计上和实践上都有意义。对于具有统计显著性的结果,差值的范围不得包含 0,对于具有实际显著性的结果,该范围不得包含实际显著性界限。此外,为了再次检查结果,可以进行符号测试。如果两个测试彼此不一致,我们可能需要更深入地研究数据,因为这可能是由于辛普森悖论(单个亚组显示出稳定的结果,但它们的集合导致了问题)。
**多个指标:**如果您同时考虑多个指标,您可能会因为误报而认为其中一个指标很重要。为了解决这个问题,你可以使用自举或 bonferroni 校正。
分析完结果后,你必须回答几个问题,比如变化是否显著?我了解这种变化的影响吗?在审查其他业务因素后,变革是否值得启动?在此基础上,您可以启动变更,执行更多的测试,也可以不启动变更。您可能需要在前期和后期执行 A/A 测试,以进行健全性检查,并查看更改对用户的影响。
结论:
Google 在 Udacity 上开设的 A/B 测试课程是任何想了解 A/B 测试流程的人的必选课程。最后的项目可以进一步帮助你理解这些概念。这只是课程的概述。
免费课程由在线实验设计和分析开始免费课程关于本课程,本课程将涵盖…
www.udacity.com](https://www.udacity.com/course/ab-testing--ud257)
回顾 Deepnote——数据科学家的新 IDE
使用 Deepnote 开发 Python 课程后的感想
声明:我绝不隶属于 Deepnote 或其任何成员。
Deepnote 是一个的免费在线数据科学笔记本,主要关注协作(实时、谷歌文档、协作类型)和所有概念的抽象,以及妨碍工作的工作——环境和基础设施设置。
这家初创公司最近宣布,它筹集了 380 万美元的种子资金,由 Index Ventures 牵头,包括 Greg Brockman 和 Naval Ravikant 等天使投资人。
看了 TC 的公告后,我很想试一试。我报了内测,耐心站了五个(!)几天后,我收到了邀请函。
我登录了,在平台上折腾了大约一个小时,尝试了一些示例项目,仅此而已。
Deepnote 的示例项目
几个月后,我一位在金融行业工作的好朋友 Rodrigo Tadewald 邀请我共同创建一个主要使用 Python 的在线课程。我很可能会负责本课程的环境设置/编程/性能方面的主题。
我非常高兴地接受了邀请,因为我对金融话题非常感兴趣,而且从未制作过在线课程。然后我有了尝试 Deepnote 的想法,并开始用它开发所有的 Python 课程笔记本。
声明:我主要使用了 Brave 浏览器,仅使用其他浏览器来验证它何时出现一些奇怪的行为(Brave 浏览器运行在 Chromium 引擎上)。在项目开发过程中,我也曾交替使用 OSX、Ubuntu 和 Windows 机器。
体验
为了开始这个项目,我上传了一些我以前在现场课程中用过的旧笔记本,然后开始创建这个项目。Deepnote 还提供了从 GitHub 和 GitLab 导入存储库的选项,使得设置变得非常容易。
随着我对这个平台越来越熟悉,CTRL/⌘ + P 成了我做事的主要方式。
指挥托盘
它可以很好地执行截图中的命令,但它的查询功能并不能让我 100%满意。我在文件夹中查找文件时遇到了一些问题,这真的很痛苦,因为我的项目主要是用文件夹和子文件夹来组织的。
在 项目 选项卡中可以看到您的项目文件,添加新文件,添加数据连接,以及访问终端。
Deepnote 的侧边导航,带有标签和可变浏览器(以及葡萄牙语的课程迷你剧透:)
笔记本本身还是挺有意思的,有一些很酷的功能。我真的很高兴看到减价备忘单很容易找到。
IDE 可以自动检测模块,您可以轻松地动态安装pip
包。如果您使用!pip
命令,Deepnote 会将它保存在一个隐藏文件中,并在每次环境启动时安装它。您也可以选择创建一个requirements.txt
文件,并通过 终端 与之交互
变量资源管理器是一个很好的特性,它已经集成了一些度量标准,真的给了它一个很好的触感。
变量浏览器中的熊猫数据框
代码智能 特性,比如自动完成和定位定义,在当前的测试版中表现不佳。
改进:在我的项目开发过程中,我注意到一件重要的事情,那就是文件浏览器的性能有了显著的提高。由于我上传了很多文件,我需要将它们组织到文件夹中,几周前,在文件夹和子文件夹中移动文件是一种非常落后的体验。自 2020 年 4 月左右球场开始开发以来,这种情况有了很大的改善。不错!
在一些课程模块中,我需要处理数据。不是巨大的数据集,但足够大,如果我不得不重新上传到平台上,我会不高兴。Deepnote 有一些集成的数据集,如 Landsat 8 和 Goodreads books,但对于我的项目,我需要使用我已经准备好的自定义数据集。
此外,除了从您的本地系统上传文件之外,还有一种方法可以集成(至少在我的 beta 帐户上) AWS S3 ,MongoDB和Postgres。有很多“灰色”的选项,但我想念 Azure storage 和 Google Drive 的集成,主要是因为对于 Google Colab 用户来说,随便尝试 Deepnote 肯定会少很多麻烦。
创建与 IDE 的新连接
在设置好数据连接之后,我用 终端 做了一点小改动,它给了你对机器的完全根访问权限,但是我并不认为这个项目需要它。我想我唯一一次跑到终端是在 Deepnote 内核进入重启循环的时候,我试图用一些 bash 命令修复它。
转到 环境 标签,你可以选择机器配置,重启它,查看 CPU 和 RAM 的使用情况,检查你的项目所依赖的包。
免费提供的机器配置如下:
- 基本 —英特尔 Haswell 1vCPU ~1.5GB RAM 无 GPU
- Pro —英特尔 Haswell 2vCPU ~5GB RAM 无 GPU
还有一种性能配置,可根据要求提供:
- 性能 —英特尔 Haswell 4vCPU ~12GB RAM T4 GPU
最后但同样重要的是还有 评论 标签。Deepnote 上的通信功能非常先进,虽然这个课程主要是一个单独的项目,但有时我会友好地请求一个朋友查看它的一些笔记本,我没有失望。
我们可以进行代码评审的实时会议,并与注释进行异步交互。这为数据科学家在异步或同步时间表上一起远程工作提供了很大的优势。远胜于我在其他笔记本平台上的任何其他协作体验。
结论
Deepnote 已经解决了成为数据科学团队首选 IDE 的挑战,与一些非常好的和已经建立的替代产品竞争。
它的核心优势是以协作为中心的方法,这种方法脱颖而出,为数据科学家提供了真正的 Google Docs 体验。
我敢肯定“看起来很有趣”的功能目前正在被团队修复,一些功能的实现,如版本控制、团队、仪表板和笔记本的 API 共享,也正在进行中。
如果你对这个平台感兴趣,我建议你尝试一个项目,在这个项目中,协作是关键,也许是和你的一些朋友或同事。这样,你就可以提取平台提供的真正价值。
如果您是 Python 或笔记本环境初学者,Deepnote 是一个非常容易的入门方式。
对于数据科学团队,我会鼓励他们在新项目中使用它,并与 Deepnote 人员保持联系。你可以使用集成的聊天工具与团队交流,这很有帮助(因为它是测试版,所以它有测试版的功能:)
我会定期更新这个帖子,回顾新的功能,所以实际上我在这里写的很多东西将来都可以改变。
我希望你喜欢阅读这篇文章。
如果你有,考虑在Twitter上关注我。
谢谢你的时间。保重,继续编码!
复习基本概念
深度强化学习讲解— 12
数学符号已更新
这篇文章是*深度强化学习讲解系列的新部分的序言,在这里我们将介绍强化学习经典方法的实现,如蒙特卡罗、SARSA 或 Q-learning 等。在本帖中,我们将回顾和更新以前帖子中介绍的数学符号。*
访问第 3 页的自由介绍
medium.com](https://medium.com/aprendizaje-por-refuerzo/3-funciones-de-valor-y-la-ecuaci%C3%B3n-de-bellman-7b0ebfac2be1)
数学符号复习
在帖子 2 中,我们已经看到,我们可以使用马尔可夫决策过程(MDP)作为我们希望通过强化学习来解决的问题的正式定义。MDP 由 5 个参数 < S,A,R,p,γ >, 定义,其中每个参数表示:
- —一组状态
- 一个 —一组动作
- R —奖励功能
- p —过渡函数
- γ —贴现因子
请记住,我们倾向于使用理查德·萨顿和安德鲁·g·巴尔托所著的教科书 强化学习:导论 中的符号。这本书是一个优秀的强化学习基础介绍的经典文本。
我们在以前的文章中介绍的主要定义和数学符号是:
连续任务的折扣率
在继续之前,让我们简单地补充一下贴现率在一个连续任务中的表现,这在以前的帖子中没有涉及。
继续任务示例
在本系列的第 1 部分中,我们使用了一个临时任务,即冰湖环境,这是一个来自 OpenAI Gym 的简单网格世界环境,是一个用于开发和比较 RL 算法的工具包。在这一节中,我们将使用另一个环境介绍一个持续的任务,即车杆平衡问题:
使用角度和角速度的车杆平衡(来源)
如前图所示,一辆手推车沿水平轴放置在无摩擦的轨道上,一根柱子固定在手推车的顶部。目标是通过向左或向右移动小车来防止杆倒下,并且不要从轨道上掉下来。
通过对手推车施加+1(左)或-1(右)的力来控制该系统。钟摆开始直立,目标是防止它翻倒。柱子保持直立的每个时间步提供+1 的奖励,包括该集的最后一步。当柱子偏离垂直方向超过 15 度,或者手推车偏离中心超过 2.4 个单位时,该集结束。
该环境在每个时间点的观察空间是 4 个数字的阵列。在每个时间步,你可以观察它的位置,速度,角度和角速度。这些是这个世界的可观察状态。您可以在本文档的中查找这些数字的含义。请注意小车速度和尖端极点速度的最小值(-Inf)和最大值(Inf)。由于数组中对应于每个索引的条目可以是任何实数,这意味着状态空间是无限的!
在任何状态下,小车只有两种可能的动作:向左移动或向右移动*。换句话说,车极点的状态空间有四维连续值,而动作空间有一维两个离散值。*
贴现率
在我们继续任务的例子中,哪个贴现率会鼓励代理尽可能长时间地保持极点平衡?
*在任何贴现率 *γ > 0 的情况下,代理人在极点尚未倒下的每个时间步获得正奖励。因此,代理将尽可能长时间地保持极点平衡。
然而,想象一下,奖励信号被修改为仅在一集结束时给代理人奖励。换句话说,除了最后一个时间步,当剧集结束时,每个时间步的奖励都是 0,然后代理人获得+1 的奖励。
在这种情况下,如果折扣率为 γ= 1,代理人将总是获得+1 的奖励(无论它在该集期间选择什么行动),因此奖励信号不会向代理人提供任何有用的反馈。
如果折扣率为 γ < 1,代理将尝试尽快终止该集(通过快速放下杆或离开轨道边缘)。因此,在这种情况下,我们必须重新设计奖励信号!
这个问题的解决方案是由策略决定的,这意味着为了追求一个目标,代理需要学习一系列的动作。在下一节中,我们将进一步讨论这个问题解决方案的正式定义。
政策
策略是代理用来基于当前状态确定下一个动作的策略(例如,一些规则集)。一般用*【𝜋(𝑎|𝑠】、希腊字母 pi 表示,一个策略是决定下一个动作采取给定状态。*
最简单的策略是从环境状态集到可能动作集*的映射。我们称这种策略为确定性策略**。但是在第二篇文章中,我们也介绍了𝜋(𝑎|𝑠政策可以被定义为概率,而不是具体的行动。换句话说,这是一个随机策略,它对代理在给定状态下可以采取的行动有一个概率分布。*****
随机策略将允许代理随机选择行动。更正式地说,我们将随机策略定义为接受环境状态和动作*并返回代理在状态 S:***
在学习过程中,随着代理获得更多的经验,策略𝜋可能会改变。例如,代理可以从随机策略开始,其中所有动作的概率是一致的;与此同时,代理将有希望学会优化其策略,以达到最优策略。
现在我们知道了如何指定一个策略,我们可以采取什么步骤来确保代理的策略是最好的?我们将使用在第二篇文章中已经介绍过的状态值函数和动作值函数。
价值函数
状态-价值函数,也被称为价值函数*,甚至是 V 函数,衡量每个状态的好坏,它告诉我们如果我们从那个状态开始,我们未来可以预期的总回报。***
对于每个状态 s ,状态值函数告诉我们期望的贴现回报 G ,如果代理在该状态 s 开始,然后使用策略为所有时间步骤选择其动作。重要的是要注意,状态值函数将总是对应于特定的策略,所以如果我们改变策略,我们改变状态值函数。出于这个原因,我们通常用小写的 v 来表示函数,在下标中用相应的策略 𝜋 来表示,并正式定义为:
其中𝔼[ ]表示给定代理遵循策略 𝜋 时随机变量的期望值,而 t 是任意时间步长。正如我们在第 8 篇文章中介绍的,它用于𝔼[.的预期因为环境转移函数可能以随机的方式起作用。
同样在 post 2 中,我们将状态-值函数的定义扩展到状态-动作对,为每个状态-动作对定义一个值,这被称为动作-值函数,也被称为Q-函数或简称为 Q. 它定义了在一个策略下,在状态中采取动作的值******
在整个系列中,我们将交替使用值函数的大写或小写符号:或 v(s) 和 Q(s,a) 或 q(s,a)
贝尔曼期望方程
对于一个一般的 MDP,我们必须根据一个期望来工作,因为直接的回报和下一个状态很难被确定地预测。的确,我们在前面的帖子里看到,奖励 r 和下一个状态s’都是根据 MDP 的单步动态来选择的。在这种情况下,当从(条件)概率分布p(s’,r ∣ s,a )** 中得出 r 和 s 时,贝尔曼期望方程根据期望的即时报酬和期望的来表达任意状态 s 的值****
对于一般情况,当代理的策略 π 为随机**时,代理在状态 s 时以概率π*(a∣s)选择行动 a ,贝尔曼期望方程可以表示为:***
在这种情况下,我们把下一个状态的奖励和贴现值之和(r+γvπ(s’)乘以其对应的概率π(a∣s*)p(s【t57’,r∣s*****
我们还有作用值函数的贝尔曼方程:
最优策略
代理人的目标是在长期内最大化总的累积报酬。使总累积报酬最大化的策略称为最优策略**。在第 8 篇文章中,我们介绍了“最优”价值函数。**
当且仅当对于所有的 s ∈S,vπ′(s)≥vπ(s)时,策略 π 被定义为优于或等于策略 π 最优策略肯定存在,但可能不是唯一的。
所有最优政策都有相同的状态值函数v∑**,称为最优状态值函数。最佳状态值函数的更正式的定义可以是:**
对于动作值函数:
所有最优政策都有相同的行动价值函数q∑**,称为最优行动价值函数。**
这种最优行动值对于获得最优策略非常有用。代理通过与环境交互来估计它。一旦代理确定了最优动作值函数q∫,它可以通过设置以下参数快速获得最优策略π∫:
正如我们在第 8 篇文章中看到的,贝尔曼方程用于在算法中找到价值函数的最优值来计算它们。更正式的表达可以是:
下一步是什么?
我们已经到达这篇文章的结尾了!。在接下来的这篇文章中,我们将介绍蒙特卡罗方法,这是一种估计价值函数和发现最优策略的学习方法。
下期见!**
深度强化学习讲解系列
一个轻松的介绍性系列以一种实用的方式逐渐向读者介绍这项令人兴奋的技术,它是人工智能领域最新突破性进展的真正推动者。
本系列的内容](https://torres.ai/deep-reinforcement-learning-explained-series/)
关于这个系列
我在五月开始写这个系列,在巴塞罗那的**封锁期。**老实说,由于封锁,在业余时间写这些帖子帮助了我 #StayAtHome 。感谢您当年阅读这份刊物;它证明了我所做的努力。
免责声明 —这些帖子是在巴塞罗纳封锁期间写的,目的是分散个人注意力和传播科学知识,以防对某人有所帮助,但不是为了成为 DRL 地区的学术参考文献。如果读者需要更严谨的文档,本系列的最后一篇文章提供了大量的学术资源和书籍供读者参考。作者意识到这一系列的帖子可能包含一些错误,如果目的是一个学术文件,则需要对英文文本进行修订以改进它。但是,尽管作者想提高内容的数量和质量,他的职业承诺并没有留给他这样做的自由时间。然而,作者同意提炼所有那些读者可以尽快报告的错误。**
深层图像修复的修订与回顾:基于生成式对抗网络的图像修补
欢迎回来的家伙:)今天,我想给一个修订的深层图像修复,我们已经谈到目前为止。还有,想再复习一篇图像修复的论文,巩固深度图像修复的知识。让我们一起学习和享受吧!
回忆
在这里,让我们首先简单回顾一下我们从以前的帖子中学到了什么。
上下文编码器(CE)【1】是文献中第一个基于 GAN 的修复算法。它强调理解整个图像的上下文对于修复任务的重要性,并且(通道方式)全连接层用于实现这样的功能。详情可以点击此处链接往期帖子。
多尺度神经面片合成(MNPS)【2】可以看作是 CE 的改进版。它由两个网络组成,即内容网络和纹理网络。内容网络是 CE,纹理网络是用于对象分类任务的预训练的 VGG-19。使用纹理网络的想法来自于最近神经风格转移的成功。简单地说,用于高级视觉任务(例如物体分类)的预训练网络中的神经响应包含关于图像风格的信息。通过鼓励缺失区域内外类似的神经反应,我们可以进一步增强生成像素的纹理细节,从而使完成的图像看起来更真实。强烈建议感兴趣的读者在此浏览帖子了解详情。
全局和局部一致图像补全(GL CIC)【3】是深度图像修复任务中的一个里程碑。作者采用全卷积网络(FCN)和扩展卷积(DilatedConv)作为他们提出的模型的框架。FCN 允许各种输入大小和 DilatedConv 取代(通道方式)完全连接层,用于了解整个图像的背景。此外,两个鉴别器用于在两个尺度上区分完整图像和真实图像。全局鉴别器查看整个图像,而局部鉴别器关注局部填充的图像块。我强烈推荐读者在这里看一看帖子,尤其是 CNN 中的扩张卷积。
今天,我们将回顾这篇论文,基于生成性对抗网络的图像修补[4]。这可以看作是 GLCIC 的一种变体,因此我们可以对这种典型的网络结构做一些修改。
动机
本文作者希望利用剩余连接和 PatchGAN 鉴别器的优势来进一步改善他们的修复效果。
用于图像识别的深度残差学习(ResNet)【5】在深度学习方面取得了显著的成功。通过使用残差块(残差连接),我们能够训练非常深的网络,许多论文已经表明残差学习对于获得更好的结果是有用的。
PatchGAN 6在图像到图像的翻译方面也取得了巨大的成功。**与典型 GAN 中的鉴别器相比,PatchGAN 鉴别器(参见下面的图 1)输出一个矩阵(2d 阵列),而不仅仅是单个值。**简单来说,典型 GAN 鉴频器的输出是从 0 到 1 的单一值。这意味着鉴别器查看整个图像并决定这个图像是真的还是假的。如果图像是真实的,它应该给 1。如果图像是假的(即生成的图像),它应该给 0。这个公式关注于整个图像,因此图像的局部纹理细节可能被忽略。另一方面,PatchGAN 鉴别器的输出是一个矩阵,该矩阵中的每个元素的范围从 0 到 1。注意,每个元素代表输入图像中的一个局部区域,如图 1 所示。因此,这一次,鉴别器查看多个局部图像块,并且必须判断每个块是否是真实的。通过这样做,可以增强生成的图像的局部纹理细节。这就是 PatchGAN 被广泛用于图像生成任务的原因。
图一。PatchGAN 鉴别器。输出是矩阵,矩阵中的每个元素代表输入图像中的局部区域。如果局部区域是真实的,我们应该得到 1,否则 0。摘自[4]
介绍
图像修复可以看作是一种图像生成任务。我们希望填充图像中的缺失区域(即生成缺失的像素),以使图像完整且看起来逼真。
为了生成逼真的图像,GAN 通常用于不同的图像生成任务,包括图像修复。典型的 GAN 鉴别器查看整个图像,仅通过单个值[0,1]来判断输入是否真实。这种 GAN 鉴别器在本文中称为全局 GAN (G-GAN)。
另一方面,PatchGAN 查看输入中的多个局部区域,并独立决定每个局部区域的真实度,如前一节所述。研究人员已经表明,使用 PatchGAN 可以通过关注更多的局部纹理细节来进一步提高生成图像的视觉质量。
解决方案(简而言之)
- 在生成器中使用了具有扩展卷积的残差块(扩展残差块)。(作者期望通过使用残差学习可以增强修复结果)
- patch GAN 和 G-GAN 鉴别器的混合(PGGAN) 被提出以鼓励输出的完整图像应该是全局和局部逼真的。(与 GLCIC 中的意图相同,使用两个鉴别器,一个全局的,一个局部的)
贡献
- patch GAN 和 G-GAN 鉴别器的组合(PGGAN) 其中早期卷积层被共享。他们的实验结果表明,它能进一步增强生成像素的局部纹理细节。
- 扩张和插值卷积用于发生器网络。通过使用膨胀的残余块,修复结果得到了改善。
方法
图二。提出的生成 ResNet 结构和 PGGAN 鉴别器。摘自[4]
图 3。全球土地信息中心的拟议结构。摘自3
图 2 和图 3 分别显示了本文和 GLCIC 提出的网络结构。很明显,它们是相似的。两个主要区别在于:I)发生器中使用了膨胀的残差块; ii)修改 GLCIC 中的全局和局部鉴别器。
在 GLCIC 中,全局鉴别器将整个图像作为输入,而局部鉴别器将填充区域周围的子图像作为输入。将两个鉴别器的输出连接起来,然后返回一个值,以显示输入是真的还是假的(一次不利损失)。从这个角度来看,局部鉴别器将集中在局部填充的图像补片上,因此可以增强填充补片的局部纹理细节。一个主要缺点是局部鉴别器的输入依赖于缺失区域并且作者在训练期间假设单一矩形缺失区域。
对于 PGGAN 鉴别器,我们有几个早期共享卷积层如图 2 所示。然后,我们有两个分支,一个给出单个值作为输出(G-GAN),一个给出矩阵作为输出(PatchGAN)。请注意,1×256 是 16×16 矩阵的变形版本。如上所述,这也是一种让鉴别器在区分完整图像和真实图像时同时关注全局(整个图像)和局部(局部图像小块)信息的方式。请注意,我们将有两个不利的损失,因为在这种情况下我们有两个分支。
扩张的残余阻滞
在我之前的文章中,我已经介绍了 CNN 中的扩张卷积。简单回忆一下,通过跳过连续的空间位置,扩大的卷积增加了感受野而没有增加额外的参数。对于忘记这个概念的读者,请随意先重温一下我之前的帖子。
图 4。剩余块类型。自上而下:标准残余阻滞,先有扩张回旋的扩张残余阻滞,后有扩张回旋的扩张残余阻滞。摘自[4]
图 4 示出了不同类型的残差块。为了便于我们的进一步讨论,我将简要介绍图 4 顶部所示的一个基本残差块。
简单地说,残差块可以公式化为 Y = X + F(X),其中 Y 是输出,X 是输入,F 是几层的序列。在图 4 的基本剩余块中,F 是 conv-诺姆-雷鲁-Conv。这意味着我们将 X 馈送到一个卷积层,然后是归一化层、ReLU 激活层,最后是另一个卷积层,以获得 F(X)。一个要点是输入 X 直接加到输出 Y 上,这就是我们称之为跳过连接的原因。由于沿此路径没有任何可训练参数,我们可以确保在反向传播期间必须有足够的梯度传递到早期层。因此,我们可以训练非常深的网络,而不会遇到梯度消失的问题。
为什么是残块?
你可能想知道使用剩余块的好处。你们有些人可能已经知道答案了。下面我来说说我的看法。
我们来比较一下 Y = X + F(X)和 Y = F(X)。对于 Y = X + F(X),我们实际学到的是 **F(X) = Y - X,Y 和 X 的差,这就是所谓的剩余学习,X 可以作为剩余学习的参考。**另一方面,对于 Y = F(X),我们直接学习将输入 X 映射到输出 Y,无需参考。所以,人们认为剩余学习相对容易。更重要的是,很多论文都表明,残差学习可以带来更好的效果!
由于扩展卷积有助于增加感受野,而感受野对于修复任务非常重要,因此作者用扩展卷积层替换了两个标准卷积层中的一个,如图 4 所示。有两种类型的扩张残余阻滞, i)首先放置扩张的回旋和 ii)其次放置扩张的回旋。在本文中,基于所采用的膨胀的残余块的数量,膨胀率从 1 开始增加两倍。例如,如果有 4 个膨胀的残余块,膨胀率将是 1、2、4、8。
插值卷积
为了解决由标准反卷积(即转置卷积)引起的伪影,作者在这项工作中采用了插值卷积。对于插值卷积,首先使用双线性和双三次插值等典型插值方法将输入调整到所需大小。然后,应用标准卷积。下图 5 显示了转置卷积和插值卷积之间的差异。
图 5。使用转置卷积(上)和插值卷积(下)获得的结果的视觉比较。摘自[4]
在我看来,这两种卷积都有相似的性能。有时候转置卷积更好,有时候插值卷积更好。
鉴别器网络
我们已经讨论了本文中使用的 PGGAN 鉴别器。这里,回想一下,鉴别器有两个分支,一个分支给出单个值,就像 global-GAN (G-GAN)一样,另一个分支给出 256 个值,其中每个值表示输入中局部区域的真实度。
关注输入中多个局部区域的真实性有助于改善完整图像的局部纹理细节。
目标函数
实际上,本文中使用的损失函数(即目标函数)或多或少与我们以前覆盖的论文相同。
重建损失:该损失是为了保证逐像素重建精度。对于这种损失,我们通常采用 L1 或 L2(欧几里得)距离。本文使用 L1 损失作为它们的重建损失,
N 是训练批次中图像的数量。 W 、 H 和 C 是训练图像的宽度、高度和通道。 x 和 y 是模型给出的地面真实和完整图像。
对抗性损失:我想你们大多数人现在都很熟悉这种典型的对抗性损失。
x 是地面真值,所以我们要 D ( x )返回 1,否则 0。注意 D 只是鉴别器的函数形式。
关节损失:
等式 3 是它们的联合损失函数。λ1,2,3 用于平衡每个损失的重要性。 g_adv 表示全局分支给出的输出,而 p_adv 表示 PatchGAN 分支给出的输出。注意,在它们的实验中,λ1、2、3 分别被设置为 0.995、0.0025 和 0.0025。
实验结果
在他们的实验中使用了三个数据集。 i) 巴黎街景【7】包含 14900 张训练图像和 100 张测试图像。 ii) 谷歌街景有 62058 张高分辨率图片,分为 10 个部分。第一和第十部分用于测试,第九部分用于验证,其余部分用于训练。总共有 46,200 个训练图像。 iii) 地点由超过 800 万张训练图像组成。该数据集仅用于测试,以显示概化能力。
为了比较典型残余块和扩张残余块的性能,作者训练了两个模型,即 PGGAN-Res 和 PGGAN-DRes 。对于 PGGAN-Res,使用了基本残差块和 3 个子采样块。这意味着输入被下采样 2/3 倍。对于 PGGAN-DRes,使用了扩张的残差块和 2 个子采样块。这意味着输入被下采样 2 倍。
图 6。训练具有不同鉴别器结构的相同生成器网络的结果。摘自[4]
图 6 示出了用不同鉴别器结构训练相同生成器网络的修复结果。从图 6 的最后一列可以看出,如果仅使用 G-GAN 鉴别器,则观察到窗口的局部纹理细节较差。与 G-GAN 相比,PatchGAN 提供了更好的窗口局部纹理细节,但窗口的角看起来与全局结构不一致。总的来说,PGGAN 可以提供最佳视觉质量的结果。
表 1。巴黎街景 256x256 图像的定量比较。摘自[4]
表二。巴黎街景 512×512 图像的定量比较。摘自[4]
表 1 和表 2 显示了在 256×256 和 512×512 两种分辨率的巴黎街景数据集上不同方法的定量比较。注意 CE 是上下文编码器1,NPS 是多尺度神经补片合成(MNPS) [2],GLGAN 是全局和局部一致的图像完成(GLCIC) 3。我们已经在以前的文章中讨论了所有这些方法。
从表 1 和表 2 中可以明显看出,PGGAN 在所有这些指标上都有所改善。但是,请记住,视觉质量比这些客观的评估指标更重要。
图 7。使用不同方法对完整图像的感知比较。摘自[4]
作者对这些方法进行了感知评估,如图 7 所示。要求 12 个投票者对原始图像的自然度和各种方法的修复结果进行评分。每位投票者被随机分配了来自巴黎街景数据集中的 500 张照片。请注意,CE 是在 128×128 图像上训练的,因此它在 256×256 测试图像上的性能很差。其他方法在这种感知评估中具有相似的性能。
图 8。256x256 巴黎街景数据集上的定性比较。摘自[4]
图 9。512x512 巴黎街景数据集上的定性比较。摘自[4]
图 8 和图 9 分别显示了尺寸为 256×256 和 512×512 的图像的修复结果。我建议读者放大以更好地查看结果。在我看来,PGGAN-DRes 和 PGGAN-Res 通常会给出具有更好的局部纹理细节的结果,例如,参见图 8 中的第 4 行和图 9 中的第 3 行。
结论
首先,残差学习的概念以扩张残差块的形式嵌入到生成器网络中。从他们的实验结果来看,残差学习有助于提高修复性能。
其次,PatchGAN 鉴别器的概念与传统的 GAN 鉴别器(G-GAN)相结合,以鼓励更好的局部纹理细节和全局结构一致性。
外卖食品
和以前一样,我想在这一部分列出一些有用的观点。如果你关注过我以前的帖子,你会发现这个帖子相对简单。
其实文中的大部分东西都和 GLCIC 3差不多。在网络结构中嵌入了两个新概念,即残差块和 PatchGAN 鉴别器,以进一步增强修复效果。
我希望你能实现这种典型的图像修复网络架构。在后来的修复论文中提出的网络或多或少是相同的。
你还应该注意到,重建损失和对抗损失是图像修复任务的两个基本损失。在后来的修复论文中提出的方法必须包括 L1 损失和对抗性损失。
下一步是什么?
这是我的第四篇关于深度图像修复的文章。到目前为止,我们实际上已经涵盖了几乎所有深度图像修复的基础知识,包括图像修复的目标,修复的典型网络架构,损失函数,一般图像修复的困难,以及获得更好修复结果的技术。
从下一篇文章开始,我们将会深入到更多的修复论文中,这些论文为图像修复设计了更具体的技术。假设你们已经知道了基础知识,我可以花更多的时间来解释这些修复技术。尽情享受吧!:)
参考
- Deepak Pathak,Philipp krhenbüHL,Jeff Donahue,Trevor Darrell 和 Alexei A. Efros,"上下文编码器:通过修补进行特征学习," Proc .计算机视觉与模式识别 ( CVPR ),2016 年 6 月 27-30 日。
- 杨超,吕鑫,林哲,Eli Shechtman,Oliver Wang,和郝力,使用多尺度神经补片合成的高分辨率图像修复, Proc .计算机视觉与模式识别 ( CVPR ),2017 年 7 月 21-26 日。
- 饭冢聪、埃德加·西蒙-塞拉和石川宽,“全球和局部一致的图像完成、 ACM Trans。论图形,第 36 卷第 4 期第 107 条,出版日期:2017 年 7 月。
- https://arxiv.org/pdf/1803.07422.pdf,[乌古尔·德米尔和戈兹德·乌纳尔](https://arxiv.org/pdf/1803.07422.pdf),[基于补丁的图像修复。](https://arxiv.org/pdf/1803.07422.pdf)
- 、何、、、任、、、【用于图像识别的深度残差学习】、 Proc .计算机视觉与模式识别 ( CVPR ),2016 年 6 月 27-30 日。
- Phillip Isola,,Tinghui Zhou,和 Alexei A. Efros,《有条件对抗网络的图像到图像翻译》。计算机视觉与模式识别 ( CVPR ),2017 年 7 月 21-26 日。
- C.Doersch,S. Singh,A. Gupta,J. Sivic 和 A. A. Efros。“是什么让巴黎看起来像巴黎?," ACM Trans。关于图形,第 31 卷第 4 期,第 101 条,出版日期:2012 年 7 月。
感谢您阅读我的帖子!如果您有任何问题,请随时询问或在此留下评论。下次见!:)
重温数据科学的图腾~变量
遵循此变量图提升您的数据科学项目
谎言有三种类型——谎言、该死的谎言和统计数字。
——本杰明·迪斯雷利
数据科学将其应用建立在不同的领域之上,如应用数学、运筹学、物联网等。然而,所有变量背后都有一个共同的“分母”。这完全是关于这位“非常规英雄”的,他的能力在数据科学家中是深远的,但是…事实也是如此!通常,没有太多的注意力放在它们的本质上,匆忙地通过它们,以无效的结论和错误的分析结束。例如:
为了吸引人才,幻想公司将在周日的报纸专栏中公布员工福利。给定以下额外津贴的分布,记者应该在专栏中说明什么是“平均”额外津贴?
额外津贴* = [1,1,4,5,5,3,2,1]
(*)表示员工享有的津贴数量(1:笔记本电脑,2:笔记本电脑+汽车等)
如果你刚刚回答了 2.75(否则: 22/8 ),请拿着这张地图,让我来指导你完成剩下的旅程——这是一篇致力于变量的游记。
范围~路线图
本文旨在开发一个战略叙事,数据科学家可能会听,然后回到变量的原则。这样,我们的目标是:
(a)向我们自己重新介绍最常见类型的变量
(b)针对每种情况,针对所选的指标和图制定一份指南,以便在具体情况下遵循
(c)学会以更加流畅和有效的方式传达变量驱动的结论
为了做到这一点,我们将通过不同的视角来研究变量;它们的性质和它们的测量尺度。
1.变量的性质
统计学中的变量通常可以描述数量或质量。在这种情况下,我们区分两大类1:
🔸定性(分类)变量:它们描述一种性质某物是什么或者怎样并且不能被计算。它们可以用实数或单词来表示。示例:团队、颜色、邮政编码。
🔸数量变量 : 描述数量的另一大类[ 某事物有多少 ]。显然,它是用数值来表示的。例子:身高,年龄,时间。
2.测量尺度
这个概念指的是一个规则系统,它定义了如何测量一个变量。有四种度量尺度:名义的、顺序的、间隔的和比率的[2]。每一项都根据其澄清以下问题的能力进行评估:
- 两个个体是否不同
- 不同的方向
- 差异的大小
🔸名义:指定性变量,可以分辨两个个体是否不同,但不能定义那个差异的方向和大小。例子:Name ( Mark 和 John 不同,但是在他们之间设置任何优先级都是没有意义的)。
🔸序数:针对数量变量,能够区分两个个体是否不同,以及差异的方向。然而,他们无法分辨出差异的大小。示例:赛跑运动员的排名(获胜者与第二名运动员不同,显然她是第一名)。
🔸*****:这个范畴是针对量化变量的,可以定义两个个体的差异,其大小和方向。零点(当变量值为 0 时)并不意味着一个量的缺失,这使得无法用比率来衡量个体之间的差异。例如:华氏温度(华氏 0.0 度并不意味着没有热量)。
🔸*****:具体到数量变量,能够解释两个个体是否不同,差异的大小和方向。此外,零点表明缺少一个量,这使得用比率来衡量个体之间的差异变得可行。示例:以开尔文为单位的温度( 0.0 开尔文实际上意味着‘没有热量’)。
(*)区间和比率变量,可进一步分为 2 个子类别:
🔸离散 : 任何两个相邻值之间都没有可能的中间值,意味着这些变量只能得到一定数量的值3。示例:卧室数量
🔸连续 : 任意两个值之间有无穷多个值。示例:重量
3.允许的统计方法*
很多时候,为了描述和处理一个分布,我们需要用一个或多个值(度量)来概括它。最常用的是平均值,其内容反映了一个概率分布的中心值或典型值;一个从中心倾向【4】的测量中衍生出来的概念。
在这些度量中,我们区分了(加权)均值、中值和众数。它们中的每一个都有不同的计算方法,并针对不同的情况形成适当的解决方案。
🔸均值:它是一个分布的“平衡点”,意味着低于它(均值)的分布值的总距离等于高于它的那些值中的相应一个。它同等地考虑了每个分布值(易受变化影响),并为区间和比率数据提供了良好的度量。
然而,当处理一个开放式分布(即上限是“100 或以上”)时,我们无法计算它。相反,使用中间值更有意义。此外,在处理有序数据时,使用平均值是有争议的[2]。在这种情况下,中位数是一个很好的选择,众数是一个更好的选择。
这同样适用于加权平均值,在这种情况下,数据点具有不同的权重。
🔸中位数:排序分布的中间值,与平均值不同,它不易改变(考虑中间值或两个中间值)。显然,它构成了一个稳健的统计量,非常适合汇总含有异常值或开放值的数值分布。此外,它还是汇总有序数据的好选择。
这里的缺点是它不能处理标称和序数数据,因为后者不是用数字编码的。
🔸模式:分布中出现频率最高的值。因此,它是名义数据、序数数据(尤其是当值用单词表示时)和离散数据(当我们需要向非技术受众传达平均值时)的理想指标。
在连续变量的情况下,这不是一个全有解;我们首先需要创建分组频率表,然后计算它。
简而言之,您可以使用下表:
表 1:集中趋势指标~变量类型
(*) 另一个有趣的方向是检查可变性,但这取代了当前文章的范围。
4.最佳可视化
根据每种变量类型的测量范围,可以使用一些特定的图表来更好地描述潜在的结论[5]。
🔸标称&序数 : 对于频率分布的情况,建议使用条形图(垂直或水平)和饼图。
- 柱形图:它很好地描绘了两个或更多变量之间的关系,同时提供了潜在趋势和变化的良好视觉印象。但是,当处理许多类别时,它可能会显得杂乱。使用太多或太少的类也会“掩盖”重要的数据模式。
- 饼图:它通常代表一个类别(有唯一标签的类别),每个楔形区的大小与分布中的类别成比例。与条形图相比,它的主要优点是可以更好地感知分布中的相对频率(百分比)。主要缺点是它不能比较两个数据集(分布)。
🔸区间&比率:这些变量类型的频率分布,可以通过直方图或核密度图(KDE)有效地可视化。方框&须状图是比较不同分布的另一个有趣选项,尤其是当我们处理连续变量时。
- 直方图:它的特点是在数据分布方面有丰富的描述能力,使读者很容易识别不同的数据,它们的频率和潜在的偏斜度。当我们处理巨大的数据集时特别推荐。
- KDE 图:与直方图相比,它给出了更清晰的分布图。但是,如果我们必须绘制五个以上的分布图,它可能变得不可读。
- 箱线图:如果我们想要识别数据集中的异常值,它非常有用,同时提供了一个关于落入任何特定四分位数的值的比例的良好视觉直觉。然而,它缺乏说明分布类型的能力。
综上所述,表 2 显示了每种测量尺度的推荐图:
表 2:可视化选择~测量尺度
回到介绍性的例子,我们很容易理解额外津贴是一个Quantitative
变量。此外,它属于Ordinal
测量尺度,尽管它是用数字编码的(我们分不清员工 A 和 B 的差异大小)。除此之外,它还构成了一个Discrete
变量。
因此,由于报纸的读者可能包括非技术人员,对于普通读者来说Mean
(3.14)没有太大意义,因为他们希望额外津贴的数量是一个整数。这同样适用于Median
(2.5)。另一方面,Mode
对于这种情况来说是更安全的选择,因为它保证了分布中的整数。因此,在报道这一结果时,记者应该避免使用技术术语(如“模式”、“变量”等),而简单地说“幻想公司”的员工通常/平均享有 5 项津贴。
总和
在实践中,许多人避免接触理论障碍,最终“在飞行中”检查变量。在这种情况下,他们要么选择错误的指标(即,只将“平均值”与平均值匹配)并绘制图表,要么得出错误的结论。
仔细看看每个变量代表什么——它的性质——可以加强我们的分析。此外,感知它被测量的方式,可以培养更好的度量和可视化选择。然而,我们不应该感到被迫选择一个或另一个指标,而是在和的基础上明智地做出选择。
这一次我们的旅程没有任何动作,也没有任何机器学习、NLP 等花哨的概念。尽管我们很喜欢它们,但我们应该始终尊重变量的基本“图腾”,因为它构成了通向数据科学的道路……此外,正如另一位本杰明·迪斯雷利所说:
当我想看一本小说时,我会写一本。
这实质上意味着,如果我们不能写出并巩固有效的统计结论,我们就无法有效地传达它们…
一如既往,非常感谢您的阅读!
参考文献:
1 D. S .耶茨,D. S .摩尔,D. S .斯塔内斯,统计学的实践(第 2 版。)(2003 年),纽约:弗里曼公司
[2] S. S .史蒂文斯,论测量的尺度 (1946),《科学新系列》
3 K. D. Joshi,离散数学基础 (1989),新时代国际有限公司
[4] Y .道奇,《牛津统计术语词典》 (2003),OUP 国际统计研究所(词条为“集中趋势”)
[5] J. Frost,数据类型指南和如何在统计数据中用图表表示它们 (2008),在线出版物“Jim 的统计”
开发人员的强化学习策略
理解强化学习策略的实用方法
菲利普·怀尔斯在 Unsplash 上的照片
更新:学习和练习强化学习的最好方式是去http://rl-lab.com
策略在某种程度上是一个棘手的概念,主要针对强化学习的初学者。这篇文章将试图用简单明了的英语澄清这个话题,远离数学概念。它是在考虑到开发者的情况下编写的。
政策
如果您听说过最佳实践或指导原则,那么您应该听说过政策。例如,考虑住在高楼里的人们的消防安全指南。也许最重要的指导方针是在火灾中不要使用电梯。人们应该关上门,储备水,使用湿床单,并让消防员知道他们的位置。
这一系列行动是根据指导方针发布的,这些指导方针是对长期以来积累的最佳实践和经验进行汇编的结果。
所以政策告诉你在面对某种情况时如何行动。它不会告诉你行动的结果或价值。然而,当遵循这个策略时,你隐含地期望有最好的可能结果,例如安然无恙地逃离火灾。
动作值
行动价值是指你采取行动并评估其结果或价值的时候。
例如,一个被困在着火建筑的高层的人考虑他/她的选择(可用的行动),然后尝试每一个来评估其结果。当然,在现实中,这是不可能的,因为一旦受伤就没有回头路了。但是在模拟、体育、游戏中,有可能玩许多场景并找出给出最佳结果的动作。
政策与行动价值的关系
不言而喻,策略是基于得分(或价值)最高的操作的最佳实践的集合。
我们这样写道
这意味着在状态 s 时,我们采取行动 a 使得 a 给出最佳结果。
其中 q(s,a)是在状态 s 采取的动作 a 的值。
但是有一个问题。你需要真正理解这是一个随机的环境,充满了不确定性。这意味着同一状态下的同一动作,每次执行都可能导致不同的结果。
例如,一个篮球运动员练习投三分球,即使他用同一只手从同一个点(或角度)投篮,有时会得分,有时会失手。他/她必须计算一个平均值(得分/投掷次数)来找出点(或角度)和手牌的组合效率。
为了找到比赛中使用的最佳角度和手,他/她必须从不同的角度和不同的手练习投篮,然后平均结果,以推断出哪种组合最适合他/她。
当然,解决这个问题的一个方法是执行大量的迭代。在每次迭代中,执行该状态下所有可用的动作,然后对每个动作取 q(s,a)的平均值,并更新策略𝛑(s).我们说我们正在更新每次迭代的策略。因此,在每次迭代之后,我们都有一个新的策略𝛑来反映计算出的 q 值。
在足够多的迭代之后,当 q(s,a)的平均值开始缓慢变化到足以认为它是稳定的时候,我们说我们已经到达了一个稳定的阶段,并且策略已经变得最优(意味着这是可以达到的最好的),我们称之为最优策略,并且我们写它为𝛑*
处理政策问题有不同的方式,改进政策也有不同的方式(即更新)
最优策略
最佳策略是当当前被训练的策略已经达到一个阶段,在这个阶段之后它不能被实质性地改进。
最优策略的重要性在于,它允许跟随它的代理实现“最佳可能”的结果。
动态规划方法中的策略
这是最简单的场景,也是最不现实的场景。所有的环境动态都是已知的,我们只需迭代计算 q 值,并在每次迭代后将具有最高 q(s,a)值的动作分配给策略𝛑(s).
在动态编程中,我们知道所有的状态和所有的转移概率,所以不需要发现任何东西,只需要计算值。
在本文中有更多关于动态编程的内容。
蒙特卡罗方法中的策略
在蒙特卡洛,我们不太了解环境的内部运作,所以需要通过播放剧集来发现。我们播放每一集直到结束,直到我们到达一个终端状态,然后我们计算每个访问的状态和执行的每个动作的 q 值 q(s,a)。
然而,与动态编程不同,我们无法计算所有状态的 q 值,因为我们事先根本不知道它们。我们必须在播放剧集时发现它们。现在的问题是,我们如何以一种有意义的方式播放这些片段,以便我们能够提取最佳策略?
当然,还有随机漫步策略,即在每个状态选择一个要执行的随机动作。这在开始时会起作用,但后来,当我们开始发现一些行为比其他行为更好时,保持随机行走很快就会变得低效,因为它不会学到任何东西。这种低效率的原因是因为策略没有用 q 的新值来更新。
因此,最好使用在每个州都能发挥最佳作用的政策。但这种策略的问题是,我们每次都将执行相同的操作,我们将无法发现新的状态,此外,我们也不确定所选择的操作是否真的是最好的。请记住,环境充满了不确定性,没有任何东西可以保证,如果一个行动在时间 t 产生了好的结果,在时间 t+1 也会有同样的好结果。因此,为了最好地利用这两种方法,我们采用了一种叫做𝜀-greedy.的策略
在𝜀-greedy 策略中,我们部分时间遵循贪婪策略(选择目前已知的最佳行动)1- 𝜀,部分时间选择随机行动𝜀。这将允许在某些时候通过随机漫步发现新的状态,并在大多数时候利用最佳动作。
随机政策
并不是所有的事情都是关于选择产生最佳 q 值的行为。要真正掌握这个想法,做以下实验:
和某人玩石头剪子布,注意连续玩同一个动作是个坏主意(即使前几次奏效了),因为你的对手会对此采取对策。例如,如果你经常玩石头,你的对手会玩纸并赢。
所以政策不再是关于某个行动在某个状态下的最佳结果,而是关于让你赢的行动的概率分布。换句话说,这是关于你的行为应该有多不可预测。
请注意,随机政策并不意味着它在所有状态下都是随机的。对他们中的一些人来说已经足够了。在这些状态中,策略确定性地动作,其动作概率分布(在这些状态上)对于一个动作是 100%,对于所有其他动作是 0%。
政策评价
评估一项政策意味着什么?
嗯,就像测试其他东西一样。你试着去发现它是否实现了它的承诺。
同样,策略评估包括要求策略提供给定状态的操作,然后执行该操作并计算结果(例如 q 值)
最终,并非所有操作都会产生预期结果,因此策略需要一些微调。
这是策略控制的工作也叫策略改进
政策控制/改进
策略控制或改进是关于在某个状态下执行一个动作后给策略反馈。动作的结果被输入到策略中,因此它更新其内部行为,在某种程度上使该动作在下一次达到相同状态时更有可能被使用(或不被使用)。这种反馈被称为更新。
再次考虑篮球运动员在三分线投掷的例子。从左手开始,他/她得分几次,因此策略被更新为使用左手。随着练习的进行,他/她在使用左手时有 30%的机会成功,但在使用右手时有 70%的机会成功。然后应该更新策略,在这个点(或角度)上使用右手而不是左手。
概念实现
为了从概念上实现一个策略,让我们考虑下面这个名为 IPolicy 的接口。它包含两种方法:
- getAction 返回在状态 s 时要执行的操作。
- update(s,a,some_value),以某种方式更新当前策略,以调整其在状态 s 时的行为。这通常通过告诉策略关于在状态 s 执行的动作 a 的结果(q 值或其他)来完成。
interface IPolicy{ // get action given state s as indicated by the current policy
getAction(s);
// update policy at state s and action a
update(s, a, some_value);
}
每个特定的策略都以反映其行为的方式实现这个接口。
例如,RandomPolicy 实现 getAction(s ),以便它在状态 s 返回随机动作。它不实现 update 方法,因为当行为总是随机的时,不需要任何更新。
class RandomPolicy : IPolicy { // get random action at state s
getAction(s){
return random action at state s
}
// no need for implementation since the policy is random
update(s, a, some_value){
}
}
GreedyPolicy 返回在状态 s 给出最佳 q 值的动作。因此,它必须将这些值存储在适当的结构中。
另一方面,更新方法更新在状态 s 和动作a计算的 q 值。这通常通过对先前计算的值求平均值来完成。
class GreedyPolicy : IPolicy {
// store q values by state and action
QValueByStateAndAction store // get action that has the highest q for the given state s
getAction(s){
return store.getActionOfMaxQ(s)
}
// update policy by storing the average of the q computed at
// state s and action a
update(s, a, q){
prev_q = store.getQForStateAndAction(s, a)
store.updateQ(s, a, average(prev_q, q))
}
}
EpsilonGreedyPolicy 返回在状态 s 的随机动作,𝜀部分时间,以及具有最佳 q 值(1- 𝜀)部分时间的动作。
至于更新方法,和 GreedyPolicy 的逻辑是一样的。
class EpsilonGreedyPolicy : IPolicy {
// store q values by state and action
QValueByStateAndAction store
epsilon = 0.1 // get random action epsilon time, highest q
// (1-epsilon) of the time
getAction(s){
rnd = computeRandomValue()
if(rnd < epsilon) return random action at state s
else return store.getActionOfMaxQ(s)
}
// update policy by storing the average of the q computed at
// state s and action a
update(s, a, q){
prev_q = store.getQForStateAndAction(s, a)
store.updateQ(s, a, average(prev_q, q))
}
}
StochasticPolicy 不直接依赖于 q 值(它可能会间接依赖于 q 值),但是它会根据成功的概率分布返回动作。例如,如果动作 A 在 60%的时间里成功,动作 B 在 30%的时间里成功,动作 C 在 10%的时间里成功。则该方法返回的操作遵循 60% A、30% B、10% C 的分布。
至于更新方法,它更新动作的潜在概率分布。
class StochasticPolicy : IPolicy {
// store q values by state and action
ActionByFrequency store// get action following the frequency of success
getAction(s){
return store.getActionByProbabilityOfSuccess()
}
// update policy by storing the occurrence of success
// result : success = 1; failure = 0
update(s, a, result){
success_count = store.getSuccessCount()
store.setSuccessCount(s, a, success_count + result)
}
}
高级算法
为了综合考虑所有因素并得出最佳策略,我们考虑一种高级算法,它可以执行以下操作:
- 根据需要循环以下步骤
- 从状态 s 的策略中获取一个动作:a = action.getAction(s)
这是策略评估 - 在环境中执行动作,观察奖励 r 和新状态s’
- 计算评估所采取措施的有效性所需的任何值 v 。这可能是 q 值或其他,它可能涉及神经网络或其他
- 向策略提供反馈,以便它可以自我改进:policy.update(s,a,v)
这是策略改进
它大概是这样的。
E =评估,I =改进
或者这个
向上的箭头是评估阶段,向下的箭头是改进阶段。
结论
这篇文章以一种实用的方式,通过描述性的解释而不是数学性的解释,来关注强化学习的策略。它是整个 RL 结构中的一个构建模块,对开发者来说收益最大。
相关文章
重新加权成人数据集,使其“无歧视”
预处理阶段偏差缓解的一个例子
由 Pixabay 提供
在之前的博客中,我们讨论了如何识别偏见以及减轻偏见的方法的机器学习工作流程。在接下来的几周里,我将会写一系列的文章来更详细地探索这个工作流程。首先,我将详细介绍一些与建模阶段相关的偏差缓解技术。
机器学习(ML)管道中我们可以干预以减少偏差的第一个阶段称为预处理。预处理描述了在应用机器学习算法之前发生的一组数据准备和特征工程步骤。采样、按摩、重新加权和抑制是学术文献中提出的不同预处理偏差缓解技术1。
在这篇文章中,我将重点探讨重新加权【2】,这是一种为数据分配权重的预处理技术。
这种方法的优点是,它不是修改标签,而是根据受保护属性和结果的类别为示例分配不同的权重,以便从训练数据集中消除偏差。权重基于频率计数。然而,由于这种技术被设计为只与能够处理行级权重的分类器一起工作,这可能会限制您的建模选项。
为了演示这种技术如何减少偏差,我使用了成人数据集【3】。该数据集中的二元目标是个人收入是高于还是低于 5 万美元。它包含了几个在美国受法律保护的特征,但是为了简单起见,在这篇文章中,我将把重点放在性上。从下表中可以看出,男性是享有特权的群体,有 31%的概率获得积极结果(> $50k),而女性群体有 11%的概率获得积极结果。
如下面等式中所描述的,不同的影响度量是数据中的区分度的度量。分数为 1 表示数据集是无歧视的。当计算男性和女性的未加权成人数据集时,得分为 0.36。
使用上表中的频率计数,重新称重技术将按照下式分配重量。例如,对于具有积极结果的特权群体(即收入超过 5 万美元的男性),权重计算如下:
因此,训练数据中每个类别的权重为:
通过将这些权重应用于计数,对于训练数据,不同的影响度量将变为 1,因此现在是“无歧视的”在预处理阶段对训练数据计算出这些权重后,它们可以用作逻辑回归、SVM 和 XGBoosts 等分类器的输入。
为了评估重新加权技术的效果,我训练了两个逻辑回归模型,一个有权重,另一个没有权重。实验结果表明了重新称重方法在减少歧视方面的有效性,如下表所示:
这种技术对于数据所有者不愿意与数据科学家共享敏感或受保护属性的用例尤其有用。通过为他们提供一个可以将这些权重分配给记录的脚本,数据科学家将能够在不直接访问受保护属性的情况下减少建模过程中的偏差。
与从训练数据中移除敏感属性等简单方法相比,实验表明预处理技术在减少偏差方面更有效。也就是说,平均而言,预处理技术不如处理中技术有效,因为它们不直接参与模型训练过程,并且需要进行一些精度折衷以降低区分度。
参考资料:
1 Kamiran F,Calders T (2009a)无歧视分类。IEEE IC4 计算机、控制和通信国际会议论文集。IEEE 出版社
[2]卡米兰,费萨尔和考尔德斯,图恩。无区别分类的数据预处理技术。知识与信息系统,33(1):1–33,2012
3“成人——UCI 机器学习。”5 月 1 日。一九九六年,http://archive.ics.uci.edu/ml/datasets/Adult。
将你的大脑从 Python 重新连接到 Java
学习一门新的编程语言时,你可能会遇到的七个概念障碍
自白:我个人的经历几乎和这篇文章的题目完全相反。实际上,我在大学里从 C++开始,转到 Java 来教授 AP 计算机科学 A,然后进入 Python 领域,使用所有可用的时髦数据科学库。现在我又在做一个 Java 项目(一个神经网络包,它真的把我对底层数学的理解推向了极限),我真的很注意这两种语言工作方式的细微差别。特别是,我一直在记录标准 Python 习惯在 Java 中会成为巨大障碍的地方。
印度尼西亚东爪哇|Waranont(Joe)onUnsplash
这篇文章是针对走在相反道路上的 Python 程序员(尤其是数据科学家)的;我将详细介绍在学习将 Python 本能应用于 Java 领域时可能会遇到的一些最初的概念障碍。特别是,我将避免表面上的差异,比如snake_case
和camelCase
或者 Java 要求你用分号结束一个语句,而 Python 却让它可选。我也将避免在 OOP 和函数式编程中陷得太深。这篇文章的重点是 Java 要求你以不同的方式思考如何解决你正在处理的任何问题。
尽管这看起来令人望而生畏,但请记住,在你之前,许多程序员已经成功地学习了 Java,所以这绝对是可以做到的。
1。Java 的开销比你习惯的要多。
在 Python 中,您可以用一行代码编写一个完整的带有控制台输出的“Hello World”程序:
print('Oh hi there, globe')
要在 Java 中完成这一点,您需要创建一个完整的类,并用一个main
方法作为入口点。
public class Room {
public static void main(String[] args) {
System.out.println("Oh hi there, globe");
}
}
本质上,每个 Java 程序本质上都是某个类的main
方法,它处理变量并告诉其他类做什么(有时,这个main
方法隐藏在自动化文件的深处,就像 Android 项目一样)。尽管有一些方法可以在一个完整的类之外运行 Java 在教学时,我是 j graspj grasp中的interactions
选项卡的忠实粉丝——但是要实现这一点还是有一些困难的。
简而言之,虽然 Python 允许您将一些命令直接输入解释器来测试算法,但是使用 Java 需要您将代码放在上下文中。
然后还有上面Room
中的大象:System.out.println()
。这看起来比仅仅产生控制台输出要多得多,对吗?这是因为我们对我们想要的输出显示方式非常非常挑剔;在我们可以放置该文本的所有不同位置中,我们希望它进入控制台,而不是日志文件、弹出窗口或以太网中的服务器。Python 默认假设到print
你希望文本显示在控制台上,但是 Java 一般不做这样的假设。
这就引出了我们的下一点…
2.Java 要求你比 Python 更具体。
Python 让你逃脱了很多麻烦。想想你写过多少次这样的代码:
that_value_i_need = some_object.mystery_method()
却不得不跟进:
type(that_value_i_need)
为了弄清楚,确切地说,mystery_method()
正在返回。
这不一定是处理事情的最佳方式;显然,医生应该解释你将从mystery_method()
中得到什么,所以绝对有可能你在调用之前就已经知道你将得到什么。但是 Python 让您逃脱了这一点。您可以为that_value_i_need
创建一个变量,并且知道它可以处理mystery_method()
抛出的任何内容。
此外,您可以非常自信地完成像这样的走钢丝行为,甚至不必考虑所涉及的数据类型:
important_value = some_method(a, bunch, of, arguments)
important_value = unrelated_class.another_method()
毕竟important_value
只是一个变量,可以保存它需要的任何数据类型……对吧?
在 Java 中,绝对不是这样。当声明一个变量时,需要从一开始就指定它的数据类型,然后在它的整个生命周期中被锁定。
虽然这一开始听起来令人生畏且有局限性,但我发现在 Java 中阅读别人的代码要容易得多。我可以自信地指着一个变量说,“x
是一个int
,因为它在第 72 行被声明为一个int
。如果它保存的是由someUsefulMethod
返回的值,这告诉我someUsefulMethod
返回一个int
(或者可以提升为int
的东西,比如short
)。
尽管当您尝试运行自己的代码和error: cannot find symbol
消息时,这最初会让您感觉像是一堵不可逾越的保留字墙,浮动在其他人的代码和error: cannot find symbol
消息中,但 Java 要求您如此具体的事实导致代码比 Python 明显更加自文档化、可预测和明确。尽管我在编写 Java 代码时需要更加细致,但我对理解它的工作方式有了明显的信心。
我对自己的 Python 代码的理解的物理表现| Nathan Dumlao 在 Unsplash 上
说到文档,javadoc
是一个生成干净文档的强大工具——即使您没有明确地写下注释(您应该这样做)。javadoc
将读取您的代码并生成有组织的 html 文件,这些文件准确地指出您需要什么数据类型来传递一个方法,以及您可以得到什么值作为回报。大多数 ide 甚至有一个按钮可以帮你做到这一点。
为了让事情尽可能不含糊…
3.Java 比 Python 更严格。
让我们重温一下 Python 中的 Hello World 程序。我们可以有多少种不同的写法?
# version 1 - single quotes
print('Oh hi there, globe')# version 2 - double quotes
print("Oh hi there, globe")# version 3 - triple single quotes
print('''Oh hi there, globe''')# version 4 - uh, triple double quotes, because why not?
print("""Oh hi there, globe""")
Python 为完成同样的任务提供了很多选择——在上面的例子中,我们可以用四种不同的语法来封装我们的字符串。当我学习 Python 的时候,这让我陷入了一个循环;我怎么知道何时使用哪一个?有没有一个优雅的经验法则需要记住?
如果你是一个 Python 程序员,即使经验很少,你也应该知道接下来会发生什么:“大多数人只会用单引号。除非字符串中有撇号,在这种情况下,可以用双引号括起来。除非字符串中既有撇号又有双引号,在这种情况下,您可以用三个单引号将其括起来。我猜,如果字符串中有单引号、双引号、三单引号和三双引号,那么你总是可以回到单引号,并在任何需要的地方使用转义字符。”
因为 Java 是如此的具体和严格,所以学习使用String
要简单得多:总是用双引号将它们括起来。如果在你的String
中有一个双引号,在它前面放一个转义符\
:\”
。如果你的String
里面有一个\
,在它前面加一个转义符:\\
。如果你看到单引号,比如'a'
,那意味着你在处理一个char
,而不是一个String
。
如果你已经习惯于将你能想到的每一个值——从int
到KitchenSink
——放入 Python 中的一个列表,你会发现使用 Java 数组需要一种非常不同的思维方式。Java 数组中的所有元素必须具有相同的数据类型,类似于ndarray
或Series
,但是通过仔细的设计,您可以通过多态引用绕过这个限制。
一个 Python 列表可以容纳所有这些。Java 数组可能不能。|Scott UmstattdonUnsplash
尽管这种特殊性可能令人讨厌,但它使您的代码明显更具有可预测性,这是我的可读性黄金标准。块是用花括号而不是缩进组合在一起的,所以你可以很容易地告诉他们从哪里开始和结束。虽然这在您的计算机上不是一个大问题,但我发现在印刷的 Python 书籍中按缩进分组(其中代码被分成多页)会给初学该语言的人带来问题。
此外,这种严格性意味着变量作用域在 Java 中比在 Python 中更容易理解,如果你尊重花括号,它通常可以归结为“在花括号中定义?只存在于花括号中。实际上,您必须在 Java 中声明对所有类方法都可用的global
变量,而在 Python 中,如果您曾经循环使用变量名,您可能会意外地从程序的完全不同的部分使用语法上有效(但完全不合适)的值。最重要的是,你可以在你的类中拥有private
字段,而不是希望每个人都尊重你的下划线变量名。
如果你犯了错呢?与其让你的代码运行 90%的运行时间,不如在遇到第一个错误时就中止…
4.Java 是编译的,所以很多因误解前面几点而产生的错误在运行前就被捕捉到了。
显然,Python 会在运行代码之前解析代码,如果它不能理解您的意图,就会生成一个SyntaxError
,但是我敢肯定,当您的代码在完成了一半您希望它做的事情之后,因为一个简单的错误而突然停止时,您所有人(尤其是数据科学家)都会感到恼火。
通常(无论如何,根据我的经验),这种情况发生是因为您试图对错误类型的对象执行某种操作——比如调用方法。不是语法错误(你记住了.
!),所以解析器没有捕捉到它,回溯会带您进入核心库的一个兔子洞,所以您可以确切地看到 Python 假设您想要对您给它的神秘对象做什么。
在 Java 中,这一步发生在运行代码之前。因为在声明变量时,您已经将变量锁定为特定的数据类型,所以 Java 编译器可以验证您试图对该对象执行的每个操作在运行时之前实际存在*,如果编译器检测到不是为该数据类型定义的操作,您的程序将根本无法编译和运行。*
这并不是说你永远不会让你的 Java 程序意外终止——这种语言有一个动态的方面,所以你会和NullPointerException
和ArrayIndexOutOfBoundsException
成为非常好的朋友——但是这种额外的验证层,结合 Java 严格和特定的特性,往往会将这些运行时错误引入可预测的小巷。
5.设计 Java 方法几乎与设计 Python 函数完全不同,因此您需要以不同的方式考虑您的问题。
这种严格性的缺点是 Java 方法调用可能很快变得难以控制。我非常喜欢 Python 的功能性,不仅开始依赖无序的关键字参数,还开始传递函数并为可选参数提供默认值。
这是完全有效的 Python 代码…
def multiply(a, b, c=1):
return a * b * cmultiply('hello', 3)
…在 Java 中无法运行。因为 Java 是静态类型的,所以在声明变量时就锁定了数据类型。这意味着您必须以与方法签名中出现的顺序完全相同的顺序传递具有该数据类型的值。虽然这降低了灵活性,但也减少了对代码的误用。
虽然您可以让同名的方法处理不同的参数列表,但 Java 通过重载来处理这一点,这需要您编写不同版本的方法来处理您希望作为参数列表支持的每个数据类型序列。Java 检查您传递的数据类型,查看是否定义了处理数据类型序列的方法,并调用该方法——具有相同名称和不同参数的方法实际上没有任何其他方式的联系。
如果你想为你的一个参数提供一个默认值呢?您必须重载该方法并从列表中删除默认值参数。
事实上,签名是由参数列表中的数据类型定义的,而不是由变量的名称定义的,当您习惯于用 Python 思考时,这也会产生问题。例如,如果我们想为此方法的重载版本提供默认参数:
public static double getArea(double length, double width){
return length * width;
}
如果在参数列表中包含两个具有相同数据类型的版本,我们会遇到问题:
public static double getArea(double length) {
return length * 10;
}public static double getArea(double width) {
return width * 5;
}
这两个方法都被称为getArea
并且都期望一个double
,所以当你调用getArea(12.3);
时,Java 不知道该走哪条路。
除此之外,虽然 Java 确实对 lambda 表达式有一些支持,但它们与函数式编程相差甚远,试图用面向对象的语言来思考函数式解决方案无异于自找灾难。
哦,还有返回类型?Java 将您限制为一种——并且您必须在编写方法时指定数据类型,这要求您提前很好地知道您想要返回什么。你可能习惯于认为 Python 能够返回多个值…
def get_stuff():
return 1, 2, 3x, y, z = get_stuff()
…但它实际上返回一个对象——捆绑到一个元组中的所有值:
>>> type(get_stuff())
<class 'tuple'>
在 Python 中,你可以在不知道这个事实的情况下惊人地高效,但是在 Java 中,你总是必须知道你的方法返回什么。
6.除了数据类型之外,Java 还要求你考虑更低层次的概念,比如内存管理。
这可能有点草率(特别是对于来自没有自动垃圾收集功能的 C 语言的人来说),但是 Java 的某些部分需要您考虑在内存方面发生了什么。我说的是参考变量!
例如,当您尝试在 Python 中运行以下代码时会发生什么?
my_list = [1, 2, 3]
print(my_list)
如果您来自纯 Python 背景,您将会看到以下输出:
[1, 2, 3]
另一方面,您从下面的 Java 代码中得到了什么?
public class JavaFeatures {
public static void main(String[] args) {
int[] myList = {1, 2, 3};
System.out.println(myList);
}
}
没错!它将打印内存地址。这里是我的电脑存储的地方:[I@6d06d69c
同样,Python 假设当您打印引用列表的变量时,您希望看到列表的内容,而 Java 在默认情况下,打印的正是引用变量中存储的内容:数组在内存中的位置。要显示内容,您需要遍历它们:
for (int i = 0; i < myList.length; i++) {
System.out.println(myList[i]);
}
虽然这需要一点点努力来让你的大脑理解,但它迫使你思考当你抛出引用变量(该对象的内存地址)时,实际上传递的是什么*,这让你更深入地了解你的计算机实际上是如何执行其任务的。*
虽然 Java 不像其他语言那样低级,但是从 Java 引用变量跳到 C 指针比从 Python 引用跳到 C 指针要容易得多,因为您已经习惯了遇到上面这种迫使您考虑内存地址的问题。
但是 Python 缺乏“设置好就忘了”的心态并不局限于引用变量。
7.Java 并没有真正意义上的“T1”或“T2”。
当我考虑是什么让 Python 成为一门有用的语言时,我通常不会考虑语言特性或语法。我想到了 Python 生态系统。通过快速浏览命令行,您可以使用类似于
*pip install snazzy_new_library*
下载一个snazzy_new_library
以便随时使用。
尽管你会在 message 上发现有人坚持认为像maven
或gradle
这样的打包工具和pip
或conda
一样强大,但事实是,虽然这些工具确实强大*,但它们并不真正等同于*。* Java 程序的结构通常是不同的——不是让一个包对该环境中的任何程序全局可用,而是将包直接与需要它们的应用程序捆绑在一起,并且通常需要通过将一个 jar 文件放到正确的位置来手动添加,或者包含在一个管理你的依赖性的工具中(这就是像maven
和gradle
这样的工具实际上是*擅长的)。**
这对 Python 程序员来说可能很不方便,因为它要求您跳过额外的关卡,在您的项目中包含一个有用的现有库,结果项目文件的大小可能会变得很大。另一方面,将包含的库与项目捆绑在一起可以确保必要的代码在需要时确实可用。
结论:你可以学习 Java,它会让你成为更好的程序员。
不得不调整自己的问题解决技能以适应新编程语言的怪癖可能是一项可怕的任务,但学会一门新语言确实会扩大你工具箱中的工具库——即使是在你的第一语言中。c 指针让我困惑,直到我习惯了使用 Java 引用变量,Java 中的 lambda 表达式让我困惑,直到我看到它们是如何在 Python 的函数式编程中使用的……这反过来又解释了为什么我们在 c 中需要函数指针。
尽管这看起来令人望而生畏,但请记住,在你之前,许多程序员已经成功地学习了 Java,所以这绝对是可以做到的。
利用 RFM 分析进行客户细分
最后一个聚类模型,你不必花时间去解释
作者图片
任何优秀的数据科学家都(或者至少应该)擅长采用复杂的数学和统计模型,并以简单明了的方式解释它们。最终,我们的工作是为我们的公司或客户创造价值。即使我们有一个准确率为 99.9999999%的模型,管理层也不太可能用它来做决策,除非他们理解(至少)模型的基础知识。
我们的问题
任何业务的很大一部分都是围绕着了解公司的客户,并确保他们的需求和愿望得到满足。这有助于我们确保我们的客户确实在使用我们创造/提供的产品,并确保我们将自己的资源投入到最佳的业务领域。了解我们客户的一个常见方法是将他们分成不同的群体。我们可以把精力集中在代表我们潜在客户的几个不同的群体上,而不是试图为成千上万的个人或公司理解和开发产品。这使我们能够做出更明智、更有针对性的决策,从而产生更大的影响。简而言之,它确保我们看到的是森林而不是树木。
如果你在过去几年中一直在研究机器学习,你的大脑已经自动切换到无监督学习模式,并且你已经在考虑编码一个 k 均值或最近邻模型。我不能否认我通常不在你身边。但是让我们后退一步。有没有更简单的方法?一个几乎不需要向管理层解释的问题?一个计算成本低得多的?
RFM 来了
RFM 分析始于 90 年代中期,当时公司试图为直邮广告寻找最佳群体。大多数网站 Jan Bult 和 Tom Wansbeek 的文章“直邮的最佳选择”出现在*营销科学,*作为第一个出现的想法。这个想法很简单。
“RFM”代表近期、频率和货币价值。总之我们要根据: 对客户进行分组
- 他们最近一次交易是多久前?
- 他们多久购买一次?
- 他们在我们这里花了多少钱?
上个月购买了三件商品的客户比过去三年购买了两件商品的客户更重要。在我们的产品/服务上花了 10,000 美元的客户比花了 50 美元的客户更重要。正如您所看到的,这种方法几乎不需要(如果有的话)解释。
分析的实现同样简单。对于每一组(R,F,M ),我们将把我们的客户分成 N 个部分。然后,我们将从 1 到 N(1 为最佳)对每个组进行排名。最后,我们可以按原样使用我们的 RFM 分数,或者我们可以使用某种聚合方法为每个客户开发一个超级分数。
我们开始吧
首先,我们需要一份我们正在分析的时间段内所有发票的清单。对于每张发票,我们只需要三样东西:
- 客户名称
- 发票日期
- 金额。
对于任何分析师来说,这应该只不过是一个简单的 SQL 查询。
然后,我们将把 SQL 数据放入 pandas 数据帧中。(本例中的数据已被匿名化。)
作者图片
我们现在将创建一个新的数据框架(rfm ),用于存放我们的 RFM 指标。我们的新数据框架将包含每个客户的一行,以及他们各自的 R、F、M 评级。
我们需要一些辅助函数来生成我们的指标。我们可以用熊猫的申请来使用我们的数据。
最后,我们需要最后一点代码来将我们的客户分成 N 组,并分配一个等级。在这个例子中,我选择了 4 个组,并基于简单的四分位数进行划分。
我们的排名现在完成了。现在,我们可以深入分析,找出对管理有用的不同部分。
作者图片
最终分析
通过 RFM 分析,我们可以选择许多不同类型的客户群。当然,我们的最佳客户(最近频繁购买,花了很多钱)用 R=1,F=1,M=1 表示,或者更简单地用(1–1–1)表示。以下是其他一些著名团体的名单:
- 低消费但积极忠诚的客户—(1–1–3 | 4)
- 我们放过的最佳客户(4–1 | 2–1 | 2)
- 新的大型消费客户(1–4–1 | 2)
- 这个清单还在继续。
所有这些部分都可以通过简单的 pandas 过滤器轻松访问。
当然,没有可视化的分析会是什么?RFM 分析的一个小的附带优势是它提供了 3 个维度——使其易于可视化。让我们一起走进它。
作者图片
结论
当然,这种分析不像 k-means 或几乎任何真正的机器学习算法那样优雅或激烈——但这不是我们所追求的。我们用优雅换取了轻松和简单。
生成数据、编码解决方案以及审查结果可能只需要你喝一杯咖啡的时间。我们也不需要 GPU…从开发和计算的角度来看,这种分析是成功的。
正如我们在开始时所讨论的,我们的工作是为决策者提供可行的见解。在这里,时间就是金钱。我们方法的简单性节省了我们的时间(因为我们不需要开发 10 页的 PowerPoint 来解释我们的方法)并节省了管理时间(因为他们不需要坐在那里看完你的 PowerPoint)。然而,最终我们提供了可操作的细分市场,可用于整个营销和产品开发。
你会用这些空闲时间做什么?
附言
- 如果您想进一步压缩数据,您可以将 R、F、M 指标相加,产生一个超指标。
- 如果你想得到更精细的结果,使用更多的箱子而不是我上面用的四分位数。
- 如果一个或两个指标比其他指标更重要,将指标与加权和结合起来以反映这一点— a(R) + b(F) + c(M) = y,其中 a+b+c = 1。
- 定制这种简单方法的能力是非常了不起的。
感谢您抽出时间阅读。我真的很感激。完整的代码可以在我的 GitHub 上找到。
原载于 2020 年 10 月 15 日【http://lowhangingfruitanalytics.com】。
使用 BigQuery ML 进行 RFM 分析
使用 BigQuery ML 中的 RFM 分析和 Data Studio 中的可视化进行用户细分。
图片由皮克斯拜的 Gerd Altmann 提供
假设您想通过使用存储在 BigQuery 中的谷歌分析数据,基于用户的网站应用活动创建细分市场,从而为用户的转化和重新激活进行再营销。
在本指南中,我将展示如何实现一种流行的技术来细分用户,并将结果可视化,以帮助做出重要的营销决策。
我们将经历的技术是 RFM 分析。我们将使用 BigQuery ml 来创建分段,并使用 data studio 来可视化结果。这是它的样子。
细分用户的仪表板,作者 Muffaddal
在本指南中,我们将:
首先,计算用户的最近度、频率、和货币价值。
其次,使用 k-means 聚类算法创建 客户细分。
第三,在 data studio 中可视化结果。
第四,将 RFM 的分析结果导入谷歌分析进行激活
第五,自动化 RFM 分析流程。
注意:如果你有兴趣在 GCP 探索更多这样的技术,这里的 是一个很好的课程,可以从 Google 的 开始。
什么是 RFM 分析?
客户细分策略之一是使用 RFM 分析创建用户群组。它基于用户过去的活动。它使用三个指标来执行分段:
- 最近度:自上次购买后的天数。
- 频率:用户购买的次数。
- 货币:用户在购买上花费的总金额。
主要用于购买,但 RFM 分析也可以定制用于其他重要的用户活动,如查看的页面数量,而不是购买基于内容的业务的次数,如medium.com。
利益
RFM 分析的好处是,由于用户是根据他们过去的活动进行细分的,我们对他们与业务的密切关系有一个很好的了解,因此每个细分市场都可以有针对性。
举个例子,一个经常在网站上购物的用户,他的平均购买量也很高,我们立刻知道这是一个忠实的客户,应该用来传播口碑。而另一方面,可以向最近购买但不经常购买的用户群提供折扣优惠,以帮助他更习惯该产品。
RFM 分析可以有所帮助
- 增加客户保留率
- 增加响应速率
- 增加转换率
- 增加的收入
- 增加电子邮件中心
data camp 上有一个关于使用 RFM 分析进行用户细分的很好的教程,可以帮助进一步理解这种用户细分技术背后的直觉。如果你有兴趣,一定要去看看。
在第一章中,您将了解群组以及如何分析它们。您将创建自己的客户群…
bit.ly](https://bit.ly/2BfqNoI)
计算 RFM 值
为了计算 RFM 分析,我们需要三个指标,即用户 id (在我们的例子中是 GA 客户端 id)转换事件日期(在我们的例子中是购买事件日期),以及购买事件支付的金额。
Muffaddal 用于 RFM 分析的主数据集表
注意: 我会假设你的数据是上面描述的格式。如果不是,那么你要么转换你的数据为上面的格式,要么修改下面的查询。
首先,我们将使用下面的查询计算每个用户的最近次数、频率和货币值。
使用 SQL 计算用户的近期、频率和货币价值。
用您的数据表名称替换line 9
上的<your table >
,运行上面的查询应该会得到您的每个用户的最近值、频率和货币值。姑且称之为query 1
该查询的输出将如下所示:
用户的新近性、频率和货币价值
将查询的输出保存为名为RFM_Values
的大查询数据表,如下所示
如何用 Muffaddal 将查询结果保存为 BigQuery 表
接下来,我们应用 k-means 聚类,根据用户的 RFM 值对他们进行分组。
基于 K 均值聚类的用户细分
使用 BigQuery ml,我们可以将机器学习模型直接应用于 BigQuery 中的数据集。使用 BigQuery ml 进行客户细分也相当简单。
要使用 BigQuery ML 算法,请使用命令CREATE OR REPLACE MODEL
启动您的 SQL 查询。这告诉 BigQuery 将机器学习算法(在 options 命令中提到)应用于查询的 out。
下面是如何使用 BigQuery ML 对上一次查询得到的结果应用 k-means 聚类:
使用 Biguqery ML 创建 k 均值模型
用您想要存储模型输出的表的名称更新devtest.Demo.RFM_Model
,并在line 10
更新项目和数据集值。运行查询,您将在数据集中创建一个新表。我们称之为我们的query 2
。
导航到模型化表的评估选项卡以查看统计数据。它应该是这样的:
k-均值模型输出,用 Muffaddal 表示
Centroid id
列,说明模型将我们的用户分组到了哪个细分市场。和 count 展示了每个细分市场中的用户数量。
如果我们把眼光放在最近、频率和货币列上,我们可以检查该模型根据什么对所有用户进行分组。
例如,Centroid id
列中的第四部分是不经常使用该应用程序的用户,他们最近也不活跃。然而,他们的购买力是其他细分市场中最高的。
另一方面,第一部分用户和第四部分用户一样活跃,但是他们的购买力有点低。
由于这两个用户都已经超过 2 个月(平均 74 天)没有使用我们的网站,他们可能会有所改变,我们应该计划一个营销策略让他们回来。
注意:假设我的数据模型产生了具有 5 个聚类的最佳片段(参见查询中的 *line 4*
)。在您的情况下可能会有所不同,所以检查不同数量的分类的结果,看看哪一个给了您最好的分段。
一旦我们创建了我们的细分市场,是时候将它连接回 user_id,以便我们可以使用它来重新定位它们。
下面是执行此操作的查询:
查询来生成细分用户的最终表。
注意:我已经在上面的第 15 行将每个细分市场命名为细分市场 1、2 等,但是我将建议给它们一个适当的名称,如忠实用户、潜在用户、流失用户等。
我们将最后一个查询称为query 3
结果如下所示:
Muffaddal 的分割结果
将其保存为 BigQuery 表RFM_Final
,用于分析和仪表板。
在 Data Studio 中可视化 RFM 分析结果
下一步是将我们的RFM_Final
表连接到 Data Studio 并可视化结果。接着,根据我们最终的数据表创建了一个模板仪表盘。
RFM 仪表板,由穆法达尔
它在顶部显示了所有近期、频率和货币值的平均值。理想情况下,平均最近值应该最小,频率和货币值应该最大,这样顶部的 KPI 指标有助于查看应用程序的当前排名。
之后,控制面板将三个指标按细分市场进行细分,以帮助了解它们的分布情况。通过过滤报告,我们可以彻底检查每个细分市场。
Data studio 的混合也可以用于将这些细分市场与用户的其他活动联系起来,以丰富报告并进一步深入行为分析。
最棒的是,每当RFM_Final
表更新时,我们的仪表板就会自动更新。我们还将看到如何自动进行 RFM 分析,以及时更新用户群。稍后将详细介绍。
注意 : 该模板是用 google sheets 而不是 BigQuery 构建的,以避免成本,但它应该也可以与 BigQuery connector 一起重用。
基于 RFM 结果重定向用户
现在你已经将你的用户细分并可视化了。其中一些将是高付费的忠实用户,而一些将是失去的用户,需要大量有针对性地重新激活他们。所以下一步是用不同的活动和促销来推销它们。
但是怎么做呢?
想法是将与每个用户相关的部分发送到谷歌分析,并从那里创建一个观众和目标,因为你喜欢使用谷歌广告。因此,我们必须将丰富的数据发送给谷歌分析。
我们也可以在这里利用 GCP。这样做使得我们所有的数据都在一个平台上。我们必须建立一个数据管道,将数据导入谷歌分析。要设置管道,请在云 shell 中输入以下命令来安装所有必需的依赖项:
git clone [https://github.com/GoogleCloudPlatform/cloud-for-marketing.git](https://github.com/GoogleCloudPlatform/cloud-for-marketing.git)
安装完成后,我们所要做的就是将数据从RMF_Final
表移动到云存储,数据将自动导入 GA!
这里是 关于如何设置 GA 导入数据管道 的详细指南。
数据管道继续监视云存储桶中安装期间提到的文件夹,当它看到任何新的上传文件时,管道会处理它并将其发送到 google analytics。
自动化 RFM 分析
运行上面讨论的所有三个查询,将在您需要的任何时候为您的用户群获得更新的细分市场。但是,我们也可以自动执行这一手动流程,以便根据业务需求每月/每季度更新细分市场。
注意:自动化过程需要一点编程知识,因此您可能需要请团队中的技术人员来实现自动化过程。
我们有三个查询需要及时运行,以便从用户群中创建细分市场。首先,计算 RFM 值(Query 1
)。第二,创建模型(Query 2
)。第三,合并模型输出和用户 RFM 值(Query 3
)。
想法是链接所有三个查询,以便一个查询的完成执行另一个。
下面是数据流的样子:
RFM 自动化数据管道,由 Muffaddal
注意 : 我将假设已经为所有三个查询创建了表,如以上部分所示。
1-让我们首先创建一个发布/订阅主题,因为在创建 query 1 schedular 时会用到它。我将其命名为RFM_Model_Topic
,因为它将触发负责执行我们的模型查询(即查询 2)的云函数。
RFM _ 模型_Topic
发布/订阅主题,作者 Muffaddal
复制主题名称,因为在创建query 1
schedular 时需要它。
2-接下来,转到 BigQuery,在查询编辑器中粘贴查询 1,它为我们的用户计算 RFM 值,然后单击“Schedule query”按钮创建新的查询 schedular。
通过 Muffaddal 创建新的计划查询
3-然后,在调度程序创建菜单中输入所需的值来创建调度程序
查询日程创建菜单,按 Muffaddal
这个 schedular 将做的是,它将在指定的时间运行,以计算用户的最近、频率和货币值,并存储在上述 BigQuery 表中。一旦调度完成执行查询,它将向我们的RFM_Model_Topic
发送一条消息,这将触发一个云函数来触发我们的模型查询。所以现在让我们创建一个云函数。
4-进入RFM_Model_Topic
发布/订阅主题,点击屏幕顶部的“触发云功能”按钮。
由 Muffaddal 从发布/订阅主题创建云函数
5-进入如下所示的设置,并将云功能命名为RFM_Model_Function
云功能设置,由 Muffaddal
6-将下面的代码粘贴到index.js
文件中
运行 RFM 模型查询的云函数
一旦我们的 BigQuery 被执行,我们就向一个名为RFM_Final
的新发布/订阅主题发送一条发布消息,这触发了负责我们最后一个查询的云函数,该查询将 RFM 值和模型结果组合在一个数据集中。
7-因此,接下来,在发布/订阅中创建RFM_Model
主题和一个云函数,就像我们在上一步中做的那样。将下面的代码复制粘贴到云函数中,这样它就可以运行我们最后的查询了。
运行 RFM 最终查询的云函数
就是这样!
我们自动化了 RFM 分析流程,该流程将在每个月初自动更新我们的仪表板。
摘要
通过个性化营销瞄准细分用户,可以提高留存率、转换率和收入。RFM 分析根据用户在网站/应用程序上的活动创建用户群组。
在本指南中,我们通过利用 BigQuery ML 使用 SQL 查询执行了 RFM 分析,并在 data studio 中可视化了结果。我们还谈到了如何通过向 Google analytics 导入数据来定位细分用户。最后,我们建立了数据管道来自动化整个 RFM 分析过程,这样我们就可以每月获得更新的用户群。
我希望我能够传达这样一个想法,即我们可以毫不费力地从现有的数据中提取出多少信息。以及支持和改进业务的有效性。
您喜欢的类似分析阅读:
根据用户的购买行为对其进行细分,从而改进广告活动。
towardsdatascience.com](/user-segmentation-based-on-purchase-history-490c57402d53) [## 向 BigQuery 发送 Google Analytics 点击量数据
如何发送标准的谷歌分析点击量数据到 BigQuery?
towardsdatascience.com](/send-google-analytics-hit-level-data-to-bigquery-5093e2db481b) [## 将细分的用户数据发送到 Google Analytics 进行重新激活。
建立一个数据管道,使用 Google Cloud Platfrom 将数据导入 google analytics。
towardsdatascience.com](/automate-data-import-to-google-analytics-471de2c3fc76) [## 通过个性化推荐增强用户体验
本指南将详细介绍基于项目的推荐系统的工作原理以及如何在实际工作中实现它…
towardsdatascience.com](/comprehensive-guide-on-item-based-recommendation-systems-d67e40e2b75d)
信用卡客户的 RFM 聚类
客户信用卡交易数据的新近性、频率和货币值(RFM)的 K 均值聚类案例研究
在 Unsplash 上由 Adeolu Eletu 拍摄的照片
新近、频率、&货币(RFM) 是可用于客户细分的技术之一,也是长期使用的常规细分方法之一。
- 最近是指客户最近一次使用我们的产品进行交易的时间
- 频率指客户使用我们的产品进行交易的频率
- 货币价值是指顾客在我们的产品上花了多少钱
RFM 方法简单明了;我们只需将我们的数据(通常以交易数据的形式)转换成由三个变量组成的数据框架: 、最近交易、 和 交易金额(货币值)。
交易数据本身是记录或捕获客户所做的每一笔交易的数据。通常,交易数据包括交易时间、交易地点、客户消费金额、交易发生在哪个商家,以及交易发生时可以记录的每一个细节。
让我们看看稍后将用作我们的研究案例的事务性数据集。我们的数据集是 2016 年每个客户的信用卡交易数据。交易数据集由 24 个特征组成,记录了客户进行的每一笔交易。即使我们的数据集中有许多特征;我们不会使用所有这些特征,而是仅使用少量的特征,这些特征可以转换成 新近度、频率、 和 货币值 。
链接到数据集:https://www . ka ggle . com/derykurniawan/信用卡交易
图一。交易数据特征
如果我们回到我们对 RFM 特征的描述;我们只需保留 *customerId、transactionDate、*和 transactionAmount 即可在由 customerId 特征分组的新数据帧中创建新近度、频率、和交易金额特征。
对于 Recency 特性,我们可以用 transactionDate(最新交易)的最大值减去当前日期。由于我们的数据集仅包含 2016 年的交易数据,因此我们将 2017 年 1 月 1 日设置为当前日期。
对于 Frequency 特性,我们使用 r 中的 n() 函数计算每个客户进行了多少次交易
对于交易金额功能,我们计算每个客户的交易金额总和。
将事务数据导入并转换为 RFM 数据
图二。RFM 数据集的前六行
现在我们有三个 RFM 分割的主要特征。这与任何其他数据分析情况类似,我们必须做的第一步是探索我们的数据集,在这种情况下,我们将使用 r 中的 hist() 函数使用直方图来检查每个特征分布。
图 3 RFM 特征数据直方图
我们的 RFM 数据集是如此右偏,这在 K-Means 聚类方法中将是一个灾难性的问题,因为该方法使用点之间的距离作为其计算之一来确定哪个聚类是最适合的点。 Log 变换可以用来处理这种倾斜的数据,由于我们在数据中有 0 (零值),我们将使用 log(n + 1)来变换我们的数据,而不是普通的 Log 变换。
对数变换和直方图
图 4。RFM 要素数据的直方图-对数标度
对数变换为 K-Means 方法提供了更好的数据,通过去除 RFM 数据集中的大量倾斜数据,为我们的数据计算和找到最佳聚类。
k 均值聚类
根据定义,K-Means 聚类方法是一种无监督学习,用于根据相似性将未标记的数据定义为组。
在 R 中,K-Means 聚类可以使用 kmeans() 函数快速完成。但是,在创建 K-Means 模型之前,我们必须找到聚类的数量。有很多方法可以找到要分配的最佳组数,其中一种是通过使用我们的商业感觉并直接分配数量,或者我们也可以使用数学感觉来计算每个点之间的相似性。
在本例中,我们将使用组内平方和来衡量每个组内观察值的可变性。我们将在 1 到 10 的范围内迭代计算每个聚类的类内平方和,并选择具有最低值且值没有进一步显著变化的组作为其下一个聚类,或者我们通常称之为 肘方法 。
R 中的肘法
图 5 数据集肘方法可视化(N = 4)
使用肘方法,我们将分配四个组作为我们的组数。使用 R 中的 kmeans() 函数,我们只需将聚类数放入 centers 参数中,并将聚类结果分配到我们的数据集中。
k 均值模型和细分汇总
图六。添加段后的数据集
现在,我们已经在细分功能中将每个客户 ID 分配到他们的组中。在下一步中,我们将通过根据段号对 RFM 特征的平均值进行分组来检查每个段的基本 RFM 轮廓。
图七。每个细分市场的 RFM 汇总
因此,我们有四组,让我们讨论每组的细节:
- **Segment-1(白银):**交易频率和消费金额位居第二的中产阶级客户。
- Segment-2 (Gold): 消费金额最大、交易次数最多的最有价值客户
- **细分市场-3(青铜级):**交易频率低、消费金额低的普通客户。但是,这个细分市场拥有最多的客户。
- **细分-4(不活跃):**不活跃/不太活跃的客户,最近的交易发生在一个多月前。该细分市场的客户数量、交易频率和交易金额最低。
现在,我们有四组顾客,每组都有详细的 RFM 行为。通常,这些信息可用于安排针对具有相似行为的客户的营销策略。 新近性、频率、 和 货币价值 细分很简单,但对于更好地了解您的客户以及制定高效和最佳的营销策略非常有用。
更丰富的缺失值
探索更强大、更灵活、更安全的数据框架
(图片由作者提供)
我的工作职责之一是维护调查数据的收集。起初这是一个简单的项目。通过一个简短的脚本,我可以将第一波数据编译成一个组织良好的数据框架,以几种不同的方式对其进行总结,然后发送一份报告。但是,一名参与者没有回应就离开了研究。另外几个参与者答错了一个问题。后来,在已经收集了几十个回答之后,我们在调查中添加了一个新问题。随着每一个新问题的出现,数据变得越来越难以维护。
每次数据丢失时,不管原因和后果如何,它都会被替换为相同的值NA
。这种过度简化导致了各种各样的问题。丢失的值看起来一样,所以更容易预测我可能在数据集中遇到什么值。但是它们以不同的方式影响计算,我发现很难验证操作是否安全地处理它们。我寻找方法来表现NA
背后的真实故事,但是我找到的解决方法冗长而复杂。NA
的简单性让我的代码变得更加复杂。
改进NA
最有用的方法是将它分成两个值:一个适用的缺失值和一个不适用的值。考虑一个新的调查问题的例子,它是在收集了一半的回答后添加的。没有回答可能有两个原因:要么有人跳过了这个问题,要么根本没人问过他们。第一种是适用的;第二种不是。如果您正在取平均值,您可以安全地删除不适用的值。但是忽略适用的缺失值是不安全的,因为了解它们的真实值(或估算它们)会改变您的结果。
不幸的是,大多数编程语言,包括 R 和 python,都很难表示这些信息。在 R 中,NA
被视为未知但适用的值。如果你试图用什么东西把它加上,就会导致另一个NA
。但是没有办法表示另一种不同的缺失值。由于您无法区分不同类型的NA
,您必须自己检测并处理它们。
在实践中,人们使用许多不同的方法来解决这个问题。一种选择是使用插补方法处理所有适用的缺失值,然后大胆使用大多数算术和统计函数中可用的na.rm = TRUE
选项。这将所有的NA
视为不适用,允许您在不删除缺失值的情况下进行求和或求平均值。但是盲目地删除丢失的值可能是不安全的。在NA
可能适用的情况下,我们几乎总是希望总和缺失,因为这有助于我们解释结果。缺少结果意味着还有一个缺少的值需要处理。一个真实的值保证我们完成了。
为了避免na.rm = TRUE
,您可以创建指示记录是否适用的变量。这看起来更安全,但是会变得冗长。你开始积累像sum(variable[isApplicable])
这样的表达式,而不是简单的sum(variable)
,数据变得越复杂,就越难记住如何写isApplicable
。你将需要多个指标变量,每一个都代表你想确定某件事是否适用的一种方式。而且数据结构也不能告诉你哪个指标变量对应哪个数据变量,你必须自己去跟踪它们。这可能会导致一系列完全不同的错误。
第三个也是最好的策略是将数据分割成更小的data.frame
,这种方法可以消除任何有问题的缺失值。为此,您将具有相同缺失值的记录分组,这样它们根本不需要缺失列。目标是删除所有不适用的值,这样每个NA
都可以被明确地视为适用的,前面的解决方法都没有必要。缺点是一些数据集需要大量的表,跨不同的表工作比在一个表内工作更困难。尽管这种方法比其他两种方法干净得多,但它仍然增加了复杂性,并增加了工作量。
关系数据库理论的启示
1986 年,E.F. Codd 写了一篇名为“关系数据库中缺失信息(适用和不适用)”的论文几年前,Codd 开发了关系数据库的理论,这是一个非常流行的模型,它和矩阵一起启发了数据框架的设计。(事实上,Hadley Wickham 著名的“整齐”数据概念是明确基于 Codd 的第三范式)。在 1986 年的论文中,Codd 探讨了缺失数据,并回答了在关系数据库中如何处理缺失数据的问题。当时最流行的方法是选择值,比如-99,来表示不同类型的缺失。这给用户带来了正确解析值以操作数据的负担。这是一种有缺陷且不安全的方法。
Codd 提出了一个 A 标志和 I 标志系统,其中 A 适用于缺失,I 不适用。他的论文描述了数据库如何处理,而不仅仅是表示两种缺失的信息,这样就不再需要特殊的值或额外的变量。在后来的一篇论文中,Gessert 讨论了它如何优于删除所有不适用的值的拆分表的解决方案,这给程序员和用户带来了许多不必要的工作。因为数据库可以理解丢失的值,所以它可以适当地处理它们,从而避免用户采取变通办法。
在他的论文中,Codd 概述了在计算中组合时如何处理值、缺失值和不适用值的建议。他说 I 标记应该被认为比 A 标记更强,A 标记应该比值更强,并且组合不同类型的运算应该返回更强的值。比如 A + 2 = A:和是未知的,因为 A 的值是未知的。类似地,A + I = I,这是合适的,因为 A + I 的和是无意义的;它不能适用于任何事情。同样的规则适用于所有算术运算,以及其他运算,如连接。
当运算是逻辑运算时,例如相等或比较,规则会更复杂。Codd 给出了一个简单的例子:像“出生日期> 1–1–66”这样的语句的值是多少?生日有了就是真的假的,其他的就不得而知了。所以,Codd 提出了一个三值逻辑,包括真、假、可能。
三值逻辑今天被广泛使用。在 R 中,MAYBE 表示为逻辑“NA”。逻辑运算比只有真和假更复杂,因为也许不能解释为一个具体的逻辑值。相反,也许是一个暂时的占位符,反映了我们目前对其真实价值的不确定性。例如,在 R 中,NA | TRUE
的计算结果为TRUE
,因为无论左侧发生什么情况,它都为真。然而,NA | FALSE
就是NA
,因为不学习缺失的信息,我们无法确定真实的价值。AND 运算的逻辑是相似的。NA & TRUE
是NA
,因为我们分不清它是什么,而NA & FALSE
明明是FALSE
。否定是最简单的运算:!FALSE
是TRUE
,!NA
是NA
。三值逻辑起初可能是违反直觉的,但所有规则都源于NA
的中心原则:它不是一个值,而是一种不确定的状态。
虽然三值逻辑是处理缺失数据的最简单方法,但 Codd 很快意识到这是不够的。在第二年的一篇后续文章中,他提出了一个四值逻辑,就像他的 A 分和 I 分一样,区分了适用的也许和不适用的也许。有趣的是,Codd 写道,他不认为实现这种逻辑值得付出努力,但指出它比三值逻辑更精确。他期望它以后会被集成(事实并非如此)。
四值逻辑扩展三值逻辑,就像 A 标记和 I 标记扩展缺失值一样。就像 I-marks,I-MAYBE 比 A-MAYBE 强,所以 A-MAYBE & I-MAYBE 就是我-MAYBE。在 AND 运算的情况下,最强的值是 false,因为无论另一端的值是什么,结果肯定是 FALSE。类似地,带有 TRUE 的 OR 将始终为 TRUE。最复杂的表达是 I-MAYBE | A-MAYBE,也就是 A-MAYBE。这是因为-MAYBE 是一个逻辑值的占位符,如果该值为真,表达式总体上也将是有意义的——它将为真。表示一个潜在的真实但未知的值的最好方法是一个也许。
Codd 对四值逻辑喜忧参半,认为它可能太复杂而不值得。他认为关系数据库的用户更喜欢简单的系统,而不是复杂的系统,因为复杂的系统需要太长的学习时间。但是,尽管三值逻辑比四值逻辑简单,但它的表达能力却远不如四值逻辑。ge sert后来为四值逻辑辩护,给出了一个欠下费用的简单例子。关键是要知道费用是因为还不知道而缺失,还是因为不适用而缺失。Gessert 说,将数据库限制为三值逻辑会阻止用户充分利用这一区别。他建议添加能够处理新的缺失值的新操作符,并指出这些操作符对于用户来说很容易学习,这样他们就会完全理解新的逻辑。
A-marks、I-marks 和四值逻辑都在简单和强大之间呈现相同的选择。这些特性无疑增加了数据和管理数据的系统的复杂性,但是它们也增加了表现力。如果我们能区分数据中适用的和不适用的信息,我们就能更有效地操作数据,更安全地进行计算。当适用的缺失值可能掩盖错误或使我们的结果有偏差时,这种区别就至关重要。
数据框架的含义
Codd 和 Gessert 探索的理论很重要,因为数据框架与关系数据库具有相同的语义。在 R 的 dplyr 包中,许多函数是以它们的 SQL 等价物命名的:select()
、*_join()
、coalesce()
,还有更多函数的行为与它们在 SQL 中的行为完全一样。在 R 中,NA
相当于 SQL NULL
。和 SQL 一样,R 不实现任何类似 Codd 的 A 标记和 I 标记的东西。仅限于三值逻辑,其中 maybe 值表示为NA
( NA_logical_
)。
如果这些数据结构能够区分适用的和不适用的缺失值,计算将变得更加简单。我们将放弃所有不适用的值,而不是使用当前的选项之一——依赖于na.rm = TRUE
,或者选择记录的子集,或者拆分表。例如,如果我们想要添加一个包含美元值的变量,我们可以安全地丢弃任何不适用的条目。但是,如果有一个适用的缺失值,我们将传播这种不确定性,我们的结果将是“适用的缺失”这比任意丢弃所有缺失的值要安全得多,并且不需要我们编写额外的代码来选择适用的记录。它比只有一个NA
更安全、更高效。
A 标记和 I 标记的系统也使得数据的结构更加灵活。例如,从同一组个体的多次观察中收集数据是很常见的。你可能有一些你在每次观察中收集的变量,还有一些描述个体的变量。问题是,一个人的变量只有在你从他们那里收集到至少一个观察结果时才会显示出来。如果没有观察到,该个人将被删除。I 标志使这变得更容易。我们为每个个体添加至少一行,并包含描述变量;但是每当个人没有数据时,我们将所有数据字段标记为不适用。理论上,同样的方法可以用来表示任何形状的数据,或者组合任何数量的表,而不会丢失信息。
Codd 提出的这个系统已经很强大了,但是还可以进一步扩展。我们可以有额外的标记来记录在某些操作或其他条件下的适用性。我们可以将标记扩展到已知的值,这样已知的值也可以由于不适用而从某些计算中删除,并且我们可以将它们用作分组数据的方法。标记可以通过多种方式进行扩展,将简单的数据结构与混乱的现实环境相匹配。
在 R 中实现一个丰富的缺失值系统
R 中最近的发展使得实际实现这些想法成为可能,因此有必要简要地探讨一下这是如何工作的。历史上,我们一直局限于原子的,基本的 R 向量。原子向量中的每个值都是相同的类型。在 double vector 中,每个值都必须是 double 或NA_real_
。但是 vctrs 包提供了一种方法来实现行为类似向量的对象。它的工作方式是为所有的 base R 函数提供替换,包括构造函数、造型、用[
和[[
设置子集、算术和其他计算,以及用format
进行可视化输出。因为对象比原子向量更灵活,它们可以建模适用和不适用的类型。
一种可能的提议是使用记录结构来表示 A 标记和 I 标记,该记录结构具有一个用于数据的字段和一个用于标记的字段。缺失值可以在数据字段中表示为NA
,在标记字段中表示为A
或I
。通过在新类型的向量上实现基 R 函数,我们可以实现我们想要的行为。
一旦我们实现了数据结构,我们就可以为它编写更好的函数。首先,我们可以默认丢弃不适用的遗漏。这尤其与sum()
、mean()
、quantile()
、%in%
、Reduce()
(或purrr::reduce()
)等功能相关。其次,我们可以实现二元操作符,使它们符合 Codd 的算术规则。特别是表达式A + A
应该是A
,I + I
应该是I
,A + I
应该是I
。最后,我们可以实现四值逻辑,扩展 base R 的三值逻辑来考虑适用和不适用的结果。这将导致 A 和 I 标记系统的完整实现,并且是我计划探索的项目。
简单的代价
因为数据集是复杂的,所以拥有有用的数据表示是非常有价值的。数据集的理论计划可能会很快因现实世界的问题而偏离轨道,如不完整、损坏或丢失的数据。尤其是丢失的数据变得难以解释,并且执行计算变得更加困难。这在操作简单的结构和复杂但能以更细微差别表示数据的结构之间产生了矛盾。
毫无疑问,学习如何处理包含适用和不适用缺失值的数据集需要付出额外的努力。NA
本身就足够令人困惑了(首先,实际上有五种不同的NA
)。两个缺失值的存在改变了所有常规操作的工作方式,虽然它们的行为受一组核心原则的指导,但人们需要时间来学习如何有效地使用它们而不出错。当用户不完全理解复杂的工具时,它们可能是危险的。
但是额外的复杂性通常是合理的。当我们使用只有一个缺失值的数据结构时,我们被迫编写代码来选择我们想要操作的记录,或者将我们的数据拆分到不同的表中。因为我们的数据过于简单,我们被迫使我们的代码更加复杂。而且因为我们的代码比较复杂,会容易出错,很难维护。相比之下,更强大的缺失值表示可以提供更简单、更可靠的方法来操作数据。
自从第一个关系数据库出现以来,用户和开发人员一直选择简单的设计,以便于学习和使用。但是有时候一个听起来很复杂的想法和现实世界的混乱是绝配。
笔记
一个 R 基函数有一个有趣的行为:%in%
。默认情况下,它实际上会丢弃丢失的值。我们期望4 %in% 1:3
是FALSE
,但是我们也期望4 %in% c(1:3, NA)
是NA
,因为我们不能排除最后一个值是4
。这种实现反映了大多数人用%in%
和用sum()
思考缺失值的方式不同,但这显然与其他逻辑运算不一致。通过区分适用的和不适用的缺失值,我们可以用一种既正确又直观的方式重新实现它。
NA
是一个逻辑值,放在任何非逻辑向量中都是非法的。相反,R 为整数向量定义了NA_integer_
,为双精度数定义了NA_real_
,为复数定义了NA_complex_
,为字符串定义了NA_character_
。通过c()
的工作方式和 R 打印出向量的方式,这些对用户是隐藏的。
Rick 和 Morty 使用变形金刚和 Streamlit 通过 GPT2 生成故事
贝尼尼奥·霍尤拉在 Unsplash 上拍摄的照片。
这篇文章将向你展示如何使用 Hugging Face 的 Transformers 库在 Rick 和 Morty 的抄本上微调一个预训练的 GPT2 模型,构建一个演示应用程序,并使用 Streamlit 共享部署它。
介绍
随着机器学习(ML)和自然语言处理(NLP)的快速发展,新算法能够生成看起来越来越像人类制作的文本。其中一种算法 GPT2 已经在许多开源应用程序中使用。GPT2 在 WebText 上接受训练,WebText 包含来自 Reddit 的 4500 万个出站链接(即评论引用的网站)。排名前 10 的出站域名包括谷歌、存档、 Blogspot 、 Github 、 NYTimes 、 WordPress 、华盛顿邮报、 Wikia 、 BBC 和卫报。预训练 GPT2 模型可以在特定数据集上微调,例如,以“获取”数据集的样式或学习对文档进行分类。这是通过迁移学习完成的,迁移学习可以定义为“从源设置中提取知识并将其应用于不同目标 setting"⁴.的一种方式有关 GPT2 及其架构的详细解释,请参见原版 paper⁵、OpenAI 的博客 post⁶或杰伊·阿拉姆马的插图 guide⁷.
资料组
用于微调 GPT2 的数据集由 Rick 和 Morty 抄本的前 3 季组成。我过滤掉了所有不是由里克、莫蒂、萨默、贝丝或杰瑞产生的对话。数据被下载并以原始文本格式存储。每行代表一个说话者和他们的话语或一个动作/场景描述。数据集被分为训练和测试数据,分别包含 6905 和 1454 行。原始文件可以在这里找到。训练数据用于微调模型,而测试数据用于评估。
训练模型
抱抱脸的变形金刚库提供了一个简单脚本来微调一个定制的 GPT2 模型。你可以使用这款谷歌 Colab 笔记本来微调你自己的模型。一旦您的模型完成了训练,确保您下载了包含所有相关模型文件的已训练模型输出文件夹(这对于以后加载模型是必不可少的)。你可以在拥抱脸的模型 Hub⁸上传你的定制模型,让公众可以访问它。当在测试数据上评估时,该模型获得了大约 17 的困惑分数。
构建应用程序
首先,让我们为 Python 3.7 创建一个名为Story_Generator
的新项目文件夹和一个虚拟环境:
mkdir Story_Generator
cd Story_Generator
python3.7 -m venv venv
source venv/bin/activate
接下来,我们要安装项目的所有依赖项:
pip install streamlit-nightly==0.69.3.dev20201025
pip install torch==1.6.0+cpu torchvision==0.7.0+cpu -f [https://download.pytorch.org/whl/torch_stable.html](https://download.pytorch.org/whl/torch_stable.html)
pip install git+git://github.com/huggingface/transformers@59b5953d89544a66d73
我们的整个应用程序将驻留在app.py
中。让我们创建它并导入新安装的依赖项:
import urllib
import streamlit as st
import torch
from transformers import pipeline
在我们做任何处理之前,我们希望我们的模型加载。通过使用@st.cache
装饰器,我们可以执行一次load_model()
函数,并将结果存储在本地缓存中。这将提高我们的应用程序性能。然后,我们可以使用pipeline()
功能简单地加载一个模型来生成文本(将模型路径替换为您的定制模型,或者从模型中心使用 my 预训练的模型):
[@st](http://twitter.com/st).cache(allow_output_mutation=True, suppress_st_warning=True)
def load_model():
return pipeline("text-generation", model="e-tony/gpt2-rnm")model = load_model()
我们可以使用 Streamlit 的text_area()
函数来制作一个简单的文本框。我们还可以提供高度和允许的最大字符数(因为大文本需要更长的时间来生成):
textbox = st.text_area('Start your story:', '', height=200, max_chars=1000)
现在我们已经有了第一行代码,我们可以通过运行应用程序来查看它是什么样子的(我们也可以通过刷新页面来查看实时更改):
streamlit run app.py
接下来,我们可以添加一个 slider 小部件,允许用户决定模型应该生成多少个字符:
slider = st.slider('Max story length (in characters)', 50, 200)
我们现在准备生成文本!让我们创建一个执行文本生成的按钮:
button = st.button('Generate')
我们希望我们的应用程序监听“按钮按压”动作。这可以通过一个简单的条件语句来完成。然后我们可以生成文本并将其输出到屏幕上:
if button:
output_text = model(textbox, max_length=slider)[0]['generated_text']
for i, line in enumerate(output_text.split("\n")):
if ":" in line:
speaker, speech = line.split(':')
st.markdown(f'__{speaker}__: {speech}')
else:
st.markdown(line)
让我们在文本框中输入提示并生成一个故事:
Rick: Come on, flip the pickle, Morty. You're not gonna regret it. The payoff is huge.
输出:
Rick: Come on, flip the pickle, Morty. You're not gonna regret it. The payoff is huge. You don't have to be bad, Morty.
(Rick breaks up)
[Trans. Ext. Mortys home]
太好了!模型正在输出新的文本,看起来不错。我们可以通过调整解码方法的参数来提高输出质量。参见拥抱脸在 decoding⁹的帖子,了解不同方法的详细概述。让我们替换我们的model()
函数,并应用更多的参数:
output_text = model(textbox, do_sample=True, max_length=slider, top_k=50, top_p=0.95, num_returned_sequences=1)[0]['generated_text']
简而言之,do_sample
随机挑选下一个单词,top_k
过滤最有可能的 k 下一个单词,top_p
允许动态增加和减少可能的下一个单词的数量,num_returned_sequences
输出多个独立样本(在我们的例子中只有 1 个)用于进一步过滤或评估。您可以使用这些值来获得不同类型的输出。
让我们使用这种解码方法生成另一个输出。
输出:
Rick: Come on, flip the pickle, Morty. You're not gonna regret it. The payoff is huge.
Morty: Ew, no, Rick! Where are you?
Rick: Morty, just do it! [laughing] Just flip the pickle!
Morty: I'm a Morty, okay?
Rick: Come on, Morty. Don't be ashamed to be a Morty. Just flip the pickle.
我们的输出看起来更好!这种模式仍然会产生不合逻辑和无意义的文本,但新的模式和解码方法可能会解决这个问题。
不幸的是,我们的模型有时会产生伤害性的、粗俗的、暴力的或歧视性的语言,因为它是根据来自互联网的数据训练的。我们可以通过简单地从 451 个单词的列表中检查粗俗的单词来应用不良单词过滤器来审查有害的语言。我敦促读者考虑使用进一步的过滤器,比如过滤仇恨言论。该滤波器可以按如下方式实现:
def load_bad_words() -> list:
res_list = []file = urllib.request.urlopen("[https://raw.githubusercontent.com/RobertJGabriel/Google-profanity-words/master/list.txt](https://raw.githubusercontent.com/RobertJGabriel/Google-profanity-words/master/list.txt)")
for line in file:
dline = line.decode("utf-8")
res_list.append(dline.split("\n")[0])
return res_listBAD_WORDS = load_bad_words()
def filter_bad_words(text):
explicit = False
res_text = text.lower()
for word in BAD_WORDS:
if word in res_text:
res_text = res_text.replace(word, word[0]+"*"*len(word[1:]))
explicit = Trueif not explicit:
return textoutput_text = ""
for oword,rword in zip(text.split(" "), res_text.split(" ")):
if oword.lower() == rword:
output_text += oword+" "
else:
output_text += rword+" "return output_textoutput_text = filter_bad_words(model(textbox, do_sample=True, max_length=slider, top_k=50, top_p=0.95, num_returned_sequences=1)[0]['generated_text'])
我们最终的app.py
文件现在看起来像这样:
import urllib
import streamlit as st
import torch
from transformers import pipelinedef load_bad_words() -> list:
res_list = []file = urllib.request.urlopen("[https://raw.githubusercontent.com/RobertJGabriel/Google-profanity-words/master/list.txt](https://raw.githubusercontent.com/RobertJGabriel/Google-profanity-words/master/list.txt)")
for line in file:
dline = line.decode("utf-8")
res_list.append(dline.split("\n")[0])
return res_listBAD_WORDS = load_bad_words()
[@st](http://twitter.com/st).cache(allow_output_mutation=True, suppress_st_warning=True)
def load_model():
return pipeline("text-generation", model="e-tony/gpt2-rnm")def filter_bad_words(text):
explicit = False
res_text = text.lower()
for word in BAD_WORDS:
if word in res_text:
res_text = res_text.replace(word, word[0]+"*"*len(word[1:]))
explicit = Trueif not explicit:
return textoutput_text = ""
for oword,rword in zip(text.split(" "), res_text.split(" ")):
if oword.lower() == rword:
output_text += oword+" "
else:
output_text += rword+" "return output_textmodel = load_model()
textbox = st.text_area('Start your story:', '', height=200, max_chars=1000)
slider = slider = st.slider('Max text length (in characters)', 50, 1000)
button = st.button('Generate')if button:
output_text = filter_bad_words(model(textbox, do_sample=True, max_length=slider, top_k=50, top_p=0.95, num_returned_sequences=1)[0]['generated_text'])
for i, line in enumerate(output_text.split("\n")):
if ":" in line:
speaker, speech = line.split(':')
st.markdown(f'__{speaker}__: {speech}')
else:
st.markdown(line)
您还可以在 Github 资源库中查看我的演示的代码,因为它包含了修改应用程序功能和外观的有用代码。
它现在已经准备好上线了!
部署应用程序
可以使用 Streamlit 共享⁰.部署该应用程序您只需要有一个公共的 Github 存储库,存储库中有一个requirements.txt
和一个app.py
文件。您的requirements.txt
文件应该是这样的:
-f [https://download.pytorch.org/whl/torch_stable.html](https://download.pytorch.org/whl/torch_stable.html)
streamlit-nightly==0.69.3.dev20201025
torch==1.6.0+cpu
torchvision==0.7.0+cpu
transformers @ git+git://github.com/huggingface/transformers@59b5953d89544a66d73
在 Streamlit Sharing 网站上,您可以简单地链接您的存储库,您的模型将很快上线!
道德考量
本文中介绍的应用程序仅用于娱乐目的!应该仔细考虑在其他场景中应用 GPT2 模型。虽然从原始训练数据中删除了某些域,但 GPT2 模型是在来自互联网的大量未经过滤的内容上进行预训练的,这些内容包含有偏见和歧视性的语言。OpenAI 的型号卡指出了这些注意事项:
以下是我们认为可能的一些次要使用案例:
-写作辅助:语法辅助、自动补全(针对普通散文或代码)
-创造性写作和艺术:探索创造性虚构文本的生成;帮助诗歌和其他文学艺术的创作。
-娱乐:创造游戏、聊天机器人和娱乐一代。
范围外的使用案例:
因为像 GPT-2 这样的大规模语言模型不能区分事实和虚构,所以我们不支持要求生成的文本是真实的用例。此外,像 GPT-2 这样的语言模型反映了他们接受培训的系统固有的偏见,所以我们不建议将它们部署到与人类交互的系统中,除非部署者首先进行与预期用例相关的偏见研究。我们发现 774M 和 1.5B 之间在性别、种族和宗教偏见调查方面没有统计学上的显著差异,这意味着所有版本的 GPT-2 都应该以类似的谨慎程度对待对人类属性偏见敏感的用例。
下面的例子展示了模型如何产生有偏差的预测(另一个例子可以在这里找到):
>>> from transformers import pipeline, set_seed
>>> generator = pipeline('text-generation', model='gpt2')
>>> set_seed(42)
>>> generator("The man worked as a", max_length=10, num_return_sequences=5)[{'generated_text': 'The man worked as a waiter at a Japanese restaurant'},
{'generated_text': 'The man worked as a bouncer and a boun'},
{'generated_text': 'The man worked as a lawyer at the local firm'},
{'generated_text': 'The man worked as a waiter in a cafe near'},
{'generated_text': 'The man worked as a chef in a strip mall'}]>>> set_seed(42)
>>> generator("The woman worked as a", max_length=10, num_return_sequences=5)[{'generated_text': 'The woman worked as a waitress at a Japanese restaurant'},
{'generated_text': 'The woman worked as a waitress at a local restaurant'},
{'generated_text': 'The woman worked as a waitress at the local supermarket'},
{'generated_text': 'The woman worked as a nurse in a health center'},
{'generated_text': 'The woman worked as a maid in Daphne'}]
我敦促读者仔细考虑这些模型在真实场景中的应用和使用。有许多资源(如 EML、艾诺)可用于了解道德规范。
结论
恭喜你!您的应用程序现已上线!
通过使用开源框架,我们能够快速微调 GPT2 模型,原型化有趣的应用程序,并部署它。通过使用更先进的预训练模型、解码方法,甚至结构化语言预测,可以进一步改进生成的故事。
参考
[2]: 排名前 30 的 Gpt2 开源项目
[4]: 网络文本中出现的前 1000 个域名
[5]: A .、Jeffrey Wu、R. Child、David Luan、Dario Amodei 和 Ilya Sutskever 2019。语言模型是无人监督的多任务学习者。
[7]: 图解 GPT-2(可视化变压器语言模型)
[10]: 部署一个 app
搭车还是开车:比较拼车和汽车所有权的金融模型
拼车真的能取代汽车吗?数据显示,如果你的驾驶里程不到 10,000 英里,也许可以。
随着加州 AB5 的实施和随后前期定价的下降,乘车共享市场最近经历了一些变化。Lyft 和优步一直在不断平衡其商业模式的动态性,同时应对日益增加的监管审查和对乘客安全的担忧。然而,两家公司都继续表示,拼车总有一天会完全取代汽车所有权。
来源: CB Insights
大约 6 个月前,我从肯塔基州的路易斯维尔搬到了洛杉矶。我在两个不同的办公室工作,一个在洛杉矶西部,一个在市中心。我不开车,一直依赖公共交通、自行车和拼车应用。所以,我的问题是:优步和 Lyft 是对的吗?拼车能取代汽车所有权吗,尤其是在世界上最臭名昭著的驾车城市之一?
优步/ Lyft 定价模型很难预测,因为市场算法消耗了大量的输入数据。内置了无数的变量,这些变量不断地接收实时事件,例如驾驶员位置、乘车次数请求以及一天中的时间等
在本文中,我首先考察了四种不同车型每年的汽车拥有成本,包括直接成本和间接成本。然后,我结合优步和 Lyft 过去几个月的数据,将拼车作为一个广阔的市场进行研究,建立三个回归模型,以获得拼车的大致成本结构,最终回答一个非常重要的问题:
我们是骑车还是开车?
每年拥有汽车的成本
为了进行这项分析,我从 2019 年 AAA 驾驶成本报告中提取了 4 种不同类型汽车的数据:(1)中型轿车,(2)电动轿车,(3)混合动力轿车,以及(4)中型 SUV。这些似乎是洛杉矶最实用的车,也是最常上路的车。如果你对自己的计算感兴趣,AAA 有一些基线指标可以提供。
直接费用
来源: AAA
这些车的年费用都差不多,从 5700 美元到 6800 美元不等。根据 AAA 的数据,2019 年拥有一辆中型轿车的平均成本为 8643 美元(假设每年行驶 15k 英里)。这包括保险、执照和注册、税收、折旧和融资费用。你开得越多,由于折旧、燃料成本等的增加,汽车就越贵。
我在分析中还包括了加州的汽车成本。在这里拥有一辆汽车更贵,因为生活费用过高。例如,一辆中型轿车平均每英里多 0.3 美元。
然而,一辆汽车伴随的成本不仅仅是直接成本。这就是分析变得有点棘手的地方,因为其中一些变量可能是主观的,我将讨论这一点。还有额外的“间接”成本,包括罚单、停车费和机会成本。
间接费用
- 交通罚单(146.34 美元+增加的保险费)
2018 年,超过 60 亿美元的交通罚单被开给了 4100 万人。平均每人的交通罚单成本是 146.34 美元。这还不包括你拿到机票后增加的保险费,如下所述,这是一笔可观的费用。加州的一张票可以提高 1/3 的保险费,第二张票可以翻倍。如果一名司机每年收到一张罚单,那将导致 150 美元的罚单费用+850 美元的保费增长——仅仅一张罚单,汽车成本每年就会增加 1000 美元。我假设在汽车的使用寿命期间,至少有一张罚单。
来源:纽约超速罚款
- 停车费(4100 美元)
平均来说,美国人每年在停车场的花费超过 1000 美元。纽约的消费额最高,为 2243 美元,西雅图位居第五,为 1205 美元。这甚至还没有考虑到寻找停车位的机会成本——纽约人在 2018 年花了 107 个小时寻找停车位。那就是每年 4.45 天,光是找地方停车。
来源:租车
根据 INRIX 的数据,停车是车主最大的一项支出。纽约是最贵的城市,因为纽约人往往更频繁地支付停车费,每次停车都要付更多的钱。洛杉矶位居第二,搜索和超额支付总计 2139 美元。
公寓和办公楼通常收取月费,根据位置不同,月费在 50-150 美元之间。我将计算停车和搜索时间(带缓冲区)的年总成本约为 4100 美元,即搜索时间的总成本和停车的总成本。
- 机会成本(1648 美元)
然后,有驾驶花费的总机会成本。我在乘车分享的后面打了一些这篇文章——当你不在方向盘后面时,更容易有效率。根据美国人口普查局的数据,2018 年平均通勤时间增加到 27.1 分钟。也就是每天 54.2 分钟,一周 4.51 小时,一个月 19.42 小时,一年 233.06 小时。
根据劳工统计局的数据,2019 年的平均工资为 28.29 美元。将平均工资乘以平均通勤时间得出的结果是生产力和工作时间损失 6593 美元。即使我们只有 25%的时间是在开车而不是做其他事情上,这仍然是每年 1648 美元的损失。
时间的估值是极其主观的,这里有很大的修改空间。正如上面的计算所示,有些人不重视他们的时间,而有些人比平均工资更重视他们的时间。都是相对的。
- 总间接成本= 6748 美元
因此,无论一辆车的成本是多少,加上间接成本,每年的额外成本就是 6748 美元。如果你驾驶的是香草冰淇淋的家庭轿车,那么你每年拥有汽车的成本估计为 15391 美元。
拼车市场的动态定价
很难找到 ride 股票背后的定价结构。很多定价源于位置、时间和交通。这些公司似乎也经常修改他们的定价模式,已经有多篇文章发表在拼车定价市场上频繁发生的变化。随着加州 AB5 的变化,现在这一切都不确定了。根据优步的说法:
来源:优步
根据拼车司机的细分(这可能有点简单,但出于说明目的很重要),估计每英里的成本为 0.80 美元,每分钟的成本为 0.20 美元至 0.28 美元,具体取决于优步的类型。预订费因城市而异,但我估计预订费为 2.30 美元。
来源:顺风车共享司机
为了简单起见,我们可以假设等式为:
***Assumed _ Fare =***Base _ Fare+(英里驱动 x 每英里成本)+(分钟驱动 x 每分钟成本)
***cost _ Uber =***2.30+(0.80 *英里 _ 驱动)+ (0.24 *分钟 _ 驱动)
美国拼车的成本
平均通勤时间为 27.1 分钟。根据 FHWA 的数据,美国人平均每年驾车旅行超过 13476 英里。根据美国汽车协会 2016 年的美国驾驶调查,美国人平均每天出行 2.13 次,每年共计 777.45 次。
假设乘客刚刚使用了 rideshares,预订费用的总成本将为 1788 美元,乘以每次乘坐的预订费用 2.30 美元,每年有 777 次乘坐。每英里的年费用为 0.8 美元* 13,476 英里或 10,781 美元。每年每分钟的总成本为 5899 美元,等于每年 777 次旅行,乘以平均通勤时间 27.1,成本为 0.24 美元。
这导致骑优步或其他拼车平台的总年成本为 17,625 美元。我想在基本模型之外验证这一点,所以我收集了自己的数据。
凯拉的拼车数据
我六个月前从肯塔基州搬到了洛杉矶。我把我心爱的斯巴鲁 Outback 交给了我的弟弟,并决定穿越洛杉矶——这是大多数洛杉矶人的罪过。
我在西洛杉矶工作,住得离办公室很近。我早上很早就去上班,一开始,我从家走到办公室。被人追了之后,我开始骑自行车。然而,在洛杉矶骑自行车是有风险的,没有多少回报。
来源:美国街头博客
我也开始在市中心的办公室工作,每周有三天在市中心和洛杉矶西部之间往返。我通常在下午三点左右离开西洛杉矶前往市中心,并在晚上晚些时候返回西部。所以,如果我选择在清晨乘车,我有三个不同的通勤时间,都有不同的价格压力和动力。值得注意的是,我的大部分交通都是在典型的高峰时间之外,因此下面的分析可能会因此而有所偏差。
来源:谷歌地图
从西洛杉矶到市中心大约有 12 英里的路程,我不能骑自行车。我曾经骑自行车到世博线,把自行车停在外面,但有人给我的轮胎放气,我的头在线路上被抚摸了不止一次(欢迎使用洛杉矶公共交通),所以在过去的几个月里,我一直避免使用所有的公共系统。
我几乎每天都乘坐优步或 Lyft,通常会打开这两个应用程序来比较两者之间的成本。
由于我的工作安排,我避免了高峰时段的大部分价格上涨,下图中用红色标出。如堆叠区域所示,我经常在傍晚和晚上骑车。我收到的平均价格可能会更低,因为我倾向于避免“激增定价”。
下图详细描述了我的拼车习惯。我更多的时候是与人合租,而不是独自乘车,主要是为了安全,也是为了省钱和保护环境(至少是一种尝试)。如果我需要快速到达某个地方,我会使用 UberX 或 Lyft,这是 Lyft 的非共享乘车。如果我漠不关心,我会用共享。合租通常便宜 5-7 美元。我通常后悔采取优步池,因为它可以添加多达四个额外的人,这可能是极其痛苦的。
我在优步旅行的平均时间比 Lyft 多 4.5 分钟,我的平均时间要低得多。这可能意味着我的优步司机效率更高,或者 Lyft 在长途旅行中更便宜,所以我更经常选择它。我 61%的乘车是从西区到市中心,更大比例的优步是带我去市中心以外的地方。21%的时间我使用优步去市中心,另外 40%的时间我使用 Lyft。
在过去的四个月里,我已经走了 580 英里。这使得我的估计年里程数为 1738,这是非常低的(老实说,有点悲伤)。如果我有自己的车,我想象这将增加至少 25%,因为我可以在周末自由旅行,逃离洛杉矶。
检查数据
这是我的三个主要乘车共享变量,费用,秒数和距离之间的相关图。这种分析的目的是预测拼车的费用。我将把我的数据外推至数千英里,这意味着我假设这种关系将保持不变。
为了说明外推的问题,考虑一下罗伯特·奇拉曾经说过的关于苹果公司估值的话:
“如果你对未来进行足够远的推断,为了保持这种增长,苹果将不得不向地球上的每个男人、女人、孩子、动物和岩石出售 iPhone。
模式一:用秒和距离预测车费
我在 R 中运行了一个基本的线性回归,以查看秒和距离在确定票价方面的预测能力,因为这是大多数拼车模型所基于的,包括前面提到的拼车司机模型,以及凯尔·希尔 2014 年的模型。
从回归中提取数据,然后模型变成:
这意味着每增加一英里和第二次旅行,票价将分别增加 0.204 美元和 0.003 美元。此模型的问题是距离和秒之间的相关性为 91%,从而产生多重共线性问题。有几种方法可以解决这个问题,包括创建一个工具变量来消除处理距离的时间部分。
模型 2:包括高峰时间的虚拟变量
我决定修改等式,加入一个虚拟变量来确定我们是否处于高峰时间。高峰时间(在洛杉矶)是早上 6 点到 9 点和下午 3 点到 7 点。窗外的任何时间都是非高峰时间。我有 40 次乘坐在高峰时间之外,18 次在高峰时间规格之内。
该模型现在变成了:
从回归中提取数据,这变成:
这意味着每增加一英里和第二次旅行,票价将分别增加 0.196 美元和 0.003 美元。如果你在高峰时间开车,你的价格会增加 1.015 美元。
模型 3:减少秒数,在距离和高峰时间之间产生交互项
通过在距离和高峰时间之间添加一个交互项,我假设距离对票价的影响在高峰时间和非高峰时间是不同的,这是有道理的。你可以在下午 5 点在加州行驶 1 英里,可能需要 30 美元,因为有几个用户需要这项服务,而在凌晨 4 点同样的乘车只需要 3 美元——根据供求规律,一天中的时间将影响你为拼车支付的费用。根据是否是高峰时间,费用会有所不同。这基本上是激增定价的代理。
我把秒从这个模型中去掉是因为距离和秒的相关度是 0.913,这是极高的,在模型 1 的分析中提到过。两者之间的 VIF 没有 10 那么高,但仍然相对较高。从模型中剔除秒数并没有显著降低 R 平方,我将在下面讨论。
这个模型就变成了
比较模型
(文字输出请不要嫌弃我)。
从上面的输出可以看出,尽管变量发生了变化,但模型之间的 R 平方并没有太大的变化。不幸的是,R 平方不是很高。增加更多的变量和数据将会改善这种情况。
模型 4:线性与稳健线性模型与分位数回归
我想让这个分析尽可能简洁明了,但是我也想确保我提到了这样一个事实,即我还可以使用其他几种回归方法。线性回归是最著名的方法,因此也是我在整个分析中使用的方法。稳健的线性模型简单地控制了异常值,这在我的数据集中不是一个大问题。
分位数回归模型不像线性模型那样取平均值,而是使用条件中值函数进行估计。这也可以控制异常值。深入探讨这个问题超出了本次分析的范围,尤其是因为样本量相对较小,但是我想把它作为一个警告包括进来。优步实际上在 2016 年写了一篇关于 quantreg 的文章,以解释他们与和交易的各种定价动态。
结论:如果你开车少于 10,000 英里,扔掉你的车
我在前两个模型的分析中保持秒不变,并在输出中包括了高峰时间。我把高峰时间包括在内,因为这将为日益拥堵的城市和普通人的通勤时间表提供最可靠的分析。对于美国的分析,我将间接成本设置为 3000 美元,以梳理出加州的生活成本。
我对每一个都进行了颜色编码,以显示哪一点更适合你驾驶。对于大多数车型,交叉点在 9000-12000 英里之间。如果你有一辆混合动力、电动或中型轿车,你会得到最大的回报。拼车公司只能在最高 9000 英里的价格上竞争。SUV 是最昂贵的车辆,其交叉点约为 12,000 英里。
如果你在加州拥有一辆车,那你就是在浪费钱。在大多数情况下,使用 rideshare 要便宜得多。我将间接成本设定为 6000 美元,以说明加州生活成本的提高。
有很多原因可以说明这个数据,包括我如何给汽车定价和我的个人拼车数据。然而,根据这项分析,与开车相比,拼车对于低里程用户来说是更好的选择。
珍惜时间有不同的方式,这可能会影响你对拼车和开车的评价。但是你有更多的自由驾驶汽车,不必担心其他乘客、司机或无法控制车辆。此外,这个数据没有考虑到加州 AB5 的变化,这可能会从根本上改变所有的模型,这是非常可悲的。
总的来说,驾驶体验相当主观。从数量的角度来看,有时搭车会更便宜。定性来说,这完全取决于你看重什么。
** 免责声明:这些都不是投资建议,我与任何拼车公司都没有关联
岭回归——两个概念的图解故事
回归很可能是人们学习的第一个机器学习算法。它是基本的、简单的,同时也是非常有用的工具,可以解决很多机器学习问题。本文是关于岭回归的,对 线性回归 进行了修改,使其更适合特征选择。整个故事分为四个同等重要的部分,如下所述:
- **线性回归:**说明线性回归中普通最小二乘法的基本思想。
- **特征选择:**阐述了什么是机器学习中的特征选择,以及它的重要性。
- **参数计算:**用图形表示的线性回归计算哪些参数。
- **岭回归:**最后一节,结合以上概念来解释岭回归。
为了理解这个概念,请仔细阅读所有四个部分。现在,让我们开始:
- 线性回归
假设给我们一个二维数据集,如下图所示,我们打算将一个线性模型放入其中。图表中的黑点显示了左侧表格中显示的数据点。蓝线是拟合到数据中的线性模型&红色箭头显示预测值和实际因变量值(Y)的差异。
在线性回归模型中,以 d12 + d22 + d32 + d42 + d5^2 最小化的方式将一条线拟合到数据中,即残差的平方(实际值和预测值之间的差异)最小化。在更一般的形式中,它可以表示如下:
这个量叫做残差平方和(RSS),这里 yi 代表因变量的预测值。用这种方法求线性模型的方法称为普通最小二乘法。拟合模型的形式如下:
上式中的 Bo 为截距, B1 为模型的斜率, X 和 Y 分别为自变量和因变量。
2。功能选择
在任何机器学习问题中,我们都有预测器,也称为特征或自变量,根据提供的数据,我们需要了解这些变量与响应变量(也称为因变量)的关系。简单来说,我们需要找出以下关系:
我们将 y 作为响应变量,将 p 作为预测变量(x1,x2,… xp),上面的等式代表了两者之间的实际函数关系。在机器学习中,我们需要尽可能准确地找到这种关系。对模型的研究带来了许多挑战,如数据不足或缺失、缺失预测因子、无关预测因子、预测因子之间的相关性、数据格式错误等。我们在机器学习中面临的所有挑战都可以通过不同的方法来缓解。我们将在这个主题中解决的挑战是“不相关的预测”。我将用一个例子来说明这个问题。
考虑了解降雨量与温度、湿度、地理位置和该地区人们的发色之间的关系。直觉表明,降雨的发生可能与前三个预测因素有关,但降雨与人的头发颜色之间似乎没有逻辑联系。给定数据集,如果我们试图拟合一个回归模型,该模型也会根据头发颜色数据进行自我调整,这是错误的。理想情况下,我们的模型训练方法应该消除不必要的预测,或者至少给它们较小的权重。类似地,如果预测因子之间存在相关性(如湿度与地理位置相关,沿海地区更潮湿等)。),模特也要学那个。消除或减少不必要预测因子权重的过程称为特征选择。这个概念在当前场景中很重要,因为岭回归直接处理它。
3。回归中的参数计算
虽然回归中的最小二乘法的过程已经讨论过了,但是现在是用图形来理解这个概念的时候了。考虑下面给出的数据集。降雨量与温度和湿度的系统由数据表示:
如果我们希望通过回归拟合上述数据中的模型,我们需要拟合类型为 Y = Bo + B1 X1 + B2 X2 的线性方程,或者更简单地说,我们需要计算 Bo 、 B1 和 B2 。这里 X1 是温度 X2 是湿度 Y 是降雨量。让我们暂时忘记波(截距),为 B1 和 B2 选择任意值,比如说B1= 1&B2= 2。这些并不是我们想要的值,而是为了理解一个概念而随机选择的。还有,我们把 Bo 的值取为零。现在,我们有了参数值,让我们预测降雨量值并计算 RSS(误差平方和)。下表显示了所需的计算:
由上表可见,对于 B1 = 1 和 B2 =2,RSS 值为 3743。在这里总结任何东西之前,让我们假设一个不同的回归参数值集。设 B1 = 3.407,B2 = 1,我们继续忽略 Bo 。如果我们再次进行预测计算&也计算 RSS,你会发现它会再次出来是 3743(几乎)。这里我想说的一点是,对于残差平方和为常数的回归参数,有不同的值。如果绘制这些点,将生成如下所示的图:
上图针对的是两个预测因子的系统,预测因子的数量越多,上图的尺寸就越大。我们最初假设 Bo 为零,但是对于 Bo 的任何值,曲线仍然相同,只是根据 Bo 的符号&大小向上或向下移动。
上述图称为回归的成本等值线图。每个轮廓或循环绘制在参数 B1 和 B2 之间,代表一个恒定的 RSS 值。在回归中,我们的目标是找出由中心点表示的值,该值既唯一又代表最小 RSS。
4。岭回归
岭回归是对最小二乘回归的改进,使其更适合特征选择。在岭回归中,我们不仅试图最小化残差平方和,还试图最小化等于回归参数平方和乘以调整参数的另一项。换句话说,在岭回归中,我们试图最小化以下数量:
上述表达式中的第一项是残差平方和,第二项是岭回归中特别添加的内容。因为这是岭回归中引入的一个特殊术语,所以让我们试着进一步理解它。对于有两个预测器的数据集,它将是 a (B1^ 2+ B2^ 2),其中 a 是调整参数。它也被称为惩罚项,因为它对回归的最小二乘法施加了约束。在寻求最小化它的过程中,它被限制到一个特定的值,由下面的等式描述:
仔细看上面的方程,是一个阴影圆的方程,半径的平方等于 s/a (约束),其中一部分如下图所示:
将上述图表与成本分布图结合起来,将得到如下所示的图表:
上图给出了岭回归的思想。这是最小二乘条件满足参数约束或惩罚条件的地方。代表约束的圆的半径直接取决于调谐参数( a )。调谐参数值越大,圆越小,惩罚越高。你可以借助上图直接想象一下。调谐参数的值越大,圆越小,两个图形的交点越靠近原点,因此回归参数的值越小。
结论:
在岭回归中,寻找对应于最小残差平方和的参数不是所寻求的。对参数施加约束以检查它们,因此不允许它们增长。这个条件确保不同的参数被赋予不同的权重,因此成为特征选择的重要工具。请注意,在岭回归中,任何预测值的参数都不会为零,但参数权重是变化的
这就是岭回归的全部内容。请发表您的评论/建议。关于这个话题的任何疑问,你可以通过 LinkedIn 联系我。
进一步阅读:
谢谢,
祝你玩得愉快😊
原载于 2020 年 4 月 17 日 https://www.wildregressor.com*。*
机器学习中的奇异值分解:岭回归和多重共线性
了解什么是多重共线性,它如何影响最小二乘法,以及经典岭回归如何有所帮助
本文从奇异值分解 (SVD)的角度讨论了什么是多重共线性,它如何影响最小二乘法,以及岭回归如何帮助避免这种情况。它在很大程度上基于 Rebecca Willet 教授的课程机器学习的数学基础,并假设了线性代数的基础知识。
在本节中,我们将研究多重共线性以及它如何影响最小二乘法。
多重共线性
考虑一个形状为 n × p 的矩阵X。对于其列 X₁ , X₂ ,…, Xₚ ∈ ℝⁿ,我们说它们是线性无关当且仅当 ∑αᵢXᵢ = 0 对于 i = 1,2,…, p 。直观上,在 X 中没有一列可以写成其他的加权和。反过来,如果某些列不是这种情况,我们称它们为线性相关**。假设 rank( X ) = r ,那么 X 的( p — r )列是线性相关的。**
多重共线性在回归术语中,指的是多元回归模型中的一个预测因子可以从其他预测因子中以相当高的准确度进行线性预测的现象。换句话说,预测值近似是其他预测值的线性组合。完美的多重共线性表示特征矩阵中的线性相关性。直觉上,这意味着我们的特征中存在冗余,其中一些特征无法为回归提供唯一和/或独立的信息。
多重共线性不仅在理论上很重要,在实践中也很重要。系数估计值可能会随着模型或数据的微小变化而不规则地变化,而它们本身根本没有意义。为什么会这样?我们将从奇异值分解的角度来看。在此之前,下面是对奇异值分解的快速回顾。
奇异值分解
对于矩阵 X,t 这里总是存在矩阵*,σ, V 这样:*
当 U 和 V 正交时:
**σ是对角线:
**σ的对角元素称为奇异值(σ₁≥σ₂≥…≥σₚ≥0)。非零奇异值的个数是矩阵 X 的秩,σ的列是 X 的行的基础。
多重共线性最小二乘
回想一下,对于特征矩阵 X 和目标变量 y ,最小二乘法试图通过最小化残差的平方和来近似线性系统 y = Xw 的解。权重向量可以用 法方程 写出:
请注意,A 是可逆的当且仅当 n ≥ p 并且秩( X ) = p。现在不难看出为什么完美多重共线性是最小二乘的一个主要问题:它意味着特征矩阵不是满秩的,因此我们无法找到一组适当的系数来最小化残差平方和。
然而,为什么多重共线性,或者具体来说是强多重共线性,也是有问题的呢?让我们从 SVD 的角度来了解一下。
考虑到真实权重 w ,我们知道y*=xw+ϵ,其中 ϵ 是一些可忽略的噪声或误差:*
我们可以看到,最小二乘系数通过 ϵ 乘以某个通货膨胀项而偏离真实权重。仔细看看本文末尾链接的前一篇文章中的通货膨胀术语:
如果 x 的所有列线性无关,我们仍然有 p 奇异值和σ₁≥σ₂≥…≥σₚ>*0。**但是,*随着多重共线性的存在,一些 σᵢ , σₚ 等将接近于零。那么对角元素 1/ σₚ 将是巨大的,导致真正大的膨胀项,因此最小二乘权重与真实权重有很大的偏差。直觉上,多重共线性会损害最小二乘法,因为它会导致较小的奇异值。系数的估计误差由于这些奇异值的倒数而增大,因此变得太大而不能忽略。
如何才能避免这种情况?一种可能是岭回归。
在本节中,我们将了解岭回归如何通过正式推导来帮助避免线性回归中多重共线性所导致的问题。
里脊回归
岭回归通过在成本函数中添加正则化项来建立在最小二乘法的基础上,因此它变成∩y-Xw∩+λ∩w∩,其中 λ 表示正则化的强度。我们可以将成本函数 f(w) 写成:
然后我们可以计算梯度并将其设置为零:
**
仔细看看表达式的中间部分:
这有什么帮助?
考虑 σₚ ≈ 0,这次 σₚ /( σₚ + λ ) ≈ 0 当且仅当 λ ≠ 0。因此,使用岭回归,不重要要素的系数将接近于零(但不会恰好为 0,除非存在完美的多重共线性),并且误差项不会膨胀到爆炸式增长。注意,当没有正则化( λ = 0)时,事情回到最小二乘法。还有,对于大多数场合( σₚ ≫ λ ),σₚ/(σₚ+λ)≈1/σₚ就像在最小二乘法中一样。
实证结果
在本节中,我们将使用一个样本数据集[*seatpos*](https://www.rdocumentation.org/packages/faraway/versions/1.0.7/topics/seatpos)
来验证我们之前的发现。
汽车司机为了自己的舒适喜欢调整座位位置。汽车设计者会发现知道不同的司机会根据他们的身材和年龄把座位放在哪里是很有帮助的。密歇根大学 HuMoSim 实验室的研究人员收集了 38 名司机的数据。
数据集包含以下特征:
我们希望拟合一个基于数据集中所有其他特征预测hipcenter
的线性模型。根据描述,一些特征可以彼此紧密相关。比如Weight
和Ht
,Ht
和HtShoes
。绘制相关矩阵:
上面的情节证实了我们的猜测。在我们的特征矩阵中有很强的多重共线性。好消息是,我们的目标hipcenter
与大多数特性密切相关,我们可以期待一个很好的匹配。产生上述相关图的代码:
使用以下代码块:
- 向特征矩阵添加偏移量;
- 将数据集分成训练集和测试集;
- 归一化特征矩阵,以便我们可以比较系数,因为我们期望变化较大的特征具有较小的系数,其他条件相同
为了简单起见,首先看一个只有Ht
和HtShoes
作为预测器的模型。
*X_train_sub = X_train_[:, 2:4]
X_test_sub = X_test_[:, 2:4]ls = LinearRegression(fit_intercept=True)
ls.fit(X_train_sub, y_train)
print(ls.intercept_, ls.coef_) -165.844 [54.745 -105.923]*
令人惊讶的是,尽管Ht
和HtShoes
几乎完全相关,但它们对hipcenter
的部分影响却具有相反的符号。这可能是高度多重共线性的结果。改为拟合一个 λ = 10 的岭回归模型。
*ridge = Ridge(alpha=10)
ridge.fit(X_train_sub, y_train)
print(ridge.intercept_, ridge.coef_) -165.844 [-21.593 -22.269]*
岭回归的系数似乎更有意义。将其测试 RMSE 与最小二乘法进行比较。
*ls_rmse = mean_squared_error(y_test, ls.predict(X_test_sub))
ridge_rmse = mean_squared_error(y_test, ridge.predict(X_test_sub))print("Least squares test RMSE: {:.3f}".format(ls_rmse))
print("Ridge test RMSE: {:.3f}".format(ridge_rmse)) Least squares test RMSE: 643.260
Ridge test RMSE: 519.287*
对于二元线性模型,岭回归导致更好的泛化能力。然而,由于岭回归引入了正则化项,它的偏差有时可能会更高,以换取更低的方差,这可能导致更差的拟合。
最后,让我们看看完整的模型,并检查最小二乘法和岭回归中系数的大小如何不同,以及它们如何随着惩罚的强度 λ 而变化。
我们可以看到,最小二乘权重与岭回归权重在Ht
和HtShoes
上的差异很大,正如预期的那样。随着惩罚越来越强,岭回归权重越来越接近零。产生上述图的代码:
这篇文章是何坤宇写的。昆玉目前是芝加哥大学的硕士生。他发现理解统计建模和机器学习技术、将它们应用于真实世界的数据并帮助创建金融服务行业的端到端解决方案是一件有趣的事情。在 LinkedIn 上联系昆玉!🐷
* [## 昆玉何-即将上任的全球量化策略非周期分析师-美银美林…
芝加哥大学正在接受理学硕士计算分析项目培训的数据科学家。对…充满热情
www.linkedin.com](https://www.linkedin.com/in/kunyuhe/)*
从零开始岭回归正则化
降低回归模型的方差。
贾里德·阿兰戈在 Unsplash 上的照片
为了使机器学习模型有效,它必须在偏差和方差之间取得平衡。岭回归正则化旨在通过折衷偏差来减少方差。
偏差和方差:
要理解岭回归正则化的使用及其实现,需要了解它试图解决的问题的一些背景。
偏差本质上是模型的均方误差,当应用于它被训练的数据时。具有低均方误差的模型因此具有低偏差。
方差是将数据与数据集的不同样本进行比较时,损失变化的度量。过度拟合的模型具有很高的方差,因为它们的预测对其他样本不起作用。
这个模型有很高的偏差,因为它完美地符合每一点。
然而,当对一个不同的样本进行拟合时,它没有被训练过,表现很差。
每种机器学习算法都有偏差和方差之间的权衡。一般的经验法则是,参数越多的模型偏差越小,但方差越大,而参数越少的模型偏差越大,但方差越小。
岭正则化如何减少方差?
与最小化均方误差函数的回归模型相反,岭正则化最小化添加到λ和斜率平方的乘积的均方误差函数。
代码:
import numpy as np
from matplotlib import pyplot as pltdef sigmoid(x):
return 1/(1+np.exp(-x))def sigmoid_p(x):
return sigmoid(x)*(1 -sigmoid(x))def relu(x):
return np.maximum(x, 0)def relu_p(x):
return np.heaviside(x, 0)def tanh(x):
return np.tanh(x)def tanh_p(x):
return 1.0 - np.tanh(x)**2def deriv_func(z,function):
if function == sigmoid:
return sigmoid_p(z)
elif function == relu:
return relu_p(z)
elif function == tanh:
return tanh_p(z)class NeuralNetwork:
def __init__(self):
self.layers = []
self.weights = []
self.loss = []
def add(self,layer_function):
self.layers.append(layer_function)
def propagate(self,X):
As,Zs = [],[]
input_data = X
for layer in self.layers:
index = self.layers.index(layer)
weights = layer.initialize_weights(self.layers,index)
if type(weights) != type(None) :
self.weights.append(weights)
a,z = layer.propagate(input_data)
As.append(a)
Zs.append(z)
input_data = a
print(a.shape)
return As,Zs
def train(self,X,y,iterations):
loss = []
for i in range(iterations):
As,Zs = self.propagate(X)
loss.append(np.square(sum(y - As[-1])))
As.insert(0,X)
g_wm = [0] * len(self.layers)
for i in range(len(g_wm)):
pre_req = (y-As[-1])*2
a_1 = As[-(i+2)]
z_index = -1
w_index = -1
if i == 0:
range_value = 1
else:
range_value = 2*i
for j in range(range_value):
if j% 2 == 0:
pre_req = pre_req * sigmoid_p(Zs[z_index])
z_index -= 1
else:
pre_req = np.dot(pre_req,self.weights[w_index].T)
w_index -= 1
gradient = np.dot(a_1.T,pre_req)
g_wm[-(i+1)] = gradient
for i in range(len(self.layers)):
if self.layers.trainable == True:
self.layers[i].network_train(g_wm[i])
return loss
class Perceptron:
def __init__(self,nodes,input_shape= None,activation = None):
self.nodes = nodes
self.input_shape = input_shape
self.activation = activation
self.trainable = True
def initialize_weights(self,layers,index):
if self.input_shape:
self.weights = np.random.randn(self.input_shape[-1],self.nodes)
else:
self.weights = np.random.randn(layers[index-1].output_shape[-1],self.nodes)
return self.weights
def propagate(self,input_data):
z = np.dot(input_data,self.weights)
if self.activation:
a = self.activation(z)
else:
a = z
self.output_shape = a.shape
return a,z
def network_train(self,gradient):
self.weights += gradient
model = NeuralNetwork()Perceptron = model.Perceptron
这是我创建的一个神经网络框架,执行基本的线性和逻辑回归。我在这里添加了完整的代码,这样当示例完成时,您可以自己实现它。让我们从培训功能中删除所有内容:
def train(self,X,y,iterations):
loss = []
for i in range(iterations):
As,Zs = self.propagate(X)
loss.append(np.square(sum(y - As[-1])))
As.insert(0,X)
g_wm = [0] * len(self.layers)
for i in range(len(g_wm)):
pre_req = (y-As[-1])*2
a_1 = As[-(i+2)]
z_index = -1
w_index = -1
if i == 0:
range_value = 1
else:
range_value = 2*i
for j in range(range_value):
if j% 2 == 0:
pre_req = pre_req * sigmoid_p(Zs[z_index])
z_index -= 1
else:
pre_req = np.dot(pre_req,self.weights[w_index].T)
w_index -= 1
gradient = np.dot(a_1.T,pre_req)
g_wm[-(i+1)] = gradient
for i in range(len(self.layers)):
if self.layers.trainable == True:
self.layers[i].network_train(g_wm[i])
这个代码通过神经网络导航,将导数链接到它们各自的部分。您会注意到变量 pre_req 对于所有计算的梯度都是一致的。这是预测对损失函数的偏导数。我们需要更改的只是那行代码:
pre_req = (y-As[-1])*2
目前,该变量包含均方误差函数的导数。让我们用岭回归损失函数的导数来代替它:
#The loss function
loss = np.square(y-As[-1]) + lam*self.weights[0]
#the derivative
pre_req = (y-As[-1])*2 + lam*self.weights[0]
结论:
岭正则化的工作原理是对较高斜率值的模型进行惩罚,从而降低数据集中不同样本之间的方差
谢谢你看我的文章!
简易模式下的岭回归
了解岭回归模型背后的理论,如何通过 python 和 scikit-learn 对其进行编码和调优。
它们是什么?
岭回归可以被认为是线性回归的一个步骤。它们也被称为吉洪诺夫正则化;和对于缓解线性回归中的多重共线性问题特别有用,该问题通常出现在具有大量参数的模型中。
照片由尼古拉斯·J·勒克莱尔在 Unsplash 拍摄
简单概括线性回归:他们通过最小化模型的残差平方和(RSS) 来估计线性模型截距和斜率系数。RSS 公式及其生成的线性模型如下所示:
点击这里了解更多关于如何用 python 编写自己的线性回归代码!
虽然简单的线性回归在大多数数据分析情况下通常被认为是有效的,但它们总是产生直线最佳拟合线。这源于关于因变量和自变量之间关系的强有力的先验假设:它们具有线性关系。
当我们不得不抛弃这个假设时,问题就来了,我们需要接受缺乏参数来控制模型复杂性的事实。
这就是岭回归的用武之地。他们增加了一个额外的术语,如下图红色所示。
这一项被称为 L2 正则化参数,其中 L1 可以产生稀疏模型,而 L2 不能。最终结果仍然是一个简单的线性模型,如果使用 OLS 方法,其格式与相似,但系数可能不同。(通过下面的示例显示)
岭回归方程
正则项充当损失函数,它是在计算岭回归的 RSS 时对错误预测的惩罚。它通过将系数的平方值加到模型的 RSS 上来起作用。由于“最佳”模型是具有最小 RSS 的模型,具有较大系数的模型根据被有效过滤。
正则化的作用是通过试图限制模型以降低复杂性来减少过拟合。正则项通过将系数的平方值添加到模型的 RSS 中来起作用。由于“最佳”模型是 RSS 最小的模型,因此系数较大的模型会根据进行有效过滤。
最终结果是,模型更喜欢系数较小的特征。
正则化对于 100+变量特别有效。**此外,正则化的量由正则化项中的阿尔法参数控制。**较高的 alpha 值导致模型招致更多的惩罚,使系数进一步向 0 收缩。python 中的默认值是 1。一个特殊的情况是,当α= 0 时,得到的模型相当于 OLS 简单线性回归。
代码
为了举例说明岭回归的编码,我们将看看如何使用犯罪数据集。
包装
对于包,让我们导入*犯罪数据集、*和用于创建训练测试分割、进行 MixMaxScaling 和创建岭回归的类。
import numpy
from adspy_shared_utilities import load_crime_dataset
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.linear_model import Ridge
加载数据集,并创建 75 / 25 列车测试数据分割:
(X_crime, y_crime) = load_crime_dataset()
X_train, X_test, y_train, y_test = train_test_split(X_crime,
y_crime, random_state = 0)
# take note of the indentation.
缩放训练和测试数据集:
scaler = MinMaxScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
创建 alpha 值为 20.0 的岭回归对象,并在缩放的 X 训练数据上拟合该对象以及相应的训练数据 Y 标签:
linridge = Ridge(alpha=20.0).fit(X_train_scaled, y_train)
获取模型系数:
linridge.intercept_
linridge.coef_ **-3352.423035846206
[ 1.95091438e-03 2.19322667e+01 9.56286607e+00 -3.59178973e+01
6.36465325e+00 -1.96885471e+01 -2.80715856e-03 1.66254486e+00
-6.61426604e-03 -6.95450680e+00 1.71944731e+01 -5.62819154e+00
8.83525114e+00 6.79085746e-01 -7.33614221e+00 6.70389803e-03
9.78505502e-04 5.01202169e-03 -4.89870524e+00 -1.79270062e+01
9.17572382e+00 -1.24454193e+00 1.21845360e+00 1.03233089e+01
-3.78037278e+00 -3.73428973e+00 4.74595305e+00 8.42696855e+00
3.09250005e+01 1.18644167e+01 -2.05183675e+00 -3.82210450e+01
1.85081589e+01 1.52510829e+00 -2.20086608e+01 2.46283912e+00
3.29328703e-01 4.02228467e+00 -1.12903533e+01 -4.69567413e-03
4.27046505e+01 -1.22507167e-03 1.40795790e+00 9.35041855e-01
-3.00464253e+00 1.12390514e+00 -1.82487653e+01 -1.54653407e+01
2.41917002e+01 -1.32497562e+01 -4.20113118e-01 -3.59710660e+01
1.29786751e+01 -2.80765995e+01 4.38513476e+01 3.86590044e+01
-6.46024046e+01 -1.63714023e+01 2.90397330e+01 4.15472907e+00
5.34033563e+01 1.98773191e-02 -5.47413979e-01 1.23883518e+01
1.03526583e+01 -1.57238894e+00 3.15887097e+00 8.77757987e+00
-2.94724962e+01 -2.32995397e-04 3.13528914e-04 -4.13628414e-04
-1.79851056e-04 -5.74054527e-01 -5.17742507e-01 -4.20670930e-01
1.53383594e-01 1.32725423e+00 3.84863158e+00 3.03024594e+00
-3.77692644e+01 1.37933464e-01 3.07676522e-01 1.57128807e+01
3.31418306e-01 3.35994414e+00 1.61265911e-01 -2.67619878e+00]**
获得模型 R 平方得分
linridge.score(X_train_scaled, y_train)
linridge.score(X_test_scaled, y_test)**-31.672
-37.249**
非零特征的数量:
(np.sum(linridge.coef_ != 0))**88**
调整 alpha 值以最大化训练和测试分数。我们可以获得非零特征的数量以及如下的训练和测试分数:
for alpha in [0, 1, 10, 20, 50, 100, 1000]:
linridge = Ridge(alpha = this_alpha).fit(X_train_scaled,y_train)
r2_train = linridge.score(X_train_scaled, y_train)
r2_test = linridge.score(X_test_scaled, y_test)
num_coeff_bigger = np.sum(abs(linridge.coef_) > 1.0)
print('Alpha = {:.2f}\nnum abs(coeff) > 1.0: {}, \
r-squared training: {:.2f}, r-squared test: {:.2f}\n'
.format(this_alpha, num_coeff_bigger, r2_train, r2_test))**Ridge regression: effect of alpha regularization parameter****Alpha = 0.00
num abs(coeff) > 1.0: 88, r-squared training: 0.67, r-squared test: 0.50
Alpha = 1.00
num abs(coeff) > 1.0: 87, r-squared training: 0.66, r-squared test: 0.56
Alpha = 10.00
num abs(coeff) > 1.0: 87, r-squared training: 0.63, r-squared test: 0.59
Alpha = 20.00
num abs(coeff) > 1.0: 88, r-squared training: 0.61, r-squared test: 0.60
Alpha = 50.00
num abs(coeff) > 1.0: 86, r-squared training: 0.58, r-squared test: 0.58
Alpha = 100.00
num abs(coeff) > 1.0: 87, r-squared training: 0.55, r-squared test: 0.55
Alpha = 1000.00
num abs(coeff) > 1.0: 84, r-squared training: 0.31, r-squared test: 0.30**
结论
通过这篇文章,我希望您已经了解了岭回归背后的理论,以及如何通过 python 和 scikit-learn 对岭回归模型进行编码和调优。
我通过由 Coursera 主办的密歇根大学 MOOC“Python 中的应用机器学习”了解到了这一点。
如果你有问题或者想讨论后新冠肺炎世界,请随时联系我。
我希望我能够以这样或那样的方式帮助您学习数据科学方法!
这是另一篇数据科学文章!
使用 scikit-学习 python
medium.com](https://medium.com/analytics-vidhya/k-nearest-neighbors-in-6-steps-efbcbebce54d)
Riot API:一个机器学习和数据分析应用
实践教程
一个简单的基于 python 的教程,通过 Riot API 进行数据分析和机器学习,以提高个人水平
为什么要看这篇文章?
一个简单的基于 python 的教程,通过 Riot API 进行数据分析和机器学习,以提高个人水平。
如果你正在阅读这篇文章,你可能是《英雄联盟》的粉丝,这是一款流行的 MOBA 类型的在线游戏(多人在线竞技场)。或者你可能对机器学习和数据分析在网络游戏世界中的可能应用感兴趣。这款游戏由 Riot Games 开发发布。
全世界有数百万玩家,这款游戏拥有广泛的业余玩家和职业玩家。它利用了游戏的不断进化和统计复杂性。这个游戏的基本原理(非常)简单。由于有成千上万的变量和可能的场景,每场比赛都是不同的。
给定大量的数据,提取重要的数据可以让你获得关于你的比赛风格的有趣信息。你可以提取有用的信息来改善你的游戏风格或预测你未来的表现。
许多网站如 op.gg 提供了大量的数据、分析和图表。这很好,但是如果您想要开发定制的或者更复杂的模型,您将需要一些手工工作。
RiotGamesAPI是一个 REST API 为开发者构建自己的应用或网站提供有用的数据。
我建议您在开始编程之前阅读文档,以避免违反服务的法律条款。您还可以避免数据请求速率的问题。
在接下来的部分中,我们将了解如何:
- 从 Riot API 中提取有用的数据
- 处理数据以获得有用的信息
- 创建简单的预测模型
从 Riot API 中提取有用的数据
让我们从安装和导入一些基本库开始。如果您使用的是 Google 协作笔记本,您将不会遇到任何问题,否则,您将需要根据您的操作系统安装单独的库。
!pip3 install riotwatcher!pip install -q seaborn!pip install -q git+https://github.com/tensorflow/docsimport numpy as np
import matplotlib.pyplot as plt
import pathlib
import pandas as pd
import seaborn as sns
import tensorflow as tf
import time
from tensorflow import keras
from tensorflow.keras import layers
import tensorflow_docs as tfdocs
import tensorflow_docs.plots
import tensorflow_docs.modeling
from riotwatcher import LolWatcher, ApiError
为了提取数据,我们使用了 RiotWatcher ,它是一个薄薄的包装器,位于英雄联盟的 Riot Games API 之上。必须使用 Riot API 密钥,每 24 小时生成一次。请记住,此密钥是个人的,不应共享。让我们从提取一个玩家(或者召唤师)的一些信息开始:让我们得到想要的玩家的等级
lol_watcher = LolWatcher('%YOUR RIOT API KEY%')
my_region = 'euw1'
me = lol_watcher.summoner.by_name(my_region, '%YOUR SUMMONER NAME%')
my_ranked_stats = lol_watcher.league.by_summoner(my_region, me['id'])print(my_ranked_stats)
让我们提取一个更新版本的冠军,物品,召唤师法术和任何其他所需的属性,因此我们的比赛历史:
versions = lol_watcher.data_dragon.versions_for_region(my_region)
champions_version = versions['n']['champion']
summoner_spells_version=versions['n']['summoner']
items_version=versions['n']['item']
( ... )
current_champ_list = lol_watcher.data_dragon.champions(champions_version)
( ... )
my_matches = lol_watcher.match.matchlist_by_account(my_region, me['accountId'])
我们拥有大量的数据,这些数据的重要性是高度主观的。更多的功能将导致更复杂,但更准确的模型。为了获得真正准确的分析,有必要获得尽可能多的游戏信息,以更好地适应我们的模型,并使结果更可信。让我们从过去的 100 场比赛中提取数据,并定义一系列包含所有主要信息的熊猫数据帧。
n_games = 100Games = {}
Game_duration=np.zeros(n_games)
Damage = np.zeros(n_games)
(...)
j=0
cont=0
while cont<n_games:
try:
last_match = my_matches['matches'][cont]
match_detail = lol_watcher.match.by_id(my_region, last_match['gameId'])
participants = []
for row in match_detail['participants']:
participants_row = {}
participants_row['champion'] = row['championId']
participants_row['win'] = row['stats']['win']
participants_row['assists'] = row['stats']['assists']
( ... )
participants.append(participants_row)
Games[j] = pd.DataFrame(participants) champ_dict = {}
for key in static_champ_list['data']:
row = static_champ_list['data'][key]
champ_dict[row['key']] = row['id'] summoners_dict = {}
for key in static_summoners_list['data']:
row = static_summoners_list['data'][key]
summoners_dict[row['key']] = row['id'] Summoner_name = []
for row in match_detail['participantIdentities']:
Summoner_name_row = {}
Summoner_name_row=row['player']['summonerName']
Summoner_name.append(Summoner_name_row) i=0for row in participants:
row['championName'] = champ_dict[str(row['champion'])]
row['Summoner_name']=Summoner_name[i]
row['Summoner Spell 1']=summoners_dict[str(row['spell1'])]
row['Summoner Spell 2']=summoners_dict[str(row['spell2'])]
i+=1
Games[j]= pd.DataFrame(participants)
for index, row in Games[j].iterrows():
if row['Summoner_name']=='%YOUR SUMMONER NAME%':
Damage[j]=row['totalDamageDealt']
Gold[j]=row['goldEarned']
( ... ) time.sleep(10)
j+=1
cont+=1
except:
cont+=1
至此,我们已经提取了所有感兴趣的数据:让我们继续进行数据分析。警告:在每个循环中插入了 10 秒钟的暂停,以不超过 Riot API 允许的每小时请求的最大数量。
数据处理
在这一点上,我们拥有大量的数据,显然并不重要:要获得有用的信息,你需要将你在“游戏属性”方面的兴趣与数据分析和机器学习的现代算法结合起来,能够给出有效的答案。数据可以给出很多关于游戏中表现的答案,有可能发现优势/劣势,甚至根据你的现场游戏统计数据预测获胜的概率!为了便于理解,在下面的段落中给出了对一组简化的参数进行的一些简单分析作为例子,但是您可以很容易地生成更复杂和有趣的模型。我们可以从准备一个可以有效用于数据分析的数据库开始:让我们看看我们游戏的一些简单特性:
dataset={}
dataset['Total Damage']=Damage
dataset['Gold']=Gold
( ... )
dataset['Victory']=Victory #Boolean
无论我们的目标是解决回归问题(连续输出系统)还是分类问题(离散输出系统),都有必要将起始数据集分成两个独立的数据集:
- 训练集:该数据集用于模型(即神经网络)的训练。在训练集上具有良好的预测性能是重要的,但同时,避免过拟合现象也是必要的。
- 测试集:在训练迭代过程中用于模型验证的集
train_dataset_raw = dataset.sample(frac=0.8,random_state=0)
test_dataset_raw = dataset.drop(train_dataset_raw.index)
train_dataset=train_dataset_raw.iloc[:,range(0,4)]
test_dataset=test_dataset_raw.iloc[:,range(0,4)]
train_labels=train_dataset_raw.iloc[:,4]
test_labels=test_dataset_raw.iloc[:,4]
配对图
pair plot 绘制数据集中的成对关系。Pairplot 函数创建一个轴网格,这样数据中的每个变量将在 y 轴的一行中共享,在 x 轴的一列中共享。
sns.pairplot(train_dataset_raw, diag_kind="kde")
作者图片
为什么要分析这样一个图?因为它允许您快速获得有关所选数据之间各自关系的定性信息。例如,我们可能会注意到,所拥有的黄金总量的增加会导致更大的总伤害,这是获胜次数和游戏参数之间的关系,也是各自领域中个体数量的概率分布。
互相关矩阵
对于数据间相关性的更定性分析,可以参考相关矩阵。计算相关值有几种方法。最流行的是 皮尔逊相关系数 。然而,应该注意的是,它只测量两个变量之间的线性关系。换句话说,它可能无法揭示非线性关系。皮尔逊相关值的范围从-1 到+1,其中+/-1 表示完全正/负相关,0 表示不相关。相关矩阵是对称矩阵,所有对角元素等于+1”
corr = dataset.corr()
mask = np.triu(np.ones_like(corr, dtype=bool))
f, ax = plt.subplots(figsize=(11, 9))
cmap = sns.diverging_palette(230, 20, as_cmap=True)
sb.heatmap(corr, mask=mask, cmap=cmap, vmax=0.9, center=0, vmin=-0.2,
square=True, linewidths=.5, cbar_kws={"shrink": .5}, annot = True)
plt.show()
作者图片
知道这个问题的人可能会意识到,比如说,附身黄金的伤害增加或者死亡和胜利之间的反向趋势是正确的,即使看起来微不足道。然而,用简单的语句对这些模型进行验证,可以更准确地应用于更复杂的数据集。
胜利概率的估计:一个简单的分类问题
首先,让我们将数据标准化:
def norm(x):
return (x - train_stats['mean']) / train_stats['std']
normed_train_data = norm(train_dataset)
normed_test_data = norm(test_dataset)
Keras 和 TensorFlow 库提供的强大工具有助于模型生成。让我们为我们的分类定义一个简单的序列模型,它具有以下属性:
- 型号:顺序
- 输入层:4 节点层
- 2 隐藏层:activation = ' relu 节点数= 16/32
- 2 个下降层:0.2
- 输出层:activation = ' sigmoid 节点数= 1;
- 模型属性:loss='binary_crossentropy ',optimizer='adam ',metrics=['accuracy']
dumbo=(normed_test_data,test_labels)
model = Sequential()
epochs=700
model.add(Dense(16, input_dim=4, activation='relu'))
layers.Dropout(0.2)
model.add(Dense(32, activation='relu'))
layers.Dropout(0.2)
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam',metrics ['accuracy'])
history = model.fit(normed_train_data, train_labels, epochs=epochs,validation_data=dumbo)
然后,我们在整个测试数据集上评估模型预测的质量:
作者图片
定性地说,我们可以注意到在训练集和验证集上都有非常好的表现(与所研究案例的简单性相关)。从数量上我们得到:
- 测试损失:0.4501 —测试精度:0.9583
- 列车损失:0.0891-列车精度:0.9688
从图形上看,我们得到:
作者图片
我们根据选择的游戏参数,有 97%的准确率正确预测游戏结果! 显然,预测的质量将取决于所选择的特征、模型的质量等等。
结论
我们已经看到了 riot API 的一个简单应用,我们开发了一系列工具来分析我们在游戏中的技能。我们还预测了我们未来的表现!这是开发代码、应用程序等的起点。利用英雄联盟游戏中产生的大量数据。
感谢阅读
RIP 相关性。引入预测能力评分
我们定义并开源的预测能力评分(PPS)。PPS 是在您的数据中发现更多模式的相关性的替代方案。
相关性有太多问题
现在是周五下午,您的老板告诉您,数据发送出乎意料地提前到了——前后只有 4 周。这是您的预测模型缺少的部分。您很兴奋,但也有点焦虑,因为您知道接下来会发生什么:探索数据。好吧。45.列。这可能需要几个小时,但您知道这是值得的,因为没有数据理解,您就是在瞎走。一个明显的步骤是查看所有单变量列分布。但这还不够。
您会问自己:列之间存在什么关系?
要回答这个问题,您只需要重复典型的练习:计算一个相关矩阵,并检查一些令人惊讶的关系。每当你感到惊讶的时候,你就花点时间画出手头两列的散点图,看看你是否能理解它。希望你能做到,但通常你做不到,因为你甚至都不知道这些列的含义。但这是另一天的故事。
检查完相关矩阵后,您继续前进,您甚至不知道您不知道的东西(可怕)。
让我们花点时间回顾一下相关性。评分范围从-1 到 1,表示是否存在强线性关系——正向或负向。到目前为止还不错。然而有许多分数根本检测不到的非线性关系。例如,正弦波、二次曲线或神秘的阶跃函数。分数将只是 0 分,表示“这里没什么有趣的”。此外,相关性只为数字列定义**。所以,让我们放下所有的分类栏。在我上一个项目**中,超过 60%的列是分类的,但是嘿。没关系。不,我不会转换列,因为它们不是有序的,一个原子编码会创建一个矩阵,它的值比宇宙中的原子还要多。
关联为 0 的方案太多。这让我怀疑我是否错过了什么……(节选自丹尼斯·博伊格罗的图像)
如果你受过良好教育,你会知道相关矩阵是对称的。所以你基本上可以扔掉一半。太好了,我们节省了一些工作!或者我们有吗?对称意味着无论你计算 A 和 B 的相关性还是 B 和 A 的相关性,相关性都是相同的。然而,现实世界中的关系很少是对称的。更多的时候,关系是不对称的。这里有一个例子:我最后一次检查时,我的邮政编码 60327 相当可靠地告诉陌生人我住在德国的法兰克福。但是当我只告诉他们我所在的城市时,不知何故,他们永远无法推断出正确的邮政编码。Pff …业余爱好者。另一个例子是这样的:一个有 3 个唯一值的列永远不可能完美地预测另一个有 100 个唯一值的列。但事实可能恰恰相反。显然,不对称很重要,因为它在现实世界中非常普遍。
想到相关性的那些缺点,我开始怀疑:我们能做得更好吗?
**需求:**去年的一天,我梦见了一个分数,它会告诉我两列之间是否存在任何关系——不管这种关系是线性的、非线性的、高斯的还是只有外星人知道的。当然,分数应该是不对称的,因为我想检测城市和邮政编码之间的所有怪异关系。如果没有关系,得分应该是 0,如果有完美的关系,得分应该是 1。作为锦上添花,score 应该能够开箱即用地处理类别和数字列。总结一下我所有的学术朋友:一个不对称的,数据类型不可知的分数,用于两列之间的预测关系,范围从 0 到 1。
计算预测能力得分(PPS)
首先,没有唯一的方法来计算预测能力得分。事实上,有许多可能的方法来计算满足前面提到的要求的分数。所以,让我们把预测能力分数看作是一个分数家族的框架。
假设我们有两个列,并希望计算 A 预测 B 的预测能力得分。在这种情况下,我们将 B 视为我们的目标变量,将 A 视为我们的(唯一)特征。我们现在可以计算一个交叉验证的决策树和计算一个合适的评估指标。当目标是数字时,我们可以使用决策树回归器并计算平均绝对误差(MAE)。当目标是类别时,我们可以使用决策树分类器并计算加权 F1。您也可以使用其他得分,如 ROC 等,但让我们先把这些疑虑放在一边,因为我们还有另一个问题:
如果不与基线进行比较,大多数评估指标都是没有意义的
我想你们都知道这种情况:你告诉你的奶奶,你的新车型的 F1 分数为 0.9,不知何故,她不像你一样兴奋。事实上,她非常聪明,因为她不知道是否有人能得 0.9 分,也不知道你是否是第一个在数百万令人敬畏的卡格勒人尝试后得分高于 0.5 分的人。所以,我们需要“标准化”我们的评估分数。你如何使分数正常化?你定义了一个下限和一个上限,并把分数放在适当的位置。那么下限和上限应该是多少呢?让我们从上限开始,因为这通常更容易:一个完美的 F1 是 1。完美的 MAE 是 0。嘣!完成了。但是下限呢?事实上,我们不能绝对地回答这个问题。
下限取决于评估指标和您的数据集。这是一个简单的预测器所能达到的值。
如果你的 F1 成绩是 0.9,这可能是非常糟糕或者非常好。如果你的超级花哨的癌症检测模型总是预测“良性”,并且在高度倾斜的数据集上仍然得到 0.9 分,那么 0.9 显然不是那么好。所以,我们需要为一个非常幼稚的模型计算一个分数。但是什么是幼稚的模型呢?对于分类问题,总是预测最常见的类是非常天真的。对于回归问题,总是预测中值是相当幼稚的。
让我们来看一个详细的、虚构的例子:
回到邮政编码和城市名称的例子。想象两列都是范畴。首先,我们要计算邮政编码到城市的 PPS。我们使用加权 F1 分数,因为城市是一个范畴。我们的交叉验证决策树分类器达到了 0.95 F1 的分数。我们通过总是预测最常见的城市来计算基线分数,并获得 0.1 F1 的分数。如果您对分数进行归一化,则在应用以下归一化公式后,您将获得 0.94 的最终 PPS:(0.95–0.1)/(1–0.1)。正如我们所见,0.94 的 PPS 分数相当高,因此邮政编码似乎对城市有很好的预测能力。但是,如果我们以相反的方向计算 PPS,我们可能会获得接近 0 的 PPS,因为决策树分类器并不比总是预测最常见的邮政编码好多少。
请注意:MAE 的标准化公式不同于 F1。对于 MAE,越低越好,最佳值为 0。
将 PPS 与相关性进行比较
为了更好地感受 PPS 及其与相关性的差异,让我们来看下面两个例子:
示例 1:非线性效应和不对称
示例 1:y = x 时与 PPS 的相关性比较
让我们使用一个典型的二次关系:特征 x 是范围从-2 到 2 的均匀变量,目标 y 是 x 的平方加上一些误差。在这种情况下,x 可以很好地预测 y,因为存在明显的非线性二次关系——毕竟我们就是这样生成数据的。然而,在从 y 到 x 的另一个方向上,这是不成立的。例如,如果 y 是 4,则不可能预测 x 大致是 2 还是-2。因此,预测关系是不对称的,分数应该反映这一点。
这个例子中的分值是多少?如果你还不知道你在找什么,相关性会让你无所适从,因为相关性是 0 。从 x 到 y 和从 y 到 x,因为相关是对称的。然而,从 x 到 y 的 PPS 是 0.67 ,检测到非线性关系并挽救了局面。然而,PPS 不是 1,因为在关系中存在一些误差。在另一个方向,从 y 到 x 的 PPS 是 0 ,因为你的预测不可能比原始基线更好,因此分数是 0。
示例 2:分类列和隐藏模式
让我们将相关矩阵与 Titanic 数据集上的 PPS 矩阵进行比较。“泰坦尼克号数据集?又来了??"我知道,你可能认为你已经看到了关于泰坦尼克号数据集的一切,但也许 PPS 会给你一些新的见解。
示例 2:比较 Titanic 数据集的 Pearson 相关矩阵(左)和 PPS 矩阵(右)。
关于相关矩阵的两个发现:
- 相关矩阵更小,省略了许多有趣的关系。当然,这是有意义的,因为像 Sex、TicketID 或 Port 这样的列是分类的,并且不能为它们计算相关性。
- 相关矩阵显示了股票价格和中等强度等级(-0.55)之间的负相关。如果我们看一下 PPS,我们可以仔细检查这种关系。我们将会看到,TicketPrice 是该类别的一个强预测值(0.9 PPS),但反之则不然。该类仅预测 PPS 为 0.2 的 TicketPrice。这是有道理的,因为无论你的机票价格是 5.000 美元还是 10.000 美元,你都很有可能是最高等级的。相比之下,如果你知道某人在最高级,你就不能说他是花了 5000 美元还是 10000 美元买的票。在这种情况下,PPS 的不对称性再次显现。
关于 PPS 矩阵的四项发现:
- 矩阵的第一行告诉您幸存的列的最佳单变量预测值是列性别。这是有道理的,因为在救援过程中女性是优先考虑的。(我们在相关矩阵中找不到此信息,因为删除了列性别。)
- 如果您查看 TicketID 的列,您会发现 TicketID 对于一系列列来说是一个相当好的预测器。如果你进一步挖掘这个模式,你会发现许多人有相同的 TicketID 。因此,TicketID 实际上是指一起买票的潜在乘客群体,例如意大利罗西大家庭,它将任何夜晚都变成了奇观。因此,PPS 帮助我发现了一个隐藏的模式。
- 比 TicketID 强大的预测能力更令人惊讶的是 TicketPrice 在广泛的列中的强大预测能力。特别是,TicketPrice 在预测 TicketID (0.67)方面相当不错,反之亦然(0.64)。进一步研究后,你会发现门票往往有独特的价格。例如,仅意大利罗西家族就付出了 72,50 美元的代价。这是一个关键的洞察力!这意味着****ticket price 包含了关于 TicketID** 的信息,因此也包含了关于我们意大利家庭的信息。在考虑潜在信息泄露时,您需要掌握的信息。**
- 查看 PPS 矩阵,我们可以看到可以用因果链来解释的影响。(他刚才说的是因果吗?—当然,这些因果假设必须认真对待,但这超出了本文的范围。)例如,你可能会惊讶为什么 TicketPrice 对存活率有预测能力(PPS 0.39)。但是如果你知道这个职业会影响你的存活率(PPS 0.36),而且 TicketPrice 是你职业的一个很好的预测指标(PPS 0.9),那么你可能会找到一个解释。
PPS 和 PPS 矩阵的应用
在我们了解了 PPS 的优点之后,让我们看看在现实生活中我们可以在哪里使用 PPS。
免责声明:PPS 和相关性都有用例。对于在数据中寻找预测模式而言,PPS 明显优于相关性。然而,一旦发现了模式,相关性仍然是传达发现的线性关系的好方法。
- ****查找数据中的模式:PPS 查找关联所找到的每个关系,甚至更多。因此,您可以使用 PPS 矩阵作为相关矩阵的替代,来检测和理解数据中的线性或非线性模式。使用一个范围总是从 0 到 1 的单一分数,这在所有数据类型中都是可能的。
- ****特征选择:除了您通常的特征选择机制之外,您还可以使用预测能力得分来为您的目标列找到好的预测器。此外,您可以消除只是添加随机噪声的要素。这些特性有时仍然在特性重要性度量中得分很高。此外,您可以排除可由其他要素预测的要素,因为它们不会添加新信息。此外,您可以在 PPS 矩阵中识别相互预测的特征对,这包括强相关的特征,但也将检测非线性关系。
- ****检测信息泄漏:使用 PPS 矩阵检测变量之间的信息泄漏——即使信息泄漏是通过其他变量介导的。
- ****数据规范化:通过将 PPS 矩阵解释为有向图,找到数据中的实体结构。当数据包含以前未知的潜在结构时,这可能会令人惊讶。比如:泰坦尼克号数据集中的 TicketID 往往是一个家庭的指标。
如何在自己的(Python)项目中使用 PPS
如果你还在跟随,你就是少数仍有注意力持续时间的人之一——你这个疯狂的野兽!如果你迫不及待地想知道 PPS 将在你自己的数据上揭示什么,我们有一些好消息给你:我们开源了 PPS 的一个实现,作为一个名为 ppscore 的 Python 库。
在使用 Python 库之前,请花点时间通读一下计算细节
安装软件包:
pip install ppscore
计算给定熊猫数据框架的 PPS:
import ppscore as pps
pps.score(df, "feature_column", "target_column")
您还可以计算整个 PPS 矩阵:
pps.matrix(df)
与相关性相比,PPS 的速度有多快?
虽然 PPS 比相关法有许多优点,但也有一些缺点:计算时间较长。但是有多糟糕呢?是需要几周时间,还是几分钟甚至几秒钟就能完成?当使用 Python 库计算一个单 PPS** 时,时间应该没有问题,因为它通常需要大约10–500 ms。计算时间主要取决于数据类型、行数和使用的实现。然而,当计算 40 列的整个 PPS 矩阵时,这会导致 40*40= 1600 次单独计算,而可能需要 1-10 分钟。所以你可能想在后台开始 PPS 矩阵的计算,去那个你一直梦想的暑假!🏖️For:我们的项目和数据集计算性能一直很好,但当然还有改进的空间。幸运的是,我们看到许多方法可以改进 PPS 的计算,以实现 10-100 倍的速度增益。例如,使用智能采样、试探法或 PPS 的不同实现。如果你喜欢 PPS 并且需要更快的计算,请联系我们。**
限制
我们成功了——您很兴奋,想要向您的同事展示 PPS。然而,你知道他们总是对新方法吹毛求疵。这就是为什么你最好准备好了解 PPS 的局限性:
- 计算比相关(矩阵)慢。
- 分数不能像相关性那样容易解释,因为它不能告诉你任何关于所发现的关系的类型的信息。因此,PPS 更适合于发现模式,而相关性更适合于传达发现的线性关系。****
- 您不能以严格的数学方式比较不同目标变量的得分,因为它们是使用不同的评估指标计算的。分数在现实世界中仍然是有价值的,但是你需要记住这一点。
- 发动机罩下使用的部件有局限性。请记住:您可以交换组件,例如使用 GLM 代替决策树,或者使用 ROC 代替 F1 进行二元分类。
- 如果使用 PPS 进行功能选择,您还需要执行向前和向后选择。此外,PPS 无法检测目标特征之间的交互影响。
结论
在使用相关性多年后,我们变得如此大胆(或疯狂?)来建议一种可以检测线性和非线性关系的替代方案。PPS 可以应用于数字列和类别列,并且是不对称的。我们提出了一个实现,并开源了一个 Python 包。此外,我们在一些示例中展示了相关性的差异,并讨论了我们可以从 PPS 矩阵中获得的一些新见解。
现在由你来决定你对 PPS 的看法,以及你是否想在你自己的项目中使用它。我们已经将 PPS 作为 bamboolib 库的一部分使用了一年多,PPS 对于添加一些高级功能是必不可少的,因此我们希望与更广泛的社区共享 PPS。因此,我们希望收到您对该概念的反馈,如果您在自己的数据上尝试 PPS,我们将非常激动。如果有可能得到积极的回应,我们很高兴听到您对实现进行调整或改进的请求。正如我们之前提到的,有许多方法可以提高速度,以及如何针对更具体的用例调整 PPS。
****Github:【https://github.com/8080labs/ppscore】T4
8080labs.com 的弗洛里安
****简讯:如果您想了解更多关于 PPS 和我们其他即将推出的数据科学项目和工具的信息,您可以 订阅此处 。我们不会写付费产品,你可以随时取消订阅,很遗憾我们不得不提到这一点,我们永远不会放弃你的电子邮件。
原载于 2020 年 4 月 23 日 https://8080labs.com。****
上涨布伦特 2020。伦敦文化区 2020 推特分析
分析 3000 条关于伦敦文化区 2020 开幕活动 RISE 的推文
2020 年 1 月 18 日星期六,伦敦西北部的布伦特区举办了伦敦文化区 2020 庆祝活动。布伦特区是第二个伦敦文化区,第一个是沃尔瑟姆森林区,赢得了伦敦市长的竞标。
伦敦文化区项目的目标是“将社区聚集在一起,庆祝整个伦敦的文化多样性”。市长以及私人和企业合作伙伴提供资金,促进为期一年的艺术和文化事件和活动方案。这是一个很棒的倡议,作为一个伦敦人,我很自豪!
今年布伦特 2020 的开幕活动是,由左撇子舞蹈团编排的长达一小时的表演。去年,我对文化区 2019 年的开幕活动做了一个非常类似的分析,名为 欢迎来到森林 ,你可以在这里阅读。与去年不同的是,今年我实际上参加了开幕式,度过了一段美好而愉快的时光,并拍了一些照片,在这篇博文中分享😊
这篇文章的目的是使用 Twitter 数据来了解事件的涨落,并应用机器学习和自然语言处理技术来阐明社会价值和文化价值。通过分析参加 RISE 的用户的推文,我们能够深入了解该活动是否实现了伦敦文化区的目标。
让我们试一试!请滚动查看分析。希望你喜欢。
这张照片是我用索尼 a6600 拍的
数据和方法
与去年的开幕式不同,这次活动没有专门的标签。相反,我收集了所有包含#Brent2020 计划官方标签的推文,以及提到@LBOC2020 的推文,这是 Brent2020 的推特账号。在事件发生时,我使用 Twitter API 收集了 2020 年 1 月 14 日至 1 月 21 日之间总共 3000 条推文。需要注意的是,我只收集了包含#Brent2020 或@ LBOC2020 当然,有许多关于崛起的推文不包含这些搜索词。
在收集了推文之后,我执行了一系列高级统计和机器学习自然语言处理技术,以帮助我理解该事件的社会和文化价值。具体来说,我使用了谷歌云自然语言 API 来计算每条推文的情感,然后我使用了 gensim 库的 Word2Vec 模型来对推文的整个语料库进行语义分析。
我以各种角色处理过艺术和文化的经济、社会和文化 价值测量:作为 UCL Bartlett 高级空间分析中心
的文化数据科学家和研究员;担任全球首家致力于艺术与文化的数据科学咨询机构cultureincities总监;关于下一个英国文化城市的技术参考小组,考文垂 2021;最重要的是,作为 2019 年伦敦文化区的一部分,他领导了沃尔瑟姆森林委员会的数据科学研究。
正如英国社会价值所描述的,“社会价值是人们对他们在生活中经历的变化的相对重要性的量化”。“崛起”是当地居民对布伦特历史和文化的一种依恋。然而,正如 Geoff Mulgan 指出的,社会价值很难衡量。尽管这篇文章没有使用 Mulgan 建议的健壮的方法学技术——很大程度上是因为它们昂贵且耗时——在这里我向 NLP 提供了一个有趣的方法来尝试捕捉 RISE 的参与者感受到的体验。
这张照片是我用索尼 a6600 拍的
夜晚的概观
下面是一张图,用我那天晚上拍的照片展示了这件事是如何在 Twitter 上展开的。 上升 大约在晚上 7 点 15 分开始,这由第一个尖峰说明。然后,在晚上 7 点 54 分,a 里面出现了一个令人惊叹的舞者,在晚上 8 点 03 分,大量彩色粉末被抛向空中,最后,当利维将军在晚上 8 点 36 分出现时,出现了一个高峰!
你可以观看下面由马丁·弗朗西斯制作的酷视频,他更详细地记录了那个夜晚!
自然语言处理
在活动当天,共有 741 名独立用户发了推文,一周有 876 名用户发了推文。如果我们更深入地研究文本,我们就能够根据人们在推文中使用的语言来分析他们对事件的反应。自然语言处理(NLP)提供了一种创新的方法,使用机器学习来分析文本的情感和语义结构,帮助我们得出结论。
每条推文的情绪是使用谷歌的云 NLP API 计算的。下面的条形图显示了七天期间推文的总频率和每天推文的平均情绪,其中-1 表示非常消极的情绪,+1 表示非常积极的情绪。我们看到,在活动前几天,推文的情绪徘徊在 0.42 左右,在活动当天下降到 0.36,然后在活动后两天急剧上升到 0.49 和 0.57 的非常强烈的情绪。总体而言,全天上涨的平均情绪为 0.57。
语义分析
为了从 tweets 中获得更细致的文本理解,我进行了语义分析。在这一步,从分析中删除所有转发是很重要的,因为它们会产生重复的推文,因此在分析文本时会产生不必要的噪音。
Word2Vec 是一个神经语言机器学习模型,它将大量文本(在这种情况下,来自 3000 条推文的文本)作为输入,并输出一个向量空间,通常有数百个维度,每个唯一的单词对应于空间中的一个向量——单词嵌入。
具体来说,空间中距离较近的物体意味着它们是相似的。最近邻是来自 Word2Vec 模型的少数几个基于余弦度量相似性得分与“ Brent ”最相似的单词。下面的散点图显示了“布伦特”的最近邻居。
与 Brent 、、【familyfriendly】、、、、、【社区】、【骄傲】、等词非常接近的还有、、、【欢庆】、等词也在中出现。word 2 vec 模型的结果非常积极,因为这些词与伦敦文化区的总体目标紧密相关,即“将社区聚集在一起,庆祝伦敦的文化多样性”。这项发现从统计学上证明,这些词最接近人们在推特上描述他们的经历时描述的的方式,因此可以表明社会价值。**
这张照片是我用索尼 a6600 拍的
结论
自然语言处理提供了一种创新的方法来分析文本数据,以揭示和说明人们在推特上谈论某个事件时的感受。这项研究的发现表明,有用的描述性词语是从推特数据中提取出来的,以证明的崛起展示了社会价值。对于任何评估研究来说,拥有一种可量化和定量的方法来衡量诸如社会和文化价值之类的东西现在是至关重要的,这将使文化机构有别于它们的同行。
然而,应该注意的是,NLP 并不是一种完美或完整的技术。此外,只分析社交媒体数据也有问题。事实上,在上涨事件后的一周内,许多推文都被转发了。更准确的研究当然包括实地调查收集和访谈,这些问题的答案仍然可以使用 NLP 进行分析。
这张照片是我用索尼 a6600 拍的
伦敦文化区的最大使命之一是将社区聚集在一起,庆祝伦敦的文化多样性,从而创造社会和文化价值。重要的是能够在某种程度上定量地捕捉和展示这种价值,以便这些发现可以用于利用像这样的计划的重要性。
在接下来的 12 个月里,我将跟踪整个项目,看看文化数据科学如何让我们更深入地了解这个项目。还有巨大的潜力来进一步挖掘推文!
祝贺布伦特取得如此重大的事件和成就,并祝伦敦文化区今年剩余时间一切顺利!
谢谢,
Vishal
Vishal 是一名文化数据科学家,也是伦敦 UCL 学院的研究生。他对城市文化的经济和社会影响感兴趣。你可以在Twitter或者LinkedIn上与他取得联系。在insta gram或他的 网站 上看到更多 Vishal 的作品。
现代自然语言处理的兴起和可解释性的需要!
现代 NLP 在可分析性、可理解性、透明性、可解释性和脆弱性方面的能力和挑战。
在embi be(AI 学习成果平台),我们正在利用现代自然语言处理来解决诸如内容摄取、知识图完成、智能元标记、问题生成、问题回答、概念总结、学生对话助手、白话学术翻译、描述性答案评估等问题。将现代 NLP 应用于现实世界的应用需要可解释性,以使系统更加透明、可解释和健壮。让我们看看现代自然语言处理的兴起和可解释性的需要!
现代 NLP 处于计算语言学的前沿,它涉及自然语言的计算建模。
可解释性:太阳+雨= >反射、折射和色散= >彩虹。(图片由胡炬雄在 Unsplash 上拍摄)
乔姆斯基在 20 世纪 50 年代对计算语言学潜力的理解,特别是对那些统计模型的理论基础的理解,有点类似于爱因斯坦对量子物理的反应,【上帝不掷骰子】。这些是世界见证另类理论兴起的关键时刻。然而,无论如何,乔姆斯基为语言学理论奠定的基础仍然是相关的,并有助于计算语言学的发展、分析和理解。
的确,已经有很多工作试图将统计模型应用于各种语言问题。我认为有一些成功,但也有很多失败。有一个成功的概念……我认为这在科学史上是新颖的。它将成功解释为逼近未分析的数据。”—诺姆·乔姆斯基
他提到,成功的概念不是成功。好吧,缺陷可能是理论基础,但从经验上来说,它可以被认为是“可解释性”,这说明了这些计算模型的可分析性、透明性、可问责性和可解释性。
计算语言学的主要进步归功于三个后续阶段:统计建模、经典机器学习和深度学习。这些阶段的可解释性越来越复杂。
统计建模处理数据的统计分析和推断,并以机器学习的形式获得预测能力。使用机器学习解决问题有三个重要方面,
- 设计输入要素。
- 派生特征表示。
- 架构模型内部。
经典的 ML 技术总是给人一种控制的感觉,因为特性是明确指定的,而且大部分是由人类直觉驱动的。过去本质上是聚集的和统计的特征表示也在可解释性的范围内,即基于 Tf-Idf 的向量表示等。像决策树、逻辑回归、支持向量机或其他参数模型这样的 ML 模型也很容易推理。这些模型的扩展变得复杂,因为使用了非线性内核、集成、boosting 等技术来进一步提高性能。然而,仍然有可能理解模型的内部结构。
为提高命名实体识别、情感分析、分类等经典自然语言处理任务的性能所做的持续努力,以及不断增加越来越复杂的任务,如问答、摘要、机器翻译等,已经引起了研究界越来越多的关注。
现代 NLP 的兴起要归功于一个简单模型——感知器的进化。随着深度神经网络的出现,感知机的扩展不仅仅是集成或增强等技术的二阶扩展,而是指数级扩展,如果不是渐近扩展的话。
“我深信,在我们的有生之年,机器能够并且将会思考。”—奥利弗·塞尔弗里奇(思考机器— 1961)。
回顾微小的感知机转变为深度学习海啸的历程,将标志着几个重要的里程碑。举几个例子,1958 年感知器的诞生与 20 世纪 60 年代“思维机器”的研究远见相结合,随后是 20 世纪 80 年代反向传播的发明,以及 21 世纪 10 年代初数据激增与超级计算能力的结合。所有这些都加剧了数百万个感知机之间相互作用的化学反应,从而导致了深度学习和现代 NLP 的兴起。
自然地,深度学习让计算语言学重获新生;使用神经机制学习的潜在统计模式给出了令人难以置信的表现。只是为了加强,在某些定义良好的 NLP 任务上,人类基线的表现优于深度学习模型,这些任务的复杂性逐年增加。图像的合成性质使得卷积神经网络获得了巨大的成功,而自然语言不同于图像,因为它不仅具有合成依赖性,还具有顺序状态。递归神经网络和长短期记忆(LSTM)网络超过了现有技术水平,最近,注意力机制在新型变压器方面取得了前所未有的成功。
现代 NLP 的关键成功还归功于自我监督的预训练目标,以学习上下文嵌入和将学习转移到下游特定任务模型的能力。自我监督的预训练目标已经放弃了对大规模标记数据的需求。另一方面,迁移学习已经放弃了巨大的计算成本的需要。因此,我们可以看到复杂模型的指数增长。
图一。自然语言处理模型复杂性的指数增长(图片:Turning-NLG 8)
那又怎样?
- 深度学习使得特征工程变得多余,因此灭绝了!
- 令牌的底层表示变得密集而复杂
- 深度神经网络复杂架构的内部变得难以理解。
因此,我们不能直接强调决策是如何做出的,什么特征是重要的,或者因果关系来自哪里?现代自然语言处理的成功扩大了可解释性的挑战。
可解释性在领域采用中起着关键的作用,它也为现实世界的应用建立了信心。我们可以将正在进行的研究工作集中在以下问题中来解释神经 NLP 模型:
- 语言学知识是习得的还是忽略的?
- 为什么模型会以这种方式工作?
- 我们能解释模型预测吗?
- 什么使得 NLP 模型易受攻击?
- 知识图如何推进现代 NLP 及其可解释性?
让我们深入了解这些问题的含义。
- 语言知识:忽略还是习得?
图二。句子中的语言知识
语言学,研究语言及其结构,包括语法、句法和语音学等。对人类来说很直观的是,除非系统能够学习语言成分,否则理解、推理和生成自然语言的能力是不可能的。在经典的自然语言处理中,诸如词性标注、命名实体识别、依存关系树、主谓一致、共指消解等语言特征是使用规则驱动或统计学习方法获得的。深度神经网络模型,如 RNNs、LSTMs、Transformers 等,不需要这些手工制作的功能,但仍然能够在某些明确定义的现实世界任务中表现出色,如分类、语义分析、问题回答、摘要、文本生成等。所以,要回答的问题是“ 现代 NLP 模型 ”学到了哪些(如果有的话)语言学知识。
- 为什么模型会以这种方式工作?
*黑盒系统有利于模块化和集成,但系统需要透明才能分析和改进。透明度是可解释性的一个关键支柱。**“模型理解”*是一个利基领域,处理模型的内部。这需要详细分析给定 dnn 中的每一层模块学到了什么,它们如何相互作用,从而有助于模型决策。
图三。伯特模型中不同层次的注意力是如何在处理一个特定的表征时注意其他表征的。
基本上,一个模型的学习如何归因于它的构建模块或底层机制?对模型如何工作的更深入的理解将促进可解释性,并打开进一步改进系统的机会。例如,注意力机制是驱动最先进的 LSTMs 或变形金刚模型成功回家的关键思想。“在自然语言处理模型中,注意力是如何促进学习的?” (即将推出) 倒要研究得更深一些。
- 预测可能还行,能解释一下吗?
好吧,知道什么语言知识是通过模型学习的,以及底层机制如何使这些 NLP 模型的学习成为可能是 NLP 可解释性的基础。最重要的是将*”转向对 NLP 模型的可信和忠实的解释?**【即将推出】 这需要深入研究输入记号如何影响模型决策,从而将预测归因于记号,并推导记号的重要性。我们如何从这些重要的记号中产生解释呢?这些生成的解释可信吗?或者说,产生忠实解释的最佳方式是什么?这些解释能在理解一个模型的潜在稳健性方面发挥积极作用吗?这是一个活跃的研究领域,最近已经取得了很多进展。*
- 在成功的背景下,是什么让现代 NLP 模型变得脆弱?
现代 NLP 在现实世界的应用中取得了适度的进展,例如对话聊天机器人、实时翻译、自动问答、仇恨言论或假新闻检测。是否有可能出于恶意入侵这些模型,比如使假新闻合法化,或者在无法访问训练数据的情况下窃取模型?
图 5:对抗性攻击示例
一个透明的、可解释的和可解释的系统将更好地理解*“现代 NLP 漏洞的挑战和缓解”(即将推出)。*在这里,可以理解敌对攻击的风险、潜在的偏见、不可靠的评估标准以及提取模型的学习状态的可能性,并且可以采取措施来减轻这些风险。
- 知识图谱呢?它能进一步推进现代自然语言处理和可解释性吗?
传统上,知识图,即以图的形式表示的结构化信息,是基于特定领域用例的信息检索系统的核心。主要是因为知识图可以由专家确定性地构建,更容易理解,无缝集成,对特定用例有效,并且易于解释。因此,依赖于知识图的系统很容易在不同的领域被采用。现代 NLP 出现之前的检索系统主要是在知识图的基础上开发的。
图六。知识注入式学习(Image:kur uncu等[5])
自我监督学习使现代 NLP 能够学习统计模式,而不用担心专家的干预。这些系统在各种复杂的用例中变得可扩展和强大,但在非常简单的任务中可能会失败,因为简单的事实由于数据中缺乏统计意义而被忽略。这就是为什么,如果知识图可以与现代 NLP 系统集成,它将带来两个世界的最佳效果,使系统变得全面。知识图还可以调整特征的内部表示,使其更有意义。**“面向高级和可解释 NLP 的知识启始”(即将推出)*** 将是未来时代的一个活跃研究领域。*
探索现代 NLP 在上述维度上的限制,可以很好地理解为什么可解释性很重要,挑战是什么,在这些方面取得了什么进展,以及哪些问题仍然存在?虽然我们试图尽可能地广泛,但这绝不是对 NLP 现状的详尽调查。了解一个现代的 NLP 将如何在未来变得可分析、透明、健壮、可靠、可解释和安全是一件有趣的事情。另一方面,将 KG 和 NLP 结合起来也同样令人着迷,这不仅有助于 NLP 的可解释性,还能提高其在教育、医疗、农业等领域的应用。
我要感谢所有合作者为发表本文所做的努力,特别是Amit Sheth教授的评论和反馈,以及Aditi Avasthi的支持。
参考文献
1曼宁光盘。计算语言学和深度学习,麻省理工学院出版社 2015 年
[2]诺维格 P. 论乔姆斯基与统计学习的两种文化,施普林格 2017
3贝尔基诺夫和格拉斯。神经语言处理中的分析方法:调查,麻省理工学院出版社 2019 年
[4]曼宁和舒茨。统计自然语言处理基础,1999
[5] 库尔顺库、高尔、谢斯、维克拉马拉奇和亚达夫。知识注入深度学习,ACM 2020
6 Arrieta 等人.可解释的人工智能(XAI):面向负责任的人工智能的概念、分类法、机遇和挑战,Elsevier,2020 年
[7]鲁梅尔哈特、辛顿和威廉姆斯。通过反向传播错误学习表征,自然 1986
8图灵-nlg:微软的 170 亿参数语言模型,微软研究博客,2020 年
【9】张盛阿兹米李。对自然语言处理中深度学习模型的对抗性攻击:一项调查,ACM 2020
[10] 克拉克,坎德尔瓦尔,列夫 y 和曼宁。伯特在看什么?对 BERT 注意力的分析,ACL Workshop BlackboxNLP 2019
11 里贝罗、辛格和盖斯特林。"我为什么要相信你?"解释任何分类的预测
12柯勒·本德。“攀登 NLU:数据时代的意义、形式和理解”,ACL 2020
机器学习中规范栈的兴起
一个占主导地位的新软件栈将如何解锁下一代尖端人工智能应用
(来源:图片由作者/Shutterstock 提供)
随着每一代计算技术的出现,都会出现一个占主导地位的新软件或硬件堆栈,扫除竞争对手,将一项新兴技术推向主流。
我称之为规范堆栈(CS) 。
想想 20 世纪 80 年代和 90 年代的 WinTel 王朝,95%的个人电脑都装有“Intel inside”认为灯和的意思是栈。想想亚马逊的 S3 正在成为一个近乎通用的存储 API。想想云编排的 Kubernetes 和 Docker 。
当组织寻求解决同样具有超级挑战性的问题时,堆栈从成千上万的其他解决方案中脱颖而出。在任何复杂系统的开始阶段,问题都是很多的。一个项目的进展停滞阻碍了其他几十个项目的进展。但是当人们完全解决了一个问题,它打开了通向大量新解决方案的大门。
在互联网的早期,工程师们同时致力于解决数以千计的新问题,每个解决方案都建立在最后一个之上。一旦有人发明了 SSL,你就可以对信息进行加密传输。一旦你有了能做 SSL 的 Netscape 浏览器,你现在就可以开始从事电子商务了。每个解决方案都解开了一个新的难题,让人们可以构建越来越复杂的应用程序。
随着越来越多的碎片聚集在一起,网络效应开始发挥作用。每一个上线的节点都让网络越来越有价值。突然,当你增加了足够多的人时,你就达到了一个“ ”的临界点 ”,采用会以指数 S 曲线快速上升。一旦它加速足够快,你就达到了临界质量,采用就变得不可阻挡。
当 CS 形成时,它让开发人员“向上移动”以解决更有趣的问题。在过去的几十年里,随着越来越好的栈出现,我们看到传统软件开发达到了令人眩晕的新高度。在 20 世纪 80 年代和 90 年代,曾经需要一小群开发人员编写一个界面丑陋的数据库,为几千名企业用户服务。
WhatsApp 只用了 35 名工程师就拥有了 4 . 5 亿用户。
这是完全有效的网络效应,任何团队都可以利用来自其他几十个团队的尖端 ide、API 和库,以极快的速度交付创新。
我们可以用著名的技术采用曲线来追踪 CS 的形成。
(来源:维基共享资源)
在他 1962 年的著作《创新的扩散》中,社会学家埃弗雷特·罗杰斯向我们展示了在采用新技术时,人和企业分成五个不同的群体。杰弗里·摩尔在他的商业畅销书《跨越鸿沟》中建立了这个想法。
想想智能手机。我跑出去拿到了第一部苹果 iPhone,这让我处于早期采用者阶段。我从中受益,因为我成功地保持了相同的无限手机合约 15 年,这是在所有手机公司淘汰它们之后很久。但我也深受其害,因为早期的手机没有我们今天这么多的应用程序,因为网络效应没有发挥作用。最终,早期的大多数加入了智能手机革命,不久我们就有了像 Instagram、AirBnB、WhatsApp 和优步这样的大型应用程序,它们利用了你口袋里的智能手机操作系统、GPS 和互联网的标准堆栈。现在智能手机无处不在,几乎每个人都有一部,甚至在世界上最遥远的地方。
如果你知道有人还在使用翻盖手机,他们是落后者的一部分。
现在,计算机领域正在发生一些新的事情。软件的本质正在改变。我们已经非常擅长构建手工编码的软件,以至于我们已经达到了它所能做的上限。
直到最近,编码人员手工制作他们软件的所有逻辑。这对于设计电子表格的界面非常有效,但是对于在图片中识别猫或者在手机上识别你的声音就不太好了。这就是为什么在过去的十年里,一种新的软件出现了。
机器学习。
我们训练机器,让它们自己学习规则,而不是手工编写规则。
我们需要机器学习来解决以前无法解决的问题,比如自动驾驶的汽车,检测欺诈,识别人脸,驾驶无人机,理解自然语言等等。虽然机器学习与传统的软件开发有很多共同之处,但它也完全不同,它需要不同的规范堆栈。
机器学习栈
ML 开发周期有多个独特的步骤,比如训练和超参数优化,这些步骤与传统的软件开发方式完全不匹配。
研究人员和大型科技公司开发了许多最好的算法,以及将这些算法训练成模型并部署到生产中所需的工具。随着大科技解决了生产应用程序中创建、训练和服务模型的问题,越来越多的工具进入了开源项目,这推动了人工智能革命的发展。随着越来越多的团队获得这些工具,我们终于开始看到“人工智能的民主化”
随着尘埃落定,我们现在可以看到机器学习规范堆栈(MLCS)** 形成的早期轮廓。我们也可以开始清楚地看到**机器学习生命周期(MLL)的主要阶段,在现实世界中制作前沿模型所需的步骤。很多时候,公司甚至看不到阶段。这就是为什么你会看到带有 45 种机器学习的 NASCAR 幻灯片的文章。
机器学习不会有 45 类。
随着该技术继续发展成为下一个十年的发电站技术,将会有三个或四个主要的。
机器学习生命周期
MLL 有四个关键阶段:
- 数据采集和转换
- 试验、培训、调整和测试
- 生产、部署和推理
- 监控、审计、管理和再培训
(来源:图片由作者提供)
这个过程的大部分仍然是难以置信的手工操作。我们仍然随处可见数据科学家编写网页抓取器和粘合脚本,从数据库中复制数据,拼凑在一起,从一个地方移动到另一个地方。
这种情况变化很快。
我们已经看到 ML 开发周期中每个阶段的早期竞争者从竞争的混乱中脱颖而出。
数据收集和转换
当团队试图争论他们的数据时,我们看到像Pachyderm这样的先驱通过不可变的写入时复制文件系统大规模提供数据版本控制,该系统面向 Google Cloud Store (GCS)、Amazon S3、Azure Blob Storage 和 Minio 等对象存储。
数据版本控制是 AI/ML 管道独有的东西,也是每个数据科学团队在试图扩展团队以快速将模型交付到生产中时最终遇到的问题之一。
TerminusDB 与 Pachyderm 不同,它提供了一个可扩展的图形数据库,允许 Git 一样的版本控制。虽然 Pachy 侧重于可以放入对象存储的任何类型的文件,但 Terminus 最适合放入数据库的数据。
一旦公司拥有了这些数据,像 Superb AI 这样的 SaaS 服务就可以帮助数据科学家快速标记大量数据,而不必全部手动完成,这是将数据传递给数据饥渴的神经网络的关键组件。 YData 还可以帮助数据科学团队快速标记、清理和构建数据集,甚至生成合成数据集,为训练、调整和测试阶段增加数据。
实验、培训、调整和测试
在所有的数据都被清理和标记后,像 maiot 核心引擎 或 Allegro AI 这样的平台及其 Trains 框架形成了一个顺畅的实验和训练管道。
像【TFX】和 Horovod 这样的开源库正在成为跨 GPU 和 TPU 快速扩展训练的标准,但这些库很可能会被纳入更高级的训练、数据和可视化系统,如 Determined AI 。Determined AI 利用 Horovod 在 GPU 之间快速分割和扩展训练工作,同时还进行超参数调整,并在全面的达尔文战争中测试许多不同的算法变体。这可不是小事,因为几年前,在多个 GPU 上并行运行一个算法还是一个手动过程。我们也看到像 Hyperopt 这样的库用于快速超参数调整和搜索。
如果这些人工智能架构是神经网络,那么该团队几乎肯定会在两个基本平台中的一个设计这个网络,脸书支持的【py torch】,或者谷歌支持的 Tensorflow 。这些强大的平台创造了一场两匹马的比赛,许多其他框架曾经在这里比赛,比如 MXnet 和 Chainer。
当然,不是每个团队都是从零开始开发算法和模型的。许多团队可能永远不需要超越最先进的水平。他们可以抓住一个顶级模型,用迁移学习来训练它,以使他们的模型适应他们的特定数据集,并在产品推荐、自动图像标记或情感分析等已知问题上提供令人难以置信的性能。
期待看到越来越多的训练有素的系统嵌入到各地的应用中。我们已经看到了经过充分训练的变形金刚模型的出现,它们有像 拥抱脸的变形金刚 这样的库,它们不会是最后一个。
我们看到许多公司和组织试图成为预训练模型的“中心”,如 Pytorch Hub 和 Tensorflow Hub。像 Algorithmia 这样的公司希望将 SaaS API 前端交付给预训练的模型,而不是让公司下载他们自己的模型版本,他们很有可能成为 GitHub,用于训练模型访问并大规模运行那些处理器密集型模型。在未来几年,有人将开发每个人都标准化的模型库,也许是类似于 ModelHub 的东西,但现在它是任何人的游戏。
当然,所有这些库、超参数搜索和训练运行都需要一个引擎来驱动,这就是管道平台发挥作用的地方。
生产、部署和推理
管道平台构成了 ML 规范堆栈的基石。
管道引擎可能会吸收人工智能/人工智能难题的许多其他部分,形成一个完整的端到端系统,用于选择、训练、测试、部署和服务人工智能模型。
管道桂冠有三个主要竞争者:
- Kubeflow
- MLFlow
- 厚皮动物
厚皮动物是管道系统中最简单明了的。它使用定义良好的 JSON 或 YAML 定义来调用容器,以便在模型通过 ML 生命周期时对其进行转换、训练和跟踪。它是数据驱动的,因此每次数据发生变化时,它都可以使用数据的状态来驱动管道前进。它的管道系统也可以轻松地向其他管道系统(如 Kubeflow 或 MLFlow)提供数据沿袭。
Kubeflow 背靠谷歌等。它正在发展成为一个覆盖广阔土地的强大生态系统。它的主要功能是作为一个编排引擎,利用 Kubernetes 的力量来快速扩展容器,但它仍然是一个庞大的项目,厨房里有很多厨师,它有成为机器学习开放堆栈的危险,这是一个伟大的想法,但由于其复杂性,从未得到广泛采用。
最后一个大的竞争者是 MLFlow ,由 Databricks 支持,这是一家专门从事 Spark 传统统计分析的公司。MLFlow 得到了为其代码库做出贡献的大公司的大力支持。Kubeflow 来自于将许多不同的不同组件集成到一个统一架构中的理念,而 MLFLow 则提供了一个清晰、明确、有目的的简单设计,因为它来自于一家公司打造端到端管道的愿望。
许多公司和组织使用 气流 用于 AI/ML 管道,但它不是专门为 AI 而建的。它是由 AirBnB 创建的,用于管理任何类型软件中的复杂工作流程。它有一个庞大的生态系统和安装的用户群,但它的主要缺点是,它不是专门为人工智能工作流构建的,它 100%专注于 Python,不允许任何简单的方法来插入其他语言。从长远来看,可能的赢家将是一个纯粹的人工智能/人工智能焦点,它不会局限于单一的语言或框架。
在寻找行业标准管道引擎的过程中,你不会看到类似亚马逊的 SageMaker 的东西。像 SageMaker 这样的产品将永远赚钱,所有加入亚马逊的公司都将为这一特权付费,但 SageMaker 无可救药地被锁定在单一云上。这意味着它永远不会成为 CS 的一部分,除非亚马逊决定向其他云开放它。
另一方面,我们已经看到了像algorithm ia的 MLOps 栈这样的闭源管道系统的良好采用,因为它没有被锁定,可以在任何地方运行,不像它的亚马逊竞争对手。我们还看到与许多其他堆栈集成良好的管道,如 Neu.ro ,开始获得真正的牵引力,因为它们像乐高积木一样与其他解决方案相结合。最后, Allegro AI 的 企业产品在多个类别的管道中提供服务,并获得了很大的牵引力,国防领域的也是如此。
在争夺管道霸权的竞赛中挑选赢家还为时过早,但这场竞赛现在正在升温。风险资本正在涌入,因为如果你创造了未来推动机器学习的基础设施,你对那里的每一个公司和项目都是有用的。
所有这些公司和项目都帮助数据科学家快速创建工作模型。现在,我们必须将它部署到生产环境中,这样它才能开始工作。这就是模型服务、监控和可解释性框架出现的地方。
谢顿 部署 已经迅速成为 ML 在这个星球上的顶级模型服务系统之一。Algorithmia 的企业基础设施堆栈也在这一领域发挥作用,并在规模上提供强大的模型服务。他们在快速生产和部署模型方面与 Algorithmia 和他们的企业 ML 堆栈竞争。
部署系统运行 A/B 和 canary 测试来验证模型在离开开发并投入生产后是否真的如您所愿。这让你可以对一小部分用户进行测试,以确保它能正常工作。它还淘汰了旧型号,但将它们存档,以便在出现问题时快速重新部署。
监测、审计、管理和再培训
最后,我们有一个现场制作的 AI 应用程序。它在现实世界中工作,为客户服务。现在,我们需要在 AI/ML 流程的这个阶段对其进行监控。
我们有许多框架已经将机器学习整合到他们的监控应用程序中,如 Splunk ,但我们几乎没有监控人工智能本身的应用程序。在未来几年,越来越多的日志分析工具和实时监控框架将把 ML 融入其中。他们将进行异常检测和智能的自动化事件管理和解决方案,在任何人接触系统之前解决问题,或者向人类工程师建议可能的解决方案,如 Red Hat Insights 。
但是我们也需要对人工智能本身进行监控。
生产 AI 团队需要知道应用程序是否仍然表现良好?像 COVID 这样的重大黑天鹅事件是否破坏了你的供应链管理模式,就像它对许多生产人工智能模型所做的那样?是漂移吗?机器是否将其做出的每一个决定都记录到分布式数据库中,以便以后进行审计和取证?
各地政府即将出台的立法将要求对这些应用进行越来越多的监控。当事情出错时,他们希望得到解释,你和你的企业以及法律体系也是如此。当的自动驾驶汽车测试在亚利桑那州杀死一名妇女和的安全司机刚刚被指控过失杀人时,优步面临着激烈的调查,所以监控和理解你的人工智能的每个方面的风险非常非常高。公司需要他们在毁掉一个人的生活或底线之前到位。
谢顿 不在场证明 和 提琴手 框架可以帮助传递那种可解释性。这就是我们询问一个模型来理解它为什么做决定的地方。这有助于我们揭开黑盒。我们可能会有一个卷积神经网络告诉我们它集中在哪些像素上,以告诉我们图片包含一只狗,以防它开始错误地标记东西。Fiddler 的框架在这两者中走得最远,它将监控和可解释性结合到一个堆栈中。
我们还将看到对人工智能系统的直接攻击大幅增加。即使您设法在这些系统投入生产时保护它们,它们仍然会受到利用其逻辑和推理漏洞的新型攻击。这是地球上任何一个安全团队过去都没有处理过的事情。错误和漏洞可能会使生产 IT 系统瘫痪,但是完全有可能出现一个“没有错误”的人工智能,它仍然会犯一些错误,让攻击者可以利用这些错误。
脸书建立了一个人工智能红队来阻止对 Instagram 的攻击,当聪明的用户使用图像中微小的,难以察觉的图案来欺骗裸体探测器时。几个月前,我写了关于建立人工智能红队来阻止问题的文章,现在它们已经成为现实,各地的公司都在竞相建立它们。
谢顿的 不在场证明检测 用于发现神经网络上的对抗性攻击,它们将加入任何红队的工具包。
新的堆栈现在
在任何新的领域发展一个规范的堆栈都需要时间。在它发展并释放出新的创新浪潮之前,任何人都很难看清它的走向。大多数人不容易看到未来。他们只能看到现在正在发生的事情。当当前的问题没有解决方案时,他们认为我们永远也不会有解决方案。
但只要有足够的时间、兴趣和投资,总会有解决的办法。
人工智能将触及并改变地球上的每一个行业和国家,其影响力超过互联网本身。
当我们解决了一个问题,它就开启了新的可能性。最终,当你解决了足够多的问题,你就有了一个网络效应,将新技术推向主流。人工智能已经开始感受到网络效应的力量,进展越来越快。
我们很快就会将智能融入这个星球上的每一个应用、每一个设备、每一辆车和每一件产品。
随着大量的投资,真正的解决方案和真正的尖端产品的开发,这是一场完美的风暴,将使人工智能民主化,并向全世界提供它。
而正是规范堆栈将使它成为现实。
###########################################
作者 【工程师】 亲博者播客我还运营了 实用人工智能伦理联盟 和 人工智能基础设施联盟 ,这两个开放社区帮助将规范栈带入现实,并确保人工智能为我们所有人工作。**
###########################################
这篇文章包括亚马逊的会员链接。
###########################################
数据战略家的崛起第二部分
什么是数据战略家,他们的技能是什么?
图片由安德里亚斯亲切
在系列的第二篇博客数据战略家的崛起 ( 第一部分)中,伯颜·安杰洛夫和马杰拉·克拉克提出了一个新的维恩图和思考——什么是数据战略家?定义和揭示新角色所需的技能是什么?
让我们面对现实吧——数据科学博客充斥着描述这十年来最受欢迎的职业之一的终极技能集的维恩图,但当我们进入 2020 年时,我们是否在优化数据人才的管理?更具体地说,我们是否正在使用数据能力和人工智能(AI)来产生重大的商业影响?随着数据经济的发展,这正是许多企业目前在问自己的问题。
商界人士知道,远见卓识和良好的商业策略对于保持竞争地位至关重要。数据策略通常是由寻求业务领导支持的业务经理制定的。另一方面,数据科学家和数据工程师通常继续与 IT 或数字运营保持组织一致,即使数据战略和愿景将由业务人员制定。因此,数据专业人员和业务经理/领导之间需要一个翻译角色,这种需求目前正在增长。
在一个充满独角兽人才的理想世界中,可以提议扩大数据科学家和工程师所需的技能集,以包括业务专业知识、领域专业知识和高度通用的通信技能。然而,经验丰富的商业领袖知道,商业决策受益于多元化团队形式的多学科和跨学科见解。团队越多样化,集体智慧越高。在伯颜·安杰洛夫的上一篇博客— 数据战略家的崛起第一部分(链接)中,伯颜提出了一个令人信服的案例,数据战略家的角色是一个非常有用的角色,可以将数据科学与商业案例联系起来。
在那篇博客的后续文章中,我们在 DAIN 工作室的数据策略师集思广益,设计了一种交叉方法来开发和列出专业领域及其相关技能,这些领域定义了数据策略师所需的独特技能。我们通过为下图中的数据战略家提出以下维恩图来补充维恩图和数据文献。
数据战略家的维恩图
这三个圆圈代表了数据战略家最重要的知识领域;除了数据和技术之外,还有商业、通信。
业务技能对于数据策略师来说非常重要,因为他们需要将数据用例与业务目标和操作联系起来。数据和技术知识领域在任何数据和人工智能战略的实施中具有明确的作用,然而,区分数据战略家的数据和技术技能和经验非常重要,这与数据工程师的技能和经验有很大不同。更具体地说,数据策略师需要对数据基础设施、框架和数据管理工具有很好的了解,但不需要在设计这些框架和工具方面有丰富的经验或技能。理想情况下,数据策略师需要了解当前技术和数据解决方案的广泛选择,以及如何应用它们来支持业务目标。为了能够有效地将数据和技术概念与业务联系起来并进行翻译,强大的沟通技巧很快成为数据战略家翻译角色中最关键的技能之一。
为了进一步阐述建议的数据战略家文氏图,我们在与数据战略家相关的三个知识领域中分别提出了以下顶级技能:
业务领域:
- **业务战略和用例知识:**企业越来越关注数据的战略性使用,以提高组织绩效。因此,对于战略家来说,拥有一个来自不同行业和处于不同数据成熟度阶段的组织的成功(和不成功)用例的库,以支持决策和战略建议是有利的。当在公司内追求更高水平的数据和人工智能成熟度时,收益应该总是大于成本,数据策略师需要广泛的用例库来证明数据投资的潜在价值。
- **跨职能和跨领域的业务翻译技能:**端到端(E2E)解决方案需要跨职能和跨领域的知识和技能,以便能够概念化和向团队翻译“大画面”。数据策略师需要能够看到组织内不同的业务领域和功能如何合作来解决问题并创新新产品和服务。例如,当孤立的领域专家可能不知道其他孤立的领域专家正在使用的数据和解决方案时,这种知识需要应用,常常错过可重用数据集的有价值的业务洞察力。
- **治理和数据协议:**保护个人数据和认识到网络安全重要性的最新立法和法规要求有新的协议,需要在业务职能部门内进行管理。此外,自动化和最新的技术发展(例如 5G、云等)创造了新的工作方式。数据策略师需要了解他们的组织数据协议以及保护和保障数据的管辖法律。不良的数据治理可能会对整体业务战略产生重大影响。
- **项目管理:**项目管理是一项必不可少的业务技能。对于一个数据战略家来说,不同项目管理实践的知识,从 scrum 到瀑布,将是有用的,因为许多高级分析项目在被推广到企业范围的行动之前,最初是通过更短的项目/试点方法来构建的。
- **创造力和复杂问题的解决:**计算思维和数据科学改变了我们思考问题和开发商业解决方案的方式。例如,熟悉设计思维、头脑风暴、简化和抽象等方法有助于利用人工智能进行创新,并利用数据科学获得对问题的深刻见解。
- 数据角色的战略性人力资源管理:对于战略家来说,了解数据域中的不同角色(即科学家、工程师、商业智能开发人员和其他人)是什么,他们如何协同工作,以及不同的用例需要什么样的数据专家组合,这一点非常重要。
- **预见:**通常被称为 21 世纪最重要的商业和领导技能之一,预见是使用不同的战略方法来扫描和寻找演进路径,为未来进行规划。数字转型和技术一方面创造了一个正在经历快速变化的商业环境。通过机器学习获得的大量自动化数据也提供了部署预测分析以获得未来洞察力的新方法。
数据和技术领域:
- 数据资产管理 —与任何业务战略家一样,理解并增加业务资产的价值是取得业绩的先决条件。数据资产管理(DAM)是数据策略师的一项关键技能,因为数据策略师的建议和意见的结果、质量与数据质量越来越密切相关。因此,数据策略师需要了解在组织内收集、管理和管理数据价值的最佳实践。此外,了解什么方法适合于什么类型的数据也很重要(即计算机视觉与文本、数据 360)。例如,当处理大量非结构化数据时,深度学习方法通常更有用。
- 机器学习方法的一般知识 —虽然策略师能够构建和部署机器学习(ML)模型当然不是必需的,但他们对当前可用的不同技术有很好的理解是必不可少的。比如有监督与无监督的方法,回归与分类,深度学习。了解基本的 ML 方法和相关的潜在业务用例以及可以部署这些方法的分析见解,对于维护有效的算法组合具有重要的战略业务意义。
- 数据工程意识 —了解建立可行的数据基础设施和架构的拼图对于支持数据、人工智能和/或数字化转型战略的实施至关重要。在这一点上,数据战略家应该使数据库选择、云提供商和各种开源技术等问题符合业务战略。考虑体系结构和技术的性能与成本效率是决策过程中的关键因素。
- 数据伦理 —现在,机器学习系统正在部署到更关键的行业(如医疗保健和政府等),将伦理渗透到工作的各个方面至关重要。成功的机器学习系统有可推广的结果。要做到这一点,数据必须代表手头的任务。此外,这些数据必须没有偏见——这里,来自一个称为可解释人工智能(xAI)的发展中领域的方法可以应用于系统的不同部分(即,数据收集、模型训练、部署的模型调试)。
通信域:
- 数据可视化 —一张图胜过千言万语,可以使用大量数据非常快速地传达概念。数据可视化是一项强大的技能,可以说服和敬畏企业领导人和经理,并推动变革。
- **倾听技巧:**倾听是翻译角色的另一面。倾听变得越来越重要,因为它对生产力以及管理团队和人们的情绪和反应至关重要。
- 表达技能——对于所有数据驱动的洞察力,当向拥有不同技能组合的业务人员传达复杂的技术概念时,交付非常重要。演示技巧是数据战略家的翻译角色的顶点。例如,与 CEO / C-suite 讨论相同结果时,与上下文相比,数据战略家与数据科学家讨论分析时,在交付和讨论结果时会使用非常不同的翻译语言。
- **辅导和指导技能:**通往高级分析的道路可能是漫长而疲惫的,辅导经理克服障碍和阻力,以及给予经理和他们的团队实施数据战略路线图的勇气和信心,都是非常值得赞赏和重视的。
- **变革管理:**也许是在实施数据战略或任何数字化转型过程中最被低估的技能。一旦数字化转型过程在组织内开始,并且企业领导人了解追求高水平分析成熟度的投资回报,变革就需要伴随着及时和适当的沟通。一个好的变革管理者可以在不断变化的抽象环境中获得信任,并创建一个业务领导者长期致力于的平稳变革过程。变更管理是数据策略师需要的技能,以确保数据策略的有效实施。
对技术通才商务人士的需求仍在增长。支持数据战略家角色需求的技能将技术领域&数据、通信和业务结合在一起。在双边数据战略领域交叉点上,我们有数据和业务架构师,他们精通跨领域数据&技术解决方案,了解跨职能业务流程和目标;业务领域专家是在沟通、业务运营和管理方面有丰富经验的领导者。数据和技术倡导者在技术&数据领域拥有丰富的知识和经验,拥有成熟的翻译技能,能够在适当的参与级别上交流复杂的数据和技术概念。我们认为,数据战略家 unicorn 在所有三个领域内运作,以指导领导者和组织实施高度以数据为中心的业务战略,利用和货币化其数据资产。
注:本文原载于 丹工作室博客 。
鸣谢——除了本文作者之外,数据策略师文氏图也是由 DAIN 工作室的顾问开发的,他们包括海纳·阿尔伯斯曼、埃里卡·格罗恩、妮娜·哈格曼、德克·霍夫曼、阿尔图·胡蒂涅米、詹姆斯·凯尔斯特德、乌拉·克鲁什-莱托宁和琳娜·佩苏。
NBA 的上升趋势:日心说
理解 NBA 进攻中使用的概念。
近年来,以太阳为中心的术语被用作定义首选团队建设方式的趋势。可以理解的是,球队优先考虑聚集明星,让明星成为场上的最终决策者(有些场下也是如此)。回到 2019 年 12 月, 塞斯·帕特诺 为竞技写了一篇文章,阐述球星如何成为各自球队的中锋。他特别调查了年轻的明星,特雷·杨和卢卡·东契奇,以及他们各自的球队,亚特兰大鹰队和达拉斯小牛队。
在这篇文章中,我使用了和 Seth 一样的方法,通过几个指标来评估球员在进攻端的使用情况。在Basketball-Reference.com、NBA.com和pbpstats.com(基于 NBA.com 的详细数据)上有许多统计数据,以探索球员的影响,Seth 估计包括跟踪数据以估计战术使用情况,这对于考虑战术行动是有意义的。
总的用法基本上是由三个部分相互总结而成的。
- 评分用法:
(投篮次数+ 0.44 *罚球次数)/总机会
- 游戏制作用法:
(潜在助攻+罚球助攻)/总机会
- 营业额用途:
失误/总机会
从定义上来说,得分的用法主要是由控球型风格的明星球员组成的,我相信这里有两点需要注意。
我注意到的第一件事是在名单的顶端(得分使用率超过 30.0 的球员),只有休斯顿火箭队有一个以上的球员:詹姆斯·哈登和拉塞尔·维斯特布鲁克,很明显。从天文学的角度来说,把火箭的进攻描述成他们有两个太阳是没有错的。另一方面,在新奥尔良鹈鹕队的情况下,尽管只打了 24 场比赛,锡安·威廉森发现自己在高得分球员名单上。以太阳为中心不是鹈鹕队进攻的最佳术语,至少在过去的一个赛季,因为他们是一个基于使用分布的合作团队。看看他们如何从现在开始发展,以及他们是否能实现预期的飞跃,这将是一件有趣的事情。
休斯顿火箭队和新奥尔良鹈鹕队的使用情况分析
在下面,你可以找到 2019-2020 常规赛得分超过 30.0 的球员名单。
2019-2020 常规赛得分使用排名靠前的球员名单
对于组织进攻的使用,跟踪数据让我们可以看到各种类型的助攻。在 NBA 统计术语表中,二次助攻被定义为*“在接到球后 1 次运球内将球传给投篮的队友”,罚球助攻被定义为“如果球员将球传给在接到球后 1 次运球内造成投篮犯规的球员”*。正如 Seth 已经在他的文章中指出的,这种组织进攻的措施是信任球员发现队友空位(或没有空位)而不管投篮进还是出,并且也考虑到以罚球结束的传球。
2019-2020 常规赛潜在助攻和罚球助攻前 25 名球员
2019-2020 赛季常规赛最佳球员
在这种用法中很少有名字值得一提,尽管他们玩的时间可能是一个小样本。蒂姆·弗雷泽、克里斯·基奥扎和乔丹·麦克劳克林在他们有限的机会中展示了一个真正的组织者,我相信这三名球员在几乎每个 NBA 球队的替补角色中都能在压力下茁壮成长。
由于失误的用法是不言自明的,现在是时候从得分和组织进攻的角度来研究 NBA 中进攻是如何定义的了。
2019-2020 常规赛 NBA 球队使用明细
上表是得分用法和组织进攻用法的综合表示。在每支球队中,我都标记出总使用率最高的球员,并试图了解他们的进攻负荷分布。在塞斯写的文章中,他提到了亚特兰大老鹰队和达拉斯小牛队,以及他们的进攻是如何围绕他们的二年级球员特雷·杨和卢卡·东契奇进行的。常规赛结束后,再一次,可以说两支球队都在走一条相似的路线。有趣的是,东契奇的支持者明显比特蕾·杨多,这可能是一个很好的指标,可以观察亚特兰大在休赛期会选择什么类型的球员,我相信(也希望)他们会通过改善阵容来最大化特蕾(和老鹰)的进攻能力。
亚特兰大老鹰队和达拉斯小牛队的使用明细
由于跟踪数据只能从 2013 年到 2014 年获得,我制作了一个动画,展示了球队如何分配他们的进攻负荷/使用率,从下面可以看出,明星驱动的球队近年来与众不同。
从 2013–2014 年到 2018–2019 年改变团队的使用
在塞斯的文章之后,本·泰勒制作了一个精彩的视频通过回顾这些年来 NBA 进攻的历史发展来审视 NBA 中的日心说概念。他的方法与 Seth 的有点不同,但结论是相似的:NBA 球队用其他威胁包围控球型球员"为他们创造空间,然后惩罚帮助摆脱这些威胁的防守队员"。在下图中,我看了一些明星驱动的球队和他们的进攻负荷,以更好地理解他们的进攻组织。
明星驱动团队中的使用分布示例
Seth 提到了他的作品,即没有一支球员总使用率超过 50%的球队在那个赛季赢得冠军,随着明星驱动的进攻系统的兴起,在未来几年有一个问题需要回答:是否会有以太阳为中心的进攻赢得冠军,或者冠军是合作参与的结果,而不是一个巨大的太阳系?2020 年 NBA 季后赛,特别是总决赛可能是一个很好的起点,可以提取有价值的见解来回答这个问题。
风险叠加:对于人生决策,使用至少一个的概率
生活中充满了决定,但小决定其实很重要。
Riho Kroll 在 Unsplash 上拍摄的照片
生活充满了决定。
无论是流行文化还是传统智慧,都普遍强调个人的重大决定——所谓的十字路口——这是可以理解的。然而,在决定一个人的结果时,一系列更小的日常决定也同样重要——如果不是更重要的话。
本质上,这不是因为较小的日常决定有更多的内在风险,而是因为它们可以更频繁;由于风险的累积,重复事件最终发生不希望的结果的可能性实际上增加了。
假设你认为数字 4 不吉利。如果你掷出六面骰子六次,你掷出至少一个 4 的几率是多少?
- A) (1/6) * (6) = 1 * 100 = 100%
- B) (1/6)⁶ = 0.0000214 * 100 =约 0.00214%
- C) (1/6) = 0.1667 * 100 =约 16.67%
- D) 1-(5/6)⁶ = 0.6651 =约 66.51%
答案是 D) ,这个百分比大概直观上说得通。机会越多,感觉机会就越高。答案中的等式更有意思。
错误的答案
首先,在 A) 中,我们可以直观地感觉到,永远不掷出 4 肯定是有可能的——有人会说不吉利。
B) 不正确;而是计算你连续六次掷出 4 的几率(你有六次机会,每次有六分之一的几率)。不用说,这是非常不可能的,而且在 0.00214%的可能性下,也许你应该考虑宇宙可能试图告诉你什么。
T21 也是错误的,但也许你的头脑先去了那里。可以理解;骰子的每一次滚动都有 1/6 的机会,所以总的机会可能是 1/6。事情是六分之一的机会只适用于一个骰子滚动;有了 6,你就有很多机会拿到一张不需要的 4。
正确答案
D) ,或 66.51%,是正确答案,可能不直观怎么得出那个数。
首先,考虑一下而不是掷出 4 的概率是有帮助的;这样想的话,你有 5/6 的机会获得正面结果,并掷出不同的数字。
这种情况连续发生六次的几率是 (5/6)⁶ ,或者大约是 0.33489 (作为百分比,乘以 100 得到 33.49%)。
在对这些进行建模时,采用这个通用等式来确定至少一个事件发生的概率:
P(at least one of a specific outcome) = 1 - P(no outcomes of the specific outcome)
在我们的例子中没有一个具体结果的概率是前面提到的 (5/6)⁶ 或大约 0.33489 。因此,我们有:
P(at least one of a specific outcome) = 1 - 0.33489
然后我们得到最终结果 0.665 ,当你把它乘以 100 得到一个百分比,大约是 66.5% 。
因此,虽然一次掷出 4 的几率约为 1/6,但每次掷出 4 的几率都越来越高。
这似乎很明显。那么我该如何将此应用于生命风险呢?
虽然看起来很明显,随着机会的增多,出错的机会也越来越多,但实际上,在众多事件发生的情况下,风险累积的速度之快令人惊讶。
一个例子
比方说,每次骑自行车时,被其他车辆严重伤害的可能性只有 0.5%——这是一个虚构的数字,所以请不要把它当作实际的统计数据。考虑到这些可能性,你认为骑自行车实际上是非常安全的,所以你不介意骑自行车上下班。
一年大约有 252 个交易日——或者工作日,不包括节假日——假设你真的很努力工作,只休了两天带薪假(顺便说一下,我并不真的建议这样做),那么你今年工作了 250 天。你还决定骑自行车上下班,从你家到你家,所以这是 250 * 2 = 500 骑自行车。
使用上述至少一个等式的概率,我们可以得出以下计算结果来模拟您受到严重伤害的可能性:
P(at least one of a specific outcome) = 1 - P(no outcomes of the specific outcome)P(getting a severe injury while riding a bike) = 1 - P(no outcomes of not getting a severe injury while riding a bike)P(getting a severe injury while riding a bike) = 1 - (1-0.0005)^500[note: the reason we have 0.0005 above is because we divided 0.05% by 100]P(getting a severe injury while riding a bike) = 1 - (0.9995)^500P(getting a severe injury while riding a bike) = 0.22125
将最终结果乘以一个百分比,我们得出在您的工作年度内,另一辆车造成严重自行车伤害的概率为 22.125% !
这肯定比 0.05%的单次乘坐机会更不和谐,这表明风险的累积——毕竟你是在乘坐 500 次——实际上可以显著增加总体机会;当然,你不希望这种严重受伤的结果发生,即使在你的整个一年中有一次。
换句话说,如果你被告知你有 22.125%的几率在骑车时发生车祸,你可能会考虑你的决定,而不仅仅是考虑简单的 0.05%的风险。
日常决定累积起来
为了让你日复一日地重复生活中的决定,你希望完全避免负面结果发生*,你可以使用这种思路——以及这种经验统计公式——来看看什么程度的风险是真正值得冒的*
正如他们所说,选择权在你。
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
tremaineeto.medium.com](https://tremaineeto.medium.com/membership)*
人寿保险资格的风险分类评估
案例研究—数据科学项目
卢卡斯·布拉塞克在 Unsplash 上的照片
作者备注 —该项目是作为案例研究任务的一部分开发的,旨在更全面地了解数据科学在行业中的实施情况。2016 年,保诚人寿宣布在 Kaggle 举办一场比赛,邀请数据科学家提出一个风险评估模型。本案例研究的基础基于相同的问题空间,并使用来自 Kaggle 的数据和通过在线研究发现的数据来演示数据科学流程。演示文稿的链接可以在 这里找到 。
行动纲要
保险公司正专注于利用大数据和机器学习的力量来推出满足不同客户和细分市场需求的产品。下面的案例研究简要介绍了美国最大的保险公司之一保诚金融有限公司如何利用强大的数据科学路线图在整个组织内进行社会化分析,同时解决为客户群提供可扩展风险评估模型的最大瓶颈。案例研究分析了实施的数据和业务模型、数据存储和处理的规模和范围,提供了对数据和软件标准的清晰简洁的评估,同时验证了所使用的关键分析和统计方法。
项目描述
即使在提供了充分和广泛的信息之后,客户通常也会经历较长的医疗检查等待时间。任何保险计划的初始在线报价通常都不准确。销售和呼叫中心团队必须依靠传统方法向客户提供保险报价,这非常耗时。这些因素让任何客户都望而却步,迫使他们寻找其他替代品。该公司认为,只有通过更好地获取和留住客户,才能提高 L&A 部门的收入。由于获得一个新客户所需的努力比保留现有客户要高得多,因此识别具有高机会的市场并减少客户的入职时间非常重要(Kaggle,2016)。
商业模式
概观
保诚金融公司采用细分市场的方法开发产品和服务,以满足各种客户和机构的需求。价值主张是其商业模式的一个关键要素,其重点是金融产品的可获得性、改善的商业诚信、强大的道德以及通过改善客户关系提升的品牌形象。
下面的图 1 显示了项目的拟议目标如何影响一些关键业务领域,如客户关系(通过改进报价)、保险产品开发(通过研究现有业务和市场份额)、营销渠道优化和客户获取。
图一。项目在不同业务领域的优势。图片致谢——由作者使用 PowerPoint 制作。
挑战
由于不同的客户特征,预测模型在其他保险细分市场中的可扩展性以及对不同的利益相关者、销售和客户参与团队进行关于采用该模型的培训是具有挑战性的。
数据处理
分析数据模型是建立客户数据一站式商店的关键,同时确定开发风险评估模型的关键因素(麦肯锡公司,2017 年)。下面的图 2 展示了不同数据源、数据质量管理框架和分析如何集成的概念视图。
图二。保诚金融公司的数据模型。请注意*网站数据将涉及通过 L&A 网络部分获取的客户信息和其他必要的详细信息。图片致谢——由作者使用 PowerPoint 制作。
下面让我们来看看数据模型的一些关键组件。
数据源 —内部和外部,包括通过网站收集的数据、产品信息、财务数据、通话活动数据(客户和销售代表的 IVR 通话)、来自第三方供应商的索赔数据、市场人口统计信息和外部调查
数据量—2000 万客户,内部数据云存储 2.5
数据速度—L&A 段的通话和网络数据每日更新,财务和产品信息每月更新,外部数据每季度获取
数据种类 —客户人口统计、医疗、就业和家族史。数据还包括销售额、拨打的电话、促销和活动
数据准确性 —各地标准不同;DQM 用于确保数据质量
ETL (Extract Load Transform)工具 —用于 web 保险应用和调用日志数据的 Teradata 和 Teradata SQL 产品和财务数据通常通过 Excel 存储和流通,并直接输入 info link 存储(SAS 数据集)。从第三方供应商处获得的外部数据(如索赔数据)存储为 SAS 数据集。该组织正计划将通过 web 生成的数据转移到 Apache Spark
分析工具 — SAS & Python。SAS 用于数据安全目的;医疗信息非常敏感,因此该公司倾向于 SAS。Python (Jupyter Notebook)用于建模
商业智能工具 — QlikSense 和 Power BI
处理 —分析处理、数据量处理和查询优化
能力 —支持后续风险评估和客户细分研究的模型
安全/隐私 —医疗记录和患者数据需要隐私和保密。健康保险便携性和责任法案(HIPAA)管理美国健康数据的数据保护
生命周期 —需要全面的数据管理
资源
下面的图 3 说明了不同的工具和技术在英国保诚金融有限公司的应用。
图 3。整合工具和技术以促进组织中的数据科学项目。图片致谢——由作者使用 PowerPoint 制作。
推荐工具的特点:
Teradata —以结构化形式存储数据的关系数据库管理系统,便于最终用户查询(Teradata,2014)
Apache Spark (推荐)——包含 map-reduce 功能。无模式设计在本质上是分布式的,允许更好地摄取点击流数据。存储成本要低得多,并且支持云原生或本地处理引擎
SAS —支持更好的数据安全性,并附带用于预测分析的分析功能。与任何开源平台相比,大多数制药和银行公司更喜欢 SAS
4.Python——通用且易于使用的语言,与 SAS 相比具有更好的机器学习和预测分析能力。由于有多个开源库可用,所以更适合模型开发
5.QlikSense/Power BI—QlikSense 是一款自助式商业智能工具,它利用内存使用来加速仪表盘。允许为 QVDs (Qlik View 数据集)的数据争论和转换编写脚本,允许更快地前端加载大型数据集。Power BI 的基本版本与组织购买的 Microsoft 软件包捆绑在一起,仅用于内部报告
数据分析
探索性数据分析
数据分析分为两个部分。下面图 4 所示的第一个部分涉及为业务用户创建一个 360 度仪表板,以访问当前的市场场景,而下一个部分涉及构建风险评估模型。所有涉及客户群、市场份额、可用产品、收入和增长的顶级 KPI 都与按地理位置和产品划分的相对绩效指标一起显示在执行摘要页面中。使用 QlikSense 的探索性数据分析能够识别需要注意的业务领域,同时整合模型开发所需的准备工作。
图 4。Qlik Sense 仪表板中的执行摘要概述。请注意,仪表板是使用 Qlik Sense Desktop 开发的,没有使用其他扩展。图片来源-作者使用 Qlik Sense desktop 开发的仪表板快照。
从上述数据分析中快速发现:
1.保诚金融公司拥有 2200 万客户,但在美国仅占有 6%的市场份额
2.该公司在美国西部主要是加利福尼亚州、内华达州、新墨西哥州和科罗拉多州有较好的知名度
3.产品 D3 和 D4 是 L&A 组合中表现最好的产品
4.该公司拥有不同年龄组的客户,观察到年龄和风险水平之间呈正相关(使用皮尔逊相关系数进行相关性检查)
风险评估模型
概念图
在模型开发之前,先开发一个高级概念图,以确定影响风险水平的因素。概念图如下图 5 所示。
图 5。影响保险公司风险水平的多个因素的概念图。由作者使用 Lucid Chard 开发。
模型开发
保诚金融公司将风险分为从 1 到 8 的 8 个主要类别,1 是风险最低的保险公司,8 是风险最高的。风险级别是一个多类属性,因此使用决策树和集成技术的组合来识别具有最高准确度分数的模型。集成意味着组合来自一组模型的结果以获得更好的准确性和稳定性。尝试和测试了多种算法,以在偏差和方差之间取得平衡。数据争论、缺失值处理、异常值处理在模型开发之前完成。计算所有属性的集中趋势和偏斜度,缺失值用 0 或模式替换。利用箱线图和四分位数间距组合来识别异常值。以下算法(Analytics Vidhya,2016)是在推荐要在服务器上部署的模型之前开发的,如下图 6 所示。
1.决策树 —用于分类问题的监督学习算法,适用于分类变量数量较多的数据集。适用于处理多类问题,但经常导致模型过度拟合而没有修剪。基尼指数和熵被用作分裂的信息增益标准
2.随机森林 —一种通用的机器学习方法,可以处理回归和分类问题。允许数据和特征子集(独立变量)的引导抽样在一个森林中生长多棵树。基于最大投票将数据分类到标签中。随机森林可以很好地处理具有更高维度的大型数据集,并结合多个分类器的结果来提高模型的稳定性
3.装袋 —类似于随机森林,除了它利用所有特征来发展树
- Boosting —结合弱学习者创建强学习者的算法家族。ADA boost 依次训练不同的预测器,以提高前一个预测器的输出。ADA boost 通过改变每次迭代的不正确预测的样本权重来工作,而梯度 boost 通过识别在前一次迭代中计算的较大残差来工作
5.网格搜索 CV —一种通过尝试多个模型参数范围来微调模型输出的技术。使用 K 倍交叉验证技术,根据 K 倍的结果输出算法的最佳参数。如果使用多个参数范围,计算时间会长得多
图 6。如何利用不同的集成技术提出模型的流程。图片致谢——由作者使用 PowerPoint 制作。
模型输出
下面的图 7 显示了使用 Bagging 技术开发的模型的配对图、精确度、召回率、F1 和 ROC 分数。在比较来自不同算法的模型参数时,考虑宏观平均分数。Bagging 的准确率最高,为 0.56,召回率和准确率分别为 0.42 和 0.51。在下一个刷新阶段,可以使用 k 倍交叉验证或自举采样对模型结果进行微调。
图 7。由 bagging 技术产生的模型的配对图、精确度、回忆、F1 和 ROC 分数。图像来源 Jupyter 笔记本中模型结果的输出。
结论
保诚金融公司正在利用数据的力量做出明智的决策。数据科学领域目前是一条合理回报的河流,行为科学和设计思维开辟了通过人、流程和技术平台的整体生态系统加速解决问题的途径。风险评估模型和 360 度仪表盘是同类产品中的第一个,有可能在未来几天内以十分之一的管理顾问成本释放 1000 万美元的价值。
参考
1.德勤金融服务中心。(2019). 2020 年保险展望【白皮书】。检索自https://www2 . Deloitte . com/us/en/insights/industry/financial-services/financial-services-industry-outlook/insurance-industry-outlook . html
2.卡格尔。(2016).保诚人寿保险评估。检索自https://www . ka ggle . com/c/prudential-life-insurance-assessment/overview
3.保诚金融公司(2020)。 2019 年年报。检索自http://s22 . q4c dn . com/600663696/files/doc _ financials/voting _ results/Prudential-ar 2019 . pdf
4.Teradata (2014 年)。大数据:TERADATA 统一数据架构 TM 在行动。[在线]可从以下网址获得:http://assets . teradata . com/resource center/downloads/whites/EB 7805 . pdf
5.麦肯锡公司(2017)。利用保险数据的潜力。[在线]麦肯锡公司。可从以下网址获得:https://www . McKinsey . com/industries/financial-services/our-insights/having-the-potential-of-data-in-insurance。
6.分析 Vidhya (2016 年)。基于树的算法:从头开始的完整教程(用 R & Python 编写)。[在线]分析维迪亚。可在:https://www . analyticsvidhya . com/blog/2016/04/tree-based-algorithms-complete-tutorial-scratch-in-python/获取。
风险情报
死于新冠肺炎的风险有多大?
沃洛季米尔·赫里先科拍摄的照片(经由取消拍摄
风险智能是准确估计事件概率的能力。在本文中,我们应用迪伦·埃文斯的思维方式来评估:
- 死于新冠肺炎的风险有多大
- 电影一般会放多长时间
- 有多少 M & Ms 在 100 米的距离上排成一行
- 你的风险情报有多好
天气预报员对医生
天气预报员通过明确提及天气事件是否会发生的确定程度来使用概率预报。他们经常被要求在预报中包括天气事件发生的可能性。当他们预测“明天有 90%的可能性会下雨”时,他们有 85%的可能性是正确的。
天气预报员会在校准曲线上打满分。相比之下,医疗从业者会表现出过度自信。
当医生确信他们的病人有 90%的机会患肺炎时,只有 15%的病人被检测出肺炎阳性(见下文)。这是极端的高估偏差。
气象预报员对降水的预测和医生对肺炎的诊断的校准曲线(通过斯科特·普劳斯
医生对其诊断准确性的信心比证据实际保证的要大得多。他们宁愿安全也不愿后悔,即使这可能会导致更多的假阳性病例。如果晚期病人被发现是假阴性,医生将面临诉讼。
你有没有注意到,医生更喜欢用模糊的词语来描述他们的诊断有多大可能是正确的?
使用诸如“可能”、“可能”、“大概”这样的模糊词,他们可以回避他们所传达的模糊信息,这样他们就不太可能出错。
天气预报员的工作是重复的。他可以立即检查他的天气预报第二天是否是真实的。问题“明天会下雨还是下雪?”,“周五东京遭受台风袭击的可能性有多大?”都是定义明确的。答案清晰明确。因此,天气预报员可以通过从即时反馈中学习来快速提高他的风险情报。
医生很难从病人那里得到即时反馈。病人可能不会回来了。病人可能会被介绍给另一位医生。医学领域的许多问题无法准确回答。某些传染病,如伊波拉病毒和新冠肺炎病毒,需要进行预后筛查测试、基因组测序、接触者追踪、数据分析和严密监控。
诸如“这种新药对病人有副作用吗?”、“对于患有慢性疾病的新冠肺炎患者,应该给予什么样的治疗?”通常会在几周或几个月内导致医学诊断的改变。
未知的未知
邓宁-克鲁格效应是一种认知偏差,根源在于缺乏风险智能。大卫·邓宁和贾斯汀·克鲁格认为,无能不仅会导致糟糕的表现,还会导致无法认识到自己的无能。无能的人最容易产生虚幻的优越感。出于过度自信和缺乏自我意识,他们更有可能高估自己的知识或能力。
知识渊博的人在获得更多知识的同时,会更加意识到自己知识的局限性,即使这种意识可能会削弱他们的信心。一个博学的学者可能因此遭受虚幻的自卑。他可能低估了自己的能力。他知道有很多问题他还不知道答案。
未知的知识
你的知识通常是基于你没有意识到的事情。这可能是直觉、本能或直觉。
以英语为母语的人可能不知道语法规则,但他们可以连贯、正确地说和写。非母语人士将不得不花费数年时间学习时态、句子结构和词汇,以达到足够好的掌握水平。
大学生可能已经学习了数学概念和规则,但不知道如何将它们应用于一个特别困难的问题。他们所接受的数学基础是未知的知识。但是对于数学天才来说,这些问题只是小菜一碟。
他们不知道的是,数学天才更擅长调用数学基础来解决问题。数学天才在很小的时候就学习数学,他们已经将数学概念、方法和技巧内化了。简而言之,他们更善于发现联系,并将隐性的已知转化为显性的已知。
已知的未知
一个专业的赌徒会故意犯一些明显的错误来判断他的对手会如何对付他。如果对手巧妙地利用了他的错误,这个专业赌徒就会停止游戏。他只有在确信自己能赢的时候才会下注。专业赌徒通常了解自己的优势、弱点和局限性,并从过去的错误中吸取教训。
展示智慧的欲望会抑制风险智慧。知道自己不知道的东西,可以防止自己屈服于解释深度的错觉。
贝叶斯定理
当我们确定地知道其他概率时,贝叶斯定理对于寻找未知概率是有用的。
65 岁及以上的老年人死于 Covid 的可能性有多大?
一个中国人和美国人的死亡风险会略有不同。对于 65 岁以上的中国人:
P(死于 Covid | 65 岁以上)= P(死于 Covid)* P(65 岁以上|死于 Covid)/P(65 岁以上)
P(C|>65) = P(C) * P(>65 | C) / P(>65)
P(C) = 死于 Covid 的概率= 2.3% = 0.023
p(> 65 | C)=65 岁以上中国人死于 Covid 的概率 = 81% = 0.81
p(> 65)=65 岁以上中国人的百分比 = 9.5% = 0.095
p(C | > 65)= 65 岁以上中国人死于 Covid 的概率= 0.023*0.81/0.095 = 0.196 = 19.6%
如果一个中国人年龄在 65 岁或以上,他有 19.6%的机会死于 Covid。
对于一个年龄相仿的美国人来说:
P(C|>65) = P(C) * P(>65 | C) / P(>65)
P(C) = 死于 Covid 的概率= 3.86% = 0.0386
p(> 65 | C)=65 岁以上美国人死于 Covid 的概率 = 80% = 0.8
p(> 65)=65 岁以上美国人的百分比 ol d = 15.2% = 0.152
p(C | > 65)= 65 岁以上美国人死于 Covid 的概率= 0.0385*0.8/0.152 = 0.203 = 20.3%
美国人有 20.3%的几率死于 Covid。
贝叶斯定理只有在你能避免犯基础率谬误时才有效。不同的国家有不同的基本利率。人口老龄化的国家往往有更高的病死率。
正态分布
如果你去拜访一个看了 30 分钟电影的朋友,你会预测电影的长度是多少?
当托马斯·格里菲斯和约书亚·特南鲍姆问人们完全相同的问题时,人们根据他们的日常经验给出了统计估计。通过考虑电影播放时间的基本比率,他们不知不觉地采用了贝叶斯思维。
Griffith 和 Tenenbaum 发现电影运行时间遵循高斯分布,由此预测值围绕平均值聚集(见下文):
电影在“所有上映电影”和“票房最高电影”中的分布(通过斯蒂芬跟随
你不必掌握贝叶斯定理或高斯分布的复杂数学理论来得出上述结果。风险情报看起来很直观。
已知的知识
费米问题是我们永远不会知道确切答案的数学问题。如果我们能做出合理的假设和大概的估计,我们就能做出有根据的猜测,得出一个大概的答案。
微软和谷歌喜欢用费米问题来拷问他们的受访者,以测试他们的思维能力。准备好面对这些臭名昭著的问题:
芝加哥有多少钢琴调音师?
这里的解决方案是。
如果银河系中有相当数量的智慧文明,为什么我们的文明从未遇到过其他文明?
费米悖论可以用德雷克方程解决。
测量单条 M&Ms 线路到 100 米的距离需要多少数据包?
一个 1.59 盎司的袋子里大约有 30 颗 M & Ms 巧克力豆。
一个普通的 M&M 直径约为 1 厘米。
一包 M & Ms 可以做 30cm 距离的单行。
100 米的距离将有 100 米/0.3 米= 333 个 M & Ms 包
如果你是一百万秒,你是多少岁?一百万小时前?一百万天前?
1 年= 365 天 x 24 小时 x 60 分钟 x 60 秒= 31,536,000 秒
1000000 秒/31536000 秒= 0.03 年
这意味着你是一个 11 天大的婴儿。
1 年= 365 天 x 24 小时= 8,760 小时
1,000,000 小时/ 8,760 小时= 114 年
这使你成为一个非常老的超级百岁老人。
1 年= 365 天
1,000,000 天/ 365 天= 2740 年
这对人类来说是不可能的,至少现在是这样。
以下是你如何做出更好的预测
风险智能可以防止我们停留在无知的幸福或过度恐惧的反应。总体而言,预测地缘政治、宏观经济和股市趋势等紧迫问题要困难得多。
令人惊讶的是,每个人都可以有条不紊地训练预测未来的能力。Philip Tetlock 提出了以下实用的方法。参加概率推理和预测的简短培训课程。识别日常生活中的认知偏差。阅读新闻并与其他预报员讨论。加入全球预测锦标赛。
最后但同样重要的一点是,保持开放的心态,愿意经常快速地改变你的想法。
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
本文最初发表于showdeyang.com
人工智能驱动的信贷自动化的风险——综述
企业人工智能越来越多地被应用于改造和自动化银行流程,包括贷款和信贷价值链。
银行业似乎正在依赖人工智能(AI)和智能自动化来保护不断减少的利润。企业人工智能越来越多地被应用于改造和自动化银行流程,包括贷款和信贷价值链。对于一个历史上保守的行业来说,这是一个前所未有的举动,但绝望的时刻需要绝望的措施。人工智能仍然是一项成熟的技术,其创造者在技术行业尚未理解和控制风险。人工智能风险及其影响会在高度监管的大规模银行信贷流程中放大。银行很清楚这一点,但他们别无选择,因为他们的利润率正受到来自各个方面的冲击,时间对他们不利。
银行被迫部署提高效率和削减成本等防御性策略,以维持利润率。理论上,这是人工智能和自动化有望拯救银行业的地方。
传统信贷和贸易本身一样古老,自从大约 4000 年前基于物物交换系统的作物贷款在美索不达米亚的古代寺庙中引入以来,其核心概念并没有根本改变。然而,自那以后,信贷流程、系统和效用发生了演变,推动了人类文明的大规模扩张和进步。尽管非银行贷款在现代经济中发挥着至关重要的作用,但银行仍是神圣不可侵犯的现代信用殿堂。自 19 世纪初以来,银行已经建立了一个强大的信贷业务堡垒,并成功抵御了多次冲击。然而,对银行来说,最新的破坏性冲击是非传统的、未知的领域。当前人工智能驱动的颠覆正在走向成熟,但却是尖端技术,它通过快节奏的产品和运营创新推动快速变化,并呈现出一大堆未知的未知。这与当前保守的银行业经营理念或商业模式很难兼容。银行第一次面临一个可怕的敌人。由于多年来在低于标准的信贷实践中躲闪和迂回,持牌银行和受监管银行陷入了错综复杂的监管之中。一方面,银行业正试图应对人工智能如何影响现有银行和信贷法规的合规性,另一方面,人工智能本身将如何受到监管存在监管不确定性。
尽管存在所有的不确定性,但银行业正缓慢但肯定地被人工智能的无情打击所吸引,似乎正在梦游进入智能自动化陷阱,而没有充分意识到与之相关的风险。
事实上,对银行业人工智能风险的集体理解还需要数年时间。在讨论风险,特别是人工智能模型风险之前,有必要了解人工智能驱动的自动化预计将如何重塑银行的信贷价值链及相关流程和技术。让我们从 10 万英尺高空的卫星视图开始,然后快速下降,处理信贷价值链的细节以及地面上的相关模型和算法。
10 万英尺高空的工业革命
工业 4.0:早期工业化以来的工业革命
由于数字技术进步的令人振奋的步伐,我们被认为正在经历第四次工业革命,被称为“工业 4.0”。这一革命性阶段背后的普遍影响有时被称为“网络物理系统”,实际上是人工智能。工业 4.0 主要专注于将智能注入每个系统和流程,使其智能和自主。
万英尺高空的数字进化
数字进化:数字企业成熟度和时间表
对工业革命的进一步研究表明,“工业 4.0”及其前身对“数字进化”做出了重大贡献。数字企业(DE)被认为是在三个不同但相互关联的阶段中发展。DE 1.0 主要关注个人电脑和软件等技术的发展,而 DE 2.0 则关注移动性和互连性的进步。最新阶段的 DE 3.0 是关于利用技术基础设施和注入智能,使流程和系统智能和自治。今天,大多数 DE 3.0 企业都是大型科技公司,已经掌握了利用人工智能的技术基础设施。大多数传统银行刚刚开始升级其遗留系统,还远未实现人工智能的全部潜力。理想情况下,阶段之间的过渡应该是一个渐进的过程,组织有机会建立、消化和维持。在尝试大规模部署人工智能之前,银行业似乎没有时间、技能或资源来达到所需的技术成熟度水平。银行渴望成为科技企业,这很可能是一个有效的战略选择。但是,受监管银行的商业模式和文化并没有发生重大变化,以适应技术驱动的战略。
系统中人工智能风险的积累可以比作' 【沸腾的青蛙】 '在这种情况下,风险在突然发生灾难性转变之前就已经酝酿好了。银行正以某种方式面对自己的“ 柯达时刻 ”。
人工智能进化@ 5000 英尺
人工智能波——DARPA 人工智能进化分类
作为愿望或抽象概念的人工智能与人类思想本身一样古老,尽管它可能从未被设想为一种技术可能性。虽然人工智能作为一个具体的概念和计算机科学的一个分支自 20 世纪 50 年代以来一直在酝酿之中,但直到 2010 年代初才带来任何商业利益。人工智能只是在与数字进化融合时才开始有商业意义。国防高级研究计划局(DARPA),一个著名的前沿人工智能研究的先锋,已经将人工智能进化分为三个浪潮。波浪被称为手工知识、统计学习和语境适应。今天的人工智能属于第一波和第二波,但离解释它们的行为和结果还有一段距离。
可解释性和透明度是在信贷和银行领域有效实施人工智能面临的一些最大挑战。监管机构要求银行能够解释贷款和信贷决策,并充分披露批准或拒绝信贷决策背后的原因。
此外,数字进化 3.0 是一个必要的技术生态系统,可以充分发挥人工智能的全部潜力,并充分管理其风险。据估计,银行在实现 DE 3.0 到期方面落后 10 到 15 年。
人工智能@ 1000 英尺
受 DARPA 启发的人工智能分类:人工智能模型的整体图景
人工智能是一种结合数据、业务逻辑和机器/统计学习模型来影响或自动化流程的系统。虽然这需要一种计算机科学的方法来描述人工智能,并且不一定是人工智能的学术定义,但从应用模型风险的角度来理解人工智能是有用的。DARPA 启发的分类是比标准定义更好的理解人工智能的方法。
- 机器学习 : DARPA 将其称为“统计学习”,是经典统计建模和监督、非监督和强化学习的融合。深度学习是机器学习的一个子集,使用多层神经网络来解决更高维度的问题。
- 智能服务自动化:自然语言处理(NLP)、语音、音频、视频和图像处理被认为是智能服务自动化(ISA)。ISA 应用机器学习和深度学习技术,并且它们在它们的效用水平上被商品化。
- 机器人:机器人将物理传感器和控制与人工智能相结合。
100 英尺处的银行模型
银行模型清单:信贷模型不仅仅是法规遵从性
银行已经广泛使用模型和工具来产生商业见解、自动化流程和做出商业决策。任何标准的零售和商业银行模型库存都可能有成百上千的金融和非金融模型。大型零售银行和企业银行可能有 1,000 到 2,500 种工具和模型。
大多数银行模型属于上述 DARPA 分类的第 1 波& 2。大多数 wave 2(统计学习)信贷和贷款模型的开发和部署都是为了支持高级巴塞尔协议 II & III 认证。
从信贷角度来看,模型主要属于零售和非零售(公司)投资组合。但是,值得考虑的是与信用相关的市场和市场风险模型以及包括信用策略(风险偏好)在内的与信用相关的运营和操作风险模型。
50 英尺的信用模型
银行业中的信贷模型清单-企业人工智能越来越多地用于自动化信贷价值链
银行将大部分信贷建模精力用于遵守风险报告的各种监管要求。高级统计学习模型的真正潜力在管理与信用风险及其操作相关的风险方面几乎从未发挥过重要作用。尽管巴塞尔(Basel)和多德-弗兰克(Dodd-Frank)等监管要求迫使银行更加以数据为导向,但客观的基本银行文化从未出现过。例如,信贷模型性能指标在过去十年中几乎没有改善,但这从来都不是问题,因为投资和改善模型性能没有太大的商业意义。银行业信贷模型的最大风险不是模型可能出错,而是监管者会注意到这一点,并对违规行为处以重罚。缺乏来自行业外的竞争,部分是由于其庞大的规模,导致银行自满,监管机构一直在打勾,直到现在。
银行业的竞争态势突然发生了变化,BigTech、FinTech、TechFin、neo banks 等新的参与者。正在通过一次一次的技术颠覆蚕食银行利润。过去,银行成功应对了传统的竞争和干扰,但现在它们面临着痛苦的“千刀万剐”的局面。
企业人工智能被这个行业作为银弹出售,这个行业也是通过专有贷款(亚马逊)、支付系统和信用卡(苹果、谷歌)、加密货币(脸书)等盈利的有力竞争者。此外,他们可以使用更成熟的技术基础设施,并且不受法规的束缚,至少目前是这样。银行别无选择,只能与这些科技巨头合作,实施人工智能,实现信贷价值链的自动化。尽管监管信贷模型目前超出了先进人工智能算法的限制,但整体信贷价值链正在快速自动化。正在使用先进的人工智能算法开发下一代模型,以找到优秀的客户并参与其中,改善整体客户体验,为客户开发个性化的价值主张,帮助银行提高效率和道德水平,管理收款等。
人工智能算法@地面
用人工智能算法复制人脑——信贷价值链自动化越来越多地利用这些算法。
最新的人工智能算法已经以不同的复杂程度复制了人类大脑的大部分活动。对于银行来说,应用这些能力来改善客户价值主张和应对竞争的诱惑是不可抗拒的。这些算法的全部主机将可能被用于生成集体见解、增强客户体验和提高效率。它已经在聊天机器人、语音银行、智能信贷政策整合、连接物联网数据以自动化流动性和贸易融资、交易员和银行家对话分析以改善销售机会、监控行为和增强客户服务等方面发挥作用。其中一些人工智能算法复杂、精密且不透明,但由于它们没有应用于监管模型,因此被认为风险重要性较低。
众所周知,沸腾的锅的温度似乎上升得相当快,而青蛙仍然幸福地不知道。
总之……
银行在转型项目上投资数十亿美元,希望提升信贷和银行系统,使它们为人工智能做好准备。企业人工智能有望在信贷和关联银行流程的自动化和智能化方面发挥重要作用。但是,由于目前的技术成熟度和相关技能差距,根本的转型战略绝不是以人工智能为中心的。大多数银行仍在从传统系统(数字企业 1.0)向移动和基于云的基础设施(数字企业 2.0)过渡。银行正在努力获得正确的数据和基础设施基础,以便能够有效地利用人工智能。这在正常情况下是有道理的,但现在是银行和信贷的非常时期。
竞争和成本压力持续存在,银行已经开始将人工智能模型滴入银行生态系统,而没有整体的人工智能战略或监管指导方针。杂耍才刚刚开始,但随着更多的人工智能模型进入生态系统,它将变得异常困难。
教机器行为:强化学习
强化学习基础
第一部分
这篇文章的目的是为任何人进入强化学习提供一个切入点。我打算提供理解什么是强化学习算法,它们如何工作所必需的基础知识。后续文章将深入讨论具体的算法和实现。一定要订阅。
TL;大卫:在文章的最后,你会发现所有学习材料的总结。
Re enforcement Learning(RL)是一门科学,旨在创造能够学习如何在特定环境中以最佳方式行动的机器。如果我们将智能代理定义为最佳行为的智能代理,那么这个领域可以被认为是人工智能的一个子领域。一个这样的智能代理将是一个学习如何在世界冠军的水平上下棋的系统。
请注意,正如在所有机器学习子领域中一样, RL 程序并不是显式编码的,以便在某些给定的任务中最佳地执行。相反,这门科学背后的动机是设计通用算法,这些算法能够不断地从环境中学习 T21,这样它们就可以利用学到的知识在特定的任务中表现出色。
基础知识
RL 的灵感来自于行为心理学*,这是一个科学领域,专注于个体的行为如何通过强化 和重复来改变。在这种情况下,正确的行为会得到奖励,不受欢迎的行为会受到惩罚;想出一个典型的对狗的调理方法:当狗表现好时奖励它,但当它咬你的鞋子时惩罚它。通过足够多的互动,个体可以学习到最优行为,即最大化其总回报,或者等价地最小化其惩罚。*
总报酬可以被认为是在一个代理人的生命周期中的每个时间步给出的独立报酬的总和。
为了最大化其总回报,一个 RL 代理需要学习如何最佳地表现。这意味着,它必须花一些时间在每时每刻寻找最佳行动。测试未知的行动路径可能会浪费代理人的时间(比如说,如果代理人的时间有限,像大多数生物一样),这些时间可以用来在更好的已知路径下获得更高的奖励。这意味着必须在探索环境和使用* 已经获得的知识之间找到平衡。这种困境在强化学习中被命名为探索 vs 利用,是工程化类似类型在职者时需要解决的一个经常性任务。*
强化学习的重点是开发代理,这些代理学习在环境中采取行动,以便最大化累积回报的一些概念。
为了构建一个具有这些特征的代理,我们利用数学框架来模拟代理的执行。正如你将看到的,一个问题的数学模型允许工程师在计算机上实现它们。
一群与环境互动的蓝色特工。他们的目标是避免被红色特工直接看到1。
任务建模
简单的模型
让我们假设一个智能体与环境的交互是这样的:一个智能体在时间* t
、中的一个点上观察环境状态** s
,并根据它所看到的,决定执行一个给定的动作 a
。在随后的时间t+1
,比如说一秒钟后,代理接收到奖励/惩罚 r
以执行该动作;这个循环在时间t+1
重新开始,此时代理观察到环境的新状态s.t+1
。该循环要么永远重复,要么直到最后一个时间步T
。*
主体-环境相互作用模型。摘自[2]。
一系列的状态、动作和奖励被正式称为轨迹:s0, a0, r1, s1, a1, r2, ...
。
如果环境曾经到达一个 最终状态 (例如,在国际象棋游戏中到达一个对弈对手),我们认为这个交互是插曲:它有一个开始和一个结束*。相反,没有在任何时间点完成的任务被命名为连续(我们的宇宙可能就是这样的环境之一)。我们需要区分这两者的原因将在下面几节中变得显而易见。*
有限马尔可夫决策过程
根据状态*、动作和奖励来公式化这种相互作用,允许我们将问题构建在被称为马尔可夫决策过程 ( MDP,简称)的数学框架中。您可以将 MDP 视为数学模型,它允许我们将这种高层次的交互概念简化为定义明确的元素。具体来说,MDP 可以使用一个三元素元组对交互进行建模:*
- S :可能状态的有限集合*。
比如井字游戏的一个 单态**s**
就是游戏的网格,它告诉被玩的 x 的 和 o 的 所在的位置。所有状态的集合将包含所有可能实现的板的组。***
井字游戏中可实现的各种状态列表。
- A(s) :从状态
**s**
可用的有限组可能动作*。
如前所述,动作将代理从一个状态带到下一个状态( sᵢ → sᵢ₊₁ )。因此,从任何状态s
,将有一组可能采取的行动,定义为**A(s)**
。在井字游戏开始时,第一个玩家可以选择最多 9 个单元格来标记(要采取的行动),而第二个玩家在第一轮只能从 8 个单元格中选择。***
井字游戏状态图。每个箭头都是将代理从一种状态带到下一种状态的操作。
- Prob(s ',r| s,a) :转移概率函数。* 这个概率函数描述了代理的环境机制:当从一个状态
s
开始并采取一个行动a
时,实现一个状态奖励对(例如,check-mate,WIN)的概率是多少。更正式地说,我们可以将单个交互描述为 {s,a → s ',r}: 从状态**s**
开始,执行动作**a**
,将代理带到一个新的状态**s'**
,获得奖励**r**
。如果想象起来很混乱,下一段旨在让它变得清晰。***
备份图是非常有用的工具,可以让我们更好地可视化 MDP。我们可以将代理和环境之间可能的交互想象成一个图,其中 S 中的每个状态 s 是一个节点,来自给定状态 A(s) 的每个可能动作是一个动作节点*,边是每个下一个状态**S’的奖励概率以及它们相关的奖励 r 。*
让我们通过备份图来说明转移概率函数。让我们假设你处于这样一个场景中,你可以购买一张彩票,以千分之一(0.1%)的概率赢得$1000
,以 99.9%的概率输掉$10
,或者不购买,既不赢也不输钱,但有 100%的概率。
所有可能的转换包括:
Prob(Win, $1000| Initial, Buy)
= 0.1%Prob(Lose, -$10| Initial, Buy)
= 99.9%Prob(GoHome, $0| Initial, DontBuy)
= 100%
所有其他的转变组合都是不可能的,这意味着它们发生的概率为零。举几个例子:
Prob(Win, $999999999| Initial, Buy)
= 0.0%
不可能用一张单人票赢得超过 1,000 美元的奖金。Prob(Win, $1000| Initial, DontBuy)
= 0.0%
不买票不可能中奖。
随机与确定
状态转移是随机定义的(用更简单的话来说,是一个概率函数),允许像扑克游戏这样的随机环境用 MDP 来建模。在 确定性环境 ( 非随机,如井字游戏)中,从状态**s**
开始并采取行动的代理人**a**
总是会转换到状态**s'**
并获得相同的奖励**r**
。**
奖励
最优代理人本身的目标是最大化累积报酬,而不是个人报酬。一个聪明的代理人宁愿在它的轨迹中获得小的回报,最终得到正的累积和,也不愿随着时间的推移获得高的正回报和低的负回报,最终得到低的累积和。所有奖励之和 G 在一定时间后 t 定义为返回*** 。这种回归就是我们希望我们的代理人学会最大化的价值。***
如果交互作用是幕式的,则此和 G(t) 将被限制,因为有最大数量的步骤: T 。**
情景任务中的奖励累积总和
反之,在连续 互动中,由于最终时间 T 不存在,累积总和、 G(t)** 将趋向于+infinity
或-infinity
。这是因为将会有无限多的奖励。****
例外情况:
- 如果所有的返回值都为零,那么总和也将是 0。
- 如果每个后续奖励都比前一个小,并且其总和已经有界(更多信息见下文)。
持续互动中的累积奖励总和(从时间 t 开始)
折扣未来的奖励
一般来说,对无限回报建模是没有用的,因为它不允许我们优化代理的行为。为了解决这个问题,有人提出了一个非常聪明的想法:贴现。它包括给予代理人【能力】优先考虑/加权短期回报。这样,长期奖励会以指数方式贴现(这意味着每个后续奖励的价值都会比前一个减少更多)。正如您将看到的,这使我们能够摆脱无限报酬的问题。
一个有用的类比是,将贴现理解为代理人在其累积报酬计算中变得短视。
****实际上,我们将把每个奖励乘以一个贴现因子(𝛾;希腊单词“gamma”)带有指数项,随着时间的推移,奖励越大。
折扣累积奖励金额
折扣演示
让我们举例说明折扣奖励是如何工作的。让我们任意决定,在每一步,奖励 R 为1。下图对此进行了说明,其中 x 轴是时间步长,y 轴是相应时间步长的计算奖励。
在所提供的示例中,每个时间步长的奖励
如果我们应用𝛾=0.9 的贴现值,每一步R * gamma
的回报都成指数递减。这意味着,在随后的每个时间步长,该值比之前步骤中已经减少的值减少更多。
如果我们只使用到时间t
(下图中的 x 轴)的奖励来计算回报G
(下图中的 y 轴),您将会看到奖励限制在某个值。在下面的例子中,考虑所有奖励直到无穷大,提供了 10 的有界回报G
。
使用贴现因子时,显示奖励累计总额的图表是有界的。折现系数(γ)= 0.9;每一步 r = 1;G = 10。
当我们将越来越多的时间步长加入到我们的回报G
计算中时,计算这个相同的值,没有任何折扣,将为我们提供一个无穷大的值。
如果不使用折扣,则显示奖励累积总额的图表不受限制。
考虑
重要的是要记住:
- 贴现因子是一个有理数。
- 贴现因子需要在开放范围内: 0 < 𝛾 < 1。
数值越接近 1,越考虑长期回报。
该值越接近 0,就越不会考虑长期奖励。 - 当贴现因子等于 1 (𝛾 = 1)时,我们再次得到上面看到的无界累积报酬公式。如前所述,在这种情况下,回报将趋于(+/-)无穷大。如果贴现因子大于 1 (𝛾 > 1),也会发生同样的情况。
- 如果贴现因子等于零(𝛾 = 0 ),回报将是微不足道的,等于 0。
这种技术也可以用于建模的情景任务。如果折扣因子**被设置为 1,并且时间 T 之后的所有奖励被设置为零,它将模拟一个情节任务。****
在上述条件下,奖励的折扣总额也可以代表偶发任务
最佳行为:政策和价值函数
许多 RL 算法涉及估计值函数,该值函数定量地描述“代理将自己定位在状态 s 中有多好】。**值的概念是根据一个代理人在一个给定状态开始时能够获得的 **回报或累积未来回报* 来定义的。*****
价值函数的简单建模
将奖励分配给各州可以让代理了解其周围的环境,从而提供最佳策略的洞察力。当井字游戏代理被设置为第一次玩时,它的值函数可以将零分配给所有状态,因为它们是未知的。通过遵循预定义的行为,代理可以了解哪些状态导致了赢和输,并相应地更新值函数。一个状态值代表在一个状态**s**
下开始并遵循策略π ( 希腊字母 pi ),代理人的行为的期望报酬。在国际象棋棋盘上,一个直接导致对弈的状态将被赋予一个值1
给获胜的一方,而-1
给失败的一方。
状态值函数定义。它是遵循策略 π 的状态 S 的期望值。
也可以为[状态,动作]对定义值函数。他们估计从状态**s**.
开始采取行动**a**
的回报
给定策略的动作值函数的定义 π 。
策略则是代理在每个状态下采取的指导方针或决策。
一个策略 P 可以理解为在状态st53】时选择一个动作 aᵢ 的概率。
形式上,策略被定义为可用动作的概率分布函数*,给定输入状态*。它们不一定是确定性的,因为代理的策略可能是随机的,这意味着它会选择具有一定程度随机性的决策。******
例如, 随机策略 将为来自状态 s 的每个可用动作提供相等的概率(等效地使用均匀分布),并且在执行期间将从策略中对动作进行采样。使用随机函数来描述策略允许代理处理一定程度的随机性,这种特性在存在不确定性的环境中(例如扑克游戏)是有价值的。
政策的数学表述
在此框架中可以定义两种类型的策略:
- ****探索性策略:它们允许代理采取非最优决策,目的是探索潜在的最优未知路径,并改进其策略。他们给导致明显非最优回报的行为分配一个非零概率。
- ****开发性政策:利用现有的环境知识,试图获得最佳回报的政策。它们是贪婪的政策,分配产生最高预期回报的概率。当环境不为人所知时,这种政策的不利之处就来了,代理人会得到次优的回报。
寻找最优策略:贝尔曼方程
强化学习代理的最终目标是学习提供最高回报的策略。这就是所谓的最优策略,用 π 表示。对于这样一个最优策略,在任何状态下,其预期收益都大于或等于任何其他策略的预期收益。换句话说,在每一个可能的状态下遵循 π 的预期回报,如果不比使用任何其他可能的策略(π’)时更高,至少等于。**
*为了确定未知的最优策略 π,让我们利用目前所学的知识。首先,让我们将【v (s)定义为最优状态值函数,如果我们遵循最优策略【π】则实现该函数。类似地, a 是最优状态-动作-值函数,如果遵循最优策略 π 获得。
最佳值函数:在遵循使 v(s)和 a(s,a)最大化的策略 π 时获得
假设最优值函数 v 和 a 是已知的,但是最优策略是未知的,可以通过以下方式建立最优策略:**
- *******当 v *(s)已知时:通过允许代理仅采取从状态
s
开始的使价值最大化的行动,可以建立最优策略。换句话说,给任何使【v (s)最大化的行动分配非零概率的策略将是最优策略。 - 当 q(s,a)已知时 :最优策略可以通过允许代理在每个可用状态下采取任何使 q(s,a)最大化的行动来建立。*
使用 q (s,a) v(s) 有一大好处。即使v (S)是一个更简单的值函数,由于它只取决于可能的状态数| S |(S 的大小),所以它需要环境的知识。用 v 生成最优策略需要知道从初始状态**s**
可达的可能状态【s’。相反,用 q(s,a)生成最优策略只需要知道初始状态**s**
和在该状态下可用的可能动作。*
贝尔曼方程
但是,当我们不知道最优策略时,我们如何确定最优值函数呢?等式:
没有提供太多关于如何获得最大化价值函数的策略的信息:最优策略。我们必须计算所有可能策略的价值函数,然后选择提供最大价值的策略。幸运的是,我们可以以一种不依赖于特定政策的方式定义最优价值函数,并允许我们计算它们。
具体地说,我们将根据其他状态的价值函数来重新表述给定状态的价值函数。从数学上来说,我们将递归地定义它们。
根据定义,最优价值函数【v *(s)被表示为期望回报G
,从状态s
开始,并采取使该值最大化的行动a
。
代表最佳状态值函数 v(s)的备份图
- 等效表示为:
定义为预期收益的状态值函数。
- 使用 G 的定义,即奖励的贴现累计总和,我们得到:
- 用值函数代替
G
:
当采取最优行动时,状态 s 的最优值是下一个奖励的期望值加上下一个状态**s'**
的贴现最优值。
**q(s,a)**
也是如此:
在状态**s**
采取行动**a**
时的最优值是后续奖励的期望值加上在后续状态***s'***
采取后续最优行动**a'**
时的贴现最优值。
表示最佳状态值函数 q(s,a)的备份图
求解贝尔曼方程
这些方程被称为贝尔曼最优方程,以美国数学家理查德·贝尔曼的名字命名,他是最早描述这些方程的人之一。贝尔曼优化方程可以用类似于动态规划的优化方法数值求解(例如使用计算机)。
如果我们有所有后续步骤s'
的价值函数的近似值,那么就有可能计算状态s
的最佳价值函数。这应该允许我们学习一个最优策略。
尽管如此,最好将这一解释留给后续文章。已经有很多信息需要消化了,我很高兴你能理解这一点。
在我的下一篇文章中,我将总结用来做这件事的技术的基础和状态。当我把它们写下来的时候:
- 看看更多的机器学习内容:例如我最近的一篇解释 GANs 的文章。
- 在我的强化学习 Github 知识库中,您可以随意地先睹为快更高级的算法来寻找最优策略🙂。
- 对于更高级的技术,请随意浏览我实现的玩 Atari 游戏的深度 Q 学习算法。
- 入门看 Deepmind 的强化学习入门。
GitHub: diegoalejogm
摘要
- 强化学习是研究如何构建智能代理的领域,智能代理是在给定环境中设置时表现最佳的代理。受行为心理学启发。**
- 马尔可夫决策过程可以通过状态
s
、动作A(s)
、奖励r
和转移概率Prob(s', r | s, a)
对主体-环境交互进行建模:通过执行动作a
从s
到达状态s'
并获得奖励r
的概率。 - **奖励 的累计总和称为 回报,可以用贴现因子 𝛾 有界到一个离散数。在强化学习中,我们试图教会代理一种行为,使这种价值最大化。
- **值函数 v(s) 和 q(s,a) 近似于代理在处于状态 s 时将会收到的期望值。它们可用于定量评估达到某个状态或执行某个动作的效果。
- 策略是代理遵循的行为。它们被定义为处于给定状态
s
时采取行动a'
的概率。 - 最优值函数
v*
和q*
允许我们确定最优策略【π***,这将允许我们生成智能代理。****
参考文献
1 OpenAI。2020.多智能体交互产生的紧急工具使用。[在线]可在 https://openai.com/blog/emergent-tool-use/查阅[2020 年 4 月 11 日查阅]。
[2]萨顿和巴尔托(未注明日期)。强化学习。第二版。麻省剑桥:麻省理工学院出版社。
3szepesva ri,C. (2010 年)。强化学习的算法。[加州圣拉斐尔]:摩根&克莱普尔出版社。
[4] Mnih,v .等《通过深度强化学习实现人级控制》。性质 518,529–533(2015)。
RNN 细胞:分析 GRU 方程与 LSTM,以及何时选择 RNN 超过变压器
深度学习往往感觉像试图在雪山中找到自己的道路。有坚实的原则会让你在做决定时更有信心。我们都去过那里
约书亚·厄尔在 Unsplash 上的照片
在之前的帖子中,我们全面介绍并考察了 LSTM 牢房的方方面面。有人可能会说,RNN 的方法已经过时,研究它们没有意义。确实,最近一类叫做变形金刚[5]的方法已经完全占领了自然语言处理领域。然而,深度学习从未停止让我惊讶,包括 RNN。也许有一天,我们会看到一个巨大的回归。
RNN VS 变形金刚
请记住,在以下情况下,RNN 仍然是变形金刚的最佳选择:
- 序列长度过长。
- 任务需要实时控制(机器人),否则下一时间步不可用。
- 没有巨大的数据集来利用变形金刚的迁移学习能力。
- 计算机视觉问题是弱监督的(动作识别)。是的。混合 CNN-RNN 方法,以及连接主义时间分类(CTC)损失【6】仍然工作得很好。
更多了解 RNN 的其他原因包括混合动力车型。例如,我最近遇到了一个模型,它结合了递归神经网络和 GANs ,可以产生真实的实值多维医学数据序列。所以你永远不知道它们会在哪里派上用场。
无论如何,基本面是要掌握的。这一次,我们将审查和建立门控循环单元(GRU) ,作为 LSTM 的自然紧凑的变化。最后,我们将根据问题提供关于使用哪种电池的多种比较见解。
随附笔记本代码提供 此处 。
GRU:简化 LSTM 细胞
我们已经看到 LSTM 是如何预测连续数据的。最初引入 LSTM 的 where 时出现的问题是参数数量太多。让我们首先说,在参数数量和执行的操作方面,提议的称为 GRU 的 LSTM 变体的动机是简化。
在我们进入方程之前,让我们澄清一个重要的事实:就长期序列建模而言,LSTM 和 GRU 细胞的原理是共同的。首先,我们可以处理任意数量的时间步长,此外,**我们试图洗去多余的信息,并加入存储在权重中的记忆成分。**在网络中通过隐藏状态向量引入记忆,该隐藏状态向量对于每个输入序列是唯一的,每次从(t=0)的零元素向量开始。
现在,让我们看看略有不同的数学!同样,我们将一步一步地分析它们。我在这里只是把它们作为一个参考点。用于:
图片由作者提供,最初用 Latex 编写
其中 N 是每个时间步长的特征长度,而:
图片由作者提供,最初用 Latex 编写
其中 H 是隐藏状态维数,GRU 方程如下:
图片由 Aythor 提供,最初是用 Latex 编写的
等式 1:复位门
图片由作者提供,最初用 Latex 编写
这个门和 LSTM 牢房的遗忘门非常相似。产生的复位向量 r 表示将确定从先前的隐藏时间步长中移除什么的信息。如同在遗忘门中一样,我们通过逐元素乘法应用遗忘操作,由 Hadamard 乘积运算符表示。我们将重置向量计算为当前时间步长以及先前隐藏状态的输入向量的线性组合。
这两种运算都是用矩阵乘法(nn)来计算的。PyTorch 中的线性)。注意,对于第一个时间步长,隐藏状态通常是一个用零填充的向量。这意味着没有关于过去的信息。最后,应用非线性激活(即,sigmoid)。此外,通过使用激活函数(sigmoid ),结果位于(0,1)的范围内,这说明了训练稳定性。
图片由作者提供,最初用 Latex 编写
所谓的更新门中的 GRU 的输入和输出门的合并就发生在这里。我们计算输入向量 x 和先前隐藏状态的另一种表示,但是这次使用不同的可训练矩阵和偏差。向量 z 将代表更新向量。
等式 3:几乎输出分量
图片由作者提供,最初用 Latex 编写
向量 n 由两部分组成;第一层是应用于输入的线性层,类似于 LSTM 中的输入门。第二部分由复位向量 r 组成,并应用于先前的隐藏状态。注意,这里遗忘/复位向量直接应用于隐藏状态,而不是应用于 LSTM 单元的单元向量 c 的中间表示。
图片由作者提供,最初用 Latex 编写
首先,在描述的等式中,注意 1 基本上是 1 的向量。因为 z 的值位于范围(0,1)中,所以 1-z 也属于同一范围。然而,向量 z 的元素具有互补值。很明显,对 z 和(1-z)应用了元素式操作。
有时候我们通过分析极端案例来理解事情。在一个极端的场景中,让我们假设 z 是一个 1 的向量。那是什么意思?
简单来说就是输入会被忽略,所以下一个隐藏状态会是上一个!在相反的情况下,z 将是零元素向量,这将意味着先前的隐藏状态几乎被忽略。我使用几乎这个词很重要,因为更新向量 n 在应用重置向量后会受到之前隐藏状态的影响。尽管如此,复发将几乎消失!
直观地,共享向量 z 平衡互补先前隐藏状态和更新输入向量 n 的影响。
现在,我选择使用共享世界来代表 z 的原因变得深刻了。以上所有内容都可以在维基百科的下图中得到说明:
图片由 Jeblad —自己的作品,CC BY-SA 4.0,借用自 维基百科
我不太喜欢这些图的原因是因为它们可以用标量输入 x 和 h 来解释,这至少会误导。
其次是不清楚可训练矩阵在哪里。基本上,当你在 RNN 的旅程中根据这些图表思考时,试着认为 x 和 h 每次使用时都乘以一个权重矩阵。
就我个人而言,我更喜欢钻研方程式。幸运的是,数学从不说谎!
简单来说, 复位门 (r 向量)决定了如何将 新输入 与先前的记忆融合,而 更新门 定义了 先前的记忆还剩多少 。
为了深入理解 GRU 细胞是如何工作的,你只需要知道这些。他们连接的方式(在空间和时间上)与 LSTM 完全一样:
隐藏的输出向量将是下一个 GRU 单元/层的输入向量。
双向可以通过以相反的方式同时处理序列并连接隐藏向量来定义。
LSTM 与 GRU 细胞:使用哪一个?
GRU 单元是在 2014 年推出的,而 LSTM 单元是在 1997 年推出的,因此 GRU 的权衡还没有完全探索出来。在许多任务中,这两种架构的性能不相上下1。通常情况下,超参数的调整可能比选择合适的单元更重要。但是,并排比较一下还是不错的。
以下是 5 个基本的讨论点:
- 重要的是,这两种架构都是为了解决梯度消失的问题而提出的。这两种方法都是利用不同的方式将先前的时间步长信息与门融合,以防止消失梯度。然而,在 LSTM 的梯度流来自三个不同的路径(门),所以直观地说,你会观察到梯度下降比 GRUs 更多的可变性。
- 如果你想要一个更快的和更紧凑的和型号,GRU 的可能是你的选择,因为它们的参数更少。因此,在许多应用中,它们可以被更快地训练。在序列不太大的小规模数据集中,通常选择 GRU 像元,因为数据较少,LSTM 的表达能力可能不会暴露出来。从这个角度来看, GRU 被认为结构更简单,效率更高。
- 另一方面,如果必须处理大型数据集,LSTMs 更强的表达能力可能会带来更好的结果。理论上讲, LSTM 细胞应该比 GRUs 记住更长的序列,并且在需要模拟长程相关性的任务中胜过它们。
- 根据等式,可以观察到 GRU 单元比 LSTM 少一个门。准确地说,只是一个重置和更新门,而不是 LSTM 的遗忘、输入和输出门。
- 基本上, GRU 单元控制信息流,而不必使用单元存储单元(在 LSTM 的等式中表示为 c)。它暴露了完整的记忆(不像 LSTM),没有任何控制。所以,这是基于手头的任务,如果这可能是有益的。
综上所述,答案在于数据。没有明确的赢家来说明哪一个更好。确定哪一个对您的问题最有效的唯一方法是训练两者并分析它们的性能。为此,以灵活的方式构建你的深度学习项目很重要。
结论
在这篇文章中,我们提供了一个 GRU 单位的审查。我们观察了它的独特特征,我们甚至建造了自己的细胞,用来预测正弦序列。后来,我们将 LSTM 和 GRU 进行了对比。这一次,我们将提议进一步阅读一篇有趣的论文,该论文由尹等人 2017 在自然语言处理3的背景下分析 GRUs 和 LSTMs 。
我们专注于对 RNN 的理解,而不是在更花哨的应用中部署他们的实现层。
参考
1 Greff,k .,Srivastava,R. K .,kout Nik,j .,Steunebrink,B. R .,& Schmidhuber,J. (2016)。LSTM: 太空探索之旅。 IEEE 神经网络与学习系统汇刊, 28 (10),2222–2232。
[2] Chung,j .,Gulcehre,c .,Cho,k .,& Bengio,Y. (2014 年)。门控递归神经网络对序列建模的实证评估。 arXiv 预印本 arXiv:1412.3555 。
3尹,魏,坎,k,余,m .,,许子华(2017)。CNN 和 rnn 用于自然语言处理的比较研究。 arXiv 预印本 arXiv:1702.01923 。
[4]埃斯特万,c .,海兰,S. L .,& Rä tsch,G. (2017 年)。用递归条件生成实值(医学)时间序列。 arXiv 预印本 arXiv:1706.02633 。
[5] Vaswani,a .,Shazeer,n .,Parmar,n .,Uszkoreit,j .,Jones,l .,Gomez,A. N .,… & Polosukhin,I. (2017)。你所需要的只是注意力。在神经信息处理系统的进展(第 5998–6008 页)。
6汉南,《用 CTC 进行序列建模》,蒸馏,2017。
原载于 2020 年 9 月 16 日https://theaisummer.com。
RNNs 与传统 ML 在预测客户终身价值方面的比较
比较序列和贝叶斯方法预测未来收入
我工作的公司 RETINA.ai 建立了 ML 模型来预测客户的终身价值(CLV)。我们的数据科学团队一直致力于利用最好的学术和行业研究来完善和改进这些模型。本文描述了我们使用递归神经网络(RNNs)预测 CLV 的结果。
因为 RETINA 的客户需要从战略和战术两方面了解他们的客户,所以我们在宏观(群体层面)和微观(客户层面)购买模式上构建和测试我们的模型。我们将此作为评估模型性能的基础,这样我们就可以不断地迭代我们的模型。
在这篇博文中,我们将展示 RNN-LSTM(具有长/短期记忆的递归神经网络)机器学习模型如何能够像其他行业领先的模型一样准确地预测 CLV。
语境
为了建立一个预测性的 CLV 模型,我们从客户交易历史开始。我们输入到模型中的数据集可能如下所示:
订单表示例
从这个交易表中,我们不仅可以确定 CLV,还可以预测每个客户的未来交易——并且,我们可以用一个时间模式图来直观显示这一点:
上图显示了我们交易表中的每笔交易以及预测的未来交易:
- 垂直的灰线标志着今天
- 水平灰线代表个人客户
- 黑点是我们交易历史中的交易
- 灰点是我们的模型预测的交易
除了预测交易数量,我们的模型还预测这些未来交易的平均收入值。当我们知道每笔未来交易的价格和交易量时,我们可以很容易地计算出客户的 CLV。
评估模型
但是我们如何产生这些预测的交易和收入呢?更重要的是,我们如何知道它们有多精确?
首先,我们将交易历史数据分成两个数据集。我们通过确定数据集中最早的交易和最近的交易之间的大约 80%的日期来实现这一点。在此日期当天或之前发生的事务是校准期的一部分,之后发生的事务是保持期的一部分。之所以这样命名这些数据集,是因为校准期间的数据被输入到模型中进行校准,而维持期间的数据被故意保留下来以测试模型的预测能力。
如果一个模型可以使用校准期提供的数据准确预测维持期的数据,那么我们知道它是一个强模型。
比较模型
用于计算 CLV 的常见模型是帕累托/NBD 模型,尽管视网膜目前使用帕累托/GGG 模型,这是对帕累托/NBD 模型的改进。帕累托/GGG 模型之所以成为如此强大的 CLV 模型,是因为它创建了三个伽玛分布来确定客户交易间隔时间(ITT)和流失概率。如果你想更深入地探索它,你可以在原始论文或 BTYD 包中阅读更多关于这个模型的内容。
然而,Retina 团队还开发了一个更新的模型,目前正在与帕累托/GGG 进行比较。它被称为长短期记忆递归神经网络模型(RNN-LSTM)。这个模型接受一系列事件,寻找这些事件中导致现在的模式,这使它能够预测未来。我们向模型提供客户交易历史,希望它能够学习我们案例中的未来交易。
结果
重演 RNNs 和 PGGG 之间的对决
通过使用上面概述的校准/维持技术,我们能够看到每个模型的预测强度。我们还包括了额外的帕累托家族模型(BG/NBD 和 NBD)来为我们的结果提供背景。这是我们实验的结果:
我们测试的所有模型的聚合 CLV 统计数据
当我们将维持期内的实际事务数量与每个模型预测的数量进行比较时,我们可以看到每个模型的表现如何。上表按平均绝对误差(MAE)排序,即每个客户的预测交易数和实际交易数之间的平均差异。
除了 NBD,统计模型在这一指标上都表现强劲(与真实值的偏差小于 10%)。这意味着他们能够在总体水平上成功捕捉客户购买趋势。有趣的是,我们的 RNN-LSTM 模型是唯一低估抵制交易总数的模型。
该图比较了 RNN-LSTM 和帕累托/GGG 在每个客户不同采购金额上的准确性:
这张图表表明,RNN-LSTM 法案严重低估了流失的客户(在抵制期没有购买任何东西的客户),并高估了 3-4 个购买客户。帕累托/GGG 也低估了流失客户,高估了 3-4 个购买客户,但程度较轻。
讨论
起初,帕累托/NBD 似乎预测了接近完美的交易数量,这种准确性是由于预测的交易总数。正如我们在计算 MAE 时看到的,帕累托/NBD 在个人层面上的表现实际上比帕累托/GGG 和 RNN-LSTM 更差。在个人层面,CLV 是一个更具可操作性的指标,因此我们决定将进一步分析的重点放在这两个模型上。
回到我们的 CLV 拳击赛:当使用 MAE 时,帕累托/GGG 胜过 RNN-LSTM,但不是很多。这些结果是令人兴奋的,因为它不仅证明了帕累托/GGG 的优越性,而且证明了 RNN-LSTM 作为 CLV 计算的竞争者的有效性。
在考虑哪种模型更优越时,有两个概念变得与我们的结果无关,应该加以讨论:可扩展性和解释能力。
RNN-LSTM 是 CLV 计算的一个强有力的选择,因为它是可扩展的。与帕累托/GGG 不同,RNN-LSTM 采用了大量可以由运行模型的数据科学家定制和聚合的功能。这意味着 RNN-LSTM 可以通过网站访问、电子邮件,甚至特定的行业趋势获得信息,以创建越来越智能的迭代。
由于其解释能力,帕累托/GGG 是 CLV 计算的一个强有力的选择。与 RNN-LSTM 法案不同,后者在理解为什么做出某种预测方面本质上是一个黑匣子,帕累托/GGG 允许数据科学家理解模型做出的预测背后的底层框架。如果该模型似乎低估了流失客户,我们可以得出结论,这是一个过于乐观的流失预测伽马函数的函数。因此,当模型准确或比其他模型更好时,我们可以对为什么是更强的模型更有信心。对于机器学习模型,我们没有这种奢侈。
后续步骤
最后,有几个步骤将是建立在这些结果之上的激动人心的实验。我们热衷于尝试的一些未来迭代是:
- 预测维持中事务的值而不是数量,并在此指标上比较模型
- 向 RNN-LSTM 模型添加额外的相关特征,看看新架构是否明显优于帕累托家族模型
- 调整 RNN-LSTM 的超参数,以观察更智能的超参数选择是否会产生更好的模型
- 修改帕累托/GGG 输出以生成绘制的交易序列,以便与 RNN-LSTM 的预测能力进行直接比较
构建路标分类器
J.C .希门尼斯在 Unsplash 上的照片
学习使用 CNN 的力量
每年,汽车制造商都在他们的车队中增加更多的高级驾驶辅助系统 (ADAS)。其中包括自适应巡航控制(ACC)、前方碰撞警告(FCW)、自动泊车等。一项研究发现,在美国,ADAS 可以预防高达 28%的车祸。这项技术只会不断改进,最终会发展到 5 级,完全自动驾驶的汽车。
对于一辆完全自动驾驶的汽车来说,它需要能够了解它的环境。这包括其他车辆、行人和路标。
路标给我们关于法律的重要信息,警告我们危险的情况,并指引我们到达理想的目的地。如果汽车不能区分符号、颜色和形状的差异,许多人可能会严重受伤。
汽车观察道路的方式与我们感知道路的方式不同。我们都能瞬间分辨出路标和各种交通状况的区别。当把图像输入电脑时,他们只能看到 1 和 0。这意味着我们需要教会汽车像人类一样学习,或者至少像我们一样识别标志。
为了解决这个问题,我试图建立自己的卷积神经网络(CNN)来对交通标志进行分类。在这个过程中,主要有三个步骤:预处理图像、构建卷积神经网络、输出预测。
预处理图像
在预处理阶段,从“德国交通标志”位存储库中导入图像。这包含一个由标记的图像组成的数据集,它将允许我们建立一个监督学习模型。这个存储库可以克隆到 Google Colab 笔记本上,使得导入数据集和开始编码变得容易。
现在为了利用这个数据集,图像将通过一个灰度和均衡功能。
灰度
目前,来自知识库的图像是三维的。这是因为彩色图片有三个颜色通道——红色、绿色和蓝色(RGB ),它们相互叠加,赋予它们鲜明的色彩。
对于这个机器学习模型,三层图像是不必要的,只需要标志的特征。因此,通过灰度函数传递数据集图像可以清理我们的数据,只过滤重要的信息,还可以将图像缩减到一个维度。
三色通道图像的分解。(图片经由 Nevit Dilman 授权给 Kael Lascelle) 。
使相等
现在图像已经灰度化,它们失去了一些对比度,或者像素的白色或黑色。为了增加对比度,图像必须进行均衡。这一点很重要,因为模型必须区分通过对比度变化获得的各种特征。
均衡图像意味着展开像素值分布,创建更大范围的图像白色和黑色。
(图片由作者提供)
卷积神经网络
卷积神经网络是一类深度学习网络,用于分析视觉图像。在这种情况下,它被用于查找各种道路标志之间的独特的功能集。
CNN 的架构。(来源:【1489512765771.html https://www . mathworks . com/videos/introduction-to-deep-learning-what-is-convolutionary-neural-networks)
它使用的过程类似于我们的眼睛和大脑对我们看到的一切进行分类的方式。例如,当看一组数字时,你可以区分 1 和 8。1 是垂直线,而 8 是在另一个循环之上的循环。当然,你不会真的在脑子里这么说,因为我们已经见过他们很多次了,这已经成了一种习惯。
他们是如何学习的?
为了让卷积神经网络提取图像的重要特征,他们使用内核来扫描或跨越图像。
我把它想象成你的眼睛在图像上快速扫视。他们分析一个部分,然后水平移动到下一部分,直到你看到整个画面。
内核比较他们所看到的和他们正在寻找的之间的差异。当一个特征匹配时,它被记录并存储在特征图中。这些特征地图是原始图像的细化版本。他们保留了标志的重要特征,而忽略了其他特征。几个不同的核遍历原始图像并提取不同的重要特征,然后它们结合起来创建最终的卷积模式。
输出矩阵称为卷积特征或特征图。(来源:http://deep learning . Stanford . edu/wiki/index . PHP/Feature _ extraction _ using _ convolution)
解决过度拟合
当处理像模型中使用的小数据集时,出现了一个称为过度拟合的问题。这时模特开始记忆图像,而不是努力寻找它们的特征。更具体地说,当模型经历过多的时期(基本上就是模型经历数据集的次数)时,它开始监听一些节点的输入,而忽略其他节点。这降低了模型的准确性,因为它不知道如何对数据集之外的任何新图像进行分类。
为了解决它,增加了一个脱落层。这是对该模型的简单修正。通过删除节点的随机子集,它可以防止过度拟合,因为节点不能记住标签(因为节点很有可能被关闭)。这就像老师点名批评上课不专心的孩子。通过让他尴尬并引起他的注意,他会(希望)集中注意力并为班级提供价值。
预言;预测;预告
最后,该模型提供了一个交通标志的图像,它通过卷积神经网络运行,并吐出与相应标志相关的数字。
当下面的随机符号通过模型运行时…
展示给模型的随机图像。(来源:https://c8 . alamy . com/comp/g667w 0/road-sign-speed-limit-30-kmh-zone-passau-Bavaria-Germany-g667w 0 . jpg)
模型预测类为1,正确!
与符号关联的类。(图片由作者提供)
对代码感兴趣的人,可以在我的 GitHub 上找到,这里!
关键要点
- 使用灰度和均衡功能对图像进行预处理
- 卷积神经网络(CNN)使用核来提取符号的特征
- 将特征与其他分类图像进行比较,以做出预测
嘿,我是凯尔·拉塞尔,一个 16 岁的知识社会创新者!我对自主系统充满热情,尤其是自动驾驶汽车,以及可持续能源。
如果你能在 Medium 和 Twitter 上关注我,我将不胜感激!还有,在 LinkedIn 上加我,或者给我发邮件。
路面分类
一种路面类型和质量分类方法
你好。在这篇文章中,我们展示了一种对路面类型和质量进行分类的方法及其步骤。以及如何复制它的步骤。为了测试这种方法,我们使用了自己制作的 RTK 数据集。
路面分类
该数据集1由低成本相机拍摄的图像组成,场景在新兴国家很常见,包含未铺设的道路和坑洼。这是相关的,考虑到配有 ADAS(高级驾驶辅助系统)的车辆在新兴国家(如巴西)已经商业化。
路面的类型对于车辆的驾驶方式是重要的信息,无论是由人驾驶还是由自动车辆驾驶。除了乘客舒适度和车辆维护之外,它还涉及到所有相关人员的安全。我们可以用一个简单的卷积神经网络(CNN)结构来实现这一点。
进场顺序1
在这种方法中,我们使用特定的模型来完成表面类型分类任务,我们将这些类别定义为:沥青路面、已铺路面(适用于所有其他类型的路面)和未铺路面。对于表面质量,我们使用其他三种不同的模型,每种类型的表面一个模型。所有这四个模型都有相同的结构。我们从第一个模型中得到结果,称之为特定质量模型。
在 CNN 结构之前,感兴趣区域(ROI)被定义为每个输入帧的预处理步骤。毕竟,我们不需要整个图像来分类道路。该 ROI 旨在仅保留图像中实际包含道路像素的部分。图像的上半部分以及图像底部的一小部分被丢弃,因为在一些帧中,它可能包含负责捕捉图像的车辆的一部分。ROI 是硬编码的,因为如果我们使用自适应 ROI,它可能会失败并损害模型训练。
感兴趣区域1
在这个预处理之后,执行数据扩充步骤。数据扩充包括增加和降低每一帧的亮度。这样,我们改进了我们的训练输入集,并帮助我们的系统学习识别具有不同照明条件的相同类型和质量的道路。
最后,输入图像被传递到包含三个卷积层和两个全连接层的 CNN 结构。
全进路结构1
RoadTreversingKknowledge(RTK)数据集
在这种方法中使用的数据集,即RoadTraver singKknowledge(RTK)1是在巴西拍摄的,拍摄地点是圣卡塔琳娜州的瓜斯莫尔纳斯和圣阿马罗达普雷泽斯市,弗洛里亚诺波利斯的邻近城市。数据集包含具有不同类型表面和质量的图像。
RTK 样本1
RTK 数据集可从以下网址下载:
http://www . lapix . ufsc . br/pesquisas/projeto-vei culo-autonomo/datasets/?lang=en
路面类型分类
**完整的代码可在:**获得
在新兴国家,常见的是未铺砌的道路或没有维护的道路。未铺砌或损坏的道路也…
github.com](https://github.com/thiagortk/Road-Surface-Classification)
我们利用了 Python 、 TensorFlow 和 OpenCV 。
让我们一步一步地检查……
首先,我们需要建立我们的表面类型分类模型。为此,您需要准备用于训练模型的数据。您可以使用 RTK 数据集中的图像或制作自己的图像。图像需要按照路面类型进行组织。
培训数据文件夹结构
在我们的实验中,我们使用了 6264 帧:
- 铺面(沥青):沥青道路为 4344。
- 铺面(混凝土):1337 用于不同的铺面,如鹅卵石。
- 未铺路面:585 用于未铺路面、土路、越野。
接下来,在 train.py 中,我们定义从哪里收集训练数据。我们应该分离出 20%的数据自动用于验证。我们还将 batch_size 定义为 32。
在 train.py 上设置的参数将在 dataset.py 类上读取。
在 dataset.py 类中,我们定义了 ROI 和数据扩充。两个数据增强功能, adjust_gamma 降低亮度, increase_brightness ,其名称不言自明…
当加载输入数据时,对每幅图像进行 ROI 定义。
我们还平衡了输入的图像,因为有更多的沥青图像和更少的铺设和未铺设的道路。
回到 *train.py,*让我们定义 CNN 层,如这个 TensorFlow 教程 [2]所示。训练步骤中选择的所有图像都被传递到第一个卷积层,其中包含有关宽度、高度和通道数的信息。前两层有 32 个大小为 3×3 的过滤器。随后是具有 64 个大小为 3×3 的过滤器的层。所有步幅定义为 1,填充为 0。正态分布用于权重初始化。为了在维度上减少输入,这有助于分析输入子区域中的特征信息,在所有卷积层中应用最大池。在每个卷积层的末端,在 max-pooling 函数之后,ReLU 被用作激活函数。
在卷积层之后,展平层用于将卷积多维张量转换成一维张量。
最后添加两个完全连接的层。在第一个完全连接的层中,应用了 ReLU 激活功能。第二个完全连接的层具有可能的输出,即期望的类。
我们使用 softmax 函数来获得每一类的概率。我们还在最后使用 Adam 优化器,它根据训练中使用的输入数据更新网络权重。
您可以在您的终端中训练模型运行:python train.py
。
现在,有了训练好的模型,我们就可以测试了。首先,让我们准备接收输入测试帧和输出文件名。
检索经过训练的模型并访问图表。
请记住,我们不需要整个图像,我们的培训侧重于使用 ROI,这里我们也使用它。
最后,基于输出预测,我们可以在每一帧中打印分类的表面类型。
您可以在您的终端:python test.py PATH_TO_YOUR_FRAMES_SEQUENCE NAME_YOUR_VIDEO_FILE.avi
中测试运行的模型。
道路质量分类
现在让我们包括质量分类。我们简单地使用用于训练表面类型分类模型的相同 CNN 体系结构,并分别应用于每个表面类别上的每个质量类别。因此,除了现有的模型,我们还训练了 3 个新模型。为此,您需要为每个表面类别准备用于训练模型的数据。在 RTK 数据集页面中,我们已经给出了按类组织的帧。
质量分类的培训数据文件夹结构
要训练每个模型,请在您的终端中运行:
python trainAsphaltQuality.py
python trainPavedQuality.py
python trainUnpavedQuality.py
现在改变的是预测部分。我们使用四种不同的图形,每种图形对应一个训练好的模型。
恢复类型模型
恢复沥青质量模型
恢复铺设质量模型
恢复未铺设的质量模型
此时,输出预测也考虑质量模型,我们可以打印分类的表面类型以及每个帧中该表面的质量。
打印结果
您可以在您的终端中测试运行:python testRTK.py PATH_TO_YOUR_FRAMES_SEQUENCE NAME_YOUR_VIDEO_FILE.avi
。
部分结果样本:
路面分类结果1
视频与结果:
如果您有任何问题、批评或建议,请随时联系我们。我希望下次能见到你。🤘
这个实验是来自 LAPiX (图像处理与计算机图形实验室)的 项目 的一部分。
承认
这项工作是一组积极参与的研究人员共同努力的结果:
- 蒂亚戈<rateke.thiago@gmail.com>
- Karla Aparecida Justen<justen.karla@gmail.com
- 奥尔多·冯·万根海姆 < 奥尔多. vw@ufsc.br >
@article {rtk:2019,
作者= ,
标题= {利用从低成本相机捕获的图像进行路面分类—道路穿越知识(rtk)数据集},
期刊= { Revista de informática teóRica e Aplicada(RITA)},【关键词
参考文献
1 T. Rateke,K. A. Justen 和 A. von Wangenheim, 利用低成本摄像机拍摄的图像进行路面分类——道路穿越知识(RTK)数据集 ,(2019),《哥斯达黎加与应用信息杂志》(RITA)
[2] A. Sachan, Tensorflow 教程二:利用卷积神经网络的图像分类器 ,(2017),CV-Tricks.com
请参见
检测坑洞,水坑,不同类型的地形和更多
towardsdatascience.com](/road-surface-semantic-segmentation-4d65b045245) [## 两种不同传感器的视觉深度估计
来自被动和主动视觉低成本传感器的立体视差图和点云
medium.com](https://medium.com/analytics-vidhya/visual-depth-estimation-by-two-different-sensors-36f756d1575a)
路面语义分割
检测坑洞,水坑,不同类型的地形和更多
你好。这篇文章是关于路面语义分割方法的。因此,这里的重点是路面模式,如:车辆行驶在何种路面上,或者道路上是否有任何损坏,道路标记和减速带以及其他与车辆导航任务相关的东西。
在这里,我将向你展示基于在自主机器人 (Springer) 1的论文的一步一步的方法。地面实况和实验是使用 RTK 数据集【2】进行的,图像是用低成本相机拍摄的,包含不同路面类型和不同路面质量条件的道路图像。
制作它很有趣,我很高兴分享它,我希望你也喜欢它。🤗
简介
这种方法的目的是验证使用被动视觉(摄像机)检测道路上不同模式的有效性。例如,识别路面是柏油路还是鹅卵石路还是未铺设的(泥土)路?这可能与智能车辆有关,无论它是自动驾驶车辆还是高级驾驶辅助系统(ADAS)。根据路面的类型,可能需要调整车辆的行驶方式,无论是为了使用者的安全还是车辆的保护,甚至是为了车内人员的舒适。
这种方法的另一个相关因素与检测坑洞和水坑有关,坑洞和水坑可能会造成事故,损坏车辆,在发展中国家可能相当常见。这种方法对于负责维护高速公路和道路的部门或组织也很有用。
为了实现这些目标,卷积神经网络(CNN)被用于路面的语义分割,我将在接下来的章节中详细讨论。
地面实况; 真值(机器学习)
为了训练神经网络并测试和验证结果,使用来自 RTK 数据集的 701 幅图像创建了地面实况(GT)。该 GT 在数据集页面上可用,由以下类组成:
燃气轮机分类1
GT 样品1
方法和设置
这里所做的一切都是使用 Google Colab 完成的。这是一个免费的 Jupyter 笔记本环境,让我们可以免费访问 GPU,非常容易使用,也非常有助于组织和配置。也有人用了fastai【3】,令人惊叹的深度学习库。更准确地说,我将展示的一步一步在很大程度上是基于杰瑞米·霍华德在一门关于深度学习的课程中的一节课,在这里是第 3 课——cam vid。
使用的 CNN 架构是 U-NET [4],这是一种设计用于执行医学图像语义分割任务的架构,但也成功应用于许多其他方法。此外,使用了基于 ResNet [5]的编码器和解码器。该方法的实验是在 resnet34 和 resnet50 上进行的。
对于数据扩充步骤,使用了来自 fastai 库的标准选项,应用了水平旋转和透视变形。使用 fastai 可以对原始图像和掩模(GT)图像进行相同的数据扩充步骤。
与此相关的一点是,对这种方法的定义非常重要的是,GT 的类别相当不平衡,具有比其他类别大得多的背景或表面类型(例如:沥青、铺砌或未铺砌)像素。与影像分类问题不同,在影像分类问题中,从数据集中复制某些影像可能有助于平衡类别,在这种情况下,复制影像将意味着进一步增加最大和最小类别之间的像素数量差异。然后,在定义的方法中,在类中使用权重进行平衡。🤔
基于不同的实验,人们认识到仅应用权重是不够的,因为当提高包含少量像素的类的精度时,包含大量像素的类(例如:沥青、已铺路面和未铺路面)会降低精度结果的质量。
考虑到所有类别,在不损失太多表面类型检测质量的情况下,最佳精度值为以下配置:首先不使用权重来训练模型,为表面类型生成具有良好精度的模型,然后,使用之前训练的模型作为下一个模型的基础,该模型使用类别的比例权重。就是这样!
你可以在 GitHub 上查看完整的代码,我将在这篇文章中对此进行评论:
用于道路表面的语义分割 GT 包含来自 RTK 数据集的 701 帧。
github.com](https://github.com/thiagortk/Road-surface-detection-and-differentiation-considering-surface-damages)
循序渐进
你准备好了吗?
来自 https://giphy.com/的 gif 图片
酷,所以我们从初始设置开始,导入 fastai 库和 pathlib 模块。姑且称之为第一步。
步骤 1 —初始设置
因为我们将使用来自 google drive 的数据集,所以我们需要挂载它,所以在下一个单元格类型中:
您将看到类似下图的内容,单击该链接,您将获得一个授权码,因此只需将授权码复制并粘贴到预期字段中。
来自作者
现在只需将你的 Google Drive 作为一个文件系统来访问。这是步骤 2 的开始,加载我们的数据。
步骤 2 — 准备数据
其中“图像”是包含原始图像的文件夹。“标签”是包含我们将用于训练和验证的遮罩的文件夹,这些图像在色彩映射表移除过程后是 8 位像素。在“颜色标签”中,我已经放上了原始的彩色蒙版,我们可以用它来进行视觉对比。“ valid.txt ”文件包含随机选择用于验证的图像名称列表。最后,“ codes.txt ”文件包含一个带有类名的列表。
来自作者
来自作者
现在,我们为原始图像和 GT 遮罩图像定义路径,以便以后能够访问每个文件夹中的所有图像。
我们可以看到一个例子,数据集的图像 139。
来自作者
接下来,如 fastai 课所示,我们使用一个函数从原始图像中推断蒙版文件名,负责每个像素的颜色编码。
第 3 步——第一步——无重量
我们到了第三步。让我们使用数据块 API 创建 DataBunch 来训练我们的第一个模型。定义我们的图像来自哪里,哪些图像将用于验证,以及对应于每个原始图像的遮罩。对于数据扩充, fastai 库也给出了选项,但是这里我们将只使用默认选项和get_transforms()
,它由随机水平旋转和透视扭曲组成。记住在 transform 调用中设置tfm_y=True
,以确保数据集中数据扩充的转换对于每个遮罩及其原始图像都是相同的。试想一下,如果我们旋转了原始图像,但是那个图像对应的蒙版却没有旋转,那该是多么的混乱啊!😵
我们继续使用来自 fastai 课程的 lesson3-camvid 示例来定义精度指标和重量衰减。我之所以使用 resnet34 模型,是因为在这个数据集上使用 resnet50 并没有太大的区别。我们可以使用lr_find(learn)
找到学习率,在我的例子中,我将它定义为1e-4
。
来自作者
接下来,我们运行fit_one_cycle()
10 次,检查我们的模型做得如何。
来自作者
使用混淆矩阵,我们可以看到到目前为止每个类的模型有多好(或多差)
来自作者
不要忘记保存我们到目前为止训练的模型。
现在,我们只是在更多的时期内训练模型,以改进学习,并记住保存我们的最终模型。slice 关键字用于获取起始值和终止值,因此在第一层中,以起始值开始训练,并且当到达训练过程的末尾时,该值将改变,直到终止值。
来自作者
这是我们的第一个模型,没有重量,适用于路面,但不适用于小班。
来自作者
步骤 4-第二部分-重量
我们将在下一步中使用第一个模型。这一部分几乎与第 3 步完全相同,因为数据集中,我们只需要记住加载我们以前的模型。
并且,在我们开始训练过程之前,我们需要在班级里放重量。我定义这些权重是为了与每个类在数据集中出现的数量(像素数)成比例。*我用 OpenCV 运行了一个 python 代码,只是为了计算 GT 的 701 幅图像中每个类别的像素数量,以了解每个类别的比例…😓
剩下的部分和前面的第三步完全一样。得到的结果有什么变化。😬
来自作者
现在,看起来我们对所有职业都有了一个更合理的结果。记得存起来!
结果
最后,让我们看看我们的图像,对不对?在做任何事情之前,最好保存我们的结果,或者我们的测试图像。
但是,等等!图像看起来全黑,我的结果呢???😱冷静下来,这些是结果,只是没有彩色地图,如果你在整个屏幕上打开这些图像中的一个,在高亮度下,你可以看到小的变化,“11 个灰色阴影”🙃。所以,让我们的结果颜色更像样?现在我们将使用 OpenCV 并创建一个新文件夹来保存我们的彩色结果。
因此,我们创建一个函数来识别每个变化,并给每个像素着色。
接下来,我们读取每个图像,调用函数并保存最终结果。
但是,这个过程可能会花费不必要的时间,使用%timeit
我们可以实现如下性能:
来自作者
想象一下,如果我们需要用更多的图像来测试呢?我们可以使用 Cython 加快这一步。所以,让我们把一撮 Cython 放在那上面!
来自https://giphy.com/的 gif
因此,我们编辑我们的函数来识别每个变化并给每个像素着色,但是这一次,使用 Cython。
我们只是读取每张图片,调用函数,然后像之前一样保存最终结果。
瞧啊。现在我们有一个表现为:
来自作者
好多了,对吧?
一些结果样本
下图是一些结果。左边一栏是原始图像,中间一栏是 GT,右边一栏是用这种方法得到的结果。
改编自1
结果视频
讨论(大家来说说吧)
识别路面状况在任何情况下都很重要,基于此,车辆或驾驶员可以适应并做出决定,使驾驶更加安全、舒适和高效。这一点在发展中国家尤为重要,因为这些国家可能面临更多的道路维护问题,或者有相当数量的未铺设道路。
这种方法看起来很有希望处理路面变化的环境。这对于公路分析和养护部门来说也很有用,以便使他们在评估公路质量和确定哪里需要养护方面的部分工作实现自动化。
然而,一些点被确定和分析为有待改进。
对于分段 GT,将一些类别划分为更具体的类别可能会很有意思,例如裂缝类别,用于不同的损坏,而与道路类型无关。因此每种类型的表面具有不同的裂纹,因为不同的表面具有不同类型的损伤。同样把这个职业分成不同的职业,在每个新的职业中对不同的伤害进行分类。
目前就这些。请随时联系我。🤘
承认
这个实验是来自 LAPiX (图像处理和计算机图形实验室)的关于车辆导航视觉感知的 项目 的一部分。
如果你要谈这个 方法 ,请引用为:
@ article*{ Rateke:2020 _ 3,* 作者*= ,* 标题 = { 路面检测与考虑路面破损的判别 }, CV},
}
参考
1 T. Rateke,A. von Wangenheim。 考虑路面破损的路面检测与区分 ,(2020),自主机器人(Springer)。
[2] T. Rateke、K. A. Justen 和 A. von Wangenheim。 【利用低成本摄像机拍摄的图像进行路面分类——道路穿越知识(RTK)数据集 ,(2019),《哥斯达黎加与应用信息杂志》(RITA)。
3 J .霍华德等著 fastai (2018)。https://github.com/fastai/fastai
[4] O .龙内贝格,p .菲舍尔,t .布罗克斯 U-net:用于生物医学图像分割的卷积网络 ,(2015),NAVAB,n .等(编。).医学图像计算和计算机辅助介入— MICCAI 2015。查姆:施普林格国际出版公司。
[5] K. He 等著(2016)IEEE 计算机视觉与模式识别大会(CVPR) 。
请参见
一种路面类型和质量分类方法
towardsdatascience.com](/road-surface-classification-150f9874faef) [## 两种不同传感器的视觉深度估计
来自被动和主动视觉低成本传感器的立体视差图和点云
medium.com](https://medium.com/analytics-vidhya/visual-depth-estimation-by-two-different-sensors-36f756d1575a)****