TowardsDataScience-博客中文翻译-2020-四十八-

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

使用 Covid19、Foursquare 和 Zomato APIs 探索印度德里的食品商店

原文:https://towardsdatascience.com/exploring-food-outlets-in-delhi-india-using-covid19-foursquare-and-zomato-apis-d6010ebb7416?source=collection_archive---------64-----------------------

IBM 数据科学顶点项目

王德·古普塔Unsplash 上拍摄的照片

作为 Coursera 上应用数据科学顶点项目的一部分,我必须使用 FourSquare API 来获取位置数据,并使用任何其他必要的数据来创建一个有洞察力的数据科学项目。在这篇文章中,我将讨论我用来探索和识别印度德里的食品商店的方法。

链接到我的 Github 项目

介绍

世界正面临来自新冠肺炎疫情的前所未有的威胁。毫无疑问,这个疫情影响了我们的生活方式,但也彻底改变了消费者的行为。

我们看到网上订购食品、衣服、日常家居用品、杂货等的数量激增。最*这段时间。

消费者行为的这种变化也意味着,现在消费者不仅会关注那些以合理价格提供优质食品的食品商店,还会关注食品商店的卫生等级和所在区域,以确保安全和卫生不会受到影响。

此外,保持消费者对食品安全性和可用性的信任和信心也变得至关重要。

在这篇文章中,我将帮助消费者找到那些不仅价格合理,而且安全的食物店。

目标

这个项目的目的是根据以下几点对印度德里的食品商店进行分类:

  1. *均值。价格
  2. 评级
  3. 位置
  4. 该区的冠状病毒病例
  5. 在线交付服务

数据

我将合并来自 3 个 API 的数据:

  1. Covid19 API —获取德里不同地区所有确诊的冠状病毒病例
  2. FourSquare API—使用我们从 Covid19 API 收到的地区的位置坐标,并将其作为输入传递给 four square API,以检索德里每个地区 4 公里半径内的 100 个地点。
  3. Zomato API —我将把从 FourSquare API 检索到的地点和位置坐标作为输入传递给 Zomato API,以获得关于餐馆的信息,如评级、*均价格。价格,评论数,是否有线上发货等。

我还将使用网络抓取来提取餐厅的卫生评级。

在合并了上述数据源之后,我绘制了从 FourSquare API 接收的数据和从 Zomato API 接收的数据,以帮助我们更好地将其可视化。

在德里地图上绘制正方形数据:

四方数据

在德里地图上绘制 Zomato 数据:

佐马托数据

从视觉上看,大多数位置似乎是匹配的,但是我们必须小心组合来自不同数据集的数据。

为了合并这两个数据集,我将检查来自 Zomato API 和 FourSquare API 的每个相应地点的纬度和经度值是否匹配,因为我们使用了该地点的坐标作为 Zomato API 的输入,以获得有关该地点的更多信息。因此,我将纬度和经度值四舍五入到小数点后 4 位。然后,我将计算相应的纬度和经度值之间的差异,并查看差异是否小于 0.0005,这在理想情况下意味着两个位置是相同的。这是我对这个项目的一个假设。

此外,一些场馆的名称根本不匹配。例如,从 Foursquare API 检索到的地点名称是 KFC,但是当我们将它传递给 Zomato API 时,它返回了“Al Kuresh ”,这显然是错误的。我们需要把这些从桌子上拿走。

清理完数据后,我们只剩下 67 行,现在可以开始处理数据了。

方法学

我们将执行 EDA 和聚类的食品出口的基础上评级,*均。价格、位置、卫生等级和冠状病毒病例数。

第 1 部分:探索性数据分析

等级

餐厅评分分布

从上面的剧情可以看出,大部分餐厅的评分都是 3.8 和 4。

价格

价格分布

接下来,让我们探索一下德里餐馆的*均价格,这对初来德里并想了解餐馆*均价格的人来说很有用。原来德里的大部分餐厅均价 300 卢比。

卫生等级

卫生等级分布

让我们了解一下餐馆的卫生等级。考虑到冠状病毒的爆发意味着餐馆必须遵守严格的卫生政策,这是一个重要因素。有趣的是,德里所有的餐馆卫生等级都是 0,这意味着这些餐馆的卫生习惯没有得到评定。Zomato 应努力确保所有餐厅都有卫生评级,尤其是有了疫情之后。

网上发货

在线交付的分布

从上面的图中,我们可以看到在线交付功能几乎是*均分布的。其中一半没有网上送货,另一半有。在这个疫情期间,如果餐馆在加强必要的卫生政策的同时,强调网上送货,利润会高得多。

价格区间

价格范围的分布

Zomato 还提供了每家餐厅“价格区间”的详细信息。此功能的范围从 1 到 4,其中 1 表示方便,4 表示昂贵的餐馆。大多数餐厅更倾向于方便消费者,这对消费者来说是一个加分点。

地区与价格

地区与价格

高端餐厅位于新德里和南德里区。我们在德里东南部和德里中部也有一些价格较高的餐厅,尽管这些地区的*均价格较低,这使得这些餐厅成为异类。

地区 vs 评级

地区与评级

德里东南部和新德里是餐馆*均得分较高的地区。而南德里的餐馆*均得分最低。评级。

评级 vs 价格

评级与价格

评分 2.6 的餐厅,均价 2500 真的很高!这些餐馆需要重新考虑他们的价格范围,因为他们的评级不是很好。经过进一步分析,发现位于新德里和德里东南部的“电气室”是 2.6 级和 2500 卢比的插座,他们可能应该重新考虑他们的价格点。

另一个有趣的观察是,评分为 4.8 的餐馆比评分为 4.5 的餐馆有更低的价格点。

地区 vs 美食

地区 vs 美食

让我们试着去了解德里每个地区的大多数餐馆都提供什么样的菜肴。

从上面的地图,我们可以看到:

  1. 在德里东北部,大多数餐馆提供“北印度、快餐、穆格莱”菜肴。
  2. 在德里市中心,大多数餐馆都提供“咖啡馆和甜点”美食。
  3. 在东德里,大多数餐馆提供“南印度、北印度和中国”菜肴。
  4. 在新德里,大多数餐馆供应“欧洲和大陆”菜肴。
  5. 在德里东南部,大多数餐馆都供应“北印度,穆格莱”菜肴。
  6. 在南德里,大多数餐馆都供应“意大利沙拉”菜肴。
  7. 在西南德里,大多数餐馆都供应“街头食品,米泰”美食。
  8. 在西德里,大多数餐馆提供“咖啡馆、快餐、甜点、饮料、三明治”美食。

第 2 部分:集群

我们将首先使用“肘方法”来确定集群的最佳数量。

肘法

对于每个 k 值,我们将初始化 k 均值,并使用惯性属性来确定样本到最*的聚类中心的*方距离之和。

使用最优‘k’进行聚类

最佳的“K”值是 3,我们将使用它进行 K 均值聚类。

kmeans=KMeans(n_clusters=3).fit(df_clustering)
kmeans.predict(df_clustering)
final_venues.insert(0,'cluster_label',kmeans.labels_)
final_venues.head()

在德里地图上绘制聚类

集群 0 中的场馆有:

  • 均价 631.82 卢比
  • *均值。评分 4.34
  • *均值。冠状病毒病例 98.91
  • *均值。复习计数 1736.36
  • 网上交货的差价为 0.36

第一组的场馆有:

  • *均价格 400.53 卢比
  • *均值。评分 3.50
  • *均值。冠状病毒个案 119.23
  • *均值。审查总数为 292.68
  • 网上交货的差价为 0.60

第 2 组的场馆有:

  • 均价 2238.89 卢比
  • *均值。评分 3.91
  • *均值。冠状病毒病例 82.00
  • *均值。审核计数为 560.44
  • 网上交货差价为 0.00

结果和讨论

从我们的分析中,我们注意到大多数餐厅的*均评分为 3.8 。我们还注意到*均。大多数餐馆的价格是 250-300 卢比,并不贵。

Zomato 的“价格区间”功能也能给我们提供有价值的见解。这个特征的范围从 1 到 4(1 是口袋友好到 4 是昂贵),结果大多数餐馆更倾向于口袋友好

关于餐馆的“卫生等级”有一个有趣而又令人担忧的观察。所有餐馆的卫生等级都是 0,这意味着这些餐馆没有被评为卫生等级。 Zomato 应努力确保所有餐厅都有卫生评级,尤其是有了这个疫情,因为它将帮助消费者确保他们的安全和卫生不受损害。

另一个有趣的观察结果是,在线交付功能在餐厅中几乎*均分布,即一半的餐厅没有在线交付,而另一半有。在这次疫情期间,更多地强调网上送货对餐馆来说是有益的。

在根据餐馆的评级分析价格时,我们注意到评级为 3.5 的餐馆的*均得分为 3.5。价格为 1500 卢比的餐馆和评分为 4.9 的餐馆的*均得分为 1。价格 2500 卢比。

不过评分 2.6 的餐厅也有均价 2500 挺高的!经过进一步分析,发现这是由于“Lodhi 酒店电气室”的 2 个插座造成的这些分店分别位于新德里和德里东南部。鉴于他们的评级如此之低,他们可能应该重新考虑他们的价格点。

我们还分析了德里每个区的大多数餐馆提供的美食,这将有助于消费者确定当他们渴望某种特定的美食时应该去哪个区。

现在来看餐馆的聚类,我们能够从我们的数据集中导出 3 个聚类。

位于第一个集群(即集群 0 的餐厅价格合理,评级最高,评论数最高,冠状病毒病例较少,因此理想情况下,人们可以在采取适当安全预防措施的情况下访问这些食品商店。有趣的是,第 0 组的大多数商店都位于德里市中心或新德里区。

集群 1 中的商店价格最低,评级体面,评论数最低,大多数餐馆提供在线送货,但与其他集群相比,该集群的冠状病毒病例数也最高。在准备和运送食物时,这个集群中的食物出口必须格外小心。如果你确实从这里订餐,我建议你采取额外的预防措施,非常小心。

最后,位于最后一个集群,即集群 2 的门店具有最高的价格点、良好的评级和评论数,没有在线交付,但冠状病毒病例最少。如果你是一个不介意花钱购买质量不错的食物,同时又注重安全的人,你可以试试这些餐馆。

结论

这个项目的目的是探索德里不同的食品商店,牢记卫生和冠状病毒病例。这个项目的局限性之一是我只能从 Zomato API 中检索大约 170 家餐馆的数据。另一个主要限制是,我已经将该区冠状病毒病例的数量分配给该区目前的每个食品商店。然而,德里的每个区都很大,需要细分到社区才能获得更准确的表示,但德里没有社区级别的冠状病毒病例。

在合并了来自不同 API 的数据之后,我执行了 EDA 来揭示一些有趣的观察结果,并且还基于 rating,avg 对数据集执行了 K 均值聚类。价格、位置、店铺所在地区的冠状病毒病例、是否提供在线配送以及该食品店铺的总评论。

聚类分析显示,新德里的大多数餐馆和德里中部的一些餐馆可以安全点餐,而且提供最优质的食物,而德里东南部的餐馆也可以安全点餐,但价格更高。根据游客对等级、价格和其他要求的选择,他/她可以在这三个集群中的不同食品商店中进行选择。

探索生成性对抗网络

原文:https://towardsdatascience.com/exploring-generative-adversarial-networks-gans-488e1d901d4a?source=collection_archive---------66-----------------------

一个生成对抗网络 (GAN)是机器学习(ML)的一种强有力的方法。在高层次上,GAN 就是两个互相反馈的神经网络。一个产生越来越精确的数据,而另一个逐渐提高其分类这些数据的能力。

在这篇博客中,我们将深入探讨这种机制是如何工作的,在哪里可以使用它,以及在现实世界中使用 GAN 的潜在后果。

一言以蔽之

GAN 中的第一个神经网络称为发生器。它从随机输入 1 开始,反复生成接*真实世界数据质量的数据。它通过将其输出发送到另一个神经网络鉴别器来实现这一点,该神经网络逐渐提高其从训练数据中对输出进行分类的能力,并将输出(分类)反馈给生成器。从实现的角度来看,发生器和鉴别器具有它们自己的损失函数,其中鉴别器的损失函数包含发生器的损失函数。输出(分类)包含在损失函数中,其中生成器在训练期间通过反向传播更新其权重。

以下流程图说明了这种设计:

图像由感知实验室提供。

GAN 的对立方面在于,鉴频器的结果可以反馈到自身以进行自我改进,和/或反馈到发电机以提高发电机的输出。从这个意义上来说,生成器提高其输出的能力在某种程度上与鉴别器在训练过程中对数据进行分类的能力相竞争。此外,鉴别器对生成模型(即生成器)的自动训练意味着 GAN 有效地将原本无监督的 ML 过程转变为自动化的、有监督的 ML 过程。

为了支持这种功能,通常使用逆卷积神经网络(有时称为反卷积网络)来构建生成器,因为该神经网络具有生成数据的能力(例如,上采样特征图以创建新图像)。鉴别器通常使用常规 CNN 构建,因为它能够将数据(例如,图像)分解成特征图,并最终对数据进行分类(例如,确定图像是真实的还是伪造的)。注意,也可以使用其他类型的神经网络层来构建 GANs。

在训练过程的最后,一个 ML 实践者可能使用完全训练过的生成器、鉴别器或者两者都使用来进行推理,这取决于他们试图解决的真实世界的问题。

甘斯的“你好世界”

在 GANs 的背景下,一个好的“hello world”2 项目可以围绕 MNIST 数据集创建,数据集是一个图像库,包含从 0 到 9 的手写数字。第一次学习神经网络的用户通常使用该数据集作为输入,以解决对这些图像中表示的数字进行分类的问题。

因此,这个问题可以进一步扩展为学习 GANs 的起点。这里,目标是逐渐生成新的手写数字图像,其质量和风格接*甚至匹配 MNIST 数据集中的图像,同时还增加了对给定图像是由 GAN 生成还是实际上是真实图像进行分类的能力。此类问题的 GAN 如下所示:

感知器成像。

生成器用随机噪声(数据)播种,并生成手写数字的图像。此时,输出可能非常糟糕,因为随机噪声可能没有很好地反映手写数字。然后,该输出与来自 MNIST 数据集(训练数据)的图像一起被馈送到鉴别器。本例中的鉴别器是二项式,将来自生成器的给定图像分类为真实图像或假(生成)图像。

然后,生成器的输出以及鉴别器的分类被递归地反馈到生成器中,以重复该过程,并有希望改进两个生成器的下一个输出。在这一点上,鉴别器还可以将其输出连同更多的训练数据一起反馈给自身,以进一步提高其对图像进行分类的能力。

训练 GAN 可能需要很长时间,大约几个小时甚至几天,这取决于数据、可用的计算资源以及 ML 从业者试图达到的准确度水*。一种理想化的情况是训练,直到鉴别器在大约 50%的时间内错误地分类图像,此时,ML 实践者通常假设生成器正在输出似是而非的数据。然而,ML 从业者可以根据他们的需要训练到不同的准确度水*。

用途和道德

GANs 的力量打开了一个充满可能性的世界。GANs 可以用于各种各样的图像处理任务,例如将夏天拍摄的照片翻译成冬天拍摄的照片,或者类似地从白天到晚上。它们还可以生成我们许多人会误认为真实的物体、场景和人物的照片。GANs 可用于类似的音频翻译,也可用于帮助识别不同类型的网络威胁。

如果你开始被各种可能性吓到,你并不孤单。由于 GANS 生成的数据与真实世界的数据没有什么区别,所以你不需要思考太多就能意识到它的潜在含义。因此,以有益于社会的方式充分利用氮化镓是很重要的。

结论

GANs 是利用神经网络力量的一种强大而聪明的方式。通过同时训练一个神经网络来创建越来越可信的数据,而另一个神经网络增加了对这些数据进行分类的能力,ML 从业者有效地将两个解决方案合二为一。当很好地使用时,GAN 的生成和分类组件可以潜在地帮助 ML 实践者构建解决方案,这些解决方案执行看起来像魔术一样的技艺。

1。生成器的输入通常被称为潜在空间。

2。hello world项目是在给定的框架或开发环境(如编程语言)中给你的第一个项目起的名字,用来证明你可以构建并运行它。

探索大悉尼郊区

原文:https://towardsdatascience.com/exploring-greater-sydney-suburbs-f2bf1562988e?source=collection_archive---------21-----------------------

使用 Python Matplotlib、Seaborn、geopandas 和 k-means 聚类

这是我的 IBM 数据科学专业证书的顶点项目的一部分。请继续阅读并跟随源代码的链接,并放心使用。

基思·朱摄于 Unsplash

当我六年前搬到澳大利亚时,肾上腺素和兴奋情绪稍微*静下来后,我面临的第一个挑战是住在哪里!我选择居住地的经历与许多第一代移民没有什么不同。降落在奥兹,在一个朋友家过夜,然后决定在附*找点东西。

现在,我的职业是会计,所以我看到数字会很兴奋。出于这个原因,我决定在数据科学领域提升自己的技能。我选择从 IBM Professional Certificate 开始,对此我将在另一篇博客中详细讨论,但是现在,让我们直接跳到完成认证所需的顶点项目。你猜对了,我选择应用一些新获得的数据技能来探索当地政府区域(LGA)或大悉尼地区的社区,并可能决定在哪个区域居住。

详细演示和源代码的链接在这里:

https://github . com/timun 01/IBM-Capstone-Project/blob/master/Week _ 4/

现在来体验一下我完成这个项目所经历的过程。

数据…当然

与任何数据科学项目一样,最大的挑战是获得一样东西…数据!我花了几个小时浏览了许多网站,最终下载了一些合适的数据,如下所示:

  • 2019 年 9 月季度 LGA/街区的住房租赁数据(来源:www.facs.gov.au)
  • 2019 年 6 月季度 LGA/街区住宅销售数据(来源:www.facs.gov.au)
  • 悉尼地区的形状文件(绘制地理地图,并获得邻*地区的坐标)
  • 基于 2016 年人口普查的人口数据(来源:http://stat.data.abs.gov.au/)
  • 2019 年 9 月至今 LGA/邻*地区的犯罪数据(来源:https://www.bocsar.nsw.gov.au)

请记住,所有这些数据都是不同的格式,LGA 边界不断变化,因此较新的数据比旧的数据具有不同的 LGA。这导致了一些数据丢失。考虑到这种分析纯粹是出于教育目的,所以我们可以接受它。

在我们继续之前有一个警告。考虑到上述因素和每个人的个人情况,此分析仅用于顶点项目和学术目的,因此不得用于任何其他目的。

方法学

好的。你可能注意到了,我的分析更倾向于租房,假设新移民会租房而不是马上买房。在清理和组合了大量不同的数据后,我使用了方框图、柱状图、散点图和热图的组合来比较不同的街区。

接下来,我使用 Choropleth 和 Folium Open street 地图进行地理空间分析。最后,我使用 Foursquare API 来探索场地,并应用 k-mean 聚类算法来创建共享相似设施的社区组。这将有助于我们通过收集对该地区的一些了解来决定搬到一个新的国家。

结果

接下来是大量数据可视化的部分。

情节

第一个图是使用 Seaborn 的盒图函数绘制的。这为我们提供了每种住宅类型的最低、第一四分位数、中间值、第三四分位数和最高租金的 5 点范围。例如,我们可以看到房屋租金从 400 美元 pw 到 1400 美元 pw 以上不等。叠加在上面的散点图显示了该范围内出租的房产数量。例如,在房屋方面,我们可以看到大部分房产的租金都在最低租金和中等租金之间。对于联排别墅,如果需要,我们可以进一步评估一些异常值,但现在就到此为止。

对于下面的图,我使用 Matplotlib 来说明每个 LGA 的*均租金(实际上是租金中位数的*均值)以及一些可用的物业的简单视图。悉尼作为一个大都市,*均拥有的住宅数量最多。650 美元。整体*均约为 530 美元。

接下来是一组散点图(使用 Seaborn 的 lmplot 函数),显示了每个街区的卧室数量的详细租金分布。再以悉尼为例,我们可以看到 4 居室的房子都是> $1100pw 不到 2500 的房产。另一方面,一居室很丰富,价格在 600 美元以下。这是像悉尼这样的中央商业区所能预料到的。

让我们用一张热图来显示所有郊区按住宅类型划分的租金成本分布。这告诉我们,例如,就个人住宅类型而言,莫斯曼是最昂贵的街区,其次是 Woollahra 等等。

现在是销售分析。下面的柱状图为我们提供了 2019 年 Q2 各街区的摩天大楼中值价格分布。这涵盖了所有物业类型的中值价格。实际上,价格会因型号和大小而异,这不在我们现阶段的考虑范围内。

2019 年 Q2 期间每个街区的销售价格中位数

基于以上所述,正如人们所料,我们可以在下面的散点图(相关系数为 0.84)中看到,*均租金和邻*地区的中值价格之间存在很强的相关性。

地图

该部分包括销售和人口数据的地理空间分布。我首先将 geojson 文件转换为 shape 文件,然后使用 geopandas 的 Choropleth 映射函数来映射这些 shape 文件。老实说,我花了一段时间才明白过来(太棒了!!!我最终绘制它的时刻)。

接下来,我根据 2019 年 9 月至今的犯罪事件下载数据,创建了一个气泡图,以可视化每个街区的犯罪相对规模。这些数据被绘制在 Folium Open street 地图的顶部。

每个街区的犯罪数据

这就结束了我们的数据可视化部分。现在让我们转到机器学习算法部分。

k 均值聚类

在这里,如前所述,我使用 Foursquare API 探索附*的所有场所(咖啡馆、健身房、酒吧、公园等),然后基于这些场所创建数据框。

在生成的数据帧上,应用了一种流行的无监督机器学习算法,称为 k 均值聚类。这将数据分为 4 个不同的组:

集群的图例

第一集群:主要以咖啡馆、海滩和公园为公共场所。

集群 2: 这里有大量的餐馆、咖啡馆和购物中心。

集群 3: 以咖啡馆、公园、餐馆和汉堡店为主

集群 4: 更接*集群 1,以咖啡馆、酒吧和公园为主。

总的来说,正如我们之前所讨论的,对于一个人来说,搬迁到一个全新的国家并不是一个容易的决定。然而,生活在科技时代也有它的好处!我们通过互联网获得大量信息,然后使用数据分析工具,我们可以根据个人偏好做出合理的决定。

这就结束了我的第一个数据科学作业,这是我从头开始做的。它帮助我在这个过程中学到了很多,我期待着在这个领域进一步提高我的技能。

请随时评论源代码或情节,以便我进一步微调。

用 Python 探索 Hulu 数据

原文:https://towardsdatascience.com/exploring-hulu-data-in-python-1eb6fa90a886?source=collection_archive---------69-----------------------

Hulu 数据的探索性数据分析

来源

网飞、Prime Video、Hulu 和 Disney Plus 上的电影数据集包含从 reelgood.com 收集的信息,其中包含上述*台上可供流媒体播放的电影列表。在本帖中,我们将对网飞的电影、Prime Video、Hulu 和 Disney Plus* 数据集中的 Hulu 数据进行基本的探索性数据分析。数据可以在这里找到。*

我们开始吧!

首先,让我们将数据读入熊猫数据框:

import pandas as pd 
df = pd.read_csv("MoviesOnStreamingPlatforms_updated.csv")

接下来,我们将打印该数据中可用的列:

print(df.columns)

我们不需要“Unamed: 0”列,所以我们可以用“del”关键字删除它:

del d['Unnamed: 0’]

现在,让我们使用“head()”方法打印前五行数据:

print(df.head())

如果我们看一下网飞、Hulu、Prime Video 和 Disney Plus 栏,我们会发现它们包含 1 和 0。1 对应于该电影可在相应*台上流式传输,而 0 对应于该电影在所述*台上不可用。

我们想专门研究 Hulu 数据,所以让我们过滤数据框,使“Hulu”列中的值等于 1:

df_hulu = df[df['Hulu'] == 1]

让我们打印原始数据框和过滤后的数据框的长度:

print("Total Length: ", len(df))
print("Hulu Length: ", len(df_hulu)))

让我们打印新数据框的前五行:

print(df_hulu.head())

我们的数据包含几个分类列。让我们定义一个将数据框、列名和限制作为输入的函数。当被调用时,它打印分类值的字典以及它们出现的频率:

def return_counter(data_frame, column_name, limit):
   from collections import Counter    print(dict(Counter(data_frame[column_name].values).most_common(limit)))

让我们将函数应用于“语言”列,并将结果限制为五个最常见的值:

return_counter(df_hulu, 'Language', 5)

如我们所见,Hulu 数据中有 607 个英语、27 个英语/西班牙语、19 个日语、18 个英语/法语和 15 个缺失的语言值。

让我们将此方法应用于“流派”列:

return_counter(df_hulu, 'Genres', 5)

现在,让我们来看看最常见的电影类型“纪录片”:

df_d1 = df_hulu[df_hulu['Genres'] =='Documentary']
print(set(df_d1['title']))

我们也可以看看这些国家:

print(set(df_d1['Country']))

接下来,让我们看看电影运行时间值的集合:

print(set(df_d1['Runtime']))

我们看到运行时间值的范围从 30 分钟到 120 分钟。接下来,从数字列(如“Runtime ”)中生成汇总统计数据会很有用。让我们定义一个采用数据框、分类列和数字列的函数。每个类别的数字列的*均值和标准偏差存储在数据框中,并且数据框根据*均值以降序排序。如果您想要快速查看特定类别对于特定数字列是否具有更高或更低的*均值和/或标准偏差值,这将非常有用。

def return_statistics(data_frame, categorical_column, numerical_column):
    mean = []
    std = []
    field = []
    for i in set(list(data_frame[categorical_column].values)):
        new_data = data_frame[data_frame[categorical_column] == i]
        field.append(i)
        mean.append(new_data[numerical_column].mean())
        std.append(new_data[numerical_column].std())
    df = pd.DataFrame({'{}'.format(categorical_column): field, 'mean {}'.format(numerical_column): mean, 'std in {}'.format(numerical_column): std})
    df.sort_values('mean {}'.format(numerical_column), inplace = True, ascending = False)
    df.dropna(inplace = True)
    return df

让我们用分类列“流派”和数字列“运行时”来调用我们的函数:

stats = return_statistics(df_hulu, 'Genres', 'Runtime')
print(stats.head(15))

接下来,我们将使用箱线图来显示基于最小值、最大值、中值、第一个四分位数和第三个四分位数的数值分布。如果您对它们不熟悉,可以看看文章了解 Boxplots

与汇总统计函数类似,此函数采用数据框、分类列和数值列,并根据限制显示最常见类别的箱线图:

def get_boxplot_of_categories(data_frame, categorical_column, numerical_column, limit):
    import seaborn as sns
    from collections import Counter
    keys = []
    for i in dict(Counter(df[categorical_column].values).most_common(limit)):
        keys.append(i)
    print(keys)
    df_new = df[df[categorical_column].isin(keys)]
    sns.set()
    sns.boxplot(x = df_new[categorical_column], y =      df_new[numerical_column])

让我们在 5 个最常见的“流派”类别中为“运行时”生成箱线图:

get_boxplot_of_categories(df_hulu, 'Genres', 'Runtime', 5)

最后,让我们定义一个函数,它将数据框和数字列作为输入,并显示一个直方图:

def get_histogram(data_frame, numerical_column):
    df_new = data_frame
    df_new[numerical_column].hist(bins=100)

让我们用数据框调用函数,并从“运行时”生成一个直方图:

get_histogram(df_hulu, 'Runtime')

我就讲到这里,但是请随意处理数据并自己编码。

结论

概括地说,我们回顾了几种分析网飞电影、Prime Video、Hulu 和 Disney Plus 数据集中 Hulu 数据的方法。这包括定义用于生成汇总统计数据的函数,如*均值、标准差和分类值的计数。我们还定义了用箱线图和直方图可视化数据的函数。我希望这篇文章有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

在边缘探索 AI!

原文:https://towardsdatascience.com/exploring-ia-at-the-edge-b30a550456db?source=collection_archive---------13-----------------------

树莓*台上基于 Tensorflow Lite 的图像识别、目标检测和姿态估计

图片来源:作者创作

介绍

什么是边缘(或者C计算

Gartner 将边缘计算定义为:“分布式计算拓扑的一部分,其中信息处理位于靠*边缘的位置,即事物和人生产或消费信息的位置。”

换句话说,边缘计算将计算(和一些数据存储)带到离生成或消费数据的设备更*的地方(尤其是实时),而不是依赖于遥远的基于云的中央系统。使用这种方法,数据不会遇到延迟问题,从而降低了传输和处理的成本。在某种程度上,这是一种“回到最*的过去”,所有的计算工作都在本地的桌面上完成,而不是在云中。

边缘计算是由于连接到互联网的物联网设备的指数增长而发展起来的,这些设备要么从云中接收信息,要么将数据传送回云中。许多物联网(IoT)设备在运行过程中会产生大量数据。

边缘计算为物联网应用提供了新的可能性,特别是对于那些依赖机器学习(ML)来完成诸如对象和姿态检测、图像(和人脸)识别、语言处理和避障等任务的应用。图像数据是物联网的绝佳补充,但也是重要的资源消耗者(如电力、内存和处理)。图像处理“在边缘”,运行经典 AI/ML 模型,是一个巨大的飞跃!

tensor flow Lite——机器学习(ML)在边缘!!

图片来源:机器学习训练对比推理 — Gartner

机器学习可以分为两个独立的过程:训练和推理,正如 Gartner 博客中所解释的:

  • 训练:训练是指创建机器学习算法的过程。训练涉及使用深度学习框架(例如 TensorFlow)和训练数据集(见上图左侧)。物联网数据提供了一个训练数据源,数据科学家和工程师可以使用它来训练各种情况下的机器学习模型,从故障检测到消费者智能。
  • 推理:推理是指使用经过训练的机器学习算法进行预测的过程。物联网数据可以用作经过训练的机器学习模型的输入,实现预测,这些预测可以指导设备上、边缘网关上或物联网系统中其他地方的决策逻辑(见上图右侧)。

TensorFlow Lite 是一个开源的深度学习框架,支持在设备上的机器学习推理,具有低延迟和小二进制大小。它旨在使在网络“边缘”的设备上执行机器学习变得容易,而不是从服务器来回发送数据。

在设备上执行机器学习有助于改善:

  • 延迟:没有到服务器的往返
  • 隐私:没有数据需要离开设备
  • 连接:不需要互联网连接
  • 功耗:网络连接非常耗电

TensorFlow Lite (TFLite)由两个主要组件组成:

  • TFLite 转换器,它将 TensorFlow 模型转换成高效的形式供解释器使用,并可以引入优化来提高二进制大小和性能。
  • TFLite 解释器在许多不同的硬件类型上运行,包括手机、嵌入式 Linux 设备和微控制器。

图片来源:TensorFlow Lite —在边缘设备部署模型

总之,一个经过训练和保存的 TensorFlow 模型(如 model.h5 )可以使用 TFLite FlatBuffer(如 model.tflite )中的 TFLite Converter 进行转换,该转换器将由 Edge 设备内部的 TF Lite 解释器使用(作为一个 Raspberry Pi),以对新数据进行推理。

例如,我在我的 Mac(上图中的“服务器”)中从头训练了一个简单的 CNN 图像分类模型。最终模型有 225,610 个参数要训练,使用 CIFAR10 数据集作为输入:60,000 个图像(形状:32,32,3)。经过训练的模型( cifar10_model.h5 )的大小为 2.7Mb。使用 TFLite 转换器,在 Raspberry Pi 上使用的模型( model_cifar10.tflite )的大小变为 905Kb(约为原始大小的 1/3)。用两个模型进行推断(h5 在 Mac 和。RPi 处的 tflite)留下相同的结果。两款笔记本都可以在 GitHub 找到。

图片来源:作者笔记本

Raspberry Pi — TFLite 安装

也可以在 Raspberry Pi 从头开始训练模型,为此,需要完整的 TensorFlow 包。但是一旦我们要做的只是推理部分,我们将只安装 TensorFlow Lite 解释器。

仅解释器包的大小是整个 TensorFlow 包的一小部分,并且包括使用 TensorFlow Lite 运行推理所需的最少代码。它只包含用于执行.tflite模型的[tf.lite.Interpreter](https://www.tensorflow.org/api_docs/python/tf/lite/Interpreter) Python 类。

让我们在 Raspberry Pi 打开终端,安装您的特定系统配置所需的 Python wheel 。选项可以在这个链接上找到: Python 快速入门。例如,在我的例子中,我运行的是 Linux arm 32(Raspbian Buster—Python 3.7),所以命令行是:

$ sudo pip3 install [https://dl.google.com/coral/python/tflite_runtime-2.1.0.post1-cp37-cp37m-linux_armv7l.whl](https://dl.google.com/coral/python/tflite_runtime-2.1.0.post1-cp37-cp37m-linux_armv7l.whl)

如果您想仔细检查 Raspberry Pi 中的操作系统版本,请运行以下命令:

$ uname -

如下图所示,如果你得到… arm7l… ,操作系统是 32 位 Linux。

安装 Python wheel 是让 TFLite 解释器在 Raspberry Pi 中工作的唯一要求。可以在终端调用 TFLite 解释器来仔细检查安装是否正常,如下所示。如果没有错误出现,我们是好的。

图像分类

介绍

应用于计算机视觉(CV)的人工智能的更经典的任务之一是图像分类。从 2012 年开始,当一个名为 AlexNet卷积神经网络 (CNN)(为了纪念其领先的开发者 Alex Krizhevsky)在 ImageNet 2012 挑战赛中取得了 15.3%的前 5 名误差时,信息架构和深度学习(DL)永远改变了。根据《经济学家》杂志的报道,“人们突然开始关注(人工智能),不仅仅是在人工智能领域,而是在整个技术行业

这个项目,在 Alex Krizhevsk,一个更现代的架构( MobileNet )的*八年后,也使用相同的数据集 ImageNet 对数百万张图像进行了预训练,产生了 1000 个不同的类。这个预先训练和量化的模型是这样的,转换成一个. tflite 并在这里使用。

图片来源:作者创作

首先,让我们在 Raspberry Pi 上移动到一个工作目录(例如, Image_Recognition )。接下来,必须创建两个子目录,一个用于模型,另一个用于图像:

$ mkdir images
$ mkdir models

一旦进入模型目录,让我们下载预先训练好的模型(在这个链接,可以下载几个不同的模型)。我们将使用量化的 Mobilenet V1 模型,用 224x224 像素的图像进行预训练。可以从 TensorFlow Lite 图片分类下载的 zip 文件,使用 wget :

$ cd models
$ wget [https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_v1_1.0_224_quant_and_labels.zip](https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_v1_1.0_224_quant_and_labels.zip)

接下来,解压缩文件:

$ unzip mobilenet_v1_1.0_224_quant_and_labels

下载了两个文件:

  • mobilenet _ v1 _ 1.0 _ 224 _ quant . TF Lite:tensor flow-Lite 转换模型
  • Labels _ mobilenet _ quant _ v1 _ 224 . txt:ImageNet 数据集 1000 个类标签

现在,获取一些图像(例如。png,。jpg)并将它们保存在创建的图像子目录中。

GitHub 上,可以找到本教程使用的图片。

Raspberry Pi OpenCV 和 Jupyter 笔记本安装

OpenCV(开源计算机视觉库)是一个开源的计算机视觉和机器学习软件库。在处理图像时,这是一种有益的支持。如果在 Mac 或 PC 上安装它非常简单,那么在 Raspberry Pi 上安装就有点“技巧”了,但是我推荐使用它。

请按照 Q-Engineering 的这个很棒的教程在你的树莓 Pi 上安装 OpenCV:在树莓 Pi 4 上安装 OpenCV 4.4.0。尽管该指南是为 Raspberry Pi 4 编写的,但也可以不做任何修改地用于 Raspberry 3 或 2。

接下来,安装 Jupyter 笔记本。它将成为我们的开发*台。

$ sudo pip3 install jupyter
$ jupyter notebook

此外,在 OpenCV 安装过程中,应该已经安装了 NumPy,如果现在没有安装,与 MatPlotLib 相同。

$ sudo pip3 install numpy
$ sudo apt-get install python3-matplotlib

完成了!我们已经准备好开始我们的人工智能之旅了!

图像分类推理

创建一个新的 Jupyter 笔记本并遵循以下步骤,或者从 GitHub 下载完整的笔记本。

导入库:

import numpy as np
import matplotlib.pyplot as plt
import cv2
import tflite_runtime.interpreter as tflite

加载 TFLite 模型并分配张量:

interpreter = tflite.Interpreter(model_path=’./models/mobilenet_v1_1.0_224_quant.tflite’)
interpreter.allocate_tensors()

获取输入和输出张量:

input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

输入细节将为您提供所需的信息,告诉您应该如何为模型输入图像:

(1,224x224x3)的形状通知一个尺寸为:(224x224x3)的图像应该一个一个输入(批量尺寸:1)。dtype uint8 表示这些值是 8 位整数

输出细节显示推理将产生 1001 个整数值(8 位)的数组。这些值是图像分类的结果,其中每个值是特定标签与图像相关的概率。

例如,假设我们想要对形状为(1220,1200,3)的图像进行分类。首先,我们需要将其调整为(224,224,3)并添加一个批处理维度 1,如输入细节中所定义的:(1,224,224,3)。推断结果将是一个大小为 1001 的数组,如下所示:

图片来源:作者创作—图片分类主要步骤

对这些操作进行编码的步骤是:

  1. 输入图像并将其转换为 RGB (OpenCV 将图像读取为 BGR 图像):
image_path = './images/cat_2.jpg'
image = cv2.imread(image_path)
img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

2.图像预处理、整形和添加批量尺寸:

img = cv2.resize(img, (224, 224))
input_data = np.expand_dims(img, axis=0)

3.指向用于测试的数据并运行解释器:

interpreter.set_tensor(input_details[0]['index'], input_data)
interpreter.invoke()

4.获取结果并将它们映射到类别:

predictions = interpreter.get_tensor(output_details[0][‘index’])[0]

输出值(预测值)从 0 到 255 不等(8 位整数的最大值)。要获得范围从 0 到 1 的预测,输出值应除以 255。与最高值相关的数组索引是这种图像最可能的分类。

有了索引,我们必须找到它指定的类别(如汽车、猫或狗)。与模型一起下载的文本文件有一个与从 0 到 1,000 的每个索引相关联的标签。

让我们首先创建一个函数来加载。txt 文件作为字典:

def load_labels(path):
    with open(path, 'r') as f:
        return {i: line.strip() for i, line in enumerate(f.readlines())}

创建一个名为标签的字典,并检查其中的一些标签:

labels = load_labels('./models/labels_mobilenet_quant_v1_224.txt')

回到我们的例子,让我们得到前 3 个结果(最高概率):

top_k_indices = 3
top_k_indices = np.argsort(predictions)[::-1][:top_k_results]

我们可以看到,前 3 个指数都与猫有关。预测内容是与每个标签相关联的概率。如前所述,除以 255。,我们可以得到一个从 0 到 1 的值。让我们创建一个循环来检查顶部结果,打印标签和概率:

for i in range(top_k_results):
    print("\t{:20}: {}%".format(
        labels[top_k_indices[i]],
        int((predictions[top_k_indices[i]] / 255.0) * 100)))

让我们创建一个函数,来*滑地对不同的图像执行推理:

def image_classification(image_path, labels, top_k_results=3):
    image = cv2.imread(image_path)
    img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    plt.imshow(img)img = cv2.resize(img, (w, h))
    input_data = np.expand_dims(img, axis=0)interpreter.set_tensor(input_details[0]['index'], input_data)
    interpreter.invoke()
    predictions = interpreter.get_tensor(output_details[0]['index'])[0]top_k_indices = np.argsort(predictions)[::-1][:top_k_results]print("\n\t[PREDICTION]        [Prob]\n")
    for i in range(top_k_results):
        print("\t{:20}: {}%".format(
            labels[top_k_indices[i]],
            int((predictions[top_k_indices[i]] / 255.0) * 100)))

下图显示了使用该函数的一些测试:

图片来源:作者根据公共数据集创作

整体表现惊人!从你输入内存卡中的图像路径开始,直到打印出结果,整个过程不到半秒钟,精度极高!

该功能可以很容易地应用于视频或现场摄像机的帧。本节讨论的笔记本和完整代码可以从 GitHub 下载。

目标检测

利用图像分类,我们可以检测这样的图像的主要主题是什么。但是,如果几个物体在同一个图像上是主要的和感兴趣的,会发生什么呢?要解决它,我们可以使用一个对象检测模型!

给定图像或视频流,对象检测模型可以识别已知对象集合中的哪一个可能存在,并提供关于它们在图像中的位置的信息。

对于此任务,我们将下载一个使用 COCO(上下文中的公共对象)数据集预训练的 Mobilenet V1 模型。这个数据集有超过 200,000 个带标签的图像,分属 91 个类别。

图片来源:作者创作

下载模型和标签

在 Raspberry 终端上运行命令:

$ cd ./models 
$ curl -O [http://storage.googleapis.com/download.tensorflow.org/models/tflite/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip](http://storage.googleapis.com/download.tensorflow.org/models/tflite/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip)
$ unzip coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip
$ curl -O  [https://dl.google.com/coral/canned_models/coco_labels.txt](https://dl.google.com/coral/canned_models/coco_labels.txt)$ rm coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip
$ rm labelmap.txt

models 子目录中,我们应该以 2 个新文件结束:

coco_labels.txt  
detect.tflite

对新图像执行推断的步骤与图像分类非常相似,除了:

  • 输入:图像的形状必须为 300x300 像素
  • 输出:不仅包括标签和概率(“得分”),还包括对象在图像上所处位置的相对窗口位置(“边界框”)。

图片来源:作者创作

现在,我们必须加载标签和模型,分配张量。

labels = load_labels('./models/coco_labels.txt')
interpreter = Interpreter('./models/detect.tflite')
interpreter.allocate_tensors()

输入预处理和我们之前做的一样,但是输出应该被处理以获得更可读的输出。以下函数将对此有所帮助:

def set_input_tensor(interpreter, image):
    """Sets the input tensor."""
    tensor_index = interpreter.get_input_details()[0]['index']
    input_tensor = interpreter.tensor(tensor_index)()[0]
    input_tensor[:, :] = imagedef get_output_tensor(interpreter, index):
    """Returns the output tensor at the given index."""
    output_details = interpreter.get_output_details()[index]
    tensor = np.squeeze(interpreter.get_tensor(output_details['index']))
    return tensor

借助上述函数,detect_objects()将返回推理结果:

  • 对象标签 id
  • 得分
  • 边界框,它将显示对象的位置。

我们已经包括了一个“阈值”来避免正确概率低的对象。通常情况下,我们应该考虑 50%以上的分数。

def detect_objects(interpreter, image, threshold):
    set_input_tensor(interpreter, image)
    interpreter.invoke()

    # Get all output details
    boxes = get_output_tensor(interpreter, 0)
    classes = get_output_tensor(interpreter, 1)
    scores = get_output_tensor(interpreter, 2)
    count = int(get_output_tensor(interpreter, 3)) results = []
    for i in range(count):
        if scores[i] >= threshold:
            result = {
                'bounding_box': boxes[i],
                'class_id': classes[i],
                'score': scores[i]
            }
            results.append(result)
    return results

如果我们将上述函数应用于一个整形的图像(与分类示例中使用的相同),我们应该得到:

太好了!在不到 200 毫秒的时间内,以 77%的概率,在由“边界框”界定的区域上检测到 id 为 16 的物体:(0.028011084,0.020121813,0.9886069,0.802299)。这四个数字分别与 ymin、xmin、ymax 和 xmax 相关。

考虑到 y 从顶部(ymin)到底部(ymax ), x 从左侧(xmin)到右侧(xmax ),如下图所示:

图片来源:作者创作

边界框有四个值,实际上,我们有左上角和右下角的坐标。有了两边,知道了图片的形状,就有可能画出物体周围的矩形。

接下来,我们应该找出 class_id 等于 16 意味着什么。打开文件 coco_labels.txt,作为一个字典,它的每个元素都有一个相关联的索引,检查索引 16,我们得到了预期的' cat '概率是从分数返回的值。

让我们创建一个通用函数来检测单个图片上的多个对象。第一个函数从图像路径开始,将执行推理,返回调整后的图像和结果(多个 id,每个 id 都有其分数和边界框:

def detectObjImg_2(image_path, threshold = 0.51):img = cv2.imread(image_path)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    image = cv2.resize(img, (width, height),
                       fx=0.5,
                       fy=0.5,
                       interpolation=cv2.INTER_AREA)
    results = detect_objects(interpreter, image, threshold)return img, results

有了整形后的图像和推断结果,下面的函数可用于在对象周围绘制一个矩形,为每个对象指定其标签和概率:

def detect_mult_object_picture(img, results): HEIGHT, WIDTH, _ = img.shape
    aspect = WIDTH / HEIGHT
    WIDTH = 640
    HEIGHT = int(640 / aspect)
    dim = (WIDTH, HEIGHT) img = cv2.resize(img, dim, interpolation=cv2.INTER_AREA) for i in range(len(results)):
        id = int(results[i]['class_id'])
        prob = int(round(results[i]['score'], 2) * 100)

        ymin, xmin, ymax, xmax = results[i]['bounding_box']
        xmin = int(xmin * WIDTH)
        xmax = int(xmax * WIDTH)
        ymin = int(ymin * HEIGHT)
        ymax = int(ymax * HEIGHT) text = "{}: {}%".format(labels[id], prob) if ymin > 10: ytxt = ymin - 10
        else: ytxt = ymin + 15 img = cv2.rectangle(img, (xmin, ymin), (xmax, ymax),
                            COLORS[id],
                            thickness=2)
        img = cv2.putText(img, text, (xmin + 3, ytxt), FONT, 0.5, COLORS[id],
                          2) return img

下面是一些结果:

图片来源:作者创作

完整的代码可以在 GitHub 找到。

使用摄像机的目标检测

图片来源:树莓派基金会

如果您有一个连接到 Raspberry Pi 的 PiCam,则可以使用之前定义的相同功能,逐帧捕捉视频并执行对象识别。如果您的 Pi: 中没有可用的相机,请遵循本教程开始使用相机模块

首先,必须定义相机要捕捉的帧的大小。我们将使用 640x480。

WIDTH = 640
HEIGHT = 480

接下来,你必须校准摄像机:

cap = cv2.VideoCapture(0)
cap.set(3, WIDTH)
cap.set(4, HEIGHT)

并循环运行下面的代码。在按下“q”键之前,摄像机会一帧一帧地捕捉视频,并绘制带有相应标签和概率的边界框。

while True: timer = cv2.getTickCount()
    success, img = cap.read()
    img = cv2.flip(img, 0)
    img = cv2.flip(img, 1) fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer)
    cv2.putText(img, "FPS: " + str(int(fps)), (10, 470),
                cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    image = cv2.resize(image, (width, height),
                       fx=0.5,
                       fy=0.5,
                       interpolation=cv2.INTER_AREA)
    start_time = time.time()
    results = detect_objects(interpreter, image, 0.55)
    elapsed_ms = (time.time() - start_time) * 1000 img = detect_mult_object_picture(img, results)
    cv2.imshow("Image Recognition ==> Press [q] to Exit", img)if cv2.waitKey(1) & 0xFF == ord('q'):
        breakcap.release()
cv2.destroyAllWindows()

下面可以看到树莓 Pi 屏幕上实时运行的视频。注意视频运行在 60 FPS(每秒帧数)左右,相当不错!。

下面是上述视频的一个截屏:

图片来源:作者创作

完整的代码可以在 GitHub 上找到。

姿态估计

人工智能更令人兴奋和关键的领域之一是估计一个人的实时姿势,使机器能够理解人们在图像和视频中做什么。在我的文章使用 TensorFlow2.x 进行实时多人 2D 姿势估计中深入探讨了姿势估计,但在这里的边缘,使用 Raspberry Pi 并在 TensorFlow Lite 的帮助下,可以轻松复制在 Mac 上完成的几乎相同的操作。

我们将在这个项目中使用的型号是 PoseNet 。我们将以与图像分类和对象检测相同的方式进行推理,其中图像通过预先训练的模型输入。PoseNet 带有几个不同版本的模型,对应于 MobileNet v1 架构和 ResNet50 架构的变化。在这个项目中,预训练的版本是 MobileNet V1,它比 ResNet 更小,更快,但不如 ResNet 准确。此外,有单独的模型用于单人和多人姿势检测。我们将探索为一个人训练的模型。

在这个站点中,可以使用现场摄像机实时探索几个 PoseNet 模型和配置。

在 Raspberry Pi 上执行姿态估计的库与之前使用的相同。NumPy,MatPlotLib,OpenCV 和 TensorFlow Lite 解释器。

预训练的模型是posenet _ mobilenet _ v1 _ 100 _ 257 x257 _ multi _ kpt _ stripped . TF Lite,可以从上面的链接或者 TensorFlow Lite —姿态估计概述网站下载。模型应该保存在 models 子目录中。

开始加载 TFLite 模型并分配张量:

interpreter = tflite.Interpreter(model_path='./models/posenet_mobilenet_v1_100_257x257_multi_kpt_stripped.tflite')
interpreter.allocate_tensors()

获取输入和输出张量:

input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

与我们之前所做的一样,查看 input_details,可以看到用于姿态估计的图像应该是(1,257,257,3),这意味着图像必须被整形为 257x257 像素。

让我们以一个简单的人形作为输入,这将帮助我们分析它:

第一步是预处理图像。这个特殊的模型没有被量化,这意味着 dtype 是 float32。这些信息对于预处理输入图像至关重要,如下面的代码所示

image = cv2.resize(image, size) 
input_data = np.expand_dims(image, axis=0)
input_data = input_data.astype(np.float32)
input_data = (np.float32(input_data) - 127.5) / 127.5

对图像进行预处理后,现在是执行推理的时候了,向张量输入图像并调用解释器:

interpreter.set_tensor(input_details[0]['index'], input_data)
interpreter.invoke()

一篇非常有助于理解如何使用 PoseNet 的文章是 Ivan Kunyakin 教程的姿势估计和与 TensorFlow lite 的匹配。Ivan 评论说,在输出向量中,找到关键点的关键是:

  • 热图大小为(9,9,17)的 3D 张量,其对应于 17 个关键点(身体关节)中的每一个在图像的特定部分(9,9)中出现的概率。它用于定位关节的大致位置。
  • 偏移向量:大小为(9,9,34)的 3D 张量,称为偏移向量。它用于更精确地计算关键点的位置。第三维的第一个 17 对应于 x 坐标,第二个 17 对应于 y 坐标。
output_details = interpreter.get_output_details()[0]
heatmaps = np.squeeze(interpreter.get_tensor(output_details['index']))output_details = interpreter.get_output_details()[1]
offsets = np.squeeze(interpreter.get_tensor(output_details['index']))

让我们创建一个函数,该函数将基于热图和偏移量返回包含所有 17 个关键点(或人的关节)的数组。

def get_keypoints(heatmaps, offsets): joint_num = heatmaps.shape[-1]
    pose_kps = np.zeros((joint_num, 2), np.uint32)
    max_prob = np.zeros((joint_num, 1)) for i in range(joint_num):
        joint_heatmap = heatmaps[:,:,i]
        max_val_pos = np.squeeze(
            np.argwhere(joint_heatmap == np.max(joint_heatmap)))
        remap_pos = np.array(max_val_pos / 8 * 257, dtype=np.int32)
        pose_kps[i, 0] = int(remap_pos[0] +
                             offsets[max_val_pos[0], max_val_pos[1], i])
        pose_kps[i, 1] = int(remap_pos[1] +
                             offsets[max_val_pos[0], max_val_pos[1],
                                         i + joint_num])
        max_prob[i] = np.amax(joint_heatmap) return pose_kps, max_prob

使用上述函数以及从输出张量提取的热图和偏移向量,图像推断的结果,我们得到:

得到的数组显示了关于关节在 257×257 像素的图像上的位置的所有 17 个坐标(y,x)。使用下面的代码。可以在调整大小的图像上绘制每个关节。作为参考,数组索引已被标注,因此很容易识别每个关节:

y,x = zip(*keypts_array)
plt.figure(figsize=(10,10))
plt.axis([0, image.shape[1], 0, image.shape[0]])  
plt.scatter(x,y, s=300, color='orange', alpha=0.6)
img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(img)
ax=plt.gca() 
ax.set_ylim(ax.get_ylim()[::-1]) 
ax.xaxis.tick_top() 
plt.grid();for i, txt in enumerate(keypts_array):
    ax.annotate(i, (keypts_array[i][1]-3, keypts_array[i][0]+1))

结果,我们得到了图片:

图片来源:作者创作

太好了,现在是时候创建一个通用函数来绘制“骨骼”,这是关节的连接。骨骼将被绘制为线条,这些线条是关键点 5 到 16 之间的连接,如上图所示。独立圆将用于关键点 0 至 4,与头部相关:

def join_point(img, kps, color='white', bone_size=1):

    if   color == 'blue'  : color=(255, 0, 0)
    elif color == 'green': color=(0, 255, 0)
    elif color == 'red':  color=(0, 0, 255)
    elif color == 'white': color=(255, 255, 255)
    else:                  color=(0, 0, 0) body_parts = [(5, 6), (5, 7), (6, 8), (7, 9), (8, 10), (11, 12), (5, 11),
                  (6, 12), (11, 13), (12, 14), (13, 15), (14, 16)] for part in body_parts:
        cv2.line(img, (kps[part[0]][1], kps[part[0]][0]),
                (kps[part[1]][1], kps[part[1]][0]),
                color=color,
                lineType=cv2.LINE_AA,
                thickness=bone_size)

    for i in range(0,len(kps)):
        cv2.circle(img,(kps[i,1],kps[i,0]),2,(255,0,0),-1)

通过调用该函数,我们得到了图像中身体的估计姿势:

join_point(img, keypts_array, bone_size=2)
plt.figure(figsize=(10,10))
plt.imshow(img);

图片来源:作者创作

最后但同样重要的是,让我们创建一个通用函数,以图像路径作为起点来估计姿态:

def plot_pose(img, keypts_array, joint_color='red', bone_color='blue', bone_size=1):
    join_point(img, keypts_array, bone_color, bone_size)
    y,x = zip(*keypts_array)
    plt.figure(figsize=(10,10))
    plt.axis([0, img.shape[1], 0, img.shape[0]])  
    plt.scatter(x,y, s=100, color=joint_color)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(img)
    ax=plt.gca() 
    ax.set_ylim(ax.get_ylim()[::-1]) 
    ax.xaxis.tick_top() 
    plt.grid();
    return img def get_plot_pose(image_path, size, joint_color='red', bone_color='blue', bone_size=1):    
    image_original = cv2.imread(image_path)
    image = cv2.resize(image_original, size) 
    input_data = np.expand_dims(image, axis=0)
    input_data = input_data.astype(np.float32)
    input_data = (np.float32(input_data) - 127.5) / 127.5 interpreter.set_tensor(input_details[0]['index'], input_data)
    interpreter.invoke()

    output_details = interpreter.get_output_details()[0]
    heatmaps = np.squeeze(interpreter.get_tensor(output_details['index'])) output_details = interpreter.get_output_details()[1]
    offsets = np.squeeze(interpreter.get_tensor(output_details['index'])) keypts_array, max_prob = get_keypoints(heatmaps,offsets)
    orig_kps = get_original_pose_keypoints(image_original, keypts_array, size) img = plot_pose(image_original, orig_kps, joint_color, bone_color, bone_size)

    return orig_kps, max_prob, img

此时,只需一行代码,就可以检测图像上的姿态:

keypts_array, max_prob, img  = get_plot_pose(image_path, size, bone_size=3)

本节开发的所有代码都可以在 GitHub 上获得。

另一个简单的步骤是将该功能应用于来自视频和现场摄像机的帧。我会留给你的!;-)

结论

TensorFlow Lite 是一个在边缘实现人工智能(更准确地说,是 ML)的伟大框架。在这里,我们探索了在 Raspberry Pi 上工作的 ML 模型,但 TFLite 现在越来越多地用于“边缘的边缘”,在非常小的微控制器上,在所谓的 TinyML 中。

一如既往,我希望这篇文章可以激励其他人在 AI 的奇幻世界中找到自己的路!

本文使用的所有代码都可以在 GitHub 项目上下载: TFLite_IA_at_the_Edge。

来自世界南方的问候!

我的下一篇文章再见!

谢谢你

马塞洛

探索新加坡的非法毒品——数据透视

原文:https://towardsdatascience.com/exploring-illegal-drugs-in-singapore-a-data-perspective-3716a75ee557?source=collection_archive---------31-----------------------

变更数据

用 Python 通过探索性数据分析发现保健品的好、坏、丑

所有的东西都是毒药,因为没有一样东西是没有毒性的。只有剂量才会使一件东西中毒。”― 帕拉塞尔苏斯

micha Parzuchowski 在 Unsplash 上拍摄的照片

执行摘要(又名 TL;博士)

  • 新加坡报道的大多数非法保健品都是为了增强性功能和减肥。
  • 大多数违禁药品都有中文标签
  • 最常见的剂型设计是绿色长方形胶囊
  • 最常见的 5 种掺假药物是西地那非、西布曲明、他达拉非、酚酞和利多卡因

背景和动机

贩卖假药和掺假药的有利可图的性质导致了非法保健品全球贸易的扩散。这也是由消费者对这些产品的需求增加以及购买这些产品的低成本所驱动的。明显的缺点是,食用这些来源可疑的保健品可能会给消费者带来严重的健康问题。

这些产品通常含有未声明的成分来增强效果,以吸引消费者服用。这些成分可能是有害的(尤其是在没有医疗监督的情况下服用),过量或不足剂量,被禁止或尚未被评估用于人类的安全使用。

为了更好地了解新加坡的非法保健品贸易,我决定对 HSA 健康科学局公布的非法保健品清单进行分析。

这一分析是由我与第一批企业家伙伴(Shrey Chaturvedi)的一次谈话引发的,当时我们正在讨论东南亚假药市场中需要解决的潜在问题。我决定这是一个很好的机会来做这个与我喜欢的东西相关的迷你项目——药物和数据的交叉。

第一部分—数据来源

HSA 报告的非法保健品数据库在第可供公众查看。虽然这份清单并不详尽,但它仍然是新加坡所有非法保健品交易的合理样本。

该数据集在网站上以数据表的形式呈现,并于 2020 年 8 月 15 日被访问和检索。

HSA 非法保健品数据库搜索结果截图

可用的功能如下:

数据集特征(列)和各自描述表

网站上的数据库内容被手动转录并保存为 Excel ( )。xlsx )文件的方法。然后将其导入 Jupyter Notebook,以便使用 Python 3 进行进一步分析。

我在国外度假时遇到过街头假药小贩,我最初的假设是这些假药主要是生活用品。特别是,最畅销的可能是针对成年男性的壮阳药。

第二部分—数据清理

在撰写本文时,HSA 非法保健品数据库中记录了总共 245 种报告的非法保健品。

在“剂型”栏中具有空值的所有 54 行都与“产品说明”栏中显示的片剂相关联。因此,这些空值被填入“片剂”作为剂型条目,从而创建了以前未使用的“片剂”新剂型类别。最终数据集中每一列的 null 值的计数如下所示:

每列的空值的频率计数

形状和颜色的值主要是由于包装成小瓶和瓶子的产品,与通常的口服片剂或胶囊相比,它们更难表征。

鉴于“剂型标记备注”一栏中存在大量缺失数据(即 61.2 % NA ),因此本次分析中省略了对产品标记的审查。

有 13 种产品的剂型注明为“药丸”,这是一个不具参考价值的分类。手动审查产品图像,以确定其确切的剂型(即片剂或胶囊)。

第三部分——探索性数据分析的见解

现在是分析的主要部分,即观察到的模式和发现。

(一)产品描述

产品说明给出了产品的名称,以及一些有用的(尽管是简短的)关于消费者预期用途的信息。鉴于我们在这里处理的是文本字符串,使用单词云生成器(带有 Python WordCloud 库)来说明这些描述中的文本频率是一个好主意。

在删除无信息的停用词(例如,“品牌”、“胶囊”、“胶囊”(中文意思是胶囊)“药片”)后,产生了以下词云:

产品描述全字云

很明显,这些单词大多是汉字的罗马化(即汉语拼音)。这表明许多产品主要以中文标注,解读这种全词云并不是理解这些产品本质的最佳方式。

鉴于单词 cloud 暗示了汉字的高出现率,那么看看在其产品描述中包含汉字的非法保健品的比例将是有趣的。

产品说明中含有汉字的非法保健品比例

可以看出,违禁药品清单以中文标注的产品为主(73.5%)。这可能意味着要么中国人是非法毒贩的主要目标群体,要么这些产品主要来自中国。

The next step is to generate a Chinese character word cloud. This was done by first using regular expression (regex) to extract all Chinese characters from the ‘Product Description’ column, and using Python’s jieba library to tokenize these Chinese characters. With certain Chinese stop words removed (e.g. 胶囊), the WordCloud library was used once again to generate a word cloud:

产品描述中包含汉字的产品词云

有了这个中文词云,就更容易理解非法保健品的本质了。

  • Finding 1
    The word America (‘美国’) occurs frequently, implying that dealers tend to market their counterfeit drugs as products of USA, likely to falsely augment its appeal, quality and legitimacy towards consumers. This assertion was confirmed when I looked at these specific products containing ‘美国’, and found these products to be branded with phrases like ‘America Warrior’ and ‘America Viagra’. Another country observed in the word cloud is Germany (‘德国’), meaning that drugs produced in Germany are also associated with strong branding.
  • Finding 2
    The two most common claims made by these health products relate to sexual performance and male genitalia (‘牛鞭’, ‘升阳’, ‘延时’, ‘魔根’), and weight loss (‘减肥’, ‘瘦身’). This is further supported by other frequently occurring nuanced words associated with sexual vitality (‘金聖力’, ‘战神’, ‘动力’, ‘天雄’, ‘神威’).
  • Finding 3
    There are several common words associated with dragon (‘龙牌’, ‘天龙’), which is not out of the ordinary since the dragon traditionally symbolizes potent and auspicious powers in Chinese culture.
  • Finding 4
    While drug names are not commonly mentioned in the Chinese descriptions, there is one obvious branded name that appeared frequently, which is Viagra (‘威哥’, ‘伟哥’).

分析不含任何中文字符的其他产品也很重要,这些产品占该非法药物数据集的 26.5%。删除英语和马来语停用词(如 Kapsul、Obat)后,生成的词云如下所示:

产品描述中无汉字的产品的词云

与之前看到的贴有中文标签的产品类似,这些产品似乎也是为男性减肥和增强性功能而销售的。这可以从英语词汇(如“男性”、“性”、“苗条”、“体重”)以及一些暗示性的马来语词汇(如“Kuat”(强壮)、“Untuk Pria”(男性)、“Tongkat Ali”(一种用于治疗勃起功能障碍的草药)中观察到。所有这些见解都支持早期的假设,即性增强药物是正在交易的主要假冒产品。

  • 发现 5 单词 cloud exploration 的另一个发现是马来语短语‘Asam Urat’的出现,它在英语中的意思是尿酸。血液中高水*的尿酸是导致痛风的原因,马来语中尿酸的频繁出现表明市场上也有许多用于痛风治疗的假冒产品。

(ii) 剂型

这些非法保健品大多是口服固体剂型,即胶囊和片剂。

剂型的分发

这并不奇怪,因为口服制剂具有许多优点,例如:

  • 易于制造、包装和运输
  • 良好的化学和物理稳定性
  • 生产成本相对较低
  • 为消费者提供简单准确的剂量

(iii) 剂型颜色和形状

由于白色通常是口服药物最常见的颜色,所以看到白色也是这些非法保健品的主要颜色也就不足为奇了。接下来最常见的三种颜色恰好是红、蓝、绿的标准原色。

剂型颜色分布

就剂型形状而言,主要形状为长方形

剂型形状的分布

单独看上面的图表,你可能会认为最常见的设计是白色长方形胶囊。然而,我们应该从剂型、颜色和形状的组合顺序来看待它。由此可见,最常见的剂型设计实际上是一种绿色椭圆形胶囊,而不是白色胶囊。

十大最常见的剂型设计

下面是一个绿色长方形胶囊的例子:

(四)剂型标记

可以看出,这些非法保健品绝大多数(60.6%)上面没有任何标识。这使得确定这些药物的具体身份以及区分假冒产品和真产品变得更加困难。

带有和不带有标记/雕刻的产品分配

(v) 掺杂物

掺假物是保健品中未被发现和未经批准的强效药物成分,这些掺假物是这些假冒产品被视为非法的主要原因。

由于意外误用、过度使用或与其他药物、潜在健康状况或补充剂中的其他成分相互作用,这些掺假物会导致严重的不良健康影响

下表列出了这些非法产品中最常见的 10 种掺杂物。

非法保健品中发现的 10 大掺假物

现在是时候介绍一些药理学知识了,描述一下上表中的五大掺假者。

①西地那非
T5 是什么?
西地那非是非法保健品中最常见的掺杂物。西地那非是伟哥(商品名)中发现的活性化合物的通用名,用于治疗勃起功能障碍(ed)。

趣闻:西地那非最初是为治疗肺动脉高压和心绞痛(心脏病引起的胸痛)而开发的。然而,在临床试验中,研究人员发现该药物在诱导勃起方面比治疗心绞痛更有效。

副作用:虽然大多数副作用通常是轻微的(如脸红、头痛),但有可能出现更严重的反应,如视力丧失、阴茎异常勃起(持续而痛苦的勃起)和严重低血压。当消费这些假冒产品时,这些风险肯定会被放大,其中所含的剂量监管不力。

(2)**西布曲明 什么东西?**西布曲明是一种用于减肥的化合物。这支持了之前收集的观点,即减肥是非法保健品的常见目标。西布曲明通过增加产热并使使用者在饭后有饱腹感来发挥作用,它主要在肥胖患者群体中进行研究。

副作用:已知它与心血管事件风险增加有关,如心脏病发作、中风和高血压。**

(3)**他达拉非 是什么?与西地那非(即磷酸二酯酶-5 酶抑制剂)属于同一药物类别,他达拉非也用于治疗 ed,并与西地那非具有许多相似的特征。它的品牌名是 Cialis。

(4)酚酞 是什么?酚酞是一种泻药,常见于掺假减肥产品中。多种含有酚酞和西布曲明的膳食补充剂此前已被美国美国食品药品监督管理局(FDA) 召回,原因是它们未经批准包含在补充剂中。

****副作用:接触酚酞与致癌性(即能致癌)有关。

(5)利多卡因 是什么?利多卡因是一种麻醉剂,这意味着当局部应用于皮肤或粘液表面时,它是一种用于麻醉特定身体区域组织的药物。它通常以局部产品(如喷雾剂、凝胶剂)的形式出现,由于其麻木作用而用于控制早泄。

****副作用:局部使用一般有轻微的副作用,如瘙痒/发红,但非法产品的潜在劣质可能会导致意想不到的过敏/过敏皮肤反应。

从这里,我决定更仔细地观察这些含利多卡因的产品,以证实我的假设,即所有含利多卡因的补充剂都是局部剂型。

含利多卡因产品的剂型分布

尽管最常见的剂型确实是用于局部应用的东西(外用液体),但我惊讶地发现还有相当多的口服胶囊和片剂产品也含有利多卡因,特别是因为利多卡因不是用于口服的。这当然是值得深入研究的事情。

接下来的步骤

该分析对新加坡非法保健品贸易中观察到的趋势和模式提供了一些见解,对 HSA 等当局可能有价值。例如,通过了解常见的营销主张和非法经销商针对的主要人群,可以开展专门策划的教育活动来提高认识,以便公众了解如何更好地保护自己。

能够访问更多数据(如购买地、生产国、报告日期、商贩/消费者概况等)。)也将有助于使这种分析在处理这种非法产品的兜售方面更有见地和有用。

收拾东西

事实上,区分真货和假货是非常具有挑战性的。因此,友好的药剂师会给你一些建议:一定要从注册的医疗机构、诊所和药店购买药物和保健品。如果您确实遇到有人兜售此类非法产品,您可以通过电话(6866 3485)或电子邮件((hsa_is@hsa.gov.sg)向 HSA 执法部门举报

期待听到大家对以上分析的反馈。如果您想要一份代码副本,或者希望讨论更多关于该审查的内容,请随时在 LinkedIn 上给我留言!

特别感谢 辜*雄 分享他对分析的反馈

在你走之前

欢迎您加入和我一起踏上数据科学学习之旅!点击此媒体页面,查看我的 GitHub ,了解更多精彩的数据科学内容。同时,享受探索药物和数据科学的交集吧!

参考书目

探索图像处理技术— OpenCV

原文:https://towardsdatascience.com/exploring-image-processing-techniques-opencv-4860006a243?source=collection_archive---------2-----------------------

一些图像处理功能概述—利用 OpenCV-4.2.0 和 Python

Matteo VistoccoUnsplash 上拍摄的原始照片

我图像处理是属于计算机视觉的知识领域。机器学习的前提首先由计算机视觉理论奠定,应用一整套技术来处理和分析图像数据,以提取计算机和机器可能用于广泛应用的有价值的信息,例如:

  • 拼接:将重叠的照片变成无缝的全景图
  • 变形:通过*滑过渡改变或合并不同的图片来创建新的图片
  • 3D 建模:将 2D 快照转换成 3D 合成
  • 人脸检测:识别数字图像中的人脸
  • 视觉认证:坐在网络摄像头前,自动将家人登录到电脑或手机上

Vision 的预期目的是利用可靠的模型,从最简单和最基本的构建块中重建复杂、丰富多彩和生动的三维世界,这些模型有助于以可评估的方式解释图像。

预处理或图像处理是计算机视觉中的前一步,目标是将图像转换成适合进一步分析的形式。曝光校正、色彩*衡、图像降噪或提高图像锐度等操作非常重要,并且在大多数计算机视觉应用(如计算摄影甚至人脸识别)中需要非常小心才能获得可接受的结果。

在本文中,我打算利用一个非常流行的计算机视觉库 OpenCV 来介绍一些常用的图像处理技术。我将尝试简要描述每个操作是如何工作的,并更注重更实际地处理这个主题,为您提供您需要的所有代码,以便您对这些材料有亲身体验。

下面给出的图像将用于我们的实验。

照片由凯尔西·加森Unsplash 上拍摄

概述:

  1. 计算机视觉中的图像
  2. 颜色:RGB 表示
  3. 像素转换
  4. 直方图均衡
  5. 回旋

我在 Google Colab 笔记本中包含了本教程的所有代码,因此您可以继续学习。

[## 谷歌联合实验室

编辑描述

colab.research.google.com](https://colab.research.google.com/drive/1c9SsagyzeFWgWzN9O-dpj5m3Ds4qOT2F?authuser=1)

注意:在开始之前,您应该在 windows 中配置一个 Anaconda 环境来使用 OpenCV。对于那些可能没有所需设置的人,我建议你看看我的文章,关于如何在 windows 10 中用 python 安装和配置 OpenCV-4.2.0,否则这个教程的代码将无法使用。

计算机视觉中的图像

计算机视觉中的图像被定义为代表每个图像像素中离散颜色或强度值的数字矩阵。每幅图像都被视为可以以多种方式显示的输入数据,无论是像素值数组还是表示像素强度分布的多维图。图像可以用三个通道(蓝色、绿色和红色)的彩色分层、像素值从 0(黑色)到 255(白色)的灰度以及仅描绘黑色或白色值(0 或 1)的二进制渲染。

原始照片由 Dim 7Unsplash 上拍摄

图像基本上是以不同强度显示的数字块:

像素化图像,致谢:从图像数据中提取特征的技术

颜色:RGB 表示

颜色空间由三个不同的通道红、绿、蓝表示。每个通道都源于人类视觉的所谓三色本性,因为我们有三个独立的感光体,每个感光体都选择性地对色谱的不同部分做出反应。在每通道 8 位的 RGB 系统中,三原色相加产生 16.777.216 种不同的颜色。

在 OpenCV 中,图像被转换成多维数组,这大大简化了它们的操作。例如,灰度图像被解释为像素从 0 到 255 变化的 2D 阵列。

原始图像的灰度版本

彩色图像稍微复杂一些,因为我们处理的是 3D 阵列,其中每个像素都在三个不同的颜色通道中呈现。将原始图像分割成蓝色、绿色和红色分量,以掌握颜色分层结构是如何工作的,这将是很有趣的。我们将使用两个基本的 OpenCV 方法来实现:

  • split(src, dests):分割多维数组。
  • mixChannels(srcs, dest, from_to):合并不同的频道。

如果我们打印结果通道的形状,我们会看到尺寸已经缩小到 1。每个通道都包含图像的 RGB 分量,但它是以一维灰度格式渲染的。

将图像拆分到其通道中

将每个通道放大到 3D 阵列将呈现所需的颜色。对于这种用法,mixChannels()派上了用场。

混合各个通道并显示蓝色、绿色和红色版本

像素转换

应用于图像的最简单类型的操作是那些输入是像素并且对应的输出也是像素的操作。点运算符,也称为点运算符,被建模为获取一个或多个输入图像并产生输出图像的函数。在连续域中,它们可以表示为:

对比度调整

例如,我们可以应用局部点运算符来调整图像的对比度和亮度。将单个图像像素乘以一个常数并添加一个偏差,将使图像或多或少变亮,对比度或多或少变得明显。

对比度调整示例

直方图均衡

绘制像素强度分布,我们可以看到一组图像的亮度值。因此,我们可以识别和纠正图像中最暗的区域,使其看起来更有吸引力。但真正的目标是找到一种自动化的过程,将光线均匀地分布在整个图像上,而不必逐个区域、逐个像素地检查。更明确地说,我们应用一个变换函数来将最频繁的亮度值均匀地分布在整个图像上。

首先,我们需要绘制一个直方图,显示颜色通道的强度分布:

直方图分析图

我们可以在直方图中区分两个区域:

  • 区域 1 :连续且相当相等的值,没有突变。我们在 CDF 图中观察到这些值的线性增长。
  • 区域 2 :图片达到高亮度值,这意味着范围值[230,250]被超过 62%的像素广泛表示。

直方图揭示了一个有趣的点:我们的图像的像素值被限制在某个特定的强度范围内(在 230 和 255 之间),因此图像在特定的中心区域更亮,而忽略了其他区域。

应用均衡公式有助于将受限区域拉伸到任一直方图边界。这些值被扩展到最大值,以改善图像闪电。

应用于原始图像的直方图均衡化公式

我们还可以查看新均衡图像的累积分布频率:我们观察到强度值的线性趋势增长,这意味着像素强度现在在图像中均匀分布,并且集中高强度 pic 的区域更有可能消失。

最后,我们可以在均衡的输出图像中看到,我们已经启发或揭示了在原始图像中暗淡的新区域。

回旋

卷积是邻域操作符的集合,其操纵局部图像区域以产生预期的变换。从数学上来说,卷积两个函数会产生第三个函数,表示一个函数的形状如何被另一个函数修改。在图像处理中,每个卷积都是用特定变换的特定核来实现的。

卷积的例子,信用:丹尼尔吉菲

卷积例子有:

  • 图像过滤应用 2D 卷积,采用各种低通和高通滤波器,帮助去除噪声、模糊图像等。
  • 图像梯度使用高斯滤波器和特殊内核进行图像边缘和轮廓检测。这种核的例子是拉普拉斯导数、索贝尔导数、沙尔导数等。

图像渐变

图像梯度技术提供了关于图像组成的非常有用的信息。梯度图像的每个像素测量原始图像中相同像素在给定方向上的强度变化。有了像素信息,我们观察到具有大梯度值的像素成为可能的边缘。因此,一些众所周知的边缘检测算法,如 Canny 边缘检测器,广泛使用梯度图像来提取轮廓。

拉普拉斯衍生物

图像的拉普拉斯算子突出了快速亮度变化的区域,它被广泛用作边缘检测的前一步。操作员通常将单个灰度图像作为输入,并生成另一个灰度图像作为输出。

拉普拉斯导数适用于 2D 函数,在我们的上下文中,我们微分的函数表示输入图像的灰度版本的像素强度值。灰度图像可以被认为是提供像素强度输出的两个输入(x 代表宽度,y 代表高度)的函数。

灰度图像的 3D 绘图,原始照片由米卡Unsplash 上拍摄

拉普拉斯导数公式也可以表示为具有特定值的 3×3 核:

拉普拉斯解析公式

应用于原始图像的拉普拉斯滤波器示例:

拉普拉斯变换

灰度和彩色图像输入的拉普拉斯滤波结果

总结想法

在本教程中,我们遇到了一些有趣的图像处理技术,解释了一些背后的理论,并提供了利用领先的计算机视觉库 OpenCV 的实践经验。

OpenCV 有大量的在线 T4 文档,在那里你可以学到更多的计算机视觉技术,比如特征检测和描述、计算摄影、物体检测等等。大部分内容以很酷的教程的形式呈现,鼓励你快速开始编码,并以一种有指导意义的方式体验这些材料。

我还建议你阅读 计算机视觉应用与算法 这是一本全面的书籍,它从科学和数学的角度很大程度上解释了所有关于图像处理和计算机视觉的理论。

另一篇值得一读的有趣文章是什么样的图像处理技术实际应用于 ML 行业Neptune . aibyAigiomawu Ehiaghe。它说明了如何利用图像处理技术来增强现实世界行业中的计算机视觉模型。

** [## ML 行业实际使用的图像处理技术有哪些?- neptune.ai

处理可用于提高图像质量,或帮助您从中提取有用的信息。这是…

海王星. ai](https://neptune.ai/blog/what-image-processing-techniques-are-actually-used-in-the-ml-industry)

如果你喜欢这篇文章,请随时与你的朋友分享。可以看看 Github 里的项目。

[## aymanehachham/图像处理-OpenCV

图像处理操作利用 OpenCV-4 . 2 . 0-aymanehachham/Image-Processing-OpenCV

github.com](https://github.com/aymanehachcham/Image-Processing-OpenCV)**

探索基巴纳

原文:https://towardsdatascience.com/exploring-kibana-ae8a770e0303?source=collection_archive---------20-----------------------

可视化和分析 Elasticsearch 索引日志文件的通用工具

这些年来,基巴纳越来越受欢迎。大多数公司依靠 Kibana 强大的可视化和分析功能从每分钟生成的大量日志结果中进行推断。web 服务器生成日志包含有关系统使用、请求时间、请求位置和搜索字符串的重要数据。Kibana 使得实时分析这些数据变得轻而易举。

Kibana 是一个开源的、基于网络的数据可视化和分析工具。它可视化了由 Elasticsearch 框架索引的搜索输出。它是由 Elasticsearch 和 Logstash 以及 Kibana 组成的 ELK 堆栈的一个组成部分。Elasticsearch 是一个开源搜索引擎,用于实时存储、搜索和分析大量数据。它是几个搜索框架的核心。Logstash 用于收集和监控来自不同来源的日志。它充当了 Elasticsearch 的数据管道。这三个工具一起提供了一个伟大的开源*台来监视、可视化和分析日志数据。

本文旨在回答一些关于 Kibana 的常见问题。首先,有没有想过这个独特的名字“基巴纳”是如何产生的?基巴纳的创造者拉什德·卡汉想用外语为他的创新取一个朗朗上口的名字。他想选择一个与该应用程序功能相*的名称,即可视化日志数据。他认为最接*的是“木屋”,谷歌在斯瓦希里语中将其翻译为“基巴纳”。

为什么是基巴纳?

开源且易于设置 : Kibana 的 USP 在于它是开源的且易于设置/使用。每个人都可以轻松设置和访问仪表板和报告。您只需要将您的 web 浏览器指向 Kibana 设置为默认端口 5601 的机器。它也可以托管在其他端口上。

强大的可视化 : Kibana 提供了大量的可视化选项,如图表、直方图、条形图、热图、饼图和区域图,以快速分析数据。Kibana 的数据可视化能力不仅仅局限于数字。它还可以分析不同的数据类型,如文本和地理空间数据。

交互式仪表板:Kibana 的仪表板特性使报告和演示变得非常简单和吸引人。可视化可以根据添加的过滤器进行定制,从而使仪表板具有交互性。对数据的任何更改都会自动反映在仪表板中。

报告:使用 Kibana dashboard 可以生成详细而有见地的报告。该报告可以下载并以不同的格式使用,如 PDF 和 DOC。

基巴纳的积木

Kibana 的功能分为两大类:

可视化和探索数据 —在这里您可以找到各种工具来探索、分析和可视化数据中的模式。您也可以创建仪表板和演示文稿。你也可以为分析后的数据建立机器学习模型。Canvas 是 Kibana 中另一个很棒的可视化和表示工具。它可用于可视化来自 Elasticsearch 的实时数据。Data Visualizer 是基本 Kibana 许可的一部分,它为生成的最大 100 MB 的日志提供异常检测功能。这有助于了解更多的数据,并以自动化的方式发现异常。

管理弹性栈 —在这里可以配置安全设置,实时监控和跟踪弹性栈,组织工作空间。通过控制台,用户可以向 Elasticsearch 发送请求,并查看他们的请求历史。您可以使用索引模式 UI 创建新的索引模式和管理现有的模式。基于索引模式,将从 Elasticsearch 检索数据。

基巴纳积木

在数据操作和导出数据方面,Kibana 几乎没有限制。它不能聚合包含嵌套对象的字段。从保存的仪表板或报告中导出数据时存在约束。只能导出屏幕上当前可见的数据。

总体来说,Kibana 是一个用户友好的工具,可以快速可视化和分析巨大的日志文件。开源和配置为与 Elasticsearch 合作增加了它的受欢迎程度。Kibana 正在不断升级,并承诺未来会有更多有趣的功能。有关基巴纳的详细信息,请参考,https://www.elastic.co/kibana

探索肯尼亚信用评分农民的机器学习解决方案

原文:https://towardsdatascience.com/exploring-machine-learning-solutions-for-credit-scoring-farmers-in-kenya-8fb653db4b08?source=collection_archive---------16-----------------------

图片由 SunCulture 提供,经许可使用。

介绍

本文涵盖了 SunCulture 的一个数据科学项目,SunCulture 是一家位于肯尼亚内罗毕的太阳能初创公司,为小农户提供太阳能水泵、电视和照明。

它强调了我们在项目中探索的不同途径,哪些可行,哪些不可行,以及我们在这个过程中学到了什么。我们希望本文包含的信息能够帮助其他在非洲从事融资工作的公司从我们的经验中学习。

非洲的小规模农民通常被传统银行部门忽视,他们的融资选择非常少。但是怎么知道他们会不会还钱呢?传统的信用评分使用过去的信用记录作为主要指标,但对于许多 SunCulture 客户来说,这些信息是不可用的。

我们提议使用物联网 (IoT)数据源的组合,包括土壤传感器和灌溉系统的水泵使用情况,这些数据已经可供该公司使用。

在 7 个月的时间里,我的任务是探索使用传感器数据进行信用评分的解决方案。这个想法是创建一个算法,根据他或她的物联网传感器数据作为输入,输出农民违约的概率。用专业术语来说,这是一个时间序列分类的问题。

时间序列数据一直是金融服务的主要兴趣,现在随着实时应用的兴起,零售和编程广告等其他领域正在将注意力转向时间序列数据驱动的应用。

在过去的几年中,云服务的几个主要参与者已经发布了用于处理时间序列数据的新产品。因此,理解机器学习在这个新兴领域中的作用和潜力是非常有趣的。

我们将谈论一个失败的第一次尝试,它引导我们探索解决方案空间。随着试验数量的增加,我们发现需要组织试验管理数据集。最后,在任务结束时,我们意识到处理我们数据的一个显著特征的重要性:低违约率。我将从介绍农民开始,因为我很幸运地认识了他们,并进行了实地考察:

会见农民

当我联系到 SunCulture 的首席技术官和联合创始人查尔斯·尼科尔斯时,我正在网上寻找任务。

由于我当时恰好在肯尼亚,他们邀请我参观他们的总部,并派我去 Nanyuki 山区会见他们的一些客户(农民)。

此次实地考察的目的是了解农民面临的问题,并寻找技术解决方案。

亚历克斯·吉托帮助我了解了农业的基本知识。农场成功的五大标准是:

  • 土壤肥力,由存在的养分来衡量
  • 水特征
  • 水的供应量
  • 土地的面积
  • 种植作物的市场价值。

我和一位新农民 Patrick Ngetha 聊了聊,他向我解释了他在 T2 的财务问题。市场价格和收获结果都存在很大的可变性和不确定性,例如由虫害造成的。这些收入在一年中不定期地出现几次。

他经营的主要成本是购买种子和支付工人工资。农民需要从公司购买高质量的种子,否则蔬菜找不到市场。

工人们需要在收获季节,也就是销售收入到来之前得到报酬,这进一步增加了现金流的压力。

他有潜力扩大自己的农场,目前农场面积约为半英亩,但他缺乏资金。

他试验了不同的作物,我的向导、阳光栽培农学家亚历克斯·吉陶(Alex Gitau)相信他有必要的技能将他的活动提升到一个新的水*。然而,他无法从银行获得资金。

实地考察并意识到该项目具有巨大的社会影响潜力是非常有意义的。所以我很有动力从我们的第一个模型开始。

我们的第一个架构:TimeNet 有一个艰难的开始

TimeNet 是由 P. Malhotra 等人在论文中介绍的深度学习模型: TimeNet:用于时间序列分类的预训练深度递归神经网络。这是一种无监督的方法,通俗地说,它将原始传感器数据转换成一个更小的汇总向量。然后,我们使用经典的机器学习方法,在我们的情况下是逻辑回归,来基于概要进行最终分类。

听起来很简单?嗯,我们有很多问题。

最主要的一点是让模型真正收敛。经常发生的是,在一次进行得相当顺利的训练中,模特突然“忘记了一切”。这在训练递归神经网络时相当频繁,被称为梯度爆炸

为了解决这个问题,我们尝试扩展我们的计算能力,并开始在多个 GPU 实例上进行培训。在整整一个月和大约 15 次实验后,我们最终放弃了,因为这种设置无法正确地对单个贷款违约进行分类。

为什么 TimeNet 不起作用?这是一个太多的研究模型,没有足够的数据可供学习。

探索解决方案空间

然后,我们继续使用深度神经网络在时间序列分类中提出的模型:来自王志广等人的强大基线。这是一篇更受欢迎的文章(从大约 500 次引用中可以看出),并且附带了它所介绍的三个模型的代码。此外,训练他们的模型非常简单,这意味着收敛会很容易。

我们用他们的 ResNet 模型开始训练。不幸的是,第一次运行没有成功,很可能是由于我们的时间序列的长度。它们比文章中探讨的大多数都要长。

像 ResNet 这样的卷积模型有一个“模式大小”,称为感受域,这是它们可能检测到的最长模式的长度。例如,如果感受域是 24 小时,那么模型只能检测每天的模式,而不能检测每周的规律性。

根据我们的数据,默认 ResNet 的感受域出现了几十个小时,我们觉得这是不够的。这被证明是关键的观察。我们最终通过将感受野扩大到大约一周(使用步长卷积)得到了我们的第一个工作模型。

该模型比虚拟基线的特异性高 4 倍。

接下来的一段时间,从 11 月到 1 月,我们致力于尝试尽可能多的不同架构。

我们尝试了 14 种不同的模型。有些是最先进的,如《创意时代》中的,有些是更经典的机器学习,如 DTW ,有些是我们自己的,如 ConvRNN。

ConvRNN 的层结构显示卷积输出直接进入 RNN 层。

ConvRNN 是一种深度学习架构,由几个卷积层后跟一个递归层组成。所有图层都按顺序排列,如上图所示。这是一个端到端的模型:输入是传感器数据,最后一层的输出是默认概率。

卷积以时间序列作为输入,也产生时间序列输出。输出长度除以步距,例如步距为 2 将使长度减半。

由于存在多个连续发生的步长,我们可以实现时间序列长度的极大缩减。在某种意义上,卷积充当了智能“子采样器”。

如果传感器数据时间序列很长,这种尺寸的减小是很重要的。递归神经网络只能在短时间序列上有效训练,数量级为几百个点。

如果在原始数据上训练,递归层会发散,因此需要卷积来缩短时间维度。

最后,我们注意到这个模型的感受野理论上是无限的。这是循环层的优势,它能够在长范围内组合和积累信息。正如在 ResNet 模型讨论中提到的,一个大的感受域允许我们在不同的时间范围内理解农民的行为——从几天到几个季节。

该模型在深度学习架构中具有最佳性能。最初的想法来自查尔斯·尼科尔斯。到目前为止,我们还没有在文献中看到这种架构。

选择建筑的教训是不要犹豫尝试新事物。即使有些事情以前没有做过,它仍然可以很好地工作。尽管为了简单起见,您可能仍然希望用现有的模型开始您的项目。****

组织实验

对于 14 种架构中的每一种,我们都有不同的运行和配置。在项目结束时,单独运行的总次数很容易就达到了数千次。数据科学项目的很大一部分是有效地管理它们。

每个实验,不管它是否带来了度量的改进,都需要被记录下来,以便我们可以用它来指导我们未来的决策。其中一些实验非常长,长达几天,因此我们保存了所有的关键信息,以避免以后必须重新运行。

起初,我使用了一个在线维基系统来记录实验。有一次,我们意识到我的很大一部分时间花在了记录实验上,而不是运行它们。然后我们开始使用一个名为重量&偏差的网站,这使得整个过程更有效率。

摘自《重量与偏见》的截图。在这里,我们可以看到不同模型的训练曲线绘制在同一时间线上。适用于绘图比较。

在这一点上还有其他问题:处理不断到来的新数据,版本化数据集,保持高数据质量。主要问题是必须管理两件事:快速做事,这需要固定的流程;探索解决方案空间,这需要灵活性。

管理数据

我们将讨论数据管理的三个主要方面:数据版本化、数据处理和数据调试。

数据版本控制或 DVC 是管理数据集的一个非常有用的工具。它允许控制数据的修订,就像 git 控制代码一样。

每次更新都对应于一个版本,并保留所有先前版本的可访问记录。如果数据集更新被证明是一个错误,我们可以恢复以前的版本并取消更改。所以这是一种安全网。

在分布式环境中工作使得数据管理更加困难。在我们的例子中,我们同时使用了多达 5 台不同的机器,包括笔记本电脑和云实例。

这在机器学习中很常见,其中大部分工作是在本地机器上完成的,但训练是在强大的云实例上完成的。挑战在于同步数据。

我们建立了一个 Azure blob 存储,通过 DVC 将所有数据集中起来。这就像一个在线硬盘,只要你有凭证,就可以从任何地方访问。它不仅存储当前数据,还存储所有修订数据。这个 blob 存储器实际上是我们的数据库

这允许机器通过使用推拉系统来同步和修改全局库。通常情况下,一旦工作机处理完一个数据集,就会将其更新推送到中央存储器。然后,一台训练机器可以从中央存储器中取出最新数据。DVC 使这些操作变得非常容易。

我们使用脚本进行数据处理,因为它们比笔记本更容易重用和维护。像任何 UNIX 实用程序一样,可以从命令行直接调用脚本。它们执行“文件到文件”操作,即输入数据集和处理后的数据都写入磁盘,这简化了调试。

对于数据调试,我们意识到单元测试是不充分的。如果我们不实际绘制数据,很容易遗漏数据错误。同时,数据测试对于检查数据的基本健全性是有用的,比如异常值和格式。因此,我们决定同时使用正式测试和可视化。

这方面的自然工具是 Jupyter 笔记本。每个都包含一些图,如分布直方图,并显示随机选择的传感器几天的数据。这非常有用,因为许多错误都可以通过视觉检测出来。它还将显示基本的统计数据。从某种意义上说,笔记本可以作为特定资产的快速“身份证”。

笔记本也会包含测试。通常,我们测试数据中的异常值和可能的问题。如果我们期望数据有一个特定的属性,例如*均值是 0,那么我们为它编写一个测试。

测试的有趣之处在于它们对整个数据集进行操作,而可视化通常只能显示一些样本的详细信息。

最后,笔记本会自动转换成 Markdown 格式,然后保存到 Wiki 作为文档。通过使用 Papermill 动态执行笔记本,这一过程可以变得非常高效。

处理低违约率

在项目的最后两个月,我们关注的是贷款违约数量的问题。在有数千个客户的测试集中,我们的违约数量只有几十个。这是一个不同于阶级失衡的问题,阶级失衡是一个低的违约比率,这里是一个低的总比率 r。然而,我们有很多非违约可用。

深度学习需要大量高质量的数据。很有可能这些模型在默认数以千计的情况下会做得更好。深度学习大放异彩的所有例子,比如图像识别,都使用了庞大的数据集。

我们探索了日复一日的训练。该模型的想法是查看一天的数据,并输出它是属于好的还是坏的付款人。在对每一天进行预测之后,我们汇总输出结果,给出一个全局分数。

这项技术的主要优势在于,对于每个农民,我们都有很多天的数据。本质上,默认值的数量乘以数据集中的天数。所以我们有数千个默认值,非常适合深度学习。

不利的一面是,一天的数据可能包含的信息不足以对一个农民进行评分。

由于优秀支付者的数量很大,该模型在检测优秀支付者方面非常出色。它达到了 99%的特异性(相对于虚拟基线的 95%)和 30%的灵敏度。

该模型显然能够识别大多数严肃农民的日常习惯。

很难“凭直觉”确定谁会还钱,谁不会。

时间序列数据显示,一些用户只用了一次泵,但总是按时还款。类似地,一些人在很长一段时间内非常有规律地使用他们的泵,然而却违约了。

我们与初级数据科学家 Justin Nguyen 一起分析了主要的统计变量,如泵的*均使用量和方差。

我们总共考虑了 36 个特征。令人惊讶的是,这些基本特性带来的分类能力非常小,与虚拟基线相比,性能仅提高了 30%。​

这意味着好的付款人和坏的付款人之间的区别来自使用模式,这些模式太微妙了,无法用简单的特征工程来描述。

这里的农民是在特征空间中绘制的。我们很少观察到好的和坏的付款人之间的区别。这两个轴是 PCA 的两个第一主分量。​

这项数据研究还揭示了一个有趣的模式:没有填写某些调查字段的农民更有可能违约。换句话说,缺失的信息可以改进预测模型,并且应该明确地添加到模型中。

我们也探索了不同的选择,比如自我监督学习。这是一种使用数据而不使用标签(默认或非默认)的方法。因为标签数量是我们的问题,这是一个很好的选择。它在训练时间和表现稳定性方面给了我们有趣的结果。

最后,自我监督学习和日复一日的训练都有给我们更稳定的指标的优势。由于模型是在数万天内评估的,它们的表现在统计学上非常有意义。这一点非常重要,尤其是当这些模型即将投入生产时。

****我们学到了如何处理少量违约:使用专业技术,比如自我监督学习。

结果

我们试图通过与基线比较来解释我们的结果的质量,然后展示如何应用它们。

评估机器学习项目始终是一个挑战。度量值本身没有什么意义,因为它们依赖于所使用的数据。例如,90%的准确率可能是非常好的表现,也可能是非常差的表现,这取决于任务的难度。

为了给出更准确的描述,我们通过将我们的模型结果与总是预测相同类别的简单的基线模型进行对比来讨论我们的模型结果。

这样,我们就有了一个好的付款人基线,无论他的传感器读数如何,都可以预测农民会还钱。类似地,不良付款人基线总是预测违约。

注意,一些读者可能会反对这个基线太简单。然而,仅仅从传感器数据来看,很难检测出“不良付款人”,所以这种天真的基线实际上接*人类水*的表现。此外,我们还尝试了稍微复杂一点的基线,但它们的表现并不明显。

我们根据模型的特异性敏感性来评估模型。特异性是真阳性与所有阳性的比率。直观上,高特异性(接* 100%)意味着很少有错误警报。

敏感度是所有真实病例中真实阳性的比率。直觉上,高灵敏度意味着很少有假阴性。

不良付款人分类结果

好的付款人分类结果

我们可以将这些结果用于信用归属。显然,信用归因的风险随着违约概率和贷款金额的增加而增加。

全球违约概率为 5%,但这些模型能够发现这一概率明显更高或更低的农民群体。然后,我们可以使用这些信息相应地调整贷款金额。

举个例子吧。如果好付款人分类将一个新农民归类为“好付款人”,那么我们知道违约的可能性是 1%(因为特异性是 99%),比其他人低 5 倍。

有了这些信息,我们知道风险很低,给这个农民更多的贷款是有意义的。当然,发放更多的贷款会给公司带来更大的回报。

同样,我们可以使用不良付款人模型来减少被检测为“不良付款人”的农民的贷款金额,这反过来会减少我们的*均损失。

贷款增加或减少会影响多少农民?由于敏感度在 30%左右,我们可以估计它会影响大约三分之一的客户。

结论

给小规模的非洲农民提供贷款将会使他们经济增长并改善他们的生活。这部分人在非洲大陆的总人口中占很大比例,因此很多人可能会从这种解决方案中受益。

根据传感器数据进行信用评分非常困难,因为这些数据只能间接预测金融稳定性。数据的特殊性是时间序列长,违约次数少。建立有效的解决方案必须考虑所有这些方面。从该项目中获得的三个主要的技术成果是:

  • 从代码附带的流行研究文章开始
  • 花时间找到一种有效的方法来组织实验,从数据准备到记录
  • 了解了数据的主要特征后,最先进的模型只能在与它所针对的数据相似的数据上表现良好。

我感谢阳光文化和查尔斯·尼科尔斯给我这个机会,并希望这份报告对其他人有益。我们也对微软 Airband 给予我们免费的 Azure 点数表示感谢。

探索 Python 列表的方法和技巧

原文:https://towardsdatascience.com/exploring-methods-and-tips-for-python-lists-7bae558ccb74?source=collection_archive---------51-----------------------

Python 列表非常强大💪🏻

照片由艾玛·马修斯在 Unsplash 上进行数字内容制作

上周,我开始复习 Python 的一些基础知识,并决定创建一个存储库,在那里为我修改的所有内容创建一个笔记本。这将使我能够在将来任何时候再次回顾某些话题时,都能够找到一个单独的地方。

上周我浏览了 Python 列表,这篇文章包括了笔记本中的一部分内容,突出了 Python 列表的关键功能。当我有机会浏览其他主题时,我会继续创作这些笔记本。

[## kb22/python-笔记本

该库包括一系列 Python 笔记本,描述了 Python 中几种有用的方法和技巧。…

github.com](https://github.com/kb22/python-notebooks)

反转列表— []

我们可以在 Python 列表中使用[]操作符的第三个参数来返回一个反向列表。当我们将第三个值设置为-1时,我们指示我们希望在从末尾走一步的同时遍历列表,因此是反转的列表。

long_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]long_list[::-1]# Output
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

数字列表—范围()

我们使用range()方法来实现这一点。它需要三个参数,起始值、最终值和每个值之后的增量步长。例如,如果第一个值是 0,增量步长是 10,则列表中的下一个数字是 10,然后是 20,依此类推。默认情况下,range()不生成列表,所以我们使用list()方法生成完整的列表。

list(range(0, 100, 10))# Output
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

具有相同值的列表— *

假设您想要为每个元素创建一个具有相同值的列表。您可以从单个元素列表开始,然后将列表乘以您希望该元素在新列表中出现的次数。

["element"]*5# Output
['element', 'element', 'element', 'element', 'element']

元素到字符串 join()

我们可以将列表中的各种元素组合成一个字符串。我们使用join()方法,并向它提供包含我们的元素的列表的名称。接下来是一个字符或一个字符列表,列表中的每个元素都要通过这个字符或列表进行连接。在下面的例子中,我用一个空格组合了各种元素。

separated_list = ["I", "am", "Karan"]
" ".join(separated_list)# Output
'I am Karan'

对列表进行切片— slice()

我们可以使用slice()方法来分割一个给定的列表,并从原始列表中检索某些元素。它需要起始索引、结束索引和增量步长。它也可以接受负的索引值。这个例子展示了我们如何检索一个 10 元素列表的最后 5 个元素。

long_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]last_five_elements = slice(-5, 10, 1)
long_list[last_five_elements]# Output
[6, 7, 8, 9, 10]

排序—排序()

列表有一个内置的函数,允许我们对列表中的元素进行排序。我们也可以将reverse参数设置为 True 来反转列表。

long_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]long_list.sort(reverse = **True**)# Output
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

检查列表中的存在性— any()与 all()

假设您有一个布尔列表,您想检查其中的True值。如果你想检查是否至少有一个True值存在,你可以使用any()方法,但是如果你想检查所有的值都是True,我们使用 all()。

arr = [**False**, **False**, **False**, **True**, **False**, **False**]print("At least one True - **{}**".format(any(arr)))
print("All True - **{}**".format(all(arr)))# Output
At least one True - True
All True - False

使用索引进行迭代—枚举()

enumerate()方法允许我们迭代 Python 列表,同时提取每一步的值以及元素的索引。

long_list = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]**for** index, value **in** enumerate(long_list):
    print("At index **{}**, value is **{}**".format(index, value))# Output
At index 0, value is 10
At index 1, value is 9 
At index 2, value is 8 
At index 3, value is 7 
At index 4, value is 6 
At index 5, value is 5 
At index 6, value is 4 
At index 7, value is 3 
At index 8, value is 2 
At index 9, value is 1

检查列表中元素的存在性—在

我们使用in操作符来查看一个元素是否存在于列表中。我们也可以使用not in来检查一个元素是否不存在。

long_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]1 **in** long_list
1 not **in** long_list# Output
True
False

空列表检查—不是

我们可以在列表前面使用not操作符,如果它返回 True,我们知道列表是空的。

empty_list = []**not** empty_list# Output
True

对每个元素的操作— map()

我们使用map()方法在列表的每个元素上应用一个给定的函数。这里,我定义了一个使输入值加倍的函数。

long_list = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]**def** double(x):
   **return** 2*x

list(map(double, long_list))# Output
[20, 18, 16, 14, 12, 10, 8, 6, 4, 2]

迭代多个列表— zip

zip()方法允许我们遍历多个列表,其中返回的对象是一个元组列表,其第一个元素属于第一个列表,第二个元素属于第二个列表。

list_1 = [1, 2, 3, 4]
list_2 = [5, 6, 7, 8]**for** item1, item2 **in** zip(list_1, list_2):
    print("**{}** - **{}**".format(item1, item2))# Output
1 - 5
2 - 6
3 - 7
4 - 8

结论

Python 列表非常强大,即使没有其他像numpy这样的高级库也可以非常有效。

我希望你喜欢我的作品。如果您有任何问题、建议或意见,请告诉我。

探索模型不可知解释的方法

原文:https://towardsdatascience.com/exploring-methods-for-model-agnostic-interpretation-816304cb6e71?source=collection_archive---------36-----------------------

我们预览了几种模型不可知方法背后的思想

米歇尔·卡塔利萨诺在 Unsplash 上的照片

在你的模型中建立信任的一部分可以归结为简单地理解它的工作方式。可解释性允许我们看到模型的结果以及为什么做出预测。很多时候,这些方面可能会因为一些建模策略的复杂性而丢失。

在这里,我回顾了一些关于一些模型不可知的可解释性方法的背景,包括部分依赖图,H 统计量成对交互作用,和 SHAP。这篇文章是对我和他人参考的概念的直觉练习。

讨论的主题:

  • 部分依赖图
  • H-统计成对相互作用
  • SHAP

部分依赖图

低维可视化通常提供了一种获得直观见解的便捷方式。部分相关图(PDP)是一种与模型无关的方法,用于显示特征和预测之间的关系。通过回顾 PDP 的趋势,您可以开始梳理对功能行为的理解。

PDP 通常通过散点图显示连续变量,通过条形图显示分类变量。回归部分相关值是预测结果;对于分类,预测值可以作为概率。

PDP 的工作是将我们感兴趣的特性(通常是一个或两个)的结果在指定的值范围内进行*均。我们本质上忽略了一组特性,以确定我们感兴趣的另一组特性的依赖性。然后,我们通过用*均预测值绘制我们感兴趣的特征值来构建 PDP。

为了更深入地了解 PDP,我们参考了以下内容:

f 是模型。部分相关函数 fxs 是特征集 xs 上的模型。x 是感兴趣的特征, xc 剩余的补码。它们一起构成了完整的特征空间。Pc(xc)是 xc 的概率密度

由于我们无法对 xc 的所有值进行积分,我们可以通过对给定数据集取*均值来进行估算。上面的等式简化为:

从概念上讲,我们基本上保持感兴趣的特征 xs 不变,并在补集 xc 的所有其他组合上找到预测。我们对提供的数据集中的所有预测进行*均,以获得该实例的部分相关值。在我们为 xs 中指定范围的值生成每个实例的*均值之后,我们可以图形化地生成 PDP。

特征 3(绿色)显示,对于等于 0 的基于网格的实例,所提供数据集的*均预测值为 0.11。特征 3 的总体行为显示出与模型预测的负相关,而特征 2(蓝色)通常显示出不相关。

值得注意的是,PDP 本身可能容易产生误导性结果。因为我们在寻找*均值,所以可视化丢失了一些关于构成*均值的数据分布的信息。例如,可能存在可以指示不同依赖行为的看不见的聚类。该信息不会被 PDP 捕获。

为了阐明这种隐藏的信息,个人条件期望(ICE)图通常与 PDP 相结合,以审查每个观察的预测。ICE 图基本上是 PDP 中生成的图*均值的独立分解。

在这里,我们看到两组观察结果:一组为负相关,另一组为正相关 PDP(蓝色)没有捕捉到的行为,这本身表明没有相关性

成对相互作用

特征交互效应是模型解释的另一个重要方面。某些变量对模型输出的影响会随着其他变量的值而变化。

我们有办法捕捉这类信息。例如,在线性回归、实验设计和方差分析的背景下,采用特征多项式是检测交互作用的一种常见且强大的方法。

这里的线性模型有两个特点:

通过包括第四项多项式作为成对相互作用,我们可以考虑模型对相互作用效应的依赖性。β 系数的大小和符号提供了相对重要性和贡献的指示。

线性模型具有很强的可解释性,您可以通过系数了解输出相对于要素的变化情况。然而,当模型性能不足且不满足严格的线性模型假设时,我们可以寻找替代的、模型不可知的方法来研究成对相互作用。

下面,我们讨论双向 PDP、SHAP 依赖图和交互作用的 H 统计量。

部分依赖图(双向):视觉上,上面讨论的 PDP 可以扩展到单个特征之外。相反,如果我们对两个特征感兴趣,我们可以在三维空间中显示多变量图,或者使用如下所示的等高线图来检测相互作用。这些视觉效果很好地表现了特征和模型预测方面的行为。

双向交互的样本图,其中一个特性值的变化会影响另一个特性值的变化

SHAP 依赖图:基于 SHAP 的依赖图类似于 PDP 的依赖图,因为我们能够使用视觉来显示特征和预测之间的行为。每个点都是一个观测值,相应的 SHAP 值是该特征对给定预测的附加贡献。
关于 SHAP 的更多细节将在下一节讨论。

左边的图显示了特征 1 对预测的总体正关系,具有轻微的相互作用传播。右边的图显示了特征 1 和 4 之间的相互作用(或缺乏相互作用)。在某些情况下,我们看到特征 4 中较低的值通常会产生稍强的信号

H-statistic :对比视觉方法,我们也可以使用 Friedman H-statistic 通过计算找到特征交互的实际度量。这种与模型无关的方法建立在 PDP 奠定的基础之上。统计量基本上是通过将特征对的部分相关(PD)函数(其中 PD 方程中的 xs 由相互作用对组成)与其各自的单独 PD 函数进行比较来确定的。

H 统计量为每个特征对产生一个介于 0 和大约 1 之间的分数。值 0 对应于没有交互作用,值 1 意味着输出变化仅强烈依赖于感兴趣的特征之间的交互作用。

使用上面的部分相关性 f 可以将 H 统计检验描述如下:

一个比较直观的观点是,如果该对的 PD 函数完全由各个 PD 函数部分的总和来解释,则不存在相互作用。相反,如果 PD 函数的某些部分不能用和来解释,那就表明了两者之间某种程度的相互作用。因此,该方法观察特征 A 的贡献、特征 B 的贡献以及 A 和 B 之间交互的任何附加贡献

一旦我们将上面的测试应用于我们感兴趣的特征的每个组合,输出可以帮助显示交互的相对强度。如果我们有合理数量的这些特性,我们可以选择使用表格或图表(如条形图和带注释的热图)来更直观地表示这些指标。

H-统计得分表:我们看到特征 1 和 3 具有很强的相对相互作用

虽然 H-统计量适合于检测特征关系,但是它的一个局限性是这些度量不能提供关于感兴趣特征的重要性的很多信息。强相互作用不一定意味着对模型的全面影响。作者 Friedman 和 Popescu 在第 8.1 节中提到了通过修改上述方程来解释这一点的方法。

SHAP(沙普利加法解释)

最后,SHAP 是一个更突出的和新兴的工具来处理模型解释。SHAP 值将重要性和贡献描述为要素对结果贡献的总和。特别是核 SHAP 方法产生了一种模型不可知的方式来解释为什么模型会做出某种预测。下面是一个温和的讨论 SHAP 的概念。

Shapley 值: SHAP 以 Shapley 值为基础,它起源于合作博弈论。Shapley 值寻求按特征公*分配预测贡献。其应用的一个常见例子是想象一个需要容纳不同飞机的机场。因为每架飞机需要不同长度的跑道,Shapley 值将是一个解决方案,根据相对要求在它们之间合理分配总成本。

Shapley 值可描述如下:

n 是特征的数量。s 是没有感兴趣特征 I 的子集特征。f 是模型

要打破上面的等式:

  • A 项是当引入 i 时,每个个体特征 i 对总体预测的贡献。
  • 术语 B 通过在引入特征 i 之前和之后将特征组合在一起的不同方式来衡量术语 A。B 中的第一项是出现在 i 之前的特征排列,第二项是出现在之后的排列。
  • C 项是所有特性的*均值。

最终值是感兴趣的要素对结果的*均边际贡献。

在高层次上,Shapley 值背后的概念是通过比较将感兴趣的特征引入模型时所有可能排序的结果变化来捕捉重要性和贡献。

SHAP: 耦合特征独立性和局部模型线性的进一步条件,可以使用核 SHAP 来*似 Shapley 值。这种模型不可知的方法建立在 Shapley 值和在 LIME(局部可解释模型不可知解释)方法中发现的局部线性回归替代模型的基础上。

LIME 使用以下方法获得模型的局部解释:

l 是最小化损失函数。 f 是型号。 g 是训练好的线性解释模型。g 是更简单的、潜在可解释的模型族。πx 是局部加权核,ω是惩罚项

内核 SHAP 使用经典 Shapley 值的属性来生成 l、ω和πₓ的特定形式,作为恢复 Shapley 值的一种方式。非常整洁!

值得注意的是,SHAP 中的加权核πₓ将重点放在具有很少特征的子集以及具有几乎所有特征的子集上。直观地说,这是有意义的,因为您通过排除该特性(几乎完整的子集)或排除除该特性之外的所有特性(小子集)来捕获关于特定特性行为的更多信息。有关更深入的回顾,请参考第 3 节和第 4.1 节。

从概念上讲,每个特征的贡献通过采样特征子集来*似。基于所提供的训练数据,那些不存在于子集中的值被普遍的值所替代——基本上是每个特征的值的扰动。从不同特征子集的这些值中生成模拟目标数据,并如上所述进行加权。局部和加权线性回归模型在该数据上被训练为解释模型,其中最终系数对应于 SHAP 值。

总的来说,这种*似试图提供一种将上述概念应用于任何模型或函数的方法,这种方法在计算上比经典的 Shapley 值更实用,同时也减轻了使用 LIME 时出现的不太直观的行为。从这里开始,SHAP 值可用于描述行为的各种方式,使用相关的可视化,如下例所示。

力图:我们可以局部看到每个特征对单个预测的每个附加贡献。如果我们把每一个观察看作是整体总结的一部分,我们就可以在每一个预测中汇总这些观察。

SHAP 值汇总:图表显示了按重要性排序的特征,以及为每个观察点绘制的所有 SHAP 值。这可以给出特征效果的更全面的感觉。在下面的示例图中,要素 1 的高值通常对预测有相当积极的影响,而低值则有负面影响。

摘要

最后,我们看了几个模型不可知的策略,这些策略有助于解释模型,否则这些模型会太复杂而无法直接解释。这些方法包括:

  • 部分依赖图(PDP)与个别条件期望图相结合,有助于提供对功能行为的一些视觉理解。我们研究了单个和成对 PDP,以了解依赖性趋势
  • 接下来,我们在 PDP 奠定的基础上计算 H 统计量,这是一种检测和探索成对交互的方法
  • 最后,我们讨论了 SHAP 及其整合的 Shapley 值和石灰方法,以了解功能的重要性和贡献

参考文献

1 Lundberg,s .,& Lee,S.-I. (2017)。"解释模型预测的统一方法."

2杰罗姆·弗里德曼(1999 年)。"贪婪函数逼*:梯度推进机."

3弗里德曼、杰罗姆 H .和波格丹一世 E .波佩斯库(2008)."通过规则集合的预测学习."

4克里斯托弗·莫尔纳尔。(2019)“可解释的机器学习。让黑盒模型变得可解释的指南。”

探索移动互联网:从纸张到 Keras

原文:https://towardsdatascience.com/exploring-mobilenets-from-paper-to-keras-f01308ada818?source=collection_archive---------41-----------------------

拆卸 MobileNets,看看它们是如何轻便高效的。

照片由安吉拉·孔波妮Unsplash 上拍摄

MobileNets 是流行的架构,用于图像分类、人脸检测、分割等等。它们在移动和嵌入式设备上的延迟是众所周知的。你可以从名字“MobileNet”中推断出这一点。由于使用了可分离卷积,它们的可训练参数数量少得多。如果你正在运行一个使用相机实时帧的图像分类模型,你可能需要一个快速、准确、占用移动设备更少内存的模型。

移动互联网的使用。来源

今天,我们将从它的研究论文到 TensorFlow ( Keras!).在进一步阅读这个故事之前,你可以确保以下几点,

  1. 如果你对可分卷积的概念不感兴趣,请阅读“ 可分卷积基础介绍 ”。
  2. Colab 笔记本 仅包含 MobileNet V1 的 TF 实现。
  3. 所有用粗体和斜体书写的术语,如 【示例】 都可以直接在研究论文中找到。
  4. 你可能会在 GitHub 的tensor flow/modelsrepo 上看到 MobileNet 的实现。

我建议您在另一个选项卡中打开 MobileNet 的 TensorFlow 实现,

* [## 移动网络 _With_TensorFlow

colab.research.google.com](https://colab.research.google.com/drive/1uUYdZk7EbOESRP7JFwHfsR7b9gUjxU75#scrollTo=K17Opyz2XLeN&forceEdit=true&sandboxMode=true)

MobileNets 使用可分离的卷积。但是什么是可分卷积呢?它们有什么“可分”之处?

可分离盘旋由下面的两个(分离的)盘旋组成。它们是深度方向卷积和点方向卷积。深度方向卷积接受一个特征图,在每个输入核上运行一个核。逐点卷积增加了输出通道的数量。

我强烈推荐阅读齐-汪锋可分卷积基础介绍

[## 可分卷积的基本介绍

解释空间可分离卷积,深度可分离卷积,以及在一个简单的。

towardsdatascience.com](/a-basic-introduction-to-separable-convolutions-b99ec3102728)

在本文中,所有的卷积都被认为是填充的。所以在卷积之后,输入和输出特征图的大小是相同的。所以在下面两张图中, Df — Dₖ + 1 只等于 Df

深度方向回旋

深度方向的回旋。

假设,我们有尺寸为 DfM 正方形特征地图。使用大小为 Dₖ 的内核,我们正在生成大小为 Df — Dₖ + 1 的输出特征图(假设没有填充,步长为 1)。我们对所有 m 个输入特征图重复这一过程,最后,我们剩下一个维度的特征图,df—dₖ+1×df—dₖ+1×m。注意,我们将对输入特征图的 M 个通道使用 M 个不同的核。这就是我们的 【深度方向卷积】

乘法次数(或文中提到的 【计算成本】 )将为,

当你只为一个时期训练了你的模型并且你用完了内存的时候!

逐点卷积

逐点卷积。

上面生成的输出特征图有 M 个通道,而我们需要 N 个输出通道。因此,为了增加输出维度,我们使用了一个 1 × 1 卷积。这些被称为 【点态卷积】 。我们使用大小为 1 × 1 × M 的核,并产生大小为df-dₖ+1×df-dₖ+1×1 的单一特征图。我们将此重复 N 次并且我们留下大小为df-dₖ+1×df-dₖ+1×n 的输出特征图。

对于一个标准卷积,计算成本应该是,

对于可分离卷积(深度方向+点方向),计算成本将是,

文中还计算了参数的缩减量。

来源

宽度和分辨率乘数

尽管 MobileNet 的可训练参数有了相当大的减少,但你仍然希望它快,为此我们引入了一个名为 【宽度乘数】 的参数。用 α 表示。因此,模型中的任何层都将接收 αM 特征图,并产生 αN 特征图。它使 MobileNet 型号更薄并增加了延迟。为简单起见,我们将设置α = 1.0,其中α ∈ ( 0,1)。

如文中所述的宽度倍增器。来源

为了进一步降低计算成本,他们还引入了一个 【分辨率乘数】 记为ρ。它减少了输入图像以及每一层的内部表示。

如论文中所述的分辨率倍增器。来源

TensorFlow 实现(带 Keras)

首先,我们将从论文本身来看一下架构。它看起来像这样,

MobileNet 架构。来源

这里, " Conv /s2" 表示步长为 2 的卷积层(非深度方向)。 " Conv dw /s1" 表示步长为 1 的可分卷积。所有层之后是批处理规范化和 LeakyReLU 层。

具有 BatchNorm 和 LeakyReLU 的标准卷积层(右)。具有深度方向和 1 × 1 卷积(点方向)的可分离卷积(左)。来源

Keras 中的实现如下所示,

可分卷积。

最后,模型由 29 层包装而成,

组装模型。

我们将在劳伦斯·莫罗尼石头剪刀布数据集上训练我们的模型。为了方便起见,它托管在 TensorFlow 数据集上。最初的 MobileNet 是在包括 ImageNet 在内的许多数据集上进行评估的。

你会在 Colab 笔记本中找到培训部分。恭喜你。您刚刚从头开始创建了一个 MobileNet。

进一步探索…

结束了

来源

我希望你喜欢 MobileNet 的概念。如果你想在大数据集上训练模型,你可以通读研究论文。他们还包括一些超参数,这将有助于你的训练。谢谢,再见。*

探索移动*均线以在 Python 中构建趋势跟踪策略

原文:https://towardsdatascience.com/exploring-moving-averages-to-build-trend-following-strategies-in-python-bd17595e3498?source=collection_archive---------9-----------------------

使用 Plotly 在 Python 中生成

移动*均线能提高投资组合相对于基准的表现吗?

“低买高卖”是金融界每个人都想实现的共同目标。然而,这比看起来更困难,因为我们不知道顶部或底部在哪里。我们只知道我们现在在哪里,以及我们去过哪里。许多投资者坐着等待下一次衰退,以获得一个良好的进场点,错过了牛市带来的巨大回报,而那些坐在指数中的投资者获得了牛市的好处,但也面临着熊市的严峻现实。

跟随趋势比预测顶部和底部更容易。因此,在这篇文章中,我们将介绍一些跟踪市场趋势的基本方法,并试图在牛市和熊市中获得稳定的回报。

简单移动*均线

100 天简单移动*均线

简单移动*均(SMA)是一种*滑函数,用于计算过去观察值的*均值。这是一个常用的技术指标,用来表示价格反转。

如果我们有 1000 天的每日定价数据,则 100 天移动*均值的计算方法是*均前 100 天,然后通过一次移动一天的范围,一次*均 100 天。

用乳胶写的

简单的基于移动*均线的策略是利用资产价格和移动*均线之间的关系来捕捉趋势。我们将使用价格和移动*均线的交叉点来确定我们的位置。

导入数据

我们可以从雅虎财经等网站下载数据,并将其加载到数据框架中,或者使用 API 直接从外部服务器读取数据到 Python 内存中。

import pandas as pd
df = pd.read_csv("your_data.csv")

Quandl 是一个在线金融数据数据库,有一个免费账户和一个付费账户。非用户的请求数量是有限的,而用户每 10 秒钟可以获得 300 个呼叫。基本使用绰绰有余。

我们使用我们最喜欢的股票 choice Apple,并下载 2009 年至 2018 年期间的价格数据。

myquandlkey = "myquandlkey"
import quandlaapl = quandl.get("WIKI/AAPL", start_date="2009-01-01", 
                  end_date="2018-12-31", api_key=myquandlkey)

另一个流行的选择是 pandas_datareader,这是这次将使用的一个。

import pandas_datareader as web
aapl = web.get_data_yahoo('AAPL', 
                          start=datetime.datetime(2009, 1, 1), 
                          end=datetime.datetime(2018, 12, 31))

数据准备

导入数据后,让我们看一下数据框,检查一下是否一切正常

aapl.head()

现在,只保持调整后的收盘,但在进一步的分析中可以有趣地看看成交量。删除第一行,因为我们不小心包括了 2008 年的除夕。

# New DataFrame only containing the Adj Close column
aapl = aapl[["Adj Close"]]# Rename the adjusted close column to Price
aapl.rename(columns={"Adj Close":"Price"}, inplace=True)# Remove the first row,
aapl = aapl.iloc[1:]aapl.head()

使用 pandas rolling 函数计算移动*均值,并将结果作为新列添加到 DataFrame 中。

aapl["100MA"] = aapl["Price"].rolling(window=100).mean()
aapl

前 99 个移动*均值显示为 NaN。这是因为我们需要前 100 个价格观察值来计算 MA。

绘制价格和移动*均线

# import plotting packages
import matplotlib.pyplot as plt
import matplotlib as mpl# Set color style
plt.style.use('seaborn-dark')
plt.style.use("tableau-colorblind10")fig = plt.figure(figsize=(20,12))
ax1 = plt.plot(aapl["Adj Close"])
ax1 = plt.plot(aapl["100MA"])
ax1 = plt.title("Apple daily ajusted close from 2009 through 2018", fontsize=22)
ax1 = plt.xlabel("Date", fontsize=18)
ax1 = plt.ylabel("Price", fontsize=18)
ax1 = plt.legend(["Price", "100 day SMA"],prop={"size":20}, loc="upper left")
plt.grid(True)
plt.show()

100 日均线是一种通过*滑价格来观察价格趋势的方法。由于它是一个滞后指标,它告诉我们过去发生了什么,尽管看一看它很有趣,但它本身可能不是一个好的策略。让我们探索一下,看看结果。

战略和实施

我们将使用两种不同的策略

  1. 当价格超过移动*均线时买入,当价格低于移动*均线时卖空。
  2. 作为一种替代方案,我们可以用现金头寸代替空头头寸,使策略只做多。

我们可以通过持有债券等低风险证券而不是现金来改进策略 2,波动性略有增加,但为了简单起见,现在现金为王。

我们希望在资产趋势上升时搭上顺风车,获得类似的回报。当它趋势向下时,选择卖出等待,或者卖空以从下跌中获利。

像这样一个简单的策略可能会有几个问题。如果趋势没有表现出来,而是给出了一个假阳性,我们的策略可能会以错误的方向买入或卖出而告终,从而亏损。短时间内的大量交叉会堆积交易成本。解决这个问题的方法是在交易前设定价格和移动*均线之间的最小距离,这可以在以后进一步探讨。

让我们按照策略 1 创建一个包含“Long”或“Short”的新列。

Position = []
for i in range(0,apple.shape[0]):
    if apple[“Adj Close”].iloc[i] > apple[“100MA”].iloc[i]:
        Position.append(“Long”)
    else:
        Position.append(“Short”)apple[“Position”] = Position
apple.head()

创建价格回报的新列,并将其添加到数据框架中

apple[“return”] = (apple[“Adj Close”] — apple[“Adj Close”].shift())/apple[“Adj Close”].shift()# The first return is defined from the 2\. row, so drop the first
apple.dropna(inplace=True)
apple.head()

在第一天,设定每种策略的价值等于苹果的价格,这样就很容易比较策略的价值如何与苹果的价格相比较。将价格与移动*均线进行比较,建立“多头”或“空头”头寸。第 1 天的回报将使用第 0 天的百分比变化来设置。我们还不能建仓,因为我们只有每日收盘,需要等到明天。

在第 2 天,我们根据第 1 天的头寸做多或做空,因为我们没有增加或删除第 1 天到第 2 天的任何值,策略将具有与第 1 天相同的值。

在第 3 天,我们乘以收益,或者从第 2 天到第 3 天苹果价格的变化,这是第 nr 行的收益。3、按每种策略。

编辑:请记住,长期持有策略是持有现金的策略 2。更好的名字应该是朗凯什。

LongShort = [0]*apple.shape[0]
LongHold = [0]*apple.shape[0]LongShort[0] = apple[“Adj Close”].iloc[0]
LongShort[1] = apple[“Adj Close”].iloc[0]
LongHold[0] = apple[“Adj Close”].iloc[0] 
LongHold[1] = apple[“Adj Close”].iloc[0]for i in range(0, apple.shape[0]-2):
    if apple[“Position”].iloc[i] == “Long”:
    LongShort[i+2] = LongShort[i+1]*(1+apple[“return”][i+2])
    else:
        LongShort[i+2] = LongShort[i+1]/(1+apple[“return”][i+2])

for i in range(0, apple.shape[0]-2):
    if apple[“Position”].iloc[i] == “Long”:
        LongHold[i+2] = LongHold[i+1]*(1+apple[“return”][i+2])
    else:
        LongHold[i+2] = LongHold[i+1]apple[“LongShort”] = LongShort
apple[“LongHold”] = LongHold
apple.drop(apple.tail(1).index,inplace=True)
apple.head()

现在把策略和 100 天的 SMA 画在一起

fig = plt.figure(figsize=(20,12))
ax1 = plt.plot(apple[“Adj Close”])
ax1 = plt.plot(apple[“100MA”])
ax1 = plt.plot(apple[“LongShort”], color=”green”)
ax1 = plt.plot(apple[“LongHold”], color=”brown”)
ax1 = plt.title(“Apple daily ajusted close and strategy from 2009 through 2018”, fontsize=18)
ax1 = plt.xlabel(“Date”, fontsize=18)
ax1 = plt.ylabel(“Price”, fontsize=18)
ax1 = plt.legend([“Price”, “100 day SMA”, “SMA crossover long/short strategy”,
 “SMA crossover long/cash strategy”],prop={“size”:22}, loc=”upper left”)
plt.grid(True)
plt.show()

在过去的 10 年里,苹果经历了非常健康的增长。因为 SMA 是滞后的,所以空头最终会伤害我们。导致 SMA 交叉的轻微下跌很快变成急剧上涨,而 SMA 图形没有足够快地跟上,当资产价格上涨时,我们做空。可以看出,多空策略被价格过程碾压,而多空/持有策略停留在中间。

2012/2013 年,做空策略发挥了作用,在苹果价格下跌时增加了价值。价格*稳,容易体现趋势。在 2015/2016 年,该战略效果不佳。价格趋势本身并不明显,表现出高度的波动性。

指数移动*均线

代替 SMA,更合适的加权函数将给予更*的观察更高的投票。这种方法的一个流行版本是指数移动*均线(EMA),它使用指数衰减权重。因为旧的观察很少有发言权,我们可以使用整个数据集作为回望期来计算均线。

该公式由下式给出

用乳胶写的

使用与前面相同的策略实施 EMA。简单地用均线而不是均线来比较价格。

至少对苹果来说,均线表现比均线好。这可能是因为它对资产价格的突然变化反应更快。仅仅持有这种资产仍然不会表现过度。

MACD

我们可以不用单一的均线,而是比较两个不同时间段的均线之间的关系。这就是所谓的移动*均收敛发散,或 MACD。

假设是根据 MACD 指标捕捉到的趋势买入或卖出资产。当短期移动*均超过长期移动*均时,我们做多,当长期移动*均超过短期移动*均时,我们做空。在这个分析中,我使用了 21 日均线和 126 日均线,代表一个月和六个月的交易日。由于回溯测试是在一个很长的时间范围内进行的,我尽量避免使用太短的回溯期。要写代码,计算 26 和 126 日均线,比较它们而不是和均线比较价格。

类似于均线,我们画出图来看结果

MACD 的这个特殊版本在这个数据上表现不佳。我们将很快研究各种数据集和时间框架上的所有策略,看看它们在不同情况下的表现。

结合一切

为了从上面的分析中进行归纳,我使用了函数来更容易地选择我们想要分析的数据,以及我们想要包含的模型。

我还加入了一个汇总统计脚本,以查看每个策略在最大提款、夏普、波动性和年化回报 VaR 等方面的表现。

现在编写一个将使用上述函数的主函数,以及一个绘制结果的函数。

让我们运行主函数 strategy()和绘图函数 plot_strategy(),并显示汇总统计表。我们计算并绘制 3 毫安变化以及所有的多头/空头和多头/持有。

2 个牛市案例

  • 苹果从 2009 年到 2018 年,和之前一样
  • 同一时期的标准普尔 500
start = datetime.date(2009, 1, 1)
end = datetime.date(2018, 12, 31)
ticker = “AAPL”
days = 100df, table, df_return_of_strategy, df_positions, df_price_of_strategy = strategy(ticker, start, end, days=days, MA=True, EMA=True, MACD=True, LongHold=True, LongShort=True)plot_strategy(ticker=ticker, start=str(start), end=str(end), df=df_price_of_strategy)
table

移动*均线策略在牛市中表现不佳。在市场上涨的时候做空,同时还能产生超额回报,这很难。正如我们所预期的那样,最大提款和波动性在现金投资组合中是最低的,这实际上给了苹果比在该期间持有股票更高的夏普比率。让我们来看看两次市场崩盘,分别发生在下跌前和下跌中。

3 熊案例

  • 标准普尔 500 从 2006 年到 2010 年,“全球金融危机”
  • 纳斯达克综合指数从 1998 年到 2001 年,“科技泡沫”
  • 20 世纪 90 年代的日经 225 指数,“失去的十年”

在熊市期间做空会产生好的结果,这并不奇怪,但我们在顶部之前很久就建仓了,这不会在上涨期间损害太多的回报。然而,在下跌过程中,空头头寸受益匪浅。这种策略的一个缺点是我们无法察觉价格的突然下跌。在 1987 年的“黑色星期五”,道琼斯工业*均指数下跌了 22.6%,标准普尔 500 下跌了 18%。这些策略不能保护我们免受这种跌倒,应该与其他方法结合使用。

2 横向资产

  • 通用汽车从 2014 年到 2019 年
  • 从 2002 年到 2017 年的微软

横盘从来不代表趋势,当落后的 MA 赶上价格时,已经太晚了。趋势太短,这表明较短的均线可能是更好的选择。需要注意的一点是,除了最后一张图,所有均线都有更高的回报,波动性相似或更低。这个版本的 MACD 不能给出很好的结果,尽管最常见的版本快速均线用 12 天,慢速均线用 26 天。

结论和进一步的工作

趋势跟踪的移动*均交叉策略是一种众所周知的简单方法,在测试期间和使用的数据中,在熊市中比牛市中表现更好。尽管高度不稳定和停滞的市场会损害其质量。

我们做了几个假设。没有滑点或交易费用。我们只使用调整后的每日收盘,并且只能在那时进行交易。我们不考虑分红或做空限制。

我们每天重新*衡,这对于一些必须转移大量资金的基金来说并不总是可行的。他们可能来不及参加聚会了。我们也简单地根据交叉来买卖,不考虑价格和 MA 在背离之前的高振荡。

为了进一步分析,比较各种具有相反行为的资产类别是很有趣的,例如,高波动性对低波动性。每天运行一组资产,查看价格和 MA 之间的百分比距离,看看交易那些距离较大的资产是否可以减少误报的数量,并更好地捕捉更可靠的趋势,这将是很有趣的。

使用适当的时间序列交叉验证方法进行更严格的回溯测试也是有用的。模型的稳定性非常重要。如果我们改变了一些参数,结果发生了巨大的变化,我们应该放弃这个模型,重新开始。回溯测试并不能证明什么,但是使用交叉验证和限制前瞻偏差可以提高我们的信心。

免责声明: 如果您发现任何错误,请告诉我。另外,请注意,这只是对一些历史数据的一些方法的探索。过去的表现不能保证未来的结果。

更新(19/02/2020): 这是一个重写的版本。我已经修改了第一版的一个计算错误。

Github 库:

https://github.com/RunarOesthaug/MA-crossover_strategies

感谢阅读!

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

在 Python 中探索网飞数据

原文:https://towardsdatascience.com/exploring-netflix-data-in-python-eb03e8f3944c?source=collection_archive---------13-----------------------

网飞数据的探索性数据分析

来源

Flixable 是一个视频流媒体服务搜索引擎,提供网飞电影和节目的完整列表。搜索引擎发布了网飞电影和电视节目数据集,其中包括 2019 年可用的电影和节目的完整列表。

在本帖中,我们将对网飞电影和电视节目数据集进行探索性数据分析。数据可以在这里找到。

我们开始吧!

首先,让我们导入 Pandas 并将数据读入数据框:

import pandas as pd 
df = pd.read_csv("netflix_titles.csv")

接下来,让我们打印列的列表:

print(list(df.columns))

我们还可以看看数据中的行数:

print("Number of rows: ", len(df))

让我们打印前五行数据:

print(df.head())

我们可以看到有几个分类列。让我们定义一个将数据框、列名和限制作为输入的函数。当被调用时,它打印分类值的字典以及它们出现的频率:

def return_counter(data_frame, column_name, limit):
   from collections import Counter    print(dict(Counter(data_frame[column_name].values).most_common(limit)))

让我们将函数应用于“国家”列,并将结果限制为五个最常见的值:

return_counter(df, 'country', 5)

如我们所见,美国有 2,032 个标题,印度有 777 个,缺少 476 个国家值,英国有 348 个,日本有 176 个。

让我们将函数应用于“director”列,删除缺失的值:

df['director'].dropna(inplace = True)
return_counter(df, 'director', 5)

现在,让我们看看最常见的导演“劳尔·坎波斯”和“扬·苏特”的片名:

df_d1 = df[df['director'] =='Raúl Campos, Jan Suter']
print(set(df_d1['title']))

和国家:

print(set(df_d1['country']))

我们看到这些头衔来自哥伦比亚、智利、阿根廷和墨西哥。让我们为马库斯·雷波依做同样的事情:

df_d2 = df[df['director'] =='Marcus Raboy']
print(set(df_d2['title']))

现在我们来分析电影时长。首先,我们需要过滤数据集,只包括电影标题:

df = df[df['type'] =='Movie']

接下来,让我们打印一组电影时长:

print(set(df['duration']))

我们看到所有的值都以字符串的形式报告,持续时间以分钟为单位。让我们从字符串值中删除“min ”,并将结果转换为整数:

df['duration'] = df['duration'].map(lambda x: x.rstrip('min')).astype(int)
print(set(df['duration']))

接下来,从像“持续时间”这样的数字列中生成汇总统计数据会很有用。让我们定义一个采用数据框、分类列和数字列的函数。每个类别的数字列的*均值和标准偏差存储在数据框中,并且数据框根据*均值以降序排序。如果您想要快速查看特定类别对于特定数字列是否具有更高或更低的*均值和/或标准偏差值,这将非常有用。

def return_statistics(data_frame, categorical_column, numerical_column):
    mean = []
    std = []
    field = []
    for i in set(list(data_frame[categorical_column].values)):
        new_data = data_frame[data_frame[categorical_column] == i]
        field.append(i)
        mean.append(new_data[numerical_column].mean())
        std.append(new_data[numerical_column].std())
    df = pd.DataFrame({'{}'.format(categorical_column): field, 'mean {}'.format(numerical_column): mean, 'std in {}'.format(numerical_column): std})
    df.sort_values('mean {}'.format(numerical_column), inplace = True, ascending = False)
    df.dropna(inplace = True)
    return df

让我们用分类列‘listed _ in’和数字列‘duration’来调用我们的函数:

stats = return_statistics(df, 'listed_in', 'duration')
print(stats.head(15))

接下来,我们将使用箱线图来显示基于最小值、最大值、中值、第一个四分位数和第三个四分位数的数值分布。如果您对它们不熟悉,可以看看文章了解 Boxplots

与汇总统计函数类似,此函数采用数据框、分类列和数值列,并根据限制显示最常见类别的箱线图:

def get_boxplot_of_categories(data_frame, categorical_column, numerical_column, limit):
    import seaborn as sns
    from collections import Counter
    keys = []
    for i in dict(Counter(df[categorical_column].values).most_common(limit)):
        keys.append(i)
    print(keys)
    df_new = df[df[categorical_column].isin(keys)]
    sns.set()
    sns.boxplot(x = df_new[categorical_column], y =      df_new[numerical_column])

让我们为 5 个最常见的“列出”类别中的“持续时间”生成箱线图:

get_boxplot_of_categories(df, 'listed_in', 'duration', 5)

最后,让我们定义一个函数,它将一个数据框和一个数字列作为输入,并显示一个直方图:

def get_histogram(data_frame, numerical_column):
    df_new = data_frame
    df_new[numerical_column].hist(bins=100)

让我们用数据框调用函数,并从“持续时间”生成一个直方图:

get_histogram(df, 'duration')

我就讲到这里,但是请随意处理数据并自己编码。

概括地说,我回顾了几种分析网飞电影和电视节目数据集的方法。这包括定义生成汇总统计数据的函数,比如*均值、标准差和分类值的计数。我们还定义了用箱线图和直方图可视化数据的函数。我希望这篇文章有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

理解神经网络的*似能力

原文:https://towardsdatascience.com/exploring-neural-networks-and-their-fascinating-effectiveness-81ebc054cb16?source=collection_archive---------37-----------------------

里面的艾

探索神经网络有效性的基本概念。

照片由布鲁克·拉克Unsplash 拍摄

一切开始的地方。

这一切都始于理解大脑实际上是如何工作的想法。早在 20 世纪 40 年代,麦卡洛克和皮茨就引入了神经元1,20 世纪 50 年代,弗兰克·罗森博尔特推出了第一台感知机2。自 20 世纪 40 年代以来,神经网络就伴随着我们,但是,由于缺乏实际的实施,该领域面临着起伏。最*涉及各种神经网络架构的深度学习技术实践的增长是因为两个主要进步,第一,(高性能 CPU 和 GPU),第二, 可用的数据量

Geoff Hinton 和他的两个研究生展示了如何使用深度学习将一个名为 ImageNet 的非常大的数据集,包含 10000 个类别和 1000 万张图像,并将分类错误减少 20%。这发生在 2012 年的 NIPS 会议上,正如 Terrence Sejnowski 所说,

传统上,在数据集(ImageNet)上,误差在一年内减少不到 1%。一年时间,绕过了 20 年的研究。这真的打开了闸门。——在《The Verge》的采访中。

这就是“深度学习——嗡嗡声”开始的时刻。人工智能就是从这一点发展起来的。

神经网络有多神奇?

人工神经网络由大量简单的相互连接的处理元件组成。这些元件并行操作,其功能由网络结构、连接强度以及在计算元件或节点处执行的处理决定。对深度学习兴趣的增长部分是由于传统编程技术在“硬”任务中的失败,如机器视觉、连续语音识别和机器学习。

神经网络在视觉、语音、信号处理和机器人方面的能力已经得到了显著的证明。神经网络解决的各种问题令人印象深刻。最*在诸如图像分类、对象检测、文本生成、图像字幕、语言翻译、GANs 等任务中有了突破。

由于神经网络的有效性和高性能处理器(GPU、TPU)的可用性,神经网络的热门研究领域正在快速发展,并且范围很广。AWS、Google Cloud 等云技术的最新进展。也有助于更好的研究。但是深度学习往往面临缩放、和现实世界问题。(关于这些问题的讨论超出了本文的范围)

函数逼*

函数逼*是通过简单函数的集合来描述复杂函数的行为。这些方法包括通过高斯级数展开多项式逼*,以计算工作点附*函数的*似值,如泰勒级数、等等。

神经网络是在统计上实现泛化的函数逼*机器。

功能😋

神经网络是通用逼*器

前馈神经网络提供了一个通用逼*框架,即通用逼*定理

通用逼*定理在其最一般的版本之一中说,如果我们仅考虑连续激活函数 σ ,那么具有一个隐藏层的标准前馈神经网络能够将任何连续多元函数 f 逼*到任何给定的逼*阈值 ε ,当且仅当 σ 是非多项式。3

前馈网络提供了一个表示函数的通用系统,在这个意义上,给定一个函数,存在一个逼*该函数的前馈网络。这表明存在一个接*所考虑的函数的大网络,但它没有回答,到底有多大?

简而言之,具有单个层的前馈神经网络是代表任何函数的 sufficient,但是该层可能相当大,并且可能不能正确概括。

*似的例子

作为函数逼*的例子,我采用了众所周知的正弦、余弦函数和一个自定义函数。数据点的范围[-3,3]使得函数图看起来如下:

  1. 余弦函数

余弦图(来源:笔记本)

2.正弦函数

正弦图(来源:笔记本)

用建筑的神经网络进一步逼*这些功能,

图层:输入(1)-隐藏(100)-输出(1)

神经网络体系结构[in-hidden-out,1–100–1]

基于神经网络优化的*似函数的结果在函数图下面,

  1. 余弦

2.正弦

问题

上图显示,通过一组正确的参数,神经网络几乎符合原始函数。一切看起来都很完美,那么还会有什么地方出错呢?

过度拟合

是的,我们的神经网络过度拟合了!训练集上的误差被驱动到非常小的值,但是当新数据呈现给网络时,误差很大。网络已经记住了训练的例子,但是还没有学会推广到新的情况。这必须避免。我们可以看看另一个具有相同神经网络结构的自定义函数。

功能,

10(a )sin(a)cos(s)*

关于函数逼*,

接*

结论

这些是理解神经网络通用逼*能力的基础的一些尝试,这使得深度学习领域在广泛的任务上有效成为可能。最后,我们将上述内容总结如下:

  • 根据数据训练神经网络*似于从输入到输出的未知的基本映射函数。
  • 在训练神经网络时,过拟合等问题会阻碍新数据的结果(看不见)。

人们可以通过在笔记本上用代码进行实验来观察改变神经架构和参数对结果的影响,如上图所示。

参考

1麦卡洛克,W. S .和皮茨,W. 1943。神经活动中固有观念的逻辑演算。数学生物物理学通报5:115–133。

2罗森布拉特,1957 年。感知机——一种感知和识别自动机。康奈尔航空实验室报告 85-460-1。

3进一步了解神经网络的*似能力,Kai Fong Ernest Chong。

要签出的资源

谢谢你!在 LinkedIn 和我联系,

* [## Pratik K. -作家-走向数据科学| LinkedIn

我是一名刚从泰国国立理工学院电子和通信工程专业毕业的学生

www.linkedin.com](https://www.linkedin.com/in/pratik-kumar04/)

查看我的投资组合网页了解更多关于我的详细信息在这里。*

探索印度媒体中关于新冠肺炎的新闻| NLP| Wordcloud |新冠肺炎文章 1

原文:https://towardsdatascience.com/exploring-news-about-covid-19-in-indian-media-nlp-wordcloud-covid-19-article-1-2bcbb127dfb3?source=collection_archive---------58-----------------------

新冠肺炎文字分析

编者注: 走向数据科学 是一份以研究数据科学和机器学习为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

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

C 现在全球的流行词是冠状病毒、死亡、隔离和封锁。因此,在这篇博客中,我试图挖掘来自印度媒体的新闻文章,并使用词云可视化哪些词出现得最多。

对 wordcloud 的结果感兴趣吗?

滚动到底部!

关于我的新冠肺炎新闻文章数据集:

我用过的新闻文章都是用 NewsAPI 的 开发者计划刮出来的。因为,我几天前才决定这个用例,我的数据集的日期范围是2020 年 3 月 10 日到 4 月 10 日。因此,数据集将每月增长。此外,新闻文章的内容被限制在260 个字符以内,但是你知道他们说什么——如果读者对引言不感兴趣,他们可能不会读到第二段。所以我们只有很少但重要的信息。

使用的新闻来源:谷歌印度新闻、印度时报和印度教徒报

照片由 Doran EricksonUnsplash 上拍摄

数据集预处理:

我使用传统的 NLP 清洗流程:

  1. 标记化、停用词删除、标点符号删除
  2. 词性标注和生成词条

我使用 lambda 函数来遍历这些行,并将最终数据集存储到 pickle 文件中以备后用。

这很大程度上源于我之前的一篇博客,所以我将跳过细节。

数据转换的一个例子:

**Actual Content:**The spectre of COVID-19 has made its appearance in one of Indias most storied tiger reserves. The death of a 10-year-old ailing male tiger, in the Pench Tiger Reserve (PTR) the countrys most munificent reserve that succumbed to a respiratory illness last Satu… [+3272 chars]**Cleaned and Normalized Content:**[[number, covid-19, case, continue, rise, 6, 33, new, case, report, 12-hour, span, take, tally, positive, case, 781], [witness, 19, fresh, case, 11, report, fro]]

Github 链接笔记本进行数据清理:

[## royn5618/Medium_Blog_Codes

github.com](https://github.com/royn5618/Medium_Blog_Codes/blob/master/Covid-Blog-Codes/Cleaning-Covid-Dataset-NLP.ipynb)

生成词频& Wordcloud:

我使用了独一无二的 Wordcloud Python 库来创建这个 word-cloud。我自己生成了术语频率词典,并在下面一步一步地记录了这个过程:

第一步: 我创建了一个令牌列表,如下所示:

temp_list = [k **for** i **in** list(df[col]) **if** i **for** j **in** i **for** k **in** j]

在笔记本中,我还根据结果单词云中出现的不需要的单词做了一些清理。

步骤 2: 我将唯一的单词作为存储到字典中,并将它们的频率分配到各自的中。

# Use *set* to get the unique elements of the list
unique_words = set(terms_list)# Iterate through the terms and store count of the indexed words to 
dict_terms_count = {}
**for** word **in** unique_words:
    dict_terms_count[word] = terms_list.count(word) 

第三步:现在,我从前面的字典中得到最大的词频,并根据最高的词频调整其他的词频。

max_tf = max(dict_term_count.values())
dict_tf_scaled = {}
**for** word, count **in** dict_term_count.items():
    dict_tf_scaled[word] = count/max_tf
sorted_dict_term_count = dict(sorted(dict_tf_scaled.items(),
                              key=**lambda** kv: kv[1], reverse=**True**))

在这种情况下,“新冠肺炎”一词的出现频率最高,为 7536 次。看看下面的情节。很明显,Covid 和冠状病毒占据了新闻,因为刮擦集中在具有这两个关键词的文章上。

第四步:生成词云。我在评论中加入了一些关于在单词云中生成颜色的解释。我使用了许多图片进行试验,并选择了最适合的一个。我用过的那个在我的 GitHub 回购上。说真的,很好玩!下载随机图像,使用 ImageColorGenerator 生成本地化的彩色像素,并尝试匹配您的文字云。

# imports
from PIL import Image
import PIL.ImageOps
from wordcloud import ImageColorGenerator# Load the mask image
image_mask = np.array(Image.open(mask_image))# Generate the wc colours from the image pixels
# This method takes the average of a region of pixels and assigns 
# that colour to the texts in that regionimage_colors = ImageColorGenerator(image_mask)# Generate the Wordcloud object using the mask. 'mask' is to 
# generate the outline of the image you have chosen.
# For me it it rectangular - so no visible change
# Since I have passed custom frequencies, I have used
# 'generate_from_frequencies' methodstopwords = set(STOPWORDS)
wordcloud = WordCloud(width = 2000, height = 1200, 
                      max_words = 500, normalize_plurals = True,   
                      **mask=image_mask**, background_color =’black’, 
                      font_step = 1, relative_scaling = 0.5,
                      collocations = False, include_numbers = False,
                      stopwords =stopwords)
                      .generate_from_frequencies(dict_term_freq)# Some matplotlib settings plt.figure(figsize = (80, 50), facecolor = None)
plt.style.use(‘dark_background’)
plt.imshow(wordcloud.recolor(color_func=image_colors))
plt.text(xpos, ypos, custom_text, fontsize=font_size)
plt.axis(“off”)
plt.show()

云这个词在这里:

意见和结论:

在所有的词语中,正面战斗比较有意思。这是因为“战斗”通常被认为是消极情绪,而“积极”正如其名称所示,是积极情绪。然而,形势显然已经发生了逆转。“拼”是正面情绪,“正面”是负面情绪在 2020 年疫情新冠肺炎的语境中。这清楚地表明了单词袋& tf-idf 作为文本表示模型的缺点、情感分析中的挑战以及我们为什么需要基于上下文/顺序的模型。**

“说”的出现表明已经说了很多,众所周知,还有很多工作要做。这些话让我好奇,在下一次刮擦中,wordcloud 会有什么不同。我在云中找不到疫苗、解毒剂或治疗之类的词。

就像在 wordcloud 中一样,很自然地,许多负面情绪被表达了出来。这个数据集可能有助于发现与种群和社会经济因素的相互关系。但那是另一个博客讨论的问题!

关于新冠肺炎文章系列:

我将会写更多关于探索和操作这个数据集的博客,这个数据集将会越来越大。如果您有兴趣了解这个数据集是如何形成的,请跟我来!

Github 链接到此数据集上的所有笔记本:

** [## royn5618/Medium_Blog_Codes

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/royn5618/Medium_Blog_Codes/tree/master/Covid-Blog-Codes)**

我的链接: |LinkedIn|GitHub

感谢来访。我希望你喜欢阅读这篇博客。

用 Jupyter 笔记本探索正态分布

原文:https://towardsdatascience.com/exploring-normal-distribution-with-jupyter-notebook-3645ec2d83f8?source=collection_archive---------4-----------------------

统计数字

使用 scipy 和 matplotlib 的正态分布初学者指南

卡洛斯·穆扎在 Unsplash 上的照片

**Table of Contents**[**Introduction**](#f050)1\. [Normal Distribution Probability Density Function](#053b)
2\. [Using random normal distribution values](#47c4)
3\. [A cumulative normal distribution function](#b23b)
4\. [Calculating the probability of normal distribution](#c5a1)
5\. [Interval between variables](#15d2)
6\. [Finding quantiles](#0adf)
7\. [Multivariate Normal Distribution](#cc27)
8\. [Standard normal distribution](#6f46)
9\. [Standardized normal variable](#dcf5)
10\. [Finding the standard normal value](#0921)[**Conclusion**](#72c4)

介绍

正态分布在自然科学和社会科学中常用来表示分布未知的实值随机变量。正态分布是一种连续的理论概率分布。在这篇文章中,我将使用 Jupyter 笔记本来探索正态分布。

让我们导入所有必需的库。

from scipy.stats import norm
import numpy as np
import matplotlib.pyplot as plt

正态分布概率密度函数

正态分布的概率密度函数(PDF)为:

PDF 描述的随机变量 𝑋 是一个正态变量,服从具有均值和方差的正态分布。

正态分布符号是:

曲线下的面积等于 1。

norm.pdf

norm.pdf返回一个 PDF 值。以下是 𝑥 =1、 𝜇 =0、 𝜎 =1 时的 PDF 值。

norm.pdf(x=1.0, loc=0, scale=1)

如果你想看上图的代码,请看这个

由于norm.pdf返回一个 PDF 值,我们可以用这个函数来绘制正态分布函数。我们使用scipynumpymatplotlib绘制正态分布的 PDF。我们使用的域为 4 < 𝑥 < 4,范围为 0<𝑓(𝑥)<0.45,默认值为 𝜇 =0 和 𝜎 =1。plot(x-values,y-values)生成图表。

fig, ax = plt.subplots()
x= np.arange(-4,4,0.001)
ax.set_title('N(0,$1^2$)')
ax.set_xlabel('x')
ax.set_ylabel('f(x)')
ax.plot(x, norm.pdf(x))
ax.set_ylim(0,0.45)plt.show()

正常曲线是*滑的钟形。关于 𝑥 = 𝜇 对称,并且在 𝑥 = 𝜇 处具有最大点。

具有不同标准差的正态分布 PDF

让我们画出一个正态分布的概率分布函数,其中*均值有不同的标准差。

scipy.norm.pdf有关键字,locscale。location (loc)关键字指定*均值,scale (scale)关键字指定标准差。

fig, ax = plt.subplots()
x = np.linspace(-10,10,100)
stdvs = [1.0, 2.0, 3.0, 4.0]for s in stdvs:
    ax.plot(x, norm.pdf(x,scale=s), label='stdv=%.1f' % s)

ax.set_xlabel('x')
ax.set_ylabel('pdf(x)')
ax.set_title('Normal Distribution')
ax.legend(loc='best', frameon=True)
ax.set_ylim(0,0.45)
ax.grid(True)

不同均值的正态分布 PDF

让我们画出标准偏差为 1 的正态分布和不同均值的概率分布函数。

fig, ax = plt.subplots()
x = np.linspace(-10,10,100)
means = [0.0, 1.0, 2.0, 5.0]for mean in means:
    ax.plot(x, norm.pdf(x,loc=mean), label='mean=%.1f' % mean)

ax.set_xlabel('x')
ax.set_ylabel('pdf(x)')
ax.set_title('Normal Distribution')
ax.legend(loc='best', frameon=True)
ax.set_ylim(0,0.45)
ax.grid(True)

分布的*均值决定了图形中心的位置。正如你在上面的图表中看到的,图表的形状并没有因为改变*均值而改变,而是水**移了图表。

[## 建模功能

从线性回归到逻辑回归

towardsdatascience.com](/modeling-functions-78704936477a)

使用随机正态分布值

norm.rvs根据标准差scale、均值loc和大小生成随机正态分布数。我们为生成的数字创建一个直方图,并添加 PDF。

fig, ax = plt.subplots()
xs = norm.rvs(scale=2,size=1000)
x = np.linspace(-10,10,100)
p = norm.pdf(x,scale=2)
v = np.var(xs)
m = np.mean(xs)ax = fig.add_subplot(111)
ax.hist(xs, bins=10, alpha=0.5, density=True)
ax.plot(x,p, 'r-', lw=2)
ax.set_xlabel('x')
ax.set_ylabel('pdf(x)')
ax.set_title(f'mean={m:.2f}, var={v:.2f}')
ax.grid(True)

累积正态分布函数

随机变量 X 的累积分布函数(在 X 处计算)是 X 取值小于或等于 X 的概率。由于正态分布是连续分布,因此曲线的阴影区域表示 X 小于或等于 X 的概率。

使用fill_between(x, y1, y2=0),它将填充两条曲线y1y2之间的区域,默认值为 0。

fig, ax = plt.subplots()
# for distribution curve
x= np.arange(-4,4,0.001)
ax.plot(x, norm.pdf(x))
ax.set_title("Cumulative normal distribution")
ax.set_xlabel('x')
ax.set_ylabel('pdf(x)')
ax.grid(True)# for fill_between
px=np.arange(-4,1,0.01)
ax.set_ylim(0,0.5)
ax.fill_between(px,norm.pdf(px),alpha=0.5, color='g')
# for text
ax.text(-1,0.1,"cdf(x)", fontsize=20)
plt.show()

计算正态分布的概率

给定 3 的均值和 2 的标准差,我们可以求出 𝑃 ( 𝑋 < 2)的概率。

norm.cdf中,location (loc)关键字指定*均值,scale (scale)关键字指定标准差。

from scipy.stats import normlessthan2=norm.cdf(x=2, loc=3, scale=2)
print(lessthan2)

让我们画一张图表。

fig, ax = plt.subplots()# for distribution curve
x= np.arange(-4,10,0.001)
ax.plot(x, norm.pdf(x,loc=3,scale=2))
ax.set_title("N(3,$2^2$)")
ax.set_xlabel('x')
ax.set_ylabel('pdf(x)')
ax.grid(True)# for fill_between
px=np.arange(-4,2,0.01)
ax.set_ylim(0,0.25)
ax.fill_between(px,norm.pdf(px,loc=3,scale=2),alpha=0.5, color='g')# for text
ax.text(-0.5,0.02,round(lessthan2,2), fontsize=20)
plt.show()

变量之间的间隔

要找出某些变量之间的间隔概率,需要从另一个cdf中减去cdf。我们来找𝑃(0.5<𝑋<2)均值为 1,标准差为 2。

norm(1, 2).cdf(2) - norm(1,2).cdf(0.5)

这是图表。

fig, ax = plt.subplots()# for distribution curve
x= np.arange(-6,8,0.001)
ax.plot(x, norm.pdf(x,loc=1,scale=2))
ax.set_title("N(1,$2^2$)")
ax.set_xlabel('x')
ax.set_ylabel('pdf(x)')
ax.grid(True)px=np.arange(0.5,2,0.01)
ax.set_ylim(0,0.25)
ax.fill_between(px,norm.pdf(px,loc=1,scale=2),alpha=0.5, color='g')pro=norm(1, 2).cdf(2) - norm(1,2).cdf(0.5)
ax.text(0.2,0.02,round(pro,2), fontsize=20)
plt.show()

要找到 𝑃 ( 𝑋 > 4)的概率,我们可以使用sf,它被称为生存函数,它返回1-cdf。例如,norm.sf(x=4, loc=3, scale=2返回当 𝜇 =4, 𝜎 =2 时,大于 𝑥 =4, 𝑃 ( 𝑋 > 4)的概率。

gr4sf=norm.sf(x=4, loc=3, scale=2)
gr4sf

让我们画一张图表。

fig, ax = plt.subplots()
x= np.arange(-4,10,0.001)
ax.plot(x, norm.pdf(x,loc=3,scale=2))
ax.set_title("N(3,$2^2$)")
ax.set_xlabel('x')
ax.set_ylabel('pdf(x)')
ax.grid(True)px=np.arange(4,10,0.01)
ax.set_ylim(0,0.25)
ax.fill_between(px,norm.pdf(px,loc=3,scale=2),alpha=0.5, color='g')ax.text(4.5,0.02,"sf(x) %.2f" %(gr4sf), fontsize=20)
plt.show()

上图同 1𝑃(𝑋t51】4)。

gr4=norm.cdf(x=4, loc=3, scale=2)
gr14=1-gr4fig, ax = plt.subplots()
x= np.arange(-4,10,0.001)
ax.plot(x, norm.pdf(x,loc=3,scale=2))
ax.set_title("N(3,$2^2$)")
ax.set_xlabel('x')
ax.set_ylabel('pdf(x)')
ax.grid(True)px=np.arange(4,10,0.01)
ax.set_ylim(0,0.25)
ax.fill_between(px,norm.pdf(px,loc=3,scale=2),alpha=0.5, color='g')
px1=np.arange(-4,4,0.01)
ax.fill_between(px1,norm.pdf(px1,loc=3,scale=2),alpha=0.5, color='r')
ax.text(4.5,0.02,round(gr14,2), fontsize=20)
ax.text(1,0.02,round(gr4,2), fontsize=20)
plt.show()

[## 线性关系的度量

皮尔逊与 Jupyter 笔记本的积矩相关性

towardsdatascience.com](/a-measure-of-linear-relationship-5dd4a995ee7e)

寻找分位数

𝑘𝑃(𝑋𝑘)= 0.95

被称为分位数,在这种情况下,95%的分位数。

百分点函数

ppfcdf的倒数,称为百分点函数。给定均值 1,标准差 3,我们可以用ppf求出𝑃(𝑋<𝑎)= 0.506 的分位数a

norm.ppf(q=0.506, loc=1, scale=3)

让我们画一张图表。

fig, ax = plt.subplots()
x= np.arange(-10,10,0.001)
ax.plot(x, norm.pdf(x,loc=1,scale=3))
ax.set_title("N(1,$3^2$)")
ax.set_xlabel('x')
ax.set_ylabel('pdf(x)')
ax.grid(True)xpoint=norm.ppf(q=0.506, loc=1, scale=3)
px=np.arange(-10,xpoint,0.01)
ax.set_ylim(0,0.15)
ax.fill_between(px,norm.pdf(px,loc=1,scale=3),alpha=0.5, color='g')ax.text(.8,0.02,"x= %.2f" %xpoint, fontsize=20)
ax.text(-5,0.05,"P(X)=0.506", fontsize=20)
plt.show()

逆生存函数

同样的均值和标准差,我们可以利用逆生存函数isf求出𝑃(𝑋>𝑏)中的分位数b= 0.198。这与使用ppf𝑞=(10.198)是一样的。

norm.isf(q=0.198, loc=1, scale=3)

norm.ppf(q=(1-0.198), loc=1, scale=3)

*均值附*的区间

norm.interval返回包含分布的 alpha 百分比的范围的端点。例如,如果*均值为 0,标准差为 1,则求 95%的概率,norm.interval返回*均值周围的 x 值,在本例中, 𝜇 =0。

a,b = norm.interval(alpha=0.95, loc=0, scale=1)
print(a,b)

fig, ax = plt.subplots()
x= np.arange(-4,4,0.001)
ax.plot(x, norm.pdf(x))
ax.set_title("Interval")
ax.set_xlabel('x')
ax.set_ylabel('pdf(x)')
ax.grid(True)px=np.arange(a,b,0.01)
ax.set_ylim(0,0.5)
ax.fill_between(px,norm.pdf(px),alpha=0.5, color='g')ax.text(-0.5,0.1,"0.95", fontsize=20)
plt.show()

多元正态分布

多元正态分布通常用于描述任何一组相关的实值随机变量。

我们使用multivariate_normal,它需要均值和协方差矩阵的数组。为了简单起见,我们使用一个对角矩阵,其中所有非对角元素为零。

from scipy.stats import multivariate_normalx,y = np.meshgrid(np.linspace(-10,10,100),np.linspace(-10,10,100))
pos = np.dstack((x,y))
mean = np.array([1, 2])
cov  = np.array([[3,0],[0,15]])
rv = multivariate_normal(mean,cov)
z = rv.pdf(pos)fig = plt.figure()
ax = fig.add_subplot(111,aspect='equal')
ax.contourf(x,y,z)
ax.set_xlim(-10,10)
ax.set_ylim(-10,10)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('pdf')

我们可以使用 matplotlib 的[mpl_toolkits.mplot3d.Axes3D](https://matplotlib.org/api/_as_gen/mpl_toolkits.mplot3d.axes3d.Axes3D.html)创建一个 3D 图形。我们也使用 Scipy 冷冻 RV 对象

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import multivariate_normal
from mpl_toolkits.mplot3d import Axes3D# Create grid and multivariate normal
x = np.linspace(-10,10,500)
y = np.linspace(-10,10,500)
X, Y = np.meshgrid(x,y)
pos = np.empty(X.shape + (2,))
pos[:, :, 0] = X 
pos[:, :, 1] = Y# Create a frozen RV object
mean = np.array([1, 2])
cov  = np.array([[3,0],[0,15]])
rv = multivariate_normal(mean,cov)# Make a 3D plot
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, rv.pdf(pos),cmap='viridis',linewidth=0)
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
plt.show()

标准正态分布

𝜇 =0,方差=1 时,称为标准正态分布。上述概率函数简化为:

所有的正态曲线都与标准正态分布相关。

标准化正态变量

为了将随机变量标准化为标准化正态变量𝑍𝑁(0,1)我们使用变换:

标准化值 Z 表示原始值低于或高于*均值多少个标准偏差。

寻找标准正常值

例如,当*均值为 2,标准偏差为 3 时,求 𝑥 =1 的标准化值。

我们可以用norm.cdf求概率,用norm.ppf𝜇 =0, 𝜎 =1 求标准化值。

norm.cdf(1, loc=2, scale=3)

norm.ppf(q=norm.cdf(1, loc=2, scale=3))

结论

scipy.stats.norm 为我们提供了参数locscale来指定标准偏差。它也有多种方法,本文中我们探讨了rvscdfsfppfintervalisf

Matplotlib 为我们提供了简单而广泛的工具来改变包括 3D 在内的图形的微小细节。

通过 成为 会员,可以完全访问媒体上的每个故事。

请订阅。

关于 Jupyter 的更多文章

[## 如何在 Docker 上运行 Jupyter 笔记本

不再有 Python 环境和包更新

towardsdatascience.com](/how-to-run-jupyter-notebook-on-docker-7c9748ed209f) [## 维恩图 Python 包:Vennfig

在 Jupyter 或 Terminal 上用一行代码画一个维恩图

towardsdatascience.com](/introducing-basic-venn-diagram-python-package-vennfig-fa3f8e4dcb36) [## 线性关系的度量

皮尔逊与 Jupyter 笔记本的积矩相关性

towardsdatascience.com](/a-measure-of-linear-relationship-5dd4a995ee7e) [## 轻松创建统计数据的 Python 包

Statsfig 可以用一行代码创建分布图和盒须图

towardsdatascience.com](/a-python-package-to-create-stats-figures-with-ease-503cf6ec0b26)

使用 Optuna 获得精确的 Scikit 学习模型:一个超参数框架

原文:https://towardsdatascience.com/exploring-optuna-a-hyper-parameter-framework-using-logistic-regression-84bd622cd3a5?source=collection_archive---------10-----------------------

在过去的几个月里,超参数框架一直是讨论的热点。有几个软件包已经开发并仍在开发中,选择一个已经成为一个艰难的选择。这种框架不仅有助于拟合精确的模型,还可以帮助数据科学家将效率提高到一个新的水*。在这里,我展示了如何使用最*流行的 Optuna 框架来获得任何 Scikit-learn 模型的最佳参数。我只实现了随机森林逻辑回归作为例子,但是其他算法也可以以这里所示的类似方式实现。

为什么是 Optuna?

如果整合到日常实验中,Optuna 可以成为工作马工具之一。当我使用 Optuna 以如此小的努力实现逻辑回归时,我被深深地打动了。以下是我喜欢 Optuna 的几个原因:

  • API 的易用性
  • 出色的文档
  • 适应任何算法的灵活性
  • 像修剪和内置可视化模块这样的功能

文件:https://optuna.readthedocs.io/en/stable/index.html

Github:https://github.com/optuna/optuna

在我们开始查看功能之前,我们需要确保我们已经安装了必备的软件包:

  1. 奥普图纳
  2. Plotly
  3. 熊猫
  4. sci kit-学习

基本参数和定义:

建立基本框架非常简单明了。它可以大致分为 4 个步骤:

  1. 定义一个目标函数(步骤 1)
  2. 定义一组超参数进行尝试(步骤 2)
  3. 定义您想要优化的变量/指标(步骤 3)
  4. 最后,运行功能。这里需要提一下:
  • 您试图优化的得分函数/变量 将被最大化或最小化
  • 您想要进行的试验次数。超参数的数量越多,定义的试验次数越多,计算成本就越高(除非你有一台强大的机器或 GPU!)

Optuna 世界中,术语试验是目标函数的单个调用,多个这样的试验一起被称为研究。

以下是 scikit-learn 包中随机森林逻辑回归的基本实现:

当您运行上面的代码时,输出如下所示:

终端或笔记本电脑中的输出

正如我们在上面看到的,逻辑回归和随机森林的选择以及它们各自的参数在每次运行中都有所不同。每次试验可以是具有不同参数的不同算法。研究对象存储各种输出,可以按如下方式检索:

更详细的结果

正如我们在这里看到的, 21随机森林n _ 估计量153最大深度最适合这个数据集。

定义参数空间:

如果我们在步骤 2 (basic_optuna.py)中查看,我们将超参数 C 定义为具有浮点值的日志。类似地,对于随机森林,我们定义了 max_depth 和 n_estimators 作为要优化的参数。Optuna 支持五种定义参数的方式:

定义参数

历史研究:

坦纳·马迪斯Unsplash 上拍摄的照片

我觉得,数据科学家的一个基本需求是,他们希望跟踪所有的实验。这不仅有助于比较它们中的任意两个、三个或多个,而且有助于理解模型在超参数变化、添加新特征等情况下的行为。Optuna 内置了记录所有实验的功能。在访问旧实验之前,我们需要存储它们。下面的代码显示了如何执行这两个命令:

  1. 您可以选择一个名称来创建实验
  2. 存储为关系数据库(RDB) 形式。我这里用的是 sqlite 。其他选项是使用 PostgreSQL,MySQL 。您也可以使用 joblib 作为本地 pkl 文件来存储和加载
  3. 之后继续进行研究

这里的存储是一个额外的参数,如果您想使用 RDB 存储选项,需要在 create_study 函数中传递。此外,设置load _ if _ exists =True将加载一个已经存在的检查。对于 joblib,它类似于如何存储和加载一个训练好的模型。再次运行将根据上次存储的试验开始优化试验次数。

如果我们使用以下方法,可以获得研究中所有试验的详细概览:

所有试验的结果

从上面的结果中可以看出,对于不适用于该算法的列/参数,有一个 NaN 值。除此之外,我们还可以计算每次试验所花费的总时间。有时,时间考虑是至关重要的,因为它提供了一种思路,即与其他参数相比,特定的参数集是否需要更长的时间来拟合。

分布式优化:

您可以在您的机器上运行多个作业,以实现超参数优化。使用 Optuna 运行分布式超参数优化非常简单。我认为使用 Optuna 作为超参数优化框架是有益的。考虑我们定义并存储为名为 optimize.py 的 python 文件的相同目标函数。参数建议将基于试验的历史,并在我们在多个终端中运行时进行更新:

在两个独立的终端中运行,输出如下所示:

端子 1 输出

端子 2 输出

比较终端 1 的输出和终端 2 的输出,我们可以看到随机森林和逻辑回归选择了不同的参数。在终端 1 中,我们看到所有试验都只选择了随机森林。在终端 2 中,仅选择了 1 个逻辑回归试验。您可以看到两个输出的试验号不同。此外,如果您使用 n_jobs 参数获得多个可用内核,您还可以增加作业数量,使其速度更快。

添加属性:

帕特里克·帕金斯在 Unsplash 上拍摄的照片

在评估历史实验时,为实验做一些笔记或属性会有很大帮助。用户可以使用 set_user_attr 方法为试验研究添加键值对,如下所示:

用户可以在研究对象上使用 user_attrs 方法访问属性,如上面的代码所示。我认为这是使用 Optuna 时可用的附件。

修剪:

https://Cornell farms . com/blogs/resources/pruning-fruit-trees

如图所示,修剪会删除树中不需要的或多余的分支。类似地,在机器学习算法的世界中,修剪是移除对分类器提供很少能力的部分的过程,并且有助于减少分类器的过度拟合,反过来提供更好的准确性。机器学习从业者必须精通术语“提前停止”,这类似于 Optuna 中修剪的工作方式。

运行 pruning.py 后的输出(上面的代码)

如上所示,对于特定的试验,如果结果不优于中间结果,试验被删除(这里是试验 7 和试验 10)。Optuna 中还提供其他类型的修剪程序,如 MedianPruner、NopPruner、PercentilePrunerSuccessiveHalvingPruner 等。你可以试着在这里得到更多的信息。

可视化:

除了上面显示的功能,Optuna 还提供了一些预先编写的可视化代码。这个可视化模块就像蛋糕上的樱桃,让我们更好地理解算法的适用性。我把其中的一些画在下面:

优化历史图:

优化历史图显示每次试验获得的目标值,并绘制最佳值。最佳值是一条直线,直到达到下一个最佳值,如下图所示:

优化历史图

*行坐标图:

*行坐标图有助于理解研究中的高维参数关系。这里我们只选择随机森林,我们将 x 轴视为参数 max_depthn _ estimatorsv/s y 轴上的目标值。我们可以看到,最佳优化值的试验是 max_depth ~ 23 和 n_estimators ~ 200。

*行坐标图

切片图:

该图有助于绘制传递给优化的所有参数之间的关系。切片图类似于上面显示的*行坐标图。

切片图

这里显示的所有可视化只是针对两个参数。如果使用多个参数,会发现它非常有用。这些图变得更加密集,可以提供参数之间关系的清晰图像。还有许多其他实现的可视化可以在这里找到。

结论:

Optuna 不仅限于用于 scikit-learn 算法。或许,TensorFlow、Keras 之类的神经网络,XGBoost、LightGBM 之类的梯度增强算法以及许多其他算法也可以使用这个奇妙的框架进行优化。Optuna 贡献者的一些例子已经可以在这里找到了。Optuna 是我遇到的最好的通用框架之一。正如我之前提到的,与众不同的是优秀的文档支持几乎所有的算法根据需要修改的灵活性等等。除此之外,Optuna 社区已经在框架的顶部构建了许多包装器,并且还在增长,负责许多繁重的工作。总的来说,Optuna 是一个巨大的超参数框架,可以作为数据科学工具包的一部分,我强烈推荐给任何数据科学家。

探索 Python 范围函数

原文:https://towardsdatascience.com/exploring-python-range-function-d509ebd36ec?source=collection_archive---------4-----------------------

了解 Python Range()函数及其功能

照片由Unsplash 上拍摄

介绍

range()是 Python 中的内置函数。默认情况下,它返回一个从零开始递增 1 的数字序列,并在给定的数字之前停止。

现在我们知道了范围的定义,让我们看看语法:

**range***(start, stop, step*)

它有三个参数,其中两个是可选的:

  • **start:**可选参数,用于定义序列的起点。默认情况下是零。
  • **stop:**这是一个强制参数,用来定义序列的停止点
  • **step:**它也是一个可选参数,用于指定每次迭代的增量;默认情况下,该值为 1。

一般用法

由于它返回一个数字序列,大多数开发人员使用这个范围来编写循环。当您没有列表或元组,而只有实现循环的特定值时,这很方便。

变奏一

这里,我们将实现一个只有一个参数— stop值的 for 循环。

这里x 是我们用来实现循环的范围,n 是每次迭代中的值。观察到输出在stop值之前结束;它绝不是类似于list.size()的范围迭代的一部分。

变奏二

这里我们将使用 start 和 stop 作为参数来实现 for 循环。

变奏三

现在,我们将使用所有三个参数:startstopstep。看一看:

当步长值为 2 时,循环在每次迭代时增加 2,而不是增加 1。我们需要记住的一件重要事情是步长值永远不应该为零;否则,它将抛出一个ValueError异常。

列表类型上的迭代

除了循环之外,range()还用于使用len函数遍历列表类型,并通过index访问值。看一看:

反向范围

对于该范围内的任何参数,我们可以给出正数或负数。这个特性提供了实现反向循环的机会。我们可以通过传递一个更高的索引作为start和一个负的step值来实现。看一看:

使用范围创建列表、集合和元组

range()在很多情况下都很方便,而不仅仅是用来写循环。例如,我们使用范围函数创建列表、集合和元组,而不是使用循环来避免样板代码。看一看:

为了更有趣一点,我们可以在 step 中传递负值来创建升序列表。看一看:

索引范围

就像我们使用索引访问列表中的值一样,我们可以对 range 做同样的事情。语法也类似于列表索引访问。

浮动范围内的参数

默认情况下,range()函数只允许整数作为参数。如果您传递流值,那么它会抛出以下错误:

TypeError: 'float' object cannot be interpreted as an integer

但是有一个解决方法;我们可以编写一个类似下面的自定义 Python 函数。它将允许您为步长参数指定一个浮点值。

奖金

要了解更多关于 Python 从基础到高级的知识,请阅读以下文章

就这些了,希望你能学到一些有用的东西,感谢阅读。

你可以在 MediumTwitterQuoraLinkedIn 上找到我。

探索 Excel 和 Python 中的工资数据趋势

原文:https://towardsdatascience.com/exploring-salary-data-trends-in-excel-and-python-34b2bc7142a7?source=collection_archive---------49-----------------------

图为亚历山大·米尔斯Unsplash

最*有人告诉我关于自我报告的匿名工资信息,所以我很想分析这些数据,看看会出现什么样的模式。

公开分享这些信息提高了透明度,有利于理解和避免妇女和有色人种经历的薪酬不*等。通过这些数据可以找到一个人的年龄组,经验水*和类似的角色,看看他们可以期望什么样的薪酬水*。人们可以利用这些信息来确定他们是否报酬过低,或者选择最值得从事的职业。

在本文中,我将完成数据科学管道的第一步,即数据清理,并以几个可视化的例子来结束,以便更好地理解这些数据。最后,我将介绍这些数据的未来发展方向。

数据采集和数据清理

数据集

该数据集通过谷歌表格填充,并在互联网上各种关于女性和少数族裔在工作场所薪酬不*等的博客帖子中被引用。你可以在这里阅读这份自报工资的趋势,在这里查看原始数据集

数据清理

虽然到目前为止已经记录了如此多的回复(在撰写本文时有 34,000 个),但该表单没有针对薪水的数据验证。这意味着是时候着手数据清理工作了。

要清理的正则表达式

正则表达式(Regex)是描述文本中要匹配的模式,然后执行某些操作(如匹配、替换或提取匹配的文本)的方法。Excel/Google 工作表有正则表达式函数(REGEXMATCHREGEXREPLACEREGEXEXTRACT),它们执行上述功能。

打扫卫生时,你首先要找出你最大的问题是什么,从你能看到/想到的更一般的问题到更具体的问题。一旦你知道要修复什么,你就实现它,测试它的准确性,然后在必要的时候改进它。在这种情况下,我看到有些工资含有文字。这不是我们所有的工资只是数字。我们希望最终将它们转换为整数数据类型。

不干净工资的例子

我的下一个问题是,有多少薪水不仅仅是数字。我创建了一个新列来创建一个二进制标志,如果annual_salary中的单元格包含字母 A-Z(不区分大小写),则该标志返回 TRUE。如果是,打印 TRUE,否则打印 FALSE。

=IF(REGEXMATCH(E34166, “[A-Za-z]+”), TRUE, FALSE)

我在一个名为how many salaries have just numbers?的新列中为每个薪水单元格运行了这个,在该列中,我看到 96%的薪水只是数字,这是个好消息。我注意到,在这 4%的脏数据中,50%只是因为人们用“K”或“K”缩写了千位,例如:62K 或 51k。

看到这一点,我添加了另一个 flag 列,以便只匹配 salary 中只有一个大写或小写“k”的情况,我还添加了另一个列,以便能够对此进行筛选:

=IF(REGEXMATCH(E2, "[Kk]{1}"), TRUE, FALSE)

作为所有可能问题中最大的一个,我创建了一个修复程序来检查has_a_k_bool列中的 1。如果那一列有一个 1,这意味着薪水是用 k 缩写的,所以我只提取了数字,然后乘以 1000,否则,我只提取了数字,因为它们被认为是干净的。这是我用的公式:

=IF( G209=1, VALUE(REGEXEXTRACT(E209,"[0-9]+"))*1000, VALUE(REGEXEXTRACT(E209,"[0-9]+")))

我还注意到,那些自称“18 岁以下”的人报告的大部分工资要么是时薪,要么低得多(异常值)。因为这个数据集主要是为大学以外的人准备的,所以我添加了一个标志来将他们从最终的数据集中移除。

=IF(B197="Under 18", 1, 0)

为了执行我的数据清理,我遵循了一个具有循环依赖的过程。第一步是观察原始数据中的错误。其次,我实现了一个标志,通过这个标志进行过滤来找出问题的大小。然后,我测试了一个问题的修复,看我能在多大程度上减少原来的问题。然后,如果需要,我改进了我的方法,并再次测试了实现的性能。

在一个新的选项卡上,我使用 FILTER 函数用一些附加的标准查询了原始的 raw data 选项卡。这将接受一个数据范围和一些标准,返回该范围的过滤视图。

=FILTER('Raw Data'!B:P,'Raw Data'!G:G = 1)

G 栏是我检查他们是否在 18 岁以下的标志。

原始数据格式

虽然我们可以而且应该进一步清理,因为工资取决于位置和其他因素,但这超出了本文的范围。

以下是我的数据的最终格式:

干净的数据集

一些可视化

此时,由于内存的使用,建议退出 Google Sheets。我下载了 CSV 并开始用 Python 在 Jupyter 笔记本上工作。

我将分享我所做的一些高层次的探索。当然,还有很多值得探索的地方!

不幸的是,Excel 数据类型不是很合适,我们的薪水本应该是类型number的,但当它们进入 Python 时就不合适了。在将数据集从 CSV 加载到 Pandas 数据框架后,我的第一步是将每一列强制转换为它们应有的数据类型:

数据类型强制

为了便于参考和节省输入,我为我查看的每一列分配了一个变量:

列分配

我怀疑这些数据可能偏向于中级专业人士(25-34 岁年龄段),所以我通过计数图验证了这一点。这是为该信息生成绘图的代码:

年龄分布图

和结果图:

年龄分布

这证实了我的假设,即数据集中的大多数值都在 25-34 岁的年龄范围内,高级专业人员占了剩余部分(35-44 岁)的大部分。

然后,我观察了大学毕业后经历的年数分布,以了解人们的经历程度:

经验分布图代码

下面是由上面的代码生成的图:

经验分布图

上图显示了大致相同的信息,就是大部分人 22 岁毕业开始工作。这意味着 25-34 岁年龄组中的大多数人将有 2 到 12 年的工作经验。这看起来就在上图的右边。

结论

结果

在 Google Sheets 的数据清理步骤之后,人们可以简单地过滤数据集,以显示他们的年龄组、经验水*组和位置。然后他们会开始大致了解你应该得到多少报酬。另一个有价值的结果可能是通过职位看到你期望得到什么,这可以帮助你决定你潜在的职业道路!

未来的步骤

薪资信息是相对的,并且各不相同,取决于地点、行业和职位/类型。因此,需要 NLP 来标准化这些字段。这是因为,在工业的拼写上,即使看似很小的差异也会使电脑失灵。例如:“高等教育”、“高等教育”、“edu”、“教育”和“教育”对人类来说显然都是教育行业,但对计算机来说是不同的行业,因为这些值是不等价的!这就是我们今后将这篇文章引向的地方。

感谢阅读和快乐编码!我也很乐意与人交流。在 GitHubLinkedIn 上找到我。

奢侈的生活

探索 SimCLR:视觉表征对比学习的简单框架

原文:https://towardsdatascience.com/exploring-simclr-a-simple-framework-for-contrastive-learning-of-visual-representations-158c30601e7e?source=collection_archive---------10-----------------------

从头开始用一个 PyTorch 实现 SimCLR

介绍

很长一段时间以来,我们知道迁移学习在计算机视觉(CV)应用中的好处。如今,预训练的深度卷积神经网络(DCNNs)是学习新任务的第一个首选预解决方案。这些大型模型是在巨大的监督语料库上训练的,比如 ImageNet。最重要的是,它们的特点是能很好地适应新问题。

当缺少带注释的训练数据时,这一点尤其有趣。在这种情况下,我们采用模型的预训练权重,在其上添加一个新的分类器层,并重新训练网络。这被称为迁移学习,是 CV 中使用最多的技术之一。除了在执行微调时的一些技巧(如果是这样的话),已经(多次)表明:

如果为一项新任务进行训练,用预训练权重初始化的模型往往比使用随机初始化从零开始训练的模型学习得更快、更准确。

然而,正如人们可能猜测的那样,在这个过程中存在一个瓶颈。目前大多数迁移学习方法依赖于在监督语料库上训练的模型。但是问题是注释数据并不便宜。

如果我们环顾四周,数据,以一种无人监管的方式,是丰富的。因此,使用未标记的数据来学习表示是有意义的,这些表示可以用作训练更好的监督模型的代理。事实上,这是一个长期存在的问题,正如我们将看到的,当前对无监督表示学习的研究终于赶上了有监督的方法。

无监督表示学习

无监督表示学习关注于解决以下问题:

我们如何从未标记的数据中学习好的表示?

除了什么是好的表示的问题之外,从未标记的数据中学习也有很大的潜力。它可以开启许多当前迁移学习无法解决的应用。然而,从历史上看,无监督的表示学习比有监督的表示学习要困难得多。

作为一个简单的例子,让我们考虑乳腺癌检测的任务。目前,所有最佳解决方案都使用 ImageNet 预训练模型作为优化流程的起点。有趣的是,尽管乳腺癌幻灯片图像和常规 ImageNet 样本之间存在显著差异,但迁移学习假设在某种程度上仍然成立。

大致来说,大多数用于乳腺癌检测的监督数据集,如camelion 数据集,在大小和可变性方面都无法与常见的计算机视觉监督数据集相比。另一方面,我们有大量未加注释的乳腺癌幻灯片图像。因此,如果我们可以从无监督的(大得多的语料库)中学习良好的表示,这肯定会有助于学习更多特定的下游任务,这些任务具有有限的注释数据。

幸运的是,视觉无监督表示学习已经显示出巨大的前景。更具体地说,使用基于对比的技术学习的视觉表现现在达到了通过监督方法学习的水*——在一些自我监督的基准测试中

让我们探索一下无监督的对比学习是如何工作的,并仔细看看该领域的一项主要工作。

对比学习

对比法的目的是通过强制相似元素相等而不相似元素不同来学习表征。

最*几个月,我们看到了基于这些原则的无监督深度学习方法的爆炸式增长。事实上,在线性分类基准中,一些自我监督的基于对比的表示已经匹配基于监督的特征。

对比学习的核心是噪声对比估计(NCE)损失。

上式中,可以把 x+ 看作类似于输入 x 的数据点。换句话说,观察值 xx+ 是相关的,并且一对 (x,x+) 代表一个正例。通常情况下, x+ 是对 x 进行某种变换的结果。这可以是旨在改变 x 的大小、形状或方向的几何变换,或者任何类型的数据增强技术。一些例子包括旋转、透明、调整大小、剪切等等

另一方面, x- 是与 x 不同的例子。对 (x,😆 形成了一个反例,它们应该是不相关的。在这里,NCE 损失将迫使他们不同于积极的一对。注意,对于每个正对 (x,x+) 我们有一组 K 个负对。事实上,经验结果表明,需要大量的否定才能获得良好的表象。

**sim(。)函数是一个相似性(距离)度量。它负责最小化阳性之间的差异,同时最大化阳性和阴性之间的差异。 经常,sim(。)点积余弦相似度**来定义。

最后, g(。)是一种卷积神经网络编码器。具体来说,最*的对比学习架构使用暹罗网络来学习正面和负面示例的嵌入。这些嵌入然后作为输入传递给对比损失。

简单地说,我们可以把对比任务看作是试图在一堆否定中找出肯定的例子。

视觉表征对比学习的简单框架——sim clr

SimCLR 使用上述对比学习的相同原则。在本文中,该方法在自监督和半监督学习基准中实现了 SOTA。它引入了一个简单的框架来学习基于大量数据扩充的无标签图像的表示。简单来说,SimCLR 使用对比学习来最大化同一图像的两个增强版本之间的一致性

学分: 视觉表征对比学习的简单框架

为了理解 SimCLR,让我们探索一下它是如何建立在对比学习框架的核心组件之上的。

给定一个输入图像,我们通过应用两个独立的数据扩充操作符来创建它的两个相关副本。这些变换包括(1) 随机裁剪和调整大小 , (2) 随机颜色扭曲,( 3)随机高斯模糊

操作的顺序是固定的,但是由于每个操作都有自己的不确定性,这使得结果视图在视觉上有所不同。请注意,由于我们在同一幅图像上应用了 2 个不同的增强函数,如果我们对 5 幅图像进行采样,我们最终会得到批次中的2**×5 = 10个增强观察值。参见下面的视觉概念。

为了最大化底片的数量,想法是将批中的每个图像(索引为 i )与所有其他图像(索引为 j )配对。注意,我们避免将观察 i 与其自身以及其扩充版本配对。结果,对于批中的每个图像,我们得到 2 ×(N-1) 负对— ,其中 N 是批大小

注意,同样的方法适用于给定观测的两个扩充版本。这样,负对的数量增加得更多。

而且通过这种方式排列否定样本, SimCLR 的优点是不需要额外的逻辑来挖掘否定。为了有一个概念,最*的实现像 PIRL T21 和 MOCO 分别使用一个存储体和一个队列来存储和采样大批量的底片。

事实上,在最初的实现中,SimCLR 的批处理大小为 8192。按照这些想法,这个批量产生每个正样本对 16382 个负样本。此外,作者还表明,更大的批次(因此更多的阴性)往往会产生更好的结果。

SimCLR 使用 ResNet-50 作为主要的 ConvNet 主干。ResNet 接收形状为 (224,224,3) 的增强图像,并输出 2048 维嵌入向量 h 。然后,一个投影头**g(。)*** 应用于嵌入向量*产生最终表示 z = g(h)投影头 g(。) 是一个有 2 个密集层的多层感知器(MLP)。两层都有 2048 个单位,隐藏层具有非线性(ReLU)激活功能。**

对于相似度函数,作者使用余弦相似度。它测量 d 维空间中两个非零向量之间角度的余弦值。如果两个向量之间的角度为 0 度,则余弦相似度为 1。否则,它输出一个小于 1 一直到-1 的数。注意,对比学习损失作用于投影头 g(.)z嵌入向量

一旦系统被训练好,我们就可以通过把投影头g(。)** 并使用表象 h (直接来自 ResNet)来学习新的下游任务。**

培训和评估

一旦对比学习目标的组成部分就位,系统的训练就简单了。你可以在这里看一下我的实现

为了训练模型,我使用了 STL-10 数据集。它包含 10 个不同的类,每个类有合理的少量观察值。最重要的是,它包含一个更大的无监督集,其中有 100000 个未标记的图像——这是用于训练的大部分图像。

对于这个实现,我使用 ResNet-18 作为 ConvNet 主干。它接收形状为 (96,96,3) 、常规 STL-10 尺寸的图像,并输出尺寸为 512 的矢量表示。投影头 g(。)** 有 2 个全连通层。每层有 512 个单元,产生最终的 64 维特征表示 z 。**

为了训练 SimCLR,我采用了数据集的 训练+未标记的 部分— ,总共给出了 105000 个图像

在训练之后,我们需要一种方法来评估 SimCLR 所学习的表示的质量。一种标准方法是使用线性评估协议*。*****

想法是在来自 SimCLR 编码器的固定表示上训练线性分类器。为此,我们获取训练数据,将其传递给预训练的 SimCLR 模型,并存储输出表示。注意,此时,我们不需要投影头 g(。)再也没有了。

这些固定的表示然后被用于使用训练标签作为目标来训练逻辑回归模型。然后,我们可以测量测试的准确性,并使用它作为特性质量的度量。

这个 Jupyter 笔记本显示了评估协议。使用 SimCLR 固定表示作为训练信号,我们达到了 64%的测试精度。有一个想法,对训练数据执行 PCA 并保留最重要的主成分,我们得到的测试精度只有 36%。这强调了 SimCLR 所学习的特征的质量。

一些最后的评论

最初的 SimCLR 论文还提供了其他有趣的结果。其中包括:

  • 非监督对比特征学习在半监督基准上的结果;
  • 向投影头添加非线性层的实验和益处;
  • 使用大批量的实验和好处;
  • 用对比目标训练大型模型的结果;
  • 对比学习中使用多种强数据扩充方法的消融研究;
  • 标准化嵌入对训练基于对比学习的模型的好处;

我鼓励你看看这篇文章,了解更多的细节。

感谢阅读!

参考文献

陈,丁等,“视觉表征对比学习的一个简单框架”arXiv 预印本 arXiv:2002.05709 (2020)。

米斯拉、伊山和劳伦斯·范德马腾。"借口不变表征的自我监督学习."arXiv 预印本 arXiv:1912.01991 (2019)。

何,,等,“无监督视觉表征学习中的动量对比”arXiv 预印本 arXiv:1911.05722 (2019)。

-何,,等,“深度残差学习在图像识别中的应用”IEEE 计算机视觉和模式识别会议录。2016.

原载于https://sthalles . github . io**

探索人工智能地牢

原文:https://towardsdatascience.com/exploring-the-ai-dungeon-253ddc577011?source=collection_archive---------32-----------------------

GPT 的不幸遭遇-3

Mauro Sbicego 在 Unsplash 上拍摄的照片

GPT-3 是由 OpenAI 创建的语言模型,它可以在给出提示的情况下形成自然语言。幕后是一个神经网络,有 1750 亿个参数,从互联网上收集了大量数据。结果是一台能够理解并回答 GPT 3 号提出的问题的机器。除了英语,它还不会说或写任何东西。但它确实对基本语法有所了解。这意味着,如果你让它告诉你什么是三角形,它会说‘一个三面体’或类似的东西。

我必须承认:我讨厌写介绍。所以我写了上面这一段的前两句话,把它插入 AI 地牢中,加上一些上下文,这一段的剩余部分就出来了。(我们马上就会看到,GPT 3 号在这里严重抛售自己。)

截图自 AI 地牢

它显然并不完美,但应该考虑到 AI Dungeon 运行的是 GPT 3 的较弱版本,并且被配置为基于文本的游戏,而不是一种写作作弊的方式。如下例所示,完整的 GPT-3(目前对其访问受到严格限制)可能会被误认为是大学水*的作家。

在我的家庭中,关于“牛仔”一词的起源一直存在争议。我们知道这个词最初是用来描述一个牧民或赶牛的人。我的一些家人坚持认为这个词是在西班牙创造的,描述的是那些工人的墨西哥或西班牙版本。

另一方面,我父亲的家庭坚持认为,这个词是英国牛仔用来形容强悍但总体上*和的牧民或牧人的。

几周前,当我们和我的父亲和他的妻子,我的继母 Barb 一起去看《独行侠》时,这个争论又出现了。他们坚持说,骑白马的人是治安官,不是牛仔。

我最终承认我并不在乎这个术语是从哪里来的,我们都笑了起来。(摘自 GPT-3 回购协议;)

偶尔,人工智能的笨拙和重复暴露了它的身份:

冰河岭的学生参加了各种比赛和竞赛。(摘自 GPT-3 回购协议;)

*心而论,许多人类作家都有类似的缺陷。然而,很少有人能用西班牙语、法语、T4 语、匈牙利语和葡萄牙语书写。

图灵测试

记得尤金·古斯曼吗?2014 年,聊天机器人因通过图灵测试而成为国际头条,说服了 30%的小组成员相信它是人类。尤金·古斯特曼是一个来自乌克兰的 13 岁男孩,充满了俚语、缩写和冷漠的语气。聊天机器人是否成功通过图灵测试仍然是一个有争议的话题;几乎可以肯定,模仿一个怀有敌意的 13 岁孩子比在智力对话中冒充人类要容易得多。

自然,我想看看 GPT-3 在图灵测试中表现如何,但我需要一些标准来评估它的反应。谢天谢地,图灵提供了一个审讯者和计算机之间的对话样本,我试图复制它。

为了促使 GPT-3 回答与图灵对话中相同的问题,我首先给询问者起名叫“保罗”,给计算机起名叫“杰克”。我这样做的目的是为了避免任何混淆,在对话中询问者和计算机是两个独立的角色。然后,我提供了一些关于接下来讨论的背景(斜体)。样本对话和我哄骗人工智能地牢之间有一些相似之处,但对话在中途很大程度上破裂了。

一个单独的对话是否表明能够通过图灵测试是值得怀疑的。然而,如果你认为古斯特曼通过了图灵测试,那么 GPT-3 似乎也能做到。

棘手的问题

通过人工智能地牢的一些操作,我们可以采访来自各种领域的名人的模仿。以下是大数据领域假拉里·佩奇的一个片段:

(改善我们对大数据的使用)有两种主要方法。第一种是自动化,或者我喜欢把它称为智能药丸……另一种方法是以不同的方式分析数据。比如这些数字背后都有什么故事?这个人为什么买东西?他们有什么故事?如果我们能理解所有这些,我们就能有针对性地做广告,所以这对人们真的很重要。

在采访的另一部分,佩奇开始谈到,在他六岁时,由于他妹妹的出生,有人想杀了他,所以考虑一下上面手里拿着盐罐的摘录。你可以在这里阅读这篇采访的全文。

也是你下一篇文章的灵感来源:

以下是发表在 towardsdatascience.com 主办的媒体刊物《走向数据科学》上的一篇文章的标题:“数据科学家分析自己代码的新工具。****

你打开文章读了一遍。这是你的一个同事写的,他继续解释说他或她已经创建了一个名为“数据分析工具包”的程序,它允许你轻松地分析你自己的代码

我必须承认,我已经拥有了这样一个工具包。这叫做“漫无目的地滚动,试图找出为什么我的代码被破坏了”。如果你问我,我会说这很有创意——显然 GPT 3 号有不同的想法。

埃米尔·佩龙在 Unsplash 上拍照

假装直到你成功?

我在 GPT 3 的经历给我留下了深刻的印象,但也暴露了它的局限性。最终,GPT 3 号不可思议地模仿了从互联网上刮来的东西,而不是展示一般的智力。即使是完整版,除了最基本的算术都有问题,而且玩的是一盘相对较弱的棋。

OpenAI 首席执行官 Sam Altman 的推文

以人类的标准来判断,GPT 3 号可能笨得让人麻木。这并没有阻止它执行以前被认为是高智能人类领域的任务。这个 Twitter 帖子整理了它的一些成就,包括以各种风格编写小说,从简单的功能描述中生成一个工作的 React 应用程序,以及法律写作。

在这一点上,我相当确信,人们会因为像 GPT-3 这样的语言模型的进步而丢掉工作。我脑子里唯一的问题是,这种情况会在未来五年还是十年发生。人工智能可能离实现还很远,但智能不是扰乱社会的先决条件。

现在,我会享受玩 AI 地牢的乐趣,尽量不去考虑几年后我可能要和它竞争一份工作。我在骗谁呢?到时候就没有竞争了。

探索条形码世界

原文:https://towardsdatascience.com/exploring-the-barcode-universe-6c80dbebb356?source=collection_archive---------50-----------------------

用 Wolfram 语言编写的计算思维故事

Johannes Plenio 在 Unsplash 上拍摄的照片

人类无法理解,但对电脑和手机来说却是小菜一碟:条形码无处不在。每一件产品,每一个包装,每一个货架上都有大量的细菌。黑白图案,通常是线,有时是点,为我们的硅朋友提供了一个小数字,概括了这个物体的所有内容。

像 barcodelookup.com这样的在线服务提供了拥有数百万商品的数据库,将这些小数字转化为丰富的信息,如产品名称、产品类别和特定供应商的信息。

在 Wolfram 语言中,您可以读取条形码,也可以创建条形码图像。它没有内置的服务来解释条形码,但在这个故事中,我将向您展示如何从 BarcodeLookup 服务连接到 API。

先从自己生成条形码说起。这里使用的函数叫做 BarcodeImage 。它可以生成最常见类型的条形码。例如,这会生成一个 UPC 条形码图像:

BarcodeImage["123456789999", "UPC"]

(图片由作者提供)

这是一个二维码的例子。大多数智能手机会在你将摄像头对准网页时打开网页:

BarcodeImage["https://www.wolfram.com", "QR"]

(图片由作者提供)

自动识别条形码是通过条形码识别功能完成的。即使条形码只是图像的一部分,它也能工作,尽管它偶尔会拾取一个“偏离的”条形码。在这种情况下,结果是正确的:

(图片由作者提供)

接下来,为了解释代码“04150800414 ”,我编写了一个简单的 Wolfram 语言函数,它绑定到条形码查找服务的 API。

[## 条形码查找

在线查找条形码

www.wolframcloud.com](https://www.wolframcloud.com/obj/arnoudb/DeployedResources/Function/BarcodeLookup)

可以通过其名称来访问它:

BarcodeLookup = ResourceFunction[
 "user:arnoudb/DeployedResources/Function/BarcodeLookup"
]

现在我们可以查找产品信息了。“密钥”是一个由条形码查找服务 API 要求并提供的小型字母数字字符串。

product = BarcodeLookup["041508300414",key]

例如,您可以通过编程方式向下钻取产品名称:

In[]:= product["products", 1, "product_name"]Out[]= "San Pellegrino Pompelmo Grapefruit Sparkling Fruit Beverage, 11.15 Fl. Oz., 6 Count"

这里的应用可能性几乎是无限的。有了这些功能,构建跟踪库存、生成报告和自动重新进货程序的应用程序变得很容易。

探索冠状病毒数据集

原文:https://towardsdatascience.com/exploring-the-corona-virus-dataset-781de3a636e2?source=collection_archive---------12-----------------------

新型冠状病毒 2019 数据集的探索性数据分析

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

在本帖中,我们将对新型冠状病毒 2019 数据集进行简单的探索性数据分析。数据集可以在 Kaggle 上找到。该数据包含 2019 年病例数、死亡数和恢复数的每日信息。数据集“covid_19_data.csv”包含以下各列:

  1. Sno —序列号
  2. 观察日期—观察的日期,以年/月/日为单位
  3. 省/州—观察的省或州
  4. 国家/地区—观察国
  5. 上次更新时间-以 UTC 表示的给定省或县的行更新时间
  6. 已确认—截至该日期的累计已确认病例数
  7. 死亡人数——截至该日期的累计死亡人数
  8. 已恢复—到该日期为止已恢复案例的累计数量

让我们将数据读入熊猫数据框:

import pandas as pddf = pd.read_csv("covid_19_data.csv")

让我们打印前五行数据:

print(df.head())

我们可以做的第一件事是在“Confirmed”列上生成一些统计数据。让我们来看看确诊病例的均值和标准差:

print("Mean: ", df['Confirmed'].mean())
print("Standard Deviation: ", df['Confirmed'].std())

我们还可以生成已确认累积病例的直方图:

import seaborn as sns 
import matplotlib.pyplot as plt
sns.set()
plt.title("Confimed Cases Histogram")
df['Confirmed'].hist(bins = 10)

我们可以为恢复的案例生成类似的统计数据:

print("Mean: ", df['Recovered'].mean())
print("Standard Deviation: ", df['Recovered'].std())

并绘制直方图:

plt.title("Recovered Cases Histogram")
sns.set()
df['Recovered'].hist(bins = 200)

最后,我们可以看看死亡的统计数据:

print("Mean: ", df['Deaths'].mean())
print("Standard Deviation: ", df['Deaths'].std())

以及直方图:

plt.title("Deaths Histogram")
sns.set()
df['Deaths'].hist(bins = 200)

我们还可以使用 collections 模块中的“Counter”方法查看省/州的频率:

from collections import Counter
print(Counter(df['Province/State'].values))

让我们删除缺失的值,并将计数器限制为仅输出五个最常见的省份:

df.dropna(inplace=True)
print(Counter(df['Province/State'].values).most_common(5))

我们还可以使用盒状图来显示基于最小值、最大值、中值、第一个四分位数和第三个四分位数的数值分布。如果你对它们不熟悉,可以看看文章了解盒图

来源

例如,让我们绘制“安徽”、“北京”和“重庆”确诊病例的分布图:

df = df[df['Province/State'].isin(['Anhui', 'Beijing', 'Chongqing'])]
sns.boxplot(x= df['Province/State'], y = df['Confirmed'])
plt.show()

我们可以对恢复的案例做同样的事情:

df = df[df['Province/State'].isin(['Anhui', 'Beijing', 'Chongqing'])]
sns.boxplot(x= df['Province/State'], y = df['Recovered'])
plt.show()

对于死亡:

df = df[df['Province/State'].isin(['Anhui', 'Beijing', 'Chongqing'])]
sns.boxplot(x= df['Province/State'], y = df['Deaths'])
plt.show()

我就讲到这里,但是您可以随意使用数据并自己编码。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

探索数据:从食物营养中学习

原文:https://towardsdatascience.com/exploring-the-data-learn-from-the-food-nutrition-a4ea2110522a?source=collection_archive---------18-----------------------

在没有明确目标的情况下,我们可以尝试从数据中探索什么

布鲁克·拉克在 Unsplash 拍摄的照片

我喜欢探索我的数据,并从中发现意想不到的模式。作为一名数据科学家,在我个人看来,我们需要具备这种好奇心特质,才能在这个领域取得成功。探索数据的方法不仅限于诸如可视化数据和获得统计数字的基本技术,一种方法是实现机器学习。

机器学习也是一种探索数据的技术,而不仅仅是人们经常喜欢宣传的预测目的。这就是为什么我经常专注于理解模型的概念,以了解我的数据是如何处理的;更好地了解我们的数据发生了什么变化。

在本文中,我想介绍通过无监督学习来探索数据,我们可以从统计数字和数据挖掘技术中获得什么信息。在这里,因为我的爱好之一是烹饪,我将使用来自 Kaggle 的关于普通食物和产品的食物营养价值的数据集。我想探究这些数据,既是为了学习,也是为了满足自己的好奇心。这意味着,我在这里的目标只是知道我的数据中发生了什么,以及我可以获得什么样的信息,而没有任何特定的目标。让我们开始吧。

探索数据

数据清理

首先,我们需要阅读我们的数据,了解我们的数据如何。这是重要的第一步。

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as snsdata = pd.read_csv('nutrition.csv')
data.head()

data.info()

我们实际上有 76 列,我没有在这里全部显示(这将是一个很长的列表),数据示例如上表所示。

我们的大部分数据是由营养值(卡路里、脂肪、糖、碳水化合物等)组成的。)与美食名。营养值栏有不同的度量单位,如克(克)、毫克(毫克)和微克(微克)。在这种情况下,我们还可以忽略功能 serving_size,因为除了所有数据都基于 100 克食物之外,它不提供任何其他信息。一些列还包含一个 NaN 值,我相信这个 Null 值意味着有等于 0 的值。现在,让我们做一些数据清理。

#Drop the serving_size column
data.drop('serving_size', axis = 1, inplace = True)#Fill the NaN value with 0
data.fillna(0, inplace = True)

在这种情况下,我希望除了 name 特性之外的所有特性都变成数字列。这意味着,我们需要删除数据中所有的非数字文本。我还想转换除卡路里以外的所有数字数据,使其具有相同的度量(克)。让我们开始吧。

#I would use Regular Expression Module to help me clean the data
import re#Looping in each non-numerical features except the name feature 
for col in data.drop('name',axis = 1).select_dtypes(exclude = 'number').columns:
    for i in data[col]:
        if i == '0' or i == 0:
            pass
        else:
            point = re.findall('[a-zA-Z]+',i)[0]
            replace = []
            if point == 'mg':
                for j in data[col]:
                    if j == '0' or j == 0:
                        replace.append(float(j))
                    else:
                        replace.append(float(re.sub('[a-zA-Z]','',j))/1000)
            elif point == 'mcg':
                for j in data[col]:
                    if j == '0' or j == 0:
                        replace.append(float(j))
                    else:
                        replace.append(float(re.sub('[a-zA-Z]','',j))/1000000)  
            else:
                 for j in data[col]:
                    if j == '0' or j == 0:
                        replace.append(float(j))
                    else:       
                        replace.append(float(re.sub('[a-zA-Z]','',j)))

            data[col] = replace    
            data.rename({col:col+'(g)'}, axis =1, inplace = True)
            break

这是我的数据的最终结果,我将进一步探索。请注意,我知道除了卡路里之外,所有数据现在都是以克为单位,但只是为了学习,我将它添加到我的列名中,这样我们就不会忘记它。

我还创建了另一个名为 food_categories 特性,因为当仔细检查这个命名特性时,逗号前面的第一个单词就是 food。

data['food_categories'] = data['name'].apply(lambda x: x.split(',')[0])

数字统计

如果我们试图一个接一个地可视化这些列,这将是巨大的并且有点重复,因为它不会给我们提供太多的信息。如果你愿意,你可以试试。我可以给你下面的代码。

for i in data.select_dtypes('number').columns:
    sns.distplot(data[i])
    plt.title(i)
    plt.show()

有时候,在这种情况下,如果我们真的只是想探索数据,通过数字而不是可视化来看会更直观(毕竟我是一个更注重数字的人,因为我相信有时可视化是有偏见的)。

pd.set_option('display.max_columns', None)
data.agg(['mean', 'median', 'std', 'skew', 'kurtosis'])

例如,在这里,我使用。数据帧的 agg 方法,用于获取关于每列的*均值、中值、标准差、偏斜度和峰度的信息。这就是数字比形象更有说服力的地方。

众所周知,*均值是数据的*均值。多个要素可能具有相同的*均值,但它们在*均值周围的分布方式不同,这通过标准差(std)来表示。有一个规则叫做经验规则,我们可以通过标准差得到数据扩散的概率。经验法则表明:

  • 68%的数据低于*均值 1 *标准差
  • 我们 95%的数据低于*均值 2 *标准差
  • 我们 99.7%的数据都低于*均值 3 *标准差

经验法则或者也有人说 68–95–99.7 法则经常被用来分析数据异常值。这种统计的主要问题是,它们会受到异常值或极值的影响,并经常导致数据失真。我用一张图片向你展示什么是扭曲的数据。

以上是 total_fat(g)特性图。它向右倾斜,因为尾巴在右边。但是,偏斜度有多大呢?这就是不对称统计的目的。我们可以记住关于偏斜度的一些规则是:

  • 如果偏斜度在-0.5 和 0.5 之间,数据是相当对称的
  • 如果偏斜度介于-1 和-0.5 之间或介于 0.5 和 1 之间,则数据是中度偏斜的
  • 如果偏斜度小于-1 或大于 1,则数据是高度偏斜的

所以我们可以看到,如果我们上面的数据是高度倾斜的,实际上你会遇到的大多数数据都是这样的。那么峰度呢?这个统计数字告诉我们什么?峰度是衡量数据相对于正态分布是重尾还是轻尾的指标。这一分析可总结如下:

  • 如果峰度接*于 0,那么通常假设正态分布。这些被称为中 kurtic 分布。
  • 如果峰度小于 0,则该分布是轻尾的,称为宽峰分布。
  • 如果峰度大于 0,那么该分布具有较重的尾部,称为细峰分布。

如果我们把它形象化,它看起来会像下面的图片。

过度峰度取自booglehead.com

准确地说,我们之前的数据被称为过度峰度,其中正态分布以峰度为 0 来衡量。如果我们只讨论峰度,正态分布将等于 3,这就是为什么在过度峰度中,我们将峰度减去 3。

我们的大部分数据都是不准确的。扭曲的数据实际上非常有趣,因为你可以尝试用它来探索。例如,基于卡路里,什么食物被认为是异常值。

由于我们的数据是足够偏斜的,我不会依靠*均值来发现异常值;相反,我会应用基于中位数的 IQR 方法。

IQR 或四分位距是基于数据位置的。例如,如果我们描述“卡路里”特征,我们将得到下面的描述。

data['calories'].describe()

IQR 将基于 25%的位置或 Q1 和 75%的位置或第三季度。我们也可以通过用 Q1 减去 Q3 得到 IQR 值(Q3-Q1)。使用 IQR 方法,我们可以根据上限或下限来决定哪些数据被视为异常值:

下限= Q1–1.5 * IQR

上限= Q3 + 1.5 * IQR

任何高于或低于此限值的数据都将被视为异常值。让我们试着实现这个方法,看看什么样的食物被认为是基于卡路里的异常值。

#Specifying the limit
cal_Q1 = data.describe()['calories']['25%']
cal_Q3 = data.describe()['calories']['75%']
cal_IQR = cal_Q3 - cal_Q1data[(data['calories'] < 1.5 * (cal_Q1 - cal_IQR)) | (data['calories'] > 1.5 * (cal_Q3 + cal_IQR)) ]['food_categories'].value_counts()

事实证明,大部分高热量食物是油,这并不奇怪。

无监督学习

上面我向你展示了一种从数字上探索数据的方法,现在我想向你展示一个机器学习如何帮助我们探索数据的例子。

无监督学习是一种机器学习,我们没有任何特定的学习目标。一个例子是聚类分析,我们向模型提供数据,输出是一个数据聚类,其中最接*的数据被视为一个聚类。

我喜欢做的是,如果我们没有任何探索数据的特定目标,我们可以让机器学习来为我们学习。使用无监督学习,我们可以获得以前没有意识到的新视角。让我们用我最喜欢的聚类分析算法举例说明。

我最喜欢的聚类算法是凝聚聚类分析,你可以在这里详细阅读。基本上,该分析将每一个数据点分配为一个单独的聚类,并通过合并每个聚类来进行,因此我们只剩下一个聚类。

现在,在我们进行分析之前,我们需要准备数据。聚类分析取决于数据之间的距离。数据的距离会受到其比例的影响,这就是为什么我们还需要转换所有的要素,使其具有相同的比例。如果你还记得,我们已经在我们的功能中的每一个单独的列都是以克为单位的,但是有一个“卡路里”列不是在同一个刻度上。这就是为什么我们仍然需要转换数据。通常我们会将数据转换为遵循标准分布,这就是我们要做的。

#Importing the transformer
from sklearn.preprocessing import StandardScaler#Transforming the data, I drop the name feature as we only need the numerical columnscaler = StandardScaler()
training = pd.DataFrame(scaler.fit_transform(data.drop('name', axis =1)), columns = data.drop('name', axis =1).columns)

这就是我们最终得到的,一个每个要素都具有相同比例的数据集。现在,让我们尝试通过聚集聚类来对数据进行聚类。首先,我们想象集群最终会如何。

from scipy.cluster.hierarchy import linkage, dendrogram#Ward is the most common linkage method
Z = linkage(training,method = 'ward')
dendrogram(Z, truncate_mode = 'lastp')
plt.xticks(rotation = 90, fontsize = 10)
plt.ylabel('Distance')
plt.xlabel('Cluster')
plt.title('Agglomerative Clustering')

上面是凝聚聚类生成的树。它只显示最后 30 个合并事件,因为如果我们在这里全部显示,它会被挤满。正如我们所看到的,数据似乎可以分为两类;当然,如果你想更保守一点,它可以分为 3 个集群,因为在上面的可视化中有证据表明它可能是这样的。尽管如此,我现在会把它保持为两个集群。

让我们回到之前的数据,将凝聚聚类结果输入到我们的数据中。

from sklearn.cluster import AgglomerativeClustering#I specify n_clusters to be 2 based on our previous analysis
ach = AgglomerativeClustering(n_clusters = 2)
ach.fit(training)#Input the label result to the data
data['label'] = ach.labels_

现在,通过无监督学习,我们实际上可以尝试将多维数据可视化成两个轴。有几种方法可以做到这一点,但我会向你展示一种叫做 t-SNE 的技术。

from sklearn.manifold import TSNE#t-SNE is based on a stochastic (random) process, that is why I set the random_state so we could repeat the resulttsne = TSNE(random_state=0)
tsne_results = tsne.fit_transform(training) 
tsne_results=pd.DataFrame(tsne_results, columns=['tsne1', 'tsne2'])#Visualize the data
tsne_results['label'] = data['label']
sns.scatterplot(data = tsne_results, x = 'tsne1', y = 'tsne2', hue='label')
plt.show()

现在,我们的多维数据已经被可视化,并且凝聚聚类方法清楚地将我们的数据分成一条清晰的线。好吧,到底是什么让他们分开的?是我们需要分析的。没有简单的方法,除了再次弄脏数字。当然,可视化在这里会有所帮助。我会给出下面每一列的分布代码。

for i in data.select_dtypes('number').columns:
    sns.distplot(data[data['label'] == 0][i], label = 'label 0')
    sns.distplot(data[data['label'] == 1][i], label = 'label 1')
    plt.title(i)
    plt.legend()
    plt.show()

上面是每一列的循环分布图,但是如果你喜欢用像我这样的数字;我们可以使用 DataFrame 对象中的 groupby 方法。

data.groupby('label').agg(['mean', 'median', 'std'])

结果会是上面的样子。我做了一些分析,使他们分开。以下是我的总结:

  • 标签 0 表示蛋白质少、糖和碳水化合物多、纤维多、脂肪和胆固醇少的食物,热量除了 200 卡左右都是分散的。
  • 标签 1 表示蛋白质多、糖和碳水化合物少、纤维少、脂肪和胆固醇多的食物,热量只分摊到 200 卡左右。

我们也可以从上面的标签看到我们有什么样的食物。

#Food label 0
data[data['label'] == 0]['food_categories'].value_counts()

标签为 0 的食品前 5 名是饮料、谷类食品、婴儿食品、汤和小吃,这是一种不含太多蛋白质和脂肪的食品。

#Food label 1
data[data['label'] == 1]['food_categories'].value_counts()

在标签 1 中,排名前 5 的食物都是肉类。这并不奇怪,因为与标签 1 相比,这个标签是针对含有更高脂肪和蛋白质的食物的。

结论

在这里,我只是试着摆弄数据,试着从数据中得到我能得到的模式。除了深入了解我的数据能为我提供什么,我没有任何具体的目标。

我们可以看到,与可视化相比,有时数字可以告诉我们更多的信息,机器学习并不总是用于预测,但也可以用于分析。

如果您喜欢我的内容,并希望获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的简讯。

如果您没有订阅为中等会员,请考虑通过我的介绍订阅。

探索感染新冠肺炎病毒动物的数据

原文:https://towardsdatascience.com/exploring-the-data-of-animals-infected-with-covid-19-50ce1ed16edd?source=collection_archive---------66-----------------------

美国农业部提供的数据分析

克里斯塔·曼古松在 Unsplash 上的照片

数据

随着病例数每天稳步上升,新冠肺炎几乎成了人们所知的每份报纸的头条新闻。尽管受到了大量的关注,但主流媒体几乎没有触及的一个话题(一些例外是农场和家养动物被感染的报道)是动物是如何受到该疾病的影响的。引用加拿大政府提供的信息,“目前关于动物和新冠肺炎的信息有限,尤其是关于动物被感染后是否会传播病毒的信息。”

科学界为了解病毒如何在动物和人类宿主中发展做出了令人钦佩的努力,关于它的研究与日俱增。然而,关于动物感染的公开数据并不容易找到。

为此,世界动物卫生组织经常在本页发布世界各地动物新病例的报告。然而,从这个来源汇编信息是一项艰巨的工作,并不是每个人都愿意/有时间从每个语句中提取数据,并从中制作一个数据集。少数向公众开放的数据来源之一是美国农业部网站。该表列出了经美国农业部国家兽医服务实验室确认的动物中的 SAR-CoV-2(导致人类感染新冠肺炎的病毒)病例。尽管在每种情况下,只有在某个机构或家庭中报告的第一种动物出现在餐桌上,因此,这是对美国有多少动物携带病毒的粗略估计。

尽管每个病例的规模很小(约 30 个数据点),但该表记录了受感染动物的类型、感染的时间和地点、检测病毒的方法以及是否与受感染的人有过接触。该表不可下载,但如果您需要,可以很容易地复制或抓取。为了让事情变得更有趣,我决定废弃它,而不是使用以下代码将其复制到 Excel 文件中:

来源:作者编写的代码从美国农业部的门户网站上删除数据。

诚然,就其预期目的而言,这是一段相当长的代码,但它完成了自己的工作,并生成了一个表,如果您愿意,可以使用 Python 来处理这个表。当然,它的可用性取决于表在添加案例时保持原样(我怀疑这是否会发生,因为随着更多数据的进入,表的大小和复杂性应该会增加)。如果你想更仔细地看看准备过程,欢迎你访问我的 Github 页面和主持整个过程的 NBViewer

分析

来源:作者使用美国农业部截至 8 月 17 日的动物新冠肺炎病例数据制作的图表

到目前为止,数据中的大多数动物(超过 90%)都接触过确诊或可能感染的人类。然而,根据⁴:疾控中心官网公布的信息

“导致新冠肺炎的病毒主要通过咳嗽、打喷嚏和说话时产生的呼吸道飞沫在人与人之间传播。最*的研究表明,被感染但没有症状的人也可能在新冠肺炎的传播中发挥作用。目前,没有证据表明动物在传播导致新冠肺炎的病毒中发挥了重要作用。根据迄今掌握的有限信息,动物将新冠肺炎病毒传播给人类的风险被认为很低”。

此外,疾病预防控制中心在同一份报告中继续补充说:

“我们仍在了解这种病毒,但它似乎可以在某些情况下从人传播到动物,特别是在与新冠肺炎病患者密切接触后”。

因此,数据中的案例极有可能有这个来源,尽管这不是唯一可能的解释,也可能有其他的来源。

从可能的来源转移到感染疾病的动物,受感染的动物种类相对较少,如下图所示:

来源:作者使用美国农业部截至 8 月 17 日的动物新冠肺炎病例数据制作的图表

除了几个例外(特别是在⁵布朗克斯动物园感染了这种疾病的老虎和狮子以及几只水貂),绝大多数记录在案的病例都属于猫和狗。同样,美国的病例分布仅限于少数几个州,迄今为止,50 个州中只有 12 个州报告了病例。

来源:作者使用美国农业部截至 8 月 17 日的动物新冠肺炎病例数据制作的图表

纽约州有 9 例,犹他州有 8 例,是迄今为止报道病例最多的州,其次是德克萨斯州,有 3 例。其他九个州各只有一个传染病。

来源:作者使用美国农业部截至 8 月 17 日的动物新冠肺炎病例数据制作的图表

到目前为止,7 月份是报告感染人数最多的月份,尽管尚未结束,但本月是第二个相对接*的月份,这使得上升趋势可能会继续下去。最后,值得注意的是迄今为止用于疾病诊断的方法,如下图所示:

来源:作者使用美国农业部截至 8 月 17 日的动物新冠肺炎病例数据制作的图表

大多数情况都是使用 PCR-test 来识别的,该测试由⁶FDA 授权,用于测试是否存在活性冠状病毒感染。另一种测试最常见的是检测免疫系统产生的抗体(Ab ),以阻止疾病。

结论

虽然目前还没有什么数据可以说是决定性的,但有几个趋势值得关注:

  • 在长达三个月的时间里,动物感染新冠肺炎的病例一直在稳步上升,到目前为止,8 月份的病例数量表明,这种情况可能会继续下去。
  • 虽然能够感染这种病毒的物种的完整名单仍然未知,但科学界一直在不间断地工作,以了解农场动物是否也能感染这种疾病。到目前为止,根据这个来源,鸭、鸡、猪对病毒有抵抗力。
  • 接受测试的动物中有很大一部分在过去感染过这种病毒,并产生了抗体来对抗它。

这些信息的大部分取决于不久的将来会发生什么,所列出的趋势要么可以逆转,要么被证明是正确的。

[5]: N. Daly,布朗克斯动物园又有七只大型猫科动物冠状病毒检测呈阳性,国家地理,(2020)

探索指环王数据集上 Neo4j 图表数据科学插件的图表目录功能

原文:https://towardsdatascience.com/exploring-the-graph-catalog-feature-of-neo4j-graph-data-science-plugin-on-a-lord-of-the-rings-d2de0d0a023?source=collection_archive---------27-----------------------

了解 Neo4j 图形数据科学插件的基础知识,以及如何将图形投影到内存中

为了继续介绍 Neo4j 图形数据科学插件,我们将回顾基础知识,并查看该库的图形管理部分。这是库的一部分,负责将存储的 Neo4j 图形投影到内存中,从而允许更快地执行图形算法。图表管理部分的一个重要部分是图表目录功能。到底是什么?让我们看看的官方文件

图形算法在图形数据模型上运行,图形数据模型是 Neo4j 属性图形数据模型的投影。图形投影可视为存储图形的视图,仅包含分析相关的、潜在聚合的拓扑和属性信息。图形投影使用针对拓扑和属性查找操作优化的压缩数据结构完全存储在内存中。

图形目录是 GDS 库中的一个概念,允许通过名称管理多个图形投影。使用该名称,创建的图形可以在分析工作流中多次使用。

有两个不同的选项可以将存储的图形投影到内存中:

  • 本机投影通过读取 Neo4j 存储文件提供最佳性能。
  • Cypher projection ,更灵活、更富表现力的方法,较少关注性能

在这篇博文中,我们将深入探讨图表目录的原生投影选项。

图形模型

我已经记不清使用 GoT 数据集的次数了,所以我决定探索互联网,搜索新的令人兴奋的图表。我偶然发现了这个指环王数据集José Calvo 提供,我们将在这篇博文中使用。

数据集描述了人、地点、群体和事物(环)之间的相互作用。在选择如何对此数据集进行建模时,我决定让“主”节点具有两个标签,主标签为“节点”,辅助标签为以下之一:

  • 地方
  • 东西

上图中,出于清晰起见,我只添加了“人”作为二级标签。我们将每本书的交互存储为一个单独的关系,这意味着第一本书的交互将被保存为交互 _1 关系,第二本书的交互将被保存为交互 _2 ,以此类推。请记住,我们将把交互关系视为无向和加权的。这些“主”节点也可以是一个职业的一部分,比如兽人、精灵、人类等等。

输入数据

如前所述,数据集在 GitHub 上可用,我们可以用LOAD CSV语句轻松获取它。

导入节点

LOAD CSV WITH HEADERS FROM 
"https://raw.githubusercontent.com/morethanbooks/projects/master/LotR/ontologies/ontology.csv" as row FIELDTERMINATOR "\t"
WITH row, CASE row.type WHEN 'per' THEN 'Person'
                        WHEN 'gro' THEN 'Group'
                        WHEN 'thin' THEN 'Thing'
                        WHEN 'pla' THEN 'Place' END as label
CALL apoc.create.nodes(['Node',label], [apoc.map.clean(row,['type','subtype'],[null,""])]) YIELD node
WITH node, row.subtype as class
MERGE (c:Class{id:class})
MERGE (node)-[:PART_OF]->(c)

我们向“主”节点添加两个标签的主要原因是为了优化交互关系的导入。现在,你可能会说优化是不必要的,因为我们的数据集很小,我同意,但让我们假设我们可能要处理数百万个节点。我们从定义标签“节点”的唯一约束开始。

CREATE CONSTRAINT ON (n:Node) ASSERT n.id IS UNIQUE

导入关系

既然我们已经设置了 unique 约束,cypher query planner 将使用它来更快地匹配我们现有的节点。

UNWIND ['1','2','3'] as book
LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/morethanbooks/projects/master/LotR/tables/networks-id-volume" + book + ".csv" AS row
MATCH (source:Node{id:coalesce(row.IdSource,row.Source)})
MATCH (target:Node{id:coalesce(row.IdTarget,row.Target)})
CALL apoc.create.relationship(source, "INTERACTS_" + book,
         {weight:toInteger(row.Weight)}, target) YIELD rel
RETURN distinct true

GDS 图表目录

在图形目录中创建命名图形的语法是:

CALL gds.graph.create(graph name, node label, relationship type).

描述我们想要投影的节点

一般来说,对于本机投影变体,有三个选项来描述我们想要投影到内存中的节点:

  • 使用字符串投影单个节点标签:
'Label' ('*' is a wildcard operator that projects all nodes)
  • 使用数组投影多个节点标签:
['Label1', 'Label2', 'Label3']
  • 使用配置图投影多个节点标签及其属性:
{ Label: { label: 'Label', 
           properties: ['property1', 'property2']}, 
  Label2:{ label: 'Label2', 
           properties: ['foo', 'bar']}
}

关于投影节点标签,有一点需要注意:

在内存图中,所有投影的节点标签合并成一个标签。与关系投影不同,当前无法在投影标签上指定过滤器。如果该图用作算法的输入,则将考虑所有节点。

虽然我们可以过滤我们想要投影到内存中图形的节点标签,但是当前不支持在执行图形算法时额外过滤节点。

描述我们想要表达的关系

描述我们想要投影的关系的语法非常类似于节点的语法。

  • 使用字符串投影单个关系类型:
'TYPE' ('*' is a wildcard that projects all relationship-types)
  • 使用数组投影多个关系类型:
['TYPE1','TYPE2']
  • 使用配置图投射更多关系类型及其属性:
{ALIAS_OF_TYPE: {type:'RELATIONSHIP_TYPE', 
                 orientation: 'NATURAL', 
                 aggregation: 'DEFAULT', 
                 properties:['property1','property2']}

配置图中的方向参数定义了我们想要投射的关系的方向。可能的值有:

  • “自然”->每种关系的投影方式与其在 Neo4j 中的存储方式相同
  • 反向'-->在图形投影过程中,每个关系都是反向的
  • “无向”->每个关系都以自然和相反的方向投射

需要注意的重要一点是,GDS 库支持在一个多重图上运行图算法。当我们想要将一个多图转换成一个单图(不是多图)时,聚合参数是很方便的,但是我们将在另一篇博客文章中进一步研究这个问题。

现在我们来看一些实际的例子。

整个图表

让我们首先对节点和关系使用通配符操作符,将整个图形投影到内存中。

CALL gds.graph.create('whole_graph','*', '*')

大多数情况下,我们通过运行(弱)连通分量算法来开始图表分析,以了解我们的图表实际上是如何(不)连通的。

CALL gds.wcc.stream('whole_graph') YIELD nodeId, componentId
RETURN componentId, count(*) as size
ORDER BY size DESC LIMIT 10

结果

该图作为一个整体由一个单独的部分组成。通常,您将从真实世界的数据中获得的是单个超级组件(所有节点的 85%以上)和一些小的不连接组件。

从目录中删除投影图

每次分析后,我们将从内存中释放投影图。

CALL gds.graph.drop('whole_graph');

交互图

下一步,我们想忽略关系中的部分,只关注交互 X** 关系。我们将使用一个数组来描述关系类型,以考虑所有三个interactions _ X关系。**

CALL gds.graph.create('all_interacts','Node',
     ['INTERACTS_1', 'INTERACTS_2', 'INTERACTS_3'])

让我们在新的投影图上运行弱连通分量算法。

CALL gds.wcc.stream('all_interacts') YIELD nodeId, componentId
RETURN componentId, count(*) as size, 
       collect(gds.util.asNode(nodeId).Label) as ids
ORDER BY size DESC LIMIT 10

结果

我们的新图由三部分组成。我们有一个超级组件和两个仅由一个节点组成的小组件。我们可以推断出地点“幽暗密林”和“旧森林”没有相互作用 _X 关系。

让我们使用同样的投影图,只看第一本书中的交互。我们可以使用 relationshipTypes 参数过滤图表算法应该考虑哪些关系类型。

CALL gds.wcc.stream('all_interacts', 
    {relationshipTypes:['INTERACTS_1']})
YIELD nodeId, componentId
RETURN componentId, count(*) as size, 
       collect(gds.util.asNode(nodeId).Label) as ids
ORDER BY size DESC LIMIT 10

结果

如果我们只考虑第一本书中的相互作用,我们会得到更多不相关的部分。这是有意义的,因为一些角色/地点在第一本书中还没有介绍,所以他们没有交互 _1 关系。

从目录中删除投影图

CALL gds.graph.drop('all_interacts');

无向加权交互图

在最后一个例子中,我们将展示如何投影一个无向加权图。我们将只考虑标记为 PersonThing,的节点,对于关系,我们将投影所有的interactions _ X关系及其权重属性,它们将被视为无向图。

CALL gds.graph.create('undirected_weighted',['Person', 'Thing'],
    {INTERACTS_1:{type: 'INTERACTS_1',
                  orientation: 'UNDIRECTED',
                  properties:['weight']},
    INTERACTS_2:{type:'INTERACTS_2',
                 orientation: 'UNDIRECTED',
                 properties:['weight']},
    INTERACTS_3: {type:'INTERACTS_3',
                  orientation:'UNDIRECTED',
                  properties:['weight']}});

未加权 pageRank

为了在我们的投影图上运行未加权的 pageRank,我们不需要指定任何额外的配置。

CALL gds.pageRank.stream('undirected_weighted')
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).Label as name, score
ORDER BY score DESC LIMIT 5

结果

加权网页排名

为了让算法知道它应该考虑关系权重,我们需要使用关系权重属性参数。

CALL gds.pageRank.stream('undirected_weighted', 
   {relationshipWeightProperty:'weight'})
YIELD nodeId, score 
RETURN gds.util.asNode(nodeId).Label as name, score 
ORDER BY score DESC 
LIMIT 5

结果

由于弗罗多与其他角色有更多的互动(定义为重量),他在 pageRank 的加权变量中名列前茅。

第一本书的图形分析:

写完这篇博文,我们来分析一下第一本书的网络。我们首先只对第一本书的交互关系进行加权 pageRank。

CALL gds.pageRank.stream('undirected_weighted', 
    {relationshipWeightProperty:'weight', 
     relationshipTypes:['INTERACTS_1']})
YIELD nodeId, score 
RETURN gds.util.asNode(nodeId).Label as name, score 
ORDER BY score DESC 
LIMIT 5

结果

标准嫌疑人在最上面。佛罗多是目前最重要的角色,其次是甘道夫、阿拉贡和山姆,从排名的中心性来看,他们的重要性差不多。戒指也出现在最重要角色的前五名。

基于 Louvain 算法的社区发现

我们也对网络的社区结构感兴趣。我们将使用 Louvain 模块化算法来确定社区结构。

CALL gds.louvain.stream('undirected_weighted',
   {relationshipWeightProperty:'weight', 
    relationshipTypes:['INTERACTS_1']})
YIELD nodeId, communityId
RETURN communityId,
       collect(gds.util.asNode(nodeId).Label) as members 
ORDER BY length(members) DESC LIMIT 5

结果

放下投影图

CALL gds.graph.drop('undirected_weighted');

使用 Neo4j Bloom 进行可视化

由于一张图胜过千言万语,我们就把第一本书的网络形象化。PageRank 用于确定节点的大小,community 用于确定节点的颜色。

第一次,我将使用 Neo4j Bloom 来可视化网络,因为最新版本(1.2)增加了对可视化的基于规则的样式的支持。

我们可以观察到阿拉贡和索伦、萨鲁曼是一个群体。这与实际的社区检测算法无关,但它显示了从作为共现图的文本中提取信息的弱点。我想下一步是从书中获取知识,比如朋友、敌人或其他人的关系。

结论

我希望读完这篇博客后,你能更好地理解如何用图形数据科学库来投影图形。请继续关注,因为我们仍然需要通过图表管理部分的 Cypher projection 部分。

和往常一样,代码可以在 GitHub 上获得。

探索 R 中的 gt(表格语法)包

原文:https://towardsdatascience.com/exploring-the-gt-grammar-of-tables-package-in-r-7fff9d0b40cd?source=collection_archive---------12-----------------------

轻松创建演示就绪的显示表格

我喜欢米格里特的前向管道%>%操作员。在我看来,它是所有编程中最合适、最有用、最自然、几乎像反射一样的操作符之一。过去,它曾将 tidyverse 推上了数据争论的超级明星之路,现在,它正冒险进入让表格变得极其简单的任务。

gt 包是最新的雄心勃勃的条目,使 R 中的表格更容易访问、修改和复制。它的目标是成为餐桌的焦点(用哈德利的话来说,不是我的),考虑到前者对 R 即的巨大影响,这款套装肩负着巨大的压力。

这是 gt 包架构的示意图—

表格布局的语法。来源— GT 文档,R Studio

我们将使用帕尔默企鹅数据,这是现在臭名昭著的虹膜数据集的替代物。你可以在这里下载数据!

在执行基本的 tidyverse 动词后,我们调用gt()命令并指定所需的行,以便按照所需的形状对数据进行过滤和分组。

添加柱扳手

显然,以上数据是创建的最简单、最原始的数据表。我们现在开始格式化它。我们首先添加列扳手,将公列和母列放入各自的罩中,并定制它们的字体和对齐方式。

创建行汇总统计&格式数据

我们还可以添加一个描述性统计,指定表中每个指标的*均值或总数。这可以实现相对比较,并可以产生丰富的见解。在这里,我计算了每个岛屿的年*均喙长、喙深和鳍状肢,并将数字格式化为不含小数。

添加颜色&脚注

现在有趣的部分是,我使用了通过palatteer包提供的众多调色板中的一个,并根据表格所代表的单元格的数值对表格进行了有条件的着色。gt 包还提供了一个为表格添加脚注的功能。我在这里用它来说明测量喙长、喙深、鳍长和身体质量的标准。

添加表格标题,子标题&更改列标签

虽然颜色给桌子带来了浮力,但标题还是很有必要的。该软件包还支持在标题/副标题中使用降价文本。这里我使用了emo::ji 包在我的标题中添加了可爱的小企鹅表情符号。由于列标签仍然混乱,我还将&格式的列表重命名为一个更短、更易读的标题。

添加背景颜色&格式边框

我知道继续添加自定义颜色到剩余的空白,即标题,副标题,行*均和脚注。我已经指定了所需的十六进制代码,参考这款彩色啤酒,以获得美学建议。我还为年份行添加了虚线边框,并沿岛屿行加厚了边框,以增强区分度和可读性。

调整字体,对齐&添加源注释

作为最后的点睛之笔,为了确保字体的一致性,我在表格上使用了 Oswald 字体,并使每个单元格居中对齐。最后,在脚注下面,我添加了一个 source-note 来说明数据来源。

这就是最后的杰作!😄

希望你喜欢阅读。可以联系我这里 & 这里

探索锁定对移动数据速度的影响

原文:https://towardsdatascience.com/exploring-the-impact-of-lockdown-on-mobile-data-speeds-664beb7ef685?source=collection_archive---------56-----------------------

保罗·史密斯在 Unsplash上的照片

印度新冠肺炎疫情封锁期间不同服务提供商的移动互联网速度的数据可视化。

前言

第五天(还是第六天?我失去了联系新冠肺炎一级防范禁闭在我的城市孟买,突然停电了,我的无线网络也断开了。我正在看《网飞王国》的一集,我真的很想看完最后几分钟。

所以我打开了我的移动数据,希望获得和一分钟前一样的无缝高清质量。相反,我得到的是颗粒状,高度像素化的垃圾,需要 15 分钟来缓冲。

这个。插曲。有过。只有。5.分钟。向左。

这让我想到了一般的移动数据速度,尤其是我的下载速度。我真的不记得上一次我遇到如此糟糕的低速数据是什么时候了。

动机

我很想知道全国移动数据使用的封锁和突然激增是否对*均数据速度产生了负面影响。我的假设是,我的服务提供商,Airtel,比其他公司更难处理高速数据。!为了测试这一点,我进行了这个小项目。

数据源

通过谷歌快速搜索,我找到了 TRAI 电信管理局的网站和他们的 MySpeed 门户网站。MySpeed 是 TRAI 开发的一款应用程序,允许用户监控其服务提供商(又称电信服务提供商或 TSP)的下载和上传速度。

该网站拥有 2018 年 3 月以来的州级和技术级(3G/4G)历史数据,并涵盖了该国所有主要的 tsp。他们也有一份写得很好的关于无线数据速度测量的白皮书,这是一份有趣的读物(只要你不像我一样在午餐后阅读)。

我下载了三年(2018 年至 2020 年)3 月、4 月、5 月和 6 月的数据,因为这几个月是今年全国封锁的关键月份(至今!)。

整个项目可以在我的 GitHub repo 上找到。

PC: memegenerator

数据预处理

数据分布在不同的。csv 文件,我将它们聚合成一个数据帧。有趣的特征是—

  • month_year —数据的月份和年份
  • tsp —服务提供商的名称
  • tech — 3G 或 4G
  • test_type —下载或上传速度测试
  • data_speed —以 Mbps(兆比特每秒)为单位的数据速度
  • lsa —特许服务区,基本上是地区或州或市。

然后,我继续清理每个特征中的虚假值数据,并重新格式化数字特征中的数据类型。如你所见,数据集非常大,占用了将* 550 MB 的内存!

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8985844 entries, 0 to 8985843
Data columns (total 8 columns):
 #   Column           Dtype  
---  ------           -----  
 0   tsp              object 
 1   tech             object 
 2   test_type        object 
 3   data_speed       float64
 4   signal_strength  float64
 5   lsa              object 
 6   year             int64  
 7   month            object 
dtypes: float64(2), int64(1), object(5)
memory usage: 548.5+ MB

需要记住的几件事…

  • 数据集中的每一个数据本质上都是用户通过 MySpeed 应用程序进行速度测试的记录,并被自愿发送到 TRAI 进行质量控制和分析。
  • 速度测试代表短时间上传和下载速度。
  • 这些数据是众包的,反映了在给定的一个月内使用 MySpeed 应用程序测试数据速度的次数。

探索性数据分析

速度测试次数

Q1:一段时间内进行了多少次速度测试?

速度测试的数量在 2018 年比 2020 年最多。月环比显示,除了从 4 月到 6 月的速度测试下降之外,这三年没有明显的趋势。

整个印度和所有 tsp 的速度测试总数(图片来源:作者)

Q2:在哪里进行的速度测试最多?

纵观各邦,很明显,在所有三年中,北方邦在速度测试的数量上领先全国,其次是马哈拉施特拉邦。这种反差在疫情期间尤为突出,尽管人数少于前几年。

描绘 2018 年至 2020 年印度各地速度测试数量变化的 Choropleth 地图

Q3:谁做的速度测试最多?

在封锁期间(3 月-20206 月),超过 50%的速度测试是由Jio(Reliance Jio Infocomm)的用户完成的,而Airtel(Bharati Airtel Limited)远远落后于第二名。这种巨大的差距是由于国内更多的用户造成的。( Jio 无线用户市场份额为 33.47%,其次是Airtel为 28.31% )

封锁期间 tsp 之间的速度测试份额(2020 年)(图片来源:作者)

Q4:做了哪些速度测试?

在封锁的几个月里,在所有的 tsp 中,速度测试在上传和下载速度测试之间几乎*分秋色,但这是意料之中的,因为应用程序会自动执行双速度测试。

两种测试中锁定期间总速度测试的份额(图片来源:作者)

数据速度的变化

问题 5:参赛选手的*均速度有什么不同?

查看三年来的*均数据速度(以 Mbps 为单位),可以发现 Jio 用户一直享受着极高的数据速度,几乎是其他 tsp 的两倍。

数据速度的绝对值表明,与竞争对手相比, JioAirtel 用户在 2020 年的最初几个月面临着速度的大幅下降。这可能是由于它们的用户基数大,因此负载较高。

*均数据速度随时间和 tsp 的变化(图片来源:作者)

Q6:锁定期间数据速度真的下降了吗?

月*均数据速度的同比变化(将某一年的值与其前一年的值进行比较)绘制为条形图。显而易见,在封锁的前四个月,所有主要 tsp 的*均速度都下降了。2019 年 4 月数据速度增幅最大的 Cellone ,2020 年 4 月数据速度降幅最大。

对于大多数 tsp,在 2020 年 4 月观察到最低的数据速度,之后似乎有一些小的缓解。令人惊讶的是, Idea沃达丰是仅有的两家在封锁的后两个月数据速度有所提升的公司。

不同 tsp 的月*均数据速度的同比趋势(图片来源:作者)

问题 7:各服务提供商的数据传输速度有何不同?

对数据速度分布的观察显示, JioAirtel沃达丰在锁定期间提供了超过 10 Gbps 的速度,尽管不一致。大多数 tsp 最常观察到的数据速度约为 2 Gbps,而 Jio 用户一直享受着更高的速度(从其分布的双峰特性来看)。

锁定期间 tsp 之间的数据速度分布(图片来源:作者)

Q8:全国各地的*均数据速度如何变化?

为了回答这个问题,我只查看了前两个 tsp—JioAirtel中央邦的用户在封锁期间享受了最高的*均数据速度,其次是马哈拉施特拉邦。在马哈拉施特拉邦(孟买是其首都),*均下载速度在 6-7 Gbps 之间。

锁定期间 Jio 用户的州*均下载速度(图片来源:作者)

泰米尔纳德邦和安得拉邦的 Airtel 用户享有最高的下载速度,其次是中央邦和哈里亚纳邦。在封锁期间,马哈拉施特拉邦的用户体验到了 7 到 8 Gbps 的速度。

锁定期间 Airtel 用户的州*均下载速度(图片来源:作者)

结论

在这个项目结束时,我明白了—

  • 在印度封锁的最初几个月,所有服务提供商的下载和上传数据速度都大幅下降。
  • Jio 用户远多于全国 Airtel 用户。
  • 尽管存在这种差异,Jio 和 Airtel 在封锁期间提供了相当的*均下载速度。
  • 在封锁的几个月里,中央邦的人们享受着两大服务提供商的高*均下载速度

我想我最初的假设是正确的!

一些有趣的链接

[## 德赖

注意:您可能找不到 TSP/ State 中提到的速度,这是因为您选择的样本不足。TSPs

myspeed.trai.gov.in](https://myspeed.trai.gov.in/) [## 什么是 dBm,它如何影响您的手机信号?

想知道如何获得手机信号强度的最佳测量结果吗?那些我们梦寐以求的信号棒…

www.wilsonamplifiers.com](https://www.wilsonamplifiers.com/blog/what-is-dbm-and-how-does-it-affect-your-cell-signal/)

希望你喜欢这篇文章。

再见!

使用 PageRank 探索印度超级联赛

原文:https://towardsdatascience.com/exploring-the-indian-premier-league-using-pagerank-9569e971ceb7?source=collection_archive---------26-----------------------

奇拉尤·特里韦迪在 Unsplash 上的照片

体育分析

关于 PageRank 算法的简短教程

这项工作的总体目标是探索面向板球分析的网络科学算法。本文涵盖了这个目标的一部分。IPL 数据用于此目的,特别关注 PageRank 算法。介绍了几种建立图形网络的方法,以及提取一些有趣见解的方法。更重要的是,还包括一个关于 PageRank 算法的简短教程。使用 PageRank 对 IPL 中最突出的两支队伍和米进行比较。

印度超级联赛是世界上最受欢迎的体育联赛之一;它的第十三版正在进行中。这是收视率最高的板球联赛。随着疫情给世界上所有体育活动蒙上阴影,特别是在印度,这被吹捧为获得前所未有的收视率。

八支队伍参加了这项一年一度的赛事,每支队伍都要面对对方两次,一次在各自的主场。在 cricsheet.org 可以免费获得 IPL 历史上每场比赛的数据。他们的网站不仅提供了 IPL 的数据,还提供了所有主要的男女板球比赛的数据。

这项工作主要处理图表,并使用它们进行可视化以及分析。让我们先湿湿我们的嘴,获得一些基本的直觉,为板球分析建立一些图表。然后我们就可以进入代码了。

构建图表

图 A. 这是投球手-击球手网络的一幅图,带有太阳升起者海德拉巴和德里夜魔侠之间的比赛的投球手和击球手之间的边缘。Rishabh Pant 是野蛮的,因为他击中了一吨,但他们的团队仍然由于 Dhawan 的攻击而失败。两个玩家都有连接到高重量保龄球手的边缘——适当的颜色。来源:作者图片

探索 IPL 数据的一种有趣方式是通过生成节点和边,其中节点可以是玩家,而边表示游戏中的特定活动。

例如,上图 A 所示的击球手-投球手网络由击球手和投球手组成,作为节点,他们之间的有向加权边代表击球手从投球手得分的回合。权重较高的边用橙色和红色着色。

例如,Rishabh Pant 在 Bhuvaneshwar Kumar 上得了 44 分,由从节点 B KumarRR Pant 的边表示,权重为 44 。特别是这场比赛,在太阳升起者海得拉巴和德里夜魔侠之间,里沙布·潘特打进了一个世纪,然而他的球队输掉了比赛。

下面的图 B 显示了一个大得多但不太有用并且有点压倒性的击球手-投球手网络,它覆盖了 IPL(直到 IPL-12)中的每一个投球。这个情节确实展示了大卫·华纳的爆炸性。

图 B. 该图以投球手和击球手为节点,以投球手到击球手的有向边为边权重,以总失球数为边权重。几乎 IPL 历史上的每一个投球都被计算在内。边缘根据重量着色。更多产的击球手有黄色到红色的彩色边缘。东南部的大卫·华纳就是这样一个脱颖而出的击球手。来源:图片由作者生成

类似地,另一种可以利用这些数据建立的网络是投球手的解雇或 T21。另一个经常被研究的网络是 batsmen 伙伴关系网络,它已经被证明在较长的格式中特别有用。

此外,请注意,在高层次上,这种分析属于网络科学的范畴。

网络科学 是研究电信网络、计算机网络、生物网络、认知和语义网络、社交网络等复杂网络的学术领域,将由节点(或顶点)表示的不同元素或行动者以及元素或行动者之间的连接视为链接(或)。—维基百科

在深入研究网络科学算法,尤其是 PageRank 之前,让我们先接触一些编码。第一个任务是准备数据。

数据准备

第一步是准备数据,这些数据以 YAML 文件的形式提供。每个 YAML 文件对应一个匹配项。并且对于每一场比赛,数据都以一个球的描述的形式给出。所以我们需要准备这些数据来形成节点和边。

以下方法用于准备使用 networkx 生成图形所需的数据。

该方法将输入作为比赛和回合,并返回一个格式为:(投球手、击球手、跑垒者)的元组列表。每个投球的数据汇总在31–37行中。然后在第41–44 行中生成元组。

下面的方法将元组转换为图的边。

第 16–17 行聚集击球手和投球手对元组的运行,以创建边权重,而击球手和投球手形成节点。defaultdict在这里挺合适的。

现在,让我们看看图 A 中的网络及其图形是如何产生的。使用的主库是 networkxmatplotlib 。这相当简单。

图形生成

下面给出了生成图 A 中图形的代码。

第 5 行分配绘图参数,第14–22行根据运行次数给边缘分配颜色(如注释中所述)。线24–28决定图形的布局以及节点和边的位置。第 30–37 行给出了标签。

第 38 行,最后画出图形。

当我写这篇文章的时候,钦奈超级国王队和孟买印度人队的首场比赛已经结束了,作为一名 CSK 球迷,我迫不及待地想为这场比赛创建一个网络,以获得想要的结果。

图 c .2020 年 9 月 19 日,击球手-投球手-运行 CSK 和密歇根州之间的首场比赛网络。Rayudu 为爆破 bum rah 22是养眼!!再次证明印度通过掉 Rayudu 掉了 WC-2019。来源:图片由作者生成

既然我们已经能够使用一个或一组匹配的数据来生成网络并将其可视化,我们就可以考虑分析图表的算法了。

PageRank 是网络科学中流行的算法之一,也是本文研究的重点。下面是一个关于 PageRank 的简短教程。

PageRank 算法教程

著名的谷歌搜索引擎下的同名 PageRank 算法,在它的基本框架上出奇的简单。大多数算法,当它们在实践中工作时,都要经历无数微小的改变才能有效,这些对 PageRank 的修改超出了本文的范围。

说句题外话,去年(即 2019 年)这个时候左右,所有与 PageRank 相关的专利都到期了。

另外,请注意,我使用了参考文献 更深入的 PageRank 作者 Langville 等人。艾尔。对于本教程以及其他一些教程。还参考了伦敦帝国理工学院的线性代数课程。

现在让我们来看看 PageRank 算法。PageRank 的目标是对网站进行排名,并决定它们在搜索结果中的显示顺序。潜在的假设是,一个网站的重要性取决于它与其他网站的链接。

下面是一个互联网的迷你模型,四个网页相互链接,如箭头所示。

互联网的迷你模型。在课程中使用了类似的表述。网页 XYZW 的链接。 YXW 连接。 ZW 相互链接,同时 W 也指向 Y 。来源:图片由作者生成

这 4 个网页中哪一个最相关?

为了确定这一点,每个页面都由基于它们之间的链接的链接向量来表示,通过链接的总数来标准化。例如,对于网页 X,向量将如下:

X 连接到 YWZ ,连接总数为 3 。这导致概率矩阵 P 的生成,通过组合所有网页的向量,如下所示(注意转置)。

互联网上的用户最终到达 X 的概率取决于 Y 。在 Y 上着陆的概率取决于 XW 。诸如此类。这个问题显然是自我参照的。

现在为了计算页面 X 的排名,我们需要 X 所连接的每个网页的排名以及链接概率向量。

这体现在下面的总结中。网页的排名 XX 与其他具有该排名的页面的链接概率的乘积。

这对于整个互联网来说将采取如下形式:

计算上述等式中的 r 的有效方法是使用迭代法。一种是从初始猜测的 r 开始,并将其乘以 P 以获得更新的r。这再次乘以 r ,等等,直到 r 停止变化。

雅可比法 就是这种迭代方法的一个正式例子。

我从维基百科上复制了一个例子来看看 Jacobi 方法的应用。

假设给我们下列线性系统:

如果我们选择(0,0,0,0)作为初始*似值,则第一个*似解由下式给出

使用获得的*似值,重复迭代过程,直到达到期望的精度。以下是五次迭代后的*似解。

该系统的精确解为(1,2,1,1)。

正如您可以推断的那样,同样的方法可以应用于求解上面描述的秩方程。在十次迭代之后,在我们的情况下获得的秩向量是,

雅可比法本质上是矩阵对角化的算法。那么对角化和这个问题有什么关系呢?矩阵的对角化为我们提供了它的特征向量。让我试着更清楚地把这些点联系起来。

矩阵通过旋转、缩放、剪切或正交投影中的一种线性变换矢量(还有更多!).特征向量是那些向量的集合,对应于一个变换矩阵,在变换下它们的方向不变。尽管这些向量的方向保持不变,但它们确实会按照由特征值决定的因子进行缩放。

用数学形式写出这个定义如下。

这里 A 是矩阵 v 是特征向量 λ 是特征值。 I 是与 A 维数相同的单位矩阵。左手边的矩阵 A 对矢量 v 进行变换,矢量v等于右手边的项,由矢量 v 以因子 λ缩放表示。

这个等式类似于我们为确定上面的等级而写的等式。如果特征值等于 1,这将是完全相同的。

换句话说,确定秩实质上是在特征值等于 1 时确定特征向量。

现在,矩阵的对角化无非是求其特征向量。这就是雅可比方法的基本原理。所以 PageRank 从根本上来说是一种计算概率矩阵特征向量的方法。请注意,有许多更有效的方法可以做到这一点。例如更适合互联网规模的幂法。

总之,反过来,本教程简要解释了特征向量的概念,并指出矩阵对角化可以用来确定它们。显示了迭代方法的应用,如 Jacobi 方法,其本质上是矩阵对角化的工具。这就导致了网页的排名确定从根本上来说就是特征向量的计算。

你有希望了解整个情况。现在让我们将 PageRank 应用于 IPL 数据。

板球分析 PageRank

让我们从 PageRank 的一个非常简单的应用开始,确定比赛的玩家。从下面的代码可以看出,使用 networkx 计算 PageRank 算法非常简单。

确定“最佳球员”

考虑图 A 和 c 中所示的两个匹配的示例。对于德里和海德拉巴之间的高得分匹配,PageRank 算法的输出如下:

 ('**S Dhawan**', 0.16706747134453998),
 ('RR Pant', 0.12847147719416976),
 ('KS Williamson', 0.11339938336161924),
 ('HV Patel', 0.054508466219623325),
 ('AD Hales', 0.04907687103359096),
 ('JJ Roy', 0.043984250939231515),
 ('PP Shaw', 0.04121692739936753),
 ('GJ Maxwell', 0.039109987886062),
 ('SS Iyer', 0.036112054051209354),
 ('B Kumar', 0.032705311057058616),
 ('Sandeep Sharma', 0.032705311057058616),
 ('Shakib Al Hasan', 0.032705311057058616),
 ('S Kaul', 0.032705311057058616),
 ('Rashid Khan', 0.032705311057058616),
 ('TA Boult', 0.032705311057058616),
 ('S Nadeem', 0.032705311057058616),
 ('LE Plunkett', 0.032705311057058616),
 ('A Mishra', 0.032705311057058616),
 ('V Shankar', 0.032705311057058616)

达万的确是这场比赛的选手,同时也被的* PageRank 排在首位。紧跟喘气。在最*和米的比赛中,Rayudu 被评为最佳击球手。但这其实微不足道,不足为奇。更有用的是比较整个 IPL 中两个队的击球手。*

让我们来分析一下锦标赛历史上最突出的两支队伍: CSK

来源:维基百科

钦奈超级国王 — vs — 孟买印度人(击球手)

两队在印度超级联赛中已经交锋 29 次,孟买赢得了其中的 17 次,最*的一次交锋属于金奈。

在图 D 中,该网络涵盖了 IPL 历史上迄今为止(2020 年 9 月 21 日)两支球队之间的每一场比赛。这确实是一个密集的情节,不是很清楚。

图 D 。击球手-投球手-运行 IPL 历史上所有 CSK vs MI 比赛的网络,直到 2021 年 9 月 21 日。来源:图片由作者生成

更有趣的是 PageRank 算法的输出。有趣的是,顶级击球手的名单被 CSK 占据了。更有趣的是,排在第一位的是巴德里纳特,他在 2013 年(或大约在那个时候)被 CSK 放弃。

 ('**S Badrinath**', 0.05421395478976649),
 ('**SK Raina**', 0.053135571284977624),
 ('**RG Sharma**', 0.041368536612979664),
 ('**MS Dhoni**', 0.04038317373144958),
 ('**AT Rayudu**', 0.03464112279515003),
 ('**ML Hayden**', 0.0330266349697345),
 ('**SR Tendulkar**', 0.02418058298782965),
 ('**DJ Bravo**', 0.021503060692972184),
 ('**F du Plessis**', 0.021390681834730786),
 ('**KA Pollard**', 0.021321303236989133),
 ('**MEK Hussey**', 0.021042740963540033),
 ('**DR Smith**', 0.01890655407121474),

为了让事情变得更有趣,也为了让剧情看起来更有意义,让我们将分析限制在金奈从禁令中回来后的几年——对其热情的粉丝来说,这是一个令人沮丧的时期。

在下面的图 E 中,显示了最*几个版本的匹配网络。让我们注意一些观察。

  1. Suryakumar YadavRohit Sharma 爱打击 Imran Tahir,看着他们之间突出的红色边缘。
  2. 无论是多尼还是刘冰这几年都相对沉寂。而 Rayudu 做得非常出色,即使是面对像 bum rah 这样的顶级保龄球手。
  3. 沃森惩罚了马林加很多次。而杜普莱西则掠夺了克鲁纳尔潘迪亚。而且 Q de Kock 喜欢打击迪帕克查哈尔

图 E 。CSK 禁令结束后,CSK 的击球手-投球手网络 vs . MI 进行 IPL 比赛。来源:图片由作者生成

应用 PageRank 算法的结果如下。Rayudu *年来在 IPL 中表现出色,是最好的击球手(在两队之间的决斗中),而许多 MI 球员也名列前茅。

 ('**AT Rayudu**', 0.0583995180647374),**CSK**
 ('**SA Yadav**', 0.05791406258909479),**MI**
 ('**RG Sharma**', 0.05623336818791069),**MI**
 ('**SK Raina**', 0.04320529341604707),**CSK**
 ('**HH Pandya**', 0.038683990832774545),**MI**
 ('**KH Pandya**', 0.03657684830688639),**MI**
 ('**SR Watson**', 0.034829476630529085),**CSK**
 ('**F du Plessis**', 0.03473325010829539),**CSK**
 ('**KA Pollard**', 0.03220709886860807),**MI**
 ('**MS Dhoni**', 0.031817576009506396),**CSK**

考虑到 CSK 在过去 5 场比赛中只赢过一次,这个结果很有意义。多尼女士刚刚进入前 10 名。

总的来说,毫无疑问,这两支球队相互之间竞争激烈,作为一名 CSK 球迷,我希望多尼在下一届 IPL 结束时进入前五名,这可能是他的最后一次。

接下来呢?

目前的焦点(为了防止文章变得太大)只集中在击球手身上。有许多网络可以用来进行分析。例如,投球手-击球手-解雇网络或击球手伙伴关系网络,如前所述。

此外,本文中考虑的 PageRank 是最基本的。多年来,它经历了许多变化,这些变化可以应用于这种分析,以获得有趣的见解。

然后,整个工作可以扩展到测试比赛和 ODI,这可以提供许多用于分析和更好地理解的指标,而不是保龄球和击球率等当前数据。去吧。

一旦用类似的网络科学算法获得了更多有趣的见解,我希望能发表一篇后续文章。

🔵在 LinkedinTwitter 找到我🔵

另外,看看我的其他文章。

[## 我的数据科学文章列表

2020 年 9 月 1 日更新

medium.com](https://medium.com/@dyaus/list-of-my-data-science-articles-edd8866029e8)

探索 ConvNet 图像分类器的潜在空间

原文:https://towardsdatascience.com/exploring-the-latent-space-of-your-convnet-classifier-b6eb862e9e55?source=collection_archive---------45-----------------------

隐藏层的潜在空间中的线性!

阿里雷扎Unsplash 上的照片

神经网络,尤其是卷积神经网络的一个迷人之处在于,在网络的最后几层中,各层是完全连接的,每一层都可以被视为一个向量空间。ConvNet 从图像中提取的所有有用的和需要的信息都以特征向量的形式存储在最终层的压缩版本中。当这最后一层被当作一个向量空间并服从向量代数时,它开始产生一些非常有趣和有用的性质。

我在 Kaggle 的imate rialist Challenge(Fashion)数据集上训练了一个 Resnet50 分类器。这里的挑战是将每一幅服装图像分类成合适的属性,如图案、领口、袖长、款式等。我使用了预训练的 Resnet 模型,并在这个数据集上应用了迁移学习,为每个标签添加了层。一旦模型得到训练,我希望看看最后一层的向量空间,并搜索模式。

潜在空间方向

Resnet50 的最后一个 FC 层的长度为 1000。在对时尚数据集进行迁移学习后,我在这一层应用主成分分析,将维度减少到 50,保留了 98%以上的方差。

潜在空间方向的概念在 GANs 和变分自动编码器中很流行,其中输入是矢量,输出是图像,观察到通过在某个方向上*移输入矢量,输出图像的某个属性改变。下面的例子来自 NVIDIA 训练的 StyleGAN,你可以看看这个网站,在这里,每当你刷新页面时,一个假脸就会从一个随机向量中生成。

图片来自界面 GAN Github |姿势、年龄、表情和眼镜等属性可以通过在各自的潜在方向上*移输入向量来调整。

这太令人兴奋了!对输入向量的简单线性运算会在输出图像中产生如此复杂的变换。这些潜在的方向就像旋钮,你可以调整以获得输出图像所需的效果。难以置信!

在我们的图像分类器中,我们做的正好与 GAN 相反。在分类器中,我们获取一个图像,并在 FC 层中获得一个长度为 1000 的向量,通过 PCA 变换,我们将其维数降低到 50。我们想要探索的想法是,我们为其训练模型的图像属性是否在 FC 层和 PCA 之后的层的向量空间中以线性方式排列。答案确实是肯定的!

iMaterialist 挑战赛的任务之一是确定袖子长度,分为五种类型:长袖、短袖、泡泡袖、无袖和露肩。这五种中,三种占多数:长袖、短袖和无袖。现在我们想看看是否存在一个潜在的方向,沿着这个方向,这三个袖长等级被分离。如果是二元分类,我们可以使用逻辑回归,系数向量会给出潜在方向,但在我们的情况下,我们有多个类别。

在多类问题中获得潜在方向的一种方法是建立一个神经网络,其中我们迫使输入层通过单个单元中间层,输入层的权重向量为我们提供潜在方向。下面给出了这个分类器的代码片段,其中我的输入是长度为 50 的 PCA 层,它通过一个单元层,经过几层后,我得到了我的最后 5 个类。迫使它通过单个单元层背后的想法是约束网络学习线性潜在方向。这个单一单位层的值本质上给了我输入到学习的潜在方向上的投影。

**class latent_model(nn.Module):**
  **def __init__(self):**
    super(latent_model, self).__init__()
    self.layer1 = nn.Sequential(nn.Linear(50, 1), nn.Linear(1,10), nn.ReLU(),nn.Linear(10,10), nn.ReLU(), nn.Linear(10,5) , nn.Softmax()) **def forward(self, ip):**
    x = self.layer1(ip)
    return x

lm=latent_model()
*#####Train the Classifier#####
#######################
##The latent direction##*
latent_direction=lm.layer1[0].weight[0].cpu().detach().numpy()

iMaterialist ConvNet 模型的结果

让我们看看训练完这个小分类器后得到了什么!
下图显示了不同袖型沿潜在方向的分布,我们可以看到三大类:短款、长款和无袖款沿潜在方向分离。

作者的图表:袖长沿潜在方向的分布。

神经网络是复杂的非线性模型,但隐藏层中隐藏着线性!

现在,我拍摄一幅裙子的图像,从该图像的 PCA 向量空间中的点开始,沿着袖子长度的潜在方向画一条线,并从训练数据集中检索最接*这条线的图像。下面是一些这样的例子。值得注意的一件有趣的事情是,虽然袖子长度沿着从长袖到短袖再到无袖的方向变化,但裙子的其他特征,如领口、裙子长度和整体风格往往保持不变。

来自 Kaggle 数据集 的图像|示例 1: 从#3 开始,检索在不同点最接*该线的其他图像。

来自 Kaggle 数据集|示例 2: 从#1 开始,检索在不同点最接*该线的其他图像。

来自 Kaggle 数据集 的图像|示例 3: 从#4 开始,检索在不同点最接*直线的其他图像。

在第二个示例中,所有检索到的图像都是长裙,并且在一个图像中有两个姿势,而在第三个示例中,大多数图像都没有模特。唯一显著的变化是袖长。

从上面的结果来看,看起来训练数据集图像已经在 PCA 层的潜在空间中以原始的顺序排列了!

对模式进行类似的分析会得到以下结果

不同模式类型沿已发现模式潜在方向的分布。(作者配图)

从上面的图表中,我们看到花型连衣裙从更坚实的类型沿着潜在的方向分离。看几个例子证实了这一观察。

来自 Kaggle 数据集 的图像|示例 5: 从#6 开始,检索在不同点最接*直线的其他图像。

来自 Kaggle 数据集|示例 5: 从#2 开始,检索在不同点上最接*该线的其他图像。

来自 Kaggle 数据集 的图像|示例 6: 从#4 开始,检索在不同点最接*该线的其他图像。

在上面的例子中,图案沿着发现的方向慢慢地从纯色到条纹到花卉到格子,并且检索到的图像在整体风格方面倾向于类似于初始图像。

结论

着眼于特征向量的潜在空间是我们对神经网络工作的理解向前迈进了一步。从上面的分析中,我们可以得出一个结论:卷积神经网络以图像的形式接收复杂数据,随着输入通过后续层,从这些图像中提取的信息变得越来越有组织。我们发现,在网络最后一层的潜在空间中,我们的训练数据集图像以有序的方式进行排序和分离,以至于我们可以发现感兴趣的某个属性变化的线性方向。
阅读更多博客此处

用神经网络探索新冠肺炎和抑郁症之间的联系

原文:https://towardsdatascience.com/exploring-the-link-between-covid-19-and-depression-using-neural-networks-469030112d3d?source=collection_archive---------30-----------------------

变更数据

对新冠肺炎相关推文进行情感分析,研究抑郁症和疫情之间的相关性。

代表形象。鸣谢:伊斯托克照片

我们生活方式的巨大变化,加上为抗击冠状病毒爆发而引入的限制、隔离和社会距离措施,导致世界各地精神健康问题的惊人增加。社交媒体是人们在特定地点和时间的精神状态的有力指示器。为了研究冠状病毒疫情和普通人群中抑郁和焦虑加速之间的联系,我决定探索与冠状病毒相关的推文。

这个博客是如何组织的?

在这篇博文中,我将首先使用 keras 训练一个神经网络来识别抑郁的推文。为此,我将使用 10,314 条推文的数据集,分为抑郁推文(标记为 1)和非抑郁推文(标记为 0)。这个数据集是由维里戴安娜·罗梅罗·马丁内斯制作的。以下是她的 github 个人资料的链接:【https://github.com/viritaromero

一旦我训练好了网络,我会用它来测试从 twitter 上抓取的推文。为了建立新冠肺炎和抑郁症之间的联系,我将获得两组不同的数据。第一个数据集将由与冠状病毒相关的关键词组成,如“新冠肺炎”、“隔离”、“疫情”和“病毒”。第二个数据集将由使用中性关键字搜索的随机推文组成,如“and”、“I”、“The”等。第二个数据集将作为对照,检查随机样本推文中抑郁推文的百分比。这将使我们能够测量随机样本和新冠肺炎特定推文中抑郁推文百分比的差异。

预处理数据

图片来源:【https://xaltius.tech/why-is-data-cleaning-important/

在我们开始训练神经网络之前,我们需要收集和清理数据。

导入库

为了开始这个项目,我们首先需要导入所有必要的库和模块。

一旦我们准备好了所有的库,我们就需要获取数据并对其进行预处理。你可以从这个链接下载数据集:https://github . com/viritaro Mero/Detecting-Depression-in-Tweets/blob/master/情操 _tweets3.csv

数据的快速检查

我们可以通过将数据集读入 pandas 数据框来快速检查数据集的结构。

现在,我们将把推文的文本存储到一个名为 text 的数组中。tweets 的相应标签将被存储到一个名为 labels 的单独数组中。代码如下:

很抱歉打印出一个相当大的数据集,但我这样做是为了让我们可以快速检查整体结构。我注意到的第一件事是,在标签数组中,0 比 1 多得多。这意味着在数据集中,我们的非抑郁推文大约是抑郁推文的 3.5 倍。在理想情况下,我希望在抑郁和非抑郁推特数量相等的数据集上训练我的神经网络。然而,为了获得同等数量的抑郁和非抑郁推文,我将不得不大幅删减我的数据。我认为较大且不*衡的数据集比非常小且*衡的数据集要好,因此,我将继续使用原始状态的数据集。

清理数据

你会注意到的第二件事是,推文中包含了很多所谓的“停用词”,如“a”、“The”、“and”等。这些词对于将一条推文归类为抑郁或非抑郁并不重要,因此我们将删除这些词。我们还需要删除标点符号,因为这也是不必要的,只会降低我们的神经网络的性能。

我决定使用令人惊叹的 wordCloud 库对清理后的数据进行快速可视化,结果如下。毫不奇怪,抑郁推文中最常见的词是抑郁。

使用 WordCloud 可视化推文

数据的符号化

标记化到底是什么?

基本上,神经网络不像我们人类那样理解原始文本。因此,为了使文本更容易被我们的神经网络接受,我们将它转换成一系列的 1 和 0。

图片来源:inboundhow.com

为了在 keras 中标记文本,我们导入了 tokenizer 类。这个类基本上是在字典中查找整个文本中一定数量的独特单词。然后使用字典查找,keras 允许我们创建向量,用字典查找中的索引值替换单词。

我们还继续填充较短的 tweetss 并截断较大的 tweet,使每个向量的最大长度等于 100。

你可能会想,“嗯,我们只把单词转换成数字,而不是 1 和 0!”你是对的。有两种方法可以做到这一点:要么我们可以将数字转换成一个热编码向量,要么创建一个嵌入矩阵。一位热编码向量通常是非常高维和稀疏的,而矩阵是较低维和密集的。如果你感兴趣,你可以在 Francois Chollet 的《用 Python 进行深度学习》一书中了解更多。在这篇博客中,我将使用矩阵,但是在我们初始化它们之前,我们需要先处理一些其他的事情。

打乱数据

图片由 Sergi Viladesau 在 unsplah 上提供

数据的另一个问题,你可能早就发现了,文本数组首先包含所有非抑郁的推文,然后是所有抑郁的推文。因此,我们需要重组数据,让随机的推文样本进入训练、验证和测试集。

拆分数据

现在我们需要将数据分成训练集、验证集和测试集。

唷!终于完成了所有的数据管理!

制造一个神经网络

图片来源:extremetech.com

现在我们可以开始制作模型架构了。

我将尝试两种不同的模型:一种是预训练单词嵌入层,另一种是可训练单词嵌入层。

为了定义神经网络架构,您需要了解单词嵌入是如何工作的。网上有大量关于单词嵌入的信息。这篇博文是我的最爱之一:

https://towards data science . com/introduction-to-word-embedding-and-word 2 vec-652 d0c 2060 fa

既然您已经对嵌入层的功能有所了解,我将继续用代码创建它。

第一个模型

对于第一个模型,该架构由预训练的单词嵌入层和两个密集层组成。为模型定型的代码如下:

图:模型 1 中训练集和验证集的准确性和损失

这里我们可以看到,该模型在测试集上表现非常好,准确率为 98 %。过度拟合可能不是问题,因为验证精度和损失几乎与训练精度和损失相同。

第二种模式

对于第二个模型,我决定排除预先训练的嵌入层。代码如下。

图:模型 2 中训练集和验证集的准确性和损失

在测试集上,两个模型的精度都一样好。然而,由于第二个模型不太复杂,我将用它来预测一条推文是否抑郁。

从 twitter 获取新冠肺炎相关推文的数据

为了获得我的推文数据集,我使用了 twint,这是一个了不起的 twitter 网络抓取工具。我准备了两组不同的数据集,每组 1000 条推文。第一个由包含 corona 相关关键词的推文组成,如“新冠肺炎”、“隔离”和“疫情”。

现在,为了获得一个对照样本进行比较,我搜索了包含中性关键词的推文,如“the”、“a”、“and”等。利用这个样本中的 1000 条推文,我组成了第二个控制数据集。

COVID 相关推文的 WordCloud

我使用与清理训练集相似的过程来清理数据集。在清理数据后,我将其输入我的神经网络,以预测抑郁推特的百分比。我得到的结果令人惊讶。

下面显示了代码的一次运行,我用不同批次的数据重复了一次运行,这些数据是使用与上述相同的过程获得的,并计算了*均结果。

我的模型预测,*均而言,在使用中性关键词获得的一组推文中,35 %是抑郁推文,65 %是非抑郁推文。在随机获得的样本中,35%的抑郁推文是一个惊人的高数字。然而,带有 COVID 相关关键词的抑郁推文数量甚至更高:55 %抑郁对 45 %非抑郁。抑郁推特增加了 57 %!

这导致了一个结论,即新冠肺炎和推特上的抑郁情绪之间确实存在相关性。

结论

我希望这篇文章能帮助你学习更多关于使用机器学习进行情感分析的知识,我希望你也能尝试类似的项目。

编码快乐!

演职员表:吉菲的斯莱特

使用 Tableau 探索墨尔本房地产市场

原文:https://towardsdatascience.com/exploring-the-melbourne-real-estate-market-using-tableau-914d63659f8e?source=collection_archive---------17-----------------------

Tableau 中的数据可视化介绍

介绍

墨尔本作为世界上最适宜居住的城市之一,吸引了全球各地的许多人。他们中的许多人梦想把这个美丽的地方作为他们的家。我在数据科学领域的旅程始于我搬到墨尔本,因此我决定对该市的房地产市场进行全面分析。我一直对这个行业很着迷。因此,在这篇文章中,我将采取一种全面的方法来识别驱动因素,并帮助潜在买家进行数据驱动的决策。因为这个分析是使用 Tableau 完成的,所以我也将为您提供一些仪表板技巧。

有趣的事实——我在出租房子的时候确实使用了这个分析。因此,如果你刚到墨尔本或者打算在这里买房,这可能会很有用。”

丹尼斯·简斯Unsplash 上拍摄的照片

关于 Tableau

Tableau 是一个功能强大且发展迅速的数据可视化工具,被大多数精通数据的组织所使用。自我智能和将数据转化为令人惊讶的商业洞察力的众多功能使 Tableau 成为最佳的 BI 工具之一。

数据描述

本项目使用的数据集是托尼·皮诺(Tony Pino)在 Kaggle 上发布的 2016 年 1 月至 2018 年 10 月期间墨尔本出售的房屋数据,这些数据来自 Domain.com.au 每周发布的公开结果。一些数据字段包括日期、价格、郊区、地区名称、土地大小、建筑大小、与中央商务区的距离等。(卡格尔)

假设和关键问题

1.随着我们越来越靠* CBD 区域,建筑规模与土地规模的比率会产生什么影响?这个比例会影响房价吗?

2.2018 年第二季度墨尔本不同大都市地区的房屋均价会是多少?

3.墨尔本哪个月卖的房子多?

4.墨尔本房价和最大卖房数排名前 10 的郊区有哪些?

数据处理

为了分析建筑与土地的比例及其与城市距离的关系,在数据中添加了一个虚拟列(比例)。我们的探索围绕着价格、与 CBD 的距离、郊区、区域类型以及建筑与土地的比例。区域列中的空值是使用郊区信息估算的。使用 Excel 中合适的过滤器删除了剩余的空值记录。对显示建筑面积与土地面积之比大于 1 的房产数据进行质量检查。此类记录已从分析中剔除。

探索性分析

为了开始分析,我首先绘制了一张 choropleth 地图,显示了墨尔本不同地区房屋的*均价格。

Choropleth 地图:

地图是一种专题地图,其中地图中的不同区域按照代表地理特征汇总的统计变量的比例进行着色或图案化。(维基百科)

图一。不同地区住房*均价格的变化。快照取自作者开发的 Tableau 仪表板。

上面的可视化显示,位于中央商务区和东部沿海地区的房价比其他地区的房价要高。

我感兴趣的是分析房子的位置对建筑面积与土地面积比率的影响。房子离 CBD 的距离被用作位置的维度。我绘制了一个二元组合图,它由“距 CBD 的距离”和“*均比率”之间的条形图和线图组成。线形图显示了比率的移动*均值,以*滑结果。为了更好的理解,这个距离被形象化为 5 公里的范围。

图二。与城市的距离相对于建筑与土地面积比率的变化。快照取自作者开发的 Tableau 仪表板。

为了清楚地了解比率随位置的变化,我还绘制了墨尔本的 choropleth 地图,显示了不同郊区的*均比率,如下图所示。

图 3。不同地区*均建筑面积与土地面积之比的变化。快照取自作者开发的 Tableau 仪表板。

以上形象化的描述让我们了解到,随着我们越来越靠* CBD 和沿海地区,建筑面积与土地面积的比例也在增加。可以推断,与位于城市和靠*沿海地区的房屋相比,位于远离城市的房屋在前院和后院有更多未被占用的土地空间。造成这种情况的主要原因可以认为是 CBD 地区缺乏空间和房价高。

现在让我们来看看墨尔本房屋销售的月度趋势。我绘制了房屋销售的年度饼状图来观察月度趋势,如下图所示。由于 2018 年的完整数据不可用,我们将可视化 2016 年和 2017 年的结果。

图 4。2011 年和 2017 年的月度销售分布。快照取自作者开发的 Tableau 仪表板。

可以观察到,2016 年的最大销售额在 11 月,而 2017 年的最大销售额在 7 月。在这两年中,据观察,大多数房屋都是在 5 月至 11 月期间出售的。由此可以推断,房子在冬季卖得更多。

为了找出*均价格最高和售出房屋数量最多的前 10 个郊区,我绘制了两个条形图,如下图所示。

图 5。最高均价和最高销售量的十大郊区。快照取自作者开发的 Tableau 仪表板。

上面的图像显示,库永是最昂贵的郊区,水库是最受欢迎的郊区。

使用 Tableau 的预测模型预测未来*均价格:

绘制了一个显示一年中不同月份*均价格的条形图。该图已针对不同区域进行了过滤。我已经用 Tableau 的预测模型预测了 2018 年第二季度的房价。该模型根据季度和月份的价格变化趋势来确定预测价格。

图 6。东部大都市地区的预测。快照取自作者开发的 Tableau 仪表板。

根据上述可视化,东部地区 2018 年 4 月、5 月和 6 月的预测*均价格分别为 122 万美元、123 万美元和 124 万美元。随着我们从 2018 年第一季度跳到第二季度,预测遵循价格下降的趋势。此外,模型*均出 2016 年和 2017 年从 4 月到 5 月和 5 月到 6 月的变化,并提供 5 月和 6 月的价格向上增长。

图 7。西部和北部大都市地区的预测。快照取自作者开发的 Tableau 仪表板。

在西部大都市和北部大都市地区,随着我们从 2017 年第 1 季度进入第 2 季度,该模型再次遵循价格下降的趋势。从四月到五月和五月到六月的价格变化被*均化,并且预测第二季度的所有三个月对于两个区域具有相似的趋势。

图 8。南部大都市地区的预测。快照取自作者开发的 Tableau 仪表板。

对于南部大都市地区,2016 年和 2017 年第一季度的数据都缺失。因此,系统无法跟踪季度变化趋势,并预测 2018 年 4 月的*均价格与 2018 年 3 月相同。此外,根据上一年 4 月至 5 月和 5 月至 6 月的*均变化,2018 年 5 月和 6 月有所上升。

图 9。南部大都市地区的预测。快照取自作者开发的 Tableau 仪表板。

在东南大都市地区,2016 年和 2017 年第一季度的数据都缺失。此外,2016 年第二季度的数据也缺失。因此,该模型无法提供准确的预测,并显示 2018 年第二季度所有三个月的固定值为 92 万美元。

结论

这种数据探索和可视化帮助我们为有抱负的买家收集了一些关于墨尔本房地产市场的有用见解。

据观察,随着我们越来越靠*城市地区,建筑面积与土地面积的比率变化很大。城市的高价格和更少的空间鼓励人们利用全部土地来建造房屋。

除了南部大都市地区,预测模型显示,随着我们从 2018 年第一季度到第二季度,房价将会下降。此外,冬季被认为是买家购买房屋的最佳季节。

参考

  1. t .皮诺(2018 年)。墨尔本住房市场。从https://www.kaggle.com/anthonypino/data取回
  2. Choropleth 地图。从 https://en.wikipedia.org/wiki/Choropleth_map取回

包装

感谢阅读👍。希望你觉得这篇文章很有见地。如果是,请在您最喜欢的社交媒体*台上分享。我希望提出一些更高级的数据可视化。

我目前正在墨尔本莫纳什大学攻读数据科学硕士学位。要提供任何反馈或建议,请发电子邮件至 rishabharora268@gmail.com。你也可以在 Linkedin脸书上联系我。

继续摆桌子!

使用 Python 查找要阅读的新书

原文:https://towardsdatascience.com/exploring-the-most-recommended-books-using-python-e5bf7291fe59?source=collection_archive---------28-----------------------

搜罗探索最值得推荐的书籍

保罗·斯查费在 Unsplash 上的照片

有成千上万的书,但并不是所有的都值得一读。引用华氏 451 度中老费伯的话,最好的书是那些“展示生活面孔上的毛孔”的书

那么,面对铺天盖地的书籍,你如何找到最好的呢?

一种方法是去专门的图书网站(比如亚马逊或者 Goodreads)。它们提供过滤工具来优化搜索结果,并显示用户的评论和*均评级,以帮助缩小选择范围。

或者,你可以向他们的朋友或熟人寻求推荐。

这两种方法无疑是有效的。

但是还有第三种方法可以获得很好的结果:看看那些知名人士的推荐,他们说他们读过的书对他们的成就起了很大的作用。

这就是这个神奇的网站Mostrecommendedbooks.com发挥作用的地方。

MostRecommendedBooks.com

这个网站几乎展示了“世界级人物”推荐的所有书籍。与同行相比,它真的是遥遥领先。

所以,我决定检索它所有的书名 ,心中有两个目的:

  1. 把所有这些书放在一个数据框架里,给我的书友们
  2. 使用 Python 可视化库深入了解这一宝贵财富。

我还使用了 Google Books API 来获取页数、出版日期和类别。我选择 Google Books API 是因为:

  • 它提供了大量图书的各种信息。
  • 文档简明易懂。
  • 有多个查询参数(标题、作者、ISBN 等。).
  • 公共数据,比如我们想要访问的数据,不需要授权。您只需要提供 API 密钥

(我的Github上有抓取数据和构建数据集的代码)。数据集也可以在 中找到【卡格尔】)

在开始之前,让我们导入将要使用的 Python 库。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sb
import textwrap%matplotlib inline

加载数据集

books_df = pd.read_csv('books_clean.csv')
books_df.head(10)

这是我们的数据集的样子。让我们看看这里有多少本书:

books_df.shape

(3003, 8)

如你所见,我们有 3003 个书名。

我们还有其他功能,如推荐数量、类别、出版日期和页数。

对于任何可能感兴趣的人,我还确保包括 Google books IDs,以方便相同书籍的数据抓取。

探索数据集

让我们从绘制推荐/书籍数量的分布图开始:

***#Histogram:***
plt.figure(figsize=[10,5])
plt.hist(data=books_df, x='num_recommendations')
plt.title('Distribution of the number of recommendations per book', size=18, fontweight='bold')
plt.xlabel('Recommendations', size=15)
plt.ylabel('Frequency', size=15)

这种分布是右偏的,许多书的推荐数量少于 2 本。

那么,这份榜单内最值得推荐的书有哪些呢?

要回答这个问题,我们不能按降序排列所有 3003 本书,因为这将产生一个不美观的图表,不能简明地传达信息。

因此,我将(任意地)将“num_recommendations”唯一值的中值作为最受推荐书籍的最小阈值:

***#Fixing the threshold:***
threshold=np.median(books_df['num_recommendations'].value_counts().index)***#Subset of the dataset based on the threshold:***
data=books_df.loc[books_df.num_recommendations >= threshold] ***#Combining titles and authors:*** 
data['title_y']=[','.join(i) for i in list(zip(data['title'],data['author']))]***#Barplot:*** 
plt.figure(figsize = [5,10])
color_base = sb.color_palette()[0]sb.barplot(data = data.sort_values(by = 'num_recommendations', ascending = False), x = 'recommender_count', y = 'title_y', color = color_base)plt.title('The Most Recommended Books', size = 18)
plt.xlabel('Recommendations', fontweight = 'bold', size = 15)
plt.ylabel('Titles', size = 15);

在这里,我们有 22 本书在我们的数据框架的绝对顶点。

正如你所看到的,《人类对意义的探索》( Victor Frankl)在 20 多条建议中名列榜首,其次是《智人》(尤瓦尔·赫拉利),然后是雷伊·达里奥的《原则》( T31)。

然而,似乎这个情节包含许多商业和自助书籍。我们几乎看不到一本小说,更别说哲学或其他特定类别的书了。

深入挖掘数据框架中的类别肯定会完善我们的发现,并带来有意义的信息,帮助我们选择最好的书籍。

但是首先,我们需要知道在我们的数据集中最常出现的类别。

为了简单起见,我将只列出前 20 名:

***#Plotting the 20 most frequently occurring categories:***plt.figure(figsize = [10,5])
color_base = sb.color_palette()[0]sb.barplot(books_df.category.value_counts().head(20).index, books_df.category.value_counts().head(20).values, color=color_base)plt.xticks(rotation = 'vertical')
plt.title('The Most Frequently Occurring Categories', fontweight = 'bold', size = 18)
plt.xlabel('Categories', size = 15)
plt.ylabel('Count', size = 15)

不出所料,小说商业书籍最受欢迎,各有超过 400 本。传记书籍排在第三位,接下来是历史科学

在一个给定的类别中有很多书并不意味着这个类别是最值得推荐的,也不意味着这个类别中的书是所有书中最值得推荐的。品味是无法解释的。有些人喜欢小说,而有些人对经济学更感兴趣。

出于这个原因,查看建议在每个类别中的分布是合理的。

这将让我们了解异常值,并帮助我们发现每个类别中最值得推荐的书籍:

cat = books_df.category.value_counts().head(20).indexfig, ax = plt.subplots(figsize = [10,5])sb.swarmplot(data = books_df[books_df.category.isin(cat)], x = 'category', y = 'num_recommendations', palette = 'tab20')ax.set_xticklabels(ax.get_xticklabels(), rotation = 90)
ax.set_title('Distribution of Recommendations by Category', fontweight = 'bold', size = 18)
ax.set_xlabel('Categories',  size = 15)
ax.set_ylabel('Recommendations',  fontsize = 15)

我们看到大多数类别都有 1-5 本推荐范围内的书籍。

同时,一些类别有超过 5 人推荐的书籍,而另一些类别有超过 10 人推荐的书籍。传记、商业和经济、小说、心理学和自助都有许多书籍,有许多推荐。

现在,让我们找出每一类中的必读书籍。

我将只考虑 9 个类别,并根据推荐数量绘制前 5 个类别。但是请注意,使用以下代码可以添加更多类别或扩大图书列表:

***#Defining the categories:***
categories = books_df.category.value_counts().head(9).index.tolist()***#Defining a function to select a subset of data:*
def** selection(cat):
    data = books_df[books_df['category'] == cat].sort_values(by =  'num_recommendations', ascending = False).head()
    **return** datafig, ax = plt.subplots(nrows = 3, ncols = 3,figsize = [20,15])
plt.suptitle('Top 5 Recommended Books in each Category', size = 30, y = 1.05, fontweight = 'bold')
fig.tight_layout(h_pad = 8)
fig.text(-0.02, 0.5, 'Recommendations', va = 'center', rotation='vertical', fontweight='bold', fontsize=25)
fig.text(0.5, -0.06, 'Titles', va = 'center', ha = 'center', fontweight = 'bold', fontsize=25)
ax = ax.flatten()
color_base = sb.color_palette()[0]y = sorted(books_df['num_recommendations'].unique())
i=0
**for** cat **in** categories:
    sb.barplot(data = selection(cat), x='title', y = 'num_recommendations', ax = ax[i], color = color_base)
    ax[i].set_title(cat, fontweight = 'bold', fontsize = 18, color = 'crimson')
    ax[i].set_ylabel('')
    ax[i].set_xlabel('')
    ax[i].set_xticklabels((textwrap.fill(x.get_text(), width=11) **for** x **in** ax[i].get_xticklabels()), fontsize = 14)
    ax[i].set_yticks(np.arange(0, max(y)+1, 5))
    ax[i].set_yticklabels(labels = ax[i].get_yticks(), fontsize =14)
    i += 1

现在我们有各种各样的书,我们可以根据自己喜欢的类型从中选择。

当然,如前所述,有可能情节超过五本书。这只是一个说明,展示它是如何呈现的。

最后,我们可以更进一步,从另一个角度来看我们的数据集。

一个作者可以有多本书,如果一些书获得了很多喜欢,一些作者可能同样比其他人拥有更多的粉丝。

换句话说,我们来看看“谁是 最值得推荐的作者”:

***#Grouping by 'recommender' and 'author' to get the unique values of #authors per each recommender:*** 
data = recommended_books.groupby(['recommender', 'author']).count().reset_index(level=1)***#Plotting the 20 most recommended authors:*** 
plt.figure(figsize=[10,5])
color_base = sb.color_palette()[0]sb.barplot(data['author'].value_counts().head(20).index, data['author'].value_counts().head(20).values, color=color_base)plt.xticks(rotation = 'vertical')
plt.title('The Most Recommended Authors', fontweight = 'bold', size = 18)
plt.xlabel('Authors', size = 15)
plt.ylabel('Count', size = 15)

这是一个很棒的条形图,有很多名字出现在第一个图的中。

不过顺序不太一样,有些名字是新的。

换句话说,即使一些书被高度推荐,我们也不要忽视作者,因为他们同样重要。

最终想法:

说名人的推荐是“有史以来最好的”,不是我的目的。当然还有许多其他令人惊讶的书没有被注意到(或者没有被翻译成英文)。

简单的建议创造推动我们选择的社会证据。一本书的评论或推荐数量越多,想要阅读它的人就越多。当这些评论或建议来自我们当中最成功的人时,社会证明往往会增加。推荐就像一个指南针,在我们迷失的时候给我们指明正确的方向。

我要感谢mostrecommendedbooks.com的联合创始人理查德·赖斯阿努拉格·拉姆达桑,他们允许我使用他们的网站作为主要的信息来源。

通过 Google books API 访问公共数据甚至可以在没有 API 键的情况下完成。我试过带钥匙和不带钥匙,两种情况下都有效。

探索下一个单词预测器!

原文:https://towardsdatascience.com/exploring-the-next-word-predictor-5e22aeb85d8f?source=collection_archive---------5-----------------------

深度学习|自然语言处理

构建下一个单词预测器的不同方法

自由股票Unsplash 上的照片

语言预测导论

你手机上的键盘怎么知道你下一步想输入什么?语言预测是一个自然语言处理 NLP 应用程序,涉及预测前面文本中给出的文本。自动完成或建议的回答是语言预测的流行类型。语言预测的第一步是选择语言模型。本文展示了在 Whatsapp 或任何其他消息应用程序中构建下一个单词预测器可以采用的不同方法。

通常有两种模型可以用来开发下一个单词的建议者/预测者:1) N-grams 模型或 2)长短期记忆(LSTM)。我们将仔细检查每种型号,并得出哪个型号更好的结论。

n 元语法方法

如果你沿着 n-grams 这条路走下去,你需要关注“马尔可夫链”来根据训练语料库预测每个后续单词或字符的可能性。下面是这种方法的代码片段。在这种方法中,一的序列长度被用来预测下一个字。这意味着我们将预测前一个单词中给出的下一个单词。

导入必要的模块:word _ tokenizedefault dict 计数器

import re
from nltk.tokenize import word_tokenize
from collections import defaultdict, Counter

创建包含方法的类 MarkovChain :

class MarkovChain:
  def __init__(self):
    self.lookup_dict = defaultdict(list)def _preprocess(self, string):
    cleaned = re.sub(r’\W+’, ' ', string).lower()
    tokenized = word_tokenize(cleaned)
    return tokenizeddef add_document(self, string):
    preprocessed_list = self._preprocess(string)
    pairs = self.__generate_tuple_keys(preprocessed_list)
    for pair in pairs:
      self.lookup_dict[pair[0]].append(pair[1])def __generate_tuple_keys(self, data):
    if len(data) < 1:
      return
    for i in range(len(data) - 1):
      yield [ data[i], data[i + 1] ]

  def generate_text(self, string):
    if len(self.lookup_dict) > 0:
      print("Next word suggestions:", Counter(self.lookup_dict[string]).most_common()[:3])
    return

当我们创建上述类的一个实例时,一个默认的字典被初始化。有一种方法可以对我们通过添加的训练语料进行预处理。add_document() 方法。当我们在的帮助下添加文档时。add_document() 方法,为每个唯一的单词创建对。让我们用一个例子来理解这一点:如果我们的训练语料库是“你好吗?从我们上次见面到现在有多少天了?你父母好吗?”在预处理和添加文档之后,我们的查找字典应该是:

{ 'how': ['are', 'many', 'are'], 'are': ['you', 'your'],
  'you': ['how'], 'many': ['days'], 'days': ['since'],
  'since': ['we'], 'we': ['last'], 'last': ['met'], 'met': ['how'],
  'your': ['parents']}

每一个唯一的单词作为一个键和它后面的单词列表作为一个值被添加到我们的查找字典 lookup_dict 中。

当我们输入一个单词时,它会在字典中查找,并在下面的单词列表中给出最常用的单词。这里,单词建议的最大数量是三个,就像我们在键盘上一样。下面是序列长度为 1 的这种方法的运行示例。输出包含建议的单词及其在列表中各自的出现频率。当我们输入单词“how”时,会在字典中查找它,并从下面的单词列表中选择最常用的三个单词。这里,“许多”单词出现了 1531 次,这意味着单词序列“多少”在训练语料库中出现了 1531 次。

n 元模型的输出(序列长度为 1)

在 n 元语法方法中:

此外,在上述方法中,我们可以具有 2 或 3 或更长的序列长度。为此,我们将不得不改变上面的一些代码。

class MarkovChain:
  """ 
  Previous code continued
  """
  def add_document(self, string):
    preprocessed_list = self._preprocess(string)
    pairs = self.__generate_tuple_keys(preprocessed_list)
    for pair in pairs:
      self.lookup_dict[pair[0]].append(pair[1])
    pairs2 = self.__generate_2tuple_keys(preprocessed_list)
    for pair in pairs2:
      self.lookup_dict[tuple([pair[0], pair[1]])].append(pair[2])
    pairs3 = self.__generate_3tuple_keys(preprocessed_list)
    for pair in pairs3:
      self.lookup_dict[tuple([pair[0], pair[1], pair[2]])].append(pair[3])

   def __generate_tuple_keys(self, data):
    if len(data) < 1:
      return 
    for i in range(len(data) - 1):
      yield [ data[i], data[i + 1] ]

  #to add two words tuple as key and the next word as value
  def __generate_2tuple_keys(self, data):
    if len(data) < 2:
      return
    for i in range(len(data) - 2):
      yield [ data[i], data[i + 1], data[i+2] ]

  #to add three words tuple as key and the next word as value 
  def __generate_3tuple_keys(self, data):
    if len(data) < 3:
      return
    for i in range(len(data) - 3):
      yield [ data[i], data[i + 1], data[i+2], data[i+3] ]

  def oneword(self, string):
    return Counter(self.lookup_dict[string]).most_common()[:3]def twowords(self, string):
        suggest = Counter(self.lookup_dict[tuple(string)]).most_common()[:3]
        if len(suggest)==0:
            return self.oneword(string[-1])
        return suggestdef threewords(self, string):
        suggest = Counter(self.lookup_dict[tuple(string)]).most_common()[:3]
        if len(suggest)==0:
            return self.twowords(string[-2:])
        return suggest

  def morewords(self, string):
        return self.threewords(string[-3:])def generate_text(self, string):
    if len(self.lookup_dict) > 0:
        tokens = string.split(" ")
        if len(tokens)==1:
            print("Next word suggestions:", self.oneword(string))
        elif len(tokens)==2:
            print("Next word suggestions:", self.twowords(string.split(" ")))
        elif len(tokens)==3:
            print("Next word suggestions:", self.threewords(string.split(" ")))
        elif len(tokens)>3:
            print("Next word suggestions:", self.morewords(string.split(" ")))
    return

我们来破解密码。方法。__generate_2tuple_keys()。__generate_3tuple_keys() 用于分别存储长度为 2 和 3 的序列及其后续单词列表。现在,我们的代码有能力根据之前的三个单词来预测单词。让我们看看我们新的查找字典 lookup_dict 的例子:“你好吗?从我们上次见面到现在有多少天了?你父母好吗?”

{ 
  """
  Same as before
  """
  ('how', 'are'): ['you', 'your'],
  ...
  ('how', 'many'): ['days'],
  ('many', 'days'): ['since'],
  ...
  ('how', 'are', 'you'): ['how'],
  ...
  ('how', 'many', 'days'): ['since'],
  ...
}

与前一对相比,新对被添加到字典中。我们上面创建的类 MarkovChain 处理我们输入的任意长度的序列。如果我们输入一个单词,那么方法' oneword' '将被调用,这将与前一个相同。对于长度为 2 或 3 的输入,将分别调用方法'两个字和'三个字'。这些方法的作用是在给定输入单词的情况下,从查找字典中查找最常见的三个单词。当输入单词多于四个时,将处理最后三个。当遇到未知单词时,该单词将被忽略,字符串的其余部分将被处理。看看下面的图来澄清任何疑问。这个数字是基于不同的训练语料库。左侧显示输入,右侧显示输出。

我们的 n-grams 模型的各种输入情况

下面是这种方法的运行输出:

n 元模型的输出(序列长度超过 1)

上面的输出是基于用于这种方法的一个不同的更大的数据集。GitHub 对于这种方式的链接是 this 。你可以在那里找到上面的代码。

局限性:

马尔可夫链没有记忆。采用这种方法有许多限制。举个例子,“我吃了这么多烤……”下一个单词“三明治”将基于“烤三明治”在训练数据中一起出现的次数来预测。因为我们得到的建议只是基于频率,所以在很多情况下这种方法可能会失败。

长短期记忆(LSTM)方法:

使用神经语言模型的更高级的方法是使用长短期记忆(LSTM)。LSTM 模型使用深度学习和管理记忆的人工“细胞”网络,使它们比传统的神经网络和其他模型更适合文本预测。

“草总是…”

下一个词是简单的“绿色”,可以被大多数模型和网络预测。

但是对于句子“现在是冬天,阳光很少,草总是……”,我们需要知道句子更后面的上下文来预测下一个单词“棕色”。

当上下文和要预测的单词之间的差距增大时,标准 RNNs 和其他语言模型变得不太准确。这就是 LSTM 被用来解决长期依赖问题的时候,因为它有记忆细胞来记住以前的上下文。你可以在这里了解更多关于 LSTM 网络的信息。

让我们开始编码并定义我们的 LSTM 模型。在构建我们的模型时,首先,使用一个嵌入层,两个各有 50 个单位的堆叠 LSTM 层。

Keras 提供了一个嵌入层,可用于文本数据上的神经网络。嵌入层用随机权重初始化,并学习训练数据集中所有单词的嵌入。它需要整数编码形式的输入数据。这个数据准备步骤可以在同样由 Keras 提供的 Tokenizer API 的帮助下执行。点击了解更多关于嵌入层的信息。

两个 LSTM 层之后是两个完全连接的或密集的层。第一层有 50 个单元,第二个密集层是我们的输出(softmax)层,其单元数量等于词汇表大小。对于每个输入,模型将根据概率从我们的词汇中预测下一个单词。分类交叉熵被用作损失函数。

数据预处理:

对于嵌入层的输入,我们首先必须使用来自 keras.processing.text 的 Tokenizer 来编码我们的输入字符串。我们在预处理中所做的很简单:我们首先创建特征字典的序列。然后我们在记号赋予器的帮助下把它编码成整数形式。

from keras.preprocessing.text import Tokenizer
import nltk
from nltk.tokenize import word_tokenize
import numpy as np
import re
from keras.utils import to_categorical
from doc3 import training_doc3cleaned = re.sub(r'\W+', ' ', training_doc3).lower()
tokens = word_tokenize(cleaned)
train_len = 4
text_sequences = []for i in range(train_len,len(tokens)):
  seq = tokens[i-train_len:i]
  text_sequences.append(seq)sequences = {}
count = 1for i in range(len(tokens)):
  if tokens[i] not in sequences:
    sequences[tokens[i]] = count
    count += 1tokenizer = Tokenizer()
tokenizer.fit_on_texts(text_sequences)
sequences = tokenizer.texts_to_sequences(text_sequences)#vocabulary size increased by 1 for the cause of padding
vocabulary_size = len(tokenizer.word_counts)+1
n_sequences = np.empty([len(sequences),train_len], dtype='int32')for i in range(len(sequences)):
  n_sequences[i] = sequences[i]train_inputs = n_sequences[:,:-1]
train_targets = n_sequences[:,-1]
train_targets = to_categorical(train_targets, num_classes=vocabulary_size)
seq_len = train_inputs.shape[1]

让我们用一个例子来理解上面的代码中发生了什么:“你好吗?从我们上次见面到现在有多少天了?你父母好吗?”。我们首先清理我们的语料库,并借助 nltk 库中的正则表达式、word_tokenize 对其进行标记。【序列】字典是做什么的?下面是使用记号赋予器之前的‘sequences’字典。

{'how': 1, 'are': 2, 'you': 3, 'many': 4, 'days': 5, 'since': 6, 'we': 7, 'last': 8, 'met': 9, 'your': 10, 'parents': 11}

我们的‘text _ sequences’列表保存了我们训练语料库中的所有序列,它将是:

[['how', 'are', 'you', 'how'], ['are', 'you', 'how', 'many'], ['you', 'how', 'many', 'days'], ['how', 'many', 'days', 'since'], ['many', 'days', 'since', 'we'], ['days', 'since', 'we', 'last'], ['since', 'we', 'last', 'met'], ['we', 'last', 'met', 'how'], ['last', 'met', 'how', 'are'], ['met', 'how', 'are', 'your']]

使用 tokenizer 后,我们得到了编码形式的上述序列。这些数字只不过是重新分配前'序列'字典中相应单词的索引。

[[1, 2, 9, 1], [2, 9, 1, 3], [9, 1, 3, 4], [1, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8], [6, 7, 8, 1], [7, 8, 1, 2], [8, 1, 2, 10]]

一旦我们有了编码形式的序列,通过将序列分成输入和输出标签来定义训练数据和目标数据。对于此示例,我们将基于前三个单词预测下一个单词,因此在训练中,我们使用前三个单词作为输入,最后一个单词作为将由模型预测的标签。我们的'T12 培训 _ 输入'T13 现在应该是:

[[1 2 9]  [2 9 1]  [9 1 3]  [1 3 4]  [3 4 5]  [4 5 6]  [5 6 7]  [6 7 8]  [7 8 1]  [8 1 2]]

然后,我们将输出标签转换成一个热点向量,即 0 和 1 的组合。' train_targets' 中的单热点向量看起来像:

[[0\. 1\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0.] 
 ...
 [0\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 1.]]

对于第一个目标标签“how ”,序列字典中的索引是“1 ”,因此在编码形式中,您会在' train_targets' 的第一个独热向量中的索引 1 处看到“1”。

注意:以上代码是针对文本“你好吗?从我们上次见面到现在有多少天了?你父母好吗?”为了更简单的解释。但实际上,使用了更大的数据集。

构建模型:

现在我们训练我们的序列模型,它有 5 层:一个嵌入层、两个 LSTM 层和两个密集层。在我们的模型的输入层,即嵌入层中,输入长度被设置为序列的大小,在这个例子中是 3。(注意:我们将训练输入和训练目标的数据分割为 3 比 1,因此当我们为预测模型提供输入时,我们必须提供 3 个长度向量。)

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Embedding
model = Sequential()
model.add(Embedding(vocabulary_size, seq_len, input_length=seq_len))
model.add(LSTM(50,return_sequences=True))
model.add(LSTM(50))
model.add(Dense(50,activation='relu'))
model.add(Dense(vocabulary_size, activation='softmax'))# compiling the network
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(train_inputs,train_targets,epochs=500,verbose=1)

预测单词:

在我们的模型被训练后,我们可以以编码的形式给出输入,并从 softmax 函数中得到三个最可能的单词,如下所示。

from keras.preprocessing.sequence import pad_sequencesinput_text = input().strip().lower()
encoded_text = tokenizer.texts_to_sequences([input_text])[0]
pad_encoded = pad_sequences([encoded_text], maxlen=seq_len, truncating='pre')
print(encoded_text, pad_encoded)for i in (model.predict(pad_encoded)[0]).argsort()[-3:][::-1]:
  pred_word = tokenizer.index_word[i]
  print("Next word suggestion:",pred_word)

在上面的代码中,我们使用填充,因为我们在长度为 3 的序列上训练我们的模型,所以当我们输入 5 个单词时,填充将确保最后三个单词作为我们模型的输入。当我们输入少于 3 个单词时会发生什么?我们不会得到最好的结果!当我们输入一个未知的单词时,也会发生同样的情况,因为在这个单词的索引中,一键向量将包含 0。我们将来可以做的是,将长度为 2(输入)的序列添加到 1(目标标签)中,将长度为 1(输入)的序列添加到 1(目标标签)中,就像我们在这里将长度为 3(输入)的序列添加到 1(目标标签)中一样,以获得最佳结果。

下面是我们的模型根据前面的单词预测接下来的 3 个单词的最终输出。

LSTM 模型的输出

上面的输出显示了输入的向量形式以及建议的单词。[6,4,3]是'编码 _ 文本',[[6,4,3]]是'填充 _ 编码'

注意:这里我们将数据分为 3(输入)比 1(目标标签)。所以,一定要输入三个字。

GitHub 上面代码的链接是这个。你可以在那里找到 LSTM 方法的代码。

结论:

上面,我们看到 n-grams 方法不如 LSTM 方法,因为 lstm 具有从文本语料库中更远的地方记住上下文的记忆。在开始一个新项目时,您可能希望通过在互联网上寻找开源实现来考虑一个现有的预训练框架。这样,您就不必从头开始,也不需要担心训练过程或超参数。

乔希·里默尔在 Unsplash 上拍摄的照片

自然语言处理领域的许多最新工作包括开发和训练神经模型,以模拟人类大脑对语言的作用方式。这种深度学习方法使计算机能够以更有效的方式模仿人类语言。

探索 Python 熊猫图书馆

原文:https://towardsdatascience.com/exploring-the-python-pandas-library-67243960271e?source=collection_archive---------40-----------------------

Python 熊猫图书馆

来源

Pandas 是一个 python 库,用于从数据中分析、转换和生成统计数据。在本帖中,我们将讨论 Pandas 中用于数据争论和探索的几种有用的方法。出于我们的目的,我们将使用来自 Kaggle医疗费用个人数据集数据。

我们开始吧!

读取数据

首先,让我们导入 pandas 库:

import pandas as pd

接下来,让我们读入熊猫数据框。Pandas 数据框基本上是一个由行和列组成的类似于表格数组的数据结构。为了读入数据,我们可以使用。read_csv()'方法:

df = pd.read_csv("insurance.csv")

接下来,我们可以使用。head()'和'。tail()'方法分别查看第一行和最后五行数据:

print(df.head())

print(df.tail())

我们还可以查看列名:

print(df.columns)

这对于包含大量列的数据集尤其有用。

清洗数据

很多时候,当使用真实数据时,我们必须处理数据列中缺失的值。使用 pandas,我们可以很快了解数据有多稀疏。isnull()”方法:

print(df.isnull().sum())

我们看到该数据不包含任何缺失值。让我们人为地为“儿童”和“地区”列添加缺失的值,以演示我们如何删除这些值:

df.loc[df.region == 'southwest', 'region'] = np.nan
df.loc[df.children == 1, 'children'] = np.nan

现在让我们计算一下我们添加的缺失值的数量:

print(df.isnull().sum())

我们可以使用。“dropna()”方法来移除这些缺少的值。这既可以就地完成,也可以返回一个值,存储在一个新的变量中。为了适当地删除丢失的值,我们执行以下操作:

df.dropna(inplace=True)
print(df.isnull().sum())

这里,df 变量已经被修改。或者,我们可以执行以下操作:

df = df.dropna()

让我们再次打印缺失的值:

print(df.isnull().sum())

我们可以在丢失值之前和之后检查数据帧的长度:

print("Length Before:", len(df))
df.dropna(inplace=True)
print("Length After:", len(df))

此外,如果想要填充数据框中缺失的值,可以使用。fillna()”方法。要做到这一点:

df.fillna(0, inplace=True)

或者:

df = df.fillna(0)

由于我们输入的是缺失值,因此数据帧的长度不应改变:

print("Length Before:", len(df))
df.fillna(0, inplace=True)
print("Length After:", len(df))

过滤数据

我们可以根据列值轻松过滤数据帧。例如,如果我们想要对应于 30 岁以下患者的记录,我们可以写:

df = df[df['age'] < 30]
print(df.head())

如果我们想要与超过 10,000 美元的费用相对应的记录,我们可以写:

df = df[df['charges'] > 10000]
print(df.head())

我们还可以过滤数据框,仅包含吸烟者:

df = df[df['smoker'] == 'yes']

让我们打印前五行:

print(df.head())

请注意,在删除数据后,索引已经被修改。我们可以通过使用“reset_index”方法来解决这个问题:

df.reset_index(inplace=True)
del df['index']
print(df.head())

我们也可以使用多个条件进行过滤。假设我们想要提取与女性吸烟者相对应的数据。我们可以使用。loc[]'方法如下:

df = df.loc[(df.sex == 'female') & (df.smoker == 'yes')]
df.reset_index(inplace=True)
del df['index']
print(df.head())

我们甚至可以添加两个以上的条件。让我们过滤 50 岁以上的女性吸烟者:

df = df.loc[(df.sex == 'female') & (df.smoker == 'yes') & (df.age >= 50)]
df.reset_index(inplace=True)
del df['index']
print(df.head())

选择行和列

现在我们将讨论如何使用。iloc[]'方法来选择索引。为了选择数据集中的第一个、第二个和最后一个索引,我们执行以下操作:

print(df.head())
print("---------------------First---------------------")
print(df.iloc[0])
print("---------------------Second---------------------") 
print(df.iloc[1])
print("---------------------Last---------------------")
print(df.iloc[-1])

你可以用'做类似的事情。特定列的 loc[]。要选择第一行和第二行,我们执行以下操作:

print("---------------------First---------------------")
print(df.loc[0, 'sex'])
print("---------------------Second---------------------") 
print(df.loc[1, 'sex'])

我们也可以在一列中选择多行:

print("---------------------First---------------------")
print(df.loc[0:3, 'sex'])
print("---------------------Second---------------------") 
print(df.loc[3:6, 'sex'])

汇总数据&生成统计数据

现在,我们将讨论如何从数据框中的数据生成统计数据。我们可以为特定类别创建单独的数据框,并从结果数据框中生成统计数据。让我们为男性和女性记录创建单独的数据框:

df_female = df[df['sex'] == 'female']
df_male = df[df['sex'] == 'male']

让我们看看女性的*均费用:

print("Female charges: ", df_female['charges'].mean())

让我们看看男性的*均费用:

print("Male charges: ", df_male['charges'].mean())

我们还可以使用'找到任何数字列的最大值。max()”方法。让我们对完整的数据集这样做:

print("Maximum Value: ", df['charges'].max())

我们还可以找到最小值:

print("Minimum Value: ", df['charges'].min())

我们可以将这些方法应用于其他数值列。让我们对“年龄”列也这样做:

print("Maximum Value: ", df['age'].max())
print("Minimum Value: ", df['age'].min())

让我们对“bmi”列进行同样的操作:

print("Maximum Value: ", df['bmi'].max())
print("Minimum Value: ", df['bmi'].min())

另一个有用的方法是。可用于聚合数据的“groupby()”方法。假设我们想知道男性和女性吸烟者的数量:

df_yes = df[df['smoker'] == 'yes']
df_yes  = df_yes.groupby(['sex'])['smoker'].count()
print(df_yes.head())

我们看到男性吸烟者的数量大于女性吸烟者的数量。我们也可以看看非吸烟者的分组统计数据:

df_no = df[df['smoker'] == 'no']
df_no  = df_no.groupby(['sex'])['smoker'].count()
print(df_no.head())

我们也可以使用。“groupby()”方法来获取不同类别类型的*均医疗费用。之前我们看了男性和女性的*均医疗费用。我们可以用'再次生成那些统计数据。groupby()':

df  = df.groupby(['sex'])['charges'].mean()
print(df.head())

我们还可以为每个区域组生成这些统计数据:

df  = df.groupby(['region'])['charges'].mean()
print(df.head())

看看每个吸烟者群体的*均医疗费用也是很有趣的:

df  = df.groupby(['smoker'])['charges'].mean()
print(df.head())

正如我们所料,吸烟者的医疗费用明显高于不吸烟者。我们也可以按吸烟者和性别分组:

df  = df.groupby(['smoker', 'sex'])['charges'].mean()
print(df.head())

我们还可以查看其他统计数据,如跨类别收费的标准偏差。标准差衡量一组值的离差量。在这种情况下,我们将考虑电荷的标准偏差,它对应于电荷数据的分散。让我们来看看不同性别间电荷的标准差:

df  = df.groupby(['sex'])['charges'].std()
print(df.head())

我们还可以查看不同地区的收费标准偏差:

df  = df.groupby(['region'])['charges'].std()
print(df.head())

或者我们可以应用。跨多列的“groupby()”。让我们计算跨地区/性别组的费用标准偏差:

df  = df.groupby(['region', 'sex'])['charges'].std()
print(df.head())

接下来,让我们计算不同吸烟者/性别群体的标准偏差:

df  = df.groupby(['smoker', 'sex'])['charges'].std()
print(df.head())

迭代数据帧

接下来,我们将讨论如何迭代数据框行。我们可以使用一种叫做。iterrows()',这将允许我们对行和索引值进行迭代:

for index, rows in df.iterrows():
    print(index, rows)

下面是一些输出值的屏幕截图:

我们还可以为我们的迭代选择特定的行。让我们对“性别”、“费用”和“吸烟者”栏也这样做:

for index, rows in df.iterrows():
    print('sex:', rows['sex'], 'charges:', rows['charges'], 'smoker:', rows['smoker'])

我们还可以根据其他列的值创建新列。假设我们想要创建一个新列来指定一个记录是否对应于一个女性吸烟者。我们可以使用。iterrows()'和'。用布尔值标记女性吸烟者的 at[]'方法:

for index, rows in df.iterrows():
    if (rows.sex == 'female') and (rows.smoker == 'yes'): 
        df.at[index, 'female_smoker'] = True
    else:
        df.at[index, 'female_smoker'] = False

让我们打印修改后的数据框的前五行:

print(df.head())

我们可以用'执行更复杂的标记。iterrows()'和'。位于[]'。假设我们要创建一列布尔值,对应于 50 岁以上有孩子的男性吸烟者:

for index, rows in df.iterrows():
    if (rows.sex == 'male') and (rows.smoker == 'yes') and (rows.age > 50) and (rows.children > 0): 
        df.at[index, 'male_smoker_with_children'] = True
    else:
        df.at[index, 'male_smoker_with_children'] = False

让我们打印结果数据框的前五行:

print(df.head())

我们可以做的另一件事是使用 collections 模块中的“Counter”方法来了解新列的布尔值分布。让我们将“计数器”方法应用于“女性吸烟者”列:

from collections import Counter
print(Counter(df['female_smoker']))

这对应于 115 个女性吸烟者的记录。让我们将“计数器”应用于 50 岁以上有孩子的男性吸烟者一栏:

print(Counter(df['male_smoker_with_children']))

这相当于 21 个 50 岁以上有孩子的男性吸烟者的记录。

写入文件

最后,如果我们对数据框进行了足够的修改,以至于我们希望将其保存到一个单独的文件中,那么我们可以使用。“to_csv()”方法:

df.to_csv("insurance_edit.csv")

结论

总之,在这篇文章中,我们讨论了熊猫的几种方法。我们讨论了如何使用 Pandas 方法读取、清理和过滤数据。我们还讨论了如何生成聚合统计数据、迭代数据帧以及将数据写入新文件。我希望这有所帮助。这篇文章中的代码可以在 GitHub 上找到。感谢您的阅读!

探索数据科学的真实世界

原文:https://towardsdatascience.com/exploring-the-real-world-of-data-science-57dc1f3fec3d?source=collection_archive---------34-----------------------

我在现实世界中学到的关于数据科学的东西

图片提供:阿蒂卡·马安

*年来,数据科学、机器学习和人工智能一直是热门领域。许多人希望成为数据科学家,并投入巨大努力通过大学、在线课程或自学来提升他们的技能。然而,就工作和解决业务问题而言,在现实世界中有很多挑战。作为一名数据科学家,非技术技能同样重要。在这篇博客中,我分享了我作为一名数据科学家在工作中的亲身经历。

理解业务问题

现实世界的问题中有很多挑战,学生在大学里不一定会遇到。在学校,他们曾经得到一个结构化的问题和一个流行的数据集,并最终得到精确的解决方案。然而,行业中的问题通常是非结构化的和复杂的。任何关于这个问题的假设在现实世界中都会适得其反。在深入分析之前,最好完全了解业务问题。理解业务问题包括对问题及其领域做更多的研究、计划、向客户提出正确的问题以及与团队成员进行讨论。

协力

数据科学是关于逻辑思维,在解决问题时产生更多的想法和创造力。因此,团队合作在数据科学中扮演着重要的角色。也有必要多维思考,而不是一维思考。团队成员可能来自不同的背景,拥有不同种类的技能。发挥每个团队成员的力量,并相应地分配工作。这帮助我用不同的方式解决问题,并学习新的东西。

好听众

另一个关键技能是成为一个好的倾听者。数据科学是关于共享和协作的。基本上,这个人需要理解团队中其他人的观点。很多时候,其他团队成员提出了好的想法,这些想法可能是独一无二的,为了在项目中成功实施,倾听和理解它们是必要的。正如我上面所说的,数据科学不是一个人的表演,它总是一个团队的努力。

证明文件

数据科学或人工智能是一个快速发展的领域,因此,总会有一些新的和至关重要的东西需要学习。很难记住所有的事情,文档帮助我克服了这个挑战。此外,它还帮助我明确了自己的思维过程。我过去常常记录我的学习、分析、建模过程、实验和代码。此外,我会详细地写下我失败的实验及其原因,从长远来看,这有助于我强化我的想法。除此之外,它还帮助我提高了我的沟通和理解概念的细节。你可以记录下你学到的或遇到的小事情,这些小事情从长远来看会产生很大的影响。使用你自己方便的工具来记录。

敏捷环境

在敏捷环境中工作让我在每个冲刺阶段的开始都有清晰的计划、优先级和方向。拥有敏捷的思维有助于应对变化和处理不确定性。如果你遇到不确定性,尝试各种选择,收集反馈,反复改进。这也给了我与不同团队合作的机会。在每个 sprint 结束时,以机器学习模型的形式向利益相关者提交一个最小可行产品(MVP)帮助我以更好的形式塑造我的项目。此外,每个 sprint 结束时的反馈帮助我纠正错误,高效地交付项目。

讲故事

讲故事是数据科学的重要组成部分。我们正在处理数据,创建模型,并寻找洞见。但是,从商业角度来看,这个模型说明了什么呢?换句话说,这种模式如何为公司赚钱或解决问题?利益相关者和管理层对 p 值或任何其他统计数据都不感兴趣。这里的主要挑战是以吸引人的方式用更简单的术语向非技术观众解释模型。一种方法是通过一个小故事来解释这个模型。这是我去年最大的收获之一。始终包括良好的视觉效果,这有助于以故事的形式传达信息。讲故事是一门艺术,需要时间和大量的练习。

展示输出的创造性

我们总是使用传统的 PPT 向客户或利益相关者展示我们的工作。我们为什么不创建一个 web 应用程序或仪表板来解释我们的模型输出,而不是 PPT 呢?创建一个 web 应用程序或仪表板显示了对项目的承诺,也与利益相关者和客户建立了联系。

始终使用版本控制

版本控制是每个人都包括在工作流中的一件重要的事情。它有助于集中管理您的代码,而不是将其保存到 PC/笔记本电脑或外部驱动器中。这样,当你在任何地方进行新项目时,你都可以参考代码或文档。

编码

在过去的 8 个月里,我显著提高了我的编码技能。我在工作和比赛中学到的一件事是编写函数式或面向对象的代码,以获得最大的代码可重用性。这将有助于在未来的项目中使用代码,并减少当前项目的时间。每当我提到 stackoverflow 或 google 时,我都会记录代码函数,这帮助我学习了新的编码知识。始终遵循最佳实践,让您的代码对读者友好。

请求帮助

数据科学融合了计算机科学、统计学、机器学习和领域专业知识。因此,从处理不同的步骤,从清理数据到解释最终的模型并部署它,都需要 it 人员的技能。不要被吓倒,你不可能一天就掌握数据科学。因此,如果你陷入困境,请随时寻求帮助,通过这种方式你将获得更多的知识,并最终使你对自己的方法充满信心。

继续学习!

人工智能是 IT 行业的新热点,让我们直面这样一个事实,所有这些都不可能在短时间内被任何人所同化。决定战略性地利用它,每天投资一两个小时来学习新概念和解决新问题,包括学习新算法、编码、阅读博客、做个人项目等。除此之外,我强烈推荐阅读对心流和讲故事技巧有很大帮助的非技术性书籍,这将是我们继续前进的有用特征。

热情

在我最初的日子里,我的印象是,在这个分析的世界里,每个人都是一切的主人。但是后来我意识到我的假设是错误的。我知道这对这里的每个人来说都是一个不断学习的过程。在这个游戏中保持流行的核心是 激情、好奇心和渴望 了解更多。无论是机器学习还是深度学习或 NLP,解决复杂问题的永远是激情。

免责声明—本博客包含我的个人经历。如果这些信息对你有所帮助,我很乐意倾听。

感谢阅读!

你也可以在 KDnuggets 上阅读这篇文章。

探索 CDI 数据集中糖尿病、高血压和高胆固醇之间的关系

原文:https://towardsdatascience.com/exploring-the-relationship-between-diabetes-high-blood-pressure-and-high-cholesterol-in-the-cdi-16f15fc80b73?source=collection_archive---------62-----------------------

使用数据分析和统计

我的上一篇文章讨论了糖尿病带各州糖尿病患病率和糖尿病相关死亡率的性别和种族差异。这些数据来自 CDC 的慢性病指标(CDI):糖尿病数据集,它提供了 2010 年至 2018 年所有州和地区的糖尿病相关信息的汇编。

在本文中,我想使用 CDI 糖尿病数据集的数据来探讨糖尿病与其共病(高血压和高胆固醇)之间的关系。就像糖尿病一样,这两种共病是心脏病的已知风险因素。我想看看在糖尿病带诊断为糖尿病的成人中,一种共病是否比另一种更普遍。我还想了解在糖尿病带中诊断为糖尿病的成年人中,高血压患病率和高胆固醇患病率是否存在性别偏见。

这种探索性数据分析是在 Jupyter Notebook/Python 中完成的。用于生成本文中使用的这些可视化和统计测试的代码已经发布到 GitHub 这里

巴克等人在 2011 年描述的糖尿病带包括“阿拉巴马州、阿肯色州、佛罗里达州、佐治亚州、肯塔基州、路易斯安那州、北卡罗来纳州、俄亥俄州、宾夕法尼亚州、南卡罗来纳州、田纳西州、德克萨斯州、弗吉尼亚州和西弗吉尼亚州……密西西比州。”在我的上一篇文章中,我关注的是这些州的子集,因为这些州比美国其他州受糖尿病的影响更大,因此可以进行更有针对性的分析。在本文中,我将继续分析这些数据,并仅针对构成糖尿病带的州得出结论。

在开始之前,我想提供一些关于这个主题的技术背景。高血压、高胆固醇和糖尿病都是心脏病的危险因素。高血压意味着血管中的血流量增加,使心脏工作更多,心脏变弱(美国心脏协会,2016)。高水*的胆固醇(体内发现的一种脂肪)会阻塞血液流动。如果血管被胆固醇堵塞,它们就会变得狭窄,需要更高的血压来保持血液流动,最终削弱心脏,增加心脏病的可能性。因此,研究这些共病的患病率对人群健康研究很重要。

与上一篇文章类似,我将继续分析 2017 年的数据,因为这是可用数据中最*的一年。

首先,我想看看糖尿病共病的总体患病率:高血压和高胆固醇。

2017 年糖尿病共病患病率。来源:我自己的数据分析。

从上图可以看出,在诊断为糖尿病的成年人中,高血压的患病率高于高胆固醇的患病率。统计测试证实两者之间存在显著差异:

  • 使用独立的 t 检验来确定在诊断为糖尿病的成人中高血压患病率和高胆固醇患病率之间是否存在统计学显著差异。使用 Levene 方差相等性检验(p > 0.05),满足正态性(p > 0.05)和方差齐性假设。对于确诊为糖尿病的成年人,高血压患病率 (M = 65.81,SD = 4.81),明显高于高胆固醇患病率 (M = 56.31,SD = 4.37),p = 0.00 < 0.05。

这一观察结果与 CDC 的《2020 年国家糖尿病统计报告》的数据相吻合,该报告指出,2013 年至 2016 年,68.4%的诊断为糖尿病的成年人患有高血压(血压> 140/90),或目前正在接受高血压药物治疗,43.5%的人胆固醇水*高(LDL 胆固醇> 130 mg/dl)。糖尿病带和美国的高血压患病率相似。然而,糖尿病带的高胆固醇患病率高于美国。与美国其他地区相比,高胆固醇患病率的增加可归因于糖尿病带中诊断为糖尿病的成年人密度的增加。

接下来,我想看看被诊断为糖尿病的成年人中高血压患病率和高胆固醇患病率之间的性别差异。

2017 年诊断为糖尿病的成年人中高血压的患病率

从诊断为糖尿病的成年人中高血压的患病率开始,我可以看到男性和女性成年人的患病率相似。两组之间没有显著差异,这一点通过统计检验是显而易见的:

  • 使用独立的 t 检验来确定男性和女性成人高血压患病率之间是否存在统计学显著差异。使用 Levene 方差相等性检验(p > 0.05),满足正态性(p > 0.05)和方差齐性假设。男性 (M = 67.64,SD = 4.90) 和女性 (M = 64.24,SD = 7.15),高血压患病率无显著差异,p = 0.15 > 0.05。

2017 年诊断为糖尿病的成年人中高胆固醇的患病率

上述诊断为糖尿病的成年人中高胆固醇患病率的图表显示,男性和女性成年人具有相似的高胆固醇患病率。统计测试证实了这一点:

  • 使用独立的 t 检验来确定男性和女性成年人的高胆固醇患病率之间是否存在统计学显著差异。使用 Levene 方差相等性检验(p > 0.05),满足正态性(p > 0.05)和方差齐性假设。男性 (M = 58.41,SD = 9.00) 和女性 (M = 56.13,SD = 5.36),高胆固醇患病率无显著差异,p = 0.42 > 0.05。

CDI 糖尿病数据集还包括种族数据;然而,由于缺少大量数据,我没有考虑种族在共病患病率中的作用。黑人(非西班牙裔)和西班牙裔人口的数据缺失太多,我无法做出有意义的见解。尽管如此,我还是很想知道在糖尿病共病的种族差异方面做了哪些研究。根据 Walker 等人(2016)的研究,与其他族裔群体相比,黑人(非西班牙裔)个体“始终表现出最低的血压控制率”。在黑人(非西班牙裔)的血脂控制中也发现了类似的趋势(Walker 等人,2016)。在我之前的文章中,一项种族差异分析显示,黑人(非西班牙裔)在整个糖尿病带中具有最高的糖尿病患病率和糖尿病相关死亡率。黑人(非西班牙人)受糖尿病的影响很大;由此可见,他们也会受到糖尿病共病的严重影响。

在我的上一篇文章中,我讨论了数据的局限性。同样的限制也适用于此。这些数据的来源是行为风险因素监测系统(BRFFS),该系统通过调查收集数据,并为诊断为糖尿病的成年人提供数据。因此,没有通过 BRFFS 的调查收集方法接触到的任何人都不包括在内,未确诊的糖尿病患者也不包括在内。此外,1 型和二型糖尿病之间没有区别。

另一个限制是 CDI 糖尿病数据集中这两个特定问题的种族数据缺失。性别、种族、环境因素和社会文化因素都有助于糖尿病的发展;因此,没有所有的碎片,很难拼凑出一幅画。

总之,糖尿病是一种复杂的疾病,有许多危险因素和并发症。我对 CDI 糖尿病数据集的分析着眼于高血压、高胆固醇和糖尿病之间的相互联系。在这个数据集中,在诊断为糖尿病的成年人中,高血压或高胆固醇没有性别偏见,但在 2017 年糖尿病带诊断为糖尿病的成年人中,高血压的患病率明显高于高胆固醇。

引用:

美国心脏协会。"血压多高会导致心力衰竭."2016,https://www . heart . org/en/health-topics/高血压/高血压对健康的威胁/高血压会导致心脏衰竭

美国已诊断糖尿病的地理分布:糖尿病带。美国预防医学杂志第 40 卷,4(2011):434–9。doi:10.1016/j . amepre . 2010 . 12 . 019

疾病控制和预防中心,2020 年全国糖尿病统计报告。第 9 页。“糖尿病相关并发症的风险因素”。https://www . CDC . gov/diabetes/pdf/data/statistics/national-diabetes-statistics-report . pdf

种族、民族和健康的社会决定因素对糖尿病结果的影响。美国医学科学杂志第 351 卷,4(2016):366–73。doi:10.1016/j . amjms . 2016 . 01 . 008

探索正则化背后简单而令人满意的数学

原文:https://towardsdatascience.com/exploring-the-simple-satisfying-math-behind-regularization-2c947755d19f?source=collection_archive---------20-----------------------

来源: Unsplash

对过度拟合的迷人防御

正则化常用于机器学习,从简单的回归算法到复杂的神经网络,以防止算法过拟合。让我们通过简单数学的透镜来探索正则化控制模型的令人难以置信的令人满意和美丽的方式。

考虑一个非常简单的回归任务。有六个参数(系数)表示为β和,五个输入表示为 x 。模型的输出只是每个系数乘以输入(加上一个截距项β-0)。

为了使这个问题人性化,我们假设我们正试图基于五个因素来预测学生在一次测试中的分数(*f*(*x*)的输出):1)他们花了多少时间做作业(hw);2)他们睡了多少小时(sleep);3)他们上次测试的分数(score);4)他们当前班级的 GPA(gpa);以及 5)他们在测试前是否吃了食物(food)。

回归模型的目标是最小化“损失”,试图量化误差。这通常通过均方误差来实现。例如,如果我们有一个输入 x 和目标 y 的数据集,对于每个数据点,我们将评估预测目标和实际目标的差异,对其求*方,并在所有项目中取*均值。为了简洁起见,可以用这样的简写来表达( E 表示“期望值”或*均值)。

因此,线性回归被训练成沿着这个损失函数 l 优化其参数。然而,请注意,我们的模型有许多特点,这通常与更高的复杂性相关,类似于增加多项式的次数。所有的特征都相关吗?如果不是,它们可能只是为模型过度拟合提供了另一个自由度。

假设一个学生当前的 GPA 和他们那天早上是否吃了食物,结果提供了最小的好处,同时导致模型过度拟合。如果这些系数被设置为 0,那么这些特征将从模型中完全消除。

这导致了一个更简单的模型,该模型对数据过度拟合的能力较弱。在某种意义上,这种将系数降低到零的行为类似于特征选择。

正则化基于这样的想法,即较大的参数通常会导致过拟合,因为它们 a)不为零,所以它向生态系统中添加了另一个变量/自由度 b)会导致预测中的大波动和不自然的波动。这种高方差是过度拟合的警示信号。

让我们探讨两种类型的正则化:L1 正则化和 L2 正则化。

L1 正则化通过添加“正则化项”略微改变了线性回归中使用的损失函数,在这种情况下是“ λE [| β| ]”。我们来分解一下: E [| β| 的意思是‘参数绝对值的*均值’,而 λ 是一个比例因子,它决定了参数的*均值应该在总损失上招致多少损失。

总的来说,这鼓励更小的参数。当模型基于损失调整其系数以达到降低其值的总体目标时,它必须确定某个特征是否有足够的价值来保留,因为它比正则化项更多地增加了预测能力。从根本上来说,保留这些特性更有利可图。

然后,丢弃不太有用的特征,模型变得更简单。

L2 正则化本质上是相同的,但是参数在被*均之前被*方。因此,正则化是参数*方的*均值。这试图完成同样的任务,即鼓励模型降低系数的整体值,但结果不同。

值得注意的是,常规线性回归是 L1/L2 归一化的特例,其中λ参数等于 0,正则项基本上被抵消。

为了探究 L1 和 L2 归一化的不同效果,我们需要看看它们的导数,或者它们的函数在某一点的斜率。为了简化,我们可以表示为:

  • L1 正则化为y = x。导数是 1。
  • L2 正规化为y = x²。导数是 2 x

这意味着:

  • 在 L1 正则化中,如果参数从 5 减少到 4,相应的正则化减少 5–4 = 1。
  • 在 L2 正则化中,如果参数从 5 减少到 4,相应的正则化减少 25–16 = 9。

在 L1 正则化中,减少参数的回报是恒定的,而在 L2 正则化中,随着参数接*零,回报变得越来越小。从参数值 5 到 4 会产生 9 的下降,但是从 1 到 0 只会产生 1 的提高。

注意,记住模型只关心相对回报。奖励的绝对值与我们无关,因为 lambda 参数总是可以放大或缩小。重要的是模型将从参数的某个变化中获得多少减少或增加。

因此,在使用 L2 时,模型可能决定值得“保留一个特征”(不丢弃,或将参数减少到 0),因为:

  • 它提供了大量的预测能力(减少损失中的第一项,*E*[(*f*(*x*)−*y*)²])。
  • 降低参数值不会有太大的好处,因为它已经接* 0 了。
  • 减小参数将消除损失函数第一项中的增益,而第二项中的增益要小得多(*λE*[*β²*])。

所以,总的来说:

  • L1 正则化将产生具有更少特征的更简单的模型,因为它为减少参数值提供了一致的回报。它可以被认为是一种变量选择的“自然”方法,例如,它可以去除多重共线性变量。
  • L2 正则化将产生参数接*但很可能不在零点的更复杂的模型,因为它提供递减的奖励来减少参数值。它能够学习更复杂的数据模式。

两种正则化方法都通过防止每个参数对最终结果产生太大影响来降低模型过度拟合的能力,但会导致两种不同的结果。

如果你正在寻找一个简单和轻量级的模型,L1 正则化是一个不错的选择。它采取了一种严肃的方法来消除对输出没有深刻影响的变量。在回归中,这被称为“套索回归”,可以在像sci-kit learn这样的标准库中找到。

另一方面,如果您的任务更复杂,例如神经网络中的正则化,使用 L1 可能是一个坏主意,它可以通过将大量超参数设置为零来杀死它们。L2 正则化通常在神经网络中被推荐,因为它充当护栏,但不会过多地干扰神经元的复杂工作。

L2 回归被称为“岭回归”,可以在标准库中实现。在神经网络中,丢弃比 L2 正则化更“自然”,但在许多用例中,应该使用后者或两者都使用。

要点

  • 正则化通过减少任何特征对结果的整体影响来防止机器学习模型中的过度拟合。
  • L1 正则化和 L2 正则化都不断地给模型施加压力以减少它们的参数。前者给出恒定的奖励,但是后者根据参数接* 0 的程度给出递减的奖励。
  • 正则化迫使模型反复比较某个特征带来的预测能力与其增加正则化项的程度,这导致模型选择保留更重要的特征。
  • L1 将导致许多不太相关的变量被一起消除(系数设置为 0),而 L2 将导致不太相关的变量仍然存在,但系数较小。

感谢阅读!

探索 Softmax 函数

原文:https://towardsdatascience.com/exploring-the-softmax-function-578c8b0fb15?source=collection_archive---------52-----------------------

用 Wolfram 语言发展直觉

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

在机器学习中,分类问题通常用神经网络来解决,神经网络给出它被训练识别的每个类别或类型的概率。一个典型的例子是图像分类,其中神经网络的输入是图像,输出是图像用概率表示的可能事物的列表。

Wolfram 语言(WL)带有一个大型的预训练神经网络库,包括解决分类问题的网络。例如,内置的系统功能 ImageIdentify 使用了一个预训练的网络,它可以识别图像中的 4000 多个对象。

作者在 Unsplash 上使用了詹姆斯·萨顿的照片

边注:由于 Wolfram notebook 界面独特的排版功能(例如将代码与图像混合),所有代码都用屏幕截图显示。在这个故事的结尾有一个笔记本,里面有完整的代码。

您可以直接使用底层神经网络来访问 4000 多个可能对象中每一个的概率。显然,“家猫”在这种情况下以几乎 1 的概率轻松获胜。其他类型的猫以较低的概率紧随其后。“浴帘”的结果可能是因为图像的背景。将所有 4,000+个概率相加得出数字 1.0。

作者在 Unsplash 上使用了詹姆斯·萨顿的照片

当你详细检查神经网络并查看它的组成层时,你会注意到最后一层是一种叫做 SoftmaxLayer 的东西。这一层在神经网络中非常常用,用于将一系列概率分配给一系列对象。

(图片由作者提供)

SoftmaxLayer 使用 softmax 函数,该函数将一个数字列表作为输入,并将一个规范化的数字列表作为输出。更具体地说,输入列表中的每个元素都被取幂并除以或归一化为所有取幂元素的总和。

(图片由作者提供)

从函数定义中可以清楚地看出,输出元素的总和总是 1。原因是输出中的每个元素都是一个分数,其中分母是所有分子的总和。不太清楚的是任意输入列表如何与输出列表相关,因为 softmax 函数是非线性的。

为了对此有所帮助并获得直觉,我编写了一个 WL 函数来理解 softmax 函数的输入和输出。它简单地创建了两个条形图,一个绘制输入列表,一个绘制输出列表。

understand[list_List] := Row[{
 BarChart[list], 
 Style[" \[Rule] ", 32],
 BarChart[SoftmaxLayer[][list]]
}]

让我们从三个零的简单输入开始。在这种情况下,输出也有三个相等的元素,因为它们的总和是 1,所以它们都是 0.333…

(图片由作者提供)

这适用于所有元素都相同的任何列表。例如,7 的四元素列表将产生所有元素都为 0.25 的结果:

(图片由作者提供)

当输入元素不完全相等时,事情变得更加有趣。让我们从线性增加的元素列表开始。输出是指数函数的缩小版本。

(图片由作者提供)

类似地,线性递减元素的列表产生递减的指数函数:

(图片由作者提供)

一个向下开口的抛物线会产生一条看起来像正态分布的输出“曲线”(可能正是如此?).

(图片由作者提供)

向上开口的抛物线给出更极端的输出,端点值占主导地位。

(图片由作者提供)

最后,主要是为了好玩,周期函数以某种重新调整的形式保持其周期性:

(图片由作者提供)

在笔记本中探索这一点和更多内容是非常有教育意义的。理解 softmax 函数如何工作有助于理解神经网络如何计算它们的最终分类概率分配。如果你想亲自体验更多,请从 Wolfram Cloud 下载这款笔记本。如果你对 WL 完全陌生,我推荐你阅读我最*的一篇名为“学习 Wolfram:从零到英雄”的文章。

用 NLTK 探索 Trump Twitter 档案

原文:https://towardsdatascience.com/exploring-the-trump-twitter-archive-6242e5100a74?source=collection_archive---------39-----------------------

探索特朗普

适合喜欢冒险的 NLP 初学者。

尼古拉斯·托马斯Unsplash 上拍摄的照片

在本帖中,我们将探索由 特朗普推特档案 提供的数据集。这是 探索王牌 系列的一部分。

对于这个项目,我们将使用 pandas 和 numpy 进行数据操作,使用 matplotlib 进行可视化,使用 datetime 处理时间戳,使用 unicodedata 和 regex 处理字符串,最后使用 nltk 进行自然语言处理。

让我们从启动 Jupyter 笔记本开始吧!

环境

我们将导入 pandas 和 matplotlib,并为 Jupyter 设置显示选项,以便行和列不会被截断。

# for manipulating data
import pandas as pd
import numpy as np# for visualizations
%matplotlib inline
import matplotlib.pyplot as plt# to print out all the outputs
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"# set display options
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
pd.set_option('display.max_colwidth', -1)

获取数据

让我们把数据读入数据帧。如果你想跟进,你可以在这里下载数据集。这个数据集包含特朗普总统从 2017 年 1 月 20 日上任到 2020 年 5 月 30 日的推文。

df = pd.read_csv('trump_20200530.csv')

让我们看看前五行,看看记录(行)和字段(列)的数量。

df.head()
df.shape

让我们对这些列进行一个快速的重命名,以便于以后使用。

df.columns=['source', 'tweet', 'date_time', 'retweets', 'favorites', 'is_retweet', 'id']

让我们删除 id 列,因为它现在并不真正相关。

df = df.drop(columns=['id'])

让我们做一个快速的健全性检查,这次我们还要检查列的 dtypes。

df.head()
df.info()

使用时间戳

我们可以从前面的截图中看到,' date_time '列是一个字符串。让我们把它解析成一个时间戳。

# for working with timestamps
from datetime import datetime
from dateutil.parser import parsedt = []
for ts in df.date_time:
  dt.append(parse(ts))
dt[:5]

让我们添加一个包含时间戳信息的“datetime”列。

df['datetime'] = df.apply(lambda row: parse(row.date_time), axis=1)

让我们仔细检查数据集的数据范围。

df.datetime.min()
df.datetime.max()

修整数据

让我们看看这些推文有多少来源。

df.source.value_counts()

让我们只保留那些使用“iPhone 版 Twitter”应用程序制作的。

df = df.loc[df.source == 'Twitter for iPhone']

我们应该删除旧的“date_time”列和“source”列。

df = df.drop(columns=['date_time', 'source'])

分离转发

看看有多少是转发。

df.is_retweet.value_counts()

让我们创建另一个只包含 retweets 的 dataframe,并删除“is_retweet”列。

df_retweets = df.loc[df.is_retweet == True]
df_retweets = df_retweets.drop(columns=['is_retweet'])

健全性检查:

df_retweets.head()
df_retweets.shape

回到原始数据帧,让我们从数据集中删除 retweets,并完全删除“is_retweet”列。

df = df.loc[df.is_retweet == False]
df = df.drop(columns=['is_retweet'])

另一个健全性检查:

df.head()
df.shape

探索数据

让我们探索这两个数据框架,并回答几个问题。

总统什么时候发微博最多?他什么时候发微博最少?

下图显示,总统在下午 12 点左右最常发推文。他也最少在早上 8 点左右发微博。

title = 'Number of Tweets by Hour'
df.tweet.groupby(df.datetime.dt.hour).count().plot(figsize=(12,8), fontsize=14, kind='bar', rot=0, title=title)
plt.xlabel('Hour')
plt.ylabel('Number of Tweets')

总统哪一天发推特最多?他哪天发的微博最少?

下图显示了总统在周三最常发推文。他周四发的微博也最少。

title = 'Number of Tweets by Day of the Week'
df.tweet.groupby(df.datetime.dt.dayofweek).count().plot(figsize=(12,8), fontsize=14, kind='bar', rot=0, title=title)
plt.xlabel('Day of the Week')
plt.ylabel('Number of Tweets')
plt.xticks(np.arange(7),['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'])

从转发中分离 Twitter 句柄

让我们导入正则表达式,这样我们就可以用它来解析文本并分离出原始推文的 Twitter 句柄。在下面的代码中,我们添加了另一个包含 Twitter 句柄的列。

import repattern = re.compile('(?<=RT @).*?(?=:)')
df_retweets['original'] = [re.search(pattern, tweet).group(0) for tweet in df_retweets.tweet]

让我们创建另一个数据帧,它将只包含最初的 Twitter 句柄及其相关的转发次数。

df_originals = df_retweets.groupby(['original']).sum().sort_values('retweets').reset_index().sort_values('retweets', ascending=False)

让我们快速检查一下数据:

df_originals.head()
df_originals.shape

让我们快速地将结果可视化,这样我们就可以知道数据是否不成比例。

df_originals = df_retweets.groupby(['original']).sum().sort_values('retweets').reset_index().sort_values('retweets', ascending=False)[:10].sort_values('retweets')
df_originals.plot.barh(x='original', y='retweets', figsize=(16,10), fontsize=16)
plt.xlabel("Originating Tweet's Username")
plt.xticks([])

总统最喜欢转推哪个推特用户?

下图显示总统喜欢转发来自“@realDonaldTrump”的推文。

转发量前 5 名

让我们来看看根据最初的 Twitter 句柄被其他人转发最多的前 5 条推文。

先说带“@realDonaldTrump”的。

df_retweets.loc[df_retweets.original == 'realDonaldTrump'].sort_values('retweets', ascending=False)[:5]

还有一个是“@charliekirk11”。

df_retweets.loc[df_retweets.original == 'charliekirk11'].sort_values('retweets', ascending=False)[:5]

检查转发的收藏夹数

让我们看看有多少转发被其他人喜欢。

df_retweets.favorites.value_counts()

令人惊讶的是,没有一条转发似乎受到了任何人的喜爱。奇怪。

我们应该放弃它。

计算 N-Grams

要做一些 n 元排序,我们需要导入 unicodedata 和 nltk。我们还需要指定可能需要从分析中排除的附加停用词。

# for cleaning and natural language processing
import unicodedata
import nltk# add appropriate words that will be ignored in the analysis
ADDITIONAL_STOPWORDS = ['rt'] 

以下是我最喜欢的几个自然语言处理函数:

让我们使用“tweet”栏来看看df数据框架中的前 10 个二元模型。

get_bigrams(df, 'tweet')

现在,对于前 10 个三元模型:

让我们使用viz_bigrams()函数并可视化二元模型。

viz_bigrams(df, ‘tweet’)

类似地,让我们使用viz_trigrams()函数并可视化三元模型。

viz_trigrams(df, 'tweet')

我们做到了!

结论

使用基本的 Python 和 nltk 库,我们探索了来自 Trump Twitter 存档的数据集,并对其进行了一些 n 元排序。

感谢您的阅读!探索性数据分析使用了很多技术,我们在这篇文章中只探讨了其中的一些。我鼓励你坚持练习,并使用其他技术从数据中获得洞察力。

在下一篇*中,我们将继续我们的旅程,进入 Trump Twitter 存档,并* 使用 spaCy 从同一数据集中提取命名实体

如果你想了解更多关于我从懒鬼到数据科学家的旅程,请查看下面的文章:

* [## 从懒鬼到数据科学家

我的无学位数据科学之旅。

towardsdatascience.com](/from-slacker-to-data-scientist-b4f34aa10ea1)

敬请期待!

你可以在推特或 LinkedIn 上找到我。*

用 PyCaret 探索 Trump Twitter 档案

原文:https://towardsdatascience.com/exploring-the-trump-twitter-archive-with-pycaret-5c9e065acd6f?source=collection_archive---------52-----------------------

探索川普

适合喜欢冒险的 NLP 初学者。

洛伦佐·瑞Unsplash 上拍照

在之前的帖子中,我们开始探索由 特朗普推特档案 提供的数据集。这是 探索王牌 系列的第三部。

在这篇文章中,我们将继续我们的旅程,但这次我们将使用 PyCaret。

对于这个项目,我们将使用 PyCaret :

PyCaret 是一个开源的,Python 中的低代码机器学习库,允许您在几秒钟内从准备数据到在您选择的笔记本环境中部署您的模型。

PyCaret 做的比 NLP 多得多。它还进行一系列有监督和无监督的 ML,包括分类、回归、聚类、异常检测和关联规则挖掘。

要了解更多信息,请查看 Moez Ali 的公告:

[## 宣布 PyCaret:一个用 Python 编写的开源低代码机器学习库

Python 中的开源低代码机器学习库。

towardsdatascience.com](/announcing-pycaret-an-open-source-low-code-machine-learning-library-in-python-4a1f1aad8d46)

家政

让我们从安装 PyCaret 开始。只要做pip install pycaret我们就可以出发了!注意:PyCaret 是一个很大的库,所以你可能想在等待它安装的时候喝杯咖啡。

此外,我们需要下载英语语言模型,因为它不是用 PyCaret 自动下载的:

python -m spacy download en_core_web_sm
python -m textblob.download_corpora

获取数据

让我们把数据读入数据帧。如果你想跟进,你可以在这里下载数据集。这个数据集包含了特朗普从 2017 年 1 月 20 日上任那一刻到 2020 年 5 月 30 日的推文。

import pandas as pd
from pycaret.nlp import *df = pd.read_csv('trump_20200530.csv')

让我们先检查一下数据的形状:

df.shape

让我们快速看一下:

df.head()

为了方便起见,我们只对 1000 条推文进行采样。

# sampling the data to select only 1000 tweets
df = df.sample(1000, random_state=493).reset_index(drop=True)
df.shape

主题建模

有趣的部分!

nlp = setup(data = df, target = 'text', session_id = 493,
      customI _stopwords = [ 'rt', 'https', 'http', 'co', 'amp'])

PyCaret 的setup()函数执行以下文本处理步骤:

  1. 移除数字字符
  2. 删除特殊字符
  3. 单词标记化
  4. 停用词删除
  5. 二元模型提取
  6. 三元模型提取
  7. 词汇化
  8. 自定义停用词

所有这些都在一行代码中!

它接受两个参数:在data中的 dataframe 和我们想要在target中传递的文本列的名称。在我们的例子中,我们还使用可选参数session_id来获得再现性,使用custom_stopwords来减少来自 tweets 的噪音。

说了这么多,做了这么多,我们会得到类似这样的结果:

下一步,我们将创建模型,并使用‘lda’:

lda = create_model('lda', num_topics = 6, multi_core = True)

上面,我们创建了一个‘lda’模型,并将主题数量作为6传入,并对其进行设置,以便 LDA 将使用所有可用的 CPU 内核来并行化和加速训练。

最后,我们将使用assign_model()为数据集的其余部分分配主题比例。

lda_results = assign_model(lda)
lda_results.head()

可视化结果

让我们绘制整个语料库的总体频率分布图:

plot_model()

现在让我们提取整个语料库的二元模型和三元模型:

plot_model(plot = 'bigram')
plot_model(plot = 'trigram')

但是如果我们只想从特定主题中提取 n 元语法呢?简单,我们只要传入topic_num参数。

plot_model(lda, plot = 'trigram', topic_num = 'Topic 1')

如果我们想要主题的分布,我们将简单地改变它并在plot参数中指定它。

plot_model(lda, plot = 'topic_distribution')

就是这样!

自上任以来,我们已经成功地对特朗普总统的推文进行了主题建模。

奖金回合

Moez Ali 写了一篇关于在 Power BI 中使用 PyCaret 的很棒的教程。看看这个:

[## 基于 PyCaret 的 Power BI 主题建模

在 Power BI 中实现主题模型的分步指南

towardsdatascience.com](/topic-modeling-in-power-bi-using-pycaret-54422b4e36d6)

感谢您的阅读!探索性数据分析使用了很多技术,我们在这篇文章中只探讨了其中的一些。我鼓励你坚持练习,并使用其他技术从数据中获得洞察力。

在下一篇文章中,我将为 pycaret 的自然语言处理模块做一个初学者指南。

感谢您的阅读。如果你想了解更多关于我从懒鬼到数据科学家的旅程,请查看下面的文章:

[## 从懒鬼到数据科学家

我的无学位数据科学之旅。

towardsdatascience.com](/from-slacker-to-data-scientist-b4f34aa10ea1)

如果你正在考虑改变方向,进入数据科学领域,现在就开始考虑重塑品牌:

[## 懒鬼将自己重塑为数据科学家指南

给我们其他人的固执己见的建议。热爱数学,选修。

towardsdatascience.com](/the-slackers-guide-to-rebranding-yourself-as-a-data-scientist-b34424d45540)

敬请期待!

你可以通过推特LinkedIn 联系我。

1 PyCaret。(2020 年 6 月 4 日)。为什么是 PyCarethttps://pycaret.org/

用 SpaCy 探索特朗普推特档案

原文:https://towardsdatascience.com/exploring-the-trump-twitter-archive-with-spacy-fe557810717c?source=collection_archive---------56-----------------------

探索川普

适合喜欢冒险的 NLP 初学者。

莱昂·塞伯特在 Unsplash 上的照片

在前一篇 的帖子 中,我们着手探索 Trump Twitter 提供的数据集 。这是 探索王牌 系列的第二部。

在这篇文章中,我们将继续我们的旅程,但这次我们将使用 spaCy。

对于这个项目,我们将使用 pandas 进行数据操作,使用 spaCy 进行自然语言处理,使用 joblib 加快速度。

让我们从启动 Jupyter 笔记本开始吧!

家政

让我们导入熊猫并设置显示选项,这样 Jupyter 就不会截断我们的列和行。让我们也为可重复性设置一个随机种子。

# for manipulating data
import pandas as pd# setting the random seed for reproducibility
import random
random.seed(493)# to print out all the outputs
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"# set display options
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
pd.set_option('display.max_colwidth', -1)

获取数据

让我们把数据读入数据帧。如果您想继续,您可以在这里下载清理过的数据集和停用词文件。这个数据集包含了特朗普从 2017 年 1 月 20 日上任那一刻到 2020 年 5 月 30 日的推文。

df = pd.read_csv('trump_20200530_clean.csv', parse_dates=True, index_col='datetime')

让我们快速看一下数据。

df.head()
df.info()

使用空间

现在让我们导入 spaCy 并开始自然语言处理。

# for natural language processing: named entity recognition
import spacy
import en_core_web_sm

我们将只使用 spaCy 的 ner 功能或命名实体识别,因此我们将禁用其余功能。这将节省我们大量的装货时间。

nlp = spacy.load('en_core_web_sm', disable=['tagger', 'parser', 'textcat'])

现在让我们将停用词文件的内容加载到变量stopswords中。请注意,我们将列表转换为集合,也是为了节省以后的处理时间。

with open('twitter-stopwords — TA — Less.txt') as f:
 contents = f.read().split(',')
stopwords = set(contents)

接下来,我们将导入 joblib 并定义一些函数来帮助并行处理。

在上面的代码中,函数preprocess_parallel并行执行另一个函数process_chunks来帮助提高速度。函数process_chunks遍历一系列文本——在我们的例子中是df数据框架的列'tweet'——并检查实体是否属于 NORP、PERSON、FAC、ORG、GPE、LOC、PRODUCT 或 EVENT。如果是,那么实体被附加到'preproc_pipe'并随后返回给它的调用者。 Prashanth Rao 有一篇关于让 spaCy 超快的非常好的文章。

[## 加速您的空间 NLP 管道

使用自定义管道和 joblib 显著加快 spaCy 中文本预处理的技巧和诀窍

towardsdatascience.com](/turbo-charge-your-spacy-nlp-pipeline-551435b664ad)

现在让我们调用函数的主驱动程序。

df['entities'] = preprocess_parallel(df['tweet'], chunksize=1000)

快速执行df.head()将显示我们之前添加的新列'entities',以保存在'tweet'列中找到的实体。

美化结果

在下面的代码中,我们制作了一个名为'entities'的列表,然后将其展*以便于处理。我们还将它转换成一个名为'entities_set'的集合。

entities = [entity for entity in df.entities if entity != []]
entities = [item for sublist in entities for item in sublist]entities_set = set(entities)

接下来,让我们统计实体的频率,并将其添加到元组列表entities_counts中。然后让我们将结果转换成数据帧df_counts

df_counts = pd.Series(entities).value_counts()[:20].to_frame().reset_index()
df_counts.columns=['entity', 'count']
df_counts

对于这一步,我们将重新初始化一个空列表entity_counts,并手动构建一个元组列表,该列表包含一组组合的实体及其频率或计数的总和。

在继续之前,让我们快速浏览一下。

最后,让我们将元组列表转换成数据帧。

df_ner = pd.DataFrame(entity_counts, columns=["entity", "count"]).sort_values('count', ascending=False).reset_index(drop=True)

就是这样!

我们已经成功地创建了特朗普总统自上任以来在推特上最常谈论的命名实体的排名。

感谢您的阅读!探索性数据分析使用了很多技术,我们在这篇文章中只探讨了其中的一些。我鼓励你坚持练习,并使用其他技术从数据中获得洞察力。

在下一篇**中,我们将继续我们的旅程,进入 Trump Twitter 存档,并使用 PyCaret* 进行一些 主题建模。*

如果你想了解更多关于我从懒鬼到数据科学家的旅程,请查看下面的文章:

* [## 从懒鬼到数据科学家

我的无学位数据科学之旅。

towardsdatascience.com](/from-slacker-to-data-scientist-b4f34aa10ea1)

敬请期待!

你可以在推特或 LinkedIn 上找到我。

1龚伟的主页。(2020 年 5 月 30 日)。为推文停字。https://sites.google.com/site/iamgongwei/home/sw

2走向数据科学。(2020 年 5 月 30 日)。给你的空间 NLP 管道增压。https://towards data science . com/turbo-charge-your-spacy-NLP-pipeline-551435 b 664 ad*

探索美国汽车数据集

原文:https://towardsdatascience.com/exploring-the-us-cars-dataset-dbcebf954e4a?source=collection_archive---------42-----------------------

美国汽车数据集的探索性数据分析

来源

美国汽车数据集包含来自北美汽车在线拍卖的零散数据。它包含了在美国销售的 28 个汽车品牌的信息。在本帖中,我们将对美国汽车数据集进行探索性数据分析。数据可以在这里找到。

我们开始吧!

首先,让我们导入熊猫库

import pandas as pd

接下来,让我们移除熊猫数据框的默认显示限制:

pd.set_option('display.max_columns', None)

现在,让我们将数据读入数据框:

df = pd.read_csv("USA_cars_datasets.csv")

让我们打印数据中的列列表:

print(list(df.columns))

我们还可以看看数据中的行数:

print("Number of rows: ", len(df))

接下来,让我们打印前五行数据:

print(df.head())

我们可以看到有几个分类列。让我们定义一个将数据框、列名和限制作为输入的函数。当被调用时,它打印分类值的字典以及它们出现的频率:

from collections import Counter
def return_counter(data_frame, column_name, limit):
  print(dict(Counter(data_frame[column_name]
  .values).most_common(limit)))

让我们将函数应用于“品牌”列,并将结果限制为五个最常见的值:

return_counter(df, 'brand', 5)

如我们所见,我们有 1235 辆福特,432 辆道奇,312 辆尼桑,297 辆雪佛兰和 42 辆通用汽车。

让我们将函数应用于“颜色”列:

return_counter(df, 'color', 5)

现在,让我们看看白色汽车的品牌:

df_d1 = df[df['color'] =='white']
print(set(df_d1['brand']))

我们还可以看看最常见的白色汽车品牌:

print(dict(Counter(df_d1['brand']).most_common(5)))

我们看到大多数白色汽车是福特、道奇和雪佛兰。

我们还可以看看销售白色汽车最常见的州:

print(dict(Counter(df_d1['state']).most_common(5)))

接下来,从像“持续时间”这样的数字列中生成汇总统计数据会很有用。让我们定义一个采用数据框、分类列和数字列的函数。每个类别的数字列的*均值和标准偏差存储在数据框中,并且数据框根据*均值以降序排序。如果您想要快速查看特定类别对于特定数字列是否具有更高或更低的*均值和/或标准偏差值,这将非常有用。

def return_statistics(data_frame, categorical_column, numerical_column):
    mean = []
    std = []
    field = []
    for i in set(list(data_frame[categorical_column].values)):
        new_data = data_frame[data_frame[categorical_column] == i]
        field.append(i)
        mean.append(new_data[numerical_column].mean())
        std.append(new_data[numerical_column].std())
    df = pd.DataFrame({'{}'.format(categorical_column): field, 'mean {}'.format(numerical_column): mean, 'std in {}'.format(numerical_column): std})
    df.sort_values('mean {}'.format(numerical_column), inplace = True, ascending = False)
    df.dropna(inplace = True)
    return df

让我们用分类列“品牌”和数字列“价格”来调用我们的函数:

stats = return_statistics(df, 'brand', 'price')
print(stats.head(15))

接下来,我们将使用箱线图来显示基于最小值、最大值、中值、第一个四分位数和第三个四分位数的数值分布。

与汇总统计函数类似,此函数采用数据框、分类列和数值列,并根据限制显示最常见类别的箱线图:

import matplotlib.pyplot as plt
def get_boxplot_of_categories(data_frame, categorical_column, numerical_column, limit):
    import seaborn as sns
    from collections import Counter
    keys = []
    for i in dict(Counter(df[categorical_column].values).most_common(limit)):
        keys.append(i)
    print(keys)
    df_new = df[df[categorical_column].isin(keys)]
    sns.set()
    sns.boxplot(x = df_new[categorical_column], y = df_new[numerical_column])
    plt.show()

让我们为 5 个最常见的“品牌”类别中的“价格”生成箱线图:

get_boxplot_of_categories(df, 'listed_in', 'duration', 5)

最后,让我们定义一个函数,它将数据框和数字列作为输入,并显示一个直方图:

def get_histogram(data_frame, numerical_column):
    df_new = data_frame
    df_new[numerical_column].hist(bins=100)
    plt.title('{} histogram'.format(numerical_column))
    plt.show()

让我们用数据框调用函数,并从“价格”生成一个直方图:

get_histogram(df, 'price')

我就讲到这里,但是请随意处理数据并自己编码。

结论

总之,在这篇文章中,我们介绍了几种分析美国汽车数据集的方法。这包括定义生成汇总统计数据的函数,比如*均值、标准差和分类值的计数。我们还定义了用箱线图和直方图可视化数据的函数。我希望这篇文章有用/有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

通过文本分析探索拉面的世界!

原文:https://towardsdatascience.com/exploring-the-world-of-ramen-through-text-analytics-1131280c4c6b?source=collection_archive---------33-----------------------

我对拉面评级网站上的评论做了一袋文字分析,以了解世界是如何消费方便面的,并决定自己尝试一种新的品种!

鸡肉拉面(@ The Flavor Bender ) 1

根据 Madator 网络【2】,拉面这个词已经和便宜的方便面联系在一起,主要是那些手头拮据的人(大学生)可能在一天中的奇数时间食用。这种看法已经演变成了全国各地正宗小酒馆供应的一道菜,并且是 Instagram 等社交媒体上帖子的热门主题!

我在❤探索新的食物——尤其是亚洲美食。大胆的口味和辣味击中了我的家。戴夫·张的《网飞秀》 丑陋的美味 促使我追寻我的好奇心,尝试来自世界各个角落的美食!我真的很喜欢吃拉面,我已经在不同的餐馆尝试过几种不同的拉面,乌龙面知道它对我的影响——我被它震撼了。

这篇文章讲述了我如何利用我有限的文本分析技能和好奇的味蕾来了解拉面的世界,并决定尝试一种新的品种!享受🍜

数据收集和准备

我发现了一个数据集,其中包含了一位铁杆拉面爱好者——拉面评分者对来自世界各地的 2500 多种方便面的评论。该数据集是“大列表”(评论)的导出,转换为 CSV 格式。

拉面在熊猫数据框中查看数据集

大多数栏目都是不言自明的,星级栏目是 1-5 级,前十名表明该拉面品种是否进入了本网站年度拉面排名前十名。

问题 1:全世界最受欢迎的拉面主题是什么?

这个数据集包含了大约 38 个不同国家的拉面信息。我想知道世界各地是如何看待即食拉面的,每个国家都流行什么口味。

我的方法是在包含拉面描述的列上应用一个单词包分析,通过将它分成单字母词、双字母词和三字母词( n 字母词)。

步骤 1:生成 n 元语法

我利用 Scikit-Learn 的 CountVectorizer API 来生成单词包。我定义了一个函数,它从“Variety”列中提取单词集,并计算每个 n-gram 的出现次数。

我在 Variety 列上应用了这个函数,用 NLTK 的默认停用词列表生成了 unigrams。

带有标准停用词的流行单字

最常见的单词是“面条”、“速食”和“风味”。因为这个分析的主要主题是方便面,我假设大多数品种将包含这些词。因此,这些也可以被认为是停用词。

带有修改的停用词的流行单字

我创建了一个包含这些拉面停用词的附加列表,并将其附加到 NLTK 的停用词中。我用修改过的停止词执行了函数,产生了左边的结果,看起来好多了!

步骤 2:连接 n 元语法

上面的函数调用“get_top_n_gram”,它在上一步中定义为返回一个单词包,并创建一个数据框,其中包含包含给定单词的单词、频率、星星的*均值和中值。

我使用这个函数来生成每个国家的 unigrams、bigrams 和 trigrams,并将这三者连接起来。我把串接的数据帧按频率降序排序,假设最上面的词就是主题。

来自泰国的品种——流行词汇

这些是我在泰国的拉面品种上运行这个函数的结果。最常见的词是“汤姆”,它本身作为一个主题没有意义。不过接下来是'冬阴汤',很好吃的泰式汤!在这种情况下,选择顶部的单词将会失败。

步骤 3:提取我们的主题

我定义了一个函数,如果一个词在一个更大的 n 元语法中出现的次数超过了一个定义的次数阈值,那么这个函数就会丢弃这个词。需要一个阈值来判断一个单词的计数( tom: 65 )是否主要是因为它是另一个 ngram 中的一个单词的一部分( tom yum: 54 )。

来自美国的品种——包含“鸡肉”的流行词汇

在这个例子中,最热门的词( : 92 )是最受欢迎的主题,并且它出现的次数明显多于相应的二元模型(辣鸡:14 )。保守的门槛仍然会保持''作为最受欢迎的主题!

现在我们对我们的功能感到满意,让我们看看世界各地最受欢迎的拉面主题是什么。这是每个国家排名前三的单词/主题!

第四步:视觉化!

Choropleth 地图是可视化地理数据的一种很好的方式,Plotly 是构建它们的一个方便的 python 库!我是跟着这篇中的文章入门的。

我利用 PyCountry 的 country API 的 get 方法为每一行添加了字母 ISO alpha 代码,这是通过 Plotly 生成 choropleth 地图所必需的。然而,这一步需要一些额外的数据清理。“USA”和“United States”对应于同一个国家,但是只有一个品种是“United States”的一部分,而所有其他品种都以“USA”作为他们的国家,所以我决定去掉“USA ”,保留“USA”。

在世界国家数据框架上运行 ISO 函数后的结果

我在函数中实现的 try-catch 逻辑捕获了额外的数据清理机会。为了从 PyCountry 获得 ISO 代码,我必须使用每个国家的官方名称。荷兰要改荷兰,韩国要改大韩民国,等等。沙捞越是马来西亚的一个州,所以为了这个可视化的目的,我把它去掉了。

一个描述世界如何吃拉面的互动情节剧

该地图本质上是交互式的。你可以在一个国家上空盘旋,了解他们是如何消费拉面的!如果你从移动设备上观看,倾斜屏幕将有助于导航地图。悬停包含关于国家的顶级主题、该主题的中值评级和国家的前三个主题的信息。

鸡肉是西方世界最受欢迎的风味。我是说,谁不喜欢🐔?大多数拉丁美洲国家的共同点是 S opa ,在西班牙语中是汤的意思。日本有乌龙面,我尝过这种品种,因为日本大多数拉面店里都有供应。韩国 Ramyun 应该是由农神公司生产的一种辛辣的拉面。我并不惊讶马萨拉是印度最受欢迎的主题。Maggi Masala 2 分钟方便面在印度各地被充满爱心的社会各阶层消费,几十年来它一直是流行文化的标志。这款产品在亚马逊和美国大多数南亚杂货店都有售,我强烈推荐你试试这款!

这张图也显示了流行食物影响邻国烹饪的模式。冬阴肉是一道泰国菜,是泰国最受欢迎的方便面,然而 T2 虾冬阴肉在邻国柬埔寨也是最受欢迎的。另一个例子是 Mi Goreng (印度尼西亚面条)从印度尼西亚到澳大利亚的旅行是他们第二受欢迎的主题。对我来说很有趣的是,食物是如何跨越国界的,并且是一个国家文化的一部分,不管它来自哪里。

在所有这些选择中,我最感兴趣的是探索一辆好的日本乌龙面、一辆印尼米高伦和一辆韩国 Ramyun 。然而,我想知道什么样的拉面是世界上评价最高的,也想尝尝。让我们来了解一下!

问题 2:评价最高的一种拉面是什么?

我扫描了所有的数据,并按照与上面相同的步骤(除了可视化部分)来生成主题以及关于每个主题的一些统计数据。我决定将丢弃单词的阈值降低到 10%,因为在扫描整个数据集时,包含其他 n 元语法中存在的单词的 n 元语法的排列明显更高。最后,为了得到一个现实的主题,我剔除了频率小于 10 的单词。

主题数据集中的随机样本

这是上一步中生成的主题示例。为了得到最高评级的主题,我按照中值评级降序排列了这些数据,然后选择了前 20 个词。

槟城白咖喱,蔬菜和 raoh 有一个完美的中值评级,但它们的品种数低于 20。印度尼西亚的 Mi Goreng 和日本的 Tonkotsu 的频率在 60 左右,评分分别在 4.4 和 4.2 左右!现在我有了一个受欢迎和高评价的拉面品种的想法,最后一个难题在于关于品牌的信息。选择什么品牌才是正确的?品牌的知名度也能保证质量吗?

问题三:什么拉面品牌最好?

为了回答这个问题,我使用了 Pandas GroupBy 方法和两个聚合(多样性计数和星级中位数),并按降序对结果进行排序。这些是可视化的结果

日清是迄今为止最受欢迎的拉面品牌,拥有超过 350 种拉面,*均评分略低于 4.0。营多面和妙条的*均评分分别为 4.0 qnd 4.2,略高于日清!然而,它们生产的品种是日清生产的三分之一。

拉面评估师有一个年度十大排行榜。我创建了一个新的数据框架,其中包括了前十名中挑选的品种。

拉面评分者的十大品种品牌

营多面在十大榜单中出现了 5 次,而日清只出现了一次。尽管品味是高度主观的,因人而异,但我觉得还是值得看看鉴赏家的推荐!因此,我会把它作为尝试一种新的拉面的一个稍微重要,但不是必不可少的先决条件,列入十大名单。

结论:挑选品种

做决定不是我的专长。我很高兴我可以利用数据对生活中最具挑战性的问题做出明智的决定,比如我下一步想吃什么拉面。我的决策标准是:

  1. 流行/有趣的主题
  2. 知名品牌
  3. 进入拉面评分者的前 10 名名单(可选)

我入围了几种风格的拉面:米果仁,拉姆云和槟城白咖喱。我决定从其中评价最高的一种开始,那就是槟城咖喱面。

槟城白咖喱品种拉面

我选择了马来西亚的‘麦考利的槟城白咖喱面‘。槟榔屿白咖喱是评价最高的品种,而 MyKuali 是一个评价很高的品牌,三次出现在十大榜单中。这很符合我的决策标准!

米果仁各式拉面

对于米粉来说,这个决定很简单,我选择了“营多面米粉巨型烤鸡”。营多面是一个受欢迎和高评级的品牌,烤鸡听起来很好吃,这个品种在 2012 年排名第二!不用动脑筋。

拉姆云品种拉面

拉姆恩是个艰难的选择。我在'帕尔多的芝士 Ramyun ' (1166)和'农神的辛 Ramyun Black '之间很矛盾。我想先试试 Nongshim,因为它是一个受欢迎的品牌,尽管它的评级略低,但它还是名列前十。

首先,我在亚马逊上点了槟城白咖喱面,我一定会在 YouTube 上发布一个反应视频!在练习我的分析技巧的同时,了解速食拉面的世界是如此有趣。这是我的 git 库的链接。

参考资料:

1迪尼。简易自制鸡肉拉面。(2019).风味弯曲机

2梅尔策,马修。12 种方便面口味你只能从亚洲运来,排名。(2019).Madator 网络

探索时间序列优步运动数据

原文:https://towardsdatascience.com/exploring-time-series-uber-movement-data-2a74f53178dc?source=collection_archive---------33-----------------------

伦敦经济学院图书馆在 Unsplash 上拍摄的照片。在 https://unsplash.com/photos/yzrdcOgEs6c有售

优步运动允许用户选择出发地和目的地区域,以查看司机在给定的一天或时间间隔内在全球多个城市从 A 到 B 的*均、下限和上限行驶时间。

在本文中,我将深入研究这些数据的样子及其一些特征,讨论其中的一些问题,并开始讨论如何从时间序列预测的角度来看待这些数据。

不幸的是,如果你想自己下载数据,优步只提供最长 3 个月的横截面数据。

幸运的是,在之前的一篇帖子中,我详细介绍了我是如何从他们网站上可下载的数据中创建时间序列数据的,所以如果您对从中生成时间序列数据感兴趣,可以查看一下。

好了,聊够了…让我们打开 csv 文件!

创建每个日期的时间旅行值

让我们看看伦敦市的数据集。

df.head()。由我来算。

我们的数据集范围从 2016 年 1 月 2 日到 2020 年 3 月 31 日,由数十万或数百万行组成(伦敦有 100 多万行),其中每个日期包含许多*均旅行时间(从出发地到目的地的每次旅行一个时间)。因此,我们必须首先*均所有的*均旅行时间。

# Plot average travel time per date
avg_times = df.groupby('Date')['MeanTravelTimeSeconds'].mean()

现在我们有了一个 Series 对象,它包含每个日期的一个值,本质上是将“date”列作为我们的索引。

我们开始策划吧。

以秒为单位的*均旅行时间(包括 2020 年)。由我来算。

我们马上看到了一个重复的模式,在第三季度末大幅下降,然后突然上升,然后在每年年底再次下降。

我们还可以看到 2020 年 2 月之后出现非常陡峭和非典型的下降。这就是新冠肺炎·疫情的效果。因此,出于本文的目的,我们将在我们的 avg_times 系列中添加一个“[:-90]”,忽略 2019 年之后的所有值。

# Excluding values after 2019 (ignoring COVID-19 impact)
avg_times = avg_times[:-90]

以秒为单位的*均行程时间(不包括 2020 年)。由我来算。

那更好(好像什么都没发生)。

我们来看几个统计数据。

avg_times.describe()

汇总统计数据。由我来算。

从伦敦最中心的区域到任何其他区域*均需要 1840 秒或 30 分钟。

我们可以看到,我们的最大值(2363 秒或 39 分钟)比最小值(957 秒或 16 分钟)离*均值的标准偏差更小,这意味着我们的数据是左偏的,或者较长的行程比较短的行程更集中。

为了证实这一点,我们绘制了一个直方图。

ax = sns.distplot(avg_times, bins=65)
ax.set(xlabel='Average Travel Times')

直方图和核密度估计器(KDE)。由我来算。

这可能是由于市中心交通拥挤和/或更多的人前往远离起点的区域,而不是短途旅行。

那么旅行的次数是多少?它们可能会对旅行时间的行为产生影响。

trip_count = df.groupby('Date')['MeanTravelTimeSeconds'].count()

目标区域的数量。由我来算。

这两幅图看起来非常相似。有了这个,我们就承认出行次数可以代表一个城市的整体交通状况。更多的汽车意味着更多的交通,更多的交通意味着更长的旅行时间。

这两者之间似乎存在线性关系:

sns.jointplot(x=daily_trip_count, y=avg_travel_times, kind='hex')

联合阴谋。由我来算。

需要注意的是,上面的散点图并不严格代表出行次数,而是代表在某一天有足够的出行次数让优步能够匿名化他们的数据的区域数量。然而,我们会不精确地互换使用目的地区域的数量和行程的数量。

将伦敦比作一张唱片

城市中目的地区域的地理分布面临着重大挑战。

为了让优步的司机到达远离市中心的目的地,他们必须通过中间的一些区域,为各自的道路交通做出贡献。

应对数据中这种限制的一个想法是进行某种地理空间加权,其中可以对行程持续时间和从目的地到出发地的距离之间的内在联系所产生的差异进行归一化。

一种有趣的方法可能是使用整个城市中出行的地理空间概率密度。

想象一个 2D 圆盘。如果你向圆盘表面投掷无限数量的飞镖,随机飞镖和圆盘中心之间的*均距离或预期距离是多少?

这个距离,类似于我们在一个随机的目的地区域和原点之间的距离,描述为

来源: Namit Chatuverdi

其中 E[Y]是从随机投掷的镖或点到圆盘中心的距离的期望值(或*均值)。

在他的文章中,Namit Chaturvedi 巧妙地解释了方程式背后的逻辑,但对我们来说重要的是,我们的旅行时间散点图的轮廓不是 100%准确,因为它没有捕捉旅行距离的影响。

因此,以某种方式将上述等式应用于我们的数据,以找出如何对不同的起点-目的地对进行加权,可能会使距离对我们的*均旅行时间的影响标准化。

但这是另一个话题了。

对我们来说,旅行时间是所有旅行持续时间的简单算术*均值,无论距离远*。

时间序列呢?

让我们远离可怕的二重积分,回到我们漂亮的图表上来。

再来看 30 日均线。

rolling_mean = avg_times.rolling(window=30).mean().plot()

行程时间的 30 天移动*均值(秒)。由我来算。

现在,我们的数据中包含的模式或季节性更加清晰可辨。

如果我们想要对数据建模并预测未来值,手头有哪些选择?

我们的数据有季节性,但年度季节性是我们唯一能观察到的吗?说到城市交通,假设人类也有每周一次的习惯似乎是合理的。并非每天都是一样的,但人们通常会为每周的流动性做计划。

让我们使用 statsmodels Python 包将时间序列分解为趋势、季节性和残差。

from statsmodels.tsa.seasonal import seasonal_decomposedecomposition = seasonal_decompose(avg_times, model='additive', period=365)
trend    = decomposition.trend
seasonal = decomposition.seasonal
residual = decomposition.resid

时间序列的趋势、季节性和残差分解。由我来算。

我们使用 365 天的时间来确定年度趋势和季节性,并使用加法模型,因为我们不相信方差会随着水*(或均值)而增加。这是的一个指示,表明我们的数据是*稳的,也就是说,不存在异方差,这由残差的分布图来证明。我们必须通过运行一个增强的 Dickey-Fuller 测试来检查*稳性。

预测优步旅行时间

预测模型将在以后的文章中讨论,但是我们需要注意的是不同的模型处理不同的时间序列。

有些模型即使有季节性项,也只能捕捉一个季节性(如 SARIMAX)。其他人甚至能够捕捉多个非整数季节性(如 TBATS)。当然,除了提及机器学习方法,如 LSTM(长短期记忆)神经网络或其变体。

下一次,我们将应用其中一个模型,解释为什么选择它而不是其他模型,并验证它在不同城市的表现。

时间序列预测中的指数*滑方法

原文:https://towardsdatascience.com/exponential-smoothing-approaches-to-forecasting-time-series-34e4957ed1a?source=collection_archive---------31-----------------------

对各种时间序列简单有效

Ocean NgUnsplash 上拍照

在这篇文章中,我们描述并解释了一些预测时间序列未来值的经典算法。这些算法被称为指数*滑器,已经被广泛使用了几十年。我们用例子传达直觉,一些例子在附录中增加了 Python 代码

指数*滑器在深度机器学习的现代继续保持吸引力。它们简单且易于实现。它们对于短期预测也惊人地有效。尤其是在快速变化的时间序列上。

指数*滑器也有助于增量学习,这通常是快速变化的时间序列的必备工具。这是为了使算法能够跟上变化的特征。例如趋势时间序列突然开始振荡。

基本概念

时间序列是一段时间内的一系列值。比如某个城市的日*均气温,某只股票的日收盘价,iPhone 11 的月销量。

我们的兴趣在于从时间序列的历史值预测其未来值。(在一个更广泛的公式中,我们不会在这里讨论,我们可能会包括额外的预测,甚至额外的时间序列。)

这个问题非常有趣。企业希望预测未来的销售。交易者希望尽可能预测股票或指数价格。我们都想预报天气。

接下来,一个关键概念。预测范围,一个正整数 h ,是我们想要预测的未来步骤数。因此,对于每日时间序列,预测范围 1 将预测第二天的值,预测范围 7 将预测未来 7 天的值。

我们从天真的预测者开始。虽然用起来太幼稚,但它可以作为一个有用的基线来与各种指数*滑器进行比较。

天真的预测者预测x(t+h)为 x ( t )。注意,不管 h 是什么,预测总是 x ( t )。

现在,我们的第一个指数*滑器。

简单指数*滑

让我们对时间序列建模如下:

x(t)=f(t)+噪音

这里 f ( t )是 t 的确定性函数,通过从合适的分布中采样,例如标准正态,在每个时间步长独立产生噪声。这个模型既丰富又直观。 f ( t )对时间序列的确定性分量进行建模。这可能相当复杂,包括多种趋势和多个季节,如果我们愿意的话。噪声模拟随机波动和其他未建模的影响。

下面是一些例子

*x*(*t*) = *t* + noise
*x*(*t*) = log(*t*) + noise
*x*(*t*) = *t*² + noise
*x*(*t*) = sin(*t*) + noise

SES 中的主要思想是从 x ( t ), x ( t -1),估计 f ( t ),然后用这个估计来预测 x 的未来值。

SES 对 f ( t )的估计是 x ( t )、 x ( t -1)、 x ( t -2)等的指数加权*均值。 x ( t )贡献最多, x ( t -1)第二多, x ( t -2)第三多,以此类推。该贡献以指数方式衰减,其速率由衰减参数 a 控制。

这可以递归地表示为

f(*t*)=*ax*(*t*)+(1-*a*)*f*(t-1)

^在那里提醒我们,这是对 f. 的估计,而不是 f 本身,它对我们是隐藏的。

现在的预测简直是x(*t*+*h*)=*f*(t。NF 是 SES 的一个特例,其中f^(t)=x(t)。

简单来说,SES 对于一步预测非常有效,即 h =1。其原因是 SES 不仅*滑噪声,而且它还局部地适合 f ( t ),即在时间 t 时,这在时间序列快速变化时很重要。NF 也适合局部 f ( t ),但是,它并不能*滑噪点。SES 对长期预测无效,即 h > 1。

简单指数*滑+趋势(TrES)

如前所述,SES 对长期预测无效。通过向 SES 添加趋势组件,我们可以改善这种情况。直觉很简单。如果在 x ( t )存在局部趋势,趋势组件可以估计它,并使用它来预测稍微更长的时间范围。(这类似于推理:如果你知道一个物体当前的位置和速度,你就可以预测它稍后会在哪里。)

这里有一个简单的例子。考虑 x ( t ) = t +噪声。比方说,我们算出 x ( t )在每个时间单位内增长 1(噪声除外)。知道了这一点,我们可以预测出 x 的值 h 时间单位之后将是其当前值加上 h

好了,让我们更彻底地描述一下算法。为此,让我们将时间序列重新表述为

x(t)=f(t-1)+df(t-1)+噪音

这里 f ( t ')是 t '的函数, df ( t ')是时间 t '的局部趋势。我们把它写成df(t’),因为它是 ft’的一阶导数的离散模拟。

这个模型相当于我们的第一个模型。我们只是将 f ( t )分解为f(t-1)+df(t-1)。

下面是一些重构的例子。

*x*(*t*) = (*t*-1) + 1 + noise
*x*(*t*) = (*t*-1)² + 2*t* + noise

这种保理有什么意义?我们可以分别估计两项 f ( t -1)和 df ( t -1)。这允许我们对可以精确估计 df ( t )的系列做出合理的长期预测。如在x(t)=t+噪声。在因式分解x(t)=(t-1)+1+噪声下我们看到 df ( t )等于 1。利用这一估计,我们可以对未来做出明智的预测。

我们如何估算 f ( t -1)和 df ( t -1)?都是通过指数*滑。 f ( t )的估计是 x ( t ), x ( t -1),…。 df ( t )的估计是x(t)-x(t-1)、x(t-1)-x(t-2)、 x ()

姑且把这些估算分别叫做 f ^( tdf ^( t )吧。现在的天气预报是

x(*t*+*h*)=*f*(t)+hdf^(t*)

注意 f ^( t )和 df ^( t )都是局部估计。因此算法适应于 f ( t )以及 df ( t )的变化。我们可以使用 ab 分别作为估计 fdf 的指数衰减参数。这给了我们更多的调整余地。(按照下面的例子,我们将讨论调整这些旋钮一点。)

例子

t           1   2    3    4    5     ...
x           1   2    3    4    5     ...
f^(a=½)     2   2.5  3.25 ... 
df^(b=½)    1   1    1    ...

因为我们已经将其初始化为 x (2),所以 f ^(2)为 2。 df ^(2)为 1 是因为我们已经将其初始化为x(2)——x(1)。我们看到,算法已经推导出序列在每个时间步长中增长 1 的趋势。

让我们在时间 t =4 时计算 x ^( t +1)。就是f(4)+*df*(4)= 3.25+1 = 4.25。接*实际值 x(5) = 5,尽管有点滞后。滞后是指数*滑的结果。我们可以通过提高最*的权重来减少延迟,但这可能会在其他地方产生成本。我们将在下一段讨论这方面的权衡。

接下来,我们来计算 x ^( t +3)在时间 t = 4。就是f^(4)+3 **df*^(4)= 3.25+3 * 1 = 6.25。显然,我们已经能够利用这一趋势来预测未来!x(7)是 7。在这种情况下,长期预测与一步预测一样准确!滞后没有增加。

*滑参数为我们提供了控制滞后的方法。在我们的例子中,增加 a 的值将减少滞后。另一方面,在我们示例的噪声版本中,过大的 a 值将无法消除噪声。所以,是的,滞后会减少,但预测质量不会。就好像我们在追逐最*的值,随着其中的噪声移动。

类似的推理适用于参数 b 。除了它适用于 df ,即斜率。在我们的例子中,斜率总是相同的,1。所以改变 b 不会有任何效果。然而,如果斜率大于 1 并且其中有乘性噪声,例如 df 是 5 *噪声,其中噪声的*均值为 1 并且围绕其波动,改变 b 可能会影响 df ^滞后 df 的程度与 df ^追赶 df 中的噪声的程度。

这里的方法是在输入数据的适当切片上自动调整这些参数。也就是说,机器学习它们以最小化合适的损失函数。这里就不赘述了。

简单指数*滑+趋势+季节性(TrSeES)

参见虽然对呈现局部线性趋势的序列有效,但对具有周期结构的序列并不总是有效。

考虑时间序列

1, 2, 3, 1, 2, 3, 1, 2, 3, … 

SeES 将预测 x ^(3)接* 4。现实中, x (3)是 1。这是一个很大的区别。如果我们知道时间序列每三个时间步重复一次,我们就可以用这个信息来改进预测。

我们如何改进 TrES?假设序列有单一的季节性,即单一的重复成分,我们知道它的顺序,即 k 。我们可以如下模拟这样的时间序列。

x(t)=tr(t)+s(t)+噪音

s(t)=s(t-k)

这里 s ( t )是一个重复的时间序列。 x ( t )是将 s ( t )加到另一个时间序列上得到的,我们称之为 tr ( t )。我们称之为 tr ( t )是因为我们认为它是建模 x ( t )的趋势分量。也就是说,现实中, tr ( t )建模的是从 x ( t )中去掉 s ( t )后剩下的东西。它还可能有其他重复成分。 tr ( t )只是比 x ( t )不太及时。当我们看到下面的算法时会变得很清楚,即使去掉一个季节性也是一种进步。

让我们看一个这样表达的例子。

*t*   1  2  3  4  5  6  7  8  9
*s*   **1  2  3**  1  2  3  1  2  3
*tr*  1  2  3  4  5  6  7  8  9
*x*   2  4  6  5  7  9  8  10 12

我们如何估算 tr ( t )和 s ( t )?首先,我们假设我们知道顺序 k 。一个合理的方法是获得一个新的时间序列yk(t)=x(t)-x(t-k),去掉季节性的影响。然后我们可以应用 TrES 来预测yk(*t*+*h*。然后我们将*x*(*t*+*h*-*k*)与*yk*(t+h)相加,这给我们一个合理的预测x^(t+h

让我们看看上面的例子是如何进行的。

t   1  2  3  4  5  6  7  8  9
x   2  4  6  5  7  9  8  10 12
y3  3  3  3  3  3  3

太好了,y3 很容易预测。其值始终为 3。消除季节性的影响帮助很大!TrES 会很快算出 y3 是常数。

我们来预测一下x(t+3 = 12)在 t =9。首先我们预测 yy3(12)是 3。然后我们把 x (9) = 12 加到这个预测上。我们得到 x ^(12) = 3+12 = 15。除非未来发生变化,否则这个预测是准确的。

只要 h 小于或等于 k 我们就可以这样做。(如果 h 大于 kt+h-k将大于 t ,即进入未来!)

*滑季节性

我们可以进一步改进。在从y^k(t+h)推导 x ^( t + h 时,我们可以添加它的*滑版本,而不是添加x(t+h-k)。用什么方法抚*?取x(t+h-k)、x(t+h-2k)、x(t+h-3k 的指数加权*均值

为什么我们认为*滑季节性可以进一步改善旅游?考虑季节性成分中含有乘性噪声的情况。即,

s ( t ) =噪声**s(t-k*)

其中,为了便于说明,假设该噪声是一个均值为 1、标准差大于 0 但远小于 1 的高斯噪声。这样的季节性模型是现实的。

在这种情况下,x(t+h-k),x(t+h-2k),x(t+h-3TrES 将解决我们之前遇到的附加噪声问题。但不是这种乘法噪声。使用从x(t-k)、x(t+h-2得到的x(t+h-k)的指数*滑估计值

Python 代码

我把它放在这里,这样人们可以看到一些实际的代码。也就是说,它有些部分是不完整的。也可能有 bug。所以,如果你想让它正常工作,就要准备做一些额外的工作。

时间序列发生器

import numpy as np
noise = np.random.normal
f = lambda t: <**some function of t**>
x = [f(t) + noise for t in range(n)]

通过适当地选择 f,我们可以生成各种时间序列。包括有趋势的,有周期的,两者都有。

接下来,我们展示各种指数*滑器的代码。作为所有这些语句的第一条语句,添加

x = [1,2,3,4,5,6,7]

或者,更好的方法是,使用时间序列生成器生成 x。

SES 算法

<**initialize x here**>
f = x[0]
y = {}
a = 0.5
for t in range(len(x)):
   xhat_tplus1 = f        # **forecast next value**
   f = a*x[t] + (1-a)*f

TrES 算法

<**initialize x here**>
f,df    = x[1], x[1]-x[0]
y       = {}
h, a, b = 3, 0.5, 0.5for t in range(2,len(x)):
   x_hat_tplush = f + h*df # **forecast h steps ahead**
   f  = a*x[t] + (1-a)*f
   df = b*(x[t]-x[t-1]) + (1-b)*df

TrSeES

这需要更多的工作来实现端到端。它也不能*滑季节性。

<**initialize x here**>
yk = [x[t] — x[t-k] for t in range(k,n)]<**Run TrES on yk**># Forecast x. forecast_y(t+h) uses the forecast model built earlier on yk using TrES.xhat_tplus_h = forecast_y(t+h) + x[t+h-k]

延伸阅读

  1. https://otexts.com/fpp2/第七章是关于指数*滑法。

导出和导入 JSON 数据

原文:https://towardsdatascience.com/exporting-and-importing-json-data-fc1753808349?source=collection_archive---------30-----------------------

这篇文章揭示了关于如何在 SQL Server 数据库中执行数据导出和导入的有价值的信息。

图片来自 Piqsels (CC0)

在前面的文章中,我们研究了 SQL 数据库设计的基本规则,为一个招聘服务创建了一个数据库模式图,并用关于雇员的测试数据填充了新创建的数据库。

Img.1 .招聘服务的数据库结构图

该数据库包含以下实体:

  • 雇员
  • 公司
  • 位置
  • 项目
  • 技能

这一次,让我们考虑通过导出和导入将数据从一个 SQL Server 数据库传输到另一个数据库的方法。当客户机数据库的管理系统的版本比数据源的版本旧时,这就很方便了。也就是说,当无法使用备份副本或只有一部分数据需要传输时,因为所有数据都太重了。

将数据从 SQL Server 导出到 JSON 表

首先,db forge Studio for SQL Server以及 dbForge Data Pump 中提供了数据导出功能。当使用外部源数据填充 SQL 数据库和在系统之间迁移数据时,数据泵是一个插件,总是很有帮助。

让我们首先考虑它在 SSMS 的应用。

首先,让我们执行数据导出。

为此,在 SSMS 中,右击你需要的数据库,在下拉菜单中选择 Data Pump\ Export Data…命令:

Img.2 .使用数据泵导出 SQL 数据

然后将出现“导出设置”窗口。在“导出格式”选项卡上,您可以选择不同的格式。在我们的例子中,我们选择 JSON 格式来传输数据并将其导入到另一个数据库中。然后,让我们按下“下一步”按钮:

Img.3 .设置“导出格式”选项卡

接下来,在“Source”选项卡上,您需要选择导出所需的表。在这种情况下,我们选择所有用户表,然后按“下一步”按钮:

Img.4 .设置“源”选项卡

接下来,在“数据格式”选项卡上,您需要在“列”选项卡上选择所需的列,并在“格式”选项卡上设置数据格式。在本例中,我们选择所有列,并保留“格式”的默认设置。然后,按下“下一步”按钮:

Img.5 .设置“数据格式”选项卡

在“输出设置”选项卡上,我们需要配置导出数据的输出参数。这里,我们保留默认设置,并单击“下一步”按钮:

Img.6 .“输出设置”选项卡

在“导出的行”选项卡上,您可以配置导出的行数,这取决于您是需要导出所有行还是只导出它们的某一部分。在这种情况下,我们保留默认设置,也就是说,我们将导出行。现在按下“下一步”按钮:

Img.7 .设置“导出的行”选项卡

接下来,在“错误处理”选项卡上,您可以指定导出期间运行时错误输出的设置。保留默认设置。请注意,为了以后使用,您可以通过单击左下角的“保存模板…”按钮将所有指定的设置保存为模板。现在,您应该按“导出”按钮开始数据导出:

Img.8 .设置“错误处理”选项卡

运行导出时,您可以在“导出”选项卡上查看数据提取过程。

完成后,您将看到“完成”选项卡,您可以通过按“完成”按钮关闭窗口,或者通过按“打开结果文件夹…”按钮立即转到包含生成文件的文件夹:

Img.9 .数据导出的结果

最后,您可以看到 JSON 文件中包含生成的 SQL 数据库数据的文件夹:

Img.10 .包含结果数据文件的文件夹

让我们打开 dbo_Employee 文件的内容:

img . 11 . dbo _ Employee 文件的内容

综上所述,我们将新数据库的数据导出到 JSON 格式的文件中。

请注意,在两种类型的数据库管理系统之间交换数据时,导出会很有用。

用 Excel 导出数据也很方便,可以为分析师提供一些数据进行研究。

将 JSON 数据导入 SQL Server 数据库

现在,让我们将结果数据复制到必要的服务器,并在那里恢复 JobEmpl2 数据库。

为此,我们需要使用以下脚本创建一个新的数据库 JobEmpl2,其模式与 JobEmpl 相同:

可以通过多种方式获得该脚本。例如,使用 SQL Server 的比较包工具。

右键单击它,并在下拉菜单中选择数据泵“导入数据…”命令:

Img.12 .数据泵中的数据导入命令

与导出类似,在“源文件”选项卡上,选择 JSON 格式和文件本身。然后按下“下一步”按钮:

Img.13 .设置“源文件”选项卡

在“Destination”选项卡上,选择 JobEmpl2 数据库的 dbo 模式中的现有 Employee 表,然后按“Next”:

Img.14 .设置“目的地”标签

接下来,在“选项”选项卡上,您可以设置编码并查看插入数据的外观。保留默认设置,然后按“下一步”键:

Img.15 .设置“选项”选项卡

在“数据格式”选项卡上,您可以配置插入数据的格式。这里,我们保留默认值,并按下“下一步”按钮:

Img.16 .设置“数据格式”选项卡

在“映射”选项卡上,您可以配置源和目标字段的映射。让我们让一切保持原样,然后按“下一步”按钮:

Img.17 .设置“映射”选项卡

接下来,在“模式”选项卡上,您可以设置数据导入模式。在我们的例子中,我们通过大容量插入来添加数据,而不删除现有数据。然后,按“下一步”:

Img.18 .设置“模式”选项卡

在“输出”选项卡上,您可以为要导入的数据配置目标位置。在这种情况下,选择将数据直接导入数据库,然后单击“下一步”:

Img.19 .设置“输出”选项卡

此后,在“错误处理”选项卡上,您可以在导入过程中配置运行时错误的输出。您也可以点击左下角的“保存模板…”按钮,将之前的设置保存为模板。我们保留默认设置,并按“导入”按钮开始导入:

Img.20 .设置“错误处理”标签

在导入过程中,在“导入”选项卡上,您可以跟踪执行进度。导入完成后,结果会显示在“完成”选项卡上。按“完成”按钮关闭窗口:

Img.21 .数据导入结果

查询目标数据库时,可以确保数据已成功导入到 Employee 表中:

Img.22 .将数据导入到员工表中

同样,您可以将剩余的文件导入到相应的表中。

您可以借助于 SSMS 的标准功能,通过右击所需的数据库并在下拉菜单中选择相应的命令来执行数据导出和导入:

Img.23 .使用标准 SSMS 工具进行数据导出和导入

结论

简而言之,数据导出和导入不仅允许在数据库之间移动数据,以方便的形式为后续处理提供数据,还允许将部分必要的数据导入所需的数据库。

在下一部分中,我们将研究如何在创建的数据库中进行对象和数据搜索。

原载于 2020 年 7 月 23 日【https://blog.devart.com】

图形神经网络的表达能力和 Weisfeiler-Lehman 检验

原文:https://towardsdatascience.com/expressive-power-of-graph-neural-networks-and-the-weisefeiler-lehman-test-b883db3c7c49?source=collection_archive---------4-----------------------

图形神经网络有多强大?

你有没有一种感觉,图形上的深度学习是一组有时有效的启发式方法,但没有人知道为什么?在这篇文章中,我将讨论图形同构问题,Weisfeiler-Lehman 启发式图形同构测试,以及如何使用它来分析图形神经网络的表达能力。

这是关于图形神经网络表达能力的三篇系列文章中的第一篇。在 第二部分 中,我讨论了如何脱离 Weisfeiler-Lehman 层次结构,在 第三部分 中,我提出了为什么重新审视整个图同构框架可能是个好主意。

传统的前馈网络(多层感知器)是众所周知的通用逼*器:它们能够以任何期望的精度逼*任何*滑函数。对于最*才出现的图形神经网络,其表示特性还不太为人所知。在实验中经常观察到,图形神经网络在一些数据集上表现出色,但同时在另一些数据集上表现令人失望。为了找到这种行为的根源,我们必须回答这个问题:图形神经网络有多强大?

挑战之一是应用中遇到的图是连续和离散结构的组合(分别是节点和边特征和连通性),因此这个问题可以以不同的方式提出。一个可能的公式是图形神经网络是否可以区分不同类型的图形结构。这是图论中的一个经典问题,称为图同构 问题,旨在确定两个图是否拓扑等价1。两个同构的图具有相同的连通性,不同之处仅在于它们的节点排列不同。

有点令人惊讶的是,图同构问题的确切复杂性类别是未知的。不知道在多项式时间内可解,也不知道NP-完全,有时会归结为一个特殊的“ GI 类2

魏斯费勒-雷曼检验。Boris WeisfeilerAndrey Lehman【3】在 1968 年的开创性论文中提出了一种高效的启发式算法,现在被称为 Weisfeiler-Lehman (WL)测试,最初被认为是图同构问题的多项式时间解决方案【4】。一年后发现一个反例;然而,从概率意义上来说,WL 检验似乎适用于几乎所有的图[5]。

在两个同构图上执行 Weisfeiler-Lehman 测试的例子。方括号表示多重集。该算法在颜色不变后停止,并产生一个输出(颜色直方图)。两个图的相等输出表明它们可能是同构的。

WL 测试基于迭代图重新着色6,从相同颜色的所有节点开始。在每一步中,该算法将节点及其邻域的颜色聚合起来表示为多重集[7],并将聚合的颜色多重集散列成独特的新颜色。算法在达到稳定的颜色时停止。如果在这一点上两个图的着色不同,那么这两个图就被认为是非同构的。然而,如果着色相同,那么这两个图可能(但不一定)是同构的。换句话说,WL 测试是图同构的一个必要但不充分的条件。存在着不同质的图,WL 测试产生相同的颜色,因此认为它们“可能是同构的”;据说在这种情况下测试会失败。下图显示了一个这样的例子:

WL 图同构判定失败的两个不同构的图,从它产生的相同着色可以明显看出。在化学中,这些图表代表了两种不同化合物的分子结构,十氢萘(左)和双环戊基(右)。图改编自[14]。

图同构网络。徐克玉路【9】和【10】(至少在两年前,托马斯·基普夫在他的博客文章中注意到)WL 测试与图消息传递神经网络有惊人的相似之处【8】,一种在图上进行类似卷积运算的方法。在消息传递层,每个节点的特征通过聚集邻居的特征来更新。聚合和更新操作的选择是至关重要的:只有多重集内射函数使它等价于 WL 算法。文献中使用的聚合器的一些流行选择,如最大值或*均值,实际上没有 WL 强大,并且不能区分非常简单的图形结构:

不能用 max 区分但可以用 mean 聚合器区分(第一和第二)和既不能用 max 也不能用 mean 区分(第一和第三)的图结构的例子。原因是以这种方式从黑色节点的邻居聚集的特征将是相同的。图改编自[9]。

徐提出了一种使消息传递神经网络等价于算法的聚集和更新函数,称之为图同构网络。这是标准消息传递神经网络所能达到的最强大的功能。但不仅仅是一个新的架构,主要的影响是在一个简单的环境中阐述了表现力的问题,这可能与图论中的一个经典问题有关。这个想法已经激发了多部后续作品。

魏斯费勒-雷曼层级。扩展徐和 Morris 结果的一个方向是使用更强大的图同构测试。由拉斯洛·巴拜提出的 k-WL 测试是 Weisfeiler-Lehman 算法的高阶扩展,它作用于 k 元组而不是单个节点。除了等价的 1-WL 和 2-WL 测试之外,( k +1)-WL 严格强于 k -WL,对于任何 k ≥2,即存在这样的图的例子,其中 k -WL 失败,( k +1)-WL 成功,但反之则不然。k——WL 因此是一个层次结构或日益强大的图同构测试,有时被称为 Weisfeiler-Lehman 层次结构[10]。

有可能设计出遵循 k -WL 测试的图形神经网络,从而比消息传递架构更强大。第一个这样的建筑, k -GNN,就是由莫里斯提出的。传统的消息传递神经网络和这种高阶 gnn 之间的关键区别在于,它们是非局部的,因为 k -WL 算法对k-节点元组进行操作。这对算法的实现及其计算和存储复杂性都有重要的影响: k -GNNs 需要𝒪( nᵏ 内存。作为降低复杂性的一种方式,Morris 设计了一个本地版本的 k -GNNs,它基于本地邻居的聚合,但是表达能力不如 k -WL。

有些不同的高阶图架构是由 Haggai Maron 提出的,2019 年 9 月我有幸参加了他在魏茨曼研究所的博士答辩。Maron 基于 k 阶张量[12]定义了一类不变图网络(IGN ),并证明了它们与 k 阶 T21-WL 一样强大。IGNs 是从k-WL【10】的不同变体中派生出来的,与 k -GNNs 相比,在复杂性方面更有优势。特别是,3-WL 等效 IGN“仅”具有二次复杂度,这可能是唯一实际有用的图形神经网络架构,严格来说比消息传递更强大,但与前者的线性复杂度仍相去甚远[16]。

从理论的角度来看,可证明强大的图形神经网络的工作提供了一个严格的数学框架,可以帮助解释和比较不同的算法。已经有多个后续工作使用来自图论和分布式局部算法的方法扩展了这些结果[14]。

然而,从实践的角度来看,这些新架构几乎没有显著的影响:例如,最新的基准测试[15]表明,最*证明强大的算法实际上不如旧技术。这在机器学习中并不罕见,理论和实践之间往往存在很大差距。一种解释可能是基准本身的缺陷。但更深刻的原因可能是,更好的表达能力不一定提供更好的概括(有时正好相反),而且,图同构模型可能无法正确捕捉特定应用程序中图相似性的实际概念——我将在下一篇文章中讨论这一点。可以肯定的是,这一系列的工作对于搭建通往其他学科的桥梁和带来之前没有在图形深度学习领域使用的方法是非常富有成效的[17]。

1即在两个图的节点之间存在保边双射。

2图同构因此可能是一个NP-中间复杂性类。对于一些特殊的图族(如树、*面图或最大度有界的图),存在多项式时间算法。

3 B. Weisfeiler,A. Lehman,将图简化为标准形式以及其中出现的代数(1968)。信息技术 2(9):12–16。英文翻译俄文原版,其中包含一个不寻常的西里尔符号形式的双关语(операция„ы),指的是三年前与同名的苏联大片。参见这篇博文中的一个流行论述。Lehman 有时也被拼写为“Leman”,然而,考虑到这个姓氏的日耳曼起源,我更喜欢更准确的前一个变体。

4 I .波诺马伦科,魏斯费勒·雷曼的原文。提供了这篇经典论文的历史背景。他指出这项工作的动机来自化学应用。

[5] L. Babai 等人随机图同构 (1980)。暹罗计算机杂志 9(3):628–635。

6weis feiler 和 Lehman 的原始论文实际上描述了 2-WL 变体,然而它等价于 1-WL,也称为颜色细化算法。作为历史记录,这样的算法以前在计算化学中是已知的,参见例如 H. L. Morgan。化学结构的独特机器描述的生成——化学文摘服务处(1965 年)开发的技术。化学博士。医生。5(2):107–113,这是在化学中广泛使用的摩根分子指纹的基础。

[7]多重集是一个集合,其中相同的元素可能出现多次,但元素的顺序无关紧要。

[8] J. Gilmer 等人,量子化学的神经信息传递 (2017)。继续。ICML。

[9] K. Xu et al. 图神经网络到底有多强大? (2019)。继续。ICLR。

[10]WL 检验存在几种变体,它们具有不同的计算和理论属性,术语也相当混乱:建议读者清楚地理解不同作者所说的“ k -WL”到底是什么意思。一些作者,例如 Sato 和 Maron,区分了 WL 和“民俗”WL (FWL)测试,这两种测试的主要区别在于颜色细化步骤。 k -FWL 测试等价于( k +1)-WL。Morris 使用的 set k -WL 算法是另一种变体,它具有更低的存储复杂度,但严格弱于 k -WL。

[11] C. Morris 等人 Weisfeiler 和 Leman go neural:高阶图神经网络 (2019)。继续。AAAI。

[12] H. Maron 等人不变和等变图网络 (2019)。继续。ICLR。

[13] H. Maron 等人可证明强大的图形神经网络 (2019)。继续。神经炎。参见作者的一篇博文。

[14] R. Sato,关于图形神经网络表达能力的调查 (2020)。arXiv: 2003.04078。提供了一个非常全面的审查不同的 WL 测试和等效的图形神经网络架构,以及链接到分布式计算算法。

[15] V. P. Dwivedi 等人标杆图神经网络 (2020)。arXiv: 2003.00982。

[16]更准确地说,消息传递的复杂性是边数的线性关系,而不是节点数的线性关系。在稀疏图中,这大致相同。在稠密图中,边的数量可以是𝒪( n 。出于这个原因,Maron 认为他的体系结构对密集图形是有用的。

[17]准确地说,WL 形式主义对机器学习界来说并不陌生。N. Shervashidze 和 K. M. Borgwardt 的开创性论文《图上的快速子树核》( 2009 年)。继续。据我所知,NIPS 是最*深度神经网络复兴之前第一个使用这种结构的,比本文讨论的工作早了*十年。

感谢迈赫迪·巴赫里、卢卡·贝利、乔治·布里萨斯、法布里奇奥·弗拉斯卡、费伦茨·胡萨尔、谢尔盖·伊万诺夫、伊曼纽·罗西和大卫·西尔弗帮助校对和编辑这篇文章,并感谢卡斯滕·博格瓦特指出了与 WL 内核的关系。承蒙 刘止庸 提供本帖的 中文翻译 。关于图形深度学习的其他文章,请参见我的 博客 关于走向数据科学, 订阅 我的帖子和 YouTube 频道 ,获取 中等会员 ,或者关注我的Twitter【

扩展命名实体识别器(NER ),用空格标记新实体

原文:https://towardsdatascience.com/extend-named-entity-recogniser-ner-to-label-new-entities-with-spacy-339ee5979044?source=collection_archive---------10-----------------------

单词的标签顺序-简洁明了

图 1:彩色编码的识别实体

这篇文章假设读者对从文本中提取实体有一些概念,并希望进一步了解新的自定义实体识别存在哪些先进的技术,以及如何使用它们。然而,如果你是第一次接触 NER 问题,那么请在这里阅读。

话虽如此,这篇文章的目的是描述使用来自 spaCy 的预训练自然语言处理(NLP)核心模型来学习识别新实体。来自 spacy 的现有核心 NLP 模型被训练以识别各种实体,如图 2 所示。

图 spaCy 核心模型识别的现有实体(来源)

尽管如此,用户可能想要构建自己的实体来解决问题需求。在这种情况下,先前存在的实体表现得不够充分,因此,需要训练 NLP 模型来完成这项工作。感谢 spaCy 的文档和预训练模型,这并不是很困难。

如果你不想进一步阅读,而是想学习如何使用它,那么请到这个 jupyter 笔记本 --) 它是独立的。无论如何,我也建议浏览一下。

数据预处理

像任何需要输入和输出来学习的监督学习算法一样,类似地,这里——输入是文本,输出根据 【罗比】 进行编码,如图 3 所示。虽然存在不同的方案,但是, Ratinov 和 Roth 表明最小 Begin,in,Out ( IOB )方案比明确标记边界标记的罗比方案更难学习。IOB 编码的一个例子是由 spaCy 提供的,我发现它与提供的参数一致。因此,从这里开始,任何注释方案的提及都将是罗比。

图 3: 罗比方案

下图显示了罗比编码实体的一个简短示例。

图 4:用 BILOU 方案编码的实体

用罗比方案编码有三种可能的方法。方法之一是创建一个 spaCy doc 格式的文本字符串,并将从 doc 中提取的令牌保存在一个文本文件中,用换行符隔开。然后根据罗比方案标记每个令牌。人们可以创建自己的令牌并标记它,但可能会降低性能——稍后将详细介绍。以下是如何标记您的数据,供以后在 NER 培训中使用。

上面的片段使生活更容易注释,但这不能直接输入到学习的空间模型中。尽管如此,spaCy 提供的另一个模块 GoldParse 解析模型接受的保存格式。使用下面的代码片段从保存的文件中读取数据,并将其解析成模型可以接受的形式。

另一种方式是使用每个实体/标签的偏移索引,即实体的开始和结束(即实体的开始、内部和最后部分组合在一起)的索引与标签一起提供,例如:

第三个类似于第一个,除了,这里我们可以修复我们自己的令牌并标记它们,而不是用 NLP 模型生成令牌然后标记它们。虽然这也可以工作,但是,在我的实验中,我发现这大大降低了性能。然而,你可以这样做:

培养

在对数据进行预处理并为训练做好准备后,我们需要在模型 NER 管道中进一步添加新实体的词汇表。核心空间模型有三条流水线:标记器解析器NER 。此外,我们需要禁用标记器和解析器管道,因为我们将只训练 NER 管道,尽管可以同时训练所有其他管道。点击了解更多

在这里,为了训练,dropout 被指定为 0.0-故意过度拟合模型,并表明它可以学习识别所有的新实体。

推论

来自训练模型的结果:

spaCy 还提供了一种生成彩色编码的实体(如图 1 所示)的方法,可以使用以下代码片段在网络浏览器或笔记本上查看:

注意事项

这里提供的训练新实体的过程可能看起来有点简单,但是,它有一个警告。在训练时,新训练的模型可能会忘记识别旧实体,因此,强烈建议将一些文本与来自先前训练的实体的实体混合,除非旧实体对于问题的解决方案不是必需的。其次,学习更多具体的 T21 实体可能比学习一个一般化的实体更好。

结论

我们看到,开始学习新的实体并不难,但是需要尝试不同的注释技术,并选择最适合给定问题的方法。

补充说明

  • 这篇文章是 spaCy 在这里提供的例子的进一步扩展。
  • 在这个 jupyter 笔记本中可以访问整个代码块。自述文件还包含如何安装空间库以及在安装和加载预训练模型期间调试错误问题。
  • 阅读由 Akbik 等人撰写的这篇论文,它应该有助于理解序列标记背后的算法,即多个单词实体。

扩展的故事可视化

原文:https://towardsdatascience.com/extended-story-visualization-f320bcad4c16?source=collection_archive---------54-----------------------

从非结构化文本生成视频的关键帧序列方法。

直到今天,视频生成中的许多方法主要关注运动一致性,而不是所生成视频的长期上下文。换句话说,模型被训练以提高每一帧相对于先前帧的*滑度。

视频生成示例。C. Vondrick,H. Pirsiavash,A. Torralba,NIPS 2016

虽然这已经产生了良好的结果,但如果我们预见到机器会创造出更多考虑到上下文的相关视觉内容,这将成为一项重要的任务。或者,可以将该任务分为两个步骤,首先创建能够生成特定初始目标帧的模型,以便以可视方式讲述一个故事,然后使用一个聚焦于运动的模块,该模块可以在一个关键帧接一个关键帧的插值中说明故事的每一部分。

因为我们都爱新内容😍!

这种关键帧式的生成是由【1】提出的一个比较新的任务,名称为故事可视化。其中任务被视为序列条件生成问题,使用故事嵌入作为生成器的隐藏状态的先验,并为故事中给出的每个单独的句子创建新的图像。这种方法显示了显著的良好结果,其中它实现了考虑给定书面故事的字符和背景分布的上下文感知生成,然而,它展示了每个生成的图像与给定句子配对的局限性。

星球大战的混搭

因此,在长期视频生成的目标中,我们认为提出该方法的扩展是相关的,在该方法中,模型将接收非结构化文本条目,然后能够选择相关特征来生成说明故事的最佳数量的图像。

模型概述

段落到图像序列模型(P2iSeq)。

如上图所示,与 StoryGAN 相似,该模型包含一个具有两个鉴别器(用于局部一致性的图像鉴别器和用于全局一致性的故事鉴别器)的顺序生成对抗网络(GAN)。对于生成,它接收来自 DistilBERT 预训练编码器的编码故事作为第一隐藏向量( h_0 ),以及由从标准正态分布中采样的随机向量和来自提取摘要器选择的句子的嵌入合成的一组堆叠向量。在训练时,生成器在两个独立的循环中更新,第一个考虑图像鉴别器的输出,第二个考虑关于故事鉴别器的输出。

在所提出的架构的情况下,关键贡献依赖于选择性模块的实现,该模块能够选择故事的最相关特征,以避免图像生成中的重复,并保持整个故事的上下文,以及能够处理来自生成器的可变长度故事和固定长度地面真相的网络。

故事蒸馏编码器

对于故事编码器模块,我们考虑使用 Google 的 BERT。BERT 是在维基百科语料库上预先训练的一堆变形金刚。它有两种尺寸,BERT base 和 BERT large。基本模型有 12 个变压器层,大型模型有 24 个。然而,BERT 模型太大,并且需要太多的训练和推理资源。经过深思熟虑,我们选择在我们的故事编码器中使用 DistilBERT。DistilBERT 是 BERT 的缩小版。通过使用 DistilBERT,我们将 BERT 模型的大小减少了 40%,同时保留了 97%的语言理解能力,并且速度提高了 60%。这是通过在预培训阶段利用知识提炼来实现的。知识提炼是一种压缩技术,在这种技术中,一个紧凑的模型,即学生,被训练来再现一个更大的模型,即教师或模型集合的行为。

我们首先采用预训练的 DistilBERT 模型,并在 Pororo-SV 数据集的文本上训练(微调)它。我们这样做是为了改进为数据集中的句子生成的编码(即它知道 Pororo 是一个名字)。接下来,我们使用这个模型对数据集中的故事进行编码。然后,文本编码被传递给递归生成器。我们还添加了一个线性层,将来自 DistilBERT 的 768 维向量嵌入映射到一个 228 维向量,分别对应于均值和方差的两个 124 维向量。此外,嵌入内容被堆叠到一个独热编码向量中,该向量表示故事中出现的角色,以帮助模型在生成过程中识别它们。

摘录摘要

这种摘要方法受到了【3】的启发,它利用句子的相似性,删除那些信息已经由文本中的其他部分表示的句子。该过程始于对人称代词的神经共指解析,其中每次找到指代时,模型用其对应的名词代词替换该指代。为了解决这个解析问题,使用基于【23】的预训练神经模型,然后将解析的句子输入到前述的 DistilBERT 编码器,以返回各自的嵌入。然后对解析的嵌入进行聚类,汇总器输出更接*每个聚类质心的嵌入,生成的聚类的比例是在实验中调整的超参数。

共指权重可视化。(*图片取自 HuggingFace 公司演示。)

培养

为了在端到端管道中训练生成器和两个鉴别器,我们使用两个独立的循环,第一个循环允许生成的图像和文本输入之间的局部一致性,第二个循环用于全局一致性,其中在计算损失时,它考虑了符合故事和书面故事本身的生成图像集。总体优化目标描述如下:

总最小最大损失函数

其中 θ 、ϕ_I 和ϕ_S 分别是发生器、图像鉴别器和故事鉴别器网络的参数。

图像鉴别器

本质上,对于与图像损失相对应的更新,我们使用二进制交叉熵损失,该损失总结了鉴别器相对于相应故事上生成的和地面真实图像的输出。为了允许在鉴别器中同时评估图像分布及其与输入故事句子的相关性,它将卷积层的编码原始图像输出与句子和故事嵌入连接起来,以确定它是否来自生成器。

图像损失函数

故事鉴别器

类似于图像鉴别器,计算的故事损失也利用来自故事鉴别器输出的二进制交叉熵损失,但是不是单独考虑每个图像-句子嵌入对,而是堆叠和*均每个与故事相关的向量组,然后馈送到鉴别器中。

故事损失函数

由于地面实况和生成的图像故事的长度不一定相同的事实,该过程实施起来特别具有挑战性。该鉴别器的主要思想是评估故事嵌入的*均信息在基本事实和生成的样本之间保持相同,即使它们具有不同的长度。

对于优化目标的最后一项,我们利用故事嵌入分布和正态标准分布之间的 Kulback-Liebler 散度惩罚来避免图像生成过程中的模式崩溃问题。

惩罚 KL 散度损失函数

实验

固定长度生成

在我们的第一个实验中,我们实现了一个 DistilBERT story 编码器,以验证它是否能为生成器提供足够的上下文,从而使输出图像有意义。我们注意到,随着训练的进行,生成的图像变得更加清晰,更有意义。在大多数生成的序列中,我们看到 DistilBERT 嵌入传递了足够的上下文信息,以准确识别输入故事中出现的角色以及它们相对于彼此和场景中其他对象的确切位置。下面描述了一个这样的序列,其中模型在它们的正确位置生成所有字符,但是它不能检测到床应该在生成的分布中。

P2iSeq 生成了与地面实况对应的上下文分布相匹配的视觉故事。

此外,场景的颜色分布以及背景环境(室外/室内)通常由模型很好地说明,如下例所示。

汇总生成

与 StoryGAN 基线相比,一旦我们在固定长度图像生成实验中取得了相当好的结果,我们就继续在提取文本摘要器模块提出的可变长度方法中设置实验管道。这给优化问题增加了更高水*的复杂性,GAN 训练变得更加不稳定,并使鉴别器的工作更容易,因为生成器更难创建用较少数量的图像覆盖完整故事信息的插值图像分布。

带有句子选择的摘要图像生成示例。

如上图所示,该模型能够根据背景(即,在第一幅图像中,即使所选的句子中没有一个提到雪的背景)和故事人物选择来识别潜在的分布;因为总结者选择了描述故事中最相关的特征,但是图像分辨率在实现这个目标时受到了损害。

结论

StoryGAN 的方法记录在1中,具有解决故事可视化问题的可靠框架,能够从给定的书面故事中识别关键特征。虽然提取摘要器提取相关句子以视觉方式讲述故事,但它仍然无法达到可靠的图像质量。这种方法能够学习 Pororo 数据集的底层上下文分布,但是需要额外的信息来导出位于完整图像序列的每一帧之间的图像空间。在整个实验中,相对于故事鉴别器,生成器表现为较慢的学习者,因为在摘要过程中,它需要推断图像到图像的分布,同时内插或试图创建在较少数量的图像中显示相同数量的信息的图像。

在训练过程中要调整的另一个复杂参数是提取模块的总结句子的比率。因此,我们认为向句子选择过程添加软放松将是一种有趣的方式,有助于模型在训练时识别要生成的正确句子量,因为它会在为给定故事生成不正确数量的图像时反向传播错误。

欲了解更多型号详情,请查看完整的附录

相关著作

其他几个与故事可视化相关的任务是从预先收集的训练集中检索故事图像,而不是生成图像[15],这是一种用于卡通生成的“剪切和粘贴”技术[8]。故事可视化的相反任务是视觉讲故事,其中输出是描述图像输入序列的段落。对于视觉讲故事任务,使用文本生成模型或强化学习[11,14,10]。

1沈,刘,程,吴,卡尔逊,高,李,甘。用于故事可视化的顺序条件 GAN。CVPR,2019。
【2】米尔扎 b 徐 d 沃德-法利 s 奥泽尔 a y 本吉奥 I 古德菲勒 j 普热-阿巴迪。生成性对抗网络。NIPS,2014。
【3】j .肖蒙德 t .沃尔夫诉桑,l .出道。蒸馏伯特,伯特的蒸馏版本:更小,更快,更便宜,更轻。NIPS,2019。
4 S .蔡 b .张 k .金,m .许良英。PororoQA:用于故事理解的卡通视频系列数据集。NIPS,2016。
[5] X .严 l .洛格斯瓦兰 b .席勒 h .李 s .里德 z .阿卡塔。生成对立文本到图像合成。ICML,2016。
6d·米勒。利用 BERT 在课堂上摘录文本摘要。CoRR,2019。
[7]蔡洪祥、白振聪、戴耀文、唐振光。人类动作序列的深度视频生成、预测和完成。arXiv 预印本 arXiv:1711.08682,2018
[8] T. Gupta,D. Schwenk,a .法尔哈迪,D. Hoiem,A. Kembhavi。想象一下!从剧本到作品到视频。ECCV,2018。
[9]何、莱赫曼、马里诺、莫里和西加尔。使用整体属性控制的概率视频生成。arXiv 预印本 arXiv:1803.08085,2018。
[10]黄,甘,切利克·伊尔马兹,吴,王,何。等级结构强化。主题连贯的视觉故事生成学习。arXiv 预印本 arXiv:1805.08191,2018
【11】t .-h . k .黄,f .费拉罗,N. Mostafazadeh,I .米斯拉,a .阿格拉瓦尔,j .德夫林,r .吉希克,x .何,p .柯利,d .巴特拉,等《视觉叙事》。在 NAACL,2016。
[12]p . Isola,J.-Y. Zhu,T. Zhou 和 A. A. Efros。基于条件对抗网络的图像到图像翻译。CVPR,2017。
[13]y . Li,M. R. Min,D. Shen,D. Carlson 和 L. Carin。从文本生成视频。AAAI,2018。
[14] X .梁,z .胡,h .张,c .甘,和 E. P .邢。视觉段落生成的过渡 gan。arXiv 预印本 arXiv:1703.07022,2017。
[15]拉维、王、、西加尔、和卡帕迪亚。给我看一个故事:走向连贯的神经故事插图。在 2018 年的 CVPR。
[16]s . Tulyakov、m-y Liu、X. Yang 和 J. Kautz。MoCoGAN:分解视频生成的运动和内容。CVPR,2018。
[17]c . von drick、H. Pirsiavash 和 A. Torralba。用场景动态生成视频。在 NIPS,2016。
[18]x . Yan、J. Yang、K. Sohn 和 H. Lee。Attribute2image:从视觉属性生成条件图像。2016 年在 ECCV。
[19]j .-y . Zhu、T. Park、P. Isola 和 A. A. Efros。使用循环一致对抗网络的不成对图像到图像翻译。ICCV,2017。
[20]s . Sharma、D. Suhubdy、V. Michalski、S. E. Kahou 和 Y. Bengio。使用对话改进文本到图像的生成。arXiv 预印本 arXiv:1802.08216,2018。
[21]c . von drick、H. Pirsiavash 和 A. Torralba。用场景动态生成视频。在 NIPS,2016。
【22】d·米勒。利用 BERT 在课堂上摘录文本摘要。arXiv:1906.04165。
[23]K·克拉克·c·曼宁。通过学习实体级分布式表示提高共指消解。在 ACL 2016 中。

扩展目标编码

原文:https://towardsdatascience.com/extending-target-encoding-443aa9414cae?source=collection_archive---------27-----------------------

入门

当分类变量具有层次结构时,利用目标编码

毛罗·吉利Unsplash 上拍摄的照片

在这个千年之初,当我的头发黑了很多的时候,我写了一篇名字相当长的小文章,题为“ 分类和预测问题 中高基数分类属性的预处理方案”。这是一篇直截了当的文章,我决定写这篇文章,因为实际需要一种方法来处理难以插入机器学习(ML)模型的数据类型。当时,我正在研究 ML 模型,以检测欺诈性的电子商务交易。因此,我处理的是非常“稀疏”的分类变量,比如邮政编码、IP 地址或 SKU。我找不到一种简单的方法来“预处理”这样的变量,除了传统的一键编码,它不能很好地适应处理数百甚至数千个唯一值的情况。当时流行的一种决策树方法,R. Quinlan 的 C5.0 算法,提供了将单个值集合组合在一起的能力,作为树生成过程的一部分。然而,C5.0 是一种专有算法,因此没有公开用于提出他们称为“离散值子集”的方法。

因此,我想出了自己的非常实用的方法。给定变量的值,我用目标的期望值替换了原始的分类值。这是一种奇特的说法,对于二进制分类问题,我使用了当输入变量 X 取值, Xi 时,在训练数据中观察到的真实目标 Y 的比例。然而,该方法也可以很好地扩展到回归问题和多类分类问题。只需将输入替换为当 X =Xi 时目标的*均值即可,对于回归模型,或者使用 N-1 概率编码用于 N 类分类问题。就是这样,或者说几乎是这样,你的棘手的分类变量很容易变成一个更加柔和、信息量更大的连续变量。

让事情变得复杂的是,在处理基数非常高的输入变量时,许多值可能只有相对较小的样本量。因此,简单地相信目标的统计可能意味着麻烦(即过拟合麻烦)。为此,我查阅了一些文献,并采用了一种*滑方法,即将目标的估计值与目标的先验概率(或基线)混合起来。混合由取决于样本大小的参数控制。样本越大,估计值越倾向于给定的目标值×= Xi;样本越小,估计值就越倾向于目标的总体基线。

混合公式:作者图片

上面的公式描述了一种实现“混合”的方式,其中 Ni 是针对 X =Xi,的样本大小,并且λ函数是样本大小的某个单调递增函数。

这篇文章发表在第二份出版物上,ACM SIGKDD 探索时事通讯,这让我非常满意。尽管如此,在那之后,除了作者,似乎没有人注意到它(同行评议文章长尾的命运)。但是随着时间的推移,数据科学在过去的 5 年里达到了第三波兴趣,我注意到一些人向我咨询关于这篇文章的问题。然后,感谢谷歌学术,我意识到突然之间,这篇文章被其他作者在 ML 文学中引用了——当然,不是大量的引用。尽管如此,在它出版* 20 年后,还是有一些人在读它!

每年的引用量。作者截图,谷歌学术提供数据

再深入一点,我发现人们已经在 Python 包中实现了该算法,甚至 H20 似乎也支持这种类型的转换。人们甚至给它起了一个名字,实际上是几个名字,比如"目标编码"或者"影响编码"——这听起来肯定比"一个针对…的预处理方案要好。”。

无论如何,我很高兴我写的东西最终对一些人有所帮助。在此期间,我自己也一直在各种用例中使用这个方法,并分享给我的同行和同事。我还回顾了引用我 2001 年文章的一些工作,以了解在什么背景下引用了先前的工作,发现:

  • Yandex 开发的名为 CATBOOST 的开源 ML 算法利用目标统计来表示分类变量,但提供了一种*滑和避免过度拟合的替代方法。
  • 所提出的目标依赖编码被许多作者认为是处理高基数分类变量的基本方法,包括在库恩和约翰逊最*出版的题为“ 特征工程和选择 的书中
  • 各种应用数据科学论文(在社交媒体电商信用评分等。)参考这篇文章,因为这是他们选择的处理分类变量的方法。

虽然我很惊讶地发现了这么多关于使用目标相关编码的参考资料,但我注意到我能够阅读的论文中,无论是各种开源实现,似乎都没有利用论文中提出的一个重要建议:对具有隐式层次结构的分类变量的应用。这是描述简单事物的另一个有趣的名字,即高基数分类变量有一种自然的方式以逻辑方式将值“分组”。在 ML 应用中有许多这种变量的例子:

  • 邮政编码:当然,在美国,邮政编码不是随机分配给各个地区的。类似的邮政编码通常覆盖邻*或附*的地区。因此,如果我们考虑所有的邮政编码都以相同的 4 位数字开始(ZIP4),我们将把相邻的编码组合在一起,我们也可以使用 ZIP3。
  • IP 地址:虽然有潜在的 4,294,967,296 个不同的 IP 地址(由于保留块的原因,实际数量要小一些),但是它们被设计成一个内置的层次结构:ZZZ.YYY.XXX.NNN,通常它们被保留在连续的块中。因此,我们也可以利用他们的自然分组结构。
  • 行业代码:NAICS 系统为业务类型提供了非常详细的 6 位分类方案,这在各种类型的 ML 应用中非常有用。虽然唯一代码的数量巨大,但 NAICS 代码也是分等级的。NAICS5、NAICS4 直到 NAICS2 代表越来越广泛的业务类别(例如,NAICS2 = 51 表示出版商,而 22 表示公用事业)。

还有许多其他分类变量的例子,它们可以很容易地“累积”到更低的粒度级别,并在模型中使用。然而,这里的要点不是简单地通过使用层次结构“降低”唯一值的数量来减少基数;使用目标编码变得更加有趣…

分层目标编码方案。作者图片

前面我提到了“混合”公式,它控制着“值统计量”(即当 X =Xi 时的目标统计量)和目标的先验概率之间的权重。我们使用目标的无条件先验概率,只是因为我们假设当P(Y |X= Xi)因样本量小而不可靠时,没有更好的替代方案。然而,当我们有一个可以利用的层次结构时,我们可以查看“父组”的目标统计数据因此,如果邮政编码为 94089 的样本量太小,我们可以将邮政编码为 9409x 的所有记录的目标统计数据考虑在内,这将有望提供更可靠的估计,如果没有,那么考虑 940xx 怎么样?目标编码方法的这种分层版本提供了几个优点:

  1. 可变的、数据驱动的粒度:回到邮政编码案例,我们可以观察到我们数据集中的一些邮政编码有大量的数据,而其他的则很少。人们可能会考虑 ZIP4 或甚至 ZIP3 聚合来处理许多稀疏的 ZIP5 代码;然而,对于那些人口高度密集的邮政编码来说,这会造成不必要的信息模糊。使用建议的方法,聚合级别实际上是可变的-高频值将使用特定于其值的目标统计数据,而其他值将与其他相关(按层次)代码分组,从而使用更广泛的组统计数据。
  2. 更高的区分度:根据其标准公式,目标编码可能会产生一个连续变量(实际上是一个离散化的连续变量),对于该变量,相对大量的情况被映射到目标的先验概率,这是一个“中性”值。对于数值分布高度偏斜或长尾的分类变量来说尤其如此。这是因为低频值的目标估计值将向同一个数字(即目标的先验概率)加权。然而,当我们有一个可用于分类变量的层次结构时,使用这种变化,我们将最终得到一个更加分布式的表示,因为每个稀疏值将与一个潜在不同的目标估计值混合。

在快速发展的数据科学世界中,极其复杂和强大的新算法吞噬着大量的计算能力,这似乎是主导趋势,发明和创造性特征工程的艺术和科学似乎越来越不相关。我经常遇到在线材料或 ML 模型,我看到这些模型是由热情但初级的数据科学家构建的,他们花最少的努力来创建“更好的预测器”——算法会找出答案,这是普遍的想法。不要担心为你的模型创建复杂的、领域驱动的预测器——将原始数据交给算法,理想的内部表示将通过学习来创建。事实上,深度学习已经表明,当输入数据具有时空结构时,这是非常正确的——神经网络模型确实创建了非常“深度”的空间特征和抽象。但不幸的是,并不是所有的数据都是由图像、声音、视频组成的。或者,并不总是如此,我们有无数的数据点可以用来训练这些类型的模型。因此,在许多情况下,我仍然相信一个模型的性能可以很大程度上依赖于它的创造者在从原始数据中制造“好的预测器”方面的精明。但是,我以前被证明是错的。

因此,最后,感谢所有发现我 2001 年长篇论文的人,不要忘记查看第 4 节,其中解释了目标编码的层次版本——在某些用例中,绝对值得。

扩展 R 中的基本 SIR 模型

原文:https://towardsdatascience.com/extending-the-basic-sir-model-b6b32b833d76?source=collection_archive---------10-----------------------

人口更替、疫苗接种和免疫力下降的原因

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

C 房室模型是一种建模方法,将人群分为不同的“房室”,代表他们的疾病状态和其他可能的特征。这里,数学方程用于模拟不同隔间之间的转换。

SIR 模型

SIR 模型构成了传染病建模的基础。这是一个分室模型,其中个体属于三个分室中的一个:

  • 易感者
  • 已感染(一)
  • 恢复(R)

这是一个基于人口的模型,在这个意义上,每个隔间都模拟了该隔间中*均个体的行为。当然,这是对现实生活场景的过度简化,但实际上有可能在此基础上构建更复杂的模型。

SIR 模型的假设是什么?

  • 同质群体:同一舱室中的个体受到相同的危害
  • 混合良好的人群:所有易感人群都有相同的感染风险
  • 永久免疫:从疾病中康复的个体是永久免疫的

最后一个假设导致观察到 SIR 模型适用于在模拟期间种群不变且免疫稳定的情况。

这些假设为我们提供了以下一组微分方程:

其中 S、I 和 R 分别代表每个隔室中易感、感染和康复个体的数量,N=S+I+R

γ是回收率。β是感染率,即单位时间内继发感染的*均数量。

基本再现 Number(R₀)

基本再生数是在完全易感人群中由单一感染病例引起的二次感染的*均数。

对于 SIR 模型,它可以计算为:

有效再现数量

如果易感人群随时间变化,最好使用有效再生数。它是在流行病的给定时间点从感染病例产生的继发性病例的*均数量。

感染之力

它是个体在单位时间内感染的风险。简单来说,就是作用于易感个体,使其变为感染者的力量。它随时间而变化。在疫情开始时,由于感染者不多,感染的力量会很小,但随着疫情的发展,感染的力量也会增加。

它可以表示为:

现在,我们可以在上面考虑的等式中代入该表达式,以获得:

这个模型可以考虑两种情况:

(a)具有常数λ的 SIR 模型

(b)具有变化λ的 SIR 模型

在下面的案例中,我们假设在疫情开始时,只有一个被感染的个体,还没有人康复。

基本模型的扩展

这里考虑扩展有:

  • 种群周转
  • 接种疫苗
  • 免疫力下降

这些因子在人群中被称为易感性的修饰因子。

模拟人口流动

在许多情况下,获得免疫力的人将被完全易感的新生儿取代。因此,考虑简单的 SIR 模型是不现实的。有必要考虑人口的出生和死亡。为简单起见,疾病引起的死亡率被忽略。

这些假设是:

  • 每个隔室中的每个个体经历相同的背景死亡率
  • b 是新生儿进入易感区间的速率

该扩展将包括出生率 b 和死亡率μ,这给出了以下微分方程:

模拟疫苗接种效果

设 p 为接种了完全有效疫苗的人口比例。这将反映在初始条件中,因为回收舱中将有一定比例的个体。

等式将给出如下:

t=0 的初始条件为 S=(1-p)(N-1)I=1R=p(N-1)

临界接种阈值

不是每个人都需要接种疫苗来预防疫情。这是因为一种叫做群体免疫的现象。当群体中有足够的免疫力来阻断传播时,群体免疫据说就实现了。

因此,需要接种疫苗的人口比例(p)可以计算为

模拟免疫力减弱

人们从感染中恢复后可能会获得免疫力,但这种免疫力不会永远持续下去。所以,这些人又变得敏感了。这里,σ是衰减率。

R 中的 SIR 模型

R 中的 deSolve 包包含了求解一阶常微分方程组(‘ODE’)的初值问题的函数。 ggplot2 包提供了可视化功能。

简单先生模型

最初,我们考虑一个简单的 SIR 模型,具有不同的传染力(λ)。

假设人口规模为 1000000,在流行病开始时,只有一个受感染的个体。还有,传染者*均每 2 天传染一个人,传染 5 天。

所以在这里,β=1/2 day⁻ =0.5 day⁻,γ=1/5 day⁻ =0.2 day⁻

感兴趣的时间段是每天间隔 100 天。

感染在 48 天左右达到高峰。

SIR 模型扩展为

假设人口规模随时间保持不变,即 10⁶,so b =μ。背景死亡率是根据人类*均寿命计算的,比如说 70 岁。所以,μ=1/70 year⁻,b=1/70 year⁻。还有,β=0.4365 year⁻,γ=0.2365 year⁻。

易感人群的患病率曲线有高峰,其间有很长的低谷。我们还观察到,当易感人群达到最大值时,感染达到峰值。

接种疫苗的影响

假设 40%的人口接种了疫情疫苗。假设γ=0.1 day⁻,β=0.4 day⁻。该模型运行时间为 3 年。

40%疫苗覆盖率的患病率图

我们从上面的图中观察到,即使有 40%的人接种了疫苗,仍有约 12.5%的人感染了这种流行病。

在这种情况下,临界疫苗接种阈值为 0.75。因此,75%的人口需要接种疫苗来预防这种流行病。

75%疫苗覆盖率的流行率图

从上面的图中我们观察到流行病没有发生。

免疫力减弱

假设γ=0.2 day⁻,β=0.4 day⁻,递减率,*均免疫期取 10 年,σ=1/10 year⁻。该模型每天运行 50 年。

流行率曲线看起来类似于人口流动的情况。虽然在人口更替的情况下,新的易感者的来源是出生,但在这种情况下,来源是失去免疫力的个人。

结合所有这些机制,它可以帮助解决决策者提出的关于接种疫苗的人口比例、接种频率等问题。这些真实世界的情况需要更复杂的模型,但是潜在的动力是相同的。

在下一篇文章中,我们将看到如何在 SIR 模型中模拟干预的效果:)

参考文献

  • Soetaert,K. E .,Petzoldt,t .,& Setzer,R. W. (2010 年)。解 R 中的微分方程:包 deSolve。统计软件杂志33
  • https://www . coursera . org/specializations/infectious-disease-modeling

广泛的 EDA 和对客户订阅(应用程序)的预测分析。

原文:https://towardsdatascience.com/extensive-eda-and-prediction-on-customers-subscription-on-an-application-analysis-2d7b0daff6aa?source=collection_archive---------70-----------------------

本文解释了应用于预测客户是否订阅应用程序的高级功能的各种数据科学方面。

我们有一个数据集,其中包含有关用户的详细信息,并显示特定用户是否注册了该应用程序的高级版本。我们将使用这个数据集来确定数据集中隐藏的各种见解,并使用这个数据集来建立一些机器学习模型。

让我们从导入数据集开始这个过程。

import pandas as pd
df=pd.read_csv("customer application subscription.csv")
df.head()

数据集的前五条记录

在加载数据集之后,我们现在要写一些行来了解数据集的总体情况。

print("\t\t\tDataset Statistics")
print("Number of variables:-",len(df.columns))
print("Number of observations:-",df.shape[0])
print("Missing Values:-",df.isna().sum().sum())
print("Missing Values %:-",round(df.isna().sum().sum()/df.shape[0]*100,3))
print("Duplicate rows:-",df[df.duplicated(keep="first")].shape[0])
print("Duplicate rows%:-",round(df[df.duplicated(keep="first")].shape[0]/df.shape[0]*100,3))
print("Variable types:-")
a=pd.crosstab(df.dtypes,columns="Count")
for i in pd.crosstab(df.dtypes,columns="Count").index:
    print("\t",str(i).split()[0],a.loc[i][0])

关于数据集的信息。

如果我们查看数据集,我们会发现缺失值只出现在登记日期列的中。因为在 50000 个条目中只有 0.03%的重复行,所以我们不会删除它们,因为这不是必需的。

现在我们将把 first_open 列转换成 datetime 格式,因为它是 object 类型。 first_open 列指定首次登录 app 的日期和时间。

df["first_open"]=pd.to_datetime(df["first_open"])
df['first_open_date'] = [d.date() for d in df['first_open']]
df['first_open_time'] = [d.time() for d in df['first_open']]
df=df.drop("first_open",axis=1)

由于我们已经从 first_open 列中获取了日期和时间,所以我们可以看到在日期内首次使用 app 的趋势。

a=pd.crosstab(index=df["first_open_date"],columns="count")
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('darkgrid')
import numpy as np
%matplotlib inline
x =  np.arange(datetime(2012,11,23), datetime(2013,7,10), timedelta(days=1)).astype(datetime)
y = a["count"]
y_mean = [a["count"].mean()]*len(x)
fig,ax = plt.subplots(figsize=(17,12))
ax.set_xlabel("Month",fontsize=20)
ax.set_ylabel("Count",fontsize=20)
ax.tick_params(labelsize=15, labelrotation = 20, color ="k")
data_line = ax.plot(x,y, label='Data')
mean_line = ax.plot(x,y_mean, label='Mean', linestyle='--')
legend = ax.legend(loc='upper right')
plt.show()

首次使用该应用程序的趋势

正如我们从图表中看到的,应用程序的使用波动很大。这可以得出结论,原因可能直接涉及到应用程序,如应用程序的推广等。而不是外部因素,因为它不会有太大的影响。

现在我们将从 dayofweek 专栏中看到一些见解。我们不会关注 first_open_time ,因为从那里找不到任何见解。

import seaborn as sns
sns.set_style('darkgrid')
ct=pd.crosstab(df["dayofweek"],columns="Count")
stacked = ct.stack().reset_index().rename(columns={0:'value'})
g=sns.barplot(x=stacked.dayofweek, y=stacked.value)
plt.title("Count of On which day user logon")

这里,在 dayofweek 中,唯一值解释了以下内容:

  • 1:星期一
  • 2:星期二
  • 3:星期三
  • 4:周四
  • 5:星期五
  • 6:星期六
  • 0:周日

该图解释了应用程序的最小使用量在星期二,最大使用量在星期四。

现在让我们分析一下小时

ct=pd.crosstab(df["hour"],columns="Count")
plt.figure(figsize=(12,12))
plt.tick_params(labelsize=15, labelrotation = 90, color ="k")
stacked = ct.stack().reset_index().rename(columns={0:'value'})
g=sns.barplot(x=stacked.hour, y=stacked.value)

超过 24 小时的应用程序使用情况

正如我们在这张图表中看到的,用户在上午 9 点左右使用应用较少,而在下午 3 点左右使用最多。

再来看年龄一栏。

df["age"].describe()

基本概念年龄栏目

plt.hist(df["age"],edgecolor="black",bins=7)
plt.show()

年龄直方图

这表明 75%的用户年龄在 37 岁以下。这意味着制造商和公司应该迎合需求,把 37 岁以下的人作为目标受众。

其他列有:- screen_list :描述客户看到的屏幕, numscreens :用户观看的屏幕数量, minigame :如果客户玩了应用程序中包含的迷你游戏,则 1 else 0, used_premium_feature :如果用户使用了应用程序的高级功能,则 1 else 0, enrolled :如果用户购买了高级功能,则 1 else 0,

我们现在将分析上面的列

groupedvalues=df.groupby('dayofweek')["numscreens","minigame","used_premium_feature","enrolled","liked"].sum().reset_index()
attributes=list(groupedvalues.columns)[1:]
att=attributes[1:]
for i in att:
    print(i)
    sns.countplot(df[i])
    plt.show()

基于 dayofweek 列,让我们看看其他列的行为:

for i in attributes:
    print(i)
    sns.barplot(x="dayofweek",y=i,data=groupedvalues)
    plt.show()

****星期几对比其他栏目

基于小时列,让我们看看其他列的行为

for i in attributes:
    print(i)
    plt.figure(figsize=(12,12))
    plt.tick_params(labelsize=15, labelrotation = 90, color ="k")
    sns.barplot(x="hour",y=i,data=groupedvalues2)
    plt.show()

****

小时 vs 其他栏目

通过这些图表,我们可以肯定地分析用户在白天的不活动性,因为大多数用户不得不执行其他任务,而不是使用这个应用程序。这可以进一步意味着可以在应用程序上执行的所有促销活动可以在下午完成,因为大多数用户在这个时间是活跃的。

让我们根据年龄来分析应用程序的使用情况。由于在 50000 条记录中有许多独特的年龄,我们将使用基于“年龄组”的可视化其他列的方法。

groupedvalues3=df.groupby(pd.cut(df['age'], np.arange(15, 106, 10)))["numscreens","minigame","used_premium_feature","enrolled","liked"].sum().reset_index()
for i in attributes:
    print(i)
    plt.figure(figsize=(12,12))
    plt.tick_params(labelrotation = 45)
    sns.barplot(x="age",y=i,data=groupedvalues3)
    plt.show()

****

年龄组 vs 其他栏目

在这些图表中,我们可以分析出,尽管 75%的观众年龄在 37 岁以下,但最活跃的年龄组在 15-35 岁之间。

由于我们执行了 EDA,我们将继续进行特性选择。

寻找各种特征之间的相关性:

for i in df.index:
    x = df.at[i , 'hour']
    y = x[0:3]
    df.at[i , 'hour'] = y
df["hour"]=df["hour"].astype('int64')
import seaborn as sns
df2 = df.drop(['user',  'enrolled_date'], axis = 1)
sns.heatmap(df2.corr(), annot = True)

各种特征之间的相关性

df3 = df2.drop(['enrolled'], axis = 1)
plt.figure(figsize=(8,8))
sns.barplot(x=df3.corrwith(df2.enrolled).index,y=df3.corrwith(df2.enrolled))
plt.tick_params(labelsize=15, labelrotation = 45)

关于登记的列的各种特征之间的相关性

上图显示小时、年龄、迷你游戏(负相关)、numscreens、迷你游戏(正相关)可以考虑建模。

在所有这些分析之后,我们将返回我们的数据框架,以便找到用户注册应用程序所花费的总时间。

df=pd.read_csv('data.csv')
df["first_open"]=pd.to_datetime(df["first_open"])
df["enrolled_date"]=pd.to_datetime(df["enrolled_date"])
df['time_to_enrolled']=(df.enrolled_date - df.first_open).astype('timedelta64[h]')
import matplotlib.pyplot as plt
plt.figure(figsize=(6,6))
plt.hist(df['time_to_enrolled'].dropna(), range = (0,100))
plt.show()

注册高级功能所需时间的直观表示。

正如我们在此直方图中看到的,50 小时前的详细信息是好的,因为其他信息是异常值,会影响模型,因此我们认为客户已注册为 0。

df.loc[df.time_to_enrolled > 50, 'enrolled'] = 0

****屏幕列表可能是一个非常有用的列,因为它可以用于建模目的。但是这个列是一个字符串。因此,为了使用它,我们需要对这个列进行编码,这将花费很多时间,因为它必须处理大约 50000 个字符串。

在继续之前,我们需要另一个包,即“mlxtend”包。为了安装它,请在 cmd/Anaconda 提示符下使用以下命令行:-

pip install mlxtend

在这之后写下下面几行:

for i in range(len(df["screen_list"])):
    df["screen_list"][i]=df["screen_list"][i].split(',')
from mlxtend.preprocessing import TransactionEncoder 
transactionEncoder = TransactionEncoder()
txnn=transactionEncoder.fit(df["screen_list"]).transform(df["screen_list"])
dfnn=pd.DataFrame(txnn,columns=transactionEncoder.columns_)
df=df.join(dfnn, how="outer")
from sklearn.preprocessing import LabelEncoder
le=LabelEncoder()
l=list(transactionEncoder.columns_)
for i in l:
    try:
        df[i]=le.fit_transform(df[i])
    except:
        pass

由此,我们将转换数据集,并仅选择模型所需的那些特征,如上所述。

a1=df[["hour","age","numscreens","used_premium_feature","minigame"]]
for i in df.index:
    x = a1.at[i , 'hour']
    y = x[0:3]
    a1.at[i , 'hour'] = y
a1["hour"]=a1["hour"].astype('int64')
a2=df[transactionEncoder.columns_]
a1=a1.join(a2, how="outer")
X=a1
Y=df["enrolled"]
from sklearn.model_selection import train_test_split
xtrain,xtest,ytrain,ytest=train_test_split(X,Y,test_size=0.3,random_state=42)

现在我们的数据要通过模型。让我们尝试通过各种 ML 模型来传递我们的模型。

  1. 逻辑回归:
from sklearn.linear_model import LogisticRegression
le=LogisticRegression(random_state = 42, penalty = 'l1')
le.fit(xtrain,ytrain)
le.score(xtest,ytest)

运行代码后,我们得到以下分数:

0.868

我们从这个数据集中得到了一个令人印象深刻的分数。让我们从训练集中检查是否存在过度拟合的情况。

le.score(xtrain,ytrain)

运行代码后,我们得到以下分数:-

0.8619428571428571

似乎不存在过度拟合的情况

2.决策树分类器
我们将使用 GridSearchCV 进行超参数调优

from sklearn.tree import DecisionTreeClassifier
from sklearn import metrics
from sklearn.model_selection import GridSearchCV
tuned_parameters = [{'criterion': ['gini','entropy'],
'max_depth': range(2,10)}]
clf_tree = DecisionTreeClassifier()
clf = GridSearchCV(clf_tree,
tuned_parameters,
cv=10,
scoring='roc_auc')
clf.fit(xtrain, ytrain )

要查找参数:-

clf.best_params_

这是我们得到的。

{'criterion': 'entropy', 'max_depth': 7}

所以我们会用它来找到分数。

clf_tree2 = DecisionTreeClassifier(criterion = 'entropy',
max_depth = 7 )
clf_tree2.fit( xtrain, ytrain )
tree_predict2 = clf_tree2.predict( xtest )
metrics.roc_auc_score( ytest, tree_predict2 ) 

收到以下分数:

0.8662688484194627

同样,我们也可以使用其他 ML 模型。这是我的第一篇文章,非常感谢您的宝贵反馈。谢谢,祝编码愉快!

笔记本链接:-https://github . com/luv 8860/Projects/blob/master/Customer % 20 application % 20 subscription . ipynb

数据集链接:-

https://github . com/luv 8860/Projects/blob/master/customer % 20 application % 20 subscription . CSV

外部地理空间数据:类型和用例

原文:https://towardsdatascience.com/external-geospatial-data-types-and-use-cases-7131e9a1ee24?source=collection_archive---------16-----------------------

不同地理空间数据流、其类型和使用案例的详细回顾

来源:Kepler.gl

“你有没有一些外部数据源,我们可以添加到我们的分析中?”

我们的客户提出这样的问题对我们来说并不罕见或陌生。

什么是外部数据?

内部数据主要是在组织的生态系统中生成的信息,包括客户交易数据、人力资源数据等。

一个单一的数据来源可能并不总能捕捉到全貌。外部地理空间数据流是指可以从其他组织公开托管的数据门户中找到和收集的数据(交易数据、人口统计数据等)。

与特定地理位置周围的人的富裕程度、人口统计、生活方式和移动模式相关的数据属于替代数据,除了与公司相关的数据(如 CRM 信息)之外,这些数据还有助于组织更好地了解他们的客户。

外部数据是衍生的数据,不易获取。然而,如今世界上的顶级组织正在利用外部数据来获得更深入、更新的见解,以保持领先地位。

根据 B2B 研究公司 Clutch 的调查,公司在收集和分析数据时最常关注的是他们的组织内部数据(70%的时间)。

如果你是:

  • 一家零售公司询问“我们如何找到 X 处人们的收入数据,以用于他们的扩张目的”或
  • 一家保险公司询问“我们如何准确定位易受自然灾害影响的区域,以集中我们的营销策略?”或者
  • 一家食品配送公司或一家餐馆公司询问“我们能否使用天气数据来预测降雨,以便更好地应对需求下降?”

这是给你的博客。我们意识到了外部数据所包含的价值,因此集思广益,研究这些外部数据如何为在混乱多变的现实世界中运营的各种行业所用。

来源:沃达丰

了解商业与空间的关系,了解事情在哪里发生,为什么会发生,以及未来会在哪里发生以及如何发生,将成为未来规划的重要工具

外部数据的示例

下面,我们将讨论外部数据源的不同例子及其用例。

人类流动性

人类的流动性在揭示人类行为模式和个人习惯方面发挥着巨大的作用。在物理空间中,人的移动性主要是指人的运动轨迹。人体移动数据的数据源主要是 GPS 数据、手机发射塔数据、WiFi 数据。

人的移动性有助于洞察移动的空间分布、用户角色的创建、公共交通的使用、可步行性水*以及一个地区的污染排放。

通过绘制停车点地图改善残疾人的行动能力【来源】

类型

各种人员流动数据的分离如下:

  • 原始数据:设备经纬度
  • 活动相关:参观人数
  • 家和工作:居民和工人数量。

人员流动可以从两个方面帮助组织:

  1. 周围人口/*均客流量:跟踪实时客流量有助于清楚了解一天内一个地区的*均预期人口。
  2. 公路/铁路连接:这给出了一个特定地区人口通常如何流动的概念。这可以显示特定区域的道路密度或铁路连通性。

用例

组织经常利用的人员移动数据的一个有趣用例是使用实时人员流量数据在正确的位置放置广告牌。

人员流动数据也被用来管理微观流动的涌入。例如,在纳什维尔大都市,市政官员正在将地理空间数据与移动数据相结合,以更好地了解车辆的集中程度,然后将固定车辆重新分配到居民生活的区域,而不是让更多的车辆上路。[ 来源

KeyMe ,一家致力于使用机器人技术革新锁匠行业的技术公司,使用实时步行交通模型进行选址。由于利用了位置数据,新安装的信息亭群组的*均收入比之前安装的信息亭增加了 52%

经济/金融数据

地理空间分析在银行业中扮演着非常重要的角色,尤其是对于金融服务提供商而言。银行的内部数据与地理空间数据相结合,提供了帮助他们扩展业务以及更好地服务客户的见解。

经济发展水*是许多企业扩张活动的指标。人们的收入和富裕程度(即购买力)有助于公司确定应该向特定地区的居民提供哪些品牌或商品。

万事达卡有助于组织更好地了解不同地区的消费趋势。该解决方案提供了对总月销售额、*均门票大小、交易总数、性能稳定性和随时间增长的性能的洞察。[ 来源

万事达卡的零售位置洞察【来源】

类型

富裕程度和收入水*可以通过以下参数得出:

  1. 基础设施:一个区域内建筑的*均面积或居住在特定周边的人口数量。
  2. 兴趣点:给定客户可以进入的区域中的自动取款机、商店、餐馆、综合商店的数量
  3. 竞争优势:业务活动和发展可以被跟踪,从而让你深入了解你当前客户群中的竞争对手是谁。

房产贷款是根据周围商业房产价值的信息进行评估的,并且对贷款偿还的风险和概率有很好的了解。

星巴克利用这些因素来规划他们的下一个商店位置。您可以在此阅读更多信息:

* [## 使用位置数据的场地规划

星巴克如何使用地理信息系统来规划他们的下一个商店位置

medium.com](https://medium.com/locale-ai/site-planning-using-location-data-ae7814973521)

用例

利用不同地区的富裕程度和收入水*,企业还可以确定他们应该扩展的领域。在肯尼亚,移动网络运营商正在与银行合作,创建通过移动货币交付的数字金融服务。[ 来源

这里有一个简短的视频,旨在了解金融数据和地理空间数据在一起使用时如何帮助银行业的日常活动。

人口统计数据

人口统计数据帮助我们描述和量化一个地区的人口特征。它可以在空间上突出显示有助于回答战略性业务问题的模式。

分析一个地区的人口统计数据有助于我们找到一些挑战性问题的答案,比如——一个地方的人口年龄有多大?一个地方的人口受教育程度如何?人口是如何随着时间变化的?

类型

突出一个地方的人口统计的两个主要因素如下:

1.年龄/性别:有助于了解属于特定年龄/性别群体的人口百分比。

2.居住人口:给出居住在特定区域的估计人数。

国际货币基金组织的信息图显示了日本人口的变化【来源】

用例

任何数据驱动的营销策略的最终成功都取决于组织收集正确数据的能力,以及他们如何利用人口统计和位置数据的组合。酒店和旅游等行业严重依赖于人口趋势。

酒店公司可以识别出对旅游服务需求最大的国家。这有助于他们将营销预算投入到这些地区的消费者中 [来源]

。id 是一家专注于经济、人口和人口预测的公司,该公司帮助学校规划者放大并确定未来十年学龄儿童增长的郊区。这有助于学校规划者根据当地人口的*均年龄战略性地确定学校类型(游戏学校、高中等)。

Orbital Insights 与联合国开发计划署阿拉伯人类发展报告团队合作,致力于消除贫困和减少不*等,主要关注埃及开罗的贫民窟居民。

位置数据(来自智能手机的聚合位置数据)与贫民窟边界数据相结合,提供了关于设备聚合行为的见解,进而提供了关于居住在该边界内的人口的信息。

环境/天气数据

QGIS 分析。[ 来源

天气/环境数据在房地产、物流、送餐和共享经济等行业中发挥着战略作用。天气/环境数据与内部数据相结合,可以提供帮助组织为其业务采取适当措施的模式。

食品科技公司 Deliveroo 利用天气数据及其内部数据来处理极端天气条件下的需求波动。他们让自己为任何条件的变化做好准备,即使只是一毫米的雨。【来源

天气是美国经济中最大的外部波动因素,每年造成超过 5500 亿美元的收入损失和多达 76,000 个工作岗位的流失。

天气灾害风险指数等参数在房地产行业中起着非常重要的作用。高风险区域的房产通常会升值。

在共享经济(优步/Airbnb)中,对服务的需求会随着天气条件的突然变化(突然下雨、狂风暴雨)而波动。价格也会飙升,以满足现有的需求,并分别*衡司机和乘客的需求和供应。

类型

卫星图像是根据一天中可以使用它们的时间以及它们最佳运行所需的适当条件进行分类的。它们有以下三种类型:

  • 可见:可见卫星图像只有在白天才能看到,因为云层会反射太阳光。它们对预测雷雨云的形成很有用,因为在雷达探测到雷雨云之前,云就可以通过白色识别出来。
  • 红外线:红外线卫星图像相对于可见光卫星图像的一个优势是它们在白天和晚上都可以被看到。使用红外图像可以探测到雾天和低云。
  • 水汽:水汽卫星显示了大气中的水分含量。它们被广泛用于预测哪里可能会有暴雨。

用例

我们在现场喜欢的一个有趣的卫星数据是夜灯——这是一个地区经济增长和发展的良好代表。美国国家航空和宇宙航行局拍摄了夜灯,每天测量非常细微的区域的夜间活动。如果你想分析不同城市的发展速度,或者你应该扩展到哪个城市,nightlights 是一个强大的数据源。

高质量的卫星图像正被广泛用于预测作物产量和土地覆盖分类。不仅如此,卫星图像还用于遥感,帮助组织在农业服务、小额信贷服务和离网能源传输方面更好地服务于农村地区。卫星图像还被用于灾后损失评估。使用变化检测(事前和事后)的基于对象的图像分类是获得损害评估的快速方法。

在商业空间,卫星图像被用于许多目的。一个有趣的用例是如何通过计算停车场中停放的汽车数量来预测零售店的盈利能力[ 来源

兴趣点

兴趣点是一个专用的地理实体,如礼拜场所、遗址或公司办公室。POI 数据最常用于评估位置和分析公众的行为趋势。企业也可以用它来监控网站的位置和竞争对手的一些营销策略。

组织使用位置智能进行选址,以确定具有市场潜力的区域。通过跟踪他们感兴趣领域的过去和现在的活动,公司可以决定哪些商店是盈利的,哪些商店的市场份额相对较少。

兴趣点有最通用的用例。旅游机构可以使用它们来突出显示城市内外的景点和活动,大学可以使用它们来为学生和游客定位校园位置,或者个人可以在谷歌地图中设置自己的兴趣点,如“工作”或“家”,以便于导航。

用例

Orbital Insights platform GO 通过在单个加油站的粒度级别跟踪天然气需求,帮助推动加油站的选址。不仅如此,关于兴趣点的数据也可用于物流优化。

Esri 帮助物流公司进行路线规划,方法是增加路线上的配送数量,并将车队引导至沿途有加油站的路线。

*

来源

这里有几个来源可以找到各种类型的外部数据。您可以在互联网上找到许多其他外部开放数据来源。

  1. https://bit.ly/2HGFzUX】人口流动数据:
  2. 金融/经济数据:https://data.worldbank.org
  3. 人口统计数据:https://data.gov.in/keywords/population
  4. 环境数据:https://www.data.gov/weather/
  5. 兴趣点数据:http://www.poi-factory.com/

不同数据源与地理空间数据的结合正帮助组织找到一些复杂问题的解决方案,并做出数据驱动的决策。这听起来可能令人吃惊,但一些看似没有影响的因素可能有助于弥合差距,也有助于扩大组织的业务。

如果你想深入研究,可以查看我们的网站或者在 LinkedInTwitter 上与 Aditi Sinha 取得联系。

每个数据科学家都应该知道的额外 4 个 SQL 技巧

原文:https://towardsdatascience.com/extra-4-sql-tricks-every-data-scientist-should-know-d3ed7cd7bc6c?source=collection_archive---------3-----------------------

充分利用 SQL 加快分析工作的第 2 部分

在我之前的博客每个数据科学家都应该知道的 6 个 SQL 技巧中,我讨论了在我作为数据科学家的日常工作中最有用的 SQL 功能。这个博客是这个迷你系列的第 2 部分,我将继续分享我的 SQL 技巧来帮助你提高你的分析/报告效率。

今天,我们将使用一个新的玩具表,如下所示,包含多种数据类型,出于演示目的,该练习将在 MS SQL server 2017 中实现。

玩具数据表(带有变量定义)

  1. ROW_NUMBER()返回行的子集

SQL 中的 ROW_NUMBER()函数为结果的每一行创建一个唯一的递增整数值。这一列值被认为是一个 - ,因为它本身并不存在于我们的数据表中,因此,结果是按照 ORDER BY 子句中分析师确定的顺序返回的。

有了这个伪列,我们可以使用一个简单的查询来解决“前 N 名”的问题,下面演示了如何为每个 ID 选择 Num_Var 值最高的前 3 条记录,

下面是返回的子集(当然,您可以从输出中删除列 RowNumber),

输出:Num_Var 值最高的前 3 条记录

我注意到,尽管只有一行,ID 0180 和其他 ID(多于 3 行)一样被正确返回。因此,不需要额外注意原始数据是否有足够的行数用于指定的数量 N。直白!

***更新 2022:你也可以在这里看这篇文章的视频版,

2。用 ROW_NUMBER()(高级)计算连续天数

知道了 ROW_NUMBER()的概念,您一定在想时间序列中的另一个可能的应用,在这里我们计算感兴趣的事件持续的连续时间。

我什么意思?好吧,让我们把玩具数据看作是登录我们网站的顾客。客户 ID 0155 在 06/01、06/02 和 06/03(即连续 3 天)登录,然后分别在 09/29 和 09/30 连续登录了 2 次。从视觉上看,如果日期没有排序,我们进行计算就没那么简单了。SQL 查询有什么帮助?

一种直观的方法是首先使用 ROW_NUMBER()在每个客户 ID 中分配按日期排序的行号。因为整数行号恰好也是递增 1,所以连续天数就是最后一个日期和第一个日期之间的差!不幸的是,它不会工作,因为它会给我们一个 5,而不是 3 和 2(对于客户 0155)。

这就引出了关于 ROW_NUMBER()函数的一个重要注意事项:它没有间隙!它为每个分区创建一个始终从 1 开始递增的值,而我们的数据有间隙(例如,06/03 和 09/29 不是连续的)。因此,简单地应用 ROW_NUMBER()并不能得到我们想要的输出。我们需要一些调整,以下是方法,

步骤 1: 创建 RowNumber (order by date ASC)

这为我们提供了这个临时输出,为了便于参考,我们将其标记为output _ table _ with _ row number

临时输出:按日期排列的行号

第二步:Date _ Var row number 对连续的天数(即具有相同计数起点的日期)进行分组

而这里的返回,标注为output _ table _ with _ grouping _ var

临时输出:创建分组变量

现在,不要纠结于这个派生变量 的值,因为它毫无意义。它只是一个分组变量,基本上是告诉 SQL 这些行是连续的(即递增 1)。

第三步 :计算按 Starting_Count_DT 分组的长度(连续天数)

这是我们的最终输出!

输出:连续天数

把所有东西放在一起,

唷,问题解决了!如果您第一次没有得到它,不要担心,您可以将它放入您的数据科学代码片段库,并在需要时随时引用。当你在下一次大型科技公司的数据科学家职位面试中遇到这个问题时,不要惊讶😄

3。用声明保持干燥

正如我们刚刚看到的,前面的查询是一个相当复杂的查询,包含两个嵌套的子查询。这些子查询增加了读取和调试代码的复杂性,如果我们将代码传递给其他队友,他们很可能不知道这个查询在做什么。

现在,WITH 子句(也称为子查询分解)可以解决问题了!让我们看看如何重写上面的查询,使它更容易理解,

这里,(1)通过利用 WITH 子句,我们将嵌套查询分解成两个单独的临时视图,以提高代码可读性;(2)对多个查询之间的关系没有要求,这意味着它们可以是独立的或相关的(如在我们的例子中)。

WITH 子句的另一个有用场景是当 WITH 查询被多次引用时。不需要一次又一次地重复编写相同的子查询(即the DRY/not Repeat Yourself principle),我们可以在前面引入,在后面重用。

4。串联以重新格式化您的数据结构

接下来,我们的下一个任务是为我们的内部利益相关者创建一个汇总报告,显示每个客户登录的日期。这将是多对多信息的聚合。还观察到 ID_Var 和 Gen_Var 都包含跨行的重复值,因此为了使其适合人类阅读,我们立即想到 MS SQL 2017 中的 STRING_AGG()函数,

这段代码片段产生了,

输出:日期串联

正如我们所看到的,(1)通过简单地指定 ORDER BY 语句(例如,ID 0155),可以对级联列表中的元素进行排序;(2)尽管 STRING_AGG()函数更常用于字符串连接,但它也适用于其他数据类型(例如,我们示例中的日期和数字变量)。

现在,关于这个聚合功能的几个 标注 :

(1)虽然在各大 SQL 数据库中都有,但具体的函数名称各不相同。在 Oracle/PLSQL (11g)中是 LISTAGG() ,在 MySQL 和 IBM Netezza 中是 GROUP_CONCAT() ,在 MS SQL server 2017 和 PostgresSQL 中是 STRING_AGG()

(2)除了使数据视图更简单之外,我发现它在我们需要将数据提取到 R 或 Python 中进行深入分析的场景中也很有用(顺便说一下,如果您还没有这样做,请查看我以前的文章中关于将数据从 SQL 数据库提取到 Python 的技巧)。我们可以先将具有不同值的字段连接到每个 ID 的一行中,以减少数据大小,然后用 R 或 Python 解析这个字段,而不是像大多数列那样传输整个原始数据表。在这种连接中,空值将被排除,因此,我们不必担心在这一点上丢失值的处理。

这就是你要的——4 个额外的数据分析 SQL 技巧!我希望你觉得这个迷你系列鼓舞人心,并喜欢阅读它像我写它一样。和往常一样,所有的代码片段和玩具数据都可以在我的 Github 中找到😀

想要更多数据科学和编程技巧?使用 我的链接 注册 Medium,获得我所有内容的全部访问权限。

还订阅我新创建的 YouTube 频道 【数据谈吉】

这个迷你系列的第一部,

* [## 每个数据科学家都应该知道的 6 个 SQL 技巧

提高分析效率的 SQL 技巧

towardsdatascience.com](/6-sql-tricks-every-data-scientist-should-know-f84be499aea5)*

用 Python 将 CVAT XML 文件中的注释提取到掩码文件中

原文:https://towardsdatascience.com/extract-annotations-from-cvat-xml-file-into-mask-files-in-python-bb69749c4dc9?source=collection_archive---------14-----------------------

一种从 CVAT XML 中获取掩码文件的方法

计算机视觉标注工具(CVAT) 是众所周知的图像标注工具。数据贴标机的工作结果可以导入 XML 文件。这个 XML 文件包含关于标记的所有必要信息。然而,对于图像分割任务,必须具有图像文件(JPEG、GIF、PNG 等)形式的遮罩。).换句话说,有了 CVAT XML 文件中的标记坐标,您需要绘制相应的遮罩。

图片由 Oleksii Sheremet 用 Adobe Photoshop 制作

如果数据标注器处理图像的分辨率高于训练所用的分辨率,那么任务将变得更加复杂。有必要考虑图像压缩因子对 XML 文件中呈现的提示点的数值的影响。

所有提取注释的代码都是作为 Python 中的脚本实现的。lxml 库用于解析 xml。它是处理 XML 和 HTML 标记的快速灵活的解决方案。 lxml 包支持 XPath 和 XSLT,包括一个用于 SAX 的 API 和一个与 C 模块兼容的 API。

tqdm 包作为进度条来说明大量文件的处理。

让我们仔细看看。导入库:

import os
import cv2
import argparse
import shutil
import numpy as np
from lxml import etree
from tqdm import tqdm

一个用于创建新目录和递归删除现有目录内容的有用函数:

def dir_create(path):
    if (os.path.exists(path)) and (os.listdir(path) != []):
        shutil.rmtree(path)
        os.makedirs(path) if not os.path.exists(path):
        os.makedirs(path)

正在讨论的脚本的参数是以下数据:具有输入图像的目录、具有 XML 格式的 CVAT 注释的输入文件、用于输出掩码的目录以及图像的比例因子。从命令行解析参数的函数:

def parse_args():
    parser = argparse.ArgumentParser(
        fromfile_prefix_chars='@',
        description='Convert CVAT XML annotations to contours'
    )parser.add_argument(
        '--image-dir', metavar='DIRECTORY', required=True,
        help='directory with input images'
    )parser.add_argument(
        '--cvat-xml', metavar='FILE', required=True,
        help='input file with CVAT annotation in xml format'
    )parser.add_argument(
        '--output-dir', metavar='DIRECTORY', required=True,
        help='directory for output masks'
    )parser.add_argument(
        '--scale-factor', type=float, default=1.0,
        help='choose scale factor for images'
    )return parser.parse_args()

为了理解提取函数是如何工作的,让我们仔细看看 CVAT XML 文件的这一部分:

<image id="7" name="7.jpg" width="4800" height="2831">
    <polygon label="roofs" occluded="0" points="2388.11,2069.80;2313.80,2089.10;2297.46,2080.21;2285.57,2043.80;2339.07,2031.17;2336.10,2018.54;2428.23,2060.89">
    </polygon>
    <polygon label="roofs" occluded="0" points="1431.35,1161.11;1353.11,1179.63;1366.25,1229.79;1398.80,1219.94;1396.11,1210.08;1437.91,1194.26">
    </polygon>
    <polygon label="roofs" occluded="0" points="1344.81,1673.28;1270.10,1619.40;1213.00,1697.00">
    </polygon>
    <polygon label="roofs" occluded="0" points="1498.35,939.31;1573.30,923.19;1586.74,985.00;1509.10,1002.32">
    </polygon>
...

首先,需要在 XML 文件中找到与当前处理的图像相对应的区域。最简单的方法是通过文件名(例子中的7.jpg)。接下来,您需要找到标记'多边形或',并从中提取必要的数据(在本例中,屋顶是基于多边形标记的)。您可以使用以下函数从 CVAT XML 获取标记结果:

def parse_anno_file(cvat_xml, image_name):
    root = etree.parse(cvat_xml).getroot()
    anno = []image_name_attr = ".//image[[@name](http://twitter.com/name)='{}']".format(image_name)for image_tag in root.iterfind(image_name_attr):
        image = {}
        for key, value in image_tag.items():
            image[key] = value
        image['shapes'] = []
        for poly_tag in image_tag.iter('polygon'):
            polygon = {'type': 'polygon'}
            for key, value in poly_tag.items():
                polygon[key] = value
            image['shapes'].append(polygon)
        for box_tag in image_tag.iter('box'):
            box = {'type': 'box'}
            for key, value in box_tag.items():
                box[key] = value
            box['points'] = "{0},{1};{2},{1};{2},{3};{0},{3}".format(
                box['xtl'], box['ytl'], box['xbr'], box['ybr'])
            image['shapes'].append(box)
        image['shapes'].sort(key=lambda x: int(x.get('z_order', 0)))
        anno.append(image)
    return anno

接下来,我们需要创建掩码文件。用白色画蒙版多边形的边,用红色画里面的内容(如上图所示)。以下函数允许您这样做:

def create_mask_file(width, height, bitness, background, shapes, scale_factor):
    mask = np.full((height, width, bitness // 8), background, dtype=np.uint8)
    for shape in shapes:
        points = [tuple(map(float, p.split(','))) for p in shape['points'].split(';')]
        points = np.array([(int(p[0]), int(p[1])) for p in points])
        points = points*scale_factor
        points = points.astype(int)
        mask = cv2.drawContours(mask, [points], -1, color=(255, 255, 255), thickness=5)
        mask = cv2.fillPoly(mask, [points], color=(0, 0, 255))
    return mask

最后,主要功能是:

def main():
    args = parse_args()
    dir_create(args.output_dir)
    img_list = [f for f in os.listdir(args.image_dir) if os.path.isfile(os.path.join(args.image_dir, f))]
    mask_bitness = 24
    for img in tqdm(img_list, desc='Writing contours:'):
        img_path = os.path.join(args.image_dir, img)
        anno = parse_anno_file(args.cvat_xml, img)
        background = []
        is_first_image = True
        for image in anno:
            if is_first_image:
                current_image = cv2.imread(img_path)
                height, width, _ = current_image.shape
                background = np.zeros((height, width, 3), np.uint8)
                is_first_image = False
            output_path = os.path.join(args.output_dir, img.split('.')[0] + '.png')
            background = create_mask_file(width,
                                          height,
                                          mask_bitness,
                                          background,
                                          image['shapes'],
                                          args.scale_factor)
        cv2.imwrite(output_path, background)

当我们对 python 解释器执行 file as 命令时,我们必须添加以下结构:

if __name__ == "__main__":
    main()

仅此而已。要运行该脚本,您应该运行以下命令(如果在标记后不调整图像大小,则默认情况下缩放因子为 1):

python script_name.py --image-dir original_images_dir --cvat-xml cvat.xml --output-dir masks_dir --scale-factor 0.4

原始图像示例:

图片由 Oleksii Sheremet 使用 Google Earth 创建

作为脚本结果获得的掩码:

图片由 Oleksii Sheremet 使用 OpenCV 库创建

结论

所考虑的方法允许从包含在 CVAT XML 中的数据获得更复杂的掩码文件。根据顶点的数量,可以提取单个多边形或用不同的颜色高亮显示多边形。此外,稍加修改后,所考虑的脚本将允许根据标记轮廓从原始图像中切割多边形截面。

参考文献

计算机视觉标注工具(CVAT)

lxml —用 Python 实现 xml 和 HTML

OpenCV

如何运行您的 Python 脚本

在 VGG16 和 VGG19 CNN 模型中提取特征、可视化过滤器和特征地图

原文:https://towardsdatascience.com/extract-features-visualize-filters-and-feature-maps-in-vgg16-and-vgg19-cnn-models-d2da6333edd0?source=collection_archive---------2-----------------------

了解如何在 VGG16 和 VGG19 CNN 模型中提取特征、可视化过滤器和特征地图

VGG16 架构

VGG19 架构

Keras 提供了一组深度学习模型,这些模型与ImageNet数据集上预训练的权重一起可用。这些模型可用于预测、特征提取和微调。在这里,我将讨论如何为给定图像的预训练模型 VGG16 和 VGG19 提取特征、可视化过滤器和特征图。

用 VGG16 提取特征

用 VGG16 提取特征

这里我们先从 tensorflow keras 导入 VGG16 模型。导入 image 模块来预处理图像对象,导入 preprocess_input 模块来为 VGG16 模型适当地缩放像素值。numpy 模块是为数组处理而导入的。然后,使用 imagenet 数据集的预训练权重加载 VGG16 模型。VGG16 模型是一系列卷积层,后跟一个或几个密集(或全连接)层。Include_top 允许您选择是否需要最终的密集层。False 表示加载模型时不包括最终的密集图层。从输入层到最后一个 max pooling 层(标注为 7×7×512)作为模型的特征提取部分,其余网络作为模型的分类部分。在定义了模型之后,我们需要加载模型期望大小的输入图像,在本例中是 224×224。接下来,图像 PIL 对象需要被转换为像素数据的 NumPy 数组,并从 3D 数组扩展为具有[ 样本、行、列、通道 ]维度的 4D 数组,这里我们只有一个样本。然后,需要针对 VGG 模型对像素值进行适当的缩放。我们现在已经准备好获取特性了。

输出最后一个最大池图层的要素形状和要素集

用 VGG16 从任意中间层提取特征

这里,我们首先从 tensorflow keras 导入 VGG16 模型。导入 image 模块来预处理图像对象,导入 preprocess_input 模块来为 VGG16 模型适当地缩放像素值。numpy 模块是为数组处理而导入的。此外,模型模块被导入以设计新模型,该新模型是完整 VGG16 模型中的层的子集。该模型将具有与原始模型相同的输入层,但输出将是给定卷积层的输出,我们知道这将是该层或特征图的激活。然后,使用 imagenet 数据集的预训练权重加载 VGG16 模型。例如,加载 VGG 模型后,我们可以定义一个新模型,从 block4 池层输出一个特征图。在定义了模型之后,我们需要加载模型期望大小的输入图像,在本例中是 224×224。接下来,图像 PIL 对象需要被转换为像素数据的 NumPy 数组,并从 3D 数组扩展为具有[ 个样本,行,列,通道 ]的维度的 4D 数组,这里我们只有一个样本。然后,需要针对 VGG 模型对像素值进行适当的缩放。我们现在已经准备好获取特性了。

例如,这里我们提取 block4_pool 层的特征。

用 VGG16 提取 block4_pool 图层的特征

使用 VGG19 提取特征

使用 VGG19 提取特征

这里我们先从 tensorflow keras 导入 VGG19 模型。导入 image 模块来预处理图像对象,导入 preprocess_input 模块来为 VGG19 模型适当地缩放像素值。numpy 模块是为数组处理而导入的。然后,使用 imagenet 数据集的预训练权重加载 VGG19 模型。VGG19 模型是一系列卷积层,后跟一个或几个密集(或全连接)层。Include_top 允许您选择是否需要最终的密集层。False 表示加载模型时不包括最终的密集图层。从输入层到最后一个 max pooling 层(标注为 7×7×512)作为模型的特征提取部分,网络的其余部分作为模型的分类部分。在定义了模型之后,我们需要加载模型期望大小的输入图像,在本例中是 224×224。接下来,图像 PIL 对象需要被转换为像素数据的 NumPy 数组,并从 3D 数组扩展为具有[个样本、行、列、通道]维度的 4D 数组,这里我们只有一个样本。然后,需要针对 VGG 模型对像素值进行适当的缩放。我们现在已经准备好获取特性了

用 VGG19 从任意中间层提取特征

这里,我们首先从 tensorflow keras 导入 VGG19 模型。导入 image 模块来预处理图像对象,导入 preprocess_input 模块来为 VGG19 模型适当地缩放像素值。numpy 模块是为数组处理而导入的。此外,模型模块被导入以设计新模型,该新模型是完整 VGG19 模型中的层的子集。该模型将具有与原始模型相同的输入层,但输出将是给定卷积层的输出,我们知道这将是该层或特征图的激活。然后,使用 imagenet 数据集的预训练权重加载 VGG19 模型。例如,加载 VGG 模型后,我们可以定义一个新模型,从 block4 池层输出一个特征图。在定义了模型之后,我们需要加载模型期望大小的输入图像,在本例中是 224×224。接下来,图像 PIL 对象需要被转换为像素数据的 NumPy 数组,并从 3D 数组扩展为具有[ 个样本,行,列,通道 ]的维度的 4D 数组,这里我们只有一个样本。然后,需要针对 VGG 模型对像素值进行适当的缩放。我们现在已经准备好获取特性了。

例如,这里我们提取 block4_pool 层的特征。

用 VGG19 提取 block4_pool 图层的特征

总结 VGG16 模型各卷积层中的滤波器

总结 VGG16 模型各卷积层中的滤波器

过滤器是简单的权重,然而由于过滤器的专门的二维结构,权重值彼此具有空间关系,并且将每个过滤器绘制为二维图像是有意义的。这里我们回顾一下 VGG16 模型中的滤波器。这里我们从 tensorflow keras 导入 VGG19 模型。我们可以通过 model.layers 属性访问模型的所有层。每一层都有一个 layer.name 属性,其中卷积层有一个类似于 block#_conv# 的命名卷积,其中“ # ”是一个整数。因此,我们可以检查每个层的名称,并跳过任何不包含字符串' conv '的层。每个卷积层有两组权重。一个是滤波器模块,另一个是偏置值模块。这些可通过 layer.get_weights() 函数访问。我们可以检索这些重量,然后总结它们的形状。上面给出了总结模型过滤器的完整示例,下面显示了结果。

VGG16 模型各卷积层中的滤波器

所有卷积层都使用 3×3 滤波器,这种滤波器很小,也许很容易解释。卷积神经网络的架构问题是滤波器的深度必须匹配滤波器的输入深度(例如通道的数量)。我们可以看到,对于具有红色、绿色和蓝色三个通道的输入图像,每个过滤器的深度为三(这里我们使用的是通道最后的格式)。我们可以将一个过滤器想象成一个有三个图像的图,每个通道一个图像,或者将所有三个图像压缩成一个彩色图像,或者甚至只看第一个通道,并假设其他通道看起来相同。

在 VGG16 模型的第二层中可视化 64 个过滤器中的前 6 个过滤器

在 VGG16 模型的第二层中可视化 64 个过滤器中的前 6 个过滤器

这里我们从 VGG16 模型的第二个隐藏层检索权重。权重值可能是以 0.0 为中心的小正值和负值。我们可以将它们的值归一化到 0–1 的范围内,使它们易于可视化。我们可以列举该模块 64 个滤波器中的前六个,并绘制每个滤波器的三个通道。我们使用 matplotlib 库,将每个过滤器绘制为新的一行子图,将每个过滤器通道或深度绘制为新的一列。这里,我们绘制了 VGG16 模型中第一个隐藏卷积层的前六个滤波器。

VGG16 模型第二层 64 个滤波器中的前 6 个滤波器

它创建了一个具有六行三个图像或 18 个图像的图形,每个过滤器一行,每个通道一列。我们可以看到,在某些情况下,各通道的滤波器是相同的(第一行),而在其他情况下,滤波器是不同的(最后一行)。深色方块表示较小或抑制性重量,浅色方块表示较大重量。利用这种直觉,我们可以看到第一行的过滤器检测到从左上角的亮到右下角的暗的渐变。

汇总每个 Conv 图层的要素地图大小

激活图称为特征图,捕捉将过滤器应用于输入的结果,例如输入图像或另一个特征图。可视化特定输入图像的特征图的想法是理解在特征图中检测到或保留了输入的什么特征。期望靠*输入的特征地图检测小的或精细的细节,而靠*模型输出的特征地图捕获更一般的特征。为了探索特性图的可视化,我们需要用于创建激活的 VGG16 模型的输入。

使用 VGG16 汇总每个 conv 图层的要素地图大小

我们需要更清楚地了解每个卷积层输出的特征图的形状和层索引号。因此,我们枚举模型中的所有层,并打印每个卷积层的输出大小或特征图大小以及模型中的层索引。

使用 VGG16 时每个 conv 图层的要素地图大小

可视化输入图像的 VGG16 模型中的第一卷积层的特征图

可视化输入图像的 VGG16 模型中的第一卷积层的特征图

这里,我们设计了一个新模型,它是完整 VGG16 模型中各层的子集。该模型将具有与原始模型相同的输入层,但输出将是给定卷积层的输出,我们知道这将是该层或特征图的激活。加载 VGG 模型后,我们可以定义一个新模型,从第一个卷积层输出特征图。利用该模型进行预测将给出给定输入图像的第一卷积层的特征图。在定义了模型之后,我们需要加载模型期望大小的输入图像,在本例中是 224×224。接下来,图像 PIL 对象需要被转换为像素数据的 NumPy 数组,并从 3D 数组扩展为具有[ 个样本,行,列,通道 ]的维度的 4D 数组,这里我们只有一个样本。然后,需要针对 VGG 模型对像素值进行适当的缩放。我们现在准备好得到特征图。我们可以通过调用 model.predict() 函数并传入准备好的单个图像来轻松实现。我们知道结果将是一个 224x224x64 的特征地图。我们可以将所有 64 幅二维图像绘制成一个 8×8 的正方形图像。

输入图像的 VGG16 模型中第一个卷积层的特征映射

对于给定的图像,

输入图像

可视化 VGG16 模型五个主要区块的特征图

在这里,我们从模型的每个块中一次性收集特征图输出,然后创建每个块的图像。图像中有五个主要块(例如,块 1、块 2 等。)结束于汇集层。每个块中最后一个卷积层的层索引是[2,5,9,13,17]。我们可以定义一个具有多个输出的新模型,每个块中的每个最后卷积层有一个特征映射输出。使用这个新模型进行预测将会产生一个特征图列表。我们知道在更深的层中的特征图的数量(例如深度或通道的数量)比 64 多得多,例如 256 或 512。然而,为了一致性,我们可以将可视化的特征地图的数量限制在 64 个。这里,我们为输入图像的 VGG16 模型中的五个块分别创建五个单独的图。

可视化 VGG16 模型五个主要模块的特征图

运行该示例会产生五个图,显示 VGG16 模型的五个主要模块的特征图。我们可以看到,更接*模型输入的特征映射捕获了图像中的许多精细细节,并且随着我们向模型的更深处前进,特征映射显示的细节越来越少。这种模式是意料之中的,因为模型将图像中的特征抽象成更一般的概念,可用于进行分类。虽然从最终的图像看不出模型看到了一辆汽车,但我们普遍失去了解读这些更深层特征地图的能力。

从 VGG16 模型中的块 1 提取的特征图的可视化

VGG16 模型中从区块 2 提取的特征图的可视化

VGG16 模型中从区块 3 提取的特征图的可视化

VGG16 模型中从区块 4 提取的特征图的可视化

VGG16 模型中从区块 5 提取的特征图的可视化

对于给定的图像,

输入图像

希望您已经获得了一些关于如何在 VGG16 和 VGG19 CNN 模型中提取特征、可视化过滤器和特征图的良好知识。更多精彩文章敬请期待。

从您的三星设备中提取健康数据

原文:https://towardsdatascience.com/extract-health-data-from-your-samsung-96b8a2e31978?source=collection_archive---------4-----------------------

从 Samsung Health 导出和解释健康数据

每次你把手机放在口袋里的时候,健康数据都会被收集。无论是苹果还是安卓,这些手机都配有计步器,可以计算你的步数。因此,记录了健康数据。这些数据可能是一个简单的机器学习或其他一些与健康数据相关的项目的免费数据集市。它是你的,可以免费使用!。让我们看看如何从三星 S-Health 应用程序中导出数据。

从手机导出

三星健康应用程序提供数据下载功能。

  • 打开健康应用程序
  • 打开左侧面板—单击设置轮
  • 找到【下载个人资料】按钮
  • 按照说明(你需要登录)点击下载
  • 您将看到查找您的健康数据的位置

导出健康数据的步骤

这可能是最容易做到的事情。但是,理解数据有点复杂。让我们浏览每个文件及其内容,以了解三星健康应用程序如何存储数据。

导出的数据

您将看到下面一组包含数据的文件。您将看到导出时间戳,而不是T。在文件文件夹中,您会看到个人资料图片。在名为 jsons 的文件夹中,可以找到 CSV 文件中引用的数据的 JSON 对象(在本文中我就不说 JSON 了)。请注意,CSV 文件的数据列还将包含包扩展名 com.samsung.health 。然而,为了文本的简单,当我解释 CSV 文件的内容时,我将忽略它。

**com.samsung.health.device_profile.T.csv  com.samsung.shealth.preferences.T.csv  com.samsung.health.floors_climbed.T.csv  com.samsung.shealth.report.T.csv  com.samsung.health.food_info.T.csv  com.samsung.shealth.rewards.T.csv  com.samsung.health.height.T.csv  com.samsung.shealth.sleep.T.csv  com.samsung.health.sleep_stage.T.csv  com.samsung.shealth.social.leaderboard.T.csv  com.samsung.health.user_profile.T.csv  com.samsung.shealth.social.public_challenge.T.csv  com.samsung.health.water_intake.T.csv  com.samsung.shealth.social.public_challenge.detail.T.csv  com.samsung.health.weight.T.csv  com.samsung.shealth.social.public_challenge.extra.T.csv  com.samsung.shealth.activity.day_summary.T.csv  com.samsung.shealth.social.public_challenge.history.T.csv  com.samsung.shealth.activity.goal.T.csv  com.samsung.shealth.social.public_challenge.leaderboard.T.csv  com.samsung.shealth.activity_level.T.csv  com.samsung.shealth.social.service_status.T.csv  com.samsung.shealth.best_records.T.csv  com.samsung.shealth.stand_day_summary.T.csv  com.samsung.shealth.breathing.T.csv  com.samsung.shealth.step_daily_trend.T.csv  com.samsung.shealth.caloric_balance_goal.T.csv  com.samsung.shealth.stress.T.csv  com.samsung.shealth.calories_burned.details.T.csv  com.samsung.shealth.stress.histogram.T.csv  com.samsung.shealth.exercise.T.csv  com.samsung.shealth.tracker.heart_rate.T.csv  com.samsung.shealth.exercise.weather.T.csv  com.samsung.shealth.tracker.pedometer_day_summary.T.csv  com.samsung.shealth.food_frequent.T.csv  com.samsung.shealth.tracker.pedometer_event.T.csv  com.samsung.shealth.food_goal.T.csv  com.samsung.shealth.tracker.pedometer_recommendation.T.csv  com.samsung.shealth.goal.T.csv  com.samsung.shealth.tracker.pedometer_step_count.T.csv  com.samsung.shealth.goal_history.T.csv  com.samsung.shealth.insight.milestones.T.csv  com.samsung.shealth.permission.T.csv  
jsons
files**

来自传感器的健康数据

照片由埃米利奥·西塞罗Unsplash 上拍摄

这些文件包含来自传感器的数据,包括来自 Galaxy Watch 和手机本身的心率数据和步数。从计步器加速度计传感器收集步数。心率是通过手表中的 PPG(光电容积描记图)传感器来测量的。对于这些数据,您必须查看以下文件。

心率数据

心率数据包含在以下文件中。

**com.samsung.shealth.tracker.heart_rate.T.csv**

该文件中的重要信息是更新时间心率栏。您还可以找到最小值和最大值以及显示录制结束的结束时间

心率信息

出于好奇,我绘制了一张我的心率直方图,看看我的心脏是如何工作的。我的心率似乎在 65-80bp 之间,谷歌搜索的结果是“成年人的正常静息心率在每分钟 60-100 次之间”。我猜直方图是有道理的。当我买手表时,我最关心的一件事就是记录我的心率。因为,通常在医生那里,我有高于*均水*的心率和惊慌失措的人的血压。如果你想了解更多关于医生的情况,请点击这里阅读。

听力比率直方图

步进跟踪器数据

钱德尔 RUnsplash 上拍照

以下文件中提供了步进跟踪器数据;

**com.samsung.shealth.step_daily_trend.202008162231.csv
com.samsung.shealth.tracker.pedometer_step_count.202008162231.csv
com.samsung.shealth.tracker.pedometer_day_summary.202008162231.csv**

每日摘要

步数每日趋势中,您将看到计步数、消耗的卡路里、行走距离和速度的每日数值。但是,在计步器 _ 步数 _ 计数中,您会找到所有步数信息,包括跑步步数、步行步数。基本上,这个文件包含计步器跟踪信息。在最后一个文件(计步器 _ 日 _ 摘要)中,你可以找到每天的步数摘要。这对于大多数任务来说已经足够了。

我们试着对这些数据做一些简单的分析。

步骤计数与日期

上面的观察结果与澳大利亚的季节变化有点一致。在六月到十二月期间,我们有寒冷的温度。从 12 月到 6 月,我们有更好的跑步天气。然而,新冠肺炎在四月和五月开始在坎培拉演出,因此活动量很低。然而,在六月,我和我的妻子散步并试图恢复身材,这样我们就可以在周年纪念日的时候出去吃很多东西。

步数并不是衡量活动的通用指标。一个人可以在健身房锻炼,不用计算步数,但却燃烧了大量脂肪。这种活动通常使用心率传感器通过卡路里来测量。然而,正如你在下面看到的,我的卡路里数和步数多少有些关联(X 轴有一点偏差,但很接*)。这是因为我唯一喜欢的锻炼是跑步或慢跑。

燃烧的卡路里与日期

有趣的东西是可见的。在我跑步的日子里,我没走多少步。相比之下,在步行的日子里,我走了 10000 多步。我想知道,是我走路的时候累了,还是跑步的步数没有计入每天的步数。不过,我将在另一篇文章中对此进行研究。

其他信息

还有更多信息,包括体重和碳水化合物摄入量。为此,您必须手动记录它们。然而,在下面的文件中有一些有见地的数据。

**com.samsung.shealth.exercise.weather.T.csv**

锻炼天气数据

然而,为了使用这个文件,您必须将它与练习文件结合起来。那是另一篇文章!

我希望这篇文章能对你最常丢弃的数据产生有用的结果。快乐阅读!

在 BigQuery 中提取嵌套结构而不交叉连接数据

原文:https://towardsdatascience.com/extract-nested-structs-without-cross-joining-data-in-bigquery-7212b075c542?source=collection_archive---------14-----------------------

分享一个不太常见但非常有用的 BigQuery 标准 SQL 语法的例子

作为一名专注于数据和分析领域的谷歌云顾问,我花了很多时间在 BigQuery 上,这是谷歌云的 Pb 级数据仓库即服务,在很大程度上,我喜欢它。它非常强大,没有基础设施管理,并且具有各种内置的分析和人工智能功能。

但是,由于其列式数据存储的性质,BigQuery SQL 语法有时使用起来并不直观。Google 推荐的查询性能和成本优化的最佳实践是对您的数据进行反规范化,或者换句话说,使用专门的数据类型(如数组和键值存储)将分散在多个表中的数据合并到一个表中。

查询非规范化数据可能比大规模连接数据更高效,但如果你习惯于在规范化的表中处理数据,查询数据就没那么容易了,这是我加入 Cloudbakers 之前的经验。因此,在本文中,我将使用一个与 BigQuery billing export 结构相同的模拟 GCP 计费数据集,介绍 BigQuery 中常见和不常见的非规范化数据结构的查询语法。

基本的结构或键值字段非常简单,因为您可以简单地使用点符号来选择子字段:

-- service is a STRUCT field and id is one of its keys
SELECT service.id AS service_id
FROM   `gcp-sandbox.gcp_billing_demo.gcp_billing_export`
LIMIT  1000

查询结果:使用点符号展*的键值对

当处理数组或重复的字段时,事情变得稍微复杂一点。您可以使用数组索引选择数组的单个组件,如果元素的顺序是预先确定的或者无关紧要,这将非常有用(您可以从下面的前两行结果中看到,在这种情况下,顺序不是预先确定的)。

SELECT credits[OFFSET(0)] as credit_offset_0,
       credits[OFFSET(1)] AS credit_offset_1
FROM   `gcp-sandbox.gcp_billing_demo.gcp_billing_export`
WHERE  ARRAY_LENGTH(credits) > 1

查询结果:按索引选择的数组元素

您还可以选择使用所谓的相关交叉连接来扁*化数据。这将接受任何重复的字段,对其进行透视,以便数组中的每个元素都是一个新行,然后将该新的表格数据与原始表连接,为原始重复字段中的每个元素创建一个具有重复行的扁*模式。

SELECT billing.credits,
       c.*
FROM   `gcp-sandbox.gcp_billing_demo.gcp_billing_export` billing,
       UNNEST(credits) c
WHERE  ARRAY_LENGTH(credits) > 1

查询结果:由相关交叉连接展*的数组

如果您需要展*数据并基于数组中包含的数据计算聚合值或指标,这将非常有用-例如,如果您需要计算 2019 年 12 月开具发票的 GCP 消费的每种信用类型的总信用额,您将使用以下查询:

SELECT   c.name        AS credit_type,
         SUM(c.amount) AS total_credit_amount
FROM     `gcp-sandbox.gcp_billing_demo.gcp_billing_export` billing,
         UNNEST(credits) c
WHERE    billing.invoice.month = '201912'
GROUP BY credit_type
ORDER BY credit_type

查询结果:由相关交叉连接展*并聚集的数组

但是,如果您只是需要对数组数据进行透视,以便它可以被另一个系统使用或导出到 Excel 或 Google Sheets 等电子表格软件中,该怎么办呢?同样,由于其列式数据存储的性质,BigQuery 不容易支持类似于 Pandas 库的 unstack 方法的语法。

作为一个具体的例子,让我们以 BigQuery billing 导出中四个重复字段中的两个为例:

  • 项目标签
  • 资源标签

如果您还不熟悉这个概念,项目资源标签允许您作为一个组织将业务概念和流程应用于 GCP 计算资源。因为应用于您的计算资源的标签会传播到您的计费数据,所以如果您正确且一致地设置标签,您可以按不同的环境、组织部门或计划来分解您的 GCP 成本消耗。您还可以启动一些流程,如向各个部门退款。

长话短说,标签是或应该是你的 GCP 成本管理战略的一个重要方面。这使得 BigQuery billing 导出中的项目标签和资源标签都位于重复的 struct 对象的字段中,或者说是作为键-值对的数组写入表中,这更加令人沮丧。

如果在这种情况下对项目标签进行相关交叉连接,因为成本字段并不包含在项目标签数组中,而信用成本与信用数组中的特定信用类型相关联,所以展*项目标签数据会导致成本字段在每个项目标签中重复一次。如果在资源标签上进行相关交叉连接,情况也是如此。

SELECT project,
       project_labels,
       cost
FROM   `gcp-sandbox.gcp_billing_demo.gcp_billing_export` billing,
       unnest(project.labels) project_labels
WHERE  cost > 1

查询结果:非数组值重复

如果您尝试在这种情况下进行分组和求和,您的 GCP 成本可能会比实际成本高得多,这取决于您对每个项目应用了多少标签。如果您的表中每一行都有一个唯一的标识符,您可以使用它来连接一个除了一个标签之外过滤掉所有标签的扁*数组,并且可以重复这样做来集成每个不同的项目标签。但是计费数据导出没有唯一的行标识符,所以这不是一个真正的选项。那么你能做什么呢?

所有的希望都没有失去,这要感谢来自 Google Cloud 的 Lak Lakshmanan 的这篇文章,它探索了 BigQuery 中一些强大的查询模式。我强烈建议您阅读整篇文章,但特别是有一个组件我发现有助于解决上述计费问题,那就是应用表达式子查询来解包 BigQuery 表中的嵌套结构对象。您可以在下面的示例中看到如何使用此查询语法拆分项目标签数据,从而创建可以在 BigQuery 或其他数据分析系统中轻松处理的表格结果:

SELECT project.labels,
       (
           SELECT value
           FROM   UNNEST(project.labels)
           WHERE  KEY='creator') AS project_creator,
       (
           SELECT value
           FROM   UNNEST(project.labels)
           WHERE  KEY='account') AS project_account,
       cost
FROM   `gcp-sandbox-213315.gcp_billing_demo.gcp_billing_export`
WHERE  array_length(project.labels) > 0
AND    cost > 1

查询结果:使用表达式子查询将嵌套的键值“拆分”到表格数据中

这就是我今天的全部内容——尽管我今天提出的查询不一定非常复杂,但我发现它们很有用(尤其是表达式子查询),希望您也能如此。

用 Python & R 从数据帧中提取行/列

原文:https://towardsdatascience.com/extract-rows-columns-from-a-dataframe-in-python-r-678e5b6743d6?source=collection_archive---------0-----------------------

这里有一个简单的 Python 和 R 数据帧操作的备忘单,以防你像我一样对混合两种语言的命令感到不安。

伊丽莎白·凯在 Unsplash 上的照片

我已经和数据打交道很长时间了。然而,我有时仍然需要谷歌“如何在 Python/R 中从数据帧中提取行/列?”当我从一种语言环境转换到另一种语言环境时。

我很确定我已经这样做了上千次了,但是似乎我的大脑拒绝将这些命令储存在记忆中。

如果你需要同时使用 RPython 进行数据操作,你一定知道我的感受。

因此,我想在本文中总结一下 RPython 在从数据框中提取行/列时的用法,并为需要的人制作一个简单的备忘单图片。

注意,为了并排比较命令行,我将只使用 Python 中的 PandasR 中的基本函数。有些综合库,比如‘dplyr’就不在考虑之列。我正尽力使文章简短。

我们开始吧。

要使用的玩具数据集。

我们将在整篇文章中使用阿伦艾弗森的游戏统计数据玩具数据集。数据帧的尺寸和标题如下所示。

# R
dim(df)
head(df)

r 输出 1

# Python
df.shape
df.head()

Python 输出 1

按位置提取行/列。

首先,让我们用 R 和 Python 从数据框中提取行。在 R 中是通过简单的索引来完成的,但是在 Python 中是通过来完成的。iloc 。让我们看看下面的例子。

# R
## Extract the third row
df[3,]## Extract the first three rows
df[1:3,]
### or ###
df[c(1,2,3),]

这产生了,

r 输出 2

# Python
## Extract the third row
df.iloc[2]
### or ###
df.iloc[2,]
### or ###
df.iloc[2,:]## Extract the first three rows
df.iloc[:3]
### or ###
df.iloc[0:3]
### or ###
df.iloc[0:3,:]

这产生了,

Python 输出 2

请注意,在从数据框中提取单行的示例中,R 中的输出仍然是数据框格式,但是 Python 中的输出是熊猫系列格式。这是 R 和 Python 在从数据框中提取单个行时的本质区别。

类似地,我们可以从数据框中提取列。

# R
## Extract the 5th column
df[,5]## Extract the first 5 columns
df[,1:5]

这产生了,

r 输出 3

# Python
## Extract the 5th column
df.iloc[:,4]## Extract the first 5 columns
df.iloc[:,:5]
### or ###
df.iloc[:,0:5]

这产生了,

Python 输出 3

提取列时,我们必须将冒号和逗号放在方括号内的行位置,这与提取行有很大的不同。

按索引或条件提取行/列。

在我们的数据集中,数据框的行索引和列索引分别是 NBA 赛季和艾弗森的统计数据。我们可以使用它们从数据框中提取特定的行/列。

例如,我们对 1999-2000 年这个季节感兴趣。

# R
## Extract 1999-2000 season.
df["1999-00",]## Extract 1999-2000 and 2001-2002 seasons.
df[c("1999-00","2000-01"),]

这产生了,

r 输出 4

# Python
## Extract 1999-2000 season.
df.loc["1999-00"]## Extract 1999-2000 and 2001-2002 seasons.
df.loc[["1999-00","2000-01"]]

这产生了,

Python 输出 4

请再次注意,在 Python 中,如果我们只提取一行/列,输出是 Pandas Series 格式,但是如果我们提取多行/列,它将是 Pandas DataFrame 格式。

当我们只对列的子集感兴趣时,我们也可以添加列索引。

# R
## Extract Iverson's team and minutes played in the 1999-2000 season.
df["1999-00",c("Tm","MP")]

这产生了,

r 输出 5

# Python
## Extract Iverson's team and minutes played in the 1999-2000 season.
df.loc["1999-00",["Tm","MP"]]

这产生了,

Python 输出 5

除了通过索引提取行/列,我们还可以根据条件进行子集化。比如我们想提取艾弗森上场时间超过 3000 分钟的赛季。

# R
## Extract MP over 3k
df[df$MP > 3000,] ## the comma cannot be omitted

这产生了,

r 输出 6

# Python
## Extract MP over 3k
df.loc[df.MP > 3000,:] ## both the comma and colon can be omitted

这产生了,

Python 输出 6

当然,更复杂的条件可以传递给方括号,它只需要一个 True/False 列表,其长度为数据帧的行号。

比如我们要提取艾弗森真实投篮命中率(TS%)超过 50%,上场时间超过 3000 分钟,位置(Pos)不是得分后卫(SG)就是控卫(PG)的赛季。

# R
## Extract rows with TS.> 50%, MP > 3000 and Pos is SG/PG### define condition as cond_
cond_ = (df$TS. > 0.5) & (df$MP > 3000) & (df$Pos %in% c("SG","PG"))
df[cond_,]

这产生了,

r 输出 7

# Python
## Extract rows with TS.> 50%, MP> 3000 and Pos is SG/PG### define condition as cond_
cond_ = (df["TS."] > 0.5) & (df["MP"] > 3000) & (df["Pos"].isin(["SG","PG"]))df.loc[cond_,:] ## both the comma and colon can be omitted

这产生了,

Python 输出 7

我们可以在“cond_”位置应用任何类型的布尔值。

备忘单图像。

这是一个备忘单,我希望当你像我一样同时使用 Python 和 R 时,它能节省你的时间。

Cheatsheet by 俞峰

就是这样!对 R/Pandas 中的表切片的简单总结。希望有帮助!

感谢您的阅读!如果你喜欢这篇文章,请在 上关注我的 。以下是我之前在数据科学发表的一些文章:

[## Pheatmap 绘制了漂亮的热图

一个关于如何在 r 中用 pheatmap 生成漂亮的热图的教程。

towardsdatascience.com](/pheatmap-draws-pretty-heatmaps-483dab9a3cc) [## 给出了随机森林分类器的特征重要性

如何建立一个随机森林分类器,提取特征重要性,并漂亮地呈现出来。

towardsdatascience.com](/present-the-feature-importance-of-the-random-forest-classifier-99bb042be4cc) [## 使用三种机器学习模型基于勒布朗数据的端到端游戏预测方案

综合指导一个二元分类问题使用三个不同的分类器,包括逻辑…

towardsdatascience.com](/end-to-end-project-of-game-prediction-based-on-lebrons-stats-using-three-machine-learning-models-38c20f49af5f)

照片由科迪板Unsplash 上拍摄

提取、转换、加载(ETL) — AWS 粘合

原文:https://towardsdatascience.com/extract-transform-load-etl-aws-glue-edd383218cfd?source=collection_archive---------15-----------------------

了解如何在 Spark 中对新的 Corona 病毒数据集使用 AWS Glue 进行 ETL 操作

AWS Glue 是一个完全托管的、无服务器的 ETL 服务,可用于为数据分析目的准备和加载数据。该服务可用于对数据进行编目、清理、丰富,并在不同的数据存储之间可靠地移动数据。在本文中,我将解释我们如何使用 AWS Glue 在 Spark 中对新的 Corona 病毒数据集执行 ETL 操作。

本文将涵盖以下主题:

  • 粘合组件。
  • 完成教程作者胶水火花工作。
  • 从 S3 自动气象站提取数据。
  • 使用 Spark 转换数据。
  • 将转换后的数据以拼花格式存储回 S3。

粘合组件

简而言之,AWS 胶水包含以下重要成分:

  • 数据源和数据目标:作为输入提供的数据存储称为数据源,存储转换数据的数据存储称为数据目标。
  • 数据目录:数据目录是 AWS Glue 的中央元数据存储库,在一个地区的所有服务之间共享。这个目录包含表定义、作业定义和其他控制信息,用于管理您的 AWS Glue 环境。
  • 爬虫和分类器:爬虫是从数据存储中检索数据模式的程序(s3)。Crawler 使用自定义或内置分类器来识别数据格式,并填充目录中的元数据表。
  • 数据库和表:每次成功的爬虫运行都会在数据目录中填充一个数据库表。目录中的数据库是一组相关联的表。每个表只有数据的元数据信息,如列名、数据类型定义、分区信息,而实际数据保留在数据存储中。在 ETL 作业运行中,源和目标使用数据库中的一个或多个表。
  • 作业和触发器:执行 ETL 任务的实际业务逻辑。作业由转换脚本、数据源和数据目标组成。我们可以用 python 或 pyspark 来定义我们的工作。作业运行由触发器启动,这些触发器可以由事件计划或触发。

我留下了一些组件,因为它们不在本文的讨论范围之内。关于 AWS Glue 的详细研究,你可以访问官方的开发者指南

在 AWS Glue 上使用 PySpark 的 ETL

现在我们已经了解了 Glue 的不同组成部分,我们现在可以开始讨论如何在 AWS 中创作 Glue 作业,并执行实际的提取、转换和加载(ETL)操作。

新型冠状病毒数据集:

数据集是从 Kaggle 数据集中获得的。我正在使用的版本最后更新于 2020 年 5 月 2 日。该数据集中的主文件是covid_19_data.csv,数据集的详细描述如下。

  • Sno —序列号
  • 观察日期—观察的日期,以年/月/日为单位
  • 省/州-观察的省或州(缺少时可以为空)
  • 国家/地区—观察国
  • 上次更新时间—以 UTC 表示的给定省份或国家/地区的行更新时间。(未标准化,因此请在使用前清洁)
  • 已确认——截至该日期的累计已确认病例数
  • 死亡——截至该日期的累计死亡人数
  • 已恢复—截至该日期已恢复案例的累计数量

1)设置我们的数据存储:

作为开发端到端 ETL 工作的第一步,我们将首先设置我们的数据存储。转到 yout s3 控制台,并在那里创建一个存储桶。我们将使用以下分区方案在 bucket 中上传数据集文件:

s3://bucket-name/dataset/year=<year>/month=<month>/day=<day>/hour=<hour>/

现在我们正在处理单个文件,所以你可以手动创建分区和上传文件,但如果处理大量文件,你可以使用我的 FTP 文件摄取代码,我在我的上一篇文章中解释为你做这项工作。在使用 AWS Athena 时,以这种方式对数据进行分区有助于查询优化。

2)创建 AWS 粘合角色

创建一个 Glue 角色,允许 Glue 访问不同的 AWS 资源,例如 s3。转到 IAM 控制台,添加一个新角色,并将 AWSGlueServiceRole 策略附加到该角色。此策略包含访问 Glue、CloudWatch、EC2、S3 和 IAM 的权限。有关如何为 Glue 设置 IAM 角色的更多细节,请考虑下面的链接

3)设置爬虫来编目数据

执行以下步骤来添加 crawler:

  • 在左侧菜单中,单击数据库并添加一个数据库。

  • 现在去爬虫和一个新的爬虫

  • 选择数据存储

  • 提供 s3 存储桶路径

  • 选择粘合角色

  • 设置按需运行的频率

  • 选择数据库

  • 最后检查并单击“完成”

  • 现在,您的爬虫已经创建好了。单击“运行 Crawler”对数据集进行编目

  • Crawler 可能需要一些时间来对数据进行分类。成功运行后,必须在指定的数据库中创建表

4)为 ETL 工作添加胶合工作

既然我们已经编目了我们的数据集,现在我们可以开始添加一个粘合工作,它将在我们的数据集上完成 ETL 工作。

  • 在左侧菜单中,单击“作业”并添加一个新作业。Glue 可以自动生成一个 python 或 pyspark 脚本,我们可以用它来执行 ETL 操作。然而,在我们的例子中,我们将提供一个新的脚本。

  • 按如下方式设置作业属性

  • 将以下内容保留为默认值

  • 将最大容量设置为 2,作业超时设置为 40 分钟。您设置的 dpu 数量(最大容量)越高,您将承担的成本就越多。

  • 因为我们没有连接到任何 RDBMS,所以我们不必设置任何连接。单击“保存作业并编辑脚本”。

  • 我们将看到以下屏幕。将我的 GitHub 库中的代码复制粘贴到下面的编辑器中,点击保存。现在,单击“运行作业”按钮。

  • 根据工作的不同,执行作业可能需要一段时间(在本例中为 15 到 30 分钟)。到目前为止,胶合作业有至少 10 分钟的冷启动时间,之后作业开始执行。

  • 如果作业执行成功,您将在胶合作业中指定的目标桶中获得拼花格式的聚合结果。

了解 Spark 工作

如果您遵循了上面提到的所有步骤,那么您应该可以通过 AWS Glue 成功执行 ETL 作业。在这一节中,我将深入研究执行实际 ETL 操作的 Spark 代码。

胶水和火花导入和参数

在最顶端,我们有必要的胶水和火花进口。

导入后,我们有几个参数设置。这包括获取作业名、设置 spark 和 glue 上下文、初始化作业、定义目录数据库和表名以及 s3 输出路径。

提取

ETL 操作的“提取”部分除了连接到某个数据存储并从中获取数据之外什么也不做。代码的提取部分执行以下操作:

  • 使用粘附目录中的创建粘附动态框架。已经提供了目录数据库和表名。
  • 创建动态帧后,我们使用 toDF() 方法将其转换为 Spark 数据帧。转换为 spark 数据帧将允许我们使用所有的 spark 转换和动作。

改变

在 ETL 操作的“转换”部分,我们对数据应用不同的转换。代码的转换部分执行以下操作:

  • 首先,我们在 spark 中使用 drop() 方法删除“最后更新”列(没有特殊原因)。
  • 然后使用 spark 中的 dropna() 方法删除任何包含 4 个以上空字段的行。
  • 然后,我们使用 spark 中的 fillna() 方法,用自定义值“na_province_state”填充“province/state”列中缺少的值。
  • 接下来,我们对数据集执行聚合。已经执行了 3 个不同的聚合。我们检查一个国家/地区的哪个省/州有最多的病例、最多的死亡和最多的康复。这是通过使用 groupBy() 方法将记录按省/州和国家/地区列分组,使用 max() 方法将记录与 max(已确认)、max(死亡)和 max(已恢复)列聚合,然后使用 orderBy() 方法将它们按降序排序来完成的。
  • 最后,我们使用 fromDF() 方法将数据帧转换回 Glue DynamicFrame,并将结果保存在 S3 中。它接受三个参数 dataframe、glue 上下文和结果 DynamicFrame 的名称。

加载

在 ETL 操作的加载部分,我们将转换后的数据存储到一些持久存储中,比如 s3。代码的加载部分执行以下操作:

我们使用 DynamicFrame()的 from_options() 方法将结果保存到 s3。该方法采用以下参数:

  • frame :我们要写的 DynamicFrame。
  • connection_type :我们正在写入的目标数据存储,在本例中是 s3。
  • connection_options :这里我们指定目标 s3 路径和数据格式(本例中为 parquet)来保存数据。
  • transformation_ctx :可选的转换上下文。

所有 3 个聚合结果都以拼花格式保存在目标路径上。

摘要

在本文中,我们学习了如何使用 AWS Glue 在 Spark 中进行 ETL 操作。我们学习了如何设置数据源和数据目标,创建爬虫来编目 s3 上的数据,并编写 Glue Spark 作业来执行提取、转换和加载(ETL)操作。

完整的 spark 代码可以在我的 GitHub 资源库中找到:

[## furqanshahid 85-python/AWS-Glue-Pyspark-ETL-Job

该模块对 noval corona 病毒数据集进行统计分析。具体实施如下…

github.com](https://github.com/furqanshahid85-python/AWS-Glue-Pyspark-ETL-Job)

感谢你阅读❤.

利用 Tesseract 和 OpenCV 从 RAOB 软件生成的图像中提取空气稳定指数数据

原文:https://towardsdatascience.com/extracting-air-stability-index-data-from-image-generated-by-raob-software-using-tesseract-and-92eece2d4439?source=collection_archive---------61-----------------------

如何正确裁剪图像以提高立方体性能的说明

作者图片

动机

RAOB 探空仪是气象学家处理高空数据的主要软件。气象学家用它来绘制当地的大气分布图,并获得当地大气的稳定指数,以帮助他们预测天气。大多数情况下,我们需要大量处理这些指数数据,例如,在 30 年内对其进行*均以获得正常值,在地图上绘制(来自多个地方的指数)。问题是,这些指标出现在当地大气剖面图旁边的图像中。所以,你需要记下每一张 RAOB 图像中的每一个索引,然后才能处理它。这是一项非常*凡和令人疲惫的任务。我们需要一个工具来从图像中自动提取这些索引。

宇宙魔方来了

安东Unsplash 上拍照

宇宙魔方是一种光学字符识别工具。使用是将图像中的文本数据提取到文本文件或你需要的任何东西中。你可以在这里找到它。让我们安装并测试它。让我们看看它的性能是否与下图相符。

这是结果

结果很完美!让我们看看它是否能处理真实的 RAOB 图像。我们将使用这个样本图像。

作者图片

结果是

因为它的源图像不是结构化的文本图像,所以很明显这里提取的字符串的结果是混乱的。我们不能把它用于我们的计划。此外,这里有一些被 tesseract 错误识别的字符,并且几乎所有我们想要提取的索引字符串都没有被提取。

每个目标检测/识别算法总是定义其感兴趣区域(RoI) 。如果它的 ROI 是混乱的,那么它被错误识别的可能性就更大。让我们通过使用 tesseract 包装库来看看它的 RoI,这里我们将使用pytesseract。这是代码

结果是

看,它的投资回报率非常混乱。有一些图像不是一个角色,但却成为 RoI-ed。我们要提取的只是这里的这一段(下面红框中的那一段)。

我的猜测是宇宙魔方的性能变得很差是因为在原来的 RAOB 图像中有许多“干扰”。让我们看看,如果我们裁剪图像,只留下下面的索引部分。

让我们用这张图片来看看宇宙魔方的投资回报率。

我们从这张图片中得到的字符串是

还是穷。让我们裁剪图像,只留下一个包含 1 个索引的字符串。

运行宇宙魔方,结果是

当不再有“干扰”时,它终于完美地提取了索引。所以现在我们需要自动裁剪原始图像,只留下每个现有索引的索引字符串。我们做了一个硬代码来自动裁剪图像,但是当图像有微小的变化时,我们必须重新校准代码。让我们做一个更优雅的解决方案。我们将使用相似性度量算法。我们必须提供一个字符串索引的图像样本,并将其与整个原始图像进行匹配,以找到索引字符串的位置。

OpenCV 拯救世界

实际上,我们从一开始就已经使用 OpenCV 来读取图像文件。现在,我们将使用 OpenCV 函数matchTemplate()来匹配我们裁剪的字符串索引,以找到索引值的位置。找到位置后,扩展它的裁剪区域以包含索引值,然后裁剪它并将其提供给宇宙魔方,这样它就可以提取索引值。例如,我们想用这个图像模板提取对流层顶的数据。

在我们找到它的位置后

扩大种植的“面积”

把它输入宇宙魔方,我们就得到了数据。哦,不!我不知道为什么,但是在我们裁剪图像后宇宙魔方不能识别任何字符。可能是因为裁剪图像部分的区域太窄。那为什么之前的裁剪被宇宙魔方成功识别?不知道,那张图片是我用 pinta手动裁剪的。

根据这个猜测,我们添加了一个大的白色画布作为裁剪图像的背景。

让我们用宇宙魔方提取这个图像,结果是

字符串被完全识别。这是我们将用来自动提取 RAOB 图像中的索引数据的算法。对于这个任务,我们将使用pytesseract来提取 RAOB 图像。

从 RAOB 图像中提取索引

这里是提取 RAOB 图像中的索引的完整代码

extract_str()中,我添加了一些代码来清理一些被宇宙魔方错误识别的字符。

让我们用我们的原始图像来试试这个代码。

结果是

很少有错误识别的字符,并且一些索引没有被检测到。总的来说这比我们的第一次尝试要好。

让我们试着用同样的图片,但是不同的是我截屏了 RAOB 的显示,而不是使用从 RAOB 生成的图像。

作者图片

结果是

一样。因此,我们的代码足够持久,可以提取 RAOB 图像中的索引,尽管图像中有细微的差异。此处本帖中我们实验的完整资源库。

收场白

这是我们第一次尝试从图像中提取字符。这远非完美。嗯,也许下次我会用 CNN,用 RAOB 使用的字体训练它。另一篇文章再见。

参考

http://opencv-python-tutro als . readthe docs . io/en/latest/py _ tutorials/py _ img proc/py _ template _ matching/py _ template _ matching . html2020 年 8 月 16 日访问

提取 OpenCV 人脸检测 DNN 模型的系数

原文:https://towardsdatascience.com/extracting-coefficients-of-opencv-face-detection-dnn-model-7f3d944898b9?source=collection_archive---------34-----------------------

图片来自 pixabay.com

最新的 OpenCV 包括一个深度神经网络(DNN)模块,它带有一个很好的预先训练的人脸检测卷积神经网络(CNN)。与 Haar 等传统模型相比,新模型提高了人脸检测性能。用于训练新模型的框架是 Caffe。然而,一些人试图在其他地方使用这种预先训练好的模型时遇到了困难,例如在英特尔的神经计算棒上运行它,将其转换为其他框架中的模型等。原因主要是自模型被训练以来,Caffe 发生了相当大的变化,使得预训练的模型与最新的 Caffe 版本不兼容。在这篇文章中,我将向您展示一种快速简单的方法,通过提取所有预先训练的神经网络系数,将模型移植到最新的 Caffe 中。

基本想法是两个步骤:

1.提取 OpenCV DNN 人脸检测器中所有神经网络层的系数。

2.使用最新的 Caffe 创建新的神经网络,将提取的系数插入其中,并保存新模型。

使用下面的脚本可以完成步骤 1。

在 pickle 文件中卸载每个网络的参数

在上面的脚本中,opencv_face_detector.prototxt是模型配置文件,opencv_face_detector_model.caffemodel是带有训练系数的实际模型文件。详细解释可以在 OpenCV 的官方 Github repo 中找到。

使用下面的脚本可以完成第 2 步。

将参数加载到新咖啡馆

一旦您使用新的咖啡馆保存了模型,它现在就与新的咖啡馆兼容了。

我希望这个小技巧对你们有帮助😄。

从蜘蛛图中提取数据

原文:https://towardsdatascience.com/extracting-data-from-a-spider-graph-99dd12abda4c?source=collection_archive---------44-----------------------

当原始数据只存在于图表中时

通常,当人们发表研究时,他们不会分享原始数据集。通常,这些数据集具有更严格的访问权限。我以前遇到过这个问题,我想重新组织一些数据,所以我做了一个半手工的过程来从发布的图表中提取数据。这个问题出现在一个更复杂的图形上,即蜘蛛图。

咖啡分数显示为一个蜘蛛图。我想从一个有 300 多个咖啡得分的数据集中提取,但是所有的数据都在一个蜘蛛图中。这个数据集是以前由Sweet Maria’s出售的所有咖啡的档案,我通常从他们那里购买我的绿咖啡。他们没有将数据保存在数据库中,我对挖掘这些数据很感兴趣。与编写代码从图表中提取数据相比,我可以用更少的时间手动输入数据,但是我担心会感到无聊和出错。

我在这里解释了如何提取数据并测量每个指标的潜在错误率。我能够得到非常精确的数字,误差在 0.05 以内,所以 8 分的误差在 0.6%左右。

来自https://www . sweet marias . com/Burundi-dry-process-gate Rama-aga hore-6431 . html经他们同意

方法学

我拿起图像,把它编入一个 16 色的小色图。这使得蓝色的数据行很容易分割出来。然后图中的其他线是相似的灰色,我可以把它们分开。我还确保对所有图像使用相同的颜色图,以减少因颜色轻微变化而产生的误差。

作者提供的图片

从环中,我标记了阈值处理后的所有对象。对于每个对象,我填充了对象(在应用了形态学闭合操作之后),并计算了圆的面积。我还确定了该对象是否包含所有对象的整体质心。然后我通过在一个范围(最小尺寸,最大尺寸)内找到那些物体的最大和最小,找到了内环(分数 6 级)和外环(分数 10 级)。

作者提供的图片

使用形态学闭合操作以及随后的骨架操作来稍微修改刻划线。结果是,对于高频点(或大的过渡),该点被稍微*滑,这引入了一些误差。

在这里,我用粉紫色的环和绿色的线标出分数。对于内部和外部对象,使用最佳拟合圆霍夫变换来制作环。

作者图片

利用每个分数的已知程度位置,我使用上面的简单等式来计算每个分数。

数据误差

我计算出总分,并用手记录下了每张唱片的纸杯校正。我计算总分,并将其与我已经手动提取的总分进行比较。该差值除以 10 个指标,如下所示:

作者图片

大多数误差低于 0.1 甚至 0.05,这意味着误差在四舍五入到 1 位有效数字后很可能不会出现。

图像处理工具对于业余爱好类型的任务非常有用,对于从事艺术的人来说,这是一项非常直接的任务。我很高兴我花时间制作了这个提取工具,而不是手动提取数据,因为这更能激发智力,而不一定能节省时间。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。

我的进一步阅读:

咖啡豆脱气

解构咖啡:分割烘焙、研磨和分层以获得更好的浓缩咖啡

浓缩咖啡的预浸:更好的浓缩咖啡的视觉提示

咖啡的形状

搅拌还是旋转:更好的浓缩咖啡体验

香辣浓缩咖啡:热磨,冷捣以获得更好的咖啡

断续浓缩咖啡:提升浓缩咖啡

用纸质过滤器改进浓缩咖啡

浓缩咖啡中咖啡溶解度的初步研究

断奏捣固:不用筛子改进浓缩咖啡

浓缩咖啡模拟:计算机模型的第一步

压力脉动带来更好的浓缩咖啡

咖啡数据表

被盗浓缩咖啡机的故事

浓缩咖啡过滤器分析

便携式浓缩咖啡:指南

使用 Pandas 和 regex 从半结构化推文中提取数据

原文:https://towardsdatascience.com/extracting-data-from-semi-structured-tweets-using-pandas-and-regex-2f293588c1dd?source=collection_archive---------22-----------------------

使用系列字符串函数和正则表达式从文本中提取数字数据

华盛顿州渡口。在 Unsplash 上由奥克拍摄的照片

今天,我们将华盛顿州渡轮推文转化为以小时为单位的等待时间。推文有一些结构,但似乎不是自动化的。目标是转变:

  • Edm/King —埃德蒙兹和金斯敦码头状态—等待 2 小时
  • Edm/King —金斯敦码头状态—等待两小时
  • Edm/King —埃德蒙兹终端状态—等待一小时
  • Edm/King —离开埃德蒙兹的司机无需长时间等待
  • Edm/King —从金斯敦和埃德蒙兹出发需等待一小时

输入特定位置的等待时间(以小时为单位)(例如,埃德蒙兹:2,n/a,1,0,1。金斯敦:2,2,不适用,不适用,1。)

有趣的是,还有一些更不标准的推文:

  • Edm/King —更新—埃德蒙兹和金斯敦码头状态,2 小时 Edm,1 小时 King
  • EDM/King——在金斯敦没有长时间等待——在埃德蒙兹等待一小时,晚班船
  • Edm/King —金斯敦早上 6:25 发车取消。一小时,等等
  • EDM/King——从埃德蒙兹或金斯敦出发不再需要长时间等待
  • Edm/King —埃德蒙兹和金斯敦码头状态—等待 2 小时
  • Edm/King —埃德蒙兹终端状态—等待 90 分钟
  • Ed/Ki —埃德蒙兹等待时间— 60 分钟

您可以看到,这是一个非常特殊的任务,但它可以转移到各种设置,例如 1)操作 Pandas 字符串系列数据,2)使用正则表达式在字符串中搜索目标信息。所以我们去兜兜风吧!

照片由查德·佩尔托拉Unsplash 上拍摄

用熊猫操纵弦系列

在任何清理之前,我的推文实际上(大部分)遵循这样的模式:Edm/King——无论什么——无论什么……有时[没有] WSP 登机牌……链接到华盛顿州轮渡通知页面”。我想删除这些对我当前意图无用的部分,以得到我需要的位置和时间数据。

pandas 通过 Series.str.method()方便地提供了各种字符串处理方法。点击查看总结文档。向上滚动查看更多创意和使用细节。

在这种情况下,我使用了.str.lower().str.strip().str.replace()。注意.str.replace()默认为 regex=True,不像基本的 python 字符串函数。

# changing text to lowercase and removing the url, 
df['tweet_text'] = df['tweet_text'].str.lower()\
                                   .str.replace('https:.*', '')# removing route indicator ('edm/king -'), extra whitespace
df['tweet_text'] = df['tweet_text'].str.replace('edm/king -', '')\
                                   .str.strip()# removing wsp boarding pass indicataor
wsp = ', no wsp boarding pass required|, wsp boarding pass required'
df['tweet_text'] = df['tweet_text'].str.replace(wsp, '')

我还用它将我的列名从['Tweet permalink ',' Tweet text ',' time']修改为['tweet_permalink ',' tweet_text ',' time']

df.columns = df.columns.str.lower().str.replace(‘ ‘, ‘_’)

Jordan SterankaUnsplash 拍摄的照片

使用正则表达式(regex)

正则表达式。包含带有或的()

我想说,如果 tweet.contains('1 '或' 1 '或' 60 分钟'),那么返回 1。

不幸的是,python 字符串没有方法.contains()。您可以使用bool(string.find() +1)来解决这个问题。但是这个不支持正则表达式。所以我的代码应该是这样的:

if (bool(tweet.find('1') +1) or bool(tweet.find('one') +1)
    or bool(tweet.find('60 minute')):

    return 1

取而代之的是正则表达式,我将我的 bool 转换计数减少到 1:

if bool(re.search('1|one|60 minute', tweet)): return 1

请注意,如果您只是检查一个字符串在另一个字符串中,您可以像这样使用基本 python 的in:

if 'one' in tweet:

正则表达式匹配多种方式来表达同一件事

完全披露,这需要一点点的试验和错误为我的情况。在识别出其中包含等待时间的推文后,我想对没有(延长)等待的推文进行适当的分类,并将它们与没有等待时间的推文(“埃德蒙兹码头等待时间标志停止服务”)和碰巧没有等待时间的推文(“金斯敦码头等待时间——一小时”)区分开来。没有 wsp 登机牌”)。

这里你需要在你的文本中寻找模式。我决定使用“no”后跟不确定数量的字符(在正则表达式句点(。)代表任何字符,星号(*)代表任何重复次数),后跟“等待”。

bool(re.search('no.*wait', text))

在评估等待时间之前,我确实切断了非常常见的“[不] wsp 登机牌”和华盛顿州渡轮更新网页的持续链接。这有助于简化文本搜索过程,减少意外匹配导致的错误机会。

额外提示:将多个 csv 加载到单个数据帧中。使用glob获取所有匹配正则表达式路径名的文件。在这种情况下,我需要数据文件夹中以 csv 结尾的所有文件。从那里,您可以读取它们中的每一个(这里有一个元组理解和pd.read_csv(),并使用pd.concat()将它们连接在一起

import globall_files = glob.glob("./data/*.csv")df_from_each_file = (pd.read_csv(f) for f in all_files)
df = pd.concat(df_from_each_file, ignore_index=True)

像往常一样,查看 GitHub repo 中的完整代码。编码快乐!

Unsplash 上由 Lidya Nada 拍摄的照片

从科学论文或图像中提取(数字化)数据

原文:https://towardsdatascience.com/extracting-digitising-data-from-plots-in-scientific-papers-or-images-6e098cb887aa?source=collection_archive---------16-----------------------

西印度群岛进出口图表(1700-1780)——w . play fair。来源: WikiCommons

我们经常看到感兴趣的图形,并希望将数据应用到我们自己的兴趣和设计中。这种情况经常发生在学术界,在学术界,研究需要与科学期刊和数据可视化中已经存在的研究进行比较,在数据可视化中,历史数据可以被建立和改进(通过添加新的数据/设计)。

我们如何提取数据

从图像中提取数据称为数字化。这是将模拟数字转换成量化的数字(数值)格式,用于操作和分析。

最简单的过程是定义一个图中的数据范围,并计算其中一条绘制线上的点的值。为此我们可以利用【WPD】

webplot 数字化仪的使用案例

这可以与从 2D (X-Y)图到条形图,三元和极坐标图的绘图范围。WPD 基于网络的本质意味着它可以在一系列操作系统甚至在线界面上运行。您可以在以下网址获得此信息:

*[https://automeris.io/WebPlotDigitizer/](https://automeris.io/WebPlotDigitizer/)*

在这篇文章中,我们举了一个数字来说明在 1700 年到 1780 年间从西印度群岛的贸易中进口和出口的利润。这是 W. Playfair 手绘的可爱图形。在下面的部分中,我们描述了数字化图形的过程,然后用 python 提供了几个提取数据的快速绘图。

数字化过程

使用 WPD 软件,一般的数字化过程相对简单。算法功能隐藏在后台,用户只需在界面上更改少量“点击”参数。这一过程概述如下:

  1. 点击file > Load Image > select the type of plot并上传您的图像。
  2. 对于x-y图,选择您的边界。首先是最小已知 x 值,然后是最大已知 x 值,接着是最小和最大已知 y 值**
  3. 输入已知点的值,并选择是否使用了log秤(您可以在按下确认按钮后添加额外的配置点。)
  4. 调整设置,如mask(选择要探索的区域)、foreground(线条)和background颜色,以及pixel sampling间隔—注意,有时像素采样间隔内较大的*均区域会产生更好的结果(在示例中使用了 30 个像素)。
  5. 点击算法框内的run

这将产生如下所示的选择。

WebPlotDigitizer 在线界面的屏幕截图。

数据管理

最后,我们可以提取生成的逗号分隔文件(CSV)用于在另一个程序(如 JS、Python、R …)中绘图。python 中使用 pandas 的一个快速示例如下:

:选择出口线。中间:进口和出口的折线图。右侧*:显示两个值之间差异的堆积面积图。*

结论

webplot 数字化仪是非常简单的使用程序,有许多实际应用。它的 HTML 和 javascript 特性使它既能在线运行,也能在大多数流行的操作系统上运行。最后,从出版物中提取数据的能力(尤其是原始数据丢失的出版物)使其成为现代科学家的无价工具。

从 Covid 的新闻中提取特征:时间序列文本数据建模的简单词袋方法|新冠肺炎文章 2

原文:https://towardsdatascience.com/extracting-features-from-covids-news-a-simple-bag-of-words-approach-for-time-series-text-data-bffe59de76a1?source=collection_archive---------52-----------------------

新冠肺炎文字分析

编者注: 走向数据科学 是一份以研究数据科学和机器学习为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

这是我之前博客的续篇,在那里我探索了出现在印度媒体与新冠肺炎相关的新闻文章中的词汇。在本文中,我对文本进行了进一步的探索,并尝试使用词袋(BoW)方法在从文本中提取的特征之间建立显著的相关性。

关于数据源:

关于资料准备和基础探索:

在我之前的博客中记录了这个关于新冠肺炎数据的系列。它使用传统的记号化、词条化和清理过程,使用 nltkStanford CoreNLP

[## 探索印度媒体中关于新冠肺炎的新闻| NLP| Wordcloud |新冠肺炎文章 1

新冠肺炎改变了全球流行语。在本文中,我研究了我的印度新闻文章数据集,内容是关于…

towardsdatascience.com](/exploring-news-about-covid-19-in-indian-media-nlp-wordcloud-covid-19-article-1-2bcbb127dfb3)

背景:我到底想在这里实现什么?

这也是对所产生的时间序列数据的试验性研究,该数据仅由 30 个数据点组成。我的目标是提取诸如每日新闻量、与医疗保健、新冠肺炎和中央政府相关的每日令牌量等特征,并评估它们与 Covid 病例计数之间是否存在任何强相关性。

入门:

1.设置时间序列数据集:

我从维基百科的 excel 文件中提取了 covid 病例和死亡人数数据,并将其读入我的 Jupyter 笔记本。接下来,从我以前的博客中创建的数据集,我通过分组和统计每天发布的新闻数量来提取新闻量,并将它们合并。

代码:

**import** pandas **as** pd**# Read the data in**
df_covid_stats = pd.read_excel('covid_stats.xlsx')
df = pd.read_pickle(text_data_pickle_file_path)**# Group daily and count news volume**
df_news_vol=df[['published_at','title']].groupby(by='published_at')
                                        .count().reset_index()
df_news_vol.columns = ['published_at', 'News Volume']# Merge Covid-19 stats with news volume data
df_merged = pd.merge(df_news_vol, df_covid_stats,
                     left_on='published_at', right_on='Date')
df_merged.head(5)

合并后的数据集如下所示:

合并数据的快照。

2.时间序列图:

然后,我绘制了这些点,以可视化和观察这三十天数据的模式。我不想拘泥于传统的折线图,所以下面是棒棒糖时间序列图的代码。看起来很整洁!!

代码:

**from** matplotlib.lines **import** Line2D
**import** matplotlib.pyplot **as** plt
**import** matplotlib **as** mpl
**import** seaborn **as** sns**# initializing configs**
columns = ['News Volume', 'Total Cases', 'Total Death']
colors = ['black', '#007acc', '#4db8ff']
custom_text = "Some Text"
plt.style.use('seaborn-darkgrid')
fig, ax = plt.subplots(figsize=(16,10), dpi= 80)**# Plot each column using the configs**
for i, column in enumerate(columns):
    ax.vlines(x=df_merged.index, ymin=0, ymax=df_merged[column],
              color='grey', linewidth=1, alpha=0.5)
    ax.scatter(x=df_merged.index, y=df_merged[column], s=75,
               color=colors[i])**# Setting up Title, Label, XTicks and Ylim**
ax.set_title('News Volume, Covid Cases and Deaths', 
             fontdict={'size':22})
ax.set_ylabel('News Volume')
ax.set_xticks(df_merged.index)
ax.set_xticklabels(df_merged.index.date, rotation=60, 
                   fontdict={'horizontalalignment': 'right',
                             'size':12})
ax.set_ylim(bottom=0)**# Setting up Legends** 
legend_elements = [Line2D([0], [0], marker='o', color='black',
                          label='News Volume', markersize=10),
                   Line2D([0], [0], marker='o', color='#007acc',
                          label='Total Cases', markersize=10),
                   Line2D([0], [0], marker='o', color='#4db8ff',
                          label='Total Death', markersize=10)]
ax.legend(handles=legend_elements, loc='upper left'plt.show()

时间序列图:

观察:

很明显,covid 病例数和死亡数在关注期内将呈指数级增长。但是,有趣和令人沮丧的是,新闻文章并没有显示出随着 covid 病例或死亡人数的变化。相反,如果你能发现,在新闻量数据中有三到五天的上升和下降周期模式。此外,在 covid 病例开始时,数量保持上升趋势,这也是一种预期行为。新闻数量随后保持一个均匀的水*,略有下降趋势,不再上升。所以,我们需要更多的数据!这有点道理,除了你可能已经注意到的异常值(我无法修复,因为我在开发计划中),但这个图表肯定会随着时间的推移而改善。

3.定义单词包特征和容量

因此,在这一步中,我直观地收集了一些与 covid、医疗保健和中央政府相关的令牌作为我的 BoW 特征,并循环浏览新闻标题,以获得每个 BoW 组的每篇新闻文章的这些令牌的计数。然后,我将每天的计数进一步分组,并将它们相加,得出我的时间序列特征。

代码:

**# Bag-of-Words**
covid_words_list = ['covid-19','corona', 'coronavirus']
central_government_list = ['government', 'modi', 'pm']
healthcare_list = ['doctor', 'healthcare', 'vaccine', 'cure',  
                   'hospital', 'test', 'testing']**# Iteration Function**
def token_counts(x, words_list):
    title_tokens = x[0]
    if len(words_list) == 1:
        return title_tokens.count(words_list[0])
    elif len(words_list) >1 :
        return sum([title_tokens
                    .count(each_word) for each_word in words_list])
    else:
        raise Exception("Recheck Wordlist")**# Applying lambda function to apply token_counts() on each row** df['Covid Count'] = df.title_cleaned.apply(lambda x: token_counts(x, 
                                                  covid_words_list))
df['Central Gov Count'] = df.title_cleaned.apply(lambda x:   
                           token_counts(x, central_government_list))
df['Healthcare Count'] = df.title_cleaned.apply(lambda x:    
                                   token_counts(x, healthcare_list))df_bow_extended = df[['Covid Count', 'Central Gov Count',   
                      'Healthcare Count','published_at']]
                      .groupby(by='published_at')
                      .sum().reset_index()
df_bow_extended

分组数据:

顺便说一下…

我的弓看起来很简单,不是吗?查看下面的“后续步骤”部分。我将在接下来的博客中为我的弓做一些主题建模,这些博客将会有更多的数据点和标记来实验!

Ayo OgunseindeUnsplash 上拍摄的照片

4.连接完整的数据并绘制时间序列

接下来,我将这些特征与之前的我的时间序列数据集合并,生成了下面的时间序列图,以便直观地寻找模式。这一次,我使用普通的多线图表,以避免不必要的混乱,因为有六条线进行观察。

代码:

plt.close()**# Setting up Configs**
columns = ['News Volume','Total Cases', 'Total Death']
columns_bow = ['Covid Count', 'Healthcare Count', 
               'Central Gov Count']
colors = ['black', '#007acc', '#4db8ff']
colors_bow = ['#cc3300', '#0000e6', '#ff8533']plt.style.use('seaborn-darkgrid') 
fig, ax = plt.subplots(figsize=(15, 10), dpi=100)**# Plotting the Time-Series**
for i, column in enumerate(columns):
    ax.plot('published_at', column, '--', data=df_merged_extended,  
            color=colors[i], alpha=0.5)for i, column in enumerate(columns_bow):
    ax.plot('published_at', column, data=df_merged_extended, 
            color=colors_bow[i], linewidth=2)**# Setting up Title, XTicks, Xlim, Ylim and Legend**
plt.title('Covid Cases and Deaths, News Volume and BOW Features from 
           10th March to 10th April, 2020')
plt.xticks(rotation=45)
plt.ylim(0, 900)
plt.xlim(min(df['published_at']), max(df['published_at']))
# print(ax.get_xlim())
# print(ax.get_ylim())
plt.text(737520.5, 310, 'News Volume', size='medium', color='black')
plt.legend()plt.show()

时间序列图:

观察:

在这一时期,医疗保健和政府话题的参与相当一致。这一趋势并没有显示出 covid 病例和死亡人数有任何特别的变化。Covid 主题和新闻文章量如预期的那样具有良好的相关性。因此,为了证明我们的观察,让我们在下一节中获得相关性。4 月 10 日,所有 BoW 功能均下降,显示 covid 案例数最高。同样,根据我们在数据集中看到的情况,这是意料之中的,因为这似乎是异常值的影响。

5.使用热图评估相关性

为了进行关联,我使用了熊猫的内置。corr()函数使用皮尔逊相关系数(ρ)来测量连续特征之间的线性关系,并返回一个 NxN 矩阵,其中 N =特征数量。您还可以使用我们在下一步中讨论的 Scipy。

。corr()自动跳过了我的 published_at 专栏。因此,在我得到相关矩阵后,我以完整的正方形格式绘制它,因为我喜欢完整正方形的热图,即使我意识到冗余信息的显示。

然而,我包括了其他两种格式的代码——下面的三角形包括和不包括对角线。你可以转置并在 mask_matrix 上得到上面的三角形。

代码:

**# Obtain Correlation**
corr = df_merged_extended.corr()**# Set up plt**
plt.style.use('default')
plt.figure(figsize=[10,10])**# Heat-map 1 : Full Square**sns.heatmap(corr, annot=True, vmin=-1, vmax=1, center=0, 
            square=True, cmap='Spectral', annot_kws={"size": 12}, 
            linewidths=1, linecolor='white')**# Heat-map 2: Lower Triangle excluding diagonal**c=np.zeros_like(corr)
mask_matrix[np.triu_indices_from(mask_matrix)] = True
sns.heatmap(corr, annot=True, vmin=-1, vmax=1, center=0,   
            square=True, cmap='Spectral', mask = mask_matrix)**# Heat-map 3: Lower Triangle including diagonal**mask_matrix=np.zeros_like(corr)
mask_matrix[np.triu_indices_from(mask_matrix)] = True
mask_matrix = 1 - mask_matrix.T
sns.heatmap(corr, annot=True, vmin=-1, vmax=1, center=0,   
            square=True, cmap='Spectral', mask = mask_matrix)**# Set up Title and Text**
plt.title("Heatmap to Assess Correlation between Extracted  
           Features")

热图

观察:

有两个不同集群——

  • 总病例总死亡
  • 船头特写和新闻卷

这些单独的特征组之间确实具有正相关性。这些集群彼此负相关。所以,我想,现在我们需要衡量相关性的可靠程度。此时,我们将我们的零假设公式化为——所有特征都是相互独立的。让我们看看下一步结果如何。

6.p 值和显著性评估

为了评估我们零假设的准确性,我使用了 Scipy 的 pearsonr 函数,该函数返回 Pearson 的相关系数(ρ)以及 p 值。下面是我用来评估的代码。我使用了三个级别的统计显著性评估— .01、. 02 和. 05。让我们看看下面的结果:

**from** scipy.stats **import** pearsonrdef assess_corr(col1, col2):
    r, p = pearsonr(col1, col2)
    return r, pdf_merged_extended.fillna(value=0, inplace=True)
df_merged_extended.set_index('published_at', inplace=True)df_stat_sig = pd.DataFrame(columns=df_merged_extended.columns,  
                           index=df_merged_extended.columns)for col1 in df_merged_extended.columns:
    for col2 in df_merged_extended.columns:
        #print("{} and {}".format(col1, col2))
        r, p = assess_corr(df_merged_extended[col1],
                           df_merged_extended[col2])
        if p < 0.01:
            df_stat_sig[col1][col2] = "{:.3f}".format(p) + "***"
        elif p < 0.02:
            df_stat_sig[col1][col2] = "{:.3f}".format(p) + "**"
        elif p < 0.05:
            df_stat_sig[col1][col2] = "{:.3f}".format(p) + "*"
        else:
            df_stat_sig[col1][col2] = "{:.3f}".format(p)df_stat_sig

输出:

观察:

所有弓形特征都与新闻量 e 强相关,具有小于 0.01 的统计显著性。同总例数总死亡数。所以我们可以拒绝——

  • 新闻计数独立于 Covid 计数、中央政府计数和医疗保健计数
  • 总病例数独立于总死亡数
  • Covid 计数独立于中央政府和医疗保健计数。

我们几乎可以拒绝医疗保健独立于中央政府的观点,尽管风险只有 5%多一点。我希望在下一篇关于这个数据集的时间序列分析的博客中,当我遍历大量数据点时,这一点会被最小化。

下一篇:

万岁!我有一些积极的结果,对这个实验的进展有积极的感觉。但是你有没有注意到在弓的特征定义中真正缺乏思考?如果我做了所有的思考,那么我的代码会做什么呢?

Sherise 拍摄的照片。 on Unsplash

因此,在下一篇博客中,我将研究一些从爱尔兰新闻上收集的数据,并检查一些令牌与印度令牌有何不同。请记住,这些国家在许多方面彼此不同,这将是一项有趣的研究,以了解媒体在第一世界国家和发展中经济体中的相似或不同之处。

我还把数据集扩展到了下个月,所以我有更多的数据可以处理。耶!!!

此外,在即将到来的博客中,我将评估新闻的主题,并将使用这些主题中出现的术语来丰富我的博客。此外,如果代码从同一个数据集创建字典,我就不必担心匹配标记。所以,敬请期待!

关于新冠肺炎文章系列:

这是我用我的新冠肺炎新闻媒体数据集写的第二篇博客,将会写更多关于我的操作和实验的文章。数据集也将增长更多。如果您有兴趣了解这个数据集是如何形成的,请跟我来!这是我以前的博客。

Github 链接到这个博客的笔记本:

[## royn5618/Medium_Blog_Codes

github.com](https://github.com/royn5618/Medium_Blog_Codes/blob/master/Covid-Blog-Codes/Covid-Time-Series-Analysis-Prelim.ipynb)

Github 链接到该数据集上的所有笔记本:

[## royn5618/Medium_Blog_Codes

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/royn5618/Medium_Blog_Codes/tree/master/Covid-Blog-Codes)

我的链接: 中型|LinkedIn|GitHub

感谢光临。我希望你喜欢阅读这篇博客。

从日期中提取特征

原文:https://towardsdatascience.com/extracting-features-from-dates-fbb7f19972fd?source=collection_archive---------36-----------------------

了解如何从熊猫的数据中获取有用的特征。

布鲁克·拉克在 Unsplash 拍摄的照片

一旦你开始使用熊猫,你会注意到日期有它们自己的数据类型。这是非常方便的,你可以用它来排序细胞根据日期和重要的时间序列分析和寻找趋势的数据。日期本身实际上传达了更多的信息,你只要看看简单的时间戳就能想到。

在本文中,您将学习如何从 pandas 的数据对象中提取所有可能的特征。每个特征类型的提取都将通过示例代码详细讨论。阅读完本文后,您将能够提取以下信息:

  • 小时
  • 分钟
  • 一年中的某一天
  • 一年中的第几周
  • 星期几
  • 四分之一

padas 中的日期类型

让我们开始在 pandas 中创建一些数据时间对象。我们可以通过下面的方式使用 pandas date_range 函数来实现。

import datetime
import numpy as np
import pandas as pd

dates = pd.Series(pd.date_range('2019-12-01 1:17', freq='31H15min',  periods=5))
df = pd.DataFrame(dict(date=dates))
df.head()

如您所见,我们创建了一个数据帧,其中有一列名为 date ,我们用五个不同的时间戳填充它。第一个时间戳是 2019 年 1 月 12 日凌晨 1: 17,随后的时间戳使用 freq 参数增加 31 小时 15 分钟。

这足以演示一些简单的特征提取,所以让我们开始吧。

获取年份功能

我们将从获得年份特性开始。这很简单,我们只需在日期列调用日期.年份。请注意,我将把结果保存为数据框中的新列。

df['year'] = df.date.dt.year
df.head()

您可以看到,所有年份功能都保存在“年份”列中,对于所有行,它都等于 2019 年。

获取月份特征

以类似的方式,我们现在将为每一行得到一个月。

df['month'] = df.date.dt.month
df.head()

获取日功能

现在让我们得到这个月中的某一天。

df['day'] = df.date.dt.day
df.head()

获取小时功能

现在让我们从日期开始算一个小时。

df['hour'] = df.date.dt.hour
df.head()

获取细微特征

让我们来看一分钟特写。

df['minutes'] = df.date.dt.minute
df.head()

获取一年中的某一天功能

现在让我们来看看一年中的某一天。请注意,这是一年中的第几天,不同于我们之前提取的一个月中的第几天。

df['day_of_year'] = df.date.dt.dayofyear
df.head()

获取一年中的星期功能

我们可以提取的另一个重要特征是一年中的星期。

df['day_of_year'] = df.date.dt.dayofyear
df.head()

获取星期几功能

获取星期几功能可能是我最喜欢的从数据中提取的功能,因为它允许您进行每周分析,并且许多数据都有每周模式。

df['day_of_week'] = df.date.dt.dayofweek
df['day_of_week_name'] = df.date.dt.weekday_name
df.head()

我们创建了两个列星期几,其中星期几用数字表示(星期一=0,星期日=6 ),以及星期几名称列,其中星期几用字符串形式的星期几名称表示。我喜欢两种形式都有,因为数字形式使数据为机器学习建模做好准备,当我们分析数据时,字符串形式在图形上看起来很好。

另外,请注意,当在 date 上调用 dt.weekday_name 时,它用下划线拼写,这与我们提取的其他特征不同。

获取四分之一特征

我们将提取的最后一个特征是一年中的一个季度。

df['quarter'] = df.date.dt.quarter
df.head()

获得更多功能

上面我们已经介绍了可以从熊猫日期对象中提取的基本特征。我已经把重点放在了最常见的特性上,但是还有更多的特性可以根据您的需要提取出来。

您可以查看 pandas 文档以了解更多信息,但一些附加功能包括:

  • 这一天是工作日还是周末,
  • 今年是不是闰年,
  • 秒、微秒和纳秒
  • 还有更多。

总结

在本文中,您已经学习了如何从 pandas 中的 date 对象获取基本特性,您可以使用这些特性进行探索性的数据分析和建模。现在是时候用在真实数据集上了,所以编码快乐!

最初发表于 aboutdatablog.com: 从熊猫的日期中提取特征,2020 年 3 月 16 日。

PS:我正在 Medium 和上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的* 邮件列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入。***

下面还有一些你可能喜欢的帖子:

** [## python 中的 lambda 函数是什么,为什么你现在就应该开始使用它们

初学者在 python 和 pandas 中开始使用 lambda 函数的快速指南。

towardsdatascience.com](/what-are-lambda-functions-in-python-and-why-you-should-start-using-them-right-now-75ab85655dc6) [## Jupyter 笔记本自动完成

数据科学家的最佳生产力工具,如果您还没有使用它,您应该使用它…

towardsdatascience.com](/jupyter-notebook-autocompletion-f291008c66c) [## 当你开始与图书馆合作时,7 个实用的熊猫提示

解释一些乍一看不那么明显的东西…

towardsdatascience.com](/7-practical-pandas-tips-when-you-start-working-with-the-library-e4a9205eb443)**

使用 PyMuPDF 从 pdf 中提取标题和段落

原文:https://towardsdatascience.com/extracting-headers-and-paragraphs-from-pdf-using-pymupdf-676e8421c467?source=collection_archive---------4-----------------------

制作的动画享受动画

一种从 pdf 文档中解析标题和段落的简单方法

这是完全不同的东西:解析 pdf 文档并提取标题和段落!有各种各样的软件包可以从 pdf 文档中提取文本并将其转换成 HTML,但是我发现这些软件包对于手头的任务来说要么过于复杂,要么过于复杂。根据我的经验,一般的 pdf 解析器对所有文档进行一般化处理,但是对于结构相似的文档的特定用例,我们可以用自己的代码来提高性能!

方法学

由于 pdf 文件由非结构化的文本组成,我们需要在不同的文档中找到一些关于标题和段落如何分隔的相似之处。使用一个关于保险公司的荷兰保单条款的大型 pdf 文件(每个 50-150 页)的小样本,我发现有些一致的是标题和段落通常由文本的字体大小字体粗细分隔,并且最常用的字体可以被认为是段落。现在,这是我们创造方法论的一个很好的起点。

  1. 使用 PyMuPDF 将段落标识为文档中使用最多的字体的文本,将标题标识为比段落样式更大的字体,将下标标识为比段落样式更小的字体。
  2. 为标题、段落和下标创建一个带有 HTML 样式元素标签的字典,比如<h1><p><s0>
  3. 用这些元素<tags>注释文本片段。

识别段落、标题和下标

我们使用 PyMuPDF 包来读取 PDF 文件。该软件包逐页打开 pdf 文档,将其所有内容保存在一个block中,并识别文本sizefontcolourflags。我发现一些 pdf 文档只通过fontsize来区分标题和段落,但是其他的使用所有四个属性。为了说明这一点,我们将添加一个granularity标志,这样我们就可以决定在区分文档中不同的文本部分时包含哪些属性。

在这个阶段,我们将创建一个包含所有不同样式和属性的dictionary和一个包含所有这些样式的[(font_size, count), ..]列表。

我们迭代文档的pagesblocks,由PyMuPDF包(导入为fitz)解析,并根据我们的granularity标志识别所有的样式和属性。

我们的一个文档的输出如下所示:

font_counts, styles = fonts(doc, granularity=False)[('9.5', 1079), ('10.0', 190), ('8.5', 28), ('10.5', 24), ...]{'12.0': {'size': 12.0, 'font': 'ArialMT'}, '9.0': {'size': 9.0, 'font': 'XKZKVH+VAGRoundedStd-Light'}, ...}

我们可以看到最常用的字体大小是9.5,有1079个这样大小的文本。很可能这个字体大小代表了我们文档中的段落。

元素标签字典

接下来,我们将为每种字体大小创建一个包含元素标签的字典。注意,这里我们只考虑字体大小,但是如果你在fonts()函数中使用granularity=True标志,通过几行额外的代码,你可以找到一种方法来合并其他属性!

line 12-13首先,我们确定段落的大小,以区分标签的类型<header><paragraph><subscript>line 16-19我们将大小从高到低排序,以便我们可以向每个元素标签添加正确的整数。注意,我们使用1作为最大的标签,这个数字随着标题和下标的字体大小的减小而减小!我们这样做是因为它与 HTLM 标签的排序方式相同。line 22-32用标签填充字典,如下所示。

{60.0: '<h1>', 59.69924545288086: '<h2>', 36.0: '<h3>', 30.0: '<h4>', 24.0: '<h5>', 20.0: '<h6>', 16.0: '<h7>', 14.0: '<h8>', 13.0: '<h9>', 10.5: '<h10>', 10.0: '<h11>', 9.5: '<p>', 9.452380180358887: '<s1>', 9.404520988464355: '<s2>', 8.5: '<s3>', 8.0: '<s4>', 7.5: '<s5>', 7.0: '<s6>'}

提取标题和段落

我们再次迭代文档的页面和块。对于第一个块,我们用element tag和来自 span s['text']的实际文本初始化block_string。对于接下来的每个区间,我们检查字体size是否与前一个区间的字体size匹配,或者是否有新的文本大小。相应地,如果字符串大小相同,我们就将它们连接起来。blocks是由PyMuPDF包分隔和识别的文本部分,但我发现它们有时包含句子的一部分。因此,为什么我用一个'|'将它们连接起来,以表明一个新的块已经开始。在后处理步骤中,我们可以决定如何处理这些由管道分隔的部分(连接它们或分离它们)。

我们返回一个包含管道的字符串列表,然后能够识别哪些文本部分是标题、段落或下标,如下所示。

['<h4>Als onderdeel van het | ZekerheidsPakket Particulieren |', '', '<h1>Informatie  over  uw|', '<h2>Inboedelverzekering|', '<h1>Basis|', '', '<h6>Inhoud|', '', '<p>pagina| Leeswijzer, Uw verzekering in het kort | 3 | Polisvoorwaarden Inboedelverzekering Basis | 7 |', '', '<s3>3|', '', '<h7>Uw verzekering in het kort|',

正如您所看到的,我们仍然需要执行几个后处理步骤来清理数据,并可能以不同的方式对其进行排序,但这至少是一个起点。我希望你在这里学到了一些东西,并快乐编码!完整的脚本和示例 pdf 文档可以在这里找到。

从文本中提取关键短语:Python 中的 RAKE 和 Gensim

原文:https://towardsdatascience.com/extracting-keyphrases-from-text-rake-and-gensim-in-python-eefd0fad582f?source=collection_archive---------4-----------------------

使用 Python 从大型文本段落中获取关键短语

《华盛顿邮报》称,它*均每天发布 1200 篇故事、图片和视频(不过,这一数字还包括有线故事)。内容真多啊!谁有时间浏览所有的新闻?如果我们能从每篇新闻文章中提取相关的短语,这不是很棒吗?

Romain Vignes 在 Unsplash 上拍摄的照片

关键短语是总结段落要点的一组单词(或词组)。这并不是对文本的总结,它只是文章中讨论的相关概念的列表。

关键短语提取是如何工作的?

  1. 当像“写作”、“书面的”、“写了的”这样的词表示相同的意思:“写”时,将每一个词包括在文章的词汇中是没有意义的。因此,我们对文本进行词汇化,也就是说,首先将每个单词转换成其词根形式。
  2. ****选择潜在短语:文本段落包含许多单词,但并非所有单词都相关。其中大多数可能是经常使用的词,如“a”、“that”、“then”等。这种词称为停用词,必须过滤掉,否则会污染输出。具有上下文相似性的连续单词必须组合在一起。
  3. ****给每个短语打分:一旦你有了一个可能的短语列表,你需要对它们进行排序,以确定哪一个是最重要的。

我们将讨论什么?

在这篇博客中,我们将探索以下关键短语提取算法的 python 实现:

  • 耙子
  • RAKE-NLTK
  • 根西姆

让我们来看一段示例文本,这样我们就可以比较所有算法的输出:

AI Platform Pipelines has two major parts: (1) the infrastructure for deploying and running structured AI workflows that are integrated with [Google Cloud Platform](https://venturebeat.com/2020/03/09/google-launches-machine-images-to-simplify-data-science-workflows/) services and (2) the pipeline tools for building, debugging, and sharing pipelines and components. The service runs on a Google Kubernetes cluster that’s automatically created as a part of the installation process, and it’s accessible via the Cloud AI Platform dashboard. With AI Platform Pipelines, developers specify a pipeline using the Kubeflow Pipelines software development kit (SDK), or by customizing the TensorFlow Extended (TFX) Pipeline template with the TFX SDK. This SDK compiles the pipeline and submits it to the Pipelines REST API server, which stores and schedules the pipeline for execution.

耙子

RAKE 代表快速自动关键词提取。算法本身在 Michael W. Berry 的 文本挖掘应用和理论 一书中有描述。我们在这里只是浏览一下实现,如果你想了解幕后发生了什么,我推荐这个站点

安装:

进口:

停用词:

这里下载这个停用词列表,并将路径保存在一个名为 stop_dir 的变量中。

从文本创建一个耙子对象:

现在,是时候提取关键词了!RAKE 最初并不按照分数的顺序打印关键字。但是它返回分数和提取的关键短语。让我们编写一个快速函数来对这些提取的关键短语和分数进行排序。

将文本段落存储在一个变量中,并将其传递给 rake_object。我们将变量命名为字幕。第一行末尾的 10 意味着我们只提取前 10 个关键字。

答对了。我们完了!分数越高,关键词就越重要。

keywords: [(‘installation process’, 4.0), (‘tensorflow extended’, 4.0), (‘sharing pipelines’, 5.4), (‘google kubernetes cluster’, 9.5), (‘ai platform pipelines’, 10.4), (‘google cloud platform services’, 15.0), (‘cloud ai platform dashboard’, 15.0), (‘pipelines rest api server’, 15.4), (‘running structured ai workflows’, 15.5), (‘kubeflow pipelines software development kit’, 23.4)]

RAKE-NLTK

RAKE-NLTK 是的修改版本,它使用自然语言处理工具包 NLTK 进行一些计算。

安装:

导入,声明一个 RAKE-NLTK 对象并提取! 我们再次提取前 10 个关键词。

下面是使用 RAKE-NLTK 对同一段文本的输出。对于所选择的通道,RAKE 和 RAKE-NLTK 给出相同的输出。但情况并非总是如此。在其他段落中自己尝试一下吧!

[‘kubeflow pipelines software development kit’, ‘running structured ai workflows’, ‘pipelines rest api server’, ‘cloud ai platform dashboard’, ‘google cloud platform services’, ‘ai platform pipelines’, ‘google kubernetes cluster’, ‘two major parts’, ‘sharing pipelines’, ‘tensorflow extended’]

根西姆

在 Gensim Python 和 Cython 中实现,Gensim 是一个用于自然语言处理的开源库,使用现代统计机器学习。

安装:

导入和函数调用:

输出:

pipelines pipeline platform developers development sdk tfx kubernetes

Gensim 中简单的关键字函数调用似乎不执行内置的预处理。

结论

我们学习了如何编写 Python 代码来从文本段落中提取关键字。

以下是一些其他很酷的关键短语提取实现。看看他们!

您可以在所有这些算法上尝试示例文本段落,看看什么最适合您的用例!

发现了不同的关键词提取算法。放在评论里吧!

从 Scikit-Learn 管道中提取和绘制功能名称和重要性

原文:https://towardsdatascience.com/extracting-plotting-feature-names-importance-from-scikit-learn-pipelines-eb5bfa6a31f4?source=collection_archive---------15-----------------------

如何解释您的渠道、模式及其特点

https://unsplash.com/photos/L0oJ4Dlfyuo

如果您曾经承担过生产机器学习模型的任务,您可能知道 Scikit-Learn 库提供了创建生产质量的机器学习工作流的最佳方式之一——如果不是最佳方式的话。生态系统的管道列转换器预处理程序估算器、&、特征选择类是将原始数据转换为模型就绪特征的强大工具。

然而,在任何人让您部署到生产环境之前,您都需要对新模型的工作原理有一些基本的了解。解释黑盒模型如何工作的最常见方式是绘制要素名称和重要性值。如果您曾经尝试过从 ColumnTransformer 处理的异构数据集中提取特性名称,您就会知道这不是一件容易的事情。详尽的互联网搜索只让我注意到其他人问了同样的 问题或提供了部分答案,而不是产生一个全面和令人满意的解决方案。

为了补救这种情况,我开发了一个名为FeatureImportance的类,它将从管道实例中提取特性名称和重要性值。然后,它使用 Plotly 库,仅用几行代码来绘制特性的重要性。在这篇文章中,我将加载一个合适的管道,演示如何使用我的类,然后概述它是如何工作的。完整的代码可以在这里或者这篇博文的末尾找到。

注意:从 scikit-learn 1.0 中的变化开始,我的类可能无法工作。

在继续之前,我应该注意两件事:

  1. 我相信 Joey Gao 在这个帖子中的代码展示了解决这个问题的方法。
  2. 我的帖子假设您以前使用过 Scikit-Learn 和 Pandas,并且熟悉 ColumnTransformer、Pipeline 和预处理类如何促进可再现的特征工程过程。如果您需要复习,请查看这个 Scikit-Learn 示例

创建管道

出于演示的目的,我编写了一个名为 fit_pipeline_ames.py 的脚本。它从 Kaggle 加载 Ames housing 训练数据,并适合中等复杂的管道。我在下面画出了它的视觉表现。

from sklearn import set_config 
from sklearn.utils import estimator_html_repr 
from IPython.core.display import display, HTML 

from fit_pipeline_ames import pipe   # create & fit pipeline
set_config(display='diagram')
display(HTML(estimator_html_repr(pipe)))

这个pipe实例包含以下 4 个步骤:

  1. ColumnTransformer 实例由 3 条管道组成,共包含 4 个 Transformer 实例,包括 category_encoders 包中的 SimpleImputerOneHotEncoder&GLMMEncoder。关于我如何动态构造这个特殊的 ColumnTransformer 的完整解释,请参见我以前的博客文章。
  2. VarianceThreshold 使用默认阈值 0,这将删除任何仅包含单一值的特征。如果一个特征没有变化,一些模型将会失败。
  3. 选择百分位数使用百分位数阈值为 90 的 f_regression 评分函数。这些设置保留了前 90%的功能,而丢弃了后 10%的功能。
  4. 使用前面步骤中创建和选择的特征,将 CatBoostRegressor 模型拟合到SalesPrice因变量。

绘图功能重要性

FeatureImportance的帮助下,我们可以提取特性名称和重要性值,并用 3 行代码绘制出来。

from feature_importance import FeatureImportance
feature_importance = FeatureImportance(pipe)
feature_importance.plot(top_n_features=25)

plot方法接受许多控制绘图显示的参数。最重要的如下:

  • top_n_features:控制将要绘制的特征数量。默认值为 100。该图的标题将显示该值以及总共有多少个特征。要绘制所有特征,只需将top_n_features设置为大于总特征的数字。
  • rank_features:该参数控制是否在特征名称前显示整数等级。默认为True。我发现这有助于解释,尤其是在比较来自多个模型的特性重要性时。
  • max_scale:决定重要性值是否按最大值&乘以 100 进行缩放。默认为True。我发现这提供了一种直观的方式来比较其他特性和最重要的特性的重要性。例如,在上面的图中,我们可以说GrLivArea对模型的重要性是顶部特性OverallQty的 81%。

它是如何工作的

应该使用合适的管道实例来实例化FeatureImportance类。(如果您想将所有诊断打印到您的控制台,您也可以将verbose参数更改为True。)我的类验证这个管道以一个ColumnTransformer实例开始,以一个具有feature_importance_属性的回归或分类模型结束。作为中间步骤,流水线可以有任意数量的或没有来自sk learn . feature _ selection的类实例。

FeatureImportance类由 4 个方法组成。

  1. 是最难设计的方法。它遍历ColumnTransformer转换器,使用hasattr函数来辨别我们正在处理的类的类型,并相应地提取特性名称。(特别注意:如果 ColumnTransformer 包含管道,并且管道中的某个转换器正在添加全新的列,则它必须位于管道的最后。例如,OneHotEncoder,MissingIndicator&simple imputr(add _ indicator = True)将之前不存在的列添加到数据集,因此它们应该在管道中排在最后。)
  2. get_selected_features通话get_feature_names。然后,基于get_support方法的存在,它测试主管道是否包含来自 sklearn.feature_selection 的任何类。如果是,此方法将仅返回选择器类保留的要素名称。它存储未在discarded_features属性中选择的特征。以下是我的管道中的选择器删除的 24 个特性:
feature_importance.discarded_features['BsmtFinSF2','BsmtHalfBath','Alley_Pave','LandContour_Lvl','Utilities_AllPub','Utilities_NoSeWa','LotConfig_Corner','LotConfig_FR2','Condition1_RRNe','Condition2_RRAe','Condition2_RRAn','HouseStyle_SLvl','RoofStyle_Mansard','RoofMatl_ClyTile','RoofMatl_Metal','RoofMatl_Roll','RoofMatl_Tar&Grv','ExterCond_Ex','Foundation_Stone','Foundation_Wood','BsmtFinType2_GLQ','Electrical_missing_value','FireplaceQu_Fa','GarageCond_Gd','MiscFeature_Gar2','SaleType_ConLI']

3.get_feature_importance调用get_selected_features然后创建一个熊猫系列,其中值是来自模型的特征重要性值,其索引是由前两种方法创建的特征名称。然后,该系列被存储在feature_importance属性中。

4.plot调用get_feature_importance并根据规格绘制输出。

密码

这篇博文的原始笔记本可以在这里找到。FeatureImportance的完整代码如下所示,可以在这里找到。

如果你创建了一个你认为应该被支持的管道,但是没有,请提供一个可重复的例子,我会考虑做必要的修改。

请继续关注关于使用 Scikit-Learn ColumnTransformers 和 Pipelines 训练和调整模型的更多帖子。如果你觉得这篇文章有帮助或者有任何改进的想法,请告诉我。谢谢!

在医院环境中从纸质表格中提取交接班数据

原文:https://towardsdatascience.com/extracting-shift-handover-data-from-paper-forms-in-a-hospital-environment-b2fbb23fe585?source=collection_archive---------61-----------------------

图片作者。

背景

在大多数医院的交接班时,会填写一份纸质表格来总结上一次交接班,并强调即将到来的交接班的关键方面。例如,一个完整的表单可能如下所示。

填好的表格样本。图片作者。

这些完成的表格在以后被收集在一起,一个人将仔细检查每一个表格并在计算机上手动输入数据。然后,记录的数据可以输入到分析系统中,以生成见解。

项目的目标

该项目的主要目标是通过构建一个工具来简化数据收集流程,

  • 用户可以使用他们的智能手机给完成的表格拍照,
  • 然后,该工具自动提取数据并预填充表单,并且
  • 用户可以查看和保存数据。

用户可以选择在完成表单后立即拍照并上传,或者在稍后拍摄多个完成的表单。

其他一些功能包括:

  • 提供表格的数字版本,用户可以直接在他们的电话/*板电脑上填写,
  • 保存原始图像和提取的数据,
  • 链接数据,如单位、用户等。到系统中的现有实体。

演示

里贝里,我们建立了一个*台,用于在医院环境中收集数据和生成见解,以及提供临床改进计划。本文只关注使用 OCR 从纸质表单中提取数据——这是数据收集方面的一个特性。

下面是如何从纸质表格中提取数据并输入系统的演示。

OCR 演示。图片作者。

架构概述

我们使用微软的表单识别器服务从表单中提取数据。更具体地说,我们已经训练了一个定制模型,而不是使用预先构建的模型,来更好地处理我们的客户使用的表单的结构。

在非常高的水*上,我们将首先训练一个模型。然后,用户可以通过前端(又名 Riberry)将填写好的表格的照片上传到名为 Rumble 的 API。然后,Rumble 使用经过训练的模型从表单中提取数据,并在将提取的数据发送回用户之前对其进行转换和清理。下图对此过程有更详细的解释。

架构概述。图片作者。

训练模型

注意:本文的重点是展示最终产品,并反思在添加 OCR 支持方面学到的经验,而不是如何使用 Azure Form Recognizer 服务的分步指南。写指南也没有意义;你不可能真的打败他们的文档和例子

如果您想学习如何使用表单识别器服务,我强烈推荐您通读他们的文档—这确实是最有效的方法。

表单识别器服务的核心是一组REST API,允许您通过使用监督/非监督机器学习来训练模型,管理(例如,列出、删除、复制)模型,以及使用定制/预构建的模型提取数据。

此外,它还提供了一个开源工具(OCR-Form-Tools) ,它可以与这些 REST APIs 进行交互,并提供一个直观的 UI 来标记您的数据,训练模型并通过预测测试文档来验证模型。

提示:在他们关于设置样品贴标工具的指南中,他们谈到了通过 Docker 运行该工具。

比起使用 Docker,我发现从 GitHub 中取出一份工具并从源代码中构建/运行它要容易得多。

在工具启动并运行之后,我能够轻松地标记我们的样本数据、训练模型和测试模型。

标记训练数据。图片作者。

训练一个模特。图片作者。

验证训练好的模型。图片作者。

杂项反思

现在项目已经部署到生产中,这是一个很好的时间来回顾它,反思我从做这件事中学到的各种事情/教训。

1.培训过程

使用监督学习方法预测表单内容应该有三个主要阶段,

  1. 检测表单上的文本元素(打印的或手写的)并计算它们的预期大小和位置,
  2. 从每个元素中提取实际的文本内容,
  3. 使用步骤 1 中获得的元素大小和位置信息,将元素分类到指定的不同标签中。

提示:通过监督学习,我们正在拟合一个模型,根据页面上元素的位置信息将页面上的元素分类到不同的标签中。

我们 不是 训练任何 NLP 模型从页面上识别的元素中提取文本。这一部分由表单识别器服务在内部处理。

每个文本元素的位置和大小由其由 8 个数字组成的边界框来表示。并且这 8 个数字应该是每个训练实例即每个文本元素的主要特征。

还可能有许多数据论证和特征操作技术应用于训练数据,以人工扩展数据集,从而提高模型的准确性。例如,他们可能会使用一些保留标签的变换技术,如去噪/锐化、弹性变形、仿射变换、降维等。

但总的来说,成本函数应该相对简单,只有几个变量。对于只需要 5 个文档就可以开始使用,我并不感到惊讶。

2.添加对复选框/单选问题的支持

表单识别器服务并不正式支持复选框或单选按钮,但是我已经能够很容易地绕过它,

  • 为复选框或单选问题中的每个选项应用标签,以及
  • 在预测时,将这些带有值的标签视为用户选择的选项。

例如,医院使用的表单包含一个带有两个选项的复选框问题— AM 或 PM。在训练过程中,我分别为 AM 和 PM 选项设置了标签_Shift.9:00_Shift.17:00(见下文)。

添加对复选框/单选问题的支持。图片作者。

假设,如果我们将上面的表单输入到训练好的模型中,将为_Shift.9:00_Shift.17:00提取一个字符串‘x’。如果这是一个复选框问题,我会认为两个选项都被选中,如果这是一个单选问题,我会认为第一个选项被选中。

3.异步提取数据,并在结果就绪时通知用户

向其端点发送表单并从中提取数据之后,您将获得一个Operation-Location,这是一个包含[resultId](https://westus2.dev.cognitive.microsoft.com/docs/services/form-recognizer-api-v2/operations/AnalyzeWithCustomForm)的 URL,用于跟踪进度并获得分析操作的结果。我们要反复检查这个结果数据的 URL。

提示:我将检查结果的频率设置为每秒一次。这似乎与他们的 OCR 工具用于检查结果的频率相同。

提示:如果您的用户必须等待结果才能采取下一步行动,请在发布图像进行分析之前对其进行压缩,以缩短等待时间。

如今智能手机上拍摄的图像相当大,我将它们压缩到 4.1 背景

纸质表单上的字段与数字表单上的字段并不完全匹配——纸质表单上的一些数据被忽略,而网络表单上有一些额外的字段。此外,虽然纸质表格很少改变,但我们会通过添加/删除问题或围绕现有问题移动来稍微更新数字表格。

4.2 我们如何设计它

web 表单上的问题及其布局是使用 JSON 文件定义的。不涉及细节,在下面的截图中,JSON 结构(右)定义了表单的团队部分(左)。

在 JSON 中定义问题。图片作者。

但是,我们也使用 JSON 文件中问题的名称来自动构造该问题的标签(在 OCR 中使用)。例如,在下面的截图中,标签— 团队..护士简写——“护士简写”问题是通过用一个点连接其所有祖先和自身的名字而创建的。

来自问题名称的标签。图片作者。

4.3 设计问题

这意味着,每当我们更改表格的数字版本时(例如,添加/删除问题或重新排列表格上的字段),都会生成一组新的标签。我们必须重新命名表单识别器中使用的标签,重新训练模型,将其复制到生产环境中等等。这是一个非常耗时的过程。

4.4 我们应该做什么而不是做什么

我们应该将标签生成从 form.gggg 的 JSON 定义中分离出来

假设纸质表单很少改变,我们应该硬编码一组标签用于表单识别器服务。然后,我们可以扩展 JSON 定义以包含一个label属性,该属性指定每个问题所使用的标签(如果适用的话)。

这不仅简化了绑定数据的代码(即,将提取的数据转换为域对象),还意味着我们可以自由地重新排列表单上的问题,而不必在表单识别器中重新训练模型。

参考

表单识别器 API (v2.0)

表单识别器文档

OCR 表单工具

设置样品标签工具

使用 Python 从视频中提取语音

原文:https://towardsdatascience.com/extracting-speech-from-video-using-python-f0ec7e312d38?source=collection_archive---------1-----------------------

使用 Google 语音识别 API 的简单实用项目

雅各布·欧文斯在 Unsplash 上的照片

在这篇文章中,我将向你展示如何从视频文件中提取演讲。在识别演讲之后,我们将把它们转换成文本文档。这将是一个简单的机器学习项目,这将有助于你理解谷歌语音识别库的一些基础知识。语音识别是机器学习概念下的一个热门话题。语音识别越来越多地用于许多领域。例如,我们在网飞节目或 YouTube 视频中看到的字幕大多是由使用人工智能的机器创建的。其他语音识别器的伟大例子是个人语音助手,如谷歌的 Home Mini,亚马逊 Alexa,苹果的 Siri。

目录:

  • 入门
  • 第一步:导入库
  • 第二步:视频转音频
  • 第三步:语音识别
  • 最后一步:导出结果

照片由亚历山大·佩莱斯Unsplash 拍摄

入门指南

正如你可以理解的标题,我们将需要这个项目的视频记录。它甚至可以是你对着镜头说话的录音。使用名为 MoviePy,的库,我们将从视频记录中提取音频。下一步,我们将使用谷歌的语音识别库将音频文件转换成文本。如果您准备好了,让我们从安装库开始吧!

图书馆

我们将为这个项目使用两个库:

  • 语音识别
  • 电影

在将它们导入到我们的项目文件之前,我们必须安装它们。在 python 中安装模块库非常容易。您甚至可以在一行代码中安装几个库。在您的终端窗口中写下下面一行:

pip install SpeechRecognition moviepy

是的,就是它。 SpeechRecognition 模块支持多种识别 API,Google Speech API 就是其中之一。你可以从这里了解更多关于这个模块的信息。

MoviePy 是一个可以读写所有最常见的音频和视频格式的库,包括 GIF。如果您在安装 moviepy 库时遇到问题,请尝试安装 ffmpeg。Ffmpeg 是一个领先的多媒体框架,能够解码、编码、转码、复用、解复用、流式传输、过滤和播放人类和机器创造的几乎任何东西。

现在,我们应该开始在代码编辑器中编写代码了。我们将从导入库开始。

步骤 1-导入库

import speech_recognition as sr import moviepy.editor as mp

是的,这就是我们完成任务所需要的。抓紧时间,让我们进入下一步。

步骤 2 —视频到音频转换

在这一步,我们将做一些很酷的事情,将我们的视频记录转换成音频文件。视频格式有很多种,其中一些可以列举如下:

  • MP4 (mp4、m4a、m4v、f4v、f4a、m4b、m4r、f4b、mov)
  • 3GP (3gp、3gpp2、3g2、3gpp、3gpp 2)
  • OGG (ogg、oga、ogv、ogx)
  • WMV (wmv、wma、asf*)

我们应该知道我们的视频格式做转换没有任何问题。除了视频格式,了解一些音频格式也是一个很好的练习。以下是其中的一些:

  • MP3 文件
  • 加气混凝土
  • WMA
  • AC3(杜比数字)

现在,我们对这两种格式都有了一些了解。是时候使用 MoviePy 库进行转换了。你不会相信这有多容易。

clip = mp.VideoFileClip(r”video_recording.mov”) 

clip.audio.write_audiofile(r”converted.wav”)

我建议转换成 wav 格式。它与语音识别库配合得很好,这将在下一步中介绍。

[## 用 Python 构建语音识别器

使用谷歌云语音 API 将您的音频文件转换为文本

towardsdatascience.com](/building-a-speech-recognizer-in-python-2dad733949b4)

步骤 3 —语音识别

首先,让我们定义识别器。

r = sr.Recognizer()

现在让我们导入在上一步(步骤 2)中创建的音频文件。

audio = sr.AudioFile("converted.wav")

完美!最棒的部分来了,就是识别音频文件中的语音。识别器将尝试理解语音并将其转换为文本格式。

with audio as source:
  audio_file = r.record(source)result = r.recognize_google(audio_file)

最后一步—导出结果

干得好!艰苦的工作完成了。在这一步中,我们将把识别的语音导出到一个文本文档中。这将有助于你储存你的作品。我还添加了一个打印(“准备!”)结束代码。以便我们知道文件何时准备好,工作何时完成。

# exporting the result 
with open('recognized.txt',mode ='w') as file: 
   file.write("Recognized Speech:") 
   file.write("\n") 
   file.write(result) 
   print("ready!")

视频演示

刚刚开始我在 YouTube 上的旅程,我将为您演示机器学习、数据科学、人工智能和更多项目。尽情享受吧!

[## 加入我的介绍链接媒体-贝希克居文

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

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

恭喜你。你已经创建了一个程序,将视频转换成音频文件,然后从该音频中提取语音。最后,将识别的语音导出到文本文档中。希望你喜欢阅读这篇文章并参与这个项目。如果你今天学到了新东西,我很高兴。从事像这样的动手编程项目是提高编码技能的最好方式。

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

关注我的博客了解数据科学以获得灵感。

相关内容:

[## 用 5 行代码将文本转换成语音

了解文本到语音转换可以发挥作用的领域

towardsdatascience.com](/convert-text-to-speech-in-5-lines-of-code-1c67b12f4729) [## Python 中的简单人脸检测

如何使用 OpenCV 库检测图像中的人脸

towardsdatascience.com](/simple-face-detection-in-python-1fcda0ea648e)

Camelot 让从 pdf 中提取表格数据变得简单。

原文:https://towardsdatascience.com/extracting-tabular-data-from-pdfs-made-easy-with-camelot-80c13967cc88?source=collection_archive---------4-----------------------

从 pdf 中提取表格并不困难。

丹尼·米勒在 Unsplash 上的照片

从 pdf 中提取表格数据很难。但更大的问题是,许多公开数据都是 PDF 文件。这些公开数据对于分析和获得重要见解至关重要。然而,访问这样的数据成为一个挑战。例如,让我们看看由[国家农业统计局(NASS)](http://by the National Agricultural Statistics Service (NASS),) 发布的一份重要报告,它涉及美国种植的主要农作物:

报告来源:https://www . NASS . USDA . gov/Publications/Todays _ Reports/Reports/pspl 0320 . pdf

对于任何分析,起点都应该是获取包含详细信息的表格,并将其转换为大多数可用工具都能接受的格式。正如你在上面看到的,在这种情况下,简单的复制粘贴是行不通的。大多数情况下,标题不在正确的位置,一些数字会丢失。这使得 pdf 处理起来有些棘手,显然,这是有原因的。我们将讨论这个问题,但首先让我们试着理解 PDF 文件的概念。

这篇文章是寻找合适数据集的完整系列文章的一部分。以下是该系列中包含的所有文章:

第 1 部分 : 为数据分析任务获取数据集—高级谷歌搜索

第 2 部分 : 为数据分析任务寻找数据集的有用站点

第三部分 : 为深度学习项目创建定制图像数据集

第 4 部分 : 毫不费力地将 HTML 表格导入 Google Sheets

第 5 部分 : 用 Camelot 从 pdf 中提取表格数据变得很容易。

第六部分 : 从 XML 文件中提取信息到熊猫数据帧

第 7 部分 : 5 个真实世界数据集,用于磨练您的探索性数据分析技能

可移植文档格式,又名 pdf

来源: [Adobe PDF 文件图标](http://Adobe Systems CMetalCore)

PDF 代表可移植文档格式。这是 Adobe 在 90 年代早期创建的一种文件格式。它基于 PostScript 语言,通常用于呈现和共享文档。开发 PDF 背后的想法是要有一种格式,使得在任何现代打印机上查看、显示和打印文档成为可能。

每个 PDF 文件都封装了一个固定布局*面文档的完整描述,包括文本、字体、矢量图形、光栅图像以及其他显示*维基百科 所需的信息。*

基本 PDF 文件包含以下元素。

来源:GUILLAUME ENDIGNOUX 的 PDF 语法简介

为什么从 PDF 中提取表格很难?

如果你看上面的 PDF 布局,你会发现其中没有表格的概念。PDF 包含将字符放置在二维*面的 x,y 坐标上的指令,不保留单词、句子或表格的知识。

来源:https://www . PDF scripting . com/public/PDF-Page-coordinates . cfm

那么 PDF 如何区分单词和句子呢?通过将字符放在一起来模拟单词,而通过将单词放在相对更远的位置来模拟句子。下图将更具体地巩固这一概念:

来源:http://www.unixuser.org/~euske/python/pdfminer/index.html

m 表示上图中两个字之间的距离, W 表示两个字之间的间距。任何带有空格的文本块被组合成一个。表格是通过在没有任何行或列信息的电子表格中输入单词来模拟的。因此,这使得从 pdf 中提取数据用于分析变得非常困难。然而,政府报告、文档等形式的大量公开数据。,以 pdf 格式发布。一种能够提取信息而不影响其质量的工具是当前需要的。这一点将我们带到了一个名为 Camelot 的多功能库,它被创建来从 pdf 中提取表格信息。

卡米洛特:人类 PDF 表格提取

来源:https://camelot-py.readthedocs.io/en/master/

Camelot 的名字来源于著名的 Camelot 项目,它是一个开源的 Python 库,可以帮助您轻松地从 pdf 中提取表格。它建立在另一个用于 PDF 文档的文本提取工具 pdfminer 之上。

它附带了许多有用的功能,例如:

  • 可配置性— 适用于大多数情况,但也可以进行配置
  • 使用 Matplotlib 库进行可视化调试
  • 输出有多种格式,包括 CSV、JSON、Excel、HTML,甚至 Pandas dataframe。
  • 开源 -麻省理工学院许可
  • 详细的文档

装置

您可以通过 conda、pip 或直接从源代码安装 Camelot。如果您使用 pip,不要忘记安装以下依赖项: TkinterGhostscript

*#conda (easiest way)
$ conda install -c conda-forge camelot-py#pip after [installing the tk and ghostscript dependencies](https://camelot-py.readthedocs.io/en/master/user/install-deps.html#install-deps)
$ pip install "camelot-py[cv]"*

工作

在我们开始工作之前,最好先了解一下到底发生了什么。通常,Camelot 使用两种解析方法来提取表:

  • Stream :查找单词之间的空格来识别表格。
  • 点阵:寻找页面上的线条来识别表格。默认使用 点阵

你可以在文档中读到更多关于卡梅洛特的工作。

使用

现在让我们进入激动人心的部分——从 pdf 中提取表格。在这里,我使用了一个 PDF 文件,其中包含了印度 2015-16 年成人教育项目受益人数的信息。PDF 看起来像这样:

来源:https://www . mhrd . gov . in/sites/upload _ files/mhrd/files/statistics-new/ESAG-2018 . pdf

我们将从导入库和读入 PDF 文件开始,如下所示:

*import camelot
tables = camelot.read_pdf('schools.pdf')*

我们得到一个TableList对象,这是一个由[**Table**](https://camelot-py.readthedocs.io/en/master/api.html#camelot.core.Table)对象组成的列表。

*tables
--------------
<TableList n=2>*

我们可以看到已经检测到两个表,通过它的索引可以很容易地访问这两个表。让我们访问第二个表,即包含更多信息的表,并查看其形状:

*tables[1] #indexing starts from 0<Table shape=(28, 4)>*

接下来,让我们打印解析报告,它是表的提取质量的指示:

*tables[1].parsing_report{'accuracy': 100.0, 'whitespace': 44.64, 'order': 2, 'page': 1}*

它显示了高达 100%的准确性,这意味着提取是完美的。我们也可以如下访问表格的数据框架:

*tables[1].df.head()*

作者将 PDF 提取到 Dataframe |图像中

整个表格也可以提取为 CSV 文件,如下所示:

*tables.export('table.csv')*

作者导出为 CSV |图像的 PDF 表格

可视化调试

此外,您还可以根据指定的种类绘制 PDF 页面上的元素,如‘text’, ‘grid’, ‘contour’, ‘line’, ‘joint’等。这些对于调试和使用不同的参数来获得最佳输出非常有用。

*camelot.plot(tables[1],kind=<specify the kind>)*

在 PDF 页面上找到的绘图元素|作者图片

高级用法和 CLI

Camelot 也有一个命令行界面。它还配备了一系列高级功能,如:

  • 读取加密的 pdf
  • 阅读旋转的 pdf
  • 当默认结果不完美时调整参数。指定精确的表格边界,指定列分隔符,等等。你可以在这里阅读更多关于这些功能的信息

缺点

Camelot 只能处理基于文本的 pdf,不能处理扫描的文档。因此,如果你有扫描文件,你必须看看其他一些替代品。

⚔️神剑——网络界面:蛋糕上的糖衣

Camelot 的另一个有趣的特性是,它也有一个名为 Excalibur 的 web 界面,供那些不想编码但仍想使用该库特性的人使用。让我们快速看看如何使用它。

装置

安装 Ghostscript 后,使用 pip 安装 Excalibur:

*$ pip install excalibur-py* 

然后使用以下命令启动 web 服务器:

*$ excalibur webserver*

然后,您可以导航到本地主机来访问该界面。下面的视频演示了整个过程:

Excalibur 演示|作者视频

结论

在上面的文章中,我们研究了 Camelot——这是一个开源 python 库,对于从 pdf 中提取表格数据非常有帮助。事实上,它有许多可以调整的参数,这使得它具有很好的可伸缩性,并适用于许多情况。Web 界面为寻找无代码环境的人们提供了一个极好的选择。总的来说,它似乎是一个有用的工具,可以帮助减少通常用于数据提取的时间。

参考

这篇文章的灵感来自 Vinayak Mehta 的演讲,vinay AKMehta 是 2019 印度 PyCon 上卡米洛特项目的创建者和维护者。一些资源摘自活动结束后公开分享的幻灯片。强烈建议观看演示以获得更清晰的内容。

利用自然语言处理从期刊论文中提取分类数据

原文:https://towardsdatascience.com/extracting-taxonomic-data-from-a-journal-articles-using-natural-language-processing-ab794d048da9?source=collection_archive---------38-----------------------

从期刊文章中提取科学用语的快速方法

澳大利亚阿德莱德州立图书馆。图片来源:弗拉德·库特波夫@ Unsplash

我最*遇到了一个客户的问题,他们希望从一篇 PDF 格式的期刊文章中提取所有的“科学词汇和名称”以及作者姓名和大学。虽然可以一个字一个字地浏览文章,并将其与分类名称列表进行比较,但这对于一篇期刊文章来说极其麻烦,尤其低效。相反,我使用自然语言处理的常用元素来确定期刊文章中的科学术语/分类数据。下面是一个教程,介绍如何从期刊文章 PDF 中提取文本,准备进行处理,并最终使用 Python libraries for NLP 从文章中获取分类或科学数据列表。

要加载的包

为此,我使用了 PyPDF、NLTK、pandas、scikit-learn 和 re。您需要 pip 安装这些包,特别是对于 NLTK,您需要通过使用 nltk.download('stopwords ')和 nltk.download('word_tokenize ')下载 stopwords 和 word_tokenize。

从期刊文章中提取文本

我将使用我随机选择的这篇期刊文章来浏览这个例子。有许多关于如何做到这一点的好文章,所以请随意查阅,但我是用 PyPDF2 做的。使用 PyPDF2 读取所有页面后,我将结果写入一个 txt 文件并处理。txt 文件。

清理用于分析的文本

现在我们有了要处理的语料库,我们必须做一些清理工作。使用正则表达式,我删除了数字、停用词、少于 3 个字符的单词和标点符号。我还定制了一个停用词表,删除那些“科学”但对我的分析没有特别启发性的词。运行代码后,可以修改该列表,删除可能没有用的额外单词。

使用 TFIDF 进行标记和提取

我们利用了上面定义的清理函数,并对清理后的输出进行了标记化(拆分成单个单词)。之后,我们得到了二元模型(词对)和三元模型(词三元组),然后对它们进行了矢量化。在矢量化之后,我们使用 TFIDF 来提取有可能成为重要科学词汇的单词。输出遵循代码。

虽然我们看到一些不相关的短语(如前所述),但这是论文中科学用语的一个很好的摘录。

结论

这篇文章展示了一种从发表的文章中提取科学信息的快速方法。对于特定的论文,可以对您的代码进行一些定制,以删除额外的短语。整个脚本可以在我的 Github 库这里找到。

使用 Pytesseract & Open CV 从扫描的 PDF 中提取文本

原文:https://towardsdatascience.com/extracting-text-from-scanned-pdf-using-pytesseract-open-cv-cd670ee38052?source=collection_archive---------0-----------------------

使用 Python 和其他开源库的文档智能

从发票的数字副本中提取信息的过程可能是一项棘手的任务。市场上有各种工具可以用来完成这项任务。然而,有许多因素导致大多数人希望使用开源库来解决这个问题。

几天前,我遇到了一个类似的问题,我想和你分享我解决这个问题的所有方法。我用来开发这个解决方案的库是 pdf2image (用于将 pdf 转换成图像)、OpenCV (用于图像预处理),最后是用于 OCR 的pytesserac以及 Python

将 PDF 转换为图像

pdf2image 是一个 python 库,它使用 pdftoppm 库将 pdf 转换为一系列 PIL 图像对象。以下命令可用于使用 pip 安装方法安装 pdf2image 库。

pip 安装 pdf2image

注意:pdf2image 使用的 Poppler 是基于 xpdf-3.0 代码库的 pdf 渲染库,没有它就无法工作。有关 Poppler 的下载和安装说明,请参考以下资源。

https://anaconda.org/conda-forge/poppler

https://stack overflow . com/questions/18381713/how-to-install-poppler-on-windows

安装后,任何 pdf 可以转换成图像使用以下代码。

使用 Python 将 PDF 转换为图像

将 PDF 转换为图像后,下一步是突出显示我们必须从中提取信息的图像区域。

注意:在标记区域之前,请确保您已经对图像进行了预处理以提高其质量(DPI ≥ 300,应调整偏斜度、锐度和亮度、阈值等。)

标记用于信息提取的图像区域

在这一步中,我们将标记图像中需要提取数据的区域。在用矩形标记了这些区域之后,我们将从原始图像中一个接一个地裁剪这些区域,然后将它们提供给 OCR 引擎。

我们大多数人都会想到这一点——为什么我们要在进行 OCR 之前标记图像中的区域,而不是直接进行呢?

这个问题的简单答案是你可以

此问题的唯一问题是,有时文档中嵌入了隐藏的换行符/分页符,如果此文档直接传递到 OCR 引擎,数据的连续性会自动中断(因为 OCR 会识别换行符)。

通过这种方法,我们可以对任何给定的文档获得最大的正确结果。在我们的例子中,我们将尝试使用完全相同的方法从发票中提取信息。

以下代码可用于标记图像中感兴趣的区域,并获得它们各自的坐标。

用于标记图像中感兴趣区域的 Python 代码

原始图像(来源:Abbyy OCR 工具示例发票图像)

图像中标记的感兴趣区域(来源:Abbyy OCR 工具样本发票图像)

对图像应用光学字符识别

一旦我们标记了感兴趣的区域(以及相应的坐标),我们就可以简单地裁剪特定区域的原始图像,并通过 pytesseract 来获得结果。

对于那些不熟悉 Python 和 OCR 的人来说,pytesseract 可能是一个让人不知所措的词。根据它的官方网站-

Python-tesseract 是谷歌的 Tesseract-OCR 引擎的包装器。它作为 tesseract 的独立调用脚本也很有用,因为它可以读取 Pillow 和 Leptonica 图像库支持的所有图像类型,包括 jpeg、png、gif、bmp、tiff 等。此外,如果用作脚本,Python-tesseract 将打印识别的文本,而不是将其写入文件。

另外,如果你想玩玩 pytesseract 的配置参数,我建议你先浏览下面的链接。

[## 宇宙魔方

Python-tesseract 是 Python 的光学字符识别(OCR)工具。也就是说,它会识别并“读取”…

pypi.org](https://pypi.org/project/pytesseract/) [## Pytesseract OCR 多个配置选项

感谢贡献一个堆栈溢出的答案!请务必回答问题。提供详细信息并分享…

stackoverflow.com](https://stackoverflow.com/questions/44619077/pytesseract-ocr-multiple-config-options)

以下代码可用于执行此任务。

裁剪图像,然后执行 OCR

裁剪后的图像-1 来自原始图像(来源:Abbyy OCR 工具示例发票图像)

OCR 的输出:

Payment:

Mr. John Doe

Green Street 15, Office 4
1234 Vermut

New Caledonia

裁剪后的图像-2 来自原始图像(来源:Abbyy OCR 工具示例发票图像)

OCR 输出

COMPLETE OVERHAUL 1 5500.00 5500.00 220
REFRESHING COMPLETE CASE 1 380.00 380.00 220
AND RHODIUM BATH

如你所见,我们输出的准确率是 100%。

所以这一切都是关于如何开发一个从复杂文档(比如发票)中提取数据的解决方案。

OCR 在文档智能方面有许多应用。使用 pytesseract,无论文档的格式如何(无论是扫描的文档、pdf 还是简单的 jpeg 图像),都可以提取几乎所有的数据。

此外,由于它是开源的,所以整个解决方案既灵活又不昂贵。

基于 DOM 分割和 BERT 的新闻故事作者抽取

原文:https://towardsdatascience.com/extracting-the-author-of-news-stories-with-dom-based-segmentation-and-bert-69225ea0e5c2?source=collection_archive---------22-----------------------

如何利用 Web2Text 的 HTML 特征生成框架和 HuggingFace Transformers 进行海量内容提取

获得大量新闻故事的作者是令人生畏的。网页有不同的格式,一个完美的解决方案应该在所有情况下,当可用时,识别作者的全名。作者的名字有时会出现在标题的正下方,但有时会出现在文章的下方,或者几乎完全隐藏在不同的栏目中。作者的名字可能出现在的任何一种语言中,可能有也可能没有助词在里面,比如英语介词 by 。在某些情况下,有一个以上的作者,名字用逗号-和- 分隔。

基于试探法的解析器,也就是说,使用正则表达式和 bash 脚本来处理条件,在很多情况下都可以很好地工作。然而,一个好的解决方案应该推广到看不见的格式。例如,一些文章在文档中有给定名称的列表(链接到网站上的其他文章或其他元素),这可能会产生歧义。

众所周知,分类器非常适合内容提取任务,因为它们可以查看多个上下文和布局特征。

这篇来自卫报的文章在左栏有作者。字符串在巴黎指的是记者写文章的地点,而不是名字的一部分。

瑞典小报 Aftonbladet 上的一篇新闻文章,通讯作者在左边。瑞典语中, av 放在作者姓名前,类似于英语中的 by。注意到第二列有一些名字(哈里王子梅根汗·马克尔等等。),这可能会被误认为是文章的作者。这个标题也包含了一个名字( Prins Phillip ),同样不是作者。

获取培训示例

我使用了 Andrew Thompson 的All News数据集(其中有来自 15 家美国出版物的 73,000 篇文章,带有 URL 和作者)。新闻文章的时间跨度为 2015 年至 2017 年。Archive.org以其原始格式存储了大约 27000 篇新闻文章,其他的都在他们原来的新闻网站上。抓取所有链接大概花了三天时间(4.1 GB 压缩数据)。

因为报纸每隔一段时间就会改变他们的网站结构,所以语料库涵盖的不同案例的数量是未知的(但可以说是很少的)。收集和手动标记其他新闻渠道的更多培训示例以涵盖更多案例应该相当容易。

概观

流水线包含三个步骤:一个预处理器,一个分类器,以及命名实体识别

端到端作者提取器管道

预处理程序

我使用了论文web 2 text:Deep Structured Boilerplate Removal(Github repo)中的预处理器。

Web2Text 可以为兼容和不兼容的 HTML 构建一个 DOM 树。它有逻辑来清理已知包含非信息数据的 DOM 节点,向下遍历 DOM 树并折叠单个子节点及其各自的子节点。

(来源:Web2Text)

该模型的训练示例是 HTML 文件的 DOM 节点。每个 HTML 文件*均有 138 个 DOM 节点。因此,该数据集总共包含 m = 73K * 138 = 101M 个训练示例。*均而言,代码需要 127 毫秒将每个 HTML 文件转换为 CSV 特征表示文件,其中每行代表一个特征,每列是一个 DOM 节点(运行在 1.7GHz 双核 i7 和 8GB DDR3 内存上)。

主类ExtractPageFeatures将一个原始 HTML 文件作为输入,并生成一个 CSV 文件,该文件具有去除样板文件的功能。我修改了这段代码,并创建了更适合作者提取任务的新特性。编译 Scala 项目后,您可以在任何 HTML 文件上运行:

> ./extract_page_features.sh  <input_html_file>

让我们以数据集中的一个文本为例:

算法通过路由header -> div -> div -> h2 / a到达令牌政治 (8 个字符)。注意<h2><a>是如何折叠成一片叶子的。

对于每个折叠的 DOM (CDOM)节点,Web2Text 构建一个特征向量:

Web2Text 允许您将 CDOM 树输出到 HTML 文件中,以便您可以看到每个节点的特征。

Web2Text 附带了一组 128 个预定义的特性:

Web2Text 的开箱即用特性(来源:Web2Text)

功能存在于以下级别:

  • 叶子
  • 父母
  • 祖父或祖母

预处理器使用对后代特征进行求和(对整数),或者使用 (对布尔值)来计算祖先级特征(父级、祖父级或根级)。例如,如果有两个兄弟节点,一个有电子邮件地址,另一个没有,预处理器会将公共父节点标记为包含电子邮件。

在作者提取任务中使用祖先级别的数据捕获功能非常方便,因为在许多新闻网站中,作者姓名和出版日期(有时还有作者的社交媒体资料)被小方框包围。该信息可以帮助分类器学习识别哪些块包含作者。

在这个来自纽约时报的例子中,预处理器将包含作者的节点标记为在祖先层有一个 T21 日期字段。

特征工程

作者提取任务用一些额外的特性扩展了 Web2Text(出于性能原因,仅当2<=nWords<=5时才运行检查):

  • contains_popular_name:如果 CDOM 节点包含 1880-2008 年期间美国每年 1000 个最常见婴儿名字的数据集中的一个名字,则为真。在任何一年,它涵盖了美国 80%的男孩和 67%的女孩的名字(68k 的重复数据删除记录)。(注意:这一部分使用了字符串比较。这个特性的一个更好的解决方案将涉及单词嵌入或者可能是 BERT 或它的后继者)。
  • contains_author_particle:如果 CDOM 节点包含粒子 byand,则为真。
  • contains_author_url:如果节点包含格式为http[s]://[something]/author/[something的 URL,则为真。许多报纸都包含一个链接,链接到一个包含作者传记的页面,或者一个包含同一作者的其他文章的页面,并带有这种格式的链接。

我很兴奋地得知我可以使用 Web2Text 的一些标准特性来捕获与我的任务相关的信息:

  • contains_two_capitalized_words:包含至少两个大写单词(无名氏无名氏* ) (Web2Text 的特性b20b21b22)*
  • at_least_two_words:包含至少两个单词(由 Web2Text 特征b5捕获)
  • contains_date:合理距离内的节点包含日期。这是由父级或祖父级的contains_year特性(b19)捕获的。

扩展该模型的一些非常有趣的特性是:

  • 呈现的 HTML 字体大小
  • 祖先节点包含到社交媒体的链接
  • number_of_sibling_nodes:同胞 CDOM 叶数。捕捉名称可以是链接列表的一部分的事实,如前面看到的 Aftonbladet 的例子。
  • 确定文章使用的语言,因为该模型依赖于大写字母、英语日期格式和一系列英语名字。

分类

Web2Text 的架构使用卷积神经网络,然后是隐藏马尔可夫模型,分别计算块和相邻块对上的一元和成对势。然而,在我们的例子中,我们希望每页最多找到一个包含作者姓名的块,所以我将这个问题构建为一个包含两个类的二进制分类器:{contains_author, not_contains_author},并选择了最小化二进制交叉熵损失的块。实际模型是一个简单的神经网络 (1 个隐含层;140 个隐藏单元)

分类结果

超参数

分析的 HTML 文件数量:15000【717414训练示例(DOM 节点)历元:50;批量大小:* 50 档;学习率:0.0001;辍学率:0.2;培训/开发/测试分割 : 60%/20%/20%。*

关键指标

准确率:99.93%;精度:91.30%;召回:95.40%;F1-得分:* 93.31%。*

培训时间: 8.3 小时

混淆矩阵

/public/trained_model_all_the_news/,训练模型的权重存储在我们的存储库中。

推理

该模型在推理期间执行两个步骤:

1.-对 HTML 文档运行训练好的神经网络,选择代价最小的 DOM 块。

2.-运行一个 BERT 命名实体识别器,从块中提取所有人名。这个模型使用 HuggingFace Transformer 对 BERT (Large,cased)链接到模型 的实现,并将一个句子中的每个标记标记为属于四种类型: PersonMISCOrganizationLocation ,使用标准的 IOB 格式。对于作者提取任务,只有人名(PER标签)是相关的。该模型使用用于命名实体识别的标准数据集 CoNLL-2003 ⁵数据集进行微调。

最后,您可以运行以下命令来预测新闻文章的作者姓名:

*> ./inference_from_url.sh [https://www.theguardian.com/us-news/2016/jul/13/alton-sterling-son-cameron-protesters-baton-rouge](https://www.theguardian.com/us-news/2016/jul/13/alton-sterling-son-cameron-protesters-baton-rouge)The Author Name is: Jessica Glenza.*

贮藏室ˌ仓库

https://github.com/canetcesc/AuthorExtractor

参考

1沃格尔斯、加内亚和埃克霍夫。" Web2text:深度结构化样板去除(2018)欧洲信息检索会议。斯普林格,查姆。

2周和马舒克。"通过机器学习进行网页内容抽取(2014)斯坦福大学

3姚和左。网页内容提取的一种机器学习方法(2013)S坦福德大学

4 J. Devlin、M.W. Chang、K. Lee 和 K. Toutanova。" Bert:用于语言理解的深度双向变换器的预训练(2018)arXiv 预印本 arXiv:1810.04805* 。*

[5]桑和德默德。CoNLL-2003 共享任务介绍:独立于语言的命名实体识别(2003)arXiv 预印本 cs/0306050* 。*

感谢

非常感谢催眠师为这篇文章提供了想法。Hypefactors 是一个面向媒体专业人士的*台,其管道中的一个组件是识别每天数百万篇新闻文章的作者。这篇文章是由他们的真实业务需求所激发的,尽管实现可能有所不同。

剪贴画由工作室提供。

用 Python 为非程序员提取网页信息

原文:https://towardsdatascience.com/extracting-webpage-information-with-python-for-non-programmer-1ab4be2bb812?source=collection_archive---------16-----------------------

基本编程必备

用一些基本的数据挖掘技能来增强自己的能力

图片由 Isaac QuesadaUnsplash 上拍摄

知道如何使用脚本从网页中提取数据是很有帮助的。我发现最简单的方法是在 lxml 库的帮助下使用 Python。

最好的部分是,你可能不需要在你的机器上做。你可以把你的脚本放到 Python 在线编译器上,然后你得到一些数据。

对于一些简单的东西,我们只需要在一个文件中的几行代码,然后它会做非常酷的事情。

下面举几个例子。

[## 如何在 Excel 中分析您的中型合作伙伴计划数据

在简单的图形中寻找模式

medium.com](https://medium.com/better-marketing/export-personal-medium-partner-program-data-into-excel-spreadsheet-8887cb4d4442) [## 如何在媒体上找到你们的相互联系

使用 Python 脚本和指令,不需要任何编码知识

medium.com](https://medium.com/better-programming/how-to-find-your-mutual-connections-on-medium-d0c586c04e6f)

学习网站

为了使学习更加相关,我们将把 Wordometer 冠状病毒网页作为我们的来源。

如果你访问这个页面,你会看到类似下面的内容。我将学习分成 4 个部分,我称之为练习,如下所示。

我已经提供了代码脚本(只有 70 行),借此复制粘贴并运行它(在在线编译器中),你会看到下面的内容

并选择每个数字来执行它。这应该会使学习更容易。

HTML 的基础

所有网页都是用 HTML 构建的。

让我们来看看 HTML 最基本的结构,因为这是我们提取所需信息时需要认识的基本模式。

我能提供的最基本的结构如下。

  1. 它们都是由包裹着<>tag组成。而且它通常带有一个对它的补充,即</tag>,或者它只是在tag中以/>结尾。
  2. <tag>中,它可能有一个或多个被命名的attribute。这有助于区分同类型的tag
  3. <tag>对周围,我们可以有一个(或多个)标签被包裹在里面,我在上面将其命名为<sub-tag>。你可以成像,sub-tag可以有 sub-sub-tag等等…,它构成了 HTML 的大部分。
  4. 有时,tag可以用一个text包围它,这通常构成了我们要寻找的信息的核心。

就是这样!给自己拍一下。您已经掌握了 HTML(以及 XML)结构🎉

第一件事:在 HTML 中阅读

在提取 HTML 信息之前,我们需要让我们的脚本先读取 HTML。有两种方法可以做到这一点。

1.直接从网站读取和加载 HTML

我们使用 Python 的请求库。别担心,就像下面这条线一样简单,然后就搞定了。

import requests

之后,尝试使用下面的代码获取网站内容。

response = requests.get(url)

为了更加健壮,万一url出错或者网站关闭,我添加了以下内容

try:
  response = requests.get(url)
except:
  print ('Sorry bad url') 
  sys.exit(2)if response.status_code != 200:
  print ('Sorry invalid response ' + str(response.status_code))
  sys.exit(2)

如果请求加载成功,那么您可以使用下面的代码获取 Html 内容,并将其提取到一个中。

tree = html.fromstring(response.text)

之所以称之为树,是因为如果我们画出标签关系,它们看起来就像一棵树。

HTML 标签树

2.将 HTML 保存在文件中并从中读取

有时这是需要的,因为一些网页需要凭证登录,因此从脚本访问它会更复杂,因为您需要提供所需的凭证。

但是因为你只需要从 HTML 中提取一些数据,你可以把它保存为一个。html 文件,并获取从中读取的脚本。

之后,在您的 python 脚本中,您只需要

  1. 打开文件,并将其作为一个字符串(一组字母)读取。
  2. 读出 HTML 内容,形成一个
inputFile = open(inputfile,"r") 
fileContent = str(inputFile.readlines())tree = html.fromstring(fileContent)

准备提取数据!

1 提取单 **tag** 包裹 **text** 简单回顾一下,在练习 1 中,我们要提取如下所示的国家名称。

如果我们检查它的 HTML 代码,我们会看到下面的模式。

<a class=”mt_a” href=”country/spain/”>Spain</a>

为了提取Spain,我们只需要识别具有"mt_a"的属性classa标签。

为了提取,我们只需对使用xpath函数。

extracteditems = tree.xpath(‘//a[[@class](http://twitter.com/class)=”mt_a”]/text()’)
print("\n".join(extracteditems))

我们将得到一个列表,在这里我们用一个新行(即"\n")将它们分开,并打印出来。

我们会得到

USA
Spain
Russia
UK
Italy
... and many more ...

轻松点。

2 抽取 **tag** **sub-tag** 包裹 **text** 。简单回顾一下,在练习 2 中,我们要提取每个国家的人口信息。

如果我们检查它的 HTML 代码,我们会看到下面的模式。

<td style=”font-weight: bold; text-align:right”>
   <a href=”/world-population/spain-population/”>46,752,556</a> 
</td><td style=”font-weight: bold; text-align:right”>2,467,761</td>
<td style=”font-weight: bold; text-align:right”>52,783</td>

我们无法获得 <a href=”/world-population/spain-population/”>,因为每个国家的href会有所不同。

我们也不能捕获<td style=”font-weight: bold; text-align:right”>,因为上面显示了许多我们不想要的其他数字(例如2,467,761)。

因此,最好是捕获后面跟有<a>标签的<td style=”font-weight: bold; text-align:right”>

为了提取,我们只对使用xpath函数。

extracteditems = tree.xpath(
    '//td[[@style](http://twitter.com/style)="font-weight: bold; text-align:right"]//a/text()')print("\n".join(extracteditems))

我们将得到一个列表,在这里我们用一个新行(即"\n")将它们分开,并打印出来。

330,758,784
46,752,556
145,926,781
67,841,324
60,472,650
... and many more ...

轻松点。

3 **tag** 中提取 **attrib** 值。简单回顾一下,在练习 3 中,我们想要提取网站的图片 URL。

在 HTML 中,图像 URL 存储为img标签的src属性。

<img src="/img/alert-plus.png" style="height:16px; width:16px" />

要提取它,我们首先需要先提取img元素,然后使用下面的特殊提取,即list(map(lambda ...))来提取每个src属性,即x.attrib.get(‘src’)

x是每个elements内的一个单项。

elements = tree.xpath(‘//img’)
extracteditems = list(map(lambda x: x.attrib.get(‘src’), elements))
print(“\n”.join(extracteditems))

由此,我们现在可以得到

/img/worldometers-logo.gif
/images/alert.png
/img/alert-plus.png
... and a few others ...

list(map(lambda ...))上有点复杂,但这是一种提取元素列表中各个项目的方法。

4 迭代每个 **tag** 来提取 **sub-tags** 简单回顾一下,在练习 4 中,我们想要提取每个大洲的高级数字

更具体地说,当我们进入其中一个大陆时,值如下所示,这就是我们要提取的内容。

如果我们查看 HTML,每个大洲的数据都用具有"total_row_world row_continnet"class属性的tr分组。

<tr class="total_row_world row_continent" data-continent="Europe" style="display: none">
  <td></td>
  <td style="text-align:left;"><nobr>Europe</nobr></td>    
  <td>1,741,129</td>
  <td></td>
  <td>160,482</td>
  <td></td>
  <td>739,811</td>
  <td>840,836</td>
  <td>12,196</td>
  <td></td>
  <td></td>
  <td></td>
  <td></td>
  <td></td>
  <td style="display:none;" data-continent="Europe">Europe</td>
</tr>

让我们提取"total_row_world row_continnet"作为信息段。

为了进一步提取每个部分中的每一项,我们创建了一个单独的函数名extractElements,如下所示。我们发送x,它是各个部分中的每个部分。

sections = tree.xpath(
    '//tr[[@class](http://twitter.com/class)="total_row_world row_continent"]')extracteditems = list(map(lambda x: 
    '\"' + str(**extractElements(x)**) + '\"', sections))print("\n".join(extracteditems))

现在在函数extractElements中,我们使用findall提取出所有的td标签,并再次使用list(map(lambda ...))单独提取它的text

def extractElements(element):
    return list(map(lambda x: x.text, element.findall('.//td')))

输出如下所示。

就是这样!

为了进一步说明element.findall(‘.//td’)是如何工作,我使用了一个 for 循环来单独打印每个提取的

def extractElements(element):
 **for item in element.findall('.//td'):
    print('  EXTRACTED: ' + str(item.text))**return list(map(lambda x: x.text, element.findall('.//td')))

输出如下所示

EXTRACTED: 1,741,129
EXTRACTED: +22,456
EXTRACTED: 160,482
EXTRACTED: +1,414
EXTRACTED: 739,811
... and more ...
EXTRACTED: Europe
EXTRACTED: None
EXTRACTED:

学会了这四种方法,你现在就有了探索你感兴趣的网站并提取相关信息进行进一步处理的基本要素。🛠

干杯。

感谢阅读。你可以在这里查看我的其他话题。

您可以在**Twitter脸书Reddit 上关注我,了解关于移动开发、媒体写作等相关主题的小技巧和学习。Elye****

从非结构化文本中提取越南地址数据

原文:https://towardsdatascience.com/extraction-of-vietnam-address-data-from-the-unstructured-text-150fe8cb0045?source=collection_archive---------36-----------------------

如今,社交网络和电子商务是我们生活的重要组成部分。我们在这些*台上买卖很多东西,越南也不例外。

丹尼尔·伯纳德在 Unsplash 上的照片

介绍

如今,社交网络和电子商务是我们生活的重要组成部分。我们在这些*台上买卖很多东西,越南也不例外;在这个人口超过 9400 万的国家,脸书(Messenger)和 Zalo 是两个最大的社交网络。除此之外,很多商家利用这些*台卖各种东西。所以聊天应用是沟通自己想买的商品的主要渠道,比如价格、保质期、收货人地址、电话号码、什么时候送到(Ahamove 和 GHN 是越最大的送货公司)等等因此,在 Ahamove,我们开发了一个应用程序,可以快速帮助商家发现买家信息,如地址和电话号码。我们面临两个挑战:

  • 如何快速提取非结构化文本的地址数据?
  • 当这些文本通常没有结构、发音符号或拼写错误时,我们如何检测它们呢?

这些问题以及我们如何解决它们将在下面的章节中介绍。

1.消息中的越南语

首先,越南语是一种严重依赖发音符号的语言。这些许多音调符号,通常在同一个元音上有两个,使得书面越南语很容易在拉丁字母的本地化变体中识别出来。有 9 个区别符号,例如一个急性符号(dấu sắc),一个坟墓符号(dấu huyền),一个扬抑符号(dấu),一个短音符(dấu ớ),一个喇叭符号(ư或ơ),一个上面的钩子符号(dấu hỏi),一个波浪符号(dấu ng),一个下面的符号(d\u n\ng),一个染料符号——类似于{\或{\。

在理想的世界中,使用拉丁语发音符号的任何语言的人都可以轻松地排版他们的语言,并产生高质量的排版。

维克多·高尔特尼

然而,当我们互相发信息时,我们可以用或不用发音符号来发信息,但对方可以很好地理解。例如,我们可以传达这样的信息:

Giao hàng cho em đến 285 đường Cách mạng tháng Tám, Phường 12, Quận 10, Hồ Chí Minh nha
// English: Can you deliver it to 285 Cách mạng tháng Tám street, Ward 12, District 10, Hồ Chí Minh city for me, please.

如果我们传达这样的信息是没问题的:

Giao hang cho em den 285 duong cach mang thang tam phuong 12 quan 10 ho chi minh nha

越南所有有文化的人都能理解,没有任何困难。

其次,人们通常倾向于在对话中使用缩写。他们通常会将上述信息缩写成以下具有相同含义的例子:

gh cho e den 285 duong cmtt, p12, q10, hcm nha
gh cho e den 285 cmt8, p.12, q10, tp.hcm nha
gh cho em den 285 d.cmt8, p12, q.10, tp hcm nha

第三,他们可以使用错误的发音标记位置,他们也理解得很好。例如,当我们发信息时,意思是一样的,但是如果你做越南语听写测试,你的分数是 F;D

đường == đừơng
Trường Trinh == Trừơng Trinh

最后,当他们一起传递信息时,客户的信息通常不遵循越南语的结构。意思是文本没有主语+动词+宾语这样的结构。例如,当他们点东西时,对话通常是这样的:

Merchant: Cho mình xin địa chỉ và số điện thoại của bạn với.
//English: Could you give me your address and phone number, please?Customer: 285 cmt8, p.12, q10 09028388xx3
//or more harder structure like
Customer: 285 09028388xx3 cmt8 p12 q10

总之,在聊天应用程序中有许多不同的方式来发送消息。其中一些不容易被统计模型预测或在两个同义词之间进行比较。要解决这个问题,我们首先需要弄清楚越南的地址结构。在下一节中,我们将对此进行更多的解释。

我们存档的结果。作者图片

2.越南地址结构

如上所述,我们只关注越南地址,但也有可能发展到其他国家和语言。越南的行政单位分为四级。在第一层,越南分为 58 个省和 5 个直辖市。直辖市是最高级别的中央控制城市,拥有与省同等的特殊地位。直辖市分为市区、镇、农村区作为二级单位。之后,城市地区被划分为选区,城镇被划分为选区和公社,而农村地区被划分为乡镇和公社。最后,最后一层单元是村落、村庄和社区。有许多层单元,但我们只用一个单元来代表每个层单元。

  1. 一线:城市
  2. 二线:县
  3. 第三层:地区

我们绕过了第四层,因为我们通常不在地址中使用它,我们也找不到任何关于第四层的知识来源。

越南地址结构。作者图片

首先,地点单位有三种可能的后缀:街道名称、国家名称和城市/省份名称。在地点单位之后,我们通常用一个地区名、县名和市/省名,以便区分两个区/县或市/省之间的地点单位。对于街道编号,给出后缀,例如街道名称。在街道名称之后,它通常跟随着与地点单元中的街道名称相同的结构。

街巷号

在越南有几种不同的方式来显示地址号码。这将在下面解释:

  1. 如果房子或建筑在正面。它由一个数字(如“2”)或一系列数字(如“200”)组成。如果有两个或两个以上的组合土地,该街道编号包含一个街道编号范围(例如“200–201–202”)。此外,它可以以字符作为后缀(例如“47a”)
  2. 另一方面,当房子放在小巷里。水花用来表示房子或建筑在巷子里。斜线越多,巷子越深越曲折(如“76/4/8/3”、“76a/34h”)。
  3. 在胡志明市,“Bis”不定期出现。事实上,它反映了越南历史上法国殖民主义时代的痕迹(如“56 之二”)。“Bis”在法语中是重复或再次的意思。
  4. 有时,街道号码的前缀是“số nhà”或“số”(如“Số nhà 500 hẻm 34/56”)。)

地址名称

街道的名称可以有不同的结构。在某些情况下,他们有前缀“đường”或“phố”,这在北边更常见,意思是“街道”然而,很大一部分街道不是以这些前缀开头的。街道可以用不同的方式命名,通常使用缩写。因为在越南常见的街道是“mạng 汤汤”,可以用不同的方式缩写:

  1. 恰赫·mạng·汤 8
  2. Cach mang thang tam
  3. cmtt
  4. cmt8

我们也有一些街道命名,如“đườngsố76”意味着“76 号街”。地址中门牌号和街道名称相同的房屋。这在 Hồ的胡志明市经常发生。不同之处在于选区或地区部分——例如,像“恰赫·mạng·汤·汤”这样的街道穿过第 1 区和第 3 区。所以这里需要病房名或区名来澄清。

地名

这没有任何具体的案例;它通常以“phường”、“x”和“thị trấn.”为前缀。但是,在某些情况下,一些县的地名可能是其他县或市/省的街道名或县名。

县名

类似的问题描述为地点名称,县名称可以是街道名称或其他地区的地点。用于识别县名的指示符以“quận”、“huyện”或“thị x”为前缀

城市/省份名称

如上面街道名称中所述,城市或省份通常以各种方式使用,如“phố Hồ市”、“TP。“hồ·齐明”、“tp.hcm”、“tp hcm”、“hcmc”都是同一个城市的同义词。然而,这种方式有一个缺点。在一些城市或省份,名称可能很难识别,例如,“Nẵng”或“đồng 奈”在缩写时是“n”。

国家名称

目前只关注越南,所以国名只有越南;我们在提取信息时也绕过国家名称,因为如果它没有我上面解释的这些步骤,那么它是绝对错误的。

地名

一般来说,地名不遵循任何特定的模式。它可以利用这是最难识别的部分,并经常改变。所以我们只关注商场、建筑、部门,因为它们很少变化。

3.我们的目标

我们旨在识别与特定地点单元和地址相关的地址数据。因此,诸如商场、建筑、部门和地址等场所单位必须加以识别。我们关注这些类型的原因是:

  1. 地址是具有一定顺序的结构化文本,由不同的属性组成(如街道号码、地址名称、地点名称、县名、城市名称、地名等。).因为我们可以依次利用这些属性。此外,如果我们不能识别所有的地址属性或大多数属性,结果也不会更有价值。
  2. 这些属性不经常变化(地名除外)。所以我们不经常维护它。对于地名,只有商场和部门是重点,因为他们很少改变。
  3. 我们不需要识别咖啡店、沙龙或餐馆,因为我们只关注住宅区。终端用户通常不会在胡志明市的星巴克咖啡点东西,不是吗?
  4. 我们从维基百科、越南统计总局、OpenStreetMap 和 350 多个网站收集数据,以收集地址和地点单位。

我们目前只关注越南的地址,因为每个国家的地址结构都非常不同。然而,我们已经计划在其他国家和语言开发。我们已经开发了一种混合方法,使得手动开发的试探法和自由数据都可以作为信任资源。

4.地址数据的标识

有许多不同的方法。然而,一般来说,信息提取可以大致分为两类。有两种方法:基于规则的匹配训练 s 统计模型。

  • 基于规则的匹配是一种定义明确模式的方式。它类似于在原始文本上使用正则表达式,但是它让您找到您正在寻找的单词和短语。此外,您可以访问和分析周围的标记,将范围合并到单个标记中,或者向命名实体添加条目。这意味着你可以控制结果。在这种方法中,它明显优于训练静态模型。
  • 训练统计模型是对数据集应用统计分析的过程。静态模型是观察数据的数学表示。训练一个新模型需要一些努力,但是一旦完成,它可以以各种形式和在各种环境中被识别。

通过结合静态模型和基于规则的组件,可以提高静态模型的准确性。通过为特定标记提供标签、实体或句子边界。我们还在静态模型之后使用基于规则的组件来纠正常见错误。为了建立更抽象的逻辑,基于规则的组件可以引用静态模型设置的属性。

5.解决办法

完整的工作流程。作者图片

通过这样做,我们还可以独立于通常在它们之后或之前的其他属性来检测属性。最后,我们将找到的候选地址组合成一个或多个完整的地址。

预处理

最初,我们通过在我们想要获得地址数据的数据上使用正则表达式来移除所有发音符号。这样做之后,会对数据进行一些清理,例如删除非 Unicode 字符或邮政编码,因为越南语很少使用邮政编码。如果没有完成这些预处理步骤,标记化可能会产生错误的结果。最后的预处理步骤包括词性(POS)。在该步骤中获得的 POS 标签稍后用于识别单个属性。

识别单个属性

地址的每个属性都是单独标识的,几乎独立于其他属性,因此数据中地址格式结构的变化对整体结果的影响很小。在某些情况下,两个有规律地相互继承的属性的序列被用来识别属性。这使得单个步骤的排序考虑了前一步骤的信息以用于下一步骤。在识别单个属性的过程中,所有可能包含地址属性的标记序列都被标注为候选。此外,一些候选属性用启发法进行了注释,从而产生了这个候选属性。

6.地址属性的集合

我们将县候选作为种子来聚合结果,因为地址的名称和地点可以重复,但县在不同的城市或省中不能重复。基于此,我们尝试为每个县候选人分配地址。为此,执行以下步骤:

  1. 首先,我们检查所有候选地址是否有地址号码。如果不是,那么我们忽略它,因为我们不能通过使用这些地址找到准确的位置。
  2. 第二,地址号后面的下一个候选必须是地址名。如果下一个候选项是地区或县,我们将其转换为地址名称,因为街道名称可以与地区或县相同(巴海 Trung 街和巴海 Trung 区)。但是,这种方法可能是错误的,因为客户可能会键入错误的地址。幸运的是,我们有一个很好的反向地址 API,可以检查地址是否正确,所以这不是大问题。
  3. 第三,地址后的名称可以是地名或县名。我们如何知道它是一个地方或县的名称?如果候选人的长度大于 5(包括城市名称)或 4(不包括城市名称),则包括地点和县名。此外,因为县在不同的城市中不重复,所以如果县候选是县名,我们可以确定县候选是县名。另一方面,它是地名。
  4. 第四,地名是一种特殊的称呼类型。在地名可以是县名、省名或市名(如永旺梦乐坛府或永旺梦乐*阳)之后,这些地名很少改变,因此我们可以将它们收集到地名录中以便快速查找。
  5. 如果在文本中找到所有属性,则假定它们属于一个公共地址。

7.问题

我们面临一些重要的挑战,这些挑战对未来的工作很有意义。检查提取的地址,我们主要意识到错误识别的地址名称的原因:

  • 我们没有足够的知识来源,所以郊区的一些地址无法识别,然后就被忽略了。为了解决这个问题,我们建立了一个统计模型,可以学习这些丢失的地址,并在下一次改进地址检测。然而,这种方法超出了本文的范围。我们将在另一篇文章中讨论这种方法。

8.结论和未来工作

我们提出了一种在非结构化文本中识别越南地址的方法。为此,我们开发了一种混合方法,利用可以从 OpenStreetMaps、Wikipedia、General Statistics Office 和其他来源获得的信息模式和地名词典。

随着 AhaMove 的区域扩展,我们将调整和评估该方法在其他语言和其他国家的可行性。为此,需要确定识别单一地址属性的模式,并需要汇编具体国家的地名录。

咖啡豆一生中的萃取

原文:https://towardsdatascience.com/extraction-over-the-life-of-the-coffee-bean-f777f017718a?source=collection_archive---------34-----------------------

咖啡数据科学

萃取与咖啡烘焙时间的数据

我收集照片数据已经快两年了。我想浏览这些信息,看看我是否能看到任何趋势,特别是烤肉的年龄。主要警告是:

  1. 随着时间的推移,我的方法有所改进。
  2. 我的品味变了。
  3. 我的味觉扩展了。

所以我对数据进行了归一化处理,以给出一个更公*的比较。我发现烘烤后 5 周内,味道和萃取度都有所改善。过去三周,我没有发现味道有所下降,而这正是烘焙师通常暗示的。然而,我没有过去 5 周的太多数据,因为我的烘焙通常在 1 磅左右,而且我喝了太多的浓缩咖啡,以至于烘焙时间不会太长。

烘焙/储存/提取

我每周用一个烤箱烤一次 T1,我把它加满到 350 克。他们说最大重量是 250 克,但是对于中等程度的烘烤,你可以更高。当我启动机器时,我把豆子放进去,而不是等着滚筒达到温度。我知道这不符合标准,但我不介意。我还没有对充电温度进行并排比较,但我相信有一天我会的。

所有图片由作者提供

当我开始收集数据时,我在第一次裂纹(FC)后 1 分钟结束烘烤。现在,我在 1:30 过 FC。我过去常常在烤之前混合豆子,现在我在烤之后做它。

储存;储备

这些豆子大部分储存在密封的塑料或玻璃罐中,但它们没有被真空密封。它们被存放在厨房的橱柜里,暴露在光线下。虽然人们说暴露在光线下对咖啡没有好处,但我还没有看到支持或否定这一说法的数据。

提取,血统

我是杠杆机器的粉丝,这些镜头大部分是在金快车上拍摄的。有些是拉帕沃尼,Flair,Kompresso,意大利的恩里科和拉佩皮纳。我从 10 秒的预灌输开始,但在过去的两年里,我已经转移到 30 秒的预灌输。我也是一年前开始压脉,很多镜头都是断奏或者断奏捣实。六个月前,我做了相当多的工作,在研磨前加热豆子,在冲泡前冷却研磨物(又名辣磨)。最重要的是,我已经使用纸质过滤器将*一年了。

所以有相当多的变化,但我相信一些标准化有助于比较随着烘烤时间的变化。

绩效指标

我使用了两个指标来评估镜头之间的差异:最终得分咖啡萃取

最终得分是 7 个指标(强烈、浓郁、糖浆、甜味、酸味、苦味和余味)记分卡的*均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水*。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难,会影响最终得分。

使用折射仪测量总溶解固体(TDS ),该数字用于确定提取到杯中的咖啡的百分比,并结合一杯咖啡的输出重量和咖啡的输入重量,称为提取率(EY)。

数据

我最终得到了 1200+个数据点,在编译下面的图之前,我必须清理这些数据。我扔掉了在咖啡馆拍的照片和一些奇怪实验的照片。

由于数字(Mac ),将数据表放在一起很有挑战性。我把我的数据储存在数字表中,每一列都是一杯浓缩咖啡。我使用了列而不是行,因为这使得在我的手机上查看这个表单更容易。然而,直到最*,最大列数还是几百列。所以我有几个表,我添加和移动了一些行来改进工作流,所以我必须创建一个公共表来收集所有其他表的重要部分。

并不是所有的镜头都有 EY,但我仍然想尽可能多地查看最终得分数据。下面是桌子一部分的大图。我有输入指标、输出指标和计算指标。我有彩色编码,可以很快看到分数之间的对比。我还记录当前镜头的笔记,以及下一个镜头要修改的内容。

数据手册的尺寸示例。所有图片由作者提供

首先,我把一切都绘制成散点图,没有归一化。我只区分了断奏和常规,但除了在 EY,似乎没有太大的区别。在过去的六个月里,我没有定期进行断奏击球,这是我能够使用更长的预灌注时间来驱动 EY 更高的时间。最终得分似乎随着时间的推移而上升,EY 也是如此。

你可以观察到我没有超过 6 周的烘烤数据。我有一些数据点,因为我出城了一个月,没有带豆子。

提取时间在第一周至第二周很长,但之后不会有太大变化。过去两个月我确实注意到了,做一次非常努力的夯实并没有多大效果;镜头会跑得很快。

然后,我使用 Z 分数归一化法通过烘焙来归一化数据。这将使用*均值 0 和标准差 1 对同一分布上的所有分数进行归一化。因此,如果点开始向正方向移动,就意味着分布在移动。散点图的问题在于它们不能很好地讲述故事。

所以让我们转到方框图。对于那些不熟悉盒子剧情的人来说,这是一个传奇:

这些是没有规格化的箱线图。它们显示出分数和 ey 随时间增加的趋势。这可能会产生误导,因为在这个数据之旅的开始,我会在两周内烤一次,喝一次。现在,我的烘焙在我酿造之前至少要放置两周。

让我们通过每次烘烤来标准化数据。最终得分和 EY 的分布似乎都有所上升,但投篮时间的分布没有上升那么多。拍摄时间下降,尤其是在过去 7 周。

我们也可以做最小最大归一化来强制所有的分数在 0 到 1 之间。我们可以对每一次烘烤都这样做,然后将它们组合起来。分数越高越好。

我们看到了一种趋势,即使用这种类型的标准化来组合数据,味道和 EY 会得到更高的分数。

只看烘焙后每天每箱的中值,它们都遵循粗略的趋势,但是有一些噪音归因于烘焙后的天数不一致。不是每一份烤肉都有每天的数据点。然而,我想尝试看看我能做些什么来理解烘焙后的味道和萃取趋势。

与 Q 分数相比

我的品味分数和 Q 分一致吗?幸运的是,我也有这个问题的一些数据。在过去的两年里,我也一直在收集关于我的考试和*均成绩的数据。我假设混合咖啡豆会得到单个咖啡豆等级的*均值,我想知道这个合并的 Q 值是否能给我一个很好的指示,让我知道一次烘焙是好是坏。

以下是我的烘焙数据表示例:

烘焙数据表示例

下面是一个例子,说明我是如何根据单个豆的分数来计算*均 Q 分数的。前两个没有名字或输出重量。

烘焙数据表的特写视图

我的混合烤肉*均 Q 值从 8.1 到 8.9 不等。下面是一个直方图,用来理解数据是如何分布的。

显然,我不能标准化每一次烘烤的拍摄数据,所以相反,我标准化了 3 到 5 次烘烤的拍摄数据:前 2 次烘烤(如果存在),有问题的烘烤,以及后 2 次烘烤(如果存在)。我用最小最大归一化法对分数进行了归一化。

箱线图可以提供一些关于趋势的信息,但我在过去一年的购买中更关注 Q 值,所以它可能会因我的购买而有所偏差。

看看最小最大标准化,最终分数似乎有轻微上升趋势,但 EY 没有。

我们可以通过查看每个 Q-score bin 的*均分数来简化这种情况,它显示了一个非常轻微的趋势。然而,数据点的数量非常少,所以我不会太依赖它。我曾希望看到一个更清晰的趋势,但正如数据中的情况一样,许多变量可能会相互妨碍。

总的来说,随着烘焙时间的推移,我发现味道和提取率都有上升的趋势,我怀疑这两者之间存在相关性。我没有看到 Q 级和口味之间的强烈趋势,这可能是由于酿造技术的改进。如果更多的技术变量得到控制,我预计趋势会更加清晰。

最让我兴奋的是,我总是可以再次进行这种分析,我很好奇更多的数据如何能够更好地理解烤肉的味道何时达到顶峰。对我来说,风味的高峰期在 3 到 5 周之间,这是一个比烘焙师建议的典型的 2 到 3 周更长的时间。对于提取率,我没有看到随着时间的推移而下降。通常情况下,EY 会继续上涨,然后到达一个*台。

对于过去 5 周的烘焙,有一丝陈腐,特别是在较暗的烘焙和持续 3 个月的烘焙中,但拍摄仍然令人愉快,部分原因是较高的 EY 潜力抵消了一些陈腐的味道。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。

我的进一步阅读:

咖啡豆脱气

解构咖啡:分割烘焙、研磨和分层以获得更好的浓缩咖啡

浓缩咖啡的预浸:更好的浓缩咖啡的视觉提示

咖啡的形状

搅拌还是旋转:更好的浓缩咖啡体验

香辣浓缩咖啡:热磨,冷捣以获得更好的咖啡

断续浓缩咖啡:提升浓缩咖啡

用纸质过滤器改进浓缩咖啡

浓缩咖啡中咖啡溶解度的初步研究

断奏捣固:不用筛子改进浓缩咖啡

浓缩咖啡模拟:计算机模型的第一步

更好的浓缩咖啡压力脉动

咖啡数据表

被盗浓缩咖啡机的故事

浓缩咖啡过滤器分析

使用 BERT 的抽取摘要

原文:https://towardsdatascience.com/extractive-summarization-using-bert-966e912f4142?source=collection_archive---------4-----------------------

一种利用 BERT 嵌入能力的监督方法

摘要总结是一项具有挑战性的任务,直到最*才变得实用。像 NLP 的许多东西一样,这种进步的一个原因是像 BERT 这样的 transformer 模型所提供的高级嵌入。这个项目使用 BERT 句子嵌入来建立一个提取摘要器,采用两种监督方法。第一种只考虑嵌入及其导数。这符合我们的直觉,一个好的总结者可以分析意思,应该纯粹根据文章的内部结构来选择句子。这种方法的基线是无监督的 TextRank 模型。另一种方法结合了序列信息,并利用了众所周知的新闻语料库特有的 Lead3 现象。这是一个观察,前三个句子通常能很好地概括文章。事实上,许多出版商都明确部署了这一策略。导联 3 用作第二种方法的基线。在这两种情况下,监督模型都优于 Rouge-1 和 Rouge-L F1 指标的基线。

背景

总结策略通常分为提取型、抽象型和混合型。提取策略选择最能代表文章要点的前 N 句。摘要试图用新词再现文章的要点。混合策略要么在确定一个抽象的中间状态后产生一个抽象的总结,要么可以根据文本的细节选择使用哪种方法(例如:指针模型)。

提取策略被设置为二元分类问题,其中目标是识别属于摘要的文章句子。摘要需要识别关键点,然后添加生成性元素。最后,混合策略需要结合这些元素,并提供一种机制来决定何时应该使用每种模式。

指标

摘要评估面临的挑战之一是它需要一组参考或黄金摘要的存在。对于大多数主题来说,这些都不是自然可得的,这也解释了为什么新闻文集和科学期刊主导了研究。科学论文有摘要,而新闻出版商通常在他们的网站上使用综述或横幅。摘要和翻译任务的自动评估是一个有趣但有争议的话题。这个马蜂窝在 TDS 上这里覆盖得很好。对于当前的目的,知道 Rouge-N 系列度量标准已经成为标准度量标准并具有以下特性就足够了:

Rouge-N 测量预测和 gold 汇总之间的 n-grams 重叠

胭脂召回通过黄金总结的长度使重叠正常化

Rouge precision 通过预测摘要的长度来归一化重叠,从而抵消回忆失败以说明简明。例如,一个非常长的预测摘要可以获得完美的回忆,尽管有许多多余的或误导性的单词

Rouge-1 F1(召回率和精确度的调和*均值)是主要的评估指标

Rouge-1 是一个更严格的衡量标准,也考虑到了顺序,通常与 Rouge-1 一起报告

数据集

康乃尔新闻编辑室数据库包含 130 万篇文章摘要对,来源于 39 种出版物。该数据集代表一组不同的汇总策略,这些策略基于透明算法被标记为(提取的、抽象的、混合的)。

用于该项目的数据集仅过滤了提取的文章摘要对,并将该选择截断为 5000 个样本。

管道

注意事项

总结的一些重要注意事项是:

句子排名:每篇文章都需要返回一个非空的摘要,但可能会有一些文章的所有句子都没有越过概率阈值。事实上,摘要的长度通常是一个棘手的问题,但一个常见的实用解决方案是指定返回的句子数量作为固定的用户输入 k。在这种情况下,句子按照预测概率的降序排列,并选择前 k 个句子。当前项目将使用 k=3。

rouge:rouge 分数不是一个标准的评估指标,需要自定义实现

混淆矩阵:使用句子排序和 Rouge 的一个结果是模型之间的评估结果可能与标准混淆矩阵显著不同。例如,一个模型可能无法预测阈值以上的许多句子,但在返回前 3 个句子后仍然得分高或模糊。

示意图

预处理

火车

预测概率

选择前 3 个句子作为总结并连接

使用 rouge-score 包通过自定义实现计算 rouge 分数

预处理

特性

BERT 足够复杂,可以从语言的所有细微差别中解析出意思,并且有意忽略了停用词移除、词干提取和小写转换等步骤。

预处理包括:

将数据从 JSONL 加载到 Pandas 数据框架

使用 spaCy 将文本分割成句子,清理短句,并通过句子转换器包使用 BERT 嵌入

通过计算句子嵌入的*均值来计算冠词的含义

计算文章中每个句子的句数

目标

数据集的提取标记依赖于一种算法,该算法在相关类别中对文章策略进行宁滨之前,在连续体上对文章策略进行评分。结果,摘要并不都是完全摘录的,也不是所有的句子在文章文本中都有精确匹配。下面的算法用于识别摘要中的句子

计算每个摘要句子和文章句子之间的余弦相似度矩阵

将具有最大值的句子标记为 in-summary(设置为等于 1 )

文件级的培训-测试-拆分

虽然句子是第一组模型中的样本单元,但是训练测试分离需要发生在文档级别,以确保文章级别的摘要可以被合理地连接起来用于 Rouge 评估。这需要一个训练-测试-分割的自定义功能。

数据探索

第一步是对文章和摘要的长度有一个高层次的概述,用句子来衡量。

句子中文本长度的统计(作者自己的图像)

Lead3 现象在数据集中非常明显,超过 50%的摘要中的句子来自前 3 篇文章的句子。随着与文章开头距离的增加,摘要收录的下降也同样明显。

引导句现象在语料库中高度可见(作者自己的图像)

主题域可以使用 t-sne 和简单的标签分配方法来可视化

计算“娱乐”、“犯罪”、“商业”和“政治”作为四个领域参考嵌入的 BERT 嵌入

计算每篇文章相对于四篇参考文献的余弦相似度

用最接*的参考文献(最高余弦相似度)标记文章

作者自己的形象

尽管有大量的信息丢失,但特定主题领域的密集程度是显而易见的,政治在左下角,犯罪在右下角,商业在左上角,娱乐在右上角。同样值得注意的是,政治和犯罪占据了底部,而商业和娱乐占据了顶部。广义的解释是,政治和犯罪共同关注社会和法律问题,而商业和娱乐有着共同的商业目标。主题域决不是预期可分离的,并且观察到的分散程度并不令人惊讶。

方法 1

这种方法的目标是仅使用句子嵌入及其派生来获得摘要,以便训练能够解析文章内部结构的监督模型。 TextRank 被选为该方法的基线。一系列逻辑回归模型和神经网络用以下总结结果进行训练:

最优 logistic 回归模型是 l1 _ 比值为 0.25、正则化倒数为 0.5 的弹性网。最佳神经网络是一个双层密集网络,每层 25 个神经元。(作者自己的图片)

整个测试过程中一个值得注意的特点是,微调,甚至是*衡数据的调整产生的益处很少。例如,所有尝试的逻辑回归模型得分在 41%和 42%之间。这并不奇怪,因为这些模型调整不太可能改变句子排名,这是他们各自胭脂分数差异的唯一来源。对于 Rouge-1 和 Rouge-L,这两个监督模型都轻松击败了文本排名基线,得分相当令人印象深刻。它们的优势在召回率和精确度方面也是一致的。一个令人惊讶的方面是,弹性网络模型略微优于神经网络。一个原因可能是仅提供句子嵌入和文章含义的特征集没有为神经网络的非线性提供足够的上下文信息来充分探索。在进一步思考中讨论了可能的补救措施。

进场 2

Lead3 是 Rouge metrics 的强大对手,本节通过包含顺序信息,利用了新闻语料库中已知的顺序结构。使用句子数量作为句子嵌入和文章含义的附加特征来训练逻辑回归模型。各种 LSTM 体系结构,自然地结合了顺序信息,在与上一节相同的嵌入特性上进行训练:

LEDE3 取前导三句。LogReg def 是 SK-learn 中的默认逻辑回归模型,LSTM Bi 50 是在 Keras 中实现的 50 神经元双向 LSTM 网络,没有填充,纪元为 1,并使用 Adam 优化器。(作者本人图片)

虽然逻辑回归模型滞后,但 LSTM 在 LEAD3 基线上享有优势。再深入分析一下,LSTM 的召回率与领先 3 相似,但在精确度方面有很大优势。这表明,在 LSTM 不同于 Lead3 的情况下,它在选择同样相关但更简洁的句子方面做得相对较好。

进一步的想法

在每个句子给出的信息很少的情况下,仅嵌入方法的结果令人惊讶地好。一个有趣的方法是通过创造性特征工程为模型提供更多关于文章内部结构的信息。这可能特别有利于从神经网络的非线性中提取更多信息。一种想法是,可以根据一些属性在语料库中标记句子,然后将文章级质心作为一个新的特征。有监督的方法可以基于词性标注为每个句子分配一个功能标签。无监督选项可以使用聚类算法来分割整个语料库上的句子嵌入空间。

进一步工作的更简单选项包括(I)使用在 TextRank 中获得的相似性矩阵作为监督模型的特征集,(ii)使用比这里使用的 5000 篇文章多得多的数据来训练模型,当然,(iii)添加注意机制或使用转换器来获得更细微的结果。

最后,值得记住的是,语料库仅被过滤为摘录摘要,下一步将包括对数据集中更广泛的策略类型采取相同的方法。

感谢您阅读我的文章。欢迎所有反馈,记得查看我的 GitHub 的代码和更详细的分析。

非凡的数据可视化—圆形图表

原文:https://towardsdatascience.com/extraordinary-data-visualisation-circular-chart-fe2d835ef929?source=collection_archive---------33-----------------------

数码师Pixabay 拍摄的照片

一个圆形图表显示了用 Python Plotly 实现的比例和位置关系

使用饼图或圆环图来表示整体中不同组成部分的比例是非常常见的。然而,最*我遇到了这样的数据可视化需求:

  • 该图表需要呈现几个组件
  • 每一个组成部分都需要显示出相对于整个事物的比例

到目前为止,饼图或甜甜圈图仍然是完美的选择。但是,请注意其余的要求。

  • 组件可能会重叠
  • 除了显示比例外,每个组件将从基线的某个位置开始,并以某个端点结束。

有些情况需要这样的要求。例如,根据 DNA 片段与基线的相似性来表示 DNA 片段。

圆形图表

我们可以用一个圆形图表来形象化这种关系。

如上所示,圆形图表包括

  1. 代表基线的圆
  2. 表示起点/终点的指示。因为是圆,所以起点和终点其实是一样的。
  3. 一些度作为刻度将指示位置,以及显示它是顺时针还是逆时针。直观来说,我会推荐用顺时针。
  4. 最后,用不同颜色显示位置(起点和终点)和比例(径向长度)的组件

要可视化的数据

照片由 MiraCosicPixabay 上拍摄

要可视化的数据如下。

gene_list = [
  [0.1, 0.25],
  [0.15, 0.3],
  [0.6, 0.68]
]

这是一个二维数组。每个子阵列代表基因的一个片段。这两个数字分别是起点和终点。

例如,第一个基因[0.1, 0.25]意味着该基因片段从基线的 10%开始,在 25%结束。所以长度是原来的 0.15。

现在,让我们看看如何使用 Plotly 来绘制这个圆形图表。

履行

julianestanczykPixabay 上拍摄的照片

用 Plotly 画圆形图并不太难。

首先,我们需要导入 Plotly。如果还没有拿到库,可以简单的通过pip install plotly安装。

import plotly.graph_objects as go
import numpy as np

Plotly 支持极坐标系统,非常适合用来绘制我们的圆形图表。要在极*面中绘制圆,两个重要的参数是

  • 圆的半径:r
  • 角度:*θ*

在我们的例子中,我们需要使用半径r来区分我们的基圆和其他组件(圆段)。角度*θ* 很重要,因为我们需要它来显示起点和终点。换句话说,我们需要基圆的*θ* 为 0–360 度,而组件取决于它们相应的比例和位置。

我们定义一个函数来得到*θ*

def get_theta(pct, num_points):
  start = pct[0] * 360
  length = (pct[1] - pct[0]) * 360
  step = 360 / num_points
  return np.arange(start, start + length + step, step)

在这个函数中,它有两个参数。第一个参数pct是一个包含两个元素的列表/元组。第一个元素是开始百分比,第二个元素是结束百分比。第二个参数num_points表示对于一个完整的 360 度圆,我们想要在图上呈现多少个点。越多的num_points我们将拥有越*滑的圆。在我的情况下,360 点就足够了,因为人眼将无法看到小角度。

让我们在这里定义两个常数:

num_points = 360
r_gap = 0.05

上面提到的num_points,我想用 360 分。r_gap表示我们希望基圆和每个线段之间有多大的间隙。

我们还需要知道图表的半径应该是多少,才能显示所有的线段。既然我们已经知道了r_gap。如果我们假设基圆有它的半径1,我们就可以计算出我们想要的最大半径。

# Get radial scale
max_r = 1 + (len(gene_list)) * r_gap

现在,让我们用 Plotly 初始化一个图形。

fig = go.Figure()

添加基圆

然后,添加基圆。它应该是黑色的。这里我们定义了半径r=1,这样线段就是1 + r_gap * (index + 1)

# Create the base circle
fig.add_trace(go.Scatterpolar(
  r=[1] * num_points,
  theta=get_theta([0, 1], num_points),
  mode='lines',
  line_color='black',
  line_width=3,
  showlegend=False
))

添加零度指示器

现在,让我们在 0 度上画一个小“杠”来表示基圆从哪里开始。此外,在图表边缘和线段之间留出一些空间也有所帮助。

# Create the zero indicator
fig.add_trace(go.Scatterpolar(
  r=[1, max_r],
  theta=[0, 0],
  mode='lines',
  line_color='black',
  line_width=3,
  showlegend=False
))

请注意,这里我们只需要图上的两点:

  • (1,0 度)
  • (最大 r,0 度)

渲染线段

现在看起来好多了。让我们在 for 循环中渲染我们的片段。

# Loop the gene list to add all the gene cirles 
for index, seg in enumerate(gene_list):
  fig.add_trace(go.Scatterpolar(
    r = [1 + (index + 1) * r_gap] * num_points,
    theta = get_theta(seg, num_points),
    mode='lines',
    line_width=3,
    name='Segment' + str(index+1)
  ))

好的。看来还是有事情要做的。如图所示,有几个问题:

  • 第三段几乎看不见,因为它几乎不在图表的边缘。
  • 零度从 3 点钟位置开始,最好让它从 0 点钟位置开始。
  • 图表是逆时针方向的,对于大多数人的习惯来说并不直观。
  • 半径记号没有用。
  • 网格没有用。

调整布局

让我们解决上述所有问题。

# Configure the layout based on the requirements.
fig.update_layout(
  polar=dict(
      angularaxis=dict(
        rotation=90,
        direction="clockwise",
        showticklabels=True,
        showgrid=False
      ),
      radialaxis=dict(
        range=[0, 1 + (len(gene_list) + 1) * r_gap],
        showticklabels=False,
        visible=False
      )
  )
)

现在,我们有了一个完美的圆形图表!

摘要

Pixabay 上的absolute vision拍摄的照片

在本文中,我展示了如何使用 Plotly 绘制一个圆形图表,表示数据的比例和位置关系。

所有代码都可以在我的 Google Colab 笔记本中找到:

[## 圆形图表

用 Python 中的 Plotly 绘制圆形图表

colab.research.google.com](https://colab.research.google.com/drive/1JyAF3saWjwb8DIr_u_cQA9Mm8jNSs688?usp=sharing)

虽然有时数据可视化库可能不提供一些现成的数字和图表,但我们仍然可以使用 Python 轻松地绘制出我们脑海中的任何东西。Plotly 就是这样一个令人惊叹的数据可视化库。

[## 通过我的推荐链接加入 Medium 克里斯托弗·陶

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@qiuyujx/membership)

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

引人注目的 R 动画地图——简单介绍

原文:https://towardsdatascience.com/eye-catching-animated-maps-in-r-a-simple-introduction-3559d8c33be1?source=collection_archive---------7-----------------------

使用传单闪亮轻松制作美丽地图的动画。

提莫·维林克Unsplash 上拍摄

作为数据科学家和数据分析师,我们每天都要处理不同种类的数据。我们都知道,数据和我们的发现的可视化是关键,尤其是在向同事或客户展示时。毕竟,用图表来讲述一个故事比用简单的数字或文本要容易得多。当您通过仪表板呈现数据时,不仅静态可视化变得重要,您还希望动态显示数据的变化。

在这篇文章中,我将展示如何使用 r 中的活页闪亮库轻松制作基于地理空间数据的图表。

1.介绍

虽然在 R 中绘制地图有许多方法(例如使用 ggplot2tmap ),但传单库是我个人最喜欢的,原因如下:

  • 简单
  • 高度定制化
  • 漂亮的交互式地图
  • 适用于所有主要的桌面和移动*台

leaflet R 库建立在 leaflet.js 之上,这是领先的用于移动友好的交互式地图的开源 JavaScript 库。R 实现让我们只用几行代码就能生成简单的地图。例如,只需一行代码,您就可以显示以下地图,放大奥地利美丽的维也纳:

基本传单地图(图片由作者提供)

尽管创建这个地图非常简单,但是它还没有显示任何数据。最终我们想要的是这样的东西:

附有数据的基本传单地图(图片由作者提供)

我们想要用数据覆盖我们的地图(就像在上面的例子中,我们已经添加了一些圆圈标记),或者甚至根据一些底层数据给我们的地图着色(所谓的 Choropleth )。最后,我们希望能够动画显示数据随时间的变化,以便将我们的地图包含在一个漂亮的仪表板中。

基本动画(图片由作者提供)

在接下来的部分,我将简要演示如何制作一个类似于上面的动画,以及如何创建一个动画的 Choropleth。

2.数据

首先,我们需要两种类型的数据:我们需要显示我们想要的地图和我们有兴趣显示的数据。

对于地图数据,我们使用活页有两个主要选项:

  • 瓷砖
  • GeoJSON 或 TopJSON 文件形式的地理空间数据

我们已经看到了如何使用上面图表中的基本图块,简单地使用默认为 OpenStreetMap 图块的 addTiles() 函数。我们也可以通过使用 addProviderTiles() 函数来使用其他第三方图块集。有关可用图块的完整列表,请参见此处的。

我们还可以从 GeoJSON 或 TopJSON 文件中读取地理空间数据,并将它们转换为 r 中的空间对象。为了创建我们的 Choropleth,我们必须使用一个名为 addPolygons() 的函数,它要求我们使用这样的空间数据。虽然这整个过程一开始听起来复杂而吓人,但实际上非常简单。

在本文中,我们将重点展示国家级别的数据。我们可以很容易地从www.thematicmapping.org获得所需的空间数据,它提供了“世界边界数据集”。下面的代码片段展示了如何从 r 下载、解压缩和加载这些数据。

生成的空间面数据框包含所有国家的信息,例如国家代码、名称、经度和纬度坐标。对象中包含的基本数据可以通过以下方式访问:

世界边界数据集概述(图片由作者提供)

对于绘制 Choropleth 来说,重要的是对象中包含的多边形数据。这基本上是用来绘制国家边界的数据。

多边形数据(图片由作者提供)

这是我们需要的所有数据,用来创建我们将要使用的基本地图。

我们将要显示的数据与当前的重要主题相关:正在进行的新冠肺炎疫情的案例数据。世界卫生组织以 csv 格式发布所有国家的每日病例统计数据,我们可以随时查阅。

世卫组织 Covid 数据集(图片由作者提供)

该数据集为我们提供了自 2020 年初以来的每日统计数据,并且每天都在更新。

3.基本地图

在这一节中,我将展示如何创建地图的基本版本,我们将在后面制作动画。

首先,我们将把空间数据与选定日期的 COVID 案例结合起来,定义将要显示的标签文本,并为数据和图表图例设置调色板。

现在,我们可以使用圆形标记来创建地图的第一个版本,以显示 COVID 案例。

基本圆形标记图(图片由作者提供)

这很简单!我们所要做的就是使用 addCircleMarkers() 函数,使用我们的数据集中包含的经度和纬度坐标作为圆的中点,并使它们的半径和颜色取决于案例的数量。我们还添加了出现在鼠标悬停时的标签文本以及左下角的图例。所有这些都不费吹灰之力!

创建 Choropleth 版本同样简单。不使用 addCircleMarkers() 函数,我们只需使用 addPolygons() 函数,并且不使用坐标,我们需要使用空间多边形数据框中包含的多边形。

基本 Choropleth 地图示例(图片由作者提供)

再说一遍,超级简单!在下一节中,我们将使用闪亮的为我们创建的两个版本的地图制作动画。

4.动画

虽然传单本身无法帮助我们完成显示数据随时间变化的任务,但我们可以使用 shiny 中的简单设置来完成这一任务。我们所要做的就是使用一个 sliderInput 小部件为我们选择日期,并将 animate 参数设置为 TRUE。

这个输入部件在右下角有一个小的播放按钮,如果我们在这个部件中观察地图的变化,我们将得到我们的模拟!

为了避免每次改变时都要重新绘制整个地图的开销,我们可以使用 leafletProxy() 函数,它是专门为在闪亮的上下文中使用而设计的。它允许我们访问已经绘制的地图并改变其特征。

对于地图的标记版本,我们只需通过 clearMarkers() 清除现有标记,并在观察到所选日期发生变化时添加新标记。

闪亮的动画标记地图(图片由作者提供)

不幸的是,重新绘制多边形在计算上更加昂贵,并且会在我们的闪亮的应用程序中引入显著的延迟。在撰写本文时,传单库中还没有直接的方法允许我们简单地改变绘制的多边形的特征。然而,使用一点 JavaScript 就像这里详细描述的一样将允许我们做我们想做的事情。

闪亮的动画 Choropleth 地图(图片由作者提供)

正如承诺的那样,你可以在下面找到闪亮应用的完整代码:

5.结论

这就把我们带到了本文的结尾,在这篇文章中,我演示了如何使用传单闪亮的** R 库轻松创建引人注目的动画地图。希望这能让你自己通过几个简单的步骤创建令人惊奇的交互式地图,并在一个漂亮的仪表板上分享它!**

如果您对我在本文中展示的内容有任何反馈或问题,请务必让我知道,并在这些不确定的时期保持安全!

F# Azure 函数

原文:https://towardsdatascience.com/f-azure-functions-a5cce33dce58?source=collection_archive---------31-----------------------

在 F#中创建 Azure 函数

F#中的 Azure 函数

F#是一种很棒的语言,也是为你的 Azure 函数编程的好选择。不幸的是,微软并没有让实现它们变得容易。这当然比以前容易,但在开始时需要做一些准备工作。但是我认为这种努力是值得的!

Azure CLI

要开始,您需要在计算机上安装 Azure CLI。如果您还不知道,请点击下面的链接:

https://docs . Microsoft . com/en-us/CLI/azure/install-azure-CLI?view=azure-cli-latest

这将使您能够从 Windows 命令行或 PowerShell 提示符使用 Azure CLI。我更喜欢 PowerShell 提示符,因为这也能让您完成制表符。

在 PowerShell 提示符下,键入以下内容以获取当前为 F#安装的 Azure 模板列表:

dotnet new --list -lang F#

您应该会看到类似这样的内容:

F#的 Azure 模板

创建项目模板

首先,我们将根据提示为 Azure 函数创建项目模板:

dotnet new func -lang F# --name AzureFunctionFSharp

这将创建 4 个文件:

创建功能

在所有可用的 Azure 函数模板中,最容易使用的是 HttpTrigger 。要在提示符下创建它:

dotnet new http -lang F# --name HttpTrigger

这将创建 HttpTrigger.fs

创建解决方案

完成所有这些后,下一步是在 Visual Studio 2019 中创建解决方案文件。如果你打开项目文件azurefunctionfsharp . fsproj,你应该会发现几乎所有你已经添加的东西:

VS2019 中的初始项目

但是,您会注意到它没有我们的 HttpTrigger.fs 文件!只需将该文件添加到项目中。还需要添加 hosts.jsonlocalhost . settings . JSON。对于这最后两个文件,您必须确保它们的构建动作是 None 并且它们被复制到输出目录(如果较新的话):

为 JSON 文件构建属性

一旦你完成了,构建项目并保存解决方案。

附加 NuGet 包

我找到了 FSharp。Data NuGet 包在处理 F#项目时非常有用。您可以通过项目的管理包选项来添加它。

创建自定义模板

完成所有这些后,您可以将整个项目保存为自定义模板,供将来的项目使用。这将使你不必再次经历这一切。如果您在解决方案浏览器选项卡中选择您的项目,然后从项目菜单中选择导出模板,您可以将该项目导出为未来模板:

导出模板

下次你想创建一个 F# Azure Function 项目时,你可以使用你已经创建的自定义模板:

创建一个新的 F# Azure 函数项目

调试你的 F# Azure 函数

如果一切设置正确,您现在应该能够按 F5 键并调试您的项目。您应该会看到类似这样的内容:

Azure 功能在本地运行

然后,您可以使用类似于 Postman 的东西向 REST API 发送请求,并查看您的输出。

结论

正如我在开头所说,这不像在 C#中创建 Azure 函数那样简单,但肯定值得付出努力。希望微软会继续改进他们对 F# Azure 函数的支持,并在 Visual Studio 2019 或未来版本中放置一个合适的模板。与此同时,这是你自己可以做到的。

寻找最佳预测模型:不同单变量预测模型的比较

原文:https://towardsdatascience.com/f-forecasting-5d23341462eb?source=collection_archive---------22-----------------------

使用 AR、MA、ARIMA 和 SARIMA 进行单变量预测的最简单、最全面的指南。

预测可能是一项艰巨的挑战,尤其是对那些只有很少或没有统计学背景的人来说。但我认为这比人们想象的要容易得多。在本文中,我将介绍基本的单变量预测模型,并相对轻松地预测一个变量。

基本模型

单变量预测有两种基本模型。第一种是利用预测变量的过去值的自回归模型和使用白噪声误差项的过去值的移动*均模型。

自回归模型看起来像这样

自回归模型

请注意,该模型仅使用预测变量(y)的过去(滞后)值。我们使用滞后的数量 pp 通过一些测试来确定。

移动*均线模型看起来是这样的

移动*均模型

像 AR 一样,MA 使用过去的值,但它使用误差项,而不是预测变量。我们使用 q 数量的滞后, q 由一些测试确定。

我们可以将自回归模型和移动*均模型结合在一个叫做 ARMA 的模型中。然而,通常情况下,我们的预测变量是非*稳的。这意味着该系列通常包含上升或下降趋势。为了减轻这一点,我们可以差分序列,以消除那些向上或向下的运动,使序列*稳。这样做,我们产生了 ARIMA 模型或自回归综合移动*均。一些时间序列变量可能具有季节性,如销售或收入,它们通常在假日期间激增。为了适应这种情况,我们有一个 ARIMA 的广义变体,称为 SARIMA,它也包含了季节滞后。

ARIMA模型看起来是这样的

滞后算子表示法中的 ARIMA 模型

在这个模型中,我们将系列差 d 次,直到它变得稳定phi 和 theta 分量分别代表 AR 和 MA 模型。

萨里玛模型看起来像这样

滞后算子表示法中的 SARIMA 模型

这仅仅是 ARIMA 的一个概括,但是增加了季节差异、季节移动*均滞后和季节自回归滞后。

预赛

我们的目标是预测下个月的通货膨胀率。您应该拥有的是逗号分隔的值文件(。从 2000 年 1 月到 2020 年 4 月菲律宾的月通货膨胀率。档案名称为 InflationRateLecture.csv。如需完整系列,您可以从 Bangko Sentral ng Pilipinas 主要统计指标页面下载。您还应该在 Mac 或 PC 上安装 R 和 RStudio 的副本。如果这是你第一次使用 R,不要害怕,只要遵循下面的代码就可以了。

第一步是安装必要的软件包。对于这个例子,我们需要安装所需的包。这些命令如下:tidyverse 用于常规数据操作,urca、forecast、TSstudio 和 tseries 用于必要的预测命令。请随意探索您可以从中获得的各种功能。

生成一个新的脚本,以便您可以跟踪事情。首要任务是安装所需的软件包。我们可以在 tools 选项卡中手动查找包,或者您可以只运行下面的命令。请注意,根据您的互联网连接,安装可能需要一些时间。

install.packages("tidyverse")
install.packages("urca") 
install.packages("forecast") 
install.packages("tseries") 
install.packages("TSstudio")

安装完成后,您现在必须告诉 R 您将要使用这些包。我们通过调用 library()函数来实现这一点。把这想象成从图书馆里拿一本书,你想借并在一次特定的学习中使用。

library(tidyverse)
library(urca)
library(forecast)
library(tseries) 
library(TSstudio)

运行完所有这些命令后,您应该准备好运行所有必要的命令。如果在预测过程中关闭 R 会话,只需再次使用库命令来重新加载包。无需重新安装(除非有可用的软件包更新)。

加载数据集

加载数据集的一个简单方法是使用 file.choose()函数,它会打开一个对话框,类似于我们打开文件时习惯使用的对话框。将数据集存储在对象中很重要,这样我们以后就可以引用它。首先,我们加载数据集并将其存储在一个对象中。在本教程中,我将物体命名为“膨胀”,但是你可以随意命名。代码和数据集可以在这里找到

https://drive . Google . com/drive/folders/11 rzi 8 p-qcvwlamdro 93 fnslqlxco 39 ef?usp =共享

inflation <- read_csv(file.choose())

read_csv 是 tidyverse 内 R 中 readr 包的一部分。这用于读取 csv 文件,并能够在 r 中加载它。您应该注意到,应该会出现一个对话框,提示您选择文件。一定要选 InflationRateLecture.csv。

head(inflation)
nrow(inflation)

运行 head(inflation)命令会列出数据集的前 6 行。你应该看到 2000 年 1 月的通货膨胀率是 5.5,2000 年 2 月是 5.6,以此类推。nrow(inflation)给出数据集中的总行数。这表明数据集中有 244 个时间段(月)。您也可以通过查看环境选项卡并单击通货膨胀旁边的网格来查看数据集。

声明时序对象

目前,我们加载的数据集是一个框架。为了能够预测,我们需要一系列。如果你查看数据集,我们只对预测其中的“利率”变量感兴趣。因此,我们需要将“利率”变量转换成一个序列。

inf <- ts(inflation$Rate, start = c(2000,1,5), frequency = 12)

我们正在创建一个名为“inf”的新对象,这是我们将使用的系列。ts 命令创建该对象。命令中的第一个参数是变量。$告诉 R 我们想从数据集通货膨胀中获得利率变量。之后,我们指定开始日期为 2000 年 1 月 5 日。r 可以在这之后自动检测结束。最后,我们指定系列的频率。因为我们处理的是月度数据,所以频率应该是 12。如果是每季度一次,频率为 4,每周一次为 52,每两年一次为 2。

绘制时间序列图

将我们的系列形象化是很重要的。我们可以使用 autoplot 命令来做到这一点。

autoplot(inf) + ggtitle("Inflation Rate (Philippines), January 2000 to April 2020") + labs(x = "Time", y = "Inflation Rate")

通货膨胀率曲线图

该命令以相应的标题“通货膨胀率(菲律宾),2000 年 1 月至 2020 年 4 月”绘制系列“inf”,其中 x 轴标记为时间,y 轴标记为通货膨胀率。对于这些规范,我们使用 ggtitle 和 labs 选项。如果你做的正确,你应该有一个类似上图的图。我们可以看到全球金融危机期间的通胀飙升,缩减恐慌,以及最*通过的第一套刺激方案。

预测构建模块

我们现在继续生成 ACF 和 PACF 图,并确定序列是否是非*稳的。

让我们首先生成通货膨胀率的 ACF 和 PACF。同样,ACF 和 ACF 可以告诉我们很多关于这个系列的特性。通常,它给出了序列的基本过程的一些指示,无论它是 AR、MA 还是 ARMA。此外,如果我们认为序列是非*稳的,我们将看到通货膨胀差值的 ACF 和 PACF。

ggAcf(inf) + ggtitle("ACF of Inflation")
ggPacf(inf) + ggtitle("PACF of Inflation")

ACF 和 PACF(水*)

图中的 ACF 是几何衰减的,而 PACF 记录了立即截止。如果我们回忆一下上节课关于 ACFand PACF 的内容,这与 AR 过程是一致的。虽然还不确定,但这给了我们一个潜在过程的线索。在 ACF 中,请注意第一个到第十一个滞后具有统计显著性(超出蓝色置信带)。我们还可以看到,一些部分自相关是重要的,如第一、第二和第十四。

系列差异

减轻非*稳性的一种方法是对序列求差分。为此,我们使用 diff()命令。

dinf <- diff(inf)
ggAcf(dinf) + ggtitle("ACF of Inflation (Differenced)") 
ggPacf(dinf) + ggtitle("PACF of Inflation (Differenced)")

第一个命令利用 diff()函数对序列进行差分,并创建一个对象“dinf ”,它是通货膨胀的差值。默认情况下,它会差一次,但我们可以将其设置为差两次或指定的任何次数。

ACF 和 PACF(差异)

类似于这些水*,我们可以看到 ACF 呈几何衰减,而在 PACF 中可以看到立即截止。这是支持 AR 过程的更多证据。但是,请注意,并不是很多滞后都很明显。这是一个信号,表明序列是“*稳的”,这迫使它显示协方差*稳的性质。我们将继续深入探讨这个问题。

水*与差异通货膨胀

比较通货膨胀的水*值和差值会得出一些有趣的结果。首先,使用简单的图形外观可以证明非*稳性。但是,在进行正式的统计测试之前,我们不能太确定。第二,请注意,在差分序列中仍然有野峰值(异常值)。这些可能是结构性突变的指标,我们需要考虑它们是否存在。

时间序列的分解

对我们拥有的时间序列进行适当的分解也很重要。这些成分是趋势、季节性和序列中的随机成分。幸运的是,R 中有一些命令可以自动为我们绘制图表。

ts_decompose(inf, type = "additive", showline = TRUE)

级数的分解

TSstudio 库中的 ts_decompose 命令为我们提供了该系列组件的可视化效果。此命令会将序列分割成序列的观察、趋势、季节和随机部分。请注意,可能在每年的八月或九月,会出现一些可观察到的季节性。原因我会留给你去想。TSstudio 中的分解命令更具交互性,允许您将光标悬停在图形(由 plot.ly,一个有趣的图形库生成)上,并深入研究该系列。随着时间的推移,我们将会更多地使用这种方法。

非*稳性测试

在测试非*稳性时,我们将使用三种最流行的测试。这些是扩展的迪基-富勒试验、菲利普-佩伦试验和 KPSS 试验。请记住 ADF 和 PP 测试是单位根测试。因此,他们的零假设是非*稳的,而他们的替代品是*稳的。相反,KPSS 检验是*稳性检验,其零假设是*稳性,而其替代假设是非*稳性。

扩充迪基-富勒试验

进行 ADF 测试的命令是 r 中的 adf.test()。我们将使用*稳性的两个备选假设对系列进行此测试。我们将在原始系列和差异系列上运行此操作。

adf.test(inf) 
adf.test(inf, k = 1)
adf.test(inf, k = 2)
adf.test(dinf)

请注意,当我们运行第一行时,有一个提示提示序列是静止的。我们测试第四行的时候也是这样。虽然通货膨胀的差异变量肯定是稳定的,但该水*的值可能具有很大的欺骗性。正如我们前面说过的,ADF 测试的限制是你必须指定滞后阶数。这些测试(第一次和第三次)在第六轮进行。如果我们使用一个更现实的滞后,比如 1 或 2,这个序列被确定为非*稳的。

菲利普斯-佩龙试验

对于 Phillips Perron 测试,我们使用 pp.test()命令。与 ADF 测试不同,我们不再需要指定滞后阶数,并且更加通用。

pp.test(inf)
pp.test(dinf)

PP 测试的结果相当有说服力。我们看到,在水*,该系列是不稳定的,因为我们无法拒绝零假设。一旦求差,数列就稳定了。因此,当我们开始建立一个预测模型时,我们需要对通货膨胀进行差分,以使其*稳化。

科维亚特科夫斯基-菲利普斯-施密特-申试验

最后,我们转向 KPSS 检验。请记住,这个测试的零假设是*稳性,而另一个假设是非*稳性。KPSS 测试的命令是 kpss.test()。我们可以指定一个名为 null 的选项为“趋势”或“水*”或两者。在这种情况下,我们就让它保持缺省值,考虑两者。

kpss.test(inf)
kpss.test(dinf)

正如所料,我们发现水*序列不是*稳的。奇怪的是,检验还发现差分序列是非*稳的。尽管如此,我们也可以参考 ADF 和 PP 检验的结果来支持我们的主张,即差分序列是*稳的。

预测本身

现在让我们转到预测本身。首先,在进行样本外预测之前,我们先进行样本内预测。正如我们在第一部分中提到的,预测样本的原因是为了查看生成的模型的质量,并让我们将不同的预测模型及其估计值与实际实现值进行比较。我们将使用上一章讨论的预测质量指标。最后,在接*尾声时,我们将使用我们确定的最佳预测模型来预测下一年的通货膨胀。

将数据集分成训练集和测试集

首先,让我们将数据集分成两个样本,一个训练样本和一个测试样本。训练样本是我们必须预测的可用数据。测试样本是已经实现的数据(即我们已经知道系列值),但我们坚持测试预测模型的质量。而以前,这一步曾经是一个痛苦,与 R,它是一件轻而易举的事。我们使用 ts_split 命令来做到这一点。

split_inf <- ts_split(inf, sample.out = 12)training <- split_inf$train 
testing <- split_inf$testlength(training)
length(testing)

我们使用 ts_split 函数创建了一个名为 split_inf 的对象,它本质上是 inf,但被分成两部分。对象 inf 分为两部分,其中测试集由命令 sample.out 给出。我们将 sample.out 设置为等于 12,即 12 个月或一年。因此,我们希望我们的测试(验证)周期等于一年。之后,我们创建两个对象(培训和测试),这将创建两个独立的系列。使用 length 命令,我们可以确定每个生成的序列中有多少个周期。您会注意到,定型数据集有 232 个周期,而测试数据集有 12 个周期(与 sample.out 选项指定的数量相同)。

诊断训练集

至少对实现什么模型有一些概念是很重要的。要做到这一点,我们需要尝试和诊断我们必须的训练数据集,看看我们是否可以提出关于哪个模型可能适合该系列的建议。为此,我们恳求使用 arima_diag()命令。

arima_diag(training)

运行这个程序,我们就能得到要跟踪的数字。由于这是使用 plot.ly 创建的,因此交互性很强。我们可以看到,它显示了训练数据集的值以及相关的 ACF 和 PACF。它还向我们展示了差异训练系列的图表。我们可以看到,ACF 正以几何级数下降,在 PACF 看到了一个直接的截止。这类似于我们对 ar 模型的预期模式。要确定要使用的滞后数量,请注意在 PACF 中,前两个滞后仍然很重要。在第二个滞后之后,大多数剩余的滞后是不重要的。现在,让我们猜测两个自回归滞后。还要注意,在 PACF 和 ACF 中,有红色的数据点。这些红色的数据点表明了季节性滞后的可能性。

ARIMA 诊断图

构建预测模型

让我们试着预测具有三种不同规格的三种模型。我们将尝试使用的三种模型是

安 ARIMA(2,1,1)

萨里玛(2,1,1)(1,0,0)

该模型使用 auto.arima()函数确定了最合适的值

对于第一个模型,我们将尝试使用 2 个自回归滞后,因为这是 PACF 所表明的。我们将对序列进行一次差分,因为我们知道在不同的水*上,序列是不稳定的,如 ADF、PP 和 KPSS 检验的结果所示。我们猜测我们有 1 移动*均线滞后。对于第二个模型,我们将使用与第一个相同的规范,只是我们添加了一个季节性自回归滞后。最后,对于第三个模型,我们使用 R 中内置的 auto.arima()函数来避免猜测选择哪个 lag 规范是最好的。

让我们转到模型 1。我们创建一个名为 arima211 的对象,并使用 arima()命令进行建模。arima()命令中的第一个选项是 training,这是我们将使用的系列。阶数选项指定了 ARIMA 的阶数,在这种情况下,我们指定了一个具有两个自回归滞后、一个*稳化差异(即序列是 1 阶的积分)和一个移动*均滞后的 ARIMA。autoplot()命令检查是否满足稳定性条件。这就是第二节中阐述的*稳性条件。由于我们处理的是逆根,所以所有的逆根都必须在单位圆内。最后,check_res 命令提供对残差的诊断,我们希望残差是白噪声。模型 2 的结构与此相同,只是我们在调用 arima()命令时添加了一个季节性订单。在这种情况下,我们添加 1 个季节性自回归滞后。模型 3 的结构与此相同,只是我们让 R 使用 auto.arima()命令来决定顺序。选项 search = TRUE 只是确保它可以选择一个 SARIMAmodel,如果它认为它是最佳的。

#For Model 1arima211 <- arima(training, order = c(2,1,1))
autoplot(arima211)
check_res(arima211)#For Model 2 sarima2111 <- arima(training, order = c(2,1,1), seasonal = list(order = c(1,0,0)))
autoplot(sarima2111)
check_res(sarima2111)#For Model 3auto <- auto.arima(training, seasonal = TRUE)
auto #We obtained a SARIMA(2,1,0)(2,0,1) based on auto.arima()
autoplot(auto)
check_res(auto)

如果你做对了,你应该会看到后面的数字。请注意,对于所有三个模型,根都在单位圆内,因此,模型已经通过了*稳性标准,表明不再有单位根。查看残差图,我们看到所有三个模型的残差通常都是白噪声。然而,我们确实注意到有一些滞后在置信带之外,但毫无疑问,模型 2 和模型 3 相对于模型 1 产生更多的白噪声误差,模型 1 在第 12 个滞后时具有相当显著的 ACF。这种红色滞后是季节性滞后,表明季节性模型更适合。

逆 AR 和 MA 根

残留诊断

生成预测和预测评估

现在我们到了关键时刻。现在让我们使用每个模型生成预测,并根据基线对它们进行评估。每个型号的命令结构相似。首先,我们创建三个对象,即 fcast1、fcast2 和 fcasta,它们代表每个模型的预测。每个对象都是使用 forecast()函数生成的,该函数有两个选项。首先是我们键入它将使用什么模型进行预测。第二个是要预测的周期数。由于测试数据集有 12 个周期长,我们将范围 h 设置为 12。接下来,我们使用 test_forecast()命令将预测值与实际值进行比较。该命令生成一个交互式图表,并将每个预测与实际值进行比较,同时还显示每个数据点的关键预测质量指标。最后,accuracy()命令生成我们在上一节中讨论的预测指标的完整*均值。accuracy()命令中的第一个选项是将每个模型生成的预测与测试或验证系列进行比较。

我们可以在下图中看到实际值与预测值的对比图。我们注意到,使用 auto.arima()命令生成的规范的模型 3 似乎是基于 fit 的最佳模型。请注意,当我们生成这些图表时,我们可以悬停在每个数据点上,它会给我们。

#For Model 1fcast1 <- forecast(arima211, h = 12)
test_forecast(actual = inf, forecast.obj = fcast1, test = testing)
accuracy(fcast1,testing)#For Model 2fcast2 <- forecast(sarima2111, h = 12)
test_forecast(actual = inf, forecast.obj = fcast2, test = testing)
accuracy(fcast2,testing)#For Model 3fcasta <- forecast(auto, h = 12)
test_forecast(actual = inf, forecast.obj = fcasta, test = testing)
accuracy(fcasta,testing)

预测与实际

预测指标

进一步使用 accuracy()命令,我们可以看到每个模型的预测统计比较。预测指标如下表所示,由 accuracy()命令生成。我们可以看到从模型 1 到模型 2 以及从模型 2 到模型 3 的改进。这表明添加季节滞后是至关重要的,基于这些指标,auto.arima()生成的模型似乎是最佳的。

样本外预测

既然我们知道了预测的最佳模型,我们现在将生成一个样本外预测。在这种情况下,我们不知道数列的实际值。我们只能利用我们所拥有的任何信息来预测未来。本质上,这是你一直期待的预测。

生成最佳拟合

与生成模型类似,我们创建一个对象,在其中存储选择的模型。我们不使用训练数据,而是使用 inf 的整个膨胀序列。然后,我们测试逆 AR 和 MA 根以及残差。

finalfit <- auto.arima(inf, seasonal = TRUE)
autoplot(finalfit)
check_res(finalfit)

最终装配诊断

我们发现所有的逆根都在 AR 和 MA 单位圆内。这样,我们满足了稳定性条件,不再有任何单位根。在残差诊断中,虽然仍有一些明显的滞后,但通常已经是白噪声了。

生成样本外预测

我们现在使用我们选择的模型进行预测。以下命令将生成预测。由于通货膨胀通常会被重新预测,让我们设定一个 4 个月的短期范围。然后,让我们看看它对 2020 年 5 月至 8 月通胀率的预测。summary()命令列出了未来四个月的点预测和置信区间。

fcastf <- forecast(inf, model = finalfit, h = 4)
plot_forecast(fcastf)
summary(fcastf)

2020 年 5 月至 8 月通胀率预测

我们可以看到,5 月(2.0%)、6 月(2.1%)、7 月(2.1%)和 8 月(2.1%)的预测值与 BSP 的通胀目标和其他预测估计值相当一致。还要注意,随着地*线变得越来越大,置信带也随之扩大。干得好,你刚刚预测了你的第一个关键经济变量。

结论

我们现在已经对样本外进行了预测,并获得了未来四个月的值。随着时间的推移,我们将会看到我们的预测是否确实可靠。可以说,预测是一个反复试验的过程,但我希望您看到指标和内置函数能够消除这一过程中的猜测。尽管如此,预测也是一门艺术,根据经济结构和直觉确定滞后和条件可能在改善预测方面发挥关键作用。当我们讨论多变量预测时,我们将会看到更多。

现在,建议您使用您现在已经学习过的许多工具进行试验,看看您是否能找到一个模型,它提供的预测质量指标甚至比使用 auto.arima()函数选择的模型还要好。这当然是可能的,它只是表明,虽然机器已经进步了这么多,但在一个充满数学和科学的地方,仍然有艺术的空间。一个人只需要寻找这样做的动机。

为了获得更多的实践经验,我制作了这篇文章的视频,可以在我的 YouTube 频道上找到。

参考

1布鲁克斯,C. 金融计量经济学导论。(2019)剑桥大学出版社。

2汉密尔顿,j .时间序列计量经济学。(1994) 普林斯顿大学出版社,普林斯顿

基于主成分分析的人脸数据集压缩

原文:https://towardsdatascience.com/face-dataset-compression-using-pca-cddf13c63583?source=collection_archive---------27-----------------------

用于图像数据集压缩的主成分分析

照片由 Unsplash 上的 Grzegorz Walczak 拍摄

在我的上一篇文章中,我们采用了一种图形化的方法来理解主成分分析是如何工作的,以及如何将其用于数据压缩。如果您对这个概念不熟悉,我强烈建议您在继续之前阅读我以前的文章。我提供了以下链接:

[## 主成分分析—可视化

使用主成分分析(PCA)的数据压缩

towardsdatascience.com](/principal-component-analysis-visualized-17701e18f2fa)

在本文中,我们将了解如何使用 PCA 来压缩现实生活中的数据集。我们将在野外(LFW),使用标记的人脸,这是一个由 13233 张人脸灰度图像组成的大规模数据集,每张图像的尺寸为 64x64 。这意味着每个面的数据是 4096 维的(每个面要存储 64×64 = 4096 个唯一值)。我们将使用主成分分析将这一维度要求降低到几百个维度!

介绍

主成分分析(PCA)是一种用于降低数据集维度的技术,利用了这些数据集中的图像具有共同点的事实。例如,在由脸部照片组成的数据集中,每张照片都有像眼睛、鼻子、嘴巴这样的面部特征。我们可以为每种类型的特征制作一个模板,然后将这些模板组合起来,生成数据集中的任何人脸,而不是逐个像素地对这些信息进行编码。在这种方法中,每个模板仍然是 64x64 = 4096 维,但是由于我们将重用这些模板(基函数)来生成数据集中的每个面,因此所需的模板数量很少。PCA 正是这样做的。让我们看看如何!

笔记本

您可以在此处查看 Colab 笔记本:

[## PCA

colab.research.google.com](https://colab.research.google.com/drive/1QZYqjLm_rLxkgR6COMjjBicHSLMwKxF-)

资料组

让我们从数据集中可视化一些图像。你可以看到每个图像都有一张完整的脸,并且像眼睛、鼻子和嘴唇这样的面部特征在每个图像中都清晰可见。现在我们已经准备好数据集,让我们压缩它。

压缩

五氯苯甲醚是一个 4 步流程。从包含 n 个维度的数据集开始(需要表示 n 个轴):

  • 步骤 1 :找到一组新的基函数(n-轴),其中一些轴对数据集中的方差贡献最大,而其他轴贡献很小。
  • 第二步:按照方差贡献度递减的顺序排列这些轴。
  • 第三步:现在,选择要使用的顶部 k 轴,放下剩余的 n-k 轴。
  • 步骤 4 :现在,将数据集投影到这些 k 轴上。

这些步骤在我之前的文章中有很好的解释。在这 4 个步骤之后,数据集将从 n 维压缩到仅 k 维(k**n)。

第一步

找到一组新的基函数(n-轴),其中一些轴贡献了数据集中的大部分方差,而其他轴贡献很小,这类似于找到我们稍后将组合以在数据集中生成人脸的模板。总共将生成 4096 个模板,每个模板的维度为 4096。数据集中的每个人脸都可以表示为这些模板的线性组合。

请注意,标量常数(k1,k2,…,kn)对于每个面都是唯一的。

第二步

现在,这些模板中的一些对面部重建贡献很大,而另一些贡献很小。这种贡献水*可以量化为每个模板对数据集贡献的方差百分比。因此,在这一步,我们将按照方差贡献的降序排列这些模板(最重要…最不重要)。

第三步

现在,我们将保留顶部的 k 个模板,删除其余的。但是,我们应该保留多少模板呢?如果我们保留更多的模板,我们的重建图像将非常类似于原始图像,但我们将需要更多的存储空间来存储压缩数据。如果我们保留的模板太少,我们重建的图像将与原始图像非常不同。

最佳解决方案是确定我们希望在压缩数据集中保留的方差百分比,并使用它来确定 k 的值(要保留的模板数量)。如果我们计算一下,我们发现要保留方差的 99%,我们只需要顶部的 577 个模板。我们将把这些值保存在一个数组中,并删除剩余的模板。

让我们来看看这些模板。

请注意,这些模板看起来都有点像人脸。这些被称为特征脸。

第四步

现在,我们将构建一个投影矩阵,将图像从原来的 4096 维投影到 577 维。投影矩阵将有一个形状 (4096,577) ,其中模板将是矩阵的列。

在我们继续压缩图像之前,让我们花点时间来理解压缩的真正含义。回想一下,这些面可以通过所选模板的线性组合来生成。由于每个面都是唯一的,因此数据集中的每个面都需要一组不同的常数(k1,k2,…,kn)来进行线性组合。

让我们从数据集中的图像开始,计算常数(k1,k2,…,kn),其中 n = 577。这些常数连同所选择的 577 个模板可以被插入到上面的等式中以重建面部。这意味着我们只需要为每幅图像计算和保存这 577 个常数。我们可以使用矩阵同时计算数据集中每个图像的常数,而不是逐个图像地进行计算。

回想一下,数据集中有 13233 幅图像。矩阵 compressed_images 包含数据集中每个图像的 577 个常数。我们现在可以说,我们已经将图像从 4096 维压缩到 577 维,同时保留了 99%的信息。

压缩比

让我们计算一下数据集压缩了多少。回想一下,数据集中有 13233 幅图像,每幅图像的尺寸都是 64x64。因此,存储原始数据集所需的唯一值总数为
13233 x 64 x 64 = 54,202,368 个唯一值

压缩后,我们为每个图像存储 577 个常数。因此,存储压缩数据集所需的唯一值总数为
13233 x 577 = 7,635,441 个唯一值。但是,我们还需要存储模板,以便以后重建图像。因此,我们还需要为模板存储
577 x 64 x 64 = 2,363,392 个唯一值。因此,存储压缩数据集所需的唯一值总数为
7,635,441 + 2,363,392 = 9,998,883 个唯一值

我们可以将压缩百分比计算为:

重建图像

压缩后的图像只是长度为 577 的数组,因此无法可视化。我们需要将其重建回 4096 维,以形状数组(64x64)的形式查看。回想一下,每个模板的尺寸都是 64x64,每个常数都是一个标量值。我们可以使用下面的等式来重建数据集中的任何人脸。

同样,我们可以使用矩阵一次性重建整个数据集,而不是逐个图像地进行重建,当然会损失 1%的方差。

我们来看一些重建的人脸。

作者图片

我们可以看到,重建的图像已经捕获了关于人脸的大部分相关信息,并且忽略了不必要的细节。这是数据压缩的额外优势,它允许我们过滤数据中不必要的细节(甚至噪音)。

那都是乡亲们!

如果你成功了,向你致敬!在这篇文章中,我们了解了 PCA 如何用于压缩在野外(LFW)标记的人脸,这是一个由 13233 个人脸图像组成的大规模数据集,每个图像的尺寸为 64x64 。我们将该数据集压缩了 80%以上,同时保留了 99%的信息。可以查看我的 Colab 笔记本 了解代码。我鼓励您使用 PCA 来压缩其他数据集,并评论您获得的压缩率。

有什么建议请留言评论。我定期写文章,所以你应该考虑关注我,在你的订阅中获得更多这样的文章。

如果你喜欢这篇文章,你可能也会喜欢这些:

[## 机器学习—可视化

理解机器学习的视觉方法

towardsdatascience.com](/machine-learning-visualized-11965ecc645c) [## 用 Pytorch 检测人脸标志点

想知道 Snapchat 或 Instagram 如何将惊人的滤镜应用到你的脸上吗?该软件检测你的关键点…

towardsdatascience.com](/face-landmarks-detection-with-pytorch-4b4852f5e9c4)

访问我的网站,了解更多关于我和我的工作的信息:

[## 阿卜杜勒·拉赫曼

让我们让电脑智能化吧!

arkalim.netlify.app](https://arkalim.netlify.app/)

面向初学者的 10 行人脸检测

原文:https://towardsdatascience.com/face-detection-in-10-lines-for-beginners-1787aa1d9127?source=collection_archive---------32-----------------------

使用 Python OpenCV 在图像和视频中检测人脸的介绍

我最*在为一个个人项目探索 OpenCV 的 Haar 级联对象检测模块。虽然网上有很多这方面的技术资料,但我这篇文章的重点是用通俗易懂的语言解释这些概念。我希望这将有助于初学者以简单的方式理解 Python 的 OpenCV 库。

在这个演示中,我们将拍摄一张图像并在其中搜索人脸。我们将使用预训练的分类器来执行该搜索。我计划分享更多关于我们将来如何训练我们自己的模型的文章。但是现在,让我们开始使用一个预先训练好的模型。

对于外行来说,OpenCV 是一个 Python 库,主要用于各种计算机视觉问题。

在这里,我们使用的是来自 opencv github 资源库作为我们的模型。您可以下载这个 xml 文件,并将其放在与 python 文件相同的路径中。这里还有一堆其他的模型,你可能想以后尝试一下(例如:-眼睛检测,全身检测,猫脸检测等。)

在开始编写代码之前,让我们先看一下程序的高级流程。

下面描述的整个过程的图表[输入、面部检测过程和输出]

输入:

该算法需要两个输入:

  1. 输入图像矩阵(我们将读取一个图像并将其转换为数字矩阵/numpy 数组)
  2. 脸部特征(可在Haar cascade _ frontal face _ default . XML文件中找到)

人脸检测过程:

OpenCV 的哈尔级联分类器基于滑动窗口方法。在这种方法中,一个窗口(默认大小为 20×20 像素)在图像上滑动(逐行)以寻找面部特征。每次迭代后,图像按一定的因子缩小(调整大小)(由参数' 比例因子 '决定)。每次迭代的输出被存储,并且在较小的、调整大小的图像上重复滑动操作。在最初的迭代过程中可能会出现误报,这将在本文后面详细讨论。这种缩小和开窗过程一直持续到图像对于滑动窗口来说太小为止。比例因子的值越小,精度越高,计算费用越高。

输出:

我们的输出图像将在每个检测到的人脸周围包含一个矩形。

代码&解释:

让我们从 python 代码开始。对于这个实验,我们将需要以下 Python 包:

**pip install numpy
pip install opencv-python**

让我们把我们的 python 文件叫做‘face _ detector . py’,把它放在与我们从上面分享的 github 链接下载的 xml 文件相同的路径中。

**# File Name: face_detector.py
# Import the OpenCV library
import cv2**

现在让我们看看承诺的 10 行!

我们准备了 2 个输入[ 输入图像 & 面部特征 XML],如上面流程图中所示。

我用贝丝·哈米蒂的这张美丽的照片(下面的链接)作为我的输入图像(kids.jpg)。

照片由 Pexels贝丝·哈米蒂拍摄

1 我们首先加载 xml 分类器和输入图像文件。由于输入文件相当大,我已经用与原始分辨率相似的尺寸调整了大小,这样它们就不会显得太大。然后,我把图像转换成灰度图像。灰度图像被认为提高了算法的效率。

**face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
image = cv2.imread("kids.jpg")
image = cv2.resize(image, (800,533))
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)**

读取的图像存储为多维 numpy 数组,如下所示。

**print(type(gray_image))
<class 'numpy.ndarray'>**

在下一步中,我们将 gray_image 作为输入传递给 detectMultiScale 方法。

detect multi scale方法将为我们执行检测。它采用以下参数:

scaleFactor : 该参数指定图像缩小的因子,例如:-如果该值为 1.05,则图像缩小 5%。如果该值为 1.10,则图像缩小 10%。比例因子 1.10 比比例因子 1.05 需要更少的计算。

****最小邻居:这是一个阈值,指定每个矩形应该有多少个邻居才能被标记为真正。换句话说,让我们假设每次迭代标记某些矩形(即,将图像的一部分分类为面部)。现在,如果随后的迭代也将相同的区域标记为阳性,则增加了该矩形区域为真阳性的可能性。如果某个区域在一次迭代中被识别为人脸,但在任何其他迭代中没有被识别为人脸,则它们被标记为假阳性。换句话说,minNeighbors 是一个区域被确定为一个面的最小次数。

让我们做一个实验来更好地理解它。我们将使用不同的 minNeighbors 参数值运行我们的代码。

对于 minNeighbors = 0,

所有的矩形都被检测为面。对于一些矩形,有许多重叠的矩形,这意味着这些矩形在多次迭代中被检测为阳性。我们设置阈值来提高算法的准确性。

minNeighbors = 0 的阳性[图片来自 Pexels贝丝·哈米蒂

明邻= 2

当 minNeighbors = 2 时,大多数重叠矩形不再存在。然而,我们仍然有一些误报。

minNeighbors = 2 的阳性[照片由贝丝·哈米蒂像素拍摄]

如果我们将这个阈值增加到 4 或 5,我们可以看到不再有假阳性。让我们将这个值设置为 5,然后继续。

**faces=face_cascade.detectMultiScale(gray_image,scaleFactor=1.10,minNeighbors=5)**

detect multi scale方法返回一个 numpy 数组,其中包含面的矩形的尺寸和位置。

x,y-矩形左上角的位置

w,h-矩形的宽度和高度

我们现在用绿色(0,255,0) (BGR 色码)画一个矩形,边界厚度= 1。

该窗口等待 2 秒(2000 毫秒)并自动关闭。

**for x,y,w,h in faces:
    image=cv2.rectangle(image, (x,y), (x+w, y+h), (0, 255, 0),1)
    cv2.imshow("Face Detector", image)
    k=cv2.waitKey(2000)
cv2.destroyAllWindows()**

或者,我们也可以通过添加下面一行来保存图像。

**cv2.imwrite("kids_face_detected.jpeg", image)**

我们的输出图像现在在每个检测到的人脸周围包含一个绿色矩形。

误报 minNeighbors = 5[图片来自 Bess Hamiti 来自 Pexels

我希望这篇文章能让您对如何在 python 中使用 OpenCV 进行人脸检测有一个基本的了解。我们也可以扩展这段代码来跟踪视频中的人脸。如果你感兴趣的话,我已经在我的 GitHub 储存库这里上传了上面讨论的和用于跟踪网络摄像头视频中的人脸的完整代码。祝你有美好的一天!

** [## 在 5 分钟内制作一个声控鼠标/键盘

Python 中语音识别和 GUI 自动化的初学者指南

medium.com](https://medium.com/@b.arindom/build-a-voice-controlled-mouse-keyboard-in-5-minutes-952bc8f101fc) [## 用 Python 生成 5 行二维码

也许在你的简历中使用它来链接到你的网站或 LinkedIn 个人资料

towardsdatascience.com](/generate-qrcode-with-python-in-5-lines-42eda283f325) [## 绝对初学者的神经网络

用简单的英语介绍感知器

medium.com](https://medium.com/swlh/artificial-neural-networks-for-absolute-beginners-a75bc1522e1d)

参考文献&延伸阅读:

1级联分类器,https://docs . opencv . org/2.4/modules/obj detect/doc/Cascade _ classification . html

2 5KK73 GPU 分配,https://sites . Google . com/site/5kk 73 GPU 2012/Assignment/viola-Jones-face-detection

3 OpenCV Github 页面,https://Github . com/OpenCV/OpenCV/tree/master/data/Haar cascades**

仅用 5 行代码实现人脸检测

原文:https://towardsdatascience.com/face-detection-in-just-5-lines-of-code-5cc6087cb1a9?source=collection_archive---------19-----------------------

使用世界上最简单的人脸识别 python 库来识别和操作人脸。

从印度尼西亚一群孩子的图像中检测人脸。图片由 Pixabay 提供。

F 王牌检测是深度学习的计算机技术师。它识别数字图像或视频场景中的人脸。它被用于多种应用,如面部识别、解锁智能手机、智能广告、情感推断等等。

深度学习是人工智能(AI)中机器学习的子集,它拥有能够从非结构化或无标签的数据中进行无监督学习的网络。

“计算机现在能够看、听和学习。欢迎来到未来!”—戴夫·沃特斯

在这个初学者教程中,我们将学习如何安装和配置 python 环境,使用集成开发环境(ide)来调试和运行我们的 python 代码。然后我们将使用广泛流行的人脸检测和操作库Adam Geitgey 开发的人脸识别。我们将在检测到的 faces🕵.周围定制不同颜色和边框形状的图像它是使用 dlib 最先进的具有深度学习功能的人脸识别技术构建的。该模型在 Wild 基准中的标记人脸上具有 99.38%的准确率。

TL;博士本教程是为绝对初学者准备的,即使你是刚毕业的学生或者是期待使用 python 开始机器学习的人。像 Web 和移动开发者后端开发者这样的技术堆栈开发者也可以轻松地阅读这篇文章。那么,让我们开始新的简短的代码之旅。

环境配置和安装

首先我们需要下载 Python 的最新稳定版本。

通常有两种著名的方法来配置 python 环境并在我们的计算机上安装软件包——pip 或 condo。

python 包包含模块所需的所有文件。模块是可以包含在项目中的 Python 代码库。

  1. PIP-一个用于 Python 包的包管理器。
  2. Anaconda-一个完整的 python 环境解决方案,运行不同版本,管理所有 python 包。使用 Anaconda Navigator,您可以安装和管理计算机中的所有软件包。

您可以关注其中任何一个或两个。

代码编辑器和 IDE

除了基本的 python REPL (命令行界面),我们可以在这两个专业编辑器中运行我们的 python 程序

  1. py charm-下载热门面向专业开发者的 Python IDE 并开始。它就像其他著名的 IDE 一样,启动和使用都很简单。
  2. Jupyter 笔记本 - 被程序员和专业培训师广泛使用的基于网络的代码编辑器。

使用康达安装 Jupyter 笔记本电脑

conda install -c conda-forge notebook

或者使用 pip 安装,然后运行 Jupiter notebook 来运行它-

pip install notebook
jupyter notebook

这足以让我们开始编写第一个 Python 程序并运行它。你可以使用上面的任何一个编辑器。在我们的教程中,我们将使用 PyCharm 编写带有 pip 包管理器的代码来安装包。

所以,让我们开始在任何给定的图像和照片中检测人脸。你不兴奋吗?😀

giphy.com 的 Gif

首先,让我们安装代码运行所需的库。我们将只安装和导入 2 个库。

  1. - 友好的 PIL 叉(Python 影像库)。
  2. -检测图像中的人脸。
**pip install Pillowpip install face-recognition**

您可以创建一个 python 类型的新文件(扩展名为)。py )或者 Jupyter 笔记本中的新笔记本开始编码— face_detection.py 。如果它需要其他相关的库,你也可以使用 pip 或 conda 简单地安装它们。

让我们在代码中导入上述库-

****import** PIL.Image
**import** PIL.ImageDraw
**import** face_recognition**

第一行

让我们在代码文件所在的文件夹中选择一个名为 GroupYoga.jpg 的图片(你可以选择任何图片),或者给出图片的正确路径。我们应该从 face_recognition 库中将我们的图像加载到 load_image_file() 方法,该方法会将它转换成该图像的 NumPy 数组。我们把它赋给变量名 given_image

**given_image = face_recognition.load_image_file(**'GroupYoga.jpg'**)**

第二行

使用同一个库中的 face_locations() 方法,我们将计算给定 _image 中的人脸数量,并将打印图像中找到的所有人脸的长度。

**face_locations = face_recognition.face_locations(given_image)

number_of_faces = len(face_locations)
print(**"We found {} face(s) in this image."**.format(number_of_faces))**

第 3 行

现在,为了在图像上绘制任何形状,我们将使用 PIL.Image 中的 fromarray() 方法将图像转换为枕头库对象。

**pil_image = PIL.Image.fromarray(given_image)**

第 4 行

现在,我们将运行一个 for-in 循环来打印四个像素位置,如检测到的人脸的上、左、下和右。

****for** face_location **in** face_locations:top, left, bottom, right = face_location
    print(**"A face is detected at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}"**.format(top, left, bottom, right))**

第 5 行

我们将绘制一个绿色的矩形框,宽度为 10。您也可以将形状更改为多边形或椭圆形。所以,在上面的循环中写下面的两个绘制方法。

**draw = PIL.ImageDraw.Draw(pil_image)
draw.rectangle([left, top, right, bottom], outline=**"green"**, width=10)**

现在,只需使用变量 pil_image 来显示我们的新图像,其中检测到的人脸周围使用矩形边框。

**pil_image.show()**

新的临时映像将在您的计算机上自动打开(如果一切设置正确)。它应该是类似下图的东西-

检测到做瑜伽的女人的脸。图片由 Pexels 提供。

答对了。🎉

如果您遇到任何编译时或运行时问题以及环境配置问题,您可以在下面的回复部分写下,或者与我联系。

现在,让我们把上面所有的小代码片段收集到一个文件中,这个文件可以在任何 python 环境中运行。让我们使用学校孩子的形象(作为文章封面的特色)

face_detection.py 中的完整代码

如果您运行上面的文件(PyCharm 或 Notebook 中的 run 按钮),如果一切正常(我指的是编译或运行时错误),您将在编辑器的控制台得到下面的输出-

PyCharm 中的控制台输出

就是这样。我们最简单的人脸检测🎭代码已准备好从任何给定的照片中识别人脸。您可以通过更改颜色、边框类型和宽度来自定义上面的代码。我建议尝试定制,并探索其他方法和选项。

Face _ recognitionlibrary 还可以用来在人脸上进行数码化妆,在一群人中检查相似的人脸,围绕这些检测到的人脸开发一些游戏。****

我相信你会发现它是互联网上所有技术文章中最简单的人脸检测教程之一。您可以通过下面的参考资料来了解这个库的更多细节。对于这个库的其他应用,下次我会写一些其他的文章。

资源:

**** [## 人脸识别

查找图片中的面孔查找出现在图片中的所有面孔:查找和处理图片中的面部特征获取…

pypi.org](https://pypi.org/project/face-recognition/) [## 年龄/面部识别

You can also read a translated version of this file in Chinese 简体中文版 or in Korean 한국어 or in Japanese 日本語. Recognize and…

github.com](https://github.com/ageitgey/face_recognition)

在 Medium 上关注我,让我们在 LinkedIn(@ kapilraghuwanshI)和 Twitter ( @techygeeek y)上保持联系,以获取更多此类有趣的科技文章。🤝****

人脸检测模型:使用哪一个,为什么?

原文:https://towardsdatascience.com/face-detection-models-which-to-use-and-why-d263e82c302c?source=collection_archive---------1-----------------------

在 Python 中实现不同人脸检测模型的完整教程之后,通过比较,找出用于实时场景的最佳模型。

Unsplash 上由 Jerry Zhang 修改的照片。

人脸检测是计算机视觉最基本的方面之一。这是许多进一步研究的基础,如识别特定的人,在脸上标记关键点。最*,由于种族定性事件,新闻报道很多,如这里的和这里的所述,有色人种比白人更容易被误解。因此,像 IBM、微软和亚马逊这样的主要科技公司已经禁止他们的系统被警方使用。然而,本文不会详细讨论这些方面,我们只会尝试使用预先训练的模型在人脸上绘制边界框,如 Haar cascades,dlib 正面人脸检测器,MTCNN,以及使用 OpenCV 的 DNN 模块的 Caffe 模型。然后我们将对它们进行比较,找出哪一个最适合实时应用程序。

目录

  • 介绍
  • 装置
  • 为模型编码
  • 比较图像结果
  • 视频比较结果以及达到的帧速率
  • 结论

介绍

我们将使用 Haar、dlib、多任务级联卷积神经网络(MTCNN)和 OpenCV 的 DNN 模块。如果您已经了解它们,或者不想了解它们的技术细节,可以跳过这一部分,直接进入代码。否则,让我们学习它们是如何工作的。

哈尔瀑布

早在 2001 年,保罗·维奥拉(Paul Viola)和迈克尔·琼斯(Micheal Jones)在他们的论文“使用简单特征的增强级联进行快速物体检测”中提出了这些方法它的工作速度非常快,就像简单的 CNN 一样,可以从图像中提取很多特征。然后通过 Adaboost 选择最佳特性。这样就把原来的 160000+的特征减少到了 6000 个特征。但是在滑动窗口中应用所有这些特性仍然需要很多时间。因此,他们引入了一系列分类器,对特征进行分组。如果窗口在第一阶段失败,则该级联中的这些剩余特征不会被处理。如果通过,则测试下一个特征,并重复相同的过程。如果一个窗口可以通过所有的特征,那么它被分类为面部区域。更详细的阅读,可以参考这里

哈尔级联需要大量的正负训练图像来训练。幸运的是,这些级联与 OpenCV 库以及经过训练的 XML 文件捆绑在一起。

正面人脸检测器

Dlib 是一个 C++工具包,包含用于解决现实世界问题的机器学习算法。虽然它是用 C++编写的,但它有 python 绑定来在 python 中运行。它还有一个很棒的面部标志关键点检测器,我在以前的一篇文章中使用它来制作一个实时凝视跟踪系统。

[## 使用 OpenCV 和 Dlib 的实时眼睛跟踪

在本教程中,学习通过 python 中的网络摄像头创建一个实时凝视探测器。

towardsdatascience.com](/real-time-eye-tracking-using-opencv-and-dlib-b504ca724ac6)

dlib 提供的正面人脸检测器使用通过梯度方向直方图(HOG)提取的特征,然后通过 SVM。在 HOG 特征描述符中,梯度方向的分布被用作特征。此外,Dlib 提供了一个更先进的基于 CNN 的人脸检测器,但是,它不能在 CPU 上实时工作,这是我们正在寻找的目标之一,因此在本文中被忽略。尽管如此,如果你想了解它,你可以参考这里的。

MTCNN

它是由张等人于 2016 年在他们的论文“使用多任务级联卷积网络的联合人脸检测和对齐”中介绍的它不仅检测面部,还检测五个关键点。它使用三级 CNN 的级联结构。首先,它们使用完全卷积网络来获得候选窗口及其包围盒回归向量,并且使用最大值抑制(NMS)来重叠高度重叠的候选窗口。接下来,这些候选者被传递到另一个 CNN,该 CNN 拒绝大量的假阳性并执行边界框的校准。在最后阶段,执行面部标志检测。

OpenCV 中的 DNN 人脸检测器

它是一个基于单触发多盒探测器(SSD)的 Caffe 模型,使用 ResNet-10 架构作为其主干。它是在 OpenCV 3.3 之后在其深度神经网络模块中引入的。也可以使用量子化张量流版本,但我们将使用 Caffe 模型。

装置

Dlib 和 MTCNN 都是 pip 可安装的,而 Haar Cascades 和 DNN 人脸检测器需要 OpenCV。

pip install opencv-python
pip install dlib
pip install mtcnn

如果您使用的是 Anaconda,那么请使用 conda 命令安装它们:

conda install -c conda-forge opencv
conda install -c menpo dlib
conda install -c conda-forge mtcnn

为模型编码

照片由法比安·格罗斯Unsplash 拍摄

在这一节中,我将解释所有这些不同模型的代码。Dlib 和 MTCNN 的基于 HOG 的描述符的权重已经预先与它们的安装捆绑在一起。Haar cascade XML 文件以及 DNN 模块的人脸检测器的权重和图层文件可以从我的 Github repo 下载。

哈尔瀑布

import cv2classifier = cv2.CascadeClassifier('models/haarcascade_frontalface2.xml')
img = cv2.imread('test.jpg')
faces = classifier.detectMultiScale(img)# result
#to draw faces on image
for result in faces:
    x, y, w, h = result
    x1, y1 = x + w, y + h
    cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 2)

如你所见,使用哈尔级联很容易做出预测。只需使用cv2.CascadeClassifier初始化模型,然后使用cv2.detectMultiScle进行检测。然后循环所有的脸,并把它们画到图像上。

基于 Dlib HOG 的正面人脸检测器

import dlib
import cv2detector = dlib.get_frontal_face_detector()
img = cv2.imread('test.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = detector(gray, 1) # result
#to draw faces on image
for result in faces:
    x = result.left()
    y = result.top()
    x1 = result.right()
    y1 = result.bottom()
    cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 2)

与所有其他模型不同,Dlib 适用于灰度图像。它返回一个“dlib 模块的矩形对象”,该对象不仅包含坐标,还包含其他信息,如面积和中心。

MTCNN

import cv2
from mtcnn.mtcnn import MTCNNdetector = MTCNN()
img = cv2.imread('test.jpg')
faces = detector.detect_faces(img)# result
#to draw faces on image
for result in faces:
    x, y, w, h = result['box']
    x1, y1 = x + w, y + h
    cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 2)

mtcnn.mtcnn加载 MTCNN 模块并初始化。函数detect_faces用于查找结果。这将返回一个 JSON 风格的字典,其中包含人脸的坐标以及它们的预测置信度和检测到的面部标志的坐标。

DNN 模块正面人脸检测器

import cv2
import numpy as npmodelFile = "models/res10_300x300_ssd_iter_140000.caffemodel"
configFile = "models/deploy.prototxt.txt"
net = cv2.dnn.readNetFromCaffe(configFile, modelFile)
img = cv2.imread('test.jpg')
h, w = img.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(img, (300, 300)), 1.0,
(300, 300), (104.0, 117.0, 123.0))
net.setInput(blob)
faces = net.forward()
#to draw faces on image
for i in range(faces.shape[2]):
        confidence = faces[0, 0, i, 2]
        if confidence > 0.5:
            box = faces[0, 0, i, 3:7] * np.array([w, h, w, h])
            (x, y, x1, y1) = box.astype("int")
            cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 2)

使用cv2.dnn.readNetFromCaffe加载网络,并将模型的层和权重作为参数传递。这可以在 OpenCV DNN 的 Github 页面上找到。

为了达到最佳精度,在尺寸调整为*300x300*的 BGR 图像上运行该模型,相应地对每个蓝色、绿色和红色通道应用值*(104, 177, 123)*的*均减法。

绿色的价值有很大的差异。在 pyimagesearchlearn openv的文章中,我发现他们都使用了 117 而不是 177,所以我在cv2.dnn.blobFromImage函数中使用了 117。最后,返回一个 4-D 数组,该数组包含置信度和缩小到 0 到 1 范围的坐标,从而通过将它们乘以原始宽度和高度,可以获得对原始图像的预测,而不是模型预测的 300x300。

比较图像结果

我创建了两个包含 10 张图片的小型数据库,其中一个是从 Unsplash 创建的,另一个是从 Google 创建的,以了解这些技术在大小图片上的表现。让我们一个一个地检查一下。

不溅

在我开始之前,我想给我使用过的布鲁斯·迪克森克里斯·库里克里斯·莫瑞伊森·约翰逊杰里·张杰西卡·威尔逊罗兰·塞缪尔蒂姆·莫斯霍尔德提供图片致谢。由于图像的*均尺寸约为 5000x5000,因此在处理之前,高度和宽度都减少了一半。

结果

正如预期的那样,Haar cascades 表现最差,也有很多假阳性。Dlib 和 MTCNN 的表现相当均衡,一家领先另一家,反之亦然。DNN 模块有一个全有或全无类型的表现。仔细观察,我们可以看到它在小尺寸的图像上表现不佳,这可能是由于在开始之前将其大小调整为 300x300,所以让我们看看如果采用原始大小,它会如何表现。为此,只需将cv2.dnn.blobFromImage()中的(300, 300)分别更改为原始宽度和高度,并移除调整大小功能。

完整图像的结果

因此,通过拍摄全尺寸图像,结果得到了相当大的改善,然而,这种方式下,DNN 模块无法对面部尺寸较大的情况做出任何预测。示例:

没有检测到人脸

谷歌图片

这些来自 Unsplash 的图像非常大,所以我决定也检查一些小图像,看看它们的性能。所有拍摄的图像都有修改后的可重复使用许可。*均尺寸为 220x220,并且它们是按原样处理的,除了 DNN 模块,在该模块中图像被调整到 300x300 的尺寸,并且如果使用原始尺寸的图像,结果并不好。

这给 Dlib 面部检测器带来了一个问题,因为它不能检测小于 80x80 大小的面部,并且由于图像非常小,面部甚至更小。因此,为了测试,图像被放大了 2 倍,但这在使用 Dlib 时是一个巨大的问题,因为面部尺寸不能非常小,并且对图像进行上采样会导致更多的处理时间。

结果

正如所料,哈尔再次表现最差。MTCNN 给出了完美的结果,除了几张图片,总共不能识别两张脸。DNN 紧随其后,无法识别 3 张面孔。Dlib 漏掉了更多的面孔,我们也不应该忘记它已经将图像放大了 2 倍。

因此,在进入视频部分之前,让我们回顾一下我们从本部分的结果中学到的东西。

  • Haar 是相当过时的,并且通常给出最差的结果。
  • OpenCV 的 DNN 模块的面部检测模型工作得很好,但是如果图像的尺寸非常大,那么它会引起问题。一般来说,我们不处理这种 3000x3000 的图像,所以这应该不是问题。
  • Dlib 不能检测小于 80x80 的人脸,所以如果处理小图像,请确保放大它们,但这会增加处理时间。
  • 所以考虑到以上两点,如果我们要处理极端的脸尺寸,MTCNN 将是最好的选择,可以说是领先竞争到现在。

注意:由于 Dlib 的作者戴维斯·金(Davis King)手动注释的人脸,Dlib 的预测有时会遗漏下巴或前额,因此如果您正在进行的任务无法负担此费用,请不要使用 Dlib。

比较视频中的模型

在开始之前,为什么不澄清我们将在哪些目标上测试我们的模型:

  • 面部的不同角度
  • 头部移动
  • 面部遮挡
  • 不同的照明条件
  • 达到的帧速率

传递给模型的每个帧的大小是 640x360,它们按原样被处理,除了 DNN 模型被减小到 300x300。

面部和头部运动的不同角度

结果(压缩以减小大小)

OpenCV 的 DNN 模块在这里打了一个本垒打。它能够检测到高达疯狂角度的侧脸,并且很大程度上不受快速头部运动的影响。其他人不是它的对手,在大角度和快速移动时失败了。

面部遮挡

结果(再次根据大小进行压缩)

同样,OpenCV 的 DNN 的面部检测模块是这里的明显赢家。让我提供确切的结果。这个视频一共 642 帧。DNN 模块能够检测出其中 601 个人的脸!相比之下,第二名是哈尔,是的哈尔,它在其中的 479 张照片中出现了这张脸,紧随其后的是 MTCNN,有 464 张照片。Dlib 远远落后,只在 401 帧中检测到人脸。

不同的照明条件

这里的目标是看看这些模型在光线很弱的情况下以及当光源在人的正后方时表现如何。

结果

让我们给它应有的荣誉,因为只有哈尔·卡斯卡特是唯一能够在黑暗中在几帧内检测到人脸的模型,而 DNN 模型在那段时间提供了假阳性。当灯打开时,DNN 模块又开始工作,提供完全准确的预测。Dlib 的输出有点不稳定,但比 Haar cascade 要好,Haar cascade 能够预测的帧数更少,也给出了一些假阳性。真正令人惊讶的是 MTCNN。它甚至没有在一帧图像中检测到人脸,这表明如果要使用它,照明条件需要良好。

帧频

报告的值是使用英特尔 i5 第七代处理器获得的,传递的图像大小为 640x360,但 DNN 模块除外,它传递的图像大小为 300x300,这是迄今为止的做法。

哈尔 — 9.25 fps

Dlib — 5.41 fps

MTCNN — 7.92 fps

OpenCV 的 DNN 模块 — 12.95 fps

结论

  • Haar Cascade 分类器在大多数测试中给出了最差的结果,同时还有许多假阳性。
  • Dlib 和 MTCNN 的结果非常相似,略微优于 MTCNN,但 Dlib 无法识别非常小的人脸。此外,如果图像的大小非常极端,并且保证照明良好,遮挡最小,并且主要是正面人脸,MTCNN 可能会在我们比较图像时给出最佳结果。
  • 对于一般的计算机视觉问题,OpenCV 的 DNN 模块的 Caffe 模型是最好的。它可以很好地处理遮挡、快速头部运动,还可以识别侧脸。此外,它还提供了所有游戏中最快的 fps。

所有的代码和文件都可以在我的 Github repo 上找到。该目标是找到最适合在线监考场景中的人脸检测的人脸检测模型。如果你有兴趣了解更多,你可以阅读这篇文章。

[## 使用人工智能实现在线监考自动化

基于视觉和音频的半自动监考功能,以防止在线考试中的作弊和监控…

towardsdatascience.com](/automating-online-proctoring-using-ai-e429086743c8)

使用 Python 使用 Detectron2 和 PyTorch 在自定义数据集上进行人脸检测

原文:https://towardsdatascience.com/face-detection-on-custom-dataset-with-detectron2-and-pytorch-using-python-23c17e99e162?source=collection_archive---------4-----------------------

在自定义人脸检测数据集上微调预训练对象检测模型

原始照片由克里斯托弗·坎贝尔

TL;DR 了解如何为 Detectron2 和 PyTorch 准备自定义人脸检测数据集。微调预先训练的模型,以在图像中找到人脸边界。

观看教程的视频版本

人脸检测是在图像中寻找人脸(边界)的任务。这对于以下方面很有用

  • 安全系统(识别一个人的第一步)
  • 自动对焦和笑脸检测功能,让您拍出精彩照片
  • 检测年龄、种族和情绪状态进行标记(是的,我们已经生活在那个世界中)

从历史上看,这是一个很难解决的问题。大量的人工特征工程、新颖的算法和方法被开发出来,以提高艺术水*。

如今,几乎每个计算机视觉包/框架中都包含了人脸检测模型。一些表现最好的使用深度学习方法。例如,OpenCV 提供了多种工具,如级联分类器

[## 用 PyTorch 完成任务

“成功创造人工智能将是人类历史上最大的事件。不幸的是,这也可能是最后一次,除非…

leanpub.com](https://leanpub.com/getting-things-done-with-pytorch)

在本指南中,您将学习如何:

  • 使用 Detectron2 为人脸检测准备自定义数据集
  • 使用(接*)最先进的对象检测模型来查找图像中的人脸
  • 你可以把这项工作扩展到人脸识别。

以下是本指南结尾部分的一个示例:

检测器 2

Detectron2 是一个用于构建最先进的对象检测和图像分割模型的框架。它是由脸书研究小组开发的。Detectron2 是对第一版的完全重写。

在引擎盖下,Detectron2 使用 PyTorch(与最新版本兼容),并允许极快的训练。你可以在脸书研究公司的介绍性博客文章中了解更多信息。

《侦探 2》的真正威力在于模型动物园里有大量预先训练好的模型。但是如果你不能在你自己的数据集上进行微调,那又有什么好处呢?还好,那超级容易!我们将在本指南中了解如何做到这一点。

安装检测器 2

在撰写本文时,Detectron2 仍处于 alpha 阶段。虽然有正式版本,我们将从主分支克隆和编译。这应该等于版本 0.1。

让我们从安装一些需求开始:

!pip install -q cython pyyaml == 5.1 
!pip install -q -U 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI'

并下载、编译和安装 Detectron2 软件包:

!git clone [https://github.com/facebookresearch/detectron2](https://github.com/facebookresearch/detectron2) detectron2_repo 
!pip install -q -e detectron2_repo

此时,您需要重启笔记本运行时才能继续!

%reload_ext watermark %watermark -v -p numpy,pandas,pycocotools,torch,torchvision,detectron2CPython 3.6.9
IPython 5.5.0
numpy 1.17.5
pandas 0.25.3
pycocotools 2.0
torch 1.4.0
torchvision 0.5.0
detectron2 0.1

人脸检测数据

数据集在公共领域可免费获得。由 Dataturks 提供,托管在 Kaggle 上。以下是描述的摘录:

用边界框标记的图像中的人脸。大约有 500 张图片,大约有 1100 张脸通过边框手动标记。

我已经下载了包含注释的 JSON 文件,并上传到 Google Drive。让我们来看看:

!gdown --id 1K79wJgmPTWamqb04Op2GxW0SW9oxw8KS

让我们将文件加载到熊猫数据框中:

每行包含一个面注释。注意,多条线可能指向单个图像(例如,每个图像有多个面)。

数据预处理

数据集只包含图像 URL 和注释。我们得下载图像。我们还将规范化注释,以便稍后在 Detectron2 中更容易使用它们:

让我们将数据放入数据框中,以便更好地查看:

409 1132

我们总共有 409 张图片(比承诺的 500 张少很多)和 1132 条注释。让我们将它们保存到磁盘中(以便您可以重复使用):

数据探索

让我们看看一些带注释的数据示例。我们将使用 OpenCV 加载图像,添加边界框,并调整其大小。我们将定义一个助手函数来完成这一切:

让我们先展示一些带注释的图片:

这些都是好的,注释清晰可见。我们可以用火炬视觉创建一个图像网格。请注意,这些图像有不同的大小,因此我们将调整它们的大小:

您可以清楚地看到一些注释丢失了(第 4 列)。这对你来说是真实的数据,有时你必须以某种方式处理它。

使用 Detectron 2 进行人脸检测

现在是时候使用定制数据集来完成微调模型的步骤了。但是首先,让我们保存 5%的数据用于测试:

传统的火车测试分割在这里不起作用,因为我们想要在文件名之间进行分割。

接下来的部分以一种更通用的方式编写。显然,我们只有一张阶级脸。但是添加更多内容应该与向数据框添加更多注记一样简单:

接下来,我们将编写一个函数,将数据集转换为 Detectron2 使用的格式:

我们将每个注释行转换成一个带有注释列表的记录。您可能还注意到,我们正在构建一个与边界框形状完全相同的多边形。这是 Detectron2 中的图像分割模型所必需的。

您必须将数据集注册到数据集和元数据目录中:

不幸的是,默认情况下,测试集的评估器并不包含在内。我们可以通过编写自己的训练器来轻松解决这个问题:

如果没有提供文件夹,评估结果将存储在coco_eval文件夹中。

微调 Detectron2 模型与编写 PyTorch 代码完全不同。我们将加载一个配置文件,更改一些值,然后开始训练过程。但是,嘿,如果你知道你在做什么,那真的很有帮助😂

在本教程中,我们将使用屏蔽 R-CNN X101-FPN 模型。它在 COCO 数据集上进行了预训练,取得了非常好的性能。缺点是训练慢。

让我们加载配置文件和预训练的模型权重:

指定我们将用于培训和评估的数据集(我们已注册这些数据集):

对于优化器,我们将施一点魔法来收敛一些好的东西:

除了标准的东西(批量大小、最大迭代次数和学习率),我们还有几个有趣的参数:

  • WARMUP_ITERS -学习率从 0 开始,到预设的迭代次数
  • STEPS -学习率将减少GAMMA的检查点(迭代次数)

最后,我们将指定在测试集上进行评估的类的数量和时间段:

使用我们的定制训练器进行训练:

评估对象检测模型

与评估标准分类或回归模型相比,评估对象检测模型稍有不同。

你需要知道的主要指标是 IoU(交集除以并集)。它测量两个边界之间的重叠——预测边界和实际边界。它可以得到 0 到 1 之间的值。

使用 IoU,可以定义阈值(例如> 0.5)来分类预测是真阳性(TP)还是假阳性(FP)。

现在,您可以通过计算精确度-召回曲线下的面积来计算*均精确度(AP)。

现在 AP@X(例如 AP50)只是某个 IoU 阈值的 AP。这将使您对如何评估对象检测模型有一个实用的理解。

如果你想了解更多有关该主题的信息,我建议你阅读 Jonathan Hui 的目标检测教程的图(*均精度)。

我已经为您准备了一个预培训模型,因此您不必等待培训完成。让我们下载它:

!gdown --id 18Ev2bpdKsBaDufhVKf0cT6RmM3FjW3nL 
!mv face_detector.pth output/model_final.pth

我们可以通过加载模型并设置 85%确定性的最小阈值来开始进行预测,在该阈值时,我们将认为预测是正确的:

让我们用训练好的模型运行评估器:

在图像中查找人脸

接下来,让我们创建一个文件夹,并将所有带有预测注释的图像保存在测试集中:

让我们来看看:

还不错。一点也不差。我建议你也自己探索更多的图像!

请注意,一些面有多个确定度不同的边界框(在第二个图像上)。也许训练模型更长时间会有帮助?增加或扩充现有数据怎么样?

结论

恭喜你!您现在已经了解了 Detectron2 用于物体检测的基础知识!鉴于我们的数据集很小,你可能会对结果感到惊讶。这就是大型预训练模型的力量😍

您学习了如何:

  • 使用 Detectron2 为人脸检测准备自定义数据集
  • 使用(接*)最先进的对象检测模型来查找图像中的人脸
  • 你可以把这项工作扩展到人脸识别。

参考

[## 用 PyTorch 完成任务

“成功创造人工智能将是人类历史上最大的事件。不幸的是,这也可能是最后一次,除非…

leanpub.com](https://leanpub.com/getting-things-done-with-pytorch)

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

使用 Tensorflow.js 优化浏览器上的人脸检测

原文:https://towardsdatascience.com/face-detection-on-the-browser-with-tensorflow-js-27846a5fe954?source=collection_archive---------19-----------------------

现实世界中的数据科学

基于浏览器的人脸检测器正是你所需要的

我的健壮的基于浏览器的人脸检测结果

让我们开始讨论最重要的问题。

为什么是这个探测器?

你可能遇到过很多人脸检测教程和项目。不过,这个不同。它部署在浏览器上,可以在任何地方使用,从监督在线考试到许多不同的街机游戏,再到使用它来实时检测人脸面具、模糊或提高人脸的分辨率(因为获得了感兴趣的区域),同时还可以以相当高的速度执行。网络上的机器学习是这个时代的要求,不应该局限于本地系统。另一种方法是 face-api.js,它使用多任务 CNN,但我们的检测器具有更高的准确性。许多其他项目将基于部署在 Flask 应用程序上的面部检测模型,相比之下,这些应用程序非常慢。

Tensorflow 服务使用 gRPC 和 Protobuf,而 Flask 应用使用 REST 和 JSON。JSON 依赖于 HTTP 1.1,而 gRPC 使用 HTTP/2。HTTP 1.1 存在延迟问题。每个单独的请求都需要 TCP 握手,大量的请求会大大增加加载页面所需的时间。HTTP 1.1 也受到行首阻塞的影响,它限制了同一个域的连接数。使用 HTTP 管道,您可以在等待前一个请求的响应时发送一个请求,从而有效地创建一个队列。但这也带来了其他问题。如果你的请求被一个缓慢的请求卡住了,那么你的响应时间将会受到影响。HTTP /2 保持了 HTTP 的基本前提和范例,但是去掉了 HTTP 1.1 的可选部分。REST 只支持 HTTP 1.x 中可用的请求-响应模型,但是 gRPC 充分利用了 HTTP/2 的功能,并允许您不断地传输信息。Protobuf 是一种用于序列化数据的二进制格式,比 JSON 更高效。Tensorflow 服务可以向同一模型批量发送请求,这更适合使用硬件(GPU)。Tensorflow 服务的性能相当于用 C/C++编写的代码。

此外,Flask 应用程序是用 Python 编写的,而 Tensorflow.js 将 Node.js 或 Chrome V8 引擎作为其服务器端节点。在这个项目中,我们使用 Chrome 的 V8 Javascript 引擎,这是一个开源的高性能 Javascript 引擎。

要获得更多关于 Chrome V8 引擎的直觉,请阅读这个令人敬畏的博客

[## 了解 Chrome V8 引擎如何将 JavaScript 翻译成机器码

通过 Mayank Tripathi 了解 Chrome V8 引擎如何在深入研究之前将 JavaScript 翻译成机器码…

www.freecodecamp.org](https://www.freecodecamp.org/news/understanding-the-core-of-nodejs-the-powerful-chrome-v8-engine-79e7eb8af964/)

Tensorflow.js 提供了使用 Web GL 层所需的正确类型的硬件加速,它可以被视为浏览器端 GPU。WebGL 是一个 JavaScript API,用于在任何兼容的 web 浏览器中渲染交互式 2D 和 3D 图形,而无需使用插件。WebGL 与其他 web 标准完全集成,允许 GPU 加速使用物理和图像处理以及作为网页画布一部分的效果。

因此,这个客户端服务人脸检测器被证明比以前的 flask 人脸检测应用程序更快。

Tensorflow.js

Tensorflow.js 是 Javascript 中的机器学习库。它是一个开源的硬件加速 JavaScript 库,用于训练和部署机器学习模型。

它可以用于在浏览器中开发 ML,通过使用灵活直观的 API,使用低级 JavaScript 线性代数库或高级 layers API 从头构建模型。也可以通过在 Node.js 运行时下用相同的 TensorFlow.js API 运行 native TensorFlow 在 Node.js 中开发 ML。TensorFlow.js 模型转换器可以在浏览器中使用预训练的 Tensorflow 或 Keras 模型。Tensorflow.js 还可以使用传感器数据重新训练预先存在的模型-连接到浏览器。

想了解更多关于 Tensorflow.js 的内容,可以查看官方文档。

[## 面向 Javascript 开发人员的机器学习

在浏览器、Node.js 或 Google 云*台中训练和部署模型。TensorFlow.js 是开源的 ML *台…

www.tensorflow.org](https://www.tensorflow.org/js)

要获得预训练的模型,您可以克隆以下官方 tfjs GitHub 库

[## 张量流/tfjs-模型

该存储库托管一组已移植到 TensorFlow.js 的预训练模型。这些模型托管在 NPM 上…

github.com](https://github.com/tensorflow/tfjs-models)

先决条件

  • 一个文本编辑器(可选)(Sublime,括号,Visual Studio 代码等)。)

您可以从下载括号编辑器

[## 一个现代的、理解网页设计的开源代码编辑器

括号是一个轻量级的,但功能强大的,现代的文本编辑器。我们将可视化工具融入到编辑器中,因此您可以获得正确的…

括号. io](http://brackets.io/)

  • 谷歌浏览器

[## 谷歌浏览器-从谷歌下载快速、安全的浏览器

现在比以往任何时候都更简单、更安全、更快速——内置了 Google 的智能。

www.google.com](https://www.google.com/chrome/)

履行

要使用基于浏览器的人脸检测器,请查看我的 GitHub 库

[## sid0312/tfjs-face_detection

使用 tensor flow . js-sid 0312/tfjs-face _ detection 在浏览器上使用网络摄像头进行人脸检测

github.co](https://github.com/sid0312/tfjs-face_detection)

复制步骤

如果你想亲自动手做一些事情,这里有一个指南

  • 创建一个起始 HTML 文件

  • 将以下几行添加到 html 文件 tensorflow.js 头中,以在 head 标签中导入 tfjs 模型

<script src=”https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script><script src=”https://cdn.jsdelivr.net/npm/@tensorflow-models/blazeface">
</script>
  • 样式(可选):创建用于格式化的 div 并添加样式表链接。添加视频元素和画布
  • 添加加载模型的 JavaScript 文件链接
  • 将你的文件重命名为 index.html

您的 index.html 文件应该如下所示

  • 为一些可选的样式创建一个 main.css 文件。向其中添加以下代码。方便时更换

您可以从以下网址获得一些可爱的 CSS

[## 密码笔

一个在线代码编辑器、学习环境和社区,用于使用 HTML、CSS 和 JavaScript 的前端 web 开发…

codepen.io](https://codepen.io/)

注意:main.css 加载一个 GIF,这是用于初始加载的,包含在存储库中。请随意使用自己的 gif。

  • 创建一个 blaze_pred.js 文件。向其中添加以下代码。

  • 解释

我们创建了一个自我调用函数,在这个函数中,我们通过它们的 id 来获取画布和视频元素。为了获得画布的上下文,我们使用 getContext()方法。

使用 navigator.getUserMedia 方法接收视频源,并将流添加到视频源对象。

video.play()用于播放视频,但是由于我们已经在 index.html 文件的 video 元素中将 visibility 设置为 false,因此无法实际查看视频提要。显示的提要是画布。使用画布上下文来绘制面部预测。

为了同步视频提要和 canvas 元素,我们添加了一个事件侦听器,并调用一个函数 draw 来绘制预测。

  • 创建一个异步绘制函数,参数为视频馈送、上下文、画布的宽度和高度。

在上面绘制视频馈送的当前帧。使用 await blazeface.load()加载模型。将 returnTensors 参数设置为 false 时,获取模型 await model.estimateFaces()上的预测。使用预测张量在画布上下文上绘制边界框。使用预测张量获得置信度得分,并将文本添加到相对于边界框的画布上下文中。要重复调用 draw 函数,请将超时设置为 250 ms。

  • 将工作文件(index.html,main.css,blaze_pred.js)添加到文件夹中。将文件夹命名为 tfjs-face_detection。你也可以给任何其他的名字。

克隆存储库

如果您还没有完成复制步骤,请在您的 shell/终端/命令提示符下键入以下内容

git clone https://github.com/sid0312/tfjs-face_detection

使用检测器

对于 Linux 和 Mac 用户,

user@username:~$ cd tfjs-face_detection
user@username:~/tfjs-face_detection$ google-chrome index.html

对于 Windows 用户,

C:\Users\username> cd tfjs-face_detection
C:\Users\username\tfjs-face_detection> index.html

允许访问网络摄像头

等待几秒钟,一切都准备好了!

结论

我们已经使用 Tensorflow.js 在浏览器上成功检测到我们的人脸,您可以创建自己的深度学习人脸模型,并使用 tfjs 模型转换器将其转换为 tfjs 模型,以增加其鲁棒性。

伊恩·斯托弗在 Unsplash 上拍摄的照片

作者

悉达多·巴尔多塔

耶!视频里的那个是我!查看我的其他文章:

[## 基于 U-网的 OCT 图像分割

使用 OCT 报告诊断糖尿病性黄斑水肿的深度学习方法。使用 Apache Mxnet 和…

towardsdatascience.com](/segmentation-of-optical-coherence-tomography-images-with-diabetic-macular-edema-the-gluon-82093cfd8e24) [## 使用 GluonCV 和 MxNet 计算网络摄像头上的人数

介绍

towardsdatascience.com](/counting-people-on-your-webcam-using-gluoncv-and-mxnet-d1a9f05c427d)

快乐的计算机视觉,快乐的深度学习,快乐的部署。下次见!

使用 Face-Api.js 和 Flask 进行人脸检测

原文:https://towardsdatascience.com/face-detection-using-face-api-js-and-flask-b641f19228cc?source=collection_archive---------21-----------------------

在 Flask Python 服务器中使用 Face-Api.js,通过使用 SocketIO 将 TF.js 资源与 Flask 集成,减少计算资源并提高 FPS

https://github.com/justadudewhohacks/face-recognition.js

T 网上有很多面向 Python 的人脸检测系统,像 Dlib、OpenCV,还有其他深度学习的物体检测系统。我们可能已经使用 OpenCV 使用帧从网络摄像头捕捉视频,并使用 Dlib,MTCNN 等进行面部标志检测。但是我总是受够了在一个项目中,我不能把它添加到 UI 中,或者由于 CPU 的负载有太多的帧跳跃。

谷歌搜索

大多数人使用 Flask 作为部署他们的 ML/DL 模型的 goto 框架,从 HTML 创建 UI 和从 python 服务器管理后端的美妙之处非常迷人。但是,每当你试图在你的网络应用程序中加入摄像头人脸检测时,你就会被 Opencv imshow()的一个对话框卡住,并破坏 UX。TF.js 的开发使我们能够在浏览器本身上开发复杂的模型。但是像我们这样对 Node.js 和其他 web 开发术语知之甚少的 python 爱好者必须知道如何在我们的 Flask playground 中使用这些工具

在本文中,我们将创建一个 Flask web 应用程序,将人脸识别集成到浏览器中

优势

  • 将数据和推理的视频流嵌入到浏览器内容中
  • 更少的资源利用和改进的 FPS
  • 不需要将项目从 Python 转移到 Node.js

了解 Face-Api.js

当我在寻找 Flask 的人脸检测解决方案时,我在浏览器中遇到了一个用于人脸检测和人脸识别的 JavaScript API,它是由 Vincent Mühler 开发的,他在为人脸检测和识别的 TF.js 实现创建 API 方面做了大量工作。这些 API 可用于从网络摄像头视频中提取数据,也可用于在视频帧上绘制地标。

[## justadudehohacks/face-API . js

在 tensorflow.js 核心之上实现的浏览器和 nodejs 的 JavaScript 人脸识别 API

github.com](https://github.com/justadudewhohacks/face-api.js)

创建面部标志检测烧瓶应用程序

我们的项目需要安装以下依赖项

pip install Flask
conda install -c anaconda flask
  • 烧瓶浸泡
pip install Flask-SocketIO
conda install -c conda-forge flask-socketio

我们的 Flask 应用程序创建包括 3 个部分

  • 步骤 1:使用 Face-Api.js 创建用于地标检测的静态网页
  • 步骤 2:将网页添加到 flask 服务器中,并将来自网页的推断异步传递到 Flask 后端进行处理

使用 Face-Api.js 创建用于地标检测的静态网页

在这一步中,我们将使用 Face-Api.js 来创建静态网页以进行人脸检测,并在控制台上记录推理。

我使用的文件结构如下

|--static
|     |--js
|     |     |--face-api.min.js
|     |     |--index.js
|     |--styles
|     |     |--style.js
|     |--models
|     |     |-- // All the models from Face-Api.js
|--template
|     |--index.html
|-app.py

最新的 face-api.min.js 可以在这里下载,要包含在模型文件夹中的权重可以在这里下载

我们将创建一个带有视频标签的基本 HTML 文件来显示输出,并将所有脚本和 CSS 文件添加到 template/index.html 中的文档中

为了改进基本 UI,在中添加了 CSS static/styles/style . CSS

魔术来了…使用 Face-Api.js 进行人脸地标检测。所有代码都添加在 static/js/index.js

上面的代码用于加载模型和初始化 Face-api.js

然后,我们将访问网络摄像头,并开始传输视频数据

加载 face API 后,调用 startVideo() 函数

加载视频数据后,我们将向视频流添加监听器,并添加 face-api.js 推断

就是这样…现在,您可以使用 VS Code Live 服务器Chrome Web 服务器查看网页……选择文件夹并启动服务器,在 Chrome 选项卡中输入 URL

Face-Api.js 推理演示

耶!!我们已经完成了使用 face-api.js 进行人脸地标检测的第一步

来自 Giphy.com

但是,我们仍然无法用 python 获得这些数据。所以让我们开始第 2 步…

设置 Flask 服务器

让我们创建一个基本的 flask 应用程序来查看网页。创建一个基本的 Flask 应用程序来渲染我们在 app.py 创建的网页

这可能会查看网页,但仍然没有办法在网页和 flask 应用程序之间发送和接收推断数据。所以我们将使用套接字进行连续的数据传输

输入插座

Socket IO 对于在网页和服务器之间创建客户端-服务器套接字非常有用。连接以及发送和接收数据的复杂性由 SocketIO 函数承担,这样我们就可以专注于数据的主要处理

[## 插座。超正析象管(Image Orthicon)

插座。IO 2.0 在这里以最快和最可靠的实时引擎为特色~/Projects/tweets/index . js var IO =…

socket.io](https://socket.io/)

在 Flask 应用程序中创建 web 套接字

安装完 Flask-SocketIO 依赖项后,我们可以按如下方式更新 app.py

上面的代码为我们的应用程序创建了一个服务器端套接字。所以我们需要为我们的 web 应用程序创建一个客户端套接字

您可能知道,在 Flask 中连接静态文件使用 url_for() 。给 index.html添加 SocketIO 依赖项,并链接文件夹中的其他静态文件,相应地更新代码

要在 Javascript 端创建套接字,首先要初始化套接字并测试连接

由于 flask 服务器的创建,face-api.js 不能像我们之前初始化的那样直接定位模型权重,因此需要更新 index.jsmodels ' 文件夹的位置

要使用 socket 发送数据,请在 setInterval() 中添加以下代码,这将不断地向 Flask 发送数据流。

就这些…你从浏览器得到的数据会被发送到 flask 后端,并在终端上打印出来。您可以相应地进行后期处理

总结一下代码实现

完成 App.py

完整的 Index.html

完整的 Index.js

使用烧瓶进行人脸检测的演示

自制人脸检测演示视频

我希望这是一个有趣的阅读给你们。感谢 thirumalainambi Yadav 对项目 JS 部分的支持。

参考

Face-API . js byVincent mühlerfromhttps://justadudewhohacks . github . io/Face-API . js/docs/globals . html

SocketIO 示例程序从此处

完整的项目代码可以在下面的 Github 库中找到

[## naidukarthi 2193/face _ API _ python

使用 Face-Api.js 和 Flask 进行人脸检测。为 naidukarthi 2193/face _ API _ python 开发做出贡献,创建一个…

github.com](https://github.com/naidukarthi2193/face_api_python)

感谢阅读

来自 Giphy.com

用于联系

给我发邮件到 karthikraj . v 17 @ sieg ST . AC . in

或者通过以下链接联系我

[## karthikraj Naidu——Android 开发者——MeitY | LinkedIn 国家信息中心

查看 Karthikraj Naidu 在世界上最大的职业社区 LinkedIn 上的个人资料。Karthikraj 列出了 3 项工作…

www.linkedin.com](https://www.linkedin.com/in/naidukarthi2193/) [## naidukarthi2193 —概述

解散在 GitHub 上注册您的个人资料,这是托管代码、管理项目和构建软件的最佳场所…

github.com](https://github.com/naidukarthi2193)

使用 MTCNN 的人脸检测——注重速度的人脸提取指南

原文:https://towardsdatascience.com/face-detection-using-mtcnn-a-guide-for-face-extraction-with-a-focus-on-speed-c6d59f82d49?source=collection_archive---------4-----------------------

在这篇文章中,我将展示如何使用 MTCNN 从图片或视频中提取人脸和特征,以及如何提高速度 x100

MTCNN 边界框示例

什么是 MTCNN

MTCNN 是由 Github 用户 ipacz 编写的 python (pip)库,实现了[张、等人的论文“多任务级联卷积网络的联合人脸检测与对齐”IEEE 信号处理快报 23.10(2016):1499–1503。交叉引用。Web](https://arxiv.org/abs/1604.02878](https://arxiv.org/abs/1604.02878 "https://arxiv.org/abs/1604.02878) 。

在这篇论文中,他们提出了一个深度级联多任务框架,使用“子模型”的不同功能来增强它们的关联强度。

MTCNN 在 CPU 上执行得相当快,尽管 S3FD 在 GPU 上运行更快——但这是另一篇文章的主题。

这篇文章使用了以下两个来源的代码,看看它们,它们也很有趣:

MTCNN 的基本用法

请通过以下方式随意访问整个笔记本:

https://github . com/JustinGuese/mt CNN-人脸提取-眼睛-嘴巴-鼻子-加速

git clone [https://github.com/JustinGuese/mtcnn-face-extraction-eyes-mouth-nose-and-speeding-it-up](https://github.com/JustinGuese/mtcnn-face-extraction-eyes-mouth-nose-and-speeding-it-up)

幸运的是,MTCNN 是一个 pip 包,这意味着我们可以使用

pip install mtcnn

现在切换到 Python/Jupyter Notebook,我们可以通过导入和快速验证来检查安装:

import mtcnn
# print version
print(mtcnn.__version__)

之后,我们准备使用 matplotlib imread 函数加载测试图像。

import matplotlib.pyplot as plt
# load image from file
filename = "glediston-bastos-ZtmmR9D_2tA-unsplash.jpg"
pixels = plt.imread(filename)
print("Shape of image/array:",pixels.shape)
imgplot = plt.imshow(pixels)
plt.show()

现在,您的输出看起来很像这样:

{'box': [1942, 716, 334, 415], 'confidence': 0.9999997615814209, 'keypoints': {'left_eye': (2053, 901), 'right_eye': (2205, 897), 'nose': (2139, 976), 'mouth_left': (2058, 1029), 'mouth_right': (2206, 1023)}}
{'box': [2084, 396, 37, 46], 'confidence': 0.9999206066131592, 'keypoints': {'left_eye': (2094, 414), 'right_eye': (2112, 414), 'nose': (2102, 426), 'mouth_left': (2095, 432), 'mouth_right': (2112, 431)}}
{'box': [1980, 381, 44, 59], 'confidence': 0.9998701810836792, 'keypoints': {'left_eye': (1997, 404), 'right_eye': (2019, 407), 'nose': (2010, 417), 'mouth_left': (1995, 425), 'mouth_right': (2015, 427)}}
{'box': [2039, 395, 39, 46], 'confidence': 0.9993435740470886, 'keypoints': {'left_eye': (2054, 409), 'right_eye': (2071, 415), 'nose': (2058, 422), 'mouth_left': (2048, 425), 'mouth_right': (2065, 431)}}

这告诉我们什么?其中大部分是不言自明的,但它基本上返回坐标,或者 MTCNN 算法检测到人脸的矩形的像素值。上面的“框”值返回整张脸的位置,后面跟着一个“置信度”级别。

如果你想做更高级的提取或算法,你将可以访问其他面部标志,也称为“关键点”。也就是说,MTCNN 模型还定位了眼睛、嘴巴和鼻子!

在面周围画一个方框

为了更好地演示这一点,让我们使用 matplotlib 在面部周围画一个方框:

# draw an image with detected objects
def draw_facebox(filename, result_list):
# load the image
data = plt.imread(filename)
# plot the image
plt.imshow(data)
# get the context for drawing boxes
ax = plt.gca()
# plot each box
for result in result_list:
# get coordinates
x, y, width, height = result['box']
# create the shape
rect = plt.Rectangle((x, y), width, height, fill=False, color='green')
# draw the box
ax.add_patch(rect)
# show the plot
plt.show()# filename = 'test1.jpg' # filename is defined above, otherwise uncomment
# load image from file
# pixels = plt.imread(filename) # defined above, otherwise uncomment
# detector is defined above, otherwise uncomment
#detector = mtcnn.MTCNN()
# detect faces in the image
faces = detector.detect_faces(pixels)
# display faces on the original image
draw_facebox(filename, faces)

在脸部周围展示眼睛、嘴巴和鼻子

现在让我们来看看前面提到的 MTCNN 模型返回的“关键点”。

我们现在将使用这些来绘制鼻子,嘴和眼睛。
我们将在上面的代码中添加以下代码片段:

# draw the dots
for key, value in result['keypoints'].items():
# create and draw dot
dot = plt.Circle(value, radius=20, color='orange')
ax.add_patch(dot)

上面的完整代码如下所示:

# draw an image with detected objects
def draw_facebox(filename, result_list):
# load the image
data = plt.imread(filename)
# plot the image
plt.imshow(data)
# get the context for drawing boxes
ax = plt.gca()
# plot each box
for result in result_list:
# get coordinates
x, y, width, height = result['box']
# create the shape
rect = plt.Rectangle((x, y), width, height,fill=False, color='orange')
# draw the box
ax.add_patch(rect)
# draw the dots
for key, value in result['keypoints'].items():
# create and draw dot
dot = plt.Circle(value, radius=20, color='red')
ax.add_patch(dot)
# show the plot
plt.show()# filename = 'test1.jpg' # filename is defined above, otherwise uncomment
# load image from file
# pixels = plt.imread(filename) # defined above, otherwise uncomment
# detector is defined above, otherwise uncomment
#detector = mtcnn.MTCNN()
# detect faces in the image
faces = detector.detect_faces(pixels)
# display faces on the original image
draw_facebox(filename, faces)

高级 MTCNN:加速(~x100)!

现在让我们进入有趣的部分。如果你要处理数百万张图片,你需要加快 MTCNN 的速度,否则,你要么会睡着,要么你的 CPU 会在它完成之前就烧了。

但是我们到底在说什么呢?如果你运行上面的代码,大约需要一秒钟,这意味着我们每秒钟处理一张图片。如果你在 GPU 上运行 MTCNN 并使用加速版本,它将达到每秒 60-100 张图片/帧。这是 T2 的 100 倍!

例如,如果您要提取一部电影的所有人脸,每秒钟将提取 10 张人脸(电影的一秒钟*均有大约 24 帧,因此每秒钟一帧),那么它将是 10 * 60(秒)* 120(分钟)= 72,000 帧。

也就是说,如果处理一帧图像需要一秒钟,则需要 72,000 * 1(秒)= 72,000 秒/60 秒= 1,200 米= 20 小时

对于加速版的 MTCNN,这项任务将需要 72,000(帧)/ 100(帧/秒)= 720 秒= 12 分钟

要在 GPU 上使用 MTCNN,您需要设置 CUDA、cudnn、pytorch 等等。关于那部分,Pytorch 写了一个很好的教程。

安装完成后,我们将进行必要的导入,如下所示:

from facenet_pytorch import MTCNN
from PIL import Image
import torch
from imutils.video import FileVideoStream
import cv2
import time
import glob
from tqdm.notebook import tqdmdevice = 'cuda' if torch.cuda.is_available() else 'cpu'filenames = ["glediston-bastos-ZtmmR9D_2tA-unsplash.jpg","glediston-bastos-ZtmmR9D_2tA-unsplash.jpg"]

看到我们如何在上面的代码中定义设备了吗?如果你不想或者不能设置 CUDA,你也可以在 CPU 上运行任何东西。

接下来,我们将定义提取器:

# define our extractor
fast_mtcnn = FastMTCNN(
stride=4,
resize=0.5,
margin=14,
factor=0.6,
keep_all=True,
device=device
)

在这个片段中,我们传递了一些参数,例如,我们只使用了图像大小的一半,这是加速的主要影响因素之一。

最后,让我们运行人脸提取脚本:

def run_detection(fast_mtcnn, filenames):
frames = []
frames_processed = 0
faces_detected = 0
batch_size = 60
start = time.time()for filename in tqdm(filenames):v_cap = FileVideoStream(filename).start()
v_len = int(v_cap.stream.get(cv2.CAP_PROP_FRAME_COUNT))for j in range(v_len):frame = v_cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frames.append(frame)if len(frames) >= batch_size or j == v_len - 1:faces = fast_mtcnn(frames)frames_processed += len(frames)
faces_detected += len(faces)
frames = []print(
f'Frames per second: {frames_processed / (time.time() - start):.3f},',
f'faces detected: {faces_detected}\r',
end=''
)v_cap.stop()run_detection(fast_mtcnn, filenames)

上图显示了在 NVIDIA Tesla P100 上运行的代码输出,因此根据源材料、GPU 和处理器,您可能会体验到更好或更差的性能。

这个故事在我的博客https://www . data fortress . cloud/blog/face-detection-using-mt CNN/上也有。

TensorFlow 中端到端回归的人脸标志点检测

原文:https://towardsdatascience.com/face-landmark-detection-with-cnns-tensorflow-cf4d191d2f0?source=collection_archive---------13-----------------------

🤖深度学习

从零开始构建一个模型,不需要使用其他包!

照片由普里西拉·杜·普里兹Unsplash 拍摄

人脸检测系统在当今这个要求安全性、可访问性或快乐的世界里有很大的用途!今天,我们将建立一个可以在一张脸上画出 15 个关键点的模型。

面部标志检测模型形成了我们在社交媒体应用中看到的各种功能。你在 Instagram 上找到的人脸滤镜是一个常见的用例。该算法对准图像上的掩模,保持面部标志作为基点。

Instagram 的自拍滤镜需要知道你的眼睛、嘴唇和鼻子在图像上的确切位置。

我们用 Keras ( TF backend)开发一个模型吧!首先,我们需要一些数据来训练我们的模型。

请注意!本博客教你用 Keras 建立一个超级简单的人脸地标检测模型。对于实际的生产模型,这可能没有用。

您可以在另一个选项卡中运行交互式 Colab 笔记本,以跟踪和理解每个步骤。

[## 人脸 _ 地标 _ 检测

colab.research.google.com](https://colab.research.google.com/drive/11PoRdorcI5C8SFPEZbO2XNGPCTGIwDfP#scrollTo=IsWsGrm8BvgN&forceEdit=true&sandboxMode=true)

数据

我们使用的是由 Omri GoldsteinKaggle 上标注了标志点数据集的人脸图像。该数据集包含大约 7000 张图像(96 * 96 ),其面部标志可以在facial_keypoints.csv文件中找到。

但是这里我们有一个问题。大多数图像没有一套完整的 15 个点。所以我们只需要那些有 15 个面部关键点的图像。

使用这个脚本,我做了一些清理,并将修改后的数据保存在我的数据集档案 GitHub repo 中。Colab 笔记本使用wget命令下载 ZIP 存档文件。

!wget https://github.com/shubham0204/Dataset_Archives/blob/master/face_landmarks_cleaned.zip?raw=true -O data.zip!unzip data.zip

我们还标准化了图像和坐标(关键点)。我已经改变了输出y_trainy_test的形状,因为它们将成为Conv2D层而不是Dense层的预期输出。

预处理数据。

亲提示:我找到了另一个用于人脸地标检测的数据集,名为 UTKFace 。它包含 68 个面部关键点以及年龄和性别等其他特征。也试试吧!

讨论模型

让我们讨论一下我们模型的结构。实际上,我用这个模型做了一些实验。我们需要一个模型,它拍摄一张尺寸为( 96 , 96 ) 的图像,并输出一个形状数组( 30, ) ( 15 个关键点* 2 个坐标)

  1. 第一个模型拍摄了一幅图像,并将其通过预先训练好的 VGG 模型。接下来,VGG 的输出被展*并通过多个Dense层。问题在于,即使在损失最小的情况下,该模型也能为每张图像预测出相同的关键点
  2. 第二种型号是您可以在 Colab 笔记本中找到的型号。我们不使用Dense层。相反,我们通过Conv2D层传递图像,并给出形状( 1 , 1 , 30 )的输出。因此,Conv2D层给了我们输出。使用这种模型,对于每幅图像以及甚至不存在于数据集中的图像,预测都是不同的!

我们的模型看起来像,

模型。

在执行回归任务时,我们使用的是均方误差。如果你有大量的数据,小的学习率总是好的。

为什么我们要使用批量标准化图层?

阅读这篇博客了解更多。

训练和推理

我们以 50 个为一批,对模型进行大约 250 个时期的训练。训练之后,我们将在测试数据集上生成一些预测。

生成预测。

注意:记住输入图像的方向。在旋转 90 度的图像上训练的模型不能对直立图像产生正确的预测。

如果没有对模型或训练参数做任何修改,250 个历元后的模型应该是这样的,

结果。

印象深刻吧。仅此而已!您刚刚从头开始构建了一个面部标志检测模型。在笔记本中,我添加了一个代码单元,你可以用网络摄像头拍摄图像,并在上面运行模型。

想要更多吗?

结束了

我看完结果后的第一反应!

很久以后我发表了作品(同时我正忙于写数学……)。感谢阅读!

基于 MediaPipe 人脸网格的人脸标志点检测

原文:https://towardsdatascience.com/face-landmarks-detection-with-mediapipe-facemesh-555fa2e10b06?source=collection_archive---------11-----------------------

用 tfjs facemesh 模型,我做了一个面具网络应用,你可以在上面试你最喜欢的面具

来源:pixabay.com

Tensorflow.js 在 3 月份发布了 MediaPipe Facemesh 模型,这是一个轻量级的机器学习管道,可以预测 486 个 3D 面部标志来推断人脸的*似表面几何形状。

在疫情期间,我呆在家里玩这个 facemesh 模型。我想提醒人们戴口罩的重要性。于是我搭建了一个虚拟的口罩试衣间,它可以在一个图像或者网络摄像头流中检测到人脸地标,把选中的口罩戴在你的脸上。

点击下面的链接亲自尝试一下:

[## 特朗普的面具-带有面部标志检测-本森技术

疾病控制和预防中心(CDC)建议美国人在公共场合戴口罩,以防止…

bensonruan.com](https://bensonruan.com/face-mask-for-trump-with-face-landmark-detection/)

履行

戴口罩是关心社区的一种表现。它可以防止佩戴者无意中将疾病传染给他人。虚拟面具试衣间利用了一种称为面部标志检测的先进技术,可以在图像或视频流中识别人脸。

如果你有兴趣建立一个面部标志检测应用程序,请在下面跟随我,了解我是如何实现它的。

#步骤 1:包括 tfjs 和 facemesh 模型

首先,简单的在 html 文件的< head >部分包含脚本Tensorflow.js及其facemesh模型。

<script src="[https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core](https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core)"></script><script src="[https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter](https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter)"></script><script src="[https://cdn.jsdelivr.net/npm/@tensorflow-models/facemesh](https://cdn.jsdelivr.net/npm/@tensorflow-models/facemesh)"></script>

或者您可以通过 npm 安装它,以便在 TypeScript / ES6 项目中使用

npm install @tensorflow-models/facemesh//import in js
const facemesh = require('@tensorflow-models/facemesh');

#步骤 2: HTML 图像和视频元素

接下来我们需要做的是添加 html <img><video>元素作为源,这样我们就可以在图像或网络摄像头视频流上执行面部标志检测。

<img id="faces" src="images/Donal_Thrump_White_House.jpg"><video id="webcam" autoplay playsinline width="640" height="480"></video>

为了让你的网络摄像头进入浏览器,我使用了 npm JavaScript 模块webcam-easy.js,它提供了一个易于使用的模块,可以访问网络摄像头并拍照。要了解更多细节,请参考我之前的博客:

[## 如何使用 JavaScript 访问网络摄像头并拍照

介绍网络摄像头-简易 npm 模块

medium.com](https://medium.com/swlh/how-to-access-webcam-and-take-picture-with-javascript-b9116a983d78)

#步骤 3:加载面网格模型

为了执行人脸地标检测,我们首先需要通过调用facemesh.load(modelParams)的 API 来加载预先训练好的 Facemesh 模型。FaceMesh 附带了一些可选的模型参数:

  • maxContinuousChecks (默认值:5)

—在不运行边界框检测器的情况下要运行多少帧。仅当 maxFaces > 1 时相关

  • 检测置信度(默认值:0.9)

—丢弃预测的阈值

  • maxFaces (默认值:10)

—输入中检测到的最大面数。应设置为性能的最小数字

  • iouThreshold (默认值:0.3)

—一个浮点值,表示在非最大值抑制中决定框是否重叠过多的阈值。必须在[0,1]之间

  • 得分阈值(默认值:0.75)

—根据非最大抑制中的分数决定何时移除框的阈值

facemesh.load().then(mdl => { 
    model = mdl;
    console.log("model loaded");
    cameraFrame =  detectFaces();
});

#步骤 4:面部标志检测

接下来,我们通过调用model.estimateFaces(inputElement)的 API,开始通过 Facemesh 模型馈送图像或网络摄像头流来执行面部标志检测。它接受一个输入图像元素(可以是张量、DOM 元素图像、视频或画布),并返回面部标志关键点、边界框和置信度的数组。

estimateFaces API 附带了模型的几个参数:

  • 输入

要分类的图像。可以是张量、DOM 元素图像、视频或画布。

  • 返回张量(默认值:假)

—是否返回张量而不是值

  • flipHorizontal (默认值:假)

—是否水*翻转/镜像面部关键点。对于面向网络摄像机流的用户来说应该是真的

let inputElement = isVideo? webcamElement : imageElement;
let flipHorizontal = isVideo;
model.estimateFaces(inputElement, false, flipHorizontal).then(predictions => {
    console.log(predictions);
    drawMask(predictions);
});

预测的返回看起来像:

对于每一个面部标志关键点,它包含 x,y 轴的位置和深度。

0: Array(3)
    0: 202.05661010742188
    1: 207.98629760742188
    2: -5.985757827758789
    length: 3

#第五步:戴上面具

在上面的函数中,我们得到了 468 个人脸地标关键点。对于我们的面罩应用,我使用了其中的 4 个标志:

  • 额头:10
  • 左脸颊:234
  • 下巴:152
  • 右脸颊:454

然后,我们可以使用这些关键点来计算我们应该在哪里覆盖人脸面具 PNG 图像。我们需要计算以下 3 个数字:

  • 遮罩图像左上角的(x,y)位置
  • 遮罩图像的宽度
  • 遮罩图像的高度

下面是我如何得到蒙版图像:使用右脸颊标志的 x 轴值-左脸颊标志的 x 轴值

maskWidth =(dots[rightCheekIndex].left - dots[leftCheekIndex].left);

对于高度和左上角位置,半遮罩和全遮罩之间存在差异。

  • 全面罩

—左上角:{x:额头 x 轴值;y:左脸颊 y 轴值}

—身高:[下巴 y 轴值]—[额头 y 轴值]

  • 半截面罩

—左上角:{x,y:左界标的 x,y 轴值}

—身高:[下巴 y 轴值]—[左脸颊 y 轴值]

switch(maskType) {
  case 'full':
    maskCoordinate= { top: dots[foreheadIndex].top, left: dots[leftCheekIndex].left};
    maskHeight = (dots[chinIndex].top - dots[foreheadIndex].top) ;
    break;
  case 'half':
    maskCoordinate = dots[leftCheekIndex];
    maskHeight = (dots[chinIndex].top - dots[leftCheekIndex].top) ;
    break;
}

最后一步是将人脸蒙版 PNG 图像叠加到人脸上。

maskElement = $("<img src='"+selectedMask.attr('src')+"' class='mask' />");
maskElement.appendTo($("#canvas"));
maskElement.css({
    top: maskCoordinate.top, 
    left: maskCoordinate.left, 
    width: maskWidth ,
    height: maskHeight,
    position:'absolute'
});

代码就这么多了!现在选择你最喜欢的面膜,自己试一试吧!

GitHub 知识库

您可以通过下面的链接下载上述演示的完整代码:

[## 面罩

图像和实时网络摄像头人脸检测,使用虚拟面罩保护自己免受 COVID19 攻击。利用张量流…

github.c](https://github.com/bensonruan/Face-Mask)

结论

Facemesh 模型是为移动设备上的前置摄像头设计的,在这种情况下,视图中的人脸往往会占据画布的相对较大部分。MediaPipe Facemesh 可能很难识别远处的人脸。

由于每个人都担心冠状病毒的传播,面部检测和识别系统可能是比传统的生物识别门禁系统更安全、更清洁的选择。这项技术不仅可以降低交叉感染的风险,还可以提高交通效率 10 倍以上,从而节省时间,减少拥堵。

最后,我希望每个人在疫情期间保持健康,呆在家里,让我们利用最新的机器学习技术来帮助我们对抗病毒。

感谢您的阅读。如果你喜欢这篇文章,请在脸书或推特上分享。如果你有任何问题,请在评论中告诉我。在 GitHubLinkedin 关注我。

用 PyTorch 检测人脸标志点

原文:https://towardsdatascience.com/face-landmarks-detection-with-pytorch-4b4852f5e9c4?source=collection_archive---------9-----------------------

计算机真的能看懂人脸吗?

Ayo OgunseindeUnsplash 拍摄的照片上的地标检测样本

想知道 Instagram 如何将令人惊叹的滤镜应用到你的脸上吗?该软件检测你脸上的关键点,并在上面投射一个面具。本教程将指导您如何使用 Pytorch 构建这样一个软件。

Colab 笔记本

完整的代码可以在下面的交互式 Colab 笔记本中找到。

[## 人脸标志检测

colab.research.google.com](https://colab.research.google.com/drive/1TOw7W_WU4oltoGZfZ_0krpxmhdFR2gmb)

资料组

在本教程中,我们将使用官方的 DLib 数据集,其中包含了 6666 张不同尺寸的图像。此外,labels _ ibug _ 300 w _ train . XML(随数据集提供)包含每张脸的 68 个地标的坐标。下面的脚本将下载数据集并将其解压缩到 Colab Notebook 中。

这是数据集中的一个示例图像。我们可以看到,面部占据了整个图像的很小一部分。如果我们将完整的图像输入神经网络,它也会处理背景(无关信息),使模型难以学习。因此,我们需要裁剪图像,只填充人脸部分。

数据集的样本图像和地标

数据预处理

为了防止神经网络过度拟合训练数据集,我们需要随机转换数据集。我们将对训练和验证数据集应用以下操作:

  • 由于人脸在整个图像中只占很小的一部分,所以请裁剪图像并仅使用人脸进行训练。
  • 将裁剪后的面调整为(224x224)图像。
  • 随机更改调整后的面部的亮度和饱和度。
  • 以上三种变换后随机旋转人脸。
  • 将图像和地标转换为火炬张量,并在[-1,1]之间归一化。

数据集类

现在我们已经准备好了转换,让我们编写数据集类。labels _ ibug _ 300 w _ train . XML包含图像路径、界标和边界框的坐标(用于裁剪面部)。我们将这些值存储在列表中,以便在培训期间轻松访问。在本教程中,将对灰度图像训练神经网络。

注意: landmarks = landmarks - 0.5是为了使地标以零为中心,因为以零为中心的输出更易于神经网络学习。

预处理后数据集的输出将类似于这样(图像上标出了地标)。

预处理数据样本

神经网络

我们将使用 ResNet18 作为基本框架。我们需要修改第一层和最后一层,以适应我们的目的。在第一层中,我们将使输入通道计数为 1,以便神经网络接受灰度图像。类似地,在最终层中,输出通道计数应该等于 68 * 2 = 136 ,以便模型预测每个面的 68 个标志的(x,y)坐标。

训练神经网络

我们将使用预测界标和真实界标之间的均方误差作为损失函数。请记住,学习率应该保持较低,以避免爆炸梯度。每当验证损失达到新的最小值时,将保存网络权重。训练至少 20 个纪元才能获得最佳表现。

根据看不见的数据预测

使用下面的代码片段来预测看不见的图像中的地标。

上面的代码片段在 Colab Notebook 中不起作用,因为 Colab 还不支持 OpenCV 的某些功能。要运行上述单元,请使用您的本地机器。

OpenCV Harr Cascade 分类器用于检测图像中的人脸。使用 Haar 级联的对象检测是一种基于机器学习的方法,其中用一组输入数据训练级联函数。OpenCV 已经包含了许多预先训练好的人脸、眼睛、行人等分类器。在我们的例子中,我们将使用人脸分类器,为此您需要下载预训练的分类器 XML 文件,并将其保存到您的工作目录中。

人脸检测

然后,输入图像中检测到的人脸被裁剪,调整大小到 (224,224) ,并被馈送到我们训练过的神经网络,以预测其中的地标。

裁剪人脸上的标志点检测

然后,裁剪后的面部中的预测界标被覆盖在原始图像的顶部。结果如下图所示。印象深刻,对吧!

决赛成绩

类似地,多个面部上的标志检测:

在这里,你可以看到 OpenCV Harr 级联分类器已经检测到多个人脸,包括一个误报(一个拳头被预测为一个人脸)。所以,网络已经在那上面画了一些地标。

那都是乡亲们!

如果你成功了,向你致敬!你刚刚训练了你自己的神经网络来检测任何图像中的面部标志。尝试在您的网络摄像头上预测面部标志!!

有什么建议请留言评论。我定期写文章,所以你应该考虑关注我,在你的订阅中获得更多这样的文章。

如果你喜欢这篇文章,你可能也会喜欢这些:

[## 机器学习-可视化

理解机器学习的视觉方法

towardsdatascience.com](/machine-learning-visualized-11965ecc645c) [## 主成分分析-可视化

使用主成分分析(PCA)的数据压缩

towardsdatascience.com](/principal-component-analysis-visualized-17701e18f2fa)

访问我的网站了解更多关于我和我的工作。

使用 YOLOv5 进行人脸面具检测

原文:https://towardsdatascience.com/face-mask-detection-using-yolov5-3734ca0d60d8?source=collection_archive---------4-----------------------

实践教程

新冠肺炎:指南建立一个面具检测器使用 YOLOv5 和运行推理视频流

YOLOv5 推论(视频由作者提供)

在本帖中,我们将逐步指导如何训练一个 约洛夫 5 模型来检测视频流中的人是否戴着面具。

我们将从物体检测模型背后的一些基本概念开始,并激励使用 YOLOv5 来解决这个问题。

从那里,我们将回顾我们将用于训练模型的数据集,并查看如何对其进行调整,使其符合 darknet 格式

然后,我将向您展示如何使用下载的数据集训练 YOLOv5 模型,并对图像或视频文件进行推理。

在这里 找到本节使用的代码 的笔记本。

这个项目是和弗兰·佩雷斯一起完成的,他也是这个社区的贡献者。我建议你读一些他的精彩文章!

背景

“YOLO”,指的是“你只看一次”,是 Joseph Redmon 用 2016 年的出版物“你只看一次:统一的、实时的物体检测”推出的一系列物体检测模型。

从那时起,几个更新的版本已经发布,其中,前三个是由约瑟夫·雷德蒙发布的。6 月 29 日,Glenn Jocher 发布了最新版本 YOLOv5声称相对于其前作有重大改进

最有趣的改进,是它的“惊人地快速推断”。正如 Roboflow 在特斯拉 P100 中运行的这篇文章中所发布的,YOLOv5 实现了每幅图像高达 0.007 秒的推理时间,意味着 140 FPS

YOLO 车型对比(图片来源)

为什么是 YOLO?

使用一个 对象检测 模型,比如 YOLOv5,很可能是解决这个问题的最简单和最合理的方法。这是因为我们将计算机视觉流水线限制为一个单一步骤,因为物体检测器被训练来检测:

  • 包围盒和一个
  • 对应标签

这正是我们试图解决这个问题的目的。在我们的例子中,边界框将是检测到的人脸,相应的标签将指示这个人是否戴着面具。

或者,如果我们想建立自己的深度学习模型,它会更复杂,因为它必须是 2 -fold :我们需要一个模型来检测图像中的人脸,另一个模型来检测找到的边界框中是否存在人脸面具。

除了复杂性之外,这样做的缺点是推断时间会慢得多,尤其是在有许多人脸的图像中。

数据呢?

我们现在知道可以用哪个模型来解决这个问题。下一个自然的,也可能是最重要的方面是… 数据呢??

幸运的是,在 Kaggle 中有一个公开可用的数据集,名为人脸面具检测,这将使我们的生活变得更加轻松。

数据集包含 853 幅图像及其对应的注释文件,指示一个人是正确佩戴错误佩戴还是没有佩戴

以下是数据集中的一个示例:

来自面罩数据集的样本图像(图片由作者提供)

在这种情况下,我们将简化上面的内容来检测一个人是否戴着面具(我们将在 Roboflow 部分看到如何戴面具)。

关于自定义数据的培训

我们现在知道了开始工作所需的一切,所以是时候动手了!

项目布局

我们需要做的第一件事是从 ultralytics/yolov5 中克隆存储库,并安装所有需要的依赖项:

!git clone [https://github.com/ultralytics/yolov5](https://github.com/ultralytics/yolov5) # clone repo
!pip install -U -r yolov5/requirements.txt # install dependencies

我们需要从存储库中获取的主要文件的结构如下:

yolov5           # project root
├── models       # yolov5 models
├── train.py     # training script
└── detect.py    # inference script

这📁 models 文件夹包含几个.yml文件,包含不同的建议型号。在其中我们可以找到 4 种不同的型号,按从小到大的顺序排列(根据参数的数量): yolov5-syolov5-myolov5-lyolov5-x、详细对比见此处

train.pydetect.py将是我们将分别调用来训练模型和预测新图像/视频的脚本。

Roboflow

为了训练模型,一个必要的步骤是改变.xml注释文件的格式,使其符合暗网格式。在链接的 github 线程中,我们会看到每个图像都必须有一个与之相关联的.txt文件,其行的格式为:

<object-class> <x> <y> <width> <height>

每行代表图像中每个对象的注释,其中<x> <y>是边界框中心的坐标,<width> <height>是各自的宽度和高度。

例如,一个img1.jpg必须有一个关联的img1.txt,包含:

1 0.427234 0.123172 0.191749 0.171239
0 0.183523 0.431238 0.241231 0.174121
1 0.542341 0.321253 0.191289 0.219217

好消息是,多亏了 Roboflow,这一步变得非常简单。 Roboflow 能够轻松在注释格式之间转换,以及扩充我们的图像数据和将其分成训练和验证集,这将非常方便!

这可以通过 5 个简单的步骤来完成:

  • 上传图像和注释

Roboflow,上传注释(图片由作者提供)

  • 选择您想要的训练、验证和测试比例(训练和验证就足够了)
  • 添加一个从现有滤镜中选择的增强步骤,例如模糊亮度旋转等。

增强(图片由作者提供)

  • 最后,生成新的图像并导出为 YOLO Darknet 格式

选择输出格式(按作者排列的图像)

我们现在应该为每个分割、训练验证(以及测试如果包括在内)都有一个单独的文件夹,其中每个文件夹都应该包含.jpg增强图像、相应的.txt注释文件和一个._darknet.labels文件,这些文件的标签按其相应的顺序排列:

mask_weared_incorrect # label 0
with_mask             # label 1
without_mask          # label 2

改变标签

这将取决于你希望你的模型如何表现,但是如上所述,我决定通过限制标签为遮罩无遮罩来简化问题。此外,标签mask_weared_incorrect在数据集中出现的次数很少,因此模型很可能在分类上表现不佳。

这个简单的脚本可以做到:

现在,注释文件中的数字标签将映射到:

without_mask          # label 0
with_mask             # label 1

数据*衡[可选]

数据集有点不*衡,有更多的with_mask标签,因此我们可以做的是增加没有戴面具的人的图像。这也将有助于显著提高模型的性能,因为我们将使用的数据集非常小。

在这里 找到本节使用的代码 的笔记本。

我们可以做到这一点的一个方法是从 COCO 数据集下载图像,然后我们自己注释它们。COCO 数据集有一个官方 API, pycocotools ,我们可以用它来下载带有person标签的图像:

以上内容将为我们提供一个字典列表,其中包含图片的详细信息和 url,我们可以使用以下内容下载到本地:

下一步将是获得这些图像的面部边界框。为此,一种简单的方法是使用预先训练的模型来检测人脸,并以适当的格式标记它们。

为此,您需要先安装pytorch,然后再安装facenet-pytorch:

conda install pytorch torchvision torchaudio cpuonly -c pytorch
pip install facenet-pytorch

我还使用cv2来检查注释是否正确。要获得暗网格式的注释,我们需要转换由facenet-pytorch进行的检测。我们可以通过下面的函数做到这一点:

然后,您可以使用以下脚本获取下载图像的注释:

其还打印检测到的注释,以验证它们是正确的。以下是一些例子:

最后一档

在训练模型之前,我们需要创建一个data.yml,指定训练和验证图像的位置和标签的数量以及训练数据的标签名称。该文件的结构应该是:

train: train/images
val: valid/imagesnc: 2
names: ['bad', 'good']

培养

为了训练模型,我们必须运行train.py,它采用以下参数:

  • img: 输入图像尺寸
  • 批量:批量大小
  • 时期:时期的数量
  • 数据:路径到data.yml文件
  • cfg: 模型在预先存在的中进行选择📁型号
  • 权重:初始权重路径,默认为yolov5s.pt
  • 名称:重命名输出文件夹
  • 设备:是否在 cpugpu 上训练。

在我的例子中,我用 GPU 训练了模型,但否则你必须添加参数--device cpu才能在 CPU 上本地运行。其余的,你只需要注意指定的路线:

python ~/github/yolov5/train.py --img 416 --batch 16 --epochs 150 --data data.yaml --cfg yolov5s.yaml --weights ‘’ --name robo4_epoch150_s --adam

一旦训练完成,您可以通过检查生成的日志以及保存为.png文件的损失图来了解您的模型的表现。

训练损失和性能指标被记录到 Tensorboard 和一个runs/exp0/results.txt日志文件中,在训练完成后被标为results.png

这里我们看到yolov5s.pt被训练到 150 个历元(蓝色),和 300 个历元(橙色):

培训损失(图片由作者提供)

一旦第一个时期完成,我们将有一个显示地面实况和测试图像预测结果的图像镶嵌图,看起来像:

示例生成的马赛克(图片由作者提供)

在 ultralytics 的 colab 笔记本上有一个详细教程,在那里你会发现上面有更详细的解释,你可以自己运行!

推理

现在我们已经在一个人脸面具图像的数据集上训练了这个模型,它已经准备好在单个图像和视频流上运行推理了!

要运行推理,我们必须调用detect.py,并调整以下参数:

  • 权重:训练好的模型的权重
  • 来源:输入运行推理的文件/文件夹,0用于网络摄像头
  • 输出:保存结果的目录
  • iou-thres:NMS 的 IOU 阈值,默认为0.45
  • conf-thres :对象可信度阈值

最后两个您可能需要根据生成的结果稍微调整一下:

  • iou-thres 定义为给定对象获得的交集/并集度量的阈值。默认为0.45,一般来说一个借据高于0.5被认为是一个好的预测。参见Adrian rose Brock的这篇伟大的文章,了解关于这一指标的更多细节。
  • conf-thres 是确定模型对给定边界框包含对象的置信度的度量。它等于 IoU 乘以一个代表物体概率的因子。这一指标主要阻止模型预测背景。阈值越高,误报越少。然而,如果我们将其设置得太高,模型将错过许多正确的检测,因为它的可信度较低。**

经过几次尝试和出错后,以下设置似乎能对此问题产生最佳结果:

python ~/github/yolov5/detect.py --weights raw/roboflow4/weights/last_robo4_epoch300_s.pt --source ./office_covid.mp4 --output raw/roboflow4/inference/output --iou-thres 0.3 --conf-thres 0.6

为了测试这个模型,我用手机拍摄了一段视频。这些是结果:

对视频流的推理测试(图片由作者提供)

在这里,您可以看到该模型能够准确地检测面罩。

改进建议

  • 更多数据训练多样性。该模型在某些条件下很难检测到面具,例如,它往往会混淆长胡子和面具。这可以通过在训练图像中增加更多的多样性以及可能运行额外的数据增强技术来减轻。
  • 比较不同的 YOLOv5 型号,根据指标并考虑培训时间,检查哪种型号性能最佳。更大的型号 YOLOv5x 将需要更长的训练时间。

非常感谢你花时间阅读这篇文章,希望你喜欢:)

每秒 400 张图片,对 3.3 亿张人脸进行人脸识别

原文:https://towardsdatascience.com/face-recognition-on-330-million-images-at-400-images-per-second-b85e594eab66?source=collection_archive---------17-----------------------

人脸检测,在 OK.Ru 的 3.3 亿张人脸上进行人脸识别。

https://habr.com/ru/company/odnoklassniki/blog/350566/

本文由亚历山大托博尔用俄语原创,发表于 2018 年 3 月 7 日,habr.com。

2018 年,每个学生甚至每个高中生都做了一个带有人脸识别的宠物项目。如果数据集不是一百万人,而是:

  • 330 百万用户账户
  • 每天有 20 万张照片被上传
  • 0.2 秒是您可以在每幅图像上花费的最长时间
  • 您的硬件有限

在本文中,我们分享了我们在社交网络 OK 中开发和部署人脸识别系统的经验。Ru

在本文中,我们分享:

  • 算法背后的数学
  • 实施的细节
  • 部署的结果
  • 我们用来推广我们的解决方案的公关活动“StarFace”。

问题

ok.ru 有 3.3 亿用户账户,总共包含 300 亿张图片。

ok.ru 的用户每天上传 2000 万张照片。其中 900 万张照片至少有一张脸。我们总共有 2300 万张脸。*均每张图片有 2.5 张脸。

用户可以在照片上给人贴标签,但他们不会这么做。我们的团队决定建立一个解决方案,自动标记图像中的人。如果用户知道其他人何时与她一起上传图像,这将是更好的用户体验。

我们希望用户在上传照片的同时确认面部标签。因此,在最坏的情况下,处理时间不会超过 200 毫秒。

人脸识别管道

图像上的人脸识别

用户从客户端上传图像:浏览器、装有 iOS 或 Android 的手机。在这之后,图像通过面部检测器。

人脸识别

要运行自动面部识别,我们需要建立每个用户的面部轮廓并填充数据库。

面部轮廓的创建

一般来说,要建立面部轮廓,只有一张照片就足够了。个人资料图片并不总是足够的。用户喜欢把集体照片或名人的照片放在那里。

硬侧写

让我们考虑一个只有群组图片的用户。如果我们知道他的性别和年龄,并且已经建立了朋友档案,我们就可以推断出档案的所有者。

建立用户配置文件的过程

为了建立档案,我们:

第一步:只使用高质量的图片。

如果用户有很多高质量的照片,我们使用最好的 100 张。为了评估我们检查的图像的质量

  • 用户标记了任何人吗?
  • 照片有关于相机类型的元信息吗?
  • 在某个时候,用户将这张图片作为个人资料图片。

第二步:在图像中寻找人脸。

如果图像中有其他人,也没什么大不了的。

第三步:计算每张人脸的嵌入向量。

步骤 4:执行嵌入向量的聚类。

聚类的目标是找出哪个嵌入集对应于用户。照片里有亲朋好友。我们使用 DBScan 进行聚类。

第五步:找到“主”集群

对于每个聚类,我们使用以下公式计算其权重:

  1. 集群的大小。
  2. 形成群集的图像的质量。
  3. 如果照片上有脸部标签。
  4. 在用户简档和图像中匹配年龄和性别。
  5. 聚类的质心到朋友的聚类之间的距离。

我们使用线性回归来计算参数的系数。
正确计算年龄和性别是一项单独的任务,我们将在后面介绍。

要将集群称为“领导者”,我们需要他的权重比最*的集群的权重大一个裕量。我们在列车组上计算这个余量。如果我们没有找到“领导者”,我们重复这个过程,但使用更广泛的图像集合。有些用户我们有两个集群。有些家庭有一个已加入的个人资料。

第六步:计算用户的“主”嵌入。

用户的主要嵌入是前导聚类的质心。有许多方法可以用来建立质心。经过大量的实验,我们决定使用最简单的:所有嵌入集群的*均值。

如果一个用户有几个集群,我们为每个集群计算一个“主嵌入”。

在我们的实验中,我们处理了 80 亿张图片,处理了 330 个用户档案,并为其中的 3 亿张图片建立了嵌入功能。*均来说,我们用每个用户 26 张照片来创建一个档案。一般来说,我们可以每人使用一张图片。但是每个配置文件使用的图像越多,我们就越有信心我们建立的配置文件符合实际用户。
我们重复了几次重建 3 亿份档案的过程。原因是关于朋友的面部简档的信息提高了用户简档的质量。

在我们的实验中,我们处理了 80 亿张图片,处理了 330 个用户档案,并为其中的 3 亿张图片建立了嵌入功能。*均来说,我们用每个用户 26 张照片来创建一个档案。一般来说,我们可以每人使用一张图片。但是每个配置文件使用的图像越多,我们就越有信心我们建立的配置文件符合实际用户。

我们重复了几次重建 3 亿份档案的过程。原因是关于朋友的面部简档的信息提高了用户简档的质量。

人脸检测器

2013 年推出的第一版人脸检测器 OK。它是基于第三方提供商的解决方案。该算法类似于维奥拉-琼斯。在接下来的几年里,这个解决方案变得过时了——基于 MTCNN 的现代方法显示出两倍的性能。我们决定跟随趋势,使用卷积神经网络(MTCNN)的级联。

对于旧的检测器,我们使用了 100 台“旧的”CPU 服务器。几乎所有现代人脸检测算法都使用卷积神经网络(CNN),它在 GPU 上的性能最好。我们没有选择购买足够的 GPU:加密货币矿工购买了所有可用的 GPU。

译者的评论:2018 年夏天是加密货币的热潮。GPU 价格上涨了几次,即使有这么高的价格,也很难买到 GPU。

我们决定在旧的 CPU 上运行新的检测器。

为了检测用户上传的图像上的人脸,我们使用了 30 台机器组成的集群。我们在云中 1000 台低优先级虚拟机上执行的人脸检测和嵌入生成(对用户帐户的迭代)。

(我们的云解决方案的细节在文章one-cloud—осуровнядата-центраводноклассниках中有描述,作者是оleg anastasiev。材料是俄文的!)

当我们分析我们的人脸检测器的性能时,我们发现了一个极端情况:级联的第一级允许太多的候选人进入第二级。探测器开始变慢。

例如,在这些照片中,每张照片需要 1.5 秒。

级联第一阶段后有很多候选人的例子。

为了解决这个问题,我们使用了通常照片没有太多人的假设。我们修改了渠道,在第一阶段后保留不超过 200 名最有信心的候选人。这种优化将最坏的预测提高了四倍。从 1.5 秒到 350 毫秒。

还有一些优化。例如,我们在第一阶段后用斑点检测替换非最大抑制 (NMS)。修改后的推理时间减少了 1.4 倍,而质量没有损失。

我们需要承认在这个领域有很多进步,有像face box这样的作品。将来我们可能会更新我们的人脸检测解决方案。

人脸识别(嵌入提取)

我们试验了 Wide ResNetInception-ResNetLight CNN 网络架构。《盗梦空间》( Inception-Resnet)略胜一筹,目前,它是我们的选择。

为了进行人脸识别,我们需要一个神经网络。一种选择是在网上找一个预先训练好的模特。另一种是我们自己训练它。

要训练网络,您需要训练和验证数据集。人脸识别是一项经过充分研究的任务。有数据集:MSCeleb,VGGFace/VGGFace2,MegaFace。问题是在它们上面训练出来的网络泛化能力不好。

我们门户网站上的面孔与研究数据集中的面孔截然不同:

  1. 年龄分布不同。我们的影像里有孩子。
  2. 不同的民族分布。
  3. 我们有低质量和低分辨率的图片。我们有集体照。

为了克服第三点,我们可以使用图像增强。下采样和 JPEG 压缩转换将完成这项工作。

来自译者的评论:albuminationslibrary 有许多可以模拟图像低质量的转换。

经过几次迭代后,我们集中于以下步骤:

第一步:从~100k 的开放档案中下载照片。
我们随机选择档案,尽量减少他们之间的好友联系。因此,我们假设每个人只会出现在一个个人资料中。

第二步:构建人脸嵌入。

我们使用 Facenet 预训练网络。

第三步:对每个账户进行人脸聚类。

  1. 我们不知道一个账号对应的图片上会出现多少人。因此,我们不应该使用“聚类数”作为聚类算法的输入。
  2. 在理想情况下,我们期望得到非常相似的用户嵌入,形成一个密集的球体。实际上,情况并非如此。例如,我们可以为一个戴眼镜的人和一个不戴眼镜的人准备一件衣服。因此,基于质心的方法对我们不起作用。我们需要使用基于密度的。

基于这两个原因,我们使用了 DBScan 。我们手动选择超参数并进行可视化验证,这是非常标准的。对于主要的超参数“eps”,我们引入了一个基于账户人数的启发式方法。

第四步:聚类过滤

数据集中噪声的主要来源以及我们如何处理它们:

  1. 对应不同人的聚类合并成一个聚类。这可能是由于 Face-Id 网络的限制或 DBScan 的基于密度的性质造成的。解决方案:如果两个或更多的脸来自同一个图像,我们删除这个集群。因此,喜欢自拍拼贴画的人没有成为我们数据集的一部分。修复减少了几次错误合并的数量,所以是值得的。
  2. 几个集群可能对应同一个人。一个戴眼镜和不戴眼镜的人。一个人化妆与否。我们提出了以下解决方案:我们测量集群之间的距离。如果它低于一个阈值,我们合并集群。如果没有,我们删除其中一个集群。
  3. 人脸检测器出错,检测到不是人脸的东西。幸运的是,这很容易解决。

第五步:根据我们得到的数据对网络进行微调,然后回到第二步。

重复 3-4 次,直到收敛。网络逐渐变得更好。在最后一次迭代中,网络变得如此之好,以至于我们的试探法不再增加价值。

我们认为多样性越多越好,并用其他东西扩展了我们新获得的 OKFace 数据集(370 万张脸,77000 人)。

我们的实验表明添加最多的是 VGGFace2 。它大而多样(角度和闪电)。像往常一样,它由在谷歌上找到的名人照片组成。它在标签中有大量的噪声。幸运的是,通过 OKFace 上训练的网络来清理它,是一项相对简单的任务。

损失函数

嵌入学习的最佳损失函数是一个公开的问题。对于我们的工作,我们选择使用尽可能类似于生产中使用的损失函数。

我们使用余弦相似性来比较嵌入“x”和来自候选嵌入(用户和他的朋友) c1,…,cn 的质心。如果 cos(x,ci) ≥ mp,我们宣称确实是照片上的用户。

因此,我们希望:

  • 对于“正确的”候选者 t,cos(x,ct) 大于余量值 mp。
  • 对其他人来说,应该比 mp 小。

我们用下面的损失函数来惩罚对期望结果的偏离。在我们的实验中,这个效果最好。

质心 c1,…,cn 是网络的参数,在梯度下降的训练过程中学习。

这个损失函数有它的问题。第一,当你从零开始训练它时,它没有很好地收敛。第二,调谐两个参数“ mp ”和“ mn ”比较繁琐。尽管如此,用这个损失函数进行微调允许我们获得比用其他函数更好的性能:中心损失对比中心损失A-Softmax (SphereFace)LMCL (CosFace)

值得吗?

数字是 10 次测量的*均值和标准偏差。

对我们来说,一个重要的指标是 TP@FP:当假阳性的数量固定时,我们正确识别的人的百分比。(表中为 0.1%)

由于每 1000 人中有一个错误的限制,并且没有微调,我们只能正确地识别出一半的人。

错误人脸检测的最小化

有时人脸检测器会在没有人脸的地方发现人脸。(占检测结果的 4%)。

列车组产生这种“噪音”是不可取的。当我们要求用户“把名字”放在玫瑰花束上或地毯中间时,这是一种糟糕的用户体验。

最直接的解决方法是在人脸检测器的训练集中添加一组不包含人脸的图像。

我们决定用不同的方法解决这个问题。

  1. 从网上收集一些不包含人脸的图片。
  2. 创建随机作物,构建嵌入,并对它们进行聚类。我们有 14 个集群。
  3. 如果人脸的嵌入位置靠*“非人脸”聚类的质心,我们可以得出结论,建议的人脸不是人脸。
  4. 庆祝我们的方法。

所描述的模式可以被实现为在嵌入之上具有 14 个隐藏单元的双层网络。

奇怪的是,人脸识别网络只向嵌入空间的几个区域发送各种非人脸图像。

每个人都撒谎或者如何在一个社交网络中找到这个人的真实年龄和性别

通常,用户不会显示他们的年龄或者写错号码。为了推导出用户的正确价值,我们使用了朋友图。通常,用户的年龄位于其朋友年龄的最大聚类中。我们从名字和姓氏推断出的性别。

维塔利·胡多巴绍夫在他的演讲中讲述了细节узнатьаквозрастчеловекавсоциальнойсети,дажееслионннетан。讲座是用俄语进行的。)

所有的内部基础设施都没问题。Ru 在 Java。因此,我们管道的所有组件都包装在 Java 中。人脸检测器和人脸识别器用 Java API 在 TensorFlow 中进行推理。人脸检测器在 CPU 上工作。它足够快,并且在现有硬件上运行良好。对于识别器,我们安装了 72 个 GPU。在 GPU 上运行 Inception Resnet 比在 CPU 上运行效率更高。

为了存储嵌入,我们使用 Cassandra。我们所有用户的嵌入总容量约为 300Gb,因此为了快速访问,我们添加了缓存。我们将缓存实现为离堆。

(细节由安德烈·潘金:использованиеразделяемойпамятив爪哇и堆外кеширование 的文章描述。俄语)

我们建立的管道每天可以处理多达 10 亿张照片进行迭代。同时,我们处理用户上传的图片。每天约 2000 万。

结果

我们实现了一个基于社交网络真实数据训练的系统。它是用有限的资源训练出来的,表现出很好的效果。

建立在真实 OK.ru 数据上的数据集的识别质量是 TP=97.5%,FP=0.1%。处理一幅图像的*均时间是 120 毫秒,第 99 个百分点低于 200 毫秒。这个系统是自我完善的。使用标签的图像越多,用户的人脸嵌入轮廓越好。

现在,上传之后,我们在图片上找到的用户会收到一个通知。他们可以确认建议的自动标签,或者如果他们不喜欢该图片,可以将其删除。

自动识别使更新提要的浏览量增加了两倍,点击量增加了三倍。用户对新功能的兴趣是显而易见的。我们计划用一个更好的用户界面和像 Starface 这样的新应用程序来进一步改进它。

关于 UX 的视频。(俄语)

Flashmob StarFace

为了向用户介绍新功能,OK.ru 发起了一项挑战。用户上传他们与在 OK.ru 拥有活跃账户的俄罗斯体育、商业、媒体、著名博主和记者的照片。用户可以获得个人资料照片的徽章或订阅付费服务。(详情。用俄语。)

在快闪活动的最初几天,用户上传了超过 10,000 张名人照片。用户上传了一张与明星的自拍,海报附*的照片,以及 PS 过的图片。

计划

管道中最耗时的部分是检测器。下一步是替换它或转移到 GPU。

我们可以尝试结合不同的人脸识别模型。如果它提升了模型的准确性,那就值得探索。

从用户的角度来看,下一步是识别视频中的人。我们还计划告知用户他们的“克隆档案”

欢迎在"щи,илираспознане330млнлицнасосости400тотото/то

人脸识别/树莓派:你自己的安全警报系统

原文:https://towardsdatascience.com/face-recognition-raspberry-pi-your-own-security-alarm-system-7c73d8af725b?source=collection_archive---------11-----------------------

(权利:自己的形象)

这个项目的目标是有你自己的安全系统在你的办公桌使用人脸识别和报警,我们将从头开始建立!

对于人脸识别,请参考这里的文章,我们在这篇文章的机器学习方面进行了深入研究,并参考这篇文章中我们处理电子组件的更多细节。

硬件:警报响铃

在上一篇文章中,我们使用一个按钮来组织电路,并向晶体管发送电流,以打开和关闭蜂鸣器,这一次,我们需要一种更具编程性的方式来完成这项工作。这实际上可以简单地通过连接两个电阻来实现,如下图所示(图 1)。

图 1(权利:自己的形象)

下一件事是修改 face_recognition.py 的代码,在每次检测到 10 帧的未知人脸时添加警报蜂鸣器,这可以通过下面的代码来完成。

检测到已知人脸时会刷新阈值

软件:人脸识别

对于人脸识别,一般的想法是结合 HaarCascade 人脸检测和局部二进制模式直方图(LBPH)方法。如前所述,我们不会在本文中深入探究这些主题,因为我们在这里解释它们。

由于 LBPH 需要从 HaarCascade 检测中提取灰度裁剪的人脸,我们将使用该检测来拍摄用户的多张照片,以便我们稍后识别用户。这是这部分的源代码,我们很快会解释。

我们拍摄 5 张照片,由人脸检测模型检测。如果可能的话,这些图片应该尽可能地互不相同。

现在到了人脸识别部分,这里是 face_detection.py 和 face_recognition.py 的源代码。

面部检测是标准的:我们输出裁剪的灰度面部和边界框。而对于认知,我们可以评论和任意做出多种事情:

  • 我们估计置信度为 65。这个标量实际上是一个违反直觉的值,因为它表达了图片之间的差异,(在 LBPH 的文章中解释了),因此它越高,我们越不自信。
  • 我们还决定将任何相似度不小于 65 的人(与数据库中的任何人)视为未知。
  • 在连续 10 次未知检测之后,我们将认为被检测的人是不在数据库中的人,因此是局外人,所以我们拉响警报。

结果:两部分的结合

如前所述,您需要做的是运行 get_faces.py。

图 2(权利:自己的形象)

在运行 get_faces.py 之后,你应该准备好让你的脸被识别了。如果您想向数据库中添加更多的人,只需再次重复 get_faces.py 步骤。

现在,通过运行 main.py 脚本,应该可以部署整个项目了。现在,当小偷来到你的电脑或房间时,你就会知道了!这是我们自己的结果(视频 1 ),供您参考。

https://aitechfordummies . com/WP-content/uploads/2020/03/video . MP4

完整的源代码和说明可以在这个上找到。

感谢阅读,如果你喜欢,请记得说出来,或者看看我们的其他文章。你可以在我们的网站上找到我们的文章!此外,点击这个链接(指向联盟计划)真的会帮我解决问题!您只需完成一些快速任务(只需等待和激活通知),所有这些将真正帮助我了解更多未来的硬件相关内容!

人脸识别

原文:https://towardsdatascience.com/face-recognition-using-deep-learning-b9be73689a23?source=collection_archive---------5-----------------------

基于 PCA 和深度学习的人脸识别

我们将学习如何使用带有三重损失函数的预训练神经网络进行人脸识别。

介绍

由于计算机的强大功能提高了效率,图像内容分析和模式识别是当今迅速扩展的应用领域。

尽管文献中提出的系统在执行人脸识别任务时变得更加健壮、可靠和高效,但是该领域中的几个真正的技术和应用方面经常被省略,或者被非常简化,使得对其性能的正式和完整的使用远不是最终的解决方案。

在这项工作中,在人脸识别领域已经证明了良好结果并提供了良好方法的几项科学贡献正在考虑进行一些修改,以便选择最有效的解决方案,并确保与最先进的技术相比,识别性能非常有趣

我们想开发一个人脸识别系统,将在课堂上作为出勤系统使用,以标记讲师和学生的存在。

数据集

我们将使用两个不同的数据集,一个用于 PCA 方法,另一个用于 CNN 方法的自定义人脸数据集。

Olivetti 数据集

https://scikit-learn.org/0.19/datasets/olivetti_faces.html

Olivetti 是剑桥美国电话电报公司实验室在 1992 年到 1994 年间制作的人脸图像数据集。它包含 40 个不同的人的 10 个不同的图像和 400 个面部图像。

除了图像具有相同背景和相同尺寸的事实之外,图像被转换为灰度级,并且像素值从 0 缩放到 1。

这个数据集将是我们接下来研究的主要参考。测试和训练子集将从中产生。

Olivetti 数据集的不同面

当显示每个文件夹的 10 张图片时,我们可以看到这 10 张图片包含了被摄对象不同的面部表情和光照。

Olivetti 数据集中每个受试者 10 张脸

由于我们的机器学习模型需要向量,我们使用 numpy reshape 函数将我们的数据从(400,64,64)图像阵列转换为(400,4096)向量。

然后,我们将数据分为训练和测试:每个对象 70%或 7 张图像作为训练,每个对象 30%或 3 张图像作为测试子集。

制作数据集

我用我的照片和我的三个同事的照片,以及我最喜欢的连续剧“La Casa De Papel”中的一些知名演员,制作了一个由 10 个主题组成的数据集,每个主题大约有 10 张照片。

一个由 10 个受试者组成的数据集,每个受试者有大约 10 张图片

方法学

我们的目的是制作一个需要尽可能少的训练数据的人脸识别系统。这种约束背后的主要原因是,对于管理者来说,用每个学生的一个或几个图片来训练模型比必须为同一个人制作具有许多图像的大型数据集更有用。

我们将比较两种主要的人脸分类模型,PCA 降维和预训练的 CNN。

要执行面部识别,将遵循以下步骤:

  • 检测图像中包含的所有人脸(人脸检测)。
  • 裁剪人脸并提取其特征。
  • 应用合适的面部识别算法将面部与学生和讲师的数据库进行比较。
  • 提供记录所识别的服务人员的文件。

利用主成分分析和不同分类器进行人脸识别

以下研究的目的是使用六种不同的分类模型来执行面部识别,以了解哪一种模型是用作考勤系统的最佳候选模型。

主成分分析

第一步是通过移除这些人脸之间的任何共同特征来标准化训练集的所有人脸,以便每个人脸只留下其独特的特征。这将通过从每个面部移除*均面部(数据集上的像素的*均值)来完成。

我们的图像向量将包括每个图像的 64×64 = 4096 个分量。这些向量将通过对齐像素将二维图像转换成一个向量来创建。

从数字的角度来看,为了表示这样的图像,大量的组件可能被夸大了。为了减少数据的大小,我们将应用 PCA 方法来只选择图像的主要成分。

由于我们的人脸数据中有许多维度,PCA 的使用使得能够恢复或移除最相关的分量,并寻找捕获最大方差的方向,从而我们可以仅获得 m 个最有代表性的分量。

当对我们的数据使用分类器时,将根据获得的最佳准确度来选择分量的数量 m。该过程包括循环几个分量,并为每个指定数量的主分量构建 PCA 模型。然后,我们将构建一个分类器,并根据混淆矩阵计算准确度,以获得可以从中选择最佳组件数量的图。

一旦选择了 m 个特征脸,我们就可以使用这些特征脸从训练集中复制任何一张脸,如图所示。

在从训练集中去除*均人脸后,我们将 2D 图像转换成矢量。然后我们应用主成分分析挑选 m 个最有代表性的成分。一旦选择了 m 个特征脸,就有可能使用这些特征脸从训练集中再现任何脸。

来自训练集的每个人脸可以被投影为 m 个所选特征脸的加权和,这是特征向量空间中给定人脸加上*均人脸的表示。与每个特征脸相关联的权重表示该特征脸对原始脸的再现的贡献。

一旦训练集的所有人脸被转换成它们相应的权重向量,我们就能够通过在特征空间中表示它们来再现训练人脸。

但是,如果我们想要识别一个新面孔,并将其与训练集中的相应主题进行匹配,该怎么办呢?

识别一张陌生的脸

为了识别未知的人脸,我们执行已经应用于训练图像的相同步骤。我们首先对这张脸进行归一化(去掉*均脸)并将其转换成一个矢量。然后,我们将人脸向量归一化到我们在使用 PCA 之前计算的特征空间上,这意味着将未知人脸表示为 m 个特征脸的组合。

一旦我们获得了未知人脸的权重向量,下一步将使用欧几里德距离作为度量,将其与我们训练集的所有权重向量进行比较。

如果两个向量之间的距离大于某个阈值,我们会说这是一张未知的脸,否则,我们会看到对应于最小距离的人,并将他识别为这个人。

用主成分分析法识别未知人脸

使用不同的分类器

一种更稳健的技术是使用分类器(如 SVM 或 KNN ),而不是将输入与训练集中最接*的人脸进行匹配。

图像降维后将引入的分类器有:

线性判别分析 : 它是统计学、模式识别、机器学习中使用的一种方法,用来寻找表征或区分两类或两类以上对象或事件的特征的线性组合。所得到的组合可以用作线性分类器,或者更常见的是,在稍后的分类之前用于维度减少。

逻辑回归 【一对一】:由于我们在一个数据集中会有许多不同的类或主题,我们每次构建模型时都会将属于一个类的数据视为正值,而将属于其余类的数据视为负值。我们将重复这个过程,直到我们建立了尽可能多的模型。

高斯 NB : 这是一种基于应用贝叶斯定理,以条件独立性为“朴素”假设的学习算法。在不检查特征的似然性是否为高斯的情况下,我们将采用这一假设,并查看结果在准确性方面是否可接受。

KNN:它是一种非参数学习算法,被称为“懒惰”,也就是说它不使用任何数据点来生成模型。训练在分类和测试阶段完成,因为算法仅寻找与其他数据点的特征相似性。K 是邻居的数量,它必须是奇数以避免票数相等。

决策树 : 由于图像分类只是模式识别中的一个特例,决策树可以用于此目的。

SVM:支持向量机是这样制造的,它们可以执行两类分类。它们可以适用于以非常有效的方式执行 K 分类。

分类工作流程

主成分分析中成分数量的选择

下图显示了主成分数量与 SVM 径向基函数(RBF)核分类器精度的关系。

SVM 径向基函数(RBF)核分类器相对于 PCA 组件数量的准确性

似乎只用 40 个元件,我们就能获得用 100 个或更多元件获得的同样精度。这意味着我们可以减少计算时间,同时保持模型的相同性能。在下文中,我们将使用 40 个组件。

分类器比较

在 PCA 阶段之后,使用选定数量的成分,我们将我们的数据引入第 3 节中列出的六个不同的分类器,并计算每个分类器的准确度。

比较不同分类器的准确度

根据上述结果,线性判别分析和逻辑回归似乎具有最好的性能,并且可以被认为是对于我们的分类问题的最佳选择。然而,需要许多数据点来预测具有不同亮度的不同图片。

结论

在 Olivetti 数据集上获得了 93%的最大准确度,即使图像被相对良好地定位和照明。对于不允许出错的考勤系统来说,这种低性能是不能容忍的。此外,对于这项技术,我们需要许多图像(大约 10 张)来训练模型。

另一方面,让我们不要忘记,我们的考勤系统必须能够服务于一个大的大学,学生的数量会随着时间的变化而变化。但是,每次必须向数据库中添加新学生时,都需要重新训练 PCA 模型。

使用深度度量学习的面部识别

另一种执行面部识别的方法包括使用名为 Inception 的深度卷积神经网络架构,该架构负责在ImageNet2014 年大规模视觉识别挑战赛(ILSVRC14)中设置分类和检测的新技术状态。

盗梦空间的名称来源于林等人的《网络论文》中的网络,并结合了电影《盗梦空间》中著名的网络迷因《我们需要更深入》。

在这项工作中,我们将使用一个初始架构的变体。该模型包括具有 128 个隐藏单元的全连接层,随后是卷积基础之上的 L2 归一化层。

最上面的两层负责从图像中创建 128 维嵌入。

深度度量架构,CNN 被训练成将图像转换成 128 d 矢量。

深度度量学习架构

目的是让 CNN 学会将每个图像转换成一个向量,使得相同身份的所有人脸之间的欧几里德距离很小,而来自不同身份的一对人脸之间的距离很大。

更准确地说,给定一对不同身份的图像,我们希望距离至少大一定程度,但是给定两幅相同身份的图像,我们希望它们的编码相似,因为它们都表示同一个人。

应保持的余量α必须符合以下公式:

d(A,P)+ α ≤d(A,N)

为了训练神经网络,我们从数据集生成三个一组的图像。然后,在定义了我们想要最小化的三元组损失函数之后,我们使用梯度下降来调整 CNN 的参数,以便学习对相同类别的两个图像给出小距离而对不同类别的图像给出大距离的编码。

训练 CNN 的三联体技术

要最小化的三重损失函数定义如下:

我们将使用 keras-Openface 项目中可用的预训练模型,并调整神经网络的权重,以便检查我们的 alpha-margin (α=0.2),而不是从头开始训练 CNN 模型,这将需要数百万张图像。

面部检测

在将我们的图像输入神经网络之前,必须找到可用的人脸,并对其进行裁剪和对齐。

dlib 库提供了猪+SVM 人脸检测器,还提供了一个预训练的 CNN 人脸检测器,可以使用 GPU 或使用 CPU 运行。

如下图所示,对于包含 9 张人脸的相同样本图像,我们使用 CPU 尝试了两种人脸检测器。两个提取器给出了相同的结果,但是 CNN 需要大约 2 分钟,而猪只需要 6 秒钟。安装 CUDA,编译 dlib 库在 GPU 上运行后,CNN 能够运行快 10 倍。

CNN 面部检测器性能

人脸检测将使用 Dlib 的 CNN 模型进行,因为文档坚持认为与 HOG 人脸检测器相比,CNN 具有较高的准确性。

用对齐的人脸图像训练预训练模型。但通常并不是照片中的所有人脸都没有正确对齐。因此,在将裁剪后的人脸图像输入神经网络之前,必须对其进行对齐,以实现人脸识别任务的高精度。

同样,dlib 有一个预先训练的模型,用于预测和找到一些面部标志,然后将它们转换到参考坐标。

图像预处理

使用 CNN 和距离度量来比较面部

最后,我们可以使用 CNN 从对齐的图像中提取 128 维的人脸向量。在 128 维空间中,欧几里德距离直接对应于人脸相似性的度量。

在使用预训练的 CNN 变换所有数据集图像之后,我们通过相同的过程输入我们想要识别的图像,以获得相似的 128-d 向量(嵌入)。人脸的相似性可以用欧氏距离来度量。

下图以图形方式显示了此过程的工作原理,并举例说明了该算法在相似和不同人脸之间测量的距离。

锚阳性对之间的距离小于其锚阴性对之间的距离(0.59 < 1.43)

最佳距离阈值

为了能够辨别两张脸是否属于同一个人,必须确定距离阈值。为了找到阈值的最佳值,将使用我们的数据库图像测试不同的值。我们将绘制不同阈值距离值的准确度图,并选择最佳值。

从下图中,将选择值 d=0.72,因为它给出了最佳精度(96.8%)。

不同阈值距离人脸识别的 F1 分数和准确率

使用分类器

不使用最小距离来确定检测到了哪些面部,而是使用 KNN 或 SVM 分类方法更有效,其中 K 将被取为等于 5。

用来自数据集的 50%的标记图像来训练分类器,并且在剩余的图像上进行测试,并且与 SVM 分类器进行比较。

使用 KNN 和 SVM 分类器的精度

在研究的其余部分,将使用 KNN 分类器。

数据可视化

由于可视化具有 128 维的嵌入图像不是一件非常容易的任务,我们将使用t-分布式随机邻居嵌入(t-SNE),这是一种由 Laurens van der Maaten 和 Geoffrey Ginton 开发的用于非线性降维的机器学习算法。这种方法将允许我们在二维的低维空间中看到我们的图像的分布。

在下图中, t 分布随机邻居嵌入 (t-SNE)应用于 128 维嵌入向量,以便将数据集汇总到 2D 空间。除了少数异常值之外,身份聚类被很好地分开。

受试者的 t-SNE 显像

结论以及与其他先进模型的比较

我们已经看到 PCA 作为考勤系统的准确率非常低,并且它需要许多人脸作为输入数据进行训练。此外,每次我们有一个新的学生,模型必须从零开始重新训练,参数(PCA 的组件数量)必须再次确定哪个不适合项目的要求。

另一方面,预训练的用于面部识别的 Inception CNN 模型用我们的数据集进行了调整,给出了非常好的性能(在我们的自定义数据集上有 97%的准确率),特别是当我们添加了 KNN 方法时。此外,这个 CNN 不需要有很多图片,因为我们可以在只有一个参考(训练)图片和另一个测试图片的 128 维空间中测量人脸之间的距离。此外,一旦被训练,当新生入学时,不需要再次寻找 CNN 的参数。

出于这个项目的目的,许多其他 CNN 模型都在同一个数据集上进行了训练和测试,但是在前面的章节中只描述了初始模型。使用 ResNet 网络(29 卷积层预训练模型)获得了最好的准确性,并且它将是被选择使用的模型,因为它能够在我们的测试数据集中正确地检测所有人脸。

ResNet 网络是一个更深入的预训练网络,Inception 在一个包含超过 13000 张图像的公共数据集上实现了 99%的准确性,该数据集被称为“野生标记的人脸”。

下表显示了过去 5 年中一些最好的面部识别模型。我们可以看到,我们的模型可以与在相同数据集上测试的最先进的验证方法相媲美。

比较不同验证方法在野生数据集的标记人脸上测试的结果。最后一行是在第一部分取自“深度人脸识别:一项调查”时添加的——王美,魏宏·邓(2019)

密码

项目:在考勤系统中使用 CNN 进行人脸识别:

[## GUI.zip

编辑描述

drive.google.com](https://drive.google.com/file/d/1F79R1GR_e4vkMm2bnsOyEbRo1qX3gAg6/view?usp=sharing)

在 Olivetti 数据集上使用 PCA 进行人脸识别;

[## Olivetti Dataset.ipynb 上的人脸识别

编辑描述

drive.google.com](https://drive.google.com/file/d/1522lW68pAW7ichHHzB9nV7u34gz5Rl-S/view?usp=sharing)

基于 TensorRT 的 Jetson Nano 人脸识别

原文:https://towardsdatascience.com/face-recognition-using-tensorrt-on-jetson-nano-set-up-in-less-than-5min-7c00bf730085?source=collection_archive---------6-----------------------

Jetson Nano 上 FP16 precision 中的 mtCNN 和 Google FaceNet

说到人脸识别有很多选项可以选择。虽然大多数都是基于云的,但我决定构建一个基于硬件的人脸识别系统,它不需要互联网连接,这使得它对机器人、嵌入式系统和汽车应用特别有吸引力。

链接到 Github 库

更新

存储库已更新(2020 年 9 月 18 日),现在一切都可以与 Jetpack 4.4、Cuda 10.2、cudnn 8.0、TensorRT 7.x 和 OpenCV 4.1.1 兼容。

NVIDIA Jetson Nano

来源:https://developer . NVIDIA . com/embedded/jetson-nano-developer-kit

NVIDIA Jetson Nano 是一款面向计算密集型嵌入式应用的单板计算机,包括一个 128 核 Maxwell GPU 和一个四核 ARM A57 64 位 CPU。此外,单板计算机非常适合计算机视觉领域 神经网络的部署,因为它以 5–10W 的功耗提供 472 GFLOPS 的 FP16 计算性能来源。有许多教程可以确保轻松开始使用 Jetson *台,例如 Hello AI-World 教程Jetbot ,这是一个基于 Jetson Nano 的小型 DIY 机器人。

NVIDIA TensorRT

TensorRT 通过合并层和张量,为特定 GPU 选择最佳内核,并在保持精度的同时降低矩阵乘法的精度(FP16,INT8),实现了在您最喜欢的 ML 框架(TensorFlow,Keras,PyTorch 等)中训练的优化机器学习模型。注意,对于 INT8 精度,需要额外的校准步骤来保持精度。由于这显著(至少在大多数情况下)减少了推理时间并提高了资源效率,因此这是在机器人、嵌入式系统(使用 GPU)、自动驾驶和数据中心部署机器学习模型的最终步骤。

来源:https://developer.nvidia.com/tensorrt

FP16 是什么意思?也被称为半精度。大多数框架中的机器学习模型使用 32 位精度进行训练。在 FP16 的情况下,经过训练的模型的精度会降低 16 位,或者对于 NVIDIA Jetson AGX Xavier,您甚至可以将模型转换为 int 8(8 位)。根据 NVIDIA 的推断,经过训练的模型的时间可以加快 100 多倍。

mtCNN

多任务级联卷积网络 (mtCNN)是一种基于深度学习的人脸和地标检测方法,对头部姿势、光照和遮挡不变。在保持实时能力的同时,通过由粗到细的三阶段过程来计算面部和标志位置,这在面部识别场景中尤其重要。

使用 mtCNN 进行人脸和地标检测(来源)

谷歌脸谱网

谷歌的 FaceNet 是一个深度卷积网络,将 160x160 RGB 图像中的人脸嵌入到 128 维的潜在空间中,并允许对嵌入的人脸进行特征匹配。通过在数据库中保存人脸的嵌入,您可以执行特征匹配,这允许识别人脸,因为当前可见人脸嵌入的欧几里德距离将比其他嵌入更接*已知嵌入。

(来源)

设置和代码

由于 Jetpack 附带了 Cuda、CudNN、TensorRT 和 OpenCV,因此这个项目的设置和构建不到 5 分钟。所以,不要害怕尝试它

链接到 Github 仓库

据我所知,这是 TensorRT 中第一个结合了 mtCNN 和 Google FaceNet 的开源 cpp 实现,我邀请您合作,从效率和功能方面改进该实现。

这个项目的设置包括:

  • Jetson Nano 开发工具包
  • Raspberry Pi Camera v2(或 Jetson Nano 支持的任何 USB 相机)
  • 可选: PWM 风扇,用于 CPU 和 GPU 的适当冷却
  • 可选:相机的某种相机支架

表演

最后,这是 Jetson Nano 在 640x480 (480p)中的人脸识别性能的概述:使用 mtCNN 进行人脸检测的
60 毫秒+/- 20 毫秒
22 毫秒+/-2 毫秒用于 facenet 推理

使用 2D 数据进行面部解锁

原文:https://towardsdatascience.com/face-unlock-with-2d-data-684b11e5aee1?source=collection_archive---------62-----------------------

Eric TERRADE 在 Unsplash 上拍摄的照片。世界上最有名的脸!

深度学习方法

所有代码都可以在这里找到。这篇文章的互动版本可以从这里下载

今天我们要用深度学习来创建一个人脸解锁算法。为了完成我们的拼图,我们需要三个主要部分。

  • 一种人脸查找算法
  • 一种在向量空间中嵌入人脸的方法
  • 比较编码人脸的函数

查找面孔

首先,我们需要一种在图像中找到人脸的方法。我们可以使用一种叫做 MTCNN (多任务级联卷积网络)的端到端方法。

就一点点技术背景,之所以叫级联是因为它是由多级组成的,每一级都有它的神经网络。下图显示了该框架。

图片来自https://arxiv.org/abs/1604.02878

我们依赖于来自 facenet-pytorch repo 的 MTCNN 实现。

数据

我们需要图像!我把自己、莱昂纳多·迪卡普里奥和马特·德蒙的一些照片放在一起。

遵循 PyTorch 最佳实践,我使用ImageFolder加载数据集。我创建了MTCNN实例,并使用transform参数将其传递给数据集。

我的文件夹结构如下:

MTCNN自动裁剪和调整输入的大小,我使用了一个image_size=160,因为模型将利用该尺寸的图像进行训练。我还添加了18像素的空白,以确保我们包括了整张脸。

(tensor([[[ 0.9023, 0.9180, 0.9180, ..., 0.8398, 0.8242, 0.8242], [ 0.9023, 0.9414, 0.9492, ..., 0.8555, 0.8320, 0.8164], [ 0.9336, 0.9805, 0.9727, ..., 0.8555, 0.8320, 0.7930], ..., [-0.7070, -0.7383, -0.7305, ..., 0.4102, 0.3320, 0.3711], [-0.7539, -0.7383, -0.7305, ..., 0.3789, 0.3633, 0.4102], [-0.7383, -0.7070, -0.7227, ..., 0.3242, 0.3945, 0.4023]], [[ 0.9492, 0.9492, 0.9492, ..., 0.9336, 0.9258, 0.9258], [ 0.9336, 0.9492, 0.9492, ..., 0.9492, 0.9336, 0.9258], [ 0.9414, 0.9648, 0.9414, ..., 0.9570, 0.9414, 0.9258], ..., [-0.3633, -0.3867, -0.3867, ..., 0.6133, 0.5352, 0.5820], [-0.3945, -0.3867, -0.3945, ..., 0.5820, 0.5742, 0.6211], [-0.3711, -0.3633, -0.4023, ..., 0.5273, 0.6055, 0.6211]], [[ 0.8867, 0.8867, 0.8945, ..., 0.8555, 0.8477, 0.8477], [ 0.8789, 0.8867, 0.8789, ..., 0.8789, 0.8633, 0.8477], [ 0.8867, 0.9023, 0.8633, ..., 0.9023, 0.8789, 0.8555], ..., [-0.0352, -0.0586, -0.0977, ..., 0.7617, 0.7070, 0.7461], [-0.0586, -0.0586, -0.0977, ..., 0.7617, 0.7617, 0.8086], [-0.0352, -0.0352, -0.1211, ..., 0.7227, 0.8086, 0.8086]]]), 0)

完美,数据集返回一个张量。让我们想象一下所有的输入。它们已经被 MTCNN 图像标准化,最后一排的最后三张图像是我自己的自拍:)

我们数据集中的人脸,后三张是我自己的照片!:)作者图片

把…嵌入

我们的数据管道准备好了。为了比较人脸并找出两个是否相似,我们需要在向量空间中对它们进行编码,其中,如果两个人脸相似,与它们相关联的两个向量也相似(接*)。

我们可以使用在著名的人脸数据集之一上训练的一个模型,例如 vgg_face2 ,并使用分类头之前的最后一层(潜在空间)的输出作为编码器。

在这些数据集之一上训练的模型必须已经学习了关于输入的重要特征。最后一层(就在完全连接的层之前)对高级特征进行编码。因此,我们可以使用它来将我们的输入嵌入到一个向量空间中,希望在这个空间中,相似的图像彼此靠*。

具体来说,我们将使用在vggface2数据集上训练的 inception resnet。嵌入空间有512个维度。

torch.Size([8, 512])

太好了,我们有了8图像和8向量

类似

为了比较我们的向量,我们可以使用cosine_similarity来查看它们彼此有多接*。余弦相似度将输出[-1,1]之间的值。在两个比较向量相同的简单情况下,它们的相似度是 1。所以越接* 1,越相似。

我们现在可以找到数据集中每对之间的所有距离。

显示数据集中所有面及其余弦相似性的热图。作者图片

很明显,我和马特或利奥不太相似,但他们有一些共同点!

我们可以更进一步,对嵌入进行主成分分析,并将图像投影到二维*面上

使用主成分分析将图像投影到 2D *面上。作者图片

对这张图片要有所保留。我们将 512 维压缩为 2 维,因此我们丢失了大量数据。

好了,我们有办法找到人脸,看看他们是否彼此相似,现在我们可以创建我们的人脸解锁算法。

我的想法是取允许的人的n张图像,在嵌入空间中找到中心,选择一个阈值,看中心和一张新图像的余弦相似度是小于还是大于它。

来测试一下吧!

锁定。图片来自https://www . timesofisrael . com/in-court-NSO-group-控告-Facebook-说谎-无视-国际法/

锁定。图片来自https://en . Wikipedia . org/wiki/Elon _ Musk #/media/File:Elon _ Musk _ Royal _ society . jpg

人们说我和《纸牌屋》里的里奥很像

锁定。图片来自https://falauniversidades . com . br/ator-la-casa-de-papel-elite-afastado-por-depressao-Miguel-herran/

相似度得分比之前的图像高,所以我猜是真的!

让我们试试我自己的新自拍照

解锁。作者图片

成功了,我加入。

结论

我们已经看到了一种仅使用 2D 数据(图像)来创建面部解锁算法的有吸引力的方式。它依靠神经网络在高维向量空间中对裁剪的人脸进行编码,其中相似的人脸彼此靠*。然而,我不知道模型是如何训练的,可能很容易骗过它(即使在我的实验中,算法运行良好)。

如果模型在没有数据增强的情况下被训练会怎样?那么,很可能,简单地翻动同一个人就能破坏潜在表征。

一个更强大的训练程序将是一个无人监管的程序(类似于 BYOL ),它严重依赖于数据增强。

感谢您的阅读。

弗朗西斯科

不明确的

http://github.com】最初发表于

脸书公开了其最新的聊天机器人搅拌机

原文:https://towardsdatascience.com/facebook-has-open-sourced-its-latest-chatbot-blender-b680eb97bfe2?source=collection_archive---------40-----------------------

这是一个更像人类的聊天机器人,击败了谷歌成为世界上最好的聊天机器人

亚历克斯·哈尼在 Unsplash 上的照片

4 月 29 日,脸书人工智能研究院(展会)宣布,它已经建立并开源了一个新的聊天机器人 Blender。

[## 最先进的开源聊天机器人

脸书人工智能有一个开源的搅拌机,有史以来最大的开放域聊天机器人。它在…方面胜过其他产品

ai.facebook.com](https://ai.facebook.com/blog/state-of-the-art-open-source-chatbot/)

FAIR 报道,Blender 是有史以来最大的 开放域 聊天机器人。它也是第一个拥有多种对话技能的聊天机器人,包括扮演角色、表现出同理心和讨论几乎任何话题的能力。FAIR 声称 Blender 击败了 Google 的 Meena 成为世界上最好的。

如果你想了解更多,请查看 Github 和报纸。

击败谷歌成为世界上最好的

费尔声称 Blender 是最大的聊天机器人,并且是世界上最好的。

预先训练和微调的搅拌机模型可在 GitHub 上获得。该模型包含多达 94 亿个参数,比现有最大的系统——谷歌最新的聊天机器人 Meena 多 3.6 倍。

与脸书 Blender 的对话

当谷歌在 1 月份发布 Meena 时,谷歌称它是世界上最好的聊天机器人。现在,根据脸书自己的成对人类评估,

  • 75%的评估者认为 Blender 比 Meena 更有吸引力,
  • 67%的评估者认为 Blender 的表现更像人类。
  • 49%的评估者最初无法区分聊天机器人 Blender 和真人。

其他聊天机器人和 Blender 的主要区别在于 Blender 有能力扮演一个角色,表现出同理心,并讨论几乎任何话题。

在撰写本文时,谷歌尚未对这一说法发表评论。

搅拌机食谱

根据 FAIR 的说法,Blender 令人印象深刻的结果是:

  1. 巨大规模的训练数据,
  2. 混合技能的附加数据集
  3. 生成策略。

与其他自然语言处理项目一样,Blender 接受了大规模的训练,涉及 15 亿次公开的 Reddit 对话。

此外,使用混合技能对话(BST) 对该模型进行了微调,这加强了以下技能的模型:

在训练和微调过程中,使用了许多可能的生成策略,包括波束搜索、下一个令牌采样、n 元语法分块和仔细选择搜索超参数。

9.4B 参数模型需要至少两个 32gb V100 GPUs 进行交互。

Blender 还是会出错

虽然结果看起来很优秀,但 Blender 的技能在对话系统中仍远未达到人类水*的智能。

到目前为止,该团队只评估了 14 轮对话流的聊天机器人。研究人员说,Blender 可能会在几天或几周的谈话过程中重复和乏味。

另一个问题是 Blender 无法记住更早的对话。Blender 使用标准的 Transformer 架构,该架构有 128 个 BPE 历史令牌的硬限制,因此不可能扩展他们从用户那里学到的东西或关于用户的东西,请参考他们以前说过的东西。

Blender 还倾向于整理事实,这是深度学习的一个限制,因为它基于统计相关性而不是知识来生成句子。

防止聊天机器人使用有毒或有偏见的语言

你还记得 Tay 吗? Tay 是一个聊天机器人,最初由微软公司于 2016 年 3 月 23 日通过 Twitter 发布;当该机器人开始通过其 Twitter 帐户发布煽动性和攻击性的推文时,它引起了随后的争议,导致微软在推出后仅 16 小时就关闭了该服务。

“泰”在不到 24 小时的时间里从“人类超级酷”变成了十足的纳粹

任何聊天机器人都面临着同样的挑战:如何防止它说出有毒或有偏见的语言。这些聊天机器人被训练成模仿人与人之间的对话,它们有时可以从人与人的数据中学习不良特征。

FAIR 一直试图通过要求众包工作人员过滤掉有毒语言来解决这个问题。然而,这似乎是一个不可能的任务,因为 Reddit 数据集太大了。此外,研究小组还试图在有毒语言出现之前应用分类器来检测它,但他们指出,这样的分类器仍然不是绝对正确的。

尽情享受吧!

大概就是这样。感谢阅读。

如果你想有一个发挥和阅读细节,这里有链接

脸书逆烹饪算法

原文:https://towardsdatascience.com/facebook-inverse-cooking-algorithm-88aa631e69c7?source=collection_archive---------76-----------------------

比人类更好地从图像中预测完整的食谱

图 1 预测寿司餐中运行逆烹饪算法后的配料3

这种食谱检索算法是由脸书人工智能研究所开发的,它能够直接从图像中预测配料、烹饪说明和食谱标题(图 2) 1

图 2 逆向烹饪算法生成菜谱的例子【1】

过去,算法一直使用基于嵌入空间中图像相似性的简单配方检索系统。这种方法高度依赖于学习嵌入的质量、数据集大小和可变性。因此,当输入图像和静态数据集不匹配时,这些方法就会失败1

反向烹饪算法不是直接从图像中检索食谱,而是提出了一个流水线,其中有一个中间步骤,首先获得配料集。这使得指令的生成不仅要考虑图像,还要考虑配料(图 1) 1

图 3 用多个编码器和解码器生成烹饪指令的逆向烹饪食谱生成模型1

这种方法的主要成就之一是在试图从图像中预测成分时,呈现出比基线配方检索系统2和普通人1更高的准确性。

图 4 左图:通过检索方法2、脸书方法(我们的)和人类获得的成分的 IoU 和 F1 分数。右图:根据人类判断的配方成功率1

反向烹饪算法包含在一个食物推荐系统应用程序中,此处发布。基于 web 应用程序中预测的成分,向用户提供了几个建议,例如:不同的成分组合(图 1)。

参考

1 A. Salvador,M. Drozdzal,X. Giro-i-Nieto 和 A. Romero,《逆向烹饪:从食物图像生成食谱》,计算机视觉与模式识别, 2018。

2 A. Salvador,N. Hynes,Y. Aytar,J. Marin,F. Ofli,I. Weber 和 A. Torralba,“学习烹饪食谱和食物图像的跨模态嵌入”,计算机视觉和模式识别, 2017。

3走向数据科学,“构建美食推荐系统”,2020。【在线】。可用:https://towards data science . com/building-a-food-recommendation-system-90788 f 78691 a。[2020 年 5 月 18 日获取]。

Python 中时间序列预测的脸书预言家

原文:https://towardsdatascience.com/facebook-prophet-for-time-series-forecasting-in-python-part1-d9739cc79b1d?source=collection_archive---------9-----------------------

预言家预测

Prophet 是一个开源的时间序列预测算法,由脸书设计,易于使用,无需任何统计或时间序列预测方面的专家知识。Prophet 通过找到一条最佳*滑线来构建模型,该线可以表示为以下部分的总和:

y(t) = g(t) + s(t) + h(t) + ϵₜ

  • 总体增长趋势。g(t)
  • 每年的季节性。s(t)
  • 每周季节性。s(t)
  • 假日效应 h(t)

在这篇博文中,我们将会看到下面列出的**fbprophet** 库中一些有用的函数,并附有一个例子。

  1. **Prophet.fit**
  2. **Prophet.predict**
  3. **Prophet.plot**
  4. **Prophet.plot_components**
  5. **Prophet.add_seasonality**
  6. **Prophet.add_regressors**
  7. **Prophet.seasonalities**
  8. **Prophet.predictive_samples**

让我们从描述我们将在演示中使用的样本数据集开始。

数据描述

我们将使用包含列(**date****target****regr1****regr2**)的合成每日时间序列数据(如下所示),共 180 天,其中**target**是我们希望每天预测的值,**regr1****regr2**是影响目标值的外部因素。

让我们通过绘制目标列和回归列来直观地查看数据。

# Importing Libraries
import pandas as pd

# loading the time series data into a dataframe
df = pd.read_csv('ts_with_2regressors.csv')
df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d') # plotting the time series data
df.plot(x='date', y='target', figsize=(20, 5), title='Time series Data')

样本时间序列数据

# plotting the regressors
ax = df.plot(x='date', y='target', figsize=(20, 5), title='Regressors Effect')ticks, _ = plt.xticks()y_min = df.target.min()
y_max = df.target.max()plt.vlines(x=list(df[df['regr1'] == 1]['date'].values), ymin=y_min, ymax=y_max, colors='purple', ls='--', lw=2, label='regr1')plt.vlines(x=list(df[df['regr2'] == 1]['date'].values), ymin=y_min, ymax=y_max, colors='green', ls=':', lw=2, label='regr2')plt.legend(bbox_to_anchor=(1.04, 0.5), loc="center left")plt.show()

回归因素效应

我们可以看到,时间序列数据中的尖峰是由回归变量造成的(**regr1****regr2**)。在接下来的章节中,我们将看到如何获取这些回归变量并对其建模。

先知安装:

和所有 python 库一样,您可以使用 pip 安装**fbprophet**。先知的主要依赖是**pystan**

# Install pystan with pip before using pip to install fbprophetpip install pystan
pip install fbprophet

现在让我们看看如何使用上述功能:

生成预测:

  • Prophet 遵循 sklearn 模型 API。我们创建了 Prophet 类的一个实例,然后调用它的 fit( **Prophet.fit**)和 predict( **Prophet.predict**)方法。
  • Prophet 的输入总是一个包含两列的数据帧:***ds******y*****ds**(日期戳)列应该是熊猫所期望的格式,理想的是**YYYY-MM-DD**表示日期,或者**YYYY-MM-DD HH:MM:SS**表示时间戳。**y**列必须是数字,代表我们希望预测的测量值。
  • 为了演示,我们将使用前 150 天的 ***target*** 值作为训练数据,并预测所有 180 天的目标。

注意:对于这一步,我们将只考虑**date****target**

# Creating train and predict dataframe
df = df.rename(columns={'date':'ds', 'target':'y'})
df_train = df[['ds', 'y']].iloc[:150]
df_predict = df[['ds']] # Fitting a Prophet model
model = Prophet()
model.fit(df_train)
forecast = model.predict(df_predict)forecast.head()

预测标题 GIF

# plotting the actual and forecast values

ax = (df.plot(x='ds',y='y',figsize=(20,5),title='Actual Vs Forecast'))
forecast.plot(x='ds',y='yhat',figsize=(20,5),title='Actual vs Forecast', ax=ax)

实际与预测

从上面的输出我们可以看到,prophet 非常适合数据,但它仍然无法捕捉数据中的突然跳跃。这些跳跃基本上是由 prophet 在默认情况下无法检测到的外部变量引起的。我们将在接下来的章节中看到如何对 Prophet 建模以捕捉这些外部因素。

绘制预测图:

  • 我们可以通过调用**Prophet.plot** & **Prophet.plot_components**方法并传入预测数据帧来绘制预测和组件,如下所示
  • 预测图是一个包含历史数据点散点图的单一图表,由黑点表示,预测/拟合曲线由蓝线表示。该图还包含对应于不确定性带的浅蓝色阴影区域。
  • 分量图是一组对应于各种时间序列分量(**trend****seasoanilities**)和外部影响的图。
# Plotting the generated forecast
fig1 = model.plot(forecast, uncertainty=True)

预测产量图

# Plotting the forecast components.
fig2 = model.plot_components(forecast)

预测组件图

如开始提到的**Prophet**根据训练数据估计了**trend****weekly_seasonality**

现在让我们理解上面的两个图:

预测产量图:

  • X 轴代表历史和未来日期的日期值(**ds** )
  • Y 轴代表历史和未来日期的目标值(**y****yhat**)。
  • 图中的**black dotted points**代表历史训练数据点。
  • **blue line** 代表对历史和未来的预测。
  • 此外还有代表不确定性范围的**light blue region** (我们将在接下来的章节中看到更多相关内容。)

预测组件图:

  • X 轴代表历史和未来日期的日期值(**ds** )
  • Y 轴代表相应预测成分的预测估计值(**trend****seasonality**)
  • Graph1: **trend** 所有日期的值(历史和未来)。
  • Graph2: **weekly_seasonality** 基于训练数据的一周中每一天的每周配置文件。

正如我们所见,使用 prophet 可以很容易地对您的时间序列数据建立合理的预测模型。

添加自定义季节

  • 在 Prophet 中,我们可以使用函数**Prophet.add_seasonality**对定制的季节性进行建模。
  • 默认情况下,Prophet 会根据可用的训练数据自动模拟附加的**daily****weekly****yearly**季节性。
  • 我们可以使用函数**Prophet.seasonalities**得到推断的季节性的细节
  • 现在让我们用上面的方法来模拟一个**monthly**季节性。
# Modelling a custom monthly seasonality
model2 = Prophet()
model2.add_seasonality(name='custom_monthly', period=30.5, fourier_order=10)model2.fit(df_train)
forecast2 = model2.predict(df_predict)print(model2.seasonalities)

fig1 = model2.plot(forecast2, uncertainty=True)

fig2 = model2.plot_components(forecast2, uncertainty=True)

从上图中我们可以看到,Prophet 已经对 custom_monthly 季节性进行了建模,与默认预测相比,预测也有所修改。

添加外部回归变量

到目前为止,prophet 模型还不能对训练数据中的一些点进行建模。我们知道,由于外部回归因素(**regr1****regr2**),这些值偏离了常规值。

现在让我们看看如何捕捉这些价值并对它们建模。

  • 与季节性相似,prophet 也有一种方法,使用函数**Prophet.add_regressors**捕捉/模拟对目标值有影响的外部因素。
  • 在我们使用的样本数据中,我们提到了影响目标值的两个外部回归量。
  • 为了模拟和预测回归变量的影响,训练和预测数据框架都应该包含回归变量数据。
  • 现在让我们来看看如何使用上述函数对这些回归变量进行建模。

注意:回归变量应该是数值,如果回归变量包含字符串数据,您必须执行一次热编码。

# adding regressor data in historical and future datesdf_train3 = (df[['ds', 'y', 'regr1', 'regr2']]
             .iloc[:150]
             .copy())
df_predict3 = df[['ds', 'regr1', 'regr2']].copy()# modelling external regressors prior to model fittingmodel3 = Prophet()
model3.add_regressor('regr1')
model3.add_regressor('regr2')

# fit and predcit
model3.fit(df_train3)
forecast3 = model3.predict(df_predict3)# Plot the forecast
fig1 = model3.plot(forecast3, uncertainty=True)

具有外部回归变量的先知模型

# plot model components
fig2 = model3.plot_components(forecast3, uncertainty=True)

具有外部回归的先知模型组件

从上面的输出中,我们可以观察到该模型已经很好地捕捉到了两个外部影响,从输出图中,我们可以看到目标值相对于回归变量有大约 5%和 20%的提升。

先知后验样本

  • 默认情况下,prophet 每天生成 1000 个后验样本,以估计不确定性范围的上限和下限。在某一天,后验样本的*均值几乎等于预测值**yhat**
  • Prophet 可以使用函数**Prophet.predictive_samples**访问历史和未来某一天的后验样本
  • 我们可以使用参数**uncertainty_samples**在 prophet 实例化时修改样本数量
  • 现在让我们用预测数据帧中 1 周的后验样本生成一个数据帧。
# Select one week from prediction df
df_1wk = df_predict3.iloc[:7]
df_1wk

# fetching the posterior samples.
samples = model3.predictive_samples(df_1wk)df_samples = pd.DataFrame(data=samples['yhat'], index=df_1wk['ds']).reset_index()df_samples

现在让我们计算一天后验样本的*均值,并将其与当天的预测值进行比较。

# Forecast 
forecast3[forecast3['ds'] == '2018-09-02'][['ds', 'yhat']]

# Mean of the posterior samples.
df_samples[df_samples['ds'] == '2018-09-02'].set_index('ds').mean(axis=1)

我们可以看到后验样本的*均值几乎等于某一天的预测值。

结论:

我们的演示到此结束。希望你会发现这篇文章内容丰富。您可以在以下存储库中找到数据和 Jupyter 笔记本:

[## upraneelnihar/ML-项目

此文件夹包含与各种时间序列任务相关的 jupyter 笔记本:Time _ series _ analysis _ FB prophet . ipynb:This…

github.com](https://github.com/upraneelnihar/ML-Projects/tree/master/Time_series)

请尝试使用 prophet 为您的时间序列数据建模,并在评论部分分享您的想法。

脸书树立了语言翻译的新里程碑

原文:https://towardsdatascience.com/facebook-sets-a-new-milestone-in-language-translation-4c9ae0a5a347?source=collection_archive---------40-----------------------

了解 M2M-100,一种多语言机器翻译模型,可在 100 种语言对之间进行翻译。

格伦·卡丽在 Unsplash 拍摄的照片

L 语言翻译是一项具有挑战性的自然语言处理任务,需要大量的数据来训练模型。然而,在过去几年中已经取得了很大进展。最*,脸书发布了一个新的多语言机器翻译(MMT)模型,为这项挑战树立了一个新的里程碑1

这是第一个在任意两种语言之间翻译时不依赖英语数据的模型。使用 BLEU 指标,它也以 10 分的优势击败了以前以英语为中心的模型。凭借其创造性的数据挖掘方法和数量惊人的计算资源,他们建立了一个真正令人印象深刻的模型。

在本文中,我们将研究模型的架构,并强调它们用来创建数据集的最重要的方法。

创建数据集

大模型需要大量的数据。为了训练这个模型,来自脸书的研究人员使用了 75 亿个句子!可想而知,要为 100 种语言找到一个高质量的句对句翻译对是很难的。

所有语言翻译都重要吗?

有些译本非常罕见。例如,土耳其语到缅甸语,或者阿尔巴尼亚语到斯瓦希里语。这些语言之间的高质量翻译数据也很难找到。脸书大学的研究人员通过将语言分成具有相似特征的语系来简化翻译任务。例如,斯拉夫语和德语是两个独立的语系。在每一个语系中,他们确定了一个语系中最常见的过渡语言。这些桥接语言被用作在两种不同语系的语言之间进行翻译的中间步骤。

以英语为中心的数据与桥梁策略。修改自1

例如,不是有一个直接的阿尔巴尼亚语到斯瓦希里语的翻译,而是有阿尔巴尼亚语-希腊语(桥)-斯瓦希里语(桥)。这有助于减少数据集的大小,并证明有助于训练每个模型的特定模型参数1

通过这种方法,他们简化了翻译任务,同时没有牺牲太多的性能损失。总共,它使用 100 种语言产生 2200 个方向的翻译。这比*移方向的最大可能数量 9900 (100 x 99)小得多。

数据挖掘技术

很难找到直接的句子到句子的翻译。然而,更容易找到以不同语言出版的相同文件。但是,为了创建相应的句子对,我们需要在文档中“关联”不同语言的句子。

为了找到相应的句子对,脸书的研究人员使用了 CCMatrix 2和 CCAligned 3

CCMatrix 通过比较两种语言中所有可能的、独特的句子来工作1。这种方法计算量很大,CAligned 可能是一个更有效的选择,因为它预先选择了要一起比较的文档1

M2M 100 建筑

该模型的架构基于众所周知的变压器架构。由于任务的复杂性,他们增加了标准架构的规模。M2M-100 的参数如下:

  • 24 个编码器和 24 个解码器层(因不同实验而异)
  • 嵌入尺寸大小为 1024
  • FFN(前馈网络)尺寸为 8192

变压器架构的架构。修改自4

变压器采用序列对序列架构。给定输入序列,模型将产生另一个输出序列。这个模型的问题在于它是为双语数据设计的1。为了适应多对多语言的情况,在编码器和解码器层添加了特殊的标记来表示源语言和目标语言1

该模型的另一个改进是添加了特定于语言的参数。这提高了模型的性能,但也增加了总参数的数量。

结果

最终的 M2M-100 模型包含 150 亿个参数。他们还有一个更小的版本(只有?)15 亿个参数。

测试数据集上的结果显示了 M2M 模型的优势。

多对多和以英语为中心的模型的 BLEU 分数。

以英语为中心的模型和多对多模型在从任意语言到英语的翻译中表现相似,反之亦然(前两列)。然而,对于非英语翻译,例如瑞典语到斯瓦希里语,或者德语到波兰语,M2M 模型实现了显著更高的 BLEU 分数。这就是这种模式的精髓和新颖之处。

此外,该模型在由人类评估语义准确性(得分从 1 到 10)时表现更好。对于每一对语言,每个评估者给每个模型 50 个句子打分。我们可以从下面的图中看到,M2M-100 对于非英语翻译来说要好得多。

翻译质量的人工评估(语义准确性)。M2M-100 vs 以英语为中心的模式。修改自1

是开源的吗?

你可以在这里找到他们的开源实现 但是,要注意:数据集和模型是巨大的。它是在多汁的脸书服务器上训练的,而不是在普通人的个人电脑上。尽管他们提供了模型检查点,但是您需要至少 64GB 的内存来将其存储在内存中。

结论

M2M-100 是语言翻译任务的又一个里程碑。当英语作为中间翻译步骤被去除时,翻译的质量显著提高。不幸的是,这种型号很难使用,即使是在好的电脑上,因为它需要 64 GB 的内存。

关于我

我是阿姆斯特丹大学的人工智能硕士学生。在我的业余时间,你可以发现我摆弄数据或者调试我的深度学习模型(我发誓这很有效!).我也喜欢徒步旅行:)

如果你想了解我的最新文章和其他有用的内容,以下是我的其他社交媒体资料:

参考

1 超越以英语为中心的多语言机器翻译

2 CCMatrix:挖掘网络上数十亿高质量的*行句

[3]c aligned:跨语言网络文档对的大规模集合

你所需要的只是注意力

[5] 第一个不依赖英文数据翻译 100 种语言的 AI 模型(来自论文的博文)

脸书的数据科学面试实践问题

原文:https://towardsdatascience.com/facebooks-data-science-interview-practice-problems-46c7263709bf?source=collection_archive---------11-----------------------

一些脸书面试问题的预演!

UnsplashNeONBRAND 拍摄的照片

鉴于我的文章的受欢迎程度…

这次我在网上收集了一些脸书的数据科学面试问题,并尽我所能回答了它们。尽情享受吧!

如果这是你喜欢的那种东西,成为第一批订阅 我的新 YouTube 频道在这里 !虽然还没有任何视频,但我会以视频的形式分享很多像这样的精彩内容。感谢大家的支持:)

问:你从 100 枚硬币中随机抽取一枚——1 枚不公*硬币(正面朝上),99 枚公*硬币(正面朝下),然后掷 10 次。如果结果是 10 头,硬币不公*的概率是多少?

这可以用贝叶斯定理来回答。贝叶斯定理的扩展方程如下:

假设选到不公*硬币的概率表示为 P(A),连续翻转 10 个头像的概率表示为 P(B)。那么 P(B|A)等于 1,P(B∣ A)等于 0。⁵ ⁰,P( A)等于 0.99。

如果填入等式,那么 P(A|B) = 0.9118 或者 91.18%。

问:有一栋楼有 100 层。你有两个相同的鸡蛋。如何用 2 个鸡蛋找到门槛楼层,在这里鸡蛋肯定会从 N 层以上的任何一层破开,包括 N 层本身。

更具体地说,问题是在给定两个鸡蛋的情况下,寻找阈值下限的最优方法。

为了更好地理解这个问题,我们假设你只有一个鸡蛋。要找到门槛楼层,你可以简单地从第一层开始,放下鸡蛋,然后一层一层往上爬,直到鸡蛋裂开。

现在想象我们有无限的鸡蛋。寻找最低门槛的最佳方法是通过二分搜索法。首先,你会从 50 楼开始。如果鸡蛋裂开了,你就在 25 楼扔一个鸡蛋,如果鸡蛋没有裂开,你就在 75 楼扔一个鸡蛋,重复这个过程,直到你找到门槛楼层。

对于两个鸡蛋,寻找阈值下限的最佳方法是上述两种解决方案的混合…

例如,你可以每隔 5 层扔第一个鸡蛋,直到它破了,然后用第二个鸡蛋找出在 5 个增量之间的哪一层是门槛层。在最坏的情况下,这将需要 24 滴。

如果你每隔 10 层楼扔第一个鸡蛋,直到它破掉,在最坏的情况下,它会掉 19 下,这比每隔 5 层楼扔第一个鸡蛋要好得多。但是如果你想做得更好呢?

这就是最大遗憾最小化这个概念发挥作用的地方。基本上,这意味着当你以给定的增量完成更多的下降(你跳过多少层)时,你希望每次都缓慢地减少增量,因为阈值楼层的可能楼层会更少。这意味着如果你的第一次下落是在 n 层,那么你的第二次下落应该是在 n + (n-1)层,假设它没有破裂。这可以写成下面的等式:

更进一步,这可以简化为:

求解 n,你得到大约 14。因此,你的策略将是从第 14 层开始,然后 14+13,然后 14+13+12,等等,直到它打破,然后使用第二个蛋一次一层地找到门槛层!

问:我们有两种在 Newsfeed 中投放广告的选择。方案一:每 25 个故事中,就有一个是 ad。方案二:每个故事都有 4%的几率成为广告。对于每个选项,100 个新闻故事中显示的广告的预期数量是多少?

两种选择的预期赔率都是 4/100。

对于选项 1,1/25 相当于 4/100。
对于选项 2,100 的 4%是 4/100。

如果我遗漏了什么,请随时告诉我,因为这个问题似乎太直截了当了!

问:只知道性别身高,你如何证明男性*均比女性高?

你可以用假设检验来证明男性*均比女性高。

零假设是男性和女性*均身高相同,而另一个假设是男性的*均身高高于女性的*均身高。

然后,您将收集男性和女性身高的随机样本,并使用 t 检验来确定您是否拒绝空值。

问:如果 iOS 上 70%的脸书用户使用 Instagram,但 Android 上只有 35%的脸书用户使用 Instagram,你会如何调查这种差异?

有许多可能的变量会导致这种差异,我将检查一下:

  • iOS 和 Android 用户的人口统计数据可能会有很大差异。例如,根据 Hootsuite 的调查,43%的女性使用 Instagram,而男性只有 31%。如果 iOS 的女性用户比例明显高于 Android,那么这可以解释这种差异(或者至少是部分差异)。这也适用于年龄、种族、民族、地点等
  • 行为因素也会对差异产生影响。如果 iOS 用户比 Android 用户更频繁地使用手机,他们更有可能沉迷于 Instagram 和其他应用程序,而不是那些在手机上花费时间少得多的人。
  • 另一个需要考虑的因素是 Google Play 和 App Store 有什么不同。例如,如果 Android 用户有明显更多的应用程序(和社交媒体应用程序)可供选择,这可能会导致用户的更大稀释。
  • 最后,与 iOS 用户相比,用户体验的任何差异都会阻止 Android 用户使用 Instagram。如果这款应用对安卓用户来说比 iOS 用户更容易出错,他们就不太可能在这款应用上活跃。

问:每个用户的点赞数和在一个*台上花费的时间在增加,但用户总数在减少。它的根本原因是什么?

一般来说,你会想从面试官那里获得更多的信息,但是让我们假设这是他/她唯一愿意提供的信息。

关注每个用户的点赞数,有两个原因可以解释为什么这个数字会上升。第一个原因是,随着时间的推移,用户的*均参与度普遍提高了——这是有道理的,因为随着使用该*台成为一种习惯性做法,久而久之的活跃用户更有可能成为忠实用户。每个用户点赞数会增加的另一个原因是分母,即用户总数,在减少。假设停止使用该*台的用户是不活跃的用户,也就是参与度和点赞数低于*均水*的用户,这将增加每个用户的*均点赞数。

上面的解释也适用于在*台上花费的时间。随着时间的推移,活跃用户变得越来越活跃,而很少使用的用户变得不活跃。总体而言,参与度的增加超过了参与度很低的用户。

更进一步说,有可能“参与度低的用户”是脸书能够检测到的机器人。但随着时间的推移,脸书已经能够开发出识别和删除机器人的算法。如果以前有大量的机器人,这可能是这种现象的根本原因。

问:脸书发现赞数每年增长 10%,为什么会这样?

给定年份的总赞数是用户总数和每个用户的*均赞数的函数(我称之为参与度)。

用户总数增加的一些潜在原因如下:由于国际扩张而获得的用户以及随着年龄增长而注册脸书的年轻群体。

参与度增加的一些潜在原因是用户对应用程序的使用增加,用户变得越来越忠诚,新的特性和功能以及用户体验的改善。

问:如果我们测试产品 X,你会看什么标准来确定它是否成功?

决定产品成功的标准取决于商业模式和企业试图通过产品实现的目标。《精益分析》一书展示了一个很好的框架,人们可以用它来确定在给定场景中使用什么指标:

精益分析框架

问:如果一个项目经理说他们想把新闻订阅的广告数量增加一倍,你如何判断这是不是一个好主意?

您可以通过将用户分成两组来执行 A/B 测试:一组是广告数量正常的对照组,一组是广告数量翻倍的测试组。然后,您将选择指标来定义什么是“好主意”。例如,我们可以说零假设是广告数量翻倍会减少花在脸书上的时间,另一个假设是广告数量翻倍不会对花在脸书上的时间有任何影响。但是,您可以选择不同的指标,如活跃用户数或流失率。然后,您将进行测试,并确定拒绝或不拒绝 null 的测试的统计显著性。

问:有一个游戏,给你两个公*的六面骰子,让你掷骰子。如果骰子上的数值之和等于 7,那么您将赢得 21 美元。但是,每次掷出两个骰子,你都必须支付 5 美元。你玩这个游戏吗?

掷出 7 的几率是 1/6。
这意味着期望支付 30 美元(5*6)赢得 21 美元。
取这两个数字,预期支付额为-$ 9(21–30)。
由于预期付款为负,你不会想要支付此游戏。

感谢阅读!

如果你喜欢我的工作,想支持我…

  1. 支持我的最好方式就是在MediumT7 这里关注我。
  2. Twitter 这里成为第一批关注我的人之一。我会在这里发布很多更新和有趣的东西!
  3. 此外,成为第一批订阅我的新 YouTube 频道 这里
  4. LinkedIn 这里关注我。
  5. 在我的邮箱列表 这里注册。
  6. 查看我的网站,terenceshin.com

资源

[## 脸书数据科学访谈

脸书雇佣了 CNN 的发明者 Yann LeCun。

medium.com](https://medium.com/acing-ai/facebook-ai-interview-questions-acing-the-ai-interview-5982add0af55) [## 脸书数据科学家面试问题

我在 12 月下旬在网上申请,然后在 1 月初与一名招聘人员谈了大约 15 分钟。我被安排…

www.glassdoor.ca](https://www.glassdoor.ca/Interview/Facebook-Data-Scientist-Interview-Questions-EI_IE40772.0,8_KO9,23_IP3.htm) [## 脸书数据科学家访谈

脸书数据科学家的职位是科技界最令人垂涎的职位之一。它需要多种技能…

towardsdatascience.com](/the-facebook-data-scientist-interview-38556739e872) [## 来自脸书的数据科学面试问题示例:

我们分析了发布在 Glassdoor 上的脸书数据科学家的采访经历和发布的普通采访…

mockinterview.co](http://mockinterview.co/index.php/2018/04/07/sample-data-science-interview-questions-from-facebook/)

脸书的代码转换器——一个人工智能源代码到源代码的编译器

原文:https://towardsdatascience.com/facebooks-transcoder-an-ai-source-to-source-compiler-23ea77f3234b?source=collection_archive---------28-----------------------

来源:https://arxiv.org/pdf/2006.03511.pdf

使用超过 280 万个开源 GitHub 存储库,TransCoder 在三种流行语言(C++、Java 和 Python)之间翻译代码。

澳大利亚联邦银行花了* 5 年时间和 7 . 5 亿美元将他们所有的代码*台从 COBOL 转换成 Java。

[## 银行争相修复旧系统,因为它的“牛仔”骑到日落

纽约(路透社)-比尔·欣肖不是一个典型的 75 岁老人。他在家庭中分配时间,他有 32 个…

www.reuters.com](https://www.reuters.com/article/us-usa-banks-cobol/banks-scramble-to-fix-old-systems-as-it-cowboys-ride-into-sunset-idUSKBN17C0D8)

用最新的编程语言或技术来更新系统需要花费数百万美元和数年时间。脸书人工智能研究所(FAIR)的团队开发了一种人工智能模型,代码转换器。FAIR 旨在通过自动化解决这一问题,借助先进的深度学习架构,在当今使用的 3 种流行编程语言之间进行翻译。

编程语言的现状

[## 堆栈溢出开发者调查 2020

每个月,大约有 5000 万人访问 Stack Overflow 来学习、分享和建立他们的职业生涯。行业估计…

insights.stackoverflow.com](https://insights.stackoverflow.com/survey/2020#most-popular-technologies)

今天使用的编程语言有数百种,从最早的 COBOL、Fortran 到现代的高级编程语言,如 C++、Java 和 Python。今天,T2 最流行的技术包括 JavaScript、Python、Java、C#和 C++。

Fortran、Lisp 和 COBOL 是至今仍在广泛使用的一些最古老的编程语言,尽管不再受到开发人员的青睐。COBOL 仍然是金融业依赖的主要语言,还有大型机系统。在全球范围内, 95%的 ATM 刷卡和 80%的当面交易都使用 COBOL 。Fortran 正被用于科学编程和高性能计算。这些遗留系统将来需要重新开发,以防止资源过时或贬值。

代码转换器将有助于以经济高效的方式,在最少的人工干预下,将他们的*台转换成现代语言。

模型

目前,代码转换工具是基于规则的,以将源代码标记化并将其转换为抽象语法树(AST ),在抽象语法树上使用手工规则。然后,AST 被转换以生成目标语言的代码。写规则的过程很耗时。

使用无监督学习的方法,人工智能模型训练了超过 280 万个开源 GitHub 知识库,以将代码片段从一种语言映射到另一种语言。来自不同语言的编程关键字被标记化并检查相似性。

代码转换器使用序列到序列(seq2seq)模型,编码器和解码器采用转换器架构。该模型实现了交叉编程语言模型预训练、去噪自动编码和回译——遵循无监督机器翻译的原则。

来源:https://arxiv.org/pdf/2006.03511.pdf

结果

FAIR 在所有 3 种语言中使用了 852 个并行函数,并通过单元测试来检查翻译的准确性。

结果如下,Java 到 C++的翻译具有最高的准确率,为 91.6%。

来源:https://arxiv.org/pdf/2006.03511.pdf

未来

人工智能的出现令人兴奋,同时也令人恐惧。人工智能将改善人类的整体体验,成为我们生活的一部分,就像帮助我们在社会中更好地相互联系和沟通。

未来,随着翻译的改进,程序员可以使用单一代码库轻松改进和构建健壮的跨*台软件,如应用程序和游戏。人工智能也可以被训练从头开始编写代码,就像莱斯大学研究人员开发的BAYOU

[## 开发者们,欢呼吧:现在人工智能可以为你写代码了

莱斯大学的研究人员创造了一个名为 BAYOU 的深度学习软件编码应用程序,可以帮助人类…

www.techrepublic.com](https://www.techrepublic.com/article/developers-rejoice-now-ai-can-write-code-for-you/)

但是随着源到源翻译的改进,智能机器将提高自动化程度,并可能取代一些工作,特别是在测试方面。编程的未来在等着我们!

参考资料:

  1. 编程语言的无监督翻译
  2. 银行争相修复旧系统,因为它的“牛仔”骑到日落
  3. 最受欢迎的技术— 2020 年开发者调查
  4. 开发者们,欢呼吧:现在人工智能可以为你写代码了

来源:编程语言的无监督翻译

LinkedInGitHub 上关注我,或者访问我的网站 rohitssajja . me

基于 Tensorflow 和 OpenCV 的人脸检测

原文:https://towardsdatascience.com/facemask-detection-using-tensorflow-and-opencv-824b69cad837?source=collection_archive---------45-----------------------

格伦·卡丽在 Unsplash 拍摄的照片

简介:

在新冠肺炎危机中,戴口罩对于公共卫生和控制疫情的传播是绝对必要的。如果我们有一个系统可以监控我们周围的人是否遵守这些安全措施,会怎么样?

借助深度学习的力量,这个系统可以检测出一个人是否戴了面具。感谢 prajnasb 编译我用于训练的数据集。我们从这里开始…

[## hod 101s/面罩检测

在 COVID19 危机中,戴口罩对于公共卫生和控制传染病的传播是绝对必要的

github.com](https://github.com/HOD101s/Face-Mask-Detection)

了解我们的数据:

在网上找到的所有资料中,由 prajnasb 发布的数据很容易处理,所以我继续使用同样的方法。任何具有大量戴口罩和不戴口罩的人的图像的数据集都适用于这个问题。

照片由马纳斯·阿查里亚拍摄

我们的数据相当*衡,667 幅图像属于无 _ 掩码类,690 幅图像属于有 _ 掩码类。

处理我们的数据:

由于 keras 强大的处理库,图像增强数据管道化的过程变得非常容易。这里我使用了 keras 在其图像预处理函数下提供的imagedata generator。使用 ImageDataGenerator,我们可以构建图像数据扩充管道,在训练期间实时执行扩充,从而节省内存,使其成为扩充数据的一个非常方便的解决方案。

这里我构建了两个数据生成器:一个用于训练和验证数据,另一个用于测试数据。训练和验证数据只是水*翻转,所以也没有应用大的扩充。完整的功能列表可在文档中找到。一个单独的测试数据生成器已经完成,因为我没有对它进行任何扩充。

模型架构和训练:

我已经利用了迁移学习,感谢 tensorflow 应用程序 api ,这是一个非常简单的任务。使用MobileNetV2模型来构建我的分类器网络。

通过使用迁移学习,我正在利用预先训练的 MobileNetV2 的特征检测能力,并将其应用于我们相当简单的模型。MobileNetV2 之后是我们的 DNN,由 GlobalAveragePooling、Dense 和 Dropout 层组成。由于我们的问题是一个二元分类问题,最后一层有 2 个神经元和 softmax 激活。

一个通用的 Adam 优化器和 Categorical _ crossentropy loss 可以很好地收敛到我的网络的最佳权重。

到第六个纪元时,我在所有测试、训练和验证集上都获得了 100%的结果。

部署:

照片由Adam nieciorukUnsplash 上拍摄

在这里,我使用了流行的 OpenCV 库来获取我的网络摄像头馈送,并在我的模型中运行它。

我们从人脸检测开始。为此,我使用了哈斯级联分类器算法。接下来,我切下面部图像,对其进行归一化和缩放,然后输入到我的分类模型中。

用于训练网络的图像尺寸为 224 x 224,因此我们需要按照 prepImg(pth) 中所述,通过整形和归一化,以类似的方式准备我们的输入图像。

Gif 由 Manas Acharya

OpenCV 实现只是以下内容的连续循环:

  • 检测面部
  • 切片人脸图像
  • 通过分类器
  • 获取并显示预测

结论:

我们已经准备好了一个工作模型,它可以检测一个人是否戴着面罩,并提示这个人戴上面罩!鉴于事情的发展方式,口罩将成为我们社会和公众健康的一个更重要的组成部分,在这种情况下,该系统将是确保遵守安全指南的必要条件。

如果您有任何建议或想法想要讨论,您可以通过 LinkedIn 与我联系。精益求精!

** [## Manas Acharya -机器学习工程师- KubixSquare | LinkedIn

机器学习和数据科学爱好者,曾在前端 Web 领域担任全栈开发人员…

www.linkedin.com](https://www.linkedin.com/in/manas-acharya/) [## 使用 Tensorflow 和 OpenCV 构建石头剪刀布人工智能

古老的游戏被重新想象和更新……

towardsdatascience.com](/building-a-rock-paper-scissors-ai-using-tensorflow-and-opencv-d5fc44fc8222)**

基于面部数据的深度学习:情感、年龄和性别预测

原文:https://towardsdatascience.com/facial-data-based-deep-learning-emotion-age-and-gender-prediction-47f2cc1edda7?source=collection_archive---------10-----------------------

UnsplashSai Kiran Anagani 拍摄的照片

我们如何利用深度学习从面部数据中提取信息?

深度学习在计算机视觉领域有着巨大的应用。计算机视觉的一些最重要的应用是在处理面部数据的领域。人脸检测和识别广泛应用于安全领域。如果您想探索这两个领域,请随意浏览:

  1. 人脸检测:在这篇文章中,我谈到了一个基于人脸检测的应用
  2. 人脸识别:这篇文章讲述了我们如何使用人脸识别来实现一个安全机制。

在上面的文章中,我已经尝试对这些机制是如何工作的给出了一个完整的解释。

在本文中,我们将讨论基于面部的深度学习的另外两个最重要的应用,情感检测或面部表情检测,以及从面部图像预测年龄和性别。

所以,让我们直接开始吧。

情感检测

首先,让我们谈谈情绪检测或预测。

对于这一部分,我们将使用 Kaggle 的 CKPlus 数据集

数据预处理

该数据集总共有 981 幅图像。这些图像根据七种不同的表情被分为七个标签:愤怒、轻蔑、厌恶、恐惧、快乐、悲伤和惊讶。每个表达式都有一个文件夹。因此,有七个文件夹存储 981 幅图像。

首先,我们使用 listdir()按顺序列出类或文件夹。

**import** **os**
files=os.listdir(fldr)
>>
['fear', 'contempt', 'happy', 'anger', 'surprise', 'disgust', 'sadness']Exp=['fear', 'contempt', 'happy', 'anger', 'surprise', 'disgust', 'sadness']

因此,我们将表达式按顺序保存在一个列表中,我们将参考该列表来创建标签。

接下来,我们对图像进行预处理。

**import** **cv2**
**from** **google.colab.patches** **import** cv2_imshow
i=0
last=[]
images=[]
labels=[]
**for** fle **in** files:
  idx=Exp.index(fle)
  label=idx

  total=fldr+'/'+fle
  files_exp= os.listdir(total) **for** fle_2 **in** files_exp:
    file_main=total+'/'+fle_2
    print(file_main+"   "+str(label))
    image= cv2.imread(file_main) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    image= cv2.resize(image,(48,48))
    images.append(image)
    labels.append(label)
    i+=1
  last.append(i)

上面的代码片段使用 OpenCV 打开并读取图像,将其尺寸调整为(48 x 48)尺寸。我已经把它转换成 RGB 图像,所以,它有三个通道。每个图像的大小为(48 x 48 x 3)。我们将在“图像”列表中添加图像,并在“标签”列表中添加相应的标签。让我们来可视化几个预处理后的例子。

**import** **tensorflow** **as** **tf**
**from** **sklearn.model_selection** **import** train_test_split
**import** **numpy** **as** **np**
images_f=np.array(images)
labels_f=np.array(labels)images_f_2=images_f/255
labels_encoded=tf.keras.utils.to_categorical(labels_f,num_classes=num_of_classes)
X_train, X_test, Y_train, Y_test= train_test_split(images_f_2, labels_encoded,test_size=0.25)

使用上面的代码片段,我们将标签和图像转换为 NumPy 数组,并通过除以 255 来规范化图像数组。我使用了一键编码将标签编码成向量。我们将使用 25%的测试分割。

型号

**from** **tensorflow.keras.layers** **import** Dropout
**from** **tensorflow.keras.layers** **import** Flatten,BatchNormalization
**from** **tensorflow.keras.layers** **import** Dense, MaxPooling2D,Conv2D
**from** **tensorflow.keras.layers** **import** Input,Activation,Add
**from** **tensorflow.keras.models** **import** Model
**from** **tensorflow.keras.regularizers** **import** l2
**from** **tensorflow.keras.optimizers** **import** Adam**def** Convolution(input_tensor,filters):

    x = Conv2D(filters=filters,kernel_size=(3, 3),padding = 'same',strides=(1, 1),kernel_regularizer=l2(0.001))(input_tensor)
    x = Dropout(0.1)(x)
    x= Activation('relu')(x) **return** x
**def** model(input_shape):
  inputs = Input((input_shape))

  conv_1= Convolution(inputs,32)
  maxp_1 = MaxPooling2D(pool_size = (2,2)) (conv_1)
  conv_2 = Convolution(maxp_1,64)
  maxp_2 = MaxPooling2D(pool_size = (2, 2)) (conv_2)
  conv_3 = Convolution(maxp_2,128)
  maxp_3 = MaxPooling2D(pool_size = (2, 2)) (conv_3)
  conv_4 = Convolution(maxp_3,256)
  maxp_4 = MaxPooling2D(pool_size = (2, 2)) (conv_4)
  flatten= Flatten() (maxp_4)
  dense_1= Dense(128,activation='relu')(flatten)
  drop_1=Dropout(0.2)(dense_1)
  output= Dense(7,activation="sigmoid")(drop_1) model = Model(inputs=[inputs], outputs=[output]) model.compile(loss="categorical_crossentropy", optimizer="Adam",
	metrics=["accuracy"])
  **return** model

我们将使用上述模型来预测表达式。

History=Model.fit(X_train,Y_train,batch_size=32,validation_data=(X_test,Y_test),epochs=1000,callbacks=[callback_list])

上面的片段将训练模型。

该模型对测试数据给出了 100%的准确度。

注意:每当一个模型在测试数据上给出 100%的准确率时,我们需要检查训练准确率,如果那也是 100%的话。这意味着模型实际上是过度拟合的,测试集与训练集的分布非常接*。因此,它显示了巨大的成果。我认为在这种情况下,最好使用交叉验证来获得模型实际工作方式的正确直觉。

让我们继续评估。

评价

两条曲线显示了模型的学习。第一条曲线显示了损失函数的下降,第二条曲线显示了精度随时期的增长。

Pred=Model.predict(X_test)
Pred
>>
array([[1.68134073e-09, 5.25928086e-11, 5.46700324e-11, ...,         7.71565616e-01, 8.71616357e-05, 4.54742303e-06],        [5.06911943e-11, 5.20724059e-17, 2.85400745e-07, ...,         2.65912314e-12, 7.78120279e-01, 2.07833662e-14],        [5.95332267e-07, 7.41830490e-07, 1.73864496e-08, ...,         4.54492539e-01, 9.06203127e-07, 1.08237209e-05],        ...,        [1.56573861e-07, 3.44979071e-07, 3.86641860e-01, ...,         3.84031367e-08, 4.99448021e-08, 6.93729362e-13],        [1.91495033e-07, 7.53485918e-01, 1.24115175e-07, ...,         2.53645931e-06, 6.98523905e-09, 2.22882386e-06],        [5.07813091e-14, 1.79454021e-12, 1.35435105e-14, ...,         9.94049311e-01, 2.74002265e-09, 1.31444740e-08]], dtype=float32)

我们获得如图所示的预测,让我们检查分类报告和混淆矩阵。

分类报告:

i=0 Y_test_l=[] 
Pred_l=[] 
**while**(i<len(Pred)):   
  Y_test_l.append(int(np.argmax(Y_test[i])))     
  Pred_l.append(int(np.argmax(Pred[i])))   
  i+=1report=classification_report(Y_test_l, Pred_l)

混淆矩阵:

我们已经看到了我们模型的混淆矩阵和分类报告。

**def** test_image(ind,images_f,images_f_2,Model):
  cv2_imshow(images_f[ind])
  image_test=images_f_2[ind]
  print("Label actual:  " + Exp[labels[ind]]  )
  pred_1=Model.predict(np.array([image_test]))
  *#print(pred_1)*
  pred_class=Exp[int(np.argmax(pred_1))]
  print("Predicted Label: "+ pred_class)

上面的片段将让我们看看一些图像、它们的真实标签和预测标签。

所以,我们已经看到了如何使用深度学习来预测情绪。让我们来看看年龄和性别预测。

年龄和性别预测

我们将使用 Kaggle 的 UTKFace 数据集来预测年龄和性别。

数据预处理

这里我使用了包含 9780 个文件的数据集。它有 9780 张年龄从 0 岁到 116 岁的男性和女性的人脸图片。每张图片都有标签显示相应的年龄和性别。男性由 0 给出,女性由 1 给出。

**import** **cv2**
ages=[]
genders=[]
images=[]**for** fle **in** files:
  age=int(fle.split('_')[0])
  gender=int(fle.split('_')[1])
  total=fldr+'/'+fle
  print(total)
  image=cv2.imread(total) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
  image= cv2.resize(image,(48,48))
  images.append(image)
  ages.append(age)
  genders.append(gender)

上面的代码片段有助于获取数据和准备训练集。“图像”列表包含所有 9780 幅图像,每幅图像的大小为(48 x 48 x 3)。“年龄”列表具有相应的年龄,“性别”列表具有相应的性别。

让我们看看预处理后的图像。

第一幅图像的年龄为 62 岁,性别为 0,第二幅图像的年龄为 67 岁,性别为 0

现在,我们需要检查我们的集合的分布。

第一个条形图显示了性别分布。它看起来很*衡。第二个线形图显示了不同年龄样本的变化。我们可以看到年龄小于 40 的样本比年龄大于 40 的样本数量要多得多。这造成了训练集分布的偏斜。

我们已经看到,在这种情况下,我们实际上需要使用相同的模型来预测年龄和性别。因此,要为我们的训练集创建实际的标签,我们需要做一些处理。

labels=[]i=0
**while** i<len(ages):
  label=[]
  label.append([ages[i]])
  label.append([genders[i]])
  labels.append(label)
  i+=1

上面的代码片段按索引方式获取每个图像样本的年龄和性别,并将每个样本转换成一个列表,并将它们附加到标签列表中。这样做是为了创建一维标签向量。

因此,“标签”列表的形状将是:

[[[年龄(1)],[性别(1)],

[[年龄(2)],[性别(2)],………………。[[年龄(n)],[性别(n)]]]

接下来,我们将标签和图像列表转换成 NumPy 数组,规范化图像,并创建训练和测试数据分割。我们将使用 25%的测试分割。

images_f=np.array(images)
labels_f=np.array(labels)
images_f_2=images_f/255
X_train, X_test, Y_train, Y_test= train_test_split(images_f_2, labels_f,test_size=0.25)

目前,我们的 Y_train 和 Y_test 的形式为:

Y_train[0:5]
>>array([[[36],
        [ 0]], [[50],
        [ 0]], [[65],
        [ 0]], [[ 3],
        [ 0]], [[25],
        [ 1]]])

我们需要对它们进行转换,使 Y_train[0]表示性别标签向量,Y_train1表示年龄标签向量。

Y_train_2=[Y_train[:,1],Y_train[:,0]]
Y_test_2=[Y_test[:,1],Y_test[:,0]]

这个简单的代码片段为我们做了工作。

Y_train_2[0][0:5]
>>array([[0],
       [0],
       [0],
       [0],
       [1]])
Y_train_2[1][0:5]
>>array([[36],
       [50],
       [65],
       [ 3],
       [25]])

现在,我们准备开始设计我们的模型。

型号

**from** **tensorflow.keras.layers** **import** Dropout
**from** **tensorflow.keras.layers** **import** Flatten,BatchNormalization
**from** **tensorflow.keras.layers** **import** Dense, MaxPooling2D,Conv2D
**from** **tensorflow.keras.layers** **import** Input,Activation,Add
**from** **tensorflow.keras.models** **import** Model
**from** **tensorflow.keras.regularizers** **import** l2
**from** **tensorflow.keras.optimizers** **import** Adam
**import** **tensorflow** **as** **tf****def** Convolution(input_tensor,filters):

    x = Conv2D(filters=filters,kernel_size=(3, 3),padding = 'same',strides=(1, 1),kernel_regularizer=l2(0.001))(input_tensor)
    x = Dropout(0.1)(x)
    x= Activation('relu')(x) **return** x
**def** model(input_shape):
  inputs = Input((input_shape))

  conv_1= Convolution(inputs,32)
  maxp_1 = MaxPooling2D(pool_size = (2,2)) (conv_1)
  conv_2 = Convolution(maxp_1,64)
  maxp_2 = MaxPooling2D(pool_size = (2, 2)) (conv_2)
  conv_3 = Convolution(maxp_2,128)
  maxp_3 = MaxPooling2D(pool_size = (2, 2)) (conv_3)
  conv_4 = Convolution(maxp_3,256)
  maxp_4 = MaxPooling2D(pool_size = (2, 2)) (conv_4)
  flatten= Flatten() (maxp_4)
  dense_1= Dense(64,activation='relu')(flatten)
  dense_2= Dense(64,activation='relu')(flatten)
  drop_1=Dropout(0.2)(dense_1)
  drop_2=Dropout(0.2)(dense_2)
  output_1= Dense(1,activation="sigmoid",name='sex_out')(drop_1)
  output_2= Dense(1,activation="relu",name='age_out')(drop_2)
  model = Model(inputs=[inputs], outputs=[output_1,output_2])
  model.compile(loss=["binary_crossentropy","mae"], optimizer="Adam",
	metrics=["accuracy"])

  **return** model

我们将使用上述模型来预测性别和年龄

以上是我们模型的示意图。在“展*”层之后,我们将使用两个不同的致密层和对应于相应输出的漏失。现在,性别预测是一个分类问题,而年龄预测是一个回归问题,所以,我们将使用 sigmoid 作为性别预测的输出激活,ReLU 作为年龄预测的激活函数。类似地,我们将使用“二元交叉熵”作为性别的损失函数,使用“*均绝对误差”作为年龄的损失函数。

**from** **tensorflow.keras.callbacks** **import** ModelCheckpoint **import** **tensorflow** **as** **tf** fle_s='Age_sex_detection.h5'
checkpointer = ModelCheckpoint(fle_s, monitor='val_loss',verbose=1,save_best_only=**True**,save_weights_only=**False**, mode='auto',save_freq='epoch')
Early_stop=tf.keras.callbacks.EarlyStopping(patience=75, monitor='val_loss',restore_best_weights=**True**),
callback_list=[checkpointer,Early_stop]
History=Model.fit(X_train,Y_train_2,batch_size=64,validation_data=(X_test,Y_test_2),epochs=500,callbacks=[callback_list])

上面的片段将训练模型。

该模型给出了 82%的性别分类准确率。

评价

让我们看看模型的损失曲线。

这是我们的模型生成的损失曲线。

让我们看看对年龄预测的评估:

上述曲线显示了黑色的模型跟踪线性回归线,蓝点显示了测试样品的分布。所以,我们可以看到我们的预测线几乎穿过了分布的中间。在 80 岁以上,样本很少,所以,可能由于这个原因,我们的模型表现得不是很好。

性别预测评估:

上面的曲线显示了性别准确性随时代的增加。

性别分类的分类矩阵:

我们的模型获得了女性 0.84 和男性 0.78 的 F1 分数。所以,它对女性的分类比男性好。

让我们来看看我们集合中的一些样本及其相应的预测年龄和性别。

**def** test_image(ind,images_f,images_f_2,Model):       cv2_imshow(images_f[ind])   
image_test=images_f_2[ind]   pred_1=Model.predict(np.array([image_test]))  
*#print(pred_1)*   
sex_f=['Male','Female']   
age=int(np.round(pred_1[1][0]))   
sex=int(np.round(pred_1[0][0]))   
print("Predicted Age: "+ str(age))   
print("Predicted Sex: "+ sex_f[sex])

上面的代码片段有助于生成我们的示例:

对于最后一个样本,实际年龄标签是 62,预测年龄标签是 60。

因此,我们可以使用面部数据来预测性别和年龄。

结论

在本文中,我们已经看到了如何从面部图像中预测情感、性别和性。

GitHub 链接在这里是。

希望这篇文章有所帮助。

使用连体网的面部再识别

原文:https://towardsdatascience.com/facial-re-identification-using-siamese-nets-d36df39da7c0?source=collection_archive---------20-----------------------

端到端教程

面部再识别(FRID)是根据一个人的面部来验证其身份的问题。例如,一个政府机构可以根除 ID 卡的使用,而简单地使用 FRID 系统来处理出席,而不用担心陌生人窃取某人的 ID 来进入系统。

这个问题的关键是一个分类问题,其中模型必须将人脸图像分类为数据库中的人。正因为如此,使用具有接* 100%测试准确率的许多先进的图像分类器可能很有诱惑力。结案了对吗?只需微调 ResNet50 甚至 ResNet101 模型,即可从人脸图像中对人名进行分类。这样做时会出现一些基本问题:

  • 我从哪里获得数据?对于您想要分类的每个人,最多会有一两张图像可用,并且该图像将是护照风格的照片,与正在分类的图像非常不同。图像分类器仅在至少有 50 幅图像时工作良好,以在测试图像上实现高置信度,这比可用图像多 49 幅图像。
  • 我如何确保对成千上万的课程有很高的信心?用于图像分类的最大数据集有 300 到 1000 个类别。然而,公司组织有 100 到 50,000 人,因此有 100 到 50,000 个班级。
  • 当新员工被录用时,我该怎么做?深度学习网络的本质是,没有办法只是向模型中添加一个新类,然后让它做得很好。添加一个新的类意味着用添加的类重新训练整个网络。这既浪费了计算资源又浪费了时间,任何人都不会有多余的计算资源和时间,尤其是数据科学家。

所有这些问题都可以用一种新的模型来回答:连体网络。

直觉

让我们首先介绍暹罗网络。当人们将人类直觉应用到深度学习模型中时,大多数深度学习进步都发生了,例如当 ResNet 中首次使用残差块时,或者当人们更加努力地尝试将人类抽象融入计算机时,基于风格的损失变得更加流行时。暹罗网络是这些进步中的另一个,它严重依赖于人类对计算机应该如何解决问题的直觉。

暹罗网络背后的核心直觉是试图学习面部的表征。这种表征类似于人类储存在大脑中的关于面部特征的信息,如面部特征的大小、肤色、眼睛颜色等。人类可以理解,如果它看到另一张具有相似特征的脸,那么新的脸很有可能属于同一个人。另一方面,如果人类看到新的面部与其先前看到的面部不匹配,那么人类再次制作新面部的表示以存储在其存储器中。

这正是暹罗网络的运作方式。一个函数将人脸的输入图像转换成包含人脸特征表示的向量。然后,我们希望这个向量与同一张脸的向量相似,而与另一张脸的向量非常不同。

简而言之,该模型学习如何提取人脸的重要特征,从而将人脸与其他人脸区分开来。一旦获得特征映射,就可以将其与数据库中要匹配的其他人脸的特征映射进行比较。

图片由(签名验证使用“暹罗”时间延迟神经网络)提供

三重态损失和其他细节

任何神经网络最重要的部分是它是如何训练的。训练是一个庞大的、看似无用的功能被调整以完成其任务的方式。暹罗网络最初是成对训练的,类似于模型的用例。同一人脸的两个向量之间的距离最大化,不同人脸的两个向量之间的距离最小化。

然而,这种方法使训练过程变得复杂,并且在计算要求方面也是低效的。训练这种所谓的对比损失意味着,对于每个训练样本,模型必须计算四个向量,然后对每对图像执行两组模型优化。出现的另一个问题是,训练样本将是高度不*衡的,因为其中人脸相同的对的数量将会少得多,而其中人脸不同的对的数量将会更多。

为了降低对比损失的计算要求,也为了部分解决数据问题,创建了三元组损失。三重态损失分四步进行:

  1. 从数据集中采样三个图像,锚、正面和反面。主播是任何一张脸,正面是和主播同一张脸的图像,反面是不同脸的图像。
  2. 计算每个图像的向量
  3. 使用一个距离函数来找出锚点和正负图像之间的距离。
  4. 将损失值计算为锚点和负片图像之间的距离与锚点和正片图像之间的距离之差。

以下等式显示了三重态损耗的数学表示,以及一些重要的微妙之处。

上述损失和等式之间的第一个差异是在差异和0.0之间添加了Max()函数。这是为了确保损失函数不会降到零以下。

第二个更重要的区别是增加了一个边距,用m表示。这个余量确保模型不会学习为所有的面输出相同的向量,不管这些面是否匹配。请注意,如果锚和正值之间的距离等于锚和负值之间的距离,如果没有保证金项,损失将最小化为零。

那么这怎么解决问题呢?

  • 该模型只需要每个身份的最多两张脸来训练它,这与现实世界中可用的数据类型非常相似,因为一个人必须至少有一张被识别的人的图像和一张该人的实时图像。
  • 由于该模型不依赖于从人脸中分类不同的身份,所以它不必处理可能的成千上万的人脸来分类,它只需要执行精确的比较。
  • 出于同样的原因,新添加的雇员并不意味着网络的重新训练,该模型将简单地计算新雇员的面部嵌入,以添加到面部嵌入的数据库中。

履行

对于这篇博文中的实现,我们将使用tensorflow==2.1和 gpu(如果有的话),因为这样一个网络的训练是一个繁重的计算。我将在英伟达 GTX 1080 TI 上训练我的模型,所以我将使用tensorflow-gpu==2.1CUDA==10.2

由于强大的特征提取器网络的发展,对于几乎每种情况,通常很少需要从零开始设计定制的卷积神经网络。我们将使用 ResNet50 模型的行业标准来提取我们的特征。因此,唯一需要增加的是在 tf 中设计一个定制的损失函数。Keras API 来训练我们的模型。

有两种不同的方法将自定义损失函数合并到 tf 中。Keras:创建一个函数来计算传递给model.compile()方法的损失,或者创建一个损失层并使用Layer.add_loss()方法。

创建自定义损失函数的两种方法之间的唯一区别是,在第一种方法中,损失函数必须是loss_fn(y_true, y_pred)的格式,而第二种方法可以是任何格式。

由于三重态损耗无法用y_true, y_pred格式表示,因此将使用第二种方法。

在上面的代码中,triplet_loss是损失函数,它接受锚、正面和负面图像。@tf.function的注释简单地使用tf.Autograph来绘制函数,并允许更快的计算。

TripletLoss层继承自tf.keras.layers.Layer,使用add_loss方法将三重损失函数添加到该层的损失中。然后,图层返回输入而不更改它们。

使用add_loss方法不仅将损失张量添加到层的损失中,而且当使用model.fit()训练模型时,所有的层损失也被自动优化,这允许我们在以下代码中编译没有任何整体损失函数的模型:

上面的代码显示了模型的完整代码以及它是如何被训练的。

结果

在位于 http://vis-www.cs.umass.edu/lfw/的LFW(野外标记的人脸)数据库上训练该模型,该模型能够以 90%的准确率正确“预测”匹配的人脸,并能够以 95%的准确率区分两张人脸是否不同。

在过去的几年里,已经发表了多篇论文,对普通的三重损失进行了重大改进,并在更困难的数据集上进行了改进,如 https://megapixels.cc/duke_mtmc/的杜克 MTMC。

在接下来的几篇文章中,我将分析最*在重新识别方面的进展。

全球营销中的面部识别

原文:https://towardsdatascience.com/facial-recognition-in-global-marketing-8d0ca0b313c7?source=collection_archive---------32-----------------------

品牌应该使用面部识别吗?

马文·迈耶在 Unsplash 上的照片

面部识别的好处

面部是交流情感最有力的渠道之一。我们的日常情绪描述了我们对事件、品牌和产品的记忆程度。对于希望利用面部识别进行营销的企业或组织来说,有许多好处。面部识别使市场研究人员能够大规模廉价地分析面部表情。使用传统的分析手段,如焦点小组和当代神经科学技术,人类可能会有偏见或不愿意分享他们的真实意见。面部识别以一种不引人注目的方式捕捉参与者不带偏见和未经过滤的情绪反应。

通过对各种情绪维度(效价、注意力、表现力/强度)的研究和对各种谨慎情绪(享受、专注、惊讶、不喜欢和怀疑/怀疑)的研究,品牌可以更好地了解他们的消费者,建立更强的情感联系。

例如,在视频广告中利用面部识别软件,广告商能够“选择最佳动画,优化场景和故事情节,创建剪辑,评估磨损效果,确定媒体支出,并对市场内表现进行预测分析”(Cateroa,Gilly,Graham and Money)。品牌能够 A/B 测试它们的内容,以及与它们的产品类别或等级中的品牌进行比较。

通过分析面部识别数据,品牌或组织可以通过唤起某些情绪来改善与消费者的联系,这些情绪可以增加分享行为、品牌忠诚度并增加购买决策。面部识别技术可以为品牌或组织提供有价值的数据,以做出明智的营销和商业决策。

面部识别正在使用

面部识别软件的先驱之一 Snapchat 允许营销人员在其营销策略中利用面部识别。Snapchat 允许品牌和组织创建符合用户脸型的过滤器。塔可钟和佳得乐是使用 Snapchat 面部识别软件进行营销的几个品牌。该品牌可以看到有多少人使用了该过滤器,该过滤器被共享了多少次,甚至可以向上滑动或查看特定的登录页面。

媒体公司也在使用面部识别来测试电影预告片、电视试播节目中的角色以及电视促销的最佳位置。脸书目前使用面部识别软件自动标记人们的照片。苹果在其产品中使用面部识别软件,因此用户可以轻松解锁设备,登录应用程序和网站,甚至进行购物。Expedia 创建了一个微型网站,为夏威夷的游客提供各种各样的活动:“该网站定制的面部识别软件能够确定哪些镜头对用户产生了最积极的反应,并相应地提供打折的度假套餐”(Yap-McNamara)。这些例子显示了品牌和组织如何从利用面部识别软件进行营销中受益。

对文化敏感

由于不同的文化展示规则,营销人员在全球营销中必须小心面部表情和肢体语言。文化展示规则可以被定义为在生活早期学到的文化规范,它根据社会背景来管理表达行为的规则(Matsumoto & Hwang)。

在很小的时候,人类就学会了根据社会环境和文化教养来改变他们的表达方式。中国和印度这样的集体主义文化更容易减少和掩盖自己的情绪,而美国这样的个人主义文化更容易放大自己的情绪。

由于各种差异,在进入外国市场之前,全球营销人员必须研究和理解特定文化的面部表情和肢体语言。对一个国家文化的曲解可能对一个品牌或组织有害。

隐私和安全

人脸识别软件侵犯隐私。安全性是另一个主要问题。计算机和人类将会监视其他人。在一些文化中,这可能是禁忌;而对于其他文化来说,这是可以接受的。

美国人不喜欢自己被监视的想法。当面部识别技术用于营销时,面部识别软件的反对者认为,人们正在被企业或组织操纵和利用。此外,面部识别技术对那些图像被存储并用于营销的人构成了风险。他们的数据可以在未经许可的情况下被黑客窃取和使用。

另一方面,一些人可能会认为他们认可面部识别技术。一些人喜欢个性化的营销内容,并发现这些内容更符合他们的口味。隐私和安全将是面部识别技术影响的两个主要问题。想要利用面部识别技术的营销人员将需要研究和了解他们试图进入的外国市场是批准还是不批准这种技术。

结论

在营销和商业中利用面部识别有很多好处。然而,了解目标市场的文化和传统是最重要的。营销人员需要调整他们的营销策略来迎合当地人。

如果面部识别在文化上被接受,对一个品牌来说会有很大的好处。如果面部识别在文化上不被接受,营销人员应该寻找其他方法来接触他们的客户。

作为一名全球营销人员,应该开发和执行迎合国外市场的营销策略。全球营销人员永远不应该采取一刀切的方法,因为面部表情和肢体语言可能包含完全不同的含义。

资源:

Cateora,P. R .,Gilly,M. C .,Graham,J. L .,& Money,R. B. (2016 年)。国际营销。纽约州纽约市:麦格劳希尔教育公司。

Matsumoto d .,& Hwang h .(2013 年)。文化展示规则。威利在线图书馆。检索自https://online library . Wiley . com/doi/full/10.1002/9781118339893 . wbe CP 126

Yap-McNamara,J. (2018 年)。为什么品牌应该使用面部识别。 AdWeek 。检索自https://www . adweek . com/digital/why-brands-should-be-use-face-recognition/

使用深度学习+ ReactJS 的面部识别登录系统

原文:https://towardsdatascience.com/facial-recognition-login-system-using-deep-learning-reactjs-61bff981eb74?source=collection_archive---------14-----------------------

深度学习|反应

构建一个面部识别应用程序,可以作为登录阶段集成到任何系统中!

安德烈·萨金塞夫Unsplash 上拍照

你一定在应用程序或网站中见过面部识别登录系统。如果您是应用程序开发人员或网站开发人员,您可能希望在您的系统中添加面部识别作为登录阶段。在这里,我们将从头开始构建一个非常容易适应的登录系统,您可以将其集成到任何应用程序或系统中进行登录。

我们将分两步建立这个系统。这些步骤包括创建一个包含我们深度学习模型的 Flask 服务器,并创建一个用于登录的 ReactJS 应用程序。ReactJS 应用程序可以在 Flask 服务器的帮助下与我们的深度学习模型进行通信。它可以发送人的图像,并且模型可以返回图像中人的真实身份。一旦我们开始编码,这些都将变得清晰。让我们进入编码部分,创建我们的登录系统。看看下图,消除对我们将要建立的系统的任何疑虑。

系统的简单流程

创建深度学习模型

面部识别面部验证是两回事。面部识别涉及通过检测面部来识别图像中的人,而面部验证确定给定的两幅图像是否是同一个人。在这里,为了构建我们的登录系统,我们将需要一个模型,该模型可以从图像中检测人脸,并将面部细节转换为 128 维向量,我们稍后可以使用该向量进行面部识别或验证。

我们可以使用由Hiroki tanai提供的 FaceNet 模型,这样我们就不必从头构建一个模型,也不必担心超参数。这个 FaceNet 模型已经在 MS-Celeb-1M 数据集上被训练,并且期望大小为 160x160 像素的彩色图像。模型可以从这里下载: Keras FaceNet 预训练模型

首先,让我们为包含深度学习模型的 Flask 服务器导入重要模块。

# Import all the necessary files!
import os
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras import Model
from tensorflow.python.keras.backend import set_session
from flask import Flask, request
from flask_cors import CORS
import cv2
import json
import numpy as np
import base64
from datetime import datetime

我们的 API 工作的一些重要步骤。你可以在这里了解更多关于我们为什么在 Flask 中使用会话的信息。

graph = tf.get_default_graph()app = Flask(__name__)
CORS(app)sess = tf.Session()
set_session(sess)

最后,我们将加载我们的模型。

model = tf.keras.models.load_model('facenet_keras.h5')

让我们创建一个函数,将给定的图像转换成 128 维向量。这个函数将图像路径和我们的模型作为参数,并输出包含图像信息的向量。

def img_to_encoding(path, model):
  img1 = cv2.imread(path, 1)
  img = img1[...,::-1]
  dim = (160, 160)
  # resize image
  if(img.shape != (160, 160, 3)):
    img = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
  x_train = np.array([img])
  embedding = model.predict(x_train)
  return embedding

让我们创建一个存储人们身份的示例数据库。如果你愿意,你可以预先存储一些身份。您可以将一个人的图像作为参数提供给 img_to_encoding 方法以及模型,您将获得 128 维的向量,您可以将该向量作为一个值存储到数据库字典中,其中人的名字是关键字。

database = {}
database["Klaus"] = img_to_encoding("images/klaus.jpg", model)
database["Levi"] = img_to_encoding("images/captain_levi.jpg", model)
database["Eren"] = img_to_encoding("images/eren.jpg", model)
database["Armin"] = img_to_encoding("images/armin.jpg", model)

让我们创建一个函数,使用数据库返回图像中人的身份。它将如上所示为数据库中的所有条目和新图像计算距离,并找到最小距离。如果最小距离大于阈值,它将显示此人未注册,否则它将返回具有最小距离的身份。

def who_is_it(image_path, database, model):
    encoding = img_to_encoding(image_path, model)
    min_dist = 1000
    #Looping over the names and encodings in the database.
    for (name, db_enc) in database.items():
        dist = np.linalg.norm(encoding-db_enc)
        if dist < min_dist:
            min_dist = dist
            identity = name
    if min_dist > 5:
        print("Not in the database.")
    else:
        print ("it's " + str(identity) + ", the distance is " + str(min_dist))
    return min_dist, identity

最后,我们希望我们的 Flask 服务器完成两项任务:1)如果用户没有注册,就在数据库字典中注册用户 2)从图像中识别用户的身份。我们将为我们的 API 创建路由。首先,我们将创建一个从图像中识别用户并返回身份的路由。此路由将从 React 应用程序接收用户一次捕获的图像的 base64 数据,如果用户已注册,它将返回用户的身份,或者它将发送用户未注册的提示,以便我们的 React 应用程序知道是否登录。注:如果你想知道使用 TensorFlow 会话背后的原因,请前往 此处

app.route('/verify', methods=['POST'])
def verify():
    img_data = request.get_json()['image64']
    img_name = str(int(datetime.timestamp(datetime.now())))
    with open('images/'+img_name+'.jpg', "wb") as fh:
        fh.write(base64.b64decode(img_data[22:]))
    path = 'images/'+img_name+'.jpg'
    global sess
    global graph
    with graph.as_default():
        set_session(sess)
        min_dist, identity = who_is_it(path, database, model)
    os.remove(path)
    if min_dist > 5:
        return json.dumps({"identity": 0})
    return json.dumps({"identity": str(identity)})

上面我们为我们的目的创建了一个临时图像文件,在检查了用户的身份后,我们删除了它,因为它对我们没有用。我们在时间戳的帮助下命名这个文件。

是时候创建我们的第二条路线了,这条路线将把新人注册到数据库中。它将从 React 应用程序接收用户名和用户图像的 base64 数据。它将计算图像的 128 维向量,并将其存储到数据库字典中。如果注册成功,它将发送状态码 200,否则它将发送 500 状态码(内部错误)。

@app.route('/register', methods=['POST'])
def register():
    try:
        username = request.get_json()['username']
        img_data = request.get_json()['image64']
        with open('images/'+username+'.jpg', "wb") as fh:
            fh.write(base64.b64decode(img_data[22:]))
        path = 'images/'+username+'.jpg'global sess
        global graph
        with graph.as_default():
            set_session(sess)
            database[username] = img_to_encoding(path, model)    
        return json.dumps({"status": 200})
    except:
        return json.dumps({"status": 500})

这就是系统的深度学习部分。有可能你仍然不清楚这些将如何适应我们正在建立的系统。让我们来看看创建完我们的 Flask 服务器后系统的流程。

正在创建 ReactJS 应用程序

应用程序的前端编码不属于本项目的范围。这里不讨论前端的细节,但是您可以从项目链接下载完整的代码。主页将如下所示:

模板由 Colorlib

我们将讨论将在我们的应用程序中使用的两个重要的 React 组件— (用于登录)和(用于注册)。

app.js 文件(包含组件)将包含以下代码。

import React, {Component} from 'react';
import './App.css';
import './css/main.css';
import './css/util.css';
import {Signup} from './signup.js';
import {Verify} from './verify.js';
export class App extends Component {
 constructor(props){
  super(props);
  this.state = {
   signup : false,
   verify : false
  };
  this.backhome = this.backhome.bind(this);
 }
 backhome(){
  this.setState({
   signup: false,
   verify: false
  })
 }
 signup(){
  this.setState({
   signup: true,
   verify: false
  })
 }
 verify(){
  this.setState({
   signup: false,
   verify: true
  })
 }
 render(){
  let home = (
    <div>
     <div className="limiter">
      <div className="container-login100">
       <div className="wrap-login100 p-l-110 p-r-110 p-t-62 p-b-33">
        <form className="login100-form validate-form flex-sb flex-w">
         <span className="login100-form-title p-b-53">
          Sign In Or Up :)
         </span>
         <div className="container-login100-form-btn m-t-17">
          <button onClick={this.verify.bind(this)} className="login100-form-btn">
           Sign In 
          </button>
         </div>
         <div className="container-login100-form-btn m-t-17">
          <button onClick={this.signup.bind(this)} className="login100-form-btn">
           Sign Up
          </button>
         </div>
         <div className="w-full text-center p-t-55">
          <span className="txt2">
          </span>
          <a href="#" className="txt2 bo1">
          </a>
         </div>
        </form>
       </div>
      </div>
     </div>
     <div id="dropDownSelect1"></div></div>)return (
      <div>
      {!this.state.signup && !this.state.verify ? home : ''}
      {this.state.signup ? <Signup backhome={this.backhome}/> : ''}
      {this.state.verify? <Verify backhome={this.backhome}/> : ''}
      </div>
  )
 }
}
export default App;

一些方法控制下一步呈现哪个组件。例如, this.signup 方法将更改状态值,以便呈现< Signup/ >组件。类似地, this.verify 方法将导致应用程序呈现< Verify/ >组件。 this.backhome 方法用于返回主页面。代码的其余部分不言自明。

让我们深入研究第一个组件(用于登录)。下面是 Verify.js 文件的代码。

import React, {Component} from 'react';
import './css/main.css';
import './css/util.css';
import './verify.css';
import Sketch from "react-p5";
const axios = require('axios');
let video;
export class Verify extends Component {
constructor(props){
  super(props);
  this.state = {
   verify : false,
   idenity: ' '
  };
 }setup(p5='', canvasParentRef='') {
        p5.noCanvas();
        video = p5.createCapture(p5.VIDEO);        
    }//to shut off the camera
stop(){
     const tracks = document.querySelector("video").srcObject.getTracks();
     tracks.forEach(function(track) {
        track.stop();
     });
    }logout(){
     this.stop();
     this.props.backhome();
    }setup2(){
     const button = document.getElementById('submit');
        button.addEventListener('click', async event => {
          video.loadPixels();
          console.log(video.canvas);
          const image64 = video.canvas.toDataURL();
          const data = { image64 };
          const options = {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify(data)
          };
          const response = await axios.post('[http://localhost:5000/verify'](http://localhost:5000/verify'), {'image64':image64});
          console.log(response.data.identity);
          if(response.data.identity){
           this.stop();
         this.setState({
          verify:true,
          idenity: response.data.identity
         })
          } else {
           this.stop();
           alert("Not a registered user!")
           this.props.backhome();
          }
        });
    }render(){let verify = (<div>
     <div className="limiter">
      <div className="container-login100">
       <div className="wrap-login100 p-l-110 p-r-110 p-t-62 p-b-33">

         <span className="login100-form-title p-b-53">
          Sign In With
         </span>
         <input/>
         <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
         <Sketch setup={this.setup} draw={this.draw}/>
         <div className="container-login100-form-btn m-t-17">
         <button id="submit" onClick={this.setup2.bind(this)} className="login100-form-btn">
           Sign In
         </button>
         </div>
         <div className="container-login100-form-btn m-t-17">
         <button onClick={this.logout.bind(this)} className="login100-form-btn">
           Back!
         </button>
        </div>
       </div>
      </div>
     </div>
   <div id="dropDownSelect1"></div></div>
  )return (<div >
      {this.state.verify? <div><h1>Welcome, {this.state.idenity}.</h1>
       <button onClick={this.props.backhome} className="container-login100-form-btn">Logout!</button>
       </div> : verify }
      </div>)
 }
}
export default Verify;

为了捕捉用户的图像,我们将使用 p5.js 库。您可以在这里了解如何使用它或者您可以直接复制代码并运行它,因为没有必要为了这个特定的应用程序而学习整个库。从我们的服务器得到响应后,我们将关闭相机,并相应地渲染下一个组件。

下面是组件的第一个输出。

未经注册

我们得到了一个错误,因为我们首先需要注册我们的用户名和脸。为此,我们将创建如下所示的组件。

import React, {Component} from 'react';
import './css/main.css';
import './css/util.css';
import './signup.css';
import Sketch from "react-p5";
const axios = require('axios');
let video;
export class Signup extends Component {
 constructor(props){
  super(props);
  this.state = {
   signup : true
  };
 }
 setup(p5, canvasParentRef) {
        p5.noCanvas();
        video = p5.createCapture(p5.VIDEO);
        const v = document.querySelector("video");
        let st = "position: absolute; top: 255px;"
        v.setAttribute("style", st);
    }setup2(){
     const button = document.getElementById('submit');
        button.addEventListener('click', async event => {
          const mood = document.getElementById('mood').value;
          video.loadPixels();
          console.log(video.canvas);
          const image64 = video.canvas.toDataURL();
          const data = { mood, image64 };
          const options = {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify(data)
          };
          console.log(image64);
          const response = await axios.post('[http://localhost:5000/register'](http://localhost:5000/register'), {'image64':image64, 'username':mood});
          if(response.status==200){
      const tracks = document.querySelector("video").srcObject.getTracks();
      tracks.forEach(function(track) {
        track.stop();
      });
     };
           this.props.backhome();
          }
        );
    }
    logout(){
     const tracks = document.querySelector("video").srcObject.getTracks();
     tracks.forEach(function(track) {
        track.stop();
     });
     this.props.backhome();
    }render(){let signup = (
    <div>
     <div className="limiter">
      <div className="container-login100">
       <div className="wrap-login100 p-l-110 p-r-110 p-t-62 p-b-33">
         <span className="login100-form-title p-b-53">
          Sign Up With
         </span>
         <div className="p-t-31 p-b-9">
          <span className="txt1">
           Username
          </span>
         </div>
         <div className="wrap-input100 validate-input" data-validate = "Username is required">
          <input id="mood" className="input100" type="text" name="username" />
          <span className="focus-input100"></span>
         </div>
         <input/>
         <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
         <br/><br/><br/><br/>{this.state.signup?<Sketch id="s" setup={this.setup} draw={this.draw}/>:''}

         <div className="container-login100-form-btn m-t-17">
          <button id="submit" onClick={this.setup2.bind(this)} className="login100-form-btn">
           Sign Up
          </button>
         </div>
         <div className="container-login100-form-btn m-t-17">
          <button onClick={this.logout.bind(this)} className="login100-form-btn">
           Back!
          </button>
         </div>      
       </div>
      </div>
     </div>
     <div id="dropDownSelect1"></div>
    </div>
  )
     return (<div >
      { signup }
      </div>
  )
 }
}
export default Signup;

当我们点击主页上的“注册”按钮时,摄像机将启动,用户将输入姓名,然后点击那里的“注册”按钮。该组件负责获取我们的用户名和图像,并将它们发送到我们之前创建的 Flask 服务器的'/register '路径。服务器会将我们的图像编码成 128 维向量,并将其存储在数据库字典中,以我们的用户名作为关键字,向量作为值。一旦我们的 React 应用程序获得状态 200,它将再次呈现主页,这表明用户已经成功注册。

下面是上面代码的输出。

报名

现在,注册后,我们应该能够登录没有任何失败。让我们再次尝试登录。

注册后成功登录

在登录阶段之后,可能会出现你想要的任何页面或网站。对于这篇文章,我一直保持简单。成功登录后,应用程序将简单地提示用户一条欢迎消息。

你可以从 GitHub 获得上面显示的所有代码。你也可以在 LinkedIn 上找到我。

结论

我们看到了如何集成深度学习和 ReactJS 来构建一个简单的面部识别登录应用程序。这个应用程序应该是你想要的任何应用程序或网站的登录阶段。成功登录后,您可以自定义下一阶段。

我们使用深度学习来为我们的应用程序进行人脸识别和验证,但我们必须经历加载模型和管理图像的过程。我们也可以使用预编程库。JavaScript 的节点包管理器(npm)中有一个叫做 face-api.js 的模块,是在 TensorFlow 上面实现的。你可以在这里查看这个库。

照片由阿曼达·达尔比约恩Unsplash 上拍摄

总之,面部识别领域发展非常迅速,这篇文章展示了一种非常简单的方法,与像脸书这样的公司在行业中使用的方法相比。高度先进的面部识别系统可以通过观察面部来检测人的情绪,或者检测性别,甚至估计人的年龄。

面部识别:让人可以信任的 AI!

原文:https://towardsdatascience.com/facial-recognition-too-biased-or-not-too-biased-ai-that-people-can-trust-5be1fdc24c77?source=collection_archive---------82-----------------------

优先考虑性别、种族和身份*衡的人脸验证数据。

人工智能中的偏倚问题:标记人脸和基准数据集

我们的报纸— FR:太偏向,还是不太偏向? —作为与 2020 年计算机视觉和模式识别会议 (CVPR)同时举行的公*、数据高效和可信计算机视觉研讨会的一部分发布。

这个简短教程的目的是向读者提供以下内容:

  1. 高层对论文的理解 —回答那又怎样?谁在乎呢。
  2. 通过分享我在主观问题上的观点来增加教程的趣味——当然,这并没有包括在我们发表的论文中。
  3. 提供一站式资源。作为这项工作的一部分,我们不仅提供论文,还以易于使用的结构和源代码(主要是 Python)提供数据。作为代码库的一部分,有几个笔记本举例说明了这项工作的各个方面(例如,论文中的每个图都有一个笔记本,提供了一种快速复制的方法)。

(3)的几个组成部分被列在写博客的待办事项清单上。换句话说,在接下来的几个星期里,预计教程将会被非常详细地分享(也就是说,通常比实际的论文更详细),而且大部分是作为独立的博客。完成后,每个链接将在此处列出。

目录

  1. 论文摘要
  2. AI 中的偏见为何是福:半空;半满?
  3. 观看论文展示(2020 年 CVPR)
  4. 相关参考文献

论文摘要

在论文中,我们提出了一个针对 FR 中偏倚问题的解决方案(即人脸验证,一对一设置)。然而,由于缺乏标记数据,我们建立并发布了野外(BFW)*衡人脸数据集——一个在身份,种族和性别方面*衡的人脸验证基准。我们探索 BFW 揭示偏见的证据,并通过应用基本信号检测理论的概念获得洞察力。最后,我们对数据进行了基准测试,确定了少数民族人口统计数据(例如,亚洲女性和印度男性)的表现确实存在偏差,而大多数人(例如,白人男性和白人女性)的表现存在明显的百分比差异。为了减轻不*衡性能,我们提出了一个滑动阈值,证明能够完全消除偏斜(即,从与预期 FPR 的百分之几的差异下降到 0%)。我们还包括一个实验,该实验显示了人类中的相同类型的偏差(即,我们评估了人类并按人口统计进行了分析,显示了在感知自己的子群中的差异时的有利表现)。下图列出了我们论文中的一个关键结果。

与预期 FPR 的百分比差异。顶部:全局阈值(t_g)产生的 FPR 跨度为预期值(即 1e-4 的 WM)的 2 倍(即 200%)。此外,女性 F 组的表现评分总是低于男性 M 组。除了 1e-4 列中的 IM,其下降到最低的负%差。下图:特定于亚组的阈值将这种差异降低到几乎为零,在有小差异的地方,不同亚组之间的%差异现在是*衡的,因此是公*的。

图的顶部显示了每个子组的预期 FPR 与实际的百分比差异。为了避免过于深入本文的任何一个方面(即,受制于未来的教程),让我们继续前进。在任何情况下,如果读者感兴趣的话,我们鼓励你仔细看看这篇文章,看看这个图的演示代码,或者在下面的评论区提出问题或想法!

我们希望 BFW 建立一个据点,为不同分组(和*衡)的 FR 性能的当前状态进行评估。换句话说,我们需要代理来衡量偏差,我们在构建时必须特别严格,因为各种来源都有可能产生偏差。

以下是几个相关链接。欢迎任何和所有请求—我们不仅会尽力提供,而且会相应地更新所有材料。

因此,我们希望发布的代码、演示笔记本以及对问题的更深入理解和建议的解决方案。不管怎样,数据现在可以下载了!只需填写表格,下载链接将被共享。

下面的 GIF 给出了项目关键方面的一些快照。

在演示文稿中快速浏览几张重要幻灯片的 GIF 图片。

半空?还是半满的?

个人对这个话题的整体看法——无论是在实际研究中,主流媒体以非专家理解的方式传播,还是作为企业家投资——偏见是这些天来讨论的一件大事,事实就是如此。

等等,我是认真的吗?bias ML 有什么了不起的地方?这怎么可能是“大事”?是的,是的,和容易,分别。我是认真的!作为一名全职的 ML 研究员,从我记事起,我就是一名兼职的历史学生。事实上,我的第一次教学经历是在《美国历史 I》和《美国历史 II》中(有趣的事实:生活中肯定有更多的关卡,我预见到自己的职业目标是成为一名政治科学家)。

这不是历史上第一次出现像偏见这样的现象;我们终于有了一种可以观察、量化和指出偏见的机制。,同时没有强加的个人指责,而是客观的机制,我们可以使用科学方法和相关的统计措施来衡量、分析和理解。

尽管如此,这个话题肯定会在适当的时候出现在自己的博客上。因此,请注意,我欣赏这个问题,而不是因为它引入的问题,因为没有问题是第一次被引入。然而,最后,我们有了衡量偏见的机制,而不需要将某人称为个人偏见(即,它是 ML 机制,而不是编码者)。最后,我们可以解决一个可以追溯到人类起源的问题。此外,我们现在可以以透明的方式解决问题,并且适合期望的结果——因为可能永远不会有一刀切的 ML 解决方案;然而,肯定会有适合特定用例的解决方案。因此,对我们来说,更重要的是意识到偏差,寻求可解释的结果和对系统偏差的理解,以便它可以被解决以适合特定的应用,或者它可以被部署,但不能更深入地理解为什么相应的 AI 会做出决定。你感觉如何?

论文展示(2020 年 CVPR)

你可能听说过,2020 年的 CVPR 将完全是虚拟的。因此,我们对这份文件的介绍也是如此。事实上,我们必须在早期(即昨天)提交视频演示。这更像是一个轻松的演讲,因为整个报告只需要几分钟(即大约 5 分钟)就可以完成。尽管如此,我们还是希望这份报告的水*足够高,能够阐明该报告旨在解决的大问题。

Github 上有复制所有已报道实验的代码,以及一些补充内容(例如,https://github.com/visionjo/facerec-bias-bfw)。此外,通过此表单下载面部图像(即 BFW 数据库)。

欢迎任何问题、评论和请求!我们希望其他人也能利用这一努力。

这里有一组被发现有趣的媒体内容(即相关作品)。

相关参考文献

一定要看看并分享你对这个博客或其他任何方面的想法。或许分享你偶然发现或想到的资源。这里,同样,是组成项目的组件。以下是论文、数据和源代码的下载链接:

如果你喜欢这篇文章,那就去 LinkedIn 上联系吧,因为我倾向于分享大多数博客帖子的链接(也就是说,关注最新最棒的:))!

感谢阅读,我希望它至少在一个方面让你受益——不要有偏见,但这可能是我最喜欢的有偏见的博客😜

posted @ 2024-10-15 13:45  绝不原创的飞龙  阅读(193)  评论(0)    收藏  举报