收集爱好数据集:咖啡
数据科学
管理野生数据集的短暂旅程
现代的数据科学已经允许人们参加一个训练营,在那里给他们清理过的数据集来训练分类器。虽然结果可能令人兴奋,但进行分析或培训只是成为数据科学家的一小部分。如果有的话,实验设计、数据收集、数据验证和数据清理消耗了你的大部分时间。如果你已经做好了所有这些事情,那么训练和分析是直截了当的,甚至时间。
从专业角度来说,我已经单独或作为团队的一员完成了所有这些步骤。就我个人而言,我收集了我感兴趣的事物的数据集。
当我想买一辆新的汽车时,我建立了一个我想要的关键特征的小数据集。一旦我面前有了所有的特征,最佳选择就很清楚了,奇怪的是,它并不是由我认为的决定性因素决定的。对汽车来说,一切都是平等的,这意味着只有像 CarPlay 这样的小功能才能使它们与众不同。
当我想更好地了解的营业额和我之前公司的健康状况时,我开始建立一个数据集。这需要耐心。没人给我或想给我数据。事实上,我的数据来自公司的电话列表这样简单的东西。随着时间的推移,我的数据集变得越来越清晰,几年后,很明显,基于不可持续的周转率,该公司正在走向破产。
咖啡数据集
几个月前,我开始对寻找咖啡 Q 等级的大型数据集感兴趣。q-分级是一种用标准化的味道分级系统来比较咖啡的方法。我想对它们做一些分析,看看它们在确定更好的混合或解释为什么混合效果好方面有多大用处。
除非另有说明,所有图片均由作者提供
虽然我发现一个数据集(CQI)管理得相当好,但我真的想从 Sweet Maria’s 建立一个更有用的数据集,因为我在那里买了大部分的绿咖啡。sweet Maria’s 也有咖啡的味道,这是 CQI 的数据集中没有的。
难点在于:这需要大量的手工工作。
原始数据
Sweet Maria’s 将他们所有的旧咖啡作为存档页面,每一种都有价格、总 Q 值和一些图片。每个都有一个显示 Q 分数的子矩阵的图像和一个显示味道的图像。这两个图像都显示为一个蜘蛛图。
图片经 Sweet Maria’s 许可转载
这个列表中有 300 多个条目。我不得不在一个页面上查看所有的咖啡,点击每个咖啡的快速摘要,点击 Q-score 图表,然后选择全部,并复制。我为味道图重复了这个步骤。这个过程大概花了两个小时。我最终这样做了两次,因为我第一次建立这个数据库时,我没有收集风味等级。
屏幕截图,合理使用
此外,我对所有这些产品进行了比较,这样我就可以获得元数据,如加工方法、地区和品种。
截屏,合理使用
分数提取
对于 Q-score 和 flavor 蜘蛛图,我编写了一个脚本来分割图像,识别圆圈,然后提取分数。
对于口味,我不得不稍微修改脚本,但我能够相对容易地得到分数。
Q-scores 有一个我单独得到的最终分数,还有一个 cupper 的修正。我编写了一个脚本来手动输入 cupper 的更正,这样我就可以帮助验证 cupper 的总得分。这让我可以在几分钟内浏览全部 300 张图片。
我使用这两条信息来计算 Q 分数子矩阵的平均误差,并通过这个误差来修正所有的子矩阵。结果,当我进行一些数据验证时,数据的每个子指标的误差小于 0.1。
然后,我通过随机采样数据、查看图像并验证提取的子测量分数与图像匹配来验证数据。这花了一些时间,但它有助于确保我的蜘蛛图提取工作正常。
然后我将它链接到元数据,数据集就可以处理了。
数据分析
我用这些数据来了解每个分项指标相对于总分的质量,甜蜜玛利亚的 Q-等级与有多相似,以及甜蜜玛利亚的 Q-分数与 CQI 的 Q-分数有多相似。
这里我展示了每个指标与的相互关系:
以下是这些分数如何被用来比较咖啡和其他咖啡并了解咖啡是如何相似的:
以下是 CQI 咖啡评分与甜甜玛利亚咖啡评分的相似之处:
总的来说,这项工作非常耗时,而且回报也不明朗。由此产生的分析可能是浪费时间,但更令人兴奋的分析部分是为分析做准备。否则,分析不会如此有趣,我也不会有如此强烈的情感依恋。
如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我中。
我的进一步阅读:
学习新语言的技巧
在 Python 中收集、转换和清理 JSTOR 元数据
使用 ElementTree XML 从 JSTOR 数据解析元数据的简单指南。
STOR 数据库是 50 多个科学领域研究论文的主要来源之一。在用于研究的数据部分,研究人员可以访问数据集,用于图书馆发布的文章和书籍的研究和教学。通过该服务可以获得的数据包括元数据、n-grams 和 JSTOR 上大多数文章、书籍章节、研究报告和小册子的字数。但是,数据请求的输出不是简单的 csv。或者 txt。文档,但 XML 文件需要一些处理和清理才能有效地处理数据。在 R 中,2020 年中期发布的包 Jstor 使得整个过程简单得多。
为了让数据科学家和研究人员更容易访问大量数据,在本文中,我展示了用于解析 XML 输出的 python 代码,解释了从 JSTOR data for research 数据库收集数据的过程,并展示了这种数据的一个很好的应用。
收集数据
研究数据(DfR)支持手动请求,一次最多可将 25,000 个文件作为外部链接发送到您的邮箱。这些文件可能包括数据库中发表的文章和书籍的元数据(文章或书籍名称、期刊名称、出版年份、参考文献等)。),以及 N-grams(文章和书籍的标记化文本)。
例如,我们可能会对从《泰晤士报》创刊到现在为止的 5 种顶级经济学期刊(《美国经济评论》、《计量经济学》、《经济学季刊》、《政治经济学杂志》和《经济研究评论》)中关注数据科学、机器学习和大数据的文章频率感兴趣。要提出这样的请求,这些查询需要放在这里:
(机器学习)jcode:(amereconrevi 或计量经济学或 revieconstud 或 quarjecon 或 jpoliecon)
(数据科学)jcode:(amereconrevi 或计量经济学或 revieconstud 或 quarjecon 或 jpoliecon)
(大数据)jcode:(amereconrevi 或计量经济学或 revieconstud 或 quarjecon 或 jpoliecon)
这些请求产生了 576 篇关于机器学习的文章,9 459 篇关于数据科学的文章,3 059 篇关于大数据的文章,以 XML 格式存储。
数据转换
从导入必要的库开始, ElementTree 用于解析 XML 文件,这些文件是 DfR 请求的输出, os 模块提供创建目录的功能,以便单个循环可以一起访问这些文件, Pandas 和 Numpy 进行数据操作, matplotlib 和 seaborn 绘制图形。
import xml.etree.ElementTree as ET
import os
import pandas as pd
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
将所有文件存储在文件夹 data 中,该循环首先访问三个子文件夹机器学习、数据科学和大数据,并在每个子文件夹中解析源文件。它遵循 XML 文件的层次结构,忽略书评和通知。
循环从每个文件中存储期刊标题、文章标题、出版年份和关键字(与存储文件的子文件夹的名称相同)。数据列表随后被转换为熊猫数据框。
数据清理
为了发现数据中的研究趋势,论文综述、索引、讨论、笔记和成员列表都被删除。通过这种基本的数据清理,只有发表的文章留在数据中,这提供了关于研究人员随着时间的推移对数据科学在经济学中的应用的兴趣的有价值的信息。
对原始 XML 源文件和 Pandas data frame 中转换后的数据集进行快速比较,可以看出其中的神奇之处:
最后,让我们使用 seaborn relplot 绘制系列图:
我们可以看到,自 20 世纪 60 年代以来,对数据科学的研究兴趣呈指数增长。自 20 世纪 80 年代以来,大数据经历了一场繁荣,自 21 世纪初以来,对机器学习的兴趣稳步增长。140 年跨度的数据涵盖了现代经济研究的重要发展。
来源:自己的作品。
结论
JSTOR data for research 提供了关于所有科学学科研究趋势的有价值的数据。研究人员和数据科学家可以使用文本挖掘、机器学习和其他数据科学技术来发现数据中有价值的模式。处理最终数据集可能具有挑战性,因为源数据文件是以 XML 格式发送给用户的。有了我介绍的 Python 代码,这些操作不再是一项具有挑战性的任务。
更新:2021 年 5 月,用于研究的 JSTOR 数据切换到新平台 星座 。
PS:你可以订阅我的 邮箱列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入https://medium.com/@petrkorab/membership。
感谢
本文是与 David str ba(布拉格 Lentiamo)合作编写的。
图像处理中的颜色交换技术。
理解色彩空间并在 Python 中实现色彩交换。
在这篇文章中,我试图解释我的探索,即为什么需要交换图像中的颜色,以及我们如何使用简单的图像处理方法,通过在 Python 中实现来智能地交换图像中的颜色。
为什么要换颜色?
数据科学家对颜色交换感兴趣可能有几个原因:
- 作为数据科学从业者,我们可能希望使用颜色交换方法作为数据增强策略,这有助于在处理深度学习算法的同时增加数据量。
- 很多时候,找到一个真实的、开源的大型数据集来研究算法是很有挑战性的,在这种情况下,使用合成数据会变得非常有帮助。因此,当图像数据有限时,这些图像处理技术在生成高质量的合成图像时会非常方便。
- 我们可能想尝试一些很酷的东西,比如在参加会议时交换背景色,调整衬衫的颜色等等。
色彩空间
类似于我们有不同类型的数字系统来表示一个数(例如:二进制、十进制、十六进制等。),同样,在特定的显示/图像中,有不同的数字系统来表示颜色/颜色的关联。这些系统被称为色彩空间**。**
在开始实现智能色彩映射之前,首先,让我们试着理解一些在计算机视觉和图像处理领域广泛使用的色彩空间:
RGB 颜色空间:
它是基于 RGB 颜色模型的三维空间。在这个模型中,任何颜色都是三原色分量(红色、蓝色和绿色)的不同强度的混合。这些分量可以被认为是色彩空间的数学坐标。借助于 3D 笛卡尔空间中的立方体,该模型被最佳可视化:
图 3:一个单位边长的 RGB 颜色立方体.图片作者。
所有分量以全强度会聚,产生白色。默认情况下,OpenCV 以 BGR 格式读取和存储图像。
HSV 颜色空间:
它是基于 HSV 颜色模型的三维颜色空间。在这个模型中,我们用单独的组件来表示颜色和强度:
*** Hue - 表示颜色(蓝色、红色、绿色等。),其取值范围为 0 到 360*。
饱和度- 代表一种颜色的纯度或色彩度*的多少。较低的饱和度值意味着褪色或变灰的颜色。
- Value - 代表一个色调的明度或暗度。**
这个模型最好在圆柱坐标系的帮助下可视化(虽然大多数文本使用 3D 圆锥体,但 3D 圆柱体实际上是更精确的数学表示)。
图:HSV 颜色模型,有单位半径和单位高度。?”表示该组件的值是多少并不重要。图片作者。
*在此模型中,方位角(0–360 )指定色调分量,距中心的径向距离与饱和度分量相关,沿轴的距离代表图像的亮度。
LAB 色彩空间:
**类似于 HSV 颜色空间如何从强度和亮度分量中分离颜色分量,LAB 颜色空间使用 2 个分量来表示颜色,1 个单独的分量来表示亮度值。
- L:明度分量,
- A:指定红/绿色组合的颜色分量,
- B:指定蓝/黄色组合的颜色分量。**
借助于 3-D 空间中的球体,颜色模型被最好地可视化。
图:带单位半径的 LAB 颜色模型。图片作者。
这些不同空间中的每一个都有其自身的优点和缺点,这取决于使用的应用。
实验
让我们进入实现部分。让我们考虑几种颜色交换的情况,我们将从一个简单的颜色交换图像开始(简单的意思是颜色分布变化不大),然后逐渐转到图像具有变化的颜色分布的例子,在这些例子中,交换选择的特定颜色是相当棘手的。
让我们考虑下图。它看起来像一支绿色的塑料笔身,由金属笔尖和绿色的塑料笔帽组成,笔帽上有一些金属部分和黑色的设计。
图:钢笔的原始图像。图片作者。
现在,我们想把笔身的颜色从绿色改为紫色,并希望生成的图像像原来一样逼真,并且需要在生成的图像中考虑所有的照明和阴影。我们能在 RGB 空间中实现吗?让我们试一试。注意:在 Open-CV 库的帮助下加载图像时,特定颜色空间中的组件范围通常是从 0 到 255。对于 HSV,OpenCV 使用 H:0–179,S:0–255,V:0–255。
图:x 轴代表[0,180]中的Hue
图:将【B】分量的值增加一个固定的量,会导致颜色和强度值都发生变化。图片作者。
这个奇怪的合成图像的原因是:
- RGB 空间借助所有三个分量(R、G 和 B)来指定颜色和亮度信息。
- RGB 图像中的每个像素都是这些成分的特定组合,我们无法解释一个成分需要改变多少才能获得所需的颜色。
- R、G、B 分量中任何一个的任何变化都会引起像素的颜色和亮度值的变化。
如果有一个空间,其中颜色和亮度信息都在彼此独立的单独组件中指定,那么交换颜色将会非常容易。这就是像 HSV 和 LAB 这样的色彩空间出现的原因。现在让我们试着通过改变 HSV 颜色空间中的色调值来交换钢笔颜色。
图:通过改变图像的色调分量得到的图像。亮度和饱和度值没有干扰。图像看起来很真实。图片作者。
类似于改变色调值如何不影响图像的亮度分量,让我们检查我们是否可以改变图像的亮度而不干扰图像的颜色/色调分量。
图:通过降低亮度分量获得的图像。图片作者。
显然,在 HSV 颜色空间中使用不同的组件非常容易。我们看到了修改不同的组件如何帮助我们分别转换图像的颜色组件和亮度。
将亮度通道乘以 0.6(暗化效果)也会导致背景变暗。在早期的图像中,我们也看到改变色调值会导致背景颜色的变化。
让我们来研究一下,如何只改变钢笔的颜色或者只改变前景的亮度而不改变背景。注意,还有其他基于深度学习的技术,如 GANs,也可以用来实现相同的目的,在本文中,我们只讨论解决该问题的简单图像处理技术。
这个想法是为背景或前景创建一个颜色范围二元蒙版,然后使用该蒙版有选择地将颜色变化应用于前景。但是,面具适合哪种颜色呢?为了回答这个问题,如果我们为我们的色调/颜色通道绘制直方图就好了。这是我们的色调通道和直方图的样子:
图:原始笔图像的色调通道。图片作者。
图:颜色分布直方图。图片作者。
上面的直方图暗示峰值出现在~120,这是我们图像中的主要背景色和噪声。从上面的 HSV 颜色空间中,可以注意到绿色在 55–65 附近达到峰值,这也是为什么我们在上面的图中在相同的间隔附近看到一个小峰。因此,我们试图为相似的色调范围创建一个遮罩。
图:钢笔的颜色遮罩(前景)。图片作者。
现在,让我们增加这个二元蒙版中非零像素的色调值。
图 5:我们改变了前景色,但没有改变背景。所有的照明都完好无损。图片作者。
这就是我们如何能够成功地交换图像的颜色,而不操纵背景颜色。
最后,我想提一下在电视和电影中非常流行的 色度键控 方法。这种技术也可以用来交换图像中的颜色。这里的想法是从两个图像开始,一个是安装在绿色或黑色屏幕上的前景,第二个是需要叠加在背景上的图像。方法是首先提取图像中的所有绿色或黑色像素,使这些像素透明,这将使我们能够在背景中覆盖所需的图像。 但是,这种方法要求表面非常光滑,只有很少的光照。
我希望你喜欢颜色交换的想法。我很乐意回答上述任何概念的问题。我想知道任何阅读这篇文章的人的反馈。你可以通过 Linkedin 联系我。
谢谢大家!
特别感谢 Apurva Gupta 对博客的评论。
基于 K-均值的彩色图像量化
一个关于如何使用 Python 和 OpenCV 减少图像中不同颜色数量的简单教程
Joyce McCown 在 Unsplash 上的照片
颜色量化是一种减少图像颜色数量的过程,同时试图保持图像质量和重要的全局信息。图像由像素组成,在 RGB 颜色空间的情况下,每个像素可以与 16,777,216 种不同的颜色相关联,这可能是最常用的颜色空间。每种颜色都可以表示为一个 3d 矢量,每个矢量元素都有一个 8 位的动态范围,这意味着 2⁸=256 不同的值(即 256x256x256 =16,777,216)。这种表示通常被称为 RGB 三元组。成功的颜色量化的关键因素是适当选择能够充分概括初始图像信息的调色板。
动机 : 什么时候应该使用彩色图像量化?
如果我们想要在仅支持有限数量颜色(有限调色板)的设备中渲染图像,彩色图像量化可能是至关重要的,这通常是由于内存限制而发生的。
作为聚类问题的颜色量化
解决图像色度压缩的最常见方法之一是使用聚类,其中特征是图像的颜色。K-means 是一种非常流行的矢量量化聚类方法,多亏了 scikit-learn 库,它真的很容易使用(只要你知道它是如何工作的)。当然,其他聚类方法如奇异值分解、高斯混合模型等。把工作做好。
色彩空间
颜色空间是描述颜色表现方式的数学模型。最简单的方法是想象一个盒子,里面装着所有可能的颜色,这些颜色可以由光的三原色混合而成:红色、绿色和蓝色、光源。在图 1 中,您可以看到数学家为了将三个轴(红色、绿色和蓝色)拟合为二维格式而绘制的图表:
图 1: CIE 色度图[ 来源
Adobe RGB、sRGB 和 CMYK 都是色域(范围),是 1976 年由国际照明委员会(简称 CIE)定义的 Lab* 色域的子集,旨在作为感知均匀空间,其中给定的数值变化对应于相似的感知颜色变化。我这样说是因为对于 K-means,我们需要一个距离度量来衡量特征之间的相似性。感知上不一致的 RGB 颜色空间意味着具有相同欧几里德距离的两对颜色可能被感知为不相等的不同(由于每种颜色的不同波长以及人眼对如何感知每一种颜色的敏感性)。
键取:应用 K-means 之前,将图像转换为 Lab* 颜色空间。
守则
下面是使用 scikit-learn 库(实现 K-means 方法)和 OpenCV 库进行图像处理的颜色量化代码。
您可以在我的 GitHub 上找到代码(作者图片)
- 最初,我们期望用户给出两个命令行参数:(1)输入图像的路径,以及(2)集群的数量。
- 我们加载图像,并将其转换为 Lab*色域。
- 我们将原始图像重新整形为(宽高,3* ),因为 k-means 将二维数组而不是三维数组作为输入。
- 我们用用户决定的 K 个聚类初始化我们的分类器。
注意:我之所以选择使用minibatch kman s是因为它比普通 kman 快得多,尽管与对整个人群进行操作的 kman 相比,它对小批量的 kman 进行操作,质心可能不那么稳定。从迷你批次开始是一个很好的做法,如果结果不太令人满意,您可以尝试使用迷你批次。
- *clf . fit _ preview(image)*返回每个像素的预测值,即该像素属于哪个聚类。
- *量化= clf.cluster_centers_。a type(“uint 8”)[labels]*通过将原始图像中的每个像素值重新分配到其对应的最近中心来创建量化图像。
- 我们将初始和量化的特征向量重新整形为图像,并将其转换为 RGB 色域。
- 最后,我们将(原始图像和量化图像的)拼接保存到磁盘上。
结果
在这一段中,我将把上述程序的结果应用在一张海报上,这张海报是我从 我的英雄学院维基 借来的我最喜欢的动漫《博库无英雄学院》🎆。
K = 2
图 2:我们的调色板包括两种颜色,黑色和米色(图片由作者提供)
注意:该算法最初从给定数据中随机选择 K 个质心,并在每一步将每个数据点分配给最近的质心。当所有数据点(特征)都被分配给一个质心时,重新计算 K 个聚类的每个平均值,这两个平均值就是新的两个质心。重复该过程,直到没有质心更新(或者至少小于阈值)发生。因此,这两种颜色并不是在初始图像中最频繁出现的颜色(可能会产生误解),但是您可以将它们想象为这两种颜色,这两种颜色是两个聚类的平均值(即中心),并且意味着其他颜色分别与这两个中心的距离总和的最小化。
K = 8
图 3:我们的调色板由 8 种颜色组成——可以观察到不同深浅的灰色、红色和黄色(图片由作者提供)
K = 32
图 4:我们的调色板由 32 种颜色和绿色组成(图片由作者提供)
K = 40
图 5:我们的调色板由 40 种颜色组成,我们可以看到它非常接近原始图像(作者的图像)
结论
总之,在这篇文章中,我们看到了几行代码如何对图像进行颜色量化。图 5 显示,由于内存限制,设备仅支持有限数量的颜色(比如 40 种颜色),这种方法可以转换初始图像,但质量不会明显下降,并且重要信息得以保留。
对抗深度学习中的过度拟合
阻止你的深度学习模型过度拟合
在 Unsplash 上由 Waldemar Brandt 拍照
过度拟合问题
过度拟合是指机器学习模型在训练数据上表现良好,但在验证数据上表现糟糕的情况。简单地说,当机器学习模型记住了训练数据中的模式,但未能推广时,这被称为过度拟合。
服装行业就是一个过度合身的真实例子。设计师们试图裁剪他们的尺码,这样一个尺码就能适合各种不同的体型和大小——例如,一个人穿中号可能会显得肌肉发达,而另一个人穿中号就会显得松松垮垮。
如果设计师决定为体型较小的人量身定做尺寸,这种服装就不能适用于各种体型和尺寸。这里你有过度拟合的问题。
解决过拟合问题
在 情绪分析:预测一条推文是否是关于一场灾难的中,我进行了一些可视化,建立了几个模型,其中我的双向 LSTM 名列前茅。
作者图片
经过仔细检查,我意识到我的模型过度拟合了训练数据。使用强大的模型时可能出现的许多问题之一。
我们可以通过两种主要方式来解决深度学习模型中的过度拟合问题:
- 对模型的改进
- 我们数据的改进
我知道你在想什么…我该如何改进我的模型?我如何改进我的数据?这些描述很模糊。所以让我们开始吧。
注:本文中用于生成模型的所有代码都可以在 Github 上找到。
对模型的改进
简化模型:我们最初建立的模型有 193381 个可训练参数。那是相当高的。随着可训练参数数量的增加,我们的模型更容易记住每个训练实例的标签,这绝对是我们想要的。最初的模型结果是:
- 训练 F1 分数— 0.9019 (4 标准英尺)
- 验证 F1 分数— 0.7444 (4 标准偏差)
以及我们模型的总结…
作者图片
我们可以通过减少网络的容量来简化我们的模型,这样我们的模型就别无选择,只能学习给网络带来价值的数据模式,或者用深度学习的术语来说,最小化损失。方法是移除隐藏层。
作者图片
注意:看我是如何在双向 LSTM 后去掉密集层的。
对我的验证数据运行后的结果是:
- 训练 F1 分数— 0.8362 (4 标准英尺)
- 验证 F1–0.7622(4 平方英尺)
**正则化:**我们可以解决深度学习模型中过拟合问题的另一种方法是应用正则化。本质上,正则化是添加信息以解决不适定问题或防止过度拟合的过程[ 来源 : 维基百科 ]。
两种流行的正则化技术是 L1 和 L2 正则化。L1 正则化不利于权重的绝对值,这导致一些权重等于 0,而 L2 正则化取所有特征权重的总和,并强制权重较小但不为 0。
吴恩达在 Coursera 上的机器学习课程中完美地解释了这种直觉。
对于我们的例子,我将添加 L2 正则化到我们的初始模型。
作者图片
我们修正模型的结果是:
- 训练 F1 分数— 0.8899 (4 标准英尺)
- 验证 F1 分数—07504 (4 标准偏差)
这是对初始模型的一点改进,但我们可以做得更好。
**Dropout Layers:**Dropout Layers 是另一个有效的正则化工具,它的名字非常直观。实际上,丢弃图层会将图层的输出要素随机设置为零。在我们最初的网络中,我们已经有了一些,但我们可以添加更多。
作者图片
向我们的模型添加漏失层的结果:
- 训练 F1 分数— 0.8205 (4 标准英尺)
- 验证 F1 分数— 0.7700 (4 标准英尺)
**早停:**早停这个名字也挺直观的。本质上,你提前停止训练过程,而不是训练固定数量的时期。停止训练的队列是当验证误差停止减小并开始上升时。
作者图片
提前停止的结果:
- 训练 F1 分数— 0.8650 (4 标准英尺)
- 验证 F1 分数— 0.7525 (4 标准偏差)
数据的改进
**收集更多数据:**当训练样本很少,但特征很多时,模型往往会过拟合。如果资源可用,那么回到绘图板并收集更多数据可能是一个好主意,至少,您希望有比功能更多的训练示例。
**特征选择:**收集数据在时间和资金方面都是一个昂贵的过程,因此,只有当它能显著提高模型的性能时,我才会推荐它。首先,我们需要收集数据的人,然后我们需要标记数据的人。我们可能决定进行特征选择,而不是获取更多的实例。这是我们选择只使用带来最大价值的特性的时候。
包裹
在这篇文章中,我向你介绍了在深度学习模型中对抗过度拟合的各种方法。结果仍然不完美,但大多数时候我们看到我们的模型有所改进。请记住,我是单独执行每一种正则化技术的,因为如果一起执行,我们可以实现一个真正强大的分类器。然而,太多的正则化会导致我们的模型拟合不足,这是一个完全不同的问题。
在 LinkedIn 和 Twitter 上与我联系,了解我关于数据科学、人工智能和自由职业的最新帖子。**
自动驾驶汽车联合学习和主动学习的结合
解决汽车应用中数据隐私和许多其他培训挑战的分布式学习方法
集中式学习是一种在一个地方(通常在云中)训练机器学习模型的方法,使用来自利用该模型的所有设备的聚合训练集。**集中学习的优势在于归纳从所有设备收集的数据,并提供优化的模型。**这种方法带来了以下挑战:
- 数据隐私:在某些行业或应用中,如医药或金融,数据是敏感的,不能移动到其他位置
- 有限的网络容量:一些网络属性,如客户端和集中式模型之间的带宽和延迟,会影响训练过程的性能
- 非独立同分布(独立同分布)数据分布:采集到的数据属于不同的环境、时间、客户端,不满足数据的独立同分布特性,这在大多数统计分析和 ML 算法中被认为是一个必需的假设。
- 中央存储容量:汽车应用中大量数据带来的高存储要求
联合学习(FL)解决了上面提到的这些集中式学习的挑战或缺点。**联合学习的一个关键特性是保护用户数据。这意味着数据应该位于生成它的位置,而不是移动到另一个位置进行培训。换句话说,算法应该移动到生成数据的地方。**但是,当您有许多客户端要发送大量数据时,另一个方面(如有限的网络容量)也很关键。我们可以用机器学习的模型参数或权重代替记录的原始数据,减少通信开销。
然而,目标是传递机器学习模型参数,而不是需要安全的数据。机器学习的新挑战是定义适当的损失函数,并以分布式方式训练模型,以最终获得收敛且准确的模型。
自动驾驶是 FL 的新应用
自动驾驶汽车的开发需要从各种点收集大量的环境数据,如自我车辆数据、来自道路上另一辆车辆的数据、基础设施传感器数据、地图数据等。分布式数据都可以与由机器学习算法实现的车辆功能相关。当集中学习不可能或不被允许时,联合学习可以提供一种分散的学习方法。作为边缘设备的车辆负责训练本地模型并将其与其他车辆共享,或者中央服务器可以聚集所有模型并创建最终的优化模型,并立即或定期更新所有车辆。
主动学习
主动学习是一种查询用户数据并为算法标注相关数据的学习算法。主动学习通过自动数据标注帮助降低培训成本。**主动学习中最关键的挑战是选择一部分与训练相关的数据。**目的是评估未标记数据的信息价值,并只挑选数据中有信息的部分。我们需要制定一个策略来避免对每个客户的数据有偏见。每个客户端可能有不同的数据量,或者包含特定于环境的数据,这会导致数据偏差。
自动驾驶中机器学习的新方法
本文表明,该方法比基于服务器的联邦学习收敛快得多。学习架构适用于克服非独立数据,管理客户数据之间的巨大差异,并在准确性和收敛能力之间找到一个平衡点。通过可视化来自驾驶场景的三个图像数据集来评估该出版物中提出的模型。
观点
使用此解决方案具有以下优势:
- 当需要实现最终模型的准确性时,我们至少可以在模型的集中训练之前在本地预先标记数据,这对于分布式数据来说是非常昂贵和具有挑战性的。
- 我们在本地训练模型,所以车辆总是使用更新和优化的模型。
- 用户数据的本地存储保证了数据隐私
- 不需要中央数据存储
- 降低网络开销
- 利用车辆的计算能力和真实世界的数据来改进 ML 模型
结合联合和主动学习可以用分布式车辆或基础设施传感器数据来训练模型。这个想法很吸引人,因为每秒钟都会从车辆或基础设施中收集大量数据。
**选择正确的分布式机器学习架构解决了网络性能限制。**需要 V2X(车辆对一切)通信技术来在车辆之间(车辆作为边缘设备)或在汽车和边缘服务器之间交换数据,这取决于所选择的联合学习方法。
**主动学习和联合学习使我们能够进入现实世界的驾驶和停车场景,这些场景并不总是容易通过模拟来验证。**这种方法允许精确的自动驾驶汽车验证,正如特斯拉和 Waymo 可能在多年前开始的那样。这种方法仍然具有挑战性,因为车辆正在运动,收集的数据是有时间标记的,可能很快就会过时。标记数据也很有挑战性,需要自动化的数据标记流程。这种方法减少了标记的时间和成本,并改善了整体 CI/CD 管道和自动驾驶汽车功能的机器学习模型的部署。
组合优化:背包问题
将动态规划技术应用于一个有趣的优化问题
作者图片
在这个故事中,我们将讨论动态编程技术在优化算法中的应用。通过开发最佳解决方案的过程,我们可以学习各种编程技术,从而获得更好的性能(最后还有一个惊喜!).
问题描述
背包问题
这个问题被称为背包问题,因为人们在将物品装入背包时会遇到类似的问题,同时试图优化所装物品的重量和价值。
因此,给定一个字符串列表:
r1 = ['001', '11', '01', '10', '1001']
并且给定一个最多可以容纳 5 个 0 和 5 个 1 的容器。
m = 5
n = 5
我可以装入容器的字符串的最大数量是多少?
一个选择是:
c1 = ['001', '1001', '11']
在这种情况下,我们已经包装在 3 个字符串中,并使用了 4 个 0 和 5 个 1,这是我们能做的最好的吗?
事实上,我们可以做得更好:
c2 = ['001', '11', '01', '10']
在这种情况下,我们已经用完了 4 个 0 和 5 个 1,并且我们装入了 4 个字符串。
问题是,我们如何着手系统地解决这个问题?
第一次尝试
只是想完成工作
我们从哪里开始?对我来说,最简单的方法是显而易见的:
循环遍历每个字符串,在循环中,如果可能的话,将当前字符串放入容器中,然后尝试找到在假设当前字符串已经在容器中的情况下可以装入容器的最大剩余字符串数,即使用递归。
def count_dim(string):
*'''
Counts the number
of zeros and ones
in a string* ***:param*** *string: '00111'* ***:return****: (2, 3)
'''* m = 0
n = 0
for i in string:
if i == '0':
m = m + 1
else:
n = n + 1
return m, n
def preprocess_input(strings):
*'''
Transforms list of strings
to tuples of dimensions* ***:param*** *strings: ['100', '011']* ***:return****: [(2, 1), (1, 2)]
'''* dim_list = [count_dim(string)
for string in strings]
return dim_list
def max_subset(input_data, m, n):
*'''
Loops through each string,
recursively try to find the max
subset of the remaining strings
and add up the results* ***:param*** *input_data: ['10', '11']* ***:param*** *m: 2* ***:param*** *n: 4* ***:return****: 2
'''* max_count = 0
for i, tup in enumerate(input_data):
if tup[0] <= m and tup[1] <= n:
new_input = input_data[:i] \
+ input_data[i+1:]
max_count = max(max_count,
1 + max_subset(new_input,
m - tup[0],
n - tup[1]))
return max_count
r1 = ['001', '11', '01', '10', '1001']
m = 5
n = 5
r1 = preprocess_input(r1)
print(max_subset(r1, m, n))
# Outputs:
# 4
算法足够简单,但执行起来如何?让我们来看看。
在每次调用 max_subsets 的过程中,它会遍历输入中的字符串数,所以如果我在输入中有 L 个字符串,第一次递归会处理循环 L 次,第二次递归会处理循环 L-1 次,以此类推。因此,算法的复杂性是:
O(L!)(图片由作者提供)
这是你能做的最糟糕的事情了。
第二次尝试
更智能的循环
实际上有一种简单的方法来加速它,而不是一遍又一遍地遍历输入中的每个字符串,我们只遍历一次字符串列表。想想看,这个问题涉及到从字符串列表中挑选出字符串的子集,所以本质上你是在试图寻找最佳的二进制字符串,例如:
r1 = ['001', '11', '01', '10', '1001']
c1 = ['001', '1001', '11']
b1 = 11001
b1 本质上是 c1 作为 r1 子集的表示
所以游戏计划是从第一根弦开始,你有两个选择:保留它或者丢弃它。首先,尽量保持它(1),并递归地找到剩余字符串的最大子集。然后尝试丢弃它(0),并递归查找剩余字符串的最大子集。两个结果中较大的一个是整个输入的最大子集。
def max_subset(input_data, m, n):
if len(input_data) <= 0:
return 0
if m < 0 or n < 0:
return -1
tup = input_data[0]
new_input = input_data[1:]
max_count = max(max_subset(new_input, m, n),
1 + max_subset(new_input,
m - tup[0],
n - tup[1]))
return max_count
该算法产生相同的结果,但是具有更好的复杂度。在每个“max_subset”调用中,您调用了“max_subset”两次,并且在字符串列表中正好有 L 个字符串,复杂性将是:
O(2^n)(图片来自作者)
好多了,但还是没那么好…
记忆增强
用空间换时间
当前形式的算法仍有许多冗余,例如:
r1 = ['001', '11', '01', '10', '1001']
b1 = 1001?
b2 = 1010?
当您到达字符串“1001”时,您可能会采用几种不同的路径,其中两种是:1001 和 1010,或者[‘001 ‘,’ 10’ ]和[‘001 ‘,’ 01’]。
两条路径剩余的 0 和 1 的数量完全相同:(2,3)。所以一旦你到达步骤‘1001’所需要的计算是相同的,并且它被做两次,并且当问题变大的时候潜在地更多次。
使用备忘录来保存已经计算过的结果将是一个加快这个过程的好方法。
在这种情况下,我们需要一个索引为(I,j,k)的映射,其中“I”是字符串列表中的当前位置,“j”是剩余的 0 的数量,“k”是剩余的 1 的数量。
def max_subset(input_data, m, n, memo={}):
if len(input_data) <= 0:
return 0
if m < 0 or n < 0:
return -1
if (len(input_data), m, n) in memo:
return memo[(len(input_data), m, n)]
tup = input_data[0]
new_input = input_data[1:]
max_count = max(max_subset(new_input, m, n, memo),
1 + max_subset(new_input,
m - tup[0],
n - tup[1],
memo))
memo[(len(input_data), m, n)] = max_count
return max_count
这个算法表现如何?嗯,由于 memo 中的每个元素只计算一次,字符串的长度为 L,所以 0 的个数为 M,1 的个数为 n,算法的时间复杂度为:
O(LMN)(图片由作者提供)
由于 memo 中的每个(I,j,k)都可能有一个条目,所以空间复杂度也是 O(LMN)。
动态规划
让算法变得更好
你会问,我们能进一步改进算法吗?
事实上,有一个非常聪明的方法可以降低算法的空间复杂度,那就是使用动态规划算法。
想象你在输入字符串列表的第三个元素:“01”。
你问自己这个问题,如果字符串列表从开始到‘01’,我需要知道什么才能算出我可以装入容器的最大子集,即:
'001', '11', '01'
?
好吧,如果我知道给定 4 个 0 和 4 个 1 容器,我可以用“001”、“11”构造的最大子集,以及给定 5 个 0 和 5 个 1 容器,我可以用它们构造的最大子集,那么给定 5 个 0 和 5 个 1,我可以用“001”、“11”、“01”构造的最大子集是:
max_subset(['001', '11', '01'], 5, 5) = \
max(max_subset(['001', '11'], 5, 5), # without '01'
1 + max_subset(['001', '11'], 4, 4)) # with '01'
这种关系构成了我们将要创建的动态编程算法的基础。
我们可以做的是有一个大小为(m+1,n+1)的备忘录地图,最初,它都用零填充。
当我们开始处理第一个字符串“001”时,我们尝试从(5,5)开始更新映射:
max_subset(['001'], 5, 5) = \
max(max_subset([], 5, 5),
1 + max_subset([], 3, 4))
然后(5,4),(5,3) …,(4,5),(4,4),…,直到(2,1),因为‘001’有 2 个 0 和 1 个 1,所以我们不能再减少容器的维数了。
我们有了更新后的地图,如下图所示:
(图片由作者提供)
现在,映射中的每个位置都表示给定字符串列表[‘001’]和容器(m,n)的最大子集。
对字符串列表中的剩余字符串重复这个过程,最终的 memo map,在位置(5,5)将包含我们问题的答案。
def init_memo(m, n):
return [[0 for i in range(n + 1)] for j in range(m + 1)]
def update_memo(z, o, m, n, memo):
for i in reversed(range(z, m + 1)):
for j in reversed(range(o, n + 1)):
memo[i][j] = max(1 + memo[i - z][j - o],
memo[i][j])
def max_subset(input_data, m, n, memo=None):
if memo is None:
memo = init_memo(m, n)
if len(input_data) <= 0:
return memo[m][n]
current = input_data[0]
input_data = input_data[1:]
update_memo(current[0], current[1], m, n, memo)
return max_subset(input_data, m, n, memo)
我们来看看这个算法的性能。由于我们遍历每个字符串一次,并且在每次迭代期间,我们更新大小为 M*N 的备忘录映射,因此时间复杂度为:
O(LMN)(图片由作者提供)
和以前一样。
但是因为我们只使用大小为 M*N 的地图,所以空间复杂度是:
O(M*N)(图片由作者提供)
我们将空间复杂度降低了 1 倍!
你会问,有什么问题?为什么现在需要的备忘录地图的大小减少到 O(MN)?这与地图的“动态”本质有关。想想看,在每次迭代期间,您都在用新信息更新存储在映射中的值,以考虑到添加的字符串,因此您丢弃了不再需要的旧信息,从而将映射的空间需求从 O(LMN)减少到 O(MN)。
结论
老实说,我第一次尝试这个问题的时候,我认为我们对时间和空间复杂度的最佳结果是 O(LMN),但是一个非常聪明的观察帮助我们大大降低了空间复杂度。因此,感谢动态编程,我们能够了解对算法进行改进的可能性,而这种改进并不明显。它还提醒我们,无论问题是什么,都要对新的或更好的解决方案保持开放的心态。
使用 Apache Flink 组合和预处理您的异构数据以进行分析
作者图片
通过使用该架构在一个地方清理和合并您的实时和历史数据,使您作为数据科学家的生活更加轻松。忘记访问多个系统和清理日常分析任务。
介绍
数据驱动的决策和应用是未来业务的核心。从数据中获得洞察力意味着成本降低、效率提高和战略优势。越来越多的公司通过应用以数据为中心的架构,在数据库中生成和收集除经典批量数据之外的流数据或实时数据。因此,公司面临的挑战是在分析中处理流数据和批量数据,以获得整体和最新的见解。
流数据和批处理数据必须先合并,然后才能作为组合数据集进行可视化和处理。本文描述了一个基于 Apache Flink 和 Lambda 架构的 Lambda 架构的实现,以解决这一挑战。Apache Flink 是一个计算无界和有界数据流的框架。Flink 在不同的抽象层次提供了多个 API,并为不同的用例提供了专用的库。为了更具体,我将在整篇文章中使用一个端到端的例子。
出发点
我们使用包含空气测量站的事件数据的数据集。在这组数据中,我们发现了九个传感器对空气中不同物质的每小时测量值。除此之外,还记录了日期、时间、温度和空气湿度。数据集由 De Vito 等人发表在 UCI 机器学习知识库上。
我们在哪里?
我们假设,作为物联网设备的测量站每小时将数据发布到 Apache Kafka 主题中,我们可以在其中使用这些数据。数据在被删除之前会在 Apache Kafka 主题中保留一段固定的时间。因为我们不想丢失这些历史数据,所以我们定期将它存储在一个持久数据库中,以便随时进一步处理数据。这两个系统构建了我们的混合数据存储架构。
作为数据科学家,我们希望访问所有数据——来自 Kafka 的实时数据和来自数据库的历史数据——以便实时访问所有数据和进行全面分析。通常我们必须用不同的访问方法查询两个系统,这既不方便,也不可扩展,也不容易维护。
我们想去哪里?
这就是为什么我们需要一个来自 Kafka 和数据库甚至更多系统的数据的组合视图,我们只需要访问一个系统就可以一次获得从历史到最近数据点的所有数据。因为它是使用最广泛的技术,我们希望使用数据库作为所有数据的一站式商店。
流数据和批处理数据在模式、数据类型、相同情况的表示以及最终的数据质量方面可能有所不同。所以,数据需要标准化。此外,作为数据科学家,我们还希望通过自动清理原始数据来摆脱日常工作。
λ架构
我们展示的系统基于 Lambda 架构,由 Nathan Marz 于 2011 年首次推出。简而言之,Lambda 架构包含三个相关层。批处理层处理来自数据库或数据湖的所有批处理数据。速度层实时处理所有流数据。因此,可以以最小的延迟访问新数据。服务层是最后一个组件,负责合并来自其他两个层的清理数据,并将其提供给其他应用程序。通常,专用(例如 Java 或 Python)应用程序用于从两层加载数据,并在服务层以标准化的形式将数据汇集在一起。使用 Flink,标准化已经在速度和批次层完成。如果你想更详细地了解 Lambda 架构,我推荐这篇文章。
Lambda 架构的示意图。作者图片
架构概述
提议的系统基于 Lambda 架构,但通过巧妙使用现代技术解决了它的一些主要弱点。我们主要使用两种工具。第一个是阿帕奇弗林克。Flink 是一个能够处理流数据和实时数据的框架。因此,它非常适合这个用例。我们使用 Flink 的连接器实时消费来自给定 Kafka 主题的消息,或者通过 JDBC 连接从数据库中读取历史数据。速度图层有一个 Flink 作业,批处理图层有另一个 Flink 作业。它们只是在数据接收方面有所不同。对于一个用例,处理和输出部分是完全相同的。我们将在后面的示例中查看数据处理。Flink 可以将数据输出到各种数据接收器。对于我们的系统,我们使用 Apache Cassandra 数据库,因为它针对繁重的编写工作负载进行了优化。
建议的数据准备系统的架构。作者图片
利益
你可以在这里阅读关于 Apache Flink 的精彩介绍。我们声明我们想要标准化和准备数据。
使用 Flink,我们可以使用相同的代码来处理批量数据和流数据,因为 Flink 将批量数据作为有限的数据消息流来处理。
这是一个独特的卖点,有利于 Flink 反对类似的选项,如 Spark 或 Storm。此外,Flink 为复杂的转换提供了很大的灵活性,因为我们可以使用 Java、Python 甚至 SQL 来处理数据。Apache Flink 由多个组件构建而成,其中每个组件都包含针对不同数据结构(数据流与表)或特定应用需求(机器学习)的特定功能。
示例:准备数据
在探索性的数据分析过程中(本文跳过了这一步),我们意识到
时间和日期的格式不正确
有许多错误值,我们应该以某种方式修复它们
已知的错误值是“-200.0”
其中一个属性(NMHC(GT))有太多的错误值,我们需要删除整个列
为了准备和合并数据,我们遵循以下路径:在下图中,您可以看到我们有两条管道,一条用于流数据,一条用于批处理层。本文的以下部分分为“加载数据”,在这里我们将使用卡夫卡和 JDBC 连接器。然后“处理数据”,在这里我们使用“映射”和“过滤”功能,甚至窗口功能来清理和标准化数据。这个管道的最后一步当然是“合并和提供”数据。Flink 将处理后的数据交付给数据库,在那里进行合并和存储以备将来使用。
在这个用例中,Kafka 中的所有数据都是通过 Apache Avro 模式定义的。Avro 就像节俭或协议缓冲区。Avro 作为一个序列化系统被用在许多生产环境中,因为序列化的数据更小。Avro 具有丰富的数据结构,提高了传输和处理效率。
转换在批处理和速度层中流动。作者图片
加载数据
让我们从导入数据开始。我们在速度层的 Flink 作业中建立了一个 Kafka 消费者。我们需要提供主题名、Kafka 节点的地址和一些连接属性,比如模式注册 URL。我将消费者和生产者代码转移到一个专用的 java 类( KafkaConnection ),这样我们就可以在更多的工作中轻松使用它。
public class KafkaConnection {
public static <avroSchema> FlinkKafkaConsumer010
getKafkaConsumer(Class avroSchemaClass, String inTopic, String
schemaRegistryUrl, Properties properties) {
FlinkKafkaConsumer010<avroSchema> kafkaConsumer = new
FlinkKafkaConsumer010<avroSchema>(
inTopic,
(DeserializationSchema<avroSchema>)
ConfluentRegistryAvroDeserializationSchema.forSpecific(
avroSchemaClass, schemaRegistryUrl),
properties);
kafkaConsumer.setStartFromLatest();
return kafkaConsumer;
}
}
这个 Kafka 消费者将 Avro 模式 AirQuality_value 中定义的收集到的消息发送到数据流中。该使用者在 Flink 作业中构建数据流的源。
// Initialize KafkaConsumer
FlinkKafkaConsumer010 kafkaConsumer = KafkaConnection.getKafkaConsumer(AirQuality_value.class,
inTopic,
schemaRegistryUrl,
$properties);// Set KafkaConsumer as source
DataStream<AirQuality_value> inputStream = environment.addSource(kafkaConsumer);
为了读取 PostgreSQL 数据库,我们定义了一个 JDBC 连接器。因此,我们使用 Flink 的 JDBC 连接器包的 JdbcInputFormatBuilder ,并传递必要的参数,如下所示。因此,我们创建了一个带有行模式的数据流。
JdbcInputFormat.JdbcInputFormatBuilder inputBuilder = JDBCConnection.getSource($fieldTypes,
$driverName,
$dbURL,
$sourceDB,
$selectQuery,
$dbUser,
$dbPassword);DataStream<Row> inputStream = environment.createInput(inputBuilder.finish());
在我们可以在两层中平等地转换数据之前,我们需要将速度层中的数据从 Avro 模式转换为更通用的行模式。你会在上图中看到这一步是速度层的第一个动作。然后,批处理和速度层中的数据流具有相同的内部格式,我们可以用相同的方式转换它们。
转换数据
我们通过应用模块化转换器来转换数据,每个转换器执行一个特定的操作。我们设置了转换器,用于从流中过滤消息,其他的操作值,改变单一数据类型或者删除属性。此外,还有窗口和 SQL 转换,例如删除重复的。我们将这些转换器实现为 java 类,让我们通过提供一些参数来调整确切的行为。它们被设计为由数据流的过滤器()、*映射()或窗口()*函数调用。当然,这些变压器是基本的,但我们可以将它们堆叠起来,构建强大的转换管道。
为了处理空气质量数据,我们首先通过 FeatureAggregation() 将“日期”和“时间”属性(在索引 0 和 1 处)连接成一个属性。然后,我们在第二行将结果字符串转换为 SQL 就绪的时间戳。接下来,我们删除原来的日期和时间属性,因为不再需要它们了。此外,我们删除了 NMHC(GT)属性,它有太多的错误,不能通过调用feature selectiontransformer 来清除。转换器只保留新的时间戳属性和除 NMHC(GT)之外的所有属性。
DataStream<Row> timestampStream = inputstream
.map(new FeatureAggregation(0, 1, "+"))
.map(new StringToDate(14, "dd/MM/yyyy HH.mm.ss"))
.map(new FeatureSelection($keptAttributes);
现在它变得稍微高级一些:我们使用一个窗口函数,用在一个时间窗口内计算的平均值来代替误差值(-200.0)。您可能知道 SQL 中的这种方法是“ OVER ”子句与“ROWS before”的组合。我们将这个转换器应用于包含传感器数据的所有属性。之前,我们需要创建窗口,这样数据流中的消息就可以拆分到不同的窗口上。像在 SQL 中一样,我们需要一个键来控制窗口分割。我们将窗口的“大小”定义为 20 秒:使用这种配置,来自同一天的、在 20 秒内到达的所有消息都将被路由到同一个窗口。对于每个属性,计算一个平均值来代替所有的误差值。
DataStream<Row> windowedStream = timestampStream
.keyBy(new DateAsKey())
.window(EventTimeSessionWindows.withGap(Time.seconds(20)))
.process(new ReplaceMultipleByAverage(replace_fields,"==",
-200.0f));
不幸的是,这不足以完全清除数据。一些属性包含如此多的错误,以至于当前窗口中计算的平均值也被错误值破坏。因此,我们需要从数据流中过滤出所有剩余的有错误的消息。
DataStream<Row> outputStream = windowedStream.filter(
new RemoveErrorValues(0,"==", -200.0f));for (int i = 1; i < outputStream.getType().length(); i++) {
outputStream.filter(new RemoveErrorValues(i,"==", -200.0f));
}
我们通过在一个循环中多次应用过滤函数来检查所有字段。最后,数据可以写入数据库,并在以后的应用程序中使用。
合并并提供数据
剩下的唯一事情就是将数据写到数据库中。将它写入服务层会同时合并流数据和批处理数据:通过将它写入一个表来合并。我们使用下面的 Cassandra 接收器将处理过的流输出到同一个 Cassandra 表。但是你也可以使用 JDBC 水槽。
CassandraSink.addSink(outputStream)
.setClusterBuilder(
new ClusterBuilder() {
@Override
public Cluster buildCluster(Cluster.Builder builder) {
Cluster cluster = null;
try {
cluster = builder.addContactPoint(cassandraURL)
.withPort(cassandaPort)
.withCredentials(
cassandraUser,
cassandraPassword)
.build();
} catch (Exception e) {
e.printStackTrace();
}
return cluster;
}
}
)
.setQuery(insertQuery)
.build();
insertQuery 只是一个普通的 SQL“Insert…”查询。重要的是要理解批处理层只写历史数据,而速度层应该在当前的时候已经写了。因此,批处理图层会覆盖速度图层中的数据,因为它更加准确和可信。您需要确保 speed 层不会插入任何带有现有主键的数据,而 batch 层必须能够覆盖带有相同主键的现有行。这可以通过配置表中的主键约束并为每个作业定义违反约束时的操作来实现。使用这种策略,我们只需要一个标准表,不需要合并服务。数据按主键排序,没有任何冲突或重复。所有想要使用预处理数据的服务都可以通过传统方法(连接器、REST APIs 等)访问 DBMS。).
结论
本文解释了如何只用四种工具和一些可重用的 java 代码来处理实时和历史数据。
您不需要复杂的管道,就可以拥有一个可扩展的安全解决方案来清理和处理您的原始数据,并将其用于您的分析。
简而言之,将 Kafka 主题用于实时事件数据,将您选择的持久性数据存储用于历史数据,将 Apache Flink 用于处理,并将输出数据存储在某个地方,直到您对其进行分析。该体系结构将帮助您更快地从数据中获得价值,并有效地实施数据清理和准备。
声明:我在惠普公司和【Bernd Bachmann 博士的支持下完成了我的学士论文。
结合 MS Excel 和 Python 的优点
您还不需要(也不应该)完全逃离 Excel
尼克·里克特在 Unsplash 上的照片
你听说过 Python 是新的 Excel 吗?老实说,我已经读过好几遍了。
那么,为什么我看到很多人还在用 Excel 呢?
首先,这两个工具的目的不同,其次,Excel 本身就很强大(如果不是这样,它不会流行这么多年)。
然而,编程语言每年都变得越来越流行,有些人,比如你和我,对验证已知的活动如何以不同的方式处理感兴趣,当然,也很容易。
这是这篇文章的一个关键方面。有一种 MS Office 原生编程语言叫做 VBA (Visual Basic for Applications)。尽管你可能不知道,但你可能已经用过了。为什么使用所谓的宏。
长话短说,VBA 是一种由微软开发的编程语言,它是如何配置宏,一堆定义好的命令。这是故事变得有趣的时刻。Python 最著名的用例之一是自动化多种类型的任务,包括但不限于 Excel 用例。然而,这类问题不是已经被 VBA 解决了吗?请记住,我们在这里是为了做得更好,做得与众不同。此外,很多宏都是由不知道如何改变或适应它们的人使用的。他们只是在那里呆了几年…
宏已经被使用的事实对你来说可能是一个很大的障碍,主要原因是的便利性。为什么?我注意到的原因是:
- 人们习惯于点击宏按钮,这对他们来说已经足够了。他们只是希望工作完成(而且这是公平的,有道理的);
- 有些人就是不愿意学习一门(新的)编程语言。
如上所述,举例来说,很难将您设法开发的 Python 脚本的唯一用途分散到整个组织中。你需要让人们能够使用 Excel 和宏,就这样。这样,他们感觉很舒服,你可能会以某种方式继续练习。
为什么要这么做?
尤其是如果你刚刚开始用 Python 运行一些程序,很可能你正在寻找真正的使用问题来解决,有时,这可能不太容易预先找到。
最重要的是尽可能多的坚持练习。今天你们要学习这个例子,我将要展示给你们,但是你们不应该就此打住。
如前所述,Python 是过去几年中发展最快的编程语言之一,这并非毫无意义。它的易用性和大量的库吸引了全球数百万程序员的注意,这是它如此受欢迎的关键。
怎么做?
那么,还记得那位同事抱怨他们需要每天准备并发送给经理的无聊报告吗?我可以肯定地告诉你,使用 Python 可以帮助他们实现这一点,如果你的同事想了解 Python,他们不需要了解任何东西,相信我。
对于解决这个问题可能存在的宏呢?嗯,如前所述,继续允许人们使用宏是很重要的。然而,这不会是他们所习惯的宏,他们只是不知道他们正在使用 Python 。
我们将使用以下内容:
- VBA 和壳牌
- Python 文件
- 表单控件按钮
我们去看看。
1.VBA 和壳牌
别生我的气,但我会让你用一点 VBA。这只是一种设置让我们能够提前使用 Python 所需的变通方法的方式。
打开您将在本练习中使用的 excel 文件。我将使用以下代码:
C:\Users\Desktop\python test\main_file.xlsm
一旦你打开它,键入 F11,然后 VBA 图形用户界面将打开。它应该类似于下图:
如果没有可用的模块,只需点击顶部菜单中的“插入”,然后点击“模块”。好了,让我们来看看代码本身:
很简单。我们来分析一下以上最重要的几个方面。
需要使用命令“Dim”来声明变量。所以我们宣布:
- Python 解释器路径(“python_exe”)
- Python 脚本路径(“python_py”)。 Chr(34)可能需要,如果你的路径包含空格,像我一样。
- 当前目录路径(“目录路径”)
声明这些变量后,需要使用一个外壳函数。简单地说,适用于我们场景的这个 Shell 函数的基本语法是:
program_to_excute file_to_execute command_line_argument
它非常类似于在 Linux 发行版中使用的 Windows Powershell 和 Bash 中用于 shell 脚本的语法(或任何其他 Shell)。
看看下面的故事,我探索了 Linux 中基本 Shell 脚本的一些功能。
从这个意义上说,我们已经设置了 Python 解释器来执行 Python 文件,并且我们正在设置一个将在 Python 文件中使用的参数。向前移动…
2.Python 文件
最后,万能的 Python 文件。
让我们强调一下你为什么真的喜欢使用 Python 的更详细的原因。Python 在过去几年变得如此流行肯定有几个原因。当然,其中之一是它的多功能性。尽管对于某些领域来说,这最终会成为一个缺点(因为它会使脚本变慢)。由于我们不是在谈论实时用例,它真的不会对我们产生负面影响。
其多功能性主要是由于三个原因:
- 解释语言。可以交互地运行脚本的每一行(它不是一种编译语言)。这甚至导致实时敏感性案例使用 Python 来构建他们的应用程序原型,因为这比一些常见的替代方法更简单。
- 动态类型语言。与 VBA 和其他语言不同,你不需要显式声明你将在程序中使用的变量类型。内存是在给每个变量赋值时分配的。
- 大型社区。有大量的图书馆可供使用。很有可能你想要达到的目标已经被别人完成了。在真正尝试之前,花时间去寻找它。
好了,评论完了,让我们看看剧本。它分为两部分:
- Windows API
- 数据操作
下面,让我带你看一下每一个。
1.Windows API
这里提到的 API 可以通过包 pywin32 获得。它允许我们从另一个应用程序控制 Windows 应用程序。在这种情况下,来自 Python 脚本。
请记住,这个图书馆里的物品很像 VBA 本身。
让我们看看 Python 脚本的第一部分:
向前发展…
2.数据操作
当然,从这里开始,这真的取决于你的情况。我们将探索一些使用 Python 可以轻松实现的常见需求。
我会考虑一个来自 Kaggle 的数据库,葡萄酒评论。更具体地说,该文件命名为“winemag-data-130k-v2.json”。
假设您同事的日常活动是共享类似数据透视表的报表,该报表包含以下行层次结构:
variety; region_1; region_2; province; taster_name
随后是每种情况的“点数”。
您可能会注意到这个数据库中有一些空值。此外,您不确定他们需要在报告中使用的字段(或列)是否会受到任何空案例的影响。从这个意义上说,根据每一列的数据类型填充空值是明智的。
这就是即使在 Excel 中使用 Python 而不是 VBA 的主要优势之一。你能想象在不借助熊猫的情况下如何做到以上几点吗?
让我们来看看实现这一点的代码。
通过执行上述操作,您的同事可以确保所有被标识为包含空值的列都填充了正确的值。
现在,是时候生成所需的数据透视表了,因为这是该领域的每个人用来管理、探索以及采取适当行动的方式。
您是否注意到“主”Excel 文件正在更新,现在它显示了数据透视表?
文章结果的屏幕截图(数据继续显示在右侧和底部)
你应该得到了类似上面的东西。
结论
您设法处理了与一个已知用例相关的多个文件(json 和 Excel 文件),您可以在日常工作中使用 Python 脚本轻松处理这些文件。
案例结构
通过利用 Python 的多功能性,您使用一个非常强大的名为 pandas 的库来操作数据源中包含的数据。除此之外,请记住,还有许多其他流行的库可以用于 web 应用程序、机器学习和可视化用例。
最重要的是:你要让用户保持他们通常的工作方式。希望你(不小心)成功唤醒用户开始学习 Python。
如何在熊猫中组合两个字符串列
了解如何在 pandas 数据框架中更有效地将两个字符串列连接成一个新列
帕斯卡·米勒在 Unsplash 上拍摄的照片
介绍
通过连接其他列来创建新列是一项相当常见的任务。在今天的简短指南中,我们将展示如何将 string DataFrame 列的内容连接成一个新列。我们将探讨几个不同的选项,您应该始终根据您正在处理的数据集大小来考虑这些选项。
这些方法中的一些在应用于小数据集时往往更有效,而其他方法在应用于大数据集时可能执行得更快。
此外,我们还将探索如何将字符串与非字符串(例如整数)列连接起来。
首先,让我们创建一个示例数据框架,我们将在本文中引用它来演示一些概念。
import pandas as pddf = pd.DataFrame(
[
(1, '2017', 10, 'Q1'),
(2, '2017', 20, 'Q2'),
(3, '2016', 35, 'Q4'),
(4, '2019', 25, 'Q2'),
(5, '2020', 44, 'Q3'),
(6, '2021', 51, 'Q3'),
],
columns=['colA', 'colB', 'colC', 'colD']
)print(df)
*colA colB colC colD
0 1 2017 10 Q1
1 2 2017 20 Q2
2 3 2016 35 Q4
3 4 2019 25 Q2
4 5 2020 44 Q3
5 6 2021 51 Q3*
在小型数据集中串联字符串列
对于相对较小的数据集(最多 100–150 行),您可以使用[pandas.Series.str.cat()](https://pandas.pydata.org/docs/reference/api/pandas.Series.str.cat.html)
方法,该方法用于使用指定的分隔符(默认情况下分隔符设置为''
)连接序列中的字符串。
例如,如果我们想将列colB
和colD
连接起来,然后将输出存储到一个名为colE
的新列中,下面的语句就可以做到:
**df['colE'] = df.colB.str.cat(df.colD)** print(df)
*colA colB colC colD* ***colE*** *0 1 2017 10 Q1* ***2017Q1*** *1 2 2017 20 Q2* ***2017Q2*** *2 3 2016 35 Q4* ***2016Q4*** *3 4 2019 25 Q2* ***2019Q2*** *4 5 2020 44 Q3* ***2020Q3*** *5 6 2021 51 Q3* ***2021Q3***
现在,如果我们想要指定一个将被放置在连接的列之间的分隔符,那么我们只需要传递sep
参数:
**df['colE'] = df.colB.str.cat(df.colD, sep='-')**print(df)
*colA colB colC colD* ***colE*** *0 1 2017 10 Q1* ***2017-Q1*** *1 2 2017 20 Q2* ***2017-Q2*** *2 3 2016 35 Q4* ***2016-Q4*** *3 4 2019 25 Q2* ***2019-Q2*** *4 5 2020 44 Q3* ***2020-Q3*** *5 6 2021 51 Q3* ***2021-Q3***
或者,你也可以使用列表理解,这种理解稍微有点冗长,但速度稍快:
**df['colE'] =** **[''.join(i) for i in zip(df['colB'], df['colD'])]**print(df)
*colA colB colC colD* ***colE*** *0 1 2017 10 Q1* ***2017Q1*** *1 2 2017 20 Q2* ***2017Q2*** *2 3 2016 35 Q4* ***2016Q4*** *3 4 2019 25 Q2* ***2019Q2*** *4 5 2020 44 Q3* ***2020Q3*** *5 6 2021 51 Q3* ***2021Q3***
在较大的数据集中串联字符串列
现在,如果您正在处理大型数据集,连接两列的更有效方法是使用+
操作符。
**df['colE'] = df['colB'] + df['colD']**print(df)
*colA colB colC colD* ***colE*** *0 1 2017 10 Q1* ***2017Q1*** *1 2 2017 20 Q2* ***2017Q2*** *2 3 2016 35 Q4* ***2016Q4*** *3 4 2019 25 Q2* ***2019Q2*** *4 5 2020 44 Q3* ***2020Q3*** *5 6 2021 51 Q3* ***2021Q3***
如果您想要包含分隔符,只需将其作为字符串放在两列之间即可:
**df['colE'] = df['colB'] + '-' + df['colD']**
连接字符串和非字符串列
现在让我们假设您尝试连接的列之一不是字符串格式:
import pandas as pddf = pd.DataFrame(
[
(1, **2017**, 10, **'Q1'**),
(2, **2017**, 20, **'Q2'**),
(3, **2016**, 35, **'Q4'**),
(4, **2019**, 25, **'Q2'**),
(5, **2020**, 44, **'Q3'**),
(6, **2021**, 51, **'Q3'**),
],
columns=['colA', 'colB', 'colC', 'colD']
)print(df.dtypes)*colA int64
colB int64
colC int64
colD object
dtype: object*
在这种情况下,您可以简单地使用[pandas.DataFrame.astype()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.astype.html)
或map()
方法来转换列。
# Option 1
**df['colE'] = df.colB.astype(str).str.cat(df.colD)**# Option 2
**df['colE'] = df['colB'].astype(str) + '-' + df['colD']**# Option 3
**df['colE'] =** **[
''.join(i) for i in zip(df['colB'].map(str), df['colD'])
]**
最后的想法
在今天的简短指南中,我们讨论了在 pandas 数据帧中连接字符串列。根据您正在使用的数据集的大小,您可能需要选择执行效率更高的最合适的方法。
此外,我们还展示了如何利用 pandas 中的astype()
方法连接字符串和非字符串列。
成为会员 阅读媒体上的每一个故事。你的会员费直接支持我和你看的其他作家。你也可以在媒体上看到所有的故事。
https://gmyrianthous.medium.com/membership
你可能也会喜欢
[## 如何将 Python 包上传到 PyPI
towardsdatascience.com](/how-to-upload-your-python-package-to-pypi-de1b363a1b3)
把你的机器学习模型和投票结合起来
利用被低估的集合方法获得更好预测性能的指南
照片由来自 Pexels 的 Tara Winstead 拍摄
当你冒险踏上机器学习之旅时,你无疑会遇到各种各样的机器学习算法。
从像 K-最近邻这样的懒惰学习分类器到像决策树这样的急切学习分类器,在构建模型时有许多不同的算法可供选择。
你有没有想过让这些模型协同工作会是什么样子?幸运的是,这可以通过一种叫做投票的技术轻松实现。
投票是一种集合方法,它将多个模型的性能结合起来进行预测。
你可能会想:首先把模型的预测结合起来有什么意义呢?当您可以单独评估分类器并选择最佳分类器时,为什么要将所有分类器合并为一个呢?
投票的好处
合并投票有很多好处。
首先,由于投票依赖于许多模型的性能,它们不会被来自一个模型的大误差或错误分类所阻碍。一款车型的不佳表现可以被其他车型的强劲表现所抵消。
为了更好地理解这个概念,我们用投资来打个比方。
当你投资时,人们经常建议你将财富分配到各种股票上。如果你把所有的钱都放在一只股票上,你的整个投资组合都依赖于这只股票的表现,这让你面临很高的风险。另一方面,如果你把钱投资于各种股票,风险就会降低;一只表现不佳的股票不会阻碍你的成功。
投票以类似的方式进行。通过组合模型来进行预测,您可以利用其他可以做出正确预测的模型来降低一个模型做出不准确预测的风险。这种方法使得估计器更加稳健,并且易于过拟合。
在分类问题中,投票有两种:硬投票和软投票。
硬投票需要挑选具有最高票数的预测,而软投票需要组合每个模型中每个预测的概率,并挑选具有最高总概率的预测。
回归问题中的投票有些不同。通过投票构建的回归模型不是查找出现频率最高的预测,而是获取每个模型的预测,并计算它们的平均值以得出最终预测。
在分类或回归问题中,投票是提高预测性能的一种手段。
投票的缺点
当你了解到组合模型的好处时,你可能会在你未来的所有机器学习项目中使用投票。
毕竟,当您可以将它们全部集成到一个评估器中并创建“完美的模型”时,为什么要经历考虑每个模型的优缺点的麻烦呢?
不幸的是,这种思路是有缺陷的。
要明白,用投票建立的模型不应该被视为机器学习中一刀切的方法。毕竟,投票集成方法也有其局限性。
首先,在某些情况下,单个模型可以胜过一组模型。例如,在回归问题中,如果预测特征和目标变量具有很强的线性关系,单个线性回归模型无疑可以表现得很好。但是,用其他回归模型做出的投票估计会使线性回归模型的准确预测无效。
其次,由于投票需要使用多种模型,因此它们的计算量自然更大。因此,创建、培训和部署这样的模型将更加昂贵。
最后,只有当机器学习分类器在相似的水平上执行时,投票才是有益的。从具有相反效率水平的模型构建的投票估计器可能不稳定地运行。
Python 中的应用
Python 中的 sklearn 包使得实现投票集成方法变得非常容易。它提供了投票分类器和投票回归器,这两个估计器分别用于构建分类模型和回归模型。
您可以使用以下代码导入它们:
由作者创建
让我们利用 sklearn 库来看看投票集合方法的效果。
个案研究
有了医院患者的数据集(此处可访问),让我们创建单独的机器学习分类器和投票分类器,以确定哪种方法最好地预测心脏病。
以下是数据集要素的预览:
由作者创建
代码输出(由作者创建)
本案例研究的目标变量是“心脏病”。
让我们在建模之前准备数据集。预处理阶段需要:
- 删除丢失的值(如果有)
- 编码分类特征
- 将数据分成训练集和测试集
- 标准化输入要素
接下来,我们用训练集训练决策树模型、逻辑回归模型和朴素贝叶斯模型,然后用测试集评估它们。这些模型的性能将根据它们的 f-1 分数来衡量。
代码输出(由作者创建)
如输出所示,支持向量机是表现最好的模型,f-1 得分为 0.8897。
请注意 3 个分类器的 f-1 分数是多么相似。这是投票估计器将适用于预测心脏病的指标。
让我们创建一个分类器,将决策树分类器、逻辑回归模型以及朴素贝叶斯模型合并为一个分类器。通过给分类器中的“投票”参数赋值,可以在硬投票和软投票之间进行选择。为了便于演示,我们将使用这两种投票技术。
代码输出(由作者创建)
由硬投票和软投票构成的投票分类器的性能都优于支持向量机。
结论
照片由来自 Pexels 的 Prateek Katyal 拍摄
现在,你了解了投票的来龙去脉,以及它在机器学习中的应用。
结合机器学习模型可以显著提高预测建模的质量。
然而,即使这种集合方法在构建模型时可以作为一种很好的选择,您也不应该将其视为一种可行的方法,因为它的成本更高,而且并不总是胜过单个模型。
我祝你在机器学习的努力中好运!
结合物理和深度学习
什么是数字双胞胎,它们是如何工作的?
随着过去 10 年计算能力的提高,我们看到模拟的数量急剧增加。数字双胞胎就是这样一个例子。它们是可以在各种场景中模拟的物理对象或过程的虚拟复制品。
约尔根·哈兰在 Unsplash 上的照片
数字双胞胎面临的一个问题是,他们如何将潜在的嘈杂的经验数据与物理结合起来。
2021 年,谢菲尔德大学的研究人员开发了一个非常简单的数字双胞胎框架,称为 PhysiNet 来解决这个问题。PhysiNet 将深度学习与物理模型相结合,以开发对设备性能的稳健预测。
虽然数字双胞胎确实需要大量的开发资源,但在物理测试极其昂贵或危险的情况下,它们可以成为有效的替代方案。
事不宜迟,让我们开始吧…
技术 TLDR
数字双胞胎是物理系统的电子副本。他们依赖于黑箱和基于规则(物理、经济等)。)模特。然而,由于这两种方法都有不足之处,我们建议通过对每个模型的预测值进行加权线性组合来将两者结合起来。
当迭代训练黑盒模型时,在每个时期,我们重新调整两个模型预测的权重,以优化准确性。预测值的这种线性组合有效地结合了两种模型并优化了准确性。
但是,到底是怎么回事呢?
让我们提供一些关于数字双胞胎的背景知识,并讨论本文中的方法。
数字双胞胎的背景
如上所述,数字双胞胎是物理事物的数字副本,例如风力涡轮机或供应链。它们通常是基于物理的产品的 3D 模型,但可以简单得多。
2010 年,美国宇航局首次使用它们来帮助开发航天器,但在物理原型难以测试和/或测试成本高昂的应用中,它们越来越受欢迎。它们最符合逻辑的用例是在产品构思和开发期间,但是它们也可以与生产产品一起使用,以获得洞察力和预测失败。
利用数字双胞胎的行业从产品生命周期管理到建筑加热/冷却优化到汽车传感器。
问题是
大多数数字双胞胎严重依赖规则或经验数据。然而,通常最稳健的模型结合了先验规则和经验数据。有多种方法可以做到这一点,但 PhysiNet 提出了可以说是最简单的解决方案。
解决方案
PhysiNet 将神经网络(NN)预测与物理模型预测相结合。神经网络处理经验数据,而物理规则将系统绑定到现实——因为现实世界的数据可能有噪声,物理模型通常非常有用。
让我们参考下面的图 1…
图 PhysiNet 框架的图形表示。图片作者。
首先,我们拟合我们的物理模型(top),它通常是变量的线性组合。因为这些模型很少需要迭代来训练,所以我们只能进行静态预测。
第二,我们拟合一个神经网络(下图)。神经网络利用多个时期的反向传播来训练它们的权重。对于每个时期,除了更新网络中的权重向量,我们还开发了结合物理和 NN 预测的预测(显示在绿色框中)。
由 w 表示的两个权重相加为 1。因此,如果物理权重等于 0,我们只使用 NN 预测,反之亦然。根据物理和经验数据的质量,该框架自动更新我们的预测值以优化准确性。
图 PhysiNet、神经网络和一个基于物理学的模型在不同时期的性能— src 。图片作者。
如上面的图 2 所示,这个极其简单的框架拥有相对于单独的任一模型的性能改进。物理模型往往过于简单,而神经网络需要大量高质量的数据,因此通过结合两种模型,我们可以避免两种缺点。
摘要
数字双胞胎是昂贵的物理测试的有效替代品。对于基于物理的模拟,PhysiNet 结合了物理模型和黑盒机器学习模型的加权预测。这个框架拥有相对于单独的任一模型的准确性改进。
该框架非常简单,并且可以扩展,例如通过使用物理模型预测作为神经网络中的特征。如果你对该话题有资源/看法,请留下评论。非常感谢!
感谢阅读!我会再写 33 篇文章,把学术研究带到 DS 行业。查看我的评论,链接到这篇文章的主要来源和一些有用的资源。
结合 Python 和 R 进行 FIFA 足球世界排名分析
展示 Python 和 R 在数据科学和分析领域的互补优势
杰森·查特斯在 Unsplash 上的照片
Python 和 R 之间的“语言战争”是数据科学中长期争论的话题,至今仍被广泛讨论。
事实上,最好的语言是最适合具体工作的语言。毕竟,Python 和 R 只是数据从业者执行最关键任务的工具——用数据解决业务问题。
在这次 FIFA 足球世界排名分析中,我们探索 Python 和 R 的不同和共同优势,以及它们如何在现代数据科学工具包中互补。
内容
(1)数据无罪释放(Python 中的网页抓取)(2)**数据可视化(条形图竞在 R)**
查看GitHub repo获取实现代码。****
使用 Python 中的 Web 抓取进行数据采集
Python 作为一种通用编程语言,经常用于 web 抓取等通用任务。这种数据搜集工作最流行的工具之一是 Selenium。
Selenium 是一个用于 web 浏览器控制的开源自动化工具,用于自动化重复操作,如按钮点击、表单填写、文本提取和页面滚动。
在国际足联男子排名页面上应用了网页抓取脚本(带有 Chrome 网络驱动)来检索 1992 年至 2021 年间的国家队积分和排名。提取的数据导出为 CSV 文件,用于数据分析。
FIFA 排名数据前五行截图|作者图片
数据可视化与 R 中的条形图竞赛
与 Python 类似,R 是一种开源编程语言,提供了无数的功能。但是,它通常用于统计分析和创建图形。
后者是 R 的一个显著优势,因为它可以生成高质量的可高度定制的图形。在这一部分中,我们将演示如何使用几个 R 包来创建动态可视化。
FIFA 世界排名柱状图竞赛|作者图片
上图是一个条形图比赛动画,它显示了国际足联前十名的排名在过去三十年中是如何演变的。这些国家通过汇总它们的年平均分数来排名。
数据可视化分两步生成。首先,使用流行的 ggplot2 包(加载在 tidyverse 中)创建了一个静态条形图,它允许通过将图形分成不同的组件进行高度定制。
许多软件包现在可用于补充 ggplot2 图。在这种情况下,我们通过使用 ggimage 包添加标记图像来定制绘图。
第二,使用 gganimate 对静态剧情进行动画处理。具体来说, transition_time 函数只需增加一行代码就可以控制条形图逐年变化!
使用 Python 和 R 进行回归分析
Python 和 R 都是非常有效的统计分析工具。为了证明这一点,我们用 Python 和 R 展示回归建模来回答具体的足球问题。
(一)国际足联排名与国家队货币价值之间的关系(Python 中的线性回归)
我们想确定一个国家队的国际足联积分是如何受到该队球员平均货币价值的影响的。
球队阵容的数据(基于最近的锦标赛,如 2020 年欧锦赛、2021 年美洲杯等。)和相应的球员市场价值(以英镑计)从公共足球网站Transfermarkt.co.uk获得(截至 2021 年 8 月 12 日准确)。
我们通过合计每个球员的市场价值来计算每个国家队的货币价值。因为每个队可能有不同的球员数量,所以平均货币价值(即总价值除以球队规模)被用于分析。****
在建模之前,将数据可视化是一个很好的做法。特别是,我们希望确保我们的独立变量(平均货币价值)遵循正态分布,这是一个需要满足线性回归的假设。
使用 seaborn 库,我们可以创建一个直方图(用 KDE )来显示平均货币值的分布。
KDE 直方图|作者图片
该图揭示了一个显著的右偏,因为几个团队的货币价值比其他团队高得多。解决方案是将对数变换应用于平均货币值。这样做后,我们得到一个更接近正态分布的图。****
KDE 直方图(对数变换后)|作者图片
自变量转换成功后,我们可以进行回归分析。最直观的基线模型是线性回归。
众多的 Python 包允许我们执行线性回归,其中最流行的是 scikit-learn 的 linear_model 模块。
在为 LinearRegression() 函数提供因变量和自变量后,我们获得了以下指标:
线性回归指标|作者图片
0.746 的 R(决定系数)分数意味着该模型占国际足联点数可变性的 74.6%。鉴于我们的模型只有一个独立变量,这是一个相当不错的结果!
这意味着国家队的平均货币价值与其国际足联积分有较强的正相关性。
最后,使用 seaborn 创建回归图,以可视化线性回归模型拟合:
Python 中的回归图|作者图片
(ii)国际足联排名与国家联赛货币价值之间的关系(R 中的线性回归)
我们还对 FIFA 积分和国家(T2)一级足球联赛(T3)的货币价值之间的关系感兴趣。联赛货币价值的数据同样来自 Transfermarkt.co.uk 的。**
鉴于不同联赛中参与俱乐部的数量不同,国家联赛的货币价值被标准化为每个俱乐部的英镑价值。
与之前的回归分析类似,国家联盟货币值的分布是右偏的,因此应用了对数变换。****
由于 R 通常用于统计分析,线性建模已经包含在基本包中,不需要导入额外的库。 lm 函数通过简单地指定 Y ~ X 格式的公式,使线性模型符合数据。
结果显示,R 为 0.47,表明国家联赛的货币价值占国家国际足联积分可变性的不到一半。这种关系可以在下面的散点图中看到:
作者 R |图像中的回归图
我们观察到,国家队货币价值的数据点比 Python 散点图更远离线性回归线。
总的来说,我们可以从这两项分析中解读出,国家队的货币价值比国家联赛的价值更能预测一个国家的国际足联积分。
摘要
Python 和 R 都是优秀的数据分析编程语言,在数据科学工具包中各有其位置。如果您专注于统计建模或从数据生成图形可视化,R 是一个更直接的选择。
另一方面,如果您的项目需要通用编程任务或与其他应用程序集成,Python 是更合适的选择。
总之,争论 Python 和 R 哪个更好是徒劳的。理想的工具取决于用例、你打算回答的问题以及你的团队和行业的文化。
*****https://www.linkedin.com/in/nien-xiang-tou-phd-a15594184/
在你走之前
欢迎您加入我的数据科学学习之旅!点击此媒体页面,查看我的 GitHub ,了解更多精彩的数据科学内容。*
结合 R {tidyverse,fleet,DT,flexdashboard}和 Python {pandas,GeoPy}创建无服务器心理治疗仪表板
照片由维特·加布雷拍摄
介绍
在捷克共和国,只有一小部分精神治疗护理(T3)由健康保险公司(T6)承保(T5)。因此,当最大的此类公司之一 VZP 向其客户提供 7 000 CZK(约合 280 欧元)的心理治疗津贴时,这是一个受欢迎的举措。
然而,给自己找一个心理治疗师的方法并不是最方便的,因为你必须滚动浏览一个. pdf 文件。幸运的是,捷克心理治疗协会https://czap.cz/eng的董事会成员 Dominika echová,通过谈判从 VZP 获得了更多信息,比如哪些心理治疗师可以接受新客户。
我的任务是将这些信息整合成一种更加用户友好的方式,让你自己找到一个治疗师,从而使服务更加容易获得。重点是交付的速度和部署的简易性,所以我决定用flex dashboard来完成 R ,这个包允许创建交互式和无服务器仪表盘。
我有以前的项目中的大部分构建模块——R 实现 传单 用于地图,以及 数据表 用于表格。 Tidyverse 用于装载和角力数据。
然而,输入表不包含纬度和经度,这是在地图上显示治疗师位置所需的两个元素。之前我已经用 ggmap 调整过数据。然而,Google API 需求的变化使得这变得有些不方便。
所以,我决定寻找一个替代方案。然后偶然看到了 Abdishakur 的文章Geocode with Python,很棒的介绍 Python 的包 GeoPy 。
现在,虽然 R 是我的特殊数据朋友,但我也喜欢在我的工作流程中有利的地方集成其他语言和工具,如 Python、熊猫、T21。
在这篇文章中,我想回顾一下我是如何创造理想结果的。
你可以在这里找到最终的仪表盘https://www.data-must-flow.com/posts/psychotherapy_vzp/和带有交互元素的原创文章*这里 。***
r 包
让我们从加载所需的包开始:
****# Load required packages*
library(flexdashboard) *# dashboard wrapping*
library(tidyverse) *# data wrangling*
library(crosstalk) *# interactivity*
library(broom) *# output of built-in functions cleanup*
library(DT) *# Table formatting*
library(htmltools) *# widgets*
library(reshape2) *# data taransformations*
library(leaflet) *# interactive maps*
library(leaflet.extras) *# interactive features****
输入数据
您可以在 GitHub 上找到输入数据集。
****# Initial dataset*
vzp_data = read.csv("vzp_data_geo.csv") %>%
select(name, surname, alias, website, address,
city, region, psc, phone, email, Kapacita, remote_therapy)***
计算机编程语言
激活
首先你需要打开 r 中的 Python 接口,我用的是 reticulate 。
****# Python interoperability in R*
library(reticulate)*# Specifying which version of python to use.*
use_python("/home/vg/anaconda3/bin/python3.7",
required=T) *# Locate and run Python****
包和数据争论
即使有可能一次运行下面所有的代码块,让我们遵循做一件事的原则,根据它们的功能将它们分开。
Python 包优先:
***from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter
import pandas as pd***
激活地理编码器:
***locator = Nominatim(user_agent="myGeocoder")***
将部分地址链接到一个变量-将用于地理编码:
***df = r['vzp_data']df['state'] = "CZ"df["ADDRESS"] = df["address"] + "," + df["city"] + "," + df["state"]df["Adresa"] = df["address"] + ", " + df["city"]***
使用 GeoPy 进行地理编码
为了减少Too Many Requests
误差,使用RateLimiter
。正如 GeoPy 的文档所说,在地理编码调用之间添加一个延迟,以减少地理编码服务的负载。**
****# 1 - conveneint function to delay between geocoding calls*
geocode = RateLimiter(locator.geocode, min_delay_seconds=1)*# 2- create location column*
df['location'] = df['ADDRESS'].apply(geocode)*# 3 - create longitude, laatitude and altitude from location column (returns tuple)*
df['point'] = df['location'].apply(**lambda** loc: tuple(loc.point) **if** loc **else** None)*# 4 - split point column into latitude, longitude and altitude columns*
df[['latitude', 'longitude', 'altitude']] = pd.DataFrame(df['point'].tolist(), index=df.index)***
导出地理编码数据
现在,您可能会问——为什么我要导出这个表?我不打算把数据作为 Python/R 对象进一步处理吗?
不幸的是,当包含 Python 代码时,flexdashboard 还不能被编织。因此,在使用仪表板时,我必须创建两个独立的工作流—一个用于数据地理编码,另一个用于编译仪表板。然而,我想使仪表板编码更具可重复性,同时将所有重要的组件保持在一个工作流中。
幸运的是,其他 R Markdown 输出如 R notebook 很乐意包装 Python 代码。这就是您在代码中看到这一步的原因。当然,这不是最有效的工作流程,但是你知道他们说什么——完成(和工作)比完美更好。
当然,如果目标是包含一些 Python 块的 R Markdown 文档,您可以简单地在 R 块中添加vzp_data = py[df]
,将 pandas 数据帧转换成 R 数据帧,并顺利进行下一部分。
****# Convert pandas DataFrame into R Data Frame (tibble)*
vzp_data_geocoded = py['df']vzp_data_geo <- vzp_data_geocoded %>%
select(name, surname, alias, website, address,
city, region, psc, phone, email, `Kapacita`, remote_therapy,
state, Adresa, latitude, longitude)vzp_data_geo <- apply(vzp_data_geo,2,as.character)
write.csv(vzp_data_geo, file = "vzp_data_geo.csv")***
稀有
tidyverse 中的数据争论
仅选择将在输出中使用的列并格式化它们:
****# Data import and wrangling*
vzp_data = read.csv("vzp_data_geo.csv") %>%
select(name,
surname,
alias,
website,
address,
city,
phone,
email,
Kapacita,
remote_therapy,
latitude,
longitude) %>%
mutate_all(list(~str_trim(.,side = "both"))) %>%
mutate(`Jméno a příjmení` = paste(name,surname),
latitude = as.numeric(latitude),
longitude = as.numeric(longitude)) %>%
rename("Email" = email,
"Telefon" = phone,
"Web" = website,
"Online nebo telefonické konzultace?" = remote_therapy,
"Kapacita?" = Kapacita,
"Město" = city,
"Ulice" = address) %>%
mutate(`Kapacita?` = case_when(`Kapacita?` == "volno" ~ "Volno",
`Kapacita?` == "naplněno" ~ "Naplněno",
`Kapacita?` == "Naplněno" ~ "Naplněno",
TRUE ~ `Kapacita?`),
`Online nebo telefonické konzultace?` = case_when(`Online nebo telefonické konzultace?` == "Ano" ~ "Ano",
`Online nebo telefonické konzultace?` == "Ano/ možnost konzultací v anglickém jazyce" ~ "Ano",
`Online nebo telefonické konzultace?` == "Ne" ~ "Ne",
`Online nebo telefonické konzultace?` == "ne" ~ "Ne",
TRUE ~ `Online nebo telefonické konzultace?`)
)*# Replace "NaN" with "Neuvedeno"*
vzp_data[vzp_data=="NaN"] <- "Neuvedeno"***
输出
可用心理治疗师列表
下表是使用DataTable
包完成的最终查找表的快照。这个包意味着许多交互元素供您使用。您可以添加跨列搜索和过滤、排序、分页等等。此外,它可以很容易地与使用crosstalk
的过滤器连接。
由于输出是捷克语,我建议您的浏览器的Translate to English
功能获得更多价值。
***vzp_data_table <- vzp_data %>%
select(`Kapacita?`, `Online nebo telefonické konzultace?`,
Město,
Ulice,
`Jméno a příjmení`,
Email, Telefon, Web, Ulice,
`Online nebo telefonické konzultace?`) test_shared <- crosstalk::SharedData$new(vzp_data_table)DT::datatable(test_shared,
extensions = c(
"Responsive"
),
rownames = FALSE, *# remove rownames*
style = "bootstrap",
class = 'cell-border display',
options = list(
pageLength = 10,
dom = 't',
deferRender = TRUE,
scroller = TRUE,
columnDefs = list(list(className = 'dt-center', targets = "_all"))
)
) %>% formatStyle(
"Kapacita?",
target = 'row',
backgroundColor = styleEqual(c("Naplněno", "Volno"), c('#ffcccb', '#d2e9af')))***
心理治疗师分布图
由于通过地图搜索可能更方便,我决定用传单添加一个。类似于数据表,传单允许多个交互式元素。包括基于字符串或不同地图图层的搜索。
同样,由于输出是捷克语,我建议您的浏览器的Translate to English
功能获得更多价值。
****# prepare a palette - manual colors according to branch column*
pal <- leaflet::colorFactor(palette = c("Naplněno" = "#8b0000",
"Neuvedeno" = "#A9A9A9",
"Volno" = "#006400"
),
domain = vzp_data$`Kapacita?`)points_fin <- SharedData$new(vzp_data)map1 <- leaflet(data = points_fin, width = '100%', height = 800) %>%
addProviderTiles("CartoDB.Positron", group = 'Základní') %>%
addProviderTiles("Esri.WorldImagery", group = 'Letecká') %>%
addProviderTiles("OpenStreetMap.Mapnik", group = 'Uliční') %>%
addProviderTiles("OpenTopoMap", group = 'Zeměpisná') %>%
addScaleBar('bottomright') %>%
setView(15.4129318, 49.7559455, zoom = 8.2) %>%
addCircleMarkers(
group = 'Obor',
stroke = FALSE,
opacity = 0.9,
fillOpacity = 0.9,
fillColor = ~sapply(`Kapacita?`, **switch**, USE.NAMES = FALSE,
"Volno" = "#006400",
"Naplněno" = "#8b0000",
"Neuvedeno" = "#A9A9A9"
),
popup = ~paste0('<h2>Detail</h2> <br>',
'<b>Město</b>: ', Město, '<br>',
'<b>Ulice</b>: ', Ulice, '<br>',
'<b>Jméno a příjmení</b>: ', `Jméno a příjmení`, '<br>',
'<b>Online nebo telefonické konzultace</b>: ', `Online nebo telefonické konzultace?`, '<br>',
'<b>Telefon</b>: ',`Telefon`, "<br>",
'<b>Email</b>: ', Email, '<br>',
'<b>Web</b>: ', Web, '<br>',
'<b>Kapacita</b>: ', `Kapacita?`, '<br>')
,
clusterOptions = markerClusterOptions(showCoverageOnHover = FALSE,
iconCreateFunction=JS("function (cluster) {
var childCount = cluster.getChildCount();
var c = ' marker-cluster-';
if (childCount < 100) {
c += 'small';
} else if (childCount < 1000) {
c += 'medium';
} else {
c += 'large';
}
return new L.DivIcon({ html: '<div><span>' + childCount + '</span></div>', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) }); }"))) %>%
addLegend(position = "topright",
values = ~`Kapacita?`,
opacity = .7,
pal = pal,
title = "Kapacita?") %>%
leaflet.extras::addResetMapButton() %>%
addLayersControl(
baseGroups = c("Základní", "Letecká", "Uliční", "Zeměpisná"),
options = layersControlOptions(collapsed = TRUE)
) %>%
addSearchOSM()map1***
结束语
我相信当以上述方式集成 R 和 Python 时,有些人会皱起眉头。"为什么不选择一种工具并使用它呢?“你可能会问自己。在我的例子中,我需要在模板中添加一部分。虽然它的部分是用 R 编写的,但我不想把自己局限在一种工具上。
同时,通过查看当前的限制,我们可以促进未来集成的便利性。在这里,我必须承认 RStudio ,在我看来是处理数据的最好工具之一,已经在集成 Python 方面迈出了重要的几步。然而,在特定的用例中,这仍然是一段有点颠簸的旅程。
最终,我想试验和测试极限。我相信 Python 和 R 在处理数据时各有利弊,所以为什么不探索一下如果将它们结合在一起可以达到什么目的呢?
结合 Spotify 和 R——一个交互式 Rshiny 应用程序+ Spotify 仪表盘教程
了解如何制作一个直观的 Spotify + Rshiny 应用程序,告诉用户他们的音乐个性、最受欢迎的艺术家和专辑比较等信息
塞尔吉·卡夫雷拉在 Unsplash 上的照片
(滚动到底部,以 GIF 格式查看完整应用的现场演示)。本文详细介绍了如何使用 Rshiny 制作一个集成的 Spotify 应用程序。这个应用程序使用了Spotify API,并揭示了如何以更简单的方式使用 Rshiny 作为类似程序(如 Python 的 Streamlit 或 Javascript)的替代方案。Rshiny 是一个 R 包,它允许用户轻松地创建 web 应用程序,因为它使用 R,所以允许比 Javascript 更直观的数据可视化和操作。要创建一个 Rshiny 应用程序,最好至少有一个 ui。r(用户界面)脚本,一个服务器。r 脚本和运行。r 脚本。用户界面。r 文件的工作方式和 HTML 文件一样,只是外观不同,功能不同。服务器。r 文件的行为类似于。js 文件,这个文件也是定义所有函数的最佳位置。这个文件中的函数和对象构成了 ui。r 文件“工作”,并且最好在开始之前在脑海中想象一下整个项目的视觉效果。我绘制了每个标签(又名页面)应该包含的内容,从登录页面开始,然后是人气、人气和用户统计标签。这直接转化为用户界面。r 脚本。然后是在服务器中创建的函数和对象。r 脚本可以继续工作,因为它们现在可以被构建出来。最后,跑步。r 文件,通常只是一个具有 runApp 功能的简单文件。该项目现在可以通过 Heroku 或 shiny apps 来完成和部署。
我开始这个项目是因为我希望用户可以轻松地输入他们在 Spotify 的用户名和密码,然后他们的信息就会被加载,用户可以通过不同的表格和可视化方式看到他们音乐品味的酷的方面。
可悲的是,用于 R 的 Spotify 软件包 spotifyr 不支持用户登录,用户需要实际的 Spotify API 才能看到他们的数据(也就是客户端 id 和客户端机密)。该应用程序仍然工作,它只是需要一个用户有 API,让他们看到自己的音乐品味。不管怎样,这款应用制作起来还是很有趣的,并且让可视化对用户来说更具互动性。
我将首先检查应用程序的布局,所以我们开始吧!
我希望该应用程序有 4 个不同的标签是:
- 简介选项卡—允许用户输入他们的客户端 id 和客户端密码,API 它还提供了如何获取 API 密钥来使用该工具的说明
作者图片
- 流行度选项卡—显示用户收听的艺术家的不同流行度指标。它有一个可视化图表,从 Spotify 的内部流行度指标 1-100 显示用户最常听的艺术家(我设置为 25 位艺术家)的流行度。它还在一张饼状图上按关注者对这些艺术家进行了比较。
作者图片
- 情感标签——可能是最复杂的标签,它允许用户滚动浏览他们最受欢迎的艺术家(前 25 名)的专辑,并查看每张专辑的情感评分。情绪是音乐的不同属性,它们包括:“可跳舞性”、“能量”、“响度”、“语速”、“声音”、“活跃性”、“积极性”和“节奏”。该标签还显示了最具有某种音乐属性的艺术家的歌曲。举个例子,艺术家劳伦·希尔女士最适合跳舞的歌曲是《最后一小时》,其可舞性得分为 0.847。我在这里获得了这张脊线图的灵感。
作者图片
- 用户统计——全面查看用户的 10 位最受欢迎的艺术家,并绘制艺术家的集体情感图表。然后它判断用户的音乐个性。在所示的例子中,用户似乎喜欢悲伤的音乐,因为音乐的能量和积极性平均较低。注意,对于非英语音乐,这不是最准确的。这也表明用户可能喜欢本质上更罗嗦的说唱音乐。我在这里得到了这个视觉化的灵感。
作者图片
作者图片
这些是我在做这个项目之前考虑的事情,在写代码之前我已经把大部分都计划好了。说到代码,让我们开始吧!
我将从 ui 开始。r 文件,所有的“前端开发”都在这里进行。代码将会显示,并解释之后会发生什么。我将包括图片,因为媒体不能识别 Rshiny 代码。
让我们一步一步地看看第一个选项卡:
- ShinyUI 是包含所有用户界面代码的地方。我们需要添加 fluidPage,以允许自动调整页面尺寸。最后,我们需要一个 navbarPage 来封装所有的 tabPanels(类似于独特的 HTML 页面)。
- Intro tabPanel 包括一个侧边栏面板,允许用户输入他们的 Spotify 客户端 id 和客户端密码。spotifyr 包目前不允许直接输入用户名和密码,因此用户必须使用 Spotify API。textInput、actionButton 和 textOutput 中的第一个字符串参数都是将在服务器中使用的变量。r 文件。
- 主面板包括注册 Spotify API 的基本说明。很明显,h#只是 Rshiny 中不同的标题大小。
- 如果您遇到问题,可能需要在启动应用程序之前声明客户端 id 和客户端密码。
现在是第二个标签:
- 这个 Popularity tabPanel 只包含一个 mainPanel,它包含两个绘图,名为 popularity_plot_output 和 follower_plot_output,我们将在 server.R 中创建它们。
- 还有一个名为 favorite_artists_table 的数据表也将在 server.R 中创建。
让我们看第三页:
- 该情感选项卡面板有两个 fluidRows,包含艺术家姓名和情感类型的下拉列表(分别为 artist_name 和 perspective _ type)。
- 在两次下拉之后,存在两个文本输出。一个在情节情绪 _ 情节 _ 输出之前,另一个在数字输入之前。第一个文本“情绪 _ 文本”只是一个情节标题,而第二个“情绪 _ 情绪”是下面数字输入框的输出。其工作方式是,无论用户输入什么数字,都将是歌曲的排名,该排名基于在情绪类型中选择的情绪。
- tags$style 的工作方式类似于 CSS 在 web 开发中的工作方式,并且格式化给定的对象。此外,br()只是增加了一个额外的空间。
最后,标签四:
- 这个最后的 tabPanel 有两个 textOutputs 和两个 plotOutputs。我们首先创建能量与积极性输出图,它将显示用户从他们所听的音乐中获得的整体积极性和能量。然后,它将显示一个名为 energy_vs_positivity 的文本输出,该文本输出根据用户的顶级艺术家来表达用户的音乐个性。
这就完成了 ui。现在我们来看看 server.R。
现在我们处于 Rshiny 项目的“后端开发”部分。我们需要在 ui 中创建我们定义的变量和对象。我们将使用许多 spotifyr 函数从 Spotify API 中提取数据。
这一部分可以分为两个部分。首先,我将讨论一些显示一些可视化效果和运行应用程序所必需的函数,然后我将展示 shinyServer 函数,它与 shinyUI 函数类似。
- authenticate 函数:允许 spotifyr 对 API 进行身份验证,并允许访问所有数据。参数只是客户端 id 和客户端机密。
- fav_artists 函数:制作一个表格,其中包括用户的顶级艺术家,以及他们的受欢迎程度(由 Spotify 排名)、Spotify 每月总听众人数和音乐流派等信息。它使用 spotifyr 函数 get_my_top_artists_or_tracks,然后使用 R 的数据操作函数和强大的管道操作符将表格精简为最基本的必需品。这个函数主要用在 tabPanel 二中。
- fav_artists_datatable 函数:格式化从最后一个函数创建的表格,使其对用户友好。
- audio_features_fav_artist 函数:创建一个包含艺术家姓名的表,以及 Spotify 为每首歌曲测量的一些音频功能。这些衡量标准是“可跳舞性”、“能量”、“响度”、“语速”、“声音”、“活力”、“积极性”和“节奏”。这个函数使用 spotifyr 的 get_artist_audio_features 函数,我们做了一些字符串操作来将 valence 的标题改为 positivity。在第四个 tabPanel 中大量使用。唯一的参数是 artist_name。
- 从上一个函数生成一个 R 数据表。最终没有使用这个函数,但它在某些场景中可能很重要,因为 plotly 有时比普通的 R 数据帧更适合使用 datatable 对象。同样,唯一的参数是 artist_name。
现在我们在实际的 shinyServer 中,项目的所有“复杂”方面都在这里。这并不复杂,但是所有的对象都源自这里,所以如果你在实际的可视化或者从 Spotify API 提取数据时出现问题,这可能就是原因。
- 我们需要 shinyServer 来创建“后端”,因此我们可以使用 Rshiny eventReactive 函数创建 validate 函数(这个函数和 Reactive 函数一样常用,所以请在这里阅读),将输入$btn 作为触发器,并执行我们在 ui.R 中声明的 validate 函数。我们还可以使用 Rshiny 的 renderText 函数将 validate 函数的输出保存为文本。
TabPanel two 有 4 个对象:popularity_data、popularity_plot_output、follower_plot_output 和 favorite_artists_table。
- popularity_data 只是保存我们之前在 server.R 中创建的 fav_artists 函数的输出的 dataframe 对象,我们需要使用 Rshiny 反应函数将该函数引入 shinyServer。这个函数非常重要,在服务器中经常使用。r 文件。
- popularity _ plot _ output 将是保存流行度条形图的对象,它比较用户库中前 25 位艺术家的 Spotify 流行度指标。这些图表的语法非常简单明了,因为更困难的问题通常是“可视化应该是什么?”
- follower_plot_output 与上一个图类似,只是它使用了 plotly。Plotly 通常需要更多的数据操作来创建图表,但它们是动态的,而标准的 ggplots。
- favorite_artists_table 是页面末尾的一个简单表格,用户可以看到他们关注的每个艺术家的详细信息
第三个选项卡面板也包含 4 个对象:情绪 _ 数据、情绪 _ 文本、情绪 _ 绘图 _ 输出和大多数情绪。
- 情绪数据是音频特征收藏艺术家函数的数据帧对象,输入是用户在这个页面的下拉菜单中选择的艺术家姓名。我们还使用一个反应函数来允许使用我们之前创建的 audio_features_fav_artist 函数。
- 仅仅显示用户在下拉列表中选择的情感,但是字体更大。
- sensition _ plot _ output 首先获取用户选择的情绪类型,并用 casefold 函数使其小写。这被保存到称为文本的向量(或 1D 数据帧)中,并且文本被用于以降序组织情绪数据。然后,为了实际制作 ggplot,我们需要为 x 轴使用文本,因为文本变量依赖于用户的输入。这看起来很复杂,但是我们这样做是为了让图表根据用户的输入而改变。
- most _ perspective 使用与上一个图相同的逻辑来保持情绪名称的动态,它基本上只是打印出情绪类型和单个音轨的分数。
TabPanel 4 有 5 个对象:top _ artist _ invision _ data、energy_vs_positivity _ plot _ output、energy _ vs _ positivity、speech ness _ vs _ dance ability _ plot _ output 和 speech ness _ vs _ dance ability
- top _ artist _ invision _ data 基本上意味着使用 audio_features_fav_artist 表,但是使用 popularity_data 作为索引。这样做是为了获得用户库中前 10 位艺术家的音频。这个对象基本上是一个艺术家名字的数据帧和艺术家所有歌曲的所有音频特征。
- energy _ vs _ positivity _ plot _ output 将该数据帧绘制成散点图,对每个艺术家使用不同的颜色。我用不同的描述给每个象限贴上标签,又名“愤怒”,代表能量较高但积极性较低的音乐。我们使用顶级艺术家情感数据来创建这个可视化
- energy_vs_positivity 将 energy 和 positivity 的分数绑定,并计算分数,决定哪种情绪最能代表用户的音乐品味。然后输出描述用户音乐个性的语句。
- speech ness _ vs _ danceability _ plot _ output 与前面的图类似,只是使用 speech ness 和 dance ability 作为情绪。
- speechiness_vs_danceability 也给出了描述用户音乐个性的陈述。
这就差不多解决了。我们需要的只是逃跑。r 文件,我们的 app 就完成了!请查看以下内容:
卢克·切瑟在 Unsplash 上的照片
对于一些人来说,查看制作 Rshiny 应用程序的过程似乎很复杂,但实际上这比尝试用 Javascript 甚至 Python 的 Streamlit 包做同样的事情要容易得多。它还允许您使用 R 在一个有效的交互式数据科学应用程序中提供的非常强大的数据操作工具,其他人可以使用和享受这些工具!
我希望这能让一些数据科学爱好者和应用程序开发人员大开眼界,并希望激发更多与数据相关的应用程序,这些应用程序具有用户真正喜欢的功能,如他们最喜欢的指标的直接和交互式可视化。
来源:
https://github.com/kingazaan/spotifyr-r-shiny https://github.com/charlie86/spotifyr https://vladyslavkushnir.medium.com/exploring-spotify-api-in-r-284f1ef32f46 https://medium.com/@joypham7/spotify-personal-data-analysis-858c8fbe6983
支持数字业务的商业机器学习工具包
商业人工智能需要在规定性分析和可操作的机器学习模型之间找到一条交叉道路。
介绍
根据 Zion market research 的数据,2017 年全球机器学习(ML)市场价值约为 15.8 亿美元,预计 2024 年将达到约 208.3 亿美元。各种规模的公司都在应用认知技术,这些技术利用了机器学习(ML)和人工智能(AI)的新兴能力。基于云的 GPU&TPU 的可用性、开源库、谷歌、脸书等公司的投资以及 Kaggle 等大规模数据集的可用性,使得机器学习的应用在每个产品开发中都触手可及。
Gartner 的首席信息官调查发现,在过去四年中,人工智能的实施增长了 270%。调查数据显示,随着机器人流程自动化(RPA)的兴起,工作流程正在通过机器学习算法得到增强,以降低成本和提高客户满意度。由于满足运营需求的技术渗透率越来越高,业务影响的价值也越来越高,采用支持 ML 的应用程序的企业正在获得发展势头。机器学习预测的数据丰富特性也是数字企业抓住机会做出实时决策的主要驱动力。机器学习的独特之处在于对该领域的整体、超然观点,以及自动识别隐藏模式。人工智能的采用正在加速,预计到 2024 年,75%的企业将转向人工智能驱动的企业。由此,一个新的趋势出现了**“机器(深度)学习驱动实时业务流程”。**
商业 ML 工具包
对于机器学习模型的商业成功,理解商业应用需要最高程度的功能性和可靠性是很重要的。与增量改进的统计度量相比,成功度量大部分是二元的。这要求对 ML 模型如何工作有高度的可解释性和透明性。该工具包解释了解决这些需求的分析和运营框架。
商业 ML 工具包[图片由作者提供]
规定性分析
传统上,公司根据历史数据执行商业计划。例如,商店经理将根据前一年的数据和商店经理的经验决定“产品促销”。随着实时信息的可用性和成熟的机器学习算法的可用性的增加,公司正在通过使用历史和实时趋势的预测分析来做出主动决策。然而,机器学习还为实时业务提供了超越预测分析的优势,这就是【规定性分析】,预计到 2022 年这个市场将达到约18.8 亿美元。
更多面向消费者的企业正在尝试采用透视分析,因为它为可能的预测结果提供了可行的建议。更大的优势是,它还实时执行具有给定约束的**“如果……会怎样”分析**。更少的例子包括:a)如果员工正在努力完成一门课程,LMS 系统会推荐额外的课程来学习必备技能;b)通过为正确的买家指定正确的内容来引导销售;c)通过根据日常销售情况优化实时数据来更好地管理商店库存。
印度 IT 巨头 Infosys 的一份名为企业中的人力放大的调查报告发现,98%的受访者表示,通过执行人工智能任务,他们的组织增加了 15%的收入。在这方面,最大的影响来自机器学习,因为它通过提供“考虑业务/运营约束的建议”来帮助做出更明智的决策。
操作框架
在这种“使用机器学习的企业实时决策”的范式转变之后,人工智能和人工智能已经成为一个工程问题而不是研究挑战。可靠性、可扩展性和管理复杂系统是实时执行 ML 模型的重点领域。问题是“与仅仅进行无休止迭代的研究实验相比,我如何让机器学习项目适应市场需求?”。专家认为,实时商业人工智能和人工智能的使用增加将有助于加速模型在生产中的部署。
由于实时决策或建议是由计算机提供的,因此关键的挑战是确保**合规、透明和道德。**因此,“商业人工智能需要规范分析和机器学习模型之间的交叉道路,以建立规范模型,帮助企业做出实时决策”。下面是解释解决这些挑战的不同技术和工具的操作框架。
商业化人工智能——操作框架[图片由作者提供]
可解释的人工智能(XAI)
“可解释的人工智能”(XAI)是实现人类与科学合作的一步,并使“以人为本的战略”成为建立面向消费者的产品的实时规定性分析。这是一套工具和框架,有助于提高可解释性和可解释性,这对实现公平、负责和透明的 (FAT) 无偏见的机器学习至关重要。它有助于回答“我应该相信这个预测吗?”
机器学习中的这个新兴领域旨在解决ML 模型如何做出黑盒决策**。一些更简单形式的 ML 模型,如决策树、贝叶斯分类器、逻辑回归都有一定的解释能力。最近的研究进展表明,在深度学习领域,更复杂的机器学习算法具有可解释性。像 DARPA 这样的研究实验室正在围绕为神经网络构建可解释的接口进行广泛的研究,这些神经网络产生更多可解释的模型,同时保持高水平的学习性能。**
在过去的几年里,人工智能研究人员一直在开发类似于 What-if 、 DeepLIFT 、 AIX360 、激活图册、 Rulex 、可解释人工智能、 Alibi 的工具,以及类似于注意力、时间、 SHAP 的方法,使从业者能够轻松地进行评估这些工具也促进了可解释的人工智能的大规模应用。
ML 的科学“敏捷”
企业衡量的一个新指标是**“在生产中部署第一个模型的时间”**。最近的一项调查显示,18%的公司投入生产的时间超过 90 天,有些甚至超过一年。它还强调了 25%的 ML 工程师时间花在将模型投入生产上。这个延长周期的一个关键原因是,ML 是一个研究密集型环境,它是不确定的。另一个方面是,研究项目未能证明可行性,也是一种可能的结果。这意味着很多时候你会以一个未交付的功能而告终。
需要开发一个适应性策略/过程来管理任何机器学习项目。这种策略应该以连续的方式为大量的调查、探索、分析和调优提供更多的机会。
快速迭代项目开发[ 图来自 Doug DeCarlo 的《极限项目管理》一书[3]][图片由作者提供]
机器学习的数据驱动、开放的本质要求更快的反馈循环,这自然有助于敏捷成为机器学习项目的事实过程。我们需要的是一个**“敏捷的新端口”**用于机器学习。
敏捷原则的移植版本将从以下方面挑选特征:a)将这种【科学方法】集成为一个持续的迭代过程 b)通过【数据分析金字塔】管理数据,它表达了基于项目管理的商业价值 c)【PERT】
根据 Dresner 的报告,70%的研发部门最有可能将人工智能和机器学习应用于他们所有的企业职能。这种向基于价值的合同的不断转变将推动人工智能和机器学习平台保持响应性和适应性,这是基本的敏捷原则。
3 M 的 ML 编排
随着 ML 的商业应用趋于激增,企业将寻求更好地管理、监控和维护生产中的模型,以确保对部署的 AI 集成的信任。随着对合规性、数据安全性和偏见的审查越来越严格,信任和透明度将变得更加重要。**需要注意的三个“M”**是:
商业人工智能——3M 的 ML 编排[图片由作者提供]
MLOps 专注于人工智能的可操作化,使技术/科学变得可访问、可应用、可重复和自动化。MLOps 还建议建立一个“跨职能团队”,让工程师和研究人员融入同一个团队。它还是评估和实现洗钱风险和洗钱健康的基本平台。企业需要专注于构建 MLOps/ CD4ML 框架,该框架考虑了特性存储、模型版本、元数据存储、模型服务和端到端部署管道。有了像 Kubeflow 、 FEAST 、 ONNX 、 Seldon Core 和 5 level 这样的开源工具,成熟度模型可以帮助企业了解他们的当前状态并向上爬,从而将 MLOps 视为他们有形业务价值的驱动因素。
ML Health 是功能监控,用于向业务发起人传达业务模型的表现。这一点至关重要,因为它展示了预测模型的性能以及对产品/业务的影响。这是通过持续的度量评估来实现的,例如准确性、精确度和召回,以确保它们在预期的范围内运行。需要一个成功的沟通策略,如模型性能下降或上升的实时通知平台。对于生产中的大规模模型部署,使用 Tableau 和 Qlik 等可视化工具构建监控仪表板也很流行。
洗钱风险不会随着模型开发而结束。模型漂移是一种预期的行为,当一个 ML 模型被集成为实际应用的一部分时。当检测到模型所训练的变量发生变化时,模型的准确性会降低。a)目标变量**(概念漂移)** b)输入数据**(数据漂移)** c)操作变化**(特征漂移)**的统计特性可以触发模型漂移的发生。
检测实时模型漂移的理想方法是实施任何技术,如**数据偏差检测、金丝雀管道、漂移检测、生产 A/B 测试、多臂土匪测试(多变量|优化)作为 ML 工作流程的一部分。另一个有用的方法是,与部署在(干预模式)相比,在【检测模式】**部署模型,这样有助于演示漂移。像 Alibi Detect 这样的监控和治理工具以及像 fiddler 、 truera 这样的商业工具被认为是这个领域的新兴领导者。
作为机器学习应用消费化的副产品,全面的生产治理机制和责任对于确保遵守 GDPR、算法责任法案、FDA 等 ML 合规要求至关重要。期望机器学习工作流程中的所有阶段都应该是可追溯的,具有可再现性、可审核性并有助于解释。
结论:
这些专注于为机器学习模型带来可解释性和透明度的进步正在推动 ML 模型的变化,以实时推动数字业务。随着规范分析中的随机优化,许多商业用例,如在线推荐、智能营销活动、信贷决策、欺诈检测,都在为人工智能支持的数字应用铺平道路。广泛的研究仍然继续为更复杂的关键任务用例带来可解释性,如医疗诊断、需要高度透明和可解释性的自动驾驶汽车。
我们还了解到,迭代和跨职能沟通的原则比以往任何时候都更加重要。围绕可解释性、公平性和隐私的问题需要通过可持续的机器学习模型管理和治理结构来解决。与模型性能相比,机器学习模型的有用性将根据业务指标来衡量。
有了机器学习的这些归纳性质,很明显,人工智能商业化的时代正在跨越【VoID】的道路上。
简单解释了常见的距离测量
探索数据科学
距离度量在数据科学和机器学习中无处不在。许多算法依赖于它们,并且"知道何时使用哪个距离度量可以帮助你从一个差的分类器到一个精确的模型。在这篇文章中,马腾·格罗登斯特出色地解释了最常见的问题。对于九种距离测量中的每一种,Maarten 描述了它们是如何工作的,提供了几个用例,并讨论了它们的潜在缺点。
</9-distance-measures-in-data-science-918109d069fa>
关于差异隐私的常见误解
人工智能校准和安全
本文将澄清一些关于差异隐私及其保证的常见误解。
来源: Gretel.ai
关于差分隐私(DP)的内容有很多,从学术著作,如 DP 创始人写的隐私书,到解释其核心原则、解释和应用的博客,如这个系列。虽然这些都是写得很好的资源,但它们需要深入研究才能完全掌握。因此,如果你对差分隐私有一个基本的了解,但还没有机会深入研究这些资源,这篇文章将澄清一些常见的误解。
差分隐私不是算法。
更确切地说,DP 是算法必须满足的标准。标准很简单,算法的输出,比如计数,不应该太依赖于任何单一记录。算法通常通过某种类型的概率噪声添加来掩盖任何记录的存在,从而达到差分隐私标准。例如,可以将少量噪声添加到精确计数中,使其具有差分私密性。
差异隐私不能为所有敏感信息提供全面保护。
借用 McSherry 的一句话,“差别隐私是正式区分你的秘密和关于你的秘密”如果您选择贡献您的秘密,DP 将以与您不贡献您的秘密相同的方式保护您的秘密。但它并不保证你的秘密会以其他方式公之于众。
考虑这个例子。你是一名数据科学家,在雨林公司(一家实行薪酬平等的虚构公司)年薪 10 万美元。雨林的人才团队希望公布数据科学家的平均收入,以吸引更多的申请人,他们已经决定使用差分隐私安全地共享这些聚合信息。你知道你的同龄人的收入与你相差不到 5k,但你从未与任何人分享过你的收入——你认为这是你的秘密。你想继续保护你的秘密,所以你选择不被包括在这个平均值中。几周过去了,你看到数据科学家的招聘信息更新为“平均工资约为 10.1 万美元”。任何阅读这份招聘启事的人都会推断出你大约挣 10.1 万美元,这是真的。所以即使你在计算中隐瞒了你的数据,你的秘密已经公开了。
再举一个例子,看看这个讲座,卡马斯讲述了为什么一个广为流传的目标市场营销的故事不是侵犯隐私。
差别隐私不是万能的。
DP 并不适用于每一种分析。这是一种量化的方式,算法会告诉你更多关于数据集中大规模趋势的信息,而不是关于任何特定个体的信息。换句话说,它旨在帮助人们巧妙地隐藏在人群中。
如果对异常值分析感兴趣,DP 就不是保护隐私的合适工具。此外,DP 不适合研究小群体。其核心是,DP 旨在允许安全地共享大量人口的汇总信息。
“有差别的私有数据”不是一个明确定义的术语。
“差异私有数据”是一个经常被提起的模糊术语。它可能有几个不同的意思,容易引起误解。我们来分解一下。
如果你读过一些介绍性材料,你可能会认为“差分私有”是一个形容词,适用于做一些聚合的算法,如求和、中值甚至神经网络,以及它们的输出。通常,隐私保护源于某种形式的校准的概率噪声添加。那么,对于产生数据记录而不是作为输出的集合的过程,噪声添加是如何工作的呢?
下面是对“差异私有数据”的几种可能的解释。
- “差分私有数据”可以指本地 DP 算法的输出。如果您不熟悉中央 DP 与本地 DP,请向下滚动到附录。随机响应等局部 DP 算法会产生一个敏感问题(例如,你吸烟吗?).该算法是可证明的差分私有的,并且该算法产生的噪声数据库也可以被描述为差分私有的。
- “有差别的私有数据”也可以指生成模型的输出,该生成模型用技术训练以满足有差别的隐私的标准。
生成建模被布朗利描述为*“机器学习中的一项任务,涉及自动发现和学习输入数据中的规律或模式,以这种方式,模型可以用于生成或输出新的示例,这些示例很可能是从原始数据集中提取的。”*生成模型最常用神经网络,可以设计成符合 DP 的标准。
差分私有生成模型的输出通常被称为差分私有合成数据。对于复杂的多变量分析,如预测建模,这些模型可以产生比随机响应更高保真的合成数据。有一个巨大的研究领域致力于开发新的技术,可以最佳地平衡高质量合成数据的需求与隐私的需求,差分隐私只是其中之一,尽管是非常受欢迎的一种。
因此,当使用差分隐私作为一个形容词来描述数据时,我鼓励你澄清所使用的算法的广泛类别,注意所产生数据的预期用途,并在适当的时候正确地将数据称为合成数据。
我希望这篇文章有助于澄清一些关于差分隐私的常见误解。如果你有任何问题或者想在 Gretel 上谈论我在应用隐私领域的工作,请给我写信 lipika@gretel.ai !
附录
中央与地方差异隐私
有两种不同的差分隐私模型—中央和本地。隐私的标准保持不变,但是区别在于数据存储在哪里以及何时出现噪声添加。
您可能熟悉中心模型,在这种模型中,所有真实、敏感的数据都可以在某个中心位置获得。例如,你和我在西雅图一家标志性的咖啡连锁店注册奖励。我们把我们的名字、电话号码和出生日期托付给他们,他们现在把这些信息储存在某个中央数据库里。如果他们想分享在晚上 7 点后订购含咖啡因饮料的顾客的年龄中位数,他们可以通过计算真实值并添加一些校准噪声来保证不同的隐私。真实的、敏感的数据仍然被不加修改地存储,并且与差分隐私无关。它是共享中值年龄(即一种算法,参见第一个误解)的过程,而不是被查询的中央数据库。
相反,本地模型是为缺乏信任或存储原始数据的中心位置的情况而设计的。例如,我的好奇的朋友乔治正在进行一项研究,关于有抱负的数据科学家完成带回家的任务是否需要比规定时间更长的时间,并要求我贡献我的数据。虽然我也同样好奇,想知道我的同行的总体信息,但我不相信乔治会透露我花了一整天完成我的最后一次带回家,尽管时间限制是 4 个小时。所以乔治告诉我掷硬币。如果是正面,我会如实回答。否则,我再次抛硬币,如果它正面朝上,我说是,如果它反面朝上,我说不是。如果乔治要求所有调查参与者都这样做,他现在就会收集到一个嘈杂版本的数据集。这个算法叫做随机化回答。收集这个嘈杂数据集的目的是聚合它,乔治通过解释第二次抛硬币引入的偏差来完成这个任务。请注意,如上所述,随机化回答是有差别的隐私(见第 3.2 节的证明)。因此,该算法是差分隐私的,并且该算法的输出,这个嘈杂的答案数据库,也可以被描述为差分隐私。
更多关于 DP 的风格和它们之间的界限,请阅读这篇文章。
集群中你应该避免的四个错误
每个人都应该知道的聚类分析的关键步骤
TL;博士
- 缺乏详尽的探索性数据分析和可消化的数据清理
- 缺少特征缩放
- 没有建立代表性的集群
- 缺少分类结果的描述
答在看了大量聚类方法和分析并做了大量工作后,我想与您分享聚类分析中的四个常见错误以及如何避免它们。
错误#1:缺乏详尽的探索性数据分析(EDA)和可消化的数据清理
使用像.describe()
和.isnull().sum()
这样的常用方法是开始探索性分析的一个非常好的方法,但绝对不应该是你的 EDA 的结束。变量的更深层次(视觉)分析和它们如何相互关联****至关重要。否则,异常值等异常值可能无法完全检测出来,某些变量之间的相关性也可能无法发现。这些步骤中的错误将牵连随后的特征选择步骤和聚类结果。
如果您在数据集中发现了缺失值或异常值,您通常可以选择是用巧妙的方法替换这些值(如 KNNImputer,使用平均值/中值)还是从数据集中删除它们。不管你在这种情况下决定做什么,重要的是要清楚地解释为什么你决定选择各自的方法。因此,你应该经常问自己这些问题(并证明答案的正确性):
- 我的清理步骤对分析和建模有什么影响?
- 如果我从数据集中删除 x%的行,这意味着什么?
- 离群值对我的数据集有什么影响,为什么我决定保留/删除它们?
- 这些异常值的原因是什么?
错误#2:缺少特征缩放
如果您正在使用基于距离的聚类算法,如 k-means,在应用该算法之前,标准化所使用的特征是非常重要的。这一步骤的原因在于计算聚类的方式。
稍后确定的聚类是由数学空间中数据点之间的距离(例如欧几里德距离)定义的**。数据集中的变量通常有不同的单位,因此也有不同的取值范围。例如,如果有一个变量的取值范围比另一个变量的取值范围大得多,它可能会强烈影响聚类结果。数据集中的每个变量通常也有不同的含义(例如,体重和身高),因此,变量不能直接比较(例如,1 公斤比 1 米更重要吗?).通过标准化我们的特征,我们可以通过将其转换为无单位的度量或相对距离来获得每个特征的相对权重。**
展示标准化重要性的最佳方式是使用葡萄酒数据集示例,该示例也在 sklearn 的文章“特性缩放的重要性”(链接)中使用。
如果我们看一看通常的描述性数字(tbl。1)我们不仅可以看到变量具有不同的取值范围(由于它们的单位不同),而且其中一些变量与其他变量相比具有较高的标准偏差(std)值。
表 1。我们的葡萄酒数据集的描述性分析。
例如,与其他变量如镁 ( 14.28 )或苹果酸 ( 1.12 )相比,变量脯氨酸具有较高的标准偏差 314.91 。
当比较单个变量的方差(std)时,巨大的差异变得更加明显(图 1)。
图一。按方差排序的特征方差。
很明显,与其他变量相比,脯氨酸的方差最大。
为了显示像脯氨酸和镁这样的具有高方差的变量可能主导聚类,我们应用了主成分分析(PCA ),不使用和使用所用特征的预先标准化(图 2)。
主成分分析侧重于最大化方差的成分。如果像酒精这样的一个变量由于其各自的单位(例如体积百分比对毫克/升)而比另一个变量(例如脯氨酸)变化更小,如果这些特征没有被缩放,则 PCA 可以确定最大变化的方向与脯氨酸轴更紧密地对应。
图二。缩放和不缩放的特征及其对 PCA 的影响。
在未缩放的情况(图 2 中的第一行)中,具有最高方差脯氨酸和镁 的特征主导方向,这导致数据点的噪声聚类。
虽然您可以在缩放案例(图 2 中的第二行)中看到,对于所有特征来说,t 的幅度大致相同,并且数据点的聚类在这里要清晰得多**。**
我希望这个例子向您清楚地展示了为什么特征缩放对于基于距离的聚类算法(如 k-means)如此重要,尽管丢失特征缩放并不是常见聚类分析中的唯一错误。
错误 3:没有建立有代表性的集群
另一个非常常见的错误是没有建立有代表性的集群。我这么说是什么意思?一些聚类结果可能如下所示:
图 3。无代表性集群的示例。
与簇 1 和 2 相比,簇 0 的大小明显更小。当然,在某些情况下,这样的结果可能是有效的**,如果在那个**后面有可理解的推理的话。
然而,这种情况通常是例外的,并且每个聚类的相对相等数量的数据点应该总是针对。通常错误在于或者是缺少特征缩放/选择或者是选择的聚类数量。
在 k-means 中你通常可以使用肘方法或者剪影评分方法来确定合适的聚类数(图 4)。
图 4。肘部和轮廓评分法。
使用肘方法,您计算多个聚类 K 的失真(即从聚类中心到各个聚类的平方距离的平均值)或惯性(即样本到其最近的聚类中心的平方距离的总和)。然后,在一个图表中,将变形/惯性值与聚类数 K 一起可视化。在失真/惯性开始线性下降后,通过寻找图中的扭结或肘状点**,从视觉上确定最佳集群数。看看我们的例子,这意味着 3 是最佳集群的数量。**
除了肘图法,还可以使用**(平均)剪影评分法**。
至于肘图法,我们也对几个聚类大小 K 运行 k-means。但我们不是计算失真/惯性,而是计算每个 K 的轮廓系数。
轮廓系数定义为:(x-y)/max(x,y)。
其中 y 代表平均类内距离(即从一个点到同一类中其他点的平均距离)。而 x 表示平均最近聚类距离(即,到下一个最近聚类的点的平均距离)。
计算完成后,我们绘制系数值和聚类数 K,以直观地确定合适的聚类数。在这里,我们为选定数量的 K 个集群寻找全局最优值(即图中的最高点)。至于肘图,轮廓系数图的最佳聚类数将是 3。
在应用了具有确定的最佳聚类数的聚类之后,您应该查看一下聚类结果。
关注属性非常有用,例如:
- 集群基数
- 集群星等
- 数量与基数
下图 5 显示了上述属性以及使用 PCA 的聚类可视化。
图 5。我们的集群、集群基数、数量和数量与基数的关系的可视化。
群集基数或群集大小图显示了每个群集的点数。您可以使用此图表来查看某些分类包含的数据点是否明显少于或多于其他分类。在我们的示例中,每个集群的数据点分布看起来不错。
群集幅度图显示了每个群集的总点到质心的距离。此图表可用于查看每个聚类中的点的“分布”有多高,以及是否有任何簇或宽簇。
基数对数量图比较了集群基数和集群数量。基数较高的聚类往往也具有较高的聚类数量级。这个想法是正常的星团位于或非常接近 45 度线上。异常往往离它更远。在我们的例子中,群集 1 是异常的。
我强烈推荐你看看谷歌开发流程图(链接)来检查你的集群质量。
图 6。流程图“如何检查你的聚类质量”(作者 Google Dev )。
错误#4:最后但同样重要的是:缺少对集群特征的描述
这可能是聚类过程中最重要的一步:描述我们的发现。不幸的是,这一步大多被忽略了。
我们的目标是以一种非技术人员一眼就能理解的方式描述每个集群。
你应该回答的问题是:
- 哪些特征代表了每个分类?
- 哪些特征区分了我的集群?
一个快速简单的解决方案是计算每个聚类的每个特征的平均值(tbl。2).
表二。每个聚类的每个特征的平均值。
像这样的表格为读者提供了每个聚类中的特征看起来如何的第一概述。例如,我们可以看到,与其他聚类相比,聚类 1 包含较高的脯氨酸和镁值。
作为绝对值的替代方法,您也可以计算相对差异(tbl。3).在这种情况下,计算每个聚类的每个要素与每个要素的总体平均值的相对差异(百分比)。
这意味着,例如,值为 619 时,聚类 0 中的特征脯氨酸与特征脯氨酸的总体平均值(743)相差-17%(=(743–619)/743)。
表 3。每个聚类的每个特征相对于每个特征的总体平均值的差异百分比。
除了表格可视化之外,绘制结果图通常也很有帮助。根据聚类和特征的数量,不同的可视化选项是合适的。
例如,其中之一是在单独的图表中显示每个特征的平均值的相对差异(图 7)
图 7。每个特征与平均值的相对差异显示为条形图。
但是,如果您必须处理许多功能,很容易很快失去对概览的关注。
另一个可视化选项是用雷达图而不是条形图来显示集群特征(图 8)。
图 8。以雷达图形式显示的每个特征平均值的相对差异。
聚类及其特征或与平均值的相对偏差显示为彩色区域。根据集群的数量,单个集群的特征可以一眼快速识别。
C 光泽分析是一种(无监督的)方法,它将没有标记或分类的数据进行分组。因此,我们有责任使用正确的应用方法和最佳实践程序在数据中找到可解释和可理解的模式。但是在我们对数据进行聚类之前,不仅适当的 EDA 和清理是必不可少的,而且特性缩放也是必不可少的。一旦我们建立了我们的集群,我们必须确保这些结果不仅具有代表性,而且对于(商业)用户来说是可以理解的。
我希望这篇文章有助于填补一些空白,并为您的下一次聚类分析提供有用的提示。
数据科学简历中的常见错误
以及如何修复它们
有很多好的方法来制作一份简历。也有很多不好的方式。
特别是对于数据科学,初级职位的申请人数往往过多,拥有一份好的简历是极其重要的。
最重要的是保持一份简洁、易于浏览的简历。如果你的简历是数百份简历中的一份,你不想强迫拿起它的人去读大段。他们的眼睛会变得呆滞,什么也看不见。
如果你的简历的优点不能很快地被发现,没有人会花时间去更深入地研究并发现真正存在的价值。
以下是我在初级求职者的简历中看到的一些常见错误:
1.在顶部有一个很长的“目标”(或“总结”)
在简历上写“目标”是为了给你的职业目标提供一些背景。
实际上,大多数目标陈述读起来都非常相似。
这并不奇怪——每个申请相同职位的人都有相似的职业目标。此外,人们倾向于列出他们认为招聘人员/招聘经理想听的话,这导致了很多模糊的商业对话。他们往往只是含糊其辞地说希望使用数据来创造商业价值,并希望提高自己的技能,成为更好的数据科学家。
除了没有太多的信息外,目标章节往往是叙述式的,而不是结构化的,这使得它们很难浏览。
因此,许多招聘人员说他们不阅读目标部分就不足为奇了。他们往往没有太多的信息,阅读他们比浏览简历的其他部分需要更多的努力。当你有数百份简历要处理时,你没有时间去阅读冗长的“客观”部分。
如果你确实想在你的简历顶部有一些东西(无论是目标还是总结),给你的简历提供背景,保持简短,并确保它真正传达了有意义和重要的信息。
2。列出不必要的技能/工具
同样,保持简历简短,不要列出不必要的技能。
有一些工具被认为是数据科学的核心。确保你清楚了解标准数据科学技术堆栈(例如 Python、pandas、sklearn)、统计学和机器学习。列出工作资格中特别要求的技能,或与之相关的技能。
不要列出招聘信息中没有提到的具体技术。列出一大堆技术可能感觉不错。克制自己。它看起来很臃肿,而且很难找到真正相关的工具。
如果你想表现出你懂一些技术,那就提一般技能而不是工具。比如列出“贝叶斯建模”而不是“PyMC3,Stan,rjags”。这不仅有助于减少空间浪费,也让那些审查你简历的人更容易,因为他们不需要知道所有这些工具是什么。
但是要确保你有节制地使用招聘启事中没有提到的技能。
3.其他不必要的信息
简历上的空间很重要。不要把它浪费在不必要的事情上:
- 完整邮寄地址。他们不会通过给你寄信来联系你
- 相关课程作业的课程编号。这些数字在大学之外没有任何意义。不要包括他们。如果你缺乏任何证明核心技能的经验,只包括“相关的课程工作”。
- **你的 GitHub 个人资料,如果你实际上什么都没有的话。**分享你的 GitHub 个人资料很棒,但是你不能因为拥有个人资料而获得积分。如果你列出来,确保如果我去那里,我可以找到一些实际的项目。
保持你的简历简洁。
4.简历太长了
与最后三条建议相一致的一般原则是:不要写太长的简历。即使在高级/领导级别,一页通常也足够了。
如果你刚刚进入这个领域,一页就足够了。
我听说过一个有用的思考方式:你的简历的价值是根据简历内容的平均质量来判断的,而不是总和。
显然,这一经验法则是有局限性的——不要仅仅把最令人印象深刻的一件事放在简历上,就认为这就够了。但一般来说,增加更多可能会让你觉得自己听起来更有价值,但很容易降低你的感知价值。
5.对项目或工作职责的模糊描述
一个人越能描绘出一个项目或工作中所涉及的内容,他们就越容易将你所申请的职位与他的职责相提并论。
避免模糊的术语,明确你使用的工具,如果你发现很难简明清晰地描述一个项目或职责,考虑一下它是否需要存在。你不必列出你曾经做过的每一个项目或责任。花点空间好好解释一下重要的。不要因为担心自己做得不够,而在填充职责上浪费空间。
6.没有上下文的项目的绩效指标
这是一个非常具体的数据科学问题。在一个项目上经常看到“建立了一个 AUC 为 0.76 的模型”。这样好吗?我不知道。
没有上下文的绩效指标毫无意义。
也许你正在解决一个众所周知的问题,并且你假设阅读它的人有上下文。也许在某些(罕见的)情况下,这是可以的。但是一般来说,您需要为性能指标提供一些上下文。
这是对以前使用的方法的改进吗?很好,告诉我改进了什么(至少说明一下是如何实现的)。
你能量化它的商业价值吗?太好了,告诉我这对公司有多大影响。
如果你做不到这两点,那就好好想想,如果没有任何额外的背景,你的绩效指标是否真的有意义。
我希望这些建议有所帮助!以下是一些你可能感兴趣的其他文章: