我在担任数据科学总监的前 6 个月学到了什么
在不同行业中转换到新角色的挑战和回报
伊恩·施耐德在 Unsplash 上拍摄的照片
在 6 个月前开始担任一个数据科学团队的主管之前,我做了许多其他人在面对新事物时会做的事情:我在媒体上搜索关于其他人在这个过程中所学到的东西的帖子。我没有找到很多关于成为数据科学经理的帖子(尽管我发现这篇帖子非常有帮助!).有很多关于数据科学的技术方面以及如何管理数据科学项目的帖子,但是没有多少关于如何管理数据科学团队的帖子。所以我想当我习惯了这个新角色后,我会分享我的经验。
TL;在这篇文章中,我将首先关注我面临的最大挑战:(1)适应一家非科技公司,以及(2)招聘和雇佣(在某些情况下,这与第一位相关)。到目前为止,我还有其他的挑战,但是我想我会从这两个开始,因为它们占据了我一天至少 75%的时间。敬请关注未来关于其他挑战和观察的帖子!
关于我的一点…
我对管理并不陌生,但最近一直在科技公司做 IC。为什么?我错过了编码和进入本质的技术细节。
当我说我不是管理新手时,我的管理经验在数据科学方面还没有达到 100%。几年前,我管理过一个团队,既有人事方面的,也有项目方面的。但是他们玩得很开心,坦白地说,我很嫉妒我没有和他们一起玩键盘。
在之前的工作中,我是 R1 大学的教授,从事应用数据科学和机器学习的前沿研究。大多数人不认为这是一项管理工作,但如果你仔细想想,它确实是。虽然有教学成分,但在 R1 大学,研究是至高无上的。但是这对教授的日常生活意味着什么呢?首先也是最重要的是,通过撰写许多冗长的提案来获得工作资金。这意味着能够证明你可以管理预算。第二,同样重要的是,这意味着招募一支团队。在巅峰时期,我的团队有 2 名博士后、10 名研究生和大约 20 名本科生。任何教授的研究小组的成功都与他们能够招募到实验室的学生的质量密切相关。他们都需要得到指导。他们都有不同的技能和经验水平。他们都需要定期接受绩效评估并给出反馈。他们都有人际关系问题,有时会影响团队。所以,是的,在 R1 担任教授是一项管理工作,同时还得兼职教授一些课程。
那么,如果我如此热爱编码,我为什么还要回到管理层呢?我想这是因为我意识到我也喜欢影响数据科学的方向。作为一名 IC 数据科学家,你的日常工作(理想情况下)是解决问题,编写和审查代码,并记录你的工作。我在担任 IC 期间发现,我没有太多机会坐在桌前讨论特定问题的业务需求,以及数据是否能够真正解决该问题。我没有能力推动数据科学工作的方向。我发现我错过了。
基于此,我接受了一份我梦寐以求的工作:领导一个在滑雪行业工作的数据科学团队——这是我热爱的行业。
照片由 Astrid Schaffner 在 Unsplash 拍摄
关于我的公司…
滑雪产业不是科技。让我们面对现实吧。这个行业可能已经存在了几十年,但它不是由花很多时间思考数据的人创建的。创立这个行业的人,都很会治山。然而,总的来说,它最初并不是以数据为中心的。
然而,我最近的工作是在技术领域。这对数据科学经理来说到底意味着什么?这意味着我们在构建基础架构解决方案的同时,通常还会构建数据科学解决方案。我花了相当多的时间谈论和解决科技公司的数据科学家可能认为理所当然的问题。比如我们应该在什么云平台上,有什么正确的工具(想想版本控制,CI/CD,集群管理等等。)我们应该用那里?对于我们的海量数据,什么是正确的存储解决方案?(看到我在那里做了什么吗?;) )当我们有大量不同的数据源时,即使是同一类型的数据,每个数据源都有自己的模式和噪声源,它们都必须很好地协同工作,我们该怎么办?在科技公司,这些问题很大程度上得到了解决或者很容易处理。如果这些问题还没有解决,会有一小群人来解决它们。但在非技术领域,数据科学家必须是多面手,对全栈解决方案之类的东西要了解得多,对某个主题的技术深度要了解得少。除了决定合适的平台和工具之外,同样重要的是能够将这些决定传达给业务部门,无论是在价值方面还是在证明成本的合理性方面。
有时候我觉得这很有挑战性。其他时候,我发现这是一个产生积极影响的好机会。我非常相信,一个人在这样一个角色中的快乐是找到一种看待事物的方式,更像是后来的事情…并且帮助他们的团队也这样做。
由 Eric Prouzet 在 Unsplash 上拍摄的照片
到目前为止,我面临的最具挑战性的问题是:招聘
任何阅读这篇文章的人都知道,获得合适的数据科学人才是非常非常困难的。数据科学家被比作独角兽。它是一种独特的技能,由许多复杂的专业技术领域组成,包括编码、统计和商业技能。对我来说,这意味着吸引和争夺最佳人才的竞争异常激烈。当我还是一名教授时,有一位招聘人员联系我,说金融科技公司有一份数据科学家的工作,起薪是每年 100 万美元,外加奖金。是的,真的。(我没拿……我觉得那种工资的附加条件不值得。)
FAANG 公司(脸书-苹果-亚马逊-网飞-谷歌)能够支付惊人的薪水。但是大多数雇佣数据科学家的公司都不是那样的。不要误会我!数据科学家仍然可以过上非常体面的生活!但是在实际实践的世界里,非技术数据科学家,事情要现实得多。不幸的是,这意味着我在和 FAANG 公司争夺人才。
因此,我不得不在刊登广告和招聘的地方变得非常有创意。数据科学家总是会在 FAANG 公司找工作,但他们并不总是认为非科技公司雇佣了数据科学家。因此,这意味着我已经知道,在推销我的空缺职位时,我必须更加主动。LinkedIn 很棒,招聘人员可以提供帮助。然而,我也发现在不寻常的在线论坛——如 Discord、Slack 和 Twitter——招聘中取得了巨大成功。
但是不要搞错:招聘数据科学家是一项全接触的运动!很乱。你必须迅速行动。简化面试流程对于快速发现人才至关重要。仔细想想你希望你的技术面试是什么样的,应该持续多长时间。因为在不到一周的时间内,理想的候选人就会从你的手下被雇用!
角色和级别
在我的团队中,我们既有数据科学家,也有机器学习工程师。关于这两者之间的区别有很多讨论,这种讨论自然也发生在我的团队中。在我到来之前,它的结构是这样的,我一直保持着这种结构:
**数据科学家:**自己创建模型的人。
机器学习工程师 (MLEs,在其他地方也被称为“数据工程师”):为数据科学家开发的模型创建管道的 MLOps 人员。
我可以告诉你,雇佣数据科学家比 MLEs 容易得多。教授基本的数据科学技能很容易,而且很多都可以在您的本地机器或小型云实例上完成。然而,如果你想一想,让学生访问包含大量数据的复杂云管道是复杂和昂贵的。所以预计需要一段时间才能找到一个有经验的 MLE!
就均衡而言,我的团队有三个级别:数据科学家/MLE、高级和负责人。我现在正在更新我们的水平指南。总的来说,我认为入门级别的角色是那些了解主题基础并能够完成分配给他们的特定任务的人。对我来说,高层就是拥有一个项目,给你一个问题,把它分解成一系列的任务,编码完成它。最后,负责人自己识别问题,指导团队解决这些问题,并创建高层次的解决方案来帮助团队解决问题。
另一方面,我的工作是让团队能够完成他们的工作,同时与其他经理和利益相关者合作,确定问题的范围并交流解决方案。在包括技术和非技术的许多环境中,像“经理/高级经理”和“主管”这样的角色是有区别的前者主要是向下管理,处理团队的日常“照顾和喂养”,而后者是向下管理和向上管理之间的一个奇怪的中间地带。我发现,在我目前的职位上,向下管理和向上管理各占一半。
给求职者的建议
首先,认真阅读招聘广告。看期望的技能是什么。以上面的角色为例,在工作描述中,你可能是你之前的角色塑造模型中的 MLE。然而,因为这些职称模糊不清,你可能在其他地方被认为是数据科学家。
第二,FAANG 公司希望你在高压力的环境下回答非常复杂的问题、结对程序和/或白板。关于如何准备这种类型的面试,有很多博客帖子。这些面试很紧张,需要几个月的学习。但是对于世界上的其他人来说,这不是标准(也不实际),你真的不会被期望在你的工作中那样工作。做好基础准备。保持简单,易于沟通。
最后,保持简历简洁明了。信不信由你,招聘经理看简历的平均时间是 6 到 7 秒。(不信的话,看这个。)不要在分散 6-7 秒注意力的内容上浪费空间,比如目标陈述。快点吃肉。如果你不知道那是什么,招聘广告会告诉你。
结论和我认为未来 6 个月我可能会期待的事情
我头 6 个月的大部分时间都花在了学习非科技实体的数据科学工作方式以及招聘和雇用上。我学会了新的方法来看待数据科学和基础设施与整体业务的关系,以及如何向非技术经理传达投资回报(ROI)。我也学到了在招聘时既有创造性又积极主动的重要性。FAANG 公司可能不需要宣传他们雇佣了数据科学家,但我需要。我在招聘方面的大部分成功来自于在不寻常的地方张贴我的招聘广告。
虽然我没有预测未来的水晶球,但有些事情我想我可以满怀信心地说,未来 6 个月会是什么样子。
首先,很难确定最近的技术裁员会对我的招聘产生什么影响。然而,一些被解雇的人已经找到了我,所以我无法想象不会有影响。第二,我真的不应该在提到“招聘”和“雇用”的时候不包括“保留”这个词。但是,留住人才也需要考虑整个科技就业环境中正在发生的事情。最后,与任何类型的人一起工作都是复杂的。任何一个经理都把这种考虑作为他们工作的一部分。然而,我认为在这方面管理数据科学家面临一些独特的挑战。例如,这个领域发展得非常快,可能比其他软件开发领域更快。当我开始做集成电路的时候,那些尖端的工具现在已经过时了。新的工具和方法不断出现。让数据科学家团队对所有这些进步保持新鲜和最新是我一直在想的。这很可能是它自己的博客文章。
敬请期待!
我在实现计算机视觉论文时学到了什么
同时练习多种技能的有效方法
Emile Perron 在 Unsplash 上的照片
作为计算机视觉工程师,我的一个朋友和我在想一种新的方法,可以同时提高多项技能,既有效又省时。我们想到了在 GitHub 上实现计算机视觉论文的想法。在这篇短文中,我想谈谈我们在这个过程中遇到的所有有趣的细节,我们遇到的所有积极和消极的发现。
首先是正面。
计算机视觉技能
要完成一篇论文,你需要理解它的每一个细节。有些章节你可能需要读 10 遍以上。有时候,要理解一个小概念,可能需要看很多其他的参考论文。结果,您获得了 T 形知识:您试图实现的主题的广泛知识,以及特定模型和技术的更深入的知识。
编程技巧
社区面前的责任来了。当你在做一个开源项目时,你觉得有责任让其他人更容易理解。为了编写一小块代码,你开始花越来越多的时间去寻找最佳的、可理解的、有用的和有效的方法。
其他你认为不会提高的技能
首先,看起来你在两个方向努力:深度学习知识和编程技能。然而,事实证明,要做到这一点,你需要学习很多东西。
- 为整个过程创建工作流程的项目管理技能:创建任务并确定其优先级,相互分配任务等。
- 沟通技巧:与合作者沟通,互相帮助,审查代码。
- 所有权和责任:拥有所有权和责任,使团队工作更有效,对你的任务和整个项目负责。
还有很多需要学习和提高的地方,在这个过程中你会发现的。
与全世界合作
GitHub 和其他平台的最大优势是它可以帮助你分享你的作品,并获得他人的帮助。当世界各地的人们在不了解你个人和你的技能的情况下开始和你一起工作,为了一个目的:社区贡献,这是一种奇妙的感觉。
群体反应和兴趣
社区贡献对我们每个人来说都是一个绝佳的机会。从想要使用你的库的人那里得到反馈是非常有价值的。许多问题、请求和未解决的问题会对你的工作产生巨大的影响。
现在让我们深入探讨一下我们遇到的不利因素。
由 Unsplash 上 Elisa Ventur 拍摄的照片
论文结构和内容
许多论文很难实现,因为作者可以接受的写作方式。有时候,为了理解一个小概念,你可能需要上下百万次才能找到一个答案。许多论文甚至不包含实验部分:他们如何做实验,设置实验的元素,以及模型和技术描述的一些一般元素。你需要假设许多细节,或者查阅其他类似的论文、参考资料来理解这些细节。
计算问题
现在,来自最好的研究实验室的许多计算机视觉论文看起来像一个收集并结合了来自其他论文的不同概念的拼图。他们的主要不公平优势之一是他们拥有的计算能力。他们可以使用大量不开放的数据,以及我们无法负担的巨大计算能力。这就是为什么有时不可能重复他们的实验并检查他们的结果。
结论
尽管在实现过程中你可能会面临一些挑战,但这是值得做的,因为你将提高技能,并从这个过程中获得乐趣。尤其是当你看到来自社区的支持和帮助时,你肯定会明白你为什么要这么做。我建议每个人都把这个练习作为他们学习过程的一部分。找到你喜欢并想学的东西,并开始为之努力。如果你需要帮助,社区会帮助你。
GitHub 库:https://github.com/LilitYolyan
在使用卡尔曼滤波器进行目标跟踪时,我错过了什么
不测量时如何估计物体的速度
由 Jure Zakotnik 在 Unsplash 上拍摄的照片
介绍
卡尔曼滤波器是一种复杂的算法,在大多数情况下,人们在没有完全理解其方程的情况下使用它。
当我开始使用卡尔曼滤波器时,我也是这样做的。我阅读了一堆试图直观地解释算法的教程,但这样做,忽略了关于协方差矩阵的作用的关键部分。
我正在开发的产品是一个基于检测的物体追踪器。其中,卡尔曼滤波器用于预测和更新给定视频流中对象的位置和速度,以及对每一帧的检测。在某些情况下,我们还想通过调整给定运动角度的对象的位置来考虑摄像机的倾斜和平移。当然,物体的速度应该不受这种摄像机运动的影响。
但是,当开始实施这一调整时,我意识到我并不真正理解速度是如何估算的。我假设在这个过程中的某个地方,有一个给定的先前和当前位置的速度的显式计算(在我们的例子中,速度从来没有被直接测量)。我还假设这个速度和位置的处理方式是一样的。令我惊讶的是,这两个假设都被证明是错误的。
这让我深入卡尔曼滤波器的方程,试图尽可能直观地找出到底发生了什么,但不要过于简化。这个博客总结了我在这个过程中学到的东西。
由于这不是一个介绍性的博客,我将假设你熟悉概率论的基本概念,如概率分布函数,高斯分布和贝叶斯定理。此外,我们将使用矩阵乘法和加法进行一些计算。所以如果你也熟悉这一点就更好了。
概观
卡尔曼滤波器是一种算法,设计用于在给定这些变量的连续测量值以及这些测量值中的不确定性量的情况下,估计一段时间内测量变量的值。卡尔曼滤波器还考虑了估计变量之间的给定关系。
让我们以在视频中跟踪乒乓球的过程为例,给定球的 2D 包围盒检测。检测可能包含给定 bbox 的坐标中的一些不准确性,或者由假阳性/假阴性引起的不准确性。
对几个连续帧的典型检测。bboxes 并不总是完美的,有时会完全丢失(假阴性)。(视频由 cottonbro 提供)
为了更平滑地跟踪球,我们将想要跟踪测量的 bbox 的中心坐标( x 、 y )、宽度和高度。假设一个运动的球的速度可以在短时间间隔内近似为常数,我们也想跟踪 x 和 y 的速度( v_x , v_y ),希望得到这些预测:
卡尔曼滤波器的预测是绿色的,平滑检测(红色)。(视频由 cottonbro 提供)
通常,当试图解释卡尔曼滤波器时,人们会使用一个使用位置和速度测量来跟踪对象的例子(例如 GPS 和速度计)。在我们的例子中,我们没有速度的直接测量。相反,卡尔曼滤波器使用测得的位置和我们注入到其方程中的关于我们期望的运动行为(在这种情况下为恒定速度)的先验知识来推断该速度。
为了简单起见,从现在开始我们只讨论 x 和v _ x的跟踪(1D 跟踪的一个例子)。理解了 1D 发生的事情后,逻辑可以很容易地扩展到二维和三维,因为在我们的例子中,每个维度都完全独立于其他维度。
假设
使用卡尔曼滤波器时有两个重要假设:
- 传感器有噪声,其输出和噪声可以通过高斯概率分布函数(PDF) 精确建模。
- 我们对实际状态的初始先验知识也是高斯 PDF。
在我们的示例中,传感器输出由 1D 高斯表示,其中均值等于实际传感器输出,方差是传感器的不确定性(主要根据经验测量)。
先验高斯是二维的(一个用于位置,一个用于速度)。使用 6 个数字可以完整地描述 2D 高斯:2 个用于其中心坐标向量(也称为平均值),另外 4 个用于 2x2 协方差矩阵。
协方差矩阵的对角线对应于每个维度的方差,2 个非对角线元素是位置和速度之间的实际协方差。由于协方差的对称性,非对角线元素总是相同的,即,x 和 y 之间的相关性与 y 和 x 之间的相关性相同(我们将在后面更详细地讨论这个元素)。
不同协方差矩阵对应的 2D 高斯分布
卡尔曼滤波器将尝试使用输入检测来更新平均值和协方差。常见的术语是将这种分布称为系统状态。
在我们的例子中,我们将使用下面的初始状态:
平均位置 μ_x 取自第一个检测到的 bbox 的 x 位置,我们假设一些初始速度 μ_v 。我们还假设,最初速度和位置之间没有协方差。我们可以用图形将这种初始状态绘制如下:
典型的初始状态。在这个阶段没有相关性(这将随时间变化),因此高斯曲线具有轴对齐的椭圆形。
算法步骤
为了发挥它的魔力,卡尔曼滤波器有两个步骤:预测,在这个步骤中,它试图预测当前的状态,给定先前的状态和从那时起已经过去的时间。**更新,**尝试将预测状态与输入测量值结合。让我们用我们的例子来看看这是如何发生的。
预测步骤方程
给定经过的时间,为了预测下一个状态,卡尔曼滤波器使用状态转移矩阵( F ),(也称为物理模型),该矩阵将前一个状态与当前状态联系起来。在我们的例子中,由于我们假设在短时间间隔内速度恒定(大约几帧),状态转移矩阵为:
这样,如果我们把它乘以我们的状态均值向量,我们得到预测的均值:
预测新的平均值是不够的。我们预计,如果时间已经过去,那么协方差矩阵(代表状态的不确定性)也将改变。为了预测新的协方差,我们将使用随机变量的线性变换公式(参见此处了解详情)并添加一个噪声对角矩阵。这种噪声被称为“过程噪声”,它包含了自我们上次更新状态以来经过的时间所产生的不确定性,并且在我们的物理模型中没有考虑到。因此,在我们的例子中,它可以表示非恒定速度和相机运动。通常用 Q 表示。因此协方差预测方程如下:
如果我们为初始状态解这个方程:
注意,除了过程噪声增加的额外不确定性之外,位置方差也增加了一个系数:
这个因素源于我们在将 F (物理模型)定义为非对角矩阵时引入的位置和速度之间的相关性。可以这样理解:给定预测位置是状态速度的函数,这个预测位置的不确定性就是我们之前状态的不确定性加上速度的不确定性乘以它们耦合的因子(平方,单位为)。
这里需要注意的另一件事是新引入的协方差因子:
这意味着我们的高斯维度不再独立。这更容易用图形来解释,所以我们就这么做吧。
预测步骤直觉
从图形上看,更新步骤如下所示:
这里发生了什么?为什么我们的状态突然横过来了?这是因为位置和速度不是两个独立变量。状态的速度直接影响预测的位置。直觉上,这意味着更高的速度应该对应更远的位置,反之亦然。从数学上来说,这由我们的状态转移矩阵(F)不是对角的这一事实来表示。非对角线元素δt 将位置和速度联系在一起。
由于这种耦合,每个更新步骤都会在协方差矩阵中引入非对角元素,这在图形上对应于我们的分布的移动,如上面的 GIF 所示。
更新步骤直觉
这一步在数学上有点复杂,但直觉上也很简单。在该步骤中,卡尔曼滤波器将接收两个可能的状态作为输入(定义为高斯 pdf ),并输出一个新的状态,该状态结合了来自两者的信息。
在深入描述这一过程的方程之前,这里有要点:以统计最优的方式组合来自两个(或更多)pdf 的信息,相当于将它们相乘。由于高斯分布的特殊性质,这种乘法的乘积是另一种具有均值和协方差的高斯分布,可以通过(相对)简单的方程获得。
现在了解更多细节。更新过程可以被认为是贝叶斯推理。如果我们将我们正在跟踪的物体的实际位置(我们实际上不知道)定义为 x ,并且将实际测量的位置定义为 m ,我们得到以下更新等式:
卡尔曼滤波器中使用的贝叶斯定理
让我们在卡尔曼滤波器的背景下理解这些术语:
- 后验:给定测量,实际位置的概率分布。这就是我们想要使用更新步骤来推断的内容。
- 可能性:给定实际位置,测量的概率分布。这被假设为实际位置周围的高斯分布(如“假设”部分所述)。
- 先验:在测量之前,尽我们目前所知的实际位置的概率分布(也称为预测状态)。这最初也被假设为高斯分布。
- 归一化:测量概率分布,对所有可能的位置求和。在这种情况下,不计算这部分,因为我们只关心更新均值和协方差,而不关心高斯振幅。
从这里我们可以推断出,更新后的状态将是预测状态和测量状态的产物(关于似然函数的更多信息,请查看本博客,关于卡尔曼滤波器中的似然性的更多信息,请查看本书的第 4 章)。因为我们在这里处理的是高斯分布,这种分布的乘积将是另一种高斯分布,它的均值和协方差有封闭的方程。
如果我们有位置和速度的测量值(我们没有),更新步骤会是这样的:
预测状态取自上述过程。测量的状态,类似于我们的初始状态,有一个轴对齐的椭圆形。这就是说,测量的位置和测量的速度来自两个独立的传感器,每个传感器的不确定性由高斯方差捕获。
但是,因为在我们的视频跟踪示例中,我们只有一个位置测量值,没有速度测量值,所以被测状态的概率只会在位置维度上衰减,但在速度维度上,它将具有均匀分布,因此看起来像这样:
在这里,您可以看到一个测量位置,其平均值高于预测值。当然,更新状态的位置将介于两者之间。但是请注意,尽管我们只测量了位置,更新状态的平均速度相对于预测状态也增加了。如果我们回想一下预测状态的位置和速度是相关的,这意味着更远的位置与更高的速度相关联,就可以直观地理解速度的这种变化。有了这个性质,为什么测量某个位置会导致我们对平均速度的信念发生改变就变得很清楚了。
考虑两个高度相关的概率分布:例如,云量概率分布和降雨量概率分布。我们知道,大量的云与更多的雨密切相关。现在假设我们必须猜测昨天巴黎下了多少雨。在没有任何先验知识的情况下,你会猜测,比如说,3 毫米的降雨量(你猜测的平均值)。现在,有人告诉你昨天非常多云。利用这一先验知识,你肯定会更新你对降雨量的猜测。这正是卡尔曼滤波器中发生的情况。给定一个远位置测量,我们也将速度更新到一个更高的值。
均值更新方程
在这篇博客中,我们不会试图推导出“更新”方程(为此你可以在这里查看),而是我们将展示它们并试图理解它们。
首先是一些定义:
我们使用 R 到来表示测量的状态协方差矩阵,因为这是卡尔曼滤波器教科书中常用的表示方法。在这个例子中,由于我们的测量是 1D,测量的状态可以用两个标量来表示:
因为我们的测量和状态具有不同的维度,为了将两者结合起来,我们需要一个线性变换,将我们从状态空间带到测量空间。我们用矩阵 H 来表示这个转换。在我们的例子中,我们的测量只有一个维度(位置),而状态有两个维度(位置&速度),因此要在它们之间转换,我们可以使用:
这样,如果我们将预测平均值乘以 H ,我们将只得到平均值的测量部分:
现在是真正的方程式。我们将首先给出更新状态的均值和协方差的完整方程,然后将它们分解成更有意义的分量,以便我们可以更好地理解发生了什么。
完全更新的均值等式(对于我们的 1D 视频跟踪示例)为:
这是一个相当复杂的等式,所以让我们来分解它。首先,我们将传感器“创新”定义为:
其仅仅是测量位置和平均预测位置之间的差。它被称为创新,因为它可以被认为是我们从传感器获得的新(创新)信息。
其次,我们将“卡尔曼增益”定义为:
卡尔曼增益是我们将新的传感器信息合并到更新的状态中的因子。
将这些定义代入等式,我们得到:
让我们进一步细分到位置更新和速度更新。对于更新后的位置我们得到:
这个等式很有道理。更新的平均值将是预测的和测量的平均值的加权平均值,权重因子与它们各自的相对不确定性成比例。
假设我们有一个完美的零方差传感器。这将导致预测的测量值等于传感器测量值(这是应该的——这是完美的。).另一方面,如果与预测状态的方差相比,传感器噪声很大(高度不确定性),则情况正好相反,完全忽略测量,仅使用预测位置。正如你所料。
现在对于平均速度更新:
在这种一般形式下没有太多意义(至少我想不到),所以让我们尝试插入我们之前导出的单个协方差预测步骤的结果,看看是否有帮助。如果我们假设零过程噪声(Q=0,这是不现实的,但对于更简单和更直观的方程是好的),我们得到预测的协方差是:
记住“ t ”上标只是“上一步”的意思;进入速度更新,我们得到:
我们将分子和分母乘以δt,得到:
让我们想想这个等式的不同部分以及它们所包含的内容。最后一部分:
是速度创新。就像位置创新一样,这是预测的状态速度和我们实际到达测量位置所需的速度之间的差异。现在,我们希望更新后的状态中包含多少这种创新?这取决于我们之前状态下速度的不确定性,相对于测量速度的不确定性。但是等等,我们没有测到速度!从位置测量中推断出。那么我们如何定义这个推断速度的不确定性呢?
速度是使用先前的位置和测量的位置来推断的,因此它的不确定性是它的两个分量的不确定性的总和是有意义的。因此,我们可以将推断的速度不确定性定义为:
如果我们回忆一下:
我们还可以定义一个广义的预测速度不确定性,该不确定性也考虑了自上次更新以来所经过的时间,如下所示:
将这些定义代入等式,我们得到:
这个等式更直观。也就是说,更新的速度将等于预测的速度加上速度创新的一部分。当推断的速度不确定性非常大(相对于预测的速度)时,这个分数将接近零,而当反过来时,这个分数将接近 1。
协方差更新方程
完整的协方差更新方程如下所示:
我们可以插入上面获得的卡尔曼增益和以下事实:
获得:
我们将相对测量不确定度定义为:
这个常数就是相对于位置总不确定度的测量不确定度。如果我们把这个代入方程(在我会告诉你更多的代数之后),我们会得到:
我们来分解一下:更新后的位置不确定度是预测位置不确定度和测量位置不确定度的调和平均值。调和平均值是一种通过接近两个元素中较小的一个来组合两个元素的平均值。所以如果:
然后:
反之亦然。
更新的位置-速度协方差也是直观的。它是预测协方差的缩小版本,比例因子是相对测量不确定性。因此,对于完美的测量,这些元素将接近零,而对于噪声测量,它们将保持不变。
现在更新速度方差。乍一看,这似乎没有多大意义,因此,正如我们之前所做的那样,让我们插入之前导出的单个协方差预测步骤的结果。
我们可以再次使用我们上面定义的推断速度不确定性和广义速度预测不确定性来获得:
我们再次得到更新的方差是推断速度不确定性和广义速度预测不确定性的调和平均值。所以基本上总是接近两者中较小的一个。
最后,我们有:
让我们总结一下从这个等式中可以学到什么。位置方差和速度方差都可以表示为两个不确定性(每个不确定性都有与之相关的不确定性)的调和平均值。位置-速度协方差也随着我们对测量相对于先验的确定程度而缩小。如果你回到显示更新过程的图表,这也是非常直观的原因。
总结
在这篇博客中,我试图把我试图直观理解卡尔曼滤波方程的过程写下来。这是图形和数学直觉的混合体,在我看来,它们是相辅相成的。希望它能帮助你更好地理解“引擎盖下”到底发生了什么,也许现在这个复杂的算法变得更容易理解了。
这里要补充一点,物体跟踪等算法不可掉以轻心。这些算法,在错误的人手中,可能被用来犯下侵犯公民权利的罪行,因此只能由专业人士开发,并受到严格的监管。
当我开始我的计算机科学之旅时,我希望我已经知道了什么
在我开始计算机科学和软件开发的旅程之前,我希望我已经知道的所有事情
当我开始我的旅程时,我发现很难得到关于这个话题的一些像样的建议,而且它分散在互联网上,有许多不同的观点。
我在这个过程中犯了一些错误,这些错误可能是我现在所知道的我不会犯的,我写这篇文章是希望我能帮助其他人避免这个问题,同时也为所有正在寻找它的人提供一些建议。
在这篇文章中,我将谈论我的旅程中的经历,以及如果我知道这一切,我可以做得更好。
当我们提到学习编程时,我们指的是学习有效地学习。
这是因为作为一名开发人员,你在不断变化的技术世界中工作,你将不得不在你的整个职业生涯中不断学习,这一切都是从第一步开始的,如果你开始错了,那么它可能是一条崎岖的道路,而如果你开始正确,那么它将是一帆风顺的。
考虑到这一点,我编写了一个完整的指南,介绍在成为开发人员的过程中需要掌握的最重要、最简单的方面,以及一些我希望能帮助你的资源。
每天写代码。
也许整个旅程中最重要的部分是身体的练习。
你应该努力每天写一些代码,即使写代码的一半时间花在调试上,这是正常的,但如果你不练习,你永远不会把它变成肌肉记忆。
就我个人而言,当我经历我的旅程时,我发现自己是如此专注和担心我还不知道的事情,以至于我花了更多的时间阅读和研究不同的课程和编程语言,而不是实际动手。
直到我意识到我没有足够的能力继续下去,没有真正的建立一些东西,我才发现什么一直就在我面前。你只有通过实践才能真正学到东西。
这就是为什么我说这是最重要的因素,不管多少,你只能通过每天写代码和调试代码来快速提高。
知识没有价值,除非你把它付诸实践。 —安东·契诃夫
解决问题前仔细计划。
虽然每天编写代码极其重要,但培养处理新问题的最佳心态也同样重要。
这意味着在编写物理代码之前,要计划好如何着手解决问题。
事实是,当在现实世界中工作时,编写代码的行为可能只占工作的百分之二十,其余的都是计划、调查和不可避免的调试。
然而,如果您正确地计划和调查,那么您应该能够减少调试代码所花费的时间。
因此,在处理新问题时,培养清晰思考和耐心的能力是非常重要的。合理利用你的时间,在尝试实施之前计划好你要做的事情。
首先,我发现最好的方法是用你的母语以简洁明了的方式写下来,然后翻译成伪代码并仔细阅读,同时思考,“这有可能出错吗?”,并且只有当你对此完全满意时,才把它实现成实际的代码。
随着时间的推移,这一过程将成为你的第二天性,你不必走到这一步,但一开始就进行长时间的思考过程来适当地训练你的思维是有好处的。
如果你没有计划,你就是在计划失败。 —本杰明·富兰克林
测试一切!
我知道,我知道。如果当我们测试我们写的所有代码时,我们不得不再次做,为什么我们要经历所有的计划?
因为我们是人,我们会犯错!不管你对自己的能力有多自信,我保证你会犯错误,避免这些错误的唯一方法是彻底测试一切。
我坚信,在测试时,你应该尽你所能让代码以一种意想不到或不想要的方式运行,这样你就可以找到你可能已经错过的错误。
将来,随着您技能的发展,您将学习如何通过自动化测试来测试您的代码,在自动化测试中,您将测试您能想到的所有可能的边缘情况,但在此之前,您应该已经教会您的大脑去思考可能会出错的地方。
坚持不懈,打造你个人投入的东西。
调试是很难的,面对一个问题,连续几天都找不到解决方案会令人沮丧,这是完全正常的,如果你没有这样做,尤其是在开始的时候,那么这可能更令人担忧。
重要的是在面对未知时变得舒适,并开发分析技能来帮助你克服这一点,毕竟调试是一项需要努力的技能,如果不是比实际编写代码更多的话。
正是因为这个原因,建议初学者找到一个真正帮助他们的项目或者他们对自己的第一个项目充满热情是很正常的。
这将有助于你保持完成项目的决心,而不是在项目变得太困难时放弃它。
我的第一个项目是一个 web 应用程序,它可以帮助我更好地完成当时的工作,主要是组织、跟踪和评分我所教的英语课。
我不仅对改善我的工作环境,而且对改善公司使用的整个系统充满热情,以至于我花了大约四个月的时间开发这个应用程序,使它达到我当时认为足够好的水平。
有目标。
这在构建您的第一个应用程序时同样重要,因为事实上您可以对任何流程或应用程序进行的改进是无止境的,但您也需要知道何时撤回并专注于学习更多来提高您的技能。
我在前面提到的应用程序中经历了这一点,我花了几个月的时间在上面工作,发现自己在不断改进。但是每当我回头看我写的代码时,我知道我可以用我学到的东西来改进它。
最终,我意识到我太专注于这些小细节了,以至于我忘记了看更大的画面,也忘记了我开始这个过程的原因。
就在那时,我认识到我们需要为我们正在构建的流程设定一个清晰简明的目标,虽然这可能会随着时间的推移而改变,但这是很自然的,我们不能忘记后退一步,看看更大的图景,以知道何时说它已经完成。
学会问正确的问题,正确使用谷歌。
当你经历许多课程并试图解决不同的问题时,通常,你会求助于 google 和 StackOverflow 来帮助找到一些解决方案。
这是开发人员的一项基本技能,在调查问题时非常重要,你需要学会问正确的问题,在找到解决方案时,不要在没有完全理解的情况下将你发现的内容复制粘贴到你的代码中,这一点非常重要。
这不仅危险,而且对你的进步毫无帮助。
我并不是说你不应该使用你在网上找到的解决方案,而是说你应该在自己实现之前完全理解他们是如何得到那个解决方案的,以及他们是如何处理代码的。
这样做将有助于你提高你的知识,甚至对你正在做的事情有更深的理解,这也将有助于你避免在应用程序中实现潜在的危险代码。
不要担心语言,但首先要坚持一种。
如前所述,当我开始学习时,我一直担心我应该学习哪种语言,先学习哪种语言是最好的,我应该知道一种以上的语言,等等。
最后,事实是这并不重要。学习一门低级语言或静态类型语言确实会让以后学习动态类型语言变得更容易,但真正的事实是,首先学习哪种语言并不是最需要担心的事情。
你应该担心的是选择一种与你将来想做的事情一致的语言,然后使用这种语言来学习对于大多数编程语言和面向对象编程来说都是真实的基础概念。
一旦你有了这些概念,不要改变语言,尽管你可能认为你很了解它,但你并不了解。
一旦你学会了这些概念,并能在所选的语言中自如地使用它们,那么这就是你可以真正开始学习更特定于语言的概念,并真正建立你在语言中的经验,直到你熟练掌握为止。
为什么我建议在此之前坚持使用一种语言?
我这样建议是因为如果你从一种语言过渡到另一种语言,只是达到一个肤浅的水平,那么你永远也不能说你懂这些语言中的任何一种,如果你想被雇佣并获得报酬,你需要对他们希望你工作时使用的语言有更深入的了解。
因此,我建议,如果你想成为一个可雇佣的人,并以一种更好的方式积累你在该领域的知识,那么选择任何一种与你未来想做的事情相一致的语言。使用它来学习面向对象编程和计算机科学的概念,然后在扩展到其他语言之前加深您在这种语言中的知识。
资源
有了以上所有的建议,你应该有了在你的旅程中前进所需的所有工具,但你也有很多要学的,你也需要一些资源来学习。
在这一节中,我将回顾我在整个旅程中发现非常有用的资源,以及我为什么发现它们有用。
StackOverflow
我不能充分地陈述这一点,StackOverflow 是你可能遇到的最好的资源!这是一个致力于开发人员互相帮助并回答他们遇到的问题的网站。
你肯定应该有一个账户,当你需要答案的时候,它会成为你第一个要找的地方。
一旦你有建设性地参与其中,这个网站的一个稍微不太重要的功能也会显现出来,这就是他们的实时聊天,让你可以用所有编程语言与令人惊叹的开发人员进行实时交流,在这里你可以汇集你的知识并互相帮助。
我应该声明一个免责声明,你永远不应该显示不属于你的代码来分享,相反,如果你面临一个问题,你应该建立一个快速的 最小可重复的例子 ,你可以安全地使用它来找到解决方案。很多时候,在构建这个例子的过程中,您需要自己找到解决方案。
CS50 的在线课程
到目前为止,这些都是计算机科学起步时,甚至是接触新领域时的最佳资源,如网络编程、游戏开发或人工智能。
它们都非常紧张,有你必须完成的附带项目,最重要的是,它们为你提供了足够的信息来启动这些项目,但也让它们变得足够困难,以至于你不得不研究你正在做什么来找到解决方案。
免费代码营
自由代码营是另一个令人惊奇的资源,你可以用它来学习许多主题,也可以找到一些有趣的、相对简单的项目。
我确实发现,在整个学习过程中,他们握着你的手对我来说有点太多了,但同时,它提供的每门课程都提供了许多关于不同主题的深入细节,而且你必须再次完成多个项目才能完成这门课程。
HackerRank ,leet code&&CodeWars
虽然 CS50 和自由代码营是提供惊人课程的惊人资源,但它们不仅仅是提供一个练习解决问题的技能和知识的地方。
这就是这三者发挥作用的地方。它们是极好的资源,为你提供了许多不同的挑战,你可以用来练习和磨练你的技能,而不必把时间投入到整个课程中。
我倾向于每周利用这些时间来练习一些解决问题的技巧,或者在学习一门新语言的时候变得更加自在。
C 结论
在你的旅程中,有许多概念和技能需要你去掌握,但你也需要记得去享受它,并在你穿越无尽的科技世界时获得乐趣。
根据我在这篇文章中所说的一切,你应该有一个良好的开端,如果你只是记得每天写代码,仔细计划,测试一切,坚持不懈,有一个目标,问正确的问题,那么你应该会发现自己进步很快。
希望这篇帖子对你有所帮助。
如果……apply()太慢?
有时我们需要在 Python 中通过使用 Pandas 数据帧的列作为函数的输入,对 Pandas 数据帧应用一些函数。不过,用的最多的方法 。对整个数据帧应用() 可能会比预期花费更长的时间。我们做什么呢
如果您正在使用 Python 处理数据,Pandas 一定是您使用最多的库之一,因为它具有方便和强大的数据处理特性。
如果我们想对 Pandas 数据框中一整列的值应用相同的函数,我们可以简单地使用。应用()。Pandas 数据框和 Pandas 系列(数据框中的一列)都可以与一起使用。应用()。
但是你有没有注意到?当我们有一个超级大的数据集时,apply()会非常慢?
在本文中,我将讨论当您想要对列应用一些函数时,加速数据操作的技巧。
对单个列应用函数
例如,这是我们的玩具数据集。
import pandas as pd
import numpy as np
import timeit
d = {'category': ['apple', 'pear', 'peach'], 'radius': [3, 4, 2], 'sweetness': [1, 2, 3]}
df = pd.DataFrame(data=d)
df
如果我们希望根据半径列中的值向数据框中再添加一列“直径”,其中基本上直径=半径* 2,我们可以继续使用。在此应用()。
df['diameter'] = df['radius'].apply(lambda x: x*2)
df
然后,我们计算执行命令行 10k 次的时间,
# Timing
setup_code = """
import pandas as pd
d = {'category': ['apple', 'pear', 'peach'], 'radius': [3, 4, 2], 'sweetness': [1, 2, 3]}
df = pd.DataFrame(data=d)
"""
mycode = '''
df['radius'].apply(lambda x: x*2)
'''
# timeit statement
t1 = timeit.timeit(setup=setup_code,
stmt = mycode,
number = 10000)
print(f"10000 runs of mycode is {t1}")
产生 0.55 秒。还不错,嗯…?但请记住,这只是一个 3 行的玩具数据。如果我们有几百万行呢?
你可能已经注意到我们不需要使用。apply()在这里,您可以简单地执行以下操作,
df['diameter'] = df['radius']*2
df
我们可以看到输出与使用。应用()。如果我们计算 10k 运行的执行时间,
# Timing
setup_code = """
import pandas as pd
d = {'category': ['apple', 'pear', 'peach'], 'radius': [3, 4, 2], 'sweetness': [1, 2, 3]}
df = pd.DataFrame(data=d)
"""
mycode = '''
df['radius']*2
'''
# timeit statement
t1 = timeit.timeit(setup=setup_code,
stmt = mycode,
number = 10000)
print(f"10000 runs of mycode is {t1}")
总共给了我们 0.32 秒,比。apply()函数。
注意,我们可以简单地避免使用。这里只使用 apply(),因为我们使用一个非常简单的函数来计算一个乘以 2 的值。但是在大多数情况下,我们需要对列应用一个更复杂的函数。
例如,我们希望为每个观测值在半径和常数(比如 3)之间添加一个较大值的列。如果你简单地做以下事情,
max(df['radius'],3)
它将生成下面的错误消息,
因此,我们需要在 apply()函数中编写比较代码。
df['radius_or_3'] = df['radius'].apply(lambda x: max(x,3))
df
让我们计算一下执行时间,
# Timing
setup_code = """
import pandas as pd
d = {'category': ['apple', 'pear', 'peach'], 'radius': [3, 4, 2], 'sweetness': [1, 2, 3]}
df = pd.DataFrame(data=d)
"""
mycode = '''
df['radius'].apply(lambda x: max(x,3))
'''
# timeit statement
t1 = timeit.timeit(setup=setup_code,
stmt = mycode,
number = 10000)
print(f"10000 runs of mycode is {t1}")
给了我们 0.56 秒。但是如果数据有几百万行,需要多长时间呢?这里没展示,不过要几十分钟。这么简单的操纵是不能接受的吧?
应该怎么加快速度?
下面是通过使用 NumPy 而不是。apply()函数。
df['radius_or_3'] = np.maximum(df['radius'],3)
这里的 NumPy 函数最大值是一个比。应用()。让我们计算一下时间。
# Timing
setup_code = """
import pandas as pd
import numpy as np
d = {'category': ['apple', 'pear', 'peach'], 'radius': [3, 4, 2], 'sweetness': [1, 2, 3]}
df = pd.DataFrame(data=d)
"""
mycode = '''
np.maximum(df['radius'],3)
'''
# timeit statement
t1 = timeit.timeit(setup=setup_code,
stmt = mycode,
number = 10000)
print(f"10000 runs of mycode is {t1}")
它产生 0.31 秒,比。apply()函数吧?
因此,要点是,在简单地使用。对所有内容应用()函数。
将函数应用于多列
有时我们需要使用数据中的多个列作为函数的输入。例如,我们希望创建一列列表,记录“半径 _ 或 _3”和“直径”之间的可能大小。
我们可以利用。将()应用于整个数据帧,
df['sizes'] = df.apply(lambda x: list(range(x.radius_or_3,x.diameter)), axis=1)
df
这一步实际上非常耗时,因为我们实际上在。apply()函数。执行时间是,
# Timing
setup_code = """
import pandas as pd
import numpy as np
d = {'category': ['apple', 'pear', 'peach'], 'radius': [3, 4, 2], 'sweetness': [1, 2, 3]}
df = pd.DataFrame(data=d)
df['diameter'] = df['radius']*2
df['radius_or_3'] = np.maximum(df['radius'],3)
"""
mycode = '''
df.apply(lambda x: list(range(x.radius_or_3,x.diameter)), axis=1)
'''
# timeit statement
t1 = timeit.timeit(setup=setup_code,
stmt = mycode,
number = 10000)
print(f"10000 runs of mycode is {t1}")
给了我们 1.84 秒。我会告诉你,对于一个数百万行的数据帧来说,这需要 20 多分钟。
我们能找到更有效的方法来完成这项任务吗?
答案是肯定的。我们唯一需要做的就是创建一个函数,根据需要接受尽可能多的 NumPy 数组(pandas 系列)作为输入。
def create_range(a,b):
range_l = np.empty((len(a),1),object)
for i,val in enumerate(a):
range_l[i,0] = list(range(val,b[i]))
return range_l
df['sizes'] = create_range(df['radius_or_3'].values,df['diameter'].values)
df
这段代码有一个函数, create_range ,它接受两个 Numpy 数组,并通过一个简单的 for 循环返回一个 Numpy 数组。并且返回的 Numpy 数组可以自动转换为 Pandas 系列。
让我们检查一下我们节省了多少时间。
# Timing
setup_code = """
import pandas as pd
import numpy as np
d = {'category': ['apple', 'pear', 'peach'], 'radius': [3, 4, 2], 'sweetness': [1, 2, 3]}
df = pd.DataFrame(data=d)
df['diameter'] = df['radius']*2
df['radius_or_3'] = np.maximum(df['radius'],3)
"""
mycode = '''
def create_range(a,b):
range_l = np.empty((len(a),1),object)
for i,val in enumerate(a):
range_l[i,0] = list(range(val,b[i]))
return range_l
create_range(df['radius_or_3'].values,df['diameter'].values)
'''
# timeit statement
t1 = timeit.timeit(setup=setup_code,
stmt = mycode,
number = 10000)
print(f"10000 runs of mycode is {t1}")
它给了我们 0.07 秒!!!!
看到了吗?它的速度比。对整个数据框应用()函数!!
外卖食品
- 如果你想用。将()应用于 Pandas 数据框中的单个列,尝试找到更简单的执行,例如 df[‘radius’]*2。或者尝试为任务找到现有的 NumPy 函数。
- 如果你想用。将()应用于 Pandas 数据框中的多个列,尽量避免。应用(,轴=1)格式。并编写一个独立的函数,它可以将 Numpy 数组作为输入,然后直接在。熊猫系列的值(数据框的列)。
为了方便起见,这是本文中代码的完整 Jupyter 笔记本。
这就是我想分享的全部!干杯!
如果你喜欢我的文章,别忘了订阅我的邮件列表或者成为 Medium 的推荐会员!!
如果数据成为每个人的事情会怎样?
在未来的数据经济中取得成功的新思维
马文·迈耶在 Unsplash 上的照片
当你看到下面的统计数据时,你和我一样震惊吗?
组织中目前有高达 97%的数据未被使用。
事实上,并不是所有的数据都是用来分析的。公司为了记录和法规遵从性而汇集数据。但是 97%,真的吗?![1].虽然利用不断增长的可用企业数据的业务优势是不可能的,但我们必须问自己的一个问题是,我们是否有潜力做得更多。
大规模收集数据后新时代的曙光
大数据的技术进步使得公司能够以前所未有的规模收集、存储和处理数据。“数据是新的石油”的意思是说,原始数据就像原油一样,本身没有价值,而是在收集和连接其他相关数据时创造的价值。但是,如果我们将石油转化为石油,却没有足够的人来驾驶我们提供燃料的汽车,那又有什么用呢?
我们已经达到了这样一个点,我们收集数据的能力超过了我们能够分析和处理可用数据的能力。在未来的数据经济中,成功不再由你拥有的数据量来衡量,而是由有权使用数据的人数来衡量。为了取得成功,公司必须从获取收集和处理大量企业数据的正确技术转变为支持全体员工协作处理提供给他们的数据。那些未能扩大谁有权处理数据的范围的企业将会错失良机。
企业数据协作:前路坎坷
Qlik & Accenture 进行的一项大规模数据素养研究发现,67%的全球员工可以使用商业智能工具,而 75%的员工可以使用数据分析软件[2] 。
企业正在意识到让更多员工在工作中利用数据的机会。很明显,这是朝着正确方向迈出的一大步,但却让我们许多人步履蹒跚。同一项研究发现,增加数据分析和 BI 工具的投资并没有让人们在处理数据时变得更加自信。
- 74%的员工表示在处理数据时感到不知所措或不开心
- 在使用数据分析和商业智能工具时,全球 59%的员工表现出倦怠症状(感觉效率低下、沮丧或有压力)
- 全球 36%不堪重负的员工表示,他们每周至少花一个小时在与数据相关的任务上
- 14%的人会完全回避这项任务
说真的,这是怎么回事?简单地说,技术进步已经超过了人们的应对能力。让人们独自访问数据是一种有压力的体验,因为数据本身是不方便的,没有额外的上下文,嗯,只是数据。无论我们能够获得什么样的技术堆栈,将数据转化为洞察力最有可能始终是一项跨学科的工作,它需要利用分散在一个组织中许多负责人身上的不同技能和知识。通常情况下,知道如何分析数据的人并不具备判断数据正确性和相关性的背景和商业头脑。完全不同的人将知道在后端何处定位这些数据。在数据隐私和合规性方面,其他人将不得不参与进来。长长的名单还在继续。虽然协作是成功的关键,但组织很难做到这一点。HBR 最近的一项研究将组织孤岛视为组织向数据驱动型企业转型的头号组织障碍[3]。据 Statista 称,员工认为缺乏组织一致性是采用大数据的最大挑战[4]。
最终,如果用户不会使用,最好的技术也是无用的。与此同时,如果使用的工具不适合协作,伟大的人才也无法发挥作用。按照现在的方式继续下去的机会成本是巨大的。
数据成为每个人的事情的那一刻
现在,几乎所有员工都有望在自己的岗位上使用数据。在当前的现实中,数据探索掌握在一小群代表其他所有人处理数据的专家手中,而大多数员工只能在一旁观看,直到他们的分析需求得到满足。在这种主要是事务性的设置中,员工对数据的信任度、执行分析请求的速度以及在任何给定时间点可以处理的分析请求的数量都严格取决于可用专家的数量。
在另一个现实中,任何背景的人都可以就数据进行合作和交流。当数据成为每个人的事情时,这些指标就会飙升。各种业务和 IT 利益相关者之间的跨学科对话为理解和信任数据提供了必要的背景。让不同的配置文件贡献知识变得可行,不仅会提高输出的质量——特别分析、仪表板、分析应用程序,等等——还会提高企业对数据进行操作的规模和速度。就像在足球比赛中,不是每个人都应该是前锋,不是每个人都需要在数据驱动的项目中部署代码和构建复杂的模型。但要达到这一点,所有球员都需要沟通和合作,才能把球传到球场上。如果你设法找到更多的前锋,很好,但如果你的整体游戏性没有改善也不要惊讶。真正的挑战将是让所有参与者尽最大努力,因为数据是一项团队运动。
让每个人都轻松的数据协作:一个新兴的商业机会?
公司积累了大量的数据和工具来进行分析。随着等式中人的部分被抛在后面,这些投资今天没有回报。无解的痛?当然不是!让我们考虑一些新兴业务,它们以消除组织障碍为己任,让协作成为新的规范。
虽然过去两年疫情对企业协作进行了压力测试,但像壁画、米罗和图玛这样的软件工具为公司提供了令人难以置信的补救措施,将创意研讨会和设计会议引入数字领域,在这个领域,人们之间的协作被降级为在家工作。为了应对处理数据的特殊挑战,软件平台 Deepnote 和 detective.solutions 正在重新思考跨学科数据协作在组织环境中的实施方式。围绕 Deepnote 的团队提供了一个 Jupyter 兼容的数据科学笔记本环境,用于在机器学习模型开发上进行实时协作。虽然前者面向精通技术的人员,但 detective.solutions 提供了一个数字合作画布,无需代码即可访问大数据。这是为了帮助任何背景的企业用户掌握数据驱动项目的协作和通信密集型阶段。
正如所有创新尝试的情况一样,时间会证明这种平台是否会继续存在。但有一点是明确的:数据分析项目,无论是处于概念阶段还是已经深入数据和算法,都依赖于商人和数据工作者在数据上的合作。如果做不到这一点,就会降低一家公司从过去几年精心制作的数据中赚到大钱的几率。
参考
[1] AWS Executive Insights (2018) —数据驱动型企业的力量—https://AWS . Amazon . com/Executive-Insights/content/The-Power of-The-Data-Driven-Enterprise/
[2]埃森哲& Qlik(2020)——数据扫盲对人类的影响——https://www . Accenture . com/_ ACN media/PDF-118/Accenture-The-Human-Impact-Data-literacy . PDF # zoom = 50
[3]HBR(2018)——数据驱动型企业的一个着力点——https://HBR . org/sponsored/2018/11/An-拐点——数据驱动型企业
[4]Statista(2019)-截至 2019 年美国和全球企业采用大数据的最大挑战-https://www . Statista . com/statistics/742983/world wide-survey-corporate-big-data-adoption-barriers/
什么是计算机内核?
了解 Jupyter 笔记本电脑内核的概念
安基特·辛格在 Unsplash 上的照片
内核,或称系统核心,确保操作系统在计算机中平稳运行,是软件和硬件之间的接口。它用于所有带有操作系统的设备,例如电脑、笔记本电脑、智能手机、智能手表等。
内核执行哪些任务?
内核主要是操作系统(即软件)和设备中的硬件组件之间的接口。这导致必须完成各种任务。然而,对于最终用户来说,这项工作是不可见的,只能通过所有程序是否正确运行来表示。
当我们在计算机上使用程序时,比如 Excel,我们在所谓的图形用户界面(GUI)上处理它。该程序将每一次按钮点击或其他动作转换成机器代码,并发送给操作系统内核。如果我们想在 Excel 表格中添加一个新列,这个调用会到达系统核心。这又将调用传递给计算机处理单元(CPU ), CPU 执行该动作。
如果几个程序同时运行,系统核心还确保程序的请求被一个接一个地处理,并且给用户进程同时运行的感觉。因此,在我们的示例中,如果浏览器窗口与 Excel 同时打开,系统内核会确保程序对 CPU 和其他硬件的需求以协调的方式得到处理。
此外,还有其他更详细的任务,例如:
- 管理外部连接的设备,如键盘、鼠标或显示器及其正常运行。
- 解决内存使用错误,例如,当程序的内存使用增加过多时。
- 优化 CPU 的使用
内核由哪几层组成?
内核在几个相互构建的层中工作。其中包括:
- 硬件:最底层形成了操作系统可以访问的系统硬件的接口。这包括例如 PCI Express 控制器或存储器。
- 内存管理:在下一层,专用的可用内存量被分配给正在运行的进程。此外,虚拟主存储器也可以分布在这里。
- 流程管理:在这一层,程序的时间被管理,传入的请求被定时,这样它们对我们这些用户来说是并行的。
- 设备管理:在这一层,进行设备管理。与硬件层相反,这涉及外部连接的设备,如显示器或打印机,它们的通信通过特殊的驱动程序来保证。
- 文件系统:在最顶层,进程被分配到硬盘上的指定区域,即 HDD 或 SSD。
这些层的运作方式是,每一个更高的层都依赖并建立在它下面的层之上。例如,进程管理层也访问硬件层中的进程。然而,反之则不然。
内核类型有哪些?
通常,根据可以同时管理的进程和用户的数量来区分三种不同的内核类型。
微内核
微内核只执行最少的任务,比如内存管理和 CPU 进程管理。其他功能,如文件系统或设备管理,被外包给操作系统本身。优点是它不会像 Windows 那样导致整个系统的故障。
例如,苹果电脑的操作系统 macOS 就是基于微内核架构的。
整体内核
单片内核集中处理已经描述过的所有任务,负责所有内存和进程管理,还处理外部连接设备的硬件管理。Windows 操作系统基于单一内核。
由于采用中央设计,单片内核通常比微内核快得多,但如果单个进程运行不正常,这也会导致系统崩溃。
混合内核
顾名思义,混合内核是这两个概念的混合。它基本上也是一个大的内核,可以接管所有的任务,但是更加紧凑,可以分成不同的模块。
Jupyter 笔记本的内核是如何工作的?
在处理数据和机器学习时,人们经常会求助于 Jupyter 笔记本。它是一个基于网络的平台,用于创建和共享编程代码。它经常用于数据科学应用,因为可以执行单独的代码块,并且它们的结果(例如,图形)是直接可见的。当接下来的编程步骤依赖于先前的结果时,这对于模型创建或数据集分析尤其有利。
当使用 Jupyter Notebook 时,还会启动一个内核,这有时会导致问题,例如在下面的示例中建立连接时。然而,这与本文中所描述的操作系统完全不同。
Jupyter Notebook 内核是一个执行笔记本代码的引擎,专用于特定的编程语言,比如 Python。然而,它不执行迄今为止描述的全面的接口功能。
在处理 Jupyter 笔记本内核时,以下命令特别有用:
- 中断:该命令停止单元中当前正在运行的进程。例如,这可用于停止模型的训练,即使尚未到达所有训练时期。
- 重启&运行全部:该命令可以再次执行所有单元,删除之前的变量。如果您想将一个较新的数据集读入现有程序,这可能会很有用。
- 重启:单一的“重启”命令导致相同的结果,但并不是所有的单元都被再次执行。
重新连接:在训练大型模型时,内核会因为内存已满而“死亡”。那么重新联系是有意义的。 - 关机:只要内核还在运行,它也会占用内存。如果您要并行运行其他程序来释放内存,那么“Shutdown”命令是有意义的。
这是你应该带走的东西
- 内核确保操作系统在计算机中平稳运行,是软件和硬件之间的接口。
- 它被分成不同的层,这些层相互构建。
- 这些任务包括管理并行运行的进程或外部连接设备的正常运行。
- Jupyter Notebook 内核不是所描述的系统内核,因为它只用于执行编程代码。
如果你喜欢我的作品,请在这里订阅https://medium.com/subscribe/@niklas_lang或者查看我的网站 数据大本营 !还有,medium 允许你每月免费阅读 3 篇 。如果你想让无限制地访问我的文章和数以千计的精彩文章,请不要犹豫,通过点击我的推荐链接:【https://medium.com/@niklas_lang/membership】每月花$5获得会员资格**
什么是数据布道者?
以及如何成为一个…
简介:数据传播者——什么?
因此,让我们从数据传道者的真正含义开始。
数据传播者是通过以博客、教程、讲座、视频等形式提供技术内容来谈论数据和技术重要性的人。其目标是传播有关数据技术的知识,以及数据行业和使用特定工具的最佳实践。最终的结果是,人们爱上了它们,并自然而然地开始使用它们。
一些类似的角色包括开发者倡导者或开发者关系角色,他们有一个共同点。担任这些角色的人通常都有很强的技术背景,并且喜欢与他人分享他们的知识。
数据传道者并不是你在每个公司都能找到的典型角色,但近年来它变得越来越受欢迎。
那我是怎么成为其中一员的呢?
我的故事
我在 2008 -2013 年期间在爱丁堡大学学习人工智能。因此,我担任了几个技术角色,开始了我的职业生涯。我做过 Java 开发人员、自然语言处理工程师和数据科学家。所有这些角色都非常令人满意,并帮助我发展了技术专长,在这个阶段,我没有真正与任何人分享。
图片由 www_slon_pics 发自 Pixabay
当我在一个著名的在线训练营担任数据科学导师时,这种变化就出现了。突然,我开始与他人分享我的知识,并意识到我真的很喜欢它。这进一步促使我创建了这个媒体账户和我的个人博客。
在某种程度上,我已经成为一名数据传播者,因为我分享了我的技术专长和知识,希望其他人相信数据的力量,并从我的文章中了解更多关于 ML 和数据科学的知识。
直到 2021 年 10 月,我加入了 Toloka ,数据传道者成为我的正式工作头衔。Toloka 在人工智能和人工智能行业工作了很长时间,对人工智能有着和我自己相似的看法,特别是关于最近以数据为中心的方法。
那么,作为一名数据传播者,我典型的一天是怎样的呢?
我认为数据传道者没有典型的一天:)
事实是,角色是如此多样,每天都是不同的,但总的来说,我花了很多时间准备技术讲座和演示,撰写技术文章和教程,并致力于 Toloka 与其他 ML 和 AI 产品和平台的技术集成。
在过去的九个月里,我已经在八个不同的数据科学会议、聚会和其他 ML 社区活动上发表了演讲。他们中的大多数都有在线网络研讨会的形式,其中一些是面对面的会谈,比如这次关于以数据为中心的人工智能的会谈。
我还参与了四个 ML 产品的整合。你可以在这篇关于弹性人在回路管道的中型文章中看到这种合作的结果。其他三个仍在开发中,将在接下来的几个月内发布。
值得一提的是,作为数据传播者,我不仅从事纯技术和传播工作,还参与了活动的组织工作。今年,我帮助发起并运行了这个关于数据驱动人工智能的在线会议系列。
每周我还会花时间和 Toloka 的用户交流。这包括帮助他们解决他们面临的技术问题,特别是如果他们是机器学习性质的。这正是我过去的数据科学背景帮助很大的时候,因为我可以在我们的请求者的情况下轻松地定位自己。最后,当我作为一名 NLP 工程师或数据科学家工作时,我已经解决了多年类似的挑战。
此外,作为一名数据传播者,我还通过提出自己的观点和提供机器学习和数据科学家社区对行业的一般观点来塑造和影响我公司的 ML 产品的开发。
总结
正如你所看到的,这个角色非常多样化,需要技术和沟通技巧的结合。如果你已经在数据科学或 ML 行业工作了一段时间,并且你喜欢知识共享和公开演讲,这可能是你的正确选择。
对我来说,这是一个平稳的过渡,我相信数据传道者的角色比数据科学中的许多传统角色更适合我的个性。
那么如何开始呢?
我认为最重要的转变是从知识消费向知识创造转变。你可能已经阅读并关注了数百个在线教程,但是你有没有想过写一个呢?
即使你是这个领域的初级学生,也有一些你已经知道的东西,你可以和比你落后一步的人分享这些经验。如果你在网上分享你的作品,随着时间的推移,更多正式的机会将会到来!
PS:我正在 Medium 和https://www.aboutdatablog.com/上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的 邮件列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入https://medium.com/@konkiewicz.m/membership。**
下面是一些你可能会喜欢的帖子
**💔-great-slack-data-science-communities-to-join-this-year-9d1bb1f51682> **
什么是数据可靠性工程师——你需要吗?
随着数据团队继续专业化,一个新的角色出现了:数据可靠性工程师。
数据可靠性工程师确保高质量的数据在整个组织中随时可用,并且始终值得信赖。图片由 Shutterstock.com的 Tamas Gabor 提供
随着软件系统在 21 世纪后期变得越来越复杂,合并开发和运营(DevOps)是显而易见的。
一半是软件工程师,一半是操作管理员,DevOps professional 的任务是在构建高性能系统和使它们安全、可伸缩和可访问之间架起一座桥梁。这不是一件容易的工作,但总得有人去做。
随着 DevOps 变得越来越流行和广泛,这个曾经新生的领域开始再次专门化。很快,站点可靠性工程师、基础设施工程师和安全工程师出现了,为软件开发带来了额外的专业知识层,允许公司快速移动,打破(许多)东西,并仍然构建更可靠和可伸缩的应用程序。
数据和分析正处于类似的十字路口:曾经的新兴职业,数据分析,以及最近的数据工程,现在是大多数认真使用数据的技术组织的重要组成部分。
“数据十年”让位于另一个专业领域:分析工程师。一部分是分析师,一部分是数据工程师,分析工程师负责将流程、框架和技术与业务利益相关者的数据需求保持一致。
这些趋势表明了一个在技术专业人士中普遍认可的真理:当一个领域的子集开始消耗如此多的时间、精力和资源时,组织和个人进行专业化就变得更加高效和有效。
那么,预计下一个主要的数据专业化是什么?数据可靠性工程师。以下是你的团队投资一个项目的原因和是否有意义。
让我们开始吧。
什么是数据可靠性工程师?
在过去几年中,随着雪花、红移和数据块等云数据仓库和湖泊的兴起,数据管道变得越来越分散和复杂,公司吸收的运营数据和第三方数据比以往任何时候都多。随着越来越多的利益相关者在数据的整个生命周期中与数据进行交互,确保高质量的数据已经成为数据团队的首要基本需求。
尽管如此,数据可靠性是更容易渴望比实现。毕竟,数据可能因为数百万个原因而损坏,从操作问题到不可预见的代码更改。Gartner 指出,仅在 2021 年,数据质量差的成本就高达每年 1290 万美元。这还没有考虑到机会成本的损失。
在过去几年与数百个团队交谈后,我们发现数据工程师和数据科学家至少花了 30%的时间处理数据质量问题。
这种对信任的高度需求导致了跨数据团队的数据工程子类的出现,称为数据可靠性工程。
数据可靠性工程师负责帮助组织在从接收到最终产品的整个数据生命周期中提供高数据可用性和质量:仪表板、机器学习模型和生产数据集。
因此,数据可靠性工程师通常会应用 DevOps 和现场可靠性工程的最佳实践,例如持续监控、设置SLA、事件管理以及对数据系统的可观察性。
数据可靠性工程师是做什么的?
这个新兴领域仍处于早期阶段,但像 DoorDash 、迪士尼流媒体服务和 Equifax 这样的公司已经开始雇佣数据可靠性工程师。
数据可靠性工程师最重要的工作是确保高质量的数据在整个组织中随时可用,并且在任何时候都值得信赖。
当损坏的数据管道出现时(因为它们总会在某一点出现),数据可靠性工程师应该是第一个发现数据质量问题的人,尽管情况并不总是如此。很多时候,坏数据首先是在仪表板和报告的下游被发现的,而不是在管道中——甚至在此之前。由于数据很少处于理想的、完全可靠的状态,数据可靠性工程师更经常的任务是将工具(如数据可观察性平台和测试)和流程(如 CI/CD)放在适当的位置,以确保当问题发生时,它们得到快速解决,并将影响传递给需要知道的人。
就像站点可靠性工程师是软件工程团队的自然延伸一样,数据可靠性工程师是数据和分析团队的延伸。
许多数据可靠性工程师在数据工程、数据科学甚至数据分析方面都有很强的背景。该角色需要对复杂的数据系统、计算机编程语言和框架(如 dbt、Airflow、Java、Python 和 SQL)有深刻的理解。
数据可靠性工程师还应该有使用流行云系统的经验,如 AWS 、 GCP 、雪花或 Databricks,并了解扩展数据平台的行业最佳实践。
数据可靠性工程师职位描述示例
有三种常见的数据可靠性工程职称,表示不同级别的资历。
通常,数据可靠性工程师拥有 3 年以上的数据工程经验,并且对整个数据生态系统有着大致的了解。
高级数据可靠性工程师通常有 5-7 年以上的经验,对数据工程最佳实践有丰富的知识,可以负责从构思到完成的任务。高级数据可靠性工程师通常负责围绕分布式数据团队和相关利益相关方的构建系统、流程和工作流制定策略。
数据可靠性工程经理往往拥有超过十年的经验,并且担任数据工程师至少 3-5 年以上。经理负责增加、扩展和雇佣数据可靠性工程时间,同时保持设计和构建更安全和可扩展的数据系统的高标准。
(当然,对这些任期建议要有所保留。我们曾与伟大的数据工程领导者共事过,他们在相关领域的经验要少得多。
虽然数据可靠性工程师的主要职责是确保您的组织拥有高质量的数据并最大限度地减少数据停机时间,但他们还有其他职责。这里有三个数据可靠性工程师职位描述我们发现它们有效地描述了这个职位。
在拥有 6000 名员工的食品配送公司 DoorDash ,一名数据可靠性工程师负责:
- 开发和实施新技术,以确保不断提高数据可靠性和数据可观察性。
- 定义决定数据质量的业务规则,协助编写验证业务规则的测试,并执行严格的测试以确保数据质量。
- 与应用程序、数据平台和数据工程团队紧密合作,重新配置数据接收管道,使其更加可靠并受到持续监控。
- 与跨职能团队一起管理数据事件并推动无过失事后分析。
对于拥有 2,600 名员工的娱乐巨头迪士尼流媒体服务公司,一名数据可靠性工程经理负责:
- 领导一个专注于解决端到端可靠性改进的数据可靠性工程师团队。
- 拥有事故管理流程,以确保事故得到快速解决,并执行和理解根本原因分析,以防止重复发生。
- 帮助团队向用户提供出色的服务,使公司更加以数据为导向。
对于全球上市信用风险评估公司 Equifax,高级数据可靠性工程师负责:
- 监控数据存储和数据分析系统的性能和可靠性,提出改进性能和可靠性的建议。
- 维护数据管道和其他大数据处理系统的基础设施可靠性。
- 主要致力于维护数据库、数据管道、部署和这些系统的可用性。
顶级数据可靠性工程师面试问题
如今,大多数工程面试都是通过视频会议进行的。图片由 Shutterstock.com菲兹克斯 提供。
雇佣一名数据可靠性工程师并不是一件容易的事情。尤其是如果这是你第一次招聘和/或申请这个职位,你可能不知道该问什么问题或期望回答什么问题。
以下是数据可靠性工程师在面试该职位时经常要回答的一些常见问题:
- 你最喜欢使用哪种编程语言?
- 数据可靠性工程师最重要的职责是什么?
- 你如何与组织中的跨职能团队沟通?
- 服务水平协议(SLA)和服务水平目标(SLO)之间有什么区别?
- 组织如何提高可观察性?
- 你能给我举个例子,说明你什么时候发现了一个以前没有发现的数据质量问题,以及你是如何传达这个影响的吗?
- 您将如何建立事故管理工作流程?
- 您如何使用您的工具来沟通和衡量数据质量的影响?
作为面试过程的一部分,也要考虑一些 leet 编码或应用程序设计的问题。你甚至可能会被要求在一个虚拟的环境中工作,这个环境包含了你未来雇主的数据堆栈中的工具,比如 Airflow 或者 dbt 。
您如何应用数据可靠性生命周期?
如前所述,数据可靠性工程师负责管理有助于提高数据平台可扩展性和可操作性的流程、技术和工作流。
事实上,许多数据团队正在从 DevOps 生命周期转向数据,并利用一个名为数据可靠性生命周期的适应流程来管理可靠数据的可用性。
数据可靠性生命周期是一种全组织范围的方法,通过将 DevOps 的最佳实践应用于数据管道,持续主动地改善数据健康状况并消除数据质量问题。
数据可靠性生命周期由三个阶段组成:检测、解决和预防。图片由巴尔·摩西提供。
通过将该框架应用于数据管道,数据可靠性工程师可以率先发现数据质量问题,充分了解影响,确切了解管道中的数据中断位置,采取行动,并收集经验教训以防止未来出现类似问题。
这种关键方法有三个主要阶段:
检测:数据可靠性工程师依靠自动监控和警报来发现新鲜度、容量、模式、沿袭和分发数据问题。借助自动化警报,当数据事件发生时,您的团队将能够更快地行动和高效地工作。
解决:在此步骤中,数据可靠性工程师应与下游利益相关方沟通,告知数据存在潜在问题,他们正在努力解决该问题。理想情况下,在 Slack、微软团队或者甚至是一个专门的网页中可能会有一个中心频道,用户可以跟随它来获取更新。
**预防:**在这一阶段,数据可靠性工程师处理他们的学习成果,并依靠来自其数据管道的历史数据,将它们转化为可操作的步骤以向前推进。从本质上讲,数据可靠性工程师给出了发生的变化的适当背景,以及它们是否是有意的。
例如,一家电子商务公司可能会在节日期间看到销售额的增长;因此,数据仓库中包含每日销售额的表每 12 小时更新一次。但与此同时,意外的模式更改确实会发生,当工程师将更新推送到生产环境时,原本是 daily_sales 的表意外地变成了 daily_sale 的表应该被标记出来。
随着时间的推移,随着您的数据可靠性团队的成长和数据堆栈的发展,您的测试和监控应该会自动调整和更新,以满足业务需求并最终减少中断的数据管道。像数据观察平台这样的机器学习工具会有所帮助。
数据可靠性工程师如何衡量成功?
在我们的 SRE 同行中流传着这样一句话:“如果你不能衡量它,你就不能管理它。”而且,随着数据系统的复杂性不断发展,对组织的重要性不断增加,我们可以将同样的说法应用于数据可靠性工程师。
众所周知,企业始终拥有可靠的数据是多么重要。为了衡量您的数据可靠性工程工作的成功,我们建议您衡量以下 KPI:数据信任、数据采用,以及针对数据质量问题的检测时间(TTD)、和解决时间(TTR) 。
数据信任和采用
对于数据可靠性工程师来说,最好的迹象之一是看到数据采用的全面增加。如果利益相关者使用数据进行决策,他们很可能会信任他们随时可以获得的数据的质量。
数据可靠性工程师需要了解关键数据计划的运营分析,如数据治理、数据质量、性能和成本。图片由蒙特卡洛提供。
尽早与利益相关方保持一致并就衡量整个公司数据质量的基准指标达成一致至关重要,因为这通常是主观的衡量,并且会因使用数据的团队而异。
一旦您定义了跨不同部门的高质量数据,您将更好地理解如何测量它,并可以定期与利益相关者进行核对,以与您团队的数据质量计划保持一致。过去,我见过数据团队向业务利益相关方发送季度调查,要求他们对可用数据的质量进行评级,或者利用运营分析平台来监控使用了哪些数据集、哪些团队使用了最多的数据,以及数据存储是否经过优化以最佳管理平台成本。一些数据工程师甚至使用数据质量测试的数量、最“活跃”的数据质量监视器,以及其他关注可观察性的统计数据,这些统计数据告知治理和数据质量过程是否实际工作。
数据停机时间
对于数据可靠性工程师来说,数据信任是另一个关键的“KPI ”,但实际上如何衡量呢?对于任何努力实现数据驱动的公司来说,测量数据停机时间是必不可少的。
数据停机时间是指数据损坏、丢失或出现其他错误的时间段,消耗了数据工程师 40%以上的时间,从许多方面来说,这是对数据可靠性工程师影响的最准确的衡量。
数据停机时间由三部分组成:
- 数据事件的数量(N) —鉴于您依赖于团队“外部”的数据源,这一点总是不在您的控制之下;然而,它无疑是数据正常运行时间的驱动因素。数据事件是指数据产品(例如,查看者仪表板)不准确的情况,这可能是由各种原因造成的。
- 检测时间(TTD) —当事故发生时,您的团队能多快意识到?如果没有适当的检测方法,不良数据结果中的隐性错误会导致贵公司和客户做出代价高昂的决策。
- 解决时间(TTR) —当事故发生时,您的团队解决问题的速度有多快?理想情况下,这个数字应该尽可能的低,并且沿袭的自动化工具使得追踪上游和下游的依赖关系更加容易。
为了衡量数据停机时间,我们推荐以下 KPI:
数据停机时间=数据事故数量
X
(检测时间+解析时间)
通过测量数据停机时间,您的团队可以确定数据的可靠性,看看他们是否可以将数据用于分析、ML 和其他生产用例,或者数据是否需要进一步处理和清理。
数据服务级别协议
通过制定数据质量服务水平协议(SLA ),数据可靠性工程师可以更好地定义(最重要的是,衡量)他们为企业其他部门提供的服务水平。
SLA 将有助于数据可靠性工程师与组织的其他部门就数据中最重要的内容达成一致,并有助于对传入的请求进行优先级排序。它们还应该包括服务级别指标(sli)和商定的服务级别目标(SLO)。
以 Red Ventures 为例——他们的子公司之一 Red Digital 依靠人工智能驱动的数字营销、顶级分析和来自其内容网络的数据来帮助他们的客户吸引和获得最有价值的客户。因此,广告公司需要及时准确的数据,以免影响收入。
Red Ventures 的高级数据科学家 Brandon Beidel 每周与每个业务团队会面,讨论团队如何使用数据以及数据质量如何影响他们的工作。
Beidel 发现,最好用简单的商业术语来组织对话,并关注数据的“谁、什么、哪里、何时、为什么和如何”。
他发现自己创建的以下模板在与业务利益相关方进行 SLA 对话时很有帮助。
以上是一个数据 SLA 模板,由 Red Ventures 的 Brandon Beidel 创建并经其许可使用。
为数据 SLA 准备一个简单的结构允许他的团队在满足不同团队对数据的需求方面不断发展,而不会被请求淹没。
数据可靠性工程的未来是什么样的?
LinkedIn 今年早些时候报道称,网站可靠性工程师是过去五年中增长最快的职位之一;同样,商业内幕报道称,数据科学家是 2022 年第二受欢迎的工作。显然,对洞察力和可靠性的需求从未如此之高。
数据工程师和分析师越来越多地承担起确保数据系统可靠性和质量的任务。随着堆栈变得越来越复杂,数据需求增加,公司将开始采用新的(经过战斗考验的)技术、流程和文化来跟上步伐。
数据可靠性工程师会跟进吗?只有时间能证明一切。
但是我们知道我们在哪里下注。
有兴趣了解更多关于数据可靠性工程的知识吗?伸出手去 格伦利奥 ,其余的 蒙特卡洛团队 了解更多信息。
本文由格伦·威利斯合著。
什么是机器学习工程师?
意见
试图理解人工智能/人工智能行业中模糊定义的角色
作者创作的标题卡
我是一家财富 50 强公司的首席机器学习(ML)工程师,我最常被问到的问题之一就是这篇文章标题中的问题:“什么是 ML 工程师?”事实是,似乎没有一个放之四海而皆准的答案。虽然我肯定没有积极寻找新的角色,但我实际上喜欢看其他公司的招聘信息,只是为了了解其他公司在 ML 工程师技能方面的需求。现实是,当谈到像数据科学家、ML 工程师,甚至某些类型的软件工程师这样的角色时,在技能组合的期望方面有很多重叠。公司 A 定义 ML 工程师的方式可能与公司 B 定义数据科学家的方式完全相同,尽管头衔不同,但每个角色都执行完全相同的活动。这些定义的范围确实很广!
也就是说,我不会试图给 ML 工程师下一个非常精确的定义。(因为我敢肯定,如果我试图这么做,我会让某人发疯的!)相反,我认为一个更有用的考试应该是理解通常与 ML 工程师相关的技能。在分析了这些技能组合之后,我们将具体地将一般 ML 工程师和一般数据科学家的技能组合并列,特别是因为我最常听到的一个问题是,“数据科学家和 ML 工程师之间的区别是什么?”最后,我们将通过对行业发展方向的分析来总结一下,这样你就可以为未来做好最好的准备。
ML 工程师的基本技能
虽然很难确定一个 ML 工程师的精确定义,但我们至少在技能组合中看到了足够的共性,我们可以将它们大致分为三类:机器学习/深度学习、软件工程和技术架构。下面我们将更详细地分析这三个类别的含义。在继续之前,我确实想解决一个你可能会奇怪地注意到从列表中遗漏的技能:数据工程。我故意在这个列表中省略了数据工程,因为我实际上发现这种技能通常需要自己的角色,所以虽然 ML 工程师在他们的角色中执行数据工程肯定不是不可能的,但它更经常被归入像数据分析师或数据工程师这样的角色。
机器学习/深度学习
这是最简单的;就在题目里!这涉及到一个人使用机器学习和深度学习算法建立一个预测模型来解决某种商业问题。我们将在下一节更深入地探讨这一点,但实际上似乎 ML 工程师更关注最终集成到实时系统中的更复杂的计算问题。换句话说,我听到更多的人工智能工程师专注于更深入的学习问题,如计算机视觉或自然语言处理(NLP),而不是解决涉及结构化表格数据的问题。同样,这并不是说 ML 工程师从不为表格数据建立预测模型。我相信一个 ML 工程师经常花更多的时间在构建更复杂的计算模型上的部分原因是因为它需要我们的下一个技能…
软件工程
特别是当涉及到深度学习时,对于一个 ML 工程师来说,拥有一套软件工程技能是绝对“必须”的。不管你是选择使用 TensorFlow、PyTorch,还是其他计算复杂度较低的算法库,几乎所有的机器学习都以软件工程代码的形式出现。大多数 ML 工程师需要特别理解 Python 编码语言,但是如果构建 iOS 应用程序,要求 ML 工程师理解 Swift 之类的第二语言,或者如果构建 Android 应用程序,要求 ML 工程师理解 Java 之类的第二语言,这并不罕见。此外,因为应用机器学习将自己表现为软件产品,所以 ML 工程师通常需要理解与任何其他一般软件工程师角色相关的基本内容:单元测试、安全扫描、CI/CD 管道等等。
技术架构
因为应用机器学习/深度学习表现为软件产品,所以 ML 工程师拥有技术架构技能集是非常常见的。这就是构建一个“蓝图”的全部思想,这个“蓝图”展示了整个系统是如何协同工作并恰当地发挥功能的。这种工作通常不是在真空中完成的。在我自己作为 ML 工程师的角色中,我与其他更通用的技术/软件工程师合作,以了解我的机器学习 API 和批量推理解决方案如何在整个总体系统中发挥作用。因为许多公司正在向云迁移,所以一家公司要求一名 ML 工程师在相当复杂的层面上理解像亚马逊网络服务(AWS)、谷歌云平台(GCP)或微软 Azure 这样的云服务是很常见的。通常需要 ML 工程师知道这些云平台中的多个服务如何一起工作,以便适当地部署机器学习解决方案。
将数据科学家角色与 ML 工程师并列
在进入下一部分之前,请允许我再次重申,公司对这些角色的定义相当模糊,所以如果这些定义与你的经验不符,请不要感到惊讶。我经常听到的一个问题是“数据科学家和 ML 工程师的区别是什么?”或者更简洁地说,“数据科学家和 ML 工程师之间有区别吗?”我认为后一个问题的答案是肯定的,但“在沙地上画出那条线”是一项艰巨的任务。
让我们退一步来理解数据科学一般是什么。数据科学之所以被称为数据科学,是因为它反映了科学方法。是的,这和你可能在高中生物课上学到的科学方法是一样的。**本质上,数据科学通过设置实验组和对照组并分析它们之间的概率差异(p 值)来了解是否有任何统计意义,从而在数据中寻找模式。**如果我们能找到统计意义,那么我们就能建立预测模型,对未来的数据进行推断。
在这种形式下,数据科学与机器学习没有直接的、一对一的关联。换句话说,我们不必总是使用机器学习来建立预测模型。尤其是保险行业,在不需要机器学习的情况下,使用广义线性模型(GLMs)等数学算法已经超过一个世纪,取得了巨大的成效。事实上,由于这个原因,许多精算分析师和统计学家最近被重新命名为“数据科学家”,我同意这是一个非常公平的行动。(公平,但对我来说,它更像是一种营销/招聘工具。😂)
有了对数据科学的这种理解,你可以开始看到数据科学家和 ML 工程师的技能组合之间的二分法。数据科学家通常需要更强的数学背景,而不是软件工程背景,因为他们可以依赖“低代码”工具来完成工作,如业界最喜欢的 SAS 工具。我很高兴在许多顶尖大学指导数据科学专业的本科生和研究生,他们会告诉你这绝对是重点。奇怪的是,在我交谈过的学生中,没有一个人把重点放在软件工程或技术架构上。当谈到机器学习时,学生们经常花费大量时间用 C++编程语言从头开始编写机器学习算法(例如,支持向量机、朴素贝叶斯、梯度提升树)。
ML 工程师角色的未来
我想非常小心,以免听起来像是我在贬低传统数据科学家角色的价值。数据科学家仍然非常有价值,因为他们通过构建这些为公司提供大量价值的伟大预测模型,一次又一次地证明了自己的价值。归根结底,是不是机器学习并不重要:商业价值就是商业价值。(需要明确的是,许多数据科学家确实使用机器学习来获得商业价值。)
也就是说,我们已经看到新技术的出现,这些新技术需要软件工程和技术架构的额外技能,而这些技能在传统的数据科学家角色中是找不到的。在我对各大公司招聘信息的分析中,我看到更多的是强调这些额外的工程技能,因此对 ML 工程师的需求总体上也在增长。当然,他们可能不一定被冠以“ML 工程师”的头衔,但你绝对可以期待看到对具有上述三种技能组合的个人的持续兴趣。
好消息是,如果你现在是一名拥有强大数学背景的数据科学家,我个人认为这是最难获得的技能。是的,转向一个新的技能组合并不容易,但我认为对于一个具有强大数据科学背景的人来说,获得一个软件工程技能组合要比反之更容易。
希望你喜欢这篇文章!最后一次重申:你对如何定义 ML 工程师角色的体验会有所不同。我个人非常享受担任这个角色的时光!它提供了右脑创造力的巨大中间地带,当构建模型时,用左脑工程实现这些模型来解决真正有趣的问题。看到我们行业的未来走向,我非常激动!😃
什么是感知器?
了解神经网络的构建模块
拉蒙·萨利内罗在 Unsplash 上的照片
感知器是来自监督学习领域的算法,代表了神经网络的基本构建模块。在其最简单的形式中,它由一个使用加权输入值计算输出值的单个神经元组成。
感知器是如何工作的?
感知器最初是一个数学模型,由于它学习复杂关系的能力,后来才被用于计算机科学和机器学习。在其最简单的形式中,它由一个所谓的神经元组成,模仿人脑的结构。
感知器有几个输入端,它在这些输入端接收数字信息,即数值。根据应用的不同,输入的数量可能会有所不同。输入具有不同的权重,这表明输入对最终输出的影响程度。在学习过程中,权重被改变以产生可能的最佳结果。
感知器的结构|来源:作者
然后,神经元本身形成输入值乘以输入权重的总和。这个加权和被传递给所谓的激活函数。在神经元的最简单形式中,正好有两个输出,因此只能预测二进制输出,例如,“是”或“否”或“活动”或“不活动”等。
Sigmoid 函数曲线|来源:作者
如果神经元具有二进制输出值,则使用其值也在 0 和 1 之间的函数。经常使用的激活函数的一个例子是 sigmoid 函数。函数值在 0 和 1 之间变化,实际上几乎只取这些值。除了 x = 0,还有一个陡升,从 0 跳到 1。因此,如果感知器的加权和超过 x = 0,并且感知器使用 sigmoid 作为激活函数,则输出也相应地从 0 变为 1。
哪个例子说明了感知器是如何工作的?
作为一个感知机如何工作的例子,让我们仔细看看一个政治家的工作。她是国会议员,一项新的法律必须投票表决。因此,政治家必须决定她是否同意该法案(在我们的例子中弃权是不可能的)。因此,感知器有一个二进制输出,即批准或拒绝。
政治家们可以从各种信息来源中获得决策所需的信息。一方面,有一份由议会发布的背景资料的资料文件。此外,政治家可以在互联网上了解各种问题,或者与同事讨论这些问题。这位政治家根据她认为可靠的程度来衡量她的输入,即她的信息来源。例如,她给议会信息文件的权重相对较低,因为她担心研究不够详细,应该已经倾向于某个方向。然后,她将可用信息的总和与权重一起传递给激活函数。
在这个例子中,我们可以把这个想象成我们政治家的头。她现在决定,根据输入的信息,她是否应该同意拟议的法律。即使输入的小细节也能导致政治家观点的巨大变化。
什么是多层感知器?
这个简单的模型已经可以用于许多应用程序,但在理解和学习更复杂的关系时很快就达到了极限。因此,在实践中,重点主要是几层感知器,然后将它们组装起来,形成所谓的人工神经网络。
这些所谓的多层感知器以这样一种方式相互连接,即只有第一层神经元接收来自网络外部的输入。另一方面,在后续层中,先前层的输出充当当前层的输入。只有神经网络最后一层的神经元是输出,然后被用作实际结果。
神经网络结构|来源:作者
与我们的政策例子相关,我们可以更仔细地观察政治家的信息来源。例如,议会的信息文件由各种研究助理的工作组成,他们的加权工作已被纳入最终产品。反过来,这些合作者也可以表示为网络中的个体感知器。
有哪些偏向神经元?
在多层感知器中,使用所谓的偏置神经元。这些是特殊的输入神经元,然而,它们没有外部意义,而是假定一个在学习过程中也会改变的恒定值。这允许激活函数的曲线向下或向上移动。
例如,偏差类似于线性回归中使用的常数,有助于模型更好地拟合输出值,从而改善结果。
哪些应用使用了感知器?
神经网络基于感知机,主要用于机器学习领域。这里的目标主要是学习以前数据中的结构,然后预测新的值。一些例子是:
- 图像中的物体识别 : 人工神经网络可以识别图像中的物体或将图像归入某一类。例如,公司在自动驾驶中使用这一属性来识别汽车应该做出反应的对象。另一个应用领域是在医学中,例如,当检查 X 射线图像以检测癌症的早期阶段时。
- 顾客情感分析 :通过互联网,顾客有很多渠道公开对品牌或产品的评价。因此,公司需要跟踪客户是否大部分满意。有了一些被分类为好或坏的评论,可以训练高效的模型,然后这些模型可以自动对大量评论进行分类。
- 垃圾邮件检测:在许多邮件程序中,有可能将具体的电子邮件标记为垃圾邮件。这些数据用于训练机器学习模型,这些模型直接将未来的电子邮件标记为垃圾邮件,这样最终用户甚至不会看到它们。
感知器的优缺点是什么?
感知器的使用具有以下优点和缺点。
优势
- 借助单层感知器,特别是多层感知器,即所谓的神经网络,可以在监督学习的领域中学习复杂的预测。
- 根据数据,可以很容易地增加输入的数量,以便在预测中包含不同的相关值。
- 受过训练的感知器相对容易解释,学习到的权重可以用来说明输入有多重要。
不足之处
- 单个感知器很少能提供真正好的结果。对于强大的模型,通常必须建立具有许多神经元的不同层。
- 尤其是多层感知器只对大型数据集有效。
- 训练多层感知器通常是耗时且资源密集的。
- 在许多层中,权重的可解释性丧失了,并且形成了一个“黑箱”,其良好的预测无法真正得到解释。
这是你应该带走的东西
- 感知器是来自监督学习领域的算法,代表神经网络的基本构建块。
- 当单个感知器被构建并连接成多层时,它被称为多层感知器或神经网络。
- 感知器由输入、权重、激活函数和输出组成。
- 它可以用来学习数据中的复杂关系,并将它们应用到新的、以前看不到的数据中。
如果你喜欢我的作品,请在这里订阅https://medium.com/subscribe/@niklas_lang或者查看我的网站 数据大本营 !此外,媒体允许你每月免费阅读三篇文章*。如果你想让无限制地访问我的文章和数以千计的精彩文章,不要犹豫,通过点击我的推荐链接:【https://medium.com/@niklas_lang/membership】每月花$ 5 获得会员资格*
什么是量子计算机?
量子计算机是一项将产生重大影响的新兴技术
图 1: IBM 量子系统一号(CES 2020) /来源链接 (CC BY-ND 2.0)
量子计算和人工智能可以结合起来,产生更大的影响。这篇博文的目标是介绍量子计算机的基本概念,并试图揭开它们的神秘面纱。量子计算机使用在微观(亚原子)水平上观察到的物质属性来执行计算和解决问题。相比之下,目前的计算机(自 20 世纪 50 年代以来)在相对宏观(半导体元素)的水平上使用物质的属性。量子计算机的进展将在不久的将来产生重大影响。它可以使当前的互联网加密标准变得无用,减少药物开发时间,改变人工智能等等。量子计算机已经展示了(例如, 肖尔算法 )与非量子(又名经典计算机)计算机相比的指数加速。这篇文章概括了以下内容。
- 量子计算背后的物理学
- 它将如何/为什么超越基于芯片的计算
- 会更好地解决哪些问题
经典到量子物理学
通过利用硅半导体的独特特性,向数字世界的过渡成为可能。它只有在满足某些条件后才导电,否则就像绝缘体一样。这种行为被用来执行基本级操作,例如与/或逻辑、基本算术运算等。通过硅门。计算机就是建立在这些基础之上的。
经典物理学在元素水平(如硅、铜)描述物质的属性,我们控制并使用这些属性进行计算、数据存储和信息处理及传输。
同样,量子物理/力学在微观亚原子水平上解释物质的性质,即电子和光子。量子计算机在亚原子水平上控制和利用物质的属性来执行计算。经典物理和量子物理的区别不仅仅在于尺度或大小。经典物理学的规则在量子层面失效了。我们需要一套全新的方法和工程来建造量子计算机。
表 1:经典物理和量子物理之间的高度差异
自从量子力学的框架第一次被开发出来已经有一个多世纪了,但是科学家们对量子水平上的观察的含义还没有达成共识。 哥本哈根解释 ,这是归功于尼尔斯·玻尔和维尔纳·海森堡的最普遍接受的版本。甚至阿尔伯特·爱因斯坦也没有完全接受哥本哈根解释。事实上,爱因斯坦的广义相对论并不符合量子力学,他最初拒绝量子力学,因为它的不确定性。
硅基计算的终极之路
1965 年,戈登·摩尔预测计算机的速度大约每两年翻一番。它被编码为摩尔定律,至今仍被证明是正确的。在此期间,硅晶体管的尺寸不断缩小。最初的尺寸是一个拇指指甲的大小,即 1950 年代的 1cm。现在在 2022 年,它是 3 纳米(即小于 1cm 的~7 个数量级),接近硅原子的大小(. 2 纳米)。物理上不可能将硅晶体管的尺寸缩小到原子尺寸以下来获得进一步的加速。因此,一些人呼吁终止基于半导体计算的摩尔定律。计算创新的下一阶段可能由量子计算机引领。
图 2:对数标度中的摩尔定律图表/来源:ourworldindata.org&卡尔鲁普(CC BY 4.0)
量子解
更高级软件和架构的创新,例如机器学习和分布式/并行计算的形式,已经提供了克服一些计算限制以解决更困难问题的手段。但与这些解决方案不同,量子计算机从头开始提供计算增益。它有可能引领计算领域的下一波创新,以解决棘手的问题。量子计算的计算收益将比摩尔定律预测的快几个数量级。由于加速发生在基础层,它可以与更高层次的创新相结合,如机器学习,如 量子机器学习 (例如 谷歌量子人工智能 ),以及作为托管云服务提供的商品化&(例如 亚马逊 Braket 量子计算机 s) 。
量子特性
量子计算的两个基本属性是:
- 叠加
- 纠缠
在我们进入它们之前,掌握一个量子位的概念是很重要的。
量子位(vs 比特)
经典计算、存储和通信中的信息单位是一个位,用二进制数 0 或 1 表示。它们是硬件(硅晶体管)级别的低电荷和高电荷(电压)的数字表示。硬件单元的状态总是 0(低电压)或 1(高电压)。在量子水平上,事情并不是那么分散的。在亚原子粒子被观察到(测量到)之前,它处于 0 和 1 两种状态,也就是说,一个电子可以向上或向下旋转。量子系统中的这种信息或状态单位被称为量子位。
a)叠加
这种在量子系统中同时为 0 和 1 的现象被称为*叠加。*叠加表示量子比特(qubits)的所有可能状态。不同状态的叠加在测量过程中坍缩成特定的状态。这在薛定谔的猫的思想实验中得到了说明,在这个实验中,一只猫和一个放射源一起被放在一个密封的盒子里,在人们观察盒子里的情况之前,它被认为是既活又死的。
b)纠缠
这是一种现象,其中两个或更多的亚原子粒子具有相同的状态属性(例如,0 或 1),尽管它们之间有距离。没有人能解释这是为什么或如何发生的。如果亚原子粒子之间存在某种通信来实现这一点,信号的传播速度必须超过光速,根据爱因斯坦的相对论,这是不可能的。爱因斯坦将纠缠称为“超距幽灵行动”。
量子计算机与经典计算机
量子计算机有多个处于纠缠态的量子比特,同时进行所有可能的量子比特组合。它们被折叠成所需的状态以解决特定的问题。由于一个量子位可以同时处于 0 或 1 状态,一台 n 量子位量子计算机可以同时处理 2ⁿ 状态。经典计算机需要双倍的位数(内存)或处理速率来实现双倍的速度。在量子计算机中,只需再增加一个量子比特(即量子比特),速度就会翻倍。因此,它可以比一次处理一个状态的经典计算机获得指数级的加速。理论上,一台 28 量子位的量子计算机相当于超过 268 百万位(2 ⁸)的硅基经典计算机,如表 2 所示。
量子优势是量子计算机可以在合理的时间内解决经典计算机无法解决的问题的既定目标。2019 年 10 月,谷歌声称他们用 54 量子位实现了量子优势。
表 2:基于比特/量子比特大小比较经典计算机和量子计算机
表 2:第 1 列和第 2 列摘自来源[ 1 和[ 2 ]。第三列是基于量子特性的外推。第四栏是我的理论比较,不代表任何官方价值。事实上,我的值可能被低估了,因为谷歌证实了他们在 2019 年实现量子优势的 54 量子位(表 2 第 5 行)量子计算机在 200 秒内完成了一项超级计算机需要 10,000 年才能完成的任务。
将量子位添加到架构中并不是一件容易的事情,因为它们对环境条件非常敏感,这会导致量子属性的损失。量子计算机需要接近绝对零度的温度,即大约-460 华氏度,才能运行。
量子计算机用例
并不是所有的问题都会受益于量子计算机,正如我在之前的帖子中所讨论的,机器学习与传统软件开发相比,并不是所有的问题都能得到更好的解决。
值得注意的是,目前量子计算机的使用仅限于特定的问题,包括一些 NP 难题,这需要在大的搜索空间中筛选。量子计算机已经在一些领域有所作为:
- 药物发现
- 加密破解
- 最佳化
由于叠加性质,量子计算机可以在一个周期内模拟整个解搜索空间的所有组合,而经典计算机需要多次迭代。因此,量子计算机最适合搜索和组合优化问题。上面列出的用例就属于这一类。
摘要
量子计算机非常有前途,已经开始解决现实世界的问题。只要我们能够通过控制亚原子粒子运行的环境来保持它们的量子特性,我们就能够在架构中添加更多的量子位。确定哪些问题更适合量子计算机和构建量子算法是活跃的研究领域。迄今为止, 格罗弗算法 和 肖尔算法 是最受欢迎的量子算法,与非量子算法相比,它们分别提供了多项式和指数加速。
在未来,经典计算机和量子计算机将共存,并将相互补充。经典计算机更适合于顺序任务(例如,在我的笔记本电脑上写这篇博客)和事务性任务(例如,计算购物车余额),而量子计算机将用于解决具有大解决方案搜索空间的更困难的问题。
资源
- https://en.wikipedia.org/wiki/Quantum_supremacy
- https://analyticsindiamag . com/race-quantum-supreme-complete-timeline/
- 量子叠加——维基百科
- 波粒二象性——维基百科
- 量子机器学习—维基百科
- 谷歌量子人工智能
- https://research.ibm.com/quantum-computing
- 亚马逊 Braket 量子计算机——亚马逊网络服务
- 亚马逊 Braket——量子计算入门| AWS 新闻博客
- 肖尔算法—维基百科
- https://en.wikipedia.org/wiki/Grover’s_algorithm
- 非结构化问题的量子加速:解决两个二十年前的问题——微软研究
- 哥本哈根解读—维基百科
- 测不准原理—维基百科
- https://phys . org/news/2015-11-quantum-迭加原理-事件. html
- https://www . scientific American . com/video/how-do-a-quantum-computer-work/
【https://en.wikipedia.org/wiki/Schr%C3%B6dinger%27s_cat】T21 - https://www . scientific American . com/article/quantum-computers-competition-for-supremity/
- https://www . popular mechanics . com/science/green-tech/a 30915638/quantum-memory-entangled/
- https://phys . org/news/2015-11-quantum-迭加原理-事件. html
- https://www . mcgill tribune . com/sci-tech/the-universe-at-odds-quantum-mechanics-vs-general-relativity 040418/
- https://www . technology review . com/2019/01/29/66141/什么是量子计算/
- 【https://en.wikipedia.org/wiki/NP-hardness
- https://Cambridge quantum . com/the-journal/future-quantum-drug-discovery/
在 Keras 和 Tensorflow 中为 NLP 项目实现 SimpleRNN、GRU 和 LSTM 模型
阿特·哈廷顿在 Unsplash 上拍摄的照片
在 Keras 和 Tensorflow 中为 NLP 项目实现 SimpleRNN、GRU 和 LSTM 模型
递归神经网络介绍及情感分析中三种递归神经网络在 Tensorflow 和 Keras 中的实现
递归神经网络(RNNs)是深度学习中最先进的算法之一,尤其适用于序列数据。它被用于许多备受瞩目的应用,包括谷歌的语音搜索和苹果的 Siri。它变得如此受欢迎的原因是它的内存。RNNs 是第一个可以记住输入的深度学习算法。在 LSTM 和 GRU 发明之后,rnn 变得非常强大。在本文中,我们将使用所有这三种类型的 rnn 进行一个自然语言处理项目。
我们将讨论 RNNs 如何工作,并在深度学习领域带来如此多的效率。对于情感分析任务,将有一个简单的 RNN、GRU 和 LSTM 的实际实现。
我将非常简要地讨论一个简单的递归神经网络如何为复习者工作,然后深入到实现中。如果您愿意,可以跳过这一部分,直接进入 Tensorflow 实现部分。
什么是递归神经网络?
因为递归神经网络有内部记忆,所以可以从输入和前几层记住重要的东西。这就是它比常规神经网络更有效的原因,rnn 是文本数据、时间序列、金融数据、天气预报等序列数据的首选算法。
递归神经网络如何工作?
为了真正理解递归神经网络如何工作以及它为什么特殊,我们需要将它与常规的前馈神经网络进行比较。
以下是常规前馈神经网络的图片演示:
作者图片
在前馈神经网络中,信息从一层移动到另一层。我们使用来自输入层的信息来计算隐藏层。如果有几个隐藏层,则仅使用前一个隐藏层的信息来计算下一个隐藏层。计算输出图层时,仅使用前一图层的信息。因此,当我们计算输出层时,我们忘记了输入层或其他层。
但是,当我们处理文本数据、时间序列数据或任何其他顺序数据时,记住前面的层中有什么也很重要。
在 RNN,信息在内部循环。因此,当 RNN 计算输出图层时,它会考虑前一个图层以及前一个图层。因为它有短期记忆。这里有一个图片演示:
作者图片
如图所示,信息在这一层循环。当循环发生时,它具有来自最近过去的信息。下面是 RNN 结构的展开版本,可以更好地理解它的工作原理:
作者图片
这里,x0、x1 和 x2 表示输入。H0、H1 和 H2 是隐藏层中的神经元,y0、y1 和 y2 是输出。
如上图所示,每个时间戳都从前一个神经元和输入中获取信息。信息在一层中循环。
这非常重要,因为前一个神经元可能包含关于下一个神经元的重要信息。例如,考虑这个句子,
天空是蓝色的
如果我只知道“是”这个词,我无法想象接下来会发生什么。但是如果我知道两个连续的单词“sky is ”,那么我们可能会想到单词“blue”。
但这也是递归神经网络的一个局限。RNNs 只有短期记忆。但是短期记忆始终不足以发现接下来会发生什么。举个例子,
她是中国人,她的语言是…
在这里,仅仅记住前面的两三个单词并不能让我们知道语言是什么。我们要一路走来记住“中国人”这个词。只有到那时,我们才能预测这种语言的名称。
这就是长短期记忆(LSTM)或门控循环单元(GRU)有所帮助的时候。它们都是简单 RNN 的更高级版本。解释它们的机制超出了本文的范围。本文的重点是展示如何在 TensorFlow 中实现它们。
资料组
我将使用 Tensorflow 附带的 IMDB 数据集。这是一个大型电影评论数据集。数据是文本数据,标签是二进制的。它已经为我们分离了 25000 个训练数据和 25000 个测试数据。点击了解关于该数据集的更多信息。对于练习一些自然语言处理任务来说,这是一个非常好的数据集。该数据集的每一行都包含预期的文本数据,标签为 0 或 1。所以,它代表好的情绪或坏的情绪。
让我们深入研究这个项目。
以下是进口货:
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds
我正在导入 IMDB 数据集及其信息:
imdb, info = tfds.load("imdb_reviews",
with_info=True, as_supervised=True)
在单独的变量中设置训练和测试数据:
train_data, test_data = imdb['train'], imdb['test']
数据预处理
将所有文本作为一个列表,将标签作为一个单独的列表将会很有帮助。因此,训练句子和标签以及测试句子和标签作为列表被检索如下:
training_sentences = []
training_labels = []testing_sentences = []
testing_labels = []for s,l in train_data:
training_sentences.append(str(s.numpy()))
training_labels.append(l.numpy())for s,l in test_data:
testing_sentences.append(str(s.numpy()))
testing_labels.append(l.numpy())
将标签转换为 NumPy 数组:
training_labels_final = np.array(training_labels)
testing_labels_final = np.array(testing_labels)
在这里,我设置一些重要的参数是必要的模型。我将在此之后解释它们是什么:
vocab_size = 10000
embedding_dim=16
max_length = 120
trunc_type= 'post'
oov_tok="<OOV>"
这里,vocal_size 10000。这意味着这个模型将使用 10000 个独特的单词。如果 IMDB 数据集超过 10000 个单词,多余的单词将不会用于训练模型。所以,通常情况下,我们会小心翼翼地取这个数。请随意尝试不同的 vocab_size。
下一个参数是‘embedding _ dim’。它表示将用于表示每个单词的向量的大小。这里 embedding_dim 是 16 意味着,大小为 16 的向量将表示每个单词。您也可以在此尝试不同的号码。
每段文本或预测标签的最大长度为 120 个单词。这就是 max_length 参数所表示的内容。如果文本比原来大,它将被截断。
下一个参数 trunc_type 设置为‘post’。这意味着文本将在末尾被截断。
如果有一个未知单词将由 oov_tok 表示。
数据预处理从标记 NLP 项目中的文本开始。
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequencestokenizer = Tokenizer(num_words = vocab_size, oov_token=oov_tok)
tokenizer.fit_on_texts(training_sentences)
word_index = tokenizer.word_indexword_index
以下是 word_index 的部分输出:
{'<OOV>': 1,
'the': 2,
'and': 3,
'a': 4,
'of': 5,
'to': 6,
'is': 7,
'br': 8,
'in': 9,
'it': 10,
'i': 11,
'this': 12,
'that': 13,
'was': 14,
'as': 15,
'for': 16,
'with': 17,
'movie': 18,
因此,每个单词都有一个唯一的整数值。这里我们用这些整数值代替单词来安排句子。此外,如果句子少于我们设置的 max_length 120 个单词,请使用填充。这样,我们将为每个文本提供相同大小的向量。
sequences = tokenizer.texts_to_sequences(training_sentences)
padded = pad_sequences(sequences, maxlen=max_length,
truncating = trunc_type)testing_sequences = tokenizer.texts_to_sequences(testing_sentences)
testing_padded = pad_sequences(testing_sequences, maxlen=max_length)
数据预处理完成。
模型开发
这是有趣的部分。
简单的 RNN
第一个模型将是简单的递归神经网络模型。
在这个模型中,第一层将是嵌入层,其中句子将通过嵌入向量表示为 max_length。下一层是一个简单的 RNN 层。然后是致密层。这是模型
model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, embedding_dim,
input_length=max_length),
tf.keras.layers.SimpleRNN(32),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.summary()
输出:
Model: "sequential_8"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_8 (Embedding) (None, 120, 16) 160000
_________________________________________________________________
simple_rnn (SimpleRNN) (None, 32) 1568
_________________________________________________________________
dense_16 (Dense) (None, 10) 330
_________________________________________________________________
dense_17 (Dense) (None, 1) 11
=================================================================
Total params: 161,909
Trainable params: 161,909
Non-trainable params: 0
_________________________
看每一层的输出形状。第一层输出形状为(120,16)。记住我们每个句子的 max_length 是 120,嵌入维数是 16。请随意更改这些数字并检查结果。
在第二层中,我们将 32 作为 SimpleRNN 层中的参数,输出形状也是 32。
这里,我们将使用 binary_crossentropy 的损失函数、“adam”优化器以及作为准确性的评估度量来编译模型。
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
我将训练 30 个纪元的模型。
num_epochs=30
history=model.fit(padded, training_labels_final, epochs=num_epochs, validation_data = (testing_padded, testing_labels_final))
输出:
Epoch 1/30
782/782 [==============================] - 17s 20ms/step - loss: 0.6881 - accuracy: 0.5256 - val_loss: 0.6479 - val_accuracy: 0.6355
Epoch 2/30
782/782 [==============================] - 15s 19ms/step - loss: 0.5035 - accuracy: 0.7632 - val_loss: 0.4880 - val_accuracy: 0.7865
Epoch 3/30
782/782 [==============================] - 15s 20ms/step - loss: 0.2917 - accuracy: 0.8804 - val_loss: 0.5812 - val_accuracy: 0.7457
Epoch 4/30
782/782 [==============================] - 16s 20ms/step - loss: 0.1393 - accuracy: 0.9489 - val_loss: 0.6386 - val_accuracy: 0.7952
Epoch 5/30
782/782 [==============================] - 15s 19ms/step - loss: 0.0655 - accuracy: 0.9768 - val_loss: 0.9400 - val_accuracy: 0.7277
Epoch 6/30
782/782 [==============================] - 16s 20ms/step - loss: 0.0360 - accuracy: 0.9880 - val_loss: 0.9493 - val_accuracy: 0.7912
Epoch 7/30
782/782 [==============================] - 15s 20ms/step - loss: 0.0273 - accuracy: 0.9900 - val_loss: 1.1033 - val_accuracy: 0.7491
Epoch 8/30
782/782 [==============================] - 16s 20ms/step - loss: 0.0993 - accuracy: 0.9639 - val_loss: 1.1237 - val_accuracy: 0.5752
Epoch 9/30
782/782 [==============================] - 15s 19ms/step - loss: 0.2071 - accuracy: 0.9136 - val_loss: 1.0613 - val_accuracy: 0.6309
Epoch 10/30
782/782 [==============================] - 15s 20ms/step - loss: 0.0267 - accuracy: 0.9928 - val_loss: 1.4416 - val_accuracy: 0.6720
Epoch 11/30
782/782 [==============================] - 16s 20ms/step - loss: 0.0031 - accuracy: 0.9996 - val_loss: 1.6674 - val_accuracy: 0.6721
Epoch 12/30
782/782 [==============================] - 15s 20ms/step - loss: 5.8072e-04 - accuracy: 1.0000 - val_loss: 1.8338 - val_accuracy: 0.6714
Epoch 13/30
782/782 [==============================] - 15s 19ms/step - loss: 2.5399e-04 - accuracy: 1.0000 - val_loss: 1.8619 - val_accuracy: 0.6824
Epoch 14/30
782/782 [==============================] - 15s 20ms/step - loss: 1.4048e-04 - accuracy: 1.0000 - val_loss: 1.8995 - val_accuracy: 0.6927
Epoch 15/30
782/782 [==============================] - 15s 20ms/step - loss: 8.4974e-05 - accuracy: 1.0000 - val_loss: 1.9867 - val_accuracy: 0.6934
Epoch 16/30
782/782 [==============================] - 15s 20ms/step - loss: 5.2411e-05 - accuracy: 1.0000 - val_loss: 2.0710 - val_accuracy: 0.6940
Epoch 17/30
782/782 [==============================] - 17s 22ms/step - loss: 3.2760e-05 - accuracy: 1.0000 - val_loss: 2.1278 - val_accuracy: 0.6980
Epoch 18/30
782/782 [==============================] - 16s 20ms/step - loss: 2.0648e-05 - accuracy: 1.0000 - val_loss: 2.2035 - val_accuracy: 0.6988
Epoch 19/30
782/782 [==============================] - 15s 19ms/step - loss: 1.3099e-05 - accuracy: 1.0000 - val_loss: 2.2611 - val_accuracy: 0.7031
Epoch 20/30
782/782 [==============================] - 15s 20ms/step - loss: 8.3039e-06 - accuracy: 1.0000 - val_loss: 2.3340 - val_accuracy: 0.7038
Epoch 21/30
782/782 [==============================] - 16s 20ms/step - loss: 5.2835e-06 - accuracy: 1.0000 - val_loss: 2.4453 - val_accuracy: 0.7003
Epoch 22/30
782/782 [==============================] - 16s 20ms/step - loss: 3.3794e-06 - accuracy: 1.0000 - val_loss: 2.4580 - val_accuracy: 0.7083
Epoch 23/30
782/782 [==============================] - 20s 26ms/step - loss: 2.1589e-06 - accuracy: 1.0000 - val_loss: 2.5184 - val_accuracy: 0.7112
Epoch 24/30
782/782 [==============================] - 18s 23ms/step - loss: 1.3891e-06 - accuracy: 1.0000 - val_loss: 2.6400 - val_accuracy: 0.7055
Epoch 25/30
782/782 [==============================] - 20s 25ms/step - loss: 8.9716e-07 - accuracy: 1.0000 - val_loss: 2.6727 - val_accuracy: 0.7107
Epoch 26/30
782/782 [==============================] - 20s 25ms/step - loss: 5.7747e-07 - accuracy: 1.0000 - val_loss: 2.7517 - val_accuracy: 0.7105
Epoch 27/30
782/782 [==============================] - 17s 22ms/step - loss: 3.7458e-07 - accuracy: 1.0000 - val_loss: 2.7854 - val_accuracy: 0.7159
Epoch 28/30
782/782 [==============================] - 18s 23ms/step - loss: 2.4265e-07 - accuracy: 1.0000 - val_loss: 2.8592 - val_accuracy: 0.7158
Epoch 29/30
782/782 [==============================] - 17s 22ms/step - loss: 1.5808e-07 - accuracy: 1.0000 - val_loss: 2.9216 - val_accuracy: 0.7172
Epoch 30/30
782/782 [==============================] - 17s 22ms/step - loss: 1.0345e-07 - accuracy: 1.0000 - val_loss: 2.9910 - val_accuracy: 0.7174
30 个周期后,训练精度变为 1.00 或 100%。完美,对吧?但验证准确率为 71.74%。没那么糟。但是巨大的过度拟合问题。
这将是很好的,看看如何精度和损失随着每个时代的变化。
import matplotlib.pyplot as pltdef plot_graphs(history, string):
plt.plot(history.history[string])
plt.plot(history.history['val_'+string])
plt.xlabel("Epochs")
plt.ylabel(string)
plt.legend([string, 'val_'+string])
plt.show()plot_graphs(history, 'accuracy')
plot_graphs(history, 'loss')
作者图片
验证精度在开始时波动很大,然后稳定在 71.74%。另一方面,训练精度稳步上升到 100%,除了一个下降。
但是验证的损失曲线看起来很糟糕。它一直在上升。我们希望损失减少。
门控循环单元(GRU)
这是 RNN 模型的改进版本。它比简单的神经网络模型更有效。它有两个门:复位和更新。在本次演示中,我将用具有相同数量单位的双向 GRU 层替换 SimpleRNN 层。
这是模型
model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, embedding_dim,
input_length=max_length),
tf.keras.layers.Bidirectional(tf.keras.layers.GRU(32)),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.summary()
输出:
Model: "sequential_6"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_6 (Embedding) (None, 120, 16) 160000
_________________________________________________________________
bidirectional_6 (Bidirection (None, 64) 9600
_________________________________________________________________
dense_12 (Dense) (None, 10) 650
_________________________________________________________________
dense_13 (Dense) (None, 1) 11
=================================================================
Total params: 170,261
Trainable params: 170,261
Non-trainable params: 0
正如你所看到的,除了 GRU 层,所有层的输出形状与前一层完全相同。因为是双向的,所以这里 32 变成了 64。
我将使用与之前完全相同的参数来编译模型,并为相同数量的时期训练模型。
model.compile(loss="binary_crossentropy",
optimizer='adam',
metrics=['accuracy'])history=model.fit(padded, training_labels_final, epochs=num_epochs,
validation_data = (testing_padded,testing_labels_final))
输出:
Epoch 1/30
782/782 [==============================] - 50s 60ms/step - loss: 0.5664 - accuracy: 0.6990 - val_loss: 0.4313 - val_accuracy: 0.8025
Epoch 2/30
782/782 [==============================] - 43s 56ms/step - loss: 0.3638 - accuracy: 0.8440 - val_loss: 0.3667 - val_accuracy: 0.8394
Epoch 3/30
782/782 [==============================] - 44s 56ms/step - loss: 0.2852 - accuracy: 0.8882 - val_loss: 0.3695 - val_accuracy: 0.8420
Epoch 4/30
782/782 [==============================] - 43s 55ms/step - loss: 0.2330 - accuracy: 0.9120 - val_loss: 0.3979 - val_accuracy: 0.8381
Epoch 5/30
782/782 [==============================] - 42s 54ms/step - loss: 0.1942 - accuracy: 0.9323 - val_loss: 0.4386 - val_accuracy: 0.8334
Epoch 6/30
782/782 [==============================] - 44s 56ms/step - loss: 0.1573 - accuracy: 0.9472 - val_loss: 0.4546 - val_accuracy: 0.8290
Epoch 7/30
782/782 [==============================] - 44s 57ms/step - loss: 0.1223 - accuracy: 0.9612 - val_loss: 0.5259 - val_accuracy: 0.8244
Epoch 8/30
782/782 [==============================] - 44s 56ms/step - loss: 0.0897 - accuracy: 0.9729 - val_loss: 0.6248 - val_accuracy: 0.8234
Epoch 9/30
782/782 [==============================] - 44s 57ms/step - loss: 0.0690 - accuracy: 0.9788 - val_loss: 0.6511 - val_accuracy: 0.8169
Epoch 10/30
782/782 [==============================] - 50s 64ms/step - loss: 0.0514 - accuracy: 0.9847 - val_loss: 0.7230 - val_accuracy: 0.8223
Epoch 11/30
782/782 [==============================] - 45s 57ms/step - loss: 0.0402 - accuracy: 0.9882 - val_loss: 0.8357 - val_accuracy: 0.8167
Epoch 12/30
782/782 [==============================] - 52s 67ms/step - loss: 0.0323 - accuracy: 0.9902 - val_loss: 0.9256 - val_accuracy: 0.8140
Epoch 13/30
782/782 [==============================] - 49s 63ms/step - loss: 0.0286 - accuracy: 0.9915 - val_loss: 0.9685 - val_accuracy: 0.8184
Epoch 14/30
782/782 [==============================] - 45s 58ms/step - loss: 0.0232 - accuracy: 0.9930 - val_loss: 0.8898 - val_accuracy: 0.8146
Epoch 15/30
782/782 [==============================] - 44s 57ms/step - loss: 0.0209 - accuracy: 0.9927 - val_loss: 1.0375 - val_accuracy: 0.8144
Epoch 16/30
782/782 [==============================] - 43s 55ms/step - loss: 0.0179 - accuracy: 0.9944 - val_loss: 1.0408 - val_accuracy: 0.8131
Epoch 17/30
782/782 [==============================] - 45s 57ms/step - loss: 0.0131 - accuracy: 0.9960 - val_loss: 1.0855 - val_accuracy: 0.8143
Epoch 18/30
782/782 [==============================] - 43s 55ms/step - loss: 0.0122 - accuracy: 0.9964 - val_loss: 1.1825 - val_accuracy: 0.8105
Epoch 19/30
782/782 [==============================] - 45s 57ms/step - loss: 0.0091 - accuracy: 0.9972 - val_loss: 1.3037 - val_accuracy: 0.8097
Epoch 20/30
782/782 [==============================] - 44s 56ms/step - loss: 0.0089 - accuracy: 0.9972 - val_loss: 1.2140 - val_accuracy: 0.8125
Epoch 21/30
782/782 [==============================] - 45s 58ms/step - loss: 0.0076 - accuracy: 0.9976 - val_loss: 1.2321 - val_accuracy: 0.8136
Epoch 22/30
782/782 [==============================] - 45s 58ms/step - loss: 0.0119 - accuracy: 0.9962 - val_loss: 1.1726 - val_accuracy: 0.8072
Epoch 23/30
782/782 [==============================] - 46s 59ms/step - loss: 0.0093 - accuracy: 0.9969 - val_loss: 1.2273 - val_accuracy: 0.8029
Epoch 24/30
782/782 [==============================] - 45s 57ms/step - loss: 0.0065 - accuracy: 0.9978 - val_loss: 1.3390 - val_accuracy: 0.8118
Epoch 25/30
782/782 [==============================] - 50s 64ms/step - loss: 0.0053 - accuracy: 0.9984 - val_loss: 1.2323 - val_accuracy: 0.8088
Epoch 26/30
782/782 [==============================] - 44s 56ms/step - loss: 0.0081 - accuracy: 0.9973 - val_loss: 1.2998 - val_accuracy: 0.8123
Epoch 27/30
782/782 [==============================] - 44s 57ms/step - loss: 0.0043 - accuracy: 0.9986 - val_loss: 1.3976 - val_accuracy: 0.8098
Epoch 28/30
782/782 [==============================] - 41s 53ms/step - loss: 0.0039 - accuracy: 0.9989 - val_loss: 1.6791 - val_accuracy: 0.8043
Epoch 29/30
782/782 [==============================] - 42s 54ms/step - loss: 0.0037 - accuracy: 0.9987 - val_loss: 1.4269 - val_accuracy: 0.8101
Epoch 30/30
782/782 [==============================] - 41s 53ms/step - loss: 0.0059 - accuracy: 0.9982 - val_loss: 1.4012 - val_accuracy: 0.8150
如您所见,30 个时期后,训练集的最终准确度为 0.9982 或 99.82%,验证准确度的准确度为 81.50%。训练精度略低于简单的 RNN 模型,但验证精度显著提高。
仍然存在过度拟合的问题。但是在 NLP 项目中,一些过度拟合是正常的。因为不管你的训练集里有什么词库,验证数据可能还是会有一些新词。
每个历元的精度和损耗图将更好地显示每个历元的精度和损耗是如何变化的。我将使用上一节中的 plot_graphs 函数来绘制图形。
plot_graphs(history, 'accuracy')
plot_graphs(history, 'loss')
作者图片
训练的准确率逐渐提高,随着 epochs 的增加达到 99%以上。但是验证准确率上升到了 85%,并保持相当稳定。
如您所见,验证损失仍在上升。但是如果你注意 y 轴上的数字,对于简单的 RNN,验证损失从 0.5 变成了 3.0。但是对于这个 GRU 模型,它从 0.4 上升到 1.7。因此,总体验证损失要小得多。
长期短期模型(LSTM)
我还想展示一个 LSTM 模型的实现。LSTM 模型和 GRU 模型的主要区别是,LSTM 模型有三个门(输入、输出和遗忘门),而 GRU 模型有两个门,如前所述。
在这里,我将只取代 GRU 层从以前的模型,并使用 LSTM 层。模型如下:
model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32)),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
model.summary()
输出:
Model: "sequential_5"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_5 (Embedding) (None, 120, 16) 160000
_________________________________________________________________
bidirectional_5 (Bidirection (None, 64) 12544
_________________________________________________________________
dense_10 (Dense) (None, 10) 650
_________________________________________________________________
dense_11 (Dense) (None, 1) 11
=================================================================
Total params: 173,205
Trainable params: 173,205
Non-trainable params: 0
模型摘要看起来几乎接近于上一节中的 GRU 模型。输出形状完全相同。但是 params #在 LSTM 层是不同的。因为如前所述,LSTM 模型有三个门,而不是两个门。我会再训练 30 个纪元:
num_epochs=30
history = model.fit(padded, training_labels_final, epochs=num_epochs, validation_data = (testing_padded, testing_labels_final))
输出:
Epoch 1/30
782/782 [==============================] - 46s 54ms/step - loss: 0.4740 - accuracy: 0.7665 - val_loss: 0.3732 - val_accuracy: 0.8413
Epoch 2/30
782/782 [==============================] - 38s 48ms/step - loss: 0.3010 - accuracy: 0.8789 - val_loss: 0.3687 - val_accuracy: 0.8397
Epoch 3/30
782/782 [==============================] - 37s 48ms/step - loss: 0.2380 - accuracy: 0.9079 - val_loss: 0.4850 - val_accuracy: 0.8311
Epoch 4/30
782/782 [==============================] - 38s 48ms/step - loss: 0.1890 - accuracy: 0.9306 - val_loss: 0.4697 - val_accuracy: 0.8355
Epoch 5/30
782/782 [==============================] - 41s 53ms/step - loss: 0.1453 - accuracy: 0.9494 - val_loss: 0.4581 - val_accuracy: 0.8305
Epoch 6/30
782/782 [==============================] - 42s 54ms/step - loss: 0.1118 - accuracy: 0.9622 - val_loss: 0.7176 - val_accuracy: 0.8212
Epoch 7/30
782/782 [==============================] - 41s 53ms/step - loss: 0.0952 - accuracy: 0.9676 - val_loss: 0.7107 - val_accuracy: 0.8230
Epoch 8/30
782/782 [==============================] - 41s 52ms/step - loss: 0.0769 - accuracy: 0.9753 - val_loss: 0.6845 - val_accuracy: 0.8205
Epoch 9/30
782/782 [==============================] - 39s 49ms/step - loss: 0.0567 - accuracy: 0.9824 - val_loss: 0.9333 - val_accuracy: 0.8163
Epoch 10/30
782/782 [==============================] - 42s 54ms/step - loss: 0.0564 - accuracy: 0.9826 - val_loss: 0.8228 - val_accuracy: 0.8171
Epoch 11/30
782/782 [==============================] - 42s 54ms/step - loss: 0.0466 - accuracy: 0.9862 - val_loss: 0.9426 - val_accuracy: 0.8177
Epoch 12/30
782/782 [==============================] - 44s 56ms/step - loss: 0.0445 - accuracy: 0.9861 - val_loss: 0.9138 - val_accuracy: 0.8144
Epoch 13/30
782/782 [==============================] - 44s 57ms/step - loss: 0.0343 - accuracy: 0.9897 - val_loss: 0.9876 - val_accuracy: 0.8149
Epoch 14/30
782/782 [==============================] - 42s 53ms/step - loss: 0.0282 - accuracy: 0.9919 - val_loss: 1.0017 - val_accuracy: 0.8152
Epoch 15/30
782/782 [==============================] - 41s 52ms/step - loss: 0.0251 - accuracy: 0.9932 - val_loss: 1.0724 - val_accuracy: 0.8158
Epoch 16/30
782/782 [==============================] - 41s 53ms/step - loss: 0.0267 - accuracy: 0.9912 - val_loss: 1.0648 - val_accuracy: 0.8117
Epoch 17/30
782/782 [==============================] - 43s 55ms/step - loss: 0.0258 - accuracy: 0.9922 - val_loss: 0.9267 - val_accuracy: 0.8109
Epoch 18/30
782/782 [==============================] - 40s 51ms/step - loss: 0.0211 - accuracy: 0.9936 - val_loss: 1.0909 - val_accuracy: 0.8104
Epoch 19/30
782/782 [==============================] - 38s 49ms/step - loss: 0.0114 - accuracy: 0.9967 - val_loss: 1.1444 - val_accuracy: 0.8134
Epoch 20/30
782/782 [==============================] - 38s 48ms/step - loss: 0.0154 - accuracy: 0.9954 - val_loss: 1.1040 - val_accuracy: 0.8124
Epoch 21/30
782/782 [==============================] - 38s 49ms/step - loss: 0.0196 - accuracy: 0.9941 - val_loss: 1.2061 - val_accuracy: 0.8128
Epoch 22/30
782/782 [==============================] - 41s 53ms/step - loss: 0.0093 - accuracy: 0.9971 - val_loss: 1.3365 - val_accuracy: 0.8032
Epoch 23/30
782/782 [==============================] - 42s 54ms/step - loss: 0.0155 - accuracy: 0.9953 - val_loss: 1.2835 - val_accuracy: 0.8123
Epoch 24/30
782/782 [==============================] - 43s 55ms/step - loss: 0.0168 - accuracy: 0.9948 - val_loss: 1.2476 - val_accuracy: 0.8160
Epoch 25/30
782/782 [==============================] - 38s 48ms/step - loss: 0.0108 - accuracy: 0.9967 - val_loss: 1.0810 - val_accuracy: 0.8091
Epoch 26/30
782/782 [==============================] - 39s 50ms/step - loss: 0.0132 - accuracy: 0.9960 - val_loss: 1.3154 - val_accuracy: 0.8118
Epoch 27/30
782/782 [==============================] - 42s 54ms/step - loss: 0.0056 - accuracy: 0.9985 - val_loss: 1.4012 - val_accuracy: 0.8106
Epoch 28/30
782/782 [==============================] - 40s 51ms/step - loss: 0.0046 - accuracy: 0.9986 - val_loss: 1.4809 - val_accuracy: 0.8134
Epoch 29/30
782/782 [==============================] - 40s 51ms/step - loss: 0.0074 - accuracy: 0.9977 - val_loss: 1.4389 - val_accuracy: 0.8104
Epoch 30/30
782/782 [==============================] - 41s 52ms/step - loss: 0.0126 - accuracy: 0.9958 - val_loss: 1.2202 - val_accuracy: 0.8124
如你所见,训练精度和验证精度非常接近 GRU 模型。剧情是这样的:
plot_graphs(history, 'accuracy')
plot_graphs(history, 'loss')
作者图片
验证损失这次更好。
结论
在这篇文章中,我想解释什么是递归神经网络,以及为什么对于序列数据它比常规神经网络更好。然后演示了一个简单的 RNN、GRU 和 LSTM 模型的实现,该模型使用相同的数据集执行自然语言处理任务。这是一个特别的情感分析项目。
这篇文章展示了 GRU 和 LSTM 模型的准确性结果看起来相似。但这并不是一个普遍的结论。对于不同的项目,您可能会看到不同的结果。事实上,如果你改变一些参数,如神经元的数量,GRU 或 LSTM 单位,层数,你可能会看到这个项目的结果有很大的不同。
请随时在 Twitter 、脸书页面上关注我,并查看我的新 YouTube。频道。
更多阅读
</30-very-useful-pandas-functions-for-everyday-data-analysis-tasks-f1eae16409af>
什么是关系知识图?
探索图形数据库和知识图的未来
图片作者。背景图片,由米卡·鲍梅斯特 在 Unsplash| Unspash.com 拍摄的免版税照片
如果关系知识图这个术语还没有出现在你的雷达上,我想它很快就会出现了。Bob Muglia 是雪花公司的前首席执行官,现在是一家推广新模式的初创公司的董事会董事。
在 FactEngine 工作时,我早期的命名思想倾向于引入术语图形数据库,在 FactEngine 中,我在寻找一个术语来充分描述图形和关系数据库的合并,而不是术语多模型数据库。
无论从哪个角度看,图形数据库和关系数据库的合并变得越来越明显,我相信关系知识图这个术语将会一直存在。
属性图模式工作组的出现标志着图形数据库市场的成熟,例如,将关系数据库中常见的特性引入图形数据库和知识图。
这个由研究人员和图形数据库供应商组成的小组已经认识到,现存的图形数据库缺乏支持关系数据库的正式形式的技巧,并且没有意识到要将 21 世纪的现象带入 21 世纪。在网上搜索这个团体的名字,会返回各种各样的宣言和支持。
尽管您可能听不到该组织吹捧该组织是关系数据库领域标准的领导者,但我怀疑就像《动物庄园》中的场景一样,盛大的声明将是“现在我们有了这些标准,一些数据库比其他的更平等”。
关系知识图采用了一种完全不同的观点,即任何数据库都可以被看作是图数据库,甚至是关系数据库,如果你采用一种支持这种观点的体系结构,那么你就可以拥有两个世界的优点。
图形数据库供应商长期以来一直吹捧图形数据库在某些查询中比关系数据库更快。当你考虑到微软吹嘘它拥有世界上最快的数据库,SQL Server,一个支持图形结构/查询的关系数据库时,这种说法是可疑的。
在理论层面上,声称在许多图形数据库中数据存储在硬件层面的方式加快了图形查询的速度也是可疑的。例如,即使关系数据库在硬件级存储为一组列分隔的固定结构矩形/表状结构,也无法阻止将硬件级数据作为图形结构加载到内存中,并针对内存中的图形结构运行查询,除了分页之外,需要将查询恢复到仍在磁盘上的数据的图形数据库目前也面临同样的问题…以图形方式将图形结构加载到内存中以执行这些快速查询。
那么,是什么阻碍了关系数据库采用这种架构,并在图形数据库的游戏中击败它们呢?图数据库和关系数据库在元模型级别上真的有概念上的区别吗?
输入相关知识图表
普通关系数据库的元模型阻止了普通图形数据库的图形查询。例如,外键关系缺少自然语言谓词,告诉您诸如“雇员为公司工作”之类的事情,其中雇员和公司是表/节点,而图形数据库供应商可能有一个结构为“雇员为公司工作”。
早在 1985 年,ORACLE 的 Richard Barker 的“ *Case Method,Entity Relationship modeling”*在描述关系数据库的实体关系图中允许这样做,但是由于缺少关系数据库上的图形查询语言,这从未(据我所知)在关系数据库的元模型级别上实际实现用于查询,因为关系数据库的查询语言Structure Query Language(SQL)无论如何都不支持在其语法中使用自然语言谓词。
带有自然语言谓词的风格化 Barker 实体关系图,图片由作者提供。
关系知识图是数据库或数据库之上的架构,其中数据库可以被视为图形数据库或关系数据库。
当我们考虑一个在经典关系视图(实体关系图)和图形视图(属性图模式)之间变化的实际模式时,我们可以直观地理解这是如何工作的:
图形数据库的支持者经常说“在图形数据库中没有多对多的表”(正如上面 ERD 视图中的 PersonLikesFilm 表)。这预先假定了其他关系数据库的数据不会作为图形存储在内存中以供查询,并且忽略了图形数据库中的“是的”这种类型,但是“多对多表数据”通常在硬件级别存储为链表(扁平表),而在概念内存级别将概念化为图形。
这种观点还预先假定,没有一种概念上的方法既有多对多(或多对多……同样)的关系,也有有效的优势。这可以通过采用类似的对象角色建模来克服:
对象-角色模型及其对应的属性图模式。图片作者。
对象-角色模型及其对应的属性图模式和实体关系图。图片作者。点击放大。
我们到达了目的地:关系知识图允许你将你的数据库概念化为关系数据库或图形数据库。选择权在你。
这意味着您可以在数据库上编写 SQL 查询或图形查询。选择权在你。
有经验的玩家会很快说:“我们不是已经得到了吗?SQL Server 之类的产品不是已经满足了 SQL 和图形查询的需求吗?”
简单的回答是,大部分情况下没有,因为我看到的所有包含图形特性的关系数据库都采用了添加特殊的表类型来管理图形查询,结果导致数据库的多语言混乱,可能会使任何使用它的人感到困惑。我几年前写过这个。也就是说,许多关系数据库供应商仍然将图形与表关系分开处理。
关系知识图的不同之处在于,不需要在其他关系数据库上采用不同的图表集来进行图表查询,您只需要在现有数据库结构上有一个语义层来满足图表查询的编写……并让数据库管理系统来考虑如何在底层数据库结构上处理这些查询。不久前,我在《走向数据科学》上写过这个。
也就是说,关系知识图同样可以被称为 图知识关系 ,但是在知识图炒作周期的当前状态下,它可能听起来不那么酷。也就是说,关系知识图并不预先假定数据如何存储在硬件层,以及这个或那个数据库声称拥有世界上最快的数据库,无论它们如何在硬件层存储数据。**
关系知识图的优势是什么?
关系知识图的主要优势在于:
- 在决定项目使用什么样的数据库时,只需要考虑数据库的硬件级实现,以及它的查询执行速度(如果这是先决条件的话);
- 在概念层次上,你可以选择如何描绘你的数据库;作为图形数据库或关系数据库;
- 自然语言语义内置于语义层,在数据库的核心元模型上运行,帮助您理解模型;
- 根据您实现关系知识图的方式,您可以选择要使用的数据库。关系知识图可以与数据库管理系统无关。也就是说,从概念上来说,当涉及到实现时,您并不局限于一种或另一种数据库技术。然而,关系知识图供应商可能会限制您使用一个底层数据库;
- 实体/节点类型可以有一个多列/属性主键,而不是像当前图形数据库中常见的只有一个 object-id 或属性;和
- 在 FactEngine 的情况下,你可以在你的数据库上写受控的自然语言查询。我觉得这将成为关系知识图的标准;
概括起来
- 关系知识图是一个术语,在不久的将来,这个术语很可能会出现在你的雷达上,这完全是因为推广这个术语的新参与者的重要性。
- 行业趋势是图形数据库采用关系数据库的结构和严密性,这种方式必然会导致关系数据库理论和图形数据库理论的概念合并;
- 关系知识图允许您从概念上摆脱数据库在硬件级别的存储方式;和
- 关系知识图,或知识关系图充分强调,通过采用描述存储什么数据而不是如何存储数据的语义层,推动力是添加到数据库的知识。**
感谢阅读。如果时间允许,我会写更多关于知识图表、图表数据库、语义建模和关系数据库的文章。
— — — — — End — — — —
什么是供应链数字孪生?
使用 python 创建代表供应链网络的模型,以优化您的运营并支持战略决策。
(图片由作者提供)
数字孪生是物理对象或系统的数字复制品。
供应链数字模型是一种计算机模型,代表供应链中涉及的各种组件和流程,如仓库、运输网络和生产设施。
使用 Python 的供应链数字双胞胎—(图片由作者提供)
在以前的文章中,我分享了为特定应用设计的 python 模型的例子,如运输路线优化、供应链网络设计或生产计划。
在本文中,我们将尝试后退一步,构建一个供应链数字双胞胎,它将代表您从生产到商店交付的完整的端到端操作。
💌新文章直接免费放入你的收件箱:时事通讯
什么是供应链数字孪生?
面向目标的网络
供应链是一个由流程和库存点组成的面向目标的网络,用于向客户交付货物和服务。
要使用 Python 创建供应链的数字双胞胎,首先需要定义组成供应链的各种组件和流程。
端到端供应链网络—(图片由作者提供)
这可能包括创建数据结构来表示仓库、运输操作和生产设施,并定义这些组件之间的关系。
数据和参数
接下来,您需要收集供应链各种组件和流程的数据,例如
- 仓库的位置和 容量
- 交通网络的路线和容量
- 生产设备的生产率
- 顾客和商店需求
工厂参数—(图片由作者提供)
这些数据可以存储在数据库或其他数据存储系统中,或者直接连接到您的仓库管理系统和 ERP。
模拟块
一旦有了供应链组件和流程的数据,就可以使用 Python 创建复制供应链行为的算法和模拟。
其他优化模型—(图片由作者提供)
这可能涉及使用优化算法来
- 使用来自商店模型的补货订单*(输入)*确定到*(输出)*的最高效路线将商店交付
- 改进您仓库的拣货流程 【输出】准备门店补货订单 【输入】
- 根据商店销售历史数据(输入)建立的需求预测,安排生产(输出)
构建块的示例
总的来说,用 Python 创建一个供应链数字双胞胎将涉及数据收集和分析、算法开发和模拟建模的组合。
这可能需要对供应链管理的深刻理解和 Python 编程的经验。
让我们举三个用 Python 构建的基本块的例子。
如何模拟仓库操作?
我们定义了一个仓库类,它具有仓库的位置、容量和库存的属性。
add_inventory 和 remove_inventory 方法可以分别用于从仓库的库存中添加和删除项目。
这是一个简单的例子,你可以通过考虑流程生产率、仓库成本结构、劳动力管理或拣货流程来添加额外的属性和方法来改进模型。
在这个阶段,确保让运营团队和持续改进工程师参与进来,以确保您的模型能够复制实际的运营。
现实生活中发生的瓶颈、非生产性任务和质量问题必须包含在您的模拟中,以验证您的模型。
💡不要忘记“双胞胎” 如果你的模型离现实太远,就会失去可信度。
事实上,如果你的最终目标是使用你从这个模型中获得的洞察力,确保用于构建它的假设和参数得到所有利益相关者的验证。
这意味着匆忙设计一个带有粗略假设的快速而肮脏的模型是没有用的。
如果您使用这些结果来推动持续改进计划或挑战他们的管理,您可以确信运营部门会仔细分析这些结果。
例如,确保考虑:
- 您的工厂和仓库中每个工人的合理生产率和容量
- 评估运营稳健性时的外部约束,如假期、劳动法规或设备采购限制*(例如,您不能在一天内将提货能力翻倍)*
- 运输限制,如卡车采购、道路限制或交通堵塞
如何模拟公路运输?
我们定义了一个卡车类,它具有卡车的位置、容量和负载的属性。
move_to 方法可用于将卡车移动到新的位置,而 load_cargo 和 unload_cargo 方法可分别用于装载和卸载货物。
上述解决方案可以通过添加装载和卸载时间、用于提前期计算的时间戳、成本参数或详细说明处理单元(托盘、纸箱……)来改进。
如何模拟门店库存管理?
我们定义了一个 Store 类,它具有商店位置和库存的属性。
place_order 方法可用于订购给定的商品和数量。
- 如果商店库存中有足够的商品,订单将被履行,库存也将相应地更新。
- 否则,将打印一条错误消息。
您可以通过以下方式改进它
外向销售将代表最重要的参数,因为它与需求相关联。
您可以通过以下方式测试供应链的弹性
- 模拟该需求的可变性(例如使用正态分布)
- 创造季节性和高峰期,复制促销和系列发布
- 预测未来的销售和新店开张,对你的网络进行压力测试,并获得如何改进的见解
需求可变性对不良库存规则的影响示例—(图片由作者提供)
后续步骤
关注我的媒体,获取更多与数据分析和供应链管理相关的文章
连接积木
现在你已经完成了基本的独立积木,你需要把它们连接起来
并添加外部参数如客户需求或原材料供应约束。
模拟几个场景来回答业务问题
场景 1:商店需求翻倍
- 对仓库容量会有什么影响?
- 为了避免商店缺货,我们需要多少天的库存?
场景 2:您将所有本地仓库合并到一个中央配送中心:
- 对服务水平会有什么影响?
- 能否通过工厂直接发货(针对部分 SKU)来降低运输和仓储成本?
场景 3:您希望减少 25%的仓库库存
- 工厂的最大补货周期应该是多少?
- 避免缺货所需的需求计划的最低精确度是多少?
- 对工厂生产水平的稳定性会有什么影响?
场景 4:您希望停止空运以减少二氧化碳排放
- 对商店的补货提前期会有什么影响?
- 配送计划员需要提前多长时间创建补货订单?
对于每种情况,您可以操作与问题相关的参数,看看您的整体性能会降低多少。
然后,您可以调整其他指标(仓库容量、补货提前期等),直到您重新达到初始目标。
这将向您展示供应链中的改进,以获得适应这些新业务需求的稳健性水平。
供应链网络设计方法—(图片由作者提供)
你可以从供应链网络设计的方法论中获得灵感(本文中的),我们尝试模拟 50 种场景的需求波动,假设需求呈正态分布。
对于每个场景,我们使用 python 的线性编程来寻找工厂的最佳组合,以最低的成本生产和向市场交付产品。
50 个场景的结果—(图片由作者提供)
您可以决定您希望实现哪种组合来提高健壮性,同时降低成本。
数字孪生 x 可持续性:绿色库存管理
(图片由作者提供)
绿色库存管理可以定义为以环境可持续的方式管理库存。
对于分销网络而言,这可能涉及一系列旨在减少订单传输、准备和交付的环境影响的流程和规则。
(图片由作者提供)
如果我们降低商场补货频率,会对二氧化碳排放量产生什么影响?
使用数据分析来模拟商店补货频率的变化,并衡量对整体环境影响的影响。
数字孪生 x 可持续发展:时尚循环经济
(图片由作者提供)
循环经济是一种旨在最大限度减少浪费和最大限度提高资源效率的经济模式。
它包括设计注重寿命、重复使用和回收的产品和工艺。
(图片由作者提供)
一些公司已经实施了一种订阅模式,在这种模式下,客户支付一笔固定费用,就可以在的特定时期内获得一种产品或服务。
使用数据分析来模拟循环订阅模式的几种情况对快速时尚零售商的减排和用水的影响。
供应链分析
现在您已经有了供应链的副本,您可以使用参数并使用数据来执行
**描述性分析:**使用仪表盘和可视化工具监控您的流程
一套工具,提供可见性和整个供应链的单一事实来源,以跟踪您的货件、检测事故并衡量您的运营绩效。
诊断分析:自动化根本原因分析流程
这可以概括为事件根本原因分析。
- 使用数据分析的物流绩效管理,Samir Saci
- 交付周期可变性和供应链弹性,Samir Saci
预测和说明性分析:将预测和优化模型添加到您的数字双胞胎中,以改进订购规则或计划
支持运营,以了解最有可能的结果或未来情景及其业务影响。因此,您可以协助运营解决问题,优化资源,以达到最佳效率。
- 零售销售预测的机器学习—特征工程,Samir Saci
- 如何:机器学习驱动的需求预测,尼古拉斯·范德普特
- 利用 Python 、Samir Saci 进行生产固定水平规划
- 使用 Python 、Samir Saci 优化仓库增值服务
- 使用 Python 的寻路算法提高仓库生产率,Samir Saci
- 商店交付计划的机器学习,Samir Saci
欲知详情,
您的数字孪生可以被视为一个核心模型,您可以在其中添加解决特定问题的模型。
关于我
让我们在 Linkedin 和 Twitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运营并降低成本。
如果你对数据分析和供应链感兴趣,可以看看我的网站
https://samirsaci.com