为什么组织需要数据驱动(第二部分)
阻碍组织成为数据驱动型组织的障碍,以及克服这些挑战的建议
这是关于“为什么组织需要数据驱动”的第二篇文章,揭示了成为数据驱动的一些挑战,以及组织如何克服这些挑战以成为真正的数据驱动。这是企业主、企业家、公司企业以及任何想了解组织如何成为数据驱动的人的必读之作。
介绍
作者图片
欢迎阅读我关于“为什么组织需要数据驱动”的文章的第二部分。如果您还没有阅读我在第一篇文章中谈到的数据驱动意味着什么以及为什么数据对每个企业都至关重要,请在继续之前点击此链接阅读文章。
当我起草这份出版物的第一部分时,我认为谈论一些成为数据驱动的挑战而不仅仅是讨论组织如何成为数据驱动的会很好。我发现这一点特别重要,因为除非组织发现并解决我将在本文中提到的一些障碍,否则可能很难真正实现数据驱动或做出有效的数据驱动决策。
在这篇新帖中,我将触及一些阻碍组织成为数据驱动的障碍,并提供一些关于克服挑战以真正成为数据驱动的建议(无论业务类型、利基或行业)。
成为数据驱动型的挑战以及如何真正成为数据驱动型
虽然数据是一种宝贵的资源,如果有效使用,可能会对您的组织有益,但成为数据驱动型企业说起来容易做起来难,而且通常会带来一些令人头疼的问题。根据 TechCrunch 的这份最新调查,72%的大型组织未能创造出一种数据驱动的文化— 这些组织中的大多数都面临着一些挑战,这些挑战往往会干扰数据驱动战略的成功实施。
在回顾了几份研究材料、思考了我的经历并回顾了数据领域中有思想的领导者的观点后,我确定了以下一些组织遇到并需要克服或避免的常见挑战,以确保他们的数据驱动的决策工作和能力不会受到损害或阻碍。
PS:我还包括了克服每个挑战的可能方法。
缺乏数据基础设施、工具和技能组合
过去,大多数公司只存储和分析非常少量的数据,如法律文档、财务记录以及来自其业务的更多数据。但是,随着当今数字化和数据生成速度的急剧加快,现代组织通常会被大量数据流淹没,使用过去适用于小数据量的传统数据库系统和基础架构,不可能有效地存储如此庞大的数据量。可以想象,数据生成的速度和数量将会继续增长。在本帖中,国际数据公司(IDC)甚至预测,到 2025 年,世界数据将增长到 175 万亿千兆字节。
我愿意被纠正,但我坚信现代组织不缺乏数据。然而,大多数组织缺乏的是有效存储/管理不断增长的数据速度、数量、种类和复杂性所需的基础设施和底层工具,以提高业务利用率。有时,一些组织最终会在他们几乎不需要的工具/基础架构上投入大量资金,仅仅是因为他们没有正确的经验来选择适合其业务的适当工具。我在这里试图传递的主要观点是,即使数据是每个组织的业务金矿,如果没有正确的数据基础架构、工具、解决方案、技能集、治理框架和流程,您也无法真正释放其全部潜力。
因此,每个组织都需要正确的专业知识或技能来评估其数据就绪性,设置数据治理策略,从当今市场上存在的无数工具和基础架构中选择适合其组织需求的适当的商业智能(BI)工具、数据存储和管理工具、云解决方案和服务等。在每个组织中有两种培养数据相关能力的主要途径:您可以建立一个专门的数据团队或雇用一名数据专家来正确地指导您的组织走向数据驱动并建立正确的基础架构(我莫,选择完全取决于您,因组织而异)。
例如,如果您的组织没有足够的预算来建立数据团队,一个好的开始方式是与数据顾问合作,并最终随着时间的推移而扩展。一旦您聘请了合适的数据专家或投资组建了数据团队,您的组织就可以更轻松地确保数据的完整性和质量,培训其他团队成员了解利用数据进行业务决策的重要性、可能的可用数据点、数据的存储位置、如何使用数据、可以使用哪些工具等。在某种程度上,这也有助于在您的组织中培养良好的数据文化并提高数据素养。
缺乏数据驱动的文化和全组织的认同
组织和数据驱动型组织之间的另一个挑战是缺乏以数据为中心的文化,这通常以不同的形式表现在新的小公司和较大的组织中。通常,缺乏组织范围内的认同可能是由于利益相关者的漠不关心、对基于数据做出决策的公然抵制、个人偏见、偏见等等。在 EY 的调查中,47%的受访者提到调整组织文化以整合大数据具有挑战性。
这种挑战通常在大型和相对较老的组织中更为明显,这些组织已经有了组织文化和实践,领导者认为他们拥有推动业务增长所需的业务知识和洞察力,即使不看数据也是如此。在某些情况下,这些较大的组织甚至投资并建立了数据基础设施和团队,即使他们不确定如何适当地适应并整合“数据驱动”的心态到他们的公司,数据驱动方法的能力,或解决业务问题的数据团队。初创公司和新公司更有活力,但它们也不会在斗争中被遗忘。哈佛商业评论的 2021 年统计数据显示,一些组织正在努力取得进展,并在打造数据驱动的文化、使用数据推动创新以及将数据作为宝贵资产进行管理方面失去了优势。
采用数据驱动型文化的斗争是真实的成为数据驱动型组织需要的不仅仅是正确的业务战略和技术。我相信它总是从最高层开始,每个公司都需要杰出的领导者和利益相关者,他们可以通过在公司、他们自己和员工中宣扬、实践和倡导数据驱动的文化来改变组织的文化。通常,这些数据倡导者应该始终引领潮流,将数据驱动的方法传播到组织的每个角落,付出更多努力来展示数据的价值,并让企业主了解数据驱动决策的好处和深远影响。 如果没有数据驱动方法的领导,一个组织及其员工真正采用数据驱动的文化可能会很有挑战性(如果不是不可能的话)。
为了更进一步,组织应该鼓励各级员工试验数据,提出数据驱动的业务问题,并根据他们的见解采取行动。你应该让每个人都保持好奇心并分享他们的见解,而不是要求员工低着头,以通常的方式开展业务。此外,您组织中的关键决策者应该总是愿意接受员工的建议,因为这在使每个人都非常自觉并鼓励人们将数据融入日常工作和生活中起着重要作用。我喜欢 Gartner 在他们的帖子:“数据只能让企业走到这一步——真正的驱动力是人。”
总之,你不应该建立一个只有业务领导或员工支持数据驱动文化的组织。虽然建立和采用数据驱动的文化和战略需要大量的时间、努力和承诺,但我相信创建数据驱动的文化是一个非常集体和包容的过程,应该让公司的每个人都参与进来。这样,就更容易推动公司范围内规范的实质性转变,加强数据在组织中的有用性、重要性和力量。
数据收集和使用前没有策略
成为数据驱动型并非偶然或巧合,因为数据无处不在,组织更有可能陷入收集数据的网络,而没有真正考虑他们想要对所有数据做什么。这是一种极具挑战性的方法,通常会导致数据债务,从而阻止组织真正成为数据驱动型组织,并阻碍其真正使用数据来满足特定业务需求、产生实际价值或实现战略目标的能力。在某些情况下,企业领导人和高管往往低估数据债务的影响,主要是因为他们没有意识到它会影响数据相关的计划,并在某种程度上拖累更广泛的关键投资和业务运营。
组织可以通过事先制定清晰的数据收集和使用策略来避免淹没在数据中,而不仅仅是收集数据而不知道如何处理数据。虽然创建数据和分析战略没有放之四海而皆准的方法,但我认为一个好的战略应该以为中心,定义需要回答的业务关键型问题并确定需要应对的挑战,评估您的数据需求和准备情况,定义如何获取、收集、保护数据并将其转化为可操作的见解,评估您的技术基础架构要求、数据能力和治理。
如今,互联网上有大量可用信息,如果没有正确的策略,可能不容易识别和获取对您的组织有益的具体、准确的数据。在数据收集之前有一个策略的总体思想是一个基本元素,适用于人类生活的几乎每个方面。例如,建造一个新公寓需要一个合适的计划和架构来指导项目的执行。
此外,组织还需要通过理解和采用 GDPR 机构指定的正确的隐私法规和规则来创建一个更加透明的世界。这有助于消除企业和客户之间日益增加的不信任差距、市场操纵风险、侵犯隐私、垄断等。通过合规,组织还可以避免制裁、高额罚款以及失去运营许可证的可能性。
我想用这种联系来总结这一部分—“组织需要定义良好的数据和分析策略来获取正确的数据,拥有正确的数据是成为数据驱动型组织并在这个新的数据驱动型世界中取得成功的最基本的先决条件之一”
结论
通常情况下,业务数据提供了有价值的见解,你需要了解你的公司是否在进步,你的竞争对手比你做得更多,你的客户如何看待你的品牌,等等。如果您的组织不是真正的数据驱动型组织,那么您很可能会输给已经将数据作为战略资源和业务流程不可或缺的一部分的数据驱动型组织。
在今天的数字世界中,取得进步并让自己成为赢家的一个极好的方法是检查本文中提到的挑战,解决您的组织目前可能面临的任何限制,然后应用我在本文中建议的原则和技术。尽管如此,请始终记住,成为一个数据驱动的组织不会一夜之间发生— 这是一个深思熟虑的持续旅程,随着时间的推移会带来更好的结果。
我想用这句话来结束我的演讲:“在没有数据的情况下经营企业或做出商业决策,就像在街上瞎跑一样没有一个现代组织希望永远盲目地运营——现在是时候开始掌握和使用数据来推动您的组织向前发展了。我祝你在成为数据驱动的旅程中一切顺利。
人工智能项目可以受益于多重云
为什么组织应该为他们的 AI/ ML 项目考虑多云化策略,以及如何实现它
图像由保罗·西奈拍摄,灵感来自于克劳迪奥·泰斯塔、 social.cut 和卢卡·巴乔
随着组织将其人工智能(AI)解决方案迁移到云,其他组织已经开始实施人工智能或机器学习(ML)多云战略。从以更低的成本推动人工智能驱动的业务解决方案到获得灵活性,采用多云策略(使用几家公共云提供商来管理您的基础设施和应用程序)具有显著的优势。但是采用多云策略是一项复杂的任务。
让我们更详细地看看为您的 AI 和 ML 项目采用多云化策略的一些优势;指出一些挑战,并强调旨在克服这些挑战并推动成功的方法。
多云人工智能战略的优势
采用多云策略的公司可以避免被单一云服务提供商所束缚。一个组织开发的所有知识产权(AI 或 ML 模型、分析、流程、规则、应用程序,甚至数据库)都被锁定并依赖于云提供商的基础设施和产品。这使得将您的知识产权从一个服务提供商迁移到另一个服务提供商变得极其困难。
一旦您构建了一个利用云提供商的许多产品的应用程序,重新配置该应用程序以在另一个云上本机运行可能会非常昂贵和困难。例如,AWS 提供的一些特定产品无法在微软 Azure 或谷歌云平台上开箱即用。因此,迁移到另一个服务提供商可能需要使用另一个服务提供商的等效产品、集成类似的第三方付费产品或使用开源软件来重建您的应用程序的功能;或者完全取消这种功能。将数据从一个云转移到另一个云也极具挑战性。
多重云允许组织将每个云服务提供商的特定产品与其特定的人工智能数据需求和应用程序流程要求相匹配。例如,一个组织的数据科学家可以轻松地扩大或缩小他们的存储容量,并优化计算能力,以使用特定的云服务提供商运行他们的 ML 算法。另一方面,应用程序开发人员可能会选择将他们的应用程序部署在另一个云上,该云托管他们喜欢的数据库,或者更适合处理特定的消费者活动工作负载。
在选择云策略时,带宽和延迟是需要考虑的重要因素。这对于快速响应时间对业务成功至关重要的用例尤为重要。例如,一个在几秒钟内分析成千上万个车牌的车牌识别应用程序无法承受任何延迟。同样,使用 AI 图像识别进行产品质量控制的制造生产线也需要快速的响应时间,以避免产品缺陷。对于此类用例,访问地理上分散的云提供商为企业提供了利用邻近性来减少延迟和降低带宽成本的可能性。
在多云服务提供商上运行您的 AI 项目可提供额外的可靠性,进一步降低停机风险,并为组织提供其业务用例所需的业务连续性。虽然云服务提供商提供不同级别的恢复和冗余,并且这些天很少遇到基础设施崩溃,但事故仍然会发生。组织的业务运营仍然可能因云中断而受到严重损害,尤其是在任务关键型组织中。假设您的一个云提供商遭遇了中断。在几个不同的云上运行你的人工智能应用程序可以让你快速(在某些情况下自动)将你的人工智能应用程序切换到另一个云提供商,并且完全没有市区的体验。
多云策略可以通过多种方式为您提供这种额外的灵活性。您可以选择在同一地区(或附近)拥有不同的云提供商,或者在几个地区拥有不同的云提供商。公平地说,公司也可以使用其他不基于多云供应商的拓扑来解决这些高可用性问题。他们可以选择在单个地理区域使用单个云提供商,但使用不同的可用性区域(一般来说,可用性区域被视为单个数据中心),或者使用分布在不同地理区域的单个云提供商。
多云人工智能战略的挑战
然而,运营多云人工智能项目会带来多种运营和管理挑战。在单一云平台上快速发展需要专门的资源和大量培训。管理多个云上的人工智能操作会增加十倍的复杂性。这需要雇佣云计算专家,并在培训上投入更多。它还要求组织良好的跨职能团队跨多个云设置、监控、优化和保护他们的人工智能应用。
每个云服务提供商都有不同的基础架构、要求、规范和安全设置程序,这使得管理这些不同的云基础架构成为一项艰巨的任务。当发生变化时,需要在每个云上手动更新设置。
很少有组织能够负担得起管理云计算环境所需的专业知识和费用。即使他们可以,他们也会遇到下一个障碍:普遍缺乏机器学习和云基础设施专家。因此,许多组织不具备创建和管理多云计算人工智能解决方案所需的内部专业知识,并发现自己在努力追赶邻居。
为特定工作匹配价格最低的云提供商也是一个优势。但是,管理多个云提供商定价模式、服务水平协议(SLA)和合同很快就会变成一场噩梦。
更简单的多云解决方案
面临这些挑战的企业应该考虑基于云的数据运营平台,该平台具有 MLOps 功能,可在多个云基础设施上管理其 AI 和 ML 项目。这些平台中的大多数都提供了一个中心框架和界面,通过它可以设置、部署、监控、供应和保护组织的 ML、AI 和分析应用程序,同时管理多云、互操作性和可扩展性,从而为组织的 AI 项目提供最终和急需的敏捷性。培训和采用也高度简化。
如今,市场上有许多具有 MLOps 功能的 DataOps 平台。更好的方法支持统一的 ML 方法(MLOps 部分),该方法可以在任何云环境(无论是公共云环境还是私有云环境)中无缝运行,并为您完成大量云基础架构管理工作(DataOps 部分)。它们在不同的云中自动设置、调配和维护您自己的环境,使组织能够轻松采用多云战略,并随着业务和应用需求的变化对其进行微调。
更先进的平台在整个云中保持一致的数据、流程、业务规则和应用实例,使组织能够在异构云平台之间实现完全的敏捷性和工作负载移动性。随着数据的增长,这些平台会在需要的地方适当地存储数据,保护数据,并确保数据始终为组织可能拥有的多个人工智能甚至分析项目做好准备。
正如我们在上面看到的,确保为每个云提供商、项目和数据类型正确设置安全设置是一项艰巨的任务。一种更简单的方法是在一个中心位置管理您的安全设置。您选择的平台应该会自动反映这些设置以及整个云基础架构的变化。
这些平台可以帮助组织节省云开支。组织不应该为了获得最佳可用价格而货比三家,了解不同的定价选项,并担心灵活的合同、支付灵活性和服务,以确保基于其特定需求的最佳交易。寻找一个平台,为您的所有云基础架构提供清晰一致的低价。这种定价结构将反映您组织的需求,并且只会随着这些需求的增加而变化。
然而,需要注意一个权衡。尽管您从服务提供商基础架构中获得的灵活性越大,但这是以失去功能为代价的。这些平台提供的产品和功能少于服务提供商本身。
当选择多云还是单云或多云 MLOps 策略时,组织应仔细权衡每种方法的优势和劣势,并考虑他们的需求可能会随着时间的推移而变化,以避免令人头疼的迁移费用,并为未来做好更好的准备。
在本文中,我们关注的是公共多云,而不是包括公共云和私有云的混合云。公司采用混合云战略的原因不同于单一的公共云。然而,混合云提出了许多与公共云相似的问题;它们通常更加复杂。
为什么并行培训可能不适合您
理解大数据
神经网络并行训练的动机、益处和注意事项指南
介绍
有几种并行训练神经网络的方法。
- 模型间并行性,也称为并行化超参数搜索
- 数据并行性
- 模型内并行性,又称模型并行性
- 流水线并行
在这篇文章中,我们将探讨两种最常见的并行方法,模型间并行和数据并行。我们将在 CIFAR10 数据集上使用一个简单的 CNN 模型来演示这些技术。我们将在运行 AWS 深度学习 AMI 和 Pytorch (1.7.1)的 4 GPU 机器上训练这个模型
并行培训的优势
并行训练最明显的优势是速度。在超参数搜索的情况下,同时评估多个配置允许我们快速缩小最有希望的选项。
通过分布式数据并行(DDP)训练,模型参数的副本被放置在每个可用的 GPU 上,并且每个副本被提供给整个数据集的不同子集。
每次批量评估后,副本的梯度将被同步和平均。基于这些同步的梯度来更新模型副本的权重。
这增加了模型使用的有效批处理大小,允许它在比单个 GPU 的内存容量更大的批处理上进行训练。随着训练数据集大小的增加,DDP 成为一种保持训练时间合理的方法。
批量的重要性
使用较大的批量会导致更快的训练,因为网络能够以更少的步骤迭代整个数据集。然而,经验证据表明,更大的批量倾向于收敛到损失面的尖锐最小值,这导致泛化能力差[ 1 ]。相比之下,批量越小,最小值越宽、越平,具有良好的泛化能力。
让我们通过对一组候选批量运行超参数搜索来测试这一点。我们将使用恒定的学习速率 0.001 在 CIFAR10 上训练我们的 CNN10 个时期。
我们将并行运行 Comet Optimizer ,并作为命令行参数输入一个 Optimizer 配置文件。
comet optimize -j 4 comet-pytorch-parallel-hpo.py optim.config
这里的j
是我们想要启动的并行进程的数量。你可以在这里找到更多关于彗星优化器的细节
optim.config
文件只是一个 JSON 对象,包含我们的参数搜索网格。
{
# We pick the Bayes algorithm:
"algorithm": "random",
# Declare your hyperparameters in the Vizier-inspired format:
"parameters": {
"batch_size": {
"type": "discrete",
"values": [8, 32, 128, 512]
},
},
# Declare what we will be optimizing, and how:
"spec": {
"metric": "val_loss",
"objective": "minimize",
},
}
左:每个批量配置的运行时间(秒),右:每个批量配置的相应测试准确度。来源:comet . ml
当查看折线图时,我们看到批量越大,训练运行时间越短。然而,较大的批量也会导致更差的训练误差和测试精度。事实上,批量越小,测试准确度越好。这是一个问题,因为最小批量的完成需要将近8 倍的时间。
完成最小批量需要将近8 倍于的时间。
提高学习速度
使用大批量的一个关键方面是调整学习速度。一般的经验法则是遵循线性缩放规则【2】。这意味着当批量增加 K 倍时,学习率也必须增加 K 倍。
让我们在超参数搜索中对此进行研究。让我们根据批量大小来线性调整我们的学习速度。我们将使用批次大小 8 作为我们的缩放常数。
左图:具有成比例学习率的不同批量的训练损失曲线,右图:具有成比例学习率的配置的测试精度。来源:comet . ml
这似乎起了作用。根据批量调整学习速度可以缩小泛化差距!让我们将这个想法与我们的分布式数据并行方法结合起来。
使用更大的有效批量
通过 DDP 训练,数据集在多个可用的 GPU 之间进行划分。
让我们使用 Pytorch 分布式数据并行模块运行一组实验。该模块处理将模型复制到每个 GPU,以及跨 GPU 进程同步梯度和更新权重。
使用 ddp 模块非常简单。将您的现有模型包装在 DDP 模块中,并将其分配给 GPU
model = Net()
model.cuda(gpu_id)
ddp_model = DDP(model, device_ids=[gpu_id])
我们将使用 DistributedSampler 对象来确保数据正确地分布在每个 GPU 进程中
# Load training data
trainset, testset = load_data()
test_abs = int(len(trainset) * 0.8)
train_subset, val_subset = random_split(
trainset, [test_abs, len(trainset) - test_abs]
)
train_sampler = torch.utils.data.distributed.DistributedSampler(
train_subset, num_replicas=world_size, rank=global_process_rank
)
trainloader = torch.utils.data.DataLoader(
train_subset,
batch_size=PER_REPLICA_BATCH_SIZE,
sampler=train_sampler,
num_workers=8,
)
valloader = torch.utils.data.DataLoader(
val_subset, batch_size=PER_REPLICA_BATCH_SIZE, shuffle=True, num_workers=8
)
最后,使用 DDP 包装的模型运行训练循环
for epoch in range(args.epochs):
train_loss = train(ddp_model, optimizer, criterion, trainloader, epoch, gpu_id)
val_loss, val_acc = evaluate(ddp_model, criterion, valloader, epoch, gpu_id)
在我们的例子中,每个 GPU 接收四分之一的数据集。当我们以这种方式运行训练时,我们的有效批量大小是 GPU 数量和每个 GPU 的批量大小的乘积。因此,当我们将每个 GPU 的批处理大小设置为 8 时,我们的有效批处理大小实际上是 32。我们可以通过将 DDP 训练运行与批处理大小为 32 的单个 GPU 训练运行进行比较来验证这一点。注意曲线看起来是多么的相似,并且跑相似的训练步数。这些曲线表明,即使我们在每个 GPU 进程中使用较小的批量,我们的模型性能仍然依赖于的有效批量。
把所有的放在一起
让我们结合我们所学的学习率调整,重新运行 DDP 培训。
左图:使用比例学习率和 DDP 训练的训练损失,右图:使用比例学习率和 DDP 训练的测试 Acc。来源: Comet.ml
看起来,即使是学习率缩放也有其局限性。当我们将批量增加到某个值时,训练得到了改善,在此之后,我们看到我们的测试精度开始下降。
警告
理论上,将训练分布在多个 GPU 上应该会加快训练模型所需的总时间。实际上,情况并非总是如此。跨多个 GPU 进程同步梯度会导致通信开销,这对于最小化是不可忽视的。
在下面的面板中,我们将批量为 32 的单个流程培训运行的运行时间与具有相同有效批量的 DDP 培训运行的运行时间进行了比较。单个流程运行需要 73 秒才能完成,而 DDP 培训运行几乎比慢八倍**,需要 443 秒才能完成。**
这可能是因为每次我们在训练代码中调用loss.backward()
时,梯度都是同步的。进程之间的持续通信导致总体运行时间增加。这是设置 DDP 培训时需要注意的一点。如果您在多机器设置中运行您的实验,请确保网络带宽足以处理发送和接收整个模型的检查点数据的每个进程。
加速这个过程的另一个方法是改变梯度的同步时间表,但是这超出了本报告的范围。
单一流程培训与分布式培训的培训损失曲线。来源: Comet.ml
结论
我们希望这份并行培训入门指南对您有所帮助。在随后的文章中,我们将讨论如何优化您的分布式培训代码,以充分利用您的计算基础设施。
Comet.ml —轻松跟踪、比较和调试您的模型!
如果你还没有试用过 Comet,它是一个很棒的工具,可以让你跟踪、比较和调试你的 ML 模型!
它可以与 Colab、Jupyter 笔记本和脚本一起使用,最重要的是它是 100%免费的!
入门 实验跟踪 今天!
参考
[1] Keskar,Nitish Shirish 等,“关于深度学习的大批量训练:泛化差距和尖锐极小值。” arXiv 预印本 arXiv:1609.04836 (2016)。
[2] Goyal,Priya 等,“精确的大型迷你批次 sgd:在 1 小时内训练 ImageNet。” arXiv 预印本 arXiv:1706.02677 (2017)。
为什么需要游戏玩家
游戏玩家(PoG)和 AlphaZero 的比较
国际象棋和扑克图片|作者图片
大家好,今天我们将比较游戏玩家 (PoG)和 AlphaZero 。PoG 是 DeepMind 开发的新 AI 智能体,是同类产品中第一个在完美和不完美信息游戏中都实现高水平性能的智能体。
在完美信息博弈中,每个参与者都知道博弈中的所有信息。对于国际象棋和围棋来说,了解游戏中的所有信息意味着玩家可以看到自己和对手的棋子。
在不完善的信息博弈中,玩家无法看到所有的信息。对于扑克,玩家看不到对手的牌,这增加了难度,因为你并不总是知道玩家是否在说实话。对于这样的游戏,人工智能很难学习,因为它没有可靠的信息来源,只能依靠自己的判断。
传统上完美信息和不完美信息游戏机器人使用不同的方法。完美信息游戏 ai 如 AlphaZero 使用蒙特卡罗树搜索 (MCTS)。然而成功的不完全信息博弈人工智能使用博弈论推理。这种方法上的差异是因为算法不适合另一种类型的游戏。AlphaZero 在众多完美信息游戏中实现了最先进的游戏性。然而,对 AlphaZero 最大的批评之一是它无法在不完美的信息游戏中表现良好,这使得 PoG 成为广义人工智能的又一次飞跃。
AlphaZero 描述
首先,我将简要介绍一下什么是 AlphaZero 以及它是如何工作的。关于 AlphaZero 的更深入的解释,请查看我的另一篇博文这里,在那里我将 AlphaZero 和变形金刚结合在一起。
AlphaZero 是一种强化学习算法,学习玩完美信息游戏。AlphaZero 之所以如此引人注目,是因为它完全通过自我游戏实现了最先进的游戏。这一特性让许多人将 AlphaZero 视为长期规划端到端学习能力的证明点。
AlphaZero 和不完美博弈
AlphaZero 在计划采取何种行动时,结合使用了神经网络(NN)和 MCTS。这种方法对于完美信息游戏非常成功,因为在给定足够计算能力的情况下,对于这种类型的游戏,MCTS 理论上与 MiniMax 搜索算法收敛。MiniMax 是一种贪婪的搜索算法,它搜索博弈树的所有可能的移动,理论上可以在给定足够计算能力的情况下“解决”所有完美信息博弈。AlphaZero 使用 MCTS 而不是极大极小,因为现代的计算限制使得极大极小对于像国际象棋和围棋这样的高复杂度游戏来说是不可行的。然而,MCTS 在不完美信息博弈中表现不佳,因为它无法保证收敛于 T2 纳什均衡。
博弈树对于完美信息博弈非常有用,因为理论上你可以知道每一个行动的反应,因为这类博弈处于纳什均衡。然而,对于不完美的游戏,这种逻辑是不成立的。为了更好地理解这个逻辑失败的原因,让我们以扑克为例。在扑克游戏中,玩家可以虚张声势,即使他们的牌不比对手好,他们也有能力获胜,这给游戏增加了很大的不确定性。由于这种额外的不确定性,除非你在游戏中有最好的牌,否则你永远无法确定自己是否会赢,这使得正确遍历游戏树变得非常困难。正因为如此,AlphaZero 不适合不完美信息博弈,因为在使用 MCTS 时结果不一致。
PoG 描述
PoG 使用神经网络和生长树反事实后悔最小化(GT-CFR)来规划要采取的行动。GT-CFR 是反事实后悔最小化 (CFR)算法的变体。GT-CFR 是一个两步算法,使用 CFR+ 来优化其策略,以最小化遗憾,随后是一个扩展阶段,在该阶段中,它扩展游戏树,类似于 MCTS。
更新策略阶段
为了更好地理解这个算法,我们先来看看策略优化阶段。CFR 算法家族使用最小化遗憾的思想作为最优策略。GT-CFR 使用 CFR+来最小化遗憾,因为它是普通 CFR 算法的前身,并且具有更快的纳什均衡收敛。CFR+算法对后悔的定义是;
“事后来看,通过遵循一些替代策略可以获得多少额外效用的衡量”【9】
也就是说,它寻找平均来说可能会产生更好结果的行动。
为了最小化遗憾,CFR+使用遗憾匹配+搜索完整的公共树。后悔匹配+是 CFR+对普通 CFR 算法的一个实质性升级。在后悔匹配+中,我们归一化累积后悔值 Q 来更新策略。通过以这种方式更新策略,我们有效地解释了不完美信息博弈中的不确定性。
后悔匹配+政策方程式|作者图片
Q 值是对遗憾匹配+的改进之一,因为它允许在向前传递期间计算累积遗憾,而不需要存储遗憾。为了确定累积遗憾,我们使用下面的等式。
累积后悔方程式|作者图片
通过查看所有其他选项,看看是否存在任何更好的举措,可以发现瞬间后悔。为了确定瞬间后悔,我们使用下面的等式。
瞬间后悔方程式|作者图片
PoG AI 使用价值和政策网络(CVPN)来预测反事实的价值和政策。在叶节点上,我们对 CVPN 进行查询,允许它充当 oracle。以这种方式使用 CVPN,使得扩展阶段成为可能,因为如果没有 CVPN,我们将无法预测之前未见过的节点的反事实价值和策略。
CVPN 方程|作者图片
CVPN 图|图片来自https://arxiv.org/pdf/2112.03178.pdf
在 CFR+算法中,线性加权策略平均通过基于迭代次数向遗憾添加自然衰减来帮助在迭代过程中平滑策略。为了帮助说明线性加权策略平均对策略更新阶段的积极影响,这里有两个图表,以便您可以比较使用策略和不使用策略的情况。
无线性加权保单平均值的保单|作者图片
采用线性加权策略平均值的策略| |作者图片
正如您在上面的图表中所看到的,在更新阶段使用线性加权策略平均值时,策略变化更加稳定。线性加权策略平均使用以下等式。
线性加权策略平均方程|作者图片
GT-CFR 政策更新阶段
树扩展阶段
既然我们已经了解了 CFR+是如何在这个算法中用来优化策略的,我们就来看看树扩展阶段。如果您熟悉 MCTS,树扩展阶段应该与您非常相似。当遍历游戏树时,使用下面的等式来确定最佳路径。
扩展节点选择方程|作者图片
pUCT 方程式|作者图片
当遍历游戏树时,当遇到一个叶子节点时,我们扩展 k 个子节点。一旦树被展开,我们的节点访问计数被更新以用于 pUCT 等式。
GT-CFR 扩展流程图|图片由作者提供
扩展游戏树的想法对 GT-CFR 来说是新的,并提供了与 MCTS 类似的好处,在那里我们可以通过用神经网络指导树搜索来玩高复杂度的游戏。
GT-CFR 扩展阶段
谢谢
现在你知道了。希望你现在能更好地理解 PoG 和 AlphaZero 之间的区别,以及为什么 PoG 是广义人工智能的又一进步。
感谢阅读。如果你喜欢这样,可以考虑订阅我的账户,以便在我最近发帖时得到通知。
参考
- https://arxiv.org/abs/2112.03178
- 【https://arxiv.org/pdf/1712.01815.pdf】T2【2】
- 【https://en.wikipedia.org/wiki/Monte_Carlo_tree_search】T4【3】
- https://en.wikipedia.org/wiki/Game_theory【4】
- https://towards data science . com/building-a-chess-engine-part 2-db 4784 e 843d 5[5]
- https://en.wikipedia.org/wiki/Minimax【6】
- https://en.wikipedia.org/wiki/Nash_equilibrium【7】
- https://poker.cs.ualberta.ca/publications/NIPS07-cfr.pdf【8】
- https://www.ijcai.org/Proceedings/15/Papers/097.pdf【9】
为什么生产机器学习会失败——以及如何修复它
通过避免这些常见的陷阱,成功部署您的 ML 模型
机器学习已经成为任何严肃的数据团队的必备工具:增强流程,生成更智能、更准确的预测,并普遍提高我们利用数据的能力。然而,在理论上讨论 ML 的应用与在生产中实际应用 ML 模型大相径庭。
巴尔摩西 、CEO 蒙地卡罗、 马努慕克吉 、工程副总裁— AI、数据和分析、8x8、 走过 共同挑战*对应解决方案 让 ML 成为你的力量倍增器*
从在谷歌地图上生成你的周末自行车路线,到帮助你在网飞发现下一个值得狂欢的节目,机器学习(ML)已经远远超出了理论上的时髦词汇,成为我们大多数人每天都在使用的强大技术。
对于现代企业来说,对 ML 的需求从未如此强烈。但是,尽管某些行业已经被人工智能带来的自动化所改变——想想金融领域的 欺诈检测 和电子商务领域的 个性化产品推荐——残酷的事实是,许多人工智能项目还没有公开就失败了。
2020 年 10 月, Gartner 报告称只有 53%的项目从原型阶段进入生产阶段——而且是在具有一定人工智能经验的组织中。对于仍在努力发展数据驱动文化的公司来说,这个数字可能要高得多,据估计的一些失败率飙升至近 90%。
谷歌、脸书和亚马逊等数据优先的科技公司正在用 ML 改变我们的日常生活,而其他许多资金雄厚、才华横溢的团队仍在努力实现他们的计划。但是为什么会这样呢?我们如何解决这个问题?
我们分享现代数据团队在大规模采用 ML 时面临的四个最大挑战,以及如何克服它们。
实际业务需求和 ML 目标不一致
当你的商业目标和 ML 目标不一致时,你所有最好的计划都注定会失败,就像你用陈旧数据训练的模型一样。图片由 Unsplash 上的 Charles Deluvio 提供。
第一个挑战是战略性的,而不是技术性的:从解决方案开始,而不是从明确定义的问题开始。
随着公司竞相将 ML 纳入他们的组织,领导者可能会雇用数据科学家和 ML 实践者来自动化或改进流程,而没有对哪些问题实际上适合 ML 解决的https://developers.google.com/machine-learning/problem-framing/good有成熟的理解。即使业务问题非常适合 ML,如果没有一个共享的成功定义,项目可能会在实验模式中被搁置数月,而利益相关者等待一个理想化的机器般的完美水平,这是永远无法达到的。
机器学习不是魔术,它不会完美地解决每个问题,本质上应该随着时间的推移继续进化。有时,一个模型仅仅达到与人类相同的结果,这是一个有价值的项目——错误和所有。
在开始任何项目之前,询问你的团队或利益相关者:我们正在试图解决什么业务问题?为什么我们相信 ML 是正确的道路?这个项目试图达到的商业价值的可测量的阈值是什么?“足够好”是什么样子的?
如果没有这些清晰的、共享的定义,许多有价值的 ML 项目将永远无法进入生产,宝贵的资源将被浪费。使用 ML 解决一个商业问题,而不仅仅是开始一个 ML 项目来检查 ML 框。
不一般化的模型训练
有了清晰定义的业务问题和目标成功度量,您的潜在陷阱变得更加技术性。在模型训练阶段,与您的训练数据或模型拟合相关的问题是未来失败的最大可能原因。
模型训练 的目标是开发一个模型,该模型可以进行归纳,或者在给定新数据时做出准确的预测,因为它了解数据点之间的关系,并且可以识别趋势。您的训练数据集应该干净、大小合适,并且能够代表模型在生产中需要处理的实时数据。没有人在生产环境中见过干净的数据。仅仅为了准备好数据,就要花费大量的时间进行清理、标记和特征工程。
代表性的训练数据也很关键:如果训练数据没有反映模型将遇到的实际数据集,那么一旦进入测试或生产阶段,模型可能就无法运行了。
训练期间可能发生的另一个问题是过度适应和适应不足。当一个模型学习太多并且产生与你的训练数据太接近的输出时,过度拟合就发生了。**
拟合不足恰恰相反-您的模型没有学到足够的知识,甚至不能对训练数据本身做出有用的预测,更不用说它在测试或生产中会遇到的新数据了。
测试和验证问题
当您测试和验证您的模型时,合并多个数据流并进行更新以提高性能可能会带来新的挑战。数据源、模型参数和 特征工程 的变化都会引入误差。
这也可能是您在模型中检测到过度拟合或欠拟合的阶段——在训练期间表现出色但在测试期间未能产生有用结果的模型可能是过度拟合的。
即使在像谷歌这样有大量人工智能工程师的公司,你的产品模型中的惊喜也会出现。
部署和服务障碍
部署 ML 项目很少是简单的,团队通常不能使用一致的工作流来做到这一点——因为 ML 项目解决了广泛的业务问题,所以有类似的广泛的方法来托管和部署它们。例如,一些项目需要定期进行批量预测,而其他项目则需要在应用程序发出使用模型进行预测的 API 请求时按需生成和交付预测。(这是为什么使模型适用于不同用例具有挑战性的部分原因,无论它对那些认为 ML 模型比狭隘的功能更有魔力的高管来说听起来多么有吸引力。)
此外,一些 ML 项目可能需要大量资源,跨职能团队需要就部署的优先级达成一致。工程师们只能生产这么多东西,正如我们已经讨论过的,ML 项目不仅仅是模型和算法:大多数项目需要基础设施、警报、维护等等来成功部署。
这就是为什么在一开始就清楚地阐明业务问题,就成功的样子达成一致,设计端到端的解决方案,并对您的 ML 项目相对于其他优先事项的价值有一个共同的理解是如此重要。没有这个战略计划,您的项目可能永远得不到最终投入生产所需的工程资源。
仅举一个例子,网飞从未将其百万美元大奖的推荐算法投入生产,因为获奖模型实现起来很复杂——而是选择了另一个更容易集成的提交。
生产中可扩展 ML 的策略
机器学习不是魔法,但它很强大——而且经常被误解。有点像这个纸简笔画。图片由 Unsplash 上的 Kobu 机构提供。
除了战略规划和人员配备,你还可以采取一些具体的步骤来帮助扩大你的 ML 生产规模。
倚入云端
如果你的团队在本地工作而不是在云中工作,是时候改变了。在云中工作是保持模型培训和部署工作流程同步的“粘合剂”。大多数供应商和开源工具都是为云开发的,一旦有了云,自动化过程就容易多了。测试、培训、验证和模型部署需要是一个可重复的过程,它不应该从本地 Python 代码进入生产环境。
利用开发运维方法
正如我们已经讨论过将 DevOps 实践应用于数据,像 设置数据 SLA和沿着可观察性支柱测量数据健康,ML 团队可以跟随 DevOps 的脚步,通过实现 持续集成(CI)和持续交付(CD) 模型,同时引入持续培训(CT) 。通过设置敏捷构建周期和工具,ML 团队可以更快地将变更交付到代码库中,并提高整体性能。
类似于 DevOps 最佳实践,ML 团队应该使用容器化来一致地在任何类型的设备上运行软件,并使工程师的工作生产化更简单。保持一致和可见的构建过程,更频繁地部署较小的更改,可以让团队更顺利地工作,并更深入地了解什么工作得好,什么不好。可见性还有助于潜在的代码“看门人”信任构建过程,并加速 ML 团队的工作流程。
投入时间建立战略 MLOps 团队和流程将有助于降低项目在生产前停滞的可能性,并使持续改进变得可行,从而为每个项目的长期成功奠定基础。
投资于可观察性和监控
最后,机器学习的首要规则是,你的输出只会和你的输入一样好。健康的数据对 ML 来说是绝对必要的。如果没有干净的数据和有效的管道,模型将无法充分发挥其潜力,并且可能无法做出准确的预测。
当您依赖 ML 来做出重要的商业决策时,您不会希望在那些输出已经交付之后才发现管道破裂或数据不准确。
这就是为什么 数据可观察性 提供了对数据健康状况的全面了解和全面监控,并且可以首先防止坏数据到达您的 ML 模型,这是非常值得投资的。
实现大规模生产
你不需要设计下一个动作激活的安全摄像头来影响你的 ML。图片由马太·亨利在 Unsplash 上提供。
机器学习不是魔法,但它很强大——而且经常被误解。
尽管如此,通过战略、流程和技术的正确组合,ML 项目可以提供竞争优势并推动每个行业的发展。
即使您没有构建下一代欺诈检测算法或虚拟个人助理,我们也希望这些最佳实践能够帮助您迈向(成功!)大规模部署 ML。
你最大的 ML 或数据痛点是什么?我们希望收到您的来信!伸出手去 巴尔摩西 或者 摩奴慕克吉 。
Lior GAVI sh,蒙特卡洛 CTO,对本文有贡献。******
为什么 Python 如此喜欢下划线
图片由 Manuel Enriquez 来自 Pixabay
使用下划线的一些技巧可以改进您的 Python 代码
很多编程语言在很多场景下使用下划线“_”,Python 也是如此。如果你曾经使用 Python 进行过面向对象的编程,你一定知道 Python 对象的构造函数是__init__()
。这可能是我们在 Python 中需要使用下划线的最常见场景。
然而,在更多的情况下,我们可以使用一个或多个下划线来玩一些把戏。这可以提高我们代码的可靠性,甚至带来一些新的特性。在本文中,我将列出下划线的一些技巧。希望他们能帮忙。
1.临时变量
图片来自 Pixabay 的 Tonda Tran
我要介绍的第一个技巧与临时变量有关。当我们不知道变量名或者不想给变量命名时,下划线可以帮助我们。
REPL 的最后结果
REPL 指的是“阅读评估印刷循环”。当我们在 Python 控制台中运行一些东西时,结果将作为变量缓存在 REPL 中。这个变量没有名字,但是我们可以用下划线得到它。
最典型的例子就是 Jupyter 笔记本。假设我们在一个单元格中运行一些东西,那么我们可以在下一个单元格中使用下划线得到结果。
但是,需要强调的是,“无”值不会被缓冲。因此,下划线的值不会被替换,如下例所示。
匿名变量
作为一个经验法则,当我们不需要命名变量时,我们也可以用下划线来命名它。通常,这只是因为我们以后不需要使用这个变量,但是它必须被放在某个地方。
for _ in range(10000):
# Do something 10000 times
pass
在上面的例子中,我们只需要一个 for 循环来运行一些代码片段 10k 次。然而,循环并不重要。因此,我们可以使用下划线作为 for 循环的索引。
同样值得一提的是,大多数 IDE 都知道这条“经验法则”,这样就不会在以后检查下划线的用法。相反,如果我们在这个 for 循环中使用一个命名变量,一些 IDE 工具可能会警告我们“定义了一个变量却没有使用它”。
占位符
下划线作为临时变量的另一个常见用法是作为占位符。当我们想从一个元组中提取值时,通常使用这种方法。请参见下面的示例。
my_tuple = (1, 2)x, _ = my_tuple
print(x)
如图所示,我们从元组中获取第一个值,并将其赋给变量x
。第二个被忽略,因为我们使用下划线作为“占位符”。
另一个您可能不知道的技巧是,我们可以使用带下划线的星号作为多个值的“占位符”。假设我们有一个包含多个值的元组,我们想从中获取第一个和最后一个值。
my_long_tuple = (1, 2, 3, 4, 5)x, *_, z = my_long_tuple
print('x =', x)
print('z =', z)
不管中间有多少个值,x, *_, z
总会得到第一个和最后一个值。
2.提高可读性
这个大概很多开发者都知道,但我还是想放在这里。这个小技巧在很大程度上提高了程序中数字的可读性。
num = 1_000_000
print(num)
我们通常用逗号来分隔一个数字中的每 3 个数字,这样我们就可以很容易地阅读这个数字。在 Python 中,我们不能使用逗号,但是我们可以使用下划线来做同样的事情。
此外,对于一些文化和习俗,不要担心,我们可以把下划线放在任何地方。也不会影响结果。
num = 100_0000
print(num)
3.解决名称冲突
图片来自 Pixabay
下划线通常也用于避免名称空间中的冲突。请注意,在解释者层面没有关于这个的定义。所以,这又是下划线的另一个“经验法则”。
例如,我们想定义一个函数来获取某些产品的“类”。如果我们按如下方式编写代码,它将引发一个错误。
def print_class(class):
print('Class:', class)
这是因为术语class
是 Python 中的保留关键字之一。具体来说,Python 认为我们在定义一类对象,但语法显然是错误的。
在这种情况下,经验法则是在变量后面加上下划线,如下所示。
def print_class(class_):
print('Class:', class_)print_class('Premium')
当然,我们不必使用“class”作为变量名,因为它只是一个变量名。然而,有时不避免保留关键字会提高代码的可读性。
4.私有/受保护的属性和功能
很不幸,此时此地的图片结束了我在 Pixabay 的旅程
下划线也可以用来保护一些我们不希望下游引用的属性和函数,或者是不必要让它们被导入或调用。
保护进口
例如,在一个.py
文件中,我们可以定义一些常量和函数。然后,这个 Python 文件的意思就是被别人作为库导入。然而,我们可能在这个文件中有一些不应该被导入的本地帮助函数。
在这种情况下,我们可以在常量或函数前加一个下划线,这样它们就不会被from ... import *
导入。
让我们创建一个文件lib.py
并将以下两个函数放入其中。
def test_func():
print("I'm a test")def _test_func():
print("I'm a _test")
然后,让我们从这个文件中导入所有内容。
from lib import *
之后,我们可以验证test_func()
是进口的,而_test_func()
不是。
但是,请注意,这是一个相当“方便”的方法,可以防止我们导入不必要的函数。它不会阻止用户显式导入它。
如果我们显式导入该函数,它将工作。
from lib import _test_func
5.保护类属性/功能
不仅仅是导入,我们还可以使用下划线来保护类中的属性和函数不被外部调用。
这可以通过在需要保护的属性或函数前面添加双下划线__
来实现。
让我们定义一个名为Person
的类,然后实例化它。
class Person():
def __init__(self, name, age):
self.name = name
self.__age = age def show(self):
print(f"My name is {self.name} and I'm {self.__age} years old.") def __show(self):
print(f"Hey {self.name}, you shouldn't call this function.")p1 = Person('Chris', 33)
所以,我们可以调用show()
函数来打印预定义的字符串。
然而,如果我们试图调用受双下划线“保护”的属性__name
和函数__show()
,就会抛出错误。
同样,这种“保护”不限于解释器级别。如果我们想在一个类中隐藏一些东西不让它被调用,这是很方便的。但是有一种方法可以显式调用。只是在他们前面加上_<class_name>
。
6.神奇的功能
嗯,每个人都知道魔法功能,但它非常重要,所以我不想跳过它。在前面的例子中使用的__init__()
函数是一种神奇的函数。除此之外,最重要的一个是类中的__repr__()
函数。它定义了当我们打印一个对象时要输出什么。如果你熟悉 Java,这几乎等同于toString()
方法。
让我们定义一个没有__repr__()
函数的类,并尝试打印对象。
class Person():
def __init__(self, name, age):
self.name = name
self.age = agep1 = Person('Chris', 33)
print(p1)
它只是告诉我们类名和内存地址,帮助不大。现在,让我们定义__repr__()
函数,再试一次。
def __repr__(self):
return f"My name is {self.name} and I'm {self.age} years old."
摘要
图片由 Franz Bachinger 提供,来自 Pixabay
在本文中,我介绍了几个与 Python 编程语言中的下划线相关的技巧。有时,它使我们能够拥有某些能力,有时它提高可读性和可靠性。此外,它为保护导入和类属性/函数提供了一些便利。
这些技巧值得了解,有时对于理解他人的代码也很重要。希望这些建议会有所帮助。
https://medium.com/@qiuyujx/membership
如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)
为什么理解 Python 中的队列和堆至关重要
队列和堆是编程中开发序列的基本构件
Melanie Pongratz 在 Unsplash 上的照片
队列是人类与生俱来的东西,因为当我们需要做一些事情并且很忙的时候,你通常不得不排队等候。在 Python 和其他编程语言中,队列和堆是构建对象顺序列表的一种方式,也是保持它们有序的一种整洁方式。对于依赖于时间或序列的程序,队列和堆是捕获这种类型的信息以流过程序所需进程的理想方式。
什么是优先级队列?
在 Python 中,优先级队列是一种特殊类型的数据结构,它包含一个项目集合,每个项目都有一个指定的优先级。优先级决定了它在队列中所属的顺序,并有助于保持项目在结构中的顺序。Python 中的术语是 pqueue。
操作优先级队列的操作
关于优先级队列的两个基本概念是关于如何将对象添加到队列中,有两种主要方法可以做到这一点,它们是:
- Stack — (LIFO)或后进先出,顾名思义,思考堆栈工作原理的一种更简单的方式。如果您在堆叠块的“队列”中将一个块堆叠在另一个块的顶部,那么当从该堆叠中移除块时,它将总是最后一个进入。
堆叠的视觉表现展示了如何通过插入和移除来构建和解构堆叠。图片作者。
- 队列— (FIFO)先进先出更符合我们人类更习惯的队列概念。基本上,当建立队列时,队列中的下一个人走到队列的后面,第一个位置的人被处理并从队列中删除。
照片由 Charles Deluvio 在 Unsplash 上拍摄
有几个不同的操作用于操纵项目在优先级队列中被捕获、移除和排序的方式。三个主要操作是 Insert、delMax/Min 和 findMax/Min。实际上,有 5 个操作,但是 del 和 find 操作的行为方式是相同的,它们分别在范围的两端执行操作。
插入 —这是一个简单的操作,它主要是在优先级队列中插入项目
delMax/Min —该操作还试图从位于范围一端的队列中删除一个项目,这取决于队列的结构(如上所示的堆栈或队列)。
findMax/Min —为了理解队列中的项目,可能有必要知道队列的 bookend 对象是什么,findMax/Min 将完成这项工作。
优先级队列的用例:
事件驱动的模拟 —如前所述,如果时间是一个您想要在一个序列中捕获的变量,那么使用一个队列来表示事物的归属是以编程方式构建它的理想方式。
数值计算— 编码的一个更“枯燥”的方面,但是研究如何最小化与舍入相关的误差可以利用优先级队列来完成。理解给定测量值的有效数字并减少由舍入误差引入的误差可以被最小化。
数据压缩— 另一个用例是尝试寻找方法对数据进行排序并将其存储在合适的分区中。搜索霍夫曼代码了解更多细节。
图搜索— 在图论操作中遍历图是利用优先级队列的理想用例,因为您可以了解图中哪些节点已经被访问过,以及访问的顺序。
操作系统——调查和理解系统的负载平衡和中断处理有助于以系统的顺序和方法确定系统的输入和输出。
额外的用例是数论、人工智能、统计学、计算机网络、垃圾邮件过滤、离散优化。
塞萨尔·卡里瓦里诺·阿拉贡在 Unsplash 上的照片
有序与无序:
有序和无序队列之间的主要概念基本上是某些操作的复杂性和速度之间的平衡。
无序数组——这些数组很容易插入,因为顺序不是问题,但另一方面,在这种类型的数组中查找 max 或 min 对象可能会耗费大量时间和资源,
有序数组——与无序数组相比,这有完全相反的问题。如果数组已经是一个结构,那么在正确的位置插入一些东西可能会占用大量资源,但是找到数组的书挡总是很容易的。
与图书馆或干净的房间相比,使用有序数组可能是一种更理想的构建和利用方式,如果东西被放置在它们需要去的地方,那么之后找到物品通常会容易得多。
完全二叉树
为了将优先级队列的概念带到下一个实现层次,您可以将它想象成一棵二叉树。二叉树是一个层次树的概念,每个父节点只有两个子分支(最多)来自它。完整树的概念是,在构建树时,通过将第一个子节点放在左边,将后续节点放在右边,对放置在树中的后续项目进行排序和构建。此外,在添加后续子层之前,需要完成每一层节点。
完全树和不完全树之间差异的表示。请注意,在下一个级别开始之前,父节点(节点#1)下没有两个子节点。作者图片
堆如树木
堆是一种特定类型的数据结构,它的根是由优先级队列形成的。正如 Wikipedia 所言,堆是一种称为优先级队列的抽象数据类型的最高效实现,事实上,优先级队列通常被称为“堆”。如你所见,优先级队列和堆这两个词通常是可以互换的,但是它们之间有明显的区别。在堆内,总是将最大(或最小)优先级的元素(取决于实现)存储为根节点,并从那里构建树。例如,如果父节点总是比子节点大,那么这被称为最大堆,反之,它们被称为最小堆。
基本堆操作:
有一些基本的堆操作与上面提到的优先级队列非常相似。第一个是删除堆的根,这可能是出于多种原因。维护操作(通常称为维护操作)是下沉或游动元素的插入命令。如果元素具有较大的值,并且需要提升一个级别,则它们可以在优先级队列中向上移动,相反,如果与同一级别中的其他项目相比,它们具有较低的优先级,则项目被沉入。最后,可以再次 delMax/Min 来从树中删除项目,然后维护树以保持其完整性。
将二叉树转化为数组:
以编程方式存储树,如数组,允许计算机将图形表示转换为自己更容易操作的表示。下表基本解释了如何根据树的工作原理构建数组,以及如何根据相同的逻辑进行扩展。
CBT 中节点的位置及其数组表示的示例。图片作者。
包裹
在本文中,我们研究了如何从概念上以编程方式捕获优先级队列和堆,以及如何实现它们的一些其他用例。对这些核心概念的深刻理解可以通过一种系统的、更加优化的方法来构建现实世界问题的模型和模拟。
一如既往地评论,回复,和/或让我知道你想阅读的其他话题。
为什么在深度学习中使用校正线性单元(ReLU ),以及在 TensorFlow 中使用它的最佳实践
入门
Keras 和 TensorFlow 2 的 ReLU 实用介绍
为什么 ReLU 在深度学习(图片由作者使用【canva.com】T2)
激活功能是深度学习的核心。它们决定了模型的输出、精度和计算效率。在某些情况下,激活函数对模型的收敛能力和收敛速度有很大的影响。
在本文中,您将了解为什么在深度学习中使用 ReLU,以及在 Keras 和 TensorFlow 2 中使用它的最佳实践。
- Sigmoid 和 Tanh 激活函数的问题
- 什么是整流线性单位(ReLU)
- 使用 ReLU 训练深度神经网络
- 将 ReLU 用于 He 初始化的最佳实践
- 与具有 Sigmoid 和 Tanh 的模型相比
- ReLU 的局限性
源代码请查看笔记本。更多教程可以从 Github repo 中找到。
1.Sigmoid 和 Tanh 激活函数的问题
历史上,最广泛使用的两种非线性激活是 Sigmoid 和双曲线正切 ( Tanh )激活函数。
Sigmoid 和 Tanh 激活函数的绘图(图片由作者提供)
Sigmoid 激活函数(也称为逻辑函数),传统上是神经网络非常流行的激活函数。该函数的输入被转换为 0 到 1 之间的值。在很长一段时间里,直到 20 世纪 90 年代初,这是神经网络上使用的默认激活。
双曲正切,也称为双曲正切,是一个形状相似的非线性激活函数,输出值范围从-1.0 到 1.0(而不是 Sigmoid 函数的 0 到 1)。在 20 世纪 90 年代后期和 21 世纪初, Tanh 函数比 Sigmoid 激活函数更受欢迎,因为使用它的模型更容易训练,并且通常具有更好的预测性能。
消失梯度问题
函数及其导数的绘图(图片由作者提供)
Sigmoid 和 Tanh 函数的一个普遍问题是渐变消失。查看函数图,可以看到当输入变小时或变大时,s 形函数在 0 或 1 处饱和, Tanh 函数在 -1 和 1 处饱和,导数非常接近 0。因此,它几乎没有梯度通过网络传播回来,所以几乎没有什么留给低层[2]。该问题阻碍了网络模型有效地学习,尤其是在深度网络中,
计算开销大的问题
Sigmoid 和 Tanh 函数的另一个问题是它们有一个指数运算,这在计算上是很昂贵的。在我们的例子中,使用 ReLU 训练的模型在收敛速度方面获得了 25%的改进(与使用 Sigmoid 和 Tanh 的模型相比,请查看部分的结果)。
2.什么是整流线性单位(ReLU)?
整流线性单元(ReLU) 是深度学习中最常用的激活函数。如果输入是负的,函数返回 0,但是对于任何正的输入,它返回该值。该函数定义为:
函数及其导数的绘图:
ReLU 及其导数的图
我们可以看到:
- 从图形上看,ReLU 函数由两个线性部分组成,以解决非线性问题。如果斜率不是常数,函数就是非线性的。因此,ReLU 函数在 0 附近是非线性的,但斜率总是为 0(负输入)或 1(正输入)。
- ReLU 函数是连续的,但是它是而不是 可微的,因为它的导数对于任何负输入都是 0。
- ReLU 的输出没有最大值(它是未饱和,这有助于梯度下降
- 该函数计算速度非常快(与 Sigmoid 和 Tanh 相比)
令人惊讶的是,这样一个简单的函数在深度神经网络中工作得非常好。
3.使用 ReLU 构建深度神经网络
出于演示目的,我们将构建一个图像分类器来处理时尚 MNIST,这是一个具有 10 个类的 70,000 个 28×28 像素的灰度图像的数据集。
使用 Keras 加载数据集
Keras 提供了一些实用函数来获取和加载公共数据集,包括时尚 MNIST。让我们装载时尚 MNIST
fashion_mnist = keras.datasets.fashion_mnist
**(X_train_full, y_train_full), (X_test, y_test) = fashion_mnist.load_data()**
数据集已经分为训练集和测试集。以下是定型集的形状和数据类型:
>>> X_train_full.shape
**(60000, 28, 28)**
>>> X_train_full.dtype
**dtype('uint8')**
我们将使用梯度下降来训练神经网络,我们必须将输入特征缩小到 0-1 范围。
创建一个深度网络
现在让我们建立一个深度神经网络!用 Keras 和 TensorFlow 2.0 创建机器学习模型有 3 种方法。由于我们正在构建一个简单的全连接神经网络,为了简单起见,让我们使用最简单的方法:带有Sequential()
的顺序模型。让我们为时尚 MNIST 创建一个具有 50 个隐藏层的深度神经网络:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flattendef **create_model**(activation):
model = keras.models.Sequential()
model.add(Flatten(input_shape=[28, 28]))
**model.add(Dense(300, activation=activation))**
**for layer in range(49):
model.add(Dense(100, activation=activation))**
model.add(Dense(10, activation="softmax"))
model.compile(
optimizer='sgd',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
我们的型号有以下规格:
- 第一层(也称为输入层)有
input_shape
来设置匹配训练数据的输入大小(28, 28)
。输入层是一个Flatten
层,它的作用只是将每个输入图像转换成一个 1D 数组。 - 然后是 50 个
Dense
层,一个 300 个单位,另一个 49 个 100 个单位。 - 输出
Dense
层有10
单元和softmax
激活功能。
让我们用 ReLU 创建一个模型:
model_relu = create_model(**activation = 'relu'**)
若要使模型符合训练数据:
history_relu = **model_relu.fit**(
X_train,
y_train,
epochs=10,
validation_data=(X_valid, y_valid),
)
如果一切顺利,我们应该得到如下输出。
Train on 55000 samples, validate on 5000 samples
Epoch 1/10
55000/55000 [==============================] - 41s 751us/sample - loss: 2.3027 - **accuracy: 0.0991** - val_loss: 2.3028 - **val_accuracy: 0.0914**
Epoch 2/10
55000/55000 [==============================] - 42s 771us/sample - loss: 2.3027 - **accuracy: 0.0979** - val_loss: 2.3029 - **val_accuracy: 0.0914**
......
......
Epoch 10/10
55000/55000 [==============================] - 39s 715us/sample - loss: 2.3027 - **accuracy: 0.0993** - val_loss: 2.3028 - **val_accuracy: 0.0914**
在这种情况下,我们可以看到训练集和验证集的性能都很差,达到了大约 10%的准确率。这表明所配置的模型不能学习问题,也不能归纳出解决方案。
在训练期间,训练集和验证集上的模型准确度的线图讲述了类似的故事。
准确度图(图片由作者提供)
ReLU 不是深度学习中默认的激活函数吗?还有什么导致了这个问题?
4.降低学习率和使用 He 初始化的最佳实践
训练深度神经网络的超参数之一是权重初始化器。一般来说,有 3 种常见的初始化器:
- 随机初始化
- Glorot (又名 Xavier )初始化
- 何初始化
如果你稍微搜索一下,你可能还会发现,如果激活函数是一个 Tanh ,那么应该使用 Glorot (Xavier)初始化,如果激活函数是一个 ReLU ,那么建议使用 He 初始化。默认情况下,Keras 使用 Glorot 初始化,这是以前模型的问题。
此外,在以前的模型中,学习率太高,因为我们已经看到训练和验证集的精度在训练期间都达到了 10%左右。让我们使用一个较小的学习率。
为了用 He 初始化来构建层,我们可以简单地将参数kernel_initializer
设置为'he_normal'
。要使用自定义学习率,我们可以将参数optimizer
设置为keras.optimizers.SGD(lr=1e-3)
。
def **create_model**(activation, **k_init**):
model = keras.models.Sequential()
model.add(Flatten(input_shape=[28, 28]))
model.add(Dense(300, activation=activation, **kernel_initializer=k_init**))
for layer in range(49):
model.add(Dense(100, activation=activation, **kernel_initializer=k_init**))
model.add(Dense(10, activation="softmax"))
model.compile(
optimizer=**keras.optimizers.SGD(lr=1e-3)**,
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model**model_with_he** = create_model(
**activation = 'relu',**
**k_init='he_normal'**
)
现在,让我们再次将模型拟合到训练数据:
history_relu_he = **model_with_he.fit**(
X_train,
y_train,
epochs=10,
validation_data=(X_valid, y_valid),
)
这一次,您应该会获得更好的输出:
Train on 55000 samples, validate on 5000 samples
Epoch 1/10
55000/55000 [==============================] - 38s 687us/sample - loss: 1.3974 - **accuracy: 0.4666** - val_loss: 1.3329 - **val_accuracy: 0.5898**
Epoch 2/10
55000/55000 [==============================] - 38s 693us/sample - loss: 0.7728 - **accuracy: 0.7079** - val_loss: 0.7561 - **val_accuracy: 0.7154**
......
......
Epoch 10/10
55000/55000 [==============================] - 38s 687us/sample - loss: 0.4063 - **accuracy: 0.8545** - val_loss: 0.4198 - **val_accuracy: 0.8552**
通过绘制模型精度图,我们可以看到初始化后的模型比我们之前看到的有了巨大的改进。
准确度图(图片由作者提供)
5.与具有 Sigmoid 和 Tanh 的模型相比
现在,让我们建立两个模型,一个用 Sigmoid,另一个用 Tanh,用训练数据拟合它们。
**model_sigmoid** = create_model(**activation = 'sigmoid'**)**model_tanh** = create_model(**activation = 'tanh'**)
之后,让我们比较一下我们讨论过的所有模型的准确性:
- 在这种情况下,用 ReLU 和 he 初始化训练的模型性能最好,其次是用 Tanh 训练的模型。
- 我们可以看到,具有 ReLU 和 Sigmoid 的模型在训练集和验证集上都很差,达到了大约 10%的准确性。这表明配置的两个模型不能了解问题,也不能归纳出解决方案。
- 此外,我们发现使用 ReLU 训练的模型的平均执行时间约为每个时段 33 秒**,而使用 Sigmoid 或 Tanh 训练的模型的平均执行时间为每个时段 40 秒。在收敛速度方面提高了 25%。(请从笔记本查看日志详情)**
比较模型(图片由作者提供)
用 ReLU 和 he 训练的模型的日志(图片由作者提供)
用 Tanh 训练的模型的日志(图片由作者提供)
6.ReLU 的局限性
ReLU 在大多数应用程序中运行良好,但并不完美。它遇到了一个被称为将死的问题。
在训练过程中,一些神经元实际上已经死亡,这意味着它们不再输出除 0 以外的任何信号。在某些情况下,你可能会发现你的网络中有一半的神经元已经死亡,尤其是当你使用大的学习速率时。当神经元的权重被调整为训练集中所有实例的输入加权和都为负值时,神经元就会死亡。当这种情况发生时,它只是保持输出 0,梯度下降不再影响它,因为当 ReLU 函数的输入为负时,它的梯度为 0。
动手机器学习[1],第 329 页
为了解决这个问题,你可能想使用 ReLU 函数的一个变体,比如 Leaky ReLU 、Parametric Leaky ReLU(PReLU)、指数线性单元 ( ELU ),或者比例指数线性单元 ( SELU )。请查看以下文章中对它们的介绍:
</7-popular-activation-functions-you-should-know-in-deep-learning-and-how-to-use-them-with-keras-and-27b4d838dfe6>
结论
在本文中,我们讨论了在深度学习中使用 ReLU 激活函数的原因,以及如何在 Keras 和 TensorFlow 中使用它。
我希望这篇文章能帮助你节省建立和调整你自己的深度学习模型的时间。我建议你查看 Keras 文档中的激活功能,并了解你可以做的其他事情。
感谢阅读。请查看笔记本获取源代码,如果您对机器学习的实用方面感兴趣,请继续关注。
您可能对我的其他 TensorFlow 文章感兴趣:
- 深度学习中你应该知道的 7 个热门激活函数
- 用 Keras 和 TensorFlow 2 构建自定义回调
- tensor flow 2 中 Keras 回调实用介绍
- 实践中的学习率计划
- 谷歌机器学习实践的 7 个步骤:结构化数据的 TensorFlow 示例
- 用 Keras 和 TensorFlow 2.0 创建机器学习模型的 3 种方法
- 批量规范化实践:以 Keras 和 TensorFlow 2.0 为例
- 实践中的提前停止:以 Keras 和 TensorFlow 为例
更多可以从我的 Github 中找到
参考
- [1]使用 Scikit-Learn 和 TensorFlow 进行机器实践学习:构建智能系统的概念、工具和技术
为什么可靠的元数据变得如此重要?
需要全面考虑数据操作中的元数据
企业内部并不缺乏数据,但是使用数据来解决业务问题是当今的一个主要挑战。在构建元数据管理框架方面有一个日益增长的焦点:网飞的 Metacat ,优步的 Databook ,Airbnb 的 Dataportal ,LinkedIn 的 Datahub ,Lyft 的 Amundsen ,WeWork 的 Marquez ,Spotify 的 Lexikon ,Apache 的
为什么元数据变得重要?
在大数据时代之前,数据在添加到中央仓库之前是经过筛选的,包括模式、谱系、所有者、业务分类等在内的元数据细节首先被编目。这被称为写模式。
作者图片
如今,处理数据湖的方法是首先聚合数据,然后推断消费时的数据细节。这被称为读取模式。因此,没有可供数据用户使用的有组织的元数据目录。
作者图片
复杂性的另一个方面是给定数据集的元数据的孤岛性质。例如,考虑驻留在 MySQL 事务数据库上的销售数据集。为了在湖中获取这些数据,用 Spark 编写了一个 ETL 作业,并安排在 Airflow 上。张量流 ML 模型使用转换后的数据。
数据管道中的每个框架都有自己的端到端元数据的局部视图。考虑到数据持久化、调度、查询处理、服务数据库、ML 框架等等技术的多样性,缺乏端到端元数据的单一规范化表示使得数据用户的消费更加困难。
元数据的作用
元数据的作用是帮助理解数据。理解数据集有几个方面:
- 数据在逻辑上代表了什么?属性的含义是什么?它是真理的来源,还是从另一个数据集推导出来的?
- 数据的模式是什么?谁管理它?是怎么改造的?
- 最后一次更新是什么时候?数据是分层的吗?以前的版本在哪里?我能相信这些数据吗?数据质量有多可靠?
- 谁和/或哪个团队是所有者?哪些是普通用户?
- 使用什么查询引擎来访问数据?数据集版本化了吗?
- 数据在哪里?复制到哪里,格式是什么?
- 数据在物理上是如何表示的,能否被访问?
- 是否存在具有共同相似或相同内容的相似数据集,无论是整体还是单个列?
即使数据集最终确定用于构建 ML 模型,仍有个操作用例需要理解元数据:
- 有许多查询引擎可用于分析数据集。单个数据集可以由多个查询引擎交替使用,例如 Pig、Spark、Presto、Hive 等。例如,从 Hive 读取数据的 Pig 脚本需要读取 Pig 类型中带有 Hive 列类型的表。类似地,处理可能需要跨数据存储移动数据。在此过程中,目标数据存储中的表使用目标表数据类型。为了能够使用多种查询处理框架,需要将规范的数据类型映射到各自的数据存储和查询引擎类型。
- 部署模型或仪表板时,需要主动监控相关的数据集问题,因为它们会影响洞察力的正确性和可用性。与数据集运行状况相关的元数据用于对数据集架构的任何更改或其他团队已经发现的任何错误进行影响分析。这些信息有助于快速调试数据管道中的中断,针对延迟的数据可用性、数据质量问题以及其他部署后的操作问题发出违反 SLA 的警报。
元数据的三大支柱
数据集的元数据细节可以分为三类:技术、操作和团队元数据/部落知识。
作者图片
技术元数据 由数据集的逻辑和物理元数据细节组成。物理元数据涵盖与物理布局和持久性相关的细节,例如创建和修改时间戳、物理位置和格式、存储层以及保留细节。逻辑元数据包括数据集架构、数据源细节、生成数据集的过程以及数据集的所有者和用户。技术元数据通常是通过爬行单个数据源来提取的,而不必跨多个数据源进行关联。
操作元数据由两个关键桶组成:沿袭和数据分析统计。沿袭包括追溯数据集是如何生成的以及它对其他数据集的依赖性。对于给定的数据集,沿袭包括所有依赖的输入表、派生表以及输出模型和仪表板。它包括实现转换逻辑以获得最终输出的作业。例如,如果作业 J 读取数据集 D1 并产生数据集 D2 ,那么 D1 的沿袭元数据包含 D2 作为其下游数据集之一,反之亦然。数据分析统计包括货架可用性和质量统计。它捕获数据集的列级和集合级特征。它还包括捕获完成时间、处理的数据以及与管道相关的错误的执行统计信息。
团队元数据:当数据科学家为他们的项目使用不同的数据集时,他们会发现关于属性含义、业务词汇、数据质量等等的更多细节。这些知识被称为部落知识。目标是通过丰富数据集的元数据细节,在数据用户之间积极地共享团队知识。
收集技术元数据的挑战
- *格式的不同:*每个数据平台存储元数据的方式不同。例如,Hadoop 分布式文件系统(HDFS)元数据以文件和目录的形式存储,而 Kafka 元数据以主题的形式存储。创建一个适用于所有平台的单一规范化元数据模型并不容易。典型的策略是应用最小公分母,这将导致抽象泄漏。数据集以多种不同的数据格式和存储方式存在。提取元数据需要不同的驱动程序来连接和提取不同的系统。
- *模式推断:*需要不自描述的数据集来推断模式。数据集的架构难以提取;半结构化数据集很难推断结构。没有通用的方法来支持对数据源的访问并生成 DDL。
- *变化跟踪:*元数据是不断变化的。鉴于高流失率和不断增长的数据集数量,保持元数据更新是一项挑战。
收集运营元数据的挑战
操作元数据不是通过连接到数据源生成的,而是通过将跨多个系统的元数据状态拼接在一起生成的。例如,在网飞,数据仓库由存储在亚马逊 S3(通过 Hive)、Druid、Elasticsearch、Redshift、Snowflake 和 MySQL 中的大量数据集组成。查询引擎,即 Spark、Presto、Pig 和 Hive,用于消费、处理和生成数据集。
给定多种不同类型的数据库、调度器、查询引擎和商业智能(BI)工具,理解跨不同处理框架、数据平台和调度系统的整体数据流和谱系是一项挑战。鉴于处理框架的多样性,挑战在于将细节缝合在一起。从代码中推断血统并不简单,尤其是对于 UDF、外部参数等等。
复杂性的另一个方面是获得完整的血统。日志中数据访问事件的数量可能非常多,传递闭包的大小也可能非常大。通常,通过仅处理来自日志的数据访问事件的样本,以及通过仅在几跳内具体化下游和上游关系,与计算真正的传递闭包相反,在沿袭关联的完整性和效率之间存在折衷。
收集团队元数据的挑战
团队知识是元数据的一个重要方面。随着数据科学团队的成长,保留这些细节以供他人利用非常重要。有四个类别:
- 注释、文档和属性描述形式的用户定义的元数据。这些信息是通过社区参与和协作创建的,通过鼓励对话和对所有权的自豪感,可以创建一个自我维护的文档库。
- 业务分类法或词汇表,用于在业务直观的层次结构中关联和组织数据对象和指标。此外,还有与数据集相关联的业务规则,如测试帐户、战略帐户等。
- 数据集在合规性、个人身份信息(PII)数据字段、数据加密要求等方面的状态。
- ML——以最流行的表格、查询等形式扩充的元数据。,并检查源代码和提取任何附加的注释。这些注释通常是高质量的,它们的词法分析可以提供捕捉模式语义的简短短语。
团队知识元数据面临三大挑战:
- 很难让数据用户简单直观地分享他们的团队知识。
- 元数据是自由格式的,但必须经过验证以确保正确性。
- 信息的质量很难核实,尤其是如果它是矛盾的。
构建元数据服务
元数据服务是数据湖/数据网格/数据湖库的关键构建块,并且通常是后特设的,即,它在数据集已经由各种管道创建或更新之后收集元数据,而不干扰数据集所有者或用户。
构建元数据服务并使其为数据用户提供自助服务涉及实现三种模式(如下图所示),定义为马斯洛需求层次:
- *特定于源的连接器模式:*简化了到不同数据源的连接和提取与数据相关的元数据信息。
- *沿袭相关模式:*自动提取与源表和目标表相关的转换的沿袭。
- *团队知识模式:*简化了数据用户之间的业务上下文聚合和知识共享。
作者图片
关于这个话题的更多讨论,请随意参考我的 O’Reilly 的书 《自助式数据路线图 。
为什么机器学习中鲁棒性不足以保证安全性和安全性
人工智能校准和安全
多个社区(机器学习、形式化方法、编程语言、安全、软件工程)的研究人员已经接受了对模型健壮性的研究,通常被称为安全性或安全性验证。他们朝着更好、更可扩展或更精确的技术不断取得令人印象深刻的进展,以评估鲁棒性和证明定理,但我在该领域阅读的许多论文基本上从未谈到如何利用这一点实际上使系统更安全。我认为这是街灯效应的一个例子:我们专注于鲁棒性验证的研究,因为它有明确定义的评估论文的措施,而实际的安全和安保问题要困难得多,需要考虑整个系统,而不仅仅是模型的属性。当考虑生产机器学习系统的测试、安全和保障时,我们需要超越狭隘的健壮性指标。
从对立的例子到稳健
我们可能都见过这样的例子,机器学习模型很容易被愚弄,通过向人类可能察觉不到的输入添加轻微的噪音来做出错误的预测,例如当添加一些人类几乎看不见的轻微噪音时,这只熊猫(非常自信地)识别出它是一只长臂猿:
来自 OpenAI 的反例
简而言之,问题出现了,因为我们学习和使用模型,却不了解它们内部是如何工作的,也不知道它们是否真正学到了反映人类认知的概念。这些模型一般都能正常工作(正如我们在模型评估过程中的准确性度量所表明的),但是我们通常真的不知道为什么以及如何工作——也许只要它们大部分都能正常工作,我们就不在乎。然而,由于我们不知道也无法具体说明这些模型是如何工作的,我们总是可以找到错误预测的例子,其中模型根本不会产生预期的结果。更糟糕的是,通过适当的搜索,通常有可能发现特定输入的微小变化,从而改变模型的预测。这就是所谓的对立的例子,有大量的研究是关于如何找到它们,有没有访问模型的内部。
虽然熊猫和长臂猿的例子看起来很有趣,但很容易将对立的例子重新定义为安全问题。例如,研究人员已经表明,贴在停车标志上的小贴纸可以欺骗视觉系统,将该标志识别为“限速 45”标志,这意味着这可能会导致自动驾驶汽车采取错误和危险的行动:
来自 CVPR 2018 论文的物理对抗示例
除了通过操纵输入的故意攻击之外,输入的自然变化也可能导致具有安全后果的错误预测。最常见的例子是自动驾驶汽车在雾天行驶,或者相机稍微倾斜或模糊,都会导致输入的小修改。例如,研究人员已经展示了图像的简单变换(反映现实世界中可能存在的问题)如何导致对汽车转向角度的错误预测:
来自 DeepTest ICSE 2018 年论文的可能输入转换示例,反映了自动驾驶系统在现实世界中的潜在条件,导致对转向角度的错误预测
在这种情况下, robustness 是指模型的预测对输入的微小变化是稳定的,希望是因为它的预测是基于真实任务的可靠抽象,反映了人类如何执行任务。也就是说,小的看不见的噪声不应该将预测从熊猫翻转到长臂猿,图像的小添加不应该阻止模型识别停止标志,天气条件或轻微倾斜相机不应该影响自动驾驶汽车的转向角度。
来自 Goodfellow 等人(2018)。使机器学习对敌对输入具有鲁棒性。ACM 的通信、 61 (7)、56–66。
*边注:*我喜欢 Goodfellow 等人对对抗性例子的可视化解释,即实际决策边界(基础事实/规范)和模型学习到的决策边界之间的不匹配。不幸的是,我们使用机器学习正是因为我们没有明确的规范,不知道实际的决策边界(参见我在机器学习是需求工程中对规范的讨论)。因此,这种解释是一种很好的概念性观点,但在我们关心预测是否正确的实际环境中没有太大帮助。稳健性只与我们是否接近模型的决策边界的问题有关,而不知道任何关于实际决策边界的事情。
定义稳健性
鲁棒性是一个吸引人的研究属性,因为它很容易定义为两个输入之间关系的不变量(技术上称为变形关系),而不必依赖于规范和实际正确预测的基础事实。
所有的局部鲁棒性属性或多或少遵循这种形式:给定一个输入 x 和一个感兴趣的模型 f ,我们希望模型的预测对于在 x 的邻域中的所有输入x’保持相同,其中邻域由某个距离函数 δ 和某个最大距离δ定义:
∀ x’ 。 δ ( x,x ')≤δf(x)=f(x ')
根据问题的不同,定义距离的方式可能会有很大不同。典型的例子允许对所有输入特征(例如,所有像素)的低噪声量,对少数输入特征的任意改变(例如,改变任意三个像素),或更复杂的变换(例如,倾斜图片或添加“雾”)。无论可能的变换或相应的距离函数和最大距离如何,我们总是对原始输入周围的一些邻域进行推理。
注意,这个定义不需要任何关于对 f ( x )或f(x’)的正确预测是什么的信息,我们简单地推理预测在邻域内应该保持一致(无论正确与否)的事实。
稳健性或者被建立为二元属性,即模型的输入被验证为稳健或不稳健(通常是保守的过度逼近,但也提出了具有置信水平的概率判断),或者被建立为某种形式的相对度量,例如到最近的对立实例的距离或邻域中稳健输入的百分比。
研究人员现在开发了许多不同的搜索和验证策略,以评估深度神经网络的这种鲁棒性。这可以通过在邻域内搜索对立的例子,通过简单地采样和测试邻域中的大量数据点,或者通过正式证明邻域中没有点可以改变预测结果的不同形式的正式验证来完成。
请注意,鲁棒性研究基本上只关注深度神经网络,因为这是难以扩展验证技术的地方。相比之下,我不知道有关于决策树或线性模型的鲁棒性论文,鲁棒性评估似乎很容易实现,并且对于许多这样的模型来说也很容易扩展——我怀疑这就是为什么我没有看到这样的论文。
除了局部稳健性,一些研究人员还讨论了模型的全局稳健性,通常是所有可能输入的某种形式的平均稳健性。例如,可以测量可以验证的输入鲁棒性的百分比,或者从每个输入到最近的对立示例的平均距离。
*边注:*Borg 等人的研究:健壮性是一个从业者经常使用的术语,但通常只是模糊地指模型预测的正确性或可信度,而不是研究文献中研究和这里讨论的健壮性的正式概念。
鲁棒性有用吗?
我读过几十篇分析机器学习模型鲁棒性的论文,其中大多数都以安全和安保问题为动机进行分析——然而这些论文中没有一篇讨论或评估鲁棒性在实际设置中如何真正使用。
首先,鲁棒性很难解读。对所有输入完全稳健的唯一模型是对所有输出返回相同预测的平凡模型。对于所有其他模型,有一个决策边界,一些输入将接近模型的决策边界,因此不稳定:决策边界附近的输入邻域的一些部分将位于决策边界的每一侧。
没有一个模型是完全鲁棒的:黑线显示了 + 和 - 预测之间的决策边界。一些输入接近决策边界,它们的邻域(圆)延伸超过决策边界。
用例 1:在推理时评估健壮性
最合理的使用场景似乎是在推理时间评估鲁棒性,也就是说,检查系统在运行期间做出的给定预测是否鲁棒。例如,当标记图像时,我们可以只标记那些我们有证据或信心该标记对微小扰动是鲁棒的图像(独立于模型可能已经提供的置信度分数),因此决定不放弃标记上面图像中的熊猫。类似地,我们可以识别停车标志没有被强有力地识别为停车标志,因此不相信它是自动驾驶汽车做出决策的任何标志。
这看起来很有吸引力,鲁棒性可能是一个强大的工具,但要将其用于系统的安全,工程师需要解决多个额外的问题:
- **成本高昂的分析:**深度神经网络的鲁棒性分析是非常昂贵的。即使技术变得更好,它们目前只适用于小型和中型的神经网络(有人知道手写数字识别吗?)由于形式分析、SMT 求解或所需大量样本的成本,他们通常需要分钟来分析单个输入的鲁棒性。我们当然可以希望研究进展继续降低成本,但我很难想象任何人会在推理时间很快使用健壮性评估;不适用于像在脸书标记照片这样的大容量系统,当然也不适用于自动驾驶汽车这样的实时应用。
- **定义最大距离:**为邻域的大小和形状定义合适的距离函数和阈值是一个不小的工程问题。邻域越大,分类为不稳定的预测就越多。如果邻域太小,攻击和意外的错误分类就更容易逃脱。此外,在实践中,由于事故或攻击,什么样的扰动是可能发生的,以及如何定义正确的邻域?我们想要防范的最糟糕的情况是什么?确定正确的距离函数和最大距离阈值是不小的工程挑战。
- 稳健≦**安全:**如果我们在推理时分析稳健性,并且我们已经找到了一个合理的最大距离,那么我们如何处理被确定为不稳健的模型预测呢?我们可以简单地决定不标记图像,但我们不能停止驾驶自动驾驶汽车。此外,我们是否假设一个预测将是正确的,仅仅因为它是稳健的?我们显然需要考虑模型之外的安全机制,仍然预期模型可能做出错误的预测,或者只是更经常地表明它不确定。
请注意,成本论证可能不适用于更简单的 ML 模型,如决策树,尽管我也没有看到任何人讨论在推理时使用健壮性。我真的很有兴趣看到试图设计安全系统的项目,并讨论他们如何应对这些挑战。
用例 2:全球模型评估
可以评估模型对于任意输入的平均稳健性,以某种全局稳健性来衡量。除了预测准确性(ROC、召回/精度、lift、MAPE,等等),我们可以将此视为模型质量的额外度量,其中稳健性和准确性度量非常不同的质量。请注意,评估可以完全离线完成;成本可能很高,但这种策略不会降低生产中模型推理的速度。
平均来说更健壮的模型可能是优选的,因为它可以被假定为学习更多的实际概念,被限制到更少的更简单的决策边界,或者可以较少地受噪声或攻击的影响。
现在的挑战来自如何衡量和有意义地解释全球稳健性。我们真的同等地关心所有的输入吗,或者健壮性应该集中在更常见的输入上吗?例如,许多方法被用来产生不稳定的合成“测试”输入,但是我们真的关心不像任何真实世界输入的随机输入吗?与准确性度量类似,什么级别的稳健性被认为是好的?应该使用什么样的邻域大小?我们如何在准确性和健壮性之间进行权衡?总的来说,全局模型健壮性很容易定义为一个度量,但是如何利用这个度量还不清楚。
最后,假设我们已经建立了较高的平均稳健性,这如何帮助我们做出任何安全声明?我们希望模型犯更少的错误或者更难被攻击,但是我们不知道任何关于推理时的特定预测。在实际环境中,攻击者很可能能够找到许多实际输入的对立例子。
用例 3:调试模型
我们可以评估一组实际输入的健壮性,而不是评估全局的健壮性(用例 2)。例如,我们可以评估验证数据集(希望代表生产中的实际输入)甚至训练集中的每个输入的健壮性。我们还可以分析生产系统中接收到的输入样本的健壮性,比如说,随机输入或通过系统遥测标记为有问题的输入(例如,用户报告预测不正确)。
了解对样本输入的某些预测是否稳健可能有助于我们进行调试。我们可能会识别出许多预测不可靠的输入区域,要么是因为它们确实接近真实的决策边界,要么更有可能是因为模型不太擅长理解这些输入。我们可能会发现危险的情况,例如我们的模型无法处理雾——希望在测试期间发现,而不是在生产中。
如果我们理解了模型的问题,我们就可以尝试改进模型。最常见的策略似乎是数据扩充,即将来自训练输入邻域的输入添加到训练数据中。对模型架构或特征工程的改变也可能有助于推动模型学习更多相关的概念。许多论文探讨了不同的方法。
总的来说,这似乎是一个很有前途的调试、强化和改进模型的策略。一个关键的挑战是哪些输入应该用于健壮性分析的问题(导致关于决定一个好的测试集的难题),以及,如上所述,如何定义要考虑的最大距离。同样类似于用例 2,我们对模型在生产中的行为没有任何健壮性保证。这些都不能提高系统本身的安全性。
超越模型:安全是系统属性
安全是系统属性,而不是软件或机器学习模型的属性。正如安全研究员南希·莱韦森(麻省理工学院)在她的ICSE 20 日主题演讲中反复提到的:
“软件不是不安全的。它会造成危险,但不会爆炸、着火、涉及有毒物质等。如果它不是关于危险,它就不是关于安全。[……]软件不是不安全的;它产生的控制信号可以是。[……]
不可能只看软件就确定安全性[……]几乎所有与软件相关的事故都是由不安全的要求造成的,而不是软件设计/实施错误。”
安全就是构建安全的系统,通常使用不可靠的组件,包括软件和硬件组件。它是关于确保系统整体是安全的,即使一个组件出现故障(例如,硬件故障,模型做出错误的预测)或多个组件之间出现意外的交互。
鉴于我们无法指定机器学习模型的预期行为,也无法验证它的功能正确性,安全问题必须关注系统如何根据通常不可靠的机器学习模型的输出与环境进行交互。我们必须考虑模型之外的安全措施,例如智能烤面包机中的热保险丝或最大烘烤时间,以确保烤面包机不会着火,无论其内部模型预测的烘烤时间是多少。
工程安全系统需要理解系统级的需求,分析世界和机器之间的交互,以及理解各种(可能不可靠的)组件的交互。决定模型是否安全的是如何使用模型的上下文。
模型的稳健性既不保证安全性也不保证本身的安全性。稳健不能保证模型的“正确性”:稳健的预测仍然可能是错误的;一个非常健壮的模型可能完全没有用。在更大的安全故事中,鲁棒性可能是一个有用的构建块(上面讨论了所有开放的工程挑战),因为当我们考虑与系统的其他部分和环境的交互时,它改变了我们可以对 ML 组件做出的假设。但是仅仅让一个模型健壮并不能让系统安全。
有研究工作是利用机器学习模型构建安全系统,特别是围绕航空电子设备和自动驾驶汽车——这都是关于需求、系统设计和系统级测试的,而确保正式的鲁棒性通常似乎不是一个很大的问题。
路灯效果:寻找光在哪里
回到街灯效应,(以一个男人在街灯下寻找钱包的故事命名,当被问及“这是你丢钱包的地方吗”时,他回答说他在别处丢了钱包,但在有光的地方寻找更容易):深度神经网络的鲁棒性是一个令人欣慰的研究主题,因为它被很好地定义,具有挑战性,并有超过艺术水平的明显可测量的改进空间。许多研究人员做出了令人难以置信的贡献。然而,如果我们真的关心具有机器学习组件的生产系统的安全性,我们应该超越简单和明确定义的问题,看看现实世界系统的真实和丑陋的工程挑战。
进一步阅读:
- 我之前发表的关于支持 ML 的系统的质量保证的文章:机器学习是需求工程(关于正确性的概念和规范的作用)关于机器学习模型质量的软件测试观点(关于超越准确性的测试策略)世界和机器以及负责任的机器学习(关于系统级思维和需求工程)
- 论文调查当前汽车工程中 ML 系统的安全工程: Borg、Markus、Cristofer Englund、Krzysztof Wnuk、Boris Duran、Christoffer Levandowski、Gao、Tan、Henrik Kaijser、Henrik lnn 和 Jonas trnqvist。 安全进入深度:机器学习的验证与确认综述及汽车行业的挑战启发 。”汽车软件工程杂志。第 1 卷,第 1 期,第 1-19 页。2019
- 关于自动驾驶汽车的安全工程和建筑安全模式的论文: Salay,Rick 和 Krzysztof Czarnecki。" 在汽车软件中安全地使用机器学习:ISO 26262 软件过程需求的评估与适应。"arXiv 预印本 arXiv:1808.01614 (2018)。
- 另一篇论文讨论了自动驾驶汽车的不同安全策略:Mohseni,Sina,Mandar Pitale,Singh 和 Wang。"自动驾驶汽车中机器学习安全的实用解决方案"2020 年 AAAI 安全研讨会。
- 列举了许多最新稳健性验证技术的调查论文(第 4 节):【黄、、丹尼尔·克罗宁、阮、詹姆斯·夏普、孙友成、埃姆斯·塔莫、和易新平。" 深度神经网络的安全性和可信度调查:验证、测试、对抗性攻击和防御、可解释性 。"计算机科学评论 37 (2020)。
- 人工智能系统软件工程的注释书目包括几篇关于健壮性、安全性和安全性的论文
我为什么要为量子机器学习费心呢?
量子机器学习有望颠覆传统
本帖是本书的一部分: 用 Python 动手做量子机器学习 。
在最近的过去,我们目睹了算法如何学会驾驶汽车,并在国际象棋和围棋中击败世界冠军。
图片由作者 www.pyqml.com·弗兰克·齐克特提供
从军事到航空航天,从农业到制造业,从金融到医疗保健,机器学习几乎被应用到所有可以想象的领域。
但是机器学习算法已经变得越来越难以训练。所以当我们看到这种表示时,当前的机器学习算法,如 2020 年发表的生成式预训练变压器 3 (GPT-3)网络,浮现在脑海中。GPT 3 号产生了类似人类的文本。
训练 GPT-3 需要在单个 GPU(图形处理单元)上花费 355 年时间,耗资 460 万美元。通过并行化,训练速度大大加快。然而,这需要大量的计算资源。
训练目标是为模型所包含的参数找到一组工作值。不幸的是,训练模型的复杂性随着参数的数量呈指数增长。
比方说,一个模型由四个布尔(真或假)参数组成。然后,有 2⁴=16 可能的配置。如果参数采用一位数(0–9)作为值,将有 10⁴=10,000 可能的配置。相应地,如果我们有 86 个而不是 4 个参数,那么这个模型将会有 10⁸⁶可能的构型。对了,这是可见宇宙中原子的数量左右!
GPT-3 模型包含 1750 亿个参数。我甚至不敢去想有多少种可能的构型。
当然,有精明的算法和启发来改善训练,并最终导致一个工作系统。然而,当前机器学习模型的复杂性成为一个问题。一些人甚至认为,我们正在走向下一个人工智能冬天,因为用当前的计算技术来训练我们正在寻找的模型是难以处理的。
量子计算机有望解决这类问题。它们同时计算多个状态的能力使它们能够并行执行几乎无限多的任务。这种能力有望改善和加速机器学习技术。与基于顺序信息处理的经典计算机不同,量子计算利用了量子物理的特性。
让量子计算如此强大的不是它的处理速度。其实挺慢的。让量子计算如此强大的也不是它的内存。事实上,它小得荒谬。所以我们谈论的是一些量子比特。
让量子计算如此强大的是它所实现的算法。此外,这些算法表现出不同于经典算法的复杂性特征。
为了理解这意味着什么,让我们简单看一下复杂性理论。复杂性理论是对运行算法所需的计算工作的研究。
作者弗兰克·齐克特的图片
例如,加法的计算量是 O(n)。这意味着两个数相加的工作量随着数的大小(位数)线性增加。乘法的计算量是 O(n)。努力随着数量大小的平方而增加。据说这些算法在多项式时间内是可解的。
但是这些问题相对简单。例如,解决因式分解问题的最佳算法是寻找一个 n 位数的质因数:O (e(n1/3).不幸的是,这意味着随着位数的增加,工作量呈指数增长。
O(n)和 o(的区别我们一定不能低估 e^ (n /3)复杂度。虽然你的智能手机可以在几秒钟内将 800 位数字相乘,但在超级计算机上,这种数字的因式分解需要大约 2000 年。
但是量子计算是一种不同形式的计算。它利用了量子物理的三个基本性质:叠加、干涉和纠缠。
这些就是叠加、纠缠、干涉。但是量子计算并没有增加可用的计算能力,而是减少了解决问题所需的能力。
叠加是指一个量子系统可以同时存在多个态的量子现象。
Actually, the quantum system does not exist in multiple
states concurrently. It exists in a complex linear combination
of a state 0 and a state 1\. It is a different kind
of combination that is neither "or" nor is it "and".
作者弗兰克·齐克特的图片
量子干涉是允许我们将量子系统偏向期望状态的东西。这个想法是要创造一种干扰模式,其中导致错误答案的路径会破坏性地干扰和抵消,但导致正确答案的路径会相互加强。
作者弗兰克·齐克特的图片
纠缠是量子粒子之间极强的关联。此外,即使相隔很远,纠缠的粒子仍然保持完美的关联。
作者弗兰克·齐克特的图片
阿尔伯特·爱因斯坦生动地拒绝了量子纠缠的概念,称之为“超距作用”。
量子计算要求我们改变对计算机的看法。它需要一套全新的算法。编码和使用量子信息的算法。这包括机器学习算法。我们不能简单地把我们目前的算法放在量子计算机上运行。我们需要开发新的算法。
我们需要一批新的开发人员来开发这些算法——理解机器学习和量子计算的开发人员。开发者有能力解决以前没有解决的实际问题。一种罕见的显影剂。今天解决量子机器学习问题的能力已经让你与众不同了。
结论
量子机器学习有望成为颠覆性的。虽然机器学习和量子计算这两个活跃的研究领域的合并主要是在概念领域,但已经有一些应用于解决现实生活问题的例子。谷歌、亚马逊、IBM、微软和一大批高科技创业公司都在努力成为第一批制造和销售量子机器学习系统的公司。
当一项技术即将证明其优势时,研究这项技术的机会是一个独特的机会。不要错过它。
本帖是本书的一部分: 用 Python 动手做量子机器学习 。
在这里免费获得前三章。
我为什么要为异常检测付费?自己打造自己不是很容易吗?
使用业务绩效数据构建成功的异常检测系统的三个关键方法
Josue Isai Ramos Figueroa 在 Unsplash 上的照片
构建异常检测系统可能看起来很简单,但这不仅仅是要求您的数据科学团队实施现成的算法,所有支持基础架构对于最终用户来说都是系统成功的关键。
在本指南中,我将列出构建成功的异常检测系统的 3 种关键方法,以及需要哪些核心组件。
不同的笔画,适合不同的人
有很多方法可以处理业务指标的时序异常检测。根据您的团队及其需求,您可能已经考虑了以下方法之一:
- 自我构建 —您在自己的基础设施上托管异常检测算法&逻辑,并构建所有周围的设备来运行检测,以及使用内部人员配置&资源来维护系统。通常,这需要最长的时间来实现价值,最高的前期成本,以及对团队时间的最高需求。
- 自行构建,通过 API 服务进行检测 —与自行构建相同,但使用 API 服务进行异常检测逻辑,接收时序数据并返回结果。除此之外,您还需要构建和维护所有相关的基础设施。
- 托管服务 —所有方面都由您的提供商托管和管理。使用他们的 SaaS 产品,你只需提供数据并选择要跟踪的内容。这通常是最快实现价值的,产生适度的持续成本,由团队花费在维护上的很少时间来抵消。
就成本、实现价值的时间和技术难度而言,每种方法都有自己的优缺点:
异常检测方法——利弊权衡。图片作者。
除了算法,我还需要什么?
无论您采用哪种方法,这些都是成功部署基本异常检测系统所涉及的元素和任务——我还提供了每个组件可能需要多长时间开发的实际指示,以及所需的技能:
成功的异常检测系统的关键组件。图片作者。
1。数据准备&转换
**团队:**数据工程、软件工程
价值实现时间:6-9 个月
存储的业务绩效数据需要转换为适合异常检测的时间序列格式,这涉及到:
- 将数据输入到数据存储系统中,并直接耦合到异常检测算法中,无论该算法位于何处
- 定义要跟踪的指标&基于这些指标以期望的频率生成时间序列
- 说明并删除任何不完整的期间、缺失值和其他数据卫生注意事项
- 重复数百/数千次,详细反映用户对跟踪内容的偏好
2。调度异常检测运行
团队 : DevOps,软件工程
价值实现时间:3-6 个月
必须构建和维护基础架构,以定期触发后续的异常检测流程—新数据预计会定期到达。为了实现最高效率,应该以不同的频率跟踪不同的指标(例如,每小时监控一次销售额,但每天只检查新客户注册情况)
3。异常检测
**团队:**数据科学、软件工程
价值实现时间:12–18 个月
这是大多数人在考虑异常检测时想到的组件,即识别业务指标中异常行为的智能算法。核心任务包括:
- 从数据准备阶段无缝接受来自各种时间序列的输入,无论频率、噪声和形状如何,并进行扩展以处理同时跟踪的数百/数千个指标。
- 优化设置,最大限度地提高检测准确性,同时最大限度地减少误报和漏报,几乎不需要人工干预— 并非所有算法都能提供相同的性能
- 要达到高水平的性能,并具有可接受的假阳性/假阴性水平,可能需要 12 个月以上的时间!
- 清楚地输出检测到的异常,以便采取后续措施
4。通知交付&任务分配
团队 : DevOps、软件工程、UX
价值实现时间:3-6 个月
一旦检测到异常,就需要通知业务用户。如果没有这一步,异常情况就会隐藏在系统中,看不到。常见的集成渠道包括:
- 应用程序内弹出窗口
- 电子邮件
- 工作场所聊天工具(例如 Slack、微软团队)
- Webhooks(用于交付给 OpsGenie、PagerDuty 等事故管理系统)
同样重要的是,能够与企业中可能没有收到相同警报的其他个人共享通知,并为他们分配任务以解决手头的问题。
5。可视化&结果存储
**团队:**软件工程,UX
时间价值:6–9 个月
虽然有一个通知是有用的,但是业务用户可能希望以一种更自由的方式探索其他已经被识别的异常。最好通过图形格式可视化检测到的异常,允许用户:
- 对照历史背景交叉引用他们被告知的异常情况
- 找到其他类似的异常,或者调查其他可能受到影响的指标
- 开始理解绩效变化背后的根本原因
- 为了获得可接受的访问速度,这需要将异常检测算法的结果存储在数据湖/数据仓库中。
6。根本原因分析和问题解决
**团队:**数据科学、软件工程、UX、DevOps
**价值实现时间:**12–18 个月
一旦发现异常情况,很自然会尝试找出它发生的原因。如果没有此功能,业务用户对检测到的异常情况快速采取行动的能力就会受到限制。虽然对数据集进行手动分析是可能的,但这需要的技能不是业务用户关注的重点,可能需要几个小时或几天才能完成。
使用机器学习的自动化根本原因分析系统有助于发现性能变化的最相关原因,如异常所识别的。这通常在几秒钟内完成,包括:
- 开发底层根本原因分析算法,足够灵活地回答任何基于指标和已识别异常的问题,并与正常行为进行比较。
- 解释趋势的变化。
- 最大限度地减少绩效变化背后的不相关原因,例如巧合的相关性
- 以一种易于理解的方式显示这些信息,业务用户可以探索其他原因,并快速与他人分享这些见解以解决问题。
总结一下:
业务绩效指标的异常检测不仅仅是检测算法,所有的支持组件都有助于使系统及其洞察力对业务用户可用且有用,方法的选择对成本和价值实现时间有实际影响!
我希望这在您为您的企业实施异常检测的过程中是一个有用的指南——如果您想了解 Avora 的方法,请访问我们的www.avora.com!
为什么要用 Viziball 来分析比较篮球运动员的表现?
看一眼图表可以帮助我们得出结论。这就是数据可视化的美妙之处。
在之前的一篇文章中,我讨论了我们如何在篮球分析网站的 Viziball 中使用 PIE ( 球员影响力评估)。这种通用的测量方法旨在汇总统计结果,以便快速总结玩家对游戏的影响。
尽管这给了我们很多,但这一指标也有局限性(和其他指标一样)。首先,我们只有可见的游戏事实,除了产生统计数据,还有其他方法可以影响游戏。第二个限制是派给出了一个总体的评估,因此,很难追踪受影响的游戏方面。
这是我们试图解决的第二个限制。为了提供更详细的见解,我们建议围绕 8 个轴对饼图进行细分:投篮、得分、进攻侵略性、防守侵略性、抢断、接球得分&、进攻和配合。
对于这些轴中的每一个,我们根据我接下来将讨论的各种公式来计算分数(在 0 到 100 之间)。但是在我继续之前,我想介绍一下我们的视觉特征,这就是为什么我们必须把所有的轴放在同一个刻度上:蜘蛛图。
达米恩·利拉德的职业表现概述。图表由 Viziball 绘制。
蜘蛛图(或雷达图)对于以一种吸引人的方式比较数据是有用的。它们对于查看数据集中哪些变量得分高或低非常有效,这使它们成为显示性能统计数据的理想选择。此外,蜘蛛图很容易被大量受众理解,并且已经相当普遍(并非所有数据可视化图形都是如此)。然后,图表几乎没有注释,可以很容易地共享。
分析人士表示,这很快带来了许多见解。球员如何控制和分配球(得分球指示器)?他在团队层级中处于什么位置(关键人物指示器)?他在赚钱时间(离合指示器)好不好?他的进攻特点是什么?他如何影响防守(防守侵略性)?他是在创造自己的水桶,还是更像一个接球手(接球得分)?
为了让你更详细地了解 Viziball 如何试图提供一些答案,这里是如何建立指标。一些是基于基本的统计数据,而另一些是基于更高级的公式或逐场分析。
为了让你更详细地了解 Viziball 如何试图提供一些答案,这里是如何建立指标。有些是基于基本的统计数据,有些是基于更高级的公式或详细的分析。
- 造球:基于助攻失误率。该指标衡量控球和创造高效比赛的能力。
- 投篮:混合有效投篮命中率 (EFG%)和真实投篮命中率 (TS%)来衡量从任何距离射门得分的能力。
- 计分:点数*。*
- Go-to guy :基于出场分钟数和使用指标(球员在场上结束时手中财产的百分比)。
- 接球&得分:跟随一次助攻得分的能力(基于助攻得分%)* 。得分低并不意味着球员错过了他的接球&投篮,而是意味着他的大部分投篮都来自个人动作(没有队友的助攻)。*
- 进攻侵略性 : 平局犯规和进攻篮板*。*
- 防守侵略性 : 抢断,盖帽,,个人犯规。
- Clutchness :这结合了几个基本的统计数据来产生一个单一的值。与派或游戏分数不同,这里我们为每个属性添加一个系数,这取决于剩余的游戏时间和动作发生时的点数差异。
如你所见,所有指标都是基于比赛期间记录的统计数据。我没有给出将所有指标放在同一尺度上的标准化过程。我同意这个过程听起来可能有些武断。但是,我们必须记住的是,我们正在尝试比较球员的表现。所以在这个过程的最后,当所有的表现都在蜘蛛图上时,这就是我们得到的。
同样重要的是要注意,在我们的计算中没有引入主观意见。比如说,看完比赛后,鲁迪·戈贝尔在防守方面度过了一个美好的夜晚。当然,如果有一个我们可以配置和调节值的仪表板,那就太好了。这样做,人们可以想象更多的轴。但这不是 Viziball 的哲学。我们避免在工作流程中引入偏见。我们做的是给分析师和内部人士带来工具,而不是相反。然后他们就可以自由下结论了。
做最后一个评论,我们也可以说这不应该代表玩家的内在价值,就像电子游戏试图做的那样。出于任何原因,球员的表现可能会被环境改变:教练的选择,裁判的决定,甚至是受伤。
我们的定位可以讨论很长时间(我也鼓励你给我反馈,帮助我们丰富我们的模型),但我认为是时候看看我们如何使用蜘蛛图了。
赛后报道
每天,对于所有可用的游戏,Viziball 建立一个赛后报告,其中每个玩家的蜘蛛图都是可用的。
例如,下面是巴姆·阿德巴约在 2021 年 1 月 23 日对阵布鲁克林篮网的比赛后的蜘蛛图。很快,在知道他在那场比赛中的统计数据之前,我们可以理解他在各个方面都度过了一个伟大的夜晚。
巴姆·阿德巴约 2021 年 1 月 23 日的表现概述。维兹鲍尔赛后报道。*
与此同时,凯里·欧文度过了一个关键的夜晚:三分球,突破上篮,关键罚球帮助篮网在第四节取得胜利。这可以通过他的蜘蛛图看出来,图中投篮和离合指标都很高。
凯里·欧文 2021 年 1 月 23 日的表现概述。维兹鲍尔赛后报告。*
Viziball 还在同一个赛后报告中提供了一个热图,显示了球员在每个序列中的影响。在这里,这种影响用砖块的强度来表示。颜色越深,影响越高。下面,与最后一节相关的最后 4 个砖块看起来是垂怜经游戏中最激烈的。我们还可以看到这与他的积分线(蓝色)的关系,积分线在游戏结束时会增加。
凯里·欧文在对阵迈阿密的比赛中的表现。维兹鲍尔赛后报告。*
玩家的个人资料页面
Viziball 数据库中记录的每个球员都有自己的球员个人资料页面,其中有一个蜘蛛图和其他各种小部件。使用这个功能,我们可以观察一个球员在特定时期的表现,可以是他们的整个职业生涯,一个特定的赛季,或者任何个性化的持续时间。
这个网页可以高度定制(比如显示或隐藏蜘蛛图的轴),并且可以使用个性化的 URL 或嵌入式模式轻松共享。
图像底部是日期选择器模块。我们可以看到黄线显示了总体绩效(PIE)如何随着时间的推移而变化。
勒布朗詹姆斯职业表现概述。图表由 Viziball 绘制。*
该页面还包括一个名为职业道路的时间线模块,显示了玩家职业生涯的最高记录和他在所有球队的第一场比赛。
勒布朗詹姆斯的职业道路。时间线由维兹鲍尔。*
比较玩家
在我看来,蜘蛛图带来最重要的洞察力的地方是当我们覆盖几个玩家的时候。Viziball 的比较功能使得同时可视化两个玩家成为可能。这带来了各种各样的场景:比较对手,比较来自同一支球队的球员以了解他们如何才能适应,或者也比较同一名球员在职业生涯的不同时刻。
例如,下面是当前赛季(2020–2021)前几场比赛杰森·塔图姆(绿色)和布拉德利·比尔(红色)的对比蜘蛛图。我们可以看到他们在接球&得分*、组织进攻和投篮指标上的相似之处,但在其他方面也有一些明显的差距,在得分和*进攻&防守侵略性上比布拉德利·比尔有优势。**
另一方面,塔图姆似乎在所选期间的第四季度表现出色,他获得了 84 的离合器性能指标(布拉德利·比尔为 49)。
杰森·塔图姆(绿色)与布拉德利·比尔(红色)在 2020-2021 赛季首场比赛中的表现。 Viziball 蜘蛛图。*
比尔似乎是进攻中的第一选择,他的指标等于 93(杰森·塔图姆是 78)。为了了解这与传统数字的关系,让我们更深入一点。Beal 记录了每场比赛 35.6 分钟和 37.8% 的使用率。塔图姆 34.3 分钟,31.2% 使用率。
杰森·塔图姆和布拉德利·比尔的平均数字。图表由 Viziball 绘制。**
这意味着杰森·塔图姆正在更多地分享球权。为了更进一步,我们可以观察的使用是如何在两个团队中分配的。我们可以在下面看到,与所有队友相比,比尔的使用率很高(除了拉塞尔·维斯特布鲁克,他有 31.42%),而凯尔特人似乎在三个关键人物之间分享进攻阶段:杰森·塔图姆、杰伦·布朗和肯巴·沃克,分别有 31.2%、35.75%和 32.35% 、。
两队使用分布:奇才 vs 凯尔特人。图表由 Viziball 绘制。**
观察性能演变
*寻找未来进步最多的玩家(或者也是*最衰退的玩家)辨别玩家换队时的进化,或者只是观察玩家在游戏某个方面的进化:所有这些都可以通过这个功能来完成。
就我个人而言,我选择用尼古拉·约基奇的比较蜘蛛图来说明这个特征:
- 蓝色的是他 2019-2020 赛季的统计数据(包括泡沫和季后赛)。
- 黄色部分是他本赛季第一场比赛的数据。
尼古拉·约基奇在两个时期的比较蜘蛛图:2019 年至 2020 年(深蓝色)与 2020 年至 2021 年的第一场比赛(黄色)。 Viziball 的蜘蛛图。**
这使得更好地反映他令人印象深刻的演变成为可能。我们可以看到,他几乎在所有方面都有所提高,但不一定会延长他的关键人物指标(与上个赛季相比,该指标仅从 68 分钟增加到 72 分钟,即每场比赛+2.7 分钟,使用率+1.8%)。
深入一点细节,我们可以理解小丑是如何在不玩太久的情况下设法增加他的影响的。首先,他改进了射击轴,这使他可以直接增加他的得分*(几乎每场+5 分)。他也制造了更多的犯规,这让他更经常地站在罚球线上。最后,他似乎扩大了他的控球和分配技能,一个制造比赛的指标从 75 增加到 88(即每场比赛+2.5 助攻和-1.1 失误)。***
最后,我们可以观察他在第四节的巨大影响。他的离合ness 指标本赛季初是 100!而且上个赛季已经很高了。每个人(从爵士和快船开始)都记得去年的季后赛和丹佛在赚钱时间的表现。
更进一步
正如您所看到的,这个特性是高度可配置的。显然,有些事情还不可能(例如,在同一个蜘蛛图上比较两个以上的球员),但该工具已经能够适应大量的组合,这可能会使球迷、分析师、赌徒甚至篮球专业人士优化他们的调查过程。因此,你可以通过这个工具自由地表达你的分析!
我想指出的是,Viziball 是一项 100%免费的服务,任何人都可以不受任何限制地使用。该研究项目于 2019 年底启动,由法国公司 Data Nostra 领导,该公司是 R&D 数据分析领域的专家(不仅限于体育),旨在确定体育数据处理的创新方法。该网站在不同的层面上不断发展。我们必须处理一个网站的经典问题(UX 设计,搜索引擎优化),但也对篮球分析方面。这就是我们尽量沟通工作的原因。更进一步说,我们特别喜欢来自专业体育分析家的信息反馈。
如今,该项目完全依靠公司自有资金运行,旨在延续 Viziball 服务。为此,我们对任何合作提议都持开放态度,无论是俱乐部、联盟还是专业媒体。
我们刚刚推出了一个 Twitter 账户,在那里我们定期分享基于 Viziball 的内容。这使得用不同的统计轴跟踪篮球新闻成为可能。因此,我邀请您跟随我们,分享我们的内容并亲自体验这一工具!
为什么要在图像分类实验中标注自己的数据?
尽管单调乏味,给你的图片贴标签可以提供有价值的见解。使用 tkteach 在 5 分钟内设置好您的贴标管道
凯利·西克玛在 Unsplash 上的照片
获取高质量的影像分类标签决定了您的项目是否有机会取得成功。互联网上有几乎无限的图像资源,但如果你的任务比猫狗分类器更复杂,往往很难找到适合解决你的特定问题的标记图像。
让事情变得更复杂的是,定义你的问题并提出正确的问题本身就是一个挑战。当您处理结构化数据时,您可以使用平均值、最大值或中值等聚合来轻松汇总数千条记录,使您在半小时内对整个样本有一些基本的了解。
当处理图像时,这变得复杂得多,因为你所能做的只是快速检查几十个图像,并希望你收集的任何见解将很好地推广到整个数据集。
影像数据的这一特征使得为您的模型定义正确数量的类或快速验证您尝试使用影像分类解决的问题的可行性变得非常棘手。
1.为什么手动标注数据集的子样本是个好主意?
从标记几千张图像开始实验听起来并不是最先进或最有趣的方法,但这种大胆的方法有几个优点:
- 标注样本数据集是探索图像的最佳方式,因为它要求您为每一幅检查的图像做出决定,从而使您比浏览数据集时更加集中注意力
- 对一个图像类做出数百个决定是验证您选择的类是否正确的快速方法,通常您需要添加一个新的类,因为您发现一些意外的图像类型比预期的更常见
- 您可能会发现,您正在尝试解决的任务的大部分信息包含在图像的一小部分中,在这种情况下,可能值得添加一些成帧算法来增强重要部分并减少噪声,然后再将其提供给分类器
- 自己对图像进行分类可以让你很好地洞察人类的表现以及你的模型可能面临的障碍。在错误分析过程中,这种经验是必不可少的,因为你经常会发现模型产生的错误类似于你花了最长时间来分类的图像
- 如果你发现自己很难对图像进行分类,它们可能不是你试图解决的问题的答案。在这种情况下,您只是为自己节省了几个小时无价值的编码,因为您的模型可能不会超过人类的性能。后退一步,想想你是否问对了问题,这是一个好主意
好吧,以上所有观点听起来都很有说服力,但是谁有时间给成千上万的图片贴标签呢?好消息是,你可以在 3 个小时的工作时间内获得这些好处——比你花在调整模型上的时间要短得多。
虽然为了获得最佳的图像分类性能,您可能需要数万或数十万张图像,但从大约 5000 张手动标记的图像开始是验证您的分类器是否有机会的快速方法。5k 图像听起来很多,但是经过几分钟的练习,你可以每小时标记大约 1.5k-2k 图像。这几个乏味的小时可以快速验证项目的可行性,如果初始实验成功,您将拥有一个值得信赖的数据样本,可以将其用作测试集,以查看在更广泛的数据集上训练的模型与人类相比表现如何。
2.如何在 5 分钟内建立一个图像标注管道?
从我的经验来看, tkteach 正是建立一个简单而有效的标签管道的合适工具。这三个步骤是你开始标记你的图像所需要的,我将使用我自己的图像分类项目,在这里我试着以平面室内标准为例进行分类:
- 将 tkteach 资源库克隆到您的项目中
git clone [**https://github.com/Serhiy-Shekhovtsov/tkteach.git**](https://github.com/Serhiy-Shekhovtsov/tkteach.git)
2.在克隆的 tkteach 存储库中创建一个 ds 文件夹,并在 ds 文件夹中创建一个包含要标记的图像的文件夹
3.打开已存在于克隆 tkteach 存储库中的 categories.txt,并按照({keyboard key}) {class name}格式创建您自己的类。
现在你已经准备好开始你项目中最无聊的几个小时了,但是相信我,你的勇气会在以后得到回报的。将目录切换到您的 tkteach 文件夹并运行 tkteach.py。这将触发一个弹出窗口,要求您找到包含您要标记的图像的文件夹。选择好准备好的文件夹后,你就可以开始享受标签了——只需点击选择的键(在我的例子中是 q,w,e ),然后进入下一张图片。
3.访问标记的图像
您的图像标签存储在 tkteach 文件夹中名为 storage.db 的 sqlite 数据库中。您可以使用 dbeaver 或类似的 sqlite 数据库工具轻松访问它,只需选择 storage.db 路径。您的数据库应该如下所示:
图片和标签表是查询图片及其标签的关键表,而类别表将 category_id 映射到实际的标签名称。如果您有多个包含图像的文件夹,您将只需要数据集表,因为它将允许您按文件夹过滤标记的图像。您可以通过一个简单的查询提取带标签的图像数据,该查询输出图像名称、位置及其类别。
SELECT imageName, imagePath, categoryNameFROM images aJOIN labels bON a.id = b.image_idJOIN categories cON b.category_id = c.id
4.一次乏味却有益的经历
我知道了艰难地标记自己的图像数据的好处——花费数小时试图改进计算机视觉模型,这些模型注定会失败,原因有两个:
- 图像和/或其标签的质量太低
- 图像中的信息与解决我的特定任务无关,我自己也没有很好地标记它们
在这两种情况下,几个小时无聊的图像标记让我实现了十几个小时的花式编码。
我不建议标记成千上万的图像——一旦你在自己的数据上取得了一些初步的成功,你可以找到其他方法来扩大你的数据集或找人来为你做标记。
然而,我鼓励你在开始你的计算机视觉项目时,试着花几个小时来标记几千张图像中值得信赖的子集。它允许您快速验证您的想法,是探索您的数据的一种很好的方式,可以节省您大量的时间。
自然语言处理中迁移学习的新进展
思想和理论
自然语言处理中迁移学习技术的发展综述
以下是我新发布的《自然语言处理的迁移学习》一书的节选。摘要总结了一些最近的 NLP 模型架构依赖于迁移学习的概念。
人工智能已经戏剧性地改变了现代社会。以前由人类完成的任务现在可以由机器来完成,速度更快,成本更低,在某些情况下效率更高。这方面的流行例子包括计算机视觉应用——涉及教计算机如何理解图像和视频——例如,用于在闭路电视摄像中检测罪犯。其他计算机视觉应用包括从患者器官的图像中检测疾病,以及从植物叶子中检测植物种类。人工智能的另一个重要分支,特别处理人类自然语言数据的分析和处理,被称为自然语言处理 (NLP)。NLP 应用的例子包括语音到文本的转录和各种语言之间的翻译,等等。在图 1 中,AI 和 NLP 在维恩图中与相邻的场并列。
图一。维恩图是自然语言处理(NLP)、人工智能(AI)、机器学习和深度学习等术语相对于彼此的可视化。也显示了符号 AI。(图片作者,来自 《自然语言处理的迁移学习》 )
人工智能、机器人和自动化领域技术革命的最新体现,被一些人称为第四次工业革命的,是由训练大型神经网络的算法进步、通过互联网获得的大量数据以及通过最初为个人游戏市场开发的图形处理单元(GPU)获得的大规模并行能力的交叉引发的。更具体地说,最近依赖于人类感知的任务自动化的快速发展,特别是计算机视觉和 NLP,要求神经网络理论和实践取得这些进展。这使得输入数据和期望的输出信号之间的复杂表示能够被学习,以处理这些困难的问题。
与此同时,对人工智能在不久的将来能够完成的事情的预测已经大大超过了在实践中已经取得的成就。我们被警告一个世界末日的未来,它将抹去大多数人类工作,取代我们所有人,甚至可能对我们的生存构成威胁。自然地,自然语言处理也不排除在这种推测之外,并且它是今天人工智能中最活跃的研究领域之一。
迁移学习旨在利用不同背景下的现有知识——无论是不同的任务、语言还是领域——来帮助解决手头的问题。它受到人类学习方式的启发,因为我们通常不会针对任何给定的问题从零开始学习,而是建立在可能相关的先验知识上。例如,当一个人已经知道如何演奏另一种乐器时,学习演奏一种乐器被认为更容易。显然,乐器越相似,例如风琴和钢琴,先前的知识就越有用,学习新乐器就越容易。然而,即使乐器大不相同,比如鼓和钢琴,一些先前的知识仍然是有用的,即使不那么有用。在这个思维实验中,部分原因可能是因为坚持一个节奏是两种乐器共有的技能。
大型研究实验室,如 Lawrence Livermore 国家实验室或 Sandia 国家实验室,以及大型互联网公司,如谷歌和脸书,能够通过对数十亿个单词和数百万张图像训练非常深度的神经网络来学习非常大型的复杂模型。例如,谷歌的自然语言处理模型 BERT】接受了来自英语维基百科(25 亿个单词)和图书语料库(8 亿个单词)的超过 30 亿个单词的预训练。同样,深度卷积神经网络(CNN)已经在 ImageNet 数据集的超过 1400 万张图像上进行了训练,学习到的参数已经被许多组织广泛外包。今天,从零开始训练这种模型所需的资源量对于神经网络的普通从业者来说通常是不可用的,例如在较小企业工作的 NLP 工程师、较小学校的学生等。这是否意味着较小的参与者无法在他们的问题上取得最先进的成果?令人欣慰的是,如果应用正确,迁移学习的概念有望减轻这种担忧。
迁移学习为什么重要?
迁移学习使您能够将从一组任务和/或领域获得的知识调整或转移到另一组任务和/或领域。这意味着,一个用海量资源训练出来的模型——包括数据、计算能力、时间、成本等。—一旦开源,更广泛的工程社区就可以对其进行微调,并在新的环境中重新使用,而所需资源只是原始资源的一小部分。这是 NLP 民主化的一大步,更广泛地说,是 AI 民主化的一大步。图 2 展示了这个范例,以学习如何演奏乐器为例。从图中可以看出,不同任务/域之间的信息共享可以导致后面的或下游任务 b 实现相同性能所需的数据减少
图二。转让好处的说明。收入模式,显示在底部面板中,其中信息在为不同任务/领域训练的系统之间共享,而传统模式,显示在顶部面板中,其中训练在任务/领域之间并行发生。在迁移学习范式中,通过信息/知识共享可以减少数据和计算需求。例如,如果一个人先知道如何弹钢琴,我们期望他更容易学会打鼓。(图片作者,来自 《自然语言处理的迁移学习》 ,灵感来自图 3 本文)
NLP 迁移学习的最新进展
传统上,对于任何给定的问题设置(任务、领域和语言的特定组合),学习都是在完全监督或完全无监督的方式下从零开始进行的。早在 1999 年,在支持向量机 (SVMs)的背景下,半监督学习就被认为是一种解决潜在的有限标记数据可用性的方法。对较大的未标记数据集合的初始无监督预训练步骤使得下游监督学习更容易。这种方法的变体研究如何处理潜在的噪音,即可能不正确的标签——这种方法有时被称为弱监督学习。然而,通常假设标记和未标记数据集具有相同的采样分布。
迁移学习放松了这些假设。迁移学习的需要在 1995 年被公认为是“学会学习”的需要。NeurIPS 可能是机器学习领域最大的会议。本质上,它规定智能机器需要拥有终身学习的能力,将学到的知识重新用于新的任务。它后来被冠以几个不同的名称进行研究,包括学会学习、知识转移、归纳偏差、多任务学习等。在多任务学习中,算法被训练成同时在多个任务上表现良好,从而揭示可能更普遍有用的特征。然而,直到 2018 年左右,人们才开发出实用且可扩展的方法,在 NLP 中实现最难的感知问题。
2018 年见证了自然语言处理领域的一场革命。对如何最好地将文本集合表示为向量的理解发生了巨大的变化。此外,开源模型可以被微调或转移到不同的任务、语言和领域,这一点得到了广泛的认可。与此同时,几个大的互联网公司发布了更多更大的 NLP 模型来计算这种表示,他们还指定了定义良好的程序来微调它们。突然之间,普通的从业者,甚至是一个独立的从业者,都有能力在 NLP 中获得最先进的结果。它甚至被广泛称为 NLP 的“ImageNet 时刻”,指的是 2012 年后计算机视觉应用的爆炸,当时一个经过 GPU 训练的神经网络赢得了 ImageNet 计算机视觉竞赛。就像最初的 ImageNet moment 一样,预训练模型库第一次可以用于任意 NLP 数据的大型子集,以及定义良好的技术,用于微调它们以适应手头的特定任务,其标注数据集的大小远远小于其他情况下所需的大小。这本书的目的是描述、阐明、评估、论证性地应用、比较和对比属于这一类别的各种技术。接下来我们简要概述这些技术。
对自然语言处理的迁移学习的早期探索集中在对计算机视觉的类比上,它已经成功地应用了十多年。一个这样的模型— 本体建模的语义推理(SIMOn) — SIMOn 采用字符级 CNN 结合双向长短期记忆网络 (LSTMs)进行结构化语义文本分类。它展示了 NLP 迁移学习方法,与计算机视觉中使用的方法直接类似。大量关于计算机视觉应用的迁移学习的知识推动了这种方法。通过该模型学习的特征被证明对于无监督的学习任务也是有用的,并且在社交媒体语言数据上工作得很好,这些数据可能有些特殊,并且与维基百科和其他基于书籍的大型数据集上的语言非常不同。
word2vec 最初表述的一个显著缺点是歧义。没有办法区分一个词的各种用法,这些用法根据上下文可能有不同的含义,即同形异义词:例如,鸭子(姿势)对鸭子(鸟),公平(聚会)对公平(公正)。在某种意义上,原始 word2vec 公式通过表示单应词的这些不同含义的向量的平均向量来表示每个这样的词。 来自语言模型的嵌入——在流行的芝麻街角色后缩写为 ELMo 是使用双向 LSTMs 开发单词的语境化嵌入的尝试。ELMo 模型的高级架构图如图 3 所示。
图 3。在文档分类示例的上下文中可视化 ELMo 架构。(图片作者,来自 【自然语言处理的迁移学习】 )
单词在该模型中的嵌入在很大程度上取决于其上下文,对于每个这样的上下文,相应的数字表示是不同的。ELMo 通过训练来预测单词序列中的下一个单词,这是语言建模领域的一项重要任务。巨大的数据集,例如维基百科和各种书籍的数据集,在这个框架中很容易用于训练。
https://arxiv.org/abs/1801.06146(ULM-FiT)通用语言模型微调(Universal Language Model Fine-tuning)是一种被提出来为任何特定任务微调任何基于神经网络的语言模型的方法,最初在文本分类的上下文中被演示。这种方法背后的一个关键概念是区别性微调*,其中网络的不同层以不同的速率进行训练。OpenAI 生成预训练转换器 (GPT)修改了转换器的编码器-解码器架构,以实现 NLP 的可微调语言模型。这个模型架构如图 4 所示。*
图 4。GPT 架构的高级表示,显示了堆栈解码器、输入嵌入和位置编码。来自顶部的输出可以用于文本预测/生成和分类。(图片作者,来自 《自然语言处理的迁移学习》 )
GPT 丢弃了编码器,保留了解码器和它们的自我关注子层。 来自变压器 (BERT)的双向编码器表示可以说是相反的,通过保留编码器和丢弃解码器来修改变压器架构,还依赖于屏蔽单词,这些单词随后需要作为训练度量来准确预测。BERT 如图 5 所示。
图 5。BERT 架构的高级表示,显示了堆栈编码器、输入嵌入和位置编码。在训练期间,来自 top 的输出被用于下一句预测和填空屏蔽语言建模目标。(图片作者,来自 《自然语言处理的迁移学习》 )
这些概念在书中进行了详细的讨论,在实践中的例子问题,如垃圾邮件检测,假新闻分类,列类型分类,聊天机器人,等等。
在所有这些基于语言模型的方法中——ELMo、ULM-FiT、GPT 和 BERT——都表明,生成的嵌入可以针对特定的下游 NLP 任务进行微调,只需要相对较少的标记数据点。对语言模型的关注是有意的;假设由它们诱导的假设集通常是有用的,并且已知大规模训练的数据是容易获得的。
从那时起,在前面描述的思想的基础上开发了各种新的模型——从旨在减少 BERT 的大小同时实现几乎相同的性能的模型,如 ALBERT 和 DistilBERT,到旨在处理长文档的模型,如 LongFormer 和 BigBird。
NLP 迁移学习领域目前是一个非常活跃和令人兴奋的领域,现在是学习如何利用它的好时机!
要了解更多,请查看 Sebastian Ruder 的优秀博客和拥抱脸的优秀变形金刚库。也请查看我在 GitHub 和 Kaggle 上的代表性代码示例报告。
《自然语言处理的迁移学习》的硬拷贝和电子书版本可从manning.com、亚马逊、巴恩斯&诺布尔和塔吉特获得。
为什么您应该重新考虑您的查询
了解什么是隐式连接、显式连接及其区别
托拜厄斯·菲舍尔在 Unsplash 上的照片
作为一名数据科学家,查询数据库是我日常生活的一部分。
因此,以精确的方式提供信息并构建查询以使它们易于被重新访问是至关重要的,因为这不仅减少了可能的错误,还节省了维护过程中的大量时间。
然而,为了达到这个理想的查询级别,有必要理解它们行为中的细微差别。
然而,没有人天生就是专家,我们试图一次理解一个人的细微差别,不管是出于需要,还是出于好奇,至少这是我的哲学。
介绍完毕,让我们继续挑战,考虑以下场景:
你的老板向你要一份 a 公司所有员工的名单。
您打开数据库,看到以下表格:
雇员
“作者截图”
和
角色
“作者截图”
很简单,不是吗?(我希望真正的查询在这个层次上,但是我们将关注一个简单的例子)。
您立即开始编写,得到的查询是:
SELECT Employees.ID, name, enterprise, role_ID, roles
FROM Employees
INNER JOIN Roles
ON Employees.role_ID = Roles.ID
WHERE Employees.enterprise = "A";
“作者截图”
你导出名单,交给你的老板,任务完成。恭喜你。
你的老板没有提到的是,他也把同样的任务交给了另一个同事,唯一的目的就是取笑你(毕竟谁不喜欢好的恶作剧呢!).
5 分钟后,你的老板打电话给你,向你展示你同事的解决方案,并问你:下面的问题和你的有什么不同?
SELECT Employees.ID, name, enterprise, role_ID, roles
FROM Employees, Roles
WHERE Employees.role_ID = Roles.ID
AND Employees.enterprise = "A";
没错,你的老板在跟你胡闹。
两个查询产生相同的结果!
然而,它们并不平等。
尽管如此,如果你想改变你的查询,我会试着永远驱除这种想法。
为此,让我们把它分成几个部分,你刚才看到的只是隐式连接(第二个版本)和显式连接(第一个版本)之间的区别。
这让我想到了第一点:
#1。通过使用隐式版本,您可以委托表合并选择
当你试图弄清楚信息是从哪里来的以及如何来的时,一个简单的事实是,你正在委托那个选择,这可能会导致将来的麻烦(下面有更多关于这个的信息)。
因此,如果可以选择的话,采用显式路径,这样可以保证在构造查询时选择的清晰性。
实际上,默认情况下,当使用条件(其中 Employees.role_ID = Roles)请求隐式连接时。ID 和 Employees.company = 'A ')执行内部联接。
这让我想到了第二点:
#2。如果你忘记了条件呢?
在只有两个表的场景中,这种情况不会发生,但是当我们讨论复杂的查询时,我们很容易调用多个表,因此忘记一个关系条件的可能性增加了。
当我们使用隐式连接时,默认情况下,如果没有指定条件,就会执行交叉连接,对于大多数健忘的人来说,这是表之间的笛卡尔积。
在我们的场景中,这将是一个包含按 n 个角色排列的 n 个雇员行的表。
SELECT Employees.ID, name, enterprise, role_ID, Roles.ID, roles
FROM Employees, Roles
WHERE Employees.enterprise = "A";
“作者截图”
(你有没有注意到我们从 3 排的桌子跳到了 9 排?!)
不同的是,当使用显式连接时,如果没有指定条件,查询只会返回一个错误。
#3。维护
自从你的老板对你恶作剧以来,两年过去了,他现在要求你对你的同事(现在在另一家公司)在同一时期所做的查询进行调整。
您打开查询,面对无限多的隐式连接,当您开始分析关系条件时,您注意到有一个条件没有声明。
当这样一个问题出现时:是我的前同事忘记了关系条件,还是查询实际上是正确的,他想进行交叉连接?
然而,没有人记录该查询的目标,并且您正在推断它的目标。由于你已经在公司工作了两年,你可以看到两种情况(有或没有条件)都有道理的现实,此外,现在甚至你的前同事可能都不记得你是正确的版本。
使用显式连接,因为没有条件查询将无法工作,如果确实存在交叉连接,则必须声明它,因此不会出现此问题。
此外,通过显式连接,查询变得更具可读性(谁不喜欢更愉快的阅读呢?).这样你就可以一点一点地浏览正在发生的事情。
还记得模块化代码的原理吗?
这是非常相似的,每个显式连接代表一个模块,所以如果您已经知道问题所在,您可以直接转到一个模块并更改它,而不是遍历每个条件来解开表之间的关系。
如果你仍然不相信,我有几个额外的要点:
#4。通过显式连接,您可以控制执行的顺序
#5。自从 1992 年显式连接被确立为标准以来(没错,将近 30 年前!!!)
特别是在 SQL-92 语言的第三个版本中。
(如果你的战士想要额外的挑战,你可以在这里查阅修订版)。
总而言之,在一天结束的时候,由你来质疑你自己的查询:它们是否带来了你需要的结果,是否有不准确的倾向?但最重要的是,你的目标够清楚吗??如果没有,你能说得更清楚吗,或者你需要在过程中记录任何东西吗?
请记住,第二天,你将在另一端试图解决留下的烂摊子。
所以,在这一切之后,我问你:
您将使用哪种类型的查询?
附注:你有没有想到任何其他的观点,或者你不同意以上提到的任何观点?在 Linkedin 上与我评论或交谈,让我们一起改进这篇文章。
信息来源:
1.维基百科| SQL
2.维基百科| SQL-92
4.Stackoverflow | SQL 左连接 vs 多个表 on FROM 行?
为什么智能数据科学家总是在基础数据科学面试中失败
如何抓住每一个工作机会
在 Unsplash 上由 Austin Distel 拍摄的照片
数据科学家的头衔不仅仅是放在盘子里交给纯粹的技术极客,而是实至名归的。从参加编程课程到科技盛会再到实习,成为本世纪最性感工作的专业人士并不是一件容易实现的壮举。你会同意,获得数据科学家的职业需要大量的申请、意向书、面试和考试,这些都有可能被不同的机构拒绝。
该领域的大多数专业人士都在不断寻找新的更好的机会来增加他们的经验,并在他们的银行账户上添加更多的零。有这么多合格但有限的职位,要找到那份理想的工作相当具有挑战性。IBM 最近发布的一项研究表明,全球还需要另外 28%的数据科学家来满足日益增长的需求。然而,大多数公司都倾向于在重要职位上雇佣有丰富经验的专业人士。
面试和你的技能一样重要。在面试中尽你最大的努力是你获得工作的首要条件。你花了几个月的时间准备你的作品集和申请,但是你带着焦虑的心情去参加面试,结果你把一切都搞砸了。根据我三年来进行数据科学工作面试的经验,以及顶级公司其他专业人士的研究,以下是大多数数据科学家面试失败的核心原因以及如何避免这些原因。
作者创造的形象。
默默工作
你喜欢在工作时保持安静吗?当你一个人的时候,它可能对你有用,但是当你在你潜在的雇主面前练习的时候,它肯定不会有用。大部分人编码的时候都不会大声说出来,我也懂。有点压力。但是你需要为你的面试说话和支撑你的步伐。大多数面试通常很简短,你的面试官希望实时了解你的技术、进步和行为特征。因此,如果你在这些方面有所欠缺,你的分数会大幅下降。
当被要求解决一个问题时,重复问题,以清楚地了解问题。通过这样做,你让面试官看到了解决问题时的同理心和准确性。积极地与面试官交流也为你赢得了思考的时间,并刷新了你解决问题所需技巧的记忆。
这是一个协调数据分析访谈的例子——展示工作时的互动:
“所以如果我答对了问题,你要我(重复问题)。我们在同一页上吗?
“在我继续之前,我会查看我正在处理的数字和统计数据,以防止在我进行过程中出现任何不必要的错误。
“首先,我启动我的 Jupyter 笔记本并导入依赖项,然后运行以检查错误。同时,预览数据的文件位置。这可以接受吗?
“我已经通过输入data.isnull()
检查了空值,但是我可以看到它运行缓慢并且充满了一些错误。为了不浪费任何时间,我将运行一个不同的命令,看看是否也能提高速度和效率……”
从这个例子中,你可以看到要点是如何分解的,面试官是如何随着每一步的进展而进行的。这只是技术性和交互性完美和谐工作的一个例子。更好更直接的改进方法是与你的教练、客户和同事进行多次模拟面试——熟能生巧。反馈至关重要;它们是你需要知道的最好的方法。
在准备阶段忽略面试的重要方面
为了赢得面试,你已经严格学习了编程、数据科学和/或机器学习的基础知识。你扮演了你的角色,尽你最大的努力尝试了这些问题。如果一切都那么“完美”,你为什么没有得到这份工作?我见过很多人哀叹,因为他们的质量和专业精神,他们被欺骗或被敲竹杠。不要误解我,这些人是技术天才,拥有健康的投资组合,但他们缺乏必要的技能。这些技能决定了数据科学家在压力下与团队和管理层一起工作时的效率。
找对职业技能堪比玩 俄罗斯方块设置为隐形 。因此,除了统计和算法,你还需要展示一些积极的技能来打动你的听众。
67%的人力资源专业人士表示,由于缺乏软技能,他们拒绝了一位有才华的 IT 候选人的工作邀请,原因如下。让我们面对它;没有人想雇佣一个不知道如何与该领域其他专业人士恰当互动的科技机器人。数据科学不像许多人认为的那样仅仅与数字有关。一旦你的项目完成,你需要向你的团队或上级展示你的工作。因此,一旦你的读者发现了这些基本但重要的技能中的漏洞,他们就会把你的简历从他们的办公桌上拿走——你就失去了这份工作。
大多数数据科学家未能开发和实践技能,如基本的沟通,带有一点幽默、协作、互动、无私、多才多艺和依赖。这些听起来可能没有技术诀窍重要,但它们对你的成功至关重要。在面试的前一天,读一些专业人士写的书,集中在发展专业交流上——像 TED 一样说话:卡门·盖洛 写的 9 个公开演讲的秘密是一个守护者。向你自己或最好是有共同兴趣的同事解释你对某个项目的解决方案和观察结果,也是提高沟通技巧的一个很好的练习。
未能跟上行业的最新趋势
越来越多的行业正在使用数据科学来满足他们各种复杂的业务需求-在瞬间提取和分析数据是所有公司都希望实现的现代进步。随着更多的参与和自动化技术,我们所知道的数据科学正在经历快速发展;因此,从发布之日起,及时了解最新变化是至关重要的。
物联网(IoT) 、机器学习、统计学只是数据科学的几个方面。数据无疑是一个广阔的领域,跟上最新的趋势和变化通常具有挑战性。跟上时代对我来说也很难适应——你并不孤单——这是压倒性的,每个人,不管知识如何,都在努力跟上。
准备面试时,你必须掌握与你申请的职位和整个数据科学相关的最新趋势信息。面试官会很好奇,想获得关于行业发展和其他前景的新观点。
为了加快您的旅程,以下是数据科学家如何保持自我更新的列表:
- 参加会议:会议和技术聚会是向其他专业人士学习和获取对当前话题的看法的好方法。如果你需要最新的科技发展,那就开始参加会议吧。
- **推特:**如今每个人都有智能手机;信息的移动性是好处之一。行业内的公司和顶级科学家使用微博平台将信息快速传递给更广泛的受众。如果你是新手,你会对你错过的大量有趣的数据科学更新感到惊讶。@GoogleAI、@OpenAI、@AndrewYNg、@KDNuggets、@Goodfellow_Ian 和其他人是我在旅途中获取更新的首选来源。
谷歌人工智能展示数据集的更新。作者截图
- **时事通讯:**你可能会因为你的“电子邮件隐私政策”而对此不以为然,但是订阅几份时事通讯总是个好主意。你可以从网上博客和出版物中找到好的时事通讯。如果你和我一样,不喜欢每日时事通讯,那么像走向数据科学这样的出版物每周都会让我了解最新消息。
最终想法
完成一项认证或四年的课程会让你成为一名数据科学家,但不是一名称职的数据科学家。公司需要不仅仅会编程的应聘者。数据科学、数据工程、DevOps 工程、人工智能领域的职业生涯都是基于棘手的面试。但好消息是,通过适量的练习、积极的态度和不断学习的动力,这些问题很容易克服。如果你正在为下一次面试做准备,或者正在寻找磨练和掌握这种技能的方法,这里有一些小贴士可以指导你:
1.事先对你申请的公司和职位进行调查。
2.互动。互动酝酿伟大的关系。
3.你的语言要精确而广博。我认为所有的数据科学家都必须具备 Python、R 和 SQL 方面的高深知识。
4.面试时,边练习边解释你的模型。带着你的听众——包括技术性和非技术性的。
5.最重要的是,要诚实。不要用你不完全熟悉的技术、语言或工具填充你的应用程序。
为什么坚实的原则不是软件设计的坚实的解决方案
软件世界
应用坚实的原则是一个目标,而不是命运
obert J. Martin 在 2000 年介绍了坚实的原则,当时面向对象编程是程序员的艺术。每个人都想设计一些持久的东西,可以尽可能地重复使用,在未来只需要最小的改变。固体是它的完美名字。
事实上,当我们能够区分什么将会保留,什么将会改变时,面向对象编程工作得最好。坚实的原则有助于倡导这一点。
我个人喜欢坚实的原则背后的想法,并从中学到了很多。
然而…
有一个主要的挑战,所有的软件都意味着改变。要预测变化真的很难,如果不是不可能的话。因此,对我们来说,很难明确界定什么会保持不变,什么会改变。
为了说明这个挑战如何影响坚实的原则,让我们来看看每一个原则。
单一责任原则
"一个类的改变不应该有一个以上的原因."换句话说,每个类应该只有一个责任。
让我们假设,我们的程序需要一个计算函数。这个班的唯一职责就是计算。
class Calculate {
fun add(a, b) = a + b
fun sub(a, b) = a - b
fun mul(a, b) = a * b
fun div(a, b) = a / b
}
对某些人来说,这是完美的,因为它只有一个责任,即计算。
但有人可能会反驳说:“嘿!它做 4 件事!加减乘除!”
谁是对的?我会说视情况而定。
如果你的程序只使用Calculate
来执行计算,那么一切都好。进一步抽象化将会过度工程化。
但是谁知道呢,将来可能有人只想做加法运算而不需要通过Calculate
类。那么上面需要改!
单一责任的定义取决于程序的上下文,并且会随着时间的推移而改变。我们现在可以实现这个原则,但不能永远实现。
开闭原理
“软件实体…应该对扩展开放,但对修改关闭.”
这个原则是一个理想主义的原则。它假设一旦一个类被编码,如果编码正确,就不需要再修改了。
让我们看看下面的代码
interface Operation {
fun compute(v1: Int, v2: Int): Int
}class Add:Operation {
override fun compute(v1: Int, v2: Int) = v1 + v2
}class Sub:Operation {
override fun compute(v1: Int, v2: Int) = v1 - v2
}class Calculator {
fun calculate(op: Operation, v1: Int, v2: Int): Int {
return op.compute(v1, v2)
}
}
上面有一个接受操作对象进行计算的Calculator
类。我们可以轻松地用 Mul 和 Div 操作进行扩展,而无需修改Calculator
类。
class Mul:Operation {
override fun compute(v1: Int, v2: Int) = v1 * v2
}class Div:Operation {
override fun compute(v1: Int, v2: Int) = v1 / v2
}
很好,我们实现了开闭原则!
但是有一天,一个新的需求进来了,说他们需要一个叫逆的新操作。它只需要一个操作符,比如 X,然后返回 1/X 的结果。
到底谁能想到这个会进来?我们已经将操作界面的计算功能固定为 2 个参数。现在我们需要一个只有 1 个参数的新操作。
现在怎样才能避免修改计算器类?如果我们事先知道这一点,我们可能就不会这样编写计算器类和操作接口了。
变化永远不可能完全计划好。如果只能完全计划好,我们可能就不再需要软件了:)
利斯科夫替代原理
“使用指向基类的指针或引用的函数必须能够在不知道的情况下使用派生类的对象.”
当我们小的时候,我们学习动物的基本属性。他们是可移动的。
interface Animal {
fun move()
}class Mammal: Animal {
override move() = "walk"
}class Bird: Animal {
override move() = "fly"
}class Fish: Animal {
override move() = "swim"
}fun howItMove(animal: Animal) {
animal.move()
}
这符合利斯科夫替代原理。
但是我们知道上面所说的并不正确。一些哺乳动物游泳,一些飞行,一些鸟类行走。所以我们改成
class WalkingAnimal: Animal {
override move() = "walk"
}class FlyingAnimal: Animal {
override move() = "fly"
}class SwimmingAnimal: Animal {
override move() = "swim"
}
酷,一切还好,因为我们下面的功能还可以用动物。
fun howItMove(animal: Animal) {
animal.move()
}
今天,我发现了一些事情。有些动物根本不动。它们被称为无柄的。也许我们应该换成
interface Animal interface MovingAnimal: Animal {
move()
}class Sessile: Animal {}
现在,这将打破下面的代码。
fun howItMove(animal: Animal) {
animal.move()
}
我们没有办法保证永远不会改变howItMove
的功能。基于我们在那个时间点所了解的情况,我们可以做到这一点。但是当我们意识到新的需求时,我们需要改变。
即使在现实世界中,也已经有如此多的例外。软件世界不是真实的世界。一切皆有可能。
界面分离原理
“许多特定于客户端的接口比一个通用接口要好。”
再来看看动物界。我们有一个动物界面如下。
interface Animal {
fun move()
fun eat()
fun grow()
fun reproduction()
}
但是,正如我们上面意识到的,有一些动物是不动的,这种动物叫做无柄动物。所以我们应该把move
功能分离出来作为另一个接口
interface Animal {
fun eat()
fun grow()
fun reproduction()
}interface MovingObject {
fun move()
}class Sessile : Animal {
//...
}class NonSessile : Animal, MovingObject {
//...
}
然后我们也想有植物。也许我们应该把grow
和reproduction
分开
interface LivingObject {
fun grow()
fun reproduction()
}interface Plant: LivingObject {
fun makeFood()
}interface Animal: LivingObject {
fun eat()
}interface MovingObject {
fun move()
}class Sessile : Animal {
//...
}class NonSessile : Animal, MovingObject {
//...
}
我们很高兴,因为我们尽可能多地分离出特定于客户端的接口。这看起来是一个理想的解决方案。
然而,有一天,有人哭了,“歧视!有些动物不育,并不意味着它们不再是有生命的物体!”。
看来我们现在必须将reproduction
从LivingObject
接口中分离出来。
如果我们这样做,我们实际上每个接口都有一个功能!它非常灵活,但如果我们不需要如此精细的分离,它可能会过于灵活。
我们应该把我们的接口分离得多好,取决于我们程序的上下文。不幸的是,我们节目的背景会不时改变。因此,我们也应该继续重构或分离我们的接口,以确保它仍然有意义。
依赖性倒置原则
“依靠抽象,而不是具体.”
这个原则是我喜欢的,因为它是相对普遍正确的。它应用了独立依赖解决方案概念的思想,其中软件实体虽然依赖于一个类,但仍然独立于它。
如果我们要严格地实践这一点,任何东西都不应该直接依赖于一个类。
让我们看看下面的例子。它确实应用了依赖性倒置原则。
interface Operation {
fun compute(v1: Int, v2: Int): Int
fun name(): String
}class Add:Operation {
override fun compute(v1: Int, v2: Int) = v1 + v2
override fun name() = "Add"
}class Sub:Operation {
override fun compute(v1: Int, v2: Int) = v1 - v2
override fun name() = "Subtract"
}class Calculator {
fun calculate(op: Operation, v1: Int, v2: Int): Int {
println("Running ${op.name()}")
return op.compute(v1, v2)
}
}
Calculator
不依赖于Add
或Sub
。但这使得Add
和Sub
反而依赖于Operation
。看起来不错。
然而,如果有人从 Android 开发组使用它,它有一个问题。println
在安卓系统中不工作。我们将需要Lod.d
来代替。
要解决这个问题,我们还应该让Calculator
不直接依赖于println
。相反,我们应该注入一个打印接口
interface Printer {
fun print(msg: String)
}class AndroidPrinter: Printer {
override fun print(msg: String) = Log.d("TAG", msg)
}class NormalPrinter: Printer {
override fun print(msg: String) = println(msg)
}class Calculator(**val printer: Printer**) {
fun calculate(op: Operation, v1: Int, v2: Int): Int {
**printer.print("Running ${op.name()}")**
return op.compute(v1, v2)
}
}
这解决了问题,同时满足依赖性反转原则。
但是如果 Android 永远不需要使用这个Calculator
,而我们提前创建了这样一个界面,我们可能已经违反了 YAGNI 。
TL;DR;
让我重申,对我来说,坚实的原则是软件设计解决方案的好原则,值得我们去追求。当我们在那个时间点很好地知道什么是固定的,什么可能会改变时,这尤其有用。
然而,变化的发生超出了我们的预料。当这种情况发生时,新的需求将使我们最初的设计不再坚持坚实的原则。
这是正常的。会发生的。我们只需要应用新的需求,并在时间点上再次改变它,重新巩固它。
软件的本质是软的,把它做实才是硬的。对于软件来说,应用坚实的原则是一个目标,而不是命运。
为什么开始使用 sktime 进行预测?
实践教程
sktime 区别于其他预测框架的特性概述
预测的作用
企业主面临的挑战之一是预测未来的市场状况。预测有助于做出明智的决策,并形成对结果的现实预期。这种对预测的需求导致了预测工具的不断发展。它们能够通过从过去的观察中获取有用的信息来预测未来的事件。最近的一些预测框架包括脸书的 Prophet ,优步的 Orbit ,或者 Linkedin 的 Greykite 。然而,大多数 Python 预测包关注于特定的模型族,例如,广义加法模型或统计模型。Sktime 旨在填补这些预测工具之间的空白。
什么是 sktime?
Sktime 是一个用于时间序列建模的开源工具箱。它结合了分布在许多 Python 库中的功能。它还增加了自己独特的预测功能。它允许我们为时间序列训练、微调和评估模型。它与 scikit-learn 兼容。该框架还支持例如时间序列分类、特征提取和时间序列聚类。要获得完整的特性列表,请查看 sktime 的文档。本文主要关注预测以及 sktime 如何让整个过程变得更简单。这是 sktime 预测功能的实际演练。但是首先,让我们快速浏览一下本文中使用的数据。
数据概述
所有代码示例都基于 statsmodels 库中的公共数据集。它包含了 1959 年至 2009 年间美国季度宏观经济数据。数据集的完整描述可在此处获得。我们将重点预测实际国内生产总值。
数据概述
一段时间内的宏观经济指标。作者图片
Sktime 对用于存储时间序列的数据结构施加了某些限制。您可以在下面找到宏观经济数据导入和转换。
但是重点是…
为什么要用 sktime 做预测?
1)它在一个统一的 API 下结合了许多预测工具
Sktime 汇集了许多预测库的功能。在此基础上,它提供了一个统一的 API,与 scikit-learn 兼容。
在这种情况下,统一 API 的优势是什么?以下是一些主要原因:
- 它允许用户轻松实现、分析和比较新模型。
- 由于预测者的明确分类,它有助于避免在选择适当的算法时出现混乱。
- 它使工作流程可读性和可理解性,因为所有预测者共享一个公共界面。它们在单独的类中实现,就像在其他工具箱中一样,包括 scikit-learn。
- 它可以改变工作流程中的预测者。这使我们不必在每次改变模型时调整代码的结构。
Sktime 的预测者分享了至关重要的 scikit-learn 的方法,比如 fit() 和 predict() 。下面的代码显示了一个基本的预测工作流。
**Output:**
2002Q2 11477.868
上面的代码生成一步预测。这就是我们将其中一个分配给预测范围的原因。现在让我们关注指定地平线的不同可能性。
预测范围可以是一组相对值或绝对值。绝对值是我们想要生成预测的特定数据点。相对值包括将进行预测的步骤列表。如果我们使用 update_predict() 方法进行滚动预测,相对预测范围尤其有用。这使我们不必在每次生成预测时更新绝对范围。当我们添加新数据时,相对范围保持不变。
我们也可以将相对地平线转换成绝对地平线,反之亦然。从绝对值到相对值的转换尤其值得一提。它不仅仅产生一个步骤编号列表。这些值与培训系列的最后日期相关。这意味着如果值为负,则它们是样本内预测。这一功能非常重要,因为预测者可以为每一步设定不同的参数。下面的代码显示了预测范围之间的差异。
**Output:**
Absolute FH: ForecastingHorizon(['2002Q2', '2002Q3', '2002Q4', '2003Q1', '2003Q2', '2003Q3','2003Q4', '2004Q1', '2004Q2', '2004Q3', '2004Q4', '2005Q1', '2005Q2', '2005Q3', '2005Q4', '2006Q1', '2006Q2', '2006Q3', '2006Q4', '2007Q1', '2007Q2', '2007Q3', '2007Q4', '2008Q1', '2008Q2', '2008Q3', '2008Q4', '2009Q1', '2009Q2', '2009Q3'], dtype='period[Q-DEC]', name='date', is_relative=False)
Relative FH ahead: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
Relative FH in-sample: [-29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0]
预测层位对比。作者图片
现在让我们深入了解一下 sktime 提供的一些常见接口功能。首先,指定和训练模型的过程被拆分为单独的步骤。在拟合模型之前,我们指定预测者的参数。在单变量时间序列的情况下, fit() 方法接受训练序列。对于一些预测者,例如directtabularregressionpredictor或directtimeseriesregressionpredictor,它还包括预测范围。对于其他人,预测范围可以在 predict() 方法中互换。下面是一个使用 AutoARIMA 预测单变量时间序列的示例。
用单变量序列进行预测。作者图片
Sktime 还允许使用外生变量进行预测。有了多元外生时间序列,拟合参数范围更广。它包括一个训练序列和一个带有外生变量的数据帧。与单变量时间序列一样,一些预测者需要参数中的预测范围。在下面的代码中,我们使用外生变量 realinv 的滞后值来预测 realgdp 的值。
用外生变量进行预测。图片作者。
除了拟合,sktime 还使能够用新数据更新预测者。这允许我们自动更新预测的截止时间,因此我们不需要在每次添加新数据时自己改变范围。截止值设置为新训练系列中的最后一个数据点。这种方法允许我们更新预测器的拟合参数。
通用接口适用于所有型号系列。Sktime 包括一系列易于使用、集成良好的预测工具。以下是目前在 sktime 中实现的预测器列表:
- Holt-Winter 的指数平滑,Theta 预测器,和 ETS(来自 statsmodels),
- ARIMA 和 AutoARIMA(来自 pmdarima),
- 蝙蝠和 tbats(来自 TBATS),
- 先知预报员(来自 fbprophet),
- 多项式趋势预测器,
- 克罗斯顿的方法。
Sktime 还允许使用 scikit-learn 的机器学习模型来建模时间序列。这就引出了 sktime 的下一大优势。
2)它提供了针对时间序列问题调整的机器学习模型
我前面提到过,sktime 的 API 兼容 scikit-learn。这意味着有可能采用许多 scikit-learn 的功能。Sktime 允许我们使用 scikit-learn 的机器学习模型来解决预测问题。
但是为什么我们不能使用 scikit-learn 中可用的标准回归模型呢?事实上,我们可以,但是这个过程需要大量的手写代码,并且容易出错。主要原因是这两种学习任务之间的概念差异。
在表格 回归中,我们有两种类型的变量——目标和特征变量。我们基于特征变量预测目标变量。换句话说,模型从一组列中学习,以预测不同列的值。这些行是可以互换的,因为它们是相互独立的。
在预测中,我们只需要有一个单变量。我们根据它的过去值来预测它的未来值。也就是说,模型预测同一列的新行。这些行不可互换,因为未来值取决于过去值。因此,即使我们用一个外生变量进行预测,这仍然不是一个回归问题。
表格回归与预测。作者图片
这两个问题之间的区别非常明显。但是在预测问题时使用回归模型有什么风险呢?以下是一些原因:
- 它产生了评估预测模型的问题。使用 scikit-learn 的训练测试分割会导致数据泄漏。在预测问题中,行是相互依赖的,所以我们不能随意打乱它们。
- **转换数据进行预测的过程容易出错。**在预测任务中,我们经常从多个数据点汇总数据或创建滞后变量。这种转换需要大量的手写代码。
- 时序参数难以调整。像滞后大小或窗口长度这样的值不作为 scikit-learn 估计器的参数公开。这意味着我们需要编写额外的代码来调整它们以适应我们的问题。
- 生成多步预测很棘手。让我们考虑生成未来 14 天的预测。scikit-learn 的回归变量根据最后一次观察值进行 14 次预测。这不是我们想要做的。我们希望我们的预测者在每次生成预测时更新最近的已知值。也就是说,每个预测应该基于不同的数据点。
Sktime 允许使用回归模型作为预测器的组成部分。由于 T21 的缩减,这是可能的。
归约是用一个算法来解决一个学习任务的概念,这个学习任务不是为它设计的。它是从复杂的学习任务到简单的学习任务的过程。
我们可以使用归约将预测任务转化为表格回归问题。这意味着我们可以使用 scikit-learn 的估计器来解决预测任务,例如随机森林。
还原过程中的关键步骤是:
- 使用滑动窗口方法将训练集分成固定长度的窗口。
举个例子,如果窗口长度等于 11,则过程如下:第一个窗口包含第 0-10 天的数据(其中第 0-9 天成为特征变量,第 10 天成为目标变量)。第二个窗口包含第 1-11 天的数据(其中第 1-10 天成为特征变量,第 11 天成为目标变量),等等。
- 把那些窗户一个接一个的排列起来。这为我们提供了表格形式的数据,特征变量和目标变量之间有明显的区别。
- 使用以下策略之一-递归、直接或多输出,来生成预测。
使用回归模型进行预测。图片来自 sktime 的文档 。
现在让我们看一些代码,用回归器组件执行预测。
在我们的例子中,sktime 的方法 make_reduction() 使用 scikit-learn 的模型创建了一个基于 reduction 的预测器。它接受一个回归变量,预测策略的名称和窗口长度。它输出一个可以像任何其他预测器一样拟合的预测器。您也可以使用directtabularregressionpredictor对象将预测问题简化为表格回归任务。然而,这位预测者使用直接策略进行缩减。
值得一提的是,**缩减的参数可以像任何其他超参数一样进行调整。**这就把我们带到了 sktime 的下一个优势,就是评估模型。
3)它能够快速、无痛苦地评估预测模型
评估预测模型不是一项简单的任务。它需要跟踪与标准回归问题不同的指标。它们并不总是容易实现,例如平均绝对标度误差(MASE)。这些模型的验证也很棘手,因为我们无法将数据分成随机的子集。最后,调整预测器的参数,例如窗口长度,需要大量的手写代码,并且容易出错。Sktime 解决了与评估预测模型相关的三个主要问题。
Sktime 允许通过 回测对预测者进行评估。这个过程包括将我们的数据分成时间训练集和测试集。重要的是,测试集包含训练集之前的数据点。剩下的过程就是我们从 scikit-learn 了解到的。我们在测试集上生成预测,并计算度量。然后我们将预测值与实际值进行比较。
Sktime 提供了几个特定于预测模型的性能指标。例如,它们包括平均绝对标度误差(MASE)或平均绝对百分比误差(MAPE)。您可以通过两种方式调用这些指标——或者通过调用一个函数,或者调用一个类。使用类接口提供了更多的灵活性。例如,它允许您更改指标的参数。更棒的是, *sktime 还提供了使用*make _ forecasting _ scorer()函数轻松实现自定义计分器。定义自定义指标和评估模型的示例如下所示。
**Output:**
custom MAPE: 0.05751249071487726
custom MAPE per row:
date
2002Q2 0.001020
2002Q3 0.003918
2002Q4 0.002054
2003Q1 0.004020
2003Q2 0.009772
Freq: Q-DEC, dtype: float64
在测试集上评估我们的模型并不总是最优的解决方案。有没有办法让交叉验证适应预测问题?答案是肯定的,而且 sktime 做得相当不错。提供基于时间的交叉验证。
它支持使用两种方法分割数据进行交叉验证。它们包括扩展窗口和滑动窗口。在扩展窗口中,我们在每次运行中将训练集扩展固定数量的数据点。这样,我们就创建了多个训练测试子集。这个过程一直进行到训练集达到指定的最大大小。在滑动窗口中,我们保持训练集的固定大小,并在数据中移动它。
我们可以在 evaluate() 方法中指定时态交叉验证拆分器。除了选择窗口类型,我们还可以指定添加新数据的策略。我们可以通过改装或更新我们的模型来做到这一点。下面是一个使用扩展窗口执行交叉验证的示例。
扩展窗口交叉验证。作者图片
最后,sktime 提供了几种调优模型超参数的方法。它还支持调整特定于时间序列的参数。目前,sktime 提供了两个调优元预测器: ForecastingGridSearch 和ForecastingRandomizedSearch。像在 scikit-learn 中一样,它们通过用一组不同的参数训练和评估指定的模型来工作。ForecastingGridSearch 评估超参数的所有组合。预测随机搜索只测试其中固定大小的随机子样本。Sktime 为各类预报员提供参数调谐。这也包括带有回归成分的预测。
什么是伟大的,我们还可以 调整嵌套组件的参数。它的工作方式与 scikit-learn 的管道完全一样。我们通过访问由 get_params() 方法生成的字典中的键来做到这一点。它包含与预测者的超参数相关的特定键值对。键名由两个元素组成,由双下划线连接,例如*estimator__max_depth*
。第一部分是组件的名称。第二部分是参数的名称。
在下面的示例中,我们使用 ForecastingRandomizedSearchCV 调整随机森林回归器的参数。
**Output:**
{'window_length': 2, 'estimator__max_depth': 14}
0.014131551041160335
优化嵌套参数是 sktime 提供的复杂用例之一。现在让我们深入到 sktime 解决的其他复杂问题。
4)它为复杂的预测问题提供了新的功能
复杂的预测问题也有 sktime 支持。它提供了各种各样的转换器,可以在拟合模型之前改变我们的时间序列。它还允许我们建立管道,连接变压器和预报员。此外,它还提供了自动化的模型选择。它比较了整个模型族和转换类型。最后,它使集合预报成为可能。
我们现在将分别关注每个功能。先说变形金刚。为什么我们甚至需要预测中的转换?首先,主要目标是去除过去时间序列中观察到的复杂性。此外,一些预测器,尤其是统计模型,在拟合之前需要特定的转换。一个例子是 ARIMA 模型,它要求时间序列是平稳的。 **Sktime 提供种类繁多的变形金刚。**其中一些是:
- Detrender —从时间序列中去除趋势,
- 去季节化器 —从时间序列中去除季节模式,
- BoxCoxTransformer —将时间序列转换为类似正态分布,
- HampelFilter —检测时间序列中的异常值,
- tabulartoseriesadapter—将表格转换适配到序列(例如,适配 scikit-learn 的预处理功能)。
请务必检查所有这些,因为可用的变压器列表仍在增长。Sktime 提供了与 scikit-learn 中类似的方法。它们包括 fit()、transform() 和 fit_transform() 。一些转换器也共享 inverse_transform() 方法。它能够访问与初始时间序列相同规模的预测。
下面的代码显示了一个转换时间序列和反转操作的示例。
反向转换后的预测。图片作者。
Sktime 允许将变压器与预测器链接起来,以获得单个预测器对象。这可以使用管道来完成。Sktime 提供了一个转型的 TargetForecaster 类。它是一个管道对象,旨在结合任意数量的转换器和预测器。它可以将多步操作减少到一步。您可以在管道中使用任何类型的预测器。
Sktime 还允许为带有外生变量的时间序列构建管道。它提供了另一个管道对象,预测管道。这种管道能够实现外生变量和目标时间序列的转换。
下面你可以找到一个用外源数据构建管道的例子。
既然您有几个要测试的转换和预测器,您可能想知道它们中的哪一个最适合您的问题。Sktime 提供了一个简单的方法来回答这个问题。启用 autoML ,即自动选择型号。这可以通过使用多重预测器类来完成。这个类的对象接受一个预测列表作为参数。你可以用它来找到一个表现最好的预测者。它可以与 ForecastingGridSearch 和 ForecastingRandomizedSearch 一起使用。你可以在下面找到一个例子。
**Output:**
{'selected_forecaster': 'ets'}
Sktime 还支持自动选择管道中使用的转换。它提供了一个可选直通变压器。它接受另一个 transformer 对象作为参数。这使我们能够验证所选择的转换是否提高了模型的性能。然后,OptionalPassthrough 对象作为管道中的一个步骤进行传递。我们现在可以将这些传递超参数添加到网格中,并应用交叉验证技术。我们还可以评估变压器的参数。
最后, sktime 支持 集合预报。您可以将一个预测者列表传递给ensemble predictor,然后使用它们来生成预测。如果您选择不同系列的型号,此功能尤其有用。预测者是平行的。他们每个人都有自己的预测。之后,默认情况下对它们进行平均。您可以通过指定 aggfunc 参数来更改聚合技术。
下面你可以找到一个集合预报的例子。
**Output:**
[TBATS(), AutoARIMA()]
复杂功能的列表仍在增长。这就引出了我想提到的最后一个优势。
5)它是由一个活跃的社区开发的
对于成熟的图书馆来说重要的是,一个多元化的社区已经积极地致力于这个项目。最新版本(v. 0.7.0)于 2021 年 7 月发布。它引入了一些特性,如带有外生变量的管道或克罗斯顿方法。预测目前被标记为一个稳定的功能。但是仍然有一个未来步骤的列表。它们包括预测区间和概率预测。此外,未来还将增加多变量预测。也有计划包括测试模型性能之间的显著差异。
**Sktime 很容易扩展。**它提供扩展模板来简化添加新功能的过程。还有一个预测者的扩展模板。它使得本地实施新的预测和对 sktime 的贡献变得容易。如果你有兴趣参加这个项目,我们非常欢迎你参加。你可以在这里找到关于贡献的所有信息。
奥利弗·帕斯克在 Unsplash 上拍摄的照片
最终注释
在我看来, sktime 是一个全面的工具包,在很大程度上改善了 Python 中的预测体验。它简化了训练模型、生成预测和评估预测者的过程。它还能够解决复杂的预测问题。此外,它采用 scikit-learn 接口模式来预测问题。该软件包仍在开发中,但即使是现在,它也是一个很好的预测选择。
资源
- 示例笔记本
- l ning,m .,Király,F. (2020)使用 sktime 进行预测:设计 sktime 的新预测 API,并将其用于复制和扩展 M4 研究
- sktime 的文档
- sktime 的 github
- sktime 的教程——预测
- sktime 的教程—使用 sklearn 进行预测及其缺点
- Hyndman,R.J .,Athanasopoulos,G. (2021)预测:原理与实践,第三版,OTexts:墨尔本,澳大利亚。OTexts.com/fpp3.于 2021 年 7 月 20 日登陆。
感谢您的阅读!我非常感谢你对这篇文章的反馈——你可以通过 Linkedin 联系我。此外,请使用参考资料中链接的我的示例笔记本随意体验一下 sktime 的特性。