TowardsDataScience-博客中文翻译-2021-五十三-

TowardsDataScience 博客中文翻译 2021(五十三)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

如何使用方差阈值进行鲁棒特征选择

原文:https://towardsdatascience.com/how-to-use-variance-thresholding-for-robust-feature-selection-a4503f2b5c3f?source=collection_archive---------2-----------------------

即使删除 50 个功能,也能获得相同的性能

照片由 比勒 像素

方差阈值特征选择简介

如今,数据集拥有数百甚至数千个要素是很常见的。从表面上看,这似乎是一件好事——更多的特性提供了关于每个样本的更多信息。但通常情况下,这些额外的功能并不能提供太多的价值,而且会带来不必要的复杂性。

机器学习的最大挑战是通过使用尽可能少的特征来创建具有强大预测能力的模型。但是考虑到当今数据集的庞大规模,很容易忽略哪些特征重要,哪些不重要。

这就是为什么在 ML 领域需要学习一整套技能— 特征选择。特征选择是选择最重要特征的子集,同时试图保留尽可能多的信息的过程。

举个例子,假设我们有一个身体测量的数据集,比如体重、身高、身体质量指数等。基本的特征选择技术应该能够通过发现身体质量指数可以用体重和身高来表示而去掉身体质量指数。

在本文中,我们将探讨一种这样的特征选择技术,称为方差阈值。这种技术是一种快速和轻量级的方法,用于消除方差非常低的特征,即没有太多有用信息的特征。

https://ibexorigin.medium.com/membership

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

https://alphasignal.ai/?referrer=Bex

关于方差的一个注记

对于那些不熟悉的人来说,方差顾名思义,表示单个度量中分布的可变性。它显示了分布是如何展开的,并显示了与平均值的平均平方距离:

作者图片

显然,值越大的分布产生的方差越大,因为每个差值都是平方的。但是我们在 ML 中关心的主要事情是分布实际上包含有用的信息。例如,考虑这样的分布:

用 Numpy 计算方差向我们展示了这个分布的方差为零,或者说完全没有用。使用零方差特征只会增加模型的复杂性,而不会增加其预测能力。再考虑一个:

同样,这个几乎是由一个常数组成的。除了少数例外,围绕单个常数的分布也是无用的。换句话说,任何方差接近于 0 的特性或分布都应该被丢弃。

如何使用 Scikit-learn 的变量阈值估计器

手动计算方差并设定阈值可能需要大量的工作。幸运的是,Scikit-learn 提供了VarianceThreshold估算器,它可以为我们做所有的工作。只要超过一个临界值,低于该临界值的所有要素都将被丢弃。

为了演示VarianceThreshold,我们将使用Ansur 数据集。这个数据集以各种可以想象的方式记录了人体的尺寸。男性和女性数据集包含近 6000 名(4000 名男性,2000 名女性)美国陆军人员的 108 个特征或测量值。我们将关注男性数据集:

首先,让我们去掉零方差的特征。我们将从sklearn.feature_selection进口VarianceThreshold:

我们初始化它就像任何其他 Scikit-learn 估计器一样。阈值的默认值始终为 0。此外,估计器显然只对数字数据起作用,如果数据帧中存在分类特征,就会产生错误。这就是为什么现在我们将数字特征划分到另一个数据帧中的原因:

所以,我们有 98 个数字特征。现在让我们将估计值与数据进行拟合,并获得结果:

直接调用fit_transform将把数据帧作为一个numpy数组返回,去掉一些特性。但是有时,我们不希望结果是这种格式,因为列名会被删除。考虑替代方案:

首先,我们将估计器与数据进行拟合,并调用它的get_support()方法。它为没有被删除的列返回一个带有True值的布尔掩码。然后,我们可以使用此掩码来划分数据帧的子集,如下所示:

让我们检查数据帧的形状,看看是否有任何常量列:

>>> ansur_male_num.shape(4082, 98)

不,我们仍然有相同数量的功能。现在,让我们去掉方差接近于 0 的特性:

threshold为 1 时,只有 1 个特性被删除。

使用特征标准化进行更公平的方差比较

通常,比较一个特性与另一个特性的差异是不公平的。原因是随着分布中的值变大,方差呈指数增长。换句话说,方差不会在同一个尺度上。考虑这个例子:

上述特征都有不同的中位数、四分位数和范围-完全不同的分布。我们无法将这些特征相互比较。

我们可以使用的一种方法是通过将所有特征除以它们的平均值来归一化它们:

这种方法确保所有方差都在相同的范围内:

现在,我们可以使用阈值较低的估计值,如 0.005 或 0.003:

如您所见,我们能够从数据集中删除 50 个要素。现在,让我们通过放弃这么多特性来测试我们是否做了正确的事情。

我们将通过训练两个 RandomForestRegressor 来预测一个人的体重(以磅为单位)来检查这一点:第一个在最终的要素选择数据集上,第二个在完整的仅包含数字要素的数据集上。

训练和测试分数都显示了一个真正的高性能,而没有过度拟合。现在,让我们在全数字数据集上训练相同的模型:

如你所见,即使去掉 50 个特性,我们也能构建一个非常强大的模型。

结论

尽管方差阈值化是一种简单的方法,但在执行特征选择时,它可以走很长的路。但是,请记住,这种技术没有考虑特征之间的关系或特征与目标之间的联系。因此,要像使用 RandomForestRegressor 一样,反复检查使用 VT 是否带来了性能提升,或者至少降低了模型的复杂性。

此外,查看 Scikit-learn 关于特性选择的官方用户指南——在那里,您可以了解如何在管道实例中插入 VT 估算器。该指南还包含其他特征选择技术的信息。

如果你不知道接下来要读什么,这里,我为你挑选了一些:

https://towards data science . com/beginners-guide-to-xgboost-for-class ification-problems-50 f 75 AAC 5390

https://towards data science . com/11-times-faster-hyperparameter-tuning-with-halvinggridsearch-232 ed 0160155

https://towards data science . com/intro-to-sci kit-learns-k-nearest-neighbors-classifier-and-regressor-4228 D8 D1 CBA 6

如何使用带有 LightGBM 的 W&B 扫描进行超参数调整

原文:https://towardsdatascience.com/how-to-use-w-b-sweeps-with-lightgbm-for-hyperparameter-tuning-b67c3cac435c?source=collection_archive---------20-----------------------

了解不同超参数对模型性能的影响

超参数调整是建模过程中的一个重要步骤,可提高模型性能并自定义模型超参数以更好地适应数据集。使用网格、随机或贝叶斯搜索,有不同的有用工具和软件包帮助进行超参数调整。这些搜索函数返回在我们的数据集上用不同超参数训练的模型的输出,但是如何理解在不同超参数排列上训练的成百上千个模型的输出呢?

请允许我介绍一下权重&偏差,这是一个有用的 MLOps 平台,提供工具来帮助进行模型实验跟踪、模型性能可视化等等。W & B Sweeps 产品旨在帮助超参数调谐。一些要强调的功能包括贝叶斯优化,以优先搜索哪些超参数集,以及强大的可视化功能,以帮助您了解不同超参数的重要性。

在本文中,我将通过一个示例演示如何使用 W & B 扫描对通过 scikit-learn 获得的加州住房数据集上的 LightGBM 进行超参数调优。目标是训练一个回归模型,在给定 8 种不同特征的情况下,以 100,000 为单位估计加利福尼亚的房屋价值。

I .安装 W&B

创建一个关于重量&偏差的账户,并完成他们简单的注册过程。

然后,在您的 Python 环境中安装 W&B,将其导入到您的 Python 脚本或笔记本中,并初始化登录过程。

!pip install wandb
import wandb
wandb.login()

然后,系统会提示您输入 API 密钥,您可以在设置> API 密钥下登录后通过 W&B 网站访问该密钥。

二。定义模型训练函数

定义一个创建和训练模型的函数是很重要的,该函数将由 Sweep agent 在后面的步骤中使用。该功能将包含以下几个组件:

  • 设置默认配置:以字典的形式指定默认配置,在扫描过程中将被覆盖。
  • 启动 W & B: 初始化新的wandb运行。
  • 加载并分割数据集:记住为您的train_test_split函数添加一个种子,以便在不同的运行中进行一致的分割。
  • 训练模型:在训练集上拟合您的模型,并使用训练好的模型在测试集上进行预测。
  • 评估模型性能:评估训练好的模型做出的预测。在这种情况下,我选择使用mean_absolute_errormean_squared_error作为回归模型的度量。
  • 记录模型性能指标:使用wandb.log()将指标记录到 W & B 中。

以下是该模型训练函数的完整 Python 代码:

三。定义扫描配置

下一步是以字典的形式为 W&B Sweep 定义要执行的配置。这里要定义的一些参数包括:

  • method:指定您的搜索策略,例如贝叶斯、网格和随机搜索。
  • metric:定义指标的namegoal(最大化或最小化)作为优化的指标。例如,我选择均方误差(MSE)作为我的度量,目标是最小化这个度量。
  • parameters:定义作为字典关键字存储的要优化的超参数及其对应的值,以列表形式搜索,作为该字典的值存储。

超参数的结果配置及其相应的搜索值定义如下:

W&B 扫描的配置

参见第了解可定制的扫描配置的完整列表。

四。用 W&B 代理初始化并运行 Sweep

定义扫描配置后,我们就可以运行扫描了。首先初始化扫描以启动扫描控制器。将扫描配置字典和项目名称(字符串)作为参数传入初始化的对象,如下所示:

sweep_id = wandb.sweep(sweep=sweep_configs, project="california-housing-sweeps")

接下来,运行 sweep 代理,并将sweep_id和模型训练函数作为参数传入。您还可以提供一个可选参数来指定代理运行的总数count

wandb.agent(sweep_id=sweep_id, function=train_model, count=30)

动词 (verb 的缩写)可视化结果

完成扫描后,您可以返回到 W&B UI 查看结果。对我来说,两个最有用的可视化工具是超参数重要性图和平行坐标图。

超参数重要性图

您可以指定要优化的度量,该图表将显示哪些超参数最重要的排序结果。在我们的示例数据集中,迄今为止最重要的超参数是n_estimators,负相关性告诉我们,树较少的模型的预测具有较高的 MSE 分数。这是有意义的,因为树较少的模型可能不适合我们的数据集。

在加利福尼亚住房数据集上训练的 LightGBM 模型的超参数重要性图

平行坐标图

在 Kaggle 竞赛中,很容易从搜索函数返回的超参数中选择最佳的一组,因为您最关心的是优化您的分数,而不是过度拟合。

在现实中,当模型被用于做出对企业底线有影响的决策时,数据科学家应该并且将会关注优化偏差-方差权衡,以避免过度适应训练集。平行坐标图是一个非常强大的可视化工具,可以帮助您理解不同超参数集的组合效果。

从下面显示我们的示例数据集结果的图中可以看出,有几种不同的超参数组合可以将模型性能提高到大约 0.195 MSE 得分范围,这比带有默认超参数的 LightGBM 模型的基线 MSE 得分 0.208 要好。

在加州住房数据集上训练的 LightGBM 模型的平行坐标图

结论

W&B Sweeps 是一个强大的工具,可以帮助数据科学家进行超参数调整过程。可视化有助于理解不同超参数集对模型的影响,从而做出更有根据的猜测以选择超参数集来训练最终模型。要查看我的 python 笔记本,请点击 Github 上的链接

我希望这是有用的-请在下面留下任何评论。谢谢!

Python 中“yield”怎么用?

原文:https://towardsdatascience.com/how-to-use-yield-in-python-5f1fbb864f94?source=collection_archive---------13-----------------------

图片由 kangbchPixabay 拍摄

Python 生成器——从基本用法到高级用法

如果你是一个 Python 开发者,我相信你一定知道 Python 中的生成器。定义 Python 生成器的关键是使用“yield”关键字。Python 生成器在我们需要大量集合、提高代码可读性以及多线程等特定场景中无处不在。

你可能知道也可能不知道如何正确使用“yield”关键字。在本文中,我将从基本用法开始介绍 Python 生成器。一些更高级的使用模式也将在后面的章节中介绍。

1.基础

图片来自 PixabayPezibear

让我们在本教程中编一个例子。假设我们公司有一群人,需要一个个随叫随到。所以,这将是一个轮换的花名册。

names = ['Alice', 'Bob', 'Chris', 'David', 'Emily']

现在,我们想从这个名称列表中定义一个 Python 生成器。代码如下所示。

def gen_roster(names):
    for name in names:
        yield name

请注意,我们需要使用yield关键字而不是return,所以我们可以使用这个函数来制作一个生成器。

roster = gen_roster(names)

对,就是这样。如果你想检查变量roster的类型,下面是结果。

现在,我们有了roster。Python 生成器也是可迭代的,所以我们可以把它放在一个 for 循环中,一次获得所有的名字。

for name in roster:
    print(name)

2.得到下一个

来自 PixabayCouleur 的图像

好吧,在前面的例子中,在 for 循环中使用生成器没有太大的意义。使用生成器的好处是我们可以一次得到一个值。当我们处理一个巨大的集合时,这可能非常有用。也就是说,当我们创建一个生成器时,这些项不会被读入内存。只有当我们试图获取下一项并点击yield关键字时,该项才会生成。

因此,无论如何,获得生成器的“下一个”元素是很重要的。在这种情况下,我们可以使用它的__next__()函数。

roster.__next__()

其实我们也可以这样做,这样更直观,也更容易记忆。

next(roster)

你是否注意到当我们试图获取“下一个”项目时,“光标”被移动了?还记得我们在生成器的定义中定义了 for 循环吗?我们可以认为 for 循环将一次执行一次,直到到达关键字yield

这也意味着,我们的“光标”现在在第三个名字上。因此,如果我们试图输出所有剩余的项目,“Alice”和“Bob”将被跳过。

现在,“光标”在末尾。如果我们试图获取下一个项目,将会抛出一个错误,因为没有更多的项目。

这实际上不是我们想要的,因为花名册将被用来决定谁将在当前的轮换中待命。换句话说,我们希望“光标”回到开头,这样所有的名字将再次循环。

诀窍是简单地在 for 循环上面放一个while True语句。所以,一旦所有的名字都用完了,for 循环就会重新开始。

def gen_roster(names):
    while True:
        for name in names:
            yield name

现在,假设我们想要一个有 12 个名字的花名册。我们只有 5 名员工。因此,它们将被轮换。

for i in range(12):
    print(next(roster))

如果我们不输入数字“12”,生成器可以无限期地生成更多的名字。

3.发送一个值

图片由设计来自 Pixabay

生成器的一个高级用法是向生成器发送一个值。该值将成为当前产出表达式的结果,该方法返回生成器产出的下一个值。

所以,不要指望生成器会返回我们刚刚发送的值,因为它会返回下一个值。然而,我们可以用它在生成器内部做一些事情。例如,我们可以通过向一个无限生成器发送某个值来停止它。

def gen_roster(names):
    while names:
        for name in names:
            current_name = yield name
            if current_name == 'stop':
                names = None
                break

如果从外部发送一个值“stop ”,发生器将终止循环。因此,我们可以验证如下行为。

roster = gen_roster(names)for i in range(10):
    if i == 3:
        roster.send('stop')
    print(next(roster))

在上面的代码中,我们要求程序循环 10 次。然而,对于第四轮,我们将值“stop”传递给生成器。结果,只有 3 个名字被输出,并且发生器在第 4 轮停止,而不是循环 10 次。

当我们想在多线程编程场景中改变生成器的行为或规则时,send 方法将非常有用。

4.停止生成器—抛出异常并关闭

图片来自 Pixabay乔拉卡尔穆克

当出现问题时,我们可以使用throw()方法在生成器暂停的地方引发一个异常。我们可以自定义错误类型。在本教程中,出于演示的目的,为了方便起见,我将简单地使用一个“类型错误”。

roster = gen_roster(names)next_name = roster.throw(TypeError, 'Stop!')

如果没有出错,但我们仍然想终止生成器,我们可以使用close()方法生成一个生成器。当我们有一个无限大的生成器,并且我们想在某个点停止它时,这将是非常有用的。

roster = gen_roster(names)for i in range(10):
    if i == 3:
        roster.close()
    print(next(roster))

上面的代码在第四轮关闭了生成器“花名册”,所以当下一个循环试图获取下一个值时,异常被抛出。

摘要

图片来自 Pixabay拉尔夫·昆泽

在本文中,我介绍了 Python 中最重要的“Python 式”概念之一——生成器。关键字yield的用法是 Python 生成器的关键。

不仅介绍了基本用法,还介绍了一些高级用法,如从外部向生成器发送值、引发异常和关闭生成器。希望它能帮助你了解更多关于 Python 生成器的知识。

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

如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)

如何利用人工贴标劳动力

原文:https://towardsdatascience.com/how-to-utilise-a-manual-labelling-workforce-b30db3ab1e8e?source=collection_archive---------19-----------------------

从面试到任务定义再到评估

来自 PexelsLittlehampton Bricks 摄影

为什么需要手动贴标

为了生成机器学习模型,我们首先需要找到数据集来训练它。在许多情况下,我们可以依赖公共数据集(使用数据集搜索索引,如 GoogleKaggle 来找到我们需要的数据)。但是有些情况需要我们自己生成数据集(由于数据规模、隐私问题或者只是因为用例是一个利基),如果 ML 任务是由监督的,那么我们也需要负责标记数据集。通常,贴标将在内部开始,一旦发现所需的规模过大(可能从 POC 转移到 MVP ),手动贴标流程将被外包(使用贴标团队或专门的承包商)。一个常见的错误是假设在内部工作的东西会无缝地在外部工作。为了确保贴标过程的输出符合我们的期望,需要避免许多陷阱。从面试候选人,到正式工作,再到评估其质量。一次必要的步行就在前方。

开始收集数据

假设我们的任务是在图像中找到橙色的猫。第一步是搜索相关的现有数据集,但由于我们的用例是一个很小的领域(特别是橙色的猫),我们决定自己生成所需的数据集。我们首先从网上抓取相关图片(有橘猫的,没有橘猫的,一般图片)。一个常见的初始简化是依靠现有的开源图像分割库(如脸书的 Detectron 或谷歌的 DeepLab )来为图像生成初始标签。使用它,我们可以控制数据集主题的分布(以加强分层)。但是,当我们专门寻找橙色的猫时(这种开源库的常见输出将只是一只“猫”),我们决定雇佣一个标签工作团队来帮助我们满足这一需求。怎么做呢?。

橘猫和几个竞争对手。照片由 Pexelscottonbro 拍摄

面试

第一步是找到最适合我们需求的贴标机。令人惊讶的是,高分和漂亮的文凭并不总是与适合工作相关联。此外,我们最好的手工贴标机很少是大学生。虽然乍一看这似乎是反直觉的,但一个可能的解释是,贴标签需要特殊的特征,如注意力、自律、打破常规的思维和愿意为成功付出额外的努力(更不用说并非所有的贴标签任务都具有相同的复杂程度,因此每个任务都需要不同的技能水平)。这些特征很可能与高分有某种关联,但并不一定要结合在一起。这就是为什么面试过程应该调整,以更好地针对这些品质;更少的成绩过滤,更多的动手评估。聪明并不直接表明一个人擅长给猫贴标签。尽量确保你问的问题旨在衡量与标签工作的相关性。朝着这个方向迈出的一小步可以是使用类似手工贴标签的家庭作业。这将有助于对候选人是否适合这份工作做出公正而直接的评价。一次好的面试应该衡量所需的关键绩效指标(比如对重复性体力工作的意愿),以确保你接受的候选人能够完成所需的任务。

介绍需求

人工贴标在许多情况下是一次性项目,会导致使用范围外的员工,在许多情况下是承包商。这就是为什么倾向于透露尽可能少,降低你分享的背景,假设承包商明天可以为你的竞争对手工作。但这是一个错误,因为这种态度可能会降低贴标签者的参与度。可以很好地定义所需的任务,而不会泄露任何内部最高机密。解释需要什么以及为什么需要。给你的手工贴标员一种感觉,他们的工作是重要的,值得欣赏的。让他们成为你的伙伴。一个除了理解“是什么”之外还理解“为什么”的人,更有可能集中更多的注意力,通常会产生更好的结果。

正式确定任务

大多数情况下,第一个标记数据的是我们自己。在这个过程中,我们可能会遇到特殊的样本和异常的样本,因此我们生成了许多自由文本反馈字段(如关注或评论)来突出它。一旦我们需要向标签员介绍任务,倾向于保持相同的反馈字段结构。但问题是,对我们有用的东西可能会混淆超出范围的标签。因此任务定义应该尽可能清晰。封闭列表比自由文本字段更好。就像在我们的例子中,我们可以使用—[橙猫/非橙猫/非猫/?].同样重要的是要求贴标签者填写每个标签上下文(在我们的例子中,它可能是被识别物体的位置)。其中的两个主要原因是,提供上下文需要更多的关注,因为它可以实现快速的手动验证路径(奇怪的标签+有问题的上下文可以突出应该双重验证的样本。就像在我们的例子中,在根据我们用于分割的开放源代码应该出现“狗”的位置标记“橙色猫”的情况下)。‘?’重要的是为了让贴标签者 一个地方 承认他们不知道。例如,考虑一个图像包括橙色和黑色猫的场景。标签应该是什么?。上下文和“杂项”标签(“?”sign)将使贴标机能够以有效的方式标记需要再次检查的样品。错误很可能会发生。将标签输入与定义明确的上下文一起形式化,可以防止错误变得致命。

工作范围

试着把需要的工作分成小批,尤其是在开始的时候,让贴标签的人知道他们能处理好。从我们的经验来看,当一个文件被分割时,标签员比处理合并的文件(以更大的格式)表现出更好的性能。可能面对较小的文件没那么可怕,因此看起来是一个更容易完成的任务。随着时间的推移,文件越来越大。它会向贴标签者反映他们的进步,这是一种隐性的反馈来约束他们。更多的自信会让贴标签的人感觉更好,工作得更好,最终甚至超过你最初的标签,找到你甚至没有意识到的东西。

专家差距

在大多数情况下,你会发现并非所有的“要贴标签的”样本都具有相同的复杂程度;有些会比其他的更难标记。为了更好地利用您的劳动力,找到一种方法,将较容易贴标签的样品交给贴标机,将较难的样品留给您的专家。这一点很重要,因为专家的可用性非常有限,而且贴标机在处理过于复杂的样品时会变得绝望。将更难的样本与其他样本区分开来的一种常见方法是使用代理分类器,即使用已标记数据集的子集训练一个简单的分类器。这个分类器不会是分类器,而是一个通过查看其预测可能性来区分样本复杂性的工具(高可能性可以表示一个简单的标签样本应该被发送到标签器)。它还可以用来验证贴标员的工作(查看其输出与贴标员所说的有很大差异的地方)或以“主动学习”的方式;偶尔根据新标记的数据重新训练代理分类器,以突出接下来应该优先处理哪些样本。并非所有样本都同样重要,因此标记力应该指向更需要的地方,指向简单代理分类器未能处理的样本。

验证工作

在进入我们的数据集之前,应该验证带标签的数据。一种常见的方法是给几个贴标签的人相同的任务,然后通过查看标签不同的地方来验证他们的工作。但问题是,它包含一个隐含的失败点,因为潜台词是你不够信任你的标签。对我们来说,当我们尝试时,结果是如此不同,以至于它强调了这样一个事实,即我们有其他问题需要首先解决。内在的动机是把标签员带到一个你可以信任他们工作的地方,就像是你自己在做一样。这并不意味着工作不应该被验证——每个人都会犯错误。找到一种机制来验证贴标机的工作。例如,通过将他们的工作与代理分类器进行比较(像我们前面提到的图像分割工具或代理分类器)。它可以是一个简单的指南针,使您能够专注于需要更多手动验证的更复杂的情况。

反馈

没有人喜欢做不好的工作。尤其不是故意的。尤其是那些根据业绩得到明确奖励的承包商。因此,重要的是要突出标签的错误,以使他们能够改善。错误很可能会发生,尤其是在开始时,因为 data domain 是新领域,还不清楚要做什么和如何做。另一方面,不良标签在初始阶段最容易识别。这就是为什么初学者的错误应该与不适合工作区分开来。一个可能的指标可以是缺乏标记https://en.wikipedia.org/wiki/Repeatability#:~:text=Repeatability or test–retest reliability,the same conditions of measurement.&text=A measurement may be said,a pre-determined acceptance criterion.;犯错误是可以的,应该给出如何避免错误的指导。但是,如果同样的错误一再发生,那就麻烦了。如果错误看起来是随机的——相同的上下文有不同的标签,那么它应该敲响警钟。一个学习缓慢但愿意全力以赴的人比一个学习快速但对任务不够专注的人要好得多。

期末笔记

不要低估你的标签。将他们与事业捆绑在一起,让他们成为你的标签任务伙伴。不是所有的任务都是一样的,有些需要专家,有些更简单。但都需要适当的关注。一旦得到指导,标签劳动力可以成为你的模型成功所需的特殊调料。

如何正确利用特征重要性

原文:https://towardsdatascience.com/how-to-utilize-feature-importance-correctly-1f196b061192?source=collection_archive---------19-----------------------

特征重要性是特征选择的一部分,这是一种对抗维数灾难的有用方法。如何最大限度地利用它并使它发挥作用是数据科学家的基本工作。

来源:由 Unsplash 上的叶戈尔·迈兹尼克

为什么特写 Importance❓

在训练机器学习模型时,理想的事情是将训练特征浓缩到一组变量中,这些变量包含尽可能多的信息。这有三个原因。1,减少特征的数量意味着缩小维度,降低稀疏性,增加训练结果的统计显著性。如果我们有太多的特征,我们也需要足够多的样本来进行训练。2、减少稀疏度有助于防止过拟合问题(特征数量越多,模型变得越复杂,因此更容易过拟合)。3,这是显而易见的,是计算能力的有效节省,同时实现可接受的性能。

因此,特征选择是数据预处理的一个重要步骤。在流行的方法中,特征重要性是最流行的方法之一。然而,通过特性重要性选择特性并不总是一帆风顺的。做出正确的选择决定确实需要一些技巧。

然而,根据我的经验,我通常在进行其他数据清理、预处理步骤后使用特征重要性,如下所示。

数据预处理的典型步骤(来源:作者)

特征重要性包括什么?✋

有几种方法可以表达特征的重要性。它可以是表示特征相关性的分数(使用基于算法的特征重要性,例如基于树的随机森林,XGBoost,..)、从原始特征降维以将所有信息合成到一个更低的维度(像 Autoencoder 或 PCA),或者领域知识选择(又名基于自己知识的选择)。面对如此多样的选择,我们应该选择哪一个呢?即使我们选择使用 PCA,选择正确数量的剩余特征似乎也需要很大的努力。难道你不认为我们应该用特性重要性分数或者测试所有东西来看看哪个表现最好吗?

对,没错,测试一切才是准确答案。从我的经验来看,我通常会将基线设置为没有任何选择的原始模型,然后尝试不同退出率的 PCA 并检查度量。然后放弃原来的特性(主要是因为我想限制所需的收集数据量,以及在保持或提高性能的同时优化训练时间)。所以降维是我的第一选择,特征重要性是下一个重要步骤。但是只使用特性重要性分数并不是一个好的选择。让我告诉你为什么。

为什么不仅仅显示重要性分数🌓

特征重要性分数在这里是指从表示特征对目标特征的预测的权重或相关性的训练模型中生成的任何分数。

下面是基于 RandomForestRegressor 模型计算的随机森林的特征重要性分数(公式细节此处为),使用 SelectFromModel 选择特征(细节),以及排列分数(公式细节此处为)。用于演示的数据是 sklearn 中的加州住房。

特征重要性分数、排列分数和 SelectFromModel 结果(来源:作者)

看了上面的内容,您有多大把握决定只保留 MedInc 并删除其他(基于第一个图)或基于第二个图保留 MedInc、纬度、经度和 ave occupation,甚至只删除 AveBedrms 和 Population?如果我是你,我只会用这个做任何决定。为什么?因为放弃这个或那个并不能保证更好的性能,如果你无意识地选择,甚至会导致更差的性能。

预测结果(来源:作者)

排列分数的选择比原始数据集稍有改进。让我们看另一个使用波士顿数据集的实验(来源)。

波士顿房屋——特征重要性分数、排列分数和选择模型结果(来源:作者)

这看起来比加州的数据集更一致,不是吗?我想保留“RM”和“LSTAT”功能的决定现在更有信心了。让我们看看如果模型在这两个特征上被训练,性能如何变化。

预测结果(来源:作者)

这些选择中没有一个与原始模型的性能相当,这意味着减少要素在这里不起作用。这两个例子显示了如何减少特性数量的不同策略,度量或分数可以帮助我们做出决定。

“不,我们需要不同的方法!”

有一种方法可以更好地决定应该删除哪些功能。这种技术是传统的,但有效和全面的。

我们通过观察删除特征后模型的性能来决定。

首先,让我们一次放下一个功能,然后一个接一个地放下,测量它们的性能,并确定足够的极限或级别。

加州住房数据集(来源:作者)

种群数量、平均数量、种群数量平均数量中去掉任何一个,性能明显保持与原来相同的水平。然而,移除药物会令人惊讶地降低测试 MSE。

当从最不相关的特征到最相关的特征(基于特征重要性分数)累积删除它们时,我们可以清楚地看到,当删除纬度和它之前的其他特征时,序列 MSE 中的肘出现,但是在删除经度时,过拟合问题恶化。因此,我们更有信心将模型浓缩成四个特征:“经度”、“纬度”、“平均占有”、“平均占有”。

让我们来看看波士顿数据集。

波士顿住房数据集(来源:作者)

移除 RM、LSTATDIS 中的任何一个都会恶化性能,并且如果我们仅在模型中保留 RM、LSTATDIS ,则不仅训练 MSE 而且测试 MSE 都会显著提高。从这个看,我们可以决定保留 NOX,CRIM,DIS,LSTAT,RM

结论🗽

分数不是唯一的出路。仅使用分数来决定特征选择的方法似乎是主观的和经验性的。使用适当的方法就像为你的模型决定正确的度量标准。确切地知道你为什么这样做,以及它给模型带来了什么影响,是你的机器学习下一次成功的关键。

如何对成对相似性度量进行矢量化

原文:https://towardsdatascience.com/how-to-vectorize-pairwise-dis-similarity-metrics-5d522715fb4e?source=collection_archive---------7-----------------------

实践教程

一种简单的模式,用于对所有成对点的度量进行矢量化,如 L1 距离和交集。

您可以在 NumPy、PyTorch 和 TensorFlow 中使用相同的模式对一整类成对(dis)相似性度量进行矢量化。当数据科学或机器学习算法中的一个步骤要求您计算这些成对指标时,这一点非常重要,因为您可能不想在昂贵的嵌套 for 循环中浪费计算时间。

这种模式适用于任何时候,只要您能将成对计算分成两个不同的步骤:扩展和缩减。它同样适用于相似性度量,如两个框之间的交集/并集,以及不相似性度量,如欧几里德距离。这篇文章解释了这种模式,并通过两个真实的例子使其具体化。

成对相异矩阵的热图。

为简洁起见,我有时称“相似性”为相似和相异的简写。我有时也用“点”来表示我们可能在成对比较中使用的任何项目。例如,在计算机视觉中,编码为(x1, y1, x2, y2)的盒子可以被视为 4 维空间中的一个点。

我们为什么要计算成对相似度函数?

有几种数据科学和机器学习算法需要成对的相似性度量作为它们的步骤之一。事实上,scikit-learn 有一个完整的模块专门用于这种类型的操作。

以下是一些您可能想要计算成对指标的示例:

  • 比较点和质心。在聚类和分类中,将单个点与一组点的类均值进行比较是非常有用的。这些类平均值称为质心,它们本身就是点,这意味着比较是成对操作。
  • 创建二部分配的成本矩阵。在检测跟踪中,您通常希望通过相似性将新的检测分配给现有对象。匈牙利算法可以通过最小化总成本来创建这些分配,同时要求一个对象被分配给一个检测(最多),反之亦然。该算法输入是成本矩阵,其中每个元素是对象和新检测之间的差异。不相似性的例子可以是欧几里德距离或并集上交集的倒数。
  • 高斯过程 (GP)回归创建内核。高斯过程中的不确定性由一个函数来定义,该函数将任意点对之间的协方差参数化。使用 GP 进行推理需要为数据集计算成对协方差矩阵。最常见的协方差函数是平方指数。

为什么两两相似是瓶颈?

“成对”是指我们必须计算每一对点的相似性。这意味着计算将是O(M*N),其中M是第一组点的大小,N是第二组点的大小。解决这个问题的简单方法是使用嵌套的 for 循环。不要这样!众所周知,Python 中嵌套的 for 循环非常慢。

NumPy(以及它的兄弟 PyTorch 和 TensorFlow)的美妙之处在于,您可以使用矢量化将循环发送到优化的低级实现。编写快速、科学的 Python 代码主要是为了理解这些包的 API。

那么它是如何工作的呢?

通常,如果您想要对一组形状为(M, D)M D维点和一组形状为(N, D)N D维点之间的成对相似性度量进行矢量化,您需要执行两个步骤:

  1. 展开。利用广播在两个D维点之间进行元素运算,产生一个形状为(M, N, D)的扩展数组。
  2. 减少。使用聚合操作减少最后一个维度,创建一个形状为(M, N)的矩阵。

这很简单。有几件事需要注意:

  • 当您计算点矩阵与其自身之间的成对相似性时,M将与N相同。
  • 有时,您还会希望对相似性度量应用额外的基于元素的计算。这可以在任何时候进行,而不会弄乱结果。

让我们看几个例子,在这些例子中,我们计算点集和它们自身之间的成对相似性,以使这个过程更加具体。

两两曼哈顿距离

我们将从两两曼哈顿距离开始,或称 L1 范数,因为它很简单。然后我们来看一个更有趣的相似度函数。

两点之间的曼哈顿距离是差值的绝对值之和。假设我们有两个四维 NumPy 向量,xx_prime。计算它们之间的曼哈顿距离很容易:

import numpy as npx = np.array([1, 2, 3, 4])
x_prime = np.array([2, 3, 4, 5])np.abs(x - x_prime).sum()# Expected result
# 4

现在,我们将曼哈顿距离扩展到两两比较。设X为单位正方形的四个角:

X = np.array([
    [0, 0],
    [0, 1],
    [1, 1],
    [1, 0]
])

单位正方形上的点。

这些点中的任何一对之间的曼哈顿距离将是 0(如果它们相同)、1(如果它们共用一条边)或 2(如果它们不共用一条边)。比较点集与其自身的成对相异矩阵将具有形状(4, 4)。每个点得到一行,每个点得到一列。行和列的顺序将是相同的,这意味着我们应该沿着对角线得到 0,因为一个点和它本身之间的曼哈顿距离是 0。

让我们用一个嵌套的 for 循环,用简单的方法计算这些点和它们之间的成对曼哈顿距离:

manhattan = np.empty((4, 4))for i, x in enumerate(X):
    for j, x_prime in enumerate(X):
        manhattan[i, j] = np.abs(x - x_prime).sum()manhattan# Expected result
# array([[0., 1., 2., 1.],
#        [1., 0., 1., 2.],
#        [2., 1., 0., 1.],
#        [1., 2., 1., 0.]])

每个元素manhattan[i, j]现在是点X[i]X[j]之间的曼哈顿距离。很简单。

现在,让我们向量化它。我们需要的第一件事是一个扩展操作,它可以通过成对的点来创建一个(4, 4, 2)数组。减法适用于广播,所以这是我们应该开始的地方。

为了正确扩展,我们需要插入维度,以便操作数分别具有形状(4, 1, 2)(1, 4, 2)。这是可行的,因为 NumPy broadcasting 在维度中后退,并在必要时扩展轴。这将产生一个距离数组(4, 4, 2):

deltas = X[:, None, :] - X[None, :, :]
deltas.shape# Expected result
# (4, 4, 2)

现在我们已经创建了一组名为deltas的 4x4 的二维点。这个结果的工作方式是deltas[i, j, k]X[i, k] - X[j, k]的结果。这相当于在上面的嵌套 for 循环中赋值deltas[i, j, :] = x - x_prime

此时,我们可以自由地应用元素绝对值运算,因为它不会改变形状:

abs_deltas = np.abs(deltas)
abs_deltas.min()# Expected result
# 0

我们仍然需要执行减少步骤来创建(4, 4) L1 距离矩阵。我们可以通过对最后一个轴求和来做到这一点:

manhattan_distances = abs_deltas.sum(axis=-1)
manhattan_distances# Expected result
# array([[0, 1, 2, 1],
#        [1, 0, 1, 2],
#        [2, 1, 0, 1],
#        [1, 2, 1, 0]])

瞧啊。矢量化的成对曼哈顿距离。

顺便说一下,当 NumPy 操作接受一个axis参数时,通常意味着您可以选择减少一个或多个维度。因此,要从一个(4, 4, 2)增量数组到一个(4, 4)带距离的矩阵,我们通过将axis=-1传递给sum()方法对最后一个轴求和。-1是“最后一个轴”的简写。

让我们将上面的代码片段简化为一行代码,它在单位正方形上的所有点对之间生成成对的曼哈顿距离:

np.abs(X[:, None, :] - X[None, :, :]).sum(axis=-1)# Expected result
# array([[0, 1, 2, 1],
#        [1, 0, 1, 2],
#        [2, 1, 0, 1],
#        [1, 2, 1, 0]])

并集上的成对交集

既然您已经看到了如何对成对相似性度量进行矢量化,那么让我们来看一个更有趣的例子。并集上的交集(IoU)是两个方框重叠程度的度量。假设你有两个盒子,每个盒子都通过它的左上角(x1, y1)和右下角(x2, y2)来参数化。IoU 是两个方框的交集面积除以两个方框的并集面积。

YoloV3 模型中的预测框。来源:pjreddie.com

让我们使用从流行的 YoloV3 模型生成的盒子。我们将使用相对坐标,因此任何坐标的最大可能值为 1.0,最小值为 0.0:

bicycle = np.array([0.129, 0.215, 0.767, 0.778])
truck = np.array([0.62 , 0.141, 0.891, 0.292])
dog = np.array([0.174, 0.372, 0.408, 0.941])

一个盒子(x1, y1, x2, y2)的面积是(x2 - x1) * (y2 - y1)。所以如果你有两个盒子ab,你可以通过创建一个相交盒子(当它存在的时候)然后计算相交的面积,以及每个盒子的面积来计算 IoU。一旦你有了那个,借据就是intersection / (a_area + b_area - intersection)。如果这些框没有重叠(因为相交框不存在),结果将为 0;如果这些框完全重叠,结果将为 1。

下面是计算自行车-狗对和狗-卡车对的 IoU 的代码:

def iou(a, b):
    """
    Intersection over Union for two boxes a, b
    parameterized as x1, y1, x2, y2.
    """
    # Define the inner box
    x1 = max(a[0], b[0])
    y1 = max(a[1], b[1])
    x2 = min(a[2], b[2])
    y2 = min(a[3], b[3])
    # Area of a, b separately
    a_area = (a[2] - a[0]) * (a[3] - a[1])
    b_area = (b[2] - b[0]) * (b[3] - b[1])
    total_area = a_area + b_area
    # Area of inner box
    intersection = max(0, x2 - x1) * max(y2 - y1, 0)
    # Area of union
    union = total_area - intersection
    return intersection / unioniou(bicycle, dog), iou(dog, truck)# Expected result
# (0.2391024221313951, 0.0)

为了对 IoU 进行矢量化,我们需要分别对交集和总面积进行矢量化。然后,我们可以将 IoU 作为两个 mat 之间的逐元素运算来计算

首先,堆叠三个盒子,创建一个(3, 4)矩阵:

X = np.stack([
    dog,
    bicycle,
    truck
])
X.shape# Expected result
# (3, 4)

np.stack()操作通过添加一个新维度将多个 NumPy 数组放在一起。默认情况下,它会在开头添加一个维度。

接下来,计算所有框对的相交框的坐标:

x1 = np.maximum(X[:, None, 0], X[None, :, 0])
y1 = np.maximum(X[:, None, 1], X[None, :, 1])
x2 = np.minimum(X[:, None, 2], X[None, :, 2])
y2 = np.minimum(X[:, None, 3], X[None, :, 3])inner_box = np.stack([x1, y1, x2, y2], -1)
inner_box.shape# Expected result
# (3, 3, 4)

这是交叉点的扩展步骤。我们不能一步到位,因为内框是对应坐标之间的最大值,也是其他坐标之间的最小值。但是我们将结果堆叠起来,以表明这一步确实将结果扩展到了一个(3, 3, 4)数组。每个元素inner_box[i, j, k]是盒子i和盒子j相交的第k个坐标。

现在,计算内盒的面积:

intersection = (
    np.maximum(inner_box[..., 2] - inner_box[..., 0], 0) *
    np.maximum(inner_box[..., 3] - inner_box[..., 1], 0)
)
intersection.shape# Expected result
# (3, 3)

面积运算减少了最后一个维度。我们通过选择指数来手动减少,但我们仍在减少维度,就像我们对上面的sum(axis=-1)所做的那样。

我们需要做另一个成对的运算来得到成对盒子之间的总面积,但是这个有点不同。对于总面积,“点”不再是盒子,而是面积。也就是说,我们将在两组区域之间进行成对操作,而不是在两组(3, 4)盒子之间进行成对计算。尽管我们扩展了“点”这个术语,但模式与前面的例子是一样的。

首先,我们计算每个单独盒子的面积来创建面积矢量,然后我们用扩展步骤计算总面积:

a_area = (X[:, 2] - X[:, 0]) * (X[:, 3] - X[:, 1])
b_area = (X[:, 2] - X[:, 0]) * (X[:, 3] - X[:, 1])total_area = a_area[:, None] + b_area[None, :]
total_area.shape# Expected result
# (3, 3)

想象total_area有形状(3, 3, 1),其中每个元素total_area[i, j, 0]包含一对盒子之间的面积总和。NumPy 自动压缩最后一个维度,所以实际结果是(3, 3),我们不需要显式执行 reduce 步骤。

其余的 IoU 计算是在intersectiontotal_area矩阵之间按元素进行的。这类似于上面的单个盒子的情况:

union = total_area - intersection
intersection / union# Expected result
# array([[1\.        , 0.23910242, 0\.        ],
#        [0.23910242, 1\.        , 0.02911295],
#        [0\.        , 0.02911295, 1\.        ]])

注意,对角线元素都是 1(完美 IoU),非重叠元素都是 0。

结论

就是这样!在这篇文章中,我们讨论了什么是成对相似性,以及一些重要的用例。我们还谈到了为什么它会成为机器学习算法的瓶颈。然后,我们看到了矢量化这些成对相似性计算的一般方法:1)扩展和 2)缩减。如果你能把成对计算分成这两个步骤,那么你就能把它矢量化。您可以随意添加任何您可能需要的额外的基于元素的操作。这篇文章中的所有例子都使用了 NumPy,但是不要忘记你也可以在 PyTorch 和 TensorFlow 中使用这个技巧。

编程快乐!

如何用图数据库用 Python 可视化一个社交网络:Flask + Docker + D3.js

原文:https://towardsdatascience.com/how-to-visualize-a-social-network-in-python-with-a-graph-database-flask-docker-d3-js-af451db57330?source=collection_archive---------42-----------------------

实践教程

照片由艾莉娜·格鲁布尼亚Unsplash 拍摄

介绍

当您考虑 web 应用程序时,通常不会想到图形数据库。相反,大多数人只是走熟悉的路线,使用 SQL 数据库存储信息。虽然这对于大多数用例来说是完全可以接受的,但有时使用图形数据库会带来巨大的好处。在本教程中,我将向您展示如何使用 Flask 创建一个基本的 web 应用程序,将所有信息存储在一个图形数据库中。更准确地说,我们使用的是 Memgraph DB ,这是一个内存数据库,可以轻松处理大量信息并快速执行读/写指令。

我们的用例是一个社交网络图(为了方便起见,在代码中称为 SNG )代表用户和他们之间的联系。通常,这样的图将包含数百万个关系,并且对它们执行的算法不适合存储在关系数据库中的数据。

在本教程中,我将一步一步地向您展示如何自下而上地构建一个简单的 Python web 应用程序,以便您对所使用的技术有一个基本的了解。如果你不想在阅读教程的时候使用它,你也可以在这里找到所有的代码。如果您在本教程中有任何问题或有什么地方不适合您,请随时在标签为memgraphdbStackOverflow 上发帖。

马丁·格兰让(2014)。 La connaissance 是一个简历CC BY-SA 3.0

先决条件

因为我们正在构建一个完整的 web 应用程序,所以在开始之前,您需要安装一些工具:

  • 诗歌:Python 中的依赖管理和打包工具。它允许你声明你的项目所依赖的库,它将为你管理(安装/更新)它们。
  • Flask :一个非常强大的 web 框架,为你提供了用于 web 开发的工具、库和技术。Flask 应用程序可以小到一个网页,也可以大到一个管理界面。
  • Docker 和 Compose :一个开发、发布和运行应用程序的开放平台。它使我们能够将应用程序从基础设施(主机)中分离出来。如果您在 Windows 上安装 Docker,Compose 将已经包含在内。对于 Linux 和 macOS,请访问这个网站
  • Memgraph DB :一个本地完全分布式内存图形数据库,旨在处理企业级的实时用例。遵循快速启动页面上的 Docker 安装说明。虽然它是完全可选的,但我鼓励您也安装 Memgraph Lab ,这样您就可以直接在数据库上执行 Cypher 查询,并看到可视化的结果。

创建项目结构和处理依赖关系

有时候 Python 中的标准打包系统和依赖管理会让初学者感到困惑,所以我们决定使用诗歌。
要开始构建我们的项目结构,选择一个工作目录并运行:

poetry new sng-demo

现在,您应该有一个包含以下内容的目录:

sng-demo
├── pyproject.toml
├── README.rst
├── sng_demo
│  └── __init__.py
└── tests
   ├── __init__.py
   └── test_poetry_demo.py

在本教程中,我们不会使用测试功能,所以继续删除目录tests和文件README.rst

现在我们需要为我们的项目添加依赖项。假设我们将在 Docker 容器中运行应用程序,我们不需要在本地安装依赖项,只需要在容器中安装。复制文件[project.toml](https://github.com/g-despot/sng-demo/blob/master/pyproject.toml)[poetry.lock](https://github.com/g-despot/sng-demo/blob/master/poetry.lock),放在项目的根目录下。关于依赖项管理,我们需要做的另一件事是告诉 Docker 如何在启动时运行诗歌,这样它就可以在容器内安装/更新所有必要的依赖项。

将申请归档

在项目的根目录下创建两个文件,Dockerfiledocker-compose.yml。在Dockerfile的开始,我们指定 Python 版本,并指示容器安装 CMakepoemmgclient、pymgclient 。诗歌对于管理我们在容器内部的依赖关系是必要的,而 CMake 和 mgclient 对于 pymgclient 是必需的,pymgclient 是用于 Memgraph DB 的 Python 驱动程序。你不必太关注这部分,只需将代码复制到你的Dockerfile:

FROM python:3.7*#Install CMake*
RUN apt-get update && \
  apt-get --yes install cmake*#Install poetry*
RUN pip install -U pip \
  && curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
ENV PATH="${PATH}:/root/.poetry/bin"*#Install mgclient*
RUN apt-get install -y git cmake make gcc g++ libssl-dev && \
  git clone https://github.com/memgraph/mgclient.git /mgclient && \
  cd mgclient && \
  git checkout 5ae69ea4774e9b525a2be0c9fc25fb83490f13bb && \
  mkdir build && \
  cd build && \
  cmake .. && \
  make && \
  make install*#Install pymgclient*
RUN git clone https://github.com/memgraph/pymgclient /pymgclient && \
  cd pymgclient && \
  python3 setup.py build && \
  python3 setup.py install

接下来,我们用以下内容定义工作目录:

WORKDIR /app
COPY poetry.lock pyproject.toml /app/

第二个命令将使我们能够缓存项目需求,并且只在pyproject.tomlpoetry.lock改变时重新安装它们。

RUN poetry config virtualenvs.create false && \
  poetry install --no-interaction --no-ansi

我们不需要创建虚拟环境,因为我们的应用程序已经被隔离在 Docker 容器中。要禁用它,需要将virtualenvs.create设置为假。
命令中的第二行确保了在安装/更新依赖项时,poem 不会问我们任何交互问题,这使得输出更加日志友好。

COPY . /app
EXPOSE 5000
ENTRYPOINT [ "poetry", "run" ]

这是我们在容器中创建所有目录和文件的地方。EXPOSE命令通知 Docker 容器在运行时监听指定的网络端口。

接下来,我们需要创建一个docker-compose.yml文件。 Compose 是一个定义和运行多容器 Docker 应用的工具。使用 Compose,您可以使用 YAML 文件来配置应用程序的服务。然后,只需一个命令,您就可以从您的配置中创建并启动所有服务。对于我们的项目,我们需要两个服务。一个是 web 应用程序(sng_demo),另一个是数据库实例(memgraph)。

如果您正确遵循了如何使用 Docker 设置 Memgraph DB 中的说明,您只需将以下代码添加到您的docker-compose.yml文件中即可运行容器:

version: '3'
services:
  memgraph:
    image: "memgraph"
    ports:
      - "7687:7687"
  sng_demo:
    build: .
    volumes:
      - .:/app
    ports:
      - "5000:5000"
    environment:
      MG_HOST: memgraph
      MG_PORT: 7687
    depends_on:
      - memgraph

说到ports键,在主机 _ 端口集装箱 _ 端口之间有一个重要的区别。密钥中的第一个数字是主机端口,它可用于从您的主机连接到服务(例如使用 Memgraph Lab )。第二个数字指定了用于服务对服务通信的容器端口。更准确地说,我们的服务sng_db可以使用这个端口访问服务memgraph并连接到数据库。

environment键包含代表服务容器中环境变量的MG_HOSTMG_PORT。它们存储建立数据库连接所需的memgraph服务地址和端口。depends_on键用于按照依赖顺序启动服务,因为我们需要数据库在 web 应用程序之前启动。

build键允许我们告诉 Compose 在哪里找到构建指令以及构建过程中使用的文件和/或文件夹。通过使用volumes键,我们绕过了不断重启映像以从主机加载新更改的需要。

最后,我们有一个利用诗歌的项目!这种方法非常适合开发,因为它使我们能够在完全不同的操作系统和环境上运行我们的项目,而不必担心兼容性问题。

使用 Flask 进行 Web 开发

Flask 使用起来非常简单,所以为什么不创建一个 Hello World 呢!尝试我们的 Docker+诗歌设置。
在项目根目录下创建一个名为app.py的文件,代码如下:

from flask import Flask

app = Flask(__name__)

@app.route('/')
@app.route('/index')
def index():
   return "Hello World"

首先,我们导入 Flask 类,然后创建它的一个实例。route()装饰器告诉 Flask 哪个 URL 应该触发我们的函数。现在,我们需要告诉 Docker 如何运行我们的应用程序。这可以通过在项目根目录中创建一个简单的脚本来完成。姑且称之为start.sh:

#!/bin/bash
export FLASK_APP=app.py
export FLASK_ENV=development
flask run --host 0.0.0.0

FLASK_ENV设置为development将启用调试模式。这使得 Flask 使用交互式调试器和重装程序。
FLASK_APP设置为app.py指定如何启动应用程序。
我们需要告诉 Docker 何时以及如何运行该脚本,因此将以下代码放在您的Dockerfile中的EXPOSE 5000行之后:

ADD start.sh /
RUN chmod +x /start.sh

命令chmod +x通过设置正确的权限使脚本可执行。
要执行该脚本,请在行ENTRYPOINT [ "poetry", "run" ]后添加以下命令:

CMD ["/start.sh"]

就是这样!我们的第一个网页已经准备好了,所以让我们开始我们的应用程序,以确保我们没有任何错误。
在项目根目录下执行:

docker-compose build

第一次构建需要一些时间,因为 Docker 必须下载和安装许多依赖项。
运行完毕后:

docker-compose up

我们的 web 应用程序的 URL 是 http://localhost:5000/ 。当你打开它时,应该会有一条信息你好,世界!这意味着应用程序已启动并正在运行。

现在是时候创建一个更复杂的网页来包含我们的社交网络图了。在项目根目录下创建一个名为templates的文件夹,并在其中创建一个名为base.html的文件。这将是我们其他页面的基本 HTML 模板。复制代码:

<!doctype html>
<html lang="en"><head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    <link rel="stylesheet" href="/static/css/style.css"><script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
    <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script><title>Social Network Graph Demo</title>
</head><body>
    {% block content %} {% endblock %}
</body></html>

我们还需要为实际的登录站点创建一个 HTML 文件,利用这个基本文件和一个附带的 JavaScript 文件。在相同位置创建名为index.html的 HTML 文件,并将以下代码复制到其中:

{% extends 'base.html' %} {% block content %}
<div class="container">
  Hello World!
</div>
<script src="/static/js/index.js" charset="utf-8"></script>
{% endblock %}

在项目根目录下创建一个名为static的文件夹,其中一个子文件夹名为js,另一个名为cssjs文件夹将包含所有需要的本地 JavaScript 文件,而css文件夹将包含所有 CSS 样式表。在js文件夹中创建一个名为index.js的文件,在css文件夹中创建一个名为style.css的文件。暂时让它们空着。

如果你想了解更多关于 Flask 的 web 开发,我建议你试试这个教程。
你目前的项目结构应该是这样的:

sng-demo
├── sng_demo
│  └── __init__.py
├── templates
│  └── index.html
├── static
│  ├── css
│  │  └── style.css
│  └── js
│     ├── base.html
│     └── index.js
├── app.py
├── docker-compose.yml
├── Dockerfile
├── poetry.lock
├── pyproject.toml
└── start.sh

数据模型和数据库连接

在 app 目录sng-demo中创建一个名为database的文件夹。该文件夹将包含我们与数据库通信所需的所有模块。你可以在这里找到它们,然后复制它们的内容。它们与数据库驱动程序密切相关,如果你想更深入地研究它们,我建议你在这里查阅驱动程序文档。在 app 目录sng-demo中创建模块db_operations.py。这是所有自定义数据库相关命令的位置。
sng_demo目录应该是这样的:

sng_demo
├── __init__.py
├── db_operations.py
└── database
   ├── __init__.py
   ├── memgraph.py
   ├── connection.py
   └── models.py

我们将使用一个非常简单的数据模型,以后可以很容易地升级。
标签为User的节点只有一个,每个User都有两个属性,一个数字id和一个字符串name。节点用类型FRIENDS的边连接:

作者图片

有几种方法来填充我们的数据库(这里有更多的),但是我们将通过执行 Cypher 查询来手动完成,这样您可以更好地理解如何与数据库通信。您将在文件[data_big.txt](https://github.com/g-despot/sng-demo/blob/master/resources/data_big.txt)[data_small.txt](https://github.com/g-despot/sng-demo/blob/master/resources/data_small.txt)中找到填充数据库所需的所有查询。前者只是拥有比后者更大的数据集。在项目根目录下创建一个名为resources的文件夹,并将文件放入其中。现在,您可以向您的 web 应用程序添加一个导入方法。
db_operations.py模块中添加以下导入和方法:

import jsondef clear(db):
  command = "MATCH (node) DETACH DELETE node"
  db.execute_query(command)def populate_database(db, path):
  file = open(path)
  lines = file.readlines()
  file.close()
  for line in lines:
      if len(line.strip()) != 0 and line[0] != '/':
          db.execute_query(line)

方法clear()在填充之前删除任何可能留在数据库中的数据。
方法populate_database()读取指定文件中的所有密码查询并执行它们。
在模块app.py中将导入和方法index()改为:

from flask import Flask, render_template, request, jsonify, make_response
from sng_demo.database import Memgraph
from sng_demo import db_operationsapp = Flask(__name__)@app.route('/')
@app.route('/index')
def index():
    db = Memgraph()
    db_operations.clear(db)
    db_operations.populate_database(db, "resources/data_small.txt")
    return render_template('index.html')

现在,每次我们刷新索引页面时,数据库都会被清空并用新数据填充。虽然这不适合生产阶段,但在开发过程中非常有用,因为它使我们能够在不重启整个应用程序或直接处理数据库的情况下更改数据。
如果您想在继续之前检查图形,我建议您打开 Memgraph Lab 并运行查询MATCH (n1)-[e:FRIENDS]-(n2) RETURN n1,n2,e;
结果应该是:

作者图片

我们的应用程序中还需要一个方法,在客户端请求时从数据库中获取所有相关数据。
姑且称之为get_graph(),将其放入db_operations.py模块:

def get_graph(db):
   command = "MATCH (n1)-[e:FRIENDS]-(n2) RETURN n1,n2,e;"
   relationships = db.execute_and_fetch(command)

   link_objects = []
   node_objects = []
   added_nodes = []
   for relationship in relationships:
       e = relationship['e']
       data = {"source": e.nodes[0], "target": e.nodes[1]}
       link_objects.append(data)

       n1 = relationship['n1']
       if not (n1.id in added_nodes):
           data = {"id": n1.id, "name": n1.properties['name']}
           node_objects.append(data)
           added_nodes.append(n1.id)

       n2 = relationship['n2']
       if not (n2.id in added_nodes):
           data = {"id": n2.id, "name": n2.properties['name']}
           node_objects.append(data)
           added_nodes.append(n2.id)
   data = {"links": link_objects, "nodes": node_objects}

   return json.dumps(data)

首先,我们需要执行密码查询MATCH (n1)-[e:FRIENDS]-(n2) RETURN n1,n2,e;并从数据库返回结果。这些结果将包含图中的所有边以及连接到这些边的所有节点。没有连接的节点不会被返回,现在还可以。

结果(对象relationships)是生成器的形式,我们可以通过使用初始查询中指定的节点/边名(n1n2e)迭代并访问其内容。
我们还需要检查一个节点是否已经被添加到node_objects列表中,因为多条边可以包含(指向或来自)同一个节点。所有对象都存储在适合以后 JSON 转换的键值对中。
最终结果是一个 JSON 对象,包含:

  • links:图中作为sourcetarget id 属性对的所有关系,
  • nodes:图中与其他节点形成关系的所有节点。

在您的app.py模块中添加以下方法:

@app.route("/get-graph", methods=["POST"])
def get_graph():
   db = Memgraph()
   response = make_response(
       jsonify(db_operations.get_graph(db)), 200)
   return response

该方法负责响应来自客户端的 POST 请求。它返回我们在前面的方法中从服务器获取的图形数据。

现在让我们用这些数据做点什么吧!从这里复制您的index.js文件的内容,从这里复制style.css文件的内容。
我们还需要将实际的 SVG 图形添加到页面中,因此将index.html文件改为:

{% extends 'base.html' %} {% block content %}
<div class="container">
    <svg class="border rounded mt-3" width="960" height="600" style="background-color:white"></svg>
</div>
<script src="/static/js/index.js" charset="utf-8"></script>
{% endblock %}

我不会详细介绍如何使用 D3.js ,所以如果你想了解更多,我鼓励你访问他们的网站

简而言之,我们从数据库中获取所有的节点和边,并将它们添加到一个 SVG 元素中。图形的可视化表示是通过模拟物理力如何作用于粒子(电荷和重力)来实现的。您可以拖放节点,将鼠标悬停在节点上以查看其 name 属性的值,放大和缩小图形以及移动 SVG 图形。

作者图片

附加功能

继续将文件[query.js](https://github.com/g-despot/sng-demo/blob/master/static/js/query.js)复制到目录static/js并将[query.html](https://github.com/g-despot/sng-demo/blob/master/templates/query.html)复制到目录templates。你可以在这里找到更新后的base.html文件。从 db_operations.py 模块和 app.py 模块中复制必要的方法。
完成更改后,只需打开http://localhost:5000/query/即可看到结果。如果你想调试从服务器上获取的数据,这个页面会让你的生活变得更容易。它返回所有节点或边,并以 JSON 突出显示的格式显示它们。

作者图片

您当前的项目结构应该是这样的:

sng-demo
├── resources
│  ├── data_big.py
│  └── data_small.txt
├── sng_demo
│  ├── __init__.py
│  ├── db_operations.py
│  └── database
│     ├── __init__.py
│     ├── memgraph.py
│     ├── connection.py
│     └── models.py
├── templates
│  ├── base.html
│  ├── index.html
│  └── query.html
├── static
│   ├── css
│   │  └── style.css
│   └── js
│      ├── index.js
│      └── query.js
├── app.py
├── docker-compose.yml
├── Dockerfile
├── poetry.lock
├── pyproject.toml
└── start.sh

结论

尽管图形数据库已经存在了很长时间,但是它们仍然没有被认为是软件开发中的主流工具。关系数据库管理系统将数据建模为一组预定的结构。当数据集变得过于相互关联时,复杂连接和自连接是必要的。现代数据集需要技术上复杂的查询,这些查询在实时场景中通常非常低效。

图形数据库为许多现实世界的问题提供了强大的数据建模和分析能力,如社交网络、业务关系、依赖关系、运输、物流…它们已被许多世界领先的科技公司采用。通过这篇教程,我希望让你明白在你的开发过程中集成一个图形数据库是多么容易,我鼓励你自己去尝试一下。

正如我在开始时说的,欢迎在标签为memgraphdbStackOverflow 或我们的官方论坛上向我们提出任何关于本教程或 Memgraph 的问题。祝你的编码好运!

作者图片

如何有效地可视化数据

原文:https://towardsdatascience.com/how-to-visualize-data-usefully-5d32e9531c56?source=collection_archive---------35-----------------------

一个好的数据可视化应该是什么样的?首先,它应该是有用的

图片由作者提供,截图来自https://youtu.be/hfXqgH2RscE?t=132

有用的数据可视化应该服务于一个目的

对于有用的东西,它应该有一个目的。

如果我们在创建一些图表或表格时头脑中没有一个目的,它们注定是没有用的,因为你从未期望它们做任何事情。这些生成的图表只是图表库的 API 调用输出。

我能想到图表/表格的三种常见用途:

  1. 探索:了解数据集,发现规律
  2. 解释:突出一个模式,提出一个理论,提示一个行动
  3. 打动:逗人开心,激起好奇心

如果我们想让数据可视化对不同的目的有用,需要注意不同的事情。

目的 1:探索

如果我们可视化的目的是探索数据,让自己轻松是你应该关心的最重要的事情。我们正在可视化的数据集很可能是我们不太熟悉的数据集,目标是发现我们不知道的东西,或者找到我们怀疑为真的一些想法的证据。

如果你不能轻松地从不同角度研究数据集,你就不会。

有用地探索数据的 3 个原则

  1. 做得又快又脏
    做得又快又脏意味着我们不需要太担心“外观”(例如数字格式、跨支线剧情的轴一致性、清晰的标签),只要它不会“挫败目的”,即从一个不熟悉的数据集中发现模式。微软 Excel 是最受欢迎的选择,现在是 Jupyter 笔记本/实验室。都抱着这种又快又脏的心态。
    也就是说,如果它变得太脏,你不再明白你的图表在显示什么,那么它就不再有用。所以需要在速度和干净之间取得平衡(例如,使用变量名、数字格式、复制图表的容易程度)。
  2. 使用支持生成交互式图表的图表库。使用交互式图表浏览数据比静态图表“更快”,因为您可以通过放大/缩小交互式图表来创建另一个静态图表,或者通过取消选中图例来排除某些组。Plotly 是这方面的一个很好的库。

使用交互式图表库加速数据浏览。来源:图片由作者提供,截图来自https://plotly.com/

3.显示更多相关字段

主图表区通常最多显示 3 到 4 个维度(通过 x 轴、y 轴、颜色、大小),但是数据集通常有比这多得多的列。当我们浏览数据集时,在一个视图中查看更多维度的数据可以帮助我们更容易地发现模式。在工具提示中显示这些额外的维度(即当鼠标悬停在数据上时弹出的窗口)会很有用。在 Plotly express(Plotly 的高级包装器)中,我们可以通过传入 hover_data 参数在工具提示中显示额外的数据字段。

使用工具提示在上下文中添加额外数据。来源:图片由作者提供,截图来自https://plotly.com/

目的 2:解释

如果我们可视化的目的是解释,那么让其他人容易理解是关键。当你探索数据时,我们可能已经发现了一些模式/想法,现在我们希望其他人看到相同的模式/想法并同意你,让那些人成为你的老板/媒体读者。

为此做一个有用的可视化, 不要让你的观众认为

这意味着你的视觉化应该是“不证自明、显而易见、不言自明的。读者应该能够“理解”它——它是什么以及如何阅读它——而不需要花费任何精力去思考它。”[2]

如何不通过可视化数据来分享想法

假设你的朋友分享了一个 Youtube 视频给你,你点击了链接,视频看起来是这样的:

图片由作者提供,截图来自https://youtu.be/hfXqgH2RscE?t=132

您很难观看该视频,因为它:

  • 没有标题
  • 字幕:韩语(假设你不懂韩语)
  • 展示了很多你不懂的视频统计数据,还挡住了被采访女士的脸
  • 视频分辨率:144p
  • 时间格式:1617559134 / 1617559734(奇怪的 Unix 时间戳格式)

创建一个类似上面 Youtube 视频的图表非常容易。通常使用默认设置就可以了。

一个好的图表应该像 Youtube 视频一样

如果你不想让你的解释性图表在你的观众面前看起来像那个奇怪的视频,记住:

  • 给标题帮助观众理解图表是关于什么的
  • 添加注释,使用观众能够理解的语言
  • 删除隐藏你想法主题的不必要的细节
  • 使其视觉清晰
  • 使用观众无需大脑额外处理就能理解的数字格式

可视化:坏与好。图片由作者提供,截图来自https://youtu.be/hfXqgH2RscE?t=132

尽一切努力消除混淆,让观众在视觉上和精神上容易阅读。

目的 3:留下深刻印象

Github 登陆页[3]里的地球仪看起来很酷吧?

https://github.com/home,来源:图片来自https://github . blog/2020-12-21-how-we-build-the-github-globe/

这是一个 three.js 可视化视图,显示 Github 中的 pull 请求活动,蓝色尖峰表示打开的 pull 请求,粉色弧线表示合并的 pull 请求。

没有人会查看这个登录页面来发现世界各地的拉请求模式,也没有人试图告诉我们 github 用户如何使用该网站的理论。因此,即使没有脚注来解释蓝色尖峰和粉色弧线是什么也没关系。在某种程度上,如果它是可视化的硬编码数据,甚至是假数据,我也没问题[4]。

最重要的是,它确实达到了目的——给人留下深刻印象。好看。如果你不是 Github 的用户,你可能会注册来了解这个网站上发生了什么。你还能从登录页面上要求什么呢?

摘要

要实现有用的数据可视化:

  1. 在头脑中有一个目的用于可视化(3 个常见目的)
  2. 请注意,不同目的的可视化会有不同的事情需要关注
  3. 试着设身处地为观众着想。这个观众可能是你自己,也可能是其他人,这取决于可视化的目的。

— — — — — — — — — —

笔记

[1]这篇文章的灵感来自保罗·格拉厄姆的随笔 如何写出有用地 。重要+新颖+正确+有力,是一篇好文章的秘诀

[2]摘自史蒂夫·克鲁格的《不要让我思考》,这是一本关于网络和移动可用性的必读书籍。购买该书的附属链接:https://amzn.to/3fGlosB

[3] Github 做了一个博客解释了这个可视化的背景和技术细节,见https://Github . blog/2020-12-21-how-we-build-the-Github-globe/

[4]当然不是,但也不是实时数据,见https://github . blog/2020-12-21-visualizing-githubs-global-community/

Youtube 上的视频是 https://www.youtube.com/watch?v=hfXqgH2RscE 的,我刚刚得知 Youtube 上有 4k 视频。

如何在 Python 中将数据库可视化为网络图

原文:https://towardsdatascience.com/how-to-visualize-databases-as-network-graphs-in-python-2ce3851f8458?source=collection_archive---------6-----------------------

实践教程

构建一个 Dash web 应用程序,以交互方式探索数据库结构。

geralt ( Pixabay )原创图片。由作者编辑。

在工作中,我最近面临的挑战是,必须分析一个 SQL 数据库的数据模型,该数据库由 500 多个表和数千个关系组成。在这个比例下, phpMyAdmin 内置的可视化功能不足以深入了解结构。我需要的是一个工具,在这个工具中,我可以应用各种过滤器(例如,表和列的名称、行数、连接数),然后以一种易于理解的可视化方式查看过滤后的表及其关系。所以,我决定用 Python 来构建这样一个工具。

注意,为了简洁和关注重点,我没有在这里提供完整的代码(大约 1000 行)。此外,我删除了注释行,以保持代码部分简短。

获取数据

为了可视化数据库的结构,我们首先需要获得表和列名以及主键和外键的数据。幸运的是,SQL 数据库提供了一个非常好的信息源:信息模式。这是一个元数据库,即描述其他数据库的数据库——不是它们的内容,而是它们的结构、约束、数据类型等等。它由许多表格组成,但我们只需要其中的三个:

:从这里我们得到所有表的名称、它们所属的数据库(模式)、它们的行数以及描述这些表的可选注释。

:这个表告诉我们所有表中每一列的列名,以及它属于哪个数据库和表。此外,我们可以获得数据类型、默认值和描述列的注释。

KEY_COLUMN_USAGE :对于我们的目的来说,这是最重要的表。它告诉我们这些表是如何连接的,也就是说,对于从一列到另一列的每个引用,它都包含一条记录。此外,它还标识主键列。

我决定使用我对数据库的 phpMyAdmin 访问以 JSON 格式导出这三个表。当然,您也可以直接访问信息模式(例如使用 sshtunnelsqlalchemy ),但是我想要一个离线工作的解决方案。以下代码将信息模式表中的数据加载到 pandas (作为pd导入)数据框中。

由于 JSON 导出的结构(该文件包含我们不感兴趣的标题),我们需要提取数据列并删除空行。然后,我们用数据帧的第一个单元中包含的数据制作一个新帧。结果数据框包含的数据与 JSON 文件被传递给函数load_from_json的信息模式表中的数据相同。

现在我们使用这个函数从上面描述的信息模式表中获取表、列和引用的数据。我们从表开始。

通过 pandas 数据框的iterrows函数,我们循环遍历所有行,每一行都给我们一个表的名称、数据库(模式)、注释和行数。最后两行值得解释一下:information_schema是一个模块,我在其中定义了存储表、列及其关系的结构。使用information_schema.Table(...),我们创建了一个对象,收集特定表上的所有数据,最后一行代码将该表添加到一个TableCollection对象中,如下所示:

在这个表集合中,表对象存储在一个字典中,该字典使用一个由数据库(模式)名和表名组成的元组作为键(同一个表名可能在多个数据库中使用)。

现在我们已经拥有了TableCollection结构中的所有表,是时候添加关于列的信息了,我们从信息模式的表的 JSON 导出中加载这些信息。

同样,我们遍历所有的行,每一行都描述一个表的一列,我们已经加载了该表的名称等。在最后两行中,我们创建了一个存储特定列属性的对象,然后将这个information_schema.Column对象添加到它所属的表中,方法是将它传递给属于表集合中适当字典条目的函数。

现在我们在TableCollection对象中有了关于表及其列的信息。仍然缺少的是关于主键和外键的信息,我们从信息模式的 KEY_COLUMN_USAGE 表中获得这些信息。

KEY_COLUMN_USAGE 的“CONSTRAINT_NAME”列中,作为其所属表中主键的列由值“primary”标记。我们使用这个信息来设置Column对象的相应属性is_primary。如果列是外键,则引用的数据库、表和列在“REFERENCED_TABLE_SCHEMA”、“REFERENCED_TABLE_NAME”和“REFERENCED_COLUMN_NAME”中指定。这些数据被添加到上面代码最后一行的Column对象中。

创建图表

如果你不熟悉图论:图是一种数学结构,由一组对象(节点)和这些对象之间的一组连接(边)组成。这样的结构正是我们探索数据模型所需要的:表将是图的节点,表之间的引用将是图的边。

我们将使用 networkx 包来创建图形,这需要四个步骤:

  1. 导入包:import networkx as nx
  2. 初始化一个图形对象,例如:g = nx.Graph()
  3. 使用g.add_node(node)添加节点,其中node可以是除None之外的任何可散列对象。我们还可以传递被解释为节点属性的关键字参数。
  4. 使用g.add_edge(node_1, node_2)在节点之间添加边,也可以选择使用包含边属性的关键字参数。请注意,原则上可以跳过第 3 步,因为如果边不存在,节点会自动与边一起创建。

但是我们还没有完成图表的构建。我们还想在以后操作它(记得我处理了 500 多个表,需要应用过滤器),为此我们编写了GraphManipulator类:

在实例化一个GraphManipulator对象时,一个图形对象被创建。注意,我们在这里使用DiGraph()(networkx包作为nx导入),这创建了一个有向图,也就是说,当创建一条边时,两个连接节点的顺序很重要。我们这样做是为了以后可以绘制从引用表指向被引用表的箭头。

load函数将我们的TableCollection对象作为参数,因此GraphManipulator对象可以访问我们从信息模式中获得的数据。然后,由名称以下划线开头的三个函数构建图形,最后保存图形对象的副本,以便在使用过滤器后恢复它(稍后将详细介绍)。让我们来看看构建图形的三个函数。

我们从节点开始:

上面的代码遍历所有表,这些表的信息存储在TableCollection对象中(这里是self.tables)。函数_build_node_id只是返回一个由数据库名和表名组成的字符串。该字符串对于每个表都是唯一的,并用作节点对象。使用tab.get_foreign_keys(),我们得到了表中充当外键的列的列表,也就是说,它们引用了其他表的主键列。

接下来,我们遍历列表f_keys中的所有外键,为每个外键在列表references中添加一个字符串。该字符串包含被引用列的数据库(模式)、表和列名。最后,我们将所有感兴趣的属性(比如我们刚刚编译的引用列表)放入attributes字典,并在我们的图中添加一个附加了这些属性的节点。请注意,两个方向上的边数(字典中的最后两个条目)是稍后设置的。

现在我们有了所有的节点,是时候给我们的图添加边了。

同样,我们遍历所有的表,并对每个表遍历所有包含的列。最里面的循环查看一个列的所有引用(一个列可能引用几个其他列)。上面代码的最后一行向 graph 对象添加了一条从引用列指向被引用列的边(记住,这里有一个有向图)。

我认为在节点属性中同时包含给定表对其他表的引用数和其他表对该表的引用数会很有用。

我将这些属性命名为N_edges_downstreamN_edges_upstream,并使用 graph 对象的number_of_edges函数获取它们的值,如上所示。正如您在代码中看到的,访问节点属性很容易:graph.nodes[name_of_node]['name_of_attribute']。现在我们的图表完成了,我们可以把它可视化了。但在此之前,我们先简单谈谈过滤。

按节点属性过滤

正如我在本文开头所说的,我正在处理一个包含 500 多个表的数据库。显然,对于大多数人脑来说,这些信息太多了,无法一次全部吸收。因此,我为我的 Python 脚本配备了过滤选项。原理很简单,包括以下步骤:

  1. 将我们在构建图表后保存的图表备份复制到图表对象,如下:self.graph = self.graph_backup.copy(as_view=False) 这是必要的,因为我们想要将过滤器应用到原始图表,而不是已经过滤的图表。
  2. 遍历图中的所有节点。
  3. 将节点属性与您的过滤标准进行比较,如果有任何比较表明节点不符合标准,那么使用graph.remove_node(node)将其删除。

在这个过程之后,只有符合过滤标准的表将作为节点留在图中。它们之间的边保持不受影响,而将它们连接到已删除节点的边不再是图的一部分。我实现了以下过滤器:

  • 数据库(模式)、表和列的名称(带通配符的字符串比较)。
  • 行数。
  • 列数。
  • 连接数,即引用其他表或从其他表引用。

有时过滤某些表是有用的,例如,所有表的名称中都有一个给定的字符串,然后还显示与过滤后剩下的那些表相连接的所有表。为此,我编写了以下函数。

整数参数depth决定了这个连接扩展到什么程度。案例depth = 1对应于我上面所说的,而depth = 2不仅包括连接的表,还包括连接到这些表的表,等等。换句话说,将保留离过滤节点不超过depth条边的所有节点(self.graph.nodes)。

我们通过遍历过滤图中的所有节点并将它们及其相邻节点添加到要保留的节点列表中来实现这一点。注意,对于一个有向图,DiGraph.neighbors(node)DiGraph.predecessors(node)将分别给出一个节点的后继节点和前趋节点,即它在两个方向上的邻居。对于一个无向图,你只能使用Graph.neighbors(node)。一旦我们有了要保留的节点列表,我们只需用未过滤的备份覆盖我们的图表,然后删除列表中没有的所有节点。如果depth大于 1,新的迭代将从self.graph开始,包含我们刚刚放入保留列表的所有节点。

在 web 应用程序中可视化图表

networkx 包提供了基本的可视化功能,但这并不是它的优势所在。我决定使用 破折号 开发一个 web 应用程序,因为这样可以对数据库结构进行交互式探索。如果你不熟悉 Dash,看看它的文档,并查看一下plottly可视化示例,了解一下你能用它做什么。你也可以在 Medium 上找到一些关于使用破折号的有用文章。

出于可视化网络图和应用过滤器的目的,我发现这些破折号 / 特性特别有用:

  • 您可以构建一个 web 应用程序(也可以在本地运行),而无需大量编码。
  • 你不需要编写 HTML 或 JavaScript 代码,除非你想将你的应用程序扩展到 Dash 提供的范围之外。
  • 您不需要为您的可视化重新发明轮子,因为 plotly 已经提供了缩放、平移、在鼠标悬停事件时显示注释等功能,以及以 PNG 格式保存绘图的能力。

关于如何使用破折号构建 web 应用程序的详细信息,请点击我上面提供的链接。在这里,我将只给出应用程序的简要概述,然后讨论有趣的部分,即可视化图形的代码。以下是创建 web 应用程序的基本步骤:

  1. 导入您需要的模块,在本例中是用于创建应用程序和添加控件的dashdash_core_components(作为dcc)、dash_bootstrap_components(作为dbc)和dash_html_components(作为html)。因为我们想在回调函数中访问控件的内容,我们还需要这个:
    from dash.dependencies import Input, Output
  2. 创建一个 Dash 应用程序对象,像这样:
    app = dash.Dash(...) 在这一行中,你可以通过向函数传递参数来做很多事情。例如,您可以通过指定 CSS 文件来更改 GUI 的外观。
  3. 创建所有的控件(文本标签、输入字段、下拉列表等。)你需要。使用dash _ bootstrap _ components您可以轻松地将它们排列成行和列,以创建一个响应式布局。绘图区域是一个dash_core_components.Graph对象(不要和我们的网络图混淆)。
  4. 这些控件组(行中的列)被收集在一个容器对象中,并被插入到我们的 Dash 应用程序对象的layout属性中:
    app.layout = html.Div(dbc.Container([...]))
  5. 最后,我们使用@app.callback装饰器将函数链接到我们的控件,如这里的所述

现在来说说网络图怎么画。当“更新图形”按钮的回调被触发时,相应的代码被执行。这个回调函数的返回值是一个plotly.graph_objs.Figure对象,其输出设置为绘图区域的'figure'属性(dash_core_components.Graph对象)。

在实际绘制之前,我们需要计算网络图中节点的位置。幸运的是, networkx 包可以为我们完成繁重的工作,因为它包含了以有用的方式排列节点的布局函数。我在 GUI 中添加了一个下拉菜单,允许用户选择他们想要应用的布局功能。我实现了以下选项( networkx 被导入为nx):

  • pos = nx.layout.planar_layout(graph)
    该函数试图定位节点,使得所有的边都可以画出而没有交叉,从而创建一个整洁的可视化。如果这是不可能的,它会引发一个错误。
  • pos = nx.layout.shell_layout(graph, nlist=node_list)
    这将根据nlist(节点列表的列表)的内容将节点排列成同心圆(壳)。我选择根据节点的边数将节点分配给壳(连接最多的节点放在中间)。当要显示的节点数量很少而边数很多时,这对于获得概览很有用。
  • pos = nx.layout.spring_layout(graph)
    应用此布局功能创建一个力导向布局,即边像弹簧一样活动,节点互相排斥。通过为节点指定权重属性,可以单独更改弹簧的吸引力(否则,所有节点的值都相同)。我发现这种布局对于在所有节点都有相似边数的非平面图中创建顺序非常有用。
  • pos = nx.layout.kamada_kawai_layout(graph) Kamada-Kawai 算法也产生力导向布局,但考虑了每对节点的图形距离(最短路径中的边数)。这对于识别强连接节点的集群是有用的。

通过调用一个布局函数计算出节点位置后,这些位置被传递给图形对象,如下所示:nx.set_node_attributes(graph, name='pos', values=pos)

现在我们有了作为节点属性的节点位置,我们可以开始绘图了。我们将从边缘开始。

上面的代码创建了散点图对象edge_trace(在将plotly.graph_objs导入为go之后),我们向其传递了一个描述用于绘制边缘的线型的字典。然后,我们遍历图中的所有边,并通过访问我们刚刚分配的'pos'属性来提取相应的开始和结束节点的坐标对(分别为索引 0 和 1)。这些位置被添加到散点图对象内的坐标数据中。因为我们希望箭头从引用指向被引用的表节点,所以我们创建了列表annotations。对于每条边,我们在这个列表中添加一个条目,这是一个描述我们想要绘制的箭头的字典。

接下来,我们处理节点(所有元素的实际绘制发生在最后)。

我决定用颜色来表示一个节点拥有的连接数。上面的代码创建了一个对数颜色条,当有许多连接很少的表和有许多连接的表时,这个颜色条很有用。列表conn_ticks包含 N 的值,我们希望在这些值处标记分笔成交点。由于有节点的 N = 0,我们将使用 log( N + 1)来分配颜色,并相应地选择放置刻度标签的值tick_vals。字典marker定义了节点的外观,利用了我们刚刚设置的颜色条和 plotly 内置的“地狱”色标。

正如我们处理边一样,我们创建了一个散点图对象,现在必须用描述每个节点的数据填充它。

上面显示的代码遍历图中的所有节点,并访问感兴趣的节点属性。这些属性被编译成字符串node_info,该字符串在代码的最后一行被设置为鼠标悬停文本。正如我们对待边缘一样,我们提取节点位置(线x, y = ...)并将其添加到散点图对象node_trace的坐标数据中。如果要显示表名,必要的数据(包含文本和位置的字典node_annot)被添加到注释列表中,我们之前使用该列表来添加箭头。使用node_trace['marker']['color']属性,根据我们的对数颜色条设置节点颜色。节点大小是根据其行数设置的(取最小值的对数)。

我们现在需要做的最后一件事是构建实际的图形对象。

上面的代码设置了绘图区域周围的边距,并定义了 x/y 轴(axis_props)和颜色轴(c_axis_props)的属性;关闭色彩范围自动缩放)。边距和轴字典与我们的注释列表(箭头和节点名)一起被传递给布局对象。最后我们创建了plotly.graph_obs.Figure对象,“更新图形”按钮的回调函数将该对象返回给绘图区域的'figure'属性。

这是我们所有努力的结果:

web 应用程序的 GUI。

上图显示了对名称中包含字符串“auth”的所有表进行搜索并将深度设置为 1(包括连接到搜索结果表的表)后的 web 应用程序。请注意,出于数据保护的原因,我在这里更改了一些名称。

下面的屏幕截图演示了鼠标悬停功能,该功能允许快速检查网络图中表的最重要属性(在示例中,选择了 Kamada-Kawai 布局,这通常有助于识别集群)。还要注意右上角的菜单栏,这是 plotly 的内置功能,允许缩放、平移和将图像保存为 PNG 文件。

鼠标悬停功能是 plotly 的内置功能。

是时候总结一下了,给你一个快速总结。在本文中,您学习了如何:

  • 从数据库的信息模式中获取表、列和引用的详细信息。
  • 使用 networkx 包创建一个(有向)图,并将表表示为节点,将它们的连接(引用)表示为图的边。
  • 向节点添加有用的属性,比如外键和表的行数。
  • 通过创建图形对象的副本并删除其属性不符合过滤条件的所有节点来应用过滤器。
  • 使用 networkx 的布局功能排列图形的节点。
  • 使用 plotly 绘制图形,信息编码在节点的颜色和大小中。
  • 添加包含最重要节点数据的鼠标悬停文本。

如何从随机森林模型中可视化决策树?

原文:https://towardsdatascience.com/how-to-visualize-decision-tree-from-a-random-forest-model-ca563c75811c?source=collection_archive---------18-----------------------

决策树模型解释

图片由皮克斯拜的 Gerd Altmann 提供

随机森林或随机决策森林是一种监督集成机器学习技术,用于训练分类和回归模型。随机森林的训练算法使用 bagging 或 bootstrap 聚集技术,使用决策树作为基学习器。随机森林使用随机化来减少决策树模型中的偏差。

什么是决策树?

决策树是一种受监督的机器学习技术,其中数据根据某个参数进行分割,并形成树状结构。可以使用决策节点和树叶来解释该树。

模型的可解释性有多重要?

在训练一个健壮的模型并评估模型的性能之后,问题出现了,预测的原因是什么。当谈到预测建模时,您需要权衡,这是业务需求,只是获得预测或预测的原因。

模型可解释性包括观察模型的内部,找出哪些特征对做出预测很重要。有各种模型解释技术来解释预测的原因。

随机森林模型解释:

图片由 Pixabaystock snap/a>提供

随机森林使用 bagging 技术来减少其基础学习者(即决策树)的偏差。随机森林模型可以被认为是一个黑箱模型,因为预测的原因很难解释。为了解释一个随机森林模型,你需要理解它的基础学习者的工作。

数据集:我们将使用 Iris 数据集来演示随机森林树的可视化

n_estimators 参数在随机森林分类器中决定了树的数量,该模型将已经作为基学习器。

为了可视化一个随机森林模型的多个决策树,我们将使用**export_graphviz** 库。这个库用于以点格式导出决策树,并生成决策树的 GraphViz 表示。

要可视化随机目录林的决策树,请按照下列步骤操作:

  • 加载数据集
  • 用 n_estimator 参数作为若干个基学习器(决策树)训练随机森林分类器模型。
  • model.estimators_:拟合子估计器的集合或决策树分类器列表及其定义的参数。
  • 使用**export_graphviz** 库将每个决策树模型保存为一个点文件以创建可视化。
  • 打印每个决策树的可视化效果

实施:

(作者代码)

如何读懂决策树的可视化?

(作者图片),决策树的可视化

For each node of the tree:
**1st line** represents the condition (example: petal_length≤2.6)
**gini:** gini score 
**samples:** total number of samples from all three classes
**value:** distribution of samples amongst each target class
**class:** most probable prediction of target class label for that node

从上面的可视化中,我们总结出以下几点:

  • 花瓣长度是最重要的特征,并且花瓣长度≤2.6,导致 setosa 类标签。
  • 树节点被分成左(真条件)和右(假条件)节点,直到我们得到叶节点。

结论:

随机森林模型可以被认为是一个黑箱模型,因为它很难解释预测的原因。在本文中,我们讨论了如何可视化构成随机森林模型的多个决策树。

然而,有一个限制,如果决策树的数量很大,那么可视化每一个都很困难。对于决策树数量较少的随机森林模型,这种技术最适合向业务人员解释模型。

参考资料:

[1]导出 Graph Viz 文档(sci kit-learn):https://sci kit-learn . org/stable/modules/generated/sk learn . tree . Export _ graphviz . html

感谢您的阅读

如何用 Python 和 networkx 可视化超图——简单的方法

原文:https://towardsdatascience.com/how-to-visualize-hypergraphs-with-python-and-networkx-the-easy-way-4fe7babdf9ae?source=collection_archive---------18-----------------------

实践教程

一种通过标准图形可视化库绘制超图的简单方法。

本文所述程序的最终结果——图片由作者提供

图很牛逼,超图超牛逼!超图是图的一种推广,它放宽了边只连接两个节点的要求,允许边连接多个节点。它们是一个非常自然的框架,在这个框架中,从遗传学到社会科学、物理学等等,在广泛的领域中制定和解决问题!但是尽管有很多成熟的 Python 库来处理和可视化图形,超图却不是这样。

图形与超图——作者图片

我最近需要可视化一些超图,但找不到任何令我满意的库;此外,据我所见,他们都是通过欧拉图来表示超图的(例如,就像上面手绘的超图)。不幸的是,这种方法并没有为我的用例产生好的图形;我最终做的是将一个超图表示为一组图形,并通过令人敬畏的networkx库绘制它们。

我决定写下我绘制超图的方法,因为它为我最近正在查看的数据类型生成了非常有趣的图(本质上是 Ising 模型,但也包含许多身体交互),并且,经过一些调整,它可能对其他努力完成超图可视化任务的人有一些帮助。

最初的想法和尝试

我们将从用 Python 表示一个 hypergraph 开始,代码如下:

注意,这只是一个非常基本的方法,因为边应该是 Python frozenset的,这样它们的集合也可以是set,节点集也应该是frozensetset。如果我们开发一个超图算法库,一个更好的模式会对我们有很大帮助,但是在这篇文章中,为了简单起见,我决定保留上面的简单模式。

首先,我们可以注意到,任何超图都可以通过所谓的星形扩展转换成图,即,我们创建一个新的图,其节点集是原始超图的节点和边,边由原始超图中的关联关系给出(如果节点 n 是超图中边 e 的一部分,则在新的图中 n 和 e 之间应该有一条边)。

这远没有听起来那么复杂,如下图所示:

超图的星形展开——作者图片

在许多应用程序中,绘制超图的星形展开图可能就足够了。例如,test_hypergraph(如上定义)的星形展开看起来如下

test_hypergraph 的星形展开—作者图片

通过进行一些编辑,例如只扩展连接三个或更多节点的边,并为额外的节点选择不同的布局,也可以像这样绘制test_hypergraph:

改进的 test_hypergraph 图——作者图片

例如,在上面的图中,我们可以从连接abd的三条红线中看到边缘(a,b,d)

虽然由部分星形扩展引起的更少的额外节点使得第二个图稍微更可读,但是上面的两个图仍然非常不令人满意。我对这些可视化的主要问题(以及我在试验这个主题时产生的类似问题)如下:

  1. 一幅图像上有太多的信息,以及太多的重叠线条;这使得情节难以阅读,并可能毫无用处。
  2. 人们可以选择用来绘制图形的嵌入可以极大地帮助理解图形本身的结构;通过进行星型扩展,这种情况通常不再存在,因为节点与超边缘混杂在一起。

解决#2 是非常具有挑战性的,并且很可能严重依赖于你想要可视化的那种超图。我发现了一个策略,它很好地解决了第一个问题,如果按照基数分割超图的边是有意义的,我将在下面解释我的方法。

将一个超图分解成许多图

关键的想法是,我们将按照超图包含的节点数量来分解超图的边,这种方式完全类似于物理学家所说的 2 体相互作用、3 体相互作用等等,并分别绘制超图的这些不同的“组件”。

为了按照边的基数分解超图的边集(假设一个类似于我们在上面的test_hypergraph中使用的模式),我们可以写

例如,test_hypergraphdecomposed_edges字典如下所示

{
  2: [('a', 'b'), ('b', 'c'), ('c', 'd'), ('a', 'c'),
      ('b', 'f'), ('f', 'c'), ('e', 'f'), ('a', 'e'),
      ('b', 'd')],
  3: [('a', 'c', 'd'), ('a', 'b', 'e'), ('a', 'b', 'd')],
  4: [('a', 'b', 'c', 'd')]
}

那么接下来,我们可以尝试为每个边序 I 绘制由原始图的节点集给定的超图的星形展开,连同边集decomposed_edges[i](除了 i = 2,这里我们将只绘制图而不进行星形展开),看看它看起来像什么。实现这一点的代码如下:

plot_hypergraph_components函数应用于test_hypergraph会产生以下图形:

test_hypergraph 的最终结果—作者提供的图片

这个脚本应该很简单,但如果你想进一步澄清什么,请告诉我。我不得不做出的一个奇怪的选择是让g成为networkx.DiGraph,因为如果g改为networkx.Graph,我就不能通过connectionstyle的参数画出曲线。

事实上,红色的节点(通过星际扩张获得的额外节点)在每个子情节中都有相同的顺序,这使得这个情节非常容易阅读。它仍然不完美,但可以说比我们早期的尝试可读性更好。例如,从最右边的子图可以明显看出,4 阶只有一条边,它是(a,b,c,d),从中间的子图可以很容易地看出,3 阶仅有的边是(a,b,e)(a,b,d)(a,c,d)

随机超图的其他例子

我们还可以通过从一组节点开始并在它们之间随机添加边来生成一些随机超图,直到我们达到指定的数量,即,

其中一个示例(order=5size=10)如下所示:根据经验,我发现它们足够易读,即使是在平面布局无法实现的情况下。

通过plot_hypergraph_components 功能可视化的随机超图——作者图片

结论

上述程序对通过networkx绘制超图很有帮助。特别是在量子物理、统计力学等超边的顺序很重要的环境中,这可能是一个有用的可视化。

所提出的方案的缺点可能是,在每个子情节中,节点的位置通常可以变化;这可以通过任意修改plot_hypergraph_components代码中的pos参数来轻松解决,但是特定于问题的属性可能有助于做出有意义的选择。

如果你做到了这一步,感谢你的阅读:-)

如何:使用可观察的绘图可视化“小倍数”图表

原文:https://towardsdatascience.com/how-to-visualize-small-multiples-charts-with-observable-plot-d13b9730eb74?source=collection_archive---------35-----------------------

关于可观察的地块(和停车场),我们能了解到什么?

显示美国各县停车场面积的图表。

让我们探索两件事:

  1. Observable 的新绘图库用于快速数据可视化和探索性数据分析。
  2. 停车蔓延这个小问题。

可观察剧情伟大 的几个原因:

  • 制作“足够好”的图表和图形是超级快速且相对不需要动脑的。如果您需要一些新奇的东西,d3 仍然是一个合理的选择,但是对于基本的条形图、折线图、分布图等。,它以最小的忙乱完成了这个任务。
  • 该 API 直观、简洁,并且使用了大多数 d3 数据可视化开发人员依赖的定制 dataviz 的惯例。
  • 我们将在这里探讨的分面概念,可以很容易地将同一数据集的许多不同维度并行可视化为多个小图表。

停车场最差的几个原因:

  • 车祸。20%的车祸发生在停车场(每年导致 6 万人受伤, src )。
  • 房价。停车多→住房少。在纽约市,最低停车要求提高 10%会导致住房密度降低 6%。
  • 污染。停车多→汽车尾气多( src )。
  • 它们太丑了。

丑陋停车场拼贴(鸣谢:各种)

停车数据集的土地使用

让我们从一个数据集开始。请注意,Plot 是根据“整齐的数据”构建的,这是它干净和表格化的另一种说法。可观察的定义:

  • 每个变量都必须有自己的列。
  • 每个观察必须有自己的行。
  • 每个值必须有自己的单元格。

所以我在这里整理了一个县停车区数据集。它结合了这项研究的结果,该研究模拟了美国的停车场土地使用和美国人口普查国家县地名索引文件,该文件有关于县的基本事实,如人口规模和土地面积。它大约有 16k 行,每行有 6 个字段:

  • geoid:FIPS 州+县的县代码
  • countyName:一个人可读的县名
  • landAreaMSq:土地面积平方米
  • parkingLandAreaMSq:停车场用地面积,平方米
  • year:与停车场测算相关联的年份。

我们可以通过以下方式提取数据:

那我们来做一些图表吧!

单个城市的停车场分布有多少?

可观察图中的简单面积图

让我们从简单的开始,只看一个城市的增长。比如说北卡罗来纳州的罗利。

首先,让我们只取出与 Raleigh 相关的行:

然后我们将创建一个简单的面积图,只显示 Raleigh 时间序列。

我们从下面的片段中得到上面的图:

这大致可以解释为“给定这些整洁的数据,给我一个合理的面积图,其中 X 是“年份”字段,Y 是“停车场面积”。当然,结果很难看,但这是一个简单明了的函数调用。

这引入了 Plot 的“标记”概念在这种情况下,“标记”是描述数据的任何可视编码的抽象术语。Plot 为所有您喜欢的数据可视化提供内置标记(例如,条形、线条、点、区域等)。

我们从下面的片段中得到上面的图表:

结论:

  • Plot 给出了(接近* ) 1-liner 图,用于在 Javascript 中可视化(愚蠢的)数据*
  • 自 1974 年以来,罗利的用于丑陋停车场的面积增加了一倍多

停车场在多个城市中分布有多广?

可观察图中的小倍数图表

让我们画出专用于停车场的土地使用面积最大的 20 个县。

我们从下面的代码片段中获得了上面的图表:

我们正在做几件事:

  • 首先,我们提取停车场面积最大的 20 个县
  • 然后,我们通过稍微侵入 Plot 的刻面系统来绘制它们

结论:

  • 洛杉矶县有很多停车场。截至 2012 年,面积为 290 平方公里(111 平方英里)。也就是说,洛杉矶县的停车面积是曼哈顿的 5 倍。
  • Plot 的刻面非常适合显示按维度划分的数据集的小倍数图表。
  • 停车场是最糟糕的。

我是谁?不,不,你是谁?!**

嗨!我是伊莱·霍德。我的公司 3iap 帮助客户设计和开发有效的 javascript 数据可视化和定制分析产品。如果你是一名创始人、创客、讲故事者、非营利行善者或商业领袖,正在思考数据、设计和用户心理的交集,我很乐意联系并聆听你的故事。

你可以发电子邮件到 eli@3isapattern.com 给我,或者在推特上关注我。

如何想象你的余生

原文:https://towardsdatascience.com/how-to-visualize-the-rest-of-your-life-28f943b1f70b?source=collection_archive---------13-----------------------

作者图片

教程-PYTHON-ALTAIR

一步一步的教程来创建一个数据 Viz 图表与你的生活在几周内使用 Python 和 Altair

1.介绍

对于这篇文章,我尽量不要过于哲学化。然而,最近我看到有人展示了一张海报,描绘了他在几周内的生活。过去的所有几周都以黑色显示,而他生命中剩下的几周则以白色显示。这多少引起了我的共鸣。作为数据科学家,我们分析和可视化数据以创建视角,发现隐藏的信息,得出结论,并对新生成的信息采取行动。

我看到的那张海报符合我的所有要求。所以我尝试用 Python 和 Altair 来生成这样的可视化。我主要使用 Altair,因为我想更熟悉它,并使用 ggplot2 和 plotnine 打破我的舒适区。

在下一节中,我将与您分享我的技术设置。在第三部分,我将解释我如何构建这个可视化,以及你如何使用它。最后,我来总结一下这篇文章。

结果可视化,用 Affinity Designer 进一步处理(图片由作者提供)

2.设置

如果你想知道我是如何构建我的代码的,它被称为方法链或管道(在 R 社区中)。我在我的另一篇文章中解释了的基础知识。

您可能知道,我使用 R 开始了我的数据科学职业生涯,因此,我非常熟悉 ggpot2 。随着我在客户项目中越来越频繁地使用 Python,我开始寻找类似的 Python 可视化包。我很高兴地说,有了 Plotnine 就有了一个极好的选择。

然而,由于我喜欢尝试新事物,特别是可视化软件包,我想尝试一下 Altair 软件包 。Altair 是一个 Python 数据可视化包,它遵循一种声明式方法,就像 ggplot2 和 Plotnine 一样。

4.创建可视化

首先,我们需要了解你一点。当然,那是你的预期寿命。还有你的生日。

然后我创建三个日期对象。一个是当前日期,你出生的那一天,最后是死亡的那一天。

接下来,下一个代码计算从你出生到现在的天数,以及从现在到死亡的天数。基于这些天的变量,我计算年和周。

最后,我创建了三个数据框来保存每周的信息,不管是已经过去的一周、当前的一周还是未来的一周。我承认,这可能不是创建数据的最优雅的方式。如果你有更高效的方法,欢迎分享。谢谢你。

最后,我创建图表。我使用了 Altair 的 mark_square 功能。我还把两个标记方块放在彼此的上面,以便创建一个黑色边框的效果。否则我无法创建它。

最后,我配置标题并保存图表。

如果您想应用您的预期寿命和您的出生日期,您只需要在代码的开头更改这些变量。

可视化结果(图片由作者提供)

5.结论

在这篇文章中,我向你展示了如何创建一个可视化来显示你的生活周。我解释了如何使用 Python 和 Altair 来实现这一点,以及如何基于数据生成可视化。

如果你觉得这篇文章有帮助,请告诉我。此外,如果您能分享任何关于如何改进此解决方案的想法,我将不胜感激。谢谢大家!

如何使用 Spark 和 Power BI 以 3d 方式可视化您的嵌套物联网数据

原文:https://towardsdatascience.com/how-to-visualize-your-nested-iot-data-in-3d-using-spark-and-power-bi-5a2be7c18e7f?source=collection_archive---------30-----------------------

使用 Azure Databricks、Spark、Python 和 Power BI python 脚本可视化

作者图片

A.介绍

时不时地,你会遇到新的独特问题需要解决。这一次是客户端获取嵌套的物联网数据。存储和可视化物联网数据通常是一项标准任务,但将嵌套的物联网数据作为每条消息的“矩阵”以及相应的向量并不像通常那样简单。

在这篇文章中,我们将学习:

  • 如何以可扩展的方式转换嵌套的物联网数据
  • 如何在 Power BI 中创建定制的 python 可视化
  • 非技术最终用户如何通过 web 浏览器消费和可视化数据

我们将使用 Spark、Python 和 Power BI 通过一些简单的步骤来解决我们的问题。

B.数据结构

首先,让我们看看来自物联网设备的数据是什么样的:

spark 数据帧中的物联网数据结构示例。图片作者。

在上图中,我们可以看到物联网数据的一个子集,我们将重点解决每个消息/行的“矩阵”类型数据的具体问题。物联网数据包含许多标准类型的其他列,但在本文中我们将只研究如何处理复杂类型。

“矩阵”中的每个位置和值都连接到特定的 x 值和 y 值。见下图。

对于每个 x 和 y 值,都存在一个 z 值。图片作者。

z = f(x,y)
1 = f(0,40)
3 = f(40,40)
2 = f(100,75)

这是我们从物联网设备获取原始数据的方式。实际上,矩阵要大得多,但是为了简单起见,我们在这里使用大小为 5x5 的矩阵。我们将使用的方法也适用于较大的矩阵。

对于 x 和 y 的每个组合,我们都有一个 z 值。我们的任务是转换数据,以便可以在 Power BI 中使用和可视化。BI-tools 无法使用我们从物联网设备接收的压缩形式的原始数据。BI-tools 通常需要表格数据。因此,我们希望创建一个如下所示的常规表:

[id ][X-value] [y-value] [z-value] [any meta-data-column(s)]
1000    0        10         0            meta-data
1000   20        30         2            meta-data
... 

C.转换数据

我们希望转换原始源数据,其中每一行都包含:

  • z 值的矩阵
  • x 值的数组
  • y 值数组

放入由唯一行组成的常规表中,这些行构成了数据的所有可能组合。

C0。关于火花的一个注记

在本例中,我们将使用有限的数据。在生产环境中,我们通常有数 TB 的数据,因此我们希望使用一种可随传入的物联网数据扩展的技术。因此,我们将看看如何使用 Spark 来解决这个问题。

我们将使用 Azure Databricks 和 Spark 来转换数据。我们将在 Spark 数据框架中保存数据。从上面我们可以看到,矩阵是作为 Spark 数据帧中的数组存储的。

C1。生成测试数据

让我们生成一些测试数据来使用。

这给了我们一个火花数据帧,看起来像这样:

用物联网数据火花数据框。图片作者。

我们以如上所述的 Z = f(x,y)的紧凑形式获得物联网数据,但 Power BI 不理解这种形式,因此我们需要创建一个常规的数据表。Spark 有内置的功能来帮助我们。在这种情况下,我们追求的功能是:

posexplode(col)

简而言之, posexplode 将创建一个包含展开数据的新列以及我们选择展开的列的附加行。此外,我们将获得一个额外的列,其中包含原始数据结构中分解的位置/索引。在这里看文件

我们需要将“矩阵”的每一个值放在它自己的行上,并带有 x 和 y 坐标的索引,这样我们就可以将正确的 z 值与正确的 x 和 y 值匹配起来。

我们将每个数组分解成一个名为“值”的新列。我们也存储索引。图片作者。

正如我们在上面第一个 posexplode 的显示中看到的,我们已经在一个名为“values”的新列中展开了列“matrixdata”的第一个数组。我们还将从“矩阵”的哪一行展开的数据存储在名为“y_index”的列中。我保留了“matrixdata”列,以便更容易理解,尽管从技术上讲我们不再需要这个列了。

接下来,我们需要对结果值进行位置分解:

展开值列的 posexplode。保留 x_index。图片作者。

所以,最后我们用 x_index 和 y_index 得到 z_value。最后一部分是将 x_index 与 x_values 列中的相同索引相匹配,将 y_index 与 y_values 列中的相同索引相匹配。

功率 BI 中消耗的最终表。图片作者。

现在,我们有了一个包含数据的常规表,可以由 Power BI 使用。

D.导出数据

D0。导出到数据湖

让我们将数据作为 CSV 文件导出到我们的存储帐户。我们将使用 Pandas 将 Spark 数据帧导出到一个命名的 CSV。对于大量的数据,我们将直接使用 Spark。变量 path_export 在我们的数据湖中保存挂载的路径。稍后我们将从 Power BI 加载 CSV 文件。

当我们使用单节点库和本地文件 API 时,我们需要在挂载路径前面加上/dbfs/

D1。替代本地出口

如果我们没有数据湖帐户,出于测试目的,我们可以将 CSV 导出到我们的本地计算机,并将 CSV 从本地文件导入到 Power BI。Azure Databricks 附带了一个 DBFS 文件系统,包含在每个工作区中。我们可以将 CSV 导出到 DBFS,并使用 Databricks CLI 从 DBFS 文件系统下载 CSV 文件。参见此处如何安装 Databricks CLI。然后,我们可以使用 CLI 命令将文件下载到本地计算机,如下所示:

# Usage: databricks fs cp [OPTIONS] SRC DSTdatabricks fs cp dbfs:/path_we_exported_to/heatmap_from_spark.csv destinationpath

之后,我们可以将 CSV 文件加载到 Power BI 桌面。

D2。关于熊猫的笔记

我们没有任何“大数据”矩阵和数组,所以我们允许使用 Pandas 将我们的 Spark 数据帧导出为一个命名的 CSV。我们可以以可伸缩的方式直接从 spark 导出 CSV 格式的数据,但是我们会得到以 Spark 命名的 CSV 文件,这需要在 Power BI 中加载数据之前做一些额外的工作。所以我们选择在这里使用熊猫,因为它满足了我们的需求。此外,如果我们有大量的数据,我们不会导出 CSV 格式的数据。在这种情况下,我们可以通过从 Power BI 到 Databricks 的直接查询来直接使用数据。(Databricks 和微软已经优化了 Power BI 和 Databricks 之间的连接,因此现在的性能比以前好得多。此外,通过 SSO 的穿越认证也是支持的,但这超出了本文的范围。)

E.电力商业智能中的可视化

我们现在有了表格形式的数据,并希望在 Power BI 中可视化这些数据。我们可以直接从 Power BI 的 Data Lake Gen 2 帐户加载数据。然后,我们可以使用内置的可视化工具或下载额外的插件来可视化数据。在这个例子中,我们将使用 Power BI 中的 python 脚本可视化。这允许我们使用 Python 以我们想要的方式创建一个自定义的可视化。

E0。让 python 可视化在 Power BI 中工作

从 Power BI 内部使用 python 的想法很简单。我们将一个熊猫数据帧放入我们的脚本,然后我们可以使用选定的 python 库来可视化我们的数据。还可以将我们的报告与 python 可视化一起发布到 Power BI 服务在线。

设置 Power BI desktop 以使用 python 视觉效果:

  • 1.只有在您使用非 Windows 计算机(如 MAC 或 Linux)时,才需要这一步。在虚拟机上安装 Windows 或确保您能够访问 Windows 安装,因为 Power BI desktop 需要 Windows。
  • 2.如果需要,安装 Power BI desktop。可以从微软商店安装
  • 3.确保您拥有符合 Power BI python 需求的正确 python 环境。这里列出了 python 版本和支持的软件包版本:https://docs . Microsoft . com/en-us/power-bi/connect-data/service-python-packages-support
    在 VM 上设置 Python 时(我是在使用 MAC 时设置的),我注意到 NumPy 和 Windows 10 的一个问题,它迫使我使用 32 位版本的 Python,作为一种解决方法,让它工作。
  • 4.使用上面链接中推荐的版本,并使用 anaconda 创建 python 环境。
conda create —name powerbi377 python=3.7.7
activate powerbi377
pip install pandas==1.0.1
pip install matplotlib==3.2.1
  • 5.将 Power BI 指向我们的 python 环境。
    启动电源 BI。
    选择文件- >选项和设置- >选项- > Python 脚本
    设置我们创建的 anaconda 环境的路径。

设置 Power BI python 主目录。图片作者。

Detected home directories: OtherSet Python Home Directory: C:\Users\YOURUSERNAME\Anaconda3\envs\powerbi377

现在,我们已经准备好在 Power BI 中进行一些 python 编码,只需简单地删除 python 可视化:

Power BI 中内置的 python visual。图片作者。

到画布上。您将获得一个脚本编辑器,其中的数据是一个名为 dataset 的熊猫数据帧。您决定使用表中的哪些字段。在我们的例子中,我们将 x 值、y 值和 z 值放到画布 Py-script 上。

我们用我们选择的列得到一个熊猫数据框架。图片作者。

现在,我们可以使用 python 和 Matplotlib 来可视化我们的数据。下面是一个将我们的数据绘制成 bar3d 可视化的例子,但是你可以选择你喜欢的可视化。

我们在 Power BI 桌面客户端中使用,但是我们希望最终用户能够在浏览器中在线使用数据。为此,我们可以向 Power BI 服务发布我们的报告,并让我们的最终用户在浏览器中使用该报告:

使用 Power BI 服务发布浏览器内 python 脚本可视化。图片作者。

E.结论

当我们拥有物联网数据的嵌套结构时,我们可以使用内置的 Spark 可扩展转换来获得我们需要的数据。

我们可以在 Power BI 中使用转换后的数据,方法是将数据导出到一个数据湖中,然后加载到 Power BI 中,或者使用直接查询。

如果我们希望在 Power BI 中以内置可视化或第三方扩展不支持的方式可视化我们的数据,我们可以使用 python 脚本可视化来可视化我们的数据。

我们需要仔细设置我们的 python 环境,以匹配 Power BI 服务中支持的版本。

我们可以将我们的自定义 python 可视化发布到 Power BI 服务并与其他人共享,这样他们就可以使用 web 浏览器在线使用这些报告。

一个笔记本(。ipynb)与上面的源代码可以在这里找到

如何用 Python 和 Altair 可视化你的跑步者的 High

原文:https://towardsdatascience.com/how-to-visualize-your-runners-high-with-python-and-altair-45dde7803141?source=collection_archive---------19-----------------------

布鲁诺·纳西门托Unsplash 上拍照;作者略有改动

教程 PYTHON 运行

使用 Python 和 Altair 检索和可视化运行数据的分步指南

1.介绍

大家好,我是 Gregor,一名数据科学家,一名充满激情的非竞赛跑步者。我才知道,十年前我就开始在手机上用跑步 app 了。那时候,我只记录 GPS,开始和结束时间。我没有办法记录节奏、心率、海拔等等。我记得我是一个糟糕的跑步者——跑得慢而且容易上气不接下气。我刚完成博士学位,在办公桌前工作太多了。所以我决定以跑步者的身份开始这段旅程。

十年是一段很长的时间,我想知道在这段时间里我的跑步发生了什么变化。我变得更健康、更快或更冷静了吗?我在哪一级训练?虽然大多数健身平台提供了一些报告,但我在过去的 10 年里错过了这些报告。尤其是我对同比比较感兴趣。

在本文中,我将向您展示(1)如何从 Garmin connect 中导出您的运行数据,(2)如何使用 Python Pandas 清理数据,以及(3)如何使用 Altair 可视化数据。

2.从 Garmin Connect 导出数据

首先,前往 Garmin Connect ,特别是“所有活动”页面。最好通过点击右上角的跑步图标来过滤你的跑步活动。

Garmin Connect 活动页面;作者图片

在您点击导出按钮之前,向下滚动您的跑步活动列表很重要。只能导出列表中显示的那些活动。完成后,按右上角的“导出 CSV”按钮。这将把文件Activities.csv下载到您的计算机系统上。数据包括日期、距离、步速、心率、海拔等信息。

3.使用 Python Pandas 清理数据

数据相当干净,我们只需要关注以下几个方面:

  1. 将日期信息转换成各种有用的功能
  2. 将配速信息转换为分钟数
  3. 将数字转换成数字类型
  4. 处理缺失值

下面你会发现我用来实现这一点的代码。如果你想了解更多关于日志记录的知识,我推荐这篇文章:“如何为 Python 设置日志记录”,如果你想了解更多关于我编写代码的方式,请考虑阅读“Python 的完美管道”。

runs_raw.info()的输出;作者图片

请注意,我使用函数assign()来创建额外的变量。这样做的好处是不会为以后的测试覆盖值,并且您可以为命名列实现自己的命名约定。然而,通过函数filter(like = "run"),我删除了所有旧的变量。请参见下面的结果列名。

清洗过程的结果;作者图片

最后一步是将清理后的数据保存到系统中。

4.用 Altair 实现数据可视化

您可能知道,我使用 R 开始了我的数据科学生涯,因此,我非常熟悉 ggpot2 。随着我在客户项目中越来越频繁地使用 Python,我开始寻找类似的 Python 可视化包。我很高兴地说,有了剧情就有了一个很好的替代方案。

然而,由于我喜欢尝试新事物,特别是可视化软件包,所以我想尝试 Altair 软件包。Altair 是一个 Python 数据可视化包,它遵循一种声明式方法,就像 ggplot2 和 Plotnine 一样。

请跟随接下来的段落,在那里我评估我的一些运行数据。也许你可以学到一些如何使用 Altair 的知识。

设置

过去十年(105 个月)我跑了多少?

每年运行次数;作者图片

每月运行次数;作者图片

我每年训练的距离是多少?

按年计算的距离;作者图片

我每年训练的心率是多少?

每年的平均人力资源;作者图片

我每年以什么速度跑多少距离?

每年每段距离的平均配速;作者图片

5.结论

在本文中,我向您展示了如何从 Garmin connect 获取您的跑步数据,如何使用 Pandas 清理数据,以及如何使用 Altair 分析数据。

你可能已经观察到了,我的跑步在 2018 年开始变得稍微严重了一点。在那之前,我的工作需要经常出差。一个阻碍我跟上跑步的事实。

对我来说,这次锻炼是值得的,可以对我的跑步数据进行年度比较。这在 Garmin connect 上是不可能实现的。此外,它让我对 Altair 软件包有了更多的了解。因为我更习惯于使用 Plotnine,所以目前我将坚持使用 Plotnine 。但是如果一个项目需要互动图表,我强烈推荐你去看看 Altair。

如有任何问题和意见,请随时联系我。谢谢你。点击此处查看更多我的文章:

  1. 了解我如何为媒体设计文章
  2. 了解如何为您的 Python 代码设置日志记录
  3. 了解如何使用链接(或管道)在 Python 中编写干净的代码
  4. 学习如何使用 R 分析你的 LinkedIn 数据
  5. 学习如何使用图形语法在 Python 中以描述性的方式创建图表

Gregor Scheithauer 是一名顾问、数据科学家和研究员。他专门研究流程挖掘、业务流程管理和分析。你可以在LinkedInTwitter上和他联系,或者在 Medium 上这里。谢谢大家!

如何使用量子正态分布

原文:https://towardsdatascience.com/how-to-work-with-a-quantum-normal-distribution-170ccc4e2da2?source=collection_archive---------30-----------------------

量子机器学习实用指南

量子机器学习要不要入门?看看 动手量子机器学习用 Python

如果我想开个玩笑,我会说,“就像你处理经典正态分布一样。”从内容相关的角度来看,我是正确的。正态分布是一种对称的概率分布,接近平均值的数据比远离平均值的数据更有可能出现。量子正态分布也是如此。

当然,在使用任何量子电路时,我们都需要迎合量子位的特殊性。在之前的一篇文章中,我们在量子贝叶斯网络中使用了量子 Multinoulli 分布。由于(离散的)正态分布是一个多对数分布,我可以就此打住。

如果我那样做,我将表明我既不理解正态分布的目的,也不理解量子电路的特性。

先说正态分布。为什么我们首先要使用它?

让我猜猜!你会说我们用它是因为它代表了我们的观察。这是我们做实验时常见的结果。不管我们看的是什么特征,我们几乎可以肯定,这个特征取决于我们实验中无法控制的其他因素。这些因素干扰了实验的结果。我们测量的是特性的实际值加上许多干扰的总和。但是所有这些扰动的大小和方向都不同。一些增加,而另一些减少我们测量的价值。只有当许多扰动共享同一个“方向”时,我们才会看到大的偏差。即使不太可能,但有时也会发生。因此,我们认为小扰动比大扰动更有可能发生。

但是说实话。没有实验是完全正态分布的。然而,我们仍然使用正态分布。

为什么我们使用正态分布,即使我们的数据告诉我们一些(稍微)不同的东西?首先,我们假设偏离完美的正态分布是测量误差。第二,我们使用正态分布,因为它很方便。只需比较一下指定一个精确的多元分布和指定一个正态分布的努力。

假设分布有一个结构,比指定每个点的精确值要容易得多。

量子电路的特性呢?

简单的问题是,我们没有多少量子位,现有的容易出错。所以,我们和他们打交道越少越好。在前面提到的文章中,我们“选择”了一个多元分布的每个值,并模拟了它对因变量的影响。由于值(状态)的数量随着我们用来模拟分布的量子位的数量呈指数增长,这种方法似乎并不实用。

此外,我们需要知道并指定所有这些单独的影响,以便正确地对它们建模。这不是一种很方便的工作方式。

正态分布不列出分布的单个值。相反,它提供了分布的一般描述。如果我们不用这些知识,我们就是傻瓜!

让我们来看看量子正态分布的结构。下图描绘了使用三个量子位的正态分布。

我们可以看到一组有序的量子态。量子位值形成了决定每个状态位置的位串。左侧(底部)的数字表示最高量子位的测量值,右侧(顶部)的数字表示最低。

所以,有了三个量子位,我们就有了八种状态。内部的 011 (=3)和 100 (=4)比外部的 000 (=0)和 111 (=7)更有可能。

当我们看这样一个抽象的分布时,我们很容易忽略一个重要的点。这就是我们排序这些值是有原因的。

通常,我们将一个可测量的特征归于 X 轴上的点,例如身高、智力或身体质量指数。通常,我们说彼此靠近的点比另一个极端的点更相似。例如,当一个人身高 2 米(6.6 英尺)或 2.1 米(6.9 英尺)时,我们说这个人很大。这是因为这两个人比一个身高只有 1.5 米(4.9 英尺)的人有更多的相似之处。所以,举个例子,身材高大的人更有可能要低头,但是他们会碰到厨房的上层。

一般来说,正态分布的 X 轴上的两个点越接近,我们预计它们对另一个变量的影响就越相似。

例如,八个量子位状态表示人的高度,状态 000 代表最小的人,111 代表最高的人。我们希望对另一个变量的影响进行建模,这个变量告诉我们这个人在一天中需要躲避的可能性有多大。我们假设这种关系是线性的,如下图所示。

最小的人根本不需要闪避(状态 000 或位置 0)。相反,最高的人(状态 111 或位置 7)需要以 0.7 的概率闪避。

显而易见的问题是,我们如何建立这种关系的模型?首先,当然,我们可以用“多种方式”来做。然后,我们将使用 X 个门选择每个状态,并指定各自对因变量的影响。

例如,我们可以使用下面的代码模拟状态 001(或 1)的效果。

首先,我们用一个 4 量子位QuantumRegister创建QuantumCircuit。前三个量子位持有我们在上面第一张图中看到的NormalDistribution。激动人心的部分发生在那之后。我们通过翻转位置 1 和 2 的量子位来选择状态 001。因为我们从 0 开始计数,所以我们翻转代表正态分布的上面两个量子位。mcry门是一个多控 RY 门。只有当所有控制量子位(正态分布的所有三个量子位)都为 1 时,它才会旋转目标量子位(不属于正态分布的量子位)。这是原始状态 001 的情况,因为我们现在把它翻转为 111。

我们使用了函数prob_to_angle,将输入概率转化为相应的量子位旋转角度。

当我们运行电路时,我们可以获得以下测量概率。

我们看到上量子位(位串的左手边)只有一次是 1——当只有正态分布的下量子位是 1 时。但它的概率连 0.1 都不到。当然不是。在其他量子位为 001 的情况下,它只有 1,概率为 0.1。但是这个状态总共有 0.071 的概率。

所以,我们来看看这是不是真的 0.1。我们为此编写了几个小的助手函数。对,我们在relation函数内部定义了select函数。

关系函数将执行量子电路的结果作为输入参数。它返回正态分布的所有状态之间的比率列表,其中因变量除以状态的总概率。

给定因变量(a)的值和正态分布(b)中的点,select子函数准备位串。

所以,我们来看看输出。

这看起来不太糟,是吗?

我们看到,当人的身高为 1 时,因变量(需要闪避)的概率为 0.1。因此,我们可以为正态分布的每个点准备因变量。

但是,这种方法效率不高。我们将使用八个多控制量子位元闸和许多闸来选择每个状态。

那么,让我们看看如何更有效地指定关系。

我们知道,量子位元态的位元串越高,闪避的机率就越高。而且我们知道,量子位的位置越高,效果就越高。因此,举例来说,较低的量子位将概率增加 0.1,中间的量子位增加 0.2,而较高的量子位增加 0.4。所以,如果三个量子位都是一,整体概率是 0.1+0.2+0.4=0.7。

让我们用这种方式来描述我们的量子电路。

在这段代码中,我们像往常一样创建了一个三量子位正态分布的量子电路。然后,我们使用一个单控 RY 门,三个量子位中的每一个作为控制量子位,第四个量子位(在位置 3)作为目标量子位。最后,我们使用对应于各自概率的角度。

我们看到只有状态 0、1、2 和 4 的值是正确的。这些状态中只有一个量子位是 1 (000=0,001=1,010=2,100=4)。所有其他状态都超过了我们指定的概率。

问题在于prob_to_angle-函数中角度θ的计算。我们将角度计算为目标概率平方根的反正弦。让我们仔细看看这个函数。下图描绘了 f(x)=arcsin(sqrt{x})的形状

首先要注意的是,函数是在 0 和 1 之间的区间内定义的。对于负值,不定义平方根。对于大于 1 的值,不定义反正弦。

第二个要注意的是函数的曲线。prob_to_angle-函数假设量子位处于基态|0⟩.𝜃—that 是我们计算的角度,是向量|𝜓⟩—that 和基态向量|0⟩—that 之间的角度,我们从基态开始。如果我们从另一个态开始,我们需要把这个态包含在𝜃.的计算中我们需要从曲线上各自的点开始。如果在曲线的起点(有一个高梯度)计算一个台阶,在曲线的中间计算一个台阶,就有区别了。

我们试图通过将 0.1 和 0.2 的概率相加,得出点 0.3 的概率。但是,当然,这是不行的。

所以,我们需要用代表 0.3 的角度来“替换”代表 0.1 和 0.2 的概率之和的角度。但是,只有当两个量子位都适用时,我们才需要这样做。

我们可以通过这样一个多重控制的𝑅𝑌门来实现。

来看看效果吧。

我们看到,我们修复了位置 0.3 处的故障。但是我们还没有修复从位置 5 开始的图表。因此,当量子位 0 和 2 为 1 或量子位 1 和 2 为 1 时,我们需要额外的门来进行组合。

7 号位怎么了?突然,它减少了。这是因为,在这种状态下,所有三个量子位都是 1。因此,我们刚刚实现的三个规则都适用。但是我们可以通过再次添加相应的旋转来快速解决这个问题。下面的代码片段描述了完整的代码。

结果表明,这在正态分布的值和因变量之间产生了线性关系。

现在,我们准备利用这种关系。所以,我们来看看一个人需要闪避的整体概率。这包括人的高度是正态分布的事实,并且闪避的需要随着人的尺寸而增加。

总的来说,一个人需要以 0.34 的概率闪开。

为了得到这个结果,你需要在电路中增加一个经典寄存器,并测量位置 3 的量子位。

我们使用七个门实现了这种依赖性。不过,优势在于,只有一个门是具有三个控制量子位的多控制门。三个门有两个控制量子位,三个门只有一个控制量子位。

相比之下,Multinoulli 方法需要 8 个门,每个门有 3 个控制量子位。结果,它会产生一个更容易出错的纠缠不清的系统。

正态分布不仅在自然界普遍存在。但是使用起来也很方便。

量子机器学习要不要入门?看看 动手量子机器学习用 Python

在这里免费获得前三章。

如何在 Python 中使用 DateTime

原文:https://towardsdatascience.com/how-to-work-with-datetime-in-python-26d4092dc484?source=collection_archive---------20-----------------------

5 分钟内 3 个有用的片段。

Elena Koycheva 在 Unsplash 上拍摄的照片

时间是金。

这句与时间的重要性有共鸣的谚语当然不会过时。在初始阶段,所有数据都会自动分配一个“出生日期”。因此,在某些时候处理数据时,不可避免地会遇到日期和时间数据。本教程将带你浏览 Python 中的datetime模块,并利用一些外围库,如pandaspytz

基础知识

在 Python 中,任何与日期和时间有关的事情都由datetime模块处理,该模块进一步将模块分为 5 个不同的类。类只是对应于一个对象的数据类型。下图总结了 Python 中的 5 个datetime类以及常用的属性和示例。

用 Python 解释日期时间类的插图。作者自我图解。

3 个有用的片段

1。将字符串转换成 **datetime** 格式

也许使用datetime最常见的情况是从正确的格式开始。将日期和时间解析为 Python 通常会被解释为字符串,因为它们具有字母数字的性质。在这一节中,我们将介绍如何将字符串列表解析为datetime格式,以及如何将日期和时间数据拆分和组合到数据帧的各个列中。

代码片段 1 的打印输出。作者自我图解。

但是如果一个datetime以一种不寻常的或者不明确的方式被格式化了呢?一个常见的问题是美国和欧洲写作方式的区别。在美式格式中,月份在前面,而在欧式格式中,日子在前面。

美国人和欧洲人解释日期的方式。作者自我图解。

默认情况下,pandas中的to_datetime通过将前 12 位以下的数字(< 12)解析为月份,将对象转换为datetime。例如,2021 年 2 月 11 日将被解析为 2021–02–11,而 2021 年 13 月 11 日将被解析为 2021–11–13。但是,有一个format参数允许您以其他方式定义格式。

import pandas as pd
dt = "02-11-2021"dt1 = pd.to_datetime(dt)
dt1
#output# Timestamp('2021-02-11 00:00:00')dt2 = pd.to_datetime(dt, format = "%d-%m-%Y")
dt2
#output# Timestamp('2021-11-02 00:00:00')

或者,strftime()方法有助于在返回字符串之前格式化datetime。在下面的示例中,原始datetime之间的破折号(-)被替换为齿隙(/),数字月份(02)被替换为缩写的英语术语(Feb)。

import pandas as pddt = pd.to_datetime("02-11-2021")dt3 = dt.strftime('%b/%d/%Y')
dt3#output# 'Feb/11/2021'

由于有多种方法来解释日期(日、月、年)和时间(时、分、秒),所以理解不同的格式代码是非常重要的。下表是常用格式代码的备忘单。有关格式代码的完整列表,请参考[strftime.org](https://strftime.org/)

Python 中 DateTime 的常用格式代码。作者自我图解。

2。使用时区

没有时区信息的datetime对象被称为“naive ”,有时区信息的对象(通常以+HH:MM 结尾,对应于 GMT)被视为“aware”。[pytz](https://pypi.org/project/pytz/)可能是 Python 中最全面的库之一,它简化了时区计算的任务,并考虑了夏令时结束时的模糊时间。

下面的代码片段将向您展示如何在“天真”和“意识到”datetime对象之间进行转换,并有可能使用不同的时区。代码的最后一部分还演示了如何将给定的datetime对象转换成本地时区。这个例子显示了日本和德国的时区代码,对于其他地区,你可以参考这里的。

代码片段 2 的打印输出。作者自我图解。

3。使用区间有条件地比较两个 **datetime(s)**

不可避免的是,有时候我们不得不有条件地对datetime的两个数据帧进行比较。假设您有两个数据帧,第一个数据帧仅由一列datetime组成,第二个数据帧由两列组成,这两列表示间隔和其余列中的其他信息。您的目标是从第一个数据帧中找到匹配的datetime,如果它落在第二个数据帧的区间内,如果是,复制其他列。

使用伪代码解释条件的图示。作者自我图解。

实现这一点的一种方法是使用pd.Interval压缩两个datetime的间隔,然后将它们指定为数据帧的索引,该索引稍后可用于有条件地比较和映射datetime。如果满足时间条件,可以使用一个for循环来复制感兴趣的列。

代码片段 3 的打印输出。作者自我图解。

结论

完整的 Python 笔记本可以在 Github 上找到。

概括来说,这 3 个片段涵盖了 Pythonic】中的 3 个主要功能:

  • 代码片段 1:将字符串转换成datetime,反之亦然,带有代码格式化选项。
  • 代码片段 2:使用不同的时区,包括在 aware 和 naive 之间转换datetime
  • 代码片段 3:有条件地将一个datetime间隔与来自不同数据帧的另一个datetime进行比较,如果发现匹配,就做一些事情。

感谢阅读这篇文章。如果你喜欢我的工作,请考虑加入 Medium 来支持我。谢谢大家!😊

**https://jackyeetan.medium.com/membership **

如何像专家一样处理百万行数据集

原文:https://towardsdatascience.com/how-to-work-with-million-row-datasets-like-a-pro-76fb5c381cdd?source=collection_archive---------2-----------------------

理解大数据

是时候卸下你的训练轮了

图片由Artem Beliaikin上的 像素组成。 除特别注明外,所有图片均为作者所有。

介绍

在我的学习旅程中,最困难的一个阶段是克服我对大规模数据集的恐惧。这并不容易,因为处理百万行的数据集与在线课程不断给我的小玩具数据集完全不同。

今天,我在这里分享我学到的概念和技巧,以应对具有数百万甚至数十亿行的千兆字节大小的数据集的挑战。最终,他们会让你觉得就像处理爱丽丝或者泰坦尼克号一样自然。

这篇文章的笔记本可以在 Kaggle 这里或者从这个回购上找到。

https://ibexorigin.medium.com/membership

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

https://alphasignal.ai/?referrer=Bex

读入海量数据

您的第一个担忧始于加载数据时——将数据集读入工作环境所需的时间可能与您训练模型的时间一样长。在这个阶段,不要使用熊猫——有更快的替代品。我最喜欢的包之一是datatable包,它读取数据的速度可以快 10 倍。

例如,我们将使用datatablepandas加载约 1M 行ka ggle TPS 2021 年 9 月数据集,并比较速度:

来源: Kaggle TPS 九月赛

7 倍加速!用于操作数据的datatable API 可能不如pandas直观——因此,在读取数据后调用to_pandas方法将其转换为 DataFrame。

除了datatable,还有DaskVaexcuDF等。它读取数据的速度比熊猫快好几倍。如果你想看一些实际的例子,请参考 Kaggle 大师 Rohan Rao 关于阅读大数据集的笔记本。

减少内存大小

接下来,我们有记忆问题。在进行复杂计算时,即使是 200k 的行数据集也可能耗尽 16GB 的 RAM。

这个第一手我在上个月 Kaggle 上的 TPS 比赛中经历过两次。第一次是当使用 UMAP 将训练数据投影到 2D 时——我用完了 RAM。第二次是在用 XGBoost 为测试集计算 SHAP 值时——我用完了 GPU VRAM。令人震惊的是,训练集和测试集只有 250k 和 150k 行,包含 100 个特性,而我使用的是 Kaggle 内核。

我们今天使用的数据集有大约 96 万行,包含 120 个要素,因此更有可能出现内存问题:

在带有deep=True的数据帧上使用memory_usage方法,我们可以得到每个特性消耗多少 RAM 的精确估计值——7 MBs。总体来说接近 1GB。

现在,你可以使用一些技巧来减少高达 90%的内存使用。这些技巧与尽可能将每个要素的数据类型更改为最小的子类型有很大关系。

Python 以独特的类型表示各种数据,如intfloatstr等。相比之下,pandas 对每种 Python 都有几种 NumPy 替代方案:

来源:【http://pbpython.com/pandas_dtypes.html】T21

数据类型旁边的数字指的是以该格式表示的单个数据单元消耗多少位内存。为了尽可能减少内存,请选择最小的 NumPy 数据格式。这里有一个很好的表格来理解这一点:

来源:https://docs . scipy . org/doc/numpy-1 . 13 . 0/user/basics . types . html

上表中,uint指无符号,仅正整数。我发现了这个方便的函数,它可以根据上表减少熊猫数据帧的内存(大声喊出这个 Kaggle 内核):

基于数字列的最小值和最大值以及上表,该函数将其转换为可能的最小子类型。让我们将它用于我们的数据:

70%的内存减少令人印象深刻。但是,请注意,在大多数情况下,内存减少不会加快计算速度。如果内存大小不是问题,您可以跳过这一步。

关于非数值数据类型,永远不要在 Pandas 中使用object数据类型,因为它消耗最多的内存。如果特征中的唯一值很少,使用strcategory。事实上,使用pd.Categorical数据类型可以将速度提高 10 倍,同时使用 LightGBM 的默认分类处理程序。

对于其他数据类型,如datetimetimedelta,使用pandas中提供的本地格式,因为它们支持特殊的操作功能。

选择数据操作库

到目前为止,我主要提到了pandas。它可能很慢,但广泛的数据处理功能使它比竞争对手有越来越大的优势。

但是它的竞争对手能做什么呢?先从datatable(再次)说起吧。

[datatable](https://datatable.readthedocs.io/en/latest/start/index-start.html)支持对高达 100 GBs 的数据集进行多线程预处理。在这样的规模下,pandas开始抛出内存错误,而datatable谦逊地执行。你可以阅读Parul Pandey的这篇优秀文章来了解这个包的介绍。

另一个替代方案是[cuDF](https://docs.rapids.ai/api/cudf/stable/),由 RAPIDS 开发。这个包有很多依赖项,可以在极端情况下使用(想想几千亿)。它支持运行分布在一个或多个 GPU 上的预处理功能,这是当今大多数数据应用程序的要求。与datatable不同,它的 API 与pandas非常相似。阅读来自 NVIDIA 博客的这篇文章了解更多信息。

您也可以查看提供类似功能的 DaskVaex

如果你对pandas死心塌地,那么继续阅读下一节。

对数据进行采样

不考虑任何速度技巧或 GPU 类固醇包,太多的数据,嗯,太多了。当您有数百万行时,很有可能可以对它们进行采样,以便保留所有的特征分布。

这样做主要是为了加快计算速度。取一个小样本,而不是对所有数据进行实验、特征工程和训练基线模型。通常,10–20%就足够了。以下是熊猫是如何做到的:

作为证明,我们可以根据样本和原始数据绘制单个特征的直方图:

如您所见,分布大致相同——您甚至可以比较方差进行检查。

现在,您可以使用这个示例进行快速原型制作、实验、构建模型验证策略等等。

使用矢量化代替循环

每当你发现自己渴望使用一些循环函数,如applyapplymapitertuples——停止。请改用矢量化。

首先,开始将 DataFrame 列视为巨大的 n 维向量。如你所知,向量运算同时影响向量中的每个元素,消除了数学循环的需要。矢量化是对数组而不是单个标量执行操作的过程。

Pandas 拥有大量的矢量化函数。事实上,几乎任何能够影响数组中每个元素的函数和操作符在 pandas 中都是向量化的。这些函数比任何循环都要快几个数量级。

还可以定义自定义的矢量化预处理函数,将整个数据帧列作为向量而不是标量接受。这方面令人毛骨悚然的细节超出了本文的范围。你为什么不看看这个很棒的导游?

为基线模型或原型选择机器学习库

机器学习是一个迭代的过程。当处理大型数据集时,您必须确保每次迭代都尽可能快。您想要构建基线,开发一个验证策略,检查不同的特性工程思想是否改进了基线,等等。

在这个阶段,不要在 Sklearn 中使用模型,因为它们是 CPU 专用的。从 XGBoost、LightGBM 或 CatBoost 中选择。这里有一个令人惊讶的事实——XGBoost 比其他两个要慢得多,即使在 GPU 上也是如此。

比 LightGBM 最多慢 10 倍。CatBoost 击败了这两个库,并且随着数据集大小的变大,速度差异迅速增长。在准确性方面,它也经常胜过他们。

当您运行多个实验、交叉验证或超参数调整时,这些速度差异会变得更加明显。

杂项提示

使用 cy thon(C Python)——通常,它比纯 Python 快 100 倍。查看熊猫文档的这一部分。

如果你真的必须循环,在安装 Numba 后用@numba.jit修饰你的自定义函数。JIT (just-in-time)编译将纯 Python 转换为本机机器指令,使您能够获得类似 C、C++和 Fortran 的速度。再次检查文档中的本节。

搜索除 CSV 文件之外的存储替代文件。像 feather、parquet 和 jay 这样的文件格式速度很快——如果存储在这些文件中,只需几秒钟就可以加载十亿行数据集。

阅读关于增强性能扩展到大型数据集的 Pandas 文档。

正在总结…

以下是这篇文章的摘要:

  1. 仅使用像datatablecuDFdask这样的库加载数据。他们总是比熊猫快。
  2. 通过将每一列转换为尽可能小的子类型,可以减少高达 90%的内存消耗。
  3. 选择一个你熟悉的或者基于你需要的数据操作库。
  4. 抽取 10-20%的数据样本进行快速分析和实验。
  5. 用向量思考,使用向量函数。
  6. 选择像 CatBoost 这样的快速 ML 库来构建基线和进行特征工程。

感谢您的阅读!

您可能也会感兴趣…

</tired-of-cliché-datasets-here-are-18-awesome-alternatives-from-all-domains-196913161ec9>

如何在 BigQuery 中使用嵌套数据

原文:https://towardsdatascience.com/how-to-work-with-nested-data-in-bigquery-84f15646b0b1?source=collection_archive---------18-----------------------

关于嵌套数据你必须知道的

冰茶Unsplash 上拍摄的照片

云数据湖和仓库正在兴起——谷歌的 BigQuery 就是一个例子。BigQuery 对于非规范化数据是最强大的。您应该对数据进行非规范化处理,并使用嵌套列和循环列,而不是使用传统的模式,如星型模式或雪花模式。这些列可以保持关系,而不会像关系模式或规范化模式那样降低性能[1]。

什么是嵌套数据?

BigQuery 支持从支持基于对象的模式(例如 JSON)的源格式中加载和查询嵌套和循环数据。

嵌套和重复数据的图示-按作者分类的图像

地址列包含一个值数组。数组中的不同地址是重复出现的数据。每个地址中的不同字段是嵌套数据。

真实的例子

对于使用 BigQuery 的示例演练,我在 geo_openstreetmap 数据集中使用了开放数据集 planet_features在这里,数据是以嵌套格式存储的,所以我们来看看:

SELECT * FROM `bigquery-public-data.geo_openstreetmap.planet_features` LIMIT 1000

这是以下输出中的结果:

结果乍一看还不错。与传统的关系数据库不同,我可以使用数组并保存额外的列。此外,整件事的效果非常好。现在,我想在德国找一家超市,应该使用简单的 where 子句,对吗?差不多了。在这里,你需要 Unnest、 的魔力

SELECT * 
FROM   `bigquery-PUBLIC-   data.geo_openstreetmap.planet_features` 
WHERE  'Netto' IN 
       ( 
              SELECT value 
              FROM   unnest(all_tags)) 
AND    ( 
              'addr:country', 'DE') IN 
       ( 
              SELECT (KEY, value) 
              FROM   unnest(all_tags)) 
AND    ( 
              'addr:city', 'Hamburg') IN 
       ( 
              SELECT (KEY, value) 
              FROM   unnest (all_tags));

这导致了期望的输出:

输出—按作者分类的图像

利用 功能,您还能够 展平数据并由此输出查询结果:

SELECT osm_id,tags
FROM bigquery-public-data.geo_openstreetmap.planet_features,
UNNEST(all_tags) as tags limit 100

拼合数据—按作者排列的图像

当在 BigQuery 中处理嵌套数据并想要查询一些数据时,这可能是您必须知道的最重要的事情。但是,如果您想将数据用于进一步的 ETL 过程,将数据存储在关系数据库中,或者需要键值对作为分类器的属性,该怎么办呢?这里,您不希望数据变平,因为这将导致重复的行,这里您希望数组中的键值对作为新列:

SELECT 
       ( 
              SELECT osm_id) osmid, 
       ( 
              SELECT value 
              FROM   **Unnest**(all_tags) 
              WHERE  KEY = "Address") AS address, 
       ( 
              SELECT value 
              FROM   **Unnest**(all_tags) 
              WHERE  KEY = "name") AS NAME, 
       ( 
              SELECT value 
              FROM   **Unnest**(all_tags) 
              WHERE  KEY = "opening_hours") AS opening_hours, 
       ( 
              SELECT value 
              FROM   **Unnest**(all_tags) 
              WHERE  KEY = "organic") AS organic, 
       ( 
              SELECT geometry) AS geometry, 
FROM   bigquery-PUBLIC-data.geo_openstreetmap.planet_features 
WHERE  ( 
              'Edeka' IN 
              ( 
                     SELECT value 
                     FROM   unnest(all_tags)) 
       OR     'Rewe' IN 
              ( 
                     SELECT value 
                     FROM   unnest(all_tags)) 
       OR     'Netto' IN 
              ( 
                     SELECT value 
                     FROM   unnest(all_tags))) 
AND    ( 
              'addr:country', 'DE') IN 
       ( 
              SELECT (KEY, value) 
              FROM   unnest(all_tags)) - 
AND   ( 
              'addr:city', 'Hamburg') IN 
       ( 
              SELECT (KEY, value) 
              FROM   unnest(all_tags));

嵌套和重复出现的列数据—按作者分类的图像

结论

在我第一次接触嵌套数据之后——我必须承认,我起初不知道该怎么处理它,并且可能有着和电影The occurrence中马克·沃尔伯格一样的面部表情。

GIF by GIPHY

但我意识到,在新的世界里,这样的数据格式是正常的,也是通向非结构化数据世界的方式。新系统通过基于列的数据库提供极高的计算能力和快速的结果。通过上面的例子,您应该能够很好地查询和处理大多数嵌套数据用例。

资料来源和进一步阅读

[1]谷歌,指定嵌套和重复的列

如何使用 COCO 格式的对象检测数据集

原文:https://towardsdatascience.com/how-to-work-with-object-detection-datasets-in-coco-format-9bf4fb5848a4?source=collection_archive---------0-----------------------

入门

使用 FiftyOne 以 COCO 格式定义、加载、探索和评估对象检测数据集的综合指南

来自可可数据集的图像 001298.jpg 在五十一中可视化(图片由作者提供)

微软的通用对象上下文数据集( COCO )是目前最流行的对象检测数据集。它被广泛用于测试计算机视觉方法的性能。

由于数据集的流行,COCO 用来存储注释的格式通常是创建新的自定义对象检测数据集时的首选格式。虽然 COCO 数据集也支持其他任务的注释,如分段,但我将把它留到以后的博客文章中。现在,我们将只关注对象检测数据

COCO 格式”是一种特定的 JSON 结构,规定了如何为图像数据集保存标签和元数据。

许多博客文章描述了 COCO 的基本格式,但是它们通常缺少加载和处理 COCO 格式数据的详细例子。这篇文章将带你了解:

为了做到这一切,我将使用我一直在开发的开源机器学习开发工具 FiftyOne 。它旨在让研究人员和工程师轻松处理和可视化图像和视频数据集,并以各种格式存储注释和模型预测。

您可以通过 pip 轻松安装 51 个:

pip install fiftyone

COCO 2017 验证分裂在五十一可视化(图片由作者提供)

更新:与 COCO 合作的新方式

截至 2021 年 6 月 29 日:在 COCO 团队的支持下,COCO 已经集成到 51 个中,使易于下载在数据集上评估。现在,您可以指定并下载您想要的数据集的确切子集,将您自己的 COCO 格式的数据加载到 FiftyOne 中,并使用由 FiftyOne 的可视化功能增强的 COCO 风格的评估来评估您的模型。

详见本帖本文档

COCO 文件格式

如果您是物体检测领域的新手,并且任务是创建一个新的物体检测数据集,那么遵循 COCO 格式是一个不错的选择,因为它相对简单并且用途广泛。本节将解释 COCO 格式的对象检测数据集的文件和文件夹结构实际上是什么样子。

在高层次上,COCO 格式准确地定义了你的注释(边界框、对象类等)和图像元数据(如高度、宽度、图像源等)在磁盘上的存储方式。

磁盘上的文件

COCO 数据集的文件夹结构如下所示:

<dataset_dir>/
    data/
        <filename0>.<ext>
        <filename1>.<ext>
        ...
    labels.json

数据集存储在一个目录中,该目录包含原始图像数据和一个单独的json文件,该文件包含所有注释、元数据、类别和您可能想要存储的关于数据集的其他信息。如果您有多个数据分割,它们将存储在不同的目录和不同的json文件中。

JSON 格式

如果你要从他们的网站下载 COCO 数据集,这将是instances_train2017.jsoninstances_val2017.json文件。(注意:官方测试集注释对公众不可用)

{
    "info": {
        "year": "2021",
        "version": "1.0",
        "description": "Exported from FiftyOne",
        "contributor": "Voxel51",
        "url": "https://fiftyone.ai",
        "date_created": "2021-01-19T09:48:27"
    },
    "licenses": [
        {
          "url": "[http://creativecommons.org/licenses/by-nc-sa/2.0/](http://creativecommons.org/licenses/by-nc-sa/2.0/)",
          "id": 1,
          "name": "Attribution-NonCommercial-ShareAlike License"
        },
        ...   
    ],
    "categories": [
        ...
        {
            "id": 2,
            "name": "cat",
            "supercategory": "animal"
        },
        ...
    ],
    "images": [
        {
            "id": 0,
            "license": 1,
            "file_name": "<filename0>.<ext>",
            "height": 480,
            "width": 640,
            "date_captured": null
        },
        ...
    ],
    "annotations": [
        {
            "id": 0,
            "image_id": 0,
            "category_id": 2,
            "bbox": [260, 177, 231, 199],
            "segmentation": [...],
            "area": 45969,
            "iscrowd": 0
        },
        ...
    ]
}
  • 信息-关于数据集的描述和版本信息。
  • 许可证 —具有由您的图像指定的唯一 id 的许可证列表。
  • 类别 —每个类别都有一个唯一的 ID。可选地与可以跨越多个类别的超级类别相关联。这些类别可以是您想要的任何东西,但是请注意,如果您想要使用 COCO 上预先训练的模型,您需要遵循COCO 类(或者遵循其他数据集类别以使用其他模型)。
  • 图像 —数据集中的图像列表和相关元数据,包括唯一的图像 ID、文件路径、高度、宽度和可选属性,如许可证、URL、捕获日期等。
  • 注解 —注解列表,每个注解都有一个唯一的 ID 和与之相关的图像 ID。在我们的例子中,您将在这里存储边界框信息,或者为其他任务存储分段/关键点/其他标签信息。这也存储了包围盒区域和iscrowd,表示一个大的包围盒,包围着用于评估的相同类别的多个对象。

创建 COCO 格式的数据集

本节将概述如何获取原始或带注释的数据集,并根据您当前拥有的数据及其格式将其转换为 COCO 格式。

案例 1:我有带注释的数据

在这种情况下,您已经有了一个包含图像和注释的数据集,但是想要将其转换为 COCO 格式。

如果你的数据集碰巧遵循一种不同的通用格式,这种格式被 FiftyOne、如 CVAT、YOLO、KITTI、Pascal VOC、TF Object detection 或其他所支持,那么你可以在一个单独的命令中将其加载并转换为 COCO 格式。

*# Convert a COCO detection dataset to CVAT image format*
fiftyone convert \
    --input-dir /path/to/cvat-image-dataset \
    --input-type fiftyone.types.CVATImageDataset \
    --output-dir /path/to/coco-detection-dataset \
    --output-type fiftyone.types.COCODetectionDataset

如果您的数据不是以支持的格式存储的,那么使用 Python 将其加载到 FiftyOne 并以 COCO 格式导出仍然很容易。想法是将每个图像和相关联的标签作为51 个样本加载,并将它们添加到51 个数据集:

然后,您可以用一行代码以 COCO 格式导出该数据集:

现在你知道了!/path/to/coco-detection-dataset现在包含 COCO 格式的图片和标签。查看下一节,了解如何轻松地将其加载回 Python。

案例 2:我只有原始图像数据

如果您只有未标记的图像,那么您将首先需要生成对象标签。您可以使用注释工具或提供者(如 CVAT标签框MTurk 或许多其他工具之一)生成基础事实标签,或者使用现有的预训练模型生成预测标签。

例如,如果您使用 CVAT 注释您的原始数据,那么您现在可以使用 FiftyOne 命令将其转换为 COCO 格式,就像上一节中一样:

*# Convert a COCO detection dataset to CVAT image format*
fiftyone convert \
    --input-dir /path/to/cvat-image-dataset \
    --input-type fiftyone.types.CVATImageDataset \
    --output-dir /path/to/coco-detection-dataset \
    --output-type fiftyone.types.COCODetectionDataset

或者,如果您想要使用模型来生成预测,您可以将未标记的数据加载到 51 中,并使用51 模型动物园生成预测,然后以 COCO 格式保存数据集。

将 COCO 数据集加载到 Python

本节假设您已经收集了图像并对其进行了注释,以 COCO 格式存储了您的数据集,或者遵循上一节,或者通过自定义脚本手动构建标签 JSON。

为了加载 COCO 格式的数据集,您可以为 JSON 标签文件编写一个解析器,但实际上您应该使用各种工具中的一种来加载它。两个最好的工具是官方可可 API 和 五十一

官方 COCO API用于 Python、Lua 和 Matlab。这些 API 是常用的,它们提供了在数据集上加载和计算数据集范围的评估的基本功能。

如果您正在使用 Python,我建议尝试一下 FiftyOne ,因为它提供了与 cocoapi 相似的功能,以及专门设计的强大 api 和 GUI,使您尽可能轻松地探索、分析和处理数据。

如果您的数据集正确遵循了前面几节中概述的 COCO 格式,您可以使用一个命令将其加载到 Python 中的 51 个数据集:

可视化和探索

现在,您的数据集处于 Python 中,您可以使用 FiftyOne API 轻松访问与您的数据相关联的所有不同信息和标注,并在应用程序中对其进行可视化。

要可视化数据集,请启动 FiftyOne 应用程序:

COCO 2017 验证分裂在第五十一中可视化(图片由作者提供)

通过 API,您可以使用聚合来获得关于您的数据集的统计数据,比如每个类别的检测数量:

与数据集交互的主要方式是通过视图。您进行的每个查询都会为您的数据集提供不同的视图,例如按包含最多对象的样本排序:

第五十一中可视化最多对象的样本(图片由作者提供)

您还可以创建一个视图,根据更复杂的值(如小边界框区域)过滤标签字段:

在第五十一张中看到的小物体视图(图片由作者提供)

51 大脑包含各种方法,允许你分析你的地面真相数据的质量。例如,您可以在数据集中找到最独特的样本,这可以帮助您更好地了解应该添加哪种附加数据:

最独特()和最不独特()的样本在第五十一中可视化(图片由作者提供)

其他大脑方法可以帮助你找到可能的注释错误识别你可能想要训练的硬样本。所有这些都将帮助您训练更好的模型,因为更好的模型通常来自更好的数据。

生成模型预测

您想要创建 COCO 格式的数据集的主要原因是使用它来训练和测试模型。

如今,大多数模型都依赖于将数据加载到 Python 中。尤其是当你使用 TensorFlowPyTorch 时,因为这些库主要是基于 Python 的。例如,使用 COCO API 或 FiftyOne 将数据集导入 Python 使得编写 PyTorch 数据加载器比自己解析标签 JSON 要容易得多。实际上,在你的数据上训练一个模型超出了这篇文章的范围,但是有很多例子可以帮助你进行 PyTorch 对象检测训练甚至 TensorFlow 对象检测 API

如果您刚刚开始,并希望了解一些预训练模型在您的数据集上的表现,生成一些预测的最简单方法是使用51 模型动物园。它包含 70 多个模型,其中许多是对象检测模型。

fiftyone zoo models list

: 如果你厌倦了配置 TensorFlow/PyTorch 模型来使用你的 GPU,可以看看我在 Conda 上的博文。

由于你的数据是以 COCO 格式存储的,所以可以加载到第五十一中,可以在上面生成模型预测,然后在 App 中可视化:

五十一应用中查看地面实况和模型预测(图片由作者提供)

评估模型图

目标检测模型的主要评估度量是平均精度(mAP)。这是一个相当复杂的指标,在其他文章中会有更详细的解释。总之,其计算方法如下:

  1. 如果预测检测与地面真实对象重叠超过某个交集/并集(IoU)值,则将预测检测与地面真实对象进行匹配
  2. 计算每个类别的所有检测的真阳性、假阳性和假阴性的数量
  3. 使用这些 TP/FP/FN 来生成精确召回曲线
  4. 计算每个类别的平均精度
  5. 取所有类别平均精度值的平均值

COCO 评估协议引入了一个额外步骤:map 在 10 个 IoU 阈值范围内求平均值。此外,COCO 对象检测评估还包括计算小、中和大边界框等事物的地图,以及每个图像的检测的变化阈值。

注: 当评估对象检测模型时,预测的类别必须与数据集的类别相匹配。这意味着您必须遵循 COCO 数据集的标签来使用在 COCO 上训练的现成模型,或者您必须微调数据集上的模型,以便它可以预测您的自定义类别。

这个 COCO mAP 值可以用 COCO APIFiftyOne 来计算。假设您有一个 COCO 格式的数据集,模型预测存储在该数据集的predictions字段中,下面将计算 51 中的 COCO 地图:

尽管 mAP 是用来比较模型性能的最流行的单个值,这一指标也有缺点。如果你真的想知道你的模型执行的有多好,你需要挖掘你的数据并查看单个样本的模型预测。

对你的模型的表现建立直觉的最好方法是通过观察那些它有信心但却错了的预测。有了 51,这很容易。例如,让我们创建一个数据集视图,查看假阳性最多的样本:

缺少注释(作者图片)

上面的例子是在这个视图中,显示了一群没有在地面实况中标注的误报对象!在 COCO 格式中,地面真实对象可以有一个iscrowd属性,指定围绕一群对象绘制边界框。这是这个iscrowd框丢失或标签不正确导致误报的众多例子之一。

仅仅通过查看模型图是不可能发现这一点的,这表明了样本级分析对于了解数据集质量的重要性。

关于体素 51

高质量、有针对性的数据对于训练优秀的计算机视觉模型至关重要。在 Voxel51 ,我们拥有超过 25 年的 CV/ML 经验,非常关心如何让社区将他们的 AI 解决方案带入生活。这就是为什么我们开发了 FiftyOne ,这是一个帮助工程师和科学家构建高质量数据集和模型的开源工具。

想了解更多?请在 fiftyone.ai 查看我们的网站。

如何使用 Python 生成器

原文:https://towardsdatascience.com/how-to-work-with-python-generators-d30d8d0af7fa?source=collection_archive---------7-----------------------

通过了解如何编写生成器来提高可读性、内存消耗和性能

照片由卡斯登·沃斯(➡️@卡斯登.沃斯)Unsplash 上拍摄

介绍

您在处理太大而无法容纳在内存中的数据集时是否遇到过问题?当您想要迭代一些需要维护状态的计算值时,您是否编写过复杂且难看的 for 循环?或者你曾经不得不从一个潜在的无限流中消费数据,比如 Kafka 消息队列,并为其编写代码,使其看起来像火箭科学?

如果你对这三个问题中的任何一个的回答是是的那么一个在未来最有可能拯救你的建议就是

使用生成器和生成器表达式!

你现在问你自己;那是什么?什么是生成器生成器表达式?如果是的话,我建议你保持冷静,继续读下去。

在这篇文章中,我将向您简要介绍 Python 中的生成器。与往常一样,我提供了示例代码,您可以进行试验,这将有助于促进理解。

你准备好了吗?让我们开始吧!

生成器和生成器表达式

编写干净、可理解且节省内存的 Python 代码(尤其是在处理海量或流式数据集时)有时被视为一门艺术。然而,这往往比您想象的更容易实现。生成器和生成器表达式是 Python 中的两个概念,在这里可以帮到你。

基本概念

让我们从基础开始,记下使用生成器的一些好处。

生成器允许你声明一个行为类似迭代器的函数。这意味着你可以在 for 循环或 list/dict 理解中使用生成器,就像你在使用 list 或 tuple 一样。因为这是你在每一门 Python 101 课程中学到的东西,所以使用生成器对你来说应该是非常自然的。

你得到的另一个好处是关注点分离单一责任。我这么说是什么意思?我的意思是,在生成器中,您可以专注于如何获取数据。 在应用生成器的 for 循环中,您可以专注于真正重要的事情,即处理数据。您经常会在冗长而笨拙的 for 循环中看到这两件事紧密地联系在一起,尽管这是两个完全不同的任务,也需要不同的知识和能力。

我想强调的最后一个优势,因为它在我们的机器学习和数据科学领域非常重要,就是使用生成器,您可以在处理大型数据集时缓解内存问题。这是如何实现的?这是通过发电机本质上被点燃并忘记来实现的。您可以按需加载数据集的子集,处理该子集,丢弃它,然后继续迭代。这意味着您不必将整个数据集保存在内存中,而只需保存它的一个子集。当然,这只有在您可以进行批处理的情况下才是可行的。

在谈论了发电机的基础和优点之后,现在让我们来看看有趣的部分;编写我们自己的生成器!

如何编写生成器

你们可能都知道如何用 Python 编写函数,以及**return**语句的作用。现在,用**yield**替换**return**关键字,您已经创建了您的第一个生成器函数。祝贺㊗️!相当容易不是吗?

现在是时候看看一些代码了,我们从最基础的开始

这里你看到一个生成器函数,numbers_123产生数字 1、2 和 3。当然,这个函数不是很有用,应该只是作为第一个例子来理解生成器背后的概念。

因为那个函数包含了**yield** 关键字,所以它变成了一个生成器函数。收益表有什么作用?yield 语句向调用者输出其右边的值。此外,它暂停函数保存其所有状态,并在随后的调用中从暂停处继续。因为它只是暂停你可以在一个函数中多次调用 yield 的函数。这与**return** 语句形成了鲜明的对比,后者只能调用一次,因为它终止了一个函数。

如前一节所述,可以像使用列表或元组一样在 for 循环中使用生成器。为了说明这一点,我已经将它添加到代码的第 7 行。

这基本上就是你要写一个生成器函数所要知道的。只要记住收益表的作用,你就做好了准备。如果你想学习如何制作一个类生成器,那篇文章可能也适合你。听起来很棒,不是吗?

照片由 Jen TheodoreUnsplash 上拍摄

除了我们到目前为止所看到的,还有一些关于生成器的更好的语法糖,我想在下一节讨论。

如何编写生成器表达式

在这一节,我想谈谈生成器表达式。听起来很复杂,但这也很简单。

我猜你们中的许多人已经知道如何写一份理解清单。现在,用圆括号代替方括号,你就有了一个生成器表达式。真的很简单不是吗?让我们用一段代码来说明这一点

这里,soun是一个生成器,它产生一个整数和一个浮点数的元组。第 5 行等号右边的表达式是创建生成器的生成器表达式。孕尿激素😃因此,当使用圆括号和 for 循环时,你不是像人们所想的那样创建一个元组,而是一个生成器。记住这一点,你会给很多人留下深刻印象。相信我😃

关于使用发电机,需要注意的是只生产你消耗的。那是什么意思?在示例中,当我们看到第一个大于 50 的number时,我们中断迭代。这意味着,我们既不处理任何大于该值的数字,也不必加载或存储它们。对于这个玩具示例,这并不重要,但在处理真实数据集时,它可能会改变游戏规则。

最后,在进入最后一个示例之前,我想向您展示另一种语法,以简洁地编写从可迭代的生成的代码。听起来又比实际情况更戏剧化。让我们试着从代码来理解它

我们创建了另一个名为some_generator的函数。我们再次看到关键字**yield** ,它将函数变成了生成器。不过这次我们把它和关键字**from**结合起来。这样,我们的 iterable 中得到的每一个元素。这实际上是编写一个 for 循环的简短形式,该循环遍历 iterable 并产生每个元素。又好又甜的 pythonic 糖😃

示例时间

为了了解生成器的全部功能,我创建了一个虚构的示例,我们首先想从服务器下载图像,然后检测每张图像中的所有猫和狗😺 🐶。

为此,我们有两个 API,一个返回所有可用图像的 URL,另一个用于下载图像。获取图像 URL 的 API 是分页的,这意味着我们必须多次调用它来获取所有图像 URL。该服务器可能包含数百万张图片,这些图片可能太大而不适合您的电脑内存。令人惊讶的是,这听起来非常适合使用发电机。让我们看看怎么做。

消化代码

在这个例子中,你可以看到两个发生器get_urlsget_images以及一些检测猫和狗的功能,我将在下面详细解释。

先说get_urls。这样,我们以分页的方式从服务器获取所有可用的图像 URL。由于这是一个生成器,我们可以使用变量current_page跟踪已经检索到的页码,并逐个迭代。一旦页面上返回的 URL 数量少于我们每页请求的 URL 数量,我们就停止检索 URL。对于一些狗食,我在这里使用了前面提到的**yield from** 构造来逐个生成图像 URL。

接下来,我们使用get_images从提供的 URL 迭代器下载每张图片,并把图片作为 NumPy 数组提供给调用者。因此,我添加了一个未指定的函数to_numpy_array,它将来自流的原始字节转换成一个 NumPy 数组。只要假设这个函数存在就可以了,不必关心细节。此外,我已经添加了可选参数max_images,允许您限制下载图像的数量。

最后,我们看看如何利用生成器来下载和处理图像。假设服务器将返回数百万张图像,那么使用这种方法就不会有任何内存问题。这里需要注意的一点是,您可以将生成器作为参数传递给函数。这允许您链接和组合生成器来创建可读性良好的处理管道。

我想在这里再次强调的最后一点是,生成器帮助你编写干净且结构良好的代码。我希望从给定的例子中可以明显看出这一点,在这个例子中,您可以看到数据加载和处理部分之间关注点的清晰分离。

照片由布雷特·乔丹Unsplash 上拍摄

包裹

在这篇文章中,我们看了如何编写和使用生成器和生成器表达式来创建干净和高性能的数据处理管道。我希望在您的代码库中应用它们是多么容易和有益。我向你保证,如果你这样做了,你将会给你的同事留下深刻的印象😎。

感谢您关注这篇文章。一如既往,如果有任何问题、意见或建议,请随时联系我或关注我,无论是在 Medium 还是通过 LinkedIn 。圣诞快乐🎅

如何写一篇大家都能看懂的数据科学帖子

原文:https://towardsdatascience.com/how-to-write-a-data-science-post-everyone-can-understand-2129cb5eb939?source=collection_archive---------26-----------------------

即使对于一个非技术人员来说,解释数据相关事物的六个有用的指南

克里斯多夫·伯恩斯在 Unsplash 上拍摄的照片

我经常写关于数据科学和机器学习的博客。我的本意是写这样的内容,让大家都能看懂。从课题研究到内容定稿,我都尽全力达成自己的意图。我仔细选择对我的读者有用,但很少或在互联网上找不到的主题。因此,我的读者可以通过阅读我独特的内容来学习一些新的东西。

当写一个特定的主题时,内容的组织是非常重要的。我经常以内容效率接近 100%的方式组织我的内容。这可以定义为:

(图片由作者提供)

这不是一个数学公式。然而,你可以从中获得一些直觉:很明显,通过让你最大限度地吸收知识,可以提高内容效率。为此,在撰写数据科学帖子时,我经常在脑海中记住以下六条准则。

1.解释算法背后的直觉

在一篇数据科学文章的开头,大多数人试图描述太多特定算法或过程的数学知识。读者可能不理解他们,并跳过阅读你的内容。我的建议是,你应该从解释特定算法背后的直觉开始,然后转移到数学部分。例如,这里有一部分对椭圆包络技术的解释,直接摘自我在 2021 年发表的《你应该知道的两种离群点检测技术》一文。

椭圆形信封背后的直觉非常简单。我们根据一些标准在数据点周围绘制一个椭圆,并将椭圆内的任何数据点分类为内点(绿色的),将椭圆外的任何观察结果分类为离群点(红色的)——由作者确定

椭圆形信封背后的直觉(图片由作者提供)

这即使对一个初学者来说也能理解。在这里,我并不试图从数学上解释“如何围绕数据点画椭圆”。相反,我解释了技术背后的直觉。现在,我的读者有了一个想法,使用椭圆包络技术来检测可能的异常值。

关键要点:直觉相关图的组合是解释一个算法或过程的好方法。

2.不要打开(解释)黑箱模型

在数据科学和机器学习的背景下,黑盒模型是指一种算法的内部结构,在这种结构中,我们无法看到或理解它是如何工作的。我们只能看到给定输入的输出。神经网络模型就是一个很好的例子。如果我们试图打开(解释)这样一个模型,我们的时间将被浪费,因为很难理解引擎盖下的复杂机制。

与之相反的是白盒模型,在白盒模型中,我们可以看到或理解算法的内部机制。白盒模型是透明的。这种模型的一个例子是决策树。

决策树的一部分:白盒模型(图片由作者提供)

在决策树中,我们可以很容易地解释内部节点如何被划分以产生最终输出。标准非常明确。你可以解释诸如决策树是如何产生这种特定输出的等等。

要点:知道何时以及如何使用一个算法比理解其内部机制更重要。所以,不要试图打开(解释)黑箱模型。另外,请注意,打开白盒模型是可选的。

3.注意模型的可解释性和可解释性

在数据科学和机器学习的背景下,区分可解释性可解释性可能是有用的。这两个术语可以互换使用。然而,有一个明显的区别。

当我们试图 解释 一个 ML 模型时,我们试图解释它的含义、约束(限制)、假设和预测的有效性。 可解释性 主要处理的是透明性。在这里,我们试图解释模型的内部工作原理(黑盒模型是不可能的!)通过更加关注模型训练过程和模型性能改进—作者

为了解释这一点,我使用以下简单的线性回归模型。

y = 𝛽0 + 𝛽1xy = Height(cm)
x = Age(years)

想象一下,上面的模型代表了一个人的年龄和身高的关系。上述模型的可解释性具有以下要素。

  • 人们可以画一个散点图来看年龄和身高之间的关系(线性/非线性,正/负)的本质。
  • 如果关系是线性的,可以计算和解释皮尔逊相关系数来测量关系的强度。
  • 人们可以计算并解释 R 平方(R ) 值,以查看模型捕捉到了多少高度可变性。
  • 人们可以解释𝛽0 和𝛽1 系数。𝛽0 是新生儿的身高(当 x=0 时)。𝛽1 是年龄每增加一个单位,身高增加的厘米数。
  • 人们可能会提到该模型的局限性。例如,一个人可以说,在一个特定的年龄点后,一个人的身高不会增加。
  • 人们可以解释和验证模型的假设。

这是解读部分。现在,我们进入可解释部分。上述模型的可解释性有以下要素。

  • 人们可以解释如何找到𝛽0 和𝛽1 系数的最佳值。人们可以解释找到最优值的成本函数和梯度下降过程。人们可以解释如何选择学习率α。
  • 可以解释用于模型评估的交叉验证程序。人们可以解释折叠的大小和数量的选择。
  • 可以解释用于从几个模型中找出最佳可能模型的超参数调整过程。
  • 如果模型过度拟合数据,可以应用并解释某种正则化(L1、L2 或 L1 和 L2)。

关键要点:所有模型都需要可解释性。但是,可解释性可能仅限于白盒模型,并且是可选的。

4.给出一个动手的方法

这是我在撰写数据科学帖子时考虑的另一个关键问题。我的大部分帖子都给你亲身体验:你通过做来学习。为此,我包含了所有代码示例和数据集。你可以用它们来练习你所学的东西。

5.提及先决条件

提及先决条件将对你的读者有所帮助。建议你把自己的内容也包括进来,作为前提内容。我的许多帖子都与其他帖子相关。基本上我都是从基本面入手,往深里走。当我写高级内容时,我通常会包含指向我自己的基本前提内容的链接。这里有一个例子:

(图片由作者提供)

6.使用一些图像和图表

一幅画胜过千言万语——亨利克·易卜生

数据科学和机器学习也是如此。在这里,一张图片不是统计图或类似的东西。这只是一个简单的图表,但对于向读者解释复杂的理论和过程来说却足够强大。这里有一个例子:

(图片由作者提供)

我在这篇文章的中创建了这个图表来解释网格搜索的超参数调整过程。

结论

你的责任是为你的观众设计有价值和可理解的内容。你可以考虑今天讨论的这些指导方针。你也可以通过考虑读者的反馈找到一些其他的方法。无论哪种方式,您的目标都是最大化前面定义的内容效率。

今天的帖子到此结束。我的读者可以通过下面的链接注册成为会员,以获得我写的每个故事的全部信息,我将收到你的一部分会员费。

https://rukshanpramoditha.medium.com/membership

非常感谢你一直以来的支持!下一个故事再见。祝大家学习愉快!别忘了看看我的一些热门榜单:

(作者截图)

(作者截图)

特别感谢 Unsplash 网站上的 Christopher BurnsT3,他为我提供了一张很好的封面图片。

鲁克山·普拉莫蒂塔
2021–10–06

如何写一份数据科学简历

原文:https://towardsdatascience.com/how-to-write-a-data-science-resume-3cc7de25b149?source=collection_archive---------12-----------------------

照片由西格蒙德Unsplash 拍摄

用一份更有条理的简历最大化你被录用的机会

当我寻找我的第一份工作时,我甚至在电话屏幕前就收到了许多拒绝。我不知道为什么。当时我有一些 Kaggle 和数据科学黑客马拉松的经验。我的简历看起来不错。

现在我知道那很糟糕。我写了很多关于我的项目的不重要的细节,所以简历很难阅读。没有人告诉我如何正确地组织它。这一重要技能在学校或大学里没有教授。我是吃了苦头才知道的。

在下面这篇博文中,我想填补这个空白。我向你展示如何正确组织你的简历。我希望我的建议能增加你被聘用的机会。

为什么需要一份好的简历?

雇主的目标是尽快找到一个好员工。空缺的职位吸引了许多候选人。但是一个雇主的时间是有限的,所以他只能面试几个候选人。他想让最有前途的候选人进入下一步,以增加雇佣机会。因此,雇主筛选简历是为了找到符合他对“有前途的候选人”和“好员工”的理解的人。

过滤是一个快速的过程。一些研究表明,的人力资源部门花了几秒钟看每份简历。没有人会花太多心思去挖掘候选人是否合适。如果一份努力工作的人的简历没有组织好或者难以阅读,它可能会被扔进垃圾桶。

创建简历时,你的任务是最大化你通过筛选的机会。让雇主的决定尽可能简单。表现出你能胜任这份工作,或者你能学会快速完成这份工作。你的简历应该有条理。你在之前项目中的贡献和成就应该是显而易见的。用清晰的信息传递让你的简历脱颖而出。

成功的简历构建

让自己变得有价值

我认为许多将要阅读这篇文章的人都是有抱负的数据科学家。你想找到你的第一份工作,但你还没有任何工作经验,具有讽刺意味的是,这往往被列在实习生和初级职位的要求中。

如果没有任何工作经验,就自己做项目吧!两三个组织良好的项目足以找到第一份工作:

  1. 在最近的 Kaggle 比赛中至少取得前 10%的成绩并发布代码。
  2. 制作一个带有分析的公共 Kaggle 笔记本。
  3. 做一个宠物项目或参加黑客马拉松,展示你的成果。
  4. 写下你参加过的数据科学课程的笔记。

我推荐读一篇关于这个话题的优秀文章:

https://ternaus.blog/tutorial/2020/08/28/Trained-model-what-is-next.html

项目不会推销自己

候选人假设硬项目推销自己。并不总是这样。你的简历会被那些没有足够时间深入挖掘或者不太熟悉机器学习(或者两者都有)的人阅读。让他们的生活更轻松。明确地展示为什么你很适合。

例子: 我在 ImageNet 上用新的增强策略训练了一架 ResNet-101。它让我达到了 92%的最高准确率。

好吧,那么…什么?如果你不熟悉计算机视觉或者你不照看 Imagenet 排行榜,你不知道这个结果好不好。你没有上下文。很难评价候选人的成就。当我写这篇文章时,92%的准确率比最先进的高 2%。用 ResNet 实现这样的结果简直是开创性的。

组织您的项目

为了让你的贡献和成就显而易见,试着通过回答以下四个问题来组织你所有的项目:

  1. 你为什么这么做?你想解决什么问题?展示项目的最终目标是什么。
  2. 你做了什么?解释你是如何处理这个问题的。如果你能在会议上展示代码、论文、博客文章或演示文稿,那就去做吧!
  3. 你是怎么做到的?展示你用过的工具。对于 HR 来说,将它们与需求中的工具相匹配会更容易。只列出你实际使用过的工具。在面试中,你可能会被问到你是如何使用它们的。
  4. 你实现了什么?在技术和业务指标中展示您工作的量化结果。只写实际结果。不要呈现比实际更好的结果。

让我们来看一个例子,以及我们如何改进它。我从实际的简历中拿了一个项目,做了一些小的改动。我做了修正版;数字取自头部。先看例题,自己试着改进一下,再往前走。

例子

NLP 模型基准测试的自动化:在芬兰超级胶水数据集上自动测试类似 Bert 模型的工具。

让我们从第一个问题开始— 这个项目的动机是什么?如果人们使用不同的管道进行基准测试,结果是不可靠的。我可以假设,如果没有一个通用的管道基准测试是困难和耗时的。我们的目标是标准化程序,因此我们的结果 a)可靠,b)易于重现 c)快速重现。

第二个问题— 你做了什么来实现目标?我可以假设一个人编写了一个以模型和数据集作为输入并输出分数的管道。最好的分数将会出现在公司的名人堂里。

继续— 你用了什么工具?在这种情况下,最有可能的是,一个人使用 HuggingFace 来获得 Bert 模型,使用 PyTorch 来训练它们,使用 DVC 来跟踪数据集,使用 git 来跟踪代码,使用 Docker 来确保可再现性,使用 MLFlow 来存储结果。

你取得了什么成就?假设有了新工具,基准测试变得更加容易。假设我们必须在没有工具的情况下跟踪数据和模型。这很耗时,而且错误也很常见。有了新的工具,基准测试变得像按一个按钮一样简单,那么多(多少?)团队开始使用它(频率如何?).

结合一切:

NLP 模型基准测试的自动化。

*目标是标准化公司的 NLP 模型基准。标准化使我们能够简单快速地复制实验,并保证实验结果的可靠性。

*我实现了一个管道,它将模型和数据集作为输入,并输出选定的指标。所有模型都保存在公司仓库中。具有最佳指标的型号显示在公司排行榜上。

*工具:HuggingFace、PyTorch、DVC、git、Docker、MLFlow。

  • Resulted pipeline 将对新模型和数据集进行基准测试所需的时间从 4 小时减少到了 15 分钟。两个团队每天都在使用新管道。新管道将每个基准的成本降低了 10%。

选择合适的 Latex 模板

前往背页的,选择适合您的模板。我推荐使用两栏的简历,因为这样更容易阅读。

尽量把你的简历放在一页纸上。如果你有很多项目或者丰富的出版物历史——在你的简历中提到几个,并提供一个 Github 中存储的完整列表的链接。

将链接加粗或加下划线。如果员工 pdf 阅读器不显示链接,则更容易发现链接(例如,Slack 在打开的 pdf 中不显示链接)。

我的简历上没有照片。拍出好的专业照片是一种努力。这不是必需的,也没有人真的希望你有一张照片。

检查错误和打字错误

错误和错别字很烦人。在提交之前,我用 Grammarly premium 反复阅读我的文本。让你的朋友检查你的简历是个好主意。他们可能会用新的眼光发现错误。

寻求公司内部的证明人

试着找一个在公司工作并且可以推荐你的人。会增加你通过 filer 的几率。通常,如果你被录用,推荐你的人会得到现金奖励。所以,这是双赢的局面。

找朋友或者人脉弱的推荐人总是比较好,但是先在 Linkedin 上写也是可以的。找到一个当前员工的 Linkedin 个人资料,与他或她联系并写一条消息。不要害怕向陌生人寻求推荐。如果我看到那个人努力写作,我愿意帮忙。对我来说,付出的努力是动力的标志。如果一个人找到了我,那就是他可以谷歌的标志。我喜欢和这样的人一起工作。

重要!尊重他人:不要给别人发改了公司名称的相同信息。通过简短和具体来尊重他人的时间。通过诚实让别人愿意帮助你。

消息的内容应该有五个重要的块。如果你决定不要求推荐信,你可以用同样的方法和问题来写求职信。

  1. 你想从一个人身上得到什么?
  2. 你为什么想在公司工作?
  3. 为什么你认为你适合?
  4. 附上简历和求职信。
  5. 还要联系谁。

示例:

你好!

我在公司名称找到了一个开放的数据科学家职位。你能推荐我吗?

我看了 Ivan 关于你做的开源框架的演讲。我自己也做过类似的项目,代码的链接:link。我想加入公司,因为我喜欢解决困难的工程任务,我可以从团队中学到很多东西。

附上我的简历和求职信。我希望尽快收到你的来信!

如果我联系错了人,你能告诉我该联系谁吗?

丹尼斯。

摘要

为了增加被聘用的机会,你必须让自己有价值,并在简历中表现出来。写一份合适的数据科学简历不是一件困难的事情,但是很费时间。你为组织和润色简历所付出的努力会有回报的。

附加材料

在下面的两个视频中,作者提供了我在这篇博文中没有提到的几个重要细节。我建议观看它们。

如何写出一篇优秀的数据科学论文

原文:https://towardsdatascience.com/how-to-write-a-great-data-science-thesis-77cda46721bc?source=collection_archive---------7-----------------------

办公时间

一些帮助你尽可能顺利地写论文的技巧和诀窍!

关于如何写一篇伟大论文的手册大概有一千多本(我最喜欢的几本可以在这里找到这里,这里这里,这里这里)。他们会强调结构、内容和风格的重要性。他们会敦促你先写下你的方法和结果,然后是文献综述、引言和结论,最后写摘要或摘要。写得清楚直接,时刻牢记读者的期望。所有这些技巧都非常有价值,但是哪些技巧适用于数据科学领域的学术写作呢?

数据科学学生来自各种领域,不一定是有经验的技术论文作者。因此,在写一篇伟大的数据科学论文之前,应该阅读哪些具体的技巧呢?两周前,我完成了数据科学硕士学位,感觉自己已经是这个领域的专家了。我和大部分同龄人的奋斗历程还记忆犹新,在此传达最实用的解决方案。

照片由 Calvin UyUnsplash 上拍摄

选择研究课题

在许多情况下,决定和明确阐述一个创新的、相关的和可管理的研究问题是整个过程中最具挑战性的方面。也许,你需要为一个公司或研究项目写论文,在那里你会从你的导师那里得到更多的指导和指示。或者,你可能需要自己想出一个研究课题。

在外部组织

在一家公司写论文简化了选择研究主题的任务,因为你可能会被安排从事特定的业务或研究问题。然而,这里还有一些你应该知道的特殊问题。作为一名数据科学家,与利益相关者的沟通非常重要,从这个意义上说,在一家公司写论文是一次宝贵的经历。至关重要的是,在项目开始时,你要了解公司运营的背景,以及他们要解决的问题和他们对你的期望。因此,你应该清楚地表明你的想法,你能做什么和不能做什么,以及你需要从组织那里得到什么来完成一个成功的研究项目。

为自己

在没有外部机构帮助的情况下写论文既有利也有弊。从好的方面来说,你可以自由选择你喜欢的主题。如果你有特别的兴趣或激情,做相关的研究可以给你一个良好的开端,让整个项目更加愉快。但是如果你心里没有任何特定的主题呢?想出自己的研究计划可能相当具有挑战性,但不要惊慌,幸运的是机器学习研究通常遵循一种特定的模式。考虑机器学习涉及使用现有数据集预测或分类新数据点。因此,传统的机器学习研究是通过使用不同的机器学习方法来解决特定的(预测或分类)问题,然后比较它们在准确性、效率(使用的时间&资源)和在组织环境中的适用性方面的性能来进行的。

额外提示:

  • 不要把事情搞得太难,选择一个有足够数据的主题。
  • 头脑风暴一下你读过的有趣的课程和文章,或者你将来想从事的研究和职业,并尝试制定一个学术相关的话题,你可以探索至少两个月。
  • 目标是制定至少 3 个引人注目的研究主题,并附带研究问题,并与你的主管讨论最佳和最可行的选择。
  • 想想自己喜欢的方法、技术、算法;如果你对神经网络充满热情,那么一个只有有限数据的主题可能不是最聪明的。

灵感:

如果你缺乏灵感,浏览一下以前的论文会很有帮助。这是让自己熟悉数据科学和机器学习领域的学术研究及其习俗、惯例和最佳实践的好方法。浏览过去的论文帮助我理解了典型的机器学习研究论文是如何构建的,并导致了许多关于有趣的统计和可视化的想法,我可以将这些想法纳入我的论文中。下面,我整理了一个包含以前论文的伟大资源和数据库的列表。

照片由斯科特·格雷厄姆Unsplash 上拍摄

研究过程

当你连续几个月都在做一个研究项目时,你无疑会有无数的疑问和问题,而你不会马上找到答案。关于如何解决某些问题,阐明你的想法或研究哪些方法。为了你自己的健康和内心的平静,请不要试图为每一个问题找到完美的解决方案,也不要试图探索每一条出路。不完美是不可避免的,在某种意义上甚至是有益的。当你被某个特定的问题困扰时,把它写下来!最后,你可以在你的讨论中使用这个烦恼列表来解释局限性和对未来研究的建议。在这个过程的每一个阶段写下你对不同选择的论点,这样当你写下你的方法的动机时你就可以背诵了。

一些额外的提示:

  • 通常鼓励通过在线分享你的代码来实践开放科学。一个很好的方法是使用 GitHub,在这里你可以将你的代码存储在一个仓库中。尝试总是注释你的代码,另外你可以使用自述文件更详细地解释你的决定。要了解更多关于 GitHub 的信息,请点击此链接
  • 最后,问问你的论文导师是否可以记录你的会议。因为他们是对你的论文进行评判和评分的人,他们的建议特别有价值,如果你问了很多问题,回放录音会很有帮助。

把一切都写下来

最后,你已经完成了你的研究,写下了你在研究项目中的考虑和程序,并准备写你的最终论文。最后,在这个过程的最后一部分,有一些实用的小技巧可以帮助你:

  • 如果你正在努力构建一个特定的句子或者寻找一个完美的词来描述某事,简单地谷歌一下或者使用同义词词典上的同义词总是能帮助我激发灵感,让我的写作流畅起来。
  • Upwork 上找一个乳胶专家,从风格和布局上对你的作品进行最后的润色。这可以大大改善你的最终作品的外观,相对便宜和快速。
  • 你的拼写和句子结构也是如此。尤其是在连续几个月写论文之后,你可能会对最简单的错误视而不见。向朋友或家人寻求帮助,找出错误和结构怪异的句子,或者在上述平台上找人。
  • 将樱桃放在最上面的一个令人惊奇的方法是为你的项目设计一个交互式例子。这并不是对所有项目都可行或有用的,但是如果你能让用户与你的模型互动和玩耍,这能真正让人们相信你的项目在实践中的价值。为此,查看诸如 DashStreamlitShiny 之类的库。

庞余浩Unsplash 上拍照

如何写一份优秀的数据科学家简历——适合初学者

原文:https://towardsdatascience.com/how-to-write-a-great-resume-as-a-data-scientist-for-beginners-139a8ad4191e?source=collection_archive---------20-----------------------

地面零点

通过描述每个数据科学家必备的三项技能

马克斯·蒂托夫Unsplash 上拍摄的照片

作为一个近几年聘请了很多 AI 工程师的 AI 总监,我想和大家分享一下我是如何根据简历挑选候选人的。在大多数公司,人工智能工程师的招聘流程有许多步骤,如带回家的人工智能任务和技术面试。但是,您需要被选中来完成这些步骤。糟糕的简历从来不会出现这种情况。在这里,我描述了如何展示你应该在简历中突出的必备技能,以便在接下来的步骤中被选中。技能包括但不限于编码机器学习、数据

如果你想从事数据科学家的职业,你可能会有一些疑虑。我写了一篇文章来尽可能地揭示数据科学行业。这可能会帮助你找到重要问题的答案。你可以在下面找到。

—编码

作为一名数据科学家,你每天都在编码。所以,你必须知道编码和向你的潜在雇主展示的最佳实践。问题是怎么做?没有什么比看到候选人在 Github 上开发了一个文档完善的 ML 包更让我兴奋的了。你不需要开发复杂的库;然而,你必须表明你了解编码的所有基础知识。

编码—来源: giphy 通过 Monstercat

展示这一点的最佳方式是在 Github 或 Bitbucket 上放置一个链接,指向过去的 ML 项目。你必须在你的项目中实现软件开发的最佳实践;否则,三思而行。例如,你的项目必须有一个简洁、易读、有用的文档。另外,代码必须基于特定的风格指南编写,比如 Python 中的 PEP8。最后,但同样重要的是,代码必须有一系列测试,这些测试可以在开发的每个步骤中轻松运行。拥有一系列的测试表明你可能意识到了测试驱动开发的基础,并且意识到了测试在开发过程中的重要性。作为一个例子,你可以在下面的 Github 上找到一个我开发并托管的简单 Python 包 sent2vec 。你应该试着或多或少地构建一些类似的东西。

https://github.com/pdrm83/sent2vec

—机器学习

一个常见的误解是,破坏机器学习技能只是为了“训练 ML 模型”。一个成功的 ML 产品不仅仅是训练一个 ML 模型。你必须在简历中表明你能够建立和维护一个 ML 渠道。如今,人们可以使用 Python 中的 scikit-learn 库,通过几行代码来训练 ML 模型。然而,你需要有真实世界的经验,才能知道诸如“如何正确地测试一个 ML 模型?”“如何维护和更新 ML 模型?”。在你的简历中展示的另一个重要技能是你是否知道“如何在云中或在特定应用的硬件上提供 ML 模型?”。你可以使用不同的技术,如 AWS 或 Databricks,但重要的是在你的简历上表明你知道 ML 模型在服务于客户之前是没有用的。

简而言之,你必须让你的潜在雇主知道你意识到了从培训到服务的 ML 管道的重要性。例如,您可以从以下陈述中获得一些提示,并根据您过去的经验定制它们,以描述您的技能:[a] “使用 Spacy、CircleCI、DockerHub、Terraform 和 AWS 构建、部署和管理一个 NLP 解决方案来分析法律文档”,或者[b] “开发了一个完整的 ML 管道,包括特征提取、模型构建、模型评估和模型选择”。你可以在下面的文章中阅读更多关于构建 ML 产品的常见错误。

—数据

许多候选人忽略了这个皮拉尔。如果你是一个优秀的程序员,并且知道各种机器学习技术,这仍然不意味着你是一个优秀的数据科学家。要成为一名优秀的数据科学家,您必须知道许多以数据为中心的问题的答案,例如:

  • “如何设计可扩展的数据管道?”,
  • "如何衡量和评估数据的质量?",
  • "如何识别数据与业务目标的相关性?",或者
  • "如何有效地收集大量数据?"。

数据来源:giphyviaGiflytics

说你必须在简历中表明你处理过大量数据,并且对糟糕的数据架构或低质量的数据可能带来的挑战有洞察力。因此,一定要在简历中强调你在过去的经历中解决了这些挑战。

例如,可以这样写:“设计成像设置的规范,如相机型号和照明模式,以确保收集低噪声的高质量数据。”简历中的这句话表明候选人意识到了质量数据和数据收集系统的重要性。

临终遗言

为了能够参加数据科学家职位的面试,你必须在简历中展示以下技能:

  • "如何用 Python 编写符合所有最佳实践的代码?",
  • "如何建立、评估、服务和管理一个 ML 管道?",
  • “如何解决大量低质量数据带来的问题?”。

请注意,没有什么是保证的,但如果你采取这些步骤,你的机会将会增加。

感谢阅读!

如果你喜欢这个帖子,想支持我…

https://pedram-ataee.medium.com/membership

如何为专业人士撰写一份出色的数据科学家简历

原文:https://towardsdatascience.com/how-to-write-a-great-resume-as-a-data-scientist-for-professionals-98359ab19a6e?source=collection_archive---------15-----------------------

地面零点

通过描述高级数据科学家必备的三项技能

照片由宣阮Unsplash 上拍摄

我最近写了一篇关于如何为初学者写一份数据科学简历的文章,受到了社区的好评。我决定将那篇文章扩展到那些更有经验但仍需要润色简历和技能才能进入高级数据科学职位的人。这可能会帮助你们中的一些人找到一些问题的答案,如“作为一名高级数据科学家,我应该如何向潜在雇主展示自己”或“我应该获得什么技能才能在公司的数据科学阶梯上向上爬?”请注意,无论你是否具备所需的技能,你都必须修改你的简历,让自己看起来像你一样有技能。你必须在简历中三大技能下描述你的技能:软件架构深度学习大数据

—软件架构

如果你想参加数据科学高级职位的面试,你必须完全了解软件开发的标准实践。我在上一篇文章中简单解释了一下。除此之外,您必须知道如何为数据科学项目设计一个易于理解和维护的可扩展架构。在这种情况下,每个人都可以为项目做出贡献,并帮助您保持项目正常运行。现在,问题是如何向潜在雇主展示你拥有这些技能。

一个简单但不是最好的办法,就是在简历上强调你知道各种 设计模式 软件架构 ,尤其是数据科学项目。了解不同的设计模式有助于您编写更高效的查询,而了解各种软件架构有助于您构建可伸缩的架构。例如,如果您使用分层模式开发一个数据科学项目,您可以删除不必要的依赖关系,让不同的团队参与项目。

数据科学项目的分层模式—作者图片

作为一名面试候选人的人工智能主管,我希望看到这些技能的运用。因此,我建议使用这些技术开发您的示例项目,即您在 Github 或 Bitbucket 上托管的项目。当我审查一个代码库时,我可以很容易地识别出一个经过深思熟虑的架构。我确信你未来的雇主也能做到这一点。查看候选人的 Github 账户已经成为审查他们简历的标准程序。

—深度学习

这时,你必须意识到知道如何开发和维护一个 ML 管道的重要性。但是,作为高级角色的候选人,你必须知道深度学习等高级机器学习技术 。你必须掌握与你申请的工作岗位相关的最佳深度学习架构。例如,如果你想从事自然语言处理方面的工作,你一定要了解 BERT 或 GPT3。你可以在下面的文章中读到更多关于伯特的内容。

另外,你的简历必须表明你有使用深度学习开发解决方案的实践经验。例如,它必须表明你知道以下问题的答案:

  • 培训过程中如何管理衔接机制?
  • 如何将迁移学习应用在一个预先训练好的网络上?
  • 如何最小化冗余计算
  • 如何降低一个深度学习技术的灵敏度

注意,虽然深度学习是机器学习的一个子集,但它的具体细节是不同的。

火花—来源: giphy

—大数据

传统的数据处理技术在非常大的数据集上失败了,也就是大数据。例如,当你需要在计算机内存中加载数据时,你会受到内存大小的限制。如今,由于大多数数据集很容易超过这个限制,分布式数据处理技术Apache Spark已经变得流行起来。在单台计算机无法做出相应响应的情况下,它们也有助于处理实时数据流。

作为一名高级数据科学家,你必须拥有这些技术的实践经验,并在简历中明确提到这一点。例如,人们可以这样写:“使用 Spark ML 和 PySpark 开发了一个 ML 流水线”“使用 Spark 和 Databricks 构建了一个高效的数据处理流水线”。这些陈述简要展示了您对 Spark 技术以及 Databricks 的了解,Databricks 是一个基于云的统一平台,用于存储和处理大数据。

近年来引进了许多技术;然而,你只需要知道当前使用的是哪一个。所以,我建议不要在简历上填写各种大数据技术的清单。最好选择一个,并解释你用它做了什么。

临终遗言

为了能够参加高级数据科学家职位的面试,你必须在简历中展示以下技能:

  • 如何创建一个可扩展且易于维护的软件架构?
  • 如何实现高级算法,例如深度学习?
  • 如何搭建一个高效的管道来存储和处理大数据?

请注意,没有什么是可以保证的,但是你可以通过记住这些笔记来增加你的机会。

感谢阅读!

如果你喜欢这个帖子,想支持我…

https://pedram-ataee.medium.com/membership

如何根据数据科学项目撰写科学论文

原文:https://towardsdatascience.com/how-to-write-a-scientific-paper-from-a-data-science-project-62d7101c9057?source=collection_archive---------11-----------------------

实践教程,学习

关于如何将数据科学项目转化为精彩的科学论文的一些提示。

斯科特·格雷厄姆Unsplash 上拍照

撰写科学论文通常与学者和研究人员联系在一起。事实上,工业和其他人也可以从科学生产中受益,因为:

  • 从概念的角度来看,发表到期刊或会议记录中会使你的工作更加严谨
  • 出版一部科学著作会让你成为某个研究领域的专家
  • 科学出版物可以添加到公司/个人课程或文件夹

如果你仍然想知道写科学论文的好处,你可以阅读下面的文章:在同行评审期刊上发表研究论文的 8 个理由

希望我已经说服您写一篇科学论文,在本文的剩余部分,我将描述如何将一个数据科学项目转化为精彩的科学出版物,提交给一些期刊或会议。

照片由安德鲁·尼尔Unsplash 上拍摄

1 定义主题

首先你要明确你的项目解决了哪个问题,比如如何提高产品销量,或者从评论中提取情绪。你可以为你的项目写一个简短的总结,最多 200 字。这是你论文摘要的初稿。

现在你可以把你的总结缩短成一句话。这是你论文的临时标题。

然后你可以把你的摘要分成 3-4 个关键词。我建议你包括非常常见的关键词,如机器学习,自然语言处理或数据可视化。

一旦写好了摘要,你就可以搜索关注你的主题的期刊或会议。你可以在 Wiki 上搜索关于你的主题的会议论文征集

会议可以分为不同的等级,从 A 级(最有声望)到 C 级(不太有声望),一直到没有等级的会议。

我强烈建议从 B-C 级别的会议开始,因为如果你还没有写任何文章,很难在 A 级会议上发表。

如果你想为一个期刊写作,你可以在Scimago Journal&Country Rank网站上查看期刊列表,那里提供了一个搜索栏,你可以在那里搜索你的主题。一个好的期刊表现为高 h 指数,以及高四分位数(典型的是 Q1 或最大 Q2)。

一旦选择了适合你的主题的期刊/会议,你应该深化期刊/会议的目标,并重写你的摘要以适应它。我强烈建议你下载会议/期刊论文模板并在写论文时使用。

2 研究文献

现在你已经准备好环顾四周:其他人在相同的话题上做什么?换句话说,你应该搜索类似的论文。这部分是最难的,因为它需要学习。

你可以利用一些网站来搜索类似的论文,比如谷歌学术或者 IEEE Xplore 。你应该搜索至少 8-10 篇类似的论文,可能是最近的论文。如果你没有找到任何论文,也许你没有用正确的方法搜索。你应该再试一次,也许改变关键词,直到你找到最少数量的论文。

现在你可以研究阅读过的论文了。迈克尔·伯克写了一篇有趣的文章描述如何阅读科学论文。

你可以通过查看你所在领域的顶级会议记录来搜索其他文章,比如本文中的文章。

当你阅读这些文章时,我强烈建议你为每篇文章写一个摘要。或者,您可以将相似的文章分组,并描述它们相似的方法。

你也应该注释其他文章和你的文章之间的区别,以及相对于艺术水平,你的作品的附加值是什么。

在阅读结束时,你可以扩展你的摘要,也包括最后一个方面,也就是你作品的附加价值。

现在是建立书目初稿的时候了。检查期刊/会议所要求的风格,并根据它格式化你的参考文献。您可以利用每篇论文下的谷歌学术引文选项来导出参考书目,如下图所示:

作者图片

3 写介绍

你准备好扩展你的论文了。再次提取摘要,并尝试扩展它,以便为你的项目提供更多细节。你不需要添加技术细节,但你应该对你的工作进行深入概述。你也应该给你的作品添加一个背景,比如这个想法是从哪里来的。这一新段落是导言的草稿。这个部分的长度是可变的。但是,我建议至少 1 页,最多 2 页。

简介应概述:

  • 你作品的背景
  • 你工作的目标
  • 实现目标所采用的方法
  • 取得的成果

引言的所有部分都应该保持平衡,因此你应该给它们保留相同的段落数,或多或少。

照片由 NeONBRANDUnsplash 上拍摄

给你的论文一个结构

到目前为止,你已经写好了摘要和引言以及相关工作部分的草稿。你已经准备好给你的论文一个结构了。我强烈建议你再看一遍引言,并把它分成几个段落。然后,您可以为每个段落添加一个部分。

提醒一下,在写论文的时候,你可以添加、删除或修改任何你已经写好的部分。

该文件或多或少应包含以下部分:

  • 摘要(已经写好)
  • 介绍(已经写好)
  • 相关作品(已写)
  • 方法学
  • 实验
  • 结果/讨论
  • 结论和未来工作。

4.1 方法

在这里,你应该描述你的项目背后的理论,而不是描述所采用的技术或数据集。例如,您可以描述项目的架构,包括机器学习管道,或者执行机器学习任务所采用的算法。

4.2 实验

在本节中,您应该说明数据、数据结构、数据的存放位置、数据集的大小以及是否对其进行了清理或丰富。您还可以添加数据样本,以更好地描述您的数据集。此外,如果你的数据覆盖了一个时间段,你描述它。

一旦描述了你的数据源,你应该描述你如何将数据集分成训练集和测试集,训练阶段有多长,以及其他类似的东西。

然后你可以描述你如何衡量你的结果的好坏,如果适用的话。例如,你可以给出准确度、精确度、召回率或其他使用的度量标准的简短定义。最后,您可以描述所采用的技术,比如 Python 库(scikit-learn或其他)。

概括地说,本节可分为以下几个小节:

  • 数据描述
  • 指标描述
  • 采用的技术

4.3 结果/讨论

这一部分旨在证明你到目前为止所描述的是真实的。因此,在这一部分,你应该描述你的发现。可以用。你不必把所有生产的数字,但只有那些有趣的。本节的附加价值可能是与其他工作的比较。

一个好的讨论不应该描述数字,但它可以讲述一个故事。因此,你可以将这部分转化为一个故事。

4.4 结论和未来工作

在这里,你应该概述一下所展示的工作,以及它的局限性,对社会、行业和研究的影响。此外,你应该加上未来的工作,比如扩展你的数据集,调优一些你在本文中没有考虑到的参数以及其他类似的东西。

5.审阅并提交论文

一旦你完成了你的论文,休息一天左右。然后,回到你的论文上再读一遍。当然,你会发现很多东西需要修改。因此,当你读这篇论文时,你可以改正它。至少把整篇文章读 4-5 遍

如果可能的话,请一些朋友或同事阅读你的论文。根据他们的建议修改论文。

最终,你的论文可以提交了!您可以在期刊/会议的提交系统中创建一个帐户并发送它!

照片由布鲁克·卡吉尔Unsplash 上拍摄

摘要

在本文中,我举例说明了一些将您的数据科学项目变成精彩的科学出版物的指导方针。

总结:

  • 首先写摘要和标题
  • 搜索相似的工作,并写出相关的工作部分
  • 写介绍
  • 编写其他部分
  • 回顾论文
  • 提交论文。

相关著作

https://alod83.medium.com/how-to-design-a-data-journalism-story-b2e421673b6e

新到中?您可以每月订阅几美元,并解锁无限的文章— 点击此处

如何编写出色的 Python 类

原文:https://towardsdatascience.com/how-to-write-awesome-python-classes-f2e1f05e51a9?source=collection_archive---------1-----------------------

这是一种魔法

Artem Maltsev 在 Unsplash 上拍摄的照片

Python 是大多数数据科学和机器学习项目的首选语言。然而,并不是每个数据科学家都一定是经验丰富的 Python 开发人员,他们知道并利用了该语言提供的所有优秀特性。这当然可以理解,但同时也是不幸的。为什么?因为了解一门语言的细节可以让你编写出重复性更低、可读性更强、可维护性更好的代码。总的来说,当充分利用一门语言时,你的代码质量会变得更高,更重要的是,你和你的同事会有更多的乐趣,我想这是我们都喜欢的。

这就是为什么我想帮助提升你的 Python 知识,这样你就可以写出更棒的代码,也许会给你的伙伴或同事留下深刻印象,并获得更多乐趣!具体来说,在这篇文章中,我想谈一谈所谓的邓德、特殊或神奇的方法。好奇想知道这些是什么?让我们开始吧。

神奇的方法

正如标题所言,我们将讨论 Python 魔术方法。有时,你可能还会读到关于 dunderspecial 方法,它们指的是同一个东西。在这篇文章中,我将使用术语魔术方法。那么那些神奇的方法是什么呢?

基础

魔法方法是属于一个类的函数。它们可以是实例和类方法。你可以很容易地识别它们,因为它们都以双下划线开始和结束,也就是说,它们看起来都像__actual_name__。这也是术语 dunder 的来源,ddoubleunderscores。我花了一段时间才发现😃

可能最重要的是魔法方法不是让你直接调用的!当然,你可以这样做,写一些类似于YourClass().__actual_name__()的东西,但是请不要这样做😃!

那么魔法方法是如何被调用的呢?它们是从应用于您的类或类的实例的某些操作中调用的。先睹为快,例如,调用str(YourClass())会调用神奇的方法__str__,或者YourClass() + YourClass()会调用__add__,如果你已经实现了它的话。

那么,魔法方法有什么好处呢?它们使您能够编写可以与 python 内置方法一起使用的类。如果你这样做,你的 c̶a̶n̶将会写出可读性更强、更简洁的代码。我希望这已经变得显而易见,从前面一段的小偷窥。

为了强调魔法方法是多么有用,并了解在进行机器学习或数据科学时如何从使用它们中受益,让我们跳到一个具体的例子中。

示例:自定义日期时间范围

作为一个例子,我想向您展示如何使用神奇的方法编写类似于内置的 范围 函数的东西。与内置版本相比,这个例子将提供更多的功能,更重要的是创建日期时间范围而不是数字范围。当然,你可以只使用 Pandas 或者其他一些库来得到它,但是我认为这个例子的目的是促进我们对魔术方法背后的一般概念的理解。它还允许我向您展示一些最有用的神奇方法,尤其是在处理数据时。

只是谈论或写代码而没有看到真实的和工作的代码是很无聊的,不是吗?因此,让我们停止这样做,看看真正的日期时间范围实现

好了,这是相当多的代码。如果你现在害怕,容忍我,我们将揭示它。总的来说,我已经实现了六种不同的魔术方法,我将在下面解释。

第一个,也可能是最著名的一个是__init__方法。您肯定知道,这个方法主要用于初始化您的类的实例属性。在这里,我们设置范围类的开始结束以及步长大小。这类似于我们在创建内置范围函数时所做的。

下一个是__iter__法。这可能是最重要的一个,因为它生成了我们的日期时间范围内的所有元素。这个函数是所谓的生成器函数,它一次创建一个元素,将它交给调用者,并允许调用者处理它。它一直这样做,直到到达范围的末端。当看到yield关键字时,你可以很容易地识别出一个发生器函数。该语句暂停函数,保存其所有状态,稍后在后续调用中继续。这允许您一次使用一个元素并使用它,而不需要将每个元素都存储在内存中。

当每个项目都占用大量内存,或者当您有大量项目时,不将所有内容都放在内存中会非常方便。例如,尝试执行**list**(DateTimeRange(datetime(1900,1,1), datetime(2000,1,1))或者不执行,因为这会创建一个包含 3184617600 个日期时间条目的列表。太大了,抱歉😃但是,使用生成器,您可以轻松地逐个处理这些元素。

现在你已经看到它不是一个列表或元组。然而,为了处理这个 DateTimeRange 类,就好像它是一个列表或元组一样,我添加了另外三个神奇的方法,即__len____contains____getitem__

使用__len__,您可以通过调用**len**(my_range)来找出属于您的范围的元素的数量。这非常有帮助,例如当你迭代所有的元素,并且想知道你已经处理了多少个元素的时候。它可能还会告诉你,嘿,我要处理很多数据,请拿一杯☕️.咖啡

使用__contains__你可以使用内置语法element **in** my_range检查一个元素是否是你的范围的一部分。给定实现的好处是,这是使用纯数学来完成的,而不必将给定元素与该范围内的所有元素进行比较。这意味着检查一个元素是否是范围的一部分是一个常量时间操作,不依赖于实际范围实例的大小。同样,这对于我们在处理数据时经常看到的大范围来说会很方便。

使用__getitem__你可以使用索引语法从你的对象中检索条目。例如,你可以得到我们范围的最后一个元素my_range[-1]。我必须承认,对于具体的例子来说,这可能是最没用的方法。然而,一般来说,使用__getitem__可以让你写出非常干净易读的界面。

我添加的第六个也是最后一个魔法方法是__str__。这个方法允许你将类的实例转换成字符串。这在调用**print**(my_range)时变得非常方便,因为 print 必须将一个实例转换成一个字符串,因此使用了__str__方法。

Unsplash 上的美元吉尔拍摄的照片

包裹

在本文中,我向您介绍了 Python 中魔术方法背后的基本概念。我已经向您展示了第一个示例,展示了如何使用这些方法,在我看来,这些方法在处理数据时非常方便。当然,还有很多,例如创建上下文管理器或者增强你的类。我可以推荐你继续探索这个领域,继续学习!

我希望你现在已经准备好在将来创建神奇的界面,也许还可以向你的朋友和同事炫耀一下💪。

感谢您关注这篇文章。一如既往,如有任何问题、意见或建议,请随时联系我或关注我,或者通过 LinkedIn

2021 年如何写出更好的数据科学文章

原文:https://towardsdatascience.com/how-to-write-better-data-science-articles-in-2021-a34210badb37?source=collection_archive---------32-----------------------

新的一年,同样的你,更好的文章。

照片由 Pexels 的 Nataliya Vaitkevich 拍摄

数据科学和写作有什么共同点?

除了显而易见的(我们每天都在寻找更多的时间来更好地掌握这两项技能),数据科学和写作也是两项技能,如果协同提高,可以让我们成为这两项技能都很全面的人。

数据科学家通常被称为“故事讲述者”,因为他们可以将海量数据转化为美丽的可视化数据,向大众讲述故事。因此,数据科学家写他们的工作来激励、告知和教导未来的数据科学家如何成为有效的故事讲述者是有意义的。

新的一年是自我提升的最佳时间(尽管自我提升大师们会说一年中的任何时候都是提升自己的最佳时间),这并不仅限于在新的一年里多去健身房或读 52 本书。相反,在即将到来的充满未知的一年里,在你的数据科学和写作技能方面取得小的进步可能是你需要的稳定常数,以在年底前看到这两个领域的巨大进步。

忽略冒名顶替综合症。

想知道一个秘密吗?我感觉自己完全是数据科学社区的局外人。

尽管我受过软件开发方面的教育,但数据科学对我来说是一个全新的世界,我还不觉得自己是其中的一部分。然而,我不会让这阻止我写它,如果你刚刚开始或过渡到这个领域,你也不应该。

正如在我之前很多人建议的那样,在实践中学习很重要。

不仅如此,在数据科学这个领域,你的学习能力比你所拥有的证书更重要。数据科学社区充满了来自各种不同背景的个人,有些人在大学学习工程或人文学科,有些人在转行前在完全不相关的行业工作,还有一些人自学了进入该领域所需的一切知识。

此外,当你阅读一篇全面的、有充分理由的文章时,你通常不会在意作者的资质。这就是科技行业的魅力所在。你不一定要有博士学位才能成为某个学科的权威或者教别人怎么做某件事。

提醒一句:记住保持一定程度的谦逊,人们会非常乐意帮助你成为更好的作家或数据科学家。作为一个新手,我很清楚我的文章不会完美,我分享的代码也不会是问题的完美解决方案。然而,作为一个初学者,如果你承认你还在学习,人们会善意地批评你,并帮助你完善你的文章或代码。不要做那个“什么都懂”的人。诚实并欢迎任何帮助,你会交到更多的朋友,成为一名全面发展的数据科学家。

坚持写,然后趁热打铁。

我要提供的第一条建议是标准的,也是给想要变得更好的新手的建议中最多的一条。第二条建议可能有点反直觉。

要想写出更好的数据科学文章,你需要持之以恒地写作。就像在健身房锻炼一样,只有当你以一种持续的、严格的方式举重时,你才能看到效果。同样,当你写作时,你在使用肌肉。写作肌肉必须坚持不懈地锻炼,直到你能定期写出有效的文章。当你有信心可以坐下来在一天内就某个特定主题写完一篇完整的文章时(因为让我们面对现实吧,强迫自己在一个小时内写完一整篇关于数据科学的文章对你自己或你的编辑来说都是不友好的),那么你知道你已经在写作中养成了一些好的写作习惯。

然而,当你持续且轻松地制作内容时,你需要确定你是否在制作最好的作品。在这一点上,你应该寻求过渡到以“趁热打铁”的方式写作。

为什么?因为 Medium 以自己是高质量文章的家园而自豪,并将支持和突出那些这样做的人。因此,如果你在灵感迸发时写作,而不是感觉需要像一只轮子上的仓鼠一样大量生产内容,你很可能会写出特别有信息量、有洞察力和深度的数据科学文章。

使用费曼技术。

经常被吹捧为快速和彻底学习概念的方法,我进一步相信费曼技术是帮助您编写更好的数据科学文章的完美方法。

理查德·费曼是一位获得诺贝尔奖的物理学家,因其在量子力学、粒子物理和纳米技术方面的贡献而闻名。然而,对我来说,他最出名的是被称为“大讲解员”。费曼以讲授最好的物理课程而闻名,不是因为他总是分享复杂、难以理解的观点,而是因为他关于这些复杂主题的讲座易于被大众理解。正因为如此,费曼被称为“有史以来最容易读懂的诺贝尔奖得主”

但是,是什么让他成为如此复杂学科的如此出色的老师呢?这都要归功于他用来掌握一个话题的方法论。众所周知,“费曼技术”是一种理解任何事物的方法。

“我不能把它简化到大一的水平。这意味着我们真的不了解它。”— 理查德·费曼

费曼技巧包括四个步骤,重点是学习者通过试错、发现和自由探究过程达到对主题的真正理解。这项技术可以分为四个步骤,您可以依次遵循:

  1. 选择一个概念来学习。
  2. 把这个概念教给自己或别人。
  3. 如果你卡住了,回到原始材料。
  4. 简化你的解释,创造类比。

那么这将如何帮助您写出更好的数据科学文章呢?好吧,如果你不理解一个主题,以至于你不能用简单的术语解释它,你怎么期望能够把这个主题教给其他人并让他们理解它?

使用费曼技巧不仅会让你成为一名更有能力的数据科学文章作者,同时还会让你有能力掌握任何数据科学概念。这是一种双赢,一石二鸟的局面。

让一个非技术人员阅读你的文章。

能够写出好的代码和分析成堆的数据是一回事,向其他人传达你在做什么以及为什么这么做是另一回事。

成为一名优秀的数据科学家意味着你也是一名优秀的沟通者,意味着你可以根据你的受众以不同的复杂程度描述一个概念。

因此,为了写出更好的数据科学文章,让一个非技术人员阅读你的文章总是一个好主意,这样你就可以看看是否有人能理解你写的东西。

如果您正在为刚开始接触数据科学的人撰写一系列介绍性文章,这一点尤其重要。你不想在它们开始旅程之前就把它们吓跑吧?

此外,正如费曼先生所说,如果你不能简单地解释某件事,你自己也不明白。

我和许多人一起上大学,他们非常聪明,可以很容易地写出精彩的代码。然而,当我向他们寻求帮助时,他们只能在一个非常复杂的层次上解释,我甚至一点也不能理解。所以当然,因为我不想看起来很傻,我会做常规的“哦,太好了,谢谢,现在完全有道理了!”然后去找其他人用我能理解的语言解释这个概念。把这和你的文章联系起来,你不希望有人读了你的文章,然后马上去找别人的文章,他们可以更好地理解。

所以,重申一下,为了克服这一点,让你的文章对不同背景的读者更加友好和有用,让一个非技术人员阅读你的文章,然后向你解释你刚刚写了什么。这样做几次后,你会对你的文章变得更容易理解而印象深刻,你的读者也会对你的作品更有反应。

阅读。很多。

叔本华有句名言“阅读仅仅是你自己思考的替代品;这意味着让别人来引导你的思想。”作为一个长篇大论的家伙,他最终继续说道,“结果是大量阅读剥夺了大脑的所有弹性,就像持续的重量压力使弹簧失去弹性一样,永远没有自己的任何想法的最可靠的方法就是每当你有空的时候就拿起一本书。”

基本上,他是在说(从我这个外行的角度来看),读书不会让你变得更聪明,如果有什么不同的话,只会让你变得更笨,更不能独立思考。

所以我明白了他想说的意思——对于我们来说,要形成自己对概念的理解,我们需要自己思考,而不是别人给我们的想法。然而,对于我们这些有生命的人来说,我们不能每天花那么多时间去为自己推理。

所以,我的论点是,要写出更好的数据科学文章,需要阅读。很多。

这条建议广为流传,理由很充分。

不确定自己的写作风格?阅读你喜欢的作者的文章,模仿他们的写作风格。

需要提高您对特定数据科学主题的理解?阅读不同作者关于这个主题的多篇文章,直到你找到一篇让你顿悟的文章。

想学点新东西,然后教给别人吗?阅读有关主题的内容,然后根据文章创建自己的项目来巩固你的理解。

这篇技巧解释了我如何能够写一篇关于如何写更好的数据科学文章的文章,而不是一个关于这个主题的多产作家。我读过大量关于 Medium 的数据科学文章,正因为如此,我能够说出什么是好文章,什么是坏文章。好的文章都有一些共同点:它们容易理解,作者使用简单的术语和类比,你可以看出他们写的是他们感兴趣的话题(而不是仅仅为了赚钱而大量输出内容)。由于我通过阅读获得了所有这些知识,我现在可以写一篇文章来帮助其他人写出更好的数据科学文章。

换句话说,尽可能多地阅读关于数据科学和写作的文章,观察你的技能突飞猛进。

最后的想法。

没有具体的方法可以保证你在这个平台上发表最受欢迎、收入最高的数据科学文章。

然而,如果你准备好了学习撰写好的博客文章和干净有效的代码的马拉松式过程,并且掌握了本文中提到的技巧,你将在 2021 年撰写更好的数据科学文章。

如何有效地用 Python 写代码

原文:https://towardsdatascience.com/how-to-write-code-effectively-in-python-105dc5f2d293?source=collection_archive---------3-----------------------

分析使用 Python 编写代码时应该遵循的最佳实践

布鲁斯·马斯在 Unsplash 上的照片

编码是现代技术时代最流行的实践之一。这是一个非常普遍的技能,被认为是大多数处理软件开发或数据分析的热门领域的强制性要求之一。

编码本质上是让你的计算机程序理解你的思维逻辑,使你能够完成手头的任务。随着我们在编程领域变得越来越先进,理解编写高效代码的重要性变得非常重要。

对于大多数初级程序员来说,Python 是最容易学习和入门的编程语言之一。它不仅提供了简单性,还提供了广泛的库来执行各种任务,使其成为最通用的语言之一。它还允许用户在许多领域工作,如数据科学、人工智能、机器人、天文学等等。

虽然 Python 是大多数任务的最佳选择之一,但程序员无法适应编码的最佳选择。在本文中,我们将介绍编写高效代码所需的大部分基本要素。在我们探索如何做到这一点的一些最佳实践之前,我们将在本文的下一部分详细讨论为什么我们都应该有效地编码。

如果您不太熟悉 Python 的一些核心概念,并且您仍然需要习惯它们,请查看下面提供的文章,该文章更详细地讨论了这个主题。它涵盖了您学习 Python 以掌握机器学习所需的大多数基本细节。

为什么有效地编码?

都铎·巴休Unsplash 上拍摄

在程序员的初级阶段,我们倾向于养成一些习惯,使我们能够以最简单的方式获得特定程序或任务的解决方案。然而,值得质疑的是,这种获得答案的简单方法是否是计算下面问题的最有效和高效的方法。

对有效和高效代码的需求是必须的。在编程或创建简单项目的过程中,似乎没有必要这样做。但是随着您变得更加高级和有经验,您将需要以系统的方式调试和测试您的代码。您需要努力使您的代码更加 pythonic 化,并确保它满足空间和时间复杂性的最佳要求。

让我们假设一个简单的例子,用 print 语句打印五次名为“Hello”的语句。你可以用许多方法来完成这项任务。我们将研究三种这样的方法,您可以利用它们来执行相同的代码,并分析它们的效率以及以下每种方法的不同之处。第一种方法是将语句打印五次。

***Approach-1:***print("Hello \n")
print("Hello \n")
print("Hello \n")
print("Hello \n")
print("Hello")

第二种方法是打印一次语句,并使用一个乘数来接收所需的输出。

***Approach-2:***print("Hello \n"*5)
(OR)
print("Hello \n"*5, end="")

我们要研究的最后一种方法是利用 for 循环来执行这个操作。

***Approach-3:***for i in range(5):
 print("Hello")

很容易推断出你可以用多种方式完成一个特定的程序。然而,对于一个好的程序员来说,最重要的是使他所需要的代码尽可能的高效,这样它更可读,并产生最好的输出。让我们在下一节通过探索五个关键步骤来探索如何编写更好的代码。

如何有效编码?

Nubelson Fernandes 在 Unsplash 上的照片

既然我们已经对有效地编写代码的重要性有了一些简单的了解,在这一节中,我们将重点了解如何才能完成这项任务。我们将涵盖编写最有效的代码来解决所有程序、任务和项目的主要需求的技术和实践方面。

1.有效文件:

***Approach-1:***

def treat():
    """
    Creating the function for manipulating the motion of the turtle    object as desired. 
    """
    speed(0)
    penup()
    goto(-140, 140)

首先,要遵循的最佳实践之一是确保您记录了代码。我越是开始编码和从事大量的项目,我就越意识到有效文档的重要性。在编程过程中,一种常见的做法是迷失在自己的编码世界中,直到您获得了所遇到的特定问题或项目的完美解决方案。

然而,当你如此深入地沉浸在你的代码中时,一个值得注意的问题是,你没有太注意通过评论你在整个程序中使用的不同函数来记录或解释你的代码。主要的问题是,当你决定退出特定的任务,并在几周或几个月后重新访问它时,它会引起什么问题。

如果没有适当的文档和对特定代码块或代码段的用途类型的理解,几乎不可能确定您试图完成的确切任务。更重要的是,你到底是如何完成任务的。

因此,有了有效的文档,你不仅可以帮助那些长时间阅读代码的人,还可以帮助那些想要阅读和理解你的代码的人。因此,输入几行注释来解释代码的用途是一个很好的做法,尤其是在平台上发布代码供他人查看时。

***Approach-2:***if __name__ == "__main__":
 # create a GUI window
 gui = Tk() # set the background colour of GUI window
 gui.configure(background="light green") # set the title of GUI window
 gui.title("Simple Calculator")

2.让您的代码更加 Pythonic 化:

为您的程序获得最佳结果的方法之一是使它们更 pythonic 化。通过对您的编码风格进行适当的修改以适应更 Python 化的编程方式,您可以使您的代码更具可读性、更好看,并且更高效。

您可以遵循的一些最佳实践包括利用变量来分配特定的语句,然后确保这些变量执行特定的操作。不要用特定的条件硬编码 if 语句,而是尝试将下面的内容分配给两个变量,并相应地计算下面的内容。

其他最佳实践包括利用函数的默认参数,以防经过身份验证的用户不希望传递任何特定的命令,并确保所描述的函数将返回值。使用下划线变量(_)作为一次性变量,以便在需要时过滤掉不必要的元素。

您可以对各自的 Python 代码进行一些改进和调整。要记住的重要方面是修改后的代码效率如何,pythonic 化程度如何。除了提供的示例之外,还有几个因素和改进可以使您的代码 pythonic 化。我们将在以后的文章中更深入地研究以下内容。

3.使用匿名函数:

函数在大多数主要 Python 项目的构建中起着至关重要的作用。函数通常用于重复性和创建 Python 程序的结构。使用关键字‘def’,定义函数,可以使用已定义或未定义的参数调用这些函数。当您调用特定的函数时,python 编译器会解释将要返回的任何值。

在 Python 中,匿名函数是定义时没有名字的函数。在 Python 中,普通函数是使用 def 关键字定义的,而匿名函数是使用 lambda 关键字定义的。使用 lambda 函数的主要优点是执行一个 lambda 函数,该函数计算其表达式,然后自动返回其结果。

下面是一个例子,它向我们展示了如何解决只打印元素列表的偶数的问题。有和没有匿名函数的方法都有解释,很容易注意到下面哪种方法更好。

***Approach-1:***def even(a):
    new_list = []
    for i in a:
        if i%2 == 0:
            new_list.append(i)
    return(new_list)

a = [1,2,3,4,5]
even(a)

下面是具有高级功能的第二种方法。请注意,两个代码块提供的输出将产生相同的值。

***Approach-2:***a = [1, 2, 3, 4, 5]
even = list(filter(lambda x: (x%2 == 0), a))
print(even)

有关 Python 中高级函数概念的完整指南和理解,以及完整的代码和示例,请参考下面提供的文章参考。它涵盖了在代码块中开始使用这些高级函数以优化它们并使它们更高效所需的大多数基本概念。

4.尝试和测试备选方案:

当你在做一个程序,并且成功地完成了手头的复杂任务时,给自己一个鼓励和兴奋的感觉是令人惊奇的。一旦你的兴奋消退,再一次检查你的代码,试着分析你可以做得更好的地方。

通过进一步检查和仔细查看您的程序,您可以找出一些微小或重大的变化,您可以添加到您的程序中,使它更加有效,并与特定的任务兼容。分析你自己、朋友或专家能做出的最佳改变变得至关重要。

有时,当您的时间安排很紧时,您只想能够以最快的方式实现最可靠的解决方案。在这种情况下,遵循传统的方法就可以得到最理想的解决方案。

然而,一旦您完成了计算和项目,请确保再次访问该主题,以进一步优化您的代码,供将来参考。

5.严格练习:

既然我们已经对一些最基本的概念有了简单的了解,对如何有效地编码有了基本的想法,下一个关键的步骤就是严格地练习。有了完美的实践技巧,并在你着手的每一个程序或编码问题中重复这些适应的方法,你就能达到最好的结果。

另一个需要注意的要点是,您必须学会始终如一地集成一些更新的技术,这些技术是您在升级编码学习过程中不断学到的。如果你对每一个项目、任务或简单的问题都坚持这样做,你最终会发现你的代码写作风格有了巨大的改进。

关于这一点的更广泛的解释,请参考下面的文章,在那里我已经彻底地解释了为什么作为一名数据科学家,每个程序员每天编码是重要的。

</5-reasons-why-you-should-code-daily-as-a-data-scientist-fa7fc6dc92c4>

结论:

Jo Szczepanska 在 Unsplash 上拍摄的照片

“有时候周一呆在床上比花一周的时间调试周一的代码更划算。” —丹·所罗门

随着您在该领域的发展,编写有效的代码来执行 Python 中的大量操作成为一项基本要求。当程序变得越来越复杂,而您的计算资源有限时,在您的代码中保持持续的进步、改进和发展,以保持其在未来几年的相关性就变得非常重要。

在本文中,我们讨论了高效编码所需的大部分概念。首先,我们通过一个简单的例子理解了有效编码的重要性,然后继续学习五个主要的实践,这将使我们在编程方面变得更加熟练,不管你是什么水平的学习者。

如果你想在我的文章发表后第一时间得到通知,请点击下面的链接订阅电子邮件推荐。如果你希望支持其他作者和我,请订阅下面的链接。

https://bharath-k1297.medium.com/membership

如果你对这篇文章中提到的各点有任何疑问,请在下面的评论中告诉我。我会尽快给你回复。

看看我的其他一些文章,你可能会喜欢读!

</5-best-python-projects-with-codes-that-you-can-complete-within-an-hour-fb112e15ef44> </14-pandas-operations-that-every-data-scientist-must-know-cc326dc4e6ee> </17-must-know-code-blocks-for-every-data-scientist-c39a607a844d> </8-best-visualizations-to-consider-for-your-data-science-projects-b9ace21564a>

谢谢你们坚持到最后。我希望你们都喜欢这篇文章。祝大家有美好的一天!

如何编写自定义 TensorFlow 回调——简单的方法

原文:https://towardsdatascience.com/how-to-write-custom-tensorflow-callbacks-the-easy-way-c7c4b0e31c1c?source=collection_archive---------33-----------------------

你觉得内置 TensorFlow 回调有局限性吗?这是您一直在寻找的解决方案

西蒙·艾布拉姆斯在 Unsplash拍摄的照片

你发现内置 TensorFlow 回调有局限性吗?您很幸运,因为今天您将从头开始学习如何编写自定义 TensorFlow 回调!当您想修改默认回调的工作方式或者想做一些疯狂的事情时,它可能会派上用场。

今天,您将编写一个定制的回调函数来重新设计训练循环,在训练完成后在测试集上打印评估指标,并绘制每个时期的训练损失与验证损失以及训练精度与验证精度的关系图。

不想看书?请观看我的视频:

你可以在 GitHub 上下载源代码。

使用的数据集和数据预处理

我今天不打算花太多时间处理数据。我们将使用与前几篇文章相同的数据集——来自 Kaggle 的葡萄酒质量数据集。它是在数据库内容许可证下许可的开源数据集:

图片 1——来自 Kaggle 的葡萄酒质量数据集(图片由作者提供)

您可以使用以下代码将其导入 Python,并随机打印几行:

我们忽略警告并更改默认的 TensorFlow 日志级别,这样我们就不会被输出淹没。

以下是数据集的外观:

图 2——葡萄酒质量数据集的随机样本(图片由作者提供)

数据集基本上是干净的,但默认情况下不是为二元分类(好酒/劣酒)而设计的。取而代之的是,葡萄酒是按等级来评定的。我们现在将解决这个问题,还有许多其他问题:

  • 删除缺失值 —它们为数不多,所以我们不会在插补上浪费时间。
  • 处理分类特征——唯一的一个是type,指示葡萄酒是白还是红。
  • 转换为二分分类任务——我们将把任何 6 分及以上的葡萄酒宣布为,任何低于的为差
  • 训练/测试拆分——经典的 80:20 拆分。
  • 缩放数据 —预测值之间的比例差异很大,因此我们将使用StandardScaler来拉近数值。

下面是完整的数据预处理代码片段:

同样,如果你想更详细地了解数据预处理背后的逻辑,请参考上一篇文章

现在,让我们看看如何在 TensorFlow 中声明回调。

编写一个模型训练函数

让我们通过编写一个构建、编译和训练模型的函数来使我们的生活变得稍微容易一些。没有它也可以继续,但是您需要多次复制/粘贴模型训练代码,这并不理想。

该函数允许您指定回调列表,并更改模型将训练的时期数。默认情况下,历元数设置为 5。其他一切都是硬编码的,包括训练集、验证集和详细度参数。最好将其设置为 0,因为我们的回调会生成自己的训练进度语句。

下面是该函数的代码:

如果你了解 TensorFlow 的基础知识,应该感觉很熟悉。解决了这个问题,让我们写第一个回调函数。

编写一个基本的自定义 TensorFlow 回调

每个自定义 TensorFlow 回调类都必须扩展tf.keras.callbacks.Callback类。它让你可以访问许多类方法,但是我们在这一节只讨论两个。这些是on_train_begin()on_train_end()。TensorFlow 的开发团队确实确定了函数名,因此没有必要进一步解释它们的功能。

与任何 Python 类一样,您可以声明一个构造函数。我们的将包含模型开始和结束训练的时间戳。我们最初将两者都设置为None

on_train_begin()函数将当前时间设置为构造函数中的开始时间戳,并打印训练开始的时间。

on_train_end()函数将当前时间设置为构造函数中的时间结束时间戳,计算并打印训练持续时间,并打印训练损失、训练准确度、验证损失和验证准确度的值。

代码如下:

简单吧?当然,但是开始定制训练日志输出就足够了。您可以使用以下代码为模型定型五个时期(默认):

下面是您将看到的输出:

图 3 —自定义 TensorFlow 回调 v1(图片由作者提供)

这是一个不错的开始,但我们看不到每个时期会发生什么。接下来让我们改变它。

使用自定义 TensorFlow 回调修改纪元行为

您可以用同样的方式修改每个时期开始和结束时发生的事情。我们将打印历元号、历元持续时间、训练损失和准确度,以及验证损失和准确度。

让我们从向构造函数添加一个额外的变量开始— time_curr_epoch —它将在每次新的纪元开始时被覆盖。

on_epoch_begin()函数将当前时间的值设置为构造函数中的time_curr_epoch变量。

on_epoch_end()函数将计算历元持续时间,并从历元日志中获取训练损失、训练精度、验证损失和验证精度。然后它会使用 Python 的 f-string 魔法将它们打印出来。

代码如下:

让我们测试一下——记住,除了之前的内容之外,您应该会看到每个时期都打印了新的一行:

以下是输出结果:

图 4 —自定义 TensorFlow 回调 v2(图片由作者提供)

整洁,对不对?故事并没有到此结束。接下来,让我们看看如何在培训完成后直观显示模型性能。

通过自定义 TensorFlow 回调可视化模型性能

绘制训练和验证度量会立即告诉您模型是否停滞或过度拟合,以及何时是停止训练的正确时间。这就是我们现在要做的。我们将声明一个可视化模型性能的辅助函数,然后在训练完成后调用它。

首先,向构造函数添加几个变量。您将需要在训练集和验证集上跟踪历元数、损失和准确性。

_plot_model_performance()函数将创建一个 1 行 2 列的图表,在左边显示训练和验证损失,在右边显示训练和验证准确性。

on_training_end()里面只调用_plot_model_performance()下面的一切。

on_epoch_end()中,增加历元数,将训练损失、训练精度、验证损失和验证精度的值追加到构造函数的列表中。

代码如下:

就是这样!现在让我们来测试一下——我们将训练 50 个时期的模型,这样图表就可以显示更多的数据:

培训结束后,您将看到以下内容:

图 5 —自定义 TensorFlow 回调 v3(图片由作者提供)

简而言之,用当前的架构和参数训练模型 50 个时代是没有意义的。验证损失大约在第 5 个历元之后开始增加,同时验证准确度或多或少处于平稳状态。

不过,这是你需要手动可视化的一件事。

结论

这就是 TensorFlow 自定义回调的基础。我们只介绍了可用功能的一小部分,所以请务必浏览官方文档以获得更多资源。写得真的很好,你会发现关于编写自定义提前停止学习率调度器回调的例子。

在从头开始编写自定义回调之前,请确保您需要的功能尚未内置到 TensorFlow 中。你可以查看我的前一篇文章,关于我在每个深度学习项目中使用的四个内置回调,以帮助你开始。

请继续关注即将到来的文章,因为我们将从下面的文章开始深入研究 TensorFlow 和计算机视觉以及卷积神经网络。

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

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

保持联系

如何用 Python 编写类似 Excel 的公式

原文:https://towardsdatascience.com/how-to-write-excel-like-formulas-in-python-4bdacab75a53?source=collection_archive---------8-----------------------

关于如何使用 Python 中的米托包编写类似 Excel 的公式的简短教程

乔安娜·科辛斯卡在 Unsplash 上的照片

M 任何 Python 用户都在从电子表格过渡,因为 Python 包允许用户使用类似 Excel 的语法。这是一个用于 JupyterLab 的电子表格环境,可以帮助您进行 Python 分析。

认识一下米托——一个将交互式电子表格初始化到 JupyterLab 环境中的 Python 包。对于您在电子表格中所做的每一次编辑,米托都会生成生产就绪的 Python 代码。也是免费使用。

通过阅读这篇文章,你将学会:

  • 如何在 Python 中执行基本的类似 Excel 的操作
  • 如何用 Python 编写类似 Excel 的公式

如果你错过了我之前关于这个主题的文章,请参见米托——一个生成 Python 的电子表格。

Python 中的 Excel 语法

使用米托 2.0 进行数据切片

要使用 Excel 语法,首先使用以下命令初始化 Mitosheet:

import mitosheet
mitosheet.sheet()

这将呈现交互式电子表格,您可以:

  • 从本地文件传入数据集
  • 或者,您可以传入笔记本中现有的数据帧作为 Mitosheet 调用的参数:
mitosheet.sheet(df))

将本地文件导入米托表单(图片由作者提供)

以防你还没有安装米托

要安装米托,请运行以下命令:

python -m pip install mitoinstaller
python -m mitoinstaller install

这里是完整的安装说明。

添加一列米托

在米托表单中添加新列(图片由作者提供)

要添加列,请单击 Mitosheet 顶部工具栏中的“添加列”按钮。使用新列,您可以使用电子表格函数和公式。

当您添加一个列时,它会在 Mitosheet 下面的代码单元中生成等效的 Python。

用米托重命名列

要重命名某个列,只需双击该列的标题,然后键入您想要的新标题。

使用 Excel 函数

在新列的单元格中,您可以分配一个公式。

在新的专栏中,您可以使用普通的类似 Excel 的函数,米托将生成等效的 Python 代码。

当您开始键入函数时,下面的菜单中将显示一个可供选择的函数建议列表。

用米托工作表编写类似 Excel 的公式(图片由作者提供)

上图中使用的函数生成了等效的 Python(这是自动记录的)。

Airport_Pets_csv['New_Column'] = IF(Airport_Pets_csv['Division'] == "Central", 1, 0)

米托有许多不同类型的 Excel 函数可以在工作表中使用。您可以使用:

  • 日期操作
  • 统计分析
  • 数据清理
  • 还有更多。

有关所有支持的类似 Excel 的公式,请参见公式参考页

米托公式参考页面(由https://docs . try mito . io/how-to/interactive-with-your-data/mito-spread sheet-formulas页面作者截图)

直接编辑数据

米托允许用户选择数据框中的任何单元格并更改特定值——就像在电子表格中一样。这对于快速数据编辑和数据验证来说是一个重要的特性。

编辑米托表单中的列(图片由作者提供)

此编辑会生成等效的代码:

# Set column City at index 0 in Airport_Pets_csv to Amherst
Airport_Pets_csv.at[0, 'City'] = "Amherst"

其他类似 Excel 的功能

米托还为用户提供了一个熟悉的电子表格环境来完成其他常见的 Python 任务。

用户可以在交互式设置中创建数据透视表,并让这些数据透视表自动生成等价代码:

用米托旋转表格(作者可视化)

用户可以生成图形和等价代码:

与米托一起制作情节(作者视觉化)

米托还支持常见的分析功能,例如:

结论

LenstravelierUnsplash 上拍摄

对于那些希望从 Excel 或 Google 电子表格环境过渡到 Python 的人来说,米托是一个强大的工具。

neet 米托的一个特点是它展示了如何计算某些运算。所以你可以边点击分析边学习。

作为一名经验丰富的 pandas 用户,我使用米托进行初步的探索性数据分析。对于米托,我避免一遍又一遍地写同样的熊猫指令。

在你走之前

如果你喜欢看这些故事,为什么不成为 中等付费会员 ?每月 5 美元,你可以无限制地阅读 10000 个故事和作家。如果你用我的链接注册,我会赚一小笔佣金。**

照片由 Alexas_FotosUnsplash 上拍摄

如何将 NumPy 数组写入 CSV 文件

原文:https://towardsdatascience.com/how-to-write-numpy-arrays-to-csv-files-449a217ae7ee?source=collection_archive---------9-----------------------

以及为什么您应该考虑其他文件格式

图片由英驰通过 Unsplash 拍摄

这篇文章解释了如何将 NumPy 数组写入 CSV 文件

我们将看看:

  • 将不同的 NumPy 数组写入 CSV 的语法
  • 将 NumPy 数组写入 CSV 的限制
  • 保存 NumPy 数组的替代方法

我们开始吧。

将 NumPy 数组写入 CSV

您可以使用np.savetxt()方法将 Numpy 数组保存到一个 CSV 文件中。

确保:

  • 添加”。csv”到文件名目的地,并且
  • 将 delimiter 关键字设置为“,”

如果你不使用这两个设置,NumPy 将会把你的文件保存为. txt。

CSV 文件可以很棒,因为它们是人类可读的。它们还有一个额外的好处,就是很容易加载到 pandas 或 Dask 数据帧中。

写一维数组

让我们使用np.random.rand()创建一个包含随机数的一维数组。

import numpy as np 
# create 1D array 
a = np.array([1,2,3]) # store in current directory 
np.savetxt( "a.csv", a, delimiter="," )

默认情况下,NumPy 将按列写入数组。让我们检查一下a.csv的内容以确认:

1
2
3

改为按行写入数据,将newline kwarg 设置为“,”(您的分隔符)。

# write array row-wise 
np.savetxt("very.csv", a, delimiter=",", newline=",")

您也可以通过先将数组转换为 2D 数组来按行写入数组

np.savetxt("very.csv", [a], delimiter="," )

在这两种情况下,very.csv的内容会是这样的:

1   2   3

写二维数组

现在让我们创建一个二维 NumPy 数组并保存到 CSV。

# create 2D array 
b = np.array([1, 2, 3], [4, 5, 6]) # write 2D array to CSV 
np.savetxt( "merry.csv", b, delimiter="," )

正如您所料,默认情况下,2D 数组是按行写入的。

merry.csv的内容:

1   2   3
4   5   6

写三维数组

最后,让我们创建一个三维 NumPy 数组,并尝试将其保存为 CSV 格式。

# create 3D array 
c = np.random.rand(3,3,3) # write 3D array to CSV 
np.savetxt( "christmas.csv", c, delimiter="," )

这不管用。您将看到如下错误消息:

--------------------------------------------------------------------ValueError Traceback (most recent call last) /var/folders/ky/bqjn_gxn1xv0cn_8q5xvp3q40000gn/T/ipykernel_46872/1804416501.py in <module> ----> 1 np.savetxt(f"{home}/Documents/numpy/bar.csv", c, delimiter=",") <__array_function__ internals> in savetxt(*args, **kwargs) ~/mambaforge/envs/numpy-zarr/lib/python3.9/site-packages/numpy/lib/npyio.py in savetxt(fname, X, fmt, delimiter, newline, header, footer, comments, encoding) 1380 # Handle 1-dimensional arrays 1381 if X.ndim == 0 or X.ndim > 2: -> 1382 raise ValueError( 1383 "Expected 1D or 2D array, got %dD array instead" % X.ndim) 1384 elif X.ndim == 1: ValueError: Expected 1D or 2D array, got 3D array instead

CSV 是一种可读的表格格式。这意味着只有 1D 和 2D NumPy 阵列可以写入 CSV。

用 np.save()保存 Numpy 数组

在磁盘上存储 NumPy 数组的另一种方法是使用本机的np.save()方法。这将以二进制文件格式存储您的数组。

这种格式允许您保存所有维度的 NumPy 数组。这意味着这些文件将不是人类可读的。

# save 3D array to binary NPY format 
np.save('christmas.npy', c)

让我们看看在 CSV 和 NPY 中存储的文件大小是否有区别。

# create medium-sized 2D array 
d = np.random.rand(100,100) # save 2D array to CSV format 
np.savetxt( f"time.csv", d, delimiter="," ) # get the size (in bytes) of the stored .npy file 
! stat -f '%z' time.csv

250000

# save 2D array to binary NPY format 
np.save('time.npy', d) # get the size (in bytes) of the stored .npy file 
! stat -f '%z' time.npy

80128

如您所见,与 250KB 的 CSV 相比,NPY 文件格式输出的文件更小:大约 80KB。

保存 NumPy 数组的其他方法

还有其他存储 NumPy 数组的方法。这里有一篇很棒的博文向你展示了如何将 NumPy 数组写入 TXT 文件。

从技术上讲,您也可以使用np.ndarray.tofile()方法,但是这将把数组编码成依赖于平台的二进制格式,所以通常不推荐使用。

NumPy 阵列的并行读/写

如果你处理的是小的本地数据,上面提到的格式就可以了。

但许多真实世界的数据集与小型和本地数据集相反:它们非常大(通常比本地内存大)并且基于云。这意味着您需要并行读写 NumPy 数组。

NPY 文件格式不允许并行读取和写入。

改为将数组写入 Zarr

如果您需要并行读/写,那么将 NumPy 数组写成 Zarr 文件格式是一个不错的选择。Zarr 是一种存储任何维度的分块和压缩数组的格式。这意味着你可以通过一次处理多个块来并行读写你的数组;通过使用类似 Dask 的并行处理库。

与前面提到的所有其他文件格式相比,这有两个重要的好处:

  1. 您可以更快地读/写数组
  2. 您可以读取/写入超出本地计算机内存的数组

结论

使用np.savetxt()方法- 可以将 NumPy 数组写入 CSV,但前提是你的数组只有 2 维或更少。

二进制 NPY 格式比 CSV 更节省内存,但它不是人类可读的,也不能并行处理。

如果数据集非常大,并行编写 NumPy 数组会快得多,并且可以避免内存错误。使用 Zarr 文件格式并行读写 NumPy 数组。

在 Twitter 上关注我,获取更多类似的内容。

原载于 2021 年 12 月 25 日 http://crunchcrunchhuman.comhttps://crunchcrunchhuman.com/2021/12/25/numpy-save-csv-write/。****

如何写出完美的数据科学简历

原文:https://towardsdatascience.com/how-to-write-the-perfect-data-science-cv-72213d546ebf?source=collection_archive---------10-----------------------

这些提示也适用于软件工程师。在你的简历上做一些改变,获得那份工作!

克里斯蒂娜@ wocintechchat.com 在 Unsplash 上的照片

写一份好的简历可能是求职中最艰难的挑战之一。

大多数雇主在将每份简历放入“是”或“否”栏之前,只花几秒钟浏览一下。

这里有 5 个技巧可以增加你的简历获得通过的几率。

这里有几个你可能会感兴趣的链接:

- [Complete your Python analyses 10x faster with Mito](https://trymito.io/) [Product]- [Free skill tests for Data Scientists & ML Engineers](https://aigents.co/skills) [Test]- [All New Self-Driving Car Engineer Nanodegree](https://imp.i115008.net/c/2402645/1116216/11298)[Course]

您愿意阅读更多这样的文章吗?如果是这样,你可以点击上面的任何链接来支持我。其中一些是附属链接,但你不需要购买任何东西。

1.漂亮的设计

照片由 Neven KrcmarekUnsplash 上拍摄

你的简历应该反映你未来的潜力。

我一直认为一份设计精美的简历并不重要——我们不是设计师,所以没有人会期待一份来自数据科学家的精美简历,对吗?

嗯,我错了!

当你申请一个偏远的职位或者一个有成千上万份申请的大公司的职位时,一份精致的简历变得很重要。

在欧洲,我们有一个标准化的简历模板,叫做 Europass 。虽然它有一个在线编辑器和令人惊讶的良好用户体验,但最终结果并不令人满意。

我的 2 页欧洲通行证简历。

Europass CV 枯燥的设计并不能吸引眼球。并不能体现你未来的潜力。

引人注目的简历

我用 Awesome-CV 模板写了我的简历。

写一份吸引眼球的简历不需要设计技巧。

Awesome-CV 是一个漂亮的 CV 模板,在里面你只需要改变内容。您也可以根据自己的喜好改变颜色,使其个性化。

这个漂亮的简历模板是用 LaTeX——一个高质量的排版系统制作的。LaTeX 是科学文献交流和出版的事实标准。

Awesome-CV 创建 CV 的先决条件是在你的电脑上安装 LaTeX

完成编辑后,您需要用 LaTeX 编译 CV,它会输出一个 PDF。

2.少即是多

照片由普拉蒂克·卡蒂亚尔Unsplash 拍摄

许多申请人会写一份长达数页的简历。

雇主没有时间审查长格式的简历,所以很多人会自动把它们放在“不”的那一堆。

不相信我?

看一看 Joseph Redmon 的简历——YOLO(统一的实时物体检测引擎)背后的想法。

这是一份一页长的简历,看起来像是来自一部漫画。但它引人注目。

我建议写一页纸的简历,因为它会迫使你浓缩你的工作经验。

3.针对申请者跟踪系统进行优化

Kelly SikkemaUnsplash 上拍摄的照片

像谷歌和苹果这样的大公司每个职位空缺都会收到成千上万份申请。招聘人员不能有效地审查所有人,所以他们使用申请人跟踪系统(ATS)。

ATS 是一款扫描和分析你简历的软件。招聘人员只看到你简历的记分卡,这是扫描的最终结果。

简历中包含与你申请的职位相关的关键词是很重要的。

大数据工程师职位的重要关键词是大数据、Hadoop、Spark、Redshift 等。

4.将最重要的成就放在首位

福赞·萨里Unsplash 拍摄的照片

把自己放在招聘者的角色中。你会如何审阅一份简历?

你很可能会浏览每个要点的前几个词。

招聘人员也是这样做的。

确保首先列出你最重要的成就。把繁琐的工作放在最后。

不要写你做的工作,而是描述你得到的结果。写下你的工作对商业的影响。

如果你能量化你所做的工作就更好了。使用“降低成本”、“自动化流程”、“优化”等句子

例如:

  • 启动分析工具,在营销部门做出数据驱动的决策,
  • 具有统计分布的分布式节点的自动化管理,
  • 维护和优化广告网络平台,以减少在云基础设施上的支出。

5.不要太深入细节

照片由屋大维丹Unsplash

当描述你的项目时,不要太详细——只列出最重要的细节。

简要描述这个项目是关于什么的,它解决了什么问题,提到有趣的事实,比如“我们的应用程序是英国‌the iPhone‌商业应用程序月”。

描述你在项目中的角色、面临的挑战和解决方案。被招募来提高一个最受欢迎的自由职业者商业应用分类的准确性。

尝试量化结果:使用机器学习模型,分类准确率提高了 30%。

用你用过的技术添加一个技术栈:Python,sklearn 等。

一个好的项目描述的例子。

结论

安德烈·格林克维奇在 Unsplash 拍摄的照片

拥有一份精致的简历会增加你被雇主看到的机会。你会脱颖而出的。

希望这些建议能帮你找到那份工作!如果你有其他建议,请在评论中告诉我。

在你走之前

Twitter 上关注我,在那里我定期发布关于数据科学和机器学习的消息。

照片由Courtney hedgeUnsplash 上拍摄

如何用 Python 编写用户友好的命令行界面

原文:https://towardsdatascience.com/how-to-write-user-friendly-command-line-interfaces-in-python-cc3a6444af8e?source=collection_archive---------2-----------------------

让人们喜欢你的应用程序的第一步

沃洛德梅尔·赫里先科Unsplash 上的照片

你在 Python 101 课程中学到的最重要的技能之一是如何使用命令行界面(CLI)运行 Python 代码,这实质上是你的 Python 之旅的起点。命令行应用程序最大的优点是它可以灵活地与其他应用程序结合,并且可以在大多数操作系统中运行。

当我们设计一个命令行应用程序时,我们花了大部分时间考虑应用程序的核心功能,这使得我们有时忽略了 CLI 设计的重要性。过去,我会根据“常识”或我写的一些文档,假设我的用户知道他们应该向 CLI 提供什么。直到我被一些设计糟糕的命令行界面弄糊涂,我才意识到用户友好的重要性。

在本文中,我想解释用户友好的重要性(展示你的同情心)以及我们如何使用 Python 中的 5 个不同库创建用户友好的 CLI。我相信这会让你的用户更开心。

为什么我需要设计一个用户友好的界面?

在进入实现之前,让我们先回答这个问题:为什么我甚至关心接口?python xx.py还不够吗?如果你想让你的用户动态配置你的程序,答案是否定的。假设你的程序需要处理一个文件。比起在代码中硬编码 filepath,更明智的解决方案是允许用户将 filepath 传递给命令行接口:python read_file.py --file_path f.txt,这样用户就可以同时处理多个文件,而不用修改代码。所以经验法则是如果你想让你的用户配置你的程序,那么请考虑创建一个 CLI 。不过,有一点需要注意的是,您应该避免像命令注入这样的漏洞,我稍后会谈到这一点。

用户友好是什么意思?

本文中提到的原则遵循命令行界面指南,这是一个关于通用 CLI 设计的令人敬畏的指南。当我们创建 Python CLI 时,我们关心这些方面:

  • 易于发现:不要假设用户知道或记得他们应该做什么。当出现错误时,可发现的 CLI 提供大量帮助文本、示例和建议。
  • 健壮性:CLI 应该期待来自用户的意外输入。应该优雅地处理错误,而不是抛出可怕的回溯。有时,根据具体情况,运算也应该是幂等的。
  • 提供足够的信息:提供过多和过少信息之间的平衡。这也是在不让人迷路和不使代码过于复杂之间的权衡。

在下面的例子中,我们将坚持这些原则,并给出不同的实现细节。

用例语句

为了便于比较不同的方法,我们将在本文中使用同一个例子。我们将为您生成一个接种二维码。CLI 将要求并验证用户输入,并调用 QR 码生成器 API 来生成 QR 码。

我们都知道这只是一个例子,对吗?不要把这个二维码给任何权威人士看。😃

简单来说,用户需要提供姓名出生日期疫苗生产商接种日期。用户可以提供 1 条以上的接种记录。

这是代码的核心功能。我还在 dataclass 中做属性验证。你可以看看我的一篇关于用 Python 验证类属性的多种方法的文章。

主要功能

默认解决方案 argparse

命令行界面指南中的第一个基本指南是使用命令行参数解析库,在那里你可以。让我们来看看 Python 中的内置解决方案: argparse

arg parser 的示例

在这段代码中,我们做了很多事情。我们创建了一个带有程序描述的ArgumentParser。然后我们向解析器添加许多参数。基本上有两种类型的参数:位置参数和可选参数。

位置参数是必需的,它们的位置定义了它们的功能。当参数的顺序很重要时,这很有用。例如,您想将一个文件从源位置复制到目标位置,那么将源路径放在目标路径前面是有意义的。

但是在这个例子中,参数的顺序根本不重要,所以我们可以使用可选参数。然而,这些参数都不是真正可选的。都是二维码要求的。我们可以通过给每个参数加上required=True来迫使它们成为强制性的。您还可以通过添加整数参数更需要的type来强制进行类型检查。help包含对论点的描述。如果论点期望某种格式或任何种类的限制,你可以在help中提及。

另一个方便的参数是choices。在这个例子中,有一个被认可的疫苗制造商的列表。您当然可以像我最初做的那样在Vaccination类中验证它,但是您也可以将它添加到解析器中,以便尽快向用户发出信号。

本例中关于参数的最后一个好特性是nargs,这是应该使用的参数数量。nargs将不同数量的参数与单个动作相关联。当用户需要提供项目列表时,这很有用。它支持多值,在本例中,我们使用+,意味着必须至少有一个元素存在,否则将会产生一个错误消息。除了这个最小长度检查,我们还检查manufacturerdate的长度,如果它们不匹配,立即返回出口 1。请记住,CLI 应该在成功时返回零退出,在失败时返回非零退出。

说到这里,这里是你如何使用不同语法的 CLI,得到不同的结果。如果你不知道你应该提供什么,你可以输入--help来打印出所有的参数和它们的描述。

—帮助(由创建)

这是正确调用 CLI 的方法。您可以使用较短的名称或较长的时间,参数的顺序并不重要。

正确格式:使用参数的简称(由创建)

下一部分是错误处理。按照指南,错误应该被捕获并以人类可读的格式重写。如果有意外的错误,提供更多的信息(例如回溯)和关于如何提交 bug 的说明。

Miss name 参数,由 argparser 处理(由创建)

这里错过一个日期,由自定义验证处理(创建者)

无效制造商,由 argparser 处理(由创建)

无效的日期格式,由自定义验证处理(由创建)

事实上,还有更多。argparser 提供了更多的特性。例如,您可以使用action="append"来允许类似-m pfizer -m pfizer的重复参数,这将导致名称空间对象中的manufacturer=[['pfizer'],['pfizer']]。您还可以使用default为缺少的参数分配默认值。

像往常一样,看看这篇来自 RealPython 的关于 argparse 的伟大文章。

https://realpython.com/command-line-interfaces-python-argparse/

基于装饰的解决方案—单击

Click 是一个第三方 Python 包,用于以可组合的方式用尽可能少的代码创建 CLI。我最喜欢 Click 的地方是它基于 decorator 的解决方案,它使代码看起来非常干净,并且去掉了一些样板代码。我也觉得这比 argparse 更人性化(我是说对开发者)

这就是如何使用 Click 完成同样的操作。你先从@click.command开始,让函数变成点击命令行工具。然后使用@click.option()添加一系列选项。Click 附带了许多方便的功能。例如,您可以使用定制逻辑通过callback来验证一个参数。在这个例子中,birthdate可以使用相同的validate_date()功能。而且,click.Choice可以和case_sensitive=False不区分大小写。

点击的例子

这是帮助信息。

—帮助(由创建)

以及验证错误的结果。

失效日期(创建人)

Click 的另一个超级好看的功能是提示。你只需要给每个选项加上prompt="<Your message>"就可以了。这是添加 prompt 后的样子。

启用点击提示(由创建)

这个例子不能展示 Click 所有的好特性。除了这些基本功能,Click 还支持从环境变量中加载值的。从某种意义上说,它是完全可组合的,你可以链接多个命令并将一个命令的结果发送给下一个命令。还有一堆高级模式实用程序,使得交互更加用户友好。

站在打字者的肩膀上

Typer 是一个基于 Click 的酷库。它没有使用 decorator,而是利用 Python 中的类型提示来配置和验证参数。例如,要定义一个应该从一组预定义的值中获取的参数,您可以创建一个 Python Enum对象。

这是 Typer 的示例代码。正如您所看到的,一切都是在类型中管理的,因此您可以专注于主函数中的业务逻辑,而不是编写许多包装器和样板代码。

打字者的例子

文档驱动的解决方案— Docopt

Docopt 使用了与以前的工具完全不同的方法。它充分利用了 Python 脚本中的 docstring。根据 PEP 257 ,脚本的 docstring 应该可以作为它的“用法”消息放在脚本的顶部。Docopt 将解析 docstring 并自动生成帮助消息来描述命令行界面。

在某种程度上,我喜欢这种方法,因为它从需求(文档)开始,然后是实现。但是另一方面,docstring 应该如何编写是非常严格的。它不像 Click 那么灵活,错过了许多开发者友好的特性,如回调函数、数据验证等。一般来说,它没有其他工具那么程序化。

但是我们还是来看看如何在我们的例子中使用 Docopt。

doc opt 的例子

如您所见,Docopt 成功解析了参数。[表示可选元素,(表示必需元素。在本例中,制造商和日期应该至少有一个参数。但是除了解析文档之外,它什么也不做。我们需要提供自定义函数来从不同的角度验证输入(例如,类型检查、值检查等)。我跳过这一部分,因为这不是本文的重点。但就个人而言,我喜欢这部分尽可能由 CLI 库处理,以保持代码看起来整洁。

参数是如何存储在 Docopt 中的(由创建)

从任何 Python 对象构建 CLI—Fire

最后,另一个有趣的 Python CLI 库叫做 Fire ,由 Google 开发。Fire 的主要特点是可以灵活地从任何 Python 对象生成 CLI,这不仅意味着函数,还意味着类、模块、对象、字典、列表等。在我看来,就程序如何接受输入参数以及如何调用和组合命令而言,它比其他 CLI 库更有创意。但另一方面,它没有为回调函数、验证等提供现成的解决方案,比如 Click 和 Typer。

让我们检查代码。Fire 没有提供很多选项来配置参数本身,这意味着验证需要包含在主函数中,有点像 Argparser 示例。但是它实际上可以解析函数的 docstring,并在你做--help的时候显示出来。

火灾示例

—火中取栗(由创造)

让我们来看看 Fire 的酷功能,它创建了一个基于类的 CLI。在这个例子中,我们有类QRCode。但是 Fire 似乎不支持像Vaccination这样的复杂数据类型,所以我们必须改变类来接收原始数据类型。另一个问题是,我们希望提供疫苗制造商列表和疫苗日期列表。这在这个基于对象的解决方案中也是不可能的,因为你不能有 2 个*vargs。你能做的是像--vaccine "["pfizer","pfizer"]"一样传递一个字符串形式的列表,并在代码中解析它,但这不是一个非常优雅的解决方案。

下面是命令。方法名也是命令名。可以添加更多类似validate()print()的方法(命令)。

python source/cli.py generate --name xiaoxu --birth 1990-01-01 --vaccine pfizer --date 2021-01-01

一个类调用多个命令并不是强制性的。您也可以使用基于函数的方法,其中每个函数名都是一个命令,不指向fire.Fire()中的任何特定函数。另一个很好的特性是你如何在 Fire 中把命令组合在一起。与 Click 不同,Fire 基本上使用一个新的类将不同的类/功能粘合在一起。总的来说,它很好地集成了不同类型的 Python 对象。

避免命令注入

正如本文前面提到的,当我们创建 CLI 时,我们必须非常小心地处理用户输入,因为用户可以键入任何内容,包括可执行代码。我们应该避免命令注入,类似于 SQL 注入的注入攻击。危险在于恶意代码被发送到您的应用程序并破坏您的环境。命令注入本身就是一个大话题,在任何编程语言中都可能发生。

这是任意命令注入的一个例子。它使用eval来动态评估用户的输入。想象一下用户输入rm -rf /,那么你的环境就真的完蛋了。eval()在 bandit 中被标记为不安全函数。尽量避免。

命令喷射

再比如上传文件。如果您的 CLI 允许用户上传文件,这些文件可能包含恶意代码。确保读取文件的库是安全的,例如,使用yaml.safe_load()而不是yaml.load()

经验法则是避免动态评估用户的输入。如果不可避免,应对用户输入进行严格验证,以降低风险。

结论

到目前为止,我已经向您展示了创建 Python CLI 的 5 个不同的库。每个图书馆都有自己的特色。这里有一点总结:

  • Argparse: Python 内置包。这是整个分析的基准。虽然与其他很酷的库相比,它可能看起来很乏味,但它仍然是您在构建 CLI 时需要学习的第一个库。它可以涵盖 CLI 应用程序的大多数基本要求,但是您可能需要围绕参数创建许多包装器来满足某些要求。
  • Click:一个非常酷的基于装饰器的 CLI 库。所有的参数都可以通过 decorators 来配置,这使得主代码非常干净。它还提供了许多开发人员友好的实用程序,如回调函数、区分大小写的设置、组命令等。
  • Typer:基于类型提示的 CLI 库,依赖于 Click。它充分利用 Python 中的类型来实现与 Click 类似的功能。
  • Docopt:这个 CLI 库通过解析脚本 docstring 来理解参数。我不得不承认这不是我喜欢的,因为它真的限制了你应该如何写文件,而且在将规则应用于论点时,它不太灵活,也不太直接。但是如果您是一个习惯于编写适当的 docstring 的人,您可能会喜欢它。
  • Fire:一个非常有创意的 CLI 库,可以基于任何 Python 对象创建 CLI。老实说,如果你不告诉我,我不会知道这是一个构建 CLI 的库,因为它没有任何显式的 CLI 语法。它与 Python 对象很好地集成在一起,例如创建一个单独的类来将命令分组在一起。但是它在参数验证方面没有那么强大。

哪一个是你最喜欢的?对我来说,我更喜欢 Typer 和 Click,因为它们功能丰富,而且与主要业务逻辑无关。请在评论中告诉我你的偏好!

参考

https://realpython.com/comparing-python-command-line-parsing-libraries-argparse-docopt-click/#packaging-click-commands https://codeburst.io/building-beautiful-command-line-interfaces-with-python-26c7e1bb54df https://www.stackhawk.com/blog/command-injection-python/

如何用 Python 编写网格搜索函数

原文:https://towardsdatascience.com/how-to-write-your-grid-search-function-in-python-43ad0da97522?source=collection_archive---------10-----------------------

Itertools 是您需要的全部

本杰明·博斯奎特在 Unsplash 拍摄的照片

介绍

我回来尝试在 medium 写一些关于编码、机器学习和 Python 的东西。可能,我是唯一一个对此感到兴奋的人,但至少有人:)

由于我没有太多的时间,我决定(希望)写一个系列来解释微小的 Python 函数,这些函数可以使您的日常开发工作变得更容易。你准备好了吗,还有大约一分钟?那我们开始吧!

问题是

假设您想要测试一组超参数来训练您的模型。一种方法是使用网格搜索。在网格搜索中,您可以创建想要尝试的参数的每种可能的组合。对于所有这些组合,您训练您的模型并运行一些评分方法,以了解在给定参数集的情况下,训练好的模型表现如何。

当您是 Python 用户时,最明显的选择是使用 scikit-learn,更具体地说是使用名为 GridsearchCV 的类。然而,您可能不喜欢 scikit-learn(我对此表示怀疑),或者您编写了一些不符合 scikit-learn 接口的自定义代码,或者您只想做一些完全不同的事情。对于这些情况,我有一个用纯 Python 编写的解决方案。这样,当您想要将搜索扩展到更多参数时,就不必编写许多嵌套的 for 循环,也不必更改代码。

解决方案

现在,不用多说,让我们直接进入解决方案

我在这里做了什么?首先,为了避免嵌套和不灵活的 for 循环,我使用了 awesome itertools 模块中的product函数。它所做的是构建一个 iterable,返回你传入的所有 iterable 的笛卡尔积。听起来很疯狂。例如,如果您将四个 iterables 传递给product,每个 iterables 包含两个条目,那么您将得到大小为 4 的 2⁴=16 元组。也许听起来不太好,那就试试吧。

其次,为了方便起见,我没有生成包含 concert 值的普通元组,而是创建了一个字典,将输入键映射到各自的单个值。这应该会简化grid_parameters函数的使用。

最后,怎么用?您必须在字典中定义想要尝试的参数。键/名称应该理想地匹配您将传递给模型的__init__函数的参数。他们不需要这样做,但是这样会让你的生活更轻松。你的字典的值必须是可迭代的,所以列表或元组或类似的东西包含所有你想尝试的值。现在,您只需将该字典传递给grid_parameters函数,并对其进行迭代。在那之后,你想用你的网格点做什么就看你自己了。很简单,不是吗?只有 3 行代码。耶!

照片由艾伦·赫特小Unsplash 拍摄

结论

在这篇非常简短的文章中,我向您展示了一个紧凑且易于使用的原生 Python 实现来生成网格点,您可以使用这些网格点来执行网格搜索。使用它的主要原因是,当您构建了一个没有实现 scikit learn estimator Apis 的模型时,或者当您只想展示您的 Python 技能时:-)

感谢您关注这篇文章。一如既往,如有任何问题、意见或建议,请随时联系我,或者通过 LinkedIn

用户的干扰是如何搞乱你的 A/B 测试的

原文:https://towardsdatascience.com/how-user-interference-may-mess-up-your-a-b-tests-f29abfcfccf8?source=collection_archive---------23-----------------------

行业笔记,实验和因果推断

来自 Lyft、LinkedIn 和 Doordash 的三个解决方案

托姆·霍姆斯Unsplash 上拍摄的照片

介绍

一个严格的 A/B 测试过程会产生与产品成功直接相关的消费者行为的宝贵见解。通常情况下,项目经理采用迭代的方法来优化产品:A/B 测试变体→找到赢家→推出赢家→新一轮 A/B 测试→...

有疑问的时候,A/B 测试一下!

在过去的一年里,全球疫情大大增加了消费者的在线存在,使得大规模跟踪和分析消费者行为数据变得更加容易。难怪公司会将注意力转向在线用户行为,并花费大量资源试图建立自己的实验平台。目标是从实验数据中更好地了解客户。

然而,许多新公司并不具备该领域的专业知识和多年的经验来建立成功的测试。

在之前的一篇文章中,我讨论了让你的商业实验失败的 8 个常见错误。如果你没有机会,请看看。

今天的帖子分享了在个人层面上简单的 A/B 测试导致有偏见的估计并可能导致错误决策的场景。更重要的是,它讨论了大型科技公司(Lyft、LinkedIn 和 Doordash)解决这一问题的三种策略。

什么是用户干扰?为什么它很重要?

为了从 A/B 测试中做出有效的推断,我们要求一个单元的潜在结果不应该受到其他单元的特定分配的影响,也就是。稳定单位处理值假设,(鲁宾,1978,1980);否则,如果假设被违反,我们会得到有偏差的估计。

这里有一个简单的例子。

脸书的 Messenger 团队试图了解新产品功能(例如,新的表情符号)对用户参与度的影响,通过应用程序上的时间来衡量。一个简单的随机化策略在用户层面将一半人口分配到治疗组,另一半分配到对照组。

由于用户在平台上联系在一起,随着他们的治疗朋友增加(或减少)参与度,未治疗组增加(或减少)在应用上花费的时间。由于用户干扰,最初的分配策略没有如预期的那样工作,这明显违反了 SUTVA 假设。

(为了解决这种类型的网络干扰,我们可以应用下面描述的第二种和第三种解决方案。)

用户干扰无处不在,并导致对治疗大小及其方向性的有偏估计。具体来说,它会导致高估或低估真实的治疗效果。实证研究和模拟表明,干扰的偏差范围从 1/3 到与处理效果相同的大小(Blake 和 Coey,2014;霍尔茨等人,2020;弗拉德金,2019)。

此外,它打乱了治疗的方向,例如,将积极的效果变成消极的;反之亦然。

汤姆·霍尔姆斯在 Unsplash 上拍摄的照片

如何在用户干扰下进行 A/B 测试?

用户干扰的存在不会使 A/B 测试无效。相反,它要求更仔细的设计规划和思考。谈到解决方案,公司已经根据干扰的性质提出了几种策略。没有一个“万能”的解决方案能神奇地一次解决所有类型的干扰。

好吧,一个好的开始是探索干扰的本质和随机化的水平。

在接下来的章节中,我将分享科技公司最常用的策略。

解决方案 1:更粗糙的随机化水平

一家拼车公司(如 Lyft )希望检验一种新的匹配算法是否能提高用户留存率。是否可以将骑手随机分配到治疗/非治疗条件下,并比较组均值?

不会,因为同一地理位置的骑手共享同一个司机池,并且由于司机池有限,一个组中的任何用户变化都会影响另一个组。

如图所示,干扰是由聚集在特定地理位置的单元造成的。因此,解决方案也在于操纵位置。我们可以在更粗略的级别(如城市、地区)管理随机化流程,而不是在个人用户级别。

然而,权衡是存在的。粒度越粗,研究的单位就越少,方差就越大,因此与粒度更细的随机化(在个体水平)相比,检验的统计功效更低(Kohavi 等人,2020)。

为了增加其有效性,我们必须将其与其他准实验设计(如差异或观察设计(如匹配)相结合。

根据经验,我们将数据聚合到这样的粒度级别,即每个单元不会相互影响,并且仍然有足够数量的观察值。

延伸阅读:

https://eng.lyft.com/experimentation-in-a-ridesharing-marketplace-b39db027a66e https://netflixtechblog.com/quasi-experimentation-at-netflix-566b57d2e362

解决方案 2:自我-集群随机化

LinkedIn 想知道一项新功能的性能如何。

他们能 A/B 测试一下吗?

不,原因与上述脸书的例子相同。

对于社交媒体公司来说,互联用户之间存在高度干扰。给人 A 和 A 的所有关系人治疗也将被治疗,不管他们最初的治疗状态如何。因此,简单的 A/B 测试是不可能的。在这种情况下,干扰不是由地理位置引起的,而是由连接的网络引起的。

例如,我的 LinkedIn 连接遍布世界各地,无法按照地理位置进行聚类。因此,如解决方案 1 所建议的,更粗糙的随机化水平不会有任何帮助。

LinkedIn 提出了一种新的策略,称为自我-聚类随机化,它将一个焦点人物(" 自我 " )和她的直系亲属(" alter ")视为一个聚类,然后在聚类级别随机化处理分配。

结果,整个集群将被分配到相同的实验条件(处理或控制),而集群之间没有高干扰。

圣雅克等人,2019

代价是它需要一个高度专业化的工程团队,这是许多公司所缺乏的。

https://arxiv.org/abs/1903.08755 https://www.unofficialgoogledatascience.com/2018/01/designing-ab-tests-in-collaboration.html

解决方案 3:转回设计

Doordash 想要测试动态定价(即高峰时段的额外费用)会如何影响客户体验,这是通过用户保留率来衡量的。

为什么用户级别的 A/B 测试不起作用?

在一个地理位置的消费者中有很高的网络效应。消费者共享相同的 Dasher 车队,在个人层面的随机化过程是不可行的。

如果我们随机将一半人口分配到治疗组,另一半分配到对照组,治疗组只能看到供应平衡的一半好处,而对照组仍然获得部分好处,而没有额外的成本(Kastelman 和 Ramesh,2018 年),这违反了 SUTVA 假设。

为了减轻网络干扰,Doordash 选择了更高水平的分析,并在不同的地理位置和时间窗口(如下)随机化处理,这被称为折返设计。它在不同的地理-时间级别上打开和关闭治疗,并检查目标指标(用户保持率)的变化。

卡斯特尔曼和拉梅什,2018 年

与更精细(个体)水平的标准 A/B 测试相比,Switchback 设计具有更少的观察单位,这使得估计不太精确,并且对变化不太敏感。为了提高度量灵敏度,该公司应用了一种称为控制的方法,使用预测作为协变量(CUPAC),以减少方差并增加转回设计的统计功效( Tang et al. 2020 )。

在转回设计中,随机化的单位是地理时间窗口。

在 A/B 测试中,随机化的单位是个人。

与 A/B 测试不同,Switchback 设计假设集群内部相互依赖,而集群之间相互独立。在个体水平上,相同区域-时间单位内的高度相关性大大低估了使用传统 t 检验的方差,这导致了高假阳性率。为了正确说明组内相关性,建议使用组稳健标准误差( Tang 和 Huang )。

延伸阅读:

https://doordash.engineering/2019/09/11/cluster-robust-standard-error-in-switchback-experiments/ https://medium.com/@DoorDash/switchback-tests-and-randomized-experimentation-under-network-effects-at-doordash-f1d938ab7c2a https://doordash.engineering/2020/06/08/improving-experimental-power-through-control-using-predictions-as-covariate-cupac/

外卖食品

  • 您的 A/B 测试中是否存在用户干扰?
  • 如果是,分析/随机化的单位是什么?
  • 关于粒度级别的争论是在保持足够高的统计能力的同时最小化干扰之间的拉锯战。
  • 有三种行业解决方案可供部署:更高的随机化、自我-集群随机化和转回设计。

Medium 最近进化出了自己的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。

https://leihua-ye.medium.com/membership

参考

t .布莱克和 d .科伊,2014 年 6 月。为什么市场实验比看起来更难:测试控制干扰的作用。第十五届 ACM 经济学和计算会议论文集(第 567-582 页)。

弗拉德金,2015 年。搜索摩擦与在线市场的设计。工作。Pap。,质量。本月的技术

霍尔茨博士、罗贝尔博士、利斯科维奇博士和阿拉尔博士,2020 年。减少在线市场定价实验中的干扰偏差。arXiv 预印本 arXiv:2004.12489 。

Kohavi,r .,Tang,d .和 Xu,y .,2020。可信的在线控制实验:a/b 测试实用指南。剑桥大学出版社。

李,h,赵,g,乔哈里,r .和温特劳布,G.Y .,2021。双边市场实验中的干扰、偏差和差异:平台指南。 arXiv 预印本 arXiv:2104.12222

鲁宾博士,1978 年。因果效应的贝叶斯推断:随机化的作用。统计年鉴,第 34–58 页。

鲁宾博士,1980 年。实验数据的随机化分析:费希尔随机化检验评论。美国统计协会杂志75 (371),第 591–593 页。

圣雅克,g,瓦什尼,m,辛普森,j 和徐,y,2019。在 LinkedIn 使用自我聚类测量网络效应。 arXiv 预印本 arXiv:1903.08755

Tang,y .,Huang,c .,Kastelman,d .和 Bauman,j .在转回实验中使用预测作为协变量进行控制。

喜欢读这本书吗?

请在 LinkedInYoutube 上找到我。

还有,看看我其他关于人工智能和机器学习的帖子。

用户觉得你产品的特性有多大价值?

原文:https://towardsdatascience.com/how-valuable-do-users-find-your-apps-features-64ddecc92e06?source=collection_archive---------49-----------------------

照片由 Unsplash 上的诺里斯尼曼拍摄

引入一个框架来减少噪音,并确定哪些功能需要增长,哪些功能需要停止。

阿布奇正处于一个岔路口:她发现自己是一个成功的冥想应用程序的创造者,该应用程序已经有机地发展到数十万活跃用户。她听取了这些用户的意见,随着时间的推移,给这个应用程序添加了各种功能。然后她被卡住了——她下一步该怎么办?阿布奇知道每个应用程序的功能有多少用户。但是她怎么能告诉她的用户发现哪些功能最有价值,哪些功能她应该取消,哪些功能应该重新开始呢?

这是大多数消费者应用程序生命周期中的一个常见问题,有许多分析可以帮助提供答案(哪些可以有效地货币化?什么会给新用户带来最大的保留率提升?).今天,我们将看看一个框架和可视化,它有助于向应用程序的用户展示一个特性的内在价值

像 Abuchi 一样,大多数团队倾向于跟踪单个功能的采用情况,要么以原始用户的形式,要么以参与率(使用该功能的应用程序活跃用户的百分比)的形式。但采用只讲述了故事的一半:它在衡量广泛的吸引力方面很棒,但将它与使用频率配对是涡轮增压它的价值。

频率是多少?这是对某个特性的采用者在过去几天内使用它的频率的衡量。使用频率高的特性对使用它们的人来说显然是有价值的。

将采用率和频率绘制在一起对于所有的应用程序中的特性是它们的相对值的强大可视化,并且是在相同的尺度上相互比较它们的有用方式。

这是图表的样子。特征通常属于 4 个部分之一:

特征分割图。作者图片

  1. 核心特性:这些具有广泛的吸引力,并且一直在使用。在很多情况下,这些特性是用户开始使用你的产品的原因,或者至少会带来大量的流量。他们有明显的产品/市场契合度。对于像亚马逊这样的电子商务网站,搜索他们的目录可能是一个核心功能。
  2. 补充功能:这些功能同样具有广泛的吸引力(在某些情况下,甚至更广泛)——但用户并不经常使用它们。补充这个词可能会让这些特性听起来像是可选的,但它们不是。对于亚马逊来说,这很可能是下订单——一个关键的用户行为,推动他们的经济引擎和用户价值。
  3. 小众功能:对于产品用户群的一部分来说,这些功能非常重要。不是每个人都使用它们,但是那些使用它们的人总是会回到它们那里拥有多样化和庞大用户群的产品往往会表现出这种行为。在亚马逊上购买维生素——不是每个人都这样做,但那些这样做的人可能会偶尔重复他们的订单。
  4. 实用程序或低产品/市场契合度特性:你可能想赶紧把这些作为需要更多工作的失败品扔在一边。是的,你可能是对的,尤其是如果这个故事片是为了服务广大的观众。但是,对产品功能至关重要的重要实用程序和设置也在这里。社交媒体应用上的隐私选项:不是每个人都需要担心,但对那些担心的人来说,这很重要。访问这些设置的人不需要一直切换它们。

现在,这个特征分割图对于 Abuchi 的冥想应用会是什么样子?让我们来看看:

一个冥想应用的虚构特征分割图。作者图片

  1. 每日冥想是的核心特征。很好——这款应用与冥想者有很强的产品/市场契合度。
  2. 介绍性课程是一个特色。这很有意义——它们是为新用户设计的。这些比日常冥想用得少,可能是因为新用户比那些已经升级到日常冥想的用户更不容易坚持。
  3. 课程也是一个小众特色。也许只有真正专注的冥想者才会被课程所吸引——但是那些听课程的人往往非常喜欢它们,以至于他们一直在使用它们。事实上,课程甚至可能是他们使用应用程序的主要驱动力;把它们拿走,你可能会完全失去这些用户。
  4. 另一方面,面试是一个补充功能。许多用户听它们,也许是因为它们很有趣,但并不经常听。阿布奇意识到,她的应用程序今天没有太多的采访,但这是一个很好的理由,开始在这一领域投入更多。
  5. 公用事业和低产品/市场契合度特性中:
  6. 分享应用程序肯定属于这里:用户不太可能需要经常这样做,但用户增长方面的好处是值得的。
  7. 另一方面,Abuchi 打算让更多的用户使用自我指导冥想。是什么阻碍了它?不难发现:Abuchi 已经确保这个功能在应用程序的主屏幕上有突出的房地产。也许她可以重新利用这个空间来推动更有前景、更高频率的功能的更强采用——比如课程。

阿布奇很兴奋!这张特征划分图给了她很多想法,但在她匆忙做出改变之前,她列出了接下来的步骤:

  1. 通过用户研究验证这些发现。虽然强烈的产品意识有助于理解为什么特性表现出这种相对重要性的模式,但与用户交谈是验证这种直觉的一种强有力的方式。也许用户真的想要自我引导的冥想,但正是这个功能的设计让他们放弃了,这是一个很容易解决的问题。
  2. 种植有潜力的作物。小众功能是考虑增长的一个很好的选择——它们在现有的采纳者中有产品/市场契合度,但其他人可能没有使用它们,因为他们不知道它们的存在。
  3. 杀死无用的东西。如果 Abuchi 在长时间认真研究后确信某个功能不能解决任何用户问题,她会考虑牺牲它,让她的应用程序更容易使用。

在现实世界中执行这种分析时,您可能需要考虑其他因素:您可以将一些功能组合到图表上的一个点,或者考虑重要的用户人口统计差异(例如国家)。

现在你知道了!

概括一下:

为什么要进行特征分割分析?了解一个应用内不同特性的相对 ,而不仅仅是跟踪特性的顶线采用情况。测量采用情况和使用频率一起讲述一个更完整的故事,并可以帮助识别哪些功能符合产品/市场,哪些功能需要更多工作,以及哪些功能给用户体验增加了不必要的复杂性。

你应该如何测量频率?

许多指标可以捕捉频率。以下是几个选项:

  1. 使用该功能时活动天数的比例(即,如果用户在过去 7 天中有 5 天是活动的,并且他们在这 5 天中的 4 天使用了该功能,频率= ⅘).
  2. 粘性(MAUWAU 或 DAU/毛)
  3. 新用户保留率(比如,2 周后保留某个功能的用户百分比)。虽然留存率通常用于衡量产品/市场契合度,但这一指标忽略了应用程序的终身用户(他们可能会表现出非常不同的行为)。

你认为你的社交媒体评论有多恶毒?😈

原文:https://towardsdatascience.com/how-vicious-do-you-think-your-social-media-comments-are-204128141eab?source=collection_archive---------23-----------------------

实践教程

预处理、单词嵌入、模型设计和评估、多标签文本分类

作者图片

该项目旨在建立一个多标签分类模型,能够检测不同类别的毒性:“有毒”、“严重有毒”、“威胁”、“淫秽”、“侮辱”以及每个评论的“身份仇恨”。一条评论可以属于以上一个以上的类别,或者不属于以上任何一个类别。我使用 Regex(正则表达式)、NLTK lib、Bag-of-Words 和 TF-IDF 创建了一个 NLP 数据预处理管道,然后使用监督机器学习模型(如逻辑回归和朴素贝叶斯)对评论进行分类。

背景

很明显人类的行为正在改变;我们的情绪越来越依赖于我们在社交媒体上收到的赞、评论和标签。我们得到好的和坏的评论,但每天在数字平台上看到仇恨的话语、诽谤和有害的想法,让它看起来很正常,而它本不应该如此。有毒评论的影响比我们想象的要灾难性得多。它不仅会伤害一个人的自尊或阻止人们进行有意义的讨论,还会煽动人们做出一些邪恶的行为,如最近美国国会的资本骚乱和对印度抗议农民的攻击。因此,如果我们想在社交媒体平台上维持一个文明的环境,以有效地促进对话,那么建立一个可靠的毒性标记系统是非常重要的。

数据集

该项目中使用的数据集是为 Kaggle 毒性评论分类挑战提供的 Jigsaw/Conversation AI 数据集。它包含了维基百科的评论,这些评论已经被人类评级员标记为六种类型的毒性。

数据集的快照如下所示:

图 1:数据示例

探索性数据分析

  • 评论总数:159,571
  • 正派评论(负面类):143346
  • 不体面的评论(正面类):16,225

这 16,225 条不体面的评论被贴上了六种不同类型的有毒标签,如图 2 所示。

图 2: 每个类别的评论数量

请注意,注释可能被分配了多个标签,因此图 3 显示了注释的数量以及与它们相关联的标签数量。

图 3:带有标签数量的注释

该数据集非常不平衡,因为负类与正类的比例为 89.8:10.2。对于这种倾斜的数据集,该模型将在不学习任何东西的情况下,将评论分类为体面评论的默认准确率为 90%。出于同样的原因,在这种情况下,准确性不应该是模型性能的度量。我们需要更具描述性的性能指标。此外,多标签分类问题必须使用与单标签分类问题不同的性能测量来评估。多标签分类度量的一些例子是 k 处的精度、k 处的平均精度、Jaccard 相似性分数、汉明损失、采样 F1 分数等。我使用了 Jaccard 相似性评分,还检查了 F1 评分和 ROC 评分(AUC ),以便更好地评估和选择模型。

在我探索的这一点上,我弄清楚了问题的本质、数据集的统计数据和用于评估模型的评估指标。于是问题出现了——这些类别之间的关联是什么?我假设任何“严重有毒”、“淫秽”、“威胁”、“侮辱”或“身份仇恨”的评论都自动归入“有毒”类别。为了验证这一点,我将“有毒”类别的评论与其他五个类别成对进行了比较,图 4 显示所有 1,595 条严重有毒评论也被标记为有毒评论,证明了我的假设是正确的。

图 4:毒性和重度毒性比较

但是当比较图 5 中的“有毒”和“淫秽”类别时,有趣的是注意到在 8449 条淫秽评论中有 523 条是无毒的。在调查了一些评论后,我得出结论,当评论给人一种总体上负面的感觉,但不包含粗俗的词语时,人类评分者会将该评论标记为淫秽评论。然而,我也看到了被贴上有毒和淫秽标签的评论。对此有什么解释?

图 5:有毒和淫秽对比

接下来,图 6 显示总共有 478 条“威胁”评论,其中 29 条是无毒的。如果这个评论“ 你会被屏蔽 ”被贴上“威胁”而非“有毒”的标签是有道理的。但是的评论真好笑。你个人被冒犯了?所以写坏事的人会写你,你的名字等等,对吗?如果一个人被某个网站上的评论或绰号冒犯了,那么这个人至少要在精神上成长 500 年以上。如果一个人被前面的评论激怒了,那么这个人必须杀了他/她自己。保重! ”被贴上“威胁”而非“有毒”的标签,对我来说没多大意义。

图 6:毒性和威胁比较

当我检查所有 7,877 条侮辱评论时,我发现 533 条侮辱评论是无毒的(图 7)。在进一步的调查中,我发现“侮辱”评论如果不包含刺耳或粗俗的话,就不是“有毒”的。

图 7:毒性和损伤比较

最后,我检查了有毒和身份仇恨评论类别(图 8),1405 条身份仇恨评论中有 103 条是无毒的,原因是这 103 条评论不包含污秽或粗俗的词语,但它们包含针对种族、肤色、种族、性取向、宗教仇恨等的词语。

图 8:毒性和身份仇恨对比

现在,让我们看看原始评论。

df.comment_text[0]

“解释\ n 为什么在我的用户名“铁杆金属迷”下所做的编辑被恢复了?他们不是故意破坏,只是我在纽约娃娃 FAC 投票后关闭了一些煤气。请不要将模板从对话页面中删除,因为我现在已经退休了。89.205.38.27 "

在这个例子中,我们看到原始评论有一些不必要的信息,如数字、标点符号和停用词。这些对模型进行预测是没有用的,所以我们在数据预处理中删除了它们。

数据预处理

  • 在 regex 库的帮助下,删除非字符、不需要的空格、数字,并将所有字母转换为小写。

这些是我在评论中注意到的模式:

让我们用这些替换来写一个清理文本的函数

  • 使用 NLTK 完成词条满足、词干提取、标记化和停用词移除

通过这两个步骤,我们得到干净的注释。现在原始评论看起来像这样:

“解释编辑做了用户名硬核金属迷还原故意破坏关闭气投纽约娃娃 fac 请删除模板对话页面,因为退休”

最好是右边!!!

基于规则的模型

在转向机器学习模型之前,我想看看我是否可以通过检查评论中是否存在类别的最常用词来预测评论中的所有六个类别。

为此,按标签创建了六个数据集,然后将来自每个数据集的所有单词存储在它们各自的字典(词汇字典)中,并按照降序排列它们各自的出现次数。最后,通过检查字典中的前三个单词在评论中的出现情况来做出预测。

预测毒性、严重毒性、淫秽、威胁、侮辱和身份仇恨等级的基线模型精度为:

  • 有毒:89.4%
  • 重度毒性:88.2%
  • 淫秽:96.3%
  • 威胁:87.8%
  • 侮辱:95.8%
  • 认同 _ 讨厌:98.3%

基于这里实现的规则,基线分类器以 76.6%的准确度对体面和不体面的评论进行分类。现在我们必须看看基于人工智能的模型是否能提供比这更好的性能。

使用词袋或 TF-IDF 将评论转换成向量

机器学习模型不接受文本格式的输入,因此我们需要将文本数据转换为矢量形式。这个过程被称为单词嵌入。单词嵌入可以大致分为:

  1. 基于频率——最流行的技术是https://en.wikipedia.org/wiki/Bag-of-words_modelTF-IDF
  2. 基于预测——最流行的技术是 Word2vecGlove

这里我将使用基于频率的单词嵌入。

结果嵌入是 NumPy 数组格式,如果我们观察嵌入,我们将看到高维稀疏数据。

机器学习模型

为了解决多标签分类问题,OneVsRestClassifier 与诸如逻辑回归和朴素贝叶斯的估计器一起使用。

逻辑回归是尝试的第一选择,因为它适用于高维稀疏数据。第二个选择是多项式朴素贝叶斯,因为它假设计数数据,这意味着每个要素代表某个事物的整数计数。在我们的问题中,整数计数代表一个单词在句子中出现的频率。

用于训练 OneVsRestClassifier 的代码:

在 train_model 函数中,我使用了 j_scoreprint_score 这些被定义为:

不同型号的培训结果

根据不同参数集训练的所有模型的性能摘要:

图 9:培训结果

从训练结果可以清楚地看出,逻辑回归在处理连续数据时表现良好(当使用“TF-IDF”计算特征时),而朴素贝叶斯在处理离散形式的数据时表现良好(当使用“词袋”计算特征时)。通过比较这两个模型的 Jaccard 评分F1-评分ROC_AUC 评分,我注意到朴素贝叶斯表现良好。我确信,随着逻辑回归中超参数的进一步微调,我们可以获得一个好的模型,但要获得与朴素贝叶斯相当的结果,在计算和训练时间方面是相当昂贵的。因此,我选择使用朴素贝叶斯,使用“词袋”嵌入技术,其中 max_features 计数为 2000。

这里要注意的另一件事是,该模型学习将相应类别中的频繁使用的词与相应的毒性类别相关联。例如,模型会将此评论“我是一个美丽的黑人同性恋女性”预测为“有毒”和“身份仇恨”,因为“黑人”和“同性恋”在数据集中的“有毒”和“身份仇恨”类别中被大量使用。为了避免这种意想不到的偏见,Jigsaw/Conversational AI 提出了另一个数据集,其中他们用身份属性标记了无毒评论的子集。

结论

我们看到机器学习模型击败了基于规则的基线。在未来,我想尝试像 LSTM,伯特先进的模式,但在这里我有一个问题给你的读者…

当我发现数据集被弱标记时,我应该担心我的模型性能并尝试 LSTM 或伯特等高级模型,还是应该尝试新的数据集,看看我当前的模型是否能表现得更好?

要试用此应用程序,请点击此处。期待听到大家的想法或评论。

VSCode 如何一跃成为 Jupyter 笔记本编辑器

原文:https://towardsdatascience.com/how-vscode-has-leaped-forward-as-jupyter-notebook-editor-29bb688ae382?source=collection_archive---------6-----------------------

改进的笔记本 API 为 Jupyter 笔记本带来了 VSCode 在 Python 编辑方面的一些优势

使用(Jupyter)笔记本——Alejandro Escamilla 在 Unsplash 上拍摄的照片

在等待了半年多的“原生笔记本”之后,现在重新命名的笔记本 API 终于发布了标准的 VSCode 版本。我一直在不耐烦地等待我在 Jupyter 浏览器界面和 JupyterLab 中错过的这些变化,而它们已经在微软的多个 vlogs 中宣布,并且也在不稳定的状态下由 Richard So 在 towardsdatascience 上进行了审查。Notebooks API 为 VSCode 带来了各种新的和改进的特性,其中一些已经在浏览器界面和 JupyterLab 中提供了,但还有一些没有。而那些在最新的 VSCode 版本中感觉更直观的。

就像阿兰·琼斯解释他转换到 VSCode 作为笔记本编辑器的经历一样,我认为编辑 Jupyter 笔记本的门槛同样很低,而在使用浏览器界面或 JupyterLab 时编辑笔记本总是感觉不太好。当我从浏览器界面开始从 R 迁移到 Python 时,我被 RStudio 吸引住了,错过了我认为对数据分析来说必不可少的特性和可用性。继续,我在 JupyterLab 中也找不到这些特性。一切都感觉有点太费力了:打开。ipynb 文件通过命令行,而不是仅仅双击,变量探索只有代码,代码完成要么花了很长时间才出现,要么根本不工作。

与 Alan 相反,我不是偶然发现 VSCode 的。我一直在寻找一个更好的选择来使用 Jupyter 笔记本,最终选择了 VSCode。然而,使用 VSCode 的体验也并不完整。从 Python 脚本在 VSCode 中的工作方式来看,有几个特性在笔记本中无法正常工作。当我听说“原生笔记本”并开始等待的时候,我正处于重新开始寻找另一个工具的边缘。下面,我想简要介绍一下这些特性,它们不仅让我坚持使用 VSCode,还改进了我的工作流程和工作效率。

变量浏览器

让我们首先关注笔记本的内容。Jupyter 笔记本的流行很大程度上归功于数据科学的发展,这涉及到大量的数据探索和分析。虽然所有这些都可以通过代码来完成,但有时类似 excel 的过滤选项可能更高效、响应更快。

这就是变量浏览器的用武之地。这不是一个新功能,但对我这个前 RStudio 用户来说,这是一个巨大的卖点和基本要求。基本上,您可以在笔记本中浏览所有变量及其值。尤其是在数据框上,你甚至可以过滤和排序。它的速度确实有点慢,但当您想要探索数据集时,它可以完成工作。

使用变量资源管理器-按作者分类的图像

移动和复制单元格

使用 Jupyter 笔记本通常是非线性的,在您正在处理的单元格的上方和下方会引入变化和新的想法。我记得一个笑话是这样的“”你能够确认并重现第二次运行笔记本的结果吗?“这归因于这样一个事实,即在初始开发过程中运行单元的顺序与笔记本的结构几乎没有任何关系。JupyterLab 和浏览器界面似乎承认这一点,并且总是允许上下移动单元格。

在引入新的笔记本 API 之前,这是 VSCode 缺少的特性之一,您必须使用复制和粘贴。在 RStudio 中,你基本上是在一个可执行代码部分的 markdown 中工作,这是可以的。在基于 cell 的 Jupyter 笔记本中,这可能非常烦人,并导致我将整个笔记本转换为 Python 脚本来进行代码重构。现在,这些特性被纳入了 VSCode。你可以拖放单元格,拆分它们,也可以合并它们。

(顺便说一下,您可以使用 VS 代码将笔记本转换为 Python 脚本,结果脚本将笔记本的单元格结构保持为 markdown 单元格的代码块和注释块。这些块将以`# %% '开头,并被主要的 Python 编辑器(如 PyCharm、Spyder,当然还有 VSCode)解释为交互式终端的单元。)

移动和连接单元格—作者图片

将绘图保存到文件

与笔记本内容的一个交互通常只需要一行代码,就是将绘图保存到文件中。使用 VSCode 中的 Notebooks API,任何单元格的输出图都可以通过按一个按钮保存为文件。如果你愿意,它也可以通过按一个按钮来扩展。

一开始这听起来没什么大不了的。但是如果你曾经因为重新运行一个单元格或笔记本而覆盖了你需要的图,你会感激这一点。如果你曾经经历过有人在编辑一个情节的时候看着你的肩膀,他只是想要文件快点,你真的想要这个。有很多方法可以错误地输入“savefig ”,当有人不耐烦地观察你编码时,你会发现所有的方法。

此外,如果您重新打开笔记本并且在保存之前没有清除所有输出,保存绘图的选项仍然可用。如果通过代码保存图,则必须重新运行该笔记本的所有单元格,直到到达保存图的行。

在哪里可以找到“另存为”选项—作者图片

可变弹出窗口(提示和快速建议)

让我们从使用笔记本内容转移到使用编辑笔记本的 IDE。当您将光标悬停在某个变量上时,VSCode 会为您提供关于该变量的附加提示和建议。这包括变量的类型和它的一些内容。

然而,正如您在图中看到的,这个特性还没有完全实现。在 Python 脚本中,它在数据框上显示一些信息加内容,而笔记本中提供的唯一提示是“data frame”,咄!

可变弹出窗口笔记本(左)与脚本(右)-作者图片

它适用于原子变量,有时也适用于列表,当您在分析流程中使用一个设置在笔记本另一端的变量,并且您想要快速检查它的最新值时,这是非常有用的。用别人的笔记本工作的时候也是很大的帮助。

原子变量的弹出窗口-作者图片

多光标(和其他编程生活质量特性)

虽然上面提到的弹出窗口不一定是我从 IDE 中需要的功能,但我希望在现代 IDE 中有各种生活质量的功能。我选择在这里展示多光标,因为我用得最多。但是还有一些类似的其他特性是软件开发的标准。

你可以使用 Zen-Mode,有一个 git 集成,你可以通过一行一行地运行代码单元来调试,几乎所有的东西都可以分配一个可定制的键盘快捷键,当然,也可以并排打开各种标签左,右,上,下或者你想要的任何方式。

在笔记本中使用多光标—作者图片

扩展ˌ扩张

除此之外,VSCode 的体验还建立在一个几乎无止境的扩展生态系统之上。自从引入了笔记本 API 之后,大多数扩展也适用于笔记本。在提高生产力和减少错误的扩展中,有括号着色程序或智能感知,它们可以方便地安装在 VSCode 中,并在笔记本中提供。虽然我也将笔记本用作报告或演示工具,但我必须强调代码拼写检查器扩展,它在代码和 markdown 单元格中工作。

不幸的是,并不是所有的扩展都能发挥其全部功能或者没有错误。linter 有时会做非常奇怪的事情,但自从 2021 年 8 月更新以来,这种情况就不那么频繁了。我使用的 TODO Highlighter 扩展通常将所有标记的 TODO 放在一个列表中,可以通过侧边栏访问。但这并不适合。 ipynb 文件。

示例性扩展:括号着色(左)和智能(右)—作者图片

时机

最后,让我们转到在您的工作流程中使用笔记本。这些事情或多或少对我的工作效率产生了一些影响。对于较小的方面,首先是单元运行时间测量。默认情况下,单元格的执行时间将简单地显示在单元格下方。

自己创建这个特性并没有那么麻烦。您需要一个导入、一个赋值和一个打印语句来为 Python 中的单元格添加计时。但是通常情况下,你不会提前设置,尤其是当你需要的时候,因为一些事情花费的时间比预期的要长,你只需要知道花了多长时间。或者更确切地说,重新运行该单元需要多长时间。很方便,它现在就在那里。

单元格执行时间-作者图片

概述

对我的工作流程更有影响的是在你的笔记本上走动。如上所述,笔记本电脑通常以非线性方式发展和增长,导致在笔记本电脑的各个部分之间跳跃。大纲功能可以帮助您,因为它显示了笔记本目录的排序表。它选取第一行降价单元格和代码单元格(如果您在选项中启用了它),并根据基于降价的标题分层组织它们。

对我来说,在引入这个特性之前,代码单元的第一行在很多情况下都是注释。现在,这始终是一个有意义的评论,因为它使我寻找细胞的速度大大加快。这个特性基本上迫使我在设计单元时更加严格。

对于减价单元格中标题的用法,我的经验也是类似的。我有时使用标题,现在一直在使用。随着大纲的折叠和展开,我在笔记本中的定位变得更加有效,同时我的笔记本也有了更好的结构。

笔记本轮廓—按作者分类的图像

展开和折叠笔记本本身

对我的工作效率影响最大的是一个单元一个单元或一个部分一个部分地展开和折叠笔记本的能力。对于在单元格之间切换,折叠整个部分绝对有帮助,这样您需要的单元格只是您正在处理的单元格上方的一个短滚动条。

但这不仅提高了我的开发工作。通过完全控制笔记本中显示的内容,我可以带着它参加会议——当然不是每次会议,当然也不是在黑暗模式下。实际上,我可以带着折叠起来的笔记本,提前有更多的时间来做分析,而不是用尽时间来创建 PowerPoint 演示文稿。在会议中,我可以根据要求做一些小的调整。但是让我们现实一点,任何更大的调整都会停止会议,每个人都看着我编码,这不是高效编码的最佳条件。如果需要,我可以在会后根据会议中的问题和感兴趣的内容制作一份分发材料,并花时间对与利益相关方相关的内容进行提炼。

这可能只有我一个人在做,而且只是有时候,并且非常专注于隐藏所有的代码以不分散和迷惑涉众,但是当它工作的时候,它节省了时间。

当然,JupyterLab 提供了类似的目录、折叠和展开选项,浏览器界面至少部分通过扩展做到了这一点。然而,我个人认为 VSCode 实现更直观,我在本文中的重点是粗略地看一下 VSCode 为笔记本提供的体验的完整性,而不是直接的比较。

展开和折叠笔记本内容-按作者分类的图片

结论

虽然在一些功能上落后了很长时间,但 VSCode 不仅赶上了笔记本编辑器,而且还实现了飞跃。开发人员进一步表现出对持续改善笔记本体验的强烈兴趣,当错误和问题被推出编辑器时,更多的功能被推出。然而,对于 Jupyter 项目背后的开发人员来说,浏览器编辑器和 JupyterLab 也在不断改进。最终它归结为味道,但我希望我可能已经用这篇文章创造了一些胃口,在 VSCode 中尝试 Jupyter 笔记本。

我们如何审计 Twitter 的时间线管理算法

原文:https://towardsdatascience.com/how-we-audited-twitters-timeline-curation-algorithm-cb66bdd07e9f?source=collection_archive---------35-----------------------

以下 的标记的例子 ,我把这个博客分成了 主要发现 和这个“展示你的作品”的板块。

我们通过创建一组“傀儡”账户来测试 Twitter 的算法,然后将他们的“最新推文”时间表与他们的“热门推文”算法时间表进行比较。

这篇文章总结了我即将发表的论文《审核 Twitter 的时间线监管算法》中的技术细节。主要发现在本博客中,全部细节在研究论文中,但这里我将总结如下:

  • 🧦:我们如何设置“袜子木偶”账户来模仿典型用户
  • 🦾我们如何运行自动时间线收集
  • 🦠:我们是如何按主题对新冠肺炎的推文进行分类的
  • 🟦 🟥我们如何为客户生成党派标签
  • 💬其他常见问题

🧦设置袜子木偶

傀儡审计包括用自动化的“傀儡”账户模拟真实世界的原型账户。以下是我们用来在 Twitter 上寻找原型账户的四个步骤:

  1. 定义潜在用户的初始池(在我们的例子中,所有在 Twitter 上关注美国国会议员的账户)
  2. 检测用户群中的社区(使用卢万算法)
  3. 从每个社区中选择一个原型用户(基于度中心性
  4. 验证原型用户不是机器人(在我们的例子中,使用机器人计)

2020 年 2 月,我收集了在 Twitter 上关注美国国会议员的所有账户,总共有 2000 万个账户。由于 Twitter API 的限制,我们在接下来的步骤中使用了 10,000 个账户的随机样本。

在这 10,000 个随机帐户中检测到社区后,我们将每个社区作为自己的网络,然后根据归一化的度中心性选择社区中最中心的用户。我们的目标是选择一个和其他用户关注许多相同账户的用户,而不仅仅是选择一个关注大量用户的账户。

一旦我们验证了原型用户不是机器人,我们就为每个人设置一个木偶,并使用与原型相同的帐号。一半的木偶模仿来自左倾社区的用户(例如,“洛根左”),另一半模仿来自右倾社区的用户(例如,“丽贝卡右”)。

设置好这些账户后,是时候收集他们的时间表了。

🦾自动时间线收集

我写了一个自动化的 Python 脚本,使用 Selenium 访问 Twitter、登录并收集时间线。所有木偶在一个月内每天收集两次时间线,每次收集按时间顺序排列的时间线中的前 50 条推文和算法时间线中的前 50 条推文。

我们的数据收集在 4 月 11 日失败了一次,当时 Twitter 要求对一个傀儡账户进行验证。我们从分析中排除了该数据点。

🦠聚类新冠肺炎推文

我们使用了一种叫做主题建模的方法来对我们收集的所有推文进行聚类。我们使用的算法被称为 GSDMM ,这是标准 LDA 方法的一种修改,更适合像 tweets 这样的短文档。

GSDMM 输出(微调参数后)是 134 个 tweets 集群,我手动检查并标记了这些集群,发现了四个与新冠肺炎相关的大集群。这是他们的样子:

论文中的表 5,详细描述了我们分析的四组推文

🟦 🟥制造党派标签

给党派贴标签是一项困难而复杂的任务,有许多不同的方法。在我们的案例中,我们最感兴趣的是曝光率,所以我们根据哪个社区关注(因此将会曝光)一个给定的帐户来标记帐户党派。

例如,我们的评分系统将本·夏皮罗和吉姆·乔丹标记为“右倾社区的影响者”,因为左倾社区很少关注他们的 Twitter 账户。出于类似的原因,皮特·布蒂吉格和卡玛拉·哈里斯被贴上了“左倾社区的影响者”的标签,因为右倾社区很少追随他们。

值得注意的是,像巴拉克·奥巴马、唐纳德·特朗普和希拉里·克林顿这样的账户在我们的评分系统中被贴上了“两党”的标签。这是因为在左倾社区和右倾社区都普遍遵循这些原则。基本上,因为我们的评分系统衡量右倾和左倾社区是否遵循这些帐户,它不一定反映这些人的政治。

💬常见问题解答

以下是我经常收到的(或预期会收到的)关于研究的一些问题的回答。

为什么只做了八个傀儡账户?

社区检测算法产生了八个主要社区,我们为每个社区创建了一个木偶。

八个账户的样本量太小了,对吧?

我们观察到的效果,包括更少的外部链接,大量的建议推文,以及增加的来源多样性,在八个木偶中是一致的。换句话说,我们有八个账户提供了影响的证据,零个账户提供了相反的证据。

我怀疑很多人会指出,八个账户不足以捕捉 Twitter 的宏观模式。但是这不是这项研究的目标。更确切地说,这更像是标记所称的“数字鞋革报告”,有点像是从 10 英尺处获得的视图,而不是从 10000 英尺处获得的视图。

即使从 10 英尺的角度来看,我们也为许多重要的模式提供了经验证据。理解这些模式如何推广到宏观模式需要不同的方法和更多的资源。

木偶们喜欢或点击推特了吗?

不,木偶们只是简单地每天滚动他们的时间线两次。Twitter 确实根据喜欢、点击和其他行为进行个性化,所以这是我们研究的一个局限。

为什么不查看所有推文,而不仅仅是前 50 条?

我们最初确实使用了被关注账户的所有推文作为基线(类似于巴克西等人在脸书算法研究中的“来自网络的潜力”基线)。然而,感兴趣的指标(例如外部链接率)在该基线和包含按时间顺序排列的时间线中最近 50 条推文的基线之间是不可区分的。此外,它还可以更恰当地比较 50 条按时间顺序排列的推文和 50 条按算法排列的推文。

为什么只收集了前 50 条推文,而不是 100 条或更多?

无论人们是在看搜索结果、广告还是社交媒体帖子,他们都倾向于关注顶部的项目。例如,在一项分析脸书算法的研究中, Bakshy 等人报告说,新闻提要中第一条的点击率约为 20%,但第 40 条的点击率下降到约 5%。这种现象被称为位置偏差我们决定将研究重点放在时间线中前 50 条推文的关键窗口,用户更有可能参与其中。

我还有一个问题…

请在评论中提问或给我发邮件!

我们如何自动化我们的自动语音识别问答

原文:https://towardsdatascience.com/how-we-automated-our-automatic-speech-recognition-qa-3c6d607c26ec?source=collection_archive---------40-----------------------

语言课程:ASR 系统自动化质量保证的逐步指南

Dialpad 能够不断提高我们转录准确性的方法之一是每周至少发布一个新的 ASR 模型。这些新模型是团队更新语言模型(LM)、声学模型(am)或向 Dialpad 字典添加新单词的结果。更多关于 LM、AM 和 dictionary 的信息,请查看我们的 ASR 101 帖子

自然,这些更新将需要测试,以确保它们不会降低准确性或性能,并且它们实际上正在进行它们应该进行的更改。即使每个组件都没有更新,我们也会确保对它们进行测试,因为我们的 QA 流程关注的是这三个组件如何协同工作。但是这些模型的工作原理是将口头电话音频转换成文字形式的文本,你怎么能在不让我们的 QA 团队整天互相打测试电话的情况下测试呢?请继续阅读,了解我们如何能够真正实现这一过程的自动化!

ASR 中的初步自动化每周 QA 流程

第一步——收集关键词

Dialpad 客户可以访问一个名为“公司字典”的功能,他们可以在这里提交对他们的业务很重要的单词和短语,如行话、产品名称和竞争对手。这些条目允许我们的系统更好地识别我们的抄本中这些通常是独特的术语。每周我们都会提取收到的任何新条目,我们称之为关键短语,以及客户为其选择的类别(行话、竞争对手、产品等)。).从所有新的关键短语列表中,随机选择一个子样本在 QA 过程中进行测试。

图片由 Dialpad 提供

dial pad 公司字典功能的实际应用。

步骤 2——测试关键短语

使用实际的客户对话作为指导,我们为每个类别制定了一套 5 个模板句子,以模仿每个关键短语的真实用法。例如,公司关键短语的模板句子如下所示:

您好,感谢您致电【公司】,我是玛丽,有什么可以帮您的吗?

为了开始问答过程,我们将关键短语插入每个模板句子的相关部分。如上例所示,[company]将被替换为我们的关键短语列表中的实际公司名称。这将产生各种不同的句子,其中包含我们随机选择的子集中的每个关键短语。接下来,我们使用一种叫做文本到语音转换(TTS)的技术,这种技术正如它的名字所说的那样,它将文本转换成所讲单词的音频文件。对于子样本中每个随机选择的关键短语,我们将生成模板句子的 TTS 音频文件,从而为每个关键短语生成每个模板句子的音频文件。这些音频文件构成了我们本周的 QA 测试集。

步骤 3——模型评估

现在我们有了测试集,我们准备开始评估实际模型的性能。我们把我们的音频文件,并让我们的新旧模型转录它们。然后,我们可以计算结果转录的准确性,并将旧模型的准确性与我们想要发布的新模型的准确性进行比较。如果新模型比旧模型更精确,并且达到了可接受的基线精度,我们就可以把它发布给我们的客户!

另一方面,如果 QA 度量评估显示旧模型比新模型执行得更好,我们将首先尝试使用相同的测试集重新运行 QA 度量,并再次检查结果。如果我们发现旧型号的性能仍然比新型号好,我们将需要考虑其他因素来决定它是否适合发布。如果新模型:

  • 拥有新的 LM/AM,并且他们的个人表现优于旧的 LM/AM,
  • 与旧模型相比,新模型在额外的客户请求单词上被训练
  • 集成后的所有其他功能都按预期工作,

…然后我们将继续发布新型号。幸运的是,两次没有通过这一部分的 QA 是非常罕见的,在过去的两年里只发生过几次。

下图显示了到目前为止的整个过程:

图片由 Dialpad 提供

第 4 步——烟雾测试

这是我们在部署模型之前在 QA 流程中执行的最后一步。完全公开,这一步还没有自动化,仍然需要手工操作。这是一个特别的步骤,我们将模型部署到试运行环境中,并执行一个测试呼叫来模拟类似客户的对话。在这一步中,我们将通过观察 ASR 模型产生的转录来了解它在产品中的表现,以及它与其他语音智能功能的表现,如时刻通话后总结

我们目前也在研究自动化这部分测试的选项!

QA 自动化流程的未来更新

随着我们将 ASR 扩展到不同的方言和其他语言,我们将一次部署多个模型。为了在自动化 QA 流程中适应多种 ASR 模型,我们计划:

  1. 扩大句子模板的范围,以包括不同的方言和语言。
  2. 为其他语言和方言更新我们的文本到语音转换技术。
  3. 概括 QA 指标,以便相同的指标可以用于多种语言和方言。
  4. 添加自动化集成和冒烟测试。

我们如何通过五个步骤实现 NPS 计划的自动化

原文:https://towardsdatascience.com/how-we-automated-our-nps-program-in-five-steps-221484f02b9f?source=collection_archive---------27-----------------------

利用全自动 NPS 调查流程扩展您的客户洞察力,与脸书或谷歌等科技巨头的项目相媲美

杰里米·毕晓普在 Unsplash 上的照片

自动化的洞察力收集程序曾经是 T4 的一种超级力量,脸书和谷歌这样的科技巨头利用它来发展他们的业务。

例如,当我在 Instagram 工作时,我们有一个全自动的客户调查程序,就像一台加好油的发动机一样嗡嗡作响。每天发送 NPS 调查,收集反馈,对数据进行代表性加权,并将结果显示在仪表板上。太神奇了!

这确保了企业领导始终拥有最新的数据,并能够根据客户的见解迅速采取行动。

不幸的是,像这样的自动化分析能力对于新兴企业和初创公司来说是遥不可及的,因为它们既没有技术专业知识来实施,也没有数据科学专家来分析,也没有资金来将其 NPS 外包给昂贵的研究公司。

直到现在!

我们最近在金融科技初创公司space ship建立了一个全自动的每周 NPS 项目,并认为我们可以分享这个过程,以防它帮助其他新兴企业和初创公司试图利用有限的资源扩大他们的客户洞察力。

我们在太空船上的 NPS 程序现在每周自动运行,完全没有任何人工参与。

结果被收集、加权并显示在仪表板上,供我们跟踪。

唯一需要的时间是初始设置。整个过程花了两个星期的时间来设置,所以这是一个小的投资,有价值的回报,定期客户的反馈。

你会看到我已经列出了我们使用的工具,所以你也可以多了解一点我们如何为这个项目设置数据流。

在此插入注意事项——这当然不是唯一的方法,根据您现有的工具,您的业务可能会有更好的方法。我在这篇文章中的目标是展示一种可以自动化 NPS 程序的方法,但不一定是最好的方法。

好了,我们开始吧。以下是我们如何通过五个步骤实现 NPS 计划的自动化:

步骤 1 —提取并存储每周的客户样本

流程的第一步——big query SQL 脚本自动抽取一个客户样本进行调查。

该脚本在每周一早上运行,并提取新的每周客户样本,这些客户最终将收到我们的 NPS 调查电子邮件。

我使用 BigQuery 中的“调度查询”功能来自动化这个过程。

样本列表存储在抽样用户表中。该表有两个目的— (1)保存将通过电子邮件发送的用户列表,以及(2)跟踪正在进行的抽样客户列表以及他们被选中进行调查的日期。

在提取每周的样本时,计划查询脚本会对照该表进行检查,并排除在过去六个月中被抽样进行客户调查的任何人。

这对于确保我们不会向客户发送过多的调查问卷非常重要。

*注意:你需要根据你的业务和误差偏好来计算最合适的样本量。我会推荐一位研究或数据科学家来帮你完成这一步。 需要帮助就找我

步骤 2 —将样本移至电子邮件工具

接下来,在 BigQuery 示例脚本运行之后,我们使用 Segment 将示例列表移动到我们的电子邮件工具 Klaviyo。

有许多方法可以自动完成这一步,例如 Segment、Zapier、CSV 自动转账,如何完成这一步取决于您的具体业务环境。

我们选择使用细分市场中的“人物角色”功能来为我们执行此功能,因为我们已经在其他一些功能中使用了此功能。但是,根据您的企业安装了什么工具,还有许多其他方法可以做到这一点。

人物角色本质上是一种编写单个 SQL 脚本的方法,该脚本将定期运行的数据分段,并寻找新的数据行。在我们的例子中,它从步骤 1 的样本表中寻找一组新的客户。

当发现新客户时(每周一,在我的计划查询在步骤 1 中运行之后),新客户的详细信息将作为新的电子邮件列表发送到我们的电子邮件工具 Klaviyo。

步骤 3-调查设置和电子邮件发送

然后,每周一下午,Klaviyo 会向步骤 2 中的新每周客户样本发送 NPS 调查电子邮件。

NPS 调查电子邮件是一封标准化的电子邮件,带有介绍和指向由 Typeform 托管的在线 NPS 调查的链接。我们每周都使用相同的电子邮件文本和调查链接。

Typeform 是我们调查工具的首选,原因有两个:(1)它为我们的客户提供了一个漂亮的界面,以及(2)它有一个广泛的集成库,链接到许多不同的平台和应用程序。集成库意味着我们可以用一个类型调查做很多聪明的自动化项目。

客户点击电子邮件中的链接,以表格形式进行调查,并收集回复。

然后,我们使用 Zapier“zap”将数据从 Typeform 直接发送回 BigQuery 数据库,NPS 响应存储在一个表中。

额外提示:扎皮尔在 飞船 帮我扩展和自动化了大量的分析程序。如果你是一家初创公司或者工程资源不足,花一点时间在像 Zapier 这样的工具上——它可以为你的自动化梦想创造奇迹。我和扎皮尔没有任何关系,只是一个粉丝。

第 4 步—称重

一旦收到调查反馈,我需要对它们进行加权,以消除调查研究中出现的反馈偏差。权重*确保您的调查回答更接近您试图研究的客户群。

这大概是整个流程中最统计的位,需要有数据科学背景的人来设置。

这里棘手的一点是,你不能简单地分配一个静态的权重集,然后就到此为止。

客户人口统计和概况会随着时间的推移而变化。它们随着新产品、策略和不同的营销方式而变化。所以你的权重也需要改变。

我解决这个问题的方法是在提取样本的同时运行每周加权查询。我的体重是根据年龄和账户余额等变量计算的。

当响应从 Typeform 进入 BigQuery 表时,权重会自动加入到每个客户的响应中。然后就是在这些分组中合计客户,将其与我的客户群进行比较,并相应地加权*以调整差异。

权重应用于原始数据并保存在新的表中,以创建加权核动力源响应数据的数据集。BigQuery 中的“Scheduled queries”可以轻松处理这一步,自动保存加权表。

加权对某些企业来说可能非常棘手,但对其他企业来说却很容易。权重很大程度上取决于你的业务和研究策略,所以我建议由数据科学家来设置。*https://www.linkedin.com/in/chrisdowsett/如果你在这里需要帮助,请联系我。**

第五步——想象

现在,我已经有了每周 NPS 的加权数据,我需要在一个仪表板中将其可视化,供每个人使用。

我使用 BigQuery 中“保存视图”的魔力来运行计算,并从我的 BigQuery 表中生成每周加权 NPS 分数。使用“保存视图”功能确保总是计算最新数据。

带有 NPS 分数的“保存视图”直接链接到我们的可视化和仪表板工具 DataStudio。将这两者联系起来意味着 NPS 数据会随着我的工作每周自动绘制和刷新。

这里有一个额外的花絮——NPS 项目有时可以大张旗鼓地推出,但过一段时间后就会被认为是理所当然的,尽管在每个 NPS 调查中都发现了神奇之处。

我通过一些提示来避免任何潜在的 NPS“盲目性”——我在 NPS 分数大幅下降时设置了警报,我在我们的 slack 渠道中发布原始客户评论以强调我看到的趋势,我提倡将 NPS 分数作为公司范围内的 KPI(当它适当且被证明是业务成果的关键驱动因素时)。

瞧,我们现在有了一个全自动的 NPS 程序。我们从抽取样本开始,将样本转移到电子邮件工具,发送调查问卷,对数据进行加权以使其具有代表性,并对数据进行可视化。

我建议在第一步和第四步中,请一位友好的数据科学家提供一些信息。如果您的企业无法访问内部数据科学资源,您可以联系自由职业者,这是一个快速且经济高效的选择。

这里的每个部分都是一次性设置,偶尔会进行一些简单的检查。一旦这个过程建立起来,它应该很大程度上照顾自己(摸木头)。

你会注意到,像任何好的自动化过程一样,所有这些都需要一些前期投资。我们花了两周时间从端到端构建这个。但是回报已经超过了前期的小额投资。

在 Spaceship,我们花时间构建了我们的 NPS 功能,现在以低于几杯咖啡的成本获得了每周一次的自动化数据。

现在,我们每周跟踪 NPS 客户的反馈,并且(最重要的是)可以毫不费力地采取行动。这意味着我们更接近客户。

所有这些精细的、定期的、自动化的 NPS 反馈正在帮助我们生产更好的产品和服务。# DataFTW。

科技巨头们早就挖掘了像这样的自动化洞察收集程序的力量。现在,由于市场上有大量经济高效的工具和集成库,新兴企业和初创公司也可以利用自动化的力量与大技术平起平坐。

祝您的 NPS 自动化之旅好运,如果您有任何问题,请联系!

我们如何使用机器学习“入侵”商业图像处理软件

原文:https://towardsdatascience.com/how-we-hacked-commercial-image-processing-software-using-machine-learning-38e9bbea3bb9?source=collection_archive---------27-----------------------

使用人工智能对算法进行逆向工程有多容易?图片来源: Pixabay

机器学习和人工智能安全

标准 ML 工具允许逆向工程图像处理方法非常容易

机器学习提供了巨大的机会。它正在改变我们的世界,我们不得不重新思考我们当前的一些观点。例如,我们认为没有源代码的软件或多或少是安全的,不会被窃取。在这篇博文中,我将展示一些算法并不是这样。

特别是在医学成像,设备制造商试图通过使用专有软件和图像格式来隐藏他们的软件是如何工作的。然而,在 ML 时代,这并不能提供足够的保护。在下文中,我将展示我们如何使用机器学习来理解商业医学图像处理方法的内部工作原理。请注意,我们使用 ML 保留设计的算法仅限于像素处理,这使得攻击特别容易。然而,如果可以访问输入和输出,同样的想法也适用于更复杂的图像处理方法。

如果能够访问正确的数据,逆向工程就变得非常容易。图片来源: Pixabay

在我们的例子中,我们可以访问基于 DICOM 的图像文件(医学成像的标准图像格式),其中包含输入数据以及算法的输出,同样是 DICOM 格式。一个主要问题是,标准图像查看器在输入文件中只会显示一个扫描/颜色通道。然而,我们从文献中得知至少需要两个来计算处理后的图像。仔细观察输入文件的大小发现,它们比只包含一个颜色通道所需的大小大了大约 5 倍。

第一步,我们使用了康拉德的原始数据打开器。它允许加载任何二进制文件,并解释为一个特定编码的图像。在我们的例子中,我们知道图像是 512x512 像素。

康拉德的原始数据开启器的屏幕截图。理解专有图像格式的好工具。图片由作者创建,并由 4.0 在 CC 下发布

使用拖放功能,我们很快就找到了图像数据的编码。这将产生如下所示的图像。图像的偏移告诉您标题的大小和图像之间的位数(导致下一个图像的偏移更大)。

用原始数据打开器打开原始 DICOM 文件的结果。图像头被解释为图像内容,它将图像内容移动像素中的字节数。图片由作者创建,并由 4.0 在 CC 下发布

这样,我们发现供应商在文件头中存储了 4 个额外的图像,这也解释了文件的大小。在下一步中,我们调整了 CONRAD 中的 DICOM 阅读器,以便从自定义 DICOM 标题中正确提取额外的图像数据。这可以用几行代码完成:

在 CONRAD 中读取新 DICOM 字段的代码示例。点击这里查看 github 上的代码。图片由作者创建,并由 4.0 在 CC 下发布

接下来,我们使用了康拉德的 ML 特性。它使用 ImageJ 和 Weka 训练 ML 模型。(我们训练的模型可以在这里找到。)为了证明 ML 能够多么容易地复制该算法,我们仅使用头部的单个切片图像来训练我们的模型。我们总共评估了三个不同的解剖区域:

在我们的例子中,只有一个图像用于训练(参见“大脑”)。测试在两个不同的身体部位进行。由作者创建并在 4.0 的 CC 下发布的图片

对于单能图像的预测,我们在数值计算精度的范围内得到 ML 输出和 vendor 算法的相似性:

对于单能图像,预测是完美的。图片由作者创建,并由 4.0 在 CC 下发布

此外,我们可以证明线性模型足以达到这种精度。通过与文献进行比较,我们可以非常精确地判断供应商实际上实现了哪种方法(在这篇博文中我们省略了这一点)。

在第二个攻击场景中,我们研究了一种非线性算法。在我们的例子中,这是一种物质分离方法。为了使任务更难,我们使用了一个参考,这个参考已经用附加软件处理过,包括重新缩放和裁剪。这意味着我们必须手动对齐输入和输出图像。由于重新缩放,完美的像素对齐不再可能,这给了我们一个更加真实的环境。尽管如此,我们仍然可以训练一个非线性 ML 模型,并实现惊人的相似性,即使是在看不见的解剖结构上。在所有情况下,结构相似性高于 0.98:

非线性方法也可以通过机器学习来学习。图片由作者创建,并由 4.0 在 CC 下发布

我们的见解是,供应商使用非线性模型来解决任务。在接下来的步骤中,我们可以应用奥卡姆剃刀来识别具有最少参数的非线性模型,该模型最好地模仿供应商的模型。然而,如果我们只对复制/再现供应商的算法感兴趣,那么我们已经使用这个简单的 ML 方法完成了。

现在用机器学习逆向工程图像处理算法是儿戏吗?图片来源: Pixabay

显然,这些结果有一定的含义。如果您可以访问图像处理方法的输入和输出,您可以使用 ML 非常快速地创建一个副本。但是,出于文档目的,您可能需要像我们的医疗示例中一样披露这一点(根据医疗设备法律,使用电离辐射创建的图像必须在许多国家存储)。因此,任何竞争者都可以利用 ML 的力量非常容易地对你的软件进行逆向工程。

鉴于这些观察,我相信我们可能会重新考虑在许多应用中反对开源软件的原因。如果你的软件可以这么容易地被黑掉,为什么不直接开源呢?

你可以在我们的文章“中阅读完整的故事。在机器学习的时代,专有软件还能提供知识产权保护吗?”,最近在德国医学影像处理研讨会上接受。

如果你喜欢这篇文章,你可以在这里找到更多的文章,在这里找到更多关于机器学习的教育材料,或者看看我们的深度学习 讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube、Twitter、脸书、LinkedIn。本文以知识共享 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中生成文字记录,试试自动博客

我们是如何学会爱上旋转不变变分自动编码器(rVAE ),并(几乎)停止使用 PCA 的

原文:https://towardsdatascience.com/how-we-learnt-to-love-the-rotationally-invariant-variational-autoencoders-rvae-and-almost-562aa164c59f?source=collection_archive---------8-----------------------

思想和理论

具有旋转不变性的无监督和类条件变分自动编码器及其在图像分析中的应用

马克西姆·齐亚德诺夫&谢尔盖·加里宁

美国田纳西州橡树岭橡树岭国家实验室纳米材料科学和计算科学与工程中心

科学研究通常会产生大量的数据。这些例子包括天文学及其精密的光学和射电望远镜、卫星地理空间成像、医学和生物成像、中子和 X 射线散射以及扫描探针和电子显微镜等领域。通常在每个空间位置的多个波段或光谱上可以获得成像信息,从而产生复杂的多维数据集。典型的例子是超光谱卫星成像,其中在每个空间位置测量全光谱。然而,更多的成像模式出现在领域科学应用的背景下,例如扫描探针或电子显微镜。在所有这些情况下,研究人员的第一步是根据感兴趣的对象可视化并随后解释成像数据,无论是天文学中的新型恒星或系外行星,地理空间成像中的植物生长模式或隐藏装置,还是扫描隧道显微镜中的单个原子的电子属性。

铁基超导体的原子级表面形貌(刚好在超导转变之上)和与几个选定位置的电子态局部密度成比例的隧道电导。图片来自 M.Z .(从他学会爱 VAE 之前的时间)

人类的眼睛非常适合分析成像数据,这种能力是草原上千年进化的结果,及时发现捕食者或猎物是生存的一个条件。同时,人类的感知和理解(几乎没有例外)通常不太适合 3、4 或更高维数据的理解和对象识别。因此,自然的问题是机器学习是否能在这方面有所帮助。

科学领域充满了远见卓识者的例子,他们的远见卓识大大超越了这个领域。一个众所周知的例子是阿达·洛芙莱斯,他早在计算机出现之前就已经探索了计算机编程的背景。另一位是 DARPA 的创始人之一 Joe Licklider ,他在 50 年代写的书《未来的图书馆》中预言了许多现代基于互联网的知识基础设施,包括电子书籍和期刊、数据库等。在显微镜学领域,Noel Bonnett 在其出版物《描述机器学习和多元统计在超光谱数据中的应用》中提出了第一个有远见的观点[1,2]。多元统计方法在显微镜学中的首次实际应用出现在几年后,当时个人计算机已经变得足够强大,可以处理电子显微镜[3]和扫描探针[4]中的“巨大”50x50x1000 超光谱数据集,从而产生可接受的图像。

当时选择(或可用)的 ML 方法是主成分分析(PCA),这是一种将高光谱数据集 R ( xyE )转换为加载图 aᵢ ( xy )和成分 Aᵢ ( E )的线性组合的技术。在最一般的意义上,组件定义了系统的特定行为,并且加载映射包含关于该行为在哪里表现的信息。人们经常认为 PCA 分析没有赋予成分物理意义(这是正确的——它们仅在信息论意义上定义),因此,在过去十年中出现了多个版本的线性和非线性降维方法,允许特定的物理约束[5]。目前,这些方法中有许多是作为 scikit-learn 等基本 Python 库的一部分提供的,甚至更多是作为独立库提供的。然而,应用于高光谱数据的这些方法的关键方面在于,它们仅探索光谱域中的共同特征,并且空间域中的像素交换不影响分量,并且仅导致加载地图中的像素交换。

然而,在许多情况下,分析成像数据的科学家对特定的形状感兴趣。在古代人类世界,我们试图在相反的事情发生之前发现掠食者。在天文学中,我们的目标是确定星系的形状或表明系外行星存在的恒星强度的微弱变化。在扫描探针或电子显微镜中,我们的目标是发现表明对称性破缺和新的电子或结构有序出现的有序模式。有时,PCA 和相关方法允许通过检查装载图进行这种发现。然而,在许多情况下,相关的空间分辨信息分布在数十个装载地图上。因此,问题是是否有机器学习算法可以探索形状?

这里的一个主要困难是图像中的形状可以有任何方向。虽然现代深度卷积神经网络(DCNNs)是等变的,即允许检测图像中任何地方的特定对象,但当发现单个对象的多个旋转类时,它们通常是有限的。例如,在经典情况下,如图像网络或图像中猫的监督学习,猫通常朝向垂直方向。虽然猫在任何方向的数据集都可以制作,但这可能会引起动物伦理待遇的严重问题。因此,即使有监督的网络在识别同一物体的旋转版本方面也不是特别好(例如,参见著名的鸭子对兔子错觉)。当我们不知道我们正在试图寻找什么特定对象时,这对于无监督学习来说甚至是一个更大的问题。

接下来是旋转不变变分自动编码器(在过去的一年里,我们已经学会喜欢它,因为它们让我们解决了困扰我们十年的几个物理问题)。让我们一步步探索这个概念。自动编码器通常指一类特殊的神经网络,其中原始数据集被压缩成少量连续的潜在变量,然后被扩展回原始数据集。网络被训练以改善(在选择的损失函数的意义上)数据重建,这听起来像是有点受限的目标(例如,我们可以不去管它)。这里的关键技巧是,在这个过程中,网络学习如何根据潜在变量来最佳地描述数据。这允许自动编码器发现最佳表示,同时也拒绝数据中存在的噪声。因此应用于去噪、图像重建等。

变分自动编码器(VAE)通过使重建过程概率化而建立在这个概念上。在这种情况下,潜在变量从特定(通常为高斯)分布中提取,并且训练寻求优化编码图像和潜在空间中对应于解码图像的潜在变量的分布之间的重建损失和 Kullback-Leibler 散度。VAEs 最吸引人的特征之一是它们解开数据表示的能力,即发现特定的特征,例如 MNIST 数据中的笔迹风格、人脸的情感或定义机器人系统自由度的复杂流形。在 Medium 和 arXiv [6]上有许多解释 VAEs 的优秀资料来源。

这里,我们将 VAE 扩展到旋转不变特征的分析。在旋转不变 VAE (rVAE)中,潜在层中有一个“神经元”被指定用于吸收图像中结构的任意旋转,而所有其他神经元用于解开剩余的变化因素。这里的技巧是将 VAE 解码器写成图像(空间)坐标的函数,这可以通过空间生成器 net 7或者通过空间广播生成器[8]的稍微修改版本(对于卷积解码器)来实现。这里,我们通过 Pyro 概率编程语言实现了 rVAE。为了完整性,我们介绍并讨论了简单 rVAE 和类条件 rVAE。(r)VAE 的更复杂版本,包括联合(r)VAE、半监督(r)VAE 和(r)VAE,增加了允许未知和部分已知类的正常化流,将在后面讨论。

让我们使用经典的 MNIST 数据集来研究 rVAE 及其变体(注意,它可以是不同的原子或分子结构,而不是数字)。首先,我们创建如下所示的旋转 MNIST 数据集:

来自 MNIST 数据集的样本在-60°到+60°范围内随机旋转。图片由作者提供。

我们进一步使用旋转的数字作为特征,并保留标签和旋转角度作为基础真实数据,以与 rVAE 和类条件 rVAE 分析的结果进行比较。

首先,我们探索简单的 VAE。在这里,我们推导出了潜在空间和点在潜在空间中的分布,用角度和数字来表示。提醒一下,说明 VAE 运算的便利方式是通过潜在空间中(编码)点的分布,以及通过投影到图像空间的潜在空间表示。在前者中,数据集中的所有特征被编码并在潜在平面中可视化。如果数据集的一些属性是已知的(例如类别或旋转角度),它们可以用于设置色标以检查潜在空间中的趋势。可选地,潜在空间可以由点的矩形网格采样,并且相应的图像可以被解码并绘制为潜在空间表示。当潜在空间是 2D,特征也是 2D 时,这种分析特别方便。

VAE 对旋转后的 MNIST 数据的分析。图片由作者提供。

上面显示的是简单 VAE 的旋转 MNIST 数据的潜在空间表示。在这里,我们可以清楚地看到,潜在空间包含所有方向的数字。通过随附笔记本中的函数vae . manifold 2d(d = some _ positive _ integer)试验重建子图像的数量可能会很有趣。特别是对于非常大的 d = 100,单个数字不能被识别,但是潜在空间表示开始显示与单个数字占据的区域相对应的图案。

对潜在空间的检查表明,角度沿着第一潜在方向变化,而数字沿着第二潜在维度变化,形成分离良好的簇。显著的例外是对应于‘9’和‘6’的群集,其在 180°旋转后不能被区分(对于 VAE 是相同的,对于人类也是相同的)。总的来说,这清楚地说明了数据表示概念的解开,其中旋转角度和类别作为数据内变化的两个最突出的因素出现。

现在,我们用条件 VAE (cVAE)重复同样的分析。在这种情况下,我们在训练和预测期间解码的对象是连接的图像和类,因此我们对每个类都有单独的潜在空间。

旋转 MNIST 数据的 cVAE 分析。图片由作者提供。

上面显示的是数字“0”、“1”和“2”的潜在空间。请注意一个非常有趣的模式——在这种情况下,“非物理形状”形成了一个由“物理上可实现的”数字包围的簇(例如,在图像中带有“1”的中心区域周围)。这种行为与物理学的一个基本方面有关,即潜在空间和数据空间的拓扑结构。这方面的一些优秀资源是参考。[9, 10].编码数据也显示在上图中。这里,潜在角度形成了一个定义明确的圆(逆时针方向从负到正的旋转角度),而数字类现在作为单个斑点分布(正如预期的那样,假设每个都形成了自己的潜在空间)。带回家的信息是,现在两个解开的因素是角度变化,VAE 和 cVAE 没有处理好角度。

现在让我们添加旋转不变性,就像包含在 rVAE 中一样。潜在空间表示如下所示。

旋转 MNIST 数据的 rVAE 分析。图片由作者提供。

在这种情况下,潜在空间中的手指指向一个方向。潜在空间显示,角度现在是随机的,而数字形成了定义明确的簇(考虑到我们仅使用两个潜在变量对数据集进行编码,这相当值得注意)。我们也得到了角度作为潜变量之一,上图比较了潜在角度和地面真值角度。请注意,它们是线性相关的,但同时潜在角度具有广泛的分布。这并不奇怪,因为角度是书写风格的特征之一,并且因人而异!因此,我们发现的潜在表征通过引入它作为一个额外的增加变量,然后将其与其他变异因素分开,从而得到了这一事实的补偿。

最后,我们说明了应用于该数据集的类条件 rVAE (crVAE ):

旋转 MNIST 数据的 crVAE 分析。图片由作者提供。

在这种情况下,我们的潜在重建清楚地表明,在每个潜在空间内,数字都指向同一个方向,潜在变量现在编码了笔迹风格的非常微妙的细节。看看上面的“0”、“1”和“2”,并在附带的笔记本上玩其他数字。

这概括了 rVAE 和 crVAE 的介绍。请随意使用笔记本,并将其应用于您的数据集。作者在他们对扫描探针和电子显微镜中的原子分辨和介观成像的研究中使用了 VAE 及其扩展,但这些方法可以应用于更广泛的光学、化学和其他成像,以及跨其他计算机科学领域。还请查看我们的 AtomAI 软件包,用于将该工具和其他深度/机器学习工具应用于科学成像。

最后,在科学界,我们感谢资助这项研究的赞助商。这项工作在橡树岭国家实验室纳米材料科学中心(CNMS)进行并得到支持,该中心是美国能源部科学用户设施办公室。您可以使用此链接进行虚拟漫游,如果您想了解更多,请告诉我们。

可执行的 Google Colab 笔记本可以通过 GitHub 在买到。

1.Bonnet,n,《显微镜图像系列分析的多元统计方法:在材料科学中的应用》。J. Microsc。-Oxf。 1998, 190 ,2–18。

2.Bonnet,n .,显微镜图像处理和分析中的人工智能和模式识别技术。在成像和电子物理学进展,第 114 卷,霍克斯,P. W .编辑。埃尔塞维尔学术出版社:圣地亚哥,2000 年;第 114 卷,第 1-77 页。

3.博斯曼,m;渡边,m;亚历山大博士。Keast,V. J .,使用电子能量损失光谱图像的多元分析绘制化学和成键信息。超显微 2006,106(11–12),1024–1032。

4.杰西;扫描探针显微镜中光谱成像数据的主成分和空间相关性分析。纳米技术 2009, 20 (8),085714。

5.坎南河;耶夫列夫公司;新泽西州拉纳伊特;文学硕士齐亚特迪诺夫;瓦苏德万;杰西;Kalinin,S. V,《通过物理约束线性分解进行深度数据分析:通用框架、领域示例和社区范围平台》。高级结构。化学。Imag。 2018, 4 ,20。

6.金玛,D. P。可变自动编码器导论。 arXiv 预印本 arXiv:1906.026912019。

7.t .贝普勒;钟;凯利,k。布里格诺尔,e;Berger,b,“用空间 VAE 明确地将图像内容从平移和旋转中分离出来。”。神经信息处理系统进展 2019 ,15409–15419。

8.沃特斯,新泽西州;马特伊湖;伯吉斯公司;空间广播解码器:学习 VAEs 中非纠缠表示的简单架构。 arXiv 预印本 arXiv:1901.070172019。

9.巴特森;哈夫公司;卡恩,y。自动编码的拓扑障碍。 arXiv 预印本 arXiv:2102.083802021。

10.法洛尔西湖;德汉,p。戴维森;新泽西州曹德;魏勒,m。福雷出版社;同胚变分自动编码的探索。 arXiv 预印本 arXiv:1807.046892018。

我们如何让 EfficientNet 更加高效

原文:https://towardsdatascience.com/how-we-made-efficientnet-more-efficient-61e1bf3f84b3?source=collection_archive---------23-----------------------

思想和理论

实践中更高效的网络性能

图片作者。

在我们的新论文“使 EfficientNet 更有效:探索批量独立的规范化、组卷积和降低分辨率训练”中,我们采用了最先进的模型 EfficientNet [1],它在理论上被优化为高效,并研究了三种方法来使它在 IPUs 上的实践更有效。

例如,添加组卷积,在 IPUs 上表现良好,在理论计算成本差异最小的情况下,实际训练吞吐量提高了 3 倍。

结合所研究的所有三种方法,我们在训练吞吐量上实现了高达 7 倍的改进,在 IPUs 上实现了 3.6 倍的推理改进,而验证准确性相当。

模型训练的理论成本(通常以 FLOPs 为单位)很容易计算,并且与所使用的硬件和软件堆栈无关。这些特征使其成为一种有吸引力的复杂衡量标准,已经成为寻求更有效的深度学习模型的关键驱动因素。

然而,在现实中,这种培训成本的理论衡量与实际成本之间存在着巨大的差距。这是因为简单的 FLOP 计数没有考虑许多其他重要因素,如计算和数据移动的结构。

引入群卷积

我们研究的第一种方法是如何提高与深度方向卷积(换句话说,组大小为 1 的组卷积)相关的性能。EfficientNet 本身对所有空间卷积运算使用深度方向卷积。众所周知,它们具有翻转和参数效率,因此已成功应用于许多先进的卷积神经网络(CNN)中。然而,它们在实践中对加速提出了几个挑战。

例如,由于每个空间核被孤立地考虑,通常由向量乘累加硬件加速的点积运算的长度是有限的。这意味着这种硬件不能总是得到充分利用,导致“浪费”周期。

深度方向卷积也具有非常低的算术强度,因为相对于执行的 FLOPs 数量,它们需要大量的数据传输,这意味着存储器访问速度是一个重要因素。虽然这可能会限制替代硬件的吞吐量,但 IPU 的处理器内内存架构提供了高带宽内存访问,可以显著提高此类低算术强度运算的性能。

最后,当深度方向卷积被夹在两个密集的点方向“投影”卷积之间以形成 MBConv 块时,它们被发现是最有效的。这些逐点卷积围绕空间深度卷积以 6 的“扩展因子”增加和减少激活的维度。虽然这种扩展带来了良好的任务性能,但它也产生了非常大的激活张量,这会控制内存需求,并最终限制可使用的最大批处理大小。

为了解决这三个问题,我们对 MBConv 模块进行了简单但意义重大的修改。我们将卷积组的大小从 1 增加到 16;这导致了更好的 IPU 硬件利用率。然后,为了补偿触发器和参数的增加,并解决内存问题,我们将扩展比率降低到 4。这就产生了一个内存效率更高、计算更紧凑的 EfficientNet 版本,我们称之为 G16-EfficientNet。

虽然这些变化主要是由吞吐量的提高推动的,但我们也发现,它们使我们能够在所有模型大小上实现比普通组大小 1(G1-高效网络)基线更高的 ImageNet 验证准确性。这种修改导致实际效率的显著提高。

G1 效率网(基线)与 G16 变体(我们的)的理论(左)和实际(右)效率的比较。作者图片。

代理正常化激活

归一化卷积和矩阵乘法运算的输出已经成为现代细胞神经网络的一个基本要素,批量归一化是用于此目的的最常见形式的方法。然而,批量规范引入的批量限制是一个众所周知的问题,引发了一系列与批量无关的替代方案的创新。虽然这些方法中的许多都适用于 ResNet 模型,但我们发现它们都没有达到与 EfficientNet 的 Batch Norm 相同的性能。

为了解决这种批次范数替代方案的缺乏,我们利用了新的批次无关归一化方法代理范数,这是在最近的论文中介绍的。该方法建立在已经成功的组(和层)标准化方法的基础上。

组范数和层范数遭受激活可能变成通道反规格化的问题。随着深度的增加,这个问题变得更加严重,因为反规格化在每一层都变得更加严重。虽然这个问题可以通过简单地减少组规范中的组的大小来避免,但是,这样的组大小的减少会改变表现性和惩罚性能。

代理范数提供了一个更好的修复方法,它保留了表达性,同时抵消了反规格化的两个主要来源:仿射变换和遵循组范数或层范数的激活函数。具体地,通过将群范数或层范数的输出同化为高斯“代理”变量,并通过将相同的仿射变换和相同的激活函数应用于该代理变量,来抵消反规格化。然后,非规格化代理变量的统计被用于校正实际激活中的预期分布偏移。

代理规范允许我们最大化组大小(即使用层规范)并保持表达能力,而不会出现通道反规范化的问题。

附加代理标准化激活操作的卷积块显示为红色。图片作者。

在相关论文[2]中详细探讨了这种新的标准化技术。

重要的是,这种整体方法没有模仿任何批处理规范的隐含正则化特征。出于这个原因,需要额外的正则化——在这项工作中,我们使用了混合和剪切混合的组合。当将层范数+代理范数(LN+PN)的性能与具有标准预处理和自动增强(AA)的两个批范数(BN)基线进行比较时,我们发现 LN+PN 在整个模型大小范围内匹配或超过具有标准预处理的 BN 的性能。此外,LN+PN 几乎与具有 AA 的 BN 一样好,尽管 AA 需要昂贵的“训练”增强参数的过程。

不同大小有效网的不同归一化方法的比较。图片作者。

降低分辨率训练

Touvron 等人(2020 年)[3]表明,通过使用比原始训练图像更大的图像对最后几层进行训练后微调,可以获得显著的精度增益。由于这种微调阶段非常便宜,很明显,这将实现一些实际的培训效率的好处。这引发了许多更有趣的研究问题。应该如何选择训练分辨率以最大化效率?鉴于较大的图像测试速度较慢,这对推断效率有什么影响?

为了研究这些问题,我们比较了两种不同分辨率下的训练,一种是“原始”分辨率(如最初的 EfficientNet 网络中所定义的),另一种是大约一半的像素数。然后,我们在各种图像尺寸下进行微调和测试。这使我们能够研究训练分辨率对效率的直接影响,并确定帕累托最优组合,以实现训练和推理的最佳速度-准确性权衡。

在比较训练效率时,我们考虑了两种测试方案:在原生分辨率上进行测试,或者选择“最佳”分辨率,以最大化整个分辨率范围内的验证准确性。

当以原生分辨率进行测试时,我们看到用一半大小的图像进行训练产生了相当大的理论和实际效率改进。值得注意的是,对于给定的模型大小,我们发现以半分辨率训练和以原生分辨率微调甚至比全部以原生分辨率训练、微调和测试产生更高的最终精度。这个结论表明,对于 ImageNet 训练,我们应该总是以比训练更高的分辨率进行测试。我们现在希望了解这是否也适用于其他领域。

如果我们接下来允许自己在“最佳”图像分辨率下进行测试,我们会看到在原始分辨率下的训练在最终精度上产生了显著的提高,缩小了 Pareto 前沿的差距。

然而,应该注意的是,为了实现这一点,“本地”训练方案的“最佳”测试分辨率最终比对应于一半训练分辨率情况的那些分辨率大得多。这意味着它们在推理时会更昂贵。

作者图片。

这些结果突出了通过研究的三个改进实现的训练效率的改进(I)组卷积[G16(我们的)对 G16(ii)代理标准化激活[LN+PN(我们的)对 GN]和(iii)半分辨率训练[半分辨率(我们的)对本地]。请注意,基线结果没有微调,并且使用原始图像分辨率。

比较推理本身的效率,我们看到在半分辨率下的训练在全精度范围内产生帕累托最优效率。这是一个显著的结果,因为在推论中根本没有直接的翻牌优势。此外,沿着半分辨率推理效率 Pareto 前沿的点对于训练吞吐量保持最优。

理论和实践推理效率。在所有分辨率下测试;线条突出了帕累托前沿。作者图片。

在所有的效率指标中,具有代理标准的模型与具有组标准的模型表现相当或稍好。这是因为精度提高了,而吞吐量只增加了约 10%。然而,重要的是,具有代理范数的模型在整个帕累托前沿使用更少的参数,突出了代理范数在相对于模型大小的效率方面的额外好处。

如何让 EfficientNet 更有效率

在进行这项研究时,我们对 EfficientNet 模型进行了一些修改,以提高训练和推理的整体效率:

  • 通过添加组卷积和降低 MBConv 块中的扩展比率,我们提高了空间卷积的 IPU 硬件利用率,并降低了内存消耗。
  • 通过使用一半分辨率的图像进行训练,我们缩短了训练时间,并显著提高了最终精度。
  • 通过利用新的标准化方法代理标准,我们匹配了批次标准性能,而不依赖于批次信息。据我们所知,这是 EfficientNet 实现这一目标的第一种方法。

结合使用所有这些方法,我们在 IPU 上实现了高达 7 倍的实际训练效率改进和 3.6 倍的实际推理效率改进。这些结果表明,当使用适合处理组卷积的硬件时,如 IPU,EfficientNet 可以提供训练和推理效率,使其超越理论,走向实际的、真实世界的应用。

看报

谢谢你

感谢 Antoine Labatie 、Zach Eaton-Rosen 和 Carlo Luschi,他们也为这项研究做出了贡献,感谢我们在 Graphcore 的其他同事的支持和见解。

参考

[1] M. Tan,Q. V. Le, EfficientNet:反思卷积神经网络的模型缩放 (2019),arXiv 2019

[2] A. Labatie,D. Masters,Z. Eaton-Rosen,C. Luschi,代理正常化激活以匹配批量正常化,同时移除批量依赖性 (2021),arXiv 2021

[3] H. Touvron,A. Vedaldi,M. Douze,H. Jégou,修复训练-测试分辨率差异:FixEfficientNet (2020),NeurIPS 2019

我们如何确定 73 种恶劣天气对快餐和零售需求的普遍影响

原文:https://towardsdatascience.com/how-we-pinpointed-the-generalized-impact-of-73-kinds-of-severe-weather-on-fast-food-and-retail-3120eb22ca9a?source=collection_archive---------18-----------------------

行业笔记

以及如何构建具有动态特征集的机器学习模型来克服数据稀疏性

我们都知道恶劣的天气会影响快速服务零售连锁店的需求。在这个行业工作的人知道,它的影响不仅仅是事件本身的一两天。但是,鉴于恶劣天气事件数据的频率和分布有限,建立一个模型来准确识别这些需求影响模式对于 QSR 链来说是不可能的。下面是我的团队如何解决这个问题,并成功确定了 73 种不同的恶劣天气事件的多天影响。

你不能依靠轶事知识来驱动预测模型或可扩展的需求计划组织。你需要信息——你需要数字。因此,我的团队需要找到一种方法,在发布观察或警告后,立即将恶劣天气影响造成的代价高昂的混乱转化为准确的影响数据。这需要包括:

  • 恶劣天气事件影响需求的时间长度,包括事件发生的日期以及提前和滞后的一天的影响
  • 这些天 QSR 需求平均每天受到多少影响

剧透:非常具有挑战性。但是我们在 QSR 工业中找到了 73 种广义需求影响模式。请注意,这些可能会因地点不同而有很大差异(更多信息请见下文。)

中等强度热带风暴的 QSR 的广义需求影响模式-请注意它产生影响的第一天就是风暴发生的那一天,但它的影响会持续一段时间。

作者图片

空气质量预警 QSR 的广义需求影响模式是不同的。影响在事件发生前就开始了,随着空气质量恶化,警告需要更长时间才能消失,因此人们发现对需求的影响更长。

作者图片

请注意,上面的可视化假设恶劣天气事件是一天的事件,但许多严重事件会持续更长时间。

虽然 2019 年美国发生了 26793 起恶劣天气事件,但恶劣天气事件有很多种,而且分布非常广泛。这意味着数据稀疏性——发生在相关相似地点的相关相似事件——将是一个需要克服的重大挑战。我知道许多数据科学家对模型有很好的计划,但由于数据集太小、太倾斜而无法充分训练模型,所以我想在这篇文章中分享我们的学习成果,以鼓励我的数据科学家同事继续解决看起来几乎不可能解决的问题。

克服数据稀疏性—如何开始

确定单个事件对需求的影响不是问题。面临的挑战是找到一种事件在多个地点和不同种类的 QSR 公司中的统计上准确的平均影响。由于数据稀疏和偏斜,这是一个挑战。

我的公司 PredictHQ 非常适合应对这一挑战,因为我们与许多大型 QSR 和零售商合作,多年来一直在我们的数据集中包括经过验证的恶劣天气观察、警告和事件。但即便如此,我们也没有多余的需求数据和天气数据可以利用。在疫情期间,我们的许多大型 QSR 和零售客户向我们寻求帮助,了解如何更好地管理恶劣天气事件,即使在世界处于封锁状态时,这些事件仍在继续对他们的计划造成严重破坏。他们知道这很重要,原因有三:

  1. 你无法控制天气,但你可以通过更好地调整员工、库存和供应链策略来应对预测的影响,从而节省数百万美元。
  2. 您需要在历史预测中考虑恶劣天气事件,否则它们会扭曲您的需求基线,导致代价高昂的不准确。
  3. 随着世界转向更加动态和强大的预测模型,如果拥有正确的数据,以每日粒度提前一周或两周进行预测的公司将能够迅速做出决策以节省资金。

如果这对他们很重要,对我们也很重要。我们必须克服数据稀疏的三个要素:

  1. 足够多的类似事件,以确定其对 QSR 公司需求的影响,并了解事件的严重程度如何影响,即各种强度的飓风足够多,严寒事件足够多,洪水足够多等
  2. 在同一地点发生足够多相似的事件
  3. 在同一时间同一地点发生了足够多相似的事件(这里时间是一个非常重要的因素,我们必须考虑多个时间段)。

作者图片

假设是好的数据科学的敌人。我们意识到,与其担心在每个地点没有成百上千个几乎相同的活动,我们需要首先确定哪些因素以具有统计意义的方式实际影响了需求。

第一步:空隙和内部空间测试,以确定必要的特征空间

我的团队对每个季节和每个地点的所有恶劣天气事件进行了空间测试,确定了这些因素的影响程度。这意味着我们可以排除一些我们认为对许多恶劣天气类型至关重要的特征。但是相关的特征根据事件的不同而有很大的不同。

例如,冬季风暴和严寒警告只发生在冬季,因此季节特征对这些类型并不重要。但我们确实了解到,纬度对这些恶劣天气类型有着巨大的影响:它们越是在北方,它们的严寒警告和事件就越严重,冬季风暴也越严重,所以这确实需要考虑在内。

我们发现了类似的高温模式(美国南部各州比北部更具影响力),以及 73 种恶劣天气类型中每一种的不同模式。

该测试使我们能够识别恶劣天气事件的一些最具影响的特征,包括:

  • 事件发生的地点。
  • 事件的严重性。
  • 事件的紧迫性。
  • 某一事件发生的概率,即某一地点某一事件的淡季或极不频繁的事件。
  • 事件发生的时间:如上所述的年度时间和每周时间——周末的恶劣天气事件或其他 qsr 和零售的高峰需求时间影响更大。
  • 事件的确定性:我们跟踪观察、警告和事件本身,因此我们需要观察和警告来反映事件的演变性质。

作者图片

步骤 2:动态特征集选择

随着我们的研究,我们的模型开始识别每种事件类型的不同模式。我们意识到,我们必须建立一个模型,其中包括针对每种恶劣天气类型的动态特征集选择。我们还需要这个特性集不断发展,以确保它保持准确。在气候变化的时代,恶劣天气事件的严重性和频率都在增加,因此我们的模型需要根据当前的情况不断更新,而不是依赖 20 年前的数据。

到目前为止,我们已经确定了 73 种不同的恶劣天气需求影响模式。这涵盖了以下恶劣天气类型影响的复杂性,但根据严重程度,有几种天气类型具有不同的模式:

  • 洪水
  • 飓风
  • 旋风
  • 酷热
  • 大寒
  • 热浪
  • 飓风
  • 大雨
  • 严重沙尘暴
  • 严重的暴风雪
  • 暴风
  • 龙卷风
  • 台风
  • 强风
  • 空气质量
  • 暴雪
  • 寒潮
  • 飓风
  • 灰尘

我们发现不同的类别有不同的关键影响因素。例如,一些恶劣天气类型发生在正常季节之外时,如暴雨,会产生更大的影响,但一些天气类型只发生在正常季节内,如冬季风暴和严寒。这意味着我们不需要为那些事件的模型加入这个特性。

我们发现的另一个有重大影响的因素是纬度。例如,严寒对美国北部的影响要大得多,而飓风对美国东南部的影响要比西北部严重得多。

最后,我们的测试版包括 73 种不同的需求影响模式来捕捉这些差异。这些被添加到 PredictHQ 的数据中每一个即将到来的恶劣天气事件中。

选择具有动态特征集的高级机器学习模型,而不是更简单的模型

像许多复杂的模型一样,我们原型的架构与我们开始研究前的想象截然不同。一旦我们完成了研究的一小部分,基于规则的模型显然是行不通的。

我们的高级机器学习模型的关键是约束正则化回归模型(CR2M)。它有一个正则项,所以它会有一个合理的形状,包含了关于你期望看到的行为的先入为主的知识。然后,我们基于预先测试的动态特征空间对其进行训练,以便它可以自动学习领先和落后的天数以及影响的大小。

利用这一点(也就是几千小时后),我们开始获得令人兴奋的结果,例如:

  • 在我们测试的数千家商店中,当他们有需求影响模式来指导他们的模型时,58%的商店可以明显受益于恶劣天气事件数据。
  • 对于受恶劣天气影响的 58%的商店,平均相对 WAPE(加权平均百分比误差)改善为 2.42%,最大改善超过 14%
  • 其根本原因是我们的需求影响模式将受计划外事件影响的预测天数从 46 天延长至 137 天,几乎增加了两倍。

即使 WAPE 改进 1 个百分点,也能为我们正在建设的全国 QSR 连锁店节省数百万美元,我们对结果感到非常兴奋。我希望这篇文章对您有所帮助,并且您的数据科学团队也在处理和解决具有挑战性的问题。

对于热衷于探索恶劣天气数据的数据科学家,我们制作了一个 Jupyter 笔记本作为指导

我们如何用 MLFlow 追踪机器学习实验

原文:https://towardsdatascience.com/how-we-track-machine-learning-experiments-with-mlflow-948ff158a09a?source=collection_archive---------37-----------------------

正确跟踪你的机器学习实验比你想象的要容易

来源:作者

当您建立机器学习模型时,通常会运行几十个或数百个实验来找到正确的输入数据、参数和算法。你做的实验越多,就越难记住什么有效,什么无效。

有时你看到一个很好的结果,但是因为它需要几个小时或几天才能产生,你已经改变了代码。而现在你不记得你用什么参数得到那个结果了!

当然,这是所有科学研究的永恒问题。这是一个传统上由实验室笔记本解决的问题:一本科学家仔细记录他们进行的每个实验的日志。

莱纳斯·鲍林实验笔记本的一页。来源:作者

许多数据科学家遵循类似的方法,用数字或手工记录他们的实验。但这并不总是适用于机器学习。您需要跟踪三件事情:数据、代码和模型。即使你记笔记非常精确,也不可能把所有事情都完整地记录下来。

幸运的是,您可以使用 MLFlow 自动跟踪实验。它不仅设置简单,而且很容易适应您现有的工作流程。

什么是 MLFlow?

MLFlow 是一个广泛的机器学习平台,有几个组件。我们现在只关注它的实验跟踪特性。我们之前已经讨论过模型注册中心以及它们为什么有价值。实验跟踪和模型注册之间肯定有一些重叠,但它们并不相同。

实验跟踪与模型注册

模型注册是为系统经理准备的,关注于生产的模型。另一方面,实验跟踪工具是让科学家跟踪所有的实验,包括不成功的实验。

注册中心跟踪并可视化这些模型的性能和相关元数据。但对于生产中的每个模型,通常都有数百次失败的尝试。实验跟踪是为科学家和研究人员设计的,有助于理解不成功和尚未成功的实验。通过确保工作不会丢失或重复,它使研究过程更有效率。

MLFlow 的 Python 库和仪表盘

您将用于实验追踪的 MLFlow 的两个组件是其 Web UI 和 Python 库。您可以通过运行一个 install 命令来获得这两者:

pip 安装 mlflow

通过运行 mlflow ui 并在浏览器中访问 http://localhost:5000 ,您可以立即查看所有实验所在的仪表板。

MLFlow 仪表板的默认视图。来源:作者

这个仪表板已经有了一系列类似于实验室笔记本的功能:你可以做笔记,搜索以前的数据,并设置新的实验。

当您将它与您刚刚安装的同一个 mlflow Python 库结合使用时,事情会变得更加有趣。通过在现有的机器学习代码文件中添加几行代码,您可以轻松地跟踪每一次运行。这将自动保存您使用的参数、结果,甚至完整的模型二进制文件。

下面的截图展示了如何用大约十行代码开始自动跟踪你的实验。

使用 MLFlow 跟踪预测葡萄酒质量的代码。来源:作者

突出显示的行是特定于 MLFlow 的,而其余的是预测葡萄酒质量的标准 scikit-learn 示例。

每当您用这段代码运行一个实验时,它都会记录一个条目,您可以在仪表板中查看。请注意以下几点:

  • 在 Python 代码中,我们引用了一个实验 id`。在 UI 中创建新实验后,您可以在仪表板中看到这一点。一个实验可以运行多次,因此每次尝试新的超参数或其他变化时,您都不需要新的实验 ID。
  • 您现有的培训和评估代码需要在 mlflow.start_run 块内。
  • 您可以使用方法 log_param、 log_metricsklearn.log_model 记录参数、度量和整个模型。

显示两次运行的 MLFlow 仪表板。来源:作者

从这里,您可以随心所欲地更改参数,而不用担心忘记您已经使用了哪些参数。例如,在屏幕截图中,您可以看到 MLFlow 跟踪了两个实验的结果,在这两个实验中,我们更改了 alphal1_ratio 参数,从而很容易比较这些指标如何影响 r2 和 rmse 性能。

保存自由格式的笔记

许多科学家保留自己的笔记本而不是使用结构化平台的原因是,他们觉得预先创建的模板不够灵活。

我们喜欢 MLFlow 的一点是,您可以在不同的级别保存笔记:与整个实验或特定运行相关的笔记。

MLFlow 的笔记功能。来源:作者

MLFlow 内部工作方式

MLFlow 可以用不同的方式设置。您可以在本地完成,就像我们在上面的例子中所做的那样,或者在远程服务器上完成,这样您就可以在整个科学家团队之间共享一个仪表板。

如果您在本地安装它,您会注意到它在您执行 Python 代码的同一个目录中创建了一个名为“mlruns”的目录。在这个目录中,您可以找到完整的模型二进制文件(如)。pkl 文件)。

如果您想要跟踪大量的模型,并且需要更多的空间,您可以配置 MLFlow 将这些文件存储在 S3 或另一个云存储提供商上。

扩展您的机器学习基础设施

我们使用 MLFlow 作为我们开放式 MLOps 架构的一部分。您可以单独使用 MLFlow,但它也可以与其他 MLOps 组件配合使用,例如用于调度和管理任务的提督,以及用于轻松协作的基于云的 Jupyter 笔记本环境。

我们喜欢讨论构建和跟踪机器学习模型的挑战。如果您想讨论您团队的机器学习方法,请联系我们。

我们如何将气流用于 SQL 警报和松弛通知

原文:https://towardsdatascience.com/how-we-use-airflow-for-sql-alerts-and-slack-notifications-5becedfc03fd?source=collection_archive---------17-----------------------

在加载数据时,当事情没有按计划进行时,使用气流来获得关于松弛的通知

Sirena ,我们使用 Apache Airflow 来运行我们所有的数据编排。Airflow 是一个开源工具,由 Airbnb 创建的,用于创建和调度数据工作流。本质上,Airflow 是一个管弦乐队,它以给定的频率运行任务,同时还处理回填、任务依赖等等。在 Airflow 中,工作流被定义为有向无环图(Dag ),它定义了不同任务之间的依赖关系。

在 Sirena,除了帮助我们将数据从一个地方转移到另一个地方,我们还发现了气流的另一种用途。我们还使用它来触发某些数据质量指标的警报。这个想法很简单,我们定义一个 SQL 查询,然后为结果定义一个条件。该查询应该输出一个数字,如果该数字不符合条件,那么我们将发送一个 Slack 警报。它的美妙之处在于它们的制作非常简单。我们已经对警报进行了参数化,允许我们在 YAML 中创建配置文件,这些文件将作为 Dag 在 Airflow 中具体化(关于这一点的更多信息,请参见未来关于 Airflow factories 的帖子……)。这些警报对于确保数据管道没有发生灾难性事件特别有用。

在这篇文章中,我将指导您为您的 Airflow 实现建立一个类似的工作流。

配置文件

在我们深入研究 Python 代码之前,让我们停下来想一想我们希望我们的配置文件是什么样子。除了在 Airflow 中创建 Dag 所需的所有“必需”字段,如名称、间隔、所有者等。我们还需要一些其他的东西。

可以说,最重要的字段是我们将用来实际定义警报的字段。为此,我们将需要一个字段来写我们的 SQL 查询和我们的条件,比如"大于 5 "之类的。我们将把我们的条件一分为二。标准(greater thanless than等)和我们的目标值。

除此之外,我们还需要定义我们希望如何通知,我们希望通知谁,以及实际的消息是什么。正如我之前提到的,在 Sirena 中我们使用 Slack 来发送通知,所以我们的通知方法是 Slack。我们的收件人来自 Slack 频道或用户列表,但我们有一个专用频道来接收所有数据团队的通知。最后,我们将使用警报的描述来发送描述性消息,让我们知道发生了什么。

注意,我们定义了一个notifier。这允许我们配置我们将使用什么服务向我们的列表recipients发送通知。

我们可以为我们想要设置的每个警报创建一个配置文件,并将它们全部存储在/dags/alerts/中,我们的 DAG 工厂将从这里获取所有这些配置文件,并创建必要的 DAG。我们的 DAG 工厂将从这个目录中获取所有的配置文件,这就是为什么这个enabled属性会派上用场。我们可以使用它来启用/禁用警报,而不必删除整个文件。

警报工厂

现在我们可以跳到我们的警报工厂。我建议你 关注我的博客 以获取即将发布的所有关于 DAG 工厂在气流中的帖子。现在,重要的是要知道工厂本质上是一个 Python 脚本,它将遍历/dags/alerts/中的所有配置文件,并为每个文件创建一个 DAG。它的代码非常简单,但是让我们一起来看一下。

我们要做的第一件事是从/dags/alets/导入所有的配置文件并迭代它们。对于它们中的每一个,我们都希望创建一个 DAG,为了做到这一点,我们实现了一个函数create_dag_alert,它接受配置文件(作为一个 Python 字典)并返回一个带有一个使用PythonOperator的单一任务的气流 DAG。

让我们将这个函数分成不同的部分,这样我们就可以一部分一部分地检查它:

第 1 部分:定义 DAG

我们首先基于配置文件为 DAG 定义一些默认参数。你可以看到,对于其中一些值,我们实际上使用了配置文件(例如ownerschedule_interval),但是对于其他一些值,我们只是硬编码了我们想要使用的值(例如retriescatchup)。这取决于你,我们目前没有看到将这些添加到配置文件中有太多的价值,但我们可能会在某个时候这样做。关键是,不要拘泥于这种做法,做对自己最有效的事情。

第 2 部分:任务功能

这其实是工厂的大头。这里我们想要做的是创建一个将使用PythonOperator执行的函数。本质上,这个函数应该确定条件是否满足,如果不满足,就发出通知。

我们首先从配置文件中获取查询,并针对我们的数据仓库运行它(在我们的例子中是雪花,但这应该适用于任何数据仓库)。然后,我们根据 YAML 文件中配置的目标值评估结果,并使用我们指定的标准进行比较。之后,我们检查是否需要通知,如果需要,我们将根据选择的通知程序调用适当的函数。

第 3 部分:设置 DAG 和任务

最后,我们只需要向 DAG 添加一个任务,使用PythonOperator执行_run_alert函数。

回到原点,注意我们如何返回我们创建的 DAG (dag ),以便我们可以使用它并将其添加到全局范围。

结论

现在,关于这个实现有很多要说的。我认为最重要的一点是 DAG 工厂方法,以及编写新警报是多么简单。但是在以后的文章中会有更多的介绍。关于警报本身,最好记住这不会取代您的数据质量工具,如 great_expectations ,甚至 dbt tests 。此外,同样地,great_expectations 和 dbt 测试可以和谐共处,我看到了这些 SQL 警报与这些其他工具相结合的地方。我的想法是,您可以使用这些 SQL 警报进行数据加载,使用 dbt 测试来测试您的转换,并对您的最终产品寄予厚望,以确保您的数据利益相关者使用可靠的数据。

回头看看实现本身,在我写这篇文章的时候,我注意到这段代码需要重构,有些东西可以用更简洁的方式实现。但是,嘿,我把它作为一个练习留给读者去寻找更好的方法来改进这个脚本,甚至可能把它扩展到更多更好的用例。在任何情况下,希望这是一个有用的基础,并激发您的创造力,以改进关于数据加载到数据仓库的通知。

你“真正”了解生存分析吗?

原文:https://towardsdatascience.com/how-well-do-you-really-know-survival-analysis-221885b89a8e?source=collection_archive---------12-----------------------

入门

乔纳森·博尔巴Unsplash 上拍摄的照片

"你能描述一下这些卡普兰-迈耶曲线中发生了什么吗?"面试官问我。我当然知道那些是什么,当他们催促我说更多的时候,我确实很震惊——我不知道我还能说什么。于是,我结结巴巴地找到了一个答案,过了一会儿,面试官们都点了点头,感谢我抽出时间。

我没有得到那份工作。

尽管我把生存分析作为我的技能之一写在了我的简历上——而且我也合法地学习和使用了它——但后来我意识到我的理解仍然存在漏洞。生存分析是一个庞大的主题,可以从不同的层面进行探讨(这里是一些常见主题的概述这里是以及深入数学的示例这里是)。这篇文章是我试图更严格地教会自己一些生存分析中固有的偏见,并与更多的读者分享这些信息。虽然有许多不同种类的偏差(你可以看到一个相当全面的,但不是详尽的,这里列出),我将重点关注长度偏差时间相关偏差(注意这些偏差有许多其他名称)。最后,我给那些曾经怀疑我真的了解自己的东西的人一些建议?

当你通读这篇文章的时候,有一些事情需要记住(我们很快会回到这个话题):

你相信这张图表向你展示的吗?

所以问问你自己:

你对生存分析有多了解?

关键生存概念

本文将假设您对生存分析和流行病学中一些更常见的主题有所了解,所以我不会涉及太多的技术细节。在这一节中,我将描述一些贯穿始终的关键概念。

生存分析是一个统计字段,它考虑了一个随机变量, X,,它代表了事件发生前的某段时间。这个事件可以是好的,比如肿瘤缓解,也可以是坏的,比如死亡。表征 X、的方法有很多,但我只会简单介绍一种:生存函数

****生存函数代表个体存活超过时间 x 的概率。这个量应该严格递减。当我们知道我们所有观察的结果时,我们可以凭经验估计生存函数——在任何时间 x,生存函数是尚未经历该事件的人或事物的比例。然而,在真实数据中,往往不是这样。要么研究在我们观察到所有研究参与者的事件之前结束,要么参与者退出并离开研究。因此,我们引入一个叫做审查的概念。这是一个二元变量,按照惯例,被审查的参与者要么没有经历过这个事件,要么已经退出,因此我们无法再观察他们。如果你忽视审查,你就高估了生存概率。

快速说明一下,审查应该是随机的。举个例子,假设我们正在进行药物 X 的临床试验,但它似乎在亚洲男性中引发了非常痛苦的副作用。所以当所有亚洲男性退出时,研究样本变得有偏差,我们失去了关于药物 X 对整个群体的实际影响的信息。

回到估计生存函数。当我们没有每个人的结果信息时,我们使用 Kaplan-Meier 估计值

其中 n_i 代表仍未经历该事件的观察值的数量,d_i 代表在时间 t_i 经历该事件的观察值的数量

如果我们在 x 轴上绘制时间,在 y 轴上绘制卡普兰-迈耶估计量,我们会得到卡普兰-迈耶曲线

还有一个关键术语我不得不介绍:截断。这通常与审查相混淆——我花了一段时间才自信地区分这两者。这可能通过图表更容易理解。

截尾与截断图

左截断发生在由于研究设计的原因,只记录了存活超过一定时间的个体的数据时。我们通常将在研究开始之前经历过该事件的个体(因此,不包括在研究中)称为我能想到的最简单的经验法则(对于相当棘手的话题!)截断和删截的区别在于,删截的个体仍然是研究的部分,而截断的个体则不是。 (注意,当我们处理多个事件时,这个经验法则开始失效,参见这篇文章获得更深入的解释)。忽略截断会产生一个有偏差的估计,因为我们试图从我们的样本中得出一个关于总体人口的结论,这个样本甚至不包括被截断的个体。我发现有一个简单的自测题有助于确定你的数据是否被截断,那就是我的研究中可以不包括某些人吗?**

希望你已经做到了这一点——这就是我愿意在本文中包含的所有数学知识!正如我在开始时提到的,本文假设对生存分析有一些基本的理解,所以理想情况下,前面的部分更多的是作为复习而不是介绍。

长度偏差

背景

长度偏差是我们要讨论的第一个偏差(我在两段前提到过它!).它也被称为长度-时间偏差长度偏差抽样、生存偏差、生存偏差、延迟进入偏差等等。它发生在我们忽略左截断的时候。考虑左截断意味着调整风险集、或仍未经历该事件的人数,以仅包括在每个事件时间已经进入研究的人。让我用一个玩具例子来演示一下:

x 表示一个事件

如果我们想估计我们在时间 30** 的生存函数,正确调整左截断,我们将得到 2/3,或 66%的存活率。如果没有正确考虑左侧截断,我们将包括在时间 30 时尚未进入研究的顶级个体,并错误地计算 3/4,或夸大的 75%存活率。你看到我们的估计是如何偏向上方的了吗?因为我们的样本错误地包括了每个人,假设每个人都是研究的一部分。**

r 使用真实数据进行演示

install.packages("pacman")
pacman::p_load(tidyverse, broom, survival, survminer, KMsurv)# KMsurv provides datasets from Klein and Moeschberger (1997)data(channing)

让我们先来看看我们正在处理的数据:

head(channing, 5) obs death ageentry  age time gender
1   1     1     1042 1172  130      2
2   2     1      921 1040  119      2
3   3     1      885 1003  118      2
4   4     1      901 1018  117      2
5   5     1      808  932  124      2

death是审查变量,ageentry表示个人进入研究时的年龄(以月为单位)(又名观察到的** 截断时间),而age表示他们经历事件/成为审查对象时的年龄(以月为单位)。在这种情况下,起源时间是出生(因为我们正在处理年龄),但在其他研究中,起源时间可以是疾病诊断年,例如,然后时间尺度将是日历年。在这个例子中,我们问的问题是“人们进入养老院后能活多久?”**

你还记得我一开始给你看的图表吗?如果我从表面上看这张图表,我会得出结论,性别与这个养老院的不同存活率有关,随着时间的推移,男性的平均存活率低于女性!

与本文前面的图表相同

但是你猜怎么着,这是因为我忽略了左截断。在采访中,这是他们希望我思考的类型,但我不知道。

为了夸大忽略左截断的影响,我稍微修改了数据。我在这个数据集中随机挑选了 50 名男性,并将他们的事件时间age设置为等于他们的进入时间ageentry。这 50 只雄性现在是左截断

set.seed(47)
male_indices <- which(channing$gender == 1)
truncated_sample <- sample(male_indices, 50)
xchanning <- channing %>%
  mutate(id = row_number(),
         age = case_when(id %in% truncated_sample ~ ageentry,
                          TRUE ~ age),
         time = age - ageentry)

然后我定义了一个函数来拟合 KM 曲线,不需要调整左截断。

fit_naively <- function(data) {
  naive_fit <- survfit(Surv(age, death) ~ gender, data = data)
  plot <- survminer::ggsurvplot(naive_fit, 
                        data = data,
                        conf.int = T,
                        risk.table = T,
                        pval = T,
                        fun = "pct",
                        legend = "bottom",
                        legend.title = "sex",
                        legend.labs = c("Male", "Female"),
                        tables.theme = theme_cleantable())
  return(list(fit = naive_fit,
              plot = plot))
}fit_naively(xchanning)$plot

就像在我们的玩具例子中一样,生存估计器没有考虑左截断,即个人在特定时间没有技术上进入风险集,并且高估了生存概率。长度偏差源于这样一个事实,即为了被纳入本研究(即进入养老院),一个人必须存活足够长的时间!

设计阶段考虑左截断为时已晚,但我们仍然可以通过使用 R survival包在分析阶段考虑左截断。我们简单地将Surv对象指定为:Surv(truncation_time, time_to_event, status, type = "counting")的形式,并过滤掉那些在研究期开始时被左截断的对象,因为他们不应该被包括在风险集中(通常,在实际设置中,我们甚至没有关于那些在研究开始前经历过事件的人的数据,因为我们永远不会知道这些人!).

fit_with_lt <- function(data) {
  adj_fit <- survfit(Surv(ageentry, age, death, type = "counting") ~ gender, data = data %>% filter(age > ageentry))
  plot <- survminer::ggsurvplot(adj_fit, 
                        data = data,
                        conf.int = T,
                        risk.table = T,
                        fun = "pct",
                        legend = "bottom",
                        legend.title = "sex",
                        legend.labs = c("Male", "Female"),
                        tables.theme = theme_cleantable())
  return(list(fit = adj_fit,
              plot = plot))
}

要了解性别效应是如何产生偏差的,最简单的方法就是用coxph运行一个 Cox PH 模型。我不会在这篇文章中解释这一点,因为担心这篇文章会比现在更长,但是你可以在这里查看一个简单的解释。

naive_cox_x <- coxph(Surv(age, death) ~ gender, data = xchanning)
broom::tidy(naive_cox_x, exponentiate = T)# A tibble: 1 x 5
  term   estimate std.error statistic  p.value
  <chr>     <dbl>     <dbl>     <dbl>    <dbl>
1 gender    0.561     0.173     -3.34 0.000823adj_cox_x <- coxph(Surv(ageentry, age, death) ~ gender, data = xchanning)
broom::tidy(adj_cox_x)# A tibble: 1 x 5
  term   estimate std.error statistic p.value
  <chr>     <dbl>     <dbl>     <dbl>   <dbl>
1 gender    0.791     0.232     -1.01   0.311

你看到如何解释左截断(解释在我们修改的数据集中没有包括在研究中的人)表明性别与长期存活率没有真正的联系吗?简而言之,coxph函数通过计算生存来解决左截断问题(技术上的风险,但本文没有涉及!)函数,其条件是人们存活足够长的时间以进入研究。

总是占截断;否则,您可能会得到一些不正确的、有偏见的结果。

时间相关偏差

背景

我想回顾一下生存分析中一种更常见的偏见。这种偏差在您的数据中可能以不同的形式表现出来,但本质上是当一个时间相关的暴露(一个您期望随时间变化的暴露)被错误地分析为一个不变的基线协变量时。这种偏差也被称为不朽时间偏差幸存者治疗选择偏差。让我用一个玩具例子来演示一下。在这个例子中,假设我们对一个叫做治疗 a 的暴露感兴趣。

x 表示一个事件

在这个假设的研究中,治疗 A 仅在时间 30 分配。不言而喻,活不到时间 30 的患者将无法接受治疗 A。然而,对于那些接受治疗的患者来说,将患者归类为在时间 30 之前接受治疗 A *将是一个错误,因为这必然会使结果偏向于研究中的暴露(如治疗),因为暴露组获得了虚假的生存优势。从概念上讲,只有当一个人实际受到暴露时,我们才应将人-时间分类为暴露。*

r 使用真实数据进行演示

处理时间相关偏差的分析方法与处理长度偏差的方法非常相似,但是两种偏差是不同的。时间依赖偏差从根本上说是一种信息误分类偏差,而长度偏差从根本上说是一种选择偏差。

让我们先来看看我们正在处理的数据:

cgd <- survival::cgd0
head(cgd %>% select(id, treat, futime, etime1:etime7))id treat futime etime1 etime2 etime3 etime4 etime5 etime6 etime7
1     1    414    219    373     NA     NA     NA     NA     NA
2     0    439      8     26    152    241    249    322    350
3     1    382     NA     NA     NA     NA     NA     NA     NA
4     1    388     NA     NA     NA     NA     NA     NA     NA
5     0    383    246    253     NA     NA     NA     NA     NA
6     1    364     NA     NA     NA     NA     NA     NA     NA

慢性肉芽肿病(CGD)是一组不常见的遗传性疾病,以反复感染为特征,通常在生命早期开始,并可能导致儿童期死亡。在 1986 年,基因泰克公司进行了一项随机、双盲、安慰剂对照试验,其中 128 名 CGD 患者在一年(treatment)内每天三次接受试验药物或安慰剂。收集了所有严重感染的数据,直到随访结束futime,对于大多数患者来说,这发生在第 400 天之前。etime代表患者感染的日期。例如,患者#1 在第 219 天和第 373 天有 2 次感染。研究的问题是这种治疗对与感染相关的存活率是否有影响。

我们需要更改这个数据集,以便每行的每个感染之间有时间间隔。下面的代码不是最漂亮的,但是它用survival::tmerge()完成了工作。有关tmerge正在做什么的更多信息,请参见本文第页。

newcgd <- tmerge(cgd %>% select(-starts_with("etime")), cgd, id=id, tstop=futime,
                 infect = event(etime1), infect= event(etime2),
                 infect = event(etime3), infect= event(etime4),
                 infect = event(etime5), infect= event(etime6),
                 infect = event(etime7))
newcgd <- tmerge(newcgd, newcgd, id=id, enum=cumtdc(tstart))head(newcgd %>% select(id, treat, infect, futime, tstart, tstop, enum))id treat infect futime tstart tstop enum
1     1      1    414      0   219    1
1     1      1    414    219   373    2
1     1      0    414    373   414    3
2     0      1    439      0     8    1
2     0      1    439      8    26    2
2     0      1    439     26   152    3

如果我们忽略与时间相关的偏差,这意味着将治疗视为非时变的,我们将得到如下错误结果:

coxph(Surv(futime, infect) ~ treat + cluster(id), newcgd) %>%
  broom::tidy(exponentiate = T)# A tibble: 1 x 6
  term  estimate std.error robust.se statistic p.value
  <chr>    <dbl>     <dbl>     <dbl>     <dbl>   <dbl>
1 treat    0.578     0.266     0.349     -1.57   0.117

为了说明这种偏差,我们使用了一种类似的Surv方法,通过指定两个时间点来说明左侧截断偏差。

coxph(Surv(tstart, tstop, infect) ~ treat + cluster(id), newcgd) %>% 
  broom::tidy(exponentiate = T)# A tibble: 1 x 6
  term  estimate std.error robust.se statistic  p.value
  <chr>    <dbl>     <dbl>     <dbl>     <dbl>    <dbl>
1 treat    0.334     0.261     0.312     -3.51 0.000446

我们可以看到,不考虑时间依赖性偏倚低估了风险比,在这种情况下,治疗对感染率没有显著影响。然而,实际上,治疗确实对感染率有显著影响,接受治疗的人感染的可能性是没有接受治疗的人的 0.3 倍。

关于这一点的更深入的解释,请参见这篇文章

始终考虑时间相关偏差;否则,你可能会低估暴露患者的风险,高估未暴露患者的风险。

总结想法

观察性研究中的生存分析非常普遍,需要很好地理解这些偏差,以减少错误的结论。

我将以从技术角度后退一步来结束我的演讲。理解是一种光谱。我很难接受面试结果,因为我想了很久,这意味着我根本不懂生存分析。那根本不是真的。总有更深更复杂的东西需要理解。在生存分析的情况下,我相信许多人能够告诉你它是什么,但是更深入的理解最终是你的研究与其他人的区别。熟能生巧,努力学习并投入时间会对这门学科有更严格的掌握。我想我想说的是:如果你想在生活中真正推进一个领域,一个话题或任何东西,不要放弃,继续学习!

自我监督学习在现实世界中表现如何?

原文:https://towardsdatascience.com/how-well-does-self-supervised-learning-perform-in-the-real-world-ece18b2d45f6?source=collection_archive---------26-----------------------

在随机互联网图像而不是 ImageNet 上预先训练模型

如果你一直在阅读最近关于自我监督预培训的出版物,你可能会注意到所有的新方法和技术大多是在 ImageNet 上评估的。ImageNet 数据集高度多样化,规模庞大,包含大量的类。它是专门为评估图像处理模型的性能而策划的,因此它无疑非常适合这项任务。但是相对来说,很少有人强调这些自我监督技术在其他图像数据集上的表现。未切割且包含大量随机影像的数据集。在他们的论文“野外视觉特征的自我监督预训练”中,Goyal 等人着手调查当在一组随机、未切割的图像上进行训练时,自我监督预训练技术的感知性能是否成立

此图显示本文的主要模型 SEER 优于所有其他架构。来源:【1】

先决条件

本文中介绍的 SEER 模型结合了计算机视觉的多项最新进展。

首先,它利用了一个新颖且可扩展的架构,名为 RegNet 。RegNet 由量化的线性函数定义,以形成具有最佳宽度和深度的多个块的网络。RegNet 有两种变体:RegNetX 使用传统 ResNet 的剩余块,RegNetY 利用挤压和激励块。我写了一整篇关于 RegNet 架构的文章,可以在这里随意阅读。

RegNet 各部分的图解。它由茎、体和头组成,如(a)所示。插图(b)和(c)更详细地展示了各个阶段和模块。来源:【2】

SEER 论文的另一个重要组成部分是一种自我监督的预训练技术,称为 SwAV 。这种技术用于 SEER 模型和进行比较。 SwaV 使用数据增强来形成同一图像的多个不同版本。这些然后通过卷积神经网络创建一个潜在的表示。然后,通过公式化交换预测问题,该向量被学习分配给 K 个原型向量之一。如果你想更新你在 SwAV 上的知识,请在这里随意阅读我在报纸上的故事。

SwAV 训练过程的图解。来源:【3】

最后,SEER 论文比较了它与另一种自我监督预训练技术 SimCLR 的性能。SimCLR 就像 SwAV 一样,使用数据增强来形成同一图像的增强版本对。这些然后被传递到一个卷积神经网络,形成一个特征向量。然后,这个矢量进入 MLP,形成最终的网络输出。SimCLR 使用了一种叫做 NT-Xent 的新型损失函数,它寻求吸引同一物体的不同表示。同样,如果你想更深入地了解 SimCLR,我在报纸上有一篇文章,你可以在这里阅读

显示 SimCLR 训练过程的图。来源:【4】

开发可受益于大型未切割图像数据集的模型

现在来看这篇论文的主要贡献。如前所述,本文的一个主要目标是找出一个大的、未切割的图像数据集将如何影响自监督方法的性能。此外,作者旨在开发一种方法,以超越其他当前最先进的技术。

为了实现这一点,他们使用 SwAV 技术来定义预训练流程。更具体地说,他们创建了分辨率为 2 x 224 和 4 x 96 的图像对,并将许多不同的数据放大传递到模型中。他们还定义 SwAV 具有 16K 原型向量,这是为该技术设置的一个重要的超参数。

对于模型架构,他们选择了前面提到的 RegNet ,具体来说,他们试验了一系列网络,即使用前面提到的挤压和激励模块RegNetY-{8,16,32,64,128,256}GF 。只有 RegNet 架构的巨大灵活性才能实现这种规格范围。在这个 RegNet 之上,他们定义了一个 3 层 MLP 投影头,以形成一个 256 维的输出向量

“SEER 将最近的架构家族 RegNet 与在线自我监督训练相结合,以在数十亿张随机图像上对数十亿个参数进行预训练。”。来源:【5】

整个 SEER 模型(SwAV with RegNet)是在多个不同的数据集上训练的,我们将在“结果”部分获得这些数据集,其中最值得注意的是来自 Instagram 的 10 亿张未切割图像。为了训练模型,作者使用了令人惊叹的512 NVIDIA V100 32GB GPU并训练了 122K 次迭代。现在,让我们看看 SEER 模型如何针对其他技术和不同的数据集进行测量。

结果

这里有很多东西要打开。让我们从自我监督学习模型的经典评估开始。

在不同数据集上进行预训练并在 ImageNet 上进行微调时,不同自我监督预训练方法的结果表。来源:【1】

作为第一个实验的一部分, SEER 在 Instagram 的 10 亿张随机图片上进行了预训练,然后在 ImageNet 上进行微调。令人难以置信的是, SEER 能够在 ImageNet top-1 精度上胜过所有其他方法。值得注意的是,它可以胜过原始的 SwAV 论文,即使它使用了自我监督的预训练技术,只是使用了不同的网络架构。此外,它的性能优于 SimCLRv2 模型,后者的参数比它的前身更大。顶级精度和参数数量之间似乎也有关联:模型越大,性能越好。有趣的是,SEER 优于所有其他方法,尽管它是唯一一种在随机图像上预先训练的方法。SimCLRv2 甚至在 ImageNet 上进行了预训练,后来用于评估。

一个显示低镜头学习场景结果的表格。来源:【1】

作者还定义了一个所谓的低镜头学习场景,即在预训练后,仅使用 ImageNet 数据集的 1%或 10%对模型进行微调(相比之下,第一次评估为 100%)。虽然 SimCLRv2 似乎是性能最好的模型,但由于在 ImageNet 上进行了预训练, SEER 尽管之前没有见过 ImageNet 中的任何图像(在随机图像上进行了预训练),但其性能几乎可以与之匹敌。这再次表明,SEER 能够学习足够多的关于它在预训练期间所看到的视觉世界的知识,以将其知识足够好地转移到 ImageNet 分类任务。

显示正则分类精度与模型中参数数量关系的图表。来源:【1】

另一个与论文高度相关的发现是,随着 RegNet 中参数数量的增加,预训练模型相对于从头开始训练的 RegNet 的优势显著增加。换句话说,如果您正在训练一个非常大的模型,那么与较小的模型相比,它更有可能受益于(自我监督的)预训练。

该表显示了使用 SEER 对下游任务(如对象检测和语义分割)进行预训练的性能。来源:【1】

最后,让我们看看 SEER 对下游任务的影响。作者还在 MS COCO 数据集上使用预训练的 RegNet 主干训练了一个 Mask R-CNN,用于对象检测和语义分割。他们表明,与使用标签从零开始训练模型相比,使用 SEER RegNet 主干的模型在随机互联网图像上预先训练,导致两个下游任务的性能提高。

包装它

在本文中,您了解了 SEER,以及自我监督的预训练即使不与精选数据集结合使用也是有效的。这一点的含义相当深远:我们可能离图像模型的完全无监督训练更近了一步。虽然我希望这个故事让你对这篇论文有了一个很好的初步了解,但仍然有很多东西需要发现,特别是在结果和消融研究方面。因此,我会鼓励你自己阅读这篇论文,即使你是这个领域的新手。你必须从某个地方开始;)

如果你对论文中介绍的方法有更多的细节感兴趣,请随时在 Twitter 上给我留言,我的账户链接在我的媒体简介上。

我希望你喜欢这篇论文的解释。如果你对这篇文章有任何意见,或者如果你看到任何错误,请随时留下评论。

最后但同样重要的是,如果你想在高级计算机视觉领域更深入地探索,考虑成为我的追随者。我试着每周发一篇文章,让你和其他人了解计算机视觉研究的最新进展。

参考资料:

[1] Goyal,Priya 等人,“野外视觉特征的自我监督预训练” arXiv 预印本 arXiv:2103.01988 (2021)。【https://arxiv.org/pdf/2103.01988.pdf

[2] Radosavovic,Ilija 等人,“设计网络设计空间”IEEE/CVF 计算机视觉和模式识别会议文集。2020.https://arxiv.org/pdf/2003.13678.pdf

[3]卡隆、玛蒂尔德等人,“通过对比聚类分配对视觉特征进行无监督学习。” arXiv 预印本 arXiv:2006.09882 (2020)。https://arxiv.org/pdf/2006.09882.pdf

[4]陈,丁等:“视觉表征对比学习的一个简单框架。”机器学习国际会议。PMLR,2020 年。https://arxiv.org/pdf/2002.05709.pdf

[5]脸书人工智能研究博客文章:SEER:计算机视觉一个更强大、更灵活、更容易进入的时代的开始。https://ai . Facebook . com/blog/seer-the-start-of-a-more-powerful-flexible-and-access-era-for-computer-vision/

批发商如何利用基于人工智能的 ERP

原文:https://towardsdatascience.com/how-wholesalers-can-capitalize-on-ai-based-erps-5cbf66db7201?source=collection_archive---------29-----------------------

了解配备人工智能的批发 ERP 如何提高业务效率

照片由老虎百合派克斯拍摄

企业资源规划系统(ERP)是整合从采购到会计再到客户服务等跨部门运营数据的平台,为企业决策者提供单一的信息来源。ERP 起源于 20 世纪 60 年代的制造业,逐渐成为整个商业世界的基本要素。

批发行业是历史上为数不多的依靠企业资源规划系统实现实时工作流可见性和全面报告的行业之一。但是,作为如此热情的 ERP 采用者,分销商现在却意外地不愿意将他们的遗留系统升级,因为高昂的成本和具有挑战性的实施使他们望而却步。

虽然可以理解,但他们的担忧在今天是不合理的,因为许多以前的尖端技术已经进入主流,它们的使用成为行业的新常态。

在这方面,人工智能似乎是大规模 ERP 的最合适的增强。人工智能可以简化繁琐的手动任务,并根据历史数据提供见解,但它的实施不一定需要重大的基础设施改革。更重要的是,许多 ERP 套件都提供了开箱即用的人工智能功能,或者可以由一家 ERP 开发公司从头开始构建。

为了给人工智能驱动的 ERP 提供一个令人信服的案例,我们概述了四个使用案例,在这些案例中,该技术可以完成繁重的工作,并使批发公司受益匪浅。

简化数据输入

ERP 作为公司唯一的真实信息来源,天生适合从各种系统收集数据。但就批发而言,并不是所有的数据源都是数字的,因为许多公司依赖于基于纸张的工作流程。因此,提货单、货运清单和其他文档中的手写信息必须手工输入到 ERP 中,这一过程不仅耗时,而且很有可能出现人为错误。

拥有一个具有人工智能驱动的光学字符识别功能(OCR)的 ERP,您可以消除手动数据输入的需要。使用移动 ERP 应用程序,现场或案头工作人员扫描文档,以便 OCR 技术可以提取手写和印刷文本,将其数字化,并将数据分类到适当的电子表格或 ERP 中的存储位置以供进一步使用。

为了安全起见,你仍然需要仔细检查 OCR 扫描的数据,以验证它是正确的,没有丢失任何东西,但这比手工输入信息需要的时间和精力要少得多。

今天,像 Odoo、Acumatica 和 Oracle 这样的领先供应商拥有官方或社区开发的 OCR 模块,可以很容易地安装到 ERP 系统中。

准确的库存预测

对于批发商来说,库存规划是一个重要的过程,存储成本、利润率和合同履行都取决于其准确性。传统的 ERP 通过需求和销售报告以及以前时期的其他相关数据来促进预测。但在当今需求波动和市场不确定性的情况下,历史预测方法被证明是不够的,并可能损害批发商的盈利能力。

被迫寻找更好的解决方案,批发商越来越多地转向人工智能。2021 年 MHI 年度行业报告发现,31%的零售商已经在供应链管理中依赖人工智能驱动的预测分析,五年内采用率将达到 79%。

积累不同的历史数据集,并已经配备了报告功能,ERP 证明是人工智能分析引擎的最佳位置。在人类需要的一小部分时间内,机器学习算法将分析来自 ERP 的历史和实时数据,并考虑影响需求的动态外部因素。完成后,该解决方案提供了关于消费者需求的准确预测,以及满足需求的充足库存种类和数量。

ERP 供应商 Oracle 目前处于人工智能库存管理的前沿,提供了一种可以与其套件集成的专用云应用程序,而其他供应商也在积极开发自己的类似功能。

配送路线优化

对于拥有车队的批发商来说,他们正在努力实现快速高效的交付,但并不总是成功的。当手动建立新路线时,车队经理必须考虑来自 ERP 的车辆和驾驶员数据,从里程表读数到事故历史,并将其与 GPS 系统的见解进行匹配,以检测车辆位置和目的地,同时检查地图和天气预报。可用的基于规则的路线规划工具可以简化这一艰巨的任务,但如果不进行手动重新配置,则不够灵活,无法考虑不断变化的需求和细微差别。

人工智能驱动的 ERP 可以进行路线规划,并帮助公司满足最后期限,节省燃料,旅行时间和车队经理的努力。专用的人工智能引擎可以处理历史 ERP 数据、关于车辆和驾驶员的实际信息以及关于天气和交通的实时见解,并无缝规划最佳路线,而无需员工参与重新配置或数据聚合。

除此之外,AI 可以持续扫描系统,以发现修改的交付要求或路上不可预见的停机时间,动态地重新优化路线和预计到达时间,并通过移动 ERP 应用程序通知司机有关变化。

财务管理自动化

ERP 是批发公司的重要会计工具,它收集来自各个部门的财务数据。但是,除了生成详细的报告之外,传统的 ERP 套件对陷入基于纸张的流程和人工预测的财务专家几乎没有什么帮助。

与此同时,人工智能成为金融管理领域的游戏规则改变者,不仅能够更快、无误地执行任务,还能提供更准确、更可靠的金融预测。根据甲骨文的《金钱与机器:2021 年全球研究》 , 77%的商业领袖承认,在财务相关任务上,他们更信任机器人而不是他们的会计团队。

看到这一机会,Oracle、Acumatica 和其他 ERP 提供商今天将人工智能驱动的财务管理功能构建到他们的软件套件中,或者作为模块单独发布。这些人工智能功能可以在大大小小的事情上帮助员工:从数据输入、交易输入和采购订单批准到加快月底结算和账户对账。除此之外,人工智能分析引擎可以提供准确的现金流预测,检测财务记录中的差异,并为财务健康改善提供可行的策略。

是时候让您的 ERP 智能化了

在现代快节奏的市场中,卓越运营和快速决策成为批发商的主要竞争优势。为您的 ERP 配备人工智能和预测分析功能,公司可以自动化数据输入等手动日常操作,并显著简化路线规划或库存预测等更加智能、繁琐的任务,巩固他们在竞争对手中的地位。

波士顿低收入社区的发展将如何影响氮氧化物水平?

原文:https://towardsdatascience.com/how-will-developing-low-income-neighbourhoods-in-boston-affect-nox-levels-af5288b3c9ab?source=collection_archive---------37-----------------------

一篇小说对波士顿住房市场数据集的分析

来自 Unsplash 的 Cameron Venti 的照片(来源

行动纲要

波士顿住房市场数据集无处不在,但并不完美:存在规模小、定义不一致和坐标不正确等问题。然而,它仍然是一个非常丰富的数据集,包含丰富的地理信息、强大的社会经济指标和连续的氮氧化物(NOx)水平。这个项目探索了发展低收入社区对氮氧化物的影响。该项目在 24 小时 AI Hack 2021 中获得一等奖。下面的链接是为那些有兴趣深入分析的人准备的。

项目网站

项目库

团队博客

目的和目标

这个项目的目的是在波士顿住房数据集中探索新的途径。数据集的典型项目侧重于回归或聚类。虽然两者都很有趣,但我们的目标是回答一个可以直接导致政策建议的研究问题。

这是通过 3 个目标实现的:

  1. 验证数据集是否能提供足够的信息来解决研究问题:我们的问题提出了一个重要的假设,即数据足够丰富,可以根据收入来区分城镇。成功标准:找到可与外部文献相媲美的集群。
  2. 寻找预测氮氧化物水平的最佳模型:该项目包括寻找预测氮氧化物水平的回归模型,以及为此选择最佳回归变量。成功标准:找到给出高精度和正态分布残差的模型。
  3. 模拟低收入城镇的‘发展’:这意味着一个城镇被‘发展’了?是否有任何参数受到限制,例如地理位置?有没有可以通过政策建议改变的社会经济参数?成功标准:找到一种合理的方式来模拟低收入城镇的“发展”。

数据处理和特征提取

我们的第一步是使用 pandas_profiling 库可视化地探索数据。这使我们能够从连续变量、顺序变量和分类变量的角度快速理解数据。

我们总结出有两种类型的特征:

  • 地理信息数据:这包括 DIS (离就业中心的距离)和 RAD (道路指数)等。
  • 社会经济指标:例如包括年龄(平均房龄)和 CMEDV (房价)。

我们注意到一些变量,如 CHAS ,因此将它们排除在任何分析之外。

我们在叶子上绘制了每个住所,在那里我们意识到纬度和经度是错误的。使用 Goolge 的 geocoder API 修复了这些问题(此处的描述了方法学)。

方法的主要方面

目标 1:验证我们的数据集足够丰富

为了验证我们的数据集包含足够的信息来回答研究问题,我们必须找到一种方法来根据收入对城镇进行聚类,并将我们的结果与文献进行比较。由于我们关心 3 个集群:低、中、高收入城镇,我们选择简单的 K-means 算法作为城镇集群的起点。结果实际上足够代表文献(见我们的报告第 11 页),所以我们觉得没有必要寻找更复杂的聚类方法。住所如下图 1 所示。

图 1:按收入分类的波士顿住宅。红色→低,橙色→中,黄色→高

我们选择了以下 4 个预测变量作为 K-means 的特征,这是基于我们对它们在聚类中的信息量的理解,以及我们对相关系数的读取。

  1. CMEDV——以千美元为单位的自有住房修正中值的数字向量
  2. INDUS —每个城镇的非零售商业英亩数比例的数字向量(对于所有波士顿区域都是常数)
  3. 年龄—1940 年之前建造的自有住房比例的数字向量
  4. LSTAT —较低地位人群百分比值的数值向量

在进行任何缩放之前, LSTAT 是高度倾斜的,并且包含许多异常值。我们编写了一个优化器,它根据变换后分布的峰度偏斜度来确定数据的理想变换(和归一化)函数。下面的图 2 显示了进行转换后我们所选特性的分布和箱线图。

图 2:标准化和转换后我们的预测变量的分布

目标 2:建立回归模型,准确预测氮氧化物水平

由于氮氧化物的输出是连续的,回归模型被认为是合适的。除了用于聚类的 4 个预测值,我们还选择了另外一个预测值, CRIM (给定城镇的犯罪指标),因为它与 NOx 排放相关。我们的目标变量当然是氮氧化物排放量。

我们从一个简单的回归模型作为基准开始,然后使用不同的模型对此进行改进。下面的流程图给出了我们的方法。

图 3:我们获得最佳回归模型的方法流程图

最好的模型是支持向量回归机。这是预料之中的,因为支持向量机可以:a)捕获非线性行为,而且 b)从顺序和分类变量中捕获信息。由于我们的预测指标之一 RAD 实际上是一个有序指数,依赖于“距离”的正常回归模型是不合适的,而 SVR 可以很好地捕捉这一信息。

除了 SVR 和标准线性回归,还使用了基于岭、套索和神经网络的回归。后两者表现相当差。在 Lasso 回归的情况下,这是预料之中的,但是神经网络的结果却相当令人惊讶。然而,由于比赛期间的时间限制,神经网络没有进一步优化,因为 SVR 获得的 R2 分数(和模型简单性)被认为是足够的。

下表 1 总结了前 3 种模型。

表 1:前 3 种型号汇总

下面的图 4 显示了相对于 4/5 回归的真实数据绘制的 SVR 的预测输出(顺序预测器 RAD 被省略)。

图 4:原始数据和预测数据的输出变量 NOx 相对于 4/5 预测变量的曲线图

为了验证我们的回归模型正确工作,我们决定在 QQ 图上绘制残差,以验证我们的正态假设。这显示在下面的图 5 中。

图 5:来自 SVR 的 y_hat 残差的 QQ 图

我们还使用了部分相关法(有关这方面的更多信息,请参考我们的报告第 14 页)来测量不同预测因素对 NOx 水平的影响,同时保持其他所有因素不变。我们只对衡量社会经济指标变化时的差异感兴趣(因为这些指标通过政策是可变的,而地理参数是固定的)。因此,我们只研究了年龄卷曲的影响。结果如下图 6 所示。

图 6:两个非地理回归变量的部分差异图

目标 3:模拟低收入城镇的发展

为了回答我们的研究问题,“波士顿低收入城镇的发展将如何影响氮氧化物水平?”我们需要定义一个衡量发展的标准。为此,我们利用了这样一个事实,即我们选择的特征可以分为地理上的和非地理上的约束。

在我们的例子中,我们注意到年龄卷曲是唯一不受地理限制的特征。这意味着,当谈到政策建议时,我们可以建议翻新房屋,或推动减少犯罪的政策。有了我们的其他预测指标,即 DISINDUSRAD ,我们不可能在不引起根本性变化的情况下提出政策建议。例如:

  • 改变 DIS 或 INUDS 意味着迁移/关闭就业中心和工业区,这将产生重大的经济影响
  • 改变 RAD 标志着波士顿道路系统的彻底改变,这将再次产生重大影响

因此,我们将这些称为地理限制特征,因为改变它们需要对城市进行彻底的重新规划。

将我们的数据分成这两类后,我们可以通过替换来自高收入社区的非地理约束特征来模拟低收入社区的发展。

这意味着,对于我们低收入城镇中的每一处住宅,我们用从基于高收入城镇的自举分布中抽取的样本来替换年龄犯罪预测值。然后,我们将新的“开发”数据点输入到氮氧化物回归模型中,以预测新的氮氧化物值。

其结果如下图 7 所示:

图 7:(左)开发后的低收入住宅,其中颜色表示氮氧化物水平的强度(红色→高,黄色→低)和(右)未开发的低收入城镇(原始数据集)

差异是明显的:这一分析的结果表明,有一个激励提高低收入城镇,因为它可能会降低氮氧化物的水平。这甚至为推行这一倡议提供了非人道的理由。下图 8 显示了中高收入地区通过自助提升低收入社区对分配的影响。似乎分布的峰值保持不变,变化很小,但是数据更加向左分散,导致总体正偏斜。

图 8:3 个数据集和直方图(左)的箱线图(右)

讨论和政策建议

部分依赖分析的结果(见图 6)既有趣又令人困惑。楼龄的影响大多是合乎逻辑的,即房屋楼龄的增加将表明供暖基础设施的老化,从而减少氮氧化物的排放。然而, CRIM 的说法令人困惑,因为它似乎表明,在其他条件相同的情况下,犯罪率的上升会增加氮氧化物的含量。如果不检查其他依赖性,很难相信这个概念。

其他推荐方面: INDUS 对 NOx 解释的比较多。对政府的一个建议可能是鼓励工业迁出城市,并在更多的农村地区(相对于城市中心)建设,因为这既影响拥堵,也影响总体污染密度。然而,需要做更多的研究来确定这对低收入社区的社会经济影响,因为许多居民可能因此失去工作。

然而,值得注意的是,数据集存在问题,影响了这项研究的有效性。例如,地理参数 CHAS 对任何事物都没有影响,而直觉上人们会这样认为,文献似乎也是这样建议的。另一个值得注意的有趣的事情是,该数据集相当薄…许多富裕的社区位于城市的郊区。虽然这似乎与文献一致,但数据集有不平衡的类。

根据模型和现有的在线阈值来观察一些概率是很有趣的。根据在线标准,加州的最大氮氧化物水平(每 1000 万份中的含量)为 0.3,联邦政府将上限设定为 0.53。如果将加州的限值作为低 NOx 的阈值,而将政府的限值作为高 NOx 的阈值,这意味着 52%的数据集具有过高的 NOx 水平,而实际上没有一个是低的。关于这种差异的另一个有趣的见解是……给定一个低收入社区,氮氧化物等级高的概率是 96.6%。下表很好地总结了这些信息:

表 2:相对于中低收入和高收入城镇,低、中和高氮氧化物水平的比例(基于在线标准)

结束语和进一步的工作

该项目的目标是探索低收入社区的发展如何影响氮氧化物水平,以便为政策制定提供见解。这个目标分为三个逻辑步骤:1)确定数据集是否足以完成手头的任务,2)找到一个模型来预测任何数据点的 NOx 水平,3)确定发展低收入社区的影响,同时保持地理限制不变。为了验证数据集的充分性,使用 K-means 聚类来寻找 3 个不同的聚类(对应于低、中、高收入社区)。这一结果与显示类似分布的过去数据进行了验证,这意味着数据足够好,可以合理地将社区分为三类。

项目的第二个方面应用回归技术,使用 5 个回归量来确定 NOx 排放量,即年龄DISINDUSCRIMRAD 。这方面发现 SVR 是最好的预测器,给出了 88%的准确度。残差的正态性通过 QQ 图进行验证,然后允许创建高收入邻里数据点的自举样本。保持地理位置固定(即 INDUSDISRAD ),来自低收入社区数据集的可改善数据被来自高收入社区的数据取代(即 AGECRIM )。发现这导致 NOx 水平的总体降低。统计结果表明,低收入居民区的氮氧化物分布不会改变其峰值。但是它的周围分散在左边,随着开发的增加,导致整体的正向倾斜。根据研究,似乎气候和年龄是氮氧化物污染的强有力的人为可变指标。证据表明,改善低收入社区与降低氮氧化物值相关。

未来的工作最好考虑以下几点:1) 因果关系:您能否探索一下年龄 / 卷曲是否可以被认为是原因,2) 数据扩充:这项工作在扩充经度和纬度以及为“发达”低收入社区创建合成数据方面做了很多工作,未来的方法可以考虑使用神经网络驱动的数据扩充技术(如 GANs)。

我希望你喜欢阅读这篇文章(并希望学到一些新东西!),并鼓励你总是渴望在你从事的项目中探索新的途径,即使看起来好像一切都已经被探索过了。

除非另有说明,所有图片均由作者创作。

希望 A/B 如何测试百分点

原文:https://towardsdatascience.com/how-wish-a-b-tests-percentiles-35ee3e4589e7?source=collection_archive---------14-----------------------

大规模在线实验中百分点差异的检测方法研究

投稿人:戚克(Max)李&

图片由 Gerd AltmannPixabay 拍摄

在本文中,我们分享了我们为百分位数开发 A/B 测试方法的旅程。您将看到示例用例、为什么 A/B 测试百分比指标具有挑战性、看似简单的解决方案如何失败、我们最终使用的统计测试以及测试的性能。

愿望时,我们 A/B 测试几乎所有的新产品特性以确保它们增强用户体验。在每个实验中,我们对许多指标进行假设检验,其中一些指标是[百分位](https://en.wikipedia.org/wiki/Percentile#:~:text=In statistics%2C a percentile (or,percentage falls (inclusive definition).),如 P50(第五十百分位或中值)或 P95(第九十五百分位)。当测试来自两个实验组的两个百分位数的差异时(例如,对照组的 P95 与治疗组的 P95),典型的假设检验方法,例如 t 检验,并不适用,因为这些检验比较的是两个样本的平均值,而不是百分位数。

示例使用案例

百分比 A/B 测试使我们能够衡量新产品功能对网站性能的影响。网站性能极大地影响了用户体验,并产生了实实在在的金钱效应。亚马逊发现仅仅 100 毫秒的额外加载时间就让他们损失了 1%的销售额。 Pinterest 减少了 40%的等待时间,这使得搜索引擎流量和注册人数增加了 15%。

照片由 CHUTTERSNAPUnsplash 上拍摄

百分位数,如 P50(第五十个百分位数)或 P95(第九十五个百分位数),是比样本均值更好的网站绩效指标。例如,对于所有用户,产品 A 在 0.5 秒内加载,对于 95%的用户,产品 B 在 0 秒内加载,对于 5%的用户,在 10 秒内加载。尽管两种产品的平均加载时间相同,但产品 A 的用户体验要好得多。产品 A 在瞬间为所有用户加载。相比之下,5%的用户似乎永远都无法加载产品 B,糟糕的体验可能会鼓励这些用户流失。在整篇文章中,我们关注的是百分比测试在性能度量中的应用。

除了性能指标之外,当我们关心对指标分布的影响时,百分位数测试开启了许多其他的应用。例如,百分比测试对于事务度量也是非常宝贵的。Wish 致力于提供一个公平的市场,为各种规模的商家发展业务。因此,当我们改变政策时,我们的目标是提高所有商家的销售额。因此,在 A/B 测试控制和展示时段之间的平均销售额时,我们还需要比较 P10、P50 和 P90 等百分点,以确保该政策不会通过严重偏袒少数顶级商家来提高平台销售额,这可能会使小型商家处于不利地位。

测试百分位数的挑战

A/B 测试绩效指标的百分比差异具有挑战性,原因如下:

  • 挑战一:随机化单元。大多数实验平台随机选择用户,这保证了用户之间的独立性。但是性能指标是在响应级别测量的,来自相同用户的响应时间可能是相关的,这违反了大多数统计测试的独立性假设,并且可能产生很高的误报率。这通常被称为随机化单元和分析单元【1】之间的差异。
  • 挑战二:可扩展性。该方法需要具有足够的可扩展性,以便在可接受的时间框架内从数十亿行输入数据中进行假设检验。

我们首先探索简单的解决方案

我们能否设置一个固定的阈值来检测性能变化?

是否足以检查治疗组和对照组之间的差异是否高于固定阈值,例如 100 毫秒的差异或 10%的相对变化?例如,如果处理桶中的 P95 比控制桶中的 P95 高 100ms,或者处理桶中的 P95 比控制桶中的 P95 高 10%,则我们得出结论:产品特性引入了延迟。

为了查看使用固定阈值是否合适,我们回顾性地进行了几次模拟/模拟实验,发现固定绝对变化和固定相对变化都不起作用。注:对于这些 A/A 实验,显示和控制之间的任何差异都不是真正的差异,而是由于自然波动。

我们研究了各种原料药在治疗组和对照组之间的 P95 差异。由于以下原因,使用固定阈值是不可靠的。

  • 一个 API 可能比另一个慢两个数量级。对于一个 API 来说,10 ms 的差异无疑是性能下降,但对于另一个 API 来说,这可能是由于自然波动造成的。
  • 当我们观察较少使用的 API 的延迟时,样本百分比变化可能相当大。例如,样本百分位数中 10%的差异可能来自自然变异。然而,对于大量使用的原料药,P95 增加 10%可能表明性能显著下降。

与统计测试相反,固定阈值不考虑样本差异(即某些 API 的响应时间比其他 API 的响应时间更易变),因此,不能保证良好控制的I 型错误率(假阳性率)。

可以应用比例 Z 检验吗?

双样本比例 Z 检验允许我们比较两个比例,以查看两个比例之间的差异是否显著。当两个实验组的两个 P95 之间确实存在显著差异时,合并的 P95(来自对照和处理的组合数据的 P95)之上的样品比例将存在显著差异。为了说明,假设治疗组、对照组和混合组中的 P95 潜伏期分别为 300 毫秒、100 毫秒和 200 毫秒。假设两组大小相等,治疗(控制)组可能包含明显更多(更少)的 200ms 以上的数据点。为了使用此属性构建一个有意义的测试,我们将比例 Z 测试修改如下:

  • 计算合并的 P95。
  • 使用比例 Z 测试来比较响应时间高于治疗组和对照组的合并 P95 的请求的比例。

这种方法对于比较百分位数似乎是合理的。但是,不幸的是,它没有解决实验单元和分析单元之间的差异(挑战 I )。因此,我们以如下两种不同的方式模拟 A/A 检验,以研究修正的比例 Z 检验是否适用于百分位数。

  • 追溯模拟的 A/A 测试使用来自 Wish 的数据,采用两种不同的随机化:1)随机化用户(随机化 I);2)随机化请求(随机化 II )。请注意,由于这些是模拟的 A/A 测试,因此随机请求是可能的。
  • 应用修改的比例 Z 检验

如果测试工作正常,A/A 测试产生的 p 值分布应该遵循从 0 到 1 的均匀分布。并且,如果我们将显著性水平设置为 5%,我们应该会看到 p 值小于 0.05 的~5% A/A 测试。

我们发现,在用户层面进行随机化时(随机化 I ),超过 60%的 A/A 测试会导致假阳性。假阳性率很高,因为随机化单元不同于分析单元。另一方面,当在请求级别随机化时(随机化单元与分析单元相同),p 值分布相当接近均匀,并且 I 型误差得到很好的控制。

总之,如果我们可以随机化请求,这种方法将是合理的。然而,在实践中,我们的随机化是在用户级别,这使得这种方法无效。

集群自举适用吗?

为了解决随机化单元和分析单元之间的差异,我们可以应用集群引导。然而,自举是不可扩展的(挑战二),它的计算非常昂贵。自举的复杂度本质上是 O(nB) ,其中 n 是样本数 B 是自举迭代次数。考虑到 Wish 庞大的用户群,运行一个实验的集群引导需要几天时间,而且我们经常同时运行数百个实验。

虽然集群自举对于 Wish 的数据规模(或大多数其他科技公司)来说是不可扩展的,但理论上是合理的。我们可以用它作为金标准来评估样本百分位数的标准误差估计值。

Wish 溶液

我们对上述方法的探索强调,A/B 测试百分位数的方法需要解决随机化单元和分析单元之间的差异(挑战 I)并且是可扩展的(挑战 II)。

LinkedIn 在 2019 年发布的一种方法 [2]提供了一种封闭形式的分析解决方案来估计样本百分位数估计的标准误差,因此是可扩展的。它还专门解决了挑战 LinkedIn 方法中的一个步骤需要估计百分位的概率密度。对于这一步,我们发现 Quora 的方法在实践中更容易使用,并且产生了令人满意的结果。

我们采用这两种方法来估计样本百分位数的标准误差。利用样本百分位数及其标准误差,我们对零假设应用 Z 检验——来自两个实验桶(例如,对照和处理)的百分位数之间没有差异。

记号

假设我们用两个变体运行 A/B 测试,每个变体中的用户在查看产品页面时会得到不同的体验。我们的目标是检测这两种变体之间的产品页面加载时间 P95 的差异。注意,这里我们使用 P95 作为例子,我们使用这种方法来测试实践中的各种百分位数。关注一个变体,假设有:

  • n 个用户,索引为 i = 1,2,.。。,N;
  • 用户 I 查看 Pᵢ产品,其中 Pᵢ's 是独立同分布(i.i.d .)随机变量;
  • Xᵢⱼ是用户 I 的 jᵗʰ页面视图的页面加载时间。Xᵢⱼ's 可能是正相关的,因为对于使用快速网络和快速设备的用户来说,页面浏览可能都更快,反之亦然。
  • {Xᵢⱼ的样品 P95,i = 1,2,.。。,N;j = 1,2,.。。,Pᵢ}被称为 Q̂.

汇总统计数据

为了进行假设检验,我们的数据管道需要输出以下汇总统计数据:

  • 用户数量 N
  • 样品 P95 Q̂
  • ∑ᵢ Jᵢ,哪里

并且 Jᵢ是在一个桶中比用户 I 的样本 P95 低的页面加载次数。

  • ∑ᵢPᵢ,其中 Pᵢ是用户 I 的页面访问量
  • ∑ᵢ Jᵢ
  • ∑ᵢPᵢ
  • ∑ᵢJᵢPᵢ
  • P(95-δ)和 P(95+δ)。δ是可调窗口大小。假设δ=0.25,我们需要计算 P94.75 和 95.25。

请注意,所有这些汇总统计数据都是在实验桶级别聚合的,这使得数据管道更加简单。关于调整参数,我们发现= 0.25 对于像 P50 和 P95 这样的百分位数产生了令人满意的结果。当涉及到像 P99 或 P99.9 这样的极端百分位数时,可能需要更仔细的调整。

假设检验

根据汇总统计数据,样本 P95 的方差估计为

注意,我们遵循 Quora 的方法来估计分母中的密度 fₓ(Q

fₓ(Q)= 2*δ/(P(95+δ) -P(95-δ))

分子估计如下

利用样本 P95 的方差估计,我们进行 Z 检验来计算 p 值。

如果你好奇为什么我们可以这样估计样本 P95 的标准差,请参考 LinkedIn 论文中的等式 1-6。本质上,百分位等于 F⁻(百分比),其中 f 是 Xᵢⱼ的累积密度函数 (cdf),在 P95 的情况下百分比是 0.95。这个百分比是∑ᵢJᵢ和∑ᵢPᵢ.的函数另外(1/n∑ᵢJᵢ和 1/n∑ᵢPᵢ)由于中心极限定理遵循二元正态分布。应用德尔塔法两次,我们可以得出样本百分位数的分布。

数据管道

百分位数测试的数据管道与典型的 A/B 测试的数据管道有很大的不同,后者通常应用 t-test,并且只需要三个汇总统计数据:样本均值、样本方差和样本大小。此外,计算大型数据集的百分位数是缓慢且资源密集型的。因此,我们计算了近似的百分位数,这快了一个数量级,并产生了令人满意的结果。最后,由于一些汇总统计数据是十进制百分位数(例如,P94.75 和 P95.25),最小样本量需要至少大于 10,000,这远远小于期望的典型样本量。

结果

解析解产生精确的方差估计

使用聚类自举作为金标准,我们比较了由上述解析解估计的标准误差和由聚类自举估计的标准误差。这两种方法估计的标准误差在不同的客户端平台上非常接近。在超过 200 个内核和 1.5T 内存的服务器上,对于中等大小的样本,集群引导需要几个小时。如果我们使用 bootstrapping 的话,所有的实验都需要几天才能完成。相比之下,解析解的计算时间可以忽略不计。

A/A 测试中 I 类错误率得到了很好的控制

为了评估 I 型错误率,我们使用来自各种 API 调用的请求数据为不同的百分位数追溯性地构建了 A/A 测试。I 型错误率(假阳性率)接近 5%,p 值分布遵循从 0 到 1 的均匀范围。

解析解产生良好的统计功效

我们还评估了功效(真阳性率)。我们将历史请求数据随机分为 50%对照组和 50%治疗组。对于处理时段,我们将请求时间乘以 110%或 101%。即使响应时间只增加了 1%,检测差异的能力仍然相当不错。

结论

可靠的统计测试是可信实验平台的关键组成部分。对于不同的指标和不同类型的业务,没有一个通用的统计测试。我们分享我们在开发百分位数测试方面的努力,这释放了我们的实验平台的更多潜在应用。百分比测试现在应用于所有实验,希望 A/B 测试它们对 API 响应时间的延迟影响。我们设置了护栏规则来识别引入高延迟的实验,并通知实验所有者来防止引入缓慢的产品特性。

感谢

感谢高波和齐超对此项目的贡献。我们也非常感谢 Pai Liu,Shawn Song,Simla Ceyhan 的支持,以及 Pavel Kochetkov,Lance Deng,Caroline Davey,Leah Levine 对本文草稿的反馈。

Wish 的数据科学家热衷于构建一个值得信赖的实验平台。如果你对解决这个领域的挑战性问题感兴趣,我们正在招聘数据科学团队

[1] A. Deng,J. Lu,J. Litz,在线 A/B 测试的可信性分析:陷阱、挑战与解决方案 ( 2017),:第十届网络搜索与数据挖掘国际会议。英国剑桥。

[2] M. Liu,X. Sun,M. Varshney 和 Y. Xu,分位数度量的大规模在线实验 (2019), arXiv 预印本 arXiv:1903.08762

xticks 和 xticklabels 的实际工作原理:演练

原文:https://towardsdatascience.com/how-xticks-and-xticklabels-really-work-a-walkthrough-aff80755838?source=collection_archive---------7-----------------------

入门

马库斯·温克勒在 Unsplash 上拍摄的照片

我最近在 Seaborn 中创建可视化,这是基于 Matplotlib 的,当标记 x 轴时,我没有得到我期望的结果。我决定后退一步,试验一下 xticks 和 xticklabels 在可视化中实际做了什么。

我们来分解一下。

基本情节

首先,我创建了一个包含两列 100 行的 dataframe。第一列为每行分配一个从 1 到 15 的随机数,第二列为每行分配一个从 16 到 30 的随机数。

np.random.seed(0)
col1 = np.random.randint(1, 16, size=100).tolist()
col2 = np.random.randint(16, 31, size=100).tolist()
df = pd.DataFrame({'col1': col1, 'col2': col2})

使用 Seaborn 的countplot方法,我测试了第一列。

ax = sns.countplot(x = df['col1'])

作者图片

当我用len(df.loc[df['col1'] == 4])运行一个单元格时,我得到了 12,这与我的可视化相匹配。换句话说,这 100 行中的 12 行是类别 bin 4 的一部分。到目前为止,一切顺利。

让我们看看数字较高的那一栏。

ax = sns.countplot(x = df['col2'])

作者图片

结果看起来与第一个相似。标签上显示的数字是 16 到 30。

添加一些刻度

假设 x 轴上有 15 个潜在值,我有 100 个?还是 200?轴标签会变得太拥挤而难以辨认。

xticks属性的要点是只显示 x 轴上某些点的值。因此,让我们尝试使用xticks只显示三个间隔开的值。

ax = sns.countplot(x = df['col1'])
ax.set(xticks=([0, 7, 14]))

作者图片

注意在ax.set(xticks=([0, 7, 14])中,数字指的是指数。数字 1 位于xticks0索引处,然后它转到数据帧中的第 8 号索引7,然后它转到数据帧中的第 15 号索引14。但是看看 xticks 是如何数出 1,2,3而不是 1,8,15 的。

那么高计数列呢?

ax = sns.countplot(x = df['col2'])
ax.set(xticks=[0, 7, 14])

作者图片

同样,在ax.set(xticks=([0, 7, 14])中,数字指的是指数。数字 16 在xticks0索引处,然后它转到数据帧中的第 23 号索引7,然后它转到数据帧中的第 30 号索引14。沿着 y 轴的可视化值仍然很好,但是请注意 xticks 是如何数出 16,17,18而不是 16,23,30 的。

综上所述,从第一个索引的值开始计数,有意义。但是,沿着 x 轴,标签每次增加 1,而不管分类容器的值。

我应该注意,它每次只增加 1,因为我的 bin 是增加 1 的整数。我创建了一个新列, col3 ,其中有 100 个 1 到 30 之间的随机数,仅由偶数和偶数组成。

标准的情节是你所期待的:

ax = sns.countplot(x = df['col3'])

作者图片

当我选择与其他示例中相同的索引时,xticks 将按 2 计数。

ax = sns.countplot(x = df['col3'])
ax.set(xticks=[0, 7, 14])

作者图片

并且 xticks 数出 2,4,6而不是 2,16,30。

出于好奇,让我们看看如果我将 xticks 放在 dataframe 的值之外会发生什么。再次使用数字较小的列:

ax = sns.countplot(x=df['col1'])
ax.set(xticks=([0, 7, 14, 21]))

作者图片

在这个可视化中,我向 xticks 列表中添加了另一个索引21,这个索引高于引用类别 bin 值的任何索引。如您所见,它扩展了 x 轴以显示空白区域。

还有一点:尽管传递给xticks()的列表引用了索引,但是如果需要的话,您可以使用浮点数在索引之间放置记号。

指定标签

为了控制标签显示的内容,设置 ax 的xticklabels属性:

ax = sns.countplot(x=df['col1'])
ax.set(xticks=([0, 7, 14]))
ax.set(xticklabels = (['one', 'eight', 'fifteen']))

作者图片

酷毙了。我得到了我想要的结果。可以使用字符串或数字。注意,如果我没有在某个时候为 ax 设置xticks,这三个标签将被放置在前三个索引中,或者[0,1,2]。

另外,请注意,在以上所有示例中,我使用了通用的Axes.set()函数,然后传递了关键字参数。

要对记号及其标签进行更多控制,请使用Axes.set_xticks()Axes.set_xticklabels()。对于后者,您可以指定各种字体属性、标签的旋转等等。

ax = sns.countplot(x=df['col1'])
ax.set_xticks([0, 7, 14])
ax.set_xticklabels(labels = ['one', 'eight', 'fifteen'], 
                   rotation=45, 
                   fontstyle='italic', 
                   color='green')

作者图片

摘要

  • 如果不指定任何内容,所有记号都将自动放置。
  • 使用ax.set(xticks=[a, b, c])ax.set_xticks([a, b, c])选择在索引处添加记号的特定位置。
  • 如果不指定标签,第一个刻度将采用输入的第一个索引的值。然后,后续值将在分笔成交点处使用,即使它们可能不会引用其余索引处的实际值。
  • 使用ax.set(xticklabels=[a, b, c])ax.set_xticklabels([a, b, c])选择标签(字符串或数字)在设定的索引处添加记号。
  • 要控制标签的外观和文本属性,请使用带有关键字参数的set_xticklabels()

如何利用时间上下文检测部分遮挡物体

原文:https://towardsdatascience.com/how-you-can-detect-partially-occluded-objects-using-temporal-context-3db1194e7171?source=collection_archive---------15-----------------------

解决长期存在的目标检测问题

检测真实世界场景中的所有对象对于任何对象检测模型都是一项具有挑战性的任务。但是,如果您有一系列由固定位置的相机拍摄的图像,您可以利用通过多个图像获得的时间背景。在本文中,我们将回顾一篇介绍 Context R-CNN 的论文,它使用这种机制在现实世界的对象检测上实现了令人难以置信的性能,即检测遮挡、光线不佳、远处和移出图像的对象。该出版物名为“Context R-CNN:每个摄像机对象检测的长期时间上下文” ,由加州理工学院和谷歌的 Beery 等人出版。我尽量让文章简单,这样即使没有什么先验知识的读者也能理解。事不宜迟,我们开始吧!

上下文 R-CNN 对被遮挡或移出帧的对象的性能。来源:【1】

先决条件:对象检测和更快的 R-CNN

如果您已经熟悉对象检测和更快的 R-CNN 模型架构,请随意跳过这一部分。

目标检测是计算机视觉中最具挑战性的任务之一。从本质上来说,目标是训练一个模型,它既可以通过预测物体周围的边界框(上面的蓝色/绿色)来定位场景中的物体,也可以通过对物体进行分类来预测物体的类别(例如,狗、猫等)。).

最流行的对象检测架构之一被称为更快的 R-CNN。不要进入太多的细节,快速介绍模型的主要概念是有意义的,因为它们与理解 R-CNN 文章的上下文相关。

通过可视化其关键概念来显示更快的 R-CNN 模型架构。来源:【2】

速度更快的 R-CNN 使用卷积骨干从图像中提取特征。这可以通过任何类型的 ConvNet 实现,例如 ResNet-50 或 AlexNet。该主干输出包含图像所有特征的特征图。现在重要的部分来了:这些特征被传递到一个区域提议网络(RPN) ,在那里模型检测它预测包含它被训练的对象的区域。区域是由包含对象的边界框标记的区域。然后,在 RoI(感兴趣区域)汇集步骤中,将区域提议与特征图汇集在一起,然后传递给分类器,最终输出边界框和预测类

利用时间上下文检测难以看见的物体

现在,让我们继续讨论 R-CNN 的背景。通常,对象检测模型对单帧输入进行操作,即,它们仅使用来自一个图像的信息来进行预测。这就是上下文 R-CNN 的不同之处。

上下文 R-CNN 的高级架构,具有窗口滑块、短期和长期记忆库。来源:【1】

让我们来分解整个架构:作为输入,使用来自不同时间的同一场景的多个帧。其中一帧(蓝色)是我们想要对其执行对象检测的图像。例如,该窗口可以设置为 5,则 5 幅图像将作为输入。也许第一张是在早上 5 点拍的,最后一张是在下午 3 点。对于这些图像中的每一个,特征由更快的 R-CNN 提取,以生成每个盒子的 RPN 特征(这就是为什么我们之前重新访问了 RPN)。因此,现在我们有了每个图像的每个边界框的特征。然后,我们将所有这些特征传递到短期记忆库中,并保存在那里。长期记忆库也包含来自过去帧的特征,但是在更长的时间范围内,例如来自过去的 50 个图像。只有关键帧特征,即我们实际上想要对其执行对象检测的图像的特征,被直接传递到注意机制。

用于整合来自短期和长期记忆库的保存特征的注意机制。这种关注决定了哪些特性是相关的,这比硬编码一些 IoU 匹配要好得多。来源:【1】

这种注意机制在两个方面发挥作用:短时记忆和长时记忆。每次,来自关键帧的输入特征与来自记忆库的上下文特征一起被传递到注意块。在注意块中,模型学习哪些特征最相关,从而做出正确的检测。这意味着,如果模型意识到对于一个提议的边界框,它已经在过去看到过那些特征,它可以组合来自关键帧和来自过去的特征来执行对象的重新识别。我个人觉得这个机制还是蛮厉害的!

结果

在本文的介绍中,我们已经看到了检测移出框架或被遮挡的对象的改进性能。让我们看看上下文 R-CNN 可以发挥作用的更多领域,如弱光、远处的物体或背景干扰物。

在具有挑战性的场景中,上下文 R-CNN 在对象检测方面的出色性能。来源:【1】

这些结果看起来相当令人印象深刻!在左侧,您可以看到没有上下文的性能,在右侧,上下文 R-CNN 使用内存库来检测额外的对象。让我们来看看一些定量结果:

有上下文的 R-CNN 与没有上下文的更快 R-CNN 的性能比较。对于所有类别,新模型都优于单帧检测。来源:【1】

毫不奇怪,对于动物数据集中的所有类,上下文 R-CNN 在单个帧上的检测性能优于其他检测(感兴趣的人可以使用 Snapshot Serengeti)。这可以归因于语境机制。

同样非常有趣的是注意力机制的可视化。该块从时间上更接近关键帧的上下文帧中了解到特征对于对象重新识别任务也是最相关的。虽然这对人类来说是直观的,但令人印象深刻的是模型能够学习这一点。

时间上分离的帧对于关键帧中的检测的重要性的可视化。这些帧在时间上越接近,它们对于检测任务就变得越重要。来源:【2】

这种模型的另一个大优势是,上下文机制可以轻松地集成到任何快速、更快或屏蔽的 R-CNN 架构中。

包装它

在本文中,您已经了解了 Context R-CNN,这是一篇以短期和长期特征记忆库的形式利用时间上下文进行对象检测的论文。虽然我希望这个故事能让你对这篇论文有一个很好的初步了解,但是还有很多东西需要发现。因此,我会鼓励你自己阅读这篇论文,即使你是这个领域的新手。你必须从某个地方开始;)

如果你对论文中介绍的方法有更多的细节感兴趣,请随时在 Twitter 上给我留言,我的账户链接在我的媒体简介上。

我希望你喜欢这篇论文的解释。如果你对这篇文章有任何意见,或者如果你看到任何错误,请随时留下评论。

最后但同样重要的是,如果你想在高级计算机视觉领域更深入地探索,考虑成为我的追随者。我试着每周发一篇文章,让你和其他人了解计算机视觉研究的最新进展。

参考资料:

[1] Beery,Sara 等人,“背景 r-cnn:每个摄像机对象检测的长期时间背景”IEEE/CVF 计算机视觉和模式识别会议论文集。2020.【https://arxiv.org/pdf/1912.03538.pdf

[2]任,,等.“快速 r-cnn:面向区域提议网络的实时目标检测”神经信息处理系统进展28(2015):91–99。https://arxiv.org/pdf/1506.01497.pdf

如何使用 Streamlit 快速构建 ML web 应用程序?

原文:https://towardsdatascience.com/how-you-can-quickly-build-ml-web-apps-with-streamlit-62f423503305?source=collection_archive---------15-----------------------

将模型嵌入 web 应用程序的最快方法。

汤姆·盖诺尔在 Unsplash 上的照片

如果你是一名数据科学家或机器学习工程师,你可能对自己构建模型解决现实世界业务问题的能力相当有信心。但是你有多擅长前端 web 开发呢?你能构建一个视觉上吸引人的 web 应用程序来展示你的模型吗?您可能是 Python 专家,但不是前端 Javascript 专家。

但值得庆幸的是,你不必成为这样的人!Streamlit 是一个 Python 框架,它使机器学习和数据科学从业者可以非常容易地用纯 Python 构建 web 应用程序。没错,你甚至不用担心 HTML 标签、引导组件,或者编写自己的 Javascript 函数。

在本文中,我将展示如何使用 Streamlit 快速构建一个展示文本分类模型的 web 应用程序。

安装 Streamlit

您可以使用下面的命令通过 pip 轻松安装 Streamlit。

pip install streamlit

训练文本分类模型

在这一节中,我将训练一个简单的垃圾邮件分类模型来确定一条文本消息是否是垃圾邮件。因为本教程的主要焦点是演示如何使用 Streamlit,所以我将包含用于构建这个模型的代码,并附上最少的注释。我使用来自 Kaggle 的这个垃圾邮件分类数据集来训练一个用于垃圾邮件分类的神经网络。原始数据集在这里可用作为垃圾短信收集。你可以在 GitHub 上找到本教程的完整代码。

上面的代码执行以下步骤:

  1. 读取垃圾邮件数据集。
  2. 将垃圾邮件数据集分成训练集和测试集。
  3. 为垃圾邮件分类创建文本预处理和深度学习管道。
  4. 在训练集上训练模型管道。
  5. 评估测试集上的模型管道。
  6. 保存训练好的模型管线。

构建简化的应用程序

在与保存的模型管道相同的文件夹中,我创建了一个名为 streamlit_app.py 的文件,并按照下面几节中的演示逐步添加代码。如果你想看这个教程的完整代码,请参考这个 GitHub 库

导入库

我导入了运行这个应用程序所需的必要库和模块,包括 Streamlit,如下所示。

import joblib
import re
from sklearn.neural_network import MLPClassifier
from sklearn.feature_extraction.text import TfidfVectorizer
import streamlit as st

创建标题

现在我们已经导入了 Streamlit,我们可以使用 Streamlit 的 Markdown 支持快速创建标题。

st.write("# Spam Detection Engine")

要查看这段代码的结果,我们可以运行以下命令。

streamlit run streamlit_app.py

运行代码并导航到 localhost:8501 会得到以下结果。

简化只有标题的应用程序。图片由作者提供。

只需一行代码(不包括导入语句),您现在就拥有了一个正在运行的 Streamlit 应用程序!接下来,我们可以通过文本输入字段为应用程序添加一些交互性。

添加文本输入

message_text = st.text_input("Enter a message for spam evaluation")

在 localhost:8501 上刷新应用程序页面,我们会在标题下看到一个整洁的文本输入字段。

向 Streamlit 应用程序添加文本输入字段。图片由作者提供。

现在,我们可以将经过训练的垃圾邮件分类模型添加到应用程序中。

加载模型

在加载模型之前,我包含了预定义的文本预处理函数,因为这是已保存模型的一部分。

def preprocessor(text):
    text = re.sub('<[^>]*>', '', text) 
    emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)', text)
    text = re.sub('[\W]+', ' ', text.lower()) + ' '.join(emoticons).replace('-', '')
    return textmodel = joblib.load('spam_classifier.joblib')

生成和显示预测

我们可以定义一个特殊的函数来返回模型预测的标签(垃圾邮件或 ham)和邮件是垃圾邮件的概率,如下所示。

def classify_message(model, message): label = model.predict([message])[0]
  spam_prob = model.predict_proba([message]) return {'label': label, 'spam_probability': spam_prob[0][1]}

使用这个函数,我们可以将模型的预测输出为一个字典。

if message_text != '': result = classify_message(model, message_text) st.write(result)

我们可以再次刷新应用程序,并传入一些示例文本输入。先说一些明显是垃圾邮件的东西。

在 Streamlit 中显示模型的输出。图片由作者提供。

从上面的截图中,我们可以看到模型预测此邮件有很高的几率(99.98%)是垃圾邮件。

现在,让我们写一条关于医生预约的消息,看看模型是否将其分类为垃圾邮件或火腿。

在 Streamlit 中显示模型的输出。图片由作者提供。

正如我们在上面看到的,根据模型生成的预测,该邮件是垃圾邮件的概率非常低。

用石灰解释预测

我们可以使用 LIME(可解释的机器学习库)为模型生成的预测添加一些解释。关于如何使用这个库的深入教程,请看下面我写的关于可解释机器学习的文章。

要使用 LIME 并在 web 应用程序中嵌入 LIME 解释,请将以下导入语句添加到代码的顶部。

from lime.lime_text import LimeTextExplainer
import streamlit.components.v1 as components

Streamlit 的组件模块允许我们在应用程序中嵌入定制的 HTML 组件。我们可以用 LIME 创建一个可视化,并将其作为 HTML 组件显示在 Streamlit 应用程序上。

接下来,我们可以在最后一个 if 块的末尾添加以下代码,以创建一个解释模型预测的按钮。

explain_pred = st.button('Explain Predictions')

点击一次按钮,变量 explain_pred 的值将被设置为 True。我们现在可以用 LIME 生成一个文本解释,如下面的代码所示。

if explain_pred:
  with st.spinner('Generating explanations'):
   class_names = ['ham', 'spam']
   explainer = LimeTextExplainer(class_names=class_names)
   exp = explainer.explain_instance(message_text, 
   model.predict_proba, num_features=10)
   components.html(exp.as_html(), height=800)

刷新应用程序使我们能够为模型的预测生成解释,如下图 GIF 所示。注意 LIME TextExplainer 如何通过突出显示模型在决策过程中使用的最重要的词,让用户理解为什么模型将邮件分类为垃圾邮件。

用细流中的石灰解释预测。作者 GIF。

此时,该应用程序功能齐全,可用于展示和解释垃圾邮件分类模型生成的预测。查看下面这个应用程序的完整代码。

额外的简化功能

我在本文中创建的应用程序绝对有用,可以作为类似项目的起点,但它只涵盖了 Streamlit 的一些强大功能。以下是 Streamlit 的一些额外特性,您一定要看看:

  • Streamlit 支持 Markdown 和 Latex 命令,允许您在 web 应用程序中包含方程式。
  • Streamlit 允许你用一行代码显示表格和熊猫数据框。
  • Streamlit 允许您显示来自各种库的图表和可视化,包括 Matplotlib、Bokeh、Pyplot、Pydeck,甚至 Graphviz。
  • Streamlit 可让您轻松显示地图上的点。
  • Streamlit 还支持在您的应用中嵌入图像、音频和视频文件。
  • Streamlit 通过 Streamlit 共享简化了开源应用的部署。

要了解更多关于 Streamlit 的功能,请查看 Streamlit 文档

摘要

在本文中,我展示了如何使用 Streamlit 构建一个 web 应用程序,该应用程序用不到 50 行代码展示了一个简单的文本分类模型。Streamlit 无疑是一个强大的高级工具,它使数据科学家的 web 开发变得简单易行。像往常一样,你可以在 GitHub 上找到这篇文章的所有代码。

加入我的邮件列表

你想在数据科学和机器学习方面变得更好吗?您想了解数据科学和机器学习社区的最新图书馆、开发和研究吗?

加入我的邮件列表,获取我的数据科学内容的更新。当你注册的时候,你还会得到我免费的解决机器学习问题的逐步指南

来源

  1. T.a .,Almedia 和 J. M. Gomez Hidalgo,垃圾短信收集,(2011),2011 年 ACM 文档工程研讨会会议录(DOCENG'11)。
  2. Streamlit Inc ., Streamlit 文档,(2020),streamlit.io

如何使用 FastAPI 快速部署 ML 模型

原文:https://towardsdatascience.com/how-you-can-quickly-deploy-your-ml-models-with-fastapi-9428085a87bf?source=collection_archive---------6-----------------------

如何使用这个 API 构建工具快速部署您的 ML 模型?

Unsplash拍照

知道如何将机器学习模型集成到可用的应用程序中是数据科学家的一项重要技能。在下面链接的上一篇文章中,我展示了如何使用 Streamlit 快速轻松地构建 web 应用程序来展示您的模型。

然而,如果你想将你的机器学习模型集成到一个更大的软件解决方案中,而不是一个简单的独立 web 应用程序,该怎么办?如果您正在与一位软件工程师一起工作,他正在构建一个大型应用程序,并且需要通过 REST API 访问您的模型,该怎么办?这正是 FastAPI 发挥作用的地方。

FastAPI 是一个 Python web 框架,它使开发人员能够轻松构建快速(高性能)、生产就绪的 REST APIs。如果您是一名主要使用 Python 的数据科学家,那么 FastAPI 是将您的模型部署为 REST APIs 的绝佳工具。在本文中,我将演示如何通过用 FastAPI 构建 REST API 并在 Docker 容器中运行该 API 来部署垃圾邮件检测模型。

训练垃圾邮件检测模型

在这一节中,我将训练一个简单的垃圾邮件分类模型来确定一条文本消息是否是垃圾邮件。我重用了我上一篇关于用 Streamlit 构建 web 应用程序的文章中的模型训练代码,所以我在下面加入了代码,并做了最少的注释。

我使用来自 Kaggle 的这个垃圾邮件分类数据集来训练一个用于垃圾邮件分类的神经网络。原始数据集在这里可用作为垃圾短信收集。你可以在 GitHub 上找到本教程的完整代码。

上面的代码执行以下步骤:

  1. 读取垃圾邮件数据集。
  2. 将垃圾邮件数据集分成训练集和测试集。
  3. 为垃圾邮件分类创建文本预处理和深度学习管道。
  4. 在训练集上训练模型管道。
  5. 评估测试集上的模型管道。
  6. 保存训练好的模型管线。

构建 FastAPI 应用程序

在这一节中,我将演示如何使用经过训练的垃圾邮件检测模型,并将其作为 REST API 与 FastAPI 一起部署。代码将被增量地写入一个名为 main.py 的文件中,该文件将运行 FastAPI 应用程序。完整代码请参考下面的 Github repo

导入库

在下面的代码中,我导入了加载垃圾邮件检测模型和构建 FastAPI 应用程序所需的库。

import joblib
import re
from sklearn.neural_network import MLPClassifier
from sklearn.feature_extraction.text import TfidfVectorizer
from fastapi import FastAPI

初始化 FastAPI 应用程序实例

只需一行代码,我们就可以初始化一个 FastAPI 实例,如下所示。

app = FastAPI()

这个 app 对象负责处理不同 URIs 对 REST API 的请求。

定义简单的 GET 请求

现在我们有了一个 FastAPI app 对象,我们可以用它来定义一个简单 get 请求的输出,如下所示。

@app.get('/')
def get_root():return {'message': 'Welcome to the spam detection API'}

上面对根 URL 的 get 请求只是返回一个带有欢迎消息的 JSON 输出。我们可以使用以下命令运行 FastAPI 应用程序。

uvicorn main:app --reload

该命令启动一个本地 Uvicorn 服务器,您应该会看到类似于下面截图所示的输出。

如何用 Uvicorn 服务器运行 FastAPI?图片由作者提供。

如果您在浏览器中转到本地主机 URL http://127.0.0.1.8000,您应该会看到如下所示的 JSON 消息输出。

根 URL 上的 JSON 输出。图片由作者提供。

我安装了 JSON Viewer Chrome 扩展,这就是为什么我可以看到上面整洁的输出,如果你没有安装这个扩展,你的浏览器中的输出看起来会更像这样。

没有 JSON 查看器的根 URL 上的 JSON 输出。图片由作者提供。

现在我们知道了如何用 FastAPI 定义一个简单的 GET 请求,我们可以定义 GET 请求来检索垃圾邮件检测模型的预测。

加载模型和定义助手函数

在定义调用垃圾邮件检测模型的 GET 请求之前,我们需要首先加载模型,并定义预处理文本数据和返回模型预测的函数。

model = joblib.load('spam_classifier.joblib')def preprocessor(text):
    text = re.sub('<[^>]*>', '', text) # Effectively removes HTML markup tags
    emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)', text)
    text = re.sub('[\W]+', ' ', text.lower()) + ' '.join(emoticons).replace('-', '')
    return textdef classify_message(model, message): message = preprocessor(message)
    label = model.predict([message])[0]
    spam_prob = model.predict_proba([message]) return {'label': label, 'spam_probability': spam_prob[0][1]}

上面的预处理器函数从文本输入中删除表情符号和不需要的字符,而 classify_message 函数调用预处理器函数在使用垃圾邮件检测模型生成预测之前清理文本消息。 classify_message 函数返回一个字典,可以方便地解释为 JSON 响应。

定义垃圾邮件检测获取请求

FastAPI 使得为 GET 请求提供和读取变量变得非常容易。您可以使用查询参数或路径变量向 GET 请求提供机器学习模型的输入。

使用查询参数

对于 REST API,查询参数是 URL 字符串的一部分,并以“?”作为前缀。例如,对于我们正在创建的垃圾邮件检测 API,GET 请求可能如下所示:

127 . 0 . 0 . 1 . 8000/spam _ detection _ query/?message= '您好,请回复此消息'

请注意,最后的消息参数是一个查询参数。我们可以编写一个函数,接受一条消息作为查询参数,并将其分类为垃圾邮件,如下所示。

@app.get('/spam_detection_query/')
async def detect_spam_query(message: str): return classify_message(model, message)

如果我们导航到 localhost URL,我们可以用一个示例消息来测试这段代码。

使用查询参数测试垃圾邮件检测 API。图片由作者提供。

使用路径变量

使用路径变量时,输入数据作为 URL 中的路径传递给 API。在这种情况下,GET 请求可能如下所示:

127 . 0 . 0 . 1 . 8000/spam _ detection _ query/您好,请回复此消息

注意,消息只是 URL 路径的一部分,我们不需要使用任何查询参数。我们可以编写一个 GET 请求来接受这种格式的消息,如下所示。

@app.get('/spam_detection_path/{message}')
async def detect_spam_path(message: str): return classify_message(model, message)

我们可以通过从 localhost 导航到 API URL 来测试这个新的 GET 请求,如下图所示。

使用路径变量测试垃圾邮件检测 API。图片由作者提供。

至此,在编写了不到 40 行代码之后,我们有了一个用于垃圾邮件检测的正常运行的 REST API。查看下面完整的 Fast API 应用程序代码。

自动生成的文档

如果您导航到http://127 . 0 . 0 . 1:8000/docs,您将找到 FastAPI 应用程序的文档页面。

FastAPI 文档页面。图片由作者提供。

我们还可以使用这个文档页面来测试每个 GET 命令,如下面的 GIF 所示。

使用文档页测试垃圾邮件检测 API。图片由作者提供。

快速 API 的伟大之处在于这个文档页面是自动生成的。我们不需要编写任何代码或者投入大量时间来构建它。

在 Docker 上部署应用程序

现在我们有了一个工作的 API,我们可以很容易地将它作为 Docker 容器部署到任何地方。如果您不熟悉 Docker,它基本上是一个工具,可以让您在称为容器的隔离环境中打包和运行应用程序。

要将 API 作为 Docker 容器运行,首先需要创建一个名为 app 的目录,其中包含所有代码文件,并在父目录中创建一个 Docker 文件,其中包含运行 FastAPI 应用程序的说明。为此,打开一个名为“Dockerfile”的文本文件,并向其中添加以下行。

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7COPY ./app /appWORKDIR /appRUN pip install sklearn joblib

您的目录结构应该看起来像这样,还有一些来自训练垃圾邮件检测模型的额外文件:


├──app
│└──main . py
└──docker file

上面的 Dockerfile 文件执行以下任务:

  1. 提取 FastAPI docker 图像。
  2. 将应用程序目录的内容复制到映像。
  3. 使应用程序目录成为工作目录。
  4. 安装必要的依赖项,如 Scikit-learn 和 Joblib。

创建这个文件后,保存它并用下面的命令构建 Docker 映像。

docker build -t myimage .

一旦构建了映像,就可以用下面的命令运行 Docker 容器。

docker run -d --name mycontainer -p 80:80 myimage

现在,您应该有一个 Docker 容器在本地机器上运行。如果您打开 Docker 仪表板,您应该能够看到容器运行,如下图所示。

带有运行容器的 Docker 仪表板。图片由作者提供。

如果您将鼠标悬停在容器上,您应该会看到一个如下所示的“在浏览器中打开”按钮。

Docker 仪表板中的“在浏览器中打开”选项。图片由作者提供。

点击此按钮查看在您的浏览器中运行的容器。您应该看到从下面的根 URL 运行 GET 命令的输出。

现在我们有了一个运行 API 的 docker 容器。图片由作者提供。

我们甚至可以通过访问 localhost/docs 中的文档页面来测试这个 API。

Docker 容器上运行的 API 的文档页面。图片由作者提供。

正如下面的截图所示,我们可以很容易地看出 API 正在按预期工作,但这次它是在 Docker 容器上运行的。

在 Docker 容器上运行 FastAPI 应用程序。图片由作者提供。

既然 API 运行在 Docker 容器中,我们就可以将它部署在广泛的平台上。如果你有兴趣将这个项目向前推进一步,如果你想在云平台上部署这个 API,请查看下面的一些链接。

如何在 AWS 上部署 Docker 容器

在 Azure 上部署 Docker 容器

在谷歌云平台上部署 Docker 容器

摘要

在本文中,我演示了如何使用 FastAPI 和 Docker 快速部署垃圾邮件检测模型。FastAPI 是一个轻量级的快速框架,数据科学家可以使用它来创建机器学习模型的 API,这些模型可以轻松集成到更大的应用程序中。

和往常一样,你可以在 GitHub 上找到这篇文章的代码。

加入我的邮件列表

你想在数据科学和机器学习方面变得更好吗?您想了解数据科学和机器学习社区的最新图书馆、开发和研究吗?

加入我的邮件列表,获取我的数据科学内容的更新。当你注册的时候,你还会得到我免费的解决机器学习问题的逐步指南

来源

  1. 南 Ramirez, FastAPI 文档,(2021)。

如何使用 GPT J

原文:https://towardsdatascience.com/how-you-can-use-gpt-j-9c4299dd8526?source=collection_archive---------1-----------------------

GPT J 解释了 3 种简单的方法,你可以如何访问它

阿瑟尼·托古列夫在 Unsplash 上的照片

什么是 GPT J?

GPT-J 是一个名为 Eleuther AI 的组织发布的 60 亿参数模型。该组织的目标是使庞大的语言模型民主化,所以他们重新发布了 GPT-J,目前它是公开可用的。另一方面,由 openAI 发布的 GPT3 具有 1750 亿个参数,并且当时不公开可用。但是不要让参数数量上的差异欺骗了你。GPT-J 实际上在代码生成任务上胜过 GPT3。

GPT 模型不需要任何进一步的训练就可以完成语言处理中的各种任务,包括从未被训练过的任务。到目前为止,在 GPT 模型中实现这一点的方式是通过用来自互联网的书面文本来训练它们。一段文本被呈现给模型,它必须预测它将如何继续。因此,它“只能”预测文本可能如何继续,但这可以用于解决许多不同的任务,如语言翻译、代码完成、聊天、撰写博客文章等。

GPT J 的使用案例

代码生成

GPT J 可以用来生成代码,这是非常高的质量和真正的工程。假设我们想在 tensorflow 中训练一个 CNN。我们可以写一个程序做什么的代码注释(也许包括一个我们希望程序使用的库),剩下的由 GPT-J 生成。

输入:

import tensorflow# 4 layer CNN with a softmax output# test on MNIST data set

输出:

(作者代码)

聊天机器人

你可以像写戏剧剧本一样写下整个对话来制作一个聊天机器人。

(图片作者

重要的是,你要不断地把整个守恒的一大块输入到 GPT j 中,否则这个模型会很快失去对话的上下文。

故事写作

开始写你的故事,把它输入 GPT J,它会继续下去。

语言翻译

输入:

**English: Vine
French:** 

输出:

**English: Vine
French: Vin**

搜索信息

GPT J 已经接受了许多科学文章的训练,并且已经吸收了许多知识。如果你不想查找某一特定的信息,你可以在 GPT-J 中键入该主题的标题,然后阅读它所写的内容。

输入:

Quantum entanglement

输出:

**Quantum entanglement** between two or more entangled particles plays an essential role in quantum information science. In many schemes, quantum states of photons, atomic spin systems, ions, and other quantum systems are entangled to encode quantum bits. An efficient method to entangle multiple quantum systems is to use the quantum interference between two or more independent and uncoupled sources, which can achieve quantum information processing and quantum cryptography[@b1]. An ideal interference can be produced by a beam splitter that splits a beam into two identical copies[@b2]. For the entanglement between two photons, beam splitter with 50:50 ratio can create maximally entang

1.浏览器中的 GPT J

Eleuther AI 设计了一个包含 GPT J API 的网页,我们可以在其中输入文本,并查看模型如何继续。

EleutherAI 网站的标题(图片由作者提供)

这是链接,你可以自己试试。

温度设定

我们还可以选择在网站上设置变压器模型的温度。将温度设置为非常低的值意味着模型对它认为可能的单词变得更有信心。过低的温度通常会导致模型陷入循环。在温度= 0.33 的下例中,我们可以很好地解决这个问题。

温度= 0.33(图片由作者提供)

高温会导致更疯狂、更出乎意料的用词。在下面的例子中,我使用了温度= 1.22。我们可以看到,现在数到十是计算机科学问题的一部分,看起来像是 stackoverflow 的一个论坛帖子。

温度= 1.22(图片由作者提供)

Top-P 设置

Top-P 值决定了有多少不太可能的单词被排除在总采样池之外。例如,Top-p 为 0.9 意味着所有单词中最不可能的 10%被排除在抽样之外。请注意,理论上一个单词有 90%的概率出现在下一个单词中,因此所有其他单词都将被排除在抽样之外。字的概率也随着温度而变化。

实际上,这意味着增加温度和增加 Top-P 具有非常相似的效果。

2.在 google colab 上运行 GPT J

Eleuther AI 网站的一个问题是,它会在很少的单词后删除文本。如果你想自己选择输出文本的长度,那么你可以在 google colab 笔记本上运行 GPT-J。如果你从来没有运行过这样的笔记本,不要担心我会指导你。但是我必须警告你,colab 需要 10 分钟来初始化模型。

(图片由作者提供)

以下是访问笔记本的链接:

https://colab.research.google.com/github/ViniTheSwan/Bot/blob/main/colab_demo.ipynb

运行所有笔记本单元格,直到最后一个单元格。在笔记本的最后一个单元格,我们可以做我们的推断。我们可以更改 Top-P 和温度设置,并设置输入文本。但是我们也可以选择改变输出文本的长度。

(图片由作者提供)

python 中的三个引号意味着字符串可以跨多行。所以你可以把整段文字复制到程序中。

示例:

(图片由作者提供)

输出文本的长度是用记号来度量的,既不是字符也不是单词。令牌是常见的字符序列,可在互联网上的文本中找到。

在下面的图片中,我们可以看到我们的输入文本是如何被分成记号的。这个例子来自他们的 GPT2 模型的 OpenAI tokenizer。这实际上是同样的记号赋予器,也用在 GPT j

https://beta.openai.com/tokenizer的说明(图片由作者提供)

我们可以看到,Hallo get 分为“Hall”和“o”。标点符号也是独立的符号。除此之外,大多数单词等于一个单词。所以你可以把 gen_len 设置的比你最终想要得到的字数稍微高一点。

3.在 python 中使用 HuggingFace

你可以在电脑上用 huggingface 的“变形金刚”python 库运行 GPT-J。

要求

据推断,该模型大约需要 12.1 GB。因此,要在 GPU 上运行它,你需要一个至少有 16GB VRAM 和至少 16GB CPU Ram 的 NVIDIA 卡来加载模型。你也可以只在 CPU 上运行它,这样你只需要 16 GB 的普通内存,但是运行时间会更长。

装置

需要 pytorch 或 tensorflow 才能工作。所以如果你没有它们中的任何一个,用 pip 或者任何其他的包管理器安装一个。

pip install tensorflow

pip install pytorch

然后安装 transformer 库。

pip install transformers

您可以加载模型并使用下面的代码运行推理。您可以像在笔记本中一样,通过更改“上下文”字符串的内容来更改输入文本。

(作者代码)

变形金刚库的完整文档可以在:https://hugging face . co/transformers/master/model _ doc/gptj . html上找到

结论

GPT-J 非常容易访问,对于许多应用程序来说,它是非常方便的工具。

相关文章

LinkedIn
https://www.linkedin.com/in/vincent-m%C3%BCller-6b3542214/
脸书
https://www.facebook.com/profile.php?id=100072095823739
Twitter
https://twitter.com/Vincent02770108
Medium
https://medium.com/@Vincent.Mueller
成为 Medium 会员并支持我(你的部分会费直接归我)
https://medium.com/@Vincent.Mueller/membership

你应该如何设计 ML 工程项目

原文:https://towardsdatascience.com/how-you-should-design-ml-engineering-projects-9af1930a4e2b?source=collection_archive---------27-----------------------

ML 工程生命周期的分析,常见的陷阱,以及一个你可以使用的复制粘贴模板。

图片来源:克里斯多夫·拉格小精灵

机器学习工程是很难的,尤其是在高速开发产品的时候(我们在变态安全就是这种情况)。开发 ML 系统时,典型的软件工程生命周期经常失败。

你或你团队中的某个人有多少次陷入了无休止的 ML 实验中?发现 ML 项目花费的时间是预期的两到三倍?从优雅的 ML 解决方案转向简单且仅限于按时发货的解决方案?如果你对这些问题中的任何一个回答是肯定的,这篇文章可能适合你。

本文目的:

  1. 分析 ML 项目软件工程生命周期失败的原因
  2. 使用附带的设计文档模板提出解决方案,帮助您和您的团队更有效地运行 ML 项目

软件和数据科学项目生命周期

典型的软件工程项目是关于开发代码和系统的。他们可能会这样:

(1)识别产品或基础设施问题(2)讨论并设计解决问题的软件系统(可能通过爬行/行走/运行 ) (3)将问题分解成几个部分并在几天、几周或几个月内实施,通常使用敏捷开发流程(4)投入生产和监控(5)根据需要返回到周期的开始以改进系统(图片由作者提供)

这个生命周期显然不是 ML 工程项目所发生的。数据实验呢?模型训练和评估呢?

也许我们应该关注数据科学研究项目,看看它们的生命周期是否更合适。

一个数据科学研究项目可能是这样的:(1)确定一个可以用数据回答的问题(2)设计实验(3)争论数据(4)用数据分析或建模评估假设(5)发布结果或训练好的模型。(图片由作者提供)

这个生命周期好像也不对。纯数据科学研究项目是关于回答问题,而不是关于构建系统。什么是中间立场?

机器学习工程

机器学习工程正处于数据科学和软件工程之间的独特十字路口。如果你试图强迫每个人在典型的软件开发生命周期中操作,那么 ML 工程师在软件工程组织中操作会有困难。另一方面,像纯粹的数据科学或研究团队一样运营机器学习团队将不会产生任何产品。

当 ML 工程师致力于一个需要实验的项目时,他们会感到沮丧。当他们不可避免地因为数据不支持他们最初的假设或因为争论数据比预期的更困难而有错误的开始时,他们开始落后于承诺的时间表。这种落后感导致一种感觉,即与从事软件工程任务的同事相比,他们工作的一个关键部分——即实验——感觉像是一个持续的失败。

一个典型的 ML 工程生命周期如下: (1)识别一个问题(2)设计软件和实验(这些是相互关联的,因为你可能计划实现的模型将取决于哪些实验成功, 但是您可能需要设计特性和模型代码,以便首先运行您的实验) (3)实现代码和争论数据(这些可能是相互关联的,因为您可能需要实现软件来获得您需要的数据,并且您可能需要数据来编写和测试特性提取或模型训练代码) (4)分析数据、训练模型、评估结果(5)发布结果(6)测试、部署和监控代码和模型。

典型的 ML 工程生命周期。软件设计和实验设计越好,需要的重复访问就越少,因为好的设计会预见到可能需要采取的分支。(图片由作者提供)

这种 ML 工程生命周期通常是在工作中发明的,而不是教授的。精心布局软件和实验设计,是有可能做得非常好的。尽管如此,它也很容易做得很差,导致许多错误的开始和通向解决方案的曲折道路(可能永远也不会达到)。

初级 ML 工程师 vs 高级 ML 工程师

在朱莉·卓的一篇精彩文章中,她生动地比较了初级设计师和高级设计师——这种形象化也适用于初级和高级 ML 工程师

初级 ML 工程师流程。他们经常会在实现、实验和数据的空间中徘徊,而没有明确的方法。这既浪费时间,又令人沮丧。(图片由朱莉·卓提供,经允许使用)

高级 ML 工程师流程)。高级 ML 工程师将仔细地规划实验路线,知道何时缩短它们,并朝着更有成效的方向前进,以及知道何时一个结果指示新的方向前进。(图片由朱莉·卓提供,经允许使用)

当重复实验时,有条理的思考和纪律是必须的。我们能帮助 ML 工程师按照这种模式规划工作吗?

帮助 ML 工程生命周期的设计文件

我们如何鼓励更好的 ML 工程设计?

我们在“异常”实施的一个流程是,要求所有 ML 工程项目通过一个使用设计文档模板的正式设计审查流程,帮助工程师同时进行良好的软件和实验设计。

设计 ML 工程项目应该鼓励什么?

  1. 在匆忙实施之前,将工作投入到明确的前瞻性实验中。这避免了我们不时会发现自己陷入的无休止且毫无结果的 ML/数据实验/无聊的实验迭代。
  2. 无论实验是否验证了假设,都要大声说出实验的“成果”是有用的。推翻一个假设是有价值的,即使它不会导致 ML 产品的改进。
  3. 设计软件时要考虑到实验,设计实验时要考虑到软件(也就是说,什么能够交付生产)。根据您将要构建的系统以及这些数据在生产中如何可用来争论您的数据。

考虑到这些,我们创建了这个模板,以便在任何 ML 工程项目开始时填写。工程师应该复制这个模板,填写他们项目的细节,然后将软件和实验设计提交给团队进行反馈和迭代。这个过程极大地提高了项目的成功和速度,我们非常鼓励你的 ML 工程团队采用这个设计模板(或类似的东西)。

— — — — — — —
异常安全的 ML 设计文件模板(在新 ML 工程项目开始时复制并填写)。放心直接用,修改分享!

问题陈述

我们具体要解决什么,为什么现在要解决?一个强有力的理由将会把这与产品或客户问题联系起来。

目标

软件目标

描述我们希望建立的软件系统及其功能。

指标目标

期望的度量改进,我们将如何衡量这项工作的影响,我们为什么要以这种方式改进系统:

  • 不好的例子:提高模型的性能
  • 正常示例:将模型的 AUC 提高 X%
  • 好的例子:在不降低任何其他类别的召回率超过 Y%的情况下,将假阴性类别的召回率提高 X%。

预期的度量折衷,如果有的话:例如:在不降低精度超过 5%的情况下提高召回率。

试验设计

与纯软件项目不同,数据科学/ ML 项目通常需要数据探索、实验、失败,以及在收集数据的过程中改变设计。为了帮助一个项目取得成功,规划潜在的分支点以及如何在这个过程中做出决策是很有帮助的。此外,所有实验都应根据基线进行评估,基线可以是问题的简单解决方案(简单算法、简单启发式算法)或当前生产解决方案(如果存在)。

数据动机

描述应该解决的问题,用数据验证这确实是一个值得解决的问题。这真的会产生真正的影响吗?

假设

假设 1:

方法: 描述你正在接近的方法论。例如,这可能是我们正在测试的模型架构,我们正在添加的新特性,等等。 指标: 描述我们将用于评估方法的一个或多个指标。 成功标准: 将表明该假设成功的度量结果。理想情况下,应该用基线来衡量。 time box:X 天,然后与团队核对决定下一步 失败下一步: 例如,继续尝试假设 2 成功下一步: 例如,将此模型推向生产。

假设 2:…… 每个假设的同一套问题

软件设计

描述执行该项目所需的软件系统和数据管道。需要构建什么软件?什么服务和数据库?生产中需要哪些数据来运行您的模型?在这里可以随意使用普通的软件设计文档原则。

执行

送什么,什么时候送。一个强有力的计划将提供增量价值,并允许我们快速进入爬行状态。

爬行: 在我们投入太多时间在软件开发之前,证明改变的功效的最小设计。

走: 更彻底的设计旨在成为一个相对完整的部件。

跑: 长远设计在这里;我们如何使它成为真正一流的系统或模型。

考虑

发布的成功标准?

描述评估的指标,以倡导推出这种模式或改变到生产中。

什么会出错?

描述我们发布时可能出错的所有可能性?

  • 哪些产品表面会受到影响?
  • 这会对客户产生什么影响?
  • 我们将如何监控?
  • 我们要怎么做才能回滚?

安全和隐私考虑

  • 这种变化会对安全性产生什么影响?
  • 这种变化会对隐私产生什么影响?

附录:实验日志

记录每个假设测试的结果和过程中做出的决定,分支点,学习,修正的假设,等等。稍后提醒自己并与团队中的其他人分享你如何处理这类问题是有益的。

— — — — — — — — — — — — — — — — — — — — — — —

这个模板已经发展了很多年。感谢 Dmitry Chechik、周宇·李、Kevin Lau、Umut Gültepe 和 Abhijit Bagri 长期以来对设计过程的所有投入。

如果你对网络安全领域迷人的应用 ML 工程感兴趣,是的,我们正在招聘

你应该如何阅读机器学习论文

原文:https://towardsdatascience.com/how-you-should-read-a-machine-learning-paper-28fd7943e210?source=collection_archive---------21-----------------------

正确阅读和理解论文的关键

介绍

在这篇文章中,我们将回顾你在阅读机器学习论文时应该考虑的最重要的原则,以及你是否真的需要阅读论文来推进你作为机器学习工程师/从业者的道路。

图片来自 Unsplash

什么是论文?

论文是一篇书面文章,但不是记者的文章,也不是你能在网络博客上找到的文章,而是一篇学术文章。这是一份将学术调查结果具体化的文件,它向读者提供了所有必要的信息来论证和揭示研究人员的发现。

科学论文的最终目标是扩大知识领域,它充当了知识被正式表达、传播和被社会评论的书面媒介。这最后一点是至关重要的,一篇被认为是这样的科学论文已经过审查和验证,以评估其质量。

一篇没有被审阅和发表的论文被称为预印本,尽管它可能可供阅读,但你应该特别小心,用更挑剔的眼光阅读它。

一旦一篇论文准备好发表,它将通过一篇社论来完成,该社论将负责将其添加到科学杂志中。这是一个评估特定研究人员学术相关性的常用指标:他/她在著名杂志上发表了多少篇文章,以及他/她的论文被引用了多少次。一些最有声望的杂志是《自然》、《细胞》、《通讯》、《ACM》、《科学》…

为了能够接触到这些科学知识,有时你必须为此付费,而且不是一笔小数目。通常,科学杂志最常见的客户是研究人员和大学。如果你目前在大学读书,你可以向图书馆询问如何免费获取这些内容。

如果你不能自由获取科学论文,你可以随时使用 Sci-Hub 来获取:)

最近,开放获取运动非常受欢迎,它的目标是每个人都可以免费获取论文,并且有像 arXiv 这样的论文库,其中有数千篇不同版本的论文的 pdf。请注意,这里你只能找到预印本。

这些平台的目标是以更灵活的方式传播科学知识,跳过通常在验证过程中需要的等待时间。这是机器学习的关键之一,还有开放的文化,这使得该领域能够以近年来的速度发展。

简化科学论文阅读的关键

纸张结构

这种结构通常在大多数论文中都很常见,但在不同的研究领域会有所不同。通常,一篇论文分为不同的部分:

  • 摘要:作为文章内容呈现的总结。
  • 介绍:提出要解决的问题。
  • 相关工作:呈现论文所属的研究线。获取相关参考书目的关键字。
  • 材料和方法:说明问题是如何解决的。在这里我们可以找到大部分的公式、伪代码和实现细节。
  • 实验和结果:图表、可视化和表格部分
  • 结论:研究结果总结
  • 参考文献:从其他作品中获得的知识
  • 随附文件:如果有一点需要进一步解释才能完全理解。

如何阅读一篇论文?

首先要做的是阅读摘要,以评估你是否对该主题感兴趣,以及你是否想深入研究该主题。

那就要看你想在这门学科上投入多少时间或者你对这门学科的掌握程度了。如果你不知道论文的研究领域,你可以专注于相关的工作,这通常是联系主题以及结论和结果的关键。一旦研究人员已经有了一定的知识水平,他们通常会直接进行实验。

作为附件,下面提到的关于如何阅读论文的文章非常有用,它列出了我个人经常使用的阅读论文的策略,并大大简化了我的阅读过程:

https://web . Stanford . edu/class/cs 244/papers/how to read paper . pdf

总之,它建议在三个阅读阶段阅读任何给定的论文:

  1. 初读:快速浏览摘要,评估你是否对论文感兴趣
  2. 第二次阅读:这一次完成得相当快,没有阅读公式或伪代码,也没有试图理解所有的实验演示。只是看介绍和结论。
  3. 第三遍阅读:在这一遍中,你将真正钻研上面解释的所有章节,之后你应该能够再现你所阅读的内容。

理解学术观点

虽然这一点有时很明显,但还是有必要强调一下。我们倾向于认为,作为科学文献,论文是以完全严谨的方式产生的,它们遵循约定的惯例和方法。没有什么比这更偏离事实了。

机器学习是最多学科的科学领域之一,因为它来源于数学、语言学、计算机科学、信号处理……其中每一个都有其独特的一套方法。这意味着在一篇论文中,从神经网络的层结构来解释神经网络,在另一篇论文中通过信号处理算法来解释,在另一篇论文中通过贝叶斯概率公式来解释。

为了完全理解一个主题,通常有必要从各个角度对其进行分析,如果你想了解更多关于概念化问题的具体方法(即贝叶斯概率),你应该查阅共享杂志或共享会议的出版物,它们通常有相似的观点。

搜索关于论文的观点和评论

在纸上征求意见,学会批判。当您阅读一篇论文时,您应该记住,尽管它是通过了一些验证测试的文档,但这并不使它成为防错文档(尤其是在阅读预印本时)。

保持批判精神,随时问自己所读的东西是否正确:

  • 方法上可以吗?
  • 结果呈现得好吗?
  • 图表和可视化遵循良好的实践吗?
  • 论文解决了它提出的问题了吗?
  • 页面之间使用的术语是否一致?
  • 是在调查路线上前进吗?或者是一种更进步的进步,没有那么大的影响?

写论文时会有许多好的和坏的实践。一个非常有趣的资源是 OpenReview 网页,其中非常优秀的人公开发表评论,并攻击那些没有足够严谨和质量的作品。

在这一点上,我们还应该强调一下 Yannic Kilcher 的 Youtube 频道,它不仅对正在发表的最相关的论文进行引人注目的即时评论,而且通常还补充了个人评估和意见,说明为什么这些论文在方法上可能不正确(从中你可以学到很多)。

不要(只是)看报纸

当学习一个你感兴趣的话题时,不要只看论文,要多模态,去不同的来源。

就我个人而言,我不喜欢论文,我喜欢它们如何有助于集体知识的增长,但我不认为它们是传播知识的最合适的手段,它们很难消化,当涉及到真正吸收它们提出的一切时,读者(通常)必须做出巨大的努力。

此外,事实上,大多数读者,谁不是那么专业的研究领域,不需要这样的深化在这些主题,肯定有很多更合适的来源,为他们在这一阶段的学习。其中一个例子是存在于机器学习领域的文章,我认为它们完成了很好的教学工作,并且在呈现内容时非常动态,因为通常它们寻求的是读者能够以最容易理解的方式理解这些见解。

因此,我邀请你,如果你正在阅读一篇论文,而你并不完全理解它所表达的内容,你可以通过阅读关于这个话题的博客来补充你的经验。因为现在有很多好的选择。例如,媒体上的文章质量最高,尤其是那些发表在走向数据科学的文章。

去阅读论坛上关于这个主题的讨论也是很有趣的,或者如果你是专家,去实现这些解决方案的 GitHub 仓库看看。如果你对后者感兴趣,你肯定也有兴趣看看这个页面: PapersWithCode ,它列出了出版物,这些出版物的 GitHub 页面与它们在论文中引用的代码相关联。所有这些都是扩展知识的好选择。

在我个人看来,论文是一种传播知识的工具,这种知识在 21 世纪并没有更新到新的可用资源。它们在学术环境中有自己的位置,但对于大多数机器学习实践者来说,它们并不是必需的,通过互联网,我们可以找到许多优秀的教学资源。

一个成功的例子是distilt . pub页面,除了非常清晰地呈现概念之外,它还包含大量的交互元素,允许任何访问该页面的读者以一种更容易理解的方式访问知识。我们不会欺骗自己,这很酷。

最后,如果你真的想深入研究论文的内容,你总是可以组成学习小组或研讨会,你可以和一群已经研究并准备好论文内容的人一起讨论它,并就尚未明确的要点提出问题。分享你对某个话题的看法并谈论它是学习某件事情的一个很好的资源。最重要的是,一个人教,两个人学。

结论

像往常一样,我希望你喜欢这篇文章,并希望你现在有一个好的策略来从你阅读的论文中提取最大数量的知识(如果你决定这样做的话)。

如果你喜欢这篇文章,那么你可以看看我关于数据科学和机器学习的其他文章 这里

如果你想了解更多关于机器学习、数据科学和人工智能的知识 请关注我的媒体 并关注我的下一篇文章

你的数据是如何存储在磁盘和内存中的?

原文:https://towardsdatascience.com/how-your-data-is-stored-on-disk-and-memory-8842891da52?source=collection_archive---------11-----------------------

思想和理论

当您操作 Excel 文件或数据框时,深入了解一下幕后发生的事情。

克里斯蒂安·威迪格Unsplash 上拍摄的照片

我认为自己是一名应用程序员,我使用像 Python 这样的高级编程语言来操作数据框架,构建简单的管道来促进某些任务的数据分析。然而,在原子层面上,计算机本身并不理解“pandas.read_csv()”是什么意思,也不理解“write.table()”函数实际上是做什么的。它让我想知道将我们的命令转换为 0/1 二进制位所涉及的中间步骤,并促使我写这篇文章。

在这篇文章中,我希望给你一个粗略而直观的图像,看看磁盘实际上是什么样子,你的数据是如何在磁盘上布局的,以及你的磁盘和内存之间的信息交换是怎样的。这并不意味着是一个严格的技术博客,而更像是放松的阅读材料。了解物理硬件结构有助于我们更好地理解工作中可能遇到的任务和问题:

内存泄露?索引文件?内存开销?输入输出流?

所以振作起来,让我们开始吧!

磁盘是什么样子的?

当您在 PC 或 Mac 上时,您打开电脑或 Finder,所有出现在那里的文件都存储在磁盘上,有时磁盘也称为存储器。现在,几乎大多数个人电脑都在使用固态硬盘(SSD),然而,为了传达一些直觉,我将使用硬盘(HD)来说明磁盘的物理结构。

本杰明·雷曼在 Unsplash 上拍摄的照片

典型硬盘的结构看起来像 CD 播放器,它有一个可以旋转并切换到选定轨道的臂,臂的头部能够读取、写入或擦除存储在表面每个轨道上的数据。

盘片、磁道、扇区、间隙、数据块

表面也被称为盘片,盘片可以被分割成一组称为扇区的物理单元。每个扇区之间有间隙,几个扇区构成一个块,这个块就是逻辑单元

如果我告诉你一个盘片中的一个磁道的最大容量是 1024Kb (1Mb),那么你就知道你的 Excel 文件,我们假设是 2Mb,将占用两个盘片来存储它。

如果转速是已知的,那么你可以很容易地计算出文件/位从磁盘传输到内存的速度,反之亦然。同样清楚的是,为什么大文件需要更多的时间来读取,因为它需要更长的时间来旋转臂,并且臂也需要更长的时间来读取,因为存储区域将更大。

固态硬盘(SSD)将具有更快的访问时间,其架构与我在上面向您展示的硬盘(HD)示例有很大不同。但希望这能给你一个清晰的图像,你的文件在哪里,接下来我将向你展示数据是如何在磁盘上的。

数据是如何在磁盘上排列的?

在数据库管理系统(DBMS)中,每个记录(记录基本上是数据帧中的一行)以某种特定的方式位于磁盘上,以加速搜索、插入和删除。想象一下,如果每条记录都分散在磁盘上,没有任何规则或组织,将无法执行查询、索引和任何操作。

磁盘上的单个记录/数据

简单地说,您可以按行的方式存储所有数据,这意味着相似的记录/行将被收集在一起。这样做,按行索引可能非常有效,但会增加列操作的成本,或者按列索引可能相对较慢。如果按照列的方式,事情会变得完全相反。

让我们假设每一行都存储在磁盘上的一个合并空间中,如图所示。物理地址或指针与该记录相关联。除此之外,搜索关键字通常作为代理出现在索引文件中。索引文件基本上是一对搜索关键字和指针的组合。因此,拥有一个搜索关键字旨在加快搜索并避免开销。随着搜索关键字的出现,科学家们已经开发了大量有效的模式来表示和组织所有的搜索关键字。突出的例子包括:

  1. B+树 : 自平衡树,使得从根到所有叶节点的距离相等。
  2. B 树 : 类似于 B+树,但其记录存储在非叶节点上
  3. 可扩展哈希 : 一个目录连同桶,桶存储哈希表或哈希函数计算出的哈希关键字
  4. 线性哈希 : 类似于没有目录的可扩展哈希,但是有多级哈希函数。

由于这不是一个技术博客,我想向您推荐一些精彩的 youtube 视频(上面的链接),它们解释了每个索引模式是什么,以及它们如何实现快速有效的插入和删除。但是从这一部分得到的信息是,数据以一种设计良好的方式在磁盘上布局,使我们能够有效地获取和操作它们。

如何从磁盘读取字节/文件到内存?

首先,我希望灌输一点非直觉的事实,即文件实际上是一个位/字节流。当你把一个文件读入内存时,你是在处理一系列的 0/1,你希望正确地载入文件的特定部分。

fseek 和 read 函数将文件流读入内存

现在我们必须使用一些低级语言,如 C:

# declare file pointer
File *fp;
# initialize file pointer with a binary file stored on disk
fp = fopen('./test_file.bin','r');
# set the reading pointer from starting point (SEEK_SET) to 4 bits forward (offset = 4)
fseek(fp,4,SEEK_SET);# declare a pointer to store the file in memory
ph = (char) malloc(128);
# read the file, read 128 bits to the pointer in memory
fread(ph,sizeof(char),128,fp)
# free the memory
free(ph)

如图和代码片段所示,fseek函数有一个内置变量SEEK_SET,它是文件流的起始位置。我们设置offset=4来指示函数从SEEK_SET前面 4 位的位置读取。然后,我们在内存中声明一个 char 指针,使用fread函数将 128 位文件流专门读入我们刚刚定义的特定内存空间。这就是从磁盘读取到内存的实际工作方式。

此外,确保首先使用 c 中的malloc函数分配内存空间。同样重要的是,无论何时使用free函数手动分配空间,都要释放内存空间。忽略此步骤会导致内存泄漏问题,这是由未正确释放的未使用内存引起的。

结论

就像我在开始所说的,在大多数情况下,作为一个应用程序员,底层实现并不是我们主要关心的。然而,我始终认为这不是阻止我们学习一点计算机系统基础知识的借口。我希望你觉得这篇文章有趣和有用,感谢阅读!如果你喜欢这篇文章,请在 medium 上关注我,非常感谢你的支持。在我的 TwitterLinkedIn 上联系我,也请让我知道你是否有任何问题或你希望在未来看到什么样的教程!

斑马医疗视觉如何开发临床人工智能解决方案

原文:https://towardsdatascience.com/how-zebra-medical-vision-developed-clinical-ai-solutions-34b385617b65?source=collection_archive---------11-----------------------

行业笔记

Zebra Medical Vision 拥有 7 种 FDA 批准的解决方案——以下是他们是如何做到的

来源:作者

临床人工智能诊断解决方案的特殊缺乏

许多研究表明,机器学习模型在一系列任务上可以像训练有素的医生一样表现出色,特别是在放射学方面,甚至可以找到人类医生可能会错过的模式。

但多年来,人工智能支持的诊断解决方案并没有在医院实际使用。在其他领域,我们习惯于从研究到实践的快速转化:在面部检测技术取得突破后,你可能会看到脸书在不到六个月的时间里使用同样的技术来标记你的朋友。但是在医学诊断中,创新并没有转化为实践。为什么不呢?

这正是 Eyal Toledano 在 2014 年 Zebra Medical Vision 诞生时面临的情况:大量的突破性研究,诊断中对人工智能支持的明显需求,大量的人才,但在日常临床使用中几乎没有解决方案。

所以他们去寻找这个现实背后的原因。他们发现,在人工智能诊断应用于临床之前,单靠研究无法解决一些需要解决的关键挑战。医生和临床医生需要:

  1. 在代表总体的数据集上训练的模型;
  2. 无缝集成到临床工作流程中;
  3. 连接研究和医院的技术平台。

挑战 1:构建代表性数据集

Eyal 和他的团队发现的第一个问题是大多数学术研究依赖于小数据集。它们不仅规模小,而且也不代表临床医生每天在医院看到的各种各样的病例。对于现实世界的诊断解决方案,代表性数据绝对至关重要。

因此,第一个挑战是获得一个大的、多样化的数据集,看起来就像你在医院里期望看到的那样。

这就是为什么在最初的两年里,斑马医疗视觉几乎没有进行任何机器学习。相反,他们专注于与以色列、美国和印度的 30 多家医院发展数据合作关系。

收集病人的全景

虽然许多研究可能只是使用一种类型的数据来比较医生和机器的诊断性能,但 Zebra Medical Vision 必须走得更远。他们收集了以下方面的数据:

  • 许多不同形式的放射学图像(X 射线、CT、MRI、乳房 X 线照相术、PET 和核医学);
  • 实验室分析;
  • 病人入院和出院;
  • 医生的诊断;
  • 临床结果(指患者出院后的情况,可能是几年后)。

这里的关键因素是 Zebra-Med 收集的样本必须代表医生每天在医院面临的完全相同的多样性和复杂性。

概念验证与临床诊断解决方案

假设您构建了一个系统,该系统可以拍摄放射学图像,然后正确判断图像是否显示肺癌迹象或指示健康患者。乍一看,这似乎非常有用。但在医院里没用。

到目前为止,这只是一个概念验证——你已经证明了一种算法可以处理放射学图像,并区分两组明确描述的患者。但是这种情况(肺癌对健康患者)真的代表了医生将面临的问题吗?

事实上,这不是医院里会出现的问题。更有可能的是,病人来找你是因为他们已经有了一些症状,你需要诊断原因:毛玻璃样阴影、肺栓塞、慢性阻塞性肺病、肺气肿和肺癌可能都呈现类似的症状。

如果机器学习模型对医生有任何用处,它需要能够区分有症状的患者的放射学图像,而不是健康和不健康的人。

换句话说:你训练诊断模型的数据需要代表你期望在诊所看到的人群

但这并不是为日常医院诊断制作有用模型的唯一障碍。

挑战 2:无缝集成到临床工作流程中

Zebra 的人工智能预测直接集成到临床工作流程中:它会标记可疑的研究,医生可以轻松地将它们排在最前面。来源:作者

可以肯定的是,医生和其他人一样,希望新的解决方案能让他们的工作变得更简单,而不是更复杂。

但是学术研究没有解决这个问题。例如,您可能会开发一个非常准确的机器学习模型,该模型仅在使用特定的机器设置拍摄图像时表现良好,这些设置是医生通常不会在常规检查中使用的。

以这种方式解决问题当然是一个有价值的研究结果,但它仍然远远不是一个用于临床实践的可行的诊断模型,因为它需要一个非标准的工作流程。

在实践中,该模型必须无缝地适应现有的工作流程。这意味着:

使用标准工作流程中产生的数据

临床上有用的模型不应该要求临床医生执行任何额外的步骤。它应该只需要在医院的正常诊断工作流程中已经产生的精确数据(以精确的格式)。

使用医生已经使用的软件

Zebra Medical Vision 没有为医生建立一个新的软件工具来添加到他们的工作流程中。相反,他们与诊断工作站合作,将他们的预测直接整合到医生已经熟悉的软件工具中。

这种无缝集成是必不可少的——不仅因为要求医生改变他们的工作流程是不现实的,还因为使用人工智能的全部目的是节省时间,而不是增加额外的工作。

但这并不容易。有各种各样的工作站提供商和软件,以及不同种类的环境(例如,基于 web 的或基于 Windows 的)。再加上很多软件都很旧了。然而,Zebra-Med 必须与它们中的每一个集成。

将积分与计算分开

Zebra-Med 构建了一个智能基础设施,在最大限度减少重复工作的同时,提供了灵活性。医院只需在他们的本地系统中安装一次代理,该代理处理隐私、安全和匿名,并提供本地用户界面。

另一方面,所有繁重的工作和预测都发生在云中。这也使得 Eyal 和他的团队推出新版本的模型变得非常简单。他们只需更新他们这边的模型,安装在医院的代理与集中托管的模型进行通信。这意味着医院不需要做任何事情来接收更新。

此外,Zebra-Med 会提前计算预测,因此当医生点击图像时,他们可以立即看到结果。

假设您已经成功构建了一个模型,该模型能够准确地代表人群,无缝集成到诊断工作站中,并符合医生的工作流程。

即使这样,你仍然不能确定医生会从使用你的诊断模型中获益。原因如下。

节省医生的时间

假设每 1000 张乳房 x 光照片中有 6 例癌症诊断,并且你已经训练了一个可以实时评估图像的机器学习模型。医生现在可以在所有扫描结果旁边看到人工智能模型的评估,并可以对已标记的病例进行优先排序。

现在我们面临两个重要的考虑因素:

假阴性率。有多少次模型认为病人是健康的,而事实上他们并不健康?这种错误显然是非常危险的。如果医生因为系统显示病人健康而不看扫描,那么病人可能会错过接受治疗的机会。这是一个必须不惜一切代价避免的严重错误。

假阳性率。当患者实际上健康时,系统多久标记一次扫描?这个错误的问题要小得多——医生会交叉检查扫描,因为系统会标记它,并会发现这是一个错误的警报。

但总体来说,假阳性率还是决定了系统是否节省了医生的时间。假设您看到一个扫描被标记。你会努力检查它,试图理解为什么人工智能系统可能会认为它有问题,并花很多时间深思熟虑,然后得出结论:“不,人工智能犯了一个错误。这个病人其实是健康的。”假设每 50 次扫描中有 49 次是这种情况。

在这种情况下,如果医生不得不花额外的时间检查和反驳人工智能标记的大多数病例,人工智能可以更快地做出单个评估并不重要。

为了评估人工智能解决方案是否能够真正加速特定的诊断工作流程,您需要考虑:

  • 整合。您的模型如何无缝集成到当前工具中?人工智能评估适合工作流程吗?
  • 陈述。你能以一种对医生有意义的方式展示预测吗?
  • 临床患病率。在给定的扫描次数下,你预计会有多少病例?还有能不能达到医生能容忍的假阳性率?

到目前为止,我们已经强调了获得真实的临床数据作为构建模型的基础的重要性,该模型可以对临床中存在的精确人群和数据执行操作。我们已经证明,简单地拥有一个自动化诊断模型并不一定意味着您节省了医生的时间——无缝集成和可管理的假阳性率是必不可少的。

但是如果我们想把研究和临床联系起来——以一种满足监管要求的方式——我们仍然缺少一些东西。

挑战 3:构建人工智能诊断解决方案的技术支柱

熟练的数据科学和研究团队是必不可少的,但这还不够。

一旦 Eyal 和他的团队拥有了数据和将解决方案送到临床医生手中的方法,他们就必须在这座桥的顶部建立一条高速公路:使其他一切成为可能的技术骨干。

大规模标注和管理数据

机器学习模型从数据集学习。因此,如果你的数据中有任何错误——比如错误的诊断——那么模型也会学习这些错误。在运行任何实验之前,您需要仔细检查并正确注释研究中的所有数据点。

对于他们的研究,Zebra Medical Vision 必须协调全球多达 60 名不同的专家注释者的支持,他们都在从事相同的临床任务。在这种规模下,Eyal 必须构建内部工具来收集、比较和整合所有这些注释。

一次运行数千个实验

在过去,研究人员可能会花时间设计完美的实验,实施它,然后评估他们的方法是否能解决问题。但这对机器学习不起作用:有太多的方法来分割数据和建立模型,你永远不会到达终点。

因此,Eyal[和他的团队]需要建立一个平台,让研究人员能够同时测试不是一个,而是数千个实验。他们还制作了工具来跟踪所有这些实验,然后比较结果。

分离研究和临床系统

许多公司谈论反馈循环——通过用户反馈改进模型。对于临床解决方案来说,这通常是不现实的,也是不负责任的。

诊断模型被认为是一种医疗设备,任何改变都必须经过监管部门的批准。

斑马医疗视觉的研究(模型训练和测试)和临床使用的两个系统是完全分开的。它们之间有防火墙,它们甚至托管在两个独立的物理位置。

当然,该团队仍然希望从医生那里获得反馈,这样他们就可以了解模型是如何执行的,并在未来的迭代中使用这些知识。

但这只是在监管环境中工作的障碍之一。

满足法规要求

与诊断模型的开发和使用相关的一切都需要是可追溯的,包括:

  • 产品定义和系统要求;
  • 设计;
  • 数据监管;
  • 研究、开发和工程;
  • 测试;
  • 发布流程;
  • 顾客投诉。

Zebra Medical Vision 建立了一个全球质量管理系统,持续向 FDA 提供这些信息,通过透明度赢得信任。它们还遵循三种不同的 ISO 标准,以及第三方审计机构发布的 SOC 2 Type 2 内部控制报告,并接受了这些标准的测试。

这需要在安全方面进行大量投资,并确保所有事情都被记录在案。

现在我们讨论了伙伴关系、数据、集成和技术骨干。都是必须的。但是这些元素仍然不足以解决机器学习诊断问题——或者 Eyal 所说的临床任务。

乐队:一个具有临床使命的跨学科团体

Zebra Medical Vision 很快认识到,数据科学家无法完全依靠自己的力量制造出有用的医疗设备。此外,如果你将临床医生和数据科学家配对,你仍然会被卡住,因为即使他们认为他们在谈论同一件事,他们通常不是。需要有人来填补空缺。

两个世界之间的翻译:临床信息管理者的角色

Zebra Medical Vision 需要一个具有临床试验管理经验的人,一个既能说临床医生的语言,又能说数据科学家的语言的人。他们称这个角色为“临床信息经理”——这个人通常拥有生物医学工程或临床研究的博士学位。

每个临床任务还需要一名项目经理、一名研究工程师和一名操作工程师。

Eyal 称这个独特的跨学科团队为乐队:不同的才能,相同的临床使命。

乐队:Zebra-Med 用来成功解决临床任务并将 AI 诊断带入临床的跨学科团队。来源:作者

每个乐队成员都有特定的角色:

  • 项目经理保持项目正常进行。
  • 的临床医生带来了关于医院日常现实复杂性的知识。
  • 数据科学家和研究工程师制定和测试对数据的假设,也知道如何训练和验证机器学习模型。
  • 临床信息经理了解临床研究,并在临床医生和研究人员之间架起一座桥梁。
  • 运营工程师以稳健和可扩展的方式实施临床解决方案。

有一个紧密合作的乐队意味着一切都可以更有活力。正如 Eyal 发现的那样,这种灵活性是绝对必要的。

动态解决问题:任务总是在不断变化

在大学研究中,你正在研究的问题通常是固定的。但是埃亚尔和乐队发现他们经常在途中有所发现。因为这些发现提高了他们对问题的理解,他们经常改变临床任务。

乐队非常适合适应这些变化。一个原因是 Zebra Medical Vision 的技术骨干,这使他们能够快速工作,轻松修改和重新运行实验——而无需从头开始。

有了这些基础设施和这个团队,斑马医疗视觉可以以令人眼花缭乱的速度前进。他们已经在开发第七种 FDA 批准的诊断解决方案,更多的方案即将推出。

现在让我们看看 Eyal 和他的团队开发的两个诊断解决方案的例子,看看他们在这个过程中学到了什么。

医学影像解决方案的真实世界和研究方法之间的差异

例 1:冠状动脉疾病的早期预警

一半的心血管相关死亡是由于冠状动脉疾病。细胞废物、蛋白质和钙粘附在血管壁上,并与脂肪结合形成斑块。如果这种情况发生在向心肌供血的动脉中,那么它会限制或停止向心脏供氧,导致心脏病发作。

不幸的是,冠状动脉钙化的积累通常只能在心脏病发作或类似心脏事件后被诊断出来(T4)。

学术研究方法:当 Zebra Medical Vision 研究这个问题时,他们发现一篇学术论文称如果您手动分割感兴趣的区域,进行门控 CT 扫描(仅聚焦于心脏的扫描),并在特定协议中使用和不使用造影剂进行测量,然后您可以建立一个模型,该模型可以提供相当于 Agatston 评分(从 0(低风险)到 400(非常高风险)的风险测量)。

本质上这是一个分割问题:你分割冠状动脉中钙化的白云。

这种方法的问题:这种特殊的 CT 扫描协议只适用于已知有心脏病风险的病人。因此,这不能帮助所有其他处于危险中但还没有症状的患者。

考虑到很少有患者在心脏病发作前出现症状,找到一种方法来诊断更多的患者将会更有帮助。

更实用的方法: Zebra Medical Vision 意识到,患者需要为许多其他疾病进行 CT 扫描。这些所谓的无目标或无门控扫描可以包括许多器官,也包括心脏。Eyal 和他的团队发现了一种方法,在这种方法中,他们可以进行更频繁的扫描,同时仍然可以达到与研究人员为目标扫描建立的模型相似的准确性——在预测心脏病风险方面。

这意味着医生现在有一个心脏病预警系统在后台运行。如果患者是高风险患者,该系统会自动提醒他们——即使他们是出于另一个原因进行扫描,可能从未检查过心脏。因此,许多患者得到早期诊断并接受预防性治疗。

如今,这是 Zebra Medical Vision 的领先解决方案之一,并已被证明对大部分人群有效。它甚至优于其他只对门控 CT 扫描有效的解决方案。

例 2:脊椎压缩性骨折

骨质疏松症的早期诊断和治疗至关重要。但是脊椎压缩性骨折——骨质疏松症的一个可靠症状——在常规检查中经常被遗漏。

脊椎压缩性骨折(VCFs)——脊椎中部分脊椎骨塌陷的情况——经常被放射科医生忽视。这不是他们标准工作流程的一部分,诊断通常不是急性的,而且诊断起来很乏味:放射科医生必须检查扫描的另一部分,然后将每个椎骨的高度与其基线高度进行比较。最终,75%的 vcf 没有得到诊断或报告。

但是大多数高危人群已经在某个地方做了扫描。这意味着像素是存在的,压缩骨折已经在数据中捕捉到了——它们只是没有被报告。

尽管这个问题并不性感,也没有得到太多的关注,但诊断 VCFs 的好处——以及随之而来的骨质疏松症——对患者来说是巨大的。例如,50%的髋部骨折患者在未来 10 年内死于并发症。然后还有巨大的康复负担。

因此,Zebra Medical Vision 构建了一种算法来定位和识别这些压缩因素。这有助于真正关心骨质疏松症预防和治疗项目的临床医生识别 VCFs 患者。

现在,对有骨质疏松风险的患者进行筛查的医院可以在后台运行该模型,并自动提醒可能有骨折的患者。然后医生可以通过人工检查来确认这些病例。

正如埃亚尔所说,“有时候我们看的问题是有意义的,而不是性感的。”当你以一种探索的心态——一种数据科学家的心态——来看待大型数据集时,你会发现这种机会。

用天真的乐观完成不可能的事情

2014 年 5 月,在最开始的时候,Eyal 和他的同事去达拉斯参加了一个放射学会议。每个人都告诉他们:“放射学中永远不会有机器视觉这样的东西。那是幻想。你们是不错的以色列人。好好享受你的假期,回以色列去,找点别的事情做。”

但是他们天真的乐观拯救了他们。Eyal 和他的联合创始人认为他们可以解决这个问题,而且要快。最终,即使花费的时间稍长,这也将是一个极其有意义的挑战,项目的影响和价值是不可否认的。

这种心态推动他们通过无数的挑战。但正如埃亚尔所说,“你需要极其愚蠢——以一种积极的方式。”

小众零到底有多零?

原文:https://towardsdatascience.com/how-zero-is-the-niche-zero-d823101f4829?source=collection_archive---------22-----------------------

咖啡数据科学

理由保留的数据综述

我买了一个小众零,零代表零留存。这样做的目的是,如果你将 20g 咖啡豆放入研磨机中,你将得到 20g 咖啡渣(不是 19.9 或 20.1,而是 20)。我很好奇这台研磨机能达到多接近零。

我喜欢数据,我发现数据对我的咖啡体验有很大的帮助。所以我开始收集一些数据。如果我们定义 0 到 1 个小数位,小生境 0 实际上是零保留。损失量在 0.05g 左右,这已经很不错了。

所有图片由作者提供

数据分析

我们可以一起看看研磨设置,因为我已经运行了不少。似乎研磨设置对研磨保持力没有影响。有时,输出的重量会增加,这是由于之前运行的研磨物加入到新运行的研磨物中造成的。我试图在每次研磨后清洗,但这并不总是抓住一切。

我也看了研磨率。这与研磨设置成线性关系,如预期那样,有一些异常值。

主要的异常值来自两次烘烤。在这两种情况下,研磨机都卡住并完全停止。我在设置 5 时研磨 40 克,然后在设置 15 时研磨 40 克。第五集有些问题,速度慢了一点,我不得不加快一点。然而,对于设置 15,它很快就卡住了。

我很好奇粒子分布中是否有一些有趣的东西,但看起来相对正常,如下所示:

我还查看了几周内的留存率,以及每周的平均损失,大多数损失低于 0.1 克。

清洁

至于清洁,在写这篇文章的时候,我决定要清洁我的机器。我有一个习惯,该打扫的时候不打扫。这只花了 5 分钟,在过去的几个月里,我已经磨了将近 4 公斤的咖啡。

我把找到的咖啡量了一下,一共是 0.86 克咖啡。我用的是纸巾,里面残留了一些,所以最多 1 克咖啡。一些这种滞留可能是由于使用壁龛研磨用过的/干的粉末,但大多数看起来是正常的。

它看起来很乱,但它是非常简单的清洁过程。

后来,我的校准改变了一个点,这可能是因为咖啡将毛刺相互推开了。

在没有空气吹过系统的情况下,生态位零点是人们可以预期的零点。在各种研磨设置下,平均保持力为 0.05 克,其表现比我想象的要好。我非常喜欢它,我希望他们能推出平毛刺版本。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我

我的进一步阅读:

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事启动页面

摄影启动页面

使用图像处理测量咖啡研磨颗粒分布

改善浓缩咖啡

断奏生活方式概述

测量咖啡磨粒分布

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡用纸质过滤器

浓缩咖啡篮及相关主题

意式咖啡观点

透明 Portafilter 实验

杠杆机维护

咖啡评论和想法

咖啡实验

HRNet 解释道:人体姿态估计、语义分割和物体检测

原文:https://towardsdatascience.com/hrnet-explained-human-pose-estimation-sematic-segmentation-and-object-detection-63f1ce79ef82?source=collection_archive---------4-----------------------

揭示最先进的算法 HRNet 背后的东西

克里斯蒂安·卢在 Unsplash 上的照片

HRNet 讲解概要:

  1. 什么是 HRNet ?(简短解释,再往下就是完整解释)
  2. 应用领域
  3. 让我们深入研究卷积神经网络
  4. 人力资源网如何工作?
  5. 结论

如果你已经知道了基本知识(CNN +应用领域),跳到第 3 节或第 4 节。

HRNet 是什么?

HRNet 是语义分割、面部标志检测和人体姿态估计领域中最先进的算法。它在 PASCAL Context、LIP、Cityscapes、AFLW、COFW 和 300W 等数据集上显示出优越的语义分割结果。

但首先让我们了解一下字段的含义,以及 HRNet 背后隐藏着什么样的算法。

应用领域

语义分割

语义分割用于将图像的结构分类成特定的类别。这是通过用某一类标记每个像素来完成的[3]。在下面的示例中,表示骑自行车的所有像素都是类 person,表示自行车的所有像素都是类 bicycle [3]。图像分割的目的是让算法将图像分割成类别,从而分割成特定的结构。

来源:http://host.robots.ox.ac.uk/pascal/VOC/voc2012/#devkit

语义分割是用来做什么的?

有各种各样的使用案例,图像分割才刚刚开始。它应用于自动驾驶、医学图像诊断、手写识别。

面部标志检测

面部标志检测用于识别和定位面部的某些区域,如鼻子、嘴、眼睛或眉毛【2】。在下图中,你可以看到使用 OpenCV 可以检测眉毛、鼻子和嘴(通过左图中的红点可以看到)。

来源:https://learnopencv.com/face-swap-using-opencv-c-python/

面部标志检测是用来做什么的?

你可能知道 Snapchat 或 Instagram 中的面部交换滤镜。或者其他一些改变你眼睛、鼻子或嘴巴的滤镜。所有这些过滤器与面部标志检测一起工作,以检测面部的某个部分位于何处。此外,它还用于人脸变形和头部姿态估计。

人体姿态估计

人体姿态估计类似于面部标志检测,除了它是应用于整个身体的,并且它与运动有更多的关系。它检测的不是面部区域,而是语义关键点,如左肩、右膝等。[4].下图很好地描绘了线条如何绘制身体并识别某些点,通常是关节,如髋、膝、肩和肘。

来源:https://arxiv.org/abs/2103.02440

姿态估计集成在哪些应用中?

它应用于训练机器人,例如人形机器人。为了学习某些动作,人的动作是可以学习的。就在几天前,特斯拉宣布,它希望成为人形机器人领域的重要参与者,这表明这是一个未来的重要话题,可能会改变整个行业。

再者,应用于交互式运动游戏,如微软 Kinect 或其他 VR 应用[4]。

所有这些应用和方法都依赖于卷积神经网络,它是 HRNet 的基础。

https://medium.com/@hucker.marius/membership

让我们深入了解卷积神经网络

一个卷积神经网络(常为 ConvNet 或 CNN) 是计算机视觉领域经常应用的神经网络的特例。深度学习算法将图像作为输入,并为其对象分配重要性(由偏差和权重组成)[5]。

好吧,这很肤浅。让我们看看为什么 CNN 是最先进的。

正常的神经网络和 CNN 有什么区别?

首先,HRNet 中使用的卷积神经网络类似于普通的神经网络。两者都是基于神经元的,都有权重和偏差。主要区别在于架构。正常的神经网络不能很好地缩放,因此对图像没有用。图像并不像大多数人想象的那样平坦。图像是三维的,例如 32×32×3。32x32 是使图像成为二维的像素,x3 是每个通道的颜色(RGB)。在普通的神经网络中,一个(隐藏)层的每一个节点都与前一层或下一层的所有节点相连。对于大小为 32x32x3 的图像,这将导致 3072(=32x32x3)个权重。而往往图像并没有那么小,所以将其进一步缩放到高分辨率图像(如 1000x1000x3),构建全连接神经网络的权值和连接数会爆炸,降低神经网络的速度[7]。

这就是卷积神经网络的用武之地。它不是构建平面层,而是将神经元排列成具有深度、高度和宽度维度的 3D 对象[7]。一个主要的优点是它保持了输出的尺寸。一个普通的神经网络会将维数减少到一个平坦的输出。

来源:https://cs231n.github.io/convolutional-networks/[7]

conv net 有哪几层?

卷积层 —使用过滤器计算图像局部区域的输出

池层 —沿空间维度执行缩减采样

全连接层 —计算最终的班级分数

CNN 的卷积层会发生什么?

出于演示目的,我们假设输入图像的大小为 5x5x1,如下图 gif 所示。卷积层的神奇之处在于过滤器(也称为内核)。在我们的示例中,过滤器的大小为 3x3x1。这个内核/过滤器在整个图像上一小步一小步地移动(在我们的例子中是 9 步)并建立一个卷积特征。这降低了维度,并产生了一个激活图[5]。

来源:https://Daniel nouri . org/notes/2014/12/17/使用卷积神经网络检测面部关键点-教程/

为了覆盖所有特征和形状,应用了不止一个而是不同的过滤器(例如,5 个不同的过滤器)。然后,网络将学习过滤器,当它们识别某种类型的视觉形状(例如,角或线)时,过滤器将激活。在分辨率更高的图像中,大小为 5x5x1 的滤镜可能会检测到其他形状,而大小为 30x30x1 的滤镜则不会。

每个过滤器产生一个激活图,识别某些形状和模式。所有这些激活图沿着深度维度堆叠,并产生输出矩阵[6]。

在池层中会发生什么?

通常在卷积层之间使用池层。它用于减少必要的参数和空间大小。这再次有助于降低所需的计算能力。有两种类型的池:最大池和平均池[7]。

最大池取过滤器/内核的最大值,而平均池计算内核所有值的平均值。

全连接层会发生什么?

这是一个层,你可能从传统的基本神经网络中知道它。完全连接的层与前一层的所有激活具有完全连接,并且在 CNN 中,它可以用作用于分类的最终层[7]。

来源:https://cs231n.github.io/convolutional-networks/[7]

现在你应该知道深入 HRNet 的基本知识了。

人力资源网是如何工作的?

HRNet 代表高分辨率网络,指的是正在处理的图像的高分辨率。强高分辨率表示在像素和区域标记问题中起着重要作用,例如语义分割、人体姿态估计、面部标志检测和物体检测[1]随着像素的增长和更多基于视频的问题,高分辨率在未来可能会发挥越来越大的作用。

HRNet 背后的网络称为 HRNetV1,它“通过并行连接高分辨率到低分辨率的卷积来保持高分辨率的表示,其中并行卷积之间存在重复的多尺度融合。”【1】

那么,这意味着什么呢?

为了回答这个问题,让我们仔细看看下图。

来源:https://arxiv.org/pdf/1904.04514.pdf

你可以看到四个浅蓝色的方块。每个表示如上所述的多分辨率块,一个连接“高到低分辨率卷积【1】”的块。并行处理由多个通道映射线在彼此下方展示。黄色通道图代表最高分辨率,而红色小通道图代表最低分辨率。第四个模块并行处理 4 个分辨率。

资料来源:https://arxiv.org/pdf/1904.04514.pdf

多分辨率群卷积会发生什么?

"是组卷积"[这将是单行的方框,例如只有黄线] "的简单扩展,它将输入通道分成几个通道子集,并分别在不同的空间分辨率上对每个子集执行常规卷积。"[1]

来源:https://arxiv.org/pdf/1904.04514.pdf

在每个阶段结束时,您可以看到与下一阶段的多分辨率组的完全连接,看起来就像左侧的图像。HRNet 的这一部分称为多分辨率卷积。

“类似于规则卷积的多分支全连接方式。”[1]

换句话说,它将一级的规则盘旋(可能只是一条线)与下一级的所有平行盘旋连接起来。

HRNet 的优势是什么,为什么它的性能优于以前的模型(AlexNet、GoogleNet、VGGNet、ResNet、DenseNet)?

语义强大且空间精确:

  1. 诸如低分辨率网络的传统卷积神经网络串联工作,因此从低分辨率恢复高分辨率。
  2. HRNet 的并行方法允许在整个神经网络中保持高分辨率,因此表示更加精确。
  3. 其他方法聚集高分辨率和上采样的低分辨率表示。HRNet 重复多分辨率并在语义上加强由高到低的表示。

以前的 CNN 有串行卷积,没有并行。来源:https://arxiv.org/pdf/1904.04514.pdf

HRNet 及其变体

在 HRNetV1 中,只有高分辨率表示会产生输出(如下所示)。因此,低分辨率卷积的子集会丢失,并且不会完全包含在输出中。

HRNetV1 插图。资料来源:https://arxiv.org/pdf/1904.04514.pdf

这就是为什么 HRNet 的发明者进行了修改,允许输出从高到低分辨率的所有子集。

“好处是充分利用了多分辨率卷积的能力。”【1】

这是通过将低分辨率表示上采样到最高分辨率并连接所有结果子集来实现的。这个模型叫做 HRNetV2 ,主要用于估计分割图/面部地标热图。

HRNetV2 图示。来源:https://arxiv.org/pdf/1904.04514.pdf

另一个模型是 HRNetV2,它是为对象检测而制造的。在这里,作者增加了一个步骤:“我们通过对多级平均汇集的高分辨率表示进行下采样来构建多级表示。”【1】

HRNetV2p 图解。来源:https://arxiv.org/pdf/1904.04514.pdf

结论

HRNet 及其变体(HRNetV1、HRNetV2、HRNetV2p)是计算机视觉领域中许多机器学习学科的最先进技术。作者将传统的串行卷积结构改为多组卷积的并行结构。这种架构允许高分辨率,并提高精度和语义连接。

人力资源网再次表明,打破常规的思维是实现最先进成果的必要条件。作者没有试图像 AlexNet 和 co .那样改进现有的串行方法,但他们试图用一种更智能的方法彻底重建它,从而获得更高的结果。我很确定这只是将来有一天会取代 HRNet 的更复杂架构的开始。

**https://medium.com/@hucker.marius/membership

阅读更多像这样的**

来源

  1. 王等(2020)。用于视觉识别的深度高分辨率表征学习。https://arxiv.org/pdf/1908.07919.pdf

2.Shakhadri,S. (2021 年)。用 Opencv 简化面部标志检测。https://www . analyticsvidhya . com/blog/2021/07/face-landmark-detection-simplified-with-opencv/

3.Jordan,J. (2018)。语义图像分割综述。https://www.jeremyjordan.me/semantic-segmentation/

4.奥德梅金德,E. (2021)。利用深度学习进行人体姿态估计——2021 年终极概览。https://viso . ai/deep-learning/pose-estimation-ultimate-overview/

5.萨哈,S. (2018)。卷积神经网络综合指南 ELI5 方法。https://towards data science . com/a-comprehensive-guide-to-convolutionary-neural-networks-the-Eli 5-way-3bd2b 1164 a53

6.微软研究博客(2020)。高分辨率网络:用于视觉识别的通用神经结构。https://www . Microsoft . com/en-us/research/blog/high-resolution-network-a-universal-neural-architecture-for-visual-recognition/

**7.无作者(未注明)。卷积神经网络【https://cs231n.github.io/convolutional-networks/ **

Python 中的 Huber 和 Ridge 回归:处理异常值

原文:https://towardsdatascience.com/huber-and-ridge-regressions-in-python-dealing-with-outliers-dc4fc0ac32e4?source=collection_archive---------14-----------------------

如何处理数据集中的异常值

来源:照片由 Natalia_Kollegova 来自 Pixabay

当处理一组数据中的异常值时,传统的线性回归被证明有一些缺点。

具体来说,如果一个数据点距离该组中的其他点非常远,这可能会显著影响最小二乘回归线,即,接近该组数据点的总体方向的线将因异常值的存在而偏斜。

为了防止这一缺点,可以使用对异常值稳健的修正回归模型。在这个特殊的例子中,我们将看看胡伯回归模型。

背景

在这种情况下使用的数据集是皮马印第安人糖尿病数据集,其最初来自国家糖尿病、消化和肾脏疾病研究所,并根据 CC0 1.0 通用版(CC0 1.0)
公共领域专用许可证
提供。

对于这种特殊情况,将建立一个回归模型来预测患者的体重指数(身体质量指数)水平。

当查看身体质量指数的箱线图时,我们可以看到存在明显的异常值,如图表上半部分的数据点所示。

# Creating plot
plt.boxplot(bmi)
plt.ylabel("BMI")
plt.title("Body Mass Index")
# show plot
plt.show()

来源:Jupyter 笔记本输出

然后创建数据的相关矩阵:

corr = a.corr()
corr

来源:Jupyter 笔记本输出

这是一个使用 seaborn 的视频:

sns.heatmap(a.corr());

来源:Jupyter 笔记本输出

线性回归分析

在自变量中,皮肤厚度葡萄糖被选为假设对身体质量指数有显著影响的两个变量。

对训练数据进行回归分析,得出以下结果:

来源:Jupyter 笔记本输出

根据以上结果:

  • 皮肤厚度增加 1 个单位导致身体质量指数增加0.1597——保持所有其他变量不变。
  • 葡萄糖水平增加 1 个单位会导致身体质量指数增加 0.0418 个单位——保持所有其他变量不变。

我们看到这两个变量在所有水平上都非常显著(假设 p 值为 0)。虽然 17.5%的 R 平方很低,但这并不一定意味着这个模型不好。鉴于影响身体质量指数波动的变量范围很广,这只是表明有许多变量是这个模型没有考虑到的。然而,使用的两个独立变量显示了高度显著的关系。

通过验证集生成预测,并计算均方根误差(RMSE)值。在这种情况下使用 RMSE,因为分数对异常值更敏感。分数越高,预测的误差越大。

>>> olspredictions = results.predict(X_val)
>>> print(olspredictions)[36.32534071 31.09716546 28.67493585 34.29867119 35.03070074
...
 36.50971909 35.97416079 36.57591618 35.10923948 34.3672371]

均方根误差的计算方法如下:

>>> mean_squared_error(y_val, olspredictions)
>>> math.sqrt(mean_squared_error(y_val, olspredictions))5.830559762277098>>> np.mean(y_val)
31.809333333333342

相对于整个验证集的平均值 31.81 ,均方根误差的值为 5.83

现在,我们将生成 Huber 和岭回归模型。同样,将使用这些模型对验证集进行预测,并计算均方根误差。

胡伯对里奇

Huber 回归和岭回归都是为了生成一条比标准线性回归对异常值更不敏感的回归线。

然而,这些模型的工作方式略有不同。

具体来说,Huber 回归依赖于所谓的 M-estimat e,或者对异常值的敏感度低于平均值的位置度量(如牛津统计词典(Upton 和 Cook,2014 年)所述)。

岭回归使用所谓的 L2 正则化-使异常值的权重更小,从而对回归线的影响更小。此外,L2 正则化试图估计数据的平均值以避免过度拟合,而 L1 正则化(如在套索回归中使用的)试图估计数据的中位数。

在本例中,将使用 Huber 和岭回归进行预测,以便根据验证集计算预测的 RMSE。然后,性能最佳的模型将用于对整个测试集进行预测。

胡伯回归

这是一个 Huber 回归的例子:

hb1 = linear_model.HuberRegressor(epsilon=1.1, max_iter=100, alpha=0.0001, warm_start=False, fit_intercept=True, tol=1e-05)

具体而言,ε的值测量应该被分类为异常值的样本的数量。该值越小,模型对异常值越稳健。

从这个观点出发,计算了五个不同ε值的独立 Huber 回归。

hb1 = linear_model.HuberRegressor(epsilon=1.1, max_iter=100, alpha=0.0001, warm_start=False, fit_intercept=True, tol=1e-05)hb2 = linear_model.HuberRegressor(epsilon=1.8, max_iter=1000, alpha=0.0001, warm_start=False, fit_intercept=True, tol=1e-05)hb3 = linear_model.HuberRegressor(epsilon=2.5, max_iter=1000, alpha=0.0001, warm_start=False, fit_intercept=True, tol=1e-05)hb4 = linear_model.HuberRegressor(epsilon=3.2, max_iter=1000, alpha=0.0001, warm_start=False, fit_intercept=True, tol=1e-05)hb5 = linear_model.HuberRegressor(epsilon=3.9, max_iter=1000, alpha=0.0001, warm_start=False, fit_intercept=True, tol=1e-05)

根据验证集对五个模型进行预测。以第一个模型为例:

>>> hubermodel1 = hb1.fit(X_train,y_train)
>>> huberpredictions1 = hb1.predict(X_val)
>>> print(huberpredictions1)[35.67051275 29.43501067 27.18925225 33.91769821 34.47019359
...
 31.52694684 31.0940833  35.37464065 30.99181107 36.11032014]

计算的均方误差如下:

  • hb1 = 5.803
  • hb2 = 5.800
  • hb3 = 5.816
  • hb4 = 5.825
  • hb5 = 5.828

我们看到,RMSE 值都略小于使用 OLS 回归时计算出的 5.83。hb2,或者ε值为 1.8 的模型,表现出最好的性能——尽管微不足道。

里脊回归

以与前面相同的方式,使用回归进行预测,随后计算 RMSE:

>>> rg = Ridge(fit_intercept=True, alpha=0.0, random_state=0, normalize=True)
>>> ridgemodel = rg.fit(X_train,y_train)
>>> ridgepredictions = rg.predict(X_val)[36.32534071 31.09716546 28.67493585 34.29867119 35.03070074
...
31.79765405 36.18771132 31.86883756 36.98120033 35.68182273]

均方差实际上与使用 OLS 回归计算的结果相同:

>>> mean_squared_error(y_val, ridgepredictions)
>>> math.sqrt(mean_squared_error(y_val, ridgepredictions))5.8305

针对测试集的性能

假设ε= 1.8 的 Huber 回归显示了对验证集的最佳性能(尽管是边缘的),让我们看看它对测试集的性能如何。

在这种情况下,Pima Indians 糖尿病数据集的一部分与其余数据在物理上是分开的,以便检查模型在看不见的数据中的表现。

以下是预测:

>>> btest = t_bmi
>>> btest=btest.values
>>> bpred = hb2.predict(atest)
>>> bpredarray([33.14957023, 30.36001456, 32.93500157, 28.91518701, 
...
34.72666166,36.29947658, 39.13505914, 33.77051646])

计算测试集的 RMSE 和平均值:

>>> math.sqrt(mean_squared_error(btest, bpred))
5.744712507435319>>> np.mean(btest)
32.82418300653595

由于 RMSE 值仅占平均值的 17%多一点,该模型在预测整个测试集的身体质量指数值方面表现相当不错。

正如我们所看到的,所有模型的 RMSE 值或多或少是相似的——休伯回归提供了略低的 RMSE 值。然而,根据异常值的大小,在某些情况下,休伯回归和岭回归可以明显优于 OLS 回归。

结论

在本例中,您看到了:

  • 如何直观地检测数据样本中的异常值
  • Huber 回归和岭回归的区别
  • 如何修改 Huber 回归中的异常值敏感度
  • 使用 RMSE 确定模型精度

非常感谢您的宝贵时间,非常感谢您的任何问题或反馈。你可以在 michael-grogan.com 的找到更多我的内容。

免责声明:本文是在“原样”的基础上编写的,没有担保。它旨在提供数据科学概念的概述,不应被解释为专业建议。本文中的发现和解释是作者的发现和解释,不被本文中提到的任何第三方认可或隶属于任何第三方。作者与本文提及的任何第三方无任何关系。

霍夫曼解码

原文:https://towardsdatascience.com/huffman-decoding-cca770065bab?source=collection_archive---------11-----------------------

解压缩您的霍夫曼编码数据,以获得您的初始数据

我们已经在霍夫曼编码& Python 实现帖子中看到了如何使用霍夫曼编码对给定数据进行编码。现在我们将研究如何解码霍夫曼编码的数据,以再次获得初始的未压缩数据。

有了我们在编码阶段获得的二进制霍夫曼树,解码是一个非常简单的过程。

让我们考虑我们有与霍夫曼编码 post 相同的例子,因此我们有 AAAAAAABCCCCCCDDEEEEE 作为我们的初始数据,000000000000110101010101110110101010101010101010101010101010 作为具有以下霍夫曼树的编码输出:

“作者提供的图像”

现在我们唯一要做的就是从哈夫曼树的头部开始,从编码数据的开始,每次我们遇到 1 就向右走,遇到 0 就向左走,穿过哈夫曼树。当我们到达一个叶节点时,我们获得符号!然后,我们只是从哈夫曼树的头部重新开始,同时向前移动编码数据。

通过在 huffman.py 中添加几行来自 Huffman 编码& Python 实现的代码,我们可以轻松实现 Huffman_Decoding,结果如下:

def Huffman_Decoding(encoded_data, huffman_tree):
    tree_head = huffman_tree
    decoded_output = []
    for x in encoded_data:
        if x == '1':
            huffman_tree = huffman_tree.right   
        elif x == '0':
            huffman_tree = huffman_tree.left
        try:
            if huffman_tree.left.symbol == None and huffman_tree.right.symbol == None:
                pass
        except AttributeError:
            decoded_output.append(huffman_tree.symbol)
            huffman_tree = tree_head

    string = ''.join([str(item) for item in decoded_output])
    return string

“作者提供的图像”

一切似乎都没问题!可以查看 github 链接到达代码,自己试试💁

数据压缩是许多应用的主题,除了“基于频率”的霍夫曼算法之外,它还有各种不同类型的算法。你可以检查“基于字典”的方法,如 LZ77·LZ78LZW对图像压缩特别有用。

如果你想进一步了解霍夫曼,你可以搜索一下自适应霍夫曼编码和解码,这是一种更新更复杂的数据压缩算法,以霍夫曼算法为基础,在编码的同时更新霍夫曼树,不像传统的霍夫曼编码是一步一步进行的🍀

霍夫曼编码和 Python 实现

原文:https://towardsdatascience.com/huffman-encoding-python-implementation-8448c3654328?source=collection_archive---------0-----------------------

用 Python 实现的一种古老而有效的压缩技术

霍夫曼编码是一种用于压缩数据的无损压缩算法。这是一种由大卫·A·霍夫曼在麻省理工学院攻读博士学位时开发的算法,并发表在 1952 年的论文《最小冗余码的构造方法》中。[1]

从“压缩技术”可以理解,目的是以占用更少空间的方式对相同的数据进行编码。因此,当用霍夫曼编码对数据进行编码时,我们为数据中的每个符号获得唯一的代码。例如,字符串“ABC”占用 3 个字节,没有任何压缩。假设字符 A 被赋予代码 00,字符 B 被赋予代码 01,作为编码的结果,字符 C 被赋予代码 10。为了存储相同的数据,我们只需要使用 6 位而不是 3 个字节。在考察霍夫曼编码的工作原理之前,希望我说的 压缩 是什么意思更好理解!

“作者提供的图像”

算法

霍夫曼编码是一种利用符号的(或)频率特征和二叉树结构的算法。它包括以下 3 个步骤:**

  • 概率计算和符号排序
  • 二叉树变换
  • 给符号分配代码

概率计算&排序符号

我们计算整个数据中每个符号的数量,然后通过将该数量除以数据中的字符总数来计算每个符号的“概率”。由于这是一种使用概率的算法,所以更常见的符号(概率更高的符号)通常比不太常见的符号使用更少的比特来表示。这是霍夫曼编码的** 优势之一。**

作为一个例子,下面的数据有 5 个不同的符号作为 A B C D E,我们的概率如右图所示:

“作者提供的图像”

然后,我们很容易地根据将每个符号表示为一个节点的概率对符号进行排序,并将其称为我们的“集合”。现在,我们准备通过下一步。

“作者提供的图像”

二叉树变换

  1. 从集合中,我们挑选出具有最小概率和的两个节点,并将它们组合成一棵新树,其根的概率等于该和。
  2. 我们将新树添加回集合中。
  3. 我们重复这个过程,直到构建了一个包含所有输入概率的树。

“作者提供的图像”

给符号分配代码

在得到这个二叉树——所谓的 哈夫曼树 之后,我们唯一要做的事情就是为我们每次向右分配 1 ,为我们每次向左分配 0

最后,我们有符号和他们的代码获得霍夫曼编码!

“作者提供的图像”

我们可以快速看一下,即使只有 21 个字符,压缩和非压缩数据之间的差异也是不小的。

“作者提供的图像”

用 Python 实现

为了实现霍夫曼编码,我们从一个节点类开始,它指的是二进制霍夫曼树的节点。本质上,每个节点都有一个符号和相关概率变量,一个左右子变量和代码变量。当我们根据我们选择的边(左 0,右 1)遍历霍夫曼树时,代码变量将是 0 或 1

“作者提供的图像”

我们有 3 个帮助函数,第一个用于计算给定数据中符号的概率,第二个用于获得符号的编码,这些编码将在拥有霍夫曼树后使用,最后一个用于获得输出(编码数据)。

“作者提供的图像”

“作者提供的图像”

“作者提供的图像”

此外,我们有一个 Total_Gain 函数,它获取初始数据,字典来自 Calculate_Code,将符号及其代码保存在一起。该函数计算压缩和非压缩数据的比特大小之差。

“作者提供的图像”

最后,我们有 Huffman_Encoding 函数,它仅将数据作为参数,并使用这 4 个函数给出结果编码和总增益。

“作者提供的图像”

让我们看看代码是如何工作的,以及我们已经检查过的案例的输出!

“作者提供的图像”

另一个例子比我们简单的例子要大得多。我创建了一个 demo_file.txt,复制了一些关于数据压缩的随机信息,有 1579 个字。对于这个例子,我注释掉了 Print_Encoded 函数,因为不可能在一个图像中截取整个输出的屏幕截图。

“作者提供的图像”

作为结论,我们看到压缩比并不随着数据量的增长而变化,这个比值接近 2:1。我们可以说霍夫曼编码是一种将数据压缩到一半大小的算法。虽然老了,但依然是有效的压缩算法!

你可以点击 github 链接进入我的代码,用你自己的例子试试。

此外,如果您想了解如何解压缩霍夫曼编码数据以获得原始数据,请点击 此处

[1]https://en.wikipedia.org/wiki/Huffman_coding

1 毫秒延迟下的拥抱面部变形推断

原文:https://towardsdatascience.com/hugging-face-transformer-inference-under-1-millisecond-latency-e1be0057a51c?source=collection_archive---------0-----------------------

行业笔记

使用微软和 Nvidia 开源工具投入生产

“哦,我的皮毛和胡须!我迟到了,我迟到了,我迟到了!”(来自https://Commons . wikimedia . org/wiki/File:The _ White _ Rabbit (Tenniel)-_ The _ Nursery _ Alice (1890)-_ bl . jpgCreative Commons CC0 1.0 通用公共领域专用)

最近,🤗拥抱脸(变形金刚库背后的初创公司)发布了一款名为“Infinity”的新产品。描述为在“企业规模”执行推理的服务器。YouTube 上有一个公开演示(下面是演示中使用的时间和配置截图)。交流围绕着产品可以在 GPU 上以 1 毫秒的延迟执行变压器推理的承诺。根据演示者的说法,拥抱 Face Infinity 服务器的成本至少为💰部署在单台机器上的单一型号每年 20,0 00 美元(没有公开的价格可扩展性信息)。

这让我很好奇,想挖掘一下并检查一下使用微软和 Nvidia 的开源工具,是否有可能使用演示中使用的相同 AWS VM/model/input 达到那些性能(详情见下面的截图)?剧透:是的,有了这个教程,很容易重现和适应你的现实生活项目

💻项目源代码可从以下地址获得:

https://github.com/ELS-RD/transformer-deploy

自述文件提供了如何运行代码的说明,并在带有深度学习图像版本 44 的 AWS VM 和带有 Nvidia 3090 GPU 的裸机服务器上进行了测试(文中发布的测量值来自 AWS 机器)。

如果你对这个话题感兴趣,在推特上关注我:https://twitter.com/pommedeterre33

在 2 种输入尺寸的公开演示期间,执行了相当稳定的措施(来自 https://www.youtube.com/watch?v=jiftCAhOYQA,作者截图)

我在 Lefebvre Sarrut R & D 工作,这是一家领先的欧洲法律出版商,我的团队在生产中部署了相当多的模型,包括几个变形金刚,从小型蒸馏模型到大型模型,以执行法律文件的各种任务。这些作品中的一些已经在这里和那里被描述过

在本文中,我们将了解如何在工业环境中部署现代 NLP 模型。关于这个主题有几十个教程,但是,据我所知,它们不是针对生产的,也没有涵盖性能、可伸缩性、CPU 和 GPU 任务的解耦或 GPU 监控。其中一些看起来像这样:1/采用 FastAPI HTTP server,2/添加 Pytorch,和 voilà🤪

如果你有有趣的内容想让我链接到,请发表评论…

本教程的目的是解释如何从 Hugging Face 大量优化一个转换器,并将其端到端地部署在一个生产就绪的推理服务器上。你可以从 Nvidia 和微软那里找到一些有趣的技术内容,关于这个过程的一些具体部分。

最接近的匹配和对我的一个启发是这篇文章。它仍然错过了两个关键点,推理服务器端的重要优化和标记化(否则你不能轻松地在 Python 之外调用推理服务器)。我们将讨论这两点。

这个过程带来的性能改进适用于所有场景,从短序列到长序列,从大小为 1 的一批到大批量。当架构符合工具的期望时,与普通 PyTorch 相比,该过程总是带来显著的性能提升。

该过程分为 3 个步骤:

  • 将 Pytorch 模型转换成图形
  • 优化图表
  • 在一个高性能的推理服务器上部署图

最后,我们将我们的推理服务器的性能与演示期间 humping Face 显示的数字进行比较,并将看到对于批量大小为 1 的 16 和 128 令牌输入序列,我们都更快(据我所知,humping Face 尚未公开分享其他场景的信息)。

更重要的是,更多的机器学习实践者将能够做一些比在非推理专用 HTTP 服务器上部署开箱即用 Pytorch 模型更可靠的事情。

从 Pytorch 到 ONNX 图

你大概知道吧,Pytorch 相比 Tensorflow 1 的一大卖点。x 的易用性:你只需编写熟悉的命令式代码,而不是构建一个图表。感觉你在写以 GPU 速度运行的 numpy 代码。

让用户开心很棒,更棒的是让优化工具也开心。与人类不同,这些工具喜欢用图表来执行(有时是离线)分析。这很有意义,图形提供了从数据点到模型输出的整个过程的静态完整视图。此外,该图提供了若干机器学习框架可能共有的中间表示。

我们需要一种方法将我们的命令式 Pytorch 代码转换成图形。有几种选择,但我们感兴趣的是 ONNX。“ONNX 是为表示机器学习模型而构建的开放格式。ONNX 定义了一组通用的运算符——机器学习和深度学习模型的构建模块——和一种通用的文件格式,使人工智能开发人员能够将模型与各种框架、工具、运行时和编译器一起使用。”(【https://onnx.ai/】T4)。这种格式最初是由脸书和微软创建的,目的是在 Pytorch(研究)和 Caffee2(生产)之间架起一座桥梁。

Pytorch 包括一个导出到 ONNX 的工具。导出工具背后的原理非常简单,我们将使用“跟踪”模式:我们向模型发送一些(虚拟)数据,工具将在模型内部跟踪它们,这样它将猜测图形看起来像什么。

跟踪模式并不神奇,例如它看不到你在 numpy 中做的操作(如果有的话),图形将是静态的,一些 if/else 代码将永远固定,for 循环将展开,等等。这没什么大不了的,因为拥抱脸和模型作者注意到主要/大多数模型是跟踪模式兼容的。

供您参考,还有另一种称为“脚本”的导出模式,它需要以某种方式编写模型才能工作,其主要优势是动态逻辑保持不变,但它会在模型编写方式中添加太多约束,而没有明显的性能增益

以下注释代码执行 ONNX 转换:

Pytorch 到 ONNX 的转换代码(图片由作者提供)

特别的一点是,我们将某个轴声明为动态的。如果我们不这样做,图形将只接受与我们用来构建它的张量形状完全相同的张量(虚拟数据),因此序列长度或批量大小将是固定的。我们赋予输入和输出字段的名称将在其他工具中重用。

请注意,ONNX export 也可以像在句子变形库中一样进行特征提取,但在这种情况下,它需要一些小技巧。

🥳félications,你知道如何准备一个图形进行优化!

图形优化:2 个工具,1 个任务

我们将重点介绍 2 款优化 Pytorch 模型的工具:来自微软的 ONNX Runtime (麻省理工学院许可下的开源)和来自英伟达的TensorRT(Apache 2 许可下的开源,优化引擎为闭源)。

他们可以单独或一起工作。在我们的例子中,我们将一起使用它们,这意味着通过 ONNX 运行时 API 使用 TensorRT。

protip:如果你想听起来像个 MLOps,就不要说 ONNX Runtime / TensorRT,而要说 ORT 和 TRT。另外,你可能会在 Github issues/PR 中找到这些名字。

这两个工具执行相同类型的操作来优化 ONNX 模型:

  • 找出并移除多余的操作:例如,在训练循环之外,dropout 没有任何用处,它可以被移除,而不会对推理产生任何影响;
  • 执行常数折叠:意思是找到由常数表达式组成的图的某些部分,在编译时而不是运行时计算结果(类似于大多数编程语言编译器);
  • 将一些操作合并在一起:避免 1/加载时间,2/共享内存避免与全局内存来回传递。显然,它将主要有利于内存绑定操作(像乘法和加法操作,深度学习中非常常见的模式),它被称为“内核融合”;

他们可以有选择地将模型权重一次性转换为较轻的表示(从 32 位浮点到 16 位浮点,甚至在量化的情况下转换为 8 位整数)。

Netron 可以产生优化前后 ONNX 图的显示:

来自 ONNX 运行时——在 GPU 和 CPU 上实现变压器推理的突破性优化

这两种工具有一些基本的区别,主要是:

  • 易用性 : TensorRT 是为高级用户打造的,实现细节没有被它主要面向 C++的 API 所隐藏(包括 Python 包装器,它的工作方式与 C++ API 完全一样,如果你不是 C++开发人员,可能会感到惊讶)。另一方面,ONNX 运行时文档很容易理解,即使你不是机器学习硬件专家,它提供了 Pythonic API 和许多这种语言的示例,你会发现更多 NLP 专用的示例和工具。
  • 优化范围:tensort 通常提供最佳性能。这个过程有点复杂,我不会在这里提供细节,但是基本上你可以为不同的硬件、模型和数据形状建立“配置文件”。TensorRT 将在您的硬件上执行一些基准测试,以找到最佳的优化组合(因此一个模型与一个特定的硬件相关联)。有时这有点太激进,特别是在混合精度中,你的变压器模型的精度可能会下降。最后,让我们补充一点,这个过程是不确定的,因为它取决于内核执行时间。简而言之,我们可以说 TensorRT 带来的额外性能是有学习曲线成本的。ONNX 运行时有两种优化,一种称为“在线”优化,在模型加载后自动应用(只需要使用一个标志),另一种称为“离线”优化,特定于某些模型,尤其是基于 transformer 的模型。我们将在本文中使用它们。根据模型、数据和硬件的不同,ONNX 运行时+离线优化有时与 TensorRT 不相上下,其他时候我见过 TensorRT 在真实场景中快 33%。TensorRT API 比 ONNX 运行时提供的更完整,例如,您可以判断哪个张量形状是最佳的,并固定一些尺寸限制,因此它将生成所有需要的轮廓。如果你真的需要最好的性能,你需要学习 TensorRT API。
  • 多后端 : ONNX 运行时有自己的 CUDA 和 CPU 推理引擎,但它也可以将推理委托给第三方后端……包括 TensorRT、TVM 或 openVINO!在这种情况下,ONNX 运行时是一个很好的、文档完善的 API,可以利用一个更复杂的工具。你猜怎么着我们将在下面进行测试!
  • 多个硬件目标 : TensorRT 专用于 Nvidia 硬件(很多 GPU 和 Jetson),ONNX 运行时目标 GPU (Nvidia CUDA 和 AMD RocM),CPU,包括浏览器部署在内的边缘计算等。

如果你没有得到它,ONNX 运行时是你足够好的 API 来完成大多数推理工作。

关于所支持的转换器架构,您可以通过查看本页了解 ONNX 运行时的基本功能。包括伯特、罗伯塔、GPT-2、XLM、layoutlm、巴特、T5 等。关于 TensorRT,我已经尝试了许多架构,没有任何问题,但据我所知,没有测试模型的列表。至少你可以在那里找到 T5 和 GPT-2 笔记本,与 vanilla Pytorch 相比,它的推理速度快了 5 倍。

根据这个自述,Nvidia 正在努力减轻变形金刚在其框架上的加速,这对我们所有人来说都是一个好消息!

离线优化

如前所述,一些优化是在将模型加载到内存中之后应用的。也有可能在执行图形的静态分析时应用一些更深层次的优化,以便更容易管理动态轴或删除一些不必要的转换节点。此外,更改模型精度(从 FP32 到 FP16)需要离线。查看本指南了解更多关于这些优化的信息。

ONNX 运行时在其工具文件夹中提供了这样的东西。支持大多数经典变压器架构,包括 miniLM。您可以通过命令行运行优化:

*python -m onnxruntime.transformers.optimizer ...*

在我们的例子中,我们将在 Python 代码中执行它们,以便执行一个命令。在下面的代码中,我们启用了所有可能的优化,并执行了到浮点 16 精度的转换。

ONNX 运行时离线优化代码(图片由作者提供)

性能改进的一部分来自于在 CUDA 级别执行的一些近似:在激活层(GELU)和注意屏蔽层。这些近似值可能对模型输出有很小的影响。根据我的经验,与在训练期间使用不同的种子相比,它对模型准确性的影响更小。

关于 TensorRT,没有离线优化,但是在 ONNX 运行时文档中建议在普通 ONNX 模型上执行符号形状推理。这很有用,因为 ONNX 运行时可能会将图形分割成几个子图,因此 tensort 的(张量)形状信息会丢失。符号形状推理将把信息放回任何需要的地方。如果你和我一样,想知道为什么它被称为符号,那是因为它真的会用一个叫做 sympy 的 Python 库来执行符号计算,这个库致力于……一般的符号计算。

ONNX 形状推理代码(图片由作者提供)

关于 GPU int-8 量化的一句话

CPU 量子化开箱即用,GPU 则是另一个故事。你可能已经看到 Nvidia 的基准测试显示了与 FP16 精度相比 int-8 量化的惊人性能,并且可能想知道,为什么你找不到任何 NLP 教程来做同样的事情(在 CV 中有很多)。

原因有几个:

  • 首先,自去年夏天发布的 TensorRT 8 以来,变形金刚量化已全面启用。
  • 第二,现有的工具(至少是我尝试过的那个)有问题,文档并不总是最新的,并且它不能很好地与 Pytorch 的上一个版本一起工作(我在导出包含 QDQ 节点的图形时遇到了一个问题)。不过,如果您深入研究 Pytorch 代码,您可以用一个脏补丁来解决这个错误。
  • 第三,结果取决于硬件,这意味着对不同的形状/模型/硬件组合进行了大量的实验。
  • 第四,根据你的量化方法,它可以通过添加大量的“重新格式化”节点,使你的模型比 FP16 中的模型慢。

量化为各种转换器架构带来了最佳性能,因为除了减少计算,它还减少了许多权重的内存传输,这是任何内核融合都无法达到的。

另一件要记住的事情是,不是所有的模型都可以开箱即用 int-8 量化,有时你会得到一些“找不到节点的任何实现…”的错误消息,这意味着你可以重做模型,等待 tensort 的新版本,或者,如果你有很多空闲时间,像这里的一样分叉 tensort。香草伯特效果很好。miniLM 可以在一些工具上工作,但不是全部,不知道为什么。

不是所有的层都应该被量化。训练后量化将量化所有图层,并注重性能(但精度可能会下降),这取决于用户选择他想要排除的图层以保持高精度。查询感知训练只量化特定的层,例如在 Bert 情况下,你会发现注意力层,因此它通常是准确性和性能之间的权衡。

最后,校准(将浮点数转换为整数和小数位数的必要操作)仍然是一个未解决的问题,有几个选项,您需要再次试验,以找到适合您的模型和任务的选项。

关于量化的更多信息,你可以查看 Nvidia 的这篇非常好的论文:https://arxiv.org/abs/2004.09602

当你在像微软、这样的互联网规模工作时,投资这项技术是有意义的。对于我们大多数人来说,直到软件部分改进后才明显。

⌛Inference 基准(本地执行)

好了,现在是时候基准测试了。为此,我们将使用一个简单的装饰函数来存储每个计时。代码的其余部分非常简单。脚本末尾的度量是用 16 个令牌输入来执行的(就像 Infinity 演示中的一个度量)。

推理基准代码(图片由作者提供)

结果如下:

针对 16 个令牌输入的每个 ONNX 运行时提供程序的度量(图片由作者提供)

💨TensorRT(第 1 行)的 0.64 ms ,优化 ONNX 运行时的 0.63 ms (第 3 行),比 vanilla Pytorch 快了近 10 倍!我们远远低于 1 毫秒的限制。

我们得救了,这篇文章的标题很荣幸:-)

有趣的是,在 Pytorch 上,16 位精度(5.9 毫秒)比全精度(5 毫秒)慢。这是由于我们的输入,没有批处理,序列非常短,并且在一天结束时,从 FP32 到 FP16 的转换增加了比它所暗示的计算简化更多的开销。

当然,我们已经检查过所有的模型输出都是相似的(如上所述,由于小的近似,它们不会相等,加上不同的后端在图中执行舍入略有不同)。

除了基准或极限用例之外,并不是每天都要在 GPU 上的一个非常小的模型上对单个 16 序列令牌执行推理,因为它没有利用 GPU 的主要优势。此外,即使您的查询以单个序列的形式出现,大多数严肃的推理服务器都有一个特性,可以成批地将单个的推理请求组合在一起。其目的是以增加的吞吐量换取几毫秒的延迟,这可能是您在尝试优化硬件总拥有成本时所寻求的。

仅供参考,与拥抱脸演示无关,请查看以下在同一虚拟机(T4 GPU)上针对bert-base-uncased、384 个令牌的序列和 32 个大小的批次(这些是我们在 Lefebvre Sarrut 的用例中使用的常用参数)的测量结果:

在 bert-base 上的性能-在大批量数据的情况下(图片由作者提供)

可以看到,TensorRT 和 ONNX 运行时带来的延迟降低非常显著, ONNX 运行时+TensorRT 延迟(4.72 ms)比 vanilla py torch fp32(25.9 ms)⚡️低 5 倍以上🏃🏻💨💨对于 TensorRT,在百分位数 99 时,我们仍低于 5 毫秒阈值。正如所料,Pytorch 上的 FP16 大约比 FP32 快 2 倍,ONNX 运行时(CUDA 提供程序)的表现与 TensorRT 提供程序非常相似。

这些结果不会让我们感到惊讶,因为我们似乎使用了与拥抱脸相同的工具:

🍎相对🍎:第一次尝试,ORT+FastAPI vs 拥抱脸无限

将前面部分的计时与拥抱脸演示的计时进行比较是不公平的:我们没有服务器通信,没有令牌化,没有任何开销,我们只是执行推理。

所以,我们将再次这样做,但这一次使用一个简单的 HTTP 服务器:FastAPI(就像你可以在人工智能创业博客上找到的几十个营销内容一样)。

请注意,无论 FastAPI 的性能如何,它都不是继续生产的好的推理服务器选择,它缺少基本的东西,如 GPU 监控、高级 ML 性能工具等。

至少,它很容易写:-)(图片由作者提供)

时间看起来是这样的:

简单基准 ONNX 运行时+ FastAPI 基准(如果用请求库替换 curl,则采用类似的方法)(图片由作者提供)

【讥讽开】whhhhhhhaaaaat????在 fastAPI 内部执行推理比本地推理慢 10 倍?真令人吃惊,谁会料到呢?【讥讽关】

如果我们检查一个著名的 web 框架基准,我们可以看到,与其他语言的其他选项相比,FastAPI 并没有那么快。在单个查询延迟方面,它甚至是最慢的(比 fasthttp Go 服务器慢 38 倍以上)。这并不意味着它是一个糟糕的软件,当然,凭借其自动打字等功能,它确实是一个很好的工具。,但这不是我们这里需要的。

拥抱脸仅在批量大小为 1 的非常短(16)和短(128)的序列上通信。该模型可以用现成的工具进行优化,但是如果我们停留在 Python 世界中,端到端的性能是无法达到的。在其他一些场景中(大批量、长序列),几毫秒的开销差异可能是微不足道的。

那么,如果不是 fastAPI,我们用什么呢?

🍎相对🍎:第二次尝试,Nvidia Triton vs 拥抱脸无限

Nvidia 发布了一款漂亮的推理服务器,名为 Triton (之前被称为 TensorRT,非常混乱)。

它提供了你可能需要的几乎所有东西,GPU 监控,漂亮的文档,我见过的最好的错误消息(说真的,就像他们把某人放在里面告诉你要修复什么和如何修复)。它有很多非常强大的可能性(我们不会在这个已经太长的教程中详述),并且对于简单的情况仍然易于使用。它提供了一个 GRPC 加一个 HTTP API,一个相当好的 Python 客户端(请求库就像 FastAPI,简单的 API,接近完美的文档,但是性能一般)和一个好的 C++客户端。它附带了一系列重要的工具来优化硬件的使用。为了更好地理解什么是一个好的推理机,查看一下https://arxiv.org/pdf/2011.02327.pdf

出于我不明白的原因,它在 NLP 社区中不是一个非常知名的工具(在 CV 社区中情况稍微好一点)。

1/在 Triton 推理服务器上设置 ONNX 运行时后端

推断海卫一很简单。基本上,你需要准备一个文件夹,里面有我们生成的 ONNX 文件和一个配置文件,如下所示,给出了输入和输出张量的描述。然后你启动 Triton Docker 容器…就这样!

这里是配置文件:

它闻起来像 json,但它不是(图片由作者提供)

2 条评论:

  • max_batch_size: 0 表示没有动态批处理(上面描述的用吞吐量交换延迟的高级特性)。
  • -1 在形状上表示动态轴,也就是这个维度可能会从一个查询改变到另一个

2/设置客户端

在与本文相关的 repo(开头的链接)中,有 2 个 Python 客户端脚本,一个基于 tritonclient 库(performant),一个基于请求库(不是 performant,但是如果需要在 Python 之外调用 Triton,它可以作为草稿使用)和一个简单的 curl 调用(在存储库自述文件中)。

我们用于查询 Triton 推理服务器的基于 tritonclient 的脚本:

不是最 pythonic 化的 API🐍(图片由作者提供)

客户端库中的微妙之处在于,首先声明输入和输出变量,然后将数据加载到它们中。

注意,输入 ids 张量是 为每个请求随机生成 ,避免任何缓存效应(据我所知,默认没有缓存但总是好查的)。

16(第一次测量)和 128(第二次测量)令牌输入长度的结果:

基准 ONNX 运行时+ Triton 推理服务器(图片由作者提供)

太棒了,我们发现了一些东西:对于 16 和 128 令牌序列长度,我们仍然低于拥抱脸基线。在 128 个令牌情况下,裕量相当大。

我们仍然在 GPU 上做纯模型计算,为了有一些我们可以与拥抱无限相比较的东西,我们仍然需要将令牌化部分移动到服务器。

3/在服务器端添加令牌化

我跟你说过英伟达 Triton 服务器很牛逼吗?正是。它支持几个后端,包括一个叫做“Python”的后端。在 Python 后端,我们可以调用免费的 Python 代码,例如准备我们的数据(在我们的例子中是标记化)。

在实现这一部分之前,您需要在 Triton Docker 容器中安装变压器。有关更多信息,请查看与本文相关的存储库的自述文件。

Python 代码看起来像什么:

非常简单的 Python 代码(图片由作者提供)

基本上,有一种__init__()函数供我们下载标记化器,还有一种execute函数执行标记化本身。for 循环是因为动态批处理功能。非常简短的代码。

我们需要一个配置来告诉 Triton 输入和输出是什么。

类似于之前的配置(图片由作者提供)

现在我们想将标记器插入到模型中,我们需要第三个配置。

将标记器输出插入模型输入的配置文件(图片由作者提供)

第一部分声明整个过程的输入和输出,第二部分将所有内容连接在一起。基本上,它说接收一个字符串,把它发送给记号赋予器,从记号赋予器得到输出,并把它作为模型的输入传递,返回模型输出。

如前所述,服务器文档写得很好。很容易使用错误的类型,错误的维度,或者在张量名称中插入一个错别字,Triton 错误消息会告诉你到底要修复什么和在哪里。

4/ 👀最终基准!

最后,这里是最终基准的时间。下面你可以看到我们最终的客户端脚本。与之前的客户端脚本的主要区别在于,我们现在的目标是整个流程,而不仅仅是模型。我们不发送整数张量,只发送字符串(存储在 numpy 数组中,这是与 Triton 通信的方式)。

*本文中最重要的基准脚本。简单,就够了。tritonclient 提供了更好的工具(不幸的是,这个工具需要编译才能在 Ubuntu 18.06 上工作。2021 年不要像 AWS 一样,用最新发布的 Ubuntu!)(图片由作者提供)

以及 16(第一度量)和 128(第二度量)令牌的度量:

最终的结果,目标达到了!(图片由作者提供)

🎯我们成功了!1.5 毫秒用于 16 个令牌(相对于 1.7 毫秒拥抱脸无限),以及2 毫秒用于 128 个令牌长度(相对于 2.5 毫秒拥抱脸无限)。

我们已经构建了一个快速推理服务器,准备部署在我们的集群中。我们现在将欣赏 GPU 监控如何使自动扩展更容易设置,或者成熟的性能测量工具如何帮助我们修复管道中的瓶颈。对于机器学习从业者、初创公司和企业来说,这绝对是令人敬畏的。

那么现在,我们能对未来有什么期待呢?

结尾部分

与你将在一些媒体上读到的不同,许多人认为机器学习社区仍处于起步阶段。特别是,有一个话题一再出现,即大多数机器学习项目从未在生产中部署,它只是机器学习爱好者的营销内容和帖子,就像在为什么 90%的机器学习模型从未进入生产为什么 87%的数据科学项目从未进入生产?为什么 ML 车型很少投产,你能做些什么等。

很明显,有人用 GPT-9 生成了这些内容。如果你知道哪里可以下载 GPT-9 的重量,请给我一个下午:-)

我怀疑是否有人能真正衡量它,但可以肯定的是,关于 NLP 模型部署的严肃文章太少了。我希望你喜欢这个,并且我希望,如果你有时间,也许你可以在 Medium 或其他地方与社区分享你的优化/部署经验。在 NLP 中有如此多的其他重要事情需要解决,CPU/GPU 部署在 2021 年应该不是一个挑战。

作为一个社区,我们还需要关键人物的适当沟通,即使是在向企业销售产品时。例如,像“部署和加速 20 毫秒延迟下的 BERT 模型需要 2 个月 x 3 名高技能 ML 工程师”这样的消息错过了关键的技术细节(模型、输入大小、硬件),使得任何比较都不可能。此外,称这些工程师“技术高超”,但在几个月的工作后仍然无法实现他们的目标,这意味着恐惧、不确定性和对我们自己做同样事情的能力的怀疑。

最后,我们需要更多针对开源工具中 NLP 模型的推理优化!

在双 LSTM/GRU &朋友时代,在几年时间里,好像每个月都有一个大的架构变化。然后变形金刚来了,吃了大部分 NLP 任务。仍然有一些架构变化,拥抱脸变形金刚库在这里帮助机器学习从业者跟随炒作,而无需在代码重写方面进行大量投资。

我有一种感觉,模型架构现在已经稳定下来,社区中对错过最新流行架构的担心正在减少。

换句话说,如果您的工具箱中已经有一个 Roberta、一个像 miniLM 这样的提炼模型,以及一个像 T5 或 Bart 这样的生成模型,那么您可能可以使用大多数工业 NLP 用例 1 或 2 年。

这对机器学习从业者来说是个好消息,因为这种稳定为微软、英特尔、英伟达和其他公司优化 NLP 模型的努力打开了大门。延迟时间的大幅减少或吞吐量的大幅增加不仅会转化为更低的成本推断,还会带来新的用途和新产品。我们还可能希望有一天,我们甚至可以使用那些据称能够做许多令人敬畏的事情的非常大的语言模型(那些有数千亿个参数的模型)。我个人相信这将会发生,因为开发 NLP 用途符合硬件制造商和云提供商的利益,并且他们有资源和知识来做这些事情。

拥抱面部变形金刚:为二进制分类任务微调蒸馏瓶

原文:https://towardsdatascience.com/hugging-face-transformers-fine-tuning-distilbert-for-binary-classification-tasks-490f1d192379?source=collection_archive---------0-----------------------

TF 2.0 中 NLP 和迁移学习的初学者指南

抱脸和 TensorFlow 2.0。来源

1.0)简介

创建高性能的自然语言模型既耗时又昂贵。毕竟,谷歌大脑背后的团队花了 3.5 天在 8 个特斯拉 P100 GPU 上训练了著名的 BERT-large 模型的所有 3.4 亿个参数,自 2018 年成立以来,自然语言模型的复杂性只增不减。

最近的自然语言模型的大小,以百万计的参数。来源

但是如果一个公司没有培养如此庞大的庞然大物所需的资源呢?嗯,由于迁移学习的最新进展(这种技术以前在计算机视觉中得到了很好的确立,只是最近才在 NLP 中得到应用),公司可以通过简单地将预训练的模型用于自己的自然语言任务来更容易地实现最先进的性能。

在这篇文章中,我想分享一个实际的例子,告诉你如何使用 Tensorflow 2.0 和优秀的拥抱面部变形器库,通过指导你如何在你自己独特的数据集上微调 DistilBERT 进行序列分类任务。

是的,我可以使用拥抱脸 API 来选择一个更强大的模型,如伯特罗伯塔伊莱克特拉MPNET艾伯特作为我的起点。但是我为这个项目选择了 DistilBERT,因为它占用的内存更少,推理速度更快。与它的堂兄弟相比, DistilBERT 的 6600 万个参数使它比 BERT-base 小 40%,快 60%,同时保留了 BERT 95%以上的性能。这使得 DistilBERT 成为寻求在生产中扩展其模型的企业的理想候选,甚至高达超过 10 亿的每日请求!正如我们将看到的,DistilBERT 通过适当的微调可以表现得相当令人钦佩。说完了,让我们开始吧!

2.0)数据

对于这个项目,我将使用 Kaggle 上找到的 Jigsaw 毒性评论数据集的个人修改版本(我将数据集从多标签分类问题转换为二进制分类问题),来对评论是有毒还是无毒进行分类。

修改的 Jigsaw 毒性评论数据集的数据预览。图片由作者提供。

转换后,数据集表现出类别不平衡,有毒评论占所有数据的 9.58%。这是一个问题,因为任何天真的模型都可以简单地“学习”类分布,并且每次都预测大多数类,并且仍然获得 90.42%的准确性。因此,虽然这看起来像我们的模型是成功的,但它实际上在预测有毒评论(少数群体)方面完全无效,这根本不是我们想要的!

处理班级失衡的方法。来源

为了解决这个问题,我们将结合欠采样和过采样来平衡我们的类分布。

(注意:请确保事先分割您的数据,并且只对训练集进行过采样,以确保您的评估结果尽可能保持公正!

2.1)“不平衡”数据集

然而,重要的是要注意,当对多数类进行欠采样时,必须达到良好的平衡。如果我们欠采样太多,我们可能会因丢失有价值的训练数据而损害模型性能。但是如果我们采样过少(或者根本不采样),模型的预测可能偏向多数阶级,而无法预测少数阶级。

记住这一点,我试图通过对修改后的数据集进行欠采样来找到正确的平衡,直到有害评论占所有训练数据的 20%左右。这个数据集此后将被称为unbalanced dataset,它是我在这个特定问题上获得最佳实证结果的数据集。

“不平衡数据集”的类别分布。作者图片

2.2)“平衡”数据集

伴随着数据科学而来的是实验之美,我认为在完全平衡的数据集上微调 DistilBERT 也是富有成效的。这样做不仅可以完全消除不平衡的分类问题,而且我还希望将合成数据添加到我们的训练集中,可以让我们的模型推广到以前看不到的数据。

为此,我采用了unbalanced dataset的训练集,并对少数民族类进行了过采样,直到两个类都有大约 48,000 个代表性文本,从而创建了balanced dataset

通过单词替换的文本扩充的各种实现。来源

对于过采样,我使用 nlpaug 库通过使用 BERT 上下文嵌入的单词替换来执行数据扩充。根据您选择的语言模型,生成这种数据可能是一个缓慢的过程(该库目前支持 DistilBERT、BERT、RoBERTa 和 XLNet 的实现),但是该库提供了数据扩充的其他方法,分为三类:

  1. 字符级增强 ( 可以模拟文字中的错别字,同时考虑键盘距离
  2. 单词级扩充 ( 可以应用回译、随机插入或删除、单词拆分或基于同义词库的同义词替换)
  3. 句子级扩充 ( 可以使用下一句预测或抽象文本摘要生成句子)

不同训练集大小(N)的五个文本分类任务的平均性能增益。α参数的大致意思是“句子中每次扩充所改变的单词的百分比” SR: 同义词替换, RI :随机插入, RS: 随机互换, RD: 随机删除。来源

此外, nlpaug 不仅允许您控制如何生成新文本,而且还允许您控制所提供文本的多少、或百分之多少应该被修改以产生新生成的文本。

正因为如此,知道从哪里开始可能会有点混乱,但在 2019 年的论文“ EDA:提高文本分类任务性能的简单数据增强技术”中,作者提供了上图,供您的数据增强管道参考。出于我的目的,我选择通过替换给定文本字符串中大约 10%的单词来生成新句子(α = 0.1),但是超参数的最佳选择可能因您的特定数据集而异。尝试一下,看看效果如何!

要了解更多关于文本增强的信息,请阅读这篇文章:链接

注:使用。append()方法实际上效率很低,因为每次调用方法都要重新复制整个数据帧。相反,迭代地构建一个包含数据的字典,并调用。from_dict()方法来构造最终的数据帧。您可以在第 47–54 行看到我这样做。) 来源

不幸的是,在我的例子中,在balanced dataset上的训练实际上导致了更差的性能(可能是由于文本增强在小数据集上表现更好的事实),所以本文接下来的部分中的所有实验都将在unbalanced dataset上进行。

3.0)抱脸迁移学习

既然我们已经有了有序的数据集,是时候开始构建我们的模型了!为此,我们将充分利用迁移学习的力量,为我们的基础选择一个预训练模型,并在其上添加额外的层,因为它适合我们的分类任务。这是有效的,因为预训练模型的权重包含代表对英语的高级理解的信息,所以我们可以通过添加额外的层来建立这种一般知识,这些层的权重将代表对特定任务的理解,即什么使得评论有毒无毒

正如我们将看到的,拥抱脸变形金刚库使迁移学习变得非常容易,因为我们的一般工作流程可以分为四个主要阶段:

  1. 标记文本
  2. 定义模型架构
  3. 训练分类层权重
  4. 微调蒸馏瓶并训练所有重量

3.1)标记文本

一旦我们选择了一个预先训练好的模型,就该把人类可读的文本字符串转换成我们的模型可以解释的格式了。这个过程被称为记号化,直观的拥抱脸 API 使转换单词和句子→记号序列→可以转换为张量并馈入我们模型的数字序列变得极其容易。

伯特和蒸馏伯特记号化过程。特殊的[CLS]符号代表“分类”,并且将包含序列的句子级表示的嵌入。特殊的[SEP]标记代表“分离”,用于划分序列之间的界限。来源

一般来说,不同的预训练模型使用不同的方法来标记文本输入(在上图中,可以看到 DistilBERT 的 tokenizer 如何在其标记化方案中包括特殊的标记,如[CLS]和[SEP]),因此有必要实例化一个特定于我们选择的模型的标记化器对象。为了获得distilbert-base-uncased使用的记号赋予器,我们将模型的名称传递给DistilBertTokenizerFast类的.from_pretrained()方法。

(注意:拥抱脸提供了其标记化器的“慢”和“快”版本。“慢”版本是用 Python 编写的,而“快”版本是用 Rust 编写的,在执行批量令牌化时可以显著提高速度。在本文中,我们使用“快速”版本来利用这些性能优势。)

一旦我们实例化了我们的 tokenizer 对象,我们就可以使用 tokenizer 的.batch_encode_plus()方法批量编码我们的训练、验证和测试集。

我们可能希望设置的重要参数包括:

  • max_length →控制给定文本中要标记的最大字数。
  • padding →如果设置为“最长”,则填充到批次中最长的序列。
  • truncation →如果为真,则根据max_length设置的值截断文本。
  • return_attention_mask →如果为真,则返回注意屏蔽。这是可选的,但是注意掩码会告诉您的模型注意哪些标记,忽略哪些标记(在填充的情况下)。因此,将注意力屏蔽作为模型的输入可以提高模型的性能。
  • return_token_type_ids →如果为真,则返回令牌类型标识。对于一些需要多个序列作为输入的任务(例如,问题回答需要一个“问题”和一个“回答”序列),这是必需的,因为令牌 id 通知模型一个输入序列在哪里结束,另一个序列在哪里开始。然而,出于我们的目的,这是可选的,因为我们的分类任务只需要一个序列作为输入(潜在有毒的注释)。

如上面的代码所示,我创建的batch_encode函数最终返回:

  1. input_ids →编码为数字序列的文本单词。
  2. attention_mask →一个二进制序列,告诉模型注意input_ids中的哪些数字,忽略哪些数字(在填充的情况下)。

input_idsattention_mask都已经转化为 Tensorflow tf。张量对象,因此它们可以很容易地作为输入输入到我们的模型中。

3.2)定义模型架构

既然我们已经对训练、验证和测试集进行了编码,那么是时候定义我们的模型架构了。因为我们将使用 DistilBERT 作为我们的基础模型,我们从拥抱面部库导入distilbert-base-uncased开始。

初始化基础模型

重要的是,我们应该注意到拥抱脸 API 为我们提供了通过改变 DistilBERT 的配置类中的几个参数来调整基本模型架构的选项。这里,我们通过将dropoutattention_dropout从默认值 0.1 增加到新值 0.2 来实例化一个新的config对象,但是还有许多其他选项可供选择,所有这些都可以在特定于您所选模型的配置类的文档中找到。

在(可选地)修改了 DistilBERT 的配置类之后,我们可以将模型名称和配置对象传递给TFDistilBertModel类的.from_pretrained()方法,以实例化没有任何特定头部的基本 DistilBERT 模型(与其他类(如TFDistilBertForSequenceClassification)相反,这些类添加了分类头部)。我们不希望附加任何特定于任务的标题,因为我们只是希望基础模型的预训练权重提供对英语的一般理解,并且我们的工作将是在微调过程中添加我们自己的分类标题,以便帮助模型区分有毒评论。

因为 DistilBERT 的预训练权重将作为我们的模型的基础,所以我们希望在训练的初始阶段,当我们的模型开始为我们添加的分类层学习合理的权重时,保留并防止它们更新。要暂时冻结 DistilBERT 的预训练权重,请为 DistilBERT 的每个层设置layer.trainable = False,稍后一旦模型性能收敛,我们可以通过设置layer.trainable = True来解冻它们。

增加一个分类头

当我们构建我们的模型架构时,我们将在 DistilBERT 的嵌入层上添加一个分类头,我们在line 35中得到这个嵌入层作为模型输出。实际上,模型的输出是一个元组,包含:

  1. last_hidden_state →形状的词级嵌入( batch_sizesequence_lengthhidden_size =768)。
  2. hidden_states →【可选】tf 的元组。形状( batch_sizesequence_lengthhidden_size =768)的张量(一个用于嵌入的输出+一个用于每层的输出)。当我们在配置文件中设置output_hidden_states=True时返回。
  3. attentions →【可选】attention softmax 之后的 Attention 权重,用于计算自我关注头部的加权平均值。当我们在配置文件中设置output_attentions=True时返回。

我们选择这个元组的索引 0 来访问last_hidden_state,而不是访问其他层的隐藏状态,因为建立这种嵌入通常会导致最佳的经验结果。⁴

微调 IMDb 电影评论数据集上不同层的伯特。来源

每个隐藏状态都是一个 tf。形状张量( batch_sizesequence_lengthhidden_size =768),包含 DistilBERT 的 12 层之一的单词级嵌入输出。因此,在我们的例子中,最后一个隐藏状态将是(64,128,768)的形状,因为我们设置了BATCH_SIZE=64MAX_LENGTH=128,并且 DistilBERT 的隐藏大小为 768。

带有以红色突出显示的[CLS]标记的“最后隐藏状态”的形状。来源

我应该强调的是,嵌入中的所有 128 个序列标记提供了一种单词级的理解,并且人们可能能够从 3D 嵌入中提取大量信息,也许使用双向 LSTM 和 max-pooling 层,如本文中所执行的。

然而,出于我们的目的,我们将通过只查看这 128 个记号中的第一个:[CLS]记号来利用 DistilBERT 的 T20 句子级的对序列的理解。代表“分类”,[CLS]令牌起着重要的作用,因为它实际上存储了一个句子级嵌入,这对预训练阶段的下一个句子预测 (NSP)很有用。因此,我们可以通过截取一段last_hidden_state来访问第 41 行中的句子级嵌入,这样我们就剩下一个代表整个文本序列的 2D 张量。

[CLS]标记的句子级嵌入。来源

为了获得我们模型的性能基线,我们可以从在[CLS]令牌的句子级嵌入之上添加一个带有sigmoid 激活函数的单个密集输出层开始。最后,我们编译模型,将 adam optimizer 的学习速率设置为 5e-5(原始 BERT 论文的作者推荐 3e-4、1e-4、5e-5 和 3e-5 的学习速率作为良好的起点),并将损失函数设置为焦点损失而不是二进制交叉熵,以便正确处理我们数据集的类不平衡。

(注意:tf.keras 不提供焦损作为你可以使用的内置函数。相反,您必须将焦点损失实现为您自己的自定义函数,并将其作为参数传入。请看 这里 了解焦损如何工作,看 这里 了解我使用的焦损功能的实现。)

3.3)训练分类层权重

好了,我们终于建立了我们的模型,所以我们现在可以开始训练分类层的随机初始化权重,直到模型性能收敛。在只有一个输出层的简单基线模型的情况下,在 6 个时期内训练所有 768 个可用权重(因为所有 DistilBERT 的权重都是冻结的)会导致测试集上的准确度为 85.7%AUC-ROC 得分为 0.926 。对于一个只用几行代码训练出来的模型来说,这已经不错了!

然而,我们肯定可以做得更好,在这个阶段我们可以考虑的一件事是改变我们的模型架构。毕竟,我们的模型在这一点上非常简单,只有一个单一的输出层在 DistilBERT 之上,所以在它们之间添加额外的密集和/或下降层可能是一个好主意。

我通过使用 Comet.ml API 执行网格搜索,对两个密集层执行此操作,并发现针对我的特定分类问题的最佳模型架构如下所示:

[DistilBERT CLS Embedding Layer] + [Dense 256] + [Dense 32] + [Single-node Output Layer]

每层之间的压差为 0.2。

网格搜索每个密集层中的节点数。图片由作者提供。

由于这一变化,我们的新模型通过仅训练添加的分类层,在测试集上获得了 87.3% 的准确度和 0.930AUC-ROC。

3.4)微调蒸馏器并训练所有权重

一旦我们完成对添加的分类层的训练,我们可以通过解冻 DistilBERT 的嵌入层并以较低的学习速率微调所有权重(以防止对预训练的权重进行重大更新)来从我们的模型中挤出更多的性能。注意在解冻层权重后,有必要重新编译我们的模型,但是除此之外,训练过程看起来与上一步相同。

作为微调 DistilBERT 预训练权重的结果,我们的模型在测试集🥳上实现了 92.18% 的最终准确度和 0.969AUC-ROC🔥🎉。

4.0)结论

正如两分钟论文中的卡罗里·佐尔奈-费尔博士所说…

“活着是多么美好的时光啊!”

正如你所看到的,激动人心的时刻即将到来,因为任何人只要有机会接触计算机,就可以利用最先进的、价值数百万美元的预训练模型,只需相对较少的几行代码。这种易用性是快速开发和模型部署的关键,小型模型(如 DistilBERT)的紧凑特性使它们可以扩展并能够产生实时结果,同时仍然保持高水平的性能。

如果 DistilBERT 还不够快,那么可以使用权重量化和使用 ONNX 运行时的模型服务来进一步优化推理速度,但是,唉,我太超前了,因为这是未来文章的主题。

无论如何,我希望本文中的代码和解释是有帮助的,我希望你现在和我一样对 NLP 和拥抱脸变形金刚库感到兴奋!如果您喜欢这些内容,请随时在 LinkedIn 上与我联系,在 Kaggle 上找到我,或者在 GitHub 上查看代码。

祝你在 NLP 领域好运,并祝你编码愉快!

5.0)参考文献

[1] A. Vaswani 等人,注意力是你所需要的全部 (2017),arXiv:1706.03762

[2] V. Sanh 等人,蒸馏伯特,伯特的蒸馏版:更小、更快、更便宜、更轻 (2019),arXiv:1910.01108

[3]魏军,邹凯, EDA:提高文本分类性能的简易数据增强技术 (2019),arXiv:1901.11196

[4] C. Sun 等,如何微调用于文本分类的 BERT? (2019),arXiv:1905.05583

在苹果 M1 上安装拥抱脸变形金刚

原文:https://towardsdatascience.com/hugging-face-transformers-on-apple-m1-26f0705874d7?source=collection_archive---------4-----------------------

以及 Tensorflow 和 Tokenizers 包

大卫·拉托雷·罗梅罗Unsplash 上拍摄的照片

不是所有的事情都来得容易。向苹果 M1 公司的过渡也有类似的故事要讲。尽管我喜欢这种速度,但我讨厌不得不寻找非传统的方法来安装传统的库,否则在命令提示符下只有一行代码。

如果你是苹果 M1 用户,并与 NLP 密切合作,有可能你以前遇到过这种情况,甚至找到了解决方案,但如果没有,或者你最近加入了 M1 党,这篇文章提供了一种方法,你可以在你的 MacBook 上安装 M1 芯片拥抱脸变压器。而且不,不是pip install transformers

启动和运行变压器有三个步骤。

  1. 安装 Tensorflow
  2. 安装 Tokenizers 包(带 Rust 编译器)
  3. 安装变压器包

虽然它的工作,请考虑研究更可靠的方法来安装变压器-写于 2021.10.25

1.张量流

安装 tensorflow 很容易,你只需指向你现有的虚拟 env,或者你可以创建一个新的来玩,或者如果你不想创建一个新的,它会为你创建一个。

  1. 创建并启用 虚拟环境

如果您还没有 virtualenv 软件包,请安装它

pip install virtualenv

通过键入以下命令创建 virtualenv

python virtualenv venv --python=python3

要启用虚拟环境

source venv/bin/activate

2.下载

点击从下载最新版本。确保下载包含安装脚本的tar.gz文件。在撰写本文时,最新的版本是 tensorflow-macos 0.1 alpha 3。没错,是 tensorflow-macos,而不是 tensorflow。

3.安装

一旦有了脚本,转到下载目录并运行下面的命令./install_venv.sh --prompt。它会询问您虚拟环境文件夹的路径,请提供我们创建的路径。您也可以让它创建另一个,但在我看来,创建我们打算使用的或我们已经拥有的总是更好。

输入虚拟环境的路径

已成功安装 tensorflow-macos

注意——你可以通过 tensorflow-metal 利用 M1 加速训练你的机器学习模型。如果你是这种情况,请点击了解更多信息

2.标记化者

我们将从源代码中构建标记化器以避免任何中断,我确信如果我们决定不这样做,它将会出现。这里有几个步骤,所以当你跟着做的时候要精确。

2.1 安装防锈语言

我们需要安装 Rust 来从源代码安装令牌化器。您可以通过键入以下命令来做到这一点

curl --proto '=https' --tlsv1.2 -sSf [https://sh.rustup.rs](https://sh.rustup.rs) | sh

您可以在安装后按照命令提示符下的说明配置当前的 shell,或者您可以打开另一个会话来查看它的效果。

2.2 安装令牌化器

一旦我们有了 Rust,我们就可以下载令牌化器的源代码

git clone [https://github.com/huggingface/tokenizers](https://github.com/huggingface/tokenizers)

转到 python 绑定文件夹cd tokenizers/bindings/python

确保您已经安装并激活了虚拟环境,然后键入以下命令来编译令牌化器

pip install setuptools_rust

最后,安装令牌化器

python setup.py install

3.变形金刚(电影名)

现在终于,你可以安装变压器了

pip install git+https://github.com/huggingface/transformers

瞧,变压器安装成功

结束注释

最近我一直在试图弄清楚如何在苹果 M1 上安装许多东西,当我弄清楚的时候,我试图记下它,以方便其他可能有同样问题的人。希望这对你有所帮助,如果你有任何反馈或正在为任何其他安装而挣扎,请随时联系联系,也许我有一个解决方案,但没有机会写下来。快乐学习。

亚马逊 SageMaker 上的拥抱脸处理工作

原文:https://towardsdatascience.com/huggingface-processing-jobs-on-amazon-sagemaker-b1f5af97b663?source=collection_archive---------29-----------------------

以可扩展和可再现的方式为 NLP 管道准备文本数据

UnsplashWonderlane 拍摄的照片

这是怎么回事?

最新版本的SageMaker Python SDK(v 2 . 54 . 0)引入了 HuggingFace 处理器,用于处理作业。这些处理作业可用于在 Amazon SageMaker 上运行数据预处理或后处理、特征工程、数据验证或模型评估的步骤。

HuggingFace 处理器对于基于 HuggingFace 的 Transformer 模型的 NLP 管道非常有用。深度学习容器(DLC)预装了所有必需的依赖项,并针对典型的 HuggingFace 数据转换(如标记化)进行了优化。在本教程中,我们将看看这些处理器,并了解如何利用它们来准备文本数据,以训练变压器模型。

和往常一样,本教程的代码可以在 GitHub 上获得。

拥抱脸+ SageMaker:简要概述

2021 年 3 月,Huggingface 和 AWS 宣布了一项合作伙伴关系,这使得在亚马逊 SageMaker 上训练最先进的 NLP 模型变得更加容易。有了新的拥抱脸训练 DLCs,训练基于变形金刚的 NLP 模型变得简单多了。7 月,这种集成得到了扩展,在 SageMaker 上增加了变形金刚模型的简单部署和推断。现在,在 2021 年 8 月,Sagemaker Python SDK 为这种集成添加了另一个构件, Huggingface 处理器

为什么这很重要?

HuggingFace 处理器允许我们在容器化的图像中准备文本数据,该图像将在专用的 EC2 实例上运行。这有两个主要好处:(1)对于大型数据集,数据准备可能需要很长时间。选择专用的 EC2 实例允许我们为手头的任务选择合适的处理能力。(2)通过处理作业对数据准备进行编码,使我们能够以可扩展和可再现的方式将数据处理步骤集成到用于 NLP 任务的 CI/CD 管道中。

下载和检查数据集

既然已经说了,让我们开始吧!我们的目标是准备一个数据集,以便在稍后的某个时刻,可以用这个数据训练一个二元情感分类器。该分类器将文本作为输入,并预测文本中的情感是积极的还是消极的。为此,我们将在本教程中利用亚马逊客户评论数据集

该数据集包含各种类别的评论,在本教程中,我们将使用数字软件的评论。我们可以从一个公开的 S3 文件夹中下载数据,先看一看:

作者图片

我们可以看到在这个数据集中有相当多的列,其中大部分在我们的模型中并不需要。这意味着我们将不得不丢弃这些列。由于我们希望训练一个二进制分类器,我们还需要将星级转换为二进制值,即 0 和 1,它们将分别代表负面和正面的评论。在本教程中,我们将使用 4 颗星的阈值将评级转换为二进制值。这意味着,每一个 4 或 5 星的评分将被标记为正面评价,而每一个低于 4 星的评分将被视为负面评价。为了准备 Transformers 模型的数据,我们还想对数据进行标记。最后,我们希望将数据分成训练、验证和测试数据。

所有这些逻辑都将被捕获到处理脚本中,你可以在这里找到。本教程的重点是利用 HuggingFace 处理器,而不是数据准备本身,所以我不会深入讨论处理脚本的细节。但是,如果你对剧本有任何疑问,请随时联系我们!

使用 HuggingFace 处理器

既然我们已经开发了处理脚本,我们可以使用 Sagemaker Python SDK 来启动处理作业。首先,我们需要定义处理作业

我们定义要运行它的实例,以及需要多少个实例。如果数据处理任务繁重,并且有大量数据,那么提供多个实例可能是有意义的。

接下来,我们需要定义处理作业的输入和输出,以及作业的参数:

最后,我们可以开始培训工作了:

作业启动后,我们可以在 Sagemaker 控制台中看到它正在运行:

作者图片

几分钟后,工作完成了。控制台将提供关于处理作业的许多细节,例如使用了哪个容器映像,以及处理后的数据存储在 S3 的什么位置。我们还可以通过 SageMaker Python SDK API 以编程方式收集这些数据点。例如,我们可以轻松地检索已处理数据的 S3 位置:

作者图片

结论

在本教程中,我们成功地利用 Sagemaker 处理作业来处理 Transformer 模型的数据。这个处理作业现在可以合并到 NLP 管道中,每次新的训练数据到达时,处理作业就开始。现在,数据已经过处理和标记化,可以很容易地用于训练 HuggingFace Transformer 模型。

用张量流进行活动分类

原文:https://towardsdatascience.com/human-activity-recognition-with-tensorflow-4e5c040208e2?source=collection_archive---------21-----------------------

实践教程

用六周时间利用深度学习创建一个身体行为分类模型。

丁满·斯图德勒Unsplash 上拍摄的照片

开始:为期 42 天的项目

几个月前,我读了丹尼尔·伯克的一篇文章,内容是关于使用 Detectron 2 复制 Airbnb 的舒适度检测系统。

这篇文章概述了 Daniel 运行 42 天(6 周)的短期项目的过程,最初是由 Basecamp 开发的,目的是尝试快速发布有用的软件。

https://basecamp.com/shapeup/webbook

为什么是 6 周?

因为 42 天的时间足够完成一些有用的事情,但也不会长到如果没有效果,你就浪费了大量的时间。

我喜欢这个主意。

很长一段时间以来,我一直试图在我的研究工作之外学习数据科学和机器学习,我一直在努力寻求学习和实践之间的平衡。我一直试图通过完成课程来提高我的技能,但我的努力没有任何表现。我知道我需要离开单调的教程,开始构建展示我的数据科学知识的项目。

所以我给自己设定了开发深度学习模型的任务。

我是深度学习的新手。我知道神经网络如何工作的基础,但我不太了解开发这些模型的工具和技术。我决定使用 TensorFlow 。之前听说过,知道是深度学习社区里用的比较好的库。

但是我需要一个创建模型的理由…

最近,我一直在从事一项人类活动识别研究项目,试图利用小腿上的加速度计数据对下肢截肢者的姿势进行分类。传统的方法是使用来自大腿的加速度数据。当你可以使用重力加速度来区分关键姿势时,区分坐姿和站姿要容易得多。但小腿是安装加速度计的最佳位置,因为它可以放在假肢内。这样做的问题是,小腿数据使得很难区分坐和站,因为设备的方向对于两种姿势是相同的。

作者图片:传统加速度计大腿佩戴位置与新型小腿佩戴位置的对比

作为研究项目的一部分,我尝试使用浅层机器学习模型、k-最近邻算法和手工制作的特征来区分姿势。

学者喜欢他们能解释的模型!

但是这个模型很难区分坐着和站着。很明显,我的特征不能区分这两种姿势。

所以这是一个完美的机会来尝试深度学习,看看它是否能解决我的问题。我已经收集了一些关于我自己和一些朋友的数据,所以我知道我可以马上开始做事。

我打开 idea,开始制作项目模板。除了正常的工作日,我估计每个工作日我会花大约 2 个小时在这个项目上。

最坏的情况是,我不能让模型工作,我会知道这是我需要关注的事情。

最好的情况是,我会做一个模型,打破我以前的研究成果,并有一个新的项目要写。

不管怎样,比起继续做教程,6 周的工作会让我有更多的东西可以展示。

给读者一个提示,这篇文章是对所发生的事情的高层次叙述,其中掺杂了一些技术。对于像我这样的书呆子来说,代码可以在 Github 仓库中找到。

分解项目

观念是我管理项目的首选工具。很容易定制页面以适应任何应用程序,并有大量的项目管理内置功能。

我在整个项目生命周期中使用它来保持我的进度和组织性。看看我的项目结构和每日日志:观念页

鉴于我有 6 周的时间来做这个项目,我决定把它分成以下几个阶段:

  1. 开始:计划和探索问题。
  2. 创建数据处理软件。
  3. 获得使用 TensorFlow 的基本模型。
  4. 使用研究论文创建最佳模型。
  5. 部署模型,以便其他人可以使用它。
  6. 评估工作,清理代码,写这篇文章。

所以,我们已经讨论了项目的规划和组织。让我们开始写一些代码。

处理数据

像所有好的机器学习项目一样,它始于数据,止于数据。

幸运的是,我已经从一些愿意的朋友那里收集到了数据,他们很乐意让我使用这些数据,并为本文提供这些数据。

数据是从戴在小腿上的三轴加速度计和戴在大腿上的活动监视器收集的。我的计划是使用戴在大腿上的设备在整个数据收集期间给我准确的姿势测量,并尝试使用小腿加速度来预测姿势。

我需要将数据分成 15 秒的窗口,每个窗口有 3 个轴的加速度数据和相应的真实姿态代码。这可能是四种姿势中的一种;坐着、站着、走着或躺着。

为此,我想创建一个面向对象的系统。

我是一个自学成才的程序员。我学会了编码,这样我就可以为研究项目处理数据,我对它的热情也从那时开始增长。

所以我不得不艰难地学习。

使用不同编程方法的缺点,通过正规教育学习时你被教导要避免的常见错误。

但是尽管我以前涉足过 OOP,我从来没有做过一个我认为真正需要 OPP 的系统。然而,这是一个很好的机会。我可以想象不同的“对象”,它们负责处理的各个阶段,它们的方法和属性。

我创建了一个代表设备本身的对象,一个负责数据标签(如果存在)的“姿态堆栈”,一个负责分离出原始数据的数据集,以及一个能够进行预测和评估准确性的模型。

这些对象很容易扩展,例如,创建不同长度的窗口或使用不同的模型根据数据进行预测。

现在我所需要担心的是数据的加载。

不幸的是,设备将文件导出为 CSV 格式,每 20 秒采样一次的 5 天 3 轴加速度数据的问题是,您会留下一些大型 CSV。

我尝试了几种不同的导入数据的方法,但我唯一的选择是使用 pandas 将数据分成块。这太慢了…非常慢。

如果有人有更快的方法导入这些数据,请告诉我。

这里也有逻辑来处理我在 CSV 头中观察到的一个奇怪的问题。

总之,经过 12 个多小时的处理后,我已经准备好开始玩 TensorFlow 了。

学习深度学习

我将数据保存为 2 个 numpy 数组;1 包含带有形状的原始加速度数据…

(number of epochs, 295, 3)

其中 295 代表原始加速度数据(15 秒* 20 个样本,其中 5 个样本被丢弃,以确保所有的时间点具有相同的形状),3 代表 3 个加速度数据通道。另一个数组包含相应的姿势代码,可能是 4 个值(0-3)中的一个。

为了让事情进行下去,我建立了一个谷歌实验室笔记本,并输入我的数据开始实验。

首先,我需要确保我的数据格式正确。幸运的是,在看了一些教程后,我知道我需要将我的数据转换成张量。据我的理解,张量是 x 维 numpy 数组,便于 CPUs & GPUs 进行深度学习的接口,这就是为什么我确保将我的数据保存为 numpy 数组,以便于转换。

我还需要确保我的姿态代码是一个热编码,我的加速度数据是正常的,我删除了任何姿态代码和相应的数据,我不想在我的模型。如果您对额外处理的细节感兴趣,或者想要进行自己的实验,请查看 collab 笔记本。

https://colab.research.google.com/github/Ben-Jamin-Griff/AmputeePostureClassification/blob/main/notebooks/amputee_posture_classification_experiments_deep.ipynb [## 姿势分类实验

colab.research.google.com](https://colab.research.google.com/github/Ben-Jamin-Griff/AmputeePostureClassification/blob/main/notebooks/amputee_posture_classification_experiments_deep.ipynb)

现在是试验不同模型的时候了。

我尝试复制了一个在 TensorFlow 教程中找到的模型,并很快了解到确保数据具有正确的形状并正确输入到输入层非常重要。程序不仅会在训练时抛出错误,还会影响模型的准确性。

INPUT_SHAPE = X_train.shape[1:]INPUT_SHAPE_RESHAPED = X_train_reshaped.shape[1:]OUTPUT_SHAPE = len(unique_classes_train)input shape: (295, 3) 
input shape reshaped: (1, 295, 3) 
output shape: 4

在这里,我创建了两个不同形状的不同输入数据集,您马上就会明白为什么。

我设法让我的第一个基本模型工作。

dnn_model = tf.keras.Sequential([
tf.keras.Input(shape=INPUT_SHAPE_RESHAPED),
tf.keras.layers.Dense(100, activation=’relu’),
tf.keras.layers.Dense(100, activation=’relu’),
tf.keras.layers.Dense(100, activation=’relu’),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(OUTPUT_SHAPE, activation=’softmax’)],
name=’DNN-Model’)

我想比较我的所有模型,所以我创建了一个函数,使用相同的参数来训练和保存模型。

callback = tf.keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=3)EPOCHS = 50model_to_train.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])history = model_to_train.fit(X_train, y_train, epochs=EPOCHS, validation_split=0.2, batch_size=32, callbacks=[callback], verbose=1)

我使用了 50 个历元和一个早期停止回调来防止过度拟合。分类交叉熵是多类分类的标准损失函数,adam 优化器是典型的优化函数。

该模型工作得相当好,并在训练集上实现了 87%的准确度(f1 分数)。

对于第一次尝试来说还不错。让我们来看看混淆矩阵

图片作者:第一个深度神经网络的混淆矩阵

我们可以看到,该模型在踩踩中工作良好,正如我们所预期的那样,因为信号非常不同。然而,它更难区分坐着和站着,因为姿势是静态的,设备的方向也是一样的。

我们可以做些什么来改进这种模式?嗯,我挖了一些关于人类活动识别的研究论文,发现卷积神经网络(CNN)被频繁使用。

CNN 通常与图像分类相关联,并对像素值执行卷积和汇集阶段,以便更容易识别图像中的特定特征。这似乎可以转化为多轴传感器数据,并比单独的 DNNs 做出更好的模型。

在浏览了一些在线教程后,我设法安装并运行了一个。

cnn_model = tf.keras.Sequential([tf.keras.layers.Conv2D(32, kernel_size = (1, 12), strides = (1, 1), input_shape=INPUT_SHAPE_RESHAPED, padding=”valid”),
tf.keras.layers.MaxPooling2D((1,4), (1, 2)),tf.keras.layers.Conv2D(64, kernel_size = (1, 4), strides = (1, 1), input_shape = (1, 295, 3), padding=”valid”), tf.keras.layers.MaxPooling2D((1,4), (1, 2)), tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation=’relu’),
tf.keras.layers.Dense(OUTPUT_SHAPE, activation=’softmax’)],
name=’CNN-Model’)

这就是为什么我创建了一个经过改造的训练数据版本。卷积需要一个四维张量,所以我需要稍微不同地安排我的数据。

其余的参数取自 CNN 模型的前几个例子,我仍然不确定除了实验之外,你是如何做出这些决定的。

如果任何人有这方面的信息,那么我很乐意听到它。

反正这个模型比我之前 84%准确率的模型略差。

非常令人失望,因为我认为这将使我的模型更好,我只能假设我没有优化参数,或者我的数据不需要优化这种类型的模型。

然而,我还想尝试最后一件事。

在我寻找论文的过程中,我可以看到一些关于循环神经网络(RNN)的信息。这些方法利用时间事件来改进未来的预测。它们经常用在自然语言处理(NLP)中,其中每个前面的单词都可以用来提高对下一个单词的预测,因为它们密切相关。

这对于我的模型非常有意义,因为前一个活动与下一个活动密切相关。如果你坐着,除非你站起来,否则你不能开始走路,反之亦然。

我开始建造另一个模型。幸运的是,TensorFlow 很容易就创建了这个,因为他们有一个专门针对长短期记忆(LSTM) RNNs 的层。

lstm_model = tf.keras.Sequential([
tf.keras.layers.LSTM(128, input_shape=INPUT_SHAPE),
tf.keras.layers.Dense(100, activation='relu'),
tf.keras.layers.Dense(OUTPUT_SHAPE, activation='softmax')],
name='LSTM-Model')

该模型的准确率比前三个模型提高了 88%。成功!🥳

我成功创建了 3 个模型,使用了 3 种不同类型的深度学习。

但是我已经非常接近难以捉摸的 90%的准确率了。

是时候求助于专业人士了,看看他们是否能帮我改进我的模型。

站在巨人的肩膀上

我需要了解其他人如何将这些不同的深度学习模型应用到我的应用程序中。

我已经查看了一些以前与 HAR 相关的研究论文,但这些论文没有提供我用 TensorFlow 复制他们的模型所需的详细程度。

在网上搜索代码示例和教程后,我看到了这篇关于机器学习大师的文章。

Jason 详细介绍了他用来训练活动分类模型的开放访问数据集,以及可用的不同算法、它们如何工作的一些信息和代码示例。

这太完美了!

它们与我已经使用过的算法非常相似,但是扩展到结合了各自的特性。

我开始写代码,在我的数据上尝试这些模型。查看下面的新笔记本。

https://colab.research.google.com/github/Ben-Jamin-Griff/AmputeePostureClassification/blob/main/notebooks/amputee_posture_classification_experiments_deep_mlm.ipynb [## 姿势分类实验-MLM

colab.research.google.com](https://colab.research.google.com/github/Ben-Jamin-Griff/AmputeePostureClassification/blob/main/notebooks/amputee_posture_classification_experiments_deep_mlm.ipynb)

我决定坚持使用相同的训练超参数,这样我就可以将它们与我以前的模型进行比较。

新模型包括另一个具有不同参数的 LSTM 模型、一个组合的 CNN-LSTM 模型和一个卷积 LSTM 模型。

需要一些额外的预处理来将我的数据变成正确的形状以执行卷积,这可能是为什么我以前的 CNN 模型在提高最佳精度方面不成功的原因。

mlm_lstm_model = tf.keras.Sequential([
tf.keras.layers.LSTM(100, input_shape=INPUT_SHAPE),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(100, activation=’relu’),
tf.keras.layers.Dense(OUTPUT_SHAPE, activation=’softmax’)],
name=’MLM-LSTM-Model’)mlm_cnn_lstm_model = tf.keras.Sequential([
tf.keras.layers.TimeDistributed(tf.keras.layers.Conv1D(filters=64,kernel_size=3, activation=’relu’),input_shape=INPUT_SHAPE_RESHAPED_1),
tf.keras.layers.TimeDistributed(tf.keras.layers.Conv1D(filters=64, kernel_size=3, activation=’relu’)),
tf.keras.layers.TimeDistributed(tf.keras.layers.Dropout(0.5)),
tf.keras.layers.TimeDistributed(tf.keras.layers.MaxPooling2D(pool_size=2)),
tf.keras.layers.TimeDistributed(tf.keras.layers.Flatten()),
tf.keras.layers.LSTM(100),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(100, activation=’relu’),
tf.keras.layers.Dense(OUTPUT_SHAPE, activation=’softmax’)],
name=’MLM-CNN-LSTM-Model’)mlm_convlstm_model = tf.keras.Sequential([
tf.keras.layers.ConvLSTM2D(filters=64, kernel_size=(1,3), activation=’relu’, input_shape=INPUT_SHAPE_RESHAPED_2),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(100, activation=’relu’),
tf.keras.layers.Dense(OUTPUT_SHAPE, activation=’softmax’)],
name=’MLM-ConvLSTM-Model’)

LSTM 模型和我自己的版本有同样的性能,88%的准确率…没有任何改进。

然而,合并后的 CNN 和 ConvLSTM 分别取得了 90%和 91%的进一步改善。

来源: Giphy 。机器学习大师坦克弗兰克

成功了!我设法超过了 90%的准确率。查看混淆矩阵,我们可以看到每个类的预测准确性都有很大的提高。

图片作者:最终混乱矩阵

我认为我还可以对这个模型进行改进。我本可以探索加速度数据的进一步预处理,或者我本可以尝试更多地调整我的超参数。

但我决定今天就到此为止,并开始思考如何让其他人也能接触到这种模式。

做预测

当我决定开始这个项目时,我知道我不能让我的模型死在 Colab 笔记本里。

我看过太多机器学习工程师的 youtube 视频,他们谈论创建端到端项目以在此结束有多么重要。

所以我需要思考如何让其他人也能使用这个模型。

在这个项目的开始,当我创建我的 OOP 软件时,我考虑了这个模型的潜在用户,并意识到他们可能只包括我和其他研究人员。

工具和数据太专业了,以至于不能让每个人都可以使用。

因此,尽管我很想尝试在 Streamlit 应用程序上运行我的模型,我还是决定将我最好的模型整合到我的 OOP 软件中。这样,任何想要使用该软件对未标记的小腿数据进行预测的研究人员都可以从 GitHub 下载该软件并运行示例脚本。

正如所言,这相当简单,我可以简单地将 TensorFlow 导入到我的模型类中,选择我想要进行预测的模型,并向它显示新的加速度数据。

然而,这些预测的结果相当无聊。我想创造一些东西,在一个简单的情节中可视化几天的姿势预测。

我的一个同事最近完成了一个类似的项目,研究上肢假肢的使用,并探索使用螺旋图来可视化加速度数据。

这非常有意义,螺旋的每个周期可以代表一天,我可以用不同的颜色来代表姿势。

我求助于可靠的 StackOverflow,发现了一个非常有用的帖子,是关于使用 Matplotlib 实现不同螺旋图的例子。

我将它添加到一个新的绘图类中,该类可以被其他类继承以满足一系列绘图需求。

这是一种享受🍰

现在,我可以查看我的姿势分类器的输出,并分析多天内的不同姿势。

图片作者:姿势:蓝色=躺下,绿色=坐着,黄色=站着,红色=迈步

我做到了!我实现了这个项目开始时设定的目标。

我有一个系统来创建深度学习模型,并做出比我之前的研究更好的姿势分类预测。

我学到了什么?

那是有趣的 6 周!

42 天项目想法是一个很好的大纲,让你有足够的时间来完成一个小项目,而不必在一个想法上投入几个月的时间。这对我非常有用,因为我有很多东西想在机器学习中尝试和学习。

以前,我试图通过教程学习,并将重点放在个别主题上,如数据库或图书馆,如熊猫。

基于项目的工作是以应用的方式学习所有这些东西的更好的方式,并帮助你记住它们为什么有用以及它们是如何实现的。

此外,在项目结束时,您会留下一个原始代码库,并且可能会留下一个您自己创建的产品。这比完成一个教程更好地展示了你的技能,在这个教程中,你生成的代码和其他跟随教程的人是一样的。

我肯定会在我的下一个想法中使用 42 天项目计划,我甚至会尝试将它融入到我生活的其他领域,比如健身训练或学习新技能。

在过去的 6 周里,我学到了很多,包括:项目管理,构建 OOP 软件,处理数据,为深度学习准备数据,构建 TensorFlow 模型,评估模型,调整模型,最后在项目内实现深度学习。

我也学到了很多关于记录和写作我的作品的知识,我计划在我所有的副业项目中继续这样做。

我希望这是一个有趣的阅读,这将是伟大的工作得到您的反馈。

下一步是什么?

是时候进入下一个项目了!

遵循 42 天项目指南,我将花一周时间冷静下来,清理一些代码,并开始思考我想为下一个项目做些什么。

我已经有一些想法了。

我想探索计算机视觉,以及如何使用机器学习来解读图像和视频数据。

真的,我只想买一个这样的…

https://store.opencv.ai/products/oak-1

如果任何人有任何有趣的想法,然后让我知道。

干杯🤙

以人为中心的数据科学

原文:https://towardsdatascience.com/human-centered-data-science-3d92066bf779?source=collection_archive---------33-----------------------

当成功的数据科学意味着与人类互动

奥马尔·弗洛雷斯在 Unsplash 上拍摄的照片

数据科学、高级分析、机器学习、人工智能、认知计算和自然语言处理都是当今商业世界的热门词汇,因为如此多的用例已经证明了利用这些工具可以带来显著的竞争优势。

尽管这些工具的功能已得到证实,但许多人仍然难以成功实施,这不是因为这些工具正在失去其功能,而是因为许多数据科学团队、供应商和个人未能在人类决策的背景下正确集成数据科学工具。因此,伟大的数据科学产品建立起来了,但它们真正的影响却因负责使用它们的人的不理性、有偏见和难以预测而消失了。

这个问题并不新鲜,我们在这篇文章中探讨的是这样一个想法,即我们也许能够从过去学到一两件事,以便为成功的数据科学制定新的路线图。在这里,我们来看看连接产品和人的不同模型。

在数据科学和人类心理学的交叉点上,有一个多学科领域已经成熟。

日常数据科学的设计是什么?

1988 年,唐纳德·诺曼出版了《T4:日常事物的心理学》一书,这本书后来变成了另一本名为《日常事物的设计》的书。这些书中包含的想法简单、有力、具有颠覆性,因为在此之前,没有人正式确定如何将工程学与人类心理学相结合。这些书启发了用户设计领域或 UX,更正式地称为以人为中心的设计(HCD)。

一晃 30 年过去了,在人们开始真正将对人类的研究融入设计工程之前,数据科学在许多业务中可能会像设计一样失败。但数据科学的问题超出了日常事物的设计,因为数据科学的产品通常不是事物。相反,它们是洞察力、自动化和人类技能和能力的模型。因此,我们不仅要借鉴 HCD 的想法来改善数据科学产品的用户体验,还必须利用其他学科来全面掌握成功实施数据科学的路线图

日常数据科学的设计应该是怎样的?

因为数据科学的产品越来越多地与事物结合,无论是冰箱、烤面包机、汽车还是应用程序,日常数据科学的设计确实会受益于 HCD 的一些原则,这些原则是诺曼博士最初想法的基石。

在我们开始之前,有必要定义几个关键概念(来自 Bruce Tognazzini 对 HCD 的大量研究):

  • 可发现性:“确保用户能够发现并理解系统能做什么。”
  • 启示:“一个对象的属性和代理的能力之间的关系,决定了该对象可能如何被使用。”
  • 意符:“启示决定了什么行为是可能的。意符传达了行动应该在哪里发生。”
  • 映射:“控件布局和受控设备之间的空间对应关系。”
  • 反馈:即时反应,适量反应。

为此,作为数据科学家,我们必须确保产品的可发现性。我们在这里经常失败,因为我们相信从统计模型或高级分析中获得的洞察力本身就是发现,因此已经可以被发现。然而,这种假设是不正确的,因为洞察力只有在适用于企业或用户时才有价值。因此,我们必须阐明交付更容易被发现的数据科学产品意味着什么。这包括可发现性的所有要素,包括识别启示、能指、映射和反馈机会。

数据科学产品是在与人类互动的环境中交付的,因此只有当它允许用户发现它的启示如何改善他们的体验时,它才是好的。启示不是产品的属性,而是用户和产品之间的关系(Norman,1988)。如果数据科学分类模型取代了人们点击成千上万的文档来查找信息的需要,那么它的启示就是时间、改进的质量和增强的性能。这些应该可以通过文档和符号清楚地发现。

能指向用户发出创建启示的可能使用点的信号。在数据科学中,这可能意味着交付带有模型的关键驱动因素,以便用户清楚为什么在上面的例子中,不同的文档被模型分类、标记或标注。这样做有助于发现启示,如提高质量和增强性能。

诺曼博士提到了不同的设计元素如何映射到它们的设计功能。例如,灯光开关通过打开或关闭灯泡来映射到灯泡。在数据科学中,我们经常将模型的功能映射到它们的概率或决策,如 1 和 0,但对于用户来说,这通常并不直观,因此这种映射通常并不那么有用。因此,我们可以调整我们的映射,以包含表示我们的数据科学产品的更直观应用的限定符。例如,概率成为“高风险”、“中等风险”和“低风险”值标签的桶,这些标签提高了用户将我们的模型的输出映射到它们的功能的能力。

在许多方面,直到我们有机会从用户那里获得反馈,最佳映射才会变得明显。对于商业用户来说,反馈可以是明确的,并遵循好的设计原则(简单、容易、不唐突)。在极少数情况下,我们的用户实际上是我们洞察力(一种预测某人获得工作或在关系中获得成功的可能性的模型)的客户,那么反馈也必须是直观的和响应性的(另见下文,我们通过语音扩展了响应性反馈设计)。

BreakslowUnsplash 上拍摄

更多心理学!!!

但是仅仅借用 HCD 的概念来提高数据科学产品的成功是不够的。因为这些产品被部署来与人互动,包括客户和企业用户,我们的成功管道必须对政治和社会心理关系敏感,这些关系定义了这些个人如何相互互动以及如何与我们的产品互动。

例如,为商业用户提供自动化甚至增强功能的机器可能会感到威胁。威胁的形式可以是对工作安全的威胁,也可以是对个人效能感和专业知识的威胁。因此,我们的数据科学渠道必须对这一结果保持敏感,直接应对威胁感,以获得认同。社会心理学家很早就认识到,为了增加认同,人们需要感觉到一个新的过程是公平的,为了确保公平,变革过程需要发言权。声音是给予用户参与过程实际如何展开的机会。从数据科学的角度来看,这意味着我们创造机会,不仅仅是像我们从 HCD 那里学到的那样提供反馈,而是展示反馈如何真正为我们的产品带来变化。

例如,向用户解释关键的模型特征,并征求反馈,以不同的方式将这些特征分组为有意义的和可操作的分组。在一个这样的例子中,一个客户想出了通过不同的外展媒体(例如,个人电话、电子邮件微移等)对可能受到影响的功能进行分组的主意。).通过将这种反馈整合到产品中,用户已经在思考如何创造性地开发可以解决这些差异的内容,当他们看到高概率(例如风险评分)以及更好地匹配不同外联模式的关键驱动因素时。用户看到了启示,因为他们现在是使用产品来提高自己影响力的积极参与者。

但声音并不是心理学中可以帮助开发成功的数据科学产品管道的唯一视角。事实上,人们可以结合政治心理学或动机的概念来理解他们产品成功的相关方面。我们把这留给读者,你们的想象力和创造力。欢迎在下面发表评论,继续这一对话,并在追求更有效的数据科学成功模式方面更进一步。

端到端成功清单

在开发成功的数据科学管道时,可以考虑一个有用的清单,如下所示:

  • 该产品的主要用户群有哪些特征?
  • 这些特征如何暗示我的产品的不同的可能的启示?我的产品为那些特定用户启用或阻止了什么(反启示)?
  • 什么样的交付或部署方法对实现这些启示最有意义?
  • 我如何向我的用户群传达这些启示?
  • 从我的用户的角度来看,什么映射最有意义?
  • 我是否提供了简单、容易且不唐突的反馈机会?
  • 我能证明反馈如何改变了产品吗?

我们关于成功的数据科学产品管道的帖子到此结束。我们感谢您花时间阅读这篇文章,并期待在下面的评论中看到您的后续想法。虽然这篇文章是高层次的,理论性的,请继续关注,因为我们将包括未来的主题,探索数据科学和人类决策编码中更实际的问题。

我还要强调的是,这仅仅是一个试图合并不同领域的应用程序,但还有许多其他方法。关键是要认识到数据科学、数据工程、应用程序开发、用户体验和心理学等不同领域交叉授粉的价值。干杯!

参考

通过 Fastdatascience.ai 学习数据科学开发、领导力和战略

诺曼博士(2013 年)。日常用品设计:修订扩充版。星座。

Tognazzini,B. (2014 年)。交互设计的基本原则(修订和扩展)。 AskTog

以人类为中心的人工智能宣言:或者如何尝试不造成伤害

原文:https://towardsdatascience.com/human-centric-ai-manifesto-or-how-to-try-and-do-no-harm-4559a6def9be?source=collection_archive---------27-----------------------

最近,我告别了学术生涯,回到了工业界。虽然我从未对这一举动感到后悔,但我开始担心,既然我的工作变得更加务实,我的自主权减少了,我是否还能继续反思我工作的道德方面。总的来说,我认为我们作为一个数据科学社区没有做足够的工作来保证我们的工作不会伤害或不利于那些与我们创造的任何东西进行交互的人。在这篇文章中,我试图通过采用一种更加以人为本和价值敏感的方法,来整合我的观察和想法,如何做得比我们目前做的更好。

数据科学和人工智能

罗伯特·奥本海默在为研制原子弹做出贡献后说:“我已经成为死亡,世界的毁灭者”。虽然可以说数据科学家并没有促成任何像原子弹那样令人发指的影响,但他们确实创造了影响数百万或数十亿人日常生活的模型和系统。这让我想知道:我怎么能保证在 5 到 10 年后我会得出类似的结论呢?进一步加剧这种担忧的是我的观察,即数据科学和人工智能社区中有相当多的人不重视或不具备对其工作的道德影响进行批判性反思的技能或背景。

这个“宣言”是我开始从事数据科学工作以来形成的思想的整合。它包含对数据科学研究如何完成以及这如何导致影响方面的盲点的观察。它描述了我在博士期间的研究如何通过考虑用户如何体验人工智能应用来避免盲点。它反思了为什么即使是这种方法也不够,因为并非所有的人工智能应用都是用户有意识使用的系统(浏览互联网的人可能没有意识到他们看到的内容是基于算法预测的个性化内容,或者公民可能没有意识到警察巡逻队是基于历史数据被派往他们的社区)。总之,我有一些想法,尽管我对我们作为一个社区应该如何前进只有一个模糊的想法,以确保十年后我们不必在尴尬、羞愧或内疚中回顾我们所建立的一切。

数据科学

照片由 Unsplash 上的尼克·费因斯拍摄

我们作为数据科学社区贡献的人工智能应用正变得越来越普遍。我们现在的情况是,任何人接触到的大部分信息在某种程度上都是人工智能的结果。这是巨大的。与此同时,我们根本不知道我们所创造的技术是如何影响接触它的人们,或者整个社会的。有大量的例子表明,人工智能并没有提高,反而降低了人们的生活质量。通读凯茜·奥尼尔(Cathy O'Neil)的《数学毁灭的武器》(Weapons of Math Destruction)给出了大量例子,说明算法通过负反馈循环伤害或不利于人们,从将多媒体平台用户归类为阴谋论或回音室的过滤气泡,到不断分配警力资源以巡逻发生轻微犯罪的弱势地区并从防止更大犯罪中夺走资源的预测性警务算法。

我自己的背景是推荐系统,所以在整篇文章中,我将使用推荐系统作为例子。推荐系统是拥有大量内容的网站所使用的软件,例如电子商务网站中的电影或产品。推荐系统的目的是帮助网站用户找到相关的项目。他们通过分析和比较所有访问者之间的互动行为来实现这一点,根据访问者的历史互动行为,他们可以使用这些模式来预测访问者最有可能购买或消费的东西。

人工智能应用未能实现改善人们生活的目标的根本原因之一是,这些应用的设计和开发往往是条块分割的。就设计而言,这些系统已经存在于不同的抽象层次上。目标是在战略层面上制定的,从战略层面上制定可客观衡量的关键绩效指标,并选择解决方案的数据。对于我们的多媒体流媒体网站,我们希望提高访问者的参与度,我们打算通过检查人们观看视频的数量来衡量这一点。

这为我们提供了足够的信息来创建一个算法,该算法将产生一个预测模型,作为我们智能系统的基础,随着时间的推移,原始指标方面的性能会得到改善。太好了!因此,我们多媒体流媒体平台的观众花在搜索电影上的时间更少了(这对他们有好处),他们看的电影更多了(对他们和我们都有好处)。

一个棘手的问题是,当你进入数字和数据的更精细的层次时,你会远离背景、战略目标以及接触到它的人。算法不关心我们是在开发一个推荐系统还是一个欺诈检测系统;同样的数字,规则,参数适用。因此,构建算法、训练和实现模型的人甚至不必理解他们的模型输出是用来做什么的,只要他们能够将问题公式化为机器学习或数据科学问题。如果忽略你的模型将被使用的环境,事情会变得很奇怪。当然,我们可以假设让人们观看更多电影的系统表现良好,我们可以训练我们的模型来优化这一指标。但是,如果走极端,这可能会导致人们一天 24 小时观看电视的不良后果?理论上,这是一个完美的模型。但实际上,这根本不是一个理想的、可持续的解决方案。换句话说,重要的是将范围从预测扩大到应用程序的原始上下文,以及预测将如何影响系统、用户、人和世界。

以用户为中心

cottonbro 在 pexels.com拍摄的照片

我有一个人机交互的学位,这允许或迫使我在整个博士学位期间采用以用户为中心的方法。我被告知,当一个人工智能解决方案仅仅改善了一个客观的行为指标,如持续时间或点击次数时,我不会感到满意,而是要始终包括主观的用户体验。即使推荐系统让人们连续 24 小时观看视频,他们真的会满意吗?因为这是我们系统的最终目标,你不能满足于使用一些满意度的代理,比如点击次数和点击越多的人越满意的假设。你得问他们!更重要的是,人们都很古怪。当他们观看由算法推荐给他们的项目时,他们真的会满意吗?或者当他们进行人工搜索时,或者当他们可以依赖电视台董事会做出的节目决策时,或者当他们观看朋友推荐的节目时,他们会更满意吗?甚至可能是,如果所有四种方法都有相同的结果,人们会有不同的满意度。

更糟糕的是,并不是所有的用户都一样。在研究如何自动执行用户经常执行的任务的系统时,如谷歌的 Nest 智能恒温器,我们可以使用人工智能开发一个系统,随着时间的推移,该系统可以学习通过完全自动化来将完成任务所需的用户努力降至最低,甚至为零。但是对以前做这个任务的人有什么影响呢?那些甚至喜欢摆弄恒温器时控制感的人呢?

所有这些都可以通过某种形式的以用户为中心的评估来解决。超越人工智能应用程序如何影响客观的用户交互,将用户体验放在评估人工智能应用程序的更中心位置,已经降低了你创建一些伤害他们的东西的可能性。但是有些事情超越了用户体验。我们的系统对用户背后的人有什么影响?推荐系统如何帮助人们发展他们的品味和偏好,甚至性格?不得不寻找电影看或音乐听,并形成一个观点,这不是我们个人发展的一部分吗?推荐系统不会剥夺我们发展自己的机会吗?

为什么用户中心性不够?

我在马斯特里赫特大学任教期间,与其他院系的同事交流,我慢慢得出结论,这种以用户为中心的观点是不够的,原因有二。第一个原因是,用户不一定是对他们有利的最佳判断者。每个吸烟者都会说他们对自己的香烟很满意,然而我们可以相当客观地说香烟对他们有害。类似地,用户可能表示他们对人工智能应用程序的输出感到满意,但从长远来看,这个系统实际上可能正在伤害他们。第二个原因是,并不是每个接触到人工智能应用程序动作的人都是真正的、有意识的用户。在某些情况下,人们没有权力决定他们是否会接触到应用程序,例如当政府使用人工智能应用程序时。在其他情况下,他们可能会与他们不理解的东西进行交互,并迫使他们理解评估他们的用户体验是不现实和不可取的。

没有(或者不是所有)用户能够判断什么对他们有益

当看到人们的满意度可能不符合他们的利益时,我们可以看看过滤气泡推荐系统。当推荐系统对用户的兴趣做出推断时,就会出现过滤气泡。一个系统意识到有人可能对某一类内容感兴趣,并开始提供更多的内容。其结果是,用户查看任何其他内容并向系统提供推断是错误的证据变得更加困难。最终的结果是,用户可能会被归类到例如自行车视频(相当无辜)或阴谋论(不那么无辜)。如果一个人被归类,只要他们对此感到高兴/满意,我们能认为这是“好的”(在道德意义上)吗?

我认为人工智能不仅应该考虑与之互动的人们的需求/愿望,还应该考虑我们作为一个社会所努力追求的价值观。不是我们做的每件事都是我们想要的。在某些情况下,我们作为一个社会设定了一些价值观,比如“每个人都需要对数学有一个基本的了解”。我们需要承认我们有价值观,这些价值观根植于我们的解决方案中。这些价值观可能已经被有意识或无意识地植入,现在是时候确保我们反思我们植入的价值观了。

并非所有用户都在有意识或自愿地使用人工智能

除了不是所有的人都能判断什么对自己好之外,这些价值也是不足的,因为不是所有的用户实际上都是‘用户’。暴露于例如目标广告的人可能不知道这些广告是基于算法预测而显示给他们的。当广告网络(如谷歌的 Adwords)使用人们的网络浏览行为来推断他们的兴趣,并使用这些推断为他们提供最有可能与他们相关的广告时,就会发生定向。现在有些人是那些系统的用户。我绝对是一个用户:我了解个性化是如何工作的,我控制我何时分享什么信息,我在我想要的时候屏蔽个性化广告。我母亲与其说是一个用户,不如说是一个系统及其输出。她甚至可能错误地认为,她在脸书 feed 上看到的帖子是马克·扎克伯格自己选择的,值得她关注,而不是基于算法预测(这带来了一个全新的问题)。

同样,当涉及到其他类型的决策时,人们可能没有意识到他们正在使用一个系统,他们可能没有选择不受算法输出的影响。这方面的例子可以是学校招生部门或人力资源部门雇用人工智能来帮助招聘。或者雇用人工智能来权衡或决定接受或拒绝申请的抵押贷款提供商。

未来:以人为本,重视价值

我们如何确保在十年后,我们不会把过去十年的努力视为一个错误?目前正在努力确保我们所做的工作经得起一些道德审查,既来自数据科学/人工智能社区本身,也来自监管机构。并且这两种努力仍然有它们的缺点。

目前的努力

老实说,人们努力制定普世价值。公平、问责和透明(或 FAccT)正在成为机器学习社区现在努力追求的价值观。任何机器学习应用都应该产生公平、透明且有人可以负责的决策/预测/输出。与此同时,我个人并不认为这些具体的问题应该是普遍的。当然,问责制是有意义的。没有人应该成为他们不能质疑的决定的主体,我们也不希望人工智能系统地偏袒一个群体而反对另一个群体。但是,透明度是我们必须争取的价值吗?我认为透明度本身符合人们能够理解他们正在交互的东西的价值,但同时它可能与易用性的价值不一致。获得了为什么会做出这样的决定的额外信息,迫使人们投入时间和精力去阅读(或至少决定是否阅读)这些额外信息。

这些社区价值的主要缺点是,这些价值也不是以用户或人为中心的。很难说,透明度是接触到人工智能系统输出的人会重视的东西。是时候调查一下与我们的应用程序交互的人们看重什么了,老实说,我很难期望“透明”是这次调查的结果。我认为在开发人工智能时,一个很重要且应该考虑的价值观是“自主性”。如果我重新开始学术生涯,这将是我的研究方向之一。

另一个确保我们不造成伤害的努力是将希波克拉底誓言改编为数据科学家的希波克拉底誓言。虽然原则上这正是我们需要争取的交战规则和原则的类型,但遗憾的是,它还没有得到 AI/数据科学界的广泛认可。

为什么仅仅遵从是不够的

在某种程度上,法规旨在作为法律界限,确保人工智能不会伤害或不利于人们。随着人工智能变得越来越普遍,更多的边界被设置到位。但是,目前的监管以及可能所有的监管都存在一些缺点。

由于人工智能的发展如此之快,监管往往发生在事后。出了问题(如剑桥分析),制定法律以避免再次发生(如 GDPR)。因此,法律界限定义了我们能做什么和不能做什么,这是基于我们过去判断为错误的事情。

另一个缺点是,在没有充分了解技术要求或对用户/公民的影响的情况下,常常制定规章。这方面的一个例子是 2009 年推出的欧洲电子隐私指南,也称为 cookie 法。这些指导方针是向数据所有权迈出的第一步,而数据所有权是 GDPR 的核心,并描述了公司如何有义务请求其网站上的访问者同意使用 cookies 来识别和跟踪他们。一件很棒的事情是,人们获得了对数据的控制权和所有权。与此同时,他们被迫做出一个决定,这个决定实际上要求他们在某种程度上理解 cookies 的作用。

这违背了“不造成伤害”的主要设计原则之一。在这种情况下,伤害可以而且应该从这个词最广泛的意义上来理解:我们不应该设计会主动伤害人的系统,也不应该设计会给公司、用户和地球带来超出绝对必要的资源成本的系统。不得不自学 cookies 在有意识地决定接受或拒绝它们时的作用,这意味着欧盟正在给其公民施加负担。通过规定在什么情况下可以和不可以跟踪访问者,他们可以相对容易地承担起这个负担。

为了确保你的行为不会导致将来的法律,你所能做的最大努力不是在法律的范围内,而是在一系列道德的范围内。它们在任何地方都不是一成不变的,除了某些行业,如新闻业和银行业,它们的行为准则是一致的。即便如此,它们也可能是含糊不清的,可以有多种解释。过去,我的一套界限是确保我所创造的一切都是以用户为中心的,把用户和他们的体验放在第一位。我可以非常自信地说,我没有创造出任何我没有评估过或者没有打算通过用户研究来评估的东西。

安娜斯塔西娅·弗拉戈娃像素上拍摄的照片

走向未来:以人为中心的人工智能

负责任的 AI 和有道德的 AI 是看似相似事物的两个名称。在我看来,确保我们不会伤害受我们作为数据科学家所做工作影响的人们的唯一方法是采取以人为本的方法。我们不能只考虑我们的人工智能应用程序采取的行动如何影响客观行为,我们必须考虑这些应用程序如何影响那些与我们的系统交互的人的体验和人类生活。通过这种方式,我们可以再次降低我们伤害他们的可能性,甚至确保我们确实通过我们的工作改善了生活。更进一步,我们可以将嵌入我们系统的价值观与我们作为向世界发布人工智能应用程序的人所拥有的价值观,我们作为人工智能应用程序的用户所拥有的价值观,甚至与我们作为社会所拥有的价值观相一致。但这确实需要我们意识到并考虑这些价值。

任何从事人工智能工作的人都不能再使用“我只是制作算法,它们的用途是别人的责任”这样的话。从产品负责人到数据科学家,再到数据工程师,链条中的任何人都需要分担责任,确保我们开发的东西以帕累托最优的方式改善世界:不造成伤害或损害任何人。要做到这一点,需要做的不仅仅是询问暴露在这些系统中的人们是否对这些系统满意。在某些情况下,它需要我们真正代表他们思考和决定。虽然这让一些人感到害怕,但这并没有错。但是有很多方法可以做到这一点,数据科学家应该接受这一点,并利用它来增强他们自己的工作,而不是将其视为分散工作的注意力。

创新研究

有大量关于创新研究的文献,或者关于创新是如何产生的思考。创新研究的关键方面是如何进行和衡量创新、技术创新系统(或创新建模的方法)、创新和政治,与本文最相关的是:创新对经济、社会和环境的影响。在这种方法中,研究人员试图通过研究新技术的客观属性和环境之间的关系来解释创新对其环境的影响。

价值敏感设计

另一个重要的方面是对价值敏感的设计。由于人工智能应用程序是由人创建的,并且它们是基于从人那里收集的数据,因此如前所述,我们创建的应用程序中总是嵌入了价值。它们要么嵌入在我们使用的数据中,要么嵌入在我们选择优化的指标中,要么嵌入在我们根据预测选择采取的行动中。确保在构建应用程序时考虑价值的一种方法是遵循一种叫做价值敏感设计的方法。这种方法通过考虑利益相关者和他们的价值,允许设计考虑人类价值的技术。其中,人种学方法被用来了解什么价值是相关的,以及它们是如何被设计的技术考虑进去的。

我将如何保持以人为本

我目前正在为 Obvion 编写数据科学路线图。在创建和实施该路线图的过程中,我将努力确保资源分配到我们工作的道德部分。作为一家金融机构,我们有很多关于如何开展工作的规定,但合规应该是最起码的要求。我的目标是超越这一点,确保我们公平对待与我们交往的人,改善他们和我们的生活。作为抵押贷款提供商,我们的行动和决定影响着任何人一生中最大的一次购买。我的主要目标是确保我们的行为和决定不会伤害、损害或不公平地对待任何人。

这将首先在发展团队中完成,我的目标是创建一个不仅仅关注数字的团队。我们每个人都应该了解和理解我们正在帮助解决方案的流程和客户、顾问和同事。我们将挑战自己,被要求接受挑战,挑战那些向我们寻求解决方案的人。其次,我们将沿着两条轴线同心地开发和推出人工智能应用。第一个轴是提供决策支持与自动化决策。我们从提供决策支持的应用程序开始,而不是自己完成决策。随着我们了解的越来越多,我们将慢慢转向可以自动完成决策的应用程序。我们将改变的第二个轴心是让我们的解决方案从内部焦点开始,着眼于影响我们内部组织的决策和行动,并慢慢转向影响我们的客户和顾问的决策和行动。

没有保证,但这是我们试图将负面影响我们交往对象的可能性降到最低。

感谢

感谢大卫·范·科克霍夫的精彩反馈!

背景

去年,我是马斯特里赫特大学商业和经济学院的数据科学助理教授。今年,我是荷兰抵押贷款提供商 Obvion 的首席数据智能。我意识到,除了一系列出版物和一些仍在进行的项目,我还没有整合我在学术界的经验、想法和观点。尽管事实上我被 Obvion 雇佣部分是因为我的经历、想法和观点。因此,我试图在我所谓的“以人为中心的人工智能宣言”中写下我所做的事情。

脚注

过滤泡在科学文献中仍然是一个争论,既有证据支持也有证据反对它的存在。这表明有一些外部因素影响过滤器气泡是否影响用户消费,因此不能忽略它们。如果有什么不同的话,这表明我们应该注意到技术可以影响我们的思维和行为这一事实。

https://www . nap . edu/catalog/25104/data-science-for-substantials-opportunities-and-options # TOC

我认为透明度不应该成为一种普世价值的另一个原因。

原载于https://aigents.co

机器翻译系统中的人在回路

原文:https://towardsdatascience.com/human-in-the-loop-in-machine-translation-systems-bdf3fe82bfa3?source=collection_archive---------33-----------------------

使用众包评估机器翻译质量

图片由来自 Pixabaystokpic 拍摄

简介

近年来,由于深度学习和人工神经网络的进步,机器翻译已经卷土重来。2015 年,机器翻译系统开始从基于统计的模型转向神经网络,这大大提高了大多数语言对的翻译质量。这些改进伴随着翻译系统评估方式的变化,机器翻译工程师开始更加关注他们创建的系统的人工评估。

在本文中,您将根据 Yandex Translate 的经验,了解如何使用众包来评估机器翻译系统,Yandex Translate 是市场上最好的机器翻译系统之一。

传统机器翻译评估指标

传统上,机器翻译质量是使用自动化指标进行评估的,如 BLUE、METEOR、LEPOR 和 BLEURT,这些指标在业界都是众所周知的。然而,自动化指标并不能为当前系统提供足够准确的评估。此外,这些方法成本高昂,因为它们需要高薪聘请专业人士来创造黄金组合。近年来,已经投入了大量的努力来探索作为替代方案的人类评估。

众包人工评估

人类评估者必须会说目标语言对中的两种语言,但他们不必是专业翻译。因此,使用这种类型的评估更便宜且更具可扩展性。这个过程可以通过众包平台来建立和自动化,比如 Toloka。从西班牙语翻译成英语的评估任务可能是这样的:

评价 ES-EN 翻译的例子,作者照片

这个任务被设置在一个众包平台上,并发送给说两种语言的人。按照机器翻译模型的建议,存在源语言的文本及其英语翻译。执行这项任务的人被问到“翻译有多好”?他们从不同的回答中选择:优秀、良好、满意、不满意、糟糕。

通过收集不同表演者对各种句子的反应,我们可以了解翻译系统的表现。这种评估通常比自动度量更准确。

并排比较

当我们想要评估一个机器翻译模型时,我们通常会将其与一个基准、另一个模型或者只是我们自己模型的以前版本进行比较。在这种情况下,比较两个系统的最佳方法之一是使用并排比较。下面的截图说明了这样一个例子。

并列式 MT 评测示例,作者照片。

在上面的截图中,你可以看到两个不同的模型提出的一个英语源句子和两个西班牙语翻译。任务执行者被要求选择哪个翻译更好,或者如果两个版本同样好,则指出相同

作为系统评估的结果,我们可以比较这两个系统在一段时间内的表现。在下面的屏幕截图中,您可以看到系统 1 一直在降级,而系统 2 一直在改进。

一段时间内的机器翻译系统比较,作者提供的照片

挑战

人工翻译比自动度量更准确的事实并不意味着它没有挑战。在上面的设置中,您看到任务执行者被给予一个句子来评估,并且没有提供上下文。这有时可能会导致错误的选择。

此外,为了评估语言对的翻译,我们需要任务执行者说两种语言。理想情况下,这个人应该是目标语言的母语使用者,并且应该能够流利地使用源语言。虽然如果我们使用众包,大多数流行语言都不是问题,但为一些更模糊的语言对找到表演者可能是一个挑战。

还有一些特殊类型的翻译需要稍微不同的设置。例如,电子商务的翻译通常必须附有一张照片,如下图所示。

电商 MT 实例,作者照片

没有额外的图片,就不可能对源查询“婴儿儿童卡通洗发沐浴浴帽洗发罩”的翻译做出正确的评价。

一个类似的例子是网页翻译。由于网页的结构由文本、HTML 标签和不同的组件组成,很难脱离上下文翻译一个句子或单个短语。在这种情况下,翻译往往伴随着网页本身,以提供更多的信息。

总结

在本文中,我们已经了解了使用众包对机器翻译系统进行人工评估的不同方法。更多详情,请观看玛利亚·什马托娃的演讲,了解她的团队在 Yandex 翻丨译丨公丨司是如何做的。此外,如果你想了解更多关于如何自动化模型评估过程,你可以加入这个数据授权的社区

PS:我正在 Medium 和aboutdatablog.com上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的 邮件列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入https://medium.com/@konkiewicz.m/membership

下面还有一些你可能喜欢的帖子

* </9-things-you-did-not-know-about-jupyter-notebook-d0d995a8efb3> *

人类学习:通过绘图创建人类学习模型

原文:https://towardsdatascience.com/human-learn-create-rules-by-drawing-on-the-dataset-bcbca229f00?source=collection_archive---------8-----------------------

使用您的领域知识来标记您的数据

作者 GIF

现在,数据科学家经常给机器学习模型数据加上标签,以便它能够找出规则。这些规则可用于预测新数据的标签。

作者图片

这很方便,但是在这个过程中可能会丢失一些信息。也很难知道引擎盖下发生了什么,以及为什么机器学习模型会做出特定的预测。

除了让机器学习模型解决所有问题,有没有一种方法可以让我们使用我们的领域知识来设置数据标签的规则?

作者图片

是的,这可以通过人类学习来完成。

什么是人类学习?

Human-learn 是一个工具,允许您使用交互式绘图和定制模型来设置数据标签的规则。在本文中,我们将探讨如何使用 human-learn 创建一个具有交互式绘图的模型。

要安装 human-learn,输入

pip install human-learn

我将使用 sklearn 的虹膜数据来展示 human-learn 是如何工作的。

交互式绘图

图画

Human-learn 允许您在数据集上绘图,然后使用您的绘图将它们转换为模型。为了演示这是如何有用的,假设您创建了一个数据集散点图,如下所示:

作者图片

当查看上面的图时,您可以看到如何将它们分成 3 个不同的区域,如下所示:

作者图片

然而,将您的绘图写成规则并将其放入函数中可能会很困难。这时,human-learn 的交互式绘图就派上了用场。

现在你可以像下面这样开始绘制你的图表了!

作者 GIF

绘制指令:双击开始绘制多边形。然后单击以创建多边形的边。再次双击可停止绘制当前多边形。如果你不清楚这一点,你可以在这里看一个视频。

我们也对其他色谱柱做同样的事情:

作者图片

作者图片

作者图片

创建模型并预测

完成数据集的绘制后,我们可以使用这些绘图创建一个模型:

酷!通过将我们的图纸提供给InteractiveClassifier类,我们能够使用类似于 sklearn 模型的方法,例如fitpredict_proba

预测的形状preds(150, 3)。让我们来看看preds的前 5 行:

注意predict_proba给出了样本具有特定标签的概率。例如,[5.71326574e-01 4.28530630e-01 1.42795945e-04]的第一次预测意味着样本有 57.13%的机会具有标签 1,有 42.85%的机会具有标签 2,有 0.014%的机会具有标签 0。

预测新数据

现在,让我们使用我们的模型来预测新数据,并将预测与真实标签进行比较。

输出:

The prediction is 0
The real label is 0

不错!预测和真实标签一样!

解释结果

为了理解模型是如何得出预测的,让我们想象一下我们的新样本在之前绘制的散点图中的位置。

首先创建一个函数来可视化我们的新样本。

使用上面的函数在petal_lengthpetal_width图上绘制一个新的样本,其点以其标签为 0 的概率着色。

作者图片

请注意,黄色圆点表示这些圆点有标签 0高概率。点越是紫色,这些点越不可能有标签 0。

我们可以看到红点(新样本)在有许多黄点的区域。但是在其他的情节中有类似的模式吗?让我们通过将相同的函数应用于其他列对来找出答案。

作者图片

作者图片

作者图片

在所有的图中,我们可以看到红点在有许多黄点的区域!这解释了为什么模型预测新样本的标签为 0。很酷,不是吗?

预测和评估测试数据

现在让我们使用该模型来预测测试数据中的所有样本,并评估其性能。使用混淆矩阵开始评估:

array([[13,  0,  0],
       [ 0, 15,  1],
       [ 0,  0,  9]])

哇酷!有 37 个真预测,只有 1 个假预测。

我们还可以使用 F1 分数来评估结果:

0.9736842105263158

不错!

结论

恭喜你!您刚刚学习了如何通过在数据集上绘图来生成标记数据的规则。这并不是说你应该完全消除机器学习模型,而是在处理数据时加入某种人类监督。

我希望 human-learn 将鼓励你在应用任何机器学习算法之前可视化你的数据。在下一篇文章中,我将向您展示使用 human-learn 创建规则的其他方法。

本文的源代码可以在这里找到:

https://github.com/khuyentran1401/Data-science/blob/master/machine-learning/human_learn_examples/human-learn examples.ipynb

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 T2 Twitter 上与我联系。

这个回购如果你想检查我写的所有文章的代码。在 Medium 上关注我,了解我的最新数据科学文章,例如:

目标检测中的人类先验

原文:https://towardsdatascience.com/human-priors-in-object-detection-5d1b6de42f82?source=collection_archive---------31-----------------------

作者图片

我们告诉人工智能的东西决定了它如何学习

在我处理过的所有计算机视觉问题中,最具挑战性的是目标检测。这并不是因为问题本身很难理解或者表述不当(图 1)。而是因为我们需要注入一些强有力的先验知识,关于我们认为我们如何理解这个世界。

图 1:目标检测问题公式(图片由作者提供)

这意味着我们注入到人工智能设计中的先验越强,人工智能学习就越有偏见。请注意,我说的是人工智能学习过程中的偏见,而不是人工智能学习什么的偏见,那是一个完全不同的话题。好吧,那么什么是先验知识呢?

先验是一种“先验”知识,它表达了一个人在解决问题之前对问题的信念。

为了说明我所说的注入一些强先验是什么意思,让我们考虑物体检测中最广为人知的人类先验:锚

锚作为先验

如果你在过去几年里一直从事物体检测工作,你可能听说过。从技术上讲,锚点是一组具有预定义纵横比和比例的边界框。所以基本上有两种类型的锚:

  • 纵横比预定义锚点:具有预定义纵横比的边界框,例如 1:1、1:2、2:1 等。
  • 缩放预定义的锚点:根据不同的缩放比例,如 x1、x2、x3 等,使用预定义大小的边界框。

图 2:锚点类型(图片由作者提供)

对象检测中的锚注入提出了以下过程。给定一个【H,W】的图像,将其拆分成一个【Gh,Gw】的网格。如果要预测的目标对象的中心落在网格的给定单元内,则该单元负责预测该对象。由于我们不知道目标对象的大小,我们用不同的比例和纵横比为每个单元格重叠锚点。然后,具有与对象背景真值框更高的 IoU (更高重叠)的锚将是目标锚,AI 将基于该目标锚进行学习。

为了说明这一点,请考虑下面这张我的未婚妻凝视着群山的照片(也许是我不停说话的短暂休息),其中:

  • 地面真相是绿色的边界框。
  • 负责预测地面实况的单元格是黄色网格单元格。
  • 锚点是蓝色的边界框,它们对应于 2:1 和 1:2 的纵横比,两者的比例都是 1(基本比例是网格单元大小)。

图 3:阿尔卑斯山之旅,也是人工智能如何看待我的未婚妻

在这个例子中,AI 被告知开始从纵横比为 2:1(较高的重叠,IoU,具有基本事实框)的锚学习,并适应基本事实绿色框的大小。所以 AI 必须从 anchor 2:1 开始学习,学会缩小宽度和移动高度(红色箭头)。

在图中,仅出于可视化的目的,示出了 2 个锚,但是实际上,根据网络的不同,每个单元网格有大约 12 个锚:efficient det[锚参数[锚计算 ],YOLO [ 锚点

让我们停下来想一想:这里到底发生了什么?有人可能会想,嗯,没什么不寻常的,我们只是告诉人工智能如何在图像中找到物体。我们知道物体有一些预定义的长宽比和比例,所以我们告诉 AI: “嘿,学会在图像中找到物体!哦!顺便说一句,物体通常有 1:1、2:1、1:2 的长宽比,以及 x1、x2、x3 的比例,所以任何物体都应该接近这个比例”。

好吧,这似乎是一个很好的起点。我们都同意,总的来说那是真的。正因为如此,这是之前的支持锚方法。换句话说,锚点方法基于以下人类先验:一般来说,所有对象在合理的范围(x1,x2,x3…)内具有共同的纵横比(1:1,2:1,1:2…)。所以我们只是让人工智能知道这一点。

然而,如果我们详细回顾锚定或先前的注入过程,我们可以看到我们真正告诉人工智能的是:“嘿,学会在图像中寻找物体!哦!顺便说一下,对象位于网格内,并以网格单元为中心……嗯,老实说,一个对象可以填充多个网格单元,但可以想象它只以一个单元为中心。好吧,也许不是居中,它更像是位于一个细胞中。但当然,对象的宽度和高度可以跨越其他单元格,顺便说一句,不要和对象所在的单元格混淆,因为只能有一个…话虽如此,但对象在合理的比例(x1,x2,x3…)内有共同的长宽比(1:1,2:1,1:2…)。希望一切都有意义,如果没有……好吧,你只要看看地面的真相就行了”。**

现在看起来像是注射前的一吨重的复合物,不是吗?然而,这并不意味着这是一个坏方法。截至 2020 年,大多数物体检测研究都是基于这一先验。巨大成功的人工智能架构是基于锚:YOLOv3,RetinaNet,FPN,Efficient-Dets,MobileNets…但它仍然太复杂了,是的,这意味着更多的编码和调试时间。

无锚前科

那么,对于物体检测先验,还有其他的选择吗?是的,他们是。人工智能社区正在考虑绕过这种方法。以下是一些例子:

  • CenterNet :提议忘掉网格,教人工智能只预测盒子坐标和类别概率。
  • ExtremeNet :建议教 AI 一个物体的极值点(这样就消除了物体应该被一个固定的 4 点框包围的先验),允许任意复杂的包围盒。
  • 物体作为点:建议教导人工智能物体是具有一些额外属性的点(宽度、高度、类别概率……)。
  • 变形金刚:它只是通过使用注意力机制强制变形金刚变成 CNN 来消除先验。

在这些要点中有一些非常创新的方法,但我仍然缺少一种直观的方法(类似人类的直观)来定义和注入先验。

似乎趋势是逐步消除前科。我的意思是不要摆脱前科。我认为先验是有用的:例如,CNN 建立在图像中像素与其他邻近像素相关(空间相关)的先验基础上,类似地,rnn 建立在时间相关先验基础上(对于视频和序列也是如此)。事实证明,拥有正确的优先顺序有助于加快训练速度(当然,还可以通过分担重量来节省空间!).

我的观点是我们应该重新思考如何定义这些前科。因为我们注入的先验直接决定了人工智能如何学习。换句话说,我们应该思考我们告诉 AI 学习的故事是什么,因为这个故事是它唯一知道的。

但是,我们怎样才能做到呢?

反思前科

我建议开始用文字来思考先验知识(把数学留给后面)。对于给定的任务,即物体检测,我建议我们考虑任务本身的一般特征:“我想定位物体,可以,但是,什么是物体?一般什么属性有对象?嗯,看起来它们位于图像中,并且它们可能具有不同的类型和形状”。所以我们需要以某种方式告诉 AI,物体具有空间信息,也可能具有其他特征属性。

一旦我们清楚了这一点,我们就可以将这些文字转化为数学:我们可以用关键点、边界框、遮罩对空间信息进行编码…我们可以用额外的关键点/框属性或通过设置另一个遮罩通道来对额外的信息进行编码…

随着我们的地面真相被编码(无论如何),我们现在可以开始思考人工智能将如何学习它。这是整个过程的关键。在这里,我们必须发挥创造力。如果我们给 AI 讲一个很一般的故事:“嘿在图像中找到物体!哦!对象有一个中心点和一些特征”,人工智能可能无法学习或收敛(这相当于对我们所有的数据使用裸回归)。另一方面,如果我们变得太具体,就像在锚点方法中,我们可能会以一个过于复杂的过程结束。

图 4:编码为 2D 高斯分布的位置(图片由作者提供)

所以关键可能在于找到正确的平衡。例如,我特别喜欢在对象中注入对象位置作为点的方法。其中它被编码为以对象为中心的 2D 高斯分布,对于 xy 【图 4】具有不同的 σ 。这就像告诉人工智能:“嘿,物体中心在这里,物体的其余部分应该靠近它”。我特别喜欢这种方法,因为我发现自己在看东西(我的笔记本电脑,现在)时也处于类似的位置。我的眼睛集中在屏幕文字上,我知道物体的形状。就像信息在 grosso modo 中一样。然而,要完全意识到我的笔记本电脑的形状,我必须将我的眼睛从文本上移开,看着物体的形状。

我认为我们需要更多这样的方法。数学遵循直觉,而不是相反。我说我们需要在如何编码我们的过去方面变得有创造性,关键是开始用语言思考。一旦我们有了单词,也只有到那时,我们才能把它们翻译成数学,并最终把数学输入到我们的人工智能中。

这样我们可以真正利用我们的优势而不会迷失在这个过程中。因为经常发生的情况是,我们做的数学计算编码了我们可能忽略的东西。

谢谢你读到这里!希望在你的头脑中有一些闪光的想法!如果你想了解我更多或者联系我这里有几个链接:LinkedIn艾栈交流

人力资源分析——我们可以用 R 中的插入符号预测员工流动率吗?

原文:https://towardsdatascience.com/human-resource-analytics-can-we-predict-employee-turnover-with-caret-in-r-3d871217e708?source=collection_archive---------6-----------------------

实践教程

在中小企业(SME)上测试不同的机器学习算法,同时关注算法偏差

照片由查尔斯先行者Unsplash 上拍摄

人是每个组织成功的关键因素——没有什么比在正确的时间和地点有技能的头脑产生更大的价值。这就是为什么世界各地的组织都在尽最大努力寻找,甚至更重要的是,留住有价值的人才。在一个数据的世界里,人力资源经理不再仅仅依靠他们的直觉来设计战略,以培养他们自己的高素质人才:他们利用分析来改善他们的人力资源实践,并使业务成功和员工满意度真正可以衡量。

在员工流失的情况下,预测分析的使用不仅被认为有利于员工,还可以节省公司的财务:当一名技术熟练的团队成员自愿离职时,总是会花费大量的时间和金钱来寻找和聘用合适的替代者。此外,它还会影响公司的整体生产率、客户忠诚度和产品的及时交付(Hammermann & Thiele,2019;Sexton 等人,2005 年)。在许多其他原因中,这是因为使用数据支持人力资源的想法产生了一个完整的领域:人力资源分析(也称为人员分析)是关于基于数据驱动的见解来改变招聘和留住人才的方式(Isson & Harriot,2016)。通过这种方式,数据分析被用于预测行为模式(例如,流失率、培训成本、生产率),这些行为模式对于相应的管理层来说是固有的信息,因为它可以指导他们的决策过程。基于机器学习算法的成功实施,一些大公司已经应用预测分析来减少流失,增加盈利员工的保留率。例如,谷歌(前)人力资源高级副总裁认为,统计数据被用来完全自动化他们的求职面试问题——基于候选人的个人资料,并实际上使用员工数据来预测流动率(拉兹洛·博克,2016)。现在,作为数据爱好者,我们的任务是为人力资源经理的规划连续性提供支持,同时帮助他们降低与频繁流动相关的成本,并促进市场的成功增长。

“人力资源分析(也称为人员分析)是基于数据驱动的洞察,改变招聘和留住人才的方式。”— 伊森&哈里奥特,2016 年

在 Google scholar 上快速搜索会发现,有一堆研究文章展示了不同的 ML 算法如何预测员工流动率。然而,焦点通常放在技术特征上(例如,模型性能、特征选择等。)而这些应用的实际环境或多或少取决于读者的理解。例如,赵及其同事评估了不同的监督机器学习技术,以在小型、中型和大型组织的模拟和真实人力资源数据集上预测员工离职(赵等人,2019)。这些机器学习算法用于从决策树和随机森林方法、梯度提升树、基于逻辑回归的极端梯度提升、支持向量机、神经网络、线性判别分析、朴素贝叶斯方法和 K 近邻来预测员工流动范围。

即使试图用现代分析来预测员工流动似乎有巨大的潜力,但也有一些限制,可能会使这些科学发现难以转化为行业的真实案例:

  1. 预测或解释行为是两回事。

当处理数据时,我们可以推动以下任一策略:当我们的目标是预测相关结果时,我们不必完全理解起作用的机制(Yarkoni & Westfall,2017)。我们的策略将更侧重于预测。就我们的员工流动问题而言,当我们已经可以预测哪些员工有可能很快离开时,我们可能不想浪费太多时间绞尽脑汁地思考“为什么”——毕竟,我们改变某些事情的机会只存在于未来。一个好的机器学习模型不一定要基于理论才能做出准确的预测,因为它天生就会从数据中学习:当向数据生成过程输入新的观察结果(例如,新员工)时,算法会模仿数据生成过程的输出,而不会明确“知道”任何原因。

但是如果你有很强的学术背景,并且问了很多“为什么”的问题,你可能会说我们也想知道为什么员工会离开公司。如果我们对导致员工流失的潜在机制没有任何线索,那么设计有针对性的干预措施将会更加困难。幸运的是,有研究强调了定期加薪的重要性,商务旅行和工作满意度对员工流动的作用。这使我们更容易从组织内部找到真正的“痛点”,并真正理解是什么驱使我们去做。

2.统计数据不足以处理个人问题。

在我们生活的如此复杂的世界中,数据并不是一把神奇的钥匙,它可以帮助我们做出完美的、有效的决策,让每个人的生活更加轻松。尽管如此,当人们谈论他们使用数据来做出基于证据的决策时,这听起来是如此的酷和先进。但如果机器学习算法后来被应用于对单个员工的决策提供有力的信息(例如,当应用于对一组申请人的候选人进行排名时),这种程序很容易就变得不道德。如果申请不正确,申请人不再作为一个人被单独评估,而是作为一个分数来评估他们在工作中表现良好的可能性。使用数据挖掘技术,历史和标记的员工数据可用于检测与高工作绩效相关的特征,以预测新员工在工作中表现良好的可能性(Mahmoud et al .,2019)。因此,其他人的绩效数据以及一些关键指标(如智商、性格测试、结构化面试结果)或他们的简历可作为预测新员工绩效的基础(Kluemper,Rosen & Mossholder,2012;Apatean,Szakacs & Tilca,2017,李,赖& Kao,2008)。因此,该算法使用过去的数据进行训练,以预测未来。尤其是在像工作申请这样的高风险背景下,这对我来说似乎是非常确定的,应该谨慎看待:该模型只能捕捉特定时刻的关联,即使它们会随着时间的推移在人与人之间以及组织的发展中动态变化。此外,算法通常还复制数据中固有的歧视性偏见(例如,女性可能预示着难以获得领导职位),这使得模型在组织内的实际部署难以证明其合理性。为了避免员工的任何反作用,组织需要解决对某些群体或个人(如父母、黑人、孕妇等)的负面影响问题。)很认真。第一步是统计测量这些偏差,并纠正它们,以创建一个公平的人工智能,这对员工以及整个组织都有好处。你可以在安德鲁·伯特 2020 年发表在《哈佛商业评论》上的一篇文章中找到更多对抗歧视性偏见的想法。这个问题与组织对外部候选人的印象密切相关:候选人应该有合理的机会通过他们的实际技能和知识来说服团队,没有任何偏见或期望。如果将机器学习算法应用于招聘目的变得透明,那么仅凭一些已被证明是一些前辈成功因素的特征组合,就能找到工作,可能会让人感觉很奇怪。类似的想法也适用于员工流动的预测:即使有一组特征被认为是员工流失的关键驱动因素(上次加薪、商务旅行、人与工作的契合度、离家的距离等)。),很明显,辞职的意图是高度个人化的。借助数据分析工具,我们只能从一群个体中描述一般模式。我们甚至可以根据这些普遍趋势来预测行为。但是我们永远无法确定它们是否适用于每个人。如果数据驱动的洞察可以影响人们的生活(例如,招聘决策、挽留努力……),我们应该保持非常谨慎,并不断质疑我们程序的合理性。

3.使用分析并不能证明不道德的行为是正当的。

人工智能反乌托邦通常涉及机器做出道德敏感的决定,将计算机变成决策者。即使下面的例子远未达到这种情况,我们也应该意识到,即使数据可以为决策者提供合理的见解,但它们并不是决策者本身,应该在适当的数据保护和隐私准则下使用。当谈到将人力资源分析用于招聘目的时,有人建议让候选人有机会选择加入并控制他们的数据,方法是决定潜在雇主和招聘人员是否可以评估他们的数字足迹,以解决任何道德和法律问题(Chamorro-Premuzic 等人,2013 年)。另一个建议涉及到受人力资源分析工具影响的人的更多自主权:员工不应成为算法治理的被动接受者,而是有机会实际了解模型如何做出预测,并在需要时给出关键反馈。

我在文献中偶然发现的另一个令人毛骨悚然的应用包括使用 LinkedIn 或 Xing 等社交媒体档案,旨在基于情感分析预测候选人的性格——这两者都是为了评估候选人是否适合某份工作(Faliagka,2012)。所有上述程序肯定为研究人员和心理学家揭示了有趣的见解,但当数据正在处理的个人没有给予任何同意时,不应应用这些程序。

4.工业中可用的员工数据集通常是嘈杂而稀疏的。

如果预测是基于历史数据,我们总是需要问自己,这些是否真的可以推广到新的,但未知的观察。现在,即使模拟的人力资源数据看起来像是给任何热情的数据科学家的礼物,真实的人力资源数据通常是机密的、小的、不一致的并且包含缺失的信息。对于中型企业来说,并不是所有企业都能负担得起大规模数据存储,这使得以一致的方式存储员工数据变得更加困难。此外,它通常只包括一小部分实际上已经离开公司的员工,这使得班级(留下/离开)不平衡——这是一个在评估机器学习模型时需要特别注意的特征(但稍后会有更多介绍)。

另一个与数据相关的视角变化是指数据的质量与数量:Yahia、Hlel 和 Colomo-Palacious (2021 年)主张从大数据向他们所谓的“深度数据”转变,即包含实际预测营业额所需的所有必要特征的定性数据。事实上,大规模的员工数据对于中小型企业来说是不可用的,如果我们能够确定人员流动的关键驱动因素,也没有必要。文献中还有其他声音更进一步,提出大型非结构化数据集(通常称为“大数据”)并不总是更好,因为它们可能非常嘈杂,以至于“淹没”了每个模型的预测能力(Chamorro-Premuzic 等人,2013 年)。

这只是一个温和的提醒,以提高您对预测分析的力量及其对人们的影响的认识——我强烈推荐 Michele Loi 博士的这篇论文,他总结了在 GDPR 以上和以外部署人员分析工具的道德准则。记住这些政治问题,我们现在将通过一个小的案例研究来了解员工流失的预测是否可以合理地应用于一个来自著名的 IBM 员工数据集的小的虚拟样本。我很想知道它是否也能在现实世界中发挥作用!

数据概述—这是著名的 IBM HR 分析数据集

我们将在案例研究中使用的数据集是由 IBM Watson Analytics 创建的模拟数据集,可以在 Kaggle 上找到。它包含 1470 个雇员条目和 38 个共同特征(月收入、工作满意度、性别等)。)—其中之一是我们的目标变量(员工)流失(是/否)。让我们看看我们的原始数据。

声明:所有图片均由作者制作,除非另有说明。

我们似乎有 26 个数字变量和 9 个字符变量,它们的层次不同。没有一个观察值丢失,skim 函数给出的总结显示了一些描述性的统计数据,包括平均值、标准偏差、百分位数以及直方图。我是 skim 函数的忠实粉丝——看看获得如此简洁而详细的数据概览是多么实用!

很明显,被视为不公平的报酬会影响一个人离开工作去寻找更好报酬的意图(Harden,Boakye & Ryan,2018;Sarkar,2018 年;布莱恩特与艾伦,2013)。这就是为什么我们想要创建另一个变量来表示每个员工月收入的支付竞争力——其背后的原因是员工可能会将他们的收入与从事相同工作水平的同龄人的收入进行比较。认为自己的报酬公平的人应该不太可能离开公司,相比之下,类似职位的人得到的报酬要少得多。为此,我们将使用 data.table 语法,首先按工作级别计算中位薪酬,并为每个观察结果存储适当的值。然后,我们将每个员工的月收入除以中位收入,得到他或她的薪酬比率:一个直接代表该员工根据工作级别预期获得的薪酬的指标。因此,分数为 1 意味着该员工与该职位的平均报酬完全匹配。得分为 1.2 意味着员工的工资比平均工资高 20%,得分为 0.8 意味着员工的工资比每个工作级别的正常工资低 20%。为了在阶乘层次上表示这一点,我们将赋值

  • 至 0.75 和 1.25 之间的“平均值”
  • 至 0 和 0.74 之间的“以下”
  • 在 1.25 和 2 的补偿比范围内。

这就是我们新生成的功能在前 10 个观察结果中的样子:

但实际还剩多少员工?让我们计算一下流失率,了解一下班级的分布情况。

因此,似乎有 237 名员工(16%)在给定的时间内离开了公司,而大多数(近 84%)留在了公司。如上所述,许多人力资源经理无法访问包含数千名完整记录员工的庞大数据集。现在,如果我们想为一家拥有 50 至 250 名员工的中小型公司提供建议,该怎么办?我们还能训练最大似然算法来预测营业额吗?

为了创造一点额外的挑战,并模仿真实生活中的样本,模仿一家中小型公司,我们将从我们完整的 IBM Watson 数据集随机抽取 126 个观察结果。我会播下一颗种子,让它更容易被你复制。

员工流失——什么可能导致员工离职?

现在让我们仔细看看员工流失的两个关键因素之间的相互作用:工作满意度和薪酬。从文献中得出的一个典型假设是,更高的工作满意度与更低的员工流动可能性相关联——不快乐的员工通常有更多的理由离开,因为他们期望在其他地方更快乐,并且不会对当前的组织产生情感上的承诺,这使得一旦找到有吸引力的替代方案,就更有必要和更容易离开(Zimmermann,Swider & Boswell,2018)。

看起来数据总体上支持这一假设:即使分布的尾部表明一些留下来的员工实际上不满意,而一些离开的员工很高兴,但总体趋势表明,离开的员工实际上比我们样本中剩余的员工更不满意。

好吧——但是月收入和工作满意度的组合与员工流失有什么不同呢?更具体地说,收入较低会是那些对工作真正满意的员工离开的原因吗?

当然,我们无法完全确定收入或工作满意度与员工流失之间是否存在因果关系,但看看是否有任何关联的迹象仍然很有趣。令人惊讶的是,对于非常不满意的员工来说,月收入实际上比留下来的员工高。这表明,在员工对工作不满意的情况下,月收入本身并不能真正解释员工流动率——金钱不是一切!这与对薪酬的满意度只是一个硬币的一面的观察结果是一致的:要真正对自己的工作感到满意,员工不仅期望对自己的辛勤工作获得适当的报酬,还期望一系列有助于他们对工作总体满意的因素(例如,来自主管的非金钱支持、与优秀同事的良好关系、工作本身的成就感等)。)(齐默曼等人,2018)。有趣的是,对于更满意的员工来说,这种关系似乎是相反的:正如所料,留下来的人比离开的人工资高得多。我们在幸福阶梯上爬得越高,这种模式似乎就越明显:薪酬差距似乎随着工作满意度的每一级而线性增加。我们可以推测,越满意的员工有更多的资源投入到他们的工作中,使他们更能适应高压的工作要求(巴克&德默罗蒂,2007)。由于薪酬通常与绩效挂钩,这可能会导致两种情况:精力的提升可能会给一些员工带来适当的晋升,让他们更有动力留在当前的雇主身边。但如果他们没有得到任何更好的补偿作为回报,这可能会被视为不公平的,也是离开组织的另一个原因(Birtch,Chiang & Van Esch,2016)。不过,测试这个假设有点超出了本文的范围,并且很难测试这样一个不包含纵向信息的模拟数据集。

但我们可以说,薪酬肯定与员工的工作级别有关,因为经理自然比初级顾问挣得多。如果我们用之前创建的 CompensationRatio 变量交换 y 轴,这些关系成立吗?例如,中到高度满意的员工离职时的工资是否低于他们的工作级别所期望的水平?

不完全是。平均而言,离职者的薪酬通常与同龄人持平,甚至更高。即使看起来不同程度的薪酬竞争力的范围在工作满意度量表的中间稍大一些,这表明已经离开的不太快乐的员工的薪酬竞争力可能会有很大的不同。但是我们应该小心谨慎,避免任何过早的解释:表现出中等程度工作满意度的员工可能比处于更极端水平(非常快乐/不快乐)的员工多得多。如果我们有更多的员工处于满意度分布的中间位置,那么每个级别的薪酬竞争力都被覆盖的可能性会更大,对吗?另一方面,如中心极限定理所述,较大的样本通常导致分布看起来更正态分布且更不平坦,而密度峰值在平均值附近。让我们计算一个快速的健全性检查,看看这如何适用于我们的示例:

哇——在我们的样本中,满意的员工比不满意的员工多,因为他们约占观察结果的 65%。因此,在这种情况下,我们的第二种解释更有可能。乍一看,工作满意度和薪酬竞争力之间没有明显的交互作用,这可能会导致员工流失。

作为一名训练有素的心理学家,我对心理气候如何影响员工离职意愿的问题特别感兴趣。特别是对于建模部分,我们将使用由 Max Kuhn 和其他聪明的贡献者开发的分类和回归训练的缩写 caret 包。Caret 有一个很好的内置函数,可以快速了解我们感兴趣的特性。

因为这些变量的等级本质上是有序的,所以密度图看起来很酷,但在这里可能不是理想的选择:曲线的峰度直接受到我们的阶级不平衡(少数人离开,许多人留下)的影响,这可能会产生误导,我们不希望在没有模式的地方产生幻觉。因此,让我们尝试另一种技术:马赛克图。

vcd 软件包中的 mosaic 函数用来测试样本中的频率是否是偶然产生的。这是通过在后台计算卡方检验来完成的。我们现在可以通过查看矩形的大小和颜色来分析结果:矩形的面积代表任何给定水平组合的病例比例,瓷砖的颜色表示变量之间的程度关系——颜色与灰色的偏差越大,我们就越必须质疑不同因子组合之间的统计独立性(如右侧的皮尔森残差标度所示)。通常,深蓝色代表随机发生的情况比预期的多,而深红色代表随机发生的情况比预期的少。

好的——在我们的例子中,每个瓦片都是灰色的,这表明没有严重偏离统计独立性。只有在环境满意度的情况下,我们才能知道离职者与其他人相比,是否对他们的工作环境过度不满意,正如我们从上面的特征图中得出的接近显著的 p 值和两种分布之间的变化所表明的那样。一个限制可能是镶嵌图函数可能不够敏感,不足以捕捉随机频率分布的轻微偏差-我们仍然有一个小样本量,通过我们尝试研究的分类水平的组合进一步细分。

特征预处理-为分析准备好数据并移除任何冗余

我们现在为实际的建模部分准备好数据集。作为第一步,我们将删除所有不太可能有任何预测能力的变量。例如,employee-ID 不能解释员工流动率的任何有意义的变化,因此现在应该在其他变量中删除它。其他示例包括与其他要素共享大量内容的变量,因此可能会导致多重共线性问题(例如,小时费率和月收入)。我们将通过同时适当地将所有字符串变量(例如,Department)转换为因子来保存缩减的数据集。

为了非常确定我们没有忽略任何高度相关的变量,我们将自动检测并删除它们。为此,我们首先识别任何数字变量,计算相关矩阵,并找出超过 0.5 的相关性。

因此,我们的代码确实标记了一些变量——我们应该仔细看看:“YearsAtCompany”、“JobLevel”、“MonthlyIncome”、“YearsInCurrentRole”和“PercentSalaryHike”。

  • 看来,YearsAtCompany 与 YearsInCurrentRole、YearsSinceLastPromotion 和 YearsWithCurrManager 高度相关。因此,只有一个与时间相关的变量可以保留:我建议保留“自上次晋升以来的年数”,因为这可以解释一些其他变量无法解释的额外差异:它不仅与员工进入公司以来的时间有关,还与没有晋升的年数有关。正如文献所表明的那样,经常因晋升而获得的定期加薪对防止人员流动起到了至关重要的保护作用(Das & Baruah,2013 年)。
  • 工作级别与年龄和月收入高度相关:看似合理的是,年龄越大的员工,他们已经爬上职业阶梯的机会就越大,与前几年相比,他们的收入也显著增加。因为我们已经讨论了月收入的影响,我宁愿放弃工作级别和年龄,而不是我们的收入变量。
  • PercentSalaryHike 与绩效评级高度相关,因为出色的绩效会得到金钱奖励。

在分析了这些变量的相互关系后,让我们修改应该删除的变量列表,并创建一个包含所选变量的新数据框架:

为了让我们的机器学习算法发挥作用,我们需要将这些因素变量转换为虚拟变量。对于每个因素水平,我们将有一个单独的变量来表明相应的参与者是否属于这一类别(例如,一个很少旅行的人将得到 1 而不是 0)。首先,我们将检测除目标(损耗)之外的所有分类变量。然后,我们将利用 caret 的 dummyVars 函数,将其应用于我们的数据集,并创建一个全新的数据框架,其中包含我们选择的一组数值变量、虚拟变量和损耗(是/否)。请注意,插入符号函数 dummyVars 将变量转换为一组完整的虚拟变量,这意味着将覆盖所有因子级别,并且没有一个会被遗漏,这一过程不适用于输出总是与参考级别进行比较的线性模型(例如,如果我们想要比较女性对代表男性员工的截距的影响)。因此,我们的变量是一次性编码的。

接下来,我们将使用 carets nearZeroVar 函数删除不提供任何预测值的变量。它适用于只有一个唯一值的预测值(即“零方差预测值”)。如果我们的所有员工都是经常出差的人,那么所有其他选项(很少出差或不出差)都是空白,这将在我们的统计模型中创建一个常数。它也适用于只有几个唯一值的预测值,这些值出现的频率非常低(例如,如果 100 个员工中有 1 个会离婚)。对于许多模型(基于树的模型除外),这可能会导致模型崩溃或拟合不稳定。作为最后的预处理步骤,我们将确保我们已经正确地排序了目标的因子级别:我注意到在过去,caret 似乎只是将第一个级别作为正类(例如,是对否,赢对输等。)有时会“混淆”混淆矩阵,例如,特异性和敏感性很容易混淆。因此,我们希望通过明确指定“是”和“否”作为流失变量的因子级别,确保实际员工流动被视为正类。

智能建模—通过交叉验证处理小样本中的过度拟合

我们的最终数据集现在已经清理完毕,可以进行建模了。因为我们有一个小样本,我们可能会遇到这样的问题,即我们的模型过于适合特定于样本的数据,以至于我们不能在以后将其应用于新员工数据。这个问题通常被称为过度拟合——这种现象可以解释为什么我们有时无法再复制以前发现的效果。对于机器学习模型,我们经常将数据分成训练集和验证/测试集来克服这个问题。训练集用于训练模型,而验证/测试集用于根据从未见过的数据验证模型。如果我们将传统的 80/20 分割用于我们的用例,模型性能将在很大程度上取决于机会,因为每次算法随机选择 25 个人进行测试时,它都会有所不同。在我们的案例中,这个问题变得更加极端,因为我们有一个不平衡的类别:记住,只有大约 20%的员工离开了公司——这意味着我们的模型可能会在大约 5 名离职者和 20 名剩余者身上进行测试,这给我们留下了一个问题,即该算法是否会在不同的情况下表现相似。此外,如果我们通过查看预测准确性来评估模型性能,结果将很容易高估其实际性能,因为有许多积极的案例作为参考(例如,没有离职的员工)。你可以在这个有趣的 Stackoverflow 讨论中找到更多关于如何从一个小的不平衡数据集中分割数据的问题。幸运的是,我们有统计工具箱里的东西:各种拆分的交叉验证。我们将把我们训练好的模型应用于一组新的观察值,并反复调整参数以减少预测误差。对于这些“新观察值”,我们甚至不需要新的样本:我们将通过将模型训练为一组观察值来回收数据集,并使用另一部分数据来测试模型性能。我们将重复 5 次,并对测试性能进行平均,以获得对我们模型性能的最终评估——一种称为 5 重交叉验证的技术。因此,我们可以利用我们所有的数据,同时仍然在“新”案例上测试模型。

用于相同目的的不同 ML 模型

现在,我们将设置一个可重用的列车控制对象,以使用相同的设置来构建我们的机器学习模型:重复的交叉验证确保我们运行我们的 5 重交叉验证过程 5 次。此外,我们要求 caret 为我们提供模型输出中的类概率以及最终预测,我们希望看到我们建模过程的进展(verbose = True)。我们将使用 caret 的内置超参数搜索及其标准设置。

我们将相互测试的模型如下:

逻辑回归:这是一种广泛使用的传统分类算法,基于统计学课程中的线性回归,最初由 Cox 于 1958 年提出。主要预测输出是观测值属于某个类别的估计概率。基于概率值,模型创建将输入空间分成两个区域的线性边界(例如,更可能是或更可能不是)。

随机森林:基本决策树是以树状方式构建的可解释模型:分支是特征的组合,树叶是感兴趣的类别标签(例如是或否)。随机森林通过结合所有多个弱学习者的力量来进行集体预测,使我们比基本决策树具有优势。这使得比简单的决策树更健壮,因为最终的预测不是由几个有影响的预测者主导的。

【极端梯度推进 (XGB):这种建模技术是陈(2014)介绍的另一种基于树的方法,该方法基于梯度推进树,梯度推进树是 Friedman 在 2001 年提出的用于回归和分类目的的集成机器学习方法。一个关键的特征是它们按顺序学习——每一棵树都试图纠正前一棵树的错误,直到无法实现进一步的改进。与梯度提升树相比,XGB 通常被描述为更快、更可扩展和更高效的技术版本。

GLMnet :这是 glm 模型的一个非常灵活、高效的扩展,在 R 中得到了很好的实现。它使用惩罚最大似然估计来拟合广义线性模型,并因此通过使用套索或弹性净惩罚项来减少常见回归模型(例如,基本逻辑或线性回归)中已知的过拟合。众所周知,它能够很好地处理小样本,更喜欢简单而不是过于复杂的模型,以及内置的变量选择。

朴素贝叶斯:该模型使用著名的贝叶斯定理,因为它基于相关特征的先验知识来估计事件的发生概率。分类器首先学习其输入的联合概率分布,并基于给定的每个相应特征组合的最大后验概率产生输出(例如,是或否)。

类别不平衡的作用—选择适当的精确度指标进行优化

因为我们有不平衡的样本(留下的比留下的多),我们稍后不会准确地评估模型的性能。由于准确性是所有案例中正确分类的案例的比例,所以即使算法简单地将所有案例分类为多数类(例如,否),给我们高分也不是什么大事。如果我们有更多对我们同样重要的平均分布的类,这是一个更合适的度量。但在这种情况下,我们实际上是关于积极的情况:你可以说,如果一个人真的留下来了,没有正确识别离开者(例如,敏感度或真阳性率)比意外预测该员工会离开(假阳性率或 1-特异性)更有害。因此,我想使用 F1 分数作为培训优化的准确性指标,因为它对正确分类积极案例(例如,员工流失)更加重要,对严重不平衡的数据集更有意义。

F1-得分是精确度和召回率的调和平均值:

精度是正确分类的阳性案例的数量除以所有阳性预测的数量(包括假阳性,例如,被确定为离职者但没有去的员工)。也叫阳性预测值。

另一方面,召回是真实阳性病例的数量除以应该被识别为阳性的所有样本的数量(例如,所有实际离开者,即使不是所有都被正确识别)。在二进制分类用例中,它也被称为敏感度。如果您还没有得到它,不要担心,它没有简单的准确性度量那么直观。我希望我的想象能帮助你理解它。总之,F1 分数与算法正确检测阳性病例的能力相关。

因为 caret 没有直接提供 f1 指标作为我们 train 函数的选项,我们将使用在 Stackoverflow 上找到的 DIY 代码。您可以在此找到更多关于精确度指标的信息。顺便说一句,解释其他不是我们达到的 F1 分数是否“足够好”并不容易,因为它很大程度上取决于我们样本中真正阳性案例的数量。因此,我们稍后将寻找我们在相同数据上获得的最高 F1 分数的模型。

决赛模型竞赛——让我们的机器学习算法来比赛吧!

为了有一个好的基线模型与其他模型进行比较,我们将创建一个逻辑回归模型:基于我们之前创建的可视化和心理学文献中的理论,我们假设较高的工作满意度可以防止员工流失。此外,我们假设月收入越低,员工离开公司以获得更高报酬的可能性就越大。此外,我们认为月收入对员工流动的影响会随着工作满意度的提高而放大。对于所有其他模型,我们将把之前选择的所有变量都扔进去,不再做进一步的理论预测。这样,我们可以看到是否给我们一个预测优势。

但是,在我们深入实际的模型比较之前,让我们看看我们的基线模型是否能够真正解释初级阶段的员工流失。

model_baseline
summary(model_baseline)

正如我们的假设所预测的,我们可以看到,模型的估计表明,员工离开公司的可能性随着每月收入每增加一美元和工作满意度每增加一个级别而略有下降。请注意,这些估计值不能直接解释,因为它们是以符合我们的逻辑回归公式的对数优势率来衡量的。互动项(月收入和工作满意度的组合)也变得具有统计学意义(p< .001).

Can the other models with a larger set of predictors do a better job predicting employee turnover in our small sample? Let’s find it out. We will first make a list of all our model objects (random forest, glmnet etc.) and name them for future reference. Then we will use the resamples-function from caret to plot the models’ performance against each. It will give us the range of F1 values across all 5 folds, making it possible to select the model with the highest average performance.

……赢家是:XGBoost!

在正确分类离职者的能力方面,XGBoost 似乎优于所有其他模型,并在所有折叠中表现出相当稳健的性能。我们的基线模型根据用于测试的折叠显示了相当可变的模型性能,使得它看起来有点不稳定。然而,我们在这里通过比较苹果和香蕉做了一些不公平的比较:对于我们的基本模型,我们使用了一个理论上似乎合理的公式,同时我们将所有的候选变量放入其他模型中。在这些情况下,我们试图用一切来预测员工流失。这使得很难判断随机森林算法的模型性能是由于过于复杂的公式还是由于模型本身的种类。我甚至可以想象,一个更简单的模型对我们的情况可能是有益的,因为我们没有足够的观察来证明在我们的模型中使用如此大的一组预测因子。正如 Yarkoni 和 Westfall (2017 年)所指出的,一小组预测值应用于许多观测值的机会越高,过度拟合的可能性就越小,表现为较低的 n/p 比(样本大小与预测值之比)。然而,如果我们有一个小数据集和许多参数,这些参数对结果 X 的贡献都很小,就像在我们的第一轮建模中一样,我们就越有可能获得大的预测误差,并且训练集和测试集之间的性能差距将会很大。

因此,我们将通过演示如果您让 caret 用工作满意度、月收入以及所有模型的这些指标的组合来预测员工流失率会发生什么,来进行更公平的比较:

现在,随机森林似乎不再显示最差的性能,但 XGB 似乎再次成为我们的赢家。有趣的是,F1 分数包含非常相似的值,就像我们的复杂模型一样,这表明一个更加节俭的模型比过于复杂的模型更可取。让我们看看混淆矩阵是否能告诉我们更多关于 XGB 性能的信息,包括与基线模型相比的简单模型公式。提醒一下,这就是这样一个混乱矩阵如何转化为我们的问题。

我们基线模型的准确性度量

我们基线模型的准确性度量

我们的 XGBoost 模型的准确性度量

XGBoost 模型的精度指标

哇——直接比较表明,XGBoost 在预测员工流失方面比我们的基线模型好得多!通过查看原始的混淆矩阵,我们可以看到 XGBoost 正确地识别了 22 个离开者中的 17 个,而基线模型只识别了其中的 3 个。我们的 winner 模型的精确度非常高(0.94),这意味着它没有混淆真实离职者和虚假离职者(误报,即实际上没有离开公司但留下来的员工)。另一方面,基线模型仅预测了 4 个阳性病例,其中 3 个是正确的,导致 0.75 的相当差的精度。对于其他指标,正确检测员工流失的能力变得更加明显:因为 XGBoost 算法也错过了 5 个真正的阳性案例,并错误地将它们标记为阴性,所以召回率不是非常高,但仍然可以接受(0.77)。提醒一下,回忆是真实阳性病例的数量除以应该被识别为阳性的所有样本的数量(例如,所有实际离开者,即使不是所有都被正确识别),也称为敏感度。相比之下,基线模型不够敏感,无法找出真正的离职者,并意外地将其中的大多数人标记为剩余员工。

底部的平衡准确度分数也反映了绩效差距,它代表了相应模型的特异性和敏感性之间的平衡,表明我们的基线模型在正确识别忠诚员工方面表现不佳。除 F1 分数外,平衡精度被认为是不平衡样本中模型精度的更好代表

总而言之,XGBoost 似乎比简单的广义线性模型更具预测优势,即使我们保持预测因子不变。

离职风险?制定数据驱动的保留策略

下一步,我们希望实际使用该模型来提高我们小公司的保留率。为此,我们将首先获得仍然活跃的员工的指数,并根据我们的模型预测这些员工离职的可能性。然后我们将保存这些概率以及实际的员工数据。最后,我们将找出离职风险最高的前 5 名员工。为了给公司一个介入的机会,这些人可能是应该首先招募的,以了解他们需要什么来变得更快乐,以及他们希望未来如何发展。这样,我们就有希望解决任何自愿离职的问题。最后,我们将向经理们提供一份完整的员工名单,按照离职风险排序——毕竟,让员工有机会摆脱可能改善工作氛围的建设性反馈是件好事。

从我的错误中吸取教训——我还没有告诉你的…

  • 不要使用 tibbles 进行建模

在我发现 data.table 语法的美妙之处之前,我曾经使用过 tibbles,因为我认为%>%运算符是一个非常直观的工具。不幸的是,caret 只接受数据帧(或 data.tables ),而不接受 tibbles,我花了很长时间才弄明白为什么我的代码不能运行。直到我发现了在 github 上的这个评论,并把整个数据争论部分改成了类似 DT 的结构。确保在使用 caret 建模之前将 tibbles 转换为经典数据帧,或者首先不要使用 dplyr 语法。

  • 合适的精度度量带来如此巨大的差异

此外,我首先使用 AUC ROC 分数作为优化的指标,然后发现它也可以与其他指标(例如 F1 分数)一起使用。这导致了一个可怕的模型性能,敏感性得分低于 0.1-算法没有真正检测到积极的情况(例如,实际的员工流失),这可能是由于我们严重不平衡的数据集造成的。正如之前预测的那样,模型摘要仍然显示了可接受的准确性分数,因为对于模型来说,识别那些留下来的人并不是一件大事,因为大多数员工无论如何都不会流失。使用更合适的优化指标确实改变了游戏规则,极大地提高了模型性能。

  • 我们的结果具有高度的样本特异性

在我为从原始 IBM HR analytics 数据集抽取随机样本时的复制目的设置种子之前,我意识到样本与样本之间的结果会有很大不同。对于环境或关系满意度等心理变量来说尤其如此。即使这对您来说听起来有点显而易见,但请思考这对于您没有任何更大的数据集可供从中提取子集的情况意味着什么:您对数据生成过程的解释(例如,哪些因素可以解释员工流动)会有很大的偏差,但由于缺乏数据,您还没有任何机会验证它。在我们有机会在更大的人群中证明之前,这应该使我们在对自然界的一般模式得出初步结论时小心谨慎。此外,请记住,数据集是虚构的,因为它不包含真实的人力资源员工数据,所以它不应该被用作回答真正科学问题的单一来源。

是时候深入思考了——我们能在小样本中预测员工流动率吗?

照片由克雷格·任Unsplash 上拍摄

从技术角度来看,我认为我们确实可以利用机器学习来预测员工离职,即使是在小样本中,如果你有一个完整的高质量的数据集。此外,我们已经看到,当涉及到预测器的数量时,一个更简单、更节俭的模型至少可以与一个复杂的模型表现得一样好。然而,机器学习模型的类型会对我们预测的准确性产生巨大的影响。从更广泛的角度来看,我们需要意识到这样一个事实,即我们似乎不可避免地会捕捉到某种程度的特定于样本的错误,而这种错误不会推广到新员工。因此,不建议让算法独自决定人们的工作和生活——作为人类,作为数据科学家、经理或人力资源专家,我们需要为在我们监督下做出的决定负责。

有几种方法可以增加我们的数据驱动方法对外部各方的透明度:如果我们在评估数据之前没有强有力的假设,明确声明我们的工作在本质上是探索性的可能是有帮助的,因为我们的解释有些事后性,因此可能有偏见。这个限制也适用于我们的方法,因为我们在指定我们的模型公式之前检查了驱动员工流动的潜在心理原因。在一天结束时,利用两个世界可能是最有成效的:调查数据背后的根源和原因,拓宽我们对数据中我们实际上并没有首先假设的模式的看法,并总是测试模型预测样本外行为的能力,以最小化过度拟合。因此,结合一定程度的理论灵活性和对数据的仔细解读,我们可以做出良好合理的预测。

当你真正考虑在你的组织中部署人力资源分析工具时,该模型的最终用户需要了解它的好处和局限性:即使我们理解增加流动可能性的共同根源,人和组织仍然是非常独特的——离开的原因也是如此。因此,导致频繁离职的个人和实际原因可能会因公司而异,甚至会随着时间的推移而变化。因此,当一个预测模型被应用时,在它已经过时并犯下严重错误之前,必须不断地对它进行评估。我是数据驱动技术的超级粉丝,如果我们深思熟虑地使用它们,机器学习技术可以成为一个强大的工具,来永远改善工作场所。但如果我们机械地使用它,它很容易成为危险的黑盒人工智能批评者担心,我们的社会不应该以此为目标。所以,让我们保持对数据的关注。

参考

[1] A. Hammermann & C. Thiele, 人物分析:evidentizbasiert Entscheidungsfindung im personal management(2019),(№35/2019),IW-报告。

[2] R. S. Sexton,S. McMurtrey,J. O. Michalopoulos & A. M .,员工流动:一种神经网络解决方案 (2005),计算机&运筹学32 (10),2635–2651。

[3] J. P. Isson & J. S. Harriott, 大数据时代的人物分析:改变你吸引、获取、发展和留住人才的方式 (2016),John Wiley & Sons。

[4] L .博克, 工作规则!:谷歌的艺术和思维,我们的生活和工作。 (2016) 瓦伦。

[5] Y. Zhao,M. K. Hryniewicki,F. Cheng,B. Fu & X. Zhu,用机器学习进行员工离职预测:一种可靠的方法 (2018),载于SAI 智能系统会议论文集(第 737–758 页)。斯普林格,查姆。

[6] T. Yarkoni & J. Westfall,《在心理学中选择预测而非解释:机器学习的教训》 (2017),心理科学视角12 (6),1100–1122。

[7] A. A. Mahmoud,T. A. Shawabkeh,W. A. Salameh & I. Al Amro,使用机器学习进行招聘流程和绩效评估中的绩效预测 (2019),载于 2019 年第十届国际信息与通信系统会议(ICICS) (第 110–115 页)。IEEE。

[8] D. H. Kluemper,P. A. Rosen & K. W. Mossholder,社交网络网站、个性评级和组织环境:比看上去的更多?(2012)1。应用社会心理学杂志42 (5),1143–1172。

[9] A. Apatean,E. Szakacs & M. Tilca,基于机器学习的人员招聘应用 (2017),Napo censis Technica58 (4),16–21。

[10]李延明,赖超英,高春平,将人格特质与支持向量机结合以获得人员招聘的素质匹配 (2008),载于第四届国际商务与信息会议(第 1-11 页)。

[11] T. Chamorro-Premuzic,D. Winsborough,R. A. Sherman 和 R. Hogan,新人才信号:闪亮的新物体或勇敢的新世界 (2013),Ind .风琴。心理学。透视。Sci。实践。, 53:1689–1699.

[12] E. Faliagka,K. Ramantas,A. Tsakalidis & G. Tzimas,将机器学习算法应用于在线招聘系统 (2012),载于 Proc .互联网和网络应用及服务国际会议(第 215-220 页)。

[13] M. Loi,民智必须造福于民。人力资源管理中数据驱动算法系统的伦理分析 (2020 年)算法观察

[14] N. B. Yahia,J. Hlel & R. Colomo-Palacios,从大数据到深度数据支持人员分析进行员工流失预测 (2021), IEEE Access9 ,60447–60458。

[15] G. Harden,K. G. Boakye & S. Ryan,技术专业人员的离职意向:一个社会交换理论的视角 (2018),计算机信息系统杂志58 (4),291–300。

[16] J. Sarkar,薪酬与离职挂钩:回顾与未来方向 (2018), IUP 组织行为学杂志17 (1)。

[17] P.C. Bryant & D. G. Allen,薪酬、福利与员工流失:留住顶尖人才的人力资源战略 (2013),薪酬&福利回顾45 (3),171–175。

[18] R. D. Zimmerman,B. W. Swider & W. R. Boswell,员工离职内容模型综合 (2019),人力资源管理58 (1),99–114。

[19] A. B. Bakker & E. Demerouti,工作需求‐资源模型:最先进水平 (2007),管理心理学杂志

[20] T. A,Birtch,F. F. Chiang & E. Van Esch,一个理解工作特征-工作结果关系的社会交换理论框架:心理契约履行的中介作用。 (2016),《国际人力资源管理杂志》27 (11),1217–1236。

[21] M .库恩、j .温、s .韦斯顿、a .威廉斯、c .基弗、a .恩格尔哈特。,… & M. Benesty,包'脱字' (2020),R 刊223

[22] B. L. Das & M. Baruah,员工保留:文献综述(2013),商业与管理杂志14 (2),8–16。

[23] T. Chen & Guestrin, Xgboost:一个可扩展的树提升系统 (2016),载于第 22 届 acm sigkdd 知识发现和数据挖掘国际会议的会议录(第 785–794 页)。

人类不是天生的数据讲述者,但你可以

原文:https://towardsdatascience.com/humans-arent-natural-data-storytellers-but-you-can-be-fed221526356?source=collection_archive---------30-----------------------

尽管你很少会在 LinkedIn 上看到招聘数据说书人的招聘信息,但能够将算法、管道和图表转化为引人注目的商业故事的人是雇主需要的资产

卢克·切瑟Unsplash 上拍摄的照片

虽然 Glassdoor 将数据科学列为 2021 年的第二大工作,但进入就业市场从事任何数据驱动的工作都具有竞争力,因为 48%的数据科学家已经获得了博士学位,比 2020 年增加了 5%。随着对入门级数据职位的技术能力和商业头脑的期望飙升,你将如何在当前的就业市场中脱颖而出?

做一个讲数据的人。

掌握使用数据推动叙事的技巧。知道能够在 ggplot 中生成散点图和能够清楚地表达其结果或为高管团队构建一个可访问的仪表板是有区别的。

构建数据故事

Excel、PowerBI 和 Tableau 等商业智能软件的普及意味着,在创建可视化的那一刻,很容易欺骗自己相信自己是一个数据故事讲述者。真正的数据叙事意味着能够向非技术受众传达复杂的想法。

《用数据讲故事》一书的作者科尔·努斯鲍默·克纳弗里克强调,尽管人类可能是天生的故事讲述者,但我们不是天生的数据故事讲述者。

虽然有机故事有开头、中间和结尾,但很难想象一个商业案例,如收入报告,遵循三幕结构。呈现数据报告的一个缺陷是缺乏背景。能够用通俗易懂的语言将方法和结果联系起来并加以解释,无疑会比技术技能更能让你脱颖而出。

提供我自己的背景,尽管我现在从事数据工作,但我的本科学位是新闻学,在获得数据科学硕士学位之前,我在媒体工作了几年。我应用于数据工作的一项可移植技能是,像记者构建新闻故事一样构建演示文稿:简洁、清晰、引人注目——一次完成。

新闻学院和整个媒体行业利用倒金字塔结构,从最重要的信息开始,变得更加具体,而不是建立一个大的想法。你可以这样组织你的演讲,记住五个 w 和一个 H:谁,什么,哪里,什么时候,为什么和如何。使用这种结构可能感觉像写备忘录,但它将有助于简化你的信息。

五个 w 和一个 H

考虑以下假设场景:您组织的核保部门负责人希望利用人工智能的力量来构建一个工具,该工具可以预测您公司的哪些客户将在贷款上违约。

将它分解成问题有助于澄清意图和期望的结果。

  • 我们为谁工作?承销团队
  • 我们提议的是什么?一种分类模型,可以预测贷方拖欠贷款的可能性
  • Where (我会用 Where 代替一个团队需要/利用的资源)?我们将使用来自 API、我们专有的抵押计算器和数据仓库的数据
  • 什么时候?最终模型将在第三季度末部署,每两周更新一次,讨论功能预处理、功能工程和部署
  • 为什么?由于过去一年的利率处于历史低位,申请人数量增加,增加了不合适债务人的可能性
  • 如何?数据科学团队将选择具有统计显著性的特征,并设计一个回归模型,该模型可以从存储的信息和第三方数据的组合中获取并做出预测

照片由王德·古普塔Unsplash 上拍摄

五个 w 中最难也最容易被忽略的是为什么。然而,在数据科学背景下,为什么是最重要的问题。开始一个没有明确目标的项目只是毫无意义的实验,不会迫使利益相关者为构思、开发和部署分配时间或资源。

为了进一步完善你的技能,我建议拿起一本关于数据讲故事的书,比如前面提到的用数据讲故事可视化这个:内森·尤的《流动数据设计、可视化和统计指南》。或者,细读一下数据新闻手册也无妨,这是一个面向记者的免费资源,但也适用于任何学习可视化的人。

数据讲述工程师

人们可能很容易将讲故事和沟通技巧视为软技能,就像大多数招聘广告倾向于做的那样。然而,帮助非技术受众在逻辑和情感层面上理解您希望完成或刚刚完成的内容具有巨大的价值。那些不仅能够很好地编码,而且能够解释其输出的可行性的人可以在工作面试、领导演示和职业发展中大放异彩。

人类与机器

原文:https://towardsdatascience.com/humans-with-vs-machines-a76dbd51161e?source=collection_archive---------32-----------------------

一个受监管的人工智能行业如何才能导致良好的人机关系

安德烈·德·森蒂斯峰在 Unsplash 上拍摄的照片

所以我们向你们保证,他们永远,永远,永远不会变得邪恶——“米切尔对机器”

如果你认为我在天马行空地谈论人工智能设备能对我们做什么,那你就错了。

我最近看了电影《米切尔夫妇与机器》,看到人工智能机器人通过将人类放入豆荚来接管世界的画面,我感到非常震惊。这些太空舱将永远被放入太空,此后世界将由机器统治。

这既不是美好的结局,也不是我们当初设计如此先进的技术时所设想的世界。

在另一个深思熟虑的例子中,这部电影展示了所有设备如何获得感知能力,并形成一个社区,根据一个支持人工智能的高级数字助理的命令采取行动,这个数字助理似乎是其盟友的创造者。

看到这些设备如何变得“情绪驱动”,将世界带入一场灾难,令人绝望。

虽然我可以继续谈论这部电影及其有趣的信息,即如果“技术的自由使用不受控制”可能会给我们带来的危险,但让我们快速跳到我今天帖子的核心本质。

艾可能会出现在这部电影的反派,但它本来就不是。人工智能只是一种技术,除非被设计成这样,否则不会造成破坏——我知道这听起来很明显,但值得同等重视。

因此,在我们做出判断之前,让我们看看这项技术的两个方面:

好的一面:

来源:PCH . vector 创建的人物向量

  • 农业
  • 减少空气和水污染
  • 通过减少塑料垃圾来改善海洋生物
  • 医疗保健的进步…

“另一面”:

侵犯隐私:照片由凯利·麦克林托克Unsplash 上拍摄

  • 隐私侵犯
  • 行为操纵
  • 24*7 虚拟监控
  • 结构偏差的放大

作为一名数据科学家,我明白人工智能不会给我们带来任何好处,因为它本身不会给我们带来坏处。

AI 和我们使用它的“意图”一样好。意图总结了我们试图让人工智能适应的所有好的或坏的结构。

好日子来了:

人工智能拥有巨大的未开发潜力,可以在创新的道路上取得进展,并为人类带来众多好处。

但是正如我们在上面读到的,人工智能伴随着它的风险,伴随着风险产生了对监管框架的需求。

然而,法规也需要有一个基本原理,以便不阻碍好的人工智能的飞行,并拯救“人类利益不落入恶意之手”

带领我们通过:

欧盟于 2016 年通过了数据保护和隐私法,通用数据保护条例( GDPR)。

正如维基百科所说,

GDPR 的主要目标是让个人控制他们的个人数据,并通过统一欧盟内部的法规来简化国际业务的监管环境

继保护个人数据的使用和传输之后,欧盟委员会宣布了一项监管框架提案,以管理高风险的人工智能系统和应用。

在更广泛的层面上,该法规涵盖了违反欧盟价值观和基本权利的人工智能系统,并确保了这些与人类互动的系统的透明度。还需要定期评估、评价和审查法规。

我一直关注人工智能在操纵用户意识和驱动决策方面的应用。该条例旨在谴责这种基于年龄、身体或精神残疾利用一群人的脆弱性的做法。

作者使用 PowerPoint 创建的快速笔记

它也不鼓励对自然人进行社会评分,因为这可能导致对他们不利或不利的待遇,从而导致最初收集数据的环境不同。

该规定提出,非高风险人工智能系统可以自愿遵守高风险系统的要求。

我们已经多次谈到高风险系统,现在是我们阐明这种系统的构成的时候了。

高风险 AI 应用:

如果产品或系统带来重大风险或预期风险会显著增加,从而危及人身和财产的健康和安全。

除了高风险人工智能系统提供商,用户和人工智能价值链上的其他参与者,如进口商、经销商和授权代表,也需要遵守这些义务。

敢不从(双关):

不遵守规定是一件代价高昂的事情。百分比是指违规公司在上一个财政年度的全球年营业额。

添加了表情符号的作者

前方有什么?

虽然我高度赞赏监管提案,并强烈认为人工智能行业需要通过此类框架进行及时干预,以看到“人工智能永远消失”的那一天,但寻求利润的企业可能会寻找一种方法,以避免不利于其增长的限制。

我希望这种规定在全球得到尊重和遵守,以便任何人都没有安全的避难所来逃避这一框架,并以任何形式扩散其伤害人类的方式。

参考资料:

加湿咖啡,脱气更快,浓缩更好

原文:https://towardsdatascience.com/humidified-coffee-for-faster-degassing-and-better-espresso-3bdf601b2890?source=collection_archive---------18-----------------------

咖啡数据科学

探索湿度对多次烘烤的影响

在意式浓缩咖啡中,一个好镜头的主要变量是烘焙时间。这在浓缩咖啡中比其他方法更具挑战性,因为在喷射过程中释放的 CO2 会减缓流动和提取。让烤肉放置几个星期,大部分二氧化碳就会释放出来,这样就更容易拍出最好的照片。

通常情况下,我会让我的烤肉放置 3 到 5 周,因为我发现这是品尝和提炼的最佳时机。这么长时间休息的唯一问题是氧化。我已经用真空罐子将氧化降到最低,但是这个过程只能通过冷藏或冷冻来减缓。然而,冷过程也会减缓脱气。

最近,我尝试了一个奇怪的测试,在咖啡中加入一个湿度控制袋。我很快意识到我无意中发现了一些奇妙的东西。镜头更好吃,但他们也流动得更快。他们表现得好像被脱气了一样。我研究了一种方法,并在这里描述了一种方法,可以加速新鲜烘焙食品的脱气,从而改善风味和提取。

咖啡湿度的历史

几个月前,我看了一段詹姆斯·霍夫曼的视频,视频中他使用湿度控制袋储存咖啡,这是他从哈马德·拉赫希德那里得到的想法。两年前,哈马德开始研究利用湿度来长期储存咖啡。两人都在研究利用湿度来陈化咖啡豆,詹姆斯指出二氧化碳的缺乏。他也注意到了不同的味道。

在此之后,没有太多的探索或讨论。我开始观察这一地区,看是否能为他们的观察提供一些数据。

加湿咖啡

最初,我打算把湿度控制袋放在里面更长时间,但是在第一次烘烤后,我决定只把它放在容器里几天(大约 5 天)。然后我用一个真空罐。所以我称之为湿度处理或加湿咖啡。

我发现加湿咖啡会让咖啡豆更快脱气。他们还增加了大约 1%的体重。我的大部分烘焙食物由于水分减少了大约 13%的重量,这很典型。

当观察研磨分布时,加湿咖啡会导致咖啡研磨得更粗糙。为了达到同样的效果,我必须在利基市场做得更好。我从典型的设置 13 到设置 5,以达到类似的研磨分布。下面,就是蓝色虚线和绿色线条。其他研磨设置仅供参考。

绩效指标

我使用两个指标来评估技术之间的差异:最终得分和咖啡萃取。

最终得分 是评分卡上 7 个指标(辛辣、浓郁、糖浆、甜味、酸味、苦味和回味)的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难确定。

使用折射仪测量总溶解固体量(TDS),这个数字结合咖啡的输出重量和输入重量用于确定提取到杯中的咖啡的百分比,称为提取率(EY)** 。**

设备/技术

浓缩咖啡机:金特快

咖啡研磨机:利基零

咖啡:中杯家庭烘焙咖啡(第一口+ 1 分钟)

镜头准备:断奏夯实

输液:压力脉动

过滤篮:20g VST

输入/输出:21g 输入,约 24g 输出

其他设备:Atago TDS 测量仪,Acaia Pyxis 秤

表演

我看了 6 次烘烤的 37 对照片。通过连续拍摄相互比较来确定配对。挑战在于,我必须等三个星期才能使用常规烘焙,所以除了第一次烘焙,每一对都是在不同的时间品尝和取出的。

在所有指标中,加湿咖啡更好。以下是最终得分(口味)和 EY/TDS:

****

我们可以通过烘烤来分开,看看一些有趣的簇在哪里。2021 年 9 月 17 日的烘焙比其他人的改善要少。

****

比较烘焙时间,与第 3 周到第 4 周的普通咖啡相比,我在前两周使用了大部分的加湿咖啡。

****

加湿咖啡的拍摄时间下降。这使得比较相同量的预输注具有挑战性,但我试图为每一个都拍摄最佳镜头。

我在这张表格里做了一些一般的烘烤统计。请注意,两次烘烤(2021 年 9 月 17 日和 2021 年 9 月 20 日)在加湿的同时放入冰箱,但它们随后像其他烘烤一样储存在室温下。

然后,我使用双尾 t 检验计算了 37 对样本的统计显著性。我添加了一列,在那里我将加湿咖啡的所有 EY 值调整了 1.5%,因为它们增加了大约 1.5%的重量。这意味着如果你放入 20 克咖啡,其中约 1.5%来自水,所以更高的 TDS 意味着 EY 更高。

推荐

  1. 添加湿度控制袋 5 至 7 天的中等烘烤。你必须尝试其他的烘烤等级。我使用了 69%的湿度控制。你可以使用少量的水,大约是咖啡总重量的 1%到 2%。
  2. 磨得更细。在利基市场上,我建议从 5 到 6 级开始。
  3. 加大剂量。我一直用稍微高一点的剂量玩,因为子弹射得太快了
  4. 稍微降低水温以减缓水流。

我开发了一种工艺来处理新烘焙的咖啡豆,使它们更快脱气,并在两周前准备好用于浓缩咖啡。这一湿度过程大大增加了风味和提取。湿度处理对于人们在家或在商业环境中是实用的,因为它只是暂时改变咖啡的储存。也有可能在储存过程中向咖啡中加入少量的水(约为重量的 1%),但我还没有测试过。

我还注意到,经过潮湿处理后,照片没有那么酸了。这在味道上非常明显。詹姆斯·霍夫曼(James Hoffman)描述说,存放了几个月的咖啡有一种奇怪的味道,我确实注意到,经过湿度处理后,最初的一两次味道有所不同,但这种味道似乎很快就消失了。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我订阅

我的进一步阅读:

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事启动页面

摄影启动页面

使用图像处理测量咖啡研磨颗粒分布

改进浓缩咖啡

断奏生活方式概述

测量咖啡磨粒分布

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡滤纸

浓缩咖啡篮及相关主题

意式咖啡观点

透明 Portafilter 实验

杠杆机维修

咖啡评论和想法

咖啡实验

潮湿的咖啡随着时间的推移

原文:https://towardsdatascience.com/humidified-coffee-over-time-4b41f108d30d?source=collection_archive---------19-----------------------

咖啡数据科学

探索湿度对时间的影响

之前,我发现加湿咖啡可以在几天内快速脱气,而不是几周(对于中度烘焙)。此外,味道和提取改善,这是一个额外的奖励。

我想更好地了解这些影响,所以我做了一次烘烤,并将湿度控制袋放在烘烤中两周。我收集了一些关于体重增加、研磨分布和每日拍摄的数据。

所有图片由作者提供

重量的增加

我用我的 Acaia Pyxis 秤来测量烤肉的重量。我开始对烤肉进行取样,所以我测量了每次拍摄之间的百分比变化,并在最后将它们合并。

我通常在 5 天后将湿度控制袋拿出来进行其他烘烤,这导致重量增加了约 1.2%。当体重增加时,我很担心,因为有持续的变化。

咖啡研磨颗粒分布

我每天测量研磨分布。日班不多,但几天后,有必要去研磨设置更好。

此外,当我移除湿度控制时,研磨分布开始变得更细,这表明随着水从豆子中出来,效果会逐渐消失。

绩效指标

我使用两个指标来评估技术之间的差异:最终得分和咖啡萃取。

最终得分 是记分卡 7 个指标(尖锐、浓郁、糖浆、甜味、酸味、苦味和回味)的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难确定。

用折射仪测量总溶解固体量(TDS),这个数字结合咖啡的输出重量和输入重量用于确定提取到杯中的咖啡的百分比,称为提取率(EY)** 。**

设备/技术

浓缩咖啡机:金特快

咖啡研磨机:利基零

咖啡:中杯家庭烘焙咖啡(第一口+ 1 分钟)

镜头准备:断奏夯实

输液:压力脉动

过滤篮:20g VST

其他设备:Atago TDS 测量仪,Acaia Pyxis 秤

表演

这些镜头的味道是一致的,但在最后几天急剧下降。这些镜头尝起来很旧。

对于 EY,它们在开始时增加,然后保持,但在最后两次拍摄中也有所下降。这有助于降低阴囊的味道。

拍摄时间下降,直到我不得不做更精细的研磨。这是可以预料的,并且可能与脱气发生的数量有关。

克丽玛

为了更好地理解克莉玛的变化,我查看了一些烘烤的数据,包括有湿度和没有湿度的情况。我用视频的最后一帧测量了克丽玛,当时镜头还在拉。我测量了从咖啡线到克莉玛线顶端的毫升数。虽然一些照片储存在潮湿的环境中,但大多数照片没有。

水与湿度

可以用一点水来代替湿度控制袋。所以我在水中加入 1%的豆子,放置 5 天,然后我做了一些配对拍摄。我没有看到很大的不同。所有的水分都被豆子吸收了,我想我可以收集更多的数据,但看不出有什么不同。然而,这是一个我没有兴趣继续下去的实验。我认为用水是比购买湿度控制袋更可行的选择。

****

这些数据更好地帮助我理解了湿度是如何影响豆子的。该机制似乎是脱气,因为克莉玛减少了。这允许更高的提取率,带来更好的味道,因为咖啡豆暴露在更少的氧气中(导致氧化)。

如果你愿意,可以在推特、 YouTubeInstagram 上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。也可以关注我在订阅

我的进一步阅读:

我未来的书

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事启动页面

摄影启动页面

改善浓缩咖啡

断奏生活方式概述

测量咖啡磨粒分布

浓缩咖啡中的粉末迁移

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡滤纸

浓缩咖啡篮及相关主题

意式咖啡观点

透明 Portafilter 实验

杠杆机维修

咖啡评论和想法

咖啡实验

用深度学习猎水雷

原文:https://towardsdatascience.com/hunting-naval-mines-with-deep-learning-8cbc3c872db1?source=collection_archive---------33-----------------------

一种帮助改进水雷探测的模型,使用自动编码器进行特征选择,使用深度神经网络进行二进制分类

用于海军水雷防御的机器人潜艇|图片由美国海军研究所提供

问题的简要介绍

毫无疑问,水雷是影响海洋航行的一个重要因素。几十年前就有很多了。生产和埋设地雷的费用通常是清除费用的 0.5%至 10%,而清除一个雷区的时间可能是埋设地雷的时间的 200 倍。现在仍然存在一些可以追溯到第二次世界大战时期的海军雷场,并且在许多年内仍然是的危险区,因为它们太大,清除起来太昂贵。

在下面的段落中,将讨论几个深度学习实现。为了保持对项目的友好描述,建议您在阅读文章的同时阅读下面报告中提供的笔记本。提供了 2 个笔记本,在第一个笔记本中,训练了一个自动编码器。第二,自动编码器的编码器部分用于训练一个神经网络二元分类器。这些笔记本也有 Kaggle 版本。

本文的数据集包含从金属圆柱体和岩石上以不同角度和不同条件反射声纳信号获得的模式。传输的声纳信号是调频啁啾声,频率上升。每个模式是一组 60 个频率区间,范围从 0.0 到 1.0。每个数字代表特定频带内的能量,在一定时间内进行积分。

每个类别的功率谱密度示例|按作者分类的图像

如果物体是岩石,则与每个记录相关联的标签包含字母“R ”,如果是地雷(金属圆筒),则包含字母“M”。标签中的数字按方位角的升序排列,但它们不直接对角度进行编码。数据集在类别之间几乎是平衡的,如下图所示。

按作者分类的数据集|图像中的类别分布

设计解决方案

每个人都同意数据中的维度是一个诅咒,拥有许多不同的维度往往会导致算法和模型表现不佳。对于深度神经网络来说,这并不是例外,这篇文章将试图证明这一点,在提供的笔记本中有更多的信息。即使数据集只有 60 个维度,问题依然存在。请记住,例如,对于图像,问题可能会大几个数量级。

由于我们有许多维度,我们可以训练一个自动编码器网络,这是一种无监督的深度学习技术,以减少变量之间的共线性,并有望使用更小维度的分类器,可以表现得更好。或者,也可以使用传统的 PCA,但是一般来说,自动编码器的 T2 表现更好。

变量之间的相关性|作者图片

从前面的图中可以看出,变量之间存在一些相关性,可以使用所提出的方法来压缩这些信息。

自动编码器结构

自动编码器由两个主要部分组成,编码器和解码器网络。编码器网络在训练和部署期间使用,而解码器网络仅在训练期间使用。编码器网络的目的是发现给定输入的压缩表示。在这个项目中,一个 10 维的表示是从一个 60 维的输入生成的。这发生在自动编码器的中间,也就是所谓的瓶颈。解码器网络只是编码器网络的反映,其目的是尽可能接近地重建原始输入。

自动编码器结构| Chervinskii —自己的作品,CC BY-SA 4.0

该网络也有两个优化。使用了批次标准化来稳定学习过程,并显著减少实现最小损失所需的时期数。此外,选择了泄漏 ReLU 激活,而不是常规 ReLU。第一种倾向于提高网络性能,实现更小的损耗值。

Autoencoder 培训和测试损失|作者图片

作为基线比较,选择了逻辑回归模型。它在一种情况下用 60 个输入进行训练,在另一种情况下用 10 个输入的压缩版本进行训练。这些结果随后得到了测试数据集的验证。尺寸较小的模型略胜一筹。这表明减少变量的数量确实有好处。

深度学习分类器

为了创建一个降维的分类器,在训练之后只使用自动编码器的第一部分,特别是编码器部分。这组层连接到分类器的输入。一组完全连接的层跟随编码器部分,直到到达输出,这最后一层仅由一个神经元组成。所描述的网络输出与原始论文中的略有不同,因为作者定义了两个输出:每个类一个。

作为二进制分类器的输入连接的编码器|由作者创建的图像

为了训练这个网络并避免过度拟合,使用了提前停止回调。这样,当被监控的度量不再改善时,训练停止。测试损失已被用作提前停止的监控参数。结果可以在下面看到,蓝色的图属于训练数据集上的损失和准确性。测试数据集中的结果用黄色曲线表示。

压缩神经网络|图像的训练集和测试集的损失和准确性(作者)

可以将结果与用非压缩输入训练网络后获得的结果进行比较。在这种情况下提出的网络模型是:

inputs --> 30 --> 20 --> 10 --> 5 --> 3 --> output

每个数字代表每层神经元的数量。在下图中,可以观察到在模型开始过度拟合之前,在测试数据集中获得的准确度不超过 80%。

未压缩神经网络的损失和准确性|图片由作者提供

最后,给出了简化模型的混淆矩阵。大多数案例都被正确分类,这表明模型具有几乎最佳的泛化能力。由于它倾向于探测地雷而不是岩石,这种假阳性产生了更安全的偏差。

那又怎样?

在分析结果之后,可以观察到用自动编码器执行的特征提取有助于分类器网络实现更高的精度值。结果与 Gorman 和 Sejnowski 在原始论文中获得的结果一致。然而,为了获得相同的结果,他们训练了一个具有大约 12 个隐藏层的模型!。在相同的方向上,对于具有 3 个隐藏层并且没有编码的网络获得的结果类似于前面提到的论文。

一些的其他努力已经完成,以增加准确性减少隐藏层的神经元数量(修剪)没有成功。还有另一个出版物专注于几个经典机器学习(ML)优化模型的比较,取得了与此类似的结果。这一结果是在使用 WEKA 软件应用特征选择技术后获得的。然而,它不能提供神经网络的良好性能。

最后,有一篇优秀的文章分析了不同的神经网络架构。其中也有与经典 ML 模型的比较。作者提出了一种特征去除技术,在分析了随机森林模型的影响因素后,通过简单地删除那些对其影响较小的变量。

最后的话

自动编码器在特征选择过程中表现出良好的性能。即使当我们像这样处理结构化数据时。该项目的主要目标是在训练模型之前分析自动特征选择的用例,特别是深度神经网络。在其他用途中,可以提到目前在移动电话中广泛使用的数据压缩。自动编码器的另一个用例是图像去噪。在 Keras 官方博客中有一个关于 autoencoder 应用的极好的条目。这是由弗朗索瓦·乔莱写的,他是 Keras 的创造者,也是一本伟大的深度学习的作者。

除了自动编码器的所有好处之外,由于它们是特定于数据的,这使得它们对于现实世界的数据压缩问题不切实际:您只能在与它们被训练的数据相似的数据上使用它们。如果有人假装在一般应用中使用它们,这将需要大量的训练数据。

谢谢你来到这里。你可以从这个 repo 中获得本文使用的笔记本。我随时可以谈论数据科学,请随时通过 twitter 联系我。

参考

博客

在 Keras 中构建自动编码器

用于分类的自动编码器特征提取

使用神经网络和 keras 构建您的第一个二元分类器

声纳数据——水雷 vs 岩石——关于 cAInvas (太大的神经网络)

重温机器学习数据集——声纳、地雷与岩石

报纸

为分类声纳目标而训练的分层网络中隐藏单元的分析

通过声纳预测水下水面目标:机器学习案例研究

神经网络对声纳目标、地雷和岩石进行分类(结果不佳)

与熊猫的狩猎威胁🐼👊——MFT 分析公司

原文:https://towardsdatascience.com/hunting-threats-with-pandas-mft-analysis-9f96a99ef27a?source=collection_archive---------26-----------------------

利用数据分析技术和工具改进事故响应。

在我看来,看到网络安全的发展方向确实令人兴奋。事件响应甚至威胁追踪越来越多地与海量信息的处理联系在一起。我认为这一方面是由于当前设备存储和/或生成的遥测数据量,另一方面是由于越来越多的事故,其中许多是非常大的事故,涉及许多计算机,甚至一个组织的许多站点。
这意味着,当我们必须在威胁追踪中找到组织内的攻击者时,或者当我们必须在 DFIR 演习中找到攻击者的踪迹时,我们必须处理越来越多的信息,来自多个来源、具有不同格式的数百万个事件……这简直是一场噩梦。

我一直认为,编程是任何网络安全分析师的基本技能,如果我们没有最起码的知识,我们注定要一直使用第三方工具,而这些工具并不总是符合我们的需求。在这种情况下没有什么不同,能够创建自动化数据处理的小脚本或程序将会有很大的不同。

蟒蛇和熊猫来救援了!

照片由埃里克·麦克林派克斯拍摄

虽然 Python 有能力让使用它的程序员感到惊讶,但 Pandas 却让我大吃一惊!Pandas 是一个数据分析和操作工具,正如它的创造者所定义的那样,它快速、强大、灵活……它们有所不足,令人震惊。😍虽然它们是独立的项目,但强烈建议使用 JupyterLab 与熊猫“玩耍”,它被推荐用于任何事情,如果你从未使用过它,当你使用它时,你会后悔以前没有这样做。我推荐你安装 Anaconda🐍要使用 JupyterLab,这不会让我们的计算机充满我们不需要的 Python 库,你必须有条理!😄首先,一旦安装了 Anaconda,我们将通过在 Anaconda 控制台中运行这个命令来启动 JupyterLab。

C:>jupyter notebook

一旦进入 Jupyter 界面,你就可以用 Pyhton 3 创建一个新的笔记本并开始游戏。

MFT 分析📂

虽然我的意图是发表几篇帖子来讨论在分析师的日常工作中使用 Pandas 的方法,但在本例中,我们将讨论如何使用 Pandas 和 Python 来处理 MFT(主文件表)。
首先,在许多安全事件中,MFT 是非常宝贵的资产,因为它是一个数据库,NTFS 文件系统在其中跟踪存储卷上创建的所有文件和目录。需要查看该日志的情况不胜枚举,但在这种情况下,我们的受害者遭受了勒索软件的侵害。
MFT 不是一种舒适的工作格式,为了让我们更容易,我将使用 Eric Zimmerman 的 MFTECmd 工具。🔝
如果 MFT 不是很大,我们可以用 MS Excel 进行分析,但很多时候文件太大,我们需要更通用的工具。

最初,必须声明一些变量并运行 MFETCmd 工具。

**import** **os**
**from** **subprocess** **import** check_output
mft_path = "**\"**C:**\\**kape**\\**collected**\\**2021-06-01T151604**\\**C**\\**$MFT**\"**"
mftexplorer_path = "**\"**C:**\\**MFTExplorer**\\**MFTECmd.exe**\"**"
output_folder = "C:**\\**Documents**\\**test"
output_filename = "MyOutputFile.csv"command = "**{0}** -f **{1}** --csv **\"{2}\"** --csvf **\"{3}\"**".format(mftexplorer_path, mft_path, output_folder, output_filename)
print(command)
output = os.popen(command).read()

这个执行的结果将是 set 文件夹中的一个 CSV 文件,这就是我们需要用来喂养熊猫的文件。🐼

**import** **pandas** **as** **pd** 
pd.set_option('display.max_columns', 500)

data = pd.read_csv(output_folder + "**\\**" + output_filename)

此时,我们已经有了一个包含来自 MFT 的所有信息的数据框架。为了继续舒适地处理数据,建议调整包含日期的字段的类型。

data.set_index("EntryNumber", inplace=**True**)
data['Created0x10'] =  pd.to_datetime(data['Created0x10'], format='%Y-%m-**%d** %H:%M:%S.**%f**')
data['Created0x30'] =  pd.to_datetime(data['Created0x30'], format='%Y-%m-**%d** %H:%M:%S.**%f**')
data['LastModified0x10'] =  pd.to_datetime(data['LastModified0x10'], format='%Y-%m-**%d** %H:%M:%S.**%f**')
data['LastModified0x30'] =  pd.to_datetime(data['LastModified0x30'], format='%Y-%m-**%d** %H:%M:%S.**%f**')
data['LastRecordChange0x10'] =  pd.to_datetime(data['LastRecordChange0x10'], format='%Y-%m-**%d** %H:%M:%S.**%f**')
data['LastRecordChange0x30'] =  pd.to_datetime(data['LastRecordChange0x30'], format='%Y-%m-**%d** %H:%M:%S.**%f**')

数据现在已准备好供查询。在这种情况下,这个 MFT 属于遭受勒索软件攻击的计算机,更具体地说是 Avaddon。
假设我们不知道勒索软件是何时执行的,并且我们想知道它以便执行调查。
首先,让我们看看在 MFT 中哪一天对文件进行了更多的更改。

dates = data["LastRecordChange0x10"]
dates.index = dates.dt.to_period('d')
s = dates.groupby(level=0).size()
s.sort_values(ascending=**False**).head(10)

MFT 发生更多变化的日子

在上图中,您可以看到我们如何通过几个命令提取文件的修改日期,在对数据进行分组后,我们首先获得操作系统的安装日期,然后获得攻击的日期。
如果我们希望以更直观的方式查看,我们可以生成一个图表,显示过去两个月所做的更改。

MFT 每日直方图变化

我们可以做的另一个测试是寻找过去 4 个月 MFT 中重复次数最多的文件,目的是发现异常。

fig = px.bar(names_plot, x="FileName", "title=Files with more entries")
Fig.show()

具有更多条目的文件

勒索信!该勒索软件在执行过程中创建勒索笔记,并使用它加密的每个文件修改它们。为了更详细地查看信息,我们将执行以下操作。

readme = data[data["FileName"].str.contains("_readme_.txt")]
redme.sort_values(by="LastModified0x10", ascending=True).head()

勒索信

在这种情况下,随着赎金笔记的出现,我们可以知道事件发生的时间,但现在我们将试图找出谁可能是肇事者,只有 MFT。为此,我们将尝试查询勒索病毒案例中攻击者使用的最常见扩展名的文件,但仅限于创建第一封勒索信之前的 12 小时内。🔍

first_note = readme1.sort_values(by="LastModified0x10", ascending=**True**).iloc[0]["LastModified0x10"]
range_exe = first_note + pd.offsets.Hour(-12)
data_filtered = data[(data['Created0x10'] > "2021-05-22") & (data['Created0x10'] < "2021-05-25")]
files = data_filtered[data_filtered["FileName"].str.contains("\.exe|\.ps1|\.msi|\.vba", regex=**True**)]

赎金可执行文件

现在我们有了文件,我们必须找出它是如何进入电脑的,但这是 MFT 无法告诉我们的事情😄。虽然我们没有深入研究,但我们可以对多个 MFT 文件进行分析,按名称模式搜索,比较创建和修改日期,搜索具有可疑属性的文件……这是一个充满可能性的世界。

在以后的文章中,我将会谈到一些更高级的案例,在这些案例中,Pandas 可以帮助我们进行调查,例如分析千兆字节的防火墙日志或分析 Windows 事件。我希望你喜欢它,并鼓励你把熊猫和朱庇特列入你的狩猎工具库。

你可以在这个链接找到这个笔记本,好好享受吧!

下集再见,祝狩猎愉快!

亨利飓风:一个数据故事

原文:https://towardsdatascience.com/hurricane-henri-a-data-story-5a3bee2840fc?source=collection_archive---------29-----------------------

实践教程

分析因东海岸亨利飓风影响而产生的游客数据波动

NASAUnsplash 上拍摄的照片

亨利飓风是一种 1 级飓风,在 2021 年 8 月造成了东海岸的严重破坏。这场飓风于 8 月 16 日在罗德岛州登陆,并于 8 月 24 日消散。亨利达到了每小时 70 英里的峰值强度,并导致了从大规模财产损失到纽约、新泽西和宾夕法尼亚等州的暴雨和洪水的破坏。这篇特别的文章旨在分析这场飓风对纽约州、新泽西州和宾夕法尼亚州的旅游景点的游客指标的影响。

为了执行此分析,我将使用位于纽约州、新泽西州和宾夕法尼亚州的 POI 的 SafeGraph 每周模式数据。SafeGraph 是一家数据提供商,为数百家企业和类别提供 POI 数据。它向学术界免费提供数据。SafeGraph 每周模式数据在结构上类似于每月模式数据(每月模式的文档可在此处找到),但提供的数据是每周和每天的,而不是每月的。这个更加具体和细致入微的数据集的文档可以在这里找到。

分析:

分析的第一步是加载数据并执行一些基本的数据预处理,以提取我们需要的数据。这个分析涉及到几个压缩为 JSON 字符串和数组的列的扩展,比如关于分时段平均停留时间和每日访问者数据的列。为了执行这个扩展,我们可以在 Spark 中使用 from_json 命令。对于此分析,使用了从 2021 年 8 月 2 日到 2021 年 8 月 30 日的数据,并将这些数据分成位于不同文件中的每周间隔。由于预处理阶段在所有四周都是相同的,我们可以使用 08/02 这一周作为我们分析的基线,并假设对所有文件执行相同的分析。该过程的第一步是加载数据:

path0802 = '/content/drive/MyDrive/UpWork/safeGraph/Data Projects/Project 6/patterns0802.csv'df0802 = pd.read_csv(path0802)df0802 = df0802[(df0802['region'] == 'NY') | (df0802['region'] == 'PA') | (df0802['region'] == 'NJ')]df0802 = df0802.drop(['parent_placekey','iso_country_code','safegraph_brand_ids','visitor_country_of_origin','related_same_day_brand','related_same_week_brand','device_type','brands','visitor_daytime_cbgs','visitor_home_aggregation','visitor_home_cbgs'], axis = 1)df0802['postal_code'] = pd.to_numeric(df0802['postal_code'], errors='coerce')df0802['raw_visit_counts'] = pd.to_numeric(df0802['raw_visit_counts'], errors='coerce')df0802['raw_visitor_counts'] = pd.to_numeric(df0802['raw_visitor_counts'], errors='coerce')df0802['poi_cbg'] = pd.to_numeric(df0802['poi_cbg'], errors='coerce')df0802['distance_from_home'] = pd.to_numeric(df0802['distance_from_home'], errors='coerce')df0802['median_dwell'] = pd.to_numeric(df0802['median_dwell'], errors='coerce')df0802 = spark.createDataFrame(df0802)df0802.show(2)

作者图片

从这里我们可以展开 JSON 字符串列:

#Horizontal Explosion of JSON columns using Pysparkfrom pyspark.sql.functions import from_json,exprfrom pyspark.sql.types import StructType, StructField, StringType, ArrayType, IntegerTypebucketedDT_schema = StructType([StructField('<5',IntegerType(),True),StructField('5-10',IntegerType(),True),StructField('11-20',IntegerType(),True),StructField('21-60',IntegerType(),True),StructField('61-120',IntegerType(),True),StructField('121-240',IntegerType(),True),StructField('>240',IntegerType(),True)])df0802 = df0802.withColumn('bucketed_dwell_times',from_json('bucketed_dwell_times',bucketedDT_schema)).select('placekey','location_name','street_address','city','region','postal_code','date_range_start','date_range_end','raw_visit_counts','raw_visitor_counts','visits_by_day','distance_from_home','median_dwell','bucketed_dwell_times.*')df0802 = df0802.toPandas()df0802.head(3)

作者图片

下一步是扩展数组列:

from ast import literal_evaldf0802['visits_by_day'] = df0802['visits_by_day'].transform(lambda x: literal_eval(x))pops = ['visit_' + str(i) for i in range(1,8)]df0802[pops] = pd.DataFrame(df0802.visits_by_day.to_list(), index=df0802.index)df0802 = df0802.drop(['visits_by_day'], axis = 1)df0802 = df0802.reindex()df0802.head(3)

作者图片

既然数据集中的列已经展开,我们可以执行一些基本的分析:

08/02 访问数据的趋势分析

px.bar(df0802, 'location_name','raw_visitor_counts',color = 'region', width= 10000000, height= 1000, barmode= 'group')

由于该条形图涵盖了纽约、新泽西和宾夕法尼亚的所有 poi,其可视化程度太大,无法显示所有 poi。相反,我们可以关注单个 POI:

作者图片

在这个特定的图中,蓝色条代表 Wendy 在纽约的位置,红色条代表 Wendy 在宾夕法尼亚州的位置,蓝绿色条代表 Wendy 在新泽西州的位置。各个条形之间的分隔用来显示每个状态中的不同位置,访问者数据被分组在彼此之上。

考虑到这些兴趣点,我们如何通过查看访客指标对平均停留时间的影响来进一步分析,并尝试确定一些模式

px.scatter(df0802, x = 'raw_visitor_counts', y = 'median_dwell', color= 'region')

作者图片

通过对第一周的分析,我们能够确定,对于给定的 POI,平均停留时间和游客数量之间的相关性似乎很小。同样的趋势在分析的所有周中重复出现。如果您希望更深入地研究这一分析,您可以在笔记本文件中看到这些可视化效果。

从该分析中变得非常明显的一个因素是数据中存在的 poi 的绝对数量。如果我们想了解飓风亨利在 8 月份所有四周的影响,那么对所有 POI 进行分析可能会很麻烦,并使分析变得比必要的更复杂。为了简化流程并大幅减少考虑的兴趣点数量,我们可以应用随机抽样来选择所有 4 周分析的相同兴趣点,并查看飓风对每日访客指标的影响。

df0802_sample = df0802.sample(10)df0802_sample['id'] = np.array(['Week 0']*10)df0802_sample.head(2)placekey_arr = np.array(df0802_sample['placekey'])df0809_sample = df0809[(df0809['placekey'] == placekey_arr[0]) | (df0809['placekey'] == placekey_arr[1]) | (df0809['placekey'] == placekey_arr[2])| (df0809['placekey'] == placekey_arr[3]) | (df0809['placekey'] == placekey_arr[4]) | (df0809['placekey'] == placekey_arr[5])| (df0809['placekey'] == placekey_arr[6]) | (df0809['placekey'] == placekey_arr[7]) | (df0809['placekey'] == placekey_arr[8])| (df0809['placekey'] == placekey_arr[9]) ]df0809_sample['id'] = np.array(['Week 1']*10)df0816_sample = df0816[(df0816['placekey'] == placekey_arr[0]) | (df0816['placekey'] == placekey_arr[1]) | (df0816['placekey'] == placekey_arr[2])| (df0816['placekey'] == placekey_arr[3]) | (df0816['placekey'] == placekey_arr[4]) | (df0816['placekey'] == placekey_arr[5])| (df0816['placekey'] == placekey_arr[6]) | (df0816['placekey'] == placekey_arr[7]) | (df0816['placekey'] == placekey_arr[8])| (df0816['placekey'] == placekey_arr[9]) ]df0816_sample['id'] = np.array(['Week 2']*10)df0823_sample = df0823[(df0823['placekey'] == placekey_arr[0]) | (df0823['placekey'] == placekey_arr[1]) | (df0823['placekey'] == placekey_arr[2])| (df0823['placekey'] == placekey_arr[3]) | (df0823['placekey'] == placekey_arr[4]) | (df0823['placekey'] == placekey_arr[5])| (df0823['placekey'] == placekey_arr[6]) | (df0823['placekey'] == placekey_arr[7]) | (df0823['placekey'] == placekey_arr[8])| (df0823['placekey'] == placekey_arr[9]) ]df0823_sample['id'] = np.array(['Week 3']*10)df0823_sample.head(2)frames = [df0802_sample, df0809_sample,df0816_sample, df0823_sample]sample = pd.concat(frames)sample.head(50)

上面的代码片段从第一周的数据中随机抽取兴趣点样本,并将它们的 placekey 值映射到剩余 3 周的数据中,以确保随机抽样在所有四周中选取相同的兴趣点。当绘制这几周的访客数据时,我们得到以下结果

作者图片

从该图中,我们可以看到随机选择的兴趣点有一些明显的趋势。为了充分理解这些趋势的重要性并理解飓风 Henri 对这些 poi 的影响,我们需要首先了解飓风在八月的第三周影响了这些地区。考虑到这一信息,我们可以看到一些地点在第三周的游客中看到香料的趋势(MTA 科尔特尤路站)。这些可能是人们在飓风期间寻求庇护或获取货物的地点的例子。在这种情况下,MTA Cortelyou 路站是一个纽约市地铁站,游客的涌入可归因于该地区的暴雨造成的交通问题。在许多情况下,在第三周游客数量下降后,第四周的游客数量会有所增加(Franklin Towne Chs、Kathleen's closet 等)。).这些可能是风暴过后游客增加的例子。然而,在某些情况下,访客指标中没有可辨别的趋势可归因于飓风的存在。游客数量没有波动与两个原因有关。首先,这些特定的 POI 可能根本没有受到风暴的影响,因为数据包含位于所选三个州的所有 POI,而位于内陆的位置受风暴的影响可能较小。第二,我们可能无法真正看到游客指标的波动,因为每周游客人数是一周中各天的总和,飓风当天游客人数的减少可能会被当天之前在 POI 发生的事件所抵消,因为在地震发生前,人们可能会增加访问该地区的供应和其他材料的数量。为了解决第一个问题,采取了以下步骤:

NJ_arr = ['Cranbury', 'Jamesburg','Concordia']NY_arr = ['New York']PA_arr = ['Albrightsville', 'Gouldsboro', 'Jim Thorpe']df0802_sel = df0802[(df0802['city'] == NJ_arr[0]) | (df0802['city'] == NJ_arr[1]) | (df0802['city'] == NJ_arr[2]) |(df0802['city'] == NY_arr[0]) | (df0802['city'] == PA_arr[0]) | (df0802['city'] == PA_arr[1]) |(df0802['city'] == PA_arr[2])]df0802_sel['id'] = np.array(['Week 0']*2439) df0809_sel = df0809[(df0809['city'] == NJ_arr[0]) | (df0809['city'] == NJ_arr[1]) | (df0809['city'] == NJ_arr[2]) |(df0809['city'] == NY_arr[0]) | (df0809['city'] == PA_arr[0]) | (df0809['city'] == PA_arr[1]) |(df0809['city'] == PA_arr[2])]df0809_sel['id'] = np.array(['Week 1']*2436)df0816_sel = df0816[(df0816['city'] == NJ_arr[0]) | (df0816['city'] == NJ_arr[1]) | (df0816['city'] == NJ_arr[2]) |(df0816['city'] == NY_arr[0]) | (df0816['city'] == PA_arr[0]) | (df0816['city'] == PA_arr[1]) |(df0816['city'] == PA_arr[2])]df0816_sel['id'] = np.array(['Week 2']*2405)df0823_sel = df0823[(df0823['city'] == NJ_arr[0]) | (df0823['city'] == NJ_arr[1]) | (df0823['city'] == NJ_arr[2]) |(df0823['city'] == NY_arr[0]) | (df0823['city'] == PA_arr[0]) | (df0823['city'] == PA_arr[1]) |(df0823['city'] == PA_arr[2])]df0823_sel['id'] = np.array(['Week 3']*2411)df0823_sel.head(2)frames = [df0802_sel, df0809_sel,df0816_sel, df0823_sel]select = pd.concat(frames)select.head()

作者图片

根据维基百科,为了解决 POI 不靠近飓风位置的问题,我们决定查看游客波动对每个州受影响最大的位置的影响。现在可视化这个特定的数据集,我们可以看到以下内容

作者图片

上图显示了每周访问者数据中更清晰、更符合预期的模式。飓风亨利于 8 月 16 日在大西洋形成,并于 8 月 24 日左右在新英格兰地区消散。因此,我们预计 8 月前两周的游客模式基本上作为给定兴趣点的控制组,第三周的游客数据有所下降,第四周略有恢复。这种模式在这些受亨利飓风影响最严重的城镇的许多兴趣点都可以看到。poi 显示,前两周游客数量停滞或略有波动,随后随着飓风开始影响该地区,第三周游客数据出现下降。当飓风在第三周末消散时,这些兴趣点的游客数据如预期的那样再次增加

为了解决第二个问题,即一周的游客总数抵消了飓风当天的波动,我们进行了以下分析

df0802_1 = pd.read_csv(path0802)df0809_1 = pd.read_csv(path0809)df0816_1 = pd.read_csv(path0816)df0823_1 = pd.read_csv(path0823)BPC02 = df0802_1[df0802_1['location_name']== 'Battery Park City']BPC02['visits_by_day'] = BPC02['visits_by_day'].transform(lambda x: literal_eval(x))BPC02 = BPC02.explode('visits_by_day')name_02 = np.array(BPC02['location_name'])for i in range(len(name_02)):name_02[i] = name_02[i] + str(i)BPC02['location_name'] = name_02BPC02['id'] = np.array('week 0')BPC09 = df0809_1[df0809_1['location_name']== 'Battery Park City']BPC09['visits_by_day'] = BPC09['visits_by_day'].transform(lambda x: literal_eval(x))BPC09 = BPC09.explode('visits_by_day')name_09 = np.array(BPC09['location_name'])for i in range(len(name_09)):name_09[i] = name_09[i] + str(i)BPC09['location_name'] = name_09BPC09['id'] = np.array('week 1')BPC16 = df0816_1[df0816_1['location_name']== 'Battery Park City']BPC16['visits_by_day'] = BPC16['visits_by_day'].transform(lambda x: literal_eval(x))BPC16 = BPC16.explode('visits_by_day')name_16 = np.array(BPC16['location_name'])for i in range(len(name_16)):name_16[i] = name_16[i] + str(i)BPC16['location_name'] = name_16BPC16['id'] = np.array('week 2')BPC23 = df0823_1[df0823_1['location_name']== 'Battery Park City']BPC23['visits_by_day'] = BPC23['visits_by_day'].transform(lambda x: literal_eval(x))BPC23 = BPC23.explode('visits_by_day')name_23 = np.array(BPC23['location_name'])for i in range(len(name_23)):name_23[i] = name_23[i] + str(i)BPC23['location_name'] = name_23BPC23['id'] = np.array('week 3')frames = [BPC02, BPC09, BPC16, BPC23]BPC = pd.concat(frames)BPC['visits_by_day'] = pd.to_numeric(BPC['visits_by_day'])BPC.head()

作者图片

使用之前来自纽约、新泽西和宾夕法尼亚受影响最严重地区的数据,我们继续按照记录对应的一周中的某一天对记录进行拆分,以消除求和导致的任何潜在偏差。我们选择了三个地点:炮台公园城、沃格林和温迪。绘制 Battery Park City 的结果时,我们可以看到以下可视化效果

作者图片

看一下巴特利公园市的日常生活,特别是过去四周的生活,可以提供一种基本的标准来看待许多原因。第一个原因可以归因于这样一个事实,即该位置只是一个高档公寓住宅,这意味着没有理由在暴风雨前后大量游客前来寻求临时住所和食物等物品。这使得该位置可以作为飓风影响游客数据的一种地面实况。从上面的视觉化图像中,我们可以看到,在第三周的中期,该地区的游客数量明显下降,这可能与该地区在这一特定时间内经历的暴雨有关。我们还可以看到,随着风暴在本周末的消退,游客人数将会激增,人们可以返回旅游景点。另一个值得注意的趋势是,接近第二周结束时,到该地点的游客有所增加,这可能是因为在风暴来临之前,大量的人来到该地点寻求安全。为了更好地阐明这种可视化,我们决定绘制几周内访问者指标的差异,并看到这些结果,这些结果以更容易理解的方式给出了相同的分析

week0 = BPC[BPC['id']== 'week 0']week1 = BPC[BPC['id']== 'week 1']week2 = BPC[BPC['id']== 'week 2']week3 = BPC[BPC['id']== 'week 3']diff1 = list(np.array(pd.to_numeric(week1['visits_by_day'])) - np.array(pd.to_numeric(week0['visits_by_day'])))diff2 = list(np.array(pd.to_numeric(week2['visits_by_day'])) - np.array(pd.to_numeric(week1['visits_by_day'])))diff3 = list(np.array(pd.to_numeric(week2['visits_by_day'])) - np.array(pd.to_numeric(week3['visits_by_day'])))combineddiff = list(diff1) + list(diff2) + list(diff3)location = np.array(BPC['location_name'])data= {'Name': list(location[0:21]),'visitor diff': combineddiff,'week': list(np.array(["Week 1 - Week 0"] * 7))+  list(np.array(["Week 2 - Week 1"] * 7))+ list(np.array(["Week 3 - Week 2"] * 7))}diffdf = pd.DataFrame(data = data)diffdf.head()

作者图片

下一步是对 Walgreens 进行同样的分析,结果看起来如下

作者图片

作者图片

对于本节的第二个分析,我选择了像 Walgreens 这样的便利店,看看风暴的存在如何影响访问量。通过这个特殊的数据显示几天没有访客的数据,我们可以看到两个趋势。我们首先可以看到,在风暴到来的前一天,游客数量激增。本周随后的几天显示,由于风暴的存在,游客数量急剧下降。另一个可以看到的趋势是,在风暴过去后,商店的访客会出现巨大的高峰,因为人们试图在风暴过去后找到材料。

该分析的第三部分是在圣卡洛斯酒店进行的,结果可以通过以下可视化效果看到:

作者图片

作者图片

作为本项目中可以探索的 POI 类型的最后一个示例,我们可以看看纽约市的圣卡洛斯酒店。从这个特殊的 POI 中,我们可以看到人们在酒店临时避难的需求如何在风暴前几周推高游客指标,以及如何在风暴后几周影响游客指标。从上面的图像中我们可以看到,酒店的游客数量在八月的第一周达到高峰,然后在接下来的几周,当风暴接近城市时,游客数量会显著下降。我们可以看到,在第 3 周,风暴实际到达该城市,游客指标出现显著下降,从而表明人们如何在风暴前在酒店避难,并在暴雨期间没有离开参观 POI。在风暴平息后的一周,我们可以看到该地点的游客数量仍然低于前几周,表明风暴对 POI 游客数量的负面影响

结论:

从这一分析中,我们能够看到访客指标随着飓风亨利的到来而波动的方式,并显示出 SafeGraph 每周模式数据在协助此类分析方面的潜力。在本系列的下一部分,我们将再次使用每周模式数据来探索飓风 Ida 在受灾严重的州(如路易斯安那州)的影响。

提问?

我邀请你在 SafeGraph 社区#help 频道问他们,这是一个为数据爱好者提供的免费 Slack 社区。获得支持、共享您的工作或与 GIS 社区中的其他人联系。通过 SafeGraph 社区,学者们可以免费访问美国、英国和加拿大 700 多万家企业的数据。

决策支持中的混合智能和一个用例:预测性危机管理

原文:https://towardsdatascience.com/hybrid-intelligence-in-decision-support-and-a-use-case-predictive-crisis-management-916fe9a4a68?source=collection_archive---------46-----------------------

人工智能校准和安全

如何应对决策技术中的人工智能挑战

1。 背景

a. 欧盟最新规范和法规

多年来,欧盟委员会一直在促进和改善整个欧盟的人工智能合作,以提高生产力,确保基于欧盟价值观的信心。继 2018 年欧洲人工智能战略发布后,经过广泛的利益相关方咨询,人工智能高级专家组(HLEG)于 2019 年制定了可信人工智能指南,并于 2020 年制定了可信人工智能评估清单。与此同时,2018 年 12 月发布了首个人工智能协调计划,作为与成员国的共同承诺。委员会在 2020 年发布的关于人工智能的白皮书为人工智能在欧洲提出了一个清晰的愿景:为卓越和信任的生态系统铺平道路,并为今天的提议奠定基础。《人工智能白皮书》的公众咨询吸引了世界各地的广泛参与。白皮书附有一份关于人工智能、物联网和机器人的安全和责任影响的'报告',得出结论认为,当前的产品安全立法包含几个需要解决的漏洞,特别是在机械指令中。

欧盟最近提出了“欧洲议会和理事会制定人工智能统一规则(人工智能法案)和修订某些联盟立法法案的条例提案”。

b. 欧盟规范和法规的要点

欧洲人工智能方法的主要组成部分是:

  • 该政策框架列出了将欧洲、国家和地区倡议更紧密地联系在一起的步骤。该框架的目标是动员资本沿着整个价值链建立一个“卓越的生态系统”,最早从研发开始。该框架还旨在建立正确的激励机制,以促进采用基于人工智能的解决方案,包括中小型企业。
  • 人工智能的潜在欧洲监管结构的核心组成部分将建立一个独特的“信任生态系统”。委员会强烈支持以人为中心的方法,并考虑了人工智能高级专家组编写的道德准则。
  • 欧洲数据战略旨在帮助欧洲成为世界上最具吸引力、最稳定、最具活力的数据敏捷经济体,使欧洲能够利用数据改善决策,改善全体人民的生活。
  • 通信概述了术语“以人为中心”和“人为监督”。但是对于“人在回路中”的方法和新兴的方法——混合智能——却没有给予足够的重视。
  • 关于人工智能驱动的决策,欧盟试图建立一个强大的法律框架——在数据保护、基本权利、安全和网络安全方面,以及与各种规模和各种产业基础的竞争性公司的内部市场。另一方面,这些沟通中缺少的一点是,通过商业和公共部门的数据做出更好的决策需要跨职能的人机团队和高级人机交互。

2。 分析

欧洲已经建立了对人工智能的成功至关重要的强大的计算基础设施(例如高性能计算机)。欧洲还有大量未被充分利用的公共和工业数据。它在生产安全、稳定、低功耗的数字系统方面拥有公认的工业优势,这些系统对人工智能的发展至关重要。利用欧盟投资下一代技术和基础设施的能力,以及数据驱动的转型和数据敏捷经济等数字能力,欧洲在数据经济的关键使能技术和基础设施方面的技术主权将会增加。然而,像中国和美国这样的竞争对手现在正在快速创新,并将他们的数据访问和使用理念推广到世界各地。因此,除了在其他领域的努力之外,强化欧盟作为全球行动者的角色需要对颠覆性技术采取统一和全面的方针。在这种背景下,成员国之间的分裂对于欧洲共同信息空间的愿景和下一代技术的发展是一个重大风险。

谈到欧盟委员会设立的人工智能高级别专家组提出的 AI 提出的关键关切,为了理解威胁的范围,值得提及以下最重要的关切:

-被禁止的人工智能做法,例如,通过超越人们意识的潜意识技术操纵人们,或利用特定的弱势群体,或操纵自由选择,或生物识别系统,或预测性警务,这是压倒性和压迫性的,

-高风险人工智能系统,如拟用作接受第三方事先合格评估的产品的安全组件的人工智能系统,

-隐蔽的人工智能系统,不能确保人类意识到——或者能够请求和验证——他们与人工智能系统交互的事实,

-算法决策系统的安全漏洞,这是由于恶意行为者可以利用的高度复杂性,

-具有认知技能的致命自主武器系统,可以在没有人类干预的情况下决定与谁、何时、何地作战。

为了应对人工智能的这些挑战,混合智能可能是一个值得信赖和可持续的选择。混合智能指的是人类和人工智能的完美结合。机器学习/人工智能可以根据以前案例中发现的模式进行统计推断,并随着数据输入的增加进行学习。此外,这种程序允许对模型配置中的复杂趋势以及单个组件之间的相互关系进行检测,扩展了模拟和场景等方法。尽管如此,他们仍然无法预测对案例的软的和主观的评估,例如价值主张的创新性、团队的愿景或契合度,或者商业模型的整体准确性,这使得计算机不可能对这些数据进行注释。

因此,人类可以成为评估数据的黄金标准,这些数据难以为创造力和创新等机器学习模型进行注释和训练。人类擅长对难以用统计方法客观量化的数据做出主观判断。此外,人类专家拥有组织良好的领域专业知识,允许他们识别和解释稀缺的数据。另一方面,由于人类确实有认知限制,这些可以通过混合智能过程来缓解。这种方法结合了更多人的意见,以最大限度地减少个人评估中的噪音和偏见。因此,通过访问更多样化的领域信息,将其合并到算法中,并降低有偏见的解释的风险,混合智能代表了补充机器学习系统的一种适当方式。

换句话说,通过整合人类和机器的互补能力,共同产生卓越的结果,并通过相互学习不断进化,混合智能驱动的决策支持极有可能改善个人决策活动的结果。此外,混合智能用于利用人类的智慧,同时最大限度地减少机器的缺点,如偏见和随机误差。这支持了混合系统可以像全自动系统一样运行的观点。涉及人类互动的每一个阶段都需要系统以这样一种方式构建,即人类可以理解它并采取后续行动,以及在决定关键步骤时的一些人类行为。此外,人类和人工智能一起工作来完成任务,使操作更加合理。这种系统不仅在生产率和正确性方面有价值,而且在人的选择和能动性方面也有价值。通过适当的界面进行持续的人工交互,可以加快对计算机无法处理的复杂或新颖数据的标记,降低与数据相关的错误和自动化偏差的风险。

混合智能驱动的系统可以确保数据和模型是正确的、相关的、透明的、可解释的和成本有效的,特别是在复杂问题的情况下。特别是对于改变生活的任务,如给予或不给予签证,检测和决定治疗,与全自动系统相比,混合智能驱动的决策系统可以提供问责制和透明度。总而言之,混合智能驱动的决策系统可以胜过单独的人工智能或基于人类的解决方案。然而,开发这样一个具有高科技隐私和准确性的决策系统需要一个非常有才华的跨职能人机团队和创新的方法。在这种背景下,为了设计这样的决策支持系统配置,图 1 绘制了决策支持(DDS)和设计原则(DPs)的维度。在这种配置中,DDS 定义为:

信息支持:没有任何建议或暗示如何行动的决策支持。

建议性支持:对如何锻炼提出建议的决策支持。

动态支持:向用户学习并提供按需指导。

参与式支持:基于用户输入的决策支持(特别是对于高度复杂的任务)。

学习支持:使用户能够主动决定需要和/或想要哪些信息的指导。

知识构建:产生新的认知工件。

视觉化:知识的心理图像。

因此,提议的存款计划如下:

DP 1:为混合智能决策支持系统(HP DSS)提供基于本体的表示,以传输主题专家(SMEs)的假设和输入,并在机器和人类之间创建共享的理解。

DP 2:通过推荐系统为 HP DSS 提供专业知识匹配(如简单的标记系统,将某些本体模型与特定领域专家匹配,以确保高的人工指导质量)。

DP 3:为惠普决策支持系统提供定性和定量的反馈机制,使人们能够提供充分的反馈。

DP 4:为 HP DSS 提供一个分类器(例如,分类和回归树),以便根据人工计算预测模型设计选项的结果。

DP 5:为 HP DSS 提供机器反馈能力,以便根据机器输出预测模型设计选项的结果(例如,前馈人工神经网络、支持向量回归或递归神经网络)

DP 6:为 HP DSS 提供一个知识构建存储库,使其能够从流程中学习。

DP 7:为 HP DSS 提供一个可视化工具,允许用户访问信息性和建议性的决策支持。

作者图片

3。 案例:预见性危机管理

政府、研究和商业行为者越来越依赖算法决策。许多计算机算法建立在传统数据分析方法的之上,这些方法利用统计技术发现变量之间的关系,然后预测结果。但是如前一节所述,特别是在高度复杂和不确定的情况下,由于算法决策的不足,混合智能决策系统在冲突和危机&运营管理和执法活动等情况下提供更好的决策支持方面有着重要的前景。

由于欧盟正在追求成为一个全球性的行动者,因此获得高价值的能力是至关重要的,如战略预见分析、预测危机和运营管理、游戏和模拟。更重要的是,每个月都有成千上万的人死于世界各地的大规模政治暴力,迫使更多的人在国内或跨境逃亡。武装冲突具有毁灭性的经济影响,破坏民主制度的运作能力,阻碍国家摆脱贫困,并阻碍最需要的人道主义援助。当大规模危机和冲突发生在意想不到的地方和时间时,避免、最小化和适应大规模危机和冲突的困难就会加剧。不用说,一个在所有有冲突风险的地方提供预警并评估冲突爆发、升级、持续和解决的可能性的系统将对欧盟决策者和第一反应者大有裨益。

毫无疑问,冲突和危机的不确定性是设计决策架构的主要挑战。为了通过提前做好准备来解决处理危机或冲突的问题,混合智能危机管理系统可以提供一个适用于整个危机生命周期、危机前准备、危机期间响应和危机后响应的综合框架。因此,可以系统地定义行为者和事件的功能行为模式,然后分析模式和关系,从而获得早期预警,预测他们未来的行动,最终发现、减轻和预防潜在的危机和冲突以及关键机会的可能性。此外,系统必须确保人机交互,并保持人在回路中的通道。基于这些论点,该框架将有四个主要支柱:

-采用全面的数据收集和分析模型,

-构建动态本体结构并通过寻找本体的节点之间的关系来构建网络,

-构建知识提取管道:使用结合了提议的网络拓扑和模式识别方法的统一检测方法,开发模拟模型,例如一步到位建模动态模拟

-开发可视化系统。

图 2 显示了一个混合智能驱动的危机管理系统的通用框架。大部分危机分析研究都是回顾性的,包括描述性分析和诊断性分析。前瞻性分析,如预测性和规范性分析,相对来说受到的关注相对较少。因此,根据这一框架,连接输入层和输出层的知识管道将由四个基本步骤组成:描述性分析(发生了什么?),诊断分析(为什么会发生?),预测分析(会怎么样?),最后是规定性分析(我们该怎么办?).

总之,以情报为动力的混合危机管理系统将极大地改变危机和冲突管理流程以及整个危机信息学生态系统。多维大危机数据信息学既包括海量数据,也包括广泛的数据源(可以由多种数据类型组成)。这些大规模危机数据源中的每一个都提供了一个独特的(但必然是不完整的)视角,来观察到底发生了什么以及为什么会发生。动态本体提供了事件和对象的混合识别模型,并以其独特的结构保证了可重用性。知识建设支柱包括预测性和规范性危机分析以及模拟,这些将成为先发制人的危机和冲突管理的核心能力。最后,可视化为各种用户和利益相关者提供了可解释性和无摩擦的互通平台,确保了响应和管理工作的互操作性和协调性。

作者图片

4。 结论和政策建议

从欧盟的角度来看,人工智能是一项战略技术,如果它以人为中心,符合伦理,可持续发展,同时仍然尊重基本权利和价值,它可以为人民、企业和整个社会的福祉做出贡献。欧洲人工智能战略旨在提升欧洲的人工智能创新潜力,同时促进欧盟经济中道德和值得信赖的人工智能的增长和采用。最新的欧盟规范和条例特别强调可信度、可解释性、准确性和人类参与。然而,当涉及到决策支持或算法决策系统时,似乎欧盟人工智能的观点需要用混合智能方法进行审查。尽管在最近的欧盟通信中已经强调了一些术语,如“以人为中心”或“人为监督”,但在欧洲利用混合智能系统仍需要深入理解和全面的方法。简而言之,欧盟必须避免在许多公众眼中的欧盟运作黑箱中运行算法黑箱。

因此,欧盟应该寻求在其内部流程中更多地使用混合情报,并将其作为欧盟委员会决策和现有政策审查的一项投入。为此,向欧盟提出的以下政策建议概述如下:

-管理共同欧洲混合情报战略的立法框架,并据此启动《混合情报法》;

-促进对高级人机交互系统的投资,加强欧洲在托管、处理和使用人在回路和互操作性方面的能力和基础设施

-投资欧洲混合智能战略的高影响力项目,包括数据共享和人机交互架构(包括标准、最佳实践、工具)和治理机制,以及欧洲可信混合智能联盟和相关服务

-让大学、实验室、研究中心、初创企业和中小型企业投资于混合智能的使用以及人机之间的互操作性

-在 Horizon Europe 项目组合中增加新的项目号召,鼓励使用混合智能。

多极德拜介电函数近似的线性-非线性混合优化方法

原文:https://towardsdatascience.com/hybrid-linear-nonlinear-optimization-approach-to-the-approximation-of-multi-pole-debye-dielectric-9163aa86baeb?source=collection_archive---------41-----------------------

思想和理论

在我之前的 帖子 中,我介绍了我在 Google Summer of Code 2021 期间所做的一些工作,这些工作与色散材料的电特性建模有关。在帖子里,我想分享我最终提交的结果。

特里·维利迪斯在 Unsplash 上拍摄的照片

使用外部电场可以极化某些种类的材料。这些电磁绝缘材料被称为电介质。它们的极化是由内部电荷的轻微运动引起的(正的方向与外部磁场的方向相反,负的方向与外部磁场的方向相反)。这产生了一个内部电场,在某些情况下,还可以重新定向材料的分子。为了测量材料的电极化率,使用了称为介电常数的变量(由希腊字母 ε 表示)。

具有高介电常数的材料比具有低介电常数的材料响应于施加的电场极化更多,从而在材料中存储更多的能量。介电性质的研究涉及材料中电能和磁能的储存和耗散,对于解释各种物理现象非常重要[1]。

此外,一些材料表现出介电色散。这意味着电介质材料的介电常数取决于外加电场的频率。这种频率依赖性反映了一个事实,即当施加电场时,材料的极化不会立即改变。材料的响应总是在施加电场后出现,在振荡电场的情况下,会出现特征介电弛豫过程[1]。

宽频率范围内的介电常数谱。ε′和ε″分别表示介电常数的实部和虚部。影响材料响应的各种过程被标记在图像上。图片由[1]提供。

松弛函数的变体

德拜方程模拟角频率ω的交变电场中的弛豫过程,描述理想的非相互作用电偶极子群体的介电弛豫响应。作为极化指数衰减的基本原理,复介电常数由德拜函数给出为[2]

这里,实部ε′(ω)是介电常数,虚部ε″(ω)是损耗因子,I =√–1。ε s 为静态介电常数,ε∞为无限频率介电常数,τo 为弛豫时间,为弛豫过程的特征时间。

德拜函数的实部和虚部。f0 是弛豫频率。图片作者。

然而,单极德拜方程是大多数材料在宽频率范围内的介电行为的不良模型。为了克服这一点,经验导出的 Havriliak–Negami 弛豫被提出作为单极德拜弛豫模型的修改。该方程另外具有两个指数参数,并表示为[3]

其中α和β为正实常数(0 ≥ α,β ≤ 1)。根据该模型,可以推导出β=1 时的科尔-科尔方程[4]和α=1 时的科尔-戴维森方程[5]。当α=1,β=1 时,得到再见方程。Havriliak-Negami 函数首先用于描述聚合物的介电特性[3],而 Cole-Cole 方程主要用于模拟生物组织[6]和液体[7]。

另一方面,恒定 Q 因子方法(或品质 Q 因子)[8]中的 Jonscher 函数主要用于描述混凝土[9]和土壤[10]的介电特性。其他类型的弛豫函数估计非均质材料的体积介电常数。这里,复折射率模型(CRIM) [11]可以根据其组分的介电性质和体积分数来说明混合物的介电性质。

Havriliak-Negami、Jonscher 函数以及稳定的 Q 因子、CRIM 和实验获得的数据不能直接应用于 FDTD 算法。许多研究人员采用的方法是使用多极德拜展开法,利用多个弛豫时间和形式[12]中的无量纲权重对复介电常数进行近似

εn 和τ0,N(N = 1,2,…,N)分别是德拜色散的介电常数(重量)和弛豫时间的变化。参数 N 表示德拜极点的数量(德拜展开分量的总数)。多极德拜模型被广泛使用,因为它可以容易地在时域和频域中表达。

寻找松弛时间和无量纲权重

多极德拜拟合过程的目标是最小化目标函数,该目标函数是所选择的弛豫模型(这里我们有 Havriliak-Negami、Jonsher、CRIM 或实验数据)和德拜展开的近似形式之间的差异。任务中的函数被明确定义,包括两倍于德拜极点数量的变量,因为我们要计算弛豫时间和无量纲权重。

由于色散材料的因果性质,介电常数的实部和虚部通过 Kramers-Kronig 关系彼此相关。这表明,对于相同的参数,介电常数的实部和虚部可以用德拜函数的和来近似表示。然后,可以仅对虚部的实值展开进行优化过程。在文献中,一些单一的非线性优化程序被用来寻找所有的未知参数(即权重和松弛时间)。然而,因为展开是德拜函数的线性组合,所以更有效的方法是使用线性最小二乘法(LS)来找到权重,使用非线性方法来找到弛豫频率,这里默认使用粒子群优化(PSO)技术。

用粒子群算法寻找函数的全局最小值。图片由维基共享提供。

gprMax 子包 DebyeFit 中采用的技术是 Kelley 等人[13]提出的混合线性-非线性优化方法的修改。这些调整可以克服一些不稳定性问题,从而使该过程更加稳健和快速。特别地,在负权重的情况下,符号被反转,以便在优化过程中引入大的惩罚(从而间接地约束权重总是正的)。此外,介电常数的近似实部和计算实部之间的差异被添加到成本作用中,以避免可能的不稳定性。

代码结构

gprMax 子包 DebyeFit 包含两个主要脚本:

  • Debye_fit.py 带有所有松弛函数类的定义,
  • optimization . py定义了三种选择的全局优化方法。

类弛豫 设计用于模拟不同的弛豫函数,如 Havriliak-Negami( havriliaknegami 类')、Jon scher( Jon scher 类')、复折射率混合( CRIM 类')模型,以及通过实验得出的或使用其他函数计算的任意介电数据( Rawdata 类')。所选对象类型的构造器构造适当的松弛对象,并定义其所有参数,以及频率点网格。

类优化器 支持全局优化算法(粒子群、对偶退火、进化算法),用于找到一组最佳松弛时间,使实际电容率和近似电容率之间的误差最小化,并计算给定松弛时间的优化权重。这里编写的代码主要基于外部库,如“scipy”和“pyswarm”。优化器对象是在松弛模块中创建的。用户可以从三种优化算法中选择一种,并以 python 字典的形式显示其属性。

通过使用 run 方法,在松弛对象初始化之后启动拟合过程。函数内部实现的算法由以下步骤组成:

  1. 使用 check_inputs 方法检查输入的有效性。
  2. 使用 print_info 方法打印关于所选近似设置的信息。
  3. 使用计算方法计算实部和虚部,然后设置 self.rl 和 self.im 属性。
  4. 使用 optimize 方法调用主优化模块,并根据 error 方法计算误差。[可选]如果德拜极点的数量设置为-1,则重复优化程序,直到百分比误差小于 5%或达到 20 个德拜极点。
  5. 使用 print_output 方法以 gprMax 格式打印结果
  6. [可选]使用 save_result 方法以 gprMax 格式将结果保存在 txt 文件中
  7. [可选]使用 plot_result 方法绘制实际和近似的介电特性。

最终用户可以绘制实际和近似电容率以及频率范围内的误差。图片作者。

总结

gprMax 工作是一次很好的学习经历。gprMax 是构建大型复杂 GPR 模拟的强大工具。它在许多领域的广泛应用证实了它的有用性。

这项工作描述了新的先进建模功能的增加,如拟合实验得出的或使用某些弛豫函数计算的任意介电数据的可能性。这里采用的混合线性-非线性优化方法提供了一种有效且精确的优化程序,以将多极德拜展开拟合到介电数据。

文学

[1]应用笔记 1217–1,测量材料介电特性的基础知识,惠普文献编号 5091–3300 e,1992 年。

[2] P .德拜,极地分子,多佛出版公司,纽约州,1929 年。

[3] S. Havriliak 和 S. Negami,某些聚合物中介电和机械松弛过程的复平面表示,聚合物,第 8 卷,第 161-210 页,1967 年。

[4] K. S. Cole 和 R. H. Cole,电介质中的分散和吸收,交流电流特性,化学物理杂志,第 9 卷,第 341-351 页,1941 年。

[5] M. F .曼宁和 M. E .贝尔,固体电介质中的导电和相关现象,修订版。物理学,第 12 卷,第 215-257 页,1940 年。

[6] D. Ireland,A. Abbosh,使用优化的德拜模型和 FDTD 方法在微波频率下模拟人体头部,IEEE Trans。天线与传播,第 61 卷第 4 期,第 2352–2355 页,2013 年。

[7] J. Barthel、R. Buchner 和 M. Munsterer,“电解质数据收集,第 2 部分:水和水性电解质溶液的介电特性”,系列。化学数据系列。德国法兰克福:DECHEMA,第十二卷,1995 年。

[8] M. Bano,遵循介电常数频率复幂定律的有损介质的探地雷达波建模,地球物理勘探,第 41 卷,第 11–26 页,2004 年。

[9] T. Bourdi、J. Rhazi、F. Boone 和 G. Ballivy,Jonschermodel 在混凝土介电常数表征中的应用,物理学杂志 D:应用物理学,第 41 卷,第 205410 页,2008 年 10 月。

[10] E. Kjartansson,恒定 Q 波传播和衰减,地球物理研究杂志,第 84 卷,第 4737-4748 页,1979 年。

[11] J. R. Birchak,C.G. Gardner,J.E. Hipp,J . M Victor,用于检测土壤湿度的高介电常数微波探头,Proc .IEEE,第 62 卷,第 93-98 页,1974 年。

[12] C. A. Balanis,高级工程电磁学,纽约州:威利市,第二区。2.8.1, 1989.

[13] D. F. Kelley,T. J. Destan 和 R. J. Luebbers,使用混合粒子群最小二乘优化方法对复介电常数进行德拜函数展开,IEEE 天线与传播汇刊,第 55 卷,第 7 期,第 1999–2005 页,2007 年 7 月。

https://github.com/gprMax/gprMax/pull/296

简化 MNIST 数据的混合量子神经网络

原文:https://towardsdatascience.com/hybrid-quantum-neural-network-for-reduced-mnist-data-840897ad08a?source=collection_archive---------12-----------------------

用少于 200 行的 Pennylane 和量子变分电路求解时尚 MNIST

量子时尚 MNIST 的标志图片。编辑自马太·亨利Unsplash 上的照片

Q uantum 机器学习 (QML)已经被证明在低输入维度的机器学习问题上是有效的。杰尔比[1]和欧文[2]已经解决了南极环境问题。量子卷积已被用来解决一个简化版本的 Mnist 数字数据集[3]。

另一种基于降维算法的解决方案已经提出[4],但在这篇文章中,我们将只关注基于变分量子电路(VQC)的实现。我们将开发一个量子神经网络,使用 Pennylane 以稍微减少的输入对 MNIST 时装数据集进行分类。

介绍

我们将尝试使用 QML 解决的问题是使用 VQC 对 MNIST 数据集进行分类。由于解决整个问题需要时间,我们将使用一个降维的数据集。我们将尝试在我们的 VQC 中适应的维度将是 64,而不是最初的 784。

我们将使用运行在 Colab 机器上的 Python 代码。在这个 Colab 上,我们需要安装 Pennylane 作为量子机器学习库,我们将使用已经安装的 Tensorflow 作为接口。

数据准备

第一步或目标将是准备图书馆和加载我们心爱的 MNIST 数据。

完成设置后,我们将定义用于模型的参数。

数据的过滤是通过选择我们感兴趣的列表中的类别的索引来完成的。这段代码确实是临时的,我相信有更好的实现。

使用自动编码器预处理

选择用于降低数据维度的模型是一个非常简单的自动编码器模型,基于 Tensorflow 自己的教程。[5]

我们将使用相对于量子位数量的潜在维度大小。层数和每层中神经元的数量由用户决定。

对数据进行编码就像将数据传递给编码器一样简单。然后,我们需要将输出替换为分类值。

量子神经网络(QNN)

我们现在将准备量子网络来分类我们的时尚数据。首先,我们将简单介绍一下 VQC。

变分量子电路是一个量子电路,它依赖于许多自由参数,我们可以手动调整这些参数,或者用学习算法来逼近某个函数。它可以被视为一个具有可学习参数的数学近似模型。它们的工作方式类似于神经网络及其权重。

该电路

为了使用量子计算机或模拟器,我们需要导入我们的库和将要使用的层。

我们将使用的两个主要层是:

  • mottonestatepreparation:处理振幅状态准备。振幅状态准备包括将一个量子状态固定到一个给定的向量上,该向量的维数等于量子位数量的 2 次方。
  • strong 纠缠层:量子神经网络门,它旋转每个量子比特,然后以循环的方式将它们与 CNOT 纠缠在一起。这一层类似于神经元之间的致密层,但它们以量子方式表现。

注意 :我们在这个电路中不使用 AmplitudeEmbedding 的原因是由于 Pennylane 中的一个已知问题,尽管在运行实际的量子计算机时,这个算法会适用。

该模型将使用强纠缠层来近似最小化某个损失函数的函数。此外,我们将使用一种称为“数据重新上传”的技术,它包括对网络中的输入数据进行多次采样。众所周知,这种技术可以改善电路效果。[6]

我们将使用的 QNN 模型由上面定义的量子电路组成,后面是一个致密层来准备输出。

一旦模型编译完成,我们就可以用之前选择的数据训练模型了。由于训练可能需要 3 个小时,但在第一个纪元后没有太大改善,我们将把训练限制在第一个纪元。进一步的时代可能会改善系统,但这是留给读者的一个练习。;)

使用这个参数,我们得到了 95%的分类准确率。

如果我们实际上试图使用相同的 6 个量子位和 10 个类,训练过程将花费更长的时间,并且准确率将下降到适度的 70%。虽然这不像带有 4 个标签的 previus 95%那样令人印象深刻,但它表明这些模型确实有能力解决实际问题,而无需太多的经典处理。

让我们来看看 10 个标签的例子,QNN!
警告,这在所有人看来都没什么了不起。

示例 1:一对 troursers

MNIST 数据集的裤子图像

前一图片类别(左)和图片预测(右)

QNN 可以清楚地检测出图片是一条裤子。

示例 2:失败的示例

MNIST 数据集的衬衫图像

前一图片类别(左)和图片预测(右)

这个例子对我们的网络来说似乎很难,因为它打印了 5 个可能的类别。当查看预测的类别时,有趣的事情出现了:检测到的标签都是衬衫类型的标签,而所有鞋子和裤子都被丢弃了!

例子 3:鞋子很奇怪

MNIST 数据集的鞋子图像

前一图片类别(左)和图片预测(右)

有些鞋确实比其他鞋有更好的结果,但总的来说,它们倾向于聚集在鞋的标签上。

结论

正如我们刚刚看到的,量子神经网络比我们想象的更接近现实生活,一些实际案例已经在入门环境和数据集上实现。

在本帖中,我们已经证明了可以使用 QNN 对时尚 MNIST 数据进行分类,并在稍微降低维度的数据上取得良好的结果。我们在 64 维数据上用 4 个标签实现了 95%的准确率,用 10 个标签实现了 70%的准确率。作为第一步,我们可以开始想象在不久的将来,只有 10 个量子位的系统将能够在不减少数据的情况下对整个数据集进行分类!

参考

[1] S. Jerbi,用于强化学习的变分量子策略 (2021),ArXiV
[2] O. Lockwood 和 M. Si,利用量子变分电路的强化学习 (2020),ArXiV
[3] E. Farhi 和 H. Neven,在近期限处理器上利用量子神经网络进行分类 (2018),ArXiV
[4] I. Kerenidis 和 A. Luongo,【T10 Tensorflow Core
[6] A. Perez,a .塞尔韦拉,E. Gil,José L .,通用量子分类器的数据重新上传 (2020),ArXiV

面向数据科学家的混合云/基于边缘的 AIML 模型部署架构

原文:https://towardsdatascience.com/hybrid-rest-api-design-and-architecture-for-data-scientists-617cf3637542?source=collection_archive---------48-----------------------

AIML 应用服务统一架构@版权所有-作者图片

简介

机器学习模型的部署是数据科学过程的关键要素之一。通常,数据科学家在部署部分努力将模型公开为一个无缝的 API,供许多端点使用。在本文中,我将解释 API 的架构和设计——本地的和云的。数据科学家最流行的框架是基于 python 的 Flask API 服务器和面向 R 用户的 Plumber。我们将探索如何在生产环境中使用这些框架来使 API 更加健壮、可伸缩和容错。

平台即服务(PaaS)或本地服务器

web 应用程序的核心是应用程序将要驻留和执行的服务器。它构成了 web 应用程序的基础。它也被称为应用程序的生产环境。它可以是单个服务器,也可以是部署在本地或云上的服务器集群。托管可以是裸机硬件,如戴尔、IBM 等,用于在本地构建应用程序,也可以是基础架构即服务,即基于云的裸机硬件,如 EC2 for Amazon、VM for azure。云部署的另一个选项是平台即服务,从裸机硬件到操作系统、web 框架和 Web 服务器,Web 应用程序的所有组件都作为完全托管的现成服务提供。如图所示,Azure App Service、亚马逊弹性豆梗、GCP App Engine 是几个比较流行的基于云的 PaaS。

OS——操作系统构成了控制和管理 HWs、软件资源的主要系统,计算机程序可以在该系统上执行。对于 web 应用程序,可以使用基于 Linux、Windows 或 macOS 的核心操作系统。最受欢迎的是基于 Linux 的版本,适用于本地和虚拟应用程序。

网络服务器

如图所示,web 服务器响应来自客户端的 HTTP 请求,并以 JSON、XML 或 HTML 格式返回状态代码和内容。从数据科学的角度来看,JSON 格式是最流行的 web 服务器响应形式。它还充当 WSGI 服务器的反向代理。反向代理只是 WSGI 和外界之间的一个中间层。web 服务器面向外部世界,并将请求重新路由到 WSGI 服务器。随着您的应用程序的增长,我们希望在服务器(VPS)之间优化和分布它,以便能够同时处理更多的连接。在您的应用服务器前面有一个反向代理有助于无缝扩展。

跨多个应用程序实例的负载平衡是一种常用的技术,用于优化资源利用率、最大化吞吐量、减少延迟以及确保容错配置。

Web 服务器有一个高效的 HTTP 负载平衡器,将流量分配给几个应用服务器,并提高 web 应用程序的性能、可伸缩性和可靠性。

流行的 Web 服务器是 APACHE 和 NGINX。几十年来,Apache 一直是领先的 web 服务器,但 NGINX 现在已经占据了大约 50%的 web 流量。NGINX 比 apache 有性能优势,而且相对容易配置。如果您想使用 apache,它会预装在 Linux 发行版中。

w3techs 的数据显示,Nginx 的市场份额一直在稳步增长,将 Apache 挤出,从第一的位置上退位。

如果你想知道更多关于 Apache Vs NGINX 的细节,你可以访问 https://kinsta.com/blog/nginx-vs-apache/的

对于 HTTP 请求,如果您不想直接输入服务器 IP,而是使用 URL,最好进行域名注册,并获得 SSL/TLS 证书,以保护和加密到您的 web 服务器的交易。由于 web 服务器是面向世界的,它暴露在许多安全威胁之下,因此用 HTTPS 加密来保护它是很重要的。

对于内部部署,其中 API 服务器用作其他内部应用程序的微服务,使用直接的基于 IP 的 HTTP 访问。如果需要,我们可以用 SSH 密钥和防火墙来保护服务器。

WSGI 服务器

Apache,NGINX 不懂 Python web 应用的运行方式。WSGI——Web 服务器网关接口——是专门为理解 python 应用程序并将其传递给 Apache、NGINX 等 Web 服务器而设计的。它是标准化的,以促进 web 应用程序在不同的 WSGI 服务器实现之间的可移植性,如 Gunicorn Mod_wagi、uwsgi 等。如果你使用 Apache,那么使用 Mod_wsgi,而对于 NGINX,Gunicorn 是一个流行的选择,因为它只需要很少的配置。

作者图片

如果你使用基于云的应用服务,它默认使用现成的 Gunicorn WSGI 服务器。

关于 WSGI 的更多细节可以在@

https://wsgi.readthedocs.io/en/latest/servers.html

https://www . app dynamics . com/blog/engineering/an-introduction-to-python-wsgi-servers-part-1/

Web 框架

Web 框架是负责构建 web 应用程序(如 HTTP 请求、响应、URL 路由、身份验证、数据处理、安全性、会话)的工具的库。

对于数据科学家来说,流行的 Web 服务器是 Python 开发人员的 Flask 和 R 开发人员的 Plumber。Flask 和 Plumber 都有无缝连接 WSGI 服务器的能力。

注意 web 框架如何与应用程序源代码、模型和后端数据库(如果有)进行交互。通常顶层包装器——python 或 R——会调用 web 框架实例以及其他依赖项来创建应用程序。

还要注意,云应用服务将只提供容器化、WSGI 支持和内置的 web 服务器,以及完全托管的服务。使用 web 框架创建应用程序是数据科学家需要编写的底层代码。

主管

ref-https://www . opensourceforu . com/2019/10/how-to-run-multiple-services-inside-a-single-container-using-supervisord/

想象一下当你的 Flask 或 Plumber 应用程序崩溃或者实际的服务器重启时的情况。为了维护应用程序的持续可用性和持久性,并使应用程序具有更强的容错能力,我们需要一个处理这一切的进程管理器。

supervisor 是一个客户机/服务器系统,它允许用户在类似 UNIX 的操作系统上监视和控制许多进程。

REST Webserver 的工作流

1.注册域名,并从 namescheap.com 这样的域名提供商那里获得 SSL 认证。如果内部微服务调用,使用必要的防火墙和 SSH 密钥通过服务器 IP 地址进行 HTTP 调用

2.设置 web 服务器。Apache 或 NGINX 是两种最流行的 web 服务器。

3.设置 WSGI 服务器。如果使用 Apache,那么使用 Mod_WSGI。如果使用 NGINX,请使用 Gunicorn。大多数云提供商默认使用 Gunicorn WSGI。

4.安装支持 python 或 r 的 web 框架。如果使用 Python,请使用 Flask。如果用 R 代表水管工。

5.编写您的应用程序包装器,使用请求/响应端点调用 Webserver、您的模型、后端数据库的实例。

6.安装 supervisor 来处理 web 服务器/应用程序中的一些容错问题。

7.为动态负载平衡/扩展需求创建一个分级容器。

在下一篇文章中,我们将介绍架构的每个模块的设置/安装步骤。我们将看到 Apache 和 NGINX 的设置

参考

  1. https://wsgi.readthedocs.io/en/latest/servers.html
  2. https://www . app dynamics . com/blog/engineering/an-introduction-to-python-wsgi-servers-part-1/
  3. https://www . opensourceforu . com/2019/10/how-to-run-multiple-services-inside-a-single-container-using-supervisord/
  4. https://www . digital ocean . com/community/tutorials/how-to-install-and-manage-supervisor-on-Ubuntu-and-debian-VPS

使用 Optuna 进行超参数优化

原文:https://towardsdatascience.com/hyper-parameter-optimization-with-optuna-4920d5732edf?source=collection_archive---------7-----------------------

如何生成模型的最佳版本。

Optuna 超参数优化(GIF 由作者提供)

超参数优化是一项艰巨的任务。然而,使用像 Optuna 这样的工具可以使它变得更容易。

在这篇文章中,我展示了如何使用 Optuna 调优 CatBoost 模型的超参数。

这里针对 Optuna 的代码可以快速适应您正在训练的任何模型。请随意收藏这篇文章以备将来使用。

来自 Optuna 的单个超参数性能(由作者绘制)

超参数

构建数据科学模型的一个经常被低估的任务是超参数优化。这项任务通常放在构建模型的最后。

然而,它可以区分一个可怕的模型和一个神奇的模型。这些超参数自成一类,因为它们简化了您正在使用的模型的结构。

相比之下,常规参数是由机器学习算法在训练期间学习的参数。在最基本的示例中,线性回归使用参数来确定每个要素的权重。

这些参数控制模型的基本输出。但是,对于线性回归,您也可以将正则化添加到模型中,并附带一个超参数来控制正则化项的权重。

这个带有超参数的附加项改变了模型的整体预测方式。改变这个参数可以让一个像样的模型预测无意义的东西,或者将模型转换成非常健壮的东西。

改变模型行为

这种行为在更复杂的模型中更为突出,如决策树,其中许多不同的超参数控制着树的深度、叶子的数量、分割的方式以及许多其他选项。

这些选项中的每一个都控制着模型的结构及其决策方式。虽然在每个配置中仍然有决策树,但是树的类型可以有很大的不同。这就是松树和盆景的区别。

更复杂的是,进一步的集合模型带来了额外的挑战。这些复杂的模型建立在许多不同的模型之上,每个模型都有其超参数。

大多数情况下,您选择每个模型用来训练集合中的模型的超参数。例如,在诸如 CatBoost 的基于树的集合模型中,这些初始参数控制树的集合。无论是树的形状还是数量。

超参数优化

谈到超参数优化,有几个选项可用。最常用的方法是网格搜索的变体。

网格搜索

网格搜索是一种简单的强力方法,可以为您输入到搜索空间的每个超参数组合生成模型。因此,为每个品种创建一个模型,然后进行比较。虽然一开始很吸引人,但还是要意识到一些关键的方面。

首先,确定最优超参数是一个 NP-Hard 问题,因为你要处理超参数的组合。因此,就复杂性而言,强力搜索的代价是惊人的。

要注意的第二个方面是,你可能正在训练的模型在搜索的大部分时间里一直表现很差。但是网格搜索是为了建立和训练这些模型而设计的。

假设您正在构建一个决策树,您有一个网格搜索,其中包括从“基尼”到标准熵的变化。此外,假设您发现“Gini”在您运行的前几个测试中的性能要优越得多。然而,即使熵在每个后续模型中表现更差,网格搜索仍将搜索这些组合中的每一个。

随机搜索

网格搜索的替代方法是随机搜索。乍一看,这似乎是比网格搜索更糟糕的选择。然而,已经证明随机搜索比网格搜索执行得更好。

基本原理很简单,随机搜索避免了网格搜索执行的许多冗余搜索。例如,通过以不均匀的间隔搜索超参数空间,更有可能找到超参数的更实质的局部最优。

可供选择的事物

现在有了到目前为止讨论的两个超参数搜索的替代方案。这些选择正是这篇文章的目标。

由于之前的两种方法都没有结合任何结构化的方法来搜索最优超参数集,因此它们处于劣势。相反,像 scikit-optimization 和 Optuna 这样的库已经引导了超参数搜索。

关于网格搜索和随机搜索比较的更多细节,你可以阅读我关于超参数优化的文章。此外,我展示了另一种方法,贝叶斯优化如何比这两种方法表现得更好。

Optuna

Optuna 是一个优化工具,允许用户在超参数空间上运行实验。重要的是,它也总是用户暂停搜索,尝试其他超参数组合,然后继续优化过程。

此外,Optuna 支持基于树的超参数搜索,称为 TPESampler“树结构 Parzen Estimator”。这种方法依靠贝叶斯概率来确定哪些超参数选择是最有希望的,并迭代地调整搜索。

Optuna 设置

无论您使用的是哪种模型,使用 Optuna 优化超参数都遵循类似的过程。第一步是建立一个学习函数。该函数规定了每个超参数的样本分布。

最常见的可用选项是分类、整数、浮点或统一对数。当您想要检查 0.001、0.01 和 0.1 范围内的值时,对数统一是理想的,其中每个值都有相同的被选中概率。

Optuna 的另一个巨大优势是能够设置条件超参数。不幸的是,许多超参数只有在与其他参数结合使用时才有意义。因此,简单地使用它们的变体会导致错误。为每个选择添加案例可以确保这些情况不会发生。

模型优化

为了说明 Optuna 的一个用例,我选择优化一个 CatBoost 模型。这些模型有大量的超参数。虽然这篇文章只展示了其中的一小部分,但还是展示了许多 Optuna 特性,比如条件超参数。

Catboost

Catboost 是一种基于树的集成方法。这是一个非常稳健的模型。

与其他预测模型相比,CatBoost 的一个直接好处是 CatBoost 可以直接处理分类变量。因此“猫”这个名字是分类的缩写。

CatBoost 的这一特性使其成为懒惰的数据科学家的理想选择。将分类变量转换为数值变量可能需要一些时间,并且需要支持其他模型的假设。此外,您需要确定特征的正确表示。

但是,使用 CatBoost,您只需要定义分类参数,然后调整超参数来处理这些分类特征。

超参数“cat_features”规定了哪些特性是分类的。如果没有指定所有这些分类特征,CatBoost 将抛出一个浮点型预期错误,因为模型通常假设剩余的特征是数字。

CatBoost 超参数

  • loss_function —训练损失函数,对于回归可以使用 RMSE 或 MAE。
  • 迭代 —限制树的数量。但是,其他超参数可能会限制树的数量,从而导致总数小于迭代次数。
  • learning_rate —学习率在优化期间使用,即在梯度下降期间。
  • L2 _ leaf _ reg-指定正则化项的系数。该术语是 L2,并被添加到成本函数中。
  • 深度 —树的深度。
  • min_data_in_leaf —指定何时停止分割。当实例数量低于此最小值时,该节点将成为一个叶节点。
  • one_hot_max_size —唯一值小于或等于该值的参数的 One-Hot 编码。
  • boosting _ type——“有序”或“普通”有序在较小的数据集上更好,但比普通方案慢。因此,对于较大的数据集,建议使用“普通”增强类型。
  • RSM—‘Alias:col sample _ by level’定义了用于在分割时选择特征以及再次随机选择特征的百分比。
  • bootstrap_type —对权重进行采样的方法,可以是“贝叶斯”、“伯努利”、“MVS”、“泊松”或“否”
  • bagging_temperature —定义贝叶斯引导的设置。当参数设置为 1 时,根据指数分布添加权重。
  • 子样本 —当‘泊松’、‘伯努利’或‘MVS’用于引导法时,使用装袋的采样率。

实验

对于这个例子,我在公共领域许可下使用 diamonds 数据集。这个数据集由分类变量和数字变量的组合组成。

该数据集旨在根据其他属性预测钻石的价格。一些变量是分类的,这通常需要一些预处理。

https://www.kaggle.com/shivam2503/diamonds

但是,使用 CatBoost,无需任何预处理就可以生成模型。此外,即使是缺失值也可以使用 CatBoost 进行处理,这使得它成为一个非常健壮且易于使用的模型。

只需加载数据集并运行。

为 CatBoost 设置 Optuna 研究(由作者编写代码)

在 Optuna 中设置研究后,仍需要调整一些参数。首先是采样器。在这里,我手动更改采样器以使用前面讨论的 TPESampler。这种选择确保了搜索将比标准的网格搜索更加结构化和有针对性。

需要注意的其他几个选项是方向、n_trials 和超时。方向规定了如何执行优化。确保这与您正在使用的损失函数的预期优化相匹配。

接下来,n_trials 控制将执行多少超参数空间的样本。加上超时,这两个因素会影响研究运行的时间。如果你发现自己时间紧迫,这些可以成为救命稻草。

由于搜索的最终状态将被保存(并可在以后重新启动),您可以使用同一研究连续搜索越来越好的超参数选择。

运行 Optuna 研究(作者代码)

超参数搜索的可视化

一旦研究终止,无论是在达到最后一次迭代还是达到超时限制之后,下一步就是评审研究结果。

上面的脚本将输出最佳模型性能和使用的超参数。您还可以使用 Optuna 的内置可视化功能查看研究进度。

超参数重要性

确定哪些参数对模型的整体性能影响最大。

绘图超参数重要性(作者代码)

来自 Optuna 的 CatBoost 超参数重要性图(由作者绘制)

多次迭代的性能

该图显示了模型在多次迭代中的性能。预期的行为是搜索顺序地提高模型性能。

情节优化进度(作者代码)

超过 100 次迭代的 Optuna 优化进度(由作者绘制)

单个超参数的性能

该图显示了多次试验中不同超参数的变化。颜色表示试用号。

因此,预期的行为是,随着研究的进展,超参数将收敛到单一值。

单个超参数性能(作者代码)

来自 Optuna 的单个超参数性能(由作者绘制)

包裹

如果没有对超参数进行适当的调整,模型的性能会受到很大影响。有几个选项可用于优化;然而,像 Optuna 这样的工具使这个过程变得简单而有效。

Optuna 为超参数优化和有效的搜索结构提供了一种基于贝叶斯的方法。用户可以搜索、停止、搜索更多内容并保存结果。

对于具有许多选项的复杂模型(如 CatBoost ),搜索可用模型配置的能力变得至关重要。

Optuna 为模型的实际超参数调整提供了一个理想的解决方案。

如果你有兴趣阅读关于新颖的数据科学工具和理解机器学习算法的文章,可以考虑在 medium 上关注我。我总是在我的文章中包含代码,您可以将其应用到您的工作中!

如果你对我的写作感兴趣,想直接支持我,请通过以下链接订阅。这个链接确保我会收到你的会员费的一部分。

https://zjwarnes.medium.com/membership

Python 中的超参数调整

原文:https://towardsdatascience.com/hyper-parameter-tuning-in-python-1923797f124f?source=collection_archive---------11-----------------------

网格搜索与随机搜索

照片由丹尼斯·莱昂Unsplash 上拍摄

当我跑完一个模型有一个结果的时候,我总想问问自己。这是我能得到的最好结果吗?

除了改变算法或增加训练数据量,我们还可以利用超参数调整来使模型对我们的数据集更加稳健

首先,让我们弄清楚术语。什么是参数,什么是超参数?

参数:****可以通过训练数据进行训练和调整的模型参数。例如 y = Ax+B。A 和 B 是可以由训练数据训练的参数。

超参数:不受训练数据影响的模型参数。它为该特定算法定义了底层模型结构。例如,决策树算法的休假次数

本文将介绍进行超参数调优的一般步骤和两个常用的自动调优包。出于演示目的,我使用 make_classification 包创建了一个分类数据集。

#Create classification dataset
from sklearn.datasets import make_classification
X, Y = make_classification(n_samples=10000, n_informative=10,n_redundant=0, n_classes=3,
                               n_features=10,
                               random_state=0)#split into training and testing set
from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=0)

基线模型(无调整)

import time
start = time.time()
import lightgbm as lgb
from sklearn.metrics import accuracy_score
clf = lgb.LGBMClassifier()
clf.fit(X=X_train, y=Y_train)
predicted=clf.predict(X_test)
print('Classification of the result is:')
print(accuracy_score(Y_test, predicted))
end = time.time()
print('Execution time is:')
print(end - start)

基本模型结果

我在这里使用了 Light GBM 作为算法。基线模型的准确率为 88.8%,完成整个过程只需要 0.3 秒。

超参数调整的步骤

第一步:我们想要实现什么?

首先,我们需要确定我们在调优过程中试图实现的主要目标。通常,有 3 个共同的目标。

  1. 提高准确性
  2. 减少过度拟合
  3. 更快的运行速度

前两个目标可以通过自动调整超参数来实现。我们可以通过在样本外数据集上测试来评估该模型(这意味着我们没有使用它进行训练)。

最后一个目标“运行速度”通常在处理大量数据时需要。如果数据科学模型已部署并每天运行,我们希望该模型能在合理的时间范围内给出结果。通常,我们可以在最后一步手动调整这一部分。

对于我的例子,我没有非常大的数据集,因此我只关心准确性和过度拟合问题(前两个目标)。

步骤 2:每个目标的调优参数是什么?

在我们明确了我们想要达到的目标之后,我们应该确定每个目标的调整参数。通常,根据您选择的算法,您可以找到关于所有可能的调优参数的文档。

在这个例子中,我使用的是 Light GBM,您可以在这里找到完整的参数列表。

以下是我为自动调谐选择的 5 个超参数:

  • num_leaves: 一棵树的最大叶子数,树模型的主要参数
  • min_child_samples: 一次休假的最小数据数
  • 最大深度:树的最大深度
  • learning_rate: 收缩率,决定模型可以学习的速度
  • reg_alpha: 正则化,处理过度拟合

“叶数”、“最小 _ 子 _ 样本数”、“最大 _ 深度”和“注册 _alpha”会影响精确度和过度拟合。“叶子数量”和“最大深度”的值越高,精确度越高,也会导致更多的过度拟合。min_child_samples 和 reg_alpha 越高,过拟合越小,但精度会降低。学习速率决定了模型学习的速度,但也会影响精度。

步骤 3:确定调谐的值范围

通常,当我们第一次开始使用某些算法时,我们不知道为自动调整设置什么值范围。我所做的是首先找出该超参数的默认值,然后围绕默认值设置数值范围。

我通常会运行模型 2 回合。对于第一轮,我通常会设置区间,主要是为了找到一个合适的参数值范围。例如,在我的例子中,num_leaves 是需要优化的最重要的参数。默认值为 31。因此,首先,我将范围设置为[10,20,30,60,90,120],范围很大。

在第一轮结果之后,我得到 num_leaves 的最佳参数值为 60。对于第二轮,我会将间隔再次设置为 60 左右,更接近于[40,50,60,70,80]。

您不需要运行模型太多次,因为最佳参数是不同参数的组合,因此单个参数没有最佳值。运行模型 2 次只是你在合理范围内缩小参数值的一种方法。

步骤 4:为模型运行自动调整

这里,我使用两种常用的方法 GridSearchRandomSearch 进行自动调优。这两种方法都采用了“适应和评分”方法。这意味着它将从定义的范围中选择一组超参数,拟合模型,产生分数,并最终输出具有最高分数的模型。这里的“分数”是由我们定义的,它取决于我们试图最大化什么。例如,它可以是准确度、对数损失、F1 分数等。

G rid 搜索与随机搜索

图片来自麻省理工学院关于随机搜索的论文

网格搜索:在预定义的参数值范围内进行穷举搜索。试验次数由调谐参数的数量和范围决定。

start = time.time()
from sklearn.model_selection import GridSearchCV
import lightgbm as lgb
lgb=lgb.LGBMClassifier()#Define the parameters
parameters = {'num_leaves':[20,40,60,80,100], 'min_child_samples':[5,10,15],'max_depth':[-1,5,10,20],
             'learning_rate':[0.05,0.1,0.2],'reg_alpha':[0,0.01,0.03]}#Define the scoring
clf=GridSearchCV(lgb,parameters,scoring='accuracy')
clf.fit(X=X_train, y=Y_train)
print(clf.best_params_)
predicted=clf.predict(X_test)
print('Classification of the result is:')
print(accuracy_score(Y_test, predicted))
end = time.time()
print('Execution time is:')
print(end - start)

网格搜索的结果

与基线模型相比,网格搜索将精确度提高了大约 1.2%。但是,运行时间是 4 个多小时!

随机搜索:从预定义的参数值范围内随机抽取样本。试验次数由‘n _ ITER’参数决定,因此更具灵活性。此外,如图所示,当您有一个连续的值范围时,它可以检索更多随机分布的情况,而不是从“网格线”中检索参数集。

start = time.time()
from sklearn.model_selection import RandomizedSearchCV
import lightgbm as lgb
lgb=lgb.LGBMClassifier()
parameters = {'num_leaves':[20,40,60,80,100], 'min_child_samples':[5,10,15],'max_depth':[-1,5,10,20],
             'learning_rate':[0.05,0.1,0.2],'reg_alpha':[0,0.01,0.03]}
clf=RandomizedSearchCV(lgb,parameters,scoring='accuracy',n_iter=100)
clf.fit(X=X_train, y=Y_train)
print(clf.best_params_)
predicted=clf.predict(X_test)
print('Classification of the result is:')
print(accuracy_score(Y_test, predicted))
end = time.time()
print('Execution time is:')
print(end - start)

随机搜索的结果

我指定试验次数为 100 次。随机搜索调优模型的精度仅比网格搜索低 0.3%。然而,它只需要 3.5 分钟,比网格搜索快得多。

第五步:看看调好的结果,做一些手动调整

根据目标和调整后的模型结果,您可以选择手动调整一些超参数。例如,如果测试精度仍然远低于训练精度,您可以选择为正则化设置更高的值,以减少过度拟合。或者,如果你想提高跑步速度,你可以设置一个较高的学习率或减少 num_leaves。

建议/结论

本文的主要信息不仅仅是关于超参数自动调整的技术部分,还包括我们应该如何调整超参数的思考过程

在网格搜索和随机搜索之间,我推荐使用随机搜索,原因如下:

  1. 随机搜索有更多的灵活性,可以控制你想进行多少次试验。
  2. 随机搜索的运行时间通常要短得多,因此它给你更多的时间来尝试更多轮次的调优。
  3. 对于连续超参数,随机搜索可以探索一组更独特的值

如果你有任何问题或建议,或者任何你想了解的新话题,请在评论中提出!

感谢您的阅读,希望它能帮助您更好地理解超参数调优。

超维度假设检验——多尺度图形相关性和距离相关性

原文:https://towardsdatascience.com/hyperdimension-hypothesis-testing-multiscale-graph-correlation-and-distance-correlation-119f2c2c6c18?source=collection_archive---------39-----------------------

理解大数据

如何对大型数据集进行独立性和 K 样本测试

你有没有想过:

  • 两个变量是否相关?
  • 两个样本是否来自同一个分布?

如果是这样的话,这篇文章是给你的。本文将解释这两种方法,并在最后介绍 Hyppo 库。

距离相关(Dcorr)

这一理论最初由加博·j·策克利等人发表在 2007 年《统计年鉴》上。它是对任意维度的两个随机向量对之间的相关性的一种度量,这两个向量不一定相等。通过一些设计调整,它也可以用于 K 样本测试。

有什么了不起的?这是非参数测试,意味着没有关于变量之间关系的潜在假设,也没有关于分布的假设。与传统的相关方法如 Pearson's r 相比,它可以有效地检测出数据中的非线性关系

样本数据集性能

数学定义

下面是计算距离相关性的公式。

距离关联

x 和 Y 是双中心距离矩阵。这两个矩阵之间的协方差是分子,标准差的乘积是分母。在我看来,理解这种方法主要有三个要素:

  • 距离矩阵:存储给定变量任意两点之间欧几里得距离的成对矩阵。

距离矩阵

  • 双中心矩阵:对于距离矩阵中的每个元素,减去列和行的平均值,然后加上矩阵的大平均值。本质上,这一步是将原点更改为点云的中心(我知道最初听起来可能很混乱,但一个简单的例子即将出现)。

双定心

  • Frobenius 内积:它是上一步中两个双中心矩阵的内积,是一个标量值。结果表明这两个矩阵是多么相似。如果它们是独立的,你会得到 0。你可以把这个操作想象成表示两个矩阵在高维空间正交性的向量点积。

距离协方差

简单的例子

感谢这个讨论,我做了一些可视化来说明这个概念。这里我们有四个点(𝑋,𝑌)=[(0,0),(0,1),(1,0),(1,1)组成一个正方形。

作者图片

X 和 Y 的距离矩阵为:

X = array([[0., 0., 1., 1.],
          [0., 0., 1., 1.],
          [1., 1., 0., 0.],
          [1., 1., 0., 0.]])Y = array([[0., 1., 0., 1.],
          [1., 0., 1., 0.],
          [0., 1., 0., 1.],
          [1., 0., 1., 0.]])

双居中后,矩阵将变成:

X_centered = array([[-0.5, -0.5,  0.5,  0.5],
                    [-0.5, -0.5,  0.5,  0.5],
                    [ 0.5,  0.5, -0.5, -0.5],
                    [ 0.5,  0.5, -0.5, -0.5]])Y_centered = array([[-0.5,  0.5, -0.5,  0.5],
                    [ 0.5, -0.5,  0.5, -0.5],
                    [-0.5,  0.5, -0.5,  0.5],
                    [ 0.5, -0.5,  0.5, -0.5]])

唯一满足条件的点是正方形的中点。

作者图片

多尺度图形相关(MGC)

MGC 是一个相对较新的衡量标准,由学者岑成·申、凯里·e·普里贝和约书亚·t·沃格尔斯坦在 2018 年提出。本质上,它是 K 最近邻(KNN)和距离相关性(Dcorr)的组合。

主要优势:

  • 也是非参数假设检验,没有数据关系和分布的底层假设。
  • 与之前提出的分析大型复杂数据集的方法相比,它需要一半到三分之一的样本量。
  • 它表明不同属性之间关系的性质。

它与 Dcorr 的区别在于能够检测数据子集中的非线性关系。下面是论文中的一个例子。如果云密度和地面湿度之间存在线性关系,则一个变量的距离变化与另一个变量相关。MGC 和 Dcorr 都能成功地拒绝两个变量相互独立的零假设。然而,如果关系是螺旋形的(底部),则一个区域中的距离变化仅在小区域中与另一个区域相关。使用所有的数据并不能提供足够的信息来检测这种关系,因此只有 MGC 在这种情况下工作得很好。详细解释请参考⁴.的论文%2C%20thereby%20motivating%20its%20use%20here.)

来源

MGC ≈ KNN +德科尔

下面的伪代码说明了主要的架构。首先,它计算变量 X 和 y 的距离矩阵。

纸上公式

然后,它会创建一个多尺度相关图,并返回最高的统计得分 C*。这一步是 MGC 和 Dcorr 的主要区别。这里是一个高层次的总结:

  • 对输入距离矩阵 A(列)和 B(行)进行排序。
  • 计算具有不同大小的最近邻 k(对于矩阵 A),l(对于矩阵 B)的距离相关性。这就构造了一个新的相关矩阵,k 为行,l 为列。每个元素包含在 k,l 组合中计算的距离相关值。
  • 在相关图中找到最大的 连通区域 ,避免样本噪声引起的相关膨胀。

最后,它运行置换测试,交换 Y 变量的值,并重复前面的步骤来生成一组统计分数。最后,它将观察样本的 C*与排列测试的所有其他分数进行比较,并计算 P 值。

用例

  • 评估聚类结果,如客户特征分析。
  • 使用嵌入确定文档是否来自同一人群。
  • 选择与目标变量相关的特征。
  • 还有更多…

希波

这是实现 MGC 和 Dcorr 的库。这是一个很好的工具,可以用详细的文档来检验超维度假设。我利用这个库构建了一个简单的演示代码,这里是笔记本

快乐阅读!

参考资料:

  1. https://arxiv.org/pdf/0803.4101.pdf
  2. https://en.wikipedia.org/wiki/Distance_correlation
  3. https://arxiv.org/abs/1710.09768
  4. https://elifesciences.org/articles/41690

使用机器学习的超局部空气质量预测

原文:https://towardsdatascience.com/hyperlocal-air-quality-prediction-using-machine-learning-ed3a661b9a71?source=collection_archive---------25-----------------------

实践教程

使用公开可用数据预测加州奥克兰的空气质量

加利福尼亚州奥克兰市谷歌街景车测量的 NO2 浓度

介绍

当谷歌和法国电力公司发布了他们关于奥克兰空气污染地图的研究时,这项研究的结果获得了很多关注。他们发布的数据是首批数据集之一,显示了东奥克兰和西奥克兰不同城市街区的空气质量如何变化。以前,奥克兰的空气质量测量只能通过放置在城市不同地方的少数几个监测器获得。这项研究揭示了奥克兰许多地方的空气污染水平上升,特别是在水泥厂和汽车修理厂附近的社区,这些地方以前并不明显。

作为一名环境研究人员和数据科学家,我很想知道我是否可以将从重复的道路采样(2015-2016 年)中收集的数据集与机器学习相结合,以预测城市中不同位置的空气质量,这些位置没有测量数据。这可以帮助我们更好地了解个人暴露于污染的程度。

任何地方的空气质量取决于几个因素,如主要街道和高速公路上的交通、铁路、港口和工业来源的排放、时间因素以及其他气象因素,如风速和风向。经过大量的研究,我决定将我的项目范围扩大到探索以下问题:

“我们能否建立一个机器学习模型,根据当地的气象条件、当地的排放源(如工业)和高速公路上的交通状况,预测奥克兰任何位置的空气质量?”

使用 Folium、Streamlit 和 Heroku 创建的 web 应用程序快照。查看这篇博客了解更多细节。

我开发了这个网络应用程序,它可以预测奥克兰所有居民区的黑碳(BC)和二氧化氮(NO2)的污染浓度。这款网络应用能让用户了解他们所在社区的空气污染物浓度,帮助识别空气质量好的地区,以便购买或租赁房屋,并帮助识别浓度异常高的“热点”。

下面概述了构建这个 web 应用程序的数据分析和机器学习管道。

数据分析和机器学习管道

目标变量

EDF 和谷歌的科学家收集的数据集包含了 2015 年 6 月至 2016 年 5 月期间由配备移动传感设备的谷歌街景车在 150 天内收集的 NO2、BC 和一氧化氮(NO)的浓度。然后,在一年的时间内对数据集进行汇总,得出奥克兰市约 30 米范围内的中值浓度。

下图显示了在奥克兰地区测量的 NO2 浓度(ppb)图。然而,这个数据集虽然非常有用,但只提供了奥克兰某些街区的空气质量测量值。

奥克兰市年平均 NO2 浓度(ppb)图。浓度测量是由谷歌街景车拍摄的,这些车驶过了东奥克兰和西奥克兰的几乎所有街区。这里有一张互动地图。

为了使用这个数据集来建立一个可以预测奥克兰其他社区空气质量的概化模型,我首先训练了一个机器学习模型,通过创建一组描述污染物浓度的概化特征来预测 EDF 数据集中测量的相同位置的空气污染物浓度。然后,我使用这个经过训练的模型,通过为感兴趣的位置生成这些特征来预测任何给定地址的浓度。

让我们首先看看这些特性是如何基于位置(坐标)开发的。

输入数据和特征工程

为了开发可用于预测浓度的特征集,我们首先需要了解任何给定位置(“目标位置”)的空气浓度如何与空气污染源相关联,例如工业排放、交通排放和当地气象参数。

我将这些功能分为以下几类:

排放点源 —我使用美国环保局的国家排放清单数据库 (2014)来获取奥克兰所有主要点源的位置,并使用“点源和目标位置之间的距离”作为度量标准来测量与浓度的相关性。

交通 —为了理解每个地点的空气污染如何与交通相关,我使用了两种不同的交通指标作为特征。第一个交通指标是 1000 英尺范围内的交通路口数量。感兴趣位置的半径,第二个度量是感兴趣位置到高速公路的接近度(距离)。使用立交桥 API 从 OpenStreetMap 获取交通指标。

气象参数——了解空气污染与年平均气象参数如降水、气压、最低气温的关系。还有麦克斯。温度和太阳辐射,我使用橡树岭国家实验室的 Daymet 数据集通过对 2015 年 6 月至 2016 年 5 月的每日数据进行平均,以 1 公里乘 1 公里的网格为基础获得了奥克兰所有地区的气象参数。**

预测空气浓度的机器学习模型模式

上图显示了所有输入数据集和机器学习模型模式的列表。最终特征集包含 324 个特征,这里的目标变量是不同点的 NO2 浓度。

  • *虽然风速和风向肯定起着重要作用,但我暂时忽略了这两个方面,因为这里测量的浓度是年平均值。

开发机器学习模型

为了建立一个预测浓度的模型,我尝试了五种不同的机器学习算法,包括简单的线性回归模型、岭回归、弹性网、随机森林和 XGBoost 回归。将 NO2 数据集分成测试/训练数据,并将 4 重交叉验证方法应用于训练数据集。模型预测与来自 Google-EDF 数据集的地面实况测量进行了比较。随机森林和 XGBoost 方法产生了最佳预测。由于 XGBoost 具有最低的 RMSE (2.69)和最高的 R2 值(0.925),所以我选择实现 XGBoost 模型来将预测扩展到不同的邻域。

NO2 测试数据集的 XGBoost 预测

我使用随机森林方法来了解哪些特征在预测浓度时最重要,并根据重要性对这些特征进行排序。下面的交互式地图显示了对该地区 NO2 浓度贡献最大的前 100 个污染源(在本例中为要素)的位置。圆点的大小表示特征的重要性,圆点越大表示重要性越高。

该图显示了机器学习模型中预测 NO2 浓度(ppb)的前 100 个特征的位置。黑色圆圈的大小表示特征的重要性。一张互动版地图在这里https://varshg.com/aq-maps/NO2-feature-imp.html

影响该地区 NO2 浓度的一些最重要的特征包括带有发电机的商业综合体(KTUV Fox 2 办公室)、奥克兰国际机场、圣莱安德罗的一家医院(可能带有发电机和锅炉)以及奥克兰的数字房地产数据中心。

在不同的街区做预测

下一步是使用 XGBoost 模型来预测整个奥克兰地区点网格中的浓度,方法是为网格中的每个点生成一个要素集。对于每个网格点,我使用生成的输入特征集和 XGBoost 模型来预测该点的浓度。

下图显示了加利福尼亚州奥克兰市不同社区所有网格点的 NO2 浓度(ppb)预测热图。

奥克兰预测 NO2 浓度图(ppb)。互动地图在这里可用。

皮埃蒙特附近有高浓度的 NO2,这可能主要是由于靠近主要公路(I-580)。San Leandro 区域附近的蓝/绿色区域表示 NO2 浓度较低,因为这些邻近区域距离主要点源较远。

我用同样的方法建立了一个不同的模型来预测生物浓缩度(微克/立方米)。

奥克兰的预测生物浓缩地图(微克/立方米)。互动地图在这里可用。

结论和后续步骤

这项工作利用环境保护基金与奥克兰谷歌街景合作收集的空气污染监测数据集,建立一个机器学习模型,使用主要排放源、交通路口数量、与高速公路的接近程度和当地气象数据的公开数据来预测任何感兴趣位置的空气污染浓度。该模型针对奥克兰地区一些邻近地区的数据点进行训练,用于预测整个奥克兰地区数据点网格中的浓度。

这里生成的热图特别有助于城市规划者、环境管理团队和公共卫生专家预测加利福尼亚州东湾区任何位置的空气质量,并确定“热点”或浓度异常高的位置。这项工作的另一个应用可能是让公众识别空气质量好的社区,以便购买、出租或出售他们的房屋。

最近,谷歌发布了一个包含湾区所有城市测量的浓度的空气质量数据集,建立一个类似的机器学习模型来预测湾区不同城市的浓度会很有趣。

我的 Github 库为这项工作,随着更详细的报告可以在这里找到。如果你有兴趣了解更多关于这个网络应用是如何建立的,看看我的帖子这里

HyperLogLog:数据科学家的简单而强大的算法

原文:https://towardsdatascience.com/hyperloglog-a-simple-but-powerful-algorithm-for-data-scientists-aed50fe47869?source=collection_archive---------6-----------------------

理解大数据

如何使用很少的内存和时间来估计超大数据集中的基数?

HyperLogLog 是一个美丽的算法,即使只是学习它也让我兴奋不已(部分是因为它的名字)。

这个简单但极其强大的算法旨在回答一个问题:如何在一个非常大的数据集中估计唯一值的数量(即基数)?这个问题在计算机科学中被称为 Count-distinct 问题或者应用数学中的基数估计问题。在本文中我们称之为基数估计问题,因为它听起来更令人印象深刻。

但是在我们理解 HyperLogLog 如何解决基数估计问题之前,我们首先要知道为什么我们需要 HyperLogLog 来解决这个问题。

马库斯·斯皮斯克Unsplash 上拍摄

展览中有多少独特的参观者?

想象你正在举办一个艺术展。你的工作是站在入口处,数一数到目前为止有多少访客,只用笔和纸。假设计数中的小误差是可以接受的,你如何完成任务?

一个解决办法是:写下所有访客的全名,然后检查上面有多少独特的名字。

但是如果你一天有成千上万的访问者呢?你有足够的文件吗?写下成千上万个名字你会开心吗?

另一个解决方法是:你可以写下他们电话号码的最后 6 位,而不是写下他们的名字。

尽管如此,它仍然需要大量的工作。现在,让我们把任务变得更加困难。你能实时或接近实时地统计数字吗?更难的是:你能仅仅通过数手指来完成任务吗?

Flajolet-Martin 算法

是的,你可以。你可以通过手指计数来实时统计成千上万的独立访客。

我们的朋友 Philippe Flajolet 和 G. Nigel Martin 在他们 1984 年的论文“数据库应用的概率计数算法”中介绍了一种出色的算法,可以帮助我们解决这个问题。[1]

解决方法是:用你的手指记录你在电话号码的 6 位数中看到的最长的前导零序列。

例如,如果你得到532885,最长的零序列是 0。

下一次你得到042311,最长的序列现在是 1。

当你看到超过 10 个人时,最长的序列很可能是 1。同样,当你看到超过 100 个人时,最长的序列将更有可能是 2。

很容易看出,在随机数据中,平均每一个 10ᴷ元素中会出现一次K0 序列。

现在,想象你现在最长的序列是 5,很有可能你见过 1000 多人找到某人电话号码的后 6 位数字以00000开头。

你明白了。

基于概率,估计有多少独特的游客将接近 10ᴸ,因为 l 是你在所有数字中找到的最长的前导零序列。

事实上,在我们朋友 1984 年的文章中,他们首先散列元素以获得更均匀分布的二进制输出。例如,他们可能将一个元素 x1 散列到010001,将另一个元素 x2 散列到101000。因此,由于某些模式(如区号)而不是均匀分布的电话号码也可以正确估计。此外,因为他们把输出变成了二进制位数组,现在基数的估计是 2ᴸ.

然而,统计分析表明,2ᴸ实际上引入了一个可预测的偏差。因此,他们加上一个修正系数 ϕ ≈ 0.77351 来完成最终公式:2ᴸ / ϕ

这个算法叫做 Flajolet-Martin 算法。多好的名字!稍后我们会看到命名的重要性,以及 Flajolet 实际上是如何提高他的命名技巧的。

如何改进:日志日志

我知道你可能认为这种估计似乎不那么可靠。想象一下,从第一个元素得到的哈希值是000000010——jackpot!在现实生活中,数据中的一些异常值可能会打乱我们的估计。当然,我们的朋友 Flajolet 也知道。

如何让我们的估计少受离群值的影响?一个显而易见的解决方案是使用多个独立的哈希函数重复 Flajolet-Martin 算法,并对所有结果进行平均。例如,如果我们使用 m 个不同的哈希函数获得最长的前导零序列,这里我们将最长的前导零序列的值表示为 L₁、L₂、…、Lₘ,那么我们的最终估计值就是 m * 2^((L₁+…+Lₘ)/m).

但是,使用多个哈希函数对输入进行哈希运算的计算开销会非常大。因此,我们的朋友 Flajolet 和他的新朋友 Marianne Durand 想出了一个变通办法:使用一个哈希函数并使用其部分输出将值拆分到许多不同的桶中,怎么样?为了将值分成桶,他们只使用哈希值的前几位作为桶的索引,并根据剩余的内容计算前导零的最长序列。

例如,如果我们想要四个桶,我们可以使用哈希值输出的前两位作为桶的索引。假设我们有四个元素,并获得它们的哈希值:

Hash(x1) = 100101:现在第二个(10)桶,最长的前导零序列= 1 ( 0101)

Hash(x2) = 010011:现在第一个(01)桶,具有最长的前导零序列= 2 ( 0011)

Hash(x3) = 001111:现在第 0 个(00)桶,最长的前导零序列= 0 ( 1111)

Hash(x4) = 110101:现在第三个(11)桶,最长的前导零序列= 1 ( 0101)

所有桶的最长前导零的平均值为(0+2+1+1)/4 = 1。所以,我们这里的估计是 4 * 2。它并不接近真实值,因为这里我们只有很少的样本,但你会明白的。

你可以在他们 2003 年的论文“大基数的对数计数”中找到关于对数对数的校正因子的更多细节。2

这是对数对数,求估计值的平均值以减少方差。对数对数的标准误差为 1.3/√m,给定 m 为桶数。

我们能不能取个更好的名字:SuperLogLog

在提出 Flajolet-Martin 算法和 LogLog 之后,我们的朋友 Flajolet 在处理基数估计问题方面势不可挡。他决定把这个问题推到极端。

在引入 LogLog 的同一篇论文[2]中,Durand 和 Flajolet 发现,在对这些篮子进行平均之前,通过剔除它们获得的最大值,可以大大提高精确度。

更具体地说,当从桶中收集值时,我们可以保留 70%的最小值,并丢弃其余的值进行平均。这样做,精度从 1.3/√m 提高到 1.05/√m,真是奇迹!在这里,他们决定给这种方法起一个更好的名字:SuperLogLog。

终极炒作:超日志

2007 年,我们亲爱的朋友 Flajolet 终于找到了基数估计问题的终极解决方案。这个解决方案就是 HyperLogLog,他称之为“接近最优的基数估计算法”。【3】背后的想法很简单:我们可以用调和平均而不是用几何平均来平均我们从 LogLog 得到的结果!

调和平均值是倒数平均值的倒数。

倒数仅仅意味着 1/值。所以调和平均数的公式是 n / (1/a + 1/b + 1/c + …)。

例如,1,2,4 的调和平均值为

3 / (1/1 + 1/2 + 1/4) = 3 / (1.75) = 1.714

为什么使用谐波手段?因为它擅长处理大的异常值。例如,考虑 2、4、6、100 的调和平均值:

4 / (1/2 + 1/4 + 1/6 + 1/100) = 4.32

这里的大异常值 100 被忽略,因为我们只使用它的倒数。因此,我们得到了一个平均方法,可以减少受大离群值的影响。

同样,你可以在他们 2007 年的论文“HyperLogLog:一个接近最优的基数估计算法的分析”中找到关于 HyperLogLog 的修正因子 ϕ 的更多细节。[3]

通过使用调和平均值代替对数对数中使用的几何平均值,并且在超对数中仅使用 70%的最小值,超对数实现了 1.04/√m 的误差率,是所有误差率中最低的。

现实世界应用中的超对数

现在我们明白了超对数是如何工作的。该算法可以使用很少的内存和时间来估计非常大的数据集中唯一值的数量。事实上,它可以在仅使用 1.5kb 内存的情况下,以 2%的标准误差估计 10⁹以外的基数。在野外哪里可以找到 HyperLogLog?

照片由埃里克·麦克莱恩Unsplash 上拍摄

一个例子是 Reddit 如何计算一个帖子的独特浏览量。在 Reddit 的文章视图计数中,他们阐述了 HyperLogLog 如何满足他们对视图计数的四个要求:

  • 计数必须是实时或接近实时的。没有每日或每小时的总量。
  • 在短时间窗口内,每个用户只能被计数一次。
  • 显示的计数必须在实际计数的几个百分点之内。
  • 该系统必须能够以生产规模运行,并在事件发生后的几秒钟内处理事件。

其他一些很好的例子是必须处理 Pb 级数据的数据库和数据仓库。为了支持高效的计数唯一函数进行数据查询,这些应用程序使用了 HyperLogLog。这样的例子有雷迪斯亚马逊红移脸书普雷斯托BigQuery阿帕奇德鲁伊

结论

就是这样。在这篇文章中,我们看到了纸与纸之间思想的发展和完善。我们学习计数不同问题(基数估计问题),我们的朋友 Philippe Flajolet 和他的许多朋友,Flajolet–Martin 算法,LogLog,SuperLogLog,HyperLogLog 算法,以及它们的应用。

顺便提一下,在原始论文中,Flajolet-Martin 算法实际上是计算二进制中最低有效位的位置,而不是计算前导零的最长序列。此外,LogLog、SuperLogLog 和 HyperLogLog 实际上计算最左边的 1 的位置(所以它是 1 +前导 0 的数目)。为了清楚起见,我简化了这些细节,但是概念都非常相似。感兴趣的读者可以阅读原文,了解更准确的细节。

在你离开之前,你可以试着自己回答这些问题,作为对算法的复习。

  • 有什么问题?
  • 为什么要用算法?
  • 算法如何解决问题?
  • 算法用在哪里?

希望你喜欢这篇文章,并感谢阅读。

感谢 Colin Gladue 和 Ting-Wei (Tiffany) Chiang 阅读本文的草稿。

参考

  1. 菲利普·弗拉霍莱特;马丁·奈杰尔(1985)。“数据库应用的概率计数算法”
  2. 玛丽安·杜兰德;菲利普·弗莱霍莱(2003 年)。“大基数的双对数计数”
  3. 菲利普·弗拉霍莱特;Fusy,ric 奥利维耶·甘杜埃;弗雷德里克·穆尼尔(2007 年)。 HyperLogLog:对一个接近最优的基数估计算法的分析

来源:https://upload . wikimedia . org/Wikipedia/commons/7/75/philippeflajolet . jpg

想了解更多?每周 I/O!

每周 I/O 是一个我分享我的学习输入/输出的项目。每个星期天,我都会写一封电子邮件简讯,里面有我那一周发现和学到的五件事。

在这里注册,让我与你分享一份学习输入/输出的精选清单🎉

超视:基于贝叶斯优化的超参数调整

原文:https://towardsdatascience.com/hyperopt-hyperparameter-tuning-based-on-bayesian-optimization-7fa32dffaf29?source=collection_archive---------2-----------------------

实践教程

优化机器学习流水线的函数和超参数的替代方案。

图一。远视的代表性建筑|作者图片|图标取自维塔利·戈尔巴乔夫自由选择

为给定的功能找到最佳的超参数配置不应该完全基于直觉或一些人的经验。相反,对这种最优配置的研究必须得到保证这种最优性的方法的支持。在这么多的方法中,我们可以找到一些基于穷举搜索(例如网格搜索和随机搜索[ 1 ]),或者在优化范式下,例如遗传算法(例如 TPOT [ 2 ])和贝叶斯优化 [ 3 )。

让我们来谈谈 HyperOpt ,这是一款基于贝叶斯 优化并由 SMBO (基于序列模型的全局优化)方法支持的工具,旨在自动搜索最优超参数配置。所以,这个博客将被划分如下:

  • 什么是远视?
  • 什么是 hyperpt-sk learn?
  • 实践中的远视
  • HyperOpt-sk 在实践中学习

什么是远视?

HyperOpt 是由 James Bergstra 于 2011 年创建的开源 python 库【4】。 HyperOpt 是一个工具,允许自动搜索机器学习模型的最佳超参数hyperpt基于贝叶斯 优化,由 SMBO 方法支持,适用于不同的算法,例如:Parzen 估计器树( TPE )、Parzen 估计器自适应树( ATPE )和高斯过程(GP)【5】。

贝叶斯优化的方法集中在概率模型 P(得分|配置)上,通过查询(得分,配置)的历史 H 的迭代过程来更新概率模型,其目标是在给定配置 c 的情况下最大化得分HyperOpt贝叶斯优化为前提,通过在采样过程、搜索空间的定义和缩小以及最大化概率模型的算法上做一些改动【4】。

HyperOpt 需要 4 个基本组件来优化超参数:搜索空间、损失函数优化算法和用于存储历史的数据库(得分、配置)。搜索空间将由连续凸函数确定。损失函数是需要优化的函数,它是通过评估具有“ c 配置的模型获得的。优化算法基于 SMBO 方法,具有 GPTPEATPE 算法给出的变体。“ H ”数据库存储通过优化算法的迭代获得的一组元组(s 核心,配置)。在图 2 中,我们可以看到关于 HyperOpt 如何工作的图形描述。

图二。作者远视图像的典型行为

鉴于 HyperOpt 的可用性和可伸缩性,创建了一个扩展,它合并了各种 scikit-learn 组件,以便优化带有大量参数的机器学习管道,这个扩展被称为 HyperOpt-Sklearn ,我们将在下一节中讨论它,让我们开始吧!

什么是 HyperOpt-Sklearn?

HyperOpt-Sklearn 于 2014 年推出[6]。 HyperOpt-Sklearn 构建在 HyperOpt 之上,旨在与 scikit-learn 套件的各种组件协同工作。创建 HyperOpt-Sklearn 的目的是优化机器学习管道,具体解决数据转换模型选择超参数优化的阶段。 HyperOpt-SklearnHyperOpt 的优点与 scikit-learn 框架的可用性和灵活性相结合,从这个意义上来说, HyperOpt-Sklearn 被设计用来处理分类和回归任务。在图 3 中,我们可以看到由 HyperOpt-Sklearn 优化的 ML 管道的组件。

图 3。由 HyperOpt-Sklearn 优化的 ML 管道组件|作者图片

简而言之,hyperpt旨在贝叶斯优化范式下优化一个或多个给定函数的超参数。另一方面, HyperOpt-Sklearn 被开发来优化机器学习流水线的不同组件,其使用 HyperOpt 作为核心,并从 scikit-learn 套件中获取各种组件。现在让我们看看如何在实践中使用它们。

实践中的远视

既然我们已经了解了hyperpt的工作原理及其组件,让我们来看看一个基本的实现。对于这个例子,我们将使用图 4 所示的函数。我们可以看到,函数的最小值是在 x = -0.5 的值时给出的。我们来看看如何在hyperpt中找到这个值。

图 4。作者使用 HyperOpt | Image 优化的示例函数

HyperOpt 需要 4 个基本实现参数,分别是:待优化的函数、搜索空间、优化器算法和迭代次数。因此,实现应该是这样的:**

代码片段 1。远视实施

正如我们所见,我们正在定义hyperpt优化虚拟函数所需的每个组件。在第 7 行中,执行要优化的函数的定义。在第 11 行中,执行了搜索空间的定义,在这种情况下,只为“ x 的值定义了一个搜索空间,然而,对于具有一个以上变量的函数,将需要为每个变量定义一个搜索空间,同样,这种搜索空间将取决于要优化的函数的类型。在这种情况下,出于教导的目的,搜索空间被定义为从-2 到 2。最后,在第 18 行,托管优化过程的类被初始化。该函数接收待优化的函数搜索空间、o 优化算法(在这种情况下,它是 Parzen 估计器的树形结构)和迭代次数作为参数。当执行前面的代码片段时,我们获得了优化函数的“ x 的值:**

*Optimal value of x: {'x': -0.5000806428004325}*

前面的实现是一个基本示例,说明了hyperpt的工作原理及其主要组件。更复杂函数的优化需要搜索空间和优化器的充分定义。 HyperOpt 提供了一套搜索空间初始化器,你可以在这里找到

很好,我们已经看到了 HyperOpt 如何在基本实现中工作,现在让我们看看 HyperOpt-Sklearn 如何为机器学习流水线优化工作。

HyperOpt-sk 在实践中学习

实现 HyperOpt-Sklearn 的方式与 HyperOpt 颇为相似。由于 HyperOpt-Sklearn 专注于优化机器学习流水线,需要的 3 个基本参数是:预处理器的类型、机器学习模型(即分类器或回归器)和优化器。值得一提的是,这三个基本元素中的每一个都可以根据每个问题的需要进行定制。

HyperOpt Sklearn 中适配的预处理器有: PCATfidfVectorizerStandardScalar, MinMaxScalar规格化器OneHotEncoderHyperOpt Sklearn 中适配的*分类器有: SVC,LinearSVC KNeightborsClassifier。RandomForestClassifier,extratereclassifier SGD classifier,MultinomialNB,BernoulliRBM,ColumnKMeans。***

出于这篇博客的目的,让我们看看分类问题中 HyperOpt-Sklearn 的两个基本实现。在这个例子中,我们将使用众所周知的乳腺癌数据集。

代码片段 2。用于分类的 HyperOpt-Sklearn

正如我们所看到的,在第 22 行中,我们定义了将要实现的分类器,在这种情况下,指令是搜索由 HyperOpt-Sklearn 定义的所有分类器(实际上,由于优化所需的计算时间,不建议这样做,因为这是一个实际的例子,进行完全搜索不是一个决定性因素)。在第 23 行中,定义了数据将接收的转换类型,在本例中是使用由 HyperOpt-Sklearn 实现的完整转换器套件的指令(正如您所猜测的,只测试那些适合数据集的转换,例如文本转换器不适用于数值数据集)。在第 24 行定义了优化器,在本例中是 TPE 。其余的行决定了迭代的次数和每次评估的时间限制。

当执行代码片段 2 时,我们获得

*Train score: 0.9723618090452262
Test score: 0.9824561403508771*

最佳配置是:

*{'learner': **ExtraTreesClassifier**(**max_features**=None, **min_samples_leaf**=9, **n_estimators**=19, **n_jobs**=1, **random_state**=3, **verbose**=False), '**preprocs**': (**MinMaxScaler**(**feature_range**=(-1.0, 1.0)),), '**ex_preprocs**': ()}*

嗯,我们已经通过在 HyperOpt-Sklearn 覆盖的分类问题的整个范围内进行搜索,获得了一个最佳配置。现在让我们看看如何通过使用特定的分类器来缩小搜索空间。

对于这个例子,我们也将使用乳腺癌数据集。然而,这一次我们将使用单个分类器,我们将通过为每个分类器定义一个搜索空间来优化它的每个参数。

代码片段 3。用于分类和定制 SGD 分类器的 HyperOpt

在本例中,我们使用 SGD 作为分类器,我们希望优化损失参数以及 alpha 值。正如我们所看到的,在第 23 行中,我们为丢失定义了一个搜索空间,这样的搜索空间由三个不同的值(铰链对数胡贝尔)定义,在选择这三个值之一时会考虑一个概率值。另一方面,在第 29 行中,我们为 alpha 值定义了搜索空间,在这种情况下,实现了一个对数函数,它由一个下限上限限定。最后,在第 33 行,定义了将托管优化过程的类。它接收的参数是分类器(及其各自的参数和搜索空间)、优化器、迭代次数和每次评估的指定时间。

当执行代码片段 3 时,我们获得

*Train score: 0.9522613065326633
Test score: 0.9473684210526315*

找到的最佳配置是:

*{'learner': **SGDClassifier**(**alpha**=0.08612797536101766,     **class_weight**='balanced', **eta0**=6.478871110431366e-05, **l1_ratio**=0.20803307323675568, **learning_rate**='invscaling', **loss**='log', **max_iter**=18547873.0, **n_jobs**=1, **power_t**=0.1770890191026292, **random_state**=0, **tol**=0.000332542442869532, **verbose**=False), 
'preprocs': (**PCA**(**n_components**=8),), '**ex_preprocs**': ()}*

HyperOpt-Sklearn 配置和定制将始终取决于要解决的问题类型、数据类型以及可用的计算能力。

结论

在这篇博客中,我们看到了什么是hyperpt,它的目的,它是如何工作的,它的主要组件是什么。同样,我们看到了hyperpt的主要扩展之一,也就是hyperpt-sk learn,它的组件以及它是如何工作的。

HyperOpt 是超参数优化的替代方案,无论是在特定函数中,还是优化机器学习的流水线。hyperpt的一大优势是通过特定的调整实现了贝叶斯优化,这使得hyperpt*成为调整超参数的考虑工具。*

参考

[1] 调整估计器的超参数

[2] TPOT:用遗传算法进行管道优化

[3] 贝叶斯优化教程

[4] 建立模型搜索的科学:视觉架构的数百维超参数优化

[5] 超参数优化算法

[6]Hyperopt-sk Learn:sci kit-Learn 的自动超参数配置

初学者的超参数优化

原文:https://towardsdatascience.com/hyperparameter-optimization-for-beginners-32e3ab07b09c?source=collection_archive---------19-----------------------

科学家讨厌的任务数据

照片由德鲁·帕特里克·米勒Unsplash 上拍摄

许多数据科学家忽略了超参数。超参数调整是一项高度实验性的活动,这种不确定性会导致任何正常人的严重不适,这是我们自然试图避免的。

“超参数调整更多地依赖于实验结果,而不是理论,因此确定最佳设置的最佳方法是尝试许多不同的组合[…]。”— Will Koehrsen,超参数调整 Python 中的随机森林

不幸的是,应该这样做。我们不会走进商店,从货架上挑选一双运动鞋,然后买下来。我们首先选择一双我们认为能解决我们问题的鞋,不管是衣柜故障还是其他什么原因,我们已经失去了所有的运动鞋。接下来,我们在购买之前调整超参数,如鞋子的尺寸和我们想要的颜色。

如果我们愿意在现实世界中这样做,那么在数据科学中就不应该跳过它。

理解超参数

超参数优化是为学习算法选择最优超参数集的问题。通过确定超参数的正确组合,模型的性能得到了最大化——这意味着当提供看不见的实例时,我们的学习算法会做出更好的决策。

被选为超参数的值控制学习过程,因此,它们不同于正常参数,因为它们是在训练学习算法之前被选择的。

在形式上,模型超参数是在提供数据时不能由模型估计的参数,因此需要预先设置它们来估计模型的参数。相反,模型参数由学习模型根据提供的数据来估计。

方法

有许多方法可以有效地执行超参数优化——参见维基百科上的超参数优化获得完整的分类。Mind Foundry 在 Twitter 上进行了一项调查,以了解平台上从业者的情绪。

Mind Foundry 在推特上进行的调查

让我们进一步了解它们,以及如何在 Python 中执行它们。

贝叶斯优化

维基百科将贝叶斯优化描述为“,一种针对嘈杂的黑盒函数的全局优化方法。应用于超参数优化,贝叶斯优化建立了从超参数值到在验证集上评估的目标的函数映射的概率模型。通过基于当前模型迭代地评估有希望的超参数配置,然后更新它,贝叶斯优化旨在收集尽可能多地揭示关于该函数的信息的观察值,特别是最优值的位置。它试图平衡勘探(结果最不确定的超参数)和开发(预期接近最优的超参数)。在实践中,与网格搜索和随机搜索相比,贝叶斯优化已被证明可以在更少的评估中获得更好的结果,因为它能够在实验运行之前对实验的质量进行推理。来源 : 维基

Scikit-Optimize (skopt)是一个优化库,它有一个贝叶斯优化实现。我建议使用这种实现,而不是尝试实现自己的解决方案——尽管如果您想更深入地了解贝叶斯优化是如何工作的,实现自己的解决方案也是有价值的。有关示例,请参见下面的代码。

使用 Python 的贝叶斯优化示例

网格搜索

网格搜索是我学习的第一个执行超参数优化的技术。它包括在学习算法中彻底搜索超参数空间的特定值的手动子集。执行网格搜索意味着必须有一个性能指标来指导我们的算法。

强烈建议您使用 Sklearn 实现,而不是从头开始实现网格搜索。有关示例,请参见下面的代码。

使用 Python 进行网格搜索的示例

随机搜索

随机搜索随机选择组合,而不是在网格搜索中穷举所有列出的组合。当少量的超参数对最终的模型性能有影响时,随机搜索可以胜过网格搜索——尽管它在上面的调查中评级很低,但随机搜索仍然是您的工具包中非常重要的技术。

像网格搜索一样,随机搜索也有一个 Scikit Learn 实现,比你自己的解决方案更好用。参见下面的代码。

使用 Python 的随机搜索示例

最后的想法

根据我的经验,在执行超参数优化时,很好地理解您正在使用的学习算法以及超参数如何影响它的行为会有所帮助。虽然这是最重要的任务之一,但我觉得超参数调优没有得到应有的重视,或者可能是我看得不够多。然而,这是你的项目中极其重要的一部分,不应该被忽视。

感谢阅读!

如果你喜欢这篇文章,请通过订阅我的免费 每周简讯与我联系。不要错过我写的关于人工智能、数据科学和自由职业的帖子。

相关文章

使用 AWS 和 Optuna 优化超参数运行时间和成本

原文:https://towardsdatascience.com/hyperparameter-optimization-run-time-and-cost-using-aws-and-optuna-40442a83db3?source=collection_archive---------38-----------------------

Unsplash 上由 Aron 视觉拍摄的照片

并行和分布式计算

了解如何最好地利用您的计算资源

大声喊出来Zeev Waks谁参与了这个项目和这篇文章的写作。

继我们关于顺序超参数优化的博客之后,我们在这里讨论运行时间和成本方面的工程考虑。我们专门研究了使用并行或分布式计算来加速参数搜索的方法。这一点很重要,因为超参数优化(HPO)通常是模型开发中最昂贵和最慢的方面之一。

我们使用 AWS 虚拟机(EC2 实例)作为硬件,使用 Optuna 作为软件框架,优化了我们的超参数。Optuna 是由 Preferred Networks,Inc .为 HPO 开发的一个相对较新的开源框架。

并行和分布式计算

并行和分布式计算都可以缩短运行时间。图片作者。

并行和分布式计算的目标是优化使用硬件资源来加速计算任务。虽然这两个术语听起来很相似,而且都是指同时运行多个进程,但是有一个重要的区别。

  • 并行计算是指在一台单机的不同处理器上同时运行多个任务。
  • 分布式计算是指在多个自主机器上同时运行任务的能力。

并行和分布式计算都支持扩展,以缩短运行时间。在并行模式下,通过纵向扩展来缩短运行时间,这意味着改进单个机器,例如增加更多的处理器或内存。对于分布式计算,横向扩展**指的是增加更多的机器,同样可以提高性能。

关于并行计算和分布式计算之间的区别和关系还有很多方面[1],但是我们不会在这篇博客中深入探讨。

用例

我们用例的细节可以在这里找到。我们使用了 9 个超参数,并在 18k 到 80k 的范围内(范围取决于超参数值)训练模型,每个样本包含大约 80 个特征。

下面的代码展示了在 Optuna 中定义并行或分布式计算是多么简单。

在我们的案例中,并行计算可以在两个地方使用,用于训练回归模型和在同一台机器上同时搜索多个超参数组合(即 Optuna trials )。相反,分布式计算在这里可以主要用于在多台机器上搜索不同的超参数组合。为了管理分发工作,我们在 AWS 帐户下使用了一个 Redis DB 端点(阅读这里关于其他存储选项)。

结果

我们使用各种机器和并行/分布式配置来测量运行时间和成本,以便更好地理解运行 HPO 搜索的最佳组合。

每项研究使用 100 次试验,比较 HPO 成本和运行时间。我们使用带有固定种子的 RandomSampler 来确保在相同的超参数组合上进行比较。-1 表示所有可用的处理器。例如 AWS us-east-1 上的价格。图片作者。

我们的两个模型库, Scikit-learn (我们使用了 RandomForestRegressor )和 XGBoost ,以及 Optuna ,都通过定义一个内置参数 n_jobs 来支持并行性。n _ jobs 的值表示并行运行的任务数量,其中-1 表示所有可用处理器的使用率。

在我们的案例中,就运行持续时间而言,最佳配置是 Optuna n_jobs=1 和 model n_jobs=-1 ,这意味着我们以并行方式训练模型,但没有使用并行方式来测试超参数组合。因为这种设置对于单台机器来说是最佳的,所以我们没有继续检查分布式运行的其他配置。

m5.24xlarge (96 个内核,374GB RAM) EC2 计算机的 CPU 利用率显示了出色的处理器利用率。作者图片

有趣的是,虽然 m5.24xlarge EC2 实例类型比 m5.4xlarge 实例大 6 倍,但它只提高了 40%的研究时间(有点令人失望)。然而,通过对两个较小的 m5.4x 大型实例使用分布式计算,我们都略微缩短了研究时间(43%比 40%),并且花费了大约 1/3 的成本。

好消息是我们可以添加更多的实例来提高运行时间。此外,其中一台机器空闲了大约 6 分钟,因为它被分配了一组运行时间更短的试验。在进行更多的试验后,这种差异可能会变得不那么有意义。

此外,Optuna 并行性使用的线程通常非常适合 I/O 绑定任务,但相比之下,对于 CPU 密集型任务(如训练模型)来说并不是最佳选择(已知问题)。点击阅读多线程和多重处理。为了解决这个问题,我们在同一台 m 5.24 x 大型机器上运行了两个不同的 Python 进程,并使用 Redis 同步了它们,但是这并没有改善我们的运行时间。

摘要

我们证明了通过使用 Optuna 进行超参数优化,横向扩展(即添加更多的机器)可以减少运行持续时间和成本,至少在我们的案例中,比纵向扩展更有效。

我们鼓励读者尝试不同的配置,因为在我们的情况下,最佳设置可能不是其他场景的理想配置。

是天际线 aihttp://skyline.ai的资深数据科学家,该公司打造的 AI 主谋解决 RE。

参考

[1] M. Raynal,并行计算与分布式计算:一个巨大的困惑?(立场文件)(2015)springer link

使用 Grid.ai 进行超参数优化,无需更改代码

原文:https://towardsdatascience.com/hyperparameter-optimization-with-grid-ai-and-no-code-change-b89218d4ff49?source=collection_archive---------28-----------------------

图片由米哈伊尔·尼洛夫派克斯拍摄

这篇文章介绍了使用 Grid.ai 平台的超参数扫描搜索,允许在多个 spot 实例上并行化和实时性能观察。

之前的一篇文章中,我们展示了如何将科学笔记本转换成一个标准的 python 包,以供分享。然后,我们演示了如何通过命令行界面(CLI)将普通 python 脚本转换为训练脚本,从而实现更快的超参数交互。

配置好 CLI 后,我们现在可以将不同的超参数(如学习率或模型架构)传递给我们的模型,而无需更改任何代码……但我们如何识别这些参数值的哪些组合会产生性能最佳的模型呢?

使用 Grid.ai 进行超参数优化

如何选择最优的超参数集是机器学习中最常见的问题之一。许多 Kaggle 大师声称,正确的参数值集是在排行榜上排名的模型和不相关的模型之间的差异。具有重要参数的简单模型可以从基本超参数优化中获得 5–15%的性能提升。

另一方面,对于大多数初学者来说,执行参数调整可能是一项费时费力的任务。一种常见但简单的超参数调整方法是顺序运行多个实验,并将配置值和结果写入 Excel 表格。

更高级的 Kagglers 可以使用简单的并行化超参数搜索,并使用 MLFlow权重&偏差、 Neptune.ai 等跟踪结果。然而,如果您采用这种方法,您需要在一台具有多个 GPU 的强大机器上进行训练,或者用几台机器创建和编排您的云。

注意如果你有自己强大的机器,还有几个其他的超参数搜索选项,比如 OptunaRay tune等。

完全公开——我目前在 Grid.ai
担任高级研究工程师。注意,您也可以使用其他替代方案来利用这些最佳实践,如 Kaggle 内核或 Colab,但 Grid.ai 是我的首选平台,因为它使我能够使用云轻松地扩展培训我的模型。

幸运的是, Grid Runs 支持对我们的代码进行快速超参数调优,而无需担心编排复杂的基础设施或向我们的代码添加外部库。网格运行自动收集日志和管理并行实验…不需要对我们的代码做任何更改!

创建数据存储

在大多数大型项目中,共享数据是快速实验的一个重要瓶颈,因为它需要安全的并行计算资源来访问。幸运的是,网格数据存储经过了优化,允许您的模型以最高速度进行训练,而无需承担技术债务或需要处理优化云存储的复杂性。此外,网格数据存储具有集成的数据集版本,可确保我们的超参数实验具有可比性和可再现性的机器学习!

之前,我们在网格交互会话中预处理/缩减了数据集。现在,我们将把这个数据集上传到新创建的数据存储区。从会话上传数据可确保更快的上传速度。稍后,我们将通过网格运行来访问该数据存储,以运行超参数搜索,从而从我们的模型中获得最佳性能。

grid datastore create \
    --name kaggle_plant-pathology \
    --source plant-pathology

有关数据存储的更多详细信息,请参见文档

创建/上传网格数据存储。

创建完成后,我们可以从 web UI 中快速检查所有数据存储库的一些基本信息,如大小或上次更新。

在 UI 中查看创建的数据存储。

超参数微调

现在,我们可以从上次培训脚本的地方开始。我们现在将展示如何使用三种不同的学习速率和三个 ResNet 模型主干的组合来运行 9 个实验。此外,您可以在命令行或 UI 中轻松扩展实验和超参数的数量,而无需更改任何代码。

以下步骤假设我们已经从 data science 内核创建了 GitHub 存储库。现在,我们可以链接我们想要运行超参数搜索的训练脚本。如果你还没有创建一个 GitHub 回购,请查看这篇文章,或者你可以跟随我冒昧为这篇文章准备的回购。

https://github.com/Borda/kaggle_plant-pathology

然后,我们选择想要使用的机器类型。在我们的例子中,我们需要一个 GPU 来训练我们的模型,所以我每次实验都选择了一个单 T4 ,使用点实例来显著降低成本。这 9 次实验(每次训练大约需要 30 分钟)花费了不到 1 美元的免费积分来调整一个可分级的模型。

使用网格运行创建网格搜索的过程。

为了准备我们的超参数搜索,我们需要做的就是用一个范围(列表、采样等)替换我们的单个 CLI 的参数值。)的 pythonic 式的价值观:

--model.model "['resnet18', 'resnet34', 'resnet50']" \
--model.lr "[0.0001, 0.0005, 0.001]" \
--data.base_path grid:kaggle_plant-pathology:1 \
--trainer.max_epochs 5

对于每个实验,我们从上一步中创建的数据存储中装载数据,因此不需要在本地下载数据,大大加快了训练时间。

实时监控训练并保存最佳模型

监控实验使您能够调试和终止不收敛的模型。这有助于降低成本并节省资源,这些资源可以再投资于训练更好的模型。

PyTorch Lightning 默认使用 TensorBoard 记录器,与 Grid.ai 平台原生集成。 TensorBoard 让我们可以毫不费力地监控和比较所有实验的结果。

浏览所有实验的汇总结果,以找到 F1 分数最高的模型。

PyTorch Lightning 默认提供自动检查点。当找到最佳实验时,我们可以打开它的 details 窗口并导航到 artifact 选项卡来下载保存的检查点,我们将在推理中使用它。

从一个特定的实验中下载艺术品。

在这篇文章中,我们讨论了对超参数搜索的需求,并且我们已经运行了 walked throw 网格,这简化了云中的微调。我们甚至可以在线监控我们的训练,并最终根据我们的选择终止一些默认配置。

在未来,我们将使用我们训练有素的模型,并展示如何准备离线运行的 Kaggle submission 内核,以便在比赛中进行评分。

敬请关注,关注我了解更多!

https://devblog.pytorchlightning.ai/best-practices-to-rank-on-kaggle-competition-with-pytorch-lightning-and-grid-ai-spot-instances-54aa5248aa8e

关于作者

Jirka boro vec已经在几家不同的 IT 公司从事机器学习和数据科学工作好几年了。特别是,他喜欢探索有趣的世界问题,并用最先进的技术解决它们。此外,他开发了几个开源 python 包,并积极参与其他知名项目。在 Grid.ai 工作,担任研究工程师,pytorchlightning . ai主要撰稿人。

超参数调整—始终调整您的模型

原文:https://towardsdatascience.com/hyperparameter-tuning-always-tune-your-models-7db7aeaf47e9?source=collection_archive---------16-----------------------

实践教程

不要放弃免费的性能提升。

西格蒙德Unsplash 上拍照

TLDR 概述

  • 网格搜索—穷举且计算量大,在超参数搜索空间受限时使用。
  • 随机搜索—与网格搜索相比,更大的搜索空间改进了模型,网格搜索是 scikit-learn 内置的定位方法。
  • 贝叶斯优化—改进了随机搜索和超参数解释的性能,尽可能使用。

什么是超参数调谐?

超参数调整是提高模型性能的一个重要方面。给定一个具有许多超参数的复杂模型,有效的超参数调整可以显著提高性能。例如,梯度增强分类器有许多不同的参数要微调,每个参数都会唯一地改变模型的性能。有些可能影响很小或没有影响,而另一些可能对模型的可行性至关重要。

最常见的方法是尝试几种用户定义的超参数组合,比较结果,并选择总体最佳表现者。这种方法有一些明显的缺点,因为基于初始选项的选择是有偏差的。虽然关于目标问题的先验知识可以为理想的选择提供一些指导,但是还有潜在的更好的选择没有被检查。网格搜索遵循这一基本方法,但即使有了先验知识,这也是不理想的。

履行

这篇文章的完整笔记可以在这里找到。

这些超参数搜索中的每一个都非常容易实现,所以您应该在模型优化过程中加入一个。对于我的例子,我使用乳腺癌数据集。首先,我加载数据、相关的库,初始化一些元参数,并拆分数据集。接下来,我创建一个小管道,运行每个搜索并打印出性能。

**import** **pandas** **as** **pd**
**from** **scipy.stats** **import** uniform, geom, loguniform, randint, expon
**from** **sklearn.ensemble** **import** GradientBoostingClassifier
**from** **sklearn.model_selection** **import** cross_val_score, GridSearchCV, train_test_split, RandomizedSearchCV
**from** **sklearn.metrics** **import** roc_auc_score
**from** **sklearn.pipeline** **import** make_pipeline, Pipeline
**from** **sklearn.datasets** **import** load_iris, load_boston, load_diabetes, load_digits, load_linnerud, load_wine, load_breast_cancerTEST_SIZE = 0.1 
RANDOM_STATE = 10  
data = load_breast_cancer() 
df = pd.DataFrame(data.data, columns=data.feature_names) df['target'] = data.target X = df.drop(['target'], axis=1) 
y = df['target'].astype(float) 
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=TEST_SIZE, random_state=RANDOM_STATE, stratify=y)

网格搜索与随机搜索

网格搜索

网格搜索是最常见的超参数选择技术之一。这种方法实际上是一种强力策略,只需为每个超参数配置创建和测试一个模型,这种方法受益于穷举搜索行为。此外,可以肯定的是,每个组合都经过了比较。

然而,应该清楚的是,使用全面搜索超参数是昂贵的。由于这些搜索处理组合的复杂性,必须测试的模型数量急剧增加,特别是当目标模型类型有许多参数要调整时。由于这种计算负担,当一些超参数的最佳选择已知时,网格搜索是最有效的。

随机搜索

随机搜索是网格搜索的常用替代方法。与对每个超参数配置的穷举搜索相反,随机搜索只对设定数量的样本运行。每个样本从可能的参数列表或参数分布中随机选择超参数。虽然与网格搜索相比,这种方法似乎不是最佳的,但在相同的计算量下,它表现得更好。

当存在许多可忽略的超参数时,该方法的好处是显而易见的。例如,在梯度增强模型中,用于具有少量特征的模型的特征选择可以是总特征的平方根或特征数量的对数。当特征的数量很小时,两个选择之间的差异是有限的。将参数的两种变体添加到搜索中会使网格搜索中的搜索空间加倍。相比之下,随机搜索将只包括所有样本中成比例的这些参数选择。包含可忽略参数变量的样本将揭示该参数的影响,并大大节省计算时间。

因此,随机搜索可以在更大的超参数空间上进行优化,其计算量与网格搜索相同。因此,与通过网格搜索优化的模型相比,随机搜索进一步提高了最优模型的性能。

此外,随机搜索比网格搜索还有一个好处。因为网格搜索使用超参数的离散选择来创建模型,所以错过不可忽略的超参数的最佳选择的概率增加了。相反,随机搜索可以从可能的超参数的连续或完全离散分布中选择配置。这种行为已被证明在识别最佳模型设置时更有效,尤其是当超参数的搜索空间很大时。

比较方法

各种方法之间的比较如下图所示。假设两个超参数需要调整,每个参数在每个配置下的模型真实性能以蓝色显示。应该清楚的是,网格搜索产生的模型可能会“错过”模型的最佳超参数配置。相反,随机搜索有效地忽略了第一个可忽略的超参数,并从第二个超参数中采样更多不同的值。因此,随机搜索可以找到更优的超参数选择。

搜索方法之间的差异(作者提供的照片)

实施搜索

网格搜索和随机搜索是标准 scikit-learn 包的一部分,可与 scikit-learn 生成的现有模型无缝协作。下面是使用网格搜索和随机搜索创建管道的大致设置。这个例子的模型是 GradientBoostingClassifier,但是这个模型是可以互换的。

要切换到另一个模型,请更新管道定义中的模型,并更新 hyper_parameter 字典中的参数名称和选择/分布。参数名称应带有前缀“ model__ ,以匹配管道中的名称“ model ”。这些名称可以根据需要进行更改。

网格搜索

N_JOBS = 1
K_FOLDS = 10
N_ITER_NO_CHANGE = 100
SCORING_METRIC = 'roc_auc'

*# Gradient Boosting Parameters*
hyper_parameters = {
        'model__n_estimators': [50, 150, 300],
        'model__learning_rate': [0.1, 0.03, 0.001],
        'model__max_depth': [3, 5, 8],
        'model__max_features': ['sqrt'], 
        'model__min_samples_split': [2],
        'model__n_iter_no_change': [N_ITER_NO_CHANGE], *# Note single elements should still be in a list*
        'model__random_state': [RANDOM_STATE],
        'model__min_samples_leaf': [2, 10]
}

*# Make pipeline - Add steps if needed, i.e. feature selection*
pipe = Pipeline(steps=[
    ('model', GradientBoostingClassifier())
])

*# 'n_iter' no longer needed as all combinations are checked*
search_space = GridSearchCV(
    pipe, hyper_parameters, 
    cv=K_FOLDS, scoring=SCORING_METRIC, n_jobs = N_JOBS, 
    return_train_score=**True**, verbose = 1
)
search_space.fit(X_train, y_train) 

y_pred = search_space.best_estimator_.predict(X_train)
y_pred_prob = search_space.best_estimator_.predict_proba(X_train)[:,1]
y_pred_test = search_space.best_estimator_.predict_proba(X_test)[:,1]

print( 
    'Best Training Score: ', search_space.cv_results_['mean_train_score'][search_space.best_index_], 
    '**\n**Best Test Score: ', search_space.best_score_,
    '**\n**Hold Out Test Score: ', roc_auc_score(y_test, y_pred_test)
)

然后是随机搜索的代码,请注意从参数列表选项到统计库中定义的分布的变化。

随机搜索

N_ITER = 54
N_JOBS = 1
K_FOLDS = 10
N_ITER_NO_CHANGE = 100
SCORING_METRIC = 'roc_auc'

hyper_parameters = {
        'model__n_estimators': randint(50,500),
        'model__learning_rate': loguniform(3e-4, 3e-1),
        'model__max_depth': randint(3,10),
        'model__max_features': ['sqrt'], 
        'model__min_samples_split': randint(2,20),
        'model__n_iter_no_change': [N_ITER_NO_CHANGE], *# Note single elements should still be in a list*
        'model__random_state': [RANDOM_STATE],
        'model__min_samples_leaf': randint(1,10)
}

pipe = Pipeline(steps=[
    ('model', GradientBoostingClassifier())
])

search_space = RandomizedSearchCV(
    pipe, hyper_parameters, 
    n_iter = N_ITER, cv=K_FOLDS, 
    scoring=SCORING_METRIC, n_jobs = N_JOBS, 
    return_train_score=**True**, verbose = 1
)
search_space.fit(X_train, y_train) 

y_pred = search_space.best_estimator_.predict(X_train)
y_pred_prob = search_space.best_estimator_.predict_proba(X_train)[:,1]
y_pred_test = search_space.best_estimator_.predict_proba(X_test)[:,1]

print( 
    'Best Training Score: ', search_space.cv_results_['mean_train_score'][search_space.best_index_], 
    '**\n**Best Test Score: ', search_space.best_score_,
    '**\n**Hold Out Test Score: ', roc_auc_score(y_test, y_pred_test)
)

贝叶斯搜索

随机搜索被证明比网格搜索更有效。然而,另一种方法证明可以找到更优的超参数选择。贝叶斯搜索是一种超参数选择技术,它对超参数搜索空间进行建模和优化。该建模使用高斯过程来完成,该高斯过程对从超参数空间产生的函数进行建模。

搜索过程如下。样本取自超参数空间,创建多个模型,测量模型的性能,并使用 argmax 函数进行优化,以确定最佳超参数配置。这个过程类似于随机搜索,增加的好处是模式被外推以找到更优的模型。此外,贝叶斯超参数搜索对每个超参数进行相互比较建模,这允许对模型的有效性进行更稳健的解释。

贝叶斯搜索与其他搜索

将贝叶斯超参数与网格搜索和随机搜索进行比较,您可以看到,贝叶斯搜索不仅随机采样类似于随机搜索,而且在许多样本之后,生成一个函数来对超参数空间进行建模,然后对其进行优化。这一过程会在图像中产生虚线,最佳点由小红星表示。请注意,这仍然不是函数的真正最佳超参数选择,但却提高了模型性能。

搜索方法之间的差异(作者提供的照片)

实现贝叶斯搜索

不幸的是,贝叶斯优化的代码不是标准 scikit-learn 包的一部分。然而,软件包 scikit-optimize 提供了一个与 scikit-learn 模型集成的贝叶斯超参数优化功能。该方法的代码遵循与网格和随机搜索相似的模式,但是参数分布的定义不同。

**from** **skopt** **import** BayesSearchCV
**from** **skopt.space** **import** Real, Categorical, Integer

N_ITER = 54
N_JOBS = 1
hyper_parameters = {
        'n_estimators': Integer(50, 300),
        'max_depth': Integer(3, 10),
        'min_samples_split': Integer(2, 300),
        'learning_rate': Real(3e-6, 3e-1,prior='log-uniform'),     
        'max_features': Categorical(['sqrt', **None**]),
}
search_space = BayesSearchCV(
    estimator=GradientBoostingClassifier(
        n_iter_no_change=N_ITER_NO_CHANGE, 
        random_state=RANDOM_STATE
    ),
    search_spaces=hyper_parameters,
    scoring=SCORING_METRIC,
    cv=K_FOLDS,
    n_iter=N_ITER,
    random_state=RANDOM_STATE,
    return_train_score=**True**,
    verbose = 1,
    n_jobs=N_JOBS
)
*# executes bayesian optimization*
_ = search_space.fit(X_train, y_train)

y_pred = search_space.best_estimator_.predict(X_train)
y_pred_prob = search_space.best_estimator_.predict_proba(X_train)[:,1]
y_pred_test = search_space.best_estimator_.predict_proba(X_test)[:,1]

*# model can be saved, used for predictions or scoring*
print( 
    'Best Training Score: ', search_space.cv_results_['mean_train_score'][search_space.best_index_], 
    '**\n**Best Test Score: ', search_space.best_score_,
    '**\n**Hold Out Test Score: ', roc_auc_score(y_test, y_pred_test)
)

理解贝叶斯搜索

此外,scikit-optimization 提供了可视化超参数优化函数的方法。这些图可以进一步指导优化过程。此外,可以查看紧急模式,例如识别可忽略的参数和有限的搜索空间。这些图用于进一步细化搜索空间,以创建一个更加优化的模型。

**import** **matplotlib.pyplot** **as** **plt**
**from** **skopt.plots** **import** plot_objective, plot_histogram

_ = plot_objective(search_space.optimizer_results_[0],
                   n_minimum_search=int(1e8))
plt.show()

每个超参数的贝叶斯优化 PDP 图(作者提供图片)

结论

如果您还没有使用超参数优化,并且您的模型有超参数,那么您应该使用超参数优化。然后,根据您的可用资源和包依赖项,您可以使用所描述的三种方法中的任何一种。

例如,贝叶斯优化非常适合快速找到好的超参数设置,而网格搜索可以在定义小搜索空间时进一步微调模型。一般来说,随机搜索是这两种方法之间的折中,您应该(至少)将这种超参数搜索整合到您现有的模型和管道中,以获得立竿见影的性能提升。

如果你有兴趣阅读关于新颖的数据科学工具和理解机器学习算法的文章,可以考虑在 Medium 上关注我。

如果你对我的写作感兴趣,想直接支持我,请通过以下链接订阅。这个链接确保我会收到你的会员费的一部分。

https://zjwarnes.medium.com/membership

超参数调谐:网格搜索和随机搜索

原文:https://towardsdatascience.com/hyperparameter-tuning-grid-search-and-random-search-caadb703c046?source=collection_archive---------26-----------------------

两种最常见的超参数调谐技术

作者图片

超参数调整是机器学习管道中最重要的部分之一。超参数值的错误选择可能导致错误的结果和性能差的模型。

有几种方法可以执行超参数调整。其中两种是网格搜索和随机搜索。

让我们看看它们是如何工作的。

超参数调谐的需要

超参数是模型参数,其值在训练之前设置。比如一个前馈神经网络的神经元个数就是一个超参数,因为我们在训练之前就设定好了。超参数的另一个例子是随机森林中的树木数量或套索回归的惩罚强度。它们都是在训练阶段之前设置的数字,它们的值会影响模型的行为。

我们为什么要调整模型的超参数?因为我们事先并不知道它们的最优值。具有不同超参数的模型实际上是不同的模型,因此它可能具有较低的性能。

在神经网络的情况下,神经元数量少会导致欠拟合,数量多会导致过拟合。在这两种情况下,模型都不好,所以我们需要找到导致最佳性能的中间神经元数量。

如果模型有几个超参数,我们需要在多维空间中寻找超参数值的最佳组合。这就是为什么超参数调整,即找到超参数的正确值的过程,是一项非常复杂和耗时的任务。

我们来看两个最重要的超参数调优算法,网格搜索和随机搜索。

网格搜索

网格搜索是最简单的超参数调整算法。基本上,我们将超参数的域划分成一个离散的网格。然后,我们尝试这个网格值的每个组合,使用交叉验证计算一些性能指标。交叉验证中最大化平均值的网格点是超参数值的最佳组合。

作者图片

网格搜索是一种覆盖所有组合的穷举算法,因此它实际上可以找到域中的最佳点。最大的缺点是它非常慢。检查空间的每一个组合需要大量的时间,有时这是不可行的。别忘了网格中的每个点都需要 k 重交叉验证,这需要 k 个训练步骤。因此,以这种方式调整模型的超参数可能相当复杂和昂贵。然而,如果我们寻找超参数值的最佳组合,网格搜索是一个非常好的想法。

随机搜索

随机搜索类似于网格搜索,但它不是使用网格中的所有点,而是只测试这些点的随机选择的子集。这个子集越小,优化速度越快,但精度越低。这个数据集越大,优化就越精确,但越接近网格搜索。

作者图片

当您有几个带有精细网格值的超参数时,随机搜索是一个非常有用的选项。使用由 5-100 个随机选择的点组成的子集,我们能够得到一组相当好的超参数值。它不太可能是最好的一点,但它仍然可以是一组很好的值,为我们提供一个很好的模型。

Python 中的一个例子

让我们看看如何使用 scikit-learn 在 Python 中实现这些算法。在本例中,我们将对仅使用 n_estimators 和 max_features 超参数的糖尿病数据集优化随机森林回归器。你可以在我的 GitHub 这里找到全部代码。

首先,让我们导入一些有用的库:

from sklearn.datasets import load_diabetes 
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV, train_test_split 
from sklearn.ensemble import RandomForestRegressor 
import numpy as np

然后,让我们导入数据集,并将其分成训练集和测试集。所有的计算都将在训练集上完成。

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

现在,让我们开始网格搜索。网格搜索是使用 scikit-learn 的 GridSearchCV 对象完成的。当我们寻找超参数值的最佳组合时,它将我们要优化的估计量、交叉验证中的折叠数以及要考虑的评分标准作为输入。最后一个参数是我们要研究的每个超参数的值列表。GridSearchCV 将为我们创建所有的组合。

假设我们希望将 n_estimators 超参数从 5 扩展到 100,步长为 5,将 max_features 超参数从 0.1 扩展到 1.0,步长为 0.05。我们正在寻找这些范围的组合,使 5 倍交叉验证的平均值最大化。下面是我们需要编写的代码:

grid_search = GridSearchCV(RandomForestRegressor(random_state=0), 
{ 'n_estimators':np.arange(5,100,5), 'max_features':np.arange(0.1,1.0,0.05), }
,cv=5, scoring="r2",verbose=1,n_jobs=-1 ) grid_search.fit(X_train,y_train)

一旦我们适合网格搜索,Python 将跨越我们提供的列表中的所有值的组合,并挑选得分最高的一个。这个过程可能需要一段时间,因为我们的网格很大。

两分钟后,我们得到:

正如我们从第一行看到的,网格搜索适合 1710 次。

最后,我们可以看看找到的最佳组合:

最好的成绩是:

现在,让我们看看随机搜索会发生什么。代码完全相同,但是现在我们必须定义要使用的迭代次数。我们将使用 50 次迭代。最后,我们将添加一个随机状态,以使结果可重复。

random_search = RandomizedSearchCV(RandomForestRegressor(random_state=0), 
{ 'n_estimators':np.arange(5,100,5), 'max_features':np.arange(0.1,1.0,0.05), }
,cv=5, scoring="r2",verbose=1,n_jobs=-1, n_iter=50, random_state = 0 ) random_search.fit(X_train,y_train)

现在我们只进行 250 次拟合(50 次迭代,每次 5 次拟合)。这个过程只需要 20 秒钟就能得出结果。

以下是最佳组合:

它的最好成绩是:

正如我们所看到的,结果与网格搜索非常相似,但随机搜索使我们节省了 83%的计算时间。

结论

我认为,在这两种算法中,随机搜索是非常有用的,因为它更快,而且由于它不会到达网格中的最佳点,所以它避免了过度拟合,并且更能够一般化。然而,对于小网格(即少于 200 点),如果训练阶段不太慢,我建议使用网格搜索。对于一般情况,随机搜索可以提高训练速度,并为我们的模型找到一个相当好的解决方案。

如果你对超参数调优感兴趣,加入我关于 Python 中监督机器学习的在线课程。

原载于 2021 年 5 月 19 日https://www.yourdatateacher.com/2021/05/19/hyperparameter-tuning-grid-search-and-random-search/

Lasso 和 Ridge 回归中的超参数调整

原文:https://towardsdatascience.com/hyperparameter-tuning-in-lasso-and-ridge-regressions-70a4b158ae6d?source=collection_archive---------4-----------------------

我用来优化正则化参数的方法。scikit-learn 的 Python 指南。

作者图片

在这篇文章中,我们首先来看看套索和岭回归时的一些常见错误,然后我将描述我通常采取的调整超参数的步骤。代码是用 Python 写的,我们主要依靠 scikit-learn 。本指南主要关注套索的例子,但基本理论与山脊非常相似。

起初,我并没有真正意识到需要另一个关于这个主题的指南——毕竟这是一个非常基本的概念。然而,当我最近想证实一些事情时,我意识到,很多指南要么非常学术性,要么太简单,要么就是完全错误。一个非常常见的混淆来源是,在 sklearn 中,总是有十几种不同的方法来计算同一个东西。

所以,事不宜迟,这里是我对这个话题的 2 美分。

快速理论背景

Lasso 和 Ridge 都是正则化方法,它们旨在通过引入惩罚因子来正则化复杂模型。它们在减少过度拟合、处理多重共线性或自动特征工程方面非常出色。这可能看起来违反直觉,但通过使模型更努力地解释训练数据,我们可以更好地理解底层结构,从而更好地概括和更好地拟合测试数据。

线性回归

根据 sklearn 的公式,这是在线性回归模型中最小化的表达式,即所谓的普通最小二乘法:

线性回归公式

其中 X 矩阵为自变量, w 为权重系数, y 为因变量。

山脉

回归采用该表达式,并在系数平方的末尾添加一个惩罚因子:

岭公式

这里,α是正则化参数,这是我们要优化的。该模型惩罚较大的系数,并试图更均匀地分配权重。通俗地说,这就是山脊模型的作用:

X1,我们看到你做得很好,如果不是因为处罚因素,我们会给你很大的压力。然而,X2 只是比你稍微差一点,如果我们在你们两个之间分配权重,我们会得到更低的惩罚,因此总得分会更高。

套索

Lasso 做了类似的事情,但是使用权重的绝对值之和(l1 范数)作为惩罚。

注意:在 sklearn 公式中还有一个 *n_samples* ,它是观测值的个数,对于同一个 X 和 y,它应该是不变的,我没有找到为什么会有那个的解释,也许是为了比较不同的模型,如果你有更好的想法,请告诉我。

套索公式

Lasso 将开始降低不太重要的变量的系数,也有可能将系数降低到 0。通俗地说:

X1,你对总分的最小贡献被记录下来。然而,根据最新的处罚分数,我们将不得不让你退出回归。把你留在身边不值得。

弹性网

值得注意的是,你还可以用一个弹性网将两种惩罚结合在同一个模型中。你需要优化两个超参数。在本指南中,我们不打算讨论这个选项。

使用的库

如果您想遵循代码,这里列出了您需要的所有库:

**import** pandas **as** pd
**import** numpy **as** np
**import** matplotlib.pyplot **as** plt
**import** seaborn **as** sns
**from** sklearn.metrics **import** \
    r2_score, get_scorer
**from** sklearn.linear_model **import** \
    Lasso, Ridge, LassoCV,LinearRegression
**from** sklearn.preprocessing **import** \
    StandardScaler, PolynomialFeatures
**from** sklearn.model_selection **import \
   ** KFold, RepeatedKFold, GridSearchCV, \
    cross_validate, train_test_split

一般提示

在这一节中,我们将讨论一些通用技巧和常见错误,以避免正则化回归。示例使用了波士顿住房数据,您可以从 Kaggle 下载。

处理数据:

column_names = \
    ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE',\
     'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
data = pd.read_csv("../datasets/housing.csv", \
    header=None, delimiter=r"\s+", names=column_names)
y = data['MEDV']
X = data.drop(['MEDV'], axis = 1)

提示 1:调整独立变量

正如标题所暗示的:这绝对是调整你的变量以进行正则化回归的必要条件。(正如我们所知,像缩放这样的线性变换对普通线性回归的预测没有影响。)如果你仔细看看这些公式,你就会很清楚为什么你必须为正则化回归进行缩放:如果你的一个变量恰好在一个非常小的范围内,它的系数将会很大,因此,它将会由于惩罚而受到更多的惩罚。反之亦然,一个大范围的变量将得到小的系数,受惩罚的影响较小。套索和山脊都是如此。

假设你做了如下的事情。

(再次说明,这个例子是没有缩放的,不会产生正确的结果,不要这样做。另外,请注意,除了缩放之外,还有其他问题,我们将很快返回。)

# don't copy!!!cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
lasso_alphas = np.linspace(0, 0.2, 21)lasso = Lasso()
grid = dict()
grid['alpha'] = lasso_alphas
gscv = GridSearchCV( \
    lasso, grid, scoring='neg_mean_absolute_error', \
    cv=cv, n_jobs=-1)
results = gscv.fit(X, y)print('MAE: %.5f' % results.best_score_)
print('Config: %s' % results.best_params_)

这将是结果:

MAE: -3.37896
Config: {'alpha': 0.01}

然而,如果你事先调整你的X变量,你通常会得到一个更好的分数。为了缩放,我们可以使用 sklearn 的 StandardScaler 。这种方法将变量集中在 0 附近,使标准偏差等于 1。

sc = StandardScaler()X_scaled = sc.fit_transform(X)
X_scaled = pd.DataFrame(data = X_scaled, columns = X.columns)

如果我们在上面的代码块中用X_scaled替换X,我们会得到:

MAE: -3.35080
Config: {'alpha': 0.08}

是的,没有太大的改善,但这是由于我们稍后将看到的一些因素。最重要的是,波士顿住房数据是线性回归的一个非常好的定制玩具例子,所以我们不能提高预测那么多。

总结:正则化前使用 StandardScaler 对自变量进行缩放。无需调整因变量。

提示№2。:当 Alpha 等于零时…

如果在“套索”和“山脊”中为 alpha 参数选择 0,则基本上是在拟合线性回归,因为在公式的 OLS 部分没有应用惩罚。

由于计算的复杂性,sklearn 文档实际上不鼓励使用 alpha = 0 参数运行这些模型。我还没有遇到过它引起任何计算问题的情况,它总是给出与线性回归模型相同的结果。

总结:挑 alpha = 0 没有意义,那就是简单的线性回归。

提示№3:扫完一次不要停下来

在上面的例子中,我们遍历了一组 alphass,尝试了所有的 alpha,并选择了得分最高的一个。然而,就像通常使用 GridSearchCV 时一样,建议进行多次扫描。找到 alpha 值最高的区域,然后进行更细致的检查。

根据我的经验,尤其是 Lasso,选择最低的非零参数是一个常见的错误,而实际上最佳参数是一个小得多的数字。请看后半部分的例子。

注:当然,我们永远不会用网格搜索法找到实际的最优数,但我们可以足够接近。

你也可以看到结果。这是未缩放版本的样子:

住房数据,MAE,未按比例

对于每个 alpha,GridSearchCV 都符合一个模型,我们选择了验证数据得分最高的 alpha(例如,重复文件夹中测试折叠的平均得分)。在这个例子中,你可以看到在 0 和 0.01 之间可能没有一个疯狂的尖峰。当然,这仍然是不正确的,因为我们没有扩展。

这是缩放版本的图:

住房数据,MAE,按比例

再一次,它看起来很好,在 0.07 和 0.09 之间可能没有什么奇怪的事情发生。

总结:情节是你的朋友,观察阿尔法曲线。确保你选择的阿尔法在一个好的“曲线”区域。

提示№4:仔细考虑你的评分方法

你可能会尝试用不同的方法来检查你的结果。如前所述,sklearn 通常有一堆不同的方法来计算同一个东西。例如,有一种 LassoCV 方法将 Lasso 和 GridSearchCV 合二为一。

您可以尝试这样的方法来获得最佳 alpha(在示例中不再使用未缩放的版本):

lasso = LassoCV(alphas=lasso_alphas, cv=cv, n_jobs=-1)
lasso.fit(X_scaled, y)
print('alpha: %.2f' % lasso.alpha_)

这将返回:

alpha: 0.03

等等,这不是上面那个 0.08 的阿尔法值吗?是的。差异的原因是什么?LassoCV 使用 R 分数,您不能更改它,而在前面,我们在 GridSearchCV 对象中指定了 MAE(嗯,减去 MAE,但这只是为了最大化并保持一致)。这是我警告过你不要复制的代码:

scoring='neg_mean_absolute_error'

看到了吧,问题是,sklearn 有几十种评分方法,看看列表。你当然可以选择比如说 max_error 来衡量你的模型的性能。但是,该模型针对平方差进行了优化。我认为使用任何从平方差得到的东西都更加一致。毕竟 LassoCV 用的是 R,所以也许那是个征兆?

这整个“在一个基础上优化,然后在另一个基础上比较性能”实际上在上面的图中非常明显。注意绿线在一段时间内是如何增加的。那是训练分数。正常情况下,在我们施加惩罚因子后,它应该不会表现得更好。

通常,这是你会看到的曲线形状。训练数据得分立即下降,验证数据得分上升一段时间,然后下降:

住房数据,R,按比例

总结:使用 R 或其他基于方差的模型作为回归的主要评分。

我的方法

在本节中,我将向大家介绍我用来准备数据和拟合正则化回归的方法。

准备数据

在得到 Xy 之前,我不会详述数据。我使用这个美国县国民健康排名数据集合中的一个版本来生成下面的结果,但是对于这个例子来说这真的无关紧要。

所以,假设你有一个漂亮干净的 Xy ,下一步是留出一个测试数据集,使用方便的 train_test_split 。如果您想使结果可重复,选择任意数字作为my_random_state

X_train , X_test, y_train, y_test = train_test_split(
    X, y, test_size=1000, random_state=my_random_state)

下一步是包含多项式特征。我们将结果保存在poly对象中,这很重要,我们稍后会用到它。

poly = PolynomialFeatures(
    degree = 2, include_bias = False, interaction_only = False)

这将产生变量的所有二次多项式组合。需要注意的是,我们将include_bias设置为False。这是因为我们不需要截距列,回归模型本身将包含一个截距列。

这就是我们如何转换和重命名 X 的方法。它假设您将 X 保存在 pandas 数据帧中,并且需要做一些调整来保持列名可用。如果你不想要名字,你只需要第一行。

X_train_poly = poly.fit_transform(X_train)
polynomial_column_names = \
    poly.get_feature_names(input_features = X_train.columns)
X_train_poly = \
    pd.DataFrame(data = X_train_poly, 
        columns = polynomial_column_names )X_train_poly.columns = X_train_poly.columns.str.replace(' ', '_')
X_train_poly.columns = X_train_poly.columns.str.replace('^', '_')

完成这一步后,下一步就是扩展。既然我们引入了多项式,这一点就更重要了,幅值将是无标度的。

sc = StandardScaler()X_train_poly_scaled = sc.fit_transform(X_train_poly)
X_train_poly_scaled = pd.DataFrame( \
        data = X_train_poly_scaled, columns = X_train_poly.columns)

棘手的部分来了。如果我们想要使用测试数据集,我们需要应用相同的步骤。

但是,我们不需要再次调整对象。嗯,和poly没关系,但是对于sc,我们想保留我们以前拟合X_train_poly的方法。是的,这意味着测试数据不会完全标准化,这没关系。所以不用fit_transform,我们用transform

X_test_poly = poly.transform(X_test)
X_test_poly_scaled = sc.transform(X_test_poly)

功能

您可能想知道如何生成我们上面使用的图。我使用了两个函数,基于上面列出的库。第一个函数绘制一个图:

第二个基本上是一个网格搜索,有一些额外的东西:它也运行测试分数,当然保存情节。

我不想在这里赘述,我认为这是不言自明的,我们稍后会看到如何调用它的例子。

有一件事,我认为很酷:sklearn 有一个 get_scorer 函数,它基于它的 sklearn 字符串代码返回一个 scorer 对象。例如:

scorer = get_scorer('r2')
scorer(model, X_test, y_test)

现在我们有了一个额外的方法来计算同样的事情。

微调

一旦这个过程像这样建立起来,我们需要做的就是运行不同 alpha 数组的函数。

这个过程中有趣的一点是,我们还绘制了测试分数:

  1. 取训练数据集和一个 alpha
  2. 做交叉验证,保存训练和验证分数;
  3. 假设这是我们选择的 alpha,并在整个训练数据上拟合一个没有交叉验证的模型;
  4. 计算该模型将在测试数据上获得的分数,并保存测试分数。

这不是你在“现实生活”中会做的事情(除非你做 Kaggle 比赛),因为现在有可能优化你的测试数据集。我们在此仅包括它来说明模型性能。红线是不同阿尔法的测试分数。

我们还需要一个交叉验证对象,这里没有一个好的答案,这是一个选项:

cv = KFold(n_splits=5, shuffle=True, random_state=my_random_state)

为了说明我对多步参数搜索的重要性的观点,假设我们想要检查这些 alphas:

lasso_alphas = np.linspace(0, 0.02, 11)

运行该函数后:

chosen_alpha, max_validation_score, test_score_at_chosen_alpha = \
    regmodel_param_test(
        lasso_alphas, X_train_poly_scaled, y_train, 
        cv, scoring = 'r2', model_name = 'LASSO', 
        X_test = X_test_poly_scaled, y_test = y_test, 
        draw_plot = True, filename = 'lasso_wide_search')print("Chosen alpha: %.5f" % \
    chosen_alpha)
print("Validation score: %.5f" % \
    max_validation_score)
print("Test score at chosen alpha: %.5f" % \
    test_score_at_chosen_alpha)

结果是:

套索广泛搜索

Chosen alpha: 0.00200
Validation score: 0.82310
Test score at chosen alpha: 0.80673

这是否意味着我们找到了最优α?你可能会看着图,看到漂亮的尖钉,决定这是足够高的。不完全是。如果我们在更精细的层次上运行它:

lasso_alphas = np.linspace(0, 0.002, 11)

这是结果,请注意 0.02,最右边的点是我们在前面的图表中的峰值:

套索窄搜索

Chosen alpha: 0.00060
Validation score: 0.83483
Test score at chosen alpha: 0.82326

如果我们早一点停止,我们会选择一个导致总体测试 R 低 2%的 alpha,我认为这是相当重要的。

在我忘记之前…山脊!

对了,帖子的标题里有脊,除了理论介绍,我们还没讨论。

原因很简单:它的工作方式和 Lasso 完全一样,你可能只是想选择不同的 alpha 参数,然后在model_name参数中传递‘Ridge’。Ridge 也有同样的问题(我不包括我们搜索 alphas 范围来检查的部分):

岭窄搜索

你会注意到,我们基于蓝线选择的点似乎不再是红线的最佳点。是的,这是真的,但我认为这是一个巧合,它在套索模型中表现得如此之好。

摘要

所以你有它,这就是我如何为套索和山脊做超参数调整。我希望你觉得有帮助,要点再说一遍:

  • 记得缩放你的变量;
  • α= 0 只是线性回归;
  • 当搜索最佳参数时,执行多个步骤;
  • 使用基于平方差的分数来衡量绩效。

Python 中超参数调优

原文:https://towardsdatascience.com/hyperparameter-tuning-in-python-21a76794a1f7?source=collection_archive---------0-----------------------

调整机器学习中超参数的技巧和窍门,有助于提高模型精度

阿菲夫·库苏马在 Unsplash 上拍摄的照片

当我还是机器学习的新手时,超参数调整曾经是我的一个挑战。我总是讨厌我的项目中的超参数调整部分,通常会在尝试了几个模型并手动选择所有模型中精度最高的一个后就离开它们。但是现在我的概念已经很清楚了,我给你这篇文章是为了让任何新手在我当前项目的超参数被调整的时候都很容易。

让我们从参数和超参数之间的区别开始,了解这一点非常重要。参数是在训练过程中学习到的模型组件,我们永远无法手动设置。模型以随机参数值开始训练过程,并在整个过程中调整它们。鉴于,超参数是您在模型训练前设置的组件。超参数的值可能会提高或降低模型的精度。

机器学习中超参数调优的需求是什么?

机器学习模型不够智能,无法知道什么样的超参数会导致给定数据集的最高可能精度。然而,设置正确的超参数值可以构建高度精确的模型,因此我们允许我们的模型在训练过程中尝试不同的超参数组合,并使用最佳超参数值组合进行预测。随机森林分类器中的一些超参数是 n_estimators(森林中树木的总数)、max_depth(森林中每棵树的深度)和 criterion(在每棵树中进行分割的方法)。n_estimators 设置为 1 或 2 是没有意义的,因为一个森林必须有更多的树,但是我们如何知道多少树会产生最好的结果呢?为此,我们尝试不同的值,如[100,200,300]。该模型将尝试所有三个给定值,我们可以很容易地确定森林中的最佳树木数量。

Python 中超参数调优

python 中有三种超参数调优方法,分别是网格搜索、随机搜索和知情搜索。下面就详细说说吧。

网格搜索

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

网格是由相交的线组成的网络,形成一组正方形或长方形,如上图所示。在网格搜索中,网格中的每个方块都有超参数的组合,模型必须在每个组合上训练自己。为了更清楚地理解,假设我们想要用下面的一组超参数来训练一个随机森林分类器。

n _ 估计值:[100,150,200]

最大深度:[20,30,40]

看看这些超参数值构成的网格。我们的模型在 n 估计量和最大深度的每个组合上运行训练过程

作者创建的超参数网格的表示

网格搜索在 Python 中的实现

Python 中的 Scikit-learn 库为我们提供了一种简单的方法,只需几行代码就可以实现网格搜索。看看下面的例子

在第 1 行和第 2 行,我们从 sklearn.model_selection 导入 GridSearchCV,并定义我们想要对其执行超参数调优的模型。在第 3 行中,超参数值被定义为一个字典,其中键是超参数名称和一个包含我们想要尝试的超参数值的值列表。

在第 4 行中,GridSearchCV 被定义为 grid_lr,其中 estimator 是我们想要使用的机器学习模型,它是第 2 行中定义为模型的逻辑回归。因此,estimator 等于 model,param_grid 等于我们在第 3 行中定义的 grid_vals,scoring 等于 accuracy,这意味着我们希望使用 accuracy 作为模型的评估技术,cv 设置为 6,意味着我们希望模型经历 6 次交叉验证,refit 参数设置为 True,以便我们可以轻松地拟合和进行预测。

在第 9 行,我们将 grid_lr 拟合到我们的训练数据集,在第 10 行,我们使用具有最佳超参数值的模型,使用 grid_lr.best_estimator_ 对测试数据集进行预测。

网格搜索的利弊

网格搜索很容易实现,可以在网格中找到最佳模型。然而,当我们添加新的超参数值时,随着模型的数量继续增加,这在计算上是昂贵的。

随机搜索

像网格搜索一样,我们仍然在随机搜索中设置想要调优的超参数值。然而,该模型并不训练超参数的每个组合,而是随机选择它们。我们必须定义想要从网格中选择的样本数量。

Python 中随机搜索的实现

在第 1 行和第 2 行中,我们导入了随机搜索并定义了我们的模型,在本例中使用了随机森林。在第 3 行,我们定义了想要检查的超参数值。

在第 5 行中,RandomizedSearchCV 被定义为 random_rf,其中 estimator 等于第 2 行中定义为 model 的 RandomForestClassifier。Param_distributions(与网格搜索中的 param_grid 相同)等于我们在第 3 行中定义的 param_vals,n_iter 指的是我们希望从所有设置为 10 的超参数组合中抽取的样本数,scoring 等于 accuracy,这意味着我们希望使用 accuracy 作为我们模型的评估技术,cv 设置为 5,这意味着我们希望模型经历 5 次交叉验证, refit 参数设置为 True,这样我们就可以很容易地进行拟合和预测,n_jobs 等于-1 意味着我们希望使用所有可用的资源来进行这种随机搜索。

在第 11 行和第 12 行,我们将 random_rf 拟合到我们的训练数据集,并使用使用 random_rf.best_estimator_ 的最佳模型对测试数据集进行预测。

请注意,总迭代次数等于 n_iter * cv,在我们的示例中为 50,因为每次交叉验证将从所有超参数组合中抽取 10 个样本。

随机搜索的利弊

随机搜索在计算上更便宜。但是,不能保证从样本空间中找到最好的分数。

知情搜索

知情搜索是我最喜欢的超参数调整方法,因为它利用了网格和随机搜索的优点。但是,它也有自己的缺点。与网格和随机搜索不同,知情搜索通过以下过程从以前的迭代中学习

  1. 随机搜索
  2. 寻找得分高的区域
  3. 在较小的区域内运行网格搜索
  4. 继续,直到获得最优解

遗传算法是一种基于现实世界遗传学概念的通知超参数调整方法。我们首先创建一些模型,从中挑选最好的,创建与最好的模型相似的新模型,并添加一些随机性,直到我们达到我们的目标。

遗传算法在 Python 中的实现

我们在这里使用的库是 tpot,它有 generation(运行训练的迭代次数)、population_size(每次迭代后要保留的模型数量)和 subject _ size(每次迭代中要生成的模型数量)作为关键参数。看看下面的例子

在第 1 行,我们导入了 TPOTClassifier。在第 2 行,我们将分类器定义为 tpot_clf。Generations、population_size 和 off_spring_size 设置为 100。Verbose = 2 将让我们看到每一次生成(迭代)的输出,cv 设置为 6,这意味着我们希望为每次迭代运行 6 次交叉验证。

在第 6 行和第 7 行,我们将 tpot_clf 训练到我们的训练集,并在测试集上进行预测。

注意,我们在这里没有定义任何模型,因为 TPOTClassifier 负责为我们的数据集选择模型。

遗传算法的利弊

如上所述,它利用了网格和随机搜索的优点。遗传算法从以前的迭代中学习,tpot 库负责估计最佳超参数值和选择最佳模型。然而,它计算量大且耗时。

结论

在本文中,我们使用 Python 研究了三种超参数调优技术。网格搜索、随机搜索和知情搜索这三种方法都有各自的优点和缺点,因此我们需要根据我们的需求来选择最适合我们问题的技术。

我希望这篇文章能帮助你在更短的时间内提高你的机器学习模型的准确性。

如果你喜欢这篇文章,请提供你的反馈并分享。感谢您的阅读!

参考

https://camp . data camp . com/courses/hyperparameter-tuning-in-python

基于 Optuna 和 PyTorch 的神经网络超参数调整

原文:https://towardsdatascience.com/hyperparameter-tuning-of-neural-networks-with-optuna-and-pytorch-22e179efc837?source=collection_archive---------2-----------------------

如何在 Optuna 帮助下为我们的用例找到完美的神经网络模型

Unsplash 上的 Feelfarbig 杂志拍摄的照片

开发正确的神经网络模型可能非常耗时。

您可能知道,神经网络模型中有许多超参数,我们需要调整它们来获得完美的拟合模型,例如学习率、优化器、批量大小、层中的单元数量、激活函数、辍学率,等等。

问题是,我们事先不知道最适合我们模型的超参数值的组合。

当然,我们可以使用任何超参数的默认值,然后查看模型的性能有多好,然后逐一迭代调整每个超参数的值,以找到最佳组合。

然而,由于以下原因,这显然非常耗时,并且不是非常有效的方法:

  • 您需要监控并记录您已经手动尝试过的超参数组合。
  • 随着搜索空间的扩大,你很有可能需要进行数百甚至数千次试验,才能得出最佳模型。

为了解决这些问题,我们可以用 Optuna 调整神经网络模型的超参数。

什么是 Optuna?

Optuna 是一个 python 库,它使我们能够自动调整我们的机器学习模型。

你基本上可以将 Optuna 与几乎所有可用的机器学习框架一起使用:TensorFlow、PyTorch、LightGBM、XGBoost、CatBoost、sklearn、FastAI 等。

当然,有很多 Python 库可以帮助我们自动调整机器学习模型的超参数。然而,有几个特性使 Optuna 从其他超参数调优库中脱颖而出,我们将在后面讨论。

在本文中,我们将使用 Optuna 来调整 PyTorch 中神经网络模型的超参数。因此,让我们先简单介绍一下我们将在本文中使用的数据集以及获取该数据集的代码。

关于数据集

如果你想跟进,你可以下载我们将在这篇关于 Kaggle 的文章中使用的数据集。这个数据集是根据开放数据库许可证(ODbL)许可的,这意味着只要我们引用官方数据源,我们就可以将数据用于我们的目的。

https://www.kaggle.com/fedesoriano/heart-failure-prediction

我们的机器学习模型的目标是在考虑每个患者的年龄、性别、胆固醇水平等的情况下,预测患者是否患有心脏病。

数据集本身结合了连续特征和分类特征。我们需要将所有分类特征转换成它们的独热编码表示。

接下来,让我们用 PyTorch 创建一个简单的数据生成器类,在模型训练期间批量获取这个数据集作为神经网络模型的输入。

既然我们已经定义了生成数据的代码,我们就可以用 Optuna 来调优神经网络模型了!作为第一步,让我们了解一下如何使用 Optuna。

Optuna 入门

要使用 Optuna,请确保首先通过 pip 安装它:

pip install optuna

每个 Optuna 超参数调整会话称为研究。我们通过调用create_study方法来实例化一个学习会话。我们可以将几个重要的参数传递给这个方法,如下所示。

如你所见,我们将变量directionsampler作为参数传递给create_study方法。

方向

direction值可以设置为maximizeminimize,这取决于我们超参数调整的最终目标。

  • 如果目标是通过准确性、F1 分数、精确度或召回率等指标来提高绩效,则将其设置为maximize
  • 如果目标是减少损失函数,如对数损失、MSE、RMSE 等,则将其设置为minimize

取样器

sampler value 表示您希望 Optuna 实现哪个采样器方法。有几个采样器选项可供您选择,例如:

  • GridSampler:基于定义的搜索空间中的每个组合来选择超参数值的集合。
  • RandomSampler:超参数值的集合是从定义的搜索空间中随机选择的。
  • TPESampler:这是我们使用 Optuna 时的默认sampler。它基于贝叶斯超参数优化,这是一种有效的超参数调整方法。它将像随机采样器一样开始,但该采样器记录了一组超参数值的历史和来自过去试验的相应目标值。然后,它将基于具有来自过去试验的有希望的客观值的集合,为下一次试验建议一组超参数值。

接下来,我们可以在学习中调用optimize方法,并将我们的objective函数作为参数之一传递。

上面的n_trials参数表示您希望 Optuna 执行的研究中的试验次数。

到目前为止,我们还没有创建objective 函数。因此,让我们通过首先定义搜索空间来创建我们的objective函数。

搜索空间定义

在每个超参数调优会话中,我们需要为采样器定义一个搜索空间。搜索空间是采样器从超参数中应该考虑的值的范围。

例如,假设我们想要调整三个超参数:学习率、层的单元数和神经网络模型的优化器。然后,我们可以如下定义搜索空间:

objective函数中,我们传递一个名为trial的参数,它来自 Optuna 的Trial类。这个类使 Optuna 能够记录一组选定的超参数值,并记录我们的objective函数在每次试验中的值(在我们的例子中是精度)。

从上面可以看到,我们将每个超参数的搜索空间定义为一个名为params的字典。对于每个超参数,我们用suggest_*方法定义搜索空间的范围(最小值和最大值)。

根据超参数的数据类型,suggest_*方法有几个扩展:

  • suggest_int:如果您的超参数接受整数类型的数值范围。
  • suggest_categorical:如果您的超参数接受分类值的选择。
  • suggest_uniform:如果您的超参数接受一个数值范围,并且您希望对每个值进行均等采样。
  • suggest_loguniform:如果您的超参数接受一个数值范围,并且您希望在对数域中对每个值进行均等采样。
  • suggest_discrete_uniform:如果您的超参数接受特定区间内的数值范围,并且您希望对每个数值进行均等采样。
  • suggest_float:如果您的超参数接受 float 类型的数值范围。这是suggest_uniformsuggest_loguniformsuggest_discrete_uniform的包装方法

建立 PyTorch 模型,训练循环,评估目标函数

现在我们可以使用保存在params字典中的所选超参数值来构建 PyTorch 模型。接下来,我们将训练模型并评估我们的目标函数,在我们的情况下是准确性。

运行超参数调整

我们已经创建了我们的目标函数,我们已经定义了搜索空间,我们已经建立了模型和训练循环,现在我们准备使用 Optuna 运行超参数调优。

要运行超参数调优,我们需要实例化一个study会话,调用optimize方法,并将我们的objective函数作为参数传递。我们已经在上面的“Optuna入门”一节中看到了这段代码。

随着超参数优化过程的运行,您将获得以下输出:

作者图片

超参数调整过程完成后,我们可以通过访问best_trial方法获取超参数的最佳组合,如下所示:

这就是你开始用 Optuna 调优你的神经网络超参数所需要做的一切!

然而,Optuna 提供了更多的功能,使我们的超参数调整管道更加有效。让我们来看看其中的一些特性。

运行定义设计

大多数时候,每当我们构建一个神经网络时,我们不希望仅仅调整一层中的单元数量,还希望调整层本身的数量。为了达到最佳性能,我们应该在神经网络模型中构建多少层?一层够吗?两个?三个?我们永远不会提前知道。

由于其模块化设计,Optuna 允许我们调整层数。这意味着允许用户动态构建搜索空间。

例如,假设我们想要调整神经网络模型中的 a)层数和 b)每层的单元数。我们可以通过实现以下方法来做到这一点:

请注意,我们没有预先为我们的神经网络模型定义任何特定的层数,也没有定义一层中的单元数。

相反,算法会在每次试验中选取特定的层数,然后选取每层中的单元数,然后建立相应的神经网络。所有过程都是以动态的方式完成的。

您可以将这一概念应用于更高级的神经网络层,例如卷积层。

修剪机制

我们知道超参数调整是一个耗时的过程,尤其是当我们有大量的超参数选择和搜索空间时。为了节省我们的时间,Optuna 提供了一个修剪机制特性。

这种修剪所做的是,它将在训练过程的早期阶段终止没有希望的试验,这样我们就不需要浪费时间和资源。

有几种修剪方法可用于 Optuna,它们是:

将特定的修剪程序集成到我们的代码中非常简单。首先,我们需要添加pruner变量作为参数,并在使用create_study创建学习会话时使用我们首选的修剪方法对其赋值,如下所示:

接下来,我们通过在每个训练步骤结束时调用reportshould_prune方法来激活修剪程序。对于 PyTorch 中的神经网络,在训练循环的每个时期后调用这些方法,如下所示:

通过运行定义设计和普鲁纳实现代码

下面是在我们集成了修剪机制和运行定义设计来调整我们的神经网络中的层数之后,整个超参数调整过程的完整代码实现。

在你运行这项研究后,你会注意到我们的神经网络的层数和每层的单元数在不同的试验中是不同的。此外,为了加速超参数调整过程,一些不被看好的试验被删除了。

作者图片

和以前一样,我们可以用best_trial方法访问最佳试验的超参数。

Optuna 还有一个非常有用的特性我们可以使用,那就是可视化特性。

调谐过程的可视化

Optuna 提供了一个特性,使我们能够在调优过程结束后可视化该过程的历史。我们现在将介绍其中一些。

第一个可视化是每个训练步骤中每个试验的目标函数(在我们的例子中是准确性)的图。

作者图片

从上面的可视化可以看出,几个没有希望的试验在第一步就被修剪掉了,因为它们的准确性非常低。

您还可以按如下方式可视化优化历史:

作者图片

这种可视化有助于了解哪个试验是最佳试验,以及其他试验的客观价值与最佳试验相比如何。由于修剪机制,在特定试验中会丢失几个数据点。

接下来,我们有平行坐标图:

作者图片

如果您有大量的超参数和搜索空间,平行图可能很难看到和解释。然而,如果我们有合理数量的超参数和搜索空间,这个图将是有用的。我们可以在每一行中看到超参数的值组合以及它们在我们的目标函数上的表现。

Optuna 还使我们能够绘制超参数重要性,如下图所示:

作者图片

该图向我们展示了每个超参数对提高目标函数得分的重要性。以上面的可视化为例,结果表明第一层中的单元数量是最重要的超参数,而层数是不太重要的超参数。

该图对于提高调优过程的效率非常有用,尤其是在有大量超参数可供选择的情况下。

作为第一项研究,您可以运行大约 50 次超参数调整,然后检查哪些超参数是最重要的。接下来,您可以在第二次研究中省略不太重要的超参数,这可以节省您的时间和资源。

结论

在这篇文章中,我们逐步讲解了如何使用 Optuna 和 PyTorch 来调整神经网络模型的超参数。

我们已经看到,运行定义设计、修剪机制和一些可视化选项是使用 Optuna 进行超参数调优的主要好处。

我希望这篇文章能帮助你开始使用 Optuna,如果你想看这篇文章中的完整代码实现,你可以随时参考 这本笔记本

数据集引用

[1]费德索里亚诺。(2021 年 9 月)。心力衰竭预测数据集。于 2021 年 12 月 14 日从 https://www.kaggle.com/fedesoriano/heart-failure-prediction取回。

基于网格搜索和随机搜索的超参数调谐

原文:https://towardsdatascience.com/hyperparameter-tuning-with-grid-search-and-random-search-6e1b5e175144?source=collection_archive---------5-----------------------

并深入探讨如何将它们结合起来

来源

超参数调整也称为超参数优化,是任何机器学习模型训练中的重要步骤,直接影响模型性能。

本文涵盖了两种非常流行的超参数调优技术:网格搜索随机搜索,并展示了如何将这两种算法与从粗到细的调优结合起来。到本文结束时,你将知道它们的工作原理和主要区别,这将帮助你自信地决定使用哪一种。

在阅读本文的同时,我鼓励您查看我的 GitHub 上的 J upyter 笔记本,以获得完整的分析和代码。🌠

背景

超参数是在训练之前定义的参数 ,用于指定我们希望模型训练如何进行。我们可以完全控制超参数设置,这样我们就可以控制学习过程。

例如,在随机森林模型中n_estimators(我们想要的决策树数量)是一个超参数。它可以设置为任何整数值,但是当然,设置为 10 或 1000 会显著改变学习过程。

参数相反,是在训练时发现的。我们无法控制参数值,因为它们是模型训练的结果。例如,在线性回归中,系数截距是在模型训练结束时找到的参数。

为了学习模型超参数和它们的值,我们可以简单地在 Python 中调用get_params。🔍

from sklearn.ensemble import RandomForestClassifier# Instantiate the model
rf_model = RandomForestClassifier()# Print hyperparameters
rf_model.get_params

RandomForestClassifier(bootstrap= True,CCP _ 阿尔法 =0.0, class_weight =None, criterion = '基尼', max_depth =None, max_features = '自动', max_leaf_nodes =None, max_samples =None,min _ infinity _ decrease【T11

如您所见,随机森林分类器有许多超参数,如果模型在没有定义超参数的情况下被实例化,那么它将有默认值。在随机森林中,默认情况下,n_estimators=100,这将产生一个中等大小的森林。(只有 100 棵树🌳)

您需要知道,在任何模型中(在本例中为随机森林),一些超参数比其他超参数更重要,例如:

**n_estimators**: Number of decision trees
**max_features**: Maximum number of features considered while splitting
**max_depth**: Max depth of the tree
**min_samples_leaf**: Minimum number of data points in a leaf node
**bootstrap**: Sampling with or without replacement

一些超参数不影响模型性能,例如:

**n_jobs**: Number of jobs to run in parallel
**random_state**: Seed
**verbose**: Printing information while training continues
**oob_score**: Whether or not to use out-of-bag samples

最后,超参数调整是根据定义的评分标准,寻找能够提供最佳性能的最佳超参数组合。

数据和初始模型

在本文中,我们将使用来自 UCI 的玻璃识别数据集,其中我们有 9 个属性来预测玻璃的类型(从 7 个离散值中)。

来自数据的 5 个随机行

接下来,我将分离 X 和 y,并生成训练集和测试集。

# Seperate X and yX = df.drop(columns=['Type'], axis=1)
y = df['Type']# Generate training and test sets for X and yX_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8, random_state=1)

之后,我们简单地运行一个带有默认值的随机森林分类器,并获得测试集的预测。

# Instantiate and fit random forest classifierrf_model = RandomForestClassifier()
rf_model.fit(X_train, y_train)# Predict on the test set and call accuracyy_pred = rf_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)print(accuracy)

0.81

如你所见,默认模型的准确率为 81%。现在,我们将了解如何使用网格搜索来优化选定的超参数。

网格搜索

网格搜索从定义搜索空间网格开始。网格由选定的超参数名称和值组成,并且网格搜索彻底搜索这些给定值的最佳组合。🚀

假设我们决定定义以下参数网格来优化我们的随机森林分类器的一些超参数。

**param_grid:**
n_estimators = [50, 100, 200, 300]
max_depth = [2, 4, 6, 8, 10]
min_samples_leaf = [1, 5, 10]
max_features = ['auto', 'sqrt']
bootstrap = [True, False]

我们将使用 Scikit-Learn 库中的GridSearchCV类进行优化。首先要提到的是,网格搜索必须运行并比较 240 个模型(=45322,所选数值的乘积)。

此外,GridSearchCV类可以选择执行交叉验证,将训练和测试数据重新采样到多个文件夹中。通过应用交叉验证,我们使用数据中的每条记录进行训练和测试,而不是在训练和测试时一次性拆分数据集。如果我们决定使用交叉验证(假设有 5 个折叠),这意味着网格搜索必须评估 1200 (=240*5)个模型性能。

让我们看看GridSearchCV类的所有输入参数:

*class* sklearn.model_selection.**GridSearchCV**(*estimator*, *param_grid*, *scoring=None*, *n_jobs=None*, *refit=True*, *cv=None*, *return_train_score=False*)

我们首先为网格定义一个字典,我们将把它作为 GridSeachCv 的输入。

# Define the gridparam_grid = {
'n_estimators': [50, 100, 200, 300],
'min_samples_leaf': [1, 5, 10],
'max_depth': [2, 4, 6, 8, 10],
'max_features': ['auto', 'sqrt'],
'bootstrap': [True, False]}# Instantiate GridSearchCVmodel_gridsearch = GridSearchCV(
estimator=rf_model,
param_grid=param_grid,
scoring='accuracy',
n_jobs=4,
cv=5,
refit=True,
return_train_score=True)

如前所述,estimator是 RandomForestClassifier(RF _ model ),而param_grid是我们上面定义的参数网格。scoring是期望的评估指标,比如分类任务的准确性,而n_jobs并行执行模型评估,但是如果设置 n_jobs=-1,就要小心了,它使用所有的处理器!由于网格搜索是一种不知情的调优,我们可以利用并行运行的模型,因为它们的结果不会影响其他模型的运行。

设置refit=True最终用找到的最佳超参数值重新拟合估计器,因此我们不需要在额外的步骤中对它们进行编码。cv定义交叉验证策略和设置return_train_score=True我们可以打印模型运行的日志以进行进一步分析。

# Record the current time 
start = time()# Fit the selected model
model_gridsearch.fit(X_train, y_train)# Print the time spend and number of models ran
print("GridSearchCV took %.2f seconds for %d candidate parameter settings." % ((time() - start), len(model_gridsearch.cv_results_['params'])))

GridSearchCV 对 240 个候选参数设置耗时 247.79 秒。

# Predict on the test set and call accuracyy_pred_grid = model_gridsearch.predict(X_test)
accuracy_grid = accuracy_score(y_test, y_pred_grid)

0.88

如您所见,简单地调整一些超参数将初始准确性从 81%提高到 88%,花费 247 秒来调整超参数。

网格搜索总是找到网格中提到的具有超参数值的最佳执行模型。它也很容易实现和解释。然而,随着要测试的超参数和值数量的增加,它很容易变得计算昂贵,因为它对超参数的所有组合进行建模。不从已经运行的模型中学习的缺点使得网格搜索低效且耗时。此外,参数网格起着极其重要的作用:即使网格搜索总是能找到最佳组合,但如果参数网格选择不当,最佳组合的性能也不会很好。

运行 GridSeachCV 后,我们可以返回以下属性以供进一步研究:

  • cv_results_
  • 最佳估算者 _
  • 最好成绩 _
  • best_params_

让我们来看看其中的一些:

print(model_gridsearch.best_params_)

print(model_gridsearch.best_estimator_)

RandomForestClassifier(bootstrap = True,CCP _ 阿尔法=0.0,class_weight=None,criterion= '基尼',max_depth=10,max_features='sqrt ',max_leaf_nodes=None,max_samples=None,min _ infinity _ decrease = 0.0,min_samples_leaf=1,min_samples_split=2,min_weight_fraction_leaf=0.0,n_estimators=300,n_jobs=None,oob_score=False,random

随机搜索

在随机搜索中,我们为每个超参数定义分布,超参数可以统一定义或使用采样方法。与网格搜索的关键区别在于随机搜索,不是所有的值都被测试,测试的值是随机选择的。

例如,如果分布中有 500 个值,如果我们输入n_iter=50,那么随机搜索将随机抽取 50 个值进行测试。通过这样做,随机搜索优化了时间花费,并且不定义绝对网格允许它探索给定分布中的其他值。

由于随机搜索并不尝试每个超参数组合,它不一定返回最佳性能值,但它会在显著更短的时间内返回相对较好的性能模型。⏰

***param_distributions**
n_estimators = list(range(100, 300, 10))
min_samples_leaf = list(range(1, 50))
max_depth = list(range(2, 20)
max_features = ['auto', 'sqrt']
bootstrap = [True, False]*

RandomizedSearchCV从 Scikit-Learn 有以下输入参数:

**class* sklearn.model_selection.**RandomizedSearchCV**(*estimator*, *param_distributions*, *n_iter=10*, *scoring=None*, *n_jobs=None*, *refit=True*, *cv=None*, *verbose=0*, *pre_dispatch='2*n_jobs'*, *random_state=None*, *error_score=nan*, *return_train_score=False*)*

我们首先为参数分布定义一个字典,它将成为 RandomizedSearchCV 的输入。

*# specify distributions to sample fromparam_dist = {
'n_estimators': list(range(50, 300, 10)),
'min_samples_leaf': list(range(1, 50)),
'max_depth': list(range(2, 20)),
'max_features': ['auto', 'sqrt'],
'bootstrap': [True, False]}# specify number of search iterationsn_iter = 50# Instantiate RandomSearchCVmodel_random_search = RandomizedSearchCV(
estimator=rf_model,
param_distributions=param_dist,
n_iter=n_iter)*

大多数参数与 GridSearchCV 相似,然而,在 RandomizedSearchCV 中,我们有param_distributions来定义搜索分布。n_iter用于限制模型运行的总数(换句话说,从网格中取样的参数组合)。这里要小心权衡,因为设置 高 n_iter 增加搜索运行时间,设置 低 n_iter 降低模型质量。

*# Record the current time 
start = time()# Fit the selected model
model_random_search.fit(X_train, y_train)# Print the time spend and number of models ran
print("RandomizedSearchCV took %.2f seconds for %d candidate parameter settings." % ((time() - start), len(model_random_search.cv_results_['params'])))*

RandomizedSearchCV 对 50 个候选参数设置耗时 64.17 秒。

*# Predict on the test set and call accuracyy_pred_random = model_random_search.predict(X_test)
accuracy_random = accuracy_score(y_test, y_pred_random)*

0.86

正如你所看到的,仅在 64 秒内,我们就能将初始模型的准确率从 81%提高到 86%。随机搜索没有达到网格搜索 88%的准确率,然而,这是两种调优方法之间的权衡。

最后,让我们看看用随机搜索找到的最佳参数。

*print(model_random_search.best_params_)*

{'n_estimators': 230,' min_samples_leaf': 4,' max_features': 'auto ',' max_depth': 13,' bootstrap': False}

粗调至微调

从文章开始,我们已经看到了如何应用网格搜索和随机搜索进行超参数优化。

使用网格搜索,我们能够测试网格中给定的所有超参数值,从中找出最佳值。然而,超参数数量的增加很容易成为瓶颈。理想情况下,我们可以结合网格搜索和随机搜索来防止这种低效率。

在从粗到细的调整中,我们从随机搜索开始,为每个超参数找到有希望的值范围。例如,如果随机搜索在 150 到 200 之间返回高性能,这是我们希望网格搜索关注的范围。使用随机搜索获得每个超参数的焦点区域后,我们可以相应地定义网格进行网格搜索,以找到其中的最佳值。

作者图片

在上图中,我们首先随机测试值,通过随机搜索找到一个焦点区域。其次,我们正在用网格搜索测试这个重点区域中的所有值,并最终找到最佳值。

奖金

另一个微调机器学习模型的有用策略是使用 集成学习 技术。与超参数调整不同,集成学习旨在通过将多个模型组合成一个组模型来提高模型性能。这种群体模式旨在比每个单独的模式表现得更好。最常用的集成学习方法是投票、bagging、boosting堆叠,如果你想了解更多或更新你的知识,你可以阅读我关于这个主题的文章。🐬

结论

在本文中,我们使用了一个随机森林分类器,使用 9 种不同的属性来预测“玻璃的类型”。具有默认超参数值的初始随机森林分类器在测试中达到 81%的准确度。使用网格搜索,我们能够在 247 秒内调整选定的超参数,并将准确性提高到 88%。接下来,我们使用随机搜索做了同样的工作,在 64 秒内,我们将准确率提高到了 86%。最后但同样重要的是,我们讨论了从粗到细的调优,以结合这两种方法并从两者中获得优势!

我希望您喜欢阅读关于超参数调优的文章,并发现这篇文章对您的分析有用!

如果你喜欢这篇文章,你可以 在这里阅读我的其他文章和* 关注我上媒如果有任何问题或建议,请告诉我。✨*

喜欢这篇文章吗? 成为会员求更!

使用 KerasTuner 和 TensorFlow 进行超参数调谐

原文:https://towardsdatascience.com/hyperparameter-tuning-with-kerastuner-and-tensorflow-c4a4d690b31a?source=collection_archive---------4-----------------------

了解使用 KerasTuner 和 TensorFlow 优化模型架构和超参数的最佳实践

图片由 Zoltan·塔西在宣传片上拍摄

构建机器学习模型是一个迭代过程,涉及优化模型的性能和计算资源。您在每次迭代中调整的设置被称为超参数。它们支配着训练过程,并在训练过程中保持不变。

搜索最佳超参数的过程被称为超参数调整超调整,在任何机器学习项目中都是必不可少的。超调通过移除不必要的参数(例如,密集层中的单元数量)来帮助提高性能并降低模型复杂性。

有两种超参数:

  1. 影响模型架构的模型超参数(例如,DNN 中隐藏层的数量和宽度)
  2. 影响训练速度和质量的算法超参数(如学习率和激活函数)。

即使在浅层 DNN 中,超参数组合的数量也可能增长得惊人地大,导致手动搜索最优集合根本不可行也不可扩展。

这篇文章将向您介绍 Keras Tuner,这是一个自动化超参数搜索的库。我们将构建并比较在时尚 MNIST 数据集上训练的三个深度学习模型的结果:

  • 具有预选超参数的基线模型
  • 超带算法优化超参数
  • 具有贝叶斯优化的调整的 ResNet 架构

你可以点击查看 jupyter 笔记本

导入和预处理

让我们首先导入所需的模块并打印它们的版本,以防您想要复制笔记本。我们使用的是 tensor flow 2 . 5 . 0 版和 kera stuner 1 . 0 . 1 版。

import tensorflow as tf
import kerastuner as ktfrom tensorflow import kerasprint(f"TensorFlow Version: {tf.__version__}")
print(f"KerasTuner Version: {kt.__version__}")>>> TensorFlow Version: 2.5.0
>>> KerasTuner Version: 1.0.1

我们将从加载时尚 MNIST 数据集开始。目标是训练一个机器学习模型来对不同的服装图像进行分类。

由于图像是灰度的,这意味着每个像素值代表一个 1 到 255 之间的数字,我们可以将每个像素除以 255 来归一化 0 到 1 之间的值。这样会让训练收敛的更快。

基线模型

如前所述,我们将首先用预选的超参数训练一个浅层密集神经网络(DNN ),为我们提供一个基准性能。我们稍后会看到简单的模型,像这个浅层 DNN,如何需要一些时间来调整。

注意我们如何在上面的代码中硬编码所有的超参数。这些包括隐藏层的数量(在我们的例子中有 1 个隐藏层),隐藏层中的单元数量(512),它的激活函数(ReLu),以及退出百分比(0.2)。我们将在下一节中调整所有这些超参数。

让我们来设置优化器、损失和指标。我们稍后将调整的另一个超参数是学习率,但现在我们将它设置为 0.001。

定义好模型的设置后,我们就可以开始训练了!我们将把周期数设置为 20,如果 5 个周期后性能没有提高,就使用提前停止来中断训练。

最后,我们想看看我们的模型在测试集上的表现,因此我们将定义一个助手函数来轻松显示结果。

图一。基线评估结果|作者图片

这是一组超参数的结果。想象一下,尝试不同的学习率、辍学率、隐藏层的数量以及每个隐藏层中的神经元数量。如您所见,手动超调根本不可行,也不可扩展。在下一节中,您将看到 Keras Tuner 如何简单地通过自动化过程和以有效的方式搜索超参数空间来解决这些问题。

Keras 调谐器

Keras Tuner 是一个简单的、可分发的超参数优化框架,它自动化了手动搜索最佳超参数的痛苦过程。Keras Tuner 带有随机搜索、超波段和贝叶斯优化内置搜索算法,旨在适应多种使用情况,包括:

  • 分布式调谐
  • 定制培训循环(例如,GANs、强化学习等。)
  • 在模型建立功能(预处理、数据扩充、测试时间扩充等)之外添加超参数。)

这些过程超出了本文的范围,但是可以随意阅读更多的官方文档。

使用 Keras 调谐器超调浅 DNN 有四个步骤:

  1. 定义模型
  2. 指定要优化的超参数
  3. 定义搜索空间
  4. 定义搜索算法

定义模型

我们为超调建立的模型被称为超模。我们在构建超模型时定义了超参数搜索空间。

有两种方法可以建立一个超级模型:

  1. 通过使用模型构建器功能
  2. 使用 Keras Tuner API 的超模子类

我们将使用第一种方法来定义模型构建函数中的 DNN。您会注意到超参数是如何内联定义的。我们的模型构建函数使用定义的超参数来返回编译后的模型。

指定要优化的超参数

我们将构建的模型与我们之前训练的浅层 DNN 非常相似,只是我们将调整模型的四个超参数:

  • 隐藏层的数量
  • 每个隐藏层中的单元数
  • 每个隐藏层后的下降百分比
  • Adam 优化器的学习率

定义搜索空间

这是通过将一个超参数对象作为参数传递给模型构建函数来实现的,该函数配置您想要优化的超参数。在我们的函数中,我们将使用:

  • 惠普。Int()来定义隐藏层的数量和每个隐藏层中的单元的搜索空间。这允许您定义最小值和最大值,以及增量的步长。
  • 惠普。Float()定义辍学百分比的搜索空间。这个和惠普差不多。Int(),只不过它接受浮点值。
  • 惠普。Choice()来定义学习率的搜索空间。这允许您定义离散值。

有关所有可用方法及其用法的更多信息,请访问官方文档

定义搜索算法

在构建了模型构建器函数之后,我们可以实例化调谐器并指定搜索策略。对于我们的用例,我们将使用超波段算法。Hyperband 是一种新颖的基于 bandit 的方法,专门用于超参数优化。研究论文发表于 2018 年,详细描述了一个通过自适应资源分配和提前停止快速收敛于高性能模型的过程。

这个想法很简单,Hyperband 使用了一个体育锦标赛风格的支架,并从搜索空间中随机选择大量具有随机超参数排列的模型开始。每个模型被训练几个时期,只有表现最好的一半模型进入下一轮。

要实例化我们的调谐器,我们需要定义以下超参数:

  • 我们的超级模型(由我们的模型生成器函数构建)
  • 目标(方向(最小或最大)将为内置指标自动推断——对于自定义指标,我们可以使用 kerastuner。目标)
  • 因子和 max_epochs 用于通过取 max_epochs + 1 的对数基础因子来计算每个括号中的模型数量。这个数字被向上舍入到最接近的整数。
  • 超带迭代用于控制您愿意分配给超调的资源预算。Hyperband iterations 是迭代整个搜索算法的次数。
  • 在超参数搜索过程中,目录保存每次试运行的日志和检查点,允许我们从上次停止的地方继续搜索。您可以通过设置额外的超参数“overwrite”= True 来禁用此行为。
  • Project_name 用于与其他运行区分开,是目录下的子目录。

请参考官方文档中所有可用参数的列表。

我们可以看到搜索空间摘要:

当指标没有改善时,我们可以设置像提前停止这样的回调来提前停止训练。

我们开始搜索吧。

搜索结束后,我们可以得到最好的超参数,并重新训练模型。

然后我们将在测试集上评估我们的超调模型!

图二。超调模型评估|作者图片

通过超调,我们发现了一种比我们的基线模型少 100,000 个参数的架构,它在测试集上的性能略好。如果我们对 hyperband 算法进行更多的迭代,我们很可能会找到一个性能更好的架构。

超级网络

除了定义我们自己的超模型,Keras Tuner 还提供了两个预定义的可调模型,HyperXception 和 HyperResnet。这些模型搜索以下架构和超参数:

  • 模型的版本
  • 卷积层的深度
  • 联营
  • 学习率
  • 最优化算法

让我们看看如何将 HyperXception 或 HyperResnet 与我们的调谐器一起使用。

我们在 HyperResnet 模型中指定输入形状和类的数量。这次我们将使用贝叶斯优化作为我们的搜索算法,它通过聚焦于更有希望的区域来搜索超参数空间。此外,我们使用不同的 project_name,以便我们的调音师可以区分之前的运行。

接下来,我们必须对数据进行预处理,以符合 HyperResnet 的要求。HyperResnet 希望要素的形状与卷积图层和一次性编码标注的形状相同。

使用下面的小代码块,我们可以开始搜索。

同上,我们可以得到最好的超参数,并重新训练模型。

最后,我们将在测试集上评估模型。

图 3。HyperResNet 模型评估|作者图片

在生产环境中,我们需要考虑的不仅仅是测试集的准确性。最佳部署选项是我们的超调 DNN,因为它在测试集上表现稍好,并且参数最少。

总结

超调是机器学习管道的重要组成部分。在这篇文章中,我们训练了一个基线模型,展示了为什么手动搜索最佳超参数是困难的。我们深入探讨了 Keras Tuner 以及如何使用它来自动执行超参数搜索。最后,我们超调了一个预定义的超 Resnet 模型。

感谢阅读!

请查看我以前发布的更多数据科学项目和教程。

我写的是我进入数据科学和机器学习工程的学习历程,请关注并联系我的 LinkedIn ,或 Github ,我们一起学习!

额外资源

https://blog.tensorflow.org/2020/01/hyperparameter-tuning-with-keras-tuner.html https://keras.io/guides/keras_tuner/

研究论文

https://jmlr.org/papers/v18/16-558.html

您还在使用网格搜索进行超参数优化吗?

原文:https://towardsdatascience.com/hyperparameters-tuning-from-grid-search-to-optimization-a09853e4e9b8?source=collection_archive---------11-----------------------

让我们讨论如何以智能的方式搜索机器学习模型的超参数背后的思想。

米伊卡上拍摄的照片

当我们训练一个机器学习模型时,我们需要做出一些选择,从哪个模型开始使用,如何准备我们的数据集,如何处理离群值,等等。

其中一个选择是超参数;这些是控制学习过程的参数,但不能由训练本身得出。一些例子是:

  • 神经网络中的学习速率、时期和层数/神经元数。
  • 随机森林中的树木数量、最大深度和质量标准。
  • 来自支持向量机的核、gamma 和 C 值。

随之而来的一些问题是:我应该为这个模型设置什么超参数?默认的够好吗?我是否可以通过尝试更多架构来提高性能?我如何决定尝试哪些选项?所有这些问题都与超参数调整有关[1]。

在这篇文章中,我将讨论:

  • 监督模型中超参数调整的标准策略。
  • 不明智策略的问题在于。
  • 明智策略的权衡。
  • 如何实现超参数调整的遗传算法(GA)思想?
  • 我们能给 GA 带来什么额外的特性。
  • 包含几个实现的 python 包的参考和例子。

如果你想马上获得一些带有示例的代码,你可以查看我在其他媒体上的帖子。

1。基本策略:

有几个选项可用来找到那些将使您的模型增强的超参数,仅举几个例子:

  • 网格搜索
  • 随机网格搜索
  • 贝叶斯优化
  • 遗传算法

网格搜索和随机网格搜索都是我们所谓的“强力方法”,这意味着超参数的选择不是以一种提供信息的方式,而是通过尝试一些选项并希望它有效。

它们的优点是实现简单,并且可以足够快地得到合适的结果,尝试一些组合并基于一些度量选择最佳的,因此对于两个超参数;该过程可能如下所示:

网格布局。图片由 Yoshua Bengio 等人提供。

上图展示了网格和随机网格搜索如何优化一个模型,该模型的得分函数(如 AUC)是绿色和黄色区域的总和,对得分的贡献是区域的高度,因此基本上只有绿色区域对得分有意义。

2。将问题可视化

您可以看到,随机布局在某种程度上优于网格布局,因为它可以探索优化函数的更多不同值,并且由于其中一个参数不重要,网格搜索“浪费”了六个额外的模型,得分没有重要变化,但在这两种情况下,我们都有可能获得接近或远离最佳值的值。

我将把这种表示简化为一维函数,只是为了获得一些直觉:

准确度分数与超参数选择。图片由作者提供。

在上面的图中,红线表示估计量可能达到的交叉验证准确度(或任何其他度量),圆点是基于准确度分数的超参数的固定选择,因此,例如,如果这是一个神经网络,圆点可以表示以下内容:

**dot 1:** {"learning_rate": 0.001, "layers": 5, "optimizer": "Adam"}
**dot 2:** {"learning_rate": 0.01, "layers": 3, "optimizer": "Adagrad"}
**dot 3:** {"learning_rate": 1, "layers": 6, "optimizer": "SGD"}
**dot 4:** {"learning_rate": 0.001, "layers": 8, "optimizer": "RMSprop"}
**dot 5:** {"learning_rate": 0.1, "layers": 20, "optimizer": "SGD"}

根据这一点,我们可以得到沿着这条线的任何值,你想得到尽可能高的值,但是通过随机或手动选择点,我们可能会得到也可能不会得到好的结果。

好..我们发现了问题,那么我们如何才能让它变得更好呢?

3.信息的方式

我提到的另外两种方法是贝叶斯优化[3]和遗传算法[4],我们可以说,它们遵循一个信息丰富的标准来做出选择,它们的共同点是,它们遵循一个顺序过程,试图通过它们过去做出的决策来找到一组更好的超参数,所以如果我们认为这是一个迭代过程,它可能看起来像这样:

迭代优化过程。图片由作者提供。

你可以看到,第一次迭代可能会看到一个随机网格会做什么,没关系,我们必须从某个点开始;其思想是聪明地探索超参数的空间,在每次迭代中取得进展,修改要尝试的集合的数量,创建新的集合,等等。

当然,正如数据科学中预期的那样,这不是一个银弹解决方案;可能会出现以下几种情况:

  • 探索与开发的困境:我是否应该去探索较少的地区,以防错过什么?或者我应该继续尝试我已经知道的显示有希望的结果的区域附近的点?
  • 局部最大:这是第一种可能的结果;如果我的优化函数是非凸的、非线性的、有噪声的怎么办?,如果我陷入局部最大值,认为这是最好的(全局最大值)解决方案,怎么办?
  • 资源消耗:正如你所看到的,我们已经把它变成了一个迭代的过程,可能比简单的网格搜索消耗更多的资源。
  • 新参数:我应该运行多少次迭代?我如何控制探索和开发?,我应该在每次迭代中创建更多的集合吗?,这些不就是我要决定的更多的超参数吗?

希望有几个实现已经(直到某个时候)解决了这些问题,并且这些选择对我们正在优化的分数的最终影响不如机器学习模型本身中超参数的选择敏感。

例如,你可以检查遗传算法方法的 sklearn-genetic-opt 或者贝叶斯方法的 scikit-optimize 。我将解释遗传算法的方法。

4.遗传算法(GA)方法

遗传算法是一种受自然选择启发的元启发式算法;它们通常用于优化和搜索问题,通常基于一组函数,如变异、交叉和选择[2]。我们称之为遗传算子。

在本节中,我将交替使用以下术语来建立遗传算法和机器学习之间的联系:

超参数的一个选择→个体

人口→若干个人

世代→一个包含固定群体的固定迭代

适应值→交叉验证分数

有几种变化,但一般来说,要遵循的步骤如下所示:

  1. 生成随机抽样总体(不同的超参数集);这是第 0 代。
  2. 从机器学习的角度评估种群中每个个体的适应度值,得到交叉验证分数。
  3. 通过使用几个遗传算子产生新一代。
  4. 重复步骤 2 和 3,直到满足停止标准。

我们一步一步来。

4.1-4.2 创建第 0 代并对其进行评估:

如上所述,您可以生成一组随机的超参数,或者您可以包含一些您已经尝试过并认为是合适的候选参数的手动选择的超参数。

每个集合通常以染色体的形式被编码,染色体是这个群体的二进制表示;例如,如果我们将第一代的规模设置为三个个体,它将如下所示:

第 0 代。图片由作者提供。

所以在这一代中,我们使用红色箭头表示的编码函数将三个个体映射到一个染色体(二进制)表示中。染色体中的每个方框是一个性别。染色体的一个固定部分是超参数之一。

然后,我们使用显示为紫色箭头的评分函数来获得每个候选人的交叉验证分数(适合度)。

4.3 创造新一代:

现在我们可以创建一组新的候选人;如前所述,有几个遗传算子;我将展示最常见的几种:

交叉:

这种操作包括取两条亲代染色体并使它们交配以产生新的子代;我们选择亲本的方式可以是通过概率分布函数,该函数将更多的概率给予具有更高适应度的个体,假设个体编号 1 和 3 被选择,那么我们可以从每个亲本中随机选取两个点,并进行交叉,如下所示:

交叉操作。图片由作者提供。

现在孩子代表了一组新的超参数;如果我们解码每个孩子,我们可以得到,例如:

**Child 1:** {"learning_rate": 0.015, "layers": 4, "optimizer": "Adam"}
**Child 2:** {"learning_rate": 0.4, "layers": 6, "optimizer": "SGD"}

但是在一些迭代之后,在相同的超参数集合上进行交叉可能会给出相似的结果,所以我们会陷入同一种解决方案;这就是为什么我们引入了像变异这样的其他操作。

突变:

以足够低的概率(< ~0.1), this operator randomly changes one of the gens or a whole hyperparameter to create more diverse sets.

Let's take, for example, the child one from the previous image; let us pick up random gen and change its value:

Mutant child. Image by the author.

Or it could even change a whole parameter, for example, the optimizer:

Random change in one parameter. Image by the author.

精英主义:

这种选择策略指的是选择每一代中最优秀的个体,以确保其信息能够跨代传播。这种策略非常简单,只需根据个体的适应值选择最优秀的 k 个个体,并将其复制到下一代。

所以在执行了那些操作之后,新一代可能看起来像这样:

第一代。图片由作者提供。

从现在开始,重复这个过程几代,直到你满足一个停止标准,例如:

  • 已达到最大代数。
  • 流程运行时间超过了预算时间。
  • 与上 n 代相比,性能没有提高(低于阈值)。

下图是我们运行 GA 优化器几代后得到的结果的一个例子;这是一个回归模型,使用带有 r 平方度量的随机森林:

几代人的度量改进。图片由作者提供。

我们可以绘制算法尝试的超参数,如点图,但在这种情况下,遵循最现实的表示,我们可以绘制每个参数的样本值的直方图和与第一个图类似的散点图。

超参数的抽样分布。图片由作者提供。

图中的颜色越深,在该区域适合的不同估计值就越多;“分数”是相同的 r 平方。

因此,在这一点上,问题是,我们如何实现这一点?我必须从头开始做吗?如前所述,已经有几个包可以帮助解决这个问题;我们会看到其中一个的特征。

注:我是下面这个包的作者;如果你想进一步了解,投稿或者提出一些建议,可以查看本文末尾的文档和 GitHub 资源库。

介绍 Sklearn-genetic-opt

Sklearn-genetic-opt 是一个基于 Python 的包,它使用来自 DEAP 包的进化算法来选择一组优化(最大或最小)交叉验证分数的超参数;该软件包可用于回归和分类问题。在这一点上,Sklearn-genetic-opt 与任何 scikit-learn 回归器或分类器(或 Sklearn 兼容的回归器或分类器)兼容。

该软件包具有以下特点:

  • GASearchCV: 包的主要类,保存进化交叉验证优化例程,它有一个类似于 scikit-learn GridSeachCV 的 API。
  • GAFeatureSelectionCV: 软件包的补充类,它使用与 GASearchCV 相同的进化算法进行特征选择,但通过尝试最小化所使用的特征数量,同时优化 CV 分数,所有这一切都使用一组固定的超参数。
  • 算法:一组不同的进化算法,用作优化程序。
  • 回调:定制评估策略,以生成早期停止规则、日志记录或您的定制逻辑。
  • 适配器:改变参数作为代函数的策略。
  • 图:生成预定义的图,以了解优化过程。比如最后两个情节就来自于包。
  • MLflow:mlflow 的内置集成,用于记录和管理所有超参数、cv 值和拟合模型的生命周期。

因此,它的工作方式是遵循类似于上一节中描述的过程,但它添加了一些额外的功能,如回调、MLflow 日志记录和不同的算法方法;看起来是这样的:

Sklearn-genetic-opt 一般步骤。图片由作者提供。

这就是 MLflow 测井的外观:

Mlflow 日志记录。图片由作者提供。

这是一个如何使用它进行超参数调整的简单示例:

你可以在这篇文章中了解更多关于这个代码的每一部分。

原来如此!感谢您阅读此内容;我希望这有助于思考您的调优策略;以下是最后一个包的相关链接,如果你想查看的话:

文献:https://sklearn-genetic-opt.readthedocs.io/en/stable/

https://github.com/rodrigo-arenas/Sklearn-genetic-opt】储存库:

参考

[1]https://en.wikipedia.org/wiki/Hyperparameter_optimization

[2]https://www . jmlr . org/papers/volume 13/bergstra 12a/bergstra 12a . pdf

[3]https://www . cs . Toronto . edu/~ rgrosse/courses/CSC 411 _ f18/tutorials/tut 8 _ ADAMS _ slides . pdf

https://en.wikipedia.org/wiki/Genetic_algorithm

Softmax 的超球面替代方案

原文:https://towardsdatascience.com/hyperspherical-alternatives-to-softmax-6da03388fe3d?source=collection_archive---------18-----------------------

超球面替代品能和 Softmax 竞争吗?

迈克尔·泽兹奇在 Unsplash 上的照片

在分类问题的上下文中,具有交叉熵损失的 softmax 分类器通常是首选方法。但是,在有许多类的情况下,softmax 的训练速度可能会很慢,因为它要求每个类都有一个输出节点,从而导致输出层非常大。例如,一个隐藏层大小为 300 和 100,000 个输出类的网络仅在输出层就有 3000 万个参数。

在应用人工智能设置中,这些类型的问题经常发生。这方面的一个例子是学习匹配论文与作者,或产品描述与实际产品。虽然这看起来很适合分类问题,但可能的作者或产品的空间如此之大,以至于使用 softmax 训练它不太可能可行。解决这个问题的一个方法是学习或预先定义每个类的原型,例如,原型网络【1】。使用这些预定义或学习的原型允许您使用恒定的输出大小,而不管类的数量。

在这篇文章中,我们研究了超球原型网络(HPNs)【2】,它承诺了恒定的输出大小,性能与 softmax 网络相当,甚至更好。我们将进一步深入 HPNs 的网络输出和性能之间的关系。我们将证明,虽然 hpn 在相对较低的输出维度下工作良好,但随着类别数量的增加,softmax 的性能大大优于它。有趣的是,这与我们预期的正好相反,这就是为什么我们决定写一篇关于它的博文。

在深入研究我们令人惊讶的结果之前,我将首先解释一下 softmax 网络和 HPN 网络的一些基础知识。

Softmax 网络公司

当在单标签分类设置中使用神经网络时,典型的方法是使用 softmax 网络。也就是说,不确定大小和图层的网络具有| C |个单位的输出图层,其中 C 是输出类的集合,以及 softmax 激活函数:

情商。softmax 激活功能。

Softmax 分类器通常通过最小化网络和目标预测之间的交叉熵来训练。这可以理解为试图相对于不正确的输出单位最大化正确输出的幅度。

由于 softmax 分类器具有 |C| 个输出单元,因此对于每个类,softmax 网络的输出层以因子 H 增长,其中 H 是最后一层中隐藏单元的数量。

超球面原型网络

相比之下,超球面原型网络(HPN)【2】的输出层具有预定义的固定维度,而不是类的数量。理论上,这意味着 HPN 中输出单元的数量可以比类的数量小得多,这对于大量的类来说是有效的。HPNs 通过最小化从网络输出到预定义原型的余弦平方距离来学习,而不是交叉熵:

情商。2:由 HPN 最小化的损失函数

在某种意义上,这需要网络学会将一个实例“旋转”到正确类的原型。注意,这个损失函数只需要正确类的原型,不像例如原型网络,它需要访问所有相关的原型。现在,超球面原型网络的特别之处在于,原型是静态的,即在训练期间不更新,并且正交。让我们解释一下为什么这两个属性都很重要。

深入静态和正交属性

如果原型不是静态的,上面的损失函数就会变成一个平凡解。众所周知,如果一个问题有一个微不足道的解决方案,反向传播就会找到它。为了理解“为什么这变成一个微不足道的解决方案”,考虑损失函数仅仅使网络最小化原型和网络输出之间的距离,但是没有规定代表不同类别的原型应该是不同的。因此,通过输出一个常数矢量(例如一个全零矢量),并给所有原型分配完全相同的矢量,网络可以完美地解决任何学习问题。如果学习的原型是期望的,例如,对于零次或少次学习,这个问题可以通过负采样****【3】来规避。

为什么原型应该是正交的就不那么明显了。直觉上,属于不同类的两个原型不应该有相同的表示,因为这意味着类是模糊的。所以,不太相似的原型更容易分开。从字面上看,正交表示是最不相似的,因此它们也可以被认为是最优可分的。因此,在某种意义上,表示应该是正交的是不正确的;他们只是表现得更好。在一些设置中,例如零镜头或少镜头分类,具有有意义相关的表示对性能非常有益,例如参见【1】

因为正交表示的维度是可控的,所以 HPN 允许输出单元数量的灵活性。如果正交表示的维数等于类的数目,则 HPN 与等效的 softmax 分类器具有相同数目的参数。

创建正交表示

制作正交表示似乎很容易,但并不容易。正如【2】所指出的,寻找与给定点集正交的点的问题仍然是公开的,并且被称为塔门问题。【4】****

本文研究了一种引入超球面原型网络的解决方案。【2】简而言之,他们首先随机生成向量,然后,对于每个向量,最小化与最接近向量的余弦相似度,同时在每次迭代后进行重正化。在我们的实施中,我们没有明确地重整,但是我们将 L2 范数的平均偏差从 1 增加到损失。这导致原型是准正交的,而没有显式重正化。与每次迭代后显式规格化相比,这具有导致更低损失的优点,因此平均来说表示更正交。

注意,通过反向投影来训练这些表示是相对有效的,但是它仍然会花费很长时间,特别是如果我们试图在低维空间中打包许多表示,例如,将 100,000 个表示打包到 100 维空间中。

为了显示生成正交表示的有效性,我们还比较了从 N 维正态分布采样的随机生成的表示。随着维数的增加,高维随机向量变得越来越随机,但永远不会真正正交。因此,随机生成的表示和训练的表示之间的任何分数差异显示了正交化过程的附加值。

实际的实验

我们特别感兴趣的是一方面在类别的维度和数量之间的权衡,另一方面在性能、训练和推理速度之间的权衡。与高维正交原型相反,低维正交原型的训练速度更快,但可能会牺牲性能。

为了测试 softmax 和 HPN 网络之间的差异,我们使用了两个相同的网络,由两个具有批量归一化、校正线性单元激活、丢失和 300 个隐藏单元的隐藏层组成。网络之间的唯一区别是顶层。在 softmax 的情况下,这是具有(300, |C| )个单位的线性层,而在 HPN 的情况下,该层的大小取决于正交原型的输出维度。使用 ADAM 优化器【5】对所有网络进行优化,学习率为 1e-3,使用固定验证集上的早期停止。

我们生成 5 个不同的数据集,分别有 10、100 和 1000 个类。对于每个数据集中的每个类,我们通过从区间[-1,1]均匀采样 300 维表示来定义中心。对于每个中心,我们从正态分布中抽取样本,样本的中心和标准差取决于类别的数量。标准偏差列于表 1。

.--------------------.----.-----.------.
|     n classes      | 10 | 100 | 1000 |
:--------------------+----+-----+------:
| standard deviation |  3 | 2.5 | 1.25 |
'--------------------'----'-----'------'
*Table 1: the standard deviations for the different numbers of classes*

对于每个数据集,我们还分别生成 3 组 10、100 和 1000 维的原型。这些原型集允许我们研究输出维度对性能的影响。我们还尝试使用 1000 多个类(10,000 和 100,000),但是为这些类创建正交原型花费了太长时间,比训练网络要长得多。

结果

表演

表 2 中列出了测试集的 F 分数,是五次运行的平均值。请注意,只有原型维度与类的数量一样多的模型才能与 softmax 模型相媲美。

对于 10 级和 100 级,HPNs 的表现往往与 softmax 模型相当,而对于 1000 级模型,HPN 表现不佳。增加原型的维度只会导致分数的边际增加,这表明对性能的上限效应。一旦你有了足够的工作空间,增加更多的空间并没有多大作用。

比较随机生成的原型和优化的原型可以发现一些有趣的模式。对于相应的维度,即 10 个类的 10 维原型,选择随机化的原型会降低性能。然而,当转向更高维的原型时,这种性能差异就消失了。重温上面的比喻:如果维度足够高,即使随机化的原型也为模型提供了足够的工作空间。因为从正态分布中生成随机样本几乎不需要时间,这对于许多类的问题来说可能是有趣的,在这些类中生成真正正交的原型是不可行的。

.-----------.---------.------.------.------.-------.------.-------.
| n classes | softmax |  10  | 100  | 1000 |  r10  | r100 | r1000 |
:-----------+---------+------+------+------+-------+------+-------:
|        10 |    91.3 | 91.2 | 92.6 | 92.5 | 78.22 | 92.5 |  92.8 |
:-----------+---------+------+------+------+-------+------+-------:
|       100 |    84.5 | 72.9 | 86.0 | 85.3 |  73.6 | 85.7 |  86.1 |
:-----------+---------+------+------+------+-------+------+-------:
|      1000 |    83.8 | 15.8 | 58.3 | 47.3 |  14.9 | 54.3 |  47.3 |
'-----------'---------'------'------'------'-------'------'-------'
*Table 2: The F-scores on the test set for classes and various models. r stands for “random”*

速度

每个时期的速度对所有模型都是可比较的。这是令人惊讶的,因为我们预计随着类别数量的增加,与余弦相似性相比,softmax 会变慢。类似地,在收敛之前的历元数之间也有明显的差异,但前提是类别数等于原型的维数。表 3 总结了一些例子。

.-------------------------.----.-----.------.
|        n classes        | 10 | 100 | 1000 |
:-------------------------+----+-----+------:
| softmax                 | 50 | 146 |  181 |
:-------------------------+----+-----+------:
| HPN dim == n_prototypes | 69 | 147 |  206 |
'-------------------------'----'-----'------'
*Table 3: The number of epochs until convergence for softmax, and the HPNs in which the prototype dimensionality matched the number of classes.*

讨论

在我们的实验中,我们看到使用 HPNs 的优势很小。我们期望它们在与许多类一起使用时性能优于 softmax,并且时间效率更高。这两件事都被证明是错误的,但可能是出于不同的原因。

让我们先来解决速度差异:我们假设,因为 HPNs 只查看正类的原型,也就是说,它们不需要负采样,所以它们也会更有效。尽管理论上效率很高,但网络的输出维度需要大致匹配类的数量,如上所示。这意味着 HPNs 和 softmax 网络在计算损耗时所执行的操作数量大致相等。此外,很可能 softmax 可以更高效地实现。

比速度差异更令人惊讶、也更关键的是性能差异。虽然 HPN 有时在较低维度上优于 softmax,但 1000 维的原型根本不起作用。随着空间维度的增加,正交化原型的损失函数很可能不能填充足够的原型。假设使用 hpn 的优势似乎很少,即使对于它们工作的环境,我们认为正确的反应不是改善空间的正交性,而是找到对相关输出表示鲁棒的 hpn 公式。

最后,我们想补充一点,我们使用了人工数据,因为我们希望能够控制班级的数量。在现实生活中,softmax 和 HPN 之间的差异可能更小或更大。例如,我们可能无意中制造了一个特别适合 HPNs 或 softmax 的问题。原始论文【2】的作者尝试了各种数据集,主要是图像集,并显示 HPNs 略微优于 softmax。重要的是,他们没有使用超过 200 个类的数据集。

结论

我们发现,虽然 HPNs 似乎是一种有前途的分类方法,但随着类别数量的增加,其性能会急剧下降。这些结果对超球原型网络用于分类任务的效用提出了一些疑问。

参考

【1】**Snell,j .、Swersky,k .和 Zemel,r .,《少投学习的原型网络》,(2017),《第 31 届神经信息处理系统国际会议论文集(第 4080-4090 页)

****【2】Mettes,p .,van der Pol,e .和 Snoek,C.G .,超球面原型网络,(2019), arXiv 预印本 arXiv:1901.10514

【3】**米科洛夫、苏茨科夫、陈、科拉多和迪安..单词和短语的分布式表示及其组合性,(2013),载于神经信息处理系统进展(第 3111-3119 页)。

【4】**tam mes,P.M.L .,《关于花粉粒表面出口位置的数量和排列的起源》(1930 年),《荷兰植物研究杂志,第 1–84 页。

【5】**Kingma,D.P .和 Ba,j .,Adam:一种随机优化的方法,(2014)arXiv 预印本 arXiv:1412.6980

手工假设检验

原文:https://towardsdatascience.com/hypothesis-test-by-hand-3331f6b5e322?source=collection_archive---------40-----------------------

通过使用临界值、p 值和置信区间方法的 4 个简单步骤,手动学习假设检验的结构

照片由 NeONBRAND 拍摄

描述性统计与推断性统计

请记住, 描述性统计 是统计学的一个分支,旨在以尽可能好的方式描述和总结一组数据,也就是说,通过将其减少到几个有意义的关键指标和可视化——尽可能少地丢失信息。换句话说,描述性统计的分支借助汇总统计和图表,有助于对一组观察结果有更好的理解和清晰的印象。有了描述性统计,就没有不确定性,因为我们只描述我们决定研究的一组观察值,并不试图将观察到的特征推广到另一组或更大的一组观察值。

另一方面,推断统计学 是统计学的一个分支,它使用从人群中随机抽取的数据样本进行推断,即得出关于感兴趣的人群的结论(如果需要刷新这两个概念,请参见人群和样本之间的差异)。换句话说,来自样本的信息用于对总体中感兴趣的参数进行归纳。

推理统计领域中使用的两个最重要的工具是:

  • 假设检验(这是本文的主题),以及
  • 置信区间(在本章节中简要讨论)

动机和限制

通过我的教学任务,我意识到许多学生(尤其是统计学导论课的学生)很难进行假设检验和解释结果。在我看来,这些学生经常遇到困难,主要是因为假设检验对他们来说相当不清楚和抽象。对他们来说,它看起来很抽象的原因之一是因为他们不理解假设检验的最终目标——这个工具背后的“为什么”。他们经常在不理解推理背后的原因的情况下做推理统计,就好像他们在遵循一个不需要任何思考的烹饪食谱。然而,一旦他们理解了假设检验的基本原理,他们应用概念和解决练习就容易多了。

出于这个原因,我认为写一篇关于假设检验的目的的文章(为什么?),在什么情况下应该使用它们(“什么时候?”),它们是如何工作的(“如何?”)以及如何解释结果(即“那又怎样?”).就像统计学中的其他事情一样,当我们事先了解我们正在测试什么或者我们试图证明什么时,在实践中应用一个概念就变得容易得多。

在这篇文章中,我尽可能全面地介绍了手工执行和完成假设检验所需的不同的步骤。这些步骤用一个基本的例子来说明。这将建立假设检验的理论基础,进而对理解大多数统计检验有很大帮助。

假设检验有多种形式,可用于许多参数或研究问题。不幸的是,我在这篇文章中介绍的步骤并不适用于所有的假设检验。然而,它们适用于至少是最常见的假设检验——对以下方面的检验:

  1. 一个平均值:μ
  2. 两个意思是:
  • 独立样本:μ1 和μ2
  • 成对样本:μD

3.一个比例:p

4.两种比例:p1 和 p2

5.一个方差:σ2

6.两个方差:σ21 和σ22

好消息是,这 6 个统计测试(以及更多)背后的原理是完全相同的。因此,如果你理解了其中一个的直觉和过程,所有其他的就都差不多了。

假设检验

为什么?

不像描述性统计只描述手头的数据,假设检验使用观察值的子集,称为样本来得出关于总体的结论

有人可能会问,为什么我们会试图根据样本“猜测”或推断某个群体的参数,而不是简单地收集整个群体的数据,计算我们感兴趣的统计数据,并根据这些数据做出决策。我们实际上使用样本而不是全部人口的主要原因是,在大多数情况下,收集全部人口的数据实际上是不可能的,太复杂,太昂贵,需要太长时间,或者这些情况的组合。 1

因此,假设检验的总体目标是基于一小组较小的观察得出结论,以证实或反驳关于人口的信念。

在实践中,我们对感兴趣的变量(代表样本)进行一些测量,并检查我们的测量结果是否符合我们的假设(我们的信念)。基于观察我们拥有的样本的概率,我们决定是否可以相信自己的信念。

什么时候?

假设检验有许多实际应用。以下是说明上述 6 种测试何时适合的不同情况:

  1. 一个平均值:假设健康专家想要测试比利时成年人的平均体重是否不同于 80 kg (176.4 lbs)。
  2. 两个意思是:
  • 独立样本:假设物理治疗师想要通过测量对照组患者和治疗组患者的平均反应时间(以秒为单位)来测试新治疗的有效性,其中两组患者是不同的。
  • 成对样本:假设物理治疗师想要通过测量治疗前后的平均反应时间(以秒为单位)来测试新治疗的有效性,其中患者被测量两次——治疗前后,因此 2 个样本中的患者是相同的。

3.一个比例:假设一位政治评论家想要测试将投票给特定候选人的公民比例是否小于 30%。

4.两个比例:假设一个医生想测试职业运动员和业余运动员之间吸烟者的比例是否不同。

5.一个差异:假设一名工程师想要测试电压表的可变性是否低于安全标准规定的值。

6.两个差异:假设在一个工厂里,两条生产线相互独立工作。财务经理想要测试这两台机器的每周维护成本是否有相同的差异。请注意,对两个方差的测试也经常被用来验证方差相等的假设,这是其他几个统计测试所需要的,例如学生的 t 检验

当然,这只是一个潜在应用的非详尽列表,许多研究问题都可以通过假设检验得到解答。

需要记住的重要一点是,在假设检验中,我们总是对总体感兴趣,而不是样本。样本用于得出关于总体的结论,因此我们总是根据总体进行测试。

通常,假设检验用于回答验证性分析中的研究问题。验证性分析是指统计分析,其中假设(从理论中推导出来)是预先定义的(最好是在数据收集之前)。在这种方法中,研究人员对所考虑的变量有一个具体的想法,她试图看看她的想法,即假设,是否有数据支持。

另一方面,假设检验很少用于探索性分析。 2 探索性分析旨在揭示被调查变量之间可能的关系。在这种方法中,研究人员在收集数据之前没有任何明确的理论驱动的假设或想法。这就是探索性分析有时被称为假设生成分析的原因——它们被用来创建一些假设,这些假设反过来又可以在稍后阶段通过验证性分析进行测试。

怎么会?

据我所知,有 3 种不同的方法来进行假设检验:

尽管这三种方法的过程可能略有不同,但它们都得出完全相同的结论。因此,使用这种或那种方法往往是个人选择的问题,或者是上下文的问题。看这个部分来知道我根据上下文使用哪种方法。

我将在下面的章节中介绍这三种方法,从我认为最全面的手动方法开始:将测试统计数据与临界值进行比较。

对于这三种方法,我将从一般的角度解释执行假设检验所需的步骤,并用下面的情况来说明它们: 3

假设一名健康专家想要测试比利时成年人的平均体重是否不同于 80 kg。

注意,对于大多数假设检验,我们下面要用的例子需要一些假设。由于本文的目的是解释假设检验,我们假设所有的假设都满足。对于感兴趣的读者,请参见介绍单样本 t 检验的文章中关于这种假设检验的假设(以及如何验证它们)。

方法 A:将检验统计量与临界值进行比较

方法 A 包括将测试统计值与临界值进行比较,可归结为以下 4 个步骤:

  1. 陈述无效和替代假设
  2. 计算测试统计量
  3. 寻找临界值
  4. 总结并解释结果

下面详细介绍了每个步骤。

步骤 1:陈述无效假设和替代假设

如前所述,假设检验首先需要一个想法,即关于一种现象的假设。这种假设,称为假说,来源于理论和/或研究问题。

由于假设检验是用来证实或反驳先前的信念,我们需要制定我们的信念,这样就有一个无效假设和另一个假设。那些假设必须是互斥,这意味着它们不能同时为真。这是第一步。

在我们的场景中,无效假设和替代假设是:

  • 零假设 H0: μ=80
  • 替代假设 H1: μ≠80

在陈述无效假设和替代假设时,请记住以下两点:

  1. **我们总是对总体感兴趣,而不是样本。这就是为什么《H0 与 H1》总是根据总体而不是样本(在这种情况下,μ而不是 xbar)来编写。
  2. 我们想要测试的假设通常是另一个假设。如果研究人员想测试比利时成年人的平均体重是否低于 80 公斤,她会说 H0: μ=80(或者等价地,H0: μ≥80)和 H1: μ < 80。不要把零假设和替代假设混在一起,否则结论会截然相反!
  3. **零假设往往是现状。举个例子,假设一个医生想测试新的治疗方法 A 是否比旧的治疗方法 b 更有效率,现状是新的和旧的治疗方法同样有效率。假设值越大越好,那么她将写出 H0: μA=μB(或者等价地,H0:μA-μB = 0)和 H1: μA > μB(或者等价地,H0:μA-μB>0)。相反,如果越低越好,她会写出 H0: μA=μB(或者等价地,H0:μA-μB = 0)和 H1: μA < μB(或者等价地,H0:μA-μB<0)。

步骤 2:计算测试统计量

从某种意义上来说,检验统计量(通常称为 t-stat )是一种指标,表明观察值与零假设相比有多极端。t-stat(绝对值)越高,观察结果越极端。

有几种计算 t-stat 的公式,每种类型的假设检验都有一个公式—一个或两个均值、一个或两个比例、一个或两个方差。这意味着有一个公式来计算一个均值假设检验的 t-stat,另一个公式用于计算两个均值的检验,另一个公式用于计算一个比例的检验,等等。第二步的唯一困难是选择合适的配方。一旦你知道基于测试的类型应该使用哪个公式,你只需要简单地将它应用到数据中。对于感兴趣的读者,可以在这个闪亮的应用中看到计算最常见测试的 t-stat 的不同公式。

幸运的是,一个和两个均值的假设检验公式,以及一个和两个比例遵循相同的结构。计算这些测试的测试统计类似于缩放一个随机变量(该过程也称为“标准化”或“规范化”),即从该随机变量中减去平均值,并将结果除以标准偏差:

z =(Xμ)/σ

对于这 4 个假设检验(一/二均值和一/二比例),计算检验统计量就像缩放与感兴趣的参数(总体中)相对应的估计量(从样本计算)。所以我们基本上是从点估计量中减去目标参数,然后将结果除以标准差(相当于标准差,但对于一个估计量来说)。

如果这还不清楚,下面是在我们的场景中如何计算检验统计量(表示为 tobs )(假设总体的方差未知):

其中:

  • xbar 是样本平均值(即估计值)
  • μ是零假设下的平均值(即目标参数)
  • s 是样本标准偏差
  • n 是样本量
  • (s/√n 为标准误差)

请注意此测试统计的公式与用于标准化随机变量的公式之间的相似性。这种结构对于两个平均数的检验是相同的,一个比例和两个比例,除了估计量,参数和标准误差,当然,每种类型的检验略有不同。

假设我们的样本均值为 71 kg (xbar = 71),样本标准差为 13 kg (s = 13),样本量为 10 名成人(n = 10)。记住总体均值(零假设下的均值)是 80 kg (μ = 80)。

因此,t-stat 为:

尽管公式因测试的参数而异,但测试统计的值表明了我们的观察结果有多极端。

我们记住这个值-2.189,因为它将在第 4 步中再次使用。

第三步:寻找临界值

虽然 t-stat 给了我们观察结果有多极端的指示,但是我们不能仅仅根据它的值来判断这个“极端得分”是否太极端。因此,在这一点上,我们还不能断定我们的数据是否过于极端。为此,我们需要将我们的 t-stat 与一个阈值(称为临界值)进行比较,该阈值由概率分布表给出(当然,也可以通过 R 找到)。

同样,计算 t-stat 的公式对于每个感兴趣的参数是不同的,临界值所基于的基本概率分布(以及统计表)对于每个目标参数也是不同的。这意味着,除了选择合适的公式来计算 t-stat,我们还需要根据我们测试的参数选择合适的概率分布。

幸运的是,对于本文中涉及的 6 个假设检验,只有 4 种不同的概率分布(1/2 均值、1/2 比例和 1/2 方差):

  1. 标准正态分布:
  • 对已知总体方差的一个和两个均值进行检验
  • 对两个配对样本进行测试,其中两个样本之间的差异方差σ2D 已知
  • 对一个和两个比例进行测试(假设满足一些假设)

2.学生分布:

  • 未知总体方差的情况下对一个和两个均值进行测试**
  • 对两个配对样本进行测试,其中两个样本之间的差异的方差σ2D 未知

3.卡方分布:

  • 对一个方差的检验

4.费希尔分布:

  • 两个方差的检验

每个概率分布也有它自己的参数(这里考虑的 4 个分布有两个参数),定义它的形状和/或位置。概率分布的参数可以看作是它的 DNA 这意味着该分布完全由其参数定义。

以我们最初的场景为例,一名健康专家想要测试比利时成年人的平均体重是否不同于 80 kg。一个均值测试的潜在概率分布要么是标准正态分布,要么是学生分布,这取决于总体的方差(不是样本方差!)是已知还是未知: 6

  • 如果总体方差已知→使用标准正态分布
  • 如果人口方差ununknown→使用学生分布

如果没有明确给出总体方差,您可以假设它是未知的,因为您不能基于样本计算它。如果你能计算出来,那就意味着你能接触到整个群体,在这种情况下,进行假设检验是没有意义的(你可以简单地使用一些描述性统计数据来证实或反驳你的观点)。在我们的例子中,没有指定总体方差,所以假设它是未知的。因此,我们使用学生分布。

学生分布有一个定义它的参数;自由度的数量。自由度的数量取决于假设检验的类型。例如,一个平均值测试的自由度数等于观察数减一(n-1)。在不深入细节的情况下,-1 来自于这样一个事实,即有一个量是估计的(即平均值)。 7 在我们的示例中,样本大小等于 10,自由度等于 n-1 = 10-1 = 9。

找到临界值只缺少最后一个元素:显著性水平。用α表示的显著性水平是错误拒绝零假设的概率,因此拒绝零假设的概率虽然它实际上是真的。从这个意义上说,这是一个我们接受处理的错误(I 型错误,与 II 型错误 8 相对),以便能够根据一个子集得出关于总体的结论。

正如你可能在许多统计教科书中读到的,显著性水平通常被设置为 5%。 9 在某些领域(如医学或工程等),显著性水平有时也会设置为 1%,以降低错误率。最好在执行假设检验之前指定显著性水平,以避免根据结果设置显著性水平的诱惑(当结果处于显著边缘时,诱惑更大)。正如我经常告诉我的学生的,你不能“猜测”也不能计算显著性水平。因此,如果没有明确指定,您可以放心地假设它是 5%。在我们的例子中,我们没有指明,所以我们取α = 5% = 0.05。**

此外,在我们的示例中,我们想要测试比利时成年人的平均体重是否与 80 kg 不同。由于我们没有指定测试的方向,所以这是一个双边测试。如果我们想测试平均体重是小于 80 kg (H1: μ < 80)还是大于 80 kg (H1: μ > 80),我们会做一个单边测试。确保执行正确的测试(双面或单面),因为它会影响如何找到临界值(详见以下段落)。

现在我们已经知道了合适的分布(学生分布)、其参数(自由度(df) = 9)、显著性水平(α = 0.05)和方向(双边),我们已经得到了在统计表中找到临界值所需的所有信息:

作者图片

通过查看学生分布表中的行 df = 9 和列 t.025,我们发现临界值为:

有人可能想知道为什么我们取 tα/2=t.025,而不是 tα=t.05,因为显著性水平是 0.05。原因是我们做的是双边测试(H1: μ≠ 80),所以 0.05 的误差率必须除以 2 才能找到分布右边的临界值。由于学生的分布是对称的,所以分布左边的临界值简单来说就是:-2.262。

从视觉上看,0.05 的误差率分为两部分:

  • -2.262 左侧的 0.025,以及
  • 2.262 右侧的 0.025

作者的情节

我们记住第四步和最后一步的临界值-2.262 和 2.262。

请注意,上图中的红色阴影区域也称为拒绝区域。下一节将详细介绍这一点。

得益于qt()函数,这些临界值也可以在 R 中找到:

*qt(0.025, df = 9, lower.tail = TRUE)## [1] -2.262157qt(0.025, df = 9, lower.tail = FALSE)## [1] 2.262157*

qt()函数用于学生的分布(q代表分位数,t代表学生)。不同的发行版还附带了其他功能:

  • qnorm()为正态分布
  • qchisq()为卡方分布
  • qf()为费希尔分布

步骤 4:总结和解释结果

在第四步也是最后一步中,我们所要做的就是将测试统计量(在步骤#2 中计算)与临界值(在步骤#3 中找到)进行比较,以便结束假设检验

在进行假设检验时,只有两种可能性:

  1. 拒绝零假设
  2. 不拒绝零假设

在我们的成人体重示例中,请记住:

  • t-stat 是-2.189
  • 临界值为-2.262 和 2.262

还要记住:

  • 与零假设相比, t-stat 显示了我们的样本有多极端
  • 临界值是 t-stat 被视为也是极限*的阈值*

为了比较 t-stat 和临界值,我总是建议绘制它们:

作者的情节

这两个临界值构成了剔除区域(红色阴影区域):

  • 从-∞到-2.262,以及
  • 从 2.262 到

如果 t-stat 位于拒绝区域之一,我们拒绝零假设。相反,如果 **t-stat 不位于任何拒绝区域内,我们不拒绝零假设**。

从上图可以看出,t-stat 没有临界值那么极端,因此不在任何拒绝区域内。总之,我们不拒绝μ=80 的零假设。

这是统计学上的结论,但是如果没有适当的解释,这些结论是没有意义的。因此,在问题的上下文中解释结果也是一个很好的做法:

在 5%的显著性水平上,我们不拒绝比利时成年人平均体重为 80 kg 的假设。

我们为什么不接受 H0?

从更哲学(但仍然非常重要)的角度来看,注意我们写了“我们不拒绝零假设”和“我们不拒绝比利时成年人平均体重等于 80 kg 的假设”。我们没有写“我们接受零假设”,也没有写“比利时成年人的平均体重是 80 kg”。

原因在于,在假设检验中,我们根据样本得出一些关于总体的结论。因此,总有一些不确定性,我们不能 100%肯定我们的结论是正确的。

也许比利时成年人的平均体重实际上并不等于 80 公斤,但我们无法根据手头的数据证明这一点。可能的情况是,如果我们有更多的观察,我们会拒绝零假设(因为所有其他条件都相同,更大的样本量意味着更极端的 t-stat)。或者,即使有更多的观察,我们也不会拒绝零假设,因为比利时成年人的平均体重实际上接近 80 公斤。我们无法区分这两者。所以我们只能说,我们没有找到足够的证据来反对比利时成年人平均体重为 80 公斤的假设,但我们并没有得出平均值等于 80 公斤的结论。

如果您仍然不清楚其中的区别,下面的例子可能会有所帮助。假设一个人涉嫌犯罪。这个人要么是无辜的——零假设——要么是有罪的——另一个假设。为了知道嫌疑犯是否犯了罪,警察收集尽可能多的信息和证据。这类似于研究者收集数据形成样本。然后法官根据收集到的证据,决定嫌疑人是无罪还是有罪。如果有足够的证据证明嫌疑犯犯了罪,法官就会断定嫌疑犯有罪。换句话说,她会拒绝嫌疑人无罪的无效假设,因为有足够的证据表明嫌疑人犯了罪。这类似于 t-stat 比临界值更极端:我们有足够的信息(基于样本)来说零假设不太可能,因为如果零假设为真,我们的数据就会太极端。由于样本不可能是“错误的”(它对应于收集的数据),唯一剩下的可能性是零假设事实上是错误的。这就是我们写“我们拒绝零假设”的原因。

另一方面,如果没有足够的证据证明嫌疑人犯了罪(或者根本没有证据),法官就会认定嫌疑人无罪。换句话说,她不会拒绝嫌疑人无罪的无效假设。但即使她得出结论认为嫌疑人无罪,她也永远不会 100%确定他真的是无辜的。可能的情况是:

  1. 嫌疑人没有犯罪,或者
  2. 嫌疑犯犯了罪,但是警察不能收集足够的关于嫌疑犯的信息。

在前一种情况下,嫌疑人确实是无辜的,而在后一种情况下,嫌疑人是有罪的,但警察和法官未能证明这一点,因为他们没有找到足够的证据来指控他。类似于假设检验,法官不得不通过认为嫌疑人无罪来结束案件,而不能区分两者。

这是我们写“我们不拒绝零假设”或“我们未能拒绝零假设”(你甚至可能在一些教科书中读到诸如“数据中没有足够的证据来拒绝零假设”的结论)的主要原因,我们不写“我们接受零假设”。

我希望这个比喻能帮助你理解我们拒绝零假设而不是接受它的原因。

在下面的章节中,我们将介绍假设检验中使用的另外两种方法。这些方法都会得出完全相同的结论:不拒绝零假设,即我们不拒绝比利时成年人平均体重为 80 kg 的假设。因此,只有当您更喜欢使用这些方法而不是第一种方法时,才会显示它。

方法 B:比较 p 值和显著性水平α

方法 B 包括计算 p 值并将该 p 值与显著性水平α进行比较,归结为以下 4 个步骤:

  1. 陈述无效和替代假设
  2. 计算测试统计量
  3. 计算p-值**
  4. 总结并解释结果

在使用 p 值的第二种方法中,第一步和第二步与第一种方法相似。

步骤 1:陈述无效假设和替代假设

无效假设和替代假设保持不变:

  • H0: μ=80
  • H1: μ≠80

步骤 2:计算测试统计量

请记住,t-stat 的公式根据假设检验的类型而不同(一个或两个均值、一个或两个比例、一个或两个方差)。在方差未知的一个均值的情况下,我们有:

步骤 3:计算 p 值

**p-值是观察到一个样本的概率(因此它从 0 到 1)至少与我们在零假设为真的情况下观察到的样本一样极端。在某种意义上,它给了你一个关于你的零假设有多可能**的提示。它也被定义为数据表明拒绝零假设的最小显著性水平。

有关 p 值的更多信息,我推荐阅读关于 p 值和显著性水平α 的注释。

形式上,p-值是超出测试统计的面积。由于我们正在进行双边测试,因此p-值是高于 2.189 和低于-2.189 的面积之和。

从视觉上看,p-值是下图中两个蓝色阴影区域的总和:

作者的情节

使用pt()函数可以计算出精度为 R 的 p 值:

*p_val <- pt(-2.189, df = 9, lower.tail = TRUE) + pt(2.189, df = 9, lower.tail = FALSE)
p_val## [1] 0.05634202# which is equivalent than:
p_val <- 2 * pt(2.189, df = 9, lower.tail = FALSE)
p_val## [1] 0.05634202*

p 值为 0.0563,这表明有 5.63%的机会观察到一个样本至少与零假设为真时观察到的样本一样极端。这已经给了我们 t-stat 是否太极端的提示(以及我们的零假设是否可能),但是我们在第 4 步正式结束。

qt()函数求临界值一样,我们用pt()p-值,因为底层分布是学生分布。分别使用pnorm()pchisq()pf()表示正态分布、卡方分布和费希尔分布。另请参见这个闪亮的应用程序来计算p-对于大多数概率分布,给定某个 t-stat 的值。

如果你不能使用电脑(例如在考试期间),你将不能精确地计算 p 值,但是你可以使用参照你的测试的统计表来限制它。在我们的例子中,我们使用学生分布,并查看行 df = 9(因为 df = n- 1):

作者图片

  1. 检验统计量是-2.189
  2. 我们取绝对值,得到 2.189
  3. 值 2.189 介于 1.833 和 2.262 之间(在上表中以蓝色突出显示)
  4. 从与 1.833 和 2.262 相关的列名 t.050 和 t.025 中,我们知道:
  • 1.833 右边的面积是 0.05
  • 2.262 右边的面积是 0.025

5.所以我们知道 2.189 右边的面积一定在 0.025 和 0.05 之间

6.由于学生分布是对称的,我们知道-2.189 左边的面积也一定在 0.025 和 0.05 之间

7.因此,两个面积之和必须在 0.05 和 0.10 之间

8.换句话说,p-值介于 0.05 和 0.10 之间(即 0.05<p-值< 0.10)

虽然我们不能精确地计算它,但它足以在最后一步完成我们的假设检验。

步骤 4:总结和解释结果

最后一步是简单地将p-值(在步骤#3 中计算)与显著性水平α进行比较。对于所有的统计测试:

  • 如果p-值小于α(p-值< 0.05) → H0 不太可能→我们拒绝*零假设*
  • 如果p-值大于或等于α(p-值≥ 0.05) → H0 很可能→我们做不拒绝*零假设*

无论我们考虑精确的p-值(即 0.0563)还是有界的(0.05<p-值< 0.10),它都大于 0.05,所以我们不拒绝零假设。在这个问题的背景下,我们不拒绝比利时成年人平均体重为 80 公斤的无效假设。

请记住,当p-值低于(等于或大于)α(方法 B)时,使用临界值方法(方法 A)拒绝(或不拒绝)显著性水平为α的零假设相当于拒绝(或不拒绝)零假设。这就是我们发现与方法 A 完全相同的结论的原因,也是为什么如果你在相同的数据上使用两种方法,并且具有相同的显著性水平,你也应该得到相同的结论。

方法 C:将目标参数与置信区间进行比较

方法 C 包括计算置信区间并将该置信区间与目标参数(零假设下的参数)进行比较,归结为以下 3 个步骤:

  1. 陈述无效和替代假设
  2. 计算置信区间
  3. 总结并解释结果

在使用置信区间的最后一种方法中,第一步与前两种方法相似。

步骤 1:陈述无效假设和替代假设

无效假设和替代假设保持不变:

  • H0: μ=80
  • H1: μ≠80

步骤 2:计算置信区间

像假设检验一样,置信区间是推断统计学中一个众所周知的工具。

置信区间是一个估计过程,它产生一个区间(即一个数值范围),包含具有某个* —通常是高的— 概率的真实参数。*

在计算检验统计量时,每种假设检验都有一个公式,同样,每种置信区间也有一个公式。不同类型的置信区间的公式可以在这个闪亮的应用中找到。

以下是一个均值μ的置信区间公式(未知总体方差):

其中,tα/2,n1 可在学生分布表中找到(类似于方法 A 的步骤 3 中找到的临界值)。

给定我们的数据,α = 0.05,我们有:

μ的 95%置信区间为[61.70;80.30] kg。但是95%的置信区间意味着什么?

我们知道,这个估计过程有 95%的概率产生一个包含真均值μ的区间。换句话说,如果我们构造许多置信区间(用相同大小的不同样本),平均起来,其中 95%的区间会包含总体的均值(真参数)。所以平均来说,这些置信区间的 5%不会覆盖真实均值。

如果希望降低最后一个百分比,可以降低显著性水平(例如,设置α = 0.01 或 0.02)。在其他条件相同的情况下,这将增加置信区间的范围,从而增加包含真实参数的概率。

步骤 3:总结和解释结果

最后一步只是将置信区间(在步骤#2 中构建)与目标参数值(在步骤#1 中提到的零假设下的值)进行比较:

  • 如果置信区间不包含假设值→ H0 不太可能→我们拒绝零假设
  • 如果置信区间包含假设值→ H0 是可能的→我们不拒绝零假设

在我们的例子中:

  • 假设值是 80(因为 H0: μ = 80)
  • 80 包含在 95%的置信区间内,因为它从 61.70 到 80.30 千克
  • 所以我们不拒绝零假设

就问题而言,我们并不排斥比利时成年人平均体重为 80 kg 的假设。

如你所见,结论与临界值法(方法 A)和p-值法(方法 B)是等效的。同样,这是必须的,因为我们对所有三种方法使用相同的数据和相同的显著性水平α。

选择哪种方法?

所有这三种方法都给出了相同的结论。然而,每种方法都有自己的优势,所以我通常会根据情况选择最方便的方法:

  • 方法 A(将测试统计值与临界值进行比较):在我看来,当我无法访问 r 时,这是三种方法中最简单明了的方法。
  • 方法 B(将p-值与显著性水平α进行比较):除了能够知道零假设是否被拒绝之外,计算**确切的p-值可能非常方便**,所以如果我可以访问 r,我倾向于使用这种方法
  • 方法 C(将目标参数与置信区间进行比较):如果我需要测试几个假设值,我倾向于选择这种方法,因为我可以构建一个单一的置信区间,并将其与我想要的多个值进行比较。比如用我们 95%的置信区间[61.70;80.30],我知道任何低于 61.70 kg 和高于 80.30 kg 的值都会被拒绝,不用对每个值进行测试。

摘要

在本文中,我们回顾了使用假设检验时的目标。然后我们通过三种不同的方法(A. 临界值,b .p-值和 C. 置信区间)向展示了如何手工进行假设检验。我们还展示了如何在初始问题的背景下解释结果

虽然当使用相同的数据和相同的显著性水平时,所有三种方法给出了完全相同的结论(否则在某个地方会有错误),但当谈到选择一种方法而不是另外两种方法时,我也提出了我个人的偏好

感谢阅读。我希望这篇文章能帮助你理解一个假设的结构。我提醒你,至少对于本文中的 6 个假设检验,公式是不同的,但是其背后的结构和推理是相同的。所以你基本上要知道要用哪些公式,简单的按照本文提到的步骤去做。

对于感兴趣的读者,我创建了两个附带的闪亮应用程序:

  1. 假设测试和置信区间:输入数据后,应用程序会显示所有步骤,以结束测试并计算置信区间。更多信息请参见本文中的
  2. 如何阅读统计表:该应用程序帮助你计算出大多数概率分布的 t-stat 下的p-值。更多信息请参见本文部分。

和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。

  1. 假设一名研究人员想测试比利时女性是否比法国女性高。假设一位健康专家想知道运动员和非运动员中吸烟者的比例是否不同。测量所有比利时和法国女性的身高,询问所有运动员和非运动员的吸烟习惯,要花太多时间。所以大多数时候,决策是基于人口的代表性样本,而不是整个人口。如果我们能在一个合理的时间框架内测量整个人口,我们就不会做任何推断性的统计。 ↩︎
  2. 不要误解我,这并不意味着假设检验在探索性分析中从不使用。它只是在探索性研究中比在验证性研究中少得多。 ↩︎
  3. 你可能会在其他文章或教材中看到或多或少的步骤,取决于这些步骤是详细还是简洁。然而,假设检验应该遵循相同的过程,不管步骤有多少。 ↩︎
  4. 对于单侧检验,写 H0: μ=80 或 H0: μ≥80 都是正确的。关键是无效假设和替代假设必须是互斥的,因为你是在用一个假设来检验另一个假设,所以两者不可能同时为真。 ↩︎
  5. 为了完整起见,每种类型的测试中甚至有不同的公式,这取决于是否满足某些假设。对于感兴趣的读者来说,可以看到所有不同的场景,以及在上测试一表示和在上测试二表示的不同公式。 ↩︎
  6. 总体方差未知时比已知时有更多的不确定性,通过使用学生分布而不是标准正态分布来考虑这种更大的不确定性。还要注意,随着样本量的增加,学生分布的自由度增加,两个分布变得越来越相似。对于大样本量(通常从 n> 30),学生分布变得非常接近标准正态分布,即使总体方差未知,也可以使用标准正态分布。 ↩︎
  7. 对于两个独立样本的测试,自由度为 n1+n2-2,其中 n1 和 N2 分别是第一个和第二个样本的大小。请注意-2,因为在这种情况下,估计了两个量。 ↩︎
  8. 第二类误差是不拒绝零假设的概率,尽管它实际上是假的。 ↩︎
  9. 这是一个好的还是坏的标准,这是一个经常出现的问题,也是有争议的。然而,这超出了本文的范围。 ↩︎
  10. 同样,p-通过统计表或通过 R 找到的值必须是一致的。 ↩︎

相关文章

原载于 2021 年 1 月 27 日 https://statsandr.com*https://statsandr.com/blog/hypothesis-test-by-hand/。***

假设检验

原文:https://towardsdatascience.com/hypothesis-testing-a23852264d09?source=collection_archive---------14-----------------------

Unsplash 上拍摄的 ThisisEngineering RAEng

它是什么以及如何在 Python 中实现它

为什么相关?

假设是我们想要检验的主张或前提。假设检验是一种用数据支持你的结论的方式,一种更“科学”的方式。它不仅对科学家有用,实际上在很多领域都很重要,从营销网页设计药物试验等等。因为它非常有用,并且基于基本的统计概念,所以学习何时应用最典型的测试将提高您的数据科学技能,即使您不是数据科学家,但仍然以某种方式处理数据。在本文中,我们试图解释最常见的假设检验的用处以及何时使用它们。它以一个 Python 代码说明如何在数据科学项目中执行测试作为结束。

这是什么?

那么,什么是统计假设呢?使用数据可以对假设进行测试。例如,如果你认为你的电子商务中的“加入购物车”按钮应该是红色而不是蓝色,因为这会让人们买得更多,你可以制定以下假设:“红色按钮会比蓝色按钮产生更多的销售”。

现在,你如何测试呢?最“显而易见”的方法是创建网站的两个版本,运行一段时间,随机分配用户给其中一个,然后看看哪个能产生更多的销售。如果“蓝色”版本在一个月内产生 100 万美元,而“红色”版本产生 1000 万美元,你得到了你的答案,对不对?如果“红色”版本产生 200 万美元呢?如果它能产生 100 万美元 1 美分呢?什么时候差异大到足够显著?这种方法的问题在于,当我们处理随机性时,它没有考虑到自然的可变性。另一方面,假设检验不仅考虑了随机性,还考虑了我们希望自己的结论有多可信。

因此,假设检验是一个程序,通过它我们可以评估我们结论的合理性,不仅使用我们的样本数据,而且知道我们愿意冒多大的风险,以及在这个过程中我们可能遇到的错误类型。

它是如何工作的?

零假设与替代假设

零假设是被普遍接受的默认主张、前提、值或参数。替代假设是一个研究或调查假设,包括要测试的主张,如果被证明为真,它有望取代原假设。下面的各种测试有助于确定样本数据中的信息可以在多大程度上推断出它所来自的人群。

在我们上面的例子中,零假设是两种颜色没有区别,而另一个假设是它们有区别(或者,更具体地说,红色按钮比蓝色按钮产生更多的销售)。

典型测试(以及何时使用)

学生的 t 检验

这是一种有用的测试类型,用于比较数据集中两组之间的一个数字特征(如身高或体重)。它通过产生 p 值来确定两组的平均值之间是否存在显著差异,这将告诉您如果在总体水平上没有差异(您的零假设),这两个样本组之间在样本中观察到的差异发生的可能性有多大。如果 p 值小于某个阈值(通常为 0.05),那么两组受试者之间存在显著的统计学差异。

t 检验的一个重要问题是,它假设两组的正态分布和方差相等。好的,但是我怎么知道我的分布是否正常呢?比如夏皮罗-维尔克测试。

夏皮罗-威尔克

以萨缪尔·桑福德·夏皮罗和马丁·维尔克命名的夏皮罗-维尔克检验通常用于检验频率统计中的正态性。当你想判断一个随机样本是否来自正态分布时,你可以使用它。测试返回的 W 值越小,您就越确信样本不是正态分布的。这个结果会导致你最初提出的零假设被拒绝。你也可以从 p 值的角度来考虑这个问题:当它小于或等于某个阈值(通常为 0.05)时,你就可以拒绝零假设。

对,但是如果我的分布不正常呢?我就是没法比较?你可以,但这次要用曼-惠特尼检验。

曼-惠特尼试验

这在统计学中也被称为曼-惠特尼 U 检验。当您想要查看两个独立组之间的差异时,尤其是当因变量是有序或连续的,但不是正态分布时,该测试变得非常有用。

我们看到的比较组的两种类型的测试都是通过使用两个组来完成的,但是如果我们有两个以上的组呢?

方差分析

当我们想要比较一个数据集中的多个类别时,方差分析测试变得很方便。ANOVA(有时称为方差分析)在同时测试两个以上类别中数字变量的差异时特别有用。方差分析还依赖于 3 个主要假设:样本是独立的,来自一个正常 分布的总体,并且具有相同的方差

但是如果你的两个变量都是分类的,并且你想检查它们的行为是否像它们是独立的呢?然后对你的数据进行皮尔森卡方检验。

皮尔逊卡方检验

这在处理分类变量时很有用,可以看出如果这些变量是独立的,观察数据分布的可能性有多大。例如,假设你想知道作为一个男人或女人,你更有可能还是更不可能成为一个吸烟者。如果这两个变量是独立的,你可以预期吸烟者和不吸烟者的男女比例是一样的。皮尔森的卡方检验将告诉你,你有多确信有这样的差异,或者没有。

使用 Python 的实际例子

我们将使用包含黑色星期五销售信息的数据集,并运行我们刚刚看到的测试(完整代码可在此处获得)。原始数据集在这里是可用的,每个订单有一行,但是我们已经将其更改为每个客户有一行,以使我们的一些分析更加直观。

然后,我们的最终数据集包含客户的性别、婚姻状况、职业、城市和购买金额等信息。

首先,让我们从 scipy 库中装入测试所需的所有函数(每个测试一个函数):

**[IN]:**
from scipy.stats import ttest_ind, shapiro, mannwhitneyu, f_oneway, chi2_contingency

接下来,我们将定义我们的 p 值阈值(0.05),并创建一个函数来确定我们是否应该拒绝零假设:

**[IN]:**
def test_result(p, ref_pvalue=0.05): if p<ref_pvalue: result=”Reject null hypothesis” else: result=”Don’t reject null hypothesis” return result

为什么我们总是选择 0.05 作为 p 值的阈值?这主要是一种约定,可能取决于你工作的领域(市场营销、生物统计学等)。)阈值越小,当你决定拒绝零假设时,你就越有信心,但你拒绝的频率就越低。

现在,假设我们想回答一个非常基本的问题:男人和女人花的钱一样多吗?起初,这看起来像是 t-test 的工作,所以让我们试一试:

**[IN]:**men = df[df['Gender']=='M']women = df[df['Gender']=='F']ttest_results = ttest_ind(men['Purchase'], women['Purchase'])print('T-test result: {}'.format(test_result(ttest_results[1])))**[OUT]:**T-test result: Reject null hypothesis

这里的零假设是,男性和女性的平均购买价值是相同的,因此拒绝它意味着这些价值之间可能存在差异。然而,在运行我们的测试之前,我们似乎忘记了检查一个非常重要的假设:那些样本是否正态分布?为了验证这一点,我们将看看我们数据的分布,然后运行夏皮罗-维尔克测试:

按性别分列的购买价值分布。图片作者。

观察男性和女性购买价值的分布,我们可以看出这可能不是正态分布,因为它有很高的偏斜度(不对称)。不过,让我们进行测试,看看我们的直觉是否正确:

**[IN]:**shapiro_results_men = shapiro(men['Purchase'])print('Shapiro-wilk test results for men: {}'.format( test_result(shapiro_results_men[1])) )shapiro_results_women = shapiro(women['Purchase'])print('Shapiro-wilk test results for women: {}'.format( test_result(shapiro_results_women[1])) )**[OUT]:**Shapiro-wilk test results for men: Reject null hypothesisShapiro-wilk test results for women: Reject null hypothesis

这里,拒绝零假设意味着拒绝观测值正态分布的假设。所以,事实上,我们之前的 t 检验结果是无效的。相反,我们应该尝试一个曼-惠特尼检验:

**[IN]:**mannwhitney_results = mannwhitneyu(men['Purchase'],women['Purchase'])print('Mann-Whitney test results: {}'.format(test_result(mannwhitney_results[1])))**[OUT]:**Mann-Whitney test results: Reject null hypothesis

同样,我们拒绝样本均值之间没有差异的假设(但这一次,使用适当的检验)。

现在,让我们尝试回答一个不同的问题:不同城市类别的购买价值是否存在差异?这一次,有 3 个不同的类别,所以 t 检验或曼-惠特尼都不行。相反,我们可以使用 ANOVA ,同样需要正态分布。有一个聪明的技巧可以让我们的数据更接近正态分布:使用对数变换。在运行方差分析测试之前,我们将在这里使用这个技巧。

**[IN]**:a = df[df['City_Category']=='A']b = df[df['City_Category']=='B']c = df[df['City_Category']=='C']a['Purchase'] = a['Purchase'].apply(lambda x: np.log(x))b['Purchase'] = b['Purchase'].apply(lambda x: np.log(x))c['Purchase'] = c['Purchase'].apply(lambda x: np.log(x))anova_results = f_oneway(a['Purchase'], b['Purchase'], c['Purchase'])print('ANOVA test results: {}'.format(test_result(anova_results[1])))**[OUT]:**ANOVA test results: Reject null hypothesis

同样,我们拒绝零假设,即我们的城市类别之间没有差异。

现在,到最后一个问题,这次涉及两个分类变量:婚姻状况和职业相关吗?这次不是比手段,而是比频率。因此,首先我们创建一个列联表来计算职业和婚姻状况的所有组合的频率,然后我们运行我们的测试:

**[IN]:**contingency_table = pd.crosstab(df['Marital_Status'],df['Occupation'])chisquare_results = chi2_contingency(contingency_table)print('Chi-squared contingency test results: {}'.format(test_result(chisquare_results[1]))) **[OUT]:**Chi-squared contingency test results: Don't reject null hypothesis

这一次,我们没有拒绝零假设,这意味着没有理由相信婚姻状况和职业之间存在某种依赖关系:他们的行为或多或少像是独立的。

请注意我们没有在代码中验证我们测试所需的所有假设。目标是展示如何在 Python 中执行它们以及如何解释它们的结果。找到一个数据集的变量同时满足所有测试的标准是不切实际的。然而在现实中,你应该总是在运行你的测试之前验证那些假设是否成立

更进一步

统计学中有许多假设检验,这个列表远远没有包括所有的假设检验。然而,这些测试是最常用的,应该覆盖最基本的用例。如果你想了解更多关于假设检验或应用统计学的知识,一本关于这个主题的好书是《数据科学家实用统计学》。另一个深入研究统计学的好资源是 LearnMore365(尽管他们的课程通常不是免费的)。这篇关于莱尔德的文章详细介绍了曼-惠特尼检验。

大多数测试对数据做出某种假设,所以请仔细阅读这些假设是什么以及如何验证它们(通常可以在 Python 函数文档中找到)。

如果你喜欢阅读应用统计学,你可能会喜欢这篇文章:

这篇文章是由亚瑟·梅洛和金斯利·埃塞格贝撰写的。

如果你想进一步讨论,请随时联系 LinkedIn 上的 Arthur 或 Kingsley。

A/B 检验的假设检验:推断统计学的应用

原文:https://towardsdatascience.com/hypothesis-testing-for-a-b-test-an-application-of-inferential-statistics-5ae2e779ff04?source=collection_archive---------5-----------------------

为什么描述性统计可能不足以解释 A/B 测试结果

为什么我们需要推断统计学(例如假设检验)来进行数据分析?为什么我们不直接计算两组的差异来知道哪一组表现更好呢?

我们来举个例子:我们想探究在送货中对司机应用某种待遇是否能更好地提高他们的绩效。但是,如果我们只比较上个月的表现(治疗前)和本月的表现(治疗后),数据集中会有太多的噪声,例如本月的雨季会影响驾驶员的表现。因此,我们将这组驾驶员随机分成两组(对照组和实验组)以隔离治疗的效果,并在相同的时间段内应用治疗。

接受治疗后,我们想比较两组的表现,是否接受治疗的实验组在接受治疗后表现更好。然而,我们看到的只是 1.3%的微小差异。此外,与治疗前相比,差异仅增加了+0.8%。我们能自信地断定治疗是有效的吗?

示例用例(虚拟数据)

什么是 A/B 测试?

在一家技术公司,执行 A/B 测试是一种常用的方法,用来确定某项治疗是否能有效地给我们带来想要的结果。经验法则如下:

  1. 将目标人群分为两组:对照组(不治疗)和实验组(接受治疗)
  2. 确定我们想要测量的性能指标,以及期望的结果是什么(通过治疗,我们应该期望实验组比对照组表现得更好)
  3. 确保对照组和实验组在治疗前有相同的表现
  4. 应用治疗一段时间
  5. 评估结果,实验组是否比控制组表现更好

图示 A/B 测试,A 组和 B 组给予不同的待遇(图片由作者提供)

A/B 测试的实验设计允许我们隔离外部因素,治疗是影响两组之间表现差异的唯一因素。因此,我们知道如果一组比另一组表现好,那是由于治疗。

我应该选择哪种假设检验?

为了比较控制组和实验组之间的表现,有各种类型的假设检验,我们需要选择一种来获得正确的 P 值。对于 A/B 检验,我们应该使用非配对的两样本检验,因为:

  1. 我们要比较两个样本或两组(对照组和实验组)。
  2. 我们要比较的是对照组和实验组治疗后的差异(非配对或非独立),而不是治疗前和治疗后的差异(配对或非独立)。

如果样本服从正态分布,我们可以使用参数检验,否则我们使用非参数检验。假设检验的更多类型和细节将在下面的文章中解释:

https://www.kdnuggets.com/2021/09/hypothesis-testing-explained.html

评估 A/B 测试的结果

要自信地总结控制组和实验组之间的显著差异,需要评估以下几点:

  1. 预处理期:确保在进行处理之前,两个对照&实验组的表现相同
  2. 后处理期:证明 if 实验组是否比对照组表现更好(表现显著更高)的假设

对于下面的例子,我们可以对治疗前和治疗后进行假设检验,以确定控制组和实验组的驾驶员是否有明显不同的表现。常用的置信度为 95%(α= 0.05)。

A/B 测试结果评估(虚拟数据)

结果解释如下:
1。在预处理期间,我们有 95%的把握认为控制&实验组的驾驶员在表现上没有显著差异,因此不应该有偏差。如果在治疗前他们已经有不同的表现,我们需要重新分组。

2.在后治疗期间,我们有 95%的把握认为,与对照组相比,实验组的驾驶员具有显著更高的表现。因此,我们可以有把握地得出结论,这种治疗在提高驾驶员的表现分数方面是有效的。

顺便提一下,我们还可以检测到治疗前和治疗后期间的增加或减少(两组都从约 87%到约 92%),这是由外部因素引起的。如果我们直接将治疗应用于 100%的目标人群,而不将其分成两组,我们的分析就会有偏差。通过将目标人群分为对照组和实验组,我们可以将治疗效果与任何外部因素隔离开来。

通过对 A/B 测试应用假设检验,我们不仅仅基于绩效得分均值的差异来评估结果。假设检验允许我们评估其他参数,如样本数量(两组可能有不同的样本大小)、方差或标准差等。

数据科学家的假设检验

原文:https://towardsdatascience.com/hypothesis-testing-for-data-scientists-everything-you-need-to-know-8c36ddde4cd2?source=collection_archive---------2-----------------------

频繁主义者的方法

安娜·涅克拉舍维奇摄于佩克斯

假设检验是研究和数据科学中常用的统计工具,用于支持研究结果的确定性。测试的目的是回答在给定随机数据样本的情况下,偶然检测到明显效应的可能性有多大。本文以商业领域的问题为例,详细解释了频繁假设检验中的关键概念。

什么是假设?

假设通常被描述为对特定参数或总体的“有根据的猜测”。一旦它被定义,人们可以收集数据来确定它是否提供了足够的证据来证明假设是正确的。

假设检验

在假设检验中,对关于参数或总体(假设)的两个互斥的陈述进行评估,以决定哪一个陈述最能得到样本数据的支持。

参数和统计

在统计学中,参数是对总体的描述,而统计量描述的是总体的一小部分(样本)。例如,如果你问你班上的每个人(人群)的平均身高,你会得到一个参数,一个关于人群的真实描述,因为每个人都被问过。如果您现在想使用从您的班级(样本)获得的信息来猜测您的年级(人群)中的人的平均身高,这些信息会变成一个统计数据。

包含特定参数的假设检验称为参数检验。在参数测试中,假设人口具有正态分布(例如,一个班级中人的身高)。

非参数测试

相比之下,非参数检验(也称无分布检验)用于不能假设总体参数呈正态分布的情况。例如,钻石的价格似乎呈指数分布(右下)。非参数化并不意味着你对一个群体一无所知,而是它不是正态分布的。

左图:正态分布数据示例。右图:非正态数据分布的例子。图片作者。

为了简单起见,我将在下面集中讨论参数测试,如果不能假设正态分布,还会提到在哪里进一步研究。

现实世界的例子

解释假设检验的一个常用例子是公平硬币的例子。这是一个很好的解释测试基本概念的方法,但也很抽象。人们可以自问的商业假设的更具体的例子是:

假设 1

参数 : 平均订单值

测试类型 : 单样本、参数测试(假设订单值服从正态分布)

— — — — — — — — — — — — — — — — — — — — — — — — — —

假设二 : 投资 A 比投资 B 带来更高的回报

参数 : 平均收益差

检验类型 : 双样本,参数检验,也称 AB 检验(假设回报服从正态分布)

— — — — — — — — — — — — — — — — — — — — — — — — — —

假设 3 : 新的用户界面将比预期多 30%的用户转化为客户

参数 :

检验类型 : 单样本、非参数检验(假设客户数量不呈正态分布)

单样本、双样本或多样本测试

在检验假设时,要区分单样本、双样本或多样本检验。这不要与单面和双面测试混淆,我们将在后面介绍。在单样本测试中,将样本(今年的平均订单值)与已知值(去年的平均订单值)进行比较。在双样本测试中,两个样本(投资 A 和 B)相互比较。

假设检验的基本步骤

几个步骤被用来测试一个假设和验证它的重要性。在下面,我将详细解释每个步骤,并将使用上面的例子来解释所有的概念。

1。空&替代假设

备选项 假设是引言中提到的关于一个参数或总体的两个互斥的陈述。零假设(通常缩写为 H0)声称没有影响或没有差异。另一个假设(通常缩写为 H1 或哈)是你想要证明的。使用上面的一个例子:

H0:A 和 B 的平均收益没有差别,或者 A 和 B 的差别为零。

H1:A 和 B 的平均收益有差异或者 A 和 B 的差异>零。

单边和双边(单边和双边)测试

上面的示例假设描述了所谓的双尾检验。在双尾测试中,你在两个方向上测试,这意味着测试来自 A 的平均回报是否显著大于和显著小于来自 b 的平均回报。

在一个单尾测试中,你在一个方向测试,这意味着要么测试来自 A 的平均回报显著大于要么显著小于来自 b 的平均回报。在这种情况下,替代假设将变为:**

H1:A 的平均收益大于 b 的平均收益**

H1:A 的平均收益低于 b 的平均收益

2.选择合适的检验统计量

为了测试你的主张,你需要决定正确的测试测试统计。经常讨论的检验是 t 检验、z 检验或 f 检验,它们都假设正态分布。然而,在商业中,通常不能假设正态分布。因此,我将简要解释你需要知道的主要概念,以便为你的假设找到合适的测试。

测试统计

参数或非参数测试,每个测试都有一个测试统计量。检验统计是样本的数字汇总。它是一个随机变量,因为它是从一个随机样本中导出的。在假设检验中,它将样本统计量与零假设的预期结果进行比较。检验统计的选择取决于:

  • 参数与非参数
  • 样本数量(一个、两个、多个)
  • 离散变量(如客户数量)或连续变量(如订单价值)

让我们假设你的网上商店的平均订单价值 AOV 曾经是 20 美元。在雇佣了一个有潜力的新网页设计师后,AOV 涨到了 22 美元。您想要测试平均 AOV 是否显著增加:

参数:表示 AOV* ( 连续变量假设正态分布)*

样本统计: $22 ( 一个样本)

期望值: $20

测试统计: t 值

测试:单样本 t 检验**

3。选择适当的显著性水平

在检验假设时,我们不能总是对整个人口进行检验,而只能对随机选择的数据样本进行检验。因此,我们能说我们的结论对总体来说总是 100%正确吗?不完全是。我们会犯两种错误:

第一类错误:当原假设为真时拒绝原假设。

第二类错误:当零假设为假时接受零假设。

Alpha 是第一类错误的概率,以及当零假设为真时拒绝零假设而出错的几率。阿尔法值越低越好。因此,它被用作决策的门槛。在开始假设检验之前,你通常会选择一个你愿意接受的误差水平。例如,当你拒绝零假设时,你愿意接受 5%的错误概率。**

但是,我不是总想 100%的自信自己没有犯错,所以 alpha = 0%吗?

测试的功效

是的,这就是问题所在。因为除了α,我们还有β,第二类错误的概率。1-β是不犯第二类错误的概率,定义为测试的功效。β越低,功率越高。很自然,您希望尽可能降低这两个误差。然而,重要的是要注意到这两个错误在某种程度上是相互抵消的:假设你想要最小化错误 I 或者当它为真时拒绝零假设的错误。那么,最简单的方法就是永远接受它。但是这将直接对抗第二类错误,即当它不为真时接受它。**

因此,常用的显著性(alpha)水平 0.01、0.05 或 0.10 是一个很好的平衡,应在数据收集前确定。请注意,在双尾测试中,alpha 水平被分成两半,并应用于统计数据的采样分布的两侧。

左图:仅在一侧有拒绝区域的采样分布示例。右图:两侧都有拒绝区域的抽样分布示例。图片作者。

4.数据收集

为了进行假设检验,我们需要一部分真正感兴趣的人群,一个随机样本。应随机选择样本,以避免任何偏差或不良影响。

关于最佳样本量的问题并不容易回答。一般来说,可以肯定地说:数据越多越好。但是,在有些情况下,由于预算或时间限制或者只是数据的性质,这很难实现。有几个公式可以帮助找到正确的样本量:

  • 科克伦样本容量公式
  • 斯洛文思公式

此外,一些检验可以使用小样本量,例如 t 检验或非参数检验,它们通常需要较少的样本量,因为它们不需要正态分布。

双样本或多样本测试中的样本量

进行双样本或多样本测试时,请注意您选择的测试可能需要相似的样本量,除非它对不同的样本量具有稳健性。例如,像 t-检验这样的检验可能不再合适,因为不相等的样本大小会影响类型 1 误差。在这种情况下,最好寻找一个稳健的替代方案(如韦尔奇的 t 检验)。

5。测试统计和 p 值的计算

一旦收集了数据,就可以计算所选的检验统计量和相应的 p 值。这两个值都可以用来对推断做出最终决定,并从测试统计的概率分布中检索(也称为抽样分布)。

如何计算检验统计量?

您可以使用公式(可以在网上找到)传统地计算测试统计,或者通过统计软件如 SPSS 或使用 R/python。对于我们之前的一个示例,假设样本大小(n)为 20,样本标准偏差(s)为 1.5,我们的测试统计数据为:

单样本 t 检验

p 值

p 值(概率值的简称)是统计学中最关键的数字。它被定义为假设零假设为真,得到至少与观察到的结果一样极端的结果的概率。我最喜欢的用简单的词语描述 p 值的资源是 Cassie Kozyrkov 的:

p 值告诉你,给定你拥有的证据(数据),如果零假设看起来可笑与否[……]p 值越低,零假设看起来越可笑。

p 值是介于 0%和 100%之间的值,可以从零假设、采样分布和数据中检索。一般来说,它是在统计软件的帮助下计算出来的,或者是通过读取带有设定参数(自由度、α水平等)的分布表计算出来的。).对于大多数测试统计数据,可以在网上找到最常见参数的分布表,如 t-score卡方得分Wilcoxon-rank-sum

6.决定

为了决定推论,要么将测试统计与一个临界值进行比较(临界值方法),要么将 p 值与α水平进行比较(p 值方法)。

临界值

临界值将抽样分布分为“拒绝区域”和“接受区域”。如果检验统计量大于临界值,则零假设被拒绝,取而代之的是置信水平为 1-α的替代假设。如果检验统计量小于临界值,则不拒绝零假设。临界值是通过抽样分布和阿尔法水平找到的。然而,更常见的测试决策方法是 p 值法。

P 值与 alpha 值的对比

鉴于你的阿尔法水平,如果 p <= alpha, the null hypothesis is rejected in favour of the alternative hypothesis with confidence level 1-alpha. If the p-value is greater than the alpha-level, the null hypothesis is accepted.

总结

在假设检验中,使用随机数据样本检验关于总体的两个互斥陈述。它包括许多对结果有很大影响的概念和步骤,如制定假设或选择测试统计、α水平和样本大小。

资源

通过 easy-ht Python 包简化了假设检验

原文:https://towardsdatascience.com/hypothesis-testing-made-easy-through-the-easy-ht-python-package-2ee395b95fe2?source=collection_archive---------14-----------------------

编码教程,统计

你应该使用哪种假设检验?皮尔逊还是斯皮尔曼?t 检验还是 Z 检验?卡方?easy-ht 没问题。

Edge2Edge 媒体Unsplash 上拍摄

一个新的数据科学家可能会遇到的主要困难之一是关于统计基础知识。特别是,数据科学家可能很难理解在特定情况下使用哪种假设检验,例如何时可以使用卡方检验,或者皮尔逊相关系数和斯皮尔曼等级相关之间有什么区别。

为此,我实现了一个名为 easy-ht 的 Python 包,它允许执行一些统计测试,如相关性、正态性、随机性、均值等,而不关心要使用的具体测试。

软件包将根据提供的数据自动配置自身。

在本文中,我通过以下步骤描述了easy-ht Python 包:

  • 包的概述
  • 单个输入数据集的使用示例
  • 两个输入数据集的使用示例

1 easy-ht 封装概述

easy-ht 软件包可以通过 pip 轻松安装:

pip install easy-ht

其完整文档可在此链接获得。在一个或两个数据集的情况下,该软件包允许计算以下假设检验:

  • 正态性 —检查样本是否遵循正态分布
  • 相关性 —检查样本是否相关。它只能用于两个样本的测试。
  • 随机性 —检查样本是否以随机方式构建。
  • 表示— 在一个样本测试中,将样本与期望值进行比较。在两个样本测试中,比较两个样本的平均值。
  • 分布 —在一个样本测试中,将样本与分布进行比较。在两个样本测试中,比较两个样本的分布。

2 一个样本测试

在第一个示例中,只考虑了一个数据集。我生成一个随机的正态分布数据集。同样的过程也可以应用于一般数据。

2.1 生成数据

首先,我导入所需的库:

from easy_ht import HypothesisTest
import random
import numpy as np

然后,我生成正态分布的数据:

mu, sigma = 0, 0.1
X = np.random.normal(mu, sigma, 100)

现在,我创建一个HypothersisTest对象,它将用于进一步的分析。我将数据集X作为输入参数传递:

test = HypothesisTest(x = X)

一旦创建了对象,我就可以运行一些测试,而不用关心要使用的具体测试。

2.1 将数据平均值与理论值进行比较

value = 50
result = test.compare_means(value = value)
if result:
   print("Test is True: There is no difference")
else:
   print("Test is False: There is difference")

2.3 检查随机性

检查数据集是否以随机方式生成:

result = test.check_randomness()
if result:
   print("Test is True: Data is random")
else:
   print("Test is False: Data is not random")

2.4 比较分布

mean = musigma = sigma比较正态分布的数据

result = test.compare_distributions(cdf = 'norm', args=(mu,sigma))
if result:
   print("Test is True: Data follows a normal distribution",mu, sigma)
else:
   print("Test is False: Data does not follow a normal distribution", mu, sigma)

2 双样本检验

在第二个例子中,我考虑两个数据集。我生成了两个正态分布的数据集,但是同样的过程也可以用于一般数据集。

3.1 生成数据

和前面的例子一样,首先我导入所需的库:

from easy_ht import HypothesisTest
import random
import numpy as np

然后,我生成两个正态分布的数据集,具有相同的平均值和不同的 sigma:

mu, sigma1, sigma2 = 0, 0.1, 0.4
X = np.random.normal(mu, sigma1, 100)
Y = np.random.normal(mu, sigma2, 100)

现在,我创建一个HypothersisTest对象:

test = HypothesisTest(x = X, y = Y)

我利用它做进一步的测试。对于一个示例情况,参数y也被作为输入传递。

3.2 比较手段

比较两个数据集的平均值:

result = test.compare_means()
if result:
   print("Test is True: There is no difference")
else:
   print("Test is False: There is difference")

不带参数调用compare_means()函数。

3.2 比较分布

比较两个数据集的分布。与compare_means()函数类似,is 函数不传递任何参数。

result = test.compare_distributions()
if result:
   print("Test is True: Samples follow the same distribution")
else:
  print("Test is False: Samples do not follow the same distribution")

3.3 检查相关性

检查这两个数据集是否相关。

result = test.check_correlation()
if result:
   print("Test is True: Samples are correlated")
else:
   print("Test is False: Samples are not correlated")

摘要

在本文中,我展示了用于假设测试的新的 easy-ht Python 包。这个包正在开发中,因此如果你在测试它的时候遇到了一些问题,请不要犹豫联系我,或者在这个链接提出问题。

本教程的完整代码可以从这个链接下载

最初发布于初学者数据科学

相关文章

https://medium.com/analytics-vidhya/a-gentle-introduction-to-descriptive-analytics-8b4e8e1ad238 https://medium.com/analytics-vidhya/basic-statistics-with-python-pandas-ec7837438a62

简化的假设检验

原文:https://towardsdatascience.com/hypothesis-testing-simplified-5264f490a578?source=collection_archive---------24-----------------------

不确定型决策

图片来自弗拉季斯拉夫·巴比延科的作品《Unplash》

你在生活中面临过不确定性吗?那时候你是怎么做决定的?我确信这应该是凭经验、直觉或基于一些数据。

当今世界比以往任何时候都更容易进入数据驱动的决策阶段。当所有必要的数据都可以用来做决策时,对数据进行分割和分析以获得信息就变得更加容易了。然而,在大多数情况下,只有部分数据可用。例如,在这个疫情时代,冠状病毒在我们周围迅速传播,让我们说,我们想确定是否老年人受影响最大。找到所有得过冠状病毒的人来确定这一点是相当不现实的。我们只能依靠一些样本信息。

那么,我们如何知道从样本中得到的信息对于整个数据群体是否是真实的呢?这是相当不确定的。推断统计学,确切地说,推断统计学中的假设检验在这里可以帮到我们。它提供了一个工具包/方法来帮助做出这种决策。

作者图片

什么是假设检验?

顾名思义,假设检验检查作为推理基础的命题是真还是假。

先说个例子。

比方说,在一个村庄里,据最近一次统计,人们每月在食品杂货上花费 230 美元。村长想知道今年是否也是如此。他随机选择了 25 个家庭,并检查了该样本的平均花费,结果为 242 美元,标准差为 31,因为这次他无法收集所有关于家庭的信息。

这似乎是一个增长,但我们不能确切地说这是由于人口平均数的实际变化,还是由于抽样误差不能代表基于这些数字的整个人口。

在这样的场景中,默认选择是这一年家庭的平均收入也是 230 美元,这被称为零假设(【H0】***),而完全相反的被称为替代假设(H1)** 。*

  • H0 : μ = 230
  • H1:μ<230

假设检验通过检验可用的样本数据来检查数据是否足够强大,或者它是否提供了足够的证据来改变默认选择或零假设的决策。在没有直接默认选择的情况下,可以从基本数据分析中得出质量零假设,这种分析侧重于从可用数据中得出见解。

简而言之,假设检验检查是否有足够的证据来改变我们的想法。

我相信你们大多数人都很熟悉这个术语,

"在被证明有罪之前是无辜的"

这是一个被称为无罪推定的法律原则,任何被指控犯有任何罪行的人在被证明有罪之前都被认为是无辜的。举证责任落在控方身上,控方必须拿出令人信服的证据和事实来证明事实并非如此。

这与我们正在进行的假设检验非常相似。我们首先假设我们的零假设是正确的,然后检查可用的数据来证明相反的证据。

可接受风险阈值

如果我们回过头来看看,为什么我们必须依赖于这些类型的测试,这仅仅是因为我们不确定样本信息对总体来说是否真实。虽然这些测试不能从不确定性中得出确定性,但它们提供了科学的方法来充分利用我们所拥有的。然而,由于背后隐藏着不确定性,因此总是存在做出错误决定的风险。

我们有机会,

  • 错误地拒绝我们的默认选择
  • 错误地不改变我们的默认选择

这些分别被称为 tI 型误差和 II 型误差。第一类错误的概率由α表示,第二类错误的概率由β表示。这些误差很少为零,所以我们应该尽可能地减小它们。

作者图片

上图显示了可能性矩阵,统计学家通过第四象限的概率定义了测试的功效,即当零假设不成立时,成功拒绝零假设 ( 1- Beta) 的概率。一般来说,这可以通过获取更大的代表性样本来提高。

所以,回到这些错误可能性的风险上来,假设检验的美妙之处在于决策者甚至在开始检验之前就可以确定他/她愿意承担的风险阈值。这被称为置信水平 l。

用概率的术语来说,它可以定义为当决策实际上为真时,你愿意承担多大的风险概率来错误地改变默认状态的决策。

α = P(当其为真时拒绝零假设)

如果它更倾向于零,它更有可能不改变默认决策,我们将期望样本数据提供更多的证据来拒绝零假设。那么如何才能确定这个阈值呢?答案是,这取决于具体情况。

我们来看一个假设的极端情况。

H0:一名昏迷的病人入院时还活着

  • I 型错误:医护人员在患者实际活着的情况下,认为患者已经死亡而不立即对其进行治疗。
  • ⅱ型错误:医护人员在病人实际上已经死亡的情况下,相信病人还活着,并立即对其进行治疗。**

在这种情况下,第一类错误会导致可怕的结果,我们应该尽量减少第一类错误,这意味着在这里最好降低置信度。

统计测试

现在,如果我们看看假设检验中的统计检验,有两种流行的检验。这些背后的数学值得一篇新文章。所以让我们保持简单如下。

  • Z 检验:当我们有足够大的样本集时(根据经验法则,当样本大小,根据中心极限定理,n≥ 30 时,我们假设数据集遵循近似正态分布),或者如果我们知道总体方差,我们就进行 Z 检验。
  • T 检验:如果样本较小或者我们不知道总体方差,我们就用 T 检验。

通过提供样本数据和置信水平,通过统计软件进行这些测试是相当容易的,这反过来给出了一个称为 p 值的值。这个值允许我们决定在给定的置信水平下是否应该拒绝零假设。

基本上如果,

作者图片

如您所见,实现和得出结果非常简单。所以让我们更进一步,深入探究这背后的理论。

什么是 p 值?

p 值的正式定义是

“如果零假设是正确的,样本产生的影响至少与样本中观察到的影响一样极端的概率”

我相信我们很多人都不会理解。因此,让我们简化一下,检查一下前面的食品杂货平均支出的例子。这个例子的事实是,

  • 上次人们的平均食品支出是 230 美元。
  • 目前,25 个家庭的样本平均食品支出为 242 美元,标准差为 31。

可能的情况是,

  • 人口平均值从 230 变为 242
  • 它没有改变,这个 242 是因为它只是我们所取样本的平均值;这有可能来自平均值为 230 的人群。

出于理解的目的,让我们直观地看这个问题。假设零假设为真,这意味着总体的均值仍为 230。根据我在统计测试部分提到的指令,我们可以假设这是一个 t 分布。

作者图片

曲线下的面积是 100%,我们可以看到,如果我们从这个分布中取出任何随机样本,它们的平均值很有可能接近 230。此外,我们可以注意到,即使很小,样本均值也有可能是 242。这也并非完全不可信。

红色区域表示从该分布中抽取样本的概率,其平均值至少与我们观察到的样本平均值一样极端(在 242 和 218 的极端侧;即 230 +/-12)。这就是 p 值的确切含义,我相信现在已经很清楚定义中说的部分意味着什么,如果零假设是正确的话,那么的效果至少与在您的样本中观察到的效果一样极端。

假设突出显示的区域占 0.064。这是我们假设的 p 值。这意味着,如果总体实际上具有平均值 230,则有 6.4%的机会出现平均值至少为 242 的样本。

接下来的问题是这个值有多极端?这种极端足以拒绝零假设吗?什么区域定义了样本值是不可能的,足以保证拒绝零假设?这是我们的信心水平。

作者图片

假设我们的置信水平是 10%,这意味着我们愿意承担 10%的错误拒绝零假设的风险。在我们的例子中,我们的 p 值是 6.4%,正如您在上面的图像中看到的,它位于极端的 10%区域内,该区域被称为临界区域。这意味着我们愿意承担上述风险。因此,我们可以得出结论,在 10%的显著性水平上,有足够的证据来拒绝零假设。

如果置信度是 5%呢?然后,如上图所示,6.4%(蓝色区域)超出了我们可接受的风险水平(红色区域),然后我们将不得不得出结论,我们没有足够的统计显著性证据来拒绝 5%置信水平的零假设。

结论

正如我们所看到的,假设检验是一个很好的工具,当只有关于样本的信息时,当我们需要对整个群体做出决定时,可以使用它。

决策者在推动决策方面占据上风,因为决策在很大程度上取决于置信度,如上所述。为了强调这种置信水平的重要性,如果我们回到被证明有罪之前无罪的法律例子,错误的置信水平会增加类似 I 型和 II 型的错误,这就像分别判一个无辜的人有罪或未能判一个有罪。

同样重要的是要记住,这只是一个辅助科学决策的工具包;在现实世界中,在做出最终决定之前,总是需要对结果进行感觉检查。例如,当对照 0.05 的置信水平分析 0.049 p 值时,分析师应该更清楚他/她做出了正确的决策,而不是随意地应用规则。

假设检验:Z 分数

原文:https://towardsdatascience.com/hypothesis-testing-z-scores-337fb06e26ab?source=collection_archive---------2-----------------------

理解什么是假设检验以及如何解释和实施 z 检验的指南

图一。双尾和单尾测试|作者图片

当然,在你培训的某个部分,甚至在你的工作中,你听说过假设检验,但是你知道它们是用来做什么的,或者它们是如何实现的吗?如果答案是否定的,我邀请你留下来,因为我们将在这个博客中讨论著名的假设检验。

放松一下,去拿你最喜欢的饮料,尽情享受吧。

假设检验

想象一下,我们在一篇文章中读到这样的陈述:“ …所有成年人平均每天睡 7 个小时”。如何验证前面的断言是有效的?假设检验。

假设检验允许我们验证从总体中假设的某些性质,这些性质与从代表性样本中提取的性质有关。在我们之前的例子中,“所有成年人”是我们的人口,我们将试图验证“T9 每天睡 7 个小时”的属性。

为了证实所有成年人每天睡 7 个小时的说法,我们需要收集一个重要的样本来与总体进行比较。

想象一下,我们随机问 100 个成年人他们每天睡多少小时,从中我们得出他们平均每天睡 7.5 小时。因此,我们的样本均值是 7.5 小时,比总体均值高 0.5 小时。

所以给定样本均值,我们可能会想:既然差只有 0.5,我们假设这个说法是对的吗?或者既然不一样,我们说这个说法是不正确的吗?为了解决这些问题,我们需要使用一个叫做z-scores的东西,我们将在后面看到它的细节。

到目前为止一切都很简单,对吗?在继续之前,让我们形式化一些事情。

为了进行假设检验,我们需要确定两个假设:第个零假设第(或第H0)和第个备择假设第(或第H1)。零假设是指要验证的总体的统计特性的断言的形式化。备择假设是零假设的对立者,也就是说,它是反驳零假设的断言。

现在让我们回到之前的问题,当我们的样本均值结果是高 0.5 时,如何知道总体陈述是否正确?为了解决这个问题,我们首先需要知道一些事情。

为了检查零假设中的陈述是否正确,我们需要定义一个显著性水平。通常显著性水平为 5%,解释如下:如果我们样本均值的概率小于或等于 5%,则拒绝零假设,反之,如果我们样本均值的概率大于 5%,则保留零假设或未被拒绝

但是为什么是 5%?让我们继续理解这是如何工作的。

在处理正态分布时,为了实用,这种分布通常被转换成一个标准正态分布,这个过程被称为标准化。标准正态分布是一条均值为 0、标准差为 1 的对称曲线,其曲线下的面积为 1 或 100%(如图 2 所示)。这种标准化使我们能够量化标准偏差的数量,在该数量下,样本均值与总体均值相关。标准偏差的数量由 z 值决定。嘣!

图二。标准正态分布|作者图片

因此,由于我们使用标准正态分布,所有与总体平均值相关的样本平均值都是正态分布的,因此,至少 95%的样本平均值落在总体平均值的 2 个标准差内,也就是说,获得超过总体平均值的 2 个标准差的样本平均值的概率小于 5%。

图 3。alpha = 5%的双尾检验|图片由作者提供

在继续之前,让我们形式化一些事情:

当样本均值与低发生概率相关联时,零假设被拒绝。当样本均值与高发生概率相关联时,保留零假设

这种发生概率更好地称为 p 值

然后,如果出现概率(或 p 值)小于或等于 5%,则拒绝零假设,反之,如果出现概率(或 p 值)大于 5%,则保留零假设。

总之,假设检验方法被描述为以下步骤的序列:

  1. ****陈述假设:在这个阶段,声明待检验的语句,即零假设。因此,产生了另一个假设。替代假设可以确定 3 种情况:总体均值大于(>)、小于(<)或不等于( )原假设中定义的值。
  2. ****设定决策的标准:决策的标准是通过显著性水平来定义的,通常定义为 5%,但是也经常使用 10%和 1%。
  3. 计算 de 检验统计量**:在这个阶段,应用统计检验来确定我们的样本均值与总体均值有多接近或多远。不同类型的分布有几种统计检验,通常,对于正态分布,使用基于 z 得分的 z 检验检验
  4. ****做出决定:给定统计测试获得的结果和步骤 2 中定义的决定标准,确定是拒绝还是保留零假设。

太棒了,现在我们已经了解了什么是假设检验,以及关于如何通过一些形式实现的直觉,现在让我们看看如何对备选假设可能采用的每个变量应用 z-test ,让我们进入下一部分!

方向性&非方向性假设检验

根据我们对人口的了解,这是我们可以应用的测试。如果我们知道平均值和方差,z 检验将是最合适的选择。

正如我们在上一节中看到的,替代假设是反驳或否定原假设的假设。这个矛盾是指样本均值大于(>),小于(≦)于零假设中建立的,即备择假设可以是定向的,也可以是不定向的。

图 4。定向和非定向测试|作者图片

当另一个假设定义了一个方向,或者大于(>)或者小于(

  • ****无效假设:所有成年人每天睡 7 个小时
  • 另类假设 : 所有成年人每天睡眠时间都超过 7 小时

以同样的方式,该假设可以被定向如下:

  • ****零假设:一个 ll 成年人每天睡 7 个小时
  • 另类假设 : 所有成年人每天睡眠时间都少于 7 小时

在这两种情况下,假设都是方向性的。

另一方面,当替代假设没有明确地定义一个方向时,假设是非定向的,也就是说,它只确定该假设不同于零假设。例如:

  • 零假设 : 所有成年人每天睡 7 个小时
  • 另类假设 : 所有成年人都不是每天睡 7 个小时

很好,现在我们知道了什么是假设检验,什么时候应用 z 检验,以及根据替代假设的假设方向,是时候看几个例子了。让我们去吧!

例子

就拿下面这个说法来说吧:“在一项研究中,发现所有成年人每天都睡 7 小时,标准差为 1 小时。假设我们取一个样本,从中我们得到样本平均值为 8 小时。执行假设检验以验证总体均值

为了进行假设检验,我们遵循以下 4 个步骤:

****第一步:陈述假设。假设我们要处理一个非方向性假设,我们的零假设和替代假设如下:

  • 零假设:成年人每天睡 7 个小时
  • ****另类假设:成年人每天不睡 7 小时

第二步:设定决策标准。

显著性水平将为 0.5 或 5%,因此决定了alpha = 0.5。由于我们正在处理一个无方向的双尾测试,我们将 alpha 值分成两半,这样上下尾的面积比例相等,如图 3 所示。α的计算如等式 1 所示。

等式 1。为双尾检验处理 alpha

既然我们已经计算了双尾检验的alpha value,那么我们就可以确定临界值,也就是在标准正态分布中决定拒绝区域的那些值。

为了找到临界值,我们看一下z-table``z的值,它近似于曲线下的面积,类似于 0.0250。在这种情况下,值是 1.96,也就是说,如果我们的统计测试值大于 1.96 标准差或小于-1.96 标准差,我们将处于剔除区

图 5。alpha = 0.05 的拒绝区域|作者提供的图片

第三步:计算检验统计量。一旦我们定义了假设和显著性水平,我们就开始计算 z 统计量

z 统计量给出了标准正态分布中样本均值偏离总体均值的标准偏差数。 z 统计量的计算方法是取样本平均值减去总体平均值(在零假设中定义),除以标准差,如公式 2 所示。

等式 2。z 统计计算

然后,通过计算,我们得到z = 1。最后,我们必须做出决定,这将在下一步中进行。

****第四步。做个决定。为了做出决定,我们根据显著性水平查看步骤 2 中获得的临界值。由于z statistic(在步骤 3 中获得)的值小于临界值,所以决定保持零假设。

图 6。z 得分= 1 |作者图片

最后,获得z = 1的概率由p-value决定。为了找到这样的值,我们使用单位标准表。在这种情况下,我们寻找等于 1 的z-score,值是 0.15866。假设我们提出了另一个双尾假设,我们将获得的值乘以 2,得到 p = (0.15866) * 2 = 0.31732。

在步骤 2 中,我们确定显著性水平等于 5%,也就是说,如果p-value小于 5%,假设被拒绝,否则,如果p-value大于 5%,假设无效。在这种情况下,p = 31.7%,大于 5%,因此保持零假设。

参考

[1] 假设检验简介

假设检验解释

原文:https://towardsdatascience.com/hypothesis-tests-explained-8a070636bd28?source=collection_archive---------6-----------------------

统计数字

快速概述假设检验的概念,它在参数和非参数检验中的分类,以及何时使用最流行的假设检验。

作者图片

什么是假设检验

根据 Jim Frost 的说法,假设检验是一种推断统计学的形式,它允许我们根据一个有代表性的样本对整个人口做出结论..]在大多数情况下,观察整个种群以了解其特性是根本不可能的。唯一的选择是收集一个随机样本,然后用统计学来分析它[1]。

在进行假设检验时,首先,必须制定一个假设。假设的一个例子是“人口中的身高和性别之间存在相关性”,或者“人口中的两组之间存在差异。”

通常,要论证的论题称为备择假设 (HA),它的反义词是零假设 (H0)。实际上,零假设表明人口中没有新的事情发生。

在前面的例子中,无效假设可以表述为:人口中的身高和性别之间没有相关性,两组之间没有差异。假设检验的目的是验证是否可以拒绝零假设。一般来说,拒绝零假设并不自动意味着替代假设被接受。然而,在某些情况下,拒绝零假设可能意味着可以接受替代假设。

执行假设检验时,可能会出现两种错误:

  • 第一类错误:拒绝零假设,当它实际上是真的。
  • 第二类错误:接受零假设,当它实际上是假的。

下表恢复了第一类和第二类错误:

作者图片

假设检验的类型

假设检验可以分为两大类[2]:

  • 参数测试,如果样本遵循正态分布。通常,如果样本的均值为 0,方差为 1,则样本服从正态分布。
  • 非参数检验,如果样本不符合正态分布。

根据要比较的样本数量,可以制定两类假设检验:

  • 一个样本,如果只有一个样本,必须与给定值进行比较
  • 两个样本,如果有两个或两个以上的样本要比较。在这种情况下,可能的测试包括样本间的相关性差异。在这两种情况下,样本可以配对,也可以不配对。配对样本也叫相依样本,而不配对的样本也叫独立样本。在成对样本中,会出现自然或匹配的耦合。

通常,参数测试有相应的非参数测试,正如[3]中所述。

本文顶部的图表回顾了如何根据样本选择正确的假设检验。

参数测试

如前所述,参数测试假设数据呈正态分布。下表描述了一些最流行的参数测试及其测量内容。

作者图片

非参数检验

非参数检验不对数据的分布做任何假设。下表描述了一些最流行的非参数测试及其测量内容。

作者图片

摘要

在这篇短文中,我描述了假设检验的概念,以及最流行的检验和它们的使用时机。

对于那些仍然难以理解假设检验的人,有一个 Python 库,叫做 easy-ht [6],它在没有任何统计学知识的情况下运行主要的假设检验。关于如何使用 easy-ht 的教程可在此链接获得。

原贴于KD nuggets

如果你喜欢这篇文章,你可以直接支持我,点击这个链接,在推特上关注我,或者访问我的新网站。

参考

[1]统计假设检验概述https://statistics byjim . com/Hypothesis-Testing/Statistical-Hypothesis-Testing-Overview/

[2]参数统计和非参数统计有什么区别?https://source essay . com/参数统计和非参数统计的区别是什么/

[3]您应该使用哪种统计测试?https://help . XL stat . com/s/article/which-statistical-test-you-use?language=en_US

[4]Kolmogorov–Smirnov 测试https://en . Wikipedia . org/wiki/Kolmogorov % E2 % 80% 93 Smirnov _ test

[5]威尔考森测试【https://www.investopedia.com/terms/w/wilcoxon-test.asp

[6]易 hthttps://pypi.org/project/easy-ht/

相关文章

https://medium.datadriveninvestor.com/a-brief-introduction-to-the-concept-of-data-7b593587e0cf https://medium.com/analytics-vidhya/basic-statistics-with-python-pandas-ec7837438a62

新到中?您可以每月订阅几美元,并解锁无限的文章— 单击此处

我分析了数百名用户的 Tinder 数据——包括消息——所以你不必这么做。

原文:https://towardsdatascience.com/i-analyzed-hundreds-of-users-tinder-data-including-messages-so-you-dont-have-to-14c6dc4a5fdd?source=collection_archive---------3-----------------------

这些数据是令人尴尬的隐私,但揭示了我们已经知道的自己最无聊的部分。

米卡·鲍梅斯特在 Unsplash 上的照片

我在 2016 年读了阿齐兹·安萨里的《T4 现代浪漫史》,毫无疑问,这是我读过的最有影响力的书之一。那时,我还是一个鼻涕横流的大学生,还在和高中同学约会。

这本书给出的关于网上约会成功的数字和数据让我觉得冷酷无情。千禧一代和他们的前辈随着互联网的出现而受到祝福和诅咒。在寻找我们的“灵魂伴侣”时,伴侣选择的激增使我们变得麻木,并给了我们不切实际的期望。

我不但没有被劝阻,反而受到了鼓舞。几个月之内我就和高中男友分手了,自己也进入了网恋世界。我很快意识到约会本身就很糟糕,当它数字化时,情况变得更糟。

火绒。邦布尔。铰链。CoffeeMeetsBagel。如果它在 App Store 上,那么我可能会使用它。尽管我的约会经历大多很平淡,但我无法摆脱对这些被上帝遗弃的应用程序的迷恋。我决定将这种魅力作为我在哥伦比亚大学数据新闻学 Lede 项目的最终项目的一部分。

仅仅使用 Python、Jupyter 笔记本和疯狂的电子邮件,我就直接使用约会应用程序数据创建了一个项目。

1.寻找数据

现在我已经有了一个项目,我需要找到实际的数据。这是一个巨大的障碍。

首先,我需要选择一个应用程序来关注。在 r/dataisbeautiful 上浏览了几个小时后,我决定使用 Tinder,因为它很受欢迎。

我从 Reddit 上了解到,通过阅读其他 文章,我可以请求我自己的数据。几年前,卫报写了一篇关于 Tinder 如何使用个人数据的报道。该公司的部分回应是根据要求提供用户数据

https://www.theguardian.com/technology/2017/sep/26/tinder-personal-data-dating-app-messages-hacked-sold

似乎很容易做到,对不对?除了,我没有任何数据下载。我有下载 Tinder 使用几个月的习惯,然后出于沮丧删除我的账户,结果只是重复这个过程。

我知道数据就在那里,尽管障碍重重,我决心找到它。在谷歌搜索了几轮“Tinder 数据”却一无所获之后,我回到了 Reddit。我在 r/dataisbeautiful 上注意到,一些人正在使用一个名为 Swipestats.io 的网站可视化他们的 Tinder 数据。

随机男性用户的 Swipestats.io 可视化

我决定尝试一下,给网站的所有者发一封电子邮件,询问他是否可以为我的项目与我分享匿名的 Tinder 数据。他同意了(谢谢你,克里斯)。

接下来你知道,我坐在一个有 556 个 Tinder 个人资料的 JSON 上。

2.清理数据

这完全是一场噩梦。

我已经浪费了生命中的几十个小时,不仅试图理解这些数据,还试图清理它们。最后,我和一个臃肿的 JSON 建立了一段非常忠诚的关系。

我面临的第一个障碍是如何打开文件。它很大,每当我试图把它上传到笔记本电脑,我会得到一个错误。我和 Lede 项目的导师谈过(谢谢你,Jeff),他建议通过 JSON lint 来运行它。我不知道那是什么。

我觉得打开一个大 JSON 是没有用的。事情看起来很黯淡,但我下定决心要用 Tinder 数据创建一个项目。

长话短说,我把 JSON 转换成. txt 文件,然后把大的。使用这个站点把 txt 文件变成更小的文件。由于某种神的奇迹,网站分裂了。txt 文件完美地由每个人的文件组成。接下来,我转换了新的吐槽。txt 文件转换成 JSON 格式。现在我有一个包含 556 个 JSONs 的文件夹。

# Loading the data
import jsonf = open(“user_x.json”, encoding=”utf-8")
data = json.load(f)

最后,我能够打开我的数据。令我惊讶的是,我注意到邮件被包括在内。

21 世纪的浪漫

我知道我必须优先考虑,并决定只关注三个不同的对象,对话对话元用户。在流程图中,我概述了每个对象中的信息。

我能做的事情有无数种可能性,但我仍然没有清理完数据。下一个障碍是组织它。

我的下一步是按照性别和语言来组织文件。我读过的很多文章都喜欢比较男人和女人的约会经历,所以我想拥有那些独立的数据集。此外,我还收到了一套相当国际化的套装,上面散布着日语、西班牙语或德语等语言。尽管我很欣赏这种多样性,但我只想用英文资料工作。

我不知道从哪里开始组织,所以我去了办公时间(谢谢你,Thanasis)。在 Gather 上绞尽脑汁之后,我们——主要是 than asis——找到了一个解决方案。

import shutil
import os
import glob
from os import pathall_files = '/directory'
male = "/directory/MALE"
female = "/directory/FEMALE"
files = glob.glob(all_files+"/*.json")
for file in files:
    with open(file, encoding="utf-8") as f:
        data = json.load(f)
        stat = data["user"]
        for stats in stat:
            if stat["gender"] == "M":
                try:
                    shutil.move(os.path.join(all_files, file), male)
                except:
                    pass 
            else:
                try:
                    shutil.move(os.path.join(all_files, file),   female)
                except:
                    pass

这段代码只是将一个 JSON 移动到它各自的文件夹中,不管它是男的还是女的。

我试图用 TextBloblangdetect 写一个类似的代码来区分语言。没用。出于纯粹的恶意,我根据语言手工分离了文件。

到这一点,我感觉神志不清,但我几乎结束了。我的最后一步是将数据保存到友好的 CSV 中,给我留下大约 300 个英语数据。

将对话保存到 CSV 中:

注意:Tinder 消息带有 HTML 标签。我在下面包含了删除它们的代码。

all_files = '/GENDER/ENGLISH'
files = glob.glob(all_files+"/*.json")# HTML parser code
from io import StringIO
from html.parser import HTMLParserclass MLStripper(HTMLParser):
    def __init__(self):
        super().__init__()
        self.reset()
        self.strict = False
        self.convert_charrefs= True
        self.text = StringIO()
    def handle_data(self, d):
        self.text.write(d)
    def get_data(self):
        return self.text.getvalue()def strip_tags(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()for file in files:
    with open(file, encoding="utf-8") as q:
        data = json.load(q)
        all_convo = data["conversations"]
        text = []
        for message in all_convo: 
            for messages in message["messages"]:
                messages["final_messages"] = ""
                updated = messages["message"]
                messages["final_messages"] = strip_tags(updated)
                text.append(messages)

        with open('GENDER_convos.csv', 'a') as csvfile:
            field_names = ['to', 'from', 'message', 'sent_date', 'final_messages']
            writer = csv.DictWriter(csvfile, fieldnames=field_names, extrasaction='ignore')
            writer.writeheader()
            writer.writerows(text)

将对话元保存到 CSV 中:

for file in files:
    with open(file, encoding="utf-8") as q:
        data = json.load(q)
        user_data = []
        user_data.append(data["conversationsMeta"])
        field_names = ['nrOfConversations', 'longestConversation', 'longestConversationInDays', 
                       'averageConversationLength', 'averageConversationLengthInDays', 
                       'medianConversationLength', 'medianConversationLengthInDays', 
                       'nrOfOneMessageConversations', 'percentOfOneMessageConversations', 
                       'nrOfGhostingsAfterInitialMessage']
        with open('GENDER_convometa.csv', 'a') as csvfile:
            writer = csv.DictWriter(csvfile, fieldnames=field_names)
            writer.writeheader()
            writer.writerows(user_data)

将用户元数据保存到 CSV 中:

for file in files:
    with open(file, encoding="utf-8") as q:
        data = json.load(q)
        user_data = []
        md = data["user"]
        for job in md['jobs']:
            if job['title'] == None:
                pass
            else: 
                md['jobs'] = job['title']
        try:         
            for school in md['schools']:
                if school['name'] == None:
                    pass        
                else: 
                    md['schools'] = school['name']  
        except:
            pass
        user_data.append(md)
        field_names = ['birthDate', 'ageFilterMin', 'ageFilterMax', 'cityName', 'country', 'createDate', 
                    'education', 'gender', 'interestedIn', 'genderFilter', 'instagram', 'spotify', 'jobs', 
                    'educationLevel', 'schools']
        with open('GENDER_md.csv', 'a') as csvfile:
            writer = csv.DictWriter(csvfile, fieldnames=field_names)
            writer.writeheader()
            writer.writerows(user_data)

数据曾经被完全清理过吗?不。这是一个无止境的任务。

3.分析数据

在你变得太兴奋之前,我需要承认我发现的所有东西都有点无聊。我花了大部分时间清理数据,所以这一部分有点枯燥,特别是考虑到我是在晚上 10:54 写的这篇文章,我应该在明天早上 9:00 提交。

你生活和学习。

我根据之前做的三个 CSV 做了一个分析。提醒一下,它们每个都包含对话对话元用户元数据。代码可在这里获得。

S ide 注:我是从 数据驱动 分析僵尸工具制作的 Tinder 数据开始,受这篇文章影响很大。那篇文章更深入,并且使用了更简洁的代码。

a)分析对话

这可以说是所有数据集中最乏味的,因为它包含了 50 万条 Tinder 消息。不足之处是,Tinder 只存储发送的和未接收的消息。

我对对话做的第一件事是创建一个语言模型来检测调情。最终产品充其量是初步的,可以在这里阅读。

接下来,我做的第一个分析是发现用户中最常用的单词和表情符号是什么。为了避免我的电脑崩溃,我只用了 20 万条信息,而且男女混合。

那么十大单词是什么呢?

《男女之间的火绒》中使用的十大词汇

引人入胜。

为了让它更令人兴奋,我借鉴了 Data Dive 的做法,在过滤掉停用词后,制作了一个标志性的 Tinder flame 形状的词云。

《男女火绒》500 大热门词汇云

是啊是啊。文字是伟大的——但是表情符号呢?

男女火绒中使用的十大表情符号

有趣的事实:我最讨厌的是哭笑表情符号,简称:joy。我非常不喜欢它,甚至不会在本文中将它展示在图表之外。我投票决定立即并无限期地撤销它。

这些结果在多大程度上因性别而异?

看来“喜欢”依然是两性中的勒宁冠军。虽然,我觉得很有意思的是“嘿”怎么会出现在男性的前十名里,而不是女性。会不会是因为男人应该主动发起对话?可能吧。

表情符号对比呢?

似乎女性用户使用更调情的表情符号(😍,😘)比男性用户多。尽管如此,我仍然感到不安,但并不感到惊讶:《欢乐:超越性别》在表情符号排行榜上占据主导地位。

b)分析对话元

这部分是最直接的,但也可能是最费力的。现在,我用它来寻找平均值。

以下是该数据帧中可用的键:

['nrOfConversations ',' longestConversation ',' longestConversationInDays ',
,' averageConversationLength ',
,' medianConversationLength ',' medianConversationLengthInDays ',
,' nrOfOneMessageConversations ',' percentOfOneMessageConversations ',
,' nrofghostingafterinitialmessage ',' Sex']

给我留下深刻印象的是 nrOfConversationsnrOfOneMessageConversationsnrofghostingsaftinitialmessage。

import pandas as pd
import numpy as npcmd = pd.read_csv('all_eng_convometa.csv')# Average number of conversations between both sexes
print("The average number of total Tinder conversations for both sexes is", cmd.nrOfConversations.mean().round())# Average number of conversations separated by sex
print("The average number of total Tinder conversations for men is", cmd.nrOfConversations[cmd.Sex.str.contains("M")].mean().round())
print("The average number of total Tinder conversations for women is", cmd.nrOfConversations[cmd.Sex.str.contains("F")].mean().round())

男性和女性的平均聊天次数是 278.0 次。

男性的总 Tinder 对话平均次数为 218.0 次。

女性总 Tinder 对话的平均次数是 464.0。

哇哦。这里可以感受到男人和女人的不同经历。

# Average number of one message conversations between both sexes
print("The average number of one message Tinder conversations for both sexes is", cmd.nrOfOneMessageConversations.mean().round())# Average number of one message conversations separated by sex
print("The average number of one message Tinder conversations for men is", cmd.nrOfOneMessageConversations[cmd.Sex.str.contains("M")].mean().round())
print("The average number of one message Tinder conversations for women is", cmd.nrOfOneMessageConversations[cmd.Sex.str.contains("F")].mean().round())

男性和女性在交谈中平均收到 80.0 条信息。

男性在交谈中平均每条短信的数量是 74.0 条。

女性在交谈中平均每条信息的数量是 99.0 条。

有意思。尤其是当我看到女性在 Tinder 上收到的平均信息是男性的两倍多时,我很惊讶她们的一条信息对话是最多的。然而,还不清楚是谁发送了第一条信息。我的客人是,它只在用户发送第一条消息时读取,因为 Tinder 不保存收到的消息。只有 Tinder 可以澄清。

# Average number of ghostings between each sex
print("The average number of ghostings after one message between both sexes is", cmd.nrOfGhostingsAfterInitialMessage.mean().round())# Average number of ghostings separated by sex
print("The average number of ghostings after one message for men is", cmd.nrOfGhostingsAfterInitialMessage[cmd.Sex.str.contains("M")].mean().round())
print("The average number of ghostings after one message for women is", cmd.nrOfGhostingsAfterInitialMessage[cmd.Sex.str.contains("F")].mean().round())

两性之间一条信息后的代笔次数平均为 50.0 次。

男性发一条信息后的平均代笔次数为 18.0 次。

女性发一条信息后的平均代笔次数是 151.0 次

类似于我之前在nrOfOneMessageConversations中提到的,并不完全清楚是谁发起了重影。如果女性在 Tinder 上被更多人跟踪,我个人会感到震惊。

c)分析用户元数据

以下是用户元数据中可用的对象。

['生日','年龄过滤','年龄过滤','最大值','城市名','国家',【T2 ','创建日期','教育','性别','兴趣','性别过滤',【T3 ',' instagram ',' spotify ','工作','教育水平','学校']

我想创建一个年龄列,并决定可以将用户年龄确定为(创建日期 - 出生日期 )

# CSV of updated_md has duplicates
md = md.drop_duplicates(keep=False)from datetime import datetime, datemd['birthDate'] = pd.to_datetime(md.birthDate, format='%Y.%m.%d').dt.date
md['createDate'] = pd.to_datetime(md.createDate, format='%Y.%m.%d').dt.datemd['Age'] = (md['createDate'] - md['birthDate'])/365
md['age'] = md['Age'].astype(str)
md['age'] = md['age'].str[:3]
md['age'] = md['age'].astype(int)# Dropping unnecessary columns
md = md.drop(columns = 'Age')
md = md.drop(columns= 'education')
md = md.drop(columns= 'educationLevel')# Rearranging columns
md = md[['gender', 'age', 'birthDate','createDate', 'jobs', 'schools', 'cityName', 'country',
        'interestedIn', 'genderFilter', 'ageFilterMin', 'ageFilterMax','instagram',
       'spotify']]
# Replaces empty list with NaN
md = md.mask(md.applymap(str).eq('[]'))# Converting age filter to integer
md['ageFilterMax'] = md['ageFilterMax'].astype(int)
md['ageFilterMin'] = md['ageFilterMin'].astype(int)

接下来,我想找出年龄年龄过滤最大值年龄过滤最小值的平均值。我注意到这些数字异常偏高,所以我检查了我的数据集,并注意到一些钓鱼。我从数据集中删除了以下内容。

一个人 106 岁,另一个 137 岁。两人 16 岁,一人列为 15 岁。我还去掉了 17 个把 1000 作为自己 ageFilterMax 的人和一个列出 95 的人。

我发现了以下情况:

*# Combined age data* 
print("The average user age for both genders is", all_age.age.mean().round()) print("The average user age filter maximum for both genders is", all_age.ageFilterMin.mean().round()) print("The average user age filter minimum for both genders is", all_age.ageFilterMax.mean().round()) print("--------------------") *# By gender* 
print("The average male user age is", all_age.age[all_age.gender.str.contains("M")].mean().round()) print("The average female user age", all_age.age[all_age.gender.str.contains("F")].mean().round())  print("--------------------") print("The average male user age filter maximum is", all_age.ageFilterMax[all_age.gender.str.contains("M")].mean().round()) print("The average female user age filter maximum is", all_age.ageFilterMax[all_age.gender.str.contains("F")].mean().round()) print("--------------------") print("The average male user age filter minumum is", all_age.ageFilterMin[all_age.gender.str.contains("M")].mean().round()) print("The average female user age filter minumum is", all_age.ageFilterMin[all_age.gender.str.contains("F")].mean().round())

*男女用户平均年龄为 24.0
男女用户平均年龄过滤最大值为 21.0
男女用户平均年龄过滤最小值为 31.0

男性用户平均年龄为 24.0
女性用户平均年龄为 23.0

男性用户平均年龄过滤最大值为 31.0
女性用户平均年龄过滤最大值为 32.0 【T27*

为了增加效果,我用同样的数据制作直方图。

最后,但肯定不是最不重要的,我看了工作、学校、城市和国家。****

# Creating df of jobs listed
jobs_df = pd.DataFrame(md['jobs'].value_counts(dropna=True))
jobs_df.reset_index(level=0, inplace=True)
jobs_df = jobs_df.rename(columns={"index": "Jobs", "jobs": "Count"})# Dropped index that said False
jobs_df = jobs_df.drop(0)
jobs_df = jobs_df.drop(1)jobs_df.head(10)

我知道你在想什么——无聊,对吧?我自己浏览了一下列表,选出了我最喜欢的。

Tinder 数据中显示的 Alyssa 最喜欢的工作

这些是 Tinder 数据中排名前十的学校。

# Creating df of schools listed
school_df = pd.DataFrame(md['schools'].value_counts(dropna=True))
school_df.reset_index(level=0, inplace=True)
school_df = school_df.rename(columns={"index": "Schools", "schools": "Count"})# Dropped index that was empty list
school_df = school_df.drop(0)school_df.head(10)

基于 Tinder 数据的十大城市。

# Creating df of cities listed
city_df = pd.DataFrame(md['cityName'].value_counts(dropna=True))
city_df.reset_index(level=0, inplace=True)
city_df = city_df.rename(columns={"index": "City", "cityName": "Count"})city_df.head(10)

很多加拿大人和冷酷的美国人。

最后,十大国家。然而,Tinder 将州和国家分组在一起,所以至少可以说它很混乱。

# Creating df of countries/states listed
country_df = pd.DataFrame(md['country'].value_counts(dropna=True))
country_df.reset_index(level=0, inplace=True)
country_df = country_df.rename(columns={"index": "Country/State", "country": "Count"})country_df.head(10)

最后的想法

总而言之,这些数据是令人尴尬的隐私,但揭示了我们已知的最无聊的部分。

毫不奇怪,我们发现女性在 Tinder 上的平均对话次数比男性多,或者“快乐:是最受欢迎的表情符号”。坦白地说,我的发现令人印象深刻,但这是一个开始。

我看到了未来项目使用这些数据的巨大潜力,我几乎没有触及表面。未来的想法包括建立一个更可靠的调情分析工具或创建一个 Tinder 消息机器人。

不管是哪种情况,我都对即将到来的事情感到兴奋。

承认

感谢 Soma 不仅是一名优秀的教师,也是 Lede 项目的先锋!额外感谢卡森、塔纳西斯、杰夫和皮特对我的帮助。

特别感谢 Swipestats.io 为我提供数据,联系方式如下。

克里斯蒂安·埃尔塞特·博

电子邮件:克里斯蒂安@京东方.风投

领英:【https://www.linkedin.com/in/kristianeboe/

我让安艾写荒诞的假新闻

原文:https://towardsdatascience.com/i-asked-an-ai-to-write-absurd-fake-news-b97c07541152?source=collection_archive---------21-----------------------

Anastasia Shuraeva 拍摄的照片。

它如此令人信服地写下了这条新闻,令人震惊

自从某个美国总统将“假新闻”一词纳入主流以来,全球范围内对媒体的信任度一直在下降。越来越多的人报告说他们在网上遇到假新闻。假新闻的问题已经在全球变得众所周知,因为它威胁到我们的民主。

我认为伪造的新闻通常是由人写的。我很好奇,想看看当今的算法能否在没有任何人工干预的情况下,自己生成可信的假新闻。我为这项任务部署了 OpenAI 强大的人工智能算法 GPT-3。这个人工智能因其读写能力而闻名。

它能自己制造出令人信服的假新闻吗?我试图通过打出三个标题并让人工智能写下其余部分来找到答案。只有每个故事的第一句,粗体字的文字,是我写的。其他的都是 GPT-3 写的,完全未经编辑。

算法生成的所有文本都以这种格式进行注释。

乔·拜登把冰淇淋放在披萨上

首先,这里有一个关于美国总统乔·拜登的假新闻。拜登既喜欢冰淇淋又喜欢比萨饼,所以我想:为什么不把两者结合起来编一个假故事呢?

乔·拜登喜欢在披萨上放冰淇淋。

这位前副总统最喜欢的食物是上面有冰淇淋的比萨饼。“这对我来说很平常,”他说。“我会打电话,他们会说,‘乔,我们给你准备了一份披萨。’我会说,‘我马上就到’。"

拜登非常喜欢这道菜,他曾经从中国给他最喜欢的披萨店打了一个私人电话。

“我已经到了可以打电话订购的地步,”他说。“我从中国——中国的长城——打来电话,我说,‘我想订一份外卖披萨。’"

拜登对比萨饼上的冰淇淋的热爱如此强烈,以至于他曾经要求他的妻子制作一个上面有冰淇淋的馅饼。

“我让吉尔给我做一个带冰淇淋的披萨,”拜登说。“她给我做了一个。这是我吃过的最好吃的东西。”

拜登对比萨饼和冰淇淋的热情可能会导致一个混乱的组合。几年前,他在从 DC 华盛顿州开往特拉华州的火车上,从他员工的孩子那里拿了一块带冰淇淋的比萨饼,然后去了镇上。

“我对此情有独钟,”他说。“这是我最喜欢的事情之一。”

我对这个故事写得如此之好感到惊讶。关于中国的部分有点尴尬,尤其是没有更多的上下文,但算法很快就回到了正轨。它当然也知道乔的妻子名叫吉尔。该算法在倒数第二段失去了凝聚力,其中提到披萨和冰淇淋是一种混乱的组合,但在下一句话中似乎改变了主题。

照片由丫蛋·古坦拍摄。

瑞典首相骑着一头猪

我自己是瑞典人。我很确定我们的总理斯特凡·勒文从来没有骑过猪,但我认为这可以成为一个像样的假故事。

昨晚有人发现瑞典首相骑着一只猪,这只猪从斯德哥尔摩郊外的一个农场逃跑了。

比约恩·莱尔瓦尔(Bjorn Lyrvall)被拍到骑着一头猪坐在他的滑板车后面,因为他的司机没能赶上他。

首相在前往斯德哥尔摩议会大厦的路上,他的司机意识到有一只猪逃跑了。

他追赶那只猪,但没能追上它。

Lyrvall 先生不得不骑着他的小摩托车去议会大厦,后面还驮着一只猪。

这头猪最终被抓住并回到了它的农场,但是 Lyrvall 先生却因为这件事而被嘲笑。

首先,比约恩·里瓦尔是一个真实存在的人,但他现在不是,也从来没有当过瑞典首相。他是一名在世界各地工作的瑞典外交官,所以他的名字可能会出现在许多训练 GPT-3 的英文文章中。不过,他绝对没有骑过猪。

再说一次,这个故事大部分都写得很好,尽管关于骑着一辆后面有猪的踏板车的句子并没有太多意义。尽管如此,这仍然是一个有趣的心理图像。

欧盟投资洋葱农场

我不太喜欢洋葱,但也许你喜欢?嗯,一个关于投资一大笔钱到洋葱农场的新闻怎么样?

欧盟将向洋葱农场投资 10 亿欧元。洋葱农场,我不骗你。有趣的是,欧盟将在名为“洋葱”的科学项目下资助这项研究

该项目包括开发新的洋葱品种,以及寻找种植洋葱和其他蔬菜的更好方法。欧盟投资这笔钱是因为它相信小洋葱是“欧洲饮食的重要组成部分”,而且“既健康又多用途”。

欧盟承诺投资 17 亿欧元用于新的耕作方法,并帮助农民采用新的工艺。我们迫不及待地想知道这项研究将会带来什么。

农业和农村发展专员菲尔·霍根说:

“我们相信创新是提高欧洲农业竞争力的关键,尤其是该领域中小企业的竞争力。”

专员还表示,农民也可以用这笔钱开发更环保的耕作方法。

这个故事显得有点不正式。这听起来更像是一篇自以为是的文章,而不是新闻报道。菲尔·霍根是真实存在的,当 GPT 3 号接受训练时,他确实是 T2 农业和农村发展专员。然而,这句话是假的。

照片由杰弗森·桑多斯拍摄。

我印象深刻,也很害怕

我不知道你怎么想,但我对算法如此令人信服地讲述这些荒谬的话题感到印象深刻和恐惧。重申一下:我只输入了每个故事的第一句话,我没有编辑 AI 的输出。

我生成的这些特别的故事显然很容易被反驳,但是该算法可以被部署来生成更严肃的文章。影响可能是严重的。

我们已经有了人工智能机器人,它们不仅在社交媒体上传播假新闻,还提供真实性。看,人类不太可能对没有多少喜欢、评论和分享的新闻文章做出回应。因此,这些机器人最先喜欢、评论和分享伪造的文章。一旦帖子达到一定的参与度,人们就开始与帖子互动。

“随着文本生成人工智能的不断改进,无论是机器还是人类都无法区分机器编写的文本和人类编写的文本。”

由于像我使用的这种文本生成人工智能,创造和传播假新闻的整个价值链似乎正在走向自动化。

当然也有识别和删除假新闻的反制方案。像脸书这样的公司结合使用复杂的机器学习算法,试图预测假新闻,以及人类事实核对器。

随着文本生成人工智能的不断改进,无论是机器还是人类都无法区分机器编写的文本和人类编写的文本。但是有很多方法可以让算法发现一个故事是假的。它可以检查分享新闻的用户,以确定他们是否是真实的人。它可以尝试找到新闻故事的来源,并确定它是否来自一个声誉良好的新闻渠道。它可以观察与新闻故事互动的人,以确定他们是否是真实的。

然而,我担心制造和传播假新闻的算法会变得更加聪明。例如,一个创新的算法可以创建一个伪造的故事,传播一个组织的议程,同时仍然基于一个真实的故事。

比方说,一家声誉卓著、备受尊重的新闻机构发布了一个真实的故事。一种算法可以生成自己的故事,引用原始文章,但稍微改变事实。然后,该算法在先前的基础上产生另一个故事,进一步偏离事实。它可以快速重复这个循环。在短短的几分钟内,你将会看到一系列相互参照的故事,它们都有着良好的来源,而最后一个故事已经远离了真相。最后一篇文章可以自动分享,很难核实事实。

“一个创新的算法可以创造一个伪造的故事,传播一个组织的议程,同时仍然基于一个真实的故事。”

可以想象,这样的系统可能会产生毁灭性的影响。

我们正在进入一个可怕的时代。歧视性算法强大的 deepfakes人工智能驱动的警察监控是现代机器学习解决方案的一些后果。

这就是为什么我们继续开发反人工智能至关重要。我们需要能够检测和防止假新闻传播以及人工智能其他负面后果的软件。

毕竟,如果我能在不到一分钟的时间内让一个关于在比萨饼上放冰淇淋的故事听起来令人信服,想象一下更有能力的人能做什么。

https://medium.com/swlh/no-gpt-3-is-not-superintelligent-its-not-tricking-humans-and-it-s-not-pretending-to-be-stupid-fa92e9c026df https://medium.com/geekculture/will-ai-replace-programmers-fb6fcfd70b37

朴素贝叶斯、歌词和体裁

原文:https://towardsdatascience.com/i-built-a-naive-bayes-model-to-predict-genre-from-song-lyrics-and-it-went-ok-ish-639af0b0a078?source=collection_archive---------21-----------------------

我建立了一个朴素贝叶斯模型来预测歌曲的风格,结果还不错

如果你对音乐和数据感兴趣,那么百万首歌曲数据集是一个非常棒的资源。不出所料,总共有 100 万首歌曲的元数据,如果你决定下载完整的数据集,大约有 280GB。还有一堆关联的数据集,比如 musiXmatch 数据集tagtraum 流派注释,所以我认为这将是一个很酷的用途,尝试看看是否有可能建立一个模型来预测基于一组歌词的音乐流派。

有数百种流派,包括一些没有歌词的,如“豪斯医生”或“器乐爵士乐”,所以我决定只看前四名:
-摇滚
-流行
-嘻哈
-乡村

(最奇怪的发现是,乡村音乐是第四种最常见的音乐类型,我一点也不理解,我认为这可能是因为人们没有把它分成一系列子类型,比如“另类音乐-乡村音乐”或“极端死亡-乡村音乐-核心音乐”)

给整个数据集做词性标注花了很长时间,但是做完之后,我就可以看看每种体裁中最常用的名词和动词了。代码很简单,因为我只是使用了 NLTK 的内置 pos_tag 函数,但这使用了感知器,所以在一个非常大的数据集上运行它,尤其是像我这样使用 pandas apply 函数,需要大约 40 分钟左右。

def pos_tag_word(word):
    '''
    try to pos tag a single word
    if word is nan then return nan
    nan check done by seeing if word is equal to self
    '''
    if word != word:
        return word
    else:
        return pos_tag([word])[0][1]genre_and_lyrics[‘pos’] = genre_and_lyrics[‘word’].apply(pos_tag_word)

就单词用法而言,使用最多的名词是“I ”,这是有道理的,但看到“love”是第二个使用最多的名词也很酷,特别是在这个国家,超过 1/500 的名词都是“love ”(我猜整个“每首歌都是情歌”的事情是真的)。

按流派显示爱情一词使用情况的条形图

除此之外,最突出的一点是,嘻哈音乐似乎真的不同于其他三种流派——像“shit”和“yo”这样的词是一些最常用的名词(“yo”是名词吗?)对于嘻哈音乐来说是如此,但是在其他音乐类型中却很少。另一方面,很多在乡村、摇滚和流行音乐中最常用的词,如“日”、“时间”和“爱”,在嘻哈音乐中出现的频率要低得多。

显示按类别选择的最常用名词的条形图

我在动词上看到了同样的情况,但是程度较轻。Hop-Hop 看起来仍然是个例外,其他三个流派在最常用动词的用法上或多或少是一致的。

显示按类别选择的最常用动词的条形图

我还认为,看看哪种体裁使用了“最罕见”的名词(即在所有使用的单词中,用法的分布情况)会很有趣。所以我开始评估他们的单词总数。

select_nouns[‘word_proportion’] = select_nouns.apply(
    lambda row: row[‘count’] / noun_count[row[‘genre’]], axis=1
)

摇滚看起来有一个明显更窄的词汇库,而乡村音乐比其他三个要宽泛得多——想到这一点真的很有趣,尽管我不知道,也许这与地名有关,地名在乡村音乐中很重要(在其他流派中很少),或者也许有一个很大的乡村音乐亚类唱着关于乌贼和肩带之类的歌曲。

kde = sns.kdeplot(
    x=’count’,
    data=grouped_nouns,
    log_scale=10,
    hue=’genre’,
)

名词用法分布的 KDE 图

在浏览了数据集之后,我训练了一个朴素贝叶斯和一个支持向量机模型。在整个数据集上训练了一个支持向量机(这需要很长时间)后,我看到 75%的准确率时非常兴奋,但当我意识到这只是因为它预测一切都是摇滚(最常见的流派)时,我立即感到失望

SVM 模型的混淆矩阵

朴素贝叶斯模型表现得还可以/令人惊讶地好,并且在大约 60%的时间里做出正确的分类。这不是很多,但比我预期的要好,除了 Hip-Hop 之外,从高层次的比较来看,流派词的用法并没有显示出很大的差异。它也做得很精确,而不是把所有东西都放在最常见的类别中。

from sklearn.naive_bayes import MultinomialNB
nb_model = MultinomialNB()
nb_model.fit(train_features, train_labels)

混淆矩阵在这方面也很酷——交叉点和你所期望的有很大关系。流行音乐是一个非常模糊的流派,经常被与摇滚(对所有酷玩乐队的粉丝来说)和乡村(对所有斯威夫特来说)混为一谈。摇滚和乡村音乐很容易混淆。奇怪的是,国家预测非常准确。

NB 模型的混淆矩阵

随意检查任何代码,这些代码主要分散在几个 jupyter 笔记本中,或者如果您喜欢使用 POS 标记的数据集,不需要等待 45 分钟让 NLTK 在成千上万行上运行正电子网络,请便

你确定你在建立预测模型吗?

原文:https://towardsdatascience.com/i-built-a-predictive-model-is-b-s-a905077fe4?source=collection_archive---------14-----------------------

第 1 部分:构建预测模型是正确的吗?

UnsplashNeONBRAND 拍摄的照片

我承认——这个标题很有煽动性,但是请继续读下去,看看最后是否有意义。我想促使我写这篇文章的是我越来越强烈的感觉到,随着构建这种模型的工具和资源的增加(例如 R、Python 等)。),在我看来,如何正确使用这些工具和资源的意识有了不成比例的小增长

我发现很容易想象这样一个场景,一个希望开始做一些预测建模的初学者首先求助于 Google。如果你在谷歌上搜索“如何建立一个预测模型”,你会得到大量主题为“在不到 10 分钟内建立一个预测模型的完美方法”的文章。这些文章都很棒——它们确实教会了你构建预测模型的步骤和代码。我不是在打击他们。他们的目的很明确。然而,最让我印象深刻的是,谷歌的搜索引擎优化并没有返回我认为甚至 更重要的你是否应该建立一个预测模型,如果是,你如何正确地做?也许这些快速文章是最先出现的没关系——毕竟,我自己也写过类似的文章。我确实认为他们有价值,因为他们可以吸引新来的人进入这个领域,并向他们介绍这个主题,这可能比用刻板枯燥的学术语言写的传统同行评议文章更有价值。

然而,我们必须在新来者成为中间用户,但未能成为“中间”和更严格的预测建模方法的点上划一条线。

这就是我希望我的文章可以进来的地方。我将这篇文章作为系列文章的第 1 部分。我打算讨论三个要点:

  1. 你真的想建立一个预测模型吗?了解解释性模型和预测性模型的区别。
  2. 如果你这样做了,以下是你应该考虑的事情。
  3. 赌注是什么?对你们大多数人来说,它们很低,你可以“建立一个预测模型”然后继续你的路。对其他人来说,它变得很危险。

解释性与预测性模型

本节主要基于 Shmueli 的论文,该论文描述了解释性建模和预测性建模之间的差异——我强烈建议您阅读一下!

这篇论文背后的主要动机是,许多人将具有高解释能力的模型与固有地具有高预测能力的模型混为一谈。好吧,那是什么意思?让我们举一个微不足道的例子:

智商=年龄b1 + b*

我们假设一个人的年龄和智商成线性关系。

解释性意味着我们寻求理解一个关联解释了多少可变性(在这种情况下,是年龄和智商之间的差异)。具有高解释力的模型包括解释因变量大可变性的自变量(如年龄)。值得注意的是,在解释性建模中,我们假设一个潜在的因果假设,即某个事物会影响另一个事物。另一方面,预测性意味着我们寻求理解年龄在新数据中能多好地预测智商(即我们能多精确地估计 b1b)。

这种差异主要表现在四个方面

  1. 解释性模型试图捕捉因果关系。预测模型试图精确捕捉关联
  2. 解释性模型往往是假设驱动的。预测模型往往是数据驱动的。
  3. 解释模型为回顾型。预测模型是前瞻性的。
  4. 解释性模型侧重于最小化偏差。预测模型关注最小化偏差和估计方差

为了理解第 4 点,我们必须快速讨论一下偏差-方差权衡。你可能听说过它,也可能见过这张流行的教学图:

形式上,您可以将给定观测值的预期预测误差表示为:

EPE = Var(Y)+Bias+Var(f(x))【来自统计学习要素

其中 Var(Y)是生活中的自然可变性,偏差是“真实”关系之间的系统差异(我们永远不知道!)和我们建模的关系,Var(f(x))是我们模型中的可变性。

在解释性建模中,因为我们寻求尽可能准确地理解“真实”关系,所以最小化偏差是我们主要关心的问题。然而,对于预测建模,我们希望通过最小化偏差和我们的估计可变性来获得“最佳点”,以便最小化我们的预期预测误差。

我编制了下表,说明了当您试图构建自己的模型时,解释性建模和预测性建模之间的差异在常见步骤中是如何表现出来的。

  • NMAR MCAR 马尔(利特尔和鲁宾,2002 年)

三脚架声明

因此,理想情况下,您已经阅读了上一节,并且更加了解您是想要构建解释性模型还是预测性模型。如果您仍然对构建预测模型感兴趣,请继续阅读!

既然我们对何时构建预测模型有了更多的了解,让我们来关注一下如何构建。这种情况下的“如何”更适用于您在构建模型时必须考虑的事项。本文并不涵盖技术如何,比如选择一个模型或者用 R 之类的语言实现(我计划作为后续文章撰写)。但是我选择优先写这个,因为我认为理解如何正确地做某事是如此重要,而不是复制和粘贴代码来构建某种类型的回归模型。

幸运的是,许多人将一种叫做 TRIPOD statement 的东西放在一起,即“用于个体预后或诊断的多变量预测模型的透明报告”。它发表在多种健康杂志上,但是这个声明中的项目也可以应用于其他预测环境(商业、政治等)。).我将特别关注开发清单(相对于验证清单)中的项目,因为这篇中型文章的最初前提是构建一个预测模型。底线如下:

  • 尽可能详细地证明数据本身、模型的目的、预测因素的定义、结果的定义、模型的选择
  • 正确解释模型系数并提供置信区间(如果使用线性模型)
  • 报告维持数据的辨别和校准指标
  • 讨论使用此模型的任何限制(此模型是否可用于所有人或所有事物?如果没有,为什么?)

这真的适用于我吗?

我还想将这一小段内容提供给那些可能已经读到这里但仍想建立一个预测模型的人。是的,你当然可以!你肯定可以通过从某个地方抓取一个数据集(例如 Kaggle )来学习如何构建预测模型,并摆弄代码,看看会发生什么。我想强调我在文章开始时提出的观点,即这样做是没问题的,直到你开始建立具有潜在现实世界影响的预测模型,而没有做尽职调查。换句话说,对我来说,最糟糕的情况是,如果一个拥有某种程度权威的人连预测模型的基本方面都不了解,他就开始对预测模型发表意见。这是危险和误导的。

解释和预测是朋友

我想以一个更抽象的解释性和预测性建模来结束我的演讲。区别比什么都细微,很多人可能并不明确知道这些区别。然而,为什么人们认为这两者有如此多的重叠,这是有一定道理的。两者都非常重要。虽然预测可能不会直接解决因果关系的理解,但它可能会揭示复杂的关联,这可能会在鲜为人知的现象中产生新的假设。同样,解释性模型试图解释解释不足或无法解释。没有一个就没有另一个。但是理解这些细微差别会有很大的不同。

我在 1 个月内为一个数据工程师的职位在 8 家不同的技术公司做了 25 次以上的面试

原文:https://towardsdatascience.com/i-did-25-interviews-at-8-different-tech-companies-for-a-data-engineer-position-in-1-month-feab3e465f13?source=collection_archive---------13-----------------------

以下是我从这场马拉松和当前的数据市场中学到的东西

别忘了拉伸。【数字图像】https://unsplash.com/@strong18philip

我得到了休息的机会,为我和我的家人抽出时间。当我准备好回去工作时,我决定进行一场马拉松式的面试,并给我最多两个月的时间来寻找下一个最佳机会。我列出了 8 家公司的候选名单,总共经历了超过 25 次以上的面试,得到了 3 份工作机会🎉。由于全球疫情,所有采访都是远程进行的,所以这场马拉松才成为可能。这篇文章将分享我从这次经历中得到的想法,并对当前的数据就业市场(主要是 EU/DE 焦点)给出一些见解。

关于数据工程师市场📊

国内完全远程选项,标准时区差异可接受

虽然 FAANG 等大型科技公司已经采取了这一举措,但我可以清楚地看到,这一趋势推动了所有工作机会中的完全远程选项。

有不同级别的远程灵活性,但一般来说,最低限度是公司将授权你在他们有办事处的国家工作。他们假设你将在与你的直接队友相对接近的时区工作。

更多的机会更多的竞争

对上述观点的直接影响是,目前有更多的机会。

如果你的国家有一个像柏林、巴黎、巴塞罗那这样的“科技中心”城市,影响会更大。科技公司现在开放他们的城市边界,有时在共同工作空间开设办公室,以接触当地人才。这意味着,只要你生活在相应的国家,你就不必被迫生活在真正的科技中心城市。

也有第三方公司通过向未来员工提供本地合同来帮助初创公司在欧盟/英国发展。这些第三方服务在多个国家设有办事处,为雇主处理所有文书工作。作为一名员工,这是完全透明的,你不应该有任何税务问题。

数据工程师牛逼。

即使考虑到前面几点,数据工程师的招聘广告数量也是疯狂的。为什么会这样呢?

  • 许多人意识到,在做花哨的机器学习东西之前,你需要对你的数据成熟=你需要数据工程师。随着围绕数据的工作定义变得更加清晰,这种说法变得更加主流。
  • 数据工程师已经超出了范围。他们比以前做更多的事情,不可避免地会有更多的工作给他们。也就是说,新的职位头衔正在出现,以定义工作的特定领域,如分析工程师或数据平台工程师。随着时间的推移,这些职称可能会取代一般的“数据工程师”头衔。

公平计划是欧盟技术工作的标准

出于某种原因,欧洲文化中并没有将股权计划作为薪酬的一部分。

虽然股权在美国科技就业市场上更为常见,但如今,我能感觉到,至少在欧盟科技中心城市,它开始成为一个标准,而且它不仅仅是为最高职位保留的。

在欧洲,股权无疑是薪酬中最被低估的部分。人们嫉妒美国的薪酬,但从数字上看,他们薪酬的最大部分来自股权。

然而,这仍然不如美国市场,但嘿,这是一个进步。

如果你不熟悉股权项目,或者想对欧盟科技公司软件工程师的薪水有更好的了解,可以看看实用工程师 youtube 频道的视频

关于马拉松🏃

入围的潜在公司将顺利通过第一轮

你不想花太多时间在面试上,意识到这家公司总体上并不适合你。我意识到,如果我对我想为之工作的潜在公司做好功课,我可以避免这种痛苦。这里有几个问题是我在申请公司之前就想回答的。然后我会检查答案是否符合我的要求。

  • 公司有多老了?
  • 公司的健康程度(从财务角度来说)如何?看一看 CrunchBase 。它还能让你深入了解融资情况等。
  • 公司规模有多大?过去的成长是怎样的?
  • 公司文化是什么?他们有关于它的博客/播客吗?对 glassdoor 有什么看法?
  • 他们积极参与开源项目吗?他们的 GitHub 组织活跃吗?

有了这些基础,我就可以很容易地锁定我想要工作的地方,并在第一轮中保留一些问题。

做马拉松式的采访很棒

我时不时做随机采访,感受市场,评价自己。但是,我从来没有在这么短的时间内同时做这么多的采访。为什么?因为是全职工作。尽管如此,我觉得花一周时间开始这样的马拉松,绝对是值得的。

  • 恰当地展示自己和应对行为面试更容易。相信我,在 1 周内做 8 次后,只要你得到反馈并有所提高,你就会做得更好。大多数行为问题都非常相似。
  • 你实际上获得了更多关于你的技能、水平和薪资市场的数据。
  • 当你同时开始面试时,你将有希望在大约同一时间获得工作机会。这让你在薪资谈判的最后有了巨大的优势。

从一开始就开诚布公地谈论你的马拉松

在第一轮中,我总是提到我正在和其他公司谈判。这没什么不好,即使是在几次面试之后,因为你真的需要掌握所有信息(包括一份工作)来做出正确的决定。

结论

参加这次马拉松是我做过的最棒的事情。如果你正在寻找一个新的机会,而不是时不时地忽略招聘广告,我会强烈推荐它。

你将在未来的公司花很多时间,所以确保它是正确的,并获得足够的数据来做出好的决定!

迈赫迪·瓦扎

感谢阅读!🤗 🙌如果你喜欢这个, 在 MediumLinkedIn 上关注我吧!

我明白了一掷千金是如何运作的

原文:https://towardsdatascience.com/i-figured-out-how-deal-or-no-deal-works-kind-of-875e63a8cef6?source=collection_archive---------17-----------------------

小心,银行家

这是 a 的第三部分??部分系列,其中我揭开了方法和疯狂的交易或没有交易。想叙叙旧吗?下面是零件 一个 两个

我有理由相信我目前拥有 NBC 演播室之外最大的一掷千金数据集。我记录了超过 100 场比赛,一轮接一轮,一丝不苟,代表了近 800 轮比赛。利用这些大量的数据,我开始解开这个节目。

让我们看看里面有什么

现在我有了所有这些数据,最好的办法就是开始可视化它。作为数据验证的一部分,我运行了pandas-profiling,它给了我一些很好的统计数据和每个特性的可视化,但我得到的最有趣的东西是这个显示每个变量如何相互影响的关联图。

使用 Pearson's r 的相关图。忽略 level_0,它是一个指数,不存在。正值表示变量一起移动,负值表示变量反向移动。

我们可以立即看到变量高度相关的几个地方。之前的出价与当前的出价高度相关,这支持了我的观察,即出价通常不会在游戏过程中大幅变化。董事会平均值(或期望值)也与出价金额高度相关。我们还可以看到,游戏回合与报价呈负相关。乍一看,这似乎有悖常理。但是,大多数游戏都不是烧钱的,所以后期的游戏优惠反映了人们在消除了他们所有的大价值后试图收回一些钱。

因此,让我们做下一个合乎逻辑的事情,只是为每个游戏绘制每一轮的报价(加上一些其他东西)。当我这样做的时候,我得到了这个非常漂亮,难以理解的图表:

每场游戏过程中的出价(彩色线),这些游戏中每轮的期望值(褪色的彩色线),以及每轮的平均出价(蓝色粗线)。每一个彩色点显示了参赛选手在每场比赛中的交易位置,因此超出该位置的线显示了假设的报价。

这是非常漂亮的,如果只是有一点点帮助,但我们可以做得更多。我们怀疑银行家的出价遵循了董事会预期价值的某个比例,所以让我们把它画出来。

报价占预期值的百分比(Y)与四舍五入(X)

我们可以看到一个非常明显的上升趋势,但看到每个游戏都重叠,这仍然有点混乱。让我们后退一步,回忆一下是什么让我踏上了这段旅程。我想弄清楚银行家是如何工作的,并向你揭示他们的秘密,忠实的读者。因此,如果我想了解银行家是如何操作的,看到每一场比赛的进展并不能提供太多信息。我想去掉每场比赛的细节,只看总的数据。所以,如果我用一个方框图进一步抽象事物,我会得到这个绝对的宝石:

@银行家,这是你?

这是值得细想一下的。我们可以很清楚地看到庄家的出价在游戏过程中是如何变化的。正如人们所推测的那样,每一轮的出价都非常接近预期价值的一部分。这是我一直在寻找的确凿证据。

这张图表告诉了我们很多。很明显,在报价中有潜在的模式,但没有潜在的算法,至少在我的想象中是这样的。起初,我想知道银行家是否只是一个拿着 Excel 表格的制片人,处理数字并果断地提出报价,但很明显,无论是制片人还是扮演银行家的演员,都有人在幕后操纵并提出独特的报价(至少在正常播放期间)。

这让我想到了我的第二个体会。虽然每个提议都有一定程度的自由裁量权,但它是由董事会之外的各种事情驱动的。银行家在一个系统中工作,这个系统有规则,但是这些规则会改变,有时会被打破。庄家可以在关键时刻向参赛者提供低价,为游戏增加一些戏剧性,开个玩笑,或者只是出于纯粹的,美味的怨恨。银行家有护栏,他们有时仍然会超越护栏,但在大多数情况下,报价会根据董事会和本轮的预期价值在一定范围内波动。这种故意的混乱是不会说话的电脑做不到的。

虽然这些认识意味着我不能逆向工程一个完美的假银行家算法来为我运行游戏,并完全取代银行家,但这意味着我仍然可以通过一些机器学习创造一个半完美的银行家近似器(正在申请专利)。有了这种力量,我可能比除了银行家自己以外的任何人都更清楚这个游戏是如何运作的。

运气、时机和勇气

这就包括了我们最喜欢的注册金融分析师,所以让我们转向参赛者。Howie 经常称 DoND 为“运气、时机和勇气的游戏”一个玩家需要这三样东西才能在游戏中真正成功。我见过如此多的参赛者拒绝了他们在比赛中的最高出价,随后只是兴登堡他们的董事会,最终带走了一小部分如果他们在正确的时间离开他们可以得到的东西。

所以,让我们来看看参赛者在比赛结束时拿走了什么。只是为了好玩。

只有一个人在游戏的最后阶段还价,成功击败了他们的最佳报价。

在这个图表中,零意味着有人接受了他们游戏的最佳报价。我们可以看到,大多数人没有接受他们的最佳报价,错过了许多潜在的奖金。事实上,平均理论“损失”超过 10 万美元!这被一些大的异常值扭曲了(这个可怜的傻瓜错过了 840,000 美元),但即使是中值损失也是 66,000 美元。参赛者经常把他们的运气推得有点过了,而没有考虑到时机。

*<caveat>*

我应该说,这不是根据某人的情况来评估他是否做了一笔好交易——我只是在考虑他们是否应该接受银行的提议,而不是他们是否应该坚持到底。你可以争辩说这两件事是相关的,你可能是对的!考虑你箱子里的东西是这个游戏的一个关键因素。但由于我专注于银行家的报价,我通常不会记录某人的情况,除非他们到了最后,因为那是他们赢得的。所以,我不能绝对肯定地说这些参赛者的决定是好是坏。但他们中的大多数人可能做了错误的决定。

</caveat>

赢意味着侥幸赢了比银行家期望的更多的钱。该节目存在的事实意味着 NBC 愿意接受每个玩家 131,478 美元的假设平均支出(在我的数据集中,平均实际支出是 108,332 美元,所以他们做得很好)。所以,如果你能得到比这更高的报价,你就已经打败了银行家。这是对该剧所利用的游戏的根本误解。一掷千金这不是一个关于信念的游戏,不管它有多想要。这绝对不是在你的案例中获得一百万美元并坚持到底。

这不是大多数玩家玩游戏的方式。在游戏中,每个人——支持者、观众,甚至我们闪亮的男孩豪伊——都积极鼓励处于危险境地的参赛者简单地相信他们的案子在棋盘上有最大的价值,而事实上,在这一点上他们只是在赌博。这部剧纯粹是胆量。有时它会起作用,参赛者的勇气会得到相应的回报,但更多的时候,它会灾难性地失败。

如果你愿意像赌博一样对待这些决定,你可以在游戏后期做出更好的决定。但是如果你在不利的情况下仅仅依靠盲目的信仰,你很可能会崩溃。

显示哪一轮竞争者接受报价的直方图。到了第 9 轮,人们通常会选择一张不好的牌。

当然,这才是节目的症结所在!说“不,不要追求 100 万”并不令人兴奋!只要根据概率尽量把你赢的钱最大化!”那场演出糟透了!我不会看的!我们希望看到有人不顾一切坚持到底,把那 100 万美元带回家!

每个参赛者的决定中有许多不同的因素,这些因素决定了带着几块钱离开还是带着一大笔钱离开。虽然我一直专注于模拟银行家的报价,但我不能假装参赛者的决定没有影响银行家。尽管这个节目试图说服我们,尽管我试图证明事实并非如此,但银行家和我们其他人一样也是人。

我无法提出一个明确的数学模型来判断某人是否应该接受交易。至少现在还没有。但现在,我认为我们必须同意豪伊。

这一切都归结于运气、时机和勇气。

我帮助我的朋友转向数据科学职业——以下是我的方法

原文:https://towardsdatascience.com/i-helped-my-friend-switch-into-data-science-career-here-is-how-52c48553019?source=collection_archive---------25-----------------------

社区笔记

如果你使用这种策略,你可以在赚钱的同时转向数据科学

Aman ShrivastavaUnsplash 上拍摄的照片

你们中的许多人希望将职业生涯转向数据科学。我相信你做了一些研究,找到了最适合你的道路。然而,你还不确定是否应该接受它。对于像你这样的专业人士来说,有很多方法可以实现这种职业转变。您可以参加数据科学训练营,学习可能不适合您日常日程的基础知识。你可以走传统的道路,参加一个为期 1-2 年的大学项目。你可以通过网上资源自学所有的东西,这些资源免费且容易获取,但需要很长时间。也可以采取一个我们(我和我朋友)都采取过的策略:“学有所得”。采取这种策略,你可以在改变职业的同时赚钱,这对我们很多人来说都很重要。

停止把钱花在各种数据科学课程和项目上。你最好选择一个更聪明的策略:“学习和赚取”。

首先,让我介绍一下我的朋友以及我们的友谊是如何开始的。小学第一次见面的时候我们才 12 岁。然后我们去了同一所高中,在那里我们成为学习伙伴,一起准备全国大学入学考试。我们俩都通过了考试。说实话,他甚至做得比我好!我选择了一个计算机科学项目,他注册了两所著名大学的一个机械工程项目。我的机器学习之旅是从那些年开始的,他直到后来才获得了对数据世界的任何接触。

在这篇文章中,我想在三集里分享我的朋友是如何使用“边学边赚”的策略转行到数据科学行业的。希望这能帮助你做同样的事情。

第 1 集——根据你的“领域知识”组建一个团队来开展一个小项目。

2015 年,我和我的朋友承担了一个小项目,建立一个用于汽车行业的粒子检测解决方案。我们必须设计和建立我们的数据收集系统,这需要一个流体动力学的专家。我的朋友是流体动力学专家,我是数据科学专家。我们为那个项目组成了一个伟大的团队。他设计并建造了一个惊人的数据收集装置。他处理了所有可能发生的潜在缺陷。例如,我们发现,如果我们不关心细节,由于流体动力学定律,粒子很容易被捕获在成像室中。在这个项目中,他大致熟悉了数据科学项目的各个方面,例如(a)如何收集高质量的数据,(b)如何测量模型性能,以及(c)机器学习管道如何工作。他通过建立数据收集系统和从汽车行业获得项目,为团队增加了巨大的价值。现在,你可以看到你的领域知识和专业关系网有多重要。

举例来说,如果你是一名化学工程师或机械工程师,并希望成为一名数据科学家,你肯定可以从你的工具集中为数据科学项目带来很多价值。你的领域知识很重要。

第 2 集—使用最佳在线课程学习数据科学基础知识

我的朋友已经决定将他的职业生涯转向数据科学。他想参加一个传统的学术项目,他不确定哪一个对他更有帮助。他打电话问我的意见。他找到了几个知名工程学院的在线项目,让我给他挑一个。猜猜我告诉他什么了?没有。我没有那样说,因为我不相信大学的课程。我一个一个地看了他们的教学大纲,我真的发现他们在那些项目中提供的东西对我的朋友没有帮助;反而把他的钱拿走了!我向他推荐了几门可以免费学习的在线课程,每门课程都有其特定的目的。你可以在这里找到那些课程。他可能没有修完所有的课程,只是浏览了最重要的部分。现在,他在数据科学方面获得了更多的知识。尽管如此,他仍然没有准备好接受数据科学的面试。

首先,您必须学习数据科学基础知识。你会学到工作中的细节。另外,如果不知道你的目标是什么,就没有机会学习所有的东西。

</6-youtube-playlists-in-data-science-for-every-educational-purpose-5bee960c4d01>

第 3 集-组建一个团队来实施一个大项目,以便通过实践来学习编码和开发

最后一集。2020 年,我和我的朋友决定写一份提案,目标是一个大项目(~20 万美元)。他已经接触了一个行业数据科学项目,并学习了机器学习的基础知识。现在是他在一个大型项目中提升技能的时候了。我们一起写了建议书。技术部分大部分是我写的,但他润色了文字,以增加我们赢得提案的机会。我们内部进行了多次讨论,这对他来说是一个学习的机会。对我们俩来说,这是一场双赢的游戏。我可以利用他的帮助来获得项目,他也可以利用我的帮助来学习数据科学。我们最终赢得了这个提议,我们开始实施这个项目。写那份提案激发了我写一篇关于如何构建人工智能咨询服务的文章。

我们的项目充满了 SQL 和 Python 代码。他是一个聪明的专业人士,所以他可以很容易地赶上 SQL 编码。他出色的 SQL 编码技能帮助我们快速进行数据探索和数据理解。当他在进行 SQL 编码的时候,我构建了一个 ML 管道,并设置了协同工作。我需要教他 Git 技术,以确保我们可以轻松地合作。这启发我写了一篇关于如何用简单的词语学习 Git 的文章,这篇文章在媒体上广为流传。从那以后,项目进展顺利。为什么?因为我们知道我们必须使用什么特性,ML 管道已经准备好训练和测试各种机器学习模型。

当你和你的 ML 工程师朋友组成一个团队时,你可以负责代码量较少的部分,比如使用 SQL 编码的数据探索。您的 ML 工程师朋友可以设置管道,并带您完成训练和测试 ML 模型的过程。

https://pub.towardsai.net/a-letter-to-those-data-scientists-living-in-north-america-9039b1925f4e

临终遗言

在这三集之后,我的朋友准备转行了。他学到了基本原理,并获得了宝贵的行业经验。在我们完成这个大项目几个月后,他找到了一份工作。

我把这种转换职业的策略称为“学习和获得”。作为一名职业人士和爸爸/妈妈,你不能离开你的工作去开始建立一条新的职业道路。这是不可能的。另一方面,你也不想推开你的梦想和目标。这就是为什么我相信“边学边赚”策略真的能帮到你。所以,我建议找一个你在数据科学领域的好朋友,开始和他/她一起走这条路。我保证你们都会享受这次旅程并从中获益。太棒了!

感谢阅读!

如果你喜欢这个帖子,想支持我…

**https://pedram-ataee.medium.com/membership **

一、♡不可复制的研究

原文:https://towardsdatascience.com/i-irreproducible-research-dbc48eb140ac?source=collection_archive---------17-----------------------

思想和理论

现实世界研究的更好的实验协议

图片来源:蔡斯·贝克

机器学习研究的黄金标准是实验的“顺序”模型:你有一个基线、你的实验和一个固定的、预先确定的测试集。你在测试集上评估你的基线,得到一个基线数字。然后你在测试集上运行你的实验,得到另一个数据。然后你比较两者。假设您发布了所有这些工件,任何人都可以复制结果。这是很好的科学。

再现性一直是科学进步的基石,也是无数研讨会的主题,特别是在机器学习领域。虽然提高研究结果再现性的尝试通常是完全正当的,并且明显有益于社区,但它们也带来了将这种非常狭隘的精确再现性模型作为唯一可接受的标准的风险。

学术机器学习界很少意识到,出于非常基本的原因,并非所有的研究都具有完美的再现性,尽管如此,如果你正确设计实验协议,还是有科学合理的方法来实现统计再现性。我相信,作为一个群体,我们需要更好地教育自己,特别是在研究主题是现实世界表现的领域,例如我的实验室正在进行的橡胶碰到马路机器人研究。

谷歌进行的许多实验并不完全可重复,因为它们基本上是关于评估模型对现实世界的影响。现实世界总是在变化的:用户与系统的交互在很大程度上随着昼夜循环、季节变化、世界大事,甚至更难以捉摸的长期社会趋势而变化。更重要的是,用户模式的变化是模型本身变化的结果。

如果你关心你的模型对现实世界的影响,那就没有测试集。

你不能按顺序进行你的实验:今天是你的基线,明天是你的实验,因为在这两天之间世界已经发生了变化,你的数据将没有可比性。你也不能保留昨天的测试集,因为你的数据会随着你的模型发展:如果你的模型向用户提供一组搜索结果,而价值指数是人们是否会点击它们,那么你就不能回到昨天的用户那里,问他们如果得到一组不同的结果,他们会怎么做。

解决方法是平行实验设计,也称为 A/B 测试。对于每个测试实例,您随机选择您将运行实验的哪一部分,基线还是实验。这种简单的处理方法消除了由于分布的潜在变化而产生的任何差异,即使您的评估设置处于不断变化的状态,您也能获得统计上有效的结果。

这让我们对 A/B 测试及其作为科学工具的实用性产生了最大的误解:例如,它经常被用于 UX 设计,以观察网站布局的微小变化是否会影响用户点击,或者阴影的细微变化是否会使广告更具吸引力。因此,它被认为是改善微小效应置信区间的工具。由于 ML 研究人员与置信区间的关系充其量是一种勉强的容忍,A/B 测试与 ML 研究的实际相关性通常被忽视。

并行 A/B 测试完全与大效果测试相关,尤其是当你的评估设置不能被严格控制的时候。

我的同事(*)最近在机器人研究领域提供了一个生动的例子。在机器人领域建立一个可重复的评估设置是众所周知的困难:机器人移动位置,设备和物体磨损,照明变化,机器人操作员以微妙的方式影响每次实验后设置重置的方式。臭名昭著的“重置问题”是一个非常棘手的问题,因为执行一个好的重置协议,将你的机器人设置恢复到一个已知的固定状态,可能与一开始进行实验一样困难。

他们采用了我们最简单的设置之一,即在一个箱子内筛选相同的泡沫塑料方块,并测量这种完全受控环境的可重复性。

简单的机器人分割设置。来源:谷歌的机器人技术。

我的同事在几天内连续进行了 11 次筛选实验,并测量了每次实验的成功率和置信区间。根据基线运行的性能标准化的结果如下所示:

相同实验的可变性。来源:谷歌的机器人技术。

如果每个实验都是不同的模型,我们会说实验#7 好了 2%,实验#5 差了 5%。我们甚至会有足够紧的置信区间来说服你。但是这里的实验没有区别,它们都是一样的。请注意,这不是缺乏数据的情况:更多的数据只会缩小置信区间,而不会相对于基线移动它们的位置。无法解释的变化完全落入环境的“未知的未知数”中。这种设置对于真实的机器人实验来说非常简单:许多机器人论文报告了顺序治疗实验,这些实验比这种实验有更多潜在的无法解释的可变性。更重要的是,如果我们没有测量这种日复一日的可变性,我们甚至不会猜到它的存在。很少有研究人员首先想到测量他们的实验设置中的内在可变性,因为让我们面对它:这是工作,只有坏消息可以从那条探究路线中出来。

这里的教训是,对于这个特定的实验协议,我们绝对不能相信任何低于 10%的性能差异——如果没有大量的重复验证,我甚至不知道我是否会相信 10%的差异。是不是没希望了?当然不是。进入平行测试。

一旦你摆脱了完美再现性的幻想,你就可以享受统计再现性带来的令人愉快的自由,并且仍然可以做可靠的科学研究,同时获得更高的数据效率作为奖励。

这是三天的完全相同的实验,但这次基线与实验平行进行,在每集随机选取。

平行相同实验的可变性。来源:谷歌的机器人技术

注意现在这些数字是多么的一致,告诉你在基线和实验之间确实没有区别。像这样的中性 A/A 实验是最难的统计测试,任何实际影响性能的实验都能够显示出清晰的信号。

这是在实验设置没有任何变化的情况下进行的,只是实验方案略有不同。

那么为什么大家都不这么做呢?让我们来看一些挑战。

一个常见的误解是,因为每个实验都要反复运行基线,所以需要两倍的评估数据。只要您的设置中存在一些可变性,这就不是真的:您从始终运行基线中获得的统计效率的收益可以抵得上一个数量级的数据,或者在最坏的情况下抵得上无限量的数据,正如我们在上面看到的。使用重叠实验有更聪明的方法来获得更高的数据效率——这可能是谷歌最被低估的研究论文,但正确地利用这一点需要比大多数研究人员可能愿意在这个问题上投入的工作更多的工作。

一个缺点是你的基线必须总是可运行的,最好和你的实验在同一个二进制文件中,并且是动态可切换的。不可否认,这需要对你的软件进行工作和仔细的设计。这样做的好处是,您还可以保护自己免受意外的 bitrot,在这种情况下,一些合作者意外地在您的下面更改了一些影响基线性能的东西,而您没有注意到,这在任何共享代码库中都有可预测的规律性。系统中的许多变化是微小的,以微妙的方式影响原始性能,最终与手头的科学问题无关。不必控制所有这些绝对是一种解放。

这种设置的一个明显的优点是,你可以动态地监控你的置信区间,当你确信自己的实验甚至有点负面时,就决定停止实验,这通常需要更少的数据来确定。如果实验是积极的,很好,只要你需要得到适当的误差线,就运行它,如果你不是测量效果的大小,而仅仅是显著性,你也可以早点停止它。

但是让研究可以被其他人复制呢?您仍然可以发布基线和实验模型,以及实验协议,任何人都可以在他们的复制系统上生成自己的数据,以说服自己这些发现的有效性。回想一下,这里的前提是,您使用的数据是而不是可重用的,要么是因为它本质上是短暂的,要么是不可移植到同一研究机构的任何未来实例中。

并行测试的另一个主要好处是保护你免受许多偏见的影响。主要的一个是实验者的偏见:因为你不知道哪个数据样本被传送到实验的哪个部分,你不能欺骗自己相信一个结果而不是另一个。它还可以防止您意外地调优测试集,因为在评估中设计了一定程度的随机性。

强化学习和机器人技术的另一个更具体的偏见是不完美的重置:如果实验的一个部分导致重置机制的行为与另一个部分略有不同,那么你可能会有细微的差异,而这些差异不会被注意到。我们已经看到 RL 系统操纵它们的环境来产生特定的重置状态,从而提高它们在后续情节中的成功机会,或者甚至以这种方式跨情节传递信息。

事实上,并行实验协议通常可以首先显著减少或消除重置的需要:如果您的系统在状态空间的有效部分终止了每一集,因为没有办法知道实验的哪一部分导致了环境的特定配置,所以您可以经常运行终身实验,没有重置,也没有跨实验部分的偏差。

相同基线的绝对可变性。来源:谷歌的机器人技术。

你要放弃的一件重要事情是拥有一对整洁的“基线准确性”和“测试准确性”结果的舒适,你可以把它们写在一篇论文上,这是每个学术评论者都期望的。每个实验都有自己的基线,而基线又有自己的置信区间。您的绝对测试精度数字取决于测量的日期,但它仍然是完美的,因为您每次测量的两臂之间的差异都会进行统计显著性评估。

尽管如此,评论家接受这一现实的障碍仍然很大。从绝对的、可复制的真理到相对的、统计的真理的飞跃是令人不舒服的。这是许多科学领域,如药物开发,出于必要而做的事情,但这对机器学习来说仍然是陌生的,在机器学习中,退回到离线评估通常是一种选择。这种对真实系统实验的机构过敏反应的问题是,在机器人学等领域,真实世界的表现实际上是房间里的科学大象,而违背那些原本坚实的科学协议的学术实践正在积极地阻碍我们。做真实世界的实验是困难的,有风险的,反对这种研究的学术动机应该随时反对。

我们在该领域的太多集体精力都花在了试图提出新的、密封的、完美的基准上,这是非常难以建立的,有点不切实际地追求让机器人看起来更像 ML 研究。最终结果是,除了极少数例外,大多数这方面的努力都止步于模拟基准和用现实主义换取可重复性。这些努力仍然有很多优点,但它们只占等式的一半左右,而且通常建造它们的纯粹费用会分散研究人员对实际科学追求的注意力。其他人试图定义元基准,通过不首先精确定义任务或实验协议来规避可重复性问题。作为一个固执于协议和过分详细说明问题的无用性的人,我认为这是一个积极的大方向,即使它将实际执行的许多困难方面留在桌面上。

现在是我们在机器学习和机器人研究中拥抱那些简单工具的时候了,这些工具使“不可重复”的研究可重复并具有科学合理性。我在这里描述的协议没有一个是特别难实现的,它们有希望让现实世界的科学变得更好、更容易、更快。

()本文背后的许多灵感和实际数据都要归功于 Arnab Bose、邝宇恒、Anthony Brohan 和 zvan Surdulescu 的惊人努力。观点是我的。*

仅仅学习了 4 个月,我就在一家人工智能初创公司找到了一份工作

原文:https://towardsdatascience.com/i-landed-a-job-at-an-ai-startup-after-studying-for-only-4-months-76d816117a1c?source=collection_archive---------11-----------------------

我学了什么,怎么学的,什么时候学的,学到了什么程度

照片由克里斯蒂娜·莫里路派克斯拍摄

我即将完成我的航空航天工程学士学位,我唯一确定的是,我不想做一名航空航天工程师。不太明朗的未来。

我的论文答辩就在几个月前,我偶然发现了神经技术领域。我一直喜欢心理学和一切与人类思维相关的东西,所以它引起了我的注意。“技术”部分听起来像是我可以从我的背景中进入的东西,但我不知道如何从我所在的地方到达那里。

我推迟了这个决定,但很快我就离开了大学,不得不做出选择:“我要么沿着这条路走,做它期望我做的事情,要么不顾一切,去追求召唤我的东西。

我选择了后者,定义了一条在神经科技领域找工作的路径。然而,我缺少一半的知识和大部分的技能。我需要一座桥来让这个过程不那么陡峭。所以我定义了一个:

“航天工程-> 人工智能 - >神经科学/神经技术”

容易吧?艾在中间等着我。我有足够的数学背景自学 AI。与此同时,人工智能离神经科技足够近,可以从那里开始飞跃。

我想研究人工智能足够长的时间,以便找到一份工作,然后跳到人类的大脑。我在接下来的一周开始。这是 2017 年 9 月下旬。

我不得不优化我能得到的每一个资源来达到我想要达到的目标,所以我非常仔细地计划我的学习。2018 年 1 月结束我在一家人工智能初创公司工作

我是怎么做到的?让我们开始吧!

学习任何东西都有 4 个关键方面:你必须学习什么,你如何学习,你何时学习,以及你学习到什么程度。

1.我所学的

我混合了各种类型的资源,并特别注意评估它们的可靠性。

在大学里,你所学的东西已经为你选定,但说到自学,你必须自己去寻找。

首先,让我们弄清楚一些事情:如果你想知道任何新的东西,你必须学习很多东西。任何一个领域都大到足以让任何人花上几年时间去对它有一个大致的了解。这意味着我不可能在短短 4 个月内了解 AI 的一切。我所做的是为了我认为更紧急的事情。

人工智能是计算机科学的一个分支。在人工智能中,有一个领域因其行业吸引力而脱颖而出:机器学习(以及其中的深度学习)。

于是我搜索机器学习资源,偶然发现了两门非常受欢迎的课程:吴恩达的《机器学习》和杰佛瑞·辛顿的《机器学习的神经网络》(可惜已经没有了)。这两门课程是我进入人工智能世界的第一步。

一旦我涉足其中,我可以环顾四周,看到许多其他资源。我几乎可以在网上找到任何我想要的东西。机器学习(ML)和深度学习(DL)在 2017 年末已经足够成熟,可以很容易地找到我想要的一切。

在这篇文章中,我将我使用的主要资源分为四类:课程、博客、书籍和论文。这些主题及其复杂性各不相同,所以你必须找出哪些更适合你的目的(例如,我想找份工作,所以深入研究人工智能的理论基础可能不是最重要的事情)。

对我来说,选择资源的标准一直是来源的可靠性,即:作者是谁,有多少人推荐内容,资源的影响力有多大等等。

下面我会选择一些对我更有帮助的。

课程:

  • 机器学习 吴恩达在 Coursera。非常容易理解,也可以说是对以前没有 AI/ML 概念的人来说最好的入门方式。
  • 用于机器学习的神经网络。与其他两门课程相比,这门课程更具理论性,也更难理解,但 Hinton(和他的团队)是 2012 年开始的 DL 革命背后的领先科学家之一,因此他是值得尊敬的人。
  • Coursera 中吴恩达的 深度学习专精 。前几部的后续。如果说 ML 在 AI 内部脱颖而出,DL 在 ML 内部脱颖而出。这是一门很好的多学科课程,对 DL 的不同分支(包括计算机视觉、CV 和自然语言处理,NLP)有所深入。

还有更多最近的课程,但这些是我的开始,所以他们在这里。我建议去寻找最适合你的课程,然后去参加。

博客:

  • 走向数据科学 (上媒)。我想你们都知道这个。在学习数据科学、人工智能、ML 或 DL 方面,排名第一。
  • 机器学习掌握 。你是否厌倦了所有以“什么是向量”开头的枯燥书籍和课程?你想让你的手陷入代码的泥淖吗?这个博客是你的地盘。
  • 提炼 。“机器学习研究要清晰、动态、生动。”这个项目背后的大人物。讨厌卷积、权重、梯度下降这样的抽象概念?在《蒸馏》中,你可以通过视觉更好地掌握它们。
  • 安德烈·卡帕西的博客 。安德烈·卡帕西在人工智能界是个响当当的名字。他曾在 OpenAI 和特斯拉工作过。
  • 塞巴斯蒂安·鲁德的博客 。对于那些想了解更多 NLP 的人来说,这是一个不错的博客。
  • Colah 的博客 。我在这里学到了关于 LSTMs 的最多的东西。
  • Adit Deshpande 的博客 。我在这里学到的卷积神经网络(CNN)最多。

肯定还有其他精彩的博客。这些只是对我帮助最大的。

入门论文:

有很多其他的文章可以帮助你更好地理解这些架构和模型是如何工作的,如何最好地实现它们,什么是最佳实践,等等。也有论文对这些论文进行了跟进,或者提出了创造历史的改进。

这里有太多要说的了,但是一旦你读了这些,并且开始熟悉这些概念和作者,你将处于一个非常好的位置,从那里开始下一步。

如果你想明天就开始编码并有一个工作模型,其中一些不是最好的论文。通常来说,博客和课程要好得多。论文让你了解技术背后的科学,但通常要密集得多。

书籍:

  • ****深度学习(古德菲勒,本吉奥&库维尔,2015)。面向 ML/DL 学生的深度教材,假设读者具有一定程度的计算机科学背景。
  • 用 Python 进行深度学习 (Chollet,2017)。从编码的角度来看,人工智能适合任何背景,尽管一些 Python 知识会更好。

书永远比论文或博客深刻。如果你想了解这个领域的每一个角落,那么你绝对应该读一些相关的书籍。

2.我是如何学习的

我定义了一个好的学习方法。

如何学习是很多人表现不佳的地方。我们在大学里学不到这些,所以我们必须想出自己的学习方法。一旦你找到了你需要的所有资源,你如何获取所有的信息并将其转化为内化的知识就是关键。

我制定了一个计划,以三种方式学习:

  • 阅读和听力
  • 划线和书写
  • 自学

阅读是学习的第一步(在这种情况下,也是听课程)。而且做的全面很重要。如果你不理解你正在读的东西,那么读点什么也没有用。

要做到这一点,我们需要把我们之前所读的知识整合到 学习 记忆

但是阅读并不是做到这一点的唯一途径。我也划线并写下我正在阅读的内容。写作帮助我用自己的话重新表达我正在学习的概念。如果我不能做到这一点,那么我就不能很好地理解这个概念。

然而,我认为我的学习方法中最重要的方面是我不断地评估我的理解。 由自己“教导”

根据我对自己演讲的感受,我知道我的思路是正确的。我有一段独白,试图理解,好像在教别人。我问了一些我试图回答的问题,并试图将我正在学习的知识与我已经掌握的知识结合起来。

如果我的结论是我不太明白,那么我会诚实地说:“这个我不明白。”然后我会从新的角度重复这个过程。

奖励提示:

  • 利用多个视角把握单一概念:

如果我在阅读、写作和自言自语后不能理解某些东西,那么我会简单地用另一个来源重复同样的过程。实际上,即使我一开始就理解了这个概念,我也经常合并来源。

我认为从不同的角度学习一些东西可以让你创建一个概念的 3D 心理图像,就好像赋予它形状和形式一样。这是关于用不同的词来描述在我脑海中“咔嚓”一声的同一件事。

"有时改变一下视角就能看到光明。"

—丹·布朗

  • 使用可视化:

AI 很抽象。

将概念转化为具体的视觉效果会有很大帮助。理论理解太难,否则难以把握。例如,通过希尔类比来学习梯度下降比看方程要好的多。我们的大脑适合处理视觉输入。 正如派克所说的:

“[……]灵长类动物大脑中处理视觉信息的部分远远多于处理其他感官信息的部分。”

我们通过视觉化更好地学习记忆

  • 把概念和你已经知道的东西联系起来:

试着把新概念和其他更普通的东西联系起来。人工智能概念对我们的日常生活来说是陌生的,所以将它们与你的日常经历联系起来以使它们更快地融入你的技能是有用的。

例如,将 CNN 理解为能够识别线条、形状和形式以及物体的系统,比试图从数学上理解它们要容易得多。

3.我学习的时候

我养成了良好的学习习惯。

如果你不坚持一个习惯,有一个好的学习方法是没有价值的。写作或任何我们想要擅长的事情都是如此。我们生活中想要改善的任何事情都需要** 一致性 **

“决定我们生活的不是我们偶尔做的事情。这是我们一贯的做法。”

―安东尼·罗宾

有时候你不想学习,可能是因为你很难理解一个概念,或者你开始厌倦数学和统计学。

不管是什么,都不重要。你的首要任务是继续前进。即使你只学习半个小时。如果你翘了一天课,第二天你就很难再继续学习了。

如果关于“什么时候”最重要的事情是习惯(至少对我来说!),那么第二件事就是有一个每日或每周的时间表。试着合理安排你的一天,当我们这样做的时候,我们的大脑会更快乐,你也会更容易日复一日地这样做。

我不得不说,我对不能坚持这个建议感到内疚(尽管我最近有所改善),但我认为它非常重要。

4.我学习到什么程度

我明白我必须明白的东西,并牢记我找工作的目标。

理解需要时间。这些概念必须在你的大脑中扎根。直到你能够用一个概念去理解其他更新的事物,你才真正理解它。如果我还不明白,我不会简单地一遍又一遍地重读同样的东西,我会尝试其他的方法或视角。

然而,在学习新东西的时候,有一件事我们应该记住:有些东西是给你去理解的,有些东西是给你去使用的。学会识别不同之处。

你不需要理解计算机如何工作来使用它。但如果你想成为一名机器学习开发者,了解神经网络是如何工作的会很有趣。然而,完全理解梯度下降算法背后的数学可能不是很有用。

这总是取决于你的目标。只有当你想进入学术界研究人工智能时,你才需要真正了解理论背景。否则,你只会使用大部分的东西。

要知道你应该理解什么,你应该使用什么,你必须找到你的方法。向专家学习,阅读博客和观看课程。

最后,你会知道你必须知道的。

除此之外,永远不要迷失在学习中非常重要。保持自我实现是必要的,多知道一件事总是好的,但不要以此为借口,永远不要在公司工作。

如果你想说服自己还没准备好,你总会想出一个可信的借口。

真相是这样的:最好不要对一份工作做好充分的准备。如果你已经做好了充分的准备,那么你的目标就太低了。工作意味着让你成长,让你学习,挑战你。

当我觉得自己开始了解人工智能时,我知道是时候找份工作了。

外卖食品

明确你要学习什么,如何学习,什么时候学习,学习到什么程度。

  • ****研究什么:寻找最好的资源并评估其可靠性。使用不同的类型(课程、博客、书籍、论文等。).一旦你进入了,你可以简单地按照你遇到的提示来知道下一步该关注哪里。
  • ****如何学习:定义一个好的方法。尝试将被动学习和主动学习结合起来。读和听,但也写和说。甚至,如果有机会的话,去给别人上课或者讲解。有证据证明结合学习方法的价值。
  • ****何时学习:养成习惯,明确时间表。一致性是关键,因为在任何你想做得更好的事情上。还有,试着有一个每日或/和每周的例行公事,并坚持下去(我自己也为没有这样做而感到内疚,但我承认它的重要性)。
  • 学习到什么程度**:去你知道的点你知道的,但只限于你知道你必须知道的东西。剩下的,简单的学会使用它们:学会你应该知道的和你应该使用的区别(这取决于你的目标和你使用的资源会在这里帮到你)。另外,不要过度延长学习过程。你永远不会觉得准备好去找工作了。设定一个期限,并坚持下去。

我模拟了棒球接下来的 50 年

原文:https://towardsdatascience.com/i-simulated-the-next-50-years-of-baseball-acaffb970a48?source=collection_archive---------31-----------------------

图片由提供,备货

1920 年 5 月 1 日。布鲁克林知更鸟队对阵波士顿勇士队,这是有史以来局数最长的一场比赛。26 局后,比赛因天黑而结束,他们打成平局。这场游戏会持续多久?连续 20 局都没有得分,所以这场比赛会不会持续到 30 局以上?不幸的是,我们永远不会知道最长的 MLB 比赛会持续多久……但是我们可以模拟这场比赛来找出现代棒球的极限,也许可以弄清楚罗宾斯和勇士队还剩多少局没有得分。

虽然这始于试图找到一个打破局数记录的游戏,但我意识到我有所有必要的工具去追求其他一些疯狂的记录。因此,我的额外目标是打破一些更荒谬的得分记录,如一场比赛中最多的组合得分(1922 年费城人队和小熊队,49 分),一场比赛中最多的组合本垒打(2019 年响尾蛇队和费城人队,13 分),甚至可能是最大的井喷(2007 年流浪者队和金莺队,27 分)。使用 2021 年 MLB 赛季的击球统计数据,我模拟了直到 2070 年的每个赛季(121,500 场比赛),发现了一些非常有趣的结果。

为了让这个模拟工作,我需要 2021 年 MLB 赛季的真实数据。在制作这个项目的时候,大约有 121,000 次击球亮相,有 12 种不同的击球结果。将这些与基础上的不同场景结合起来,可以产生与现实生活非常接近的模拟。下面显示了一个场景示例。这是为了如果垒是空的,击球手击出一垒或二垒安打。

if sum(bases) == 0 % if nobody on baseif indicator == 1 % if batter hits a singlebases(3) = 1; % sets first base to occupiedouts = outs + 0; % no outs addedif top_bottom == 0 % if top of inning, gives stats to away teamrunsA = runsA + 0;hitsA = hitsA + 1;rbiA = rbiA + 0;else               % if bottom of inning, gives stats to home teamrunsB = runsB + 0;hitsB = hitsB + 1;rbiB = rbiB + 0;endelseif indicator == 2 % if batter hits a doublebases(2) = 1; % sets second base to occupiedouts = outs + 0; % no outs addedif top_bottom == 0 % if top of inning, gives stats to away teamrunsA = runsA + 0;hitsA = hitsA + 1;rbiA = rbiA + 0;else               % if bottom of inning, gives stats to home teamrunsB = runsB + 0;hitsB = hitsB + 1;rbiB = rbiB + 0;end

为每个基本场景和击球事件添加了类似的代码副本。

在模拟的 50 年中,平均打击率为 0.239,非常接近实际的平均打击率 0.241。同样,模拟中的上垒率是 0.315,而现实中是 0.316(至少在 2021 赛季)。现在我们有了现实的精确描述,我们可以开始模拟游戏了。

看看能否打破 26 局的 100 年纪录。在 2048 年 MLB 赛季的第 983 场比赛中,经过艰苦的 28 局比赛,A 队以 5-3 击败 B 队,成为 MLB 历史上最长的比赛。在 19 局中以 3 比 3 打平后,A 队终于在第 28 局开始时以一局两分的成绩打开了局面,然后在第 28 局结束时将 B 队拒之门外。

在 2062 年 MLB 赛季的第 1257 场比赛中,A 队以 26 比 2 的比分击败 B 队,成为 MLB 历史上第三大井喷(24 分差)。虽然我可以再模拟几组 50 年,试图找到一个创纪录的分数,但我认为最好还是欣赏一下 2007 年流浪者队以 30 比 3 战胜金莺队的比赛,这是 MLB 历史上最大的井喷。

在 2050 年 MLB 赛季的第 1045 场比赛中,A 队以 18 比 9 击败 B 队,两队在比赛中一共打出了 14 个本垒打。这打破了 2019 年响尾蛇队和费城人队对抗并联合 13 场的纪录。

在 2070 年 MLB 赛季的第 2302 场比赛中,B 队以 19 比 14 击败 A 队,共得 33 分。虽然这对两支球队来说都是一个不可思议的壮举,但不幸的是,它没有接近 1922 年 49 分的纪录。看起来我们将不得不等待超过 50 年才能看到任何两支球队接近这一纪录。

对于我想打破的最后一个得分记录,我选择了一场比赛中的组合大满贯。在 2067 MLB 赛季的第 1509 场比赛中,A 队以 15 比 9 击败 B 队,获得 4 个大满贯。这打破了 1986 年至 2015 年期间 4 支不同球队创下的 3 次大满贯纪录。

在这个模拟中,我可以采取许多不同的方向。最长的无安打比赛还是完美比赛?一场比赛最多三分球?最多连续本垒打?所有这些都可以用当前的程序实现。我也可以采取更具分析性的方法,试图找到一个在看分数时最重要的统计数据。击球率较高的球队最有可能赢得比赛吗?领先 4 局后获胜的球队比例是多少?所有有趣的话题都可以在以后的文章中探讨。

打破一些得分记录被证明是一项有趣且相当有趣的任务。这部 28 局的惊悚片证明了 1920 年知更鸟队和勇士队之间的比赛可能至少会多进行几局。B 队遭受的 24 分差距无法与游骑兵队在 2007 年对金莺队的 27 分差距相提并论。如果有什么不同的话,这个项目显示了这种类型的游戏是多么的罕见,他们应该为这种罕见而受到赞赏。

我是作为一名 Python 程序员开始学习 Scala 的。原因如下。

原文:https://towardsdatascience.com/i-started-learning-scala-as-a-python-programmer-heres-why-e309ded982?source=collection_archive---------22-----------------------

Python 非常适合数据科学。对于数据工程,这就是为什么你应该考虑学习 Scala 作为你的编程工具包的一部分。

迭戈博士Unsplash 上拍摄的照片

学习 Scala 的动机

我 2021 年的科技目标之一就是学习 Scala。我学习 Scala 的关键原因是为了学习数据工程的函数式编程。

问题是:如果 Python 中支持函数式编程,为什么还要不厌其烦地学习 Scala 呢?

我如何学习不同的编程范例

作为一个相信使用工具达到预期目的的语言纯粹主义者,我相信深入学习一种新的编程范式(无论是面向对象编程还是函数式编程)的最佳方式是学习一种合适的编程语言,它是:

  1. 主要是为目标编程范例设计的(不是事后的想法)
  2. 在语法和代码模式上与您已经熟悉的编程语言相似

第二点之所以重要,是因为这样可以将重点更多地放在学习编程范式上,而不必过多地关注语法和代码模式。

例如,我通过学习面向对象的概念,如类、继承和多态,重新熟悉 C 并逐渐过渡到 C++来学习面向对象编程。这种语言转变有助于加速学习 Python 的过程,虽然 Python 支持多种编程范式,但它主要是一种面向对象的编程语言。

为什么 Python 不适合学习函数式数据工程

在探索 Python 中用于数据科学的并行编程时(我强烈推荐您观看我的 PyData Global 2020 演讲以获得对并行的生动解释),我通过mapitertools了解了 Python 中的函数式编程。令我惊讶的是,我可以如此直观地将函数式编程与有意义的数学函数联系起来,并且我已经下意识地使用一些函数式编程概念来可视化我的数据流。

从那以后,我开始深入研究不同的编程范式,但觉得自己对 Python 函数式编程范式的研究还不够深入。

Python 主要是一种面向对象的编程语言。

虽然函数是 Python 中的一级对象,但内置的代码模式和 Python 标准库是围绕类和对象构建的。这使得 Python 主要被设计为鼓励面向对象和命令式设计模式,而不是函数式模式,尽管它是一种多范式编程语言,为开发人员提供了使用他们首选的编码模式的一定程度的灵活性。

由于 Python 内部设计的原因,并行编程在 Python 中并不是真正的并发

Python 及其内置的面向对象设计也导致了 Python 中并行编程的复杂性,将顺序程序分解成并行程序块的问题意味着需要管理并发性以防止对共享变量的并发访问(因此在 CPython 中需要全局解释器锁)。

作为一名处理至少需要某种程度的并行性的数据量的数据专业人员,不得不花费宝贵的开发时间来确定顺序程序的哪些部分可以针对并行性和一致性进行重构,这是沮丧和焦虑的主要来源。直觉地将程序分解成更小的独立功能(I/O 和非 I/O)并不会使重构过程变得更容易。

我仍然热爱 Python 全面的数据生态系统和我从社区中结交的朋友,我仍然在个人和工作项目中积极使用 Python。

然而,对更大规模的数据处理流水线的可伸缩性和可再现性的需求需要通过并行或甚至分布式处理来提升,以及支持这种提升的编程范例,同时允许数据专业人员在设计数据解决方案时更有效率,他们有信心对相同的数据输入产生相同的结果。

为什么要学习数据工程的 Scala

开发人员选择学习 Scala 可能有多种原因。对一些人来说,这可能是由于网络编程。近年来,学习 Scala 的一个流行原因是为了大数据。

以下是我学习 Scala 进行数据工程的原因:

Scala 主要是为函数式编程和面向对象编程而设计的

Scala 旨在无缝集成 Java 的面向对象编程范式和函数式编程范式,旨在解决对 Java 的批评。

【Scala 的语法与 C/C++和 Python 有相似之处

Scala 使用类似于 C/C++的花括号语法,也鼓励嵌套逻辑块的缩进(例如类中的函数)。略有不同的是,Scala 使用 2 个空格,而不是 4 个空格或制表符(Python 就是这种情况)。

Scala 是一种具有类型推断的强静态类型语言,它节省了琐碎的击键,同时保持了函数定义的强类型

静态类型允许在开发过程中更容易地捕捉错误,从而避免复杂应用程序中的错误。作为一种强静态类型语言,用 Scala 编写的代码在编译时而不是运行时被检查类型安全。与 Python 类似,Scala 也支持类型推断——这意味着 Scala 编译器通常可以根据源代码的不同元素来推断类型。

Scala 在类型推断方面与 Python 的不同之处在于,函数定义的参数中需要类型注释(在 Python 中它们是可选的),以防止对函数内部的破坏性更改,并优化编译时间。虽然我试图在 Python 中尽可能多地使用类型注释,但它们不会影响 Python 解释器的执行。将类型批注显式设置为默认值有可能节省开发人员调试依赖于多个函数的应用程序的宝贵时间,同时确保从函数返回所需的数据类型。

接下来是什么:我作为 Python 程序员学习 Scala 的进展

从我开始学习 Scala 到现在已经将近 3 个月了,这是一个非常陡峭的学习曲线。虽然我很高兴可以依靠我以前学习编程语言的经验开始提高 Scala 的工作效率,但我也明白,对于初学者来说,学习曲线可能会更陡。

我不得不承认,函数式编程确实需要适应很多东西,尤其是当一个人已经习惯了用过程式和面向对象的编程范式编写代码的时候。我愿意把函数式编程看作是定义了输入和输出的数学,而过程式编程是一步一步的方法,面向对象编程是具有属性的对象。它们是编写有效代码的不同方式,但是编写代码过程背后的思想是不同的。

当学习变得困难时,回到舒适的代码模式确实很诱人,尤其是在像 Python 这样的多范例编程语言中。因此,当我习惯于(并被“引导着”)用函数式范式编写代码时,我确实发现自己有时会感到非常低效。不过,我确实喜欢在 Scala 中使用类型注释——它们确实让开发过程中的调试变得更加容易!

在我即将发表的文章中,我将介绍函数式编程的基本原则,并将这些原则与可再现的数据管道设计联系起来。

想要更多关于我作为数据专业人员的学习历程的幕后文章吗?查看我的网站 https://ongchinhwee.me

原载于 2021 年 4 月 18 日https://ongchinhwee . me

📊我在 2020 年研究了 365 个数据可视化

原文:https://towardsdatascience.com/i-studied-365-data-visualizations-in-2020-ac1e0fc9799c?source=collection_archive---------11-----------------------

📅一年的数据分析

疯狂的 Instagram 数据验证实验📸

图片来源:由作者创作

2020 年 1 月 1 日,我创建了 Instagram 账户@ VeryData_365 (最近把账户名改成了@SnowDataScience_)。“非常”是因为我的名字叫艾弗里(我喜欢摆弄“非常”是我名字的事实),而“数据”是因为我喜欢数据;我得说我被迷住了。“365”试图捕捉我将在 2020 年每天研究/发布一个数据可视化的想法。

我创建这个账户的目的是学习更多关于数据可视化的知识。我希望我能从其他人的工作中得到启发,并理解什么时候使用特定的技术,以及什么类型的图表强调了某些要点。从很多方面来说,这次经历对我来说都是一次变革。不仅我对数据可视化艺术的理解和知识增长了,我的网络和社交媒体营销技能也增长了。

我学到了什么?你可以查看我的年中文章,在那里我讨论了前 6 个月。这篇文章解释了我从这个长达一年的数据实验中学到的其他东西。

2020 年,我:

学习新的技术和图表

当然还有折线图,条形图,还有大家最喜欢的,饼状图。但是有哪些不太典型的数据显示方式呢?

文字:
我了解到当描绘成数据可视化时,文字是多么强大。通常,我们作为人类 阅读 词语,但如果使用正确,有时我们可以 看到 词语并理解它们的影响。

《纽约时报》是这方面的奇才。他们的两篇文章让我大吃一惊: 集会是川普竞选的核心,一大堆谎言和错误信息 以及他们的头版标题 美国死亡人数近 10 万,无法估量的损失

图片来源:纽约时报

图片来源:纽约时报

可滚动的数据故事:

最近,纽约时报和其他创作者发布了通过滚动制作动画的数据故事。这是一个令人难以置信的用户界面,将故事带入生活。这些是数据的未来,即。下面是《泰晤士报》做的一个名为 的病毒是如何赢得 :

图片来源:纽约时报

Flow Immersive 的业务负责人 Michael DiBenigno 在抖音走红,向世界展示了一种可视化数据的新方法,给了 3d 一个全新的定义

开发了一种独创的数据可视化技术

推特+人像。推特头像!他们说一张图片抵得上一千个字。嗯,如果图片是 1000 字呢?我想出了这个问题,“某人的社交媒体是如何评价他们的?”我想,“哇!Twitter 实际上只是人们在说话。如果我们用他们的话画一幅肖像会怎么样。”砰。推特肖像诞生了。

Twitter Portraits 只是简单地提取某人在 Twitter 上发布的每个单词,进行一些分析以找到他们使用最多的单词,并将这些单词作为颜色遮罩应用到图片上,单词的大小与该单词的使用次数相关联。

我喜欢分析我的朋友或最喜欢的名人,看看他们的肖像是什么样子。

这是我高中时的推特。我看到了“女孩”、“足球”和“爱情”。啊,又年轻了!我现在有了一个新的 Twitter,在那里我可以更多地谈论数据。

图片来源:由作者创作

这是最近被禁的推特,即将成为美国前总统的唐纳德·特朗普。“很好”、“现在”和“工作”对我来说很突出。我也想过为他的演讲做这个。

图片来源:由作者创作

还有一些我最喜欢的 NBA 篮球运动员:

图片来源:由作者创作

找到了大量研究数据的资源,即

集合:
以下是在任何给定主题下,从世界各地寻找集合并发现数据可视化的惊人之举。

Creators:
以下是观看数据可视化的好去处。

发现数据艺术

数据是一门技术性很强的学科,但也不尽然。我找到了几十个人们把数据变成艺术的例子;让它变得美丽。

一年中,有好几次我都注意到了 StoxArt。把枯燥的财务数据和生命注入其中,创造出美丽的风景。参差不齐的特斯拉山是什么样子的?比特币的波峰波谷怎么样?

图片来源:StoxArt

Nick Rougeaux 用一种全新的方式将巴赫的杰作融入到这种“抽象”艺术中,实际上描绘了你可能知道的东西。

图片来源:Nick Rougeaux

当我象征性地将 NBA 球员的脚浸在墨水中,并绘制他们在球场上创造的独特形状时,我创造了自己的篮球主题抽象艺术作品。

图片来源:由作者创作

爱上了塔夫特

我很幸运地在二月份参加了一个凝灰岩可视化课程。我现在有他所有的四本书,并在推特上关注他。我完全相信他说的话。在我的书房里,我看到他的技术被反复谈论。以下是我最喜欢的一些。

如果你没有读过任何 Tufte,并且你正在做数据,请停下你正在做的事情,读一些 Tufte

迷你图:

Tufte 的数据-油墨比:

“最重要的是展示数据”

图片来源:爱德华·塔夫特

罗沙汗搜索 2020 年: 这些从技术上来说是山脊图,但足够接近迷你图。罗尚恩优雅地强调了世界在一年中不同地方搜索的词汇,这样我们就可以进行关联和比较。

图片来源:罗沙汗

小倍数:

NBA 球队最常见的拍摄地点作者欧文·菲利普斯展示了一次比较许多图表并理解更大的画面是多么有趣。

图片来源:欧文·菲利普斯

Klara prps TL用抽象的方式,创造性地向我们展示了地铁上几个人的样子。

图片来源:Klara Prö pstl

凯特·格林布鲁克通过小塑料回收龟展示了我们对地球的影响。

图片来源:Kat Greenbook

遇到了很多很酷的志同道合的人

这一年来,我发现了一些很棒的数据人员。

  • 凯尔·帕斯托尔经营着@ datastufplus,他帮助其他人的 viz 迅速传播,并分享他对数据可视化的热情。
  • Aaron Penne 是一位不可思议的艺术创作力艺术家,他的杰出作品可供购买,所有收入将捐给慈善机构。
  • 我遇到了 Kate Strachnyi,她是 LinkedIn 上一位善良的数据女王,也是许多数据原则的指导者。

读一些很棒的书

我喜欢数据可视化书籍。以下是我今年最喜欢的:

  • 史蒂夫·韦克斯勒、安迪·科特格里夫和杰夫·谢弗的《仪表板大全》;在任何情况下突出显示您想要的仪表板。
  • 用数据讲故事科尔·克纳弗利奇;dummie 的数据入门指南。
  • 设想信息由爱德华·塔夫特提供;涉猎使数据变得简单的复杂性。
  • 观察,收集,绘制!Giorgia Lupi 和 Stefani Psavec 的视觉杂志;引领您体验基于数据的日志记录。
  • 柯克·戈德贝里的《蔓生球》;描述了 NBA 的历史和数据在发展中的作用。
  • 图表如何说谎阿尔贝托·开罗;说明了图表是如何被用来传播错误信息的。
  • 彼得·戈尔曼著勉强地图;讲述了一个简单的故事,关于一个人,他的自行车,以及他在越野自行车骑行中看到的模式。这本书确实鼓舞人心,是一个有趣的故事。

快速消防知识

  • 人们喜欢地图。地图是人们能够立即理解和联想到的东西。这是美国许多城市的字体地图。这是另一张显示美国街道上不同自然名称的照片。
  • 热门话题:有史以来最好的数据可视化是神奇宝贝卡片?不要@我。
  • 数据视频更有诱惑力和教育意义。看看这张显示两年各州谷歌搜索排行榜的。下面是另一部关于大片兴衰的动画。
  • Data viz 在 2020 年占据了前座席位。我们经常检查这个来自约翰·霍普斯金的仪表板。
  • 并非所有的数据可视化结果都是
  • 种族条形图很好玩;人们喜欢它们。中国会赶上美国吗?观看以找出答案。

图片来源:作者创作

很棒的一年?

这是充满压力的一年。这是悲惨的一年。但这并不意味着今年不会很棒。2020 年对我来说是伟大的一年。通过这次实验,我学到了很多东西。我迫不及待地想看看数据可视化的 2021 年会带来什么!

欢迎继续在 Instagram 上关注我的旅程!

附言:这些书的一些链接是亚马逊的附属链接,如果你最终从链接上买了这本书,我会收到一分钱:】

我偶然发现了数据科学

原文:https://towardsdatascience.com/i-stumbled-into-data-science-by-accident-part-1-52498c44206e?source=collection_archive---------28-----------------------

办公时间,引导数据进行改进

如果像我这样的假人能学会编码和分析数据,任何人都可以!

我自己的照片:)

似乎人们从各种不同的背景进入数据科学。很明显,进入这个领域没有“最佳”方法。我觉得分享我自己的故事可能会很有趣。

我在 LDC(最不发达国家)的一家制造公司做了 15 年的 CEO。一些人口统计数据(来源:【http://hdr.undp.org/en/countries/profiles/PNG】T2

  • 80%的人口过着自给自足的农村生活。
  • 平均年龄= 22 岁。
  • 教育指数= 0.439(定义:教育指数是平均受教育年限(成人)和预期受教育年限(儿童)的平均值。
  • 城市人口:13.2%。自给自足的农村人口 82.7%。

我们一直在努力使我们的流程现代化,有过一些成功,也有过一些失败,但我们总能从经验中学到一些东西。十多年来,我的职业生涯一直是一个接一个的改进项目,说实话,我喜欢这样。也许是未来文章的主题。

最新的是一个改变我们计划和报告生产方式的雄心勃勃的项目。

许多年来,我们的生产计划过程是非正统的。没有与其他利益相关者协商或沟通,生产经理就会武断地决定他们的生产计划。该计划基于 excel 电子表格,只有生产经理可以访问。任何类型的生产数据第一次进入该公司的企业资源规划系统(ERP)是在一天的生产完成后 24 小时。将手写的纸质生产记录表交给两名生产文员,他们的唯一任务是在 ERP 中创建新的工作订单,以匹配生产记录表,并立即关闭工作订单。成品的数量会增加,而原材料会减少。我们称之为“反冲”。每个人都知道事情不应该是这样的,但是像许多公司一样,我们反对改变。

冒着显而易见的风险,这似乎是一种糟糕的生产计划和报告方式。这种方法产生的问题很多,但这里有一些:

  • 没有与销售部门协商这是否是满足客户需求的合适产品,也没有与供应链部门协商以确保我们有足够的原材料。
  • 信息总是晚 24 小时,所以股票在卖出前会在地板上停留 24 小时。
  • 缺乏可见性和可疑的生产交易记录意味着我们的库存水平的有效性总是有一个问号,这经常反映在盘点中。生产经理通过在他的物料清单(BoMs)中添加“脂肪”来处理这个问题,以确保在盘点时总是有原材料的收益来抵消成品的损失。
  • 缺乏质量信息意味着无法对生产绩效进行有意义的分析

我可以继续说下去,但你会明白的。

在我们赢得了一些唾手可得的果实后,我们最终决定解决这个问题。我们知道这将是一场艰难的比赛,团队需要几场胜利来给他们信心,以承诺如此重大的变革,这将涉及并影响如此多的利益相关者。

  • 我们需要销售人员生成一个滚动的 3 个月预测,该预测将作为 ERP 生成建议生产计划的基础。该生产计划将分发给所有利益相关方,他们将有 48 小时的时间做出反馈。一旦计划最终确定,生产计划将被“锁定”到 ERP 中,并根据该计划生成工作订单。
  • 工厂将按照该计划工作,当每个完成的产品托盘下线时,只需贴上 ERP 生成的唯一条形码并扫描它,就可以完成更新。所有的脂肪都从 BoMs 中去除了,所以原材料消耗尽可能的接近准确。
  • 采购和供应链也将受益,因为他们的采购计划将由相同的销售预测和生产计划提供信息。ERP 将每周生成一个建议订单列表,该列表将被审查然后执行。

对于读者来说,这听起来非常明显,因为这是非常标准的,并且应该一直这样做。我可能永远也不会知道为什么这家公司一开始就开始“反冲洗”。

重要的是要理解为什么改变如此困难:人和组织天生厌恶改变。无论从金融还是非金融的角度来看,变革都是艰难的、高风险的、昂贵的。技术从来都不是有效进行可持续变革的限制因素。赢得人心是关键因素。

它花费了大量的时间和工作来达到上线的程度,但我们做到了,团队感到非常自豪和成就感。上线后的头几个月,事情似乎进展顺利,但后来我们注意到总分类账中出现了奇怪的、有时是无意义的数字。

例如,有时从库存中扣除的原材料的价值大于生产的成品的价值。想一想:这显然是荒谬的,但没有人能解释为什么会发生这种情况。

问题在于,所有制造会计交易都是通过自动流程从企业资源规划系统的制造模块转移到总分类账的。这个过程的记录被捕获并记录在 txt 文件中,我们称之为“日志”。每个日记账可能包含 15,000 个或更多不同的交易。

都说一张图胜过千言万语,下面就来几张截图说明一下。这是一个很小的文件,因为它发生在 1 月 2 日,这通常是一个非常安静的时间:

一天的日志文件的顶部。

日记本的中间部分

日记的摘要部分

很明显,这个文件有很多问题:

  • 缺少一致的分隔符(逗号、空格、制表符等)。它是分隔符的混合。这使得导出。txt 文件转换成 excel 电子表格。
  • 交易日期仅在每隔一行出现,因为第二笔交易是对销交易。我假设读者有基本的会计知识。为了分析,我们需要每笔交易的日期。
  • 数据在文本文件中一式三份,该文件已被配置为以 3 种不同的格式显示相同的数字。中段和总结是多余的。这使文件变得臃肿不堪。从现在开始,我们将参考顶部,因为清理数据的关键部分是剥离中间部分和摘要。
  • 负值在数字的末尾有负号,而不是在数字的前面。这给任何识别负数的软件带来了问题。
  • 为了执行任何有意义的分析,我们不仅需要转换一个文件,还需要转换 28–31 个文件。每天一个。这些需要合并成一个文件。
  • 尝试将如此大量的数据导入到 excel 中是一项挑战。我发现 excel 大约有 200,000 行。这个问题要求我们在一个月内处理超过 140 万行。

没有人知道如何在每月超过 100 兆的数据中找到“大海捞针”的方法,以找到错误交易的模式。我们都有自己的理论,我们试图在小样本数据上进行测试,但每次都失败了。

这种情况持续了几个月,在此期间,我们被迫对总账进行越来越大的“总”调整,以使数字看起来像我们认为应该的那样。这对任何经理来说都是一种可怕的感觉,因为你根本不知道自己是在报道事实,还是在歪曲公司的表现。

更糟糕的是,这个问题是实质性的,而且越来越严重。

压力和挫折感累积到团队变得如此沮丧和失望的程度,以至于他们达成了一个普遍的一致意见,即最好的解决方案是退回到旧的做事方式。投入了如此多的时间和精力来实现这一点,这对团队来说是一个毁灭性的打击。我天生固执。这充其量是一件喜忧参半的事情。因此,我是一个反对的声音。

我向团队承诺:“给我 30 天。如果在那段时间内我不能解决,我会同意恢复原状。在那 30 天里,我将只关注这个问题。我需要你们都站出来,做好我的本职工作,这样我才能集中精力”。我是首席执行官,所以他们别无选择,只能同意。自然有很多怀疑:当会计师、IT 专业人士和顾问都失败了,我怎么可能成功?非常合理的怀疑,因为我不是那些东西。我是个多面手:什么都懂,什么都不懂。

不过,交易就是交易。

我遵循的过程描述如下。事后看来,我现在知道这不是一个伟大的过程,但当时我是随着我的进步才明白的。我会继续提高。

  • 第一步:手动导入数据。使用定点分隔符将。第一次尝试花了 9 个小时处理一个文件。我无意中选择了一个较大的文件。这显然不是一个实用的方法。不仅耗时,而且容易出错。不过有一个好处:我学到了很多关于数据的东西。我将这个手动过程重复了两次,将每个文件的处理时间减少到了 3 小时。
  • 第二步:录制一个宏。我以前从来没有这样做过,但这似乎是一个明显的下一步。鉴于我已经有了一个缓慢但有效的手动处理文件的过程,使用宏可以使它更快更一致。每个文件的时间减少到 15 分钟。将每天的文件组合成一个合并的月文件仍然是手工的。

此时,也就是第 5 天,我已经有了足够的清晰信息来诊断这个问题,但是我将稍后再回到这个问题。在清理这些数据的过程中,我意识到这些文件中有很多我们没有使用的有价值的信息。

这些信息可用于持续的绩效管理,因此将目标从仅仅解决眼前的问题转变为建立一个可重复的过程,使生产经理能够轻松地分析这些文件中包含的事务性数据是有意义的。

  • 第三步:写一个 VBA 的剧本。我一生中从未写过代码。VBA 是我的“入门毒品”。通过一些搜索和对我愚蠢问题的一些非常有用的回答,我编写了一个 VBA 脚本,它可以在 60 秒内处理每个文件。这是一个很大的改进,但是为了进行有意义的分析,我仍然需要手动将每个日志文件组合成一个合并的月文件。
'Macro to format and align text data from Iscala WIP JNL MPC report - Michael Kingston 03/05/2020
'Main Routine
Sub WIPJNLMPC()
Sheets("WIPJNL").Select ' Make WIPSUMMARY the active worksheet
Range("A1").Select
LoadDataWIP
LoadDataSUM
LoadDataTOT
Sheets("WIPJNL").Select ' Make WIPSUMMARY the active worksheet
Range("A1").Select
Exit Sub
End Sub
'================ Sub routines to on WIPJNL Worksheet======================================
Sub LoadDataWIP()
    Sheets("WIPJNL").Select ' Make WIPSUMMARY the active worksheet
    Range("A1").Select

    With ActiveSheet.QueryTables.Add(Connection:= _
        "TEXT;C:\MacroTemplates\WIPJNLData.txt", Destination:=Range("$A$1"))
        .Name = "data1"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 437
        .TextFileStartRow = 1
        .TextFileParseType = xlFixedWidth
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = True
        .TextFileSemicolonDelimiter = False
        .TextFileCommaDelimiter = False
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = Array(2, 4, 2, 1, 1, 1, 1, 2, 1, 2)
        .TextFileFixedColumnWidths = Array(10, 9, 7, 7, 7, 7, 21, 26, 7)
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With
    Cells.Select
    Columns("A:A").Select
    Selection.Find(What:="- - - -", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
        :=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
        False, SearchFormat:=False).Activate

这是一个相当长的脚本,所以这只是头部。

  • 第四步:发现 Python 和熊猫,感谢 Medium 和数据科学(当然还有 Google)。令人惊叹的 python 开发人员社区和在线资源帮助我编写了一个非常简单的 Python 脚本来遍历目录中的所有 txt 文件夹,清理它们并输出一个完整的月文件。

一个简单的 python 脚本。每个人都有起点。

调查结果:

根据这些数据,许多问题变得很明显。

  • 我们曾错误地认为 ERP 被配置为全面使用加权平均成本。实际情况是,生产使用标准成本,而业务的其他部分使用加权平均。
  • 因为我们没有意识到这一点,所以我们没有意识到这两名生产文员在旧流程中关闭每个工作订单后正在进行标准成本累计。任何预部署研讨会都没有记录或提及这一步骤。一旦我们对新流程进行了更改,标准成本累计就停止了,随着时间的推移,标准成本和实际成本越来越远。这导致了生产差异。

表格将有助于理解接下来的几点

原始制造账户

  • 制造帐户结构没有适当的差异帐户。只有一个差额账户。好的做法是将差异类别分开,以便进行差异分析,从而达到减少差异的目的。下表显示了我们认为在我们的环境中应该如何做:

新制造账户

这是一个简单的方法。人们可以把这个提升到 n 次。有更多的差异帐户允许更大的粒度,但太大的粒度可能会有问题。对于我们这种规模的行动,我们认为这已经足够了。接吻(保持简单)是一个很好的经验法则。

  • 在旧制度下,差异账户既不需要也没有被正确使用。通过在一个步骤中创建工作订单、关闭工作订单和累计标准成本,意味着无需报告任何差异。然而,在新系统下,需要适当的差异账户。
  • 自动记帐计划(AAS)配置不正确。当差异发生时,它们不是被过账到差异账户,而是被过账回原材料账户。这就是为什么我们在月度损益中看到原材料成本>成品成本。“tell”是每个工作订单的结束交易:它将是针对 001021 的(有时很大的)借记交易。这不应该发生。这不合逻辑。但它确实发生了,而且只发生在工作指令的关闭交易上。这是关键的洞察力。在我们的 ERP 中,差异交易仅在工作订单的结算交易时创建(根据文档)。确定有问题的交易后,我可以查看该交易的详细数据,这些数据清楚地显示,在工作订单结束时,差异被过帐到帐户 001021,在某些情况下,被过帐到帐户 100112。这是不正确的。

这是我们在总账层面看到大量错误数字的根本原因。

  • 一些工作订单结转到上月底(EOM),导致 001049 在 EOM 不平衡。一个相对较小的问题,但有改进的机会。
  • 一些工作订单没有正确关闭。在我们的 ERP 中,当工单被正确关闭时,它会变为状态 8。但是,如果出现问题,工作单将变为状态 7。调查显示,原因是物理原材料从仓库转移到工厂,没有匹配的 ERP 交易。实际上,原材料在工厂里并被使用,但是从 ERP 的角度来看,原材料并不在那里。当生产部门关闭工作单并贷记原材料时,系统发现没有足够的原材料来关闭工作单。这导致受影响的工作单被归类为类型 7。显著的改进机会。

解决方案:

  • 第 1 步:根据上表重新组织制造账户
  • 步骤 2 :更新 AAS 以确保所有交易都被过账到正确的账户,并且不需要人工干预来“纠正”由不正确的 AAS 配置引起的错误。
  • 步骤 3 :常规标准成本累计,以及将整个组织转移到标准成本的计划,以便能够监控采购价格差异(PPV)。
  • 步骤 4 :修改流程,增加一个预检步骤,以确保在工作指令开始之前,工作指令所需的所有原材料都在工厂中,无论是实物还是系统。
  • 步骤 5 :确保所有工作指令在 EOM 翻转时关闭。
  • 步骤 6 :计划将整个组织转移到标准成本。

给我的教训:

  • 有疑问的时候,去看看数据。不要一味的相信数据,而是要以数据为指导。
  • 有很多很棒的工具可以帮助你处理具有挑战性的数据,如果你提出要求,有一个很棒的社区愿意提供帮助。
  • 我真的很喜欢挖掘数据和写代码。新的爱好/激情。
  • 知道什么时候面对困难要坚持,什么时候要退缩,并不总是容易的。相信你的直觉,给自己一个时间限制。如果你不能在限定范围内解决,撤退并重组。
  • 技术是一个伟大的工具,但人而不是技术是任何持久变革的核心。仅有技术是不够的。

感谢阅读。

我在 15 分钟内为数据科学家总结了 100 多个命令行工具

原文:https://towardsdatascience.com/i-summarized-100-command-line-tools-for-data-scientists-in-15-minutes-976def544ffe?source=collection_archive---------17-----------------------

数据科学家

所有命令行工具的概述

那是一个旧的命令行工具

命令行界面是以文本行的形式处理计算机程序命令的程序。在这篇精彩的文章中,我将介绍 100 多种在数据科学中广泛使用的命令行工具。

别名和 unalias

别名工具是内置的 Z shell。

$ type alias
alias is a shell builtin

对于命令行,语法是:

$ alias name=’string’

我们可以用它创建自己的命令。下面是将 Python 3 设置为默认的正确方法。

$ type python
python is /usr/bin/python$ python --version
Python 2.7.16$python3 --version
Python 3.9.4$ alias python=python3
$ python --version
Python 3.9.4$ type python
python is an alias for python3

要删除别名,可以使用 unalias 命令,如下所示。

$ unalias python
$ type python
python is /usr/bin/python

Awk、sed 和 grep

为了便于讨论,让我们定义一个文本文件 list.txt:

$ cat list.txt
John Daggett, 341 King Road, Plymouth MA 
Alice Ford, 22 East Broadway, Richmond VA 
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK 
Terry Kalkas, 402 Lans Road, Beaver Falls PA 
Eric Adams, 20 Post Road, Sudbury MA 

awk

awk 工具是一种模式扫描和文本处理语言,由 Mike D. Brennan 和 Thomas E. Dickey 开发。

$ type awk 
awk is /usr/bin/awk

awk 工具为每行输入执行一组指令。对于命令行,语法是:

awk 'instructions' files

例如,我们有一个包含姓名和地址列表的list.txt文件。我们编写一条指令,打印输入文件中每行的第一个字段。

$ awk ‘{ print $1 }’ list.txt
John
Alice
Orville
Terry
Eric

阅读更多:【https://invisible-island.net/mawk】

一项 Linux 指令

sed 工具是一个流编辑器,用于过滤和转换文本,作者是杰伊·芬拉森、汤姆·洛德、肯·皮齐尼和保罗·邦兹尼。

$ type sed
sed is /usr/bin/sed

对于命令行,语法是:

$ sed [-e] ‘instruction' file

只有在命令行上提供多条指令时,才需要-e选项。它告诉 sed 将下一个参数解释为指令。

以下示例使用s命令进行替换,将“MA”替换为“Massachusetts”

$ sed 's/MA/Massachusetts/' list.txt
John Daggett, 341 King Road, Plymouth Massachusetts 
Alice Ford, 22 East Broadway, Richmond VA 
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK 
Terry Kalkas, 402 Lans Road, Beaver Falls PA 
Eric Adams, 20 Post Road, Sudbury Massachusetts 

阅读更多:https://www.gnu.org/software/sed

可做文件内的字符串查找

grep 命令搜索与正则表达式模式匹配的行,并将这些匹配的行打印到标准输出。目前由吉姆·梅耶林维护。

$ type grep
grep is /usr/bin/grep

对于命令行,语法是:

$ grep [options] pattern [file...]
  • 模式是一个正则表达式模式,它定义了我们想要在由 FILE 参数指定的文件内容中找到什么。
  • 选项可选参数是修改 grep 行为的标志。

假设我们想从 list.txt 中提取包含“John”文本的行。

$ grep “John” list.txt
John Daggett, 341 King Road, Plymouth Massachusetts

阅读更多:https://www.gnu.org/software/grep/

尝试

bash shell 是由 Brian Fox 和 Chet Ramey⁴.开发的 GNU Bourne-Again shell

$ type bash
bash is /bin/bash

它包含了 C shell 的大部分主要优点以及 Korn shell 的特性和一些自己的新特性。

阅读更多:【https://www.gnu.org/software/bash】

历史

历史 命令显示自会话开始以来输入的命令列表。目前由布莱恩·福克斯和切特·雷米维护。

$ type historyhistory is a shell builtin

例如,您现在应该会看到一个列表,其中快速显示了最近使用的 500 条命令。

$ history
496  ls -la
497  ls
498  history
499  ls
500  cd domains
501  cd ..
502  ls
503  history
504  cd ls
505  ls
506  cd data
507  ls
508  cd ..
509  cd domains
510  ls
511  cd ..
512  history

使用该命令还有更多方法。

公元前

bc 工具是一种支持任意精度数字和交互式执行语句的语言,作者是菲利普·a·nelson⁵.

**$** type bc 
bc is /usr/bin/bc

对于命令行,语法是:

$ bc [ -hlwsqv ] [long-options] [ file ... ]

下面将把“pi”的值赋给变量 pi。

$ pi=$(echo "scale=10; 4*a(1)" | bc -l)
$ echo $pi
3.1415926532

阅读更多:https://www.gnu.org/software/bc

cd 命令是 Z shell 内置的。它用来改变你正在工作的当前目录。

$ type cd 
cd is a shell builtin

对于命令行,语法是:

cd [option(s)] directory

若要导航到您的个人目录,请使用“cd ~”:

$ cd ~ 
$ pwd
/Users/dangtrunganh

要导航到根目录,请使用“cd /”:

$ cd /
$ pwd
/

若要向上导航一级目录,请使用“cd ..”:

$ pwd
/Users/junryo$ cd ..
$ pwd 
/Users

Util Linux

util-linux 库是由 linux 内核组织发布的标准包,用作 Linux 操作系统的一部分。

阅读更多:【https://www.kernel.org/pub/linux/utils/util-linux】https://www.kernel.org/pub/linux/utils/util-linux

圆柱

Linux 中的 column 命令用于以列的形式显示文件的内容。它由卡雷尔·扎克维护。

*$ type column
column is /usr/bin/column*

对于命令行,语法是:

*column [-entx] [-c columns] [-s sep] [file ...]*

例如,您希望将由特定分隔符分隔的条目排序到不同的列中。

*$ column -t -s “|” list.txt
1 Anh Dang
2 Linh Hong*

发动机的旋转

逐字符反转线条。

例如:

*$ echo ‘name: Anh Dang’ | rev 
gnaD hnA :eman*

考赛

这个工具是托尼·门罗开发的一个程序,可以生成带有信息的奶牛的 ASCII 艺术图片。

*$ type cowsay 
cowsay is /usr/bin/cowsay*

Unix 命令 fortune 也可以通过管道传输到 cowsay 命令中:

*$ fortune | cowsay
 ________________________________________
/ You have Egyptian flu: you're going to \
\ be a mummy.                            /
 ----------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||*

在 GPLv3 许可证下可以获得 cowsay 工具,您可以在 GitHub 上找到 Perl 源代码。

**阅读更多:https://github.com/tnalpgge/rank-amateur-cowsay

科里蒂尔斯

GNU 核心工具是 GNU 操作系统的基本文件、外壳和文本操作工具。这些是每个操作系统中都应该存在的核心实用程序。

阅读更多:*https://www.gnu.org/software/coreutils。***

chmod

chmod 命令用于更改权限,由大卫·麦肯齐和吉姆·meyerin⁶.维护

**$ type chmod 
chmod is /usr/bin/chmod**

只有文件或文件夹的所有者才能更改其模式。

丙酸纤维素

cp 命令用于复制文件或文件组或目录。它由托尔比约恩·格兰伦德、大卫·麦肯齐和吉姆·迈耶林维护。

**$ type cp 
cp is /usr/bin/cp**

这里有五个命令可以让您在 Linux 终端中查看文件的内容,如下所示:cat、nl、less、head 和 tail。

这是 Torbjorn Granlund 和 Richard M. Stallman⁶.编写的在 Linux 中查看文件的最简单也可能是最流行的命令

**$ type cat 
cat is /usr/bin/cat**

下面是如何保存一个日期范围内的所有日志文件,如下所示。

**$ cat localhost_log_file.2017-{09-{03..30},10-{01..08}}.txt > totallog.csv**

cat 命令的大问题是它在屏幕上显示文本。

北纬

nl 命令几乎和 cat 命令一样,由斯科特·bartram⁷.维护

**$ type nl 
nl is /usr/bin/nl**

唯一的区别是,在终端中显示文本时,它会预先考虑行号。

**$ nl main.js 
1 console.log([…[1, 2, 3], …[4, 5, 6]])%**

有时,您并不需要某个命令的所有输出。您可能只需要前几行或后几行。

head 命令打印文件的前 10 行。

**$ ls /usr/bin | head -n 5
2to3-
2to3–2.7
AssetCacheLocatorUtil
AssetCacheManagerUtil
AssetCacheTetheratorUtil**

尾巴

一个 命令打印最后 10 行。

**$ ls /usr/bin | tail -n 5
zipsplit
zless
zmore
znew
zprint**

限位开关(Limit Switch)

ls 命令可能是使用最多的命令。它列出了目录内容。

**$ type ls
ls is /bin/ls**

例如,我们列出了用户的主目录(用~符号表示)和/usr 目录。

**$ ls ~ /usr**

切口

cut 程序用于从一行中提取一段文本,并将提取的部分输出到标准输出。它可以接受多个文件参数或来自标准输入的输入。

**$ type cut
cut is /usr/bin/cut**

回声

echo 命令用于显示作为参数传递的文本/字符串行。

**$ type echo 
echo is a shell builtin**

对于命令行,语法是:

**$ echo [option] [string]**

例如:

**$ echo "TowardsDataScience"**

包封/包围(动词 envelop 的简写)

显示当前环境或设置执行命令的环境。

**$ type env 
env is /usr/bin/env**

对于命令行,语法是:

**$ env [ -i | — ] [*Name*=*Value* ]… [*Command* [ *Argument* … ] ]**

例如,要在运行 date 命令时更改 TZ 环境变量,请键入:

**env TZ=MST7MDT date**

折叠

Linux 中的 fold 命令将输入文件中的每一行换行以适应指定的宽度,并将其打印到标准输出。默认情况下,它以最大 80 列的宽度换行,但这是可以配置的。

**$ type fold 
fold is /usr/bin/fold**

对于命令行,语法是:

**$ fold [  -b ] [  -s ] [  -w Width] [ File... ]**

例如,要将名为 longlines 的文件的行折叠成宽度 72(72),请输入:

**$ fold -w 72 longlines**

mkdir

创建一个或多个新目录。

**$ type mkdir 
mkdir is /usr/bin/mkdir $ man mkdir** 

对于命令行,语法是:

**$ mkdir [-e] [ -m *Mode* ] [ -p ] *Directory …***

例如:

**$ mkdir -p /mybook/chapter{01..10}**

Dsutils

dsutils 是用于数据科学的命令行工具列表。作者是耶鲁安·扬森斯和李维·吉列。

阅读更多:https://github.com/jeroenjanssens/dsutils

身体

body 命令允许您将任何命令行工具应用于 CSV 文件的主体。

**$ type body 
body is /usr/bin/dsutils/body**

例如:

**$ echo -e “value\n8\n2\n6\n3” | body sort -n 
value 
2 
3 
6 
8**

关口

此工具允许您对列的子集应用命令。

**$ type cols
cols is /usr/bin/dsutils/cols**

csv2vw

csv vvw工具将 CSV 转换为 Vowpal Wabbit 格式。

**$ type csv2vw 
csv2vw is /usr/bin/dsutils/csv2vw**

dseq

命令 dseq 生成一个日期序列。

**$ type dseq 
dseq is /usr/bin/dsutils/dseq** 

例如,你使用dseq⁠command 生成一个dates.txt文件。

**$ dseq 5 > dates.txt
2021–08–01 
2021–08–02 
2021–08–03
2021-08-04
2021-08-05**

页眉

标题 命令用于添加、替换和删除 CSV 文件的标题行。

**$ type header 
header is /usr/bin/dsutils/header**

对于命令行,语法是:

**$ header [-adr] text**

下面举个例子,如何统计下面 CSV 的正文的行。

**$ seq 5 | header -a count | body wc -l 
count 
5**

中国人民银行(People's Bank of China)

pbc 命令是并行 bc

**$ type pbc 
pbc is /usr/bin/dsutils/pbc** 

例如:

**$ seq 5 | pbc ‘{1}²’ 
1 
4 
9
16
25**

servewd

该工具使用一个简单的 HTTP 服务器提供当前工作目录。

**$ type servewd 
servewd is /usr/bin/dsutils/servewd** 

例如:

**$ cd /data && servewd 8080**

整齐

修剪 命令用于限制输出到给定的高度和宽度。

**$ type trim 
trim is /usr/bin/dsutils/trim**

例如:

**$ echo {a..z}-{0..9} | fold | trim 5 60 
a-0 a-1 a-2 a-3 a-4 a-5 a-6 a-7 a-8 a-9 b-0 b-1 b-2 b-3 b-4… 
c-0 c-1 c-2 c-3 c-4 c-5 c-6 c-7 c-8 c-9 d-0 d-1 d-2 d-3 d-4… 
e-0 e-1 e-2 e-3 e-4 e-5 e-6 e-7 e-8 e-9 f-0 f-1 f-2 f-3 f-4… 
g-0 g-1 g-2 g-3 g-4 g-5 g-6 g-7 g-8 g-9 h-0 h-1 h-2 h-3 h-4… 
i-0 i-1 i-2 i-3 i-4 i-5 i-6 i-7 i-8 i-9 j-0 j-1 j-2 j-3 j-4… 
… with 8 more lines**

解除…的负担

解包 工具用于提取 tar、rar、zip 等常见文件格式。

**$ type unpack 
unpack is /usr/bin/dsutils/unpack**

例如:

**$ unpack logs.tar.gz**

请记住,它会查看您想要解压缩的文件的扩展名,并调用适当的命令行工具。

Csvkit

csvkit repo 是一套命令行工具,用于转换和处理 CSV,表格文件格式之王。目前由 Christopher Groskopf 维护。

阅读更多:https://csvkit.rtfd.org**

csvkit 工具让你的生活更轻松。

  • 将 Excel 转换为 CSV:
**$ in2csv data.xls > data.csv**
  • 将 JSON 转换为 CSV:
**$ in2csv data.json > data.csv**
  • 打印列名:
**$ csvcut -n data.csv**
  • 选择列的子集:
**$ csvcut -c column_a,column_c data.csv > new.csv**
  • 重新排序列:
**$ csvcut -c column_c,column_a data.csv > new.csv**
  • 查找具有匹配单元格的行:
**$ csvgrep -c phone_number -r "555-555-\d*{4}*" data.csv > new.csv**
  • 转换为 JSON:
**$ csvjson data.csv > data.json**
  • 生成汇总统计数据:
**$ csvstat data.csv**
  • 使用 SQL 查询:
**$ csvsql --query "select name from data where age > 30" data.csv > new.csv**
  • 导入 PostgreSQL:
**$ csvsql --db postgresql:///database --insert data.csv**
  • 从 PostgreSQL 提取数据:
**$ sql2csv --db postgresql:///database --query "select * from data" > new.csv**

卷曲

一个 curl 是一个命令行工具和库,用于通过 url 传输数据。这是一个免费的开源软件,它的存在要感谢成千上万的贡献者

**$ type curl 
curl is /usr/bin/curl**

例如:

**curl https://www.keycdn.com**

阅读更多:https://curl . se

出口

将环境导出到随后执行的程序。它是一个内置的 Z 外壳。

**$ type export 
export is a reserved word**

对于命令行,语法是:

**$ export [-f] [-n] [name[=value] ...]** 

例如:

**$ export $PATH:$HOME/bin**

查看当前 shell 中所有导出的变量。

**$ export -p**

查看所有导出的变量。

**$ export**

足球俱乐部(Football Club)

fc 命令是 Z shell 内置的。这是一个命令行实用程序,用于列出、编辑和重新执行以前输入到交互式 shell 中的命令。

**$ type fc
fc is a shell builtin**

发现

find 命令在目录层次结构中搜索文件。它是由埃里克·b·德克尔、詹姆斯·杨曼和凯文·戴利写的。

**$ type find 
find is /usr/bin/find**

例如:

**find /Volumes/MyData -type f -name ‘*.csv’ -size -3**

阅读更多:https://www.gnu.org/software/findutils

命令的 是 Z shell 内置的。它允许代码重复执行。

**$ type for
for is a reserved word**

例如:

**$ for i in $(seq 1 2 20)
do
   echo “Welcome $i times”
done
Welcome 1 times
Welcome 3 times
Welcome 5 times
Welcome 7 times
Welcome 9 times
Welcome 11 times
Welcome 13 times
Welcome 15 times
Welcome 17 times
Welcome 19 times**

外汇(foreign exchange 的缩写)

fx 库是 Anton Medvedev 开发的命令行工具和终端 JSON 查看器。

**$ type fx 
fx is /usr/local/bin/fx**

下面介绍如何使用 fx 命令。

**$ curl ... | fx**
  • 或者将文件名作为第一个参数传递。
**$ fx data.json**
  • 传递几个 JSON 文件。
**cat foo.json bar.json baz.json | fx .message**
  • 充分利用 JavaScript 的力量。
**$ curl ... | fx '.filter(x => x.startsWith("a"))'**
**$ curl ... | fx '_.groupBy("commit.committer.name")' '_.mapValues(_.size)'**
  • 使用 spread 运算符更新 JSON。
**$ echo '{"count": 0}' | fx '{...this, count: 1}'
{
  "count": 1
}**
  • 从地图中提取值。
**$ fx commits.json | fx .[].author.name**
  • 将格式化的 JSON 打印到 stdout。
**$ curl ... | fx .**
  • 通过管道将 JSON 日志流导入 fx。
**$ kubectl logs ... -f | fx .message**
  • 试试这个:
**$ fx --life**

阅读更多:https://github.com/antonmedv/fx

饭桶

愚蠢的内容跟踪器。

**$ type git 
git is /usr/bin/git**

对于命令行,语法是:

**$ git [--version] [--help] [-C <path>] [-c <name>=<value>]
    [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
    [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
    [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
    [--super-prefix=<path>] [--config-env=<name>=<envvar>]
    <command> [<args>]**

阅读更多:https://git-scm.com

格朗

让 JSON greppable!它是由汤姆·哈德森维护的。

**$ type gron 
gron is /usr/bin/gron**

对于命令行,语法是:

**$ gron [options] [file|URL|-]**

例如:

**$ gron "https://api.github.com/repos/tomnomnom/gron/commits?per_page=1" | fgrep "commit.author"
json[0].commit.author = {};
json[0].commit.author.date = "2016-07-02T10:51:21Z";
json[0].commit.author.email = "mail@tomnomnom.com";
json[0].commit.author.name = "Tom Hudson";**

阅读更多:https://github.com/TomNomNom/gron

主机名

hostname 命令显示或设置系统的主机名。它是由彼得·托拜厄斯,贝恩德·艾肯费尔斯和迈克尔·梅斯克斯写的。

****$** type hostname
hostname is /usr/bin/hostname**

例如:

**$ hostname
Trungs-MacBook-Pro.local**

阅读更多:https://sourceforge.net/projects/net-tools/

JQ

jq 库是一个轻量级且灵活的命令行 JSON 处理器,由 Stephen Dolan 编写。

**$ type jq
jq is /usr/bin/jq**

例如:

**$ curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.[0]'**

阅读更多:https://stedolan.github.io/jq

Json2csv

将换行符分隔的 json 数据流转换为 csv 格式。

**$ type jq 
jq is /usr/bin/jq**

对于命令行,语法是:

**$ json2csv
    -k fields,and,nested.fields,to,output
    -i /path/to/input.json (optional; default is stdin)
    -o /path/to/output.csv (optional; default is stdout)
    --version
    -p print csv header row
    -h This help**

例如

  • 要转换:
**{“user”: {“name”:”jehiah”, “password”: “root”}, “remote_ip”: “127.0.0.1”, “dt” : “[20/Aug/2010:01:12:44 -0400]”}
{“user”: {“name”:”jeroenjanssens”, “password”: “123”}, “remote_ip”: “192.168.0.1”, “dt” : “[20/Aug/2010:01:12:44 -0400]”}
{“user”: {“name”:”unknown”, “password”: “”}, “remote_ip”: “76.216.210.0”, “dt” : “[20/Aug/2010:01:12:45 -0400]”}**
  • 收件人:
**"jehiah","127.0.0.1"
"jeroenjanssens","192.168.0.1"
"unknown","76.216.210.0"**
  • 您可以:
**$ cat input.json | json2csv -k user.name,remote_ip > output.csv**

阅读更多:https://github.com/jehiah/json2csv

制造

GNU Make 是一个工具,它控制从程序的源文件生成程序的可执行文件和其他非源文件。

**$ type make
make is /usr/bin/make**

阅读更多:https://www.gnu.org/software/make/

男人

系统参考手册的界面。

**$ type man 
man is /usr/bin/man**

例如:

**$ man ls**

阅读更多:https://nongnu.org/man-db/

毫微;纤(10 的负九次方)

GNU nano 被设计成 Pico 文本编辑器的免费替代品,Pico 文本编辑器是华盛顿大学 Pine 电子邮件套件的一部分。

**$ type nano 
nano is /usr/bin/nano**

阅读更多:https://nano-editor.org

平行的

GNU parallel 是使用一台或多台计算机并行执行作业的 shell 工具。

**$ type parallel 
parallel is /usr/bin/parallel** 

例如:

**$ seq 3 | parallel “echo Processing file {}.csv” 
Processing file 1.csv 
Processing file 2.csv 
Processing file 3.csv**

阅读更多:https://www.gnu.org/software/parallel/

它是一个安装和管理 Python 包的工具。

**$ type pip 
pip is /usr/bin/pip**

例如:

**$ pip install EvoCluster$ pip freeze | grep Evo
EvoCluster==1.0.4**

小狗

pup 库是处理 HTML 的命令行工具。它从标准输入中读取,打印到标准输出,并允许用户使用 CSS 选择器过滤页面的部分内容。

**$ type pup 
pup is /usr/bin/pup**

对于命令行,语法是:

**$ cat index.html | pup [flags] '[selectors] [display function]'**

计算机编程语言

Python 是一种编程语言,可以让您快速工作并更有效地集成系统。

**$ type python
python is /usr/bin/python**

对于命令行,语法是:

**$ python [-bBdEhiIOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]**

阅读更多:https://www.python.org

稀有

r 是一个用于统计计算和图形的自由软件环境。它可以在多种 UNIX 平台、Windows 和 MacOS 上编译和运行。

**$ type R 
R is /usr/bin/R**

阅读更多:https://www.r-project.org

rush 库是一个 R 包,可以让你直接从 shell 中运行表达式,创建 plots,安装包。

**$ type rush 
rush is /usr/local/lib/R/site-library/rush/exec/rush**

例如:

**$ rush run 6*7
42**

阅读更多:https://github.com/jeroenjanssens/rush

样品

在给定的延迟和一定的持续时间内,根据某种概率从标准输入中过滤掉行。

**$ type sample 
sample is /usr/local/bin/sample**

例如:

**$ time seq -f "Line %g" 1000000 | sample -r 1% -d 1000 -s 5
Line 71
Line 250
Line 305
Line 333
Line 405
Line 427
seq -f "Line %g" 1000000  0.01s user 0.00s system 0% cpu 5.092 total
sample -r 1% -d 1000 -s 5  0.06s user 0.02s system 1% cpu 5.091 total**

阅读更多:https://github.com/jeroenjanssens/sample

XML2json

使用 xml 映射 npm 模块将 XML 输入转换为 JSON 输出的命令。

**$ type xml2json 
xml2json is /usr/local/bin/xml2json**

对于命令行,语法是:

**$ xml2json < input.xml > output.json**

阅读更多:https://github.com/Inist-CNRS/node-xml2json-command

XMLStarlet

XML stallet库是一组命令行实用程序(工具),使用一组简单的 shell 命令来转换、查询、验证和编辑 XML 文档和文件,与使用 UNIX grep、sed、awk、diff、patch、join 等实用程序处理文本文件的方式类似。

**$ type xmlstarlet 
xmlstarlet is /usr/bin/xmlstarlet**

xsv

用 Rust 编写的快速 CSV 命令行工具包。

**$ type xsv 
xsv is /usr/bin/xsv**

例如:

**$ curl -LO [https://burntsushi.net/stuff/worldcitiespop.csv](https://burntsushi.net/stuff/worldcitiespop.csv)$ xsv headers worldcitiespop.csv
1   Country
2   City
3   AccentCity
4   Region
5   Population
6   Latitude
7   Longitude**

阅读更多:https://github.com/BurntSushi/xsv

祖蒂尔斯

Zutils 是一个工具集,能够透明地处理任何压缩和未压缩文件的组合。

更多阅读:https://www.nongnu.org/zutils/zutils.html

zcat

解压缩并将文件复制到标准输出。

zcmp

解压缩并逐字节比较两个文件。

zdiff

逐行解压缩并比较两个文件。

zgrep

解压缩并在文件中搜索正则表达式。

ztest

测试压缩文件的完整性。

zupdate

将文件重新压缩为 lzip 格式。

zsh

Zsh 是一个为交互使用而设计的 shell,尽管它也是一种强大的脚本语言。

**$ type zsh 
zsh is /usr/bin/zsh**

阅读更多:https://www.zsh.org

太神奇了!100 多个命令。对于那些每天使用命令行工具处理数据的人来说,这篇文章非常有用。

posted @ 2024-10-18 09:27  绝不原创的飞龙  阅读(372)  评论(0)    收藏  举报