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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

如何在 Plotly 中创建非美国位置的地图

原文:https://towardsdatascience.com/how-to-create-maps-in-plotly-with-non-us-locations-ca974c3bc997?source=collection_archive---------17-----------------------

美国人永远不会知道我们的痛苦。

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

安妮·斯普拉特在 Unsplash 上的照片

Plotly 使在交互式 choropleth 地图中显示地理空间数据变得非常容易,尤其是当您的数据与美国相关时。不幸的是,如果你的数据位置在美国以外,并且比国家一级的数据更细,事情就会变得有点模糊。当您在堆栈溢出和 GitHub 问题中寻找实现映射目标的线索时,您可能会觉得自己像一个可怜的表亲。我在这里说我也经历过,我感受到你的痛苦,也有解决的办法。让我们跳进来吧!

步骤 1:获取一些数据进行绘图

在本教程中,我将显示澳大利亚维多利亚州的失业数据。我从澳大利亚统计局的统计门户网站得到了我的数据。该门户允许您选择数据的地理空间粒度。我选择下载“2016 年人口普查,G43 按年龄和性别分列的劳动力状况(LGA)”,其中 LGA 指的是地方政府区域,这是数据的空间粒度。让我们把它放进去,稍微改变一下形状:

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

“LGA 2016”一栏指的是每个地方政府区域(LGA)的 ID 或代码。通过旋转数据,我们为每个 LGA 创建了一行,从而创建了一个失业率。这一点很重要,因为当我们创建地图时,我们需要为每个显示的地理空间区域指定一个值。

步骤 2:获取与数据相对应的几何图形

使用美国以外的数据创建 Plotly choropleth 的关键是拥有一个 GeoJSON,其几何图形与您的数据相对应。虽然有时您可能已经有了一个 GeoJSON,但更有可能的是您必须创建一个,对于我来说就是这种情况。

我再次使用澳大利亚统计局,通过此链接访问 ESRI Shapefile 格式的我的数据的几何图形(我下载了“ESRI Shapefile 格式的 ASGS 地方政府区域 Ed 2020 数字边界”)。可以使用 Geopandas 将这种格式加载到 Python 中,方法是将它指向。“shp”文件:

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

现在我们可以看到,两个数据框都有一列包含每个 LGA 的代码,这就是我们将要加入的内容。每行还有一个“几何”值,即 LGA 的地理空间轮廓。

**附注:**对于澳大利亚数据的绘图,ABS 将是您获取形状文件的最佳选择。我不太精通其他国家的数据(如果你知道有网站提供你国家的地理数据,请留下评论),但如果你被困住了,http://www.diva-gis.org/gdata 的包含大多数国家的形状文件,可以免费下载。

步骤 3:合并数据和几何图形(可选:使用 Geopandas 显示)

如果您的两个数据框都有像我这样的匹配键,那么在该列上连接它们并删除所需列中没有数据的行就很简单了。

我还喜欢在此时使用 Geopandas 显示我的数据框,作为一种健全性检查,并了解我的 plotly 地图最终应该是什么样子。

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

澳大利亚维多利亚州的失业率,使用 Geopandas 绘制。

**注意:**合并数据帧对于绘图中的几何图形来说并不是绝对必要的,但它确实可以将几何图形与要绘制的数据对齐。如果不执行此合并步骤,您将需要确保包含数据的数据框和包含几何的 shapefile/geoJSON 具有对应且排序相同的行。

步骤 4:将数据框转换为 GeoJSON

现在我们有了一个地理数据框架,其中包含了我们需要使用 Plotly 绘制的所有信息。除了一个小细节:Plotly 想要 GeoJSON 格式的。幸运的是,Geopandas 可以轻松地从数据框转换为 GeoJSON,如下所示。不过首先,你要确保你的几何图形是纬度/经度格式(EPSG:4236),这正是 Plotly 所期望的。

您的 GeoJSON 应如下所示:

{'type': 'FeatureCollection',
 'features': [{'id': '20110',
   'type': 'Feature',
   'properties': {'LGA_2016': '20110',
    'LGA_CODE20': '20110',
    'LGA_NAME20': 'Alpine (S)',
    'percent_unemployed': 0.037868162692847124},
   'geometry': {'type': 'Polygon',
    'coordinates': (((146.67057224400003, -36.56828108499997),
      (146.670555271, -36.568038086999934),
      (146.67051924600003, -36.567766081999935),
      (146.67051924600003, -36.56750909899995),
      (146.6704312810001, -36.56723709299996),
      ...

您可以看到该字典包含一个名为“features”的嵌套字典,其中每个数据框行的索引都存储为“id”。如果您没有使用此方法创建 geoJSON,请确保您的 geo JSON 具有类似的格式。

第五步:剧情!

在下面的代码中有一些需要注意的地方。
首先是,你需要一个 Mapbox 访问令牌。你可以通过在这里创建一个地图箱账户来得到这个。对于个人使用级别,访问 API 将是免费的。
其次,我们为地图分配数据,将 geoJSON 用于几何图形,将合并的数据框用于颜色和文本。
最后,我们设置一些参数来定义地图的布局,包括标题、中心经纬度、缩放级别。

这将生成一个漂亮的交互式地图,显示维多利亚的失业率。不错!

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

澳大利亚维多利亚州的 Plotly choropleth 显示失业率。

您可以使用自己的数据和 shapefiles 自定义本教程。要在 GitHub 上查看代码,请点击这里

如何使用 pyRDF2Vec 创建知识图中实体的表示

原文:https://towardsdatascience.com/how-to-create-representations-of-entities-in-a-knowledge-graph-using-pyrdf2vec-82e44dad1a0?source=collection_archive---------12-----------------------

实践教程

关于如何处理知识图中表示的数据的下游 ML 任务的教程。

目录

用知识图表示数据

是用来表示无处不在的现象的数据结构,比如社交网络、化学分子和推荐系统。它们的优势之一在于,它们明确地对各个单元(即节点)之间的关系(即)进行建模,这为数据增加了额外的维度。

我们可以使用 Cora 引用网络来说明这种数据丰富的附加值。该数据集包含数百篇论文的词袋表示以及这些论文之间的引用关系。如果我们应用降维(t-SNE)来创建单词袋表示的 2D 图(图 1,左侧),我们可以看到集群(根据其研究主题进行着色)出现,但它们重叠。如果我们产生一个嵌入的图形网络(图 1,右),考虑到引用信息,我们可以看到集群被更好地分离。

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

图 1: 左图:每篇论文的词袋表示的 t-SNE 嵌入。右:图网络产生的嵌入,考虑了论文之间的引用。来源:“深度图 Infomax”,Velickovic 等人

知识图 (KG)是一种特定类型的图。它们是多关系(即不同类型的关系有不同的边)和有向(即关系有主语和宾语)。这些属性允许以统一的格式表示来自不同来源的信息。我们可以将知识图转换成规则的有向图,这有助于进一步的分析,如图 2 所示。

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

图 2: 转换一个正则有向图中的多关系有向 KG。图片作者。

运行示例:DBpedia 中的国家

在这篇文章中,我们将使用一个运行的例子。让我们首先关注为世界各地随机选择的几个国家创建表示。我们将从 DBpedia 中提取每个国家的信息,DBpedia 是从 Wikipedia 中创建的大型通用 KG。

让我们来看看 KG 在一个特定的国家附近是什么样子的:🇧🇪比利时🇧🇪.这个过程类似于转到其对应的 DBpedia 页面,然后递归地点击该页面上的所有链接。我们在下面的图 3 中对此进行了描述。我们注意到,迭代地扩展这个邻域会使事情变得很快复杂,即使我们通过删除一些部分引入了一些简化。尽管如此,我们看到 DBpedia 包含了一些关于比利时的有用信息(例如,它的国歌、最大的城市、货币……)。

我们通过使用 DBpedia SPARQL 端点创建了一个包含国家信息的定制数据集。我们从曼海姆的大学的“机器学习语义网”存储库中检索了一个国家列表。每个国家都包含有关其通货膨胀和学术产出的信息。这些信息被二进制化为“高”和“低”(因此两个二进制分类任务)。此外,对于每个国家,我们检索了他们的大陆(欧洲、亚洲、美洲、非洲或大洋洲),这给了我们一个 5 级分类任务。包含这些国家信息的 KG 是 DBpedia 的一个子集:对于每个国家,我们通过将 KG 扩展三次来检索所有信息。这个过程与图 3 中描述的完全一致。由于 SPARQL 端点的速率限制,深度为 3 的节点及其父节点最多只能包含 10000 个。KG(Turtle 语法)可以在这里下载,带有国家及其标签列表的 CSV 文件可以在这里下载。

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

图 3: 递归扩展知识图让事情变得复杂得很快。图片作者。

用 RDF2Vec 创建实体嵌入

RDF2vec 代表资源描述框架 To Vector。这是一种无监督的、任务不可知的算法,以数字形式表示 KG 中的节点,允许它们用于进一步的(下游)机器学习任务。RDF2Vec 建立在现有的自然语言处理技术之上:它结合了来自 DeepWalkWord2Vec 的见解。Word2Vec 能够为提供的句子集合(通常称为语料库)中的每个单词生成嵌入。为了生成一个 KG 的语料库,我们提取行走。提取 walks 类似于访问一个实体的 DBpedia 页面并点击链接。你点击的次数相当于一次散步的跳数。这种步行的一个例子,对于比利时来说,将是:比利时->-dbo:首都->-布鲁塞尔市->-dbo:市长->-Yvan Mayeur。注意,我们在遍历中没有区分谓词/属性(例如,dbo:capital 和 dbo:mayor)和实体(例如,比利时、布鲁塞尔、Yvan Mayeur 等等),如图 2 所示。现在,每一步都可以被视为一个句子,该步中的每一跳都对应于一个句子的标记(单词)。一旦我们提取了大量植根于我们想要为其创建嵌入的实体的遍历,我们就可以将其作为语料库提供给 Word2Vec。Word2Vec 将学习每个唯一跳的嵌入,然后可以用于 ML 任务。

pyRDF2Vec 简介

pyRDF2Vec 是一个存储库,包含了 RDF2Vec 算法的 Python 实现。在原始算法的基础上,还实现了不同的扩展。

在本教程中,我将解释我们如何使用 pyRDF2Vec 在 KG 中生成实体的嵌入。此外,我将简要解释 RDF2Vec 的一些扩展,以及如何在 pyRDF2Vec 中使用这些扩展。

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

图片取自我们的知识库

有偏向的行走或采样策略

现在,从图 3 中可以注意到,我们可以提取的可能行走的数量随着深度呈指数增长。当我们使用像 DBpedia 这样的大 kg 时,这就成了问题。在最初的 RDF2Vec 论文中,行走只是从图中随机抽样,但是科切兹等人提出了几个度量来偏向行走。这些走步当时被称为有偏走步,但是我们将它们称为符合 pyRDF2Vec 术语的采样策略。一个可能的采样策略示例如图 4 所示。

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

图 4: 对行走中的下一跳进行采样的一种可能方式是根据外出边的数量来缩放权重。这只是一个例子,有许多不同的指标(基于频率,PageRank,度,…)。图片作者。

行走修改和变换

到目前为止,我们将行走算法解释为从节点的邻居连续采样,直到达到某个深度。但是,我们可以对该算法进行修改(提取算法),或者我们可以对行走进行后处理以包含额外的信息(转换算法)。这是我们在 IDLab 一直在研究的内容。这些策略应用于一个简单的例子,如图 5 所示。

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

图 5: 从图中提取行走(深度 2)的不同策略。在这个图中,A 和 F 是我们想要从中提取行走的根。c 和 H 属于同一个社区(社区检测)。来源:“知识图中 RDF2Vec 节点嵌入的行走提取策略”,Vandewiele 等人(博客作者)。

既然我们已经介绍了这些改进的行走策略,我们现在讨论 RDF2Vec 算法的三个主要构建模块:(I)一个行走策略 , (ii)一个采样策略,( iii)一个嵌入算法 (NLP)。正如我们将进一步讨论的,这些构建块中的每一个都可以在 pyRDF2Vec 中配置。

用 pyRDF2Vec 加载 kg

知识通常以资源描述框架(RDF)格式表示。pyRDF2Vec 可以通过包装 rdflib 轻松加载不同 RDF 语法的文件。这将把整个 KG 加载到 RAM 存储器中。然而,当 KG 大于可用的 RAM 内存时,这就成问题了。因此,我们也支持与端点的交互:KG 可以托管在某个服务器上,我们的 KG 对象将在任何需要的时候与那个端点进行交互。这大大减少了所需的 RAM 内存,但代价是延迟更长。

用 pyRDF2Vec 加载元数据和知识图

创建我们的第一个嵌入

现在我们已经将 KG 加载到内存中,我们可以开始创建嵌入了!为了做到这一点,我们创建一个RDF2VecTransformer,然后用新加载的 KG 和一个实体列表调用fit()函数。一旦模型被拟合,我们可以通过transform()函数检索它们的嵌入。与常规的 scikit-learn 流程(我们在训练数据上调用fit(),在测试数据上调用predict()transform())不同的一点是,训练和测试实体都必须提供给fit()函数(类似于 t-SNE 在 scikit-learn 中的工作方式)。由于 RDF2Vec 在无人监督的情况下工作,这不会引入标签泄漏。

用默认的超参数创建我们的初始嵌入。我们为每个提供的实体获得 100 维的嵌入。

上面的代码片段会给我们一个列表列表。对于向转换方法提供的每个实体,将返回 100 维的嵌入。现在,为了用肉眼检查这些嵌入,我们需要进一步降低维数。一个很好的方法是使用 t-SNE。我们可以使用下面的代码片段来做到这一点:

用 t-SNE 进一步降低我们嵌入的维数,从 100D 到 2D,以便可视化它们。

这给了我们如图 6 所示的结果。

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

图 6: 我们初始嵌入的 t-SNE 图。我们可以开始看到国家集群的出现。图片作者。

现在让我们来看看这些嵌入有多好,以便解决我们已经讨论过的三个 ML 任务:两个二元分类任务(高/低通货膨胀和高/低学术产出)和一个多类分类任务(预测大陆)。应该注意的是,由于 RDF2Vec 是无监督的,在创建这些嵌入的过程中,从来没有使用过这个标签信息!RDF2Vec 是任务不可知的,从我们的节点到嵌入的投影不是为特定的任务定制的,嵌入可以用于多个不同的下游任务。让我们创建一个效用函数,它将生成的嵌入作为输入,然后对所有三个任务执行分类:

为三个不同任务的嵌入装配分类器。

现在让我们调用classify(walk_embeddings)来看看我们基线嵌入的性能:

**Research Rating**
Accuracy = 0.765625
[[26  8]
 [ 7 23]]

**Inflation Rating**
Accuracy = 0.5882352941176471
[[14 16]
 [12 26]]

**Continent**
Accuracy = 0.6716417910447762
[[13  3  1  1  0]
 [ 4 11  0  1  0]
 [ 0  1  7  3  0]
 [ 1  3  1 14  0]
 [ 0  1  0  2  0]]

研究评级、通货膨胀和大陆分类的准确率分别为 76.56%、58.82%和 67.16%。虽然这些准确性远非完美,但它确实显示了所有这些任务的一些信息存在于生成的嵌入中。这些较低精确度的一个可能原因是,由于 DBpedia 的公共 API 的速率限制,只使用了 DBpedia 数据的一个子集。此外,我们只使用默认的超参数来生成我们的嵌入。

调整超参数

如前所述,RDF2Vec 算法的三个构建模块(行走算法、采样策略和嵌入技术)都是可配置的。现在,让我们尝试提取更深层次的遍历并生成更大的嵌入:

设置不同的行走深度和嵌入大小。

我们指定我们想要使用随机行走策略来提取深度为 3 的行走,这对应于从某个 DBpedia 页面跟随 3 个链接,或者在我们转换的 KG 中采取 6 次跳跃(参见图 1)。我们还指定我们想要为每个实体详尽地提取深度为 3 的所有可能的遍历,由None参数指示。我们没有指定任何采样策略,但是指定了我们想要使用 Word2Vec 嵌入技术来产生大小为 500 的嵌入。这种超参数配置为我们提供了以下精度:

**Research Rating**
Accuracy = 0.78125
[[25  9]
 [ 5 25]]

**Inflation Rating**
Accuracy = 0.6470588235294118
[[14 16]
 [ 8 30]]

**Continent**
Accuracy = 0.6865671641791045
[[15  0  0  3  0]
 [ 6  9  0  1  0]
 [ 1  2  6  2  0]
 [ 0  3  0 16  0]
 [ 0  0  0  3  0]]

如我们所见,三项任务中有两项的准确性有所提高,而第三项任务(通货膨胀分类)的准确性保持不变。

尝试不同的行走策略

pyRDF2Vec 允许我们使用不同的行走策略,不同策略的概述如图 5 所示。此外,我们可以组合不同的策略:pyRDF2Vec 将提取每个策略的遍历,并在提供给嵌入技术之前将提取的遍历连接在一起。让我们试着结合几种行走策略:

我们现在得到的精度是:

**Research Rating**
Accuracy = 0.71875
[[24 10]
 [ 8 22]]
 **Inflation Rating**
Accuracy = 0.6764705882352942
[[14 16]
 [ 6 32]]

**Continent**
Accuracy = 0.7910447761194029
[[15  0  0  3  0]
 [ 5 11  0  0  0]
 [ 2  0  9  0  0]
 [ 0  1  0 18  0]
 [ 0  1  0  2  0]]

因此,通胀评级和大陆任务有所改善,但研究评级的表现有所下降。

采样更深的行走

现在,如果我们想要提取更深的行走,我们很快就会遇到内存问题,因为行走的次数会随着行走的深度呈指数增长。这就是抽样策略发挥作用的地方。作为最后一个实验,让我们使用上一节中的行走策略对深度为 6 的 5000 次行走进行采样:

总共提取了 854901 次行走。这为我们提供了以下精度:

**Research Rating**
Accuracy = 0.671875
[[30  4]
 [17 13]]

**Inflation Rating**
Accuracy = 0.5
[[14 16]
 [18 20]]

**Continent**
Accuracy = 0.8059701492537313
[[17  0  0  1  0]
 [ 4 10  0  2  0]
 [ 0  2  9  0  0]
 [ 0  1  0 18  0]
 [ 0  3  0  0  0]]

因此,只有一个大陆分类的改进和其他两个任务的显著恶化。当然,人们可以调整 RDF2VecTransformer 的许多超参数(行走和采样策略及其相应的超参数)和随机森林(或任何其他分类技术)来获得最佳精度,但我们将此作为练习留给读者!

RDF2Vec 的缺点和研究挑战

当前版本的 RDF2Vec 存在一些缺点,需要进一步研究来解决这些缺点:
–**最初的 RDF2Vec 实现没有结合 NLP 领域的最新见解:**自 2017 年 RDF2Vec 问世以来,NLP 领域已经取得了许多进展。我们目前正在致力于将不同的 NLP 嵌入技术(比如 BERT)实现到 pyRDF2Vec 中。
**–随机游走产生的嵌入的表达能力是有限的:**游走只是单链,它们捕捉的信息有些有限。行走策略试图缓解这一缺点,但需要在这一方向进行进一步的研究。此外,我们或许可以将不同策略生成的行走组合在一起。
**–RDF2Vec 无法扩展到大型 kg:**由于可以提取的可能行走的数量随深度呈指数增长,rdf 2 vec 无法很好地扩展到具有大量节点的 kg,尤其是当它包含许多高度连接的节点时。采样策略提高了可伸缩性,但是还可以做更多的研究。
**–rdf 2 vec 不能很好地处理 KG 中的数值:**目前,遍历中的所有跳,对应于 KG 中的节点,都被作为分类数据处理。这对于有序数据(例如,居民人数和国家大小)来说是次优的。
–**rdf 2 vec 不能处理易变数据:**如前所述,训练和测试数据都需要提供给我们的fit()方法。但是如果我们的一些测试数据还不可用呢?这里有一些技术可以提供帮助,比如在线和渐进式学习。

我们希望,通过发布 pyRDF2Vec,提供一个工具包,可以促进解决这些挑战的研究。

代码和数据可用性

pyRDF2Vec 库可以在 Github 上找到。如果你喜欢这个知识库,请给我们一颗星,我们将不胜感激!此外,我们欢迎各种贡献。

这篇博文中使用的自定义数据集可以下载: KGCSV 。我们还在一个 Google Colab 笔记本中提供了所有的代码,这样你就可以从你的浏览器中交互地运行它了!

如何创建可重用的命令行

原文:https://towardsdatascience.com/how-to-create-reusable-command-line-f9a2bb356bc9?source=collection_archive---------41-----------------------

你能把你的多个有用的命令行打包成一个文件以便快速执行吗?

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

照片由 Joshua LamUnsplash 上拍摄

动机

作为一个数据科学家,知道一些基本的有用的命令行是很方便的。您可能有一些喜欢的命令行命令,您会一遍又一遍地使用它们。

例如,您想要创建一个 Django 应用程序,这个库使得用 Python 创建 web 应用程序变得容易。要为 Django 应用程序设置文件夹和环境,您需要执行以下操作:

# Create the folder for the app
mkdir newapp# Go to the directory
cd newapp# Create the virtual environment
python -m venv venv# Activate the environment
source venv/bin/activate# Upgrade pip and install Django
pip install --upgrade pip
pip install Django# Create Django project
django-admin startproject myapp# Make the structure cleaner
mv myapp/manage.py ./
mv myapp/myapp/* myapp
rm -r myapp/myapp/

既然我们想在将来使用相同的命令行命令来创建一个新的应用程序,如果我们能够将这些命令保存在某个地方,然后在我们想创建一个新的应用程序时使用它,是不是很好?

像这样简单的事情

./createapp.sh

而设置一个 app 的每一个基本步骤都要照顾到?本文将向您展示如何使您的命令更加可重用和更快地执行。

可重用的命令行

首先,我们用touch创建一个文件,并使用。sh 表示 shell 脚本。

touch createapp.sh

使用nano编辑文件

nano createapp.sh

我们应该能够在这里插入所有的命令

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

用 Control + X 关闭文件(或用 Mac 用 Command + X)。键入 y 保存更改。使用回车键退出文件。

现在用 Bash 运行这个文件

bash createapp.sh

app 应该设置好了,随时可以使用!但是为什么要 bash 呢?Bash 是 shell,即命令语言解释器。有没有办法不用 bash 直接运行文件?试着跑

./createapp.sh

我们会得到这个错误:

bash: ./createapp.sh: Permission denied

这里发生了什么事?使用以下命令查看该文件的权限

ls -l createapp.sh

我们会看到类似这样的东西

-rw-r--r-- 1 khuyentran khuyentran 229 May 14 22:58 createapp.sh

如果我们看一下第一个— ,后面的字符rw,我们可以看到拥有该文件的用户可以读r和写w,但是不能执行x.,所以我们只需要使用

chmod u+x createapp.sh

u代表用户,+代表添加权限,x代表执行。现在我们应该可以不用 bash 来运行我们的文件了!

轻轻一点,让你的命令变得可携带

我们发现这个文件非常方便,所以我们决定与我们的朋友分享或在另一台计算机上运行它。我们可能需要意识到环境中可能发生的变化。

默认情况下,我们使用的 Bash shell 在这个目录 /bin/sh 中执行。其他 shells 可能有不同的缺省值。所以为了确保这个文件总是正常工作(当在另一台计算机上使用时),我们应该添加这个添加到我们的createapp.sh文件的开头

#!/usr/bin/env bash

但是如果我们想要另一个变量呢?

我们已经成功地用 bash 文件创建了一个应用程序。但是如果我们想为我们的下一个应用程序取另一个名字呢?我们可以编辑文件或者使用更快的方法,在我们的脚本中将名称作为变量

#!/usr/bin/env bash
APPNAME="$1"
mkdir $APPNAME
cd $APPNAME
python -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install Django
django-admin startproject $APPNAME
mv $APPNAME/manage.py ./
mv $APPNAME/$APPNAME/* $APPNAME
rm -r $APPNAME/$APPNAME/

用一个变量替换newapp,在本例中是 APPNAME。使用$1指示在运行脚本时获取第一个参数。将每个appname替换为$APPNAME.

现在快跑

./createapp.sh someapp

另一个新名字的应用程序被创建了!

最后一步:从任何地方运行你的脚本

我们已经成功地从当前目录执行了我们的应用程序。如果我们可以从计算机上的任何目录执行这个脚本,不是更方便吗?

为了使我们的文件能够从任何地方运行,我们将把这个文件添加到 PATH 中,PATH 是一个环境变量,它告诉 shell 在哪个目录中搜索可执行文件。

在 PATH 下找到一个目录列表。

echo $PATH | tr ":" "\n"

选择一个目录,并将文件移动到该目录中。假设我选择/usr/local/bin 作为保存所有工具的目录

sudo mv createapp.sh /usr/local/bin/

就是这样!将来,您可以在计算机的任何目录中使用

createapp.sh someapp

而不需要记住每一步。

结论

恭喜你!您已经学习了如何使您的命令行可重用。如果您尚未使用此工具,您应该考虑将此工具添加到您的工作流程中。你工作流程中的一个小小的改变可能会在未来增加大量的时间。

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedInTwitter 上联系我。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

[## 使用这两个工具在您的机器学习项目中实现可重复性

你能打包你的机器学习模型,并根据你的需要挑选一个最好的吗?

towardsdatascience.com](/achieve-reproducibility-in-machine-learning-with-these-two-tools-7bb20609cbb8) [## 如何有效地微调你的机器学习模型

发现为您的 ML 模型寻找最佳参数非常耗时?用这三招

towardsdatascience.com](/how-to-fine-tune-your-machine-learning-models-with-ease-8ca62d1217b1) [## 如何用 Github 组织你的数据科学文章

被新信息淹没?现在,您可以轻松地跟踪文章并为其创建自定义注释

towardsdatascience.com](/how-to-organize-your-data-science-articles-with-github-b5b9427dad37) [## 如何用 Ngrok 用 3 行代码分享你的 Jupyter 笔记本

想象一下,让你的朋友在远程机器上使用你的本地 Jupyter 笔记本

towardsdatascience.com](/how-to-share-your-jupyter-notebook-in-3-lines-of-code-with-ngrok-bfe1495a9c0c) [## 如何使用 HyperDash 远程监控和记录您的机器学习实验

培训需要很长时间才能完成,但你需要去洗手间休息一下…

towardsdatascience.com](/how-to-monitor-and-log-your-machine-learning-experiment-remotely-with-hyperdash-aa7106b15509)

如何使用 Python 从头开始创建简单的新闻摘要

原文:https://towardsdatascience.com/how-to-create-simple-news-summarization-from-scratch-using-python-83adc33a409c?source=collection_archive---------26-----------------------

新闻摘要入门

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

照片由 Aaron BurdenUnsplash

如果你是机器学习领域的新手,特别是自然语言处理(NLP ),你听说过自动新闻摘要,并且对它感兴趣。你一定在想,比如“如何做出一个好的模型?”,“我该学什么?”以及“我应该从哪里开始?”。

然后你开始搜索哪些方法有利于自动摘要,并找到诸如****,的方法,然后你尝试预先训练的模型,并对其结果留下深刻印象。那么你有兴趣为你的母语训练模型。但有一个问题,你生活在第三世界国家,没有预先训练好的模型可用,或者你没有任何超级计算机可以运行,或者你甚至没有找到你的语言的数据集,你也懒得单独给它贴上标签。

所以在这篇文章中,我会给你一个简单的方法来制作简单的新闻摘要。首先,让我们谈谈新闻摘要的方法。

一般来说,新闻摘要方法分为两种,即提取的和抽象的。提取摘要意味着识别文本的重要部分,并使其从原始文本中逐字产生句子的子集;而抽象概括在使用先进的自然语言技术解释和检查文本之后,以新的方式再现重要的材料,以产生新的、更短的文本,该文本传达来自原始文本的最关键的信息。

因为我们最初的目标是做一个简单的摘要,这里我们将使用提取摘要的方法。开始吧,如果想看这篇文章的完整代码,请访问我的 github

首先,导入将要使用的包

import numpy as np
import nltk
import re

这里我们使用了 NumPynltk ,以及 re 库。NumPy 是用于数值计算的库,nltk 是广泛用于 NLP 的库,re 是用于正则表达式的库。

之后,我们定义将要执行的预处理功能。它旨在集中单词并消除不需要的字符。这里有 3 个预处理功能,即:

  • 大小写折叠:将所有字母改为小写
  • 清除:删除所有标点和数字,仅保留字母字符
  • 标记化:将句子转换成标记

下面是预处理过程的代码

def casefolding(sentence):
    return sentence.lower()def cleaning(sentence):
    return re.sub(r'[^a-z]', ' ', re.sub("’", '', sentence))def tokenization(sentence):
    return sentence.split()

此外,您还可以添加其他功能,如停用词移除、词干提取或词汇化。但是,因为每种语言的用法可能不同,所以本文将不解释该功能,但我提供的 Github 链接中有一个示例。

接下来,我们还需要一个函数将整个故事转换成句子的集合

def sentence_split(paragraph):
    return nltk.sent_tokenize(paragraph)

接下来,我们将定义一个函数来计算文档中每个单词的数量。执行这个过程是为了给单词加权,目的是确定该单词是否有效果。以下是该过程的代码

def word_freq(data):
    w = []
    for sentence in data:
        for words in sentence:
            w.append(words)
    bag = list(set(w))
    res = {}
    for word in bag:
        res[word] = w.count(word)
    return res

然后,我们会做一个函数来计算每个句子的权重。这个过程是为了确定哪一个句子被认为最能代表整个故事。

def sentence_weight(data):
    weights = []
    for words in data:
        temp = 0
        for word in words:
            temp += wordfreq[word]
        weights.append(temp)
    return weights

现在,我们将使用的所有函数都已定义。我们举个案例吧。例如,我将使用一篇来自的文章,标题为“《纽约时报》向一群愤怒的暴民投降了”。新闻业将会因此而遭殃。

我们将从手动复制粘贴将网站上的新闻插入变量开始。如果你不想做复制粘贴,对网页抓取感兴趣,可以看我之前的文章《用 Python 做 4 行的 网页抓取新闻》。

**** [## 用 Python 实现 4 行新闻的网络抓取

抓取网站的简单方法

towardsdatascience.com](/scraping-a-website-with-4-lines-using-python-200d5c858bb1)

news = """
IIn a time in which even a virus has become the subject of partisan disinformation and myth-making, it’s essential that mainstream journalistic institutions reaffirm their bona fides as disinterested purveyors of fact and honest brokers of controversy. In this regard, a recent course of action by the New York Times is cause for alarm.On December 27, 2019, the Times published a column by their opinion journalist Bret Stephens, “The Secrets of Jewish Genius,” and the ensuing controversy led to an extraordinary response by the editors.Stephens took up the question of why Ashkenazi Jews are statistically overrepresented in intellectual and creative fields. This disparity has been documented for many years, such as in the 1995 book Jews and the New American Scene by the eminent sociologists Seymour Martin Lipset and Earl Raab. In his Times column, Stephens cited statistics from a more recent peer-reviewed academic paper, coauthored by an elected member of the National Academy of Sciences. Though the authors of that paper advanced a genetic hypothesis for the overrepresentation, arguing that Ashkenazi Jews have the highest average IQ of any ethnic group because of inherited traits, Stephens did not take up that argument. In fact, his essay quickly set it aside and argued that the real roots of Jewish achievement are culturally and historically engendered habits of mind.Nonetheless, the column incited a furious and ad hominem response. Detractors discovered that one of the authors of the paper Stephens had cited went on to express racist views, and falsely claimed that Stephens himself had advanced ideas that were “genetic” (he did not), “racist” (he made no remarks about any race) and “eugenicist” (alluding to the discredited political movement to improve the human species by selective breeding, which was not remotely related to anything Stephens wrote).It would have been appropriate for the New York Times to acknowledge the controversy, to publish one or more replies, and to allow Stephens and his critics to clarify the issues. Instead, the editors deleted parts of the column—not because anything in it had been shown to be factually incorrect but because it had become controversial.Worse, the explanation for the deletions in the Editors’ Note was not accurate about the edits the paper made after publication. The editors did not just remove “reference to the study.” They expurgated the article’s original subtitle (which explicitly stated “It’s not about having higher IQs”), two mentions of Jewish IQs, and a list of statistics about Jewish accomplishment: “During the 20th century, [Ashkenazi Jews] made up about 3 percent of the U.S. population but won 27 percent of the U.S. Nobel science prizes and 25 percent of the ACM Turing awards. They account for more than half of world chess champions.” These statistics about Jewish accomplishments were quoted directly from the study, but they originated in other studies. So, even if the Times editors wanted to disavow the paper Stephens referenced, the newspaper could have replaced the passage with quotes from the original sources.The Times’ handling of this column sets three pernicious precedents for American journalism.First, while we cannot know what drove the editors’ decision, the outward appearance is that they surrendered to an outrage mob, in the process giving an imprimatur of legitimacy to the false and ad hominem attacks against Stephens. The Editors’ Note explains that Stephens “was not endorsing the study or its authors’ views,” and that it was not his intent to “leave an impression with many readers that [he] was arguing that Jews are genetically superior.” The combination of the explanation and the post-publication revision implied that such an impression was reasonable. It was not.Unless the Times reverses course, we can expect to see more such mobs, more retractions, and also preemptive rejections from editors fearful of having to make such retractions. Newspapers risk forfeiting decisions to air controversial or unorthodox ideas to outrage mobs, which are driven by the passions of their most ideological police rather than the health of the intellectual commons.Second, the Times redacted a published essay based on concerns about retroactive moral pollution, not about accuracy. While it is true that an author of the paper Stephens mentioned, the late anthropologist Henry Harpending, made some deplorable racist remarks, that does not mean that every point in every paper he ever coauthored must be deemed radioactive. Facts and arguments must be evaluated on their content. Will the Times and other newspapers now monitor the speech of scientists and scholars and censor articles that cite any of them who, years later, say something offensive? Will it crowdsource that job to Twitter and then redact its online editions whenever anyone quoted in the Times is later “canceled”?Third, for the Times to “disappear” passages of a published article into an inaccessible memory hole is an Orwellian act that, thanks to the newspaper’s actions, might now be seen as acceptable journalistic practice. It is all the worse when the editors’ published account of what they deleted is itself inaccurate. This does a disservice to readers, historians and journalists, who are left unable to determine for themselves what the controversy was about, and to Stephens, who is left unable to defend himself against readers’ worst suspicions.We strongly oppose racism, anti-Semitism and all forms of bigotry. And we believe that the best means of combating them is the open exchange of ideas. The Times’ retroactive censoring of passages of a published article appears to endorse a different view. And in doing so, it hands ammunition to the cynics and obfuscators who claim that every news source is merely an organ for its political coalition."""

之后,我们将通过把新闻切割成句子的形式来处理它,然后使用我们上面定义的函数对每个句子进行预处理。

sentence_list = sentence_split(news)
data = []
for sentence in sentence_list:
    data.append(tokenization(cleaning(casefolding(sentence))))
data = (list(filter(None, data)))

之后,我们将从我们定义的函数中统计文档中每个单词的数量。

wordfreq = word_freq(data)

然后,从单词计算的结果我们只需要计算每个句子的权重。

rank = sentence_rank(data)

之后,我们决定要输出多少个主要句子来表示新闻。例如,我将输出 2 个句子,所以这里我用 2 填充 n。然后,系统将选择权重最高的前两个句子。要看你选择多少个句子出现。

n = 2
result = ''
sort_list = np.argsort(ranking)[::-1][:n]
for i in range(n):
    result += '{} '.format(sentence_list[sort_list[i]])

要显示结果,请使用以下代码

print(result)

所以结果会是这样的。

The editors did not just remove “reference to the study.” They expurgated the article’s original subtitle (which explicitly stated “It’s not about having higher IQs”), two mentions of Jewish IQs, and a list of statistics about Jewish accomplishment: “During the 20th century, [Ashkenazi Jews] made up about 3 percent of the U.S. population but won 27 percent of the U.S. Nobel science prizes and 25 percent of the ACM Turing awards. Detractors discovered that one of the authors of the paper Stephens had cited went on to express racist views, and falsely claimed that Stephens himself had advanced ideas that were “genetic” (he did not), “racist” (he made no remarks about any race) and “eugenicist” (alluding to the discredited political movement to improve the human species by selective breeding, which was not remotely related to anything Stephens wrote).

不错吧?虽然它可能不如我们使用最先进的方法,但我们可以很好地理解我们简短新闻的本质。根据我的提示,通过使用这种方法,您可以生成自己的数据集,尽管它仍然有局限性,因为获得的结果并不总是您想要的方式。

祝你好运!****

如果你喜欢这个帖子,我想推荐一篇启发了我 的 文章。

使用快照和数据工厂备份您的 Azure 存储

原文:https://towardsdatascience.com/how-to-create-snapshots-and-backups-of-your-azure-storage-e72bef58e0aa?source=collection_archive---------21-----------------------

了解如何使用 blob 快照和数据工厂增量备份来自动备份您的数据湖

完整的数据湖恢复解决方案请看我的后续博客:https://towards data science . com/how-to-recover-your-azure-data-lake-5b 5e 53 f 3736 f

1.Azure 存储备份-简介

Azure 存储总是存储您数据的多个副本。当使用地理冗余存储(GRS)时,它也被复制到配对区域。这样,GRS 可以防止数据在灾难发生时丢失。但是,当应用程序错误损坏数据时,GRS 无法防止数据丢失。然后,损坏的数据会被复制到其他区域/地区。在这种情况下,需要一个备份来恢复你的数据。两种备份策略如下:

在这篇博客中,讨论了如何从存储帐户创建快照和增量备份,另请参见下面的概述。

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

1.数据湖备份—高级概述

为了支持您的存储帐户的自动快照和增量备份的创建,在本博客的剩余部分将使用和讨论三种类型的脚本:

  • 生产者触发的基于事件的脚本,用于在接收/修改数据后创建快照和增量备份请求
  • 使用 ADFv2 创建增量备份的队列触发器脚本
  • 管理员触发的基于时间的脚本,用于协调丢失的快照/增量备份

请注意, blob 快照仅在常规存储帐户中受支持,在 ADLSgen2 中尚不受支持(但预计在 ADLSgen2 中也会可用)。因此,脚本基于常规存储帐户,下面提供了脚本的详细说明。另请注意,脚本处理快照/备份的创建,而不是恢复。

2.基于事件触发的快照/增量备份请求

在数据湖中,数据通常由生产者使用 Azure Data Factory 获取。要创建基于事件的触发快照/增量备份,应部署以下内容:

  • 将下面的脚本部署为 Python 中的 Azure 函数。见此链接如何用 Python 创建 Azure 函数。参见我的另一篇博客如何保护 Azure 函数。
  • 将 Azure 函数作为链接服务添加到 Azure 数据工厂实例中,并将 Azure 函数作为最后一步添加到摄取管道中。
  • 创建两个存储帐户作为源存储和备份存储。还要创建一个存储队列来处理备份请求消息。

现在,每次使用 ADFv2 接收新数据时,都会调用一个 Azure 函数来创建快照,并为新的/已更改的 blobs 发送增量备份请求,另请参见下文。

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

2.基于事件触发的快照/增量备份请求

脚本 HttpSnapshotIncBackupContainerProducer的内部工作原理可以解释如下:

  • 0.初始化快照/备份脚本通过将 blob 的 ETag 与之前的快照(如果有)进行比较,来检查存储帐户的容器中的已修改/新 blob。在它检测到修改的/新的斑点的情况下,完成以下 2 个步骤:
  • 1a。从修改的/新的 blob 创建快照
  • 1b。向存储队列发送增量备份请求消息。备份请求消息仅包含已修改 blob 的元数据。

脚本的核心如下:

**# Get all blobs in container** prev_blob_name = ""
prev_blob_etag = ""
blob_list = container.list_blobs(include=['snapshots'])                           for blob in blob_list:                                                       if blob.snapshot == None:
    **# Blob that is not snapshot
 **   if prev_blob_name != blob.name: 
        **# New blob without snapshot, create snapshot/backup**                                        
        create_snapshot_backup(blob.name, blob.etag)
    elif prev_blob_etag != blob.etag:
        **# Existing blob that has changed, create snapshot/backup** create_snapshot_backup(blob.name, blob.etag) prev_blob_name = blob.name
    prev_blob_etag = blob.etag

请注意,只有生产者 ADFv2 托管身份和此 Azure 函数托管身份对此容器具有写访问权限。Blob 触发器在这种情况下不起作用,因为修改 blob 时不会触发任何事件。

异步增量备份创建将在下一章讨论。

3.增量备份创建

一旦新的增量备份请求被添加到存储队列,该消息将被处理,从而创建增量备份。在这种情况下,应部署以下内容:

  • 将下面的脚本部署为 Python 中队列触发的 Azure 函数。可以使用与步骤 2 中相同的应用服务计划
  • 确保正确填写所有必需的应用程序设置,参见此处
  • 部署 ADFv2 管道,通过将 blobs 从源存储帐户复制到备份存储帐户来创建增量备份
  • 确保您为 Azure 函数分配了一个托管身份,并且 Azure 函数拥有 RBAC 角色“contributor”来运行它

现在,每次在存储队列上接收到新的增量备份请求消息时,都会触发一个 Azure 函数,该函数调用创建增量备份的 ADFv2 管道,另请参见下文。

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

3.增量备份创建

脚本 queuecreateblobbackupadfv 2的工作原理可以解释如下:

  • 2a。存储队列收到 blob 的新备份请求消息。请注意,消息可以并行处理
  • 2b。Azure 函数从存储队列中提取消息,并检查备份请求是否过期。然后,它使用 REST API 和 Azure Function 托管身份触发 ADFv2 管道
  • 2c。ADFv2 通过将 blob 从源存储帐户复制到备份存储帐户来启动复制活动

在步骤 2b 中,还可以决定运行 blob_lease 模式,该模式排他地锁定文件并保证文件的正确版本被添加到备份存储帐户。是否使用 blob 租约取决于许多因素(例如,允许的最大租约时间、文件大小、作业数量、不变性)。

脚本的核心如下:

USING_BLOB_LEASE = True **# check if source blob has not changed in the meantime** if source_blob_changed(blob_name, blob_etag) == True:
    return**# Start copying using ADFv2** try:                               
    if not USING_BLOB_LEASE:
        **# Copy without locking the file
**        copy_adf_blob_source_backup(blob_name, blob_etag)
    else:      
        **# Copy with blob lease locks the file
**        copy_with_lease(blob_name, blob_etag)                           except:                               
    logging.info("copy failed")

在前两章中,我们讨论了当生产者使用 ADFv2 向数据湖添加新数据时,如何创建快照和增量备份。但是,也可能需要触发基于时间的快照/增量备份。这将在下一章讨论。

4.基于时间的触发快照/增量备份请求

在第 2 章中,讨论了生产者如何创建基于事件的快照/增量备份请求。然而,还需要能够创建丢失快照和/或丢失备份的协调脚本。当生产者忘记将 Azure 功能添加到其摄取管道和/或脚本无法运行时,会发生这种情况。为了创建基于时间的功能,应部署以下内容:

  • 将下面的脚本部署为 Python 中的 Azure 函数。可以使用与步骤 2 中相同的应用服务计划。
  • 确保正确填写所有必需的应用程序设置,参见此处

现在,管理员可以将协调脚本配置为定期运行,以便创建快照并发送增量备份请求,另请参见下文。

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

4.基于时间的触发快照/增量备份请求

脚本 httpsnapshotincbackupstoragereconcing的内部工作原理可以解释如下:

  • 0.基于初始化快照/备份时间的脚本通过将 blob 的 ETag 与以前的快照(如果有)进行比较,来检查存储帐户中修改的/新的 blob。在它检测到修改的/新的斑点的情况下,完成以下 2 个步骤:
  • 1a。如果它检测到还没有快照的修改的/新的 blob,则创建新的快照:
  • 1b。如果它检测到还没有增量备份的修改的/新的 blob,则发送新的备份请求消息

脚本的核心如下:

**# Get all containers in storage account**
container_list = client_source.list_containers()
for container in container_list:
    **# Get all blobs in container
**    prev_blob_name = ""
    prev_blob_etag = ""
    blob_list = container.list_blobs(include=['snapshots'])
    for blob in blob_list:
        if blob.snapshot == None:
            **# Blob that is not snapshot
            # 1\. Check if snapshot needs to be created
 **           if prev_blob_name != blob.name: 
                **# New blob without snapshot, create snapshot**
                create_snapshot(blob.name, blob.etag)
            elif prev_blob_etag != blob.etag:
                **# Existing blob that has changed, create snapshot** create_snapshot(blob.name, blob.etag) **# 2\. Check if incremental backup needs to be created**
 **# Check if blob exists in backup** blob_exists = check_blob_exists(blob.name, blob.etag)
            if blob_exists == False:         
 **# Not in backup, put backup request message on queue**
                queue_json = "{" + "\"container\":\"{}\",
                \"blob_name\":\"{}\", \"etag\":\"{}\""
                .format(container.name, blob.name, blob.etag) + "}"
                queue_service.put_message(queue, queue_json)                

        prev_blob_name = blob.name
        prev_blob_etag = blob.etag

5.结论

Azure 存储始终存储您的数据的多个副本,地理冗余存储(GRS)在成对的区域中额外存储副本。但是,GRS 存储不能保护因应用程序错误而损坏的数据。然后,损坏的数据会被复制到其他分区和区域。可以防止数据损坏的两种方法如下:

  • 快照创建:一旦添加或修改了 blob,就会为当前情况创建一个快照。
  • 增量备份:一旦添加或修改了一个 blob,就会创建该 blob 到另一个存储帐户的增量备份。

在这篇博客中,我们讨论了如何使用 github 中的脚本创建同步快照和异步增量备份。另请参见下文描述的扩展高级概述。

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

1.数据湖备份—高级概述扩展

如何创建 Tableau 数据警报

原文:https://towardsdatascience.com/how-to-create-tableau-data-alerts-3e7f508555ec?source=collection_archive---------43-----------------------

在你的老板接到你客户的电话之前得到关于数据异常的通知

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

图片由苏·曼斯菲尔德皮克斯拜拍摄

当你有一套自动化的报告提供给你的商业伙伴时,你最终会收到可怕的电话或电子邮件。“我本打算在与客户会面时使用这些数据,但它看起来不太对。”要么是数据出了问题,要么是管道坏了,要么就是出现了可以解释的异常现象。当问题是由于你的一个中断的过程引起时,接到电话是令人尴尬的。最好在你的用户看到它之前得到通知。我将回顾如何在 Tableau 中设置通知。第一个知道。

有时候你需要设置一个主动预警。没什么问题,但是…但是你需要提前通知,这样你就可以密切关注整个过程。

如果你关注我的文章,你就会知道我尽量不去烦无聊的业务 KPI(当呼叫等待时间超过 2 分钟时提醒我,诸如此类)。让我们为一些有趣的事情设置一个提醒。假设你有一个连续测量你的万圣节糖果碗。不给糖就捣蛋的人来了,你购买了各种糖果,另一个家庭成员正在分发。私底下,你真的很想在士力架吃完之前吃一块。你还需要知道你什么时候会没有糖果,因为你可能需要在食品室里找一些应急储备(有人要吃吗?).

设置

我试图在 Tableau Public 上做这个演示,但是我现在找不到任何可以在 Tableau Public 上设置警报的地方。我不得不切换到 Tableau 服务器。如果您的公司使用 Tableau,您很可能可以在已发布的工作表上设置预警。

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

来自 Pixabaypixel1 的图像

数据

实时数据会有当前的日期和时间,如下表所示。我开始时每个人有 40 块糖果,数字逐渐减少,代表所有的小公主和忍者都来拿他们的糖果。因为我今晚要运行这个,所以我必须相应地调整日期/时间。

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

糖果碗算数——作者截图

工作簿

要在数据达到警报阈值时得到通知,您需要在过滤器架上将日期和/或时间设置为相对日期或时间。

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

Tableau Public 上的工作簿设置—作者截图

警报

工作簿发布后,任何具有访问权限的人都可以设置通知。首先,突出显示您想要监控的数据元素。在这种情况下,我希望在士力架用完时得到提醒。我还可以在 Bowl 泳道中设置总数警报。

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

在已发布的工作簿上设置警告—作者截屏

当满足警报条件时,您会收到一封电子邮件。

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

有人提醒我跑去拿最后一块士力架!—作者截图

多甜啊?

结论

不要让数据的变化让你吃惊。设置警报只需一分钟。第一个知道!如果有问题,您可以在任何人注意到之前解决它。

参考:

[## 从 Tableau Online 或 Tableau Server 发送数据驱动的警报

当数据达到您业务的重要阈值时,数据驱动的警报会自动向以下人员发送电子邮件通知…

help.tableau.com。](https://help.tableau.com/current/pro/desktop/en-us/data_alerts.htm)

如何使用 Atom 为数据科学创建最棒的开发环境?

原文:https://towardsdatascience.com/how-to-create-the-most-awesome-development-setup-for-data-science-using-atom-261113b46be8?source=collection_archive---------8-----------------------

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

令人敬畏的 Atom 功能使其成为 Python 的优秀编辑器

Github + Markdown +堆栈溢出+自动完成+ Jupyter

在我开始这篇文章之前,我只想说我喜欢 iPython 笔记本,Atom 在任何方面都不是 Jupyter 的替代品。笔记本为我提供了一个界面,在这里我不得不一次思考编码一个代码块,我喜欢这样称呼它,它帮助我更清晰地思考,同时帮助我使我的代码更加模块化。**

然而,Jupyter 目前的形式并不适合某些任务。最突出的是当我不得不处理.py文件的时候。一个需要合作的人。py 文件,每当他们想把你的代码推向生产或改变别人的代码。所以,直到现在,我用 sublime text 编辑 Python 文件,我发现它非常优秀。但是最近,当我查看 Atom 编辑器时,当我看到它提供的多个开箱即用选项时,我的忠诚度似乎发生了转变。

现在,Atom 的真正力量来自您可以安装的各种包。在这篇文章中,我将讨论帮助 Atom 成为有史以来最易被黑客攻击和最健康的开发环境的包。

安装 Atom 和一些开始的调整

在我们开始之前,我们需要安装 Atom。你可以在主网站这里做。无论您的平台是什么,安装过程都非常简单。对于 Linux,我只是下载了.deb文件,双击它。一旦你安装了 Atom,你可以看看做一些调整:

  • 使用Ctrl+Shift+P打开 Atom 中的核心设置,并在其中键入设置。这个Ctrl+Shift+P命令将成为 Atom 中最重要的命令之一,因为它允许您导航和运行许多命令。

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

使用 Ctrl+Shift+P 访问设置窗口

  • 现在进入Editor菜单,取消勾选Soft Tabs。这样做是为了使TAB键注册为TAB而不是两个空格。如果需要,您也可以激活“Soft Wrap”,如果文本超出窗口宽度,它会自动换行。

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

我首选的软包装和软标签设置。

现在,我们已经安装了 Atom,我们可以看看它提供的一些最棒的包。而其中最重要的是 GitHub。

1.不离开编辑器提交到 Github

您是否厌倦了每次向 Github 提交时都离开文本编辑器使用终端?如果您的答案是肯定的,Atom 通过让您无需离开文本编辑器窗口就可以提交来解决这个问题。

这是将我从崇高文本推向 Atom 的主要特征之一。我喜欢 Atom 预装的这一功能,并且设置它不需要太多时间。

要开始使用它,请点击 Atom 屏幕右下方的 Github 链接,Atom 屏幕会提示您登录您的 GitHub 以提供访问。这是一次性的设置,一旦您登录并将生成的令牌交给 Atom,您将能够从 Atom 屏幕本身推送您的提交,而无需导航到终端窗口。

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

点击 GitHub,然后登录

推送提交的过程是:

  • 更改任何文件或多个文件。
  • 点击右下角的 Git。
  • 上演变革
  • 编写提交消息。
  • 点击右下角的推送。
  • 我们完成了:)

下面,我将一个非常简单的提交推送到 Github,在这里我将一个标题添加到我的 Markdown 文件中。这是一个 GIF 文件,所以可能需要一些时间来加载。

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

在 Atom 中提交

2.用实时预览写减价

每当我为自己的网站写博客时,我总是在媒体编辑和 Markdown 之间左右为难。首先,当我不得不在帖子中使用数学符号或使用自定义 HTML 时,我更喜欢使用 Markdown。但是,我也喜欢媒体编辑器,因为它是所见即所得(所见即所得)。有了 Atom,我终于找到了完美的 markdown 编辑器,它为我提供了 Markdown 和 WYSIWYG。现在它已经成为我为 GitHub 创建任何 README.md 文件的默认选项。

在 Atom 中使用 Markdown 也是小菜一碟,默认情况下是激活的。要在 Atom 中查看 Markdown 的实时预览:

  • 使用Ctrl+Shift+M打开降价预览窗格。
  • 您在文档中所做的任何更改都将近乎实时地反映在预览窗口中。

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

降价分屏编辑器

3.小地图——大型代码文件的导航地图

到目前为止,我们还没有给 Atom 安装任何新的包,所以让我们安装一个基础包作为我们的第一个包。这个包被称为小地图,它是我在崇高的文字时代喜欢拥有的东西。它让你有一个侧面板,你可以点击并到达代码的任何部分。对于大文件非常有用。

要安装软件包,你可以去设置,然后点击安装软件包。Ctrl_Shift+P > Settings > + Install > Minimap> Install

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

安装小地图或任何软件包

一旦你安装了这个包,你就可以在你的屏幕上看到这个小地图。

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

侧边栏轻松导航大文件

4.在文本编辑器中使用函数定义的 Python 自动完成

一个编辑器永远不会真正完整,除非它为你提供一些你喜欢的语言的自动完成选项。Atom 与 Kite 集成得很好,Kite 尝试集成 AI 和 autocomplete。

因此,要启用 Kite 的自动完成功能,我们可以在 Atom 中使用名为[autocomplete-python](https://atom.io/packages/autocomplete-python)的包。安装步骤与之前相同。即Ctrl+Shift+P > Settings > + Install > autocomplete-python> Install。你也会看到使用风筝的选项。我通常最终使用 Kite 而不是 Jedi(另一个自动完成选项)。这是使用 Kite 自动完成功能处理 Python 文档时的样子。

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

使用 Kite 的自动完成功能也可以让你看到函数定义。

5.Hydrogen —在 Jupyter 环境中运行 Python 代码

想在带有 Jupyter 内核的 Atom 编辑器中运行 Python 吗?这也有办法。我们只需要用和以前一样的方法安装氢气。安装氢气后,您可以通过以下方式使用它:

  • 使用Ctrl+Enter运行光标所在的命令。
  • 从内核选择屏幕中选择任意内核。我从列表中选择pyt内核。
  • 现在我可以继续在pyt内核中工作了。

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

使用 Ctrl+Enter 运行命令会询问您使用哪个环境。

有时,您可能在 Atom 中看不到环境/内核。在这种情况下,您可以安装 ipykernel,使该内核对 Jupyter 和 Atom 可见。

下面是如何在 Jupyter/Atom 中创建一个新内核并使其可见的方法:

**conda create -n exampleenv python=3.7
conda activate exampleenv
conda install -c anaconda ipykernel
python -m ipykernel install --user --name=exampleenv**

一旦您运行这些命令,您的内核将被安装。现在,您可以使用以下命令更新 Atom 的内核列表:

Ctrl+Shift+P >Hydrogen: Update Kernels

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

您的内核现在应该可以在 Atom 编辑器中使用了。

6.文本编辑器中的搜索堆栈溢出

堆栈溢出是任何开发人员生活中不可或缺的一部分。但你知道麻烦是什么吗?离开编码环境,去 Chrome 搜索你需要做的每一件简单的事情。结果我们一整天都在这样做。那么,如果我们可以从 Atom 访问堆栈溢出呢?你可以通过"ask-stack"包准确地做到这一点,它让你在 SO 上搜索问题。我们可以使用Ctrl+Alt+A来访问它

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

使用 Ctrl+Alt+A 访问 Atom 中的堆栈溢出。

您可以使用的其他一些值得尊敬的软件包有:

  • 电传 : 做配对编码。
  • Linter: 检查代码的风格和编程错误。要在 Python 中启用林挺,可以使用“ linter ”和“Python-linters”。
  • 高亮显示选中的 : 通过双击或用光标选择文本来高亮显示文本的所有出现。
  • 原子-文件-图标 :在左侧树形视图中提供文件图标。看起来比以前好多了,对吧?

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

文件图标

结论

在这篇文章中,我谈到了如何在 Python 开发流程中使用 Atom。

Atom 中还有很多您可能喜欢的其他,您可以看看它们,让您的环境更加可定制。或者一个甚至可以像 Atom 一样编写自己的包的人被称为 【最可黑客攻击的编辑器】

如果你想学习 Python,但又不完全是 Python 编辑器,我想向你推荐密歇根大学的一门优秀的中级 Python 课程。一定要去看看。还有,这里是我的课程推荐2020 年成为数据科学家。

将来我也会写更多初学者友好的帖子。在 媒体 关注我,或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系到我。

此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。

如何使用 GANs 创建独特的神奇宝贝

原文:https://towardsdatascience.com/how-to-create-unique-pokémon-using-gans-ea1cb6b6a5c2?source=collection_archive---------18-----------------------

以及如何让它变得更好的想法

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

我儿子真的很喜欢口袋妖怪。我不明白,但我想这是题外话。不过,我确实开始想知道,我是否可以利用深度学习自动为他创建新的口袋妖怪卡片。

我最终成功地使用生成对抗网络(GANs)生成了类似口袋妖怪的图像,我想其他人可能会喜欢看到这个过程。

生成对抗网络

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

来源

我不想花太多时间讨论什么是 gan,但上面的图像是对过程的一个非常简单的解释。

你训练两个网络——一个鉴别器和一个生成器。生成器学习如何接受随机噪声并生成看起来像来自训练数据的图像的图像。它通过将其生成的图像馈送到鉴别器网络来做到这一点,该鉴别器网络被训练来辨别真实图像和生成的图像。

生成器被优化以越来越好地欺骗鉴别器,而鉴别器被优化以越来越好地检测生成的图像。因此,两者共同提高。

如果你想了解更多,你可以通过谷歌找到许多令人惊叹的文章、书籍和 YouTube 视频。

所以——我的假设是,我可以用真实的口袋妖怪图像作为我的训练集来训练 GAN。结果将是一个发电机,然后将能够创造新的口袋妖怪!太棒了。

数据

我的第一个挑战是寻找口袋妖怪的图像。幸运的是,Kaggle 数据集拯救了我们!

有人已经想到了一个类似的想法,虽然听起来他在生成新的口袋妖怪图像方面没有太大的成功,但是因为他花了时间收集 800 多张图像,他决定将它们上传到 Kaggle 数据集

这节省了我大量的时间。

我还了解到,实际上只有大约 800 个口袋妖怪,所以不可能用额外的口袋妖怪来扩展这个数据集。

以下是其中一幅图像的示例(256 x 256):

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

该算法

现在我有了数据,我必须选择我想要使用的 GAN 类型。可能存在数百种不同的 GAN,但我在过去使用 DCGAN 时看到了很好的结果。

DCGAN 从神经网络中消除任何完全连接的层,使用转置卷积进行上采样,并用卷积步长(以及其他)替换最大池。

我喜欢 DCGANs,因为与我尝试过的其他 gan 相比,它们似乎更健壮,因此更容易训练,而无需对超参数进行重大调整。

事实上,DCGAN 是如此受欢迎,以至于 PyTorch 有一个非常好的实现作为它的例子之一。最棒的是,他们的例子可以直接从文件夹中读取输入。因此,通过下面的命令,我可以开始训练我的 GAN:

python main.py --dataset folder --dataroot ~/Downloads/pokemon/  --cuda --niter 10000 --workers 8

这个命令从~/Downloads/pokemon 文件夹中读取图像,在我的 GPU 上运行,有 8 个工人加载数据,并运行 10,000 次迭代。

事实证明 10,000 次迭代对这个问题来说太多了,但是我想看看我能把它推进多远。我们来看看吧!

结果呢

第一步从一无所知的网络开始,所以产生的都是噪音:

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

每个盒子是一个 64 x 64 像素的图像,并试图从我们的生成器生成一个口袋妖怪。由于我们的网格是 8 x 8,我们有 64 个不同的口袋妖怪试图生成。我将图像缩小到 64 x 64,因为当试图生成更大的图像时,这种算法变得不稳定(或者至少对我来说是这样)。

50 个纪元后,我们开始看到一些生命:

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

150 年后,事情变得更清楚了:

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

3700 后,你有一些中途体面的 64 x 64 尝试口袋妖怪。在这之后,它开始转向更坏的结果:

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

现在——我知道你在想什么,那些看起来一点也不像口袋妖怪!

我想请你把浏览器缩小到 25%左右,再看一遍。从远处看,它们和真正的口袋妖怪惊人地相似。

问题是,由于我们是在 64 x 64 的图像上进行训练,鉴别器很容易被形状和颜色都像口袋妖怪的图像所欺骗,因此生成器不需要改进。

后续步骤

在我看来,显而易见的下一步是训练更高分辨率的 GAN。事实上,我已经在这方面做了一些尝试。

我的第一次尝试是重写 PyTorch 代码,以缩放到 256 x 256 的图像。代码起作用了,但是 DCGAN 坏了,我无法稳定训练。我相信这主要是因为我只有大约 800 张图片。虽然我做了一些数据扩充,但这不足以训练更高分辨率的 DCGAN。

然后,我尝试使用一个相对论 GAN ,它已经成功地用小数据集对高分辨率数据进行了训练,但也无法正常工作。

我将继续尝试一些其他的想法来生成更高分辨率的口袋妖怪,如果我得到一些工作,我会张贴我使用的技术。

别的不说,也许我们可以把这些生成的口袋妖怪叫做烟雾型口袋妖怪?

你也可以在这里找到这个故事。

有兴趣了解有关 Python 数据分析和可视化的更多信息吗?查看我的课程

如何在 Python 中创建用户定义的函数

原文:https://towardsdatascience.com/how-to-create-user-defined-functions-in-python-e5a529386534?source=collection_archive---------2-----------------------

通过定义您自己的函数来提升您的 Python 游戏

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

拉杆脚轮

你有没有想过,“我希望 Python 有一个做 ________ 的函数。”填空。如果是这样,我有个好消息!Python 让您能够创建自己的自定义函数。有几件事你需要明白,但这并不难做到。所以让我们开始吧。

自定义函数是很好地打包可重用代码块的好方法。在最基本的层面上,自定义函数只需要五个组件:

  1. 使用 def 关键字开始函数定义。
  2. 说出你的函数。
  3. 提供一个或多个参数。*实际上参数是可选的,但是括号不是。*后跟冒号。
  4. 输入代码行,让你的函数做任何事情。输入代码,此处的 #逻辑如下面的示例代码所示。
  5. 在函数末尾使用 return 关键字返回输出。这也是可选的。如果省略,该函数将返回 None。

如您所见,函数的基本框架很简单。让我们停止玩理论思维,创建一个实际的功能。

函数名

每个函数都需要一个名字。否则,当您需要使用它时,就无法在代码中引用它。给你的函数起一个直观的名字。如果您的函数的目的是对您通过参数列表发送给它的所有数字求和,请将其命名为 add_nums()sum_the_numbers() 。不要将其命名为 s()function1()。最后两个是糟糕的选择。记住,代码是由人类阅读的。

此外,函数名后面必须跟一组括号。如果你不需要任何参数,括号将是空的,但它们必须存在。然后用冒号结束定义行。冒号表示该行下面的任何缩进行都是函数的一部分。

因素

一旦命名了函数,就要决定所需的参数。参数或自变量用于将相关数据传递给函数。这个函数能把多少个数字加在一起?如果没有提供参数,将使用默认值吗?论点的顺序是什么?

参数被插入到函数名后面的括号中。它们由逗号分隔。同样,使用直观的名称,这样您可以很容易地回忆起每个参数的用途。

如果我们的函数只将两个数相加,我们可以创建两个参数, num1num2 。如果我们改变函数来添加三个数字,我们可以添加第三个参数, num3

如果您选择为参数分配默认值,只需将当前参数名称替换为 num1=0num2=0 。0 应该替换为您想要分配的任何默认值。

通常,当你执行一个函数时,你会使用一行类似于 sum_the_numbers (5,3) 的代码来调用它。通过提供默认值,您可以从代码的执行行中省略一个或多个参数,函数仍然会运行,只使用默认值。

逻辑

现在让我们给函数添加一些逻辑。这就是函数将数字相加的原因。如果您正在执行一个简单的任务,例如将两个数字相加,这一部分可能会很短。或者,对于更复杂的任务,这一部分可能有数百行代码。记住,作为函数一部分的所有代码行都必须像下面的 total = num1 + num2 行一样缩进。

返回值

既然您的代码已经完成了规定的工作,您可能需要也可能不需要向调用您的函数的进程返回值。如果不需要返回值,可以省略 return 语句。然而,在这个示例函数中,我们需要返回总和。该行是返回总计

return 语句将存储在 total 中的值发送回执行该函数的代码段。通常会有一个变量来存储返回值。例如,求和= sum_the_numbers (5,3) 。该函数返回的值将存储在求和变量中。现在我们已经拥有了成功实现函数的所有必要组件,让我们看看如何在代码段中执行它。

执行功能

每当我们执行一个用户定义的函数时,我们使用带有任何必需参数的函数名。如果函数返回值,我们通常会对它的输出做一些事情。我们可以把它打印出来,存储在一个变量中,或者发送到另一个函数中。假设我们要将输出存储在一个变量中,我们的函数执行可能类似于下面的代码。

如果我们选择将返回值直接打印到屏幕上,我们可以使用下面的代码。

请记住,当您调用您的函数时,参数必须按照您在函数定义中列出的顺序提供, num1 后跟 num2 。但是,如果您忘记了顺序,只要在执行函数时指定参数关键字,就可以更改顺序。当使用参数关键字时,该命令将类似于 sum_the_numbers (num2=5,num1=10)

不确定数量的参数

我相信你已经看出我们设计的问题了。每次我们希望添加更多的数字时,我们都需要添加另一个参数。但是有一种方法可以处理函数中无限多的参数。使用*args 技术,而不是在函数定义的括号中列出每个参数名。

当一个*跟在一个参数名后面时,它表示可以向该函数传递任意数量的参数。这将创建一个参数值列表。您只需在函数中解包 args 列表。我们功能上的这一小小变化使它变得更加灵活。

把所有的放在一起

通常,用户定义的函数和执行它的代码在同一个 Python 脚本中。在我们的例子中,整个脚本看起来像这样。

标准的用户定义函数使用起来很简单,但是对于开发人员来说是一个非常强大的工具。当然,用户定义的函数不会因为这种标准方法而停止。如果你在网上或者从深夜的电视购物节目中买东西,你会期望花 19.95 美元得到更多。用户定义的函数也是如此。

匿名函数

如果你喜欢标准的用户定义函数,你会喜欢匿名的用户定义函数。这些函数是在您需要的地方内联编写的,没有名称,也没有适当的定义语法。这些函数也被称为理解函数或λ函数。

对于这个例子,假设我们的场景和上面一样。我们需要一个能将两个数相加的函数。我们可以使用 lambda 函数来代替 sum_the_numbers 函数。

Lambda 是用来定义这些函数的 Python 关键字,而不是 def 。因此,它们通常被称为λ函数。

在这个 lambda 函数的例子中,我们将变量 answers 定义为函数本身。然后,当我们引用变量名时,我们只需传入所需的参数。结果是一个伪装成动态变量的匿名函数。

简而言之,匿名函数的语法是lambda argument _ list:expression

让我们的例子更进一步,假设这个场景从一个数字列表开始。我们需要通过平方第一个列表中的每个数字来创建一个新的数字列表。我们可以像上面那样创建一个标准的用户定义函数来完成这个任务。但是,我们决定使用匿名函数。

为了遍历列表,我们使用 Python 的 map 函数。map 函数有两个参数。第一个是函数。在这种情况下,它将是一个匿名函数。第二个参数是一些可迭代的数据,比如我们要平方的数字列表。map 函数将获取 iterable 中的每一项,通过指定的函数运行它,并将输出附加到一个新的 iterable 数据结构中。

这段代码中的 list() 函数将 map 函数的默认可迭代输出(map 对象)转换为 Python 列表。列表在我们代码的其余部分更容易使用。

同样,你可以看到,与下面使用的标准方法相比,我们的 lambda 代码相对较短。

结论

投入必要的时间来学习如何用 Python 实现用户定义的函数。他们很强大。他们创建可重用的代码块。他们帮助组织你的代码。如果您开始使用面向对象编程技术,它们是绝对必要的。用户自定义函数是现代开发人员必备的工具。

如何在 Python 中使用地理空间数据创建 Voronoi 区域

原文:https://towardsdatascience.com/how-to-create-voronoi-regions-with-geospatial-data-in-python-adbb6c5f2134?source=collection_archive---------7-----------------------

地理数据科学

在 Python 中创建和绘制 Voronoi 图的逐步指南

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

安迪·福尔摩斯在 Unsplash 上的照片

假设你打算步行去车站取一辆小型摩托车。附近有很多车站。你应该去哪家取滑板车骑?

最近的车站,对!

但是,你怎么知道离你家最近的车站呢?

输入 Voronoi 图。

Voronoi 图是多边形的集合,所有点都在最接近单个对象的平面上。

换句话说,每个多边形分区都与一个对象相关联,并且包含与该对象最近的所有点。

应用程序

Voronoi 图的应用很多,通常包括确定哪个特征最接近任何给定点。例如,确定在邻近区域的给定点上哪所学校最近。或者哪个手机发射塔离我手机最近才能打电话。

据说,1854 年约翰·斯诺绘制的霍乱爆发图在五天内导致 500 人死亡,该图在一张图表上绘制了水泵数据,并有效地构建了伦敦内部街区的 Voronoi 图。

我们不能在这里列出 Voronoi 图所有可能的用例。尽管如此,它的应用是深远的,包括人类学和考古学,统计学和数据分析,市场营销和气象学。这里有一长串它的应用

用 Python 创建 Voronoi 区域

在本教程中,我们使用幼儿园数据集创建一个 Voronoi 图。该数据集包含瑞典乌普萨拉县的所有幼儿园。为了创建 Voronoi 图,我们将使用几个库,包括 GeopandasGeovoronoi

让我们先导入库并读取数据。

import numpy as np
import geopandas as gpd
import contextily as ctx
import matplotlib.pyplot as pltfrom shapely.ops import cascaded_unionfrom geovoronoi.plotting import subplot_for_map, plot_voronoi_polys_with_points_in_area
from geovoronoi import voronoi_regions_from_coords, points_to_coordsgdf = gpd.read_file("data/preschools.shp")
gdf.head()

如数据的前几行所示,我们有一个几何列,其中包含点和一些其他属性,如县、邮政地址等…

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

学前教育数据

我们可以绘制点数据。为了给出一些背景,我们还读取了县的边界,并在其上绘制了点。

boundary = gpd.read_file(“data/uppsala.shp”)fig, ax = plt.subplots(figsize=(12, 10))
boundary.plot(ax=ax, color=”gray”)
gdf.plot(ax=ax, markersize=3.5, color=”black”)
ax.axis(“off”)
plt.axis(‘equal’)
plt.show()

输出是显示瑞典乌普萨拉县所有幼儿园(黑点)的地图。

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

乌普萨拉的幼儿园

在我们计算 Voronoi 区域之前,我们需要确定两件事。首先,我们需要检查数据的投影,然后将其转换为 Web 墨卡托投影(epsg=339599。

boundary = boundary.to_crs(epsg=3395)
gdf_proj = gdf.to_crs(boundary.crs)

其次,我们需要将数据准备成 Geovoronoi 库可以使用的格式。这里,我们将边界几何转换为多边形的并集。我们还将 Geopandas 点对象的地理序列转换为 NumPy 坐标数组。

boundary_shape = cascaded_union(boundary.geometry)coords = points_to_coords(gdf_proj.geometry)

计算 Voronoi 区域

现在,我们已经准备好了数据,我们可以简单地使用 Geovoronoi 的方法 voronoi_regions_from_coords()来计算 Voronoi 区域。

# Calculate Voronoi Regions
poly_shapes, pts, poly_to_pt_assignments = voronoi_regions_from_coords(coords, boundary_shape)

输出包含形状、点以及两者之间的标识链接。

绘制 Voronoi 图

为了绘制 Voronoi 图,我们还使用了 geo Voronoi—**plot _ Voronoi _ polys _ with _ points _ in _ area()的功能。**这里,我们提供了上述 Voronoi 计算的所有输出和边界形状。

fig, ax = subplot_for_map()plot_voronoi_polys_with_points_in_area(ax, boundary_shape, poly_shapes, pts, poly_to_pt_assignments)ax.set_title('Voronoi regions of Schools in Uppsala')plt.tight_layout()
plt.show()

输出是一个 Voronoi 图,它将学校点划分为离每个位置最近的区域。

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

Voronoi 图

上面的地图很小,但好处是我们可以使用熟悉的 Matplotlib 接口来调整它。让我们先看看 plot _ Voronoi _ polys _ with _ points _ in _ area()函数的参数和文档。

plot_voronoi_polys_with_points_in_area**(
**    ax**,
**    area_shape**,
**    poly_shapes**,
**    points**,
**    poly_to_pt_assignments**=None,
**    area_color**='white',
**    area_edgecolor**='black',
**    voronoi_and_points_cmap**='tab20',
**    voronoi_color**=None,
**    voronoi_edgecolor**=None,
**    points_color**=None,
**    points_markersize**=5,
**    points_marker**='o',
**    voronoi_labels**=None,
**    voronoi_label_fontsize**=10,
**    voronoi_label_color**=None,
**    point_labels**=None,
**    point_label_fontsize**=7,
**    point_label_color**=None,
**    plot_area_opts**=None,
**    plot_voronoi_opts**=None,
**    plot_points_opts**=None,
)**
**Docstring:**
All-in-one function to plot Voronoi region polygons `poly_shapes` and the respective points `points` inside a
geographic area `area_shape` on a matplotlib Axes object `ax`. By default, the regions will be blue and the points
black. Optionally pass `poly_to_pt_assignments` to show Voronoi regions and their respective points with the same
color (which is randomly drawn from color map `voronoi_and_points_cmap`). Labels for Voronoi regions can be passed
as `voronoi_labels`. Labels for points can be passed as `point_labels`. Use style options to customize the plot.
Pass additional (matplotlib) parameters to the individual plotting steps as `plot_area_opts`, `plot_voronoi_opts` or
`plot_points_opts` respectively.

如您所见,我们可以使用许多参数来格式化可视化。文档也非常清晰和有用。

我们可以增加点的图形大小和标记大小。我们也可以使用 Matplotlib Colormap 改变颜色。这只是一种方式,还有其他方式可以调整,我留给你。

fig, ax = plt.subplots(figsize=(14,12))plot_voronoi_polys_with_points_in_area(ax, boundary_shape, poly_shapes, pts, poly_to_pt_assignments,
 voronoi_and_points_cmap=’tab20c’,
 points_markersize=20)ax.set_title(‘Upssalla Preschools — Voronoi Regions’)
ax.axis(“off”)
plt.tight_layout()
plt.show()

现在的输出贴图与之前的默认贴图相比要好得多。

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

沃罗诺伊——乌普萨拉幼儿园

结论

Voronoi 图是有用的,并且在许多地理应用中广泛使用。在本教程中,我们已经介绍了如何使用 Python 创建 Voronoi 图。

本文的代码和数据可以在这个 Github 存储库中找到。

[## shakasom/voronoi

用 Python 制作 Voronoi 图。在 GitHub 上创建一个帐户,为 shakasom/voronoi 的发展做出贡献。

github.com](https://github.com/shakasom/voronoi)

如何创建你的第一个机器学习模型

原文:https://towardsdatascience.com/how-to-create-your-first-machine-learning-model-4c8f745e4b8c?source=collection_archive---------4-----------------------

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

凯尔西·奈特在 Unsplash 上的照片

用 Python 创建简单机器学习模型的指南

许多机器学习教程专注于机器学习工作流的特定元素,如数据清理、模型训练或算法优化。然而,如果你是机器学习的新手,没有完整简单的解释或演练,很难完全掌握基本的端到端工作流。

在下面的帖子中,我将提供一个非常简单的教程,用 python 开发一个有监督的机器学习模型。在这篇文章中,我将假设你只有非常基本的 python 编程知识,并且已经安装了一些常用的数据科学库。如果你首先需要一个关于数据科学的 python 介绍, Codeacademy 是一个不错的起点。我还将提供教程中包含的所有库的文档链接。

什么是机器学习?

机器学习是计算机能够学习一些输入(数据特征)和一些已知输出(数据标签)之间的映射而无需显式编程的能力。目标是,给定未知输出的新输入,机器可以正确预测标签。

“机器学习本质上是一种事物标签.”, 卡西科兹尔科夫

这种输入到输出的映射由数学函数执行,主要来自线性代数和微积分领域,其执行速度和规模在没有大量计算能力的情况下是无法实现的。有许多不同的算法可以完成这项任务,从简单的基于回归的方法到更复杂的深度学习技术。

幸运的是,python 编程语言有一个非常活跃的开源开发者社区,他们构建了许多库,这些库抽象出了直接编写这些算法的需求。其中一个核心的机器学习库是 scikit-learn ,对于初学者来说非常容易访问。在本教程中,我将关注这个库。

数据

为了简单起见,我将使用机器学习来解决一个分类问题。我将使用 scikit-learn API 中的一个玩具数据集,该数据集包含三种类型的葡萄酒(标签或目标)的许多葡萄酒属性(特征),如酒精度和颜色。

要加载数据并将其转换为 pandas 数据框,请使用如下所示的代码。

from sklearn.datasets import load_wine
import pandas as pdwine = load_wine()
data = pd.DataFrame(data=wine['data'], columns = wine['feature_names'])
data['target'] = wine['target']
data.head()

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

因为机器学习算法是基于数学的,所以用于机器学习的数据本质上必须是数字。这个数据集完全是数字的,但是,如果我们有分类特征,我们将需要执行一些预处理来首先将它们转换成数字。我选择了这个数据集,这样我就可以展示开发模型的最简单的工作流,而不用引入更多关于数据预处理的高级概念。

测试列车分离

在开发机器学习模型时,重要的是能够评估它能够将输入映射到输出并做出准确预测的能力。但是,如果您使用模型已经看到的数据(例如,在训练期间)来评估性能,那么您将无法检测诸如过度拟合之类的问题。

过度拟合是指模型在训练数据中学习了过多的细节或噪音,而这些不一定存在于看不见的数据中。在这种情况下,模型在训练数据上表现良好,但在看不见的数据上表现不佳。这通常被称为模型不能很好地概括。

机器学习中的一个标准是,首先把你的训练数据分成一组用于训练,一组用于测试。对于要进行的精确大小划分没有规则,但是为训练保留更大的样本是明智的——典型的划分是 80%训练数据和 20%测试数据。

重要的是,数据也是随机分割的,这样您就可以很好地表示两组数据中存在的模式。Scikit-learn 有一个工具可以在一行代码中完成这个过程,这个工具叫做 test_train_split 。下面的代码将特性和目标数据传递给函数,并指定 20%的测试大小。

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(data.drop('target', axis=1), data['target'], test_size=0.20, random_state=0)

基线模型

接下来训练一个虚拟分类器以获得基线分数来为模型开发的进一步迭代设定基准是一个好主意。Scikit-learn 有一个功能,允许你训练一个模型,并根据简单的规则进行预测,比如随机预测。这有助于评估您的模型开发在您迭代后续步骤时是否有所改进。

在下面的代码中,我训练了一个虚拟分类器,它总是预测最频繁出现的类。然而,虚拟分类器对此有许多不同的方法。准确度分数是 0.44。完美的准确度分数应该是 1.0。现在进入下一阶段,我们将知道我们是否在这个基线上有所改进。

from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_scorebaseline = DummyClassifier(strategy='most_frequent', random_state=0).fit(X_train, y_train)
y_pred = baseline.predict(X_test)
print(round(accuracy_score(y_test, y_pred),4))

型号选择

现在我们有了一个训练好的基线模型,我们需要评估是否有另一种算法可以更好地处理我们的数据。Scikit-learn 有这个有用的备忘单,它将让你了解解决分类问题的不同算法。

下面的代码循环遍历一系列分类算法,并打印出结果分数。输出显示在代码下方。

from sklearn.metrics import accuracy_score, log_loss
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC, LinearSVC, NuSVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysisclassifiers = [
    KNeighborsClassifier(3),
    SVC(kernel="rbf", C=0.025, probability=True),
    NuSVC(probability=True),
    DecisionTreeClassifier(),
    RandomForestClassifier(),
    AdaBoostClassifier(),
    GradientBoostingClassifier()
    ]for classifier in classifiers:
    model = classifier.fit(X_train, y_train)
    print(classifier)
    print("model score: %.3f" % model.score(X_test, y_test))

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

我们可以看到,RandomForestClassifier 对于该模型表现最佳,因此我们将选择该算法来训练我们的最终模型。

超参数优化

每个机器学习算法都有大量的参数用于控制学习过程。这些参数可以更改,并且根据数据集可以提高模型的性能。为算法和数据集寻找最佳参数集的过程被称为超参数优化

从上一节运行的代码中我们知道,随机森林分类器在我们使用的数据集上表现最好。如果你看一下这个模型的文档,你会发现这个算法有很多参数可以调整。

超参数优化的一种常用方法是网格搜索。Scikit-learn 提供了一个名为 GridSearchCV 的函数来执行这个任务。我们需要向这个函数传递一个 python 字典形式的网格,其中包含参数名和相应的参数列表。这就变成了函数将要搜索的参数空间。

然后,该函数将为给定分类器的每个参数组合建立一个模型。一旦完成,您将能够以最佳模型和最佳参数组合的形式获得结果。

为了简单起见,在下面的例子中,我选择只调整四个参数。它们如下:

n_estimators: 模型中树的数量。

max_depth: 树的最大深度。

min_samples_split: 节点被拆分前,节点中数据点的最小个数。

min_samples_leaf: 每片叶子中数据点的最小数量。

下面的代码执行超参数调整,并打印最佳模型得分和参数组合。

from sklearn.model_selection import GridSearchCVn_estimators = [100, 300, 500, 800, 1200]
max_depth = [5, 8, 15, 25, 30]
min_samples_split = [2, 5, 10, 15, 100]
min_samples_leaf = [1, 2, 5, 10]param_grid = dict(n_estimators = n_estimators, max_depth = max_depth,  
              min_samples_split = min_samples_split, 
             min_samples_leaf = min_samples_leaf)rf = RandomForestClassifier()grid_search = GridSearchCV(estimator=rf, param_grid=param_grid)
best_model = grid_search.fit(X_train, y_train)print(round(best_model.score(X_test, y_test),2))
print(best_model.best_params_)

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

最终评估

最后,我们使用最佳模型来预测测试集上的标签,并打印分类报告来详细评估其性能。我们可以看到,与基线模型相比,整体性能有了很大的提高。

from sklearn.metrics import classification_reporty_pred_best = best_model.predict(X_test)
print(classification_report(y_test, y_pred_best))

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

在本文中,我展示了开发机器学习模型所需的最简单的工作流程。开发一个模型通常需要更多的步骤,尤其是当您使用真实世界的数据集时。其中包括数据清理、特征工程和交叉验证等许多可能的步骤。一旦你掌握了这篇文章中的基本步骤,你就可以继续学习机器学习中涉及的其他元素。

在本文中,我只讨论了分类,但对于其他类型的机器学习的简要概述,请参见— 三种机器学习类型的初学者指南

如果你对学习数据科学感兴趣,可以在这里看到我的学习数据科学的完全免费资源列表— 如何免费学习数据科学

感谢阅读!

如何创建自己的聊天机器人

原文:https://towardsdatascience.com/how-to-create-your-own-chatbot-a70120b34b42?source=collection_archive---------48-----------------------

使用 Dialogflow 构建对话体验

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

沃洛季米尔·赫里先科在 Unsplash 上的照片

介绍

在新冠肺炎一级防范禁闭的情况下,你有没有发现自己时不时地自言自语?别担心,我会向你展示如何创建一个聊天机器人,这样你就可以和机器人版本的你说话了。

玩笑归玩笑,聊天机器人有相当多的用例:

  1. 改善客户服务体验——使用聊天机器人,用户可以根据需要获得客户服务,而不必排队。
  2. 简化购买订单流程—使用聊天机器人,用户可以轻松购买他们想要的东西(例如购买比萨饼),而不必拨打热线电话。
  3. 自动回复——对于重复的问题,如退款问题、运输问题或支付问题,聊天机器人可以根据知识库提供回复。
  4. 减少客户服务工作量——我们可以将普通任务外包给聊天机器人,只要求客户服务人员完成更复杂的任务。
  5. 或者甚至提高自己的工作效率——你甚至可以创建一个聊天机器人来帮助你点播物品,播放你最喜欢的视频或者在你的日历上写一个任务。

有很多聊天机器人服务,但这篇文章将集中在谷歌的对话流。这篇文章将带你为我的虚构业务——pizza eiou 创建一个聊天机器人。正如你可能猜到的,我们卖比萨饼。由于我们有现金流问题,我必须确保我的聊天机器人服务是免费的。当我们不再有现金流问题时,我就可以查看他们的定价方案来升级我的聊天机器人。

代理人

聊天机器人从代理开始。我将把我的代理人命名为代理人 1 ,因为我没有足够的创造力来想出一个名字。代理负责存储意图、实体、内容和履行。简而言之,代理就是你的聊天机器人。

在转到 Dialogflow 并使用我的个人 Gmail 帐户登录控制台后,我看到了以下页面:

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

让我们继续创建一个代理:

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

意图

一旦我创建了我的代理,我将会看到两个默认的意图:

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

意图就像主题。每当我的客户向代理 1 询问某个问题时,代理 1 会尝试将问题归类到一个意图/主题下。

如果问题对 agent_1 来说太复杂,该问题将属于回退意图,其中代理将为她不理解的所有问题提供标准化回答。

第二个默认意图是欢迎意图。是的,你是对的。欢迎意向为问候 agent_1 的客户提供默认回复。

快速注释:

在这篇文章中,我将定期测试我的聊天机器人。每当我们配置代理时,我们首先要保存代理。这将允许 Dialogflow 培训我们的代理。其次,我们可以在右边的聊天中键入任何我们想要的命令。然后,我们可以观察 agent_1 的输出。

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

披萨订单

让我们为比萨饼订单创建一个意向。在任何意图中,都有训练短语。这些是客户会键入的短语。记得使用各种各样的短语,以便我们的代理可以更聪明。

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

当然,对于问题,必须有回答(暂时忽略$符号,我们稍后会谈到):

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

在测试了 agent_1 之后,我们发现它是有效的!

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

实体

agent_1 能回复披萨订单真是太好了。但是,什么是披萨?什么是培根?什么是草莓奶昔?对于 agent_1 来说,这是一个非常陌生的术语。因此,让我们定义实体。实体有助于识别句子中的何人、何事、何地、何时。

让我们定义一个实体来帮助 agent_1 理解比萨饼配料:

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

在我的 pizza_topping 实体中,我指定了 Pizzaeiou 提供的所有浇头。通过勾选“定义同义词”框,我允许不同的单词到达同一个词根,如第三行 bacon 示例所示。

通过勾选第三个框“允许自动扩展”,我们可以允许 agent_1 学习新单词。例如,如果所有客户都要求将“apple”作为比萨饼配料,agent_1 会自动将 apple 包含到该实体中。当然,没有人会喜欢苹果作为披萨的配料…因此,我不会勾选这个框。

注释训练短语

定义了我们的实体后,让我们将它投入使用。让我们在披萨上标注我们的训练短语。订购意图:

  1. 双击单词“鸡”

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

2.搜索我们预定义的 pizza_topping 实体:

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

3.Agent_1 现在将鸡肉视为披萨的配料:

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

让你的实体更有创造力

几个实体可以定义或随时可用:

  1. 系统实体—时间、日期、数字都是预定义实体的例子。您不必为它们创建实体。Dialogflow 会自动将“现在”、“下午 4 点”、“十月”标记为日期或时间实体。
  2. 复合实体——假设披萨店也卖饮料。我们当然可以把“奶昔”定义为我们的饮料。然而,我们如何定义“大杯草莓奶昔”是我们的饮料呢?当然,我们不希望 agent_1 将“大草莓奶昔”理解为“大草莓”和“奶昔”,那将是灾难性的。因此,我们可以定义一个名为 drinks_composite 的实体,并指定不同类型的订单。切记不要勾选“定义同义词”

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

当然,我们必须具体说明我们提供的口味类型:

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

缝隙填充

“我的顾客总是点披萨。我怎么知道他们想要巧克力披萨还是鸡肉披萨?!他们什么时候想要?!他们想要个人披萨还是大披萨?!"—代理 _1

Agent_1 现在已经受够了。她很难完成订单。让我们帮助她,确保我们的顾客总是提供尺寸、时间和配料:

  1. 用实体注释我们的训练短语

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

2.创建动作和参数。勾选所需参数,并定义用户未能提供参数时的提示

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

3.修改我们的回答。包括带有“$”符号的参数。

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

让我们来测试一下!(记得先保存您的代理)

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

如您所见,通过一个模糊的请求,agent_1 开始询问我们的客户以获取更多信息。

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

上下文

由于 Pizzaeiou 正面临现金流问题,我们应该开始向那些想要披萨的人追加销售饮料。目前,对话将会这样进行:

顾客:我现在想要一个小蘑菇比萨饼

代理 1:当然,你想喝点什么吗?

顾客:好的

抱歉,那是什么?

在这种情况下,没有上下文。 Agent_1 无法理解对话的流程。因此,让我们创建一个追加销售 _ 饮料 _ 是意向和一个追加销售 _ 饮料 _ 否意向。在此之前,我们必须修改我们的 pizza.order 意图,以产生一个追加销售饮料上下文:

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

数字 5 表示该上下文将持续的交互次数。然后,我们可以将我们的 upsell_drinks_yesupsell_drinks_no 意图的输入上下文设置为我们的 pizza.order 意图的输出,并指定一些示例训练短语:

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

让我们来测试一下!

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

实现

现在我们已经收到了一个订单,我们需要将其推送到一个数据存储,以便 Pizzaeiou 的厨房可以获得订单!这可以通过满足来实现。有两种履行方式:

  1. 内联编辑器:你可以通过你创建的云函数将你的订单推送到你的数据库中。这通常用于测试目的。您应该切换到 Webhook 进行部署。
  2. Webhook : Webhook 允许不同的应用程序通过 JSON 请求相互交流。订单完成后,厨房会立即收到订单详情通知。

导出代理 _1

让我们导出 agent_1,这样她就可以永远生活在云中:

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

结论

瞧啊。我们已经成功地为 Pizzaeiou 创建了一个聊天机器人。我们现在可以让我们的客户支持人员处理更复杂的问题,而不是接受订单。

为了使它完全发挥作用,考虑创造更多的意图、实体和环境,这样你的聊天机器人听起来会尽可能的人性化。也试着创建一个聊天机器人,用于介绍中提到的不同目的。

参考资料:

https://www . coursera . org/learn/conversation-experiences-dialog flow/

如何创建自己的自定义对象检测器

原文:https://towardsdatascience.com/how-to-create-your-own-custom-object-detector-766cb11ccd1c?source=collection_archive---------11-----------------------

目标检测

使用 YOLOv3 和 ImageAI 创建您的自定义对象检测器

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

伊利亚·巴甫洛夫在 Unsplash 上的照片

这篇文章旨在帮助那些想第一次开发自己的自定义对象检测器的初学者,指导他们通过所有的关键点来训练一个成功的模型。

所示的例子将用 ImageAI 进行训练,这是一个开源的 Python 库,它允许你用几行代码训练一个模型。

介绍

在本文中,我们将详细介绍创建自定义对象检测器的所有必要步骤,从收集数据到最终测试我们的模型。

整个过程的步骤是:

  1. 收集数据
  2. 标注数据集
  3. 数据扩充
  4. 培训模式
  5. 评估模型

数据采集

在我们训练我们的模型之前,我们需要收集大量的数据,在这种情况下,是图像。根据检测机的复杂程度,最少 200 张图像应该没问题。

如果我们希望我们的模型尽可能健壮,我们的图像应该在光照和背景方面彼此不同,这样模型才能更好地概括。

这些图像可以从你的手机上获取,也可以从互联网上获取。

在这里,您可以看到我的药丸探测器模型的一个子集:

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

收集数据后,我们需要调整图像的大小,因为有些图像可能会很大。更小的图像意味着我们的模型将训练得更快。

为此,我编写了以下脚本:

标签数据

这是最繁琐的一步,因为你需要在每张图像中标注出你希望模型检测到的每一个物体。

你可以用 LabelImg 库给你的数据加标签。运行以下命令从终端安装它。

pip3 install labelImg

安装完成后,我们可以通过运行以下命令开始标记数据集。

labelImg path_to_images/

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

然后,您必须为图像中的每个对象创建一个带有相应标签的矩形框。

一旦标记了图像中的所有对象,就必须将其保存为 PascalVOC 格式,生成一个. xml 文件。

数据扩充

拥有大型数据集对于我们深度学习模型的性能至关重要,因此我们可以使用 imgaug 库来扩充我们已经拥有的数据。

这个 github repo 解释并提供了关于如何在图像边界框旁边增加图像的代码。这个过程可以分为三个步骤:

  1. 转换。xml 文件合并成一个。csv 文件
  2. 应用数据增强管道
  3. 转换结果。csv 文件分成多个。xml 文件

首先,我们定义一个函数来转换我们的。xml 文件合并成一个。csv 文件:

然后我们定义另一个函数来做相反的过程:

然后,我们用 imgaug 定义一个数据增强管道,比如下面这个。

最后,我们将这个管道应用到我们的数据集,并保存增强图像及其增强标签。你还要定义 image_aug()bbs_obj_to_df() 函数,在这个 github repo 里可以找到

训练模型

在所有这些预处理之后,我们最终可以用 ImageAI 训练我们的模型。

首先,我们需要安装库。

pip3 install imageai

要使用迁移学习,可以在这里下载模型

然后,我们需要将数据集分成训练和验证文件夹。

dataset
├─ train
│   └── images
│   └── annotations
└─ validation
    ├── images
    ├── annotations

我们可以通过下面几行代码做到这一点:

然后我们可以用下面的脚本进行训练。

评估模型

一旦我们训练了我们的检测器,我们就可以通过它的映射来评估每个模型检查点的执行情况。

输出应该类似于以下内容:

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

使用我们的模型进行检测

最后,我们可以在生产中使用我们的模型来检测单个图像中的对象。

您可以调整minimum _ percentage _ probability参数,以或多或少的置信度显示检测到的对象,获得如下结果。

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

现在我想听听你的意见,让我知道它是如何工作的!

感谢阅读!

参见

[## 对象检测算法和库- neptune.ai

对象检测在图像中找到并识别事物,这是深度学习的最大成就之一…

海王星. ai](https://neptune.ai/blog/object-detection-algorithms-and-libraries)

如何为深度学习创建自己的图像数据集

原文:https://towardsdatascience.com/how-to-create-your-own-image-dataset-for-deep-learning-b53f1c22c443?source=collection_archive---------6-----------------------

弥合入门学习和现实世界应用之间的差距

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

照片由比塔·拉图兹尼亚克Unsplash 拍摄

动机

有太多的 MOOCs 声称通过带你解决经典的 MNIST 问题,让你成为深度学习/计算机视觉专家。这基本上是说,我会成为一个懂得如何打字的专业程序员。真正的专业知识是用深度学习解决自己的问题来展示的。然而,构建您自己的影像数据集本身就是一项重要的任务,而且在大多数在线课程中对它的介绍还远远不够全面。

本文的目标是帮助您收集自己的原始图像数据集,然后您可以将其用于自己的图像分类/计算机视觉项目。

要求:

  • Python :你需要在你的机器上安装一个 Python 的工作版本。(我用的是 3.7.4)
  • Linux/Unix 终端:我们将从命令行运行映像下载程序。如果你使用的是 Mac 或 Linux,那么标准终端应该没问题。(我运行的是 Ubuntu 18.04)。对于 Windows,您可能需要为 Linux 设置 Windows 子系统或找到另一个第三方终端应用程序。

步伐

信不信由你,下载一堆图片只需几个简单的步骤。

一个:使用 pip 安装谷歌图片下载器:

pip install googleimagedownloader

两个:下载谷歌 ChromeChromedriver

  • 你需要确保你得到的 Chromedriver 版本与你运行的 Google Chrome 版本一致。
  • 要检查你机器上的 Chrome 版本:打开一个 Chrome 浏览器窗口,点击右上角的菜单按钮(三个堆叠的点),然后点击“帮助”>“关于谷歌 Chrome”。

一旦你下载了 Chromedriver,一定要记下“chromedriver”可执行文件的存储位置。下一步我们需要知道它的位置。

:使用命令行批量下载图像

举个例子,假设我想建立一个可以区分蜥蜴和蛇的模型。这意味着我需要一个包含蜥蜴和蛇图像的数据集。我首先使用以下命令下载蜥蜴的图像:

$ googleimagesdownload -k "lizard" -s medium -l 500 -o dataset/train -i lizards -cd ~/chromedriver

该命令将使用关键字“蜥蜴”从谷歌图片中抓取 500 张图片。它会将这些图像输出到:dataset/train/lizards/-cd参数指向我们之前下载的“chromedriver”可执行文件的位置。

(注意:运行 500 张图像需要几分钟时间,所以我建议先用 10-15 张图像进行测试,以确保它能按预期工作)

如果打开输出文件夹,您应该会看到类似这样的内容:

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

关于如何使用google_image_downloader的更多细节,我强烈推荐查看文档

现在,要获得一些蛇的图像,我可以简单地运行上面的命令,将关键字/图像目录参数中的“蜥蜴”替换为“蛇”。

$ googleimagesdownload -k "snake" -s medium -l 500 -o dataset/train -i snakes -cd ~/chromedriver

**嘣!**只需两个简单的命令,我们现在就有 1000 张图像来训练一个模型。多酷啊。!

然而,要制作一个好的数据集,我们真的需要挖掘得更深。也许我们可以尝试用关键词来描述特定种类的蜥蜴/蛇。我们只需要认识到我们试图解决的问题,并发挥创造力。

结论

在这一点上,我们几乎没有触及开始深度学习项目的表面。我们所做的只是收集一些原始图像。如果我们想要构建一个有用的模型,仍然需要做大量的数据清理/格式化工作。构建一个好的数据集需要时间,这一点我再怎么强调也不为过。我只是希望这篇文章能够为您提供工具,帮助您克服收集图像来构建自己的数据集的最初障碍。

我希望你喜欢这篇文章。如有任何意见、问题或反馈,请联系我。我会尽力及时回复。

如何解决数据信任问题

原文:https://towardsdatascience.com/how-to-cure-data-trust-issues-49d15b9149ac?source=collection_archive---------42-----------------------

如果你在数据部门工作了一年,你可能参加过这样的会议:

分析师:“数字是 X”

商人:“但是我的另一个仪表盘显示这个数字是 Y”

分析师:希望地震能结束她的痛苦

那么,哪里出了问题?许多信息源都有不同的编号。这是怎么发生的?

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

照片由 s 托克兰在 Unsplash

这是一个组织数据需求演变的例子。利益相关者需要一些关于应用程序用户的信息。因此,她与数据团队聊天。然后,数据工程师创建一些管道,分析师编写代码来生成可视化信息的仪表板。

每次创建像仪表板这样的数据产品时,都会使用一整套假设和业务逻辑规则。例如,我们是否将搅动的用户定义为“超过 70 天不活动的用户?”或者“用户 50 天不活动?”我们是否使用表 1,它没有计算未注册的用户?还是用大一点的桌子?许多决策是在创建数据产品的过程中做出的。

因此,假设我们创建了一些跟踪用户流失的仪表板。一个月过去了,一个不同的利益相关者进来要求另一个仪表板。现在,企业领导层已经决定,被搅动的用户被定义为“50 天不活动的用户”但是,之前创建的控制面板将大量用户定义为“70 天不活动的用户”除非每个人都密切关注正在发生的事情,否则将会有两个相互冲突的数字在组织中流传。

与信息冲突相关的问题是什么?首先,企业主很难做出正确的决定。由于决策失误,企业可能会遭受损失。此外,数据分析师开始显得无能,企业领导人对他们的工作失去了信任。

解决方案:真理的单一来源

我的团队一直朝着这个天堂般的理想努力。这种涅槃被称为“真理的唯一来源”在这种状态下,您的所有数据产品(例如:仪表板、模型)都使用相同的管道、相同的业务逻辑,并且所有数字都是一致的。当然,说起来容易做起来难。而且,这需要时间和金钱。但是,这是值得的。那么,我们如何执行它呢?

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

车头拍摄

首先,停止仪表板和管道的扩散。有时候,我们向用户提供的信息越多,我们创造的价值就越多。不。这是不正确的。少即是多。拥有更少的仪表板会更好,这些仪表板相互集成并使用相同的业务逻辑。投入实际的努力来检查您创建的所有仪表板,无情地删除任何与业务规则和报告标准的当前状态不同步的内容。对数据工程管道做同样的事情。

此外,确保业务的分析和业务方面的每个人都始终相互交流。我知道我们都害怕召开更多的会议。它们看起来像是巨大的时间浪费。但是,如果做得好,会议和空闲时间更新可以让你避免很多困惑。

保持真理的单一来源是一个持续的、痛苦的但非常值得的过程。记住,没有你努力追求的完美状态。你只是想跑得快一点,跟上业务和业务报告的变化。我将引用《爱丽丝梦游仙境》中的一句话,红皇后角色说你必须奔跑才能停留在一个地方。你觉得这句话是激励人心还是相反,就看你自己了。我觉得两者都有。

“现在,在这里,你看,它需要所有你能做的运行,保持在同一个地方。如果你想去别的地方,你至少要跑两倍的速度!”

如何处理不平衡的分类,而不重新平衡数据

原文:https://towardsdatascience.com/how-to-deal-with-imbalanced-classification-without-re-balancing-the-data-8a3c02353fe3?source=collection_archive---------9-----------------------

在考虑对倾斜数据进行过采样之前,请尝试在 Python 中调整分类决策阈值

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

Elena Mozhvilo 在 Unsplash 上的照片

在机器学习中,当用一个类的实例比另一个类的实例多得多的数据建立分类模型时,初始的默认分类器通常不令人满意,因为它将几乎每个案例都分类为多数类。许多文章向您展示了如何使用过采样(例如 SMOTE )或有时使用欠采样或简单的基于类的样本加权来重新训练“重新平衡”数据的模型,但这并不总是必要的。在这里,我们的目的是展示在不使用平衡数据或重新训练模型的情况下可以做多少事情。

我们通过简单地调整阈值来做到这一点,当模型预测的类别 1 的概率在两类分类中高于它时,我们称之为“类别 1”,而不是天真地使用默认分类规则来选择哪个类别被预测为最有可能(概率阈值为 0.5)。我们将看到这是如何为您提供灵活性,在假阳性和假阴性分类之间进行任何所需的权衡,同时避免重新平衡数据所带来的问题。

我们将用 Kaggle 的信用卡欺诈识别数据集来说明。数据集的每一行代表一笔信用卡交易,目标变量 Class0 表示一笔合法交易,Class1 表示该交易结果是一笔欺诈。有 284,807 笔交易,其中只有 492 笔(0.173%)是欺诈——确实非常不平衡。

我们将使用一个梯度增强分类器,因为这些通常会给出好的结果。特别是 Scikit-Learn 的新 histgradientsboostingclassifier,因为当数据集像这样相对较大时,它比他们原来的 GradientBoostingClassifier 快得多。

首先让我们导入一些库并读入数据集。

import numpy as np
import pandas as pd
from sklearn import model_selection, metrics
from sklearn.experimental import enable_hist_gradient_boosting
from sklearn.ensemble import HistGradientBoostingClassifier
df=pd.read_csv('creditcard.csv')
df.info()

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

V1 到 V28(来自主成分分析)和交易金额是特征,它们都是数字并且没有缺失数据。因为我们只使用基于树的分类器,所以不需要标准化或规范化特征。

在将数据分成训练集和测试集之后,我们现在将训练模型。这在我的笔记本电脑上花了大约半分钟。如果验证子集的性能由于过度拟合而开始恶化,我们使用 n_iter_no_change 来提前停止训练。我单独做了一点超参数调整来选择 learning_rate 和 max_leaf_nodes,但这不是本文的重点。

Xtrain, Xtest, ytrain, ytest = model_selection.train_test_split(
        df.loc[:,'V1':'Amount'], df.Class,  stratify=df.Class, 
        test_size=0.3, random_state=42)
gbc=HistGradientBoostingClassifier(learning_rate=0.01, 
        max_iter=2000, max_leaf_nodes=6, validation_fraction=0.2, 
        n_iter_no_change=15, random_state=42).fit(Xtrain,ytrain)

现在,我们将这个模型作为默认的硬分类器应用于测试数据,预测每个事务为 0 或 1。我们将决策阈值 0.5 隐式应用于模型的连续概率预测,作为软分类器。当概率预测超过 0.5 时,我们称之为“1”,当低于 0.5 时,我们称之为“0”。

我们还为结果打印了混淆矩阵,按照惯例,认为类别 1(欺诈)是*“正”*类别,因为它是更罕见的类别。混淆矩阵显示了真阴性、假阳性、假阴性和真阳性的数量。标准化混淆矩阵比率(如 FNR =假阴性率)以百分比形式包含在括号中。

hardpredtst=gbc.predict(Xtest)
def conf_matrix(y,pred):
    ((tn, fp), (fn, tp)) = metrics.confusion_matrix(y, pred)
    ((tnr,fpr),(fnr,tpr))= metrics.confusion_matrix(y, pred, 
            normalize='true')
    return pd.DataFrame([[f'TN = {tn} (TNR = {tnr:1.2%})', 
                                f'FP = {fp} (FPR = {fpr:1.2%})'], 
                         [f'FN = {fn} (FNR = {fnr:1.2%})', 
                                f'TP = {tp} (TPR = {tpr:1.2%})']],
            index=['True 0(Legit)', 'True 1(Fraud)'], 
            columns=['Pred 0(Approve as Legit)', 
                            'Pred 1(Deny as Fraud)'])
conf_matrix(ytest,hardpredtst)

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

我们看到第 1 类的召回率(也称为敏感度或真阳性率,如上面的 TPR 所示)仅为 71.62%,这意味着 71.62%的真实欺诈被正确识别为欺诈并因此被拒绝。因此,28.38%的真实欺诈不幸被批准为合法。

特别是对于不平衡的数据(或者通常任何时候假阳性和假阴性可能具有不同的后果),重要的是不要限制我们自己使用默认的隐式分类决策阈值 0.5,就像我们在上面通过使用。预测()”。我们希望提高 1 类产品(TPR)的召回率,以减少我们的欺诈损失(减少假阴性)。为了做到这一点,当我们预测一个高于阈值的概率时,我们可以降低我们所说的“类 1”的阈值。通过这种方式,我们称“1 类”为更大范围的预测概率。这种策略被称为阈值移动

最终,我们希望在多大程度上减少这些假阴性是一个商业决策,因为作为一种权衡,假阳性(作为欺诈被拒绝的真实合法交易)的数量将不可避免地增加,因为我们调整了应用于模型概率预测的阈值(从“获得”)。predict_proba()“而不是”。预测()”)。

为了阐明这种权衡并帮助我们选择阈值,我们绘制了假阳性率和假阴性率与阈值的关系图。这是接收器工作特性 (ROC)曲线的变体,但强调了阈值。

predtst=gbc.predict_proba(Xtest)[:,1]
fpr, tpr, thresholds = metrics.roc_curve(ytest, predtst)
dfplot=pd.DataFrame({'Threshold':thresholds, 
        'False Positive Rate':fpr, 
        'False Negative Rate': 1.-tpr})
ax=dfplot.plot(x='Threshold', y=['False Positive Rate',
        'False Negative Rate'], figsize=(10,6))
ax.plot([0.00035,0.00035],[0,0.1]) #mark example thresh.
ax.set_xbound(0,0.0008); ax.set_ybound(0,0.3) #zoom in

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

虽然存在一些选择最佳阈值的经验法则或建议的度量标准,但最终它只取决于假阴性与假阳性的业务成本。例如,看上面的图,我们可以选择应用阈值 0.00035(垂直绿线已添加),如下所示。

hardpredtst_tuned_thresh = np.where(predtst >= 0.00035, 1, 0)
conf_matrix(ytest, hardpredtst_tuned_thresh)

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

我们已将假阴性率从 28.38%降至 9.46%(即识别并拒绝 90.54%的真实欺诈,作为我们新的召回或敏感度或真阳性率或 TPR),而我们的假阳性率(FPR)从 0.01%增至 5.75%(即仍批准 94.25%的合法交易)。为了只批准不到 10%的欺诈交易,拒绝大约 6%的合法交易对我们来说可能是值得的,当我们使用默认硬分类器(隐式分类决策阈值为 0.5)时,欺诈交易的比例为 28%,这是非常昂贵的。

不平衡不平衡数据的原因

避免“平衡”不平衡的训练数据的一个原因是,这种方法通过系统地增加模型对原始少数类的预测概率,偏向/扭曲了最终训练模型的概率预测,从而使这些预测成为误校准,并因此简化为仅仅是相对的序数判别分数决策函数置信度分数,而不是原始(“不平衡”)训练和测试集以及分类器可以对其进行预测的未来数据中潜在准确的预测类概率。如果训练的这种重新平衡是真正需要的,但是仍然需要数值精确的概率预测,那么人们将不得不重新校准具有原始/不平衡类别比例的数据集的预测概率,或者对来自平衡模型的预测概率应用适当的校正——参见此处的、此处的或此处的。

通过过采样来平衡数据的另一个问题(与没有这个问题的依赖于类的实例加权相反)是,它偏向于天真的交叉验证,潜在地导致在交叉验证中没有检测到的过度拟合。如果对整个训练集执行过采样,则在交叉验证中,每次数据被拆分到“折叠”子集时,一个折叠中可能会有与另一个折叠中的实例重复的实例,或者由另一个折叠中的实例生成的实例。因此,折叠并不像交叉验证假设的那样是真正独立的——存在数据“流失”或“泄漏”。例如,参见不平衡数据集的交叉验证,它描述了如何通过仅在每组训练折叠上执行过采样,在交叉验证循环内正确地重新实施交叉验证,如中所示,本例。或者,您可以在由 imb learn . pipeline . make _ pipeline()创建的管道中执行过采样,该管道通过将交叉验证循环中的过采样仅应用于训练折叠,而不应用于测试折叠来解决这一问题。在 scikit-learn 中,至少对于通过简单实例复制/重采样(不一定是 SMOTE 或 ADASYN)进行过采样的情况,该问题可以通过使用 model_selection 来解决。GroupKFold 用于交叉验证,它根据选定的组标识符对实例进行分组,该标识符对于给定实例的所有副本都具有相同的值——参见我对前述文章的回复

结论

我们可以尝试使用原始模型(在原始“不平衡”数据集上训练),并简单地绘制假阳性和假阴性之间的权衡,以选择可能产生理想业务结果的阈值,而不是天真地或隐含地应用默认阈值 0.5,或使用重新平衡的训练数据立即重新训练。

编辑:即使唯一真正的“问题”是默认的 0.5 阈值不合适,为什么重新平衡你的训练数据“有效”?

由您的模型产生的平均概率预测将近似为类 1 的定型实例的比例,因为这是目标类变量的平均实际值(其值为 0 和 1)。回归也是如此:目标变量的平均预测值有望逼近目标变量的平均实际值。当数据高度不平衡并且类别 1 是少数类别时,该平均概率预测将远小于 0.5,并且类别 1 的概率的绝大多数预测将小于 0.5,因此被分类为类别 0(多数类别)。如果您重新平衡训练数据,平均预测概率会增加到 0.5,因此许多实例会高于默认阈值 0.5 的以及低于默认阈值 0.5 的,预测的类会更加平衡。因此,重新平衡不是降低阈值以使概率预测更经常地高于阈值并给出类 1(少数类),而是增加预测的概率以使概率预测更经常地高于默认阈值 0.5 并给出类 1。

如果您想要获得与重新平衡类似(不完全相同)的结果,而不实际重新平衡或重新加权数据,您可以尝试简单地将阈值设置为等于模型预测的类 1 概率的平均值或中值。当然,这并不一定是针对您的特定业务问题在误报和漏报之间提供最佳平衡的阈值,重新平衡您的数据并使用 0.5 的阈值也不一定。

在某些情况和模型中,重新平衡数据可能会大大改进模型,而不仅仅是将平均预测概率移动到等于默认阈值 0.5。但是,当使用默认阈值 0.5 时,模型在绝大多数情况下选择多数类这一事实本身并不支持这样一种说法,即重新平衡数据除了使平均概率预测等于阈值之外,还能完成任何事情。如果您希望平均概率预测等于阈值,您可以简单地将阈值设置为等于平均概率预测,而无需为了扭曲概率预测而修改或重新加权训练数据。

编辑:关于置信度得分与概率预测的注释

如果您的分类器没有 predict_proba 方法,例如支持向量分类器,您也可以使用它的 decision_function 方法来代替它,产生一个序数判别得分置信度得分模型输出,即使它是而不是可解释为 0 和 1 之间的概率预测,也可以用相同的方式设定阈值。根据特定分类器模型如何计算两个类别的置信度得分,有时可能需要而不是将阈值直接应用于类别 1 的置信度得分(我们在上面将其作为类别 1 的预测概率,因为类别 0 的预测概率只是 1 减去 1),或者将阈值应用于类别 0 和类别 1 的置信度得分之间的差*, 对于假设假阳性的成本与假阴性的成本相同的情况,默认阈值为 0。 本文假设了一个两类分类问题。*

如何处理不平衡数据

原文:https://towardsdatascience.com/how-to-deal-with-imbalanced-data-34ab7db9b100?source=collection_archive---------8-----------------------

Python 中处理不平衡数据集的分步指南

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

作者照片

具有不平衡类的数据集是常见的数据科学问题,也是常见的面试问题。在本文中,我提供了一个分步指南来改进您的模型并很好地处理不平衡的数据。您最常看到不平衡数据的领域是分类问题,如垃圾邮件过滤、欺诈检测和医疗诊断。

是什么让不平衡的数据成为问题?

几乎每个数据集都有不同的类表示。只要差异很小,这就不是问题。然而,当一个或多个类非常罕见时,许多模型在识别少数类时不太好用。在本文中,为了简单起见,我将假设一个两类问题(一个多数类和一个少数类),但是这些技术中的大多数也适用于多个数据集。

通常,我们会查看验证分割的准确性,以确定我们的模型是否表现良好。然而,当数据不平衡时,准确性可能会产生误导。例如,假设您有一个数据集,其中 92%的数据被标记为“非欺诈”,剩下的 8%是“欺诈”案例。数据明显不平衡。现在假设我们的模型最终将它看到的一切都归类为“非欺诈”。然而,如果我们着眼于准确性,这是一个惊人的 92%。但银行仍然关心那些“欺诈”案件。这就是它赔钱的地方。那么我们如何改进我们的模型呢?

为了克服不平衡数据集的问题,您可以执行以下一系列步骤和决策。

1。能收集更多数据吗

你可能会说,“好吧,网上的随便一个人,如果我能收集更多的数据,我就不会读这些了,不是吗?收集更多数据”。

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

通过 https://stopthatrightnow.github.io/生成的图像

但是听我说完。后退一步,考虑以下问题:

  • 你收到的数据是否经过了筛选,以排除可能导致辅修课观察被忽略的情况。
  • 你有多少年的历史,如果你回到一两年前,你会得到更多的数据仍然合理的次要类的实例。
  • 如果是客户数据,我们能否使用不再订阅我们服务的客户,而不影响我们试图解决的参数。也许使用这些以前的客户记录,以及“当前客户”?(Y/N)"布尔变量会有所帮助。
  • 你能把你的少数民族班合并成一个班吗?例如,如果您正在对一个人的心跳中的不同类型的异常进行分类,而不是试图对每种类型的异常进行分类,那么如果我们将它们都合并到一个单一的“异常心跳”类别中,该模型还会有用吗?

只是一些想法和一个提醒,总是考虑不同的可能性。

2。 更改绩效指标

如上所述,由于在处理不平衡数据集时,精确度不是一个好的衡量标准,所以让我们考虑更合适的衡量标准。

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

作者的混淆矩阵照片

基于混淆矩阵,我们可以测量以下内容:

  • **精度:**真阳性/所有预测阳性= TP / (TP+FP)。精度是对分类器准确性的度量。低精度表示大量的误报。
  • **回忆:**真阳性/所有实际阳性= TP / (TP + FN)。召回是对分类器完整性的一种度量。它也与敏感度或真实阳性率相同。低召回率表示大量的假阴性。
  • F1 得分: 2TP/(2TP + FP + FN)精度和召回率的加权平均值。如果我们想在精确度和召回率之间取得平衡,那么我们应该看看 F1 的分数。

注意:这里我假设少数类在混淆矩阵中被标记为正类。

查看此维基百科页面,获取绩效指标公式列表。

我们还可以看一看:

  • 灵敏度/特异性ROC 曲线:灵敏度与回忆基本一致,告诉我们真实的阳性率。
  • Kappa(或 科恩的 kappa ) :分类精度由数据中类别的不平衡性归一化。

在这种情况下,我们希望寻找高回忆/灵敏度和 f1 分数,而不是准确性,以查看我们的模型在预测辅修课程方面的表现。

Jason Brownlee 在这里了解更多关于选择不同绩效指标的信息

3。 尝试不同的算法

与大多数数据科学问题一样,对数据尝试几种不同的合适算法始终是一种好的做法。

有两种主要类型的算法似乎对不平衡数据集问题有效。

决策树

决策树似乎在不平衡数据集上表现得很好。因为他们在拆分的每个阶段都提出了条件/规则,所以他们最终把两个类都考虑进去了。

我们可以尝试一些不同的决策树算法,如随机森林、CART、C4.5。

处罚车型:

惩罚学习模型(代价敏感训练)对模型强加了额外的代价,用于在训练期间对少数类进行分类错误。这迫使模型更多地关注少数类观察。

异常检测模型:

如果只是 2 个类,多数类和少数类,那么您可以考虑使用异常检测模型而不是分类模型。这些异常模型试图做的是为多数类创建一个配置文件。任何不符合这一特征的观察都被认为是异常或异常值,在我们的例子中是来自少数群体的观察。这类模型用于欺诈检测等情况。

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

异常检测图片来自维基百科 ( CC BY-SA 4.0 )

4。 对数据集进行重新采样

这一步可以在尝试上述不同的模型方法时完成。不同类型的重采样如下:

  1. 对多数类欠采样
  2. 对少数民族阶层进行过度采样

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

按作者对数据照片进行重采样

欠采样(下采样)多数类

欠采样随机移除多数类的观测值。这减少了在训练集中使用的多数类观察的数量,并且因此更好地平衡了两个类的观察的数量。当您的数据集中有大量观测值(> 10K 观测值)时,这非常适合。风险是你正在丢失信息,因此可能导致不适合。

Scikit-learn 提供了一种“重采样”方法,我们可以用它来进行欠采样。不平衡学习包还提供了更高级的功能。Python 代码示例如下所示:

由于多数类的许多观测值已被丢弃,因此产生的数据集现在要小得多。这两个班级的比例现在是 1:1。

**注:**我们不一定要使用 1:1 的比率,我们可以使用这种方法将多数类观察的数量减少到任何合理的比率。

过采样(上采样)少数类

过采样随机复制少数类的观测值,以使其信号更强。最简单的过采样形式是置换采样。当数据集中没有大量观测值(< 10K 观测值)时,过采样非常合适。风险在于,如果你重复了太多的观察,那么你就是过度拟合了。

我们可以使用相同的 scikit-learn“重采样”方法,但使用不同的参数。下面显示了一个代码示例:

这一次,我们使用替换进行采样,以便在最终的训练集中有更多的代表性。但正如我提到的,这可能会导致过度拟合。那么,怎样才能把事情做得更好,避免过度拟合呢?

5。 生成合成样本

为了减少上采样期间的过拟合,我们可以尝试创建合成样本。

重击

一个流行的算法是 SMOTE (合成少数过采样技术)。SMOTE 不是使用观测值的副本进行过采样,而是改变观测值的属性来创建新的合成样本。

你可以在这里找到 SMOTE 的例子。

增大

与 SMOTE 类似,如果您的数据是音频或图像之类的东西,那么您也可以对原始文件执行转换来创建新的样本。

6.结论

正如数据科学和机器学习算法中的大多数事情一样,没有每次都有效的确定的正确方法。根据数据集的性质、类的分布、预测器和模型,上述一些方法会比其他方法更好。这取决于你来找出最佳的组合。

需要记住的几点是:

  • 在创建合成/增强样本之前,始终进行训练/测试分割。您希望根据原始数据观察来验证和测试您的模型
  • 使用相同的衡量标准进行比较——每次你尝试新的东西时,记得正确地进行比较。不要只看一个型号的精度,另一个型号的灵敏度。

除了这些步骤之外,不要忘记您还必须做一些事情,例如数据清理、功能选择和超参数调整。

希望这有所帮助!

if_you_like(this_article):
    please(CLAPS) # Do this :)
else:
     initiate_sad_author()  # Don't do this :(# Thanks :)

参考资料和进一步阅读

博伊尔塔拉。"处理不平衡数据的方法."中等。2019 年 2 月 04 日。2020 年 6 月 21 日访问。https://towards data science . com/methods-for-processing-unbalanced-data-5b 761 be 45 a 18。

布朗利,杰森。"在你的机器学习数据集中对抗不平衡类的 8 个策略."机器学习精通。2020 年 1 月 14 日。2020 年 6 月 21 日访问。https://machine learning mastery . com/tactics-to-combat-unbalanced-classes-in-your-machine-learning-dataset/。

"如何处理机器学习中不平衡的类."2020 年 5 月 23 日。https://elitedatascience.com/imbalanced-classes.

Python 中如何处理不平衡数据

原文:https://towardsdatascience.com/how-to-deal-with-imbalanced-data-in-python-f9b71aba53eb?source=collection_archive---------1-----------------------

平衡不平衡的 pythonic 解决方案

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

Photo by 青 晨 on Unsplash

不平衡数据在现实世界中是非常常见的,尤其是当决策系统的目标是一个罕见但重要的案例时。当未来的决策是基于对历史数据的洞察而做出时,这可能是一个问题。来自少数案例的不充分数据会妨碍正在做出的新决策的稳健性。

不平衡数据的情况几乎存在于任何实际应用中。例如,美国无线运营商的平均客户流失率在 1-6%之间。同样在市场营销中,的平均转化率也徘徊在个位数范围内。

那么,在机器学习(ML)中使用不平衡数据会出现什么问题呢?你如何处理不平衡的数据?本文将带您了解所有这些问题,并展示一些 Python 中的实际例子。

令人惊讶的是,我将在本文末尾提供“另一件事”,说明如何结合使用过采样和欠采样方法来选择最佳采样比。

什么是精确的不平衡数据?

不平衡数据集分类问题的特例,其中类在类间的分布不均匀。通常,它们由两类组成:多数(消极)类和少数(积极)类【1】。****

通常少数类是我们希望 ML 模型能够正确预测的,因此被称为正类。例如,如果一个模型试图以 3%的转换率对一组 10,000 个客户数据进行训练,它可能没有足够的样本进行足够好的训练来预测未来正转换率的概率。

那么,我们如何准确定义不平衡数据的阈值呢?

根据谷歌开发者的说法,答案可以分为 3 个不平衡度——轻度(20–40%)、中度(1–20%)和极端(< 1%)。

为什么重要?

不平衡数据的影响是隐含的,即当您构建和运行模型时,它不会立即引发错误,但结果可能会令人迷惑。如果多数类的类不平衡程度是极端的,那么机器训练的分类器可以产生高的总体预测精度,因为该模型最有可能预测属于多数类的大多数样本。例如,在一个类分布为 90:10 的两类问题中,分类器在多数类示例上的性能是少数类示例的九倍。

如何处理不平衡的数据?

文献中已经提出了几种解决这个问题的方案,其中有:

  • 数据级技术— 在数据级,解决方案通过应用重采样技术来平衡数据集。这可以通过对少数类进行过采样来实现,即从现有的实例中综合创建新的实例;或者对多数类进行欠采样,这消除了多数类中的一些实例。然而,这两种技术都有缺点。过采样新数据会导致分类器过拟合;而欠采样会丢弃重要信息。在专业文献中可以找到这两种技术与启发式方法的结合,结果非常好。
  • 算法级技术— 算法级解决方案可以通过相应地调整加权成本来实现,以适应每一类中训练实例的数量。在像支持向量机这样的参数分类器中,可以应用网格搜索和交叉验证来优化 C 和 gamma 值。对于像决策树这样的非参数分类器,调整树叶处的概率估计可以提高性能。
  • ****两者的结合——各种文献中也在不断探索一种混合方法,包括彭和姚提出的 AdaOUBoost (自适应过采样和欠采样增强)和利用 Japkowicz 提出的基于自动联想的分类方法概念的通过识别学习

用 Python 处理不平衡数据

Python 中最流行的采样方法库之一就是不平衡学习包。它提供了多种过采样和欠采样方法,以及一些组合方法。在本教程中,我们将为这三种方法分别探索一个示例:

  • 使用随机欠采样器进行随机欠采样
  • 使用 SMOTE 进行过采样(合成少数过采样技术)
  • 使用流水线的随机欠采样和过采样的组合

本教程中使用的数据集基于来自 UCI 回购的银行营销数据。这是一个分类问题,目标是预测客户是否会订阅定期存款。所有分类(文本)特征列都被编码成机器友好的数字形式。编码数据集托管在 Github 上。为了测试数据在重采样后的表现,我们在重采样数据上训练支持向量机模型,以检查模型的表现。完整的 Python 代码也可以在同一个 Github 库中找到。

之所以选择这个数据集,是因为它反映了日常应用中常见的不平衡数据集。正如预期的那样,数据非常不平衡,只有大约 13% [5,289/(5,289+39,922)]的联系客户实际上订阅了定期存款。在 Python 中,可以使用方法value_counts()打印每个预测类的编号。

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

目标类的分布。0 表示未转换的多数负类 aka 客户,而 1 表示认购定期存款的少数正类 aka 客户。

  1. 随机欠采样

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

照片由帕特里克·福尔Unsplash 拍摄

顾名思义,随机欠采样将多数类的数量随机减少到相对于少数类的期望比率。这可能是最简单的欠采样方法,如果有许多彼此接近的多数类实例,这种方法实际上可以产生良好的结果。关于减少多数类的更统计的方法,你可以参考浓缩最近邻(又名。CNN,基于 Hart 算法), Tomek Links (对原始 CNN 技术的改进), NearMiss 等等,这里仅列举一个新的。幸运的是,所有提到的技术都可以在同一个不平衡学习包中获得,你可以很容易地导入并尝试它们。

代码片段分为两部分:第 1 部分向您展示随机欠采样多数类的代码;第 2 部分使用支持向量机训练重采样数据,并输出 ROC AUC 得分。

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

代码片段的输出:第 1 行显示原始数据分布;第二行显示欠采样分布;第三行显示了使用欠采样数据的模型性能

2。使用 SMOTE 进行过采样

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

SMOTE 使用 5 作为 k 个最近邻进行过采样的示例。作者自我图解。

对于过采样技术, SMOTE (合成少数过采样技术)被认为是 ML 和数据挖掘中最流行和最有影响力的数据采样算法之一。使用 SMOTE,少数类通过创建“合成”示例进行过采样,而不是通过替换进行过采样[2]。这些引入的合成示例基于沿着连接定义数量的 k 个少数类最近邻居的线段,其在imblearn包中默认设置为五个

代码片段分为两部分:第 1 部分展示了用 SMOTE 对 minority 类进行过采样的代码;第 2 部分使用支持向量机训练重采样数据,并输出 ROC AUC 得分。

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

代码片段的输出:第 1 行显示原始数据分布;第二行显示了过采样分布;第三行显示了使用过采样数据的模型性能

3。使用流水线的欠采样和过采样方法的组合

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

Unsplash 上创意交流拍摄的照片

代码片段分为两部分:第 1 部分展示了创建管道的代码,使用欠采样和过采样方法对数据进行重采样;第 2 部分使用支持向量机训练重采样数据,并在交叉验证后输出平均 ROC AUC 分数。

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

使用组合抽样方法显示 ROC AUC 得分的代码片段的输出。

奖励—我如何知道哪个采样比是最好的?

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

乔恩·泰森在 Unsplash 拍摄的照片

在上面的教程中,我们对数据进行了欠采样或/和过采样,以使两个类的分布达到 50:50 的平衡。但是如果我们想根据模型性能找出最佳的采样率呢?我们可以通过在 Python 中实现一个for循环来迭代一个可能的采样比率列表,并在交叉验证后根据平均 ROC AUC 得分(或选择的其他性能指标)来查看哪个组合具有最佳性能。

代码片段向您展示了使用欠采样和过采样方法创建管道以对数据进行重采样的代码。过采样的可能比率列表为[0.3,0.4,0.5],欠采样的可能比率列表为[0.7,0.6,0.5]。这些比率是出于演示目的而随机选择的,并且可以在一些试验和错误之后用其他值替换。然后,在交叉验证后输出平均 ROC AUC 分数之前,用每个可能的比率组合对的重采样数据训练支持向量机。

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

每个可能的比率组合对的平均 ROC AUC 评分的代码片段输出。

如输出快照所示,本例中的最佳采样率为 0.5 的过采样率,其次是 0.7 的欠采样率,以获得 82.1%的最佳可能平均 ROC AUC 得分。

结论

对于欠采样还是过采样方法更适合不平衡数据的问题,没有简单的答案,尤其是在使用哪种精确采样技术(随机或 SMOTE)时。然而,大多数研究指出,欠采样在大多数情况下确实比过采样产生更好的结果。在行业实践中,据报道,像脸书和微软这样的科技巨头在对他们的广告表现进行分类时也倾向于使用欠采样方法。常见的论点是欠采样通常比过采样“更便宜”,并且由于感兴趣的类是少数正类,因此减少多数负类的一些信息是可以接受的。但是不能保证在你的情况下同样的事情总是能重复发生。

我的建议是,在处理不平衡数据时,根据你拥有的时间和资源来决定。如果您有有限的时间和资源来研究哪种方法最适合您,那么您可以从一开始就选择随机欠采样。然而,如果你有一点奢侈去尝试不同的采样方法和技术,我会强烈推荐后者。一旦你有了一个平衡的数据,你的模型就有可能学会更好地对不同的类进行分类,从而得到更可靠的预测。

处理不平衡数据后的下一步可能是为您的模型选择最佳特性,为此,欢迎您查看我在特性选择中的文章。

*免责声明:由于训练测试分割和交叉验证的随机性,您可能不会得到如图所示的准确输出。

参考:

[1] 不平衡数据集,龙骨 2018

[2] SMOTE:合成少数过采样技术

感谢阅读这篇文章。如果你喜欢我的工作,请考虑加入 Medium 来支持我。谢谢大家!😊

** [## 通过我的推荐链接-谭施敏加入媒体

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

jackyeetan.medium.com](https://jackyeetan.medium.com/membership)**

如何在 Python 中处理无穷大

原文:https://towardsdatascience.com/how-to-deal-with-infinity-in-python-ab041fc95546?source=collection_archive---------34-----------------------

介绍在 Python 中定义和使用无限值的方法

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

鲁本·特奥Unsplash 拍摄的照片

我们只是追求绝对完美的无限探索者。—g·h·哈代

很多人认为无穷大只是一个非常大的数。但在现实中,无限是无限的概念,没有任何界限。

从早期开始,数学家们就在用这种永无止境的概念赌博。正如约翰·格林在他的书《我们星星中的错误》中所写的,

“在一个由其结局定义的宇宙中,无尽是一个非常奇怪的概念.”

对于算法设计来说,无穷大有许多可取的特性。最受欢迎的是:

∀ x ∈ ℝ,-∞ < x < ∞

每个数都小于正无穷大,大于负无穷大。

在 Python 中,我们可以用多种方式表示无穷大。我们将在下面讨论三个最受欢迎的。

设置

本文编写的代码在 Python 3.6 上进行了测试。这里唯一需要的非标准库是 numpy 。您可以使用以下命令非常简单地安装它:

pip install numpy

使用 float('inf ')

我们将创建两个变量并用正负无穷大初始化它们。

输出:

Positive Infinity:  inf
Negative Infinity:  -inf

使用数学模块(math.inf)

另一种表示无穷大的流行方法是使用 Python 的数学模块。看一看:

输出:

Positive Infinity:  inf
Negative Infinity:  -inf

使用 Numpy 模块(numpy.inf)

Numpy 对于无穷大的值也有自己的定义。我们也可以创建用无穷大值填充的数组。代码如下所示:

输出:

Positive Infinity:  inf
Negative Infinity:  -inf
Infinity Array:  [inf inf inf inf inf inf inf inf inf inf]

在 Python 中检查一个数是否是无限的

math 模块提供了一个isinf()方法,允许我们轻松地检查 Python 中的无限值。它返回一个布尔值。看一看:

输出:

For First Infinity: True
For Second Infinity: True
For Third Infinity: True
For Large Number: False

无限算术

大多数无穷数的算术运算都会产生其他无穷数。无限零悖论成为一个非常有趣的晚餐话题。至少我希望如此。我还没试过。

输出:

Addition :  inf
Subtraction :  inf
Multiplication :  inf
Division :  inf

Multiplication by Zero:  nan

结束语

在最优化问题中经常用到无穷大。例如,在最短路径算法中,我们需要将当前距离与迄今为止的最佳或最小距离进行比较。

我们用正无穷大初始化未知距离。无论你在程序中输入什么距离,没有一个数能大于这个无穷大的表示。

我们讨论了在 Python 中表示无限值的多种方式。

我个人使用 math.inf 方法来定义一个无穷数。这是因为这种方法通常是三种方法中最快的。另外,math是一个标准库,已经是我大部分代码的一部分。

%timeit np.inf
# 38.3 ns ± 0.208 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)%timeit float('inf')
# 198 ns ± 2.56 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)%timeit math.inf
# 37.5 ns ± 0.0933 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

但是像往常一样,当我们开始处理数组时,Numpy 变得更快:

%timeit [math.inf for _ in range(10000)]
# 585 µs ± 8.29 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)%timeit np.full(10000, np.inf)
# 10.4 µs ± 49.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

希望你觉得这个教程有用!你可以在这里找到我的其他故事

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值