TowardsDataScience 博客中文翻译 2020(六百零五)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

机器学习可以在不到五分钟内检测到新冠肺炎!

原文:https://towardsdatascience.com/machine-learning-can-detect-covid-19-in-less-than-five-minutes-23bba57aeaa3?source=collection_archive---------27-----------------------

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

疾控中心Unsplash 拍摄的照片

旨在快速检测冠状病毒的研究进展的信息和收获。

介绍

一群来自世界知名学术机构的研究人员,如牛津大学华威大学蒙彼利埃大学和可信的研究实验室,发明了一种在几分钟内检测新冠肺炎(新型冠状病毒)和其他呼吸道病原体的方法。

这一壮举是通过利用图像分析和机器学习技术,更具体地说是卷积神经网络,根据病毒特有的结构特征对呼吸道疾病的微观病毒进行分类而实现的。

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

照片由 L NUnsplash 上拍摄

本文介绍了与上述机构研究人员开展的工作相关的发表的研究论文中的关键信息和要点。

通过阅读这篇文章,你将理解用于创建新冠肺炎 5 五分钟检测系统和其他重要背景信息的方法背后的直觉和技术。

有些读者可能不熟悉本文中的一些术语和短语,这是完全可以理解的,因此,在本文的某些地方,一些章节提供了所用单词和关键术语的定义。

新型冠状病毒:引起新冠肺炎病的人类冠状病毒株。

病原体:致病生物或传染物。常见的病原体有病毒、细菌、真菌、朊病毒和寄生虫。

以前检测新冠肺炎的方法(新型冠状病毒)

你可能已经熟悉了检测新冠肺炎的方法,也许你最近做过一些新冠肺炎试验。一些新冠肺炎测试检测咽拭子样本中病毒的存在,而其他测试检测人类免疫系统产生的抗体来对抗疾病。

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

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

以下是对通常用于检测新冠肺炎病毒的测试的更正式的解释和描述。

核酸扩增试验

核酸扩增测试通过识别特定的核酸序列来检测新冠肺炎;这意味着对病毒特有的独特的生物聚合物生物分子的检测。

这种检测程序的扩增部分是指产生新冠肺炎特有的遗传物质或 DNA 的拷贝。

就早期疾病诊断而言,与抗体检测相比,检测病毒 DNA 的存在实际上好得多。身体通常需要一段时间来产生抗体,以应对新冠肺炎病毒感染。

抗原和抗体检测

抗原是侵入性生物,可引发免疫系统产生抗体的反应。抗体通常会将自身结合到抗原上,导致感染和疾病,进而导致免疫系统中和抗原。

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

由 Brian 0918&# 153;—自己的作品,公共领域,https://commons.wikimedia.org/w/index.php?curid=404735

新冠肺炎的抗体测试通过检测血液中的抗体来检测个体中抗体的存在,从而揭示一个人以前是否感染过新冠肺炎病毒。

抗体测试不会显示一个人目前是否感染了新冠肺炎病毒,而抗原测试将确认一个人现在是否被感染。

抗原测试的工作原理是检测与入侵病原体相关的蛋白质的存在。

生物聚合物:这些是由活生物体产生的长重复分子链的材料,(RNA(核糖核酸)或 DNA(脱氧核糖核酸))。

五分钟检测程序如何工作

该程序的工作原理是传递标记病毒粒子的图像,这些图像经过处理后显示出特定的颜色信号。卷积神经网络对显微镜图像中的病毒颗粒信号进行分类。

以下是更详细的程序步骤:

  1. 该程序从通过咽拭子提取病毒颗粒开始。
  2. 收集的病毒样本用甲醛灭活。
  3. 下一步是通过短的荧光 DNA 与病毒表面的结合来即时标记完整的病毒颗粒。
  4. 标记后,使用壳聚糖包被的载玻片固定病毒颗粒,并置于其上。
  5. 通过使用显微成像收集病毒颗粒的衍射受限图像。
  6. 然后使用图像处理和机器学习技术对样本中的各种类型的病毒进行分类。

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

荧光标记策略和病毒检测的程序。

卷积神经网络(CNN)根据病毒颗粒表面荧光团的分布对病毒颗粒进行分类。CNN 利用了病毒颗粒表面荧光团分布的独特特性。

病毒颗粒具有独特的形状、大小、结构和表面化学性质,这反过来使得病毒颗粒表面荧光团的分布能够作为对病毒进行分类的独特特征。

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

作者 Gregor 1976——自有作品,公共领域,【https://commons.wikimedia.org/w/index.php?curid=1251744

呈现给 CNN 网络的图像包含被照亮为单一绿色或红色荧光信号的病毒粒子和黄色粒子。黄色颗粒对应于共同定位的绿色和红色荧光信号(具有红色和绿色荧光标记的病毒颗粒)。

根据研究,在不含新型冠状病毒病毒(病毒阴性)的咽拭子样品中,观察到几乎没有共定位信号。

在病毒阳性样品中更容易观察到共定位信号。有关提取图像的示例,请参见下面的图像。

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

左图:荧光显微成像显示共定位的红色和绿色信号为黄色颗粒(病毒阳性)。右图:病毒负面形象

在通过卷积神经网络前馈图像之前,基于定义的视场内图像信号的稀缺性(< 10 pixels) of image signals areas or abundance(> 100 像素)来过滤图像信号的区域。

自适应滤波 是用于从背景中分割病毒信号的图像处理方法。

用于确保病毒粒子信号在图像中普遍存在的另一种方法是通过基于协同定位条件的信号过滤。

符合设定的协同定位信号条件的信号将被保留,不符合条件的信号将从通过 CNN 的最终图像中过滤掉。

大多数机器学习实践者将上述过程视为在机器学习项目生命周期的数据准备阶段强制执行的确保数据完整性和清洁性的方法。

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

放置在协同定位信号周围的边界框

荧光团:一种化合物,通过其吸收和重新发射各种波长的光的能力而充当检测剂。

共定位:涉及荧光标记空间重叠的事件。

网络体系结构和 ML 技术

在这项研究工作中设计和实现的卷积神经网络架构由 15 层组成。

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

CNN 架构的设计分为三个阶段,最后才是分类头。

第一阶段在输入层之后,其中有一个 conv 层(8 个通道,2x2 滤波器大小,0 填充),随后是一个 ReLu,批量归一化和一个最大池层(池大小 2x2,步长 2)。第一阶段向下一阶段输出八个下采样特征图。

第二阶段由 conv 层(16 个通道,2×2 滤波器大小,填充为 1)组成,随后是 ReLu、批量归一化和最大池层(池大小为 2×2,步长为 2)。第二阶段向下一阶段输出 16 个下采样特征图。

第三阶段由 conv 层(32 个通道,3×3 的滤波器大小,填充为 1)组成,随后是 ReLu、批量归一化和无最大池层。

第三阶段的结果被传递到完全连接的层上。在典型的 CNN 中,conv 层的输出在传递到完全连接的层之前被展平为一维数组。

全连接层(致密层)包含任意数量的神经元/单元。全连接层的激活通过 softmax 层,在此对输入数据进行分类。

以下是本节包含的一些关键术语的快速定义,如果您已经熟悉这些术语,请随意跳过。

卷积层:卷积是一个数学术语,描述两组元素之间的点积相乘。在深度学习中,卷积运算作用于卷积层中的滤波器/内核和图像数据阵列。因此,卷积层只是一个包含滤波器和通过卷积神经网络的图像之间的卷积运算的层。

批量标准化层 :批量标准化是一种通过引入一个附加层来减轻神经网络内不稳定梯度影响的技术,该附加层对来自前一层的输入执行操作。这些操作对输入值进行标准化和规范化,然后通过缩放和移位操作转换输入值。

下面的 max-pooling 操作有一个 2x2 的窗口,并滑过输入数据,输出内核感受域内像素的平均值。

展平图层:取一个输入图形,将输入图像数据展平成一维数组。

Softmax 激活函数:一种激活函数,用于导出输入向量中一组数字的概率分布。softmax 激活函数的输出是一个向量,其中它的一组值表示一个类或事件发生的概率。向量中的值加起来都是 1。

超参数和附加信息

  • 当训练卷积神经网络时使用的学习速率被设置为 0.01,没有学习速率衰减。
  • 小批量:1000 个
  • 训练时期数:100
  • 验证频率:20 步

培训和测试

新型冠状病毒病毒与其他呼吸道疾病如流感和季节性人类冠状病毒(hCov)有相似的早期症状;因此,任何新冠肺炎检测方法必须有助于区分相似的病毒。

研究中使用的 CNN 网络在包含四种独特病毒的数据集上进行训练和验证,训练和验证分区分别为 70%和 30%。

研究人员确保实现的 CNN 可以区分具有相似形状、结构和表面化学的病毒。

根据研究论文的笔记,训练和验证阶段总共花了 12 分钟。

结果

经过训练的 CNN 架构的性能通过包含在研究论文中的混淆矩阵呈现。

混淆矩阵说明了分类算法在一组测试或评估数据上的性能,其中数据分类(标签)是已知的。

CNN 在受控环境中的实验室生长病毒和从患者身上获得的病毒临床样本上进行了测试。

下面是分类的性能和结果的详细信息。

实验室培养的病毒和受控测试

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

实验室培养的病毒和控制测试结果

测试了 CNN 对阳性和阴性 IBV(传染性支气管炎病毒)病毒样本进行分类的能力。IBV 是一种影响鸟类的冠状病毒。CNN 能够以 91.4%的准确度对阳性和阴性 IBV 单一病毒颗粒进行分类。

进行的另一项测试是 CNN 区分具有相似结构特性的病毒的能力。用于本次试验的病毒为 IBV 和其他三种流感病毒( UdornX31PR8 株)。

CNN 能够区分来自 IBV 样本的病毒,准确率为 95.5%(乌多恩)94.5%(PR8)。当任务是对病毒 X31 或 Udorn 病毒样本进行分类时,CNN 提供了 68.8%的性能,这两种病毒在结构特性方面非常相似。

非受控环境中的临床病毒样本

一个更可靠的测试突出了 CNN 的性能,那就是对来自病人的新型冠状病毒病毒样本进行分类。病毒样本取自新型冠状病毒病毒检测呈阳性和阴性的患者的咽拭子,以及其他人类冠状病毒株( OC43HKU1NL63 )

CNN 架构在从咽拭子病毒样本收集的数据上被训练和测试。

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

非受控环境中的临床病毒样本结果

经过训练的 CNN 在阳性和阴性新型冠状病毒之间的分类表现良好,准确率约为 70%,在 hCov 和阴性样本之间的分类准确率为 78%。

当 CNN 的任务是对新型冠状病毒或任何季节性人类冠状病毒的病毒样本进行分类时,分类准确率达到了 73%。

在实验室培养的病毒和临床样本之间观察到的性能准确性的降低归因于临床样本中病毒的复杂性;此外,实验室培养的样品不含会影响病毒样品完整性的外部残留细胞物质。

优势和推广计划

本文中提到的快速测试过程和技术的好处是显而易见的。

至关重要的是,我们作为一个社会,实施的方法,使目前的疫情处于控制之下。

以下是所讨论的快速测试技术提供的一些主要优势:

  • 在 2-5 分钟内提供高准确度的诊断结果。
  • 本文提到的研究中提出的快速新冠肺炎检测方法作为早期诊断工具是有益的,可以通过早期诊断帮助抑制感染的传播。
  • 可以有效区分类似于新型冠状病毒病毒的病毒,这在季节性冠状病毒在患者中更流行的冬季月份中将是有益的属性。
  • 在这种特定的新冠肺炎检测方法中使用的过程可以重新用于检测其他呼吸道病毒。
  • 研究论文中提出的检测技术可以在实验室环境之外使用。因此,我们可以看到这种检测技术在学校、养老院、医院和国际交通枢纽的部署。

就这种 5 分钟新冠肺炎探测技术何时向公众推出的时间框架而言,目前计划成立一家公司,该公司可以在 2021 年初开始产品开发。

值得一提的是一种快速检测技术,这种技术一直处于公共新闻的最前沿,这就是目前在英国健康和美容零售商 Boots 销售的 12 分钟新冠肺炎检测测试。这些测试设备来自 LumiraDx ,最初价格为 120 英镑,随着需求的增加,价格会下降。

[## 使用单粒子成像和深度学习在几分钟内检测和识别病毒

近几十年来,病毒爆发的频率和规模不断增加,集中体现在当前的新冠肺炎…

www.medrxiv.org](https://www.medrxiv.org/content/10.1101/2020.10.13.20212035v3)

我希望这篇文章对你有用。

要联系我或找到更多类似本文的内容,请执行以下操作:

  1. 订阅我的 邮件列表 获取每周简讯
  2. 跟我上
  3. 通过 LinkedIn 联系我

其他文章

[## 我如何使用智能手表传感器来防止面部触摸

一个值得追求的想法?

towardsdatascience.com](/how-im-using-smartwatch-sensors-to-limit-covid-19-infection-51abe04f81f9) [## 你可以通过这些 YouTube 视频了解 GPT 3

通过这些 YouTube 视频,在不到 3 分钟的时间内对 GPT 3 号有一个初步的了解

towardsdatascience.com。](/you-can-understand-gpt-3-with-these-youtube-videos-6a30887c928b)

对 ROC-AUC 指标的零数学直观理解

原文:https://towardsdatascience.com/machine-learning-classification-making-sense-of-the-roc-curve-30a510bba81d?source=collection_archive---------30-----------------------

没有数学或公式。是的图像和动画。

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

卡伦·艾姆斯利在 Unsplash 上的照片

了解轴

典型的 ROC 图如下所示:

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

在我们进入任何其他内容之前,我们需要理解轴的含义。不要陷入令人困惑的公式,这里有一个最简单的解释:

  1. x 轴(假阳性率,或 FPR)是模型标记为阳性(假阳性)的实际阴性样本的分数。
  2. y 轴(真阳性率,或 TPR)是模型标记为阳性(真阳性)的实际阳性样本的分数。

请注意两者之间的相似性!本质上,ROC 曲线是真阳性对假阳性曲线,两个轴都是标准化的。

与阈值的关系

每当我们看到一个线图,我们倾向于认为随着时间的线性进展,或一些参数表示在 x 轴上。当我们增加 x 轴上的参数时,线图会前进。思维过程通常是这样的:“对于 x 轴上给定的值,图形给我 y 轴上对应的值”。

但是 ROC 在这方面很微妙——它不是从 FPR 值(x 轴)到 TPR 值(y 轴)的映射,因为你不能真正计算 TPR 作为 FPR 的函数。那么,随着 ROC 曲线远离原点,什么在变化呢?答案是(请击鼓):门槛。

如果我们更深入地研究大多数分类模型,我们会发现它们不只是给一个数据点分配一个标签,而是给一个数据点分配一个分数,然后将该分数与一个阈值进行比较,以决定是将其分类为正面还是负面:

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

分类模型在幕后使用分数和阈值

因此,给定一个阈值,模型将为每个数据点生成一个分类。对于给定的一组分类,TPR 和 FPR 各有一个值。但是,随着阈值的变化,TPR 和 FPR 都将在 0 到 1 之间变化。这就是为什么我们说阈值随着 ROC 曲线的进展而变化。

极端情况

为了恰当地形象化这一点,让我们从考虑极端情况开始;这将为我们理解 ROC 曲线在其他情况下如何工作提供一个更好的视角。

首先,考虑阈值被设置为最大值的情况。没有比阈值更高的得分,也没有被模型标记为阳性。这是 ROC 曲线位于(0,0)时的情况:

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

现在考虑另一种极端情况——当阈值处于最小值时。所有事情的得分都高于阈值,并且所有事情都被模型标记为积极的。这是 ROC 曲线位于(1,1)时的情况:

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

介于两者之间的一切

贯穿这两个极端之间的一切看起来像这样:

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

随着模型阈值的降低,正面预测的总数将会增加。ROC 图表达了这些阳性预测是如何被分为真阳性和假阳性的。

ROC 曲线的理想特征

现在我们知道了 ROC 曲线代表什么,我们可以开始理解什么会使一个给定的 ROC 曲线“好”或“坏”。

让我们再来看看这些轴:

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

很明显,我们想要真阳性,不想要假阳性。对于坐标轴,我们想沿着 y 轴向上移动,但不想沿着 x 轴向前移动。然而,ROC 曲线从(0,0)一直到(1,1)…换句话说,无论如何,你都要穿过 x 轴。

所以 ROC 曲线的好坏必然与曲线的形状有关。为了理解什么形状被认为是好的,我们回到阈值图,试图理解什么使分类模型更好。很明显,一个给数据点打分的模型是这样的:

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

比这样计算数据点的公司更糟糕:

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

哪一个比这样的数据点更糟糕(理想情况):

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

如果我们将所有这些与它们的 ROC 曲线进行比较,一个清晰的模式开始显现出来:

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

如果更多的白点(实际上是正数据点)比黑点(实际上是负数据点)排名更高,ROC 曲线在 x 轴(FPR)上向前移动之前沿 y 轴(TPR)上升。TPR 上升越早,曲线下的面积越大:

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

这就是为什么您会经常看到 ROC-AUC(ROC-曲线下面积)或 AUROC(ROC 下面积)指标被用来衡量分类算法的性能。

本质上,更好的 ROC 曲线是曲线下具有更大面积的曲线,因为这意味着分类模型对更多正样本的排序高于负样本,即模型具有更好的正负数据点分离(在正确的方向上)。

结论

希望这些动画和解释能让你更直观地理解什么是 ROC 曲线,以及为什么我们选择 ROC 曲线下的面积作为分类算法性能的度量。

机器学习分类器与 Python 的比较

原文:https://towardsdatascience.com/machine-learning-classifiers-comparison-with-python-33149aecdbca?source=collection_archive---------6-----------------------

用于机器学习的 Python

评估和比较分类器性能

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

凯文·Ku 拍摄的图片可在 Unsplash 获得

机器学习分类器

机器学习分类器是用于在标记数据可用时预测数据点类别的模型(即监督学习)。一些最广泛使用的算法是逻辑回归、朴素贝叶斯、随机梯度下降、k-最近邻、决策树、随机森林和支持向量机。

选择正确的评估者

在解决机器学习问题时,为给定的工作确定正确的估计器是最关键和最困难的部分之一。每个估计值都适用于特定类型的数据和问题。 Scikit-learn ,机器学习最流行的 Python 库之一,提供了下面的图表来指导用户选择最合适的估计器的决策过程。

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

图片由 scikit-learn 提供scikit-learn.org

绩效评估指标

必须对分类模型进行评估,以确定它们执行特定任务的有效程度。虽然好的分类模型对于预测目的是有用的,但是差的分类模型导致不可靠的结果,因此对于用户是无用的。

绩效评估指标基于以下变量的总数:

  • 真阳性:结果被正确预测为阳性类别
  • 真阴性:结果被正确预测为阴性类别
  • 假阳性:结果被错误地预测为阳性类别
  • 假阴性:结果被错误地预测为阴性类别

其中一个轴是机器学习模型预测的标签,另一个轴是实际标签:

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

二元分类的混淆矩阵

有四个主要的性能指标用于评估分类模型的有效性:

  • 准确性:测试正确预测两个类别的能力
  • 精度:测试从所有预测的阳性类别中正确检测出阳性类别的能力
  • **回忆(灵敏度)😗*测试从所有实际阳性类别中正确检测出阳性类别的能力
  • F1 得分:精确度和召回率的调和平均值

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

绩效指标公式

在下面的例子中,让我们评估五种不同分类模型(即逻辑回归、支持向量分类器、决策树、随机森林和高斯朴素贝叶斯分类器)在弗雷明汉心脏研究数据集(一项旨在确定导致心血管疾病的常见因素的研究)上的性能,以确定导致最可靠结果的模型。

下面的 Python 代码将分为五个主要步骤。包含的注释行提供了简短的解释,并指导您完成编码过程。

步骤#1:数据加载

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

弗雷明汉心脏研究

步骤 2:探索性数据分析

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

男性/女性比例

根据上面的图,弗雷明汉心脏研究包含更多与女性相关的数据点,而不是男性。

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

结果计数

上面的图表揭示了弗雷明汉心脏研究是一个严重不平衡的数据集。大多数数据点对应于负面类别(即十年内发展成心血管疾病的低风险)。要解决这个问题,需要进一步的数据平衡。

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

按性别统计的结果

有意思。尽管与男性相对应的数据点总数较低,但上图表明,男性患心血管疾病的风险高于女性。

步骤 3:数据清理

步骤 4:数据平衡

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

上图显示,在使用随机欠采样技术平衡数据集后,相同数量的类是相等的。

步骤#5:模型建立和性能评估

最终结果

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

模型的绩效评估得分表

结果解释

根据上表的结果,支持向量分类器获得了最好的准确度、召回率和 F1 分数,以及第二好的精确度分数,使其成为该数据集最可靠的机器学习分类器。另一方面,可以说决策树和高斯朴素贝叶斯模型具有最差的性能,因此,对于该数据集不是可靠的分类模型。

接下来是什么?

在支持向量分类器被识别为最可靠的机器学习分类器之后,下一步将包括调整其参数,以确定其性能是否可以进一步提高。

值得说明的是,在上述代码中机器学习分类器的实例化期间,它们的参数被设置为默认参数,除了逻辑回归模型中用于实现模型收敛的 max_iter 参数和支持向量分类器中的 dual 参数,因为样本的数量大于特征的数量。

现在轮到你了

在前面的示例中,分类模型是使用整个数据集(即,对应于男性和女性的数据点)构建的,它假设导致心血管疾病的因素对两性具有相同的权重。作为练习编码技能的一种方式,尝试按性别划分数据集,并为每个数据集建立分类模型。使用本文中讨论的评估指标比较它们的性能,并评估是为每种性别建立独立的分类模型更方便,还是为两种性别建立一个公共的分类模型更方便。

总结想法

机器学习和人工智能算法在解决问题和复杂任务方面有许多有用和多样的应用。除了数据科学,它们已经成为学术界和专业人士非常流行的研究趋势,在广泛的领域中出现了新的研究方向。研究人员继续为多种编程语言和软件更新和开发新的编程库和包,以促进这些算法的实现和执行。

Python 代表了一种伟大的免费开源编程语言,能够执行广泛的机器学习、人工智能、数据科学和数据分析任务。它最受欢迎的一些机器学习和深度学习库包括 scikit-learn、TensorFlow、Keras、PyTorch、Pandas 和 NLTK。数据科学家和分析师必须充分利用这些工具来解决现实生活中的复杂问题和任务,从而为组织、客户或研究领域带来附加值。

— —

如果你觉得这篇文章有用,欢迎在GitHub上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 个人资料 来探索我以前的文章。感谢阅读。

——罗伯特

机器学习分类器:数据重采样器与 Python 的比较

原文:https://towardsdatascience.com/machine-learning-classifiers-data-resamplers-comparison-906442d04fde?source=collection_archive---------61-----------------------

用于机器学习的 Python

评估和比较重采样技术

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

图片由杰瑞米·托马斯提供,在 Unsplash

机器学习分类器

机器学习分类器是用于在标记数据可用时预测数据点类别的模型(即监督学习)。一些最广泛使用的算法是逻辑回归、朴素贝叶斯、随机梯度下降、k-最近邻、决策树、随机森林和支持向量机。

绩效评估指标

必须对分类模型进行评估,以确定它们执行特定任务的有效程度。虽然好的分类模型对于预测目的是有用的,但是差的分类模型导致不可靠的结果,因此对于用户是无用的。

绩效评估指标基于以下变量的总数:

  • 真阳性:结果被正确预测为阳性类别
  • 真阴性:结果被正确预测为阴性类别
  • 假阳性:结果被错误地预测为阳性类别
  • 假阴性:结果被错误地预测为阴性类别

其中一个轴是机器学习模型预测的标签,另一个轴是实际标签:

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

二元分类的混淆矩阵

有四个主要的性能指标用于评估分类模型的有效性:

  • 准确性:测试正确预测两个类别的能力
  • 精度:测试从所有预测的阳性类别中正确检测出阳性类别的能力
  • **回忆(灵敏度)😗*测试从所有实际阳性类别中正确检测出阳性类别的能力
  • F1 得分:精确度和召回率的调和平均值

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

绩效指标公式

不平衡数据集

不平衡数据集是指不同类别中样本总数变化很大的数据集,导致机器学习分类器偏向样本数较大的类别(即多数类别)。下图说明了使用不同级别的类平衡训练线性 SVC(支持向量分类器)。

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

图片由 g .勒迈特等人提供,可在 Im balanced-learn . readthedocs . io获取

为了解决这个问题,有两组重采样技术用于平衡数据集:

欠采样技术

欠采样包括减少来自多数类的样本数量,以使其与来自少数类的样本数量相匹配。一些欠采样技术包括:随机欠采样、托梅克链接和压缩最近邻。

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

欠采样表示

过采样技术

过采样包括增加来自少数类的样本数,使其与来自多数类的样本数相匹配。一些过采样技术包括:随机过采样、SMOTE、SMOTE-NC、边界 SMOTE 和自适应合成。

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

过采样表示

对于下面的例子,让我们在应用了 11 种不同的重采样技术(随机欠采样、接近缺失 I、接近缺失 II、接近缺失 III、Tomek 链接、浓缩最近邻、SMOTE、边界 SMOTE、SMOTE-NC、自适应合成和随机过采样)以确定导致最可靠结果的技术之后,评估逻辑回归模型在弗雷明汉心脏研究数据集上的性能。

下面的 Python 代码将分为五个主要步骤。包含的注释行提供了简短的解释,并指导您完成编码过程。

步骤#1:数据加载

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

弗雷明汉心脏研究

步骤 2:探索性数据分析

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

男性/女性比例

根据上面的图,弗雷明汉心脏研究包含更多与女性相关的数据点,而不是男性。

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

结果计数

上面的图表揭示了弗雷明汉心脏研究是一个严重不平衡的数据集。大多数数据点对应于负面类别(即十年内发展成心血管疾病的低风险)。要解决这个问题,需要进一步的数据平衡。

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

按性别统计的结果

有意思。尽管与男性相对应的数据点总数较低,但上图表明,男性患心血管疾病的风险高于女性。

步骤 3:数据清理

步骤 4:不平衡的模型构建和性能评估

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

模型的性能衡量不平衡数据集中的分数

第 5 步:数据平衡

步骤#6:平衡的模型构建和性能评估

最终结果

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

模型的性能衡量平衡数据集中的分数

结果解释

根据上表中的结果,为在采样技术下与浓缩最近邻平衡的数据集开发的逻辑回归模型获得了最佳的精确度、召回率和 F1 分数,以及第三好的精确度分数,使其成为该数据集最可靠的模型。

与从为原始不平衡数据集开发的逻辑回归模型中获得的绩效指标得分相比,为平衡数据集开发的模型的绩效指标得分有所提高。精确度分数从 0.6135 增加到 0.6596,召回分数从 0.0777 增加到 0.7929,F1 分数从 0.1362 增加到 0.7188。然而,准确度分数从 0.8512 下降到 0.6260。根据上表中的结果,没有可提高模型精度得分的重采样技术,因为最高的一个是通过随机欠采样技术获得的值 0.6516。

接下来是什么?

在浓缩最近邻被识别为导致最可靠的机器学习模型的最佳重采样技术之后,下一步将包括调整其参数以确定其性能是否可以进一步提高。

值得说明的是,在机器学习分类器的实例化和上面代码中的重采样技术期间,它们的参数被设置为默认参数,除了逻辑回归模型中的 max_iter 参数用于实现模型收敛,以及一些重采样函数中的 random_state 参数用于可复制性。

现在轮到你了

在前面的示例中,仅开发了一个机器学习分类器(即逻辑回归),并使用多种重新采样技术进行了评估。然而,其他机器学习分类器(例如决策树、随机森林、支持向量分类器、高斯朴素贝叶斯分类器)的发展可能会导致更好的结果。尝试用其他机器学习分类器重复这个实验,以确定对于这个数据集,是否有更好的分类器和重采样技术的组合。

同样,机器学习模型是使用整个数据集(即对应于男性和女性的数据点)建立的,它假设导致心血管疾病的因素对两性具有相同的权重。作为练习编码技能的一种方式,尝试按性别划分数据集,并为每个数据集建立分类模型。使用本文中讨论的评估指标比较它们的性能,并评估是为每种性别建立独立的分类模型更方便,还是为两种性别建立一个公共的分类模型更方便。

总结想法

机器学习和人工智能算法在解决问题和复杂任务方面有许多有用和多样的应用。除了数据科学,它们已经成为学术界和专业人士非常流行的研究趋势,在广泛的领域中出现了新的研究方向。研究人员继续为多种编程语言和软件更新和开发新的编程库和包,以促进这些算法的实现和执行。

处理不平衡数据集并选择最合适的重采样技术是数据科学项目中的重要一步。适当的重采样技术选择可以导致更可靠的机器学习模型,而不适当的选择可能导致机器学习模型的偏差,不能预测准确的结果。本文展示了一种为给定数据集决定最佳重采样技术的方法。

Python 代表了一种伟大的免费开源编程语言,能够执行广泛的机器学习、人工智能、数据科学和数据分析任务。它最受欢迎的一些机器学习和深度学习库包括 scikit-learn、TensorFlow、Keras、PyTorch、Pandas 和 NLTK。数据科学家和分析师必须充分利用这些工具来解决现实生活中的复杂问题和任务,从而为组织、客户或研究领域带来附加值。

如果你觉得这篇文章有用,欢迎在 GitHub 上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 简介 来探索我以前的文章。感谢阅读。

——罗伯特

银行营销活动:成本预测-EDA(I)

原文:https://towardsdatascience.com/machine-learning-costs-prediction-of-a-marketing-campaign-exploratory-data-analysis-part-i-758b8f0ff5d4?source=collection_archive---------16-----------------------

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

照片由萨姆森Unsplash 上拍摄

预测营销活动最佳目标候选人的数据科学方法

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

探索性数据分析—gon alo GUI mares Gomes

关于项目

该数据集存储了 2008 年至 2015 年葡萄牙一家银行的营销团队为吸引客户认购定期存款而实施的营销销售操作(电话营销)的信息,将结果分为“是”和“否”两个二进制分类变量。

在那之前,我们的策略是不加区别地争取最大数量的客户,并试图通过电话向他们销售金融产品。然而,这种方法除了花费许多资源之外,对于许多被这种类型的行为困扰的客户来说也是非常不舒服的。

为了确定营销活动的成本,营销团队得出结论:

  • 对于每个被确定为优秀候选人并因此被定义为目标但没有认购存款的客户,银行的成本为 500 欧元
  • 对于每个被确定为不良候选人并被排除在目标之外但会认购产品的客户,银行的成本为 2.000 欧元

机器学习问题和目标

我们面临一个二元分类问题。目标是训练最好的机器学习模型,该模型应该能够预测作为目标的候选人的最佳数量,以便将成本降至最低,并将效率最大化。

项目结构

该项目分为三类:

  1. EDA: 探索性数据分析
  2. **数据争论:**清理和特征选择
  3. **机器学习:**预测建模

在本文中,我将只关注第一部分,探索性数据分析(EDA)。

绩效指标

用于评估的指标是总成本,因为目标是确定活动的最低成本。

你可以在这里找到这个项目的全部代码。
可点击此处下载“银行 _ 营销 _ 营销活动. csv”数据集。

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

丹尼尔·麦金尼斯在 Unsplash 上的照片

首先要做的是导入所需的库和依赖项。

# import librariesimport pandas as pd
from pandas.plotting import table
import numpy as np
import seaborn as sns
import scipy.stats
import matplotlib.pyplot as plt
%matplotlib inline

加载数据集(我将把它指定为“df”)并检查第一行。

df = pd.read_csv('bank_marketing_campaign.csv') # load the datasetdf.head() # print the data

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

head()是一种用于显示数据帧中前‘n’行的方法,而tail() 用于显示最后‘n’行

标有“y”的因变量或目标(在右边最后一列)是一个二元范畴变量。让我们从将它转换成二进制数字开始,如果客户端订阅,它将假定值为 1,否则为 0。新列“目标”将替换“y”(将被删除)。

# converting into a binary numeric variabledf['target'] = df.apply(lambda row: 1 if row["y"] == "yes" else 0, axis=1)
df.drop(["y"],axis=1,inplace=True)

我还将重命名一些列,用下划线代替点。

# Renaming some columns for better typing and calling variablesdf.rename(columns={"emp.var.rate":"emp_var_rate", "cons.price.idx":"cons_price_idx", "cons.conf.idx":"cons_conf_idx", "nr.employed":"nr_employed"}, inplace=True)df.head()

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

将二进制类别目标转换为二进制数值变量,并重命名一些列

数据集的基本信息

  • 有多少功能可用?
  • 数据集中有多少客户端?
  • 有重复的记录吗?
  • 有多少客户订阅了定期存款,有多少没有?
# Printing number of observations, variables including the target, and duplicate samplesprint(f"Number of clients: {df.shape[0]}")
print(f"Number of variables: {df.shape[1]} incl. target")
print(f"Number of duplicate entries: {df.duplicated().sum()}")

客户端数量:41188
变量数量:16 包括目标
重复条目数量:5853

我必须得出结论,这些明显重复的样本实际上来自具有相同特征的人。

# How many clients have subscribed and how many didn't?absolut = df.target.value_counts().to_frame().rename(columns={"target":"clients"})
percent = (df.target.value_counts(normalize=True) *100).to_frame().rename(columns={"target":"%"})
df_bal = pd.concat([absolut,percent],axis=1).round(decimals=2)

print(f"[0] Number of clients that haven't subscribed the term deposit: {df.target.value_counts()[0]}")
print(f"[1] Number of clients that have subscribed the term deposit: {df.target.value_counts()[1]}")

display(df_bal)absolut.plot(kind='pie', subplots=True, autopct='%1.2f%%', 
             explode= (0.05, 0.05), startangle=80, 
             legend=False, fontsize=12, figsize=(14,6));

数据集高度不平衡:

[0]未认购定期存款客户数:36548
[1]已认购定期存款客户数:4640

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

数据集不平衡,0:“否”大约是 1:“是”的八倍

探索性数据分析

现在让我们检查变量类型、缺失值、相关性以及显示统计描述。

# Type of variables
df.dtypes.sort_values(ascending=True)age                 int64
pdays               int64
previous            int64
target              int64
emp_var_rate       float64
cons_price_idx     float64
cons_conf_idx      float64
euribor3m          float64
nr_employed        float64
job                object
marital            object
education          object
default            object
housing            object
loan               object
poutcome           object
dtype: object# Counting variables by type
df.dtypes.value_counts(ascending=True)int64      4
float64     5
object     7
dtype: int64# Detecting missing values
print(f"Are there any missing values? {df.isnull().values.any()}")Are there any missing values? False# Visualization of correlations (heatmap)
mask = np.triu(df.corr(), 1)
plt.figure(figsize=(19, 9))
sns.heatmap(df.corr(), annot=True, vmax=1, vmin = -1, square=True, cmap='BrBG', mask=mask);

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

Seaborn 热图(皮尔逊方法)

变量'emp_var_rate''nr_employed''euribor3m'非常多余。'nr_employed'与目标最相关。

为了对目前的数据有一个清晰和更准确的认识,我将展示一般的统计数据。

# General stats of numeric variables adding 'variance' valuesdescribe = df.describe()
describe.append(pd.Series(df.var(), name='variance'))

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

数字变量的一般统计

年龄:最小的客户 17 岁,最大的客户 98 岁,中位数为 38 岁,而平均年龄为 40 岁。分布向左倾斜。这可能表明异常值的存在。

Pdays :从上一次活动中最后一次联系客户后经过的天数。大多数客户都有 999 号码,这表明大多数人没有与银行联系,也没有被银行联系。那些 999 被认为是“超出范围”的值。

上一次:在本次活动之前,每个客户的联系次数。绝大多数人从未被联系过。

Emp_var_rate :就业变动率。在此期间,指数从[-3.4,1.4]不等。

Cons_price_idx :居民消费价格指数从【92.2,94.8】不等。

Cons_conf_idx :该期间消费者信心水平始终保持负值,变动幅度为[-51,-27]。这些负值可能是因为在记录数据的同一时期,由于全球金融危机,经济衰退严重影响了葡萄牙。

Euribor3m :在分析期间,Euribor 利率出现了巨大的变化【5%至 0.6%】。这种波动加上上文验证的负面信心加强了数据提供危机时期信息的假设。

活动期间,就业人数在 200 人左右。

df.describe(include=['object']) # General stats of categoric variables

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

类别变量的一般统计

工作:有 12 种类型的工作记录,其中管理角色是最常见的,几乎占所有客户端的 10.5k。

婚姻:大部分客户已婚,有近 25k 记录。

学历:12k 以上的人有大学学历。

违约:在所有 41.188 个客户中,32.588 个没有任何信用违约。

住房:几乎一半的客户都有住房贷款。

贷款:几乎 34k 客户没有任何个人贷款。

没有任何关于之前营销活动结果的信息。

所有变量的统计描述

为了能够对数字和类别变量进行分析,我将首先按照变量的类型分别定义和创建一个特性列表。

# creating indexescat_features = list(df.select_dtypes('object').columns)
int_features = list(df.select_dtypes('int64').columns)
float_features = list(df.select_dtypes('float64').columns)
num_features = int_features+float_features

EDA 过程的下一步包括提供数据集中所有变量的完整描述,从数字变量开始。

# Visualization of the numeric distributiondf[num_features].hist(figsize=(10,8), bins=25, xlabelsize=8, ylabelsize=8, alpha=0.9, grid=False)
plt.tight_layout();

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

数值分布的可视化

**Age**

# creating a dataframe
stats_age = {'Designation': ['Value'],
             'Variable': 'age',
             'Description': 'clients` age',
             'Type of variable': df.age.dtype,
             'Type of distribution': 'continuous',
             'Total observations': df.age.shape[0],
             'Missing values': df.age.isnull().sum(),
             'Unique values': df.age.nunique(),
             'Min': df.age.min(),
             '25%': int(df.age.quantile(q=[.25]).iloc[-1]),
             'Median': df.age.median(),
             '75%': int(df.age.quantile(q=[.75]).iloc[-1]),
             'Max': df.age.max(),
             'Mean': df.age.mean(),
             'Std dev': df.age.std(),
             'Variance': df.age.var(),
             'Skewness': scipy.stats.skew(df.age),
             'Kurtosis': scipy.stats.kurtosis(df.age)
            }st_age = pd.DataFrame(stats_age, columns = ['Designation',
                                          'Variable',
                                          'Description',
                                          'Type of variable',
                                          'Type of distribution',
                                          'Total observations',
                                          'Missing values',
                                          'Unique values',
                                          'Min',
                                          '25%',
                                          'Median',
                                          '75%',
                                          'Max',
                                          'Mean',
                                          'Std dev',
                                          'Variance',
                                          'Skewness',
                                          'Kurtosis'
                                             ])st_age.set_index("Designation", inplace=True)results = st_age.T # transposing the dataframe
resultsT = st_age
display(results)

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

由数据帧呈现的完整描述

非常重要的一点是,要将分布和离散可视化,如下所示。

# Visualization of 'age'
# creating a distribution graph and bloxplot combinedage = df.age
np.array(age).mean()
np.median(age)f, (ax_box, ax_hist) = plt.subplots(2, sharex=True, gridspec_kw= {"height_ratios": (0.5, 2)})mean=np.array(age).mean()
median=np.median(age)sns.boxplot(age, ax=ax_box)
ax_box.axvline(mean, color='r', linestyle='--')
ax_box.axvline(median, color='g', linestyle='-')sns.distplot(age, ax=ax_hist)
ax_hist.axvline(mean, color='r', linestyle='--')
ax_hist.axvline(median, color='g', linestyle='-')plt.legend({'Mean':mean,'Median':median})
ax_box.set(xlabel='')plt.show()

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

数据的分布和分散

百分点计算:1%,5%,95%,99%

display(df.age.quantile(q=[.01, .05, .95, .99]))0.01    23.0
0.05    26.0
0.95    58.0
0.99    71.0
Name: age, dtype: float64

为了能够根据目标可视化变量,我们必须首先定义两个组:必须订阅的客户端和没有订阅的客户端(让我们分别称它们为“好”和“坏”客户端)。

# Visualization variable vs. targetage_0 = df[df.target == 0].iloc[:,:1]
age_1 = df[df.target == 1].iloc[:,:1]a = np.array(age_0)
b = np.array(age_1)np.warnings.filterwarnings('ignore')plt.hist(a, bins=40, density=True, color="r", alpha = 0.6, label='Bad client')
plt.hist(b, bins=40, density=True, color="g", alpha = 0.6, label='Good client')plt.legend(loc='upper right')
plt.title('age', fontsize=14)
plt.xlabel('age')
plt.ylabel('absolute frequency');

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

相对于目标的可变“年龄”

从比例上看,年龄在 30 岁以下和 60 岁以上的用户比 30 岁至 60 岁的用户多。

让我们更进一步,使用cut 方法,按照年龄将订阅的客户分为三个类别:年轻(<=30), adult (> 30 到<=60), and senior (> 60)。

df['age_bins'] = pd.cut(df['age'], bins = [df['age'].min(), 30, 60, df['age'].max()],labels=['Young', 'Adult', 'Senior'])​group_age_target = df.groupby(['age_bins'])['target'].mean().multiply(100)display(group_age_target)group_age_target.plot.barh()
plt.xlabel('Subscribed [%]');

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

使用 cut()方法对订阅客户端进行分组

  • 45.5%的老年人(+60 岁)认购定期存款。
  • 不到十分之一的成年人(> 30 和<=60 years old) subscribed.
  • Young people were the 2nd group that subscribed to the deposit corresponding to 1/6 of all young people.
  • Senior subscribers alone were almost as much as Young and Adults subscribers, respectively, all together.

Following the previous structure, I’ll be only displaying visuals for a greater understanding. The full code can be seen 此处)。

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

由数据帧呈现的完整描述

百分点计算:1%,5%,95%,99%

display(df.pdays.quantile(q=[.01, .05, .95, .99]))0.01      3.0
0.05    999.0
0.95    999.0
0.99    999.0
Name: pdays, dtype: float64

接下来,可视化数据的分布以及相对于目标的变量。

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

左边是分布,右边是相对于目标的变量

仅考虑那些必须订阅的客户,让我们来数一数从上一次活动联系后过去了多少天。大多数人会在第 6 天和 7 到 8 天内做出反应,你可以在下面观察。

dummy = df.loc[(df['pdays']!=999) & (df['target'] == 1), 'pdays']
print('Median: {:.2}'.format(dummy.median()))
dummy.hist().grid(False)
plt.title('Histogram')
plt.xlabel('Couting days after contact \n for those who subscribed')

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

**Previous**

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

由数据帧呈现的完整描述

百分点计算:1%,5%,95%,99%

display(df.previous.quantile(q=[.01, .05, .95, .99]))0.01    0.0
0.05    0.0
0.95    1.0
0.99    2.0
Name: previous, dtype: float64

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

下图显示,之前联系的客户以高得多的利率认购了定期存款。

仅考虑从未联系过的客户,只有 10%订阅,而之前联系过两次或更多的客户,活动的成功率增加到 45%以上。

group = df.groupby(['previous'])['target'].mean().multiply(100)
group.plot.barh()
plt.xlabel('Subscribed [%]');print('How many people got previously contacted? {}'.format(df.loc[df['previous']!=0].shape[0]))print('How many people got contacted 7 times? {}'.format(df.loc[df['previous']==7, 'previous'].count()))print('How many people got previously contacted with success? {}'.format(df.poutcome.value_counts()[1]))print('How many people got previously contacted without success? {}'.format(df.poutcome.value_counts()[2]))
  • 之前联系了多少人?5625
  • 有多少人被联系了 7 次?一
  • 有多少人以前接触过成功?4525
  • 之前有多少人联系不上?1373

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

索引变量

数据集中有 4 个宏观评级变量或经济指标:‘EMP _ var _ rate’‘cons _ price _ idx’‘cons _ conf _ idx’‘euribor 3m’

让我们进一步挖掘,简要调查它们的相关性,并检查这些指标之间以及指标之间是否有任何趋势或模式。为此,我必须创建一个仅包含这些特定变量的列表,并并排显示它们(pairplot 方法)。

注意:我们将在这个项目的稍后部分(但是在另一篇文章中)回到数据争论:清理和特性工程一节中的相关性主题。

# creating a list
idx_list = ["cons_price_idx", "cons_conf_idx", "euribor3m", "emp_var_rate", "target"]df[idx_list].corr()

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

我们可以看到,euribor3mcons_price_idxemp_Var_rate高度相关。接下来,使用 pairplot 方法可视化指数变量之间的相关性。

sns.pairplot(df[idx_list], hue="target")
plt.show()

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

指数变量相关性的可视化(pairplot)

散点图中我们可以观察到什么?请记住,(蓝色)0 =否,(橙色)1 =是

  • euribor3memp_var_rate.正变化时增加
  • cons_conf_idxcons_price_idxemp_var_rate线性变化:物价和就业率越高,信心指数越低。
  • emp_var_rate(就业率)增加cons_price_idx(物价指数)也增加。

活动的产出会受到指数变量的影响吗?答案来自对分布图的观察。

  • euribor3m越低,订阅数越高。
  • cons_price_idx(消费者价格指数)增加时,客户订阅会产生强烈的负面反应。
  • emp_var_rate(就业率)为负时,对该活动的积极响应更高。

Nr _ 已就业

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

由数据帧呈现的完整描述

百分点计算:1%,5%,95%,99%

display(df.nr_employed.quantile(q=[.01, .05, .95, .99]))0.01    4963.6
0.05    5017.5
0.95    5228.1
0.99    5228.1
Name: nr_employed, dtype: float64

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

从分析中,我们知道被联系的人有更高的订阅率。上面的直方图显示,第一次联系专门针对已知客户,这导致了一个雇佣人数较少、效率更高的活动。

让我们继续讨论分类变量的描述。

职位

“作业”有 12 个唯一值。有一个标记为“unknown”的类被认为是缺失值(我暂时不会对缺失值做任何处理)。

stats_job = {'Designation': ['Value'],
            'Variable': 'job',
            'Description': 'type of job',
            'Type of variable': df.job.dtype,
            'Total observations': df.job.shape[0],
            'Unique values': df.job.nunique(),
           }st_job = pd.DataFrame(stats_job, columns = ['Designation',
                                      'Variable',
                                      'Description',
                                      'Type of variable',
                                      'Total observations',
                                      'Unique values',
                                          ])st_job.set_index("Designation", inplace=True)​results = st_job.T
resultsT = st_job
display(results)print(f"List of unique values: {df.job.unique()}")

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

由数据帧呈现的完整描述

客户的工作是如何分配的?

data_count = df['job'].value_counts().plot(kind='bar', figsize=(6,4), fontsize=12)
plt.title('Categorical variable \'job\'', fontsize=12)
plt.xlabel('Jobs')
plt.ylabel('Absolute frequency');

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

下面,我们可以找到绝对值(工作的总和)和它们的比例。5 个最常见的作业足以代表 80%的数据。

num_obs = df.job.value_counts()
num_o = pd.DataFrame(num_obs)
num_o.rename(columns={"job":"Freq abs"}, inplace=True)
num_o_pc = (df.job.value_counts(normalize=True) * 100).round(decimals=2)
num_obs_pc = pd.DataFrame(num_o_pc)
num_obs_pc.rename(columns={"job":"percent %"}, inplace=True)
n_obs = pd.concat([num_o,num_obs_pc], axis=1)display(n_obs)

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

job_0 = df[df.target == 0].iloc[:,1:2]
job_1 = df[df.target == 1].iloc[:,1:2]a = np.array(job_0)
b = np.array(job_1)np.warnings.filterwarnings('ignore')plt.hist(a, bins=40, color="r", alpha = 0.8, label='Bad client', align="left")
plt.hist(b, bins=40, color="g", alpha = 0.8, label='Good client', align="right")plt.legend(loc='upper right')
plt.title('job', fontsize=12)
plt.xlabel('Professional ocupation')
plt.xticks(rotation='vertical')
plt.ylabel('Absolute frequency');

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

这些课程是“管理”、“蓝领”、“技术人员”、“管理人员”和“服务人员”是大多数客户必须订阅的工作,但就比例而言,“学生”和“退休人员”是最具代表性的。

下面我们看到“退休”和“女佣”是最老的客户,也是比其他任何一个阶层接受订阅更多的客户。

type_pivot = df.pivot_table(
    columns="target",
    index="job",
    values="age", aggfunc=np.mean)type_pivot.sort_values(by=["job"], ascending=True).plot(kind="bar", title=("Type of customer by professional occupation and age"), figsize=(6,4), fontsize = 12);

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

婚姻的

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

由数据帧呈现的完整描述

“婚姻”有 4 个独特的价值。如下图所示,图表显示,占主导地位的阶层是 61%的“已婚”人士,而“离婚”客户占所有客户的 11%。

# pie chart
df['marital'].value_counts(dropna=False).plot(kind='pie', figsize=(14,9), explode = (0.01, 0.01, 0.01, 0.01), autopct='%1.1f%%', startangle=120);# table
marital_obs = df.marital.value_counts()
marital_o = pd.DataFrame(marital_obs)
marital_o.rename(columns={"marital":"Freq abs"}, inplace=True)
marital_o_pc = (df.marital.value_counts(normalize=True) *100).round(decimals=2)
marital_obs_pc = pd.DataFrame(marital_o_pc)
marital_obs_pc.rename(columns={"marital":"percent %"}, inplace=True)
marital_obs = pd.concat([marital_o,marital_obs_pc], axis=1)
marital_obs

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

按类别观察

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

教育

“教育”有 8 个独特的价值。前 4 个教育水平对应 80%的数据。拥有 4 年基础教育或不识字的客户年龄最大,容易订购该产品。

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

默认

有了 3 个唯一的值,类“yes”就没有意义,变量没有表达,完全不平衡。

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

房屋

该变量有 3 个唯一值,其中“未知”被解释为缺失值,代表 2%的观察值。“是”和“否”的比例非常接近,可能会降低其预测能力。

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

贷款

虽然,一般来说,“贷款”显示了大量的非用户,这个变量与“住房”有一些相似之处,在某种意义上,按比例,“是”和“否”是非常均匀的。这又一次降低了它的预测能力。

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

噘嘴

有趣的事实:在之前成功的促销活动中接触过的客户中,这次大多数都订阅了。

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

最常见的类别有哪些?

详细的分析给了我们大量关于数据、客户和变量行为的信息。我们来做一个概述。

n = len(cat_features)
i=1
plt.figure(figsize=(16,14))for feature in df[cat_features]:
plt.subplot(round(n/2),round(n/3), i)
df[feature].value_counts().plot.bar()
plt.xticks(rotation=90)
plt.title(feature)
i+=1plt.tight_layout();

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

最常见:

  • 工作:行政
  • 婚姻状况:已婚
  • 教育:大学学位
  • 违约信用:否
  • 住房:是的,但是没有住房贷款是非常接近的
  • 贷款:没有
  • poutcome:没有参加以前的活动

请注意,除了“poutcome”变量之外,所有特性都包含“未知”类别。

这些类别如何影响目标变量?

n = len(cat_features)
i=1
plt.figure(figsize=(16,14))for feature in df[cat_features]:
plt.subplot(round(n/2),round(n/3), i)
df.groupby([feature])['target'].mean().multiply(100).plot.barh()
plt.xlabel('Subscribed [%]')
plt.title(feature)
i+=1plt.tight_layout();

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

观察:

  • “学生”和“退休人员”的订阅比例最高(> 25%),而“蓝领”和“服务人员”的订阅比例最低。
  • “文盲”的用户比例最高(> 20%),另一方面,“基本 9y”、“基本 6y”和“基本 4y”的用户比例最低。
  • 有信用违约的人没有认购。
  • 之前联系过其他活动的人中有超过 60%的人进行了订阅。
  • 婚姻状况、有无贷款和住房对认购率没有太大影响。

结论

我一直专注于如何开始一个机器学习项目,从最重要的部分开始,让我们超越数据,探索性数据分析。这是一个非常重要的程序,因为如果你没有深刻理解你将要处理的数据,它将会是一片混乱。

在下一篇文章(数据清理和特征选择)中,我将进行特征工程和特征选择,清理数据集,处理我们可能会发现的异常以及插补和转换。

在最后一部分和第三篇文章(机器学习:预测建模)中,我们将训练一些机器学习模型,以便能够选择最佳模型,并找出预测营销活动最小成本的最重要特征。

  • 你可以在这里找到这个项目的全部代码。

查看您可能也会喜欢的其他文章:

[## 描述性统计:期望与现实(探索性数据分析——EDA)

一种简单的描述性统计方法来总结集中趋势的措施和传播的措施

towardsdatascience.com](/descriptive-statistics-expectations-vs-reality-exploratory-data-analysis-eda-8336b1d0c60b) [## 熊猫变得容易(指南— I)

有许多最常用的函数和方法的例子

towardsdatascience.com](/pandas-made-easy-the-guide-i-81834f075893) [## 营销活动的成本预测(数据清理和特征选择——第二部分)

预测营销活动最佳目标候选人的数据科学方法

towardsdatascience.com](/costs-prediction-of-a-marketing-campaign-data-cleaning-feature-selection-part-ii-6aa5298909b5)

就是这样!我希望你喜欢读这篇文章,就像我喜欢写它一样。

联系人

好的阅读,伟大的编码!

机器学习:模型构建的数据洞察

原文:https://towardsdatascience.com/machine-learning-data-insights-for-model-building-b6bdea0ac092?source=collection_archive---------30-----------------------

一种数据驱动的增量式机器学习模型构建方法

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

在这篇文章中,我将以最简单的方式,展示一个人如何以一种递增的激情来解决一个问题。这种方法可以解释为数据驱动的方法,因为我们将依赖数据本身所寻求的信息来做出一些决策。该数据集将包含 2014 年 5 月至 2015 年 5 月期间西雅图出售的房屋价格。在本文中,我们将尝试找出价格和其他参数之间的关系。

获取和观察数据

数据可以来自任何来源,然而,对于这篇特定的文章,我将使用来自 Kaggle 的数据(在公共领域下可用)。我们的数据会像这样。

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

我们数据集中的几列

这个数据直接从 描述熊猫 的样子;

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 21613 entries, 0 to 21612
Data columns (total 21 columns):
id               21613 non-null int64
date             21613 non-null object
price            21613 non-null float64
bedrooms         21613 non-null int64
bathrooms        21613 non-null float64
sqft_living      21613 non-null int64
sqft_lot         21613 non-null int64
floors           21613 non-null float64
waterfront       21613 non-null int64
view             21613 non-null int64
condition        21613 non-null int64
grade            21613 non-null int64
sqft_above       21613 non-null int64
sqft_basement    21613 non-null int64
yr_built         21613 non-null int64
yr_renovated     21613 non-null int64
zipcode          21613 non-null int64
lat              21613 non-null float64
long             21613 non-null float64
sqft_living15    21613 non-null int64
sqft_lot15       21613 non-null int64
dtypes: float64(5), int64(15), object(1)
memory usage: 3.5+ MB

分析数据

既然我们已经找到了数据集中的属性(或要素),我们可以绘制图表来查看可能分布的属性数量。一种方法是为每个属性绘制直方图。

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

直方图

查看一些属性的直方图,我们可以看到它们是分布的。事实上,这表示属性具有变化的值,从而导致预测属性(价格)的变化。为了看到我们将看到的相关性。俗称 皮尔逊相关系数

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

相关

我们可以看到 价格 多少会随着一套房子里几个地方的 号卧室卫生间平方英尺数字 而有所不同。这为我们提供了一个线索,因为这些属性作为我们模型的输入可能实际上是有意义的。请注意,我们是基于我们的数据而不是直觉做出这一决定的。很明显,价格会随着建筑面积的变化而变化。

您可能已经注意到,在我们的数据中,我们也给出了位置。我们不妨使用它们来看看位置作为输入是否有意义。对于该任务,我们可以将价格可视化为西雅图城市地图上的热图。

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

不同地点的价格

在上面的图中,价格以价格递增的顺序用蓝色到红色标出。虽然不是很明显,但是每个分散点的比例描述了房子覆盖的正方形区域。仅通过观察地块的颜色,我们可以说价格分布没有受到地理位置的显著影响(尽管在滨水区附近看到昂贵的房子是有意义的)。这让我们摆脱了位置信息,因为它不是决定价格的主要因素。

预处理数据

至于预处理步骤,我们对数据集进行标准化和缩放,使得每个属性都表示为范围 [-1,1] 内的一个数字。这对于使用神经网络训练模型非常有帮助。使用 sci-kit-learn 库本身可以很容易地逆转缩放转换。

建立模型

我尝试了几种使用均方根误差(RMS) 进行评估的模型。这是因为选择正确模型的决定可以通过选择报告最小 RMS 误差的模型来决定。

回归

回归几乎总是分析的首选。这是因为它能够为这种关系提供可靠的数学表达式。然而,在这个实验中,我的均方根误差为 0.71。虽然这个值可能没有意义,但是我们确实可以将这个值与其他模型进行比较。这里我使用了线性回归,它假设标签值和特征之间存在线性关系。

决策图表

决策树被训练为使用一个被遍历以估计目标值的树来挑选值。观察到的均方根误差为 0.87。这意味着模型在训练数据集中训练得太多了。我们称此为 过拟合 。这可以通过再次运行以预测返回 0.03 RMS 误差的训练数据集来确认。

随机森林

这可以被认为是对我们模型的改进。这是因为在随机森林中,随机的一组树被收集起来用于决策。树/估计器的数量可以预先设定。使用 100 个估值器得到的均方根误差为 0.68。我们对回归模型做了一点点改进。

人工神经网络

使用神经网络可以被认为是决策树的图形版本。然而,在神经网络中,我们将调整权重来估计最终输出。如果你有兴趣了解一些神经网络的基础知识,你可以阅读我以前的文章。

[## 神经网络导论

神经网络基础

towardsdatascience.com](/introduction-to-neural-networks-ead8ec1dc4dd)

我使用了一个非常简单的带有 Keras functional API 的架构。

i = tf.keras.layers.Input(8)
ix = tf.keras.layers.Dense(16, activation='relu')(i)
z = tf.keras.layers.Dense(1)(ix)model = tf.keras.Model(i, z)
model.compile(loss='mse', optimizer='sgd', metrics=['mse'])
model.summary()
tf.keras.utils.plot_model(model)

然而,我能够实现 0.64 的最低均方根误差。

结束语

  • 重要的是先观察数据,而不是在整个数据集上尝试几种方法
  • 有人可能会建议使用特征提取技术,如 PCA 或邻居嵌入。然而,具有除了真正相关的特征之外的特征可能会增加不必要的噪声,导致过度拟合。
  • 虽然我在这篇文章中没有发现,最近邻回归可能表现良好。这是因为我们打算预测的数据很可能在训练数据的闭合范围内。

我相信这篇文章将有助于人们从可视化数据开始,并使用这些见解建立一个适当的机器学习模型。

感谢阅读。完整的 jupyter 笔记本附后。

干杯!!

使用 Python 进行机器学习部署

原文:https://towardsdatascience.com/machine-learning-deployment-with-python-e64a37c3155a?source=collection_archive---------58-----------------------

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

鸣谢:L.J. Stroemsdoerfer(无艺术家)

机器学习部署绝对是现在的热门话题。我正准备用时下最热门的模因来支持我的第一句话,然而,我觉得业内的每个人都同意我的观点。有许多很酷的方法来部署和操作 ML 模型。然而,他们大多引入新的工具,使用他们自己的生态系统。这增加了一层新的复杂性,最终可能会产生锁定效应,因为您需要调整代码以最佳地适应平台。

开源概念,比如 Docker 和 Kubernetes 在这个问题上给予了更多的自由,但是,使用起来非常复杂。因此,我构建了一个 Python 库,允许您在 Kubernetes 上专业化、测试和部署您的模型,但是您不必为此而离开 Python。听起来好得难以置信?好吧,让我们看看你是怎么想的。

生产化图书馆

除了这个糟糕的包名——建议是非常受欢迎的——这个包允许你做一些漂亮的事情来简化和加速你的部署体验。

我们先来看看名字朗朗上口的库是做什么的。

它是做什么的?

简单回答:它允许你在不离开 Python 的情况下容器化你的 ML 模型。最重要的是,它在您的机器上构建一个本地 Kubernetes 集群来测试容器化的模型是否工作正常。如果你在想,等等,我没有本地的 Kubernetes 集群,不要担心,我内置了一些函数来处理这个问题。让我们仔细看看。

要开始您的生产化之旅,您可以首先设置您的本地“工作台”,我称之为“工作台”。这是一个小型集群,带有 Docker 注册表,运行在您机器上的 VM 中。任何以前做过这种噱头的人都知道,这样做有点烦人。使用 productionize,这是两行 Python 代码。

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

生产化的工作流。

一旦这个“工作台”开始运行,productionize 库就需要一个已经内置在 API 结构中的 ML 模型。为此,您可以使用 Flask 等工具,也可以使用其他工具。然而,我肯定会推荐 Flask,因为我真的很喜欢它的轻量级方法。

有了几行 Python 代码,您就可以将 API 容器化,并将其部署到本地工作台中进行测试。如果一切正常,那么您可以将容器推送到您可能喜欢的任何 Kubernetes 集群。那么,让我们来看看代码。

你怎么能这样做?

首先,您需要安装托管在 PyPi 上的库。我目前不支持康达,请原谅我。

之后,就可以导入库了。请注意,该库目前不支持 Jupyter 笔记本电脑,因为我没有使用 Jupyter 内核来设置虚拟机,Minikube 集群和所有其他细节组件。

该库包含两个主要的类。第一个是workbench()类,它负责在您的机器上完成所有这些令人惊奇的事情所需的工具。第二个是product()类,它处理你的 API 和它的容器化。

让我们从设置工作台开始。workbench()类将为你安装、管理和卸载 Docker、VirtualBox、Kubectl 和 Minikube。首先,我们初始化这个类。这将检查您的本地机器上的上述组件,并标记那些要安装的组件。

现在,我们可以安装缺少的组件,并对它们进行配置,使它们能够很好地相互协作。在接下来的步骤中,您可能需要输入您的 sudo 密码。

如果这一步出错,我为此添加了一个调试方法。假设 Minikube 安装失败,您可以运行:

一旦设置步骤完成,您就可以启动工作台,这实际上启动了您机器上的 Minikube 集群。

接下来,您应该在工作台上创建一个项目,这会创建一个 Kubernetes 名称空间。我建议你这样做,这会在你的集群上产生一些秩序感。

如果您厌倦了您的工作台,您可以使用stop_cluster()方法轻松地停止集群,甚至可以使用uninstall()方法干净地删除所有不需要的组件。

现在让我们继续学习product()课程。这个类将您的 ML API 转换成一个容器,并将其部署到工作台。首先,我们必须初始化这个类:

您现在可以准备部署了,这实际上将创建一个 Dockerfile 文件。我添加了这个中间步骤,以便您可以根据需要编辑 Dockerfile 文件。

无论您是否编辑了 docker 文件,现在都可以使用deploy()方法将它部署到本地工作台。

这将在 Minikube 注册表上创建 Docker 映像,使用您的容器部署一个 pod,并将服务公开给外部。在deploy()方法的输出中,您会找到指向您的 API 的链接。你可以用它来测试你的模型是否工作正常。如果是的话,你可以把它推到任何你想要的 Kubernetes 集群。您可以使用push_product()方法并传递您的 Kubernetes 集群的注册表链接来实现。

好吧,那是很多。我知道这个结构有点复杂,所以又总结了一遍。

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

将工作流程生产化到最佳状态。

GitHub 和 PyPi 上有更多的信息和文档。你可以去看看。此外,当然还有一些有趣的复活节彩蛋。

下一步是什么?

正如你所看到的,这个库提供了一些不错的特性,但是,它还远远没有完成。目前,productionize 只在 macOS 上运行。这是因为我使用家酿作为主要的软件包管理器。我已经在为 Ubuntu 开发一个版本了。任何 linux 发行版都是可管理的,然而,Windows 将是一个相当大的挑战。因此,如果你有建议或想法,请让我知道。此外,如果你给我一个关于https://github.com/LJStroemsdoerfer/productionize的问题,我会非常乐意处理任何 bug。

机器学习值得拥有自己的持续交付风格

原文:https://towardsdatascience.com/machine-learning-deserves-its-own-flavor-of-continuous-delivery-f4d1e76e6b69?source=collection_archive---------47-----------------------

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

mmmswan via flickr

当作为一个美国人在加拿大旅行时,事情感觉略有不同,但却惊人地相似。例如,麦当劳吸管上的红色竖线要粗一些。这很像我作为一名软件工程师在数据科学领域的旅行。

虽然数据科学世界很神奇,但我很怀念古典软件项目中 连续交付(CD) **的精炼状态。**什么是持续交付?

马丁·福勒 发生以下情况时,您正在进行连续交付:

  1. 您的软件在其整个生命周期中都是可部署的
  2. 你的团队优先考虑保持软件的可部署性,而不是开发新的特性
  3. 任何人都可以在任何时候对他们的系统进行更改时获得快速、自动化的生产就绪性反馈
  4. 您可以按需将任何版本的软件部署到任何环境中

对于一个部署到 Heroku 的小规模软件项目来说,持续交付(以及它的超级活跃的兄弟持续部署 )是一幅轻松优雅的画面。您可以在几分钟内设置好 CI ,这意味着您的单元测试会在每次推送 git repo 时运行。你让 Review Apps 预览来自 GitHub pull 请求的应用。最后,每个git push to master 都会自动部署你的 app。所有这一切只需要不到一个小时的时间来配置。

现在,为什么同样的过程不适用于我们缠绕在单个*predict函数上的纠结的纱线团呢?嗯,数据科学的世界不容易理解,除非你深入到它的内部省份。让我们看看为什么我们需要CD4ML以及你今天如何在你的机器学习项目中实现它。*

为什么经典 CD 不适用于机器学习

我在一个机器学习项目中看到了 6 个关键差异,它们使得经典软件 CD 系统难以应用:

1.机器学习项目有多种可交付成果

不像传统的软件项目仅仅是为了交付应用程序而存在,机器学习项目有多种交付方式:

  • ML 模型——经过训练和序列化的模型,每个模型都有评估指标。
  • web 服务—通过 HTTP API 提供模型推理结果的应用程序。
  • 报告—生成的分析结果(通常来自笔记本),总结了关键发现。这些可以是静态的,也可以是使用像 Streamlit 这样的工具进行交互的。

拥有多个可交付成果——每个都有不同的构建过程和最终演示——比编译单个应用程序更复杂。因为其中的每一个都是彼此紧密耦合的——并且与数据紧密耦合——为每一个都创建单独的项目是没有意义的。

2.笔记本很难复习

git 分支上的代码审查是如此普遍,它们被烘烤到 GitHub 和其他托管版本控制系统中。GitHub 的代码审查系统对于*.py文件来说很棒,但是对于查看 JSON 格式文件的更改来说很糟糕。可惜笔记本文件(*.ipynb)就是这么存的。这尤其令人痛苦,因为笔记本——而不是将逻辑抽象成*.py文件——是几乎所有数据科学项目的起点。

3.测试不是简单的通过/失败

Elle O’Brien 介绍了使用 CI 进行模型评估的模糊性。

通过对代码分支运行单元测试套件,很容易指出一个经典软件 git 分支是否可以合并。这些测试包含简单的真/假断言(例如:“用户可以注册吗?”).模型评估更加困难,通常需要数据科学家手动审查,因为评估指标通常会向不同的方向变化。这个阶段更像是经典软件项目中的代码审查。

4.实验对比 git 分支

传统项目中的软件工程师在处理 bug 或增强时会创建小的、集中的 git 分支。虽然分支是轻量级的,但是它们不同于模型训练实验,因为它们通常最终被部署。模型实验?像鱼卵一样,绝大多数永远见不到开阔的水域。此外,与传统软件 git 分支相比,实验可能只有很少的代码更改(例如:调整一个超参数)。

5.非常大的文件

大多数 web 应用程序不在它们的 git 存储库中存储大文件。大多数数据科学项目都是如此。数据几乎总是需要这样。模型可能也需要这样做(在 git 中保存二进制文件也没有什么意义)。

6.可再现输出

对于传统软件项目的任何开发人员来说,重现应用程序在任何时间点的状态都很容易。该应用程序通常只在两个方面发生变化——代码和数据库的结构。在 ML 项目中很难达到一个可再现的状态,因为许多维度都可以改变(数据量、数据模式、特征提取和模型选择)。

一个简单的 CD 系统如何寻找机器学习?

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

使 CD4ML 变得生动的一些工具。

在优秀的机器学习连续交付中, Thoughtworks 团队提供了一个示例 ML 应用,它展示了一个 CD4ML 实现。让它运行起来涉及到许多移动部件:GoCD、Kubernetes、DVC、Google Storage、MLFlow、Docker 和 EFK 堆栈(ElasticSearch、FluentD 和 Kibana)。对于 Throughworks 的企业客户来说,组装这 10 个部分是容易做到的,但是对于较小的组织来说就有些困难了。精益组织如何实施 CD4ML?

以下是我的建议,按照我首先要做的事情排序。早期的项目更容易接近。后面的项目建立在基础之上,在适当的时候增加更多的自动化。

1.从 Cookiecutter 数据科学开始

在创建一个新的 Rails 项目之前,没有人会无所事事地去弄清楚他们想把自己的视图放在哪里;他们只是像其他人一样运行 rails new 来获得一个标准的项目框架。

viaCookiecutter 数据科学

当我查看现有 Ruby on Rails 应用程序的源代码时,我可以很容易地浏览,因为它们都遵循相同的结构。不幸的是,大多数数据科学项目不使用共享的项目框架。然而,事情并不一定是这样的:从《烹饪与数据科学》开始你的数据科学项目,而不是想象出你自己独特的结构。

Cookiecutter Data Science 建立了一个适用于大多数项目的项目结构,创建了像datamodelsnotebookssrc这样的目录(用于共享源代码)。

2.nbdime 或 ReviewNB 获得更好的笔记本代码审查

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

nbdime 是一个 Python 包,使得查看笔记本文件中的更改更加容易。

很难在标准的比较工具中查看对*.ipynb的更改。对一个*.py脚本进行代码审查是微不足道的,但是对于一个 JSON 格式的笔记本来说几乎是不可能的。 nbdimeReviewNB 让这个过程更容易。

3.数据文件的 dvc

*dvc add data/ git commit -ma "Storing data dir in DVC" git push dvc push*

安装 dvc 并添加遥控器后,以上就是用 dvc 对您的data/目录进行版本控制所需的全部内容。

很容易提交大文件(esc。数据文件)复制到 git repo。Git 不能很好地处理大文件:它降低了速度,会导致回购文件的大小快速增长,而且无论如何你都不能真正地查看这些文件的差异。一个获得大量大文件版本控制的解决方案是数据版本控制(dvc) 。dvc 易于安装(只需使用pip)并且其命令结构模仿 git。

但是等等——您直接从数据仓库中查询数据,并且没有大型数据文件?这是不好的,因为它几乎保证了你的 ML 项目是不可复制的:数据和模式的数量几乎保证会随着时间而改变。相反,将这些查询结果转储到 CSV 文件中。存储很便宜,dvc 可以轻松处理这些大文件。

4.用于可再生训练管道的 dvc

dvc 不仅仅适用于大文件。正如 Christopher Samiullah 数据科学版本控制(DVC) 的第一印象中所说:

管道是 DVC 区别于其他能够处理大数据文件的版本控制工具的真正开始。DVC 流水线是典型的机器学习工作流(例如,数据加载、清理、特征工程、训练等)中有效的版本控制步骤。),以及预期的依赖项和输出。

您可以使用创建一个包含培训渠道的渠道阶段:

*dvc run -f train.dvc \ -d src/train.py -d data/ \ -o model.pkl \ python src/train.py data/ model.pkl*

dvc run命名这个阶段train,依赖train.pydata/目录,输出一个model.pkl模型。

稍后,您只需运行以下管道:

*dvc repro train.dvc*

这就是“可再生”的由来:

  • 如果依赖关系没有改变,那么dvc repo只需从远程存储中获取model.pkl。没有必要再次运行整个培训管道。
  • 如果依赖关系改变了,那么dvc repo会警告我们并重新运行这个步骤。

如果您想回到先前的状态(假设您有一个v1.0 git 标签):

*git checkout v1.0 dvc checkout*

运行dvc checkout会将data/目录和model.pkl恢复到之前的状态。

5.将慢速培训管道移至 CI 集群

重塑 DevOps 中,Elle O’brien 为使用 CI 来运行模型训练做了一个优雅的案例。我认为这很棒——CI 已经被用于在云中运行经典的软件测试套件。为什么不使用云中可用的更大的资源来为您的模型培训管道做同样的事情呢?简而言之,用您想要的实验变更来推进一个分支,并让 CI 进行训练和报告结果。

Christopher Samiullah 还涵盖了将培训转移到 CI 的内容,甚至提供了一个在 CI 流程中使用dvc repo train.dvcGitHub PR 的链接。

6.交付物特定的审核应用程序

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

Netlify 是一个针对静态站点的 PaaS,它允许您直接从 GitHub pull 请求中查看站点的当前版本。

像 Heroku 和 Netlify 这样的平台允许您直接从 GitHub pull 请求中查看应用程序的运行版本。这对于验证事情是否按预期运行是非常棒的。这对于向非技术团队成员展示工作非常有用。

使用 GitHub 动作做同样的事情,启动 Docker 容器来为您的交付服务。我会启动 web 服务和任何动态版本的报告(比如用 Streamlit 构建的东西)。

结论

就像健康饮食、刷牙、呼吸新鲜空气一样,在软件项目中实现持续交付没有任何负面影响。我们不能在机器学习项目上复制和粘贴经典的软件 CD 过程,因为 ML 项目将大型数据集联系在一起,这是一个缓慢的训练过程,不会生成明确的通过/失败验收测试,并且包含多种类型的可交付成果。相比之下,一个经典的软件项目只包含代码,并且只有一个可交付成果(一个应用程序)。

令人欣慰的是,现在有可能用现有的工具(git、Cookiecutter Data Science、nbdime、dvc 和 CI server)为非企业组织创建一个机器学习特定风格的连续交付( CD4ML )。

CD4ML 在行动我很想举一个机器学习项目的例子,它在 GitHub 上实现了一个精简的 CD4ML 堆栈,但是我在观众面前表现得更好。 订阅此处,在示例应用程序构建完成时收到通知!

在别处

原载于 2020 年 4 月 17 日https://booklet . ai*。*

机器学习能源需求预测项目—第一部分数据清理

原文:https://towardsdatascience.com/machine-learning-energy-demand-prediction-project-part-1-data-cleaning-841a7b657723?source=collection_archive---------45-----------------------

让我们看看我们的机器学习项目规划基本编码工具如何在现实世界的项目中实现!今天,我们将讨论如何利用温度数据来预测我们每天消耗的能量。我们从导入和清理数据开始,然后绘制和描述我们的能源使用情况,最后建模

这是三个中的第一部分。请随意编码,完整的项目在 GitHub 上。

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

马太·亨利在 Unsplash 上的照片

我们早上醒来,打开加热器/空调,从冰箱里找到一些酸奶做早餐,刮胡子,打开电脑,打开音乐,最后开始工作。这些任务都有一个共同点——它们使用电力!我们对电力的严重依赖使得估算我们每天需要产生多少能量变得至关重要。

但是,如果这看起来很有挑战性,不要担心。我们会一步一步来。在每个阶段,链接回它与我们的 ML 领域指南的关系。

我们从寻找能量和温度数据开始(没有它我们做不了什么😊).我们的是从气象局和澳大利亚能源市场运营商,但请复制另一个国家(即美国)的过程。在快速而轻松的下载之后(幸运的我们),我们可以简单地回顾一下我们的电子表格。但是看看这些数据就可以发现一个可怕的事实——要处理的事情实在是太多了!数字无情的细胞,更多的数字和类别,真的让人应接不暇。我们如何将一系列电子表格组合在一起,以及我们如何能够对其进行分析、学习或建模,都不是很清楚。

作为乐观的人,我们首先记下数据是如何组织的。包含文件的文件夹,它们在哪里,每个文件包含什么。将我们对数据结构的理解与导入技术结合起来,自然会让我们克服第一个恐惧——用代码提供对数据的轻松访问。

接下来,我们寻求消除笨拙的混乱。我们需要清理温度&能量数据,确定哪些信息对我们的净能量使用有最大的影响!它又一次从对电子表格的简单观察开始,以粗略地掌握当前的数据类型。我们特别感兴趣的是发现奇怪的怪癖/重复出现的模式,这些模式 可以表明有问题。一旦我们跟踪了每一个预感,我们就能对问题的根源更加自信。这让我们能够自信地决定直接删除、保留和快速修复什么🤔(我们不想去兰博👹对一切)。简单的统计数据和图表构成了这一分析的基础!

此时,我们已经成功地完成了项目的第一个也是最重要的部分!在短暂的庆祝之后,我们可以继续合并两个独立的数据集(一个用于能量,一个用于温度)。这使我们能够将两者联系起来。最后,我们能够描绘出我们在每个令人羡慕的日子、月份和年份中如何使用能源的故事…借助于我们在图表中看到的趋势和模式!究竟什么会更令人满意?嗯,几件事…但我们不要忘记创建一个模型(这将是有趣的)炫耀给我们所有的朋友!让我们不要操之过急,虽然…这都将在未来两个教程。

第 1 章—导入数据

数据有各种各样的形状和大小,所以我们用来将所有东西编码的过程经常会有所不同。

通过分析可用的文件,我们发现了我们的数据是如何构成的。我们从高层次开始,注意到有许多 CSV 格式的温度和能量电子表格。尽管数量惊人,但这只是因为数据被分成了小块。每个 CSV 都是上一个 CSV 的延续。实际温度电子表格包含日期,以及各种温度、湿度和降雨量的测量值。我们的能源文件要简单得多,只包含日期、能源需求历史、价格(RRP)以及数据是手动还是自动记录的。测量是在 30 分钟的基础上进行的。

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

各个击破!

正如我们所见,所有这些信息汇集在一起,形成了对原始数据的直观理解。当然,我们还不了解执行分析所需的一切,但我们有足够的东西从原始数据过渡到可用代码 🥳!

为了转换成代码,我们将我们的发现与我们的导入技术进行比较。我们知道我们有一个要合并的电子表格列表,所以我们可以首先形成列表,然后使用 Pandas concat将它们堆叠在一起。

energy_locations = os.listdir("../Data/Energy")
temperature_locations = os.listdir("../Data/Temperature")

energy_CSVs = [pd.read_csv("../Data/Energy/" + location) for location in energy_locations]
temperature_CSVs = [pd.read_csv("../Data/Temperature/" + location) for location in temperature_locations if "Data" in location]energy_data = pd.concat(energy_CSVs, ignore_index=True)
temperature_data = pd.concat(temperature_CSVs, ignore_index=True)

现在,信不信由你,我们已经完成了 90%的导入,唯一剩下的就是确保我们的特性(列)被简洁一致地命名。通过重命名我们的列(如下所示),我们可以清楚地了解每列中的内容。未来的我们一定会感激不尽!

energy_data.columns
temperature_data.columnsIndex(['REGION', 'SETTLEMENTDATE', 'TOTALDEMAND', 'RRP', 'PERIODTYPE'], dtype='object')
Index(['hm', 'Station Number', 'Year Month Day Hour Minutes in YYYY', 'MM',
       'DD', 'HH24', 'MI format in Local time',
       'Year Month Day Hour Minutes in YYYY.1', 'MM.1', 'DD.1', 'HH24.1',
       'MI format in Local standard time',
       'Precipitation since 9am local time in mm',
       'Quality of precipitation since 9am local time',
       'Air Temperature in degrees C', 'Quality of air temperature',
       'Wet bulb temperature in degrees C', 'Quality of Wet bulb temperature',
       'Dew point temperature in degrees C',
       'Quality of dew point temperature', 'Relative humidity in percentage %',
       'Quality of relative humidity', 'Wind speed in km/h',
       'Wind speed quality', 'Wind direction in degrees true',
       'Wind direction quality',
       'Speed of maximum windgust in last 10 minutes in  km/h',
       'Quality of speed of maximum windgust in last 10 minutes',
       'Mean sea level pressure in hPa', 'Quality of mean sea level pressure',
       'Station level pressure in hPa', 'Quality of station level pressure',
       'AWS Flag', '#'],
      dtype='object')energy_data.columns = ["Region", "Date", "TotalDemand", "RRP", "PeriodType"]
temperature_data.columns = [
    "HM", "StationNumber", "Year1", "Month1", "Day1", "Hour1", "Minute1", "Year", "Month", "Day", "Hour", "Minute", "Precipitation", "PrecipitationQuality",
    "AirTemperature", "AirTemperatureQuality", "WetBulbTemperature", "WetBulbTemperatureQuality", "DewTemperature", "DewTemperatureQuality", "RelativeHumidity",
    "RelativeHumidityQuality", "WindSpeed", "WindSpeedQuality", "WindDirection", "WindDirectionQuality", "WindgustSpeed", "WindgustSpeedQuality", "SeaPressure",
    "SeaPressureQuality", "StationPressure", "StationPressureQuality", "AWSFlag", "#"
]

现在骄傲吧,因为我们刚刚完成了旅程的第一部分!现在我们已经开始行动了,从现在开始事情会变得更加顺利。

第 2 章—数据清理

格式化数据

每个人都会被丢失的数据逼疯,但隧道的尽头总会有一线光明。

有好消息也有坏消息,所以我先从好消息说起。我们已经经历了把所有东西都放在一起的初始阶段,所以我们现在对我们可以获得什么/如何获得它有一个基本的了解。我们可以使用energy_datatemperature_data数据框查看我们的数据!

现在是坏消息。虽然我们可能还没有注意到,但我们的数据远非完美。我们有大量缺失的(空的)单元格,以及重复的和格式错误的数据。但是不要灰心,因为这不是一场罕见的大灾难:它一直都在发生😎(有什么不喜欢的?)😎。

这个过程看起来很危险,因为一切看起来都…一团糟。现在洞察力和经验确实很有帮助,但是但是…这并不意味着对我们凡人来说这是不可能的!我们可以做一件事来克服这一点——像疯狂的科学家一样工作!我们可以识别数据集的怪癖/问题,然后测试我们想到的每一种技术🤯。我们的技术来自现场指南(永远不要重新发明轮子)!

只是为了确保我们没有跑偏,下面是我们正在寻找的问题:

  • 完全空的列/行
  • 重复值
  • 不准确/通用的数据类型

是的,现在只有三个,但是…别忘了我们不会稳健分析!因此,实际上以一种具体的方式处理这些问题确实需要一点努力(不要太狡猾,那是留给政治家的权利——无意冒犯)。

最后声明——有很多东西需要理解,所以请深呼吸,喝点咖啡,慢慢寻找规律。

energy_data
temperature_data

我们可以看到像PrecipitationQualityHM这样的列似乎始终具有相同的值。为了修正这一点,我们可以删除具有两个或更少唯一元素的列。

def remove_non_uniques(dataframe: pd.DataFrame, filter = []):
    remove = [name for name, series in dataframe.items() if len(series.unique()) <= 2 and not name in filter]
    dataframe.drop(remove, axis=1, inplace=True)
    return remove

print("Removed:")
remove_non_uniques(energy_data)
remove_non_uniques(temperature_data)Removed:
['PeriodType']

['HM',
 'PrecipitationQuality',
 'AirTemperatureQuality',
 'WetBulbTemperatureQuality',
 'DewTemperatureQuality',
 'RelativeHumidityQuality',
 'WindSpeedQuality',
 'WindDirectionQuality',
 'WindgustSpeedQuality',
 'SeaPressureQuality',
 'StationPressureQuality',
 '#']

也可以删除重复的行。这简单多了!

energy_data.drop_duplicates(inplace=True)
temperature_data.drop_duplicates(inplace=True)

最后一件事是检查我们的数据类型。这在这里似乎没有必要,但是建模和图形库对数据类型非常敏感。

这个过程非常简单,查看列/它包含的内容,然后将其与实际的数据类型进行比较。对于大量的列,最好从查看日期和类别开始,因为它们几乎总是被误解(作为对象、浮点数或整数)。一般来说,object应该只用于字符串。

energy_data.dtypes
temperature_data.dtypesRegion          object
Date            object
TotalDemand    float64
RRP            float64
dtype: object

StationNumber          int64
Year1                  int64
Month1                 int64
Day1                   int64
Hour1                  int64
Minute1                int64
Year                   int64
Month                  int64
Day                    int64
Hour                   int64
Minute                 int64
Precipitation         object
AirTemperature        object
WetBulbTemperature    object
DewTemperature        object
RelativeHumidity      object
WindSpeed             object
WindDirection         object
WindgustSpeed         object
SeaPressure           object
StationPressure       object
AWSFlag               object
dtype: object

在我们的例子中,我们有不止一组日期,而是两个(该死的,BOM 数据收集团队需要冷静)🥴.正如我们预测的那样,日期是整数,分布在多个列中(一个表示年,一个表示月、日、小时和分钟)。

我们可以先去掉重复的日期集(第二个是因为夏令时),然后我们可以解析剩余的日期列。这以我们期望的良好有序的方式格式化了我们的数据!

# Remove extra dates
temperature_data.drop(["Year1", "Month1", "Day1", "Hour1", "Minute1"], axis=1, inplace=True)

# Reformat dates into Pandas' datatime64 objects
# Replacing old format
temperature_data["Date"] = pd.to_datetime(temperature_data[["Year", "Month", "Day", "Hour", "Minute"]])
energy_data["Date"] = pd.to_datetime(energy_data["Date"])

temperature_data.drop(["Year", "Month", "Day", "Hour", "Minute"], axis=1, inplace=True)

现在,我们还可以看到一些关于站号(在哪里进行测量)、AWSFlag(是否手动收集数据)、温度、湿度、压力和降水测量的问题。我们确实需要改变这些数据类型,但是这样做我们需要稍微脱离书本,因为使用标准的.astype("category")转换数据类型会抛出一些错误。我们可以通过记下投诉的内容、解释投诉原因,然后尝试再次运行上述功能来解决这些问题。

为了确保我们都在同一页上,下面是我们正在处理的错误的简短摘要:

  • 前导/尾随空格(因此“12”变成了“12”)
  • 随机标签偶尔会出现(所以 99.99%的单元格会包含数字,但其中一个会包含“###”)
  • 有少量缺失的分类数据

我们可以通过使用.str.strip()删除前导和尾随空格。接下来,要删除 rouge 标签,我们可以使用 Pandas 的replace函数用np.NaN(用于空数据的默认数据类型)覆盖它。最后,我们可以假设任何丢失的数据都是手工收集的(最坏的情况)。fillnareplace函数都是需要的,因为熊猫对np.NaN和空字符串(“”)的处理是不同的。

def to_object_columns(lambda_function):
    string_columns = temperature_data.select_dtypes("object").columns
    temperature_data[string_columns] = temperature_data[string_columns].apply(lambda_function)to_object_columns(lambda column: column.str.strip())

temperature_data["AWSFlag"] = temperature_data["AWSFlag"].replace("", 0).astype("category")
temperature_data["AWSFlag"].fillna(0, inplace=True)
temperature_data["RelativeHumidity"] = temperature_data["RelativeHumidity"].replace("###", np.NaN)

to_object_columns(lambda column: pd.to_numeric(column))temperature_data.dtypesStationNumber                  int64
Precipitation                float64
AirTemperature               float64
WetBulbTemperature           float64
DewTemperature               float64
RelativeHumidity             float64
WindSpeed                    float64
WindDirection                float64
WindgustSpeed                float64
SeaPressure                  float64
StationPressure              float64
AWSFlag                     category
Date                  datetime64[ns]
dtype: object

我们还可以做最后一件事来改进数据的格式。这是为了确保用于标识温度和能量测量位置的列使用相同的类别。

因为我们每个地区只有一个电台,所以我们可以用简短的地区代码来代替单独的地区代码。请注意,这些信息是在数据集注释中提供的(不要担心,我们不需要记住 94029 是指维多利亚)。要进行这些转换,我们只需创建两个字典。每个键-值对表示旧代码,以映射到新代码(因此将“SA1”映射到“SA”,将 23090 映射到“SA”)。Pandas map函数完成剩下的工作。

energy_data["Region"].unique()
temperature_data["StationNumber"].unique()array(['VIC1', 'SA1', 'TAS1', 'QLD1', 'NSW1'], dtype=object)
array([94029, 86071, 66062, 40913, 86338, 23090])region_remove_number_map = {"SA1": "SA", "QLD1": "QLD", "NSW1": "NSW", "VIC1": "VIC", "TAS1": "TAS"}
station_to_region_map = {23090: "SA", 40913: "QLD", 66062: "NSW", 86071: "VIC", 94029: "TAS", 86338: "VIC"}

temperature_data["Region"] = temperature_data["StationNumber"].map(station_to_region_map)
energy_data["Region"] = energy_data["Region"].map(region_remove_number_map)

temperature_data.drop("StationNumber", axis=1, inplace=True)

关于我们的数据格式化的最后一点需要注意的是(承诺)。我们目前没有以任何特定的方式索引/排序我们的数据,即使它是一个时间序列。所以我们可以用set_index来改变它。

energy_data.set_index("Date", inplace=True)
temperature_data.set_index("Date", inplace=True)

处理缺失数据

到目前为止,我们已经确保我们所有的数据都可以轻松访问,没有任何麻烦。我们已经确保所有东西的格式都是正确的,现在我们可以使用它了…嗯,算是吧。虽然我们的数据格式正确,但这并不意味着它是有意义的、有用的,甚至是存在的!

我们可以度过这个难关,我们只需要有战略眼光。这里要记住的关键是:

不要做不必要的工作!

我们的最终目标不是修复一切,而是删除那些绝对无用的东西,提高那些可能特别有趣/有用的东西的质量。这个过程有助于我们知道我们正在做出可靠的、概括的和合理的预测或解释(否则整个过程就没有什么意义了)。

一个很好的方法是使用图表。通过可视化我们的数据,我们可以很容易地发现哪里缺少数据,哪里存在异常值,哪里两个特征相关。当然,我们不能在一个图上做所有这些,所以我们将从寻找缺失的数据开始。大间隙或频繁间隙的部分是我们正在寻找的潜在问题区域。如果这些不存在(即很少或没有丢失数据),那么我们的工作就会减少。

请记住,我们有两个数据集(不是一个),按州分类!由于数据是以不同的状态记录的,因此将它们组合在一起并不能正确地表示数据。因此,对于我们想要分析的每个特征,我们将有一系列的图(每个州一个)。不过我们稍微幸运一些,因为只有一个有意义的能量特征(TotalDemand),我们将看到它几乎没有丢失数据。

fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(20, 12), tight_layout=True)

energy_data.groupby("Region").get_group("TAS")["TotalDemand"]["2000":"2019"].plot(color= "red",title="Tasmania Energy Demand",ax=axes[0,0])
energy_data.groupby("Region").get_group("VIC")["TotalDemand"]["2000":"2019"].plot(color= "green",title="Victoria Energy Demand",ax=axes[0,1])
energy_data.groupby("Region").get_group("NSW")["TotalDemand"]["2000":"2019"].plot(color= "purple",title="New South Wales Energy Demand",ax=axes[0,2])
energy_data.groupby("Region").get_group("QLD")["TotalDemand"]["2000":"2019"].plot(color= "orange",title="Queensland Energy Demand",ax=axes[1,0])
energy_data.groupby("Region").get_group("SA")["TotalDemand"]["2000":"2019"].plot(color="blue",title="South Australia Energy Demand",ax=axes[1,1])

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

正如我们所看到的,这些图都是连续的,这就是我们如何确认没有丢失数据的主要来源。这里有各种各样的其他趋势,但我们将这些留到以后!

现在转到天气数据。这就是我们将看到图表的用处的地方!虽然可以简单地找到丢失数据的百分比,但是图表很容易显示空值的性质。我们可以立即看到它在哪里丢失了,这本身就表明应该使用什么方法(例如,删除数据、重新采样等)。

我们从看WetBulbTemperature开始。我们会看到它很大程度上是完整的,就像我们的能源数据。然后我们会看到AirTemperature,这将是…粗糙破烂。

为了简洁起见,这里只包括几个关键的图表。然而,更多的负载可以用图表表示(请仔细研究代码,看看还能做些什么)!AirTemperature的问题类似于以下特征中的问题:

  • 沉淀
  • 空气温度
  • 露点温度
  • 相对湿度
  • 风速
  • 风向
  • 风速
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(20, 12), tight_layout=True)

temperature_data.groupby("Region").get_group("TAS")["WetBulbTemperature"]["2000":"2019"].plot(color= "red",title="Tasmania Wet Bulb Temperature",ax=axes[0,0])
temperature_data.groupby("Region").get_group("VIC")["WetBulbTemperature"]["2000":"2019"].plot(color= "green",title="Victoria Wet Bulb Temperature",ax=axes[0,1])
temperature_data.groupby("Region").get_group("NSW")["WetBulbTemperature"]["2000":"2019"].plot(color= "purple",title="New South Wales Wet Bulb Temperature",ax=axes[0,2])
temperature_data.groupby("Region").get_group("QLD")["WetBulbTemperature"]["2000":"2019"].plot(color= "orange",title="Queensland Wet Bulb Temperature",ax=axes[1,0])
temperature_data.groupby("Region").get_group("SA")["WetBulbTemperature"]["2000":"2019"].plot(color= "blue",title="South Australia Wet Bulb Temperature",ax=axes[1,1])

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

fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(20, 12), tight_layout=True)

temperature_data.groupby("Region").get_group("TAS")["AirTemperature"]["2000":"2019"].plot(color= "red",title="Tasmania Air Temperature",ax=axes[0,0])
temperature_data.groupby("Region").get_group("VIC")["AirTemperature"]["2000":"2019"].plot(color= "green",title="Victoria Air Temperature",ax=axes[0,1])
temperature_data.groupby("Region").get_group("NSW")["AirTemperature"]["2000":"2019"].plot(color= "purple",title="New South Wales Air Temperature",ax=axes[0,2])
temperature_data.groupby("Region").get_group("QLD")["AirTemperature"]["2000":"2019"].plot(color= "orange",title="Queensland Wind Air Temperatue",ax=axes[1,0])
temperature_data.groupby("Region").get_group("SA")["AirTemperature"]["2000":"2019"].plot(color= "blue",title="South Australia Air Tempeature",ax=axes[1,1])

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

图表中随机出现的几个月到几年的气温数据(空白部分)表明不值得进一步研究。这实际上并不是一件坏事,它让我们更加关注现在的:能量需求和湿球温度。

这些图表显示了大量或有规律的缺失数据,但是,它们没有显示随机分布的少量数据。为了安全起见,我们可以快速使用熊猫DataFrame.isnull来查找哪些值为空。它立即显示我们的能量数据处于完美的状态(没有任何遗漏),而大多数温度列有很大比例的遗漏!

我们将删除大多数特性,因为它们需要我们牺牲大量的行。我们想要保留的(即WetBulbTemperature)可以对其缺失值进行插值(根据其周围的值推断出该值应该是什么)。

def get_null_counts(dataframe: pd.DataFrame):
    return dataframe.isnull().mean()[dataframe.isnull().mean() > 0]get_null_counts(energy_data)
get_null_counts(temperature_data)Series([], dtype: float64)

Precipitation         0.229916
AirTemperature        0.444437
WetBulbTemperature    0.011324
DewTemperature        0.375311
RelativeHumidity      0.375312
WindSpeed             0.532966
WindDirection         0.432305
WindgustSpeed         0.403183
SeaPressure           0.137730
StationPressure       0.011135
dtype: float64remove_columns = ["Precipitation", "AirTemperature", "DewTemperature", "RelativeHumidity", "WindSpeed", "WindDirection", "WindgustSpeed"]
temperature_data.drop(remove_columns, axis=1, inplace=True)

# Note that using inplace currently throws an error
# So interpolated columns must be manually overridden
missing_columns = list(get_null_counts(temperature_data).keys())
temperature_data[missing_columns] = temperature_data[missing_columns].interpolate(method="time")

组合能量和温度数据

现在,到了最后一步。将两个数据框架结合成一个,这样我们就可以将温度数据与能源需求联系起来。

我们可以使用merge_asof函数来合并这两个数据集。该功能将最接近的值合并在一起。因为我们有按地区分组的数据,所以我们用by参数来指定。我们可以选择只合并相隔 30 分钟或更短时间的能量和温度条目。

energy_data.sort_index(inplace=True)
temperature_data.sort_index(inplace=True)

data = pd.merge_asof(energy_data, temperature_data, left_index=True, right_index=True, by="Region", tolerance=pd.Timedelta("30 min"))

为了检查合并是否成功,我们可以检查有多少空值。这是因为不成对的行会导致空值。

get_null_counts(data)
data.dropna(inplace=True)WetBulbTemperature    0.001634
SeaPressure           0.001634
StationPressure       0.001634
AWSFlag               0.001634
dtype: float64

现在终于可以看到一些干净理智的数据了!这是我们看到的第一张不会对健康和安全造成巨大危害的桌子。既然我们已经到了这个阶段,我们应该庆祝一下…从这里开始只会变得更好👊。

data

保存最终数据

pd.to_pickle(data, "../Data/Data.pickle")

【https://www.kamwithk.com】最初发表于

机器学习能源需求预测项目——第二部分使用图表讲故事

原文:https://towardsdatascience.com/machine-learning-energy-demand-prediction-project-part-2-storytelling-using-graphs-9c62a7dfadd2?source=collection_archive---------54-----------------------

让我们看看我们的机器学习项目规划基本编码工具如何在现实世界的项目中实现!今天,我们将讨论如何利用温度数据来预测我们每天消耗的能量。我们之前导入并清理了我们的数据,现在将绘制并描述我们能源使用背后的故事!。

这是三部曲的第二部(第一部在这里)。请随意编码,完整的项目在 GitHub 上。

故事

我们早上醒来,打开加热器/空调,从冰箱里找到一些酸奶做早餐,刮胡子,打开电脑,打开音乐,最后开始工作。这些任务都有一个共同点——它们使用电力!我们对电力的严重依赖使得估算我们每天需要产生多少能量变得至关重要。

我们已经找到、导入并清理了我们的数据(好员工),所以我们可以继续讲述我们的用电情况。但是,如果这看起来很有挑战性,不要担心。我们会一步一步来。在每个阶段,链接回它与我们的 ML 领域指南的关系。

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

斯科特·格雷厄姆摄于Unsplash

我们从困难但必要的任务开始,解释我们的数据。我们的第一个想法是一次绘制出整个时间序列,但该死的一个有 4 个特征的图,每个特征在 20 年内每 30 分钟有大约 5 次测量,这是不漂亮的,有意义的或快速的。在把头撞向砖墙一段时间后,我们当然意识到我们可以描绘出具体的特征和关系,而不是一次性描绘出一切*。由于损失不大,我们开始使用简单的汇总统计数据来查找最大值、最小值和平均值。这些给了我们每个专栏的大致概述,但是为了更进一步,我们来看看我们的特征与的相关性如何。*

一旦我们理解了温度与能量需求高度相关(足够直观),我们就可以开始绘制一些图表了😉!虽然我们不能一次描绘出所有的事情,但是我们仍然希望掌握全局——我们的数据是如何随时间变化的。我们首先确定我们的问题——当我们寻找 20 年来的变化时,每 30 分钟一次的运动实际上是没有意义的,只会模糊画面。幸运的是,我们的字段指南解释说,我们可以通过重采样来绘制每周的平均值!现在我们知道了状态之间的一般增加和减少趋势。

在查看了能量和温度的单个数据后,我们继续寻找两者之间的关联。每个州的图表是不同的。趋势较大的州有更复杂的图形。这很复杂,我们没有数据来解释这些趋势,所以我们需要在以后删除它们。

现在我们只剩下一件事了——找出能源需求在一天和一周内是如何变化的。然后……很快,我们就成功地描述了每个令人振奋的日子、月份和年份的能源使用情况😎。此时,我们已经成功地完成了项目的大部分!在短暂的庆祝之后,我们可以开始建模了…但是不要操之过急,这将在下一个(最后的)教程中介绍。

*import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

from IPython.core.interactiveshell import InteractiveShell

InteractiveShell.ast_node_interactivity = "all"
pd.options.display.max_columns = None

data = pd.read_pickle("../Data/Data.pickle")*

时代

第 1 章—描述性统计

由于我们不能一次查看所有内容,所以我们希望对我们的数据有一个粗略的估计。自然的第一步是查看每一列的平均值、最小值和最大值。这些被称为描述性统计,Pandas 使用describe函数为我们计算它们。

因为我们想扩展这个来看看什么与能源需求相关(因为我们试图在以后预测它),我们将找到相关性*。为了找到特性之间的相关性,Pandas 提供了corr函数。*

统计数据显示:

  • TotalDemand平均 4619MW,最小 22 mW,最大 14580 MW。
  • WetBulbTemperature最低气温为零下 9 摄氏度,最高气温为 41 摄氏度
  • TotalDemandWetBulbTemperature最相关

尽管相关函数只考虑了线性关系(直线),但它仍然有助于了解哪些要素值得绘制并包含在我们的模型中。这里主要是WetBulbTemperature,但StationPressure也可能有用。

*data.describe()*
*data.corr()*

第 2 章——寻找长期趋势

20 年的能源

我们想知道我们如何使用能源的故事。有一个简单的方法可以做到这一点——图表🤓。我们可以从大尺度上看发生了什么开始,然后慢慢放大。

我们将分别查看每个状态,因为它们的趋势可能不一样。

*fig, axes  = plt.subplots(nrows=2, ncols=3, figsize=(20, 12), constrained_layout=True)

data.groupby("Region").resample("3W").mean()["TotalDemand"]["TAS"].plot(color="red", title="Tasmania Energy Demand", ax=axes[0,0])
data.groupby("Region").resample("3W").mean()["TotalDemand"]["VIC"].plot(color="green", title="Victoria Energy Demand", ax=axes[0,1])
data.groupby("Region").resample("3W").mean()["TotalDemand"]["NSW"].plot(color="purple", title="New South Wales Energy Demand", ax=axes[0,2])
data.groupby("Region").resample("3W").mean()["TotalDemand"]["QLD"].plot(color="orange", title="Queensland Energy Demand", ax=axes[1,0])
data.groupby("Region").resample("3W").mean()["TotalDemand"]["SA"].plot(color="blue", title="South Australia Energy Demand", ax=axes[1,1])*

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

重新采样后,解释图表仍然很困难。所以让我们慢慢来,一步一步来。

第一个值得注意的模式是能量总是在高点和低点之间波动。高点和低点并不总是一样的。

  • 塔斯马尼亚岛和南澳大利亚从大约 900 到 1400 不等
  • 维多利亚从 4500 年到 6500 年
  • 新南威尔士从 6000 到 10000
  • 昆士兰从 4500 到 7500

但是我们可以说趋势并不是一成不变的。能源使用可能会快速增加(昆士兰州,直到 2010 年),急剧下降(维多利亚州,2010 年后),甚至持续稳定(塔斯马尼亚州)!这种模式显然不是有规律的,也不是直接由温度引起的(因此无法使用历史温度和能量数据进行预测)。

虽然我们没有这些趋势的数据,但我们可以给出一个有根据的猜测。我们知道人口不稳定,不同的州人口增长率不同。技术和能源效率也有了巨大的提高,经济状况影响着人们使用能源的意愿。除此之外,全球变暖促使越来越多的人安装太阳能电池板(太阳能电池板产生的电能没有被计算在内)。由于我们没有任何关于这些特征的数据,在开始建模之前,我们将尝试去除这些趋势。

一年中的能量

现在让我们放大!我们将着眼于一年中发生的趋势。因为我们绘制的是 5 年而不是 20 年,我们当然需要更少的重采样*。*

*fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(20, 12), constrained_layout=True)

data.groupby("Region").resample("W").mean()["TotalDemand"]["TAS"]["2015":"2020"].plot(color="red", title="Tasmania Energy Demand", ax=axes[0,0])
data.groupby("Region").resample("W").mean()["TotalDemand"]["VIC"]["2015":"2020"].plot(color="green", title="Victoria Energy Demand", ax=axes[0,1])
data.groupby("Region").resample("W").mean()["TotalDemand"]["NSW"]["2015":"2020"].plot(color="purple", title="New South Wales Energy Demand", ax=axes[0,2])
data.groupby("Region").resample("W").mean()["TotalDemand"]["QLD"]["2015":"2020"].plot(color="orange", title="Queensland Energy Demand", ax=axes[1,0])
data.groupby("Region").resample("W").mean()["TotalDemand"]["SA"]["2015":"2020"].plot(color="blue", title="South Australia Energy Demand", ax=axes[1,1])*

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

我们可以看出,能量需求通常在春季和秋季最低,而在冬季和/或夏季最高。塔斯马尼亚冬季的需求往往高于夏季。维多利亚州与此相似,但夏季的能源需求高峰更为频繁。另一方面,昆士兰州在夏季使用最多的能源。新南威尔士州和南澳大利亚州在夏天和冬天都有最大的能量!

塔斯马尼亚岛一直比较凉爽(作为一个小岛),不像炎热多汗的新南威尔士和南澳大利亚。这可以解释最大值/最小值出现的相对差异。

超过 20 年的温度

不过,温度和能量一样重要。所以我们也来看看吧!

*fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(20, 6), constrained_layout=True)

data.groupby("Region").resample("3W").mean()["WetBulbTemperature"]["TAS"].plot(color= "red", title="Tasmania Temperature", ax=axes[0,0])
data.groupby("Region").resample("3W").mean()["WetBulbTemperature"]["VIC"].plot(color= "green", title="Victoria Temperature", ax=axes[0,1])
data.groupby("Region").resample("3W").mean()["WetBulbTemperature"]["NSW"].plot(color= "purple", title="New South Wales Temperature", ax=axes[0,2])
data.groupby("Region").resample("3W").mean()["WetBulbTemperature"]["QLD"].plot(color= "orange", title="Queensland Temperature", ax=axes[1,0])
data.groupby("Region").resample("3W").mean()["WetBulbTemperature"]["SA"].plot(color="blue", title="South Australia Temperature", ax=axes[1,1])*

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

与能量图不同,温度图没有任何明显的趋势。然而,我们可以看到温度从最低 8 度左右到最高 22 度左右不等。虽然这张图没有显示各州之间温度的显著变化,但它们确实存在。塔斯马尼亚岛一直比较凉爽(作为一个小岛),不像炎热多汗的新南威尔士和南澳大利亚。

温度和能量相关性

我们知道温度和能量高度相关,但我们还不知道如何相关。好吧,让我们来看看!

*fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(20, 12), constrained_layout=True)

data.groupby("Region").get_group("TAS").resample("D").mean().plot(kind="scatter",x="WetBulbTemperature", y="TotalDemand", s=10, color= "red", ax=axes[0,0], title="Tasmania")
data.groupby("Region").get_group("VIC").resample("D").mean().plot(kind="scatter",x="WetBulbTemperature", y="TotalDemand", s=10, color= "green", ax=axes[0,1], title="Victoria")
data.groupby("Region").get_group("NSW").resample("D").mean().plot(kind="scatter",x="WetBulbTemperature", y="TotalDemand", s=10, color= "purple", ax=axes[0,2], title="New South Wales")
data.groupby("Region").get_group("QLD").resample("D").mean().plot(kind="scatter",x="WetBulbTemperature", y="TotalDemand", s=10, color= "orange", ax=axes[1,0], title="Queensland")
data.groupby("Region").get_group("SA").resample("D").mean().plot(kind="scatter",x="WetBulbTemperature", y="TotalDemand", s=10, color= "blue", ax=axes[1,1], title="South Australia")*

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

这些图表向我们展示了一件重要的事情,趋势越大,温度和能源需求之间的关系就变得越混乱(和复杂)。这就是为什么塔斯马尼亚岛的温度和能源需求曲线几乎是一条直线(尽管是一条粗线),而其他地方是曲线。换句话说,趋势越大,曲线越宽越粗!

由于我们没有任何人口或经济数据,趋势必须被删除(在下一个教程中)。

第 3 章——分析小时间框架

下图显示了冬季和夏季一天和一周内不同地区的能源需求对比。我们可以从一周(此处为 2017 年 11 月 6 日至 2017 年 6 月 17 日)开始,看看能源需求在一周内是如何波动的。我们只测试了一个小时间段*,这是为了简洁(下面的相同模式也可以在其他地方看到)。*

*fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(20, 10), tight_layout=True)

# Winter
data["2017-06-11":"2017-06-17"].groupby("Region").get_group("TAS")["TotalDemand"].plot(color="red", title="Tasmania Winter", ax=axes[0,0])
data["2017-06-11":"2017-06-17"].groupby("Region").get_group("VIC")["TotalDemand"].plot(color="green", title="Victoria Winter", ax=axes[0,1])
data["2017-06-11":"2017-06-17"].groupby("Region").get_group("NSW")["TotalDemand"].plot(color="purple", title="New South Wales Winter", ax=axes[0,2])
data["2017-06-11":"2017-06-17"].groupby("Region").get_group("QLD")["TotalDemand"].plot(color="orange", title="Queensland Winter", ax=axes[1,0])
data["2017-06-11":"2017-06-17"].groupby("Region").get_group("SA")["TotalDemand"].plot(color="blue", title="South Australia Winter", ax=axes[1,1])

# Summer
data["2017-1-14":"2017-1-20"].groupby("Region").get_group("TAS")["TotalDemand"].plot(color="red", title="Tasmania Summer", ax=axes[2,0])
data["2017-1-14":"2017-1-20"].groupby("Region").get_group("VIC")["TotalDemand"].plot(color="green", title="Victoria Summer", ax=axes[2,1])
data["2017-1-14":"2017-1-20"].groupby("Region").get_group("NSW")["TotalDemand"].plot(color="purple", title="New South Wales Summer", ax=axes[2,2])
data["2017-1-14":"2017-1-20"].groupby("Region").get_group("QLD")["TotalDemand"].plot(color="orange", title="Queensland Summer", ax=axes[3,0])
data["2017-1-14":"2017-1-20"].groupby("Region").get_group("SA")["TotalDemand"].plot(color="blue", title="South Australia Summer", ax=axes[3,1])*

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

所有州每天的能源使用量都差不多。夏季和冬季有两个高峰。第一个较小,在白天(上午 5-9 点),而第二个较大,在晚上(下午 4-7 点)。这些发生在人们在家最活跃的时候(工作前后)。虽然这里只能显示一些图表,但这些模式确实会持续存在(交换不同的日期会显示这一点)。

夏季一周内的能量需求与冬季相似,但需求在一周内增加得更多!

我们现在可以继续查看某一天(此处为 2017 年 11 月 6 日)。

*fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(20, 10), constrained_layout=True)

data["2017-06-11"].groupby("Region").get_group("TAS")["TotalDemand"].plot(title="Tasmania", ax=axes[0,0], color="red")
data["2017-06-11"].groupby("Region").get_group("VIC")["TotalDemand"].plot(title="Victoria", ax=axes[0,1], color="green")
data["2017-06-11"].groupby("Region").get_group("NSW")["TotalDemand"].plot(title="New South Wales", ax=axes[0,2], color="purple")
data["2017-06-11"].groupby("Region").get_group("QLD")["TotalDemand"].plot(title="Queensland", ax=axes[1,0], color="orange")
data["2017-06-11"].groupby("Region").get_group("SA")["TotalDemand"].plot(title="South Australia", ax=axes[1,1], color="blue")*

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

从这些图表中,我们可以看到,从早上 6 点到 9 点,以及从下午 3 点到 6 点,能源使用量逐渐增加。在上午 12 点到下午 3 点,我们的能源使用保持稳定。它通常在一天开始和结束后下降(可能是在大多数人睡着的时候)。夏季和冬季的需求基本相似。

照片由斯科特·格雷厄姆在 上 Unsplash

原载于https://www.kamwithk.com*。*

机器学习工程师对软件工程师

原文:https://towardsdatascience.com/machine-learning-engineer-versus-software-engineer-fb59f8cba9dd?source=collection_archive---------7-----------------------

这两个角色有什么区别,他们是怎么想的?

截至 2018 年,软件工程已经发展到在美国拥有超过 100 万 员工,并且预计增长不会放缓。接下来是机器学习工程师,他处理自动化或决策问题,并对其应用尖端工具。

机器学习是在不确定性下做出决策的研究:给定一个训练数据集,当我看到新的东西时,我应该如何行动。

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

照片由希塔斯·贾达夫派克斯拍摄。

随着机器学习(特别是深度学习)在整个行业的普及,越来越多的工程师在日常生活中部署这些工具。利用深度学习为公司带来巨大利润的工具实际上是无穷无尽的:搜索推荐、语音转文本、语音助手、面部识别、广告等等。

实现这些模型与构建大型分布式软件系统的角色有何不同?心态相似,但专攻不同。

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

加州海岸——作者。

软件工程—构建数据网络

数据流是任何大规模软件项目的关键。工程师必须选择在本地设备上部署的正确算法,用什么语言开发(以及编译成什么语言),以及软件堆栈中有多少层。

软件工程师最终在语言、数据结构和算法领域工作。

  • 语言:开发和测试语言是软件工程师的工作环境。他们对不同语言的能力有了深入的了解,并且权衡的尺度也很大。Python 是最受欢迎的,因为下游决策变得更加流畅(我同意 Python)。
  • 数据结构:不同的数据结构决定了哪些计算机操作速度快——我们是想要快速访问数据(哈希表)吗?使用学习工具(张量)进行快速后处理?还是别的?不同的语言有不同的属性可以利用,最好的软件工程师对这些都像外语一样流利。
  • 算法:标准算法是技术面试的基础——排序、搜索等等——因为它们在规模上确实很重要。“ Big O ”符号是一种古怪的学习工具,但是当在部署的系统上工作时,这种思想可以大规模地转化。

在这里,软件工程师可能会失败:爱上他们自己系统的复杂性。

热爱自己系统的复杂性,这样你就可以在其中创造更多的东西,并在别人试图使用它时炫耀指标,这是一个超级能干的工程师的失败。简单是王道,因为它可以扩展并支持公司范围的协作。

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

Python 开发者环境。

好的软件工程最终会让机器学习的任务变得更容易。数据将更加可用和统一,以便提炼为产品和价值。

机器学习工程——构建知识网络

学习工程师正在提取记录的知识(数据)并创建决策边界。决策边界通常是非线性的,并且通常难以解释(例如交易代理或机器人规划者),但是它们是由数据通知的决策边界。

机器学习工程师在模型、部署和影响的空间中思考。

  • 模型:我什么时候应该使用深度模型或者贝叶斯近似?对于机器学习工程师来说,知道哪些系统概括得更好,可以在设备上进行微调,并且可以解释是关键。此外,对模型的专业知识使 ML PhD 成为科技公司如此有价值的雇员。
  • 部署:很多公司都在这个领域明确了自己的定位。设备级人工智能是消费电子公司(咳咳,苹果)目前的推动力,模型效率主导着数字巨人的成本。(脸书、谷歌等)。特斯拉凭借无与伦比的云汽车更新主宰着汽车自动化市场。接下来是单个工程师如何做出贡献— 针对特定任务的更多特定模型将在我们的生活中不断增加,模型的效率将改变互联网速度和电池寿命
  • 影响 : 伦理。我正在部署的模型是否以牺牲另一个子群的利益为代价而使一个子群受益?这是 ML 工程师需要的,因为你选择和训练的数据集将反映在你的产品中。考虑一下,如果一个数据集是从 100 个前 alpha 用户的样本中收集的,当它触及数百万双不知情的眼睛时,将如何翻译?数据透明度落后,个人需要承担责任。

机器学习工程师的不足之处:将他们的贡献困在过多的层级和工具中。

当调查实现选项时,其他机器学习者希望能够以模块化的方式提取和镜像有用的代码,从而实现快速发展。我试图利用多个最先进的项目,这些项目在内部陷入了太多的层次,以采取下一步措施,并使它们在现实世界中大规模产生影响——这就是为什么简单是王道。

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

我博士期间训练的不同模型的集合。左)高斯过程拟合物理优化的设计变量,中)深度动力学模型预测洛伦兹系统(经典混沌系统),右)不同类型的深度神经网络预测长期机器人轨迹。

主题——数码便宜,简单为王

这两个工程角色都利用了数字领域的迭代既便宜又快速的事实— 每个边缘用户都以低成本增加高价值。这样,最简单的方法往往会占主导地位,因为它们可能非常普遍— 简单方法在学习中具有更好的通用性,在软件中具有更好的接口

就像最优秀的软件工程师一样,最优秀的机器学习工程师也会富有创造力和效率。

最优秀的工程学生不会在给他们的盒子里进行优化,他们会寻找会彻底改变游戏性质的漏洞。在软件工程中,这是使用新工具和数据结构的形式,在机器学习工程中,这将是调整新的模型类型或如何部署。我怀疑随着软件工程变得越来越自动化,机器学习工程师将推动最好的公司。

这篇文章的灵感来自于人工智能播客上的一段对话,莱克斯·弗里德曼主持了吴恩达,讨论了大规模在线开放课程的影响,计算机科学是如何教授的,以及大型科技公司如何主导市场。

更多?订阅我关于机器人、人工智能和社会的时事通讯!

[## 自动化大众化

一个关于机器人和人工智能的博客,让它们对每个人都有益,以及即将到来的自动化浪潮…

robotic.substack.com](https://robotic.substack.com/)

机器学习进化——感知机的故事

原文:https://towardsdatascience.com/machine-learning-evolution-the-story-of-perceptron-b1de3f180ed6?source=collection_archive---------52-----------------------

这一切是如何开始到我们现在的位置

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

一个神经元细胞— 背景向量由 brgfx 从 freepik 创建

A 人工智能(AI)是新的电。它已经成为镇上的话题。像机器学习(ML)和深度学习(DL)这样的花哨词汇现在是企业界提供的每个产品或解决方案的强制性部分,以激励他们的客户和最终用户。但在现实中,这些不再仅仅是花哨的术语。

在过去的几十年里,人工智能的众多应用已经出现,这些应用正在解决现实世界的问题,使其成为一种全球现象。吴恩达是成千上万像我一样有抱负的机器学习者的导师,他将人工智能称为新的电力,并说:

正如 100 年前电力几乎改变了一切一样,今天我实际上很难想到一个我认为人工智能在未来几年内不会改变的行业。

每一家主要的技术公司都已经适应了这场计算机革命,因为他们了解主要的技术趋势,不能冒被甩在后面的风险。ML 会在这里停留一段时间,如果你是一个寻求提升你的投资组合技能的开发者,我建议你开始学习。另外,报酬也更高。

人工智能已经颠覆了所有主要行业。今天,由于其在医疗保健、神经科学、农业、安全、监控等领域的跨领域应用,人工智能和人工智能已经成为我们生活中不可或缺的一部分。多年来,人工智能已经进化,现在它有能力帮助人类。但是这一切都是从大约五十年前感知器发明的时候开始的。

在我们继续我们大约有 65 年历史的感知机故事之前,让我们先非正式地定义一下感知机:

感知器是一种方便的生物神经元的人工模型。它是一种用于监督学习的单层神经网络算法。它由输入值、权重和偏差以及激活函数组成。

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

单个感知器单元—作者图片

我们不讨论技术细节,让我们继续我们的故事。

感知器的崛起

感知器是神经网络的基本构件,由 Frank Rosenblatt 于 1957 年 1 月在纽约布法罗的康奈尔航空实验室发明。这项发明是名为“感知机——一种感知和识别自动机”的研究成果

韦氏词典将自动机定义为:

一种机器或控制机构,设计成自动遵循预定的操作顺序或对编码指令作出反应。

这是为期五年的研究的一部分,旨在设计一种能够学习复杂模式、模式感知和归纳的电子大脑模型。这项研究背后的直觉是构建一种具有类似人类功能的设备,如感知、概念形成、从经验中归纳的能力、识别复杂的信息模式以及感知不同大小、形状和方向的类似对象。

然而,为了执行所有这些操作,传统的计算机系统将需要存储数千个(如果不是数百万个)图案,然后每当需要时,搜索这些过量的图案以识别看不见的图案,这在计算上非常昂贵,并且不是识别图案或物体的经济方式。

为了解决这个问题,Frank Rosenblatt 提出了一个系统,该系统可能会根据生物大脑的原理工作,并使用概率方法而不是确定性方法来识别模式之间的相似性。

他的感知机模型由三个主要部分组成:

  • 感觉系统
  • 联想系统
  • 响应系统。

这三个主要系统中的每一个都将进一步包含相互连接的单元。可以根据正在识别的模式打开或关闭这些连接。感觉系统会接受输入模式。关联系统将打开或关闭特定的连接,并使用响应系统呈现输出。

感知器模型是通过构建名为 Mark 1 感知器的定制硬件来赋予生命的,它主要是为图像识别而设计的。它是一个黑匣子,很像当今的神经网络,有输入层、隐藏层和输出层。

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

Mark I Perceptron —康奈尔大学新闻服务记录,4–3–15 号。康奈尔大学图书馆珍本和手稿收藏部

反向传播到达现场

现在向前移动几十年,感知器的故事继续了 Geoffrey Hinton 在 1986 年提出的工作,当时他提出了一种新的学习程序,名为反向传播,后来成为现代神经网络模型的支柱。该技术通过调整神经网络模型的权重来最小化实际值和期望值之间的差异。它使神经网络学习或提取特征,并概括输入的模式或序列,以对看不见的数据表示做出相当准确的预测。

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

多层神经网络模型中的反向传播可视化—图片由作者提供

自那时以来,已经取得了许多进展。现在,我们已经有了 VGGNet、ResNet、Inception 等模型,可以快速准确地对对象进行分类。所有这些都是基于这样一个事实,即我们正试图模仿人脑。

但问题仍然存在,我们是否已经了解我们的大脑是如何识别我们日常生活中看到的物体的?随着每一天的过去,神经科学研究人员都在假设大脑理论,帮助我们理解我们的大脑如何学习、感知和记忆模式。

最先进的机器学习

杰夫·霍金斯提出了一个这样的理论,他称之为智力的千脑理论,它告诉我们大脑中被称为新皮层的部分是如何负责制作某个物体的各种模型,然后以分层的方式投票,以达成共识,告诉我们正在感觉、感知或看到什么。

该理论表明,当我们在现实生活中看到某个物体时,我们的新皮层中会有一组特定的神经元被激活。现在,如果我们面对一个不同大小和方向的相似物体,我们的新大脑皮层中会有一组相似的神经元被激活,这使我们能够概括我们在日常生活中看到的物体。事情没那么简单,但你可以大致了解一下。

这是一种不同于传统的 ML 或最先进的 DL 的方法,后者需要大量的输入表示来学习模式,然后进行预测。

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

可视化新大脑皮层中神经元的层次——图片由格尔德·奥特曼提供,来自皮克斯巴伊,由作者编辑,灵感来自努门塔·HTM

杰夫·霍金斯创立了 Numenta,致力于将最先进的神经科学理论,如智能的千脑理论与人工智能相结合,以创造真正智能的机器,这些机器的工作原理与生物大脑相同。我们可能还有很长的路要走,但我们肯定正朝着正确的方向前进。我们已经取得了重大进展,而感知机是这一切的核心。

故事继续…

作为一名有抱负的数据科学研究人员,我觉得我们欠计算世界的早期思想家很多。从 1642 年布莱士·帕斯卡发明第一台机械计算器开始。献给阿达·洛芙莱斯,他是第一个在 1842 年描述解决数学问题的一系列操作的人。艾伦·图灵,他在 1950 年创造了世界闻名的图灵测试,以及历史上更多的人。

随着人工智能领域目前的进步,我们往往会忘记导致我们今天能够做的出色工作的卑微开端。对任何研究人员来说,研究直觉并使用有意识的推理来证明直觉的能力是最大的财富。所以,让你的直觉驱使你走向科学的伟大,成为这一进化的一部分。

机器学习实验跟踪

原文:https://towardsdatascience.com/machine-learning-experiment-tracking-93b796e501b0?source=collection_archive---------6-----------------------

为什么实验跟踪对于进行真实世界的机器学习如此重要?

乍一看,构建和部署机器学习模型看起来很像编写代码。但是有一些关键的差异使得机器学习更加困难:

  1. 机器学习项目比典型的软件项目有更多的分支和实验。
  2. 机器学习代码一般不会抛出错误,只是表现不佳,使得调试变得格外困难和耗时。
  3. 训练数据、训练代码或超参数中的一个微小变化都会极大地改变模型的性能,因此重现早期的工作通常需要与之前的设置完全匹配。
  4. 运行机器学习实验可能非常耗时,而且计算成本可能会变得非常昂贵。

有组织地跟踪实验有助于解决所有这些核心问题。weights and bias(wandb)是一个简单的工具,可以帮助个人跟踪他们的实验——我与不同规模团队的几位机器学习领导者谈论过他们如何使用 wandb 来跟踪他们的实验。

开始使用 wandb 进行实验跟踪

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

查看现场仪表盘

ML 项目进展的基本单位是实验,所以大多数人以某种方式跟踪他们正在做的事情——通常我看到从业者从电子表格或文本文件开始跟踪他们正在做的事情。

电子表格和文档非常灵活——这种方法有什么问题?

这是几年前我在一个项目中使用的谷歌文档:

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

我确信这些笔记在当时很重要,但现在我不知道这些笔记是什么意思。

权重和偏差使得自动记录所有超参数(输入)和指标(输出)变得非常简单。

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

一个典型的项目在 wandb

这就是你如何在 pytorch 中设置 wandb(你可以在文档中找到其他常见的 ML 框架)。

**import wandb****wandb.init(config=args)** # track hyperparameters
**wandb.watch(model)** # track model metricsmodel.train()
for batch_idx, (data, target) in enumerate(train_loader):
  output = model(data)
  loss = F.nll_loss(output, target)
  loss.backward()
  optimizer.step() **wandb.log({“loss”: loss})** # track a specific metric

一旦设置好,Weights and Biases 就会默认监控很多东西。任何命令行参数都成为保存的超参数。pytorch 提供的任何值都成为度量。实验可以自动链接到最新的 git 提交或训练代码的确切状态。被动地收集信息真的很重要,因为持续地写下你可能关心的所有事情几乎是不可能的。

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

实验概述权重&偏差

写下关于你稍后构建的模型的定性注释也是极其重要的。在 Weights and Biases 中,您可以创建报告来跟踪模型度量的注释,并与您的团队共享您的发现和进展。

在后台收集系统指标就是一个很好的例子。Wandb 在后台收集系统使用指标,如分配的 GPU 内存、网络流量和磁盘使用情况。大多数情况下,您不需要查看所有这些信息,但是在您不再使用大部分 GPU 内存的情况下进行更改是很容易的,并且很难跟踪您何时进行了更改。如果你用 wandb 对你的训练代码进行一次测试,你将能够回顾你所有的实验,并看到用法在哪里发生了变化。

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

实时仪表盘中查看

使用实验跟踪来比较不同实验的结果

典型的 ML 工作流程包括运行大量实验。我们发现,在其他结果的背景下观察结果比单独观察一个实验更有意义。

同时查看大量实验很快就会变得混乱。有许多输入在变化,也有许多不同的可能输出。一些运行不可避免地会过早失败。

不同的实验风格导致不同的工作流程,但是我们发现记录下你可能关心的每一个指标,并用一些对你有意义的一致标签来标记实验,可以让事情在以后变得更有条理。

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

实时仪表盘中查看。

一旦你记录了大量的模型,你就有更多的维度需要检查,而不是一下子就能看到。我们发现的一个强大的可视化工具是平行坐标图。

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

查看实时仪表盘

这里每行是一个单独的实验,每列是一个输入超参数或输出度量。我突出显示了最高精度运行,它非常清楚地表明,在我选择的所有实验中,高精度来自低压差值。

跨实验查看是如此重要,以至于 wandb 允许您构建工作空间,您可以在其中选择像散点图这样的可视化图形组,然后立即查看所选运行的比较

查看具体例子

总的指标是好的,但是看具体的例子是必要的。函数 wandb.log() 可以处理各种数据类型,并自动可视化。

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

查看现场报道

测井图像

记录图像对于许多应用来说非常重要,可以在多次运行中查看图像。以下是构建 GAN 的不同方法以及不同规模和时间步长下的结果。

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

测井 Matplotlib 图

通常代码已经在 matplotlib 中跟踪了一些东西——如果你记录了图表,它将被永久保存,并且很容易恢复。事实上,你可以为你的训练代码的每一步记录一个独特的图表。

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

使用实验跟踪管理分布式培训

当进行分布式训练时,即使只是可视化结果也会变得更加困难。

在多台计算机上的分布式运行中,每个实例都可以调用 wandb init 并设置 group 和 job_type,如下所示:

wandb.init(group=”first-run”, job_type=”train”)

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

查看实时仪表盘

Wandb 将显示集合在一起的组中所有运行的指标,但也可以查看单个流程,看看它们的表现如何。

使用实验跟踪报告管理团队协作

随着团队的成长,跟踪一切变得越来越重要。Wandb 允许您构建静态报告,精确显示您使用聚合统计数据运行的实验,并具有深入挖掘的能力。

在 OpenAI 机器人团队中,wandb 报告是 ML 从业者记录他们所做工作并与同事分享的地方。当一个变化可能无意中损害了进展时,可视化是至关重要的。

在潜伏空间,每个团队项目会议都以审查最新的 wandb 实验报告开始,并围绕当前方法的效果以及下一步应该尝试什么实验进行讨论。

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

查看现场报道

使用实验跟踪作为模型的记录系统

随着团队的成长和模型被部署到产品中,记录所发生的一切变得越来越重要。在丰田研究所,wandb 实验链接被用作每一款 ML 车型的官方记录。如果在模型构建的下游发生了一些事情,他们可以将问题追溯到 wandb 培训运行。从一组实验中构建一份报告意味着对所做的工作有一个永久的记录,团队可以很容易地回去回顾到底发生了什么。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值