TowardsDataScience 博客中文翻译 2021(一百四十二)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

人工智能系统中的偏见及其解决方法

原文:https://towardsdatascience.com/bias-in-ai-systems-and-efforts-to-fix-it-318798f5b39f?source=collection_archive---------35-----------------------

理解人工智能系统中的种族和性别偏见是如何发生的,以及如何解决它们

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

杰西卡·菲利西奥在 Unsplash 上的照片

2019 年 4 月,纽约大学的 AI Now Institute 发布了一份关于人工智能系统中偏见的影响的报告。大约 12 个月后,你可能还记得当一个人工智能模型将巴拉克·奥巴马的像素化图像变成这位前总统的更高分辨率图像时,Twitter 引起的风暴。除了当模型得到一个黑人的像素化图像时,它返回一个白人的高分辨率图像。这是 AI Now 研究所在 NYU 报告中详述的偏见的一个典型例子。随着我们越来越多地将人工智能系统融入我们的日常生活,我认为描述这些问题并就如何解决这些问题展开对话是至关重要的。在我们了解这些偏见是如何产生的以及需要采取什么措施来解决它之前,我们先来快速了解一下有监督的机器学习算法是如何工作的。

有监督的机器学习算法是如何工作的?

监督机器学习算法的目的是学习一个函数,该函数最接近输入数据和目标数据之间的关系。监督学习算法从带有期望输出的标记为的给定训练数据集中学习。一个好的算法必须是可推广的,这意味着它必须能够根据在训练数据中学习到的内容来准确预测新数据的输出。如果输入的新数据包含以前在训练数据集中没有看到的特征,人工智能将很难对这些新数据进行分类。如果这一切听起来有点抽象,这里有一个简单的例子。假设您想要训练一个 ML 模型来分类照片中是否有马或狗。在训练数据集中,你给它提供了成千上万张带有标签的吉娃娃和种马的图片。如果你给你的模型看一张大丹犬的图片,它很可能会误认为是一匹马。该模型对所有犬种不够通用,因为它没有用其他犬种的图像进行训练。

ML 模型中偏差是如何产生的?

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

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

简单的答案是,有偏差的 ML 输出是由于有偏差的训练数据而产生的。当然,数据本身并不存在固有的偏差,人工智能中出现偏差的真正原因是,负责提供训练数据的人存在偏差,或者未能注意到他们数据中的偏差。

未能注意到有偏差的数据是一个微妙的概念,但会导致与不小心收集有偏差的数据一样糟糕的结果。看看亚马逊 2015 年的招聘工具就是一个经典例子。该工具旨在更好地自动选择公司招聘的最佳候选人。这位模特显然是在十年前接受过 CVs 训练的。理论上,到目前为止一切顺利。简历库中应该有各种各样的人。事实并非如此,2005 年申请这些职位的人比 2015 年更加偏向男性。最终结果是该工具被发现对完全合格的女性有偏见,当事情变得明显时,亚马逊很快放弃了整个项目。就模型而言,男性是这项工作的最佳候选人,因为所有的训练数据似乎都表明了这一点。

人工智能中出现偏见的另一个原因是建立这些模型的公司缺乏代表性。以下是 AI Now 研究所报告中的一些统计数据;人工智能的教授 80%是白人男性;在谷歌、脸书和微软之间,没有一家公司的黑人员工比例超过 4%。该领域的女性人数同样惨淡,尽管推动了更多女性进入科技行业。此外,该领域的人往往很富有,这就带来了潜在的社会经济偏见

我们如何解决这个问题?

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

照片由克里斯蒂娜@ wocintechchat.comUnsplash 上拍摄

我认为,解决这个问题的第一步是承认这个问题。我在这里看到了令人鼓舞的迹象,因为人工智能专业人士和机构似乎认识到了这些问题,并正在努力解决这些问题。应对人工智能系统中的偏见的另一个步骤是,在开发和分发系统的公司的所有级别中,纳入受到偏见的人。对这些公司领导职位的需求有偏见的团体。一些科技公司的少数群体、女性和残疾人的数量似乎在朝着正确的方向发展,但不清楚这些人中有多少人能够做出影响其产品偏见的决定。

结束语

像我们社会的许多领域一样,我们在人工智能系统中看到了不可接受的偏见。这是一个需要尽快解决的问题,因为这些系统融入了我们生活的更多方面,公司使用它们来做出影响整个社区的决策。令人鼓舞的是,AI Now Institute 等人工智能研究机构认识到了这个问题的严重性,并致力于解决这个问题。现在,科技公司有责任在领导岗位上增加女性、有色人种和残疾人的代表,并赋予他们权力,成为解决人工智能偏见的一部分。

我将留给你们一段我认为是来自艾安娜·霍华德教授和 T2 教授讨论人工智能种族偏见的有力的引用。

“有时有色人种在场,而我们没被发现。其他时候我们失踪了,但是我们的缺席没有被注意到。这里的问题是后者。”

数据集中的偏见:新冠肺炎案例研究

原文:https://towardsdatascience.com/bias-in-your-datasets-covid-19-case-study-d065aa698b74?source=collection_archive---------31-----------------------

偏见如何通过过度拟合来影响深度学习模型的性能?让我们关注医学图像的模型可解释性。

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

胸部 x 光打开快门架

动机

在过去的几年里,大量的实验显示了人工智能(AI)在医学成像服务中的兴趣,特别是在放射学中。这是由于大型数据集的可用性、计算能力的巨大进步以及新的深度学习算法的出现而成为可能。然而,由于这些人工智能算法在实验阶段和真实条件下的实现之间的性能退化,这些技术今天没有广泛普及。对这一现象的解释之一与过度拟合有关:该算法不会在新数据上广泛传播。

在这个项目中,我们想说明偏倚如何显著影响胸部 X 射线(CXR)图像分类模型的性能。除了对数据集进行简单的探索性分析,我们试图证明这些偏差的存在,并对其进行表征。

主要目的是开发一种算法,该算法将从 CXR 图像中预测患者是否患有病毒性肺炎新冠肺炎或无病(正常)。在这种情况下,使用了这三类中每一类的 CXR 图像的三个数据集,即具有平衡分布的 3886 个射线照相图像:新冠肺炎射线照相数据库【1,2】。

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

包含 3 个类别的数据集:COVID、NORMAL、PNEUMO(作者提供的图片)

作为深度学习领域的新手,我们选择了一个简单的 CNN 模型来实现(LeNet)两个卷积层。你猜怎么着,我们得到了 97%的测试准确率🎊!

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

使用 30 个时期的(LeNet)模型实现 97%的准确性(图片由作者提供)

我们没有公布 2021 年诺贝尔医学奖的结果,而是问了自己以下问题:

用一个简单的 2 层卷积神经网络模型检测胸部疾病几乎有 97%的准确率是对的吗?

答案是否定的 。这就是为什么在训练迁移学习模型之前,深入研究数据集的偏差并尝试纠正它们是非常重要的。

我们的数据集中存在哪些偏见?

第一步是试图找出图像的差异和异质性。为此,比较了正常图像和 COVID 图像之间的亮度分布。

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

Covid/正常图像的亮度分布(图片由作者提供)

观察到亮度分布的显著差异。因此,这个全局特性足以以“正确”的方式区分这两个类别,并为我们之前注意到的高性能提供了第一个解释(LeNet)。

让我们进一步分析…

为了可视化数据集的偏差,我们已经开始寻找可以将 3 个类分开的局部特征。想法是将图像投影到更小的维度空间中,以观察 3 个类别的图像中的趋势。为此,图像被调整为 28x28:

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

CXR 图片尺寸调整为 28x28 像素(图片由作者提供)

由于缺乏细节,理论上不可能检测出 covid 或肺炎。

t-SNE 算法[3]是一种非线性聚类方法,可以通过连续迭代在二维或三维空间中表示一组高维空间的点。然后,数据可以以点云的形式可视化:

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

用 t-SNE 算法可视化高维数据(来自https://zaburo-ch.github.io/images/mnist_process.gif

t-SNE 应用了像素强度的两个分量,数据集显示在这两个轴上。令人惊讶的是,使用无监督聚类方法和没有细节的图像,可以在 2D 投影上区分 3 个类别!

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

数据集的 t-SNE 可视化,然后进行 SVM 分类(图片由作者提供)

事实上,通过在对应于两个 t-SNE 轴的两个变量上应用 SVM,获得了 84%的准确度。

t-SNE 算法似乎可以从 28x28 的非细节图像中提取重要信息,使其能够进行良好的分类。为了便于解释,让我们用 PCA 做同样的事情。

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

数据集的 PCA 可视化(图片由作者提供)

投影的效率低于 t-SNE 方法,但我们注意到第一模式(x 轴)可以正确地将 Covid 图像与非 Covid 图像分开。根据这一观察,我们可以显示向量“pca.components_[0]”,仅取系数的绝对值,并查看 28x28 热图:

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

第一个 PCA 组件的热图(图片由作者提供)

从上面的投影(第一主成分)可以看出,重要的像素位于图像的左右边缘。因此,边缘的亮度使我们能够正确地将数据集中的 covid 图像与非 covid 图像分开,这在我们的研究中代表了一种真正的偏差!

让我们更进一步…

对神经网络最常见的批评是难以提取和以人类可读的形式解释决策过程。它们通常被视为“黑匣子”。但这还不包括最近解决这个棘手问题的出版物:

卷积神经网络如何决定?

Grad-CAM 是 2017 年发布的一种方法[4],有助于解读 CNN 的结果。它通过计算从决策反向传播到最后卷积层的梯度,提供由神经网络确定的类别的激活图:

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

Grad-CAM 架构(图片由作者提供)

Grad-CAM 算法应用于具有 12 个随机 COVID 图像的第一个原型(LeNet ),激活图向我们显示网络主要使用图像的边缘来做出决策,而不是在肺部内部寻找有用的信息:

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

绿色/黄色区域是基于网络决策的感兴趣区域,蓝色区域是不感兴趣区域。(图片由作者提供)

如何纠正这些偏见?

在对数据集的偏差进行分析后,我们观察到分类算法主要基于图像边缘的像素来做出决定。因此,我们的想法是去除这些边缘,并且只关注具有分类所需信息的肺。

这需要使用一个 U-Net 神经网络,该网络是根据 CXR 图像预先训练的,是专门为肺部分割开发的。

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

U-Net 架构(图片由作者提供)

下面的序列说明了经过所有预处理方法后的图像转换:

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

细分渠道(图片由作者提供)

分割后,图像在肺部周围以 10 像素的边缘被裁剪。

然后,均匀化和裁剪后的图像用于构建我们的新数据集,以训练和测试深度学习模型。

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

预处理前后(图片由作者提供)

最后,它有用吗?

通过对裁剪后的图像应用 t-SNE 方法,仍然可以在数据集中观察到偏差,因为无监督算法仍然能够分离类别😭:

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

预处理数据集上的 t-SNE(图片由作者提供)

预处理图像的迁移学习

测试了两个迁移学习模型:DenseNet121 (121 个卷积层😮)和 VGG16 架构,两者都在庞大的 Imagenet 数据集上进行了预训练。

PS:因为 CXR 是黑白的,所以在输入之后插入了一个卷积层来给图像“上色”。

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

训练参数和准确度(图片由作者提供)

两个迁移学习模型的准确性低于 LeNet 的准确性,但是 Grad-CAM 激活图向我们显示,他们主要是在肺部做出决定。

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

Grad-CAM 激活图应用于 VGG16,经过预处理(图片由作者提供)

您还可以使用您的图像测试这 3 个模型,并通过以下地址提供的 Streamlit 应用程序观察 Grad-CAM 激活图:https://studio.datascientest.com/project/covid/

结果

  • 通过 t-SNE 和 PCA 方法降维突出数据集偏差。
  • 通过分割肺来均衡直方图和从图像中去除边缘的流水线的开发。
  • 用(Densenet121 和 VGG16)迁移学习。
  • 使用最近的 Grad-CAM 方法可视化神经网络类激活图。

思想

  • 通过对每个类别使用不同来源的新图像,纠正预处理后仍然存在的偏差。
  • 通过训练更多的 epochs 和解冻预训练网络的一些层来继续优化网络性能。
  • 与放射科医生合作,评估 grad-CAM 卡在患者图像上的适用性
  • 除了图像之外,将患者信息添加到模型中:症状、病史、年龄、性别、位置、日期等;以便使该模型更加稳健并忠实于实际的医学诊断。

道德

拥有出色的性能是没有意义的,你必须限制数据集中的偏差!

在深度学习中,决定算法是什么的主要是数据。

作者

巴蒂斯特·莫罗:领英

查迪·马斯里:领英

卡莉玛·本尼亚:领英

参考

[1] CHOWDHURY,Muhammad EH,RAHMAN,Tawsifur,KHANDAKAR,Amith,AI 能否帮助筛查病毒性和新冠肺炎肺炎?。 IEEE Access ,2020 年,第 8 卷,第 132665–132676 页。

[2] RAHMAN,Tawsifur,KHANDAKAR,Amith,QIBLAWEY,Yazan 等.利用胸部 X 射线图像探索图像增强技术对新冠肺炎检测的影响.生物学和医学中的计算机,2021 年,第 132 卷,第 104319 页。

[3]范德马腾,劳伦斯和辛顿,杰弗里。使用 t-SNE 可视化数据。机器学习研究杂志,2008 年,第 9 卷,第 11 期。

[4] SELVARAJU,Ramprasaath R .,COGSWELL,Michael,DAS,Abhishek,等. Grad-cam:通过基于梯度的定位从深度网络进行视觉解释.IEEE 计算机视觉国际会议论文集。2017.第 618-626 页。

偏差方差权衡

原文:https://towardsdatascience.com/bias-variance-trade-off-7b4987dd9795?source=collection_archive---------22-----------------------

了解偏差、方差和总误差与模型复杂性和过度拟合/欠拟合的关系。

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

马克西姆·霍普曼在 Unsplash 上的照片

偏差-方差权衡是机器/深度学习领域的每个人都应该知道的重要概念。无论您计划将模型应用到哪个应用领域,这些概念都将帮助您采取措施,潜在地解决为什么您的模型在您的训练或测试集上表现不佳的问题。

引言[1]

偏差方差权衡将帮助我们理解模型对训练数据过度拟合和欠拟合的概念。我们将能够判断我们的模型是否能够将误差降低到特定值以上。

在开始偏差和方差的概念之前,我们将看看 ML/DL 模型作为一种估计基础函数的方法。

机器学习以及深度学习中的一般任务是从训练数据中估计底层函数。我们将使用下面的符号。

  • f(x) :真函数
  • f̂(x) :估算函数

在经典估计理论中,在估计实际模型参数之前,需要根据数据的特征和属性对数据进行数学建模。对于信号处理,概率密度函数(pdf)是基于数学模型的未知参数定义的。例如,均值和方差是高斯过程的参数。

然而,PDF 的规格是决定一个好的估算器的关键因素。这些 pdf 不是给我们的,而是需要选择的,它不仅与问题约束一致,而且在数学上是易处理的,或者在合理的时间内实际上是可解的。每个 PDF 都有一组潜在的假设,所有的数学都是有效的。如果不满足这些条件,那么估计器就不会按预期运行。

对于 DL/ML 模型,这些参数是权重和偏差矩阵。我们没有定义 pdf 的类型,而是关注于架构类型、初始化技术、损失函数等。基于问题定义。我们试图根据训练数据找出这些矩阵的最佳可能值。我们使用基于梯度下降的优化技术来寻找逼近实际函数的最优或最佳函数。【你可以在这里了解更多:梯度下降解开

寻找最佳估计量

寻找最优估计量通常需要一个最优性准则。对于 DL/ML 模型,这个准则就是我们使用的损失函数。有几种损失函数可供选择。函数的选择取决于您试图解决的问题,例如分类、回归、分段等。

然而,均方误差(MSE)是最自然的一种,定义如下。

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

估计函数的 MSE 是估计函数与实际函数之差的平方的期望值。我不会讨论什么是期望,因为这超出了本文的范围。然而,如果你想了解更多,我推荐以下内容。

MSE 衡量估计值与真实值的平均均方偏差。它有一个漂亮的凸面,即向上弯曲,只有一个最佳值。因此它非常适合于各种各样的优化技术。

偏差方差分解

MSE 误差可以分解成两项,即偏差和方差。我将在下面展示和解释分解推导。为推导起见, f(x) 表示为 ff̂(x) 表示为

但在此之前,我将简要给出偏差和方差的数学定义:

偏见

偏差定义为:b()= e(f̂)-f

b( )这里是估计量的偏差。它本质上是测量估计者的期望值和被估计参数的真实值之间的差异。【你可以在这里了解更多。[https://en.wikipedia.org/wiki/Bias_of_an_estimator](https://en.wikipedia.org/wiki/Bias_of_an_estimator#:~:text=In%20statistics%2C%20the%20bias%20(or,objective%20property%20of%20an%20estimator.)

差异

方差定义为:Var(f) = E[(f - E(f)) ]

随机变量的方差是随机变量与其期望值之差的平方的期望值。所以它是随机变量与其自身均值的均方偏差。高方差意味着 X 的观测值将远离平均值,反之亦然。你可以在这里阅读。https://www.stat.auckland.ac.nz/~fewster/325/notes/ch3.pdf

现在我们用 MSE 函数的定义开始推导。接下来是对 f̂.期望的战略性加减然后,我们使用一些属性和定义来得到偏差和方差分量。

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

来源:作者

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

来源:作者

偏差-方差分解可以用下面的三角关系来表示。

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

来源:作者

偏差是估计量的期望值和实际基础函数之间的差异。方差是模型的可变性。在估计理论中,存在不同类型的估计量。然而,对于经典的估计理论,从实用的角度来看,最小均方误差估计需要被放弃,因为这个标准导致不可实现的估计。我们经常求助于最小方差无偏(MVU)估计量,它有更专业的版本,如最佳线性无偏估计量(BLUE)等。如果你对估计理论统计信号处理基础感兴趣,第一卷:估计理论是一个惊人的资源。

在深度学习的情况下,网络在没有任何明确定义的情况下作为强大的估计器工作。上面所做的所有分析也直接适用于这种情况。

现在让我们看看,如果我们给随机过程添加一些噪声,分解会是什么样子。这是因为对于我们可用的随机过程的观测值 Y,总是包含一些固有的噪声。可以这样写:

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

ϵ 具有均值和方差为零的正态分布 σ

这个假设在 MSE 分解中增加了一项。由于求导和没有噪声项几乎一样,所以我直接写尾方程。不过,如果你对推导感兴趣,请参考这个链接。

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

σ 项表示贝叶斯误差,可表示如下。

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

贝叶斯误差是指任何分类器的最低可能误差,类似于不可约误差。它也被称为最佳误差。即使你建立了一个完美的模型,这个误差也无法消除。这是因为训练数据本身并不完美,包含了噪声。

因此,模型的总误差是三种误差的叠加:

  • 模型偏差导致的误差
  • 由于模型差异造成的误差
  • 不可约误差(贝叶斯误差)

偏差和方差对模型总误差的影响

偏差、方差和总误差之间的关系可以用下图来解释。x 轴代表我们模型的复杂性,y 轴是误差值。

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

来源:作者

  • 我们看到,随着模型复杂性的增加,偏差继续减少,方差继续增加。这是因为如果模型变得越来越大,它表示函数的能力就会不断增加。事实上,如果你让模型足够大,它可以记住整个训练数据,导致误差为零(如果贝叶斯误差为零)。然而,拥有一个过于复杂的模型将导致较差的泛化能力,即使你将获得良好的训练性能。这叫做过度拟合。
  • 另一方面,如果你的模型太简单,它会有很高的偏差和很低的方差。即使对于训练样本,误差也会非常高。如果您观察到,即使在许多个时期之后,您的模型仍然具有较差的定型数据性能,这可能意味着您的数据具有损坏的标签,或者模型不够复杂,无法逼近基础函数。这就是所谓的不适应。
  • 正如我们在图中看到的,总误差继续降低,直到达到最佳复杂度点。这是仅留下贝叶斯误差并且模型具有最高性能的地方。在这一点上,我们在偏差和方差之间取得了恰当的平衡。

以下是欠拟合、最佳拟合和过拟合的一些例子。

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

来源:作者[5]

我们观察到,对于具有高方差的模型(最右列),潜在的噪声也被捕获。这导致了令人敬畏的训练表现,但是可怕的测试表现。因为在这种情况下泛化能力最差。相反,对于具有高偏差的模型(最左边的列),模型不能捕捉数据中的潜在模式。因此,该模型即使在训练数据上也表现不佳。最佳模型是最好的模型,也是最通用的模型,因为它有适当的偏差和方差。

结论

我们看到了偏差-方差分解是如何工作的。模型复杂性如何影响总误差、偏差和方差。我们讨论了贝叶斯误差,这是一种最小误差,它总是存在于噪声观测中。最后,我们看到过拟合、欠拟合和最佳拟合是什么样子的。在我未来的一篇文章中,我计划讨论深度学习中使用的技术,以克服过拟合/欠拟合的问题。感谢您阅读我的文章。希望你觉得有用。

参考

[1] 统计信号处理基础:估计理论。

[2]https://en.wikipedia.org/wiki/Expected_value

[3]https://en.wikipedia.org/wiki/Bias_of_an_estimator

https://www.stat.auckland.ac.nz/~fewster/325/notes/ch3.pdf

[5] Pinterest 图片

Python 示例中的偏差-方差权衡

原文:https://towardsdatascience.com/bias-variance-trade-off-with-python-example-6519d2084be4?source=collection_archive---------13-----------------------

根据误差估计选择最佳拟合模型

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

图片作者。

这篇文章旨在通过 Python 中的一个实际例子来展示偏差-方差权衡

偏差-方差权衡指的是机器学习模型的两个竞争属性之间的平衡。

监督机器学习问题的目标是找到解释输入预测值(x)和观察结果(y)之间关系的数学表示(f):

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

其中ɛ表示数据中的噪声。

例如,我们通过选择正弦波作为两者之间的关系来创建我们的合成 x 和 y:

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

其中{ x ∈ R ∣ 0 < x < 2 }

We also assume a normally distributed noise, with mean=0 and variance=1.

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

Image by author.

In a real-world scenario, we would not know the relationship between predictors and outcome.

Given a dataset, our task is to find suitable candidate models and choose the one that better fits our information.

To this aim, we split our data in, 至少,两个不同的集合:

  1. 训练集:拟合模型的部分数据。
  2. 测试集:评估模型性能的数据部分。

由于测试集包含模型以前未见过的数据,因此评估该测试集的性能可以更好地估计模型在真实世界中对未知数据的表现。

我们将原始数据分为训练集(80%)和测试集(20%),如下所示:

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

图片作者。

现在,我们希望在训练集上训练一些模型,并在测试集上评估它们的性能。

特别是,我们希望最小化模型在从预测器预测结果时产生的误差;对于我们所有的观察(n),这种误差通常是预测结果(y_predicted)和观察结果(y_observed)之间的距离的度量。

在这种情况下,我们可以使用均方误差,定义如下:

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

此外,我们可以证明这个误差可以分解为三个量的和:

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

任何模型,无论多好,都是数据间复杂关系的近似,因此所谓的不可约误差是不可避免的。

从公式中可以看出,一个好的模型应该将偏差和方差最小化:让我们来定义这些术语。

偏置

偏差考虑了模型预测和真实结果之间的差异。

这主要取决于我们选择的解决问题的模型,以及模型假设如何恰当地解释预测因素和结果之间的关系

通过观察我们的训练集图,我们注意到一个非线性趋势。如果我们选择用线性回归来模拟 x 和 y 之间的关系,模型假设显然不能解释我们的 f,我们知道 f 是非线性的。在这种情况下,我们将获得一个具有高偏差的模型。

我们可以凭经验评估模型遭受高偏差,因为它在训练集上显示高误差。或者换句话说,训练表现不佳:这种情况被称为训练不足

偏高:

-模型假设未能解释预测因素和结果之间的关系。

-涉及“更简单”(不太灵活)的模型,如线性回归。

-导致装配不足(列车组性能不佳)。

方差

方差衡量训练集的不同选择如何影响模型参数。

当我们训练一个机器学习模型时,我们希望通过选择一个稍微不同的训练集,函数不会发生显著变化。否则,我们将获得一个在输入数据的微小变化面前无法概括的模型:这被称为过拟合

直觉上,具有较少假设的模型不会遭受高方差,因为它们在训练集中的小变化面前不会改变。因此,高方差是一个影响更灵活的模型(如决策树)的问题。

由于该模型足够复杂,足以在训练集上过度拟合,我们会期望高训练性能(或低训练误差),但也会期望差的测试性能,因为该模型需要参数的显著变化来解释数据中的小变化。

高方差:

-涉及更“复杂”的模型(更灵活),比如决策树。

-导致过度拟合(测试集性能不佳)。

这幅图概括了这个概念:

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

来自:Trevor Hastie、Robert Tibshirani 和 J H. Friedman,“统计学习的要素:数据挖掘、推理和预测”,纽约:Springer,2001 年。

为了在我们的示例中说明这些概念,我们在训练集上拟合多项式次数递增的多个多项式模型,然后观察 MSE 随模型复杂度增加的趋势:

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

图片作者。

如果我们从左到右观察多项式次数(模型复杂度)的 MSE 图,模型复杂度的增加导致训练误差的减少(较低偏差),但测试误差 ( 高方差)也显著增加**。**

另一方面,我们也注意到模型复杂度的降低导致较差的训练集性能 ( 高偏差)以及在测试集 ( 低方差)上更好的泛化。

最佳拟合由最小化测试误差的多项式次数表示:

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

总之,最佳拟合显示了两个特征:它很好地拟合了训练集(低训练集误差),并且它很好地概括了看不见的数据(低测试集误差),因为它最小化了方差和偏差。在我们的例子中,误差较大的模型要么表现出高方差,要么表现出高偏差。因此,这个名字叫做偏差-方差权衡。

机器学习中的偏差-方差权衡:一种直觉

原文:https://towardsdatascience.com/bias-variance-tradeoff-in-machine-learning-an-intuition-da85228c5074?source=collection_archive---------20-----------------------

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

由古斯塔沃·托里斯在 Unsplash 上拍摄的照片

在糟糕的和高度优化的模型之间进行选择

一般直觉

如果我们口袋里有更多的钱,我们会花得更多——这几乎是每个人都知道的事实。但人们通常不知道收入和支出之间的确切关系,也就是说,在已知收入的情况下,人们会花多少钱。

一个近似的解决方法是,通过观察人们的收入和支出,建立一个统计模型。数据越多,模型越好。然后,我们可以把这个模型应用到一个未知的地方或人群,并有合理的把握。

但该模型无法做出 100%准确的预测,因为人们的行为会随着时间和空间而变化(嗯,这就是为什么这被称为统计模型而不是确定性模型)。然而,即使这个模型不是通用的,我们也想让它具有足够的普遍性——一个**“平均** 模型”,能够适应各种各样的变化和情况。

让我们考虑一个不同的背景,当我们真的想要为一个同质的群体建立一个模型时,他们的行为或多或少是可以预测的。在这种情况下,我们的目标是**“优于平均水平的模式”**适合特定人群。然而,我们知道,这种模式是为目标人群定制的,因此在异国环境中会失败。

我们构建的平均模型有偏差,但它具有很高的灵活性,可以在各种情况下工作,而优于平均水平的模型是定制的,偏差较小,但在接受训练的人群之外表现不佳。

现在让我们把这两个模型都发挥到极致。在一个光谱中,我们将模型简化得太多,以至于它失去了所有的预测能力;随机猜测比模型表现更好。在另一个极端,让我们基于群体中的每个个体构建模型,并对模型进行调整,使其对该群体具有高预测能力。

那么哪款更好呢?

取决于你想如何使用模型。一个坏的模型在任何地方都表现很差,一个普通的模型在大多数情况下表现一般,而一个微调的模型在一种情况下表现很好,但在其他情况下就不那么好了。

建立模型的目的是解释现实世界的现象,我们使用模型是因为这些现象会在空间和时间上发生变化。但是我们能建立一个适用于任何地方和任何时间点的模型吗?

答案是否定的。这就是偏差-方差权衡的概念有用的地方。

偏差-方差权衡

现在让我们将这种直觉与偏差-方差权衡的正式概念联系起来。

在机器学习中,每个模型都被指定了许多决定模型性能的参数。一个好的模型在训练和样本外数据上都表现良好。

有些型号可以使用默认参数。但是,如果我们不调整参数,模型就有可能无法发挥最佳性能。这种情况被称为欠适配。

因此,我们调整参数以适应训练数据,然后根据测试数据评估模型性能。重复该过程,直到模型达到期望的性能。但是这种定制模型如果放归野外会有怎样的表现呢?这种高度调整的模型很可能在样本外数据中表现不佳,这就是所谓的过拟合问题。

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

高调优模型与差模型和一般模型(来源:作者)

适应不足和适应过度同样不好——它们不擅长做出一般的预测。因此,偏差-方差权衡无非是维持欠拟合和过拟合之间的平衡,在高方差和高偏差之间进行选择。数据科学家找到了最佳点,因此他们相信该模型在样本外数据中表现良好。

一个例子

现在让我们用 Python 中的一个例子来扩展直觉和偏差-方差权衡的概念。为此,我将首先导入几个库(numpyseaborn)并创建两个小数组——x 和 y——来演示。

import numpy as np
import matplotlib.pyplot as plt
import seaborn as snsx = [0, 1, 2, 3, 4, 5, 6]
y = [0, 1, 2, 14, 18, 32, 52]

现在让我们画出 x 和 y 变量,并拟合一条线性回归线。

# linear fit
sns.regplot(x,y, ci=False);

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

线性模型似乎不太适合数据,它显然看起来像一个坏模型,大多数数据点远离直线。它有很大的偏差,偏差很小。因此,显然有机会改进这一模式。

现在让我们拟合一条高次多项式线,看看模型表现如何。

# polynomial fit
poly_fit = np.poly1d(np.polyfit(x,y, 6))plt.plot(x, poly_fit(x), linestyle='-')
plt.scatter(x, y);

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

多神奇啊!6 次多项式完美地拟合了数据——实际上太完美了,没有误差。该模型捕捉数据中的每一点噪声。这个模型有很高的(完美的)方差,没有偏差。

这是我们想要的型号吗?

大概不会。随着多项式阶数的增加,模型的复杂性增加。不能保证该模型在其他数据上的表现也是如此。

那么更好的模型应该是什么样的呢?介于太坏和太好之间的东西?让我们尝试将多项式次数从 6 降低到 2。

# polynomial fit
poly_fit = np.poly1d(np.polyfit(x,y, 2))plt.plot(x, poly_fit(x), linestyle='-')
plt.scatter(x, y);

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

这个 2 次多项式模型有一些误差,当然没有 6 次模型好,但也没有简单的线性拟合差。因此,事实证明,高次多项式更适合数据,但它也使模型变得复杂。

有什么解决办法?

复杂模型过度拟合训练数据,但无法在测试和样本外数据中做出高质量的预测。另一方面,一个简单的模型不符合训练数据,在测试数据中也表现不佳。

因此,数据科学家的目标是找到一个平衡点来平衡权衡。但是在实践中到底是怎么做的呢?

欠拟合很容易发现,因为它显示在模型性能中。然而,过拟合很难捕捉,因为模型在误差度量方面表现良好。对于数据科学家来说,扔掉一个非常适合的模型,选择一个性能较低的模型也是非常困难的。但是有一些工具可以让这个决定变得更容易。这里有几个选项:

1)错误与复杂性的直观解释:通常,一个好的实践是通过绘图来选择模型:

  • 训练数据中的误差与复杂性
  • 测试数据中的误差与复杂性
  • 检查两条曲线的相交处,并相应地调整参数

在回归中,偏差-方差权衡可以通过绘制均方误差(MSE)与模型复杂性的关系图来检查。在分类中,同样可以通过将错误分类的数量与复杂性相对比来检查。

2)正则化:这是一种通过在成本函数中添加小偏差来优化模型性能的技术。这种小偏差会缩小特征系数,降低其灵敏度。

如果数据集中有太多的要素,正则化会控制它们的影响,并降低它们的敏感度。这是通过将模型系数向零收缩来实现的。通常使用两种类型的正则化-L1(套索回归)和 L2(岭回归),它们由超参数λ控制。

摘要

总结偏差-方差权衡的概念:

  • 如果模型过于简单且不符合训练数据,它在实际预测中的表现也会很差。
  • 根据训练数据高度调整的模型也可能表现不佳。
  • 偏差-方差权衡允许检查平衡以找到合适的模型。
  • 有两种方法来检查权衡——a .错误与复杂性的直观解释,b .正则化。

希望这是对机器学习中这个重要概念的有益讨论,如果你有意见,请随时写在下面,或者通过媒体推特LinkedIn 与我联系。

时间序列中的偏差-方差权衡

原文:https://towardsdatascience.com/bias-variance-tradeoff-in-time-series-8434f536387a?source=collection_archive---------11-----------------------

使用 PyCaret 时序模块

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

照片由艾萨克·史密斯Unsplash 拍摄

📚背景

在为任何机器学习问题建立模型时,我们必须注意偏差-方差权衡。具体来说,对于时间序列:

  1. 偏差太大(拟合不足)意味着模型无法捕捉数据中的所有信号,因此在训练阶段(进而在预测阶段)会导致更高的误差。
  2. 模型中有太多的变化(过度拟合)意味着模型不能很好地概括未知的未来数据(即,它可以很好地处理训练数据,但不能像它训练的那样预测未来数据)。

让我们看看如何用 PyCaret 来诊断这个问题。

🚀PyCaret 中的解决方案概述

PyCaret 中的解决方案是基于吴恩达的建议[1]。我强烈建议读者在继续阅读本文之前,先浏览一下这个短片。PyCaret 中遵循的步骤是:

  1. 时间序列数据首先被分成训练和测试两部分。
  2. 然后,在多个折叠中交叉验证训练分割。交叉验证误差用于在超参数调整阶段从多个模型中进行选择。
  3. 在整个“训练分割”中训练具有最佳超参数的模型
  4. 然后,该模型用于做出与“测试分割”中的时间点相对应的预测。然后,通过将这些“测试”预测与测试分割中的实际数据进行比较,可以报告最终的泛化误差。
  5. 一旦满意,用户可以使用在前面步骤中获得的“最佳超参数”来训练整个数据集(训练+测试分割),并进行未来预测。

1️⃣设置

我们将使用经典的“航空公司”数据集[6]在 PyCaret 中演示这一点。本文的 Jupyter 笔记本可以在这里 找到 ,也可以在文章末尾的“参考资料”部分找到。

from pycaret.datasets import get_data
from pycaret.internal.pycaret_experiment import TimeSeriesExperiment**#### Get data ----**
y = get_data(“airline”, verbose=False)**#### Setup Experiment ----**
exp = TimeSeriesExperiment()**#### Forecast Horizon = 12 months & 3 fold cross validation ----**
exp.setup(data=y, fh=12, fold=3, session_id=42)

2️⃣火车-测试分裂

为了诊断偏差-方差权衡,PyCaret 最初将时间序列数据分为训练和测试两部分。当执行这种分割时,数据的时间依赖性得以保持。测试集的长度与设置实验时指定的预测范围相同(本例中为 12)。这显示在设置摘要中。

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

设置摘要[图片由作者提供]

这种分割也可以使用plot_model功能可视化。

exp.plot_model(**plot="train_test_split"**)

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

时间序列训练-测试分割[图片由作者提供]

3️⃣交叉验证

接下来,训练分割被分解成交叉验证折叠。这样做是为了使训练不会因为一组训练数据而产生偏差。例如,如果过去 12 个月的数据是异常的(比如由于 Covid),那么这可能会影响一个本来很好的模型的性能。另一方面,它可能会让一个糟糕的模型看起来不错。我们希望避免这种情况。因此,我们在不同的数据集上进行多次训练,并对性能进行平均。

在跨这些多个数据集(也称为“折叠”)进行训练时,再次保持时间依赖性是很重要的。可以应用许多策略,如扩展或滑动窗口策略。关于这一点的更多信息可以在[2]中找到。

在设置阶段可以控制折叠的次数。默认情况下,PyCaret 时序模块使用 3 倍。再次使用plot_model可以可视化训练数据中的褶皱。蓝色圆点代表用于每个文件夹中训练的时间点,橙色圆点代表用于验证训练文件夹性能的时间点。同样,橙色点的长度与预测范围(12)相同

exp.plot_model(**plot="cv"**)

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

训练分割中的交叉验证折叠[图片由作者提供]

4️⃣创建初始模型

在本文中,我们将以简化回归模型为例。关于简化回归模型的更多信息可以在[3]中找到。

model = exp.**create_model("lr_cds_dt")**

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

跨交叉验证折叠的基线模型性能[图片由作者提供]

性能显示在 3 个折叠上。3 次折叠的平均绝对误差(MAE)大于 30,平均绝对百分比误差(MAPE)大于 8%。根据应用的不同,这可能还不够好。

交叉验证完成后,PyCaret 将返回在整个定型拆分中定型的模型。这样做是为了让模型的泛化可以在我们之前展示的测试数据集上进行测试。

exp.**predict_model**(model)
exp.**plot_model**(model)

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

测试数据上的基线模型性能[图片由作者提供]

使用此模型的预测现在显示了对应于测试数据集(蓝线)的时间点的预测。还显示了这些“测试”预测的指标。这些指标比交叉验证期间获得的指标更差。由于指标一开始就很糟糕(交叉验证错误率很高),这表明模型中的偏差很大(即模型在这一点上不能很好地捕捉数据集的趋势)。此外,测试指标比交叉验证指标差。这表明差异很大(详情请参考[1])。这在预测图中也是可见的,其显示在测试期间蓝色预测线不接近相应的黑线。

让我们看看是否可以通过调整模型的超参数来改善偏差。

5️⃣调整模型以提高性能

调整过程会尝试各种超参数组合,以查看哪些组合最适合模型。更多信息可在[4]和[5]中找到。一旦尝试了各种超参数组合,就会根据“折叠”的平均交叉验证误差挑选出最佳超参数。然后显示使用这些最佳超参数的交叉验证指标。

tuned_model = exp.**tune_model**(model)

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

跨交叉验证折叠调整模型性能[图片由作者提供]

因此,我们已经能够将交叉验证阶段的错误减少到大约<= 20 and the MAPE is < 5% by performing hyper-parameter tuning. This is much better than before and we have reduced the underfitting significantly. But now we need to ensure we are not overfitting the data. Let’s look at the performance across the test dataset again.

exp.**predict_model(tuned_model)**
exp.**plot_model(tuned_model)**

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

Tuned Model Performance on the Test Data [Image by Author]

The forecasts across the test dataset show better performance than the cross-validation metrics indicative of a lack of overfitting. The plot also shows a good match to the actual data points during the test period.

So this model looks good. But what we need is the ability to predict the true “unknown” future data. This can be done by finalizing the model.

6️⃣ Finalizing the Model to make Future Predictions

Finalizing the model takes the hyperparameters from the model (tuned_model in this case), and fits the entire dataset using these hyperparameters.

final_model = exp.**finalize_model(tuned_model)**
print(exp.predict_model(final_model))
exp.plot_model(final_model)

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

Future Predictions from Finalized Model [Image by Author]

And there you have it. Our best model is now able to make future predictions. Note that metrics are not displayed at this point since we do not know the actual values for the future yet.

🚀 Conclusion

Hopefully, this workflow example has shown why it is important to diagnose bias-variance tradeoff. For time series, this process is complicated by the fact that the temporal dependence must be maintained when performing the splits and cross-validation. Luckily, the PyCaret Time Series module makes managing this process a breeze.

That’s it for this article. If you would like to connect with me on my social channels (I post about Time Series Analysis frequently), you can find me below. Happy forecasting!

🔗 LinkedIn

🐦推特

📘 GitHub

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

https://ngupta13.medium.com/membership

📗资源

  1. Jupyter 笔记本 包含了本文的代码

📚参考

[1]吴恩达模型选择与训练/验证/测试集

[2]PyCaret 中时间序列交叉验证

[3] 时间序列预测的简化回归模型

[4]pyCaret 中时间序列模型的基本超参数整定

[5]pyCaret 中时间序列模型的高级超参数整定

[6]可通过 sktime python 软件包根据 BSD 3-条款许可证获得航空公司数据集。

偏差与方差的权衡——解释清楚

原文:https://towardsdatascience.com/bias-vs-variance-trade-off-clearly-explained-3becf5454b30?source=collection_archive---------22-----------------------

偏差与方差,过度拟合与欠拟合

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

照片由 Pexels 的 Gabby K 拍摄

为什么我们需要偏差-方差权衡

在机器学习中,我们收集数据,并使用训练数据建立模型。我们将该模型应用于该模型未见过的测试数据,并进行预测。我们的主要目的是减少预测误差。

我们通过最小化训练误差来建立模型,但是我们更关心测试误差/预测误差。预测误差取决于偏差和方差。

以下情况需要偏差-方差权衡。

  1. 为了克服欠配合和过配合情况
  2. 预测的一致性。

让我们在本文中详细了解偏差-方差权衡背后的概念。

模型结构

在进行偏差-方差权衡之前,让我们看看当我们增加模型复杂性时,训练误差和预测误差有什么不同。

假设,我们有这样的数据点。我们必须找到 X 和 y 之间的关系。

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

作者图片

X 和 Y 之间的真关系或真函数表示为 f(X) 。这个功能未知。

Y=f(X)+ε

现在,我们必须建立一个模型来描述 X 和 y 之间的关系。

输入→模型→输出

**学习算法:**学习算法将接受输入并返回一个描述 X 和 y 之间关系的函数。

输入→学习算法→ f̂(X)

示例:在线性回归中,学习算法是梯度下降法,它根据成本函数 OLS(最小二乘法)找到最佳拟合线。

假设给定一个数据集,我们把它分成训练数据和测试数据。

训练数据—使用训练数据
测试数据构建模型—使用选择的模型预测输出。

现在,让我们考虑基于训练数据构建的 4 个模型。

在所有的模型中,我们都在假设 y 和 x 的关系。

  1. 简单模型→1 度→ y=f̂(x) = w0 +w1x

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

作者图片

在这个简单的模型中,拟合线远离数据点,因此拟合误差/训练误差会很高。

2.二次多项式

y=f̂(x) = w0 +w1x + w2x

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

作者图片

3。五次多项式

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

作者图片

4。复杂模型→20 度

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

作者图片

这里,在这个复杂的模型中,拟合的曲线穿过所有的数据点,因此拟合误差/训练误差将接近于零。这个模型试图将数据和噪音一起记忆下来,而不是将其一般化。因此,这个模型在看不见的测试数据/验证数据上表现不好。这种情况被称为过度拟合。

现在,如果我们使用这 4 个模型对验证数据进行预测,我们将得到不同的预测误差。

现在绘制训练误差和预测误差与模型复杂性(在我们的例子中,多项式的次数)的关系

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

作者图片

从上面的图表中,我们可以看到,随着模型复杂度的增加[1 度、2 度、5 度、20 度],训练误差趋于减小。

但预测误差在一定程度上减小,当模型变得更复杂时,预测误差会增大。

在训练误差和预测误差之间存在权衡。在两条曲线的末端,一端有高偏差,另一端有高方差。因此,在偏差和方差之间存在一个折衷,以实现理想的模型复杂性。

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

作者图片

什么是偏差-方差权衡?

偏向

假设 f(x)是真实模型,f̂(x)是模型的估计值,那么

)= bias(f̂(x)

偏差告诉我们期望值和真实函数之间的差异。

E[f̂(x)] →模型的期望值。

如何计算模型的期望值?

我们建立模型())使用相同的形式(例如。多项式次数 1)在从训练数据中抽取的不同随机样本上。然后我们将计算所有函数的期望值,记为e[f̂(x)】

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

作者图片

在上图中,橙色拟合曲线是对从训练数据中抽取的不同随机样本执行的所有复杂模型(度数=20)的平均值。

在上图中,绿色拟合线是对从训练数据中抽取的不同随机样本执行的所有简单模型(度数=1)的平均值。

从上面的图中,我们可以看到简单模型有很高的偏差。因为平均函数离真实函数很远。

复杂模型具有较低的偏差。它们完全符合数据。

差异

方差告诉我们一个 f̂(x 与 E(f̂(x)).模型的期望值有多大的不同

variance(f̂(x))= e[(f̂(x)]-e[f̂(x)]]

因此,对于复杂的模型,方差往往更高,因为训练样本中的微小变化将导致不同的 f̂(x).因为复杂的模型,把数据点背下来。

对于简单的模型,在 f̂(x 不会有太大的区别),如果我们稍微改变一下训练样本。简单的模型概括了这种模式。

所以,根据偏差和方差,我们可以说,

简单模型可能具有高偏差和低方差。
复杂模型可能具有低偏差和高方差

偏差和方差之间有一个权衡,因为两者都会导致误差。

预期预测误差

预期预测误差取决于三个误差

  1. 偏见
  2. 差异
  3. 噪声(不可约误差)

预期预测误差公式

EPE=偏差+方差+不可约误差

使用模型 f̂(x),我们预测不在训练数据中的新数据点(x,y)的值。

那么期望的均方误差将是

EPE =E[(y-f̂(x) ]

从 EPE 公式中,我们知道误差取决于偏差和方差。

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

作者图片

所以,从上面的情节来看

  1. 当偏差高时,预测误差高。
  2. 当方差高时,预测误差高。
  • 一次多项式→训练误差和预测误差高→ 欠拟合
  • 2 次多项式→训练误差和预测误差高→拟合不足
  • 5 次多项式→训练误差较小,并且训练误差和预测误差之间的差异较小。→ 最佳拟合
  • 20 次多项式→训练误差较小,预测误差很大→过拟合

关键要点

  • 简单模型可能具有高偏差和低方差。
  • 简单的模型会更加通用,有时会显得不够合适。
  • 复杂模型可能具有高方差和低偏差。
  • 复杂的模型会记住数据,并且倾向于过度拟合。
  • 最佳拟合模型将具有低偏差和低方差。

感谢阅读,我希望你们都喜欢它。

如果你喜欢看我的更多教程,就关注我的 LinkedIn 推特

点击这里成为中等会员:https://indhumathychelliah.medium.com/membership

有偏见的 AI,引擎盖下的一个眼神

原文:https://towardsdatascience.com/biased-ai-a-look-under-the-hood-5d0a41968f16?source=collection_archive---------17-----------------------

受偏见困扰的人工智能系统到底是怎么回事?

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

Pawel Czerwinski 在 Unsplash 上的照片

人工智能(AI)中的偏见问题最近成为许多负面头条。这些报告表明,人工智能系统有可能无意中歧视敏感的子群体。例如,一家国际技术公司开发的人工智能招聘系统被发现系统性地偏向男性申请人,而不是女性申请人。在这篇文章中,我将揭示一些当人工智能变成流氓时发生的内部过程。它的灵感来自于我发表的一篇关于这个主题的研究论文。[1]

为了更好地理解这个问题的背景,让我们首先介绍一些关于机器学习的基础知识。与传统编程相比,一个主要区别是算法决策背后的推理不是由人类明确编程的硬编码规则定义的,而是通过示例数据学习的:数千个、有时数百万个参数在没有人类干预的情况下得到优化,最终捕获数据的广义模式。由此产生的模型允许对新的、未知的数据进行高精度的预测。

请举例

为了说明这个概念,让我们考虑一个关于保险索赔中欺诈检测的示例场景。核实保险索赔的合法性对于防止滥用是至关重要的。然而,欺诈调查对保险公司来说是劳动密集型的。此外,对于某些类型的保险,许多索赔可能同时发生,例如,由于影响整个地区的自然灾害。另一方面,对于投保人来说,补充检查可能很烦人,例如当他们被要求回答进一步的问题或提供额外的文件时。双方都对快速决策感兴趣:客户期待及时的补救措施,而公司试图保持低成本。因此,加速这项任务的人工智能系统可能会非常有用。具体地说,它应该能够可靠地识别合法的保险索赔,以便能够迅速付款。潜在的欺诈案例也应该被可靠地检测到并标记出来,以便进一步调查。

你的 AI 表现如何?

现在,让我们深入研究一下技术细节。为了评估这种分类器的性能,我们通常将预测输出ŷ与真实输出值 Y 进行比较。在索赔数据中,输出值 1 代表欺诈索赔,而 0 代表合法索赔。下表包含我们正在运行的示例的示例预测。

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

与预测相反的真实输出等级 yŷ

为了更好地说明,请在下面的动画中找到相同的结果。黑点对应于负样本( Y =0),这里是实际合法声明。白点代表正样本( Y =1),在本场景中为实际欺诈索赔。红色大圆圈构成了分类器的边界:圆圈外的点被预测为阴性/合法(ŷ= 0),圆圈内的点被预测为阳性/欺诈(ŷ= 1)。不同的背景颜色进一步显示了分类器的正确位置(浅绿色和深绿色),以及错误位置(浅灰色和深灰色)。

值得注意的是,在这个过于简单的二维例子中,画一个理想的边界来分隔黑白点,从而定义一个完美的分类器是显而易见的。然而,在高维真实世界用例中,几乎不可能获得错误率为零的完美分类器;优化始终是一个权衡的问题。

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

示例场景的图形表示。作者制作的动画。

结束混乱

所谓的“混淆矩阵”有助于可视化和计算通常用于检查 ML 模型性能的统计测量。矩阵的行代表实际的输出类,在我们的例子中是 0 或 1。这些列表示给定分类器预测的输出类。预测类别对应于实际类别的单元格包含正确分类的实例的计数。只要类别不同,分类器就会出错,数字代表分类不正确的样本。

在抽象层次上,单元格中的数字通常由下表中提供的术语来标识。

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

混淆矩阵模式

以运行示例中的数据为基础,相关的混淆矩阵如下所示。正如您所注意到的,给定的分类器正确预测了 9 个欺诈性声明和 30 个合法声明。然而,它也错误地预测了 12 项索赔是合法的,实际上是欺诈性的,12 项索赔是欺诈性的,实际上不是。

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

样本数据的混淆矩阵

重温上面的动画插图,我们进一步认识到图式中的彩色片段对应于混淆矩阵中的不同单元:真阳性(浅绿色)、假阳性(浅灰色)、真阴性(深绿色)和假阴性(深灰色)。

把公式拿来!

从混乱矩阵中,我们可以提取大量有趣的统计测量。首先,我们对数据集中的实际阳性进行计数。这个数字是真阳性和假阴性的总和,假阴性可以被视为遗漏的真阳性。同样,实际阴性的数量是真阴性和假阳性的总和,假阳性也可以被视为遗漏的真阴性。在我们的示例中,这些数字代表实际欺诈索赔和实际合法索赔的数量。

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

实际阳性§和实际阴性(N)

(阳性)基本比率,有时也称为患病率,代表实际阳性相对于整个数据集的比例。在我们的示例中,该比率描述了数据集中实际欺诈索赔的份额。

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

基本利率

真阳性率真阴性率分别描述正确分类的阳性和阴性实例在其实际发生时的比例。在本例中,真实肯定率描述了被检测到的所有实际欺诈索赔的份额。真正的负比率是成功发现的实际合法索赔的份额。

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

真阳性率(TPR)和真阴性率(TNR)

错误发现率描述了所有肯定预测的误分类肯定分类的份额。因此,它是关于被错误识别或发现的积极分类实例的比例。相反,假漏检率描述的是假阴性预测占所有阴性预测的比例。这些实例实际上是积极的,但被忽略了——它们被错误地忽略或省略了。在我们的示例中,错误发现率是被归类为欺诈的所有索赔的错误率。虚假遗漏率描述了所有被归类为合法的索赔中实际欺诈性索赔所占的份额。

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

错误发现率(FDR)和错误遗漏率(FOR)

存在大量的其他统计方法来评估 ML 模型的性能。然而,为了证明人工智能的偏见,上面介绍的指标已经足够了。

你忽略了一些东西

到目前为止,我们将数据作为一个群体进行分析,没有考虑数据中可能存在的敏感亚组。然而,由于最大似然算法的决策通常会影响人类,许多数据集包含敏感的数据子群。例如,这种分组可以按性别、种族或宗教来定义。为了分析一个分类器是否有潜在的偏差,我们增加了这个额外的维度,并根据这个敏感属性将结果分成子组。这允许调查它们之间可能的差异。任何这种偏离都可能是对一个敏感群体的歧视。

我们现在检查我们的运行中的保险欺诈检测的例子。来自训练模型的输出保持不变,但是这一次我们假设数据中有两个敏感的亚组,例如我们将数据分成男性和女性。

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

敏感子群的独立混淆矩阵

我们注意到,两个亚组中的基本比率(BR)是相同的,这意味着在这个例子中,男性和女性提出欺诈性(或合法)索赔的可能性相同。然而,男性的真实负比率(TNR)为 0.79,而女性为 0.57。这意味着 79%由男性提出的有效索赔被正确归类为合法,而对于女性来说,只有 57%的同类索赔是合法的。另一方面,男性的错误遗漏率为 24%,女性为 38%。因此,在我们虚构的示例场景中,女性提交的欺诈性索赔比男性提交的欺诈性索赔更有可能不被发现。

那又怎么样

当一个敏感亚组与另一个敏感亚组之间的统计测量值(如上所述)存在显著差异时,就出现了 AI 偏倚。换句话说,当系统对不同的群体表现不同时,它是有偏差的。由于大多数机器学习算法的黑盒性质,特别是在输出不能由人眼直接评估的应用领域(例如分数),这个问题可能会在很长时间内不被注意。然而,由于人工智能对人们生活的影响越来越大,因此必须检测和减轻人工智能偏见,以防止对来自敏感亚群体的个人的系统性不平等待遇,并确保负责任地使用人工智能。

既然我们对有偏见的人工智能到底出了什么问题有了更清晰的认识,我们可以把注意力转向问题的根源。在我的下一篇文章中,我深化了这些偏见到底来自哪里的问题。

非常感谢 Antoine Pietri 为撰写本文提供的宝贵支持。除非另有说明,所有图片均为作者所有。

参考

[1] B. Ruf 和 M. Detyniecki,《走向人工智能中的正确的公平》 (2021),ECML/PKDD 工业追踪。

有偏数据及其处理方法

原文:https://towardsdatascience.com/biased-data-and-how-to-deal-with-it-fdaeb9da3b20?source=collection_archive---------25-----------------------

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

Edge2Edge 媒体Unsplash 拍摄的照片

欠采样的故事

我的一个学生刚刚完成了一个涉及分类的数据科学荣誉项目——或者至少他认为他完成了。他收到了波士顿地区大约 2000 名学生和大约 700 名企业家发布的几千条推文。他必须训练一个 ML 模型(RandomForestClassifier)来预测一条推文是由学生还是由企业家发布的。听起来很容易。他随机选择了 70%的推文用于训练,其余的用于测试。这个模型看起来很有效,准确率达到了 83%——对于一个课程项目来说,这已经很不错了。

不幸的是,该模型非常擅长识别学生推文(95%的准确率),但识别企业家推文(55%的准确率)却相当糟糕。为什么?因为训练数据集有大约 1400 名学生,只有大约 500 名企业家。换句话说,它偏向于学生,并学会了如何更好地识别他们的推文。

修复训练数据集的一种方法是为每个结果提供相等或大致相等数量的样本。如果我们在培训数据中只有大约 500 名企业家,那么我们也应该只包括大约 500 名学生,除非我们的目标是扭曲培训过程。Python 中最流行的数据分析包 Scikit-Learn 没有无偏倚的训练/测试分裂功能。但是我们可以自己造一个。

假设 X 是一个 Pandas 数据框架,它包含我们整个数据集的特征(预测)和结果。特征在列 x1 中…xN 和结果在 y 列。首先计算支持每个结果的样本数:

from numpy.random import binomial
np.random.seed(0)
# Generate synthetic dataset with three outcomessamples = 100
X = pd.DataFrame({"x1": binomial(1, 0.3, samples),
                  "x2": binomial(1, 0.6, samples),
                   "y": binomial(2, 0.5, samples)})grouper = X.groupby("y")
sizes = grouper.size()
#0 26 <- the smallest
#1 46
#2 28

假设我们仍然希望从最小的组样本中选择 70%用于训练,并从较大的组中选择匹配数量的样本。我们可以计算来自较大组的样本的百分比,以匹配最小组的 70%。这些百分比是选择样本的概率:

fracs = (sizes.min() * 0.7) / sizes
#0 0.700000 <- the smallest
#1 0.395652
#2 0.650000

现在我们知道了概率,我们可以使用二项式分布(np.random.binomial)及其布尔补码来分别随机选择训练和测试样本。当我们在相同结果的组中循环时,我们将在两个最初为空的数据帧中累积样本:

test  = pd.DataFrame()
train = pd.DataFrame()for grp, data in grouper: # reuse the grouper!
    mask = binomial(1, fracs.loc[grp], data.shape[0]).astype(bool)
    train = train.append(data[mask])
    test  =  test.append(data[~mask])

现在,对于每个结果,训练数据集中的行数大致相同。训练数据集是平衡的,不偏向任何特定的结果:

train.groupby("y").size()
#y
#0    21
#1    20
#2    23

在该数据集上训练的模型将会看到属于这三个类的大约相等数量的样本,并且不会有偏差。

我们是否也应该均衡不平衡的测试数据集?很可能不是:您只将它用于测试,它的偏差不应该是一个问题。

大数据和新冠肺炎:数据可视化的一年

原文:https://towardsdatascience.com/big-data-and-covid-19-a-year-in-data-visualizations-ea78cd6c21cc?source=collection_archive---------24-----------------------

我们对新冠肺炎的看法是如何通过数据可视化随着时间的推移而演变的

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

回到未来——多洛瑞恩作者:杰森·梁

尽管新冠肺炎疫情在过去的一年中有许多负面影响,但它已经在数据可视化领域引发了创造力的爆发。图形设计师、研究人员和其他数据爱好者已经将他们的才能用于公共利益,以清晰和解释性的图形呈现与新冠肺炎相关的大数据。从基础到互动地图,从彩色到非典型图表,你可能已经看到了数百个与新冠肺炎相关的数据可视化。

**但是你有没有注意到他们是如何模仿我们对冠状病毒的认识的?**事实上,随着时间的推移,数据可视化已经与我们一起发展,同时帮助我们——普通人、记者、政治家——更好地了解正在发生的事情。在本文中,我想带我们回到 2020 年初,追溯数据可视化的发展以及这种新型冠状病毒的传播。你准备好出发了吗?我们走吧!

1.记录和跟踪新冠肺炎病例

从 2019 年底开始,一些网站开始收集世界各地的数据,以集中这种新型病毒的传播数据。汇总数据使研究人员、媒体和公众能够更广泛地了解情况,而不必掌握语言和从几十个国家寻找原始数据来源。

关于记录和更新每日与新冠肺炎相关的病例和死亡人数的先驱之一是 Worldometer 网站。除了致力于计算地球上居住人数的实时计数器,该网站还开发了一个非常可靠的冠状病毒部分。正如他们自己解释的那样,他们“从官方报告中收集数据,直接从政府的沟通渠道收集数据,或通过被认为可靠的当地媒体来源间接收集数据”。尽管 Worldometer 的设计相当基础,但它经常被世界各地的媒体和机构作为可靠的数据来源。

这些机构中包括位于马里兰州巴尔的摩的约翰霍普金斯大学。2020 年 1 月 22 日,他们首先发布了一张全球地图来追踪与新冠肺炎相关的病例和死亡。这个最初的项目后来发展成为约翰·霍普金斯冠状病毒资源中心(CRC),该中心包括“260 多个来源”,在美国的行动范围更广(如检测、追踪、疫苗)。

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

约翰·霍普金斯大学系统科学与工程中心(CSSE)的新冠肺炎仪表板

2.了解最新的新闻

数据可视化也有助于说明我们的社会必须克服的众多挑战。从谷歌趋势到疫苗,它们让我们更好地理解想法和传达关键信息。

从谷歌搜索词开始,我想起了 Alberto Cairo 在 2020 年 1 月至 4 月期间在网站上进行的这项研究。作者调查了美国与冠状病毒相关的顶级搜索趋势,并从中构建了富有洞察力的可视化效果。这里有一个例子:随着时间的推移,我们看到搜索从“什么”搜索演变而来,比如“什么是疫情?”更务实的问题,如“如何使用缩放?”。

在试图理解感染对我们社会的影响时,以创新的方式可视化数据将帮助我们更好地理解一些文章的观点。例如,这篇纽约时报的文章用一个相当基本的散点图制作了一篇互动文章:基于两个维度(接触疾病和与他人的身体接近)的感染概率。在这里,技术的使用支持了作者的说法,因为它迫使读者向下滚动页面继续阅读,从而积极地让读者参与进来。

随着时间的推移,关于社会距离的问题出现了:在他们的“电晕模拟器中,来自华盛顿邮报的作者通过动画展示了各种社会距离措施(从“免费开放”到强制隔离)如何有助于平坦化感染曲线。在那个时代,社交距离对我们大多数人来说都是一个新概念,如此强大的可视化功能清楚地表明,这是摆脱疫情的一种方式。

最近发布了新的“数据追踪器”来追踪世界各地新冠肺炎疫苗接种的进展。来自我们的世界数据的图表就是一个很好的例子。它们是基于开源数据(查看他们的 GitHub 知识库这里)并以图表形式展示了世界上每天服用的新冠肺炎疫苗剂量。对我来说,这个网站的优势在于你可以轻松地在不同的指标(病例、死亡、检测、疫苗接种)和不同类型的图表(线图、世界地图、数据表)之间切换,以便可视化你正在精确寻找的内容。

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

新冠肺炎数据浏览器关于疫苗接种的数据我们的世界

3.退一步看全局

在后新冠肺炎时代,数据可视化的另一个主要方面是透视。尽管有悲惨的消息,数据可视化也可以帮助我们把每天的数字放到一个更广阔的背景中。

当我们正在经历有生以来第一次全球性的疫情时,我们可能会忘记人类历史上曾经发生过次大流行病——而且它们造成的损失要大得多。这就是为什么我觉得这张由 Data Visualist 制作的信息图特别发人深省。当然,目前的疫情是致命和令人担忧的,但时至今日,艾滋病毒已经造成更多的死亡,而我们还没有任何疫苗来对抗它。

最终,通过将多个数据可视化汇总到仪表板中,可以更好地理解疫情。这就是一些网站所做的,将所有与新冠肺炎相关的当前数据集中在一个地方。尽管在图表的选择和呈现方式上存在潜在的偏见,但这些仪表板允许读者从许多数据源中获得最多的信息。与已经格式化的文章相比,它们为读者解释留下了更多的空间,因此每个人都可以从显示的许多图表中得出自己的结论。

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

新冠肺炎数据仪表盘由信息漂亮

结论:回归基础

你喜欢这趟旅程吗?我刚刚向你们展示了一年多来与新冠肺炎·疫情相关的数据可视化。现在,当你遇到一个新的数据可视化时,我想给你一些建议,特别是如果它与冠状病毒这样的“热门话题”有关。

在我看来,在考虑任何数据可视化时,有两个主要问题需要考虑,无论它是否与新冠肺炎有关:

  • 数据来源:使用的数据来自哪里?来源可靠吗(政府、知名机构……)?
  • 图表真实性:你是否发现了作者可能用来误导读者的潜在偏见?

一旦你确定这两个条件都令人满意地满足,享受数据即!

信用

你喜欢读这篇文章吗? 成为 的一员,加入一个不断成长的充满好奇心的社区吧!

大数据管理:数据存储库策略和数据仓库

原文:https://towardsdatascience.com/big-data-management-data-repository-strategies-and-data-warehouses-bfa9b45c95de?source=collection_archive---------19-----------------------

介绍

管理大量结构化和非结构化数据对于每个需要系统化组织和治理以确保其数据高质量并适合分析和商业智能应用的公司的成功至关重要。虽然大数据的关键方面可以概括为流行的 3 个 v,即容量、速度和多样性,但在选择存储和转换数据所需的适当流程时,每个公司还需要问其他一些关键问题。

大数据方面

Volume: 传入的数据流有多大,需要多大的存储量?

**速度:**指的是数据生成的速度和需要访问的速度。

**品种:**数据需要以什么格式存储?结构化(如表格)或非结构化(如文本、图像等)。

**值:**存储所有数据得出什么值?

**准确性:**数据来源、类型及其处理的可信度如何?

**粘度:**数据如何在流中流动,阻力和可加工性如何?

**病毒式:**数据在网络上分发的能力及其在用户间的分散率

大数据管理

由于企业数据存储呈指数级增长,管理大数据已成为一项越来越具有挑战性的任务。跨行业研究表明,大多数组织在决策分析中只使用了一半的结构化数据和近 1%的非结构化数据。许多组织倾向于保留尽可能多的数据,因为没有办法预测哪些数据源在未来会有价值。[1]

他们经常会发现过时的数据或与其他系统中的其他副本发生冲突,并且由于有如此多的数据源可用,实施高效的数据管理技术可能是一项繁琐的任务。数据分散可能会导致跨多个位置维护记录,并带来重复的风险,从而导致管理成本增加和安全策略不一致。

没有数据管理战略会导致缺乏信任、错失良机、客户满意度下降,以及违规和监管处罚。由于这些原因,组织倾向于通过投资能够帮助他们满足需求的策略和大数据工具来实施数据管理原则。

大数据管理可以被视为一个宽泛的术语,包括数据清理、集成、迁移、准备、丰富、分析、质量、管理、报告、治理和规划。根据企业的需求,每个流程的关注点和资源分配可能会有很大的不同。

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

图一。从数据收集到预测分析

数据存储策略

通过将数据集中在一个引用元数据和单个逻辑名称空间的系统中,数据存储库可以成为解决数据管理挑战的一个很好的解决方案。它们用于将特定的数据群体隔离在一个或多个数据存储实体中,以挖掘数据用于业务洞察、报告需求或机器学习。这个术语经常与数据仓库或数据集市一起使用,它的主要好处是由于数据被隔离,使得报告或分析更容易。

一个有效的数据存储库策略需要一个一致的策略来统一、管理、评估和部署大量的数据资源。这将增强数据管理功能,最终提高分析和查询性能。

定义数据存储库策略的第一步是阐明组织数据目标的主要目的,这将指导他们的数据管理方法。健壮的数据策略包含几个要素。这包括创建一个覆盖整个企业的数据架构,定义业务需求,并确定数据质量和集成的优先级。此外,它还通过定义数据保留标准以及降低风险和复杂性来实现问责制。[2]

在实施数据策略时,公司面临着多种方法,他们的决策是基于组织的可用资源或以前的经验。虽然有些策略有助于组织确保管理数据隐私和通过内部来源分发的数据的完整性的指导原则,但其他策略可能更侧重于通过创建快速框架来支持业务决策,这些框架提供实时快速洞察、预测性建模和交互式仪表板。虽然大多数公司需要这两种方法的平衡,并选择灵活性来取得成功,但有些公司会更加强调一种具有适当权衡的方法。

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

图二。决定数据策略时的关键因素

数据仓库

企业数据仓库

企业数据仓库(EDW)可以概括为一个面向主题的数据库或一组数据库,这些数据库将来自多个来源和应用程序的数据收集到一个集中的来源中,以便进行分析和报告。它存储和管理企业的所有历史业务数据。[3]组织、转换和聚合数据源的各种输入可以为人工智能(AI)就绪数据结构节省宝贵的时间和管理成本。

这是提取、转换、加载(ETL)或 ELT 方法经常使用的地方,Hadoop 或 Apache Spark 等大数据分布式框架帮助组织进行繁重的数据清理和转换。

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

图 3。数据仓库概述

数据仓库和标准操作数据库之间的关键区别在于,后者经过优化以保持实例中的精确准确性,并跟踪快速数据更新,而数据仓库则提供随时间变化的大范围数据视图。尽管数据仓库是管理大数据的常用工具,但当组织需要扩展它们时,它们会变得非常昂贵,并且在处理非结构化或复杂的数据格式时,它们的性能也不好。

EDWs 的架构复杂性为组织提供了许多好处:

  1. 将多个数据源集成到单个数据库中,用于单个查询
  2. 维护数据历史,提高数据质量,保持数据一致性
  3. 为整个企业的多源系统提供一个集中视图
  4. 重构数据以提高复杂查询的性能

数据集市

虽然数据仓库(DW)可以有效地处理大型数据集,但实时人工智能和针对不同业务运营子集的数据分析需要使用数据集市(DM)。DMs 可以被认为是 DWs 的缩小版本,具有更有限的范围或它们的逻辑子集,旨在满足不同业务单位或部门的特定最终用户群的信息需求,并且通常为重点内容或定制的决策支持提供聚合数据。它们有相互依赖和相互独立的格式,前者从 EDW 中填充,后者直接从操作数据存储(ODS)中获取。

DM 减少了来自组织中其他数据源的查询、转换和繁重网络使用的负载,并为最终用户提供了一个定制的 DM,使他们能够进行更多的访问和控制。DMS 还会带来一些固有的问题,如信息孤岛和限制用户访问。

数据湖

数据湖(DL)是另一种类型的数据存储库,它的一个关键区别是数据以原始格式存储,没有任何转换。数据可以是结构化的,也可以是非结构化的,这使得 DLs 适用于批量数据类型,如服务器日志、点击流、社交媒体或传感器数据。

数据只是存储在存储库中,不知道将进行什么类型的分析,也不知道它是否会在分析中使用。当数据需要用于业务洞察时,这反过来将需要大量的预处理。

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

图 4。数据湖的简单表示

由于 DLs 更具开源性和未定义的结构,因此其存储成本更低,并且可以建立在具有内部管理的组织数据中心或不同供应商(如 Amazon、Microsoft 或 Google)的云服务中。

虽然数据仓库的目标是已经进行了转型的决策者,但数据仓库需要专业的数据科学家来预处理和分析数据,他们可以改善客户交互、R&D 创新并提高运营效率。

交易型商店

事务数据存储(TS)针对基于行的操作进行了优化,例如在维护数据完整性的同时读写单个记录。然而,它们并不是专门为分析而构建的,但由于它们在生产环境中已存在多年,因此可以用于分析查询以及低延迟信息监控。

TSs 是 ACID(原子性、一致性、隔离性、持久性)兼容的,这意味着尽管有错误,它们也能保证数据的有效性,并确保数据不会因为某种故障而损坏。这对于需要高度数据完整性的业务用例至关重要,例如银行交易。

TSs 设计为在生产系统中运行,由于其基于行的低延迟特性,可以运行需要与主数据库几乎同步的操作或查询。虽然 dw 由于其基于列的特性而被优化用于读取数据,但是 ts 在写入时性能更好。对于拥有少量数据的公司来说,这可能不是一个大问题,但随着可用数据的增加,这可能会在选择正确的数据策略方面产生影响。

操作数据存储

操作数据存储(ODS)是减轻从 DWs 中查询最新数据的挑战的另一种方法,可以被视为提供查询功能的临时区域。ODS 可以提供更接近实时的细粒度非聚合数据,因为它是在繁重的转换和加载操作之前接收的,从而减轻了事务性系统的负担。它们用于运营报告,并作为 EDWs 的补充元素。

它们的一般目的是通过数据清理、解决冗余和建立业务规则,将不同来源的数据集成到一个单一的结构中。ODS 可以是 EDW 的关键组成部分,并且由于其多用途结构,可以实现事务和决策支持处理。存储在 ODS 中的数据是面向事务的,与 DWs 相比,其大小更小。[5]

结论

大数据管理是每个公司的必需品。它提高了他们对客户的理解和开发新产品的创新能力,同时由于对每个部门的大量数据进行分析,使他们能够做出重大的财务和业务决策。建立数据策略需要定义问题并了解每个公司的业务需求,以改进他们的数据系统和源管理。

尽管并非所有公司都需要在一开始就开始担心大数据管理,但当传统数据库表现不够好,无法提供大数据存储库的优势时,就需要开始考虑这一点。当竞争优势、创新、收入增长和客户获取的各个方面都达到稳定水平时,这一点通常会变得很明显。

值得一提的是,每个数据存储库都有自己的缺点。一些公司通过存储所有数据来使用数据湖,而没有有效地利用每个部门的信息提取,这使他们的业务战略计划失败。将没有任何目标的数据转储到数据仓库将导致高管理成本,失去对存储内容的跟踪,并且不能利用新建立的资源。

在大多数情况下,数据策略可能不会在一夜之间提供商业价值,而是需要通过反馈和评估在每个阶段逐步改进。数据存储库并不能保证公司数据策略的成功;然而,它确实减少了常见故障场景的可能性、从数据中提取价值所花费的过多成本和时间,并为公司的未来创新指明了方向。

参考

  1. 你的数据策略是什么?关键是攻防平衡。莱安德罗·达勒姆勒和托马斯·达文波特(2017 年 5 月至 6 月)
  2. 让您的数据仓库井然有序,麦肯锡公司 2018
  3. 企业数据仓库:概念、架构和组件,2019
  4. “大数据质量日益重要”。数据圆桌会议。检索于 2020 年 6 月 1 日。
  5. 构建操作数据存储(第 2 版。),英蒙,威廉 1999

使用 Python 中的 Datashader 实现大数据可视化

原文:https://towardsdatascience.com/big-data-visualization-using-datashader-in-python-c3fd00b9b6fc?source=collection_archive---------0-----------------------

理解大数据

【Datashader 是如何工作的,为什么速度会如此之快?

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

图片来自https://examples.pyviz.org/opensky/opensky.html经许可

几个月前,我写了一篇关于我最喜欢的 Python Viz 工具——holo Viz 的文章。许多人有兴趣了解更多关于 Dashshader 的信息 HoloViz 家族中的大数据可视化工具。我非常喜欢 Datashader,喜欢 Datashader 如何快速创建大型数据集的有意义的可视化。因此,在本文中,我将带您浏览一个简单的 Datashader 示例,解释 Datashader 是如何工作的,以及它为什么这么快。

为什么大数据可视化很难?

以我的理解,大数据可视化主要有两个障碍。

  • 首先是速度。如果您使用常规的 Python 绘图工具来绘制我下面的例子中的 1100 万个数据点,将会非常慢,并且您的 Jupyter 内核很可能会崩溃。
  • 第二是画质。即使它没有崩溃,并且您愿意等待,大多数绘图库也会简单地将每个新数据点绘制为一个圆形或其他形状,这将导致过度绘图。在这种情况下,即使为重叠点添加 alpha 透明度也不总是有帮助。想象一下,在一幅图像上,你有许多点一个接一个地显示:你所看到的将是一个斑点,并且很难从这个斑点中提取信息。

Datashader 为这两个障碍提供了优雅且看似神奇的解决方案。接下来,我将向您展示一个示例,并探究其中的神奇之处。

使用 Datashader 的大数据可视化—示例

该示例来自 pyviz.org 的纽约市出租车数据示例。完整示例请参见https://examples.pyviz.org/nyc_taxi

  • 导入需要的包

conda install您的 Conda 环境中所需的软件包:

然后在 Python 文件中导入包:

读入数据

对于非常大的文件,您会希望使用像 Dask 这样的分布式处理库和 Datashader,但是这里我们有一个“只有”1100 万条记录的 Parquet 文件,Datashader 可以在使用 Pandas 的笔记本电脑上轻松处理它,而不需要任何特殊的计算资源。在这里,我们将加载两列来表示出租车的下车地点。

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

  • 绘图

在这里,我们使用 Datashader 绘制数据。我只用了 4 行代码和 6 毫秒的时间,用我的笔记本电脑绘制了 1100 万行数据,覆盖在纽约地区的地图上:

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

或者,不使用datashade函数,我们可以使用hvplotrasterize=True来使用 Datashader 应用栅格化。如此简单!我强烈推荐使用 hvplot 进行可视化。

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

如果您正在实时运行它,那么您将能够放大到此地图的任何区域,并且绘图会动态更新以使用该缩放级别的全分辨率。

【Datashader 是如何工作的?

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

图一。Datashader pipeline(图片经许可来自 Datashader)。

Datashader 使用五步管道将您的数据转化为绘图。 Datashader 文档说明了管道在每个步骤中是如何工作的——投影、聚合、转换、色彩映射和嵌入。我将把我前面的例子分解成这些小步骤,这样我们就可以确切地看到 Datashader 在幕后做什么。

让我们首先安装底层的 Datashader 函数,这样我们就可以运行各个步骤:

  • 投影

首先,我们为要投影的数据定义一个具有宽度和高度的 2D 画布。画布定义了我们希望在最终图像中看到多少像素,并可选地定义将映射到这些像素的x_rangey_range。此处,要绘制的数据范围未在画布中设置,因此它们将在下一步中根据数据框中数据 x 和 y 值的最大值和最小值自动填充。画布定义了投影的内容,但是为了加快速度,每个点实际上都是在聚合步骤中投影的。

  • 聚合

在定义了投影画布之后,我们将每个点投影到二维输出网格中,并聚合每个像素的结果。Datashader 支持这种聚合的许多选项,但在本例中,我们只是通过遍历数据点并在该点所在的位置增加像素,来计算有多少数据点投影到每个像素中。这种情况下的结果是一个计算每个像素衰减的二维直方图:

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

  • 转换(可选)

无论原始数据集有多大,上一步的结果现在都是固定大小的格网。一旦数据在这个网格中,我们可以对它进行任何类型的转换,比如只选择某个范围的计数,根据其他数据集或值的结果屏蔽数据,等等。在这里,衰减数据的范围从一些像素的零到其他像素的数万,如果我们试图直接绘制网格,我们只会看到几个热点。为了使所有不同的水平都可见,如上图所示,使用图像处理技术“直方图均衡化”对数据进行转换,以显示计数的分布,而不是它们的绝对值。直方图均衡化实际上被合并到下面的色彩映射步骤中,但是如果我们愿意,我们可以在这个阶段进行显式转换,例如对计数求平方:

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

  • 色彩映射

接下来,我们可以将入库的网格数据渲染到图像的相应像素。通过线性插值或自动变换(例如,通过对每个值调用对数函数,或如这里使用直方图均衡化),每个箱值被映射到色图中定义的 256 种颜色之一。这里我们使用 Colorcet 的“fire”色图,它从黑色开始,代表最低的计数(1 和 2 衰减),经过红色,代表更高的值(以百为单位),然后是黄色,代表更高的值(以千为单位),最后是白色,代表每像素的最高计数(在本例中为数万)。我们将背景设置为黑色,以便更好地显示数据。

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

  • 嵌入

如您所见,Datashader 只渲染数据,而不渲染任何轴、彩条或您在完整绘图中预期的类似特征。为了获得那些有助于解释数据的特性,我们可以将 Datashader 生成的图像嵌入到一个绘图中。最简单的方法是使用 HoloViews,这是一个高级绘图 API,它提供了使用 Matplotlib、Bokeh 或 Plotly 作为后端的灵活性。这是一个使用全息视图定义一个“点”对象,然后对所有点进行数据阴影处理的例子。在这里,我们演示了一个替代方法“光栅化”而不是“数据阴影”,这样 Bokeh 就负责变换和色彩映射步骤,并允许悬停和彩条工作。

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

为什么 Datashader 速度如此之快?

首先,我们需要谈谈原始数据格式。Datashader 非常快,以至于读入数据通常是最慢的一步,尤其是当您的原始数据是一堆 JSON 文件或 CSV 文件时。对于像 dropoff points 这样的列数据,Parquet 文件格式通常是一个很好的选择,因为它很紧凑,可以快速加载,只有效地读取您需要的列和范围,并在适当的时候支持分布式和核外操作。

第二,使用正确的输入文件格式,我们可以研究下一个最昂贵的任务,这是组合的投影+聚集步骤。这一步需要计算数百万个数据点中每一个的值,而所有后续计算都使用最终的固定大小的网格,因此速度更快。那么,Datashader 怎么做才能让这一步走得快呢?

  • Datashader 的聚合计算是用 Python 编写的,然后使用【Numba】即时编译成超快的机器代码。例如,这里是代码,在这里对每个箱子进行计数。
  • 上面的例子使用了一个 CPU,但是 Datashader + Numba 也支持 CUDA cudf 数据帧作为 Pandas 数据帧的替代,如果你有一个 GPU,它会运行得更快。
  • Datashader 还可以并行化其管道(代码示例),以便您可以利用所有可用的计算核心,扩展到更大的数据集,并提供更快的结果。

因为 Datashader 非常快,我们实际上可以交互地可视化大数据,无论何时缩放或平移,都可以动态地重新绘制。这里有一个示例,您可以在面板仪表盘中交互查看纽约市出租车数据。我最喜欢的关于船舶交通的例子说明,即使你看到的只是 Datashader 渲染的像素化图像,你仍然可以检查单个数据点并理解你所看到的。examples.pyviz.org 的另一个例子展示了大得多的文件的数据散列,在一台普通的笔记本电脑上高达数十亿个点。

在哪里可以了解到更多关于 Datashader 的信息?

总之,本文向您展示了一个使用 Datashader 可视化 1100 万行坐标数据的示例,并解释了为什么 Datashader 能够如此快速地生成有意义的可视化效果。值得注意的一点是,Datashader 可以用于任何类型的数据,而不仅仅是上面例子中的地理点。我强烈推荐看看 Datashader.org 大学的许多好例子。

确认

非常感谢 Jim Bednar 对本文的指导和反馈。

参考文献

【https://examples.pyviz.org/nyc_taxi/nyc_taxi.html

https://datashader.org/getting_started/Pipeline.html

http://numba.pydata.org/

大数据和机器学习

原文:https://towardsdatascience.com/big-ger-data-and-machine-learning-71104e3c229f?source=collection_archive---------35-----------------------

探索我的电脑在这个领域的极限

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

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

最近,我在一个项目中面临着越来越多的数据——达到了千兆字节。在使用我的雇主提供的工具时,我很好奇:如果我在我的家用机器上工作,并且只能访问免费资源,会怎么样?

**TL / DR: PySpark 在 25%的时间里做两倍于 Python 的工作,PySpark 的优势受限于一个用户的机器。**超越这一点意味着转向云提供商(未来文章的重点)。

语境

在一个令人筋疲力尽的工作周结束时,我选择了 Coursera 大数据专业的天气 csv 数据集。该数据集包含气压/温度、风速/方向和雨水累积/持续时间,所有这些都是为了预测相对湿度。

这个监督学习问题使用了一个 123 MB 的数据集:远小于我在工作中处理的数据集,但我可以轻松地从我的家用电脑开始使用它来评估不同的工具。

本文的带有代码和数据集的 GitHub repo 是这里的。

方法和工具

Python

我决定比较使用 PySpark 和 Python 的方法。我在这里的重点不是特征工程或选择;我的其他故事涵盖这些话题。

在使用 pandas read.csv 读入数据集后,我定义了 x 和 y 数据帧。在测试训练分割之后,进行了 5 重交叉验证,在 max_depthlearning_rate 超参数上执行网格搜索。

from sklearn.model_selection import GridSearchCV, KFold
from sklearn.metrics import mean_squared_errorcv = KFold(n_splits=5)gbr_param_grid = {"max_depth": [2,10], "learning_rate" : [0.01, 0.1]}gsXGBr = GridSearchCV(gbtr, gbr_param_grid, cv = cv, scoring='neg_mean_squared_error', refit =  True, verbose=True ,return_train_score=True)gsXGBr.fit(xtrain,ytrain)XGB_best = gsXGBr.best_estimator_ypred = XGB_best.predict(xtest)import numpy as npnp.sqrt(mean_squared_error(ytest,ypred))

这个脚本需要多长时间?2459 秒或者说不到 41 分钟。只是为了在我的 6 核 12 GB 内存惠普 Pavilion 上回归。

PySpark

Apache 的 Spark 是处理大型数据集的便利工具。它最初是用 Scala 编写的,PySpark 为我们提供了一个 API,用于在 Python 中使用 Spark 的功能。

这篇文章可以方便地安装 Spark 并使其运行。使用下面的代码测试 PySpark 的成功安装。

%pip install findspark*import findspark
findspark.init()*

SparkSession 是一个方便的入口点,它结合了 SparkContext 和 SQLContext 等其他命令授予的访问权限。虽然我通常使用 SparkSession,但我将使用 SparkContext,这样我可以首先为这个 stackoverflow 线程配置可用内存。

from pyspark.sql import SparkSession
from pyspark import SparkConf, SparkContext, SQLContextconf=SparkConf()
conf.set("spark.executor.instances", "4")
conf.set("spark.driver.memory", "10g")sc = SparkContext.getOrCreate(conf)spark = SQLContext(sc)

在读入数据集之前,我单击了创建的 SQLContext 的用户界面,并查阅了 Executors 选项卡。在 Spark 中,执行器执行实际的计算工作,并由驱动程序管理。

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

图 1: Spark UI 执行器选项卡。图片作者。

我只有一个执行器,即驱动程序,因为我运行在本地模式。随着代码的运行,我可以保持这个窗口打开,观察内存和磁盘空间的使用如何随着代码的运行而变化。我还确保使用了主 URL 下面星号所暗示的所有可用线程。

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

图 2:主 URL。图片作者。

为了方便起见,我放弃了一些功能——详见 repo 现在我将构建机器学习模型。

from pyspark.ml.regression import GBTRegressorgbtr = GBTRegressor(labelCol='relative_humidity')train,test = df_no_date_row_no_null.randomSplit([0.6,0.4])

您将观察 Python 的机器学习和 PySpark 的机器学习库(MLib)包之间的语法差异。我发现后者稍微麻烦一点,但我希望它会随着时间的推移而逐渐消失。

from pyspark.ml.tuning import CrossValidator, ParamGridBuilder
from pyspark.ml.evaluation import RegressionEvaluatorparamGrid = ParamGridBuilder().addGrid(gbtr.maxDepth, [2, 10]).addGrid(gbtr.stepSize, [0.01, 0.1]).build()rg = RegressionEvaluator(metricName="rmse",  labelCol=gbtr.getLabelCol(),
predictionCol=gbtr.getPredictionCol())cv = CrossValidator(estimator=gbtr,evaluator=rg,numFolds=5, estimatorParamMaps=paramGrid)from pyspark.ml.feature import VectorAssemblerfeatures_input = (df_no_date_row_no_null.drop('relative_humidity')).columnsdassember = VectorAssembler (inputCols = features_input, outputCol='features')df_feat = dassember.transform(df_no_date_row_no_null)from pyspark.ml.pipeline import Pipelinepl = Pipeline(stages=[dassember,cv])
Model = pl.fit(train)
Pred = Model.transform(test)
rg.evaluate(Pred)

repo 中的代码还包括对分类器的训练和评估。

H 使用 PySpark 进行回归和分类需要多长时间? 698 秒或略多于 11.5 分钟。

外卖

PySpark 更快的内存处理显示:大约是 Python(仅分类)25%时间的两倍工作(回归和分类)。

不过,在一天结束时,我只使用了我的 12gb RAM 机器的资源,尽管通过 PySpark 的多核更有效。如果我通过云使用 Linux 和其他计算资源,我可以使用 Apache Livy

我将转向微软 Azure 的免费层来探索这里的选项,包括数据块。我试图注册社区版,但目前看到该产品已关闭。

我将在随后的文章中介绍我对 Azure 和 Databricks 的测试。一如既往,我欢迎任何反馈。

BigQuery Hack:灵活查询任意数量的列

原文:https://towardsdatascience.com/big-query-hack-flexible-queries-for-any-number-of-columns-713fa0c6f6a5?source=collection_archive---------12-----------------------

理解大数据

如何使用 BigQuery 处理多列的表?下面是如何使用脚本和表元数据。

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

BigQuery 很棒,但是它如何处理有很多列的表呢?尤其是当我们甚至不知道有多少列的时候?(图片来源:伊尔泽·奥尔塞尔)

BigQuery (BQ)是一个 Pb 级的专有谷歌数据仓库产品。在我的工作中,几乎每天我都使用 BQ 来处理数十亿行数据。但有时,棘手的情况会出现。例如,如果我的表有大量的行和列,该怎么办?BQ 是如何处理的?

与所有其他 SQL 语言一样,除了一些语法技巧,如*EXCEPT,每个查询都要求我们手动输入所有所需列的名称。但是,如果我有一个有数百列的表,我想计算,比如说,所有的成对相关,该怎么办呢?使用CORR功能,我不需要手动输入 100 个✕100 ~ 10000/2 组合吗?

当然,我可以利用 BASH/python 来获取列名,并运行一些特殊的脚本来完成这项工作。但是,如果我们可以避免设置不同的连接器,并在 BQ 中本地完成所有工作,这不是很好吗?

感谢 BQ 的脚本功能和表元数据,事实证明这终究是可能的!因此,让我们深入一些测试数据,看看它是如何工作的。

数据样本

让我们获取一些样本数据。我们将使用 BQ 关于芝加哥出租车出行的公共数据集。下面是在我们自己的数据集中创建我们自己的表的查询(MyDataSet):

查询以创建我们自己的芝加哥出租车信息表

注意,我们使用PARTITION BY添加了一个分区列,这总是一个好主意。该查询将花费 13GB = 0.065 美元。如果我们想进一步降低成本,我们可以使用CREATE VIEW来代替(尽管预览将不可用)。

最终的表格应该如下所示:

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

芝加哥出租车样本数据预览

这里的目标是计算所有变量(trip_secondstrip_milesfare、…、is_cash)之间的成对相关性。我们如何进行?

列到行

我们如何在不显式引用所有列的情况下查询所有列?嗯,我们可以找到一种方法来重组数据,使多列变成一行。怎么做呢?我们可以使用ARRAYSTRUCT在 BQ 中创建一种模拟字典,有效地将列转置为行。这是最终结果的样子:

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

我们希望将所有列压缩到一列数组中,这就像一个字典

我们如何创造这种结构?以下是查询:

将多列转置为多行的查询

注意,我们使用了[]STRUCT来显式创建数组。当然,查询仍然引用单个列的名称,当列数太大时,这会很快变得难以处理。要解决这个问题,我们可以:

  1. 查询INFORMATION_SCHEMA.COLUMNS以获得所有相关的列
  2. 使用FORMAT使用列信息构建一个查询字符串
  3. 使用EXECUTE IMMEDIATE执行构造的查询字符串

所有这些步骤都可以在 BQ 脚本中串起来。让我们一步一步地分解它。

使用元数据的 BQ 脚本

我们可以使用各种元数据表获得给定数据集中的所有表元数据。对于与列相关的信息,我们可以简单地查询

SELECT * FROM MyDataSet.INFORMATION_SCHEMA.COLUMNS

(该查询是免费的,因为它处理 0 个字节)

例如,我们可以提取所有数字列:

查询以提取所有数字列的名称

为了提取所有的数字列,我们在data_type上应用了一个过滤器。使用ordinal_position和/或is_partition_column还有其他可能性。

现在,我们不仅仅想要列名;我们想为EXECUTE IMMEDIATE命令构建一个查询字符串。因此,我们使用 BQ 脚本,并将列名转换成一个字符串数组,以便于稍后构建查询字符串:

查询来提取字符串数组,这样我们就可以在以后构造查询字符串

我们使用FORMATcolumn_name转换成我们之前用于将列转置为行的'STRUCT(... key, ... val)'模式。

ARRAY将查询结果转换成一个数组,该数组存储在变量query_ary中,供 BQ 脚本使用(标记为BEGIN ... END)。

现在我们已经准备好构造列转置查询,但是不引用任何特定的列名!

BQ 脚本将所有数字列提取到一个数组中,并构造和执行一个将列转置为行的查询

我们增加了两个额外的步骤:

  1. 将字符串数组query_ary格式化为查询字符串query_string
  2. 使用EXECUTE IMMEDIATE执行构建的查询。

请注意,在我们的 BQ 脚本中没有提到任何列!

成对相关

我们还缺少最后一步:如何使用转置表计算成对相关性?这可以使用一个简单的聚合来完成(可以插入到上面的 BQ 脚本中):

计算成对相关的查询

该查询执行以下操作:

  1. UNNEST``info数组两次,创建数组中所有可能的项目组合
  2. i1 < i2删除重复项,并确保只保留比较不同变量的组合
  3. GROUP BYCORR计算每个唯一对的相关性,使用FORMAT构建一个好看的输出

最终结果应该是这样的:

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

芝加哥出租车数据的前 15 个正相关性

不出所料,最大的相关性来自于trip_totalfare,因为trip_total等于fare + tips + tolls + extras,而出租车费很可能是一次乘车总成本的最大组成部分。更令人惊讶的是,trip_milestrip_secondstrip_total并不完全相关,这表明更长的旅程并不一定会导致司机收入的显著增加。

我们也可以看看最负的相关性:

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

芝加哥出租车数据的倒数 5 个负相关性

有趣的是,现金支付似乎与小费的减少有关!有人可能会认为这是因为现金很可能被用来支付更便宜的旅行,但这种相关性不是那么强。另一种可能性可能是现金小费一直没有报告,或者现金的使用与不太富裕(非商务)的乘客有关,但这些当然是推测。

结论

使用 BQ 脚本和表元数据,我们可以纵向(大量行)和横向(大量列)扩展 BQ 中的分析。

如果你觉得这篇文章有帮助,你可能也会对我的其他 BQ 技巧感兴趣。欢迎随时留下评论/问题,BQ 黑客快乐!👋

https://medium.com/swlh/bigquery-hack-1000x-more-efficient-aggregation-using-materialized-view-7243e07208da https://medium.com/swlh/bigquery-hack-create-multiple-tables-in-one-query-bc47e52bf44a https://medium.com/swlh/bigquery-hack-monte-carlo-simulation-for-free-57d18fb87076

大型销售市场回归再探:进入潮流模型

原文:https://towardsdatascience.com/big-sales-mart-regression-revisited-enter-the-tidymodels-a6a432be58d4?source=collection_archive---------22-----------------------

使用 Tidymodels 的介绍性机器学习回归项目

Tidymodels 是一个元包,很像 tidyverse,它将一组有用的 tidy 包加载到您的会话中。不同之处在于它加载了一系列在机器学习模型开发过程中使用的包。

当我们使用它们时,我将介绍每一个,并提供实际的使用案例。Tidymodels 由 Max Kuhn 开发,他是 RStudio 的成员,开发了一种生成机器学习模型的整洁友好的方法。库恩之前最著名的作品是《脱颖而出》,是《下雨了》CategoricalRegressionTraining。Caret 本身已经是一个非常强大的包,可以与 Python 的 Scikit-Learn 相媲美。

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

照片由粘土堤Unsplash 上拍摄

但是,每个模型类型都有其特定的包、输入要求、规格和训练方法。Tidymodels 试图通过简化工作流程和创建生成机器学习模型所需的统一语法来解决这个问题。

大销售市场数据集可通过分析 Vidhya 和他们向成员提供的免费项目之一获得。

https://courses . analyticsvidhya . com/courses/big-mart-sales-prediction-using-r

该项目的目的是开发和评估一系列回归模型,根据一些输入变量预测商品经销店销售额。

当我亲自完成这个项目时,许多方面都是用 base R 编写的,并不像它应该的那样直观,也没有利用 tidyverse 包提供的易用性。因此,我看到了一个真正的机会,将这个项目转化为“整洁”的思维方式,并展示 tidymodels。

探索性数据分析

#Load Packages
library(tidymodels)
library(magrittr) #Tidy pipes
library(patchwork) #Visualisation grids
library(stringr) #String Manipulation
library(forcats) #Working with Factors
library(corrr) #Develop tidy Correlation Plots
library(vip) #Most important feature visualisations

加载一系列包,最重要的是 tidymodels 元包。与 tidyverse 非常相似,它实现了一系列较小的包,这些包有不同的用途,并在模型开发过程中发挥作用,还有 dplyr、ggplot2、purrr、tibble 等。随着模型开发的进展,我们将介绍每个包。

#Load Data
train = read_csv("train.csv")
skim(train)

数据被加载到项目中,我们使用 skimr 包中方便的 skim 函数检查结构。有 12 个变量(7 个字符和 5 个数字)和 8,523 行数据。

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

skim 输出的屏幕截图(图片由作者提供)

从这里开始,我们需要用一些丢失值的变量来整理数据集。我们通过可视化数据集中的每个变量来进一步研究。

我编写这个函数是为了使我的数据科学项目的初始 EDA 步骤非常简单,并通过 purrr 的 map2()创建一个图列表,并传递给 patchwork 的 wrap_plots()以生成一个图网格。

viz_by_dtype <- function (x,y) {
  title <- str_replace_all(y,"_"," ") %>% 
           str_to_title()
  if ("factor" %in% class(x)) {
    ggplot(combi, aes(x, fill = x)) +
      geom_bar() +
      theme(legend.position = "none",
            axis.text.x = element_text(angle = 45, hjust = 1),
            axis.text = element_text(size = 8)) +
      theme_minimal() +
      scale_fill_viridis_d()+
      labs(title = title, y = "", x = "")
  }
  else if ("numeric" %in% class(x)) {
    ggplot(combi, aes(x)) +
      geom_histogram()  +
      theme_minimal() +
      scale_fill_viridis_d()+
      labs(title = title, y = "", x = "")
  } 
  else if ("integer" %in% class(x)) {
    ggplot(combi, aes(x)) +
      geom_histogram() +
      theme_minimal() +
      scale_fill_viridis_d()+
      labs(title = title, y = "", x = "")
  }
  else if ("character" %in% class(x)) {
    ggplot(combi, aes(x, fill = x)) +
      geom_bar() +
      theme_minimal() +
      scale_fill_viridis_d()+
      theme(legend.position = "none",
            axis.text.x = element_text(angle = 45, hjust = 1),
            axis.text = element_text(size = 8)) +
      labs(title = title, y  ="", x= "")
  }
}
variable_list <- colnames(train) %>% as.list()
variable_plot <- map2(train, variable_list, viz_by_dtype) %>%
  wrap_plots(               
    ncol = 3,
    nrow = 4,
    heights = 150,
    widths = 150
  )

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

通过数据类型适当的可视化简化 EDA(图片由作者提供)

由此我们注意到:

  • 项目标识符有 1559 个单独的值,为了简化模型,我们将删除这个变量
  • 项目重量没有明显的分布
  • 项目脂肪含量标签不一致
  • 项目可见性是右偏的
  • 项目类型有多种标签
  • 物料 MRP 有四个主要组
  • 插座标识符有 10 个独特的标签
  • 奥特莱斯建立的年份是多种多样的,许多商店从 90 年代中期开始
  • 插座尺寸标签不一致
  • 插座位置类型有三个标签
  • 出口类型有四个标签
  • 商品出口销售是右偏的

此外,让我们研究一下 Item_Outlet_Sales 和其他数字变量之间是否存在有趣的关系。使用 GGally 的 ggscatmat(),我们生成了一个简洁的双变量分析,沿对角线进行了高斯平滑,并为每个变量对生成了皮尔逊相关性。

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

连续变量的二元分析(图片由作者提供)

我们发现,把数字变量和目标变量对应起来,有三种不同的观察结果。

  • 物品销售在物品重量的整个范围内分布良好,没有任何明显的模式
  • Item_Visibility 与 Item_Outlet_Sales 没有关系
  • Item_MRP 有四个不同的级别,并与 Item_Outlet_Sales 适度相关,我们将在稍后的特性工程中利用这一点。

数据角力

如前所述,我们需要修正一些变量输出。

#Correct mislabeled Item_Fat_Contenttrain %<>% mutate(Item_Fat_Content = if_else(Item_Fat_Content %in% c("reg", "Regular"), "Regular", "Low Fat"))#Outlet Size is missing a labeltrain %<>% mutate(Outlet_Size = if_else(is.na(Outlet_Size),"Small",Outlet_Size))

经销店规模是根据与小型经销店具有非常相似的 Item_Outlet_Sales 分布的 NA 标签估算的。

模型开发:引入 tidymodels

到目前为止,我们已经使用了一系列 tidyverse 包来争论和可视化数据,现在让我们来看看使用 tidymodels 元包开发机器学习管道的过程。

数据拆分— rsamples

很像 sci-kit 学习测试训练分割模块,rsamples initial_split 完成类似的操作。在下面的示例中,使用 intial_split 函数生成 mc_split 对象 mart_split,传递我们的训练数据帧,将比例设置为 75%,并按 Item_Outlet_Sales 变量分层。

这有效地创建了两个数据帧的列表,由 training()或 test()调用。我们将使用测试数据框架来判断我们的模型在看不见的数据上表现如何。

set.seed(55)
mart_split <- initial_split(train, prop = 0.75, strata = Item_Outlet_Salesmart_train <- training(mart_split)
mart_test <- testing(mart_split)

特征工程—配方

recipes 包提供了大量用于处理变量的函数,并使它们对机器学习友好。配方包的三个主要功能是

  • recipe() —定义一系列连续的预处理步骤(或者收集并列出我的配料以及我将如何准备它们)
  • prep() —计算所需的统计变换(或者准备我的烹饪原料)
  • bake() —将预处理步骤应用于数据集(或烹饪我准备好的菜肴)

recipe 函数的构造类似于其他模型 outcome ~ predictor,在这里,我们通过使用波浪符号(~)指出我们想要使用所有其他变量作为模型的预测变量。).

我们已经使用配方生成了一个新的变量 Price_Per_Unit,它是 Item_MRP 和 Item_Weight 的商,然后通过应用 Box-Cox 变换并求 Item_Visibility 的平方根来寻求降低 Price_Per_Unit 的偏斜度。
在生成虚拟变量之前,名义/字符变量被转换为二进制列,表示该行是否属于某个特定的组(1 =真,0 =假),我们可以使用 reshape2::dcast(),然而,配方的强大之处在于,它能够通过管道传输一条简单的指令,使用 step_dummy 为所有名义变量创建一个虚拟变量。为了简单起见,我决定不为 Item_Identifier 创建虚拟变量,此外,这样会创建 5000 多列,可能会使模型过于复杂。

mart_recipe <- 
  training(mart_split) %>% 
  recipe(Item_Outlet_Sales ~ .) %>% 
  step_rm(Item_Identifier) %>%
  step_impute_bag(Item_Weight) %>% 
  step_impute_knn(Item_Visibility) %>% 
  step_mutate(Price_Per_Unit = Item_MRP/Item_Weight) %>% 
  step_sqrt(Item_Visibility) %>%
  step_log(Price_Per_Unit, offset = 1) %>% 
  step_discretize(Item_MRP,num_breaks = 4) %>%
  step_normalize(all_numeric_predictors()) %>%
  step_dummy(all_nominal())mart_recipe_prepped <- prep(mart_recipe)

然后,配方对象通过 prep()函数传递,也生成一个配方对象,但是已经进行了转换,因此数据已经被“准备”了。

将 prep(ed) recipe 对象传递给 bake 执行转换,因为已经创建了许多虚拟变量,所以我们现在有 54 列。

mart_train <- bake(mart_recipe_prepped, new_data = mart_train)
dim(mart_train)
[1] 6391 54

由于准备好的配方实际上是一个转换管道,我们可以在测试数据集上调用这些相同的转换。

mart_test <- mart_recipe_prepped %>% 
             bake(testing(mart_split))
dim(mart_test)
[1] 2132 54

瞧,完全处理的训练和测试数据集。

相关图— corrr

相关图对于理解哪些预测因子与结果变量相关非常有趣和重要。要创建相关图,需要将数据转换为相关数据框(cor_df)。
我们采用 mart_train,选择所有数字变量并传递给 corr::correlate,corr::correlate 生成 cor_df,给出变量对之间的 pearson 或 rho 值。

cor_df 对象被传递给 rplot(),就像对待其他 ggplot 对象一样,我们可以通过使用 theme()和配色方案来定制它的外观。

corr_df <- mart_train %>% select(is.numeric) %>% 
              correlate() %>%
              rearrange() %>% 
              shave()
rplot(corr_df,) +
 theme_minimal() +
 theme(axis.text.x = element_text(angle = 90)) +
 scale_colour_viridis_c()

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

预处理(烘焙)数据的相关图(图片由作者提供)

给聪明人的一句话,你可能不打算“通常”使用这么多变量的相关图,正如我写的,如果没有更大的监视器,这很难阅读。但是,请注意创建这样一个情节的代码是多么优雅。

在这种情况下,人们可能会决定继续完成主成分分析,并根据重要性减少变量的数量。我将把那个留给另一个时间。

模型开发—防风草

RStudio 的团队,尤其是 Max Kuhn,有一种非常邪恶的幽默感。在命名这个包时,他们不能称之为 caret2,所以他们选择了 parsnip。

由于我们试图创建一个预测 Item_Outlet_Sales 的回归模型,为了便于演示,我们将开发两个模型,并使用均方根误差(RMSE)作为评估指标。

  • 线性回归
  • 随机森林

使用 parsnip 生成模型是非常优雅的。从我们要评估的第一个模型开始,线性回归,我们声明一个模型规范,然后是用于拟合模型的计算引擎。在这个实例中,parsnip 模型将使用 stats:lm()函数。

lm_model <- linear_reg() %>% 
            set_engine("lm")lm_mart_fit <- 
  lm_model %>%
  fit(Item_Outlet_Sales ~ ., data = mart_train)

调用 parsnip 模型对象将生成类似于调用 stats:lm()对象时的输出,即每个输入变量的公式和系数列表。

lm_mart_res <- 
  predict(lm_mart_fit, new_data = mart_test) %>% 
  bind_cols(mart_test %>% select(Item_Outlet_Sales))lm_mart_res %>%
  ggplot(aes(x = Item_Outlet_Sales, y = .pred)) +
  geom_abline() +
  geom_point(alpha = 0.5) +
  theme_minimal() +
  labs(x = "Item Outlet Sales", y = "Predicted Item Outlet Sales")

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

mart_test 的线性回归模型预测与期望值的散点图(图片由作者提供)

衡量绩效——衡量标准

在 mart_test 上使用我们的回归模型的输出,我们可以评估模型使用标尺包的准确性。标尺包为评估模型性能提供了一个有效的整洁的方式。

metrics <- metric_set(rmse, rsq, mae)metrics(lm_mart_res, truth = Item_Outlet_Sales, estimate = .pred)

为指定的误差度量创建一个包装函数。在我们的例子中,我们规定了均方根误差(RMSE)、R 和平均绝对误差(MAE)。

调用指标,指定 tible、实际和预测度量,生成一个包含每个错误度量和输出的 tible。

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

指标包装函数的输出(作者图片)

将模型的误差与测试集的预测误差进行比较,我们发现 RMSE(测试)= 1141.8,RMSE(模型)= 1144.3。差别很小,我们可以说该模型很好地适用于测试数据。

但是,回归模型预测了许多值的负值,因此不适用于此上下文,因为我们不能有负销售额。

生成 ML 管道—工作流程

如上所述,为了生成基本的线性模型,我们采取了许多精细的步骤,workflows 包提供了一种优雅的方法来处理这些步骤。我们现在将通过生成一个随机森林模型来演示工作流有多有用。

随机森林模型

随机森林算法是决策树的集成方法,通常通过 bagging 方法训练。RF 算法在随机特征子集中搜索最佳特征。这导致更大的树多样性,用更高的偏差换取更低的方差和更好的整体模型。

rf_workflow <- 
  workflow() %>% 
  add_recipe(mart_recipe) %>% #Pre-processing Steps
  add_model(rand_forest(mode = "regression") %>% #Specify Model
              set_engine("ranger"))

在四行代码中,我们生成了一个 ML 工作流,现在可以用作模型对象。

rf_mart_res <- 
  rf_workflow %>% 
  fit(training(mart_split)) %>% 
  predict(new_data = testing(mart_split)) %>%
  bind_cols(mart_test %>% select(Item_Outlet_Sales))rf_mart_res %>% 
  ggplot(aes(x= Item_Outlet_Sales, y = .pred)) +
   geom_abline(lty = 2)+
   geom_point(alpha = 0.5)+
   theme_minimal()+
   labs(x="Item Outlet Sales", y= "Predicted Item Outlet Sales", title = "pRandom Forest Regression")

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

来自未调整随机森林模型的预测与实际商品销售散点图(图片由作者提供)

这里我们发现 RMSE(训练)= 1110.446,RMSE(测试)= 1126.359。随机森林模型确实有过度拟合的趋势,我们可以通过训练超参数来进一步改进模型,这也可以使用工作流和 dials 包来完成。

表盘—精炼模型开发

通过调整超参数来调整模型是模型开发的一个重要方面。

进入 dials 包和函数 grid_regular(),该函数用需要调优的超参数的每种可能组合建立一个 tibble。dials::grid_regular 的工作方式类似于 dplyr::expand_grid。

下面,我们重新建立一个随机森林模型规范,这次将 trees 设置为 500,mtry 和 min_n 设置为 tune()。Mtry 是每次分裂时采样的预测值数量,min_n 是分裂节点的最小观测值数量。

正如前面一样,我们通过管道传输模型和配方规范,从而生成一个调整工作流。

此外,我们创建了一个 4 重交叉验证对象(vfold_cv)。

最后,我们通过初始化 tune_grid()(网格搜索)生成一个 tune_results 对象,它遍历 rf_grid 中的每个组合,tune_wf 使用 4 重交叉验证。

set.seed(256)
rf_mod <- 
  rand_forest(trees = 500,
              mtry = tune(),
              min_n = tune()) %>% 
  set_engine("ranger", importance = "impurity", num.threads = 12) %>% 
  set_mode("regression")#Establish Model Flow
tune_wf <- workflow() %>%
  add_recipe(mart_recipe) %>%
  add_model(rf_mod)#Generate grid to perform grid search for hyperparameter optimisation

rf_grid <- grid_regular(mtry(range = c(6,10)), 
                        min_n(range = c(14,20)), 
                        levels = c(10,9))# 4-fold Cross Validation Stratified by Item_Outlet_Sales
folds <- vfold_cv(train, v = 4, strata = Item_Outlet_Sales)#Train and evaluate all combinations of hyperparameters specified in rf_griddoParallel::registerDoParallel(cores = 12)
rf_grid_search <- tune_grid(
  tune_wf,
  resamples = folds,
  grid = rf_grid)

请注意,我们已经利用并行处理来使用更多的工作站计算能力,因为网格搜索可能需要大量计算。

我们可以可视化这种计算的结果,并直观地看到哪个超参数组合提供最低的 RMSE。

rf_grid_search %>%
  collect_metrics() %>% 
  filter(.metric == "rmse") %>%
  select(mean, min_n, mtry) %>%
  filter(mtry > 4) %>% 
  ggplot(aes(min_n, mean, color = as_factor(mtry))) +
  geom_point()+
  geom_line()+
  scale_color_viridis_d() +
  theme_minimal()+
  scale_x_continuous(breaks = pretty_breaks())+
  theme(legend.position = "bottom") +
  labs(x = "Minimum Number of Observations to Split Node", y = "RMSE", title = "Grid Search Results for Random Forest", color = "Number of Predictors Sampled at Each Split")

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

随机森林的网格搜索结果(图片由作者提供)

调用 show_best()提供了关于网格搜索结果的更多细节

rf_grid_search %>% show_best()

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

show_best()的输出打印前 5 个结果(图片由作者提供)

我们可以使用网格搜索的结果来更新随机森林模型规范。

rf_best_rmse <- select_best(rf_grid_search, "rmse")
final_rf <- finalize_model(
  rf_mod,
  rf_best_rmse
)final_rf

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

网格搜索后的最终随机森林模型规格(图片由作者提供)

使用 vip 包,我们可以适应 final_rf 并突出显示前 10 个最重要的功能。

final_rf %>%
  fit(Item_Outlet_Sales ~., data = bake(prep(mart_recipe),training(mart_split))) %>% 
  vip(geom=c("col"), num_features = 10) +
  theme_minimal()

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

rf_final 模型的十个最重要的特性(图片由作者提供)

这真正突出了特征工程的重要性,其中一些是在我们清理数据或通过配方生成时创建的。

最后让我们评估一下 final_rf

final_wf <- 
  workflow() %>% 
  add_recipe(mart_recipe) %>% 
  add_model(final_rf)final_rf_res <- 
  fit(final_wf, training(mart_split)) %>% 
  predict(new_data = testing(mart_split)) %>% 
  bind_cols(mart_test %>% select(Item_Outlet_Sales))final_rf_res %>% ggplot(aes(x= Item_Outlet_Sales, y = .pred)) +
                  geom_abline(lty = 2)+
                  geom_point(alpha = 0.5)+
                  theme_minimal()+
                  labs(x="Item Outlet Sales", y= "Predicted Item Outlet Sales", title = "Tuned Random Forest Regression")

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

rf_final 的实际和预测产品销售散点图(图片由作者提供)

metrics(final_rf_res, truth = Item_Outlet_Sales, estimate = .pred)

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

度量函数的误差度量(图片由作者提供)

将 RMSE(测试)= 1120.365 与 RMSE(训练)= 1106.629 进行比较,我们将过拟合略微降低了 2 个 RMSE 单位,并在超参数调整后产生了略微更好的模型。

结论

该项目试图举例说明 tidymodels 元包的易用性,通过使每个步骤可管道化,拟合两种模型类型并根据测试集评估它们的性能,可以使用它来生成机器学习工作流。如果您想更进一步,训练 XGBoost 模型是非常容易的,为了简洁起见,我没有包括这一点。

将 tidymodels 与 sci-kit learn 进行比较的一个关键要点是,tidymodels 过程中的每一步都需要 tibble 数据帧,并且不需要将数据帧转换为矩阵。此外,鉴于一切都通过 tibbles 工作,正如我所演示的,这使得模型性能和超参数训练的可视化诊断更容易理解。

我强烈推荐那些有兴趣了解更多关于 tidymodels 的人去寻找神奇的朱莉娅·斯利格@https://juliasilge.com/,以及她与马克斯·库恩在备受期待的 Tidy Modeling with R 上的合作(你可以在这里预览一下https://www.tmwr.org/

BigQuery:审计和监控数据库的 3 种简单方法。

原文:https://towardsdatascience.com/bigquery-3-simple-ways-to-audit-and-monitor-your-dabatase-1cf09027f0de?source=collection_archive---------5-----------------------

如何审计和监控您的 BigQuery 数据库,以保持其整洁和高效。

Google BigQuery 是一个可管理的、高度可伸缩的、无服务器的数据仓库,能够在几秒钟内查询万亿字节的数据。这是一个很棒的工具,数据分析师和科学家很容易使用。因为 GCP 使它完全被管理,你不必过多考虑数据库管理。

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

@sadswimUnsplash 上的照片

多年来,我一直在使用老式的企业级数据库(Oracle,SAP / Sybase,…).我们需要团队中的数据库管理员来管理数据库“健康”

但是当谈到主要由数据分析师和数据科学家使用的完全托管的 BigQuery 数据库时,没有人接管这个角色是一个典型的陷阱。

因此,这里有 5 种简单的方法可以立即开始监控您的 BigQuery DB!

方法 1:元数据

元数据是提供关于其他数据的信息的数据。
—维基百科

对于关系数据库,元数据提供关于数据库本身的信息:模式、表、列或任何其他关于数据库元素和用法的信息。

GCP 和 BigQuery 提供了一些通过元数据监控数据库的便捷方法。

我不会详细讨论 BigQuery 的元数据,因为你可以参考 Skye Tran 的这篇文章。但是让我们有一个概述。

A. 信息 _ 模式

INFORMATION_SCHEMA 是一系列视图,提供关于表、视图、数据集等等的信息。你可以访问INFORMATION_SCHEMA.TABLESINFORMATION_SCHEMA.VIEWSINFORMATION_SCHEMA.COLUMNS等几个。

示例:深入了解模式中的表

-- Returns metadata for tables in a single dataset.SELECT * FROM `bigquery-public-data.census_bureau_international`.INFORMATION_SCHEMA.TABLES;

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

示例:显示按创建日期排序的数据集

SELECT * FROM myProject.INFORMATION_SCHEMA.SCHEMATA
ORDER BY creation_time;

b . _ _ 表 __

每个数据集都有自己的隐藏元数据表,名为 TABLES 。那个很有用!这是获取类似“您的表最后一次更新是什么时候?”“你们的桌子有多大?”

示例:数据集的表最后一次更新是什么时候?

SELECT
  table_id, # creation_time and last_modified_time to a timestamp 
  TIMESTAMP_MILLIS(creation_time) AS creation_time,
  TIMESTAMP_MILLIS(last_modified_time) AS last_modified_time, row_count,# convert size in MB
  ROUND(size_bytes/(1024*1024),2) as size_mb,# Convert type from numerical to description 
  CASE 
   WHEN type = 1 THEN 'table' 
   WHEN type = 2 THEN 'view' 
  ELSE NULL 
  END AS type 

FROM `bigquery-public-data.census_bureau_international`.__TABLES__ 
ORDER BY last_modified_time ASC

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

一种非常方便的分析数据集的方法

方法 2:将 Google Cloud 日志导出到 BigQuery

现在,您希望对数据库中发生的事情有更多的控制:您的表最后一次被访问是什么时候?一个用户“花费”多少?哪些桌子使用量最大?

即使无法通过 BigQuery 的元数据获得信息,您也可以通过将云日志导出到 BigQuery 来回答这些问题。

A.如何将日志从云日志导出到 Bigquery?

步骤 1:创建一个新的 BigQuery 数据集来存储日志

由于您希望在 BigQuery 中接收日志并使用 SQL 对其进行分析,因此最好通过创建新的数据集来组织数据库。选择一个方便的名称,如 日志监控

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

第二步:创建云日志接收器

接收器允许您将日志或日志的过滤子集路由到选定的目的地。你可以使用 gcloud CLI 或谷歌云的用户界面来创建它。让我们使用第二种方法。注意:接收器不会用创建前的事件进行回填。

进入谷歌云日志,选择日志路由器

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

点击**创建水槽。**给它起个名字。

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

选择大查询数据集作为目的地,并使用您新创建的数据集。我建议选中“使用分区表”选项:我可能会提高性能,并使您的数据集更具可读性。

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

最后,您可能希望使用一个过滤器来只包含相关的日志。
要导出核心 BigQuery 操作的所有记录,请使用过滤器:
protoPayload.metadata."@type"="type.googleapis.com/google.cloud.audit.BigQueryAuditMetadata"

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

第三步:从 BigQuery 查询您的日志

很快,您的日志就会流入数据集,形成 3 个表:

  • cloud audit _ Google API _ com _ data _ access
  • cloud audit _ Google API _ com _ activity
  • cloud audit _ Google API _ com _ system _ event

cloudaudit_googleapis_com_data_access是迄今为止监控数据库最有用的表。让我们开始吧!

B.如何通过 cloud audit _ Google APIs _ com _ data _ access 进行审计?

分析访问可能会有很大帮助。现在我们已经在cloudaudit_googleapis_com_data_access中获得了“访问历史”日志,让我们运行一些查询吧!

例子:你的表最后一次被访问是什么时候?

SELECT# Dataset name
REGEXP_EXTRACT(protopayload_auditlog.resourceName,   '^projects/[^/]+/datasets/([^/]+)/tables') AS dataset,# Table name
SPLIT(REGEXP_EXTRACT(protopayload_auditlog.resourceName, '^projects/[^/]+/datasets/[^/]+/tables/(.*)$'), '$')[OFFSET(0)] AS table,# Last access date
MAX(timestamp) as last_accessed_at,# Was it a Read or Write operation ?
CASE WHEN JSON_EXTRACT(protopayload_auditlog.metadataJson, "$.tableDataRead") IS NOT NULL THEN 'Read'
     WHEN JSON_EXTRACT(protopayload_auditlog.metadataJson, "$.tableDataChange") IS NOT NULL THEN 'Change'
END method,# Optionally: display the user who executed the operation
#protopayload_auditlog.authenticationInfo.principalEmailFROM logs.cloudaudit_googleapis_com_data_accessWHERE
  JSON_EXTRACT(protopayload_auditlog.metadataJson, "$.tableDataRead") IS NOT NULL
  OR JSON_EXTRACT(protopayload_auditlog.metadataJson, "$.tableDataChange") IS NOT NULLGROUP BY dataset, table, method# Optionally: Select a specific dataset
#HAVING dataset = 'public'ORDER BY last_accessed_at desc

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

上次访问的表

示例:您的数据库每天/每小时/每月的成本是多少? 这个方便的要求直接来自于的文档

SELECT# Adapt the period of time according to your needs
TIMESTAMP_TRUNC(TIMESTAMP(JSON_EXTRACT_SCALAR(protopayload_auditlog.metadataJson, "$.jobChange.job.jobStats.endTime")), DAY) AS period,FORMAT('%9.2f',5.0 * (SUM(CAST(JSON_EXTRACT_SCALAR(protopayload_auditlog.metadataJson, "$.jobChange.job.jobStats.queryStats.totalBilledBytes") AS INT64))/POWER(2, 40))) AS Estimated_USD_CostFROM logs.cloudaudit_googleapis_com_data_accessWHEREJSON_EXTRACT_SCALAR(protopayload_auditlog.metadataJson, "$.jobChange.job.jobConfig.type") = "QUERY"GROUP BY periodORDER BY period DESC

示例:您的数据库每个用户每月的费用是多少? 和前面的要求类似,我们来分解一下每个用户每月的费用!

SELECT# Adapt the period of time according to your needs
TIMESTAMP_TRUNC(TIMESTAMP(JSON_EXTRACT_SCALAR(protopayload_auditlog.metadataJson, "$.jobChange.job.jobStats.endTime")), MONTH) AS period,# User
protopayload_auditlog.authenticationInfo.principalEmail as principal,FORMAT('%9.2f',5.0 * (SUM(CAST(JSON_EXTRACT_SCALAR(protopayload_auditlog.metadataJson, "$.jobChange.job.jobStats.queryStats.totalBilledBytes") AS INT64))/POWER(2, 40))) AS Estimated_USD_CostFROM logs.cloudaudit_googleapis_com_data_accessWHEREJSON_EXTRACT_SCALAR(protopayload_auditlog.metadataJson, "$.jobChange.job.jobConfig.type") = "QUERY"GROUP BY period, principalORDER BY period, principal DESC

您可以在文档中找到更多请求示例。请随意创建您自己的!

额外收获:BigQuery 实用程序

由于cloudaudit_googleapis_com_data_access可能会令人困惑,BigQuery 通过 BigQuery utils 项目提供了这个表的帮助视图。

如果您遵循了本文的内容,就不需要重新创建日志接收器。只需跳到先决条件的步骤 3 和 4,执行。sql 脚本,一切都准备好了!

结论

通过 BigQuery 中的 INFORMATION_SCHEMATABLES云日志,您现在有 3 种简单的方法来审计和监控您的数据库。

因为您不想每次检查数据库健康状况时都重写所有这些查询,基于您最常用的分析创建视图是一个好的实践。您还可以基于某些阈值创建警报,但那是以后的事情了!

基于 BQ ML 的 K 均值聚类的大查询异常检测

原文:https://towardsdatascience.com/bigquery-anomaly-detection-using-kmeans-clustering-from-bq-ml-41688f7a50f2?source=collection_archive---------27-----------------------

理解大数据

你有没有利用你的系统来发现它本身的错误?

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

威尔·迈尔斯在 Unsplash 上的照片

用例

在愉快的 12 月,当你不在办公室,享受 COVID 让你享受的户外时光时,你团队的两名开发人员使用一些服务帐户(甚至可能是他们的私人帐户)运行了一系列流氓查询,看你是否能识别他们。他们拒绝给rogue下定义,希望看看 ML 在网络安全领域有没有用。

或者,您怀疑 BQ 数据集中的外部活动,并希望了解 ML 在网络安全领域是否有优势。[ಠ_ಠ]

剧透:是。

方法

我们将在 BQ 数据库中收集所有交易的元数据。我们将使用 BQ 机器学习(BQ ML)来训练一个(无监督的)Kmeans 算法来对事务进行聚类。我们将使用这些聚类信息来预测异常值。

生成数据集

CREATE OR REPLACE TABLE
  `analysis.ref_data_training` AS
SELECT
  *
FROM
  `region-xx`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
WHERE
  DATE(creation_time) BETWEEN "2020-11-01" AND "2020-12-01"

让我们将上述日期之间的数据视为我们的训练数据。这假设在此期间没有发生欺诈性交易,并且我们基于此数据生成“正常”聚类。region-xx应替换为适当的区域。此外,让我们假设在2020-12-01 to 2021–01–01期间存在欺诈/异常交易。我们用这段时间创建一个类似的表analysis.ref_data_testing

该表包含我们将用于构建模型的以下各列:

job_id
creation_time
end_time, start_time
**statement_type**
**query**
total_bytes_processed
total_slot_ms
destination_table.dataset_id

创建模型

CREATE OR REPLACE MODEL
  `anomaly_kmeans_001` OPTIONS (model_type='kmeans',
    standardize_features = TRUE) AS
SELECT
  r.job_id,
  EXTRACT (HOUR
  FROM
    creation_time) AS hod,
  EXTRACT (DAYOFWEEK
  FROM
    creation_time) AS dow,
  TIMESTAMP_DIFF(end_time, start_time, MINUTE) AS duration_mins,
  statement_type,
  ML.NGRAMS(bt.words_array,
    [1,
    2]) query_grams,
  query,
  total_bytes_processed,
  total_slot_ms,
  destination_table.dataset_id AS dest_dataset_id
FROM
  `analysis.ref_data_training` r
JOIN (
  SELECT
    REGEXP_EXTRACT_ALL(LOWER(query), '[a-z0-9]+') AS words_array,
    job_id
  FROM
    `ref_data_training`) AS bt
ON
  r.job_id = bt.job_id
ORDER BY
  RAND() --usually *rand() < number_rows/total_rows* works well
LIMIT
  100000 --depending on your data size, you might want to skip this

我们还制作了某些功能,比如一天中的某个时间hod和一周中的某一天dow。此外,我们还有一个主要特性**query_grams**,这将是集群的定义特征。您可以将 grams 扩展到 2 以上进行实验。

在模型创建过程中,我们不指定最佳(相关读数)的集群数量,我们让 BQ ML 来处理。

一旦你的模型完成训练,一定要检查它的统计数据。您可以像在 BQ 中预览表格一样进行操作。它有很多方便的可视化。

可视化示例分类特征、一些数字特征的质心点

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

语句 _ 类型分布[图片由作者提供]

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

我们的数字特征,所有这些都需要一些额外的预处理

预测未知样本的正确聚类

CREATE OR REPLACE TABLE
  `analysis.predicted_clusters` AS
WITH
  refs_table AS (
  SELECT
    r.job_id,
    EXTRACT (HOUR
    FROM
      creation_time) AS hod,
    EXTRACT (DAYOFWEEK
    FROM
      creation_time) AS dow,
    TIMESTAMP_DIFF(end_time, start_time, MINUTE) AS duration_mins,
    statement_type,
    ML.NGRAMS(bt.words_array,
      [1,
      2]) query_grams,
    query,
    total_bytes_processed,
    total_slot_ms,
    destination_table.dataset_id AS dest_dataset_id
  FROM
    `analysis.ref_data_testing` r
  JOIN (
    SELECT
      REGEXP_EXTRACT_ALL(LOWER(query), '[a-z0-9]+') AS words_array,
      job_id
    FROM
      `analysis.ref_data_testing`) AS bt
  ON
    r.job_id = bt.job_id)
SELECT
  * EXCEPT(query_grams) --we don't want to complicate o/p table
FROM
  ML.PREDICT( MODEL `analysis.anomaly_kmeans_001`,
    (
    SELECT
      *
    FROM
      refs_table))

ML.PREDICT函数返回的两个重要列:CENTROID_ID和一个嵌套的NEAREST_CENTROIDS_DISTANCE.第二列包含一个数组centroid_iddistance。不用说,实例被分配给具有最小distancecentroid_id的集群。

这个嵌套字段也可以用于其他目的。

计算百分位数

您现在可能已经猜到了,这个想法是离群值(流氓事务)将会相对远离群集质心。我们创建一个表来存储百分位数(9990 是 99.90%的简写)。如果不清楚,99.90%的分类实例的distance小于该值。

两个音符:

  1. 根据数据的大小,您可以使用不同的百分点(例如 75%、90%和 95%)
  2. 您不需要存储这些百分点,我这样做是为了保持持久性。
CREATE OR REPLACE TABLE
  `analysis.percentiles_anomaly` AS
SELECT
  percentiles[
OFFSET
  (9500)] AS p9500,
  percentiles[
OFFSET
  (9900)] AS p9900,
  percentiles[
OFFSET
  (9990)] AS p9990,
  percentiles[
OFFSET
  (9999)] AS p9999
FROM (
  SELECT
    [APPROX_QUANTILES](https://cloud.google.com/bigquery/docs/reference/standard-sql/approximate_aggregate_functions#approx_quantiles)((dist_from_centroid), 10000) AS percentiles
  FROM (
    SELECT
      job_id,
      c.CENTROID_ID,
      MIN(ncd.DISTANCE) AS dist_from_centroid
    FROM
      `analysis.predicted_clusters4` c,
      UNNEST(NEAREST_CENTROIDS_DISTANCE) AS ncd
    GROUP BY
      1,
      2) t) AS t2

附加说明

理想情况下,我们应该独立计算每个聚类的百分位数,因为聚类不是均匀分布的。修改上面的查询来反映这一点。

我看到你了,异常点

是时候根据预测数据和距离百分位数剔除欺诈交易了。从最高的百分位数开始,查看有多少个实例被归类为异常值,然后继续往下。

CREATE OR REPLACE TABLE
  `analysis.anomalies9999` AS
WITH
  anomalies AS (
  SELECT
    job_id,
    c.CENTROID_ID,
    MIN(ncd.DISTANCE) AS dist_from_centroid
  FROM
    `analysis.predicted_clusters4` c,
    UNNEST(NEAREST_CENTROIDS_DISTANCE) AS ncd
  GROUP BY
    1,
    2
  HAVING
    MIN(ncd.DISTANCE) >= **34.3668866** --example percentile 99.99
  ORDER BY
    dist_from_centroid DESC)
SELECT
  d.*
FROM
  `ref_data_check_all_datasets` d
JOIN
  anomalies a
ON
  a.job_id = d.job_id

运行常规查询的服务帐户靠近质心,它们没有出现在上述潜在异常中。出现的一些实例具有以下特征:

  1. 唯一查询从个人用户帐户运行,具有少量的总生存期查询。user_email是我们选择忽略的一个特性,因为我们想在交易级别而不是用户级别检查完整性。
  2. 各种帐户运行的错误查询。
  3. 在它们各自分布的尾部具有上述特征的查询。e.x 极高的total_bytes_processed值。McTotallyRealPherson 先生又忘记用分区了。😞💰
  4. 对这些异常的dowhod过滤有助于进一步缩小范围。同样的还有statement_typeuser_email

喜欢读中肯的文章?我喜欢写them。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值