TowardsDataScience 博客中文翻译 2022(一百四十三)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

你的代码有味道吗?

原文:https://towardsdatascience.com/does-your-code-smell-acb9f24bbb46

什么是代码气味,如何减少代码气味

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

马库斯·斯皮斯克在 Unsplash 上的照片

我承认,直到最近一位更资深的开发人员告诉我我的代码“有味道”时,我才发现代码有味道。我看着它们,看着我的代码,想知道它们到底是什么意思。当他们接着解释说代码气味是代码中的模式,不一定会阻止代码运行,但可能表明一些有缺陷的逻辑,或者可能是不稳定或难以维护的代码时,我的脸上一定露出了这种表情。我明白他们的意思,也明白为什么我的代码不是我能写出的最好的代码,所以我着手修复它。然而,从那以后,我想更深入地了解什么是代码味道,以及如何在自己或他人的代码中找到它们。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Unsplash 上的battle creek 咖啡烘焙师拍摄

那么什么是代码气味呢?首先,它们不一定是你的代码中的 bug 或错误,事实上你的代码实际上可以运行得非常好,并通过所有它需要的测试。但是这并不总是好的代码。代码气味基本上是代码片段,在运行时,往往表明逻辑有问题,或者给代码库带来不必要的复杂性。虽然现在并不总是产生问题,但这可能会使代码难以扩展,或者在将来产生难以调试的错误。

代码气味可能会产生一些问题,比如降低处理速度、增加失败的风险,以及进一步产生 bug。糟糕的代码会导致糟糕的代码质量,并且会增加您的团队将来必须处理的技术债务的数量。这是你绝对不希望你的名字出现在代码提交中的。然而,好的一面是代码气味可以被“嗅到”,并且相对快速地发现。尤其是当你的公司使用代码审查系统时,因为其他人可以指出你的问题,或者你使用一个自动工具来标记你的代码库。当然,您更愿意使用后者或者知道要注意什么,而不是依赖别人来发现您的糟糕代码。

实际上,不同项目、不同开发人员、甚至不同公司的代码味道可能不同,因为这将取决于对代码所期望的定义和接受的标准。尽管如此,通常有一些众所周知的代码味道,您可以尝试在自己的代码中减少:

  • **重复代码:**这是同一段代码在你的程序中多次出现的地方。此时,最好尝试将这段代码放入一个函数中,这样你就可以多次调用它,而不必多次输入。这也意味着,如果你需要对它的功能进行修改,你不需要复制这些修改,也不需要冒以后代码中出现 bug 的风险。
  • 不必要的复杂性:这可能意味着各种各样的事情,但是当你使用复杂的设计模式时,更简单、不复杂的设计也能工作。如果你看着你的代码,认为它可以用一种更简单的方式来完成,或者它看起来很复杂,它可能是可以的。花些时间想想那段代码,写下它应该做什么,什么时候做,然后想想如果你从头开始会有什么变化。然后着手重构代码,使之变得更容易。
  • 做多种事情的大型函数:这是一个大忌,会让程序很难调试。如果你程序中的一个大函数出了问题,你可能知道错误来自那个函数,但不知道是什么触发了它。这也会使测试变得非常困难,从而使您的代码在将来难以维护。您希望确保您的函数很小,并且只处理一件事情。这使得测试变得非常容易,如果以后出现任何错误,也可以很容易地看到哪里出了问题。
  • 嵌套的 if 语句:这也是一种典型的代码味道,所以如果可能的话,你应该尽量避免。这往往表明你的逻辑有问题,或者你试图一次检查太多的事情(这就是我被抓到的做法)。这使得阅读和理解正在发生的事情以及确切的代码运行时间变得非常困难。在这一点上,试着找出你的基本条件应该是什么(无论如何应该做什么),然后从那里开始你的逻辑工作。这同样适用于 if、elif 和 else 语句链,它们通常看起来非常混乱。
  • 陌生而不相关的名字:这适用于以不清楚它们做什么或如何使用的方式命名的变量、函数、类和模块。这在数据科学中很常见,我们称事物为“x”或“y ”,没有一般的原因。这也使得代码非常难以阅读。原则上,您希望确保所有的名称都清楚地表明这段代码是什么或者它应该做什么。这也有助于识别大型函数,因为难以命名的函数通常表明它做得太多。尽可能简单明了地给事物命名。你和其他人以后会感谢你的。

这些是程序员在旅程开始时(有时甚至更早)挣扎的常见代码气味,但还有更多。在您自己和其他人的代码中注意这些模式是很重要的,以确保您正在构建的产品是可靠的、健壮的、可伸缩的,从长远来看对您自己和客户都有好处。一旦识别出来,重要的是尽可能地重构代码,同时试图确保不会引入更多的气味,并且所有的测试仍然通过。这将使下一个接管你的代码的人免于在将来不得不重构你的工作,并减少为你的团队引入技术债务的可能性。

结论

虽然代码气味不会破坏你的代码,但是注意它们是很重要的。当您刚开始尝试学习很多东西并让事情运转起来时,这可能很难,但是能够识别它们并知道如何解决它们将使您能够产生更好的代码,这对您的团队未来是有用的。创建一个新的变化或新的特性可能会花费你更多的时间,但是如果没有代码的味道,这些代码在将来会更健壮、更简单、更易维护,这意味着你将有更多的时间来构建产品,而不是简单地维护它。祝你好运!

如果你喜欢你所读的,并且还不是 medium 会员,请使用下面我的推荐链接注册 Medium,来支持我和这个平台上其他了不起的作家!提前感谢。

https://philip-wilkinson.medium.com/membership

或者随意查看我在 Medium 上的其他文章:

https://python.plainenglish.io/a-practical-introduction-to-random-forest-classifiers-from-scikit-learn-536e305d8d87

你的模型超过基线了吗?

原文:https://towardsdatascience.com/does-your-model-beat-the-baseline-3b9fb31cbe76

让我们将我们的模型与一个普通的基线进行比较

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片 by Pixabay:T3【https://www.pexels.com/it-it/foto/lampadina-chiara-355948/】

每次我们训练一个模型时,我们都应该检查它的性能是否超过了某个基线,这是一个没有考虑输入的琐碎模型。将我们的模型与基线模型进行比较,我们实际上可以计算出它实际上是否学习了。

什么是基线模型?

基线模型是一种实际上不使用特征的模型,但对所有预测使用一个平凡的常量值。对于一个回归问题,这样的值通常是训练数据集中目标变量的平均值(10 年前,我曾经进行 ANOVA 测试来比较线性模型和这样一个微不足道的模型,这种模型被称为零模型)。对于分类任务,普通模型只返回训练数据集中最频繁的类。

因此,这是我们数据集的基线,一个经过适当训练的模型应该能够超越这种算法的性能。事实上,如果一个模型像基线一样执行,它实际上没有考虑特性,所以它不是学习。请记住,基线模型的给定定义根本不使用特性,它们只是以某种方式对目标值进行平均。

在这篇文章中,我们将会看到如何比较一个模型和一个基线模型。

战略

总的想法是用模型和基线模型在测试数据集上计算一些性能指标。然后,使用 bootstrap ,我们计算这种测量的 95%置信区间。如果间隔不重叠,则模型不同于基线模型。

按照我们选择的性能指标,我们允许模型实际上具有可比性的概率高达 5%。不幸的是,只看指标的平均值是不够的。小数据集可能会引入有限大小的效应,使我们的分析变得不可靠。这就是为什么我更喜欢使用 bootstrap 来计算置信区间,这让我们更好地了解情况,从我们的数据集中提取尽可能多的信息。

Python 中的一个例子

在 Python 中,基线模型由 DummyClassifier 和 DummyRegressor 对象表示。前者考虑训练数据集中最频繁的目标类,后者考虑目标变量的平均值。这些设置是可以改变的(例如,通过考虑中间值来代替平均值),但我通常更喜欢使用默认设置,因为它们非常真实和有用。

对于回归问题,我们将使用“糖尿病”数据集和随机森林分类器。我们的绩效指标将是 r 平方分数。

让我们先导入一些库:

import numpy as np
from sklearn.ensemble import RandomForestClassifier,RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_wine, load_diabetes
from sklearn.dummy import DummyClassifier,DummyRegressor
from sklearn.metrics import accuracy_score, r2_score

然后,让我们导入数据集:

X,y = load_diabetes(return_X_y = True)X_train,X_test,y_train,y_test  = train_test_split(X,y,test_size=0.4,random_state=0)

我们现在可以训练随机森林和虚拟回归器。

model = RandomForestRegressor(random_state=0) model.fit(X_train,y_train) dummy = DummyRegressor() 
dummy.fit(X_train,y_train)

最后,通过 500 次迭代的 bootstrap,我们可以根据相同的测试数据集计算模型的 r 平方的置信区间。

scores_model = []
scores_dummy = []
for n in range(500):
  random_indices = np.random.choice(range(len(X_test)),size=len(X_test),replace=True)
  X_test_new = X_test[random_indices]
  y_test_new = y_test[random_indices] scores_model.append(r2_score(y_test_new,model.predict(X_test_new)))
 scores_dummy.append(r2_score(y_test_new,dummy.predict(X_test_new)))

最后,这些是模型和虚拟分类器的置信区间:

np.quantile(scores_model,[0.025,0.975]),np.quantile(scores_dummy,[0.025,0.975]) # (array([0.20883809, 0.48690673]), array([-3.03842778e-02, -7.59378357e-06]))

正如我们所看到的,区间是不相交的,并且与模型相关的区间的下限大于与虚拟模型相关的区间的上限。因此,我们可以说我们的模型在 95%的置信度下比基线表现得更好。

使用分类器可以遵循相同的方法。在本例中,数据集将是“葡萄酒”数据集。评分标准将是准确性得分。

X,y = load_wine(return_X_y = True) X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.4,random_state=0)

以下是模型:

model = RandomForestClassifier(random_state=0) 
dummy = DummyClassifier() 
model.fit(X_train,y_train) 
dummy.fit(X_train,y_train)

这是两个模型的准确性得分的自举:

scores_model = []
scores_dummy = []
for n in range(500):
  random_indices = np.random.choice(range(len(X_test)),size=len(X_test),replace=True)
  X_test_new = X_test[random_indices]
  y_test_new = y_test[random_indices] scores_model.append(accuracy_score(y_test_new, model.predict(X_test_new)))
  scores_dummy.append(accuracy_score(y_test_new, dummy.predict(X_test_new)))

最后,这些是置信区间:

np.quantile(scores_model,[0.025,0.975]),np.quantile(scores_dummy,[0.025,0.975]) # (array([0.91666667, 1\. ]), array([0.31215278, 0.54166667]))

同样,该模型以 95%的置信度比虚拟模型表现得更好。

结论

在本文中,我展示了一种技术来评估一个简单的基线模型的性能。尽管这经常被忽视,但这种比较很容易进行,而且必须经常进行,以便评估我们的模型的稳健性及其泛化能力。

原载于 2022 年 7 月 3 日【https://www.yourdatateacher.com】

进行云迁移?何时应该添加数据目录和治理?

原文:https://towardsdatascience.com/doing-a-cloud-migration-when-should-you-add-a-data-catalog-and-governance-4da78400308e

早点做。保持敏捷。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 pixabay — CC 授权提供

这不完全是先有鸡还是先有蛋的问题,但这是许多企业数据领导者在倾向于采用现代数据堆栈(通常从采用云数据仓库开始)时面临的一个困境:何时是引入数据目录的合适时机?

尝试一步一步来做很有诱惑力:我会先将所有数据迁移到我的数据仓库,然后再担心发现和治理。但是我想说的是,你应该同时做这两件事。

我将阐述我的观点,然后描述采用敏捷数据治理方法的流程,这将实际上帮助您更快地完成迁移,通过数据目录和治理平台协调工作。无论是在内部还是在我们的整个客户群中,我们都看到了这样做如何能够增加您的迁移成功的机会,并加快数据驱动文化的采用。

通过将敏捷方法应用到数据堆栈开发中来获得正确的结果

在迁移到现代数据堆栈的同时,通过数据目录采用敏捷数据治理,可让您从新数据平台中即时获得收益和投资回报。它还可以帮助您避免典型的瀑布开发方法的缺陷,这些方法会困扰数据和分析并减缓创新。在您的数据治理和管理流程中采用敏捷原则将使您的组织比以往任何时候都更快地获得现代工具的投资回报。

以下描述的方法在 data.world 内部(我们使用自己的数据目录从 AWS Athena 迁移到 Snowflake)和我们的客户中都证明是成功的:

1.建立分析积压

创建企业需要或想要的指标列表。通常最好将这些指标表述为这样的问题,“我们网站的访问者的日平均会话长度是多少”,或者“我们在某个时间段的平均订单价值是多少?”这相当于软件开发中的用户故事。从高价值的问题开始,你会发现有助于你下一步的模式。这也是考虑创建度量标准或语义层真正有用的地方。不过,最终这些指标将需要被分解成计算所需的数据源,这就是在这个过程中考虑第二步变得有价值的地方(这样您就可以创建超越简单指标的可重用数据产品)。

2.决定建筑风格

像一个设计良好的软件应用程序一样,数据仓库或数据湖中的数据应该符合一种架构风格。您可以基于您的分析积压中的问题类型以及您的企业中主要可用的数据的形状和类型(星型模式、雪花型模式、数据仓库和许多其他非规范化格式)来选择样式。考虑数据模型的层次,从原始数据到干净数据,再到转换后的分析模型。您可以将这种分层与从原始 API 到业务逻辑再到 UX 的软件分层进行比较。

您选择的架构风格将对分析师和数据科学家如何访问和使用数据产生重大影响。一致地应用这种风格将使您的数据平台对所有数据消费者更有用。在 data.world,我们使用星型模式布局和 ELT(提取、加载、转换)架构模式。事实表和维度表的星型布局特别适用于跟踪我们的会员群的活动,也适用于按时间段或按客户组织进行分析。

3.选择工具链

一旦你有了一个架构风格和一堆分析故事,是时候选择一些工具了。在一个数据科学和分析用例不断扩展的世界中,这些工具的协同工作对于保持敏捷性至关重要。不同的数据平台支持不同的架构风格。工具链的关键是数据平台/查询层、ETL/数据集成工具和数据目录。

随着使用的成熟,可以集成数据质量、概要分析、沿袭和其他工具。拥有一个开放灵活的元数据模型的数据目录对于随着时间的推移添加新工具至关重要。它还为您提供了扩展 BI、ML/AI 和数据科学工具箱的基础,以便随着时间的推移支持数据消费者。在 data.world,我们采用了 JIRA 来管理我们的分析积压,雪花用于我们的数据平台,dbt 用于转换,以及各种分析工具。所有这些都通过 data.world 数据目录进行协调。

4.召集你的团队

现在是时候将数据消费者和生产者聚集在一起,他们将参与最初的分析故事。好的敏捷过程在每个接触点都包含了各种各样的利益相关者。这使得反馈循环紧密,可能是推动采用的最重要的事情。考虑一下你会找谁来协调你的数据冲刺;此时,指定某人扮演数据产品经理或所有者的角色。数据工程师、管家和产品经理不能躲在山洞里几个月,然后出来期待分析师和数据科学开始使用结果。如果没有让所有的利益相关者都参与数据产品的开发,并获得反馈和实时提供价值,那么失败的几率就会成倍增加。从我们的数据产品中获取投资回报的能力也提高了,因为从基于数据的见解中获得优势的机会往往稍纵即逝。等待数月才能使用一个“完美”的数据仓库将意味着获取价值的机会已经过去。

5.挑选你的第一个分析故事

按照经典的敏捷/scrum 方式,现在是时候分组、区分优先级,并选择第一组要处理的故事了。所有利益相关者都应参与这一进程。分组可以使用传统的技术来完成,如卡片分类和亲和力练习。规模、业务影响和可用的团队也可以在故事最先完成的过程中发挥作用。

确保分析是具体的,而不是假设的。选择与数据消费者需要完成的工作密切相关的故事,以便最终交付清晰、可衡量的价值。此外,对这些可交付成果进行时间分类,并设定一个日期来衡量结果。这将有助于你在第一次迭代中控制住煮沸海水的诱惑。

6.在数据目录中收集您的资源

是时候让数据生产者(通常是数据库管理员或数据工程师)收集原始数据源来回答第一组分析故事中提出的问题了。当生产者在你的数据目录中按故事筛选来源时,消费者可以对这些来源进行评估和提问。最初的问题和发现对于实时捕捉至关重要,不能消失在聊天或电子邮件中。一个好的数据目录使这种管理、分析和问题处理变得流畅,并简化了整个工作流程。在这一步中,您会明白为什么应该同时构建一个目录和仓库。

7.构建并记录您的数据产品

随着数据源被细化到您所选择的架构风格中,数据消费者应该实时处理数据,并评估模型在回答所提出的度量问题方面有多好。数据管理员在正在使用的数据旁边构建数据字典和业务术语表。既然您已经通过分析故事对来源进行了筛选,那么现在就可以根据目的发现适当的数据资产了。通过将数据目录作为新数据平台协作的支点,所有这些知识的获取都是实时进行的。这最大限度地减少了不得不回去从 Google Sheets 中抓取数据字典或编写无聊文档的麻烦。通过在构建资产时合并您的数据目录,您可以确保它们的重用并最小化您的知识债务。

8.同行评审分析

在你的第一次数据冲刺结束时,是时候对工作进行同行评审了。有了企业数据目录,这个过程的效率要高得多。您的数据目录为消费者和中小企业提供了一个提问和了解结果的友好环境,防止了当人们带着不同的结果和定义出席决策会议时发生的数据争吵。每个人都可以看到谁对这项工作做出了贡献,以及被问到的其他问题。可以快速有效地验证和扩展工作。您的数据工作都在一个地方:数据目录。

9.公布结果

恭喜你!您已经在全新的出色数据管理平台中拥有了第一套数据模型。一切都由分析故事精心策划,经过同行评审,并记录在您的云数据目录中。您已经为企业做了一些有益的事情,同时使其可重用。最重要的是,您的团队没有进行大量的事后文档工作,因为工作从一开始就在数据目录中完成了。您还迈出了采用数据网格架构并将数据资产视为产品的第一步。

10.精炼和扩展

通过以敏捷的方式同时使用您的数据平台和数据目录,您的资产将在发布时得到很好的记录和组织。随着下一个 sprint 的到来,您现在可以扩展或细化已经发布的资产。一个资产被很好地记录并围绕用例组织的起点使得接下来的冲刺变得越来越容易。然后,您可以扩展该计划,以包括更多的业务线或工作组。这种扩张推动了我们都渴望的采用、数据素养和数据驱动的文化。

如果您已经开始了迁移到新的云数据仓库或数据湖的道路,您仍然可以采用敏捷数据治理实践,消除您拥有的任何知识债务——永远都不会太迟!采用一个数据目录,让你能够反复减少你的知识债务,这将是让你感觉不到你有一个沸腾的海洋的关键。如果您有兴趣了解更多信息,或者您已经在以这种方式工作,我很乐意收到您的来信!

进行解释性数据分析

原文:https://towardsdatascience.com/doing-explanatory-data-analysis-f184c01557e7

有没有可能完全在 GPU 上完成?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

约书亚·索蒂诺在 Unsplash 上拍摄的照片

当我们对训练**深度学习模型不感兴趣时,我总是在黑暗中感觉这些 GPU 设备有多有用。不过,最近看了一些关于熊猫以及如何加快处理速度的文章。这些文章让我有点好奇,所以我决定启动我的数据科学机器,在 **GPU、上抓取一个大文件,看看我是否能在 GPU 上完成整个 EDA 练习。我在黑暗中有一种阳光的感觉,有点像照片里的人。

那么 EDA 可以完全在 GPU 上完成吗?让我们来了解一下!

我的数据科学机器

让我们从了解主机开始。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来自 about 系统的截图——在 Ubuntu 设置中——作者在写作当天的图片

系统的主要亮点是:-

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

该系统有三种板载存储类型——作者在写作当天截图。

我自己组装了系统,并按照主板和 GPU 卡上允许的价格升级了组件。这个系统可以处理大多数任务,应该足以应对我们的挑战!我希望你同意,它是安全的说,没有硬件障碍!

用于实验的数据集

我为 GPU 实验选择了一个有 7M 记录的数据文件。在 Kaggle [1]上描述了700 多万家公司的数据集,并在其他文章中使用,如“使用 Python 对 700 万家公司进行探索性数据分析”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本地驱动器上数据文件的屏幕截图。图片由作者提供。

该文件大小为 1.1 GB,有 700 多万行和 11 列。由于 700 多万行,它扼杀了 Excel。 Alteryx 整个吞下。 PowerBi 和 PowerQuery 可以处理这个文件,但是我必须做摘要视图来将它们加载到 Excel 中。

在下载和使用数据集之前,最好检查许可,并确定所有权和权限。根据知识共享 CC0.01 获得许可的 700 多万公司数据集。 “你可以复制、修改、分发和执行作品,即使是出于商业目的,都无需征得许可。”

也有特定于发布者的规则,例如关于数据科学的。因此,请小心选择数据集和来源,将许可证与出版商条款&条件相匹配。

GPU 设置

通常,调用 Nvidia-smi 是我检查和确定 GPU 是否可用的第一件事。我们看到,CUDA 11.4 可与 Nvidia 驱动程序 470.141.03 一起使用。所有这些都与我今年早些时候安装 Quadro 时所做的设置一致。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者展示 Nvidia-smi 命令输出的图片。

您可能会注意到,GPU 上已经有一些工作负载,这只会导致问题。几乎 1GB 的卡 RAM 已经被分配。 因此,我们必须将视觉显示工作负载转移到英特尔板载 GPU 上。重新配置 Xorg 屏幕设置使得 NVIDIA GPU 可以自由地专用于数据工作!我很喜欢在 4K 看网飞!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将视觉显示移到英特尔 CPU/GPU 后,NVIDIA 卡的可用性更高。作者图片

接下来,我们需要安装急流

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

https://rapids.ai/start.html

复制命令并粘贴到终端。让 conda 负责一切,但只是根据您的系统做出正确的选择,以避免冲突和问题。最后,激活环境(rapids-22.08),启动 jupyter 并做一个快速测试。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Jupyter 笔记本加载 cudf 成功的截图。作者图片

好了,我们了解了我们的硬件,并配置了我们的软件;现在是时候来点 EDA 了。感谢感谢**激流队,**我没有复杂的依赖挑战。

我们就偷懒吧,把文件扔在卡上。

因为 Rapids 安装在一个环境中,所以您必须首先激活该环境。我使用了 Anaconda Navigator,只是从可用的环境中进行选择。我使用的是 rapids-22.08 ,这个环境是由 RAPIDS conda install 命令创建的——见前面。

我对这种快速而肮脏的方法感到惊讶。成功了!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由帕蒂·布莱克Unsplash 上拍摄

让我们分几个块来看一下代码

加载模块

导入常规嫌疑人和 CUDF。因为我不确定我能走多远,所以我同时使用 cudf(cu)和 pandas(pd)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

朱庇特笔记本——作者截图

构建基于 GPU 的数据框

请注意。read_csv()方法,它看起来类似于 pandas 方法,但是我们需要深入了解不同之处。现在,我只想感受一下它的表现,如果有的话!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

使用传统的 RAM 和 CPU 计算方法

可能还要做一个 cudf。DataFrame.from_pandas!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

结果

令人惊讶的是,这种方法开箱即用。之前我做了很多’ SUDOing '和其他痛苦的依赖问题的解决。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

我仍然很惊讶这样一种懒惰的方法起作用了——只需要大约 2 秒钟就可以读取那个大文本文件并将其传输到 GPU。印象深刻!该文件在磁盘上有 1.1GB。注意内存的使用——它是 1.3+ GB,嗯!Alteryx 在 Mac Mini M1 的 Windows 11 上通过 Parallels 报告了 6.4 秒。几分钟后,Power Query 仍在后台运行查询。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图。

不出所料,装载熊猫总是开箱即用。读取、创建数据结构和将数据帧加载到 RAM 中需要 16 秒。几乎慢了 8 倍。但是看看内存占用大小-> 602.0+ MB 对 1.3+ GB。从视觉上看,两个设备上的数据帧具有相同的列和数据类型。

再次使用 NVIDIA-smi

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者使用 Nvidia-smi 命令输出的截图

事实上,GPU 将 python 报告为分配了 1605 兆字节存储的用户。这令人印象深刻。

清洁

所以我们知道可以把大文件加载到 GPU,但是清理呢?尤其是丢失的值,计算代价会很高。

if(df.isnull().values.any()):
    missing = df.isnull().sum()
    print(missing)
    print(" ")
    for col in df.columns:
        print (col, "-\t", df[col].nunique())df.dropna(axis=0,inplace=True)df.notnull().sum()

打印缺失值汇总的基本代码,显示每列中唯一条目的数量,删除列中缺失值的所有行,然后转储所有非缺失值的汇总。

这种代码在 GPU 上速度快如闪电,但在传统的 CPU/RAM 方法上速度很慢。

Summarize missing: CPU/RAM: That took : **0:00:30.536083** 
with GPU taking **0:00:01.035225**

在传统配置上需要 30 秒,而在 GPU 上几乎不需要。Aggregation 和 groupby 也极快,语法和熊猫一样。

df.groupby('size range').agg({'year founded': ['min', 'max', 'count'], 'country': lambda x: x.nunique(), 'current employee estimate': 'median'})

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者在练习中从 Jupyter 笔记本中获得

df = df[df['year founded'] < 2023].copy()
pddf = pddf[pddf['year founded'] < 2023].copy()

子设置和复制数据帧在这两种方法中的行为也是相同的。酷!

形象化

好吧,清理一个数据帧在 GPU 上效果更好,但是一些图形呢?

好吧,这就是你可能已经在等待的东西!消息是 CUDF 不像 Pandas 那样包装 matplotlib。因此,我们不能直接在 GPU 数据框架外绘图。相反,我们必须将数据从 GPU 卡复制到主板 RAM 中。

df.to_pandas().plot()

自然,这就是我们停下来的地方。毕竟,我无法在 GPU 上完成整个 EDA 练习。我可以很快地准备一个数据框架,而且几乎没有痛苦,速度也很快!

警告

GPU 设备的行为不同于传统方法。像%%timeit%%这样的项目会导致 GPU 出现内存错误。

del pddf
del df

从 GPU 中删除数据帧会释放设备上的分配,并允许加载更多数据帧。您必须注意释放分配,否则设备会抱怨。

贮藏室ˌ仓库

我把我的代码加载到 GitHub,你可以在下面的链接找到这个笔记本。

https://github.com/CognitiveDave/ReadingList/blob/main/cudf.ipynb

为什么不加入 medium?50 美元的投资在 12 个月内是不错的回报

https://cognitivedave.medium.com/membership

参考文献/引文

[1]700 多万公司数据集根据知识共享 CC0.01 获得许可。你可以直接从人民数据实验室索取一份的拷贝,并在这里阅读更多关于他们的内容。这里的数据用于加载到 GPU 上,并用于创建战术总结。

领域专家是健壮的 ML 系统的基本模块

原文:https://towardsdatascience.com/domain-expert-is-an-essential-block-of-a-robust-ml-system-a29fd1576832

在试图做得更好之前,先了解业务

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Unsplash 上拍摄的 ThisisEngineering RAEng

我们看到不同的数字表明有多少百分比的机器学习模型从未投入生产。我不想给出一个确切的数字,但我们只能说大多数机器学习模型都没有实现生产化。

无法进行最后一步部署可能有多种不同的原因。

例如,与模型提供的值相比,运算在计算和存储方面可能太昂贵。或者,当模型被缩放时,结果和性能急剧恶化。

我们也可能无法将模型正确地部署到生产中。这是一个操作问题,可以通过实施一个强大的 MLOps 系统来处理和解决。

MLOps 指的是用许多不同类型的操作构建一个系统的过程,这些操作是同步的并且协同工作。

就像 DevOps 是创建大规模软件系统的常见做法一样,高效的机器学习系统也需要 MLOps。

数据科学家可以使用 Jupyter 笔记本中的样本数据集来创建和评估机器学习模型。

然而,当涉及到将 Jupyter 笔记本中的这个模型转换为在生产中连续运行的 ML 系统时,需要涉及到其他角色。

在这篇文章中,我们将讨论我认为对于创建一个健壮的、有利可图的、有益的 ML 系统最关键的角色:领域专家。

领域专家

这些都是懂业务的人。它们不一定是面向数据的,但对于数据如何在特定领域发挥作用提供了非常有价值的反馈。

ML 系统中面向数据的人员(例如,数据科学家、数据分析师、数据工程师)不可能对业务有全面的了解,这通常需要在特定领域积累多年的经验。

领域专家充当面向数据的人员和业务之间的桥梁。信息以洞察力、反馈或行动的形式在这座桥上双向流动。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(图片由作者提供)

假设一个数据科学团队试图为一家拥有许多商店的杂货零售商创建一个预测系统。

如何开始

ML 系统应该从领域专家开始。它们有助于定义业务目标和关键绩效指标(KPI ),这对于衡量 ML 系统的绩效至关重要。

领域专家知道企业需要什么。它们有助于解决需要解决的问题和有潜力改进的流程。

数据科学家或机器学习工程师挖掘数据,以提取见解,发现模式和关系。但是,需要将他们引向具有更大影响或商业价值的问题。这是领域专家可以帮忙的。

如何结束

假设面向数据的专业人员和领域专家坐在一起,进行长时间的头脑风暴。他们提出了问题和解决问题的方法。

设计并实现了 ML 系统。然后,我们开始看到结果。这些指标看起来不错,至少基于预定义的 KPI。

然而,我们离产生商业影响还很远。例如,问题可能是银行的客户流失预测。从数据科学家的角度来看,只要评估指标符合预定义的值,解决方案就很好。

然而,ML 系统的主要目标并不是满足度量标准。重要的是创造的商业价值。因此,领域专家应该参与到这样的场景中。

他们在负责 ML 系统的团队和以业务为导向的部门(如客户服务和市场营销)之间传递信息。这个信息流主要由迭代反馈组成,目标是使生产中的 ML 系统创造价值。

最后的话

一个 ML 系统由许多构件组成,这就是为什么有一个完整的规程来使它工作:MLOps。

MLOps 中涉及的职业可能会因组织或业务而异。典型的角色有数据科学家、数据工程师、软件工程师、机器学习工程师/架构师和领域专家。

当然,每个角色的工作都是至关重要的,但我觉得领域专业知识的重要性有时被低估了。没有领域专家或非常了解业务的人的 ML 系统很可能会失败。

你可以成为媒介会员来解锁我的作品的全部访问权限,以及媒介的其余部分。如果你已经是了,别忘了订阅如果你想在我发表新文章时收到电子邮件的话。

感谢您的阅读。如果您有任何反馈,请告诉我。

暂时不要成为数据科学通才

原文:https://towardsdatascience.com/dont-be-a-data-science-generalist-yet-8675fceb2f1e

选择一个专业,加倍下注

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

保罗·斯科鲁普斯卡斯在 Unsplash 上的照片

我不时会看到一张“数据科学家路线图”,里面塞满了天底下所有的数据工具和 ML 概念。虽然这些对于获得生态系统的高层次视图是有用的,但我认为它们通常会适得其反。这可能会让新手认为,他们必须学习一切才能被雇佣——每种算法、每种工具、每种机器学习和数据科学库。

就业市场的一些趋势强化了这一观念。职称不一致且模糊不清。一家公司称之为数据科学家,其他公司会称之为数据分析师。做足够多的采访,你会被问到所有的问题——从 leet 代码问题,到案例研究,再到统计数据。

事实是,要成为一名高效的员工,你不需要什么都知道。

是的,一些职位描述让你看起来是这样。但是工作描述是愿望清单。你不需要满足所有的先决条件。你真正需要的是对基本面的扎实把握和成长心态。

当你找到工作时,学习不会停止。事实上,那是你大部分学习的地方。你只需要让你的面试官相信你有能力学到你错过的东西。

当你刚开始的时候,不要走得太远。选择一个专业并专注于它。没有一种工作是完全分类的,这个行业在不断发展。但是有几个核心原型需要考虑:数据分析师、数据科学家、机器学习工程师和数据工程师。你的第一个目标应该是确定这些原型中哪一个最适合你(这个小测验可能会有帮助)。

平心而论,没有实际经历,这很难真正知道。你的第一份工作可能是数据科学家,然后才发现你更喜欢数据工程师的工作。那很好。那是自然的。随着时间的推移,你会了解自己的偏好,你的职业道路也会随之改变。但是如果你能缩小搜索空间,尽管你自己也有不确定性,你最初的求职会容易得多。

你可以通过动手做些事情来弥补经验的不足。构建涉及数据管道所有方面的端到端项目——收集和清理一些数据,训练一个模型,部署它。注意管道的哪些部分你喜欢,哪些部分你不喜欢。深入挖掘你喜欢的事情。

一旦你对自己喜欢的工作有了概念,就加倍努力。同样,你不必学习所有的。实际上,选择 2-3 项技术。收集一堆吸引你的工作描述,看看在需求中最常出现的是什么。与业内人士交谈,看看他们使用什么工具,他们认为什么是重要的。专注于那些事情。

有些公司确实需要一个数据科学通才——一个基本上什么都能做的人。这在初创公司或大公司的全新团队中很常见。然而,对于初学者来说,这些通常不是好角色。

不要做数据科学通才。至少,现在还没有。

不要忘记你的数据科学家头衔中的“科学家”(第 2 部分)

原文:https://towardsdatascience.com/dont-forget-about-the-scientist-in-your-data-scientist-title-part-2-28c208b86ba2

在不引入混淆变量的情况下同时测试多个因素

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

国家癌症研究所Unsplash 上拍摄的照片

如果您错过了第 1 部分,请前往那里阅读完整的实验设计介绍

作为快速复习,实验设计是一种技术,允许研究人员评估许多不同因素对系统的影响[1]。我们讨论了如何避免混杂因素,并浏览了一些例子,但我们并没有真正讨论如何同时测试多个因素。

添加另一个因素

析因设计的美妙之处在于它非常容易扩展。

让我们从以前的帖子中构建一个假设的深度学习模型的例子。每个级别中包含的具体内容并不重要,因此了解深度学习概念并不是能够理解的必要条件。

要评估如果模型中的神经元数量增加会发生什么,只需在实验中添加一个因子即可。让我们看看如果神经元的数量增加到 32 或 64(即 3 个级别:级别 1 是 16 的基线,级别 2 是 32,级别 3 是 64)会发生什么。为了全面衡量这一变化的影响,需要创建额外的实验来测试这些不同的超参数配置。下面是这一过程的概述,每个方框代表一个实验。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片:2×3 因子设计

从 2x1 设计到 2x3 设计会导致额外增加四个测试场景。这看起来很简单,但是除了测试如果层数增加会发生什么之外,还创建了其他场景来测试不同数量的神经元场景。这里重要的一点是,我们需要测试一个因素的每一个水平与另一个因素的每一个水平。当一个实验被概括为 2×3 因子设计时,很容易进行数学计算,并看到需要测试六个场景来全面评估每个选项。最终的结果是,通过使用一个度量来测试性能,很容易评估六个场景中哪一个表现最好。

再加一个因素??

这太简单了,为什么要止步于此呢?让我们疯狂一下,再加一个因素。

为了真正了解析因设计(这是我们在这里讨论的实验设计的具体类型的名称)是如何扩展的,让我们播放一个场景,其中我们还想测试不同的优化器。最初,ADAM 是基线优化器,但是如果使用 SGD,让我们测试一下性能指标的变化。为此,设计从 2x3 设计变为 2x3x2。这导致我们以前的设计有 6 个场景移动到一个将测试 12 个场景。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片:添加两个级别的附加因子(优化器)的概要

冒着多余的风险,您可以很容易地看到,添加另一个具有两个级别的因素,使我们根据新因素的所有级别来评估之前的每个场景。此时,应该很容易看出这个框架的可扩展性。然而,增加一个额外的因素会增加总体工作量,这也是显而易见的。

自动化您的实验

如您所见,析因设计是一个很容易扩展的概念,但就需要测试的场景数量而言,它可能最终成为一个负担。这听起来可能需要做很多工作。如果每个场景都被单独测试,那么它肯定是可以的。

但是,通过创建嵌套的 for 循环,可以自动测试每个因素。这应该会减少将这个框架付诸实践的摩擦。只需确保将结果和基准度量保存到每个设计级别的列表或字典中。当所有的场景都完成后,你的实验将呈现一个模型的每个排列是如何执行的清晰画面。

总的来说,通过遵循实验设计框架,确定模型结果是否朝着正确的方向发展变得更加容易。不要将模型设计和评估的大部分精力集中在算法上,要确保在方法上花费一些时间来达到最终的模型状态。很容易认为一个小的改变不会影响性能或者只会略微改变结果。实验设计提供了一种方法,以确保这些结论植根于科学和严谨。实验设计,更确切地说是析因设计,是添加到您的数据科学家工具箱中的一个很好的工具。

来源

[1]https://www . jmp . com/en _ us/articles/what-is-experimental-design . html

不要掩盖数据文化

原文:https://towardsdatascience.com/dont-gloss-over-data-culture-1a05b48dc2de

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

莎伦·麦卡琴在 Unsplash 上的照片

早在 2011 年,麻省理工学院斯隆管理评论的一篇文章与 IBM 合作,调查了企业读者群,以了解企业对商业智能数据分析的当前和期望状态(BI & A) (LaValle,Lesser,Shockley,Hopkins,& Kruschwitz,2011)。十分之六的受访者表示,他们的组织拥有的数据超过了其所知的可操作性;除此之外,“管理和文化”障碍是使 BI &更好地为企业服务的最常见障碍(LaValle 等人,2011 年,第 23 页)。

十多年后,企业在采用和使用 BI &A;方面取得了长足的进步,然而,2011 年存在的许多相同差距今天仍然很突出。看一看围绕数据分析的在线内容。其中大部分涉及数据素养和数据文化。然而,我们仍然没有达到目标。

问题是,组织中的“文化”仍然被认为是一个单数概念,而不是复数。这是许多现有 BI&A 成熟度评估中的一个标准,需要检查或掩盖。因为文化是成功 BI&A 实现的主要驱动力,所以必须对包括其子文化在内的组织数据文化进行更可靠的评估。只考虑组织的主导文化及其实施驱动因素的 BI&A 解决方案肯定会满足一些人的需求,而让其他人不参与、得不到充分服务并感到失望。

拥抱亚文化

组织不是铁板一块的实体。人是不同的,团队以自己独特的方式工作。这些团队在公司数据方面有自己的优先级、挑战和成功定义。反过来,成功的 BI&A 实施和向数据驱动文化的转移可能对不同的组织部门具有多重意义。使这种情况变得更加复杂的是,人们倾向于认为,在没有检查当前文化和对这种实现的准备的情况下,可以获得和实现特定的软件包或解决方案。

全速采用分析技术并相信该技术可以治愈所有疾病,这可能很有诱惑力。有很多工具为 BI&A 做了很多好事。但是,这些不能被视为整个组织的灵丹妙药。每个解决方案都有自己的优点和缺点,对于组织来说,实现最适合所有用户的解决方案是非常重要的。这意味着拥抱数据亚文化,并让它们推动采用——而不是让采用粗暴地对待利益相关者。

忽视后果自负

掩盖组织中的各种数据亚文化会导致缺乏组织中所有业务部门的适当认同和/或适当的管理层支持的采用周期。如果没有这种认同,不一致可能以一种或多种方式出现:文化、切入点、拨款措施或历史(Jenks,2012)。

在文化错位的情况下,利益相关者根本不理解或接受彼此的使命。正如我们将在后面探讨的,这种不一致可能取决于组织内的各种职业文化。在切入点不一致的情况下,解决方案是由一个或多个变革推动者引入的,他们似乎是为了自己的狭隘利益而推动解决方案,而没有给整个组织带来任何明显的好处。在拨款措施不一致的情况下,新的解决方案没有适当地整合到组织的现有实践中,而只是浮在其上,没有提供真正的价值。在历史错位的情况下,组织可能背负着重复失败实现的记忆,并且可以理解地怀疑最新的实现。在任何一种情况下,实现都会受到阻碍,并且没有一个原因与技术直接相关。

前进的道路

在成功的组织中,围绕 BI&A 能力的软技能和无形资产越来越受到关注。学术界和工业界的新发展正在塑造对话,并强调数据素养和文化的重要性。在撰写本文时,我自己的研究已经产生了一个评估框架,将这些数据亚文化与组织范围内的分析成熟度联系起来。虽然这项研究是突发的,但早期结果表明,特定的亚文化确实对整体成熟和成功有影响。就像员工一样,组织内部的数据处理方式也各不相同。现在是我们把它从障碍转变为资产的时候了。

参考文献

詹克斯,B. (2012)。在数据仓库/商业智能环境中组织对变革的抵制。 (D.B.A .)安阿伯金门大学。从https://proxy.cecybrary.com/login?取回 URL = https://search . proquest . com/docview/1197494174?accountid=144789 ProQuest 学位论文&学位论文全球数据库。(3533517)

LaValle,s .,Lesser,e .,Shockley,r .,Hopkins,M. S .,& Kruschwitz,N. (2011)。大数据、分析和从洞察到价值的路径。麻省理工学院斯隆管理评论,52 (2),21–31。

不要只是拟合数据,还要获得洞察力

原文:https://towardsdatascience.com/dont-just-fit-data-gain-insights-too-1dba73d3cf8e

一个轻量级的 Python 包可以让您对回归问题有更多的了解

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:作者创作

为什么需要洞察力?

首先要做的事。为什么线性回归很重要?

线性回归是一项基本技术,它深深植根于久经考验的统计学习和推理理论,并为现代数据科学管道中使用的所有基于回归的算法提供支持。此外,对于大多数数据分析工作,除了处理图像、音频或自然语言等高维数据的问题,这种回归技术仍然是最广泛使用的工具。

它们易于实现,更重要的是,易于遵循和解释。而且,可交代性越来越重要

https://blog.fiddler.ai/2021/10/the-key-role-of-explainable-ai-in-the-next-decade/

然而,一个线性回归模型的成功还取决于一些关于基础数据性质的基本假设。验证这些假设是否“合理地”得到满足是多么重要,怎么强调都不为过。这种检查是确保线性回归模型质量的唯一保证。

我在之前的一篇文章中探讨了这些问题,

对于我们所有使用 Python 作为数据科学语言的人来说,机器学习的首选包是 Scikit-learn。尽管 Scikit-learn 的估计器经过了高度优化和精心设计,但它们并没有为回归任务提供许多统计见解或检查。例如,他们可以给你 R 分数和回归系数,除此之外别无其他。

但是,如果您想从同一个评估者那里获得以下见解/图表,该怎么办呢?

  • 残差与预测变量图
  • 拟合与残差图
  • 归一化残差的直方图
  • 归一化残差的 Q-Q 图
  • 残差的夏皮罗-维尔克正态性检验
  • 残差的库克距离图
  • 预测特征的方差膨胀因子(VIF)

这些图中的每一个都很关键,可以告诉您回归问题(即输入数据)是否质量良好或者是否满足建模假设。本质上,问题必须满足这些,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:作者创作,摘自本文文章(作者拥有版权)

在本文中,我们将探索一个简单、轻量级的 Python 包**mlr**,展示如何用最少的代码深入了解回归问题。

安装和基本安装

基本 pip 安装。

pip install mlr

我们可以为演示生成一些随机数据。

num_samples=40
num_dim = 5
X = 10*np.random.random(size=(num_samples,num_dim))
coeff = np.array([2,-3.5,1.2,4.1,-2.5])
y = np.dot(coeff,X.T)+10*np.random.randn(num_samples)

特征向量有 5 个维度。请注意添加到数据中的随机噪声。它看起来怎么样?我们绘制了响应变量 w.r.t .特征向量的每个维度,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:作者创作

此时,我们可以使用mlr库创建一个模型实例。

model = mlr()

这是什么?我们可以探测:-)

model>> I am a Linear Regression model!

下一步是接收数据。还不适合,但只是为了消化。

model.ingest_data(X,y)

在这一点上,数据已经被摄取,但不适合。

model.is_ingested>> Truemodel.is_fitted>> False

相关矩阵立即可用于可视化。即使在拟合回归模型之前,你也必须检查多重共线性,不是吗

model.corrplot()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:作者创作

所有相关数据和完整的协方差矩阵也是可用的。我们不会为了节省空间而打印它们,

model.corrcoef()
model.covar()

然后,合身就好。

model.fit()

一堆东西任你处置

一旦安装完毕,就会发生大量的内部动作,模型对象就有了大量的度量和可视化,供您深入了解。

简单 R 分数(以及所有相关指标)

我们可以打印简单的 R 系数,

model.r_squared()
>> 0.8023008559130889model.adj_r_squared()
>> 0.7732274523708961

或者,我们可以一次性将它们全部打印出来!

model.print_metrics()
>>
sse:     3888.1185
sst:     19666.8452
mse:     97.2030
r^2:     0.8023
adj_r^2: 0.7732
AIC:     308.5871
BIC:     318.7204

为了简洁起见,我不会讨论所有这些指标,但是这些是线性回归问题的基础,你应该已经熟悉了:-)

进行总体显著性的 f 检验

它返回测试的 F 统计量和 p 值。如果 p 值很小,您可以拒绝所有回归系数为零的零假设。这意味着较小的 p 值(通常< 0.01)表明总体回归具有统计学意义。

model.ftest()>> (27.59569772244756, 4.630496783262639e-11)

t 检验统计和系数的标准误差

标准误差和相应的 t 检验为我们提供了每个回归系数的 p 值,它告诉我们特定的系数是否具有统计显著性(基于给定的数据)。

同样,所有这些,一个函数调用,

print("P-values:",model.pvalues())
print("t-test values:",model.tvalues())
print("Standard errors:",model.std_err())

我们得到,

P-values: [1.37491834e-01 8.39253557e-06 1.62863484e-05 1.64865547e-03
 1.23943729e-06 1.97055499e-02]
t-test values: [-1.5210582   5.23964721 -5.017859    3.41906173  5.87822303 -2.44746809]
Standard errors: [7.35200748 0.65528743 0.58944149 0.58706879 0.55966142 0.7806859 ]

每个特征的置信区间?

一行代码,

model.conf_int()
>>
array([[-26.12390808,   3.75824557],
       [  2.10177067,   4.76517923],
       [ -4.15562353,  -1.75984506],
       [  0.81415711,   3.20029178],
       [  2.15244579,   4.42718347],
       [ -3.49724847,  -0.3241592 ]])

残差的可视化分析

残差分析对于检查线性回归模型的假设是至关重要的。mlr通过为残差提供直观的可视化分析方法,帮助您轻松检查这些假设。

拟合与残差图

使用此图检查恒定方差和不相关特征(独立性)的假设。

model.fitted_vs_residual()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:作者创作

拟合与特征图

用该图检查线性假设,

model.fitted_vs_features()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:作者创作

标准化残差的直方图和 Q-Q 图

使用这些图检查误差项的正态假设,

**model**.histogram_resid()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:作者创作

**model**.qqplot_resid()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:作者创作

特征选择

简化 API 的一个好处是,我们可以用它来完成复杂的任务,只需要几行代码。例如,我们可能希望使用mlr来检查回归指标是如何变化的,因为我们开始时只有一个解释变量,然后逐渐增加更多的。这是特征选择方法的常见任务。

为此,假设我们已经使用fit_dataframe方法将数据放入 Pandas 数据框架中。

for i in range(1,6):
    m = mlr() # Model instance
    # List of explanatory variables
    X = ['X'+str(j) for j in range(i)]
    # Fitting the dataframe by passing on the list
    m.fit_dataframe(X=X,y='y',dataframe=df) 
    print("\nRegression model built with feature vector", X)
    print("Metrics are as follows...")
    print("-"*80)
    m.print_metrics()

打印出类似下面的内容,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:作者创作

我们还可以绘制出随着变量的增加,AIC 和 BIC 的价值逐渐减少的曲线。

从上面的剧情中你能得到什么样的感悟?也许,如果您的模型训练资源有限,您可能会停止使用三个特性来构建模型。

向您的客户解释,为什么您只选择了这三项功能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:作者创作

此处提供了方法的完整列表。

摘要

仅仅拟合数据和预测是不够的。为了进行严格的回归分析,需要进行许多统计显著性检验和残差检验。拥有一个轻量级的库有助于用最少的代码量实现这一点。这就是我们在本文中演示的内容。

在这里阅读本库(mlr)的完整文档: 文档

喜欢这篇文章吗?成为 中等会员 继续 无限制学习 。如果您使用下面的链接, ,我将收取您的一部分会员费,而无需您支付额外费用

https://medium.com/@tirthajyoti/membership

不要让通货膨胀和经济衰退毁了你的数据策略

原文:https://towardsdatascience.com/dont-let-inflation-and-recession-ruin-your-data-strategy-a7e744ca0240

宏观经济学如何帮助数据领导者制定稳健且有远见的数据战略

作为一个数据领导者,你到底为什么要关心宏观经济?

你曾经和高层领导在会议室里讨论过通货膨胀或经济衰退吗?以及如何建立一个特别工作组来解决这个问题?我有。这让我很不舒服。每个人似乎都有自己的看法,但我不明白他们在谈论什么。我想知道他们是如何学习经济学的。这不是你在学校学的东西,对吗?至少不是以一种适用于你工作的方式。这也不是你每天在工作中都会遇到的事情。每隔一年,当一些不寻常的事情发生时,你就会接触到它。那么,所有这些高级领导人似乎都很轻松地做出预测和决策,这怎么可能呢?作为一名年轻的经理,看到自己缺乏经验暴露出来,感觉很糟糕。经济学是曾经让我感到难为情的话题之一。当经济衰退来袭时,更有经验和智慧的高层领导似乎总是更清楚正在发生什么,接下来会发生什么,以及该做什么。

作为一名年轻的经理,看到自己缺乏经验暴露出来,感觉很糟糕。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

经济风暴数据——人工智能生成的艺术与 DALL。E

山村里的长辈可以通过云的形状和天空的颜色告诉你是要下雨还是要下雪。他们知道如何探测和准备即将到来的雷暴。当然,他们不能阻止风暴的发生,也不能防止所有的损害,但他们通常比年轻人准备得更充分。

要变老变聪明,你必须先变年轻变笨

然而,我有一个好消息:你不必永远在你的高层面前显得愚蠢。如果你能从别人的经验中学习,你会变得更聪明,更早。在商界,就像在山区一样,你可以学会识别经济衰退或恶性通货膨胀的早期迹象以及对你的业务可能产生的后果,这样你就可以更好地带领你的团队度过难关。

什么是宏观经济学?

根据维基百科:

宏观经济学 经济学的一个分支 把一个 经济 作为一个整体来处理表现、结构、行为和决策。比如,利用利率、税收和政府支出来调节经济的增长和稳定。

换句话说,宏观经济学是对你的企业所处的全球环境的研究。

宏观经济学大部分时间“看不见”的原因。

做生意的时候宏观经济学无处不在。但是因为它一直在这里,而且通常移动很慢,所以你甚至不会注意到它。宏观经济学对于经理来说就像水对于鱼一样。

让我用戴维·福斯特·华莱士的一个故事来说明我的观点:

有两条小鱼在游泳,它们碰巧遇到一条游向相反方向的老鱼,老鱼朝它们点点头说:“早上好,孩子们。水怎么样?”两条小鱼游了一会儿,最后其中一条看着另一条,问道:“水到底是什么?”

鱼缸里的小鱼不明白什么是水,因为它从未遇到过其他任何东西。它甚至不能理解水的存在。

同理,一个有五年经验的年轻经理,从来没有经历过衰退,或者相反,只知道衰退。

你没看到不代表不会改变

下图说明,你可能有整整 10 年的工作经验,但仍从未遇到过像目前这样的能源价格上涨。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

[天然气价格由维基百科](http://by Wikipedia CC BY-SA 3.0) CC BY-SA 3.0

另一个例子是看更广泛的经济。1926 年,经济学家尼古拉·康德拉蒂耶夫提出资本主义经济体系存在 40 年周期的假设。在 20 年的上升阶段,公司投入大量资金来对抗竞争,价格也随之上涨。达到峰值后,由于供应过剩和需求放缓,经济会放缓 20 年。此后,这一理论受到了挑战并得到了丰富。但我们仍然确信,经济不是一个水平不变的海洋,而是一个潮汐周期非常缓慢的海洋。这一潮流不断改变着商业环境。在周期的某一点,事情开始加速,让那些没有准备好的人大吃一惊。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

康德拉季耶夫波由维基百科 CC BY-SA 3.0

我并不是说你应该变得偏执,对一切不可避免会出错的事情麻木不仁。但是了解宏观经济学会给你一个直觉,让你知道明天事情会如何变化,并挑战你的假设。

不懂经济学会让你付出什么代价

如果你不了解宏观经济学,这里有两个在你领导数据函数期间可能出错的例子:

  • 一场重大的、意料之外的通胀浪潮可能会突然出现。突然,你发现以客户为中心的定价成了首席执行官的头等大事。你需要几周时间来了解哪些类别的通货膨胀将受到最严重的打击,以及如何重新调整数据科学团队来解决这个问题。当您的团队开始运作时,您的竞争对手已经重新定位了他们的整个目录定价。他们行动更快,并大胆宣布将保护旗舰产品的价格。他们赢得了对客户价格认知的竞争,同时保护了他们的利润。在你反应过来的几周内,你损失了数百万的息税折旧及摊销前利润。
  • 一场突如其来的疫情引发了严重的供应短缺。曾经运转良好的供应链开始崩溃。您刚刚花了两年时间构建了一个最先进的需求预测算法,将准确性提高了 2 个百分点,这是一个值得称赞的成功。问题是你的算法被微调以在平稳的巡航速度条件下工作。现在销售曲线快速下降,算法预测销售会完全崩溃,你必须在它搞乱你的整个供应链之前拔掉它。

在 2019 年,那些世界末日的场景会让你笑得不敢相信。现在你知道这真的发生了。人们很容易将它们视为无人能预测的不可抗力。真的吗?有没有一种方法可以让您的数据策略更具弹性,以便为最坏的情况做好准备?有没有办法比你的竞争对手更快更好地应对危机?我相信宏观经济学技能会给你这种优势,我会举例说明如何做到这一点。

宏观经济学知识给你一个直升机视角,让你看得更远

理解宏观经济学将帮助你在空间和时间上看得更远。

  • 在太空中,因为你会明白世界上其他地区的经济状况会有很大的差异。在你的欧洲总部,通货膨胀可能不是一个问题,但在业务运营的新兴国家,通货膨胀却是一个反复出现的危险。
  • 及时,因为即使你现在正在经历增长,如果你的核心客户群的购买力明天被通货膨胀摧毁,你很可能会失去你的业务。

这一增强的愿景将使您能够:

  • 当经济风暴来袭时,做一个有战略头脑的冷静领导者,
  • 在董事会面前看起来更聪明,这总是感觉很好,说实话。

最终,我相信宏观经济学素养可以成就或毁灭一个首席数据官。根据《HBR》的一篇文章,CDO 的平均任期只有两年半:“为什么首席数据官的任期这么短?”[1].这意味着你只有一次机会。如果你最初的战略仅仅一年后就因为经济环境的变化而变得无关紧要,这将严重降低你成功的机会。

CDO 的平均任期只有两年半。这意味着你只有一次机会。

经济条件决定您的数据策略的例子

在接下来的部分中,我将给出具体的例子,说明如何在数据策略中考虑宏观经济因素,如通货膨胀和 GDP。我将说明它会如何影响:

  • 您的用例优先级。
  • 您的数据团队的组织。

通货膨胀的影响

通货膨胀是价格水平的普遍上涨。大多数发达经济体的通胀率稳定在 2%以下。它允许最低限度的失业和通货膨胀的不利影响。然而,新兴经济体更容易出现恶性通货膨胀,有时会带来灾难性的后果。在最严重的危机中,人们的工资每天会被支付很多次,因为早上赚的 100 美元的国家货币到当天晚上可能会贬值 20%。人们在午休时开始购买食品杂货,因为如果他们等到下午 5 点,价格会变得更贵。即使在发达经济体,通胀也可能像 2022 年那样失控,成为首席执行官们最关心的问题。

用例优先级

在通货膨胀时期,你的成本可能会急剧增加,并在几个月内将你的利润降至零。这意味着成本控制用例以及定价用例成为优先事项。

  • 在成本控制用例类别中,能源价格通常是上涨最快的。如果你能够进行能效分析,你就知道在哪里采取行动来实现节约。
  • 在定价用例类别中,如果您可以利用高级分析,您可以战略性地确定价格增长目标。你将冻结需求价格弹性最高的产品的价格上涨。这样你就能在低价竞争中击败竞争对手。你将最大限度地提高不太敏感产品的价格,因为你比竞争对手更便宜,从而赢得利润。

数据团队组织

如果你在一家跨国公司工作,对于你在伦敦总部的数据科学家来说,通货膨胀可能是一个非常抽象的概念,而对于你在伊斯坦布尔办公室的数据科学家来说,这可能是完全正常的事情。土耳其业务部门可能没有资源来开发端到端价格弹性算法,最好在总部为整个集团开发。然而,你可以让你的土耳其数据科学家微调通胀经济的算法。

国内生产总值和增长的影响

用例优先级

当经济衰退来袭时,每个客户群都会受到不同的影响。例如,越朴素的家庭失去的购买力越多。这扭曲了你的客户细分。这需要你与市场营销密切合作,量化需求的结构性变化,并定义可操作的杠杆。

然后,你的公司变得厌恶风险,并试图控制成本,以度过营业额崩溃。你将不得不在成本效益用例上与财务部门合作。

数据团队组织

当经济衰退出现时,你的数据预算可能会缩减,或者至少增长会更慢。你将比以往任何时候都更需要向你的首席财务官证明你的价值。衡量价值创造需要花费数月时间来建立官僚机构和能力。因此,即使今天很容易获得预算,开始跟踪价值创造也可能是值得的,这样当糟糕的日子到来时你就可以做好准备。

如何开始

  • 问经济问题:不要只依赖公司战略幻灯片,你可以通过研究对潜在经济假设的敏感性,使你的战略更稳健、更有远见。例如,问你的营销部门:“什么会出错?”,“当经济衰退来临时,我们的客户需求会发生什么变化”?或者问你的财务部门:“在恶性通货膨胀的情况下,成本结构会以多快的速度和多深的程度演变?”。
  • **学习基础知识:**了解供给、需求、通货膨胀和 GDP。在我看来,如果你不能上完整的课程,学习经济学家的历史是最令人信服的方法。早期的经济学家从非常简单的模型开始,经过几十年的研究,这些模型被挑战、扩充或替换。观察他们的思维过程是令人着迷和有启发性的。

如果你不知道从哪里开始,这里有一些我推荐的资源。我没有深入研究所有这些内容,但内容似乎经过改编,并以一种可操作的方式呈现出来(我没有任何从属关系):

  • 《宏观经济学简明指南:经理、高管和学生需要知道的东西》,作者是大卫·A·莫斯。虽然我没有读它,但它在亚马逊上被评为 4.6 星,这对于一本经济学书来说是很了不起的。它似乎是为管理者设计的。一个好的简洁的选择,比大的教科书便宜。
  • Coursera上的商业管理宏观经济学 MOOC。评论是恒星与 4.9 星评级。它似乎提供了坚实的理论基础以及商业规划和投资决策的应用。因为它代表了 14 小时的学习。
  • 经济学,教科书作者大卫·贝格吉安路易吉·韦尔纳斯卡鲁迪格·多恩布什斯坦利·菲舍尔。这是我为宏观经济学课学习的书。它内容全面,既有深入的理论探讨,又有大量图表和历史插图,读起来引人入胜。它非常丰富和详细,所以需要一定的努力,但你可以浏览一下。它也涵盖了微观经济学。

结论

宏观经济学不是你作为数据领导者需要的第一技能。然而,基本的宏观经济学知识将帮助你在空间和时间上看得更远。这对有效的领导至关重要。了解通货膨胀和 GDP 增长将使您能够构建更加优化和稳健的数据策略。你不会被经济危机压垮,而是冷静地领导。

不要等到老了才明白。历史会重演。

特别感谢我的编辑本·胡伯尔曼,让这篇文章对社区来说更具相关性和可操作性。

[1]达文波特、比恩和金、为什么首席数据官的任期如此之短? (2021 年),HBR

不要让数据科学家做 Scrum

原文:https://towardsdatascience.com/dont-make-data-scientists-do-scrum-de87bc921a6b

来自数据科学家和认证 Scrum 大师的想法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by 傅甬 华 on Unsplash

Scrum 指南*::*Scrum 是一个轻量级框架,通过对复杂问题的适应性解决方案,帮助个人、团队和组织产生价值。”

Scrum 已经超级流行很多年了。我对它在营销上的成功感到惊讶。这就像软件开发管理框架世界的卡戴珊。我对 Scrum 也有同样的感觉,因为《敏捷宣言》的作者之一在他的文章中写道:“一旦宣言流行起来,敏捷这个词就变成了一块磁铁,吸引着任何有观点、有时间、有产品要卖的人。”

对我来说,Scrum 看起来很重过程,这违背了敏捷宣言的第一个价值观——个人和交互重于过程和工具。但也许我对 Scrum 了解不够?所以我决定学习更多关于 Scrum 的知识,甚至成为一名认证的 Scrum 大师。现在我更明白为什么我不喜欢它,为什么它对数据科学家来说不理想。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1。Scrum 是不可变的

Scrum 指南:“Scrum 框架,正如这里所概述的,是不可变的。虽然只实现 Scrum 的一部分是可能的,但结果不是 Scrum。Scrum 只完整地存在,并且作为其他技术、方法和实践的容器运行良好。

“框架的每个元素都服务于一个特定的目的,这个目的对于 Scrum 实现的整体价值和结果是必不可少的。改变 Scrum 的核心设计或想法,省略元素,或者不遵循 Scrum 的规则,掩盖了问题,限制了 Scrum 的好处,甚至可能使它变得毫无用处。”

Scrum 是一个框架,由一个 Scrum Master、一个产品所有者和一个或多个开发人员组成的小团队组成。Scrum 被组织成 Sprint,有四个与 Sprint 相关的事件:Sprint 规划、每日 Scrum、Sprint 回顾和 Sprint 回顾。根据 Scrum 指南,Scrum 是不可变的。敏捷框架怎么可能一点都不敏捷?许多人说他们喜欢只使用吉拉门票和每日站立,根据 Scrum 指南,这不是 Scrum。

2。数据科学家并不致力于单一的“产品”,我们的工作往往不是一个增量

Scrum 指南:“Scrum 的核心是冲刺,这是一个月或更短的时间,在此期间,一个完成的、可用的、有价值的产品增量被创造出来。这适用于每一次冲刺。Sprint 的目的是产生一个有价值和有用的工作产品增量。”

数据科学家通常只从事各种项目,每个项目都与不同的利益相关者相关联。同一个团队的数据科学家通常不从事相同的“产品”工作,而是有着共同的“产品目标”。数据科学家所做的工作通常不是增量,也不是为单一的“产品目标”或“冲刺目标”而设计的。

3。数据科学家并不总是需要产品负责人

Scrum 指南 : “产品负责人代表了产品 Backlog 中众多利益相关者的需求。产品负责人代表 Scrum 团队的利益相关者,这包括在产品 Backlog 中代表他们想要的需求。

依靠产品负责人代表 Scrum 团队的利益相关者进行数据科学研究是一个糟糕的想法。正如我前面提到的,数据科学家经常与许多不同的利益相关者和不同的项目合作。仅仅从产品负责人那里了解背景是不够的,没有动力,也没有必要。对于数据科学家来说,更有效的方法是直接与利益相关者互动,了解问题的背景,深入与利益相关者的讨论,并自己制定计划。

同样,在 Scrum 中,产品负责人的责任是将复杂的问题分解成待办事项。这对数据科学家也不起作用。数据科学家做的大部分工作是研究,而不是产品开发。给定问题和问题的背景,我们设计我们自己的项目路线图和分析框架。因为所需的任务对任何人来说都还不清楚,从数据科学家那里拿走这些任务是不合理的,他们的工作是让他们清楚。

产品负责人为项目设定优先级也是不合理的。其他利益相关者经常给我们项目的时间表。由于这些需求来自不同的来源,数据科学家需要能够根据所有不同项目的时间表和紧迫性来确定自己时间的优先级。如果需要,数据科学经理,而不是产品所有者,应该能够提供帮助。

4。Scrum 夺走了所有权

Srum.org:“开发人员何时成为 Sprint Backlog 项目的唯一所有者?

从来没有。所有 Sprint Backlog 项目都由 Scrum 团队的开发人员“拥有”。整个 Scrum 团队负责在每个 Sprint 中创建有价值的、有用的增量,并且为 Sprint 选择的产品 Backlog 项目集由开发人员集体所有。没有一个单独的开发人员可以声称对一个项目的所有权,因为这将阻碍沟通和协作。随着学习的深入,开发人员会在整个 Sprint 过程中更新 Sprint Backlog。"

数据科学家拥有自己的项目是相当常见的。拥有这种主人翁意识从本质上激励数据科学家在项目中做得更好。坦率地说,数据科学家可能甚至不想拥有其他数据科学家的项目。例如,一个从事新闻提要工作的数据科学家不应该觉得他/她应该拥有另一个数据科学家正在从事的广告项目。所涉及的知识和专业技能不会在人与人之间均匀地转移,部分原因是每个人都在探索特定主题的旅程中。即使两个数据科学家在同一个项目中工作,在我看来,每个人仍然应该拥有项目的不同部分。

5。“完成”的定义因项目而异

Scrum 指南 :要求开发者符合 Done 的定义。如果有多个 Scrum 团队一起开发一个产品,他们必须相互定义并遵守相同的 Done 定义。

理解和应用 Scrum 框架允许团队和组织在 30 天或更短的时间内迭代地和增量地交付“完成”工作的可发布软件的有价值的产品。

不同的项目差别很大,不可能对我们所有的项目使用相同的 Done 定义。

6。冲刺复习不起作用

Scrum 指南 : “冲刺评审的目的是检验冲刺的成果,确定未来的改编。Scrum 团队向关键利益相关者展示他们的工作成果,并讨论产品目标的进展。

一个数据科学家团队可能有许多不同的关键利益相关者。我们邀请哪些利益相关者参加冲刺评审?对于数据科学家来说,在每周的项目会议上直接向各种项目干系人展示结果通常更有效。

更多想法

如果 Scrum 不起作用,那么什么会为数据科学家团队工作呢?我喜欢一个朋友的建议,忽略 Scrum 的形式,想想 Scrum 的哪些部分在数据科学而不是软件开发的背景下是有价值的。我确实认为人渣的三大支柱(透明、检查、适应)有道理。我认为所有这三个价值可以简单地通过与涉众的每周项目会议、项目演示的每周团队会议以及良好的文档来实现。具体来说:

1。如何让人们对他们正在做的事情有一个共同的理解?

与利益相关者的每周项目会议项目演示的每周团队会议让每个人都有机会公开他们在做什么、他们的进展和他们的计划。我想了解其他人项目中的思维过程、研究框架和详细的学习内容,我不在乎人们每天/每小时都在做什么。这就是为什么我更喜欢项目演示,而不是毫无意义地浏览每一张票/任务,而不去了解项目的背景和细节。对于指导和学习新的技术技能,深入项目演示会议或结对编程会议的技术细节也会有所帮助。

文档也有助于提高透明度。包含所有会议记录、决策、分析、结果和其他内容的共享项目文档通常很有价值。找不到所有的文件?使用 wiki 页面列出所有项目文档。对于喜欢吉拉门票的团队来说,吉拉可以是一个很好的记录工具,这样就可以记录正在做的事情。使用什么文档工具取决于团队自己的偏好。

2。如何就成功的要素达成共识?

由于数据科学家项目通常没有“完成”的明确定义,我们如何检查和衡量成功?与涉众的每周项目会议、项目演示的每周团队会议和文档允许涉众和团队成员检查、深入研究并给出有意义的反馈。为了在项目上取得成功,可能有两种情况:a)涉众或数据科学家自己对项目有一个清晰的愿景和期望。在这种情况下,当项目符合利益相关者的期望时,数据科学家就完成了项目。b)通常情况下,利益相关者或数据科学家只有一个模糊的初始想法,项目期望是一个正在进行的对话。在这种情况下,与利益相关者会面和沟通以制定潜在的计划和后续步骤是非常重要的。每周都会有新的项目步骤,当利益相关者和数据科学家觉得可以与他人分享见解时,项目就可以完成了。

3。什么时候决定一种方法不起作用,需要一种新的方法?

就实际工作而言,数据科学家在会议和文档审查中收到上下文和反馈,这有助于他们改进甚至在需要时转向新的分析框架。鉴于数据科学工作的研究性质,反复试验是不可避免的。因此,尝试一些东西,然后发现它可能不工作也没关系。

就结构和管理方法而言,Scrum 呼吁召开一次 Sprint 回顾会议,讨论什么可行,什么不可行。我认为这是一个很好的想法,但它可以集成到其他方法中。每个人都应该感到鼓舞,在空闲时间和会议上表达他们的担忧。我认为在每周例会和与经理一对一的会议中给人们一些时间和空间是一个很好的做法。如果关注是有价值的,并且需要单独的空间来讨论,我们可以安排一个会议来讨论这个关注。

如果你是数据科学家或数据科学经理,我很好奇你的团队是如何管理的,以及你对 Scrum 的体验。请让我知道。很想听听大家的经验和建议。

参考资料:

  • Scrum.org
  • Scrumguides.org
  • https://pragdave.me/blog/2014/03/04/time-to-kill-agile.html
  • 【http://agilemanifesto.org/

作者索菲亚·杨 2022 年 1 月 4 日

MediumTwitterLinkedinYouTube :)上关注我

不要以“Select”语句开始 SQL 查询

原文:https://towardsdatascience.com/dont-start-your-sql-queries-with-select-clause-d30fa1b701f6

遵循这种正确的方法来编写 SQL 查询

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:Unsplash

问题是

大多数开发人员开始用’ SELECT ‘子句编写他们的 SQL 查询,然后编写’ FROM ‘,’ WHERE ‘,’ HAVING’…诸如此类。但这不是编写 SQL 查询的“正确”方式,因为这很容易出现语法错误,尤其是如果您是 SQL 初学者。

解决方案

“理想的”查询编写顺序应该与 SQL executor 执行查询的方式一致。这将确保您不会犯任何语法错误,并编写高效的 SQL 查询。您将知道如何在执行连接之前过滤数据,何时使用“HAVING”或“WHERE”子句等等。

在这篇博文中,我们将探讨编写 SQL 查询的“理想”方式,这将帮助您成为一名高效的 SQL 开发人员。

我们将使用客户和订单表(如下)来查找来自美国/英国的总消费超过 300 美元的前 2 名客户。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

客户表(图片由作者提供)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

订单表(作者图片)

让我们深入探讨编写 SQL 查询的正确方法。

1.总是以 FROM/JOIN 开头

直观地说,第一步是使用 FROM 子句读取表并执行 JOIN(如果需要的话)。因此,您应该始终以“FROM”/“JOIN”语句开始查询。

 FROM Customers
INNER JOIN Orders
ON Customers.customer_id = Orders.customer_id

甚至在执行连接之前,我们也可以从输入表中过滤行。我们可以通过在连接的“ON”子句后添加“AND”子句来做到这一点。

-- Filter happens before Join

FROM Customers
INNER JOIN Orders
ON Customers.customer_id = Orders.customer_id
AND country in ('USA','UK')

2.那搬到哪里去

执行顺序中的第二个子句是 WHERE 子句。它用于在应用连接后过滤数据表。

WHERE 子句非常有助于减少行数,尤其是当我们处理具有数百万行的大型数据集时。

FROM Customers
INNER JOIN Orders
ON Customers.customer_id = Orders.customer_id
WHERE country in ('USA','UK')

3.然后使用分组依据

Group By 子句应写在 Where 子句之后。它用于根据选定的一列或多列对行进行分组。

在下面的查询中,我们根据客户 id 对行进行分组。分组后,每个客户 id 在输出中都有一行。我们一般使用聚合(sum,min,max 等。)当我们把数据分组的时候。在本例中,我们将找到 Orders 表中 amount 列的总和。

FROM Customers
INNER JOIN Orders
ON Customers.customer_id = Orders.customer_id
WHERE country in ('USA','UK')
GROUP BY Customers.customer_id

4.在分组依据之后

HAVING 子句在 group by 之后执行,它用于筛选 GROUP BY 操作中生成的聚合行。

在我们的例子中,我们将过滤每个客户花费的金额总和大于 300。

FROM Customers
INNER JOIN Orders
ON Customers.customer_id = Orders.customer_id
WHERE country in ('USA','UK')
GROUP BY Customers.customer_id
HAVING sum(amount) >300

WHERE 子句在 GROUP BY 之前执行,而 HAVING 子句在 GROUP BY 之后执行。因此,WHERE 子句不能筛选聚合数据。

5.然后编写 SELECT 子句

我们希望在输出中显示的列是使用 SELECT 子句选择的。

如果我们使用 GROUP BY 子句对数据进行分组,我们需要使用 select 语句选择分组后的列。

在我们的示例中,我们将选择客户 id 和 sum(金额)来显示对应于每个客户的支出。

select Customers.customer_id, sum(amount) as total_amount
FROM Customers
INNER JOIN Orders
ON Customers.customer_id = Orders.customer_id
WHERE country in ('USA','UK')
GROUP BY Customers.customer_id
HAVING sum(amount) >300

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输出(图片由作者提供)

6.在 SELECT 子句后使用 ORDER BY

选择列之后,下一步是提供我们希望输出行的顺序。

在我们的示例中,我们可以使用 ORDER BY 子句按照总支出的降序对行进行排序。

SELECT Customers.customer_id, sum(amount) as total_amount
FROM Customers
INNER JOIN Orders
ON Customers.customer_id = Orders.customer_id
WHERE country in ('USA','UK')
GROUP BY Customers.customer_id
HAVING sum(amount) >=300
ORDER BY total_amount desc

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输出(图片由作者提供)

7.最后写限制条款!

写入序列的最后一步是限制我们希望在输出中看到的行数。

在我们的例子中,我们可以将输出行的总数限制为 2。

SELECT Customers.customer_id, sum(amount) as total_amount
FROM Customers
INNER JOIN Orders
ON Customers.customer_id = Orders.customer_id
WHERE country in ('USA','UK')
GROUP BY Customers.customer_id
HAVING sum(amount) >=300
ORDER BY total_amount desc
LIMIT 2

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输出(图片由作者提供)

结论

我们看到了编写 SQL 查询的理想方式,它与 SQL 查询的执行方式一致。

如果您还没有这样做,我希望您将按照下面的顺序编写您的 SQL 查询。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

感谢您的阅读!

你可以在收件箱里看到我所有的帖子。 做到这里

如果你自己喜欢体验媒介,可以考虑通过 注册会员 来支持我和其他几千位作家。它每个月只需要 5 美元,它极大地支持了我们,作家,你可以在媒体上看到所有精彩的故事。

关注我 查看我在你的订阅中的数据科学帖子。

处理缺失值时不要走捷径

原文:https://towardsdatascience.com/dont-take-shortcuts-when-handling-missing-values-afb9312e73c3

如何确保缺失数据得到正确处理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

安 H 的照片:https://www . pexels . com/photo/pink-jigsaw-puzzle-piece-3482441/

在许多数据集中,缺失值是一个两难问题,但是许多用户渴望分配更少的时间来处理它们,以便他们可以将更多的精力放在建模上。

我写这篇文章之前,我最近遇到了许多将丢失数据视为事后想法的投资组合项目。人们对最佳算法和超参数进行了大量的考虑,但很少对选择的插补方法进行论证。

我明白,建立模型很有趣,但机器学习项目的成功取决于在任何建模之前如何处理数据。

在这里,我们深入探讨了许多人在处理缺失数据时往往会跳过的重要步骤,并展示了用户如何在自己的项目中实现这一点。

最重要的一步

那么,您必须执行什么步骤来确保正确处理丢失的数据呢?

答案很简单:探索性数据分析(EDA)!

不幸的是,在处理数据集中缺失的数据时,用户经常会忽略 EDA。相反,他们选择依靠他们最熟悉/最舒适的方法。

总的来说,不考虑“为什么”而盲目地执行技术是一个灾难。

毕竟,丢失数据的性质因情况而异。在处理缺失值时,适用于一个使用数据集中的方法可能不适用于另一个使用数据集中。

跳过 EDA 的用户更有可能使用基于错误假设的技术,这将影响数据质量。较差的数据质量自然会对后续建模阶段建立的任何机器学习模型产生负面影响(垃圾进,垃圾出)。

使用 EDA 处理缺失数据

EDA 是掌握数据集的关键特征及其缺失值的有效方法。通过掌握关于缺失数据的更多信息,您将能够就如何处理这些缺失值做出更明智的决策。

下一个问题是:当用户用 EDA 检查他们的数据时,到底应该寻找什么?

理想情况下,处理缺失数据的用户应回答以下问题:

  • 哪些要素包含缺失值?
  • 每个特征的记录中缺失数据的比例是多少?
  • 缺失数据是随机缺失(MAR)还是非随机缺失(MNAR)?
  • 具有缺失值的要素是否与其他要素相关?

处理缺失数据的方法

为了有效地解决缺少值的困境,用户将受益于对他们可用的各种技术的熟悉。了解几种方法及其优缺点将增加选择最佳方法的机会。

现在,我们简要概述一些处理缺失数据的基本和高级方法,并考虑它们的优点和局限性。

此外,我们将使用下面的模拟数据集演示如何在 Python 中使用这些方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码输出(由作者创建)

基本方法

  1. 省略有缺失数据的记录

有缺少值的数据点吗?

只需从数据集中删除它们!问题解决了!

这种方法的优点是它是处理缺失值的最简单的方法。就代码而言,您可以使用 Pandas 库用一行程序执行这个操作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码输出(由作者创建)

但是,这种方法会产生一个小得多的数据集,从而为模型提供较少的训练信息。此外,如果缺失值不是随机缺失(MNAR),这意味着移除这些数据点将不可避免地导致模型中的偏差。

这很少是处理缺失数据的首选方法。对于考虑这种方法的人来说,至少要确保有足够的数据,并且缺失值是随机缺失的。

2。省略丢失数据的特征

另一种选择是只移除特征而不是数据点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码输出(由作者创建)

同样,这需要移除数据,因此用户在考虑此方法之前,应首先验证要素中缺失数据的数量。

如果某个要素缺少太多数据,它很可能不会对模型有所贡献。对于这种情况,最好不要考虑这个特性。

3。用统计数据输入缺失数据

用户可以依靠简单的插补方法,用导出值替换缺失数据,而不是删除缺失值的记录或特征。对于数字要素,缺失数据可以用分布中值的平均值或中值来替换。对于分类特征,缺失数据可以由模式替换。

Python 中的插补可以用 Scikit Learn 包的simple imputr类来实现。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码输出(由作者创建)

虽然简单的插补听起来像是一种完美的方法,但它忽略了感兴趣的特征与任何其他特征之间可能存在的相关性,而其他特征可能不适合感兴趣的数据。因此,用基本方法替换缺失值可能会产生不能充分代表数据点的值分布。

处理缺失数据的高级方法

到目前为止,我们已经探索了一些解决缺失值的简单方法。然而,这些方法基于可能不适用于现实生活场景的假设。

对于较简单的方法无法解决的情况,值得考虑在输入缺失数据时考虑多个变量的更高级的方法。

  1. 用 K-最近邻进行输入

您可能熟悉 K-最近邻算法在分类中的应用,但是您知道吗,您还可以利用 K-最近邻算法来估算缺失值?

该过程需要在特征空间中绘制特征,以找到具有缺失值的记录的“最近邻”。然后,最近邻值的平均值用于估算缺失值。

您可以使用 Scikit-learn 模块的 KNNImputer 类来执行这项技术。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码输出(由作者创建)

KNN 算法的主要缺点是计算量大,容易出现异常值。

2。用链式方程进行多元插补(小鼠)

MICE 是一种独特的插补方法,没有得到足够的重视。可以说它值得单独写一篇文章。

简而言之,该方法需要为每个缺失值创建多个插补,而不是只有一个。该算法解决了统计不确定性,并使用户能够估算不同类型数据的值。

如果你想了解这个算法的来龙去脉,我找到了一篇很好的论文,在这里详细介绍了它。

可以使用 Scikit Learn 包的iterative imputr类在 Python 中实现 MICE 算法。注意这个类还是实验性的,所以你还需要导入enable_iterative_imputer来使用它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码输出(由作者创建)

MICE 算法是健壮的,但是它是在假设数据中的缺失值是随机缺失(MAR)的情况下运行的。

寻找最佳方法

因为没有一种放之四海而皆准的方法可以用来处理缺失值,所以理想的方法取决于所讨论的数据。

因此,任何关于丢失数据处理的决定都应始终基于明智的决定,这就是为什么在处理丢失数据之前进行 EDA 如此重要的原因。

通过识别感兴趣的数据集的特征,您可以识别最合适的方法,或者至少可以不考虑某些方法。

以下是一些示例,说明您可以从 EDA 中检测到什么,以及如何根据您的发现处理丢失的数据:

  1. 如果数据集的要素有超过 80%的记录缺失数据,最好是将该要素完全移除。
  2. 如果具有缺失值的要素与其他缺失值密切相关,则值得考虑使用高级插补技术,该技术使用来自其他要素的信息来推导值以替换缺失数据。
  3. 如果某个特性的值不是随机丢失的(MNAR ),请不要考虑像鼠标这样的方法。

关键要点

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Unsplash 上的 Prateek Katyal 拍摄

本文的主要观点应该是始终分配时间来执行 EDA,以便更好地理解您的数据。您的 EDA 结果将让您深入了解与给定用例最兼容的技术。

此外,值得用处理缺失数据的多种方法的知识来武装自己,以确保 EDA 的发现将引导您选择最佳方法。

当您可以直接进入建模阶段时,花费额外的时间查看您的数据可能看起来很麻烦(我明白,EDA 可能很无聊),但是当最终的模型表现令人满意时,花费额外的时间来确定要使用的最佳技术将会得到回报。

我祝你在数据科学的努力中好运!

不要扔掉你的离群值!

原文:https://towardsdatascience.com/dont-throw-away-your-outliers-c37e1ab0ce19

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Unsplash 上的absolute vision拍摄

首先,在数据集中寻找错误的原因。

检测到异常值 或者异常后,你需要决定如何处理它们。这篇文章解释了处理异常值的技巧。

第一步,调查

调查你的异常值。它们为什么会发生?它们真的是错误吗?现实生活中永远不会发生吗?它们在数据中,所以发现错误来自哪里是很重要的。由于实验或人为错误,可能会出现异常值。加载或处理数据时可能会出错。找到原因后,你就可以决定该怎么做了。

问题解决了吗?如果您决定离群值不应该出现在数据中并删除它们,请确保您可以定义原因。或者更好:记录下来。如果您发现新数据可能与异常值具有相同的值,您应该使用其他技术来处理它们,如下所述。

处理异常值

如果离群值与其他数据点相比只是不规则的,但是可能会发生,那么要小心它们!您可以尝试几种技术来改善机器学习模型的结果,而不删除异常值。

这些技术基于数据转换:

给数据封顶

您可以尝试的一种特殊转换是对数据进行 capping 或winsor izing。这是一种将特性的最大值设置为特定值的方法。您可以决定将最低的 2%设置为第二个百分位的值,最高的 2%设置为第 98 个百分位的值。这里是一个使用 python 代码的例子。

其他数据转换

除了封顶,还有其他方法来转换数据。您可以使用缩放器、对数变换或宁滨。

缩放器是您应该尝试的一种技术,因为缩放会对模型的结果产生巨大的影响。在这里你可以找到 sci-kit learn 对不同 scaler 的比较。你可能想阅读更多关于鲁棒定标器 的信息,它被设计用来处理异常值。

当变量以指数比例增长或衰减时,最好使用对数变换,因为变换后变量更接近线性比例。尾部的影响减小了。

宁滨,或称分桶,将一系列值替换为一个代表值。您可以以不同的方式使用宁滨:您可以设置箱的距离,您可以使用频率(每个箱获得相同数量的观察值),或者采样

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由玛丽娜·赫拉波娃Unsplash 上拍摄

基于模型的技术:

使用正则化

正则化减少了方差,这使得它在处理异常值时很有用。两种最常见的正则化类型是套索正则化和岭正则化,也分别称为 L1 正则化和 L2 正则化。

正则化通过惩罚高值回归系数来工作。它简化了模型,使它更健壮,不容易过拟合。

正则项在所有著名的 ML 包中都有实现。例如,看看 scikit-learn 套索添加正则化到 Keras 层

型号选择

有些模型在处理异常值方面比其他模型更好。例如,如果你正在处理一个回归问题,你可以尝试随机样本一致性(RANSAC)回归或者希尔森回归RANSAC 使用来自数据的样本,建立一个模型,并使用残差来分离内部值和外部值。最终的模型只使用内联器。

如果您想要使用所有数据点,您可以使用基于树的模型。基于树的模型通常比其他模型更好地处理异常值。一个直观的解释是:树关心的是一个数据点位于拆分的哪一侧,而不是拆分和数据点之间的距离。

更改误差度量

最后一个选项是改变误差度量。一个简单的例子:如果你使用均方差,你会更严厉地惩罚异常值,因为你平方了误差。您可能希望切换到平均绝对误差,因为您采用误差的绝对值,而不是平方它。

摘要

在扔掉离群值之前,调查它们。寻找数据集中出现错误的原因。如果您无法解决这些问题,请使用变换、添加正则化或选择适当的模型或误差度量来处理数据。

感谢阅读!❤

有关系的

**https://hennie-de-harder.medium.com/are-you-using-feature-distributions-to-detect-outliers-48e2ae3309 **

不要低估 Python 集合的优雅力量💣

原文:https://towardsdatascience.com/dont-underestimate-the-elegant-power-of-python-sets-9b152f9de7f4

有用的小技巧!

快速学习 Python 集合的基础知识!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

David ClodeUnsplash 上拍摄的照片

您的旅程概述

  1. 为什么要关心 Python 中的集合?
  2. 创建器械包
  3. 有用的设置方法
  4. 速记符语法
  5. 一套能放什么?
  6. 收尾

1 —为什么要关心 Python 中的集合?

Python 中有四种基本的容器类型:

  • **列表:**Python 中的列表是可变序列,可以包含不同类型的数据。比如dates = ["19-12-1922", "08-02-2005"]
  • **元组:**Python 中的元组类似于列表,只是它们不是可变的。它们的内部状态不会随着时间而改变。比如seasons = ("Spring", "Summer", "Autumn", "Winter")
  • 字典:Python 中的字典是键值存储,其中的键指向一个特定的值。一个例子是age = {"Eirik": 27, "Grandma": 86}
  • **集合:**Python 中的集合是无序且可变的集合。最重要的是,集合只包含唯一的值。例如emails = {"toy_email@gmail.com", "not_a_real_email@hotmail.com"}

在 Python 入门课程中,每个人都学习了列表、元组和字典。然而,Python 中的集合经常被忽略。一些初级数据专业人员认为集合更高级或更深或*。这不是真的!*

Python 中的 set 非常实用,也没那么难学。在这篇博文中,我将或多或少地向您展示开始使用 Python 时需要知道的一切。

作为一个例子,在我们开始之前,考虑从下面的列表中提取唯一值的问题:

*languages = ["Python", "R", "R", "SQL", "Python", "C", "SQL"]*

你可以看到PythonR都被列了两次。要手动执行此操作,您可以执行以下操作:

*languages = ["Python", "R", "R", "SQL", "Python", "C", "SQL"]# Manually:
unique_languages = []
for language in languages:
    if language not in unique_languages:
        unique_languages.append(language)*

这工作得很好,但是它比需要的代码多得多。使用集合,您可以在一行可读的代码中轻松实现这一点:

*languages = ["Python", "R", "R", "SQL", "Python", "C", "SQL"]# Manually:
unique_languages = []
for language in languages:
    if language not in unique_languages:
        unique_languages.append(language)

# With Sets
unique_languages = list(set(languages))*

太棒了,对吧?如果你是一个视觉学习者,我制作了一个视频,涵盖了差不多相同的主题🔥

***注意:*除了这里提到的四种类型,还有许多其他类型的容器。我写了一篇关于数据类的博客,如果你想看的话,你可以看一下!

2 —创建集合

在 Python 中创建集合的第一种方法是使用花括号,如下所示:

*# Basic Syntax for Creating Sets
favorite_foods = {"Pizza", "Pasta", "Taco", "Ice Cream"}*

现在,您已经创建了一个有四根弦的 set。集合可以包含不同的数据类型,但是在应用程序中,数据类型通常是相同的。在 Python 中创建集合的另一种方法是使用集合构造函数:

*# Set Constructor
aweful_foods = set(["Tuna", "Tomatoes", "Beef", "Ice Cream"])*

这里首先创建一个包含四个字符串的列表,然后将该列表传递给 set 构造函数。你可以想象上面两个例子的数据来自一项关于最喜欢和最不喜欢的食物的调查。

一般来说,如果你已经有了一个列表(或者另一个 iterable)中的数据,那么使用 set 构造函数可能是最简单的。

了解器械包会自动删除重复项是很重要的:

*i_love = {"You", "You", "You", "You"}
print(i_love)**Output:** 
{"You"}*

甜食😍

***注意:*要创建一个空集,你不能给一个变量赋值{}。这将创建一个空字典。相反,使用set()创建一个空集。

3 —有用的集合方法

集合上有一堆有用的方法。我想告诉你四个最重要的:

向集合中添加元素

您可以使用add()方法向集合中添加元素:

*favorite_foods.add("Chocolate")
print(favorite_foods)**Output:**
{'Ice Cream', 'Pasta', 'Pizza', 'Chocolate', 'Taco'}*

回想一下,对于列表,有一个方法append()可以将一个元素追加到列表的末尾。集合没有顺序。因此 Python 的开发者选择使用名字add()而不是append()来强调这一点。

合并两个集合

如果您有两组,那么您可以使用union()方法将它们组合起来:

*all_foods = favorite_foods.union(aweful_foods)
print(all_foods)**Output:**
{'Tomatoes', 'Ice Cream', 'Tuna', 'Pasta', 'Pizza', 'Chocolate', 'Beef', 'Taco'}*

这里,两个集合中的所有元素都被合并到一个新的集合中,称为all_foods。注意"Ice Cream"all_foods中只出现一次,即使它同时出现在favorite_foodsaweful_foods中。Python 集合删除重复!

寻找共同元素

如果你想找到两个集合共有的元素,那么你可以使用intersection()方法:

*dividing_foods = favorite_foods.intersection(aweful_foods)
print(dividing_foods)**Output:**
{'Ice Cream'}*

如您所见,intersection()方法挑选出两个集合中的元素。如果你有两组投票,想找出两组都投了什么,这个方法真的很有用。

寻找差异

给定两个集合,您通常希望找到第一个集合中不在第二个集合中的元素。为此,您可以使用difference()方法:

*likable_foods = favorite_foods.difference(aweful_foods)
print(likable_foods)**Output:** {'Pizza', 'Pasta', 'Taco', 'Chocolate'}*

在上面的代码示例中,aweful_foods中的每个元素都已从集合favorite_foods中移除。

另一个例子

让我们再做一个例子,这样你就可以看到集合是多么有用。假设您有以下两个编程学习平台列表:

*platforms = ["Udemy", "Coursea", "YouTube", "DataCamp", "YouTube"]
paid_platforms = ["Udemy", "Coursea", "Skillshare", "DataCamp"]*

***现在说想找免费的平台。*你会怎么做?使用集合,您可以简单地编写:

*print("Free: ", set(platforms).difference(set(paid_platforms)))**Output:**
Free:  {'YouTube'}*

4-速记运算符语法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Jippe JoostenUnsplash 上拍摄的照片

在上一节中,我向您展示了一些很酷的方法。但是你知道还有union()intersection()difference()的简写吗?简写操作符语法更容易记忆和阅读。这里您可以看到一个同时包含四个运算符的代码示例:

*print("Union: ", favorite_foods | aweful_foods)
**Output:** Union: {'Tomatoes', 'Ice Cream', 'Tuna', 'Pasta', 'Pizza', 'Chocolate', 'Beef', 'Taco'}print("Intersection: ", favorite_foods & aweful_foods)
**Output:** Intersection: {"Ice Cream"}print("Difference: ", favorite_foods - aweful_foods)
**Output:** Difference: {'Pizza', 'Pasta', 'Taco', 'Chocolate'}*

我个人更喜欢简写的操作符语法。也超级直观!例如,在编程语言中,符号&通常代表and布尔组合器。and布尔组合器的工作方式与交集相同。其他两个例子也很容易得出类似的结论。

5 —你能在一套中放些什么?

让我问你一个简单的问题。你能在一套中放什么样的物体?你可能认为答案是任何东西*。然而,事实并非如此。考虑如果您尝试运行以下代码会发生什么:*

*invalid_set = {[1, 2, 3], "Good try, though"}**TypeError**: unhashable type: 'list'*

如您所见,如果您试图将一个列表放入一个集合中,Python 会抛出一个TypeError。原因是一份名单不是所能公布的。解释 hashable 最精确(但最没帮助)的方式是可以在 hashable 对象上调用hash()函数。在实践中,你通常需要知道的是不可变对象是可散列的。然而,并不是所有的可散列对象都是不可变的。

因此,您可以确定任何不可变的东西(例如整数、字符串和元组)都可以放入集合中。但是,将列表和字典放入集合是不可能的。您也可以不将一个集合放在另一个集合中:

*nested_set = {1, set([2]), 3}**TypeError**: unhashable type: 'set'*

6—总结

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由斯潘塞·伯根Unsplash 上拍摄

希望您对 Python 中的集合感觉更舒服。如果你对数据科学、编程或任何介于两者之间的东西感兴趣,那么请随意在 LinkedIn 上添加我,并向✋问好

喜欢我写的?查看我的其他帖子,了解更多 Python 内容:

不要在 A/B 测试中使用 T 测试

原文:https://towardsdatascience.com/dont-use-a-t-test-for-a-b-testing-e4d2ef7ab9b6

如何使用多元线性回归确定 ATE 和统计显著性

你有没有想过加快 A/B 测试的速度?好吧,这可以说是在 A/B 测试环境中减少方差的最高 ROI 解决方案。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由亚历克斯·罗伯特Unsplash 拍摄

频繁主义者的实验通常被用于实验。然而,与贝叶斯或序贯方案相比,频繁 A/B 测试通常需要大样本量,这减慢了公司迭代。下面我们将讨论一个实际的解决方案,它允许我们在一半的时间内达到统计显著性。

与之前的帖子不同,我们不会评论一篇论文。相反,我们将汇集我在过去 8 个月中所做的研究,并在此过程中链接相关资源。

事不宜迟,让我们开始吧…

技术 TLDR

t 检验是在 A/B 检验中确定统计显著性的最简单的频率主义方法。函数形式为north_star ~ const + treatment_indicator的 OLS 在数学上等同于 T 检验,但是它允许我们包含减少方差的协变量。一个著名的例子就是 CUPED

通过利用稳健的因果模型而不是 T 检验,我们可以自由地大幅降低方差。

1 —设置

让我们慢一点,真正明白发生了什么。为了便于交流,我们将从一个例子开始。

我们是在线应用商店的数据科学家。我们的目标是确定 app store 游戏的最佳排名算法(图 1)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1:在线应用商店的例子。图片作者。

我们可以利用任何参与度数据,例如点击、下载、评分等。我们也可以使用这些指标的加权组合。

然而,为了测试最好的系统,我们将利用因果推理的黄金标准:A/B 测试。我们的控制臂将采用默认排序算法,每个治疗臂将采用新排序算法。最后,我们的北极星指标,我们用来作为实验成功标准的指标,将是收入。

2—基线:T 检验

传统的 frequentist A/B 测试程序将利用双样本 T 检验来查看我们的治疗组是否显示出与我们的对照组有统计学上的显著差异。实现起来非常简单高效,如下所示…

from scipy.stats import ttest_ind
import numpy as np
np.random.seed(1)mu_c = 5
mu_t = 5 + 0.05                                 # 1% liftc = np.random.normal(loc=mu_c, scale=1, size=1e4)
t = np.random.normal(loc=mu_t, scale=1, size=1e4)ate = np.mean(t) - np.mean(c)                # 0.04966
percent_lift = ate / np.mean(c)              # 0.0099
p_val = ttest_ind(t, c).pvalue               # 0.00044

在上面的例子中,我们创建了一个控制和处理阵列,其中处理平均比控制高 1%。这代表了 1%的提升,表明我们治疗部门使用的算法增加了 1%的收入。

从那里,我们计算提升百分比和统计意义。如最后两行代码所示,正如预期的那样,我们的模拟返回了 0.99% 的提升,非常接近 1%。还要注意,我们观察到 p 值为 0.00044 ,远低于标准的 0.05 阈值。

太好了!T 检验有效。

现在,虽然 T 检验在统计学上非常稳健,但它们留下了很多问题。interest 的主要缺点是,他们假设我们度量观察中的所有方差都是真正的噪声**。通常,在现实世界中,我们称系统方差为噪声,因为我们没有可靠解释方差的变量。**

但是,在大多数实验中,并不是所有的方差都是不可解释的,我们将使用线性回归来控制这些趋势。

3 —线性回归

线性回归是一个比基本 T 检验更强大的工具。但在我们深入讨论之前,让我们先退一步。

我们选择的假设检验由我们的数据生成机制决定——在这种情况下,随机分配给治疗组或对照组。通过随机分配和中心极限定理,我们保证满足 T 检验的所有假设。

然而,对于线性回归,我们必须对协变量更加小心。我必须避免的主要问题是特征之间的共线性,尤其是我们的治疗指标。但这是非常可行的。

还要注意,与许多因果推断模型不同,我们不必假设模型是正确的,因为给定随机分配,我们有渐近推断。所以,在英语中,我们可以用线性回归来确定 ATE 和统计显著性。

让我们看一个例子。

3.1-T 检验的奇偶校验

下面,我们利用 statsmodels 包来重新创建 T 检验的结论…

import statsmodels.api as sm# 1\. Create treatment indicator variable (1 = treat)
is_treat = np.append(np.repeat(1, len(t)), np.repeat(0, len(c)))# 2\. Create independent and dependent vars
x = np.array([is_treat, np.repeat(1, len(t) + len(c))]).T
y = np.append(t, c)# 3\. Fit LM
lm = sm.OLS(y, x).fit()# 4\. Observe ATE and stat sig
ate_ols  = lm.params[0]                                # 0.04966
pval_ols = lm.pvalues[0]                               # 0.00044
round(ate_ols, 6) == round(ate, 6)                     # True

我们首先创建一个二元处理虚拟变量和一个常数。然后,我们使用这两个特征来拟合我们的模型,作为对我们的兴趣指标(收入)的预测。最后,我们提取治疗指标的系数及其 p 值。

正如我们所见,线性回归产生的平均治疗效果(ATE)与 T 检验产生的效果相同。从数学上来说,他们是相同的。

所以现在我们可以清楚地看到,OLS 和 T 检验的步骤产生了相同的结果,但我们为什么要使用 OLS 呢?

4 —多元线性回归

正如这一节的标题所暗示的,OLS 允许我们使用多个变量。随着我们增加相关变量的数量,理论上我们将减少方差并更快达到统计显著性。

现在重要的是重申我们必须避免共线特征。这意味着我们的特征没有一个能够非常相互关联。当这种情况发生时,不仅模型系数表现奇怪,而且方差会被夸大,这损害了我们确定统计显著性的能力。

4.1 —解释变量

让我们看另一个例子。在下面的代码中,我们开发了两个协变量:seasonalcovariate_random。请注意,在现实世界中,我们实际上是解释性变量,如一周中的某一天或来自用户的总收入。

seasonal = np.sin(np.arange(len(control))) + np.array([1 if np.random.uniform(len(control)) > 0.7 else 0])
covariate_random = np.random.chisquare(5, size=n)c *= seasonal
c += covariate_randomt *= seasonal
t += covariate_random

**在使用季节性和随机协变量来衡量我们的治疗和控制后,我们接下来拟合多元线性回归。这个多元回归缺少我们的 **covariate_random** **变量。输出可以在图 2 中看到…

x = np.array([np.repeat(1, len(t) + len(c)), 
              is_treat, 
              np.append(seasonal, seasonal))]).T
y = np.append(t, c)lm = sm.OLS(y, x).fit()
print(lm.summary())

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 MLR 的输出,其中 x1 是治疗指标,x2 是季节性成分。图片作者。

在图 2 中,我们的治疗指示器(x1)指示一个 0.0350 ATE。但是,它在统计上并不显著,如 P > |t|列中的 0.469 所示。我们还要注意,我们的治疗指标变量的标准误差是 o.o48.

现在,covariate_random掌握了我们的因变量收入的重要信息,我们用它来创建我们的治疗/控制值。所以,让我们把它加入到模型中,看看会发生什么…

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 MLR 的输出,其中 x1 是治疗指标,x2 是季节性因素,x3 是我们的“协变量”。图片作者。

可以看到,我们的待遇指标 x1 的系数仍然是 0.0350 。这很好——我们没有添加共线性变量。然而,真正令人印象深刻的是 P > |t|列—我们已经从 P 值 0.469 到 0.044。

****通过简单地包含预测协变量,我们能够达到统计显著性。我们不需要收集更多数据,例如延长实验时间。我们只是利用统计数据和关于数据方差的知识。

很容易看出这个微不足道的例子是如何推广到现实世界的。如果您有一个健壮的因果模型,您的组织可以更快地迭代,并使更少的用户暴露于次优处理。

本节的最后一点(感谢评论中的 Alvin),在探索治疗指标变量和其他解释变量之间的关系时,探索相互作用可能是一个好主意。

4.2-正则化协变量选择

值得注意的是,在现实世界的例子中,会有许多潜在的协变量,其中一些可能包括之前的购买行为、在平台上的持续时间、一天中的时间、一周中的日期等。理论上,稳健的多元模型会考虑所有这些因素(假设要素之间不存在共线性)。

这里,为我们的因果模型做一些特征选择是有意义的。但是请注意,在我们的休闲模型中包括像 LASSO 这样的正则化项会破坏协变量和我们的治疗指标之间的独立性,从而破坏因果推断。

如果要构建多元因果模型,请确保使用独立数据集进行要素选择。在最终模型中不包括正则化。

4.3-使用 CUPED 减少方差

最后一个技巧是利用方差减少技术,例如 CUPED 。一句话,CUPED 使用实验前的数据从我们的实验数据中去除“通常的”差异。有了方差减少的 ATE,我们能够更快地达到统计显著性。

ML 模型最近也变得流行,以减少实验方差,但它们涉及到大量更多的工作。也就是说,如果你是一家大公司,这可能是值得的。

5 —摘要

在这篇文章中,我们通过使用多元线性回归来估计 ATE,确定统计意义,并减少方差。如果你在实验中使用 T 检验这样的频率主义方法,那么利用多元 OLS 可能会对你有好处。然而,确保你符合 OLS 的假设——如果你不符合,你的 ATE 和统计显著性计算将是错误的。

感谢阅读!我会再写 17 篇文章,把学术研究带到 DS 行业。查看我的评论,链接到这篇文章的主要来源和一些有用的资源。

不要在 Python 中使用 Apply,遵循这些最佳实践!

原文:https://towardsdatascience.com/dont-use-apply-in-python-there-are-better-alternatives-dc6364968f44

应用功能的替代方案,可将性能提高 700 倍

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:Unsplash

什么是应用功能——如果你还不知道的话!

Apply 函数是一个单行函数,可用于在数据帧的所有元素上或跨数据帧的行或列应用操作。

简介

数据科学家/分析师经常使用 Apply 函数来执行数据操作任务**,但是当您的数据有太多行时使用它真的是最佳选择吗?**

不尽然!

在这篇博客中,我们将看看下面 3 个非常有用的替代方法,你可以用它们来代替 Apply 函数,尤其是当你有大量的行时:

  1. 并行化
  2. Loops(是的,可以更快!)
  3. 矢量化(最佳实践!)

但是首先,让我们来看看 apply 函数在大型数据集上的执行时间。

创建数据集

我们将创建一个具有 5 百万行和 4 列的数据集。每列可以有一个从 0 到 50 的整数值。

import numpy as np
import pandas as pddf = pd.DataFrame(np.random.randint(0, 50, size=(5000000, 4)), columns=('a','b','c','d'))df.shape
# (5000000, 5)df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据框(图片由作者提供)

定义功能

现在,让我们定义我们的函数,该函数基于 dataframe/input 变量的现有列中的值返回一些值。

def infer(a,b,c,d):
    if a==0:
        return d
    elif a <= 25 & a>0:
        return b-c
    else:
        return b+c

应用功能

现在,我们将使用“应用”函数来调用上一步中定义的推断函数。

import timestart = time.time()
df['e'] = df.apply(lambda x: infer(x['a'], x['b'], x['c'], x['d']), axis = 1)
end = time.time()
print(end - start)### Time taken: 200 seconds

应用功能大约需要 200 秒才能得到结果。

让我们来看看替代方法:

选项 1:并行化

并行化是通过将大数据块划分为较小的数据块来实现的,这些较小的数据块使用多个 CPU 和内核的能力来并行处理。

有几个包,比如 SwifterDask ,我们可以使用它们实现并行化。在这篇博客中,我们将看看 swifter,因为它非常容易使用,并且在某些情况下可以达到几乎相同的结果或更好的结果。

我们可以简单地在 dataframe 之后调用 swifter 包,然后继续应用函数。

## install the package
!pip install swifter## import the package 
import swifter## use the swifter package
start = time.time()
df['e'] = df.swifter.apply(lambda x: infer(x['a'], x['b'], x['c'], x['d']), axis = 1)end = time.time()
print(end - start)## Time taken: 60 seconds

因此,使用 Swifter 包,我们可以将执行时间减少 3 倍以上,对于简单添加包名来说,这已经不错了。

Swifter 试图以最好的方式实现 apply 函数,要么在后端使用 Dask 将其矢量化或并行化,要么在数据集很小的情况下简单地使用 pandas apply。

选项 2:循环

我知道这听起来令人震惊,但如果你有一个没有太多列的数据集,那么这种技术可以方便地获得比 swifter 包更好的结果。

诀窍是首先将 dataframe 转换成默认的 light 数据结构,比如数组或字典,然后遍历这些行来操作数据集。

start = time.time()## empty list 
list2 = []## adding 'e' column with default 0
df['e'] = 0## convert dataframe into array 
for row in df.values:
    if row[0] == 0:
        row[4] = row[3]

    elif row[0] <= 25 & row[0] > 0:
        row[4] = row[1]-row[2]
    else:
        row[4] = row[1] + row[2]
    list2.append(row)

df2 = pd.DataFrame(list2, columns=['a', 'b', 'c', 'd','e'])end = time.time()
print(end - start)## Time taken: 20 seconds

因此,使用 for 循环遍历数组,我们能够将执行时间减少到 20 秒,比 apply 函数提高了 10 倍。

选项 3:矢量化

矢量化是在数据集上实现数组操作的技术。在后台,它一次将操作应用于数组或序列的所有元素(不像 for 循环一次处理一行)。

对 python 代码进行矢量化是实现最佳性能的最佳实践。

# using vectorization 
start = time.time() df['e'] = df['b'] + df['c']
df.loc[df['a'] <= 25, 'e'] = df['b'] -df['c']
df.loc[df['a']==0, 'e'] = df['d']end = time.time()
print(end - start)
## 0.28007707595825195 sec

因此,我们能够将运行时间减少到 0.28 秒,比应用函数的运行时间快 700 倍。

摘要

  • 我们研究了 python 中 Apply 函数的 3 种替代方法,尤其是当数据集包含大量行时。
  • 我们了解了 swifter 软件包的并行处理能力。
  • 我们发现,如果聪明地使用,python 中的循环并没有那么糟糕。
  • 对于一个大型数据集,代码的矢量化带来了最佳的性能提升,大约是 apply 函数的 700 倍。因此,使用矢量化处理大型数据集是最佳实践。

我希望你从这篇文章中学到了一些新的东西。

你可以在收件箱里收到我的帖子。 做到这里 如果你喜欢体验媒介的自己,可以考虑通过 报名会员来支持我和其他成千上万的作家。它每个月只需要 5 美元,它极大地支持了我们,作家,而且你也有机会通过你的写作赚钱。

不要用 Python 的列表乘法([n] * N)

原文:https://towardsdatascience.com/dont-use-python-s-list-multiplication-n-n-450c68d673a3

意见

这是个陷阱

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由像素上的像素拍摄

无论您是新手还是有经验的 Python 程序员,都有可能使用过列表乘法和/或在那些“很酷的 Python 特性”风格的文章中读到过它。

这是因为它无疑是那些旨在使您的 Python 生活更容易的很酷的特性之一。

列表乘法的好处是它抽象了初始化列表的过程。

不使用迭代方法或列表理解:

# Iterative approach
my_list = []
for _ in range(N):
    my_list.append(n)# List comprehension
my_list = [n for _in range(N)]

您可以通过以下方式获得相同的结果:

my_list = [n] * N

你看,我是按照以下顺序学习编程语言的:

C -> C++ -> MATLAB -> R -> Python.

在 Python 之前,我使用过的任何其他编程语言都无法提供如此的简洁和直观。

然而,随着我开始编写越来越复杂的代码,列表乘法开始让我心烦。

我记得有一次我花了整整一个下午调试代码,结果发现问题源于使用*操作符创建不正确的列表。

因此,我觉得有必要讨论一下这个问题,因为我知道一个事实,一些开发人员仍然没有注意到 star 操作符在列表创建方面的权衡。

列表乘法有什么问题

让我们考虑下面的代码:

>>> my_list = [0] * 3
>>> my_list[0] = 1
>>> my_list
[1, 0, 0]

这是你所期望的。到目前为止,一切顺利。

现在,让我们尝试使用相同的方法创建一个 2D 阵列:

>>> my_list = [[0] * 3] * 5
>>> my_list[0][0] = 1
>>> my_list
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]

嗯!这可能不是你想要的。

通过初始化一个 3D 数组来进一步推动它怎么样:

>>> my_list = [[[0] * 3] * 5] * 2
>>> my_list[0][0][0] = 1
>>> my_list
[[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]], [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]]

预期的输出是更新子列表[0, 0, 0]的第一个值。然而,似乎这个更新在所有的子列表中都被复制了。

那么,为什么会这样呢?

列表乘法是如何工作的?

为了理解前面的行为,有必要重温一下 Python 的 FAQ ,其中写道:

原因是用*复制一个列表不会创建副本,它只会创建对已有对象的引用

让我们将其转化为代码,以便更好地理解 Python 在幕后是如何操作的:

  • 列表乘法:
my_list = [[0] * 5] * 5
for i in range(5):
    print(id(my_list[i]))

输出:

2743091947456
2743091947456
2743091947456
2743091947456
2743091947456
  • 使用 for 循环
my_list = []
for _ in range(5):
    my_list.append([0] * 5)for i in range(5):
    print(id(my_list[i]))print(my_list)

输出:

2743091947456
2743095534208
2743095532416
2743095534336
2743095532288
  • 释义

for循环不同,通过操作符*复制的所有列表都指向同一个内存地址。这意味着影响一个嵌套列表的任何改变都会影响所有其他列表,这显然违背了我们的初衷。

现在的问题是:

  • 为什么第一个例子([n] * N)工作得很好,尽管列表中的所有元素都引用同一个对象?

事实证明,这种行为背后的原因(如 Python 的 wikibook 中所述)是列表是可变项,而int, str等是不可变的。看看这个:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源

因为不可变的对象不能被改变,所以当你更新列表中的一个条目时,Python 会创建一个新的(不同的)对象引用。

>>> my_list = [0] * 3
>>> id(my_list[0])
1271862264016
>>> my_list[0] = 1
>>> id(my_list[0])
1271862264048

工作区

解决这个问题的一个快速简单的方法是使用列表理解。当然,这是在标准的for循环之外的。

>>> my_list = [[0] * 3 for _ in range(5)]
>>> my_list[0][0] = 1
>>> my_list
[[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

此外,我们可以看到不同的内存地址被分配给每个列表。

>>> my_list = [[0] * 3 for _ in range(5)]
>>> [id(l) for l in my_list]
[1271867906112, 1271864321536, 1271864322048, 1271864326912, 1271864322560]

更重要的是,这种方法适用于所有场景。

所以,你为什么不坚持下去,为了安全起见,而不是在使用列表乘法之前必须三思呢?

结论

我不是 Pythonic 句法糖的超级粉丝。

是的,我同意这有助于代码简洁明了。

然而conciseness == readability在软件行业是什么时候?

事实上,我用 Python 编写的代码越多,我就越倾向于使用 Python 标准语法和放弃快捷方式。

说到底,重要的是性能可维护性,以及可读性。而不是你有多少行代码。

如果你不能没有捷径,至少读一读你正在使用的语法糖的好的、坏的和丑陋的。在这种情况下,可能需要对软件工程概念(即数据结构、内存分配……)有一定的理解。

快乐编码!

如果你觉得这个有用,可以考虑成为 高级 会员。如果用这个 链接 ,我会得到一个小切。

https://ayarmohammed96.medium.com/membership

不要在生产中使用 R

原文:https://towardsdatascience.com/dont-use-r-in-production-e2f4c9dd4a7b

但是,如果你这样做,这里是如何

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

DALL-E 生成:计算机科学可再生技术环境的说明

我们已经在生产中运行 R 好几年了,这篇文章是关于如何让它发生的。这篇文章也是关于为什么我仍然不认为你应该在生产中运行 R,如果你真的不需要它。我是从一个工程师的角度来看这个问题的。我们将讨论许可、R 限制以及如何解决主要障碍,以达到这样一个目的,即您可以在生产环境中运行 Rscripts,而不那么痛苦( Github link )。这篇文章不是关于付费或托管服务的。

生产中的研发

使用检查点解决版本控制问题

R 的最大问题是可重复性。与 Python 相比,R 没有高级版本和包管理。数据科学家在他们的机器上使用 R,安装所有的包并使用当时发布的版本。从用户的角度来看,这很容易,不需要考虑版本控制。但是如果您现在想在其他机器上运行这个脚本,那么它很有可能不起作用,尤其是在编写脚本和部署之间有延迟情况下。安装一个旧版本的 R 包并不像你想象的那样简单,有很多方法,但是很麻烦。

微软承认这一点,并建立了检查点库,它这样描述自己:

checkpoint 的目标是解决 r 中的包可复制性问题。具体来说,checkpoint 允许您在特定的快照日期安装 CRAN 上存在的包,就像您有一台 CRAN 时间机器一样。

因此,有了 checkpoint,我们可以选择按日期进行版本化,而且到目前为止已经有了可复制的 R 环境。这个帖子在使用 checkpoint 的同时,还有 renv ,解决了同样的问题。

使用它很简单,我们只需将它添加到我们的脚本中:

library(checkpoint)
checkpoint(“2022–07–17”, r_version=”4.2.1")

Checkpoint 将扫描脚本中的导入并管理它们,但是如果您有自定义包,您需要在包含以下内容的 checkpoint.yml 中排除这些包:

exclude:
   - myRPackage

使用 Docker 隔离环境

通常,我们有多个脚本,使用不同的库和版本。为了使它们相互独立,我们使用 Docker。有了 Docker,我们可以构建可靠的环境,并将它们部署到我们想要的任何地方。Docker 与检查点库相结合,解决了可再现性问题。

rocker 项目提供了预构建的版本化 R 容器,我们可以通过扩展版本化映像来使用这些容器:

ARG VERSION=”4.1.0"
FROM rocker/r-ver:$VERSION as base
# Install needed packages and git
RUN apt-get update \
&& apt-get -y install \
libgit2-dev \
libcurl4-openssl-dev \
libssl-dev (...)# checkout our git repository
WORKDIR /workdir
RUN git clone [https://{secret_key}@github.com/username/repo.git](https://{secret_key}@github.com/username/repo.git) .# install checkpoint library
RUN Rscript -e “install.packages(‘checkpoint’)”#start R script
CMD git pull && Rscript my_r_script.R

有了这个小 docker 文件,你已经能够用一个特定的 R 版本来启动一个 R 脚本了( docker run ),而且你还可以确保所使用的库的版本是由检查点库修复的。但是,您会注意到执行花费了相当长的时间,因为检查点库第一次管理指定日期的脚本依赖项时,需要花几分钟来下载和设置它们,并且每次都是这样。

确定开始时间

像这样使用 Docker 和预构建的 R-images 是一个很好的开端,但是我们必须解决另一个问题。如果我们在每次代码更改时都从头构建映像,我们会有巨大的开销,因为检查点库最初需要花费很多时间来构建。但是,如果 R 代码发生变化,我们不需要构建映像,也不需要每次都清除检查点。

为了避免这种情况,我们将 R 脚本的执行移出了 docker 文件。为了避免在设置 R 之后关闭容器,我们在最后调用sleep infinity将控制权交给我们的 bash 脚本。

现在 bash 脚本必须自己启动和停止 docker 容器。然而,现在我们可以在启动 R 脚本之前执行 git pull,而不必在每次代码更改时都重新构建容器。

在 Dockerfile 文件中,我们通过调用以下命令来替换最后一个命令:

CMD sleep infinity

我们最初构建容器(或者如果我们需要更新依赖项),使用:

docker build --no-cache -t foo_image . #build the image
docker create --name foo_container foo_image #create container

我们的 bash 脚本完成了以下工作

docker start foo_container
docker exec foo_container git pull origin master
docker exec foo_container Rscript my_r_script.R
docker stop foo_container

有了这些简单的脚本( github )我们现在可以快速、可伸缩和可复制地运行 R 脚本。

为什么 R 还不用于生产

许可证

R 使用多个许可证,大多数核心 R 库都是在 copyright license 下发布的,比如 GPL-2 和 GPL-3。因此,在某些情况下,这已经是一个问题。如果您计划编写 R 代码并将其作为产品的一部分发布,您将被迫开源您的代码。这已经是一个原因,为什么没有很多产品允许在云环境中执行 R。然而,如果您的产品没有附带 R,那么对于核心库来说,您很可能是安全的。但由于我不是律师,请询问你们的法律部门。

r 不适合软件工程师

大多数 R 用户不会发现这些问题,直到他们必须反复修改他们的脚本。这很好,因为大多数 R-coder 不是软件工程师,不需要知道产品软件应该是什么样子。然而,经常有人试图争辩,因为它对他们来说很容易使用,它在其他地方也一定很容易使用。以下是我个人在生产中遇到的一些实际问题:

  • R 缺乏 OOP 支持,R 是一种函数式语言是有充分理由的。这对小脚本来说很好,但对大项目来说是个问题,因此不建议构建更大、更复杂的应用程序。r 更像是编写狭窄任务的脚本,而不是管理大型工作流。
  • 与编译语言相比,r 本身很慢。因此,很多 R 库要么依赖于预编译的二进制文件,要么需要安装 g++工具链从源代码构建它们。该来源依赖于平台,可能会导致许多问题。此外,出于安全原因,您(或您的 IT)不希望在生产服务器上使用 g++。
  • 您可以生成日志,但这很糟糕,因为您不能轻松地将所有相同格式的日志重定向到 std:out 和 std:err ,所以如果您将日志推入 ELK(或类似的)并处理来自 R print 语句的多行日志,您必须做更多的工作。
  • 在 python 中,你有 requirements.txt/setup.py 来定义需求,处理依赖和版本,在 R 中你没有。r 易于使用,但这是有代价的。这表明 R 正在关注特定的分析任务
  • 当您在自己的机器上编写代码时,它可能无法在另一台机器上运行,尤其是如果中间有一段时间。变化很大,一些库被修改了,代码不再工作了。r 缺乏非常基本的版本控制
  • CI/CDs 工具通常不支持 R ,你必须定制一切。这包括单元测试、集成测试、静态代码检查、包部署和版本控制。
  • r 没有成熟的生态系统来部署 web 服务器和 API。有用于简单可视化的闪亮的和用于 API 的 OpenCPU水管工,但正如其名称所示,它笨重且感觉有限,与 Python 等语言中的类似工具相去甚远。特别是 R 用户经常提倡的 plumber,缺少 HTTPs、OAUTH 和其他大多数更高级的特性。此外,在 R 中,一切都是单线程的。
  • 社区中没有安全问题的意识,人们经常用 devtools 安装未经检查的 github 库。这是生产服务器上的一个主要安全问题(不仅仅是那里)。
  • r 确实比 python 更容易崩溃,因为它的易用性和函数式编程风格让用户不必考虑极限情况。

结论

在这篇文章中,我展示了为什么我认为 R 不是生产用例的好选择。然而,有时候无论如何都是有意义的。原因可能是上市时间、团队组成或技术基础设施。对于这些情况,我展示了如何使用 Docker 和 checkpoint 以可重复的方式部署 R。代码可以在这里找到。

不要浪费你未标记的数据

原文:https://towardsdatascience.com/dont-waste-your-unlabeled-data-9bb778743b41

行业笔记

不要浪费你未标记的数据

评估您的模型的弱点,并在可用数据中确定最具信息性的数据样本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不确定性之光。迈克尔将抱在的 Unsplash 上。

以数据为中心的方法

在过去的十年里,人工智能的主要趋势是专注于建立创造性的复杂模型。但是最近几年,任何人都可以用 Python 等流行语言和 Pytorch、Tensorflow、JAX 等库来使用最先进的架构。现在,人工智能的最高优先级是让这些模型对每个特定的用例都有价值。这需要对可用的精选数据有深刻的理解,不幸的是,数据分析和如何建立一个良好的训练集是经典 ML 课程中很少教授的技能,而是通过时间和汗水学习的。

到目前为止,数据并不被认为是一个主要问题:可变大小的标准研究数据集是免费的( ImageNet,COCO,GLUE 等,以及预训练模型的权重( ModelZoo,Huggingface 等),作为对特定数据子集进行微调的先验知识。除此之外,在小规模数据集上训练本地模型成为一种商品。但在实践中,在生产阶段成功制作 ML 模型是一个难题。

失败的主要原因之一是研究模板上的模型和现实环境中部署的模型之间的准确性损失。事实上,这些公司中有 13%的模型能够投入生产[7]。

当我们知道随着 AutoML 平台的兴起,甚至模型搜索也已经自动化时,这似乎很令人惊讶。瓶颈是什么?

瓶颈是数据。下一个需要强大框架和标准化的挑战是处理数据的管道。行业中的人工智能可能需要从以模型为中心的方法后退一步,转向以数据为中心的方法。以数据为中心的方法试图将模型开发与训练数据集的创建和模型性能的监控协调起来。

“并非所有数据都是生而平等的”——詹妮弗·普伦斯基

不确定性的量化

因为真实世界的数据是杂乱的、嘈杂的、错误的、充满离群值的,并且不遵循正态分布,所以量化不确定性对于构建可信的人工智能模型至关重要。选择好你输入的数据。剔除可疑数据。避免致命的垃圾进,垃圾出,节省时间和金钱。除非我们可以信任模型预测,否则它几乎毫无用处。为了发现这些病态数据,我们将探索作为数据质量代理的模型的不确定性。我们想确定数据在哪里混淆了模型。

不确定性的原因有哪些?

不确定性有许多原因。当训练和测试数据集的分布不匹配时,推理中可能出现不确定性。当数据类重叠或数据本身有噪声时,它也会出现。一般来说,我们应该意识到数据集中不确定性的原始来源,以便创建一个有效的策略来尽可能地减少它。

在主动学习文献中,这些不确定性被分为两大类:认知任意不确定性。一方面,随机不确定性是由数据的噪声产生的,并且在同一实验的每次运行中都会有所不同。这种不确定性是不可减少的,因为它是数据的固有属性。另一方面,认知的不确定性可以通过学习来减少。通过增加数据集大小或使模型复杂化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

两种不确定性的示意图。图自开篇:【https://arxiv.org/pdf/2011.06225.pdf

从理论到实践

默认情况下,我们经常错误地将 softmax 函数输出的每个标签的概率视为每个标签的模型置信度。这种误解可以通过使用一种简单的技术来避免:考虑每个 softmax 输出相对于其他标签或其他实例的相对值。

在本文中,我将分享扫描所有可用数据(标记的或未标记的)的标准技术,以帮助对数据和模型的当前状态做出以数据为中心的结论。这些技术根据模型对其预测标签的置信度来排列每个数据点。我们可以使用不同的函数,将“不确定性”分数归属于每个数据点。高度不确定性意味着模型对该数据点不确定,推断很可能是错误的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用不确定性分数识别类边界附近的实例。图片由作者提供,灵感来自[1]。

为什么我们应该尝试自动化每个可用数据点的评分?

  • 利用现有数据和模型
  • 在数据集中查找边缘案例
  • 查找质量差的数据以重新标记或从训练数据集中排除
  • 通过追踪歧义来澄清标签说明
  • 找到当前模型的弱点
  • 识别新传入数据的数据漂移
  • 误差分析,以找出下一个要标记的样本
  • 查找异常值

考虑到我们将模型投入生产的不断发展的世界,持续改进数据是必要的一步。我听说过一个保龄球图片分类器的故事,当 COVID 开始时,因为社交媒体在这件事上的趋势,它将空卫生纸架上的图像标记为保龄球图片。我们永远不知道未来的数据会是什么样子,我们应该始终意识到我们让数据溜进我们的模型预测。

我们的实验

在本文中,我们评估了为 CNN 模型提供分类的图像。我们将使用 EMNIST 进行实验。

我们使用 softmax 根据最后一个激活函数计算的输出逻辑创建概率分布。Softmax 无法提供模型确定性的概率,并且正在丢失信息,因为它使用指数,所以它丢失了数字的比例([1,4,2,1]将产生与[101,104,102,101]相同的分布)。但我们仍然可以使用 softmax 作为模型可信度的代理,并从高模型可信度到低模型可信度对我们的数据样本进行排序。

“没有算法能在坏数据中存活”——罗伯特·莫纳克

不确定性评分

我们希望将数据标注在我们的模型最混乱的地方——不确定性。因此,对于每个数据点,我们将为所有未标记的数据点给出单个不确定性分数,并将它们从最不确定性到最不确定性进行排序。

该方法是不确定性量化的最简单、最便宜的方法。您可以识别位于模型决策边界附近的数据点

对于一个数据点,您的模型:

  • 给不同的类一个相似的 softmax 概率(例如,输入图像是狗,输出 softmax 是:狗 33.3%,猫 33.3%,鸟 33.3%)
  • 将低概率赋予最高概率(例如,在十个等级中,最高的 softmax 是“青蛙”, softmax 为 10.5%)

我们将按照从简单到复杂的顺序列出评分技术。

我们称 p_max 为针对一幅图像推断出的类的最高 softmax 分数,称 p_2nd 为针对一幅图像的类的第二高置信度。 n 为分类的类数。

对于下面的每个函数,输入 prob_dist 是一个数据点的 softmax 输出数组,输出是该数据点的模型的 0 到 1 之间的不确定性分数。如果数据集是具有三个类的多类分类, prob_dist 的形状为(3,)。

评分类型:

  • 最小置信度(最大置信度预测和 100%置信度之间的差值)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们希望选择在最可能的类别中可信度最低的实例。假设我们有两个图像 A 和 B,模型的最高 softmax logit 分别是 A 的 0.9 和 B 的 0.3。在这种情况下,我们可能希望了解 B 看起来是什么样子,处理,(重新)标记或删除它。

我们使用为每个数据点计算的标准化“最小”不确定性分数(公式(1))。由于最有可能的实例的最低置信水平不能低于 1/n ,我们添加了标准化分数,以将不确定性分数从 0 调整到 1。

该分数将给出预测的等级顺序,其中我们希望对预测标签置信度最低的项目进行采样。

这种评分技术只取决于最有信心项的信心,而不关心第二个或第 n 个信心分。

  • 置信区间

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

边际置信度取一个数据点的两个最有把握的预测之间的差值。我们可以通过将结果减去 1(公式(2))将该差值转换为[0–1]范围。这次你只关心两个最高类别中两个最高分的差。这个差值越小,越接近 1,你就越不确定。与最小置信度得分相比,该算法对 softmax 基数不太敏感,但仍然敏感。

  • 置信度(两个最有把握的预测之间的比率)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

比率评分函数是置信区间评分的变体。这个不确定性分数看两个最高分数的比率(3)。该比率作为用于 softmax 的基数的乘数给出,因此与前两种方法不同,它对 softmax 基数不敏感。它捕捉到第一个标签比第二个标签更有可能。

  • 基于熵的(所有预测之间的差异)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

熵分数考虑了所有类别的预测。它是通过将概率的负和乘以其 log_2 概率来计算的。

我们除以 log_2(n)来归一化 0 和 1 之间的熵(等式(4))。

2 作为对数的基数是不改变排名的任意基数,即使它将单调地改变绝对不确定性分数。

实验设置

我们举例说明两个评分函数的结果(最小)。我们首先在一半的 EMNIST 数据集(130,106 张图片)上训练一个简单的两层 CNN。然后,我们预测所有看不见的数据点的类别,并根据它们的不确定性得分对它们进行排序。我们对前 1000 幅图像进行采样,给出它们的不确定性分数。

我们的 CNN 由两个卷积层组成,每个卷积层之后是 RELU 激活,然后是两个完全连接的层。在验证准确度开始降低之前,我们在第 6 个时期停止训练。我们在验证集上获得了 0.79 的 F1 分数。

您可以在以下位置找到培训代码:https://github . com/ble DEM/active-learning/blob/master/run _ experiment . py

以及用于采样前 1000 个图像作为新数据集,位于:https://github . com/ble DEM/active-learning/blob/master/create _ new _ set . py

结果

我们查看在验证集上每个类的平均 F1 分数最高和最低的类。

F1 分数最低的类别(F1 <50%) are:

'k' 'o' 'i' 'r' 'Y' 'q' 'b' 'l' 'h' 'e' 'm'

and the classes with the highest F1 score (F1> 95%)是:

'n' 'Z' 'A' 'a' '3'

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每级 F1-验证数据集中的分数。

现在让我们来看看根据不确定性得分排名的前 1k 张图片。为了便于比较,我们还随机抽取了 1k 的样本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用“最少”评分技术从看不见的数据中分配 1k 个采样数据点。

从上图可以看出,我们对容易混淆的字符进行了过采样:“I”、“1”、“l”或“O”、“O”、“0”。

在下图中,我们将每个类的 F1 分数与使用熵不确定性评分函数采样的 1k 的不同类之间的实例分布进行了比较。我们在“容易混淆”的类中发现一个高峰,这在随机采样的数据集中不会发生。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

验证数据集(蓝色)上的 F1 分数与“最少”技术得出的样本集中每个类的百分比的叠加。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

验证集(蓝色)和随机采样的 1k(橙色)上 F1 分数的叠加。

我们在下面展示了一些 EMNIST 图像作为前 1k 不确定推理的例子。当我们查看基于“最少”或“熵”的样本时,我们可以清楚地看到标签中的噪声(例如 S 标记为 0)和图像本身(模糊、不可读的字符)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

随机采样的图像(右)和模型置信度最低的图像(左)之间的比较。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

给定“熵”不确定性分数的高不确定性图像(低模型置信度)的示例。

在实践中使用不确定性评分

使用不确定性分数对新标注任务的数据批次进行采样是标记未知数据集中最具信息量的数据点的有效方法。然而,正如我们所看到的,我们应该注意不要系统地对过度表示的类及其近邻中的相似数据点进行过采样。

我们在这里列出了使用上面介绍的评分方法的利弊:

优点:

  • 使用现有/标准模型
  • 快速且易于计算和解释。
  • 如果您的模型使用传统的机器学习(而不是深度学习),请创建一批新的信息数据样本进行标记

缺点:

  • 这些简单的评分函数不应用于为深度学习的新批量任务选择数据点。由于潜在的采样偏差,在对这些采样数据进行训练后,模型的性能可能比随机采样差[5]。
  • 使用贝叶斯深度学习创建高维数据(图像、文本等)的采样策略更安全。).

复制不确定样品的注意事项

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由穆罕默德·道迪拍摄

使用不确定性量化方法可以非常有效地在未标记的数据中找到位于模型边界上的样本。但是,在为下一批注释选择要采样的数据点时要小心。该抽样单独评估每个未标记点的信息量。如果您只选择最高不确定性得分数据点,您将检索到一个信息数据点和许多几乎相同的拷贝。如果你天真地获得了前 k 个最有信息的点,你可能最终也会问 k 个几乎相同的点。这将使您的样本批次的贡献低于随机抽样批次。例如,在 EMNIST 实验中,如果你观察熵采样技术,你可以看到字符“I”,“1”,“l”被大量采样。

为了避免这种重复采样效应,一些研究论文提出了补充方法,如 BatchBALD 等批量感知采样技术解决方案[2]。在本文中,作者不仅关注每个样本的不确定性得分,还关注为下一批训练样本提供最丰富的信息。

使用 wise 采样构建注释的智能批处理[1]:

  • 最小化样本量,以确保从每个数据点获得最大收益。
  • 最大化样本量,以避免过于频繁的重新训练。

关于智能采样的更多信息

1)异议评分:

评估每个未标记数据点的不确定性的另一种流行的启发式方法被称为委员会的查询方法。如果您有一组模型,您也可以通过获取每个模型的每个数据点的所有分数来调整不确定性评分。您在初始训练集上训练几个不同的模型,您可以查看它们在未标记数据上的分歧。

例如,我可以在相同的训练集上用不同的超参数训练相同的 CNN,然后将它们应用于未标记的数据,并使用它们的不一致来选择下一个要标记的样本。

当您想要评估预测中 softmax 置信度不可用的回归任务的不确定性分数时,此方法特别有用。

辍学策略

如果你没有一个集合模型,你可以为每个数据点画出不同的预测,其中每个新的预测是在每次丢弃不同的随机选择的神经元之后做出的。正常情况下,退出仅在训练期间应用,所有神经元在测试期间都被激活。但是如果我们在测试中也应用 dropout,我们可以为每个实例推断出一系列不同的预测。每个样本的不确定性可以计算为所有预测的变化:不一致程度越高,不确定性就越大[1]。这种技术通常被称为蒙特卡洛退出技术。蒙特卡洛是一种计算技术,它从真实分布中随机取样,以获得该分布的估计值。在不确定性估计过程中,我们将来自漏失模型的每个预测视为蒙特卡罗样本。

面向 MC 辍学和其他主动学习技术的开源库:https://github.com/ElementAI/baal/【论文】

2)贝叶斯模型

您可以使用生成贝叶斯模型对每个类的分布进行建模。在这种情况下,您不需要使用概率代理来推断模型预测的可信度,因为您可以从模型输出本身直接读取每个数据点属于每个类的概率。

您可以使用贝叶斯神经网络来估计神经网络的不确定性。在贝叶斯神经网络框架中,在训练期间,你不尝试学习单个函数 f,而是学习类似于集成模型的多个函数。训练之后,我们可以对每个数据点进行平均预测,并计算这些预测之间的方差。可以为从回归到分割的各种任务建立贝叶斯神经网络。它将模型参数视为正态分布以及每个模型参数分布的均值和方差。这些参数通常在训练过程中学习。

3)主动学习

我一直专注于给每个未标记的样本分配一个不确定性分数。但是,不确定性量化只占更广泛的主动学习领域的极小一部分。AL 致力于通过标记尽可能少的样本来获得尽可能多的性能增益[3]。理论上,理想的系统会查询位于模型的决策边界上的实例和远离决策边界的实例(离群值、多样性采样、要定义的新类)。不幸的是,还没有一种标准的方法来构建最佳的管道来查询最小的数据样本以获得最高的性能。

4)课程学习

另一个非常有趣的研究领域试图通过向模型提供适当的数据点来优化学习。它不是关注未标记的数据,而是关注已经标记的数据。学习任务需要一些时间来为模型提供简单的样本,并在训练过程中一点一点地增加样本的难度,类似于人类。对于不平衡的数据集,相反的策略工作得很好:我们为硬(罕见)实例分配更高的惩罚,以迫使模型学习它们。在实践中,这种先易后难的学习策略是由损失函数的选择来设定的。我鼓励你阅读这篇文章[4]来学习更多关于标记数据中的抽样技术。

本文的代码

https://github.com/bledem/active-learning

参考

[1] 人在回路机器学习:以人为中心的人工智能的主动学习和注释,Robert Monarch。

[2]巴特包勒德:https://oatml.cs.ox.ac.uk/blog/2019/06/24/batchbald.html

【3】深度主动学习的调查。、任&肖、昀&常、肖军&黄、王宝耀&李、陈志辉&陈、肖江&王、辛。(2020).https://arxiv.org/pdf/2009.00236.pdf

[4] 先学哪些样本:容易还是难?欧武,2021。https://openreview.net/pdf?id=pSbqyZRKzbw

[5] 通过期望改进最大化在 CNN 中主动学习。纳格帕尔,乌代。(2020).https://open access . the CVF . com/content _ WACV _ 2020/papers/Mayer _ Adversarial _ Sampling _ for _ Active _ Learning _ WACV _ 2020 _ paper . pdf

[6]https://www.youtube.com/watch?v=Yqj7Kyjznh4&t = 1260s&ab _ channel = deep learning ai

[7]https://venturebeat . com/2019/07/19/why-do-87-of-data-science-projects-never-make-it-into-production/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值