TowardsDataScience 博客中文翻译 2020(八十七)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

使用 Python 在图像上添加文本

原文:https://towardsdatascience.com/adding-text-on-image-using-python-2f5bf61bf448?source=collection_archive---------5-----------------------

使用枕头库的简单机器学习项目

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

伊戈尔·米斯克在 Unsplash 上的照片

在这篇文章中,我将向你展示如何使用 Python 给你的图片添加文本。这将是一个非常简单的项目,我们将使用编程来做一些设计。在这篇文章之后,你将能够使用一些 python 技巧来设计你的下一张传单或名片。听起来是不是很酷?也许这不是设计的最佳方式,但这是可能的:)

作为一个喜欢设计和编程的人,我认为这将是一个伟大的项目,我可以结合我的两个兴趣。这实际上是编程的一大部分,你总能找到不同的领域来练习你的技能。在我之前的文章中,我展示了如何给你的视频添加文本,今天我们将在一张图片上做这件事。我们开始吧!

目录

  • 导入枕头库
  • 选择一幅图像
  • 字体选择
  • 渲染正文
  • 导出结果
  • 视频演示

[## 使用 Python 渲染视频文本

使用 moviePy 库的动手机器学习项目

towardsdatascience.com](/rendering-text-on-video-using-python-1c006519c0aa)

步骤 1-导入枕头库

首先,让我们安装这个项目需要的库。安装完成后,我们可以导入库以在项目中使用它。安装这个库的最好方法是使用 PIP,它是一个 python 包管理器工具。与大多数 Python 库完美配合。

pip install pillow

很好,现在我们可以将它导入到我们的代码中了。使用大型库时,与其导入整个库,不如练习导入将要使用的特定函数。这将在运行程序时节省存储空间和时间。对于我们的简单项目,我们只需要三个函数:Image、ImageFont 和 ImageDraw。

我们可以在一行代码中导入这三个元素,如下所示:

from PIL import Image, ImageFont, ImageDraw 

步骤 2 —选择一幅图像

在这一步中,我们将选择并导入一个要添加文本的图像。我推荐使用 Unsplash ,这是一个很棒的股票图片网站,可以找到质量很好的图片。以下是我下载的图片,也与秋季相匹配:

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

诺亚·西利曼在 Unsplash 上的照片

下载图像后,确保将它复制到代码所在的目录中。这将帮助您将其导入到程序中。让我们定义一个新的变量,并使用 open 方法分配图像。

my_image = Image.open("nature.jpg")

步骤 3 —字体选择

这个项目的好处是,你可以选择你的字体风格。定制字体会让我们在设计时更加灵活。

首先,我们将下载我们想要选择的字体的 TTF(TrueType 字体)文件。将文件放在同一个目录中后,我们可以使用 ImageFont 函数将其导入到我们的程序中。这是我将使用的字体。

title_font = ImageFont.truetype('playfair/playfair-font.ttf', 200)

现在,我们可以进入下一步,在这里我们将添加文本。

步骤 4 —呈现文本

这一步就是奇迹发生的地方。选好图片和字体后,就该决定写什么了。首先,我们将定义一个文本变量,并给它分配一个字符串。

title_text = "The Beauty of Nature"

其次,我们将使用 ImageDraw 函数将图像转换成可编辑的格式。多亏了枕头库,我们可以一行搞定。

image_editable = ImageDraw.Draw(my_image)

第三,我们将做渲染。我们将向渲染函数传递四个参数。我将在代码下面与一些有用的资源分享每个参数的描述。

image_editable.text((15,15), title_text, (237, 230, 211), font=title_font)
  • **起始坐标:**枕头库采用笛卡尔像素坐标系,左上角为(0,0)。
  • **文本:**单引号或双引号之间的字符串
  • RGB 格式的文本颜色: Google Picker 是寻找最佳颜色的绝佳资源。在谷歌上搜索“拾色器”,它就会出现。
  • 字体风格: Google Fonts 是挑选你的字体风格的绝佳资源,你也可以下载字体家族的 TTF(TrueType Font)文件。

[## 用 Python 构建颜色识别器

使用 OpenCV 的简单实用的机器学习应用程序

towardsdatascience.com](/building-a-color-recognizer-in-python-4783dfc72456)

步骤 5 —导出结果

干得好!我们差不多完成了。这将是最短的步骤,只导出编辑过的图像。下面是使用保存方法导出的代码。

my_image.save("result.jpg")

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

result.jpg

视频演示

[## 每当贝希克居文出版时收到电子邮件。

每当贝希克居文出版时收到电子邮件。注册后,如果您还没有,您将创建一个中型帐户…

lifexplorer.medium.com](https://lifexplorer.medium.com/subscribe)

恭喜你。!您已经创建了一个使用 Python 在图像上呈现自定义文本的程序。这不是设计图像的最佳方式,但是通过编程来实现它的可能性是很酷的。希望你喜欢阅读这篇文章并参与这个项目。如果你今天学到了新东西,我会很高兴。从事像这样的动手编程项目是提高编码技能的最好方式。

如果您在执行代码时有任何问题,请随时联系我

关注我的博客youtube 频道,保持灵感。谢谢你,

附加边际软最大损失(AM-Softmax)

原文:https://towardsdatascience.com/additive-margin-softmax-loss-am-softmax-912e11ce1c6b?source=collection_archive---------8-----------------------

了解 L-Softmax、A-Softmax 和 AM-Softmax

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

来源:SphereFace:深度超球面嵌入人脸识别

在本文中,我将记录我在阅读用于人脸验证的附加保证金 Softmax论文时,对附加保证金 soft max 损失或 AM-Softmax 损失的理解历程。在分类中,将创建一个决策边界来分隔类别。然而,当输出位于判定边界附近时,这可能是一个问题。AM-Softmax 旨在通过向决策边界添加余量来解决这一问题,以增加类的可分性,并使相同类之间的距离更紧密。

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

软最大 VS AM-软最大【来源】

除了 AM-Softmax,我还将讨论早期的作品,这些作品也将余量引入 Softmax 损耗,以不同的方式实现,如 L-Softmax 和 Angular Softmax,以便更好地理解 AM-Softmax。

目录

  1. 先决条件
  2. 软最大损失
  3. L-Softmax(大余量 Softmax)
  4. α-最大柔度(角度最大柔度)
  5. AM-Softmax(附加余量 Softmax)

先决条件

  1. 深度学习和神经网络基础
  2. 卷积神经网络

我假设你有深度学习和神经网络的基础知识,特别是 CNN,因为这可能是理解 AM-Softmax 所需要的。

Softmax 损失

在深入到 AM-Softmax 之前,我们先多退一步,刷新一下对 Softmax 损耗的认识。当我第一次听说最大损失的时候,我很困惑我所知道的,最大损失是一个激活函数,而不是损失函数。

简而言之,Softmax 损失实际上只是一个 Softmax 激活加上一个交叉熵损失。Softmax 是一个激活函数,它输出每个类的概率,这些概率的总和为 1。交叉熵损失就是概率的负对数之和。它们通常在分类中一起使用。您可以在下面看到 Softmax 和交叉熵的公式,其中 f 是 Softmax 函数, CE 是交叉熵损失。因此,Softmax 损失只是这两个相加。

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

Softmax 损失。来源:劳尔·戈麦斯

为了更好地理解 Softmax 损失,我建议阅读 Raúl Gómez 的一篇文章,因为他在 中清楚地解释了这一点,理解分类交叉熵损失、二元交叉熵损失、Softmax 损失、逻辑损失、焦点损失以及所有那些令人困惑的名称

大幅度软最大(左软最大)

L-Softmax 是在原始 Softmax 损失的基础上引入余量的第一批论文之一。这里的容限具有与三元组损失函数中的容限相似的概念,在三元组损失函数中,容限将增加类别之间的可分性或距离,并进而最小化相同类别之间的距离。这种类内紧密性和类间可分性将显著提高各种视觉分类和验证任务的性能。

在论文中需要注意的一件重要事情是,当我们使用术语 Softmax 损失而不仅仅是 Softmax 激活和交叉熵损失时,我们还包括分类器或全连接层。

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

根据上面的图像,我们可以将 Softmax 损失定义如下,其中 f 作为最后一个完全连接的层或分类器的输出。

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

软最大损失

全连接层的输出只是权重和前一层输出加上偏差的乘积。所以 f 也可以写成 W * x 如下。( b 或 bias 为简单起见被省略,但如果加上它仍然可以工作)

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

由于 fWx 之间的内积,因此也可表示为

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

其中θ是矢量 Wx 之间的角度。因此,Softmax 损耗也可以通过代入 f 定义如下。

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

修改的 Softmax

为了理解 L-Softmax 背后的直觉,我们将使用一个二元分类的例子。假设我们有一个来自类 1 的样本 x 。最初的 Softmax 需要W1x>W2x才能将 x 正确分类为 1。

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

二元分类

但是,W1x>W2x也可以写成如下。

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

接下来,我们希望分类更严格,并扩大决策范围。因此,我们需要下面的条件,其中我们将θ1 乘以一个正整数, **m,**和(0 ≤ θ1 ≤ π/m)。

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

这将为我们提供如下所示的决策余量。

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

L-Softmax 几何解释

因此,按照前面的要求。L-Softmax 损耗可定义为

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

L-Softmax 损失公式

我们要求ψ在哪里,

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

其中 m 是正整数,其中 m 越大,分类余量越大。然后,要求 D(θ)是单调递减函数,D( π/m)应等于 cos( π/m)。这是因为,我们希望 cos 函数在π之前只有一个递减的值,因此,如果 theta < π/m 和 D(θ)应该是递减函数,我们才使用 cos 函数。

为了满足上述要求并简化前向和后向传播,本文构造了一个特定的ψ,如下所示,其中 k ∈ [0,m1],k 为整数。

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

总之,L-Softmax 引入了一个可调的裕度,它鼓励学习特征的类内紧密性和类间可分性,这可以显著提高各种视觉分类和验证任务的性能。可以使用参数 m 来控制裕量,其中较大的 m 导致较大的决策裕量。L-Softmax 还在几个基准数据集上进行了测试,与当时的其他方法相比,它表现出了更好的性能和更低的错误率。

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

来源:卷积神经网络的大幅度软最大损失

角度软最大值

2018 年在论文中介绍了 Angular Softmax, SphereFace:用于人脸识别的深度超球面嵌入。Angular Softmax 非常类似于 L-Softmax,因为它旨在实现比最小类间距离更小的最大类内距离。然而,它与 L-Softmax 的不同之处在于将分类器权重 **W、**归一化为 1。这导致了在开集人脸识别数据集中性能的提高,在开集人脸识别数据集中会有在训练期间不存在的人脸。

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

闭集 VS 开集【来源】

如前所述,A-Softmax 与 L-Softmax 非常相似,只是分类器权重 W 被归一化为 1,偏差被设置为 0。因此,之前修改的 Softmax 公式

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

修改的 Softmax

将更改为

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

具有归一化权重的修改的 Softmax

因此,如果我们使用相同的二进制分类示例。将样品 x 正确分类为 1 类的要求将从

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

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

因为|W1| = |W2|,因此|W1||x| = |W2||x|我们可以从等式中抵消 W 和 x。

然后,引入保证金,它将

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

m 越大,决策界限越宽。决策边界方程的比较如下表所示。

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

【来源】

因此,A-Softmax 损失最终可定义为

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

最大损失

在哪里

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

A-Softmax 的一个优点是它在超球解释中也能很好地渲染。

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

【来源】

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

超球解释用不同的*【来源】*

总之,A-Softmax 对分类权重进行了归一化处理,使偏差为零,并引入了可通过参数 m 进行控制的角裕量,以学习具有区别性的特征,并具有清晰的几何解释,这将在开集数据集中表现得更好,如下所示。

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

【来源】

最大附加余量(AM-Softmax)

AM-Softmax 随后在用于人脸验证的附加余量 soft max论文中提出。它采用了不同的方法来增加 softmax 损失的利润。它不是像 L-Softmax 和 A-Softmax 那样将 m 乘以 θ ,而是通过将 ψ(θ) 改为

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

与 L-Softmax 和 A-Softmax ψ(θ) 相比,这要简单得多,AM-Softmax 的性能也更好。此外,与 A-Softmax 类似,AM-Softmax 也对权重和偏差进行归一化处理,但引入了一个新的超参数 s 来缩放余弦值。最后,AM-Softmax 损耗可以定义如下。

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

因此,决策边界将形成于

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

AM-Softmax 判决边界

其中,在二元分类示例中,P1 是类别 1 的特征,p2 是类别 2 的特征。

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

AM-Softmax 在二进制分类中的直观解释【来源】

为了更好地可视化 AM-Softmax 损失的影响,使用具有时尚 MNIST 数据集的 7 层 CNN 模型将其与其他损失进行比较。CNN 模型的 3 维特征输出被归一化并绘制在如下所示的超球体(球)中。从可视化中,您可以看到 AM-Softmax 在对输出进行聚类时的性能与 SphereFace (A-Softmax)相似,并且随着裕度的增加,m 越大,性能越好。

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

超球面几何解释【来源】

此外,AM-Softmax 和其他损失也在开放集数据集上进行测试,使用 Casia-WebFace 进行训练,使用 LFW 和 MegaFace 进行测试,并移除重叠身份。我们可以看到 AM-Softmax 优于其他损失,特别是在 MegaFace 数据集上。

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

【Source】:用于人脸验证的附加边距 Softmax】

摘要

总之,L-Softmax、A-Softmax 和 AM-Softmax 损失都试图通过引入 Softmax 损失的余量来结合分类和度量学习,并旨在最大化类之间的距离和增加相同类之间的紧密性。在这三个模型中,AM-Softmax 被证明在模型性能方面提供了最好的提高,特别是在用于人脸验证的 LFW 和 MegaFace 数据集上。

最后,我要衷心感谢我团队中的所有同事,尤其是阿克毛、易卜拉欣和英·康咪咪,他们回答了我所有的问题,并帮助我理解了这些概念。

附言:看看我的另一篇关于圈损的文章。我实际上读到了 AM-Softmax,因为它被圈损论文引用了。它引入了一个有趣的统一公式,可以根据输入退化为 AM-Softmax 或三重态损耗。

* [## 暹罗网,三重损失,圆损失解释。

理解“圈损失:对相似性优化的统一观点”

medium.com](https://medium.com/vitrox-publication/understanding-circle-loss-bdaa576312f7)

参考

【1】刘文伟,温,于,杨。卷积神经网络的大幅度软最大损失。国际机器学习会议,第 507–516 页,2016 年

【2】刘文伟,温,俞正声,李,拉杰,宋。用于人脸识别的深度超球面嵌入。2017 年 IEEE 计算机视觉和模式识别会议论文集。

【3】王凤芳,郑俊杰,刘文伟,刘浩辉。用于人脸验证的附加余量 softmax。IEEE 信号处理快报,25(7):926–930,2018。*

使用 Pytorch 第 2 部分轻松解决班级失衡问题

原文:https://towardsdatascience.com/address-class-imbalance-easily-with-pytorch-bb540497d2a6?source=collection_archive---------23-----------------------

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

使用 Pytorch 对同一棵向日葵进行过采样?图片来源于杰弗里·约翰逊

了解 Pytorch 的称重随机取样器

在之前的文章中,我们看到了如何通过加权随机采样器进行过采样来解决类不平衡问题。实际上,这降低了过度拟合的风险。在本文中,**我们将展示 WeightedRandomSampler 是如何实现的,并给用户一些直觉。**我们首先给出一个应用简单统计的例子,然后我们从数学上处理一个更一般的场景。我们的目标是理解我们如何从每个类中得到相同数量的观察结果,即使它们是不平衡的。

没有比不明白我们用什么更糟糕的了,对吗?🤗

。如果你喜欢这篇文章,一定要关注我。很多人喜欢我的文章,请关注我以示支持,这真的很有帮助!🤗

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

我们数据集的 10 个批次中的类分布。红色表示辅修课,蓝色表示主修课。我们使用 WeightedRandomSampler 从左边不平衡的数据集到右边更平衡的数据集。

现在让我们看看 Pytorch 中实现的 WeightedRandomSampler 的源代码。我们将学习一些理论来理解代码,然后看一个简单的例子来很好地理解实现。

Pytorch 的源代码中,关键函数如下:

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

在 WeightedRandomSampler 类中,关键函数是 call iter

**一个关键思路:**从有控制参数的多项式分布中提取。

Pytorch 使用具有给定参数的多项式分布,即权重、样本数量 s 的以及我们是否使用替换进行采样。

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

Pytorch 引入的关键思想是从点集的多项式分布中提取。每个点被赋予一个给定的采样概率。这种概率由其具有给定权重参数的类来定义。

一个简单的例子:

让我们假设我们的数据点按如下方式排序:

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

左边是 100 个观察值,中间是它们的类别分布,右边是 WeightedRandomSampler 分配的权重参数。蓝色代表大类,红色代表小类。

我们可以控制权重,以便给予次要类别更多权重:

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

然后,我们绘制一个带有受控参数的多项式分布。每个参数定义了一个给定观察值的绘制概率。事实上,我们是从一组观察值的多项式分布中得出的。

这里,我们将权重参数设置如下:

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

将 WeightedRandomSampler 中的权重设置为每个类别分布的经验先验的倒数。

概率可以通过使用类似于 softmax 函数的简单标准化权重向量来找到。例如,可以执行以下操作:

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

重要提示:我们需要对 N 个观测值进行归一化处理。目标是得到一个元素之和等于 1 的向量。这不是通过权重向量实现的,因此标准化是必要的。

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

从权重向量(左边)到概率向量(右边)。蓝色代表大类,红色代表小类。

现在,我们能否从数学上展示,在抽取 100 个随机样本后,我们如何从 c0 中抽取 50 个观察值,从 c1 中抽取 50 个观察值?

设一个随机变量描述 c1 中采样 m 个点后的观测数,这里设为 100。

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

因此,

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

利用期望的线性度,我们可以在小类 c1 的点集上得到一个线性方程。

现在,我们知道,从一个多项分布中,在采样 m 次后,我们可以将期望值表示如下:

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

采样一个点 xi 有一个由多项式分布多项式(【x1,…,x90,x91,…,x100],[p0,…,p0,p1,…p1])。

对于位置[91,100]中的所有观察值,我们说它们属于 c1 类:

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

结果,从辅修课 c1 中抽取的期望点数(最初包含 10 个点)现在是 50 个。类似地,主要类别 c0 的预期观测值数量如下:

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

从类别 c1 中提取的预期观察值数量也在 50 左右。

更严谨,更通用:

在这一节中,我们试图更加概括。然而,为了简单起见,我们假设我们处理的二元问题只有两个类 c0 和 c1。

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

蓝色代表大类,红色代表小类。

我们现在有 N 个观察值,使得:

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

我们需要像前面的例子一样建立概率。这次,我们有:

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

现在我们要生成从整组点 X 上的多项式分布中采样的 m 个点:多项式 (X,[p0…,p0,p1,…p1])。

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

我们从数据 x 中生成 m 个样本。

我们定义一个随机变量来描述一个点是否来自类 c0:

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

描述抽样观测值是否属于 C0 类的随机变量。

因此,我们可以很容易地表达这样的随机变量的期望值:

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

现在让我们描述随机变量,它给出了从 c0 类中采样的点的总数:

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

因此,我们可以计算 m 次后从类 c0 采样的元素的预期数量:

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

我们之前已经了解了如何在加权随机采样器中设置权重:

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

将 WeightedRandomSampler 中的权重设置为每个类别分布的经验先验的倒数。

现在我们可以有一个更简单的表达式来表示在 m 次之后从类 c0 中采样的元素的预期数量:

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

这意味着我们期望正好一半的采样观察值来自 minor 类。我们从数学上解决了类别不平衡问题,证明了我们可以从次要类别中采样与主要类别完全相同数量的观察值。

贝叶斯理论的进一步发展:

给每个类增加权重相当于贝叶斯方法。我们调整了优先等级,给了次要等级更多的权重。这种等价性通过以下关系式得到强调:

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

事实上,我们可以将我们的抽样方法建立在贝叶斯理论的基础上,我们引入了一个叫做先验的新元素。该过程是顺序采样:

  • 第一步:抛一枚概率为 p(c0)的非公平硬币,得到小类 c0,概率为 p(c1)得到大类 c1。
  • **第 2 步:**从上一步中抽取的类中,对一个观察值进行统一采样:

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

顺序抽样的第二步,我们从第一步确定的固定先验类别中抽取一个点。

结论

总之,通过使用带有多项式分布的加权随机抽样器,我们期望从每一类中得到相同数量的观察值。

关键思想在于在一组观察值上构建多项式分布,其中每个观察值表现为其自己的类,具有受控的被抽取概率。

贡献者:

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

索海尔。洛桑联邦理工学院应用数学专业硕士研究生。

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

马斯塔法。之前是微软的数据科学家实习生和瑞典皇家理工学院的机器学习学生。

使用 Pytorch 轻松解决班级失衡问题

原文:https://towardsdatascience.com/address-class-imbalance-easily-with-pytorch-e2d4fa208627?source=collection_archive---------21-----------------------

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

计算机视觉中的数据增强。图片的制作者名单为 fastai

当你的模型过度拟合你的数据时,你能做什么?

重要提示:如果你能看到这个故事的结尾,请考虑在灵媒上跟我学更多的。我将非常感谢你的支持。

这个问题经常发生在我们处理不平衡数据集的时候。如果您的数据集代表几个类,其中一个比其他的少得多,那么就很难了解代表这样一个小类的真正的底层分布。

正如这篇必读的论文、**中所解释的,解决几乎在所有分析场景中都占主导地位的类不平衡的方法是过采样。**过采样应应用于完全消除不平衡的水平,而最佳欠采样率取决于不平衡的程度。与一些经典的机器学习模型相反,过采样不会导致 CNN 的过拟合。

在实践中,当训练机器学习模型时,人们将遵循一些关键步骤:

  1. 将数据分成一个训练/测试集(80%,20%)。
  2. 通过对训练数据进行拟合来训练机器学习模型。
  3. 在测试集上评估性能。

当使用深度学习架构时,通常会将训练数据分成几批,我们在训练期间将这些数据馈送给我们的神经网络。为了构建这样的批次,我们通常按照观察值集的均匀分布从训练集中随机抽样。

现在需要一些简单的统计数据。假设我们有一个包含两个类 class_1class_2 的数据集。class_1 中随机抽取一个点的概率是多少?

遵循点集合上的均匀分布,这样的概率很容易表达:

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

实际上,在二元问题中,当我们从一个类中得到的观察值比另一个类中得到的多得多时,就会出现类不平衡:

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

因此,我们有:

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

二元问题中的类别不平衡由从给定类别中得出观察值的不平衡可能性来描述。

换句话说,从 class_1 比从 class_2 更有可能得出一个点。因为模型看到的 class_2 要少得多,所以它不能从这样的类中学习有用的特征也就不足为奇了…

现在,在深入编码之前,我们需要理解人工扩充数据时的一个关键思想。我们想要的是确保通过人为增加辅修班,我们有:

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

在扩充了我们的数据之后,我们的目标是使从每个类中抽取样本的可能性尽可能接近。

是时候了!让我们用 Pytorch 的weighted random sampler来编码解决这个问题。

数据集:我们用来自 class_major 的标记为 0 的 900 个观察值和来自 class_minor 的标记为 1 的 100 个观察值构建数据集。(90%, 10%)

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

我们数据集的样本。标签 1 对应于法语句子,标签 0 对应于英语句子。

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

具有文本数据和两类值 0 和 1 的不平衡数据集的类分布。我们有 900 个 0 类句子和 100 个 1 类句子。

假设我们构建了 10 批,每批 100 个句子,我们最终将得到平均 10 个第 1 类句子和 90 个第 0 类句子。

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

每班分配 10 批,每批 100 句。红色代表小类,蓝色代表大类。我们可以清楚地看到每一批训练数据中的不平衡。0 类的估计比例现在是 90.5,1 类的估计比例是 9.5。

**如何轻松重新平衡以上内容?**让我们用 Pytorch 库写几行代码。

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

24 行 python 魔术构建平衡批次。

从上面我们可以看到 WeightedRandomSampler 使用数组 example_weights 对应于赋予每个类的权重。目标是给次要类分配更高的权重。这将通过从均匀分布移动到具有受控参数的多项式分布来影响从每个类中提取点的可能性。

现在我们可以详细看看 *arr_batch 中包含的批次,*每个批次实际应该有 100 个句子。出于形象化的目的,我们只关注这里的标签。

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

0 类的估计比例现在是 51.4,1 类的估计比例是 48.6。

正如我们从上图中看到的,我们现在有了平衡的数据批次。因此,在训练期间,我们的模型不会看到一个类别比另一个类别多很多,因此降低了过度拟合的风险。

总之,我们看到:

  1. 过采样是解决类不平衡的关键策略,因此降低了过度拟合的风险。
  2. 当数据集中存在类别不平衡时,从数据集中随机取样是个坏主意。
  3. 使用 加权随机抽样加权随机抽样器 通过对次要类进行过抽样来重新平衡我们的训练数据类。

重要的:如果你到目前为止,一定要在 Medium 上关注我,以示支持。🤗

在下一篇文章中,我们将深入研究 WeightedRandomSampler的实现,更好地理解加权方案。我们还将在一个简单的机器学习场景中应用过采样,并分析其对整体性能的影响。

感谢阅读,如有任何反馈,请在下方留下评论!🤗

解决人工智能的隐藏议程

原文:https://towardsdatascience.com/addressing-ais-hidden-agenda-e67d353769ff?source=collection_archive---------34-----------------------

人工智能中内隐偏见的来源和显著例子有哪些?在建立可接受的数据实践中,怎样做才能最小化它们的后果?

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

图片来源:巴伊特·罗斯·史密斯

当我们唤起人工智能的隐性偏见时,我们正在认识到机器学习反映了在重复和例外情况下影响管理理解、行动和决策的不合理态度和刻板印象。尽管这种偏见可能是有利的,也可能是不利的,但这些隐含的评估或信念可能会严重限制组织客观利用数据科学的能力。人工智能中存在四种潜在的隐性偏见来源:数据、算法、我们自己的逻辑以及我们对道德行为的定义。让我们依次探索每一个。

机器学习涉及指定用于训练(测试)算法的数据集,该算法随后将用于现实世界条件。虽然作为一个规则,一个组织收集的训练模型的数据越多,结果就越好,但在实践中,隐含偏差的几个来源显著地损害了模型的相关性。当用于训练模型的数据不能准确表示模型将在其中运行的环境或问题空间时,就会出现样本偏差。当训练数据内容受到来自人群的刻板印象或偏见的影响时,就会出现偏见。最后,测量偏差来自错误的测量,其结果系统地污染了数据。

Twitter 流为消费者意见的情感分析提供了一个公共资源,也是样本偏差的一个生动例子。当运行 SVM 和朴素贝叶斯等算法时,Twitter 是文本挖掘的合理选择,因为产生的数据集易于访问,具有成本效益,并且包括各种各样的消费者资料。然而,这种选择提供了一组特定技术用户的意见,而不是一般人群的代表性样本。它将错过那些无法使用智能手机(也无法使用电脑)的人,更不用说那些对这一社交媒体渠道过敏的人了。测试数据可能包括来自大量涌入该媒体的自动用户账户的几条消息,以及这些机器人的转发,这些机器人被编程为在每个问题上提供两极分化的立场。

处于机器学习核心的算法永远不会比用于测试它们的数据更好。

隐含偏差的第二个来源是构造算法来解释或预测现实世界现象的方式。对于数据科学家来说,偏差和方差一起描述了影响预测性能的算法属性。由于偏差和方差是相互依赖的,数据科学家被迫在两者之间寻求平衡。具有高方差的模型往往更适合训练数据,但可能不能很好地推广到训练数据集之外的数据。对于一个给定的用例,在两者之间找到适当的平衡是任意的,并且对于依赖这些算法的组织决策者来说通常是不透明的。

Equivant 的 COMPAS 软件在许多刑事司法系统中广泛用于保释和判刑。这种专有软件依靠一种算法来预测重复犯罪的可能性。这也是算法偏差的一个证据充分的例子。2016 年初,新闻机构 ProPublica 发表了一项研究,证明了该算法的种族偏见:它系统地高估了黑人被告的犯罪意图,同时低估了白人被告的累犯率。尽管由于软件的专有地位,COMPAS 的算法不向公众开放,但该算法显然有两倍的可能将黑人被告错误分类,白人惯犯有 63.2%的时间被错误分类。

偏见的第三个来源可以在人类从他们看到的数据中归纳和推断逻辑结论的方式中找到。认知偏差是在判断中偏离规范或理性的系统模式。一些认知偏差可能是适应性的。认知偏差可能会影响对相似性、判断、记忆和行动的感知。尽管认知偏差可能会在每种情况下导致更有效的行动,但它们通常会导致对个人和业务挑战的误导性表述。某些认知偏差是人类处理局限性的“副产品”,要么是由于缺乏适当的心理机制,要么是由于管理者处理信息的带宽有限。

这种认知偏差导致团队刚刚实现盈利的经理们将可用数据视为市场正在增长的证据,而苦苦挣扎的经理们则倾向于将相同的数据解读为相反的证据。可用性偏差涉及到一种认知机制,在这种机制中,管理者在鉴定新信息时会优先考虑容易想到的数据。如果他们正在进行风险评估,他们倾向于通过最近发生的或提供强烈情感依恋的类似事件来衡量新数据。管理判断的准确性受到经验的影响,他们更有可能低估或高估事件发生的可能性。这回避了一个问题,即人类理性是否不可避免地背负着认知偏见,或者管理决策的内在价值是否是管理者有选择地解释人工智能结果的能力?。

偏见的最后一个来源来自人类对伦理的看法。伦理可以理解为一套指导个人和组织行为的一般原则。道德反映了我们对什么是对什么是错的看法,我们对公司及其市场性质的信念,以及我们对商业实践中可接受的行为的看法。根据文化相对主义的支持者,伦理行为并不存在唯一的真理:我们对可接受限度的解释受到现有社会规范、文化习俗和宗教影响的制约。道德考量通常与我们对自身利益的认知相冲突,因此,许多经理可能会越界,而没有意识到他们正在做任何不道德的事情。

以斯坦福大学以人为中心的人工智能研究所为例。该大学去年成立了该研究所,其愿景是“人工智能的设计师必须广泛代表人类”。然而,当该研究所透露 120 名教师和技术领导者参与该计划时,超过 80%的人是白人,几乎同样多的人是男性。这个群体到底代表了什么?他们代表了不同的种族、文化和当今行业的知识潮流,还是代表了大众?大多数人在专门的商业和工程学校接受教育,他们能够应对当地的道德挑战吗?如果它们确实代表了当今的挑战,那么这种代表是否应该被修改以代表更理想的多样性?

可以做些什么来最小化人工智能隐含偏见的后果?一个策略可以是提高管理层对整个组织使用的数据、算法和应用程序中隐含偏差来源的认识。一个补充的策略将包括定期评估用例以及数据驱动的决策,以寻找不良偏差的证据。识别经常困扰管理决策的风险、不确定性和模糊性的来源,可以帮助确保将机器智能用在最有效的地方。高级管理层可以更进一步,确定并有意识地承认可接受的数据实践和期望的道德立场。最后,但同样重要的是,组织和专业协会可以建立反馈机制,以鼓励围绕数字伦理的讨论和辩论。

这篇文章是我们对 Jay Liebowitz 即将出版的“数据分析和人工智能”一书的贡献的一部分。关于数字伦理的进一步想法可以在我们关于数字伦理的电子书中找到,也可以在我们在商业分析研究所举办的管理会议、课程和暑期学校中找到。

Lee Schlenker 是商业分析和社区管理教授,也是 BAI 的校长。他的 LinkedIn 个人资料可以在www.linkedin.com/in/leeschlenker.查看,你可以在https://twitter.com/DSign4Analytics的 Twitter 上关注白

通过数据解决对新冠肺炎报道的批评

原文:https://towardsdatascience.com/addressing-criticisms-to-covid-19-reporting-through-data-de0a4c0eea8?source=collection_archive---------39-----------------------

调整世界末日数字的轻触式尝试

在过去几个月的谨慎“回归正常”时期之后,英国首次实施封锁措施的 6 个月纪念日即将到来,随之而来的是再次收紧限制的承诺。我们大多数人都预料到,在经历了夏季的相对轻浮之后,会出现某种形式的第二次封锁,因此,对于鲍里斯·约翰逊宣布重新引入某些限制以遏制病毒传播,很少有人会感到惊讶。看着报告的阳性病例以惊人的速度增加,这似乎也是一个显而易见的决定:

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

图 1 英国总病例数— 来源

随之而来的是公众对报道的数字越来越怀疑。包括英国广播公司在内的一些媒体对这些数字的可靠性提出了质疑,原因是观察到住院人数和与 COVID 相关的死亡率都没有接近报告的阳性病例率:

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

图 2 英国住院总人数— 来源

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

图 3 英国总死亡人数— 来源

虽然这些渠道提出的所有挑战可能都不成立,但它们确实凸显了这些数字的报告方式存在的一些突出问题,更重要的是,公众以及政府对这些数据的解读方式也存在问题。在接下来的几分钟里,我试图强调其中的几个,并提供从不同角度看待这些数字的方法。

放弃

开始之前,我想强调我不是医生、流行病学家、医学生物学家、卫生部长、政策顾问、经济学家和功利主义哲学家。这些计算应该有最大限度的保留,当然不能用来支持任何议程。然而,我确实相信,如果政策决定是基于数据做出的,那么数据应该尽可能地被仔细检查。

英国 COVID 报告的问题

我将探讨关于阳性病例报告的三个关注领域,但在我们深入探讨之前,有必要提供一点关于英国如何进行检测的背景。

测试目前以 4 种方式进行(支柱)。这些是:

  • 支柱 1: NHS 和 PHE 检测 —在英国公共卫生(PHE)实验室和 NHS 医院为有临床需求的人以及卫生保健工作者进行 PCR 拭子检测
  • 支柱 2:商业伙伴检测——政府指导中规定的针对更广泛人群的 PCR 拭子检测
  • 支柱 3:抗体检测——抗体血清学检测,以显示人们是否有 6 月 1 日以来报告的新冠肺炎病毒抗体
  • 支柱 4:监测检测——在 PHE、国家统计局、生物银行、大学和其他合作伙伴的支持下,为国家监测进行抗体血清学和 PCR 拭子检测,以更多地了解病毒的流行和传播情况,并用于其他检测研究目的,例如家庭检测的准确性和易用性

支柱 1、2 和 4 都是在不同情况下进行的 PCR 拭子试验;支柱 3 是与众不同的,它是一项血清抗体测试。支柱 2 测试通过商业承包商、在移动测试点或通过送到人们家中的工具包进行。顺便说一句,支柱 2 测试在最近几个月有显著增加,因为政府正在加强其测试计划(理应如此)。这就引出了第一个问题。

案例没有根据测试数据进行调整

敏锐的观察者会点击 gov.uk 上的每日病例计数,并漫步到显示 pillar 进行的测试数量的图表上:

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

图 4 支柱在英国进行的测试— 来源

虽然大多数支柱保持相当一致,但支柱 2 测试(深蓝色)的活动自 8 月份以来显著增加,尤其是在 9 月份。

这个问题应该是显而易见的:你测试得越多,你就会发现越多的情况。这背后的科学非常直观;至少一些阳性病例的增加可以用这样一个简单的事实来解释,即更多的家庭药盒被提供和使用。

测试被认为是完美的

这些数字的一个更微妙的复杂因素不是来自有多少人接受了测试,而是我们能在多大程度上信任这些测试。医学测试并不完美,你对自己的诊断有多少把握很大程度上取决于它们的预测能力。与分类算法非常相似,医学中的诊断工具具有敏感性和特异性。为了在 COVID 的上下文中理解它们,首先孤立地看它们是有用的。

敏感性给了我们明确患有冠状病毒的个体被诊断为冠状病毒的概率。如果我们以 60%的灵敏度测试 10 个肯定携带病毒的人,结果(平均)将返回 6 个阳性病例和 4 个阴性病例:

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

图 5 作者图,图标 bqlqn 制作

另一方面,特异性是健康人被正确识别为阴性诊断的概率。如果用具有 60%特异性的试剂盒测试 10 个健康人,结果将平均返回 6 个阴性和 4 个阳性:

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

图 6 作者图, bqlqn 图标

我们可以用略高的数字来说明在大规模测试中特异性的影响。假设我们有 100 个人,其中 10 个肯定有病毒,90 个没有。在这种情况下,100%灵敏度、90%特异性测试会给出什么结果?

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

图 7 作者图,图标 bqlqn 制作

该测试具有 100%的灵敏度,因此它能直接正确地识别所有 10 名真正受感染的人。然而,90%的灵敏度意味着剩余的 90 个阴性中只有 90%被正确诊断,剩余的 9 个人在他们实际上没有携带病毒时检测为阳性。

这是怀疑论者书中的另一个关键章节;如果特异性(或者更确切地说是 1-特异性)明显高于病毒的实际流行率,更多的检测只会把水搅浑,并必然增加阳性检测病例的数量。RT-PCR 检测的实际灵敏度和特异性分别在 60-85%和 94-99%之间,这取决于你咨询的是哪项(小样本)研究。

不管怎样,特异性和敏感性应该(而且确实)在真实患病率的估计中发挥作用,我们将在下一节探讨。

测试支柱一视同仁

但首先,我想指出一些更微妙的东西;测试进行的环境对于我们能在多大程度上依赖其结果非常重要。当然,由医院专业人员进行的检测(例如,在医院可以进行重复检测以减少不确定性)应该比带回家的试剂盒更有意义,在医院人们自己进行擦拭,污染的风险要高得多。

有趣的是,尽管这些因素表明以医院为基础的支柱 1 测试的阳性率更高,但实际情况恰恰相反:

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

图 8 支柱 1 的比率& 2 在英国检测返回阳性— 数据来源

自 6 月份以来,在医院检测出阳性的机会已经减少,并且对于带回家的试剂盒来说保持相对稳定,直到两者在 9 月份再次开始增加,到那时,你在家里检测出阳性的可能性是在医院的 4-5 倍。

对此可能有多种解释,但我只能猜测(不是专家,记得吗?)——例如,这可能是污染和人口统计学差异的结合。支柱 2 测试在护理院中使用很多,这些护理院因局部大规模感染而闻名,但它们也在普通公众中使用,大概是在旅行或工作之前。另一方面,支柱 1 测试用于病人和有医疗需求的人。另一个关键区别是,支柱 2 测试由商业承包商处理,因此涉及的方法可能有所不同。

无论如何,这种系统性的差异应该被强调,尤其是当这些阳性病例被一起报告时。

我们能做得更好吗?

在本文的最后一部分,我将演示一些方法来解决我上面概述的问题。为了简洁起见,我不会分享内嵌的代码片段,但我会让任何人都可以阅读我的笔记本。

数据

我将在 5 月 28 日至 9 月 9 日期间使用英国 15 周的支柱 1 和 2 测试结果,这些结果发布在 gov.uk 上。该数据提供了按支柱分列的每周测试总数和阳性测试案例。快速浏览一下阳性病例总数,我们会看到熟悉的上升曲线:

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

图 9 周正支柱 1 & 2 测试案例— 来源

我在这里的工作是:

  1. 在给定 PCR 检测的特异性和敏感性估计值的情况下,估计测试人群中活动性感染的真实流行率
  2. 对支柱 1 和 2 分别执行此操作
  3. 针对每周样本量的差异进行调整

估计真实流行率

你的医学测试不是 100%准确的想法并不新鲜。因此,已经推导出一个非常简单的公式,如Lewis&Torgerson(2012)所示:

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

其中 P_t 是该疾病在人群中的真实患病率, P_a 是表观患病率, S_eS_p 分别是诊断测试的灵敏度和特异性。注意,这里我们有 3 个未知数,数据只提供给我们表面的患病率。鉴于 P_a 是获得阳性测试结果的概率,我们的观察值(测试结果)将遵循二项分布:

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

P_a 由三个未知数参数化, P_tS_eS_p — 这些我们都不确定。为了解决这个问题,我将使用贝叶斯推理和马尔可夫链蒙特卡罗(MCMC)抽样来绘制给定先验分布的参数的随机值,将结果与上面由二项式 PDF 给出的概率进行比较。给定测试结果,我的 P_t 的后验概率应该在真实患病率附近收敛。

灵敏度和特异性先验

我们简要讨论了 PCR 拭子试验的敏感性和特异性;这些研究的结果有很大的不同,取决于许多因素,如人口统计、地理、疾病阶段和研究时间。张&杜(2020) 将这些结果汇总在一起,给出了敏感性和特异性的估计概率分布,我从中获得了构建β先验的灵感:

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

其中支柱 1 和支柱 2 拭子测试的灵敏度和特异性的平均值分别为 0.821 和 0.983,但是支柱 2 灵敏度的方差加倍,表示家用试剂盒正确检测病毒的能力的不确定性更高。

真实患病率先验

这就是事情变得更加困难的地方。COVID 是一种疫情,因此它的流行率会随着社区、人群和人群的变化而变化,所以在这里使用海外的研究不会很有效。理想的数据集将来自支柱 4 测试,它正是为此目的而设立的。可悲的是,英国政府并没有公布结果(最近拒绝了信息自由的要求这样做)。

由于缺乏好的数据,我的最佳选择是最初相信结果告诉我的东西,并用与那一周的明显患病率相对应的方法构建我的β先验(对我的参数进行一定程度的任意缩放,以表示我对结果的信心):

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

我可以画出从 9 月 3 日开始的一周内的真实流行率:

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

图 10 敏感性、特异性和患病率的β先验

蒙特卡罗马尔可夫链抽样

我们可以从之前的 3 个分布中随机抽取样本(支柱 1 和支柱 2 ),根据之前的公式估计我们的表观患病率。然后,我们可以将其与我们观察到的数据进行比较,评估这些样本出现的可能性,给出我们表观患病率的二项式分布,并构建后验分布。

抽取 10,000 个样本后,支柱 1 的后验概率如下所示:

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

图 11 支柱 1 后视图

敏感性和特异性大致保持不变,我们对支柱 1 测试真实流行率的估计集中在一个较低的平均值附近(从 0.010 下降到 0.006)。

支柱 2 也是如此:

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

图 12 支柱 2 的后视图

同样,测试准确性指标保持相对一致,而流行率从 0.040 下降到 0.031。

每周估计

我们可以为我们的个人每周观察重复上述过程,根据我们的数据重新创建先前的构建练习。这使我们能够将估计的流行率与报告的流行率进行对比;我将 94%的最高后验密度值作为伪置信区间包含在图上:

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

图 13 支柱 1 & 2 的估计流行率

我们观察到,两个支柱的估计平均患病率始终低于报告的患病率,然而,报告的患病率确实在 94% HPD 范围内。

我们还可以按支柱构建总病例的估计值,方法是通过已进行的总检测按比例放大患病率估计值,从本质上给出我们认为受检测者中有多少人真正被感染:

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

图 14 支柱 1 & 2 的预估案例

最后,我们可以结合支柱 1 和 2 案例的估计值,将其与报告的案例总数进行比较:

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

图 15 两大支柱的估计案例总数

我们从中学到了什么?

我概述了英国新冠肺炎报告面临的一些挑战,并提供了一些解决这些挑战的方法,展示了它们对公开数据的影响,特别说明了 PCR 检测的估计特异性和敏感性,着眼于估计患病率而不是总病例数(不考虑检测量),并分别处理了两个支柱。这告诉了我们什么?

阳性结果可能比报道的要少…

也就是说,在被测试的人群中。假设我们对聚合酶链式反应测试准确性的了解是正确的,并且我们的先验具有相当的代表性,那么实际的阳性案例可能低于支柱 1 & 2 中报告的案例。话虽如此,如果我们扩大到英国的人口,即使减少的估计流行率也意味着全国范围内更高的实际阳性病例数*,所以可能没有理由放松。*

…但病例可能仍在增加

在理想情况下,我们可以通过支柱 4 测试结果更好地估计真实流行率,但是估计(和报告)的流行率表明,即使我们对进行的测试数量进行调整,我们仍然观察到从 9 月开始阳性病例相对急剧上升。虽然特定支柱数据的可用性仅允许我们对截至 9 月 9 日的数据进行建模,但从报告的案例总数来看,有理由假设这一趋势将在此后继续。

那现在怎么办?

我们已经能够解决怀疑论者提出的一些挑战,并为他们提供数据驱动的解决方案。虽然我们的分析显示,真正被发现的病例数量总体较低,但我们不能否认患病率突然上升。相对于阳性病例,住院率可能仍然较低,但在我们的新世界中保持谨慎可能是明智的,以免我们发现自己处于一种因缺乏能力而无法治疗疾病的境地。

事后思考

我做错什么了吗?我能做得更好吗?我做得好吗?

请随时在 LinkedIn 上联系我;如果你对我的工作感兴趣,我总是很乐意接受挑战或者只是聊聊天。

如果你想自己玩代码,请点击我的 Google Colab 笔记本的链接:

* [## 谷歌联合实验室

编辑描述

colab.research.google.com](https://colab.research.google.com/drive/1l3l-ZQ2fJQozHh_vn03WwIr-oWGX7JQm?usp=sharing)*

解决人工智能中的种族偏见:好奇者指南

原文:https://towardsdatascience.com/addressing-racial-bias-in-ai-a-guide-for-curious-minds-ebdf403696e3?source=collection_archive---------29-----------------------

想学习算法公平,但不知道从哪里开始?这是一份精选的阅读材料、播客和视频列表。

由法希姆·哈桑和海伦·格扎亨合著

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

照片由 Unsplash 上拍摄

众所周知,人类容易犯错,容易受到偏见的影响,这些偏见会影响算法以歧视的方式表现也不是什么秘密。然而,很难了解这些偏见在我们日常生活中使用的技术中有多普遍。在当今技术驱动的世界,我们需要批判性地思考人工智能对社会的影响,以及它如何与性别、阶级和种族相交。

说到种族——想象一下由于算法中的种族偏见而被错误逮捕。这正是发生在罗伯特·朱利安·博查克·威廉姆斯身上的事情——他是密歇根州的一名非裔美国人,在妻子和年幼的孩子面前被从家中逮捕。他没有犯任何罪,但警方使用的面部识别软件怀疑他在商店行窃。他被错误关押的经历是执法部门手中有缺陷的技术如何放大对黑人社区的歧视的缩影。

面部识别技术的偏见现在已经成为媒体的趋势。最近,许多科技公司(包括亚马逊、IBM、微软等巨头。)发布公告停止面部识别服务或产品的设计和开发,并停止向州和地方警察部门和执法机构销售。一些研究人员指出了这些技术的局限性和不准确性,并对这些技术如何能够延续歧视和种族貌相表示关切。小罗伯特的案例清楚地表明,虽然科技巨头的这些决定可以被认为是朝着正确方向迈出的一小步,但这些显然不会解决科学历史上根深蒂固的种族主义问题。

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

白居松的拼贴插图(经许可使用)

当我们意识到应用有偏见的人工智能技术的危险后果时,我们也意识到我们需要忘记我们都被教导的种族主义。这就提出了一个问题— 我们如何确保我们创造的技术也能忘记它?

要回答这个问题,我们需要了解技术是如何强化压迫和延续种族偏见的。

关于这个话题的一本很好的入门书是《压迫的算法》一书**,作者是加州大学洛杉矶分校信息研究副教授萨菲娅·乌莫哈·诺布尔(1)。萨菲亚用通俗易懂的语言解释了自动化决策背后的数学基础,以及人类偏见是如何嵌入到“大数据”、“搜索引擎”和“算法”等关键概念中的。通过使用广泛的例子,她表明,即使算法决策似乎是一个公平和客观的过程,但在现实中,它反映了人类的偏见和种族偏见。这本书鼓励读者关注他们用来查找信息的搜索引擎和其他信息门户,并提出关键问题*“这是正确的信息吗?给谁的?”***

关于同一主题的另一本好书是凯茜·奥尼尔的《数学毁灭的武器》,凯茜·奥尼尔毕业于哈佛大学,是一名数据科学家,因她的博客 mathbabe.org 而闻名。像 Safiya 一样,Cathy 也使用几个案例研究来提高对使用影响政策决策和放大不平等和偏见的算法的社会风险的认识。这些案例基于她自己在华尔街的职业生涯和她广泛的调查研究。例如,在现代工作场所雇用和解雇人员的算法,提供获得信贷的途径等等。作为算法公平的倡导者,她通过讲座和演示分享了她的经验(查看她的 TED 演讲这个短视频动画或她在谷歌的讲座)。

那么,我们能做些什么来解决算法中的这些偏差呢?

首先,我们必须理解这些有偏见的、普遍存在的技术的设计过程,这正是 T2·鲁哈·本杰明所著的《追逐技术:废除新吉姆法典的工具》一书的重点(3)。作为普林斯顿大学非洲裔美国人研究的副教授,Ruha 研究并教授种族、技术和正义之间的关系。她形容自己的工作是“创造一个环境,让他们(学生)可以超越他们可能无意中为智力发展设定的限制。”这一理念也被灌输到她的书籍和演讲中。除了她的学术文章之外,她还不厌其烦地谈论这场战斗需要的集体努力和公民参与。一种快速简单的方法来更好地了解她的工作是在哈佛大学伯克曼克莱恩互联网中心举办的视频演示会,她在会上讨论了更多关于社会的细节:“一系列编码不平等的歧视性设计:通过明确放大种族等级,通过忽视但复制社会分裂,或通过旨在解决种族偏见但最终做了相反的事情。”**

其次,我们可以合作克服这些有缺陷的设计方法。将我们凝聚在一起的共同主线是同理心,这是世界经济论坛 Joy Buolamwini 的口语表演“ 通过计算产生同情:对抗算法偏见 ”的核心。麻省理工学院媒体实验室的计算机科学家 Joy 是算法公平的拥护者。她创建了算法正义联盟(ASJ)——一个由跨学科研究人员组成的组织,致力于设计更具包容性的技术,并减轻人工智能对社会的有害影响。在乔治城法学院隐私技术中心的合作下,ASJ 开发了安全脸承诺,帮助组织公开承诺算法的公平性。

如果你对流媒体更感兴趣,你可以看看 Joy Buolamwini 的 ted 演讲“我如何对抗算法中的偏见”。有几个播客值得偷听;比如— 与米兰达·莫布雷如何设计一个道德算法与德里克·莱本 以及牛津大学关于 AI 伦理与法律规制的讨论

现在,如果你已经在这个列表上走了这么远,并渴望了解更多,请查看以下内容-

**亲爱的算法偏见,在谷歌与洛根·布朗宁的讨论(没错!她是来自网飞的亲爱的白人 !)Avriel Epps-Darling (哈佛大学博士生,研究音乐、科技、有色人种青年及其性别身份之间的交集)。

●一个相关的谈话是“算法能减少不平等吗?重新确定 Abebe 。Rediet 是加州大学伯克利分校的计算机科学研究员和助理教授。她还在 2019 年组织了关于 AI for Social Good 的研讨会,并与 Timnit Gebru 共同创立了 Black in AI 。谷歌的计算机科学家蒂姆尼特是算法偏差领域的另一个鼓舞人心的人物。

●另一位面部识别技术的激烈批评者是黛博拉·拉杰,她是多伦多大学的工程系学生,目前在人工智能研究所担任技术研究员。要快速阅读,请查阅《纽约时报》报道她学术工作的文章。

●敬请关注纪录片“编码偏差”。这部电影受到乔伊·波伦维尼作品的启发,探索了两个关键问题:“人工智能在管理我们的自由方面日益增长的作用会产生什么影响?那些因为种族、肤色和性别而被锁定的人会有什么后果?”对于幕后故事,你也可以和电影制作人 Shalini Kantayya* 以及上面提到的其他有影响力的研究人员——萨菲娅·诺布尔、黛博拉·拉吉和乔伊·波伦维尼(Joy Buolamwini)一起观看 Q & A。***

呼吁采取集体行动

阅读这些主题可以帮助我们更好地了解我们的世界——一个正在被技术的快速创新所塑造的世界。这些问题影响着我们的整个社会,所以我们需要在学术圈之外,在我们的朋友和家人之间进行讨论(让我们为餐桌上的谈话增添趣味,好吗?).如果是对我们来说,我们人类需要处于设计过程的中心——就这么简单。为了让这样的参与式设计成为现实,让我们更加关注新技术和现有技术的设计。每当我们看到媒体大肆宣传技术拯救世界,我们就来谈谈它是如何设计的。为了谁?做什么?当我们交谈时,让我们把自己的生活经历与我们正在读的书、正在听的播客和正在看的视频联系起来(或者希望狂看!).**

作者

法希姆·哈桑和海伦·格扎亨是加拿大阿尔伯塔大学的 BIPOC 学生。法希姆是公共卫生专业的博士生,对机器学习感兴趣。他也是阿尔伯塔省健康服务的顾问委员会成员。海伦正在学习计算机科学;她还是一个名为 Ada’s Team 的学生团体的主席,该团体致力于促进 STEM 的多样性,特别关注阿尔伯塔大学的技术。

放弃

作者对自己的观点负责。观点不反映雇主或大学的观点。

确认

感谢 JuSong Baek 的插图和 Susie Moloney 深思熟虑的评论和反馈。我们也感谢加拿大阿尔伯塔大学黑人研究生协会成员和 Ada 团队的鼓励。

参考文献

①贵族苏。压迫的算法:搜索引擎如何强化种族主义?纽约:纽约大学出版社;2018.

(2)奥尼尔 c .数学毁灭的武器:大数据如何增加不平等并威胁民主。第一版。纽约:皇冠;2016.

(3) Benjamin R.《技术之后的竞赛:新吉姆法典的废奴主义工具》。英国剑桥;马萨诸塞州梅德福德:政治出版社;2019.

解决约翰·史密斯问题

原文:https://towardsdatascience.com/addressingthejohnsmithproblem-1533da4f7db8?source=collection_archive---------39-----------------------

使用模糊逻辑识别不匹配的副本

特别感谢凯拉什·阿瓦提

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

图片由作者重现,灵感来自自由词典

1.介绍

许多数据库都有重复的数据。尤其是在需要手动输入数据的情况下。为了清理数据和解决不必要的重复,有必要识别和纠正杂乱的数据。然而,许多重复是不匹配的;这意味着可能存在包含例如拼写错误的重复数据。使用SQL数据库语言完美地识别这些重复项是具有挑战性的,因为这依赖于精确的匹配(由于关系数据库理论的原则)。因此,有必要寻找其他方法来识别不匹配的副本,这就是模糊匹配能够被使用的地方。

模糊匹配摆脱了编辑距离的概念,实质上是将一个字符串转换成另一个所需的最小操作数。最常用的编辑距离度量之一是 Levenshtein distance ,它本质上是,“将一个单词变为另一个单词所需的单个字符编辑(插入、删除或替换)的最小数量。”。其他度量包括汉明距离Jaccard 距离Jaro-Winkler 距离、最长公共子串距离余弦距离。出于本文的目的,使用光学字符串对准距离 (OSA)(它是 Damerau-Levenshtein 距离的变体)。

为了说明 OSA,给出下面的例子:

bear -> bear    = 0 steps (0 characters changed)
bear -> beat    = 1 step  (1 characters changed)
bear -> meat    = 2 steps (3 characters changed)
bear -> tearing = 4 steps (1 character changed, 3 characters added)
bear -> ear     = 1 step  (1 character removed)

正如所见,将一个字符串转换为另一个字符串所需的更改次数就是所采取的步骤数。该逻辑将用于匹配给定数据库中的记录。

2.建立

2.1.加载包

第一步是加载必要的包。

# Load required packages
library(tidyverse)  #Various tools
library(readxl)     #Read in Excel's
library(readr)      #Read in data
library(magrittr)   #Great piping tools
library(kableExtra) #Pretty tables
library(stringdist) #For Edit Distance algorithms
library(DBI)        #Testing SQL
library(RSQLite)    #Testing SQL
library(tictoc)     #Check code run-time

2.2.加载数据

下一步是加载数据。JohnSmiths数据是“虚拟数据”,用于说明模糊匹配的例子。原始数据可在八 2Late 上找到。

# Load files from Excel
dat_JohnSmiths <- find_rstudio_root_file() %>% 
   paste0("/Data/", "many_john_smiths.xlsx") %>% 
   read_excel() %>% 
   data.frame()

2.3.检查数据

加载完电子表格后,JohnSmiths数据如下所示:

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

查看数据帧后,详细信息如下所示:

>  Name: dat_JohnSmiths
>  Type: data.frame
>  Dims: 10 x 8
>  Size: 4.9 Kb
>  Field Counts:
>    field           distinct count distinct%
>  1 CustomerID      10       10    1.0      
>  2 FirstName        4       10    0.4      
>  3 LastName         2       10    0.2      
>  4 Title            4       10    0.4      
>  5 AddressLine1    10       10    1.0      
>  6 AddressSuburb    5       10    0.5      
>  7 AddressPostcode  6       10    0.6      
>  8 Phone           10       10    1.0

3.使用 SQL

当使用SQL检查数据时,使用了以下脚本。注意到它加入了FirstNameLastNameAddressPostcodeCustomerID字段。查询结果返回所有数据。这意味着它无法确定任何重复。因此,SQL 不能用于此目的。

/* Check for duplicates between the two tables. */
SELECT *
FROM JohnSmiths t1
WHERE EXISTS (
    SELECT 'x'
    FROM JohnSmiths t2
    WHERE t1.FirstName=t2.FirstName
        AND t1.LastName=t2.LastName
        AND t1.AddressPostcode=t2.AddressPostcode
        AND t1.CustomerID=t2.CustomerID
    )

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

4.使用 R

4.1.概观

要通过模糊匹配查找重复项,请遵循以下步骤:

  1. 将中的关键字段连接成每行的单个文本字符串
  2. 计算每条记录的字符串长度。
  3. 创建字符串距离矩阵(使用[stringdist](https://www.rdocumentation.org/packages/stringdist/versions/0.9.5.5)包中的[stringdistmatrix()](https://www.rdocumentation.org/packages/stringdist/versions/0.9.5.5/topics/stringdist)函数)。
  4. 将字符串距离矩阵归一化为 0 到 1 之间的值:
    4.1。创建一个最大长度的成对向量。
    4.2。将距离长度除以较长字符串的长度。
  5. 创建相似性矩阵
  6. 识别高于相似性阈值的每对记录。
  7. 显示结果记录。

4.2 演练

第一步是将字符串连接在一起。这是使用paste()功能完成的。产生的向量如下所示(为了方便起见,每个元素都放在一个新行上)。

# Create concatenated vector
vec_Strings <- dat_JohnSmiths %>% 
    mutate(strings=paste0(FirstName
                         ,LastName
                         ,AddressLine1
                         ,AddressPostcode
                         ,AddressSuburb
                         ,Phone
                         )) %>% 
    select(strings) %>% 
    pull()# Review
vec_Strings %>% cat(sep="\n")>  JohnSmith12 Acadia Rd9671Burnton1234 5678
>  JhonSmith12 Arcadia Road967Bernton1233 5678
>  JSmith12 Acadia Ave867`1Burnton1233 567
>  JohnSmith13 Kynaston Rd9671Burnton34561234
>  JohnSmithNA9671Burnton34561233
>  JohnS12 Kinaston Road9677Bernton34561223
>  JonSmith13 Kinaston Rd9761Barnston36451223
>  JohnSmith12 Aracadia St9761Brenton12345666
>  JohnSmith13 Acacia Ave8961Burnside67231231
>  JohnSmith12 Kingsford Rd9671Burnton89624328

接下来,必须使用[stringr](https://www.rdocumentation.org/packages/stringr/versions/1.4.0)包中的[str_length()](https://www.rdocumentation.org/packages/stringr/versions/1.4.0/topics/str_length)函数计算每条记录的字符串长度。

# Create vector of lengths
vec_Lengths <- str_length(vec_Strings)# Review the vector
vec_Lengths %>% print()>   [1] 41 43 39 42 30 40 42 42 42 43

接下来,使用[stringdist](https://www.rdocumentation.org/packages/stringdist/versions/0.9.5.5)包中的[stringdistmatrix()](https://www.rdocumentation.org/packages/stringdist/versions/0.9.5.5/topics/stringdist)函数计算字符串距离矩阵。注意通过使用超参数method="osa"使用最佳字符串对齐算法。这个函数将值保存在一个一维数组中,但是在打印时,它会显示距离矩阵的下三角。

# Create distance matrix
vec_Distances <- stringdistmatrix(vec_Strings, method=”osa”)# Review
vec_Distances %>% print()>      1  2  3  4  5  6  7  8  9
>  2   7                        
>  3  10 13                     
>  4  15 21 24                  
>  5  18 25 25 15               
>  6  22 21 28 12 17            
>  7  20 23 26  9 21 14         
>  8  10 13 17 20 22 25 22      
>  9  19 22 19 21 23 29 23 22   
>  10 17 22 25 13 22 19 16 22 24

接下来,需要计算每对记录的最大长度。这可以通过[utils](https://www.rdocumentation.org/packages/utils/versions/3.6.2)包中的[combn()](https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/combn)函数来实现。该函数采用以下参数:

  1. 要迭代的长度向量。
  2. 要选择的元素数量的数值。值2表示它将匹配记录对。
  3. 将应用于每对的函数。在这种情况下,选择max()功能。
  4. 一个逻辑值,表示是将结果简化为一个向量还是返回一个列表。

产生的向量如下所示。

# Create Pairwise Vector
vec_PairwiseMax <- combn(vec_Lengths, 2, FUN=max, simplify=TRUE)# Review
vec_PairwiseMax>   [1] 43 41 42 41 41 42 42 42 43 43 43 43 43 43 43 43 43 42 39 40 42 42 42
>  [24] 43 42 42 42 42 42 43 40 42 42 42 43 42 42 42 43 42 42 43 42 43 43

接下来,计算归一化的距离矩阵。

# Calculate normalised values
vec_NormalisedDistances <- vec_Distances/vec_PairwiseMax# Review
vec_NormalisedDistances>          1      2      3      4      5      6      7      8      9
>  2  0.1628                                                        
>  3  0.2439 0.3023                                                 
>  4  0.3571 0.4884 0.5714                                          
>  5  0.4390 0.5814 0.6410 0.3571                                   
>  6  0.5366 0.4884 0.7000 0.2857 0.4250                            
>  7  0.4762 0.5349 0.6190 0.2143 0.5000 0.3333                     
>  8  0.2381 0.3023 0.4048 0.4762 0.5238 0.5952 0.5238              
>  9  0.4524 0.5116 0.4524 0.5000 0.5476 0.6905 0.5476 0.5238       
>  10 0.3953 0.5116 0.5814 0.3023 0.5116 0.4419 0.3721 0.5116 0.5581

接下来,归一化的距离被强制到一个矩阵中。创建后,确保不重复计算两次是很重要的。要做到这一点,右上角的三角形和对角线都是零的。

# Create Similarity Matrix
mat_SimilarityScore <- round(1-vec_NormalisedDistances, 2) %>% as.matrix()# Make the upper triangle all zero’s. This is to avoid double-counting duplicates.
mat_SimilarityScore[upper.tri(mat_SimilarityScore)] <- 0# Make the diagonals all zero’s. This is to ensure that the same string does not get matched to itself.
mat_SimilarityScore[diag(mat_SimilarityScore)] <- 0# Review
mat_SimilarityScore>        1    2    3    4    5    6    7    8    9 10
>  1  0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00  0
>  2  0.84 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00  0
>  3  0.76 0.70 0.00 0.00 0.00 0.00 0.00 0.00 0.00  0
>  4  0.64 0.51 0.43 0.00 0.00 0.00 0.00 0.00 0.00  0
>  5  0.56 0.42 0.36 0.64 0.00 0.00 0.00 0.00 0.00  0
>  6  0.46 0.51 0.30 0.71 0.57 0.00 0.00 0.00 0.00  0
>  7  0.52 0.47 0.38 0.79 0.50 0.67 0.00 0.00 0.00  0
>  8  0.76 0.70 0.60 0.52 0.48 0.40 0.48 0.00 0.00  0
>  9  0.55 0.49 0.55 0.50 0.45 0.31 0.45 0.48 0.00  0
>  10 0.60 0.49 0.42 0.70 0.49 0.56 0.63 0.49 0.44  0

作为参考,相似性矩阵的详细信息打印如下。

>  Name: mat_SimilarityScore
>  Type: matrix
>  Dims: 10 x 10
>  Size: 2.6 Kb

接下来,将识别高于给定阈值的值。为了实现这一点,编写了一个自定义函数。

# Add function for identifying scores above a given threshold.
tlargest <- function(matrix, threshold, print=FALSE) {
    #' @title Return Matrix Values Above A Threshold
    #' @description Subset a matrix to return values that are above a specified threshold.
    #' @note Will also print the count of how many records were matched. Necessary due to the ambiguity of using a threshold value.
    #' @param matrix matrix. A matrix, which is the matrix to be sub-set.
    #' @param threshold numeric. A single numeric value, corresponding to the threshold, above which values are to be returned.
    #' @return A matrix containing columns:
    #' — 'row' : A numeric value corresponding to the row index of the returned value.
    #' — 'col' : A numeric value corresponding to the column index of the returned value.
    #' — 'val' : A numeric value which is the similarity score between the 'row' and 'col' values.

    # Validations:
    if (!is.matrix(matrix)) {stop("'matrix' must be a matrix")}
    if (!is.numeric(matrix)) {stop("'matrix' must be numeric")}
    if (!length(threshold)==1) {stop("'threshold' must be atomic")}
    if (!is.numeric(threshold)) {stop("'threshold' must be numeric")}
    if (!between(threshold, 0, 1)) {stop("'threshold' must be between 0 and 1")}

    # Determine the indices to be returned
    sort <- sort(matrix, decreasing=TRUE)
    order <- order(matrix, decreasing=TRUE)
    order <- order[sort>=threshold]

    # Generate the matrix of indices to be returned
    position <- arrayInd(order, dim(matrix), useNames=TRUE)
    position <- set_colnames(position, c("rec1", "rec2"))
    position <- cbind(position, val=matrix[order])

    # Print subset number
    if (print==TRUE) {
        cat("Selected threshold : ", threshold, "\n"
           ,"Matching records   : ", nrow(position), "\n"
           ,"Total records      : ", nrow(matrix), "\n"
           ,"Matching percent   : ", nrow(position)/nrow(matrix)
           ,sep=""
           )
    }

    # Return
    return(position)

}

因此,当应用该函数时,将生成如下所示的矩阵。

# Generate matching records
mat_MatchingRecords <- tlargest(matrix = mat_SimilarityScore
                               ,threshold = 0.7
                               ,print = TRUE
                               )>  Selected threshold : 0.7
>  Matching records   : 8
>  Total records      : 10
>  Matching percent   : 0.8 # Review
mat_MatchingRecords>       rec1 rec2  val
>  [1,]    2    1 0.84
>  [2,]    7    4 0.79
>  [3,]    3    1 0.76
>  [4,]    8    1 0.76
>  [5,]    6    4 0.71
>  [6,]    3    2 0.70
>  [7,]    8    2 0.70
>  [8,]   10    4 0.70

一旦识别出匹配的记录,就需要从原始表中提取它们。为此,再次编写一个自定义函数。它获取原始数据帧和相似性矩阵,然后遍历矩阵,从数据帧中提取相关记录。

find_MatchingRecords <- function(dataframe, sim_matrix, print=FALSE) {
    #' @title Find Mathching Records
    #' @description Use 'sim_matrix' to find matching records from 'dataframe'.
    #' @note The `sim_matrix` contains the similarity matrix, generated from `stringdistmatrix()` and the `nlargest()` (or `tlargest()`) functions.
    #' @param dataframe dataframe. The dataframe from which the matching records will be extracted.
    #' @param sim_matrix matrix. The matrix containing the attributes for finding the matching records.
    #' @param print logical. Whether or not to print the output as a text string.
    #' @return A data.frame containing the score and the records that have been matched. Also, this is printed to the console.

    # Validations
    if (!is.data.frame(dataframe)) {stop("'dataframe' must be a dataframe")}
    if (!is.matrix(sim_matrix)) {stop("'sim_matrix' must be a matrix.")}
    if (!is.double(sim_matrix[[2]])) {stop("'sim_matrix' must be a numeric matrix.")}
    if (c("rec1","rec2") %>% is_in(colnames(sim_matrix)) %>% all() %>% not()) {stop("'sim_matrix' must contain two columns named: 'rec1' and 'rec2'.")}

    # Set output
    str_return <- NULL
    dat_return <- data.frame("Score"=NA_real_
                            ,"Index1"=NA_real_
                            ,"Record1"=NA_character_
                            ,"Index2"=NA_real_
                            ,"Record2"=NA_character_
                            ,stringsAsFactors=FALSE
                            )

    # Determine number of itterations
    iterations <- sim_matrix %>% nrow()

    # Loop through number of itteraions
    for (i in 1:iterations) {

        # Extract score
        sim_score <- sim_matrix %>% 
            extract(i, 3)

        # Extract the first matching index
        rec1_index <- sim_matrix %>%
            extract(i,1)

        # Extract first matching record
        rec1_record <- sim_matrix %>% 
            extract(i,1) %>% 
            extract(dataframe, ., ) %>% 
            as.character() %>% 
            paste(collapse=" ")

        # Extract the second matching index
        rec2_index <- sim_matrix %>% 
            extract(i,2)

        # Extract second matching record
        rec2_record <- sim_matrix %>% 
            extract(i,2) %>% 
            extract(dataframe, ., ) %>% 
            as.character() %>% 
            paste(collapse=" ")

        # Build return
        str_return %<>% paste0("\n") %>% 
            paste0("Score: ", sim_score, "\n") %>% 
            paste0("Record 1: (Index ", rec1_index, ") ", rec1_record, "\n") %>% 
            paste0("Record 2: (Index ", rec2_index, ") ", rec2_record, "\n") 
        dat_return[i,] <- c(sim_score, rec1_index, rec1_record, rec2_index, rec2_record)

    }

    # Print str_return
    if (print==TRUE) {
        cat(str_return)
    }

    # Return dat_return
    return(dat_return)

}

最后,当应用该函数时,数据显示如下。

# Generate data
dat_MatchingRecords <- find_MatchingRecords(dataframe = dat_JohnSmiths
                                           ,sim_matrix = mat_MatchingRecords
                                           ,print = TRUE
                                           )>  Score: 0.84
>  Record 1: (Index 2) 2 Jhon Smith Mr 12 Arcadia Road Bernton 967 1233 5678
>  Record 2: (Index 1) 1 John Smith Mr 12 Acadia Rd Burnton 9671 1234 5678
>  
>  Score: 0.79
>  Record 1: (Index 7) 7 Jon Smith Mr. 13 Kinaston Rd Barnston 9761 36451223
>  Record 2: (Index 4) 4 John Smith Mr 13 Kynaston Rd Burnton 9671 34561234
>  
>  Score: 0.76
>  Record 1: (Index 3) 3 J Smith Mr. 12 Acadia Ave Burnton 867`1 1233 567
>  Record 2: (Index 1) 1 John Smith Mr 12 Acadia Rd Burnton 9671 1234 5678
>  
>  Score: 0.76
>  Record 1: (Index 8) 8 John Smith Dr 12 Aracadia St Brenton 9761 12345666
>  Record 2: (Index 1) 1 John Smith Mr 12 Acadia Rd Burnton 9671 1234 5678
>  
>  Score: 0.71
>  Record 1: (Index 6) 6 John S Dr. 12 Kinaston Road Bernton 9677 34561223
>  Record 2: (Index 4) 4 John Smith Mr 13 Kynaston Rd Burnton 9671 34561234
>  
>  Score: 0.7
>  Record 1: (Index 3) 3 J Smith Mr. 12 Acadia Ave Burnton 867`1 1233 567
>  Record 2: (Index 2) 2 Jhon Smith Mr 12 Arcadia Road Bernton 967 1233 5678
>  
>  Score: 0.7
>  Record 1: (Index 8) 8 John Smith Dr 12 Aracadia St Brenton 9761 12345666
>  Record 2: (Index 2) 2 Jhon Smith Mr 12 Arcadia Road Bernton 967 1233 5678
>  
>  Score: 0.7
>  Record 1: (Index 10) 10 John Smith Dr 12 Kingsford Rd Burnton 9671 89624328
>  Record 2: (Index 4) 4 John Smith Mr 13 Kynaston Rd Burnton 9671 34561234

其数据帧如下所示:

# Review
dat_MatchingRecords %>% 
    kable() %>% 
    kable_styling(bootstrap_options=c("striped", "bordered", "condensed")
                 ,full_width=FALSE
                 ,position="left"
                 ) %>% 
    (function(x){
        x %>% save_kable("Images/JohnSmithsMatching.png")
        x %>% return()
    })

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

如所见,该方法已经以合理的准确度水平识别了这些重复。

4.3.包裹

因此,在识别数据库中的重复项时,使用“模糊匹配”来识别不同记录集之间的相似性是很有用的。

但是,考虑到本例中提供的数据是虚构的,对真实世界的数据执行相同的过程是有用的。

5.真实的例子

使用从网上搜集的商业地址,同样的方法被应用。

5.1.预处理

数据是从 Excel 电子表格AddressData.xlsx中加载的。

# Load Data
dat_Addresses <- find_rstudio_root_file() %>% 
    paste0("/Data/", "AddressData.xlsx") %>% 
    read_excel(col_types=c("text")) %>% 
    data.frame()

前 10 条记录如下所示:

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

数据的详细信息显示如下:

>  Name: dat_Addresses
>  Type: data.frame
>  Dims: 19388 x 8
>  Size: 4.2 Mb
>  Field Counts:
>    field        distinct count distinct%
>  1 COMPANY       6320    19388 0.3259748
>  2 ADDRESS       8646    19388 0.4459459
>  3 CITY          2459    19388 0.1268310
>  4 STATE            8    19388 0.0004126
>  5 ZIP           1264    19388 0.0651950
>  6 ISOCNTRYCODE     1    19388 0.0000000

然后,对地址执行一些预处理操作,以减小数据的大小。

# Mutate data.
# Steps:
# 1\. Remove special characters
# 2\. Remove numeric values (Street numbers, etc.)
# 3\. Remove additional white spaces
# 4\. Capitalise
# 5\. Select distinct.
dat_AddressesClean <- dat_Addresses %>% 
    mutate_all(str_replace_all, "[[:punct:]]", "") %>% 
    mutate_at(c("COMPANY", "ADDRESS", "CITY", "STATE"), str_replace_all, "[0-9]", "") %>% 
    mutate_all(str_squish) %>% 
    mutate_all(str_to_upper) %>% 
    distinct() %>% 
    arrange(ISOCNTRYCODE, STATE, CITY, ADDRESS)# Check result
check_ObjectDetails(dat_AddressesClean) %>% cat()# Check result
check_ObjectDetails(dat_AddressesClean) %>% cat()>  Name: dat_AddressesClean
>  Type: data.frame
>  Dims: 9945 x 6
>  Size: 1.5 Mb
>  Field Counts:
>    field        distinct count distinct%
>  1 COMPANY      6279     9945  0.6313725
>  2 ADDRESS      6267     9945  0.6301659
>  3 CITY         2344     9945  0.2356963
>  4 STATE           8     9945  0.0008044
>  5 ZIP          1264     9945  0.1270990
>  6 ISOCNTRYCODE    1     9945  0.0000000

最后,必须将数据一起粘贴到一个向量中,如下所示。现在数据可以进行模糊匹配了。

# Create vector
vec_Addresses <- dat_AddressesClean %>% 
    unite("vec", sep="") %>% 
    pull()# Review
vec_Addresses %>%
    head(10) %>%
    cat(sep="\n")
>  MELBOURNE FACADES PTY LTDANU ELLERY CRESACTONACT2601AU
>  IC FORMWORK SERVICES PTY LTDCLUNIES RDACTONACT2601AU
>  RICHARD CROOKES CONSTRUCTIONS PTYDALEY RDACTONACT2601AU
>  STOWE AUSTRALIA PTY LIMITEDELLERY CRESACTONACT2600AU
>  MELBOURNE FACADES PTY LTDELLERY CRESACTONACT2601AU
>  CONSTRUCTION CONTROL HOLDINGSSULLIVANS CREEK RDACTONACT2601AU
>  QUATTRO BUILDING SERVICES PTY LTDSULLIVANS CREEK RDACTONACT2601AU
>  IC FORMWORK SERVICES PTY LTDMORNINGTON ST AMANDA STAMAROOACT2914AU
>  RENROW STEEL PTY LTDCOPPER CRESBEARDACT2620AU
>  OPTIMUM BRICK BLOCKLAYINGCOPPER CRESBEARDACT2620AU

5.2 流程

对地址数据的处理已经被组合到单个块中,并被相应地处理。必须列出以下关键信息:

  • 初始输入向量是 9964 个元素长,而距离向量是 49635666 个元素长。
  • 距离向量是 378.7 Mb 大,而相似性矩阵是 758.7 Mb 大。
  • 耗时 128.2 秒。请注意,这取决于处理器的计算能力。
# Start the clock
tic("\n\nTime to Process Data")# Calculate the lengths
vec_AddLengths <- str_length(vec_Addresses)# Calculate the distances
vec_AddDistances <- stringdistmatrix(vec_Addresses, method="osa")# Calculate the max lengths
vec_AddPairwiseMax <- combn(vec_AddLengths, 2, max, simplify=TRUE)# Normalise the distances
vec_AddNormalisedDistances <- vec_AddDistances/vec_AddPairwiseMax# Add object details to the output
str_Output <- c("vec_Addresses", "vec_AddLengths", "vec_AddDistances", "vec_AddPairwiseMax", "vec_AddNormalisedDistances") %>% 
    check_ObjectDetails() %>% 
    paste(sep="\n")# Create the similarity matrix
mat_AddSimilarityScore <- round(1-vec_AddNormalisedDistances, 2) %>% as.matrix()# Add matrix to output
str_Output %<>% paste(check_ObjectDetails(mat_AddSimilarityScore), sep="\n\n")# Tidy the matrix
mat_AddSimilarityScore[upper.tri(mat_AddSimilarityScore)] <- 0
mat_AddSimilarityScore[diag(mat_AddSimilarityScore)] <- 0# Re-add matrix to output
str_Output %<>% paste(check_ObjectDetails(mat_AddSimilarityScore), sep="\n\n")# Print the output
cat(str_Output)# Stop the clock and print the time taken
toc()>  Name: vec_Addresses
>  Type: character
>  Dims: 1 x 9945
>  Size: 1.2 Mb
>  
>  Name: vec_AddLengths
>  Type: integer
>  Dims: 1 x 9945
>  Size: 38.9 Kb
>  
>  Name: vec_AddDistances
>  Type: dist
>  Dims: 1 x 49446540
>  Size: 377.2 Mb
>  
>  Name: vec_AddPairwiseMax
>  Type: array
>  Dims: 1 x 49446540
>  Size: 188.6 Mb
>  
>  Name: vec_AddNormalisedDistances
>  Type: dist
>  Dims: 1 x 49446540
>  Size: 377.2 Mb
>  
>  Name: mat_AddSimilarityScore
>  Type: matrix
>  Dims: 9945 x 9945
>  Size: 755.8 Mb
>  
>  Name: mat_AddSimilarityScore
>  Type: matrix
>  Dims: 9945 x 9945
>  Size: 755.8 Mb
>  
>  Time to Process Data: 258.7 sec elapsed

结果,记录现在可以匹配了。请注意,匹配记录的数量是 2389(占总数的 24%)。

# Find matches
mat_AddMatchingRecords <- tlargest(matrix = mat_AddSimilarityScore
                                  ,threshold = 0.8
                                  ,print = TRUE
                                  )>  Selected threshold : 0.8
>  Matching records   : 2185
>  Total records      : 9945
>  Matching percent   : 0.2197# Find records
dat_AddMatchingRecords <- find_MatchingRecords(dataframe = dat_AddressesClean
                                              ,sim_matrix = mat_AddMatchingRecords
                                              )

一旦识别出这些匹配的记录,就可以将它们返回。为简单起见,每个相似性得分的前 10 个匹配项已在下面的块中返回。

# View 0.99
dat_AddMatchingRecords %>% 
    filter(Score==0.99) %>% 
    head(10) %>% 
    print_MatchingRecords() %>% 
    cat()
>  Score: 0.99
>  Record 1: (Index 685) AUTOMATIC FIRE PROTECTION DESIGN THE NORTHERN RD BERKSHIRE PARK NSW 2765 AU
>  Record 2: (Index 684) AUTOMATIC FIRE PROTECTION DESIGN THE NORTHERN RD BERKSHIRE PARK NSW 2756 AU
>  
>  Score: 0.99
>  Record 1: (Index 1062) EJ CONSTRUCTIONS NSW PTY LIMITED ROBERTSON RD CENTENNTIAL PARK NSW 2021 AU
>  Record 2: (Index 1061) EJ CONSTRUCTIONS NSW PTY LIMITED ROBERTSON RD CENTENNIAL PARK NSW 2021 AU
>  
>  Score: 0.99
>  Record 1: (Index 2050) CPB DRAGADOS SAMSUNG JOINT VENTURE A COMMERCIAL RD KINGSGROVE NSW 2208 AU
>  Record 2: (Index 2049) CPB DRAGADOS SAMSUNG JOINT VENTURE A COMMERCIAL RD KINGSFROVE NSW 2208 AU
>  
>  Score: 0.99
>  Record 1: (Index 4593) CULLEN STEEL FABRICATIONS PTY LTD GATE WHARF HICKSON RD WALSH BAY NSW 2060 AU
>  Record 2: (Index 4592) CULLEN STEEL FABRICATIONS PTY LTD GATE WHARF HICKSON RD WALSH BAY NSW 2065 AU
>  
>  Score: 0.99
>  Record 1: (Index 5677) BM ALLIANCE COAL OPERATIONS PL CY HAY POINT OPERATIONS HAY POINT QLD 4740 AU
>  Record 2: (Index 5676) BM ALLIANCE COAL OPERATIONS PL CY HAY POINT OPERATIONS HAY POINT QLD 4744 AU

当选择threshold=0.99时,算法几乎完全匹配,记录之间只有单个字符的差异。

# View 0.98
dat_AddMatchingRecords %>% 
    filter(Score==0.98) %>% 
    head(10) %>% 
    print_MatchingRecords() %>% 
    cat()
>  Score: 0.98
>  Record 1: (Index 25) KENNARDS HIRE PTY LIMITED OATLEY CT BELCONNEN ACT 2617 AU
>  Record 2: (Index 24) KENNARDS HIRE PTY LIMITED OATLEY CT BELCONNEN ACT 2616 AU
>  
>  Score: 0.98
>  Record 1: (Index 152) ABS FACADE PTY LTD SHEPPARD ST HUME ACT 2620 AU
>  Record 2: (Index 149) ABS FACADE PTY LTD SHEPARD ST HUME ACT 2620 AU
>  
>  Score: 0.98
>  Record 1: (Index 229) CRYSTAL POOLS PTY LTD DAVE MCINNES RD STROMLO ACT 2611 AU
>  Record 2: (Index 228) CRYSTAL POOLS PTY LTD DAVE MCINNES RD STOMLO ACT 2611 AU
>  
>  Score: 0.98
>  Record 1: (Index 410) RICHARD CROOKES CONSTRUCTIONS PTY PRINCESS HWY ARNCLIFFE NSW 2205 AU
>  Record 2: (Index 403) RICHARD CROOKES CONSTRUCTIONS PTY PRINCES HWY ARNCLIFFE NSW 2205 AU
>  
>  Score: 0.98
>  Record 1: (Index 875) ODK CONSTRUCTION PTY LTD PARRAMATTA RD BURWOOD NSW 2134 AU
>  Record 2: (Index 478) ODK CONSTRUCTION PTY LTD PARRAMATTA RD B URWOOD NSW 2134 AU
>  
>  Score: 0.98
>  Record 1: (Index 574) EODO PTY LTD HAVANNAH ST BATHURST NSW 2795 AU
>  Record 2: (Index 570) EODO PTY LTD HAVANNAH ST BATHRUST NSW 2795 AU
>  
>  Score: 0.98
>  Record 1: (Index 749) LIN BETTY BUILDING GROUP PTY LTD A OXFORD ST BONDI JUNCTION NSW 2026 AU
>  Record 2: (Index 748) LIN BETTY BUILDING GROUP PTY LTD A OXFORD ST BONDI JUNCTION NSW 2022 AU
>  
>  Score: 0.98
>  Record 1: (Index 927) LAING O ROURKE AUSTRALIA CARDIGAL LN CAMPERDOWN NSW 2050 AU
>  Record 2: (Index 926) LAING OROURKE AUSTRALIA CARDIGAL LN CAMPERDOWN NSW 2050 AU
>  
>  Score: 0.98
>  Record 1: (Index 1055) CJ SJ O KEEFFE BUILDING PTY LTD LOT NELSON ROAD CATTAI NSW 2756 AU
>  Record 2: (Index 1054) CJ SJ OKEEFFE BUILDING PTY LTD LOT NELSON ROAD CATTAI NSW 2756 AU
>  
>  Score: 0.98
>  Record 1: (Index 1083) METRO CHATSWOOD JHCPBG JV MOWBRAY RD CHATSWOOD NSW 2067 AU
>  Record 2: (Index 1081) METRO CHATSWOOD JHCPBG JV MOWBRAY RD CHATSWOOD NSW 2057 AU

当选择threshold=0.98时,算法也几乎完全匹配,记录之间也只有单个字符的差异。

# View 0.8
dat_AddMatchingRecords %>% 
    filter(Score==0.8) %>% 
    head(10) %>% 
    print_MatchingRecords() %>% 
    cat()
>  Score: 0.8
>  Record 1: (Index 67) IC FORMWORK SERVICES PTY LTD CHALLIS ST DICKSON ACT 2602 AU
>  Record 2: (Index 2) IC FORMWORK SERVICES PTY LTD CLUNIES RD ACTON ACT 2601 AU
>  
>  Score: 0.8
>  Record 1: (Index 43) IC FORMWORK SERVICES PTY LTD CNR OF HOBART PL LONDON CCT CANBERRA ACT 2601 AU
>  Record 2: (Index 36) IC FORMWORK SERVICES PTY LTD CNR CONSTITUTION AVE AND LONDON CCT CANBERRA ACT 2601 AU
>  
>  Score: 0.8
>  Record 1: (Index 141) TS ANDREW TAYLOR SAWMILL CCT HUME ACT 2620 AU
>  Record 2: (Index 139) TS ALEX GARNER SAWMILL CCT HUME ACT 2620 AU
>  
>  Score: 0.8
>  Record 1: (Index 187) ACT INTERIORS HUDDART CT MITCHELL ACT 2911 AU
>  Record 2: (Index 175) ACT INTERIORS BROOKS ST MITCHELL ACT 2911 AU
>  
>  Score: 0.8
>  Record 1: (Index 292) TS DHAWAL NANDA BOURKE RD ALEXANDRIA NSW 2015 AU
>  Record 2: (Index 270) TS GEORGE NAJJAR BOURKE RD ALEXANDRIA NSW 2015 AU
>  
>  Score: 0.8
>  Record 1: (Index 295) SCHAI DARREN BOURKE RD ALEXANDRIA NSW 2015 AU
>  Record 2: (Index 278) SMITH STEVEN BOURKE RD ALEXANDRIA NSW 2015 AU
>  
>  Score: 0.8
>  Record 1: (Index 302) ABS FACADE PTY LTD BOURKE RD ALEXANDRIA NSW 2015 AU
>  Record 2: (Index 281) DELTA PTY LTD BOURKE RD ALEXANDRIA NSW 2015 AU
>  
>  Score: 0.8
>  Record 1: (Index 311) CPB CONTRACTORS PTY LTD BOURKE RD ALEXANDRIA NSW 2015 AU
>  Record 2: (Index 297) FLEXEM CONSTRUCTION PTY LTD BOURKE RD ALEXANDRIA NSW 2015 AU
>  
>  Score: 0.8
>  Record 1: (Index 300) CHAN PETER BOURKE RD ALEXANDRIA NSW 2015 AU
>  Record 2: (Index 299) LOCANO PAULO BOURKE RD ALEXANDRIA NSW 2015 AU
>  
>  Score: 0.8
>  Record 1: (Index 307) PETER CHAN BOURKE RD ALEXANDRIA NSW 2015 AU
>  Record 2: (Index 305) PAULO LOCANO BOURKE RD ALEXANDRIA NSW 2015 AU

当选择threshold>0.9时,算法也几乎完全匹配,记录之间也只有单个字符的差异。然而,当选择threshold=0.8时,算法产生了错误匹配。例如:

  • 记录4336实际上可能是匹配的副本,因为它们都是LONDON CCT上的IC FORMWORK SERVICES
  • 记录141139匹配了同一郊区同一街道上的不同商家。这是一个错误的匹配。
  • 记录187175匹配了同一郊区不同街道上的相同企业。这是一个错误的匹配。

因此,建议在使用小于0.9的阈值时要谨慎。

6.结论

总之,模糊匹配能够以合理的准确度成功地识别重复项。当将具有单个字符差异的字符串匹配在一起时,这些字符串会得到近乎完美的匹配分数(>0.99)。但是当阈值设置为~0.8时,那么逻辑就开始匹配同一郊区同一街道的不同商家,或者同一郊区不同街道的同一商家等等。这对于实施来说是一个风险,因此必须仔细选择阈值。

此外,由于在处理期间创建了相当大的对象,适当的数据分段是适当的,以避免引起计算问题。

还要注意,数据输入验证总是比回顾性数据清理要好。在地址数据由外部方提供的情况下(如 EDI 连接),应实施此解决方案。如果数据被识别为>0.99的置信区间,那么自动修改数据是合理的;但是,如果是~0.8,那么最好将数据标记出来供员工查看。

7.参考

Awati 2019 年,“解决约翰·史密斯问题——通过 R 中的模糊匹配消除重复数据”,<https://eight 2 late . WordPress . com/2019/10/09/cracking-the-John-Smith-Problem-de duplication-data-via-fuzzy-matching-in-R/>。

维基百科 2019,‘余弦相似度’,【https://en.wikipedia.org/wiki/Cosine_similarity><

维基百科 2019,‘编辑距离’,<https://en.wikipedia.org/wiki/Edit_distance>。

维基百科 2019,‘海明距离’,<https://en.wikipedia.org/wiki/Hamming_distance>。

维基百科 2019,‘雅各布索引’,<https://en.wikipedia.org/wiki/Jaccard_index>。

维基百科 2019,“贾罗-温克勒距离”,<https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance>。

维基百科 2019,‘莱文斯坦距离’,<https://en.wikipedia.org/wiki/Levenshtein_distance>。

维基百科 2019,‘最长公共子串问题’,<https://en . Wikipedia . org/wiki/Longest _ common _ substring _ problem>。

维基百科 2019,‘最佳字符串对齐距离’,<https://en . Wikipedia . org/wiki/damer au % E2 % 80% 93 levenshtein _ distance # Optimal _ string _ alignment _ distance>。

8.附言

鸣谢:本报告是在他人的帮助下完成的。致谢发送至:

  1. Kailash Awati 因为我使用了他的原始文章(解决 John Smith 问题)作为这篇文章的基础。

出版物:该报告也在以下网站发布:

  1. RPubs:RPubs/chrimaho/addressingthehohnsmithproblem
  2. GitHub:GitHub/chrimaho/addressingthehohnsmithproblem
  3. 中:中/chrimaho/addressingtheohnsmithproject

更改日志:本出版物于以下日期修改:

  1. 2020 年 7 月 4 日:原始出版日期。

作为大学数据科学家的兼职教师

原文:https://towardsdatascience.com/adjunct-teaching-as-a-data-scientist-for-a-university-80fd1891a0c7?source=collection_archive---------28-----------------------

对于数据科学家来说,教授大学课程可能是一项有益的兼职工作。

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

我在家乡的一所大学教深度学习课程。这份教学工作是我作为一家大型保险公司数据科学副总裁的主要工作之外的工作。大学的兼职讲师通常被称为兼职讲师。很多人问我关于我的兼职讲师职位的问题,所以我决定写一篇关于我为什么以及如何成为兼职讲师的文章。

每当你阅读一篇包含职业建议和反思的文章时,你必须始终考虑作者的情况与你的方向有多接近。这种考虑揭示了材料的哪些部分是适用的,哪些部分你应该完全忽略。人们选择加入大学的兼职教师队伍有很多原因。对我来说,教书完全是一项兼职工作。我并不寻求全职进入学术界,成为一名教授或讲师。相反,我成为了一名兼职教授,以提升我作为数据科学思想领袖的品牌,为招聘/联网提供可能性,也为我的沟通发展提供机会。还有其他附带的好处。我在从笔记本电脑到电影票的各种产品上都有教育折扣。我可以进入电子和实体的大学图书馆系统。电子图书馆让我能够访问出版商不开放的付费学术论文。作为一名数据科学家,对这类文档的访问已被无数次证明是有价值的。

成为一名助理需要什么样的资格

你有资格成为兼职讲师吗?成为兼职讲师所需的证书和经验因机构而异。在我工作过的三所不同的学校,我看到了各种各样的要求。最有可能的是,要进入任何级别的学术界,都需要某种程度的学位。在我本科学习的最后一部分,一所社区大学找到我,让我教一门 Java 课程。尽管我已经是一名软件工程师,但和他们交谈时我还是有点紧张,因为还有几个月我就要获得学士学位了。进一步说,当时我没有教学经验。尽管有这些保留意见,我最终还是在那所学校兼职教学了将近七年。学校认为我的用户组演示是教学经验,并重视我的行业经验。

社区大学可能会接受只有学士学位的候选人。大多数大学都会要求最低的硕士学位,至少以我的经验来看是这样的。获得硕士学位后,我申请成为一所大学的兼职教授。我喜欢为“大学”教书的想法,而这所学校恰好离我家很近。我教过几年技术编程课程。我离开的主要原因是结婚和看到我的优先权和空闲时间的转变。我一直喜欢教书,以后还会回来。

博士学位无疑是大学阶段的宝贵资格;然而,并不是所有的副教授都有博士学位。我有一个计算机科学的博士学位,来自我认为不错的学校,但它不是一流的大学。作为补充,我想说你的资格是你的教育、工作经验、教学经验、出版物和其他考虑因素的结合。你的 GitHub 活动、会议演示、YouTube 视频、MeetUp 体验等活动,以及 Medium 等博客文章也很重要。这些因素中没有一个能让你得到这份工作。这些的完整组合成为你作为数据科学家的品牌。没有人是这些方面的专家。然而,希望你的优势可以弥补你经验不足的地方。

为什么要成为兼职讲师

我选择成为兼职教员有很多原因。当你阅读关于数据科学职业建议的文章时,你会发现优秀的数据科学家应该从事许多活动。同样的建议也适用于有抱负的数据科学家。作为一名兼职讲师,我的工作已经成为一项核心活动,可以带来一些有价值的额外好处。我必须跟上深度学习的步伐,这样我的课程材料才是最新的、相关的。我把所有的课程资料都保存在 GitHub 上的 Jupyter 笔记本里。我的职业库现在有近 2K GitHub 粉丝和 1.3K 星星。我以混合形式讲授课程,也就是说,我通过课堂会议、预先录制的视频和缩放会议的组合来提供指导。我预先录制的视频在 YouTube 上变得很受欢迎,导致一个频道目前拥有 24K 订户。就个人而言,如果我将这些项目作为独立的不相关的活动来追求,我将没有时间来完成它们。我并没有打算成为 YouTuber 或社交媒体的影响者。

为一门课程会给你的生活增加的工作量做好准备。在学校每周都有时间在课堂上讲课。准备课程材料和作业需要时间。批改作业和回答学生的问题也需要相当长的时间。然而,对我来说,这些都有助于我作为一名数据科学家的价值。向学生解释复杂的技术有助于我更好地理解技术并磨练我的沟通技巧。准备课程材料迫使我学习任何高级数据科学家都应该学习的最新技术。在学生继续或开始职业生涯时,与学生见面提供了有价值的社交活动。我经常从我的学生中雇佣实习生,偶尔也会雇佣他们为我的雇主做全职工作。

金钱是一种利益。许多金融作家谈到了“旁门左道”的价值。兼职教师的工作确实产生了第二收入来源。学校会支付给你的金额因你的证书、学校和地理位置而异。像 Glassdoor 这样的网站会给你一个合理准确的薪水预估。

如何成为兼职讲师

既然我已经解释了你为什么想成为一名兼职讲师,让我们来谈谈如何真正成为一名兼职讲师。如果你没有教学经验,我建议在你选择的领域尝试一两次 MeetUp。第一,注意观察他人,学习新事物。想出一个可能成为你第一堂课的话题。在聚会上演讲成为你最初的教学经验。用这一全新的宝贵演讲体验更新您的 LinkedIn 个人资料。此外,确保你的 LinkedIn 个人资料有一张好照片,并列出相关的工作经历。

当你准备尝试找一份兼职时,选择几所离你近的大学。找到你的目标部门。学院由以院长为首的学校或系组成。无论是直接的还是间接的,在院长的领导下,将会有部门领导或项目主管,他们通常是个人的任务,雇佣兼职讲师。这些是你要接触的人。

希望项目总监在 LinkedIn 上。如果是的话,这是最初联系的好方法。LinkedIn 可以让主管看到你的资历和经验。提出初次联系请求,并提及您对课程有想法,并且有兴趣讨论附加机会。一些学者在 LinkedIn 上一点也不活跃。如果主管在 LinkedIn 上不理你,那就试着发邮件。如果主任在这两方面都忽略了你,那就去下一所学校。

对于你最初的交流,无论是电子邮件还是 LinkedIn 信息(在你联系上之后),总是提出一个你可能想教的课程的想法。在这一点上,这个提议只不过是大学在目录中可能有的描述水平。当然,浏览他们的课程目录,并确保你没有提出一个重复的课程。主任很可能有一个班级,他们正在寻找一个新的兼职讲师。然而,提出一个课程想法表明你是一个思想领袖,可能会激起主任的兴趣。

我已经在我现在的大学工作了三年,我发现辅助教学是一项有益的活动。我发现辅助教学与我的主要职业非常契合。对学生来说,与同行业的人交流是有益的。如果你正在寻找一种方法来提高你作为一名数据科学家的品牌和思想领导力,那么辅助教学可能非常适合你的职业生涯。

针对泊松回归中的过度离散进行调整

原文:https://towardsdatascience.com/adjust-for-overdispersion-in-poisson-regression-4b1f52baa2f1?source=collection_archive---------2-----------------------

广义线性模型

消除泊松模型中显著系数的假阳性检测及其在 r。

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

蒂莫·沃尔茨在 Unsplash 上的照片

T 当我们想要对每单位时间或空间的平均发生次数进行建模时,泊松回归模型自然而然地出现了。比如罕见癌症的发病率,十字路口汽车穿越的次数,或者地震的次数。

泊松分布的一个特征是均值等于方差。然而,过度分散欠分散分别发生在方差大于或小于均值的泊松模型中。实际上,在数据量有限的情况下,过度分散会更频繁地发生。

过度分散问题会影响模型的解释。为了避免对系数的错误估计,有必要解决这个问题。

在这篇文章中,我将讨论一些基本的方法来调整泊松回归模型中的过度分散现象。实现将用 R 代码展示。希望这篇文章有帮助。

假设我们想要使用预测器 xi 的向量来模拟计数响应易*。*我们知道,响应变量 Yi 遵循参数为μi 的泊松分布

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

易服从泊松分布

其中概率函数是

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

泊松 PMF

对数连接函数用于连接预测值 Xi 和泊松参数μi 的线性组合

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

泊松回归模型。

让我们用《T21》一书中介绍的例子建立一个简单的模型。

## R code
library(faraway)
data(gala)
gala = gala[,-2]
pois_mod = glm(Species ~ .,family=poisson,gala)
summary(pois_mod)

这是泊松模型的总结。

Call:
glm(formula = Species ~ ., family = poisson, data = gala)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-8.2752  -4.4966  -0.9443   1.9168  10.1849  

Coefficients:
              Estimate Std. Error z value Pr(>|z|)    
(Intercept)  3.155e+00  5.175e-02  60.963  < 2e-16 ***
Area        -5.799e-04  2.627e-05 -22.074  < 2e-16 ***
Elevation    3.541e-03  8.741e-05  40.507  < 2e-16 ***
Nearest      8.826e-03  1.821e-03   4.846 1.26e-06 ***
Scruz       -5.709e-03  6.256e-04  -9.126  < 2e-16 ***
Adjacent    -6.630e-04  2.933e-05 -22.608  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for poisson family taken to be 1)

    Null deviance: 3510.73  on 29  degrees of freedom
Residual deviance:  716.85  on 24  degrees of freedom
AIC: 889.68

Number of Fisher Scoring iterations: 5

不要被超级显著的系数所迷惑。那些漂亮的 p 值正是过度分散问题的后果。我们可以从视觉上或数量上检查过度分散。

让我们先画出相对于平均值的估计方差。

## R code
plot(log(fitted(pois_mod)),log((gala$Species-fitted(pois_mod))^2),xlab=expression(hat(mu)),ylab=expression((y-hat(mu))^2),pch=20,col="blue")abline(0,1) ## 'varianc = mean' line

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

过度分散诊断

我们可以看到,大多数方差大于平均值,这是过度分散的警告。

定量地,可以使用皮尔逊卡方统计和自由度来估计色散参数 φ

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

离差参数的估计

当φ大于 1 时,为过度离散。为了手动计算参数,我们使用下面的代码。

## R code
dp = sum(residuals(pois_mod,type ="pearson")^2)/pois_mod$df.residual
dp

这给了我们 31.74914,并证实了这个简单的泊松模型有过度分散的问题。

或者,我们可以直接在拟合的模型上应用显著性检验来检查过度分散。

## R code
library(AER)
dispersiontest(pois_mod)

这产生了,

Overdispersion test

data:  pois_mod
z = 3.3759, p-value = 0.0003678
alternative hypothesis: true dispersion is greater than 1
sample estimates:
dispersion 
  25.39503

该过度分散测试报告了模型中过度分散问题的重要性。

我们可以检查过度分散对系数估计的影响程度。

## R code
summary(pois_mod,dispersion = dp)

这产生了,

Call:
glm(formula = Species ~ ., family = poisson, data = gala)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-8.2752  -4.4966  -0.9443   1.9168  10.1849  

Coefficients:
              Estimate Std. Error z value Pr(>|z|)    
(Intercept)  3.1548079  0.2915897  10.819  < 2e-16 ***
Area        -0.0005799  0.0001480  -3.918 8.95e-05 ***
Elevation    0.0035406  0.0004925   7.189 6.53e-13 ***
Nearest      0.0088256  0.0102621   0.860    0.390    
Scruz       -0.0057094  0.0035251  -1.620    0.105    
Adjacent    -0.0006630  0.0001653  -4.012 6.01e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for poisson family taken to be 31.74914)

    Null deviance: 3510.73  on 29  degrees of freedom
Residual deviance:  716.85  on 24  degrees of freedom
AIC: 889.68

Number of Fisher Scoring iterations: 5

现在,大约一半的预测变得无关紧要,这改变了整个模型的解释。

好吧,让我们用下面两种方法来解决这个问题。

允许离差估计

调整过度分散的简单方法与估计模型中的分散参数一样简单。这可以通过 r 中的准族来完成。

qpoi_mod = glm(Species ~ .,family=quasipoisson, gala)
summary(qpoi_mod)

这产生了,

Call:
glm(formula = Species ~ ., family = quasipoisson, data = gala)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-8.2752  -4.4966  -0.9443   1.9168  10.1849  

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  3.1548079  0.2915901  10.819 1.03e-10 ***
Area        -0.0005799  0.0001480  -3.918 0.000649 ***
Elevation    0.0035406  0.0004925   7.189 1.98e-07 ***
Nearest      0.0088256  0.0102622   0.860 0.398292    
Scruz       -0.0057094  0.0035251  -1.620 0.118380    
Adjacent    -0.0006630  0.0001653  -4.012 0.000511 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for quasipoisson family taken to be 31.74921)

    Null deviance: 3510.73  on 29  degrees of freedom
Residual deviance:  716.85  on 24  degrees of freedom
AIC: NA

Number of Fisher Scoring iterations: 5

我们可以看到,色散参数估计为 31.74921,这与我们前面提到的手动计算非常接近。这个过程告诉我们,只有三个预测系数是有意义的。

用负二项式代替泊松

解决模型中过度分散的另一种方法是将我们的分布假设改为负二项式,其中的方差大于均值

让我们在 r 中实现负二项模型。

## R code
library(MASS)
nb_mod = glm.nb(Species ~ .,data = gala)
summary(nb_mod)

这产生了,

Call:
glm.nb(formula = Species ~ ., data = gala, init.theta = 1.674602286, 
    link = log)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-2.1344  -0.8597  -0.1476   0.4576   1.8416  

Coefficients:
              Estimate Std. Error z value Pr(>|z|)    
(Intercept)  2.9065247  0.2510344  11.578  < 2e-16 ***
Area        -0.0006336  0.0002865  -2.211 0.027009 *  
Elevation    0.0038551  0.0006916   5.574 2.49e-08 ***
Nearest      0.0028264  0.0136618   0.207 0.836100    
Scruz       -0.0018976  0.0028096  -0.675 0.499426    
Adjacent    -0.0007605  0.0002278  -3.338 0.000842 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for Negative Binomial(1.6746) family taken to be 1)

    Null deviance: 88.431  on 29  degrees of freedom
Residual deviance: 33.196  on 24  degrees of freedom
AIC: 304.22

Number of Fisher Scoring iterations: 1

              Theta:  1.675 
          Std. Err.:  0.442 

 2 x log-likelihood:  -290.223

它更符合数据,因为偏离度与自由度之比仅略大于 1。

结论

**答:**过度分散会影响泊松模型的解释。

B. 为了避免我们模型中的过度分散问题,我们可以使用一个拟族来估计分散参数。

C. 我们也可以用负二项式代替泊松模型。

参考资料:

https://biometry . github . io/APES/lecture notes/2016-JAGS/over dispersion/over dispersion jags . pdf

远方,Julian J. 用 R 扩展线性模型:广义线性、混合效应和非参数回归模型。CRC 出版社,2016。

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

Peter ScherbatykhUnsplash 上拍摄

仓库:具有真实异常的异常检测数据集

原文:https://towardsdatascience.com/adrepository-anomaly-detection-datasets-with-real-anomalies-2ee218f76292?source=collection_archive---------18-----------------------

持续更新的异常数据集集合

我创建了一个 Github 存储库,以提供一个持续更新的流行真实数据集集合,用于文献中的异常检测。请在下面找到指向存储库的链接。

[## 关松庞/异常检测数据集

在这个库中,我们提供了一个不断更新的用于异常的流行真实世界数据集的集合…

github.com](https://github.com/GuansongPang/anomaly-detection-datasets)

异常检测发展的一个主要障碍是缺乏具有真实异常的真实世界数据集。尽管在 UCI 机器学习库和/或 Libsvm 数据集中有许多相关的公开可用数据集,但我们可能经常需要投入大量时间来使公开可用数据集为我们的异常检测模型做好准备。创建这个存储库就是为了解决这些问题。它将专注于现成的数据集,即不需要任何进一步的数据预处理,并不断用我或其他研究人员预处理的数据集更新它。

现在存储库中可用的数据集来自不同的领域,如信用卡欺诈检测、入侵检测、疾病检测等。这些数据集的基本统计数据可以在下面找到。

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

Pang,g .,Shen,c .,& van den Hengel,A. (2019 年 7 月)使用的数据集。基于偏差网络的深部异常探测。《第 25 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集》(第 353–362 页)。请参阅本文中对这些数据集的详细介绍以及其中的源链接。

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

庞,曹,陈(2016 年 1 月)使用的数据集。复杂分类数据中异常值检测的特征值耦合模型。在 IJCAI 国际人工智能联合会议上。和其他几篇论文。请参阅本文中对这些数据集的详细介绍以及其中的源链接。

带有可访问链接的数据集列表也可在以下调查报告中找到:

[## 用于异常检测的深度学习:综述

异常检测,也称为离群点检测,已经成为各种研究中一个持久而活跃的研究领域

arxiv.org](https://arxiv.org/abs/2007.02500)

高级 AI 快到了,快跑。

原文:https://towardsdatascience.com/advanced-ai-is-almost-here-run-d0d43d483d08?source=collection_archive---------20-----------------------

我们应该在多大程度上拥抱有意识机器的发展?

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

附身摄影Unsplash 上拍照

尽管人工智能已经在全球广泛使用,但它的发展应该得到专业和谨慎的处理,因为我们仍然不知道有意识的机器会对人类产生什么影响。该领域的领先研究人员警告其潜在后果,史蒂芬·霍金教授声称,超级智能机器可能会导致人类的末日。

人工智能是计算机系统的理论和发展,能够执行通常需要人类智能的任务。近年来,由于其快速的发展和广泛的应用,以及公众人物如埃隆·马斯克和比尔·盖茨对该主题的关注,它已经获得了主流媒体的关注。事实证明,这是计算机科学家和哲学家之间争论的话题,其中一些人表示,超级智能人工智能将是我们创造的最后一件东西。

这份报告评估了来自杰出研究人员和学术报告的证据、研究和陈述,并得出结论认为,应该允许开发人工智能,但只能在严格到适度的监督和监管下进行。它致力于讨论研究问题:超级智能人工智能是否对人类构成生存威胁,创造有意识的机器是一个好主意吗,创造有意识的机器是否不道德?

创造有意识的机器对人类来说是个好主意吗?

人工智能的种类—

人工智能可以分解为三个 categories⁴.人工狭义智能(ANI)是一种低水平的智能,ANI 可以执行复杂的任务,但不能理解它为什么要这样做,它不会在有意识的层面上思考,例如 Siri,Alexa。人工通用智能(AGI)是有意识的,它可以在与人类相同的水平上思考,有自我意识,可以理解它是一台机器。AGI 还不存在。最后,人工超级智能(ASI)是比人类更高级的机器智能,它也尚不存在,但它能够解决超出我们理解的问题。

时间框架—

由于 AGI 和阿西还不存在,这是一个猜测的主题,他们是如何迫在眉睫,因此我们需要如何关注。field⁵的一项专家调查发现,受访者的中位数估计,到 2040 年,AGI 将有二分之一的可能性被创造出来,到 2075 年,这一比例将上升至十分之九。他们还预测,不到 30 年后,ASI 也将步其后尘。ASI 对人类来说变成“坏”或“极其坏”的可能性估计为三分之一。

虽然该调查很有见地,并为我们提供了一个工作时间框架,但应谨慎依赖,因为该调查报告并未提及这些专家是谁,以及被归类为专家的标准是什么。

好处和威胁—

据了解,有了意识,自主的决定和意见就形成了。这意味着有意识的机器可能有与其创造者不一致的目标。它们的处理时间比人快数百万倍,很难抵御。来自威斯康星大学麦迪逊分校的一份报告指出,创造一个人工智能可能导致人工智能武装 race⁶.AGI 将允许自主武器系统,它可以很快变得非常复杂,当机器从 AGI 转换到 ASI 时,我们可能会失去对它的控制。以及试图获得该技术的敌对国家。这可以被归类为一种生存威胁,因为人类对一台武装的超级智能机器无能为力。在同一篇论文中,进行了一项调查,48%的受访者同意“社会应该优先考虑将人工智能的潜在风险降至最低”。虽然现在的回应有点过时,观点可能也有所改变,但这反映了一个事实,即人们对开发有意识的机器存在担忧。

仅仅因为有意识的机器对人类来说是一大进步,它带来了威胁,这并不意味着它根本不应该被创造出来。AGI 全球协作和政府法规等解决方案可以到位,以确保其得到负责任的发展。让-马克·里克利博士声称,AGI 的好处将是巨大的,它可以在防止欺诈和发现网络攻击以及国防和 anti-terrorism⁷.等活动中发挥重要作用虽然,里克利的想法很容易引起争议,因为 AGI 也可以帮助网络攻击和恐怖主义。

创造人工意识对机器公平吗?

当建造有意识的机器时,伦理是一件需要考虑的重要事情,因为它本质上是在创造生命。有太多限制的意识就像关在笼子里的动物。此外,无情地强迫一个意识去执行一个又一个的任务会让人想起我们现在回想起来并不愉快的历史事件,例如奴隶制。

为了防止历史重演,需要就对 AGI 能做什么和不能做什么制定指导方针。博斯特罗姆提出了一个被认为是 ethical⁸的总清单,随着伦理不可避免的转变,这个清单可以更新。AI 也应该遵守这个主列表。虽然这是一个很好的建议,但可能被认为是不现实的。Bostrom 只提出了一个解决方案,但没有说明如何实施。假设每个人都会遵守它是不合理的。

最后

“制造一台有意识的机器对人类来说是个好主意吗?”这个问题似乎没有明确的答案,但如果不付诸行动,它还是会继续下去。因此,由于人工意识是如此不朽和改变世界,似乎最好继续创造它,但要有严格的规定来确保它安全和负责任地发展。

AGI 很可能是对人类的生存威胁,赋予机器意识也可能是不道德的,如果不是出于责任感的话。确实有证据表明,AGIs 的发明会给人类带来许多好处,但这并不意味着我们可以忽视威胁,这些威胁可能更重要。

在回答“创造人工意识对机器公平吗?”,就看谁在控制它了。这就是监管如此重要的原因,也是如此大规模的技术进步不能向世界隐瞒的原因。

技术的演变是不可避免的,但这并不意味着人类在这样做的时候不应该是道德的、安全的和前瞻性的,特别是在先进的人工智能的情况下。

www.linkedin.com/in/joe-drury18

参考

[1]塞兰·琼斯博士,2014 年。斯蒂芬·霍金警告人工智能可能会终结人类。英国广播公司新闻,2014 年第 2 版

[2]词典|英语。(2019).人工智能| Lexico 对人工智能的定义。【在线】见:https://www . lexico . com/en/definition/artificial _ intelligence【2019 年 10 月 23 日访问】。

[3]n .博斯特罗姆,2003 年。高级人工智能中的伦理问题。科幻小说与哲学:从时间旅行到超级智慧,第 241 页

[4]特威迪,M. (2017)。3 种类型的人工智能:窄,一般,和超级人工智能。[在线]

[5]米勒,V.C .和 n .博斯特罗姆,2016 年。人工智能的未来发展:专家意见调查。《人工智能的基本问题》(第 555-572 页)。斯普林格,查姆。

[6] Ramamoorthy,a .和 Yampolskiy,r .,2018 年。超越疯狂?人工智能竞赛。国际电联 J,1,第 1-8 页。

[7] Rickli,J.M .,3.2 评估人工智能的风险。

[8]n . Bostrom 和 e . Yudkowsky,2014 年。人工智能的伦理。《剑桥人工智能手册》,316,第 334 页

代码机器人。可在:https://code bots . com/artificial-intelligence/the-3-types-of-ai-is the-third-even-possible【2019 年 11 月 12 日访问】。

https://unsplash.com/photos/YKW0JjP7rlU

使用全息视图在 Python 中实现高级数据可视化

原文:https://towardsdatascience.com/advanced-data-visualization-with-holoviews-e7263ad202e?source=collection_archive---------15-----------------------

HoloViews 将数据和绘图升级为高质量的注释和可视化。本文通过一个简化的群组分析展示了 Python HoloViews 包,该分析使用了关于公司不断发展的客户群的模拟数据。读者应该对 Python 和 pandas 有一个基本到中级的了解。

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

来源:http://blog.holoviews.org/release_1.10.html

全息视图概述

HoloViews 是一个开源包,它用最少的代码和努力产生高质量的交互式可视化。项目页面可以在这里找到这里以及许多例子来理解软件包的功能。相对于遗留选项(Matplotlib、Seaborn 等),我对易用性和性能非常满意。

断代分析

在解决真实世界的数据分析练习时,探索和学习新的包更有吸引力。本文通过对一个简化的 SaaS 企业的队列分析,来确定在客户群中是否有任何新兴趋势。这种分析在许多情况下是有用的,包括准备和验证顶线预测,以及评估产品供应或定价的最近变化的影响。本例中的群组将被定义为在给定月份首次出现的所有用户。这个练习的目的是检查新业务的组合如何随着时间的推移而变化,以及组合的变化对保留意味着什么。在这种情况下,mix 指的是产品等级和订阅持续时间,在其他情况下,它可以是任何可用的分类字段。

数据的描述

分析所依据的数据被模拟以复制在多个公司中观察到的模式。

有两个文件:

  • mrr.csv 包含每个订阅在 2.5 年期间的每月收入。没有左审查。
  • user.csv 包含用户 id、订阅 id、产品等级和订阅期限

一个用户可能有多个订阅,他们可以交换产品等级和订阅期限。为简单起见,保留是基于订阅而不是基于用户来计算的。

到代码

分析从进口开始。显示这一点是为了确保读者已经安装了所有的依赖包。请注意 hvplot 包是建立在 HoloViews 上的,它有一个方便的 API 来绘制熊猫图,这需要从 HoloViews 中单独安装。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
import hvplot.pandas
import holoviews as hv
from holoviews import opts
hv.extension('bokeh')

附注:HoloViews 中日期时间格式的默认行为是打印精确到纳秒的日期/时间。对于初学者来说,控制这种行为的文档通常很难找到,也不完全清楚。这个格式化问题可以通过创建一个 DatetimeTickFormatter 对象并根据需要将其传递给图形来解决。

from bokeh.models.formatters import DatetimeTickFormatter
dtf = DatetimeTickFormatter( days = '%m-%Y', months = '%m-%Y' , years = '%m-%Y')

整形数据

在绘制数据之前,需要将其转换为内容,使图形有意义,并以适当的格式传递给 HoloVeiws。一些基本的熊猫操作被排除在这篇文章之外。完整的文件可以在 github 找到。

创建群组是群组分析的第一步,有许多方法可以进行这种计算。给定输入数据的格式,这里应用以下步骤:

### Calculate start period of the subscription## #1 Create cohorts based on the first observation of a month with a positive mrr value
cohort = (mrr > 0).idxmax( axis = 1).rename('cohort')## #2 Add the cohort date to the index
tenure =  mrr.join( cohort ).set_index( 'cohort', append = True).stack()
tenure = tenure.reset_index( ).rename( columns = {'level_2':'date',## #3 Calculate the number of periods (months) from the cohort date to the mrr date
0:'revenue'} )
tenure['periods'] =  np.round( (tenure['date'] - tenure['cohort']) / np.timedelta64(1, 'M') ,0).astype(int)

#1 中的代码将数据帧转换为二进制变量的值,当一个月有正收入时,这些值为真。然后应用 idxmax 提取最大值第一次出现的列标题,这将是收入为正数的第一个日期。结果是一个与 mrr 具有相同索引的序列,该序列作为 mrr 的#2 中的二级索引被附加,堆叠(该操作通过将列标题(在本例中为每月日期)转换为值字段来解除数据透视)并保存为一个名为“保有权”的新数据帧。步骤#3 计算群组月份和当前月份之间经过的周期数(在本例中为月数)。

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

结果数据帧

在群组分析的 EDA 阶段,这两条曲线通常非常有用,可以对客户保持率有一个总体的了解。两者都表示相对于每个客户活跃的第一个周期,在给定时间点剩余的业务的百分比。一个使用客户作为分子和分母,另一个使用收入。这些计算分为两部分,如下所示:

## #1 Calculate revenue and subs count by cohort by month
gb =  tenure.groupby( [ pd.Grouper( key ='cohort' , freq = 'M') , 'periods'])
rev_cohorts = gb['revenue'].sum().unstack()
count_cohorts = gb['sub_id'].nunique().unstack()## #2 turn them into a percentage relative to the first month
scaled_revenue_cohorts = rev_cohorts.apply( lambda x : x/x[0] ,axis = 1)
scaled_count_cohorts = count_cohorts.apply( lambda x : x/x[0] ,axis = 1)

#1 中的计算为每个有观察值的周期中的每月客户群计算总收入和客户的唯一计数,unstack 命令将周期转换为列标题,这对使用 hvplot 绘图很有用。#2 中的计算利用了新的数据形状,并应用 lambda 函数将每个期间的值(收入或客户数)除以第一个月观察到的值。

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

视觉化

对 HoloViews 的 hvplot 扩展提供了一种非常快速的方式来从 pandas 对象生成交互式可视化,这有助于 EDA。以下代码遵循与 matplotlib 相同的 API 格式,可以快速生成用于探索的线图。

### Quick hvplot of both dataframes
p1 = scaled_revenue_cohorts[scaled_revenue_cohorts>0].T.hvplot( figsize = [11,7], legend=False , title = 'Revenue')
p2 = scaled_count_cohorts[scaled_count_cohorts>0].T.hvplot(figsize = [11,7], legend=False , title = 'Logo Count')### Add the graphs together to display as one output
(p1 + p2).cols(1)

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

有两件事在全息视图中比在绘图包中更容易实现。工具提示允许用户以交互方式浏览数据,并且是自动生成的。将图形添加到单个可视化中的语法比从 matplotlib 调用 axes 对象更容易。

这些图表已经提供了大量信息,有助于指导接下来的分析。首先,请注意,这里混合了不同的订阅长度。最好分别分析不同持续时间选项的保留情况,因为显然一年期订阅与一个月期订阅的情况不同。其次,保留曲线的轮廓正在改变。较短的线是最近的线,因为可用的数据很少。这些有更多的曲率比旧的,而且他们似乎有一个较低的保留百分比。稍后,本文将展示一种更好的方法来演示这种模式。在此之前,我们将探索基础订阅基础的变化。

当新业务组合发生变化时,保留模式通常会开始改变。由于新的营销活动、产品供应、期限选择、地区或人口特征等诸多因素,新业务的组合可能会发生变化。在该数据集中,只有持续时间和订阅层可用作分类特征。评估任何分类特征的组合如何随时间变化的一个好方法是将它们绘制成两个堆叠的条形图,显示总量和相对百分比。

为了生成下一组图表,需要对数据进行整形,按层和持续时间划分群组。

## #1 Create product duration cohorts
gb = tenure.groupby( ['sub_product','sub_duration','cohort', 'subs_id','periods'])## #2 Divide each periods user count (observations with revenue > 0) by the month 0 count
cohorts_scaled = gb['revenue'].sum().unstack().groupby(level=[0,1,2]).apply( lambda x : (x>0).sum()/(x[0]>0).sum())

有了新的群组数据,创建条形图相当容易,但需要几行:

## #1 
mix = cohorts[0].rename('count').reset_index()
mix = mix.set_index(['cohort','sub_product','sub_duration'] )
mix = mix.sort_index()## #2
abs_bars = hv.Bars( mix )
abs_bars.opts( stacked = True, xrotation = 45 , width = 700 , height = 400 , xaxis= None , ylabel = 'Conversions')## #3
hund_bars = hv.Bars( mix/mix.groupby( level =0 ).sum() )
hund_bars.opts( stacked = True, xrotation = 45 , width = 700 , height = 400 , xformatter = dtf, ylabel = 'Relative %')layout = (abs_bars + hund_bars).cols(1)
layout.opts(shared_axes=False)

#1 下的代码创建了一个多索引序列,可以传递给 HoloViews bars 类。Holoviews 需要平面数据,而 hvplot 可以平稳地处理表格数据。的。HoloViews 中的 opts()方法让开发人员可以非常详细地控制可视化的几乎每个部分。

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

条形图显示,产品层级没有随着时间的推移而发生任何明显的变化。然而,持续重复这一步骤显示出新业务组合的显著变化。

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

一个月的订阅完全取代了六个月的订阅。这一结果几乎肯定会导致保留曲线的整体移动。为了证明这一点,我们将按产品和持续时间绘制保留曲线。

与全息地图建立互动

之前展示的情节很容易制作,也很吸引人,但是在交互性方面有所限制。HoloViews 的一个很好的特性是能够产生类似仪表盘的可视化效果。此外,它还以 html 格式生成这些可视化效果,以便它们可以嵌入到网页中。这些特性比简单地将数据帧传递给 hvplot 需要更多的代码。这些功能通过两种可视化方式进行了演示,有助于识别保留趋势。

在生成可视化之前,构建一些助手函数将使代码更具可读性。在之前显示的群组曲线图中,很难看出哪条线属于哪个年份。为了使这一点更清楚,人们可以指定一种随着年龄增长而褪色的颜色。下面的代码块将线条涂成蓝色,并且随着时间的推移,蓝色逐渐变成白色/灰色。

def gen_cohort_plot( cohort ):
    cohort = cohort[ cohort > 0]
## #1 Create curves with hvplot
    plot = cohort.T.hvplot( width=700, height=350, legend=False ) 
    d_min = 2015 REPLACE
    d_max = 2017 REPLACE
## #2 loop through curves to adjust the formatting 
    for item in plot.items():
        date , curve = item
        year = pd.to_datetime( date ).year 
## #3 interpolate the blue scale bounded between .2 and .8
        c = plt.cm.Blues( .8* (year - d_min ) / ( d_max - d_min ) + .2)
        curve.opts( hv.opts.Curve( color=c ))
    return plot

这个函数看起来很吓人,但是逻辑非常简单。在#1 中,hvplot 用于生成与前面所示相同的曲线。这些曲线在#2 中循环,而#3 将相对于最小和最大群组年的群组年线性插值到 matplotlib 的蓝色地图上。

## #1 loop through possible pairs of product and duration 
## pd_curve is a helper function that just filters data before 
## being passed to gen_cohort_plot()
curve_dict_2D = {(d,p):pd_curve(p,d, cohorts_scaled) for p in products for d in durations }## #2 create hmap visualizations 
hmap = hv.HoloMap(curve_dict_2D , kdims=['Duration', 'Product'])## generate a plot of the number of conversions
conv_curve_dict_2D = {(d,p):conversion_plot( p , d , cohorts ) for p in products for d in durations }
conv_hmap = hv.HoloMap(conv_curve_dict_2D, kdims=['Duration', 'Product'])## generate a plot of the average price for a cohorts first month
asp_curve_dict_2D =  {(d,p):asp_plot(p,d, cohort_asp) for p in products for d in durations }
asp_hmap = hv.HoloMap(asp_curve_dict_2D, kdims=['Duration', 'Product'])(hmap +conv_hmap + asp_hmap ).cols(1)

曲线存储在字典中,可以在不同的布局选项中传递。这里展示的是全息地图。全息地图根据显示的字典键生成下拉选择器:

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

线条越黑,群组越新。点击不同的组合后,可以清楚地看到一个月订阅的保留情况更差。我们之前已经观察到,一个月订阅在新客户群中所占的比例越来越大。

虽然给线条涂上不同的颜色有助于显示群组的年龄,但热图提供了一种显示信息的替代方法,使某些趋势更容易识别。但是,如果向不熟悉这种格式的各方展示热图,热图确实需要比线图更多的解释。本教程最后将讨论如何生成和解释热图视图。

创建辅助函数是为了格式化图形,并使代码更易于管理。

def heatmap_product_duration( product , duration , data = cohorts_scaled):
## #1 filter the data for the product duration pair
    idx = pd.IndexSlice
    data = data.loc[ idx[product, duration, :] , :].reset_index( level = [0,1], drop = True)

    data = data[data>0]

    data = data.stack().rename( 'retention').reset_index()
    data = data[ data['retention'] > 0]
    data.columns = ['cohort','tenure','retention']
## #2 Create a heatmap
    hm = hv.HeatMap(data , kdims=['tenure','cohort']).sort()
## #3 Formatting options note the addition of the hover tool 
    hm.opts( opts.HeatMap( width = 500 , height = 500  ,colorbar = True, yformatter = dtf , xrotation = 90 ,cmap = 'RdYlGn' ,tools=['hover'], toolbar='above'))
    return hmdef left_conv_bar( product , duration, data = cohorts ):
## #1 filter the data for the product duration pair
    idx = pd.IndexSlice
    data = data.loc[ idx[product, duration, :] , :].reset_index( level = [0,1], drop = True)
    data = data.loc[:,0].rename( 'conversions').reset_index() 
## #2 similar to the previous bar charts, note the invert_axes option
    bar = hv.Bars(  data ).opts( invert_axes=True , height = 500 , width = 200 , color = 'Green' , yaxis = None, invert_xaxis=True )
    return bar

在构建了 helper 函数之后,以类似于之前的方式,代码循环遍历产品持续时间对,并创建一个字典来存储可视化,然后最终将它们传递给全息地图。

heatmap_curve_dict_2D = {(d,p):heatmap_product_duration(p,d) for p in products for d in durations }
heatmap_hmap = hv.HoloMap(heatmap_curve_dict_2D, kdims=['Duration', 'Product'])
left_bar_curve_dict_2D = {(d,p):left_conv_bar(p,d) for p in products for d in durations }
left_bar_hmap = hv.HoloMap(left_bar_curve_dict_2D, kdims=['Duration', 'Product'])
layout = (left_bar_hmap  + heatmap_hmap ).opts( shared_axes = True)
layout

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

此视图通过观察一个月订阅的所有层在 2018 年 10 月后从早期任期的绿色转变为黄色,显示了不同群组的老化情况。注意,这种偏移也对应于转换次数开始增加的时期。这种现象在不断发展的企业中相当普遍。增加营销支出或改变产品/价格将吸引更多的新客户,但增加的新客户不一定与以前的客户群相同。

HoloViews 允许分析师产生高质量的可视化,通过高度定制来加速产生有意义的见解的时间。谢谢你读到这里,我希望你能去图书馆看看。

fastai2 的高级数据加载器

原文:https://towardsdatascience.com/advanced-dataloaders-with-fastai2-ecea62a7d97e?source=collection_archive---------33-----------------------

快速介绍

优雅的 fastai2 方法创建超出通常的输入-目标对的数据加载器——一个使用 Kaggle Bengali 的例子。人工智能数据

在深度学习项目中,在开始训练任何模型之前,关键的一步是要有一个数据加载器,能够为模型提供批量数据,并执行图像放大等操作。在这个故事中,我将展示一个用于孟加拉语的数据加载器。AI Kaggle 竞赛可以使用 fastai 创建,只需 12 行干净的代码。贯穿全文,当提到 fastai 时,我指的是库的最新版本( fastai2 )。

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

作者照片

为什么是 fastai?

引用他们的学术论文:

“fastai 是围绕两个主要设计目标组织的:平易近人和快速高效,同时也是高度可黑客化和可配置的。其他库倾向于在简洁性和开发速度,或者灵活性和表达性之间做出选择,但不能两者都选。我们希望获得 Keras 的清晰度和开发速度,以及 PyTorch 的可定制性。”

fastai 的这一核心特征使它能够为更广泛的受众所使用,同时也是有经验的从业者和研究人员的优秀工具。fastai 高级 API 包括两个组件:数据块学习器。这个故事着重于数据块组件,我发现这是一个优雅的解决方案,可以轻松地创建一个具有一个输入和三个目标的数据加载器——这是 Bengali 所需要的。人工智能竞赛。

孟加拉语。AI 比赛数据

用孟加拉语。人工智能竞赛给我们一组手写的字素,目标是用对应于字素不同组成部分的三个分类标签对每个字素进行分类。图像名称和各自的标签存储在一个 CSV 文件中,该文件可以加载到 pandas 数据帧:df = PD . read _ CSV(CSV _ file)

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

五个字素和各自标签的样本。作者使用竞赛数据创建的图像。

dataframe 包括 image_id、三个不同标签的类别号(grapheme_root、元音 _ 音调符号、辅音 _ 音调符号)、字形的表示以及范围从 0 到 4 的折叠号,该折叠号将用于将数据分成训练/验证集。

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

数据报的前 5 行。作者使用比赛数据笔记本中的数据创建的图像。

用 12 行代码创建数据加载器

要创建数据加载器,包括图像扩充和规范化,只需要下面的 12 行代码(其中 df 是数据帧, train_path 是存储图像的路径)。

在 fastai 中创建一个带有一个图像输入和三个分类目标的数据加载器。

  • 在前两行中,定义了图像标准化和图像放大。Fastai aug_transforms 函数返回一个带有默认扩充的列表。由于字形是水平不对称的,翻转图像可能不是一个好主意,因此参数 do_flip 被设置为 false。
  • 在第 3 到 10 行,创建了数据块。第 4 行的参数接收一个包含四个元素的元组——一个用于图像输入,三个用于分类目标。用于这些类型数据的 fastai 块有:用于图像的图像块和用于目标标签的类别块。由于该数据集中的图像是灰度而不是 RGB,因此将cls = piimagebw赋予 ImageBlock。注意*(3*[CategoryBlock])是写三次 CategoryBlock 的懒惰方式。
  • getters 参数接收定义如何获取每个块的数据的类列表。Fastai ColReader 类用于从 pandas dataframe 的一列中获取数据。在第 5 行中,第一个 ColReader 获取图像名称(检查上面的 dataframe 示例以供参考),然后对于每个 CategoryBlock,给出对应于不同标签的 dataframe 的一列。
  • 第 9 行中的拆分器参数定义了如何将数据集拆分为训练/验证。有几种方法来定义分割。在这种情况下,由于我们在数据框中有折叠数,fastai IndexSplitter 函数可用于选择哪些样品将出现在验证集中。
  • 在第 10 行中, batch_tfms 参数接收一个转换列表,如前两行所定义的。
  • 现在数据块已经完成,在第 11 行中,使用以下参数创建了数据加载器:dataframe 和 batch-size。
  • 最后,在第 12 行, n_inp 被设置为 1,这意味着只有一个输入——其他三个模块应被视为目标。

使用数据加载器

调用 dls.show_batch() 将打印出几个样本,类似于本文中第一幅图所示的内容。

不言而喻,数据加载器与 fastai Learner 类完美集成。然而,可以在一个循环中调用训练和验证数据加载器 dls.traindls.valid 来提取批量数据,如下图所示。注意,有四个值要解包,对应于数据块中定义的块。

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

使用列车数据加载器的循环示例。作者创造的形象。

这有什么关系

fastai 库允许为孟加拉语创建数据加载器。人工智能竞赛仅 12 行干净的代码,包括图像放大和规范化。拥有一个默认情况下提供高效代码的框架,可以让深度学习实践者将更多时间分配给实验,从而增加更好的最终结果的可能性。拥有简洁的代码也减少了小错误的机会,这些小错误可能会悄悄地影响模型的性能。最后,代码在共享时更容易理解。

值得注意的是,fastai aug_transforms 增量是在 GPU 中计算的(如果有一个可用的话)。

像这样的细节很重要。

结束语

这个 Kaggle 内核为孟加拉语提供了一个完整的工作示例。人工智能竞赛,包括模型定义和使用学习者类的训练,这在本故事中没有涉及。

进一步阅读

在下面的故事中,我将进一步探索 fastai 数据块:

[## 使用 3D 数据— fastai2

了解 fastai 数据块并创建用于深度学习的图像序列的构建块…

towardsdatascience.com](/working-with-3d-data-fastai2-5e2baa09037e)

关于我

[## 我的 3 年历程:从零 Python 到深度学习竞赛高手

自从 2017 年开始学习 Python 以来,我一直遵循的道路是成为一名独自参加 Kaggle 比赛的大师…

towardsdatascience.com](/my-3-year-journey-from-zero-python-to-deep-learning-competition-master-6605c188eec7)

感谢阅读!

编辑日志:

2020 年 5 月 10 日:修正了代码中的错误。batch_tfm 参数先前已在 dataloader 中给出。它应该在数据块中给出,而不是如正确的版本所示。

2020–06–07:增加了进一步阅读部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值