设计与商业软件集成的对话式人工智能的最佳实践
作者图片
介绍
在这篇文章中,我将尝试描述设计与后端软件集成的对话式人工智能。
真实的例子:创建一个由雇员添加时间活动的机器人。使用时间活动,您可以指定日期、在某项任务上花费的时间、将其分配给项目或客户,此外,还可以指定每小时的费率以及是否计费。
步骤 1 —定义意图
在许多情况下,为了设计意图,我试图与机器人的未来用户沟通。您可以写一个故事,解释您请求的目的,以提供不同的话语(意图)示例,他们可以在 bot 中使用这些示例来添加新的时间活动。这一步骤旨在获得来自用户的实时示例,这不仅是为了训练意图和获得更高的置信度,也是为了以最合适的方式设计机器人。
当然,您可以自己设计话语,并开始设计流程,但最终,这可能会导致额外的工作,因为您需要重新构建一切。
例如,你可以设计接下来的话语(意图):
作者图片
而当用户开始使用你的 bot 的时候,你会发现他们会尝试使用其他的话语,很多时候不会像你设计的那么简单。它们可能看起来像这样:
作者图片
上面的例子给了我们很多启示。首先,我们发现这些话语包括像“今天”、“我”、“7 小时”和客户“迪士尼”这样的上下文变量。如果这个人想在最初的信息中提供所有需要的信息,我们需要自动处理它们。在这种情况下,我们不需要要求用户提供关于时间活动的日期、谁执行了时间活动、花费的时间和客户的信息。
当我说我们不需要问额外的问题时,我的意思是:
作者图片
你需要自动识别所有的上下文变量,不要问不必要的问题,因为这会导致糟糕的用户体验。
所以现在,当你有了不同话语的例子,你可以开始设计实体,命名实体识别,对话流,以及与第三方软件的集成。
步骤 2-定义实体
基于用户的话语实例,我们可以起草实体的第一个版本来自动识别上下文变量。有些我们可以轻松处理,有些需要更多的工作。
几乎所有提供开发机器人功能的平台( IBM Watson Assistant 、 Google Dialogflow 、 Amazon Lex )都包括识别日期、数字、时间、货币等的系统实体。
你需要激活它们,你的机器人会识别下一个数据:“今天”、“7 小时”,可能还有“迪士尼”最后一个不太清楚,因为它是一家知名公司,有些平台有识别组织名称的功能,有些没有。此外,您需要考虑到世界上有许多不同的公司名称,可能看起来像“Freezman sporting goods”或“Amy Rudchuk Company”等,在这种情况下,系统实体将不会识别它们或以错误的方式识别它们。
同样,如果我们想一想来自用户的这样的话语:“约翰·史密斯今天和艾米·鲁楚克公司呆了 7 个小时”。
其中“John Smith”是执行时间活动的公司的员工,“Amy Rudchuk company”是客户。这是一个更复杂的例子,因为系统实体可以返回几个对象,例如, entity.person-John Smith 和 entity.person-Amy Rudchuk 。
这是你可以用不同的选择来解决的挑战。这也取决于你用于 bot 开发的平台。
例如,在 IBM Watson Assistant 中,您可以找到实体注释的功能。例如,如果你想让沃森理解所有的名字,你至少要在十个例子中标注名字。这些句子可能包括“我的名字是玛丽·史密斯”,或者“他们叫我约瑟夫·琼斯”。选择每个名称将其高亮显示,然后从弹出菜单中创建或选择一个名为“name”的实体。从现在开始,沃森将理解它以前从未见过的名字,但这些名字被用在相似的句子中。你可以在这里阅读更多关于注释的内容。
作者图片| IBM Watson 助手的用户界面
在 Google Dialogflow 中,您可以使用自动扩展的功能,这可以为自定义实体类型启用自动扩展。启用后,您的代理可以识别尚未明确提供的值。除此之外,您还可以应用模糊匹配和正则表达式实体。
图片作者| Google dialog flow 的用户界面
而有了 Amazon Lex,你可以使用槽的默认功能。除此之外,你可以尝试使用亚马逊理解服务。
图片作者|亚马逊 Lex 的用户界面
尽管如此,您会发现在定义实体时存在一些限制,并且识别的可信度会有所不同。这里的要点是,您可以在一些简单的情况下预定义所有可能的实体,并且您的 bot 可以以最高的置信度识别它们。但是在某些情况下,当您不能预测实体的所有可能的例子时,您需要找到一种方法来利用每个平台的功能进行自动识别。还有一些独立的服务可以帮助您在非结构化文本中识别您所在行业特有的实体和关系。其中一项服务是 IBM 沃森知识工作室。
如果您还记得一些上下文变量(实体值)在默认情况下是被验证的,那将会很有帮助。例如,如果它是一个日期,默认情况下会进行验证,这意味着您不需要执行额外的步骤来验证您是否可以使用该上下文变量中的值。对于客户名称案例,我们需要执行额外的验证,这不是强制性的,但是为了构建更好的用户体验,我们在所有的项目中都执行了这个步骤。
步骤 3-验证实体(可选)
为什么我们需要这一步?在我们的例子中,用户可以提供任何客户名称,我们需要在后端验证它是否存在。假设您正在使用一些企业软件,其中有所有客户的注册信息。因此,在与用户进行对话之前,您需要获取客户名称的上下文变量的值,并在后端检查它。
如果您不执行此操作,您将引导用户直到对话结束,当您试图在您的后端软件中创建时间活动时,您将得到这样一个错误:这样一个客户不存在。对于用户来说,这意味着他或她需要再次重复所有的过程。他们还需要访问企业软件,检查客户的准确姓名,然后重试。这个不适用!这是你在设计机器人时可能面临的最糟糕的情况。
所以现在您需要将 API 发送到后端来验证客户是否存在。如果您感兴趣,我将在另一篇文章中描述通过 API 与后端进行技术集成的选项。尽管如此,我还是想描述一下您在将数据发送到后端时可能面临的挑战。
作者图片
当您将 API 发送到后端以验证客户的名称是否存在于后端时,您将需要评估至少三种不同的响应类型,并设计对话流来处理每一种类型。
选项 1 —一对一匹配。你找到了一个顾客。一切都好。您确信客户存在,并且您可以与用户一起创建时间活动。
选项 2 —存在一对多匹配。你找到了不止一个顾客。在这种情况下,我们建议用户选择应该选择哪个客户。我们可以这样做,因为你将获得关于那些客户的信息,并且你可以向用户显示快速回复按钮。之后,用户可以选择客户,您可以继续。
作者图片
选项 3 —您可以得到空响应,这意味着没有客户匹配上下文变量值。现在,您可以建议用户从整个客户列表中选择客户。
作者图片
此外,您可以评估来自后端的更多响应:情况 1 —当我们从后端接收到错误时,以及情况 2 —当与后端的集成离线时。
未完待续…
点击率模型的 ML 可观察性的最佳实践
作者图片(阿里泽·艾)
在假期及以后保持点击量的小贴士
今年数字广告总支出预计将达到 4553 亿美元。其中,55.2%将用于展示广告,40.2%将用于搜索。随着数字格式占据了广告收入的最大份额,营销人员需要不断优化他们活动的效果。点击率(CTR)是广告商用来帮助量化数字广告效果的一个指标。对于直接回应广告客户来说,点击通常是消费者在线购买的第一步,或者在离线销售数据不可用或难以归因于给定广告的情况下,是购买意图的良好代理。
点击率的计算方法是将点击次数除以印象次数,并将结果表示为百分比。根据最近的基准,所有行业的 Google AdWords 的平均点击率在搜索网络上是 3.17%,在显示网络上是 0.45%。
多年来,机器学习(ML)系统在有效预测点击概率的能力方面变得更加复杂。影响点击率的因素很多,从上下文相关性(广告在哪里投放,在页面上的位置,广告形式等等。)到用户属性(一个人正在使用哪种设备和他们的位置或更深入的第一方人口统计数据、购物历史、媒体消费习惯等数据)。
了解广告选择流程
为了更好地理解机器学习系统如何适应广告生态系统,让我们仔细看看广告选择过程。
超过 90% 的展示和搜索广告是通过编程方式进行交易的。当用户加载网页或应用程序(例如,纽约时报、Expedia、ESPN)或搜索引擎时,该过程开始。然后,向广告交换发送一个请求,其中包含诸如 URL、发布者名称、在页面上的位置、设备、匹配关键字等信息,以及其他帮助广告商更好地锁定特定受众的信息。广告交换然后通过需求侧平台(DSP)将请求提交给多个广告客户。具有匹配标准的广告的广告客户通过发出投标进入拍卖。然后进行拍卖,广告印象归出价最高者所有,广告随后出现在页面上。所有这些都发生在页面加载前的几毫秒内,用户不会察觉。如果用户对广告感兴趣,他们可以点击或采取其他行动;如果没有,他们可能只是滚动过去,或者根本没有注意到它。
ML 驱动的系统存在于交易的双方,提高了出版商的收益和广告商的 T4 业绩。尽管点击率是这篇文章的重点,也是最常用和最容易衡量的关键性能指标之一,但应该注意的是,存在各种各样的模型来优化一切,从电视规划到特定受众,再到视频广告可视性和最大限度地减少僵尸网络流量。
图片来源:Arize AI,IAB |广告技术生态系统
CTR 模型特有的挑战
随着 CTR 模型投入生产,一些常见的挑战可能会导致性能低于预期。其中包括:
- 未知的新趋势: CTR 模型通常根据特定网站(即前 1000 家最受欢迎的新闻发布商)的历史数据以及其他输入进行训练。如果广告交换开始发送对不属于原始训练数据的新的流行网站的投标请求,则广告可能最终被放置在与广告的上下文不一致的页面上,从而导致较低的点击率。这方面的一个例子可能是当 Vice 或 Buzzfeed 等网站开始受欢迎,而人们对广告在这些网站上的表现知之甚少。
- **一天中的时间或季节波动:**一些搜索关键词或显示广告在一年中的某些时段可能或多或少相关,或者在上午与下午相比不太可能被点击。例如,用户可能更有可能在午餐或晚餐时间点击寿司店的搜索广告,而不是在早上上班的路上。有鉴于此,跟踪模型在特定时间段内的表现或退化是至关重要的。
- 关键输入数据错误、损坏或缺失: CTR 模型经常受到数据质量问题的影响,包括缺失数据。如果模型的输入包含设备信息,则此功能的缺失或损坏可能会影响性能。更具体地说,带有“下载应用程序”行动号召的广告可能与移动设备上的某人更相关,并且如果在上下文相关性较低的计算机上发送给某人,则导致较低的点击率。类似地,当用户外出时,位置信息与移动广告商特别相关,可能已经在购物了。移动广告中定位的一个例子是从用户到最近商店的距离。在这些情况下,不可靠的位置数据可能会对 CTR 性能产生负面影响。
ML 监控的最佳实践&CTR 模型的可观察性
一旦你为你的 CTR 模型建立了一个基线和监视器,手头的任务就变成了确定问题的根本原因,并在广告业绩显著下降之前做出反应。由于消费者行为和媒体消费总是在不断变化,因此快速发现问题或行为趋势的变化并采取行动非常重要。
重要指标
评估您的 CTR 模型时,需要注意的一些重要指标包括:
- 日志损失 : 准确度是计算模型做出正确预测的次数的度量。然而,使用展示广告的平均点击率 0.45%,我们的模型可以通过预测“无点击”达到 99%的准确率,但仍然会错过每次点击机会。另一方面,对数损失是用于测量概率模型预测的最佳分类指标之一。 Log loss 回答了模型认为实际观察到的结果有多大可能性的问题。预测值与实际值偏差越大,测井曲线损失越大。在这种情况下,预测得分可能是:“有人点击的可能性有多大?”(例如 0.15,0.2 0.05),实际得分为“有人实际点击了吗?”(例如 0,1,0)。
- PR AUC**😗*PR 曲线说明了在各种阈值设置下精度和召回率(PR)之间的权衡, AUC 是曲线下面积(AUC)。精度衡量真正肯定的肯定分类(真肯定和假肯定)的百分比;召回衡量真正的肯定(例如,预测的和实际的点击)相对于所有分类的肯定的百分比,包括那些被错误分类的(例如,假阴性)。通常,当您有一个小的阳性类或不平衡的数据集时,您最关心的是确保每个阳性预测是正确的(精度),并且您获得尽可能多的阳性预测(召回),这种情况下使用 PR-AUC 度量,非常适用于 CTR 模型。
- 预测值与实际值的时间序列:在对您的 CTR 模型进行故障排除时,绘制预测值与实际值的时间序列图可以向您显示您的模型何时遇到问题——这是发现您的模型何时最错误的良好第一步。如果模型有问题,您将看到特定时间段的波动,您可以单击深入了解,调查哪些部分是预测过高或过低的根本原因。
有了这些指标,团队可以更深入地研究性能退化,分析他们的模型是否显示了任何漂移,和/或表面不一致或其他数据质量问题。
图片作者/艾瑞泽 AI: 模型监控 预测与实际
性能下降
一旦发现问题,确定导致性能下降的部分(或一组特征值)是至关重要的。通过过滤各种低性能切片来深入分析您的模型,有助于揭示影响性能的用户行为的特定波动。
再看一个寿司店广告的例子,模特表现突然下降背后的切片可能反映了一个事实,即模特在一天的不同时间没有得到足够的训练——例如在很少有人想吃寿司的清晨时段。然后,ML 团队可以适应性地重新训练模型,以提高一天中不同时间的性能,而不是选择在早餐时间对广告机会或搜索术语进行竞价。
漂移的重要性
作为一名 ML 从业者,随着时间的推移,你可能会遇到漂移或分布变化。监测和排除漂移是每个从业者工具箱的重要组成部分。
尤其是在购物行为和媒体习惯不断变化的广告中,考虑漂移以确保你的模型保持相关性是很重要的。识别各种模型环境和版本之间的特性、模型和实际偏差有助于识别模式、数据质量问题,以及跨您的发行版改变用户行为。
让我们回到你看到一个新的流行网站流量突然激增的例子。通过注意在训练中的特征输入(在这种情况下,新流行的站点)与你的特征在生产中看到的值之间的显著变化,你可以主动地重新训练你的模型以说明这个新的趋势站点。
你可能遇到的另一个例子(这一次是关于概念漂移)是,与模型的预测相比,实际点击量突然激增。深入研究可能会发现生产中存在的欺诈性僵尸网络流量,这在训练数据中是不存在的或已知的问题,因此需要一个经过修改和重新训练的模型来区分和预测人类和非人类的点击。
数据质量保证
我们都听说过这样一句话,“垃圾进,垃圾出。”没有干净的数据,ML 模型无法做出准确的预测。了解不同要素之间的数据质量对于解决任何问题以及确保模型正常工作是非常必要的。
以我们之前的坏数据为例:挖掘不同的特性,我们注意到我们得到的设备和位置的数据是空的,这影响了模型正确预测 CTR 的能力。由于这两个特征在我们的预测中非常重要,注意到这一点对于能够确定问题的根本原因非常重要。
结论
随着数字广告支出持续增长,并成为品牌广告预算的更大一部分,数据科学和 ML 团队制定可观察性战略以捕捉、监控和排除生产中 CTR 模型的问题至关重要。通过采用一种既能被动监控关键指标,又能主动测量偏差、数据质量和性能的方法,ML 团队可以在潜在问题影响营销活动绩效之前提前采取措施。作为补充参考,下面是一个 ML 可观察性平台如何帮助客户解决点击率模型监控和可观察性的问题。
联系我们
如果这篇博客引起了你的注意,并且你渴望了解更多关于机器学习可观察性和模型监控,请查看我们的其他博客和关于 ML 监控的资源!如果您有兴趣加入一个有趣的 rockstar 工程团队,帮助模型成功生产,请随时联系我们,并在此找到我们的空缺职位!
您应该知道的最好的 Python IDEs 和代码编辑器——第 2 部分
更多具有显著特性的 Python IDEs 和代码编辑器
编写 Python 代码的乐趣应该在于看到短小、简洁、易读的类,这些类用少量清晰的代码表达了大量的动作——而不是让读者厌烦得要死的大量琐碎代码。
吉多·范·罗苏姆
Python 的 拔得头筹,成为今天最流行的编程语言的确很壮观。而且,由于它的多功能性,大多数开发人员现在都在各种项目中使用这种编程语言。但是任何开发人员,无论是 Python 还是其他 编程语言 都离不开的一个工具就是代码编辑器和 ide。
看着 Python 越来越受欢迎,几个月前,我写了一篇文章,介绍了可用的最好的 Python 代码编辑器和 IDE。
从那以后,这篇文章获得了大量的赞扬,同时我们的读者 提出了一些有价值的建议,增加了一些我们可能忽略了的更受欢迎的代码编辑器和 IDE 。这篇后续文章旨在通过在开发人员社区中添加一些更强大且广泛使用的 Python 代码编辑器和 ide 来实现这一目的。
点击这里查看第一部分—
你应该知道的最好的 Python IDEs 和代码编辑器
尽管 Python 有大量的代码编辑器和 ide,但是选择正确的代码编辑器和 ide 还是很有挑战性的。在最初的文章中,我们强调了一些最好的,在这篇文章中,我们将分享一些同样著名的。
1. Emacs
- **类别:**代码编辑器
- 首次发行日期: 1975 年
- 平台兼容性: Windows、macOS、Linux
- 支持语言: Lisp,C,Emacs Lisp
- **价格:**免费
- 下载: Emacs 下载链接
- 热门公司使用 Emacs Python 代码编辑器— Stack、Accenture、Bukalapak、Chime。
从现代计算机的早期开始,Emacs 就是一个长期运行的文本编辑器。这个编辑器因为与另一个著名的文本编辑器Vi(现在叫做 Vim) 的恶名昭著的编辑器战争而变得流行。多年来,Emacs 已经发展成为一个高度可定制和可扩展的代码编辑器,可以免费获得。
就其核心而言,该编辑器是 Emacs Lisp 的解释器,但也可以很容易地用作大多数编程语言的代码编辑器。Emacs 的显著特点是:
●提供大量按键绑定
● 附带调试器、项目规划器等
●用于安装扩展件的内置包装系统
优势—
●快速
●最小化系统资源的使用
●提供大量的扩展或软件包
劣势—
●高学习曲线
●广泛的定制选项可能会分散注意力
2021 年学习 Emacs 的理由—
2. Vim
- **类别:**代码编辑器
- 首次发行日期: 1991 年
- 平台兼容性: Windows、Linux、Mac OS、IOS、Android、UNIX、AmigaOS 和 MorphOS
- **适合谁:**专业
- 支持语言: C,Vim 脚本
- **价格:**免费
- 下载: Vim 下载链接
- 热门公司使用 Vim 代码编辑器**-
-**Lyft、阿里巴巴游记、CircleCI、Ruangguru。
**还记得那场牵扯到 Emacs 的编辑大战吗?**在擂台的另一边是 Vi,另一个流行的文本编辑器,**内置于基于 Unix 的操作系统,**提供同样令人印象深刻的功能。**Vim(Vi 改进版的缩写)**是 Vi 的现代化版本,提供了大量方便的特性,使其符合当今开发人员的文本编辑器。
Vim 编辑器不仅允许您高效地创建完整的 Python 程序,还允许您轻松地处理文本文件。编辑器也在积极更新,增加了许多现代代码编辑器的标准特性。我们在下面列出了其中的一些功能:
●提供超过 10 种界面模式
●自带一种名为 Vimscript 的内置脚本语言
●为插件提供广泛的支持
●支持多种编程语言
优势—
●重量轻
● Vimtutor,内置教程可以对抗其高学习曲线
●高度可配置和可移植
劣势—
●一开始可能看起来很复杂
●定制 Vim 可能会成为一个永无止境的过程
截图供参考-
3.托尼
- 类别: IDE
- **平台兼容性:**微软视窗、Linux、macOS
- **适合谁:**初学者
- 支持语言: Python
- **价格:**免费
- **下载:**Thonny 下载链接
对于很少或没有编程经验的人来说,Thonny 是一个非常适合初学者的 Python IDE 。Thonny 让新手更容易进入 Python 编程,因为它带有 Python 3.7 ,节省了安装时间。
Thonny 的教育性编程风格不仅教你编程语言的某些部分,比如变量,而且还给你一个执行的可视化表示。托恩尼的主要亮点是:
●简单干净的 IDE
●附带一个简单的调试器
●提供代码完成功能
优势—
●提供大量初学者友好的功能
●提供一个简单的 Python 外壳来安装附加的包
●可以用几个方便的插件进行扩展
缺点—
●它不如列表中的其他一些 ide 先进
●缺乏对模板的支持
截图供参考-
4.孙耀威
- 类别: IDE
- 首次发行日期: 2002 年
- 平台兼容性: Linux、macOS、微软 Windows
- 支持语言: Python
- **价格:**免费
- 下载: 孙耀威下载链接
- 使用 Eric Python IDE 的热门公司- BristoSoft、GymGlish、Climpact
尽管不像这个列表中的其他代码编辑器和 ide 那样受欢迎,Eric仍然提供了大量的特性来处理你的日常文本编辑需求。Eric 的特别之处在于它不仅是 Python 的代码编辑器,也是同样令人印象深刻的 IDE。****
基于流行的 Qt 工具包和灵活的闪烁编辑器控件,Eric 为创建 Python 应用和专业管理软件项目提供了几个方便的特性**。它的一些**最好的特性是:****
●源代码编辑能力
●支持使用 Qt Designer 进行 GUI 设计
●代码调试、检查、测试和记录
优势—
●可以同时运行多个编辑器
●自带高效调试器
●围绕 Python 编程语言
缺点—
●即使对专业人士来说,界面也可能看起来很复杂
●使用多个插件时,性能会受到影响
</10-cool-python-project-ideas-for-python-developers-7953047e203>
5.竞技表演
- 类别: IDE
- 首次上映日期: 2016 年
- 平台兼容性: Windows、Linux、Mac OS 等。
- **价格:**免费
Rodeo 是一个面向 Python 的跨平台 IDE,它是轻量级的,是现代数据科学家开发用于 机器学习 和数据科学问题的完美工具。
Rodeo 可以有效地用作您的个人数据探索和解释工具。如果你发现自己在某个时候陷入了困境,Rodeo 的综合教程可以帮助你找到出路。使 Rodeo 成为数据科学绝佳选择的特性包括:
●其数据绘图能力
●提供代码完成、语法高亮等功能
●支持 IPython
优势—
●提供直观的工具,如可视化文件导航器、包搜索和点击式目录
●备忘单使引用 Python 主题更加容易
缺点—
IDE 有几个内存和性能问题
●发展停滞了相当一段时间
结论
Python 对开发人员来说非常友好,但是在选择合适的代码编辑器和 IDE 时,事情就变得困难了。Python 为具有不同编程语言经验的人提供了代码编辑器和 ide。在这篇文章中,我们介绍了我们在最初的文章中遗漏的其他顶级 Python 代码编辑器和 ide。
如果您正在寻找一个强大的 Python 代码编辑器和 IDE,我们希望这篇后续文章能为您指出适合您的工具。
你对这份迷你清单有什么想法?我很想听听他们的故事。
更多有趣的 Python 读物
我希望这篇文章对你有用!以下是一些有趣的读物,希望你也喜欢
https://blog.digitalogy.co/python-interview-questions-and-answers-for-freshers/ </10-world-class-companies-using-python-26cde24919a8> https://blog.digitalogy.co/best-python-frameworks-for-web-development-2020/
关于作者
克莱尔 D 。在digital ogy—***是一个内容制作者和营销人员,这是一个技术采购和定制匹配市场,根据全球各地的特定需求,将人们与预先筛选的&顶尖开发人员和设计师联系起来。与我连线上 中Linkedin&推特 。*
最佳文本聚合方法:重访 VLDB 2021 人群科学挑战赛
思想和理论
今年, Toloka 在丹麦哥本哈根举行的世界上最大的数据科学会议之一——超大规模数据库 (VLDB 2021)上领导了一个群体科学研讨会。作为研讨会的一部分,Toloka 研究团队组织了一场竞赛,以确定众包文本文件的最佳聚合方法。所谓的群众科学挑战提供 6000 美元的现金奖励,其中 3000 美元给获胜者,2000 美元给亚军,剩下的 1000 美元给第三名。至关重要的是,作为这场激动人心的比赛的结果,我们能够找到聚合众包文本的最佳方法。
文本聚合
为什么大惊小怪?
大多数众包任务都是关于分类的:众包执行者必须从一组预定义的选项中选择正确的答案。然而,一些任务需要内容生成、音频注释或对象选择。由于这些任务需要的答案超出了多项选择的范围,因此通常需要手工检查作业。出于这个原因,两个标签项目并行运行——一个收集来自群众演员(我们也称之为 Tolokers)的提交,另一个在项目中涉及的其他演员验证后接受或拒绝这些提交。验收后,绿灯 Tolokers 得到相应的报酬。
让我们感兴趣的问题是,这两个阶段的过程是否可以被绕过,整个机制是否可以自动化。
转录音频→验证转录
开拓者和超越者
我们绝不是第一个想到或试图这样做的人。90 年代,识别器输出表决误差减少 (ROVER)被开发出来。它使用动态编程从几种可能的预测中提供一种新的高质量的语音识别预测。由于这种方法在众包中被广泛认可( Marge et。,2010 ,我们选择它作为我们的基线。因此,一种新的聚合方法不仅有望展示最好的结果,而且有望在相同的数据集上超过 ROVER。
当然,在过去的 30 年里,同样的问题还有其他的解决方案。其中有一类 RASA 和 HRRASA 方法(李,2020 ),它们使用类似 BERT 的语言转换器来聚合文本。这些方法使用检索方法解决聚集问题;然而,从我们的经验来看,它们通常不如 ROVER 工作得好。尽管如此,它们也包括在基准中以供参考。
因此,最好的聚合方法应该能够处理大量嘈杂的转录,并提供与相应音频文件精确匹配的最佳文本版本。作为评估标准,我们使用平均单词准确度(AWAcc)。
转录音频→谢谢!
数据准备
对于我们的竞争,我们决定使用一个全新的、类似 LibriSpeech 的数据集,它不会类似于任何其他东西。以下是我们为此所做的准备:
1.选自维基百科和图书语料库的随机句子。
2.丢弃很短或很长的句子,以及包含数字的句子。
3.使用 Yandex SpeechKit 生成所选句子的音频版本。
4.在 Toloka 上发起了一个标签项目,要求表演者转录音频文件。
5.为每段录音收集了一些注释。
(正确答案提前知道)。
正如大多数 ML 竞赛一样,我们将过程分为一个训练(“训练”)和两个测试阶段(“公开测试”和“私人测试”)。“训练”用于训练和调整竞争的 ML 模型,“公开测试”用于评估比赛过程中的质量,“私人测试”用于确定获胜者并结束比赛。我们从 3,039 名群众工作者那里收集了总共 99,414 条音频注释,转录了 9,700 条音频记录。
数据
挑战中使用的所有数据都可以在 GitHub 上获得。
描述本次比赛整个数据准备过程的研究论文已在 NeurIPS 2021 数据集和基准赛道上发表,并在此处提供。
VLDB 大赛
ML 比赛通常在赛道、赛道或赛道举行。权衡各种选择后,我们最终选择了 Yandex。谁能够为我们提供优先支持。
除了想出最好的转录文本聚合方法,参赛者还被邀请提交他们方法的书面描述,我们后来在我们的研讨会记录中发表了这些描述。托洛卡还向有意愿和能力的参与者提供竞赛资助。
VLDB 2021 人群科学挑战赛时间表如下:
- 2021 年 4 月 15 日——比赛启动,训练阶段开始(“训练”)
- 2021 年 5 月 5 日——主要比赛阶段开始(“公开测试”+“私人测试”)
- 2021 年 6 月 18 日—比赛结束
- 2021 年 7 月 5 日—概述汇总方法的论文提交截止日期
- 2021 年 8 月 20 日— VLDB 2021 人群科学研讨会
获奖者和荣誉奖
由于 ROVER 和 HR/RASA 显示的 AWAcc 值分别等于 92.25%和 91.04%,我们一直在寻找具有更好结果的模型。共有 18 名参赛者参加,其中只有 8 人在活动的“私人测试”阶段展示了超过 ROVER 基线的平均单词准确度值。需要注意的是,包含大规模语言模型的 HR/RASA 方法最终未能给人留下深刻印象。以下是挑战赛的三名获胜者以及那些想出了巧妙解决方案但没有获胜的参赛者:
- 第一名 (AWAcc = 95.73%)。最好的方法是用于文本摘要的微调 BART 模型。为了在训练中调整模型,参赛者打乱了所有提交的转录,随后用美国英语单词替换英国英语。令人惊讶的是,一个成功的文本聚合方法依赖于一个执行良好的文本摘要策略。
- 第二名 (AWAcc = 95.66%)。在使用微调的 T5 模型进行自动文本摘要之前,这位参赛者还尝试了许多 seq2seq 方法。他们的方法证实了获胜方法的有效性;然而,亚军可能由于缺乏模型正规化而缺乏一致性。
- 第三名 (AWAcc = 95.48%)。该值是不同信号的线性组合的结果,包括 BERT、假设分类器和执行者特征,如答案的数量及其一致性。值得注意的是,这是我们在比赛的三个获胜者中看到的唯一一个真正考虑表演者技能的方法。此外,这位参赛者使用了我们提供的一笔资助来完善他们的方法。
- 第四名 (AWAcc = 95.00%)。这个参与者使用了一个经过微调的 T5 模型,并使用 LightGBM 对注释进行了排序。这种方法虽然值得称赞,但产生的输出不如前三种精确。
- 第六名 (AWAcc = 93.37%)。事实证明,人们可以使用 Levenshtein 距离的中值来提出可行的解决方案。但是这种方法意味着一个非常仔细的执行者选择试探法,它极大地影响了结果。
结果和结论
感谢 VLDB 2021 人群科学挑战赛,我们能够获得一种可靠的文本聚合方法,成功地将 ROVER 在我们的新数据集上的错误率减半,从 7.75%降至 4.27%。
我们收到了来自不同背景和观点的人的解决方案,有趣的是,事实证明,总的来说,整合音频转录和文本的任务是一个自动文本摘要问题。此外,我们了解到一些基于语言的模型显示了不错的结果,在这种情况下,大多数检索方法都不是特别好,并且 ROVER 不再是无可争议的音频转录聚合之王。第一名获胜者提供的方法将被添加到我们的众包中,这是一个用于众包的开源 Python 库。这并不意味着问题已经完全解决,但它确实意味着已经取得了相当大的进展。
我们的研讨会记录包括题为 VLDB 2021 关于聚合众包音频转录的众包科学挑战的论文,其中包含对竞赛及其结果的更详细描述。还有两篇论文概述了竞赛冠军和亚军和亚军使用的汇总方法。
尽快掌握数据科学需要关注的最佳话题
开始学习数据科学时,您应该主要关注哪些主题和领域?
汤姆·里森在 Unsplash 上的照片
“没有任何伟大的营销决策是基于定性数据做出的.”— 约翰·斯卡利
数据科学是一个庞大的领域,很容易迷失在该领域呈现的大量主题中。然而,如果你只是一个想要深入研究数据科学主题的初学者,它会让你想知道什么是你应该关注的基本概念,以便你可以更好地掌握这个领域。
如果你想从头开始学习一切,并制定一个完美的计划来学习你想要的一切,那么请务必查看下面的文章,在 12 个月内掌握数据科学,同时使用上述 12 个步骤学习和获得更多知识。
</12-steps-for-beginner-to-pro-in-data-science-in-12-months-c6f6ba01f96e>
然而,如果你没有很多时间,只想完成一个快速速成课程,那么这篇文章将是你尽快专注于数据科学最本质方面的完美选择。本文的主要目标是关注在数据科学领域被认为非常有价值的清晰的主题。
让我们开始了解数据科学中最重要的主题,您必须关注这些主题,以便尽快了解更多信息并获得更多知识。这些概念的概要可以被认为是在本文的各个部分中列出的。
数据
照片由 Unsplash 上的 Pietro Jeng 拍摄
没有数据,就不可能有数据科学。数据科学包括数据挖掘、数据准备、数据操作、数据可视化和其他与数据相关的重要方面。数据科学的正式定义如下—
数据科学是一个跨学科的领域,它使用科学的方法、流程、算法和系统从许多结构化和非结构化的数据中提取知识和见解。数据科学与数据挖掘、机器学习和大数据相关。
数据被认为是当今时代最重要的资源之一。科技巨头和大公司正在大力投资,以尽可能获得最佳资源。这样做的原因是为了达到期望的客户满意率,并借助收集的数据分析他们的行为模式。
如果你是一个初学者,刚开始学习数据科学,你处理数据的方法必须是从获得的资源中收集和处理尽可能多的信息。学会识别最适合你的特定项目的相关数据。
一旦您能够获得必要的数据,您的任务就是考虑从中获得有用的信息,并预处理额外的不必要的需求。收集和准备你的数据。帮助你完成这个过程的最好的工具通常是 pandas 库模块,以及一个去除无关数据的模块,比如正则表达式(re)模块。
我强烈推荐阅读下面这篇关于 NLP 的文章,这篇文章用四个正则表达式命令简化了 NLP。下面提供了链接。
编程;编排
在 Unsplash 上由Nejc sokli拍摄的照片
编程恰好是构建数据科学项目时需要关注的最重要的主题之一。这一点是显而易见的,但是如果你对编程一无所知,或者你只是一个想要学习更多编程知识的初学者,你怎么能更快地有效理解编程呢?
这个想法很简单。Python 是初学编码爱好者最容易学习和探索的编程语言之一。关于 Python 的最佳结果可以通过有效地研究这个主题来获得,并且可以在一个月的时间内掌握到中级水平。
我强烈推荐初学者从下面的链接中找到掌握 Python 数据科学的十步快速程序指南。按照上述步骤的顺序进行操作,以获得最佳效果。
</10-steps-to-master-python-for-data-science-f54199bb328d>
数据科学的另一个要求是足够数量的 SQL。结构化查询语言 (SQL)是一种用于编程的领域特定语言,设计用于管理关系数据库管理系统中保存的数据,或用于关系数据流管理系统中的流处理。
对 SQL 简单的基本理解通常足以开始从事体面的数据科学项目。借助互联网丰富的资源,您可以对 Python 编程语言有一个中级的了解,然后就可以开始从事数据科学项目了。
您必须关注的编程的更重要的方面是使用 Python 开发环境中存在的大量数据科学库模块的能力。您可以探索这些工具,因为它们将帮助您完成许多独特的任务。
可视化技术
为了简化您的数据科学项目,您的主要精力必须放在使用各种可视化技术来掌握您可用的数据中的有用信息。这种有用信息的程序性检索可归因于称为探索性数据分析(EDA)的重要步骤。正式定义可以表述如下—
在统计学中, 探索性数据分析 是一种分析数据集以总结其主要特征的方法,经常使用统计图形和其他数据可视化方法。可以使用或不使用统计模型,但 EDA 主要是为了查看数据可以告诉我们什么,而不仅仅是正式的建模或假设测试任务。
可视化在数据科学中占有非常重要的地位,因为它能够为特定的任务找出正确或错误的数据。在分析数据时,您可以找出模式和许多其他元素,这将有助于您更有效地应对复杂的数据科学项目。
Python 编程对这一目的非常有益,因为它允许用户利用 matplotlib 和 seaborn 中一些最好的可视化工具对大量数据集进行分析。当你能够对这些库模块有更好的理解时,你就可以在分析过程背后发展出更强的直觉。
尝试各种图表,如条形图、饼图、直方图、散点图和其他可视化技术,将有助于您更好地理解问题陈述和解决问题的方法。你不仅能理解数据,还能解释破解项目必须遵循的步骤。
数学
杰斯温·托马斯在 Unsplash 上的照片
数学是数据科学的一个重要方面,你需要掌握一些知识才能直观地理解众多概念。对数学有很强的基本理解将有助于你弄清楚机器学习算法和其他与数据科学相关的概念背后的概念熟练程度。
在数学方面,如果你刚刚开始接触数据科学,你需要掌握的主要目标必须是线性代数、概率统计和微积分这三个领域。在线性代数中,尝试开发向量、欧几里德距离、点积和其他类似主题背后的直觉,以轻松理解众多机器学习方面。
概率和统计是直观理解图形信息的重要主题,也是机器学习算法背后的过程理解,如基于贝叶斯定理的朴素贝叶斯算法。虽然积分学可能不需要立即关注,但你应该专注于微分学,以更快地掌握反向传播和其他类似概念的过程。
要了解更多关于学习数学的最佳免费资源,你可以查看下面的链接,或者阅读包含学习数学的最佳资源的下一部分。
学习数学的最佳资源:
- 可汗学院(*): 开始学习线性代数、微积分、概率统计等基本数学概念的最佳去处。
- 3Blue1Brown (*): 最好的 YouTube 频道之一,可以查看一些精彩的深入解释,并更好地直观理解概念。
- 书籍:如果你更喜欢读书,那就在谷歌上快速搜索一下,找到一些优秀的学习数学的免费电子书资源。为了更好地练习,你应该为每个特定的主题选择单独的书。
机器学习
阿瑟尼·托古列夫在 Unsplash 上的照片
机器学习是数据科学中的一个特殊主题,也是您可以构建和建立模型以完成您计划完成的目标和任务的主要方式之一。机器学习可以被定义为一种计算机程序,它将随着时间的推移而学习,即通过执行特定的任务并在许多时代之后学习它来获得经验。
机器学习模型是解决你的数据科学项目的主要方式。一旦您完成了对数据集的分析,并且使用多种可视化技术找出了最佳方法和途径,并且完成了数据准备,您的机器学习模型现在就可以构建了。
在构建机器学习模型的过程中,您的主要目标是解决特定的任务,同时实现体面的准确性和损失结果。向所有没有任何机器学习算法经验的数据科学初学者强烈推荐 Python 中的 scikit-learn 库模块。
对于数据科学家来说,理解这些模型的工作和方向非常重要。如果你有时间,我会建议你从头实现所有这些机器学习算法。然而,如果你没有足够的时间来做这些项目,而你又想尽快对这个主题进行实验,那么就试试这些预先构建的算法。
一旦您成功地完成了模型的训练,并且成功地运行了相当数量的纪元,您就应该考虑部署这些模型了。这一步将确保您在几天或几周内完成第一个数据科学项目。您可以专注于数据科学的基本部分,并构建许多更有用的项目。
结论:
“智慧不是学校教育的产物,而是终生努力获取的产物.”— 阿尔伯特·爱因斯坦
虽然数据科学有几个方面是至关重要的,需要全神贯注才能掌握这门学科,但有几个特定的主题尤为重要。在这些概念的帮助下,您可以完成各种各样的任务,从而使您能够更快地在项目中获得想要的结果。
你的目标必须是获取广泛的数据,并彻底研究这些数据。应用一系列可视化技术,并相应地确定您可以在项目中实现的最佳机器学习算法。这样做将帮助你达到你想要的结果,而且比你花时间解决所有事情花费的时间要少得多。
不要忘记关注编程的基本方面,即像 Python 这样的编程语言,使您能够学习编码的基础知识并开发独特的项目。为您的数据科学项目学习一些管理数据库的 SQL。不要忘记数学,因为它是数据科学和机器学习的核心。它将帮助你获得坚实的基础和对主题的理解。
如果你对这篇文章中提到的各点有任何疑问,请在下面的评论中告诉我。我会尽快给你回复。
看看我的其他一些文章,你可能会喜欢读!
</5-reasons-why-you-should-develop-a-game-with-python-and-ai-9f5f276e7637> </5-reasons-why-you-should-code-daily-as-a-data-scientist-fa7fc6dc92c4>
谢谢你们坚持到最后。我希望你们喜欢阅读这篇文章。我希望你们都有美好的一天!
研究数据科学的最佳大学
并非所有的数据科学学位都是一样的,所以请找出适合你的课程
数据科学是世界上发展最快的职业之一。美国劳工统计局估计,到 2026 年,将有大约 1150 万个与数据科学相关的工作机会**【1】**。这些数字表明,学术、公共和企业部门已经认识到数据专业人员对其最终目标的重要性。因此,我们应该看到许多学术机构提供数据科学课程,大多是研究生水平(硕士学位),以适应就业市场的直接需求。
然而,从学生的角度来看,决定哪个数据科学项目适合你并不容易。就所提供的课程而言,大学可能会有很大的不同。此外,每个项目都有不同的课程,这就是为什么仔细比较你感兴趣的选择以及以下标准因素至关重要:
学制: 1 年或 2 年(通常在欧洲,英国除外,硕士需要两年)
**学习类型:**全日制和非全日制。
**最低要求:**计算机科学或另一相关量化学科(如数学、工程、统计、物理、自然科学或商科)学士学位。申请人应该熟悉基础数学,尤其是微积分和线性代数。此外,申请人应该对至少一种编程语言(Python 或 R)相当熟悉。
**语言要求:**如果你的第一语言不是英语,那么你必须提供证据证明你的口头和书面英语技能足以胜任该课程。在欧洲,大学接受名为雅思的英语考试,而在美国和加拿大,大学要求托福考试。如果你有一个用英语授课的学位,一定要检查你是否免除了语言要求。
一旦您满足了最低要求,您现在就能够决定哪个地方是学习数据科学的最佳场所。下面,我根据学术成就、研究成果和对比数据科学课程,仅列出了一些顶尖学校。以下是北美和欧洲的一些顶尖学校。
北美
麻省理工学院
位于美国波士顿的麻省理工学院提供商业分析硕士项目(MBAn) 。这个为期 12 个月的项目为学生从事应用和管理现代数据科学的职业做准备,以解决关键的商业挑战。该计划的一个亮点是分析顶点项目,该项目允许学生与行业数据专业人员一起研究数据科学问题。所有学生都将获得 22,000 美元,并因其参与而抵消学费。MBA 毕业生继续在谷歌、亚马逊、波士顿咨询公司、麦肯锡公司和许多其他顶级科技和咨询公司工作。
https://mitsloan.mit.edu/master-of-business-analytics#tour-welcome
卡内基梅隆大学
卡内基梅隆大学的数据科学课程旨在培养跨学科环境中的学生。他们提供课程和前沿研究的结合。数据规模和复杂性的快速增长可以在多个领域进行收集和分析,包括医疗保健、公共安全、科学研究和公共政策。学生和教师都与名为 Meltwater 的数字媒体智能公司合作,利用该公司的人工智能平台推进涉及人工智能的研究和教育。他们可以访问世界上最多样化的开放和许可数据平台。
然而,获得卡内基梅隆大学计算数据科学硕士学位的学生可能不得不在匹兹堡之外寻找工作。这是因为美国的其他城市提供了更多的工作机会。
提示:值得一提的是,如果你打算毕业后在美国学习和工作,那么你应该多读一些关于 STEM 分类的内容。一些项目符合“STEM 指定项目”的条件,允许国际学生毕业后在美国延长培训 24 个月。否则,你将不得不返回你的国家。
除了美国大学,一些加拿大大学为数据专业人员提供优秀的研究生课程和丰富的环境。例如, MILA 位于魁北克科技和创业生态系统的中心,是一个由 500 多名专注于机器学习和人工智能的研究人员组成的社区。他们致力于科学的卓越和创新,以成为科学进步和创新的全球中心为使命。
MILA 有几个通过参与机构提供的培训项目: 麦吉尔大学 、 蒙特利尔高等商学院 和 蒙特利尔大学 。如果你对研究感兴趣,MILA 将让学生和一名志愿者导师配对,为期 9 个月。导师将支持他们的学员实现个人和职业发展目标。2021 年 3 月,Mila 将启动导师计划的第二批项目。请记住,一些课程和导师项目需要高级法语水平,主要是在蒙特利尔大学。麦吉尔和 HEC 都提供一些英语课程。
欧洲
几乎欧洲的每个国家,特别是法国,都已经采取措施为那些对从事与数据相关的职业感兴趣的人提供必要的培训。欧洲一直有一些世界领先的大学,现在这些学术机构也提供解决数据培训和研究需求的课程。
伦敦帝国学院
伦敦帝国理工学院推出了数据科学研究所(DSI)。这一重大举措汇集了学院现有的数据科学活动和专业知识,并创造了新的合作伙伴关系和研究机会。在帝国理工学院学习的一个独特方面是学院的学术专家和学院之间跨许多学科的多学科合作,如医疗保健,金融,气候科学和城市发展。他们的最终目标是创造复杂问题的解决方案。除了研究,他们还通过研究生课程培养未来的数据科学家。一个例子是生物医学研究中的 MRes 与数据科学流 。
本课程提供现代高通量生物分子研究中数据分析的跨学科培训。他们的学生将接受多元统计、机器学习方法和这些方法的研究经验的核心培训,以回答真正的生物医学问题。事实上,伦敦帝国理工学院研究实验室一直在向英国政府提供与新冠肺炎相关问题的数据分析支持。
然而,如果你对数据科学的商业方面感兴趣,你会在法国找到一门独特的课程,但是用英语授课。
巴黎综合理工学院&巴黎高等商学院
商业数据科学硕士项目是一个为期两年的项目,结合了商业和科学方法来应对当前的数据科学挑战。第一年,学生将在理工学院学习,重点是科学和数学课题。而在第二年,在巴黎 HEC,学生们不仅要面对一个新的物理环境,还要接受一种不同的学术方法,即边做边学。这些变化有助于学生提高他们的管理和数据科学知识,并应用它们来解决业务挑战。他们独特的课程在数据科学方面培训学生,并为他们提供高水平的战略和商业技能。每学年学费为 20,800€(约 25,200 美元)。
一个穿着制服戴着双角帽的理工学院学生。照片由 Marie-Lan Nguyen 在维基百科上拍摄。
赫尔辛基大学
这可能会让许多有抱负的数据科学家感到惊讶。尽管如此,芬兰仍在数据相关项目上投入了大量资金,以帮助本国民众做好准备,利用人工智能和数据科学的指数级增长。赫尔辛基大学在教育芬兰人方面发挥了重要作用。学生可以选择专攻与数据科学相关的许多不同技术领域中的一个,如高级分析、机器学习、计算机视觉和研究。数据科学硕士课程为期两年,用芬兰语、英语和瑞典语授课。
结论
数据科学领域已经赢得了领先大学专业硕士学位的权利。然而,为自己选择正确的课程可能不像预期的那样简单。申请者和有抱负的数据科学家应该花时间从课程的角度调查每个项目到底提供了什么。正如你所看到的,一些学位是以研究为导向的,而另一些则开发了商业和实际应用。然而,在正式的学术环境中有很多机会学习数据科学。请记住,并不是每门课程都会用英语教授。如果你想在美国学习和工作,一定要查看 STEM 分类。这不是一份详尽的清单。希望现在你知道许多其他大学提供高质量的数据科学学位,以及每个大学如何对同一主题采取不同的方法。
感谢阅读。以下是你可能喜欢的其他文章:
https://medium.com/codex/top-10-artificial-intelligence-influencers-you-should-follow-ca91e94c797b
参考文献:
【2】https://www . gov . uk/government/news/January-2021-findings-from-新冠肺炎-study-published
解决 Python 编码问题的最佳方式
了解如何有效解决 Python 编码问题
韦斯利·廷吉在 Unsplash 上拍摄的照片
关于 Python 编码网站(如 codewars 或 leetcode)的好处,以及使用它们是否真的能让我们成为更好的程序员,肯定存在一些争议。尽管如此,许多人仍然使用它们来准备 Python 面试问题,保持他们的 Python 编程技能,或者只是为了好玩。然而,对于任何 Python 程序员或数据科学家来说,这些资源肯定都有一席之地。
在本教程中,我们将看看从这些 python 编码问题中提取最大效用的最佳方式。我们将研究一个相当简单的 Python 编码问题,并通过适当的步骤来解决它。这包括首先用伪代码想出一个计划或大纲,然后从最简单的解决方案开始用不同的方法解决它。
Python 编码问题
我们需要编写一个函数,它将单个整数值作为输入,并返回从零到该输入的整数之和。如果传入了非整数值,该函数应该返回 0。
因此,如果我们将数字 5 传递给函数,那么它将返回整数 0 到 5 的和,或 (0+1+2+3+4+5) ,等于 15。如果我们传入除了整数之外的任何其他数据类型,比如字符串或浮点数等,函数应该返回 0。
制定计划
我们应该做的第一件事是用伪代码解决这个问题。伪代码只是一种不用担心编码语法就能规划出我们的步骤的方法。
我们可以试着这样做:
def add(num):
# if num is an integer then
# add the integers 0 through num and return sum
# if num is not an integer then return 0**Sample inputs/outputs:****# input: 5, output: 15
# input: 'and', output: 0**
我们定义了一个函数 add ,它接受一个输入 num 。在 add 函数中,我们使用注释编写了一个步骤大纲。如果传递给函数的值是一个整数,那么我们将把整数 0 和该值相加,然后返回和。如果传递给函数的值不是一个整数,那么我们简单地返回 0。在那之后,我们写一些例子,我们希望我们的输出被给定一个特定的输入。
让我们在上面的伪代码中展开这一步:
# add the integers 0 through num and return sum
这一步可以用很多方法来完成。如果我们使用 for 循环尝试这一步,伪代码会是什么样子?
def add(num):
# if num is an integer then**# create sum variable and assign it to 0****# using a for loop, loop over integers 0 to num****# update sum value by adding num to it****# return sum**# if num is not an integer then return 0
让我们根据上面创建的蓝图来尝试解决它!
使用 For 循环
我们可以使用 for 循环来解决这个提示,如下所示:
def add(num):
**# if num is an integer then** if type(num) == int:**# create sum variable and assign it to 0** sum = 0**# using a for loop, loop over integers 0 to num** for x in range(num+1):**# update sum value** sum += x**# return sum** return sum**# if num is not an integer then return 0** else:
return 0
下面我们来剖析一下代码。
我们首先使用类型的函数检查传入的值 num 是否是一个整数。
if type(num) == int:
如果类型是整数,我们创建一个 sum 变量,并给它赋值 0。
sum = 0
然后,我们使用 for 循环和 range 函数对从 0 开始的整数进行循环,直到传递给我们的函数的整数。请记住,range 函数创建了一个 range 对象,它是一个可迭代的对象,从 0 开始(如果我们没有指定起始值),到小于停止值的整数(因为停止值是唯一的)。这就是为什么我们需要在停止值( num+1 )上加 1,因为我们想把从 0 到这个数字的所有整数加起来。
range
(开始、停止[、步进])
range 函数将创建一个 range 对象,这是一个可迭代的对象,因此我们可以使用 for 循环来遍历它。当我们循环遍历这个 iterable 对象时,我们将每个数字,或 x ,添加到 sum 变量中。
for x in range(num+1):
sum += x
然后,在 for 循环迭代完成后,该函数返回总和。
return sum
最后,如果传入的数字不是整数,我们返回 0。
else:
return 0
这是没有注释的代码:
def add(num):
if type(num) == int:
sum = 0
for x in range(num+1):
sum += x
return sum
else:
return 0
如果我们测试我们的加法函数,我们得到正确的输出:
add(5)
# 15add('and')
# 0
这是解决编码问题的一个好方法,它完成了工作。它易于阅读,工作正常。但是,在我看来,通过尝试以其他方式解决这个问题,我们也许可以通过利用我们的其他 python 知识和解决问题的技能从中提取更多的价值。这些其他的方法可能更 pythonicic 化,也可能不更 python 化,但是思考不同的方法来解决同一个问题是非常有趣和有用的。
让我们试着用不同的方法解决这个编码问题。
关于可迭代对象的更多信息:
使用 Reduce 函数
我们最近在之前的教程中学习了 reduce 函数的功能。reduce 函数接受一个 iterable 对象,并将其缩减为一个累积值。reduce 函数可以接受三个参数,其中两个是必需的。两个必需的参数是:一个函数(它本身接受两个参数)和一个 iterable 对象。
我们可以使用 reduce 函数来计算一个可迭代对象的和。
因此,代替 for 循环,我们可以使用 reduce 来解决我们的 Python 问题:
from functools import reducedef add(num):
if type(num) == int:
return reduce(lambda x,y: x+y, range(num+1))else:
return 0
就是这样!我们使用 lambda 函数作为函数参数,使用 range 对象作为我们的 iterable 对象。然后, reduce 函数将我们的 range 对象减少到一个值,即 sum。然后我们返回总和。
关于 reduce 功能的更多信息:
使用三元运算符
通过使用三元运算符,我们可以进一步缩短代码。使用三元运算符,我们可以使用以下格式将上面的 if/else 语句缩短为一行:
x if C else y
C 是我们的条件,先评估哪个。如果评估为真,则评估 x 并返回其值。否则,对 y 求值并返回其值。
我们可以在代码中实现这一点,如下所示:
def add(num):
return reduce(lambda x,y: x+y, range(num+1)) if type(num) == int else 0
通过这些改变,我们设法将函数中的代码减少到一行。这可能不是解决这个问题的最具可读性或 pythonic 式的方法,但在我看来,它通过迫使我们找出解决同一问题的不同方法来帮助我们提高编码和解决问题的技能。
让我们看看能否用另一种方法解决这个编码问题。
关于三元运算符的更多信息:
sum()函数
我们可以使用 Python 内置的 sum 函数以不同的方式解决这个编码问题。sum()函数可以接受一个 iterable 对象,并返回其元素的总和。如果我们想先将起始值添加到元素中,我们也可以传入一个起始值。
sum(iterable,start)
让我们使用 sum 函数来解决编码问题:
def add(num):
return sum(range(num+1)) if type(num) == int else 0
就是这样!这可能是解决这个编码问题的最好方法,因为它是最简洁和易读的解决方案。此外,它还可能具有最佳性能。
有关代码性能的更多信息:
如果你喜欢阅读这样的故事,并想支持我成为一名作家,考虑注册成为一名媒体成员。每月 5 美元,你可以无限制地阅读媒体上的故事。如果你用我的 链接 报名,我就赚点小提成。
https://lmatalka90.medium.com/membership
结论
在本教程中,我们了解到使用不同的方法解决 Python 问题可以通过拓宽我们的知识库来增强我们的编码和解决问题的技能。我们看了一个示例 python 编码问题,并经历了解决它的步骤。我们首先计划如何用伪代码解决这个问题。然后,我们通过使用 for 循环来解决提示问题,从而实现了这些步骤。后来,我们用 reduce 函数解决了同样的问题。我们还实现了三元运算符来进一步缩短代码,但仍然保持可读性。最后,我们使用 Python 内置的 sum 函数和三元运算符,得出了最短但仍然最 Python 化的解决方案。
贝塔分布预测 2020 年选举结果
快速实时预测的简单更新
不同参数值的 beta 分布动画。维基百科上 Pabloparsil 的 Gif。 CC BY-SA 4.0 。
不知何故,在我上学的几年里,我从未听说过 beta 发行版,直到我在大卫·罗宾逊的博客上偶然发现它们,但它们很快成为我最喜欢的发行版之一。我的意思是,看看那个向左摆动的东西。它们是非常灵活的发行版,但这并不是它们真正酷的原因。正是你可以轻松地更新你的预测,使得贝塔分布脱颖而出。
贝塔分布由两个参数描述,阿尔法和贝塔(你可以看到改变这些值如何影响上面的分布形状),虽然这种分布有丰富的数学描述,但对它们的高级解释是阿尔法-1 =成功数,贝塔-1 =失败数,是的,贝塔分布与二进制数据有关,成功或失败,就像二项式和伯努利分布一样。事实上,在技术语言中,我们会说贝塔分布是二项式分布和伯努利分布之前的共轭,为了简化,这意味着当我们想要更新由这些分布建模的数据时,我们使用贝塔分布来完成它,但是为了更深入的解释,请查看 Aerin Kim 的 MIT 18.05 和这两篇文章( 1 、 2 )(按照她的推荐顺序)。
更新 beta 发行版就像了解您正在使用的 alpha 和 beta 一样简单。更新,新的成功?给 alpha 加一(字面意思是 alpha + 1)。更新,5 个新故障?在 beta 上加 5(字面意思是 beta + 5)。就这么简单,数据集的预期均值总是 alpha / (alpha+beta)。
让我们举一个选举数据的例子,但首先,一个警告:这更接近于一个我称之为天真贝塔分布和贝叶斯更新的例子,就像天真贝叶斯分类器一样,也就是说我忽略了我的观察的独立性(因为它们不是),我承认我不知道这种天真到底有多可恶。也许只有一点。也许完全是。但正如他们所说的,LAAETTR(发音为“后来”,带有南加州口音,如“后来,笨蛋”):
留给读者作为练习。
我们的例子:贝塔分布和 2020 年选举数据。
在美国,我们通过直接代表而不是直接代表来选择我们的国王:这就是选举团,它无疑是人民民主的古老和可以说是良好的遗迹,但对人民来说却没有太多的民主。这是一个让候选人有可能赢得普选的制度,但不是总统职位。)
比方说,在最近的 2020 年总统选举中,随着一周内民调开始出现,你希望更新你的预期。也许你有前几年候选人的选举人票的历史数据(和),并且知道一个候选人期望得到的平均票数。
为什么,这是一个采用贝塔分布的绝佳机会——除了这些观察结果不是独立的这一事实。一个候选人在选举团中表现很好,意味着至少有一个候选人表现很差,根据定义,这不是独立观察。我们知道这是一种糟糕的做法,但为了举例,我们还是继续进行。
所以我们使用了一个库,如果你使用 Python 的话,可能是 SciPy,来拟合 beta 分布,并给出 alpha 和 beta 值。
from scipy import statselectoral_votes = [0.29, 0.7, 0.11, 0.13, ...]
beta_params = stats.beta.fit(electoral_votes, loc=0, scale=1)
beta_params# alpha, beta, loc, scale
>>>(1.032, 0.975, 0.001, 0.984)
α= 1.032,β= 0.975。图片作者。
这就是我们开始工作所需要的一切。拿起你的爆米花,舒适地躺在安乐椅上,准备好享受 2020 年选举数据吧。综合起来,你对这一周的期望应该是这样的:
从第一个(左)到最后一个(右)选举人票报告,每个候选人获得的全部选举人票的预测分数,必须大于 0.5 才能获胜。图片作者。
这就是测试版的美妙之处:易于使用,易于解释,易于更新。
最后一个提醒和免责声明:记住,你依赖于测试版的独立性来工作。要获得一个可行应用程序的更好的例子,请查看下面大卫·罗宾逊的棒球统计数据的例子。
资料来源和进一步阅读
- 贝叶斯推理——直觉和例子 由艾林·金在中
- 共轭在先 由艾林金在介质上解释
- 麻省理工学院 18.05 关于贝叶斯推断和贝塔分布的更多信息
- 【理解贝塔分布(使用棒球统计数据)】 作者大卫·罗宾逊,这是对贝塔分布的另一个很好的介绍,但是这次,你猜对了,是棒球统计数据。
- 【了解贝塔二项式回归(使用棒球统计)】 作者大卫·罗宾逊(与第一篇不同的文章),另一篇看贝塔分布及其背后的假设。
- 帖子使用的代码和投票数据可以在我的 GitHub 上找到
BetaBoosting
思想和理论
XGBoost 的学习速度非常快
TLDR: 传统上,像 XGBoost 这样的梯度推进实现使用静态学习率。我们建议使用一个函数,其参数可以传递到一个标准的超参数调整过程,以学习“最佳”的学习率形状。
所有代码都在这里: BetaBoost Github
关于升压的简要复习
在这一点上,我们都知道 XGBoost ,因为它在 Kaggle 等平台上举办的众多数据科学竞赛中取得了巨大成功。随着它的成功,我们已经看到了一些变化,如 CatBoost 和 LightGBM 。所有这些实现都基于 Friedman 开发的梯度推进算法,该算法涉及迭代地构建弱学习器的集合(通常是决策树),其中每个后续学习器都根据前一个学习器的错误进行训练。让我们从统计学习的元素来看一些算法的通用伪代码:
来自 ESL 的伪代码(图片由作者提供)
然而,这还不完整!一个核心机制是一个收缩参数,它在每一轮提升中惩罚每个学习者,通常称为“学习率”。它的主要功能是防止过度拟合,它是对梯度下降算法的一个很好的回调,该算法启发了梯度增强的许多方面。为了利用学习率,弗里德曼将 2.d 改为:
作者图片
现在,我们将每一轮的学习者乘以一个常数。但是我们应该用什么常数呢?这是一个常见问题,通常用超参数调整来处理,通常会产生一个常数,如. 1 或. 01。一些数字远低于 1,或者换句话说,一个严重惩罚每一轮的数字。由于人数少,我们无法最大限度地利用每个学员。
使用动态学习率
当具体查看学习率参数时,下一个自然的问题(尽管通常是不重要的)是为什么使用常数?梯度下降具有允许学习速率改变的动量策略。为什么渐变提升不能用类似的思路?
嗯,我们可以…
…它就是不起作用****。
快速的谷歌搜索显示,有一些工作是利用一个衰减的学习率完成的,这个学习率开始时很大,每一轮都在缩小。但是我们通常在交叉验证中没有看到准确性的提高,并且当查看测试误差图时,它的性能和使用常规的旧常数之间的差异很小。为什么像这样的方法不起作用背后的推理似乎是一个谜。这让我们想到了启发 BetaBoost 的一个核心主题:
这方面应该多做研究。
贝塔密度函数
为了与我们的主题保持一致,我们进行了研究,并发现了一个似乎很有前途的功能:beta 功能(当然还有一些护栏!).或者更具体地说,贝塔概率分布函数。这个函数最初是通过蛮力方法发现的,一旦它提供了令人鼓舞的结果,一些半连贯的基本原理就被挖掘出来了。
那么,什么是 beta PDF 呢?顾名思义,这是一个主要由两个参数描述的概率分布: α 和 *β。*除了这些参数之外,还增加了几个参数以及一些更进一步的“护栏”,这些参数似乎会有所帮助。出于我们的目的,我们很大程度上不关心函数作为概率密度函数的任何属性,只关心它与 boosting 的结果。
与许多其他功能相比,Beta PDF 的一个明显优势是您可以使用它实现大量的形状:
图片来自维基百科
如果我们想做类似指数衰减的事情,或者在中间产生一个大尖峰,只需要改变一个参数。这意味着如果我们将整个过程交给一个超参数调整包,比如 Hyperopt ,我们可以发现最适合(或过度适合)的学习率形状!)我们的数据。虽然,我们主要看到一个形状出现在顶部。
最终,我不知道为什么这些会有任何好处,所以:
在这方面应该做更多的研究。
BetaBoosting
这一切把我们带到了 BetaBoosting。这不是一个新的方法来建立一棵树或提出分裂。它只是在 XGBoost 的学习 API 中使用回调在每一轮提升中分配不同的学习速率。我们的具体实现基于 Beta PDf 分配学习率,因此我们得到了“BetaBoosting”这个名字。
该代码可通过 pip 安装,以便于使用,并要求 xgboost==1.5:
pip install BetaBoost==0.0.5
如前所述,特定的形状似乎比其他形状做得更好。这个形状在早期有一个很大的尖峰,由于我们的护栏,它很快就变成了一个“地板”参数。让我们看看使用类默认参数的 BetaBoost。这个函数将默认参数传递给 scipy Beta PDF 函数,还有一些附加的护栏。下面是一个简单的独立函数和实际的 BetaBoost 实现:
def beta_pdf(scalar=1.5,
a=26,
b=1,
scale=80,
loc=-68,
floor=0.01,
n_boosting_rounds=100):
"""
Get the learning rate from the beta PDF
Returns
-------
lrs : list
the resulting learning rates to use.
"""
lrs = [scalar*beta.pdf(i,
a=a,
b=b,
scale=scale,
loc=loc)
+ floor for i in range(n_boosting_rounds)]
return lrs
为了便于使用,这里列出了使用 BetaBoost 类的相同学习率:
from BetaBoost import BetaBoost as bb
import matplotlib.pyplot as plt
booster = bb.BetaBoost(n_boosting_rounds=100)
plt.plot(booster.beta_kernel())
plt.show()
作者图片
鉴于这种形状做得很好,这表明采取更大的步骤,不是在开始或结束时,而是在被促进的树发育的“青少年时期”提供最大的帮助。
为了进一步研究,我们可以用模拟数据运行它,并与其他学习率进行比较。
(下面的例子来自几年前的一个帖子,关于使用一个衰减的学习率,我找不到,如果有人找到了请告诉我,这样我就可以引用这篇文章了!)
首先,我们将进行导入并模拟一些数据:
import numpy as np
import xgboost as xgb
import matplotlib.pyplot as plt
def generate_data():
y = np.random.gamma(2, 4, OBS)
X = np.random.normal(5, 2, [OBS, FEATURES])
return X, y
max_iter = 300
eta_base = 0.2
eta_min = 0.1
eta_decay = np.linspace(eta_base, eta_min, max_iter).tolist()
OBS = 10 ** 4
FEATURES = 20
PARAMS = {
'eta': eta_base,
"booster": "gbtree",
}
X_train, y_train = generate_data()
X_test, y_test = generate_data()
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)
evals_result = {'train': dtrain}
接下来,让我们使用衰减学习率,并将我们的结果保存在一个字典中,我们最终将绘制该字典:
progress1 = dict()
model1 = xgb.train(
maximize=True,
params=PARAMS,
dtrain=dtrain,
num_boost_round=max_iter,
early_stopping_rounds=max_iter,
evals=[(dtrain, 'train'),(dtest, 'test')],
evals_result=progress1,
verbose_eval=False,
callbacks=[xgb.callback.LearningRateScheduler(eta_decay)]
)
现在,0.01 的标准常数:
progress2 = dict()
model2 = xgb.train(
maximize=True,
params=PARAMS,
dtrain=dtrain,
num_boost_round=max_iter,
early_stopping_rounds=max_iter,
evals=[(dtrain, 'train'),(dtest, 'test')],
evals_result=progress2,
verbose_eval=False,
callbacks=[xgb.callback.LearningRateScheduler(list(np.ones(max_iter)*0.01))]
)
常数 0.1
progress3 = dict()
model3 = xgb.train(
maximize=True,
params=PARAMS,
dtrain=dtrain,
num_boost_round=max_iter,
early_stopping_rounds=max_iter,
evals=[(dtrain, 'train'),(dtest, 'test')],
evals_result=progress3,
verbose_eval=False,
callbacks=[xgb.callback.LearningRateScheduler(list(np.ones(max_iter)*0.1))]
)
最后,我们的 BetaBoost,其中 fit 方法只是返回与 XGBoost 学习 API 中的 train 方法相同的输出
#Here we call the BetaBoost, the wrapper parameters are passed in the class init
bb_evals = dict()
from BetaBoost import BetaBoost as bb
betabooster = bb.BetaBoost(n_boosting_rounds=max_iter)
betabooster.fit(dtrain=dtrain,
maximize=True,
params=PARAMS,
early_stopping_rounds=max_iter,
evals=[(dtrain, 'train'),(dtest, 'test')],
evals_result=bb_evals,
verbose_eval=False)
让我们回顾一下每一轮测试准确性的结果:
plt.plot(progress1['test']['rmse'], linestyle = 'dashed', color = 'b', label = 'eta test decay')
plt.plot(progress2['test']['rmse'], linestyle = 'dashed', color = 'r', label = '0.01 test')
plt.plot(progress3['test']['rmse'], linestyle = 'dashed', color = 'black', label = '0.1 test')
plt.plot(bb_evals['test']['rmse'], linestyle = 'dashed', color = 'y', label = 'bb test')
plt.legend()
plt.show()
作者图片
查看最小测试集误差,我们看到衰减的学习率实际上最快地达到最小值,但这也是一个不稳定的结果,因为它很快开始过度适应测试集。下一个达到“拐点”的是 betaboosted 测试集。然而,与衰减测试集不同的是,我们可以看到,随着它的收敛,它的误差继续缓慢减小。最终,在迭代 300 左右,它遇到了对应于恒定的 0.01 学习率的错误率。因此,看起来我们在这两个方面都得到了最好的结果:我们非常快地收敛到接近最优的测试精度,然后我们可以抵抗过度拟合。但是,它真的表现最好吗?
号
在接下来的 100 次迭代中,静态的 0.01 略胜一筹。然而,情况并非总是如此,在下一篇文章中,我们将看到一些 5 倍 CV 结果,其中优化的 BetaBooster 实际上在真实世界数据上优于优化的 vanilla XGBoost!
摘要
使用β密度函数作为其学习速率的梯度增强似乎给了我们更快的收敛和对过拟合的鲁棒性。这样做的代价是要调整更多的参数。此外,随着学习速度调整某些函数的想法可以很快地添加到主要的增强包中,如 XGBoost 和 LightGBM,使用它们的回调功能。这看起来像是我们目前正在从岩石中榨出水的田地里的一个低垂的果实。
最终,BetaBoosting 回避了这个问题:
有更好的功能吗?
我们的回答是…
这方面应该多做研究。
参考
- 随机梯度推进。(1999 年 3 月)
- Hastie,Tibshirani,r .,,j . h . Friedman(2009 年)。统计学习的要素:数据挖掘、推理和预测。第二版。纽约:斯普林格。
- https://en.wikipedia.org/wiki/Beta_distribution
数据科学家和业务用户之间更好的沟通
记住,你是在解决一个商业问题,而不是科学实验。
通常,分析或数据科学中最大的挑战不是实际工作本身,而是将结果传达给通常自己没有任何技术背景的业务用户。有效的沟通可能比数据科学本身更重要,因为如果你不能让你的业务用户理解你在做什么,那么你就不能建立信任。如果人们不信任提建议的人,他们往往会拒绝接受建议……如果他们不明白你在说什么,他们也不会信任你。那么,怎样才能更有效地沟通呢?
- 在你开始着手解决方案之前,了解你的受众的技术成熟度
- 从业务用户的角度向后研究,了解他们如何看待和解释信息
- 从一开始就投资于如何以您的业务用户能够认同、理解和信任的方式解释解决方案
- ****采用业务用户的语言,使用简化的语言解释数据科学工作
- 使用图像、图形和可视化来解释分析概念;不要用方程式
- 解释数据科学时,目标是概念上的准确性,而不是数学上的准确性****
- 不要让完美成为好的敌人;有时,如果一个次优算法提供了好的结果并且易于解释和理解,那么从这个算法开始会更好
- 找一个不是技术人员的导师,并通过他或她运行你的结果;脸皮厚一点,当他们说“我不明白你在说什么”的时候,把它当作改善沟通的机会
有效沟通对于数据科学家个人和职业的成功至关重要。我能给你的最好建议是:“记住,你正在解决一个商业问题,而不是一个科学实验。“你应该始终围绕必须做出的商业决策来定位分析或数据科学,而不是将其视为一个有趣的数学问题来探索。如果你做到了这一点,那么你将开始理解有效交流数据科学的正确方式。
这篇文章补充了我在 2018 年 9 月做的一次播客采访,其中有标签数据谈话,将对我见过的许多行之有效的技术进行更深入的讨论。上面的八(8)种技术总结了我讨论的要点,但是我强烈建议你收听播客,以了解我在何时何地看过这些作品的完整背景。
使用 Python 中的双轴图形实现更好的数据可视化
大蟒
使用 Plotly 库以易于阅读的方式分析和展示您的数据
我才华横溢的姐姐的作品
可视化数据使人们更容易理解趋势并做出明智的决策。数据可视化的一个重要部分是选择合适的图表来展示数据。此外,甚至像条形图和折线图这样的特定图表也可以进一步定制,以最好地解释您想要展示的数据。
除了颜色和字体之类的修饰性变化,您还可以考虑添加额外的功能,如平均趋势线、预测或实现双轴。在这篇文章中,我们将介绍如何在折线图中使用双轴,让数据点之间的相关性和趋势对您的受众更加明显。我们还将快速看一下没有双轴的常规图表是什么样子,这样您就可以决定这两个图表中哪一个最适合您的可视化需求。
我们将使用 Python 中的 Plotly 库进行数据可视化,并使用 Pandas 进行一些初始数据预处理,所以请确保您已经安装了这两个包。然后,导入以下内容,并准备好跟随!
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import random
用 Plotly 简单实现一个规则折线图
首先,要生成一些示例数据,请运行以下代码。
expense_data = {
"Person": random.choices(["A", "B"], k=20),
"Amount": random.sample(range(100, 200), 10) + random.sample(range(0, 99), 10),
"Category": ["Groceries"] * 10 + ["Restaurant"] * 10,
"Date": pd.to_datetime(pd.date_range('2020-01-01','2020-10-01', freq='MS').tolist() * 2)
}
df = pd.DataFrame(data=expense_data)
我们将要可视化的数据将基于一些随机生成的个人支出数据。从上面可以看到,我们只是随机创建了 10 个月的费用数据,并将其加载到 Pandas 数据框架中。上面的代码应该输出 20 行数据。
**我们这次分析的目标是随着时间的推移比较“食品杂货”和“餐馆”的消费类别。**因此,接下来让我们使用几行熊猫按日期和类别字段对数据进行分组。
df_grouped = df.groupby(by=[pd.Grouper(key="Date", freq="1M"), "Category"])["Amount"]
df_grouped = df_grouped.sum().reset_index()
最后,仅使用 Plotly Express 的一行代码,我们就可以创建一个折线图,将分组的数据帧作为输入。
px.line(df_grouped, x="Date", y="Amount", color="Category")
Plotly Express 允许我们用一行代码生成上面的图表,在这里我们输入我们的数据帧、x 轴值、y 轴值和可选的color
参数,因此在图表中有多条彩色的线(每个类别一条)。
这个图表看起来很不错,但是正如你所看到的,比较这两个类别有点困难。这从直觉上讲是有道理的,因为你会认为,一般来说,人们每个月在食品杂货上的花费要比在餐馆旅行上的花费多。(此外,我们将这个逻辑硬编码到生成这个样本数据的代码中——您可以在上面仔细检查它。)
接下来,让我们看看如何实现双轴,以便更容易地比较两种不同类别的支出。
用 Plotly 创建双轴折线图
首先,我们需要使用make_subplots
(我们之前导入的)创建一个空的支线剧情。我们还将定义两个变量来命名我们的目标类别。
# making dual axis and defining categories
fig = make_subplots(specs=[[{"secondary_y": True}]])
category_1 = "Groceries"
category_2 = "Restaurant"
我们还没有输出任何东西,但是值得注意的是,在make_subplots
方法中,我们在specs
中传递了"secondary_y": True
,以确保我们稍后可以正确地实现双轴。
接下来,我们将手动创建折线图中的第一条线。
# creating first plot
fig.add_trace(
go.Scatter(
y=df_grouped.loc[df_grouped["Category"]==category_1, "Amount"],
x=df_grouped.loc[df_grouped["Category"]==category_1, "Date"],
name=category_1
),
secondary_y=False,
)
以前,使用 Plotly Express 让我们只需通过一行代码就能生成所有内容,这真的很容易。使用常规的 Plotly 库意味着我们需要编写更多的代码。上图中,我们在前面定义的fig
对象上使用了add_trace
方法来添加来自之前分组的数据帧的数据。我们之前还将plotly.graph_objects
作为go
导入,所以我们可以传入 x 和 y 列的值。最后,我们将secondary_y
设置为False
,因为这只是图表中的第一行。
如果您运行fig.show()
,您应该会看到类似这样的内容:
有点平淡,但目前为止还不错!现在,我们只有杂货数据。为了向第二行添加餐馆数据,我们将运行以下代码。
# creating next plot
fig.add_trace(
go.Scatter(
y=df_grouped.loc[df_grouped["Category"]==category_2, "Amount"],
x=df_grouped.loc[df_grouped["Category"]==category_2, "Date"],
name=category_2
),
secondary_y=True,
)
这几乎是完全相同的代码,除了我们使用category_2
并传入secondary_y=True
来代替。然后,如果您再次运行fig.show()
,您应该会看到类似这样的内容:
看起来更好!与以前不同的是,我们可以更容易地看到这两类支出数据在一段时间内的相对表现。这只是随机生成的数据,但你可以看到在某些月份,当食品支出高时,餐馆支出相对较低(反之亦然)。
我们可以通过编写更多的代码来添加轴标签,使这一点更加清楚,如下所示:
fig.update_yaxes(title_text=category_1, secondary_y=False)
fig.update_yaxes(title_text=category_2, secondary_y=True)
我们在这里使用相同的update_yaxes
方法,但是先传入 False,然后传入 True 到secondary_y
参数,以适当地标记两个轴。
到目前为止,这非常好,但是我认为我们可以稍微清理一下,将所有的逻辑移到一个适合重用的函数中。下面是我的实现:
def create_dual_axis_graph(input_df, *args):
# making dual axis initial fig
dual_axis_fig = make_subplots(specs=[[{"secondary_y": True}]])
# defining categories from kwargs
categories = [*args]
assert len(categories) == 2, f"Must only provide two categories. You provided {len(categories)}." # creating graph with loop
for count, category in enumerate(categories):
dual_axis_fig.add_trace(
go.Scatter(
y=input_df.loc[input_df["Category"]==category, "Amount"],
x=input_df.loc[input_df["Category"]==category, "Date"],
name=category
),
secondary_y=count,
) dual_axis_fig.update_yaxes(title_text=category, secondary_y=count) return dual_axis_fig
我们做的事情和以前完全一样,除了我们删除了一些有助于演示的重复内容。create_dual_axis_graph
函数将一个input_df
作为主参数(您可以像我们之前一样提供已经分组的数据帧),然后将*args
作为您想要检查的两个类别的名称。
我们将*args
放在一个列表中(同时检查该列表只有两个元素),然后遍历该列表并再次使用add_trace
方法添加 x 和 y 轴的数据。我们还将在这个循环过程中使用enumerate
,这样 0 或 1(它们是布尔型的)可以被传递到add_trace
和update_yaxes
的secondary_y
参数中,就像我们之前所做的一样。
运行该函数只需一行代码,如下所示:
create_dual_axis_graph(df_grouped, "Groceries", "Restaurant").show()
这将为您提供与之前完全相同的双轴图。为了展示不正确的实现会是什么样子,您可以尝试这样做:
create_dual_axis_graph(df_grouped, "Groceries", "Restaurant", "Appliances").show()
我们之前定义了一个AssertionError
来确保只有两个参数被传递到类别列表中。您还可以定义一种更全面的数据验证步骤,比如检查数据帧是否有正确的列,列值是否有正确的数据类型,所提供的类别是否确实在数据帧中,等等。然而,对于这个演示,上面的函数就足够了。
就这些了,伙计们!
我希望这个快速(半端到端)的数据分析和可视化演示对您有所帮助!我喜欢双轴图,因为它使得在相同的尺度上比较两个不必要的类别变得非常容易,并且因为 Plotly Express 没有一种本地方式来做到这一点,我认为与每个人分享这个实现会很棒。
祝您好运尝试这种方法并将其用于您自己的数据!
再次感谢你的阅读!如果你正在考虑成为 Medium 的付费会员,如果你使用我下面的推荐链接注册,我会非常感激!这会让我直接收到你的一部分会费,所以这将是一个很大的帮助。
https://byrondolon.medium.com/membership
**More by me:** - [Check for a Substring in a Pandas DataFrame](/check-for-a-substring-in-a-pandas-dataframe-column-4b949f64852?sk=bfb5bbab11ae45c47bfb316d931c3b56)
- C[onditional Selection and Assignment With .loc in Pandas](/conditional-selection-and-assignment-with-loc-in-pandas-2a5d17c7765b?sk=e5672d859a3964c1453a1c09edca22cf)
- [2 Easy Ways to Get Tables From a Website With Pandas](/2-easy-ways-to-get-tables-from-a-website-with-pandas-b92fc835e741?sk=9981ddaf0785a79be893b5a1dd3e03dd)
- [5 (and a half) Lines of Code for Understanding Your Data with Pandas](/5-and-a-half-lines-of-code-for-understanding-your-data-with-pandas-aedd3bec4c89?sk=7007a1ae248cf7ea4ef5fcd4af7ae72b)
- [Top 4 Repositories on GitHub to Learn Pandas](/top-4-repositories-on-github-to-learn-pandas-1008cb769f77?source=friends_link&sk=d3acc38062490a86ecb46875342224e6)
做得更好贝叶斯?
实践教程
用贝叶斯和频率统计规划我们的婚礼。
那是 2019 年夏天,我看着克罗地亚多云的天空,那时我深深改变了对统计的看法。在读完 Regina Nuzzo 的《p 值的诅咒》之后,我突然明白了——统计证据并不是我曾经认为的那样:即使是合理规划的随机实验的合理有力的“高度显著”的结果也可能变成假警报。因为即使是最聪明的科学家也无法关闭统计估计带来的自然不确定性。但还有一件事更让我感兴趣:即使是置信区间——我的大学教授曾经非常自豪地教给我们的一个概念——实际上也很少提到我们的估计带来的不确定性。在此之前,我认为置信区间反映了 95%最可信的参数值——或者至少包含了 95%情况下的“真实”值。但这要复杂得多。而且,我不知道我最初的解释甚至已经是贝叶斯理论了。在接下来的部分,我想告诉你传统假设检验的真正错误是什么——并更深入地探究理论基础。我的目标并不是以最不吸引人的形式呈现频繁主义者的统计概念,但我认为现在可能是时候对 p 值、置信区间和无假设显著性检验(NHST)进行更谦卑的解释了。那么,我们大多数人习惯的统计方法有什么问题呢?贝叶斯对等体真的能更好地找到我们问题的数据驱动答案吗?
有什么大惊小怪的?
假设我们正在进行一项实验,以发现与温水淋浴相比,定期冰浴是否真的能增强我们的免疫系统。如果你知道维姆·霍夫方法,这一假设应该会引起注意(艾伦,2018)。现在我们想知道相信冰浴真的对我们的免疫系统有很大影响有多合理——至少我们想避免在冰浴没有任何效果的情况下感到极度不适。因此,我们想用输入统计软件的真实数据来回答我们的问题。我们使用的数据分析(无论是 t 检验、方差分析、广义线性模型……)通常基于正式的数学模型。John Kruschke 和 Torrin Liddell (2018)提供了一个非常有说明性的定义:
你可以把数学模型想象成一台机器,它根据控制旋钮的设置,以某种模式产生随机的数据样本。例如,淋浴喷头喷出水滴(即数据)的模式取决于淋浴喷头的角度和喷嘴的设置(即参数)。”(克鲁施克&里德尔在 《贝叶斯新统计学:从贝叶斯的角度进行假设检验、估计、元分析和功效分析 (2018),第 2 页)
这意味着,不管我们使用的数据分析类型如何,我们总是试图通过统计模型尽可能好地模拟观察到的数据。为了达到这一目标,我们为机器(统计模型)配备了“模拟”自然的参数值,例如白细胞浓度随冰浴频率的变化。因此,我们可以将数据分析解释为对模拟观察数据的正确设置的搜索,以找到潜在的模式。换句话说:我们想知道“现实”是什么味道。
一旦我们有了想法,我们不想把它藏在心里——这就是为什么科学家喜欢用数学符号来表示数据。例如,众所周知,智力(以智商衡量)正态分布,参数 mu = 100,sigma = 15。有了这些数字,我们就可以对许多数据点进行简洁的总结,让我们能够对后续的观察做出推断:例如,我们可以说一个智商为 128 的人可能比你在街上遇到的绝大多数人都聪明。
许多研究人员的数学模型所基于的范式被称为频率主义统计学。它基于这样一种想法,即自然界的效应是固定的(但未知),而我们试图捕捉它们的数据是随机的。每一种经典的数据分析都包括基于虚数据采样分布的方法,这些方法会产生 p 值和置信区间。坚持我们的冰浴例子,统计计算将是这样的:为了证明在你的观察中是否有值得注意的模式,程序制造随机的假数据来表示如果冰浴是浪费时间会是什么样子。即便如此,参与者的免疫系统当然会有所不同——但这种差异完全是随机的,与任何温度控制无关。这就是零假设所代表的。现在,您的观察结果被汇总(例如,在 t 统计中),并与基于假样本的统计分布进行比较。根据冰浴和温水淋浴之间的“极端”差异,汇总统计留下了一定比例的实验可能结果。在这种分布的边缘,这些情况可以被认为是非常不寻常的,因为它们很少偶然发生。如果是这样的话,这应该让我们有点怀疑:我们应该考虑仔细看看。这就是 p 值所代表的——在一个零假设为真的世界中,观察到数据至少是这个极端值的可能性有多大?只有当您的数据收集完全遵循您的初始测试协议时,得到的估计才是正确的。按照惯例,我们不接受 p 值小于 0.05(或 0.01)就没有显著影响的观点。
拟议影响的大小及其不确定性通常基于最大似然估计(MLE),这是一种估计参数值的数学技术,使数据在模型环境中最有可能。是的——再读一遍这个句子。… 这使得数据最有可能出现在模型的上下文中 …这看起来是不是有点奇怪?
因此,置信区间是不会被正式假设检验拒绝的参数范围(例如,相对于某一免疫反应的平均差异)(坚持 p < .05)。因此,置信区间不一定给我们提供一系列我们可以“确信”的参数。除非你天生有一种非常技术化和数学化的思维方式,否则它无法被解释。
这就是对零假设显著性检验最深刻的批评的来源:没有办法直接和直观地解释统计结果。围绕这一概念有一个完整的误解指南,因为 p 值远非直观、简单明了(Greenland 等人,2016 年)-对于业余爱好者和研究人员来说都是如此。此外,有时似乎整个世界的分析师和研究人员都只盯着那个 p 值,战战兢兢地希望结果是“有统计学意义的”。我们对“中间”的任何结果都不感兴趣,是吗?学者们经常提到“过于简单化的非黑即白思维”(Kruschke & Liddell,2018)。当谈到有无效果时。然而,许多东西自然是灰色的。例如,暖浴和冰浴都不会强烈影响我们的免疫系统,而现实情况介于两者之间。出于对这一现象的好奇,我们想知道它的确切位置:这就是为什么我们需要对影响的大小进行一些估计(例如,冰浴能在多大程度上减少每年的感染数量?我们应该有多冷?)以及围绕该估计的不确定性(例如,我们对从我们的分析中得到的效应大小有多大把握?).
现在是时候对我们的分析程序采取更加细致和差异化的观点了——这是心理学研究多年来一直呼吁的事情:学者们主张从无意识的假设检验转向量化不确定性的估计,这种估计理想地建立在以前的研究基础上(Kruschke & Liddell,2018;Vandekerckhove,Rouder & Kruschke,20018),这一概念也被称为“新统计”(Cumming,2014)。
贝叶斯统计从何而来,它与频率主义者的观点有何不同?
虽然著名的贝叶斯定理在 1763 年左右就已经发表(Fienberg,2006)并且一直存在,但贝叶斯统计直到今天才流行起来。在世界上的每一门“初学者统计学”课程中,学生们在学习频率主义统计学之前——如果有的话——他们后来会发现贝叶斯统计。然而,与频率统计相比,贝叶斯估计可以更好地处理噪声数据和小样本,并且具有更直观和直接的解释。方便的是,有一些方法可以使用相同的统计程序(t 检验、相关性、ANOVAs 等)。)在“贝叶斯”术语中,它允许分析师结合关于所讨论现象的先验知识(例如,基于以前的数据,当涉及到免疫系统时,我们可以预期冰浴和温水淋浴的人之间有多大的差异?).这使得它成为促进元分析和持续研究的理想候选,这是一个很大的优势,我将在后面更深入地讨论。贝叶斯统计受到许多作者的喜爱,因为它有可能对抗心理学中的可信度危机(Kruschke & Liddell,2018 年),有能力减轻发表偏倚,有能力将更多可测试的理论纳入统计模型。尽管如此,贝叶斯并没有让你在分析数据时摆脱思维的束缚——我们无法从“动态”数据中得出有意义的结论,这是有充分理由的。即使我们可以认为显著性测试是科学中的一个坏习惯,贝叶斯显著性测试(即贝叶斯因子)本身并不能满足我们的问题。无论哪种方式,我们都必须全面处理利益问题。
那么,贝叶斯统计有什么不同呢?与频率统计相反,贝叶斯假设数据是固定的,而自然界的影响是未知的。因此,相应的估计可以被定义为不同可能选项的概率的重新分配。Kruscke & Liddell (2018)为这种思维风格提供了一个极好的类比(在Bayesian data analysis for the 新人, p. 2):夏洛克·福尔摩斯的任务是找到一个杀人犯。他从对每个嫌疑人不同程度的怀疑开始,不断寻找证据,让他重新考虑自己的观点。即使嫌疑人 A 从一开始看起来相对无辜,但一旦排除了其他嫌疑人(例如,因为他们有强有力的不在场证明,他们的动机与犯罪不符,等等),他/她似乎更有可能犯了罪。…).按照贝叶斯的说法,夏洛克·福尔摩斯从对每种可能性(犯罪嫌疑人)的先验信任度开始,逐渐重新分配每种可能性的可信度,并以后验信任度结束——这是他在跟踪最有可能犯罪的人时应该非常确定自己的猜测的地方。这一过程非常接近我们的自然推理方式,并转化为以下模型:我们从各种可能的参数组合开始,根据我们到目前为止的知识,某些值或多或少是可能的,这称为先验分布。现在,我们收集数据,并可以计算每个数据点被赋予我们所知道的总体效果的可能性——这被称为可能性分布。看到这些数据后,我们的知识需要更新,因为我们现在对哪些参数是可信的有了更狭隘的理解。我们认为与数据不一致的参数值可信度较低,因此与数据一致的参数值可信度较高。我们对理论上可能的每个参数值重复这一过程——这种数据驱动的洞察然后产生后验概率分布。这种分布总结了我们新的知识状态,并可以为未来的分析师提供服务,以建立他们对类似问题的“先验信念”。
多亏了这个程序,我们可以更彻底地测试各种假设:虽然 NHST 只能拒绝零假设(由低 p 值表示),但贝叶斯假设测试的结果不仅拒绝或接受假设,还包含一个“灰色区域”——对于在给定数据的情况下仍未决定哪个假设更有可能的情况。有时我们只是还不知道——这种证据状态在研究中应该很常见,因为自然很复杂,很难理解。因此,“介于两者之间”的结果应该相当令人放心。但是这个选项经常被我们提供“重要”结果的需要所否决。贝叶斯假设检验有三种状态:
- 数据提供了有利于 H0 的充分证据
- 数据提供了有利于 H1 的充分证据
- 数据无法支持任何一种假设
这种三方面的区别导致了这样一个事实,即贝叶斯和频率主义分析并不总是得出相同的结论,即使它们基于相同的数据(Dienes & Mclatchie,2018 年)——提供支持任一假设的证据的能力与早期完全不同。贝叶斯假设检验可以表明零假设比替代假设(或者相反)更可信,而 NHST 永远做不到这一点,因为它不产生相对概率。
请记住,当使用频率统计时,我们只能测试针对 H0 的证据*——如果我们假设没有任何影响,这些数据看起来够奇怪吗?这是一个有点麻烦的技术,因为我们通常对支持替代假设的证据更感兴趣。我妈妈会说我们好像是“从后面穿过胸腔进入眼睛”(而不是直视)。即使我们非常确定我们的数据在“无效效应”的情况下似乎不太可能,我们也无法知道我们脑海中的选择是否正确。我们甚至不知道零假设首先是否是假的。我们掌握的证据相当薄弱,实际上我们的问题仍未解决。似乎这还不够糟糕,p 值还伴随着其他(方法论)问题,使它们变得非常不方便(例如,著名的“测试和停止意图”)。*
总之,贝叶斯统计和频率统计之间的差异可以总结如下:
- 对于常客来说,效果是固定的,而数据是未知的,而对于 Bayesians 来说,数据是固定的,效果是未知的。
- Frequentist 方法基于从零假设采样的虚构数据提供 p 值,而 Bayesian 方法比较数据的相对能力,以支持零假设、替代假设或两者都不支持。
- 频率主义者的推理基于观察给定假设的数据的概率,而贝叶斯主义者估计给定数据的某个假设的概率。
案例分析——我如何才能知道哪个月会足够温暖,适合我的婚礼派对?
几个星期前,我已经开始和我一生的挚爱计划婚礼。我们想和我们最亲密的家人和朋友在他父母的花园里开一个小派对。但是在组织一切的时候,我们在想我们最好是在四月还是五月结婚,因为我们想在外面庆祝。总的来说,四月是个不错的选择,因为我的肚子还没有五月大,而且柏林的天气已经很热了。另一方面,五月可能是一个更好的候选人,因为有更多的时间让 COVID 感染下降,天气应该足够温暖——但我们能有多确定?
Honey Yanibel Minaya Cruz 在 Unsplash 上拍摄的照片
作为一名数据科学爱好者,我将使用数据来回答我的问题。为此,我将使用传统的频率主义方法以及一些贝叶斯对应方法。首先,我查看了一些历史温度数据。我发现了一些有趣的表格——柏林自由大学的 rg Wichmann 和 Manfred Wegener 发表的气象数据集合。这些表格显示了自 1908 年以来柏林-达勒姆每月每天观测到的最极端最高日温度以及平均最高日温度。为了对四月和五月的极端和正常最高温度有一个印象,我提供了相应的数据:
为了绘制结果,我将温度值的每个向量保存在一个数据帧中,并将它们整理成一种更整洁的格式。
数据几乎已经准备好用于绘图——我们只需要设置调色板并保存每个参数的平均值(最大值、最小值、平均值),用密度图明确表示它们。
看起来柏林四月份的平均最高温度为 13.4°C(SD = 1.52),而最热日的温度通常在 0.5°C 到 30.9°C 之间变化——在柏林天气数据的历史上,四月份有非常寒冷的日子(例如 1911 年 3 月 4 日),但也有非常温暖的夏天(1968 年 3 月 22 日)。通过观察 4 月份每天的正常最高气温,我们可以发现,4 月上半月的最高气温约为 11°C,而 4 月下半月的最高气温可达 15°C 左右。这也解释了 4 月份平均最大值数据的密度曲线的下降。嗯——五月会有不同的趋势吗?
我们可以预计一个典型的五月天的温度将达到 18.7 摄氏度(SD = 1.51),正如所料,这比一个典型的四月天要暖和得多,即使正常的最高温度变化程度不同。历史上,我们经历过 5 月份的最高日温度在 3.8 摄氏度(1941 年 5 月 3 日)和 33.3 摄氏度(2005 年 5 月 28 日)之间。与 4 月相比,有史以来观测到的最低最高温度(用蓝色表示)比有史以来观测到的最高温度(用红色表示)覆盖的数值范围更广。这可能是因为与四月相比,五月不太可能出现寒冷的气温(尽管我们有几个稍微凉爽的五月天),但当一个典型的五月天无论如何都是温和的,很难超过真正炎热的夏季温度。与 4 月相似,接近月末时天气变得越来越暖和,5 月上半月的温度约为 17°C,下半月的温度约为 19°C。但是我们能有多确定五月对于我们的游园会绝对是一个更好的选择呢?
通过从五月的正常最高温度中减去四月的正常最高温度,我们得到一个差值向量。因为 May 包括多一天,所以我们需要排除最后一个值,以便进行公平的比较和便于计算。我们最后得到以下描述性统计数据:
嗯,看起来五月的一个典型日的最热时刻通常比四月的一个典型日的最热温度高 5.27°C,而它通常相差 1°C。一般来说,自 1908 年以来的几十年中,正常的最大温差在 3.7°C 到 6.4°C 之间。但是,五月和四月的最高气温实际上没有差别,这种可能性仍然存在吗?
假设我们只有去年(2020 年)的数据。
为了检验我们的假设,我们首先计算独立样本的经典 t 检验。
如您所见,p 值超过 0.05,这意味着很有可能只是偶然观察到这些温度差异。通过查看置信区间,我们可以看到给定数据下包含 95%最可能温差的范围,对吗?不。我们不知道 CI 包括的温度差异中哪一个更可能,因为没有包括分布信息:区间中间(大约 0)的参数值不一定比 CI 边缘的值更可能。我们可以说,如果用相似的数据反复进行相同的实验,95%的温度平均差异将在-1.51 和 2.71 之间,包括零(无差异)。如果我们真的只有 2020 年的数据,我们会决定暂时不拒绝零假设。好吧,但是贝叶斯如何解决这个问题呢?
首先,我们当然会使用所有可用的温度数据,但我想让算法更难模拟最糟糕的情况:实际缺乏数据。如果我们有一个杂乱的小样本,数据分析表明了什么?
让我们来探索理查德·d·莫雷和他的同事们(2015)的 BayesfactorR-package 中的贝叶斯 t 检验。我们正在分析 Bayes 因子,以检验替代假设(五月和四月之间的温差)和零假设(无温差)。
[1] Alt., r=0.707
–这是指差异可能有多大的假设,而默认值是基于心理学中常见的通常效应大小。我们可以使用 ttestBF-语法来改变这个假设,但是我们暂时不做讨论。
贝叶斯因子是数据中支持两个假设之一的相对证据。换句话说,它是一个假设比另一个假设更好地预测观察到的数据的程度。在这里,我们计算替代的 hyothesis(五月和四月之间的温差)比无效的零假设能更好地预测观察到的数据的程度。由于贝叶斯因子在我们的案例中已经下降到 1 以下,证据表明 H0 比 H1 更有利(杰弗里斯,1998)。如果原假设的先验概率相对于替代假设减少了 0.30 倍,这表明我们现在应该接受原假设,因为支持我们替代假设的证据还不够有力。即使贝叶斯因子和 p 值并不总是一致,经验法则表明,0.05 的常规 p 值大致等于贝叶斯因子 3 (Dienes,2014;Jeffreys,1998)即使一些研究人员总体上要求更高的决策阈值(Etz & Vandekerckhove,2017;Schö nbrodt 等人,2016 年)—在我们的案例中,贝叶斯因子和 p 值都表示保留零假设。
然而,我们应该记住,拒绝零假设的事实并不能告诉我们任何关于效果大小的信息。当——就像在我们的例子中——零假设没有被 p 值拒绝或者甚至没有被贝叶斯因子接受时,人们倾向于相信实际上存在零效应。鉴于 2020 年的温度数据只是 100 多年来可用温度观测的一部分,仍然有理由相信 5 月实际上仍然比 4 月更温暖。如果我们对以前的一组历史温度数据进行相同的分析,我们会得到不同的结果,这一事实支持了这一想法(为了清楚起见,我在这里不给你看)。
好的——我们现在想知道根据我们的后验分布,可信的温度差是什么样的:
从图中可以看出,MCMC 迭代运行稳定,我们现在知道日温差可能在-2°C 和 2.5°C 之间,中间值约为 0.48°C。
使用 Makowski 及其同事(2020 年)的bayestr-package,我们还可以从后验分布中计算出参数值的数量,这些参数值代表实际上相当于“无影响”的温度差异。例如,如果五月的平均气温比四月高 1 摄氏度或低 1 摄氏度,我不会选择五月而不是四月来举办我们的游园会。从统计学上讲,我们可以计算实际等效区域(ROPE ),该区域被定义为“零”值周围实际等效于“无效”的区间。在临床研究中,它可以用来测试实验组是否实际上不同于对照组,因此已经纳入了一种“最小”效应大小(有关函数的详细概述,也请参见:马科夫斯基,本-沙查尔&吕代克,2019 )。
结果表明,72.3 %的温度差异位于我们预先定义的实际等效区域内,这意味着不到三分之一的数据指向五月和四月之间有意义的差异。为了找出哪个月实际上更暖,我们可以计算方向概率(PD)——它可以被解释为观察到的温差(由其后验分布描述)严格为正或负的概率(以最有可能的为准)。在数学上,它被定义为后验分布中中位数符号的比例(在我们的例子中是正的,表明五月比四月暖和)。
在我们的例子中,根据我们的后验分布,有 69.70 %的可能性五月比四月暖和。
鉴于我很确定无论如何五月可能是一个更好的选择,我想测试一个具体的日期:五月 28 日天气够暖和可以在外面庆祝吗?
我的决定规则是:如果结果表明我们婚礼当天的某个时候气温可能会达到 21 摄氏度或更高,我可以在室外庆祝。那么,5 月 28 日气温超过 21 摄氏度的可能性有多大?
当我在寻找一种频率主义方法来回答这个问题时,我偶然发现了基于历史天气数据预测气温的 ARIMA 模型。但是因为这似乎超出了本文的范围,我们将直接跳到贝叶斯方法。此外,我将向您展示如何从零开始应用贝叶斯方法,不涉及任何特殊的 R-package,灵感来自 Rasmus B eth 的 R 中的课程贝叶斯数据分析基础。为什么?这样,通常发生在幕后的必要步骤对您来说变得更加明显。
首先,我们需要一些新的温度数据。我发现一个网站提供了过去 10 年中柏林 5 月 28 日的最高气温。我们将使用这些数据和我们“更多”的历史数据来估算 2021 年最有可能的最高温度。
现在,我们需要为温度数据定义一个生成模型——您可以将它视为未知的潜在分布模式,它可能会在几年内生成 5 月 28 日的最高气温。为此,我们需要一个可能值的参数空间来表征 5 月 28 日最高气温数据的“真实”分布,因此我们指定 mu(总体均值)和 sigma(总体标准差)。当然,我们无法真正知道真实的潜在分布,但基于我们在上一节中建立的关于所有 5 月最高日温度的知识,我们可以假设 mu 可能位于 10°C 和 30°C 之间,sigma 可能在 0.5°C 和 6°C 之间。即使我们想对 5 月 28 日进行预测,我们使用从上个世纪的极值中获得的信息也会有点保守。通过使用网格近似,我们将测试 mu 和 sigma 的任何可能的参数组合,以计算其与我们已有数据的兼容性。
网格将足够宽和细粒度,以表示理论上可能的任何参数组合。结果参数空间如下所示:
接下来,让我们定义 mu 和 sigma 的先验概率——基于我们对每个可能参数与我们所知的可能性的信念。通过查看 FU 温度数据,我们可以看到 5 月 28 日的平均最高温度为 20°C,我猜每年可能相差 3°C 左右。此外,我假设平均温度呈正态分布,因此我们将此信息放入 dnorm 函数中,以创建适当的密度函数。然而,对于 sigma,我认为 0.5°C 和 8°C 之间的任何值都是同等可能的,因此我将使用均匀分布。最高温度数据的先验现在基于μ和σ,并相乘以获得组合的先验概率分布。
现在需要为每个可能的参数组合计算数据的可能性,假设可能性函数接近正态分布。然后,我们结合这一计算,分别为每个可能的参数组合获得所有 10 个温度观测值的似然值。
根据贝叶斯法则,我们计算后验分布如下:
后验∝先验*似然/先验加权的似然之和
在考虑新数据后,mu 最可信的参数值似乎在 22°C 左右,sigma 最可信的参数值在 6°C 左右。
哇,终于到了预报我们婚礼天气的时候了!现在,让我们根据我们创建的模型,尝试预测 5 月 28 日最可信的最高气温。在通常的贝叶斯软件解决方案中,我们将通过使用马尔可夫链蒙特卡罗方法,从后验概率分布(在我们的情况下为后验 28)中随机抽样最可信的一组参数值来实现这种预测。对于本例,我们将通过从模拟概率分布中随机抽样 mu 和 sigma 来简化这种方法,模拟概率分布直接由我们的后验分布提供信息。出于预测目的,我们使用 mu 和 sigma 的后验分布来模拟 10000 个新鲜温度样本。
好的——不错!在我看来,我们将会有一个 21 摄氏度左右的最高气温,但是超过 21 摄氏度的可能性有多大呢?
sum(pred_temp >= 21 ) / length(pred_temp)
大约 55%的预测样本超过 21 摄氏度。老实说,这比我希望的要少,但我们将能够举办一次花园聚会的机会并不坏。现在,5 月 28 日最高气温的最可能值是多少?
为此,我们将计算最大后验概率(MAP ),定义为后验分布的最可能值。
根据我们的计算,我们现在知道 5 月 28 日平均最高日温度的最可信值是 22.93 摄氏度。鉴于我们仍然有些不确定,哪个温度范围也是可信的呢?
与 frequentist 置信区间相反,我们可以直接从后验分布中“读出”估计的不确定程度。更具体地说,在给定数据的情况下,最高密度区间(HDI)跨越了 95%最可能的参数值。换句话说,它是一个区间,从该区间开始,所有包含的值比该区间之外的值具有更高的概率。在我们的例子中,我们预计 mu 的最可信值在 12°C 和 30°C 之间(HDI 89% [12,30])。
总的来说,当谈到在户外庆祝时,我现在更有信心了——我关于选择五月而不是四月的问题,以及 28 日气温的预测,都没有用 Frequentist 统计数据充分回答。我知道我们应该多带些外套以防万一。但是为什么贝叶斯估计在我的案例中胜出呢?在总结之前,让我们转向理论层面。
贝叶斯统计的优点是什么?他们能做得更好的是什么?
贝叶斯统计可以直接解释,并且符合我们的自然推理。
从我的角度来看,贝叶斯统计最根本的优势在于能够对我们最初提出的问题给出令人满意的答案。相比之下,传统统计学在大多数情况下实际上是基于错题。例如,我们不想要今天下雨的概率(这有点荒谬),而是今天下雨的概率。翻译成概率术语,它转换成这样的事实,即频率主义者要求给定(空)假设为真的数据的概率,而贝叶斯主义者要求给定数据(例如,今天的天气参数)的假设的概率(例如,将下雨)。第二个问题肯定更有趣—这可能是为什么 p 值和置信区间被解释为好像它们是贝叶斯的(例如,p 值 0.05 意味着零假设为真的概率是 5%,对吗?…).如果我们得到了与我们想知道的完全相反的结果,为什么我们会有兴趣首先测试它呢?
贝叶斯统计促进信息丰富的&合作研究。
在心理学研究和许多其他学科中,实际的研究不仅仅是由寻找真相的动机驱动的:包括“无关紧要”结果的草稿仍然留在大型科学期刊的文件抽屉中——各自的研究可能不够醒目,不足以吸引读者的注意,即使其他研究人员可能有兴趣找到发现。一些作者认为,贝叶斯估计可以通过定义一个不同的成功标准来克服这种出版偏差:编辑应该根据一项研究的实际限制条件是否达到了合理的精确度来检查草稿,而不是专注于统计意义(Kruschke & Liddell,2018)。因此,高度精确的结果在研究中应该比高度“重要”的结果更有价值——因为独立研究应该是开放式的。参考开放科学的理念,预先登记研究的过程也有助于减少偏见。
此外,贝叶斯估计允许对任何样本大小进行稳健估计——这对于习惯于追求足够大的 Ns 的人来说是非常方便的先决条件。这不是没有原因的:p 值和置信区间需要足够大的样本大小来进行可靠的计算和足够的能力,而另一方面,它也不应该太大,因为算法往往会过于乐观,甚至会拾取最微小的影响。对频率主义者统计数据的依赖带来了另一个问题:估计不仅会因样本大小而产生偏差,还会直接依赖于分析师的确切测试和停止意图。这意味着,如果我们计划测试 50 名参与者,结果却只有 60 名,那么 p 值应该会受到影响。为什么?因为频率主义者的统计是基于模拟的,可能结果的云随着我们最终得到的每一个额外的(或缺失的)观察而变化。一个类似的原则适用于进行比原计划更多的测试:我们可以观察到 p 值的膨胀,因为小的 ps 变得越来越没有价值。这是因为我们每进行一次额外的测试,发现任何重要结果的机会就会增加。因此,我们必须明确地对多个测试进行校正(例如,使用 Bonferroni 校正)。对于贝叶斯估计,我们不担心固定的 N 个观察值或测试值,因为它不是基于假想分布的抽样。
贝叶斯估计的另一大好处是,它促进了持续研究和累积知识的增长,这种想法通常是通过汇总特定现象的证据状态的元分析来实现的。理想情况下,随着越来越多的研究进行,我们希望积累我们的知识,并使证据不断发展。因此,单个研究应该基于以前的研究,并作为未来研究的基础,以最终得出更可靠的结论。然而,我们迄今为止的荟萃分析可能会得出错误的结论,因为 a)有些研究从未发表,b)一些包含“无关紧要”结果的研究经常被解释为证明自然界中绝对没有影响。如果有更多发表的基于贝叶斯估计的数据分析,我们将对反对、支持或不支持某个假设的试验性证据有一个更全面、更精细的看法。更好的是,贝叶斯估计带有一个特殊的随机效应模型,以从合作研究中获得洞察力:元分析可以分层建模,为我们提供每个个体(低水平,例如单个研究)和一般(高水平,例如跨研究的整体变化)参数的描述(Kruschke & Liddell,2018)。这使得在数据中找到潜在的模式变得更容易,同时允许研究之间的一些可变性。
贝叶斯统计反映了证据的连续程度。
当涉及假设检验时,p 值和贝叶斯因子都包括“有用的”约定,这些约定反映了足以值得注意的证据程度。然而,贝叶斯因子仍然遵循另一个基本原理:它代表证据的连续程度。在我们的例子中,它展示了一个微小的暗示,即 2020 年 5 月和 4 月的最高日温度之间应该有差异,即使它通常让我们认为有更多的证据支持零假设。我非常欣赏这种想法,因为对于 p 值来说,没有明显的界限或必要的阈值,为数据驱动的见解留下了更多空间,这些见解由分析师的经验所伴随和告知。因为我们将证据理解为证据的阴影,并且每个估计的不确定性都被明确地建模,贝叶斯统计使我们对自己的解释更加谦逊(也更加自信)。
贝叶斯统计让我们记住了舞蹈。
另一个支持贝叶斯统计的论点是,它承认自然界多样性的美。我的意思是,它可以将我们的注意力转移到随机和动态的变化上,这些变化自然地发生在样本之间,甚至发生在个体之间。换句话说,贝叶斯估计可以帮助我们记住数据的“舞蹈”(Cumming,2014)。相反,Frequentist 模型并不明确地以数据为条件,而是以虚拟样本的模拟为条件,以找出我们的数据在面对特定场景时有多奇怪(例如,如果五月和四月之间的最高日温度相同)。使用贝叶斯估计,我们可以模拟非常复杂的系统,同时仍然允许不同的人,措施和研究的可变性。
贝叶斯统计的缺点是什么?为什么它不能让我们摆脱所有的问题?
贝叶斯统计比频率统计更直观、更灵活、信息量更大——这是肯定的。然而,在比较这两种范式时,我们应该记住,现实世界的决策不应该基于单个研究的 p 值或贝叶斯因子是否超过某个阈值这一事实。对统计显著性概念的滥用告诉我们,我们应该尽一切可能避免这种对甚至无法复制的结果的机械的非黑即白的思考。在解释数据时,任何统计指标都不能作为唯一的推断来源——相反,分析师可以从各种不同的统计工具中受益。用著名科学家 Gerd Gigerenzer 和 Julian Marewski 的话说,贝叶斯因素不应成为又一个“盲目的无效仪式”(Gigerenzer 和 Marewski,2015 年,第 423、437 页)。
此外,贝叶斯估计受到主观性的指责,因为先验分布的规范给分析者留下了更多的自由度。即使我们也能欣赏结合相关背景知识的机会,但这让我们承担责任:我们需要有意识地选择先验知识,并事先形成理论上合理的假设。如下,先验分布应该尽可能具体。让我给你举个例子:如果我们假设零假设的可信度很小,那么贝叶斯因子必须很大才能产生实际上有利于零假设的后验概率。因此,贝叶斯估计直接受到分析师背景知识的影响。这可能会阻止年轻而天真的分析师去尝试——但事实并非如此。
哪个范式能更好地回答我的问题?
我们可以说,如果准确性是你的目标,贝叶斯统计应该是选择的估计,而如果减少假阳性率是你的目标,频率统计是你的伙伴。在我看来,这肯定也取决于你的个人喜好。就我个人的案例研究而言,我更喜欢贝叶斯统计,因为它对我来说信息量更大,即使我花了一些时间才弄明白。不幸的是,贝叶斯估计很少在大学教授,因此一些专业人士可能会在没有深入知识的情况下犹豫使用它。可以理解!这两种方法都应该在适当的时候使用——考虑到自然通常是复杂的,我们只有有限的可能性通过数据来接近真相。但是如果我们尝试,让我们保持一点谦卑。我们永远无法确切知道。
参考文献
[1] J. Allen,“维姆·霍夫方法的用户特征和报告效果:一项混合方法研究” (2018),特温特大学硕士论文。
[2] J. K. Kruschke & T. M. Liddell,贝叶斯新统计:从贝叶斯角度进行假设检验、估计、元分析和功效分析 (2018 ),心理计量学通报&综述,25(1),178–206。
[3] S. Greenland,S. J. Senn,K. J. Rothman,J. B. Carlin,C. Poole,S. N. Goodman & D. G. Altman,统计检验,P 值,置信区间和功效:误解指南 (2016),《欧洲流行病学杂志》, 31 (4),337–350。
[4] J. K. Kruschke & T. M. Liddell,新人贝叶斯数据分析 (2018),心理计量学通报&综述,25(1),155–177。
[5] J. Vandekerckhove,J. N. Rouder,J. K. Kruschke,推进心理科学的贝叶斯方法 (2018),心理计量学通报&综述 (25),1–4。
[6] S. E. Fienberg,贝叶斯推理什么时候变成了“贝叶斯”?(2006)贝叶斯分析,1(1),1–40。
[7] Z. Dienes & N. Mclatchie,比显著性检验更喜欢贝叶斯分析的四个理由 (2018),心理计量学通报&评论,25(1),207–218。
[8] H .杰弗里斯,《概率论》(1998),OUP 牛津大学出版社。
[9] Z. Dienes,使用 Bayes 从非显著性结果中获取最多信息 (2014),《心理学前沿》,5781 页。doi:10.3389/fpsyg
[10] A. Etz & J. Vandekerckhove,关于再现性项目的贝叶斯观点:心理学 (2016),PloS one,11(2),e0149794。
[11]f . d . schnbrodt,E. J. Wagenmakers,M. Zehetleitner & M. Perugini,带 Bayes 因子的序贯假设检验:有效检验均值差异 (2017),心理学方法,22(2),322。
[12] D. Makowski,D. Lüdecke,M. S. Ben-Shachar,M. D. Wilson,P. C. Bürkner & T. Mahr,Package‘bayeststr’(2020),最后一次查看于 2020 年 8 月 20 日。
[13] D. Makowski,M. S. Ben-Shachar,D. Lüdecke,bayestr:描述贝叶斯框架内的效应及其不确定性、存在性和意义 (2019),开源软件杂志,4(40),1541。
[14] G. Cumming,《新统计:为什么和如何》 (2014),心理科学, 25 (1),7–29。
更好的带 Katib 的 ML 模型
Kubernetes 上的自动机器学习超参数调整
由 Markus Gjengaar 在 Unsplash 拍摄
在机器学习中,超参数是用户定义的值,在训练期间保持固定。超参数的例子是 k-means 聚类中的k
值、学习速率、批量大小或神经网络中的隐藏节点数。
虽然现在有一些技术依赖于在我们的模型学习时改变这些值(例如,Leslie Smith 的单周期策略、模拟退火等)。),这些不是可学习的参数,例如神经网络的权重。
然而,超参数可以极大地影响由训练过程生成的模型的质量以及算法的时间和存储器要求。因此,必须调整超参数,以获得给定问题的最佳配置。
我们可以手动或自动调整模型的超参数。在大多数情况下,手工执行这项任务是不切实际的。因此,自动超参数调整机制将有助于在合理的时间范围内发现每个超参数的最佳值。
许多系统自动完成这一过程。这个故事考察了 Katib ,这是一个开源的、框架无关的、云原生的、可扩展的、生产就绪的超参数调优系统。但是为什么我们需要另一个超参数优化引擎呢?我们已经有了众多的选择: Optuna ,远视, NNI ,维齐尔,或者雷。所以,首先,让我们看看 Katib 做了什么来改善现实世界中的事情。
Learning Rate 是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。订阅这里!
动机
要在生产环境中部署机器学习系统,我们必须同时满足数据科学家和 DevOps 工程师的需求。这并不容易,因为环境的这两个用户很少说同一种语言。
数据科学家对开发尽可能精确的 ML 模型感兴趣;因此,要调整模型的超参数,它们的工作方式如下:
- 使用数据集的一个样本,在他们的本地机器上试验 HP 调优
- 将实验转移到更大的计算环境中,在那里可以利用专用硬件的能力,如 GPU 或 TPU
- 比较并可视化结果
- 在团队内部跟踪、版本化和共享结果
另一方面,DevOps 工程师管理基础设施,确保平台保持健康和高度可用。我们可以将开发运维工程师的职责总结如下:
- 执行资源高效型部署
- 支持多个用户,通过动态资源分配在同一系统中执行不同的操作
- 实时升级系统,不会给用户带来任何停机时间
- 通过日志记录监控系统并及时做出决策
定义了背景之后,我们需要我们的系统来工作,让我们看看 Katib 如何应对这些挑战。
Katib 优势
Katib 是唯一一款能够在本地数据中心或私有/公有云中作为托管服务运行的惠普调优系统。这是真实的原因有很多:
- 多租户: Katib 支持多租户,这有利于跨团队协作。维齐尔也支持多租户;然而,Vizier 是一个专有系统。
- 分布式训练: Katib 支持分布式训练(如参数服务器、RingAllReduce 等。).像 Optuna 和 HyperOpt 这样的流行框架缺乏对分布式训练的支持。
- Cloud-native: Katib 是 Kubernetes 准备好的。这使得它非常适合云原生部署。射线调谐和 NNI 也支持 Kubernetes,但需要额外的努力来配置。
- 可扩展性: Katib 很容易扩展,提供了一个模块化接口,允许搜索算法和数据存储定制。
- NAS: Katib 是仅有的两个支持神经架构搜索的框架之一,另一个是 NNI。
因此,作为一个支持多租户的分布式容错系统,Katib 同时满足了数据科学家和系统管理员的需求。
系统工作流程
现在让我们检查一个典型的工作流,用户将遵循这个工作流与 Katib 进行交互。在本例中,我们将使用贝叶斯优化创建一个 HP 调优作业。
- 用户可以创建 YAML 规范并使用客户端工具(如
kubectl
)提交,也可以通过编程方式与 Katib 通信。这里,为了清楚起见,我们将做前者。因此,让我们创建一个Experiment
的 YAML 规格。
apiVersion: "kubeflow.org/v1beta1"
kind: Experiment
metadata:
namespace: kubeflow
name: bayesianoptimization-example
spec:
objective:
type: maximize
goal: 0.99
objectiveMetricName: Validation-accuracy
additionalMetricNames:
- Train-accuracy
algorithm:
algorithmName: bayesianoptimization
algorithmSettings:
- name: "random_state"
value: "10"
parallelTrialCount: 3
maxTrialCount: 12
maxFailedTrialCount: 3
parameters:
- name: lr
parameterType: double
feasibleSpace:
min: "0.01"
max: "0.03"
- name: num-layers
parameterType: int
feasibleSpace:
min: "2"
max: "5"
- name: optimizer
parameterType: categorical
feasibleSpace:
list:
- sgd
- adam
- ftrl
trialTemplate:
primaryContainerName: training-container
trialParameters:
- name: learningRate
description: Learning rate for the training model
reference: lr
- name: numberLayers
description: Number of training model layers
reference: num-layers
- name: optimizer
description: Training model optimizer (sdg, adam or ftrl)
reference: optimizer
trialSpec:
apiVersion: batch/v1
kind: Job
spec:
template:
spec:
containers:
- name: training-container
image: torch-mnist:v1beta1
command:
- "python3"
- "/opt/torch-mnist/mnist.py"
- "--batch-size=64"
- "--lr=${trialParameters.learningRate}"
- "--num-layers=${trialParameters.numberLayers}"
- "--optimizer=${trialParameters.optimizer}"
restartPolicy: Never
一个Experiment
是一个定制的 Kubernetes 资源(CRD ),指的是一个完整的用户任务。例如,这里的Experiment
命令 Katib 运行一个贝叶斯优化任务。目标是通过调整学习率或优化器选择等参数来最大化验证的准确性。它将并行运行3
试验,如果没有达到目标(即验证精度> = 0.99
),它将在12
试验后终止。
在这种情况下,我们对自己创建的 MNIST 数据集使用 PyTorch 解决方案。
2.这将触发一个Suggestion
规范的创建。Suggestion
是另一个 Kubernetes CRD,它请求创建基于优化算法的x
平行试验。因此,对于我们的示例,它将生成以下规范:
spec:
algorithmName: bayesianoptimization
requests: 3
3.接下来,基于搜索算法,部署相关服务。在我们的例子中,每个实验都将部署一个贝叶斯优化服务。
4.然后Suggestion
控制器用来自算法服务的结果更新Suggestion
规范。
spec:
algorithmName: bayesianoptimization
requests: 3
status:
suggestionCount: 3
suggestions:
- name: bayesianoptimization-run-1
parameterAssignments:
- name: --lr
value: "0.013884981186857928"
- name: --num-layers
value: "3"
- name: --optimizer
value: adam
- name: bayesianoptimization-run-2
parameterAssignments:
- name: --lr
value: "0.024941501303260026"
- name: --num-layers
value: "4"
- name: --optimiz
value: sgd
- name: bayesianoptimization-run-3
...
5.我们现在准备产生多个Trials
。如果您要将模型训练代码重构为一个函数,那么Trial
将执行这个函数,并将超参数建议作为参数传递。这句话几乎是真的。确切发生的情况是,我们的Experiment
定义中的trialTemplate
被转换成一个runSpec
,其中建议替换了模板变量:
runSpec: |-
apiVersion: batch/v1
kind: Job
metadata:
name: bayesian-run-1
namespace: kubeflow
spec:
template:
spec:
containers:
- name: bayesian-run-1
image: katib-mnist-example
command:
- "python"
- "/classification/train_mnist.py"
- "--batch-size=64"
- "--lr=0.013884981186857928"
- "--num-layers=3"
- "--optimizer=adam"
6.最后,Trial
控制器读取Trial
规格并产生相应的TrialJobs
。超参数作为命令行参数传递给TrialJobs
。
7.Trial
控制器监控TrialJobs
并更新Trial
状态中的相关字段。当底层作业完成其运行时,Trial
也被标记为完成。度量被报告给度量存储,并且最佳客观度量被记录在Trial
状态中。
8.最后但同样重要的是,Experiment
控制器读取所有试验的状态,并尝试验证我们是否达到了目标。如果Experiment
已经达到其目标,那么它被标记为完成。如果没有,它将继续运行,直到达到Experiment
规格中指定的最大试验次数。
如果你认为工作量很大,让 Kale 为你处理所有这些步骤。请看下面的故事:
结论
在这个故事中,我们描述了什么是超参数,以及为什么优化模型的超参数配置很重要。我们看到这是一个很难手工完成的任务。因此,我们研究了 Katib 如何帮助我们实现这一过程的自动化。
Katib 是迄今为止唯一一个在云世界中如此自然出现的超参数优化系统。投入其中,让它为您处理惠普优化的日常工作。
学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!
关于作者
我的名字是 Dimitris Poulopoulos ,我是一名为 Arrikto 工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。
如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请在 Twitter 上关注我的 Medium 、 LinkedIn 或 @james2pl 。此外,请访问我的网站上的资源页面,这里有很多好书和顶级课程,开始构建您自己的数据科学课程吧!
所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。
更好的 Pythoning 化 1:三元运算符
如何通过几个简单的步骤来缩短代码行并使其更具可读性
图片取自 hiteshchoudhary
如果您是数据科学的初学者,很可能您已经遇到过三元运算符(很酷的单行 If 语句)。你是否想知道它们是什么,为什么它们无处不在,什么时候应该使用它们?
在这篇文章中,我将用例子简要地解释三元运算符,使它们易于理解。这是关于使用单行语句来缩短代码(例如,列表理解、Lambda 函数等)的四部分系列的第一部分。).本系列的最后一篇文章将教你如何结合这些不同的方法来大大缩短你的代码。我希望读者喜欢阅读这篇文章,学习一些新的东西,同时提高代码的可读性。
三元运算符——或者我称之为“花哨的 if 语句”
在 Python 中,IF 语句允许你在某些情况下运行代码的某些部分。一个简单的例子:
自然,这可以扩展到包括更复杂的命令。三元运算符可以实现 if 语句在一行中完成的大部分功能,例如:
这可以从字面上理解为:print('I have a name')
如果my_name
为真否则print('I don\t have a name')
。
truthy 指的是 Python 读为 boolean
True
的东西。这几乎可以是任何东西,除了一些显著的例外(这些被称为 falsy),比如一个空列表[]
,一个零0
,一个空字符串''
等等。
当 if 语句的唯一功能是设置变量时,这非常有用。例如:
注意,这是一个非常简单的例子,通过设置
is_retired = age > retirement_age
可以使它变得更加简单。
关键是三元运算符本身实际上不是语句,它们实际上是一个值。这意味着语句True if age > retirement_age else False
就像一个运行后会返回值的函数。
另一方面,if 语句本身并不返回任何值。返回或不返回值的是 if 语句中的实际内容。这非常重要,因为像raise
这样的函数不能用在三元运算符中,因为它们实际上不返回任何东西。
那么,如果是这样的话,第一个带print
的三元运算符是如何工作的呢?事实上,这并不违反规则:print
在运行时返回None
。
如果你怀疑这一点,尝试设置
a = print('Hello World')
,然后print(a)
这意味着当我们执行print('I have a name') if my_name else print('I don\t have a name')
时,我们实际上返回了None
,但是我们没有指定一个变量来存储这个值!
最后一个复杂的问题是:三元运算符也可以接受函数的值。这解释如下:
值得注意的是,三元运算符中的函数difference
和print
没有任何括号。整个事情外面的括号意味着那些实际上是以(retirement_age, age)
为变量的函数。虽然这很酷,但通常不经常使用,而且代码过于复杂,所以最好避免。
关键要点:
- 三元运算符是一个单行 if 语句,看起来像运算符,根据条件,必须返回值
- 这意味着它们对于设置变量非常有用,但是对于运行代码却没有用
- 三元运算符可以链接,例如:
my_surname = 'Unchained' if my_name.lower() == 'django' else 'Fett' if my_name.lower() == 'jango' else 'Surnameless'
- 三元运算符可以用另一种形式编写,如下所示
- 值得注意的是,三元运算符只有在设置变量时才真正提高可读性,更复杂的用例是 if 语句的更好储备
结论
三元运算符有:
- 对于使代码可读来说相当强大(当明智地用于
return
变量时) - 当用于简单表达式时,使你的代码更短
总的来说,我发现它们比 if 语句更好,并经常使用它们,尤其是因为它们对效率没有显著影响(见附录)。
值得注意的是,当在其他函数和表达式中使用这些操作符时,它们会变得更加强大,比如 List Comprehensions(同样,这是很酷的单行循环),这是下一篇文章的主题。在这篇文章中,我将举例说明它们在实际数据科学问题中的用处。对列表理解的一个简短的窥探:
附录
这是我运行的一个小实验,看看三元运算符是否对效率有任何影响(根据堆栈溢出,它们不应该)
我比较了两个使用三元运算符或 if 语句设置变量的 for 循环。然后,我重复实验 100 次,计算每次运行的时间差。代码和结果如下所示:
从上面我们可以看到,三元算子稍微慢了一点,大概~2.5%是相当小的。
更好的 Pythoning 化 2:列表理解(包括带有 spaCy 的 NLP 示例)
如何通过几个简单的步骤缩短代码行并使其更具可读性
图片取自 hiteshchoudhary
如果您是数据科学的初学者,那么您可能会遇到 List Comprehensions(很酷的循环单行代码)。你想知道这些是什么吗?为什么它们如此普遍,什么时候应该使用它们?
在这篇文章中,我将用例子简要地解释列表理解,使它们易于理解。我将特别强调它们与 for 循环的区别,以及它们是否更有效。
这是关于使用单行语句缩短代码的四篇系列文章的第二篇。本系列的上一篇文章研究了三元运算符(很酷的单行 if 语句)。本文将建立在前一篇文章的基础上,向您展示列表理解和三元运算符如何一起使您的代码更短、更易读。
我希望你喜欢阅读这篇文章,学习一些新的东西,提高你的编码技能。
列出理解——“花式循环”之类的?
在 Python 中,for 循环允许你遍历一个 iterable 来执行重复的任务。
典型的例子是打印数字 1 到 10:
这里,函数range
是一个 iterable 对象,它创建从 0 到num — 1
的数字(因此,本例中总共有 10 个数字)。我们可以使用列表理解来重新创建这些:
上面的语句是,range(num)
中的每个i
对应print(i+1)
。我们基本上用少一行代码重复了相同的任务,这似乎并没有节省多少空间。那么这些有用吗?
当然了。
如果我们目光敏锐,我们会注意到我们实际上已经创造了一个list
。我们同样可以将其设置为一个变量,例如:
numbers = [i + 1 for i in range(num)]
这很容易理解:在列表中为range(num)
中的每个i
创建一个值为i+1
的元素。如果我们打印numbers
,我们会得到:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
您可能想知道打印示例创建了什么?因为我们运行了print
10 次,所以我们创建了一个None
值的列表(因为print
返回None
):
[None, None, None, None, None, None, None, None, None, None]
这使得我们的列表理解对于设置变量非常强大,因为我们有效地创建了变量,并在 iterable 运行时将它们存储在一个列表中。相比之下,for 循环不会在它自己的上创建任何东西,而是由我们传递给 for 循环的东西来做这件事。
将其与使用 for 循环创建列表所需的行数进行比较:
除了列表理解更短这一事实之外,值得注意的是它们更具可读性。
简单地说,值得注意的是,列表理解也可以用于创建集合和字典。例如:
列表理解和三元运算符
当你把列表理解和三元操作符一起使用时,你可以打开一个新的可读性层次。
示例 1: 假设您是一名教师,有一本学生姓名及其考试成绩的字典,您想从中提取成绩不太好的学生的姓名,以便为他们提供更多支持。
您可以使用 for 循环来实现这一点,但是使用列表理解要容易得多(并且可读性更好…):
列表理解为:在score
小于或等于failing_threshold
的情况下,为student_scores.items()
中的每个student
和score
保存student
。
值得注意的是,这个上下文中的列表理解只对减少数据有用。例如,不可能将不及格的学生和及格的学生都存储在两个不同的列表中。为此,您可以使用 For 循环。
三元运算符有用的另一个例子是,如果您希望根据某个条件来区别对待列表的组件。
示例 2: 假设您有一个包含学生及其分数的相同数据集,但是您想要创建一个目标变量“fail ”,如果学生不及格,该变量将给出 1,如果学生及格,该变量将给出 0
你可以这样做:
注意,这实际上是一个简单的例子,因为 if 语句和三元运算符都可以用int(score <= fail_threshold)
代替。
然而,我们注意到当我们将列表理解与三元运算符一起使用时,它们会变得相当复杂(并且很长)。当你试图让你的代码更易读的时候,这是需要记住的。
二维列表理解?
列表理解可以被链接,这允许它们超越一维。让我先解释一个例子,你可能需要这个。
我最近遇到了一个问题,我需要展平一个列表列表,例如:
list_of_lists = [[1,2], [3,4], [5,6]]
我想把它转换成list_of_lists = [1,2,3,4,5,6]
我的第一反应是使用解包操作符*
,但是这在列表理解中不受支持。我的逻辑是:
相反,我发现我需要本质上链接两个列表理解来使它变平:
令人困惑的是,逻辑并不符合你的预期:我的直觉是num for num in list_ for list_ in list_of_lists
,但是 Python 要求列表顺序颠倒。
也可以在这里添加三元运算符,分别作用于列表理解,但是正如您可以想象的那样,这使得代码的可读性非常差,因此我个人避免这样做。我只是为了完整起见才添加的。
spaCy 的应用实例
我将给你一个真实的数据科学的例子,说明列表理解是多么有用,特别是在 NLP 中。
我使用 spacy 来创建我拥有的Doc
文本对象。这意味着每个token
实际上是一个对象,包含解释那个token
是什么的参数(例如,它是一个名词,一个动词,一个数字等等……)。
spacy 做了所有这些注释,这很好,因为清理过程在我这边变得非常容易(也非常可读…):
结论
列表理解本质上是一种从可重复项创建列表的方法。它们提供了一种简单的方法,用一行代码概括大量的代码,使得代码非常易读。
关键要点:
- 列表理解是一个单行 for 循环,用于从 iterables 实例化新列表。与 for 循环不同,它们返回值
- 当与三元运算符一起使用时,它们对于从受约束的现有列表创建新列表非常有用
- 他们更有效率(参见附录)
- 它们可以被链接以沿着更高的维度工作,但是这失去了可读性
- 它们可以用于字典、集合和列表
- 像往常一样,更复杂的情况最好留给循环和 if 语句
总的来说,我发现这些理解非常优雅,并尝试将它们用于上述用例。正如你所看到的,列表理解在与三元运算符一起使用时确实很出色,然而,它们也可以与 Lambda 函数(很酷的单行函数)结合使用,这可以使你的代码更加紧凑。这将是本系列下一篇文章的主题,这是一个短暂的高峰:
附录:
和我之前的文章一样,我想试验一下列表理解是否比使用 for 循环更快。三元运算符的实验表明,它们的效率比循环略低。
为此,我用学生的名字进行了实验,并对包含 1000 个学生名字的字典进行了评分。我重复了 10000 次。值得注意的是,在这种情况下,必须在 for 循环中使用 if 语句,在 list comprehension 中使用三元运算符。
我们可以看到列表理解实际上要快 30%,这给了我们更多的理由去使用它们。
更好地量化视频中对象检测的性能
视频对象检测有几个独特的挑战,使其区别于静态图像中的对象检测。
对象检测现在是计算机视觉中最常见的应用之一,特别是随着普通分类问题已经变得更容易用现代深度学习架构来解决。由于大规模数据集(例如 COCO [1])的广泛可用性,对象检测研究对于计算机视觉社区来说变得更加容易,从而导致技术以惊人的速度发展。随着对目标检测的研究越来越深入,在视频中进行目标检测的并行研究已经出现。这样的问题是几个通常研究的计算机视觉问题(即,跟踪、对象检测和分类)的混合,其中对象必须通过视频内的相关帧被正确地定位、分类和关联(即,相同的对象在不同的视频帧中通过唯一的标识符被如此标识)。
视频对象检测有几个独特的挑战,使其区别于静态图像中的对象检测。在这篇文章中,我不会概述任何当前的视频对象检测方法(见[2]更全面的视频对象检测概述)。相反,我将讨论该领域目前阻碍持续技术进步的主要问题之一:**缺乏一种可以评估视频中对象检测器性能的综合指标。**没有这样一个评估视频对象检测器的标准化指标,不同方法之间的比较变得困难,导致研究人员质疑他们的贡献是否真正有价值。
作为这个问题的解决方案,我认为高阶跟踪精度(HOTA)是对象跟踪社区中的一个标准化指标,是视频对象检测的正确指标,只要它具有分类意识。我将通过提供开发更好的视频对象检测指标的动机来开始这篇文章。然后,我将介绍一些与对象检测相关的概念和定义,然后讨论该领域中存在的当前指标。我将以对 HOTA 指标的讨论来结束这篇文章,强调它作为视频对象检测评估指标的适用性。
为什么我们需要更好的指标?
简而言之,视频对象检测的度量标准的当前状态非常差。特别是,该领域研究人员的常用方法是在视频的每一帧上分别评估他们的模型,然后平均所有帧的性能。结果,完全忽略了视频对象检测性能的时间方面,并且不可能根据这样的度量来确定整个视频中预测的时间一致性。换句话说,这种评估协议将视频对象检测简化为在静态图像内执行对象检测(即,每个帧被视为独立的检测问题),这(如前所述)是完全不同的问题。尽管这种方法可能是合理的起点,但是对于将时间数据结合到它们的预测中以鼓励随时间的一致预测的基于视频的对象检测器(例如,基于光流的检测方法)来说,这显然是不合适的。
与静态图像中的对象检测相比,视频对象检测的时间方面是使问题变得困难和有趣的关键部分。因此,最广泛使用的视频对象检测度量不能捕捉这种时间行为是完全不可原谅的。如果没有更好地量化视频对象检测性能的所有方面的指标,社区将无法取得一致、向前的进展,因为无法正确比较所提出方法的性能。为了解决这个问题,必须标准化和采用统一的度量标准(即一个度量标准,而不是几个度量标准的组合)。理想情况下,视频对象检测的适当度量应该提供单个可解释的分数(可能分解成多个更具体的子分数),该分数捕获视频对象检测性能的所有相关方面,包括检测、定位、关联和分类。
相关概念
在本节中,我将简要讨论几个有用的概念,这些概念对于理解目标检测评估非常重要。特别地,我将描述匈牙利算法(即,用于将预测对象与真实对象相关联的对象检测中最常用的算法)和平均精度度量(即,用于静态图像中对象检测的最广泛使用的评估度量)。
匈牙利算法
在任何形式的对象检测中,我们在评估期间被给予一组基础事实和预测对象。但是,现在还不清楚这些预测中的哪一个符合事实。因此,在评估预测的质量之前,必须做一些工作来确定基础事实和预测对象之间的最佳映射。更具体地说,必须产生预测对象和基础事实对象之间的一对一映射。然而,预测的或基本事实对象也可能没有匹配(即,在这种情况下,映射在技术上不是一对一的,因为存在不成对的元素)。
匈牙利算法是一种组合优化算法,可用于在多项式时间内解决集合匹配问题。在对象检测领域中,它通常用于生成预测对象和真实对象之间的映射,通常基于对象之间的成对交集/并集 (IoU)分数。此外,对于在匈牙利算法中要相互匹配的对象,通常会施加一些额外的要求(例如,两个边界框对象检测的 IoU 必须大于 0.5 才能被认为是可行的匹配)。由于匈牙利算法的性能和效率,它对于这样的应用是理想的。
平均精度
如前所述,平均精度(mAP)是评估静态图像中对象检测器的标准度量。为了计算 mAP,必须首先计算图像中的真阳性/阴性和假阳性/阴性的数量。在运行匈牙利算法之后,计算这样的度量是非常简单的(即,我们仅仅检查检测是否丢失了一对、对是否是错误的,等等)。).由此,可以在图像内的不同“置信度”水平上计算精度和召回率,以确定平均精度(AP)。对于给定问题领域中的每个不同的语义类,这样的过程被单独重复。然后,计算所有语义类的平均精度的平均值,形成平均平均精度(mAP)度量。
想要更深入的描述 mAP,我推荐阅读这篇文章。然而,理解(1) mAP 是用于评估静态图像中的对象检测性能的首选指标,以及(2) mAP 是通过查看单个图像中的预测指标来计算的,这对于理解本文的剩余部分应该是足够的。
我们已经有了哪些衡量标准?
在我介绍(在我看来)最适合评估视频中的对象检测器的指标之前,有必要考虑一些可以使用的其他指标。我将根据指标是用于对象检测还是对象跟踪来将此讨论分为两类,并对每种指标进行简要的高级描述,旨在展示其在评估视频对象检测方面的不足之处。首先,回想一下测量视频中对象检测的性能有四个主要部分:检测、定位、关联和分类。如本节所述,目标跟踪不考虑评估的分类部分*,但目标跟踪的分类感知指标有可能捕捉视频目标检测性能的所有相关部分*。
目标检测
如前所述,评估视频中对象检测的最常见指标(在撰写本文时)是图。具体地,跨视频的每个帧单独计算 mAP,并且跨所有视频帧取 mAP 分数的平均值,以形成最终的性能度量。这种方法完全不能捕捉视频对象检测的时间方面(即,没有关联的概念),因此不足以作为评估协议。然而,mAP 目前是视频中对象检测的首选度量,并且关于改变/修改该度量的讨论似乎很少。
一个包含时间信息的有趣的地图变体是基于速度的地图【3】(也就是说,我为这篇博文的上下文编造了这个名字;相关联的引用不提供特定的名称)。为了计算该度量,首先基于对象在帧之间移动的速度(即,使用相邻帧的运动 IOU 来计算),将对象分成三个不同的组(即,慢、中和快)。然后,为这三组中的每一组中的对象分别计算 mAP,并且分别呈现三个 mAP 分数。尽管基于速度的图基于视频中的对象速度提供了对象检测性能的更细粒度的视图,但是它提供了三个度量而不是一个,并且仍然不能捕捉视频对象检测的时间方面;同样,映射不包含关联的概念。因此,基于速度映射不是视频对象检测的合适度量。
为视频对象检测提出的最后一个度量是平均延迟(AD)【4】。AD 捕捉的是物体进入视频和被探测器“拾取”之间的延迟,这种延迟被称为“算法延迟”。这种延迟是以帧为单位测量的,因此 AD 为 2 意味着,平均而言,对象将在视频中存在两个完整的帧,直到它被模型实际检测到。虽然 AD 在视频对象检测中捕获时间信息,它被提议作为一种与 mAP 结合使用的度量。因此,它不是一个可以用来全面评估视频中对象检测器性能的独立指标。
目标跟踪
尽管还没有针对视频对象检测提出全面的度量,但是在对象跟踪社区中存在许多有用的度量,从中可以获得灵感。对象跟踪要求在整个视频中以一致的方式识别、定位和关联对象(每个视频帧中的一个或多个对象)。虽然对象跟踪不包含分类的概念,但是在对象跟踪和视频对象检测之间存在足够的重叠,以保证对对象跟踪中的当前评估度量进行更深入的检查。
多目标跟踪精度(MOTA)【5】是目标跟踪中最广泛使用的度量之一。MOTA 将基础事实与每个检测的预测对象相匹配,这意味着在评估过程中,每个预测和基础事实检测都被视为一个独立的实体。在高层次上,MOTA(基于匈牙利算法提供的匹配)确定所有视频帧中的身份切换(即,相同的对象在相邻的视频帧中被分配不同的标识符)、假阳性和假阴性检测的数量。然后,通过用视频中地面实况对象的总数对这些分量的总和进行归一化来计算 MOTA,如下式所示。
MOTA 跟踪度量
MOTA 通过身份切换(即,表示为上面的IDSW
)来捕获关联性能,而检测性能通过假阳性和假阴性来捕获。但是,MOTA 不考虑本地化。相反,定位必须通过一个单独的指标来衡量,多目标跟踪精度(MOTP) [5],它对视频中所有检测的定位分数进行平均。尽管 MOTA 是用于对象跟踪的长期标准化度量,但是它有几个缺点,这限制了它在视频对象检测中的适用性。也就是说,它过分强调检测性能(即,身份转换对上述分数的影响是最小的),不考虑相邻帧之外的关联,不考虑定位,提供多个分数而不是统一的度量,高度依赖于帧速率,并且提供可能难以解释的无界分数(即,MOTA 可以具有[-∞,1]的值)。因此, MOTA 不足以作为视频对象检测的度量。
对象跟踪社区中其他广泛使用的指标是id f1【6】和 track-mAP (也称为 3D-IoU),它们在轨迹级别上将地面实况与预测进行匹配(即,轨迹被定义为贯穿视频帧的预测或地面实况对象的序列,它们共享相同的唯一标识符)。与 MOTA 相比,IDF1 和 track-mAP 在对象跟踪社区中没有得到广泛使用,因此我不会对这些指标进行深入讨论(有关指标之间更全面的讨论和比较,请参见[7])。然而, IDF1 和 track-mAP 都有许多限制,这阻碍了它们被采用为视频对象检测的标准度量。也就是说,IDF1 过分强调关联性能,不考虑定位,并且忽略彼此不匹配的轨迹之外的所有关联/检测。类似地,轨迹地图要求每个轨迹预测包含置信度得分,要求轨迹距离度量由用户定义,并且可以容易地“游戏化”(即,可以提供简单的反例,其表现很差但是实现了高轨迹地图得分)。
走向全面的衡量标准
尽管上一节概述了指标的局限性,但截至 2020 年中期,对象跟踪社区中有一个新的标准指标:更高阶跟踪精度(HOTA)【7】。在本节中,我将介绍 HOTA 指标,并解释为什么我认为它是评估视频对象检测器的合适指标。虽然 HOTA 不考虑分类性能,但它的分类感知对应物 CA-HOTA 在单个评估指标内有效地捕获了视频对象检测性能的所有相关方面。
为什么是 HOTA?
HOTA 的目标是(1)提供一个单一的分数,该分数捕捉跟踪性能的所有相关方面,(2)使长期关联性能能够被测量(即,两个相邻帧之外的关联),以及(3)分解成捕捉跟踪性能的更详细方面的不同子度量。HOTA 旨在缓解以前跟踪指标的问题,它提供了一个在[0,1]范围内的单一分数,该分数以平衡的方式捕获跟踪性能的所有相关方面(即检测、关联和定位)。此外,这个单一的、可解释的分数可以分解为子指标,这些子指标在更细粒度的级别上表征跟踪性能的不同方面。下图总结了与其他广泛使用的跟踪指标相比,HOTA 的优势。
HOTA 与其他跟踪指标的比较[7]
尽管 HOTA 不考虑分类性能,但是已经提出了将分类并入 HOTA 得分的变体(例如 CA-HOTA)。CA-HOTA 在一个可解释的指标内捕获视频对象检测性能的所有方面(即关联、定位、检测和分类)。因此,CA-HOTA 可以被认为是用于视频对象检测的(相对)全面的度量。
HOTA 是什么?
`,HOTA 度量的说明[7]
与 MOTA 类似,HOTA 在探测层面(即,与 IDF1 或 track-mAP 中的轨迹层面相反)匹配预测和地面实况对象。在 HOTA 中,从基础事实和预测对象匹配(同样由匈牙利算法产生)中计算出两类度量:检测组件和关联组件。检测组件只是真阳性、假阴性和假阳性,这在前面已经讨论过了。有些不同的关联成分包括真阳性关联(TPA)、假阴性关联(FNA)和假阳性关联(FPA)。
考虑在特定帧中具有有效匹配的对象(即,真正的肯定检测),我们将其表示为c
。在这种真正的肯定检测中,预测和基础事实对象都必须被分配一个唯一的标识符。为了计算 TPA 的数量,只需找到与c
共享相同基本事实和预测标识符的其他帧中的真阳性的数量,并对视频内的每个可能的c
重复该过程(即,每个真阳性检测)。FNA 和 FPA 以类似的方式定义,但是必须在其他帧中找到分别具有相同基本事实标识符和不同预测标识符或者相同预测标识符和不同基本事实标识符的检测。实质上,TPA、FPA 和 FNA 允许跨视频内的所有帧测量关联性能,而不仅仅是相邻帧之间的关联性能。因此,命名为“高阶”跟踪精度。
给定某个定位阈值(即,定位阈值修改由匈牙利算法产生的匹配),我们可以计算 HOTA 的所有检测和关联组件。然后,在给定定位阈值(我们表示为α)下的合计 HOTA 分数可以计算如下。
单一定位阈值下的 HOTA 度量
一旦在特定本地化阈值下计算出 HOTA,就可以通过在几个不同的本地化阈值上对上述度量进行平均来导出合计 HOTA 分数。通常,定位阈值的样本取值范围为[0,1],如下式所示。
HOTA 度量
如上面的等式所示,HOTA 捕获检测(通过检测组件)、关联(通过关联组件)和定位(通过定位阈值)性能。此外,HOTA 可以分解成许多子指标。下图中概述的每个子指标都可以用来分析跟踪器性能的更具体方面(例如,定位、检测或孤立的关联性能)。
HOTA 中的子指标[由作者创建]
关于如何计算 HOTA 度量的更全面的讨论,也可以阅读相关论文[7]或博客文章[8]。
分类呢?
我之前提到过,可以修改 HOTA 来获取分类性能,但是从来没有明确说明这是如何实现的。尽管提出了分类感知 HOTA 的多种变体[7],但一种可能的方法是在某个定位阈值处修改 HOTA 得分,如下所示。
分类感知 HOTA (CA-HOTA)
从上面可以看出,分类性能是通过用给定真阳性检测的正确类别的相关置信度来缩放对 HOTA 度量的所有贡献而合并的。因此,如果分类性能很差,HOTA 度量将会恶化。给定以上定义,然后可以将合计 CA-HOTA 度量计算为不同本地化阈值上的得分的平均值(即,就像对于普通 HOTA 一样),产生 CA-HOTA 度量。
结论
目前,视频对象检测社区缺乏正确捕捉模型性能的统一评估度量。通常,使用 mAP 度量并跨视频帧进行平均来表征性能,但是这种技术完全忽略了模型性能的时间方面。根据对象跟踪领域的最新进展,我认为高阶跟踪精度(HOTA)度量是视频中对象检测的合适评估标准。HOTA 的分类感知变体 CA-HOTA 捕获视频对象检测性能的所有相关方面,包括检测、关联、定位和分类。因此,它是一个全面的指标(尤其是与 mAP 等静态指标相比),可以而且应该用于对视频对象检测中的不同方法进行基准测试。
我希望这篇文章能在社区内引发讨论,并为视频中的对象检测带来更标准化和更全面的基准测试。这项工作是我在 Alegion 做研究科学家工作的一部分。如果你对这个话题感兴趣,我鼓励你去看看这家公司,或者申请一个空缺的职位。我们一直在寻找更多对机器学习相关话题感兴趣的人!要了解我的博客文章,请随时访问我的网站或在 twitter 上关注我。
参考文献
[1]https://cocodataset.org/#home
[2]https://www.mdpi.com/2076-3417/10/21/7834
https://arxiv.org/abs/1703.10025
【https://arxiv.org/abs/1603.00831
[6]https://arxiv.org/abs/1609.01775
[7]https://arxiv.org/abs/2009.07736
[8]https://jonathonluiten . medium . com/how-to-evaluate-tracking-with-the-hota-metrics-754036d 183 e 1
通过利用标签的层次结构提高深度学习分类模型的可靠性
如何使用来自标签的附加信息来训练合理性模型
在实践中使用预测性深度学习模型往往会带来一个问题,即我们可以在多大程度上信任该模型的预测。虽然有几个框架来验证它确实学习了正确的特征(例如,石灰, LRP ),但对于看不见的数据,仍然不能保证预测的类别是正确的。增加这种模型的可信度的一种选择是引入似真性检查。建立这种检查的一种方法是使用来自标签的分层结构的信息,这在公共数据集(CIFAR-10,Image-Net)中经常见到。目标是建立第二个模型,在层次结构中的父标签上训练,这篇文章将展示为什么这增加了模型的可靠性以及代价是什么。
扁平标签结构
大多数对新模型架构和更好的模型的研究都是基于平面标签,从数据集中丢弃了层次结构。对于 ImageNet 通常使用 1000 个标签, Birdsnap 使用 500 种鸟类作为标签。有一些模型利用了这些类别的层次结构,如 HD-CNNs 和 Tree-CNNs ,但这是一个相当小的领域。
在实践中,我们经常有这样的应用,其中我们的训练数据是有限的,并且随着时间的推移而增长。我们每个类别用于训练的图像数量是变化的,一些标签的准确性比其他标签差。新的标签不时出现,我们至少应该知道,我们可以在多大程度上依赖我们的预测。换句话说,我们能在多大程度上信任我们的模型?
概率分数在看不见的数据上是不可靠的
好的一面是,我们有概率得分,我们可以用它来估计预测的确定性。然而,当一个模型面对新数据时,它有时会给我们很高的概率分数,即使预测完全错误。特别是在具有许多标签的图像 CNN 中,当处理新数据时,我们可以观察到不稳定的预测。当我们谈论细粒度图像分类时,这个问题变得更加难以解决,在这种情况下,图像中的小细节会产生影响。
图 1—Twitter 上一些非常流行的错误分类
这些例子通常很难解决,但它们很好地说明了问题。一个以动物品种为标签的 CNN 无法检测食物或拖把。CNN 通常会采取一切可能的捷径来解决这个问题,很明显,从物体的整体颜色、形状和姿态来看,这些图像看起来非常相似。由于在动物身上训练的神经网络不理解狗的概念,它会感到困惑,并以很高的可信度对这些例子进行预测。
但是,如果我们另外有一个不同的 CNN 训练检测鼻子,眼睛和其他特征,这是动物的代表呢?
从标签中挖掘领域知识
这就是合理性检查的想法。如果第二个模型被训练来检测与我们的标签相关的不同特征,我们可以检查可信度。我们想从我们的数据结构中发掘信息。
另一个例子是在第二个模型中使用来自 ImageNet 的活动信息,并检查该活动与检测到的对象相结合是否有意义(当然,该信息必须在层次结构中编码)。
有了这些信息,就有可能利用标签结构中隐含领域知识。一个假设是,似真性模型受益于每类的大量训练数据,并且概括得更多,因此防止了过度拟合。
训练模型以检查可信度
原始模型在我们的目标标签上训练,因为它们在最高粒度上(标签层次结构中的叶子)。似真性模型在更高级别的标签(图中的父节点或相关节点)上被训练。为了使用动物分类器示例,原始模型根据动物的品种进行训练,并且具有 1000 个不同的标签,而似真性模型被训练来对数据中的 50 种不同的动物进行分类。
一个旁注:
你可能会认为用多个模型直接对层级进行建模会容易得多,例如一个模型用于动物,在检测到动物后用另一个模型来检测每只动物的品种。是的,这是可能的,但是除了玩具数据,我们通常在一个树中有更多的类和节点,最终有数百个模型集合在一起。这通常是不实际的。
具有似真性模型的另一个好处是,我们也可以使用带有不完整标签信息的图像。我们知道这种动物,但不知道确切的品种。当对现有的图像分类系统使用用户反馈时,这种情况经常发生。用户可能无法确定动物的品种,但清楚地知道它是一只狗。对于一个检测品种的模型来说,这些例子是不可用的。但是对于第二个模型,我们可以包括它们。
测试可信度
当我们训练这两个模型时,我们可以预测两个概率分数,一个用于细粒度目标标签,一个用于粗粒度似真性标签。由于类别数量的减少和每个类别图像数量的增加,我们的似真性模型通常比原始模型具有更好的准确性。
最后,我们得到图像的两个预测,并需要对结果应用一些逻辑:
- 当两个分数都很高,并且原始模型(例如品种)预测了一个标签,该标签与似真性预测(例如动物)相匹配时,我们可以假设该预测是正确的。举例:0.98 狗/ 0.89 秋田
- 当两个分数都很低时,我们知道结果不可靠或者图像上有简单的其他东西。例如:0.05 的狗/ 0.07 的小猎犬
- 当原始模型预测值较低,而第二个模型预测值较高时,我们可能会在原始模型的训练数据中发现一个缺失的标签(例如,缺失的品种)。举例:0.98 猫/ 0.28 波斯
- 当原始模型预测值较高而可信度模型预测值较低时,可能会出现上图所示的情况。不是猫,但形象很像。举例:0.21 猫/ 0.98 波斯
- 最后,最有趣的情况:假设我们的似真模型有很高的概率,原始模型有中等的概率,但标签不是似真的:例如:0.98 狗/ 0.47 波斯。显然,波斯人不是狗。但是,如果我们在原始模型中查看第二好的预测,发现 Briard 的 0.46,实际上是一只狗,会怎么样呢?在这里,假设布里亚德是正确的似乎是合理的。因此,一般来说,我们可以应用一个逻辑(或另一个模型),搜索与给定动物匹配的最小分数的品种模型的前 n 个预测。
结论
使用似真性模型,其中数据中的层级信息是可用的,可以使预测更可靠。如果系统给出相互矛盾的分数,我们可以认为预测是错误的。此外,通过不仅查看顶部的预测,还查看前 N 个预测,我们可以更深入地了解模型的可能错误,找到丢失的标签,甚至纠正预测。另一方面,我们需要一个额外的模型,并在系统中引入逻辑检查。
数据科学中更好的软件写作技巧:保持干燥
封面图片由https://pixabay.com/users/chillervirus-2033716/pix abay组成。
首先,我想回到上周的帖子,问你一个问题。我收到了一位读过我博客的朋友的评论,他告诉我一些大致的内容:“显然,让你的学员读一本书是你的指导方式”。这让我想到……考虑到与不直接与我合作的学员进行准时的指导会议(连续数周,每周半小时),考虑到提高软件开发技能的总体目标,以及更具体的 Python 软件编写技能,有人能提出更好的方法吗?我真诚地接受建议。
现在,让我们继续使用当前的方法,并将本周的指导和帖子建立在“实用程序员:从熟练工到大师”的第二章:实用方法的基础上。在那一章中提出的观点之一就是所谓的干原理。不要重复自己。
不重复自己当然是软件开发的一个重要方面。在多段代码之间进行复制粘贴可能是最好的方法,而且速度很快。然而,当在那些多个副本中的一个中发现一个 bug 时,你会做额外的努力到处纠正它(包括其他人的工作)吗?你能找到所有这些拷贝吗?有时,复制粘贴的代码可能会有一些变化。更改变量名,到处添加条件,…
几年前,我领导了一个项目,开发了一个检测软件克隆的软件。即使我们能够识别出与原始版本不同的软件克隆,让软件开发人员基于这种洞察力重构代码也是非常困难的,甚至是不可能的。当一个克隆体被创造出来,就很难杀死它!所以最好的方法是不要创建它们,从头开始重构,根据需要创建函数或类,而不是复制粘贴。
希望我说服你在数据科学的软件开发中保持干爽。但这也适用于数据科学的其他方面。您是否曾经在这样一个地方工作过,那里的数据定义依赖于许多列,可能来自不同的表,这些表没有标准化,并且对于许多仪表板或查询是重复的。什么是你网站的访问者?网站的任何页面有点击率吗?你有没有安排一些会议,并且每次会议只数一次?你是否有一个登录名并且只计算用户数?假设会话跟踪或用户登录,你如何计算访问者的数量?是一段时间内的滚动平均值吗?那段时间是什么?它很容易成为确定谁是特定时间的活动用户的重要查询。你确定组织里的每个人都用最新最伟大的定义吗?查询是否从仪表板复制粘贴到仪表板?这个定义是根据一个人或一个团队的目的稍微修改的吗?你看,不要重复你自己也适用于数据定义。有多种方法可以解决这个问题,但没有一种方法是简单的,你允许代码、查询或定义复制粘贴的时间越长,就越难杀死那些克隆体。
在第二周的练习中,我建议找出一个你的团队中制造了大量克隆的区域或特定实例。找个人(最好是你团队里的)讨论一下。有没有什么方法可以提出一段代码、查询或定义,并开始重构相关的工件来消除这种克隆?这可能很难!什么是可接受的渐进方式?我们如何确保未来不会产生新的克隆体?这可能是您的团队将要采取的最初几个步骤,以限制和减少您的工件中的克隆。
至于上周,第二章还有更多内容。尽管如此,对于希望提高 Python 编程技能的初级数据科学家来说,我建议熟能生巧。在这种情况下,这个主题内的练习可能会被证明是有用的。
一旦你完成这个练习,问问你自己我上周练习中提出的所有问题。更具体地说,你应该确保自己不会重复。密码问题是对称操作的一个很好的例子,对称操作有很好的代码重用潜力。如果您没有定义在编码和解码之间多次使用的函数,我建议您重新考虑一下您的实现。另外,一定要思考上周的其他问题:你会早休息吗?你尊重合同吗?你记录你的程序吗?你有单元测试吗?
同样,如果你能接触到一个你觉得相处融洽并且你认为他写了很棒的代码的人,问问他对你的练习解决方案的意见。你可能会学到一两件事!或者,如果你解决了那个问题,你可以看看其他人的最佳解决方案。阅读他人的代码也是提高编程技能的好方法。
我知道我说的是每周一个话题,但是这一章还有一个方面值得一提。我不会增加更多的锻炼,只是一个潜在的终身追求!主题是评估。这本书会告诉你记录你的估计。我说:不要简单地记录这些,记录你做的每一件事以及花了多长时间。在你职业生涯的早期,记录下你做了什么,花了多长时间。随着时间的推移,尝试概括您收集的数据,例如,所有数据概念都定义良好的数据请求平均花费我 x 小时;使用现成的图表类型创建一个带有 y 图表/数据点的仪表板平均花费我 x 小时;…为自己建立一个评估库。
当你开始对你的个人估计有一个概括的心智模型时,用它做一个游戏。即使没有被要求做一个评估,也要做一个,然后检查它有多好。让游戏化成为你的优势,让你更好地预测未来!
如果或者当你毕业去领导团队时,你会发现你的评估也是一个很好的基础。然后,当您了解团队成员时,您可以对他们应用对等因素。甚至可能从那次练习中找出他们的长处和短处。
这是我对“实用程序员:从熟练工到大师”第二周/第二章的快速补充,作为提高数据科学中软件编写技能的媒介。下周见第 3 章:基本工具。
在软件领域 20 多年了。目前在 Shopify 担任数据科学家。在深度学习、机器学习/分析、云计算、物联网、领域特定语言、遗传算法和编程、人工生命/智能以及所有技术领域的研究兴趣!通过点击查看所有帖子
原载于 2021 年 3 月 30 日 http://thelonenutblog.wordpress.com的 。**
数据科学中更好的软件写作技巧:在项目之前
实用程序设计员的每周指导章节阅读
本周的指导和帖子是基于“务实的程序员:从熟练工到大师”的第七章:项目之前。通读这一章,你会发现我们离编码只有一步之遥。然而,良好的项目准备卫生将确保您在数据科学项目中取得成功,并限制编码时的意外。
通读这一章,一些数据科学家会发现挖掘需求不仅是数据科学家的任务,也是软件开发人员的任务,这让他们感到欣慰。在数据科学中,就像在软件工程中一样,需求不会简单地躺在地板上,随时可以被拿走和珍藏,你必须首先把它们挖掘出来。数据科学中的需求会有不同的形式,这取决于您正在从事的项目的类型。在几个组中进行分类就足够了,还是需要更精细的回归?如果能提高精确度或召回率,允许更多的假阳性会更好吗,或者假阳性会被禁止以后处理?如果您正在构建一个仪表板,那么监控项目的合适指标是什么?构建实验时,您应该定义哪些组?
从数据科学的角度来看,需求与从软件开发的角度来看是不同的,但是如果你的项目将数据作为一个产品来构建,那么它们可能会比你预期的要多得多。有一点是不变的,那就是和用户一起工作,像用户一样思考。没有什么比与目标用户一起工作更好地了解他需要你做什么了。
记录这些需求。但是不要过度记录它们!永远记住,有些事情做得比描述的要好!一旦写下来(或画下来),你就有了一个讨论和找出可能被不同利益相关者误解的细节的基础。如果使用正式方法或部分正式方法可以帮助你,好吧,去做吧。然而,不要错误地认为方法本身就是目的。用例的概念既适用于软件开发,也适用于数据科学。弄清楚谁是参与者,他们期望从系统中得到什么,以及你将向他们提供什么,是建立强大结果的关键。需求收集、设计和实现都是交付高质量解决方案的不同方面。不要忽略任何一个阶段。
解决不可能的难题也是数据科学的一个标志。在这里,我很喜欢作者提出的“找到盒子”这种表达方式。这并不总是一个跳出框框或跳出框框思考的问题。相反,你应该弄清楚什么是盒子,什么是真正的绝对约束,同时摆脱想象的先入为主的观念。这不仅适用于现实生活中的数据科学问题,也适用于小思维问题。有时你只需要退后一步,问自己书中提出的几个问题:
- 有更简单的方法吗?
- 你在尝试解决正确的问题吗?
- 为什么这是一个问题?
- 是什么让它难以解决?
- 需要这样做吗?
- 到底需不需要解决?
通过问自己这些问题,诚实地面对自己,你可能会对答案感到惊讶!
这是我对《实用程序员:从熟练工到大师》第七章阅读的补充,作为提高数据科学中软件写作技能的媒介。下周,这本书的最后一章,也是我这个系列的最后一篇文章。然后我们将看一看第 8 章:务实的项目。
在软件领域 20 多年了。目前在 Shopify 担任数据科学家。在深度学习、机器学习/分析、云计算、物联网、领域特定语言、遗传算法和编程、人工生命/智能以及所有技术领域的研究兴趣!通过点击查看所有帖子
原载于 2021 年 5 月 11 日https://thelonenutblog.wordpress.com/2021/05/11/better-software-writing-skills-in-data-science-before-the-project/。
数据科学中更好的软件写作技巧:弯曲还是断裂
实用程序设计员的每周指导章节阅读
封面图片来自 Pixabay 上的未知作者。
本周的指导和帖子是基于“务实的程序员:从熟练工到大师”的第五章:屈服或突破。本章的重点是确保你的程序、ETL 或模型在未来新的现实出现时可以改变。除了会被废弃的一次性原型(但通常会被转化为产品代码)之外,代码也必须进化。无论是 ETL 还是模型,你的代码都必须进化,如果你想提高效率,你最好从一开始就得到一些提示。
让我们首先同意代码将需要改变,很少有用的代码编写一次就永远不会改变,许多代码编写不是空白页面类型,而是编辑现有的代码(即使是遗留代码)。一些原则有助于确保将来更容易更新代码:
- 低耦合(系统的每个部分都只依赖于几个组件吗?或者代码的耦合是依赖关系的蜘蛛网吗?),
- 可逆性(如果我想改变数据库访问,我是否需要到处改变代码,或者数据库访问是抽象的,以便所需的改变可以本地化到一个文件或组件?),
- 元编程(有没有办法通过正确编写的可重用代码、数据驱动代码或参数化配置来最小化代码?),
- 时间耦合(代码对以一定顺序出现的事件有很强的依赖性吗?,有反馈回路吗?),
- 使用视图将表示从数据模型和黑板技术中分离出来,在模块之间进行匿名和异步的信息交换。
我不会深入这些原则的所有细节,因为我认为这本书在解释它们方面做得非常好,但也许我们可以举几个与数据科学相关的例子来补充这本书所提供的内容。
低耦合
通常在数据科学中,我们通过创建 ETL 从现有的资产中创建派生的数据资产。然后我们从这些中推导出更多的。我们混合和匹配数据,甚至可能无意中通过这些数据资产创建反馈循环。您应该尽早考虑映射这些数据资产依赖关系的方法,并了解可以在您的组织中应用哪些规则来确保数据资产的低耦合性。在数据科学中,数据是最有价值的资产。不要把它转换成意大利面数据!是的,它会像意大利面条代码一样糟糕。
可逆性
如果它还没有发生在你身上,你应该感到幸运。但是在某个时候,您的组织选择了数据库提供商 A 或云基础设施提供商 B,将决定转向提供商 c。为什么?成本,可靠性,特性,……理由层出不穷。如果它不是数据库端或云基础架构端,它很可能是深度学习框架或您的组织从第三方购买的其他一些基础架构。如果在建立软件架构之前没有考虑到这种转变,它可能会成为一个糟糕的转变。
元编程
我记得在我的第一份工作中,我们假设地球是平的,进行地理定位。这不成问题,因为覆盖的区域足够小,看不到地球弯曲的假象。一天,一位客户要求我们覆盖一大片区域。没有别的办法,我们必须考虑纬度、经度和地球的曲率。首先,对嵌入在每个组件中的东西进行解耦是非常困难的。有什么比在平坦的地球上计算距离或方位更容易呢…所以每个组件都在做。第一步是抽象这些功能,并创建一个组件来完成这些计算(一个需要填充的高耦合地狱)。
接下来,我们决定,由于一些客户可能想要一个平坦的地球,其他人想要一个球形模型,或者一个椭圆形模型,甚至更复杂的地球模型,我们要使地球模型参数化。不仅距离和方位被解耦,用于地球的模型也被参数化。然而,在开发的后期进行解耦是一项艰巨的任务。
同样的事情也会发生在数据上。也许今天您可以用相对较小的计算单元来处理您的 ETL,但是明天呢?最好早点考虑参数化,这样如果你需要更多的能量,你可以调整参数。输入和输出数据集的名称和路径也是一个容易互换的参数吗?ETL 的过滤条件可能取决于具体情况,但是所有的处理都是一样的。与其拥有几乎相同的 ETL 的多个副本,也许一个可以接收过滤条件作为参数的副本会让您的生活更轻松。可能有很多事情你可以在早期参数化,这将使你的未来生活更容易。花点时间想想吧。
时间耦合
你的 ETL 中有可以并行执行的部分吗?思考并行处理在哪里是可能的,并相应地创建你的系统。也许今天串行运行它是好的,但是也许明天如果您想要满足您的服务级别目标(SLO ),您可能需要以使用更多资源为代价来进行并行处理。将来你会感谢你早点想到它!我有第一手的经验,我设计的 ETL 链开始花费太长时间。只需更改几个参数,我就可以运行可并行化的部分,并提高转换的速度。
视图
模型视图控制器设计模式似乎不太适用于数据科学。但其背后的原理可能是一个很好的灵感来源。使用上面介绍的其他技术,保持您的源代码可配置但具有相似的特征可能是个好主意。这样,也许您可以开发可参数化的模型(可能包括训练参数或训练参数文件),并轻松地交换它们,甚至并行使用它们。ETL 或模型的服务也可以是参数化的和可交换的。这可以扩展到模型的评估,或者 ETL 的健康监控。模型视图控制器良好的解耦原则在数据科学环境中仍然非常受欢迎。只是想法有点不同!
这是我对第五章“实用程序员:从熟练工到大师”阅读的补充,作为提高数据科学中软件写作技能的媒介。下周我们将看一看第 6 章:当你编码的时候。
在软件领域 20 多年了。目前在 Shopify 担任数据科学家。在深度学习、机器学习/分析、云计算、物联网、领域特定语言、遗传算法和编程、人工生命/智能以及所有技术领域的研究兴趣!查看网友的所有帖子
原载于 2021 年 4 月 20 日 http://thelonenutblog.wordpress.comhttps://thelonenutblog.wordpress.com/2021/04/20/better-software-writing-skills-in-data-science-bend-or-break/。
数据科学中更好的软件编写技巧:破窗
通过实用程序员的每周章节阅读和 Python 练习来提高你的数据科学编程技能。
封面照片来自 Pexels 上的cotton bro。
我最近开始指导一名初级数据科学家提高他的编程技能。人们常说数据科学家缺乏编程技能,这可能是因为他们的数据科学项目,也可能是因为他们不同的背景导致他们从事数据科学。然而,有时数据科学家愿意承认自己的弱点,并加以改进。我目前是一名数据科学家,但鉴于我在过去的生活中作为软件开发人员有多年的专业经验(在许多事情上),我觉得这个导师是一个很好的匹配,并认为我们可以看到我们如何通过这个导师学习。
在我的软件开发经历中,我读过的一本很有影响力的书是安德鲁·亨特和戴维·托马斯写的《实用程序员:从熟练工到大师》。我认为这可能是一个很好的讨论和练习的起点。这本书本身没有那么多章节,所以我最初的打算是每周与我的学员讨论一章,并用一些练习来补充阅读。更具体地说,我的学员希望提高他的 Python 编程技能,因此我们将针对该语言进行练习。
你可能会问我:为什么程序员的书对数据科学家有好处,尤其是一本没有深入讨论语言的书?嗯,我认为有很多事情对程序员来说很重要,对数据科学家来说同样重要,甚至更重要。例如,在第一章中,有一节是关于交流的。如果你还没有被告知,沟通是数据科学的关键!
我希望这是一系列的帖子,将突出本周章节最重要的部分,以及一些关于我向我的学员提议的每周 Python 练习的讨论。所以事不宜迟,第一周我提议阅读序言和第一章:实用主义哲学。
在数据科学中,就像在一般的编程中一样,你必须调整你的方法来适应当前的环境。这些调整将来自你的背景和经历。与务实的程序员一样,务实的数据科学家完成工作,并且做得很好。
我将集中讨论一个方面,而不是一章的细节。从这个意义上来说,这篇博文是对《实用程序员:从熟练工到大师》中相应章节的补充。这周我想集中讨论“破窗”。建筑从破窗理论当你在一栋建筑上留下一扇破窗,它会灌输一种对那栋建筑的遗弃感。从那种被抛弃的感觉,人们会开始觉得没人关心这栋建筑。更多的窗户将被打破,涂鸦将被画出,其他损害将被带到该建筑。一个类似的例子是软件,当你有一个“破碎的窗口”时,人们会试图远离那段代码,不会有试图改进它的反射。
作为第一周的练习,我建议在你的团队拥有的代码中找出一个破损的窗口,并找个人(最好是在你的团队中)来讨论它。情况有多糟?我们如何改进它?更好的办法是,怎样才能修好那扇破窗户?也许采取最初的几个步骤可能是你的团队对破窗和技术债务的新态度的开始。
第一章还有更多的内容。尽管如此,对于希望提高 Python 编程技能的初级数据科学家来说,我建议熟能生巧。在这种情况下,这个主题内的练习可能证明是有用的:破窗。
完成这个练习后,问自己这些问题:
- 如果合同没有得到遵守,比如最初的断言,你能确保你的程序提前中断吗?在这个练习中,我们需要一个 int 类型的列表,如果你收到了其他的东西,你应该在这里中断。您可能还需要检查其他先决条件。
- 相反,如果合同允许输入,你确定你能处理边缘/边界值吗?你知道你的程序应该如何反应吗?
- 你是否编写了处理特定任务的函数?如果你发现程序的某些部分在重复,你有没有采取措施重新调整这些部分,这样你就不会重复了?
- 你以任何方式记录你的程序吗?在这里,团队文化可能会有所不同,但仍然是一个很好的做法,为将跟随的人留下面包屑(即使是未来的你!).你的变量名有意义吗?它们是文档的一部分吗?
- 你做了创建单元测试的额外工作了吗?许多框架都可以用于这个目的。理想情况下,你要让自己了解你的团队最常用的一种。
也许你会认为这些问题对于这样一个小程序来说有些小题大做,但是再次强调,熟能生巧。如果你不在小问题上练习这些,很可能你不会想到在大问题上做这些。
如果你能接触到一个你觉得相处融洽的人,并且你认为他写了很棒的代码,问问他对你的练习解决方案的意见。你可能会学到一两件事!
这是我对“实用程序员:从熟练工到大师”第一周/第一章的快速补充,作为提高数据科学中软件编写技能的媒介。下周见第二章:务实的方法。
在软件领域 20 多年了。目前在 Shopify 担任数据科学家。在深度学习、机器学习/分析、云计算、物联网、领域特定语言、遗传算法和编程、人工生命/智能以及所有技术领域的研究兴趣!通过点击查看所有帖子
封面照片来自 Pexels 上的cotton bro。
原载于 2021 年 3 月 23 日 http://thelonenutblog.wordpress.comhttps://thelonenutblog.wordpress.com/2021/03/23/better-software-writing-skills-in-data-science-broken-window/。