TowardsDataScience-博客中文翻译-2019-六十-

news/2024/10/13 15:28:12

TowardsDataScience 博客中文翻译 2019(六十)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

堆叠分类器以提高预测性能

原文:https://towardsdatascience.com/stacking-classifiers-for-higher-predictive-performance-566f963e4840?source=collection_archive---------2-----------------------

利用多分类器的智慧提高性能

Photo by Erwan Hesry on Unsplash

目的:这篇文章的目的是为读者提供必要的工具来实现称为堆叠的集成学习技术。

材料和方法:使用 Scikit-learn ,我们为一个分类任务生成一个类 Madelon 数据集。然后分别训练支持向量分类器(SVC)、Nu-支持向量分类器(NuSVC)、多层感知器(MLP)和随机森林分类器。每个分类器的性能将使用受试者操作曲线下面积(AUC)来衡量。最后,我们使用 StackingCVClassifier 对象堆叠这些分类器的预测,并比较结果。

硬件:我们在配备英特尔酷睿 i7–8700 处理器(12 个 CPU,3.70 Ghz)和英伟达 GeForce RTX 2080 的工作站上训练和评估我们的模型。

注意:如果您是从零开始,我建议您按照这篇文章安装所有必要的库。最后,假设读者熟悉 Python、 Pandas 、Scikit-learn 和 ensemble 方法。这篇文章的全部内容可以在我的 GitHub 上找到。欢迎你来叉它。

符号:粗体文本将代表一个列表、字典、元组、一个 Pandas DataFram e 对象,或者将引用一个图形或脚本。This notation will be used to represent parameters in an object or command lines to run in the terminal.

什么是堆叠?

最简单的堆叠形式可以描述为集成学习技术,其中多个分类器(称为一级分类器)的预测被用作训练元分类器的新特征。元分类器可以是您选择的任何分类器。图 1 显示了如何训练三个不同的分类器。它们的预测被叠加,并被用作训练元分类器的特征,元分类器做出最终预测。

Figure 1 — Schematic of a stacking classifier framework. Here, three classifiers are used in the stack and are individually trained. Then, their predictions get stacked and are used to train the meta-classifier.

为了防止信息从目标(您试图预测的事物)泄漏到训练中,在堆叠分类器时应遵循以下规则:

  1. 一级预测应该来自没有用于训练一级分类器的训练数据的子集。

一个简单的方法是将你的训练分成两半。使用训练数据的前半部分来训练一级分类器。然后使用训练好的一级分类器对训练数据的后半部分进行预测。然后,这些预测应该用于训练元分类器。

一种更可靠的方法是使用 k 重交叉验证来生成一级预测。这里,训练数据被分成 k 倍。然后,前 k-1 个折叠用于训练一级分类器。然后,验证折叠用于生成一级预测的子集。对每个独特的组重复该过程。图 2 说明了这个过程。

Figure 2 — Schematic of k-fold cross validation used with a Stacking classifier framework.

热心的读者可能会想,为什么不堆叠另一层分类器呢?可以,但这会增加堆栈的复杂性。例如,考虑以下架构:

Figure 3 — Schematic of a Stacking classifier with two layers of classifiers.

这开始看起来像一个神经网络,其中每个神经元都是一个分类器。第二级中使用的分类器的数量和类型不必与第一级中使用的相同——看看事情是如何很快失控的。例如,一级分类器可以是额外树分类器、决策树分类器和支持向量分类器,二级分类器可以是人工神经网络、随机森林和支持向量分类器。在本文中,我们将实现如图图 2 所示的堆叠分类器架构。

堆叠,还是不堆叠,这是个问题。

在开始堆叠分类器之前,建议您首先考虑所有其他选项,以提高您的预测性能。作为指导,请考虑以下问题,以确定是否应该开始堆叠:

  • 你有可能掌握更多的数据吗?在机器学习中,数据为王(即通过收集更多数据可以实现性能的最大提升);因此,如果这是一种可能性,你应该集中精力,把一个更大更多样化的数据集放在一起。
  • 是否有可能向您的数据集添加更多功能?例如,您可以使用图像中的像素亮度值作为特征。您还可以从这些图像中提取纹理特征,这些特征考虑了像素亮度值在空间上的分布。从手头的问题中收集尽可能多的特征是很重要的。这样做只是因为你不知道这些特征中哪些是好的预测器。请记住,任何模型的预测能力应该主要来自用于训练它的特征,而不是来自算法本身。
  • 您是否正确地预处理了所有数据?如果你把垃圾推进模型,垃圾就会出来。确保您在视觉上探索了您的所有功能,以便更好地理解它们。注意丢失的值、异常值,并确保您的数据集不会严重失衡。缩放您的功能,删除所有冗余功能,如果您的功能数量很大,请应用功能选择方法,并考虑功能工程。
  • 你用你的数据集探索过一大组分类器的预测性能吗?你仔细调过这些分类器吗?

如果你对所有这些问题的回答都是肯定的,并且你愿意做任何事情来提高性能,那么考虑堆栈。

安装必要的模块

实现如图图 2 所示的堆栈架构的最简单方法是使用 MLXTEND Python 库。要安装它,请阅读他们的 GitHub 自述文件在这里。如果您在 Windows 上安装了 Anaconda,请启动 Anaconda 提示符,导航到要安装此模块的 conda 环境,然后运行以下命令:

conda install -c conda-forge mlxtend

或者您可以使用画中画:

pip install mlxtend

免责声明:我几乎可以肯定这不会破坏您的 Python 环境,但是如果真的破坏了,不要怪我。这里有一个关于如何使用 Anaconda 在 Windows 中安装基于 Python 的机器学习环境的指南,供感兴趣的读者参考。

数据集

我们将使用 Scikit-learn 为分类任务生成一个类似 Madelon 的合成数据集。这是我在 Medium 上发表的一篇文章[中用来探索各种模型性能的相同数据集。Madelon 数据集是一个人工数据集,包含放置在边长为 1 的五维超立方体的顶点上的 32 个聚类。聚类被随机标记为 0 或 1 (2 类)。](http://Model Design and Selection with Scikit-learn)

我们将生成的数据集将包含 30 个特征,其中 5 个将提供信息,15 个将是冗余的(但提供信息),5 个将重复,最后 5 个将是无用的,因为它们将被随机噪声填充。数据集的列将按如下顺序排列:

  1. 信息特征—第 1–5 列:这些特征是您构建模型时真正需要的唯一特征。因此,一个五维的超立方体。
  2. 冗余特征——第 6–20 列。这些特征是通过线性组合具有不同随机权重的信息特征而形成的。您可以将这些视为工程特性。
  3. 重复特征——第 21–25 列:这些特征是从信息特征或冗余特征中随机抽取的。
  4. 无用特征——第 26–30 列。这些特征充满了随机噪声。

让我们从导入库开始。

Script 1 — Importing all libraries

现在我们可以生成数据了。

Script 2 —Generates the data set. The random_state parameter is fixed so that we can work with the same data.

分割和预处理数据

一旦我们有了数据,我们就可以继续创建一个训练和测试集。

Script 3— Create train and test set. Notice we set the random_state parameter.

现在我们可以扩展我们的数据集。我们将通过 Z 分数标准化来实现。

Script 4 — Scaling the data.

我们已经完成了数据集的预处理。在这个例子中,我们不会去费力地去除高度相关的、冗余的和有噪声的特征。然而,重要的是,在你可能处理的任何项目中,你都要注意这一点。

分类器

出于说明的目的,我们将训练支持向量分类器(SVC)、多层感知器(MLP)分类器、Nu-支持向量分类器(NuSVC)和随机森林(RF)分类器——Scikit-learn 中提供的分类器。将设置这些分类器的超参数——我们将假设我们已经尽了最大努力来调整它们。坦率地说,如果你的分类器是垃圾,那么一堆分类器可能也是垃圾。此外,为了获得可重复的结果,每个分类器上的random_state已经固定。

Script 5— Initializing classifiers.

堆积分类器

为了堆叠它们,我们将使用 MLXTEND 中的 StackingCVClassifier。我建议你看一下官方文档,因为它详细介绍了如何实现 StackingCVClassifier 的有用例子。例如,它向您展示了如何堆叠对不同特征子集进行操作的分类器——这太酷了。最后,我们将把 StackingCVClassifier 中的use_probas参数设置为 True。这意味着第一级分类器将通过概率预测,而不是二进制输出(0 或 1)。然而,这并不意味着您应该使用这个设置,如果您将use_probas设置为 False,可能会对您的工作更有好处;然而,知道这一点的唯一方法是实际去做。作为meta_classifier,我们选择一个 SVC 并使用它的默认参数。

Script 6— Initializing the stacking classifier.

最后,为了方便起见,我们将所有的分类器放在一个字典中。

Script 7— Saving classifiers in a dictionary.

训练分类器

我们训练每个分类器,并将其保存到标记为分类器的字典中。分类器被训练后,将被保存到同一个字典中。

Script 8— Training classifiers.

做预测

现在我们准备在测试集上进行预测。这里我们首先创建结果,一个 pandas DataFrame 对象。然后使用 for 循环,我们遍历训练好的分类器,并将预测存储在结果中。最后,在第 14 行,我们添加了一个标有“Target”的新列,其中包含实际的目标

Script 9— Making predictions on test set.

可视化结果

现在是想象结果的时候了。我们将通过创建一个有 5 个支线剧情的人物来实现。在每个子图上,我们将显示从每个分类器的测试集上获得的概率分布。我们还将报告受试者工作曲线下的面积(AUC)。

Script 10 — Visualizing results.

Figure 4 — Probability distribution for each classifier. The AUC is also reported.

不错!每个分类器单独获得小于 0.909 的 AUC 然而,通过叠加它们,我们得到 AUC = 0.918。这是一个很好的提升,你不觉得吗?

调整堆积分类器

StackingCVClassifier 为您提供了调整每个分类器以及元估计器的参数的选项。但是,我不建议使用 StackingCVClassifier 进行全面的搜索。例如,假设您想要使用四个分类器,每个都有 100 个点的参数网格—老实说,这是一个相当小的网格。探索这个空间需要多长时间?让我们做一个简单的计算:

100 * 100 * 100 * 100 =你必须适应的 1 亿个模型

假设每个模型需要 0.5 秒来拟合,那将需要 5000 万秒或更长时间,简单地说就是 1.6 年。没人有时间做那个。这个计算没有考虑到元分类器不是固定的,并且包含它自己的需要调整的参数。这就是为什么我建议您首先单独调优您的分类器。之后,您可以将它们堆叠起来,只对元分类器进行调优。如果您决定调整分类器堆栈,请确保您为每个分类器调整了参数空间中的最佳点。

在这个例子中,我们首先为元分类器——支持向量分类器——创建一个参数网格。然后,我们使用 GridSearchCV 进行彻底搜索,以确定参数网格中产生最高性能的点。结果被打印到控制台上。

Script 11 — Tuning the meta-classifier.

The AUC of the tuned Stacking classifier is 0.923

很好,通过调整元分类器,我们成功地将堆叠分类器 AUC 从 0.918 推至 0.923。然而,我们还没有完成。让我们看看我们是否能从堆叠分类器中得到更多。为此,我们将创建一组堆叠分类器,每个分类器在第一层都有唯一的分类器组合/堆叠。对于每个堆叠分类器,将调整元分类器。结果将被打印到控制台上。

Script 12— Stacking different classifiers and exploring their performance.

AUC of stack ('SVC', 'MLP'): 0.876
AUC of stack ('SVC', 'NuSVC'): 0.877
AUC of stack ('SVC', 'RF'): 0.877
AUC of stack ('MLP', 'NuSVC'): 0.876
AUC of stack ('MLP', 'RF'): 0.877
AUC of stack ('NuSVC', 'RF'): 0.877
AUC of stack ('SVC', 'MLP', 'NuSVC'): 0.875
AUC of stack ('SVC', 'MLP', 'RF'): 0.876
AUC of stack ('SVC', 'NuSVC', 'RF'): 0.879
AUC of stack ('MLP', 'NuSVC', 'RF'): 0.875
AUC of stack ('SVC', 'MLP', 'NuSVC', 'RF'): 0.923

事实证明,如果我们将所有分类器堆叠在一起,我们会获得最高的 AUC。然而,情况并不总是如此。有时堆叠较少的分类器会产生较高的性能。实际上,我花了整整一天的时间才弄明白应该将哪些分类器堆叠在一起才能获得这种提升。此外,我注意到,有时通过叠加,我获得了较低的性能。诀窍是堆叠分类器,这些分类器弥补彼此的错误,而不是彼此对立。

结束语

我开始这篇文章是为了向读者介绍堆叠技术。它本应该又短又快,但结果却很长。如果你能走到这一步,我很感激你的时间。我希望这对你的努力有所帮助。我想指出的是,堆叠分类器可能并不总是有效,对于小的提升来说,这可能是一个乏味的过程;然而,如果做得正确,运气站在你这边,你将能够获得性能的提升。我建议您首先探索其他选项来提高您的性能。堆积的过程应该留到最后,因为它可能很耗时,回报可能很少。最后,如果你堆放垃圾,垃圾很可能会出来。这篇文章的全部内容可以在这里找到。祝一切顺利,继续学习!

你可以在 LinkedIn 找到我。

Sklearn 让堆叠变得简单

原文:https://towardsdatascience.com/stacking-made-easy-with-sklearn-e27a0793c92b?source=collection_archive---------7-----------------------

Photo by Jeremy Thomas on Unsplash

sci kit-学习

用几行代码创建一个 StackingClassifier

介绍

整体方法的基本原则是在统一中发现力量。通过组合多种方法,每种方法都有自己的优缺点,可以创建更强大的模型。

整体大于部分之和——亚里士多德

这句话尤其适用于堆叠,这是一种将许多不同的学习者组合成一个更强大的模型的方法。

写这篇文章的主要原因不是解释堆栈是如何工作的,而是演示如何使用 Scikit-Learn V0.22 来简化堆栈管道并创建有趣的模型。

1.堆垛

尽管有许多很棒的资料来源介绍了堆栈(这里的、这里的和这里的),但是让我快速地让您了解一下。

堆叠是一种技术,它采用几个回归或分类模型,并使用它们的输出作为元分类器/回归器的输入。

本质上,堆叠是一种集成学习技术,很像随机森林,通过组合典型的弱模型来提高预测的质量。

Overview of a single level Stacking model

上图给出了堆叠原理的基本概述。它通常由许多弱基础学习或几个强基础学习组成。然后,元学习器基于每个基础学习器的预测输出进行学习。

2.Sklearn 堆叠

虽然有许多包可以用于堆叠,如 mlxtend 和 vecstack ,但本文将深入探讨 scikit-learn 新版本中新添加的堆叠回归器和分类器。

首先,我们需要确保将 Scikit-learn 升级到版本 0.22:

pip install --upgrade scikit-learn

我们要做的第一个模型是一个分类器,可以预测花的规格。该模型相对简单,我们使用随机森林和 k *邻作为我们的基本学习器,使用逻辑回归作为我们的元学习器。

One-layer Stacking Model

编码堆叠模型可能相当棘手,因为您将不得不考虑您想要在不同步骤生成的折叠和交叉验证。幸运的是,新的 scikit-learn 版本只需几行代码就可以创建如上所示的模型:

基本上就是这样!只有几行代码的堆叠分类器。

3.交叉验证

堆叠的一个困难是您选择在哪里应用交叉验证。我们可以只在元学习者级别应用它,但是这可能会导致我们的模型过拟合,因为基础学习者的输出可能已经过拟合了。

尽管有许多解决这个问题的策略,但在 scikit-learn 中,堆栈的实现如下:

基础学习者适合于完整的X,而最终估计者则通过使用cross_val_predict的基础学习者的交叉验证预测来训练。

这意味着每个单独的基础学习者的预测被堆叠在一起,并被用作元学习者的输入来计算预测。然后通过交叉验证来训练这个元学习者。

交叉验证自动设置为 5 倍 CV,但可以手动调整:

但这还不是全部,您还可以加入任何您想要的交叉验证策略:

4.多层堆叠

在第 2 步中,我们已经创建了一个具有单层基本学习者的 StackingClassifier。但是如果你想用另一组基础学习者代替元学习者呢?你如何添加层来增加模型的复杂性?

这里,我们将在步骤 2 中向模型添加另一层学习者,以便了解如何编写解决方案。

在上图中,我们可以看到我们想要添加一个包含两个额外分类器的层,即一个决策树和一个随机森林。

为了做到这一点,我们创建了两个估计列表,每层一个。我们使用最终模型的第二层估计量,即逻辑回归,创建一个 StackingClassifier。然后,我们用第一层估计器创建一个新的 StackingClassifier 来创建完整的模型管道。

正如你所看到的,模型的复杂性随着每一层的增加而迅速增加。此外,如果没有适当的交叉验证,您很容易使用这么多的层来填充数据。

结论

堆叠可能是一个棘手的问题,因为它需要对数据泄漏有深刻的理解,以便选择正确的程序。确保总是对你的模型进行广泛的验证,以便理解它的普遍性。

如果你像我一样,对人工智能、数据科学或心理学充满热情,请随时在 LinkedIn 上添加我。

支持最佳实践:

原文:https://towardsdatascience.com/stand-up-for-best-practices-8a8433d3e0e8?source=collection_archive---------6-----------------------

深度学习在《自然》杂志地震余震论文中的误用

Source: Yuriy Guts selection from Shutterstock

机器学习炒作的危险

人工智能、机器学习、预测建模和数据科学的从业者在过去几年中有了巨大的增长。曾经由知识混合定义的利基领域正在成为一个快速发展的职业。随着围绕人工智能的兴奋继续增长,新一轮的 ML 增强、自动化和 GUI 工具将导致试图建立预测模型的人数进一步增长。

但问题是:虽然使用预测建模工具变得越来越容易,但预测建模知识还没有普及。错误可能是违反直觉的和微妙的,如果你不小心,它们很容易让你得出错误的结论。

我是一名数据科学家,以与数十个专家数据科学团队合作为生。在我的日常工作中,我看到这些团队努力构建高质量的模型。最好的团队一起检查他们的模型来发现问题。有许多难以检测的方法会导致有问题的模型(比如,允许目标泄露到他们的训练数据中)。

识别问题并不有趣。这需要承认令人兴奋的结果“好得难以置信”,或者他们的方法不正确。换句话说,与其说是吸引眼球的性感数据科学炒作,不如说是一门严谨的科学学科

糟糕的方法会产生糟糕的结果

大约一年前,我在《自然》杂志上读到一篇文章,声称通过使用深度学习预测地震余震达到了前所未有的准确性。读了这篇文章,我内心的雷达对他们的结果产生了深深的怀疑。他们的方法根本不具备仔细预测模型的许多特征。

我开始深入调查。在此期间,这篇文章炸了,成了广为人知的!它甚至被包括在 Tensorflow 的发行说明中,作为深度学习可以做什么的例子。然而,在我的挖掘中,我发现了论文中的重大缺陷。也就是说,数据泄漏会导致不切实际的准确性分数和对模型选择的不重视(当一个更简单的模型提供相同水*的准确性时,您不会构建一个 6 层神经网络)。

The testing dataset had a much higher AUC than the training set . . . this is not normal

对于我之前的观点:这些是微妙的,但是难以置信的基本的预测建模错误,它们可以使整个实验结果无效。数据科学家接受培训,在工作中识别和避免这些问题。我假设这只是作者忽略了,所以我联系了她,让她知道,以便她可以改进她的分析。尽管我们之前有过交流,但她没有回复我关于论文的邮件。

充耳不闻

那么,我该怎么办呢?我的同事告诉我只要发推特就可以了,但我想坚持良好的建模实践。我认为理性和最佳实践会占上风,所以我开始了为期 6 个月的过程来记录我的结果,并与自然分享。

在分享我的结果时,我在 2019 年 1 月收到了《自然》杂志的一份说明,尽管对数据泄露和模型选择的严重担忧使他们的实验无效,但他们认为没有必要纠正错误,因为“德弗里斯等人主要关注的是使用机器学习作为一种工具来提取对自然世界的洞察力,而不是算法设计的细节”。作者给出了更加严厉的回应。

你可以在我的 github 上阅读整个交流。

仅仅说我很失望是不够的。这是一篇重要的论文(这是自然!尽管使用了有缺陷的方法,但还是相信了人工智能的炒作并发表了一篇论文。

然后,就在这个星期,我偶然看到阿诺·米格南和马尔科·布罗卡多写的关于他们在《余震》文章中发现的缺点的文章。这里还有两位擅长地震分析的数据科学家,他们也注意到了论文中的缺陷。我还将我的分析和可复制代码放在了 github 上。

Go run the analysis yourself and see the issue

支持预测建模方法

我想澄清一点:我的目标不是丑化余震论文的作者。我不认为他们是恶意的,我认为他们会说他们的目标只是展示机器学习如何应用于余震。Devries 是一位有成就的地震科学家,她想将最新的方法用于她的研究领域,并从中发现了令人兴奋的结果。

但问题是:他们的见解和结果是基于有根本缺陷的方法。光说“这不是机器学习论文,这是地震论文”是不够的。如果您使用预测建模,那么您的结果质量由您的建模质量决定。你的工作变成了数据科学工作,你因为你的科学严谨性而上钩。

对使用最新技术和方法的论文有着巨大的需求。很难收回这些文件。

但如果我们允许带有根本性问题的论文或项目取得进展,这将伤害我们所有人。它破坏了预测建模领域。

请推回坏数据科学。向报社报告不好的发现。如果他们不采取行动,去推特,发布相关信息,分享你的结果,制造噪音。这种类型的集体行动有助于提高对 p 价值观的认识,并打击 p 黑客的流行。如果我们希望我们的领域继续增长并保持可信度,我们需要良好的机器学习实践。

鸣谢:我要感谢 DataRobot 所有伟大的数据科学家,他们在过去的一年里给予了我合作和支持,其中包括:Lukas Innig、Amanda Schierz、Jett Oristaglio、Thomas Stearns 和 Taylor Larkin。

在数据科学家的海洋中脱颖而出

原文:https://towardsdatascience.com/standing-out-in-a-sea-of-data-scientists-c82e42a1e62b?source=collection_archive---------9-----------------------

Source: Pexels

2019 年,Glassdoor 将数据科学家列为美国排名第一的最佳工作。数据科学职业道路的日益普及导致了针对希望进入该领域的人的学位、项目和训练营的爆炸式增长。据发现数据科学报道,5 年前数据科学学士学位几乎不存在,而现在有超过 50 个。虽然对数据科学家的需求继续增长(事实上报告称从 2018 年到 2019 年需求增长了 29%),但我认为,由于入门级人才的供应增加,获得数据科学家的第一份工作可能比以往任何时候都难。许多职位描述都强调在该领域拥有多年的工作经验,这并没有什么帮助。事实上,我在上找到的关于数据科学家工作的第一个描述是这样的(注意:这可能完全适合这个特定的工作;用它来说明不需要多年经验的数据科学职位描述很少):

  • 本科学历或四年以上工作经验。
  • 四年或以上相关工作经验。

Source: http://transpremium.com/the-sad-truth-of-hiring-employees-nowadays/

鉴于所有这些,我收到的最常见的问题之一就是“我如何进入数据科学领域?”就不足为奇了

有成千上万种方法可以回答这个问题,但我想集中讨论四种。不过,我的回答对你有所假设。首先,你实际上已经学习了数据科学,并且对该领域的基本原理感到很舒服。如果你不确定,可以看看吴恩达的机器学习课程。如果你对这些材料感到满意,那么我相信我的建议是适用的(如果你也参加了他的深度学习课程会加分)。

要有战略眼光

不幸的是,大多数技术项目并不十分关注实际获得一份工作。相反,学生们花费大量时间去追求完美的*均绩点。虽然渴望取得好成绩肯定没有错,但我发现这耗费了太多的时间,以至于当学生在课程结束时终于出来透透气时,他们发现他们没有花太多时间从战略上考虑如何找到他们梦想中的工作。

我说战略性是因为随着就业市场变得越来越全球化,仅仅通过提交申请和抱最大希望就能找到理想工作的日子已经一去不复返了。几乎每一份工作都会有几十份甚至几百份申请。事实上,谷歌每年收到大约300 万份申请,这意味着你获得工作的预期几率大约为 0.2%。另一方面,哈佛的录取率为 T4 的 4.5%。因此,虽然你仍然可以通过提交简历和通过“标准”程序在谷歌找到一份工作,但你最好还是努力提高自己的胜算。

网络

我提高胜算的第一条建议是建立关系网。不要相信“过程”会帮你找到工作,因为你是最好的候选人。招聘过程非常嘈杂,许多优秀的候选人都被忽略了。人际关系网非常有价值,因为它通常可以帮助你通过简历筛选。大多数公司的正常流程是创建一个职位发布,接收数百名申请人,然后使用一些流程来筛选简历,以选择谁将继续前进。挑选简历的过程,以我的经验来看,是最吵闹的。问题是非常大的公司必须有一个非常标准的过滤器才能处理如此大量的简历,而较小的公司往往几乎没有标准的流程。所以,如果你不完全符合大公司的要求,你就有麻烦了。在小公司,你可能不会被注意到,仅仅是因为你的简历从来没有被看过,或者可能是公司审查你简历时的偏见对你不利。

那么网络有什么帮助呢?建立关系网是获得推荐的第一步。曾在谷歌工作的丹·奎因说(2013 年)

没有比获得谷歌现任员工的推荐更有效的方法了。当我在那里的时候,公司面试的所有人中大约有 4%是员工推荐的,但他们占了被雇用人员的 20%以上。当一个谷歌人推荐你时,招聘团队会非常关注。

我发现几乎每个公司都是如此。公司渴望找到优秀的人才,他们知道他们的招聘过程很嘈杂。所以当一个优秀的员工推荐某人时,他们会倾听。

所以——我的建议是建立关系网,这样你就可以得到推荐,但是从哪里开始呢?以下是一些建议:

  • 开始和人们交谈。轻松地去了解别人,并真诚地向他们学习。你班上可能有你不认识的人——去认识他们吧!想象一下,当你得知你曾经坐在像马克·扎克伯格这样的人旁边,却从来没有和他说过一句话。那感觉很糟糕。
  • 将人际关系网视为给予的机会,而不仅仅是索取。亚当·格兰特有一本名为《给予与索取》的优秀书籍,讲述了作为给予者的价值。人们很容易将人际关系视为试图从某人身上获取价值。我建议你反其道而行之,试着给你的网络赋予价值。通常,这也会给你带来最大的价值。
  • 不要害怕走出你的舒适区去拓展你的人际网络。登上 meetup.com号,找到和你志趣相投的人。联系 LinkedIn 上你钦佩的人。想在脸书找份工作吗?尝试与公司的一些当前数据科学家联系。我很惊讶人们有多么愿意联系。注意:在 LinkedIn 上联系时,不要咄咄逼人,也不要泛泛而谈。以我的经验来看,一封简短、礼貌的短信,表明你理解这个人是做什么的,以及为什么联系是有意义的,会大有帮助。如果他们没有回应,那也没关系,我会避免咄咄逼人。

人脉需要时间,所以越早开始越好。但是,希望通过发展和扩大你的人际网络,你会有了解你和你的技能的人,他们会更愿意给你介绍一份工作。

做一些独特的事情

当我第一次开始雇用数据科学家时,最让我惊讶的事情之一是所有候选人的感觉是多么相似。大多数候选人的 GPA 都不错,知道 Scikit-Learn 和 Pandas,有一些像垃圾邮件分类或情感分析这样的学校项目,甚至一些深度学习的知识也变得越来越普遍。这一切都很好,但问题是,虽然你是一个好的候选人,但你不是一个必须具备的候选人。

你在简历和面试中的目标不应该是在离开公司时认为你是一个强有力的候选人。应该让他们认为你是最佳人选,他们最好现在就雇佣你。

以下是我发现的一些有助于候选人脱颖而出的事情:

  • 阅读、理解并完成一篇研究论文。最好是学生不经常实现的(再次强调——努力脱颖而出)。确保你的代码在 GitHub 上,甚至写一篇关于你的经历的博客。
  • 通过端到端的机器学习获得定义和解决问题的经验。比如,也许你对梦幻足球充满热情。谈谈你如何定义你的问题,组装你的数据集,分析数据,做出预测,并评估这些预测,以做出更好的幻想足球决策,这真的很有价值。成为一名伟大的数据科学家不仅仅是理解所有的算法。这种类型的项目表明您可以执行整个数据科学流程。
  • 花时间去了解公司和工作要求。然后修改你的简历和回答,突出你的技能与公司的要求相符合。这似乎是显而易见的,但在我的经验中很少做得好。
  • 为开源做贡献,拥有一个活跃的 GitHub 账户。如今,几乎每个人都链接到 GitHub 账户,但除了几个学校项目,它们几乎都是空的。不知道如何开始为开源做贡献?我建议看一下 Scikit-Learn 关于投稿的指南。他们对初学者如何入门有非常明确的指导方针。设定一个目标,每周向 GitHub 推送一些代码,你将开始开发一个可靠的活动历史来展示。

有一个成长的心态

成长心态是理解能力和智力是可以发展的。德韦克博士创造了这个术语,发现了,“当学生相信他们可以变得更聪明时,他们明白努力会让他们变得更强大。因此,他们会投入额外的时间和精力,从而获得更高的成就。”谷歌还发现,成长思维是成功经理人的一个关键特征。

我非常支持成长型思维,这也是我在招聘时寻找的关键品质之一——尤其是初级职位。我发现具有成长心态的人更有可能将挑战和失败视为成长的机会,接受反馈,并推动自己和团队取得更多成就。我对培养成长心态的建议是:

  • 通过不断学习来检验这个想法。如果能力和智力能够得到发展,那么就把工作放在每天去做,并分析结果。我个人确保每天至少花 30 分钟的空闲时间来学习。我对结果感到惊讶。这是我第一次学习强化学习,GANs,CSS,JS,还有很多更多的话题。
  • 分享你的成长。当你学习和发展新技能时,通过 GitHub、LinkedIn 和 Medium 等渠道分享它们。分享的行为将有助于巩固你的知识,并经常把你介绍给其他有成长心态的人。
  • 专注于你能控制的。在某种程度上,在你对自己的知识感到满意之前,你无法控制学习一个领域要花多少时间。当我刚开始学习强化学习的时候,对我来说是一个缓慢的过程。如果我专注于在一定的时间内“掌握”这个领域,那就很容易放弃。相反,我专注于我能控制的东西:我付出的努力。我当时的目标是每天花 30 分钟学习强化学习。我花了多长时间适应这个地区并不重要。
  • 不要害怕拓展和学习数据科学以外的领域。如果你想让学习成为你一生的目标,你就需要让学习变得愉快,并且追随你的兴趣。我花了整整一个夏天来学习如何建立和部署我自己的网站。我还花了一些时间学习围棋语言。
  • 试着将失败和挑战视为通往成功和学习的路标。没有人喜欢失败,但是没有失败你不会成长。将失败视为你将自己推出舒适区并不断成长的标志。现在,这只有在你真的花时间思考你的失败以及如何成长和从失败中学习的情况下才有效(然后投入工作去做)。此外,在失败中要有策略。虽然你肯定会从一个耗费了你一生积蓄的商业想法的失败中吸取教训,但那次失败将是非常严重的,而且这条路只能在深思熟虑后才能走。其他故障要安全得多,并且可以通过更少的预先分析来探索。比如我应该花时间学习话题 x 还是话题 y?如果你“失败”并选择了一个你不喜欢的话题,那么转向新的话题是相当容易的。

最后

我对希望进入数据科学领域的人的建议是要有战略眼光,建立关系网,做一些独特的事情,并有一个成长的心态。我也在 LinkedIn 上提出了这个问题,所以如果你想查看其他人的建议,你可以在这里查看:

[## Tyler Folkman 在 LinkedIn 上写道:“我正在整理一篇文章,给那些想要……

2019 年 9 月 23 日:泰勒·福克曼在 LinkedIn 上发帖

www.linkedin.com](https://www.linkedin.com/posts/tylerfolkman_datascience-firstjob-advice-activity-6581901513793384448-gq1P)

这篇文章也可以在这里找到。

星巴克:分析咖啡

原文:https://towardsdatascience.com/starbucks-analyze-a-coffee-b4eef811aa4a?source=collection_archive---------10-----------------------

星巴克拥有独特的方式与购买其产品的顾客建立联系并给予奖励。星巴克奖励计划允许该公司创建忠诚度计划,通过奖励购买特价产品的忠诚顾客。

介绍

S tarbucks 是一家全球性咖啡公司,在 75 个国家销售咖啡、茶、浓缩咖啡、面包和外卖。该公司的价值观之一是“创造一种温暖和归属感的文化,欢迎每一个人。”因此,它利用多种渠道营销其产品,从社交媒体到电视插播和广告。星巴克通过运用营销媒体渠道的组合来执行其非凡的营销策略,创造品牌知名度。星巴克不仅了解它的产品和顾客,而且还了解顾客如何使用技术。星巴克应用程序使客户能够跟踪参与商店的优惠和欢乐时光交易。它允许客户赚取并收集(每美元收集两颗星),可在店内或通过该应用进行兑换。

星巴克执行副总裁兼首席战略官马特·莱恩表示:“由于每周有* 1 亿顾客光顾我们的门店,我们正在寻找更多直接和私人接触的机会,为他们提供有意义的特别福利和优惠。”。

在这里,我们将调查和分析三个模拟人们如何做出购买决定以及促销活动如何影响这些决定的文件。A 清理分析后的最终数据的潜行:该数据包含发送给 14,825 客户8 个要约的信息,这些客户在完成至少一个要约的同时进行了 26,226 笔交易。以下是两个例子,说明星巴克通过应用程序向顾客提供优惠,鼓励他们购买产品和收集明星。

Buy One, Get One (BOGO) is one of the offers that will be analyzed in our data

Another type of the offer that Starbucks sends to the customers

奖金 :下图是一个交互式的日爆图,显示了更多关于交易数量的细节客户收到要约,通过使用的渠道之一查看该要约,然后进行交易在该要约期限结束前完成要约

Click on the interactive chart to see the number of transactions of two offer type, eight offer ID, and gender.

分析及其结果只是观察性的,不是正式研究的结果。下面列出了一般的业务问题,以指导我们通过分析开发一套启发式方法,其中的发现不能保证是最佳的或合理的。这是我的 Github 库,里面有所有需要的代码。

商业问题

分析的目的是检验星巴克的顾客对一个提议的反应,不管这个提议是 BOGO 还是折扣。并非所有的顾客都有相同的动机去查看报价,然后进行交易以完成报价。许多因素在影响客户如何做出购买决策方面发挥着重要作用;例如,一些客户更喜欢让他们收集越来越多的星星来获得独家津贴甚至免费产品。有时,特定年龄组的顾客更喜欢与其他年龄组不同的产品。此外,我们应该记住,女性顾客对报价的反应可能与男性顾客不同。可以从很多方面进行调查分析,寻找这类问题的答案。所有这些都将有助于星巴克锁定目标顾客,然后根据顾客群个性化定制产品。可以问很多问题;下面是我们将要调查的一些内容:

1.至少收到一份报价的客户数量是多少?
2。谁通常在星巴克消费更多,女性还是男性?
3。对于消费更多的顾客;谁的年收入更多?
4。就性别而言,大多数星巴克顾客的年龄是多少?
5。自优惠活动开始以来,顾客在任何时候都花了多少钱?
6。我们能否按年龄组或性别找到最受欢迎的优惠,然后将其与其他优惠,甚至另一个年龄组的优惠进行比较?
7。哪个优惠对星巴克最有利?BOGO 优惠和折扣优惠有区别吗?如果是这样,男性顾客对这两种报价类型的反应是否和女性顾客一样?

数据集

我们已经拥有和将要读取、清理和分析的数据集:

  • portfolio.json —文件中各变量的说明:
    -id:offer id
    -offer _ type
    -难度:完成一个要约所需的最低花费
    • 奖励:完成一个要约所给的星级
    • 持续时间:要约开放的时间,以天为单位
  • profile.json —文件中各变量的解释:
    • 年龄-成为 _ 会员 _ 日期:客户创建 app 账号的日期
    • 性别
    • id :客户 id
    • 收入
  • transcript.json —文件中各变量的解释:
    • 事件:记录描述(交易、收到要约、查看等。)
    • :客户 id
    • 时间:自报价开始起的小时数
    • :报价 id 或交易金额,视事件而定

数据准备

如果您想查看最终结果,而不想深入了解技术细节,请跳到数据探索部分。

: 在清洗过程中,一些变量的名称和顺序已经改变,以便于交流。

对这三个文件进行了许多修改和准备,以获得一个最终的干净数据集,该数据集包含每个变量所需的所有信息,从优惠类型到性别和年龄组。已经解决和解决的要点是:

1.第一部分

  • 简档文件中的年龄变量包含一个最大值 118 岁,这被认为是一个不寻常的值,将进一步调查。结果,我们发现有 2175 个客户在收入和性别信息方面没有值。配置文件中的所有空值都是年龄值为 118 的客户的一部分。因此,作为配置文件清理过程的一部分,值为 118 的行将被删除,这导致我们拥有 14825 个客户,而不是最初的 17000 个客户。

Printing the number of nulls, and then the age of customers who have nulls

  • 投资组合文件中的渠道变量列出了一个字段中用于报价的所有渠道。因此,我们拆分渠道,其中每个渠道本身成为一个变量,如果它已被用作特定报价的渠道,则值为 1 ,而值 0 表示它尚未被使用。

Code for splitting the channels

A view of the channels before being split into 4 variables

The portfolio data after splitting the channels

  • 组合文件中的持续时间变量将在清理过程中发挥主要作用,它将与抄本文件中提供的每个抄本的时间进行比较。因此,它被转换为以小时表示,而不是以时间变量表示的天数。
  • 简档文件中的变成 _ 成员 _ 开变量可用于查找大多数顾客加入星巴克应用程序的时间趋势。因此,首先,该列被转换为日期而不是整数,然后创建了一个按membership_period ,其中显示了客户成为会员时的

Before converting become_member_on variable

After converting the variable to date and creating membership period

  • 抄本文件中的变量包含了一系列信息,这些信息取决于客户所做的事件。如果客户进行了交易,这意味着该值是交易金额。否则,我们将获得客户已经收到、查看或完成的优惠 id。因此,我们将拆分为两列:记录(报价 id 或交易)和记录 _ 值(金额或 id)。因此,创建了两个新的数据集。第一个是报价,包括客户已收到、查看或完成的客户 id报价 id 等信息。另一个文件是具有交易金额而不是报价 id 的交易

  • 基于针对要约的事件变量创建的三个数据框架,创建了新的数据框架offers _ count;已接收、已查看或已完成。这三个集合被合并以创建完整的比较,该比较说明了接收、查看或完成报价的客户数量,包括完成百分比。

if complete(not_viewed) is positive that indicates some customers completed an offer without viewing it

2.第二部分

在浏览数据以找到启发式发现之前,让我们总结一下我们将在探索步骤中关注的重要文件,然后合并它们以创建一个最终的、干净的数据集用于进一步分析。

A.轮廓

B.处理

C.提议

D.报价比较

created by merging offers_count data and portfolio data after being clean

  • 这四个数据集被合并以创建将被分析的完整数据。然后,根据我们想要使用的变量创建子数据集。例如,可以只为女性顾客创建一个子数据集,为只完成至少一个报价的女性顾客创建另一个子数据集。此外,我们还可以为 only offer 5 创建一个子数据集,其中只有男性客户完成了该报价,并且在报价结束前至少进行了一次交易。
  • 客户 id报价 id在整个数据集中进行了清理,以便在分析时有简单的数字,而不是散列。
  • 通过比较交易的时间和要约的持续时间,我们删除了要约结束后发生的交易。

接下来,我们将检查从最终的干净数据集创建的每个子数据集,以回答之前发布的问题。

数据探索

请注意,所有图表都是交互式的,因为当悬停在图表的任何部分时,您可以获得更多信息。此外,一些图表在左上角有过滤器,您可以通过性别报价 id 过滤图表。

1.客户数量

甜甜圈图显示了女性客户占 41.30%男性客户占 57.20% 的数据总体情况,无论他们是否在要约结束前完成要约、达成交易。还有,选择其他为性别的客户只占 1.43% 。我们是否可以认为,男性顾客越多,就意味着他们的交易量就越大?接下来,我们将进一步调查这些数字。

2.按性别分列的收入

我们可以看到,*均而言,顾客一年挣的顾客少。事实上,女性顾客的年收入高于所有性别类型的*均收入。当顾客*均每年挣大约7.1 万时,顾客*均每年挣大约6.1 万

这里,该图表明,总体而言,我们的大多数客户收入在 50k75k 之间。*均每收入率客户数为 163 个客户。因此,当少数人每年挣超过 100k 时,一些顾客挣不到 50k 而另一些挣在 76k100k 之间。总体来看,我们可以看到大多数客户赚在 60k75k 之间,大多数客户赚 45k60k 。接下来,我们将确认女性和男性客户收入比率之间的差异。

在这里,我们证实了以前的收入分布的发现。该图证实,所有性别类型的大多数顾客的收入在 40k60k 之间。大多数顾客的年收入在 60k80k 之间,而大多数顾客的年收入在 40k60k 之间。

3.按性别划分的年龄

箱线图描述了按性别分列的年龄分布概况。他们显示,*均而言,女性顾客比男性顾客年龄大。

从另一个角度看按性别划分的年龄分布。箱线图证实了大多数男女顾客的年龄都在 40 岁到 60 岁之间。

4.交易的时间和金额

自优惠开始以来的交易趋势显示,*均而言,从优惠开始到 10 天内的任何时间,女性顾客支付的金额都比男性顾客支付的金额多**。回到我们在第一张图中关注的问题;尽管男性顾客的数量更多,但女性顾客支付的费用比男性顾客支付的费用更多。唯一的例外是在要约开始后 228 小时后进行的交易。自优惠活动开始以来,*均而言,所有顾客在任何时候支付的总金额为16.55 美元我们可以看到女性顾客支付的比任何时候的*均都多!而男性顾客支付的时间比*均水*少。同样,我们可以观察到一些* 高峰 随着时间的推移,男女双方*均比*时付出更多。这可能是在周末或白天的特定时间。***

该图显示了自这些优惠开始以来的任何时间在两个优惠上花费的*均金额。我们可以看到,*均而言,所有顾客对优惠 5 的反应和支付都比他们在任何时候对优惠 7 的反应和支付都多

5.报价分析

Top offers by the total transaction amount

在这里我们可以看到,报价 5报价 7 是所有完成报价并完成至少一笔交易的客户中支付的总交易金额最多的:分别为$ 194632$ 149296.9,。接下来,我们将查看与优惠类型和性别相关的最高优惠。

Top BOGO offers by the total transaction amount

BOGO offers by the total transaction amount paid by gender

优惠 2 在四个 BOGO 优惠中获得最高金额,所有客户支付的总金额为 $110113.8 。总的来说,女性顾客支付的男性顾客支付的要多 BOGO 的任何一项优惠。顾客对报价 2报价 1 的支付最多。

Top Discount offers by the total transaction amount

Discount offers by the total transaction amount paid by gender

优惠 5 是四个优惠中金额最高的,所有顾客共支付194632.34 美元。总体而言,在任何折扣优惠中,女性顾客比男性顾客支付的顾客对优惠 5优惠 7 的支付最高。

6.提供完成率

在之前的清理过程中对数据进行了进一步清理之后,下面是每个职位按性别划分的完成率比较。完成百分比来自完成报价的客户数量与收到报价的客户数量。所有客户的总体完成率;其他Offer 5 是最受欢迎的 Offer,完成率为 82%。显然,女性顾客对优惠的回应率总是高于男性顾客。两种性别都最喜欢出价 5 英镑。然而,尽管超过 80%的女性客户完成了报价 3** 和 4 ,但*均有 55%的男性客户完成了这些报价**。****

柱状图展示了之前发现的数字,从中我们可以看到女性顾客对优惠的行为和男性顾客行为之间的明显差异。总体来说, offer 8 是最不热门 offer, offer 5 是最热门 offer 男女通用。报价 8最不受女性客户欢迎的报价,而报价 3** 是最不受男性客户欢迎的报价。**

该图显示了所有客户女性男性的每个年龄组的每次报价完成率。比如在年龄层 35 岁offer 6最高完成率 82.61% 。而年龄层 25 岁更喜欢报价 5 最多,完成率 77.55%

调查结果摘要

  1. 向 14,825 名客户发送了八个优惠(4 个 BOGO 和 4 个折扣),他们完成了 26,226 笔交易,同时完成了至少一个优惠
  2. 在所有数据中,女性客户占 41.30%,男性客户占 57.20%,无论他们是否在要约结束前完成要约、达成交易。
  3. *均来说,男顾客一年赚的钱比女顾客少。女性顾客的年收入高于所有性别类型的*均收入。女性顾客*均年收入约为 7.1 万英镑,而男性顾客*均年收入约为 6.1 万英镑。
  4. 所有性别类型的大多数客户收入在 4 万到 6 万之间。大多数女性顾客年收入在 6 万到 8 万英镑之间,而大多数男性顾客年收入在 4 万到 6 万英镑之间。
  5. *均而言,女性顾客比男性顾客年龄大。男女顾客的年龄大多在 40 至 60 岁之间。
  6. *均而言,自优惠开始后的任何时候,所有客户支付的总金额为 16.55 美元。女性顾客在任何时候都比*均水*付出更多!而男性顾客大多数时候支付的费用低于*均水*。
  7. 报价 5 和 7 是所有完成报价并至少完成一笔交易的客户支付的最大交易总额:分别为 194,632 美元和 149,296.9 美元。*均而言,所有客户对优惠 5 的反应和支付的费用几乎总是高于他们在任何时候对优惠 7 的反应和支付的费用。
  8. 在 BOGO 的四个优惠中,优惠 2 的金额最高,所有客户支付的总金额为 110113.8 美元。女性顾客比男性顾客为 BOGO 提供的任何产品支付更多的钱。
  9. 在四个折扣优惠中,优惠 5 的金额最高。女性顾客比男性顾客支付更多的折扣。优惠 5 是最受欢迎的优惠,完成率为 82%。
  10. 就客户年龄而言,25 岁的客户完成率最高,为 77.55%。而 35 岁和 45 岁的客户更喜欢 offer 6,完成率分别为 82.61%和 83.33%。

星巴克优惠优化

原文:https://towardsdatascience.com/starbucks-offer-optimisation-cdf9bcedd48a?source=collection_archive---------33-----------------------

介绍

促销优惠目前相当普遍。几乎每一家销售消费品的公司都会时不时地推出某种促销活动——无论是因为竞争加剧,还是为了扩大客户群或增加收入。由于发送这些报价是有成本的,所以通过设计有效的促销策略来最大化这些报价成功的可能性是至关重要的。

在本帖中,我们将分析模拟促销优惠数据,这些数据模拟了星巴克奖励移动应用程序上的客户行为,以获得商业见解,然后将这些发现转化为一个“可解释的”机器学习模型,该模型将预测客户是否会对优惠做出反应。目标是只向那些更有可能响应的客户发送报价,并且只发送那些最有可能成功赢得客户的报价。

对于这个项目,我们将遵循最广泛使用的分析过程模型 CRISP-DM 。

商业理解

每隔几天,星巴克就会向手机应用程序的用户发出一次报价。优惠可以仅仅是饮料的广告,也可以是实际的优惠,如折扣或 BOGO(买一送一)。某些用户可能在特定的几周内收不到任何优惠。

并非所有用户都收到相同的报价,这是这个数据集要解决的挑战。

这个数据集是真实星巴克应用程序的简化版本,因为底层模拟器只有一种产品,而星巴克实际上销售几十种产品。

每个报价都有一个难度级别,并且在报价到期前有一个有效期。例如,难度级别为 7 的 BOGO 报价可能仅在 5 天内有效。这意味着如果顾客在优惠到期前消费 7 美元或更多,他将免费获得价值 7 美元的产品。信息优惠的难度级别为 0,因为它们不要求进行任何购买。它们也有有效期,即使这些广告只是提供产品信息;例如,如果信息性报价有 7 天的有效期,我们可以假设客户在收到广告后的 7 天内感受到了报价的影响。

然后是客户数据,其中包含人口统计信息,如年龄、性别、收入以及会员开始日期。

有交易数据显示用户在应用程序上进行的购买,包括购买的时间戳和购买的金额。该交易数据还包含用户收到的每个要约的记录,以及用户实际查看要约的记录。也有用户完成报价的记录。

我们将结合交易、人口统计和优惠数据,然后标记有效的客户-优惠组合。有效报价是指客户受到报价的影响并进行交易以完成报价的报价。接下来,我们将进行探索性数据分析,以培养对客户和/或与优惠有效性相关的优惠属性的直觉。我们将使用我们在数据分析阶段的发现来建立一个受监督的机器学习模型,该模型将客户和提供细节的组合作为输入,并预测它是否将是一个有效的组合。我们将只发送那些模型预测对客户有效的报价。

数据理解

在这一节中,我们将粗略地看一下数据,以便对数据形式的一切有一个高层次的了解。

数据包含在三个文件中:

  • portfolio.json —包含报价 id 和关于每个报价的元数据(持续时间、类型等)。)
  • profile.json —每个客户的人口统计数据
  • transcript.json 记录交易、收到的报价、查看的报价和完成的报价

以下是文件中每个变量的模式和解释:

portfolio.json

  • id(字符串)—优惠 id
  • offer_type (string) —优惠的类型,即 BOGO、折扣、信息
  • 难度(int)——完成一项提议所需的最低花费
  • 奖励(int) —为完成一项提议而给予的奖励
  • duration(int)-要约开放的时间,以天为单位
  • 频道(字符串列表)

profile.json

  • 年龄(整数)—客户的年龄
  • 成为会员日期(int) —客户创建 app 帐户的日期
  • 性别(str) —客户的性别(请注意,有些条目包含“O”代表其他,而不是 M 或 F)
  • id (str) —客户 id
  • 收入(浮动)—客户的收入

抄本. json

  • 事件(str) —记录描述(即交易、收到的报价、查看的报价等。)
  • 人员(字符串)—客户 Id
  • time (int) —测试开始后的时间,以小时为单位。数据开始于时间 t=0
  • value —(字符串字典)—报价 id 或交易金额,具体取决于记录

以下是数据概述:

  • 有 10 个报价,这些报价的子集被发送给 17000 个客户。
  • 报价有效期从 3 天到 10 天不等。
  • 报价的难度从 0 到 20 不等。最容易的报价的购买金额阈值为 5,最难的报价的购买金额阈值为 20。
  • 优惠相关事件和交易数据的有效期为 30 天。
  • 最*一次会员是 2018 年 7 月,说明数据是 1 岁。

数据准备

在这里,我们将首先进行数据辩论,然后使用可视化进行数据分析。

数据清理

对于每个数据集,我们将评估数据的不一致性和特征,然后我们将使用清理功能一起解决这些问题。

在数据理解阶段,我们知道客户 Id 和报价 Id 列中的数据不是用户友好的格式。我们需要使用一个通用的映射函数将这些列转换成更易读的格式,该函数将唯一的整数值映射到每个 id。

根据我们的评估,以下是我们需要遵循的清洁步骤。

投资组合

  • 将唯一的整数 id 映射到每个优惠 id。
  • 将频道分成单独的列。
  • 放弃电子邮件渠道,因为它是所有报价的公共渠道。

简介

  • 将唯一的整数 id 映射到每个人。
  • 删除 118 岁人员的概要文件,因为这是为缺少性别和收入数据的人员填充的默认年龄。
  • 将“成为成员日期”转换为日期格式。
  • 从“成为成员于”创建新列“成员资格 _ 持续时间”,因为“成为成员于”列在其当前格式下不是很有用。我们将以最*的“成为会员日期”作为参考,以天为单位计算会员持续时间。
  • 删除“成为成员于”列

成绩单

对于抄本数据,清理过程稍微复杂一些。以下是初始步骤:

  • 将唯一的整数 id 映射到每个人,并使用在清理个人资料和投资组合数据中使用的 id 映射字典提供
  • 从值列提取金额、优惠 id 和奖励
  • 隐蔽时间从几小时到几天。由于优惠持续时间以天为单位,这将帮助我们比较数据,并根据优惠接收日期和优惠持续时间得出优惠到期日期。
  • 将抄本数据帧分割成包含交易和非交易数据的两个独立的数据帧。

交易金额没有映射的优惠 id。因此,了解客户在特定优惠期间消费金额的唯一方法是,总结客户在优惠期间的交易金额。

让我们画出交易金额。

大多数购买金额在 100 美元以下。然而,有许多高价值交易,最大交易金额高达 1062 美元。我们从投资组合数据中得知,最困难的报价要求客户花费 20 美元或更多。因此,远远超过 20 美元的高价值交易可能是团体订单,不受促销优惠的影响。出于我们的分析和建模目的,我们将使用四分位数范围中的最大阈值将这些交易标记为异常值。在要约期内,如果客户有一笔或多笔异常交易,我们不会将其视为客户的有效要约。

接下来,我们将按照以下步骤将所有数据集合并到单个数据帧中:

  • 通过为事件创建单独的列,将 non_transactions 数据转换为宽格式。
  • 根据交易数据,计算每位客户在 30 天促销期间的总消费金额。从该计算中排除异常交易。
  • 使用通用客户和报价 id 列将所有数据集合并到一个数据框架中。
  • 对于多次向客户发送相同报价的情况,我们将只考虑第一次。

识别受影响的客户

在我们绘制数据以寻找趋势和模式之前,我们需要对客户进行分类,并提供有效和无效类别的 id 组合。

为此,我们将查看发送给客户的每份促销优惠,并确定该优惠是否影响了他/她。根据客户对促销活动的反应,可以分为四大类。

  • 不受影响:如果客户看到了报价,但没有完成,那么他不受报价的影响。他知道该优惠,但没有受到影响而购买。
  • 受影响:客户查看了报价并完成了交易。经验法则是,如果客户意识到该优惠,然后选择完成它,那么该优惠会影响他。但是,我们将排除那些符合此标准但在报价期间有异常交易的客户-报价组合。
  • 完成但未查看:客户完成了报价但未查看,或者在报价完成后查看了报价。因为他不知道这个提议,所以这并没有影响到他。可能他或她是一个高级客户,不管促销优惠,他们的*均消费都比普通客户高。也可能只是普通顾客的一次性高额交易。无论哪种方式,它都不同于前两类客户报价组合。我们无法断定,如果顾客看到了报价,他是否会受到影响。
  • 未查看未完成—这些是客户未查看或在到期后查看的不完整优惠。同样,我们也不能说如果顾客看了报价会有什么样的反应。

在合并的数据中,这些类别将分别映射到 0、1、2 和 3 值。

值得一提的是,这些不是客户分组,而是客户-报价组合,因为同一个客户对不同的报价会有不同的反应。此外,理想情况下,我们将清理与第三和第四类相关的数据。但在此之前,我们将绘制所有四个类别的数据,并看看它们如何相互比较。

这里要注意的另一件事是,由于信息提供从未完成,默认情况下,它们将属于“未受影响”类别。

数据分析

在本节中,我们将执行可视化数据分析,以获得对数据的一些关键见解,并找到与相关业务问题相关的答案。

我们将绘制一些客户和优惠属性,以直观地了解这些属性如何影响客户对促销优惠的反应。在我们对这些图进行视觉分析的过程中,我们将忽略信息提供的趋势。

分类特征

对于分类特征,我们将通过比较不同类别的响应比率(受影响与未受影响)来判断影响。

报价类型

  • 似乎顾客对折扣的反应比 BOGO 更好。

优惠 Id

  • 根据客户回应率,id 为 7、6 和 4 的优惠分别是前三名。以下是这些优惠的详细信息。

7:10 天内消费 10 美元,获得 2 美元作为折扣。

6:7 天内消费 7 美元,获得 3 美元作为折扣。

4:7 天内消费 5 美元,免费获得价值 5 美元的产品。

  • 这里要注意的一个有趣的点是,BOGO 的出价与出价 id 7 的难度相同(出价 id 1 和 2 ),即使奖励比率更高,成功率也更低。消费者似乎更喜欢以折扣价购买产品,而不是免费获得额外的产品。

难度

  • 难度为 7 级的提议有最好的回应率。
  • 对于具有最高难度级别的报价,大多数报价没有被客户查看。但是,难易程度和回答率之间没有明确的相关性。

持续时间

  • 持续时间越长的优惠成功率越高,可能是因为顾客有更长的时间购买更多的东西。

性别

  • 女性比男性有更好的回应率。
  • 尽管属于“其他”性别的顾客数量相对较少,但他们的回应率高于男性。

数值特征

接下来,我们将通过比较回应和非回应要约的分布来探讨数字特征在成功要约中的影响。

总花费金额

  • 受优惠影响的顾客*均每小时花费的时间比没有响应的顾客多得多。这在预期行上。
  • 总花费几乎总是在 200 美元以下。
  • 难度级别分别为 20 和 10 的出价 Ids 5 和 10 的总花费金额略高。
  • 似乎有两大类。完成报价的人(第 1 类和第 2 类)和没有完成报价的人(第 0 类和第 3 类)。
  • 0 和 1 的支出总额分布相似,段 2 和 3 也是如此。
  • 并且没有明显的趋势来将观看的和未观看的片段彼此区分开来。让我们看看这一趋势是否适用于其他客户属性,如年龄、收入和会员资格期限。

收入

  • 大多数优惠都发给了收入在 40-80,000 之间的客户。
  • 在所有报价中,受影响的部分比不受影响的部分属于高收入群体。可以有把握地推测,属于高收入群体的客户更有可能对促销优惠做出反应,而不管优惠种类如何。
  • 就像“支出总额”一样,细分市场 1 和 2 与细分市场 0 和 3 具有相似性。这种相似性没有我们在“总支出”中看到的那么深刻。
  • 与“总支出”不同,已完成和未完成部分之间没有明确的界限。

年龄

  • 大多数优惠都是发给 40 到 70 岁的顾客。
  • 不同细分市场之间的“年龄”分布差异不如收入和支出总额的差异大。然而,与其他类别相比,第 3 类似乎总是属于较低的年龄组。最年轻的会员更有可能不查看和/或不完成报价。

会员期限

  • 大多数优惠是发给会员资格不到 2 年的客户的。
  • *均而言,对优惠活动做出回应的顾客成为会员的时间比没有做出回应的顾客长。
  • 成员资格期限很好地分离了不同的部分。这似乎是决定客户对报价作出反应的可能性的一个重要特征。
  • 此外,在“每小时花费的金额”中观察到的趋势似乎或多或少也适用于此,即类别 1 和类别 2 具有相似性。类别 0 和 3 也是如此。然而,类别 3 比类别 0 具有更广泛的成员分布。

特征创建

从上面的可视化扩展,我们将创建一些更多的功能,将年龄,收入和成员资格持续时间等连续功能分离到不同的人口统计组。

我们将比较这些人口统计群体,以了解他们中的哪一个对优惠的反应更好。

难度比

难度比是由出价难度除以持续时间得出的。

  • 难度比较低的报价似乎有更好的响应率。

收入群体

  • 收入在 100,000 以上的客户的回答率最高,其次是收入在 80-100,000 之间的客户。
  • 从上面的图像中可以清楚地看出收入和客户反应之间的正相关关系。
  • 我们可以有把握地推断,收入超过 6 万英镑的人更有可能对这些提议做出回应。

会员范围

  • 会员时间不到 1 年的客户是响应最慢的客户。
  • 响应最快的客户是那些拥有 1 至 2.5 年(365-900 天)会员资格的客户,其次是拥有 2.5-4 年会员资格的客户。
  • 在会员资格达到 1-2.5 年后,回复率会随着会员资格持续时间的增加而持续下降。

年龄组

  • 80 岁以上年龄组的客户回答率最高,其次是 61-80 岁年龄组的客户。
  • 年龄和客户的反应之间存在正相关关系。老年顾客似乎比年轻顾客有更好的回应率。
  • 可以有把握地推断,40 岁以上的顾客更有可能对这些优惠做出反应。

建模和评估

在这一部分,我们将建立一个预测模型,预测客户是否会对报价做出反应。由于发送报价会增加组织的成本,我们不想向不太可能做出回应的客户发送报价。此外,我们不想错过向真正会做出回应的客户发送报价的机会。由于我们需要优化精确度和召回率,我们将使用 F1 分数作为模型评估指标。

为预测模型选择特征

作为第一步,我们需要只为模型选择相关的特性。我们的目标是建立一个预测模型,根据客户的人口统计数据和优惠属性,对客户和优惠 id 组合是否有效进行分类。我们将删除所有与交易数据相关的内容,包括“总消费金额”。尽管“总支出”很好地区分了“受影响”和“不受影响”的类别,但将其作为一个独立的特征将导致数据泄露。

此外,从数据分析部分,可以有把握地推测,没有明显的趋势将类别 2 与其他类别分开。尽管类别 1 和类别 2 有相似之处,但我们不能将它们合并,因为类别 2 中可能有一些高价值客户,他们的*均支出高于普通客户。向这些客户发送报价没有太大的商业意义。我们不能将类别 2 与“未受影响”组合并,因为这两个组之间没有相似之处。

但是,我们可以合并类别 0 和类别 3,因为它们具有相似的特征,并且可以不向没有查看报价的客户发送报价,即使在查看后也很可能不会做出响应。

朴素预测器

我们将从一个简单的分类器开始,该分类器对所有客户进行随机分类,并提供“受影响”或“不受影响”的 id 组合。

这仅仅是为了展示一个没有智能的基本模型将如何运行。我们可以用这个来比较我们将要构建的机器学习算法的性能。

似乎如果我们随机分配报价,有 50%的机会获得成功报价。

准备建模数据

当要素处于相对相似的规模并且接*正态分布时,许多机器学习算法会工作得更好。通常的过程是应用变换,例如,从数字特征中去除偏斜的对数变换。此外,最好是one-hot-encodee 分类特征,以避免在名义变量中引入*凡性等原因。

对于我们的初始模型,我们将不应用数值变换。稍后,我们将探讨这个选项来提高模型性能。

初始模型评估

我们将考虑以下监督模型,并查看哪种模型最能概括数据集:

  • 逻辑回归
  • Ada 增强
  • 随机森林
  • 轻型 GBM

对于这些模型中的每一个,我们将使用 5 重交叉验证来查看模型分数在不同的数据子集上如何变化。现在,我们将保留模型参数的默认设置。

结果如下:

LightGBM 是这里的赢家。它具有最佳的*均交叉验证分数,并且交叉验证分数的低标准偏差值表明模型在输入数据变化时的稳健性。

特征重要性和模型可解释性

我们将使用排列重要性来检查模型的特征重要性。它通过删除变量或移动行来检查模型结果的变化量,从而确定输入变量的权重。

报价难度、会员时长、收入、报酬、性别似乎是最重要的特征。

接下来,我们将查看一个使用 lime 的预测示例,以解释模型如何进行预测。

验证数据行预测的示例说明:

决策界限似乎或多或少地证实了我们在 EDA 阶段开发的直觉。

性能调整

在本节中,我们将使用 RandomizedSearchCV 通过调整 LightGBM 模型的参数来进一步提高模型得分。

  • num_leaves:较大的 num_leaves 值有助于提高准确性,但可能会导致过度拟合。为了防止这种情况,我们应该让它比 2^(max_depth).小
  • min_data_in_leaf:其最优值取决于训练样本数和 num _ leaf。将其设置为较大的值可以避免树长得太深,但可能会导致欠拟合。实际上,对于大型数据集,将其设置为数百或数千就足够了。
  • max_depth: max_depth 用于显式限制树的深度。
  • boosting _ type:“dart”通常提供更好的准确性

与使用默认参数的未优化模型的分数(0.79)相比,我们可以优化模型以获得更好的分数(. 80)。如果我们与朴素预测相比,使用这种模型可以大大提高我们成功报价的机会,而不仅仅是随机分配报价。

结论

倒影:

  • 清理抄本数据是这个项目最具挑战性的方面之一。
  • 优惠的难度和奖励金额以及会员期限、收入和客户年龄是决定优惠成功几率的最重要因素。
  • 折扣优惠类型、更长的持续时间、更低的难度是增加成功优惠概率的一些优惠属性。
  • 一些客户认为增加响应概率的原因是更高的收入(> 60 k)、更长的会员资格(甜蜜点在 1 到 2.5 年的范围内)、女性和更高的年龄(> 40 岁)。

改进空间:

  • 仍然有进一步改进模型性能的空间。我们可以简单地尝试其他高性能模型,如 XGboost、Catboost,看看它们是否比 LightGBM 更通用。另一个常用于提高模型性能的策略是将一堆模型堆叠在一起。此外,由于这是一个不*衡的数据集,我们当然可以探索的另一个选项是SMOTE——从少数类中过采样数据。
  • 使用交易数据来预测客户的反应会导致数据泄露。但是,与客户购买量相关的历史数据可以帮助我们更好地预测客户对报价的反应。例如,如果一个客户的*均支出比普通客户高得多,向他们发送低难度的报价就没有多大的商业意义。我们宁愿把高难度的报价发给他们。此外,根据目前的数据,很难判断信息提供是否有任何影响。将客户的历史*均消费率与优惠期的*均消费率进行比较有助于我们确定信息性优惠的效果。
  • 有很多情况下,顾客没有看就利用了优惠。从商业角度来看,我们最好避免发送这些报价。在我们的分析中,我们找不到有助于预测这部分客户的属性。然而,一个解决办法是提供优惠券。这样,只有希望利用优惠的客户才会完成优惠。
  • 由于所有的优惠都没有发送给所有的用户,我们可以通过将所有的优惠映射到所有的客户来创建一个数据集,然后预测客户对每个优惠的反应。如果一个客户可能会对多个报价做出反应,我们只需要选择那些能带来最大业务的报价,例如,难度最高或报酬率最低的报价。

本次实现的全部代码可以在 这里 访问。

星巴克的个性化服务——给正确的顾客提供正确的服务

原文:https://towardsdatascience.com/starbucks-offer-personalization-sending-the-right-offer-to-the-right-customer-14d4fbc20575?source=collection_archive---------15-----------------------

基于机器学习的个性化营销

星巴克可以说是世界上最成功的咖啡连锁店之一。早在 2010 年,谷歌就率先推出了自己的奖励应用。客户可以获得促销优惠通知,通过移动应用程序订购和支付,并为其订单赢得奖励积分。这使得星巴克不仅可以直接联系顾客,提高品牌忠诚度,还可以收集有价值的第一手顾客信息以及他们的交易行为。

但问题是,所有的用户都得到同样的优惠吗?假设你是星巴克的一名数据科学家,你会如何确定向每位客户发送最有效的优惠,以提高用户参与度?

目标

在这个项目中,我接受了这个挑战,我的目标是使用通过 rewards 应用程序收集的用户人口统计和行为属性来预测向个人客户发送什么样的最佳个性化报价,以最大限度地提高转化率。

此外,我想看看在整个客户群中是否有任何独特的子群,它们表现出特定的人口统计和购买行为模式,这使它们彼此区分开来。

数据集概述

有三个数据文件:

portfolio . JSON——包含每个报价的报价 id 和元数据。它包含以下属性:

  • id(字符串):报价 id
  • offer_type (string):优惠的类型,即 BOGO(买一送一)、折扣、信息(一种饮料的广告)
  • 难度(int):完成出价所需的最低花费。只有最低 BOGO 和折扣优惠,但没有信息。
  • 奖励(int):为完成一项提议而给予的奖励
  • duration (int):报价开放的时间,以天为单位
  • 渠道(字符串列表):手机、电子邮件等。

profile.json —每个客户的人口统计数据。

  • id (str):客户 id
  • 年龄(整数):客户的年龄
  • become _ member _ on(int):客户创建应用帐户的日期
  • 性别(str):客户的性别(有些条目包含“O”表示其他,而不是 M 或 F)
  • 收入(浮动):客户的收入

transcript.json —交易记录和优惠使用记录。

  • 人员(字符串):客户 id
  • 事件(str):记录描述(即交易、收到报价、查看报价、完成报价)
  • time (int):测试开始后的时间,以小时为单位。数据开始于时间 t=0
  • 值:(字符串字典)-根据记录,可以是优惠 id 或交易金额

抄本数据是我将用来设计用户行为特征的主要数据集。它包含模拟数据,模拟星巴克奖励应用程序上的真实客户购买和优惠使用情况,包括购买时间戳和购买金额。该交易数据还包含用户收到的每个要约的记录,以及用户实际查看要约的记录。当用户完成报价时,也有记录。

这是棘手的部分。在要约到期之前,每个要约都有一个有效期。用户可能会收到“买 10 美元买 2 美元优惠”,但用户在 10 天的有效期内从未打开过该优惠。顾客在那十天里花了 15 美元。数据集中会有要约完成记录;然而,客户并没有受到报价的影响,因为客户从未看过报价。对于信息性要约,如果用户在查看要约后的有效期内进行交易,他将被视为完成要约。

挑战

鉴于要约完成的规则和例外,数据清理和特征工程部分变得特别重要和棘手。

该项目的关键部分是从按时间顺序排列的活动日志中总结每个客户的交易行为,以将正确的交易归因于正确的优惠类型,并在用户级别上跟踪它们对不同优惠的转换。然后,这些设计的功能将与用户档案信息(如收入、年龄、性别和他们的会员资格何时开始)相结合,以提供每个客户的整体视图。

考虑到这一点,我解决问题的方法将遵循以下步骤。

(尤指为开车者设计的) 公路交通图

1.探索性分析&数据清洗:了解三个数据集,准备数据集

2.特性工程:在用户级从事务日志中创建属性

3.机器学习:建立一个多输出分类模型,以确定每个客户的最佳报价类型,按照转换的可能性排序

4.聚类:找出顾客中的子群体,星巴克可以根据每个群体不同的人口统计学或行为模式来确定不同的目标。

一.探索性分析和数据清理

一、简介数据

年龄和收入分布

年龄分布中有一些异常值——在 17000 名顾客总数中,超过 2000 人的年龄超过 110 岁,这似乎是不正确的。我将用 NaN 替换它们,然后填入中值年龄。收入有一个普遍但总的来说,看起来不错。有 2150 个 NaN 记录,稍后我也将填入收入中值。

成员任期

下面的左图显示,在大多数年份,男性顾客的增长远远超过女性。我将成员资格开始日期转换为任期的月数,作为一个数字人口统计属性。右边的直方图显示了分布情况。

二。投资组合数据

总共有 10 行 10 种优惠类型,因为这是真实星巴克优惠的简化版本。数据非常直观。

portfolio data snippet

三世。成绩单数据

这是我将使用的最重要的数据集。这是它最初的样子。

“值”列是一个字典,这里是唯一的键。

我们可以看到“优惠 id”出现了两次——当它带有“奖励”时,事件列显示“优惠已完成”,否则,事件要么是“优惠已收到”,要么是“优惠已查看”。当“金额”不为空时,事件始终为“交易”。

我将字典键分为 3 列:“offer_id”、“amount”和“reward”。两个“offer_id”键被合并为一列。

frequency of events after the clean-up

然后,我将脚本数据与 offer_id 上的投资组合数据连接起来,以查看不同报价类型之间的事件分布。

让我们检查一个人的旅程,以便更好地了解他完成要约时的事件顺序。在这种情况下,客户通过两次交易进行了两次报价转换。另外五笔交易是在没有报价的情况下完成的。

问题定义

有效报价转换的理由

为了使要约有效,导致转化的事件将按以下顺序发生:
1 .收到报价- >已查看报价- >交易- >已完成报价(BOGO 和折扣报价)
2。已收到报价- >已查看报价- >交易(信息性报价,但交易必须在有效报价期限内发生)

只有遵守了这两个转换顺序,我们才能认为要约已经完成。

还有几种情况被视为无效报价:
1。收到报价,但客户没有采取任何行动
2。offer received->transact->offer viewed-这也是无效的,因为此人没有在交易中使用该要约
3。在没有报价的情况下交易——这种类型的人无论有没有报价都会交易。从商业角度来看,我们可能根本不需要向他们发送报价。

记住这些,并知道我的目标是预测我们应该发送给每个客户的最佳报价,以最大限度地提高报价转化率,我需要建立一个用户级数据集,其中包括从脚本日志中提取的用户人口统计数据和每个用户的交易行为特征,以及他们对每种报价类型的响应。

二。特征工程

详细地说,这些是我想在用户层面上为机器学习模型设计的功能。

  1. 每种报价类型被接收的次数——用户是否执行报价:bogo_off_receivedinfo_off_receiveddiscount_off_received
  2. 交易总数——交易是否受要约激励:total_trans_cnt
  3. 总交易金额—总交易金额之和:total_trans_amt
  4. 收到的总奖励—从任何优惠类型收到的奖励总和:total_rewards_received
  5. *均交易金额—总交易金额/总交易笔数:avg_trans_amt
  6. 无要约交易次数——用户在无要约完成事件的情况下交易的次数:trans_cnt_no_offer
  7. 要约完成的交易次数—要约完成事件后用户交易的次数:trans_cnt_offer
  8. 任何报价的交易金额—报价完成事件的总交易金额:trans_amt_offer
  9. 要约激励的交易笔数比率—要约完成的交易次数/总交易笔数:offer_trans_cnt_ratio
  10. 要约激励的交易金额 raio 要约完成事件的总交易金额/总交易金额:offer_trans_amt_ratio
  11. 报价完成与报价浏览比率—完成的报价数/浏览的报价数:off_comp_view_ratio
  12. 要约完成与要约接收比率—完成的要约数量/接收的要约数量:off_comp_receive_ratio
  13. 每笔报价交易金额—包含报价的总交易金额/包含报价的交易笔数:trans_amt_per_offer
  14. 每次报价的奖励—收到的总奖励/完成的报价数:reward_per_offer
  15. bogo 报价完成数—查看 BOGO 报价后,BOGO 报价类型的“报价完成”事件数:bogo_comp
  16. 折扣优惠完成数—查看折扣优惠后,折扣优惠类型的“优惠完成”事件数:discount_comp
  17. 信息报价完成次数——在报价有效期内,查看信息报价后发生“交易”事件的次数:information_comp
  18. bogo 报价转换率—完成的 bogo 报价数/收到的 bogo 报价数:bogo_conv_rate
  19. 折扣优惠转换率—完成的折扣优惠数/收到的折扣优惠数:discount_conv_rate
  20. 信息报价转换率—完成的信息报价数/收到的信息报价数:info_conv_rate

模型的 3 个二元目标变量:

  • bogo_offer (0/1):如果用户在查看报价后,曾经有过 BOGO 报价类型的“报价完成”事件,则 1 否则 0
  • discount_offer (0/1):如果用户在查看优惠后曾有折扣优惠类型的“优惠已完成”事件,则 1 否则 0
  • information_offer (0/1):如果用户曾经有过“交易”事件,之后是“报价已查看”,则信息报价类型为 1 否则为 0
  • no_offer:如果用户从未回复过任何报价,只是在没有报价的情况下交易,那么我们可能没有任何报价推荐。这可以从上面三个报价类型中有三个 0 推断出来。这个变量不会在模型中使用,但可以用作参考。

正如我在开始时提到的,这一过程中最大的挑战是根据优惠类型,通过遵循导致优惠完成的特定事件顺序来识别正确有效的优惠。

本质上,所有有效报价相关特征都可以基于offer completion counttransactions amount from the offer conversion.来计算

特征工程的完整脚本相当长。基本步骤是:

  1. 对于配置文件数据中的每个用户 id,按照时间顺序从脚本日志中获取他们的活动。
  2. 遍历每个客户的交易记录。如果发现“收到要约”事件,根据要约持续时间计算其到期日期。
  3. 对于有效的 BOGO 和折扣优惠,如果“offer_completed”发生在“offer _ viewered”事件之后和到期之前,则在 BOGO/折扣优惠完成中加 1,并合计 offer _ viewered 和 offer_completed 之间的交易金额。
  4. 对于有效的信息要约,由于没有明确的要约转换事件,所以比较棘手。如果有交易发生在“要约 _ 已查看”事件之后,并且在要约持续时间内,那么我们可以假设这些交易是在信息要约的影响下进行的,因此我们将信息要约完成计数加 1,并将要约收到时间和到期时间之间的交易金额相加,作为要约交易金额的一部分。

在这个过程之后,我将用户人口统计数据与工程特性结合起来,作为用户属性的最终面板。

三。机器学习

计划是构建一个多输出分类模型,使用 3 种优惠类型作为目标变量 Y,使用上述工程要素(排除最后 6 个要素,因为这会导致信息泄露)以及个人资料数据集中的人口统计要素作为 x 来预测最佳优惠类型。请注意,用户可能在预测结果中有多个 1,在这种情况下,概率较高的优惠类型将在建议中优先考虑。

因为有多个输出,所以支持多输出的分类器的选择是有限的——决策树家族通常都支持多输出模型。

我会选择随机森林,原因如下:

  • 使用自举来选择每棵树的数据样本,并且在每个节点处仅使用特征的随机子集来决定最大化信息增益的最佳分裂。特征和数据样本选择中的随机化可以显著减少模型方差,从而不容易过度拟合。这是随机森林相对于决策树模型的最大优势。
  • 并行构建一组树,每个数据点分类的最终决定基于多数投票。该过程提供了对特征重要性的更好估计,即从林中的所有决策树计算出的*均杂质减少量。
  • 它不假设目标变量和特征之间的线性关系,使其在识别非线性类边界时更加灵活。此外,树模型在运行模型之前不需要太多的特征预处理,例如标准化或规范化。

模型结果

model performance metrics

模特表演非常好。区分每种优惠类型的转换者和非转换者的最重要特征是什么?

特征重要性

feature ranking from random forest

似乎reward_per_offeroffer_trans_amt是最重要的特性。三种产品类型的每种功能有何不同?

X 轴上的标签分别对应于三种报价类型。当它为 1 时,表示使用该优惠类型的人。例如,(1,1,0)表示对 BOGO 和折扣优惠有反应的人,但对信息性优惠没有反应。

很明显,使用所有三种优惠类型的人不仅在优惠上花费最多,而且交易总额也最高。这意味着我们越鼓励顾客使用优惠,他们就越有可能在店内消费。

此外,总的来说,BOGO 优惠比折扣和信息性优惠推动了更多的销售,因为总交易量较高的三个组都对 BOGO 优惠做出了回应。同样值得注意的是,使用 BOGO 和折扣优惠的人实际上*均花费了超过一半的交易总额。这些是星巴克最活跃、最有价值的顾客。这是一个积极的迹象,证明给予我们的优惠和奖励确实可以提高客户的参与度,从而推动整体销售。

现在,让我们来看看总体优惠完成率、由优惠推动的交易金额比率以及每次优惠的奖励是如何受到用户统计数据的影响的。

按人口统计提供使用情况

从上面的散点图中获得的关键信息:

  1. 要约完成率在开始时随着任期的增加而稳步增长,当男女用户任期在 20-30 个月之间时达到峰值,然后随着任期的增加而略有下降,尤其是对于男性客户。事实上,随着新用户习惯于应用程序并开始更频繁地利用好处,优惠转化率将会增长。在那个阶段之后,转换率变得*稳。
  2. 在收入达到 80000 英镑之前,报价完成率似乎也与收入呈正线性关系。之后随着收入的增加开始下降。当顾客的收入低于一定水*时,他们更倾向于使用优惠。超过这一收入水*后,使用要约激励交易的效果就会下降。
  3. 一般来说,女性客户的报价完成率高于男性客户,尤其是在任期早期和低收入阶段。
  4. 随着收入的增加,每次报价的*均回报稳步增长。
  5. 在几乎所有的任期、年龄和收入范围内,女性客户也倾向于在每次报价中获得更高的回报。部分原因是女性的录用完成率高于男性。这也意味着女性用户更倾向于使用 BOGO 或折扣优惠来获得奖励,因为信息性优惠不会给出奖励。

接下来,我想检查不同的人口统计群体对三种优惠类型的反应是否不同。

按人口统计的优惠类型

从这组散点图中有一些有趣的见解。

  1. 收入和任期似乎对出价转换率有显著影响,而年龄则没有。
  2. 在不同的年龄、收入和任期中,女性客户对 BOGO 要约的转化率稳定较高,而在大多数任期中,信息性要约往往对男性客户更有效(图 6)。
  3. 按任期划分的 BOGO 要约转换率显示出与整体要约完成率非常相似的模式——当用户的任期在 20-30 个月之间时达到峰值,然后开始急剧下降。另一方面,折扣优惠转换率随着任期的增加而稳定增长。
  4. BOGO 和折扣转换率都随着收入的增加而增加,在用户收入达到 8000 后略有下降。然而,随着收入的增长,信息报价的转换率持续下降。这是一个非常有趣的趋势,它实际上是有意义的,因为与 BOGO 和折扣优惠不同,信息优惠没有任何最低交易金额,使得使用信息优惠的难度比其他两种优惠小得多。这就是为什么它在低收入群体中更受欢迎。这也解释了为什么上图中每次优惠的奖励随着收入的增加而持续增加——BOGO 和折扣优惠通常都有奖励和使用优惠的最低交易金额,因此它们在高收入群体中更受欢迎。

预测任何给定客户的最佳优惠类型

如果模型预测客户有多种优惠类型,则根据概率的降序对建议进行排序。

以下是从测试集中随机选择的 20 个客户 id 的推荐优惠类型,较高概率的优惠在前面。如果客户只有交易,以前从未使用过任何优惠,模型将显示“不推荐任何优惠”。在商业环境中,如果用户愿意花 10 美元,我们甚至不需要给他“买 10 美元减 2 美元”的折扣。

更深一层—具体报价预测

既然我们可以预测最佳报价类型,我想知道我是否可以将它带到一个更细粒度的级别—使用与 X 相同的功能集来预测将哪个特定报价 id 发送给每个客户。我们的想法是,对于只喜欢使用低难度(最低交易)报价的客户,我们可能希望根据报价难度级别而不是宽泛的报价类型向他/她发送报价,因为同一报价类型的难度级别可能在相当大的范围内变化。

组合表中有 10 个报价 ids 个用于信息,4 个用于折扣,4 个用于 BOGO。如果用优惠类型+奖励+难度组合来表示每个优惠 id,可以得到 6 个唯一的优惠名称:“bogo_10_10”、“discount_5_20”、“discount_3_7”、“bogo_5_5”、“discount_2_10”、“informational_0_0”。

由于一些优惠 id 被映射到相同的优惠名称,它们被合并到一列中。如果用户曾经转换过同一类型+奖励+难度组合下的任何优惠 id,则该优惠名称将被标记为 1 else 0。

还是和以前一样,我把 3 个报价类型替换为 6 个报价名称 Y,在 X 中没有太大变化,除了我包括了 3 个在上一个模型中被排除的功能以避免信息泄漏:BOGO 的完成计数、折扣和信息。此外,我创建了一个名为“难度/报价”的新功能,它是使用每个已完成报价的最小交易(难度)的总和/报价完成的总数。我相信这一新功能在很大程度上说明了客户对享受优惠的最低消费的容忍度。

模型性能

有了这些额外的新特性,模型性能甚至从将报价类型切换到作为目标变量的实际报价得到了改进。为了确保高分不是仅由 0 类中的高准确性引起的,让我们打印每个报价模型的分类报告,它们看起来都不错。

特征重要性

正如我所料,“难度/报价”显然占据了几乎所有报价模型的主要特性。

预测任何给定客户的最佳报价

以下是使用与上次相同的预测函数从测试集中随机选择的用户的推荐优惠。

四。使聚集

在对发送给每位顾客的最佳优惠类型进行预测后,我想知道在整个星巴克顾客群中,是否有任何针对特定子群体的行为和人口统计属性的通用模式,将他们彼此区分开来。这种方式让我们不仅在个人层面上,而且在市场细分的背景下了解客户,这将有助于针对不同的客户群体制定不同的营销策略,使目标更加精确和有效。

cluster inertias vs. number of clusters

我在标准化的用户属性上拟合了 KMeans 聚类模型,使用了不同数量的聚类,并在每次迭代中提取惯性。使用肘方法,我决定使用 3 个集群,虽然折线图是非常模糊的。在用 n_clusters= 3 再次拟合模型后,我将数据反向转换回原始比例。

下面是 3 个分类的每个属性的分类中心。

cluster centers

从聚类中心,我们可以看到三个聚类的*均年龄几乎相同。集群 1 男性远多于女性,*均收入、交易金额和要约完成率最低。集群 0 和 2 在*均成员任期、总交易量和每次报价的交易量方面非常相似。然而,它们对于不同的报价类型明显表现出不同的偏好模式——我们可以通过一些可视化来证实这一点。

集群可视化

income vs. total transaction amount by cluster

第 0 类和第 2 类有一些高收入的高消费人群。

offer completion rate vs. transaction amount with no offer

集群 1 通常对出价没有反应。集群 2 似乎具有最高的*均报价完成率,而集群 0 在没有报价的情况下比集群 2 花费最多。

群组 0 的信息报价转换率为 0,而群组 2 的人显然在 3 组中最喜欢信息报价。

transaction amount per offer vs. rewards per offer

集群 0 显然*均每份报价有更高的回报,这意味着他们更倾向于使用回报更高的报价以及相应的更高的最低交易量。

集群描述

从上面的可视化和集群中心,我们可以看到每个集群在他们的交易行为和对不同报价的反应方面都有一套独特的属性,尽管他们在年龄、收入和成员任期方面有着非常相似的人口统计数据。

  • 第 0 类:这一类人受到折扣和 BOGO 等奖励的高度激励,几乎从不回应信息性的优惠。他们的*均收入最高,总交易量与集群 2 相似。虽然他们的报价完成率可能没有第 2 类高,但他们实际上在没有报价的情况下比有报价的情况下花费更多。这个群体是星巴克的常客,他们*均花费最多,对他们来说最有效的优惠是折扣,然后是 BOGO 优惠。
  • 第 1 组:这一组主要是休眠账户,他们通常不经常购物,对报价没有反应,交易也比其他两组少得多。事实上,这个群体中的许多人都被贴上了“无优惠”客户的标签。他们偶尔会使用星巴克的应用程序,但绝对不是星巴克的核心客户群。不出所料,这一群体中男性顾客的比例要高得多,这与我们在按性别划分的报价转化率图表中发现的结果一致。
  • 群组 2:最后一个群组是另一个活跃群组,它在三个群组中具有最高的出价完成率。聚类 0 和聚类 2 之间的最大区别在于,尽管 BOGO 和折扣优惠转换率低于聚类 0,但该组具有非常高的信息优惠转换率。这意味着这部分客户更倾向于使用没有最低交易限制的优惠,我们可能希望优先向他们发送他们更有可能使用的难度较低的优惠。因此,要发送的优惠类型的顺序可能是信息->折扣-> BOGO。

最后的想法

当我第一次开始这个项目时,我的目标只是预测每个客户的最佳报价类型。随着项目的进展,我提出了更多的问题和更多的角度来分析用户行为,这导致了更细粒度的个性化报价推荐和客户细分聚类。

正如我所料,整个项目最具挑战性的部分是特性工程步骤。提取和总结正确的交易和报价使用的用户行为属性集在随后的预测和聚类模型中起着关键作用。

尽管在第一个和最后一个分类的人口统计数据中没有观察到太多的差异,但是分类模型成功地根据客户在行为属性上的差异将他们分开。如果我们可以从其他来源获得更多的用户统计信息,我们可以将 KMeans 识别的组映射回来,以更好地描述每个用户群。

我们还可以通过交叉检查来确认聚类结果是否准确,例如,分类模型是否向聚类 2 中的用户推荐了信息提议。如果结果令人满意,则在可以收集足够的数据用于报价个性化之前,拟合的聚类模型可以用作市场细分的第一步。

我们对客户行为研究得越多,我们就能更好地发送个性化的报价,从而产生更高的转化率,客户参与度和用户粘性也就越高。这是大多数企业努力的目标。

星巴克促销优化

原文:https://towardsdatascience.com/starbucks-promotion-optimization-ca56e29fb584?source=collection_archive---------33-----------------------

星巴克促销和用户交易数据的探索性回归分析

Photo by quan le on Unsplash

介绍

作为星巴克奖励系统的长期粉丝(时不时给我免费早餐🥪),我很好奇它在引擎盖下工作。具体来说,可能有无数的活动可能性(通过结合不同的价格、产品、持续时间、内容等),星巴克的数据科学家必须从中找出表现最佳的活动。

此分析的目的是更好地了解用户人口统计和活动之间的关系,以最大限度地增加收入。🔎

目标

分析的目的是确定优惠和人口统计细分之间的关键关系。总共有 10 个报价,如下所示:

Promotional Offers

为了缩小与每个细分市场相关的促销活动的范围,我们对 10 个促销活动与我们确定的细分市场之间的关系进行了启发式回归分析。

具体来说,我们希望:

  1. 确定每个细分市场最能响应的促销活动。
  2. 根据预期收入确定向每个细分市场发送哪些促销活动。

第 0 部分—预处理和勘探

任何数据分析的第一步都是检查数据集的质量,并进行预处理以解决可能混淆分析的问题。

根据数据研究,最大的奇怪之处是用户数量异常高,年龄显示为“118”。巧合的是,这些用户也没有标明收入值。我的猜测是,这些用户的年龄和收入数据缺失。因此,这些只有在考虑“性别”对购买行为的影响时才有帮助。

由于我们的细分将考虑年龄和收入(除了性别之外),我将把这些用户排除在分析之外。在验证观察数据集的大小和分布后,最合适的细分方式似乎是按年龄组和性别。虽然从技术上来说,我们可以进一步细分(例如,按收入、按加入日期),但这可能足以获得对关系的适当理解。

此外,还有几个数据预处理步骤,以确保数据集可用于分析,包括:

  • 转换分类变量→虚拟变量
  • 日期格式
  • 特征提取(从对象数据格式)
  • 特征工程(确定细分市场)

第 1 部分—促销响应

为了确定每个细分市场对 10 个报价的响应度,我们需要观察与已查看报价相关的报价完成数。具体来说,这不包括与用户没有看到的报价相关联的报价完成(即,他们无论如何都要花那么多美元)。

对于促销优惠(即没有“完成”的内容),我通过“查看”优惠的用户进行区分,以便观察促销的影响。

Offer Responses by User Segment

从上面可以看出一些重要的观察结果:

通用

  • 在所有细分市场中,报价 5-8 似乎有最好的回复率。巧合的是,这些报价都是通过社交渠道(以及网络、电子邮件、手机等其他渠道)传递的。通过观察社交渠道回应率的差异来检验这一假设可能是值得的。
  • 优惠 7 的回复率特别高,因为它只是一个促销优惠(即“已浏览”的优惠)。然而,与其他促销活动(#2)相比,回应率存在明显差异,这进一步加强了社交渠道的有效性。
  • 优惠 4 ,难度最高(10 天内最低消费 20 美元)且奖励最高(5 美元折扣)的折扣优惠,在的回复率中遥遥领先。这很有可能是因为它只通过网络&手机进行交付。

特定于细分市场的

  • 女性群体(2、5、8、11)似乎总体上比男性群体有更好的*均回应率,尤其是通过移动社交渠道提供的报价&。
  • 第一部分(千禧一代,男性)的回复率似乎特别低(大约 40%,而大多数其他人是 50%)。
  • “其他”性别部分(3、6、9、12)的回复率分布似乎相当不同,这很可能与它们的样本量非常低有关。

从本质上讲,最高的回复率似乎与通过社会渠道提供的服务有关,特别是针对女性群体。

第 2 部分—哪些促销?

由于促销响应只是整个故事的一部分,我们需要更好地了解每个细分市场的财务影响。为了评估财务指标,需要进行回归分析。

从考虑的候选模型中,最合适的一个似乎是二次多项式,因为它的训练&测试分数相对较高:

使用二次多项式回归,我确定了每个细分市场的最高预期支出:

Expected Spend for each offer, by User Segment

此外,我还仔细研究了每个细分市场的最高报价:

Top offer for each segment

从这些结果中可以得出一些重要的结论:

  • 优惠# 4(10 天内消费 20 美元,享受 5 美元折扣)似乎是大多数细分市场最有效的活动
  • 总的来说,的报价 0、1 和 9 似乎也表现强劲(紧随#4 之后)。
  • 所有细分市场的 10 大解决方案包括“折扣”和优惠(几乎*分)。

of offer_types in top 10 for all segments

  • 一般来说,收入似乎与支出金额有直接的正相关关系(这与直觉有关)。

Expected Spend vs Income (by Offer)

  • 【沉默的一代】似乎有最高的预期收益,紧随其后的是【婴儿潮】和【千禧一代】。

总的来说,这揭示了高潜力的报价(#4),由于其交付渠道和要关注的报价和细分市场(A/B 测试等),这些报价可能表现不佳。).

结论

这一分析揭示了一些关键的见解,将非常有助于缩小未来的分析和整体推广战略。

就目前的优惠组合而言,最佳促销策略似乎是针对高收入女性(尤其是“千禧一代”和“沉默一代”)的优惠 0 & 1,因为她们有更高的真实优惠完成率,同时也有相对较高的预期支出。

然而,在确定一个强有力的推广策略之前,还有一些出色的实验和分析要做。这些是:

  1. 验证完成率和渠道之间的关系。具体来说,如果你通过社交渠道提供报价#4(最高回报,最低完成率),会发生什么?
  2. 对于每个细分市场,发送哪个最佳报价组合
  3. 探索“意外完成”的价值(未查看,但已完成的报价)——它能导致未来消费行为的改变吗?
  4. 执行分类分析(例如 K-Means 聚类)以验证/强化已识别的细分市场。
  5. 有没有办法提高男性的毕业率(特别是他们有很高的预期支出)?
  6. 对具有较大样本使用数据的“其他”性别段(3、6、9、12)进行分析。

你可以在这里找到 GitHub 回购。

StarGAN —图像到图像的翻译

原文:https://towardsdatascience.com/stargan-image-to-image-translation-44d4230fbb48?source=collection_archive---------10-----------------------

星际之门是用来做什么的?

给定来自两个不同领域的训练数据,这些
模型学习将图像从一个领域翻译到
另一个领域。

比如——将一个人的发色(属性)从黑色(属性值)改为金色(属性值)。

我们将域表示为共享相同属性值的一组图像。黑发人是一个领域,金发人是另一个领域。

斯塔根

  1. g 将图像目标域 标签作为输入,并生成假图像。(二)
  2. g 试图从给定原始域标签的伪图像中重建原始图像
  3. 这里,鉴别器不仅告诉我们伪造性,而且将图像分类到其对应的域,从而 G 试图生成与真实图像无法区分并且可被 D 分类为目标域的图像。即最终将学会生成对应于给定目标域的真实图像。(四)

歧视者的目标

这里,鉴别器有两件事要做,

  1. 它应该能够识别一个图像是不是假的。
  2. 在 D 之上的辅助分类器的帮助下,鉴别器还可以预测作为输入给 D 的图像的域。

辅助分类器有什么用?

利用辅助分类器,D 从数据集中学习原始图像及其对应域的映射。当 G 生成以目标域 c(比如金发)为条件的新图像时,D 可以预测生成图像的域,因此 G 将生成新图像,直到 D 将其预测为目标域 c(金发)。

Loss function of Discriminator

生成器的目标

发电机有三个用途—

  1. 调整发生器权重,以使生成的图像逼真。
  2. 调整生成器权重,使得生成的图像可由 d 分类为目标域。
  3. g 尝试从给定原始域标签的伪图像重建原始图像。我们使用单个生成器两次,首先将
    原始图像转换成目标域中的图像,然后从转换后的
    图像重建原始图像。

Loss function of Generator

数据集

CelebA。名人面孔属性(CelebA)数据集
包含 202,599 个名人的面部图像,每个图像都有 40 个二元属性的注释

Radboud 人脸数据库(RaFD)由从 67 名参与者收集的 4824 张图片组成。每个参与者
在三个不同的凝视
方向上做出八个面部表情,这些表情是从三个不同的角度拍摄的。

参考

StarGAN:用于多领域图像到图像翻译的统一生成对抗网络

StarSpace 算法:挖掘和嵌入用户兴趣

原文:https://towardsdatascience.com/starspace-mining-and-embedding-user-interests-28081937f95?source=collection_archive---------11-----------------------

如何使用脸书 Starspace 算法进行用户嵌入

Photo by Max McKinnon on Unsplash

数据科学家总是希望更多地了解他们的客户。如果我们了解我们的客户,我们可以:

  1. 基于用户兴趣推广活动
  2. 预测用户属性
  3. 查找用户相似性并进行聚类

听起来不错?棘手的问题是,所有这些下游任务都需要高度信息化的用户嵌入,以便您可以使用机器学习算法。当然,你可以在没有用户嵌入的情况下进行机器学习,只需简单地将用户与算法相匹配。问题是,通常,关于用户的数据是高度非结构化的,甚至是可变长度的。编码这种杂乱数据的预处理步骤并不简单。

借助 StarSpace,我们可以根据用户行为获得高度信息化的用户嵌入。

背景

StarSpace 是脸书提出的一种算法[1]。

StarSpace 是一个通用的神经模型,用于有效学习实体嵌入,以解决各种各样的问题

所以,关键词是【通用】**【实体嵌入】。换句话说,你可以通过 StarSpace 嵌入任何你想要的东西,包括用户。实际上,HK01 数据团队也利用 StarSpace 做文章嵌入,与其他嵌入算法并行。

[## 使用脸书空间学习文档嵌入

medium.com](https://medium.com/@LouisKitLungLaw/documents-embeddings-using-facebook-s-starspace-67b8d1feba32)

怎么会这么泛?秘密是:StarSpace 学会将实体及其组件表示到同一个向量空间中。使用 StarSpace 的唯一要求是您应该提供实体和组件之间的链接。以链接作为训练数据,StarSpace 可以学习组件之间的相似性,进而学习实体之间的相似性。

直觉

接下来的问题是什么组件可以代表用户。在 HK01 中,用户由阅读的文章表示。

Three levels of entities. All mapped into the same space

上图说明了不同级别实体之间的联系。用户由阅读的文章表示,而文章由令牌表示。特别地,用户由他/她的阅读历史中的令牌包来表示。

背后的直觉是,每一层的信息都可以传播到上下游各层。通过链接,StarSpace 可以发现文章之间的相似性,因为它们共享令牌。同样,用户之间的相似性因此可以被学习。

结果

只有 50 维的 StarSpace 学习的用户嵌入,在下游任务中可以提供与原始用户嵌入不相上下的性能,原始用户嵌入有 20000 多维。

理论

到目前为止,我们仍然不知道 StarSpace 是如何工作的。StarSpace 的创新之处在于提出了一个新的损失函数:

The loss function of StarSpace

别担心。背后的想法是,StarSpace 被训练为正面样本分配比负面样本高一个幅度的相似性。损失函数称为边际排序损失,类似于铰链损失。相似性函数可以是余弦相似性。

比如在用户嵌入中,每个实体对 (a,b) 都是由(用户,令牌)构成的。正实体对是实际的连锁,而负实体对是通过负采样产生的。StarSpace 被训练成将用户映射到实际记号而不是负采样记号附*的位置。

参考

[1]:吴,于,等,“星际空间:嵌入所有的东西!."第三十二届 AAAI 人工智能大会。2018.

开始版本控制您的机器学习数据集

原文:https://towardsdatascience.com/start-version-controlling-your-machine-learning-datasets-2b872e109856?source=collection_archive---------18-----------------------

使用开源工具使您的机器学习和数据科学项目具有可重复性。

在我过去一年参与的许多机器学习项目中,我的数据集在整个实验过程中改变了几次。例如,当我处理生物医学数据时,几乎每周都会收到新数据。在我用图像分割做的一些实验中,我一直在使用一种叫做主动学习的技术来逐渐增加我的训练数据集。

所有这些都让我有些不安,虽然我的代码是用 git 进行版本控制的,但我的数据集和训练模型通常不是(由于文件大小的限制,以及 git 对二进制文件不理想的事实)。每当我用新的数据重新训练我的模型时,我要么覆盖我现有的模型,要么在我的项目目录中填入许多稍有不同的版本的训练模型,文件名也稍有不同。像这样:

Model_v1.h5
Model_v2morepics.h5
Model_v3evenmorepics.h5

好吧,我会尽量选择更好的文件名。但是,这种方法是不系统的,并且很难精确复制。感觉不科学。我最*了解了 DVC,这是一个开源版本控制系统,与 git 配合使用,可以跟踪大型数据集和模型文件的变化(剧透:我将于 2020 年 1 月加入 DVC!).我试用了它,非常喜欢它给动态 ML 问题增加结构的方式——有点像采用 git 如何鼓励我采取更好的编码实践。我想分享一些关于如何为 ML 实验版本化数据集的信息。

问题是

先说一个玩具问题。我有一个数据目录,里面全是来自斯坦福狗数据集的图片,这是一个很棒的狗图片库,按品种分类。假设我想建立一个分类器来区分两种毛茸茸的狗,阿富汗猎犬和马耳他狗。

Left: Sample image of the Afghan Hound. Right: The Maltese. From the Stanford Dogs dataset.

首先,我有每个品种的 100 张图片(构建这个数据集的脚本在 GitHub 上,所以如果你愿意的话,可以克隆这个 repo)。但我知道数据集在未来可能会改变:可能会添加更多的图像,我可能会决定排除一些图像,或者我(或我团队中的某个人)可能会意外删除一个文件。这些变化中的每一个都会对适合我们数据的模型产生影响。

对于这样一个非常小的数据集,我可以想象使用 git。对于更大的数据集,我可以转移到 git-lfs(尽管这也有空间限制——而且,根据我在大学医院处理生物医学研究数据的经验,如果不经过审计程序,一些机构是不会允许的)。但是,想象一个大得多的数据集——更不用说我将要生成的大型训练模型文件了——您可以开始看到这种方法变得棘手的地方。

设置版本控制

这就是 DVC 的切入点。DVC 是一个围绕 git 构建的版本控制系统,所以语法非常相似——一旦您在本地机器上创建了一个存储项目代码(比如 ML 模型)的文件夹,您就可以运行

$ git init
$ dvc init

请注意,如果您按照我们提供的代码进行操作,您会将整个斯坦福狗数据集下载到您的项目目录中——我们不关心跟踪这个,所以运行

$ echo '/Images' >> .gitignore

接下来,你需要选择一个位置,在那里 DVC 将处理你的数据和模型的各种版本的存储,称为数据远程。远程可以是您选择的存储位置——我将使用 S3 存储桶,但是您也可以使用 GCP 存储桶、Azure blob 存储、您自己的内部文件服务器,甚至是本地目录。使用外部存储的一个好处是,不同机器上的新用户(比如说,合作者)可以很容易地进入并开始复制您的 ML 项目。特别是,云存储的伸缩性很好,所以您可以避免随着数据集的增长而耗尽磁盘空间的沮丧(这种情况发生在我身上,真的是度过一个下午的最糟糕的方式)。一句话:只要有可能,我建议您为数据科学项目使用云存储。

以下是我们如何添加 S3 桶作为这个项目的遥控器:

$ dvc remote add -d s3remote s3://bucket-of-dogs
$ git commit .dvc/config -m "Configure my S3 remote"

接下来,我们开始跟踪数据集。在我们的代码示例中,数据集当前位于项目目录中名为“data”的子目录中。

$ dvc add data

这将创建一个. dvc 文件,这是一个轻量级的文本文件,用于索引数据集的当前状态(如果您有兴趣,可以在文本编辑器中打开它!).这个。像任何其他文本文件一样,使用 git 跟踪 dvc。

最后,我们将 git commit 和 DVC push——运行这些命令后,git 现在通过。dvc 文件,数据文件的内容现在在 S3 桶中。

$ git add .
$ git commit -m "Add initial dataset"
$ dvc push

有关为您的特定工作流程配置 dvc 的更多详细信息,请查看入门文档。

训练模型

现在,让我们对数据集运行一个分类器。这一个使用预训练的 VGG-16 权重来为每个图像创建特征,然后训练一个完全连接的层来将这些特征映射到一个类别标签(你可以在这里看到代码)。分类器的细节——语言、架构和框架的选择——对于这个例子并不重要。

$ PYTHONHASHSEED=0 python breed_classifier.py
Validation Accuracy: 0.950

(为什么我们指定 PYTHONHASHSEED=0?您不必这样做,但是如果您继续这样做,它将确保您得到与我完全相同的结果——我们保持随机数种子的一致性)。

在模型训练之后,您将在项目目录中拥有一个模型文件。保存的模型也可以用 DVC 跟踪。让我们 dvc 添加,然后 git commit 来做。

$ dvc add model.h5
$ git add .
$ git commit -m “Trained model”
$ dvc push

更改数据集

假设一个动物收容所突然给我们发送了更多的狗的照片,我们想要重新训练我们的模型来利用这些新数据。现在,我们将每个品种的另外 100 张照片添加到数据目录中(如果您在自己的机器上跟随,那么项目 repo 中的脚本 grow_dog_dataset.sh 将会做到这一点!).我们可以通过运行以下命令来确认这一点

$ ls data | wc -l
400

这些图像还没有被 DVC 跟踪,所以让我们添加它们:

$ dvc add data
$ git add .
$ git commit -m "Added new dogs"
$ dvc push

让我们再次训练这个模型。太好了,看起来我们有进步了。

$ python breed_classifier.py
Validation Accuracy: 0.988

同样,我们可以 dvc add 和 git commit 来跟踪. h5 模型文件。由于最*的提交既跟踪了已训练模型的最新版本,也跟踪了已训练模型的数据集,因此它们在项目的历史中被有效地绑定在一起。

发现了一个错误

所以我准备生产这个神奇的马耳他/阿富汗猎犬分类器,对我遇到的所有狗进行分类,直到我意识到我犯了一个错误。也许收容所不小心给我发了一堆彭布罗克柯基的照片,被误标为麦芽酒,我在训练前没有注意到。但是,因为我们已经对数据集进行了版本控制,所以这种错误很容易解决(并且不会导致不可跟踪的、不可逆的文件删除)。

Not supposed to be here.

有两种方法可以解决这个问题…

选项 1。删除 CORBA。

如果我们确切地知道哪些文件是错误的,我们可以只删除那些图像。然后,用更新项目的状态

$ dvc add data
$ git add .
$ git commit -m "Remove pesky corgis"

我们自然希望重新训练模型,使其与数据集保持同步。

选项 2。将项目恢复到以前的状态。

如果我们不知道哪些图像是有问题的,我们可能想放弃我们最*对项目的所有更改,并恢复到最后一波狗图片到来之前的版本。为此,我们可以使用 git checkout 和 dvc checkout:

$ git log --oneline
17746b7 Added new dogs
45e678d Trained model
df11d07 Add initial dataset$ git checkout 45e678d
$ dvc checkout

现在查看数据目录:同样只有 200 个文件(每个品种 100 个)。

$ ls data | wc -l
200

我们项目目录中的训练模型也反映了数据集的这个版本。

底线

ML 项目很少直线前进——不仅仅是因为找到正确的模型不是线性的,还因为数据集本身是变化的。当然有一些自制的方法来跟踪和管理这些变化,但 DVC 可以在几个方面提供帮助:

  • 如果你已经在使用 git,DVC 是一个简单的插件。
  • 作为一名研究人员,跟踪模型文件和数据集的能力对我来说是很直观的。我不希望经过训练的模型和训练数据集在没有某种联系的情况下发生变化。
  • 能够配置自己的数据存储对我参与的许多数据科学项目来说是一件大事(特别是生物医学数据,因为还没有人愿意付钱让我分析狗)。

除了所有这些实际的原因,我的主要原因是版本控制仅仅是好的实践。我努力做到系统化和谨慎,但有时在实验过程中,我会忘记我的数据集是如何变化的。像 git 一样,DVC 帮助我坚持可复制、可共享科学的最佳实践。

开始:成为伟大的数据科学家(学生/职业改变者版本)

原文:https://towardsdatascience.com/starting-out-becoming-a-great-data-scientist-student-career-changers-version-8a2915f126b9?source=collection_archive---------12-----------------------

好吧,我在数据事物的免费图片之间被撕裂,但是最*被一些多样性和包容性研讨会洗脑。所以,我选择了这种多元化的拼贴——不管怎样。像右上方的那个女孩一样,用你最喜欢的被子裹住自己,我们来谈谈如何让你走上成为一名伟大的数据科学家的道路。这篇文章的职业建议更适合学生和转行者。

这次演讲的目的

大约每隔几周,我就会收到类似这样的问题:

1。“什么认证对金融数据科学家有好处?”

2。“你会给试图获得定量分析师职位或金融类人工智能职位实习机会的学生什么建议?”

3。"财务分析招聘经理寻找什么?"

你明白了。就像他们在学校里总是说什么来引诱你问问题一样,别人可能也有同样的问题,那就问吧。让我们检查一下这些问题。

“什么认证对金融数据科学家有好处?”

对于第一个问题,当我第一次规划我的职业生涯时,我发现这个问题很难。终审法院非常关注金融。FRM 对于风险管理是好的,但是仍然没有足够的编码。CQF 是相当新的,所以我没有进入它。现在看看这些项目,我会选择 CQF,因为它比终审法院或 FRM 更复杂。这个答案的潜在主题是向第二个问题的完美过渡。

做最难的事

“你会给试图获得金融类 quant 职位或 AI 实习职位的学生什么建议?”

我支持上面的副标题。让我们从招聘经理的角度来看。他们收到了大量的申请。从这个巨大的池中,他们必须创建简单的规则来过滤应用程序。例如,我听说一些经理只是从应用数学或计算机科学背景中挑选一些人,而抛弃所有其他专业。基本上,大多数招聘经理都在寻找聪明、精力充沛、能够完成工作的人。从前面的例子来看,招聘经理只是简单地使用她认为更严格的专业作为预测她认为什么是好候选人的特征。如果你打算实习,那么让自己看起来能克服困难和复杂的问题。

找工作糟透了

“财务分析招聘经理需要什么?”

在获得数据科学职位的过程中,预计会有一段艰难的旅程。这样,在你继续下去的时候,任何其他结果都不会对你的心态产生太大影响。相信我,我有多方面的经验:招聘方面,申请方面,以及帮助人们进入内部。在招聘方面,我一直认为高层的人会少些偏见,并有一些更好的秘方。我错了。招聘经理仍然是人,有时这些人会进行权力旅行。例如,我见过招聘经理偏爱男性多于女性,偏爱某个少数群体(他自己的),根据他们的大学立即拒绝申请人,等等。

在申请人方面,我有许多压抑的记忆,我把我的申请送到了网上申请的黑洞中,再也看不到了。随着我获得了更多的经验,我开始根据目标职位的关键词调整我的简历,并根据该角色调整成就。例如,如果他们想要做 ARIMA 的人(这是时间序列分析的一部分),那么我会在我的简历中列出一个时间序列项目,并在我的面试中提到它。

在帮助人们进入角色方面,我的最佳建议适用于所有工作——网络。我见过的从求职者到雇员的最简单的转换方式是认识招聘经理或向招聘经理推荐。仔细想想,还是有道理的。招聘经理通常有一大堆申请,像大多数人一样,他只是想要一个简单的出路。有什么更好的方法来解决这个问题,而不是找一个你已经知道可以做这项工作并且已经是适合团队的良好文化的人呢?

成为伟大的数据科学家

好吧,对大多数人来说,伟大是一个主观的东西。但是,让我们把范围缩小到获得更多报酬或晋升。当我们谈到制定基本规则时。我只是想说,所有的企业都希望利润最大化(不包括非营利组织)。记住这一点,你可以通过带来更多的钱来为你的公司增加更多的价值。这可以表现为实际产生收入,或者以更高的效率降低成本。

早在我刚开始创业的时候,一位投资组合经理给了我一条建议,帮助我更快地晋升。

“接硬项目。”

当一家公司有没人想碰的问题时,你就有一个巨大的成功机会,大大增加了你加薪或升职的机会。当然,风险是看起来像个傻瓜和失败,但我们在这里谈论的是变得伟大。通往成功的旅程偶尔会迫使你跨过失败之桥来取得进步。所以,解决困难的问题,高级管理层会倾听你的意见。

结论

好了,我们今天讨论了一些事情。但是潜在的主题是成为一个强有力的问题解决者。当试图进入数据科学职位时,展示招聘经理希望看到的你已经完成的困难任务。可能是挑个好专业,去个好点的学校,有个真的很好的 GitHub 等等。申请工作时,要有一个困难的心理准备。这样,你不会让任何事情困扰,更有利的结果将只是娱乐性的玩笑。一旦开始工作,记得接受困难的项目,并超越对它们的期望。在公司里,有很多人只想混日子。通过成为公司中应用数据科学来增加收入和降低成本的人,你一定会成为一名伟大的数据科学家。

请将此分享给你所有的媒体朋友,点击下面的按钮,让它传播得更广。也请在下面的评论中添加你经常使用的任何其他技巧或诀窍!

免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。

数据科学入门:从未编码

原文:https://towardsdatascience.com/starting-out-data-science-never-coded-b79ed985e661?source=collection_archive---------29-----------------------

好吧,这篇文章是写给任何刚开始写代码并且需要一点指导的人的。以下是我从没有编程经验到成为一名成熟的副总裁,一家财富 30 强公司的数据科学家所做的事情。

寻找动力

当你开始一个新的大项目、爱好或其他什么的时候,你需要从你的为什么开始。如果你不知道你为什么要做某件事,你在那个选定项目中的工作不会持久。想想吧。你有没有做过没有深层原因的长期工作?大概不会。

美妙的是你的“为什么”可以成为激励你的任何理由。就我而言,我对我的目标或大项目进行逆向工程。基本上,我会选择一些我想做的事情,这些事情需要花一段时间,然后从最终目标开始,回溯到我认为我需要做什么来完成它。在这个阶段,你不必把一切都做好。你只需要把它记下来,每天复习。关于如何逆向工程目标的更多内容,我从《6 个月到 6 位数》一书中获得了灵感。既然你正在读这篇关于编码的文章,你可能应该把它设定为获得 X(数据科学家,web 开发人员…)工作,赚 Y(8 万美元,15 万美元…)钱,等等。

参加斗争

我不想撒谎。编码很难。在你学习了任何语言的编码基础之后,现实世界中的编程是艺术和科学的结合。你有编码的元素,但它们是如此的无定型。我的意思是,有许多方法可以自动化一个预测性的分析模型,这取决于你这个开发人员如何实现它。还有编码本身的过程。你的代码永远不会 100%完美。你必须调试,客户要求改变,你发现更好的东西,等等。编码中的挫折和挣扎总是存在的,但是完成任务是非常值得的。为了度过通往成功之路的挣扎,我强烈推荐雷伊·达里奥【2】的《原则》一书。戴洛解释说,学习一项新技能或获得专业知识就像一个反馈环。你尝试一些事情,得到环境的回应,你调整你的行动,然后你再试一次。冲洗,并重复卓越。

养成习惯

我们都听说过,养成一个习惯大约需要 21 天,误差在几天之内。这是你成功编码的最关键的一点。在《引爆点》中,Gladwell 给出了大规模事件在达到临界质量水*之前不会发生的例子。对于你的编码来说,它会持续到 21 天。除了每天审视你的目标来推动你实现之外,也要改变你的编码环境。例如,我喜欢奇多,但我知道它们对我来说不太健康。所以,我家里根本就没有。虽然听起来很傻,但即使在我家对面有一家杂货店的时候,这种方法仍然有效。编码也是一样。把你的笔记本电脑放在一个好地方,放上一杯好咖啡和你最好的毛绒拖鞋。

复合技能

这是最后一点,以防上面所有的东西都没有帮到你。从《天才密码【4】这本书来看,顶尖高手都是后天培养出来的,不是天生的。让我给你省下 3 个小时的阅读时间,给你那本书的要点。每天至少花 20 分钟为编写代码。出于某种原因,当我们不断努力时,我们的大脑就会变得非常擅长某事。书中一个类似的例子是,他们让学生在一年中每天练习一种乐器 20 分钟,而另一组学生在半年中每天练习同样的时间,总共是 20 分钟。坚持练习一年的学生比练习六个月的学生表现更好。我是说,想想看。即使学习了同样多的时间,日复一日的练习也胜过集中练习。

结论

为了长期发展高水*的编码技能,首先要从目标开始。为什么要编码?每天提醒自己为什么。把它作为一个目标写下来,并列出达到目标所需的所有步骤。基本上,你必须每天提醒自己为什么想要它。目标召唤你所需的能量,帮助你跨越失败的障碍。接下来,半信半疑地面对编码的挣扎。这种痛苦是你成长为更好的编码者过程的一部分。其实有点像健身。一旦你把这些都记下,开始做至少 20 天。方法不重要,但要坚持做下去。我的建议是让你每天编码变得非常容易。让它成为你想去编码的好地方。最后,时间和你做的时间很重要。每天至少练习 20 分钟编码。这部分很重要。死记硬背一项技能是不起作用的。你的头脑需要时间和持续的练习来适应你想要成为的人,或者,在这种情况下,你想要拥有的技能。

所有这些,帮助我从不知道如何从代码中打印文本,到建立自动化预测分析模型。如果我从一无所知到精通代码,你也可以。只需承诺并步入更好的你——每次 20 分钟。

如果你想和我联系,请给我发一条信息到 LinkedIn。

免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。

[1] P. Voogd, 6 个月到 6 位数 (2014),游戏改变者公司

[2] R .达利奥,原则:生活与工作 (2017),西蒙&舒斯特

[3] M .格拉德威尔,《引爆点:小事情如何能产生大影响》 (2006),利特尔·布朗公司

[4] D. Coyle,天才法则:伟大不是天生的。它长大了。以下是方法。 (2009),矮脚鸡

从 Python 中的 SQL 开始

原文:https://towardsdatascience.com/starting-with-sql-in-python-948e529586f2?source=collection_archive---------1-----------------------

这是用 Python 在 Jupyter 笔记本中启动和运行 SQL 的介绍。

Photo by Christopher Gower on Unsplash

使用 Python 运行 SQL 查询的一个快速简单的方法是使用 SQLite 。SQLite 是一个利用 SQL 数据库引擎的库。它的执行速度相对较快,并已被证明是高度可靠的。 SQLite 是测试环境中最常用的数据库引擎。

以下是简单的入门步骤。

步骤 1 —导入 SQLite 和 Pandas

首先,我们需要将 SQLite 导入到 Jupyter 笔记本中。

import **sqlite3** import pandas as pd

步骤 2 —连接数据库

使用 connect() 函数允许您在自己的环境中创建一个数据库。这有助于用户命名他们的数据库,以便稍后在 Python 中调用。connect()函数在您使用数据库时保持连接。

需要注意的重要一点是,当您连接到数据库时,其他用户将无法同时访问它。这就是为什么当你完成时,关闭()连接是必要的(我将在最后讨论关闭连接)。

对于这个例子,我将引用一个名为“factbook.db”的中情局数据库。

sql_connect = sqlite3.**connect**('factbook.db')

步骤 3 —光标对象

cursor() 函数用于帮助执行我们的 SQL 查询。

cursor = sql_connect.**cursor**()

使用 cursor()返回与我们要查询的数据库相对应的游标实例是很重要的。

步骤 4 —编写查询

使用 SQLite 和 Python,SQL 查询将需要通过一个字符串传递。虽然这不是必需的,但我认为将查询保存到变量中是一种好的做法,这样以后就可以引用它,而不必重写整个查询。

我们的 factbook.db 文件中的表叫做事实

  1. 将 SQL 查询保存为字符串
query = "SELECT * FROM factbook;"

2.使用前面的游标变量执行查询。这会将结果转换为元组,并将其存储为局部变量。为了得到所有的结果,我们使用 fetchall()。

results = cursor.execute(query).**fetchall**()

步骤 5-运行查询

为了运行我们之前保存的关于 pandas 的查询,我们执行以下操作。

pd.**read_sql_query**(query,sql_connect)

输出:

A snippet of the output from our query

步骤 6 —关闭您的连接

请记住,完成后关闭连接是非常重要的。关闭连接将授予其他人访问数据库的权限。

sql_connect.**close**()

这里有一个很好的 SQLite 思维过程的模板。

1\. connection open2\. transaction started3\. statement executes4\. transaction done
5\. connection closed

第 7 步——奖励(为什么使用 Python 和 SQL?)

如果你像我一样,那么你可能想知道为什么在 Python 中运行 SQL 查询,而在 PostgreSQL 或 MySQL 中运行它们似乎更容易。

Python 有大量的库(例如,Pandas、StatsModel 和 SciPy)用于可测量的科学分析。这些库同样致力于不断完善抽象,因此你不必手工计算所有的基本数学。此外,您可以迅速获得结果,因此您可以迭代地利用 Python 来调查您的信息。( Janbansk 训练)

下面是用 Python 和 SQL 查询绘制直方图的片段。

import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inlinefig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111)**query = '''
SELECT population, population_growth, birth_rate, death_rate
FROM factbook
WHERE population != (SELECT MAX(population) FROM facts)
AND population != (SELECT MIN(population) FROM facts);
'''**pd.read_sql_query(query, sql_connect).hist(ax=ax)

资源:

  • Github 资源库

2020 年你应该读的创业书籍

原文:https://towardsdatascience.com/startup-books-you-should-read-in-2020-ba8684000128?source=collection_archive---------21-----------------------

如何成长一家初创企业?每日阅读!

读书是成功的首席执行官们经常提到的活动之一。我们的经济变成了一个由一群热心人士和专家管理的中小型公司进行创新的地方。如果你是他们中的一员,或者如果你想成为他们中的一员,阅读是为冒险做准备的最好方式,那就是建立你自己的公司。

The best startup books to read in 2020

以下是 2020 年值得一读的 8 本创业书籍:

零比一是贝宝联合创始人、亿万富翁彼得·泰尔的经典之作。这本书简明扼要地探讨了与众不同意味着什么,以及如何建立一个有潜力成为独角兽的公司。

精益创业公司将精益方法引入商业世界,并展示如何使用它从零开始建立一个伟大的公司。这篇文章发表后,精益方法获得了成千上万的追随者。我们名单上的另一个经典。

《10%的企业家:实现你的创业梦想而不放弃你的日常工作》是对企业家精神的一种不同看法,也是一种非常需要的看法。作者提出了在你的全职工作之外建立一个企业的论点和用例,而不要放弃它(至少在开始的时候)。这很好地补充了启动建设的精益方法。

困难的事情的困难之处:在没有简单答案的情况下创业作者是安德森·霍洛维茨公司的传奇创始人,该公司是硅谷最好的风险投资公司之一。作者经历了一个人在成长过程中不得不面对的困境,并用自己生活中的例子来说明。

衡量什么是重要的:谷歌、博诺和盖茨基金会如何用 OKRs 震撼世界是一位亿万富翁风险投资家和企业家写的书,他推广了客观关键结果的方法论。这是理论与来自世界上最伟大的公司的非常实际的使用案例的奇妙结合。

Rework 是一本关于通过质疑现状,以不同的方式做事并使之有效的书。作者通过与一个偏远的团队合作,多次从零开始重建一切,并违背流行的信念,建立了一个成功的初创企业。

原则:生活与工作由一位亿万富翁对冲基金经理撰写,展示了一种伟大的公司文化如何让你取得惊人的成就。作者经常强调,如果不首先建立适当的文化,他就不会成功。

从为什么开始:伟大的领导者如何激励每个人采取行动是一本关于如何成为领导者的很棒的辅导书。它分析了“魅力”和其他企业家的属性,并用很好的生活例子来说明它们。

这些书是开启你创业之旅的绝佳方式。他们每个人都表现出不同的角度,因此他们在大多数时候是互补的。

如果你更倾向于技术,看看你应该在 2020 年阅读的人工智能书籍清单。

[## 加入我的技术简讯

让我们保持联系,了解更多关于技术和人工智能的新闻。](https://creative-producer-9423.ck.page/c3b56f080d)

2019 年人工智能状况报告已经出炉

原文:https://towardsdatascience.com/state-of-ai-report-for-2019-is-out-b5178dc8f320?source=collection_archive---------32-----------------------

《人工智能状况报告》捕捉了过去 12 个月人工智能的指数级进展及其最有趣的影响和发展。

这是什么?

该报告概述了人工智能的进展,重点是过去 12 个月的发展。这份报告汇集了人工智能领域发生的最有趣的事情,其目的是引发一场关于人工智能现状及其对未来影响的知情对话。这一版本建立在 2018 年人工智能报告的创始状态基础上,可以在这里找到。

“我们相信,人们越来越需要关于人工智能在几个方面(研究、工业、人才、政治和中国)的状态的可访问、详细和准确的信息。我们报告的目的是推动关于人工智能进展及其对未来影响的知情对话。” —贝奈希在采访中对【ZDNET】

谁编写这份报告?

Source

该报告借鉴了一些知名人士的专业知识,如谷歌人工智能研究员兼 Keras 深度学习框架负责人 Franç ois Chollet,风投和人工智能思想领袖李开复,脸书人工智能研究员 Sebastian Riedel 等。

报告的主要内容是什么?

  1. 研究:技术突破及其能力。
  2. 人才:在该领域工作的人才的供给、需求和集中度。
  3. 行业:人工智能驱动创新的今天和明天的大型*台、融资和应用领域。
  4. 中国:有两个截然不同的互联网,AI 在中国有自己的类别。
  5. 政治:AI 的舆论,经济含义和 AI 的新兴地缘政治。

他们的预测有多准?

从问责和诚实的角度来看,该报告从他们在 2018 年报告中预测的实现和没有实现的内容开始。

True vs False

报告在哪里?

整份报告嵌在下面,是一个明确的必读。快乐阅读!

State of AI Report

数据科学和机器学习的现状

原文:https://towardsdatascience.com/state-of-data-science-machine-learning-e8bdd4f21b6b?source=collection_archive---------12-----------------------

“数据科学回答独立于数据科学而存在的问题”——Hugo bow ne-Anderson。

简介

D ata 科学、机器学习、深度学习、人工智能都是新兴的学科,并且经常与小说纠缠在一起。

当我第一次开始从传统软件开发过渡到数据科学领域时,我面临着许多挑战,我有很多问题:我应该回到学校吗?MOOC 好还是新兵训练营好?应该学习哪些新的编程语言?应该熟悉哪些框架和工具?我如何证明我的专业知识?如此等等。

作为一个新兴领域,很少有实证证据来回答这些常见的问题。在我研究弥合知识差距的过程中,我偶然发现了 Kaggle 数据科学家&机器学习调查。

Kaggle 在 2017 年发起了一项全行业调查,该调查真实全面地展示了数据科学和机器学习的现状。2018 年,该研究在 10 月份进行了一周的直播,并收集了 23,859 名个人的回复。

这个博客的目标受众是学生、软件开发人员、产品经理、招聘人员以及任何对数据科学的现状感兴趣的人&机器学习。

调查对象的人口统计数据

在分析调查反馈之前,让我们先看看调查参与者是谁。

为了推断一般人群的调查反馈,理想的调查对象应代表(但不限于):

  1. 多个地理位置
  2. 所有性别和成年年龄组
  3. 多样的学术&专业背景

来自 147 个国家和地区的个人参与了调查,大约三分之一的调查者来自美国和印度。

Demographic Location of Survey Respondents

所有年龄段的成年人都有代表。几乎一半的受访者年龄在 30 岁以下,三分之二的受访者认为自己是男性。

Age & Gender Distribution

这项调查收集了来自不同行业、不同职位的个人的反馈。

Job title count by business domain

大多数受访者目前在软件和学术领域工作。

Business Domain of the respondents

年度薪酬取决于被调查者工作的业务领域。与其他领域相比,软件领域的回报最高。

Annual Compensation in USD by Business domain

职位名称因公司而异。大多数调查受访者声称自己是学生,其次是数据科学家、软件工程师和数据分析师。

Current Job title

就像商业领域一样,职称在年度薪酬中也起着至关重要的作用。

Annual Compensation in USD by Job title

当被问及受访者是否认为自己是数据科学家时,超过一半的受访者回答是。

Do you consider yourself a Data Scientist?

Kaggle 是许多有抱负的数据科学家的乐园。尽管受访者并不认为自己是数据科学家,但就目前而言,我已经考虑了所有的回答,以获得一个整体的观点。

几乎所有的调查对象都在工作中参与了一些编码活动。

Active coding percentage

说到经验,大多数调查对象的编码经验不到 5 年,机器学习经验不到 3 年。有相当多的人,他们没有事先的编码和机器学习知识,但热衷于学习。

Coding and Machine Learning Experience

鉴于调查的规模和多样性,我们可以自信地将调查趋势推断到一般人群。

成为数据科学家

在这一部分,我们将分析数据科学的知识来源和调查对象的学术背景。

从历史上看,开设数据科学/机器学习专业的大学和学院并不多。正因如此,数据科学家&机器学习工程师的学术背景非常多样。

通常,许多从业者有不止一个知识来源。

Data Science knowledge source

从调查反馈来看,典型的数据科学家通过自学和在线课程获得了超过一半的知识。

为了满足市场需求,许多知名大学和学院已经开始开设数据科学专业。然而,对于许多职场人士来说,由于地理和时间的限制,重返校园并不总是一个选择。然而,由于灵活的注册和访问,在线学习*台已经成为一种可行的替代知识来源。

Online Resources

Coursera 是注册人数最多的在线资源,其次是 Udemy。大多数在线资源都有多样化的课程目录,并且有灵活的注册开始日期。有些甚至提供同行评议、测验和指导来模仿传统教育。

Alternative Online Resources

在线资源的一个主要缺点是,随着技术环境的不断变化,一些课程可能会过时。论坛、博客、YouTube 频道、时事通讯和播客系列都是用来更新的。

新兵训练营是数据科学和机器学习培训的另一个受欢迎的资源。通常情况下,新兵训练营都是面对面的,需要全天参与。

Online & Boot Camp vs Traditional Education

新兵训练营提供传统(面对面培训)和在线教育(灵活的时间框架)的精华。同时,新兵训练营非常昂贵,只有在大城市才有。

大多数受访者投票认为在线课程比传统教育更好或一样好。另一方面,许多参与者没有接触过新兵训练营的训练。

作为一名数据科学家,应该具备领域知识、软件工程技能和统计知识。没有一个在线课程或训练营能够教授所有这三个方面。坚实的学术基础为填补知识空白指明了正确的方向。

Highest level of formal education and Undergraduate Major of survey respondents

与普遍的看法相反,拥有博士学位的受访者人数少于拥有其他最高水*正规教育的人数。大多数受访者的本科专业是计算机科学,其次是工程学。

Independent Projects vs Academic achievements

如图所示,数据科学家的学术背景非常多样化,因此,在雇用数据科学家时,学术成就并不总是合适的衡量标准。或者,分析独立项目可能是评估潜在员工技能的最佳方式。

数据科学家军火库

数据科学和机器学习技术的前景正在不断扩大。人类不可能精通所有可用的框架、*台和方法。

该调查收集了参与者使用和建议的编程语言、框架、工具&*台。忽略边缘情况,这应该给一个有抱负的数据科学家一个好主意,告诉他应该精通什么技术。

**提及的技术是累积性的,因项目而异。

编程语言

绝大多数的回答者都建议将 Python 作为第一个要学习的编程语言。

First language for newbies

以下是我认为 Python 值得推荐的几个原因:

  1. Python 是一种开源的模块化编程语言,学习曲线很短。
  2. Python 是许多流行的数据分析、机器学习和深度学习包的首选编程语言。
  3. Python 拥有庞大的开发者支持基础和第三方库。

Popular programming languages

知道多种编程语言总是一个好主意。有了不止一种编程语言的知识,我们可以模块化地设计应用程序,以利用不同语言和各自支持的框架所提供的功能。

受访者对其他编程语言的建议与调查对象给出的第一语言建议相结合。

例如,在开发信用卡欺诈检测应用程序时,我将使用 Apache Spark (Scala)管道进行数据转换,并使用 Scikit (Python)模型进行机器学习。

虽然 Spark 有 Python (PySpark)支持,但使用 PySpark 时有一个潜在的权衡,如果你想使用自定义用户定义函数(UDF)来实现基于上下文的逻辑,数据需要不断地序列化和反序列化。为了避免这种情况,我选择 Scala Spark 进行数据转换。

**如果上述示例中的技术术语令人困惑,请忽略该示例。

框架和库

学习语言本身并不足以成为一名成功的数据科学家或数据工程师。框架和库的知识是必要的。框架和库提供了可重用和可扩展的代码托盘。

在典型的工作中,数据科学家利用各种框架和库来探索、可视化和训练数据集。

Machine Learning Frameworks

机器学习框架提供了监督、非监督和深度学习算法的抽象实现。不是每个框架都提供所有的算法。

机器学习框架的选择取决于团队使用的语言和基础设施等参数。

Visualization Frameworks

“一张图胜过千言万语”, 用图表和图形(正如我在这篇文章中所做的)传达信息比用文字描述更直接。可视化框架将数据作为输入,并产生易于理解的可视化效果。

可视化库的选择取决于语言、用法和熟悉程度。

工具

从人类诞生之日起,人类就致力于开发新的工具来让生活变得更容易。数据科学家使用技术工具来简化他们的日常工作。

每种语言都有其句法和语义,作为人类,要记住它们是不可能的。开发集成开发环境(ide)是为了避免语法和语义错误并提高生产率。

大多数企业使用 ide 进行开发。ide 有助于提高开发人员的整体生产力:

Popular IDEs

  1. 在开发过程中提供语法和语义验证。
  2. 第三方库的文档。
  3. 与终端、GIT 等外部工具集成。

通常,IDE 的选择取决于所使用的编程语言和开发团队的偏好。

在数据科学项目的初始实验阶段,笔记本内核为探索、分析和概念化数据提供了一个交互式环境。笔记本还提供了一种以多种格式记录和分享发现的简单方法。

Notebook Kernels suggested by respondents

根据调查结果,使用笔记本内核的受访者并不多。这可能是因为大多数公司使用集成开发环境。根据我的经验,如果你开始从事数据科学,熟悉笔记本内核是试验数据和代码的一个很好的方法。

公用事业

编程语言,框架&库提供逻辑处理,我们仍然需要其他工具来存储和计算数据。

RDBMS systems

关系数据模型是关系数据库管理系统背后的基本原理。

每个 RDBMS 都包含表,每个表由行和列组成。表和列结构是预定义的。

RDBMS 在软件应用中广泛用于存储数据。结构化查询语言(SQL)用于访问和操作数据。即使在今天,许多公司仍然高度依赖这个系统。

数据科学家应该熟悉 RDBMS 和 SQL。RDBMS 有许多实现方式,如 Oracle、MySQL、DB2 等。并根据团队使用的应用程序框架和库进行选择。

几乎所有的 RDBMS 都有支持编程语言直接交互的框架和库。

**请注意即使调查中关系数据库下提到 AWS 迪纳摩 DB (如上图所示),迪纳摩 DB 也是一个非 SQL 数据库。

在从事数据科学和机器学习项目时,我们很有可能会在开发终端或调配的服务器资源上遇到有关存储和计算能力的瓶颈场景。

云*台在共享的服务器网络上提供存储和计算能力。理论上不应该缺少存储空间&计算能力。

云计算服务和产品提供了广泛的硬件容量和软件产品,能够在短时间内灵活扩展。

例如,我正在开发一个深度学习网络,我预计只训练这个网络 1 周。要训练一个深度学习网络,我需要 GPU。但是,同时在 GPU 上投资一周的任务没有任何意义。相反,我可以使用云 GPU 一周,并根据我使用它的时间支付费用。

Cloud Platforms

AWS 是受访者使用最多的云*台。

尽管云*台有其固有的优势,但许多受访者都提到他们没有接触过云*台。

大多数云*台通过产品即服务(PaaS)架构提供计算、机器学习和分析产品。这些产品专门为云供应商开发。

Cloud Computing Services

云*台以*台即服务的形式提供虚拟机(VM)和容器,具有硬件和软件调整的灵活性。使用云,我们可以按需添加或删除虚拟机和容器。

根据受访者的说法,亚马逊 EC2 和 AWS Lambda 是最常用的两项服务。

许多云供应商通过 API 提供预训练的机器学习模型。

Cloud Machine Learning Products

使用经过训练的模型,开发人员可以轻松地将 ML 模型集成到应用程序代码中。通过这种方法,具有最少或没有机器学习知识的开发者可以在应用中实现 ML。

数据科学家的一天

到目前为止,本文的重点是数据科学家的人口统计、专业、学术和技术背景。接下来,我们将分析数据科学家的一天是什么样的。

从高层次来看,典型的数据科学项目分为收集、清理、分析和建模数据。

Data Science Project Activity Time Proportion.

收集数据是第一步。数据不仅从内部数据源收集,还使用 API 交互和 Web 报废从外部数据源收集。这一步由数据科学家或数据工程团队执行,具体取决于团队的规模和结构。

清理数据包括选择数据中哪些特征是有用的,以及如何处理丢失的值。项目的成功直接取决于这一步。糟糕的数据清理选择会导致糟糕的数据和错误的见解。

在分析阶段,干净的数据被转换成可视化数据,用于与利益相关者交流见解。

模型选择阶段包括为问题选择正确的机器学习算法,并调整超参数以实现偏差和方差之间的最佳*衡。这个阶段不是所有数据科学项目的一部分。当需要时,这个阶段是耗时的。

数据科学家的日常活动源自高级数据科学项目阶段。

Daily activities of a Data Scientist

从调查反馈来看,理解领域和模式知识花费了大部分时间,其次是模型&超参数选择和实施。

来自数据科学家 Vantage 的机器学习

在调查中,受访者被问及如何评价公*偏差、可重复性和解释模型输出的重要性。

Importance of Fairness Bias, Reproducibility and Explaining the model output

机器学习模型使用输入数据进行预测,如果输入数据本身有偏差或不公*,同样会传播到模型预测中。

一个现实世界的例子是,现在废弃了歧视女性的亚马逊人工智能招聘工具。你可以在 路透社 新闻文章中了解更多相关信息。

Reasons of Bias in training data

寻找无偏见的数据总是一个挑战。好的一面是大多数数据科学家都意识到了这个问题,坏的一面是没有多少数据科学家投入时间来减少偏差。

Percent of data projects involved exploring unfair bias in the dataset and/or algorithm

机器学习库具有简化的模型训练和超参数调整过程;问题是有时很难解释模型的结果。

只有四分之一的受访者有信心能够解释机器学习模型的输出。

ML Black-box

再现性对于成功的 ML 模型至关重要。一旦模型被调优,只要输入是常数,它就必须产生相同的结果,而不管它在哪个机器上被执行。下图中提到的工具和方法用于使您的作品易于访问和复制。

Tools and Methods to reproduce ML

ML 模型的一个优点是一个模型的输出可以作为另一个模型的输入,创建一个模型管道。

值得注意的是,在深度学习的情况下,这是非常有利的。当利用训练好的层开发图像识别算法时,我们可以节省大量的时间和计算能力。

受访者被问及是什么阻碍了他们让自己的作品更容易被重用和复制。

Barriers to accessible ML models.

商业华帝的机器学习

不是所有的项目都实现机器学习。在数据科学项目中实现机器学习是不可行的,原因有很多。

从调查反馈来看,不到 10%的受访者就职于在生产中成功实施机器学习模型超过 2 年的公司。

ML in Use

每个企业都有自己的衡量标准来衡量机器学习的成功实施。对于大多数企业来说,准确性与收入和业务目标一样,是实施 ML 的关键驱动因素。

Metrics of successful ML implementation.

结论

Kaggle 真正掌握了数据科学和机器学习的全面状况。这个博客对任何有兴趣进入数据科学和机器学习领域的人来说都是一个指南针。

人们可以将这篇博客作为进一步分析的起点——将调查结果与 2017 年 Kaggle 调查数据 以及stack overflow调查数据(改天)进行比较。

此分析的源代码托管在GIT上,可视化托管在Tableau Public上。

使用 Google Brain 的 SpecAugment 和 Pytorch 增强最先进的音频数据

原文:https://towardsdatascience.com/state-of-the-art-audio-data-augmentation-with-google-brains-specaugment-and-pytorch-d3d1a3ce291e?source=collection_archive---------15-----------------------

Photo by Steve Harvey on Unsplash

使用 Pytorch 和 TorchAudio 实现 SpecAugment

谷歌大脑最*发布了 SpecAugment:一种用于自动语音识别的新数据增强方法,它在各种语音识别任务上取得了最先进的结果。

不幸的是,谷歌大脑没有发布代码,似乎他们在 TensorFlow 中编写了他们的版本。对于喜欢 Pytorch 的从业者,我已经发布了使用 Pytorch 的伟大伙伴库 torchaudio 和一些从与其他 FastAI 学生的持续合作中借来的功能 fastai-audio 的 SpecAugment 的实现。

SpecAugment 基础

在语音识别中,原始音频通常被转换成基于图像的表示。这些图像是典型的频谱图,它以一种许多模型都觉得更容易学习的格式对声音的属性进行编码。

SpecAugment 没有对原始音频信号进行数据增强,而是借鉴了计算机视觉的思想,对频谱图进行操作。SpecAugment 工程。谷歌大脑报告了奇妙的结果:

SOTA results using SpecAugment

SpecAugment 有三个增强功能。

时间隧道

time warping a spectrogram

简而言之,时间扭曲通过使用插值技术在随机选择的方向上挤压和拉伸数据来及时移动频谱图。

时间扭曲是 SpecAugment 最复杂、计算量最大的增强。深度学习工程师 Jenny Cai 和我一起完成了 Tensorflow 的[sparse_image_warp](https://www.tensorflow.org/versions/r1.9/api_docs/python/tf/contrib/image/sparse_image_warp?hl=en) 功能,直到我们有了 Pytorch 的支持。

如果你对细节感兴趣,你可以查看回购中的SparseImageWarp.ipynb。谷歌大脑的研究表明,时间扭曲是最无效的增强,所以,如果性能是一个问题,你可能会考虑先放弃这个。

频率和时间掩蔽

频率屏蔽和时间屏蔽类似于计算机视觉中常用的剪切数据增强技术。

简而言之,我们用频谱图的*均值,或者,如果你喜欢,零,来屏蔽随机选择的频带或时间步长。

X 轴为时间,Y 轴为频段,时间屏蔽如下所示:

time masking a spectrogram

这是频率掩蔽:

frequency masking a spectrogram

自然,您可以在一个声谱图上应用所有三种增强:

All three augmentations combined on a single spectrogram

希望这些新的 Pytorch 函数将在您的深度学习工作流程中证明有用。感谢阅读!

最先进的多语言词汇化

原文:https://towardsdatascience.com/state-of-the-art-multilingual-lemmatization-f303e8ff1a8?source=collection_archive---------12-----------------------

对适用于数十种语言的最先进的分类器的分析

我发现变元化是一项有趣的 NLP 任务,在这项任务中,我们必须找到处理人类语言的丰富性和任意性的方法。在这篇文章中,我总结了令人印象深刻的多语言 lemmatizers 的最新技术,为该领域的从业者和新手提供了一些有用的提示,并指出它们的局限性。

词干:低成本,低回报

当我们处理文本数据时,有时需要减少词汇:如果您正在搜索“二手车价格”,包含汽车价格汽车价格的文档很可能是相关的。

这个问题的一个常见策略是词干,从单词中去除前缀和后缀,直到我们只剩下它的词干,它承载了大部分的意思。于是,被词干为重播播放出租车继续为出租车。它只是通过字符串编辑来执行,没有任何类型的预处理或机器学习。

词干提取因其简单性已被许多搜索引擎成功使用。然而,这种简单性也是一个限制因素:甚至没有一个关于单词词干是什么的精确定义。重播的梗可能是,但排练的梗肯定不是灵车。认为关心的梗是关心,而不是是有道理的;但是为了实现这一点,我们需要一个更复杂的算法,知道何时插入一个 final -e 。对于其他语言来说,这可能会变得更加混乱。

底线是任何只基于字符串编辑的方法都缺乏语言的一致性。当这是一个问题时,我们转向术语化

词汇化

词条化是确定给定单词的词条(即词典形式)是什么的过程。拿前面的例子来说,的引理是,而回放的引理是回放本身。这是一个定义明确的概念,但与词干提取不同,它需要对文本输入进行更精细的分析。

对于英语这种几乎没有词形变化的语言来说,这相当简单。但是对于大多数语言来说,词汇化既重要又困难。请看这个捷克语例句:

由 v . kabin ce stujím tr valo překročit řeku 波托马克 asi čtyři minuty 编写。

将每个单词替换为它的引理,得到如下结果:

studieproveditelnostodhadovatebútv卡比娜***cestující*****

(如果你想知道,它的意思是“可行性研究估计,乘客乘坐*底船穿越波托马克河大约需要 4 分钟。”)

在我们的捷克语例子中,15 个单词中有 8 个与词条不同!那几乎是句子中所有的实词。NLP 中的大多数研究使用英语数据,但是正如您所看到的,这是一个糟糕的语言选择,不能反映其真正的挑战。

然而,随着 CoNLL 2017 和 2018 共享任务的出现,我们已经为超过 50 种语言发布了大量带有词条注释的数据。参与者被要求,除了其他事情之外,提出适用于这种广泛语言的 lemmatizer 模型。这些数据为评估 lemmatizers 提供了一个很好的基准。

困难

单词变形有很多规律,这可能会让你想到开发一套规则来恢复单词的引理。但是,由于一些因素,这可能会非常困难:

  • 不规则表格。你必须一个一个地治疗他们。
  • 看起来有屈折变化,但实际上没有的单词。例如 bring 不是不可认动词 to bre 的屈折形式。
  • 不同引理共有的屈折形式。如德语中,gehrt可以是hren(听到)的分词,也可以是gehren(属于)的分词,只有语境才能消除歧义。**
  • 变形规则的数量可能太多,或者您可能对正在使用的语言没有足够的了解。

如您所见,设计手写的词汇化规则甚至对英语来说也很麻烦。所以,像往常一样,我们求助于机器学习。更具体地说,是指一直存在的神经网络。

神经旅鼠是如何工作的?

使用神经网络对单词进行词汇化的方法不止一种,但让我们坚持使用效果最好的方法,这也是最简单的方法。它使用序列到序列(seq2seq)神经网络,逐字符读取单词,然后逐字符输出它们的词条。这是 Turku NLP 小组使用的模型,该小组在 2018 年的 CoNLL 中在词汇化方面取得了最好的结果。

我将不详细介绍 seq2seq 是如何工作的。我在这里关注的是 lemmatizers 的实际用法;有很多解释 seq2seq 的好帖子。其中一个风趣地称其为深度学习的小丑车,因为它可以在看似很少的参数中容纳大量信息。

An overview of the seq2seq lemmatizer architecture

结束符号,也表示为< /s >,用于表示该型号何时完成生产输出。如果没有它,seq2seq 将无限期地生成字符。

模型输入不需要只有单词。我们还可以包含一些元数据,比如 POS 标签,这有助于确定哪个是歧义表单的正确引理。记住每个字符都被编码成一个嵌入向量,这个向量是和其他神经网络参数一起学习的。因此,只要我们能在相同维度的向量中编码我们的标签,我们就可以做得很好。

让我们看一个 POS 标签很重要的例子。在葡萄牙语中, olho 可以是名词,意为,也可以是屈折动词,意为;在后一种情况下,应该将其引理为 olhar**

Additional information about the inputs can help disambiguate

这允许很大的灵活性。该模型可以学习某些单词形式看起来一点也不像它们的词条(例如, was / be ),一些单词形式从不改变(语法单词,如介词和连词),而对于大多数其他单词形式来说,这是改变前缀、中缀或后缀的问题。它还可以学习将某些变形模式与某些 POS 标签相关联。

处理歧义

然而,大多数当前最先进的实现都没有完全解决词条歧义的问题。诸如 StanfordNLP 和 Turku Parser 之类的模型独立地对每个单词进行词汇化,同时考虑其词性和词法标签(如性别、数字、时态、格等)。),而不是句中的其他词。这足以解决上面例子中的情况,其中名词和动词有不同的词条,但当单词、词性标签和形态变化的相同组合仍然可以映射到一个以上的词条时就不行了——就像我前面提到的gehrt**

顺便说一句,不要把引理歧义误认为词义歧义!在引理化中,我们只对书面的引理感兴趣,对意义不感兴趣。因此,你不需要知道球棒是指会飞的动物还是棒球中使用的棍子,只要你知道它的引理是球棒**

但是为什么这些模型是那样的呢?基本上,因为这种情况非常罕见。在本文中,来自图尔库的研究人员认为,对于大多数树银行来说,这种现象只发生在不到 1%的令牌上。即使是在常见的语言中,比如西班牙语(14%)、印地语(22%)和乌尔都语(36%),也有一个词条出现的频率比其他词条高得多。例如,形式 fue 出现了几十次,标记为 AUX(助动词),并以 ser (to be)作为引理,而少数情况下,标记相同,但引理 ir (to go)。

最重要的是,许多这种歧义可能是注释错误。我检查了西班牙语树库,发现许多模糊的单词/标签组合实际上有拼写错误或者没有正确地进行词汇化。不幸的是,我不知道任何乌尔都语重复检查,但我不会惊讶地发现相同的。

这并不意味着不值得去发现两者之间的差异——恰恰相反。问题是,由于例子太少,统计模型很难学习正确的引理。因此,如果我们真的想准备我们的模型来消除所有的 fuegehrt等词的歧义,我们需要准备针对这些词的数据集。

但是,至少在理论上,有一些实现能够消除它们的歧义。 UDPipe Future 和 Combo 解析器就是其中的两个,尽管没有使用 seq2seq,但它们的基本原理与之兼容。下图描述了 UDPipe 架构,但这里重要的是递归神经网络(RNN)的使用,Combo 也采用了它。

The lemmatizer architecture in UDPipe Future. A bidirectional LSTM encodes words in context-sensitive vectors.

双向 LSTM 是 RNN 的常见选择,它读取整个输入句子,并产生上下文相关的向量来编码每个单词。之后,一个词条解释器 MLP 将每个单词分类到一个自动生成的词条解释规则中,该规则包括移除、添加和替换子字符串。

这种表示并不是他们的模型所独有的;这在 NLP 中是相当标准的。Turku 和 Stanford 系统也有自己的 BiLSTMs,但是它们只用于其他的 CoNLL 任务(词性标注、形态标注和语法分析;我打算在接下来的帖子中更多地谈论它们)。

然而,事实证明,上下文感知并不一定转化为更好的词汇化性能。在 CoNLL 评估中,Turku 和 Stanford 系统在拥有合理数据量的树库中获得了最好的结果。即使是在歧义标记更常见的树银行中,结果也不是很清楚:

  • 对于乌尔都语和印地语,图尔库模型的结果最好,紧随其后的是 UDPipe Future 和 Combo
  • 对于西班牙语,UDPipe Future 和 Combo 的效果最好,其次是 Turku

考虑到不明确的标记/标签组合是多么罕见,区分它们的能力在结果中扮演了一个非常边缘的角色。与 UDPipe 中使用的分类器相比,seq2seq 架构更有可能对这种任务更有效。当然,我们仍然可以结合这两个领域的优点,设计一个 seq2seq lemmatizer,它以与额外的标记元数据相同的方式包含一个上下文表示:

The context-sensitive output of an RNN can help disambiguate when even POS and morphological tags are the same

上图第一句话的意思是我没有听到任何消息,第二句话是属于事务所的。在每种情况下,双向 LSTM 将能够捕捉特定的句子上下文,为 seq2seq 引理器提供更多信息,seq 2 seq 引理器反过来将能够(至少在理论上)预测正确的引理。如果没有上下文向量,词条解释器永远不会为同一个单词产生两个不同的词条。

但同样,我们会遇到数据瓶颈。由于不明确的例子非常少,这个改进的模型没有足够的例子来学习和利用它的架构。

神经旅鼠有多好?

现在我们已经看到了这个简洁的 lemmatizer 架构,下一个自然的问题是它实际上有多好。我之前提到的 CoNLL 2018 记分牌给了我们一个很好的概述,但这些数字应该谨慎阅读。

第一个表,All tree bank,包括只有几千个单词的树银行的结果。这不足以学习正确的词汇化规则,并且根据随机初始化,这些树库的性能会有很大的差异。

第二个表格是大树库 only ,过滤掉了那些非常小的树库(事实上,这里的可能会产生误导,因为这些树库中的一些仍然非常小;但是不是极小的树银行听起来不是一个好名字)。在这些剩余的树库上训练的分类器更适合生产使用。

那里的数字看起来相当不错:大多数语言都在 90%以上。您还可以注意到,尽管总体上 Turku 模型是最好的,但对于某些语言来说,其他模型做得更好。但是请记住,每种语言中都有大量完全没有屈折变化的词,如连词和介词,这些值被夸大了。还记得本文开头的捷克例子吗?捷克语有很多词形变化,但是在那个句子中,15 个单词中有 7 个看起来和它们的引理一模一样。

无论如何,我在这里提到的 lemma tizer 的性能对于生产应用来说似乎很好——至少如果您正在处理的文本看起来像 lemma tizer 被训练的树库。因此,如果你需要使用其中的一个,这里有一些警告和实用的提示。

外部知识

基于机器学习的分类器面临的最大挑战是不规则形式。这并不奇怪:它们对人类也有挑战性,有时甚至是用他们的母语,正是因为它们的不可预测性。因此,如果你的模型在训练数据中从未看到禁止禁止的过去式,它可能会认为禁止听起来像是一个很好的引理。

如果你真的想提高你的 lemmatizer 的性能,在你使用的语言中有一个不规则单词的补偿列表是一个好主意。然而,这个列表应该有(词尾变化形式,词性标记,词条)的元组,否则你可能会遇到歧义问题。虽然单词/词性/引理歧义非常罕见,但正如我之前提到的,即使在英语中,也只有单词/引理是一个问题:例如,想想中的名词-动词歧义【锯】思想射击

看不见的变化

现在,一些变形规则可能非常有规律,但是如果它们从未出现在训练数据中,那么没有基于机器学习的系统会学习它们。由于 UD 数据集中的许多语料库来自报纸文本,一个共同的特点是第二人称动词总体上相当罕见。例如,在德语训练树库中,有* 3 万个动词,只有 13 个是第二人称动词。其中一个芬兰的树库,大小差不多,有 462 棵,稍微好一点——但那只是总数的 1.5%!

因此,如果你使用一个在 CoNLL 数据上训练的 lemmatizer,并注意到它在某些特定的变调中表现很差,很可能它没有足够的例子来学习。如果这是一个问题,您将不得不提出更具代表性的数据来重新训练模型,或者实现一些手动规则来覆盖自动输出。

结论

我已经展示了最先进的 lemmatizers 已经开发了非常有趣和高效的体系结构。单词/词性标签/形态标签模糊组合的情况仍然是一个问题,但这种情况非常罕见,在实践中几乎不用担心。然而,处理训练数据中不存在的不规则单词和变化更令人担忧。

尽管如此,如果你说的语言具有丰富的词法,尝试一下我在这里提到的系统,你会惊讶于它们消除屈折变化的能力!

我写的检查西班牙 UD 树库的脚本可以从 Github 获得。您可以使用它来检查其他树库的不明确的词条和可能的注释错误。

彩票的现状

原文:https://towardsdatascience.com/state-of-the-lottery-e705984e4df?source=collection_archive---------27-----------------------

旁注——卢卡斯·加尔克

在这一期中,我们为您带来一篇由 MTank 团队成员撰写的文章,该文章研究了降低神经网络训练成本的技术。通过在训练早期识别子网络的学习强度,即挑选一个获胜的子网络,我们可能会降低现代深度学习研究人员&从业者的计算成本。

除了我们的连载博客, 艾酒厂&杯具意识’之外,我们还会偶尔发布一些&材料作为单机版或短期系列。说到题外话,与我们的其他出版物相比,这些材料的性质有些模糊,我们选择称之为“旁注”。

“旁注”就是这样。我们认为我们的读者可能会喜欢的与 MTank & AI 相关的辅助作品。格式会有所不同,但可能包含所有内容。把它看作是额外项目、会谈&想法的总称。

介绍

神经网络变得越来越大,使用多达数十亿个参数。研究人员开始量化在云计算*台上训练这些大规模模型的努力,以$$$的数量,甚至以吨的碳排放量。通常的理解是,过度参数化的网络容量更大,但也更容易过度拟合训练数据。最*的研究表明,过度参数化实际上起到了正则化的作用,并提高了泛化性能[Arora et al. 2018]。

然而,在训练之后,这种大规模模型的大部分可以被修剪掉,而不会损害模型的准确性。修剪技术可以追溯到【LeCun 1990】关于最佳脑损伤。修剪的动机是减少模型大小,从而减少内存需求、推理时间和能量消耗。一种修剪技术是幅度修剪,它修剪那些具有最低幅度的权重,因此对网络输出的影响最低【韩等,2015】。

彩票假说(LTH)【Frankle&Carbin 2019】之前,普遍的经验是修剪过的架构更难从头开始训练。现在,LTH 声称,某些子网可以被训练得与原始的、未经训练的网络的准确度相当,甚至更好。关键的想法是迭代地训练一个网络,修剪它的参数,直到只剩下一小部分参数。在每次迭代中,幸存的权重被重置为它们的初始化。然后可以在可比较的时间内训练产生的子网,以匹配原始网络将达到的精度。这些子网被称为中奖彩票。

彩票假设。 随机初始化的密集神经网络包含一个子网络,该子网络被初始化为:当被隔离训练时,它可以在最多相同次数的迭代训练后匹配原始网络的测试精度。[Frankle & Carbin 2019]

在 LTH 的论文中,作者发现中奖彩票的大小只有密集彩票的 10-20%。有了更多的剩余参数,获胜的门票甚至可以达到比原始网络更高的测试精度。

为什么这很重要?LTH 建议,如果我们能够在训练过程的早期识别出获胜的门票,就没有必要训练一个完整的模型。如果这是可能的,它可以为我们节省美元和吨的碳排放。

在下文中,我们将首先考虑一个思维实验,以获得关于中奖的直觉。随后,我们将概述如何在 LTH 报纸中识别中奖彩票。最后,我们将经历彩票假说的一些后续工作。

一个最小的例子:两个输入的和

为了直观地了解 LTH,让我们考虑一下计算两个输入之和 y = x0 + x1 的简单任务。我们想用一个两层的线性神经网络来逼*真实值“y ”,这个网络有 n 个隐藏单元,没有偏差。

对于人类来说,两个输入之和的中奖票很容易确定。这样的中奖票将会是

对于一些剩余权重为零的“I”。这将确保在第一层计算两个输入的实际和,并通过第二层传递。

因此,这张成功的入场券甚至可以推广到培训数据领域之外。无论我们选择的隐藏层大小‘n’有多大,我们的中奖票都将 由三个非零权重 组成。因此,我们可以在不损害准确性的情况下,删除除这三个权重之外的所有权重。当我们开始使用仅由这三个非零参数组成的掩码进行训练时,网络最终会学习到正确的权重。

如何识别中奖票

为了证明中奖彩票的存在,弗兰克尔和卡宾采用了以下程序:

  1. 用参数 θ₀ 以及设置为全 1 的掩码 m 初始化模型
  2. 为 j 次迭代训练屏蔽模型
  3. 删除最低幅度权重,并相应地更新掩码 m
  4. θ【m】复位到它们在 θ₀ 中的值,将所有其他参数固定为零。
  5. 从步骤 2 开始重复,除非满足稀疏性或验证准确性的停止标准(迭代修剪)

结果是子网(由掩码 m 给出)及其初始化,这可以执行多一次训练。在他们对图像分类的实验中,作者将中奖彩票的准确性与整个模型和随机彩票进行了比较。随机票证共享相同的结构,但随机重新初始化。主要的结果是获胜的票始终比随机的票导致更高的分数,并且还可以匹配甚至优于完整的模型。

因此,随机彩票与中奖彩票具有相同的结构,但中奖彩票会产生更高的分数。这意味着初始化值对于中奖票的成功非常重要。当我们有更多的参数时,我们得到更多的初始值。我们还获得了更多的可能性来将好卷的子集组合成稀疏的子网。作者推测,优化器会特别关注一组已经接受了良好初始化的参数。可能的组合越多,优化器就越容易找到初始化良好的参数的子集。

迭代幅度修剪

Figure 1: Taken from [Han et al. 2015]. Comparison of different pruning techniques and regularization methods. L2 reg. is better than L1 reg. as soon as the parameters are retrained. Iterative pruning outperforms all other methods.

LTH 论文的作者反复修剪和重新训练他们的模型。这是基于[韩等人,2015]的结果。Han 等人比较了一次性修剪、修剪和再训练以及使用不同正则化项的迭代修剪和再训练(见图 1)。主要结果是迭代修剪效果最好。 Frankle 和 Carbin 观察到,与一次性修剪相比,使用迭代修剪可以识别更小的中奖票。

为了验证彩票假说,弗兰克尔&卡宾应该找到与原始网络的准确性相匹配的子网络,当单独训练时。这意味着他们不能利用完整模型从以前的培训中获益。因此,他们通过将(非修剪的)权重值重置为初始化时的值来修改训练和修剪过程。

全局修剪与局部修剪

在修剪期间,可以在每一层修剪到期望的权重分数,或者将所有层的权重放入一个池中并进行全局修剪。在 LTH 的论文中,作者对 LeNet 和 Conv-2/4/6 使用了局部剪枝,而对更深层次的模型:Resnet-18 和 VGG-19 使用了全局剪枝。这个想法是,在更深的模型中,一些层的权重可能更重要,以保持[Morcos et al. 2019]。在视觉上,这些可以是充当特征检测器的第一层,并且可能不会像后面的层那样接收相同数量的修剪单元,后面的层可能具有更多冗余连接。

后期重置

学习率热身可以帮助找到更深入模型的中奖门票【Frankle & Carbin 2019】。在后续工作中,作者引入了一种不同的技术来处理更深层次的模型:后期重置[Frankle et al. 2019]。对于后期重置,权重不是重置为第一次训练迭代之前的值,而是重置为训练过程中非常早期的一些值(大约一到五次迭代之后)。当使用后期重置时,学习率预热不再必要。

赢得图像域之外的门票

彩票现象是使用前馈卷积网络进行监督图像分类的人工产物,还是会推广到其他领域?[Yu et al. 2019]可以表明,在强化学习和自然语言处理架构中也存在中奖票。他们的实验包括经典控制问题、雅达利游戏、LSTMs 和变形金刚。他们可以找到所有这些架构的中奖门票,这表明 LTH 现象并不局限于监督图像分类,而是可能是深度神经网络的一个普遍特征。

获奖入场券可以跨任务转移

到目前为止,识别中奖门票的程序仍然很昂贵,因为它涉及几个完整的培训通行证。我们怎么还能从中奖的门票中获益?我们能否将它们转移到其他任务中,以便只需要为目标任务学习一小部分权重?

两篇论文已经解决了这个问题:[Mehta 2019]和[Morcos et al. 2019]。这两项工作都停留在图像领域,并在不同的对象识别任务之间转移获奖门票。因为[Mehta 2019]打算充分利用源任务。在这种情况下,他将延迟重置扩展到源任务训练期间的任何地方。

他的结果表明只要至少全连接层被微调,中奖彩票是可以转让的。在迁移学习场景中,微调最终的全连接层是强制性的,因为不同的任务有不同的类。

[Morcos et al. 2019]也对图像域内的迁移学习进行了实验。该研究考虑了 CIFAR-10/100、FashionMNIST 和 MNIST 上的 VGG19 和 ResNet50 架构,同时还改变了优化器(SGD 和 Adam)。

他们的结果表明,赢得入场券并不特定于某个优化器。例如,通过 SGD 训练获得的中奖彩票可用于初始化 Adam 训练的砝码。关于跨任务的迁移,作者比较了从其他数据集获得的中奖票和从同一数据集获得的中奖票。

令人惊讶的是,从其他数据集获得的门票几乎与从同一数据集获得的门票一样好。他们的关键结果是,更大的数据集产生了更多通用的中奖彩票。

中奖票是什么样子的?

[周等 2019]对中奖彩票的性质进行了细致的调查。它们表明初始化值的一个至关重要的元素是它们的符号。初始化值的实际大小似乎不太重要。这可能会给优化者一个线索,让他们努力将消极的归因调整为积极的归因,反之亦然。

他们进一步假设将某些权重屏蔽为零类似于执行训练迭代。某个特征将与当前分类任务无关的信息与进行实际的训练迭代一样珍贵。

在分析了不同的剪枝和变更标准后,作者进一步声称当初始化接*它们的最终形式时,稀疏子网工作得特别好。在这个假设的基础上,作者更进一步发展了超级掩码的概念,超级掩码仅仅是根本没有经过训练的掩码和值的初始化。

有趣的是,这些超级任务产生的准确度分数远远好于偶然性。

修剪和剔除

Dropout 是一种众所周知的正则化方法,它通过将权重或隐藏单元的随机分数设置为零来鼓励训练期间的稀疏性容限。虽然丢弃概率是均匀随机绘制的,但修剪会专门移除低幅度的权重。[Gomez et al. 2019]追求改善辍学和修剪的交互作用的想法。这个想法是,丢失可以针对可能被删除的单元,即那些具有低幅度的单元。

在本文中,作者不仅分析了标准的单位丢失,还分析了权重丢失(又名 DropConnect ),这更接*于所采用的剪枝技术。

移动修剪

赢得入场券的圣杯是在训练过程中尽早识别它们。[Dettmers & Zettlemoyer 2019]提出了一种无需昂贵的再培训就能识别中奖门票的技术。他们利用梯度的动量来确定训练过程中权重变化的速度,以及他们可以降低训练误差的一致性。然后,在每个训练时期之后,它们修剪那些不能一致地减少误差的权重,并且在剩余的参数之间动态地重新分配它们的值。

在他们的实验中,他们所谓的稀疏动量技术优于所有被认为是稀疏学习的基线,甚至可以与密集模型竞争,所有这些都在一次训练迭代中完成。

限制

一些研究挑战彩票假说:【Gale et al . 2019】用 transformers 进行机器翻译的稀疏神经网络与 ResNet-50 进行图像分类的大规模比较。一方面,他们的结果证实了朴素量级剪枝[Han 2015]是比较中最好的剪枝技术。另一方面,他们报告说,LTH 的方法无法为这些更深层次的架构找到制胜的入场券。[Liu et al. 2018]表明,通过精心选择的学习率,随机门票可以与“中奖门票”一样好地执行,这就质疑了初始化的价值。然而,这两部作品都还没有使用后期重置[Frankle et al. 2019],这有助于找到获胜的门票,尤其是在深度架构中。

结论

彩票假说指出,密集神经网络包含稀疏子网络,这些子网络可以被隔离训练以匹配密集网络的性能。这种现象为过度参数化提供了一种新的解释,过度参数化导致彩票开奖次数成倍增加。为了从它们的存在中受益,人们需要找到方法来尽早识别中奖彩票,而根本不需要训练整个模型。一些方法已经解决了这一问题,而其他方法则专注于使神经网络更易于后期修剪的训练方法。

如果我们能够尽早识别出成功的入场券或将它们转移到其他领域,我们将节省大量的培训工作。赢得的入场券有时甚至胜过原来的网络,这可能会对我们理解和设计架构及其初始化方案产生影响。

奖励材料

  • 一个干净且通用的 pytorch 实现(迭代)幅度修剪,以我们的思想实验为特色。

参考

  1. 阿罗拉、桑吉夫、纳达夫·科恩和埃拉德·哈赞。“深度网络的优化:过度参数化的隐式加速”ICML 2018 年奥运会。
  2. 放大图片作者:LeCun,Yann,John S. Denker 和 Sara A. Solla .“最优脑残”神经信息处理系统进展,第 598–605 页。1990.
  3. 韩,宋,等.【高效神经网络的权值和连接学习】 NeurIPS 2015。
  4. 弗兰克、乔纳森和迈克尔·卡宾。彩票假说:寻找稀疏的、可训练的神经网络 ICLR 2019。
  5. Morcos,Ari S .,et al. “一张彩票赢所有人:在数据集和优化器中推广彩票初始化”arXiv 预印本 arXiv:1906.02773 (2019)。
  6. 等着,《彩票规模假说》 arXiv 预印本 arXiv:1903.01611 (2019)。
  7. 余,郝楠,等“用奖励和多种语言玩彩票:RL 和 NLP 中的彩票” arXiv 预印本 arXiv:1906.02768 (2019)。
  8. 梅塔,拉胡尔。“通过中奖彩票实现稀疏迁移学习” arXiv 预印本 arXiv:1905.07785 (2019)。
  9. 周,海蒂,贾妮斯兰,刘莎妮和杰森约辛斯基。《解构彩票:零、符号和超级面具》 arXiv 预印本 arXiv:1905.01067 (2019)。
  10. Gomez,Aidan N .等人“使用定向辍学学习稀疏网络” arXiv 预印本 arXiv:1905.13678 (2019)。
  11. 我是泽特勒莫耶。《从零开始的稀疏网络:更快的训练而不损失性能》 arXiv 预印本 arXiv:1907.04840 (2019)。
  12. 盖尔,特雷弗,埃里希·埃尔森和萨拉·胡克。“深度神经网络中的稀疏状态。” arXiv 预印本 arXiv:1902.09574 (2019)。
  13. 刘、庄、孙明杰、周廷辉、、特雷弗·达雷尔。“重新思考网络修剪的价值” arXiv 预印本 arXiv:1810.05270 (2018)。

时间序列预测的状态空间模型和卡尔曼滤波

原文:https://towardsdatascience.com/state-space-model-and-kalman-filter-for-time-series-prediction-basic-structural-dynamic-linear-2421d7b49fa6?source=collection_archive---------1-----------------------

基本结构模型&动态线性模型

利用金融数据进行时间序列预测

Image by author

https://sarit-maitra.medium.com/membership

T ime 系列由四大部分组成:季节变动(SV)、趋势变动(TV)、周期变动(CV)、随机变动(RV)。这里,我们将使用 状态空间模型 对单变量时间序列数据进行预测分析。该模型具有连续的隐藏和观察状态。

状态空间模型

让我们使用斯伦贝谢有限公司(SLB)自 1986 年以来的历史数据。

线形图

df1 = ts(df1$Open, start= c(1986,1), end = c(2019,12), frequency = 12)
xyplot(df1, ylab = “Price (US $)”, main = “Time series plot for Schlumberger price”)

这里,为了便于计算,数据是按月频率(12 个月)计算的。

线形图显示价格始终在波动,波动性很大。

密度和 Q-Q 图

下面由密度和正常 QQ 图组成的分布图清楚地表明数据分布不正常。

par(mfrow=c(2,1)) # set up the graphics 
hist(df1, prob=TRUE, 12) # histogram 
lines(density(df1)) # density for details 
qqnorm(df1) # normal Q-Q plot 
qqline(df1)

描述性统计

*稳性检验

让我们对原始数据进行*稳性检验(ADF,菲利普-佩龙& KPSS)。

stationary.test(df1, method = “adf”)
stationary.test(df1, method = “pp”) # same as pp.test(x)
stationary.test(df1, method = “kpss”)Augmented Dickey-Fuller Test 
alternative: stationary Type 1: no drift no trend lag   ADF p.value
[1,]   0 0.843   0.887
[2,]   1 0.886   0.899
[3,]   2 0.937   0.906
[4,]   3 0.924   0.904
[5,]   4 0.864   0.893
[6,]   5 1.024   0.917
Type 2: with drift no trend lag     ADF p.value
[1,]   0 -0.1706   0.936
[2,]   1 -0.0728   0.950
[3,]   2 -0.0496   0.952
[4,]   3 -0.0435   0.952
[5,]   4 -0.0883   0.947
[6,]   5  0.3066   0.978
Type 3: with drift and trend lag   ADF p.value
[1,]   0 -2.84   0.224
[2,]   1 -2.83   0.228
[3,]   2 -2.72   0.272
[4,]   3 -2.79   0.242
[5,]   4 -2.96   0.172
[6,]   5 -2.96   0.173
---- 
Note: in fact, p.value = 0.01 means p.value <= 0.01 
Phillips-Perron Unit Root Test 
alternative: stationary Type 1: no drift no trend lag Z_rho p.value5 0.343   0.768
----- Type 2: with drift no trend lag   Z_rho p.value5 -0.0692   0.953
----- Type 3: with drift and trend lag Z_rho p.value5 -11.6   0.386
--------------- 
Note: p-value = 0.01 means p.value <= 0.01 
KPSS Unit Root Test 
alternative: nonstationary Type 1: no drift no trend lag  stat p.value4 0.261     0.1
----- Type 2: with drift no trend lag  stat p.value4 0.367  0.0914
----- Type 1: with drift and trend lag  stat p.value4 0.123  0.0924
----------- 
Note: p.value = 0.01 means p.value <= 0.01 : p.value = 0.10 means p.value >= 0.10

数据标准化

我已经使用均值和标准差对数据集进行了归一化。戴夫。

自相关函数

确定不同时间滞后的相关性是否为 0

稳定=高斯噪声,一个趋势=高斯噪声的累积和。

这里,我们将通过查看每个信号的自相关函数来检查每个信号的*稳特性。对于*稳信号,我们期望 ACF 在每个时间延迟(τ)达到 0,因为我们期望不依赖于时间。

我们可以看到,稳态信号很少滞后于 ACF 的 CI。这种趋势导致几乎所有的滞后都超过了置信区间。可以断定 ACF 信号是稳定的。但是,趋势信号不是静止的。*稳序列在*均水*附*具有更好的方差,峰值是原始序列中干预的证据。

我们将进一步分解时间序列,包括水*、趋势、季节性和噪声成分的组合。分解有助于在分析和预测过程中更好地理解问题。

分解时间序列

我们可以应用差分数据或对数转换数据来消除趋势和季节性。如果我们只关心预测,这样的过程也许不是缺点。然而,在统计学和计量经济学应用的许多背景下,这一组成部分的知识具有潜在的重要性。趋势和季节的估计可以通过最大化残差均方差从差分序列中恢复,但这不如直接建模组件有吸引力。我们必须记住,实数列从来都不是稳定的。

这里,我们将使用时间序列的简单移动*均*滑方法来估计趋势分量。

df1SMA8 <- SMA(df1, n=8) # smoothing with moving average 8
plot.ts(df1SMA8)

df1Comp <- decompose(df1SMA8) # decomposing
plot(df1Comp, yax.flip=TRUE)

该图显示了原始时间序列(顶部)、估计趋势分量(从顶部数第二个)、估计季节分量(从顶部数第三个)和估计不规则分量(底部)。

我们看到,估计趋势分量显示从 1997 年的约 9 小幅下降到 1999 年的约 7,随后从那时起稳步上升到 2019 年的约 12。

季节性调整

df1.Comp.seasonal <- sapply(df1Comp$seasonal, nchar)
df1SeasonAdj <- df1 — df1.Comp.seasonal
plot.ts(df1SeasonAdj*)*

我们也将探讨卡尔曼滤波器在预测之前的系列滤波和*滑的目的。

结构模型

结构时间序列模型是(单变量)时间序列的(线性高斯)状态空间模型。当考虑状态空间架构时,通常我们有兴趣考虑三个主要方面:

  • 预测,即预测状态的后续值
  • 滤波,从过去和当前的观察值中估计状态的当前值
  • *滑,即在给定观察值的情况下估计状态的过去值

我们将使用卡尔曼滤波器来进行各种类型的推断。

过滤有助于我们在每次观察到来时更新对系统的了解。*滑有助于我们根据整个样本来估计感兴趣的数量。

基本结构模型(BSM)

结构模式的优点是使用简单,非常可靠。它给出了最大似然法拟合时间序列结构模型的主要工具。

结构化时间序列状态空间模型,基于将序列分解为若干部分。它们由一组误差方差指定,其中一些方差可能为零。我们将使用一个基本的结构模型来拟合随机水*模型进行预测。构成状态空间模型的两个主要部分是(1)观察到的数据和(2)未观察到的状态。

最简单的模型是局部级别模型,它有一个基础级别 t,它通过以下方式发展:

我们需要看到观察结果,因为系统噪声对我们隐藏了状态。观察值是当前状态和一些称为测量噪声的附加随机变化的线性组合。观察结果是:

它实际上是一个 ARIMA(0,1,1)模型,但是对参数集有限制。这是随机变化的水*(随机游走)用噪声观察到的。

局部线性趋势模型具有相同的测量方程,但是对于 t 具有动态时变斜率,由下式给出

有三个方差参数。这里εt,ξt,ζt 是独立的高斯白噪声过程。基本结构模型是一个带有额外季节性成分的局部趋势模型。因此,测量公式为:

其中γt 是具有动态的季节性分量

训练/测试分割

模型拟合和预测

最好的做法是检查结构化过程的收敛性。与任何结构化过程一样,我们需要有适当的初始起点,以确保算法将收敛到正确的最大值。

autoplot(training, series=”Training data”) + autolayer(fitted(train, h=12), series=”12-step fitted values”)

交互效度分析

交叉验证是时间序列分析的一个重要步骤。

  • 将模型拟合到数据 y1,.。。,yt
  • 生成提前一步的预测-yt+1
  • 计算预测误差 e∫t+1 = yt+1yˇt+1
  • 对于 t = m,重复步骤 1–3。。。,n-1,其中 m 是适合模型的最小观察值
  • 根据 e∫m+1,计算预测 MSE。。。,e *

残差 Ljung-Box 检验的 p 值为 0.2131015 >显著水*(0.05);因此,不建议使用交叉验证的结果,因为该模型明显不符合数据。

基础诊断学

我们进行任何统计分析的第一个诊断是检查我们的残差是否符合我们假设的误差结构。在单变量状态空间模型中,我们有两种类型的误差:过程误差,wt,和观察误差,vt。它们不应该有时间趋势。

模型.残差

vt 是 t 时刻的数据与预测数据之差:vt = yt Zxt a

在状态空间模型中,xt 是随机的,模型残差是随机变量。yt 也是随机的,尽管不像 xt 那样经常被观察到。模型残差随机变量为:Vt = Yt ZXt a

Vt 的无条件均值和方差为 0,R

checkresiduals(train)

卡尔曼滤波器

卡尔曼滤波算法使用一系列随时间观察到的测量值,包含噪声和其他不准确性,并产生未知变量的估计值。这种估计往往比仅基于单个测量结果更准确。使用卡尔曼滤波器并不假设误差是高斯的;然而,在所有误差都是高斯的特殊情况下,滤波器产生精确的条件概率估计。

卡尔曼滤波是一种寻找过程估计值的方法。过滤来自于减少或“过滤掉”不想要的变量的原始用法,在我们的例子中是估计误差。

sm <- tsSmooth(train)
plot(df1)
lines(sm[,1],col=’blue’)
lines(fitted(train)[,1],col=’red’)# Seasonally adjusted data
training.sa <- df1 — sm[, 1]
lines(training.sa, col=’black’)
legend(“topleft”,col=c(‘blue’, ’red’, ‘black’), lty=1,legend=c(“Filtered level”, ”Smoothed level”)

x <- training
miss <- sample(1:length(x), 12)
x[miss] <- NA
estim <- sm[,1] + sm[, 2]
plot(x, ylim=range(df1))
points(time(x)[miss], estim[miss], col = ’red’, pch = 1)
points(time(x)[miss], df1[miss], col = ’blue’, pch = 1)
legend(“topleft”, pch = 1, col = c(2,1), legend = c(“Estimate”, ”Actual”))

plot(sm, main = “”)
mtext(text = “decomposition of the basic structural”, side = 3, adj = 0, line = 1)

预言;预测;预告

sm %>%forecast(h=12) %>%autoplot() + autolayer(testing)

下图显示了预测的斯伦贝谢数据以及 50%和 90%的概率区间。

正如我们所看到的,BSM 模型能够很好地提取季节成分。我们可以在这里试验基于 SMA 的分解(如前所示),并比较预测准确性。

带有卡尔曼滤波器的动态线性模型

dlm 模型是状态空间模型的特殊情况,其中状态和观察分量的误差是正态分布的。这里,卡尔曼滤波器将用于:

  • 状态向量的过滤值。
  • 状态向量的*滑值,
  • 预测提供了未来观测值和状态的均值和方差。

我们必须在拟合 dlm 模型之前定义参数。这些参数是 V,W(分别是测量和状态方程的协方差矩阵),FF 和 GG(分别是测量方程矩阵和转移矩阵),以及 m0,C0(状态向量的先验均值和协方差矩阵)。

但是,在这里,我们通过编写一个如下所示的小函数来启动 dlm 模型:

我考虑了具有 dlm、多项式 DLM(局部线性趋势是二阶多项式 DLM)和季节成分 12 的局部水*模型。检查 MLE 过程的收敛性是一个好的实践,而不是最佳实践的一部分。

卡尔曼滤波器和*滑器也被应用。

我们可以看到,dlm 模型的预测精度相当不错。过滤器和*滑线在系列中几乎是一起移动的,彼此没有太大区别。这里忽略了季节因素。预测序列和原始序列的线非常接*。

状态空间模型与时间序列分析的一个很好的例子可以在这里找到

摘要

状态空间模型有多种风格和处理大量时间序列模型的灵活方式,并提供了处理缺失值、似然估计、*滑、预测等的框架。单变量和多变量数据都可以用来拟合状态空间模型。在本练习中,我们展示了一个基本级别的模型。

我可以到达这里的 **

参考:

  1. 德宾,j .,&库普曼,S. J. (2012)。用状态空间方法进行时间序列分析。牛津大学出版社。
  2. Giovanni Petris&Sonia Petrone(2011),R 中的状态空间模型,统计软件杂志
  3. G . Petris、S . Petrone 和 P . Campagnoli(2009 年)。带有 R. Springer 的动态线性模型
  4. Hyndman,R. J .,& Athanasopoulos,G. (2018)。预测:原理与实践。OTexts。

时间序列分析的*稳性

原文:https://towardsdatascience.com/stationarity-in-time-series-analysis-90c94f27322?source=collection_archive---------1-----------------------

*稳性的概念和类型综述

这篇文章旨在提供一个简明而全面的综述,介绍*稳性的概念,以及在处理时间序列分析的学术文献中定义的不同类型的*稳性。

未来的帖子将致力于提供类似的简要概述,介绍时间序列数据中非*稳性的检测,以及将非*稳时间序列转换为*稳时间序列的不同方法。

为什么*稳性很重要?

在深入研究*稳性的正式定义及其相关概念之前,有必要考虑一下为什么*稳性的概念在时间序列分析及其各种应用中变得如此重要。

从最直观的意义上来说,*稳性意味着生成时间序列的过程的统计特性不会随时间而改变。这并不意味着这个系列不会随着时间而改变,只是它改变的方式本身不会随着时间而改变。因此,代数等值可能是一个线性函数,而不是一个常数;线性函数的值随着𝒙的增长而变化,但是它变化的方式保持不变——它有一个恒定的斜率;一个能捕捉到变化率的值。

Figure 1: Time series generated by a stationary (top) and a non-stationary (bottom) processes.

为什么这很重要?首先,因为*稳过程更容易分析。没有生成时间序列数据的过程的正式定义(还没有;它们被称为随机过程,我们一会儿就会讲到),已经很清楚,*稳过程是一个更广泛的现实可能模型家族的一个子类。这个子类更容易建模和研究。上面的非正式定义也暗示了这样的过程应该是可以预测的,因为它们变化的方式是可以预测的。

虽然这听起来有点像路灯效应,简单的理论或模型应该变得更加突出,但这实际上是科学中相当常见的模式,而且有充分的理由。在许多情况下,简单的模型会令人惊讶地有用,要么作为构建更复杂模型的基础,要么作为复杂现象的有用*似。事实证明,这也适用于*稳过程。

由于这些性质,*稳性已经成为时间序列分析中许多实践和工具的共同假设。其中包括趋势估计、预测和因果推断等。

因此,*稳性的重要性的最后一个原因是它在时间序列分析中的普遍性,使得理解、检测和建模的能力对于时间序列分析中许多重要工具和程序的应用是必要的。事实上,对于许多涉及时间序列的情况,您会发现您必须能够确定数据是否是由*稳过程生成的,并可能对其进行转换,使其具有由这种过程生成的样本的属性。

如果你想处理时间序列数据,希望我已经说服你理解*稳性是重要的,我们可以更正式地介绍这个主题。

随机过程的形式定义

在介绍更正式的*稳性概念之前,需要一些先驱性的定义。本节旨在提供进一步阅读所需的时间序列分析和随机过程理论的基本概念的快速概述。如果你熟悉他们,请随意跳过。

时间序列:通常,时间序列 (x,…,xₑ) 被认为是从时间 t=1 到时间 t=e 在连续的等间距 ⁶ 时间点所取的一系列实数值。

滞后:对于某个特定的时间点 r ,观测值 x ᵣ₋ᵢ ( i 周期回退)称为 x ᵣ.的 i -th 滞后将另一个时间序列 X 后移 i 时间步长产生的一个时间序列 Y 有时也称为 X 的Ith滞后Xi 滞后。这种变换既称为后移算子,通常表示为 B (∙),也称为滞后算子,通常表示为L();于是,l(xᵣ)= xᵣ₋₁经营者的权力定义为:lⁱ(xᵣ】= xᵣ₋ᵢ.

随机过程

时间序列数据分析的一种常见方法是将观察到的时间序列视为随机过程实现的一部分。在定义随机过程之前,需要两个粗略的定义。

概率空间: A 概率空间是三元组(ω,F,P) ,其中
(I)ω是非空集,称为样本空间。
(ii) F 是ω的子集的-代数,即关于ω的可数并闭和补的子集族。
(iii) P 是为 F 的所有成员定义的概率测度。

随机变量: A 随机变量实随机变量(ω,f,P)* 上是一个函数x:ω→ℝ,使得任意区间 (-∞,a】【t40)的逆像属于f*;即可测功能。**

我们现在可以定义什么是随机过程。

随机过程:一个实随机过程是一族实随机变量𝑿={ x(ω);i* ∈ T} ,都定义在同一个概率空间上(ω,F,P) 。集合 T 称为流程的索引集合。如果 T ⊂ℤ,那么这个过程叫做离散随机过程。如果 T 是ℝ的一个区间,那么这个过程叫做连续随机过程。*

有限维分布:对于有限整数集合 T ={t₁,…,tn} ,𝑿= {X(ω)的联合分布函数;iT} 定义如下

Equation 1: The joint distribution function.

对于随机过程,𝑿通常也表示为:

随机过程的有限维分布于是被定义为任意大小 n 的所有此类有限整数集 T 的所有此类联合分布函数的集合。因此,对于离散过程,集合为:

Equation 2: Finite dimensional distribution for a discrete stochastic process.

直观地说,这代表了流程在有限维向量空间上的投影(在这种情况下,是一组有限的时间点)。

*稳性的定义

有了随机过程的基本定义,我们现在可以引入*稳性的概念。

直观上,*稳性是指过程的统计性质不随时间变化。然而,多年来在计量经济学文献中已经提出了几种不同的*稳性概念。

在深入这些定义之前,要做的一个重要区分是*稳性——任何种类——是随机过程的属性,而不是它的任何有限或无限实现的(即值的时间序列)。

强*稳性

强*稳性 要求随机过程的有限维分布具有*移不变性(在时间上)。这意味着随机过程的随机变量的有限子序列的分布在我们沿着时间索引轴移动它时保持不变。比如所有的 i.i.d. 随机过程都是*稳的。

形式上,离散随机过程𝑿={ x;i∈ℤ}* 是否静止如果*

Equation 3: The stationarity condition.

对于 Tn ∈ℕ与任意τ∈ 。[考克斯&米勒,1965]对于连续随机过程来说条件是类似的,用 T ⊂ℝ、 n ∈ℕ和任何一个τ∈ℝ 代替。**

这是*稳性最常见的定义,通常简称为*稳性。有时也被称为严格意义上的*稳性强意义上的*稳性

注:该定义不假设构成随机过程的随机变量的任意时刻的存在/有限性!

弱*稳性

弱*稳性 只需要一阶矩和交叉矩(自协方差)的*移不变性(在时间上)。这意味着该过程在所有时间点都具有相同的均值,并且任意两个时间点的值 tt k之间的协方差仅取决于两个时间点之间的差值 k ,而不取决于沿时间轴的点的位置。

形式上,流程{ x;i∈ℤ}* 是弱*稳如果:
1。 x ᵢ的一阶矩不变;即 ∀t,e【x]=𝜇t23】2。对于所有 t, x ᵢ的二阶矩是有限的;即 ∀t,e【x<∞(这其中当然也隐含着e[(x-𝜇)]<∞;即对于所有的 t )
3,方差是有限的。交叉力矩——即自协方差——仅取决于差值u-v;即 ∀u,v,a、cov(xᵤ、xᵥ)=cov(xᵤ₊ₐ、xᵥ₊ₐ)*

第三个条件意味着每个滞后𝜏ℕ都有一个与之相关联的恒定协方差值:

注意,这直接意味着过程的方差也是常数,因为我们得到所有 t ℕ的方差

这为弱*稳过程描绘了一幅特殊的图画,即那些具有恒定均值和方差的过程。它们的属性与下面图 2 中的对应属性形成了鲜明的对比。

Figure 2: Constancy in mean and variance.

弱*稳的其他俗称有广义*稳、* 弱意义*稳协方差*稳二阶*稳 。令人困惑的是,根据上下文,它有时也被简单地称为*稳性(参见【Boshnakov,2011】中的例子);例如,在地理统计文献中,这是*稳性的主要概念。[迈尔斯,1989 年]*

注意:强*稳性并不意味着弱*稳性,后者也不意味着前者(见例此处)!高斯过程是一个例外,对于它来说,弱*稳性意味着强*稳性。
强*稳性并不意味着弱*稳性的原因是,它并不意味着过程必然有一个有限的二阶矩;例如,具有标准柯西分布的 IID 过程是严格*稳的,但是没有有限二阶矩 ⁴ (参见【Myers,1989】)。的确,对于强*稳过程的弱*稳性,有一个有限的二阶矩是一个充分必要条件。

白噪声过程 : 白噪声过程是一个序列不相关的随机过程,均值为零,方差恒定且有限。

形式上,流程{ x;i∈ℤ}* 是t18】一个白噪声过程如果:
1。 x ᵢ的一阶矩始终为零;即 ∀t,e[x
= 0*
2。对于所有 t, x ᵢ的二阶矩是有限的;即 ∀t,e[(x-𝜇)]<∞
3。当 u≠v 时,交叉力矩e[xᵤxᵥ】为零;即 ∀u,v w. u ≠v、 cov(xᵤ、xᵥ)=0**

注意,这意味着每个白噪声过程都是弱*稳过程。此外,如果每个变量 xᵢ遵循具有零均值和相同方差的正态分布 σ ,则该过程被称为高斯白噪声过程

n 阶*稳性

非常接*于强*稳性的定义, N 阶*稳性要求随机过程的任意 n 个样本的分布的*移不变性(在时间上),对于所有 nN 阶。

因此,需要相同的条件:

Equation 4: The N-th order stationarity condition.

对于 Tn{1,…,N} 与任意τ∈

自然,对某一阶 N 的*稳性并不意味着任何更高阶的*稳性(但反之亦然)。在 mathoverflow 中的一个有趣的线程展示了一个一阶*稳过程(不是二阶*稳)的例子和一个二阶*稳过程(不是三阶*稳)的例子。

注意,对于 N=2 的第 N 阶的*稳性令人惊讶地不等同于弱*稳性,即使后者有时被称为二阶*稳性。[Myers,1989]与强*稳性一样,𝑿的任意两个样本的分布的二阶*稳性所设定的条件并不意味着𝑿具有有限的矩。同样,具有有限的二阶矩是二阶*稳过程也是弱*稳过程的充分必要条件。

一阶*稳性

一阶*稳性这个术语有时用来描述一个序列,它的均值永远不会随时间变化,但其他任何时刻(如方差)都可能发生变化。[Boshnakov,2011 年]

再次注意,这个定义并不等同于 N=1 的 N 阶*稳性,因为后者需要 x ᵢ对于进程𝑿= {x都是同分布的;我ℤ} 。比如一个过程,其中 x ᵢ~𝓝(𝜇, f(i) )其中 f(i)=1 为偶数的 if(i)=2 为奇数的,在时间上具有恒定的均值,但是 x ᵢ不是同分布的。因此,这种过程属于一阶*稳性的特定定义,但不属于 N=1N 阶*稳性。

循环*稳性

如果任意样本集的联合分布在 mP,的时移上不变,则随机过程是循环*稳的,其中m和 P∈ℕ是过程的周期:

Equation 5: The cyclostationarity condition.

循环*稳在信号处理中非常重要。

Figure 3: A white noise process 𝑛(𝑡) modulated by sin2𝜔𝑡 produces the cyclostationary process 𝑥(𝑡)=𝑛(𝑡)sin2𝜔𝑡

趋势*稳性

如果一个潜在的趋势(仅仅是时间的函数)可以被移除,留下一个*稳的过程,那么一个随机过程就是趋势*稳的。含义,该过程可以表示为yᵢ=f(I)+εᵢ,其中 f(i) 是任意函数f:ℝ→ℝεᵢ是均值为零的*稳随机过程。

在存在冲击的情况下(序列值的显著和快速的一次性变化),趋势*稳过程是均值回复的;即,随着时间的推移,该序列将再次向增长(或收缩)均值收敛,这不受冲击的影响。

Figure 4: Trend stationary processes revert to their mean after a shock is applied.

联合*稳性

对于随机过程对,上述所有类型的*稳性都有直观的扩展。例如,对于一对随机过程𝑿和𝒀,联合强*稳性是由强*稳性的相同条件定义的,但是简单地强加于两个过程的联合累积分布函数。弱*稳性和 N 阶*稳性可以用同样的方法扩展(后者扩展到 M - N 阶联合*稳性)。

内在假设

弱*稳性的一种较弱形式,在地质统计学文献中较为突出(例如,参见【Myers 1989】和【Fischer 等人 1996】)。内在假设适用于随机过程𝑿={Xᵢ},如果:

  1. 由距离 r 分开的任意两个地方的值之间的期望差为零: E[xᵢ-xᵢ₊ᵣ]=0
  2. var[xᵢ-xᵢ₊ᵣ给出的差的方差是存在的(即它是有限的),并且只取决于距离 r

这个概念暗示了差分 Xᵢ-Xᵢ₊ᵣ的弱*稳性,并通过定义 N 阶内在假设进行了扩展。

局部*稳随机过程

一类重要的非*稳过程是局部*稳(LS)过程。【Cardinali&Nason,2010】给出了 LS 过程的一个直观定义,即它们的统计特性随时间缓慢变化。或者,【达尔豪斯,2012】将它们(非正式地)定义为在每个时间点局部上接*于*稳过程,但其特征(协方差、参数等)是*稳的过程。)随着时间的推移以一种不确定的方式逐渐变化。正式定义见[Vogt,2012 年],T28,[达尔豪斯,2012 年],T29 对该主题进行了严格审查。

LS 过程非常重要,因为它们在一定程度上弥合了参数非*稳过程的彻底探索子类(见下一节)和更广泛的非参数过程家族的未知水域之间的差距,因为它们已经接受了严格的处理和一套相应的分析工具,类似于参数过程所享有的那些工具。关于这个主题的一个很好的在线资源是 Guy Nason 教授的主页,他把 LS 过程作为他的主要研究兴趣。

*稳概念的类型学

下面的类型图,虽然可能是局部的,但可以帮助理解我们刚刚讨论过的不同的*稳性概念之间的关系:

Figure 5: Types of non-stationary processes

非*稳性的参数概念

到目前为止,*稳性的定义是非参数的;也就是说,他们没有假设数据生成过程的模型,因此适用于任何随机过程。然而,差分*稳性和单位根过程的相关概念需要简单介绍随机过程建模。

随机建模的主题也是相关的,因为各种简单的模型可以用来创建随机过程(见图 5)。

Figure 6: Various non-stationary processes (the purple white noise process is an exception).

随机过程建模中的基本概念

未来值的预测是时间序列数据研究中的一项常见任务。要进行预测,需要对数据生成过程(DGP)和生成数据的机制做出一些假设。这些假设通常采用过程的显式模型的形式,并且在为其他任务(如异常检测或因果推断)建模随机过程时也经常使用。我们将讨论三种最常见的模型。

自回归(AR)模型 : 使用 AR 模型建模的时间序列被假设生成为其过去值的线性函数,加上随机噪声/误差:

Equation 4: The autoregressive model.

这是一个基于记忆的模型,在这个意义上,每个值都与前面的 p 值相关;具有滞后 p 的 AR 模型用 AR(p) 表示。系数𝜙 是衡量这些在前值对值 x【t】的影响的权重,c* 是常数截距,ε 是单变量白噪声过程(通常假设为高斯)。*

向量自回归(VAR) 模型将 AR 模型的单变量情况推广到多变量情况;现在,长度为 k 的向量x【t】的每个元素可以被建模为过去的向量 p 的所有元素的线性函数:

Equation 5: The vector autoregressive model.

其中 ck 常数(截距)的向量, Aᵢ 为时不变的 k×k 矩阵,e={ e;i∈ℤ}* 是一个白噪声多变量过程k 变量。*

移动*均(MA)模型 : 一个使用移动*均模型建模的时间序列,用 MA(q) 表示,被假设为由ε ᵢ、单变量白噪声过程产生的最后一个 q+1 随机冲击的线性函数;

Equation 6: The moving average model.

像自回归模型一样,向量泛化,VMA,是存在的。

自回归移动*均(ARMA)模型 : 使用 ARMA(p,q) 模型建模的时间序列被假设为由ε ᵢ、单变量白噪声过程产生的最后 p 值和最后 q+1 随机冲击的线性函数;

Equation 7: The ARMA model.

ARMA 模型可以以多种方式推广,例如处理非线性或外生变量、多变量情况(VARMA)或处理(特定类型的)非*稳数据(ARIMA)。

差分*稳过程

有了对常见随机过程模型的基本理解,我们现在可以讨论差分*稳过程和单位根的相关概念。这个概念依赖于这样一个假设,即所讨论的随机过程可以写成一个阶为 p、的自回归过程,表示为 AR(p):

Equation 8: An autoregressive process of order p, or AR(p).

其中ε 通常是不相关的白噪声过程(对于所有时间 t )。我们可以将相同的过程写成:

Equation 9: An AR(p) model written using lag operators.

左边括号内的部分称为过程的特征方程。我们可以考虑这个等式的根:

Equation 10: The characteristic equation of a AR(p) model.

如果 m=1 是方程的根,那么这个随机过程被称为是一个差分*稳过程,或者是积分。这意味着通过对其应用某种类型的变换,该过程可以被转换成弱*稳过程,称为差分。

Figure 7: A time series (left) and a the series after differencing (right)

差分*稳过程有一个积分阶,这是差分算子必须应用于它的次数,以便实现弱*稳性。一个必须被微分 r 次的过程被称为按照顺序 r、被积分,用 I(r) 表示。这正好与根的重数 m=1 相吻合;也就是说,如果 m=1 是特征方程的重数 r 的根,那么这个过程就是 r 阶的积分。

单位根过程

差分*稳过程的一个常见子类型是一阶积分过程,也称为单位根过程。这种过程最简单的例子是下面的自回归模型:**

单位根过程和一般的差分*稳过程是有趣的,因为它们是非*稳过程,可以很容易地转化为弱*稳过程。因此,虽然这个术语不能与非*稳性互换使用,但关于它们的问题有时是可以互换的。

我认为这里值得一提,因为有时检查一个过程是否有单位根的测试和过程(一个常见的例子是 Dickey-Fuller 测试)被错误地认为是测试非*稳性的过程(在本系列的后面一篇文章中会提到)。因此,重要的是要记住这些是不同的概念,虽然每个具有单位根的过程都是不稳定的,集成到订单 r > 1 的每个过程也是不稳定的,但相反的情况远非如此。

半参数单位根过程

另一个有趣的定义是非*稳过程的更广泛、参数更少的子类,可以称为半参数单位根过程。该定义是在[Davidson,2002]中介绍的,但可以在[Breitung,2002]中找到它的简明概述。

如果你对*稳性的概念感兴趣,或者在处理时间序列数据时无意中发现了这个主题,那么我希望这篇文章是对这个主题的一个很好的介绍。下面是一些参考资料和有用的链接。

正如我提到的,本系列的后一篇文章提供了非*稳性检测方法的类似概述,另一篇文章将提供非*稳性时间序列数据转换的类似概述。

另外,如果你对这篇文章或这个话题有任何意见和想法,请随时联系我。

参考

学术文献

  • [博什纳科夫,2011 年] G .博什纳科夫。 关于随机系数模型的一阶和二阶*稳性 。线性代数应用 434,415–423。2011.
  • [Breitung,2002 年] 单位根与协整的非参数检验。 《计量经济学杂志》,108 卷 2 期,第 343–363 页。
  • [卡迪纳利和纳森,2010 年]局部*稳时间序列的协同性。时间序列计量经济学杂志2 (2)。
  • [考克斯和米勒,1965 年]考克斯博士;和 H. D .米勒,1965,《随机过程理论》,伦敦,398 页。
  • [达尔豪斯,2012 年]达尔豪斯河(2012 年)局部*稳过程。在统计手册(第 30 卷,第 351-413 页)中。爱思唯尔。
  • 戴维森,2002 年。 建立非线性和半参数时间序列过程中泛函中心极限定理的条件 ,《计量经济学杂志》106,243–269。
  • 【Dyrhovden,2016】Dyrhovden,Sigve Brix。2016. 随机单位根过程 。卑尔根大学。
  • [费希尔等人,1996 年]费希尔,m .斯霍尔滕,H. J .和昂温,d .编辑。GIS 的空间分析视角 。宾夕法尼亚州布里斯托尔:泰勒&弗朗西斯——吉斯达;4.
  • [迈尔斯,1989]迈尔斯博士,1989。 生存还是毁灭。。。静止的?那就是问题 。数学。地理 21,347–362。
  • 【Nason,2006】Nason,GP 2006,*稳与非*稳时间序列。在 H Mader&SC Coles(eds)火山学中的统计学。地质学会,第 129–142 页。
  • [Vogt,2012 年] Vogt,M. (2012 年)。局部*稳时间序列的非参数回归。统计年鉴40 (5),2601–2633。

在线参考

  • 在 Analytics Vidhya 用 Python 处理非*稳时间序列的温和介绍
  • 单位根在维基百科
  • 第 4 课:*稳随机过程来自翁贝托·特里亚卡的随机过程课程
  • 特征方程的根与其逆的根的倒数
  • 随机过程特征
  • 趋势*稳与差异*稳过程
  • 盖伊·纳森教授的主页

脚注

  1. 这里的措辞并不严格准确,因为——正如我们很快会看到的——时间序列本身不可能是静态的,只有产生它们的过程才能是静态的。然而,我使用它是为了不假设开头的段落有任何知识。
  2. 弱意义*稳性的常见同义词二阶*稳性可能与二阶随机过程的概念有关(但不应与之混淆),二阶随机过程被定义为具有有限二阶矩(即方差)的随机过程。
  3. 注意,反之则不然。不是每个*稳过程都是由 IID 变量组成的;*稳性是指变量的联合分布不依赖于时间,但它们仍可能相互依赖。
  4. 这也是一个很好的例子,说明 IID 并不意味着弱*稳性;然而,由于它确实意味着强*稳性,所以它具有与它意味着强*稳性相同的充分必要条件:具有有限的矩。
  5. *稳性的一个次要但有趣的概念是p——*稳过程。
  6. 也有正式的方法来处理样本间隔不相等的时间序列。

统计分布

原文:https://towardsdatascience.com/statistical-distributions-24b5b4ba43cc?source=collection_archive---------10-----------------------

分解离散和连续分布,研究数据科学家如何最有效地应用统计数据。

什么是概率分布?

概率分布是一种数学函数,它提供了实验中各种可能结果出现的概率。概率分布用于定义不同类型的随机变量,以便根据这些模型做出决策。有两种类型的随机变量:离散的和连续的。根据随机变量所属的类别,统计学家可能决定使用与该类随机变量相关的不同方程来计算*均值、中值、方差、概率或其他统计计算。这很重要,因为随着实验变得越来越复杂,用于计算这些参数(如*均值)的标准公式将不再产生准确的结果。

A continuous distribution (Normal Distribution) vs. a discrete distribution (Binomial Distribution)

离散分布

离散分布显示了具有有限值的随机变量的结果的概率,并用于模拟离散随机变量离散分布可以用表格来表示,随机变量的值是可数的。这些分布由概率质量函数定义。

概率质量函数(或 pmf)计算随机变量采用一个特定值的概率:Pr(X=a)。下面显示了一些离散分布的图示示例。对于离散框架中的任何 x 值,都有一个概率对应于特定的观察结果。

连续分布

连续分布显示具有无限值的随机变量的结果的概率范围,并用于模拟连续随机变量连续分布衡量一些东西,而不仅仅是计数。事实上,这些类型的随机变量是不可数的,在一个特定点上连续随机变量的概率为零。连续分布通常由概率分布函数描述。

概率密度函数(或 pdf)是用于计算连续随机变量小于或等于其计算值的概率的函数:Pr(a≤X≤b)或 Pr(X≤b)。为了计算这些概率,我们必须分别在[a-b]或[0-b]范围内对 pdf 进行积分。下面显示了一些连续分布的图形表示示例。可以观察到,这些图具有曲线性质,每个 x 值没有不同的值。这是因为,在任何给定的特定 x 值或连续分布中的观察值,概率为零。我们只能计算一个连续的随机变量位于一个值范围内的概率。还应注意,曲线下方的面积等于 1,因为这代表所有结果的概率。

期望值或*均值

每种分布,无论是连续的还是离散的,都有不同的相应公式,用于计算随机变量的期望值或均值。随机变量的期望值是随机变量集中趋势的度量。描述期望值的另一个术语是“第一时刻”。这些公式中的大部分通常不像人们直观预期的那样工作,这是由于分布将我们置于其中。重要的是要记住期望值是人们对随机变量的期望值。

为了手动计算离散随机变量的期望值,必须将随机变量的每个值乘以该值的概率(或 pmf),然后对所有这些值求和。例如,如果我们有一个离散随机变量 X,它具有(值,概率):[(1,0.2),(2,0.5),(3,0.3)],那么 E[X](或 X 的期望值)等于(1 * 0.2) + (2 * 0.5) + (3 * 0.3)= 2.1。这个策略可以被认为是对 X 可以假设的所有值进行加权*均。

为了“手动”计算连续随机变量的预期值,必须在 x 的整个定义域上对 x 乘以随机变量的 pdf(概率分布函数)进行积分。如果您还记得,pdf 在整个定义域上的积分结果是值 1,因为这是在假设随机变量在其定义域中的任何值的情况下计算随机变量的概率。这类似于这样一个概念:如果我们将离散随机变量 X 的每个值的所有概率相加,而不乘以 X 的每个对应值,那么总和将等于 1。在积分中乘以 x,可以让我们考虑这个值,就像在离散变量求和中乘以 x,可以让我们考虑这个值一样。当我们将 pdf 乘以 x 时,我们得到了随机变量 x 的所有可能观测值的加权*均值。

差异

每个定义的随机变量也有一个与之相关的方差。这是对随机变量中观察值的集中程度的度量。这个数字将告诉我们观察值与*均值相差有多远。常数的方差为零,因为常数的均值等于常数,只有一个观测值恰好是均值。标准差也很有用,它等于方差的*方根。当计算方差时,想法是计算随机变量的每个观察值离它的期望值有多远,*方它,然后取所有这些*方距离的*均值。方差的公式如下:

开始学习统计和概率的时候,分布的个数和它们各自的公式会变得非常令人应接不暇。值得注意的是,如果我们知道一个随机变量遵循一个定义的分布,我们可以简单地使用它们的均值或方差公式(有时甚至是它们的参数)来计算这些值。然而,如果随机变量并不明显遵循定义的分布,最好使用应用求和与积分的基本公式来计算*均值和方差,或您分析中可能需要的任何其他值,其中随机变量 x 乘以每个观察值的 pmf 或 pdf,并分别求和或积分。为了找到方差,请遵循方差公式,并通过使用与第一个矩相同的程序获得随机变量的第二个矩,但是,用 x 替换 x。例如,有时通过一些检查很容易发现,或者我们被告知某个随机变量遵循某个分布,而其他时候我们只得到可能不熟悉的 pmf 或 pdf,以匹配已知的分布。

随着使用这些随机变量的实践,识别随机变量的 PMF 和 pdf 变得更加容易。能够在实践中快速识别各种分布是有利的,因为它可以节省大量时间,并帮助统计学家和精算师变得更有效率。

然而,对于数据科学家来说,Python 中的 scipy.stats 库为您需要处理的每种概率分布都提供了方便的类,可以用来轻松地可视化和处理这些分布。我们能够生成遵循特定分布的随机变量,并以图形方式显示这些分布。下面显示了使用 Python 代码获得离散和连续分布可视化的一些示例。

First, matplotlib.pyplot and seaborn should be imported

From there, we are able to import the distribution we want to examine, define it’s parameters, and plot the distribution using seaborn’s distplot. Here, we look at the continuous distribution called Uniform Distribution.

Here we examine one of the most common continuous distributions, the Normal Distribution.

Here we look at a discrete distribution called the Binomial Distribution.

Here we look at another discrete distribution that may be less common, the Logser Distribution.

scipy.stats 中还内置了“屏蔽统计函数”,使我们能够快速计算随机变量的不同特征(均值、标准差、方差、变异系数、峰度等。).最后,通过使用这个 Python 库,我们能够轻松地对数据应用不同的变换,例如 BoxCox 变换或 z-score 变换。

我们来连线:

https://www.linkedin.com/in/mackenzie-mitchell-635378101/

[## 麦肯齐米切尔 6 -概述

在 GitHub 上注册您自己的个人资料,这是托管代码、管理项目和与 40…

github.com](https://github.com/mackenziemitchell6)

参考资料:

[## 统计函数(scipy.stats) - SciPy v1.3.0 参考指南

这个模块包含了大量的概率分布以及不断增长的统计函数库。

docs.scipy.org](https://docs.scipy.org/doc/scipy/reference/stats.html#random-variate-generation) [## 教练精算师

你具备成为精算师的条件。我们有备考工具来帮助您有效地利用视频…

www.coachingactuaries.com](https://www.coachingactuaries.com/) [## Python 中的概率分布

概率和统计是数据科学的基础支柱。事实上,机器的基本原理…

www.datacamp.com](https://www.datacamp.com/community/tutorials/probability-distributions-python)

统计学习和知识工程

原文:https://towardsdatascience.com/statistical-learning-and-knowledge-engineering-all-the-way-down-1bb004040114?source=collection_archive---------34-----------------------

结合机器学习和知识库的途径

Photo by Joao Tzanno on Unsplash

Cycorp,Inc .的首席执行官兼 AAAI 研究员道格·勒纳特,在AAAI Make 会议期间,在斯坦福大学 AAAI 之春研讨会上做了一个有趣的主题演讲。

当前的社会趋势与人们受教育程度越来越高的普遍看法相反。的确,事实表明,我们生活在这样一个时代,我们可以看到:

  • *均人口中猖獗的算术(即,对数学相关问题的无知,包括非常基本的概念),与年龄、性别和社会阶层无关。举个例子,请看这个案例:“为什么我们在麦当劳买 1/3 磅肉和 1/4 磅肉要花同样的钱?你多收了我们的钱。”
  • 与现实和知识的联系减少,最终导致对事实的无知(因为你可以依靠谷歌!)
  • 人们普遍不相信存在(并且可能存在)一个真实的客观现实
  • 假设问题的答案总是可用的

今天,人们依靠机器获取知识,而当前的引擎不具备将来自许多不同来源的知识整合在一起并得出结论或答案的逻辑。

Photo by Lacie Slezak on Unsplash

例如,埃菲尔铁塔比美国国会大厦高吗?在谷歌上无法完全自动找到答案,因为没有现有的网页明确讨论这一点,尽管答案的各个部分都是可用的。

这是由于机器学习的困难:

  • 专家对结果意见不一的情况
  • 确认偏差的风险
  • 荒谬的答案或中间结论
  • 可用的少量数据
  • 当答案暗示“常识”时
  • 当顶级专家比普通人强很多的时候

对于理解问题和答案,机器学习可以对人类生成的文本(从社交媒体到莎士比亚的情节,如罗密欧与朱丽叶)做一些事情,通过使用不同的有限逻辑:从命题逻辑到完全一阶逻辑。但是,相对于随便阅读文本或观看情节表演或电影的人所能回答的问题而言,人类能够提出和我们能够回答的问题的数量是极其有限的(至今仍然如此)。最重要的是,有一个悬而未决的问题,人工智能很难回答:为什么?

大多数时候,一阶逻辑的计算速度不够快(更不用说二阶或更高阶逻辑了)。

Doug 提出的想法包括将推理中的两个重要成分分开,以处理表达能力和效率之间的权衡:

  • 认识论方面
  • 启发式方面

通过将两者分开,您可以将非常高效的语言用于启发式部分,而将非常强大(和不太高效)的语言用于认识论部分。因此我们在游戏中有两种语言:启发式层次语言(HL)认识论层次语言(EL)

对推理的另一个有趣贡献是语境:语境应该是知识过程中的一等公民,因为知识在不同的语境中可能是不同的。

该系统能够使用溯因推理(或溯因推理)来提出答案中可能的可能性,例如为什么故事中会发生什么。

这与道格和赛克公司的历史有关。早在七十年代,斯坦福的一群朋友就在为人工智能概念而奋斗。他们决定加入逻辑、人工智能和专家系统,并致力于解决 EL-HL 分裂的工作方法和工程解决方案。

这项工作主要是通过教授事实和逻辑规则来教育系统,然后设计推理方法,该项目历时 30 年,预算超过 200 MLN 元,能够建立包含数亿条断言的知识资产。

将机器学习和知识库结合起来的途径是利用它们潜在的协同作用。

Google doodle about Bach’s music, where ML was not combined with KE.

实际上,这包括以下选项:

  • 实现商定的自定义 API
  • 使用知识库作为机器学习系统的大量训练数据的生成器。因为我们知道 80%的事实实际上可以从三重模型中产生,这已经是一笔巨大的财富了。
  • 使用机器学习来生成假设,然后使用知识库来检查不良形式或矛盾(可以使用这种方法的一个例子是改进最*关于巴赫音乐的谷歌涂鸦,其中巴赫风格的一些基本概念化可以避免生成的音乐中的重大错误,这产生了音乐专家的巨大反斜杠)。

但是 AI 和 KB 结合的实际价值真的更广阔。

这一贡献的主要长期破坏性影响之一是使分析能力从相关性转移到因果关系成为可能。这可能会给整个领域带来全新的味道。

Photo by dylan nolte on Unsplash

这个故事的灵感来自于 Cycorp,Inc .的首席执行官兼 AAAI 研究员 Doug Lenat 在斯坦福大学 AAAI 之春研讨会上的一次演讲。

统计建模——实用指南

原文:https://towardsdatascience.com/statistical-modeling-the-full-pragmatic-guide-7aeb56e38b36?source=collection_archive---------14-----------------------

第 2 部分—解释机器学习模型

继续我们关于如何解释机器学习算法和预测的系列文章。

About the importance of explaining predictions.

第 0 部分(可选)— 什么是数据科学和数据科学家
第 1 部分— 可解释性介绍
第 1.5 部分(可选)— 统计学简史(可能对理解本帖有用)
第 2 部分—(本帖)解读高偏倚和低方差模型。线性回归。
第 3 部分——解读低偏差和高方差模型。
第 4 部分——有可能解决偏倚和方差之间的权衡吗?
第 5 部分——可解释性的本地方法。
第 6 部分——可解释性的全局方法。利用沙普利终于打开了黑盒!

在本帖中,我们将关注高偏差和低方差模型的解释,正如我们在上一帖中解释的,这些算法是最容易解释的,因此假设数据中有几个先决条件。让我们选择线性回归来代表这组算法。如果你不知道什么是线性模型,你可能想看看文章统计简史。

该职位的所有代码可在 Kaggle 上获得。

这里的目的不是解释这些线性模型是什么或它们是如何工作的,而是如何解释它们的参数和估计,但简单介绍一下可能会有帮助。线性模型可以是简单回归,如 OLS,可以是常规回归,如拉索和岭,
它们可以是分类模型,如逻辑回归,甚至是时间序列模型,如 ARIMA 过滤器。它们都有一个共同的事实,即它们具有线性参数,也就是说,当我们估计变量的“权重”时,它们对于任何水*都是恒定的。有趣的是,如果神经网络的激活层是线性的(f (x) = x),它也可以是线性模型,这样的单层网络将类似于我们在这里使用的简单线性回归,但效率低得令人难以置信。

Linear models, well Spacious, high bias and low variance and Neural Networks that adapt to any behavior.

让我们创造一个理论世界,在那里我们有兴趣解释各种变量对人们收入的影响。在我们假设的世界里,我们的最低工资是 1000 美元,每受一年教育,月薪*均增加 500 美元。因为我们的世界是随机的(不是确定性的),所以我们有随机性。

ScatterPlot Salary x Education

运行回归模型时,我们得到产生最小可能误差的直线:yhat = x * 496 + 1084。也就是说,该模型能够“理解”我们创建的现实,并估计斜率系数约为 496(非常接*创建的 500 美元),截距约为 1084,这种情况下的解释非常简单。他确定了最低工资(当教育等于零时)和当一年的教育改变人们的收入时,500 美元。

Best fit line (which produces the smallest error).

但是这个案例很简单,离现实很远。顺便说一下,这种情况非常类似于高尔顿在十九世纪创建的模型,相关系数' R '与 R 相同(只是*方)。在现实世界中,我们有许多解释工资的变量,所以让我们在这个模型中插入更多的变量。

在我们的“世界 v2”中,我们将有以下更像现实的行为:

*工资由以下三个部分解释:

  • Grit =范围从 0 到 16 的随机变量。
    -教育=从 0 到 16 的随机变量+努力的一部分,因为努力影响你自己受教育的程度。
    -实验=从 0 到 25 的随机变量。*

=毅力* * 200 +经验* 200 + 学历 * 300 +随机部分*

查看变量之间这些关系的一种方法是通过热图中的关联图:

HeatMap with correlations between variables

看第一列,我们会认为最重要的变量是毅力/爪,因为它与工资的相关性最高,我们会说经验和教育有几乎相等的影响。

显示变量之间行为的另一种方式是通过图表,这是我更喜欢的方式,但仍然不能普及,其中每个节点都是一个变量,边的颜色强度是它们相关性的“强度”:

Alternative way to represent the correlations between the variables, developed by the author.

我们可以更清楚地看到,工资是中心变量,教育和爪是相互关联的,所以通过估计爪和工资的相关性,我们可能捕捉到了教育的一部分效果,高估了爪的效果,低估了爪的效果。教育。我们说这种相关性被“污染”了。
如何解决?

偏相关

解释线性回归的一大诀窍是理解偏相关是如何工作的。如果你深刻理解这一点,那么开始做另一篇文章主题的因果分析就成功了一半。要做到这一点,让我们用维恩图创建一种“统计语言”,如下所示:

  • 每个圆圈代表一个变量。
  • 圆圈的大小代表这个变量的方差;
  • 圆圈之间的交点代表这些变量的协方差。我们可以解释为相关性而不失一般性。

Venn diagram representing Variance and Covariance.

我们如何解读这种表述?基本上,工资有一个方差,可以用教育和毅力来解释,但由于教育和毅力是相关的,它们可以解释相同的方差,即有重复计算。当我们使用这种偏相关时,基本上我们正在做的是扔掉这种重复计算,只捕捉纯相关性,它与任何其他模型变量都不相关。在这种情况下,我们将使用由 Grit 和 Educ 解释的数字 100,我们将只留下 200 (Grit -> $)和 300 (Educ -> $)。这正是线性回归为我们做的:

Each column is a model that has been run and each row is a variable. Values ​​are estimates for the effect of variables.

让我们播放它。当在没有教育变量或没有砂砾变量的情况下回归时,我们注意到它们捕捉到了彼此的影响,即,为了预测工资,移除变量不会干扰太多,因为它们是相关的,部分影响被剩余的变量捕捉到了。为了解释这些影响,理想情况下,我们把所有重要的变量都放进去,否则估计的影响会被污染。在 Exp 变量的情况下(它是在与其他变量不相关的情况下构建的),部分相关性与传统相关性非常相似,因为没有联合效应。使用文氏图:

Venn diagram showing orthogonal / independent variables.

统计建模及其解释。

正如我们多次重复的,这个模型有许多先决条件,所以让我们开始分解它们并解释它们。

非线性行为。

最强有力的假设之一是,变量(X)对目标(y)的回报必须是常数,因此线性模型的名称(因为估计的参数是线性的)。但是如果行为不完全是线性的呢?我们必须求助于其他模式吗?简单的回答是否定的,
我们可以通过对问题建模来理解非线性。让我们来看例子:

让我们想象一下,相对于工资,教育回报率不再稳定,而是实际上达到峰值,然后开始下降。也就是说,它不仅不会永远增加,而且增加的速度会降低,直到发生逆转。这是一个非常容易接受的假设,可以用真实数据观察到。在估计这个新现实的线性模型时,我们有一个相当奇怪的结果:

Adjustment of a linear regression by a quadratic behavior. Don’t mind the numbers, it’s simulated data.

看起来不太合适,对吧?这在问题的本质中是很常见的,我们的影响会随着变量的变化而变强或变弱,我们处理它的方式是通过两次添加教育变量,一个线性(原始)部分和一个二次部分,因此线性模型可以理解非线性行为:

Linear Regression Adapting to Nonlinear Behaviors

由于模型继续估计偏相关,为了解释这些变量,我们需要同时考虑教育的两个部分,估计的线性和二次部分是:648 和-32,而实际数据是 600 和-30。例如,我们可以通过取曲线的最大值来计算使工资最大化的教育程度。

弹性模型。

另一个非常常见的非线性效应的例子是,变量不是具有恒定的名义效应,而是具有恒定的百分比效应。一个例子是估计人数(X)对面包店产量(y)的影响。如果只有一个员工,生产率就很高。当你多雇一个人,产量就会增加很多,他们可以轮流工作,而一个人满足另一个人补充库存,等等。随着我们增加更多的员工,生产率在下降,增加第十个员工不再那么有效率,而是增加了产量。我们称之为边际递减效应,对此问题建模的一种方法是应用自然对数(ln)。当你有 1 个员工时,多一个员工是 100%的增长,而当你有 10 个员工时,多一个员工只是 10%的增长。
除了纠正这种百分比增加行为之外,日志记录还有助于减轻左侧不对称分布、异常值的影响,并且通常会将这种分布转换为与正态分布非常相似的分布。

通过对数变换后,我们如何解读这个新变量?基本上是百分比变化而不是名义变化。让我们来看例子:

Histograms of the annual salary variable. No logging in the left corner and logging in the right side. The interpretation must be a percentage interpretation!

当我们对 1990 年的工资进行回归时,会发生两件事。首先是 R2 从 0.065 增加到 0.125(翻了一倍!),意味着我们的建模走上了正轨。但是当我们看教育的估计值时,我们看到它从 300 到 0.0062,如何解释它呢?百分比变化!新的解释是,多受一年教育而不是增加 300 美元的工资,这个模型增加了 0.0062%,我们称之为对数水*,估计值变成了半弹性。如果我们记录这两个变量,这将是一个逻辑模型。记录和解释将是:对于教育 1%的增长,增加变量 y 的估计百分比值。我们称之为效应弹性(等于我们在定价团队中经常看到的价格弹性)。

分类变量

我们已经从其他模型中知道了如何添加分类变量,我们需要将其建模为虚拟变量(0 或 1)并用这个新变量进行回归,让我们在我们的工资模型中创建一个这样的变量,它将代表该个人是否出生在巴西,因为我们的制度不是最好的,对于具有相同经历、教育和努力的同一个人来说,在巴西生活的“仇恨”是(在我们的理论世界中)1000 美元。

ScatterPlot representing the actual (blue) points and the red predicted values. The differences between the lines is caused by the dummy that affects only the intercept and not the inclines.

请注意,预测值是*行的,这表明线的斜率完全由教育给出,出生或不出生在巴西只是将整个曲线下移。

假人超级强大,可以帮助控制许多复杂的效果,包括时间,但这是一个因果张贴的问题。

变量之间的相互作用。

最后,我们需要纠正一个相当复杂的自然行为,即变量之间的相互作用。这方面的一个例子是前一种情况,不管其他变量如何,教育回报率是一样的吗?在巴西生活与否应该不会影响这次回归吧?如果是这样的话,这个模型,因为它非常简单,它不理解这个行为,我们需要再次建模,以便模型能够理解。

在我们的示例中,变量“巴西”将与变量 Education 交互。为了让模型理解这种行为,我们只需要创建第三个变量,它是两个变量的乘积。请注意,我们乘以 1 和 0,因此当观察值等于 1 时,新变量将具有重复教育列,否则将为零,回归结果如下:

Inclination of the return of education interacting with the variable “Brazil”, making the inclination different for each situation.

允许模型与两个变量相互作用允许教育的回报因情况而异。现在的解读将是,虽然出生在巴西有负面影响(保持一切不变),但巴西的教育回报比巴西以外更高(线更倾斜)。也就是说,我有一个估计的教育倾向(例如 300),一个估计的巴西出生率(例如-1000),一个估计的巴西人的教育价值(例如 50),当我们想要分析巴西的教育回报时,我们需要加上 300(来自每个人)+作为巴西人的回报 50。

所有代码和图形都可以在 Kaggle 中找到。

帖子系列:

  • [统计简史](http://A Brief History of Statistics);
  • 为数据科学家推荐书籍、课程和电影。
  • 数据科学 的范围是什么;
  • 解释机器学习。

LinkedIn GitHub

线性回归的统计概述(Python 中的示例)

原文:https://towardsdatascience.com/statistical-overview-of-linear-regression-examples-in-python-80a38680e053?source=collection_archive---------4-----------------------

在统计学中,我们经常寻找方法来量化现实生活中的因素和反应之间的关系。

也就是说,我们可以把我们想要理解的反应大致分为两种类型:分类反应和连续反应。

对于分类案例,我们正在研究某些因素是如何影响我们在一组选项中做出哪种反应的决定的。

例如,考虑一个关于脑瘤的数据集。在这种情况下,这些因素包括肿瘤的大小和患者的年龄。另一方面,反应变量必须是肿瘤是良性的还是恶性的。

这些类型的问题通常被称为分类问题,实际上可以通过一种称为逻辑回归的特殊类型的回归来处理。

然而,对于连续的情况,我们正在观察我们的因素在多大程度上影响我们的反应变量的可测量的变化。

在我们的特定示例中,我们将查看广泛使用的波士顿住房数据集,该数据集可以在 scikit-learn 库中找到

虽然该数据集通常用于预测性多元回归模型,但我们将专注于统计处理,以了解房间大小增加等特征如何影响住房价值。

模型符号和假设

线性回归模型表示如下:

其中:

为了“拟合”线性回归模型,我们建立关于随机误差的某些假设,一旦这些假设适用,这些假设将确保我们对实际现象有一个很好的*似。

这些假设如下:

探索性研究

为了这个模型的目的,我们将把 MEDV 作为响应变量。MEDV 是以 1000 美元为单位的自有住房的中值

在这里,我们将会看到在 y 轴上有 MEDV 的那一行。也就是说,我们将查看房屋价值与数据集中所有其他要素之间关系的散点图。

你可以在这里找到所有数据集名称的完整描述:
https://www . cs . Toronto . edu/~ delve/data/Boston/Boston detail . html

All Features vs the Median Value of Owner Occupied Homes

一个特别突出的线性关系是每个住宅的*均房间数(RM)。

让我们仔细看看:

简单线性回归

最简单的线性回归形式只包含截距和单因子项。

在这种情况下,我们将使用最小二乘法拟合模型。

最小二乘法

当我们说“适合”模型时,我们的意思是找到最适合给定数据的因子项的估计值。在回归的情况下,这意味着我们找到最小化回归线和每个观察数据点之间距离的距离。

也就是说,我们将*方误差降至最低,数学上表示为:

其中 sigma 是数据集中所有行的总和。

下面是我们如何使用 python 库 statsmodel 拟合模型。

我们首先导入库:

import statsmodels.api as sm

我们现在准备安装:

请注意,我们必须添加一列称为“截距”的数字。

这是因为我们可以使用线性代数重写我们的模型,以便:

所以 1 列是 X 矩阵的第一列,所以当我们乘以因子系数向量时,我们得到了每个方程的截距值。

这种形式用于扩展多元回归的情况,但我们不会在本文中广泛涉及这种数学。

适合摘要

slr_results.summary()

这些是因子系数的估计值。考虑截距术语的解释通常是没有意义的。例如,在我们的例子中,截距项与房子有 0 个房间的情况有关…房子没有房间是没有意义的。

另一方面,RM 系数有很多含义。它表明,每增加一个房间,业主自住房屋的中值就会增加 9102 美元。

P > |t|: 这是一个双尾假设检验,其中零假设是 RM 对 MEDV 没有影响。由于 p 值很低,接*于零,因此有强有力的统计证据来否定 RM 对 MEDV 没有影响的说法

R *方:这是模型解释的方差,通常被认为是对模型拟合程度的衡量。然而,这个因素可以被抛弃,因为它可以通过增加因素的数量而被人为地夸大,即使这些因素并不重要。因此,我们还必须考虑调整的 R *方,它调整计算以适应因子的数量。然而,在简单的线性回归中,这两者是相同的。

How our line fit’s the data

多元线性回归:

当我们加入其他因素时会发生什么?

既然我们没什么别的事可做,为什么不干脆把它们都扔了呢
(免责声明:也许你不应该在家里尝试…..尤其是如果你有成千上万的功能…)

  • 除了 CHAS:因为它是二进制的*

好吧…我为那张汇总表有多长而道歉:/

请注意,R *方和调整后的 R *方显著增加。然而,也请注意,现在有一个强有力的统计证据支持它不影响 MEDV 的说法。

这一特点是年龄,我们将删除它从我们的模型和改装。

我们将继续修剪和比较,直到我们有所有的统计显著特征。

Red: Dropped, Black: R-squared, Green: Adjusted R-squared

正如我们所看到的,列 Age 和 Indus 对模型的拟合没有贡献,最好不要考虑它们。

Prob(F-statistic): 是与整体模型的显著性检验相关联的 p 值。在这种情况下,零假设是模型总体上不显著。由于我们的值远低于 0.01,我们可以拒绝零假设,而支持另一种选择,即该模型具有统计学意义。

**注意 * *

对于多元线性回归,β系数的解释略有不同。

例如,RM coef 建议,对于每一个额外的房间,我们可以预期自有住房的中值增加 3485 美元,所有其他因素保持不变。还要注意,系数的实际值也发生了变化。

模型诊断

此时,您可能想知道我们可以做些什么来提高模型的拟合度。由于 adj. R-squared 为 0.730,当然还有改进的空间。

我们可以考虑的一件事是,我们可以向数据集添加哪些对我们的模型可能很重要的新功能。

除此之外,我们还需要进行测试,看看首先应用线性回归实际上是否合理。

为此,我们寻找剩余图。

这里的好处是残差是对模型中随机误差的一个很好的估计。也就是说,我们将能够绘制残差与特征(或预测值)的关系图,以了解残差的分布情况。

我们预计,如果模型假设成立,我们将看到一个完全分散的图,点的范围在某个恒定值之间。这意味着残差是独立的,正态分布的,具有零均值和恒定方差。

standard residual plot

然而,在我们的单反案例中,我们有 RM

这里我们可以看到,有一些非线性模式的迹象,因为残差图似乎在底部是弯曲的。

这违反了我们的模型假设,我们假设模型具有恒定的方差。

事实上,在这种情况下,方差似乎是根据其他函数而变化的。我们将使用 box-cox 方法来处理这个问题。

我们可以通过创建一个 QQ 图来进一步检验我们的正态性假设。对于正态分布,QQ 图将趋向于直线。

但是请注意,这条线明显是倾斜的。

博克斯-考克斯方法

这是一个过程,通过这个过程,我们可以找到最合适的变换的最大似然估计,我们应该应用于响应值,以便我们的数据能够具有恒定的方差。

使用 scipy.stats 实现后,我们得到的 lambda 值为 0.45,我们可以将它用作 0.5,因为它不会在拟合方面产生巨大的差异,但它会使我们的答案更具可解释性。

import scipy.stats as stats
df.RM2,fitted_lambda = stats.boxcox(df.RM)

下面你会发现一个常见的 lambda 值及其建议的响应转换表。

Common Lambda Values — taken from statistics how-to

此后,我们相应地改变我们的回应:

df.MEDV2 = np.sqrt(df.MEDV)

然后我们将模型拟合到 MEDV2,它是 MEDV 的*方根。

在特征数量相同的情况下,我们的 R *方值和调整后的 R *方值都上升了不少。有点酷吧?

此外,我们的剩余地块也有一些改进:

此外,我们还可以尝试将我们的转换应用于特征变量的每个

X = df[['intercept','CRIM', 'ZN','NOX', 'RM','DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT']]
X2 = X.apply(np.sqrt)

然后,我们拟合由 X2 作为我们的特征矩阵和 MEDV2 作为我们的响应变量组成的模型。

在这里,我们看到在相同数量的特性下,这些值有了更大的提高。

我们最后的剩余图看起来像这样:

所以很明显还有改进的空间,但是我们确实取得了一些进步。

一些附加说明

回归模型的统计理解还有更多的部分。例如,我们有可能得出围绕每个节拍系数甚至围绕我们的预测值的置信区间。

此外,关于 CHAS,由于它的{1,0}编码,包含 chase 也没问题。对于更多的选项,除非选项有自然的顺序,否则很难或不可能解释贝塔系数。当我们用 chas 拟合最终模型时,调整后的 R *方为 0.794。在这种情况下,对β系数 0.077 的解释是:

如果房屋区域毗邻查尔斯河,那么在所有其他因素保持不变的情况下,业主自住房屋的中值将比未毗邻查尔斯河的房屋高出 77 美元。

结论

我希望我能够让大家明白回归不仅仅是基于某些特征进行预测。事实上,有一个回归分析的世界致力于使用这些技术来更深入地了解我们周围现实世界中的变量。

用于比较机器学习和基准性能的统计测试

原文:https://towardsdatascience.com/statistical-tests-for-comparing-machine-learning-and-baseline-performance-4dfc9402e46f?source=collection_archive---------5-----------------------

当将机器学习方法与当前解决方案进行比较时,我希望了解任何观察到的差异是否具有统计显著性;这不太可能仅仅是由于数据中的偶然因素或噪声。

评估统计显著性的适当测试取决于您的机器学习模型预测的内容、数据的分布以及您是否正在比较对主题的预测。这篇文章强调了常见的测试以及它们适用的地方。

零假设统计检验

零假设统计检验用于比较两个数据样本,并计算在更广泛的人群中观察到的数学特征的感知差异(例如,不同的*均值)的统计置信度。

尽管对零假设显著性检验有持续的批评,但它仍然是最常用的验证技术。

虚假设

零假设是两个数据样本的分布之间不存在差异的陈述;任何差异都是由于噪音或偶然因素造成的。

就机器学习而言,我们的零假设是性能指标相等,观察到的任何小的增益或损失在统计上不显著。

p 值

测试表明我们是否应该拒绝,或者拒绝不存在差异的无效假设。下面讨论的统计检验倾向于提供检验统计量和 p 值。

如果 p 值低于给定的阈值(通常为 0.05),我们可以拒绝零假设,并推断差异具有统计学意义。

商务口译

如果您正在将您的机器学习解决方案与当前基线进行比较,并且您看到了性能的提高,那么这一显著提高是一个好消息!

类似地,如果您使用这些技术来测试某个特定的模型是否比另一个模型表现得更好,这可以指导您决定继续使用哪个模型。

如果您不能拒绝零假设(p 值大于或等于阈值),则两个数据集之间的任何观察到的效应或差异都不具有统计显著性。如果您正在尝试自动执行一项任务,匹配当前的手动性能就足够了,这可能是一个积极的消息。但是,如果成功的标准是超越当前场景,没有统计上的显著性差异意味着您不太可能看到将该模型用于生产的好处。

假设

数据分布

当对回归模型使用假设检验时,区分应该使用参数检验还是非参数检验是很重要的。参数检验是首选,因为它们通常比非参数检验具有更大的统计功效;这意味着他们更有可能检测到统计上的显著影响,如果存在的话。然而,这些测试假设数据是正态分布的;如果这个假设不成立,就必须使用非参数检验。

If you plot error values, it is likely they will be of a non-normal distribution

当您比较误差值时,它们很可能是向左倾斜的:大多数误差都很小,随着误差值的增加,频率会降低。如果你要绘制你的数据,你也许可以直观地解释它,但是也有正态性检验,你可以用它来进行数学上的确认。

成对或不成对观察值

如果为每个模型从相同的受试者收集数据,这被称为“配对”。在机器学习中,这意味着基线和训练模型的测试数据是相同的。

从两个独立组收集的数据被称为“不成对的”。这在科学研究或 A/B 测试中很常见,当你比较一个对照组和一个治疗组时。

适当的统计测试

回归

如果您的机器学习模型正在预测数值,则误差度量往往是以下之一:

  • 均方误差
  • *均绝对误差
  • *均绝对百分比误差(MAPE)
  • 加权*均绝对百分比误差

当使用假设检验来比较*均误差时,您看到的是误差来自同一分布的可能性;如果可能性足够低,则两个*均误差值之间的差异具有统计学意义。

对于正态分布的数据,两种合适的测试要么是学生 t 检验要么是韦尔奇 t 检验。它们都检验两个总体具有相同的均值,但 Welch 的 t 检验更可靠,因为方差或样本量存在差异。根据观察值是成对的还是不成对的,有两种实现方式。

两个非参数检验是曼-惠特尼 U 检验威尔科克森符号秩检验,这再次取决于观察值是否成对。

分类

如果您的机器学习模型预测一个实例属于哪个类,则误差度量往往是以下之一:

  • 准确(性)
  • 精确
  • 回忆
  • f1-分数

虽然您的企业必须决定应该优先考虑哪个指标,但是分类模型最常用的技术只是评估错误的比例是否有显著差异。如果您明确希望测试精确度或 F1 分数的统计显著性,则需要进一步的研究。

分类模型可以是二元的(例如搅动的或未搅动的),也可以是多类的(例如体育、政治或科学)。对于二元分类模型比较,合适的测试是麦克内马测试,而对于多类,合适的测试是斯图亚特-麦克斯韦测试

算法比较和超参数调整

当评估一个模型相对于基线(或者另一个模型)的结果时,使用上述指标。

当评估不同的算法或超参数时,通常使用 k 倍交叉验证。这允许您训练和测试 k 模型,并收集它们的评估指标,使用它们的*均值作为算法性能的指示。如果对两种算法都这样做,可以使用统计测试来比较这两种方法。

例如,如果要比较逻辑回归模型和随机森林模型。你可以把数据分成 10 份,训练 10 个逻辑回归模型和 10 个随机森林模型。这两个模型将分别具有 10 个相应的性能度量值(例如准确性),然后可以将这些值传递给统计测试,以查看任何观察到的差异是否具有统计显著性。

随着 k 重交叉验证对数据进行重新采样,训练集之间存在重叠。这意味着这些值不是独立的,这通常是统计假设检验的一个假设。因此,两种最常见的技术是使用修改的 t 检验的 5x2 交叉验证麦克内马检验

统计学家证明统计很无聊

原文:https://towardsdatascience.com/statistician-proves-that-statistics-are-boring-4fc22c95031b?source=collection_archive---------0-----------------------

用细致入微的词汇回归基础

我要给你看一个逻辑证明,统计学很无聊...为了帮助你们理解像我这样的统计学家进行的所有那些花哨计算的点。作为一个额外的奖励,这几乎是你在大多数 STAT101 课程的第一天所学到的,所以它也是对统计数据好奇的间谍任务。让我们从沉湎于一些本地术语开始。

This statistician is about to prove that statistics are boring. Pulling faces all the while — I’m still learning how to use my face. Humaning is hard. Come pull a face back at me here if you like.

人口

当典型的人类想到“人口”这个词时,他们会想到什么?人,对吧?不是一两个,而是很多。所有的人!在我们的学科,更像是所有的事情。一个群体可以是人、像素、南瓜、神奇宝贝,或者任何你感兴趣的东西。

群体是我们感兴趣的所有项目的集合。

停下来。花点时间。你现在看到的是处于整个追求核心的法律合同。

事情是这样的:通过写下对你的人口的描述,你同意只有人口,整个人口,除了人口之外没有任何东西对你的决定感兴趣。通过进一步阅读,您接受这些条款和条件。(正如你所料,这篇博客详细描述了大量的人口。在这里找到更多的沉思。)

如果列出你感兴趣的人群听起来令人生畏,请记住,选择你感兴趣的内容是由你自己决定的。没有不正确的选择,只要具体彻底。我会说得很透彻,我会给你一千个单词:下图中的树木是我们对这篇文章感兴趣的人群。

If my population is all trees in this forest, they represent everything I care about for this decision. I’m getting pretty excited about these trees. Actually, to be quite honest with you, the excitement is real: I’m irrationally fond of this graphic because I’ve been using it in my lectures for many years. Allow me my misguided nostalgia just this once… of course trees floating on some planes in space make perfect sense.

因为这是我的种群,我应该记住我没有理由放弃我的分析,因为我相信我已经了解了其他森林中的树木。我的发现充其量只能应用于这些树。在最坏的情况下,嗯…我们只能说在一个数据科学家的一生中可能会有一些塑造性格的时刻。

这里有你看不见的树吗?对你来说死了,没意思。它不是我们人口的一部分。随便挑一棵树?对你也一样。一样无聊。这不是你的全部人口。只有他们所有人(一起!)对我们来说很有趣。这是法律合同上说的

样品

样本是总体中任何项目的集合。

样本是你拥有的数据,总体是你希望拥有的数据。

Either of these orange collections of trees is a sample. I hope you have some intuition as to which one is the better one here. In a future article, I’ll tell you all about what makes a sample a good sample. I’m going to use the one that irritates professionals for the rest of this example to prove a point.

观察

观察值是对样本中一个单一项目的测量。

The measurement we took from this blue-labeled tree is an observation. Sticklers for precise language will notice that a “sample” is a collective noun for a group of observations. Technically, “samples” as a plural does not mean “observations”, it means “multiple collections of observations.”

统计的

啊哈!统计!这肯定是重要的事情,因为我们以这些事情命名了我们的学科!

统计是将样本数据混合在一起的任何方式。

那么…什么是统计?这只是将我们现有的数据进行混合的一种方式。多么令人失望!提示悲伤的长号噪音。事实证明,统计学和统计学学科是两码事,在这里阅读全部相关内容。

Example of a statistic: if we’re interested in tree heights, you wouldn’t be surprised to see a statistic like the average height of all those orange-labeled trees. If you feel like it, though, you could also take those sample tree heights, find the top three, add them up, take the log, add to it the square root of the difference of the bottom two tree heights, send the whole unholy thing through a meat grinder… and out pops another statistic! Maybe useful, maybe not so useful, but also a statistic.

证明统计数据很无聊

假设我们感兴趣的是*均树高,在这个例子中恰好是 22.5 米。这个数字对我们来说有意思吗?

我们再回头参考一下我们签约的法律合同:只有人口才是有趣的。这个样本是人群吗?没有。因此,我们对此不感兴趣。我们从一些无聊的树上取了一些无聊的测量值,然后我们把这些无聊的测量值搅成糊状……这个过程产生的结果也是无聊的。

所以我向你们证明了你们心里一直都知道的:统计很无聊!神盾局。

用词不当!

统计学家疯了吗?为什么我们要用一些无聊的数字来命名我们的学科?其实是用词不当。

我们这些天使用这些术语的方式是,分析是关于计算统计数据的学科,但统计是关于超越那些数据混乱的——一个伊卡洛斯式的飞跃进入未知(如果你不小心的话,预计会有一个大的冲击)。在此了解更多关于数据科学的子学科。

我们学科的真实名称(从你可以用来召唤巫师的真实名称的意义上来说)会更冗长:统计的消化… 但是这听起来有点粗俗,所以我们把它缩短成一些通俗易懂的东西。(由于我们脾气暴躁的名声,我们需要尽可能的*易*人。)

让我解释一下。

参数

进入我们节目的明星: 参数 。这东西太花哨太闪亮了。演出结束后,它会收到一束鲜花,通常还会收到自己的希腊字母(通常是 θ )。您可以将参数视为统计数据的总体版本—参数是将所有感兴趣的数据组合在一起的任何方式,我们通常无法访问 IRL。

一个参数为您汇总了总体。

我们一致认为,我们对这些树深感兴奋,现在我将为你总结你所关心的一切?安静点,你的小心脏!参数让你如此激动!

Parameter value revealed: the true average height of all the trees just so happens to be 21.1 meters.

想象一下,这是一个星期六的早晨,你正站在森林中的一块空地上。你还没有测量过任何树木,但是你真的很想知道这个数字——这是你梦寐以求的一切。(通过法律合同,即。一旦我们写完这篇文章,你就可以回到正常人的生活中,对生活有其他的兴趣。)

要知道这个参数需要什么?

你必须准确无误地测量所有的树!一旦你做到了,你还有什么不确定的吗?不,你有所有的信息。你可以通过使用分析来结束——继续计算*均值。那么统计量 就是 这个参数,因为你的样本 就是 这个总体。你处理的是纯粹的 事实 。由于拥有完善和完整的数据,不需要复杂的计算。

我碰巧住在纽约市——是我自己选择的!离树越远越好。因此,当我面临“完美地测量所有这些树”这样令人生畏的任务时,懒惰就开始了我很想知道这个参数,但是我开始思考,“我真的需要完全了解它吗?或者我可以只测量几棵树吗?也许我可以只看一眼全貌,就能得出一个对政府工作足够好的参数的最佳猜测。

当我以这种方式思考时,我是在以统计学的方式思考!我永远不会知道答案。我的懒惰意味着我不得不放弃获取事实或确定性,但希望我最终会得到一些仍然对做决定有合理帮助的东西。我仍然可以把它变成一个合理的行动。就是统计学的全部内容。

Speaking of measuring trees perfectly, this photo on Reddit made me laugh. The caption was: “My brother wanted to measure the trees in his yard. This is how did he did it.”

无中生有?

你们中的一些人希望我会说,“有了 这个 的神奇公式,你就能把不确定性变成确定性!”没有,当然没有。没有无中生有的魔法。

当我们没有事实时,我们所能希望的就是结合数据和假设来做出合理的决定。

假设

一个假设是关于宇宙可能看起来如何的描述,但它不一定是真的。我们将弄清楚我们的样本是否让我们的假设看起来荒谬,以确定我们是否应该改变我们的想法,但这超出了这篇博文的范围——在这里继续讨论。

Here I am, uttering some uninformed garbage like “The true average height of all the trees is less than 20 meters.” That’s a hypothesis. You know the truth (I’m wrong!) because you’re omniscient in this example …but I don’t know anything. My statement is a perfectly valid hypothesis, describing how reality might potentially look. I’ll see how I feel about it after I get some data.

估计和估算者

如果我们知道参数,我们现在就能回家了。我们寻找的是事实,但不幸的是事实并不总是存在的。由于我们无法计算参数,我们只能使用统计数据对其进行最佳猜测。

估计只是一个最好的猜测的花哨词。

估计只是一个关于参数真实值的 最佳猜测(估计命令)的花哨词语。它是你猜测的值,而估计值是你用来得出那个数字的公式。

让我告诉你,你已经很擅长统计估计了。准备好了吗?

让我们假设你只知道其中一棵树有 23 米高。你能告诉我你对所有树的真实*均高度的估计吗?

23m?是啊,我也是!

如果这是我们仅有的信息,我们不得不猜测 2300 万——如果我们猜测其他任何东西,我们只是在编造。我们只知道 23m,所以只能猜 23m。为了得到其他的东西,我们不得不加入更多的信息(在这个例子中我们没有)或者我们不得不做出假设…在这一点上,我们再次处理事实之外的东西。

好吧,让我们试试另一个!假设我们有一个样本,我们只知道它的*均高度是 22.5 米。你现在最大的猜测是什么?

22.5 米?哇!你太擅长这个了!你甚至不需要一门课程!

这里是几个教科书章节的统计数据的妙处,包括矩估计法最大似然估计法以及所有它们的表亲:结果证明彩虹尽头的答案就是你刚刚直观得出的答案!在现实生活中,你遇到的 99%以上的情况下,只要把你的样本当作你的总体来对待,不管里面有什么,你就能得到最好的猜测。你不需要任何特别的课程。哒哒,我们完了!

总是需要统计是骗人的;你不知道。如果你只是试图做出最好的猜测来获得的灵感,分析是你的最佳选择。不要理会那些 p 值,你不需要不必要的压力。

相反,你可以选择遵循这些原则:更多(相关)数据更好,你的直觉很适合做出最佳猜测,但不知道这些猜测有多好……所以保持谦逊。

然而,不要认为我在抨击我的纪律。十多年来,我一直致力于研究统计数据,我喜欢认为自己没有完全疯掉。

当采取统计方法有用时,它的 非常 有用。

那么你什么时候真正需要它呢?它什么时候能阻止你伤害自己?看我的 “统计学有什么意义?” 找出…

Learn more about the difference between the subdisciplines in data science here.

感谢阅读!人工智能课程怎么样?

如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:

Enjoy the entire course playlist here: bit.ly/machinefriend

喜欢作者?与凯西·科兹尔科夫联系

让我们做朋友吧!你可以在 Twitter 、 YouTube 、 Substack 和 LinkedIn 上找到我。有兴趣让我在你的活动上发言吗?用这个表格联系。

R *方解释| R *方线性回归

原文:https://towardsdatascience.com/statistics-for-machine-learning-r-squared-explained-425ddfebf667?source=collection_archive---------3-----------------------

Photo by Roman Mager on Unsplash

机器学习涉及大量的统计数据。在前面的文章中,我们将看看 R *方的概念,它在特性选择中很有用。

相关性(也称为“R”)是一个介于 1 和-1 之间的数字,其中值+1 意味着 x 的增加会导致 y 的增加,-1 意味着 x 的增加会导致 y 的减少,0 意味着 x 和 y 之间没有任何关系。与相关性一样,R 会告诉您两个事物的相关程度。然而,我们倾向于使用 R,因为它更容易解释。r 是由两个变量之间的关系解释的变化百分比(即从 0 到 1 变化)。

后者听起来相当复杂,所以让我们看一个例子。假设我们决定绘制工资和工作经验之间的关系。在上图中,每个数据点代表一个个体。

我们可以通过将样本中所有个体的总和除以样本中个体的总数来计算*均值。

整个数据集的方差等于每个数据点之间的距离和均方值之和。差值的*方使得低于*均值的点不会被高于*均值的点抵消。

var(mean) = sum(pi - mean)²

现在说,我们找了同样的人,但是这一次,我们决定画出他们的工资和身高之间的关系。

注意,不管我们把什么作为自变量,*均工资都保持不变。换句话说,我们可以用人民生活的其他方面作为 x 但工资会保持不变。

假设我们使用线性回归找到了最佳拟合线。

R 的值可以表示为:

**R² = (var(mean) - var(line)) / var(mean)**

其中 var(mean) 是相对于*均值的方差,而 var(line) 是相对于直线的方差。

就像我们之前提到的,方差可以通过计算个人工资和均方差之间的差来计算。

使用相同的逻辑,我们可以确定橙色线周围的变化。

假设我们获得了线的方差和均值的下列值。

我们可以使用之前描述的公式计算 R

R 值意味着线周围的变化比*均值小 96%。换句话说,工资和工作年限的关系解释了 96%的变异。换句话说,工作年限是薪水的一个很好的预测指标,因为当工作年限增加时,薪水也会增加,反之亦然。

密码

让我们看看如何用 R 来评估一个线性回归模型。首先,导入以下库。

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
from sklearn.metrics import r2_score
from sklearn.linear_model import LinearRegression
sns.set()

我们将使用以下数据集。如果您想跟进,请将其内容复制到 csv 文件中。

YearsExperience,Salary
1.1,39343.00
1.3,46205.00
1.5,37731.00
2.0,43525.00
2.2,39891.00
2.9,56642.00
3.0,60150.00
3.2,54445.00
3.2,64445.00
3.7,57189.00
3.9,63218.00
4.0,55794.00
4.0,56957.00
4.1,57081.00
4.5,61111.00
4.9,67938.00
5.1,66029.00
5.3,83088.00
5.9,81363.00
6.0,93940.00
6.8,91738.00
7.1,98273.00
7.9,101302.00
8.2,113812.00
8.7,109431.00
9.0,105582.00
9.5,116969.00
9.6,112635.00
10.3,122391.00
10.5,121872.00

我们使用 pandas 将数据加载到我们的程序中,并使用 matplotlib 绘制它。

df = pd.read_csv('data.csv')plt.scatter(df['YearsExperience'], df['Salary'])

接下来,我们对工资数据训练一个线性回归模型。

X = np.array(df['YearsExperience']).reshape(-1, 1)y = df['Salary']rf = LinearRegression()rf.fit(X, y)y_pred = rf.predict(X)

我们可以通过运行下面几行来查看模型生成的最佳拟合线。

plt.scatter(df['YearsExperience'], df['Salary'])
plt.plot(X, y_pred, color='red')

然后,我们用上一节讨论的公式计算 R。

def r2_score_from_scratch(ys_orig, ys_line):y_mean_line = [ys_orig.mean() for y in ys_orig]squared_error_regr = squared_error(ys_orig, ys_line)squared_error_y_mean = squared_error(ys_orig, y_mean_line)return 1 - (squared_error_regr / squared_error_y_mean)def squared_error(ys_orig, ys_line):return sum((ys_line - ys_orig) * (ys_line - ys_orig))r_squared = r2_score_from_scratch(y, y_pred)print(r_squared)

我们可以利用 sklearn r2_score函数,而不是每次都从头开始实现。

r2_score(y, y_pred)

统计学是数据科学的语法—第 1/5 部分

原文:https://towardsdatascience.com/statistics-is-the-grammar-of-data-science-part-1-c306cd02e4db?source=collection_archive---------10-----------------------

统计复习,开启您的数据科学之旅

英国数学家、现代统计学之父卡尔·皮尔逊被认为是这句话的作者:

“统计学是科学的语法”

在这里,我们将重点关注与数据科学
相关的统计数据——看到我在那里做了什么吗?😄

像 Tensorflow 或 scikit-learn 这样的机器学习库对用户隐藏了几乎所有复杂的数学。
这意味着我们不需要成为数学专家,但是对基本原理有一个基本的理解是绝对必要的;这将帮助我们更好地利用这些图书馆。

我正在撰写一个由 5 篇短文组成的系列文章,涵盖以下主题,以启动并随后伴随我们的数据科学之旅:

第 1 部分:数据类型|集中趋势度量|可变性度量第 2 部分:数据分布第 3 部分:位置度量|矩第 4 部分:协方差|相关性

让我们从 1️⃣…部分开始

数据类型

我们不能再简单了:数据分为三类,数据科学家根据这三类选择如何进一步分析和处理数据:

#1。数字数据代表一些可测量的可量化信息,并进一步分为两个子类别:

  • 离散数据,基于整数(如人数)
  • 连续的数据,以十进制为基础(如价格、距离、温度)。

#2。分类数据是用于将数据分类的定性数据(想象一下编程中的枚举)。例如,性别、汽车品牌、居住国等。有时我们可以给类别分配数字,这样它们会更紧凑,但是它们没有任何数学意义。

*#3。序数数据代表离散的和有序的单位,例如冠军联赛排名(第 1、第 2、第 3)、错误优先级(低、关键或表演停止)或酒店评级(1–5 )。

集中趋势的度量

假设我们有一个由 5 个数字组成的数据集:

*{ 6, 3, 100, 3, 13 }*

*均

*均值(用希腊字母 mu— μ表示)是数据集的*均值。为了计算*均值,我们将所有值相加,然后除以值的个数。

*E.g. 6 + 3 + 100 + 3 + 13 = 125 →μ = 125 ÷ 5 = 25*

中位数

中位数是数据集的中间。为了计算中间值,我们对所有值进行排序(按升序或降序),并取中间值。

*E.g. 3, 3, **6**, 13, 100 → 6*

如果有偶数个数据点,那么我们计算落在中间的两个数据点的*均值。

中位数比*均值更不容易受到离群值的影响,因此我们需要考虑数据分布的样子,以选择使用哪一个。

方式

众数是数据集中最常见的值。为了计算模式,我们找到出现频率更高的数字。

*E.g. 3:2, 6:1, 13:1, 100:1 → 3*

模式通常只与离散数值数据相关,与连续数据无关。

差异量数

范围

范围是数据集的最低和最高数字之间的。为了计算范围,我们从最大值中减去最小值。

*E.g. 100 – 3 = 97*

它向我们展示了数据集是如何变化的,也就是说,它是如何分布的,但同样,像均值一样,它对异常值非常敏感。

差异

方差衡量如何展开数据。为了计算方差,我们从*均值中取方差的*均值。

  • #1。求数据点的*均值
*From previous section it is 25*
  • #2。从每个数据点中减去*均值
*6 - 25 = -19
3 - 25 = -22
100 - 25 = 75
3 - 25 = -22
13 - 25 = -12*
  • #3。*方每个结果
*(-19)^2 = 361
(-22)^2 = 484
(75)^2 = 5,625
(-22)^2 = 484
(-12)^2 = 144*
  • #4。求结果的*均值(即求和并除以 n)
*361 + 484 + 5,625 + 484 + 144 = 7,098 →
7,098 ÷ 5 = 1,419.6*

✏️《*方和》
在第 3 步我们之所以使用*方和的区别是双重的:

  • 负面差异与正面差异具有相同的影响,即它们不会相互抵消
  • 它放大了数据集中异常值的影响。

✏️数据完整性
根据数据集的完整性,第 4 步有细微的区别:

  • 对于完全群体,我们除以数据点的数量(n),即第 4 步是正确的,因为在我们的情况下,我们有一个完全群体
  • 对于样本,我们除以数据点数减 1 (n - 1)
*7,098 ÷ 4 = 1774.5*

标准偏差

标准差(用希腊字母 sigma — σ表示)就是方差的*方根

*E.g. σ = SQRT(1,419.6) = 37.68*

它是一种离差的度量,即它偏离*均值多少标准差,正如我们将在下面的文章中看到的,它用于判断哪个数据点是异常值。

*100 was a rather big number in our example, let's see how many standard deviations it is away from the mean:μ = 25
σ = 37.68
100 / 37.68 = 2.65*

感谢阅读!第二部快到了…

我定期在 媒体 上撰写关于技术的&数据——如果你想阅读我未来的帖子,请“关注”我!

统计学是数据科学的语法—第 2/5 部分

原文:https://towardsdatascience.com/statistics-is-the-grammar-of-data-science-part-2-8be5685065b5?source=collection_archive---------8-----------------------

统计复习,开启您的数据科学之旅

这是“统计学是数据科学的语法”系列的第二篇文章,涵盖了各种类型的概率分布以及我们如何绘制它们

修订本

其余文章的书签,便于访问:

文章系列 第 1 部分:数据类型|集中趋势度量|可变性度量
第 2 部分:数据分布🚩
第 3 部分:位置|矩的度量
第 4 部分:协方差|相关性
第 5 部分:条件概率|贝叶斯定理

概率分布函数

概率分布是描述事件或结果的可能性的函数。它们有许多形状,但只有一种大小:分布中的概率总和总是 1。我们现在将根据数据集是连续的还是离散的来深入研究不同类型的分布。

概率密度函数

当我们看到类似下图的图表时,我们认为它显示了给定值发生的概率。然而,这对于连续的数据来说并不完全正确,因为数据点的数量是无限的。因此,特定值发生的概率可能非常小——无限小!

PDF 表示给定的值范围出现的概率。因此有了“密度”这个词!为了形象化概率,我们将数据集绘制成曲线。两点之间曲线下的面积对应于变量落在这两个值之间的概率。

Courtesy: scipy.stats.gennorm

✏️ “臭名昭著”的钟形标准正态分布
为了更好地理解这一点,我们将研究 PDF 的一个特例:

Courtesy: Princeton University

在*均值和一个标准差(1σ)之间,有 34.1%的可能性值落在该范围内。因此,对于给定值,有 68.2%的机会落在-1σ和 1σ之间,这是非常可能的!!!
这意味着在*均值附*有一个集中值,当我们超出一个标准差(+-)时,概率变得越来越小。

概率质量函数(PMF)

当谈到离散数据时,PMF 是给我们一个给定发生的概率的度量。为了直观显示概率,我们将数据集绘制成直方图。

Courtesy: scipy.stats.rv_discrete

连续数据分布

现在我们了解了 PDF 和 PMF 之间的区别,我们将看到最常见的分布类型,从连续分布开始。

#PDF-1:均匀/矩形分布

均匀分布意味着某个值在给定范围内出现的概率为*坦常数,并且与同样可能发生的事件有关。

Courtesy: scipy.stats.uniform

在上面的图中,我们不希望看到低于 0.0 或高于 1.0 的范围之外的任何东西。但是在这个范围内,我们有一条*坦的线,因为这些值中的任何一个出现的概率是恒定的。

#PDF-2:正态/高斯分布

当我们探索 PDF 是什么时,我们看到了一个标准的正态分布。如果我们引入“随机”元素,正态分布看起来不像一条完美的曲线,而更像下面的例子。

Courtesy: scipy.stats.norm

标准正态分布的*均值为零,标准差为一。

#PDF-3: T 分布

T 或 Student 的 T 分布看起来很像正态分布的钟形曲线,但稍短一些,尾部较重。当我们有小样本和/或总体方差未知时,使用它(而不是正态分布)。

Courtesy: scipy.stats.t

#PMF-4:卡方分布

卡方(χ)分布用于评估一系列问题:

  • 数据集是否符合特定的分布
  • 两个总体的分布是否相同
  • 两个事件是否可能是独立的
  • 人群中是否存在不同的变异性。

曲线向右倾斜。

Courtesy: scipy.stats.chi2

#PDF-5:指数概率分布

另一个经常遇到的分布函数是指数概率分布函数,其中事物以指数方式下降。

Courtesy: scipy.stats.expon

大值越来越少,小值越来越多,也就是说,某件事发生的可能性很大,接*于零,但当我们离它越远,它就会急剧下降。

一个日常的例子是顾客一次去超市花的钱:花小额钱的人多,花大额钱的人少。

它被广泛用于模拟事件之间经过的时间以及可靠性,后者处理产品持续的时间量,例如汽车电池持续的时间量(从现在开始),以月为单位。

在我们进入下一部分之前,我想向推荐来自 Sean Owen 的这篇关于 pdf 的特别文章,他在文章中创建了他们的关系图:

Courtesy: Sean Owen — Cloudera

离散数据分布

至于离散概率分布,两个主要类别包括:

#PMF-1:二项式分布

让我们考虑一个有两种可能结果的实验:要么成功要么失败。假设实验重复几次,重复次数彼此独立。结果证明是成功的实验总数是一个随机变量,其分布称为二项式分布。

Courtesy: scipy.stats.binom

#PMF-2:泊松分布

泊松分布给出了在固定时间间隔内发生的事件数量的概率,如果这些事件发生:

  • 具有已知的*均速率和
  • 独立于自上次事件以来的时间。

Courtesy: scipy.stats.poisson

一个经典的例子是呼叫中心接到的电话数量。
—或者—
如果我们知道给定时间段内发生的事情的*均数量,另一个用例可以是预测在给定的未来时间获得另一个值的可能性。例如,我的中型帖子*均每天有 1000 次浏览;我可以使用泊松概率质量函数来估计 1500 次访问的概率。

今天的文章到此结束!我希望这对于理解各种类型的分布是什么以及它们看起来是什么样子是有用的,即使我“隐藏”了所有的数学类型!

感谢阅读!第三部即将上映……

我定期在 媒体 上撰写关于技术&的数据——如果你想阅读我未来的帖子,请“关注”我!

统计学是数据科学的语法—第 3/5 部分

原文:https://towardsdatascience.com/statistics-is-the-grammar-of-data-science-part-3-5-173fdd2e18c3?source=collection_archive---------6-----------------------

统计复习,开启您的数据科学之旅

这是“统计学是数据科学的语法”系列的第 3 篇文章,涵盖了位置的度量(百分位数和四分位数)和

修订本

其余文章的书签,便于访问:

文章系列 第 1 部分:数据类型|集中趋势的度量|可变性的度量
第 2 部分:数据分布
第 3 部分:位置|矩的度量🚩
第四部分:协方差|相关性
第五部分:条件概率|贝叶斯定理

位置的测量

百分位数

百分位数将有序数据分成百分之和百分之。在一个排序的数据集中,一个给定的百分位数是数据百分比比我们现在所处的点少的点。

第 50 百分位几乎是中间值。

例如,想象一下女婴从出生到两岁的成长图表。顺着这条线,我们可以看到 98%的一岁女婴体重不到 11.5 公斤。

Girls’ growth chart. Courtesy: World Health Organisation Child Growth Standards

另一个流行的例子是一个国家的收入分配。第 99 个百分位数是指美国其余 99%的人收入低于这个数字,而 1%的人收入高于这个数字。在下图中的英国,这个数字是 75,000。

UK income distribution. Courtesy: Wikipedia

四分位数

四分位数是特殊的百分位数,它将数据分成个四分位数。第一个四分位数 Q1 与第 25 个百分位数相同,第三个四分位数 Q3 与第 75 个百分位数相同。中位数被称为第二个四分位数,Q2,和第 50 个百分位数。

I 四分位数范围( IQR)

IQR 是一个指示如何分布数据集的中间一半(即中间的 50%)的数字,可以帮助确定异常值。这就是 Q3 和 Q1 的区别。

IQR = Q3 - Q1

IQR. Courtesy: Wikipedia

一般来说,异常值是那些不在 Q1-1.5 倍 IQR 和 Q3 + 1.5 倍 IQR 范围内的数据点。

箱线图

箱线图(也称为箱线图和须线图)说明了:

  • 数据有多集中
  • 极值值离大部分数据有多远。

Elements of a boxplot. Courtesy: Wikimedia

箱形图由一个缩放的水*或垂直和一个矩形组成。

最小值最大值是轴的端点(本例中为-15 和 5)。 Q1 标记盒子的一端,而 Q3 标记蓝色盒子的另一端。

'须条'(显示为紫色)从框的两端延伸至最小和最大数据值。也有箱线图,其中的点标记了异常值(显示为红色)。在这些情况下,胡须不会延伸到最小值和最大值。

正态分布的✏️箱线图
正态分布的箱线图有一个微妙的差别:尽管它们被称为四分位数 1 (Q1)和四分位数 3 (Q1),但它们并不真正代表 25%的数据!他们代表 34.135%,介于两者之间的区域不是 50%,而是 68.27%。

Comparison of a boxplot of a nearly normal distribution (top) and a PDF for a normal distribution (bottom). Courtesy: Wikipedia

朋友圈

瞬间描述了我们分布的本性形状的各个方面。

#1 —一阶矩是数据的均值,描述了分布的位置

#2 —二阶矩是方差,描述了分布的。高值比小值更分散。

#3 —第三个矩是偏斜度,它基本上是一个衡量分布有多不*衡的指标。正的偏斜意味着我们有一个左倾和一个长的右尾巴。这意味着*均值在大部分数据的右边。反之亦然:

Skewness. Courtesy: Wikipedia

#4 —第四个矩是峰度,描述尾部有多粗,波峰有多尖。它表明在我们的数据中找到极值的可能性有多大。较高的值更有可能产生异常值。这听起来很像 spread(方差),但有细微的不同。

Kurtosis illustration of three curves. Courtesy: Wikipedia

我们可以看到,较高的峰值具有较高的峰度值,即最顶部的曲线比最底部的曲线具有较高的峰度。

那都是乡亲们!这是一篇相当短的文章;我们知道了百分位数有多重要,因为它们表明了我们相对于其他人的地位。然后,我们看到了一个特殊的类别,称为四分位数,以及它们在寻找异常值中的应用。最后,我们探索了描述曲线形状的四个“矩”。

感谢阅读!第四部分即将到来……

我定期在 中型 上写关于技术的&数据——如果你想阅读我未来的帖子,请“关注”我!

统计学是数据科学的语法—第 4/5 部分

原文:https://towardsdatascience.com/statistics-is-the-grammar-of-data-science-part-4-5-e9b1ce651064?source=collection_archive---------16-----------------------

统计复习,开启您的数据科学之旅

这是“统计学是数据科学的语法”系列的第 4 篇文章,涵盖了协方差相关性的重要主题。

修订本

其余文章的书签,便于访问:

文章系列 第 1 部分:数据类型|集中趋势度量|可变性度量
第 2 部分:数据分布
第 3 部分:位置度量|矩
第 4 部分:协方差|相关性🚩
第五部分:条件概率|贝叶斯定理

介绍

为了给本文打下基础,我们将假设我们有一个散点图,每个数据点代表一个人:一个轴上是他们多年的职业经历,另一个轴上是他们的收入。

‘Professional experience vs. Income’ scatterplot

如果散点图看起来像右边的,那么我们得出经验和收入之间没有真正的关系,即对于任何给定的经验,都可能有一个收入范围。

相反,在左图中,这些属性之间存在明显的线性关系。

协方差和相关性为我们提供了一种测量数据集属性相互依赖程度的方法

注意:在这个例子中,描述的数据类型是双变量的——两个变量的“bi”。实际上,统计学家使用的是多元数据,即许多变量。

协方差

协方差是两个(或更多)随机变量之间关联的度量。

顾名思义,“co + variance”类似于方差,但用于比较两个变量——我们用叉积之和代替*方和。方差告诉我们单个变量如何偏离均值;协方差告诉我们两个变量如何彼此不同。因此,可以公*地说:

协方差是衡量两个变量之间的方差。

协方差可以是负的也可以是正的(或者明显为零):正的值意味着两个变量趋向于以相同的方向变化(即如果一个增加,那么另一个也增加),一个负的值意味着它们以相反的方向 变化(即如果一个增加,那么另一个减少),而意味着它们不一起变化

公式

这个公式可能很难解释,但更重要的是理解它的含义:

Covariance between variables X and Y

如果我们认为一个随机变量的数据集被表示为一个向量,那么在前面的例子中,我们有两个向量,分别是经验和收入。以下是我们需要遵循的步骤:

  • #1 。将这两个向量转换为*均值的方差向量。
  • #2 。取两个矢量的点积(等于它们之间夹角的余弦)。
  • #3 。除以样本量(n 或 n - 1,如前所述,基于是否为完全总体)。

第二步,我们有效地测量这两个向量之间的角度,所以如果它们彼此接*,就意味着这些变量是紧密耦合的。

主要限制

值得注意的是,虽然协方差确实度量了两个变量之间的方向关系,但它并不显示它们之间的关系强度。

实际上,这种度量的最大问题是它依赖于使用的单位。例如,如果我们将几年的经验转换成几个月的经验,那么协方差会大 12 倍!

这就是相关性发挥作用的地方!

Rainbow scatterplot. Courtesy: Scipy

相互关系

相关性是统计学中最常见的度量之一,它描述了两个随机变量之间的关联程度。它被认为是协方差的归一化版本。让我们看看为什么…

公式

相关性(用希腊字母ρ — rho 表示)可以用以下公式表示:

Correlation between variables X and Y

相关性被限制在-1 和 1 之间。与协方差一样,相关性的符号表示关系的方向:正表示随机变量一起移动,负表示随机变量向不同方向移动。

端点(即 1 和-1)表示两个变量之间存在完美的关系。例如,米和厘米之间的关系总是 1 米对应 100 厘米。如果我们画出这个关系,它将是一条完美的线,因此相关性是 1。

请注意,完美的关系在现实生活数据中非常罕见,因为两个随机变量通常不会通过常数因子相互映射。

相关性为 0 意味着两个变量之间没有线性关系。可能有一个 x = y 关系。

关键特征

相关性不仅指示关系的方向,还指示其强度,(取决于绝对值有多大)因为它是无单位的:因为我们将协方差除以标准偏差,所以单位被抵消了。

最后,我们需要记住' 相关性并不意味着因果关系 ':两个随机变量之间的高度相关性只是意味着它们彼此关联,但它们的关系在本质上并不一定是因果关系。证明因果关系的唯一方法是用受控实验,在这里我们排除外部变量,隔离两个变量的影响。

😆 Courtesy: Pinterest

全部完成!我们已经学会了如何使用协方差和相关性来衡量数据集中的两个不同属性是否以线性方式相互关联,以及为什么相关性通常是首选,因为它是无单位的。

感谢阅读!第五部即将到来……

我定期在 媒体 上撰写关于技术&的数据——如果你想阅读我未来的帖子,请“关注”我!

统计学是数据科学的语法—第 5/5 部分

原文:https://towardsdatascience.com/statistics-is-the-grammar-of-data-science-part-5-5-3f6099faad04?source=collection_archive---------7-----------------------

统计复习,开启您的数据科学之旅

这是“统计学是数据科学的语法”系列的第 5 篇(也是最后一篇)文章,涵盖了条件概率贝叶斯定理及其重要性。准备好了吗?

修订本

其余文章的书签,便于访问:

文章系列 第 1 部分:数据类型|集中趋势度量|可变性度量
第 2 部分:数据分布
第 3 部分:位置度量|矩
第 4 部分:协方差|相关性
第 5 部分:条件概率|贝叶斯定理🚩

条件概率

条件概率是一个事件发生的可能性,基于一个先前事件的发生。

条件概率的符号是 P(A|B),读作'给定 B 的概率'。条件概率的公式是:

Conditional Probability of A given B

A ∩ B 是维恩图中 A 和 B 的交集,所以 P(A∩B)是 A 和 B 同时出现的概率。
照这样:

给定 B 的概率等于 A 和 B 发生的概率除以 B 单独发生的概率。

Venn diagram: Probabilities of events A and B.

✏️的例子:

假设我们从一个袋子里抽出三颗弹珠——红色、绿色和蓝色。

在已经画了红色的弹珠之后,再画蓝色弹珠的条件概率是多少?

如果事件 A 是首先获得红色弹珠的事件,而事件 B 是获得蓝色弹珠的事件,我们希望计算 P(A∩B) :

  • P(A) 是第一回合得到红色弹珠的概率。因为这是三种可能结果中的一种:
P(A) = 1/3 = 33.33%
  • P(B|A) 是第二回合得到蓝色弹珠的概率。因为还剩下两个弹珠:
P(B) = 1/2 = 50%
  • P(A ∩ B) 是第一轮画出红色弹珠,第二轮画出蓝色弹珠的概率:
P(A ∩ B) = P(A) * P(B|A) = 33.33% * 50% = 16.66%

为了形象化这一点,我们可以使用树形图——每个分支都有一个条件概率

Tree Diagram for the marble bag example

原因

我们在第四部分中看到了因果关系的含义。条件概率不表示两个事件之间有必然的因果关系,也不表示两个事件同时发生。

独立事件

独立事件是那些其结果不影响其他事件结果的概率的事件。由于这个原因:

P(A|B) = P(A)
P(B|A) = P(B)

互斥事件

互斥是指那些不能同时发生的事件,即如果一个事件已经发生,另一个就不能发生。因此:

P(A|B) = 0
P(B|A) = 0

Neon sign showing the simple statement of Bayes’ theorem. Courtesy: Wikipedia

贝叶斯定理

刚刚探索了什么是条件概率,让我们来看看贝叶斯定理。它只是说:

给定 B 的概率等于给定 A 的 B 的概率乘以 A 的概率,除以 B 的概率。

Bayes’ Rule

换句话说,它提供了一种在 P(A|B)和 P(B|A)之间转换的有用方法。

在更大的范围内,它是统计学中整个领域的基石(“贝叶斯统计学”)。它被用于各种学科,最著名的例子是医学药理学,但也用于金融,例如预测一项投资成功的概率。

将这些条件变量应用于贝叶斯定理时,数量几乎和质量一样重要。例如,假设我们想计算借钱给借款人的风险。如果我们考虑其他可能性,如借款人的年龄、信用评级和风险偏好,借钱给特定个人的可能性会有所不同。

正如理论本身所假定的那样:

变量越多,我们对这些变量越有把握,就越能利用条件概率得出准确的结论!

✏️的例子:

假设我们是诊所的医生,我们知道:肝病患者的概率是 20%,酗酒者的概率是 5%,在被诊断为肝病的患者中,10%是酗酒者。我们现在想知道:

如果一个病人是个酒鬼,那么他患肝病的条件概率是多少?

  • P(A) 是患肝病的概率:
P(A) = 20%
  • P(B) 是成为酗酒者的概率:
P(B) = 5%
  • P(B|A) 是假设患者患有肝病,则患者为酗酒者的条件概率:
P(B|A) = 10%
  • P(A|B) 是假设患者是酗酒者,他们患肝病的条件概率:
P(A|B) = (10% * 20%) / 5% = 40%

互斥事件

贝叶斯定理的一个特例是当事件 A 是二进制值时。在这种情况下,我们用‘A–’表示事件 A 已经发生,用‘A+’表示事件 A 没有发生(即事件 A–和 A+是互斥的)。
公式表示如下:

Bayes’ Rule for mutually exclusive events A- and A+

准确(性)

一个真正是模型正确预测类的结果。类似地,真负是模型正确预测类的结果。

假阳性是模型错误地预测阳性类别的结果。类似地,假阴性是模型错误地预测阴性类的结果。

灵敏度表示测试正确预测病例的概率→真阳性。

特异性表示检测将正确识别阴性病例→真阴性的概率。

Sensitivity = true positives / (true positives + false negatives)
Specificity = true negatives / (true negatives + false positives)

✏️的例子:

我们假设某种疾病的发病率为 2%。如果假阴性率为 10%,假阳性率为 1%:

一个测试呈阳性的人实际患有这种疾病的条件概率是多少?

如果事件 A 是个体患有这种疾病的事件,并且事件 B 是个体测试呈阳性的事件,我们希望计算 P(A|B) ,即假设个体测试呈阳性(B),他们实际上患有疾病(A)。

  • P(A+)P(A) 为患此病的概率:
P(A+) = 2%
  • P(A)为不患此病的概率,可推导出:
P(A-) = 100% - 2% = 98%
  • P(B | A–)是假阳性的概率,即没有患病(A–)但呈阳性(B):
P(B|A-) = 1%
  • P(B –| A)是假阴性的概率,即患有疾病(A)但结果为阴性(B –)
P(B-|A) = 10%
  • P(B|A+)P(B|A) 为真阳性,即患病(A)和阳性(B),可推导出:
P(B|A) = 100% - 10% = 90%
  • 我们现在有了计算 P(A|B)的所有信息:
P(A|B) = [ P(B|A) x P(A) ] **/** [ P(B|A-) x P(A-) **+** P(B|A+) x P(A+) ]= [ 90% x 2% ] / [ 1% x 98% + 90% x 2% ] == 64.7%

我们可以用一个矩阵来显示测试精度:

在树形图中:

完毕完毕。今天我们学习了条件概率反映了一个事件对另一个事件的概率的影响。然后我们深入研究了贝叶斯定理,这是统计学的基础,因为它允许概率推理。

结束了

Photo by Matt Botsford on Unsplash

这是《统计学是数据科学的语法》续集的结尾。我希望您现在已经具备了开始数据科学之旅的知识!如果你想了解其他内容,请在评论中给我留言,并尝试把它添加到我的下一篇文章中。

感谢阅读!

我定期在 中型 上写关于技术的&数据——如果你想阅读我未来的帖子,请“关注”我!

棒球迷的统计数据:进攻的唯一指标是 OPS。

原文:https://towardsdatascience.com/stats-for-baseball-fans-the-single-metric-for-offense-is-ops-fc568af5e87b?source=collection_archive---------19-----------------------

今年夏天,我爱上了棒球,因为我把我喜欢的东西(统计学)和我不太感兴趣的东西(芝加哥小熊队和箭牌棒球场)结合了起来。)

现在,我如何找到小熊队的故事可以成为自己的博客帖子——它充满了浪漫,从南方搬到亚特兰大勇士队,一份新工作,住在离箭牌球场几步之遥的地方……有一天我会写这本书。

但是…今天的博客是关于用统计数据来证明你只需要关注一个数据就能了解你的球队中最好的进攻球员,从而成为我所能做到的最有见识的球迷。这个数据就是 OPS(上垒率加上击球率。)

TLDR:你最喜欢的球队中 OPS 数据最高的球员很可能是他们整体进攻最好的球员。当他们来到本垒时,大声欢呼。

数字,数字,无处不在…

你去过 MLB 棒球场,注意到记分牌是数字的海洋吗?AVG、OBP、SLG、OPS,这些指标在棒球卡上、报纸上和电视分析师那里都有报道。它们有什么意义吗?

事实证明确实如此。每个人都试图测量表面上看起来很重要的击球方面。SLG 是一个用来了解玩家实力的指标;OBP 是一个衡量一个球员有多擅长跑垒的标准。

作为一名分析师和数据科学家,这些指标让我着迷。作为一个只想享受比赛的球迷,他们可能会感到困惑。当我想了解我支持的球队中最好的击球手时,肯定有一个指标是我应该注意的。

我喜欢简单的运动——它让啤酒、饼干和热狗味道更好。

现在我意识到有时候很容易理解你最好的击球手。尤其是,当你的球队中有一个像迈克·特劳特这样的强力击球手或者每个人都喜欢的球员——芝加哥小熊队的贾维·贝兹。从粉丝反应就能看出来。这很好,但我如何才能穿过噪音,只关注那些为球队得分的球员呢?

这就是我们求助于统计数据的地方。

理解棒球数据的问题是:球员也是人。

用球员的个人表现来理解统计数据的价值有一个很大的问题。不幸的是,球员生病,有孩子,休息几天,被送到小联盟,玩疯了或者只是过了糟糕的一天。

换句话说,玩家也是人。

为了消除我们数据库中讨厌的人类特征,我们做了一点小技巧来消除玩家噪音。不分析球员,我们来分析球队。球队不休假,通常一年打 162 场比赛(当我们除去像 1994 年 MLB 罢工这样的离群值时。)*均来说,每支球队都应该有相似的击球次数和均等的得分机会。因为它不太人性化和规范化,所以团队级别的数据是理解棒球统计重要性的门票。

  • 查德威克棒球数据库(见此 帖子 了解更多信息)。)

从球员分析过渡到球队分析使我们的数据正常化;让统计学家更容易完成这个项目。

进攻=跑垒。

Dictionary.com 是这样定义棒球的:

(棒球)两个九人队之间的一种球类运动,通常在一个场地上打九局,该场地的焦点是一个菱形内场,该内场有一个本垒板和三个相距 90 英尺(27 米)的其他垒,形成一个必须由跑垒者完成才能得分的回路,中心进攻动作包括用木制或金属球棒击打投球并跑垒, 获胜者是得分最多的队

我们关心跑垒,因为这是进攻球员唯一最重要的目标——打击跑者或通过到达本垒使自己跑起来。该分析需要运行目标函数(y)。分析的目标是找到与跑垒最相关的击球统计数据。我们的假设是,一个球员让自己得一分(r)和一分(rbi)的能力将会是一个强有力的进攻球员的信号。我们如何在单一指标中捕捉到这一点?

OPS 与跑步最相关。

我们通过计算一些你会发现投射在整个 MLB 体育馆的记分牌上的统计数据来开始这项分析。潜在的指标包括击球率(AVG)、击球率(SLG)、上垒率(OBP)、上垒率加击球率(OPS)以及其他常见的击球指标(AB、H、2B、3B、HR 等)。)

我们不得不从头开始创建一些指标,它们的定义如下所示:

SLG =(安打+双打+(三双2) +(小时3)) /在击球时

AVG =击球数

OBP =(安打+保送+投球命中)/(击球+保送+投球命中+牺牲苍蝇)

OPS = OBP + SLG

早些时候,我提到过我们通过使用团队赛季总数而不是个人球员总数来标准化我们的数据。我通过去除一些异常的季节进一步规范化。以下是我的团队剔除异常值的全部细节:

  • 删除 1970 年之前的球队:1970 年赛季之前没有跟踪几个关键指标(包括牺牲苍蝇、被投球击中和其他)。)
  • 删除了比赛场次低于 156 场的赛季:这将删除因罢工和其他日程怪事而缩短的赛季。(再见 1994 赛季。)
  • 删除了不参加国家或美国联赛的球队:我们不关心这个分析中的小联盟或春训联盟。

一旦我们有了干净的数据,我们就可以运行将常见命中指标与运行相关联的分析。分析结果表明,OPS 是唯一最重要的指标,相关系数为 0.95(与运行高度相关。)

有史以来最好的玩家(在随机森林的帮助下)

现在我们知道我们应该最关注运营,我想问的下一个问题是,根据这个标准,谁是最好的玩家?答案很容易计算…

事实上,他们不是。

在这篇文章的早些时候,我提到在某些棒球时代,球员的统计数据并没有保持干净。1954 年,形成我们今天看到的牺牲飞统计的规则被创造。在 1954 年之前,MLB 对 SF 有不同的定义或者根本没有跟踪。

那么,我们要如何为 1954 年之前的玩家定义 OPS 呢?

我使用随机森林算法根据 MLB 收集的数据来预测玩家丢失的数据。然后我用预测的数据来估算 1954 年之前玩家的 OPS。我不打算用这个博客来展示随机森林方法,但是我会展示一些输出,这样你就知道是我做的。

随机森林模型

我选择的包是 R 图书馆,randomForest。下面是调整后的射频算法和输出预测牺牲苍蝇的球员的统计数据保存:

你会看到随机森林在模拟牺牲苍蝇方面非常有效,92.4%的方差可以用已知的命中变量来解释。我超级自信我的 OPS 对于 1954 年之前的玩家来说是合理的。

不再赘述,以下是 OPS 评选出的前 15 名史上最伟大球员名单;在我看来是有史以来最伟大的进攻球员。

根据行动计划,我儿时的偶像弗兰克·托马斯晋级了。迈克·特劳特是前 15 名中唯一活跃的选手;而贝比鲁斯是进攻之王……愿他统治长久。

最后

OPS 是一个可靠的指标,它包含了棒球进攻策略的两个关键组成部分。

  1. OBP:球员将自己置于得分位置的能力。
  2. 玩家的力量和他们创造打击的能力,这种能力可以让玩家在垒周围移动(包括他们自己)。)

我的建议是小心那些拥有极高 OPS 数据的玩家。他们通常会是你最兴奋的击球手。根据数据,0.8 的 OPS 是例外的;我以此为标准来评估今天的球员。

站在数据科学的前沿

原文:https://towardsdatascience.com/staying-on-top-of-data-science-baeff05ca59f?source=collection_archive---------25-----------------------

Data Scientists trying to stay on top of technological developments in the 1880s.

在最*的一条推文中,一位 DS 招聘经理报告说,他问了一位候选人一个具体的框架,当候选人承认他们没有听说过这个框架时,他给出了否定的回答。在为自己的立场辩护时,招聘经理表示,负面分数的原因是不了解框架会让候选人看起来跟不上新的发展。

数据科学家需要做出特殊努力来跟上新发展的想法非常普遍。数据科学被认为是一个不断出现新发展的前沿领域。然而,数据科学课程反映了相反的情况——新的数据科学家被教授用 SQL、Python 和 R 编写代码——年龄分别为 40 岁、25 岁和 26 岁。

另一方面,机器学习算法和统计技术往往更古老——逻辑回归通常被认为是在 1944-75 年前开发的;C&RT 发明了将* 40 年。神经网络是在 20 世纪 60 年代发明的。

深度学习可以说是最引人注目的例外。尽管它的根源在于从 20 世纪 80 年代到 21 世纪初的一系列发展,但最常被引用的“突破时刻”发生在 2012 年。针对不同应用使用不同的架构吸引了新的发展,深度学习的相对年轻也是如此。

然而,每周新的深度学习架构或新的 R 包的存在并不意味着数据科学家应该感到必须学习它们。需要有一个理由来解释为什么这些新的发展会增加你的技能。

困难在于,虽然学习一个新的框架或库可能会略微提高您的生产率,但随着大多数数据科学领域达到的成熟水*,生产率的差异将是微不足道的。在很大程度上,通过学习每一个额外的新工具,你将看到的收益会比以前的框架小一些。

与此同时,提高你作为数据科学家的效率的最佳方式不是学习一种新技术来帮助你更快地训练一种算法,或者甚至更快或更好地准备数据。而是花更多的时间去了解你工作的领域,花更多的时间去了解你的客户想要从数据科学中得到什么。

对新技术的不懈追求将会偏离这一目标;花在阅读 R 包文档上的时间通常是你没有花在更好地了解你的用户上的时间,或者至少(假设你的用户没有无限的时间和你在一起)你没有花在训练自己更好地理解你的客户对你说的话上的时间。

数据科学已经存在了大约 50 年。直觉上,一年的创新价值不到 2%的额外知识。统计创新没有摩尔定律。

与此同时,大多数完成了基本培训和几年工作的数据科学家在技术上并不弱。更有可能的是技术是他们的优势。成为更好的数据科学家的最有效的方法不是学习更多的技术,而是找到一个较弱的领域并努力改进。最有可能的是,薄弱环节将是沟通技巧、销售技巧或最有效的与用户产生共鸣的方式。

罗伯特·德格拉夫的书 管理你的数据科学项目 ,已经通过出版社出版。

在 Twitter 上关注罗伯特

一步一步:在罗宾汉建立自动交易系统

原文:https://towardsdatascience.com/step-by-step-building-an-automated-trading-system-in-robinhood-807d6d929cf3?source=collection_archive---------0-----------------------

Photo by Maxim Hopman on Unsplash

在这篇文章中,我将探索通过 Python 代码与 Robinhood API 集成的用法。

想法是用 Robinhood 做交易*台。Robinhood API 对市场数据的访问非常有限。不建议将他们的 API 用于数据目的。

什么是罗宾汉?

Robinhood 提供了一种允许客户买卖股票和交易所交易基金(ETF)而无需支付佣金的方式。它是一个交易*台,还没有提供官方的 API。

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

开始吧

如果你搜索Robinhood API python,有大量的 Github 链接或者文档。但是大部分都不支持最新的 API。还有一些项目很久没更新了,见 sanko 的罗宾汉。

这里我用的是 Robinhood (一个 python 框架),它最初来自 Jamonek 的 Robinhood 框架。自从 Robinhood 实施强制 MFA 以来,我做了一些改变以确保它的工作。

在控制台中找到您想要下载的位置,然后简单地运行:

git 克隆https://github.com/LichAmnesia/RobinhoodCD 罗宾汉
sudo python3 setup.py install

那你就可以走了!

注册

默认方式需要你手持手机输入验证码。

这样,您需要每 24 小时登录一次,因为您的身份验证令牌将过期。

使用类似这样的内容登录:

如果不想启用 2FA,可以跳过这一部分。启用 2FA 后,每次登录罗宾汉网站时都需要输入验证码。

若要启用 2FA,请转到您的 Robinhood Web 应用程序。进入设置,打开 2FA,选择“认证 App”,点击“扫描不了?”,并复制 16 个字符的二维码。

使用类似这样的内容登录:

访问市场数据

数据是任何策略的支柱,但 Robinhood API 只返回股票非常基本的信息。

如果您需要历史价格数据:

目前,API 仅支持 5 分钟| 10 分钟| 30 分钟|天|周的时间间隔。日期范围为日|周|年| 5 年|全部。

从 API 交易

Robinhood 需要你有 25k 以上才能做日内交易。否则 5 天只能做 4 天的交易。参见罗宾汉模式日交易。

由于 Robinhood 没有任何纸质账户,因此从 API 执行的所有订单都与在 App 中执行的订单相同。

这里我用DWT举例,每股 5 美元。

现在我提交一份市价单:

此处GFD表示当天有效,如果今天未满将被取消。此外,您可以设置GTC,这意味着直到取消良好。

做市价单截图:

我可以看到一个市场买入订单在排队,一个市场卖出订单错过了。

在这里我收到了400 Client Error: Bad Request for url: https://api.robinhood.com/orders/。因为如果你没有足够的库存,罗宾汉不允许你发出卖出指令。

记得*仓你的DWT

现在我试着做限价单并取消它:

限价单制作和取消截图:

所有支持的订单功能:

place _ market _ buy _ order
place _ market _ sell _ order
place _ limit _ buy _ order
place _ limit _ sell _ order
place _ stop _ loss _ sell _ order
place _ stop _ limit _ sell _ order

账户管理

如果您想查看您的当前头寸和当前市值:

然后

学习和建立一个自动交易系统并不容易。有了正确的工具,你现在可以开始制作你的第一个交易算法。接下来,我打算谈谈如何在 Robinhood 中建立一个基本的交易策略。如果你有任何问题,请在下面提问。

从头开始构建自己的神经网络的分步指南

原文:https://towardsdatascience.com/step-by-step-guide-to-building-your-own-neural-network-from-scratch-df64b1c5ab6e?source=collection_archive---------2-----------------------

学习深度学习的基础知识,并为图像分类建立自己的神经网络

Photo by Aron Visuals on Unsplash

关于机器学习、深度学习和人工智能的实践视频教程,请查看我的 YouTube 频道。

“什么”和“为什么”

什么是深度学习

我们之前都听说过深度学习。由于计算能力、数据可用性和算法方面的最新进展,它在数据科学从业者中非常受欢迎,现在被用于各种环境中。

但是深度学习到底是什么

简单来说,深度学习就是指训练一个神经网络

现在,什么是神经网络?

嗯,它只是一个适合某些数据的函数。最简单的形式是用一个函数来拟合一些数据,如下所示。这种结构被称为神经元

Schematic of a neuron

函数可以是任何东西:线性函数或 sigmoid 函数。当然,单个神经元并没有优于传统机器学习算法的优势。

所以一个神经网络结合了多个神经元。将神经元视为神经网络的构建模块。通过堆叠它们,可以构建如下所示的神经网络:

Schematic of a neural network

注意上面每个输入是如何输入到每个神经元的。神经网络会自己计算出哪个函数最符合数据。你需要提供的只是输入和输出。

为什么要用深度学习?

深度学习已经成功应用于许多监督学习设置中。传统的神经网络应用于在线广告目的。卷积神经网络( CNN )非常适合照片标记,递归神经网络( RNN )用于语音识别或机器翻译。

*年来,我们的数字活动显著增加,产生了非常大量的数据。虽然传统机器学习方法的性能将随着更多数据的使用而趋于*稳,但足够大的神经网络将随着更多数据的可用而提高性能。*年来,数据存储变得非常便宜,计算能力允许训练这种大型神经网络。

这就是为什么深度学习现在如此令人兴奋。我们可以访问大量的数据,我们有计算能力来快速测试、构思和重复实验,以提出强大的神经网络!

现在我们知道了什么是深度学习,以及它为什么如此棒,让我们编码我们的第一个用于图像分类的神经网络!点燃你的 Jupyter 笔记本!

Yes, our neural network will recognize cats. Classic, but it’s a good way to learn the basics!

你的第一个神经网络

目标是建立一个神经网络,该网络将图像作为输入和输出,不管它是不是猫的图片。

在此随意获取整个笔记本和数据集。它还包含一些用于导入数据集的实用工具。

导入数据

和往常一样,我们首先导入相关的包来使我们的代码工作:

然后,我们加载数据,看看图片是什么样的:

您应该会看到以下内容:

Example of a cat image in the dataset

然后,让我们打印出关于数据集的更多信息:

您应该会看到:

General information about the dataset

如你所见,我们在训练集中有 209 幅图像,我们有 50 幅图像用于训练。每个图像是一个 64px 宽和高的正方形。此外,您会注意到图像的第三维是 3。这是因为图像由三层组成:红色层、蓝色层和绿色层(RGB)。

A picture is composed of three layers

每层中的每个值都在 0 到 255 之间,它代表该像素的红色,或蓝色,或绿色,为每种组合生成一种独特的颜色。

现在,我们需要在将图像输入到我们的神经网络之前将它们展*:

太好了!您现在应该看到训练集的大小为(12288,209)。这意味着我们的图像被成功地展*了

12288 = 64 x 64 x 3。

最后,我们将数据集标准化:

选择激活功能

建立神经网络的第一步是找到合适的激活函数。在我们的例子中,我们希望预测一张图片是否有猫。因此,这可以被框定为一个二元分类问题。理想情况下,我们应该有一个为猫图片输出 1 的函数,否则输出 0。

你可能已经知道,sigmoid 函数在这里是有意义的。我假设你知道 sigmoid 函数的大部分性质。不然可以在这里了解更多。

数学上,sigmoid 函数表示为:

Sigmoid function

因此,让我们定义 sigmoid 函数,因为稍后它会变得很方便:

太好了,但是什么是 z ?它是加权输入,表示为:

Weighted input

其中 w权重矩阵, b偏差。现在,我们需要初始化权重偏差

将权重视为一个特性的重要性。通常我们将其初始化为非零随机值

偏差是我们添加的常数,就像线性方程的截距。这为神经网络提供了一个额外的参数来调整,以提高拟合度。偏置可以初始化为 0。

现在,我们需要为正向传播反向传播定义一个函数。

在前向传播期间,执行一系列计算以生成预测并计算成本。成本是我们希望最小化的函数。在我们的例子中,成本函数将是:

Cost function

其中 y 是观察值,而 y_hat 是预测值。

然后,反向传播计算梯度或导数。这在优化阶段将是有用的,因为当导数接*或等于 0 时,这意味着我们的参数被优化以最小化成本函数。

因此,我们编写以下函数:

太好了!如上所述,我们需要重复正向传播和反向传播来更新参数,以便最小化成本函数。这是使用梯度下降完成的。为此,我们设置了一个学习率,它是一个小的正值,控制每次运行时参数的变化幅度。

为学习率 a 选择一个合适的值很重要,如下所示:

Pot of the cost as a function of the weights. Left: small learning rate. Right: large learning rate.

如果太小,就需要更长的时间来训练你的神经网络,如左图所示。如果它太大,你可能永远不会达到全局最小值,梯度下降将永远振荡。

在我们的例子中,我们将像这样更新参数:

Gradient descent

其中 alpha 是学习率。在代码中,我们写道:

太棒了,我们快完成了!我们需要做的就是计算一个预测。知道 sigmoid 函数输出一个 0 到 1 之间的值,我们就确定如果值大于 0.5,我们就预测一个正例(是猫)。否则,我们将预测一个错误的例子(不是猫)。

太神奇了!将我们所有的功能组合成一个单一的模型应该是这样的:

现在,我们可以训练我们的模型并进行预测了!

运行上面的代码单元后,您应该看到在测试集上获得了 99%的训练准确率和 70%的准确率。对于一个简单的神经网络来说还不错!

您甚至可以将成本绘制为迭代次数的函数:

您应该会看到:

Cost function going down as more iterations are performed

你会看到每次迭代后成本确实在下降,这正是我们想要的。

随意试验不同的学习速率和迭代次数,看看它如何影响训练时间和模型的准确性!

恭喜你!您学习了深度学习的基础知识,并建立了您的第一个用于图像分类的神经网络!这篇文章中解释的概念是理解更复杂和更高级的神经网络结构的基础。

在未来的中,我们将通过建立一个具有更多层的更深神经网络,将我们的图像分类器带到下一个级别,并看看它是否能提高性能。

敬请关注,继续学习!

来源: 深度学习 AI

创建文本到语音到文本电子邮件助手的分步指南

原文:https://towardsdatascience.com/step-by-step-guide-to-creating-a-text-to-voice-to-text-email-assistant-ca62eaf96437?source=collection_archive---------28-----------------------

Photo by Charles 🇵🇭 on Unsplash

在这篇文章中,我将描述如何创建您的个人电子邮件秘书。

这个电子邮件秘书是一个电子邮件应用程序,它使用 Gmail API 读取您的电子邮件,使用 Google 文本到语音 API 和“playsound”API 读出您的电子邮件,使用“py audio”API 听到您的响应,使用 Google 语音到文本 API 将音频响应转换为文本,最后使用 Gmail API 再次发送响应。

要查看这个电子邮件助手的运行情况,请观看视频

我相信你一定很想知道它是如何创建的,以及所有的步骤都需要什么。所以让我们开始吧。我将详细列出所有应该易于遵循和实施的步骤

步骤 1:创建虚拟环境并安装 Python 库

整个程序是在 mac-book-pro 上编写的,但它是独立于*台的,可以在 windows pc/laptop 上遵循相同的步骤。除此之外,我使用 anaconda python 安装和 pycharm 社区版作为编程编辑器。如果您熟悉创建虚拟环境和安装 python 库,请直接跳到下一节。

在虚拟环境中工作总是安全的,以防止应用程序之间的库冲突

1a。创建虚拟环境

在 mac 终端窗口创建您的虚拟环境,并安装 playsound 和 pyaudio 库

*#conda create — name p36
#conda activate p36
#pip install playsound
#pip install pyaudio*

第二步:配置谷歌云*台

在这一步中,我们需要转到 google cloud 开发者*台,创建服务密钥、凭证并激活相关的 API 来使用它们。谷歌。

2a。激活环境

在激活时,谷歌会要求你提供信用卡,并承诺在年底不会拖欠你的费用。如果提供 300 美元的 1 年免费信贷,则使用 API

链接激活您的账户【https://console.developers.google.com/

Google Cloud Platform Activation Steps

Google Cloud Platform Activation Success

不幸的是,随后启用 API、创建服务密钥和凭证的后续步骤相当复杂,但请继续

2b。创建服务帐户密钥

Create Service Account Key — Input

完成这一步后,会创建一个扩展名为. json 的密钥文件。下载此服务帐户密钥。此密钥是根据您的程序的身份验证要求提供的

2c。创建 OAuth2.0 凭据

这一步是为了让您的应用程序能够访问 GMAIL。我们将申请'撰写'和'发送'电子邮件,以便能够适时运行我们的原型

在此步骤之后,凭证页面将如下所示,即带有服务帐户密钥和 OAuth 客户端 id。

Final Credentials Page

下载相关凭证到您计算机上存储 python 脚本的文件夹中(任何地方都可以,只要您提供应用程序的正确路径)

2d。激活文本到语音、语音到文本和 Gmail APIs

最后,我们激活文本到语音 API、语音到文本 API 和 Gmail API。在仪表板上,您会看到“启用 API 和服务”选项。

Enable APIS on the dashboard

从过多的 API 和服务中启用的最简单的方法是通过搜索(常见的是 Google,你还能在那里做什么)。请参见下面的搜索文本到语音和语音到文本 API 的示例。

Searching for APIS to enable

找到 API 后,只需点击启用(下面是 Gmail 的示例)

Enable Gmail API

最后,我们准备研究程序本身。

步骤 3:运行应用程序

现在是比较容易的部分。这很简单,因为大多数代码示例都可以在 GCP 教程网站上找到,可以选择复制,还有很多解释。另一方面,这些链接有很多深层链接,为用户提供了所有的 API 选项。这导致新用户容易迷路。

在这里,我向您描述了启动和运行原型的相关部分。之后,根据 GCP 站点上的文档,按照您的特定需求进行配置就容易多了。我提供了每个特定部分的 GCP 教程的链接

运行原型的步骤是

  • 从 github 下载代码到特定文件夹
  • 将凭据(服务帐户密钥和 OAuth 密钥)复制到与代码相同的文件夹中
  • 在 Main.py 中替换要导出的 GOOGLE_APPLICATION_CREDENTIALS 的路径
#Replace this with the correct file path of the service account key
os.environ[**'GOOGLE_APPLICATION_CREDENTIALS'**] = \**"/Users/name/Documents/GitHub/Python-Exercises/googleSpeechToText/GMAIL_gTtS_gStT_ServiceAccountKey.json"**
  • 在 RaSmails.py 中替换 OAuth2.0 文件的名称
#Replace this with correct file path of credentials .json
flow = InstalledAppFlow.from_client_secrets_file(**'oath2_credentials_mailreceiver349.json'**, SCOPES)
  • 在终端窗口中激活虚拟环境(#conda activate — name p36)
  • 以#python Main.py 的身份运行代码

代码流程的简要概述如下:

获取 Gmail 服务实例>获取最新 5 封电子邮件的片段>将最新片段转换为音频>播放音频文件(最新电子邮件) >录制回复电子邮件>将音频转换为文本>发送回复电子邮件

以下链接详细描述了正在使用的 API

  • 阅读邮件,
  • 将文本转换为语音,
  • 将语音转换为文本最后
  • 发送邮件。

我希望你喜欢这个原型。乐意回答任何问题。让我知道你的想法

创建 R 和 Python 库的分步指南(在 JupyterLab 中)

原文:https://towardsdatascience.com/step-by-step-guide-to-creating-r-and-python-libraries-e81bbea87911?source=collection_archive---------3-----------------------

r 和 Python 是当今机器学习语言的面包和黄油。r 提供了强大的统计和快速的可视化,而 Python 提供了直观的语法和丰富的支持,是当今主流 AI 框架的首选接口。

在本文中,我们将看看用 R 和 Python 创建库的步骤。这是每个机器学习从业者都应该拥有的技能。库帮助我们组织代码并与他人共享,为数据社区提供打包的功能。

注意:在本文中,我交替使用了术语“库”和“包”。虽然有些人区分这些词,但我不认为这种区分有用,而且很少在实践中看到这样做。我们可以把一个(或者)想象成一个包含函数的脚本目录。这些功能组合在一起,帮助工程师和科学家解决挑战。

创建图书馆的重要性

如果不广泛使用库,构建今天的软件是不可能的。库极大地减少了团队将工作投入生产所需的时间和精力。通过利用开源社区,工程师和科学家可以将他们独特的贡献推向更多的受众,并有效地提高他们代码的质量。各种规模的公司都使用这些库来将他们的工作置于现有功能之上,从而使产品开发更加高效和集中。

但是创建库不仅仅是为了生产软件。库对于快速原型化想法至关重要,可以帮助团队快速验证假设和制作实验软件。虽然流行的图书馆享有大量的社区支持和一套最佳实践,但较小的项目可以在一夜之间转化为图书馆。

通过学习创建轻量级的库,我们养成了维护代码和共享工作的习惯。我们自己的开发速度大大加快,我们将编码工作锚定在一个有形的工作单元上,我们可以随着时间的推移而改进。

文章范围

在本文中,我们将重点关注用 R 和 Python 创建库,以及在 GitHub 上托管和安装它们。这意味着我们不会关注流行的托管站点,比如 R 的 CRAN 和 Python 的 PyPI 。这些额外的步骤超出了本文的范围。

只关注 GitHub 有助于鼓励从业者更频繁地开发和共享库。CRAN 和 PyPI 有许多必须满足的标准(它们经常变化),这会减慢我们发布工作的过程。请放心,其他人从 GitHub 安装我们的库也一样容易。此外,CRAN 和 PyPI 的步骤可以在以后添加,如果你觉得你的库可以从托管站点中受益的话。

我们将使用相同的环境(JupyterLab)构建 R 和 Python 库,对这两种语言使用相同的高级步骤。这应该有助于您建立将代码打包成库所需的核心步骤的工作知识。

让我们开始吧。

设置

我们将用 R 和 Python 创建一个名为 datapeek 的库。datapeek 库是一个简单的包,提供了一些处理原始数据的有用函数。这些功能是:

encode_and_bind

remove_features

apply_function_to_column

get_closest_string

我们将在后面研究这些函数。现在,我们需要设置一个 R 和 Python 环境来创建 datapeek,以及一些支持打包代码的库。我们将在一个 Docker 容器中使用 JupyterLab ,以及一个我们需要的“Docker 栈”。

安装并运行 Docker

我们将使用的 Docker 栈被称为jupyter/data science-notebook。该图包含 R 和 Python 环境,以及许多通常在机器学习中使用的包。

因为这些都是在 Docker 里面运行的,所以你必须在你的机器上安装 Docker。所以 安装 Docker 如果你还没有的话,一旦安装好,在终端中运行以下命令data science-notebook:

docker pull jupyter/datascience-notebook

这将提取 Docker Hub 上托管的最新图像。

注意 : 任何时候你从 Docker Hub 拉一个项目,你都会得到最新的版本。如果距离上次拉动已经过了一段时间,请再次拉动以更新您的图像。

运行上述命令后,您应该立即看到以下内容:

一旦所有东西都被取出,我们就可以通过运行以下命令来确认我们的新映像存在:

docker images

…显示类似如下的内容:

现在我们有了 Docker 堆栈,让我们来设置 JupyterLab。

JupyterLab

我们将在一个 JupyterLab 环境中创建我们的库。JupyterLab 是一个基于 web 的编程用户界面。有了 JupyterLab,我们在浏览器中有了一个轻量级的 IDE,方便了构建快速应用程序。JupyterLab 提供了用 R 和 Python 创建库所需的一切,包括:

  • 一个终端环境,用于运行 shell 命令和下载/安装库;
  • 一个 R 和 Python 控制台,用于与这些语言交互工作;
  • 一个简单的文本编辑器,用于创建各种扩展名的文件;
  • Jupyter 笔记本用于 ML 工作的原型制作。

我们刚刚获取的 datascience-notebook 包含 JupyterLab 的安装,因此我们不需要单独安装它。在运行我们的 Docker 映像之前,我们需要挂载一个卷来确保我们的工作保存在容器之外。

首先,在你的桌面上创建一个名为 datapeek 的文件夹(或者任何你想创建的地方),然后进入这个目录。我们需要用 JupyterLab ,运行 Docker 容器,因此我们的完整命令应该如下所示:

docker run -it -v `pwd`:/home/jovyan/work -p 8888:8888 jupyter/datascience-notebook start.sh jupyter lab

你可以在这里了解更多关于 Docker 命令的信息。重要的是,上面的命令公开了我们在端口 8888 上的环境,这意味着我们可以通过浏览器访问我们的容器。

运行以上命令后,您应该会在最后看到以下输出:

这告诉我们将提供的 URL 复制并粘贴到浏览器中。打开浏览器,在地址栏中添加链接,然后按 enter 键(您的令牌会有所不同):

**localhost**:8888/?token=11e5027e9f7cacebac465d79c9548978b03aaf53131ce5fd

这将在您的浏览器中自动打开 JupyterLab 作为一个新标签:

我们现在准备开始建造图书馆。

我们从 R 开始这篇文章,然后看看 Python

在 R 中创建库

r 是机器学习的“两大”语言之一。在撰写本文时,它已经拥有超过 10,000 个图书馆。转到按发布日期 和运行日期列出的可用起重机包…

document.getElementsByTagName('tr').length

…在浏览器控制台中显示 13858。减去标题和最后一行,得到 13856 个包装。不用说,R 不需要变化。凭借强大的社区支持和简洁(如果不是直观的话)的语言,R 轻松地位居值得学习的统计语言之首。

关于创建 R 包最著名的论文是哈德利·威卡姆的书 R 包。它的内容可以在网上免费获得。如果想更深入地了解这个话题,我建议去那里看看。

我们将使用 Hadley 的 devtools 包来抽象出创建包所涉及的繁琐任务。dev tools已经安装在我们的 Docker Stacks 环境中。我们还需要 roxygen2 包,它帮助我们记录我们的函数。因为它没有预装我们的映像,所以让我们现在安装它。

注意:从现在开始我们将使用 JupyterLab 中的终端,以便于在浏览器中保存我们的工作。

打开 JupyterLab 发射器内的终端:

注意:如果您想将 JupyterLab 更改为黑暗主题,点击顶部的设置,点击 JupyterLab 主题,然后点击 JupyterLab 黑暗:

在控制台内键入 R,然后…

install.packages("roxygen2")
library(roxygen2)

安装好必要的软件包后,我们就可以开始每一步了。

步骤 1:创建包框架

我们需要为我们的包创建一个目录。我们可以使用 devtools create 函数,在一行代码中做到这一点。在终端运行中:

devtools::create("datapeek")

这将自动创建定义我们的 R 包所需的基本文件和目录。在 JupyterLab 中,你会在左侧看到一组新创建的文件夹和文件。

注意:你还会看到你的新目录结构在你的桌面上(或者你选择创建它的任何地方)被创建,因为我们在设置期间挂载了一个卷到我们的容器中。

如果我们在 JupyterLab 检查我们的包装,我们现在看到:

**datapeek**
├── **R**
├── datapeek.Rproj
├── DESCRIPTION
├── NAMESPACE

R 文件夹最终会包含我们的 R 代码我的包。Rproj 文件是特定于 RStudio IDE 的,所以我们可以忽略它。描述文件夹存放我们包的元数据(关于的详细讨论可以在这里找到)。最后, NAMSPACE 是一个确保我们的库与其他库很好地配合的文件,并且更多的是一个 CRAN 需求。

命名规格

命名 R 包时,我们必须遵循这些规则:

  • 曲柄上必须是唯一的(你可以在这里查看所有当前的 R 库);
  • 是否只能由字母数字句点组成
  • 不能包含下划线连字符**
  • 必须以字母**开始
  • 不能在周期结束

你可以在这里阅读更多关于命名包的内容。我们的包名“datapeek”通过了上述标准。让我们转向曲柄并执行命令+F* 搜索“数据检查”以确保它没有被占用:*

Command + F search on CRAN to check for package name uniqueness.

…看起来我们很好。

步骤 2:填写描述细节

文件的工作是存储关于我们包的重要元数据。这些数据包括运行我们的库所需的其他包,我们的许可证,以及我们的联系人信息。从技术上来说,R 中的包的定义是包含一个DESCRIPTION文件的任何目录,所以总是要确保它存在。

C 点击 JupyterLab 目录列表中描述文件上的 。您将看到我们运行devtools::create(“datapeek”)时自动创建的基本细节:

让我们添加我们的具体细节,以便我们的包包含必要的元数据。只需在 JupyterLab 中编辑这个文件。以下是我补充的细节:

  • 包装 : datapeek
  • 标题 : Provides useful functions for working with raw data.
  • 版本 : 0.0.0.1
  • 作者@R : person(“Sean”, “McClure”, email=”sean.mcclure@example.com”, role=c('aut','cre'))
  • 描述:data peek 包帮助用户转换用于机器学习开发的原始数据。
  • 取决于 : R (≥ 3.5.1)
  • 执照 : MIT
  • 编码 : UTF-8
  • LazyData : true

当然你应该用你自己的细节填写这些部分。你可以在哈德利关于元数据的章节中读到更多关于这些的定义。作为一个简单的概述…这些packagetitleversion部分是不言自明的,只要确保将* title 保持在一行Authors@R必须遵循你上面看到的格式,因为它包含可执行的 R 代码。注意角色参数,它允许我们列出本库的主要贡献者。常见的有:*

aut : 作者

cre : 创建者或维护者

ctb : 投稿人

cph : 版权所有者

还有更多的选项,完整列表见此处。

您可以通过将多个作者列为一个向量来添加他们:

*Authors@R: as.person(c("Sean McClure <sean.mcclure@example.com> [aut, cre]", "Rick Deckard <rick.deckard@example.com> [aut]","RachaelTyrell <rachel.tyrell@example.com> [ctb]"
))*

注意:如果你计划在 CRAN 上托管你的图书馆,确保你的电子邮件地址是正确的,因为 CRAN 会用这个联系你。

description可以是多行,限 1 段。我们使用depends来指定我们的包所依赖的 R 的最低版本。您应该使用与您用来构建库的版本相同或更高的 R 版本。今天大多数人把他们的License设置为 MIT,它允许任何人“使用、复制、修改、合并、出版、分发、再许可和/或出售软件的拷贝”,只要你的版权包括在内。你可以在这里了解更多关于麻省理工学院许可证的信息。Encoding确保我们的库可以使用现代解析器打开、读取和保存,而LazyData指的是如何加载我们包中的数据。因为我们将我们的设置为 true,这意味着我们的数据在被使用之前不会占用内存。

步骤 3:添加函数

3A:向 R 文件夹添加功能

我们的图书馆没有功能就没什么用。让我们添加本文开头提到的 4 个函数。下面的要点显示了我们在 R 中的 datapeek 函数:

我们必须将我们的函数添加到 R 文件夹,因为这是 R 在库中查找函数的地方。

***datapeek**
├── **R**
├── datapeek.Rproj
├── DESCRIPTION
├── NAMESPACE*

由于我们的库只包含 4 个函数,我们将把它们放入一个名为 utilities 的文件中。R ,这个文件位于 R 文件夹中。

进入 JupyterLab 中的目录,打开 R 文件夹。**点击启动器中的文本文件*** 并粘贴到我们的 4 R 函数中。右击该文件并重命名为 utilities.R。*

3B:导出我们的函数

仅仅将 R 函数放在我们的文件中是不够的。每个函数都必须导出才能向我们库的用户公开。这是通过在每个函数上方添加 @export 标签来实现的。

导出语法来自 Roxygen ,并确保我们的函数被添加到名称空间中。让我们将@export 标签添加到我们的第一个函数中:

对其余的函数也这样做。

注意 :在更大的库中,我们只导出需要在我们的包之外可用的函数。这有助于减少与另一个库冲突的机会。

3C:记录我们的功能

记录我们的功能很重要。文档功能为用户提供信息,这样当他们输入?datapeek时,他们就可以获得关于我们的包的细节。文档还支持使用小插图,这是一种长格式的文档。你可以在这里阅读更多关于记录函数的信息。

我们将采取 2 个子步骤:

  • 添加文档注释
  • 运行

—添加文档注释

文档被添加到我们的功能之上,直接在我们的#’ @export 行之上。下面是我们第一个函数的例子:

为了可读性,我们将这些行隔开,添加了标题、描述和函数使用的任何参数。让我们为我们的剩余功能这样做:

—运行 devtools::document()

将文档添加到我们的函数中,然后在根目录外的终端、中运行以下内容:

*devtools::document()*

注意:确保你在 datapeek 目录之外的一级。

您可能会得到错误:

*Error: ‘roxygen2’ >= 5.0.0 must be installed for this functionality.*

在这种情况下打开 JupyterLab 中的 端子并安装 roxygen2* 。您还应该安装 data.table 和 mltools,因为我们的第一个函数使用这些工具:***

*install.packages('roxygen2')
install.packages('data.table')
install.packages('mltools')*

再次运行devtools::document()。您应该看到以下内容:

这会生成。Rd 文件里面有一个新的人文件夹。你会注意到。Rd 文件是为我们包中的每个函数创建的。**

如果您查看您的描述文件,它现在会在底部显示一个新行:

这也将生成一个名称空间文件:

我们可以看到我们的 4 个功能已经暴露。现在让我们继续确保在我们的库中指定依赖关系。

步骤 4:列出外部依赖关系

我们的函数经常需要其他库中的函数。我们必须做两件事来确保外部功能对我们库的功能可用:

  1. 在我们的函数中使用 双冒号来指定我们所依赖的库;
  2. 导入添加到我们的描述文件中。

你会注意到,在上面的要点中,我们只是将我们的库列在了顶部。虽然这在独立的 R 脚本中工作得很好,但这不是在 R 包中使用依赖关系的方式。当创建 R 包时,我们必须使用" 双冒号方法 "来确保正确的函数被读取。这与 R 包中的“顶层代码”(不像函数那样是对象的代码)如何只在编译包时执行,而不是在加载包时执行有关。

例如:

***library(mltools)**do_something_cool_with_mltools <- function() {auc_roc(preds, actuals)
}*

…不起作用,因为auc_roc将不可用(运行库(datapeek)不重新执行库(mltools))。这个工作:

*do_something_cool_with_mltools <- function() {**mltools::**auc_roc(preds, actuals)
}*

我们的 datapeek 包中唯一需要额外包的函数是我们的第一个函数:

Using the double-colon approach to specify dependent packages in R.

注意每次我们调用一个外部函数时,我们都会在它前面加上外部库和双冒号。

我们还必须在我们的DESCRIPTION文件中列出外部依赖项,这样它们才能被正确处理。让我们 我们的导入添加到描述文件:

确保导入的库用逗号分隔。注意,我们没有为外部依赖项指定任何版本。如果我们需要指定版本,我们可以在包名后面使用括号:

*Imports:data.table (>= 1.12.0)*

由于我们的encode_and_bind函数没有利用任何最新的更新,我们将不对它指定任何版本。

步骤 5:添加数据

有时在我们的库中包含数据是有意义的。包数据可以让我们的用户练习我们的库的功能,也有助于测试,因为机器学习包总是包含摄取和转换数据的功能。将外部数据添加到 R 包的 4 个选项是:

  1. 二进制数据
  2. 解析的数据
  3. 原始数据
  4. 序列化数据

你可以在这里了解更多关于这些不同方法的信息。对于本文,我们将坚持使用最常见的方法,即将外部数据添加到 R 文件夹

让我们将虹膜数据集添加到我们的库中,以便为用户提供一种快速测试我们功能的方法。数据必须在中。rda 格式,使用 R 的**save()**函数创建,并具有与文件相同的名称。我们可以通过使用 devtools 的use_data函数来确保满足这些标准:

*x <- read.csv("[http://bit.ly/2HuTS0Z](http://bit.ly/2HuTS0Z')")
devtools::use_data(x, iris)*

在上面,我从 Iris 数据集的 URL 中读取它,并将数据帧传递给devtools::use_data()

在 JupyterLab 中,我们看到创建了一个新的数据文件夹,以及我们的 iris.rda 数据集:

***datapeek**
├── **data** └── iris.rda
├── **man**
├── **R** ├── datapeek.Rproj
├── DESCRIPTION
├── NAMESPACE*

在接下来的部分中,我们将使用我们添加的数据集来运行测试。

步骤 6:添加测试

测试是软件开发的一个重要部分。测试有助于确保我们的代码按预期工作,并使调试代码成为一个更快、更有效的过程。点击了解更多关于测试 R 包的信息。

测试中的一个常见挑战是知道我们应该测试什么。测试大型库中的每一个功能都很麻烦,而且并不总是需要,而测试不足会使发现和纠正出现的错误变得更加困难。

我喜欢马丁·福勒关于何时测试的下面这段话:

每当您想在 print 语句或调试器表达式中键入某些内容时,请将其编写为测试—马丁·福勒

如果您定期构建应用程序原型,您会发现自己经常向控制台写东西,看看一段代码是否返回您所期望的结果。在数据科学中,编写交互式代码甚至更常见,因为机器学习工作是高度实验性的。一方面,这提供了充分的机会来思考编写哪些测试。另一方面,机器学习代码的不确定性意味着测试 ML 的某些方面可能不那么简单。作为一般规则,寻找每次都应该返回相同输出的明显确定性代码段。

我们在数据科学中做的交互测试是手动,但是我们在我们的包中寻找的是自动测试。自动化测试意味着我们运行一套预定义的测试,以确保我们的包端到端地工作。

虽然在软件中有很多种测试,但这里我们主要讨论“单元测试”从单元测试的角度思考迫使我们将代码分解成更多的模块化组件,这是软件设计中的良好实践。

注意 :如果你习惯用 Python 这样的语言测试,注意 R 本质上更 functional (即方法属于函数而不是类),所以会有一些区别。

我们将采取 2 个子步骤来测试我们的 R 库:

6A :创建tests/testthat文件夹;

6B :写作测试。

— 6A: 创建 **tests/testthat** 文件夹

正如 R 希望我们的 R 脚本和数据放在特定的文件夹中一样,它也希望我们的测试也是如此。为了创建 tests 文件夹,我们在 JupyterLab 的 R 控制台中运行以下命令:

*devtools::use_testthat()*

您可能会得到以下错误:

*Error: ‘testthat’ >= 1.0.2 must be installed for this functionality.*

如果是这样的话,使用上面相同的方法在 Jupyter 的终端中安装 roxygen2。

*install.packages('testthat')*

运行devtools::use_testthat()将产生以下输出:

** Adding testthat to Suggests
* Creating `tests/testthat`.
* Creating `tests/testthat.R` from template.*

现在我们的主目录中会有一个新的测试文件夹:

***datapeek**
├── **data** ├── **man**
├── **R** ├── **tests** └── testthat.R├── datapeek.Rproj
├── DESCRIPTION
├── NAMESPACE*

上面的命令还在 tests 文件夹中创建了一个名为testthat.R的文件。当R CMD check运行时,它会运行所有的测试(我们很快就会看到)。您还会注意到test 在我们的DESCRIPTION文件中的建议下添加了:

— 6B:写作测试

test 这是 R 最流行的单元测试包,至少有 2600 个 CRAN 包使用,更不用说 Github 上的库了。你可以在 Tidyverse 页面这里查看关于 testthat 的最新消息。也可以查看它的文档。

我们需要考虑 3 个级别的测试:

  • 期望(断言):一次计算的预期结果;
  • 测试:将单个功能的多个期望,或者跨多个功能的相关功能组合在一起;
  • 文件:将多个相关测试组合在一起。文件被赋予一个人类可读的名称context().

断言

断言是我们选择的测试库中包含的函数。我们使用断言来检查我们自己的函数是否返回预期的输出。断言有多种风格,这取决于被检查的内容。在接下来的部分,我将介绍 R 编程中使用的主要测试,展示每一个失败的测试,这样你就可以理解它是如何工作的。

相等断言断言****

  • expect_equal()
  • expect_identical()
  • expect_equivalent
***# **test for** **equality**
a <- 10
expect_equal(a, 14)> Error: `a` not equal to 14.# **test for identical** 
expect_identical(42, 2)> Error: 42 not identical to 2.# **test for equivalence** 
expect_equivalent(10, 12)> Error: 10 not equivalent to 12.***

上面的例子之间有细微的差别。例如,expect_equal用于检查在数值公差内是否相等,而expect_identical用于测试是否完全相等。以下是一些例子:****

***expect_equal(10, 10 + 1e-7) # true
expect_identical(10, 10 + 1e-7) # false***

随着你写更多的测试,你会明白什么时候使用每一个。当然,如有疑问,请参考上述文件。

测试字符串是否匹配****

  • expect_match()
***# **test for string matching**
expect_match("Machine Learning is Fun", "But also rewarding.")> Error: "Machine Learning is Fun" does not match "But also rewarding.".***

测试长度****

  • expect_length
***# **test for length** 
vec <- 1:10
expect_length(vec, 12)> Error: `vec` has length 10, not length 12.***

比较测试

  • expect_lt
  • expect_gt
***# **test for less than**
a <- 11
expect_lt(a, 10)> Error: `a` is not strictly less than 10\. Difference: 1# **test for greater than**
a <- 11
expect_gt(a, 12)> Error: `a` is not strictly more than 12\. Difference: -1***

测试逻辑****

  • expect_true
  • expect_false
***# **test for** **truth** 
expect_true(5 == 2)> Error: 5 == 2 isn't true.# **test for** **false** 
expect_false(2 == 2)> Error: 2 == 2 isn't false.***

测试输出****

  • expect_output
  • expect_message
***# **testing for outputs** 
expect_output(str(mtcars), "31 obs")> Error: `str\(mtcars\)` does not match "31 obs".# **test for warning** 
f <-function(x) {if(x < 0) {message("*x* is already negative")}
}expect_message(f(1))> Error: `f(1)` did not produce any messages.***

testthat 库中包含了更多。如果你是测试新手,开始写一些简单的来适应这个过程。随着时间的推移,你会对测试什么和何时测试有一个直觉。

写作测试

一个测试是一组断言。我们在 tests 中编写如下测试:**

*****test_that**("this functionality does what it should", {// group of assertions here
})***

我们可以看到我们既有描述(测试名称)又有代码(包含断言)。描述完成了句子,“测试那个…”**

上面,我们说“测试这个功能做了它应该做的事情。”**

断言是我们想要测试的输出。例如:

*****test_that**("trigonometric functions match identities", {expect_equal(sin(pi / 4), 1 / sqrt(2))expect_equal(cos(pi / 4), 1 / sqrt(10))expect_equal(tan(pi / 4), 1)})> Error: Test failed: 'trigonometric functions match identities'***

:结合我们的测试文件,需要考虑内聚和耦合之间的*衡。正如 Hadley 在书中所说,“这两个极端显然是不好的(所有测试在一个文件中,每个测试一个文件)。你需要找到一个适合你的快乐的媒介。一个好的起点是为每个复杂的功能准备一个测试文件。”

创建文件

我们在测试中做的最后一件事是创建文件。如上所述,测试中的“文件”是一组覆盖相关功能集的测试。我们的测试文件必须位于tests/testthat/目录中。下面是 GitHub 上的 stringr 包的测试文件示例:

Example Test File from the stringr package on GitHub.

这个文件叫做测试用例。r(以“test”开头)位于tests/testthat/目录中。顶部的上下文只允许我们提供文件内容的简单描述。当我们运行测试时,它会出现在控制台中。**

让我们创建我们的测试文件,它将包含与我们的 4 个函数相关的测试和断言。像往常一样,我们在 Launcher 中使用 JupyterLab 的文本文件来创建和重命名一个新文件:**

Creating a Test File in R

现在让我们添加我们的测试:

对于第一个函数,我将确保返回具有正确特征数量的数据帧:**

注意我们如何调用我们的encode_and_bind函数,然后简单地检查维度和预期输出之间的相等性。我们在任何时候运行我们的自动化测试,以确保我们的测试文件运行,并且我们得到预期的输出。在控制台中运行devtools::test()运行我们的测试:

我们也得到了一个笑脸!

由于我们的第二个函数删除了一个指定的特征,我将使用与上面相同的测试,检查返回的框架的尺寸。我们的第三个函数将指定的函数应用到选择的列,所以我将编写一个测试来检查给定指定函数的结果。最后,我们的第四个函数返回最接*的匹配字符串,所以我将简单地检查返回的字符串以获得预期的结果。**

以下是我们的完整测试文件:

注意 :注意测试文件中数据的相对路径。

测试我们的包

如上所述,我们使用以下命令运行测试:

***devtools::test()***

这将运行我们放在 testthat 目录中的任何测试文件中的所有测试。让我们来看看结果:

我们在 4 个单元测试中有 5 个断言,放在一个测试文件中。看来我们没事了。如果我们的任何测试失败,我们将在上面的打印输出中看到这一点,在这一点上,我们将寻求纠正问题。

步骤 7:创建文档

这通常是通过在 R 中使用“Vignettes”来完成的。你可以在这里了解如何为你的 R 包创建 R vignettes。就我个人而言,我认为这是一种过时的文档方法。我更喜欢用类似于狮身人面像或者 T21 的东西。文档应该很容易共享搜索托管

点击 julepcode.com 大学的问号,了解如何使用 Julep。

我为我们的 R datapeek 库创建并托管了一些简单的文档,你可以在这里找到。

当然我们也会在 GitHub 上有这个库,我会在下面介绍。

第八步:共享你的 R 库

正如我在引言中提到的,我们应该定期创建库,这样其他人就可以受益于并扩展我们的工作。最好的方法是通过 GitHub ,这是开源软件项目分发和协作的标准方式。

如果您是 GitHub 的新手,这里有一个快速教程可以帮助您入门,这样我们就可以将我们的 datapeek 项目推到远程 repo。

注册/登录 GitHub 并 创建一个新的库

…这将为我们提供通常的屏幕:

使用我们的远程回购设置,我们可以在我们的机器上初始化我们的本地回购,并发送我们的第一个提交。**

打开 JupyterLab 中的终端,进入 datapeek 目录:

初始化本地 repo :

***git init***

添加远程原点(您的链接会有所不同):

***git remote add origin [https://github.com/sean-mcclure/datapeek.git](https://github.com/sean-mcclure/datapeek.git)***

现在运行git add .将当前目录和所有子目录下所有修改的和新的(未跟踪的)文件添加到 staging 区域:

***git add .***

不要忘记上面命令中的“点”。现在我们可以提交我们的更改,这将任何新代码添加到我们的本地回购中。**

但是,由于我们在 Docker 容器中工作,与我们的本地回购相关联的用户名电子邮件不能被自动检测。我们可以通过在终端中运行以下命令来设置****:****

*****git config --global user.email {emailaddress}
git config --global user.name {name}*****

使用您用来登录 GitHub 的电子邮件地址和用户名。

现在我们可以承诺:

*****git commit -m 'initial commit'*****

提交新代码后,我们可以进行推送,将最后一次提交转移到我们的 remote repo:

*****git push origin master*****

注意 :因为我们在 Docker 中,你可能会再次被要求认证。出现提示时,只需添加您的 GitHub 用户名和密码。然后再次运行上面的命令。****

一些读者会注意到我们没有在目录中放置一个.gitignore文件。将所有文件放入较小的 R 库中通常没问题。对于更大的库,或者包含大型数据集的库,你可以使用站点 gitignore.io 来看看常见的 gitignore 文件是什么样子的。这里是一个用于 R 的通用 R .gitignore 文件:

Example .gitignore file for an R package

概括地说,git add 将当前目录中所有修改过的和新的(未跟踪的)文件添加到 staging 区域。提交将任何更改添加到我们的本地回购,而推送将最后的提交转移到我们的远程回购。虽然git add可能看起来是多余的,但它存在的原因是因为有时我们只想提交某些文件,这样我们可以有选择地存放文件。上面,我们通过在git add后使用“点”来暂存所有的文件。****

你可能还注意到我们没有包括一个自述文件。您确实应该包括这一点,但是为了简洁起见,我省略了这一步。****

现在,任何人都可以使用我们的库。👍让我们看看怎么做。****

步骤 9:安装你的 R 库

正如在引言中提到的,我不会在本文中讨论 CRAN。坚持使用 GitHub 使得频繁共享我们的代码变得更加容易,并且我们总是可以在以后添加 CRAN 标准。

要从 GitHub 安装一个库,用户只需在本地机器上运行以下命令:

*****devtools::install_github("yourusername/mypackage")*****

因此,我们可以简单地指示希望使用 datapeek 的其他人在他们的本地机器上运行以下命令:

*****devtools::install_github("sean-mcclure/datapeek")*****

这是我们将包含在自述文件和/或我们创建的任何其他文档中的内容。这将像我们从 CRAN 获得的任何其他软件包一样安装我们的软件包:

然后,用户像往常一样加载库,一切就绪:

*****library(datapeek)*****

我建议在一个新的 R 环境中尝试上述命令,以确认新库的安装和加载符合预期。

用 PYTHON 创建库

创建 Python 库遵循与我们之前看到的 r 相同的高级步骤。我们需要一个基本的目录结构和适当的命名约定,函数描述导入,指定依赖关系,添加数据集文档,以及能够共享并允许其他人安装我们的库****

我们将使用 JupyterLab 来构建我们的 Python 库,就像我们对 r。

库 vs 包 vs 模块

在本文的开始,我讨论了“库”和“包”之间的区别,以及我是如何喜欢交替使用这些术语的。这同样适用于 Python 库。"模块"是另一个术语,在 Python 中简单地指任何包含 Python 代码的文件。Python 库显然包含作为脚本的模块。****

在我们开始之前:

我在介绍中说过,我们将在 GitHub 上托管和安装我们的库。这鼓励了库的快速创建和共享,而不会因为在流行的 R 和 Python 包托管站点上发布标准而陷入困境。

Python 最流行的托管站点是 Python 包索引( PyPI )。这里是寻找安装发布* python 库的地方。每当您运行pip install <package_name>(或easy_intall)时,您都会从 PyPI 获取一个包。*****

虽然我们不会讨论在 PyPI 上托管我们的包,但是看看我们的库名是否是唯一的还是一个好主意。这将最大限度地减少与其他流行 Python 库的混淆,并提高我们的库名与众不同的可能性,如果有一天我们决定在 PyPI 上托管它的话。

首先,我们应该遵循一些 Python 库的命名约定。

Python 库命名约定

  • ****全部用小写
  • 让名字在 PyPI 上唯一(在 PyPI 上搜索名字)****
  • 没有连字符(可以用下划线分隔单词)****

我们的库名是 datapeek ,所以满足第一个和第三个标准;让我们检查 PyPI 的唯一性:

一切都好。👍

我们现在已经准备好完成创建 Python 库所需的每个步骤。

步骤 1:创建包框架

JupyterLab 应按照本文设置部分中的说明启动并运行。

使用 JupyterLab 的新文件夹文本文件选项创建以下目录结构文件:****

*******datapeek**
├── **datapeek**└── __init__.py└── utilities.py
├── setup.py*****

: 粗体名称为文件夹浅色名称为文件。我们将把内部* datapeek 文件夹称为“模块目录”,把外部 datapeek 目录称为“根目录”。*****

下面的视频展示了我在 JupyterLab 中创建 datapeek 目录的过程:

有些文件我们不想提交给源代码管理。这些文件是由 Python 构建系统创建的。照此,我们也把加上下面的。gitignore 文件到我们的包框架:****

:在撰写本文时,JupyterLab 缺少在浏览器中切换隐藏文件的前端设置。因此,我们将简单地把我们的文件命名为 gitignore(前面没有点);在推送到 GitHub 之前,我们会把它改成一个隐藏文件。

将你的 gitignore 文件作为一个简单的文本文件添加到根目录:

*******datapeek**
├── **datapeek**└── __init__.py└── utilities.py
├── setup.py
├── gitignore*****

步骤 2:填写描述细节

正如我们对 R 所做的一样,我们应该添加关于我们新库的元数据。我们使用设置工具来完成这项工作。Setuptools 是一个 Python 库,旨在方便打包 Python 项目。****

打开 setup.py 并为我们的库添加以下详细信息:

当然,您应该将创作更改为您自己的创作。稍后我们将向该文件添加更多的细节。这些关键字是不言自明的。url是我们项目在 GitHub 上的 URL,后面会添加;除非您已经创建了 python repo,在这种情况下,现在添加 URL。我们在 R 部分讨论了许可。zip_safe简单地说,我们的包可以作为一个 zip 文件安全地运行,这是通常的情况。你可以在这里了解更多关于可以添加到 setup.py 文件的内容。

步骤 3:添加函数

我们的库显然需要函数有用。对于更大的库,我们将组织我们的模块以*衡内聚/耦合,但是因为我们的库很小,我们将简单地把所有的函数放在一个文件中。

我们将添加与 R 相同的函数,这次是用 Python 编写的:

****这些函数添加到utilities.py模块,在 datapeek 的模块目录中。

步骤 4:列出外部依赖关系

我们的库经常需要其他包作为依赖关系。当安装我们的库时,我们用户的 Python 环境需要知道这些(所以也可以安装这些其他的包)。 Setuptools 提供了install_requires关键字来列出我们的库所依赖的任何包。

我们的 datapeek 库依赖于用于模糊字符串匹配的 fuzzywuzzy 包和用于数据结构高性能操作的 pandas 包。要指定我们的依赖关系*,请将以下内容添加到您的 setup.py 文件中:*******

*****install_requires=['fuzzywuzzy','pandas'
]*****

您的 setup.py 文件当前应该如下所示:

我们可以通过在 JupyterLab 终端会话中运行以下命令来确认一切正常:

*****python setup.py develop*****

注意 :在 datapeek 的根目录下运行这个。

运行该命令后,您应该会看到类似这样的内容:

…结尾写道:

Finished processing dependencies for datapeek==0.1

如果我们的一个或多个依赖项在 PyPI 上不可用,但在 Github 上可用(例如,一个尖端的机器学习包只在 GitHub 上可用…或者它是我们团队的另一个库,只托管在 GitHub 上),我们可以在设置调用中使用dependency_links:

*****setup(...dependency_links=['http://github.com/user/repo/tarball/master#egg=package-1.0'],...
)*****

如果要添加额外的元数据,比如状态许可语言版本等。我们可以这样使用classifiers:****

*****setup(...classifiers=['Development Status :: 3 - Alpha','License :: OSI Approved :: MIT License','Programming Language :: Python :: 2.7','Topic :: Text Processing :: Linguistic',],...
)*****

要了解更多关于可以添加到 setup.py 文件中的不同分类器的信息,请参见这里的。

步骤 5:添加数据

正如我们在 R 中所做的一样,我们可以将数据添加到我们的 Python 库中。在 Python 中,这些文件被称为非代码文件,可以包括图像数据文档等。****

我们将数据添加到我们库的模块目录中,这样任何需要这些数据的代码都可以使用来自消费模块的__file__变量的相对路径****

让我们将虹膜数据集添加到我们的库中,以便为用户提供一种快速测试我们功能的方法。首先,使用 JupyterLab 中的新建文件夹按钮在模块目录下新建一个名为 data* 的文件夹:*****

*******datapeek**
├── **datapeek**└── __init__.py└── utilities.py└── **data**
├── setup.py
├── gitignore*****

…然后在名为 iris.csv 的数据文件夹中创建一个新的文本文件,并且*将中的数据粘贴到新文件中。*******

如果您关闭并打开新的 csv 文件,它将在 JupyterLab 中以适当的表格形式呈现:

CSV file rendered in JupyterLab as formatted table.

我们使用一个MANIFEST.in文件来指定非代码文件。创建另一个名为MANIFEST.in的文本文件,将其放入根文件夹:****

*******datapeek**
├── **datapeek**└── __init__.py└── utilities.py└── **data**
├── MANIFEST.in
├── setup.py
├── gitignore*****

…然后将这一行添加到文件中:****

*****include datapeek/data/iris.csv*****

:manifest . in 通常不需要,但为了完整起见包含在本教程中。更多讨论见此处。

我们还需要在 setup.py 中包含下面一行:****

*****include_package_data=True*****

我们的 setup.py 文件现在应该如下所示:

步骤 6:添加测试

与我们的 R 库一样,我们应该添加测试,以便其他人可以扩展我们的库,并确保他们自己的函数不会与现有代码冲突。添加一个测试文件夹到我们库的模块目录:****

*******datapeek**
├── **datapeek**└── __init__.py└── utilities.py└── **data** └── **tests**├── MANIFEST.in
├── setup.py
├── gitignore*****

我们的测试文件夹应该有自己的__init__.py文件以及测试文件本身。创建那些现在使用 JupyterLab 的文本文件选项:****

*******datapeek**
├── **datapeek**└── __init__.py└── utilities.py└── **data** └── **tests** └──__init__.py└──datapeek_tests.py
├── MANIFEST.in
├── setup.py
├── gitignore*****

我们的 datapeek 目录结构现在被设置为存放测试函数,我们现在将编写这些函数。

写作测试

用 Python 编写测试类似于用 r 编写测试。断言用于检查本库函数产生的预期输出。我们可以使用这些“单元测试来检查各种期望的输出,这取决于什么可能会失败。例如,我们可能希望确保返回一个数据帧,或者在某种已知的转换后返回正确的列数。

我将为我们的 4 个函数添加一个简单的测试。请随意添加您自己的测试。思考应该检查什么,并记住马丁·福勒在本文 R 部分引用的话。

我们将使用 Python 中流行的单元测试框架****

单元测试添加到 datapeek_tests.py 文件中,确保单元测试和 datapeek 库被导入:

为了运行这些测试,我们可以使用 Nose ,它扩展了 unittest,使测试更加容易。使用 JupyterLab 中的终端会话安装* 机头;*****

***$ pip install nose***

我们还需要向 setup.py 添加以下几行:**

***setup(...**test_suite='nose.collector',tests_require=['nose'],**
)***

我们的 setup.py 现在应该是这样的:

从根目录运行以下命令来运行我们的测试:

***python setup.py test***

如果需要,Setuptools 将负责安装 nose 并运行测试套件。运行上述程序后,您应该会看到以下内容:

我们所有的测试都通过了!

如果任何测试失败,unittest 框架将显示哪些函数没有通过。此时,检查以确保您正确地调用了函数,并且输出确实是您所期望的。故意先写测试失败的代码,然后写你的函数直到它们通过,这也是一个很好的实践。

步骤 7:创建文档

正如我在 R 部分提到的,我使用 Julep 来快速创建可共享和可搜索的文档。这避免了编写晦涩的注释,并提供了立即托管我们的文档的能力。当然,这并不像其他文档那样附带 IDE 挂钩,但是对于快速交流来说,它是有效的。

你可以在这里找到我为这个库创建的文档。

步骤 8:共享你的 Python 库

共享 python 库的标准方法是通过 PyPI。正如我们没有介绍 R 中的 CRAN 一样,我们也不会介绍在 PyPI 上托管我们的库。虽然要求比 CRAN 少,但要在 PyPI 上成功托管,仍然需要采取许多步骤。在 GitHub 之外的站点上托管所需的步骤可以在以后添加。

开源代码库

我们在 R 小节中介绍了向 GitHub 添加项目的步骤。同样的步骤也适用于此。

我在上面提到需要重命名我们的 gitignore 文件使其成为一个隐藏文件。您可以在终端中运行以下命令:**

***mv gitignore .gitignore***

您会注意到这个文件在我们的 JupyterLab 目录中不再可见(它最终会消失)。由于 JupyterLab 仍然缺乏切换隐藏文件的前端设置,因此只需随时在终端中运行以下命令即可查看隐藏文件:

***ls -a*** 

如果我们需要在 JupyterLab 中查看/编辑该文件,我们可以通过运行以下命令使其再次可见:

***mv .gitignore gitignore***

这里有一个关于将我们的库推送到 GitHub 的快速回顾(将 git URL 改为你自己的):

  • 在 GitHub 上创建一个名为 datapeek_py 的新 repo
  • 使用git init初始化你的库的目录
  • 使用您的 GitGub 电子邮件和用户名(如果使用 Docker)配置您的本地回购:
***git config --global user.email {emailaddress}
git config --global user.name {name}***
  • 使用 git remote add origin [https://github.com/sean-mcclure/datapeek_py.git](https://github.com/sean-mcclure/datapeek_py.git)添加您的新远程原点
  • 阶段你的图书馆使用git add .
  • 使用git commit -m ‘initial commit’提交所有文件
  • 使用git push origin master您的库推送到远程 repo(出现提示时进行身份验证)

现在,任何人都可以使用我们的 python 库。👍让我们看看怎么做。**

步骤 9:安装 Python 库

虽然我们通常使用以下命令安装 Python 库:

***pip install <package_name>***

…这需要在 PyPI 上托管我们的库,正如上面解释的,这超出了本文的范围。相反,我们将学习如何从 GitHub 安装我们的 Python 库,就像我们对 r 所做的那样。这种方法仍然需要pip install命令,但是使用 GitHub URL 而不是包名。

从 GitHub 安装我们的 Python 库

我们的库托管在 GitHub 上,我们只需使用pip install git+,后跟 GitHub repo 上提供的 URL(可通过点击 GitHub 网站上的克隆或下载按钮获得):**

***pip install git+https://github.com/sean-mcclure/datapeek_py***

现在,我们可以将我们的库导入到 Python 环境中。对于单一功能:**

***from datapeek.utilities import encode_and_bind***

…对于所有功能:**

***from datapeek.utilities import ****

让我们在新的 Python 环境中做一个快速检查,以确保我们的函数可用。创建一个新的 Docker 容器,我运行以下代码:

获取数据集:

***iris = pd.read_csv('[https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv'](https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv'))***

检查功能:

*****encode_and_bind**(iris, 'species')***

*****remove_features**(iris, ['petal_length', 'petal_width'])***

*****apply_function_to_column**(iris, ['sepal_length'], 'times_4', 'x*4')***

*****get_closest_string**(['hey there','we we are','howdy doody'], 'doody')***

成功!

摘要

在本文中,我们研究了如何使用运行在 Docker 容器中的 JupyterLab 来创建 R 和 Python 库。Docker 允许我们利用 Docker 栈,这样我们的环境很容易控制,并且可以使用公共包。这也使得使用相同的高级接口通过浏览器为 2 种不同的语言创建库变得容易。因为我们在 Docker 中装入了一个卷,所以所有的文件都被写到我们的本地机器上。

创建库对于任何机器学习从业者来说都是一项关键技能,我也鼓励其他人经常这么做。库有助于将我们的工作隔离在有用的抽象中,提高可再现性,使我们的工作可共享,并且是设计更好软件的第一步。使用轻量级的方法确保我们可以快速地构建原型和共享,并根据需要选择添加更详细的实践和发布标准。

一如既往,如果你遇到问题,请在评论区提出问题。快乐编码。**

如果你喜欢这篇文章,你可能也会喜欢:

*** [## 学习建立机器学习服务,原型真实的应用程序,并部署您的工作…

在这篇文章中,我将向读者展示如何将他们的机器学习模型公开为 RESTful web 服务,原型真实…

towardsdatascience.com](/learn-to-build-machine-learning-services-prototype-real-applications-and-deploy-your-work-to-aa97b2b09e0c) [## 用 D3.js 从玩具视觉过渡到真实应用

我们经常孤立地学习技术和方法,与数据科学的真正目标脱节;至…

towardsdatascience.com](/combining-d3-with-kedion-graduating-from-toy-visuals-to-real-applications-92bf7c3cc713) [## 机器学习工作流的 GUI 化:快速发现可行的流水线

前言

towardsdatascience.com](/gui-fying-the-machine-learning-workflow-towards-rapid-discovery-of-viable-pipelines-cab2552c909f)

进一步阅读和资源

  • 哈雷·威克姆的 R 包
  • 哈德利·韦翰的测试
  • Scott Torborg 的 Python 打包
  • Jupyter 数据科学笔记本
  • Docker —定位和设置
  • JupyterLab 文档
  • 按发布日期列出的可用起重机包
  • 记录 R 中的功能
  • 七月
  • gitignore.io
  • Python 包索引
  • 设置工具文档
  • GitHub 上的虹膜数据集
  • 单元测试—维基百科文章
  • unitest——一个单元测试框架
  • Nose——Python 更好的测试
  • 测试驱动开发—维基百科上的文章
  • 对接器运行参考***

安装 Tensorflow 2 的分步指南

原文:https://towardsdatascience.com/step-by-step-guide-to-install-tensorflow-2-0-67bc73e79b82?source=collection_archive---------12-----------------------

由于其易用性、效率和交叉兼容性,TensorFlow 2 将改变深度学习的格局。在这里,我们将学习安装和设置它。我们还将使用 TensorFlow 2 实现 MNIST 分类。

<了解深度学习,了解更多> >

TensorFlow 2 将改变深度学习的格局。它制造了,

  • 模型构建更简单,
  • 任何*台上的生产部署都更加健壮,并且
  • 支持强大的研究实验。

有了这些,深度学习将在研究和工业的各个领域变得更加主流。

TensorFlow 2 中集成了 Keras API。Keras 是一个极其流行的高级 API,用于构建和训练深度学习模型。在前进之前,重要的是要知道,

  • TensorFlow 1.x 也支持 Keras,但在 2.0 中,Keras 与 TensorFlow *台的其余部分紧密集成。2.0 正在提供一个单个高级 API,以减少混乱并支持高级功能。
  • 现在普遍使用的 Keras 是一个独立的开源项目,位于www . Keras . io(2019 年 6 月)。然而,Keras 是一个 API 规范,现在在 TensorFlow 中也可以使用(详见[ 1 )。

推荐阅读[ 1 ]和[ 2 ]了解更多 TensorFlow 2.0 的好处。总之,TF 2.0 带来了易实施性以及巨大的计算效率,并与任何*台兼容,如 Android、iOS 和嵌入式系统,如 Raspberry Pi 和 Edge TPUs。

以前实现这些目标很困难,需要投入时间寻找替代方法。由于 TensorFlow 2 已经带来了所有这些,因此尽快迁移到它是势在必行的。

为此,我们将在这里学习安装和设置 TensorFlow 2.0。

先决条件

选项 1: Python 3.4+通过 Anaconda

Anaconda with Jupyter 提供了一种更简单的方法来安装和使用 Python。

安装 Anaconda 相对简单。关注最新 Python 3.4+的链接:https://jupyter.org/install

类似于pip,对于 Anaconda,我们有conda来创建虚拟环境和安装包。

选项 2: Python(没有 Anaconda)

a .安装 Python 3.4+

检查您的当前版本。

$ python --version

或者,

$ python3 --version

我在 Mac 上有不同的 Python(Python 3.6 在 Anaconda 上)和 Ubuntu (Python 3.7)。我在上面看到的输出是,

Python 3.6.8 :: Anaconda custom (x86_64)*# Mac*Python 3.7.1*# Ubuntu*

无论是 Anaconda 中的 Python 还是其他都可以。

如果你的版本是不是 3.4+,安装如下。

$ brew update
$ brew install python *# Installs Python 3*$ sudo apt install python3-dev python3-pip

b .安装 virtualenv

virtualenv需要创建一个虚拟环境。其要求将在下一节中解释。

Mac OS

$ sudo pip3 install -U virtualenv*# system-wide install*

Ubuntu

$ sudo pip3 install -U virtualenv*# system-wide install*

: pip(代替pip3)有时也会用到。如果两者之间不确定,使用pip3。你用pip3不会出错。如果您想知道是否可以使用pip,请运行以下命令

$ pip3 --version
pip 19.1.1 from /Users/inferno/anaconda/lib/python3.6/site-packages/pip (python 3.6)$ pip --version
pip 19.1.1 from /Users/inferno/anaconda/lib/python3.6/site-packages/pip (python 3.6)

在我的系统中,pippip3的版本是一样的。因此,我可以使用其中任何一个。

在下文中,我们将研究这两种方法的安装步骤。

第一步。用 Python 创建一个虚拟环境。

我们为什么想要虚拟环境?

虚拟环境是 Python 项目的隔离环境。在虚拟环境中,我们可以拥有一组完全独立的包(依赖项)和设置,它们不会与其他虚拟环境中的任何东西或默认的本地 Python 环境相冲突。

这意味着我们可以保留同一个包的不同版本,例如,我们可以对一个项目使用 scikit-learn 0.1,而对同一系统上不同虚拟环境中的另一个项目使用 scikit-learn 0.22。

实例化虚拟环境

Ubuntu/Mac(没有 Anaconda 的 Python)

$ virtualenv --system-site-packages -p python3 tf_2

上面的命令将创建一个虚拟环境tf_2。理解命令,

  • virtualenv将创建一个虚拟环境。
  • --system-site-packages允许虚拟环境中的项目tf_2访问全局站点包。默认设置不允许此访问(--no-site-packages以前用于此默认设置,但现在已弃用。)
  • -p python3用于设置tf_2的 Python 解释器。如果virtualenv是和 Python3 一起安装的,这个参数可以跳过。默认情况下,这是虚拟环境的 python 解释器。将 Python3.x 设置为解释器的另一个选项是$ virtualenv --system-site-packages --python=python3.7 tf_2。这提供了更多的控制。
  • tf_2是我们创建的虚拟环境的名字。这将在虚拟环境的位置创建一个物理目录。这个/tf_2目录包含 Python 编译器的副本和我们稍后将安装的所有包。

Ubuntu/Mac 上的 Conda(来自 Anaconda 的 Python)

如果您使用 Conda,您可以创建虚拟环境,

$ conda create -n tf_2

上面的命令也将创建一个虚拟环境tf_2。与以前不同,我们不需要安装不同的软件包来创建虚拟环境。内置的conda命令提供了这一点。

理解命令,

  • conda可用于创建虚拟环境、安装包、列出环境中已安装的包等。简而言之,conda执行pipvirtualenv执行的操作。然而,conda并不取代pip,因为有些封装在pip上可用,而在conda上不可用。
  • create用于创建虚拟环境。
  • -n是专用于create的参数。-n用于命名虚拟环境。n的值,即环境名,这里是tf_2
  • 其他有用的论据:类似于virtualenv中的--system-site-packages,可以使用--use-local

第二步。激活虚拟环境。

激活虚拟环境。

Ubuntu/Mac(没有 Anaconda 的 Python)

$ source tf_2/bin/activate

Ubuntu/Mac 上的 Conda(来自 Anaconda 的 Python)

$ conda activate tf_2

激活后,终端将变为此(tf_2) $

第三步。安装 TensorFlow 2.0。

以下说明对于这两个 Python 选项是相同的。

在开始 TensorFlow 安装之前,我们将更新pip

(tf_2) $ pip install --upgrade pip

现在,安装 TensorFlow。

(tf_2) $ pip install --upgrade tensorflow==2.0.0-beta1

上面的tensorflow参数安装了一个 2.0.0-beta1 的纯 CPU 版本。

从 https://www.tensorflow.org/install/pip选择合适的 TensorFlow 版本。

在写这篇文章的时候,我们有 tensorflow 2.0.0-beta1。这是推荐的。根据我们的要求,我们可以将参数更改为以下之一。

  • tensorflow==2.0.0-beta1-仅针对 CPU 的 TF 2.0 Beta 版本预览(推荐)。
  • tensorflow-gpu==2.0.0-beta1-用 GPU 支持预览 TF 2.0 Beta 版本。
  • tensorflow-CPU 专用的最新稳定版本
  • tensorflow-gpu-支持 GPU 的最新稳定版本。
  • tf-nightly-仅针对 CPU 预览每夜构建。
  • tf-nightly-gpu-借助 GPU 支持预览每夜构建。

注意:对于 conda,我们也将使用 **pip install** 。TensorFlow 不具备 **conda**

第四步。测试安装。

要通过终端快速测试安装,请使用

(tf_2) $ python -c "import tensorflow as tf; x = [[2.]]; print('tensorflow version', tf.__version__); print('hello, {}'.format(tf.matmul(x, x)))"

输出将是(忽略系统消息),

tensorflow version 2.0.0-beta1
hello, [[4.]]

注意 TensorFlow 版本输出。如果它不是您安装的版本(在本例中是 2.0.0-beta1),那么一定有问题。最有可能的情况是,之前安装了 TensorFlow 和/或当前安装失败。

TensorFlow 2.0 示例

我们将使用 MNIST ( fashion_mnist) 图像分类示例来测试和学习 TensorFlow 2.0。

**import** **matplotlib.pyplot** **as** **plt****import** **tensorflow** **as** **tf**
layers = tf.keras.layers**import** **numpy** **as** **np**print(tf.__version__)

确保tf.__version__输出 2.x。如果版本较旧,检查安装或虚拟环境。

tf开放数据集中下载 fashion_mnist 数据并进行预处理。

mnist = tf.keras.datasets.fashion_mnist(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

为了熟悉这些数据,我们将从中绘制几个例子。

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']plt.figure(figsize=(10,10))
**for** i **in** range(25):plt.subplot(5,5,i+1)plt.xticks([])plt.yticks([])plt.grid(**False**)plt.imshow(x_train[i], cmap=plt.cm.binary)plt.xlabel(class_names[y_train[i]])
plt.show()

现在,我们将逐层构建模型

model = tf.keras.Sequential()
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)

请注意,该模型仅用于演示,因此仅在五个时期进行训练。

我们现在将根据测试数据测试模型的准确性。

model.evaluate(x_test, y_test)

我们将想象其中一个预测。我们将使用[ 3 中的一些 UDF。

**def** plot_image(i, predictions_array, true_label, img):predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]plt.grid(**False**)plt.xticks([])plt.yticks([])plt.imshow(img, cmap=plt.cm.binary) predicted_label = np.argmax(predictions_array)**if** predicted_label == true_label:color = 'blue'**else**:color = 'red'plt.xlabel("**{}** **{:2.0f}**% (**{}**)".format(class_names[predicted_label],100*np.max(predictions_array),class_names[true_label]),color=color)**def** plot_value_array(i, predictions_array, true_label):predictions_array, true_label = predictions_array[i], true_label[i]plt.grid(**False**)plt.xticks([])plt.yticks([])thisplot = plt.bar(range(10), predictions_array, color="#777777")plt.ylim([0, 1]) predicted_label = np.argmax(predictions_array)thisplot[predicted_label].set_color('red')thisplot[true_label].set_color('blue')

我们将为测试图像找到预测,即每个图像属于 10 个类别中的每一个的概率。

predictions = model.predict(x_test)i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, y_test, x_test)
plt.subplot(1,2,2)
plot_value_array(i, predictions, y_test)
plt.show()

正如我们在上面的图中看到的,“踝靴”的预测概率是最高的。为了进一步确认,我们将预测的标签输出为,

predicted_label = class_names[np.argmax(predictions[0])]
print('Actual label:', class_names[y_test[0]]) 
print('Predicted label:', predicted_label)

第五步。停用虚拟环境

在关闭之前,我们将停用虚拟环境。

virtualenv使用,

(tf_2) $ deactivate

conda使用,

(tf_2) $ conda deactivate

在 TensorFlow 2.0 上有 MNIST 例子的 GitHub 库在这里是。

结论

  • TensorFlow 2.0 带来了 keras API 的易用功能,例如逐层建模。
  • 我们学习了安装 TensorFlow 2.0。
  • 我们用 TF 2.0 完成了一个真实的 MNIST 数据分类示例。

参考

  1. Keras 标准化:TensorFlow 2.0 中的高级 API 指南
  2. tensor flow 2.0 中的新功能
  3. 训练你的第一个神经网络:基本分类

本帖原帖发布于 2019 年 6 月 13 日medium.com**

使用 Keras 预训练模型的简单指南

原文:https://towardsdatascience.com/step-by-step-guide-to-using-pretrained-models-in-keras-c9097b647b29?source=collection_archive---------5-----------------------

Image by Wendy

Keras 包含 10 个用于图像分类的预训练模型,这些模型是在 Imagenet 数据上训练的。Imagenet 是一个包含 1000 种图像的大型图像数据集合。这些预训练的模型能够对落入这 1000 个图像类别中的任何图像进行分类。

本指南将涵盖以下概念。

  • 图像分类车型。
  • 在 Keras 中使用经过预训练的型号。
  • 将我们自己的分类器附加到预训练的模型上。
  • 预训练模型中的输入形状
  • 使用池化
  • 冻结预应变模型中的层。
  • 使用预训练模型的特定层。

图像分类模型

简单来说,图像分类模型如下所示。

Pretrained Model

其包含卷积层,随后是全连接层。卷积层从图像中提取特征,全连接层使用提取的特征对图像进行分类。

当我们在图像数据上训练一个 CNN 时,可以看到网络的顶层学会从图像中提取一般特征,如边缘、颜色分布等。随着我们在网络中不断深入,各层往往会提取更多的特定特征。

现在,我们可以使用这些已经知道如何提取特征的预训练模型,避免从头开始训练。这个概念被称为迁移学习

使用预训练模型

在 Keras 中有两种创建模型的方法。一个是顺序模型,另一个是功能 API 。顺序模型是层的线性堆叠。您可以通过调用add方法简单地在顺序模型中添加层。另一个是 functional API,它允许您创建可能包含多个输入和输出的更复杂的模型。

在本指南中,我将使用 VGG16 预训练模型的例子。我们可以类似地使用其他预训练模型。

Keras 的应用模块中提供了所有预训练模型。首先,我们必须导入预训练的模型,如下所示。

from keras.applications.vgg16 import VGG16

然后我们可以像下面这样添加预训练的模型,或者在顺序模型或者功能 API 中。

VGG in Sequential Model

VGG in Functional API

要使用预训练的权重,我们必须将参数weights设置为imagenet。默认值也被设置为imagenet。但是如果我们想从头开始训练模型,我们可以将weights参数设置为None。这将在网络中随机初始化权重。

附加我们自己的分类器

我们可以移除默认分类器,并在预训练模型中附加我们自己的分类器。为了排除默认分类器,我们必须将参数include_top设置为false

在下面的例子中,我从 VGG 移除默认分类器,然后附加我自己的分类器,这只是一个dense层。我们还必须在添加一个dense层之前添加一个flatten层,将卷积层的 4D 输出转换为 2D,因为dense层接受 2D 输入。

Attaching a Classifier

输入形状

VGG16 在大小为(224, 224)的 RGB 图像上训练,这是网络的默认输入大小。我们也可以输入默认尺寸以外的图像。但是图像的高度和宽度应该超过 32 像素。当我们从网络中排除默认分类器时,我们只能馈送其他大小的图像。以下是显示(32, 64, 3)输入尺寸的示例。最后一个维度是 3,表示颜色通道的数量。

Changing input shape

我们也可以通过提供输入张量来定义输入形状,如下例所示。

Input Tensor

我们可以注意到,当我们提供有意义的较小尺寸的图像时,输出维度也被压缩。

联营

我们可以对卷积层的最终输出应用两种类型的池。全球*均统筹全球最高统筹

在全局最大池中,我们在张量的每张幻灯片上选择一个最大值,如下图所示。

Global Maximum Pooling

假设卷积层的输出张量具有形状(7, 7, 512)。如果我们应用全局最大池,我们从每张(7, 7)幻灯片中选择一个最大数字,这样我们总共有 512 个数字。*均池做同样的事情,除了取*均值而不是最大值。

为了使用池,我们必须将参数pooling设置为maxavg来使用这 2 个池。在下面的例子中,我使用的是全局*均池。

Global Average Pooling

当我们有一个可变大小的输入图像时,全局池是有用的。假设我们从不同大小的图像中得到 2 个不同大小的输出张量。输出张量的形状是(3, 3, 512)(7, 7, 512)。在对这些张量中的任何一个应用全局池后,我们将得到一个长度为 512 的固定大小的向量。因此,在应用全局池后,可变大小图像的最终输出仍然是固定大小的向量。

冻结层

在训练网络之前,你可能想根据任务冻结一些层。一旦层被冻结,其权重在训练时不会更新。

在下面的例子中,我冻结了网络的前 10 层。我已经打印了网络中的所有层,以及它们是否可训练。我们可以看到只有前 10 层是不可训练的。

Freezing top 10 layers

如果当前数据集与训练这些网络的数据集相似,则最好冻结所有图层,因为两个数据集中的影像具有相似的要素。但是如果数据集不同,那么我们应该只冻结顶层并训练底层,因为顶层提取一般特征。数据集越相似,我们应该冻结的层就越多。

使用特定层

在上面的例子中,我们可以看到模型包含的所有层。我们也可以单独选择这些层中的任何一个,并在我们的模型中使用它们。

在下面的例子中,我将第三层预训练模型(block1_conv2)添加到顺序模型中。

Adding a specific layer

这几乎涵盖了在 Keras 中使用预训练模型时需要了解的所有用例。谢谢你的时间。

用 Python 从头开始一步一步实现 R-CNN

原文:https://towardsdatascience.com/step-by-step-r-cnn-implementation-from-scratch-in-python-e97101ccde55?source=collection_archive---------2-----------------------

分类和目标检测是计算机视觉的主要部分。分类是找到图像中的内容,而对象检测和定位是找到该对象在图像中的位置。检测是一个更复杂的问题,因为我们需要找到对象在图像中的坐标。

为了解决这个问题,2014 年 Ross Girshick、Jeff Donahue、Trevor Darrell 和 Jitendra Malik 引入了 R-CNN。R-CNN 代表有 CNN 的地区。在 R-CNN 中,我们通过选择性搜索传递图像,并从结果中选择第一个 2000 区域建议,并在此基础上运行分类,而不是在大量区域上运行分类。这样,我们只需要对前 2000 个区域进行分类,而不是对大量区域进行分类。这使得该算法比以前的对象检测技术更快。R-CNN 有 4 个步骤。它们如下:

  1. 通过选择性搜索图像并生成区域建议。
  2. 使用地面真实数据计算建议区域的 IOU(交集/并集),并向建议区域添加标签。
  3. 使用带标签的建议区域进行迁移学习。
  4. 将测试图像传递给选择性搜索,然后传递来自训练模型的前 2000 个建议区域,并预测这些区域的类别。

R-CNN

我将使用来自http://www.escience.cn/people/JunweiHan/NWPU-RESISC45.html的飞机数据集在 Keras 从头开始实现完整的 R-CNN。要获得带注释的数据集,你可以从下面的链接下载。实现 RCNN 的代码也可以在下面提到的资源库中找到。

https://github.com/1297rohit/RCNN.git

下载完数据集后,您可以继续执行下面的步骤。

import os,cv2,keras
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

第一步是导入实现 R-CNN 所需的所有库。我们需要 cv2 对图像进行选择性搜索。要使用选择性搜索,我们需要下载 opencv-contrib-python。要下载刚刚运行的 pip,请在终端中安装 opencv-contrib-python ,并从 pypi 安装它。

ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()

下载 opencv-contrib 后,我们需要初始化选择性搜索。为此,我们增加了上述步骤。

def get_iou(bb1, bb2):assert bb1['x1'] < bb1['x2']assert bb1['y1'] < bb1['y2']assert bb2['x1'] < bb2['x2']assert bb2['y1'] < bb2['y2'] x_left = max(bb1['x1'], bb2['x1'])y_top = max(bb1['y1'], bb2['y1'])x_right = min(bb1['x2'], bb2['x2'])y_bottom = min(bb1['y2'], bb2['y2']) if x_right < x_left or y_bottom < y_top:return 0.0 intersection_area = (x_right - x_left) * (y_bottom - y_top) bb1_area = (bb1['x2'] - bb1['x1']) * (bb1['y2'] - bb1['y1'])bb2_area = (bb2['x2'] - bb2['x1']) * (bb2['y2'] - bb2['y1']) iou = intersection_area / float(bb1_area + bb2_area - intersection_area)assert iou >= 0.0assert iou <= 1.0return iou

现在,我们正在初始化函数,从通过选择性搜索计算出的盒子中计算出基础真值盒子的 IOU(交集/并集)。要了解更多关于计算欠条,你可以参考下面的链接。

https://www . pyimagesearch . com/2016/11/07/intersection-over-union-iou-for-object-detection/

train_images=[]
train_labels=[]
for e,i in enumerate(os.listdir(annot)):try:if i.startswith("airplane"):filename = i.split(".")[0]+".jpg"print(e,filename)image = cv2.imread(os.path.join(path,filename))df = pd.read_csv(os.path.join(annot,i))gtvalues=[]for row in df.iterrows():x1 = int(row[1][0].split(" ")[0])y1 = int(row[1][0].split(" ")[1])x2 = int(row[1][0].split(" ")[2])y2 = int(row[1][0].split(" ")[3])gtvalues.append({"x1":x1,"x2":x2,"y1":y1,"y2":y2})ss.setBaseImage(image)ss.switchToSelectiveSearchFast()ssresults = ss.process()imout = image.copy()counter = 0falsecounter = 0flag = 0fflag = 0bflag = 0for e,result in enumerate(ssresults):if e < 2000 and flag == 0:for gtval in gtvalues:x,y,w,h = resultiou = get_iou(gtval,{"x1":x,"x2":x+w,"y1":y,"y2":y+h})if counter < 30:if iou > 0.70:timage = imout[y:y+h,x:x+w]resized = cv2.resize(timage, (224,224), interpolation = cv2.INTER_AREA)train_images.append(resized)train_labels.append(1)counter += 1else :fflag =1if falsecounter <30:if iou < 0.3:timage = imout[y:y+h,x:x+w]resized = cv2.resize(timage, (224,224), interpolation = cv2.INTER_AREA)train_images.append(resized)train_labels.append(0)falsecounter += 1else :bflag = 1if fflag == 1 and bflag == 1:print("inside")flag = 1except Exception as e:print(e)print("error in "+filename)continue

Running selective search on an image and getting proposed regions

上面的代码是预处理和创建要传递给模型的数据集。在这种情况下,我们可以有两个类。这些类别是提议的区域可以是前景(即飞机)还是背景。所以我们将前景(即飞机)的标签设为 1,背景的标签设为 0。在上面的代码块中执行以下步骤。

  1. 循环浏览图像文件夹,使用代码 ss.setBaseImage(image) 将每个图像逐一设置为选择性搜索的基础
  2. 使用代码ss . switchtoselectvesearchfast()ssresults = ss.process() 初始化快速选择性搜索并获得建议区域
  3. 迭代通过选择性搜索传递的所有前 2000 个结果,并使用上面创建的 get_iou() 函数计算建议区域和注释区域的 IOU。
  4. 现在,由于一个图像可以有许多负样本(即背景)和一些正样本(即飞机),所以我们需要确保我们有良好的正样本和负样本的比例来训练我们的模型。因此,我们设定从一幅图像中最多收集 30 个阴性样本(即背景)和阳性样本(即飞机)。

运行上面的代码片段后,我们的训练数据就准备好了。List train_images=[] 将包含所有图像,而 train_labels=[] 将包含所有标记飞机图像为 1、非飞机图像(即背景图像)为 0 的标签。

Positive sample on right, Negative sample on left

X_new = np.array(train_images)
y_new = np.array(train_labels)

在完成创建数据集的过程后,我们将把数组转换成 numpy 数组,这样我们就可以轻松地遍历它,并以有效的方式将 datatset 传递给模型。

from keras.layers import Dense
from keras import Model
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adamfrom keras.applications.vgg16 import VGG16
vggmodel = VGG16(weights='imagenet', include_top=True)

现在,我们将对 imagenet 权重进行迁移学习。我们将导入 VGG16 模型,并将图像净重放入模型中。要了解更多关于迁移学习的内容,你可以参考下面链接上的文章。

https://medium . com/@ 1297 rohit/transfer-learning-from-scratch-using-keras-339834 b 153 b 9

for layers in (vggmodel.layers)[:15]:print(layers)layers.trainable = FalseX= vggmodel.layers[-2].output
predictions = Dense(2, activation="softmax")(X)
model_final = Model(input = vggmodel.input, output = predictions)
opt = Adam(lr=0.0001)
model_final.compile(loss = keras.losses.categorical_crossentropy, optimizer = opt, metrics=["accuracy"])
model_final.summary()

在循环的这一部分,我们冻结了模型的前 15 层。之后,我们取出模型的倒数第二层,然后添加一个 2 单位的 softmax 密集层,因为我们只有 2 个类要预测,即前景或背景。之后,我们使用 Adam 优化器编译模型,学习率为 0.001 。我们使用分类交叉熵作为损失,因为模型的输出是分类的。最后,将使用 model_final.summary()打印模型摘要。下面附上总结的图片。

Model Summary

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizerclass MyLabelBinarizer(LabelBinarizer):def transform(self, y):Y = super().transform(y)if self.y_type_ == 'binary':return np.hstack((Y, 1-Y))else:return Ydef inverse_transform(self, Y, threshold=None):if self.y_type_ == 'binary':return super().inverse_transform(Y[:, 0], threshold)else:return super().inverse_transform(Y, threshold)lenc = MyLabelBinarizer()
Y =  lenc.fit_transform(y_new)X_train, X_test , y_train, y_test = train_test_split(X_new,Y,test_size=0.10)

创建模型后,现在我们需要将数据集分为训练集和测试集。在此之前,我们需要一次性编码标签。为此,我们使用了 MyLabelBinarizer() 并对数据集进行编码。然后我们使用 sklearn 的 train_test_split 来拆分数据集。我们保留 10%的数据集作为测试集,90%作为训练集。

trdata = ImageDataGenerator(horizontal_flip=True, vertical_flip=True, rotation_range=90)
traindata = trdata.flow(x=X_train, y=y_train)
tsdata = ImageDataGenerator(horizontal_flip=True, vertical_flip=True, rotation_range=90)
testdata = tsdata.flow(x=X_test, y=y_test)

现在我们将使用 Keras ImageDataGenerator 将数据集传递给模型。我们将对数据集进行一些增强,如水*翻转、垂直翻转和旋转,以增加数据集。

from keras.callbacks import ModelCheckpoint, EarlyStoppingcheckpoint = ModelCheckpoint("ieeercnn_vgg16_1.h5", monitor='val_loss', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)early = EarlyStopping(monitor='val_loss', min_delta=0, patience=100, verbose=1, mode='auto')hist = model_final.fit_generator(generator= traindata, steps_per_epoch= 10, epochs= 1000, validation_data= testdata, validation_steps=2, callbacks=[checkpoint,early])

现在我们使用 fit_generator 开始模型的训练。

z=0
for e,i in enumerate(os.listdir(path)):if i.startswith("4"):z += 1img = cv2.imread(os.path.join(path,i))ss.setBaseImage(img)ss.switchToSelectiveSearchFast()ssresults = ss.process()imout = img.copy()for e,result in enumerate(ssresults):if e < 2000:x,y,w,h = resulttimage = imout[y:y+h,x:x+w]resized = cv2.resize(timage, (224,224), interpolation = cv2.INTER_AREA)img = np.expand_dims(resized, axis=0)out= model_final.predict(img)if out[0][0] > 0.70:cv2.rectangle(imout, (x, y), (x+w, y+h), (0, 255, 0), 1, cv2.LINE_AA)plt.figure()plt.imshow(imout)break

现在一旦我们创建了模型。我们需要对那个模型做预测。为此,我们需要遵循以下步骤:

  1. 传递选择性搜索的图像。
  2. 使用 model_final.predict(img) 将选择性搜索的所有结果作为输入传递给模型。
  3. 如果模型的输出表明该区域是前景图像(即飞机图像),并且如果置信度高于定义的阈值,则在建议区域的坐标上在原始图像上创建边界框。

Output of the model

正如你在上面看到的,我们在建议的区域创建了一个盒子,在这个盒子里,模型的精度超过了 0.70。这样,我们可以在图像上进行定位,并使用 R-CNN 执行对象检测。这就是我们如何使用 keras 从零开始实现 R-CNN 架构。

您可以从下面提供的链接中获得完全实现的 R-CNN。

https://github.com/1297rohit/RCNN.git

如果你想从头开始一步一步地学习人脸检测和人脸识别,那么你可以点击链接阅读我的文章:https://medium . com/@ 1297 rohit/step-step-step-Face-Recognition-code-implementation-from-scratch-in-python-cc 95 fa 041120

享受 R-CNN!

基于机器学习的分步信号处理:流形学习

原文:https://towardsdatascience.com/step-by-step-signal-processing-with-machine-learning-manifold-learning-8e1bb192461c?source=collection_archive---------12-----------------------

关于如何使用 Python 中的 Isomap 和 LLE 从头开始执行非线性降维的教程

https://www.delish.com/cooking/recipe-ideas/a24788319/how-to-make-donuts-at-home/

在我关于使用机器学习进行信号处理的第一篇文章中,我介绍了用于降维的主成分分析 (PCA)和独立成分分析 (ICA)。我们能够看到如何使用这些方法来减少数据中的特征数量。然而,它们是线性方法:当我们的数据中存在非线性关系时,它们并不总是表现良好。

这就是流形学习的用武之地。流形是局部欧几里得的任何空间。简单来说,你可以把它想象成任何在小尺度上*乎“扁*”的物体。例如,地球是圆的,但在我们看来它是*的。地球是一个流形:局部它是*的,但整体上我们知道它是一个球体。然后,流形学习通过将数据表示为嵌入在高维空间中的低维流形来进行降维。

在本文中,我将介绍两种流形学习算法: Isomap局部线性嵌入 (LLE)。它们都在 scikit-learn 上有现成的实现,这对您的项目很有用,但是出于本文的目的,我将展示如何从头开始实现这些方法。

我将在整篇文章中提供代码片段,您可以在 Github 上找到完整的代码和示例数据集。

出于演示的目的,我对一组数字为 5 的手写图像进行了降维处理。每个图像的大小为 28x28,在应用算法之前,我们对数据进行整形以获得大小为 784 的 1D 向量。首先,这是使用主成分分析的 2D 投影:

我们可以看到这个投影组图像在一定程度上具有相似的空间特征:在 x 轴上,左侧的图像具有较粗的线条,而右侧的图像具有较细的线条。在 y 轴上,顶部的图像更加直立,或者稍微向左倾斜,而底部的图像向右倾斜。

Isomap

Isomap 是一种基于谱理论的流形学习方法,用于保持测地线距离。Isomap 可以理解为多维标度(MDS)的扩展:经典的 MDS 执行主坐标分析,基本上是基于数据点之间成对的欧几里得距离对距离矩阵而不是协方差矩阵进行 PCA。Isomap 使用测地线距离代替,这是数据点之间的最短路径的距离。

首先,这里有一个简单的代码提供了 Isomap 的步骤:计算数据集的距离 矩阵,获得最短路径矩阵,并对其应用 MDS

距离矩阵可根据输入数据集计算,如下所示,其中我们使用欧几里德距离。

现在,我们将实现 MDS。对于 MDS,重要的是首先双中心输入距离矩阵。双定心操作不会改变任何一对点之间的距离,但允许生成的矩阵具有简化后续操作的属性。

接下来,像在 PCA 中一样,我们计算中心距离矩阵的特征向量和相应的特征值

然后,我们通过选择具有两个最大特征值的特征向量来选择两个主分量,并且我们获得将用于投影的形状为 784×2 的子空间变换矩阵 W

以下是我们将 Isomap 应用于示例数据所获得的结果:

在上面的结果中,我们可以观察到投影有一个“U”形,图像的变化似乎遵循这个“U”形。这是因为 Isomap 寻找非线性流形,这就是它能够检测潜在的现有曲线的原因。

左上末端的形状较圆,并且“5”的下半部分较大,而在右上末端,“5”的下半部分较小。与 PCA 投影不同,它似乎不会用更细或更粗的线来分隔数字。

此外,检查该投影的不同区域,图像看起来与它们的每个邻居更相似,不像 PCA 投影,其中不具有相似形状的图像可以彼此相邻。PCA 投影是一种线性缩减,可能擅长拾取线性 相关性,例如像素值和线条粗细之间的相关性,但是 Isomap 投影可能会找到有意义的非线性相关性。

局部线性嵌入

局部线性嵌入(LLE)是另一种流形学习算法。LLE 背后的想法是计算一组权重,将每个数据点描述为其邻居的线性组合。然后,类似于前面的方法,它使用基于特征向量的优化技术来寻找低维嵌入,使得点与其邻居之间的线性组合关系被保持

我们像以前一样通过计算距离矩阵来开始 LLE,除了这次,我们感兴趣的是每个数据点的最*邻居的点。

接下来,LLE 找到最小化以下成本函数的权重矩阵 W :

这个函数就是每个点 X_i 和它从它的邻居X _ j的重建之间的误差之和。我们可以使用 FastLLE 算法实现这个部分,如下所示。

以下是使用 LLE 进行降维的结果:

LLE 投影给出了比 ICA 投影更尖锐的“V”形,我们甚至可以认为这种表示与以前的 Isomap 投影相比有些失真。这是因为 LLE 是一个局部方法,而 Isomap 是一个全局方法,所以 LLE 更倾向于扭曲投影空间,而 Isomap 更稳定。

有趣的是,在 LLE 和 Isomap 投影中,远离一般聚类的点对应于相同的图像。这两种方法都确定了相同的数据点,这些数据点看起来确实不像“5”的其余部分,并将它们投射到远离其余部分的空间中,如下所示。

Left: Isomap, right: LLE

我希望你喜欢我的文章,谢谢你的关注!请随时告诉我你想在我的信号处理库:)里看到什么

逐步信号处理与机器学习:主成分分析,独立分量分析,NMF 源分离,降维

原文:https://towardsdatascience.com/step-by-step-signal-processing-with-machine-learning-pca-ica-nmf-8de2f375c422?source=collection_archive---------13-----------------------

关于如何在 Python 中从头开始使用 PCA 执行降维以及使用 ICA 和 NMF 执行源分离的教程

https://www.surfline.com/contests/wave-of-the-winter/north-shore/2018-2019/

信号处理在许多数据科学任务中至关重要。一旦我们开始处理音频文件、图像甚至生物测量,了解处理这些数据的技术是很有用的。

在这篇文章中,我将介绍三种算法,你可以用在两个用例中:主成分分析 (PCA)用于降维和特征提取,独立成分分析 (ICA)和非负矩阵分解 (NMF)用于源分离。

所有这三个方法在 scikit-learn 上都有现成的实现,对您的项目很有用,但出于本文的目的,我将展示如何从头开始实现这些方法,只使用 OpenCV 打开和保存图像,使用 NumPy 处理矩阵。

我将在整篇文章中提供代码片段,您可以在 Github 上找到完整的代码和示例数据集。

主成分分析

我将总结实现 PCA 的要点,并向热心的读者推荐这篇很棒的文章,它给出了更全面的解释。

PCA 的主要目的是找到我们数据集的特征子集能够最好地捕获整个数据的信息,以便我们能够以最小的信息损失减少维度。例如,我们可以通过在将训练图像数据送入深度神经网络进行分类之前降低其维度来缩短计算时间。

有几种降维技术,如高相关滤波器、随机森林或后向特征消除。PCA 通过识别主成分来完成这项任务,主成分是原始特征的线性组合。提取这些分量,使得第一主分量包含数据集中的最大方差,第二主分量包含与第一主分量不相关的剩余方差,依此类推。

作为一个例子,我们将使用手写数字 4 的 982 个图像的数据集。每个图像的尺寸为 28x28,但是在应用 PCA 之前,我们首先对数据进行整形,使得每个图像成为大小为 784 的 1D 向量,并且整个数据集的形状为 982x784。

Input images

为了使用 PCA 将特征的数量减少到 k ,我们首先计算这个数据集的协方差 矩阵

然后,我们计算协方差矩阵的特征向量和相应的特征值

为了选择 k 主分量,我们首先按照特征值的降序对特征向量和特征值对进行排序。我们选择具有 k 个最大特征值的特征向量,因为它们包含关于数据的最多信息。

最后我们得到一个形状为 784 x k 的矩阵 W ,我们将其与数据集的转置取乘积,得到降维后的数据 k x 982。

为了重建已经减少的数据,我们简单地将减少的数据与之前获得的矩阵 W 的逆矩阵相乘。这样,我们获得了与原始数据具有相同维度的数据。最后,我们将 2D 数据整形为 982x28x28 维的 3D 矩阵,这样我们就有了一组可以再次可视化的图像。

为了计算重建误差,我们可以通过比较原始图像和重建图像之间的每个图像像素来计算均方误差。

Results of dimensionality reduction with PCA, error measured with MSE

以上结果表明,主成分越多我们取,越低 重构误差就越大。这是因为维数降低得越多,我们丢失的可用于重建的原始信息就越多。选择最佳分量数以优化降维和信息之间的权衡的一种常见方法是计算每个分量数的 PCA 的解释方差,并选择方差在 95–99%之间的分量数。这确保我们不会丢失太多关于数据的信息。

Left to right: original image, reconstruction from 2, 16, 64, 256 components

独立成分分析

现在,我们有 1000 张图像,是四个手写数字 0,1,4,7 的组合,比例各不相同。我们希望从混合图像中恢复源图像。

Source images

Mixed data

一种分离线性混合信号的方法是通过独立分量分析 (ICA)。信号的混合可以定义为矩阵乘积 WH = X ,其中 H 是包含不同源信号的矩阵, W 定义混合期间源的比率, X 是混合输出。然后 ICA 旨在恢复矩阵 W ,这样我们就可以计算 H = WinvX ,其中 WinvX 的逆。

ICA 不能应用于任何混合信号。首先,混合信号必须是源信号的线性组合,原因如前矩阵乘积所示。接下来,ICA 假设源信号是独立的,而混合信号不是(因为它们共享相同的源信号),并利用这一事实进行分离。最后,ICA 还假设源信号为非高斯信号,并使用中心极限定理,该定理意味着两个信号之和的分布比两个信号本身的分布更接*高斯分布。

我们可以使用 FastICA 算法高效地进行 ICA。该算法用维度(n_sources,n_samples)的随机 权重 W 初始化,其中我们使用先验信息,我们有 4 个想要分离的源,并且我们有 1000 个图像样本。对于我们期望分离的每个源,我们迭代与该源相关联的权重。

对于 W 中的每个权重向量 w ,该算法寻求最大化投影 v = w.TX非高斯程度(其中 w.Tw 的转置)。为了测量非高斯性,该算法使用一个非二次非线性函数f(v)它的一阶导数 g(v) 和它的二阶导数 g'(v)。

对于这些函数,我们使用梯度下降来更新权重。

然后,我们归一化去相关权重。去相关是为了确保后续源的迭代不会返回与在前一次迭代中获得的源相同的输出。最后,我们检查收敛来决定是停止还是继续迭代。

为了从 ICA 的输出 W 中获得原始源,我们简单地取 W 和给定输入数据的乘积,以获得维度矩阵( n_sourcesn_features ),然后我们将它整形为原始的 3D 维度以获得图像。

Four sources separated by ICA

上述 ICA 的结果表明,它能够在某种程度上提取图像 0、4 和 7,但它不能提取图像 1,相反,它返回的图像似乎是几个源图像叠加在一起。让我们看看我们是否能做得更好…

非负矩阵分解

分离混合信号的第二种方法是非负矩阵分解 (NMF)。像 ICA 一样,NMF 也旨在将混合数据 X 分解成矩阵 WH = X 的乘积,但这里有一个附加约束,即每个矩阵 X,W,H 都是非负的。这种约束在数据本质上是非负的应用中提供了优势,并且给出了具有更好的可解释性的结果。

为了应用 NMF,我们从随机初始化 WH开始。

然后,在每次迭代中,我们首先更新新的 H 给定旧的 HW ,然后更新新的 W 给定 H 和旧的 W ,使用乘法更新规则直到收敛。

Multiplicative update rules

我们使用 XWH 之间的 Frobenius 范数来检查收敛性。

最后,我们对获得的矩阵进行归一化,并在保存可视化之前对其进行整形,使其包含 2D 图像。

Four sources separated by NMF

正如我们在上面看到的,在我们的例子中,NMF 算法比独立分量分析好得多。

感谢阅读我的文章,我希望你喜欢它!我希望开始向我的信号处理库添加更多的方法,所以如果接下来有什么需要我介绍的,请告诉我:)

使用 Spotify API 逐步可视化音乐流派

原文:https://towardsdatascience.com/step-by-step-to-visualize-music-genres-with-spotify-api-ce6c273fb827?source=collection_archive---------11-----------------------

Source: OpenClipart-Vectors on Pixabay

你听什么,你就是什么。每个人都有他/她喜欢的音乐家,这些音乐家通常擅长某些类型的音乐。我们很容易把一首歌归类为蓝调、爵士或乡村音乐,那么它背后的寓意是什么呢?我们能说出或看到音乐和数据的区别吗?由于 Spotify 的开放 API,我们可以理解音乐的不同方面,包括速度、音调和音频特征,并构建网络应用程序来有效地回答我们的问题。

在这篇文章中,我们使用 R Shiny 作为与 Spotify API 通信的接口,并将其托管在 shinyapps.io 上。通过此处的链接可以访问该网站。然而,shinyapp.io 有一些限制——每月 25 个小时的免费活动时间。如果您无法正常连接,请下个月再试。否则,如果您已经安装了 R,下面的命令可以在您自己的环境中运行它。

shiny::runGitHub("Music_ANA","BarryPan")

这篇文章有两个部分。第一部分是关于构建可视化应用程序的步骤;在第二部分,我们可以分享它如何帮助我们确定不同的音乐流派。阅读后,你将能够建立自己的音乐分析工具,并对 Spotify API 有更多的见解。

步骤 1:阅读 API 文档

F 首先,我们需要了解我们的数据以及我们拥有哪些信息。Spotify 为其 API 提供了全面的解释,开发者或分析师在开始做任何事情之前阅读它是非常重要的。根据我们的经验,我们认为速度、音调和音频特征是识别音乐流派的决定性因素,它们应该是我们要可视化的内容。

在 Spotify API 中,它提供了许多音频功能。我们选择某些特性,下面显示了定义:

  • 声学:一个从 0.0 到 1.0 的音轨是否声学的置信度度量。1.0 表示音轨是声学的高置信度。
  • 可跳舞性:可跳舞性描述了一首曲目在音乐元素组合的基础上适合跳舞的程度,包括速度、节奏稳定性、节拍强度和整体规律性。值 0.0 最不适合跳舞,1.0 最适合跳舞。
  • 能量:能量是从 0.0 到 1.0 的量度,代表强度和活动的感知量度。通常,高能轨道感觉起来很快,很响,很嘈杂。例如,死亡金属具有高能量,而巴赫前奏曲在音阶上得分较低。对该属性有贡献的感知特征包括动态范围、感知响度、音色、开始速率和一般熵。
  • speech ness:speech ness 检测音轨中是否存在口语单词。越是类似语音的录音(例如脱口秀、有声读物、诗歌),属性值就越接* 1.0。高于 0.66 的值描述可能完全由口语单词组成的轨道。介于 0.33 和 0.66 之间的值描述可能包含音乐和语音的轨道,可以是分段的,也可以是分层的,包括说唱音乐。低于 0.33 的值很可能代表音乐和其他非语音类轨道。
  • 效价:从 0.0 到 1.0 的一个量度,描述一个音轨所传达的音乐积极性。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。

对于其他目的,您可以选择不同的变量来满足您的需要。一旦你知道你要向你的观众传达什么,让我们进入下一步。

步骤 2:后端开发

potify API 遵循 OAuth 认证,因此用户需要在开始连接之前申请 API 密钥。此外,R 中有一个[spotifyr](https://cran.r-project.org/web/packages/spotifyr/index.html) 包使得请求变得容易多了。

在这个可视化中,我们想按艺术家对数据进行分组。由于不同的艺术家擅长不同类型的音乐,我们可以根据艺术家来比较不同风格的音乐。为了提供有用的信息,我们需要计算每个艺术家的*均速度、受欢迎程度、声音、舞蹈性、精力、语速和价值。还要计算大调的频率,看音乐流派的差异。这些计算可以用 R 中的dplyr包轻松完成,输出可以用ggplot包可视化。

我们希望用户决定他们对谁感兴趣,而不是只选择某些艺术家。为此,我们需要一个文本输入小部件和一个搜索按钮来激活。一旦用户点击按钮,程序应该连接到 Spotify API 并获取信息,进行计算并将其可视化,并将信息更新到前端。在 Shiny 中,我们可以使用observeEvent来触发功能并完成任务序列。

第三步:用户界面设计

数据可视化是科学和艺术的结合。因此,考虑什么是传达你的想法的最佳方式以及你的观众的感受是非常重要的。

在我们的可视化工具中,有很多我们想要传递给观众的信息,不同的信息可以用不同的方式说出来。经过一些尝试,我们找到了显示这些信息的正确方法,如下所示:

  • *均速度可以用词来表达。
  • 艺术家的音调频率可以用水*条形图来表示。为了便于阅读,我们只列出了艺术家的前 5 个关键词。
  • 艺术家的*均音频特征可以在雷达图中显示。

除了这些信息之外,还有一些对用户做出判断至关重要的信息。因此,我们在 Spotify 上包括了歌曲的受欢迎程度、歌曲数量和播放时间。此外,我们还应该在网站上包含相册图片,使其看起来更花哨。

A 同样,颜色也是数据可视化成功的一个重要因素。为了避免过于分散注意力,我们选择了白底黑字。我们可以使用 Spotify 的品牌颜色, html 颜色代码 #1DB954,作为我们绘图的主色调。第一个版本看起来是这样的。它包含了所有的功能,但对用户没有太大的吸引力。通过改变字体,情节大小,添加标志和音频功能的解释,我们可以使它成为我们的最终版本。现在好多了,至少我是这么认为的。

Figure 1: First Version for our tool

Figure 2: Final Version for our tool

第四步:托管它

要让每个人都能看到你的结果,你需要找到一个服务器来托管它。我们有很多选择,包括一些流行的云*台,像 GCP 、 AWS 或 Azure ,价格实惠。对于 Shiny 应用程序,还有另一个选择:shinyapp.io。这是一个为 Shiny 应用程序设计的*台,根据你选择的软件包,价格从 0 美元到 299 美元不等。如果你想将闪亮的应用发布到 shinyapp.io,只需在 R Studio 中点击“发布”并链接到你的 Shiny app . io 账户。

有了这个工具,我们可以看到不同风格的艺术家的样子。这里有一些流行蓝调、乡村音乐、爵士乐和流行音乐艺术家的例子。

布鲁斯

乔安妮·肖·泰勒

Figure 3: Joanne Shaw Taylor

乔·博纳马萨

Figure 4: Joe Bonamassa

迈克·济托

Figure 5: Mike Zito

乡村音乐

克里斯·斯台普顿

Figure 6: Chris Stapleton

佛罗里达乔治亚边境线

Figure7: Florida Georgia Line

杰森·阿尔迪恩

Figure 8: Jason Aldean

爵士乐

保罗·西蒙

Figure 9: Paul Simon

范·莫里生

Figure 10: Van Morrison

威利·尼尔森

Figure 11: Willie Nelson

流行音乐

Lady Gaga

Figure 12: Lady Gaga

魔力红

Figure 14: Maroon 5

泰勒·斯威夫特

Figure 15: Taylor Swift

根据上面的视觉效果,我们可以看到这些流派之间的一些差异:

  • 与布鲁斯、乡村音乐和爵士乐相比,流行音乐倾向于使用更多样的音调。至于蓝调、乡村和爵士艺术家,前 5 个调占据了他们创作的 50%以上,相比之下,流行音乐家不会只关注某些调。
  • 乡村音乐和爵士音乐通常使用大调来给听众带来一些积极的印象。
  • 蓝调在“能量”和“化合价”上的价值较低,因为它们是蓝调。

C 结束语

在这篇文章中,我们从一个简单的问题开始:我们如何区分音乐流派。我们想回答这个问题,所以我们试图找到数据,找出我们想要表达和证明我们思想的方式,然后玩电脑。感谢开放的环境,包括公共 API、开放数据和像 R 这样的开放资源软件,让编程能力有限的人开发自己的创作并与世界分享真的很简单。如果你对这个世界有什么想法,让我们一起努力,用数据把它可视化。

逐步教程-创建条形图竞赛动画

原文:https://towardsdatascience.com/step-by-step-tutorial-create-a-bar-chart-race-animation-da7d5fcd7079?source=collection_archive---------8-----------------------

使用 Python 和 flore 构建 2019 年的虚拟场景

Photo by Lukas Blazek on Unsplash

2019 年是条形图竞赛动画年。当然,这种类型的动画已经存在了一段时间,其受欢迎程度在 2019 年初达到顶峰。虽然我不是一个大粉丝——因为同样的见解可以用一个简单的线图来解释——但这是一个有趣的可视化和毫无疑问的审美愉悦观看。

因此,这篇文章是关于如何用 Python 和 T2 创建条形图比赛动画的一步一步的教程。事实上,fluore 将是创建可视化的主要工具,但格式化数据集也需要一些 python 脚本。我的意思是,如果数据格式化可以手动完成(当然是在可接受的时间内),你可以跳过 Python。).

最终的输出应该是这样的:(如果你想知道,Y 轴标签是用希腊语写的,但是数据集就是这样)

Bar Chart Race Visualisation

或者,如果上面的 GIF 预览滞后,您可以在以下网站在线观看:

[## 塞浦路斯失业——种族歧视可视化

preview . floride . studio](https://preview.flourish.studio/338947/pzgmyVTKTwIOqgG7X10bF6MlXioP4cn0LjH464Jwa5OD0S7jll0nQzSOPR3VKiz_/)

最后,这里是 GitHub 存储库,包含所有相关的代码和数据:

[## apogiatzis/种族条形图-失业

塞浦路斯每项经济活动失业率的种族柱状图---- apogiatzis/种族柱状图----失业率

github.com](https://github.com/apogiatzis/race-bar-chart-unemployment)

资料组

出于本教程的考虑,我将使用来自塞浦路斯开放数据门户的数据集。更准确地说,该数据集包含自 2013 年以来每个月每个经济活动类别申请失业津贴的人数。想象这些数字如何随时间循环将会很有趣,这也是利用国家开放数据门户提供的一些数据集的好机会。

我已经在数据格式化代码中包含了数据集的链接,但下面的链接仅供参考:

[## 国家开放数据门户

Αποστολή της Υπηρεσίας είναι η εφαρμογή της κυβερνητικής πολιτικής στον τομέα των κοινωνικών ασφαλίσεων με την…

www.data.gov.c](https://www.data.gov.cy/node/3779?language=en)

这个计划

这个计划很简单,因为荣替我们处理繁重的工作。便利的是,荣有一个模板来创造这种特殊的观想。因此,我们将使用 Python 将数据集转换成适合 flower 模板数据格式的格式。然后,数据将被导入并繁荣,而视觉化将被捕捉。

逐步地

正如承诺的,本教程是一步一步的。因此,让我们继续前进,并遵循以下步骤。

第一步:创建繁荣账户

请通过以下链接创建一个“繁荣”账户:

[## 蓬勃发展|数据可视化和讲故事

蓬勃发展是最强大的*台,数据可视化和讲故事

app . floride . studio](https://app.flourish.studio/register)

步骤 2:打开条形图竞赛模板

使用下面的链接打开条形图比赛模板,并点击“创建可视化”:

[## 条形图竞赛

让您自己的条形图比赛与蓬勃发展

app . floride . studio](https://app.flourish.studio/@flourish/bar-chart-race)

单击“数据”选项卡,观察数据应如何格式化以使模板工作。请注意,每个条形是一行,每个时间点是一列(除了可选的“区域”和“图像 URL”)。

第三步:数据格式化

让我们继续并格式化要导入的数据,使其更加丰富多彩。我已经在 Colab 中为此编写了 Python 代码,因此不需要任何环境设置:

[## 谷歌联合实验室

Bar Race 数据格式

colab.research.google.com](https://colab.research.google.com/drive/1TZHUPS1ReaNrijIlS28INqxzBqRo3O_T)

打开 Jupyter 笔记本,并在您的硬盘上保存一份副本,如下所示:

当笔记本被复制后,您应该能够运行代码,从而继续运行所有的单元格。代码将格式化数据,并在本地 Jupyter 笔记本电脑中生成一个 data.csv 文件。

我不会在这篇文章中解释代码是如何工作的,但是为了更容易理解,我在笔记本中加入了注释。

步骤 4:下载格式化数据并导入

可以通过展开左侧窗格,点击“文件”选项卡,右键单击 data.csv 文件(如果还没有,点击刷新)并点击“下载”来下载 data.csv

步骤 5:导入文件并修复列名

返回到 Flourish 模板,点击“导入您的数据”并选择刚刚下载的 data.csv :

出于某种原因,fluorescence 将月份列的名称转换为“dd/mm/YY”格式的日期,但是,这在可视化上看起来不太好,所以让我们用最初给定的名称来重命名这些列。

通过在电子表格编辑器中打开 CSV 文件,复制列名并将其粘贴到 Flourish data 选项卡中,这是一个相当容易的手动操作。

步骤 6:调整可视化和预览

回到预览选项卡,可视化应该已经与您的导入数据动画。此外,在颜色、布局、字体大小等方面,Flourish 提供了调整视觉效果的机会,所以你可以根据自己的喜好随意改变。

最后,点击左上方的“全屏”图标,打开一个只包含可视化的新网页。

步骤 7:保存观想

到现在为止,你应该会看到在一个新窗口中产生的可视化效果,并且赞叹它是多么的整洁!干得好!但是是时候把它保存在某个地方了。

有两种方法,视情况而定,一种可能比另一种更可取。

  1. 另存为 HTML 文件:可视化的全屏预览可以保存为本地独立的 HTML 页面。右键单击页面上的任意位置,然后选择“另存为”并确保格式设置为“网页,完整”

2.记录为 GIF: 将可视化图像记录为 GIF 或任何其他视频格式,这使得它易于分享(在大多数情况下)。有许多程序可以做到这一点。如果你用的是 Windows,一定要用的 ScreenToGif ,如果用的是 Mac,一定要用的 LiCEcap 。使用这两个的主要原因是它们没有录音长度的限制。无论如何,可以随意使用任何达到相同目的的软件。

请注意,由于帧速率的限制,录制为 GIF 可能会给动画带来延迟。

结束了

这就是辅导的结束。我希望这足够简单易懂。保存在本地的观想可以在博客、演示、网站或任何你喜欢的地方分享。

虽然我们只使用免费功能,但我想说,如果你对数据可视化感兴趣,升级到高级账户是值得的。

任何反馈都非常受欢迎。下次见!

逐步了解 LSTM 自动编码器图层

原文:https://towardsdatascience.com/step-by-step-understanding-lstm-autoencoder-layers-ffab055b6352?source=collection_archive---------1-----------------------

这里我们将分解一个 LSTM 自动编码器网络来逐层理解它们。我们将检查各层之间的输入和输出流,并将 LSTM 自动编码器与常规的 LSTM 网络进行比较。

<了解深度学习,了解更多>

在我之前的文章极端罕见事件分类的 LSTM 自动编码器 [ 1 ]中,我们学习了如何为多元时间序列数据构建 LSTM 自动编码器。

然而,深度学习中的 LSTMs 稍微复杂一些。理解 LSTM 中间层及其设置并不简单。例如,return_sequences参数、RepeatVectorTimeDistributed层的用法可能会令人混淆。

LSTM 教程已经很好的解释了 LSTM 单元的结构和输入输出,例如[ 2 , 3 ]。但是,尽管有其特殊性,很少发现解释 LSTM 层在网络中一起工作的机制。

这里我们将分解一个 LSTM 自动编码器网络来逐层理解它们。此外,普遍使用的 seq2seq 网络类似于 LSTM 自动编码器。因此,这些解释中的大多数也适用于 seq2seq。

在这篇文章中,我们将使用一个简单的玩具例子来学习,

  • return_sequences=TrueRepeatVector()TimeDistributed()的含义。
  • 了解每个 LSTM 网络层的输入和输出。
  • 常规 LSTM 网络和 LSTM 自动编码器之间的区别。

理解模型架构

首先进口我们的必需品。

*# lstm autoencoder to recreate a timeseries*
**import** **numpy** **as** **np**
**from** **keras.models** **import** Sequential
**from** **keras.layers** **import** LSTM
**from** **keras.layers** **import** Dense
**from** **keras.layers** **import** RepeatVector
**from** **keras.layers** **import** TimeDistributed*'''*
*A UDF to convert input data into 3-D*
*array as required for LSTM network.*
*'''***def** temporalize(X, y, lookback):output_X = []output_y = []**for** i **in** range(len(X)-lookback-1):t = []**for** j **in** range(1,lookback+1):*# Gather past records upto the lookback period*t.append(X[[(i+j+1)], :])output_X.append(t)output_y.append(y[i+lookback+1])**return** output_X, output_y

创建示例数据

我们将创建一个多元时间序列数据的玩具示例。

*# define input timeseries*
timeseries = np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9],[0.1**3, 0.2**3, 0.3**3, 0.4**3, 0.5**3, 0.6**3, 0.7**3, 0.8**3, 0.9**3]]).transpose()timesteps = timeseries.shape[0]
n_features = timeseries.shape[1]timeseries

Figure 1.1. Raw dataset.

根据 LSTM 网络的要求,我们需要将一个输入数据整形为 n_samples x 时间步长 x n_features 。在这个例子中,n_features 是 2。我们将制作timesteps = 3。这样,结果n_samples是 5(因为输入数据有 9 行)。

timesteps = 3
X, y = temporalize(X = timeseries, y = np.zeros(len(timeseries)), lookback = timesteps)n_features = 2
X = np.array(X)
X = X.reshape(X.shape[0], timesteps, n_features)X

Figure 1.2. Data transformed to a 3D array for an LSTM network.

了解 LSTM 自动编码器结构

在本节中,我们将构建一个 LSTM 自动编码器网络,并可视化其架构和数据流。我们还将考察一个常规的 LSTM 网络,比较它与自动编码器的不同之处。

定义 LSTM 自动编码器。

*# define model*
model = Sequential()
model.add(LSTM(128, activation='relu', input_shape=(timesteps,n_features), return_sequences=**True**))
model.add(LSTM(64, activation='relu', return_sequences=**False**))
model.add(RepeatVector(timesteps))
model.add(LSTM(64, activation='relu', return_sequences=**True**))
model.add(LSTM(128, activation='relu', return_sequences=**True**))
model.add(TimeDistributed(Dense(n_features)))
model.compile(optimizer='adam', loss='mse')
model.summary()

Figure 2.1. Model Summary of LSTM Autoencoder.

*# fit model*
model.fit(X, X, epochs=300, batch_size=5, verbose=0)
*# demonstrate reconstruction*
yhat = model.predict(X, verbose=0)
print('---Predicted---')
print(np.round(yhat,3))
print('---Actual---')
print(np.round(X, 3))

Figure 2.2. Input Reconstruction of LSTM Autoencoder.

model.summary()提供了模型架构的概要。为了更好的理解,让我们在下面的图 2.3 中可视化它。

Figure 2.3. LSTM Autoencoder Flow Diagram.

该图示出了一个数据样本通过 LSTM 自动编码器网络的各层的数据流。数据样本是数据集中的一个实例。在我们的例子中,一个样本是图 1.2 中大小为 3x2 的子数组。

从这个图表中,我们了解到

  • LSTM 网络采用 2D 阵列作为输入。
  • 一层 LSTM 的像元数量与时间步长一样多。
  • 设置return_sequences=True使每个时间步长的每个单元发出一个信号。
  • 这在图 2.4 中变得更加清晰,该图显示了return_sequencesTrue(图 2.4a)与False(图 2.4b)之间的差异。

Figure 2.4. Difference between return_sequences as True and False.

  • 在图 2.4a 中,来自一层中时间步长单元的信号被后续层中相同时间步长的单元接收。
  • 在 LSTM 自动编码器的编码器和解码器模块中,重要的是在如图 2.4a 所示的连续 LSTM 层中的各个时间步长单元之间具有直接连接
  • 在图 2.4b 中,只有最后一个时间步长单元发出信号。因此,的输出是一个矢量
  • 如图 2.4b 所示,如果后续层是 LSTM,我们使用RepeatVector(timesteps)复制这个向量,以获得下一层的 2D 数组。
  • 如果后续层是Dense,则不需要变换(因为Dense层需要一个矢量作为输入)。

回到图 2.3 中的 LSTM 自动编码器。

  • 输入数据有 3 个时间步长和 2 个特征。
  • 第 1 层,LSTM(128),读取输入数据并输出 128 个特征,每个特征有 3 个时间步长,因为return_sequences=True
  • 第二层,LSTM(64),采用第一层的 3x128 输入,并将特征尺寸减小到 64。从return_sequences=False开始,它输出大小为 1x64 的特征向量。
  • 该层的输出是输入数据的编码特征向量
  • 这个编码的特征向量可以被提取并用作数据压缩,或者任何其他监督或非监督学习的特征(在下一篇文章中我们将看到如何提取它)。
  • 层 3,RepeatVector(3),复制特征向量 3 次。
  • RepeatVector 层充当编码器和解码器模块之间的桥梁。
  • 它为解码器中的第一个 LSTM 层准备 2D 阵列输入。
  • 解码器层设计用于展开编码。
  • 因此,解码器层以与编码器相反的顺序堆叠。
  • 第 4 层 LSTM (64)和第 5 层 LSTM (128)分别是第 2 层和第 1 层的镜像。
  • 最后添加第 6 层(时间分布式(密集(2)),以获得输出,其中“2”是输入数据中的要素数。
  • 时间分布图层创建一个长度等于前一图层输出的要素数量的矢量。在这个网络中,第 5 层输出 128 个特征。因此,时间分布图层创建了一个 128 长的矢量,并将其复制了 2 (= n_features)次。
  • 第 5 层的输出是一个 3x128 的数组,我们将其表示为 U,而第 6 层的时间分布的输出是一个 128x2 的数组,表示为 V,U 和 V 之间的矩阵乘法产生一个 3x2 的输出。
  • 拟合网络的目的是使输出接*输入。请注意,这个网络本身确保了输入和输出维度匹配。

LSTM 自动编码器与常规 LSTM 网络的比较

当我们将其与为重构输入而构建的常规 LSTM 网络相比较时,上述理解变得更加清晰。

*# define model*
model = Sequential()
model.add(LSTM(128, activation='relu', input_shape=(timesteps,n_features), return_sequences=**True**))
model.add(LSTM(64, activation='relu', return_sequences=**True**))
model.add(LSTM(64, activation='relu', return_sequences=**True**))
model.add(LSTM(128, activation='relu', return_sequences=**True**))
model.add(TimeDistributed(Dense(n_features)))
model.compile(optimizer='adam', loss='mse')
model.summary()

Figure 3.1. Model Summary of LSTM Autoencoder.

*# fit model*
model.fit(X, X, epochs=300, batch_size=5, verbose=0)
*# demonstrate reconstruction*
yhat = model.predict(X, verbose=0)
print('---Predicted---')
print(np.round(yhat,3))
print('---Actual---')
print(np.round(X, 3))

Figure 3.2. Input Reconstruction of regular LSTM network.

Figure 3.3. Regular LSTM Network flow diagram.

常规 LSTM 网络和 LSTM 自动编码器的区别

  • 我们在所有的 LSTM 图层中都使用了return_sequences=True
  • 这意味着,每一层都输出一个包含每个时间步长的 2D 数组。
  • 因此,没有一维编码的特征向量作为任何中间层的输出。因此,将样本编码成特征向量是不可能的。
  • 这个编码向量的缺失将用于重建的常规 LSTM 网络与 LSTM 自动编码器区分开来。
  • 但是,请注意,在自动编码器(图 2.1)和常规网络(图 3.1)中,参数的数量是相同的。
  • 这是因为,自动编码器中额外的RepeatVector层没有任何附加参数。
  • 最重要的是,两个网络的重建精度相似

引人深思的事

在 LSTM 罕见事件分类自动编码器 [ 1 ]中讨论的使用异常检测方法的罕见事件分类正在训练 LSTM 自动编码器来检测罕见事件。[ 1 中自动编码器网络的目标是重建输入,并将重建不佳的样本归类为罕见事件。

既然,我们也可以建立一个常规的 LSTM 网络来重建一个时间序列数据,如图 3.3 所示,这样会改善结果吗?

这背后的假设是,

由于没有编码层,在某些情况下重建的精度会更好(因为时间维度的维数没有减少)。除非任何其他分析需要编码向量,否则尝试常规 LSTM 网络值得尝试稀有事件分类。

Github 资源库

完整的代码可以在这里找到。

[## cran 2367/理解-lstm-自动编码器

了解 LSTM 自动编码器。通过创建一个项目,为 cran 2367/understanding-lstm-auto encoder 的开发做出贡献

github.com](https://github.com/cran2367/understanding-lstm-autoencoder/blob/master/understanding-lstm-autoencoder.ipynb)

结论

在本文中,我们

  • 通过一个玩具示例来一层一层地理解 LSTM 网络。
  • 了解每层之间的输入和输出流。
  • 理解了return_sequencesRepeatVector()TimeDistributed()的含义。
  • 比较和对比了 LSTM 自动编码器和常规 LSTM 网络。

在下一篇文章中,我们将学习优化一个网络: 如何决定添加一个新层及其大小

参考

  1. Keras 极端罕见事件分类的 LSTM 自动编码器
  2. LSTM 自动编码器简介
  3. 了解 LSTM 及其图表

初学者在 Keras 中逐步实现 VGG16

原文:https://towardsdatascience.com/step-by-step-vgg16-implementation-in-keras-for-beginners-a833c686ae6c?source=collection_archive---------0-----------------------

VGG16 是一种卷积神经网络(CNN)架构,用于在 2014 年赢得 ILSVR(Imagenet)比赛。它被认为是迄今为止最优秀的视觉模型架构之一。关于 VGG16 最独特的事情是,他们没有大量的超参数,而是专注于使用步长为 1 的 3×3 滤波器的卷积层,并始终使用相同的填充和步长为 2 的 2×2 滤波器的最大池层。在整个体系结构中,它始终遵循卷积和最大池层的这种安排。最后,它有 2 个 FC(全连接层),后跟一个 softmax 输出。VGG16 中的 16 指的是它有 16 层有权重。这个网络是一个相当大的网络,它有大约 1.38 亿个(大约)参数。

Architecture of VGG16

我打算在 Keras 中从头开始实现完整的 VGG16。这个实现将在狗和猫的数据集上完成。您可以从下面的链接下载数据集。

https://www.kaggle.com/c/dogs-vs-cats/data

一旦你下载了图片,你就可以继续下面的步骤了。

import keras,os
from keras.models import Sequential
from keras.layers import Dense, Conv2D, MaxPool2D , Flatten
from keras.preprocessing.image import ImageDataGenerator
import numpy as np

在这里,我首先导入实现 VGG16 所需的所有库。我将使用顺序方法,因为我正在创建一个顺序模型。顺序模型意味着模型的所有层将按顺序排列。在这里,我从 keras.preprocessing 导入了 ImageDataGenerator。这是一个非常有用的类,因为它有许多功能来缩放,旋转,缩放,翻转等。这个类最有用的一点是它不会影响存储在磁盘上的数据。该类在将数据传递给模型的过程中不断修改数据。

trdata = ImageDataGenerator()
traindata = trdata.flow_from_directory(directory="data",target_size=(224,224))
tsdata = ImageDataGenerator()
testdata = tsdata.flow_from_directory(directory="test", target_size=(224,224))

在这里,我为训练和测试数据创建了一个 ImageDataGenerator 对象,并将包含训练数据的文件夹传递给对象 trdata,类似地,将包含测试数据的文件夹传递给对象 tsdata。数据的文件夹结构如下-

Folder structure of the data to passed to ImageDataGenerator

ImageDataGenerator 会自动将猫文件夹中的所有数据标记为猫,而不是狗文件夹。通过这种方式,数据很容易传递到神经网络。

model = Sequential()model.add(Conv2D(input_shape=(224,224,3),filters=64,kernel_size=(3,3),padding="same", activation="relu"))model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same", activation="relu"))model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"))model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))

在这里,我首先通过指定模型是顺序模型来初始化模型。初始化模型后,我添加了

→ 2 个 3×3 内核的 64 通道卷积层,填充相同

→ 1 个最大池层,池大小为 2x2,跨度为 2x2

→ 2 个 3×3 内核的 128 通道卷积层,填充相同

→ 1 个最大池层,池大小为 2x2,跨度为 2x2

→256 通道的 3 x3 内核和相同填充的 3x 卷积层

→ 1 个最大池层,池大小为 2x2,跨度为 2x2

→3 x 3 内核和相同填充的 512 通道的 3x 卷积层

→ 1 个最大池层,池大小为 2x2,跨度为 2x2

→3 x 3 内核和相同填充的 512 通道的 3x 卷积层

→ 1 个最大池层,池大小为 2x2,跨度为 2x2

我还添加 relu(整流线性单位)激活到每一层,使所有的负值不会传递到下一层。

model.add(Flatten())model.add(Dense(units=4096,activation="relu"))model.add(Dense(units=4096,activation="relu"))model.add(Dense(units=2, activation="softmax"))

创建完所有的卷积后,我将数据传递给密集层,因此我将卷积后的矢量展*并相加

→ 1 个 4096 单位的密集层

→ 1 个 4096 单位的密集层

→1 x 2 个单元的密集 Softmax 层

我将对 4096 个单元的密集层都使用 RELU 激活,以便停止通过网络转发负值。我在最后使用了一个 2 单位的密集层,因为我有 2 个职业可以预测,分别是狗和猫。softmax 层将根据图像所属类别的模型置信度输出介于 0 和 1 之间的值。

创建 softmax 层后,模型最终准备就绪。现在我需要编译模型。

from keras.optimizers import Adam
opt = Adam(lr=0.001)model.compile(optimizer=opt, loss=keras.losses.categorical_crossentropy, metrics=['accuracy'])

在这里,我将使用亚当优化器达到全局最小值,同时训练出模型。如果我在训练时陷入局部最小值,那么亚当优化器将帮助我们走出局部最小值,达到全局最小值。我们还将指定优化器的学习速率,在本例中,它被设置为 0.001。如果我们的训练在不同的时期有很大的波动,那么我们需要降低学习率,这样我们就可以达到全局最小值。

我可以使用下面的代码检查我创建的模型的概要。

model.summary()

其输出将是我刚刚创建的模型的摘要。

Summary of the model

from keras.callbacks import ModelCheckpoint, EarlyStoppingcheckpoint = ModelCheckpoint("vgg16_1.h5", monitor='val_acc', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)early = EarlyStopping(monitor='val_acc', min_delta=0, patience=20, verbose=1, mode='auto')hist = model.fit_generator(steps_per_epoch=100,generator=traindata, validation_data= testdata, validation_steps=10,epochs=100,callbacks=[checkpoint,early])

创建模型后,我将从 keras 导入 ModelCheckpoint 和 EarlyStopping 方法。我将创建两者的对象,并将其作为回调函数传递给 fit_generator。

ModelCheckpoint 通过监控模型的特定参数来帮助我们保存模型。在这种情况下,我通过将 val_acc 传递给 ModelCheckpoint 来监控验证的准确性。只有在当前时期的模型验证精度高于上一时期的模型验证精度时,才会将模型保存到磁盘。

如果我在早期停止中设置监控的参数没有增加,早期停止有助于我们尽早停止模型的训练。在这种情况下,我通过将 val_acc 传递给 EarlyStopping 来监控验证的准确性。我在这里将耐心设置为 20,这意味着如果模型在 20 个时期内没有看到验证准确性的任何提高,它将停止训练。

我使用 model.fit_generator,就像我使用 ImageDataGenerator 将数据传递给模型一样。我将把训练和测试数据传递给 fit_generator。在 fit_generator 中,steps_per_epoch 将设置批量大小以将训练数据传递给模型,validation_steps 将对测试数据执行相同的操作。您可以根据您的系统规格进行调整。

在执行上述代码行之后,模型将开始训练,您将开始看到训练/验证的准确性和损失。

Training of the model

一旦你训练了模型,你可以可视化训练/验证的准确性和损失。您可能已经注意到,我正在将 mode.fit_generator 的输出传递给 hist 变量。所有的训练/验证准确性和损失都存储在 hist 中,我将从那里可视化。

import matplotlib.pyplot as plt
plt.plot(hist.history["acc"])
plt.plot(hist.history['val_acc'])
plt.plot(hist.history['loss'])
plt.plot(hist.history['val_loss'])
plt.title("model accuracy")
plt.ylabel("Accuracy")
plt.xlabel("Epoch")
plt.legend(["Accuracy","Validation Accuracy","loss","Validation Loss"])
plt.show()

在这里,我将使用 matplotlib 可视化训练/验证准确性和损失。

training/validation accuracy and loss

为了对训练好的模型进行预测,我需要加载保存最好的模型,预处理图像,并将图像传递给模型进行输出。

from keras.preprocessing import imageimg = image.load_img("image.jpeg",target_size=(224,224))
img = np.asarray(img)
plt.imshow(img)
img = np.expand_dims(img, axis=0)from keras.models import load_model
saved_model = load_model("vgg16_1.h5")output = saved_model.predict(img)
if output[0][0] > output[0][1]:print("cat")
else:print('dog')

Output of the model

在这里,我已经使用 keras 中的 image 方法加载了图像,并将其转换为 numpy 数组,并为图像添加了一个额外的维度,以匹配 keras 的 NHWC(数字、高度、宽度、通道)格式。

这是一个完整的 VGG16 在 keras 中使用 ImageDataGenerator 的实现。我们可以根据需要分类的类别,将最后一个 softmax 密集层的单位更改为我们想要的任何数量,从而使该模型适用于任何数量的类别

Github 回购链接:https://github.com/1297rohit/VGG16-In-Keras

如果你的数据量较少,那么你可以尝试迁移学习,而不是从头开始训练你的模型。我还为初学者编写了一个使用 Keras 在 VGG16 上进行迁移学习的分步指南。可以到:https://medium . com/@ 1297 rohit/transfer-learning-from scratch-using-keras-339834 b 153 b 9查看

如果你想从头开始一步一步地学习人脸检测和人脸识别,那么你可以点击链接阅读我的文章:https://medium . com/@ 1297 rohit/step-step-by-step-Face-Recognition-code-implementation-from-scratch-in-python-cc95fa 041120

享受分类!

建模前的步骤:清理至 EDA

原文:https://towardsdatascience.com/steps-before-modeling-cleaning-to-eda-9a9e02981e57?source=collection_archive---------21-----------------------

Python 中的数据清理和 EDA 初学者指南

在能够利用我们都知道并喜爱的机器学习算法之前,重要的是要了解如何最初以适当的顺序获得数据,以及如何有效地分析数据,以便产生最佳模型。这篇文章将提供一个基本的路线图,数据科学家在使用 Python 处理新数据集时可以遵循它来执行探索性数据分析(EDA)。

数据集:

在这篇文章中,我们将调查 2017 年和 2018 年各州的 SAT 和 ACT 参与率。数据集包括每个考试部分的全州*均分数、两次考试的综合/总分以及参与率。

Python 库:

#Imports:
import num               as np
import pandas            as pd
import matplotlib.pyplot as plt
import seaborn           as snsfrom scipy               import stats

初步审查:

在将文件加载到 Pandas dataframe 中之后,查看前几行和数据集的大小会对您正在处理的内容有所帮助。这最好通过使用来完成。头()。形状方法。

First 10 rows of 2017 SAT data

。describe() 方法提供了数据集中定量特征的快速统计概览,从每个特征的标准差到最小值和最大值。这也可以用来发现潜在的异常值。在下图中,我们可以很快看到科学的最低分数是 2.3,与其他值相比,这看起来并不正确。这需要进一步研究。

Summary of 2017 ACT data

act_2017.sort_values('Science').head()

利用 sort_values() 方法,我们可以看到马里兰州的*均科学分数为 2.3。这很可能是一个打字错误,需要更正。

描述完数据后,务必确保没有缺失值,并且所有数据类型都适用于每个要素。这个。 isnull()。在这种情况下,最好使用 info() 方法。

act_2018.isnull().sum()State            2
Participation    2
Composite        2

从上面我们可以看到,2018 ACT 数据在每一列中都包含 2 个缺失值。下面的参与列作为一个对象列出,但它应该是一个浮点型,因为值是百分比。

这些 Pandas 方法为我们提供了数据的初步视图,以及在我们开始建模之前可能需要清理或纠正的内容。

数据清理:

在我们的初步审查之后,修复我们发现的错误是很重要的。首先,我们将使用将马里兰的科学分数改写为 23.2。锁定以隔离数据框中的特定位置。

act_2017.loc[act_2017['State'] == "Maryland", 'Science'] = 23.2

下面,我们可以看到包含空值的 2 行。

act_2018.drop(act_2018.index[[52,53]], inplace = True)

上面的代码可以用来删除两行丢失的值。。dropna() 方法是另一个有用的工具,当有丢失的值需要删除时。

最后,在我们开始可视化数据之前,我们需要纠正参与列的数据类型。使用。astype() 方法,我们可以将列中的值更新为浮点数而不是对象。

sat_2018['Participation'] = sat_2018['Participation'].astype(float)

可视化数据:

创建可视化可以帮助我们更详细地理解数据,并允许我们发现潜在的关系,这些关系是我们仅通过描述数据无法看到的。可视化还可以揭示可能会扭曲我们结果的异常值。我们将使用 seaborn 和 matplotlib 库来创建我们的可视化。

关联热图对于查看要素之间的线性关系非常有用。决定在模型中使用哪些要素时,避免多重共线性非常重要。在下图中,较亮的值表示高度正相关的要素,较暗的图像表示高度负相关的要素。这两种考试的分数和参与率往往是逐年相关的。

sns.heatmap(final.corr(),mask=mask, vmax=.3, square=True, annot=True)

Correlation Heatmap of All Features

散点图是查看两个特征之间是否存在线性关系的另一种方法。

# Establish the size of the figure.
plt.figure(figsize=(16, 9))# Create scatter plot of SAT vs. ACT math scores for 2017.
sns.regplot(stats.zscore(final['total_sat_2017']),stats.zscore(final['composite_act_2017']), ci = None, line_kws = {'color': 'orange'})plt.title("SAT vs. ACT 2017 Overall Scores", fontsize = 25)
plt.ylabel("ACT 2017 Composite ZScores", fontsize = 20)
plt.xlabel("SAT 2017 Composite ZScores", fontsize = 20)
plt.xticks(size = 12)
plt.yticks(size = 12);

从散点图可以看出,ACT 和 SAT 综合成绩是负相关的。所以,一门考试考得好,不一定代表你另一门也会考得好。

直方图在查看特征分布时非常有用。下面的代码在同一个图上创建了两个直方图,因此我们可以并排分析这些特征。

plt.figure(figsize=(16, 8))plt.subplot(1, 2, 1)
final['total_sat_2017'].hist()
plt.title('2017 SAT Total Scores', size = 25)
plt.xlabel('Scores', size = 20)
plt.ylabel('Frequency', size = 20)
plt.vlines(x = np.mean(final['total_sat_2017']), ymin = 0, ymax = 10, color = 'r')
plt.xticks(size = 12)
plt.yticks(size = 12)plt.subplot(1, 2, 2)
final['total_sat_2018'].hist()
plt.title('2018 SAT Total Scores', size = 25)
plt.xlabel('Scores', size = 20)
plt.ylabel('Frequency', size = 20)
plt.vlines(x = np.mean(final['total_sat_2018']), ymin = 0, ymax = 10, color = 'r')
plt.xticks(size = 12)
plt.yticks(size = 12)

从上面的直方图我们可以看出,2017 年和 2018 年的 SAT 总分并不是正态分布,而是向右偏的。在这两年中,分数下降的频率在 1100 和 1200 之间。看了这张图之后,我们可能会决定进一步研究为什么会有这种差距。

最后,箱线图在查看要素分布时也很有用,但它们也有助于发现异常值。

#2017 ACT scores by section
plt.figure(figsize = (16, 9))plt.title("ACT Subsection Scores 2017", size = 25)
sns.boxplot(data = final[["math_act_2017", "science_act_2017", "english_act_2017", "reading_act_2017"]])plt.ylabel("Average Score", size = 20)
plt.xlabel('Section', size = 20)plt.xticks(size = 16)
plt.yticks(size = 16)

在上图中,我们可以看到 2017 年 ACT 分段分数的数据集中没有剩余异常值。在执行数据清理时,科学部分中的异常值已被移除。

后续步骤:

现在,我们的数据是干净的,我们已经分析了我们的特征,我们准备开始预处理和建模。

正确清理数据集和执行 EDA 是数据科学家工作流程中的关键步骤。每个数据集都是不同的,但希望你学到了一些有用的方法,下次当你面临需要分析数据集的问题时可以遵循这些方法。

这个帖子的代码可以在我的 Github 上找到。

你也可以在LinkedIn上找到我。

从零开始到基本现代神经网络模型的步骤

原文:https://towardsdatascience.com/steps-to-basic-modern-nn-model-from-scratch-1e86b7c042?source=collection_archive---------20-----------------------

该博客将包括创建初级神经网络的步骤,从理解矩阵乘法开始,到构建你的训练循环。除了构建神经网络,我还将讨论各种定制技术。

Photo by Gertrūda Valasevičiūtė on Unsplash

步骤 1 — MatMul

今天,我们将学习构建神经网络的第一步,即初级矩阵乘法。有许多方法可以做到这一点,我们将看到每一种方法,并将比较它们以获得最佳结果。

我们需要神经网络的线性层中的矩阵乘法。要做矩阵乘法,我们需要一个数据集。Fastai 很好地提供了各种数据集,我们将使用 MNIST 数据集来做操作。

所以,让我们抓住数据集。

  • 首先,我正在导入我将在整个系列中使用的库。
  • 之后,我正在下载带有扩展名.gz的 MNIST 数据集。
  • 因为下载的文件是 pickle 格式的;因此,我使用函数pickle.load来访问数据集。
  • 下载的数据集是 numpy 数组,我们希望 PyTorch 张量执行关于神经网络的操作。因此,我使用map函数将 numpy 数组映射到 torch 张量。
  • 这样,我们的数据集就准备好了。

Training dataset

Validation dataset

weights = torch.randn(784,10)
bias = torch.zeros(10)m1 = x_valid[:5]
m2 = weightsm1.shape,m2.shape **= (torch.Size([5, 784]), torch.Size([784, 10]))**

类型 1:简单的 Python 程序

我们可以用简单的 python 程序做矩阵乘法。但是 python 程序需要很多时间来实现,让我们来看看如何实现。

%timeit -n 10 t1=matmul(m1, m2)

847 ms

  • 当验证数据集中只有 5 行时,847 ms 是一段很长的时间。

类型 2:元素式操作

Pytorch 为我们提供了一种毫不费力的方法来做矩阵乘法,它被称为元素操作。让我们来理解一下。

  • 我们已经消除了最后一个循环。
  • 在逐元素运算中,乘法单元被视为秩为 1 的张量。
m2[:, 1].shape**=** **torch.Size([784])**m1[1, :].shape**=** **torch.Size([784])**
  • 上面的代码在 c 中运行,让我们看看它执行所用的时间。
%timeit -n 10 t1=matmul(m1, m2)

1.31 ms < 847 ms

类型 3:广播

广播是矩阵乘法的另一种方式。

根据 Scipy 文档,术语 broadcasting 描述了 numpy 在算术运算中如何处理不同形状的数组。在某些约束条件下,较小的阵列在较大的阵列中“广播”,以便它们具有兼容的形状。广播提供了一种向量化数组操作的方法,因此循环在 C 而不是 Python 中发生。这样做不会产生不必要的数据副本,并且通常会导致高效的算法实现。广播发生在一个 C 速度和 CUDA 速度的 GPU 上。

m1[2].unsqueeze(1).shape **= torch.Size([784, 1])**
  • 在广播中,尺寸为[1 * 784]的输入的整个列被压缩为[784 * 1],然后乘以权重。
  • 最后,在列中取总和作为sum(dim=0),并存储在c中。
%timeit -n 10 _=matmul(m1, m2)

265 us << 1.31 ms < 847 ms

第四类:爱因斯坦求和

爱因斯坦求和(einsum)是一种以一般方式组合乘积和求和的紧凑表示。

来自 numpy docs:
"下标字符串是一个逗号分隔的下标标签列表,其中每个标签都指向相应操作数的一个维度。"

  • 这是一种更紧凑的表示。
  • 输入的数量代表输入的秩ik表示秩 2 张量,kj表示秩 2 张量。
  • 矩阵的维数表示为i*kk*ji*j
  • 每当你看到重复的维度,就在那个维度上做点积。
%timeit -n 10 _=matmul(m1, m2)

39.5 us <<< 265 us << 1.31 ms < 847 ms

类型 5: PyTorch 操作

我们可以直接用 PyTorch 的函数或算子进行矩阵乘法。

%timeit -n 10 t2 = m1.matmul(m2)

15.5 us < 39.5 us <<< 265 us << 1.31 ms < 847 ms

%timeit -n 10 t2 = m1@m2

10.9 us < 15.5 us < 39.5 us <<< 265 us << 1.31 ms < 847 ms

因此,我们可以很容易地比较各种代码的时序。这也是我们不喜欢用 Python 语言编写代码的原因,因为它的性能很慢。因此,大多数 python 库都是用 c 实现的。

步骤 2 和 3 — Relu/init &向前传递

在我们定义了矩阵乘法策略之后,是时候为神经网络定义 ReLU 函数和前向传递了。我想请读者浏览一下本系列的第 1 部分,以了解下面使用的数据的背景。

神经网络定义如下:

output = MSE(Linear(ReLU(Linear(X))))

基础架构

n,m = x_train.shape
c = y_train.max()+1
**n,m,c**

让我们解释一下矩阵乘法的权重。

我将创建一个两层的神经网络。

  • 第一线性层将进行输入与 w1 的矩阵乘法。
  • 第一个线性图层的输出将作为第二个线性运算的输入,该输入将乘以 w2。
  • 我将获得单个输出,并使用 MSE 来计算损失,而不是针对单个输入获得十个预测。
  • 让我们宣布权重和偏差。
w1 = torch.randn(m,nh)
b1 = torch.zeros(nh)w2 = torch.randn(nh,1)
b2 = torch.zeros(1)
  • 当我们使用 PyTorch randn声明权重和偏差时,获得的权重和偏差被归一化,即它们的均值为 0,而标准差为 1。
  • 我们需要对权重和偏差进行归一化,以便它们不会在对神经网络的输入进行线性运算后产生实质性的值。因为大量的输出对计算机来说变得难以处理。因此,我们倾向于将输入标准化。

  • 出于同样的原因,我们希望 out 输入矩阵的均值为 0,标准差为 1,但目前并非如此。让我们看看。****
train_mean,train_std = x_train.mean(),x_train.std()
train_mean,train_std

  • 让我们定义一个函数来归一化输入矩阵。
def normalize(x, m, s): return (x-m)/sx_train = **normalize**(x_train, train_mean, train_std)
x_valid = **normalize**(x_valid, train_mean, train_std)
  • 现在,我们根据相同的均值和标准差对训练数据集和验证数据集进行归一化,以便我们的训练数据集和验证数据集具有相同的特征定义和比例。现在,让我们重新检查一下*均值标准差

Mean approx. to 0 & SD approx. to 1

  • 现在,我们有了标准化的权重、偏差和输入矩阵。

让我们为神经网络定义线性层并执行操作。

def lin(x, w, b): return x@w + bt = lin(x_valid, w1, b1)
t.mean(),t.std()

现在,线性运算后获得的*均值和标准偏差再次是非归一化的。现在,问题还是单纯的。如果保持这种状态,更多的线性运算将导致重要的和实质性的价值,这将是一个挑战。因此,我们希望线性运算后的激活也能被规范化。

简化的明凯初始化或氦初始化

为了处理线性神经网络操作的非标准化行为,我们定义了将被明凯初始化的权重。尽管明凯归一化或初始化被定义为处理 ReLu/泄漏 ReLu 操作,我们仍然可以将其用于线性操作。

我们将权重除以 math.sqrt(x ),其中 x 是行数。

完成上述琐事后,我们得到归一化的*均值和标准差。

def lin(x, w, b): return x@w + bt = lin(x_valid, w1, b1)
t.mean(),t.std()

让我们为神经网络定义ReLU层并执行操作。现在,为什么我们将 ReLU 定义为非线性激活函数,我希望你知道 通用逼*定理。

def relu(x): return x.clamp_min(0.)
t = relu(lin(x_valid, w1, b1))t.mean(),t.std()

t = relu(lin(x_valid, w1, b1))
t = relu(lin(t, w2, b2))t.mean(),t.std()

你注意到什么奇怪的事情了吗?

请注意,我们的标准偏差是线性运算后得到的一半,如果它在一层后减半,想象在八层后它将达到 1/2 ⁸,这非常非常小。如果我们的神经网络有 10000 层😵,算了吧。

来自 PyTorch docs:
a:该层之后使用的整流器的负斜率(ReLU 默认为 0)

这是在描述 Imagenet 获奖方法的论文中介绍的,作者是何等人:深入研究整流器,这也是第一篇声称 Imagenet 具有“超人性能”的论文(最重要的是,它介绍了 ResNets!)

因此,按照相同的策略,我们将把我们的权重乘以math.sqrt(2/m)

w1 = torch.randn(m,nh)*math.sqrt(2/m)t = relu(lin(x_valid, w1, b1))
t.mean(),t.std()

It is still better than (0.1276, 0.5803).

虽然我们有了更好的结果,但*均水*还是不太好。根据 fastai 文档,我们可以通过下面的调整来处理*均值。

def relu(x): return x.clamp_min(0.) - 0.5w1 = torch.randn(m,nh)*math.sqrt(2./m )
t1 = relu(lin(x_valid, w1, b1))
t1.mean(),t1.std()

Now, it is so much better.

让我们结合上述所有代码和策略,创建我们的神经网络的正向传递。PyTorch 定义了明凯归一化的方法,即kaiming_normal_

def model(xb):l1 = lin(xb, w1, b1)l2 = relu(l1)l3 = lin(l2, w2, b2)return l3%timeit -n 10 _=**model(x_valid)**

对于正向传递,最后要定义的是损失函数:MSE。

根据我们以前的知识,我们通常使用CrossEntroyLoss作为单标签分类函数的损失函数。我稍后会谈到这个问题。目前,我使用 MSE 来理解操作。

def mse(output, targ): return (output.squeeze(-1) - targ).pow(2).mean()

让我们对训练数据集执行上述操作。

preds = model(x_train)
preds.shape, preds

为了执行 MSE,我们需要浮动。

y_train,y_valid = y_train.float(),y_valid.float()**mse(preds, y_train)**

在所有上述操作之后,仍有一个问题没有得到实质性的回答,它是

为什么我们需要明凯初始化?

让我们再来理解一下。

如下初始化两个张量。

import torch**x** = torch.randn(512)
**a** = torch.randn(512,512)

对于神经网络,主要步骤是矩阵乘法,如果我们有一个大约 100 层的深度神经网络,那么让我们看看所获得的激活的标准偏差和*均值。

for i in range(100):**x = x @ a**x.**mean()**, x.**std()**

mean=nan, sd=nan

我们可以很容易地看到*均值,标准差不再是一个数字。这也是合理的。计算机不能储存那么多的数字;它无法解释如此庞大的数字。出于同样的原因,它限制了从业者训练这样的深度神经网络。

你会遇到的问题是激活爆炸:很快,你的激活将去南。我们甚至可以在第一次出现这种情况时要求循环中断:

for i in range(100):**x** = x @ aif x.std() != x.std(): **break**i

Just after 28 loops

因此,这样的问题导致了明凯初始化的发明。最终想出这个主意肯定花了几十年时间。

S o,这就是我们如何定义神经网络的 ReLu 和反向传递。

步骤 4 —向后传球

到目前为止,我们已经理解了矩阵乘法、ReLu 函数和神经网络前向传递背后的思想。现在,我们将讨论向后传球。

在进入后传之前,让我们先了解一个问题。

什么是反向传播?

这是深度学习实践者的花哨术语,尤其是在你和某人讨论的时候。但是,更简单地说,反向传播只是通过链式法则计算梯度。我们发现关于权重/参数的梯度。就是这么简单。反向传播正好与正向传播的梯度相反。

让我们一步一步地寻找梯度。

MSE 层的梯度

def mse(output, targ): return (output.squeeze(-1) — targ).pow(2).mean()

def **mse_grad**(inp, targ):**# grad of loss with respect to output of previous layer**inp.g = 2\. * (inp.squeeze() - targ).unsqueeze(-1) / inp.shape[0]
  • 我们计算输入层的梯度,这是前一层的输出。MSE 的梯度定义为
    2(predicted — target)/mean
  • 由于计算梯度形成链规则,我们需要存储每一层的梯度,这得到乘以前一层。出于这个原因,我们将渐变保存在inp.g输入层,因为它是前一层的输出层。

ReLU 的坡度

现在,对于任何大于 0 的值,我们都要用 0 来代替,对于小于 0 的值,我们要保持它们为 0。

def relu(x): return x.clamp_min(0.)

def **relu_grad**(inp, out):**# grad of relu with respect to input activations**inp.g = (inp>0).float() * out.g
  • 我们将前一层的梯度相乘,这是 ReLU 的输出层,即out.g
  • 这定义了链式法则。

线性层的渐变

我发现线性图层的渐变比其他图层更难理解。但我会尽量简化。

def lin(x, w, b): return x@w + b

def **lin_grad**(inp, out, w, b):**# grad of matmul with respect to weights****inp.g** = out.g @ w.t() **w.g** = (inp.unsqueeze(-1) * out.g.unsqueeze(1)).sum(0)**b.g** = out.g.sum(0)
  • inp.g —首先,我们计算关于参数的线性层的梯度。
  • w.g —重量梯度
  • b . g——与重量相关的偏差梯度。

现在,让我们把向前传球和向后传球结合起来。

def **forward_and_backward**(inp, targ):**# forward pass:****l1** = inp @ w1 + b1**l2** = relu(l1)**out** = l2 @ w2 + b2  **# we don't actually need the loss in backward!****loss** = mse(out, targ)**# backward pass:****mse_grad**(out, targ)**lin_grad**(l2, out, w2, b2)**relu_grad**(l1, l2)**lin_grad**(inp, l1, w1, b1)

forward_and_backward(x_train, y_train)

如果我们把我们计算的梯度和 PyTorch 计算的梯度进行比较。

在比较之前,我们需要存储我们的梯度。

**w1g** = w1.g.clone()
**w2g** = w2.g.clone()
**b1g** = b1.g.clone()
**b2g** = b2.g.clone()

我们稍微作弊,用 PyTorch 签名来检查我们的结果。

**xt2** = x_train.clone().requires_grad_(True)
**w12** = w1.clone().requires_grad_(True)
**w22** = w2.clone().requires_grad_(True)
**b12** = b1.clone().requires_grad_(True)
**b22** = b2.clone().requires_grad_(True)

让我们使用 PyTorch 定义正向函数来计算梯度。

def **forward**(inp, targ):**# forward pass:****l1** = inp @ w12 + b12 **l2** = relu(l1) **out** = l2 @ w22 + b22**# we don't actually need the loss in backward!****return** mse(out, targ)loss = forward(xt2, y_train)
loss.backward()

让我们比较一下 w2 的梯度。

w22.grad.T, w2g.T

They are almost the same.

现在,我们有很多方法可以重构上面写的代码,但这不是我们所关心的。我们需要理解神经网络反向传递背后的语义。这就是我们在模型中定义向后传球的方式。

步骤 4(b) —卷积网络的明凯初始化

在前一部分中,我们寻找了稳定非线性激活动作效果的明凯初始化的需求。现在,主要是看明凯初始化如何用于卷积网络。我还会告诉你它是如何在 PyTorch 中实现的。因此,让我们开始学习之旅。

背景

从上一章中,我们得到了下面的值。

**x_train.shape, y_train.shape, x_valid.shape, y_valid.shape**

让我们看看数据集的形状。

**x_train**[:100].shape, **x_valid**[:100].shape

根据我们对卷积网络的了解,让我们使用 PyTorch 创建一个简单的卷积神经网络。

import torch.nn as **nn****nh**=32
**l1** = nn.**Conv2d**(1, nh, 5)
  • CNN 的输入层数是 1。
  • 输出滤波器或层的数量是 32。
  • 5代表仁的大小。

当我们谈到明凯初始化时,首先想到的是计算卷积神经网络权重的均值和标准差。

def **stats**(x): return x.mean(),x.std()

l1 在其中定义了权重。在计算统计数据之前,让我们先了解它们。

l1.weight.shape

按重量计:

  • 32表示输出层/过滤器的数量。
  • 1代表输入层数
  • 5, 5代表内核大小。

我们需要关注卷积神经网络的输出。

**x = x_valid[:100]** 
# *you may train the neural network using the training dataset but for now, I am taking vaidation daaset. There is no specific reason behind it.*x.shape

  • 100 —图像数量
  • 1 —输入层。
  • 28, 28 —输入图像的尺寸。
**t** = l1(x)
t.shape

  • 100 —图片数量
  • 32 —输出层数
  • 24, 24 —果仁大小
stats(t)

但是,我们希望标准差为 1,而不是 0.6,尽管我们的*均值为 0。因此,让我们将明凯初始化应用于权重。

init.**kaiming_normal_**(l1.weight, a=1.)
**stats**(l1(x))

现在,更好了。*均值几乎为 0,标准差大约为 1。

但是,明凯初始化被引入来处理非线性激活函数。让我们来定义一下。

import torch.nn.functional as **F**def f1(x,a=0): return F.**leaky_relu**(l1(x),a)init.**kaiming_normal_**(l1.weight, a=0)
**stats**(f1(x))

— Mean 不在 0 附*,但 SD 几乎等于 1。

没有明凯初始化,让我们找到统计数据。

l1 = nn.**Conv2d**(1, nh, 5)
stats(f1(x))

  • 现在,你可以很容易地比较有和没有明凯的统计数据。
  • 在明凯,结果要好得多。

比较

现在,让我们将我们的结果与 PyTorch 进行比较。在此之前,我们需要看到 PyTorch 代码。

**torch.nn.modules.conv._ConvNd.reset_parameters**

明凯制服

计算 _ 校正 _ 风扇

计算扇入扇出

让我们了解一下上面的方法。

  • PyTorch 使用明凯制服,而不是明凯正常。明凯统一在价值边界上不同于后者。

  • calculate_fan_in_fan_out()中有一个变量receptive_field_size。计算如下。
l1.weight.shape** = torch.Size([32, 1, 5, 5])**l1.weight[0,0].**shape= torch.Size([5, 5])**rec_fs = **l1.weight[0,0].numel()**
**rec_fs**

  • fan_in(number of input parameters)fan_out(number of output filters)计算如下。
nf,ni,*_ = **l1.weight.shape**
nf,ni

32 is output filters/layers, 1 is the input layer

**fan_in**  = ni*rec_fs
**fan_out** = nf*rec_fsfan_in,fan_out

  • 明凯 _ 制服()里多了一个参数gain。它是非线性激活函数中的泄漏量。其定义如下。
def **gain**(a): return math.sqrt(2.0 / (1 + a**2))
  • 对于 ReLU,a 的值为 0。因此,ReLU 的 gain 值是 math.sqrt(2.0)。查看下面的链接。

[## 皮托赫/皮托赫

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/pytorch/pytorch/blob/fd4f22e4eaae17b8ee8c7de8b0b2b0e202fdf147/torch/nn/init.py#L60)

从所有上述知识,我们可以创建我们的明凯 _ 制服如下。

def **kaiming2**(x,a, use_fan_out=False):**nf,ni**,*_ = x.shape**rec_fs** = x[0,0].shape.numel()**fan** = nf*rec_fs if use_fan_out else ni*rec_fs**std** = gain(a) / math.sqrt(fan)**bound** = math.sqrt(3.) * std**x.data.uniform_**(-bound,bound)

让我们来计算一下统计数据。

**kaiming2**(l1.weight, a=0);
**stats**(f1(x))

成绩还是比较好的。

这就是明凯概念在卷积神经网络中的应用。

步骤 5 —训练循环

现在,我们已经到了需要了解交叉熵损失的地步,因为交叉熵损失主要用于单分类或多分类问题。因为我们使用 MNIST 数据集,所以我们需要创建一个神经网络来预测 10 个数字,即从 0 到 9。之前,我们使用 MSE 损失并预测单一结果,这是我们通常不做的。

所以在深入学习损失函数之前,让我们使用 PyTorch nn.module 创建一个神经网络。

from torch import nn
class **Model**(**nn**.Module):def __init__(self, n_in, nh, n_out):super().__init__()**self.layers** = [nn.**Linear**(n_in,nh), nn.**ReLU**(),      nn.**Linear**(nh,n_out)]def __call__(self, x):for l in self.layers: x = **l(x)**return **x**

我们有下面定义的变量。

**n,m** = x_train.shape
**c** = y_train.max()+1
**nh** = 50

让我们再次定义权重。

**w1** = torch.randn(m,nh)/math.sqrt(m)
**b1** = torch.zeros(nh)
**w2** = torch.randn(nh,10)/math.sqrt(nh)
**b2** = torch.zeros(10)

您可以观察到重量初始化的差异。这一次,我们需要十个预测,输出中的每个数字一个。这就是我把 w2 初始化为(nh,10)的原因。

model = Model(m, nh, 10)
pred = model(x_train)**pred.shape**

—交叉熵损失

同样,在沉迷于交叉熵损失之前,我们需要对我们的预测或激活进行 softmax。我们在这种情况下做 softmax 我们想要单一标签分类。在实践中,当我们计算损失时,我们将需要 softmax 的对数,因为它有助于进一步计算交叉熵损失。

Softmax 定义为:

或者更简洁地说:

def log_softmax(x): return (x.exp()/(x.exp().sum(-1,keepdim=True))).log()
  • x.exp().sum(-1,keepdim=True)将对该行激活的指数求和。
  • 如果keepdimTrue,则输出张量的大小与input相同,除了在维度dim中其大小为 1。否则,dim被压缩,导致输出张量比input少一个维度。

Dimensions are squeezed

既然我们已经定义了log_softmax,那就让我们取预测的log_softmax

sm_pred = log_softmax(pred)

交叉熵损失定义如下:

**def** CrossEntropy(yHat, y):**if** y == 1:**return** -log(yHat)**else**:**return** -log(1 - yHat)

在二进制分类中,类的数量 M 等于 2,交叉熵可以计算为:

−(*𝑦*log(*𝑝*)+(1−*𝑦*)log(1−*𝑝*))

如果 M>2(即多类分类),我们计算每个观察的每个类标签的单独损失,并对结果求和。

我们的问题是多类分类,所以我们的交叉熵损失函数将是后一个。多类分类的交叉熵损失函数也可以使用 numpy 风格的整数数组索引来完成。让我们用它来实现。

def **nll**(input, target): return -input[range(target.shape[0]), target].mean()
**loss** = nll(sm_pred, y_train)

请注意,公式

当我们计算 log softmax 时,给出了一个简化,之前定义为(x.exp()/(x.exp().sum(-1,keepdim=True))).log()

def **log_softmax**(x): return x - x.exp().sum(-1,keepdim=True).log()
**loss** = **nll**(log_softmax(pred), y_train)

然后,有一种更稳定的计算指数之和的对数的方法,叫做 LogSumExp 窍门。这个想法是使用下面的公式:

where a is the maximum of the 𝑥𝑗.

  • 从预测中取出最大值。
  • 从预测的指数中减去最大值。
  • 最后,将最大值添加到操作日志中,如上图所示。
  • 它有助于计算,并使它更快,而不影响任何情况下的输出。

让我们定义我们的 LogSumExp。

**m** = **pred**.max(-1)[0]
m[:,None]

def **logsumexp**(x):m = x.max(-1)[0]return m + (x-m[:,None]).exp().sum(-1).log()

因此我们可以将它用于我们的log_softmax功能。

def **log_softmax**(x): return x - x.**logsumexp**(-1,keepdim=True)

让我们看看 PyTorch 中的上述实现。

import torch.nn.functional as F
F.**nll_loss**(F.**log_softmax**(pred, -1), y_train)

在 PyTorch 中,F.log_softmaxF.nll_loss被组合在一个优化函数F.cross_entropy中。

—基本训练循环

训练循环重复以下步骤:

  • 根据一批输入获取模型的输出
  • 将输出与我们拥有的标签进行比较,并计算损失
  • 计算损失相对于模型每个参数的梯度
  • 用这些梯度更新参数/权重,使它们更好一点。
  • 在称为epochs的循环中重复上述步骤。

让我们结合上述所有概念,创建我们的循环。

bs = 64
lr = 0.5   # learning rate
epochs = 1 # how many epochs to train for

S o,这就是我们在神经回路中定义训练回路的方式。现在,在 PyTorch 中,它有一些语法差异,你现在可以理解了。随着时间的推移,我将在这个系列中添加更多的步骤。在那之前,请随意探索 fastai。

参考

  • fast.ai

STL 分解:如何从零开始?

原文:https://towardsdatascience.com/stl-decomposition-how-to-do-it-from-scratch-b686711986ec?source=collection_archive---------0-----------------------

弄清楚什么是 STL 分解,以及它是如何工作的。

这篇文章将帮助你理解什么是 STL 分解,以及如何从头开始。最后,我也将使用 statsmodel 库,在几秒钟内得到结果。

什么是 STL 分解?

所以,STL 代表使用黄土进行季节和趋势分解。这是一种将时间序列数据分解为包含季节性、趋势和残差的 3 个分量的统计方法。

现在,什么是时间序列数据?它是一系列数据点,在一个连续的时间轴上变化。下面是一个时间序列数据的例子,你可以看到时间轴是在一个小时的水*,股票价值随时间而变化。

现在我们来谈谈趋势。趋势给你一个总体数据的大致方向。从上面的例子中,我可以说,从上午 9:00 到上午 11:00 有一个下降趋势,从上午 11:00 到下午 1:00 有一个上升趋势,下午 1:00 之后趋势是恒定的。

而季节性是以固定时间间隔重复出现的规则且可预测的模式。例如,下图有助于我们了解零售商每月的总销售量。所以,如果我们仔细观察,我们会发现每年 12 月份的单位销售额都在增加。因此,在 12 个月的时间内,单位销售额有一个规律或季节性。

随机性或噪声或残差是随机波动或不可预测的变化。这是我们无法猜测的。例如,2014 年 3 月有一个高单位销售额,这在每个 3 月都是不规则的。因此,我们可以说,在这个月中,它有一些高百分比的噪声或残余。

现在,我们来谈谈黄土。因此,黄土是一种回归技术,它使用局部加权回归来拟合通过序列中的点的*滑曲线,在我们的情况下,序列是时间序列数据。要更详细地了解黄土,点击这里。

如何从零开始做 STL 分解?

所以在这里,我采用 Corporación Favorita 杂货销售预测数据集来可视化每一步。为了更好地理解,我将数据按月进行了汇总。

该数据集的时间序列数据如下所示。这里我们可以观察 2013 年到 2016 年每个月售出的单位价值。

第一步

找出符合上述时间序列数据的*似趋势线。

第二步

通过用*似趋势线减去时间序列数据,找到去趋势序列。

第三步

找出季节性因素。在这里,我找出了月水*上的季节性(周期= 12)。因此,我必须按月对去趋势化系列进行分组,以找出整个数据(48 个月)中每个月的*均销售量。

第四步

在整个数据中填充此组件(48 个月)。

第五步

通过用季节性数据减去时间序列数据,找到去季节性的时间序列。

第六步

通过将去季节性数据拟合到多项式模型中来寻找趋势。

第七步

通过减去具有季节性和趋势性的时间序列数据来找到残差。

时间序列的分解成分

所以,下面是 STL 分解的最终图:

使用 stats 模型库进行 STL 分解

首先,您必须完成 statsmodel 库的 pip 安装。然后,运行下面几行代码。

通过比较两种技术的结果,我们可以看到,趋势和残差分量只有显著变化,季节分量与实际情况相同。

链接到笔记本

这里是到笔记本的链接,用于上面执行的观察。

最后,我只想说,一旦你使用一个库来完成任何统计和机器学习任务,试着去了解构建这些任务所需的实现和数学。这将帮助您更好地理解任何库的每个已定义类的方法参数的用法。

敬请关注下一篇博客…

随机梯度下降——解释清楚!!

原文:https://towardsdatascience.com/stochastic-gradient-descent-clearly-explained-53d239905d31?source=collection_archive---------0-----------------------

随机梯度下降是各种机器学习算法中非常流行和常用的算法,最重要的是形成了神经网络的基础。在这篇文章中,我尽力用简单的语言详细解释它。我强烈建议在阅读本文之前,先浏览一下线性回归。

梯度下降的目的是什么?

简单地说,坡度意味着一个表面的斜度。所以梯度下降字面上的意思是沿着斜坡下降,到达表面的最低点。让我们想象一个二维图形,比如下图中的抛物线。

A parabolic function with two dimensions (x,y)

在上图中,抛物线的最低点出现在 x = 1 处。梯度下降算法的目标是找到“x”的值,使得“y”最小。“y”在这里被称为梯度下降算法操作的目标函数,以下降到最低点。

在继续下一步之前,理解以上内容是很重要的。

梯度下降——算法

我用线性回归问题来解释梯度下降算法。正如我们从这篇文章中回忆的,回归的目标是最小化残差*方和。我们知道,当斜率等于 0 时,函数达到最小值。通过使用该技术,我们解决了线性回归问题并学习了权重向量。同样的问题可以用梯度下降技术解决。

“梯度下降是一种迭代算法,它从一个函数上的随机点开始,一步一步地沿着它的斜率向下移动,直到它到达那个函数的最低点。”

在通过将函数的斜率等于 0 而找不到最佳点的情况下,该算法很有用。在线性回归的情况下,您可以在脑海中将残差*方和映射为函数“y ”,将权重向量映射为上面抛物线中的“x”。

如何分步下移?

这是算法的关键。总的想法是从一个随机的点开始(在我们的抛物线例子中,从一个随机的“x”开始),并找到一种方法在每次迭代中更新这个点,这样我们就可以沿着斜坡下降。

该算法的步骤是

  1. 找到目标函数相对于每个参数/特征的斜率。换句话说,计算函数的梯度。
  2. 为参数选择一个随机的初始值。(为了澄清,在抛物线的例子中,区分“y”和“x”。如果我们有更多像 x1、x2 等功能。我们对每个特征取“y”的偏导数。)
  3. 通过插入参数值来更新梯度函数。
  4. 计算每个特征的步长:步长=梯度*学习率。
  5. 计算新参数如下:新参数=旧参数-步长
  6. 重复步骤 3 至 5,直到梯度几乎为 0。

上面提到的“学习率”是一个灵活的参数,它严重影响算法的收敛性。较大的学习率使得算法在斜坡上向下迈出巨大的步伐,并且它可能跳过最小点,从而错过它。所以,坚持 0.01 这样的低学习率总是好的。从数学上也可以看出,如果起点较高,梯度下降算法会在斜坡上向下迈出较大的步伐,当它接*目的地时会迈出较小的步伐,以确保不会错过它,并且足够快。

随机梯度下降

梯度下降算法有一些缺点。我们需要更仔细地看看我们为算法的每次迭代所做的计算量。

假设我们有 10,000 个数据点和 10 个特征。残差*方和由与数据点一样多的项组成,因此在我们的例子中有 10000 项。我们需要计算这个函数相对于每个特征的导数,所以实际上我们每次迭代要做 10000 * 10 = 100,000 次计算。通常需要 1000 次迭代,实际上我们有 100,000 * 1000 = 100000000 次计算来完成算法。这是相当大的开销,因此梯度下降在大数据上是缓慢的。

随机梯度下降来救我们了!!“随机”,简单来说就是“随机”的意思。

在梯度下降算法中,我们可以在哪里引入随机性??

是的,你可能猜对了!!在每一步选择数据点来计算导数。SGD 在每次迭代中从整个数据集中随机选取一个数据点,以极大地减少计算量。

通常在每一步采样少量的数据点,而不是一个点,这被称为“小批量”梯度下降。Mini-batch 试图在梯度下降的优势和 SGD 的速度之间取得*衡。

结论

我希望这篇文章有助于掌握该算法。敬请关注更多文章。请在下面留下您的评论/疑问。

随机过程分析

原文:https://towardsdatascience.com/stochastic-processes-analysis-f0a116999e4?source=collection_archive---------2-----------------------

内部 AI

随机过程的介绍,以及它们在数据科学和机器学习中的日常应用。

(Source: https://www.europeanwomeninmaths.org/etfd/)

“唯一简单的事实是,在这个复杂的宇宙中没有简单的东西。一切都有关联。万物相连”

—约翰尼·里奇,《人类剧本》

介绍

机器学习的主要应用之一是模拟随机过程。机器学习中使用的随机过程的一些例子是:

  1. 泊松过程:用于处理等待时间和排队。
  2. 随机漫步和布朗运动过程:用于算法交易。
  3. 马尔可夫决策过程:常用于计算生物学和强化学习。
  4. 高斯过程:用于回归和优化问题(如超参数调整和自动机器学习)。
  5. 自回归和移动*均过程:用于时间序列分析(如 ARIMA 模型)。

在本文中,我将向您简要介绍这些过程。

历史背景

随机过程是我们日常生活的一部分。使随机过程如此特殊的是它们对模型初始条件的依赖。在上个世纪,许多数学工作者如庞加莱、洛仑兹和图灵都被这个话题迷住了。

如今,这种行为被称为确定性混沌,它与真正的随机性有着截然不同的界限。

多亏了爱德华·诺顿·罗伦兹,对混沌系统的研究在 1963 年取得了突破。那时,洛伦兹正在研究如何改进天气预报。洛伦兹在他的分析中注意到,即使是大气中很小的扰动也会引起气候变化。

洛伦茨用来描述这种行为的一个著名表达是:

“一只蝴蝶在巴西扇动翅膀就能在得克萨斯州引起一场龙卷风”

—爱德华·诺顿·罗伦兹

这就是今天混沌理论有时被称为“蝴蝶效应”的原因。

分形

一类混沌系统的简单例子是分形(如文章精选图片所示)。分形是不同尺度上永无止境的重复模式。它们不同于其他类型的几何图形,因为它们的比例不同。

分形是递归驱动的系统,能够捕捉混沌行为。现实生活中的一些分形的例子有:树木、河流、云彩、贝壳等…

Figure 1: MC. Escher, Smaller and Smaller [1]

艺术中运用自相似物体的例子很多。毫无疑问,M.C. Esher 是从数学中获取作品灵感的最著名的艺术家之一。事实上,在他的画中重现了各种不可能的物体,比如彭罗斯三角形和 T2 的莫比乌斯带。在《越来越小》中,他也再次使用了自相似性(图 1)。除了蜥蜴的外环,图画的内部图案是自相似的。它包含了每次重复的一半比例的副本。

确定性和随机过程

有两种主要类型的过程:确定性的和随机的。

在确定性过程中,如果我们知道一系列事件的初始条件(起点),我们就可以预测这一系列事件的下一步。相反,在随机过程中,如果我们知道初始条件,我们就不能充满信心地确定接下来的步骤。那是因为有很多(或者无限!)过程可能演变的不同方式。

在确定性过程中,所有后续步骤的已知概率为 1。另一方面,这不是随机过程的情况。

任何完全随机的东西对我们来说都没有任何用处,除非我们能从中识别出一种模式。在随机过程中,每个单独的事件都是随机的,尽管连接这些事件的隐藏模式是可以识别的。这样,我们的随机过程就不再神秘,我们能够对未来事件做出准确的预测。

为了用统计术语描述随机过程,我们可以给出以下定义:

  • 观察:一次试验的结果。
  • 总体:可以从试验中登记的所有可能的观察结果。
  • 样本:从分离的独立试验中收集的一组结果。

例如,投掷一枚公*的硬币是一个随机的过程,但是由于大数定律,我们知道给定大量的尝试,我们将得到大致相同数量的正面和反面。

大数定律表明:

随着样本量的增加,样本的*均值将更接*总体的*均值或期望值。因此,随着样本量趋于无穷大,样本均值将收敛于总体均值。重要的是要明确样本中的观察值必须是独立的”

——杰森·布朗利[2]

随机过程的一些例子是股票市场和医疗数据,如血压和脑电图分析。

泊松过程

泊松过程用于模拟一系列离散事件,其中我们知道不同事件发生之间的*均时间,但我们不知道这些事件可能发生的确切时间。

如果一个过程满足以下标准,则可以认为它属于泊松过程类:

  1. 这些事件相互独立(如果一个事件发生,这不会改变另一个事件发生的概率)。
  2. 两件事不能同时发生。
  3. 事件发生之间的*均速率是恒定的。

让我们以停电为例。电力供应商可能会公布*均每 10 个月可能会发生一次停电,但我们无法准确说出下一次停电会在何时发生。例如,如果发生重大问题,电力可能会重复中断 2-3 天(例如,如果公司需要对电源进行一些更改),然后在接下来的 2 年内继续供电。

因此,对于这种类型的过程,我们可以非常确定事件之间的*均时间,但是它们的发生在时间上是随机间隔的。

从泊松过程中,我们可以得到一个泊松分布,它可以用来计算不同事件发生之间的等待时间的概率或一段时间内可能发生的事件的数量。

泊松分布可以使用以下公式建模(图 2),其中 k 代表一段时间内可能发生的事件的预期数量。

Figure 2: Poisson Distribution Formula [3]

可以使用泊松过程建模的现象的一些例子是原子的放射性衰变和股票市场分析。

随机行走和布朗运动过程

随机行走可以是在随机方向上移动的任何离散步骤序列(长度总是相同)(图 3)。随机漫步可以发生在任何类型的维度空间(如 1D,2D,钕)。

Figure 3: Random Walk in High Dimensions [4]

我现在将向你介绍使用一维空间(数线)的随机漫步,这里解释的这些相同的概念也适用于更高维度。

让我们想象一下,我们在一个公园里,我们可以看到一只狗在寻找食物。他现在在数轴上的零位置,他有相等的概率向左或向右移动以找到任何食物(图 4)。

Figure 4: Number Line [5]

现在,如果我们想知道狗在 N 步之后的位置,我们可以再次利用大数定律。利用这个定律,我们会发现,当 N 趋于无穷大时,我们的狗可能会回到它的起点。反正这个在这种情况下用处不大。

因此,我们可以尝试使用均方根(RMS)作为我们的距离度量(我们首先*方所有的值,然后计算它们的*均值,最后计算结果的*方根)。这样,我们所有的负数都会变成正数,*均值不再等于零。

在这个例子中,使用 RMS 我们会发现,如果我们的狗走 100 步,它*均会从原点移动 10 步(√100 = 10)。

如前所述,随机游走用于描述离散时间过程。相反,布朗运动可以用来描述连续时间的随机行走。

随机行走应用的一些例子是:在扩散过程中追踪分子穿过气体时所采取的路径,体育赛事预测等

隐马尔可夫模型

隐马尔可夫模型都是关于理解序列的。它们可应用于数据科学领域,例如:

  • 计算生物学。
  • 书写/语音识别。
  • 自然语言处理(NLP)。
  • 强化学习。

hmm 是概率图形模型,用于从一组可观测状态中预测一系列隐藏(未知)状态。

这类模型遵循马尔可夫过程假设:

鉴于我们了解现在,未来独立于过去

因此,当使用隐马尔可夫模型时,我们只需要知道我们的当前状态,以便对下一个状态做出预测(我们不需要任何关于先前状态的信息)。

为了使用 hmm 进行预测,我们只需要计算隐藏状态的联合概率,然后选择产生最高概率(最有可能发生)的序列。

为了计算联合概率,我们需要三种主要类型的信息:

  • 初始条件:我们在任何隐藏状态下开始序列的初始概率。
  • 转移概率:从一个隐藏状态转移到另一个隐藏状态的概率。
  • 发射概率:从隐藏状态转移到可观察状态的概率。

举个简单的例子,假设我们正试图根据一群人的穿着来预测明天的天气(图 5)。

在这种情况下,不同类型的天气将成为我们的隐藏状态(如晴天、刮风和下雨),而穿着的衣服类型将成为我们的可观察状态(如 t 恤、长裤和夹克)。我们的初始条件将是这个系列的起点。转移概率,将代表我们从一种不同类型的天气转移到另一种天气的可能性。最后,排放概率将会是某人根据前一天的天气穿着某种服装的概率。

Figure 5: Hidden Markov Model example [6]

使用隐马尔可夫模型时的一个主要问题是,随着状态数量的增加,概率和可能场景的数量呈指数增长。为了解决这个问题,可以使用另一种称为维特比算法的算法。

如果您对生物学中使用 HMMs 和 Viterbi 算法的实际编码示例感兴趣,这可以在我的 Github 库中的这里找到。

从机器学习的角度来看,观察形成了我们的训练数据,隐藏状态的数量形成了我们要调整的超参数。

hmm 在机器学习中最常见的应用之一是在基于代理的情况下,如强化学习(图 6)。

Figure 6: HMMs in Reinforcement Learning [7]

高斯过程

高斯过程是一类*稳的零均值随机过程,完全依赖于其自协方差函数。这类模型可用于回归和分类任务。

高斯过程的最大优点之一是,它们可以提供关于不确定性的估计,例如,给我们一个估计,一个算法有多确定一个项目是否属于一个类。

为了处理包含一定程度不确定性的情况,通常使用概率分布。

离散概率分布的一个简单例子是掷骰子。

想象一下,现在你的一个朋友向你挑战掷骰子,你赌 50 点。在公*掷骰子的情况下,我们期望 6 个面中的每一个都有相同的概率出现(各 1/6)。这如图 7 所示。

Figure 7: Fair Dice Probability Distribution

无论如何,你玩得越多,你越会注意到骰子总是落在相同的面上。在这一点上,你开始认为骰子可能被装载了,因此你更新了关于概率分布的最初信念(图 8)。

Figure 8: Loaded Dice Probability Distribution

这个过程被称为贝叶斯推理。

贝叶斯推理是一个过程,通过这个过程,我们在收集新证据的基础上更新我们对世界的信念。

我们从一个先验信念 开始,一旦我们用全新的信息更新它,我们就构建一个 后验信念 。这一推理同样适用于离散分布和连续分布。

因此,高斯过程可以让我们描述概率分布,一旦我们收集到新的训练数据,我们就可以使用贝叶斯规则(图 9)更新概率分布。

Figure 9: Bayes Rule [8]

自回归移动*均过程

自回归滑动*均(ARMA)过程是一类非常重要的用于分析时间序列的随机过程。ARMA 模型的特点是它们的自协方差函数只依赖于有限数量的未知参数(使用高斯过程是不可能的)。

ARMA 首字母缩写词可以分为两个主要部分:

  • 自回归 =该模型利用了预定义数量的滞后观测值和当前观测值之间的联系。
  • 移动*均 =该模型利用了残差和观测值之间的关系。

ARMA 模型利用了两个主要参数(p,q)。这些是:

  • p =滞后观察次数。
  • q =移动*均线窗口的大小。

ARMA 过程假设时间序列围绕一个时不变均值均匀波动。如果我们试图分析一个不遵循这种模式的时间序列,那么这个序列将需要差分,直到它能够达到*稳。

这可以通过使用 ARIMA 模型来实现,如果你有兴趣了解更多,我写了一篇关于使用 ARIMA 进行股票市场分析的文章。

感谢阅读!

联系人

如果你想了解我最新的文章和项目,请在媒体上关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

  • 领英
  • 个人博客
  • 个人网站
  • 中等轮廓
  • GitHub
  • 卡格尔

文献学

[1]M . C .埃舍尔,“越来越小”——1956 年。可从以下网址获取:https://www . etsy . com/listing/288848445/m-c-escher-print-escher-art-smaller-和

[2]机器学习中大数定律的温和介绍。机器学习大师,杰森·布朗利访问:https://machine learning mastery . com/a-gentle-introduction-to-the-law-of-large-numbers-in-machine-learning/

【3】正态分布,二项分布&泊松分布,让我来分析。访问网址:http://makemanealyst . com/WP-content/uploads/2017/05/Poisson-Distribution-formula . png

[4]维基共享。访问网址:https://commons . wikimedia . org/wiki/File:Random _ walk _ 25000 . gif

【5】什么是数线?数学怪物。访问地址:https://www . mathematics-monster . com/lessons/number _ line . html

[6] ML 算法:一种 SD (σ)-贝叶斯算法。萨吉沙伊尔,中等。访问:https://towards data science . com/ml-algorithms-one-SD-% CF % 83-Bayesian-algorithms-b 59785 da 792 a

[7] DeepMind 的 AI 正在自学跑酷,结果很萌。边缘,詹姆斯·文森特。访问:https://www . the verge . com/tldr/2017/7/10/15946542/deep mind-parkour-agent-reinforcement-learning

[8]为数据科学专业人员介绍强大的贝叶斯定理。KHYATI MAHENDRU ,分析 Vidhya。访问:https://www . analyticsvidhya . com/blog/2019/06/introduction-powerful-Bayes-theory-data-science/

使用 ARIMA 进行股票市场分析

原文:https://towardsdatascience.com/stock-market-analysis-using-arima-8731ded2447a?source=collection_archive---------3-----------------------

(Source: https://ei.marketwatch.com/Multimedia/2018/03/30/Photos/ZH/MW-GG561_DJI_20_20180330105510_ZH.jpg?uuid=57e356ee-342a-11e8-978d-ac162d7bc1f7)

投资中最危险的四个字是:“这次不一样”

-约翰·邓普顿爵士

时序数据

时间序列是我们日常生活的重要组成部分。事实上,它们被用于医学(脑电图分析)、金融(股票价格)和电子学(传感器数据分析)。为了处理这些类型的任务,已经创建了许多机器学习模型,两个例子是 ARIMA(自回归综合移动*均)模型和 RNNs(递归神经网络)。

介绍

我最*一直在 Kaggle 上做一个股票市场数据集。该数据集提供了所有美国股票的每日价格和交易量数据。如果你想了解更多,我所有的代码都可以在我的 Kaggle 和 GitHub 个人资料中免费获得。

在这篇文章中,我将解释如何使用 ARIMA 进行时间序列预测,以及在预测微软公司股票价格时,我使用这种方法获得了什么结果。

ARIMA(自回归综合移动*均)

ARIMA 的首字母缩写代表[1]:

  • 自回归 =该模型利用了预定义数量的滞后观测值和当前观测值之间的联系。
  • 综合 =原始观测值之间的差异(例如,减去不同时间步长的观测值)。
  • 移动*均 =该模型利用了残差和观测值之间的关系。

ARIMA 模型利用了三个主要参数(p,d,q)。这些是:

  • p =滞后观察次数。
  • d =差分的程度。
  • q =移动*均窗口的大小。

如果应用于短期预测,ARIMA 可以产生特别好的结果(就像本例中所使用的)。Python 中 ARIMA 的不同代码模型在这里可用。

分析

为了实现下面的代码练习,我使用了下面的库和依赖项。

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt
from pandas.plotting import lag_plot
from pandas import datetime
from statsmodels.tsa.arima_model import ARIMA
from sklearn.metrics import mean_squared_error

首先,我在所有其他可用的数据集中加载了特定的微软(MSFT)数据集。该数据集由七个不同的要素组成(图 1)。在这篇文章中,我将只研究“开放”的股票价格特性。对于大多数其他特征,可以重复同样的分析。

df = pd.read_csv("../input/Data/Stocks/msft.us.txt").fillna(0)
df.head()

Figure 1: Dataset Head

在开始研究时间序列预测之前,我决定分析相对于固定滞后 5 的“开放”特征的自相关图(图 2)。图 2 中显示的结果证实了 ARIMA 是适用于此类数据的良好模型。

plt.figure(figsize=(10,10))
lag_plot(df['Open'], lag=5)
plt.title('Microsoft Autocorrelation plot')

Figure 2: Autocorrelation plot using a Lag of 5

接着,我将数据分为训练集和测试集。完成后,我将两者绘制在同一张图上,以便对我们的时间序列有一个大致的了解(图 3)。

train_data, test_data = df[0:int(len(df)*0.8)], df[int(len(df)*0.8):]
plt.figure(figsize=(12,7))
plt.title('Microsoft Prices')
plt.xlabel('Dates')
plt.ylabel('Prices')
plt.plot(df['Open'], 'blue', label='Training Data')
plt.plot(test_data['Open'], 'green', label='Testing Data')
plt.xticks(np.arange(0,7982, 1300), df['Date'][0:7982:1300])
plt.legend()

Figure 3: Graphical Representation of Train/Test Split

为了评估 ARIMA 模型,我决定使用两种不同的误差函数:均方误差(MSE)和对称*均绝对百分比误差(SMAPE)。SMAPE 通常用作基于相对误差的精度测量(图 4)。

Scikit-learn 目前不支持 SMAPE 作为一个损失函数,因此,我必须首先自己创建这个函数。

def smape_kun(y_true, y_pred):return np.mean((np.abs(y_pred - y_true) * 200/ (np.abs(y_pred) +       np.abs(y_true))))

Figure 4: SMAPE (Symmetric mean absolute percentage error) [2]

之后,我创建了 ARIMA 模型用于这个实现。在这种情况下,我决定将 p=5、d=1 和 q=0 设为 ARIMA 参数。

train_ar = train_data['Open'].values
test_ar = test_data['Open'].valueshistory = [x for x **in** train_ar]
print(type(history))
predictions = list()
for t **in** range(len(test_ar)):model = ARIMA(history, order=(5,1,0))model_fit = model.fit(disp=0)output = model_fit.forecast()yhat = output[0]predictions.append(yhat)obs = test_ar[t]history.append(obs)
error = mean_squared_error(test_ar, predictions)
print('Testing Mean Squared Error: **%.3f**' % error)
error2 = smape_kun(test_ar, predictions)
print('Symmetric mean absolute percentage error: **%.3f**' % error2)

该模型的损失结果如下所示。根据 MSE,模型损耗相当低,但是对于 SMAPE,模型损耗一直较高。这种差异的主要原因之一是因为 SMAPE 是时间序列问题中常用的损失函数,因此可以提供更可靠的分析。这表明我们的模型还有改进的余地。

Testing Mean Squared Error: 0.343
Symmetric mean absolute percentage error: 40.776

最后,我决定绘制训练、测试和预测价格相对于时间的曲线图,以直观地显示模型相对于实际价格的表现(图 5)。

plt.figure(figsize=(12,7))
plt.plot(df['Open'], 'green', color='blue', label='Training Data')
plt.plot(test_data.index, predictions, color='green', marker='o', linestyle='dashed', label='Predicted Price')
plt.plot(test_data.index, test_data['Open'], color='red', label='Actual Price')
plt.title('Microsoft Prices Prediction')
plt.xlabel('Dates')
plt.ylabel('Prices')
plt.xticks(np.arange(0,7982, 1300), df['Date'][0:7982:1300])
plt.legend()

Figure 5: Microsoft Price Prediction

图 6 提供了图 5 的放大版本。由此可以看出两条曲线是如何紧密相连的。然而,预测价格似乎看起来像实际价格的“嘈杂”版本。

plt.figure(figsize=(12,7))
plt.plot(test_data.index, predictions, color='green', marker='o', linestyle='dashed',label='Predicted Price')
plt.plot(test_data.index, test_data['Open'], color='red', label='Actual Price')
plt.legend()
plt.title('Microsoft Prices Prediction')
plt.xlabel('Dates')
plt.ylabel('Prices')
plt.xticks(np.arange(6386,7982, 300), df['Date'][6386:7982:300])
plt.legend()

Figure 6: Prediction vs Actual Price Comparison

使用 ARIMA 的这种分析总体上导致可观的结果。事实证明,该模型提供了良好的预测精度,并且与 RRNs(递归神经网络)等其他替代方法相比相对较快。

联系人

如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

  • 领英
  • 个人博客
  • 个人网站
  • 中等轮廓
  • GitHub
  • 卡格尔

文献学

[1]如何用 Python 创建时间序列预测的 ARIMA 模型,Jason Brownlee 机器学习精通。访问网址:https://machine learning mastery . com/ARIMA-for-time-series-forecasting-with-python/

[2]对称*均绝对百分比误差,维基百科。访问地址:https://en . Wikipedia . org/wiki/Symmetric _ mean _ absolute _ percentage _ error

“股市异常”和“股市异常检测”是两回事

原文:https://towardsdatascience.com/stock-market-anomalies-and-stock-market-anomaly-detection-are-two-different-things-624331c7b65a?source=collection_archive---------4-----------------------

如果这是你第一次看到这两个术语,你可能会想:“啊?他要谈什么?它们不都是关于股市中发生的怪事吗?”大多数人不明白他们代表了两个不同的大型文学研究作品。发行的动机和技术也不同。在这篇文章中,我将谈论他们是什么。

股票价格时间序列值得我们努力研究和创新。对于刚刚开始研究股价运动的读者,可能会对我的文章《R 中技术指标的算法交易》和《RNN/LSTM/GRU 股价预测技术指南》感兴趣。

(一)什么是股票市场异常现象?

人们认为,价格应该已经充分反映了所有可用的信息。没有办法“跑赢大盘”获得超额收益。这就是著名的“效率市场假说(EMH)”。根据 EMH 的观点,价格已经反映了至少所有过去公开的信息——所谓的弱式;或者价格瞬间变化以反映所有可公开获得的信息——所谓的半强式;或者价格也反映了任何隐藏的内幕信息——所谓的强势形式。尤金·法玛(Eugene Fama)提出 EMH 后,几十年来一直有激烈的争论和实证数据分析。2013 年诺贝尔奖得主尤金·法玛(Eugene Fama)认为,异常现象与理性定价是一致的。他将此归因于风险回报权衡:没有办法使用预测模型来改善风险回报权衡。

所有交易者都订阅 EMH 吗?不完全是。许多交易者认为,存在价格被错误定价的机会,他们可以获得异常回报。“异常”是一种价格没有完全反映所有公开信息的情况,因此提供了一个交易机会。尽管“战胜市场”是许多新手或有经验的交易者都想做的事情,但很少有人成功。罗伯特·希勒——也是 2013 年诺贝尔奖得主——认为市场是非理性的,并且受制于投资者预期的行为偏差。如果是这样的话,投资业绩可以通过已经存在或即将出现的先进预测模型来提高。

公认的市场异常有哪些?

几十年的市场研究在金融文献中被吹捧。已经发现了许多市场异常现象。这里我描述八个典型:

  1. 动量:你是否有时会观察到一个上涨的股票价格持续上涨超过合理水*,或者持续下跌低于不可思议的水*?似乎有一种推动资产价格超出预期价值的势头。
  2. “一月”回来:这种异常现象就是“一月效应”,或许也是符合逻辑的。前一年第四季度表现不佳的股票往往会在 1 月份跑赢大盘。这种“日历效应”有一个很好的解释:投资者倾向于在年底前出售亏损的股票,以冲销他们的税收损失。然而,这种现象不会在市场历史中可靠地重复。因此,在 1 月份买入 12 月份的输家并不能保证交易策略盈利。
  3. 一周中的每一天:股票往往在周五而不是周一有好的结果。这种现象有时被称为周末效应,自 20 世纪 70 年代以来就有记录。但它的规模还不足以成为一种有利可图的交易策略。可能的解释是,公司倾向于将坏消息保留到周五收盘后。
  4. 账面市值比:这可能是文献中记载的最古老的效应。它将公司的账面价值与其价格进行比较。较大的市净率意味着股价被低估,否则被高估。公司的账面价值来源于其历史成本或会计价值。一家公司的市场价值是其股票价格乘以其发行在外的股票数量,即市场资本总额。这种异常在经典的 Fama 和法国研究论文(1993) 中有很好的描述。一种解释是,投资者对成长股的增长方面反应过度,因此价值股被低估。
  5. 被忽视的股票:文献记载,不太知名的公司的股票可以产生更高的收益。小型股往往较少被市场分析师分析。但是,是因为不重视还是因为小?文献还发现,较小的公司可以表现出更好的业绩,因为更高的风险和更高的回报。
  6. 价格反转:关于这个主题的文献中有大量可信的研究。表现非常好的股票在长达一年的时间里逆转并跑输市场。类似地,在一段时间内表现不佳的股票可以在很长一段时间内跑赢市场。即使没有基本的财务报表来证明价格变动,这种现象也会发生。价格反转的原因是什么?这可能是投资者心理使然。不幸的是,很难预测投资者情绪开始导致价格突然上涨或下跌的时间。
  7. 收益惊喜:投资者根据分析师的报告形成预期。当实际报告的收益与预期相差很大时,收益意外可能会导致价格长期大幅波动。福斯特、奥尔森和谢夫林表明,积极的惊喜导致价格在宣布后长达两个月的时间里上涨,而消极的惊喜导致在随后的七天里大幅下跌。他们的研究表明,如果投资者只是观察收益惊喜并迅速做出反应,异常情况就可能发生。它们还显示,价格变化没有 EMH 所说的那么快。
  8. 小公司效应:小公司往往表现优于大公司。Banz (1981)和 Reinganum (1981)首次证明了这种小企业效应。随后的许多其他研究发现了小企业在其他资产和市场中的影响。然而,自从发现小企业异常现象的论文首次发表以来,这种现象似乎已经消失了。

市场异常现象经常发生,但并不总是发生
创造超常回报一直是许多投资者的追求。请记住,市场异常可能已经发生,但不会可靠地重复。

(B)什么是股市异常检测?

异常检测在统计学和机器学习中被广泛研究,它也被称为异常检测、偏差检测或新奇检测。各种成功的异常值检测算法的出现现在被应用于检测股票市场价格中的异常值。

异常值检测的一个直接应用是检测任何市场操纵。市场操纵是一种故意干预市场价格的企图,目的是在证券价格方面制造人为的、虚假的或误导性的表象。市场操纵是有害的,因为它扭曲了价格,破坏了证券市场的功能。更有甚者,由于大多数操纵者的非法获利,许多投资者将遭受重大损失。艾伦和盖尔(1992) 和贾罗(1992) 是最早研究操纵的研究者。艾伦和盖尔将操纵行为分为基于行动的操纵、基于信息的操纵和基于交易的操纵。这里的重点是基于交易的操纵,艾伦和盖尔将其定义为通过实际交易订单扭曲股票市场价格。为此,需要收集每日股票数据或日内数据,如分笔成交点数据。检测任何非法内幕交易是另一个应用。任何人在内部消息公开之前就掌握了它,就可以利用这一优势进行交易。在大多数情况下,非法内幕交易是在消息公开一段时间后才被发现的。往往为时已晚:欺诈已经发生,无辜的投资者已经处于不利地位。我们需要及时的反应或预警探测系统。因此,机器学习开始扮演一个有希望的角色。

我想你明白“股市异常”和“股市异常检测”之间的区别:前者涉及效率市场假说(EMH),后者的动机主要是由机器学习创新驱动的。

发生内幕交易的典型企业事件有哪些?

并购(M&A)和收益公告是典型的发生内幕交易的公司事件。 Ahern (2017) 通过使用美国证券交易委员会(SEC)和司法部(DOJ)在 2009 年至 2013 年间提交的所有内幕交易案件,报告称 M & As 占内幕交易的大约 51%,其次是收益公告,占 26%。剩下的事件包括临床试验和监管公告、新证券的销售以及运营新闻,如首席执行官更替。

典型的内幕交易有哪些症状?

当人们根据内部消息交易时,他们会在交易数据中留下痕迹。多诺霍(2004) 记录了一些已知的症状:

  • 异常高的交易量
  • 异常的价格变动
  • 交易较少(或“交易清淡”)的证券
  • 选项作为经济高效的渠道。如果内幕人士对内幕消息非常确定,期权可以放大内幕人士的收益。例如,如果一个人知道 XXX 公司将在未来几周内被收购,股票很可能从 50 美元涨到 60 美元。如果内幕人士以 50 美元买入 XXX 股票,当股票涨到 60 美元时,他或她获利 20%。然而,如果这个人以 1 美元买了一个看涨期权(执行价格为 50 美元),那么这个看涨期权在跳跃后将价值 10 美元。交易者将获得 900%的利润,而不是 20%。

早期预警系统的目标是提醒监管者进行进一步的调查。值得注意的是,股票价格的上涨并不总是涉及内幕交易,即使所有的迹象都表明异常。金融业监管局(FINRA)的欺诈检测和市场情报办公室(OFDMI)肩负着这一特殊使命。OFDMI 将其组织结构分为四个单位:(I)内幕交易监督小组,(ii)欺诈监督小组,(iii)中央审查小组,以及(iv)举报人办公室。听本期播客了解他们发现非法内幕交易的操作。

一些著名的股价操纵

你可能在新闻中听说过“泵转储”和“欺骗交易”。泵和转储是一种操纵方法,购买股票,推动其价格上升,然后转储所有的股票,以赚取利润。欺骗交易是一种操纵方法,欺骗其他投资者以操纵的价格买入或卖出。

Figure (I): Pump and dump

追踪内幕交易的证据

当人们根据内部消息交易时,他们会在交易数据中留下痕迹。交易量通常非常高,价格波动也不寻常。这在“交易清淡”的证券(通常交易量较低)中尤其如此,因为少量的内幕交易对整体交易有较大的影响。

利用数据发现价格操纵

监控系统的建立是为了寻找内幕交易的痕迹证据。新闻是“触发器”,开始搜索新闻之前的异常交易。全国证券交易商协会(NASD)的市场监管部建立了两个主要的“中断检测”系统——高级检测系统(ADS)和证券观察、新闻分析和监管(SONAR)——用于监视纳斯达克和其他几个市场。除了检测非法交易,该系统还可以用来防止恐怖袭击。

数据分析师将使用所有数据源,包括新闻、文本、每日股票价格或报价单位价格、公司信息等。找出任何操纵价格的行为。贸易数据可以分为两个层次。1 级数据是成功执行的交易。它是特定时期内的开盘价-最高价-最低价-收盘价和成交量。2 级数据包括 1 级数据和不匹配的买/卖订单。它显示输入、取消或匹配的每个特定订单。

创建要检测的特征

创建信号以识别潜在的泵送和倾倒方案仅仅是第一步,这并不容易。我们必须非常有创意地创造信号,或者用数据科学术语“特征”。这些功能可能会检测到完全正常的股票走势,因此信号会变成假阳性。我们的工作是高效和有效地发现异常交易,换句话说,以较小的误报率。图(二)是一个假设的“泵送-倾倒”方案(用圆圈标出)。你可以应用 5 日和 10 日移动*均线来发现潜在的情况。你也参考同期新闻或内幕交易信息,获得更多见解。除了价格变动,你还可以监控交易量的变化。图(二)的底部监测数量变化。

一个假设的例子

这里我们选取一只小股票“利民纸业有限公司”,代号 LMPMY,来创造特色。当您使用getSymbols()时,它将在数据集中加载股票的历史价格。数据有开盘-盘高-盘低-收盘和成交量信息。我使用 R 库quantmodTTR。这在股票市场分析中很流行。

我加了几个技术分析指标:addVo()加成交量,addBBands()加布林线,addCCI()加商品通道指数。布林线是一种统计图表,描述了价格和波动性随时间的变化。商品通道指数是一个振荡器。还有很多其他的技术指标。注意,这些指标本身都不能揭示异常交易。你需要相关信息来调查案件。

*** [## 通过我的推荐链接加入 Medium-Chris Kuo/data man 博士

阅读 Chris Kuo/data man 博士的每一个故事。你的会员费直接支持郭怡广/戴塔曼博士和其他…

dataman-ai.medium.com](https://dataman-ai.medium.com/membership)*

RNN 利用每日市场变量进行股票市场预测

原文:https://towardsdatascience.com/stock-market-predictions-with-rnn-using-daily-market-variables-6f928c867fd2?source=collection_archive---------10-----------------------

在这个项目中,我试图构建一个 RNN(特别是 LSTM)来预测股票市场的回报。该预测是根据 S&P500 指数做出的,该指数是最广泛用于交易和衡量股票市场回报的指数之一。然后,基本交易策略的执行基于预测,其相对于 S&P500 指数的表现是我们衡量成功的标准。

众所周知,股票市场由于其高维空间而很难预测,S&P500 可能是全球最有效的市场股票指数。由于这个原因,项目任务更具挑战性。因此,这可以看作是作者对机器学习技术的学习,特别是对时间序列分析中的神经网络的学习。

该项目经历了以下几个步骤:数据生成、数据预处理和特征选择、基线预测、LSTM 训练和结果展示。该项目已建立在 Python 编程语言与神经网络的 Keras 库。

训练集和测试集的数据生成

该项目使用了 20 多个具有日常频率的市场变量(特征),数据历史从 2006 年开始,一直到 2019 年 4 月。数据来源于彭博终端。使用的特征大多是各种 S&P500 技术指标,但也有市场变量,如指数前瞻共识收益估计,美国国债 2 年期和 10 年期收益率,美元指数,商品指数和波动指数。第三类是用 S&P500 指数信号收盘和开盘,高,低称为 OHLC 集,和交易量。与该领域的大多数类似项目相比,最初的特征选择试图带来更多的多样性和代表性,这些项目主要使用价格信号或指数的 OHLC。在项目期间,不同的特征集合已经被实验,但是最终总共 10 个特征被选择用于训练。预测的输出是 S&P500 指数第二天的回报(价格变化)。

数据预处理遵循 RNNs 情况下所需的时序排序原则。它是超过 13 年的连续每日数据,被分成 43 个学习周期,每个学习周期的长度为 3 年(假设一年中有 240 个交易日)用于培训,60 天(大约。3 个月)进行测试。它提供了 10 年零 9 个月的连续预测范围。图一。下图说明了数据排列。

Fig 1. Dataset arrangement during the whole period

此外,每个研究周期(训练和测试)被排序作为图 2 中的示例说明。在滚动功能窗口和相应的输出方面。

Fig 2. Input sequence illustration on selected features and output

在项目期间,试验了 5 到 20 天范围内的不同时间步长,但这里选择了 10 天时间步长。整个数据集按照以下维度顺序排列:病历报告、样本、时间步长、特征。

数据预处理和特征选择

用于训练的原始输入数据被标准化为每个研究期间的 z 得分,因此训练数据中的每个要素的均值为 0,标准差为 1。重要的是,用从训练数据中获得的*均值和标准偏差来标准化测试数据。

为了确定特性的相对重要性,来自 XGBoost 库的回归器在标准化的特性和输出上实现。图 4。下面显示了功能的重要性,从中选出了 10 个最重要的功能,以供以后使用。然而,当选择具有最高重要性的特性时,我们冒着丢失全部特性集合中所表示的关系的风险。

Fig 4. Feature importances from XGBoost

数据预处理后,数据集具有以下形状,可用于训练和测试。

X train (43, 711, 10, 10) y train (43, 711, 1) x test (43, 60, 10, 10) y test (43, 60, 1)

基线预测-K-最*邻

为了评估 RNN 在股市预测中的能力,我们使用 scikit-learn 回归实现了基于 K-*邻算法的基线预测。从 1 到 200 范围内的不同 K-s 已经在训练期间回归,并且在验证期间具有最小均方误差的 K-s 已经在测试的特定研究期间使用。图五。下图在上图中显示了真实的 S&P500 和预测回报。下图显示了测试期间的交易表现(在任何真实生活成本之前)。这里我们使用的是对称规则,即如果预测回报为正,则 150%投资于指数,如果预测回报为负,则 50%投资于指数。在超过 2500 个交易日的所有测试期间,该结果与 S&P500 指数买入并持有表现一起绘制。即使准确性是评估分类模型的传统度量,我们在这里和在后面的阶段使用性能来比较 K-NN 和 RNN 预测能力。K-NN 模型在整个期间都取得了优异的表现,回报是初始投资的 3.5 倍,而 S&P500 买入并持有策略的回报是 3.0 倍。下方面板中的红色标记代表相对于全指数投资的多头(1)和空头(-1)头寸信号(在 alt y 轴上)。即使 K-NN 在整个期间的结果是正的,它也是不一致的,因为在时间跨度的开始和后半段有很长一段时间(以年计)表现不佳。

Fig 5. K-NN performance

LSTM 预测

该问题被设置为二进制分类,并为正的日回报分配值 1,为负的日回报分配值 0。所使用的 LSTM 网络设置和架构如图 6 所示。

Fig 6. LSTM settings and architecture

用于拟合的参数是批量大小 32、验证分割 20%和 200 个时期。每个研究阶段的训练和验证损失结果如图 7 所示。以及图 8 中的相应精度。这些表明网络在纪元期间在验证方面有困难。重要的是,很少有损失更低、准确性更高的异常值研究集,这可以在测试期间对交易表现产生影响。然而,在训练期间*似的关系似乎在验证期间也勉强成立,因为在最后一个时期之后的研究期间的*均验证准确度是 53.75%。

Fig 7. LSTM network training and validation loss

Fig 8. LSTM network training and validation accuracies

基于 LSTM 模型的交易绩效

当对 LSTM 输出应用与 K-NN 相同的交易规则时,结果表现在图 9 中。我们可以观察到,交易结果是初始投资的 4 倍,相比之下,S&P500 买入-持有是 3 倍,K-NN 是 3.5 倍(图 5。).因此,在这个项目中,基于 LSTM 的交易表现优于 S&P500 指数和 K-NN 算法。

Fig 9. S&P500 buy&hold and LSTM based trading performance

该项目的结论是,在其他机器学习方法中,LSTM 神经网络可以很好地替代股票市场时间序列预测。然而,目前的 LSTM 设置在解决该项目中的任务方面的整体成功是值得怀疑的,因为在所有测试期间,51.6%的测试精度可能是不够的。需要进一步测试不同的参数和架构设置,以提高精度。

未来工作:用于特征提取的神经网络

下一步,计划是使用卷积神经网络(CNN)上的自动编码器生成提取的特征。想法是使用提取的特征作为 LSTM 网络的输入。由于时间限制,这里不介绍由此产生的损失、准确性和交易性能,但是下面介绍构建自动编码器和提取压缩特征的描述。将 CNN 用于特定目的的想法来源于一篇很好的文章这里是,它提供了自动编码器不同网络的比较和结果,其中 CNN 似乎是一个有前途的替代方案。

为该项目构建的自动编码器网络架构如图 10 所示。可以看出,尝试将 10 个特征编码成 5 个特征。在对来自第一卷积层的编码器输出进行拟合之后,它被用于生成压缩特征,然后将被馈送到 LSTM。

Fig. 10 CNN autoencoder

进一步的想法包括用小波进行输入转换,并试验不同的数据处理方法和超参数。

免责声明:本故事中呈现的材料不应被视为与持有、购买或出售证券或其他金融产品相关的建议或推荐,也不是创建或使用本故事中提及的任何技术或策略的建议或推荐。

不要孤注一掷

原文:https://towardsdatascience.com/stock-portfolio-optimization-d1dc66c7251?source=collection_archive---------36-----------------------

如何利用数据科学优化你的股票投资组合

Photo by Markus Spiske on Unsplash

现代投资组合理论认为,多样化有助于降低投资组合的风险。投资组合包含高波动性但总体波动性低的资产,因为你可以组合负相关的资产——当一些资产上涨,另一些资产下跌。

这篇文章描述了我使用 S&P500 的股票,通过数学和数据科学优化投资组合的努力。

模型

目的是确定投资组合的哪一部分投资于几种可能的资产中的每一种,以最小化投资组合的波动性为目标,并符合目标回报。

为了用数学方法来框定这个问题,假设 f 是一个 n 维向量,它是我将投资于每一项 n 金融资产的分数。设 C 表示资产日收益的协方差矩阵,一个 n x n 矩阵。设 r 为每项资产预期收益的 n- 维向量。目标回报由 r*决定。

要解决的优化问题是:

由于我们希望最小化投资组合波动性(风险水*)的函数,问题的三个约束是:

  • 分数之和应该是 1。
  • 投资组合应该达到目标收益, r* 。
  • 每只股票的分数应小于 100%。

因为我们要最小化的目标函数是一个二次的,这类问题在运筹学和数值优化界被称为二次 程序。值得注意的是,因为它是一个凸函数,所以总是有唯一的解。

数据

我用了一个 2019 年 2 月 20 日到 4 月 18 日之间的股票价格的数据集。我选择了科技行业的一些股票——AMZN、GOOGL、MSFT、IBM、FB 和 NFLX(亚马逊、谷歌、微软、IBM、脸书和网飞)——并制作了一个图表来可视化它们的相关性:

除了网飞(NFLX)之外,大多数股票都有很强的相关性,但是记住这只是 2 个月的时间。

最优投资组合分配

为了解决这个问题,我需要计算 S & P500 指数中每只股票的日收益和估计收益的协方差矩阵 C 。我决定用 9%作为我的目标回报率。

一旦我计算了预期收益和每日收益的预期波动性(和协方差),我就准备好解决最优化问题了。

访问 this repo 查看我的 Python 代码,它将在 Watson Studio 桌面上运行。(你只需要将数据集放入你的项目中。)下面是一个片段:

优化模型从 S&P500 指数中的 500 只股票中选择了总共 28 只股票,包括作为前 3 名的这些股票:

  1. COTY——11.14%
  2. SRE——9.14%
  3. 冠心病——8.74%

Portfolio Optimal Allocation

为了解决优化问题,我使用了来自 Python 的决策优化工具 CPLEX,灵感来自 CPLEX github repo 的一个笔记本。

最后的想法

  • 我在这篇博客中使用的预期回报只是来自数据集中观察到的 2 个月期间,但你也可以使用机器学习和人工智能技术来确定它们。如果您对项目的预测方面感兴趣,请联系我们,我们可以合作!
  • 该数据仅包含 S&P500 指数的股票。显然,股票是风险很大的资产。根据你的风险厌恶程度,你可以选择将短期和中期债券纳入投资组合,以降低投资组合的波动性。
  • 同样,我只使用了两个月的数据。我当然不会建议根据这个数据集或任何时间框架如此短的数据集做出任何严肃的决定。
  • 每个目标回报都有相应的投资组合波动性。对不同的目标回报率做同样的练习,以画出所谓的马科维茨有效边界。如果感兴趣,请阅读这篇关于用 Python 绘制有效边界的伟大的帖子。
  • 我在 Watson Studio 桌面中完成了所有的分析,结合了不同的工具:Jupyter 笔记本、数据精炼(用于可视化)和 CPLEX 决策优化社区版(用于求解二次规划)。

[1]哈里·马科维茨。(1952).投资组合选择。《金融杂志》第 7 卷第 1 期。(1952 年 3 月),第 77-91 页。

[2]数据来源:https://www . ka ggle . com/qks 1 lver/amex-NYSE-Nasdaq-stock-histories

[3] IBM 决策优化(CPLEX) Github Repo。https://ibmdecisionoptimization . github . io/tutorials/html/Beyond _ Linear _ programming . html

特别感谢史蒂夫·摩尔对这篇文章的大力反馈。

在 Twitter 上关注我:@ castan 在 LinkedIn 上找我: @ jorgecasta

基于递归神经网络的股票预测

原文:https://towardsdatascience.com/stock-prediction-using-recurrent-neural-networks-c03637437578?source=collection_archive---------2-----------------------

Normalized stock price predictions for train, validation and test datasets. Don’t be fooled!

与人工智能交易

预测给定股票的梯度

这种类型的帖子已经写了很多次,但很多都让我不满意。最*,我阅读了利用深度学习的最新进展来预测股票价格走势的,我认为这是一篇非常有趣的文章。它涵盖了许多主题,甚至给了我一些想法(它也促使我写了我的第一篇文章🙂).但它实际上并没有说明网络的表现有多好。我的直觉告诉我“不太好”,因为这是通常的情况,但也许/希望我是错的!
一段时间以来,我一直在开发自己的交易算法,所以这篇文章介绍了我的方法、想法和一些结果。

这包括:

  1. 挑战
  2. 数据
  3. 构建数据集
  4. 培训
  5. 结果
  6. 结束语

挑战

总体挑战是确定一个收盘价和下一个收盘价之间的梯度差。不是实际的股票价格。为什么?当你试图预测可能小幅波动(| < 0.01%|)和/或大幅波动(| > 5%|)的东西时,很容易欺骗自己认为你有一个可行的模型。下图给出了一个例子。一个基本模型(没什么特别的)被训练来预测高盛的(标准化)价格:

Actual vs predicted (normalized) prices for the validation dataset.

股票的实际价格在 y 轴,而预测价格在 x 轴。这里显然有一个很好的线性趋势。或许可以由此发展出一种交易策略。但是如果我们画出两个连续点之间的梯度会怎么样呢?

The actual vs predicted gradient for the validation+test datasets. Ideally, it would be a diagonal line.

啊哦。对于预测下一根蜡烛线(这里梯度的定义)的价格是上涨还是下跌,我们的模型本质上并不比猜测好多少。这是一个相当大的基本问题。这里的准确度(51.5%)是通过将正确象限(右上和左下)中的值相加并除以所有点计算出来的。

我不会告诉你为什么这是一个困难的问题(你可能已经知道了),我会提到我在这里面临的两个个人斗争。

  1. 数据。数据的质量决定了你的模型的结果显然是。清理和处理你的数据,理解它,玩它,绘制它,拥抱它。确保你探索了它的每一个方面。比如说;我用新闻故事。它们在不同的时区出版。股票价格数据来自另一个时区。确保您正在正确同步,而不是使用未来的信息欺骗自己。这只是一个例子。另一个:当向我的经纪人索要每小时一次的烛台时,第一栏是一个 30 分钟的窗口。如果没有抓到这个的检查,你将会有一段时间挠头。
  2. 构建一个简单的估计器。我的意思是,你的模型的预测很大程度上是基于前一点。这似乎是股票预测中最常见的问题。建立一个模型来缓解这种情况并保持准确性是关键,因此也是困难的部分。

A naive estimator. The red line (the prediction) follows the blue line (the actual price) with a lag of 1 data point.

好吧,简而言之:

我们能否训练一个模型,准确预测下一个梯度变化,同时减轻天真的估计影响?

剧透警告:是的,我们可以!(我觉得)。

数据

股票价格信息

花在这个项目上的大部分时间是确保数据的格式正确,或者排列正确,或者不太稀疏等等。(嗯,还有我围绕这个工具构建的 GUI,但那是完全不同的问题🙄).

我的数据来自 互动券商 (IB)。注册并存入最低金额后,您就可以订阅各种订阅源。目前,我每月为实时数据支付 15 欧元。

我利用 他们的 API 下载股票价格的功能可以在本要旨 中看到

重要的是:

1)连接到 IB
2) 创建一个“契约”
3) 请求使用那个契约的历史条。

由于我的代码已经在一个线程上,所有这些都放在一个打了补丁的异步循环上(因此有了包 nest_asyncio )。上述要点中的用法给出了一个如何调用这个函数的例子。

我现在有一个 1 小时烛台的熊猫数据框。从那里很容易制作情节:

60 minute candlesticks for Goldman Sachs

我用的是相当牛逼的库。稍微复杂一点的语法是对交互式情节的牺牲(尽管对本文来说不是交互式的)。通过放大某个部分,可以更好地突出目标:**

What is the gradient (i.e. sign change) from one Close price to the next? To make this prediction, everything in the shaded box (among other things) is taken into account. More on variables later. This shows a sequence of 5 candles used to predict the 6th.

我将尝试预测从我最*的收盘价到即将到来的收盘价的梯度。这可以用来制定交易策略。在稍后阶段,梯度的大小也可能被考虑。

新闻

假设是新闻对股票价格的演变有很大的影响。有几个消息来源,比如 newsapi.org,IB 也有一些选择,汤森路透等等。至于我的消息来源,我还没准备好分享🙂。

我目前以最基本的形式使用新闻情绪:我计算给定时间段内正面/负面和中性故事的数量,并将它们用作特征。我使用自己自制的半监督新闻分类器,但也可以使用 BERT 或任何其他预先训练好的库。
还有其他方法来包含情感,例如将嵌入内容直接注入网络。

对于每只股票,我选择了某些关键字并检索相关的新闻文章。一个超参数是“滞后”。滞后值为 0 意味着如果我预测下午 2 点的收盘价,那么只使用同一天下午 2 点之前的报道。滞后 1 表示包括前一天的新闻,依此类推。这里的问题是:消息通过社会和交易算法传播需要多长时间,它对股票的影响有多长时间?
下面显示了给定时间段和 2 天滞后期内高盛的故事数量。我认为 4 月 15 日至 18 日之间的负峰值与银行报告第一季度业绩
喜忧参半有关。
**

The number of positive and negative news articles with lag=2 for a given date range

构建数据集

变量和特性

预测股票价格的一个问题是,实际上只有有限的数据。此外,我不想回到太久远的过去,因为我相信从 2013 年到现在,交易的本质已经完全改变了。我可以训练许多或少数股票串联在一起,与其他人使用的功能。通过将股票串联起来,我增加了数据的数量,也可能学到新的见解。我的数据集构建器的伪代码如下所示:

**# Specify stocks to concatenate and specify those to use as features. 
Training_assets=[...] # i.e. currencies, or other stocks
Feature_assets[...] # i.e. related stocks
For stock in Training_assets:Download/update stock from IBMerge in News sentimentsAdd extra variables like MACD, Boilinger Bands, etc.Download Feature_assets and append to stockNormalizeConcatenate with the previous training stock**

归一化

在训练期间,我将每个特征标准化,并将参数保存到一个标量文件中。然后,在推断时,我读取文件并将参数应用于变量。这加快了我可以向我的经纪人询问最新数据的推断过程。如何正常化的一个要点可以在这里看到。一个有趣的参数是norm_window_size。这指定了要素中有多少个点应该一起归一化。窗口太大意味着分辨率不够精细。尚未被考虑在内的各种各样的外部因素将发挥更大的作用。太小的窗口本质上看起来就像噪音。这是一个有趣的参数。

相关性

每个变量之间的相关性如下所示。请记住,在最广泛的意义上,两个高度相关的变量意味着如果一个增加,另一个也会增加。对于反相关,如果一个变量减少,另一个就会增加。
较高的正相关性颜色较深,较低/负相关性颜色较浅。目前,我确实使用开放、高、低作为特征。它们与收盘价高度相关,但我在推断时有所有这些信息,所以嘿,为什么不呢。在未来的训练中,我可能会移除它们,看看会发生什么。总的来说,有“重复性”的变量不好。
其他看似多余的功能是用收盘价构建的指标。但是它们给了我一个简单的方法来改变那些变量的序列长度,所以我现在把它们留在这里。

但是有哪些“外部”来源(即,不是来自我们试图推断的股票)?这些是最重要的变量。
货币、指数等特征之间的高度相关性以及与 VIX 的反相关性是非常有前途的。
一些货币可能会被淘汰,以减少整体网络规模(即,美元和南非兰特似乎不会相互影响,但谁知道呢),针对不同变量的进一步培训可能会淘汰其中一些货币。

重要的是要记住“…相关性和交易预测不是一回事。”正如丹尼尔·夏皮罗在 算法交易的数据科学 中指出的,我。相关性不是因果关系。因此,待办事项列表中的一项过滤技术是,观察单个变量与给定股票收盘价的相关性如何随时间演变。这将允许我们删除变量并减少维数。****

Variable correlations. Currencies are technically “midpoints” instead of “close” prices.

滑动窗口算法

此时pandas.head()给出:

其中显示了 5 个时间步长,7 个归一化特征(为了简洁)。

然后,我们创建训练、验证和测试数据集。
由于这是一个序列预测问题,我们使用滑动窗口算法。前提如下图所示。使用了 X 个点(图中为 4 个),以 X+1 作为标签,形成一个新的数组。然后,窗口向前移动 1 点,重复计算。这样你就有了一个大的数组(X,是你的输入)以及你的标签,y。

Sliding window algorithm of sequence length 4, for data (X) and corresponding labels (Y).

从这里开始,在分成训练、验证和测试大小(80%、15%、5%)之后,数据可以输入到神经网络中。

结构

我尝试过各种架构(包括 GANs),直到最终选定一个简单的递归神经网络(RNN)。就这样 奥卡姆可以安息 。理论上,LSTM(RNN 的一种)应该更好,我需要再玩一次。Christopher Olah 提供了一篇关于 RNN 和 LSTMs 的非常好的文章。

我在 Tensorflow (1.12)中的模型看起来有点像这样(名称空间和直方图等)。已删除):

**def gru_cell(state_size):cell = tf.contrib.rnn.GRUCell(state_size)return cell# Inputs
inputs = tf.placeholder(tf.float32, [None, seq_len, len(variables)])
labels = tf.placeholder(tf.float32, [None ,n_outputs])# Placeholder for dropout to switch on and off for training/inference
keep_prob = tf.placeholder(tf.float32)# Run the data through the RNN layers
batch_size = tf.shape(inputs)[0]initial_state = tf.zeros([batch_size, num_layers * size])cell = tf.contrib.rnn.MultiRNNCell([gru_cell(size) for _ in range(num_layers)], state_is_tuple=False)outputs, final_state = tf.nn.dynamic_rnn(cell, inputs, initial_state=initial_state) # Then feed into a dropout layer
dense_layer = tf.contrib.layers.dropout(outputs[:,-1], keep_prob=keep_prob)# ... and a dense layer
dense_layer = tf.layers.dense(dense_layer, dense_units, activation=tf.nn.selu)# ... followed by a single node dense layer
final_predictions = tf.layers.dense(dense_layer,n_outputs,activation=tf.sigmoid)**

图表看起来像这样:

Tensorboard graph visualization (The multi_rnn namespace is connected to accuracy by a variable placeholder, batch size).

这是一个相当简单的网络,其中一个多层 RNN(带有 GRU 层)被馈入一个密集层(包括一个漏失层)。层数、激活和退出百分比都在训练期间被优化。
“准确性”节点是一组复杂的 TF 运算,将密集网络的预测转换为二元梯度运动。作为一个实验,这种精度实际上目前在我的成本函数中使用为:

**cost = (1-Accuracy) + tf.losses.mean_squared_error(labels, final_predictions)**

其中标签是归一化价格,最终预测是归一化实际价格预测。我使用具有循环函数学习率的adamotimiser。这是做这件事的最佳方法吗?我还不完全确定!🙂

培养

我在训练阶段也使用了 贝叶斯优化 (BO)。我认为这是一个很棒的库,但是,我确信它对这种类型的问题很有效,并且实际上节省了大量的时间吗?不完全是。我想画一些图来看看训练是如何进行的,功能是什么样子的。但是有这么多参数,这很难。然而,也许它提供了一个略有偏差的随机数生成器。也就是说,本文中用于结果的参数是:

Final parameters used for training for the purpose of this article

这里有一个有趣的阅读 关于比例指数线性单位(selus)。

训练(橙色)和验证(蓝色)数据集的损失曲线如下所示。生产线非常不稳定,也许使用更大的批量会有所帮助。这两个数据集之间也有一些不同。这并不奇怪。请记住,我已经将高盛的多只股票串联(并洗牌),所以我们实际上训练的是一个给定“部门”的模型,或者随便你怎么称呼它。理论上,它更一般化,因此更难训练(这是获得更多数据的代价)。因此,它可能暗示一些过度训练;有待进一步检查的东西。然而,人们可以看到验证损失随着时间的推移而减少的趋势(直到某一点)👍。

Loss function for 4k iterations. Only the best model is saved.

结果

这种最新型号性能如何?下面是实际坡度与预测坡度的对比。65%的准确性(使用之前使用的相同定义)并不算太差。

The actual vs predicted gradient for the validation+test dataset.

下图显示了实际梯度与预测梯度的混淆矩阵。它表明,我们 59%的时间正确预测负梯度,而 71%的时间正确预测正梯度。这种不*衡可能来自数据集和模型的性质,即,可能三个小的正梯度进行单个负梯度。模型了解这一点,因此引用准确性可能有点误导。这在实际制定交易策略时会变得非常重要。

Confusion matrix showing accuracy for up and down predictions.

再次显示了封面图,重点是验证和测试数据集。说实话,不是那么性感。但是有时候梯度变化的趋势确实是遵循的。对我来说,每当这样的情节以看似完美的重叠出现时,读者的脑海中就会响起警钟。
记住,验证数据集仅在训练步骤中用于确定何时停止训练(即 x 个时期后无改善,停止)。测试数据集没有在任何地方使用即表示该图显示了大约 600 小时的“半看不见的”数据,以及不到 300 小时的完全看不见的数据。

Predictions for the validation and test datasets.

我们的结果有多稳定?
在 114 次训练中,预测梯度的准确度分布如下所示(绿色直方图)。每次训练的准确度都用橙色标出了跑步次数。这证实了我的怀疑,BO 在这里工作得不太好,但也许它只是需要更多的迭代和/或调整参数。

事实证明,我本可以使用一个更好的结果。哎哟😀。(更好的结果是在混淆矩阵中上/上相对于下/下有更均匀的分布,这很好)。
从绿色直方图中可以看出,我们正在学习一些东西。同样,很高兴看到有些结果并不比猜测好,这意味着我们并不总是在玩参数时学到东西。有些模特就是很烂。如果没有模特表现糟糕,这将是一个警钟。

结束语

在这篇文章中,我强调了我构建 RNN 的方法,它能够在大约 65%的时间内预测两个收盘价之间的正确梯度差。我相信随着更多的发挥和一些调整,这个数字可以得到改善。此外,还可以进行更多的检查和研究。
回测的时候真的会赚钱吗?交易直播的时候呢?需要考虑的数量很大。从使用相当酷的back trader库,到将其插入 IB API,这些将是下一篇文章的主题。🙂

我希望你觉得这篇文章很有趣…我写得很开心!

约书亚·怀亚特·史密斯

使用 Twitter 进行股票预测

原文:https://towardsdatascience.com/stock-prediction-using-twitter-e432b35e14bd?source=collection_archive---------4-----------------------

有没有想过如果你能预测股市你能做什么?很多:)

许多经济学家认为,股票市场是随机的,因为它受随机事件的控制,这是在有效市场假说和随机漫步理论中提出的。但真的是这样吗?

研究人员对此进行了测试,并试图预测股票市场,以表明确实有可能对市场的走向有所了解,并且似乎已经证明了他们的观点具有一定的准确性。关于这个主题的一篇里程碑式的论文是由博伦等人撰写的。艾尔。, [1]在这篇博客中,我将试着用简单的语言解释他们是如何做到的。

Bollen 利用公众意见(使用 twitter tweets)证明了在 twitter 上表达的公众情绪与股市表现之间存在相关性。

在详细了解 Bollen 做了什么以及他是如何做的之前,我们需要了解一些事情:

  1. 什么是股票市场,它是如何运作的?
  2. 如何从推文中找到表达的心情?
  3. “如何发现/证明两个时间序列之间的相关性”
  4. 假设两个时间序列相关,如何从一个时间序列回归/预测另一个时间序列的未来结果。

什么是股票市场?

公司是一个大实体。现在,大多数公司都不是由一个人甚至一个组织所拥有,而是大量的人分享公司,这些人被称为股东。所有这些人都拥有公司的一部分,称为股票,因此这些人也被称为股东。股票市场是一个你可以出售你的公司股票或购买公司股票的地方。

更正式地说,股票可以定义为:

一家公司的是该公司所有权被分割成的全部股。【1】在美式英语中,股份俗称股票。【1】一股股票代表与股份总数成比例的公司的部分所有权。这通常赋予股东那部分公司收益、资产清算所得(在清偿所有优先债权,如有担保和无担保的债务)、【2】或投票权,通常按照每个股东投资的金额比例进行分配。-维基百科

股票市场可以定义为:

一个股票市场是股票(也称为股份)的买方和卖方的集合(一个松散的经济交易网络,而不是一个实体设施或实体),它代表着对企业的所有权要求;这些可能包括在公共证券交易所上市的证券,以及只在私下交易的股票。-维基百科

如果您有兴趣了解更多信息,请参考此链接

现在有许多股票市场,但我们的重点将是“纽约证券交易所”。为什么?因为它是最大的股票市场,大部分研究都围绕着它。在继续之前,我们需要了解一个术语,它就是“道琼斯工业*均指数”,或者简称为“道琼斯指数”。

道琼斯工业*均指数(DJIA)是在纽约证券交易所和 T2 纳斯达克交易的 30 种重要股票的价格加权*均值。DJIA 是查尔斯·道在 1896 年发明的。

通常被称为“道琼斯”,DJIA 是世界上最古老、最受关注的单一指数之一,包括通用电气公司、华特·迪士尼公司、埃克森美孚公司和微软公司等公司。当电视网说“T4 股市今天上涨了”时,他们通常指的是道琼斯指数。-投资媒体

所以道琼斯(或 DJIA)给了我们一个好主意,股票市场是在高点还是在低点收盘,那么 DJIA 到底衡量什么呢?它只是前 30 家公司股票价格的加权*均值,其中价值更高的股票具有更大的权重,最终结果被归一化以剔除一次性事件。因此,它本身就是一个价格。

所以有了 DJIA,我们现在有了一个可靠的方法来观察市场一天的表现。我们现在需要的是挖掘公众意见的方法,为此我们求助于 twitter。

推特情绪分析

机器能理解情感吗?不,他们不能,直到现在,我说的“不”不是指一个完美的“不”(而是一个非常不完美的“不”),因为机器现在可以理解广泛的情感(尽管不是完美和可靠的),并且很容易被愚弄/混淆。(这是另一篇博文的话题)。

有了机器学习算法,就有可能衡量某段文本中表达的情绪(或情感)。但是精确度还有待提高。但是如果情感表达明确,文字没有扭曲,那么我们就可以做出一个可靠的情感分析模型。这是 Bollen 用来从推文中获取情绪的工具背后的想法。

情感分析是机器学习的一个非常重要的应用,难怪许多不同的算法(我指的是很多)被应用于从文本中获取情感,让我们选择一个最简单和直观的算法。让我们考虑一下正文:

“埃隆·马斯克的个性和他的人生哲学给我留下了深刻的印象,难怪特斯拉和 spaceX 会如此努力”。

我们的算法将只查看重要的词,如“漂亮”、“印象深刻”等。(而不是像“我”、“我”之类的词。此外,我们的算法可能不知道 spaceX、Elon、Musk,所以它可能会忽略它)。现在,考虑到该算法之前已经看到了积极的文本看起来是什么样子(在训练它的时候),它已经弄清楚了像“漂亮”、“印象深刻”、“棒极了”这样的词大多与积极的情绪相关联。因此,很可能将文本标记为正面的。

这是一种非常简单的方法,它是由 Textblob (一种文本分析工具)采用的,Textblob 基于朴素贝叶斯算法,这是一种非常简单的算法,考虑到它的简单性,它给出了很好的结果,所以其思想是-每个单词根据它所关联的文档的类型给出一个分数,因此在正面文档中出现得比负面文档多的单词可能具有更大(或更正面)的分数,因此如果它出现在文档中,那么该文档更可能是正面的。因此,每个单词都有自己的分数,然后对这些分数进行*均,以获得文档的情感。

不用说,这种方法并不理想,而且在复杂的文档中效果很差。因此,大多数研究人员使用更复杂的分类器(如支持向量机)来建立情感分析模型。

Bollen 使用了两个工具进行意见挖掘,一个是意见查找器,另一个是情绪状态的 Google Profile。这些天我没有看到很多人使用意见查找器,它对这个博客来说也不是很重要,所以我们将把它放在一边,专注于谷歌情绪状态(或 GPOMS)的概况。

GPOMS 是一个工具,可以帮助你准确地检测出一段文字所表达的情绪。它基于情绪状态简介问卷,这是一份由 65 或 37 个问题组成的问卷,取决于你选择哪一个。对于每个问题,你都要表明你的感受——从“一点也不”、“一点点”、“一般”、“相当多”、“非常多”。例如,对于问题“遗憾”,你将表明你作为上述状态之一的感受,它将使用 a 标准转换为分数,并根据你的回答计算你的情绪。这里有一个到测试的链接。

那么 GPOMS 是如何利用 POMS 从文本中预测情绪的呢?谷歌连接来了。博伦使用了谷歌发布的数据集之一。该数据集由从英语网络文本的 1 万亿个单词中提取的 n 元语法的频率计数组成。你可以在这里试试。bollen 所做的是:将 POMS 调查问卷中的每个单词与谷歌 n-gram 数据集中的 n-gram 相关联,然后将最频繁出现的 n-gram 分成标记,现在这些单词中的每一个都有与之相关联的语气,并可以给它们一个加权分数(基于出现次数),根据这些单词在一段文本中的出现方式,可以用相应的语气进行标记。

以上是我对 Bollen 在论文中解释的内容的理解:

因此,964 个术语的扩大词典允许 GPOMS 捕捉推文中更广泛的自然出现的语气术语,并将它们映射到各自的 POMS 语气维度。我们将每条推文中使用的术语与该词典进行匹配。匹配 n 元词的每个推文词被映射回其原始 POMS 词(根据其共现权重),并通过 POMS 评分表映射到其各自的 POMS 维度。因此,每个 POMS 情绪维度的得分被确定为与 GPOMS 词典匹配的每个推特词语的同现权重的加权和。

不幸的是,GPOMS 不再可用,它现在是一个闭源工具。Goel-Mittal【2】用一种更简单的方法建立了一个类似的模型(尽管不太准确),他们使用了 POMS 调查问卷中出现的单词的同义词,然后将它们映射到文本。

根据他的 GPOMS 模型和意见搜索器,博伦发现了人们的情绪,结果如下:

Results From GPOMS and Opinion Finder

如你所见,图表上有两件突出的事情:一件是 2008 年总统大选,另一件是感恩节,Bollen 似乎因为这个非常特殊的原因选择了这个时期,因为人们的情绪在这些场合是可以理解的,所以我们可以用这个来表明我们的模型确实能够衡量公众的情绪,公众情绪和股票市场的波动都很大,因此很容易观察到。

我们现在完成了四个部分中的两个,我们知道如何衡量公众的情绪和市场的情绪。现在我们可以继续证明这两者确实相关。

时间序列之间的相关性

如上图所示,我们已经获得了人们情绪的时间序列,类似的时间序列对于 DJIA 的得分也可以很容易地获得。现在我们需要寻找一种方法来证明这些是相关的,或者人们的情绪(从 twitter 上挖掘)导致了股票市场的变化。

我们用格兰杰因果关系来做这件事。那么格兰杰因果关系到底是什么?根据这篇的《学院派》文章:

格兰杰 因果关系 是基于预测的因果关系的统计概念。根据格兰杰因果关系,如果一个信号 X 1“格兰杰原因”(或“G 原因”)一个信号 X 2,那么 X 1 的过去值应该包含有助于预测 X 2 的信息,而不仅仅是包含在 X 2 的过去值中的信息。它的数学公式是基于随机过程的线性回归模型(格兰杰 1969)。存在对非线性情况的更复杂的扩展,然而这些扩展在实践中通常更难应用。

因此,如果我们有两个时间序列,比如 X1 和 X2,我们可以证明 X2 依赖于它以前的值,即,

X2(t)= a(0)+a(1)X2(t-1)+a(2)X2(t-2)+……。+ a(p)X2(t-p)

这里,常数 a(1),a(2),…,中的至少一个..,a(p)不为零,那么我们可以说 X2(t)依赖于其先前的值,在表明这一点之后,如果下面的关系对于 b(1),b(2),…,中的至少一个成立。,b(p)不为零:

X2(t)= a(0)+a(1)X2(t-1)+a(2)X2(t-2)+……。+a(p)X2(t-p)+b(1)X1(t-1)+b(2)X1(t-2)+……。+b(p)X1(t-p)

那么我们可以说 X1 是 X2 的原因,或者 X1 有可能预测 X2。请参考这段视频更好的理解格兰杰因果关系。

经过双变量格兰杰因果分析,Bollen 发现,在六个情绪状态(即*静、警觉、确定、充满活力、善良和快乐)中,只有一个,即“*静”情绪状态与股票市场的格兰杰因果关系最高,滞后时间为 2 到 6 天,其他四个情绪维度与股票市场的因果关系不显著。

因此,博伦绘制了“*静”时间序列(滞后 3 天)和 DJIA 时间序列,以显示两者之间的相关性:

阴影部分显示了具有显著相关性的部分。我们应该记住,*静的图表是滞后 3 天的,因此 twitter 数据不是同时预测市场,而是提前 3 天预测。如果我们仔细观察,我们可以看到在这个图表中存在大量的相关性,因此现在可以确定这两个时间序列之间存在相关性。我们可以利用这些信息来预测股票市场,看看我们的预测有多准确。

预测股票市场

现在进行石蕊测试,我们能根据可用的推文预测以前看不见的股票市场趋势吗,我们能预测未来吗?!!

为了预测股票市场,Bollen 使用了一种称为自组织模糊神经网络(SOFNN)的东西,他们使用了一种五层混合 SOFNN 模型来预测股票市场,并获得了相当令人印象深刻的结果。他们使用不同的数据排列,例如,只有*静,*静和快乐等等。他们最好的准确率是 87.6%(哎哟!!!)是他们用非线性的方式把*静和快乐结合起来后得到的。

那么,SOFNN 到底是什么?根据的这篇学者百科文章,他们结合了模糊逻辑和神经网络的精华,为这类任务创建了一个非常好的模型。这两个主题都超出了本文的范围。因此,我们将只简要地讨论其中的每一个。

当处理计算机时,我们主要处理布尔或二进制逻辑,即,任何实体可以是 0 或 1,但是这种类型的逻辑在许多真实世界场景中不适用,因为我们主要处理不止一个结果,例如,游戏的结果主要是赢或输,但是也可以是*局/*局,或者可能赢的差距也可以被考虑, 因此,在 0 和 1 之间可以有更多的状态,这对我们来说似乎比二进制(又称黑和白)方法更自然,更有助于模拟真实世界的情况,这种模糊方法是模糊逻辑背后的逻辑,你可以在这里阅读更多信息。

如果你还没有听说过神经网络,现在是时候从岩石下走出来了,看看一些博客,神经网络是一个时髦词。基本上,它们是一个数学模型,试图模仿(还没有成功)人脑内部的神经元。

这里有一个来自 sholaropedia 的关于什么是混合模糊神经网络的很好的解释:

混合神经模糊系统是同质的,通常类似于神经网络。这里,模糊系统被解释为一种特殊的神经网络。这种混合 NFS 的优点在于它的结构,因为模糊系统和神经网络不再需要相互通信。他们是一个完全融合的实体。这些系统可以在线和离线学习。

模糊系统的规则库被解释为神经网络。模糊集可以被视为权重,而输入和输出变量以及规则被建模为神经元。神经元可以在学习步骤中被包括或删除。最后,网络的神经元代表模糊知识库。显然,两种基本系统的主要缺点都被克服了。

大局

以上四个部分试图解释用于构建 Bollen 提出的模型的较小部分。现在我们来看看最终的模型,以便更好地理解可用于预测股票市场的模型:

The Final Model

首先提取和处理来自 twitter 和 DJIA 的原始数据,然后 twitter 数据通过情绪分析模型 Opinion Finder 和 GPOMS,然后对它们进行格兰杰因果分析,以证明来自 twitter 的情绪确实与 DJIA 值有一些相关性,一旦这种相关性消失,我们现在可以开始用 SOFNN 模型预测股票市场。

[1] Bollen,j .,Mao,h .,Zeng,x .:推特情绪预测股市。计算科学杂志,2(1),1–8(2011)

[2]米塔尔、安舒尔和阿尔皮特·戈埃尔。"使用推特情绪分析进行股票预测."斯坦福 cs 229(2011)http://cs 229 . Stanford . edu/proj 2011/goel Mittal-stockmarketpredictionusingtwittersentimentanalysis . pdf)(2012)。

股票价格预测系统使用 1D CNN 与 tensor flow . js-机器学习轻松有趣

原文:https://towardsdatascience.com/stock-price-prediction-system-using-1d-cnn-with-tensorflow-js-machine-learning-easy-and-fun-fe5323e68ffb?source=collection_archive---------1-----------------------

了解如何建立股票价格预测系统使用 1D 卷积神经网络与张量流。JS 库

Image 1: Stock Price Prediction Application

当我在网上阅读股票预测时,我看到人们谈论使用 1D CNN 来预测股票价格。这引起了我的注意,因为 CNN 是专门为处理像素数据而设计的,用于图像识别和处理,这看起来是一个有趣的挑战。

这个解决方案是使用 Tensorflow.js 库的前端应用程序,最好的部分是它不需要任何服务器端。数据可通过“ IEX 开发者*台API 服务获得。上面的图片 1 来自这个股票预测应用程序。

代码可以在我的 Github 库中找到。

[## gago 993/股票预测 CNN

使用卷积神经网络和 TensorflowJS-gago 993/StockPredictionCNN 的股票预测

github.com](https://github.com/Gago993/StockPredictionCNN)

所有需要完成的工作可以分为 6 个步骤:

  1. 获取数据
  2. 生成要素
  3. 生成 ML 模型
  4. 训练 ML 模型
  5. 测试 ML 模型
  6. 用 ML 模型预测

那么让我们开始…

获取数据

这些数据是使用 IEX 的 API 收集的。API 描述可从以下链接获得。在此应用程序中,我使用的图表端点具有预定义的 1y (1 年)历史周期。占位符 %company% 用于替换我们在应用程序中输入的公司符号。

let url = 'https://api.iextrading.com/1.0/stock/%company%/chart/1y'

这个 API 的结果是带有所请求公司历史数据的 json 数组。以下是来自响应数据的一些示例。

[
...{"date":"2018-02-20","open":169.4694,"high":171.6463,"low":168.8489,"close":169.2724,"volume":33930540,"unadjustedVolume":33930540,"change":-0.5713,"changePercent":-0.336,"vwap":170.3546,"label":"Feb 20, 18","changeOverTime":0},
...
]

生成要素

检索数据后,我们需要处理它并准备特征集和标签集。当我在研究的时候,我发现了他们使用日期字段作为特性的想法。然而,我不喜欢这样,因为有两个原因。首先,日期是不断增加的特征。第二,日期是独立的(与股价没有直接联系)。

我认为与当前股价联系更紧密的是过去股价是如何变化的。例如,今天的股价取决于过去 7 天的股价变化。为此,我们为测试集定义了 7 个特征,每个特征都标有第二天的股票价格。

所有这些数据的预处理都是在 helpers.js 文件中定义的 processData 函数中进行的。在我们的例子中时间部分变量的值为 7。

...
// Create the train sets
for (let i = timePortion; i < size; i++) {for (let j = (i - timePortion); j < i; j++) {trainX.push(scaledFeatures[j]);}trainY.push(scaledFeatures[i]);
}
...

对于 trainX,我们得到的是值的*面数组,但是稍后我们将把它重新整形为具有格式的矩阵:
【样本数- 7,特征数】

另一件重要的事情是,我们首先使用 helpers.js 文件中定义的 minMaxScaler 函数来规范化我们的特性。这将缩放 0 到 1 之间的所有值。这一点很重要,这样预测模型才能更好地适应我们的模型,并且在有大量数据时会更快。如果你想知道更多关于这个最小-最大标准化的信息,你可以在这个博客的末尾找到参考资料。

生成 ML 模型

下一步是创建 CNN 模型。这是由 prediction.js 文件中的 buildCnn 函数完成的。使用 Tensorflow 库确实简化了这一步。我们需要做的是定义顺序(层的线性堆叠)张量流模型,然后添加预定义的层,以便构建我们的 CNN 模型。

但 CNN 是什么? CNN卷积神经网络是深度神经网络的一类,最常用于分析视觉表象。这就是为什么用它来预测股票价格是不寻常和有趣的挑战。

CNN 有 4 个重要的层次,使它与众不同。它们是卷积层、ReLU 层、汇集层和全连接层。他们每个人都有具体的任务要做。然而,我现在不会深入解释 CNN。

让我们继续用 Tensorflow 构建 CNN。我们总共定义了 7 层:

  1. 输入层—输入大小为[7,1],因为我们有 7 个特征
  2. conv1d—第一个卷积层
  3. averagePooling1d 第一个*均池层
  4. conv1d —第二卷积层
  5. *均池 1d-第二个池层
  6. 展*-减小维度,将输入整形为[样本数,要素数]
  7. 密集-使用线性激活函数的全连接图层,其中 1 个单元返回 1 个输出值

下面是我们在顺序张量流模型中定义所有这些层的代码。

在我们建立模型之后,我们进入下一步,即训练我们的模型。

训练 ML 模型

既然我们已经创建了模型,我们需要准备好并转换我们的数据。这意味着将我们的训练和标签集转换为张量数据,因为 tensorflow 使用的是它自己的数据类型,即张量。

这是非常简单的一步。我们创建张量并将我们的特征数据整形为[样本数,时间部分,1]。在这种情况下,时间部分是 7。

...
let tensorData = {tensorTrainX:    tf.tensor1d(built.data.trainX).reshape([built.data.size, built.data.timePortion, 1]),tensorTrainY: tf.tensor1d(built.data.trainY)
};
...

现在我们已经得到了张量,我们将它们与 cnn 函数中的模型一起使用。在这里,我们首先建立优化算法和损失函数。我们使用“ adam ”算法作为优化器,使用“ minSquaredError ”作为损失函数。

model.compile({ optimizer: ‘adam’, loss: ‘meanSquaredError’ });

与 SGD(学术梯度下降)不同,Adam 优化器对每个权重使用不同的学习率。

这里我们需要做的最后一件事是在 tensorflow 模型上调用 fit 函数,并发送 trainX (特征)和 trainY (标签)集合。我们还将 epochs 的选项设置为 100。

在集合的每个项目上训练你的网络一次是一个时期。

...
// Train the model
model.fit(data.tensorTrainX, data.tensorTrainY, {epochs: epochs
}).then(fucntion (result) {
...

当训练结束时,它返回结果,并且模型准备好用于生成预测。

测试 ML 模型

在这一步中,我们已经为将来的预测准备好了模型。我们首先要做的是使用这个模型在我们训练模型的同一个集合上进行预测。这背后的想法是,我们可以比较(可视化)我们的模型符合训练集的程度。

我们简单地通过从模型中调用预测函数来创建预测。

var predictedX = model.predict(tensorData.tensorTrainX);

我们通过调用以下命令获得预测数据:

predictedX.data().then(function (pred) {
...

由于我们之前已经归一化(缩放)了我们的特征,所以我们需要运行逆最小-最大运算,以便获得真实的特征值。我们通过从 helpers.js 调用minmaxinverscaler函数来实现,在这里我们发送预测数据以及最小值和最大值。

var predictedXInverse = minMaxInverseScaler(pred, min, max);

现在我们使用 plot.js 中定义的 plotData 函数,这样我们就可以可视化(实际的和预测的)数据集。P.S .我用了 Chart.js 库做可视化。

Image 2: Actual vs Predicted values for AAPL(Apple)

用 ML 模型预测

剩下要做的是为第二天的股票价格预测生成测试特性。该特性是使用 helpers.js 文件中的generateNextDayPrediction函数生成的。

let nextDayPrediction = generateNextDayPrediction(result.originalData, result.timePortion);

这个函数做的很简单。它从给定的数据中提取最* 7 个股票价格值,并创建测试特征集(用于第二天的预测)。

然后,我们重复相同的步骤,将该数据转换为张量数据,并将其整形为[样本数,特征数,1],在这种情况下,它将是[1,7,1],因为我们只有一个测试示例。

接下来,我们从模型中调用预测函数。

let predictedValue = model.predict(tensorNextDayPrediction);

我们得到预测值并运行逆最小-最大归一化

predictedValue.data().then(function (predValue) {// Revert the scaled features, so we get the real valueslet inversePredictedValue = minMaxInverseScaler(predValue, min,   max);
...
predictedXInverse.data[predictedXInverse.data.length] = inversePredictedValue.data[0];

最后,我们只需将该值添加到预测数据的末尾(来自之前“测试 ML 模型”部分中的训练集),这样就可以在图表上显示该值。

结论

希望这是清晰易懂的。如果您认为某些部分需要更好的解释,请随时添加评论或建议。如有任何问题,请随时联系我。

希望你喜欢它!

有用的链接

[## 功能缩放-维基百科

特征缩放是一种用于标准化独立变量范围或数据特征的方法。在数据中…

en.wikipedia.org](https://en.wikipedia.org/wiki/Feature_scaling) [## 深度学习的 Adam 优化算法简介

你的深度学习模型的优化算法的选择可能意味着良好结果之间的差异…

machinelearningmastery.com](https://machinelearningmastery.com/adam-optimization-algorithm-for-deep-learning/)

别再自称是机器学习公司了

原文:https://towardsdatascience.com/stop-calling-yourself-a-machine-learning-company-c7b231cbe365?source=collection_archive---------30-----------------------

为什么给自己贴上这样的标签可能弊大于利

你听说过一个建筑商把他的公司叫做螺丝刀公司吗?一个摄影师把他的生意叫做相机公司怎么样?那为什么我们突然开始看到所有这些公司都自称为机器学习公司?我认为这个类比很简单,你不应该用你使用的工具来定义你的业务,不管这个工具有多酷。

Photo by Ross Findon on Unsplash

根据你带来的价值来定义你的业务

如果你看过盖伊·卡瓦斯基关于创新艺术的演讲,你可能听说过美国制冰行业的发展。我会建议检查整个演讲,但现在,让我们总结一下这个故事。

Ice 1.0 始于 20 世纪初,人们从冰冻的湖泊中收获冰块,并运送给人们

Ice 2.0 始于人们建造中央制冰厂,可以全年制冰,并按需向人们提供冰块

Ice 3.0 始于我们家里都有冰箱的时候

虽然现在很容易看到这种演变,但许多 Ice 1.0 公司没有过渡到 Ice 2.0,许多公司也没有过渡到 Ice 3.0。这就是我想在这里谈论的,因为我认为给公司贴上机器学习公司或人工智能公司的标签,我们可能会让它们失败。

曾经有一段时间,机器学习是一种可行的方法,当时人们能够建立统计模型来解决他们的业务问题。它可能不那么准确或高效,但它奏效了,而且我们没有看到一波 GLM 公司的成立。尽管机器学习和人工智能很酷,但它只是一种帮助人们解决特定问题的工具。企业需要定义自己,不是通过他们的工具,而是通过他们能给客户带来的价值。如果那些 Ice 收割机在过去根据他们给客户带来的价值来定义他们的业务,帮助他们保持食物的冷藏和新鲜,那么他们将有更好的机会跟上 Ice 1.0 到 3.0 的发展,甚至可能超越这一发展。

机器学习应该放在哪里?

我们需要开始面对这样的事实,仅仅因为你拥有最新的机器学习技术,并不意味着你有一个伟大的企业。为了真正利用人工智能、机器学习和其他技术可以提供的力量,你需要从顶层开始。

如果你不知道你要去哪里,任何一条路都会把你带到那里。
——刘易斯·卡罗尔

一个企业的存在首先是因为它想给生活带来某种改变。这是公司愿景的基础,也是组织努力的目标。借用 Simon Sinek 著名的黄金圈概念,这也是这个行业的原因。请务必注意,无论您提供什么解决方案、销售什么产品以及使用什么工具,您做什么的原因都是一样的。一旦你有了一个清晰的愿景,那么你就可以考虑你的方法,这是你可以传递你独特的愿景的方法。可以是你对客户服务的执着,也可以是你优秀的品质,也可以是你有竞争力的价格等等。只有在你清楚地阐明了为什么和如何之后,你才能继续做你想做的事情,这就是你选择工具的地方。你可能想使用机器学习来在国际上扩展你的个性化客户服务,或者你可能想使用机器学习来提高供应链的整体效率。人工智能和机器学习的使用应该总是伴随着公司为了实现目标而想要解决的问题。人们很容易被诱惑去追逐炒作和跟随市场,并试图以某种方式利用这些新技术,但如果你想实现你的愿景,你必须努力理解这些工具如何增加价值,而不是分散你的目标。

接下来会发生什么?

尽管机器学习和人工智能目前是媒体的一大焦点,但如果历史可以借鉴的话,我们知道总有一天它们会变得像人们使用电脑工作一样普遍。我相信,如果企业想要长期成功,关键是要保持一个长期的观点,一个不受(相对)短期炒作支配的观点。这并不是说公司不应该专注于使用最新的技术和技巧,但这绝不应该是业务的唯一焦点。

随着新技术和新方法的产生和向世界发布,我相信这将为不同市场的参与者提供公*的竞争环境。小型创业公司将和大型成熟企业一样有机会接触到最新技术,这将迫使每个人专注于为人民解决真正的问题。毫无疑问,拥有更多资源的公司可以犯更多的错误,并在游戏中呆更长的时间,但继续保持领先的唯一方法是向客户提供真正的价值。

如何为自己的成功做准备

我在这里绝对不是说你不应该专注于定义一个强大的数据战略和建立一个高级分析工具包。当涉及到交付你想要做的东西时,它们肯定是重要的,但是,它们不应该决定你的企业为什么存在。我认为强大的数据分析能力是一个加速器,它不会告诉你应该去哪里,但会让你快速到达那里,所以在你起飞前明智地选择目的地是非常重要的。

尽管我们非常希望有一颗银弹,但机器学习、人工智能、数据科学以及未来将出现的任何新技术都不会是银弹。如果我们想保持领先,给世界带来积极的变化,我们必须超越工具,开始关注我们为什么要做我们正在做的事情。

如果您喜欢我的内容,请在 https://jchoi.solutions/subscribe注册更多内容

停止对商业领袖说精确和回忆…

原文:https://towardsdatascience.com/stop-saying-precision-and-recall-to-business-leaders-f17082ab5052?source=collection_archive---------11-----------------------

开始说捕获率,改为命中率。

写这篇文章的动机是基于我最*参与的一个项目,在这个项目中,管理层试图辨别一个预测模型的商业价值。对模型结果及其业务影响的理解不够清晰。

用于评估模型能力的指标是准确度、精确度和召回。我不会去解释为什么这些特定的度量标准会被使用,那将是另一个时间。

A diagnostic testing table for binary classification. Source: en.wikipedia.org/wiki/F1_score

我会假设你已经熟悉精度,并回忆或至少理解它们是什么。如果你没有听说过这些指标,Koo 的这篇文章很好地解释了它们。下面是公式的快速复习:

Source: towardsdatascience.com/331fb37c5cb9

我想关注的是管理层在分解预测模型结果时反复提出的问题:那么如果精度是 90%呢?如果我的回忆率低于准确率,这对决策有什么帮助?这些是数据科学家在交流他们的发现以帮助企业决策时必须克服的障碍。在追求创建有史以来最好的模型的过程中,经常会忽略模型的实际方面。

除了了解什么是精确度和召回率,还应该了解关注不同的指标会如何影响预测模型在业务环境中的作用。

我将尝试创建一个强大的业务联系,以提供更多关于如何提升业务价值预测模型的直觉。

精度转换为转化率

让我们从一个简单的上下文开始。假设我们是一家在线零售商,每天有 1000 名访客访问我们的网站。您制作的预测模型用于预测访问者是否可能购买(热门线索)。然后,跟进针对这些线索。

该模型预测并识别了这 1000 人中的 100 个热门线索,并假设 80 个热门线索实际上最终进行了购买。这意味着 80%的转化率。你可能意识到的是,转化率实际上是模型的精度!就这么简单!现在,你可以用一种熟悉的方式告诉管理层预测如何帮助业务,即提高转化率。现在,管理层可以将这个指标与他们当前的过程进行比较,您的项目现在有了清晰的业务含义。

翻译召回捕获再到

假设现在你知道有一个由 100 名高价值访客组成的团队,他们比普通顾客花费更多。预测模型做着同样的预测:一个访问者是否具有高价值,后续行动是针对这些个人的。

该模型设法包括 80 个高价值客户,这是我们的目标市场。这将意味着我们试图锁定的 100 个人的捕获率为 80%。嗯,80%的捕获率实际上就是该车型的召回

简单来说,精准是获得高价值客户比例最高的能力,召回是不错失高价值客户的能力。

请注意,对于不同质量的客户,我们的关注点会有所不同。在第一种情况下,我们更感兴趣的是用最少的努力将尽可能多的访问者转化为买家,而在第二种情况下,我们的目标是抓住尽可能多的目标细分市场。

让我们看一个不同的例子。如果一家银行发起一项活动,提供有吸引力的个人贷款套餐,你会希望将你的套餐提供给尽可能多的潜在贷款支付者,同时避免贷款给潜在的违约者。为了简单起见,我没有考虑其他成本,如竞选成本或因不*等待遇而疏远现有客户的成本。

重温之前的类比:

精准是在活动中获得最高贷款支付者比例的能力,召回是不遗漏贷款支付者的能力。

或者,precision 的目标是不把任何人误认为付款人。召回旨在不将任何人误认为违约者。你的精度是借款人的命中率,而召回是借款人的捕获率

精确度越高,招募违约者的可能性就越小,但潜在客户群会变得更小。召回率越高,潜在客户群就越大,但招募违约者的风险也就越高。我们的召回和精确水*的*衡是一个风险偏好的问题。为了吸引更多的潜在客户,我们是否愿意承担招募不良客户的更大风险?至关重要的是,这些是企业关注的重点。

与业务目标保持一致

企业的战略目标可以是任何东西,从识别潜在客户,捕捉欺诈,最大限度地提高活动效果或减少流失。为了有效地传达预测模型的结果,我们应该与业务领导关注的指标保持一致:转化率、流失率、欺诈事件率、捕获率、命中率等。

因此,与其说你的模型实现了某个百分比的召回率或精确度,不如说你设法实现了更高的捕获率或命中率。

模型度量与业务目标完全一致!

虽然数据科学家能够产生所需的结果,但随之而来的沟通不匹配可能会让决策者感到困惑。确定业务指标对于最大化稳健预测算法的优势至关重要。

我希望我成功地引入了一种不同的视角来使用精确度和召回率来弥合业务用户和数据科学之间的差距。感谢阅读!

停止使用均值来填充缺失数据

原文:https://towardsdatascience.com/stop-using-mean-to-fill-missing-data-678c0d396e22?source=collection_archive---------7-----------------------

均值插补是我用过的第一种处理缺失数据的“高级”方法。在某种程度上,这是用 0 或常数(例如-999)填充缺失值的一大步(请不要这样做)。

然而,这仍然不是一个最佳的方法,今天的帖子会告诉你为什么。

Photo by Pietro Jeng on Unsplash

数据集

对于本文,我选择使用泰坦尼克号数据集,主要是因为它广为人知,并且 年龄 列包含一些缺失的值。首先,让我们导入所有需要的东西,并做一些基本的数据清理。以下是进口货:

Imports — https://gist.github.com/dradecic/bd084cb0c27bd76ed848dccabc9ed9b4

当您检查数据集的头部时,您将得到以下内容:

Titanic Head

关于数据清理,应该完成以下工作:

  1. PassengerIdTicket 应该被丢弃——第一个只是一个任意的整数值,第二个对于每个乘客都是不同的。
  2. 性别 列的值应重新映射为 0 和 1,而不是“男性”和“女性”
  3. 姓名 中提取人物头衔,如先生、夫人、小姐…,如果头衔常见(先生、小姐…),则进一步转换为 0 和 1-0。),如果不是,则为 1(博士、牧师、上尉)。最后, 名称 应该去掉
  4. 应替换为 舱 _ 已知 —如果值为 NaN ,否则为 1
  5. 虚拟列应该从 开始创建 并且第一个虚拟列应该被删除以避免共线性问题

下面是实现这一点的一小段代码:

Data Cleaning — https://gist.github.com/dradecic/74a77c38c4986b490d111331ee74c3ca

*均插补

数据集现在是干净的,但是在 年龄 列中仍然包含丢失的值:

Missing values

因为我不想弄乱原始数据集,所以我会做一个副本并做上标记,所以很明显这里会做均值插补。然后,我将创建一个新属性—Age _ Mean _ Filled—顾名思义,它将包含 Age 属性的*均估算值:

Mean Imputation — https://gist.github.com/dradecic/f7cde4d83cd2fc800a63e59b718039b2

从统计学角度来说,均值插补对数据集的影响如下:

Mean Imputation Changes

是的,意思是一样的,很明显,但是看一下第 25 位第 50 位第 75 位百分位。另外,查看标准差的变化。结论是显而易见的——均值插补对属性可变性有影响。

让我们看看这些分布是什么样子的:

Mean Imputation Distribution Check

左侧和右侧都很接*,但是显著的差异在中间——如你所见。

现在的问题是——如何解决这个问题?

介绍老鼠

MICE,或链式方程多元插补(多么难忘的术语),是一种插补方法,通过多次填充缺失数据来工作。链式方程方法还有一个好处,就是能够有效地处理不同的数据类型,比如连续数据和二进制数据。

引用 statsmodels.org 的,

基本思想是将每个有缺失值的变量视为回归中的因变量,剩余变量中的一些或全部作为其预测变量。MICE 程序通过这些模型循环,依次拟合每个模型,然后使用一种称为“预测*均匹配”(PMM)的程序,从拟合模型确定的预测分布中产生随机抽取。这些随机抽取成为一个估算数据集的估算值。[1]

根据国家生物技术信息中心的说法,以下是使用老鼠的一些主要优势:

多重插补比其他缺失数据方法有许多优势。多重插补涉及多次填充缺失值,创建多个“完整”数据集。如斯查费和格拉汉姆(2002) 所述,缺失值是基于给定个体的观察值和其他参与者数据中观察到的关系进行估算的,假设观察变量包含在插补模型中。[2]

好了,说够了,让我们做一些编码!要开始,您需要通过 pip 安装 impyute 库:

pip install impyute

如果你习惯于均值估算,你可能会认为其他任何事情都要复杂得多,至少在实现方面是如此。在这种情况下,你就大错特错了。

由于 impyute 库的简单性,MICE 的实现不能再简单了。你需要在数组中传递纯值,所以默认情况下 Pandas DataFrame 不会剪切它。很幸运,你可以直接叫 。值就设置好了:

MICE Imputation — https://gist.github.com/dradecic/6b567e42dd9890f9e6dae125a70a433f

这很快。

快速调用。描述()小鼠 _ 年龄 会产生以下结果:

MICE default

请注意最小值。现在是零下 7 度。因为这个属性代表年龄,所以有负值是没有意义的。这可以通过一些基本的列表理解很容易地解决:

Negatives — https://gist.github.com/dradecic/8e8a4c5df08369abb6b3246f25cd5cfc

如果你现在检查原始的 年龄 的统计数据,和老鼠估算的一,你会看到数值更接*:

MICE Imputation Changes

快速分布图证实了这些说法。小鼠估算值的分布更接*原始分布。

MICE Imputation Distribution Check

最后的话

你现在知道你的库存里有什么新技能了。我的建议是,你可以试着在你已经处理过的数据集上使用它,但是用均值插补或者其他方法代替。

如果你在那里开发了一个预测模型,看看准确性如何比较。如果能因此挤出点额外的精准度就太好了。

感谢阅读。

直到下一次…

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

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

medium.com](https://medium.com/@radecicdario/membership)

参考

[1]—https://www.statsmodels.org/stable/imputation.html

[2]—https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3074241/

停止使用终结者图像

原文:https://towardsdatascience.com/stop-using-terminator-images-10b2feb79c78?source=collection_archive---------37-----------------------

人工超级智能不会有奥地利口音

Image by WikiImages from Pixabay

我们都看过这些文章。他们警告我们,未来先进的人工智能(AI)将变得“流氓”,并毁灭我们所知的生命。由于这部分是终结者电影的情节,这些文章使用这些电影的图像来说明这一点。

我完全赞成警告人类人工智能未来可能出现的问题。我确实认为这会导致我们的灭绝。这可能是我们最大的生存风险。我在使用《终结者》系列电影的图像时遇到的问题是,这些电影预测了一个极不可能的未来。终结者特许经营是娱乐——它(可能)甚至不意味着是准确的。

对于不知道终结者特许经营权的你们中的少数人,我将快速解释一下剧情。这个想法是,在某个时间点,一群人构建了一个名为天网的人工智能。用于国防,天网这个学习系统变得越来越聪明,最终发展成为一个有自我意识的 AI 。将人类视为一种威胁,它建立了一支杀手机器人军队,在导致不同国家相互投掷核弹后,与人类的残余进行战斗。人类由一个名叫约翰·康纳的人领导,天网在约翰出生前派了一个终结者(阿诺德·施瓦辛格饰演的一个被人肉覆盖的人形机器人)回到过去杀死了约翰的母亲莎拉·寇娜

从电影中我不太清楚天网的确切智能水*,但由于天网确实有自我意识,并且是一个学习系统(智能不断增加),我将假设它是一个人工超级智能:一个比任何人类都要智能得多的人工智能

为什么我认为《终结者》电影中的场景不太可能?首先,高度先进的感知暗杀机器人将能够准确射击,施瓦辛格扮演的终结者是一个可怕的射手。

任何人类与 ASI 对抗并且不会很快被消灭的场景都是不现实的。

但是关于终结者的场景有一个更大(也更可怕)的问题,那就是:任何人类与人工智能对抗并且不会很快被消灭的场景都是不现实的。从定义上来说,一个 ASI 非常擅长实现它的任何目标,而且几乎对任何目标来说自我保护都很有用。因为从定义上来说,人工智能比我们更聪明,所以它很可能比我们更善于自我保护。这直接意味着将赢得这场战争,如果有一个的话。如果你认为一个 ASI 可能没有办法杀死我们,再想想。它会找到办法的。它甚至可能说服我们给它提供手段,就像如果它没有互联网连接,它会说服我们给它提供互联网连接一样。我在这里写了一个有趣的实验:

[## 人工智能盒子实验

一个简单的实验能教会我们什么是超级智慧

towardsdatascience.com](/the-ai-box-experiment-18b139899936)

《终结者》的场景不切实际,这是不使用其图片来说明高级人工智能出错警告的一个非常好的理由。即使人们知道这是科幻小说,我仍然害怕看到图片会产生一些 锚定 效果他们知道场景是假的,但他们没有在头脑中进行足够的调整。结果是对未来的某种半虚构的憧憬,这对任何人都没有好处。考虑 ASI 已经非常困难了,因为我们很难不把拟人化;看到终结者的图像只会让这变得更加困难。

停止使用邮政编码进行地理空间分析

原文:https://towardsdatascience.com/stop-using-zip-codes-for-geospatial-analysis-ceacb6e80c38?source=collection_archive---------3-----------------------

上次使用邮政编码时,您很可能是在网站上输入您的地址进行购物,在您家或办公室附*寻找商店,或者填写其他在线表格。你很可能找到了你想要的答案,而没有停下来进一步思考你刚刚输入的五位数代码。

然而,许多公司、营销人员和数据分析师会花数小时查看邮政编码。他们正在决定如何使用与这些邮政编码相关的数据来了解趋势,经营他们的业务,并使用相同的五位数代码找到联系您的新方法。

即使有不同的地点关联对你个人来说可能更有意义,例如街区、街道或你居住的街区,但在许多组织中,邮政编码是地理单位的选择。它用于制定营销、开店或关店、提供服务的重大决策,以及可能产生巨大财务影响的决策。

问题是,邮政编码并不能很好地代表真实的人类行为,当用于数据分析时,往往会掩盖真实的潜在见解,并可能最终导致糟糕的结果。要理解这是为什么,我们首先需要了解邮政编码本身。

邮政编码:简史

邮政编码的前身是邮政区,代表特定城市的邮局部门。例如:

无名氏先生

亨内*大街 515 号

明尼苏达州明尼阿波利斯 16

“16”代表明尼阿波利斯市的邮政区。但是随着越来越多的邮件被发送,1963 年邮政服务决定推出区改善计划,该计划将地址改造成如下所示:

无名氏先生

亨内*大街 515 号

明尼苏达州明尼阿波利斯 554 16

五位数代码代表国家的一部分(5_ _ _ ),一个部门中心设施( ** 5 4 _ ),以及相关的邮局或投递区域( _ _ 1 6)。

The first digit for every zip code for the states in the contiguous United States

到 1967 年,邮政编码成为批量邮寄的强制性规定,并继续被几乎所有在美国发送邮件的人所采用。随着时间的推移,添加了 ZIP+4 来增加邮政编码的粒度,以表示特定的位置,甚至是供邮政工作人员投递的建筑物。邮政服务甚至创造了一个角色,邮政先生,来推广邮政编码的使用,他出现在邮票、商业广告和歌曲中。

Mr. Zip

邮政编码本身实际上并不代表一个区域,而是一组路线:

尽管大多数邮政编码的地理来源不同,但编码本身并不代表地理区域;通常,它们对应于地址组或传递路线。因此,邮政编码“区域”可以重叠,可以是彼此的子集,也可以是没有地理区域的人工构造(例如,095 表示寄给海军的邮件,它在地理上是不固定的)。以类似的方式,在没有常规邮政路线的地区( 农村路线 地区)或者没有邮件递送的地区(不发达地区),不分配邮政编码或者基于稀疏的递送路线,因此邮政编码地区之间的边界是不确定的。

美国人口普查局为邮政编码列表区或地理文件提供数据:

邮政编码列表区(ZCTAs)是美国邮政署​(USPS)邮政编码服务区的通用区域表示。

USPS 邮政编码标识与邮寄地址相关联的各个邮局或大都市地区投递站。USPS 邮政编码不是区域要素,而是邮件递送路线的集合。

在这里,我们发现了邮政编码的第一个问题,即它们并不代表地图上的实际区域,而是帮助邮政工作人员有效投递邮件的路线集合。它们不是为了衡量社会人口趋势而设计的,而这正是一家企业通常想要做的。您可以实际查找单个交货路线,如下图所示:

One zip code route in New York’s East Village

我们在这里只是触及了问题的表面。类似的问题在世界各地都存在,邮政编码代表着奇怪的边界:

Postal Codes in London, Toronto, and Sydney

使用邮政编码进行数据分析

快进到今天,许多公司可以很容易地查看他们的数据库,找到一个带有 zip_code 列的数据集,这使他们能够分组和聚合数据,以查看趋势和业务绩效指标。如前所述,邮政编码的问题在于:

  1. 它们并不代表真正的边界,而是路线
  2. 它们不代表人类的行为方式

后者代表了使用空间数据的两个具体问题:观测的空间比例和空间比例支持(您可以在 UChicago 的 Luc Anselin 的讲座中了解更多信息,此处)。首先,人类的行为不会基于行政单位,如邮政编码,甚至人口普查单位。他们的行为更多地受到他们邻居的影响,或者受到社区或高活动区域(如中央商务区)的影响。第二,空间数据是以多种比例提供的,而且这些边界往往重叠或嵌套在另一个边界内。

让我们来看一个发生在达拉斯某个特定地区的例子。

Zip Code boundaries (white) with Census Block Groups based on Income

在这张地图中,我们可以看到大的白色边界,代表邮政编码的边界,在它们下面是美国人口普查区块组的边界。美国人口普查提供的数据显示,深绿色代表高收入。

当我们查看一个特定邮政编码时,我们可以看到更详细的收入数据:

我们可以看到,在这个单一邮政编码(75206)中,12 个月的家庭收入中位数在 9700 美元到 227000 美元之间,当我们看完全或部分属于这个单一邮政编码的街区群体时,人口普查列出的家庭收入中位数为 63392 美元。

收入中位数是评估一个邮政编码范围内的值的一种方法(请记住,这些是 ZCTA 边界),但我们可能会在人口、就业和其他数据分析的相关指标中看到这样的差异。

坚持家庭收入中位数,我们决定将这一分析扩展到整个美国,当您查看邮政编码和与 ZCTA 边界相交的人口普查区块组(至少有 1 人居住在该区块组中)时,看看哪些区域最不*等和最不*等。

最不*等的邮政编码是佛罗里达州迈阿密海滩的 33139

  1. 33139:佛罗里达州迈阿密(差额 241344 美元)
  2. 44120:俄亥俄州克利夫兰(237501 美元差额)
  3. 10013:纽约州纽约市(233,559 美元差额)
  4. 10023:纽约州纽约市(233,157 美元差额)
  5. 11201:纽约布鲁克林(233031 美元的差价)
  6. 10601:纽约州怀特普莱恩斯(232,813 美元差价)
  7. 33141:佛罗里达州迈阿密(差额 232633 美元)
  8. 92648:加州亨廷顿海滩(231290 美元差价)
  9. 98105:华盛顿州西雅图市(230,906 美元差额)
  10. 33143:佛罗里达州迈阿密(差额 230626 美元)

最相似的*邮政编码在西弗吉尼亚州的切萨皮克

  1. 25315:西弗吉尼亚州切萨皮克(2 美元差额)
  2. 79357:德克萨斯州圆锥市(4 美元差价)
  3. 65052:密苏里州林恩克里克(9 美元差价)
  4. 73093:俄克拉荷马州华盛顿(相差 12 美元)
  5. 68370:东北希伯伦(相差 13 美元)
  6. 19541 年:宾夕法尼亚州莫尔斯维尔(相差 15 美元)
  7. 05340:佛蒙特州邦德维尔(18 美元差价)
  8. 12958:纽约州穆尔市(相差 26 美元)
  9. 19941 年:埃伦代尔,德(相差 37 美元)
  10. 54896:洛丽塔,威斯康星州(38 美元的差异)

*差异大于 0 时类似

为了对整个美国进行这种分析,我使用 CARTO 及其笔记本扩展 CARTOframes 来获取人口普查区块组和人口普查 ZCTA 地区的人口普查数据,这些数据存储在 CARTO 中。

一旦我们有了两组边界,我们就要查看所有完全被 ZCTA 边界包含,或者至少 50%被 ZCTA 边界包含的块组。为此,我们可以使用 PostGIS 来查找这些交叉点,并根据这些数据创建不同的统计测量值(最小值、最大值和百分位数)。

你可以在这个笔记本里看到完整的方法论和代码。

SELECTz.*,MIN(b.median_income),MAX(b.median_income),SUM(b.total_population) AS total_pop,percentile_disc(0.25) WITHIN GROUP (ORDER BYb.median_income) AS p_25,percentile_disc(0.5) WITHIN GROUP (ORDER BYb.median_income) AS mean,percentile_disc(0.75) WITHIN GROUP (ORDER BYb.median_income) AS p_75,stddev_pop(b.median_income)FROMincome_zips zLEFT JOIN income_bgs b ON ST_Intersects(z.the_geom, b.the_geom)WHEREb.total_population > 0AND (ST_Area(ST_Intersection(z.the_geom, b.the_geom))/ ST_Area(b.the_geom)) >.5GROUP BYz.cartodb_id

创建新表后,我们可以看到,大多数最不*等的邮政编码往往位于城市或更大的都会区,而更*等的邮政编码往往位于全国各地的农村地区。

根据最高值和最低值之间的范围探索邮政编码的空间显著性聚类也是值得的,这非常适合使用空间自相关。你可以在这篇文章或者这篇教程中了解更多。

那么我们为什么使用邮政编码呢?

实际上,使用邮政编码作为地理空间单位很容易。正如我们之前所说的,几乎所有使用定位或需要以任何方式定位用户的电子商务或交付服务或应用程序都会收集邮政编码。此外,每个人都熟悉邮政编码,因为在大多数国家,邮政编码是任何地址的一部分。

‘Find A Store’ on Target.com

不经常使用地理空间数据的人不太熟悉人口普查区块组或区域等术语,它们可能更难找到和使用,尤其是如果您不熟悉 Shapefile、FTP 和 ETL 等术语。即使这样,你也必须通过美国人口普查 FTP 网站,下载各州的地理文件,并将这些文件加入人口普查数据。

最后,不用看地图,大多数人都知道邮政编码代表的区域比城市小,但比街区大。从概念上讲,他们觉得自己足够小,可以获得一个非常集中的世界视图,也足够大,可以捕捉足够多的趋势样本。

简短的回答是邮政编码很容易找到,很熟悉,并且提供了一个足够详细的世界视图(或者我们是这样认为的)。

也就是说,在地理空间分析中使用邮政编码会产生一些现实问题。一个例子是房地产,在许多城市或地区,有房屋列在一个‘期望’邮政编码中,尽管我们知道这些界限是任意的。这篇来自《哈佛商业评论》的文章也描述了 Airbnb 房源和房租上涨的类似现象。

简单来说,我们认为,如果一个邮政编码是“旅游性的”,意味着它有很多餐馆和酒吧,如果 Airbnb 的知名度增加,我们使用谷歌搜索指数搜索关键词“Airbnb”,那么该邮政编码的 Airbnb 供应的任何跳跃都可能是由 Airbnb 短期租赁需求的增加驱动的,而不是当地的经济状况。

更重要的是,使用邮政编码进行分析可以掩盖在不同空间尺度上发生的严重情况。弗林特水危机就是其中之一。密歇根州立大学助理教授 Richard Casey Sadler 的这篇文章详细描述了这个问题,并提出了关于邮政编码的类似观点(全文值得一读):

亚利桑那州立大学的教授托尼·格鲁贝希奇博士称它们为“世界上更加古怪的‘地理学’之一”哈佛大学教授南希·克里格(Nancy Krieger)博士和他的同事们呼吁他们的用于小范围分析。

最终,该州使用邮政编码来分析血铅统计数据,这有效地掩盖了实际问题。这是因为:

在弗林特的案例中,州政府的错误是因为“弗林特邮政编码”与弗林特市或其供水系统不一致。城市和水系统几乎 100%相连,也就是说,它们共享相同的边界…总之,该州分析中使用的弗林特邮政编码覆盖了弗林特周围八个不同自治市(七个乡镇和一个城市)的部分区域。

Map by Richard Casey Sadler

在弗林特的例子中,简单地观察不同的空间尺度或分析可能会更清楚地显示问题。对于公共卫生和关键服务等领域,理解和使用适当的空间比例至关重要。

我们还能做什么?

因此,如果您被迫放弃邮政编码分析,好消息是有几种不同的选择。

使用地址

首要的建议是使用真实的地址。当你知道一个地址串时,你可以使用地理编码器——或者谷歌或其他地图搜索引擎用来获取地址并将其转换为纬度和经度的服务。几乎每个主要的服务都为不同的语言提供了 API 和包装器来实现这一点。请记住,通常有一些清理数据的最佳实践,你将需要有效的地址串来这样做。其他工具如 Libpostal 可以帮助你规范化和解析你的地址字符串。

使用普查单位

您也可以使用人口普查单位,如人口普查区块组或区域。正如我提到的,寻找和收集大规模的数据并不总是容易的,但有许多新的工具正在变得可用。 CenPy 是一个 Python 库,允许你连接和查找人口普查数据(好的教程在这里),在这里你可以找到十年一次的人口普查或美国社区调查的数据。CARTO 还通过数据观测站提供人口普查和 ACS,该观测站在笔记本中用于完整的美国分析。

您还可以使用美国人口普查地理编码器找出特定地址位置的人口普查几何 id。你可以在 API 中传递各种参数,或者在 Python 中使用 censusgeocode 包。

在收集地址数据时,您可以轻松地将人口普查区域或街区组 ID 添加到该条目中,并在数据中使用该 ID 而不是邮政编码字段。这将允许您进行与之前相同的聚合,只是在更合适的地理范围内。

使用自己的空间索引

最后,现在有越来越多的地理空间索引工具。谷歌用 S2 单元格,你可以用四键索引网格单元格,优步用 H3 hexbins 。所有这些库的好处是父单元的子单元被父单元更均匀地包含,以避免空间重叠问题。只要您有纬度和经度(这将需要地理编码),您就可以使用各种各样的库之一为该记录分配一个 ID。

使用空间索引有两个主要优点。首先,您不会被锁定到任何特定的边界类型,您可以在地球上的任何地方使用相同的研究单位。只要基础数据相同,您就可以将曼哈顿中城的某个单元格的趋势与尼日利亚拉各斯的某个单元格的趋势进行比较。

***

Uber H3 Cells*

第二是敏感数据的匿名化。考虑到地址数据可能很敏感,您可以创建一个数据管道,只需读取传入地址,对其进行地理编码,分配一个空间索引,然后将该索引数据传递到一个单独的表中,然后您可以根据需要存储或删除地址数据。

使用空间数据可能很困难,但数据和工具的可用性使其变得更容易访问。通过使用正确的空间比例并放弃邮政编码级别的分析,您可以提高见解的质量并创建更有意义的结果和分析。

Matt Forrest 在 CARTO 工作,过去 9 年一直从事空间数据科学方面的工作。

别等了!开始使用异步并等待!

原文:https://towardsdatascience.com/stop-waiting-start-using-async-and-await-18fcd1c28fd0?source=collection_archive---------2-----------------------

Photo by Harry Knight on Unsplash

介绍

对我们数据科学家来说,最重要的因素是数据。我们如何把我们需要的数据输入到我们的程序中?我们通过一些 I/O 操作来做到这一点,如查询数据库、从磁盘加载文件或通过 HTTP 请求从 web 下载数据。这些 I/O 操作可能需要相当长的时间,我们只是在等待数据被访问。当我们必须加载多个文件、执行多个数据库查询或执行多个 HTTP 请求时,情况会变得更糟。大多数情况下,我们按顺序执行这些操作,这导致执行 100 个 I/O 操作总共要比执行单个操作多花 100 倍的时间。现在等待不仅令人讨厌,而且成为一种真正的痛苦。但是等待,不要太久:),在我们启动另一个完全独立的请求之前等待请求的响应有意义吗?或者举一个日常生活中的例子,当你给两个人发邮件时,你会等到收到第一个人的回复后再给第二个人发邮件吗?我想不会。在本文中,我想向您展示如何使用 Python 中的异步 IO(简称 AsyncIO)编程范例来显著减少 IO 绑定问题的等待时间。我不会过多地探究技术细节,而是让它保持相当基本,并向您展示一个小的代码示例,希望这有助于您的理解。

问题是

假设我们想从一个服务器下载三个不同的文件。如果我们按顺序执行,大部分时间我们的 CPU 是空闲的,等待服务器响应。如果响应时间占主导地位,那么总执行时间就是各个响应时间的总和。示意性地,这看起来像图 1 所示。

Picture 1 showing the sequential execution flow and time.

我认为空闲的 CPU 听起来不太理想。按顺序发送请求,等待所有请求完成,然后组合所有响应,这样不是更好吗?在这种情况下,再次假设响应时间占主导地位,总的执行时间大致是所有请求中最大的响应时间。这示意性地显示在图 2 中。

Picture 2 showing the idealized concurrently send non-blocking request execution time.

请注意,蓝色条只是显示了发送请求和响应可用之间的时间。在这段时间内,我们不应该只是有一个空闲的 CPU,而是应该利用它来执行一些工作。这正是我们在这里所做的。当一个请求的响应到达时,我们已经处理了它,同时还在等待其他响应的到达。听起来很棒,不是吗?那么我们如何编写利用这一点的代码呢?正如在介绍中已经说过的,我们可以使用 AsyncIO 来达到这个目的。

解决方案

异步是一种更高级的编程范式,在这种情况下,您开始一项任务,虽然您没有该任务的结果,但您做了一些其他工作。这样,尽管在单个进程中使用单个线程,AsyncIO 还是给人一种并发的感觉。实现这一点的神奇要素是事件循环、协程和属于协程的可应用对象——对象、任务和未来。非常简单

  • 一个事件循环协调一个可应用对象的执行和通信。没有事件循环,我们就不能使用 awaitables,因此,每个 AsyncIO 程序至少有一个事件循环。
  • 本地协程是用异步定义定义的 python 函数。你可以把它想象成一个可暂停的函数,它可以保持状态并从暂停状态恢复执行。你可以通过调用wait来暂停一个协同程序。通过暂停,它将控制流释放回事件循环,从而使其他工作得以完成。当 awaitable 的结果就绪时,事件循环将控制流交还给协程。调用协程会返回一个协程对象,必须等待它才能得到实际结果。最后,重要的是要记住**你只能在一个协程内调用 await**您的根协程需要通过阻塞调用被调度到事件循环上。

下面是一些非常基本的代码,希望有助于您的理解

***import** asyncio**async def** sample_coroutine():**return** 1212**async def** main_coroutine():coroutine_object = sample_coroutine()**# With await, we stop execution, give control back to the # eventloop, and come back when the result of the # coroutine_object is available.**    result = **await** coroutine_object**assert** result == 1212**# Blocking call to get the event loop, schedule a task, and close
# the event loop**
asyncio.run(main_coroutine())*

如果你对更全面的介绍感兴趣,我向你推荐这个、这个和那个。

这个例子

理论够了,来试试吧。使用原生协程的先决条件是 Python 3.5+,但是 asyncio 发展很快,所以我建议使用最新的 Python 版本,在撰写本文时是 3.7+。举个例子,我下载了几张狗的图片。为了进行比较,我以同步和异步方式进行了相同的操作。为了执行 HTTP 请求,我将请求用于同步部分,将 AIOHTTP 用于异步部分。我有意省略了任何类型的错误检查,以避免重复代码。

代码

所以让我们首先安装必要的模块

*pip install aiohttp requests*

接下来,我导入模块并添加一个小的助手函数

***import** asyncio
**import** time
**from** typing **import** Any, Iterable, List, Tuple, Callable
**import** os
**import** aiohttp
**import** requests**def** image_name_from_url(url: str) -> str:**return** url.split(**"/"**)[-1]*

现在,给定一组图像 URL,我们可以通过以下方式将它们顺序下载并存储为一个图像对列表(图像名,字节数组)

***def** download_all(urls: Iterable[str]) -> List[Tuple[str, bytes]]:**def** download(url: str) -> Tuple[str, bytes]:print(**f"Start downloading** {url}**"**)**with** requests.Session() **as** s:resp = s.get(url)out= image_name_from_url(url), resp.contentprint(**f"Done downloading** {url}**"**)**return** out**return** [download(url) for url in urls]*

我添加了一些打印语句,这样您就可以看到执行该函数时会发生什么。到目前为止还不错,到目前为止没有什么新的,但现在来了异步版本

***async def** donwload_aio(urls:Iterable[str])->List[Tuple[str, bytes]]:**async def** download(url: str) -> Tuple[str, bytes]:print(**f"Start downloading** {url}**"**)**async with** aiohttp.ClientSession() as s:resp = **await** s.get(url)out = image_name_from_url(url), **await** resp.read()print(**f"Done downloading** {url}**"**)**return** out**return await** asyncio.gather(*[download(url) for url in urls])*

啊哈,这看起来几乎是一样的,除了所有那些异步和等待关键字。让我给你解释一下这里发生了什么。

  • download_aio 是一个协同例程,因为它是用异步定义定义的。它必须是一个协程,因为我们在其中调用其他协程。**
  • 下载协程中,我们使用异步上下文管理器(async with)创建一个会话对象,并等待 get 请求的结果。此时,我们执行潜在的持久 HTTP 请求。通过等待,我们暂停执行,给其他任务工作的机会。
  • asyncio.gather 可能是这里最重要的部分。它执行一系列合适的对象,并返回收集结果的列表。有了这个功能,你可以达到一种并发的感觉,如图 2 所示。使用 gather 不能调度太多的协程,它的数量级是几百个。当您遇到这种问题时,您仍然可以将调用划分为较小的块,然后逐个收集。像调用协程返回一个变量一样,调用 gather 也返回一个变量,您必须等待它才能得到结果。

让我们把它们放在一起,运行它,然后比较下载狗狗需要多长时间。

结果呢

下面是执行同步和异步 Http 调用的代码。

***if** __name__ == **"__main__"**:**# Get list of images from dogs API**URL = **"https://dog.ceo/api/breed/hound/images"
**    images = requests.get(URL).json()[**"message"**]**# Take only 200 images to not run into issues with gather**     reduced = images[:200]st = time.time()images_s = download_all(reduced)print(f"Synchronous exec took {time.time() - st} seconds")st = time.time()images_a = asyncio.run(donwload_aio(reduced))print(f"Asynchronous exec took {time.time() - st} seconds")*

在稍微简化的版本中,同步版本打印出

开始 1,结束 1,开始 2,结束 2,…,开始 200,结束 200

这反映了图 1 所示的流程。异步副本打印出如下内容

开始 1,开始 2,…,开始 200,结束 3,结束 1,…,结束 199

这反映了图 2 中所示的内容。太棒了,这就是我答应你的。但我认为单凭这一点并不太有说服力。所以,把最好的留到最后,让我们看看执行时间。在我的机器上下载 200 张图片,同步调用需要 52.7 秒,而异步调用需要 6.5 秒,大约比快 8 倍。竟有人会说出这种话来!亏你(他)说得出口加速会因单个项目的最大下载时间而异,这取决于项目的大小和服务器在不减速的情况下可以处理的负载。

外卖

  • 对于您希望加速的 IO 相关问题,请使用 AsnycIO。有许多 IO 绑定操作模块,比如 Aioredis 、 Aiokafka 或 Aiomysql 等等。要获得更高级别的异步 API 的完整列表,请访问 awesome-asyncio 。
  • 您只能等待协程中的协程。
  • 您需要通过调用 python 3.7+中的 asyncio.run 或 asyncio.get_event_loop()来调度您的异步程序或“根”协程。python 3.5–3.6 中的 run_until_complete。
  • 最后也是最重要的:不要等待,等待!

希望你已经学到了一些新东西,可以减少等待时间。感谢您的关注,如果有任何问题、意见或建议,请随时联系我。

仓储+商业建筑:负荷预测

原文:https://towardsdatascience.com/storage-commercial-buildings-part-1-load-forecasting-8d3c4d1e083d?source=collection_archive---------31-----------------------

Photo by chuttersnap on Unsplash

长期以来,储能一直被吹捧为“银弹”,它将通过一长串有前途的价值主张(例如,与间歇发电、能源套利、辅助服务相结合)来解决我们所有的能源挑战。

在过去几年中,我们看到前台和后台级别的存储部署都在快速增长。除了 2016-2017 年几个巨大的公用事业规模的电池部署,非住宅存储系统是增长的关键来源。

Source: Wood Mackenzie U.S. Energy Storage Monitor Q3 2019 (link)

储能市场尚未爆发,技术和成本挑战仍阻碍着广泛部署。然而,我们非常接*拐点,这将为一个全新的技术类别打开大门,这将永远改变更广泛的能源领域的所有方面。从这个项目开始,我们寻求更好地理解这个巨大的技术浪潮(所以我们不要错过它!)🌊

项目目标

为了更好地了解商业存储领域的挑战和机遇,我们在商业建筑环境中模拟了一般电池存储单元的调度。

具体来说,我们试图回答以下问题:

  1. 商业建筑负荷(千瓦)的关键决定因素是什么?
  2. 商业存储的价值主张在哪些地区最强?
  3. 是什么阻碍了现有商业规模存储公司的高速增长?
  4. 在大型办公楼中调度电池时,需要考虑哪些关键因素和限制?

我们将首先探索商业建筑负荷,然后使用机器学习技术为我们感兴趣的地理位置生成预测(本文)。然后,我们将使用建筑负载预测作为输入来测试和改进我们的存储调度算法(即将推出⏳).

概述:商业负荷预测

仪表后储能单元最重要的变量之一是建筑的每小时能耗(单位为 kWh)。为了对大型商业建筑中的仪表后能量存储单元的最优调度进行适当建模,我们需要对建筑的负荷进行多年预测。

我们采用监督学习技术(特别是多项式回归)来预测这个商业建筑负荷。本文的其余部分将介绍这个过程的细节。

1.识别关键驱动因素💭

我们打算使用监督学习技术(特别是多项式回归)来预测这个商业建筑负荷。商业建筑负荷取决于各种内部和外部因素,包括:

  • 小时
  • 温度
  • 尺寸(空间体积)
  • 照明类型和消耗
  • HVAAC 类型和消耗量
  • 雇员人数
  • 工作时间
  • 电动汽车的数量
  • 房间数量
  • 诸如此类…

不幸的是,这些数据很难在训练集中获得。出于此分析的目的,我们采用了一种简单的方法来预测单个建筑的商业负荷,方法是使用外部空气温度(OAT)和时间作为独立变量。

具体来说,我们将使用能源部的参考建筑 7(“办公室”)长期能源消耗&室外空气温度数据集(来源),其中他们已经发布了每小时建模的建筑负荷数据,以及相应的时间戳和 OAT。

2.探索关系🔎

仅仅通过挖掘我们的独立变量(一天中的某个时间,温度)和相关变量(建筑负荷)之间的关系,我们就可以确定清晰的模式和见解。

时间序列(温度、负荷)

为了获得训练数据的鸟瞰图,我们绘制了温度和负载的每小时时间序列数据。将这两张图表放在一起看,你已经可以开始画出它们之间的关系了(极端温度=更高的建筑负荷)。

温度与负载

当我们观察温度和建筑负荷之间的关系时,事情变得更有趣了。一般来说,建筑负荷似乎在极端天气(0–20℉和 80–100℉)期间达到峰值,很可能是由于制冷和供热增加&。这并不奇怪,因为暖通空调系统(供暖、通风和空调)占办公楼总能耗的 28%。

我们确实注意到许多情况,尽管温度极高,但能源消耗保持相对*稳。这有点违反直觉,值得在未来研究。

小时与负载

小时与构建负载之间的关系也相当直观(尽管模式相对来说不那么“清晰”)。在典型的工作时间(上午 9 点到下午 5 点)能耗水*较高,从下午 6 点开始能耗水*显著下降(也称为“快乐时光”)🍸)

一个意想不到的观察结果是,早上 5 点到 8 点之间的能耗水*明显高于夜间/黎明时段。一种假设是办公大楼可能在员工到达前几个小时就开始制冷/制热(有点怀疑,因为这意味着大楼需要 4 个小时制冷/制热😒).无论哪种方式,绝对值得一看后🕵️‍♀️

3.建模🤖

基于#2 中的探索性分析,很明显,因变量和自变量之间的关系是非线性的。因此,我们将使用带有正则化的多项式回归作为我们的模型。

为了确定超参数的最佳组合(即多项式次数、正则化 alpha),我们使用了 scikit-learnGridSearchCV 功能。

[关于评估指标的更多详细信息即将发布…🔃]

4.结果📊

为了预测我们感兴趣的位置(华盛顿州西雅图市)的建筑负荷,我们需要获得该城市的每小时温度数据。幸运的是,这在来自 Kaggle ( 来源)的历史整点天气数据 2012–2017数据集中很容易获得。我们使用这些数据(经过一些预处理)作为我们在#3 中训练的回归模型的输入,来预测相应的每小时建筑负荷。

虽然得到的每小时负载形状与我们从 OpenEI 得到的训练数据集有些不同,但总体趋势与我们在#2 中观察到的一致。

工作时间的负载峰值:

极端天气下的负载峰值(主要在寒冷的冬天):

结论

由于商业建筑的能耗往往在工作时间达到峰值(尤其是在极端天气事件期间),我们可以得出初步结论,气温变得非常热(例如亚利桑那州、奥斯汀、丹佛)或非常冷(例如纽约、芝加哥)的大都市更有可能成为有吸引力的市场。

考虑到预测值通常有意义并且与训练数据一致,我们开始使用该数据集作为输入来测试存储调度模型。同时,我们打算进一步完善和测试我们的建模,以生成更完善的每小时负载形状。

正如在开始时提到的,这绝对是一个非常简单的商业站点负荷预测模型,因为在现实中有许多其他变量决定着建筑物的能耗。虽然我们可以在 DoE 的参考建筑中保持相同的假设,用于本项目的实际目的,但扩展我们的回归模型以考虑额外的变量(在可能的范围内)可能是值得的。

上面分析的 GitHub repo 可以在这里找到。

项目贡献者: Jae Beom Bae , Niel Patel

商店不会去任何地方:人工智能授权的客户真正想要什么

原文:https://towardsdatascience.com/stores-arent-going-anywhere-what-ai-empowered-customers-really-want-6f06ca007e5f?source=collection_archive---------30-----------------------

Photo by Mike Petrucci on Unsplash

网上购物更快、更方便,提供了更多的种类和选择,而且不会有烦人的推销人员来推销东西。实体店面对新一代客户,他们拥有人工智能和技术知识,有着多样化的需求和高期望。无论我们关注的是一家小型品牌商店还是整个购物中心,零售业要想生存下去,就必须提供全新的体验,以便为越来越多与渠道无关的一代客户提供服务。那些设法适应的商店将提供如此特别的东西,以至于任何电子商务*台都无法与之竞争。

你可以在网上买到任何东西。从杂货(亚马逊生鲜)到时尚(Stitchfix),从汽车(Carvana)到眼镜(Warby Parker)。你想要的一切只需点击几下鼠标。很自然,我们不得不期待一场零售业的末日,因为商店正在关门,购物中心越来越空,似乎没有人再去把食品杂货带回家了。这是零售业末日的普遍说法。

这里有些事实可能会让你大吃一惊:

购物中心没有消亡。

在世界范围内,购物中心的数量正在增长而不是放缓。主要是在亚洲,对线下零售空间和商店概念有巨大的需求。(在科尔尼)

去商店仍然是零售的首选

目前,电子商务仅占美国零售总额的 16%,预计到 2030 年,这一数字将接*零售总额的三分之一。这意味着:在相当长的一段时间内,三分之二的零售销售不会发生在网上。(在科尔尼)

千禧一代非常喜欢在商店购物

只是不是任何商店。在美国的所有世代中,千禧一代对今天的零售空间持最积极的看法,57%的人说他们觉得商店更有吸引力。40%的 X 世代同意。此外,更令人惊讶的是,56%的千禧一代欢迎更多的个人店内互动,而老一辈人则觉得这很烦人。(来源)

但是等等,还有这个:

商场空无一人。2018 年是美国购物中心空置率最高的一年。各地的传统实体店都在关门。

年轻的购物者对流动性有很高的期望。越年轻的客户越不了解渠道,这意味着他们不在乎通过哪种方式从你这里购买。他们希望在线和线下、信使、电子邮件、网站聊天机器人和店内对话之间实现无缝转换。

电子商务正在扼杀当地企业及其商店。亚马逊杀了当地的书店,成千上万。现在,他们瞄准了你的杂货,并将淘汰较小的杂货连锁店。中国的同行也会如此。

Photo by Markus Spiske on Unsplash

显然,我们不会很快看到实体店或购物中心的终结,但我们需要明白,我们正在目睹完全不同的购物期望的出现。这种转变要求企业思考,面对习惯于提高便利水*的人工智能客户,这意味着什么。

大约 20 年前,亚马逊的杰夫·贝索斯对实体店做了一个预测,在他看来,只有当实体店提供即时便利或某种形式的娱乐价值时,实体店才能生存。事实证明他是正确的。顾客关心的是位置、速度、产品的多样性以及在它们之间选择的认知便利性。因此,毫不奇怪,特别是杂货店已经把消除结账过程或至少使其更快作为目标。

未来的商店永远不会看到人们排队。

在旧金山,亚马逊最*开设了几家名为 Amazon Go 的小型杂货店。在这些商店里,当你走进去的时候,用你的智能手机扫一个码。接下来,你抓起所有你想要和需要的东西,放进包里,然后走出来。没有更多的支付过程,因为你被数百个传感器和摄像头跟踪,当你走出去的时候,这些传感器和摄像头会自动为你的亚马逊账户充电。我亲自试过几次,可以确认是绝对无摩擦的体验。当然,亚马逊不是唯一一家试图取消支付处理的零售商。尤其是中国遥遥领先。在那里,你可以用你的脸、你的短信服务或你的阿里巴巴账户付款。

未来的商店永远不会缺货。

大胆的声明,我知道。但是,鉴于商店收集的数据质量不断提高,以及现在有无穷无尽的机会来观察、补充和预测产品需求,商店几乎不可能(或至少不太可能)用完某种产品。为了实现这一点,已经有几种技术问世。我们刚刚谈到的一个是天花板上堆放着摄像机和传感器,以便随时观察一切。沃尔玛正在他们所谓的沃尔玛智能零售实验室进行测试。正如预期的那样,摄像头检测产品及其可用性,从而实时提高补货过程的效率,但真正有趣的是这一应用的结果。这一过程取代的不是销售助理,而是经理。他的任务完全由算法接管,但机器人补货仍然太复杂,甚至无法与地板上的客户交谈。

未来商店的首要目标不是卖东西。

虽然直到今天,商店仍在衡量他们是否、多久以及在不久的将来让顾客购买多少产品,但这一成功指标将不得不转向更复杂的衡量方法。零售空间的目的将不再是展示和销售,而是让顾客体验和谈论。如果你看看线上到线下的品牌和他们的展厅概念,你会发现,他们不仅不鼓励你在商店里买东西,他们实际上并不关心你是在线上还是线下购买。在许多情况下,在商店购买的过程与网上购买非常相似,因为销售代表使用相同的界面来获得想要的产品。通常,他们还会要求您提供电子邮件地址或电话号码,以便识别和跟踪您。

这让我们想到了未来十年零售业最重要的转变:

商店将充满技术,使识别、跟踪、监控、测试和观察顾客成为可能。这方面已经到位的例子有沃尔玛的智能零售实验室,或者前面提到的亚马逊 Go。此外,有趣的案例如 b8ta 或 Target Open House 都旨在观察潜在客户与新产品的互动,并了解他们的问题和障碍。

沃尔玛还获得了一项心率监测器的专利,这种监测器被嵌入顾客推过商店的购物车中。这项技术能够区分紧张的顾客和兴奋的顾客,并告知商店服务员应该和谁交谈以及如何交谈。(来源)

沃尔格林和其他一些公司用屏幕取代了商店冰箱的玻璃门,屏幕上还有摄像头,可以跟踪顾客的虹膜运动,提供顾客的兴趣、偏好和年龄等信息。(来源)

所有这些都只有一个目的:为购物者提供最顺畅、最个性化和最真实的体验。我们谈了很多关于摩擦和效率,摆脱支付过程等等。现在让我们看看其他组件:

只适合我:个性化、完全定制、个性化的体验

电子商务从一开始就一直在分析客户在网上留下的数据踪迹。我们现在看到越来越多的尝试以类似的方式跟踪商店和零售空间中的客户数据。从无处不在的摄像头和传感器到心率监视器、虹膜跟踪和增强现实功能。我们看到有人试图通过客户的联系信息来识别他们,以建立关于他们长期购物习惯以及个人偏好的数据库,从而在他们走进商店时为他们提供定制体验。今天,当我们走过购物中心时,我们看到的商业广告和广告大多是普通的,是为了迎合大量的观众。在不久的将来,我们将会看到广告和横幅广告根据站在他们面前的人的个人喜好进行调整。

第一批数字价格标签正在实施,并允许定制产品信息。想象一下,在你当地的杂货店拿起一块鸡肉,它下面的屏幕开始向你显示鸡肉来自哪里、谁饲养它以及它如何生活的确切信息。对于你旁边拿起同样鸡肉的人来说,显示屏可能会显示最好的低碳水化合物鸡肉食谱。他们怎么知道你想看什么?第一,你购物篮或购物车里的其他产品比你想象的透露了更多关于你的细节。如果你所有的其他产品都是本地养殖的有机产品,你可能会关心你的鸡肉来自哪里。如果你的购物车里有蛋白质棒和一本健身杂志,你更有可能想了解健康食谱。第二,如果一家商店设法用面部识别软件识别你,它就有可能调出你购买过的所有购物车和购物篮。根据你的历史来个性化你的购物体验的机会是无穷无尽的。

因为预测是可能的,所以它将被部署。因为它将无处不在,客户将习惯于被预测。他们将习惯于别人问候他们的名字,他们将期望被记住,他们将要求所呈现给他们的东西具有高度的相关性。

帮助我成长:真实、教育品牌宗旨

你卖的只是开始。在大多数产品品牌中,有难以置信的有价值的未使用的知识。杂货店将成为健康顾问。购物中心将成为娱乐、教育、医疗和个人成长的中心。每个参与体验的个人都将提供一个高度策划的、知识增长的、个人的体验,这是网上无法提供的。

品牌需要问自己,他们服务的最终目的是什么。如果你制作太阳镜,你是想帮助人们看起来更时髦吗?如果是这样,你的品牌不仅仅是太阳镜业务,你也是咨询和发现业务,这就是人们来找你的原因。他们不想买眼镜,他们想看起来很帅。如果你从事空气净化器行业,人们来找你是因为他们担心自己呼吸的空气。那么你是在医疗保健、健身、生活方式或清洁行业。免费的瑜伽课从来没有伤害过任何生意。无论哪种方式,客户都希望向你学习,他们重视你的建议,信任你的专业知识。在美国,49%的千禧一代希望在零售场所看到研讨会和专家讲座。

让我分享一下:社交媒体就绪,值得 Instagram 的空间和设计

伟大的经历值得分享。像 Platform LA T1 这样的新购物中心概念为人们提供了视觉上准备好的空间,通过在不同的社交媒体渠道上分享他们的体验来策划他们的体验。如果购物中心没有 Instagram 帖子,可能是因为它没有提供可分享的体验。如果它不提供这种体验,那么它将无法生存。因此,可治愈性将成为购物中心或商店成功的一个非常重要的指标。虽然今天只有 12%的消费者认为在社交媒体上接触品牌对他们如何感受或思考该品牌有任何意义,但现实是,随着对品牌的影响力来源变得民主化,在线分享体验将变得更加重要。品牌从未完全掌控过自己的品牌形象,但今天和明天,消费者将会把品牌声誉掌握在自己手中。影响者将更加有机地成长,并要求品牌更加真实。

商店和购物中心哪儿也不会去,但它们会戏剧性地改变面貌。实体零售没有死亡,它正在重生。有了数据和人工智能支持的、高度个性化的、方便的、有教育意义的、值得分享的店内体验,实体零售空间将为客户已经在网上期待的东西增加难以置信的价值。

阅读更多 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

  • 【https://www.atkearney.com/retail/article? /a/购物中心的未来-文章
  • https://www . chain storage . com/technology/study-young-customers-show-shopping-in-store-shopping-preferences/
  • https://www . the verge . com/2019/4/25/18516004/亚马逊-仓库-履行-中心-生产力-解雇-终止
  • https://info . retailspacesevent . com/blog/10-crazy-technologies-about-transform-physical-retail
  • https://www . fast company . com/40437912/inside-the-l-a-mall-that-defying-the-retail-启示录

来自市政分析世界的故事

原文:https://towardsdatascience.com/stories-from-the-world-of-municipal-analytics-d3dc97077682?source=collection_archive---------14-----------------------

我们的城市变得越来越智能

随着地方政府开始认真对待大数据,将其作为一种更好地了解公民、提高项目和政策的有效性以及节省资金的手段,分析领域在美国各城市继续获得发展势头。采用分析实践的城市比以往任何时候都多,这增加了对分析专业人员的需求,以监督这些新技术在当地的采用、部署和评估。在成功实现的项目中,许多都经历了多次失败和迭代,以实现与改善治理相关的目标。随着机器学习和人工智能等复杂技术的出现,人们需要理解更复杂的假设和偏见,这些假设和偏见可能会违背为舒适人群和弱势人群服务的目标。

可以在分析的帮助下解决的公民问题可能会通过内部资助的问题来源工作到达当权者的办公桌,但在参与式社区的情况下,需要优先考虑的问题通常会自己出现。为了与分析专业人员一起解决公民问题,似乎不仅必须存在对分析应用的明确需求,而且更重要的是,必须获得拥有决策权的利益相关方的认可,从人才和技术角度获得适当的资源,以及成熟、经过审查的数据。公共部门的创新努力往往会遇到官僚主义和低风险容忍度,这就是为什么较小规模的分析项目试点迭代在展示初始价值方面具有重要地位。尽管该领域存在固有的障碍,但我对市政分析和数据科学的潜力感到非常兴奋。事实上,我们在全国已经看到了许多成功的例子。为了激发您对这一不断发展的领域的兴趣,并希望您能够参与并了解您所在的市政当局在大数据应用于政策方面的进展,我将总结一些我最喜欢的成功故事,让您了解哪些事情已经成为可能,这是由成功实施公民分析的领先国家资源激发的。

烟雾探测器+纽奥良

Source: NOLA Office of Performance and Accountability

新奥尔良消防局认识到,当一个家庭安装了烟雾报警器时,因火灾死亡的风险会减少一半,因此决定向有需要的居民免费发放救生烟雾报警器。该市通过其绩效和责任办公室建立了数据能力,该办公室建立了一个数据团队,并决定利用预测分析模型来确定房屋的属性,这将有助于该小组了解每个物业对新烟雾报警器的需求及其整体火灾死亡风险属性。该办公室尚未收集到此类数据,但当一名研究人员在美国人口普查局的美国住房调查中发现一个关于烟雾报警器的问题,并将其与该局的美国社区调查数据相结合时,该项目得以启动。该小组能够确定有助于预测新警报和高度易受影响房屋需求的关键特征。他们能够利用这一点来达成一个逐块烟雾探测器推广和分配计划。两年后,8000 个新的、针对风险的烟雾报警器问世,该部门得以庆祝这一出色的工作,肯定了分析的力量,并激励美国红十字会和 DataKind 在全国复制他们的项目。

参见 预测火灾风险:从新奥尔良到全国范围的工具 (哈佛大学灰中心)

早期警方介入+纳什维尔/夏洛特

芝加哥大学数据科学和公共政策中心开发的早期警察干预系统使警察部门能够识别那些可能发生不良事件的人,以便为他们提供培训、咨询和类似资源。该小组跟踪“不利事件”,这些事件可能以公民或同事投诉、使用武力、事故或伤害的形式出现。该系统用于在部门数据中查找不良事件的预测因素。这包括跟踪警官行为的各种实例,这些实例可能揭示警官的潜在倾向,可能对不良事件的发生有影响,也可能没有影响。系统还学习管理者如何对系统的发现进行优先化或去优先化。传统系统揭示了一个可行性问题,因为它们可能通过标记整个警察队伍中几乎 70%的人来捕获 80%的有不良事件的警察。鉴于许多警察部门的资源已经非常有限,建议一个部门持续地重新培训 70%的警力并不是非常有用。在 UChicago 设计的新系统仍然标记了 80%的警力,但能够锁定 30%最需要干预的警力,并根据历史表现给每个警官一个综合风险评分。像这样的系统显然不是为了取代警察主管做出判断的责任,而是可以帮助通知它,实施的长期影响仍在测量中。

参见“ 警察项目更新:扩大和实施早期干预系统”(UChicago 的数据科学和公共政策中心)

房东歧视+纽约市

纽约市禁止基于种族、性别和收入来源歧视潜在租户……理论上。尽管有《纽约市行政法》第 8 条,基于收入的歧视仍然是报道最多的住房相关问题之一。纽约市长数据分析办公室和人权委员会决定建立一个模型,通过确定房主最有可能非法拒绝潜在租户购买住房券的地区,更有效地部署调查资源。研究人员假设,针对犯有此类行为的大型物业管理公司将产生涓滴效应,鼓励较小的潜在违法者遵守法律。通过确定较大的违规者,该模型更有效地揭露了非法住房做法,使人权委员会能够更好地确定其工作流程的优先次序,并提高纽约市遏制住房歧视的能力。

见项目“ ”。纽约市人权委员会与 MODA 合作,协助确定潜在收入歧视的地点”(MODA 纽约市 GitHub)

城市破坏+新奥尔良

新奥尔良在 2005 年遭受卡特里娜飓风破坏的许多地区在飓风过后的许多年里都没有受到这座城市的影响,当市长米奇·兰德鲁(Mitch Landrieu)在 2010 年上任时,决定对城市周围的财产采取改造或拆除行动以弥补损失是一个关键的讨论话题。该市的数据中心 OPA 的任务是开发一种使用分析的性能管理工具来帮助解决这一问题。他们开发了 BlightSTAT 和 Blight Scorecard,以应对积压的 1500 处房产,这些房产正等待住房法规执行机构做出决定,要么出售房屋,要么继续拆迁。开发的系统允许中级主管外出并对物业进行评分,提高了评估过程的速度和一致性。在这种情况下,像许多情况一样,人类的判断是公民分析过程中不可替代的因素。拆除建筑物的决定是由先进的数据系统告知的,而不是被其取代。这一过程中的书面交流基本上被法规执行部门的技术消除了。反过来,等待裁决的积压财产也基本上消除了。

参见 代码强制消减工具 (新奥尔良市)

参见“ 利用时空数据对有枯萎风险的物业进行早期检测”(UChicago 的《社会公益数据科学》)

食品检查+芝加哥

Chicago Restaurants Failing to Pass Inspections: 2015–2016 (https://chicago.github.io/food-inspections-evaluation/)

尽管对食品制备、储存和服务有着严格的规定,但在一个城市中监控食品安全确实具有挑战性,但分析模型可以帮助城市官员有效地分配专业知识和财政资源来完成这项任务。芝加哥有 7300 多家餐馆、数千家杂货店和其他食品摊贩,它们共同负责这座城市的整体健康。也就是说,只有大约 35 名检查员负责 15,000 多家食品企业。该市决定在分析的同时提高检查绩效,而不是简单地雇佣更多的检查员。芝加哥创新与技术部与公共卫生部合作,预测一家餐馆未通过检查的风险。最终的模型使该市能够比人工过程提前 7 天发现违规行为,并且在研究过程中,该团队创建了一个透明的、社区可访问的食品检查跟踪器,并根据实时检查结果进行更新。

用食品检验预测更快出结果 (哈佛大学灰中心)

参见 食品检验 (芝加哥数据门户)

交通死亡人数+纽约市

随着城市人口的增加,新技术已经为居民如何穿越城市的革命让路,随着这种变化,城市必须调整其系统和法规,以确保公民的安全。丰富的交通数据和新的分析模型为城市提供了一种低成本的途径来评估和改善交通系统。作为通过数据分析解决交通问题和低效率的全球愿景零运动的一部分,纽约市在 2015 年与 DataKind 合作,评估所有新交通改善项目的风险和某些结果的可能性。旨在改善交通模式和减少延误的项目可能与提高安全性相关,也可能与安全性相权衡。在克服了有限有用数据的速度障碍后,该团队能够制作一个模型,绘制暴露地图,以更准确地判断特定街道设计的有效性。该模型使纽约市交通局能够预测特定地区特定时间的活跃汽车数量,以帮助优化交通模式和提高道路安全。

参见“ ”更好的数据能否让零交通死亡成为现实? (哈佛的灰烬中心)

其他被彭博慈善机构“有效城市”认可的前瞻性城市

A Bloomberg Philanthropies Map of Certified Cities

波士顿市市长马蒂·沃什在他的办公室里安装了一个类似芬威公园记分牌的 T2 大屏幕,汇集了一系列关键的城市绩效指标,如接听 311 电话的*均时间、救护车响应时间、犯罪统计数据以及与基准和目标进行比较的整体成功得分。堪萨斯市市长 Sly James实施了一项季度市民满意度调查来指导政策倡议,第一批由市民关注的问题积极推动的资助项目已经以债券的形式到位,用于资助毁坏建筑的拆除以及道路、桥梁和人行道的翻新。洛杉矶市长埃里克·加希提发布了清洁街道指数,该指数列出了需要清洁的街区,在发布该指数一年后,不清洁街道减少了 82%。路易斯维尔市市长格雷格·菲舍尔(Greg Fischer)推出了一个公民分析创新中心和合作空间,即 Louielab,以鼓励合作,并优先开放所有公共记录作为城市默认设置。圣地亚哥市长 Kevin Faulconer 帮助实现了一个名为 Get It Done 的应用程序,以方便市民报告城市公害,并向市民报告公害修复后的照片。市长穆里尔·布瑟发起了一个名为DC 实验室的内部数据科学研究团队,致力于将科学思维应用到城市的日常运作中,他们因发布一项具有里程碑意义的研究而闻名,该研究是关于佩戴在身上的摄像头在使用警力方面缺乏效力。

未来:智能城市需要智能政府

Click the interactive visualization above for sample solutions & results

只有通过不同类型的利益相关者之间的合作,所有人的最光明的未来才会到来,而参与的不同部门行为者既可以相互传授宝贵的经验,也可以相互学习新的知识。

智慧城市技术,无论源自哪个行业,都必须与健全的政策举措相结合。例如,基础设施投资,倾向于长期的、昂贵的项目生命周期,可以变得更加灵活,以应对不断变化的环境。将现有车道重新分配给行人和骑自行车的人,或者支持建立私人运营的通勤巴士服务,可能会更好地服务于一个拥挤的城市,而不是精心策划一个为期 10 年的地铁线路基础设施开发项目。否则,基于这种长期愿景的项目很容易出现可能会在项目中期发生变化的情况或问题,并且解决方案本身的大部分价值可能会随着时间的推移而丧失。

市政府不应该在私人部门行为者的筒仓中运作。公共部门有充分的理由希望拥有许多智能技术应用和程序,但绝对有理由允许私营部门投资和政府项目财务回报的空间。应该由城市来确定哪些领域退一步是有意义的,并为企业、大学、基金会和非营利组织发挥作用腾出空间。许多城市遵循的“总体规划”方法并没有像那些将自己定位为潜在公私合作伙伴关系的资源中心和生态系统中心的城市所部署的项目那样取得成本效益上的成功。

利用智能的数据驱动系统提高公民参与度也有很大的潜力。公民和政府官员之间真正的双向对话可以通过互动应用和社交媒体来维持。决策者可以向公众关注的实时信息流敞开心扉,并将这些见解作为新政策的基础。因此,新技术和分析工作需要透明,以促进社区参与和信任。更大比例的人口应该上网,以增加获取相关信息的机会,这样城市就可以了解人口统计中的小众和主流意见。更好的信息系统和沟通渠道也有可能激发更积极的社区参与,如志愿服务、指导和其他积极的社区活动。

总之,我认为要真正实现数据驱动的智能城市,需要关注两个领域。公共部门必须找到一种方式,通过独特、创造性的激励计划,与私营部门争夺技术人才。城市还必须优先考虑网络安全,以保护新系统免受精通技术的坏人带来的风险,特别是在供水和电网等关键系统的情况下。似乎从市政技术事业的第一天起,这两个领域都需要加以考虑,以便经受住时间的考验。尽管存在风险,但我对市政部门越来越多地采用数据驱动系统和新技术持乐观态度,并迫不及待地继续阅读不同政府机构如何决定抓住眼前的机遇。

感谢阅读,

亚历克斯

请随时提出您的想法和问题,或者在 LinkedIn GitHubMedium上跟随我的数据科学之旅!

将电影存储到 pi (π)中

原文:https://towardsdatascience.com/storing-a-movie-into-π-960ffcab4eed?source=collection_archive---------29-----------------------

用π做数据存档值得吗?

visual representation of φ, e and π as treemaps

多年来,关于 T2πT3,人们提出了许多比科学起源更浪漫的说法。所有这些都与无穷大有关,或者说,它的小数部分包含了所有其他从未设想过的数字序列。

这不是真的或者至少没人知道如何证明。即π的正规性的论证还不存在。

但是很多数学家相信π是一个正常数的事实,甚至不知道如何证明;那是因为目前所有的研究都指向这个方向。

因此,假设π是一个正常的数字,我们可以陈述如下:

  • 小数部分的数字是均匀分布的
  • 任何长度的数列都包含在π中。

这意味着我们可以在里面的某个地方找到我们的电话号码,或者,给定一个合适的编码,我们的名字或者这篇文章。

那么我们能在里面找到一部电影吗?是的,将电影和π编码成二进制字符串,我们最终可以在π中找到代表电影的比特序列。

好吧……但是如果π真的包含了世界上所有的电影、文章和任何产生的信息,我们能找到它们并记下它们在π中的位置吗?

再说一次,是的,我们可以!那么为什么我们现在不这样做呢?

压缩

在π内寻找一个比特序列,以便只存储它第一次出现的位置,这是一种压缩,因为我们希望通过只存储一个数字内的位置而不是整个序列来节省空间。

但是为了有效,序列(即另一个数)第一次出现的位置(即一个数)必须小于序列本身。否则,我们使用的空间会比需要的多。

让我们算一下

我们想知道的是给定序列 {X₀, ₂, …} 在π中的*均位置是多少,以及该位置是否小于序列的值(或者它*均占用的空间是否更小)。

这个信息可以用下面的定理来检索:

如果{X₀、X₁、X₂、…} 是一个独立同分布在集合 m 元素的 S 上的随机变量序列,则连续子序列【𝜏】**𝑆ⁿ**的期望首达时间由下式递归给出

其中𝜏 最长的固有 suffix,也是的前缀。**

例如,我们可以搜索序列“456456”,即 𝜏

正如我们所见,该序列可以用 6 位数字来描述,但它在π中的位置需要 7 位数字(1001000)。序列“456456”可以在位置 1023671≈e[t]≈2⋅456456中找到。因此,存储“456456”的位置需要比序列本身更多的空间。

还要考虑到所有的 𝜏 认为:

因此,子序列长度 n 呈指数增长。

结论

虽然在π内部“存储”一部电影是可能的,但假设是一个普通的数,在π内部寻找一个序列并存储其位置,无论从空间还是时间上都不方便。以统计方式保存位置比直接存储值需要更多的空间,并且这个空间量呈指数增长。

这显然不仅限于π,而是任何正常的数字。

用数据讲故事

原文:https://towardsdatascience.com/storytelling-with-data-40708c129f37?source=collection_archive---------22-----------------------

优秀的分析和可解释的洞察力的微妙艺术

Storytelling with Data isn’t as whimsical. It does, however, provide the correct mental model. (Source Pixabay)

你的故事是什么?

纵观全球,我们正在以指数级的速度生产和消费数据。这只是事实。随着 5g 网络的到来,我们应该能够从 4g LTE 的 300 Mbs 处理高达 10 Gbs 的数据。这意味着,与人类历史上的任何时候相比,我们有足够的带宽从各种互联设备和嵌入式系统发送和使用更多的事件数据和指标。然而,你要问自己 “你的数据告诉你什么”?

当你考虑数据优先/数据驱动并在各自行业取得成功的公司(想想谷歌、脸书、微软)与收集数据并最终希望用它来解决未来某个时间点的业务目标的公司——但这些公司收集数据只是为了未来消费;目标和心态有天壤之别。

如果您正在积极地生产、消费和使用组织内生成的数据,那么企业内通常会有丰富的伴随数据文化,以及直接的公司范围的要求,即从各个垂直行业或业务部门发出和存储可用的数据。或者,不使用他们生产的数据的公司不知道数据的结构是否会给公司带来直接的好处,这将阻碍该公司未来根据他们的数据做出明智决策的能力。(参见我的另一篇关于 防止数据湖深渊 的文章,了解更多关于数据卫生的细节)。

为成功准备数据

The Library is a good analogy for a Data Store or Data Warehouse. It is organized by category, broken down by author and you can lookup and find exactly what you are looking for no matter when the book was written. (Source: Pixabay)

维护数据词汇表

如果你考虑智慧生命是如何交流的,那么你就可以将其提炼为一个普通的词汇,将单词转化为意义。假设单词的含义是由它们的上下文环境决定的,那么用一组通用的词汇来表示封装在事件或指标中的数据,并在一个在可预见的将来易于理解和维护的结构中进行定义,是有意义的。

采取主动,比如试图为基于事件的基础设施构建开放模式的 CloudEvents 开放规范,或者试图统一组织将数据写入 ElasticSearch 的方式的 Elastic Common Schema ,甚至是更老的 HTML 微数据规范,它使一组公共的实体和关系能够存在于 HTML 的标记中。所有这些计划都有重叠和共同的目标,即创建支持统一数据词汇和结构的规范。

记录可以在您的公司或组织内重用的商定格式是非常宝贵的

无论您是使用这些规范中的任何一个,还是仅仅将它们作为如何对数据建模的备忘单,记录一个可以在您的公司或项目中重用的商定格式都是非常重要的。

共享库和通用格式有助于减轻计算如何对新数据建模的负担。这可以通过多种方式实现,但我是编译结构化数据(如谷歌的协议缓冲区)的大力支持者。协议缓冲区允许使用导入跨许多可组合类型重用数据结构。它们还可以编译成多种语言(Java/obj-c/JavaScript/Scala/etc ),因此通过导入一个库,相同的数据结构可以在整个组织中使用。这篇文章不是关于 protobuf 的,而是关于如何考虑数据建模的,所以我会回头再谈。

当考虑数据时

想象一下,在一家没有数据仓库、没有数据湖、甚至没有传统数据库的公司,对用户数据建模看似简单的用例。初创公司总是面临这种问题,如果你已经开始考虑解决这个问题,那么你可能已经开始考虑你的网飞或脸书用户了。不过,问问自己什么是一般用户,用户的概念是否在多个上下文中具有相同的含义,以及询问封装“用户数据”的确切内容是什么,这将有所帮助。

您希望这些数据解决哪些用例

我喜欢从逆向工作开始这个过程。您希望这些数据解决哪些用例。这个过程与产品经理(PM)经历大多数工程师现在非常熟悉的类似实践没有什么不同。你知道“作为该功能的用户,我想……”。人们可以从项目管理用户故事中得出许多推论,并将该过程用作处理数据的心智模型——因为它有助于将复杂的问题分解成简单的上下文想法。

Data primitives can be combined to create new structures from common components. (Source: Pixabay)

假设我们都在一家新的创业公司工作,专注于提供下一个伟大的本地农场新鲜到前面门廊的概念。现在我们有了上下文,给定的上下文是王道,我们现在可以开始在同一个页面上考虑用户和用户数据建模之旅。那么,我们应该能够讲述什么样的数据故事呢?

“从这些数据中,我希望能够了解基于地理区域的客户流失情况”

“从这些数据中,我希望能够了解农场新鲜食品供应商如何影响客户满意度”

“从这些数据中,我想了解一年中什么时候对某种农产品的需求较高,这种农产品是什么,以及我们如何从当地供应商(供应商)那里获得这些产品。”

分解东西。因为这很有趣!

如果我们从我们的数据将如何被使用的具体例子开始,那么以相反的顺序分解事物的过程将变得更容易,并且给数据建模者一个什么是必要的清晰的想法。

从上面给出的三个用例中,我们可以提炼出对一个用户(客户)、一个供应商(本例中为供应商/农场)、一个产品(农场新鲜食品箱),其中包含一个或多个项目(产品/货物)的集合,这些项目由一个时间表(交付间隔)控制,该时间表规定了一箱农场新鲜食品何时作为一次交付出现在某人的家门口

现在把这些关系想象成一个总体的数据故事:“我们服务的一个用户在一个给定的时间表收到我们的产品,并且每次交付中的项目包含来自当地供应商的季节性选择”。

这提醒我,我们需要将地理区域以及一些时间数据的概念归属于用户/供应商以及用户和供应商活动/这些数据可以直接封装在主记录(用户/供应商)以及事件中。事件可以是增加或减少交货时间表的频率,或者供应商宣布他们缺货。几乎可以为任何事情创建事件,并使您能够在系统中交叉关联用户和供应商的行为,以开始添加对事件数据层的更多洞察。

在构建用例时,我们还必须考虑用户的满意度,这可以通过与每个产品交付相关联的评级的概念来解决。这可以通过服务应用程序或网站的直接请求来获得,例如,当你走出 Lyft 或获得一些 Doordash 交付时,你会获得典型的“评价你的体验”。这里的积极好处是,您可以根据每个用户之前对其交付的满意度开始向他们学习。这为在所有这些数据的基础上构建新的学习模型打开了大门。假设您希望根据直接的客户反馈来跟踪各个地区的最佳和最差供应商,那么此指标可用于对表现最佳的供应商的合作费用进行折扣,也是抛弃表现不佳的供应商时使用的指标。

讲故事的人

分解复杂的想法并从文字中传递意义是任何一个伟大的讲故事者的责任。对于一个讲数据的人来说,这甚至更重要,因为他们的成功可以成就或毁灭一家公司,他们的想法和意义是由易于遵循的指标、明确定义的事件和对大量枯燥数据的深刻行为驱动的会计组成的!现在去为你自己实现它吧。

全局优化策略

原文:https://towardsdatascience.com/strategies-for-global-optimization-79fca001c8bb?source=collection_archive---------6-----------------------

一旦我们离开高中微积分,局部和全局优化通常是已知的,但有些被忽略了。快速回顾一下,看看这篇博客的封面图片。对于一个给定的函数,在空间上有多个点有倾角。每次下降都是最小的。但是,你可以看到只有一个点是最深的,称为全局最小值。所有其他点都是局部最小值。第一部分,我将回顾计算一个已知函数的全局值。然而,一旦我们离开高中数学的这个已知函数的领域,大多数优化问题只处理局部优化。即使这样,我也要说明原因。快速注意,还有很多其他的策略我没有在这篇博客中提到。然而,我希望它能让你有足够的兴趣去探索更多的选择。

已知函数

我们来复习一些基础的高中微积分。首先,看一下这个简单的一元函数:

f(x) = 1/4x⁴ + 1/3x³ — 3x² — 7

从图表中,我们可以看到全球最小值在-3 左右。然而,让我们尝试使用微积分,因为我们知道这个情节的功能。

我们看到 f(-3)=-22.75 ,f(x)的最小可能值。我们甚至可以超越 2D,进入多元微积分领域来解决这个问题。

未知函数

在处理数据科学的大部分时间里,我们无法访问函数来执行任何演算。通常,f(x)是一个系统,我们可以输入变量 x,并获得一些输出 y。一个可能的解决方案是执行随机梯度下降,我们迭代地沿着斜坡下降,直到我们达到最小值。

Stochastic Gradient Descent

现在让我们用 python 来实现这个问题,假设 f 是一个黑盒函数。

#Unknown Function
f = lambda x:(1/4*x**4)+(1/3*x**3)-(3*x**2)-7def next_step(x,f,step_size):y=f(x)#Left Pointx_left=x-step_sizey_left=f(x_left)diff_left=y_left-y#Right Pointx_right=x+step_sizey_right=f(x_right)diff_right=y_right-y#Comparisonif diff_right<diff_left:return x_right, y_right, diff_rightelse:return x_left, y_left, diff_leftdef gradient_descent(f,start,step_size=0.01,tol=0.1, debug=False):x=startdiff=9999999while abs(diff)>tol:x, y, diff=next_step(x,f,step_size)if debug:print("Current Point: (%.2f,%.2f), Change: %.2f"%(x,y,diff))print("Minimum Point: (%.2f,%.2f)"%(x,y))

现在我们有了函数,让我们试着从 x=4 开始搜索。

gradient_descent(f, start=4)#Minimum Point: (2.65,-9.54)

这给了我们 2.65 的最低分。现在,让我们对另一个起点 x=-4 做同样的尝试。

gradient_descent(f, start=-4)#Minimum Point: (-3.51,-20.43)

使用 x=-5,我们得到全局最小值-3.51。这是寻找全局和局部最小值变得棘手的时候。我们的最终结果取决于起点。

Stochastic Gradient Descent gives different minima based on starting point

由于它是一个未知函数,我们不知道:

  • 理想的起点
  • 理想的步长
  • 理想域(我们不能穿越无限大的 x 空间)

一个可能的解决方案是使用模拟退火,它给我们一个达到全局最小值的合理概率。

模拟退火

这个名字和灵感来自冶金中的退火,一种涉及加热和控制冷却材料以增加其晶体尺寸并减少其缺陷的技术。两者都是依赖于热力学自由能的物质属性。加热和冷却材料会影响温度和热力学自由能。退火的模拟可用于寻找具有大量变量的函数的全局最小值的*似。

在模拟退火算法中实现的这种缓慢冷却的概念被解释为随着解空间的探索,接受更差解的概率缓慢降低。接受更差的解是元启发式算法的一个基本属性,因为它允许对全局最优解进行更广泛的搜索。

一般来说,模拟退火算法工作如下:

  • x = x 0
  • 对于 k = 0 到 k max(不含):
    • T 每步递减
      -随机选取一个邻居, x_ new ←邻居(x)
      -IfP(E(x【T22)), E ( 【T25
  • 输出:最终状态 x

以下是我们特定函数的 Python 实现:

import numpy as np#Unknown Function
f = lambda x:(1/4*x**4)+(1/3*x**3)-(3*x**2)-7def acceptance_probability(E, E_new, T):return np.exp(-(E-E_new)/T)def random_neighbour(x):return x += np.random.uniform(-1,1)def simulated_annealing(f, steps):x = np.random.random()E = f(x)print("x=%.2f, fmin=%.2f"%(x, E))for k in range(steps):T = T*0.9x = random_neighbour(x)E_new = f(x)P = acceptance_probability(E, E_new, T)if P > np.random.random():E = E_newprint("x=%.4f, fmin=%.4f, Prob.=%.4f"%(x,E,P))return Esimulated_annealing(f,20)

运行该等式,我们得到以下输出:

x=0.62, fmin=-8.04
x=-0.3446, fmin=-7.3664, Prob.=0.4753
x=-0.8717, fmin=-9.3559, Prob.=11.6601
x=-0.8329, fmin=-9.1534, Prob.=0.7575
x=-1.6213, fmin=-14.5791, Prob.=3903.7178
x=-2.3907, fmin=-20.5342, Prob.=23982.6510
x=-1.8220, fmin=-20.5342, Prob.=0.0003
x=-1.1582, fmin=-20.5342, Prob.=0.0000
x=-0.2298, fmin=-20.5342, Prob.=0.0000
x=-0.8731, fmin=-20.5342, Prob.=0.0000
x=-1.8032, fmin=-20.5342, Prob.=0.0000
x=-2.1873, fmin=-20.5342, Prob.=0.0110
x=-1.8673, fmin=-20.5342, Prob.=0.0000
x=-2.7618, fmin=-22.3598, Prob.=1315.6210
x=-2.3266, fmin=-22.3598, Prob.=0.0001
x=-2.5017, fmin=-22.3598, Prob.=0.0036
x=-2.6164, fmin=-22.3598, Prob.=0.0466
x=-1.7016, fmin=-22.3598, Prob.=0.0000
x=-1.7248, fmin=-22.3598, Prob.=0.0000
x=-1.6569, fmin=-22.3598, Prob.=0.0000
x=-1.5051, fmin=-22.3598, Prob.=0.0000

如上所示,该值收敛到-22.75。虽然这种方法不能保证全局最优,但是如果我们不限制我们的领域,它是相当接*的。还要注意,尽管初始值非常接*局部最小值,但它仍然设法找到了全局最小值。

动态规划

这部分更多的是时间复杂性而不是准确性。动态编程主要是对普通递归的优化。每当我们看到递归解决方案重复调用相同的输入时,我们可以使用动态编程来优化它。其思想是简单地存储子问题的结果,这样我们就不必在以后需要时重新计算它们。这种简单的优化将时间复杂度从指数级降低到多项式级。例如,如果我们为斐波纳契数编写简单的递归解决方案,我们得到指数时间复杂度,如果我们通过存储子问题的解决方案来优化它,时间复杂度降低到线性。

让我们以斐波那契数列为例:

def f(n):if n <= 1:return nelse:return f(n-1)+f(n-2)

这个问题的复杂性在于 O(2^n).如果你问我,我会觉得非常复杂!然而,让我们更好地分析这个问题。

Fibonacci at n=6

如果你看一个 n=6 的递归树,有很多重复。只需计算 f(3)的值的个数。在动态编程中,我们将把值存储在内存中,如果再次调用,就不会重新计算。下面是斐波那契的动态编程版本:

store = {}
store[0] = 0
store[1] = 1def f(n):store[n] = f(n-1)+f(n-2)return store[n]

使用新方法,每一步的复杂度为 O(1)。这允许我们探索 n 的整个域,以找到具有最小时间复杂度的最优解。

模型调试的现实策略

原文:https://towardsdatascience.com/strategies-for-model-debugging-aa822f1097ce?source=collection_archive---------8-----------------------

测试和修复机器学习模型的系统方法

内容:

  1. 简介 1.1 关于信任和理解的快速说明
    1.2 例题和数据集
  2. 检测策略 2.1 敏感度分析
    2.2 残差分析
    2.3 基准模型
    2.4 针对 ML 攻击的安全审计
  3. 补救策略 3.1 数据扩充
    3.2 噪声注入和强正则化
    3.3 模型编辑
    3.4 模型断言
    3.5 不需要的社会学偏见补救
    3.6 模型管理和监控
    3.7 异常检测
  4. 进一步阅读和结论
  5. 参考文献

1.介绍

所以,你已经训练了一个机器学习(ML)模型。你做的一切都是对的:交叉验证、提前停止、网格搜索、单调性约束和正则化。它在过时的测试数据中是准确和稳定的,并且比它所取代的线性模型要好。您甚至为您的数据工程和信息技术(IT)伙伴将您的模型包装在 Docker 容器中,以及它的所有依赖项。部署时间到了?没那么快。目前 ML 模型训练和评估的最佳实践并没有告诉我们如何发现和修复所有可能在现实世界 ML 系统中发生的讨厌的事情。如果这些系统能像常规应用程序一样被测试和调试就好了…输入:模型调试。模型调试是一门新兴学科,致力于发现和修复 ML 系统中的问题。模型调试试图像测试代码一样测试 ML 模型(因为它们通常是代码),并探测复杂的 ML 响应函数和决策边界,以系统地检测和纠正 ML 系统中的准确性、公*性和安全性问题。

1.1 关于信任理解的快速说明

在 ML 中,信任和理解是相似但不相同的。解开这种差异有助于我思考模型调试以及它与 ML 工作流的其他部分的关系。如图 1 所示,现在有很多工具可以用来促进人们对 ML 的信任和理解。一些技术,如模型调试和社会偏见测试和补救,帮助我们使 ML 更加准确、公*和安全,而无需告诉我们模型是如何工作的。这些帮助我们信任一个模型,而不是帮助我们理解它。其他技术,如可解释的 ML 模型和事后解释,通过揭示模型机制或总结模型决策来直接增加我们的理解。当我们喜欢模型或解释时,这些技术只会增加信任。

Figure 1: Many tools exist today to increase trust and understanding of ML systems. Some promote trust directly, while others promote understanding directly. Figure courtesy of Patrick Hall and H2O.ai.

这篇文章将集中在调试 ML 和促进 ML 信任的许多方面。然而,考虑负责任的 ML 工作流程的这两个额外方面是至关重要的:

  • 促进对 ML 的理解
  • 测试和强化支持 ML 模型的 IT 系统

即使您重视信任,特别是准确性,而不是公*性、可解释性或安全性,也需要使 ML 系统可理解,以实现逻辑上诉或操作员推翻错误的 ML 决策。很难反驳黑箱。[1]你不会喜欢你的孩子被一个精确但不可思议的 ML 系统拒之门外。你也不会喜欢被同样的黑箱系统拒绝医疗保健。你希望有机会对影响你生活的错误的 ML 决策提出上诉,这就是为什么商业或生活关键的 ML 系统总是可以理解的。图 2 提出了一个工作流程,包括在 ML 系统中增加信任和理解的步骤。当与图 2 中提出的其他技术一起使用时,模型调试可能工作得最好。

你们中的许多人可能比我更了解向消费者展示 ML 模型的测试和强化系统。那种工作还是有必要的,我就不多说了。仅仅因为一个系统包含一个 ML 模型并不能免除它的测试。此外,谷歌(可能还有其他公司)已经在这个问题上提出了一些可行的想法和框架。[2]

Figure 2: A ML workflow that can enhance trust and understanding. Figure courtesy of Patrick Hall and H2O.ai.

现在,让我们进入如何调试 ML 模型的内部。首先,我们将讨论本帖中使用的示例问题和数据集,然后讨论如何检测 bug,最后讨论如何消除 bug。

1.2 例题和数据集

下面的一些例子基于来自加州大学欧文分校(UCI) ML 知识库的著名的台湾信用卡数据集。[3]在这个数据集中,我们试图预测某人是否会在下一次信用卡付款时付款,DEFAULT_NEXT_MONTH = 0,或 DEFAULT,DEFAULT_NEXT_MONTH = 1。关于支付的变量用于产生违约概率,或 p_DEFAULT_NEXT_MONTH。我将使用我最喜欢的模型之一,一个可解释的单调约束梯度推进机(M-GBM)来进行这些预测。在 M-GBM 中,当某个输入变量增加时,p_DEFAULT_NEXT_MONTH 必须只增加,或者只减少。这使得解释和调试模型变得非常非常容易,并且不会真正影响该数据集模型的整体准确性。M-GBM 接受支付变量的训练,包括 PAY _ 0-PAY _ 6,或客户最*至前六个月的还款状态(较高的值是延迟付款),PAY _ am t1-PAY _ AMT 6,或客户最*至前六个月的付款金额,以及 BILL _ am t1-BILL _ AMT 6,或客户最*至前六个月的账单金额。所有货币价值均以台币(新台币)为单位。

一些示例结果还包含变量 LIMIT_BAL 和 r_DEFAULT_NEXT_MONTH。LIMIT_BAL 是客户的信用限额。r_DEFAULT_NEXT_MONTH 是一个 logloss 残差值,或者是 M-GBM 预测 p_DEFAULT_NEXT_MONTH 与已知正确答案 DEFAULT_NEXT_MONTH 之间差距的数值度量。我还将使用数据集中的人口统计变量,如性别,来测试不想要的社会学偏见。在很大程度上,这篇文章将示例信用贷款问题视为一般的预测建模练习,而不考虑适用的法规。(当然,违规处罚可能会使模型调试更具商业吸引力。)

2.检测策略

我们如何发现 ML 模型中的数学 bug?我至少能想到四种主要方式:敏感性分析、残差分析、基准模型、ML 安全审计。你大概也能想到别人。

2.1 敏感性(“假设”)分析

敏感性分析,有时称为“假设”分析,是一个简单而强大的想法。只需模拟代表有趣场景的数据,然后查看您的模型在这些场景中做出何种预测。因为几乎不可能知道一个非线性 ML 模型将如何对它在训练期间没有看到的数据作出反应,所以对我们所有重要的 ML 模型进行敏感性分析是非常重要的。[4]你可能对测试什么样的场景有一些想法。如果是这样,那太好了,就这么做吧。也许你也想玩你的模型?也很棒。对于这些情况,一定要检查一下假设工具,它为某些类型的 ML 模型提供了交互式沙盒体验。

这也有助于采用更结构化的方法进行敏感性分析。本小节将介绍结构化敏感性分析的三种策略:

  • 部分相关、个体条件期望(ICE)和累积局部效应图(ALE)
  • 对抗性示例搜索
  • 随机攻击

在我们开始之前,最好知道哪些变量对你的模型最重要。我总是首先将我的测试工作集中在那些变量上。图 3 是使用 XGBoost 通过 Shapley 值计算的精确一致的变量重要性图。[5] (Shapley 变量重要性测量在 H2O 和 LightGBM 中也是本地可用的。)图 3 向我们展示了 PAY_0 非常重要,而且可能太重要了,我们将在后面看到。

Figure 3: An accurate and consistent variable importance chart for the M-GBM model and the credit card dataset. Figure courtesy of Patrick Hall and H2O.ai.

2.1.1 部分依赖、ICE 和 ALE

部分相关将感兴趣的数据集中的感兴趣的列(例如 PAY_0)的所有值(例如验证数据集中的值)设置为感兴趣的值(例如 missing 或 NaN)或任何其他合理的值。这个新数据集通过训练好的模型运行,为每一行创建一个预测。取所有这些预测的*均值就是该变量、该数据集、该值和该模型的估计部分相关性。现在,我们对我们感兴趣的几个不同的值重复这个过程,以创建一个部分依赖曲线来绘制。在图 4 中,该图向我们展示了 M-GBM 模型中 PAY_0 的大致*均行为。

尽管这很容易理解,但是部分依赖并不完美。众所周知,当数据集中存在强烈的交互或相关性时,会显示不可信的结果。我们至少有两种选择来改善部分依赖,麦芽酒和冰块。听起来很有趣,对吧?ALE 几乎是部分依赖的直接替代。计算起来更有效率,通常也更准确。ALE 有 R 包,比如: ALEPlot 、 DALEX 和 iml 。

冰经常和部分依赖一起使用。ICE 是与部分依赖非常相似的计算。除了感兴趣的数据集只有一行之外,遵循与上述相同的步骤。我们通常计算数据集中许多不同行的 ICE 曲线。当代表许多不同的真实或模拟个体的 ICE 曲线跟随由部分相关性代表的整体*均行为时,这是部分相关性足够准确的好迹象。当 ICE 曲线偏离部分相关性时,这可能表明模型中存在相互作用(可能是部分相关性的*均值)。简而言之,ICE 可以告诉我们在我们的模型下有趣的真实或模拟个体的行为,部分依赖是否值得信任,以及我们是否应该在我们的模型中寻找任何强相互作用。部分依赖和 ICE 的组合和变体可以在几个开源包中获得,如 PDPbox 、 PyCEbox 、 ICEbox 和 pdp 。

图 4 结合了部分相关、ICE 和直方图,提供了关于 M-GBM 模型中最重要的变量 PAY_0 的更多信息。首先,我们可以看到,对于 PAY_0 > 1,训练数据非常稀疏。这通常是一个不好的迹象。ML 模型需要大量的数据来学习。这个模型几乎没有数据来了解最*一次还款逾期超过 1 个月的人。看看部分依赖,我们可以看到其他一些潜在的问题。该模型给出了缺失(即 NaN)数据的最低*均违约概率。这有商业意义吗?我不知道怎么做。此外,从安全角度来看,这有点可怕。如果我想从这个模型中得到一个好的分数,我可能只需要将一个带有缺失值 PAY_0 的对立示例放入 M-GBM 的生产评分队列中。此外,我们可以看到预测从 PAY_0 = 1 到 PAY_0 = 2 的巨大变化。从商业角度来看,这有意义吗?也许是这样,这很好,但从安全性和数据漂移的角度来看,这是另一件需要注意的事情。如果我想对这个模型的客户进行拒绝服务攻击,我只需要将他们的 PAY_0 值更改为大于 1。对于这个模型,我们可能希望让我们的 IT 伙伴知道监视涉及 PAY_0 = NaN 和 PAY_0 > 1 的对抗性示例攻击。此外,如果我们的市场向衰退条件转变,客户有更多的逾期账单,记住这个 M-GBM 对 PAY_0 > 1 的值有多敏感是很重要的。

Figure 4: Histogram, partial dependence, and ICE for PAY_0. Figure courtesy of Patrick Hall and H2O.ai.

另一方面,部分相关性和 ICE 曲线显示了*均和许多个体对 PAY_0 的单调性约束。单调约束幸运地帮助我们处理了数据稀疏问题。由于单调性约束,该模型从有一些训练数据的 PAY_0 = 2,一直到没有训练数据的 PAY_0 > 8,保持违约概率。如果没有约束,在 PAY_0 的这个域中的模型预测可能只是随机噪声。最后,因为 ICE 和部分相关几乎是一致的,我们可以看到 PAY_0、这个数据集和 M-GBM 模型的部分相关曲线可能是相当可信的。现在,你只需要对其余最重要的变量进行分析。为了简洁起见,我将转移到下一个敏感性分析调试策略,对抗性示例搜索。

2.1.2 对抗性示例搜索

对立的例子是使模型产生意外结果的数据行。寻找对立的例子是一种很好的调试技术。搜索过程使我们能够看到我们的模型在许多不同场景中的表现。发现和理解实际的对立例子可以指引我们找到使我们的模型更健壮的方法,并告诉我们当模型进入生产环境时要寻找的异常。如果你在 Python 深度学习领域工作,可以看看 cleverhans 和 foolbox 来寻找对立的例子。对于结构化数据,有更少的免费软件可以帮助我们,但是我有一个小的启发式搜索方法,你可以尝试或修改。图 5 显示了启发式搜索的结果。

Figure 5: Maximum predicted probability of default for adversarial example search across several important variables. Figure courtesy of Patrick Hall and H2O.ai.

对于 M-GBM 模型和数据,启发式搜索从 PAY_0 开始,像我在图 4 中做的那样计算 ICE,找到预测中摆动最大的 ICE 曲线。对于此数据集和模型,这是 p_DEFAULT_NEXT_MONTH 的第 90 个百分位数处的 ICE 曲线。然后,p_DEFAULT_NEXT_MONTH 的第 90 个百分位数的数据行被扰动 10,000 次,通过四个重要变量的十个不同值:PAY_0、PAY_3、PAY_AMT1 和 PAY_AMT2。(选择这些变量是因为它们的 Shapley 值范围很大,而不是直接来自图 3 中的变量重要性图。)然后,M-GBM 模型对 p_DEFAULT_NEXT_MONTH 的第 90 个百分位的 10,000 个受干扰的行实例的数据集进行重新存储,结果绘制在图 5 中。

图 5 向我们展示了 M-GBM 模型的一些有趣之处。首先,我们可以看到单调性约束甚至适用于几个变量的组合。其次,我们可能发现了 M-GBM 模型的一个逻辑缺陷。似乎无论某人最*或第二次最*的付款金额有多大,如果他们最*的付款逾期超过一个月,该模型都会产生很高的违约概率。这意味着 M-GBM 模型在不发布违约预测的情况下,可能无法考虑提前还款,或某人支付大笔款项以弥补逾期付款。如果我确实想在我的 M-GBM 模型或基于 M-GBM 模型的基于 ML 的信贷系统中考虑这些条件,我可以考虑编辑 M-GBM 模型或使用模型断言来使信贷系统能够处理这些更复杂的场景。(参见第 3.3 和 3.4 小节。)第三,这次调查确实发现了至少一个对立的例子。极低的 PAY_AMT1 和 PAY_AMT2 值,当与用于初始化搜索的行中的其他值组合时,将导致 M-GBM 模型生成高得惊人的违约概率。当 M-GBM 模型投入生产时,需要对这些值进行监控。他们可能会指出模型受到了恶意攻击。

如果你认为提出的对抗性搜索方法似乎有用,试试看。启发式搜索过程可以总结如下。

对于每个重要变量:

  1. 计算模型预测每十分位数的冰曲线。
  2. 找到预测中摆动最大的冰曲线。
  3. 隔离与此 ICE 曲线相关的数据行。
  4. 对于这一行数据:
  • 扰乱行中 1-3 个额外的重要变量。(很难绘制超过 1-3 个变量的结果。)
  • 重新对受干扰的行进行评分。
  • 继续 直到每个额外的重要变量循环通过其在训练数据中的域,并通过缺失或其他有趣的超范围值。

5.绘制并分析结果。

随机攻击

随机攻击是通过将模型暴露给各种随机数据来进行的。想想:双字节字符集,一行一列的数据集,一千万列一行的数据集等等。等等。等等。随机攻击可以发现传统的 IT 错误和数学错误。考虑一下,当暴露于一个有 1000 万列和 1 行的数据集时,您的 API 会表现失常,吐出一个包含太多私有或内部信息的 stacktrace。或者它只是以一种非常丑陋的、服务崩溃的方式失败了?也许您的 API 和模型将双字节字符视为缺失值,并且总是为包含它们的记录分配低违约概率?谁知道呢?不是你…如果你不测试这种东西。此外,如果你完全不知道从哪里开始你的模型调试工作,从随机攻击开始。我打赌你会发现一些非常有趣的东西。

2.2 残差分析

残差分析长期以来一直是线性模型诊断的基石,在 ML 时代仍然如此。残差指的是已知的真实结果和模型预测的结果之间的差异。计算残差的方法有很多,但通常较大的残差意味着模型是错误的,较小的残差意味着模型是正确的。残差图将您的所有输入数据和预测放入二维可视化中,有影响的异常值和其他类型的数学错误可以清晰可见。残差分析的唯一缺点是,为了计算残差,我们需要真实的结果。因此,如果我们在一段时间内无法获得真实结果的情况下进行预测,有时我们无法实时处理残差。(比如在抵押贷款中。)

图 6 显示了 M-GBM 模型的对数损失残差,由重要变量 PAY_0 的水*绘制。洋红色残差来自实际违约的客户。蓝色残差来自没有违约的客户。可悲的是,图 6 描绘了我的 M-GBM 模型的糟糕的一面。

Figure 6: Logloss residuals plotted by PAY_0. Figure courtesy of Patrick Hall and H2O.ai.

在图 6 中,我们可以看到,对于 PAY_0 < 1, i.e. NO CONSUMPTION (-2), PAID DULY (-1), or USE OF REVOLVING CREDIT (0), there are a lot of large magenta residuals. This means that the model basically fails to predict default when someone made their most recent payment. For PAY_0 > 1 的理想值,模型误差由大的蓝色残差驱动,这意味着当客户的 PAY_0 值不理想时,即延迟几个月,M-GBM 模型无法预测按时付款。将这些信息与图 3 中的可变重要性图结合起来,可以看出 M-GBM 病态地过度依赖于 PAY_0。我可能会部署一个业务规则:如果 PAY_0 > 1,那么 DEFAULT_NEXT_MONTH = 1,并且具有与 M-GBM 或几乎任何 GBM 相同的准确性。那样的话,我只会将一个脆弱的规则释放到野外,而不是成千上万个破碎的、潜在的有偏见的、可破解的规则。

我们可以尝试用数据扩充、强正则化、模型编辑或模型断言来修复这个危险的错误,所有这些都将在本文的补救部分讨论。但有一点是清楚的,这个模型是破碎的,不可信的,不适合在现实世界中使用。这个问题没有出现在 fit 统计、lift 或 AUC 图中,如果不看残差,我永远不会如此清楚地看到它。事实上,残差图向我们展示的看似健康的模型可能会令人震惊。[6]希望我已经让你相信绘制残差是一种高效的调试技术。用你喜欢的任何语言和一个像样的绘图库来做自己通常很容易,但是像 DALEX 、 themis-ml 和 auditor 这样的包提供了开箱即用的功能。

2.2.1 不同的影响、准确性和错误分析

不同影响(DI)大致指决策系统中的无意歧视。DI 测试方法是在训练数据和预测建模结果中发现某些类型的不想要的社会学偏见的众所周知的方法。他们完美吗?不。它们是你能做的最起码的事情来阻止你的 ML 模型延续或加剧不必要的社会学偏见吗?大概吧。还有几个开源包可以帮助您进行 DI 测试,包括 aequitas 、 AIF360 和 Themis 。基本的 DI 测试方法着眼于人口统计学变量的准确性和错误率。理想情况下,我们希望这些准确率和错误率在不同的人群中大致相等。如果不是,这强烈表明你的模型正在延续或加剧不必要的社会学偏见。在图 7 中,我们可以看到,就可变性别而言,男性和女性的准确率和错误率看起来相当相似。这是一个好现象,但这并不意味着我们的模型没有不必要的社会学偏见,即使是在性方面。

所有模型都有能力根据输入数据的微小变化来区别对待相似的人,这可能会导致局部偏差,或者缺乏个体公*性。地方偏见的一个例子是,对一个有良好还款记录且收入为新台币 100,000 元的年轻女性给予信贷延期,但对一个收入为新台币 99,999 元的非常相似的年轻女性拒绝信贷。我们知道新台币 1 元的收入差异不会产生真正的差异,但 ML 模型可以任意地将这两个相似的人置于非线性决策边界的不同侧。更糟糕的是,标准的 DI 测试通常无法发现局部偏差问题。我们如何在个人层面上确保公*?到今天为止,这仍然是一个多少有些开放的问题,许多恒星研究人员正在试图回答。[7]我能给出的一个实际建议是,仔细观察最接*你的模型的决策边界或概率截止点的个人。在大多数情况下,非常相似的个人不应该在该边界的不同侧。现在,在讨论作为一个通用的错误检测工具的不同的准确性和错误率之前,重要的是要说 ML 中的公*性远远超出了这里的小讨论。如果你想了解更多,请查看公*、问责和透明的 ML (FATML)会议和相关资源,并试用上面链接的一些软件包。[8]

Figure 7: Accuracy and different types of error for PAY_0 and SEX across levels of these categorical variables. Figure courtesy of Patrick Hall and H2O.ai.

传统的 DI 测试方法也可以应用于一般的分类变量,我发现这是一个很好的 bug 检测方法。图 7 显示了重要变量 PAY_0 在不同分类级别上的许多准确性和误差指标。在这里,我们可以看到 M-GBM 的性能与 PAY > 1 之间的巨大差异,这可能是由该领域中训练数据的稀疏性造成的。该表很好地展示了该领域中模型性能的脆弱性,以及 PAY > 1 时模型性能的差异。这种缺陷检测技术也可以应用于数值变量,只需对它们进行宁滨。

残差的解释

在过去的几年里,我们已经有了许多解释 ML 模型预测的技术。这些技术也可以用来改进我们的残差分析。可以创建局部可解释的模型不可知解释(LIMEs)、部分相关或残差的单个条件期望图。最*添加到 shap 包中的功能使得计算 Shapley 对残差的贡献成为可能,这意味着您可以准确地了解哪些变量在局部(如单行)和全局(如整个数据集)产生误差。解释残差的另一个好方法是拟合模型。图 8 是当 DEFAULT_NEXT_MONTH = 1 时适合 M-GBM 残差的决策树。图 8 显示了为什么 M-GBM 模型错过了未来违约的模型,这可能会导致现实世界中的冲销。

Figure 8: Decision tree model of residuals for DEFAULT_NEXT_MONTH = 1. Figure courtesy of Patrick Hall and H2O.ai.

对于 DEFAULT_NEXT_MONTH = 1 残差,图 8 中决策树的交叉验证 R *方为 0.89,*均绝对百分比误差约为 17%。所以这是相当准确的,这意味着在 M-GBM 的错误猜测中有很强的模式。此外,决策树可以帮助我们看到那些模式可能是什么。最大的残差出现在 PAY_0 < 0.5 和 PAY_AMT2

2.3 基准模型

基准模型是稳定的、可信的、透明的模型,通常类似于线性模型、单一决策树、简单的基于规则的模型,或者先前存在的和被很好理解的 ML 模型。检查您的新 ML 模型在过时的测试数据中的表现是否优于已知的基准测试,这总是一个好主意。如果你的新 ML 模型没有超越一个更传统或透明的模型,请不要使用它。

一旦你确定了你的 ML 模型至少比一个简单的或者预先存在的基准更准确,那么这个基准模型就可以成为一个可靠的调试工具。我使用基准模型来问这样的问题:我的 ML 模型错了谁,而我的基准模型对了谁?如果您可以隔离错误的 ML 模型行为,您可以考虑将基准模型预测与 ML 模型预测相结合,以便对这些情况做出更好的预测。此外,您还可以推理为什么透明模型对于某些数据子集表现更好,并开发潜在的补救策略。例如,当将行为不当的 ML 模型与线性模型进行比较时,ML 模型不准确的一个可能原因是过度强调 ML 模型中的非鲁棒交互。此外,基准模型可用于实时发现异常。在大多数低信噪比情况下,面向人的 ML 问题,简单模型和 ML 模型预测应该不会有太大差异。实时比较基准模型和 ML 模型预测可以帮助您捕捉一些正在发生的准确性、公*性或安全性异常。

2.4 针对洗钱攻击的安全审计

有几种针对 ML 模型的已知攻击可以导致改变的、有害的模型结果或者暴露敏感的训练数据。[9][10]图 9 概述了一些最著名的 ML 攻击。不幸的是,传统的模型评估方法并不能告诉我们模型是否安全。除了其他调试步骤,将一些或所有已知的 ML 攻击添加到您的组织已经进行的任何白帽黑客练习或红队审计中可能是谨慎的。

Figure 9: A cheat sheet that describes several different types of known attacks against ML. A full size version of this cheat sheet is available: https://github.com/jphall663/secure_ML_ideas. Figure courtesy of Patrick Hall and H2O.ai.

3.补救策略

现在我们已经讨论了一些系统的方法来发现基于 ML 的系统中的准确性、公*性和安全性问题,让我们考虑一些补救策略来修复任何检测到的问题。

3.1 数据扩充

如果您的模型调试暴露了定型数据中的稀疏位置或模型中与缺少数据相关的逻辑错误,则您可能需要获取更多数据。您可以模拟所需的数据,将其添加回您的训练数据中,重新训练您的模型,并重新测试您的模型。更有可能的是,您必须返回白板,重新思考您的培训数据是如何收集的,并等待更完整的数据可用。为了帮助避免将来出现这种问题,可以考虑实验设计技术。[11]在这里的例子中,收集关于债务收入比或就业状况的信息可能有助于在 M-GBM 模型中降低 PAY_0 的重要性。

数据扩充也可以是对 ML 模型中不必要的社会学偏见的补救策略。ML 中社会学偏见的一个主要来源是人口统计学不*衡的训练数据。如果你的模型将用于各种各样的人,最好确保你的训练数据也能代表各种各样的人。性别阴影线的研究既是一个警示故事,也是一个成功的故事,除了其他重要的事情,人口统计*衡的训练数据的必要性。[12]

3.2 噪声注入和强正则化

今天,我们大多数人在 ML 模型中使用 L1 和 L2 正则化。我们也许应该继续这样做。不幸的是,标准类型的正则化可能无法克服我们训练数据中强烈的病态偏差、相关性或依赖性。在讨论的例子中,PAY_0 就是这种情况。一个潜在的解决办法是启动 L1 和 L2 正则化。如果这种补救措施不够有力,你可以考虑其他措施,比如 L∞正则化、丢弃、权重裁剪或噪声注入技术。

采取如此极端的方式来修复你的训练数据也可能表明数据收集存在问题。如果一个变量驱动着你的整个模型,你可能至少遗漏了一个混杂的输入变量。在这种情况下,考虑将数据扩充作为另一种补救策略。

3.3 模型编辑

一些 ML 模型被设计成可解释的,所以你可以直接理解它们是如何工作的。其中一些模型,如决策树或 GA2M (又名可解释的助推机器,EBM)的变体,可以由人类用户直接编辑。如果您在 GA2M 模型的内部工作中发现了您不喜欢的东西,那么更改模型方程来去掉您不喜欢的东西并不困难。其他模型可能不像 GA2M 或决策树那样容易编辑,但是如果它们生成人类可读的评分代码,它们是可以编辑的。如果你的 M-GBM 评分代码中有很多错误的规则,也许你可以修复它们,也许你可以删除它们。当然,可以尝试 GA2M,但是也可以考虑为其他模型进行编辑,作为一种可行的错误修复策略。

关于模型编辑要考虑的一件事是,它可能会使您的模型在训练或验证数据中看起来更差。无论你的模型中有什么,因为它使训练和验证误差变得更好。所以,如果你编辑一个模型,你需要有坚实的理由来支持你的决定。

3.4 模型断言

模型断言,也称为预测后业务规则,是关于模型预测的断言语句,可以帮助纠正错误的或有问题的模型预测。[13]在我的例子中,我看到我的 M-GBM 模型不能说明在客户最*一次付款逾期超过一个月之后的预付或超额付款。在发布默认决定之前,明智的做法可能是检查客户上次付款是预付还是超额支付。生产中 M-GBM 模型的模型断言可以说:IF((PAY _ 0 > 1)AND(PAY _ am t1 > LIMIT _ BAL))那么 DEFAULT_NEXT_MONTH = 0

(一个滑稽的、来自头条新闻的模型断言可能更接*于:在将与怀孕相关的优惠券送到客户家中之前,检查以确保客户不是未成年人。[14])

3.5 不想要的社会学偏见补救

今天,有许多人和技术的方法来修正 ML 模型中不必要的社会学偏见。许多人为修正涉及促进数据科学团队观点和经验的多样性,并确保不同的知识分子参与模型构建的所有阶段。技术补救方法分为三个基本类别:

数据预处理:

  1. 明智的特征选择,例如使用存档时间作为输入变量,而不是破产标志。[15]
  2. 对训练数据中的行进行采样和重新加权,以尽量减少训练数据中不必要的社会学偏差,例如在 AIF360 中重新加权。

模特培训与选拔:

  1. 选择超参数和截止阈值时考虑公*性度量。
  2. 直接培训展会模特:
  • 在 AIF360 中学习公*陈述(LFR)和对抗性去偏见。
  • 使用考虑准确性和公*性度量的双目标函数。

预测后处理:训练后改变模型预测,如 AIF360 或 themis-ml 中的拒绝选项分类。

(当然,在 2019 年的 ML 模型中给出两段关于修正不想要的社会学偏见的主题*乎荒谬和冒犯。今天,有许多技术可以修正不必要的社会学偏见。了解更多关于他们的信息。今天真的没有借口部署种族主义模型,但它一直在发生,甚至在高风险的生命危急的情况下。[16])

3.6 模型管理和监控

知道你有多少模型,谁训练了他们,什么时候训练的。像记录其他软件资产一样记录它们。此外,监控重要的已部署 ML 模型输入和预测。注意相关的趋势和异常情况。不要只关注准确性。还要考虑公*和安全问题。

大多数数据科学家现在明白,模型通常是根据现实快照的数据进行训练的。随着时间的推移,现实会发生变化。新数据会偏离该快照,并且新数据的模型准确性会降低。这种模型漂移可能在模型输入和预测的统计趋势中很明显。这种漂移会影响模型的公*性吗?大概吧。因此,除了您今天可能要做的任何输入或预测监控之外,还要考虑对 DI 进行实时测试。

最后,当旧型号被拆卸下来进行更换时,旧型号应该退役,这意味着要小心保存,以备将来任何诊断、取证或诉讼需要。重要的模型不应该只是删除。

3.7 异常检测

异常的输入和预测总是令人担忧,并且可能预示着对手正在攻击您的模型。在示例 M-GBM 模型中,我们看到它对 PAY_0 的缺失值、PAY_0 的高值以及 PAY_AMT1 和 PAY_AMT3 的极低值特别敏感。在这种情况下,缺失和其他不合逻辑的值可能甚至不允许进入 M-GBM 的生产评分队列。对具有高值 PAY_0 或极低值 PAY_AMT1 和 PAY_AMT3 的新数据进行实时监控,可能会将这些客户转移到人工个案工作者或更透明的模型中进行处理。

要实时捕捉异常预测,请考虑传统的统计过程控制方法,将 ML 预测与稳定透明的基准模型预测进行比较,或者监控新数据如何流经您的模型。(后者有时被称为激活分析。)对于基准模型,将 ML 模型预测与基准模型预测进行比较。如果它们非常不同,在发布预测之前仔细看看,或者只对这些数据使用基准模型预测。对于激活分析,新数据通常不应该流过在模型训练期间不频繁激活的模型机制(例如,决策树节点或神经网络隐藏单元)。如果这种情况经常发生,最安全的做法可能是调查原因。

4.进一步阅读和总结

这篇文章介绍了 ML 模型的几种调试策略,主要集中在结构化数据和标准商业数据挖掘用例上。如果您感兴趣,可以深入研究用于在 GitHub 上创建我的示例的代码。[17]要了解 ML 研究社区中模型调试的情况,请查看学习表示国际会议(ICLR)调试机器学习模型研讨会会议录。[18]

虽然从业者和研究人员正在围绕模型调试展开讨论,但该学科可能仍处于起步阶段。从这里到哪里很大程度上取决于我们。每当 ML 被用于商业或生活关键决策时,我个人希望看到更多值得信赖的 ML 和模型调试。

5.参考

[1]参见: 当一台电脑把你关在监狱里

[2]如测试调试机器学习模型、、机器学习:技术债 的高息信用卡,或tensor flow 的模型分析工具

[3]参见:信用卡客户数据集的默认

[4]参见: 教我数据分析

[5]参见: 可解释性机器学习 ,第 5.9 节

[6]参见: 残(Sur)实在论

[7]例如, 公*通过认识 和相关的工作

[8] 机器学习中的公*、问责和透明

[9] 模型漏洞与安全建议

[10] 警告信号:机器学习时代的安全和隐私的未来

【11】机器学习中的受控实验

【12】IBM、微软、Face++ AI 服务对人脸性别的猜测有多准?

【模型断言】用于调试机器学习

[14] 塔吉特如何在她父亲之前发现一名少女怀孕了

[15] 负责任的数据科学:识别并修复有偏见的人工智能

【16】数百万黑人受医疗算法中的种族偏见影响

[17] 用 Python 进行可解释的机器学习

调试机器学习模型

生产机器学习模型的策略

原文:https://towardsdatascience.com/strategies-for-productionizing-our-machine-learning-models-53399a3199da?source=collection_archive---------22-----------------------

让我们的最佳模式更快见天日,帮助企业更好地做出决策

Photo by ian dooley on Unsplash

因此,您已经编写了您最好的机器学习代码,并且现在已经将模型调至最佳精度。

现在怎么办?

您将如何部署您的模型,以便业务能够真正利用该模型并做出更好的决策?

这是我上一篇讨论生产大数据 ETL 的文章的后续。在这篇文章中,我将讨论生产我们的机器学习模型的不同策略。

典型的培训工作流程

我们都熟悉机器学习,以及如何找到最佳模型。这是我们工作流程的样子-

Typical EDA and Training workflow

作为一名数据科学家,我们通常将数据分为训练和测试数据,并用训练数据训练模型,然后我们预测测试数据,并根据误差指标或准确性微调我们的模型。

在此活动结束时,我们将获得具有最佳准确度分数的最佳模型。

典型部署工作流

通常,一旦我们找到了最佳模型,我们会想把它保存在某个地方。保存模型很重要,因为我们在训练阶段经过大量努力和时间后实现了这一模型。我们希望重用该模型,并为新数据的预测阶段加载该模型。

这是典型部署工作流的样子——

Typical Prediction workflow

在这个工作流中,我们需要一些机制来加载我们保存的模型,并通过新到达的数据运行它。此阶段的输出是输入数据的预测数据/标签。

企业可能希望将这些数据保存在某个地方,或者根据实时预测数据采取一些措施。

部署策略

有各种策略来部署我们的机器学习模型。策略的选择完全取决于我们计划如何消耗输出预测的业务需求。

批量预测

这种预测策略通常在一天中的特定时间运行预测,或者以固定的时间间隔在一天中运行多次。当我们不需要等待实时决策并且可以按时间批量输入数据时,这种策略非常有用。

Batch Prediction strategy

主要步骤如下

  • 代码以固定的时间/间隔运行
  • 代码从保存的位置加载模型
  • 代码读取一批输入数据
  • 输入数据是我们想要预测的新的和未标记的数据
  • 输入数据可能包含分组在一起的多个用户/实体的数据
  • 代码对输入批次运行模型预测,并产生一个预测批次
  • 预测批次包含输入数据中每条记录的预测标签
  • 预测的数据然后被保存在一些新的位置

随着批预测管道继续运行,新的预测数据将继续追加到该位置。这些数据可用于分析和决策。

流式/实时预测

当必须立即做出决定时,这种策略非常有用。通常有一个应用程序需要根据用户的交互/行为/属性动态地做出一些决定。

Streaming / Realtime prediction strategy

主要步骤如下

  • 我们有一个包装代码的 web 服务
  • web 服务公开 Rest 端点以获取预测
  • 消费者应用程序进行 web 服务调用,并以 Json 格式发送输入数据
  • 输入数据包含预测所需的所有特征。它通常只有一条记录,而不是一批
  • 代码从保存的位置加载模型
  • 当调用 web 服务端点时,代码获取输入数据
  • 代码对输入数据运行模型预测,并产生预测数据
  • 预测数据被返回给消费者应用程序
  • 消费者应用程序可以决定如何使用预测数据来获得更好的用户体验

通过 SQL 进行即席预测

这是最*在业内流行的一种新趋势。这种方法将 ML 模型公开为 SQL 函数。这种方法将新的输入数据视为表格,并允许通过将 ML 模型作为函数运行来对数据进行特别分析。输出也以表格形式显示,如果需要,可以保存下来供将来使用。

Ad-hoc / SQL based prediction strategy

主要步骤如下

  • ML 模型被包装在 SQL UDF 中
  • 有一个理解 UDF 的 SQL 执行引擎(如 Spark 或 Google Big Table)
  • SQL 执行引擎在 UDF 中加载代码
  • 用户向执行引擎发出 SQL 查询,在 SQL 查询中选择特征表
  • 执行引擎通过 UDF 运行输入要素来计算预测
  • 预测数据被返回给用户
  • 用户可以将预测数据保存为新表

实施思路

业内有各种方法解决这个问题。

气流调度程序

气流调度程序非常适合批量预测策略。它可以将最大似然训练和最大似然预测作为独立的作业在不同的时间间隔运行。气流还提供了过去所有跑步的可视性。所有预测运行都可以记录预测详细信息,以供将来分析。

码头集装箱

这是 Kaggle 在比赛中采用的方法之一。我们可以为训练和预测工作旋转 Docker 容器。容器可用于批量和实时预测策略。

亚马逊 SageMaker

这是最流行的部署策略之一。最好的部分是它由亚马逊管理,我们不需要模型部署的基础设施。

我们可以在 Jupyter 笔记本中提供我们的 ML 代码。部署在 sagemaker 上的每个 ML 模型都有一个惟一的部署端点,可以用于预测。

这里有一个关于 SageMaker 入门的很棒的教程

Amazon Sage maker — Web Interface

谷歌大查询 ML

谷歌已经开始在 BigQuery 之上提供机器学习功能。它允许我们在现有的 BigQuery 表之上使用 ML 模型作为 SQL 函数。

这里有一个关于开始使用 BigQuery ML 的很棒的教程

Big Query ML — SQL predictions

毫升流量

ML flow 是 Databricks 的一项新举措。ML flow 是开源,并为用户提供模型跟踪和服务的能力。ML flow 对于培训生命周期来说也是很棒的,因为它提供了一个 web 界面来显示模型在多次运行中的性能和准确性。ML flow 还允许我们将多次运行作为单个实验的一部分进行分组。

ML Flow — Model tracking and serving

ML flow 的伟大之处在于,我们不必为保存和加载模型而编码。ML flow 为我们提供了 Python 库来加载和保存模型。

ML flow 的另一个优点是,一旦模型与 ML flow 一起保存,就可以通过上面提到的三种策略中的任何一种进行部署。

这里有一个关于开始使用 ML flow 的很棒的教程

这个帖子到此为止。在下一篇文章中,我计划写一篇关于 ML flow 或 SageMaker 的深度文章。敬请关注。

原载于 2019 年 3 月 4 日confusedcoders.com

分层抽样以及如何在 R

原文:https://towardsdatascience.com/stratified-sampling-and-how-to-perform-it-in-r-8b753efde1ef?source=collection_archive---------6-----------------------

对大型数据集进行采样的正确方法

Photo by Giorgio Tomassetti on Unsplash

在之前的一篇文章中,我写了关于以适当的方式从人群中选择样本的重要性。今天我将向大家展示一种叫做分层抽样的技术,它可以帮助我们从一个庞大的数据集中创建一个具有统计显著性的样本。

对大量人口进行抽样的正确方法

当我们从总体中执行一个样本时,我们想要实现的是一个更小的数据集,它保持总体的相同的统计信息

产生一个相当好的样本的最好方法是统一收集人口记录,但是这种工作方式并不是完美的。事实上,虽然*均来说效果很好,但单个样本与总体差异太大的概率仍然很低,有限。这种概率非常小,但它会在我们的样本中引入偏差,这将破坏我们在其上训练的任何机器学习模型的预测能力。

真正的要点是,我们不想要一个理论上正确的方法,这个方法适用于大数;我们想要提取一个正确的样本,并尽可能具有最高的统计显著性。

在这一点上,统一的抽样已经不够了,我们需要一个更强的方法。

分层抽样

分层抽样是为了从一个人口记录到另一个记录构建样本,尽可能忠实地保持原始多元直方图而创建的一种方法。

它是如何工作的?好吧,让我们从一个单一的,单变量直方图开始。对这种直方图进行采样的最佳方式是将 0–1 区间分割成子区间,子区间的宽度与直方图条的概率相同。然后,我们从 0 和 1 之间的均匀分布生成一个伪随机数。我们将根据随机数的位置从直方图中选择一个值。然后我们想重复多少次就重复多少次。

下图让一切都变得更加清晰。

这张图表是由以下代码制成的:

library(“ggplot2”)s = c(rep(“A”,50),rep(“B”,35),rep(“C”,15))d = as.data.frame(table(s))p = ggplot(d,aes(x=s,y=Freq,fill=s)) + geom_bar(stat=”identity”)+geom_text(aes(label=Freq),vjust=1.6) +theme(legend.position = “none”)p

如何在 R 中进行采样?强大的样本功能可以指定赋予每个值的权重,即概率。

因此,如果我们想要该数据的 10 个样本观察值,我们可以简单地使用这一行代码:

sample(d$s,replace = TRUE,prob = d$Freq,10)

通过这种方式,我们能够创建具有高置信度的直方图,迫使样本遵循相同的总体分布。

多元方法

多元直方图怎么样?嗯,多元直方图只是许多直方图的层次结构,通过条件概率贝叶斯公式粘合在一起。我们可以轻松地将多变量直方图转换为单变量直方图来标记每个聚类组合,但是如果我们有太多的列,那么在计算上很难将它们全部聚集起来。当我试图在 200 列上聚合 3000 万条记录的数据集时,我亲眼目睹了强大的 RDBMS 的失败。

通过下面的过程,我们可以独立地管理每一列,而不用关心它们的数量,也不会让我们的 CPU 遭受太多的痛苦。

程序如下:

  • 根据第一个变量聚集整个数据集(即根据第一个变量创建数据集的直方图)。
  • ****根据用于单变量直方图的相同技术,选择该变量的一个值。
  • ****过滤整个数据集,仅考虑那些在所选变量上具有该值的记录。
  • 继续处理第二个变量(聚合并选择一个值)等等,直到最后一个变量。由于过滤器的作用,每一步都会产生一个更小的数据集。
  • 最后,您有一个非常小的数据集,但没有变量留给切片。此时,您可以从该数据集中选择一个随机记录统一并重复整个过程,直到您得到想要的样本大小。

Stratified sampling procedure

连续值和分类值

会发生什么呢?有些变量是连续的,有些是分类的?嗯,问题现在变得非常困难。我能给你的唯一答案是用直方图标准(如斯特奇斯或赖斯的)离散化连续变量。

给定数据集中的 n 点,用于直方图的仓的数量 k 通过以下公式从两个规则中导出:

Sturges’ rule

Rice rule

让我们看看他们的行动。使用下面的代码,我们将从对数正态分布(本质上是偏斜的)中创建 10000 个随机数,绘制原始密度函数和由这两个规则生成的直方图。

x = rlnorm(10000,0,0.5)
windows()
layout(matrix(c(1,1,2,3), 2, 2, byrow = TRUE))plot(seq(0,3,length.out=1000),dlnorm(seq(0,3,length.out=1000),0,0.5),xlab="x",ylab="Density",main="Lognormal distribution with mean = 0 and sd = 0.5")hist(x,probability = TRUE,main="Sturges rule",xlim=c(0,3))hist(x,breaks=2*length(x)**(1/3),probability = TRUE,main="Rice rule",xlim=c(0,3))

如你所见,莱斯法则能够非常有效地再现原始概率分布形状。这就是为什么它是我个人最喜欢的直方图标准,我总是用它来离散数值变量。****

R 中的一个例子

现在是时候让所有的理论在 r 变成实践了。

首先,我们将模拟一些数据,确定维度和所需的样本大小:

**# Generate a random 10000 records data frame
set.seed(1)
n = 1000
d = data.frame(a = sample(c(1,NA),replace=TRUE,n),b = sample(c("a 1","b 2","c 3"),replace=TRUE,n),c = c(runif(n-100,0,1),rep(NA,100)),id = 1:n)# Remove the useless "id" column
dimensions = setdiff(names(d),"id")# Desired sample size
n_sample = 100**

然后,我们执行分层采样,目标是用样本填充生成的数据帧,而不重复。为了应用最后一条规则,我们将使用强大的 sqldf 库。

现在“生成”的数据帧包含了我们想要的样本。

结论

在本文中,我介绍了数据科学家应该知道的最重要的采样技术。记住:一个生成良好的样本真的可以在机器学习中发挥作用,因为它可以让我们用更少的数据工作,而不会失去统计意义。****

Gianluca Malato 是意大利的一名小说作家和数据科学家。他的书可以在 亚马逊 上找到,他的文章可以在 中型 上找到。

面向数据工程师的从 S3 存储桶到雪花数据库的数据流

原文:https://towardsdatascience.com/streaming-from-s3-buckets-to-snowflake-db-for-data-engineers-8e4827b81b16?source=collection_archive---------7-----------------------

如何使用 Snowpipe REST API 调用将文件加载到表中的工作示例。这是一个关于如何连接雪花以及如何使用 Snowpipe 将文件摄取到雪花表中的小教程。因此,为了向我们亲爱的读者提供本教程,我们在雪花开设了一个免费试用账户。本课包含三个步骤,第一步是将数据从您的计算机加载到内部阶段,第二步是将数据从 S3 存储桶手动加载到外部阶段,最后一步是使用 AWS Lambda 函数将数据加载到外部阶段。

我们为什么要这么做?为什么我们不把它从 S3 桶自动加载到雪花表呢?

这个过程背后的原因是为了更好地理解 S3 桶和雪花表如何和谐地一起工作。所以你可以用更少的工作,最少的努力享受更多的满足感。但是在我们开始玩雪花和 S3 之前,让我们检查一下需求。

要求

  1. 通过 AWS 帐户访问 S3 时段。
  2. 通过雪花帐户访问雪花控制台。
  3. 通过 AWS 帐户访问 EC2 实例。

第一步:从内部阶段加载数据

在本文档的这一部分中,您将在 Snowflake 中准备好创建表、阶段和管道的环境,通过遵循以下语句,您将能够实现这一点:

  • 在文件~/中定义与您的用户、帐户和密码的连接。snowsql/config,连接的名称是 zaid_connection
  • 在您终端和雪花工作表中运行这些命令
snowsql -c zaid_connection -o log_level=DEBUGalter user almalikz set RSA_PUBLIC_KEY="your_public_key"desc user almalikzcreate user zaid_user password='your_password';alter user zaid_user set rsa_public_key='your_public_key';use role securityadmin; create or replace role snowpipe_s3; grant usage on warehouse compute_wh to role snowpipe_s3; grant usage on database demo_db to role snowpipe_s3; grant usage on schema demo_db.public to role snowpipe_s3; grant insert, select on demo_db.public.TABLE_S3 to role snowpipe_s3; grant read on stage demo_db.public.STAGE_S3 to role snowpipe_s3; grant ownership on pipe demo_db.public.PIPE_S3 to role snowpipe_s3; grant role snowpipe_s3 to user zaid_user; alter user zaid_user set default_role = snowpipe_s3;create or replace table TABLE_S3(c1 number, c2 string); 
create or replace stage STAGE_S3; 
put file:///data/test_file.csv @STAGE_S3; 
create or replace pipe demo_db.public.PIPE_S3 as copy into TABLE_S3 from @STAGE_S3;

所以我们创建了这个程序simple _ ingest _ snow flake . py来访问雪花,使用用户、帐户、主机、端口、管道名、pem 格式的私钥,在下面的文件中检查这些参数:

ingest_manager = SimpleIngestManager(account='by16910',user='almalikz',private_key=private_key_pem, pipe=pipe_name,scheme='https',host='by16910.eu-west-1.snowflakecomputing.com',port=443)

在上面提到的 python 程序中,我们使用这些参数来构建 JWT。让我们从一个抽象的定义开始。

JSON Web 令牌(JWT)是一个 JSON 对象,它在RFC 7519中被定义为一种安全的方式来表示双方之间的一组信息。令牌由报头、有效载荷和签名组成。

米奇·斯泰基-埃凡蒂斯

在 Snowflake 中,jwt 的生成是预先构建到 Snowflake API 提供的 python 库中的(并且记录在 Snowflake 文档中),所以理想情况下,我们只需编写一个简单的脚本,使用这些库来为我们自动处理 jwt。通过包装器的 python 代码 简单-摄取-雪花

在我们运行程序几秒钟后,我们成功地将文件从内部暂存区摄取到雪花的表区,您可以检查接下来的日志,一切都很顺利。

*DEBUG:botocore.vendored.requests.packages.urllib3.connectionpool:"POST/v1/data/pipes/demo_db.public.PIPE_S3/insertFiles?requestId=b9f27491-6434-4c5f-93b6-c6831afae12d HTTP/1.1" 200 88 DEBUG:snowflake.ingest.simple_ingest_manager:Ingest response: {'requestId': 'b9f27491-6434-4c5f-93b6-c6831afae12d', 'responseCode': 'SUCCESS'}*

如果您检查上面的日志,您可以看到,首先是 POST 操作,其次是响应代码成功,这是积极的反馈。

*'pipe': 'DEMO_DB.PUBLIC.PIPE_S3', 'completeResult': True, 'nextBeginMark': '1_0', 'files': [ {'path': test_file.csv.gz', 'stageLocation': 'stages/b3767d50-e0f8-4bb2-a52a-6677122c8223/', 'fileSize': 64, 'timeReceived': '2019-05-14T13:48:30.725Z', 'lastInsertTime': '2019-05-14T13:49:00.579Z', 'rowsInserted': 4, 'rowsParsed': 4, 'errorsSeen': 0, 'errorLimit': 1, 'complete': True, 'status': 'LOADED'}*

然而,第二个日志是一个 GET 操作,由我们代码中的表达式调用,用于检查文件大小、接收时间、看到的错误、是否完成以及状态类型(在我们的例子中是 loaded)。

第二步:从 S3 外部阶段加载数据

在本节中,我们将讨论如何使用雪花和通知事件的自动摄取新功能来摄取数据,我们成功地将数据从 S3 存储桶传输到雪花表,但我们是手动完成的,为什么要手动呢?因为我们的免费帐户没有自动摄取激活选项,这就是为什么我们没有通知和自动摄取。我们通过执行以下任务来完成这一步:

第一项任务:设置你的 AWS 账户。

对于此任务,您必须遵循 AWS 安全的良好实践,并考虑以下规则:

  1. 删除 root 密码。
  2. 创建一个 IAM 用户。
  3. 创建一个新组。
  4. 定义新的 IAM 密码策略。

第二项任务:更改仓库以支持自动恢复模式

我们有两种类型的用户,一种是管理员用户 almalikz ,另一种是普通用户 zaid_user ,因此该任务只能使用管理员用户激活:

**alter warehouse compute_wh resume;**

第三个任务:将数据加载到雪花表中

在此任务中,我们使用普通用户帐户 zaid_user,而不是管理员用户。

**create or replace stage s3_stage**url= 's3://outputzaid/'**credentials = (AWS_KEY_ID = 'your_key' AWS_SECRET_KEY='your_secret');
create or replace table s3_table(c1 number, c2 string);
copy into s3_table**from s3://outputzaid/test_file_trusted.csv credentials=(AWS_KEY_ID = 'your_key' AWS_SECRET_KEY='your_secret')**file_format = (type = csv field_delimiter = ',' );**

第三步:使用 Lambda 函数从 S3 阶段加载数据

在这一节中,我们将引导您完成使用 AWS Lambda 函数自动化 Snowpipe 的过程。

AWS Lambda 是一个事件驱动的无服务器计算*台,由 Amazon 作为 Amazon Web Service 的一部分提供。它在被事件触发时运行,并执行已经加载到系统中的代码。您可以修改本主题中提供的示例 python 代码,并创建一个 Lambda 函数,该函数调用 Snowpipe REST API 从外部阶段 S3 加载数据。该功能部署到您的 AWS 帐户中,在那里托管它。您在 Lambda 中定义的事件(例如,当您的 S3 存储桶中的文件被更新时)调用 Lambda 函数并运行 python 代码。

本节描述了配置 Lambda 函数以使用 Snowpipe 连续地以微批处理方式自动加载数据的必要步骤。因此,让我们开始遵循以下步骤:

第一项任务:访问 AWS 实例

  1. 访问您的 EC2 微实例,并检查关于 your-ssh-key-name 的信息。
  2. 使用 AWS 控制台的 web 向导创建并运行 EC2 的实例。
  3. 下载 ssh-key。
  4. 使用 ssh 命令选项连接实例。
**ssh -i "zaid_key.pem" ubuntu@ec2-3-91-26-48.compute-1.amazonaws.com**

第二个任务:创建 Lambda 执行环境

为了完成本指南,您需要首先创建一个包含您的代码及其依赖项的部署包。一种简单的方法是获取一个 t2.micro 实例,并建立一个模拟 python Lambda 运行环境的执行环境。这是您必须在 EC2 微实例中执行的步骤,遵循以下命令:

**sudo apt-get install gcc make zip awscli libffi-dev openssl libssl-dev zlib1g-dev
wget* [*https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz*](https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz) *tar -xzvf Python-3.6.1.tgz
cd Python-3.6.1 && ./configure && make
sudo make install
sudo pip3 install --upgrade pip 
/usr/local/bin/virtualenv ~/zaid_venv* 
s*ource zaid_venv/bin/activate
pip install Pillow
pip install boto3
pip install requests
pip install snowflake-ingest**

第三个任务:创建 Python 部署包

  1. 编辑 lambda 处理函数 为一个基本的 Lambda 处理函数创建文件【Lambda _ Function . py,该函数使用 python 的雪花连接器。调整连接变量、表名和 S3 存储桶,以匹配您的环境。
  2. 创建并打包 python 虚拟环境 脚本Package _ lambda _ function . sh包含为您的 Lambda 函数创建并打包 Python 环境的命令。这里要小心,因为如果你改变包含 Lambda 处理程序的文件名,你也必须修改这个脚本。
  3. 使用 将代码复制到 AWS EC2 实例运行package _ Lambda _ function . sh后,将生成文件 lambda_function.zip 包含您的 python Lambda 处理程序代码/文件以及在 AWS Lambda 环境中运行所需的 python 依赖项。
  4. 在雪花中创建阶段、表格和管道
**create or replace stage s3_stage url= 's3://outputzaid/' credentials = (AWS_KEY_ID = 'your_key' AWS_SECRET_KEY='your_secret');create or replace table s3_table(c1 number, c2 string);create or replace pipe s3_pipe as copy into s3_table from @s3_stage file_format = (type = 'CSV');create or replace pipe s3_pipe as copy into s3_table from @s3_stage file_format = (type = 'CSV');**

第四项任务:创建和配置 AWS Lambda 权限

  1. 运行 aws configure 并编写您的凭证和您的默认区域
  2. 为了执行 Lambda,您需要使用 aws 命令为角色和策略创建和设置适当的权限,然后上传包含我们的 python 环境的 zip 存档。这些命令可以在文件AWS _ lambda _ setup . sh中找到

第五项任务:使用测试文件测试 Lambda 函数

此时,您可以测试启动 Lambda,并在 AWS Web 控制台 UI 中查看输出。导航至λ>函数>λ_ 函数。

您现在应该看到右上方的列表框,因此您需要在这里配置一个测试,您选择一个名称,并将以下语句放入测试框中

*{ "Records": [ { "eventVersion": "2.0", "eventSource": "aws:s3", "awsRegion": "us-east-1", "eventTime": "1970-01-01T00:00:00.000Z", "eventName": "ObjectCreated:Put", "userIdentity": { "principalId": "AIDAJDPLRKLG7UEXAMPLE" }, "s3": { "s3SchemaVersion": "1.0", "configurationId": "testConfigRule", "bucket": { "name": "outputzaid", "ownerIdentity": { "principalId": "A3NL1KOZZKExample" }, "arn": "arn:aws:s3:::sourcebucket" }, "object": { "key": "test_file_lambda.csv", "size": 1024, "eTag": "d41d8cd98f00b204e9800998ecf8427e", "versionId": "096fKKXTRTtl3on89fVO.nfljtsv6qko" } } } ] }*

结论

你完成了任务,我亲爱的朋友,干得好!
您已经创建了一个 Lambda 函数,将数据从 S3 桶传输到雪花表,这是您成为数据工程师的第一步!
我已经创建了相当多的教程来告诉你如何做流数据。所有这些都是从最基本的开始。我们将在接下来的几周开始放更多的文章。因此,请与我们保持联系,并探索一种学习流式数据的简单方法。

干杯,
扎伊德·阿利萨·阿尔马利基

或者,你可以获得 5 美元/月的中等订阅。如果你使用这个链接,它会支持我。

在 Twitch 上寻找成功

原文:https://towardsdatascience.com/streaming-recommender-twitch-e40d4a45e4ee?source=collection_archive---------8-----------------------

Photo by Caspar Camille Rubin on Unsplash

介绍

似乎就在几周前,我在 Metis 开始了我的旅程,这是一个位于旧金山的沉浸式和挑战性的数据科学项目,十二周后,我们在这里进行我们的最终项目。在这篇博客文章中,我们将介绍我们如何为 Twitch 构建流媒体推荐器,以及我们用来制作应用程序的各种工具,现在可以在 Heroku 上使用。这个项目的代码可以在这里找到。

这一切都始于一个想法。在我的沉浸式活动工作室挂灯笼工作两年后,我加入了创意内容创作者的行列,与他们非常熟悉。不断努力向观众或参与者提供愉快的体验是一个艰难但令人兴奋的挑战,所以我在 Metis 工作期间,通过研究 Kickstarter 活动的过程和公众对《权力的游戏》的看法,探索了它的各个方面。

当选择最终项目的时候,我正在考虑为流行的流媒体网站 Twitch 上的内容创作者制作一个推荐系统,以表达我对视频游戏的热爱和帮助内容创作者的热情。当时看起来好像没有这样的推荐者,尽管有很多文章对流媒体内容提供建议,还有几个网站致力于 Twitch running stats。这似乎是一个完美而过于雄心勃勃的最终项目,我不是我们团队中唯一一个对视频游戏和 Twitch 充满热情的人。与 Jeremy ChowRandy Macaraeg一起,我们开始了Metis 有史以来第一个三人最终项目工作,我们着手为 Streamers 制作一个全功能的 Twitch 推荐器。

抽动是怎么工作的?

Ninja’s channel page on Twitch

对于那些不熟悉它的人来说,Twitch 是一个流媒体视频网站,内容创作者通过播放流行的视频游戏或其他娱乐内容来吸引大量观众和订户。仅在 2018 年,Twitch 上就消费了超过100 万年的内容,每月有超过 400 万条独特的流媒体提供这些内容。正如你所想象的,有这么多的选择看什么,流光是相互竞争的观众和专门的订户。

选择一个游戏(或类别)在 Twitch 上播放是最难做出的选择之一,也是最能影响你成功的一个选择。(作者《涌现》的马克·朗赫斯特(Mark Longhurst)在《如何选择流媒体游戏》一书中写道)

这正是我们的推荐者要解决的问题,这样的问题不是 Twitch 独有的,许多公司将内容、商品或服务的提供商与这些产品的消费者联系起来,因此消费者可以获得的产品的多样性和质量对公司的福利有直接影响。

特别是对于 Twitch 来说,我们的目标是帮助流媒体公司选择最佳的增长游戏,吸引观众和订户,发展他们的频道并分享他们喜欢的内容。

让我们来看看两条假设的抽动彩带:

Photo by KAL VISUALS on Unsplash

Melany 是一个全新的流人,她知道她喜欢什么,但不确定她喜欢的流派和游戏是否会给她带来观众订户

如果我们知道她喜欢角色扮演冒险游戏,并且她最喜欢的游戏是巫师 3:疯狂狩猎龙腾世纪:起源,我们可以向她展示这些类型和游戏目前在 Twitch 上的表现,这样她就可以决定她是否想要继续玩下去。我们还可以展示当前的流媒体趋势,以帮助她了解市场,确定她可以填补的供应缺口,并确保她可以专注于她已经熟悉的游戏类型。

她需要知道:

她应该把她最喜欢的视频串流吗?

哪些内容会产生更多的浏览量?

Unsplash

亚历克斯,另一方面,是一个现有的流光。她的堡垒之夜马登 NFL** 游戏已经有了观众,她希望探索增长选项,带来现有的粉丝,进一步扩大她的观众群,探索她最喜欢的射手体育游戏类型。**

她需要知道:

她现有的观众会喜欢的下一个大型游戏是什么?

她还应该尝试哪些游戏来保持势头?

让我们建立一个数据管道

记住这两个 streamer 案例,让我们浏览一下我们的数据收集过程。

只有三周的时间来实现我们脑海中的复杂愿景,我们投入到数据收集中。在研究了几个 Twitch 分析网站后,我给 SullyGnome 的所有者发了一条 Twitter 消息,他慷慨地向我们提供了 40 天的 Twitch 汇总数据,为我们提供了收视率和频道流信息

为了提取恒定的流数据,我们构建了一个查询 API 的管道,通过 Amazon EC2 实例将数据传输到我们使用 Amazon 关系数据库服务创建的 PostgreSQL 数据库中,并保存在那里供我们使用。然后,我们获取这些数据进行数据分析和开发,并使用 Heroku 推出我们的应用程序。

这个管道的架构确保我们在任何时候都可以访问相同的信息流,Python 脚本每小时收集一次 Twitch 数据,将结果存放到我们为接收信息而设置的三个 PostgreSQL 表中。

 **Our PostgreSQL Tables Schema****stream_data                              game_information**stream_id text                           game_id textuser_id text                             game_name textuser_name text                           pic_urlgame_id text                            stream_type texttitle text                              **game_genres**viewer_count int                         started_at timestamp                     game_name textlanguage text                            game_genres texttime_logged timestamp

表格完成后,我们直接查询数据并开始探索性的数据分析。这种分析的精华可以在推荐应用程序的第一个标签和我们的 Tableau 仪表盘中找到。例如,我们通过观察观众与频道的比率变化,检查了哪些类型的内容正在增长,并找到了那些有流媒体增长和进入空间的类型。

Taste of our Tableau graphs, the entire selection is linked below.

** [## 随着时间的推移,Twitch 的游戏、类型、频道和收视率的趋势。GitHub…

随着时间的推移,Twitch 的游戏、类型、频道和收视率的趋势。GitHub…

随着时间的推移,Twitch 的游戏、类型、频道和收视率的趋势。GitHub…public.tableau.com](https://public.tableau.com/views/TwitchVisualizations/PickYourGame?:embed=y&:display_count=yes&:origin=viz_share_link)

惊喜!我们的推荐创建流程

我们使用了惊奇 Python 库,它是开发推荐系统的一个很好的工具。对于这个框架,我们所需要的是关于我们的流媒体工具、他们喜欢的类型和游戏或者已经流媒体化的信息,以及我们开发的自定义游戏成功指标,该指标的范围从 1 到 5,并作为每个流媒体工具-游戏关系的评级。

我们的算法选择侧重于准确性和速度——较低的测试均方根误差意味着这些算法在处理未知数据时表现最佳,并且工作速度快,这意味着当可用的流数据量不断增加时,可以轻松地重新训练和部署。

这三者协同工作,根据流媒体工具的偏好、他们现有的体验(如果有的话)以及具有类似内容的其他流媒体工具的相对成功来确定最合适的游戏和流派。我们将它们融合在一起,为每个流媒体工具生成一个单一的推荐列表,提供各种类型和游戏进行流媒体播放,所有这些都有可能提高他们的收视率并留住订户。你可以在 Heroku 上亲自试用推荐者。目前,推荐应用程序中使用的模型是我们测试过的更简单、更快的模型,但如果服务器能够处理大量的流媒体数据,我们可以利用我们开发的更强大的算法。**

时机就是一切

除了推荐飘带和什么可以传送,我们还希望能够告诉他们什么时候是传送的好时机。考虑到 Twitch 的收视率在本质上是周期性的,通常收视率的峰值出现在晚上,识别一天或一周内的供应缺口变得非常重要。我们使用长短期记忆(LSTM)网络模型来研究观众和频道随时间的波动,旨在预测预期的变化。

LSTM 使用长期记忆来量化一段时间内的增长并检查季节性趋势,使用短期记忆来考虑最*/每天的趋势,其遗忘能力允许其进一步回顾,而没有其他网络如递归神经网络(RNNs)的速度损失。

我们查看了整个上周的数据(168 小时),检查了 24 个最后的模型状态,并预测了接下来的一周(168 小时)。

当样本内和测试 RMSE 为 10%时,我们能够很好地预测流媒体频道随时间的波动。

成长得分

除了提供推荐和指定何时进行流媒体播放,我们还希望能够根据一个通用指标对我们推荐的游戏进行排名,该指标不仅包括我们之前讨论过的推荐评级,还包括作为前 8 大流媒体市场份额函数的增长潜力。这种方法可以防止流媒体工具试图闯入一个已经被少数人垄断、没有扩张空间的游戏。

Doesn’t this look clear and uncomplicated?

它真正的意思是:

Ah, much better!

第一项,流媒体亲和力,来自推荐者本身,并且针对每个流媒体游戏的成功潜力而言是个人的,游戏增长游戏受欢迎程度随着时间而变化,并且可以从输入的数据流中推断出来,市场渗透性源自每个游戏被其顶级流媒体所垄断的程度。作为一个整体,成长分数反映了每个游戏的每个流的全部潜力。它目前正在开发中,我们希望将来在我们的建模中实现它。

总的来说,我们的推荐系统完成了几件重要的事情:它改善了流媒体体验和保留,它鼓励了频道的增长和内容的多样性,并增加了 Twitch 的收入。这种内容创建者推荐系统可以适用于其他公司和类型的内容创建。这个项目一直是一个令人惊叹的挑战,我们希望扩展我们的模型,以用于 Twitch 实时流数据,收集所有实时数据,并不断训练我们的推荐模型以提高其准确性,并将其完全集成到 Twitch 上的流媒体体验中。

你可以在 Heroku 上找到我们的应用程序。该推荐器的代码可在 GibHub 上找到。

感谢您的阅读。如果你想联系我,可以在 Github 、 LinkedIn 和 Twitter 上找到我。

** [## 娜塔莎·鲍德斯

具有市场研究和品牌管理、CPG、宠物和沉浸式活动行业背景的数据科学家…

www.natashaborders.com](https://www.natashaborders.com/)**

流式 scikit-通过 PySpark 学习

原文:https://towardsdatascience.com/streaming-scikit-learn-with-pyspark-c4806116a453?source=collection_archive---------8-----------------------

Source: https://www.maxpixels.net/Water-Creek-Stream-River-Cascade-Nationalpark-4324529

第八章《生产中的数据科学》节选

本章探索了模型管道,当记录到达一个流式 ML 框架时,在管道中对它们进行评估。这本书涵盖了 AWS 上的 Spark 和 Kafka 以及 GCP 上的 PubSub 和 Dataflow 的流工作流,而这篇博客文章则涵盖了前者。本章中所有例子的源代码都可以在 GitHub 上找到。

[## 生产中的数据科学

从初创公司到数万亿美元的公司,数据科学在帮助组织最大化…

leanpub.com](https://leanpub.com/ProductionDataScience)

第 8 章流模型工作流

许多组织现在都在使用流*台来构建实时数据管道,以转换数据流并在云环境中的不同组件之间移动数据。这些*台通常是分布式的,并为流数据提供容错。除了将不同的系统连接在一起,这些工具还提供了存储记录和创建事件队列的能力。

最受欢迎的流*台之一是 Apache Kafka,这是一个开源解决方案,用于跨公共云和私有云提供消息流。Kafka 是一个托管解决方案,需要供应和管理一个机器集群以便扩展。GCP 提供了一个名为 PubSub 的全托管流媒体*台,AWS 提供了一个名为 Kinesis 的托管解决方案。最佳选择取决于您的云*台、吞吐量和延迟要求以及开发运维问题。

借助流媒体*台,您可以在云环境中的不同组件之间以及外部系统之间传递数据。比如,现在很多游戏公司都在使用这些*台从手机游戏中收集游戏性事件,其中一个事件从游戏客户端传输到游戏服务器,然后以流的形式传递到数据*台。在这种情况下,消息生产者是将消息传递给消费者的游戏服务器,消费者是转换和存储事件的数据*台。

与生产中的数据科学的联系是,流*台可用于应用 ML 模型,作为流管道中的转换步骤。例如,您可以设置一个 Python 流程,该流程从一个主题读入消息,应用 sklearn 模型,并将预测输出到一个新主题。该过程可以是为用户提供实时 ML 预测的更大工作流的一部分,例如移动游戏中的物品推荐。对于扩展到大量消息的模型应用步骤,我们需要使用 Spark 和 Cloud Dataflow 等分布式系统,而不是单一的 Python 流程。

虽然流模型管道中的模型应用步骤类似于设置 Lambda 或 Cloud 函数,这已经提供了接*实时的预测,但一个关键的区别是易于与云*台中的其他组件集成。例如,使用 Cloud Dataflow,您可以将事件路由到 BigQuery 进行存储以及模型应用程序步骤,这可能会将输出推送给新的消息消费者。另一个好处是,它支持使用分布式工具(如 PySpark)来处理模型应用程序的请求,而不是使用基于端点的方法来孤立地处理请求。

在云*台中使用消息传递系统的好处之一是,它允许不同的工具和不同的编程语言使用标准化的接口进行通信。在本书中,我们将重点介绍 Python 和 PySpark,但是这些*台也支持 Java、Go 和许多其他语言。在本章中,我们将首先使用 Apache Kafka 在不同的 Python 进程之间传递消息,然后使用 PySpark 流来消费、转换和生成新消息。接下来,我们将使用 GCP 上的 PubSub,在流模式下使用云数据流提供*乎实时的模型预测。

8.1 火花流

Spark 从 0.7 版本开始就支持流数据集,但直到 2.3 版本才发布了一种称为结构化流的低延迟模式。借助结构化流,当扩展到高容量工作负载时,可以使用连续处理来实现毫秒级延迟。结构化流的一般流程是从输入流(如 Kafka)读取数据,使用 Spark SQL、Dataframe APIs 或 UDF 应用转换,并将结果写入输出流。Spark Streaming 还可以与包括 PubSub 和 Kinesis 在内的托管流*台以及包括 Flume 在内的 Apache 生态系统中的其他框架协同工作。

在这一节中,我们将首先设置一个 Kafka 实例,然后在同一台机器上使用 Kafka 生成和使用消息。接下来,我们将展示如何使用 PySpark 中的readStream函数消费来自 Kafka 的消息,然后构建一个应用 sklearn 模型的流管道。

8.1.1 阿帕奇卡夫卡

Kafka 是在 LinkedIn 孵化的开源流媒体*台。它旨在处理高吞吐量和低延迟的实时数据流。它是用 Java 和 Scala 编写的,但是支持一系列编程语言,用于通过标准化的 API 产生和消费流。通过使用水*扩展和分区将工作负载分布在称为代理的服务器集群上,该*台可以扩展到大型数据集。虽然开源的 Kafka 是一个托管的消息流解决方案,但一些云提供商现在提供完全托管版本的 Kafka,如 Amanon 的 MSK 产品。

为了展示 Kafka 如何集成到流工作流中,我们将使用单节点设置来启动和运行。对于生产环境,您会希望设置一个多节点集群来实现冗余和改进延迟。由于本章的重点是模型应用程序,因此我们不会深入探讨为高可用性设置 Kafka 的细节,而是为小团队的入门者推荐托管解决方案。要安装 Kafka,浏览到网站并找到最新版本是很有用的。为了安装 Kafka,我们首先需要安装 Java,然后下载并解压 Kafka 版本。在 EC2 机器上设置单节点 Kafka 实例所需的步骤如下面的代码片段所示。我们还将安装一个用于在 Python 中使用 Kafka 的库,名为kafka-python

sudo yum install -y java
pip install --user kafka-python
wget http:**//**mirror.reverse.net/pub/apache/kafka/2.4.0/kafka_2.12-2.4.0.tgz
tar -xzf kafka_2.12-2.4.0.tgz
cd kafka_2.12-2.4.0
bin/zookeeper-server-start.sh config/zookeeper.properties***# new terminal*** bin/kafka-server-start.sh config/server.properties***# new terminal*** bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic dsp***# output*** [2019-12-18 10:50:25] INFO Log partition=dsp-0, dir=**/**tmp/kafka-logs Completed load of log with 1 segments, log start offset 0 and log end offset 0 **in** 56 **ms** (kafka.log.Log)

在设置 Kafka 时,我们需要生成三个独立的进程来运行依赖项,启动 Kafka 服务,并为发布消息创建一个新主题。上面的代码片段运行以下流程:

  • Zookeeper: 为分布式系统提供配置和服务发现的 Apache 项目。
  • Kafka 推出启动服务,支持设置 Kafka 主题和使用流式 API。
  • 主题:创建一个名为“dsp”的新主题。

ZookeeperKafka任务是长期运行的进程,将继续执行直到终止,而Topics进程将在新的 Kafka 主题建立后关闭。代码片段底部的输出显示了运行该命令的输出,它将显示在运行Kafka流程的终端中。在这个配置中,我们为主题设置了一个单独的分区,没有复制。我们现在有了一个用于测试消息流的单节点 Kafka 集群。

我们将探索的第一个 API 是Producer API,它使流程能够向主题发布消息。为了向我们的 Kafka 服务器发布消息,我们通过传入一个地址和一个序列化函数来创建一个 producer 对象,该函数指定如何将 Python 对象编码成可以传递给 Kafka 服务器的字符串。下面的 Python 代码片段展示了如何创建生产者,如何将 dictionary 对象作为消息发送给服务器,并将消息发布到dsp主题。dict对象包含hellotime键。如果我们运行这段代码,消息应该会成功地传输到服务器,但是还没有消费者来处理消息。

from kafka import KafkaProducer
from json import dumps
import timeproducer = **KafkaProducer**(bootstrap_servers=['localhost:9092'],value_serializer=lambda x: **dumps**(x)**.encode**('utf-8'))data = {'hello' : 'world', 'time': **time.time**()}
**producer.send**('dsp', data)

为了建立一个消费消息的流程,我们将探索“消费者”API,它用于读入数据流。下面的 Python 片段展示了如何创建一个连接到 Kafka 服务器的消费者对象并订阅dsp主题。返回的consumer对象是可迭代的,可以与 for 循环结合使用来处理消息。在下面的例子中,for 循环将暂停执行,直到下一条消息到达,并继续迭代,直到进程终止。value对象将是我们从生产者那里传递过来的 Python 字典,而deserializer函数定义了如何将字符串转换成 Python 对象。这种方法适用于小规模的流,但是对于较大的数据量,我们还希望分布消息处理逻辑,我们将在下一节用 PySpark 演示这一点。

from kafka import KafkaConsumer
from json import loadsconsumer = **KafkaConsumer**('dsp',bootstrap_servers=['localhost:9092'],value_deserializer=lambda x: **loads**(**x.decode**('utf-8')))**for** x **in** consumer:**print**(x.value)

现在我们有了用于生成和消费消息的 Python 脚本,我们可以用 Kafka 测试消息流。首先,在 Jupyter 笔记本中运行Consumer脚本,然后在单独的笔记本中运行Producer脚本。在多次运行生产者单元之后,您应该看到来自消费者单元的输出,类似于下面显示的结果。

{'hello': 'world', 'time': 1576696313.876075}
{'hello': 'world', 'time': 1576696317.435035}
{'hello': 'world', 'time': 1576696318.219239}

我们现在可以使用 Kafka 在云部署中的不同组件之间可靠地传递消息。虽然本节使用了一个测试配置来启动 Kafka 服务,但是我们探讨的 API 适用于数据量大得多的生产环境。在下一节中,我们将探索用于处理流数据的Streams API,比如应用 ML 模型。

8.1.2 Sklearn 流

为了使用 Kafka 构建端到端的流管道,我们将利用 Spark 流来处理和转换到达的数据。Spark 2.3 中引入的结构化流增强支持使用数据帧和 Spark SQL,同时抽象出处理批处理和数据集的许多复杂性。在这一节中,我们将建立一个 PySpark 流管道,从 Kafka 主题中获取数据,应用 sklearn 模型,并将输出写入一个新主题。整个工作流是一个连续运行和处理来自 Kafka 服务的消息的 DAG。

为了让 Kafka 与 Databricks 一起工作,我们需要编辑 Kafka 配置以与外部连接一起工作,因为 data bricks 运行在独立的 VPC 上,并且可能与 Kafka 服务分开。此外,我们之前使用 bootstrap 方法来指代使用localhost作为 IP 的经纪人。在 AWS 上,Kafka 启动脚本将使用内部 IP 监听连接,为了启用来自远程机器的连接,我们需要更新配置以使用外部 IP,如下所示。

vi config/server.properties 
advertised.listeners=PLAINTEXT:**//**{external_ip}:9092

在进行了这个配置更改之后,您需要重新启动 Kafka 进程,以便从 Databricks 接收入站连接。您还需要通过修改安全组来启用来自远程机器的入站连接,这将在第 1.4.1 节中介绍。端口 9092 需要为将连接到 Kafka 服务的 Spark 节点打开。

我们还将设置第二个主题,用于发布模型应用步骤的结果。我们将建立的 PySpark 工作流将使用来自一个主题的消息,应用一个 sklearn 模型,然后将结果写入一个单独的主题,称为preds。这个工作流程的一个主要好处是,您可以替换掉进行预测的管道,而不会影响系统中的其他组件。这类似于云工作流中的组件调用端点进行预测,但我们可以无缝地交换新的后端逻辑,而不会影响工作流中的其他组件,而不是更改调用端点的组件的配置以指向新的端点。

bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic preds

在考虑如何构建预测性建模管道之前,从简单地使用消息的基本工作流开始是一个很好的实践,尤其是在处理流数据时。为了确保我们已经正确地设置了 Kafka 与 Databricks 的远程连接,我们可以编写一个最小的脚本来使用流中的消息并输出结果,如下面的 PySpark 片段所示。Databricks 将定期刷新输出,并在新数据到达时在输出表中显示新数据。将startingOffsets值设置为earliest意味着我们将从最后一个 Kafka 检查点加载数据。移除此设置将意味着只有新消息显示在可视化表格中。

df = spark **.readStream.format**("kafka")**.option**("kafka.bootstrap.servers", "{external_ip}:9092")**.option**("subscribe", "dsp") **.option**("startingOffsets", "earliest")**.load**()
**display**(df)

让 Databricks 与 Kafka 服务通信可能是让这个示例管道工作的主要挑战之一,这就是为什么我建议从最简单的 PySpark 脚本开始。编写简单的 UDF 来处理接收到的消息的value字段也很有用,这样可以确保 PySpark 中解码的消息与 Python 进程中编码的数据相匹配。一旦我们可以消费消息,我们将使用 UDF 来应用 sklearn 模型,其中 UDF 指的是 Python 函数,而不是熊猫 UDF。作为一般实践,向 Spark 工作流添加检查点是很好的,上面的代码片段是检查接收的数据是否与传输的数据匹配的一个很好的例子。

对于 Spark 流示例,我们将再次使用游戏数据集,它有十个属性和一个标签列。在这个工作流中,我们将把特征向量作为输入发送到流管道,并输出一个额外的预测列作为输出。我们还将添加一个惟一的标识符,如下面的 Python 片段所示,以便跟踪管道中的模型应用程序。下面的代码片段展示了如何用模型所需的 10 个属性创建一个 Python dict,将一个 GUID 附加到字典,并将对象发送到流模型主题。

from kafka import KafkaProducer
from json import dumps
import time
import uuidproducer = **KafkaProducer**(bootstrap_servers= ['{external_ip}:9092'],value_serializer=lambda x: **dumps**(x)**.encode**('utf-8'))data = { 'G1': 1, 'G2': 0, 'G3': 0, 'G4': 0, 'G5': 0, 'G6': 0, 'G7': 0, 'G8': 0, 'G9': 0, 'G10': 0, 'User_ID': **str**(**uuid.uuid1**())}
result = **producer.send**('dsp', data)
**result.get**()

为了实现流模型管道,我们将使用 PySpark 和 Python UDF 来在新元素到达时应用模型预测。Python UDF 对单行进行操作,而熊猫 UDF 对行的分区进行操作。下面的 PySpark 片段显示了该管道的代码,它首先在 driver 节点上训练一个模型,为 Kafka 流设置一个数据接收器,为应用 ML 模型定义一个 UDF,然后将分数作为管道输出发布到一个新主题。

from pyspark.sql.types import StringType
import json 
import pandas as pd
from sklearn.linear_model import LogisticRegression***# build a logistic regression model*** gamesDF = pd.read_csv("https://github.com/bgweber/Twitch/raw/master/Recommendations/games-expand.csv")
model = LogisticRegression() 
model.fit(gamesDF.iloc[:,0:10], gamesDF['label'])***# define the UDF for scoring users*** def score(row):d = json.loads(row)p = pd.DataFrame.from_dict(d, orient = "index").transpose()   pred = model.predict_proba(p.iloc[:,0:10])[0][0]result = {'User_ID': d['User_ID'], 'pred': pred }return str(json.dumps(result))***# read from Kafka*** df = spark.readStream.format("kafka") .option("kafka.bootstrap.servers", "{external_ip}:9092") .option("subscribe", "dsp").load() ***# select the value field and apply the UDF*** df = df.selectExpr("CAST(value AS STRING)")
score_udf = udf(score, StringType())    
df = df.select( score_udf("value").alias("value"))***# Write results to Kafka*** query = df.writeStream.format("kafka") .option("kafka.bootstrap.servers", "{external_ip}:9092") .option("topic", "preds") .option("checkpointLocation", "/temp").start()

该脚本首先使用从 GitHub 获取的数据训练一个逻辑回归模型。模型对象是在驱动程序节点上创建的,但在 UDF 使用时会被复制到工作节点。下一步是定义一个 UDF,我们将应用于管道中的流记录。Python UDF 将一个字符串作为输入,使用json库将字符串转换成字典,然后将字典转换成 Pandas 数据帧。dataframe 被传递给 model 对象,UDF 返回带有User_IDpred键的 dictionary 对象的字符串表示,其中预测值是用户购买特定游戏的倾向。

管道中的下三个步骤定义了 PySpark 流工作流。readStream调用建立了与 Kafka 代理的连接,并订阅了dsp主题。接下来,在将值传递给 UDF 之前,使用 select 语句将流记录的value列转换为字符串,然后使用 Python UDF 的结果创建一个新的数据帧。最后一步将输出数据帧写入preds主题,使用本地目录作为 Kafka 的检查点位置。这三个步骤作为连续处理工作流的一部分运行,其中这些步骤没有完成,而是暂停执行,直到新数据到达。结果是操作的流 DAG 在数据到达时对其进行处理。

运行流式管道时,Databricks 将在单元下方显示有关工作流的详细信息,如图 8.1 所示。绿色图标表示这是一个将继续执行直到终止的流式操作。还有一些图表可以直观显示数据吞吐量和延迟。对于生产管道,使用流程编排工具(如带有 Databricks 操作符的气流)来运行代码很有用,但笔记本环境确实提供了一个运行和调试流管道的有用环境。

FIGURE 8.1: Visualizing stream processing in Databricks.

既然我们正在将模型预测流式传输到一个新的主题,我们需要为这些消息创建一个新的消费者。下面的 Python 代码片段显示了如何为新的预测主题使用来自代理的消息。与以前的消费者相比,唯一的变化是 IP 地址和deserializer函数,它不再在将字符串转换为字典之前应用编码。

from kafka import KafkaConsumer
from json import loadsconsumer = **KafkaConsumer**('preds',bootstrap_servers=['{external_ip}:9092'],value_deserializer=lambda x: **loads**(x))**for** x **in** consumer:**print**(x.value)

我们现在一切就绪,可以用 Spark streaming 和 Kafka 测试流媒体管道了。首先,在 Databricks 单元格中运行 PySpark 管道。接下来,在 Jupyter 笔记本中运行消费者脚本。要完成工作流,请在单独的 Jupyter 笔记本中运行生产者脚本,以向管道传递消息。结果应该是打印到消费者笔记本控制台的预测字典,如下所示。

{'User_ID': '4be94cd4-21e7-11ea-ae04-8c8590b3eee6', 'pred': 0.9325488640736544}

我们现在有一个 PySpark 流管道,它以接*实时的性能应用模型预测。我们可以执行额外的调整,将延迟控制在 1 毫秒以内,这对各种模型和 web 应用程序都很有用。使用 Spark 执行模型应用程序的好处是,我们可以扩展集群以满足需求,并且可以根据需要换入新的管道来提供模型更新。Spark streaming 最初的启动和运行有点棘手,但是最*的增强使得使用模型应用程序管道变得容易多了。在这个管道中,我们使用了一个简单的回归模型,但流式工作流也可以用于深度学习任务,如图像分类。

8.3 结论

流式模型管道对于需要实时应用 ML 模型的系统非常有用。为了构建这些类型的管道,我们开发了两个消息代理,它们可以扩展到大量事件,并为这些管道提供数据源和数据接收器。由于延迟要求,流管道通常会限制您可以执行的操作类型。例如,构建对用户数据执行特征生成的流管道将是一项挑战,因为需要检索历史数据并将其与流数据相结合,同时保持低延迟。有一些模式可以实现这种类型的结果,例如为用户预先计算聚合并将数据存储在应用程序数据库中,但是与批处理模式相比,让这种类型的管道在流模式下工作可能需要更多的工作。

我们首先探索了 Kafka 作为一个流消息*台,并使用 structure streaming 和 PySpark 构建了一个实时管道。接下来,我们构建了一个数据流管道,重用了上一章中的组件,这些组件现在与 PubSub 流服务接口。Kafka 通常会在这两个消息代理之间的延迟方面提供最佳性能,但是与使用托管解决方案相比,维护这种类型的基础设施需要更多的资源。对于刚入门的小团队,PubSub 或 Kinesis 提供了很好的扩展选项来满足需求,同时减少了 DevOps 支持。

本·韦伯是 Zynga 的一名杰出的数据科学家。我们正在招聘!

破产预测的简化模型调整

原文:https://towardsdatascience.com/streamline-model-tuning-on-bankruptcy-predictions-aabbc2fe62c0?source=collection_archive---------21-----------------------

大家好,今天的主题是关于使用 sklearn、xgboost 和 h2o 软件包简化机器学习模型。特别是,我们将检查预测破产的波兰公司使用他们的财务报表。在我早期的机器学习建模中,我总是想知道是否有更简单的方法来调整模型。从这个问题开始,我偶然发现了自动化机器学习,我们可以通过 h2o 包访问它。这是我们要复习的内容的大纲:

  1. 为什么预测破产很重要
  2. 为建模设置数据
  3. 用逻辑回归和 xgboost 预测破产
  4. 用 h2o 预测破产
  5. 结论

这篇文章的数据来自这里:https://www.kaggle.com/c/companies-bankruptcy-forecast/data

为什么预测破产很重要

在信贷或借贷领域,破产相当重要。例如,银行贷款给企业获取利息,并期望在一定时间后得到回报。如果银行有业务没有偿还(如破产),那么银行本身将不会盈利,必须关闭。这个小例子也有助于解释为什么不同的企业在衰退期间会合并。一旦一家公司倒下,另一家公司通常会受到影响——引起连锁反应。

在更个人的层面上,人们可以应用破产预测来更好地保护他们的股票投资组合。例如,你知道你有高风险的股票,并想知道这些公司破产的可能性?不要再看了!你可以有自己的破产预测来卖出可能变坏的股票。对于那些愿意承担更多风险的人,你也可以开发一个短期策略模型。基本上,做空是指你押注一只股票的价格将会下跌,但这被视为比押注一只股票上涨风险更大。

为建模设置数据

像其他 Python 代码一样,我们需要首先加载包:

# Load up packages
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.linear_model import LogisticRegression
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, auc, roc_auc_score
import h2o
from h2o.automl import H2OAutoML

接下来,我们将加载名为变量 data 的数据:

# Load data
data = pd.read_csv('bankruptcy_Train.csv')

就我个人而言,我知道这个数据集非常干净,但我们将经历一些动作:

# Seeing how big the dataset is
data.shape

(10000, 65)

上面显示了 10,000 行 65 列。这里会看到一个表格:

# Glancing at what some of the values are
data.head()

为了便于机器学习预测,一切看起来都包含在一个规范化的形式中,但是让我们检查任何空值:

# Checking for null values
data.isnull().values.any()

错误的

很好,不用担心 Nan 值。在这个数据集中,我们期望的破产输出被称为“类”我不喜欢它,所以我打算把它改名为“目标”,如下图所示:

data.rename(columns={'class':'target'}, inplace=True)

现在,我们可以为我们的模型拆分特性和输出:

# For features in h2o model
cont_names = data.columns[:-1]#Setting up desired output and features for logistic regression and xgboost models
output = data[data.columns[-1]]
features = data[data.columns[:(data.shape[1]-1)]]

出于好奇,我们来看看数据集有多不*衡。

#Check the balance of outputs
output.value_counts()

0 表示非破产公司,1 表示破产公司。这里没有那么多破产就不足为奇了。这导致了一些棘手的情况,比如如何预测逻辑回归的数据不*衡,但由于算法的工作方式,xgboost 对它没有太大影响。幸运的是,对于逻辑回归来说,该模型有一个参数来调整阶级不*衡,我们很快就会看到!

用逻辑回归和 xgboost 预测破产

在所有的数据建立之后,我们终于可以开始建立破产预测的模型了。在预测模型中,标准做法是将数据分成定型集和测试集。模型将从训练集中学习,我们将看到它如何从测试集中学习。

#splits data into X (features) and y (predictions)
X_train, X_test, y_train, y_test = train_test_split(features, output, test_size=0.2, random_state=42)
train = pd.concat([X_train, y_train], 1)
test = pd.concat([X_test, y_test], 1)

因为我们想要查看两个模型(logistic 和 xgboost),所以我设置了下面的代码来运行这两个模型,并进入相同的接收器操作特性(ROC)曲线。

plt.figure()# Add the models to the list that you want to view on the ROC plot
models = [
{'label': 'Logistic Regression','model': LogisticRegression(class_weight='balanced'),
},
{'label': 'XGBoost Classifier','model': XGBClassifier(max_depth=10, n_estimators=300),
}
]# Below for loop iterates through your models list
for m in models:model = m['model'] # select the modelmodel.fit(X_train, y_train) # train the modely_pred=model.predict(X_test) # predict the test data
# Compute False postive rate, and True positive ratefpr, tpr, thresholds = roc_curve(y_test, model.predict_proba(X_test)[:,1])
# Calculate Area under the curve to display on the plotauc = roc_auc_score(y_test,model.predict(X_test))
# Now, plot the computed valuesplt.plot(fpr, tpr, label='%s ROC (area = %0.2f)' % (m['label'], auc))
# Custom settings for the plot 
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('1-Specificity (False Positive Rate)')
plt.ylabel('Sensitivity (True Positive Rate)')
plt.title('Logistic Regression v. XGBoost ROC')
plt.legend(loc="lower right")
plt.show()

对于 ROC 曲线,数值越高,模型越好。把 ROC 曲线想象成一种更好的衡量分类问题准确性的形式。它将真阳性(实际预测为目标变量)和假阳性(预测但不是实际目标变量)比率绘制到一个模型性能统计数据中。

在我们的例子中,在给定的设置下,逻辑回归比 xgboost 更好。但是鉴于 xgboost 像几乎所有 Kaggle 比赛一样获胜的历史,我们知道 xgboost 可以做得更好。对于模型调整来说,这也是一种更简单的方法。

用 h2o 预测破产

这就是 h2o 的乐趣所在——为我们的机器学习模型增加自动化!

# starting up h20
h2o.init()

您将看到类似上面列表的内容,只是时间更长。这只是意味着你的 h2o 的东西工作。有些人可能需要安装 Java,但是 h2o 会告诉你。现在我们可以开始训练了(在训练一小时的时候喝杯茶):

# Training phase set up
data = h2o.H2OFrame(train)# Setting up features and output for h2o models
data['target'] = data['target'].asfactor()
y = "target"
cont_names = cont_names.tolist()
x = cont_names# Setting up max time of model training
aml = H2OAutoML(max_runtime_secs= 3600, max_models=60, sort_metric='AUC')
aml.train(x = x, y = y, training_frame = data)# Displaying best models built
lb = aml.leaderboard
lb.head(rows=lb.nrows)

上表向我们展示了 h2o 为我们打造的前 5 款产品。前 4 名显示了所有的梯度增强模型(xgboost 属于该类型的模型),第五名是堆叠集成模型。堆叠集成基本上是一堆用来一起预测的机器学习模型。相比之下,我们的 GBM 模型只是一种单一类型的机器学习模型。

不管怎样,让我们用我们最好的 GBM 模型做一些预测,看看 ROC 分数。

# Creating Predictions of best model
hf = h2o.H2OFrame(test)
preds = aml.predict(hf)
preds = preds.as_data_frame()
preds['p_p0'] = np.exp(preds['p0'])
preds['p_p1'] = np.exp(preds['p1'])
preds['sm'] = preds['p_p1'] / (preds['p_p0'] + preds['p_p1'])# ROC score of best model
roc_auc_score(y_test, preds['sm'])

0.887

好吧,ROC 得分 0.89 击败了我们上面的逻辑模型 0.78——耶!对于那些对 h2o 模型的设置感兴趣的人,我们可以这样看它:

# Settings of best model
aml.leader.summary()

最酷的是,如果你的工作不允许 h2o 包,但允许底层模型,那么你可以复制设置!另一件要注意的事情是,你可以保存你的模型,以后再加载它,以节省训练时间。

# Saving model for future use
h2o.save_model(aml.leader, path = "/model_bankrupt", force=True)

' c:\ \ model _ 破产\ \ GBM _ grid _ 1 _ AutoML _ 2019 09 11 _ 090503 _ model _ 23 '

# Loading model to avoid training time again
saved_model = h2o.load_model('C:\\model_bankrupt\\GBM_grid_1_AutoML_20190911_090503_model_23')

一旦加载了模型,您就可以使用它进行预测,如下面的代码所示:

# Examlple on how to predict with loaded model
saved_model.predict(hf)

让我们回顾一下如何读取上面的输出。到达行是来自测试集的预测。第一列“预测”显示模型预测的内容。在我们的例子中,0 表示没有破产。p0 是模型认为预测应该为 0 的概率,而 p1 是模型认为第一行应该破产的概率。所以,我们的 GBM 模型认为第一家测试公司 99%不会破产。很酷,对吧?

最后,不要忘记关闭你的 h2o 会话:

# Closing an h2o session after use
h2o.shutdown()

结论

太棒了,我们在这篇文章中做了很多事情!首先,我们讨论了破产的重要性,以及如何将这个模型应用到我们自己的个人投资组合中。接下来,我们从 Kaggle 加载了破产的波兰公司的数据集。第三,我们应用了逻辑回归和 xgboost 来获得一些模型表现的基线。最后,我们通过引导 h2o 的流线型力量,自动化了一个更好的预测模型!

希望你喜欢这个小教程,下次再见!

免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。投资带有严重的风险,在采取任何投资行动之前,请咨询您的投资顾问。

Streamlit 101:深入介绍

原文:https://towardsdatascience.com/streamlit-101-an-in-depth-introduction-fc8aad9492f2?source=collection_archive---------3-----------------------

Streamlit app with code

使用 Airbnb 纽约数据深入了解 Streamlit

Streamlit 是一个令人敬畏的新工具,它允许工程师围绕他们的数据、机器学习模型和几乎任何东西快速构建高度交互式的网络应用。

Streamlit 最大的优点是它不需要任何 web 开发知识。如果你懂 Python,你就可以开始了!

这是本教程的完整代码,如果你想继续学习本教程的话。

为什么细流是超级酷的

一句话:它给了你一个惊人的快速、迭代和交互式的开发循环。

分割你的屏幕,使你的代码编辑工具在一半,你的浏览器在另一半,编辑你的代码,并看到你的应用程序即时更新!关于 Streamlit,我最喜欢的部分是它如何在几个小时内让您从 Jupyter 笔记本变成一个值得向客户展示的时尚 web 应用程序。

设置它

安装步骤:

$ pip install streamlit
$ streamlit hello

进口:

import pandas as pd
import streamlit as st
import plotly.express as px

要运行您的 Streamlit 应用程序:

$ streamlit run app.py

获取 Airbnb 纽约房源数据

Airbnb 没有正式发布任何数据。Airbnb 内部的另一个名为的小组定期发布 Airbnb 房源并审核数据。

**@st.cache**
defget_data():url = "http://data.insideairbnb.com/united-states/ny/new-york-city/2019-09-12/visualisations/listings.csv"return pd.read_csv(url)df = get_data()

数据缓存

st.cache decorator 表示 Streamlit 将执行内部魔术,这样数据将只下载一次并缓存以备将来使用。

在幕后,Streamlit 跟踪函数名、函数体中的代码以及我们在函数调用中传递的输入参数。在第一次调用时,它将函数的返回值存储在本地缓存中。在随后使用完全相同的参数调用该函数时,Streamlit 从本地缓存返回结果。

Streamlit 数据缓存的主要限制是它不能跟踪函数体外部发生的数据更改。

以标题(和引用)开始

**st.title**("Streamlit 101: An in-depth introduction")
**st.markdown**("Welcome to this in-depth introduction to [...].")**st.header**("Customary quote")
**st.markdown**("> I just love to go home, no matter where I am [...]")

上面的代码呈现了以下内容。

Title, section header, and Markdown content rendered by Streamlit

st.title 适合主标题。对于章节标题,使用第一标题或第二标题。

st.markdown 呈现使用 Github 风格的 Markdown 编写的任何字符串。它也支持 HTML,但 Streamlit 建议不要允许,因为存在潜在的用户安全问题。

数据一览

这是我们开始探索性分析时通常做的第一件事。 st.dataframe 渲染熊猫数据帧。

**st.dataframe**(df.head())

Pandas dataframe rendered using streamlit.dataframe

我喜欢它允许在点击任何列标题时对数据帧进行排序(注意 host_name 标题中的小 v 形符号)。

右上角有一个方便的小按钮,可以切换到全屏视图。非常适合查看较大的数据框,无需过多滚动。

它还支持样式的数据帧。

代码块

st.code 渲染单行和多行代码块。还有一个指定编程语言的选项。

st.code("""
@st.cache
def get_data():url = "http://data.insideairbnb.com/[...]"return pd.read_csv(url)
""", language="python")

Code rendered using streamlit.code

或者,使用一个with [st.echo](https://streamlit.io/docs/api.html#streamlit.echo)块执行其中的代码,并将其作为应用程序中的一个代码段。

Code rendered using streamlit.echo

纽约最贵的 Airbnb 房源

Airbnb 最贵的房产都在哪里?

在地图上

st.map 在地图上显示位置,无需编写一行样板代码来准备地图对象。唯一的要求是 dataframe 必须包含名为 lat / latitudelon/longitude的列。

Streamlit map with markers based on latitude and longitude

不出所料,曼哈顿岛是昂贵的航空公司最集中的地方。一些分散在布鲁克林。最贵的标价是 10000 美元。

st.deck_gl_chart 允许更多参数创建更有趣的定制地图。

选择列的子集

Streamlit 有一个 multiselect 小部件,允许从项目列表中选择或删除项目。这让我们可以为 dataframe 构建一个列选择器小部件。

cols = ["name", "host_name", "neighbourhood", "room_type", "price"]
st_ms = st.multiselect("Columns", df.columns.tolist(), default=cols)

Streamlit multi-select widget with auto-completion

multiselect 小部件是 Streamlit 中最强大、最方便的工具之一。除了列选择之外,还有一个用途是基于列的一个或多个值来过滤数据帧。另一种方法是根据不同模型的预测,为并排比较 ROC 曲线选择支线图。

按房间类型划分的*均价格

哪种房型*均最贵?

在静态表中

st.table 显示一个静态表。但是,您不能通过单击列标题对其进行排序。

**st.table**(df.groupby("room_type").price.mean().reset_index()\
.round(2).sort_values("price", ascending=False)\
.assign(avg_price=lambda x: x.pop("price").apply(lambda y: "%.2f" % y)))

Static table rendered by Streamlit

哪些主机列出的属性最多?

Sonder (NYC) 以 387 个房产列表位居榜首。Blueground 排名第二,有 240 个条目。下面是从使用[st.json](https://streamlit.io/docs/api.html#streamlit.json)呈现为 JSON 的两个清单中随机选择的清单。

Streamlit 呈现完全交互式的 JSON 部分,支持折叠/展开对象和数组,以及复制到剪贴板功能。

JSON section rendered by Streamlit

房产价格分布是怎样的?

我们使用 st.plotly_chart 将房地产价格直方图显示为 Plotly 图表。

边栏和价格范围滑块

我们使用 st.slider 来提供一个滑块,允许选择直方图的自定义范围。我们把它藏在一个侧边栏里。

values = **st.sidebar.slider**(“Price range”, float(df.price.min()), 1000., (50., 300.))
f = px.histogram(df.query(f”price.between{values}”), x=”price”, nbins=15, title=”Price distribution”)
f.update_xaxes(title=”Price”)
f.update_yaxes(title=”No. of listings”)
**st.plotly_chart**(f)

In the sidebar

On the main page

最高的条形对应于 60-79 美元的价格范围,有 7229 个列表。

注意:在本教程中,我将滑块的最大值限制为 1000,这样范围选择就会清晰可见。

不同社区的可用性分布

availability_365表示酒店全年可用的天数。我们按邻居组检查availability_365的汇总统计数据。

使用 st.radio ,我们显示一个可供选择的邻居组列表。默认情况下,我们排除价格≥200 美元的物品,并使用 st.checkbox 提供一个包含昂贵物品复选框。

st.write 是一种伞状函数,接受字符串、数据帧、字典、绘图、地图等等(文档中的完整列表)。它允许传入多个参数,其行为取决于它们的类型。

**st.write**("Using a radio button restricts selection to only one option at a time.")
neighborhood = **st.radio**("Neighborhood", df.neighbourhood_group.unique())
show_exp = **st.checkbox**("Include expensive listings")

Radio group and checkbox rendered by Streamlit

169 天,布鲁克林的*均可用性最低。斯塔滕岛的*均可用性最高,为 226。如果我们包括昂贵的清单(价格> = 200 美元),这个数字分别是 171 和 230。

注意: 有 18431 条记录带有 *availability_365* 0(零),我已经忽略了。

按邻居组列出的*均可用性

st.pyplot 渲染使用 matplotlib 构建的地块,如下图所示。

df.query("availability_365>0")\
.groupby("neighbourhood_group")\
.availability_365.mean()\
.plot.bar(rot=0)\
.set(title="Average availability by neighborhood group",
xlabel="Neighborhood group", ylabel="Avg. availability (in no. of days)")
**st.pyplot**()

Created with pandas (matplotlib)

评论数量

我们希望查看评论数量在我们可以自定义的范围内的属性。

在侧栏中,我们使用 st.number_input 提供了一个数字范围选择器。如果minimum > maximum,我们使用 st.error 显示错误信息。

minimum = **st.sidebar.number_input**("Minimum", min_value=0)
maximum = **st.sidebar.number_input**("Maximum", min_value=0, value=5)
if minimum > maximum:**st.error**("Please enter a valid range")
else:df.query("@minimum<=number_of_reviews<=@maximum")

486 是最高评论数。两个列表有这么多评论。两家都在东埃尔姆赫斯特街区,都是价格分别为 65 美元和 45 美元的私人房间。一般来说,超过 400 条评论的列表价格低于 100 美元。有几款在 100 美元到 200 美元之间,只有一款定价在 200 美元以上。

图像和下拉菜单

使用 st.image 显示猫、小狗、特征重要性图、标记视频帧等的图像。

现在来点好玩的。

pics = {"Cat": "https://cdn.pixabay.com/photo/2016/09/24/22/20/cat-1692702_960_720.jpg","Puppy": "https://cdn.pixabay.com/photo/2019/03/15/19/19/puppy-4057786_960_720.jpg","Sci-fi city": "https://storage.needpix.com/rsynced_images/science-fiction-2971848_1280.jpg"
}
pic = **st.selectbox**("Picture choices", list(pics.keys()), 0)
**st.image**(pics[pic], use_column_width=True, caption=pics[pic])

Cat image source: https://cdn.pixabay.com/photo/2016/09/24/22/20/cat-1692702_960_720.jpg

魔法

请注意,在上面的评论数量部分,我们将df.query("@minimum<=number_of_reviews<=@maximum")写在了它自己的一行上,而没有将其包装在对st.dataframe的调用中。这仍然呈现了一个数据帧,因为 Streamlit 在其自己的行上检测到一个变量或文字,并使用st.write来呈现它。

结论

我们已经讨论了交互式小部件、数据框、表格、图像、降价、绘图渲染、地图和文本内容。Streamlit 允许对现有元素和显示进度的进行修改,这在本教程中没有涉及。例如,您可以向现有表格中添加行,或者向图表中添加新数据。您还可以显示长时间运行的进程的进度条。

恭喜,您已经准备好开始构建自己的 Streamlit 应用程序。

派对时间!

当你运行为这个教程创建的应用时,点击 庆祝! 按钮由下面的代码呈现。

**st.markdown**("## Party time!")
**st.write**("Yay! You're done with this tutorial of Streamlit. Click below to celebrate.")
btn = **st.button**("Celebrate!")
if btn:**st.balloons**()

下一步是什么?

我的下一篇文章将是关于我在 Kaggle 上的沃尔玛购物旅行类型分类竞赛中获得银牌(排名 35 /前 4%)的解决方案。

参考和链接

  • 为本教程创建的 Streamlit 应用的完整代码:https://github . com/shaildeliwala/experiments/blob/master/Streamlit . py
  • 出自Streamlit 联合创始人 Adrien Treuille:https://towardsdatascience . com/coding-ml-tools-like-you-code-ml-models-ddba 3357 eace
  • Streamlit API 文档:https://streamlit.io/docs/api.html
  • Streamlit 教程:https://streamlit.io/docs/tutorial2/
  • Streamlit 演示视频:https://youtu.be/B2iAodr0fOo
  • Airbnb 纽约房源数据(非官方):http://data . inside Airbnb . com/United-States/ny/new-York-city/2019-09-12/visualizations/listings . CSV
  • Plotly 直方图文档:https://plot.ly/python/histograms/

Streamlit-部署机器学习模型,无需学习任何 web 框架。

原文:https://towardsdatascience.com/streamlit-deploy-a-machine-learning-model-without-learning-any-web-framework-e8fb86079c61?source=collection_archive---------13-----------------------

用一个演示项目来解释-

对于许多人来说,从事一个实际的数据科学项目,然后花更多的时间在 web 框架、后端和前端上工作是非常令人厌倦的。对于数据科学家或机器学习工程师来说,研究这些技术是次要任务。所以问题是,在没有学习 flask(一个非常著名的最小 python 框架)的情况下,如何部署 ML 模型呢?在这篇博客中,我将向您展示最有用的工具,即 Streamlit,它可以帮助您专注于数据科学家的工作。但是,它将负责您的模型的部署,您的模型可以作为工作的 web 应用程序发布。

让我们了解一下 streamlit 工具对于像你我这样的 ML/数据科学从业者部署我们的模型是如何有用的。我们将使用著名的 首都自行车共享数据集 ,并实现各种分类算法来确定用户的会员类型,无论他/她是会员、临时会员还是未知的。在开始之前,让我告诉你们,我是一个博客新手,因为我没有写太多的习惯,这也是我的第一个博客。所以,请原谅我可能犯的任何错误。我会尽可能简单地解释,所以在阅读这篇文章时请耐心等待。您应该了解基本的 python 编程语言,并且通过 scikit-learn 库了解一点实现 ML 算法的工作知识就足以理解这个项目。

要开始使用 Streamlit,您需要使用 pip 在您的系统上安装它。在您的终端/cmd 上键入" $ pip install streamlit" 。对于 Linux 和 Windows 用户,该命令是相同的。

让我们从导入几个和 streamlit 开始,如下所示:

Import Libraries

我们将训练决策树、神经网络和 KNN 分类器模型来预测用户的成员类型。看看我们数据集的一个实例:

Capital Bike Share Dataset

现在,让我们从定义我们的 main() 函数开始,在这里我们将调用其他函数来对我们的数据集执行预处理并调用我们的 ML 模型。

Main function beginning

在上面的代码片段中, st.title() 是一个 streamlit 函数,它帮助显示我们项目的标题。它将在您的 web 应用程序上显示为标题,一旦您在本地系统上运行此 streamlit 代码,它将自动部署在本地主机上。要运行 Streamlit 代码,移动到您的代码所在的目录,并在您的终端或 cmd 上键入Streamlit run your _ file _ name . py,它将在 localhost:8501 上运行您的 web 应用程序。

现在,我们必须通过调用我们的用户定义函数 loadData() 来加载数据集。然后我们会进行预处理,通过调用预处理()函数(loadData()和预处理()函数的片段如下所示)将数据拆分成训练和测试数据。函数 st.checkbox() 也是一个 streamlit 函数,有助于在 web 应用程序上启用复选框小部件。因此,当用户单击复选框时,将调用 st.write() 函数,从而在我们的应用程序中弹出数据集的一个实例。

看看函数 loadData()预处理():

Loading and Preprocessing Dataset

streamlit 最有趣也是最有用的功能在上面的代码中有介绍,即 @st.cache 。它有助于缓存在相应函数中执行的每个任务。在这里,数据集被缓存,所以下次加载时不会有延迟。现在,我们已经将独立和从属特征分别指定为 X 和 y。我们考虑的独立特征是持续时间、起点站号和终点站号。依赖特性是数据集的成员类型列,但它需要编码,因为它由分类数据组成。这里,我使用了 scikit-learnlabel encoder(),但是您可以使用您选择的任何编码器。最后,我们将使用 scikit-learn 库的 train_test_split() 方法将数据分成训练和测试数据集。

现在我们已经准备好了训练和测试数据,让我们实现 ML 算法,并在我们的 web 应用程序上显示结果。

首先,我们将让用户使用 Streamlit 的 st.sidebar.selectbox() 方法从侧边栏的选择框中选择所需的 ML 模型,如下所示。

The function call to Decision Tree Classifier

由于这是一个带有动手项目的 streamlit 工具演示,解释 ML 算法超出了范围。所以,我希望你们有一些用 python 实现 ML 算法的知识。好吧!让我们回到上面显示的代码。如果用户选择我们的第一个模型,这是一个决策树分类器,那么 decisionTree() 函数(如下所示)将被调用,返回混淆矩阵和训练模型的准确性。再次使用 st.write() ,我们可以在我们的 web 应用程序上显示混淆矩阵和分数。

此外,如果用户想要将他的测试样本输入到模型中并得到预测,该怎么办呢?为此,我们可以在应用程序中使用复选框。如果用户点击复选框,则 accept_user_data() 函数(accept_user_data()函数代码如下所示)被调用,用户可以手动填充三个独立的特性。因此,模型将预测相同的成员类型。

accept_user_data() 函数的代码:

Code for accepting user data needed for performing prediction on user data

此外,我们可以通过调用构建 KNN 分类器和神经网络分类器的函数来重复同样的事情。请注意,我们刚刚讨论了对这些模型的函数调用,我们还没有看到实际模型被训练的那些函数定义。看看这些函数调用的代码片段:

The function call to Neural Network and KNN Classifier

其次,ML 算法将使用scikit-learn库来编写,这是 python 中一个众所周知且广泛使用的机器学习库。

决策树分类器编写如下:

Decision Tree Classifier Model

在 scikit-learn 中使用 MLPClassifier 也以有点类似的方式编写了神经网络。这里,我们必须在训练模型之前缩放数据,因为这样,它会给出更准确的结果。请注意,我们已经使用 streamlit 缓存了模型,如上所述。这将有助于立即加载模型,从而减少执行中的延迟。

参见下面的神经网络实现:

Neural Network Classifier Model

类似地, KNN 分类器模型是使用 scikit-learn 库中的 KNeighborsClassifier 编写的:

KNN Classifier Model

就数据科学和机器学习领域而言,我们都知道数据可视化的重要性。

最后,让我们探索如何使用 Streamlit 在我们的 web 应用程序上展示漂亮的交互式可视化效果。

出于演示目的,我们将基于这些数据开发两个可视化工具。第一个是来自数据集的车辆的几个开始位置的可视化。Streamlit 无法在地图上直接显示地理空间点的散点图;但是,它需要数据集中的纬度和经度列。因此,我个人更喜欢使用 地理库 来解码数据集的起始位置列中存在的 1000 个地址的纬度和经度。如果你有兴趣知道我是如何解码的,那么请访问我的 GitHub 库 。否则,您可以从我的 GitHub 存储库中为这个项目下载带有和不带有坐标的数据集。

此外, st.map() 函数会根据纬度和经度自动绘制世界地图以及数据点。请参见下面的示例:

Plotting Scatter Plot on the World Map

对于最后一个可视化,我们将绘制直方图来确定特定特征中每个元素的计数。例如,根据我们的数据集,有三种类型的成员。所以,我们将使用 plotly 库 绘制一个直方图来查看每种类型的大概计数。让我们使用三个特征的直方图来可视化计数,即起点桩号、终点桩号和构件类型。此外,让用户使用 streamlit 选择框功能选择要查看的可视化。

参见下面的代码:

Plotly Histogram using Streamlit

下面是一些使用 streamlit web 应用程序获得的惊人结果的快照:

ML Model Running

Prediction on User Input

Streamlit Map Plot

Plotly Histogram Plot

那可是相当可观的教程,我知道!但是,最令人兴奋的事实是,您已经学会了如何部署机器学习 web 应用程序,而无需学习 Flask 或 Django。此外,streamlit 非常容易使用,因为在这个项目中,我们刚刚进行了 33 次 streamlit 调用,其中很多都是相同类型的函数调用。我希望你喜欢这篇文章,并发现它很有帮助。如果是的话,请与你的朋友和同事分享。

注意:不要*复制并运行代码片段,因为这可能会导致缩进错误。因此,为了节省您的时间,我将我的 GitHub 链接添加到这段代码— 点击这里 *

你可以用 Streamlit 做很多很酷的事情。所以,查阅一下Streamlit的官方文档。

Airbnb 新加坡的严格法律——分析

原文:https://towardsdatascience.com/strict-laws-in-airbnb-singapore-an-analysis-92ad7cf9a8cc?source=collection_archive---------23-----------------------

将挑战短期住宿法则的房源比例可视化

Photo by Swapnil Bapat on Unsplash

新加坡短期居留法

除了缺乏值得探索的自然景点和是最昂贵的居住地之一外,新加坡无疑是东南亚短期旅行的最佳城市之一,拥有最高效的公共交通系统,实惠的餐饮和干净的环境。

住在 Airbnb 酒店一直是许多旅行者的首选,他们希望在预算有限的情况下探索一些地方,获得一种宾至如归的体验。然而,新加坡颁布了一项针对房东的法律,如果客人在私人房产中停留不到 3 个月,将被处以高达 20 万美元的罚款。更严厉的法律适用于 HDB(住房发展委员会)房产的业主,这是一种设施有限、更实惠的房产。你可以通过下面的链接了解更多。

[## Airbnb 在新加坡违法吗?SingaporeLegalAdvice.com

希望通过出租房屋获得额外收入?在房屋共享网站 Airbnb 上挂牌越来越…

singaporelegaladvice.com](https://singaporelegaladvice.com/law-articles/is-airbnb-illegal-singapore) [## 两名新加坡房东因非法合租房屋被罚款:Airbnb 在不同城市的法律

新加坡——4 月 3 日,两名 Airbnb 房东因提供未经授权的短期…

www.straitstimes.com](https://www.straitstimes.com/singapore/two-hosts-charged-over-illegal-home-sharing-airbnb-laws-in-various-cities)

在你犹豫要不要在新加坡预订 Airbnb 之前,先别着急!客人在新加坡的 Airbnb 停留任何时间都不违法。但由于害怕被罚款,一些客人被公寓保安赶走了。你可以在下面了解更多。

[## NZ family 的 Airbnb 困境凸显了房源的不透明性

一个新西兰的四口之家出现在加勒比海的吉宝湾,期望拿起公寓的钥匙…

www.straitstimes.com](https://www.straitstimes.com/singapore/housing/nz-familys-airbnb-woes-highlight-lack-of-clarity-on-listings)

好了,法律已经够了。我们在这里探索新加坡“高风险”房源的分布。在这个项目中,我将在 Airbnb 中使用来自 的最新 Airbnb 数据集。

数据预处理

在我们深入研究数据集中的要素之前,我想专门针对新加坡禁止短期停留的严格法律创建一个新要素。这将是一个分类特征,取值为“高风险”、“中等风险”或“低风险”。由于私有财产和 HDB 财产分类等可用特征的限制,分类特征定义如下:

  • 高风险:最低夜数< 90 天,评论数< 90%
  • 中等风险:最低夜数< 90 天,审查数量≥90%
  • 低风险:最低夜数≥ 90 天

除了增加一个新功能,我还使用标准的 1.5x +/- IQR 和超过 365 天的最小住宿时间删除了异常价格。此分析不需要的列也被删除。

df.head()

探索性数据分析

价格分布

价格的分布与上市的风险几乎没有任何关联。然而,找出上市物业的预期价格范围仍然很有趣,这样我们就可以知道我们在新加坡的*均 Airbnb 住宿的预期价格。

上市价格的这种分布似乎是右偏的。如果我们更仔细地观察其按地区的分布,我们随后会发现至少有一个地区不符合总体*均价格。这可以很容易地用一个简单的非参数多重独立样本检验来证实:克鲁斯卡尔-沃利斯检验。

像任何其他大都市一样,在中心地区看到更高的价格分布并不奇怪,因为大多数游客会在购物区/酒吧/景点/夜生活丰富的中心地区附*闲逛。与任何其他地区相比,中部地区的私有财产比例也要高得多。

列表的地理位置分布

很难通过地理位置来可视化风险列表,因为它们往往会相互重叠。下面的填充地图对于查找新加坡风险列表的分布几乎没有任何作用:

A Tableau-generated distribution of listings by risk rating

但一旦按地区划分,很明显,大部分房源都集中在中部地区:

Credits: Baval

使用 python 中漂亮的叶库,我们可以大致观察各个地区的房源数量:

folium 包允许每个列表的地理位置的交互式可视化。从这里可以很明显地看出大部分房源来自哪里,但是这些房源中有多少是符合法律的呢?

符合法律的列表

在本节中,我们将查看符合法律的列表的分布情况:

我使用评论数量作为感兴趣的特征,因为让许多不同的客人住在最低夜数较低的酒店是有意义的,这最终会导致更多的评论。从这个散点图中,我们可以清楚地看到分布在 90°/180°/365°夜标的图的区别。由于我们无法区分哪些房源是 HDB 的,哪些是私人房产,所以我假设入住至少 90 晚的房源是符合法律的。乍一看,似乎大多数上市公司都不遵守短期居留的规定。此外,某些情节似乎没有意义。以 90 晚最低 285 条评论为例。这怎么可能呢?经过进一步调查,似乎上市在 2017 年法律生效之前就已经存在,这导致了高审查数。此外,该列表只出租可能获得更高评论数的私人房间,因为它将容纳更多的独特客人。

无论如何,让我们通过一个甜甜圈图来看看上市的比例:

当我第一次观察到这一点时,我很惊讶有这么多的主人如此大胆地列出他们违反法律的财产。不过话说回来,由于 Airbnb 在预订得到确认之前不会给出房源的确切地址,这给当局抓住这些房东带来了挑战,尤其是在新加坡的大多数房产都是多层的情况下。在我的分析的最后我会更多地谈到这一点。但是现在,让我们看看风险上市的比例。

高风险上市

知道了大部分房源都集中在中部地区,让我们来看看各地区风险房源的分布情况:

再说一次,这一点也不奇怪。许多海外客人只是喜欢住在当地景点的附*,而这些景点恰好聚集在中心区域,但是不同类型房间的分布情况如何呢?

现在,我们能够看到符合法律的列表与不符合法律的列表之间的差异。与整个公寓相比,低风险房源的私人房间出租比例更高。我们可以在下面的链接中看到新加坡各个地区的房间/公寓的*均租金。

[## 2019 年新加坡租金-租房或租房的成本指南

乔安妮·波这么说,你是被这个岛国的高薪承诺和机会吸引,要搬到新加坡去了…

blog.moneysmart.sg](https://blog.moneysmart.sg/property/rent-singapore-cost-guide/)

新加坡非常高的房租使得租房子而不是整间公寓成为更明智的选择。这恰好是使新加坡成为生活成本最高的国家之一的驱动力之一。Airbnb 产生的额外费用让这种选择变得更加明显。大多数公寓租赁是通过适当的房地产代理或双方之间的私人协议来降低费用。

如果你想知道哪个街区的房源数量最多,我整理了以下 5 个街区的房源数量:

拿走

虽然还不清楚是否决定实施严格的短期居留法,但大多数私房业主似乎支持《3 个月住宿法》的决定:

2018 年下半年,URA 委托对一千多名私人房主进行的全国调查发现,大多数新加坡人支持拟议的 STA 监管框架。— CNA

[## 私人住宅物业的最短逗留时间不变:URA

市区重建局(市建局)周三(5 月 8 日)宣布,将维持现行的规例。

www.channelnewsasia.com](https://www.channelnewsasia.com/news/singapore/no-change-to-3-month-minimum-stay-duration-for-private-11513474)

URA 维持现状的决定是一个信号,表明它认识到这个问题的复杂性,需要更多时间来研究。— CNA

作为一名私人房产的居民,以及在法律生效前将我的备用房间转租给客人的人,我能够看到硬币的两面(支持和不支持)。

不支持:与 HDB 的业主相比,私人业主为现场设施支付额外费用,如游泳池/网球场/健身房/私人停车场等..这些设施有可能被游客滥用,这是非常不雅观的,特别是因为私人财产设施的维护不如公共设施那样详细。

支持:随着现代旅行的出现,Airbnb 一直是提供*价住宿的最佳*台之一,每支付一美元就能获得更多空间(例如,以酒店房间的价格购买整个公寓)。作为一个意识到自己消费习惯的千禧一代旅行者,每当我出国旅行时,我都会选择 Airbnb,因为它的价格和便利性。因此,我认为这一举措是针对那些更愿意将旅行预算花在体验上而不是住宿质量上的客人的一种手段。

看着明显不符合短期住宿法的房源比例,我真的很怀疑这项法律的严格性。也许只要客人不会造成任何干扰,就不值得去追捕房主?也许吧。

法律漏洞

列出最短住宿时间少于 90 天的房产并不一定意味着房主将房产出租给客人是违法的。

正如我提到的,当客人通过 Airbnb 预订时,将收取费用,作为房主和客人的一种保险和责任形式。房主可能会选择租赁一个月来“评估”他们的客人,然后再延长到 3 个月。

这正是我在加拿大呆了 4 个月进行冬季交流时所经历的程序。房主所要做的就是在他们的 Airbnb 列表中屏蔽剩余的 3 个月,基于信任,我们用现金支付租金。我们设法把整个公寓的租金每月减少了 100-200 美元。

如果你正在阅读这篇文章,请对来自蒙特利尔的卡尔大声喊出来!这是一个非常愉快和难忘的冬天!

其他漏洞

房主通知他们的客人让保安知道他们是要来拜访的朋友是很常见的。在新加坡,朋友在别人家过夜并不违法。

这高度依赖于不同公寓的保安。有些人会让你摆脱困境,但有些人会用他们的方式把你赶走,就像可怜的新西兰家庭所发生的那样。

你应该注意什么?

如果你仍在阅读,并愿意不顾风险在新加坡预订 Airbnb,请继续阅读。但是请理解,我只是说如果我预订的话,我会怎么做,这并不能保证你不会被驱逐,尽管风险会降低。

  • 检查评论和最*评论的数量。如果上一次好评是在你访问网站的几天后,这意味着之前的客人没有被驱逐出酒店。
  • 尽量避免在公寓里挂牌,这些地方有保安,他们负责把你赶出去。如果你必须呆在一个房间里,给你的主人发信息,让他/她去警卫室接你。这会让警卫相信你们是熟人。也不要和庞大的群体一起旅行,这只会引起怀疑。
  • 无论如何,一定要告诉你的主人,你知道新加坡的短期住宿法律,并为你即将到来的逗留寻求指导。

现在你知道了新加坡的短期住宿法,你会冒险住在 Airbnb 吗?

我知道我会的。

如果你热衷于复制我的作品供自己使用,这里有我的 Github 库的链接:

[## bobby muls/新加坡-Airbnb

在这个库中只有 3 个感兴趣的文件,这包含新加坡 Airbnb 的数据,这包含…

github.com](https://github.com/bobbymuls/Singapore-Airbnb)

尽情享受吧!

在探索和开发之间取得*衡

原文:https://towardsdatascience.com/striking-a-balance-between-exploring-and-exploiting-5475d9c1e66e?source=collection_archive---------24-----------------------

强化学习中探索与利用的困境

我们的代理在学习玩井字游戏[ Medium article ]时面临的探索-开发困境。这种困境是强化学习以及现实生活中的一个基本问题,当我们在选项之间做出选择时,你会选择:

  • 挑选你熟悉的东西,以最大化获得你想要的东西的机会
  • 或者选择一些你没有尝试过的东西,可能会学到更多,这可能会(也可能不会)让你在未来做出更好的决定

这种权衡将会影响你是尽快获得奖励,还是先了解环境再获得奖励。

直觉

假设你搬到了一个新城镇,你正在考虑从你的办公室到你的新家该走哪条路。你快速搜索了一下,发现有几种方法:

  1. 坐地铁 A 线,跟着 B 线
  2. 乘地铁 A 线,然后乘 123 路公共汽车
  3. 步行到地铁 C 线,然后是 B 线

最初,您不知道哪种方式是最好的,但是您信任技术,所以选择了选项 1,因为它的持续时间最短。你设法在第一天到家,所以你决定选择 1 作为你的回家路线。你继续利用你所知道的有用的东西,并通过选项 1 旅行。

也许有一天,你决定去探索,认为从办公室回家可能有更好的方式,所以你决定尝试选项 2。结果可能是你设法在更短的时间内回到家,或者花了你更多的时间(也许还会花更多的钱)。在尝试了选项 2 之后,确实比选项 1 花了更长的时间。可能是因为在高峰时段,交通对 123 路公交车不好。所以你决定选择 2 不好。但这是否意味着你再也不会尝试第二种选择了呢?在非高峰时间,这可能是一个更好的选择。

如果选项 3 实际上是回家的最佳方式,但决定不再探索而坚持选项 1,该怎么办?那么你将永远不会意识到选项 3 比选项 1 更好。

取得*衡

学习做出这些选择是强化学习的一部分。这意味着有时你不得不故意决定不选择你认为最有回报的行动,以便获得新的信息,但有时在探索的过程中最终会做出一些糟糕的决定。但与此同时,你想通过利用你知道最有效的方法来最大化你的回报。

那么,我们如何在充分探索未知和利用最佳行动之间取得*衡呢?

  • 充分的初步探索,以便确定最佳方案
  • 利用最佳选择以最大化总回报
  • 继续留出一个小概率来试验次优和未开发的选项,以防它们在未来提供更好的回报
  • 如果这些实验选项表现良好,算法必须更新并开始选择这个选项

ε贪婪

在强化学习中,我们可以决定要做多少探索。这是ε贪婪参数,范围从 0 到 1,它是探测的概率,通常在 5%到 10%之间。如果我们设置 0.1ε-greedy,该算法将在 10%的时间里探索随机选项,在 90%的时间里利用最佳选项。

评估不同的ε贪婪

我已经创建了一个井字游戏,代理可以通过相互对抗来学习游戏。首先,让我向你介绍我们的代理人,他们是代理人 X 和代理人 o。代理人 X 总是先走,实际上比代理人 o 更有优势赢得更多的机会。

为了找出最适合这个游戏中每个代理的ε贪婪值,我将测试不同的ε贪婪值。首先,用ε贪婪值 0.01 初始化代理 X,意味着有 1%的概率代理 X 会选择探索而不是利用。然后,特工们互相对战 10000 场,我记录下 X 特工获胜的次数。在 10,000 场游戏之后,我将ε-greedy 值增加到 0.02,代理将再玩 10,000 场游戏。

代理 X (eps 增量)vs 代理 O (eps 0.05),结果如下:

Number of games (out of 10,000) won by agent X on different epsilon-greedy value

蓝线是代理 X 赢代理 o 的次数。胜率随着ε-贪婪值的增加而降低,并在ε-贪婪值为 0.05 时达到赢得 9268 场游戏的峰值(代理 X 探索 5%的时间)。特工 O 开始赢得更多的游戏,因为特工 X 有超过 50%的时间在探索。

让我们尝试一下,代理 O 用最优的 5%ε贪婪挑战代理 X,让我们看看代理 O 在不同ε贪婪值下的表现。

Number of games won by agent O on different epsilon-greedy value

给定代理 X 具有最优ε贪婪并且在游戏中首先开始的优势,代理 O 在它能够学习游戏之前输掉了大部分游戏。

让我们把代理人 X 的 epsilon greedy 调整到 100%,代理人 X 将一直玩随机动作。

Number of games won by agent O on different epsilon-greedy value, where agent X play randomly

代理人 O 能够学习这个游戏并战胜代理人 X,在 4% epsilon greedy 时达到顶峰,在 30%时开始失败。

最后

探索在线演示并在井字游戏中挑战我们的代理。

只想以这张图结束。

[## 数据科学家:21 世纪最肮脏的工作

40%的吸尘器,40%的看门人,20%的算命师。

towardsdatascience.com](/data-scientist-the-dirtiest-job-of-the-21st-century-7f0c8215e845)

嗨!,我是叮当。我喜欢构建机器学习项目/产品,我在向数据科学写关于它们的文章。在媒体上关注我或者在 LinkedIn 上联系我。

基于分布式云计算的大数据字符串相似性匹配

原文:https://towardsdatascience.com/string-similarity-matching-for-big-data-using-distributed-cloud-computations-ea7cfc918b9f?source=collection_archive---------18-----------------------

将 BigQuery、Python 的 Scikit-Learn & Dask(分布式)和 Kubernetes 组合在一个项目中。

Photo by daveynin on flickr

e̶x̶i̶s̶t̶e̶n̶t̶i̶a̶l̶问题设置

像大多数故事一样,我们的故事始于一项雄心勃勃的事业!我们得到了两个大型数据集(来自 BigQuery 中的两个表)。一个包括来自 Google Play 和 iOS 应用商店的所有应用名称——大约 1400 万个条目——我们称之为“干净的”应用名称。另一个包含大约 5K 个“脏”应用程序名称。肮脏是指遗漏的单词、某些单词的拼写错误、涉及操作系统或其他信息的附加单词等。可以通过查看“将所有东西放在一起并运行它”一节来找到例子。

Choose wisely — Photo by W.carter on Wikimedia Commons

除了数据集,我们还为提供了蓝色和红色药丸。我们认为自己足够勇敢,决定服用红色药丸,接受挑战,寻求残酷的真相。

请求是将“脏”数据集中的条目与“干净”数据集中的条目进行匹配,然后将结果存储为查找表。

旅程——测试和失败

在成为男人和面对 t̶h̶e̶ ̶r̶e̶a̶l̶ ̶w̶o̶r̶l̶d̶制作之前,一个男孩需要在操场上发展他的技能。一个奇特的例子是谷歌合作实验室,这是一个托管在云上的 Jupyter 笔记本电脑,提供免费的强大计算资源(包括 GPU/TPU),这是第一次测试运行的地方。

计算机科学家会把我们的问题归类为*似字符串匹配问题。这些问题的传统解决方案使用不同的字符串度量来得出两个给定字符序列之间的距离。例如Jaro-Winkler 距离和 Levenshtein 距离。

我们的第一个尝试是使用 fuzzy wuzzy ,一个实现 Levenshtein 距离的 Python 库。(请保留下面的粗略数字,而不是适当的基准。最终的差异如此显著,以至于完美的精度并不重要。)Fuzzy wuzzy 需要大约 15 分钟来计算来自“脏”数据集的单个条目和来自“干净”数据集的所有条目之间的距离。重复这个过程 5K 次相当于大约 52 天,这比我们希望的每天至少运行一次的过程稍微多了。如果时间就是金钱,我们早就破产了!

最终(目前)算法

为了避免严重的贷款和破产,采用了一种略有不同的方法:通过数字的力量提高业绩。基于TF–IDF将字符串数据集转换成向量,以便使用余弦相似度。该算法的核心之前已经用于类似的问题这里,这里这里和这里这里。为了进一步提高性能,本文引入了一些修改,以支持在云 Dask 客户端上运行分布式计算。

为什么是达斯克?Dask 是什么?

Dask 是一个库,它提供了在本地扩展 Pandas、Scikit-Learn 和 Numpy 工作流的方法,只需最少的重写。因此,普通的 Python 操作可以在不同的节点/CPU 内核之间分布/并行化。它也可以(但不是必须)在分布式集群上运行。也就是说,Dask 只不过是提供基础设施来将数据(如 Pandas 数据帧)分割成不同的节点,然后使用多个内核执行操作,并确保分割数据之间的通信。

设置事物

注:下面的 干净 命名约定分别用于基线和待匹配数据集。

下面是这个项目使用的基本库的列表:

从 BigQuery 导入数据

为了从 BigQuery 获取数据,我们使用了 Python 的 BigQuery 客户端库。客户端将数据加载到 Pandas 数据帧中,该数据帧立即转换为 Dask 数据帧。Dask 数据帧只不过是分布在许多分区( npartitions )上的 Pandas 数据帧的组合,具体取决于 CPU 架构。

转换为向量

使用 tf-idf 将数据帧从字符串转换为向量实际上需要 3 行代码:

使用 Scikit-Learn 中的TfidfVectorizer函数并通过定义分析器函数来初始化矢量化函数(参见下面的信息)。干净的数据帧用于定义特征向量(基于分析器),同时计算干净的 tf-idf 矩阵(fit_transform),然后计算脏的 tf-idf 矩阵(transform)。

分析器是用于将每个应用程序名称(字符串)分割成较小部分的功能。从干净数据帧的所有条目中收集所有这些较小的比特定义了特征向量。如果一个特定的应用程序名称包含这一位,那么当转换为向量时,它将在相应的位置获得一个浮点值——如果不是 0。浮点值取决于该位在应用程序名称中出现的次数,并且该值被修改,使得该应用程序名称的向量被归一化(向量范数等于 1 个单位)。举个例子:如果分析仪定义如下

干净的数据帧简单如下,

那么特征向量具有这样的形式:

***['ACE','AGR','BOO','CEB','EBO','FAC','GRA','INS','NST','OOK','RAM','STA','TAG']***

干净的数据帧被转换成下面的向量矩阵(输出矩阵以稀疏矩阵(CSR)格式给出,但在这里显示为数组)

***[[0.40824829 0\.         0.40824829 0.40824829 0.40824829 0.408248290\.         0\.         0\.         0.40824829 0\.         0.0\.        ][0\.         0.37796447 0\.         0\.         0\.         0.0.37796447 0.37796447 0.37796447 0\.         0.37796447 0.377964470.37796447]]***

余弦相似性

一旦干净和脏数据集处于向量模式,我们就可以继续获得余弦相似性得分矩阵。在干净和脏的矢量化矩阵之间执行点积足以给出余弦值,因为向量是归一化的。即,点积与余弦(相似性)一致。

为此,使用了以下代码:

这里使用了 sparse_dot_topn 包,它提供了一种快速的方法来执行稀疏矩阵乘法,然后使用 Cython 进行 top-n 乘法结果选择。余弦相似性将以稀疏矩阵形式给出,其中行对应于脏数据集,列对应于干净数据集。

使用这个相似性矩阵,我们可以提取在 干净 之间匹配的条目以及它们的相似性分数,使用:

上传到 BigQuery

最后但同样重要的是,我们需要将匹配过程的结果作为查找表上传回 BiqQuery。这样做的代码如下所示:

比起算法的千言万语,你会更喜欢一张图片吗?这是它的简图:

部署(在 Kubernetes)

节由 盖亚尔 撰写

Dask 是一个如此通用的工具,甚至通过使用其内置的 Pandas API 支持在本地运行它也能让您受益。然而,当它在分布式系统上运行时——也就是集群——显示了它的全部能力。通过与 DevOps 工程师的合作,我们可以访问部署在谷歌云*台(GCP)上的托管 Kubernetes (k8s)集群。在大多数情况下,在获得对集群的访问权后,可以使用 helm package manager 通过运行以下命令在 k8s 上轻松部署 Dask:

***helm install —name my-dask stable/dask***

过一会儿,你会部署 5 个吊舱:

  • 调度程序—主 Dask 任务管理器
  • 3 名工作人员—处理数据和应用操作
  • Jupyter 舱——一个预先设置的 Jupiter 实验室舱,是与 Dask 互动的好方法

为了获得部署后的 pod 列表,我们创建了一个简单的 shell 脚本。运行它,它将显示所有新创建的 pod 的 IP 地址列表:

如果你不再需要它,或者你弄坏了什么东西,想要一个新的开始,你可以跑:

***helm delete dask —purge***

是不是看起来太容易不真实了?你说得对;通用的解决方案很少奏效。

Made with imgflip.com

这里有一点定制,使它为我们的需要工作。

在最初的测试之后,我们已经发现了几个在使用 Dask helm 时的问题**

  1. 它有几个 bug。幸运的是,所有的修复都在官方回购中作为未决的拉请求(PRs) 存在,但是没有被合并。
  2. 我们需要的一些软件包缺少默认图像。
  3. 一个包在 pip 中没有二进制版本,并且在pip install ...部分失败。
  4. 默认的 pod 配置不足以处理我们的大型数据帧。

继续讨论解决方案:**

1。头盔配置中的错误
幸运的是,这些错误已经通过待定的 PRs 在官方回购中修复了。要应用它们,我们必须制作一个 repo 的本地克隆,并将所有 PRs 与解决方案合并为补丁。这当然不是理想的解决方案,但却是一种快速有效的方法。
另一个问题是回购协议中定义的 Jupyter Lab 版本有一些 UI 问题。为了克服它们,必须通过指定包版本来升级。方法包含在第二个问题的解决方案中。

2。由于我们的数据管道是基于 GCP 的,我们需要包含 SDK 包和一些其他的库。幸运的是,Dask helm chart 支持使用 YAML 配置文件。因此,可以指定包含哪个pipconda包,分配给工人多少 RAM 以及更多。
在我们的例子中,我们添加了以下内容:

大多数软件包将通过conda使用conda-forgegaiar通道安装(见下文为什么也需要这个通道)。其余通过pip安装。

3。缺少二进制包版本
为了加速稀疏矩阵乘法,我们使用的是sparse_dot_topn,在算法部分提到过,它依赖于 Cython。像这样的包通常以两种方式提供:或者作为二进制预编译包,或者当库在安装主机上编译它的一部分时。在我们的例子中,我们遗漏了二进制发行版,这意味着我们应该在已经“不那么轻”的映像中添加编译工具。相反,我们选择了另一种方式。我已经有了在自己的渠道中构建和维护 conda 包的经验。conda 的一个显著优势是它以二进制方式发送包,这正是我们所需要的。
根据 pip 分布使用 conda 配方定义 YAML 文件相对容易:

有了这个配方,您就可以运行conda build命令并将包上传到您可以访问的频道。然后,可以用conda -c CHANNEL_NAME PACKAGE_NAME或者在我们的例子中用conda -c gaiar sparse_dot_topn来安装这个包。我准备了两个版本——一个用于 Linux,另一个用于 MacOS(因为它在安装上也有一些问题)。

4。吊舱的有限资源
这部分是具体情况,取决于 Dask 正在运行的任务类型和约束条件。在我们的例子中,我们需要更多的 RAM,并希望定义每个 pod 可以消耗的内存上限。这通过配置 YAML 文件再次完成:

也就是说:每个员工的最低限额是 3G,但是如果需要的话,可以申请 6G。

下面是 Dask 在 GCP k8s 上工作的简单演示:

把所有东西放在一起并运行它

结合上述算法和部署,我们的代码在大约 20-30 分钟内执行匹配过程;与最初的 52 天相比,速度大大加快了。😆

这是我们一次运行的输出表中的一小部分:

这张表和获取它所需的执行时间表明,红色药丸可能是这次更明智的决定。

编后记

让我们试着用一句话来说:部署在 Kubernetes 中的 Tf-idf 矢量化和余弦相似性结合高效的稀疏矩阵计算和并行执行操作使用 Dask 的分布功能,被证明是处理大规模字符串相似性问题的非常有效的方法。

特别感谢 盖亚尔·白木拉托夫 做出部署并撰写相应章节。

大脑和神经元的结构。

原文:https://towardsdatascience.com/structure-of-brain-and-neurons-examination-of-rewiring-in-brain-38f5a7c0d850?source=collection_archive---------31-----------------------

用建议的大脑和神经元结构检查脑瘤切除。

当我们谈论大脑时,我们首先说什么?我们说它太复杂了,以至于我们仍然不能完全理解它。我将对大脑的结构做一个假设,并且,我将检验“大脑重塑自身”中提到的情况。

Photo by Daniel Hjalmarsson on Unsplash

神经的结构是什么?

神经只是二元开关。当它们用于一个信息时,它们是 1。不使用时为 0。它是如何发生的?当一个信息到来时,该信息被连接到离输入门最*的空神经元(0)。举一个基本的例子,让我们假设当我们看到一只狗时,一个连接并靠*视觉输入门的神经元被激活。我们看到的狗的图像被分配给那个神经元。当我们看到同一只狗处于与我们之前看到的完全相同的状态时,神经元被激活,这样我们就知道它是同一只狗。如果我们很长时间看不到那只狗会怎么样?那只狗的图像到神经元的分配被删除,这意味着我们忘记了那只狗。那么,我们如何忘记呢?

大脑中有一个遗忘规则。如果分配给一个信息的神经元长时间或以必要的频率不被激活(如果任何电流不通过该神经元),则分配给该神经元的信息被擦除。

大脑的结构是什么?

首先,正如大家所说,我们有神经元和轴突。大脑只由神经元和轴突组成。在大脑的所有区域,神经元的类型完全相同。在大脑中,没有为执行特定任务而保留的特殊区域。这些场是由大脑的一般工作原理创建的,在我解释了它的结构之后,我也会解释。由于学习时间的原因,这些区域用于特定的任务。我这么说是什么意思?

第一个获得输入并将其处理到大脑的地方是传感器首次连接的地方。所以,当一个输入来临时,它首先会被放置在大脑中与输入相连的最*的空神经。

当一个婴儿出生时,它实际上感觉到的第一件事是光(婴儿不能像正常人一样看东西,它只能感觉到光)。所以,大脑的第一个输入来自眼睛。眼睛首先与大脑的后场相连。因此,婴儿获得的视觉输入开始被放置在最靠*视神经连接区域的空神经元中。

这个条件适用于人体内所有的传感器活动。听觉信息开始被放置在最靠*听觉输入门的神经元中。

包含复杂认知行为、决策、社会行为和个性的区域是什么?

要回答这个问题,我们先来看看哪个地方离听觉、视觉等输入门最远……答案是额叶。我们分配给神经元的第一个信息来自我们的传感器(输入门)。大脑中离这些区域最远的地方包含了负责最复杂信息的神经元。我们通过传感器获得并分配给神经元的信息是更复杂信息的基础。首先分配的神经元代表最基本的信息,而最后分配的神经元代表我们学习的最复杂的信息。

在图 1 中,大脑的结构以简化的结构示出。圆圈表示神经元,神经元之间的箭头表示轴突,用红色绘制的神经元表示被分配给第一听觉信息的第一神经元,用黑色绘制的神经元表示被分配给第一视觉信息的第一神经元,Hear6 表示包含听觉信息的神经元之一,See7 表示包含视觉信息的神经元之一,Hear6+See7 表示被分配给与 Hear6 和 See7 中的信息相关的复杂信息的神经元。

Figure 1 - An Example of Brain Structure

对“再造自身的大脑中讲述的案例的检验

这个案子是关于一个男孩的。这个男孩的大脑后部有一个肿瘤。医生切除了肿瘤,切除了他大脑右半球的 1/3。手术后他可能会失明,因为被切除的区域被分配给了视力,但他没有失明。

我将从文章中提取部分内容,并通过将案例与我上面解释的大脑和神经的结构联系起来进行解释。我不会用男孩的名字,因为他的父母可能不想要。我就写“男孩”来表达他吧。

外科医生切除了对处理通过我们眼睛的视神经传递的信息很重要的脑叶,使我们能够看到,同时它们对识别面孔和物体以及贴上相应的名字也很关键。没有办法确定这个男孩手术后是否能再次看见,认出他的父母,甚至正常发育。

  • 1)根据我的大脑结构模型,大脑被切除部分的神经会导致男孩失去信息。如果基础神经元(首先连接到输入门的神经元)被移除,男孩将在第一时间看到问题。但是过一段时间后,他的视力会在大脑的另一边发育,就像新生儿一样。分配给视觉信息的新区域将是大脑中最靠*视神经的地方。如果分配给更复杂视觉信息的神经元被移除,那么男孩的视觉不会受到显著影响,但他拥有的更复杂的视觉信息将受到影响。他可能无法识别和命名周围的物体和人。一段时间后,男孩将能够认出他的父母和物品,同时他也能正确地说出他们的名字。因为连接到分配复杂视觉信息的被移除神经元的基础视觉神经元仍然存在,男孩的大脑将使用与具有基础信息的神经元最接*(剩余)的神经元来分配复杂视觉信息。

Figure 2 — Closest Neurons to Optical Nerve (L1, L3, L6, R1, R3, R6)

尽管失去了超过 15%的大脑,这个男孩还是很好。

唯一的例外是他的左眼失去了周边视觉。

“它不像是模糊的或者只是那里黑。就像,都是混合的,”男孩说。

  • 2)正如我上面解释的,这个男孩会没事的。首先认识到的问题是他留下了他的周边视觉。但是周边视觉的问题并不像他说的那样是一片漆黑或者模糊。所以,他实际上没有失去视力,他的大脑只是忘记了,因为分配给这些部分的神经元被移除了。基本上,他的周边视觉就像一个新生儿的视觉。他只能从他周围的景象看到原始的视觉输入。

他的左脑承担了他现在基本缺失的右脑的所有责任和任务。

  • 3)如上所述,被去除的神经元被分配给视觉信息。当它们被移除时,新的神经元将被用来分配这些信息。他大脑的哪一侧会被使用并不重要。大脑中最靠*视神经的神经元将被用于此。

大脑具有可塑性(可伪造的)改变自身的能力这一事实并不新鲜。较少了解的是大脑究竟是如何做到的。

据说大脑锻造自己的方式是未知的。按照我的大脑结构模型是怎么做到的,在第一篇里讲了。

男孩大脑的剩余结构能在多大程度上接管他被移除的那部分大脑的功能?

答案是肯定的。男孩大脑的剩余结构可以接管他大脑被移除部分的功能。他将和任何人一样正常。

科学能描述大脑如何进行这些变化,一直到细胞水*吗?

下面的图 1 解释了这些变化。

Figure 2 - How information is received and assigned to neurons

当男孩癫痫发作时:“我的大脑就像冻僵了一样,”他说。“我真的很困惑,然后我真的感到恶心,呕吐,然后我又会表现得很正常。”

大脑中的电活动紊乱会导致癫痫发作。神经元在没有任何输入的情况下开始随机传递电流。原因是他得了肿瘤。肿瘤细胞在大脑中产生了无计划的电活动。这就像给你的神经元一个随机输入。因此,他会感到困惑和恶心。当随机输入结束时,癫痫发作结束,他又感觉正常了。但长时间癫痫发作会导致他的神经元结构紊乱,这可能会导致永久性记忆丧失或神经元功能丧失。这就是为什么手术对他来说至关重要。

“我们知道儿童的大脑具有可塑性,我们不断在大脑中创造新的算法来生活。但除此之外,当你癫痫发作时,这些被破坏的电网络会阻止任何有意义的重新映射。”克里斯蒂娜·帕特森说。

意义重映射有问题的原因是不*衡的电活动。如图 2 所示,就神经元的电荷而言,在神经元之间产生了新的连接。

手术后,男孩认出了他的父母,但他无法将他们的脸和名字对应起来。这个问题几天后就自行解决了。

看起来,这个男孩也失去了一些连接他父母名字和面孔的轴突和神经元。在图 2 中可以看到之前分配了信息的两个神经元之间的连接创建的例子。手术后,男孩失去了大脑中的这种联系。所以,他不能匹配他父母的脸和名字。

儿童的大脑年轻,仍在发育,因此最有可能发生神经可塑性变化。

神经元是按顺序分配的。我告诉他们,离输入门最*的神经元开始给他们分配信息。当我们变老时,我们学到的信息变得更加复杂。正因为如此,失去负责基本信息的神经元对成年人的影响可能比男孩更大。但是,如果成年人失去了分配给复杂信息的神经元(例如从额叶移除一部分),则更容易恢复丢失的信息,同时对成年人的生活影响较小。

20 世纪 60 年代,科学家 David Hubel 和 Torsten Wiesel 绘制了小猫的视觉皮层,以了解视觉是如何处理的。然后,在一个公认的可怕的过程中,科学家们合上(缝合)了研究中一只小猫的眼睑。打开眼睑后,他们发现小猫大脑中负责处理来自那只眼睛的图像的视觉区域没有发育,导致小猫的那只眼睛失明,尽管这只眼睛在生物学上没有任何问题。研究人员发现,如果小猫的大脑正常发育,它们必须在出生后的第三周到第八周之间能够看到周围的世界。

正如我们所见,被缝了一只眼睛的小猫用被缝的眼睛看不清楚,但它可以很好地使用另一只眼睛。David Hubel 和 Torsten Wiesel 关闭了眼睛到大脑的输入门。因为没有输入,所以在输入门附*没有分配给视觉信息的神经元。

但是这项研究的另一个发现被证明更加重要——并为胡贝尔和威塞尔赢得了诺贝尔奖。“小猫的大脑中被剥夺了闭眼输入的那部分没有保持空闲,”Doidge 写道。“它已经开始处理来自睁着的眼睛的视觉输入,就好像大脑不想浪费任何‘皮质不动产’,并且已经找到了自我重组的方法。”

一段时间后,即使没有来自闭眼的输入,也需要更多的神经元来分配来自睁眼的视觉信息。最*的地方是另一个未使用的一侧,靠*闭眼的视神经。因此,他们继续从那里接受信息。

在男孩的案例中,问题是完整无损的左半球是否会恢复缺失的三分之一大脑的功能,特别是面部识别任务,这通常是由右半球执行的。

通过使用被称为扩散张量成像的神经成像技术分析大脑扫描,Behrmann 发现大脑的白质(强调多个神经区域之间通信的电线)实际上发生了变化,扩散张量成像显示了水如何沿着大脑的白质束流动。之前没有连接的大脑区域产生了新的连接,这是一个神经可塑性的例子,可以保护大脑功能。但是科学家仍然不知道是什么引发了白质细胞的这种行为。

上面的段落保证了我在图 2 中展示的结构和功能。

在玛琳·贝尔曼对这个男孩和其他九个孩子(他们都失去了左半球或右半球的部分区域)进行的后续研究中,包括男孩在内的八个孩子显示出绝对正常的视觉功能。两个没有死的孩子在手术前由于癫痫发作造成的脑损伤更严重。

正如我上面所说,癫痫发作可能会导致永久性记忆丧失或神经元功能丧失。在无功能神经元的情况下,如果在大脑中有足够数量的健康神经元留在足够靠*输入门的地方以进行连接,则视觉信息仍然可以分配给那些健康神经元。如果不再有健康的神经元留下,或者如果剩余的健康神经元没有足够*以在神经元之间形成极性从而使它们连接,那么被剥夺的视觉信息不能被分配给新的神经元。

泰勒·阿贝尔和贝尔曼指出,甚至可能是这样,男孩大脑中发生的一些重组在他预定的手术之前就开始了。这不是贝尔曼能证明的,因为所有对男孩的研究都是在手术后进行的。

“当你的大脑出现异常导致癫痫发作时,这种异常实际上会导致大脑重组,或者在手术实际发生前就开始重组,”Abel 说。“但有时会发生的另一件事是,癫痫发作会影响大脑的功能,大脑不会重组。”

根据提出的神经元和大脑的结构,如果癫痫发作是局部的并且不影响整个大脑,那么靠*受癫痫发作影响的神经元的未使用的神经元可以连接到受影响神经元的基底神经元来分配信息。由此,信息被检索。

所有哺乳动物的大脑结构都一样吗?

答案是肯定的。结构相同,但神经元的数量与输入门结构和输出门结构(手臂、舌头、嘴、腿等)相同。)都不一样。神经元的数量只能影响分配给神经元的信息量。但是输入结构和输出结构是人类和所有其他哺乳动物的唯一区别。如果我们能够将狗的输入门改造成与人类完全相同的输入门,我们将会看到狗能够像人类一样说话。我们还需要记住,哺乳动物的输入门已经足够发达,可以像我们一样感受到痛苦和悲伤。所以,当我们想起对动物的不良行为时,会变得更加悲伤。因为对人和对动物做出那些不好的行为没有任何区别。

泰京·埃夫林·奥兹默默

构建成功的数据科学项目

原文:https://towardsdatascience.com/structuring-a-data-science-project-for-success-ff3ecbdc8187?source=collection_archive---------22-----------------------

我在微软实习的经验教训

I wonder if all this was written for the stock photo. Looks real.

数据科学项目是棘手的野兽。目标是获取大量原始数据并产生有价值的可操作的见解。问题是,数据科学项目本质上是探索性的——你不知道什么方法会奏效,也不知道你会找到什么见解。所有这些不确定性是一些常见项目疾病的温床:

  1. 项目蠕变:随着项目的进行,项目的范围逐渐扩大。如果不加以处理,项目范围将扩大到无法完成的程度。这种疾病通常是由好奇心和注意力之间的不*衡引起的。
  2. 项目停滞:你遇到了一个 bug 或数据问题,它会让你停滞几天甚至几周,让你没有动力去做项目。治疗的第一步是接受你停滞不前的事实,然后坦率地和你的团队谈论你面临的问题。

通过构建您的项目,您可以开发管理不确定性的方法,避免一些项目疾病,并按时完成项目。

在微软实习期间,我在教育客户洞察研究团队工作。该小组的目的是使用数据来帮助定义微软在教育领域的战略。我今年夏天的项目是分析教育机构如何使用微软的应用程序和服务。这是一个广泛的项目想法,而且是有目的的——我的经理想知道我会用它做什么。以下是我收到的建议和学到的经验。

1.设定截止日期

为什么在学校学一门新语言比在家里容易?事实是,许多人在截止日期、明确的目标和想象不到的后果方面做得很好。我是他们中的一员,你可能也是。

我打印出我实习的三个月的日历,然后垂直地粘在一起。我用蓝色标出了我将要出差、参加会议或不参与项目的日子,用红色标出了最后期限。在你的办公桌旁放一个可视化的时间表(俗称“日历”),可以很容易地检查你的进度。贴在我办公桌附*也增加了一点隐性的社交压力。我怀疑是否有人花时间看我的日历,但是清楚地定义并公开发布我的截止日期让我更倾向于遵守它们。

个人期限是脆弱的;他们需要所有能得到的外部压力。

Your calendar need not be Instagram ready.

以下是一些你可能想包括的截止日期:

  1. 提案初稿:你第一次发给你的经理/团队的文件(开始后 1 周)
  2. 提案终稿:在你发出这份提案后,你可以对项目做一些调整,但你必须开始全职处理数据(开始后 1.5-2 周)
  3. 签到:记下一些常规的,让自己负责任
  4. 开始停止:选择一个日期,在这一天你将停止全职编码,并开始拼凑一个故事(在最终演示前 2 周)
  5. 首次演示:向熟悉项目的小组演示,收集初步反馈(最终演示前 0.5-1 周)
  6. 展示日
  7. 报告/演示最终草案

2.尽早与利益相关者交谈

最糟糕的事情莫过于有人在谈话中途插嘴,提出不相关但却很坚定的观点。数据科学就是这样。如果你是一个组织或项目领域的新手,你可能不知道足够的信息来产生好的见解。抱歉。

然而,您的组织中可能有许多人已经在该领域工作了一段时间,对业务如何运作有直觉。你应该尽快和这些人谈谈。如果你正在研究顾客行为,和销售或设计部门谈谈。如果你打算提供策略建议,和项目经理谈谈。

了解他们的工作。描述你的项目,让他们思考你的目标。这可能需要时间,但最终你可能会梳理出有价值的方向。对我来说,我发现与项目经理、用户研究人员和工程师交谈很有帮助。我和他们谈了很多次,但是最重要的是早期的谈话,那时我正在制定一个提案并确定项目的范围。

3.确定项目范围

如果你像我一样,你会有一个宏伟的想法,你的项目将使用最先进的算法,并将解决现在和未来永远的问题。这个宏伟的想法实际上可能需要 6 个月和 4 名工程师来实现。

你可能不会实现这个伟大的想法。

你应该确定项目的范围。

Don’t lose sight of the trees for the forest.

你的第一个目标应该是完成最小可行分析。想一想利益相关者看重什么,调整你的项目,这样你就可以用简单的方法生产出更多的东西。将一些放弃的目标作为达成目标。当你做最后陈述时,有人问“你在 Y 的情况下考虑过 X 吗?”,你可以冷静地回答,“是的,我可能应用了方法 Z,但是那超出了项目的范围。”

一个更简单的完成的项目比一个花哨的不完整的项目要好。

4.开始工作

当你开始处理数据时,事情会变得非常糟糕,而你对此无能为力。实际上是有的,你应该尽快开始处理数据。不要忽视计划阶段,但是不要忘记一些数据流会让你抓狂。最好能快点发现。在我耗时两周的项目中,浏览多层客户许可是一件非常痛苦的事情。我没有办法预测它,它阻止了我实现一些目标,但这没什么大不了的。

5.开始停止

如果你在期末报告前三天尝试一些新奇的方法,你可能做错了。记住,你需要传递的是洞察力,而不是方法。项目经理们更看重一个奇特的算法,而不是你将见解翻译成英语的想法。一位实习同事创造了这种“社交数据”。我觉得行业行话就是“讲故事”。

Imagine a cogent, data-driven Scheherazade. Now become her.

是的,你的分析是开创性的,全世界都因为没有花时间去理解它而变得愚蠢。但事实就是如此。你必须做 80%的艰苦工作,将你的结果翻译成通用语言,并开发令人难忘的可视化或仪表板。计划至少花整整一周的时间来做这件事。

在一次与工程师的会议上,我问了工程师一个关于业务的问题,他拿出了我团队中的一位数据科学家几年前制作的仪表板。我的经理指出,这应该是每个数据科学家的梦想。您希望开发易于理解、团队以外的人在日常工作中采纳和引用的见解。思考永恒的研究。

6.不要觉得有义务报告你所学到的一切

还记得不久前你去的那个有很多数字的无聊演示吗?很可能是因为缺乏焦点。关注与您的提案目标最一致的可行见解。回想一下你在高中英语课上学到的说服性写作。其中一个关键因素是了解你的受众。试着考虑只发布能打动观众的内容:利益相关者。因为你早就和他们谈过了,这应该不会太难。

重要的是,你的项目应该讲述一个有清晰开头、中间和结尾的故事。“结尾”应该包括你对利益相关者的明确建议。即使我有一点不确定,我也经常喜欢把一个想法写下来,这样我就有东西可以辩论,而不是错过一个发展思路的机会。但是你应该确定你画了这条线。

7.编写可重用的代码

使用函数和类来保持代码的模块化和整洁。编写测试——它们不仅仅是为软件工程师准备的!众所周知,机器学习算法很难调试。在我实习期间,我最初根据客户对应用程序和服务的使用情况生成了一个客户亲和矩阵。然而,几天后我才意识到,我用距离而不是相似性得分填充了这个相似性矩阵,我的结果是谎言。(我修好了它,一切都很好。)防止谎言传播;编写测试。

代码 50%是计算机指令,50%是为其他人编写的计算机指令文档。文档记录良好的代码加上写得很好的演示或报告应该会给你的分析带来最大的生存机会。

我希望我学到的经验能对你的项目有所帮助。祝你好运!

特别感谢 Sooraj Kuttykrishnan、Jodie Draper 和微软 EDU 团队的其他成员,感谢他们给了我一个美好的夏天和永恒的指导。

如果你对这篇文章有想法,或者想了解更多关于我所做的工作,请通过媒体关注我,并通过 LinkedIn 与我联系。

结构化数据预测未来,又名项目通量电容器

原文:https://towardsdatascience.com/structuring-data-to-predict-the-future-aka-project-flux-capacitor-7133715d7e57?source=collection_archive---------26-----------------------

数据准备是一个好的机器学习(ML)模型的核心,但获得正确的数据需要时间。很多时间!不要害怕。

为了帮助传递一些知识并使您的过程更容易,我和我的团队发布了代码来支持、加速甚至改进您构建 ML 模型的方式,如倾向模型、客户生命周期价值模型、推荐系统等。

大卫、凯西和鲁克山为开发这一解决方案并使之成为可能而付出的努力让他们感到无比自豪。

我们走吧!

在幕后,代码利用谷歌云数据流来运行 Apache Beam 管道,并利用谷歌云 BigQuery 来读取和保存。将大量数据转换成 ML ready 格式的强大而快速的方法。

我们已经优化了代码,可以插入到一个 Google Analytics BigQuery 表中,但是如果有用的话,也可以插入到其他 BigQuery 数据源中。输入您的 BigQuery 表,运行管道,然后——瞧——输出带有结构化特征和标签的新 BigQuery 表。准备好使用你最喜欢的 ML 工具来训练一个 ML 模型,比如 AutoML-Tables,BigQuery ML,Tensorflow,Python sklearn…等等。

渴望一头扎进去?去吧…

  • 在Google cloud platform/cloud-for-marketing/…GitHub Repo中检查 ML 数据窗口管道代码。
  • 说明如何使用的自述文件的直接链接。
  • 我们还发布了一个关于为个性化准备 ML 就绪数据的 Google Cloud 教程。

或者,如果你能坚持听我说几分钟,了解通量电容管道如何构建数据对于理解其价值非常重要。我试图向我的非技术伙伴(yikes)解释这种技术,所以决定在这里发表我的想法,作为一个更非官方的——希望更有趣的——解释。

为什么要通量电容器?

我们的正式项目名称是 ML 数据窗口管道。尽管如此,一切都需要一个有趣的名字,当我们根据过去发生的事情构建数据来预测未来时,Flux Capacitor 似乎很合适。正是这些数据让“时间旅行”成为可能,🧀。好了,先把这些劣质的东西放在一边,让我来解释一下它是做什么的。

“医生”布朗想买辆车

让我们考虑一个随机的人,称他为医生。在这个例子中,Doc 从我们的网站上购买了一辆新车。

Image Christopher Lloyd as Dr. Emmett Brown — Back to the Future

我们的汽车网站上有谷歌分析设置,让我们记录和查看文件的浏览活动。让我们记住,实际上我们只查看匿名指标(我们只是为了好玩才使用文档参考)。

Image made by author — User timeline of events

这是代表活动的时间线,蓝色方框表示导致购买事件的交互。每次互动都有一些我们可以从谷歌分析中获得的指标,例如浏览器、一天中的时间、访问的页面、点击量等。

让我们从一个时间快照来看这个时间线中的细节,并将该快照称为日期 d 。

Image made by author — User timeline of events from Date d

现在,关于日期 d ,我们可以开始回顾过去一段时间,并将文档的会话信息汇总在一起。这个定义的时间段被称为回顾窗口

Image made by author — User timeline of events with Features

在这个例子中,Google Analytics 交互被聚合以创建新的指标,例如最频繁的页面、浏览器、活跃天数、总点击数等。它们代表了我们将用来训练 ML 模型的特征。

接下来,从我们的日期 d 开始,我们通过指定的时间量来预测未来,并将此称为预测窗口

Image made by author — User timeline of events with Features and Label

因此,就数据而言,如果购买发生在相对于日期 d 和日期 d预测窗口内,那么它发生在日期 d 和日期 d 。换句话说,该标签基于在预测窗口期间是否发生了购买事件。

这是这里的关键,所以我们的模型是根据未来会发生什么以及如何预测来训练的。

Image made by author — User timeline of events with Features and Label

这代表了我们将用来训练 ML 模型的标签。

一旦我们为文档——我们的匿名用户——提取了与 d ate d 相关的特征和标签,我们就会在表中看到一行,如下所示:

Image made by author — User Features and Label for Date d

然后,我们为网站上的所有用户在日期拍摄这些快照。

Image made by author — Users timeline of events with Features and Label

生成的表格看起来像这样:

Image made by author — Users Features and Label for Date d

然后,我们以间隔 w (例如,一天、一周…等)将日期 d 移动一个设定的滑动窗口,以针对 d + w、d + 2w…等为所有用户及时创建更多快照。

Image made by author — Users snapshots over time

随着时间的推移,通过多个快照,我们的数据集可以了解数据如何变化以适应季节性(最*和频率信息)。

“伟大的斯科特!”

结果。一个强大(大)的数据集,准备好训练你的 ML 模型。

最后要记住的是成本。简单运行 ML 数据窗口管道代码,比如使用 Google Analytics 样本数据集,应该是最少的。然而,生产成本将取决于您的数据大小。管道被设计为尽可能高效,但请注意谷歌云数据流定价指南和谷歌云*台定价计算器,以确保没有意外。

我希望这是有用的,我们很乐意在评论区看到你是如何应用它的。

PS。如果你从未看过电影《回到未来》,我向你道歉!因为许多这些类比/图片可能看起来有点随机。

Image Meme — Made at imgflip

在 Raspberry Pi 上运行对象检测的困难

原文:https://towardsdatascience.com/struggles-of-running-object-detection-on-a-raspberry-pi-fa61b50a3b9f?source=collection_archive---------19-----------------------

斗争是真实的!

Frustrated man (Image by Gerd Altmann from Pixabay)

你是否曾经在阅读了操作指南或 github 自述文件后兴奋不已,却发现事情并不像他们说的那么简单?

我遇到过无数这样的例子,我发现我下载的一些解决方案或者我遵循的一个教程简单地工作了,这是一个罕见的时刻。不过那一刻!如果你对此有共鸣,也有自己的故事可以分享,我很高兴听到这些(欢迎在下面留下评论)

现在,我将分享我在 Raspberry Pi 上运行对象检测的奋斗故事。

我喜欢尝试新技术,并看到它的工作情况。就在一年前,我接触到了 Raspberry Pi,这是一款小型、经济的设备,你可以在上面安装摄像头和其他传感器,部署你的 python 代码,并立即看到它的工作情况。多酷啊。我立刻从 Raspberry pi Australia 的网站上为自己订购了一台,配有 Pi 相机、Raspberry Pi Sense 帽子和一个小外壳,迫不及待地想玩它。

当我在接下来的一周拿到 Raspberry Pi 3 Ultimate Kit 时,我已经准备好了对象检测 python 脚本,可以在 Pi 中复制并运行它。我打开包装,取出圆周率和圆周率相机,组装好,放入黑色外壳,并连接到电源。我没有鼠标,也没有键盘,我有一台电视和一根 HDMI 电缆,这些都在树莓 Pi 套件中,所以我的第一个挑战是将其连接到互联网。我的第二个想法是将我的 python 脚本复制到 Pi 中。几个小时的研究和尝试不同的东西,人们不得不说在线,让我的 Pi 连接到互联网和 VNC 浏览器,我现在能够从我的笔记本电脑远程连接到它,并复制我的 python 脚本。

如果你正在努力使用 wifi 将你的 Pi 连接到互联网并远程访问它,使用这个教程“ 直接连接到你的树莓派 ”,它非常有用,简单易懂,更重要的是,它很有效!

Raspberry Pis (Photo by Jeff Loucks on Unsplash)

如果我的程序能马上工作,我会跳上跳下,可能会在我的阳台上大喊,告诉每个人它工作了。可悲的是,没有成功。它抱怨缺少库,甚至处理一个又一个库,似乎从未停止。不知何故,我甚至在 Pi 中破坏了 pip 安装。我认为这也是许多其他开发者面临的问题,缺少依赖性,版本不受支持,*台不兼容,这个列表永远不会结束。

Error (Image by bartekhdd from Pixabay)

如果有一个我可以运行的脚本或程序,它会为我安装所有需要的库和依赖项,这不是很好吗?

一定要这么难吗?

第二天,我终于在一个 Raspberry Pi 上实现了对象检测代码,它可以检测不同的对象,并在其周围绘制一个边界框。我用的是当时最先进的物体检测模型 YOLOv3 ,非常快速准确。我很开心。Yeyy!终于!

我注意到带有边界框的输出视频滞后,就像当你的互联网连接不好,而你正试图在 YouTube 上观看视频时一样。很糟糕!我很兴奋它的工作,但同时也有点失望,最快的物体检测在 Pi 上不够快。我的意思是,给我的父母或朋友看,它甚至不能做一个好的演示。

所以我的下一个目标是让它在圆周率上跑得更快。

经过大量的研究,我发现我并不是唯一一个在这个问题上挣扎的人,这个问题也不容易解决。事实上,这是大多数希望在边缘设备上运行对象检测的开发人员讨论的挑战之一。

“……我们能够达到每秒 0.9 帧,这还不足以构成实时检测。尽管如此,考虑到 Pi 的处理能力有限,0.9 帧/秒对于某些应用来说仍然是合理的。”—计算机视觉专家和博客作者 Adrian Rosebrock 在他的一篇博客中提到。

有一些像 SqueezeNet 和 MobileNetSSD 这样的模型,开发人员正在讨论,它们针对 Raspberry Pi 进行了优化,可以获得更好的结果,但同样,这需要一个学习曲线。我很沮丧,我不得不经历这么多麻烦来做一个我想要的小实验。如果速度是问题所在,我怎么能指望用它来实现实时解决方案呢?可能有些情况下它不需要实时处理帧,每 10-20 秒处理一帧是可以接受的,但是需要更频繁地检测物体的解决方案呢?

最终,我将 YOLOv3 的 darknet 实现用于一个预先训练好的小型 YOLOv3 模型。推理速度比我所拥有的要好,但是我对解决方案的整体性能并不满意。我有很多问题和顾虑。

为什么它占了这么多空间?我不能并行运行任何其他代码。

为什么圆周率这么热?感觉随时都会炸。

我的 Pi 经常死机,我不得不重启它。我不知道为什么会这样,也不知道如何解决。

这个 Pi 到底为什么一次次重启?

我一直在寻找一种比 YOLOv3 在树莓 Pi 上表现更好的更快的物体检测方法,直到三个月前,我发现悉尼的初创公司 Xailient 的表现超过了 YOLOv3 和 Tiny YOLOv3,并树立了一个新的基准。这对我来说是一个好消息,我知道,无论如何我必须亲自接触他们的对象检测模型并进行测试。三个月后,我来到了 Xailient (这是另一个时间的故事),在 Pi 上试验当前最先进的实时物体检测。

在 Raspberry Pi 上运行对象检测时,你遇到过哪些挑战?在下面的评论中分享你的想法。

原载于

医学中的学生 t 检验:阐明其直观概念

原文:https://towardsdatascience.com/students-t-test-in-medicine-shedding-light-on-its-intuitive-concepts-fa5d7734aae?source=collection_archive---------8-----------------------

统计学术语被技术术语和复杂的数学符号所困扰。纵观我在生物医学领域的经历,我遇到过两种类型的人:一种是对这种抽象语言感到绝对着迷的人,另一种是每次看到有几个希腊字母的公式就惊恐地逃离的人(尽管他们的研究是基于这些公式的结果)。

我主要为医生和生物医学研究人员工作,他们对应用统计学有着早已被遗忘的知识,所以我最终花更多的时间回答解释性的问题,而不是做分析。这是神秘的统计数据变得如此简单的直接结果。

最常见的问题之一也来自医学中最流行和最常用的统计测试之一:学生的 t 检验和 p 值。

但是学生的 t-test 是什么?

为什么使用学生的 t 检验

给定一个连续变量,Student 的 t 检验允许比较两个样本的*均值。简单明了,不涉及重大复杂问题。

对于喜欢数学记数法的人来说,Student 的 t 等于均值之和,除以组合标准差,再乘以 2 的*方根除以观察次数。这比听起来简单:

为了说明学生的 t 检验,我们将设计一个小实验。假设我们想进行一项适度的临床试验,在试验中,我们打算评估一种新药在使用一个月后是否能降低患者的血液胆固醇水*。为此,我们选择了 100 名高胆固醇血症(> 240 mg/dL)患者,并将他们随机分配到两个治疗组(对照组或治疗组)中的一个,比例相同。这样,我们将拥有:

Figure 1. Simple study design where 100 patients, whose cholesterol blood concentration is above 240 mg/dL, are randomly assigned to one of the two treatment groups: control or treated.

一旦研究完成,我们如何知道我们测试的药物是否足够有效?这就是学生 t 检验变得有用的地方。但是首先,我们必须定义我们相信会发生什么。

告诉我可能的假设

这是我经常说的一句话:要在医学中正确使用统计学,良好的前期实验设计是最重要的。必须在开始任何实验之前确定假设。为什么会这样?每个统计测试对不同事物的评价是不同的。最合适的测试将在很大程度上取决于我们如何制定我们最初的假设。这是一个常见的错误来源,可能导致不确定的结果,甚至更糟,错误的结论!****

在开始一个像我们上面设计的简单实验之前,我们必须定义两个假设:零假设(T0)和替代假设(T4),零假设(T1)和替代假设分别是 h₀(T2)和 h₁(T7)。

本实验的适当的零假设可以定义为 H₀: (x̅₁ - x̅₂) = 0 ,在我们的例子中,这意味着当比较对照组( x̅₁ 和治疗组( x̅₂ )的*均值时,胆固醇血症没有差异。这很直观:如果血液胆固醇浓度没有变化,对照组和治疗组的手段是一样的,对吗?****

相反,替代假设可以由 H₁: (x̅₁ - x̅₂) ≠ 0 来定义,它设置了与前一种情况相反的情况。如果我们测试的药物引起胆固醇水*的变化,两组*均值的差异必须是非零的。

无效假设(H₀ ) : 治疗对胆固醇水*没有影响。

替代假说(H₁ ) : 治疗改变胆固醇水*。

这些假设设置了理想的场景,使用学生的 t 检验来评估它们,t 检验专门评估均值之间的差异。一旦假设成立,这些方法应该有多大的不同,这样我们才能确定新的治疗方法是有效的?在统计学中,这就是 p 值的用武之地,但首先,我们将从视觉和数字上探索我们的数据。

看看你的数据!

将我们的测量结果存储在电子表格、笔记本或数据库中是非常常见的。这是数据存在的地方,但我们人类一旦达到了容量和密度的临界点,就很容易失去洞察力。尽管在本例中完全可以用肉眼得出结论,强烈建议通过视觉探索数据来了解每个治疗组的表现。

Figure 2. Density graph and boxplot representing the distribution of populations for the control group (in blue) and the treated group (in orange). The vertical dashed line (in red) shows the initial cholesterol and inclusion criteria for the study.

乍一看,我们看到两组分布的中心沿着横坐标轴彼此分离,这意味着,先验地,它们的均值不同(稍后我们将看到是否充分)。此外,我们可以看到治疗组中的大多数个体低于 240 mg/dL 的阈值,考虑到在开始临床试验之前患者的胆固醇浓度高于该值,这是明显改善的指标。

如果我们用数字的形式来研究集中趋势和分散程度,我们会得出同样的结论。显然,这种新药有效!

Table 1. Measures of central tendency and dispersion of each treatment group.

但是在科学上,特别是在研究人们的健康时,我们不能简单地根据两条曲线被一条垂直线移动和分开的事实来说一种治疗是有效的。我们不得不求助于数字的客观性。

什么是 p 值

当医生理解 p 值的真正含义时,他们解释研究结果的方式通常会发生范式转变。需要澄清的是,Student 的 t 检验(以及更多的统计检验)假设零假设为真,这意味着他们从药物没有效果的基础出发。

用技术术语来说, p 值是假设零假设为真,获得与我们的数据中观察到的结果一样极端的结果的概率(从 0 到 1)。例如,如果我们获得的 p 值为 0.6,就有可能发现均值之间的差异,就像我们在 60%的情况下观察到的那样。科学界一致认为,当测试的 p 值低于 0.05 时,该测试被认为具有统计学意义。

这是这里的关键概念:p 值并没有提供任何关于替代假设的确定性的证据(这正是我们感兴趣的),它只是说机会无法解释我们在数据中观察到的可变性。这是统计学结束和解释开始的地方:你如何解释为什么另一个假设可能是真的?

解释结果

在进行学生 t 检验之前,根据所使用的统计软件,会产生几个疑问。我的样本有关系吗?我应该假设方差相等吗?单尾还是双尾?

对于第一个问题,在我们的特殊情况下,我们定义的两个治疗独立的,因为每个组由不同的人组成。如果我们在临床试验的第一天,即给药前测量胆固醇浓度,并在治疗一个月后再次测量胆固醇,以随后分析同一患者随时间推移发生的差异,情况就会相反。在这种情况下,我们应该认为我们的措施是相关的。这就是实验的设计阶段如此重要的原因!

为了检查两组之间的方差是否相等,有必要执行一个 F 检验,我们不会在本文中讨论。一般来说,我们可以假设当方差之间的比值接* 1 (127/134 = 0.94)时,方差实际上是相等的。这影响了学生的 t 检验,因为如果方差足够不同,我们必须使用韦尔奇校正(这也是另一篇文章)。

当 Student t-test 问我们是想进行单尾还是双尾检验时,基本上是问我们是否知道我们期望的结果会改变我们的均值。在医学上,这转化为我们是否期望药物增加降低胆固醇浓度,或者是否两者可能同时发生。在生命科学中,在对人体进行试验之前,通常会有一些关于药物预期效果的先验证据:体外,动物实验等。为此,执行单尾测试是相当常见的。但是,如果我们想对学生的 t 检验进行更严格的限制,并且假设在我们最初的替代假设中我们确定存在差异(但不是在哪个方向),我们将使用双尾检验。

Table 2. Output of a Student two-tailed t-test for 2 independent samples, assuming equal variances.

我们首先再次发现的是每个治疗组的手段。乍一看,有 50 毫克/分升的绝对差异。但这有关系吗?获得的下一个参数是 t 值,它表明观察到的均值差异几乎是我们数据中可变性大小的 22 倍。太多了!这转化为低于 0.01 的 p 值,如果我们回忆之前的解释,这表明我们在患者中发现像我们观察到的那样极端的变异性的概率不到 1%,这种变异性可以用纯粹的概率来解释。综上所述,我们拒绝零假设,接受另一个假设。

最后两个参数是 95% 置信区间:其下限和上限。这告诉我们,在大多数情况下,两个值之间的真正差异。对于这种特殊情况,我们发现与对照组相比,胆固醇的差异在 44.70 和 53.88 mg/dL 之间。物理学家应该从这里开始进行临床解释!

那么,新药有效吗?

好吧,统计学永远无法回答这个问题,它只是给我们一些线索,告诉我们某些事情正在发生,而这不是偶然的。这里开始解释部分。在医学上,找到有统计学意义但与临床无关的证据并不罕见。对于这种特殊情况,我们治疗的患者的*均浓度为 220 毫克/分升,仍然高于临床推荐的限值(~200 毫克/分升)。是的,他们有所改善,但也许其他药物的效果更好,副作用更少,等等。甚至可能发生的是,尽管已经发现了显著的差异,但我们所看到的是由于其他因素,如临床试验期间饮食的变化,身体活动的增加,甚至是基因变异。作为研究人员,我们必须考虑所有可能的选择,并在得出结论之前进行测试。

从这个样本实验中得到的信息应该是:对于初始浓度超过 240 mg/dL 的患者,这种治疗可以将胆固醇降低到 45 到 54 mg/dL 之间。

这足以证明它的用途吗?看你问谁了!同样,这是统计学不能(也不应该)回答的解释性部分。

最后

这个例子非常简单(它来自于 R 中的模拟分布),但是我认为它确实说明了学生的 t 检验是有用的。在实际的临床实践中,要考虑更多的变量,甚至是它们的部分贡献,对此学生的 t 检验是不够的。这就是回归和混合模型发挥作用的地方。

记住:要报告一个学生的 t 检验,你必须包括所有的参数: p 值是不够的!有无数的论文只提供了最后一个参数,正如我们已经解释过的,这个参数很少甚至没有提到实际的差异,也不能让我们了解我们观察到的效应的大小。请给出置信区间!

像大师一样设计熊猫数据框

原文:https://towardsdatascience.com/style-pandas-dataframe-like-a-master-6b02bf6468b0?source=collection_archive---------0-----------------------

Photo by billow926 on Unsplash

什么是造型,为什么要在意?

造型背后的基本思想是利用视觉辅助手段,如颜色和格式,以便更有效地传达洞察力。

可视化数据集的最常见方式之一是使用表。表格允许你的数据消费者通过读取底层数据来收集洞察力。例如,您可能会发现自己处于这样的场景中,您希望使用表为您的消费者提供对底层数据的访问。

在本文中,您将学习如何通过使用 pandas 样式和选项/设置为 pandas 数据框架添加可视化。熊猫文档本身是相当全面的,但是如果你正在寻找稍微友好的介绍,我想你来对地方了。我将使用 kaggle' " 旧金山工资数据集"作为一个例子,像往常一样,我们首先使用 pandas 加载数据集。

熊猫代码加载数据集和一些基本的数据管理:

df = pd.read_csv('Salaries.csv')\.replace('Not Provided', np.nan)\.astype({"BasePay":float, "OtherPay":float})

This is the rendered dataframe of “San Fransisco Salaries”

熊猫选项/设置 API

熊猫有一个选项系统,可以让你定制它行为的某些方面,这里我们将着重于显示相关的选项。在使用渲染数据框时,您可能会遇到以下问题:

  • 数据框中的列/行太多,中间的一些列/行在显示时被忽略。
    例如,如果想要显示最多 7 行和最多 7 列,可以:

  • 包含长文本的列被截断,包含浮点的列仅在显示器上显示过多/过少的数字。

  • 以及更多的用例。

熊猫造型 API

正如我们提到的,pandas 也有一个样式系统,可以让你使用 CSS 定制渲染数据帧的某些方面。您编写一个“样式函数”,它采用标量、DataFrameSeries,并返回 like-indexed 数据帧或带有 CSS "attribute: value"对的序列作为值。

最简单的样式示例是在处理货币值时使用货币符号。例如,在我们的数据中,一些列(BasePay、OtherPay、TotalPay 和 TotalPayBenefit)是货币值,所以我们希望添加美元符号和逗号。这可以使用style.format功能来完成:

Pandas 代码通过格式化货币列来呈现数据帧

df.head(10).style.format({"BasePay": "$**{:20,.0f}**", "OtherPay": "$**{:20,.0f}**", "TotalPay": "$**{:20,.0f}**","TotalPayBenefits":"$**{:20,.0f}**"})

这些样式函数可以递增地传递给在呈现前收集样式的Styler,因此,如果我们想添加一个函数来格式化 EmployeeName 和 companyTitle,可以使用另一个style.format函数来完成:

Pandas 代码呈现数据帧,也将一些列格式化为小写

df.head(10).style.format({"BasePay": "$**{:20,.0f}**", "OtherPay": "$**{:20,.0f}**", "TotalPay": "$**{:20,.0f}**","TotalPayBenefits":"$**{:20,.0f}**"})\.format({"JobTitle": **lambda** x:x.lower(),"EmployeeName": **lambda** x:x.lower()})

现在看起来好多了,但是让我们再往前走一步这里的索引没有添加任何真实的信息,我们可以使用下面的代码片段使用hide_index函数来取消索引的显示:

Pandas 编写代码来呈现不带索引的格式化数据帧

df.head(10).style.format({"BasePay": "$**{:20,.0f}**", "OtherPay": "$**{:20,.0f}**", "TotalPay": "$**{:20,.0f}**","TotalPayBenefits":"$**{:20,.0f}**"})\.format({"JobTitle": **lambda** x:x.lower(),"EmployeeName": **lambda** x:x.lower()})\.hide_index()

在呈现我们的数据集时,拥有这种类型的灵活性是非常强大和有用的,但这还不够。您可以应用条件格式,这是一个数据帧的可视样式,取决于其中的实际数据。最简单的例子是样式 API 中的内置函数,例如,可以用绿色突出显示最高的数字,用彩色突出显示最低的数字:

熊猫代码也强调最小/最大值

df.head(10).style.format({"BasePay": "$**{:20,.0f}**", "OtherPay": "$**{:20,.0f}**", "TotalPay": "$**{:20,.0f}**","TotalPayBenefits":"$**{:20,.0f}**"})\.format({"JobTitle": **lambda** x:x.lower(),"EmployeeName": **lambda** x:x.lower()})\.hide_index()\.highlight_max(color='lightgreen')\                            .highlight_min(color='#cd4f39')

另一个有用的函数是background_gradient,它可以突出显示一列中的值的范围。此外,cmap参数允许我们为渐变选择调色板。matplotlib 文档列出了所有可用的选项(seaborn 也有一些选项)。

熊猫代码,也增加了背景渐变

df.head(10).style.format({"BasePay": "$**{:20,.0f}**", "OtherPay": "$**{:20,.0f}**", "TotalPay": "$**{:20,.0f}**","TotalPayBenefits":"$**{:20,.0f}**"})\.format({"JobTitle": **lambda** x:x.lower(),"EmployeeName": **lambda** x:x.lower()})\.hide_index()\.background_gradient(cmap='Blues')

当风格实际上不依赖于值时,甚至可以使用styler.set_properties 。在这个例子中,我们将使用黑色背景和绿色文本来呈现数据集。

Pandas 编码为每个单元格以相同的方式呈现格式化的数据帧。

df.head(10).style.set_properties(**{'background-color': 'black',                                                   'color': 'lawngreen',                       'border-color': 'white'})

但是,如果我们诚实的话,大多数时候我们希望根据值和我们想要强调的内容来更改可视化属性,我们可以使用以下方法之一来帮助实现我们的目标:

  • Styler.applymap(func)针对元素风格。
  • Styler.apply(func, axis=0)用于列样式。
  • Styler.apply(func, axis=1)针对行式风格。
  • Styler.apply(func, axis=None)用于表格风格。

第一个例子是突出显示数据帧中的所有负值。

如果值是一个字符串,则用改变的字体颜色呈现格式化的数据帧

df.head(10).style.format({"BasePay": "$**{:20,.0f}**", "OtherPay": "$**{:20,.0f}**", "TotalPay": "$**{:20,.0f}**","TotalPayBenefits":"$**{:20,.0f}**"})\.format({"JobTitle": **lambda** x:x.lower(),"EmployeeName": **lambda** x:x.lower()})\.hide_index()\.applymap(lambda x: f”color: {‘red’ if isinstance(x,str) else ‘black’}”)

最后,pandas 样式 API 还支持更高级的样式,如在列中绘制条形图,我们将在这里介绍bar函数和一些参数来配置它在表中的显示方式:

df.head(10).style.format({"BasePay": "$**{:20,.0f}**", "OtherPay": "$**{:20,.0f}**", "TotalPay": "$**{:20,.0f}**","TotalPayBenefits":"$**{:20,.0f}**"})\.format({"JobTitle": **lambda** x:x.lower(),"EmployeeName": **lambda** x:x.lower()})\.hide_index()\.bar(subset=["OtherPay",], color='lightgreen')\.bar(subset=["BasePay"], color='#ee1f5f')\.bar(subset=["TotalPay"], color='#FFA07A')

结论

pandas 风格的 API 和 options API 在您的数据分析接*尾声并需要向他人展示结果时非常有用。字符串格式化有几个棘手的部分,所以希望这里突出显示的内容对您有用。

高清图像上的 GANs 风格转换

原文:https://towardsdatascience.com/style-transfer-with-gans-on-hd-images-88e8efcf3716?source=collection_archive---------0-----------------------

如何使用 GANs 生成高清图像,而无需昂贵的硬件

简介

最*的一些研究探索了使用 GANs(生成对抗网络)生成高清晰度图像(1024×1024 像素)的一些方法和技术。看到超逼真的,由算法生成的人脸、动物和其他事物的高清图像,尤其是记得几年前的第一张 GAN 图像,令人难以置信地惊讶。我们很快就从低质量的像素化图像发展到了接*现实的图像:这是该领域研究进展有多快的一个非常清晰的证明。

StyleGAN HD face samples

但是阅读这些最*的研究(最相关的是 Nvidia 的 StyleGAN 和 Google 的 BigGAN 论文),我总是发现一个方面能够降低我的惊讶和兴奋感:计算能力。发现巨大的计算能力被用来完成那些图像让我意识到在我和那些结果之间有一个不可逾越的障碍。光是这个想法就让我觉得研究中探索的整个新技术对我来说都很遥远,因此不那么令人惊讶。

这就是为什么在这篇文章中,我想探讨如何使 GANs 和 HD 图像一起工作而不需要昂贵的硬件,为不一定有机会使用高级 GPU 的人打开新的机会。这里解释的一切都可以使用免费的谷歌合作实验室*台来实现,该*台为你所有的机器/深度学习项目提供免费的 GPU。

我们的目标

我们将尝试在高清图像的两个域之间执行风格的传输,使用特殊但简单的 GAN 架构来执行我们的任务。更具体地说,我们将把梵高的绘画风格应用到风景的高分辨率图像上。公*地说,在过去的几年里,风格转换一直是计算机视觉中的一个热门话题;开创潮流的原始论文是《一种艺术风格的神经算法》 (Gatys 等人),在一个预训练的卷积网络上使用了一个内容和风格损失来执行任务。虽然这种方法可以在高清图像上工作,但它只能使用一个单幅图像(假设是“星夜”)作为画家风格的表示,这不是我们想要的。

Style Transfer examples from the original paper

另一方面,GAN 通常需要一个图像域来进行训练,因此在我们的情况下能够完全捕捉画家的风格(CycleGAN 的论文显示了风格转移的有趣结果)。

CycleGAN Style Transfer examples

然而,训练 GANs 在计算上极其昂贵:高分辨率图像的生成只有在非常高端的硬件和长训练时间的情况下才有可能。我希望本文中解释的技巧和技术能够帮助你进行高清图像生成的冒险。

Van Gogh paintings

****

HD images translated to Van Gogh Style

我们开始吧!

架构

我们要努力实现的叫做图像到图像的翻译(从域 A 到域 B)。有不同的方法和网络架构来实现它:最著名的可能是 CycleGAN,但也存在许多关于同一主题的其他论文。

在我的实验中,我使用了一个定制的架构,该架构包含一个作为鉴别器的暹罗网络和一个特殊的(但超级简单的)损失函数。我选择这种方法是因为它不依赖于任何损失中的每像素差异:这仅仅意味着网络不遵循生成图像的任何几何约束,因此能够创建更令人信服的图像转换(这在我们的情况下是有效的)。

在我写的另一篇文章 这里 中可以找到对这种架构及其工作原理的深入透彻的解释。

下面简单介绍一下暹罗甘建筑。

Siamese GAN Architecture

它由单个生成器(G)和鉴别器(D)组成:G 以一幅图像为输入,输出翻译后的图像;d 以一幅图像作为输入,输出一个潜在向量。

暹罗鉴别器有两个目标:告诉 G 如何生成更真实的图像,并在这些假图像中保持与原始图像的相关性(相同的“内容”)。

调用 A1、A2、 B1、B2 分别来自 A 域和 B 域的随机图像、X 域的随机图像、 G(X) 生成器生成的图像,鉴别器必须将图像编码成矢量【D(X)如:

1. D(B1) 一定离一个固定点(例如原点)很*(欧几里德距离),而 D(G(A1)) 一定离同一点很远。因此,更接*固定点的向量代表更真实的图像。另一方面,生成器试图以经典的对抗方式最小化从 D(G(A1)) 到固定点的距离。

2. (D(A1)-D(A2)) 必须与 (D(G(A1))-D(G(A2))) 相似(余弦相似),才能保留 AG(A) 之间的‘内容’。发生器和鉴别器都参与这个目标。

Siamese Discriminator

有了这两个约束(损失),第一个依赖于向量的大小,而第二个依赖于向量之间的角度,我们的全部目标得到满足,我们可以实现从域 A 到域 b 的图像到图像转换的最终目标。我真的建议您阅读 这篇文章 ,其中我给出了该架构的更全面和深入的解释,同时展示了插图和示例。

现在我们已经锁定了架构,让我们来探索如何以及向网络提供什么,以实现高清图像生成。

图像提取

我们需要 2 个高清图像数据集:在我们的例子中,我们将使用一个风景数据集(域 A)和一个梵高画作数据集(域 B)。请记住,您选择处理的图像越大,对这些图像进行预处理(切割、调整大小)所需的时间就越长(尽管它不会增加专门用于训练网络的时间!).

现在,我们需要选择将被馈送到生成器的图像的大小:显然,我们不能使用来自数据集的整个 HD 图像的大小,否则训练时间和网络大小将是巨大的,并且不会解决任何问题。因此,我们选择了一个足够小的 SxS(例如 64x64 像素),这样训练时间可以得到控制,一切都保持计算上可行,即使对于中端 GPU 也是如此(就像在谷歌合作实验室上免费提供的那些)。

因此,正如您可能已经想到的,图像在被馈送到发生器之前,必须被剪切(或裁剪)成更小的 SxS 图像。因此,在读取图像并将其转换为张量后,我们对图像执行随机 SxS 裁剪,将其添加到一个批处理中,并将该批处理馈送到网络。这听起来非常简单,事实也确实如此!

现在,假设我们使用这种方法训练一个 GAN,直到每一个小的 SxS 裁剪都被生成器以一种令我们满意的方式转换为梵高风格:我们现在如何将整个高清图像从域 A 转换到域 B?

同样,非常简单:图像被分成小的 SxS 块(如果 HD 图像的大小是 BxB,那么我们将有(B//S)x(B//S)个小的 SxS 图像),每个 SxS 图像被生成器翻译,最后所有的东西被重新组合在一起

然而,如果我们尝试使用这种从较大图像中提取较小图像的简单思想来训练 GAN,在测试期间,我们很快就会注意到一个相当恼人的问题:由我们想要翻译的大图像提取的小图像,当由生成器转换到域 B 时,不会** 有机地融合在一起。每个 SxS 图像的边缘在最终构图中清晰可见,破坏了原本成功的风格转移的“魔力”。这是一个相对较小的问题,但可能相当令人讨厌:即使使用基于像素的方法,如 cycle gan相同的障碍仍然出现。**

The edges are visible

怎么才能解决呢?

我使用的解决方案很容易理解,在我看来也很优雅,它代表了我希望你能从这篇文章中记住(也许会用到)的核心思想

首先,我们需要重新审视我们的数据管道:在我们直接从 BxB HD 图像中剪切 SxS 裁剪之前,我们现在必须得到 2Sx2S 裁剪(如果 S=64,那么我们需要 128x128 裁剪)。然后,在定义了我们的生成器之后,我们创建了一个名为 Combo 的新模型,它执行以下操作:

1.取一批 2Sx2S 图像(来自 A 域)作为输入(INP);

2.将 INP 中的每幅图像切割成 4 幅 SxS 图像(INP cut);

3.将input的 4 幅 SxS 图像中的每一幅输入到发生器,并获得 OUTCUT (与input的形状完全相同,但每幅 SxS 图像都有翻译版本);

4.将每组 4 张 SxS 图像加入 OUTCUT 中,取出 OUT (与 INP 形状完全相同,但每张 2Sx2S 图像有翻译版本);

5.输出输出。

Combo model: cutting, translating, joining

Combo 的输出然后作为输入传递给鉴别器,鉴别器现在接受比以前大一倍的输入(2Sx2S)。这个小小的调整不需要太多的计算时间,并且可以有效地解决我们之前的问题。怎么会?

现在,生成器被迫生成关于边缘和颜色一致的图像,因为鉴别器不会将不一致的合并图像归类为真实图像,因此会通知生成器可以改进的地方。深入一点,生成器被迫学习如何在 SxS 图像的 4 个边缘中的每一个上生成逼真的边缘:在最终的 2x2 合并图像中,4 个边缘中的每一个都与另一个接触,甚至一个生成不好的边缘都会破坏 2x2 图像的真实感。

Samples during training: (from left to right) images from domain A, translated images (AB), images from domain B

所有的事情加在一起

为了确保到此为止的一切都清楚明白,让我们总结一下整个网络是如何工作的。

目标是将 B 的样式应用于 A 中的图像。大小为 2Sx2S 的图像是从域 A 和 B 中的高分辨率图像中剪切的。来自 A 的图像是 Combo 的输入;该模型将图像切割成 4 个较小的图像(SxS),然后使用生成器 G 转换它们,最后将它们连接在一起。我们称这些假图像为 AB。

现在让我们来关注一下连体鉴别器 D** :其输入的大小是生成器输入(2Sx2S)大小的两倍,而输出是大小为 LENVEC 的向量。**

D 将图像编码成向量 D(X ),例如:

1.D(B)必须靠*原点(大小为 VECLEN 的零点向量):

LossD1 是 D(B)到原点的欧氏距离的*方,所以Eucl(D(A))

2.D(AB)必须远离原点:

LossD2 是( max(0,cost — Eucl(D(AB))))

3.变换向量(D(A1)-D(A2))和(D(AB1)-D(AB2))必须是相似的向量,以保留图像的“内容”:

LossD3 是余弦 _ 相似度(D(A1)-D(A2),D(AB1)-D(AB2))****

另一方面,生成器必须生成(结合的)图像 AB,例如:

1.D(AB)必须靠*原点:

LossG1 是 Eucl(D(AB))

2.变换向量(D(A1)-D(A2))和(D(AB1)-D(AB2))必须是相似的向量(与鉴别器的目的相同):

LossG2 是余弦 _ 相似度(D(A1)-D(A2),D(AB1)-D(AB2))****

在我的文章 here 中可以找到关于这些损失如何工作的更深入的解释,在那里我详细解释了暹罗鉴别器是如何工作的(我认为这值得一读!).

就是这样!

按照这种方法,生成器能够学习如何生成小的风格化图像,这些图像可以被连接在一起而没有任何边缘差异。因此,当翻译整个高清图像时,在将它切割成单独的较小 SxS 图像并将它们馈送到生成器之后,我们能够将它们连接在一起成为最终的、视觉上令人愉快的和连贯的高清图像。

Translation examples on HD images: although not perfect, realistic brush strokes are generated and the images look quite coherent. Solutions might be networks fine tuning and bigger capacity

结论

本文中解释的技术仍然存在一些我们需要解决的问题。

如果选择极高清晰度的图像,用于训练网络的较小作物可能不包含任何相关信息(它们可能只是纯色,类似于单个像素),因此训练可能不会成功:生成器和鉴别器都需要某种信息来处理(鉴别器必须根据图像的“内容”对图像进行编码),如果该信息不可用,可能会面临一些问题。

Failure case: the generator “hallucinates” incoherent colors and shapes in some areas

即使训练成功结束,当连接具有非常高分辨率的图像的所有不同裁剪时,每个小的翻译图像的风格贡献对于整个高清图像来说是不够的,整个高清图像通常看起来与原始图像相似,只是颜色发生了变化。

在我的实验中,我发现,对于训练阶段,使用调整大小(较低分辨率)的 HD 数据集版本,同时在转换时切换到整个 HD 图像,对于第一个问题肯定有帮助。

这项技术给留下了很多有待探索的空间:不同于传统风格转换的其他类型的图像翻译也是可能的。重要的是要记住,本例中的生成器不知道整个高清图像的上下文,只“看到”较低分辨率的裁剪。因此,给生成器一些上下文(可能以编码的‘上下文向量’的形式)?)可以扩展该技术的应用范围,为更复杂的“上下文感知”类型的高清图像翻译(对象到其他对象、人脸、动物)提供了可能性

因此,正如你可能已经理解的,可能性是无穷无尽的,尚未被发现!

我很乐意真诚地感谢您对本文的关注,非常感谢,我希望您带着新的东西离开。

玩得开心!

用一点深度学习的魔力来装饰你的照片

原文:https://towardsdatascience.com/style-up-your-photos-with-a-touch-of-deep-learning-magic-60a003c676f9?source=collection_archive---------22-----------------------

看到深度学习的艺术一面

风格转移在成像的语境中,指的是将一幅图像的“风格”转移到另一幅图像,同时保持第二幅图像的“内容”的过程。

例如,最左边的图像是“内容”图像。我们将中间图像的“样式”(“样式”图像)应用于我们的内容图像。我们预计,由于中间的图像有一种大城市夜晚的氛围,这将反映在最终的图像中——这正是最右边的结果中发生的事情!

Source from the original research paper.

这一领域最具突破性的研究之一来自 Adobe Research。他们称之为 深照风格转移【DPST】

如何转移照片风格

为了正确地执行从一张照片到另一张照片的样式转换,Adobe 团队设计了他们的 DPST 的目标:“将引用的样式转换到输入,同时保持结果的照片真实感

这里的关键部分是保持输出的“照片真实感”属性。如果我们有一个像上面这样的内容照片,我们不希望任何建筑改变。我们只是想让它看起来像是同一张照片是在晚上拍的。

在这项研究发表之前出现的许多风格转换算法扭曲了原始图像的许多内容。在当时神经风格转移技术的结果中,像使直线呈波浪状和改变物体形状这样的事情很常见。

这完全可以接受。许多算法是为艺术风格的转换而设计的,所以一点点的变形也是受欢迎的!

Example of a distorted style-transferred image. Source

但在这种情况下,目的是创造仍然逼真的图像——就像是由真实世界的相机拍摄的一样。

作者做了 2 件主要的事情来实现这一点:(1)损失函数中的照片真实感正则化项(2)用作指导的内容图像的语义分割。

摄影现实规则化

想想我们如何直观地保持图像的真实感。我们希望原始图像的线条和形状保持不变。颜色和灯光可能会改变,但一个人看起来仍然像一个人,一棵树像一棵树,一只狗像一只狗,等等。

基于这种直观的想法,作者实现的正则化项迫使像素从输入到输出的变换在色彩空间中为局部仿射。根据定义,仿射变换在将输入映射到输出时必须保持点、直线和*面。

有了这个约束,直线永远不会变成波浪,在我们的输出中也不会有任何奇怪的形状变化!

分段指导

除了保持点、直线和*面之外,我们还希望确保样式图像中各种“事物”的样式被真实地转换。

想象一下,如果你有一个风格图像,显示一个美丽的橙色日落,如下图所示。

Source

图像的大部分是略带红色的橙色。如果我们把它转换成一个城市形象,所有的建筑都会变成红色!然而这并不是我们真正想要的——一个更真实的转换会使大部分建筑非常暗(接*黑色),只有天空会有日落和水的颜色。

深度照片风格转移算法使用应用于内容图像的语义分割的结果,以便 T2 引导风格转移。当算法确切地知道哪些像素属于前景和背景时,它可以更真实地传递风格。天空像素将始终被转换为天空像素,背景像素被转换为背景像素,依此类推。

转移样式的代码

您可以从 GitHub 下载照片真实感风格传输库:

git clone [https://github.com/GeorgeSeif/DeepPhotoStyle_pytorch.git](https://github.com/GeorgeSeif/DeepPhotoStyle_pytorch.git)

运行它所需要的只是一个最新版本的 Pytorch 。完成后,进入文件夹,使用下载脚本下载语义分段的模型:

cd DeepPhotoStyle_pytorch
sh download_seg_model.sh

现在我们准备好运行我们的代码了!

下载一个风格图片和一个内容图片——任何你选择的图片!以我的经验来看,城市和风景图片效果最好。最后,像这样运行代码:

python main.py --style_image path_style_image --content_image path_content_image

该算法将迭代地改进样式传递结果,因此您等待的时间越长,效果就越好!默认情况下,它设置为运行 3000 步,但如果您觉得更多的步骤可以改善结果,您可以增加。

自己试试代码吧,很好玩的!查看风格转换后照片的外观。欢迎在下面发布链接,与社区分享您的照片。

喜欢学习?

在推特上关注我,我会在这里发布所有最新最棒的人工智能、技术和科学!也请在 LinkedIn上与我联系!

推荐阅读

想了解更多关于深度学习的知识?用 Python 进行 深度学习 本书将教你如何用有史以来最简单的 Python 库:Keras 进行真正的深度学习!

提醒一句,我支持这个博客,因为分享好书对每个人都有帮助。作为一名亚马逊员工,我从合格购买中获得收入。

StyleGAN2

原文:https://towardsdatascience.com/stylegan2-ace6d3da405d?source=collection_archive---------2-----------------------

本文探讨了 StyleGAN2 中的变化,如权重解调、路径长度正则化和移除渐进增长!

StyleGAN 架构的第一个版本在被称为 Flicker-Faces-HQ (FFHQ) 的面部图像数据集上产生了令人难以置信的结果。与早期迭代的 GANs 如条件 GANs 或 DCGANs 相比,这些结果最令人印象深刻的特征是生成图像的高分辨率(1024)。除了分辨率之外,还从生成图像的多样性(避免模式崩溃)和一套比较真实图像和生成图像的定量指标(如 FID、初始分数、精确度和召回率)等方面对 gan 进行了比较。

Facial images generated from StyleGAN2

Frechet 初始距离(FID)是最常用的自动度量之一,用于评估从生成模型中采样的图像。该度量基于对真实图像和生成图像上的预训练分类网络的激活进行比较。下表显示了过去 2 年中在该数据集和指标上从 StyleGAN 到 StyleGAN2 的 GAN 进度。

FID results reported in the first edition of StyleGAN, “A Style-Based Generator Architecture for Generative Adversarial Networks” authored by Tero Karras, Samuli Laine, and Timo Aila. Note the FID scores on the right on the FFHQ dataset to compare with the StyleGAN2 resutls below.

FID results reported in the second edition of StyleGAN, “Analyzing and Improving the Image Quality of StyleGAN” authored by Tero Karras, Samuli Laine, Miika Aittala, Janne Hellsten, Jaakko Lehtinen, and Timo Aila. Note the FID scores on the far left for the sake of comparison with StyleGAN1.

本文将讨论将 FID 指标提高了约 3 倍的架构变化,以及像消除生成图像中的伪像和*滑潜在空间插值这样的定性改进。潜在空间的*滑导致生成图像的源的微小变化,从而导致结果图像的微小感知变化,实现这样的惊人动画。如果你感兴趣,我还制作了一个视频来解释 StyleGAN2 的变化:

如何辨别图像是否是 StyleGAN 创作的

StyleGAN 的第一版产生了令人惊讶的逼真的面孔,从下面 whichfaceisreal.com 提供的测试中,你能看出哪个面孔是真实的吗?

你认为你能训练自己在这个游戏中获得满分吗?你认为你能训练一个神经网络来做这件事吗?这是 Kaggle 上价值 100 万美元的 Deepfake 检测挑战背后的想法。whichfaceisreal.com 的作者详细列出了一系列泄露秘密的“人工制品”,可用于区分 StyleGAN 生成的图像。一个这样的伪像是图像中出现的“水滴”效果。意识到这一点会让这个游戏变得更容易(如下所示)。

StyleGAN2 的作者试图从生成的图像中消除这些伪像。他们将水滴的来源归因于自适应实例规范化层对生成器施加的限制。

权重解调

NVIDIA 的研究人员是将标准化层用于图像合成应用的大师,如 StyleGAN 和 GauGAN 。StyleGAN 使用自适应实例规范化来控制源向量 w 对最终生成的图像的影响。 GauGAN 使用一个空间自适应反规格化层从涂鸦草图合成真实感图像。(如下图)

Image taken from “Semantic Image Synthesis with Spatially-Adaptive Normalization” by Taesung Park, Ming-Yu Liu, Ting-Chun Wang, and Jun-Yan Zhu. An example showing the power of normalization layers for image synthesis applications.

在 StyleGAN 的第二个版本中,作者重新调整了自适应实例规范化的使用,以避免这些水滴伪像。自适应实例规范化是一个规范化层,源于对实现更快的神经风格转移的研究。神经风格转移展示了卷积神经网络中明显的低级“风格”特征和高级“内容”特征之间的显著分离(如下所示):

Image above taken from “Arbitrary Style Transfer in real-time with Adaptive Instance Normalization” authored by Xun Huang and Serge Belongie

但是,样式转换(在自适应实例规范化之前)需要一个漫长的优化过程或仅限于单一样式的预训练网络。阿丹表明,风格和内容可以结合起来,通过标准化统计的唯一使用。(这方面的概述如下所示):

Image above taken from “Arbitrary Style Transfer in real-time with Adaptive Instance Normalization” authored by Xun Huang and Serge Belongie

StyleGAN2 的作者解释说,这种标准化丢弃了以相对激活幅度编码的特征图中的信息。发生器克服了这种限制,通过这些层偷偷传递信息,导致这些水滴假象。作者和读者一样困惑,为什么鉴别器不能从这种液滴效应中区分图像。

在 StyleGAN2 中,自适应实例归一化被重构为权重解调。(这一进展如下所示)

自适应实例规范化(类似于其他规范化层,如 Batch Norm)缩放和移动中间激活的激活。Batch Norm 使用从批次统计数据中计算出的学习均值和方差参数来实现这一点,而 Instance Norm 使用单个图像与批次进行比较。自适应实例范数使用不同的比例和偏移参数来将源 w 的不同区域与特征图的不同区域对准(在每个特征图内或者通过按空间位置按通道分组特征)。

权重解调将缩放和移位参数从顺序计算路径中取出,而不是将缩放烘焙到卷积层的参数中。在我看来,值的移动(在 AdaIN 中用(y)完成)是噪声图 b 的任务。

将缩放参数移动到卷积核权重中使得该计算路径更容易并行化。这导致 40%的训练速度从每秒 37 幅图像提高到每秒 61 幅图像。

移除渐进增长

第二版中 StyleGAN 介绍的下一个工件也可能帮助你在 whichfaceisreal.com 图灵测试中获得好的结果。在他们的配套视频的 1:40 中描述,StyleGAN 图像对鼻子和眼睛等面部图像特征有强烈的位置偏好。作者将此归因于渐进增长。渐进生长描述了首先用低分辨率图像(例如 4)分配 GAN 框架的任务,并且当在较低比例下达到期望的收敛属性时将其放大的过程。

虽然渐进增长可能难以实现,在较高分辨率层中引入关于衰落的超参数,并且需要更复杂的训练循环,但是它是高分辨率图像合成问题的非常直观的分解。众所周知,GANs 的训练具有挑战性,尤其是在生成像 1024 图像这样的图像之后,传统观点认为鉴别器很容易区分真实和虚假的图像,导致生成器在训练期间无法学到任何东西。

Animesh Karnewar 和 Oliver Wang 最*发表的另一篇关于 GANs 的论文“生成对抗网络的多尺度梯度”展示了一种有趣的方式,即利用单个端到端架构来利用多尺度生成。(如下所示):

Technique to avoid progressive growing from “Multi-Scale Gradients for Generative Adversarial Networks” by Animesh Karnewar and Oliver Wang

受 MSG-GAN 的启发,StyleGAN2 的作者设计了一种新的架构,以利用多尺度的图像生成,而无需明确要求模型这样做。他们通过低分辨率特征映射到最终生成的图像之间的 resnet 风格的跳过连接来实现这一点。

StyleGAN2 architecture without progressive growing

作者表明,与渐进式增长类似,早期的训练迭代更依赖于低频率/分辨率尺度来产生最终输出。下图显示了每个要素地图在最终输出中所占的比重,通过检查跳过的连接添加来计算。对这一点的考察启发作者按比例增加网络容量,以便 1024×1024 的比例对最终输出有更大的贡献。

路径长度正则化

StyleGAN2 为损失引入了一个新的归一化项,以加强更*滑的潜在空间插值。潜在空间插值描述了源向量 z 的变化如何导致所生成图像的变化。这是通过在发电机上增加以下损耗项来实现的:

这是如何实现的具体细节超出了我的理解范围,但是高层次的想法似乎是雅可比矩阵将 w 中的小变化映射到结果图像中的变化(从 w 空间中的点到 1024 个图像)。该矩阵乘以随机图像以避免陷入局部最优,并且该矩阵的 l2 范数乘以其指数移动*均值。因此,l2 范数越大,损耗增加得越多,导致发电机打球并保持潜在空间*滑。

这种实现的另一个有趣的特征被称为惰性正则化。由于计算该雅可比矩阵的计算量很大,因此与每一步相比,该归一化仅每 16 步添加到损失中。

这种*滑的潜在空间极大地方便了将图像投射回潜在空间。这是通过获取一个给定的图像并针对能够产生该图像的源向量 w 进行优化来实现的。这已经在许多有趣的 twitter 帖子中得到证实,研究人员将自己的图像投射到 FFHQ 上训练的 StyleGAN2 的潜在空间中:

来自吉恩·科岗的投影的一些推特演示:( 1 , 2 )

投射到一个完全*滑的潜在空间有很多有趣的应用。例如,动画工作流通常包括勾画出高级关键帧,然后手动填充更细粒度的中间帧。像 StyleGAN2 这样的模型将允许您将高级关键帧投影到潜在空间,然后在由先前 w~ p(w)的结构定义的两个 w 向量之间的路径中搜索,直到您找到满意的过渡。

比方说生成图像的源,w 是从这个球形分布(表示 3D 均匀分布)采样的。然后,将两个关键帧投影到这个球体中,以找到分别生成每个图像的向量。那么在源代码分布中的这些点之间将会有许多路径可供您选择。一个*滑的潜在空间将确保这些过渡是*滑的,就像由人类插图画家和动画师提炼的细粒度中间点一样。

通过投影进行深度伪造检测

投影的一个应用是用它来找到给定生成图像的来源,以判断它是真是假。这个想法是,如果它是假的,你可以找到产生它的潜在载体,如果它是真的,你不能。我认为这种将图像投射回潜在空间的想法非常有趣,但我并不认为这是一种深度伪造检测技术。似乎不可能记录下所有可能的数据集,人们可能不得不训练这些模型,这些模型将是图像投射回潜在空间的真正贡献者。此外,我不明白为什么 StyleGAN 不能完美地重建原始训练图像,因为这确实是训练目标的核心。

我认为投影可以以一种有趣的方式用于异常检测和终身学习。当一个新的例子被错误分类时,它可以被重新投射回用于训练分类器的相同数据集,并且可以像 l2 距离或预先训练的分类器特征那样计算某种图像相似性距离。

感谢您阅读 StyleGAN2 的概述!

人工智能发展中的主观和客观

原文:https://towardsdatascience.com/subjective-and-objective-in-the-development-of-artificial-intelligence-c5627a522f47?source=collection_archive---------25-----------------------

Photo by — @pawel_czerwinski

探索人工智能中偏见的定义

当在人工智能中谈到“数据”这个词时,“偏见”经常与给定的讨论一起被提及。我将首先对与主观和客观相关的偏见进行一般性讨论。之后,我将回到与人工智能的发展有关的要考虑的事情的总结。

偏见 不成比例 重量 赞成或反对一个想法或事物,通常是以一种思想封闭、有偏见或不公*的方式。偏见可以是 先天或后天 。人们可能会对某个人、某个团体或某个信仰产生偏见。 在科学与工程中,一个偏差就是一个系统误差 。统计偏差来自对总体的 不公*抽样 ,或者来自不能给出准确*均结果的估计过程 。”【加粗补充】

有很多我们可以关注的,但是让我们把这些不同的词拿出来,仔细研究一下。

  • 重量(数量/选择)
  • 先天的还是后天的
  • 系统误差
  • 不公*抽样
  • 评估过程

什么是加权?

一个加权*均值是一种*均值。不是每个数据点对最终*均值的贡献相等,而是一些数据点比其他数据点贡献更多的“权重”。如果所有的权重相等,那么加权的*均值等于算术*均值(你习惯的常规“*均值”)。这意味着有人决定什么应该给予更多的重视。Vox 在一个视频中展示了一个例子,它考察了美国的一些优秀学校,这些学校更重视(衡量)学生的能力,而不是考试成绩的增长。

先天还是后天?

先天还是后天是一个古老的争论,然而我们已经开始了解我们人类的某些事情。这些知识不仅仅来自一个领域,而是来自自然科学、社会科学、人文科学以及其他领域。

可以提及的几个例子是:

  • 一种 归因偏差 可能发生在个体评估或试图发现自己和他人行为背后的解释时。人们对自己和他人行为的原因进行归因;但是这些属性并不一定准确地反映现实。个人不是作为客观的感知者,而是倾向于感知失误,导致对他们的社会世界有偏见的理解。
  • 确认偏差是一种以确认个人信念或假设的方式搜索、解释、偏好和回忆信息的倾向,而对与之矛盾的信息给予的关注却不成比例地少。对于情绪化的问题和根深蒂固的信念,这种影响更大。人们也倾向于将模糊的证据解释为支持他们现有的立场。

除此之外,“经济人”,或者说“经济人”——理性人的神话,在某种程度上已经被揭穿。李·罗斯说,我们至少可以对自己的不理性保持理性。

系统误差

人们通常认为,如果真的出了问题,系统一定有缺陷。

(也称系统偏差)是一致的、可重复的误差,与有缺陷的设备或有缺陷的实验设计有关。

这些误差通常是由未正确校准或未正确使用的测量仪器造成的。

那么,如果我们同意人类判断相似情况的非理性(或不同)方式的数量,这可能会导致一些人得出结论,我们不是合适的测量工具。

在讨论中经常听到这样的说法:“我们需要减少……中的偏见。”其次是产品、系统、语句、算法等。

人类学家玛丽莲·斯特拉瑟恩(Marilyn Strathern)这样描述经济学家古德哈特定律:“当一个衡量标准成为目标时,它就不再是一个好的衡量标准。”

我不一定完全同意这种说法,但重要的是要认识到,一旦我们确定了一项措施,我们就会改变系统。系统改变后,我们可能需要重新测量。

这有时被认为是人工智能系统的设计,测量可以被“重新校准”。那就是:对仪器进行微小的改动,使其测量准确。但是如果一开始就不准确呢?

不公*采样

编码凝视是乔伊·波伦维尼创造的。她指出,许多解决方案都存在缺陷,因为缺乏对有色人种(除了白色以外的所有颜色)的面部识别。它探测不到她的脸。两年前,同样的面部识别软件在世界各地的几个地方使用,现在仍然如此。因此,偏差可以“传播”,因为一个样本大小用于在一个地方训练算法,所以任何偏离正常的情况。她说我们需要“全谱训练集”。她指出,开发机器学习算法的团队缺乏多样性。

除此之外,她发现面部识别更可能识别男性而不是女性,而女性黑人是最差的。这是一个与人工智能合作的每个人都必须看到的视频:

《广泛、神秘和破坏性的算法》( WMDA)是由《数学毁灭武器》一书的作者凯茜·奥尼尔创造的。凯西是一名“定量分析师”(金融领域的定量统计学家)。这个简短的插图有助于更清楚地表达她的一些主要观点:

人是不同的,每次测量算法的测试数据时,都会定义什么是成功。

“算法让事物为算法的建造者工作”——凯西·奥尼尔

估算过程

这就给我们留下了由某人定义的估计算法。因此,了解以下内容很重要:

  1. 那个人是谁
  2. 决策是如何做出的
  3. 后果

这是一个三指法则试探法,然而它可能非常复杂。尤其是如果我们考虑到一套算法可以应用于数十亿人,例如脸书和谷歌。

下次你说:客观决策,考虑一下这在实践中意味着什么。

这里是#500daysofAI,您正在阅读的是第 186 条。500 天来,我每天都写一篇关于人工智能或与之相关的新文章。

Matplotlib 中的支线剧情:规划剧情的指南和工具

原文:https://towardsdatascience.com/subplots-in-matplotlib-a-guide-and-tool-for-planning-your-plots-7d63fa632857?source=collection_archive---------5-----------------------

我最*做了一个项目,需要在 matplotlib 中进行一些微调的子绘图和叠加。虽然我对制作基本的可视化感到很舒服,但我很快发现我对支线剧情系统的理解没有达到标准。我不得不回到基础,花了一些时间通读文档,在 Stack Overflow 中寻找例子和清晰的解释。

当我开始理解 mateplotlib 的 subplot 系统是如何错综复杂地工作时,我意识到如果有一个简单的 UI 工具可以测试你的代码并确切地看到你的图形中发生了什么,那么学习起来会容易得多。我找不到我要找的东西,所以我继续做了我自己的小网络应用,我称之为情节策划者!这是一个非常简单的工具。只要调整几个参数,看看它们如何改变你正在处理的支线剧情。

在本文中,我将使用我的 plot planner 工具来解释 matplotlib 的 subplot 系统的一些特性是如何工作的。具体来说,我将讨论两种方法。add_subplot()和. subplot2grid()。

但是说够了。我们开始吧!

subplot emojis!

。add_subplot()

figure.add_subplot()方法是将现有图形对象划分为不同大小的不同区域的最简单方法之一。它返回一个轴对象,并接受三个整数。如果这些整数中的每一个都是一位数,那么它们可以简化为一个三位数的整数。例如,。add_subplot(1,2,3)可以简化为。add_subplot(123)。但是这些数字实际上意味着什么呢?如果这几个栈溢出帖子上的话题,这里似乎有一些混乱。

关键是要理解,前两个整数定义了图形的划分,最后一个数字实际上表示了子情节应该在该划分中的位置。因此,如果您将子情节定义为(2,3,1),这意味着将子情节分成一个 2 x 3 的网格,并将新的子情节放在该网格的第一个单元格中。

你可以阅读更多关于。 matplotlib 文档中的 add_subplot()。

记住所有这些,让我们试着去做吧。我们将制作下面的例子,有 5 个不同大小的支线剧情。

我们将从标有 ax1 (红色)的那个开始。只需查看图像,ax1 似乎占据了图形区域的左半部分。首先,我们将定义我们的图形,并使它成为一个 8x8 的正方形(图形大小是任意的,但在这个例子中很好)。然后,忽略所有其他的次要情节,让我们把我们的图形分成两部分,左边和右边。

fig = plt.figure(figsize=(8,8))fig.add_subplot(1, 2, 1)

在这种情况下,这些数字的意思是— 取我的数字,以这样一种方式划分,即有 1 行和 2 列。最后一个数字表示要使用的单元格。奇怪的是支线剧情的索引是从 1 开始的,而不是你所期望的 0。所以当我们说使用第一个支线剧情时,我们是在告诉我们的图形进入第一个支线剧情的空间。

这是一个非常简单的次要情节,但是更复杂的会变得难以理解。这是因为每个支线剧情都是独立的,我们永远不会看到没有被选中的支线剧情。但这里有一个来自 plot planner 应用程序的图像,它可能会使整个事情变得更加清晰。

1 row by two columns. Select 1st subplot

我发现这种形象化比我看到的任何解释都要清晰得多。我们可以看到 1 行 2 列。然后,用绿色突出显示,我们可以看到编号为 1 的单元格是我们选择的子情节。太好了!我们的第一个次要情节完成了。

现在事情变得更有趣了。你可能会想,既然你已经把你的形象分成了左右两部分,那么你现在唯一的选择就是把右半部分留白,或者在那个支线剧情中设计一些东西。事实并非如此。

你定义的每个新支线剧情都不关心你已经制作的任何其他支线剧情。本质上,每一个新支线剧情都会愉快地按照你告诉它的方向发展,而不管其他支线剧情已经存在。

考虑到这一点,让我们创建 ax2 支线剧情(蓝色)。再来看这张图片,ax2 占据了图的右上象限。所以再一次,我们会忘记所有其他的支线剧情(甚至是我们已经做好的那个),我们只专注于在右上角做一个新的支线剧情。

为了做到这一点,我们希望将图形空间分成 4 个象限,并选择右上象限。让我们再看一下情节设计器,看看这是如何工作的。

由此看来,我们想要一个 2x2 的网格,我们想要第二个支线剧情。地块索引首先按行编号,然后按列编号。所以我们的代码应该是:

fig.add_subplot(2,2,2)

太好了!让我们来看看我们迄今为止的工作:

看来一切都上轨道了!现在我已经解释了一些基本原则,我将快速浏览剩下的次要情节。

对于 ax3 (黄色),它看起来大约是我们 ax2 插槽垂直尺寸的一半,出现在它的正下方。基本上,我们在寻找这个:

那将是 4 行 2 列,第 6 个支线剧情。或者:

fig.add_subplot(4,2,6)

最后两个支线剧情看起来一样大。在这里很难看到确切的比例,所以我会告诉你,我们正在寻找一个 8 行 2 列的图形分割。它看起来应该是这样的,我们想要为我们的两个新轴抓取第 14 和第 16 个支线剧情。

fig.add_subplot(8,2,14)fig.add_subplot(8,2,16)

我们现在应该有我们的数字完全充满了支线剧情。下面是完整的代码,添加了一些其他视觉元素(颜色、标签等)。).

import matplotlib.pyplot as pltfig = plt.figure(figsize=(8,8))ax1 = fig.add_subplot(1, 2, 1, xticklabels=[], yticklabels=[], xticks=[], yticks=[], fc="red",)ax2 = fig.add_subplot(2, 2, 2, xticklabels=[], yticklabels=[], xticks=[], yticks=[], fc="blue")ax3 = fig.add_subplot(4, 2, 6, xticklabels=[], yticklabels=[], xticks=[], yticks=[], fc="yellow")ax4 = fig.add_subplot(8, 2, 14, xticklabels=[], yticklabels=[], xticks=[], yticks=[], fc="green")ax5 = fig.add_subplot(8, 2, 16, xticklabels=[], yticklabels=[], xticks=[], yticks=[], fc="orange")ax1.text(0.5, 0.5, "ax1", horizontalalignment='center', verticalalignment='center')ax2.text(0.5, 0.5, "ax2", horizontalalignment='center', verticalalignment='center')ax3.text(0.5, 0.5, "ax3", horizontalalignment='center', verticalalignment='center')ax4.text(0.5, 0.5, "ax4", horizontalalignment='center', verticalalignment='center')ax5.text(0.5, 0.5, "ax5", horizontalalignment='center', verticalalignment='center')plt.show()

就是这样!现在你知道了支线剧情系统是如何与?add_subplot()方法。

的。add_subplot()方法当然可以是一个强大的工具,但它有其局限性。例如,你创建的每个支线剧情只能占用一个单元格。这意味着下面的事情是不可能的。add_subplot()(即使看起来更简单)。

这里的问题是红色支线图占据了图表左侧的 2/3。不幸的是。add_subplot()不能处理选择图形区域的 2/3。

为此,我们可以使用. subplot2grid()。

.subplot2grid()

比如。add_subplot(),. subplot2grid()返回一个 axis 对象,其中包含有关新的子情节应放置在何处的信息。它接受两个必需的位置参数,shape 和 loc。

shape 参数作为两个数的列表或元组传入,其功能类似于。add_subplot()方法。它们指定网格布局,第一个数字是行数,第二个数字是列数。

第二个参数 loc 代表 location,也是一个由两个数字组成的列表或元组。不像。add_subplot(),你不需要通过在你的网格上指定一个索引来指定把你的 subplot 放在哪里。相反,您可以通过指定想要放置子情节的行号和列号来选择网格索引。同样不同的是,. subplot2grid()从 0 开始索引。因此(0,0)将是网格中第一行第一列的单元格。

除了这两个参数,还有两个可选的关键字参数, rowspancolspan 。这就是我们真正体会到. subplot2grid()威力的地方。有了网格布局(shape)和起始索引(loc)之后,就可以用这两个参数来扩展选择,以占据更多的行或列。默认情况下,rowspan 和 colspan 都设置为 1,这意味着占用相当于 1 行 1 列的单元格。当您增加这些数字时,您可以告诉您的轴对象在当前的网格布局中占据尽可能多的相邻行和列。

让我们仔细看看上面那个只有 3 个支线剧情的例子。虽然这些支线剧情中有一些可以(或许应该)用。add_subplot(),我们将在这里对它们都使用. subplot2grid()进行练习。

正如我已经说过的红色支线剧情,我们需要它占据总高度的 2/3。那么我们如何用. subplot2grid()做到这一点呢?除了占了我们三分之二的行之外,它还被绘制在两列的左列。有了这些信息,让我们将网格分成 3 行 2 列,并将起始索引设置为左上角的单元格。最后,我们需要告诉我们的支线剧情占用我们的三行中的两行。为此,我们将 rowspan 参数设置为 2。因此,我们的网格和支线剧情应该是这样的。

a 3x2 grid, start at index (0,0), use 2 rows and 1 column

plt.subplot2grid((3, 2), (0, 0), rowspan=2, colspan=1)

正如您所看到的,对. subplot2grid()还有一点要求。但是它允许你非常精确地安排你的可视化空间!

让我们快速完成这个例子。我们接下来将处理蓝色网格框。就像我说的,你可以用。add_subplot()(图 add_subplot(325))。但是我们也可以用. subplot2grid()来完成这个任务。在我们的 3x2 网格中,我们希望这个子情节占据左下角的单元格。这在下面的绘图设计器的图像中进行了描述。

我们的网格形状是相同的(3,2)。因为我们只选择了一个单元格,所以我们将 rowspan 和 colspan 都设置为 1。我们只需要将 loc 参数指向正确的单元格。方便的是,plot planner 应用程序中的单元格标有该单元格在网格中的位置(尽管它们并不难理解)。从上面的图像中,我们想要 cell (2,0),所以我们将它插入到我们的 loc 参数中。代码将会是:

plt.subplot2grid((3, 2), (2, 0), rowspan=1, colspan=1)

对于最后一个支线剧情,我们只需要整个右栏。同样,这很容易通过。add_subplot(122)。我们也可以用 plt.subplot2grid((3,2),(0,1),rowspan=3,colspan=1)来实现。

变得更加冒险(接*荒谬),我们也可以用下面的代码完成右边的专栏。这只是为了说明可以做些什么,而不是如何解决这个问题的实际建议。

plt.subplot2grid((6, 6), (0, 3), rowspan=6, colspan=3)

将所有这些放在一起,我们得到了以下内容(同样,我添加了一些额外的代码来处理颜色和文本):

fig = plt.figure(figsize=(8,8))ax1 = plt.subplot2grid((3, 2), (0, 0), rowspan=2, colspan=1, xticklabels=[], yticklabels=[], xticks=[], yticks=[], fc="red",)ax2 = plt.subplot2grid((3, 2), (2, 0), rowspan=1, colspan=1, xticklabels=[], yticklabels=[], xticks=[], yticks=[], fc="blue",)ax3 = plt.subplot2grid((3, 2), (0, 1), rowspan=3, colspan=1, xticklabels=[], yticklabels=[], xticks=[], yticks=[], fc="orange",)ax1.text(0.5, 0.5, "ax1 \n(rows = 2/3)", horizontalalignment='center', verticalalignment='center')ax2.text(0.5, 0.5, "ax2", horizontalalignment='center', verticalalignment='center')ax3.text(0.5, 0.5, "ax3", horizontalalignment='center', verticalalignment='center')plt.show()

以及由此产生的视觉效果:

现在你知道了!的基础演练。add_subplot()和. subplot2grid()。如果你想自己尝试一下,或者只是想得到一点帮助来为一个复杂的布局建立索引,可以看看我的 plot planner 工具。

感谢你的阅读!

子空间聚类

原文:https://towardsdatascience.com/subspace-clustering-7b884e8fff73?source=collection_archive---------6-----------------------

高维空间中的挑战

这篇文章回答了以下问题:

  1. 处理高维数据的挑战是什么?
  2. 什么是子空间聚类?
  3. 如何用 python 实现子空间聚类算法

高维数据存在于具有几十到几千个特征(或维度)的输入中。这是在生物信息学(各种测序数据)或 NLP 中经常遇到的情况,其中词汇表的大小非常大。高维数据具有挑战性,因为:

  • 这使得可视化和理解输入变得困难,通常需要预先应用降维技术。它导致了“维数灾难”,这意味着随着维数的增加,所有子空间的完全枚举变得难以处理
  • 大多数基本的聚类技术依赖于结果和降维技术的选择
  • 许多维度可能是不相关的,并且可能掩盖噪声数据中的现有聚类
  • 一种常见的技术是执行特征选择(删除不相关的尺寸),但有时识别冗余尺寸并不容易

什么是子空间聚类?

子空间聚类是一种在不同子空间(一个或多个维度的选择)中寻找聚类的技术。潜在的假设是,我们可以找到仅由维度子集定义的有效聚类(不需要所有 N 个特征都一致)。例如,如果我们考虑将观察基因表达水*的患者数据作为输入(我们可以有超过 20000 个特征),仅通过查看 100 个基因的子集的表达数据就可以发现患有阿尔茨海默病的患者群,或者换句话说,该子集存在于 100 个基因中。换句话说,子空间聚类是传统 N 维聚类分析的扩展,它允许通过创建行和列聚类来同时对特征和观察值进行分组

得到的聚类可能在特征空间和观测空间都重叠。另一个例子如下图所示,摘自的论文。我们可以注意到,来自两个聚类的点可能非常接*,这可能会混淆分析整个特征空间的许多传统聚类算法。

此外,我们可以看到子空间聚类设法找到一个子空间(维度 ac ),在这个子空间中,期望的聚类是容易识别的。

子空间聚类的类型

根据搜索策略,我们可以区分两种类型的子空间聚类,如下图所示:自底向上方法从在低维(1 D)空间中找到聚类开始,并迭代地合并它们以处理更高维空间(高达 nd)。自顶向下的方法在全维集合中寻找聚类,并评估每个聚类的子空间。下图摘自同一篇论文,概述了最常见的子空间聚类算法。

团算法

为了更好地理解子空间聚类,我在 python 这里实现了团算法。

简而言之,该算法的功能如下:对于每个维度(特征),我们在 nBins( 输入参数)中分割空间,并且对于每个 bin,我们计算直方图(计数的数量)。我们只考虑密集单元,即计数高于作为第二输入参数给出的阈值的仓。密集单元具有以下特征:

  • 它所属的尺寸(例如特征 1)
  • 容器的索引(或位置)(从 0 到 nBins)
  • 躺在箱子里的观察报告

在我的实现中,我已经在 2D 空间中生成了 4 个随机聚类,并且我已经选择了 8 个箱和 2 个点作为最小密度阈值。下图显示了应用于输入空间的结果格网。

Input space split in 8 bins per dimension

clique 算法背后的直觉是存在于 k 维空间中的聚类也可以在 k-1 中找到。我们从 1D 开始,对于每个维度,我们试图找到密集的箱。如果两个或更多的密集仓是相邻的,我们将它们合并成一个更大的仓。该操作可以通过将所有现有的密集面元转换成图来容易地实现,其中如果 2 个密集单元属于相同的维度并且它们的面元索引之间的差不超过 1(例如,对应于特征 3 和面元 4 的密集单元是相同特征的密集单元以及面元 3 和 5 的邻居),则绘制边。要合并的密集单元可以通过计算上述图上的连通分量来识别。

该合并操作的结果为第一维度检索 1 D 中的以下聚类(每个聚类一个图):

对于第二维度:

接下来,我们要计算从 2 到输入维数的每个子空间中的所有有效聚类。该操作归结为计算 k 维中密集单元的组合,并且仅保留具有大小大于初始最小密度阈值的密集连续箱的重叠的结果。一旦我们计算了 k-1 维的密集单元,我们可以通过计算最后 k-1 个候选的所有组合来扩展到 k 维。

因此,在 2 D 中,我们能够检索下图所示的集群。注意,4 个聚类之外的一些点(紫色)是因为它们属于密度低于任意输入 2 的箱。

团聚类因其对输入参数(箱的数量和最小密度)的高度敏感性而受到批评,这会导致非常不同的结果。然而,它是自底向上子空间聚类家族中的一个基本算法。有多种方法可以优化 clique 算法,例如通过使用 MAFIA 算法中提出的密度自适应网格。

参考

小团体论文

黑手党算法

子空间聚类方法的比较研究

子空间聚类方法的介绍

在小公司/初创公司中成为成功的数据科学家

原文:https://towardsdatascience.com/succeeding-as-a-data-scientist-in-small-companies-startups-92f59e22bd8c?source=collection_archive---------4-----------------------

这与成熟的大公司完全不同。

这可能会是一个无限的帖子系列,从这个问题衍生而来,这个问题来自一个令人敬畏的社区,即数据呆子 twitter 集群:

一些背景

我已经在规模在 15-150 之间的公司工作了将* 12 年,身兼数据分析师、工程师以及偶尔的科学家等各种职务。作为一名 UX 的研究人员,走进大型企业谷歌云有点不符合他的性格,但随着新产品不断涌现,就问题和混乱而言,这感觉就像一家初创公司,尽管涉及数十亿美元的总收入。

我曾在室内设计(办公室设计)、广告技术、社交网络、链接缩短、电子商务以及现在的企业云等多个领域工作过。我有社会科学背景,有一点 NLP,应用数学和工商管理。我主要生活在后端系统、日志和 SQL 中。

一句话,我是一个多面手,就是人们似乎会推荐给初创公司的那种,而这正是我整个职业生涯蓬勃发展的地方。

这些是我的偏见,也是我从中汲取的经验。如果你在一家初创公司,人工智能/人工智能实际上是业务的核心基础,我可能与你的需求无关。YMMV。

成为第一个“数据人”

我就直说了, 小公司不需要一个数据科学家,但是需要一个“数据人”。 他们可能会称这份工作为“数据科学家/工程师/分析师/忍者”,随便什么。

我的经验是,在 20 至 60 名员工之间,有足够的客户、积累的数据和角色专业化,需要引入能够利用数据提供有用商业见解的人,这开始证明雇佣某人的成本是合理的。在那之前,他们用现有的技能凑合着过日子。

职位几乎可以是任何东西,但是职位描述往往是以下各项的混合:

  1. 理解我们拥有的数据
  2. 帮助建立我们的数据系统
  3. 帮助我们实现数据驱动/运行实验
  4. 发展业务
  5. 教育/认证可能与任何事情相关,也可能不相关

通常很有可能他们并不真正完全了解他们需要什么。这只是一种广义的感觉,“我们有数据,它似乎很有用,但我们没有任何人有技能让它变得有用。”

实际上,担任这个职位的人需要同时做两件大事:

  • 帮助公司今天取得成功
  • 让公司明天成为数据驱动型企业

帮助公司取得今天的成功

创业公司被不确定性所包围。他们不确定谁是他们的客户,生产系统可能不可靠,他们不知道他们的客户在用产品做什么,他们不知道如何利用他们拥有的数据做出决策,他们不知道他们拥有的数据是否有用。

对这些问题的聪明回答会导致更聪明的决定,并有希望实现每个人梦寐以求的神话般的曲棍球棒增长。问题是,这些问题中的大部分并不适合花哨的方法。有用的方法通常是一个世纪前的和/或基于定性方法而不是定量方法。

大多数 DS 方法在优化现有流程时是最有效的,它们会在客户获取、转换、保留和支出等方面为您带来 5%、10%甚至 25%的增长。A/B 测试,推荐系统,ML 分类器,这些都有助于优化。收益是真实的,可量化的,并且可能是显著的,但是早期可能有更大的鱼要煎。

早期最大的影响通常涉及洞察力。洞察力从根本上改变了公司的行为。它们来自非常*凡的事情,比如对用户偏好/行为的研究,为销售人员揭示了一个新的营销概念,或者帮助产品团队认识到 Twitter 上最令人讨厌的功能实际上被 90%的付费客户使用,他们不应该无缘无故地放弃它。

我对这个“现在就帮助公司”角色的看法是,数据人是一个力量倍增器。企业内部的人有问题,工作就是帮助他们解决问题。

成为第一个“数据人”=成为“拥有数据的科学家”

对我来说,成为一名科学家意味着你有一个问题,一个研究问题,并且你使用任何你能使用的方法来得到这个问题的可靠答案。

作为数据科学家,我们倾向于使用定量方法和从系统中收集的数据来回答问题,但这不是获得洞察力的唯一途径。有时你会全力观察或询问用户(定性方法),或者你出去收集数据(实验和调查),或者你观察其他人(竞争分析)。一个好的科学家不会用他们的方法来定义自己,第一个数据人(或任何后来的数据人)也不应该。

目标是回答紧迫的业务需求:“为什么没有人使用我们的产品?”“我们的回报怎么会这么高?”我们该不该进行这次昂贵的拍卖?”“是什么推动了客户流失?”“客户的终身价值是什么,是什么推动了这种价值?"

成为数据驱动的未来

我看到的一个常见陷阱是,数据科学专业毕业的人加入这些职位时,期望使用 Spark 等性感的东西,并将 RNNs 应用到他们的工作中。但可悲的是,他们想住在需要首先完成的基础工作的山顶上,从工程角度来看是,从文化角度来看是。这种不匹配是残酷的。

Fancy “Data Science” methods rely on a ton of things, DO NOT expect each layer to be “done” before moving to the next. Think of the colors as “time spent”.

作为第一个被专门雇佣来处理数据的人,金字塔的任何部分都不太可能是坚固的。这是一项历时多年、跨职能、全公司共同努力的工作,旨在将所有部分都落实到位。并行培养所有这些部分是这项工作的一大部分。

请注意,在一个典型的业务中,您将试图同时在金字塔的上下游做事情,而不管底层的稳定性如何。我已经针对脆弱的新系统构建了大量的仪表板和分类器,您也一样。

关于所有这些东西的各个方面,有足够的空间来发表大量的帖子,但这里是我的想法的粗略概述。

固体生产系统和工程实践

这是一件在工程领域非常常见的事情,但是如果一个系统有问题并且损坏了,你就不能真正地测量这个系统的行为,所以期望在需要的时候能帮上忙。

你最终戴的“数据工程师”的帽子越多,你在帮助构建可靠的系统中扮演的角色就越大。人们自然会问你一些问题,比如 PostgresSQL 对 MySQL,AWS 对 GCP,Spark 对 Redshift 等等。帮助这些决定增加了持久的价值。如果没有足够的工程资源,你必须自己建立系统并运行它们。

我还发现,出于商业目的将工程推向仪器系统有一个很好的副作用,那就是发现有趣的 bug。有一次,我在一个不应该有 dupes 的关键表中发现了重复的 id,那是一组 bug hunt,它修复了一个创收系统中的一些东西。经常查看生产表可以发现非常奇怪的错误。

可靠的仪器

垃圾进,垃圾出。

获得可靠的仪器是第一数据人员做的最重要的事情。这是一个无止境的旅程,从挑选框架(多个)到收集系统和用户数据,确保工程师学会如何在不计算错误(这很容易发生)的情况下实现事情,确保数据库和日志做正确的事情(tm),并确保你正在计算你认为你正在计算的东西。

同时,将增加专门收集和报告数据的系统。这些需要由某个人,也许是你来整理和管理。

在文化方面,从新人到首席执行官,每个人都会不断询问数据的可靠性以及如何处理这些信息。他们会要求澄清,解释,深入了解他们自己建立的系统。

这种文化培训本身就是一个漫长的旅程,因为你要制作报告和仪表板,人们会发现与其他系统不一致的地方,并得到与他们对现实的看法不一致的结果。有时他们的现实是错误的,但通常他们是正确的。仅仅是这些对话就能让所有参与其中的人变得更聪明。

老实说,我不认为这个阶段是“完全”的,它只是达到了一个点,当一个新的特性或大的变化出现时,你只需要担心它。

报告和处理数据

仪表板和报告并不是一个性感的工作,但不幸的是,这通常是整个公司的人每天观察公司健康状况的第一/唯一方式,因此投资是必要的。目标是将(潜在的)可操作信息放在能够主动采取行动的人手中。

开始时,大多数仪表板和报告将是手动的。这需要大量的迭代来发现人们足够关心多次看到的指标。自动化是一个不错的选择,但是获得洞察力更重要。

技术方面并不超级复杂。有许多服务和*台可以生成报告和仪表板,您甚至可以使用自定义代码来完成。诀窍是让所有的数据系统一起发挥作用(Ha),有良好的性能,并尽量减少(重大!)随着业务增长维护仪表板和报告的开销。

文化方面是有趣的地方。你在训练人们变得更加数据驱动。这也需要多年的工作和练习。

这里涉及到大量的教育。你将教人们如何阅读 A/B 测试的结果,显著差异意味着什么,解释什么是置信区间/预测区间,解释为什么该图表“只是一个估计,因为我们依赖于第三方报告,它们是不可靠的”。你将回答关于样本大小的问题(永远不够),并不断需要教人们好的方法。

如果人们担心仪表板上的数字,他们应该怎么做?就我个人而言,我告诉他们来和我谈谈。他们关心的是潜在的研究问题(或缺陷),这是字面上的研究黄金。这些人是这部分业务的领域专家,而我只是一个使用 SQL 的书呆子。

自动化和实验

随着时间的推移,您将为新功能的推出建立指标和仪表板。不可避免地,人们会对某个功能的表现感到失望,并想知道为什么。如果你还没有学会前/后分析方法,还没有记住你的主要市场的所有节假日,现在是时候这样做了。

一旦人们习惯了拥有信息,并可能运行一些 A/B 测试得到令人失望的结果,当测试数据与人们的假设相反时,预计将花费大量时间来验证数字是否正确。

尽管有那些痛苦的时刻,我们现在终于在做真正的科学了。提出假设并收集数据进行测试。

到目前为止,有用的仪表板应该是相当自动化的,人们习惯于使用数据来做出决策。当一个新功能被提出时,你知道你已经到了,“我们将如何判断它的成功?”不用你去争取就会出现。

我注意到的另一件有趣的事情是,在这个阶段,一家公司可能会过于舒适地进行实验。他们学习设计他们知道会成功的测试(低风险),或者他们会“测试”一个他们 100%知道不管结果如何都会启动的东西(“我们稍后会优化它”)。

作为科学家,现在你的工作是呼吁人们关注这种行为。他们可以完全不顾测试结果而推出,激进的改变往往测试效果不佳,但应该明确说明意图。

最后,数据科学

在经历了漫长、漫长、漫长的旅程和许多弯路之后,公司本身已经过渡到数据驱动。他们有假设,能够可靠地收集数据,并根据结果做出深思熟虑的决定。他们也更加自给自足,能够阅读(也许创建)带有一些指导的仪表板,并且已经学会何时担心以及如何提出问题。

在金字塔的底部总会有事情要做,但至少现在事情不会一直着火。企业有望更好地了解其在市场和世界中的位置,并且兴趣转移到优化现有流程以获得增量(但显著)收益。

现在,你可以考虑打破花哨的算法…

或者,可能有一个数据仓库需要构建,因为您现在有太多的系统,分析查询无法进一步加速,哎呀。

欢迎评论/反馈

我一口气写完了整篇文章,因为内容需要一个出口。由于篇幅原因,我已经掩盖了一大堆东西。因此,我们非常欢迎对未来帖子的任何反馈和主题请求。在推特上给我打电话。

成功的政府绩效管理

原文:https://towardsdatascience.com/successful-performance-management-in-the-government-6cfc967e0622?source=collection_archive---------19-----------------------

为什么系统的失败对管理者来说是一个潜在的胜利

Photo by Stephen Dawson on Unsplash

在过去的四十年里,美国联邦政府越来越多地使用绩效管理系统。虽然早期支持者的关注点是绩效管理的潜在好处和使用绩效信息进行政策衡量,但最*的工作对基于政策的系统的功效提出了质疑。然而,通过子机构的采用和实施,可以实现显著的好处。

绩效信息的公开是为了监控政策和计划的有效性。例如,我们能否在全系统的基础上衡量监狱改革立法、福利转工作计划或医疗改革的成功?

不幸的是,的研究显示,在美国,绩效管理还没有在系统层面上运作良好。这主要是因为虽然国会和州立法机构经常需要这些指标和数据,但它们通常不会用于基于政治现实的项目审查或预算过程。

然而,研究表明,在联邦机构的决策中成功地使用了绩效信息,最常见的是在办公室或局一级。在这一级,产生的信息与办公室的目标联系更紧密,反馈回路更紧密,可以说会导致更有效的采纳。

什么是公共部门绩效管理?

绩效管理可以从衡量特定流程的输入和输出的角度来考虑。在公共部门,这承担了与预期政策的产出和结果相关联的绩效信息的额外定义;衡量它们是否符合最终的政策目标,以评估大多数情况下的有效性以及效率。

在公共部门,关注成就和结果也很重要,而不仅仅是财务方面。因此,虽然私营部门可能会关注商业情报和绩效信息,而这些信息关注的是利润和市场份额,但公共部门项目通常会关注与目标和效率一致的结果。

业绩信息的另一个重要特征是,它是定量的,通过报告、数据库变得透明,并包含与公开宣布的目标一致的客观标准。这是数据科学团队花费时间编译输入/输出数据,并为内部和外部利益相关者创建有用的报告和仪表板的地方。

我们定义为绩效信息的收集是有意的,遵循一个设计好的信息创建、收集、分析和报告系统。这一点很重要,因为它不同于简单的数据收集和分析,后者是特定的,而不是基于逻辑模型或预期的因果关系有目的地设计来测量程序。

绩效管理运动简史

绩效管理起源于私营部门,并从早期的科学管理运动中被采纳。科学管理相信你可以衡量一切;从输入、过程、程序和输出。

通过衡量一切并应用分析来发现流程中低效的部分并确定新的流程,公司可以通过更好地利用资源和消除浪费来实现利润最大化。

公共部门对绩效管理的采用通常来自管理顾问、拥有私营部门经验和偏好的任命领导层,以及希望将私营部门的“效率”带到公共部门的政治家。

从根本上来说,这场运动承诺了效率、效力和透明的监督。这些长期以来一直是政治家和公民对联邦政府的要求。

从政治角度来看,绩效管理运动是一种证明从公民那里收取的税款费用是合理的方式。在其他情况下,它是一种机制,用于识别和确保对他们在政治上或政策议程上重要的项目或政策的有效实施。

根据 1993 年的政府绩效结果法案(GPRA) ,美国国会要求联邦机构实施绩效管理技术。GPRA 要求各机构通过五年战略计划公开设定目标,根据这些目标衡量其年度进展,并提交年度进展公开报告,以确定其实现目标的成败。

在 GPRA 之后,为了回应一些领域的关注和批评,联邦机构也被要求遵守项目评估评级工具(PART)。第一部分要求机构回答有关其项目的评估问题,以证明预算的合理性.

最*,国会于 2010 年通过了 GPRA 现代化法案(GPRMA ),旨在纠正 GPRA 的失误和失败,并重新建立国会对行政部门绩效管理指导的控制,因为这被视为部分党派之争。具体而言,GPRAMA 要求各机构以机器可读的格式在线发布其报告和战略计划。它还强调制定较少量的较高层次的目标,以及确定具体的机构间优先目标。这背后的意图是将焦点、精力和注意力限制在更少的目标上,以使机构领导层能够保持关注,并更成功地进行项目改进。

现在政府正在创建绩效信息,它在政策和项目决策中的使用频率和效果如何?

认识到政治局限性

在高度政治化的政策领域,价值观、谈判和说服通常会排挤使用专业知识和数据来指导决策或问题讨论。当政治推动决策时,必然会产生冲突、权衡和妥协的结果,这些结果本质上很可能不符合客观数据和基于证据的建议。

值得注意的是,这可以而且应该从美国政府这样的代议制民主结构中得到。事实上,几位已经指出,绩效管理运动的客观和简单的数据驱动目标与要求民选官员代表的政治体系有些不相容。

成功采用绩效管理的关键因素

在决策中成功使用绩效管理的一个最重要的发现是经理是最重要的因素之一。然而,并不总是以你期望的方式。

研究人员已经确定了经理的某些特征,这些特征可以鼓励在组织决策中使用绩效信息。这些因素是经理的自我效能感对反馈的感受性、s 对外部环境的敏感性、以及他们对员工投入的重视程度。这些发现背后的想法是,经理的个性可以通过塑造好奇的天性来“摆好桌子”,从而积极影响组织中绩效信息的使用。

其他研究发现,绩效信息使用与组织绩效之间的关系很重要。这些发现支持这样一种观点,即要成功运用绩效管理,它必须与新的愿景、利益相关者更好的结果或组织的重大变化联系起来

组织战略也很重要。当绩效信息与延伸目标或创新相关联时,您更有可能体验到绩效信息的成功实施和使用。如果用于监控现有的工作和目标,这些系统的效率将会降低。因此,经理们不应该仅仅把它放在现有的流程和产品上,而是应该把它的采用与新的计划联系起来,并把组织团结在他们的后面。

组织文化、灵活性和专业性也被发现与绩效信息的使用呈正相关。此外,个人经理层和组织文化层的公共服务动机的存在是绩效信息使用的良好预测因素。

培训员工

毫不奇怪,培训会影响联邦政府成功采用和实施绩效评估。

这一点很重要,因为每一个连续的绩效管理原则都将培训确定为一个必要的组成部分。事实上,GPRAMA 特别要求政府确定并实施对机构工作人员的必要培训。

虽然大部分培训旨在对员工进行绩效管理要求和系统的教育,但能力培训将通过向他们提供所需的知识和技能,而不仅仅是告知他们要求,来帮助机构员工成功实施和使用绩效信息。能力培训应包括涵盖如何衡量绩效、如何运用判断力、如何从绩效数据中学习以及如何将绩效数据用于问责目的的课程。

结论

绩效管理很可能以某种形式留在公共部门。除非美国代议制民主结构发生重大变化,否则我们不太可能看到绩效信息被用来客观地决定采取哪些政策和计划。相反,这些很可能仍然是基于价值的决策,由选民和利益相关者提供信息。

我不认为这是基于表现的运动的失败,而是对我们依赖选民意见的制度的承认。有希望的是在次级机构一级采用和实施业绩管理的程度。

此外,使用绩效信息进行战略规划、制定计划和程序变更,以及向领导层提供见解和反馈的成功案例越来越多,令人印象深刻。

此外,有一项很有前途的工作是研究领导力如何将绩效信息与基于证据的政策和计划评估的理念相结合,不仅可以监控领导力并为其提供信息,还可以探索关于产出和结果之间因果联系的假设。这可以更好地确定性能信息应该测量什么,以确保报告的指标是正确的指标。

即使这些信息没有直接插入到政治决策中,它仍然会确保我们的政策项目有更大的效力和效率,而这些正是我们的目标。

此外,它确实为利益集团、研究人员和监督组织提供了更好的信息和透明度,从而可以在政治领导层和选民需要时向他们报告。

后续不确定性

原文:https://towardsdatascience.com/successor-uncertainties-b498097827fb?source=collection_archive---------19-----------------------

无模型强化学习的高效探索

我在这里描述一下我们最*的 NeurIPS 论文【1】【code】,介绍了无模型强化学习中高效探索的最新方法后继不确定性** (SU)。**

主要作者是来自剑桥 机器学习小组 的两名博士生 David JanzJiri Hron ,这项工作源于 David Janz 在 微软剑桥 研究院实习期间。

SU 背后的主要见解是使用概率模型描述 Q 函数,该模型直接考虑 Q 函数值之间的相关性,如贝尔曼方程所示。这些相关性在以前的工作中被忽略了。

结果是一种方法,即在表格基准和 Atari 游戏上胜过竞争对手,同时仍然是快速高度可扩展

问题描述

我们考虑一般的强化学习 (RL)设置,其中代理通过采取动作 a_t,与具有状态 s_t 的环境进行交互,然后环境通过转换到状态 s_t+1 并给出奖励值 r_t+1 进行响应,如下图所示。

环境通常是由未知的跃迁分布 P(s_t+1,r_t+1|s_t,a_t)完全确定的随机马尔可夫,。

代理使用策略函数 π(a|s)选择其下一个动作作为当前状态的函数,π(a|s)是给定当前状态下动作的概率分布,即π(a|s)=P(a_t=a|s_t=s)。

RL 的目标是从与环境的相互作用中找到一个政策函数,该函数使贴现回报的期望总和最大化

其中 0≤γ<1 保证和是有限的。

RL 中的主要挑战之一是,行为对奖励的影响通常会延迟,直到很久以后才会被察觉。这使得很难确定在任何给定状态下采取的最佳行动。

q-函数和广义策略迭代

当根据政策π行动时,一种立即说明行动对未来回报的影响的方法是使用状态-行动值函数Q 函数。

Q 函数返回当在状态“s”采取行动“a”然后根据π行动时将获得的折扣奖励的预期总和。特别是,

其中期望是π选择的未来行动和环境的转移概率。

Q 函数可以被示为满足贝尔曼方程,因为在特定状态的动作的值取决于在后续状态的其他动作的值。特别是,

该等式清楚地表明 Q 函数不是任意函数,并且必须满足 特定约束。这将是 SU 设计中的关键,这是在构建 Q 函数的概率模型时考虑这些约束的第一种方法。

政策改进

Q-函数非常有用,因为我们可以通过贪婪地对π的 Q-函数采取行动来获得比π更好或等于π的新策略π_new。这个过程叫做政策完善。当行动空间离散时,我们得到以下贪婪策略

政策评价

为了实现策略改进,我们需要对当前策略的 Q 函数进行估计。这一估计最初可能不可用。获得这种估计的一种方法是对 Q 函数的初始随机猜测重复应用贝尔曼算子:

它根据其他状态-动作对的 Q 值来更新一个状态-动作对的 Q 值。这个过程叫做政策评估

广义策略迭代和有效探索

大多数无模型 RL 方法通过从初始随机策略开始,然后以不同程度的粒度交替策略评估和策略改进步骤来找到最优策略。这被称为广义策略迭代 (GPI)。

在许多 GPI 方法中,贝尔曼算子在政策评估步骤中所要求的期望值通常通过蒙特卡罗*似,通过对从与环境的交互中收集的数据求*均

好的实证结果的一个关键因素是如何收集数据以便快速收敛到最优政策。高效探索指的是与环境的智能互动,旨在使这种快速融合在实践中发生。

然而,大多数情况下,无模型 RL 方法不执行有效的探索,并且只是通过遵循具有概率 1-ɛ的贪婪策略,然后选择具有概率ɛ.的随机动作来收集数据

汤普森采样和概率 Q 函数

Thompson sampling (TS)是一种有效收集数据的策略,该策略在许多不同领域都非常成功。特别地,我们的方法 SU 使用 TS 的*似版本来进行有效的探索。

在一般设置中,TS 通过迭代执行以下两个步骤来工作:

  1. 在给定可用数据的情况下,后验分布中关于数据生成机制的样本假设“H”。
  2. 根据采样的“H ”,通过最佳动作收集新数据。

下图显示了当我们想要最大化一个未知的目标函数时,TS 迭代的一个例子。

图 1 显示了通过在三种不同输入下评估目标获得的数据。图 2 显示了给定目前收集的数据的目标后验分布的样本。曲线 3 显示选定的样本,曲线 4 显示使采样函数最大化的输入。这个输入是我们下一步根据 TS 收集数据的最佳动作。

在 RL 设置中,TS 通常被称为强化学习的后验采样(PSRL)【5,6】。当 TS 应用于 RL 问题时,“H”是一个特定的转移分布,并且“H”上的后验概率是在给定观察元组(r_t+1,s_t+1,s_t,a_t)形式的数据的情况下计算的。相对于特定“H”的最佳动作包括为采样的 P(s_t+1,r_t+1|s_t,a_t)找到最佳策略

这意味着上面的步骤 2 在实践中是高成本的,因为一旦我们采样了特定的跃迁分布,最优行动需要解决由采样的 P(s_t+1,r_t+1|s_t,a_t)指定的新 RL 问题。

结果是汤普森采样在大多数 RL 问题中是不可行的

概率 Q 函数

RL 中 TS 的巨大计算成本促使研究人员提出*似方法。

一种常见的方法是在 Q 函数上使用后验分布,而不是在转移分布上使用后验分布。这种方法通常被称为随机化价值函数(RVF)【7】。在这种情况下,对从后验分布采样的假设采取最优行动与为采样的 Q 函数计算贪婪策略一样简单。

RVF 在实践中被证明是成功的,导致 RL 方法执行更有效的探索。然而,当 Q 函数由神经网络*似时,这种方法仍然具有局限性

首先,获得 Q 函数的后验分布并不简单,因为当我们执行非策略 RL 时,我们无法直接访问 Q 函数的输入和相应输出值形式的数据。许多使用神经网络*似的 RVF 方法错误地假设情况就是这样。此外,这些方法还存在以下两个问题之一:

  1. Q 函数上的分布忽略了函数值之间的相关性,例如由贝尔曼方程给出的相关性。
  2. Q 函数上的分布捕捉到了这些依赖性,但是计算成本很大

SU 没有这些问题,因为它捕获了由贝尔曼方程给出的依赖性,并且具有低计算成本。

后续不确定性

给定策略π的 Q 函数上的后验分布可以通过以下方式获得:首先,从观察到的元组(r_t+1,s_t+1,s_t,a_t)计算转移分布上的后验分布,然后将该后验分布映射到 Q 函数上的对应分布。

令人惊讶的是,当转移分布满足以下假设时,前面的操作可以直接完成:

  1. P(r_t+1|s_t,a_t)由线性高斯模型r _ t+1 =(s_t,a_t)+ϵ_t,其中 ϕ (s_t,a_t)是状态和动作的特征表示,ϵ_t 是高斯噪声。
  2. 忽略关于 P(s_t+1|s_t,a_t)的不确定性。

奖励的先前线性模型导致 Q 函数的对应线性模型。特别是,

其中 ψ (s_t,a_t)为后继特征【10】,即π下每个 ϕ (s_t,a_t)的折现期望未来发生。

在对于 w 的高斯先验下,我们获得对于 w 的高斯后验 N( w|m,S ),在前面的等式下,导致对于 Q 函数的完全相关的高斯后验,均值和协方差函数由下式给出

由于 Q 函数仅针对给定策略π定义,我们假设该策略是通过从后验分布中采样 Q 函数而获得的*均贪婪策略

这个协方差函数保证采样的 Q 函数将满足贝尔曼方程

实际实施

初始特征 ϕ (s_t,a_t)和后续特征 ψ (s_t,a_t)使用多头神经网络计算,每个可能的动作值和特征类型( ϕψ) 一个头。每个头的输出乘以 m 以获得对下一个奖励和 Q 函数值的预测。

下图显示了 Atari 游戏设置的整个过程,头部的输入由一个卷积神经网络给出,后面是一个完全连接的层。在表格环境中,网络的这一部分可以由状态的一次热编码来代替。

苏通过优化学习神经网络的参数和 m

期望超过通过与环境交互收集的元组(r_t+1,s_t+1,s_t,a_t)。

上述目标包括三种不同的损失条款。第一个是后续特征时间差误差。此项强制 ψ 收敛于 ϕ 的贴现预期未来发生。第二个损失项调整 mϕ ,使得回报预测中的误差较低。最后,第三项是 Q 函数和的估计中的时间差异误差,它强制 ψ 也适用于预测 Q 函数值。

最后,根据高斯线性模型中的贝叶斯规则在线更新协方差矩阵 S :

其中β是奖励的线性模型中的噪声方差,0≤ζ≤1 是允许模型遗忘的衰减因子,这有助于在学习过程中对抗 ϕ 的非*稳性。在下面的实验中我们用了β = 0.001(二叉树)和β = 0.01(雅达利)和ζ = 1(二叉树)和ζ = 0.99999(雅达利)。

二叉树基准的实验

我们评估了 SU 在一个需要高效探索的挑战性问题上的表现。在这个问题中,见下图,有 2L+1 状态和两个可能的动作,这两个动作在环境生成时被随机映射到每个状态中的向上向下的运动。奖励总是 0,除非在到达产生奖励 1 的 s_2L 州之后。奇数指数和 s_2L 的状态是终端。

这个问题具有挑战性,因为代理将总是获得奖励 0,除非问题被解决,如果没有智能探索,这将以指数小概率发生,作为 L 的函数。

下图显示了学习最佳策略所需的发作次数的中位数。将 SU 与其他 RVF 方法进行比较,如贝叶斯 DQN ( BDQN ) [3]、不确定性贝尔曼方程( UBE ) [2]和自举 DQN [4]。后一种方法用一组 Q 函数估计量来逼* Q 函数后验。

BDQN 和 UBE 执行与相同的策略,随机地对行为进行统一采样****,并且当 L 很大时,他们都努力寻找最优策略。自举的也比苏差,当自举的使用比苏多 25 倍的计算时,差距变得更小。原因是我们的贝叶斯线性模型使用的分析更新允许不确定性得到真正快速的解释,而 bootstrap DQN 更依赖于基于梯度的更新。

雅达利游戏的实验

为了表明它可以扩展到复杂的领域,我们在 49 个 Atari 游戏的标准集上评估了 SU[8]。实施、网络架构和培训程序的具体细节可以在[1]中找到。在[9]中描述的“无操作启动 30 分钟模拟器时间”测试协议下,在 200 米训练帧后,SU 获得了 2.09 的中值人类标准化得分(3 粒种子的*均值)。下表显示 SU 明显优于竞争方法。

关于更多细节,SU 和各个游戏的竞争算法之间的人类标准化分数的差异绘制在下图中。

Bars show the difference in human normalized score between SU and Bootstrap DQN (top),
UBE (middle) and DQN (bottom) for each of the 49 Atari 2600 games. Blue indicates SU performed
better, red worse. SU outperforms the baselines on 36/49, 43/49 and 42/49 games respectively.
Y-axis values have been clipped to [−2.5, 2.5].

摘要

后继不确定性是无模型强化学习中高效探索的最新方法。尤其是苏

  1. 是 Q 函数的第一个概率方法,它结合了贝尔曼方程给出的依赖性。****
  2. 是高度可扩展的,和以前的方法一样快或者更快。
  3. ****在表格基准测试和雅达利游戏上胜过竞争对手

参考

[1] Janz D .,Hron J .,马祖尔 p .,霍夫曼 k .,埃尔南德斯-洛巴托 J. M .和 Tschiatschek S. 后继者的不确定性:时间差异学习中的探索和不确定性,载于 NeurIPS,2019 年。*同等贡献者。**

[2]b .奥多诺格、I .奥斯本、r .穆诺斯和 v .姆尼赫《不确定性贝尔曼方程与探索。在 2018 年的 ICML。

[3] Azizzadenesheli,k .、Brunskill,e .和 Anandkumar,A. 通过贝叶斯深度 Q 网络进行有效探索。在 2018 年的 ICLR。https://openreview.net/forum?id=Bk6qQGWRb

[4] Osband,I .、Blundell,c .、Pritzel,a .、Van Roy,B. 通过自举 DQN 进行深度探索。在 NeurIPS,2016。

[5] Strens,M. 强化学习的贝叶斯框架。2000 年在 ICML。

[6] Osband,I .、Russo,d .和 Van Roy,B. (更)有效的通过后验抽样的强化学习。在 NeurIPS,2013 年。

[7] Osband,I .、Van Roy,b .、Wen,Z. 通过随机值函数进行概括和探索。2016 年在 ICML。

[8] Mnih,v .,Kavukcuoglu,k .,Silver,d .,鲁苏,A. A .,Veness,j .,Bellemare,M. G .,Graves,a .,Riedmiller,m .,Fidjeland,A. K .,Ostrovski,g .,等人通过深度强化学习实现人的水*控制。自然,518(7540):529,2015。

[9] Hessel,m .,Modayil,j .,van Hasselt,h .,Schaul,t .,Ostrovski,g .,Dabney,w .,Horgan,d .,Piot,b .,Azar,M. G .,和 Silver,D. 彩虹:结合深度强化学习的改进。2018 年 AAAI 人工智能大会。

[10] Dayan,P. 改进时间差异学习的概括:后继表征。神经计算,5(4):613–624,1993。

SudachiPy:一个用 Python 编写的日语词法分析器

原文:https://towardsdatascience.com/sudachipy-a-japanese-morphological-analyzer-in-python-5f1f8fc0c807?source=collection_archive---------20-----------------------

Sudachi 的 Python 版本,专注于日语文本的自然语言处理(NLP)

Photo by Damon Lam on Unsplash

本文介绍了 SudachiPy 的基本功能,它可以用来执行简单的自然语言处理任务,比如日语的标记化。基于官方 Github 页面:

Sudachi 和 SudachiPy 是由人工智能的 WAP 德岛实验室和 NLP 开发的,NLP 是 Works Applications 下的一个研究所,专注于自然语言处理(NLP)。

最初的版本是 Java,而 SudachiPy 是它的 python 实现。说了这么多,有些功能还是和 Java Sudachi 不兼容。本文由 4 个主要部分组成:

  1. 设置
  2. 命令行
  3. 基本用法
  4. 结论

1.设置

SudachiPy

让我们从创建一个虚拟环境并激活它开始。完成后,在终端中运行以下命令:

pip install SudachiPy

这将安装 SudachiPy 的最新版本,在本文撰写时是 0.3.11。SudachiPy 高于 0.3.0 的版本默认引用 SudachiDict_core 包的 system.dic。这个软件包不包含在 SudachiPy 中,必须手动安装。

SudachiDict_core

您可以通过运行以下命令来安装该软件包:

pip install https://object-storage.tyo2.conoha.io/v1/nc_2520839e1f9641b08211a5c85243124a/sudachi/SudachiDict_core-20190718.tar.gz

它会自动安装默认词典。一旦你准备好了,让我们跳到下一部分。以下段落旨在设置您自己的自定义词典。

自定义词典(可选)

Sudachi 为我们提供了 3 种不同的字典

  • 小号:仅包含 UniDic 的词汇
  • 核心:包含基本词汇(默认)
  • :包含杂项专有名词

您应该能够下载 system.dic 文件。您可以将字典修改为任何内置或自定义的字典。

  • 路径修改:创建一个 sudachi.json,放在你喜欢的任何地方。默认情况下,包在以下目录中包含此文件。
<virtual_env>/Lib/site-packages/sudachipy/resources/

Image by Author

你可以选择编辑这个文件或者创建一个新的并粘贴下面的代码:

将 systemDict 修改为 systemDict 的相对路径,以指向 system.dic 文件。

  • 直接替换:转到以下目录:
<virtual_env>/Lib/site-packages/sudachidict_core/resources

您应该只能看到一个名为 system.dic 的文件

Image by Author

用您的自定义词典或从官方网站下载的词典替换该文件。

如果您使用的是 Windows 操作系统,并且遇到了OSError: symbolic link privilege not held问题。请以管理员身份运行您的终端。然后,键入并运行以下命令:

sudachipy link -t core

2.命令行

SudachiPy 还为我们提供了一些命令行。一旦安装了 SudachiPySudachiDict_core 模块,您就可以直接使用它了。我将用它来测试我们是否正确安装了模块。有 4 个主要的可用命令:

  • 标记化
  • 建设
  • ubuild(包含使用 0.3 版本时的 bug。*)

打开终端并运行以下命令:

sudachipy tokenize -h

您应该能够看到以下结果。

Image by Author

如果您遇到任何问题,请确保您已经正确安装了 SudachiPySudachiDict_core 模块。

3.基本用法

导入

首先,让我们导入分词器字典模块。

from sudachipy import tokenizer
from sudachipy import dictionary

记号赋予器对象

创建一个标记器对象需要这两个模块。继续添加以下代码:

tokenizer_obj = dictionary.Dictionary().create()

方式

接下来,我们需要为记号赋予器定义模式。模式用于确定标记器应该如何拆分文本。

  • A :文本被分割成与 UniDic 短单元相当的最短单元
  • B :将文本分割成 A 和 C 之间的中间单元
  • C :提取命名实体

让我们通过将其设置为模式 A 来测试一下:

mode = tokenizer.Tokenizer.SplitMode.A

创建一个新变量,并指定任何日语文本。然后,调用列表理解中的 tokenize 函数,如下所示:

txt = "医薬品安全管理責任者"
print([m.surface() for m in tokenizer_obj.tokenize(txt, mode)])

您应该能够获得以下结果:

['医薬', '品', '安全', '管理', '責任', '者']

您可以对其进行测试,以查看所有三个输出的结果,如下所示:

from sudachipy import tokenizer
from sudachipy import dictionarytokenizer_obj = dictionary.Dictionary().create()
txt = "医薬品安全管理責任者"
mode = tokenizer.Tokenizer.SplitMode.A
print([m.surface() for m in tokenizer_obj.tokenize(txt, mode)])
mode = tokenizer.Tokenizer.SplitMode.B
print([m.surface() for m in tokenizer_obj.tokenize(txt, mode)])
mode = tokenizer.Tokenizer.SplitMode.C
print([m.surface() for m in tokenizer_obj.tokenize(txt, mode)])

字典和规范化形式

日语以复杂的动词变化著称。SudachiPy 还为我们提供了一种通过内置函数自由转换它们的方法。我们将只探索三个主要的函数,我们可以在通过 tokenizer obj 分割文本后访问它们。

第一个是原始文本,可以使用表面()函数调用

print([m.surface() for m in tokenizer_obj.tokenize(txt, mode)])

此外,我们还有 dictionary_form ()函数

print([m.dictionary_form() for m in tokenizer_obj.tokenize(txt, mode)])

最后一个是 normalized_form ()函数

print([m.normalized_form() for m in tokenizer_obj.tokenize(txt, mode)])

让我们将它们结合在一起,看看有什么不同:

from sudachipy import tokenizer
from sudachipy import dictionarytokenizer_obj = dictionary.Dictionary().create()
txt = "ゲームデータを消失してしまいました。"
mode = tokenizer.Tokenizer.SplitMode.A
print([m.surface() for m in tokenizer_obj.tokenize(txt, mode)])print([m.normalized_form() for m in tokenizer_obj.tokenize(txt, mode)])print([m.dictionary_form() for m in tokenizer_obj.tokenize(txt, mode)])

您应该能够获得以下结果:

['ゲーム', 'データ', 'を', '消失', 'し', 'て', 'しまい', 'まし', 'た', '。']
['ゲーム', 'データ', 'を', '消失', '為る', 'て', '仕舞う', 'ます', 'た', '。']
['ゲーム', 'データ', 'を', '消失', 'する', 'て', 'しまう', 'ます', 'た', '。']

词性

任何自然语言处理中最重要的特征之一是词性标记。我们可以通过词性()函数轻松获得:

print([m.part_of_speech() for m in tokenizer_obj.tokenize(txt, mode)])

输出结果如下所示:

[['名詞', '普通名詞', '一般', '*', '*', '*'], ['名詞', '普通名詞', '一般', '*', '*', '*'], ['助詞', '格助詞', '*', '*', '*', '*'], ['名詞', '普通名詞', 'サ変可能', '*', '*', '*'], ['動詞', '非自立可能', '*', '*', 'サ行変格', '連用形-一般'], ['助詞', '接続助詞', '*', '*', '*', '*'], ['動詞', '非自立可能', '*', '*', '五段-ワア行', '連用形-一般'], ['助動詞', '*', '*', '*', '助動詞-マス', '連用形-一般'], ['助動詞', '*', '*', '*', '助動詞-タ', '終止形-一般'], ['補助記号', '句点', '*', '*', '*', '*']]

4.结论

让我们回顾一下今天所学的内容。我们从安装必要的 python 模块开始, SudachiPySudachiDict_core 。还有一个选项可以配置它来加载您自己的自定义词典。

然后,我们研究了一些可以在终端中调用来测试安装的基本命令。

接下来,我们深入研究基本的 python 代码,学习如何标记日语文本。此外,我们可以得到字典或规范化形式的输出标记。更不用说词性()函数,它可以帮助识别每个令牌的 POS 标签。

感谢您的阅读,祝您愉快。下一篇文章再见。

参考

  1. https://github.com/WorksApplications/SudachiPy
  2. https://github.com/WorksApplications/Sudachi

数独和时间表

原文:https://towardsdatascience.com/sudokus-and-schedules-60f3de5dfe0d?source=collection_archive---------10-----------------------

Pan Am’s Reservation Center in the 1950’s

用树搜索解决调度问题

如今,机器学习非常流行,以至于人们很容易忽视“人工智能”领域还有其他算法的事实。事实上,这些算法是如此的重要,以至于忽视它们是很容易的。以搜索算法为例,或者在这种情况下更具体地说是约束满足。

Video version of this article

假设你需要安排课程和教室。有 36 节课、36 个房间和 800 个讲座作为你的时间表。想猜猜有多少种可能的配置吗?答案如下:10 种⁴⁹⁰可能的配置。客观地说,宇宙中有 10⁸⁰可观测的原子。即使像教室安排这样*凡的任务也要处理天文数字和排列,并冒险进入 NP 难领域。但是我可以告诉你如何及时地用算法解决这些问题。

运筹学领域并不新鲜,但它的技术和算法对日常实际问题至关重要。在工厂产能如此有限的情况下,如何在多条产品线中实现利润最大化?你如何安排一家医院的 200 名护士,他们有不同的休假要求、职位、工会限制和工作时间规定?如果你需要安排体育比赛并最小化团队旅行距离该怎么办?如何优化列车网络的准点性能?还是简单的解一个数独?

有许多算法可以解决优化性质的问题。这些包括线性规划、元启发式和整数规划等等。我个人觉得这些优化和搜索算法非常迷人,并且有大量的实际问题需要用它们来解决。有趣的是,这些算法中的一些如何直接应用于机器学习,因为机器学习本身在其核心是一个优化问题。

但今天,我想谈谈如何安排大学课堂,以及解决数独。您可以使用这种整数规划方法在基于规则的约束下安排员工、工厂生产线、云服务器作业、运输车辆和其他资源。我们可以使用数学建模实现神奇的一键生成时间表,而不是依赖迭代的强力策略来将事件放入时间表中(这可能是无药可救的低效)。你甚至可以采用这些方法来构建象棋人工智能算法或者进行任何基于离散的回归。

在我开始之前,我强烈推荐这个具有挑战性但很有用的 Coursera 离散优化课程。这门课相当雄心勃勃,但是很有价值,很有用,也很有趣。这是值得的时间和精力,即使你不得不放慢自己的步伐。

做好准备,对于你们这些技术人员来说,将会有相当多的代码!重要的是要着眼于大局,从概念上理解模型。所以我鼓励你在第一次阅读这篇文章的时候忽略掉这段代码(或者干脆跳过它)。如果您决定深入研究,请确保您熟悉面向对象和函数式编程。

定义问题

在本文中,我们将针对一个教室生成每周大学课程表。我们将在两个维度上绘制占领状态网格:班级与 15 分钟离散间隔的时间线。如果我们想要安排多个房间,那将是三个维度:班级对时间线对房间。我们现在将坚持前者,做一个房间,稍后我将解释如何做多个房间。

这些课程时间长短不一,可能会在一周内“重复出现”。每个重复会话必须在一天中的同一时间开始。

以下是这些类:

  • 心理学 101 (1 小时,2 节课/周)
  • 英语 101 (1.5 小时,2 节课/周)
  • 数学 300 (1.5 小时,每周 2 节课)
  • 心理学 300(每周 3 小时 1 节课)
  • 微积分 I (2 小时,2 节课/周)
  • 线性代数 I (2 小时,每周 3 节课)
  • 社会学 101 (1 小时,2 节课/周)
  • 生物 101 (1 小时,2 节课/周)
  • 供应链 300 (2.5 小时,每周 2 次会议)
  • 定位 101 (1 小时,1 节课/周)

一天应该以 15 分钟为间隔,并且只能以这些间隔来安排课程。换句话说,一节课只能在整点的 00、15、30 或 45 开始。

运营周是周一至周五。营业时间为上午 11:30 至下午 1:00,休息时间如下:

  • 上午 8 时至 11 时 30 分
  • 下午 1 时至 5 时

您的目标:创建一个模型,该模型安排这些课程,没有重叠,并符合这些要求。

剧透提示:这是我们最终将使用我们从头构建的“人工智能”算法来计算的解决方案。如果你想知道这是如何做到的,请继续阅读。

SPOIILER ALERT: Here is the schedule our algorithm will build by the end of this article

奠定基础

好吧,不知所措了吗?有很多规则,要探索的排列数量是天文数字。但是一旦我向您展示了这种技术,它将有望非常直接地实现。

关于这个问题,你应该注意的第一件事是每件事是如何被分成“15 分钟”块的。这不是一个连续的/线性的问题,而是一个离散的问题,这就是现实世界中大多数计划是如何建立的。假设我们已经为整个周创建了一个时间表,分成 15 分钟的时间段,如下所示:

请注意,“…”只是一个折叠的占位符,因为我们没有足够的空间来显示一周的 672 个数据块(672 = 7 天* 24 小时*一小时 4 个数据块)。

现在让我们扩展这个概念,把类作为时间轴的轴。每个交叉点/单元是一个可以是 1 或 0 的Slot。这个二进制变量将被求解,以指示Slot是否是该类第一次循环的开始时间。我们现在将它们都设置为 0,如下所示:

A grid of our decision variables

这个网格对于从逻辑上思考这个问题至关重要。这将是一个有效的视觉辅助,因为我们的约束将集中在网格内的区域。

我将使用 Kotlin 作为编程语言,它与 Java 库配合得非常好,但比 Java 更易读、更简洁。我们将利用 Java 8 强大的LocalDate / LocalTime API 来简化我们的日历工作。

如果你不熟悉 Kotlin,它基本上是一个类似 Swift 的“dumbed down Scala”,大量用于 Android 开发。它本质上利用了 Java、C#、Scala、Groovy 和 Python 的实用特性来创建一种实用的工业语言。它还可以编译成 Java 字节码,并与 Java 库无缝互操作。

让我们像这样设置我们的基本规则参数:

**import** java.time.LocalDate
**import** java.time.LocalTime*// Any Monday through Friday date range will work* **val** *operatingDates* = LocalDate.of(2017,10,16)..LocalDate.of(2017,10,20)**val** *operatingDay* = LocalTime.of(8,0)..LocalTime.of(17,0)**val** *breaks* = *listOf*<ClosedRange<LocalTime>>(LocalTime.of(11,30)..LocalTime.of(12,59)
)

接下来让我们声明ScheduledClass,它保存了我们想要调度的给定类的属性。

**data class** ScheduledClass(**val id**: Int,**val name**: String,**val hoursLength**: Double,**val recurrences**: Int,**val recurrenceGapDays**: Int = 2)

recurrenceGapDays是每次重复的开始时间之间所需的最少天数。例如,以Psych 100为例,它需要 2 次重复,默认间隔为 2 天。如果第一堂课是在星期一上午 8 点,那么第二堂课必须安排在两天(48 小时)后,也就是星期三上午 8 点。我们将把这个值默认为2,这将使每个会话的开始间隔 48 小时。

接下来我们可以在一个List中声明所有的ScheduledClass实例:

**val** *scheduledClasses* = *listOf*(ScheduledClass(id=1, name=**"Psych 101"**,hoursLength=1.0,recurrences=2),ScheduledClass(id=2, name=**"English 101"**,  hoursLength=1.5, recurrences=3),ScheduledClass(id=3, name=**"Math 300"**, hoursLength=1.5, recurrences=2),ScheduledClass(id=4, name=**"Psych 300"**,  hoursLength=3.0, recurrences=1),ScheduledClass(id=5, name=**"Calculus I"**, hoursLength=2.0, recurrences=2),ScheduledClass(id=6, name=**"Linear Algebra I"**, hoursLength=2.0, recurrences=3),ScheduledClass(id=7, name=**"Sociology 101"**, hoursLength=1.0, recurrences=2),ScheduledClass(id=8, name=**"Biology 101"**, hoursLength=1.0, recurrences=2),ScheduledClass(id=9, name=**"Supply Chain 300"**, hoursLength=2.5, recurrences=2),ScheduledClass(id=10, name=**"Orientation 101"**,hoursLength=1.0, recurrences=1))

Block类将代表每个离散的 15 分钟时间段。我们将使用一个 Kotlin Sequence结合 Java 8 的LocalDate/LocalTime API 来为整个规划窗口生成所有块。我们还将创建几个助手属性来提取timeRange以及它是否是withinOperatingDaywithinOperatingDay属性将确定此Block是否在可安排的时间窗口内(例如,未安排在午夜或休息时段内)。

*/** A discrete, 15-minute chunk of time a class can be scheduled on */* **data class** Block(**val range**: ClosedRange<LocalDateTime>) {**val timeRange** =     **range**.**start**.toLocalTime()..**range**.**endInclusive**.toLocalTime()*/** indicates if this block is in operating day/breakconstraints */* **val withinOperatingDay get**() =  *breaks*.*all* **{ timeRange**.**start !in it }** &&**timeRange**.**start in** *operatingDay* &&**timeRange**.**endInclusive in** *operatingDay// manage instances* **companion object** {*/* All operating blocks for the entire week, broken up in 15minute increments.Lazily initialize to prevent circular construction issues */* **val all by** *lazy* **{***generateSequence*(*operatingDates*.**start**.atStartOfDay()){dt **->** dt.plusMinutes(15).*takeIf* **{ it**.plusMinutes(15) <= *operatingDates*.**endInclusive**.atTime(23,59) **}}**.*map* **{** Block(**it**..**it**.plusMinutes(15)) **}** .*toList*()**}** */* only returns blocks within the operating times */* **val allInOperatingDay by** *lazy* **{all**.*filter* **{ it**.**withinOperatingDay }}** }
}

注意我将使用一个[lazy { }](https://kotlinlang.org/docs/reference/delegated-properties.html#lazy) 委托为每个域对象初始化项目。这是为了防止循环构造问题,方法是在第一次调用这些项之前不构造它们。

最后,Slot类将代表一个ScheduledClass和一个Block之间的交集/单元。我们将通过将每个ScheduledClass与每个Block配对来生成它们。我们还将创建一个未赋值的selected二进制变量,它将是null,直到我们给它赋值为10

**data class** Slot(**val block**: Block, **val scheduledClass**: ScheduledClass) {**var selected**: Int? = **nullcompanion object** {**val all by** *lazy* **{** Block.**all**.*asSequence*().*flatMap* **{** b **->** ScheduledClass.**all**.*asSequence*().*map* **{** Slot(b,**it**)**}}**.*toList*()**}** }
}

建模约束

在我进入模型的实现之前,我应该强调你可以使用混合整数解算器库来建模带有线性函数的约束,并让它求解selected变量。在 Python 中你可以使用纸浆或者 PyOmo 。在 Java *台上,您可以使用 ojAlgo 或 OptaPlanner 。对于许多这样的库,我还可以加入一个$10K IBM CPLEX 许可证,它可以更快地解决更大、更复杂的问题。

但是我将展示如何从头开始构建一个解决方案。在没有任何库的情况下进行优化的好处是,您可以对启发式算法(搜索策略)进行大量控制,并根据您的领域来表达模型。

在我们开始求解每个Slot中的selected变量之前,让我们做一些思维实验来理解我们的约束。我可能浪费了 50 张纸来做这个模型,但我发现了一些有用的东西。它有点抽象,但是对于这个特殊的问题来说是强大而有效的。

同样,我们将为每个Slot分配一个10 来指示第一节课重复的开始。这是我们的求解器可能会想到的一个可能的迭代,其中第一节心理学 101 课在周一上午 9:00 开始,社会学 101 课在周一上午 9:15 开始。这是我们的地图:

仔细研究这个场景。你明白为什么这是一个无效的案例了吗?在周一上午 9:45,心理学 101(需要四个街区)和社会学 101(也需要四个街区)相互冲突。视觉上,你也许能看到冲突。但是怎么形容呢?

“影响”上午 9:45 时间段的计划班时段的总和必须小于或等于1。总和1实际上意味着只有一个类占用那个块,而0意味着根本没有类占用那个块(也有效)。以下情况也是失败,因为“影响”槽的总和是2

如果我们将社会学 101 移到上午 10:00,那么总和将是1,一切都好(如下所示):

我们需要将这个逻辑应用于整个时间线上的每个块的,查询占据这个块的每个类的更早的槽,并规定它们的总和必须不大于 1。这个抽象但强大的想法实现了我们在约束方面需要的一切。下面是实际情况,所有影响上午 9:45 的时间段都用蓝色突出显示。所有这些蓝色时间段的总和必须不超过 1,这样上午 9:45 的时间段才不会被重复预订。

这甚至可以解释复发的原因。毕竟,我们在一个槽中放了一个1来表示第一个类的候选开始时间。如果我们正在查看星期五上午 9:45 的时间段,我们将查询一周中会导致星期五上午 9:45 的时间段被占用的时间段(一直到星期一)。下面是一个大视野。这些蓝色槽的总和必须不大于 1。

好的,你开始头晕了吗?这个模型的强大之处不在于数学,而在于每个块能够查询影响它的槽,并要求它们的总和不超过 1。这是艰苦工作发生的地方。另一个好处是,我们不需要创建任何新的变量来模拟约束,并且可以用一系列简单的求和约束来约束现有的槽二元变量。

提取重复和受影响的插槽

为了执行影响给定块的槽的想法,我们首先需要做的是为给定块上的每个类识别这些槽,并且说它们的总和必须是“1”。这个代码库的明星是针对给定的List项的 Kotlin 函数:

**enum class** RecurrenceMode { **PARTIAL_ONLY**, **FULL_ONLY**, **ALL** }**fun** List<T>.affectedWindows(slotsNeeded: Int, gap: Int, recurrences: Int,mode: RecurrenceMode = RecurrenceMode.**FULL_ONLY**) = (0..**size**).*asSequence*().*map* **{** i **->** (1..recurrences).*asSequence*().*map* **{** (**it** - 1) * gap **}** .*filter* **{ it** + i < **size }** .*map* **{** r **->** subList(i + r, (i + r + slotsNeeded).*let* **{ if** (**it** > **size**) **size else it }**)**}** .*toList*()**}**.*filter* **{when** (mode) {RecurrenceMode.**ALL** -> **true**RecurrenceMode.**FULL_ONLY** -> **it**.**size** == recurrences && **it**.*all* **{ it**.**size** == slotsNeeded **}**RecurrenceMode.**PARTIAL_ONLY** -> **it**.**size** < recurrences || **it**.*any* **{ it**.**size** < slotsNeeded **}** }**}**

我将让您自己深入研究这个函数的实现。现在,更有效的方法是覆盖它所完成的任务,即获取任何List<Slot>并执行一个专门的窗口操作,在每次循环之间注入一个gap。这将返回一个列表列表,List<List<T>>,其中每个列表都是一个循环,列表中的元素是受影响的元素。注意gap是窗口每次开始之间的元素数量。

为了了解这种模式,我们可以将整数 1 到 20 分成 4 个一组,每个循环开始之间的间隔为 6,并且有 3 个循环。我们将只考虑完整的而不是部分的组,所以mode将被设置为RecurrenceMode.FULL_ONLY

**fun** main(args: Array<String>) { (1..20).*toList*().*affectedWindows*(slotsNeeded = 4,gap = 6,recurrences = 3,mode = RecurrenceMode.**FULL_ONLY** ).*forEach* **{** *println*(**it**) **}** }

输出:

[[1, 2, 3, 4], [7, 8, 9, 10], [13, 14, 15, 16]]
[[2, 3, 4, 5], [8, 9, 10, 11], [14, 15, 16, 17]]
[[3, 4, 5, 6], [9, 10, 11, 12], [15, 16, 17, 18]]
[[4, 5, 6, 7], [10, 11, 12, 13], [16, 17, 18, 19]]
[[5, 6, 7, 8], [11, 12, 13, 14], [17, 18, 19, 20]]

如果我们将mode设置为RecurrenceMode.PARTIAL_ONLY,它将给出无法产生长度为43循环的“破碎”组。这将有助于稍后识别必须为 0 的槽,因为我们无法获得给定块所需的所有槽(例如,它们溢出超过 5pm 限制)。

**fun** main(args: Array<String>) {(1..20).*toList*().*affectedWindows*(slotsNeeded = 4,gap = 6,recurrences = 3,mode = RecurrenceMode.**PARTIAL_ONLY** ).*forEach* **{** *println*(**it**) **}** }

输出:

[[6, 7, 8, 9], [12, 13, 14, 15], [18, 19, 20]]
[[7, 8, 9, 10], [13, 14, 15, 16], [19, 20]]
[[8, 9, 10, 11], [14, 15, 16, 17], [20]]
[[9, 10, 11, 12], [15, 16, 17, 18]]
[[10, 11, 12, 13], [16, 17, 18, 19]]
[[11, 12, 13, 14], [17, 18, 19, 20]]
[[12, 13, 14, 15], [18, 19, 20]]
[[13, 14, 15, 16], [19, 20]]
[[14, 15, 16, 17], [20]]
[[15, 16, 17, 18]]
[[16, 17, 18, 19]]
[[17, 18, 19, 20]]
[[18, 19, 20]]
[[19, 20]]
[[20]]

我们可以使用这个affectedWindows()函数来处理课程重复,并在周一到周五的时间规划窗口内生成所有可能的排列。然后,我们可以使用它来查找影响特定块的特定类的槽。我们还将“清除”属于损坏组的插槽。例如,在下午 4:15 开始生物 101 将导致它溢出超过下午 5:00。因此,这个槽应该被固定为“0 ”,甚至在我们稍后进行的搜索中不被考虑。

*/** A discrete, 15-minute chunk of time a class can be scheduled on */* **data class** Block(**val range**: ClosedRange<LocalDateTime>) {**val timeRange** =     **range**.**start**.toLocalTime()..**range**.**endInclusive**.toLocalTime() */** indicates if this block is zeroed due to operating day/break constraints */* **val withinOperatingDay get**() =  *breaks*.*all* **{ timeRange**.**start !in it }** &&**timeRange**.**start in** *operatingDay* &&**timeRange**.**endInclusive in** *operatingDay* **val affectingSlots by** *lazy* **{** ScheduledClass.**all**.*asSequence*().*flatMap* **{it**.affectingSlotsFor(**this**).*asSequence*()**}**.*toSet*()**}companion object** {*/* All operating blocks for the entire week, broken up in 15minute increments.Lazily initialize to prevent circular construction issues */* **val all by** *lazy* **{** *generateSequence*(*operatingDates*.**start**.atStartOfDay()){dt **->** dt.plusMinutes(15).*takeIf* **{ it**.plusMinutes(15) <= *operatingDates*.**endInclusive**.atTime(23,59) **}}**.*map* **{** Block(**it**..**it**.plusMinutes(15)) **}** .*toList*()**}** */* only returns blocks within the operating times */* **val allInOperatingDay by** *lazy* **{all**.*filter* **{ it**.**withinOperatingDay }}** }
}**data class** ScheduledClass(**val id**: Int,**val name**: String,**val hoursLength**: Double,**val recurrences**: Int,**val recurrenceGapDays**: Int = 2) {*/** the # of slots between each recurrence */* **val gap** = **recurrenceGapDays** * 24 * 4*/** the # of slots needed for a given occurrence */* **val slotsNeededPerSession** = (**hoursLength** * 4).toInt()*/** yields slots for this given scheduled class */* **val slots by** *lazy* **{** Slot.**all**.*asSequence*().*filter* **{ it**.**scheduledClass** == **this }** .*toList*()**}** */** yields slot groups for this scheduled class */* **val recurrenceSlots by** *lazy* **{slots**.*affectedWindows*(slotsNeeded = **slotsNeededPerSession**,gap = **gap**,recurrences = **recurrences**,mode = RecurrenceMode.**FULL_ONLY** ).*toList*()**}** */** yields slots that affect the given block for this  scheduled class */* **fun** affectingSlotsFor(block: Block) = **recurrenceSlots**.*asSequence*().*filter* **{** blk **->** blk.*flatMap* **{ it }** .*any* **{ it**.**block** == block **} }** .*map* **{ it**.*first*().*first*() **}** */** These slots should be fixed to zero **/* **val slotsFixedToZero by** *lazy* **{** *// broken recurrences* **slots**.*affectedWindows*(slotsNeeded = **slotsNeededPerSession**,gap = **gap**,recurrences = **recurrences**,mode = RecurrenceMode.**PARTIAL_ONLY** ) .*flatMap* **{ it**.*asSequence*() **} //flatten the groups!** .*flatMap* **{ it**.*asSequence*() **}**.*plus*(**recurrenceSlots**.*asSequence*().*flatMap* **{ it**.*asSequence*() **}** .*filter* **{** slot **->** slot.*any* **{** !**it**.**block**.**withinOperatingDay }}** .*map* **{ it**.*first*() **}** ).*distinct*().*onEach* **{it**.**selected** = 0**}** .*toList*()**}** */**translates and returns the optimized start time of the class */* **val start get**() = **slots**.*asSequence*().*filter* **{ it**.**selected** == 1 **}** .*map* **{ it**.**block**.**dateTimeRange**.**start }** .*min*()!!*/** translates and returns the optimized end time of the class */* **val end get**() = **start**.plusMinutes((**hoursLength** * 60.0).toLong())*/** returns the DayOfWeeks where recurrences take place */* **val daysOfWeek get**() = (0..(**recurrences**-1)).*asSequence*().*map* **{ start**.*dayOfWeek*.plus(**it**.toLong() * **recurrenceGapDays**) **}**.*sorted*()**companion object** {**val all by** *lazy* **{** *scheduledClasses* **}** }
}

求解变量

现在我们已经建立了一个有效的基础设施来查询影响给定块的槽,我们现在准备求解符合我们的约束的变量。希望你对编写递归算法相当熟悉。如果没有,这里有一个练习的机会!

但是首先我要用一个更简单明了的例子来证明这个想法:数独。在我回到调度问题之前,它将演示如何使用分支算法求解变量。

想想数独游戏

但愿数独是一个熟悉的益智游戏。您将看到一个 9x9 的单元格网格,其中一些单元格已经有了可能的数字 1-9。您需要找到其余空白单元格的值,以便每一行、每一列和 3×3 的正方形都有数字 1-9。

A typical Sudoku puzzle

那么如何求解空白值呢?强行搜索效率会非常低,所以我们需要一个更聪明的搜索策略。

请允许我向您介绍树搜索。感觉类似于决策树,但是我们处理的是离散变量(整数)而不是连续变量(小数)。

首先获取单元格,并在列表中根据它们拥有的候选值的数量对它们进行排序。例如,单元格[4,4]只能是一个值 5,所以它先出现,而单元格[2,6]应该是最后一个,因为它有 6 个可能的值。然后创建一个函数,作为分支算法递归地探索每个可能的值。以下是这种递归算法如何探索可能值的视觉效果:

With this sorted list, create a recursive tree that explores each Sudoku cell and its possible values.

请注意我们是如何首先从最受约束的单元格开始的,这大大缩小了我们的搜索空间。搜索策略的这种用法被称为“启发式”。当一个给定的分支被认为不可行时(违反了数独规则),该分支立即终止并转移到下一个替代分支。上图中,单元格[4,2]不能被赋值为“3”,因为单元格[3,2]已经被赋值为“3”。这意味着“3”已经存在于列 2 中,所以没有理由继续搜索那个分支,我们修剪它。

当我们找到一个探索了所有 91 个值的分支,并且没有违反任何约束时,我们就解决了我们的数独游戏!然后,我们可以将分支值折叠回游戏板,如下所示:

We have solved our Sudoku!

如果你想看数独解算器的源代码,你可以在这里找到。这部分代码是递归树发生的地方。

[## 托马斯尼尔德/科特林数独求解器

一个用 Kotlin 写的 suduko 游戏解算器。有助于托马斯尼尔德/科特林数独解决方案的开发,通过创建一个…

github.com](https://github.com/thomasnield/kotlin-sudoku-solver)

回到调度问题

那么数独和日程安排问题有什么关系呢?嗯,实际上很多!我们可以应用这种技术,通过使用搜索树来解决 1 或 0 值的槽。在每一个被探索的分支上,你可以像数独游戏一样检查你的约束是否仍然被满足,确保课程没有被安排在已经被占用的时间段。

从概念上讲,这是我们的递归搜索树的样子:

下面是我如何从零开始实现这个野蛮的算法(请原谅我的代码格式或只看源代码)。请注意我是如何使用BranchNode来表示正在搜索的分支的顶端的,我可以在分支上向后遍历,以评估到目前为止所做的决策是否与我当前的决策不冲突。然后我可以创建一个traverse()函数来递归地探索整个树,直到找到解决方案。

**import** java.time.DayOfWeek**class** BranchNode(**val selectedValue**: Int,restOfTree: List<Slot>,**val previous**: BranchNode? = **null**) {**val slot** = restOfTree.*first*()**val traverseBackwards** =  *generateSequence*(**this**) **{ it**.**previous }**.*toList*()*// calculate remaining slots and prune where constraint propagates* **val remainingSlots by** *lazy* **{if** (**selectedValue** == 0)restOfTree.*minus*(**slot**)**else** {*// if this slot is occupied, affected slots can be pruned* **val** affectedSlotsPropogated = Block.**allInOperatingDay** .*asSequence*().*filter* **{slot in it**.**affectingSlots}**.*flatMap* **{ it**.**affectingSlots**.*asSequence*() **}** .*filter* **{ it**.**selected** == **null }** .*toSet*()restOfTree.*asSequence*().*filter* **{it**.**scheduledClass** != **slot**.**scheduledClass** && **it !in** affectedSlotsPropogated**}**.*toList*()}**}val scheduleMet get**() = **traverseBackwards** .*asSequence*().*filter* **{ it**.**selectedValue** == 1 **}** .*map* **{ it**.**slot**.**scheduledClass }** .*distinct*().*count*() == ScheduledClass.**all**.*count*()**val isContinuable get**() = !**scheduleMet** && **remainingSlots**.*count*() > 0 **val isSolution get**() = **scheduleMetfun** applySolution() {**slot**.**selected** = **selectedValue** }
}**fun** executeBranchingSearch() {*// pre-constraints* ScheduledClass.**all**.*flatMap* **{ it**.**slotsFixedToZero }** .*forEach* **{ it**.**selected** = 0 **}** *// Encourage most "constrained" slots to be searched first* **val** sortedSlots = Slot.**all**.*asSequence*().*filter* **{ it**.**selected** == **null }**.*sortedWith*(*compareBy*(**{** *// prioritize slots dealing with recurrences* **val** dow = **it**.**block**.**range**.**start**.*dayOfWeek* **when** {dow == DayOfWeek.**MONDAY** && **it**.**scheduledClass**.**recurrences** == 3 -> -1000 dow != DayOfWeek.**MONDAY** && **it**.**scheduledClass**.**recurrences** == 3 -> 1000 dow **in** DayOfWeek.**MONDAY**..DayOfWeek.**WEDNESDAY** && **it**.**scheduledClass**.**recurrences** == 2 -> -500 dow **!in** DayOfWeek.**MONDAY**..DayOfWeek.**WEDNESDAY** && **it**.**scheduledClass**.**recurrences** == 2 -> 500 dow **in** DayOfWeek.**THURSDAY**..DayOfWeek.**FRIDAY** && **it**.**scheduledClass**.**recurrences** == 1 -> -300 dow **!in** DayOfWeek.**THURSDAY**..DayOfWeek.**FRIDAY** && **it**.**scheduledClass**.**recurrences** == 1 -> 300 **else** -> 0}**}**, *// make search start at beginning of week*                    **{ it**.**block**.**range**.**start }**, *// followed by class length* **{**-**it**.**scheduledClass**.**slotsNeededPerSession } **)).*toList*()*// this is a recursive function for exploring nodes // in a branch-and-bound tree* **fun** traverse(currentBranch: BranchNode? = **null**): BranchNode? {**if** (currentBranch != **null** && currentBranch.**remainingSlots**.isEmpty()) {**return** currentBranch}**for** (candidateValue **in** intArrayOf(1,0)) {**val** nextBranch = BranchNode(candidateValue, currentBranch?.remainingSlots?: sortedSlots,currentBranch)**if** (nextBranch.isSolution)**return** nextBranch**if** (nextBranch.isContinuable) {**val** terminalBranch = traverse(nextBranch)**if** (terminalBranch?.isSolution == **true**) {**return** terminalBranch}}}**return null** }*// start with the first Slot and set it as the seed// recursively traverse from the seed and get a solution* **val** solution = traverse()solution?.traverseBackwards?.forEach **{** it.applySolution() **}**?: **throw** Exception(**"Infeasible"**)
}**import** java.time.LocalDate
**import** java.time.LocalTime*// Any Monday through Friday date range will work* **val** *operatingDates* = LocalDate.of(2017,10,16)..LocalDate.of(2017,10,20)**val** *operatingDay* = LocalTime.of(8,0)..LocalTime.of(17,0)**val** *breaks* = *listOf*<ClosedRange<LocalTime>>(LocalTime.of(11,30)..LocalTime.of(12,59)
)

我还使用启发式搜索“最受约束”的位置,这意味着它们更有可能被分配“1”。例如,3-recurrence 类必须安排在星期一,所以我们应该首先评估它在星期一的时间段。启发式算法还会优先搜索高重现类(比如 3 和 2 ),这样我们就可以完成搜索。毕竟高递归类没有太大的灵活性,应该先评估。

请注意,我们还积极地“提前”删除我们不再有理由搜索的未探索的值。例如,如果我的分支刚刚为生物 101 的 9:30AM 时间段分配了“1 ”,我应该为该 9:30AM 时间段和生物 101 提前修剪所有时间段,因为这两个时间段都已被该分支占用。

现在我剩下要做的就是调用这个递归函数并打印结果!

**fun** main(args: Array<String>) {*executeBranchingSearch*() ScheduledClass.**all**.*sortedBy* **{ it**.**start }** .*forEach* **{** *println*(**"${it**.**name}-   ${it**.**daysOfWeek**.*joinToString*(**"/"**)**} ${it**.**start**.toLocalTime()**}-${it**.**end**.toLocalTime()**}"**)**}**
}

如果你像我一样设置你的试探法和参数,下面是它生成的时间表:

Linear Algebra I- MONDAY/WEDNESDAY/FRIDAY 08:00-10:00
English 101- MONDAY/WEDNESDAY/FRIDAY 10:00-11:30
Supply Chain 300- MONDAY/WEDNESDAY 13:00-15:30
Math 300- MONDAY/WEDNESDAY 15:30-17:00
Calculus I- TUESDAY/THURSDAY 08:00-10:00
Psych 101- TUESDAY/THURSDAY 10:00-11:00
Sociology 101- TUESDAY/THURSDAY 13:00-14:00
Biology 101- TUESDAY/THURSDAY 14:00-15:00
Orientation 101- THURSDAY 15:00-16:00
Psych 300- FRIDAY 13:00-16:00

验证输出。不错吧?如果我们要直观地绘制出来,时间表应该是这样的:

很酷,不是吗?除了调度员工和其他资源,我们还可以使用完全相同的方法。它还可以用于任何需要找到可行或最优值以找到更好的解决方案的离散模型。这在最意想不到的情况下非常方便。我不能分享细节,但我有一个项目,似乎有预测/回归的性质。当我放弃了传统的连续回归模型,并谨慎地使用树搜索技术时,它非常有效,比任何回归库更好地解决了我的具体问题。

在我结束之前,如果您想要针对多个教室进行调度,只需针对时间段、班级和房间设置每个二进制Slot变量,使其成为三维的,如下所示。然后,您可以创建约束,以确保任何房间都不会被占用两次。否则,建模工作是一样的。

A 3-dimensional model that defines variables against multiple rooms

希望你们觉得这很有趣并且有用。我也希望这能让你看到其他已经存在了几十年却很少曝光的“人工智能”模型。如果你想了解更多,一定要看看 Coursera 上的离散优化课程,从运筹学领域了解更多的秘密。

源代码:

[## 托马斯尼尔德/优化调度演示

创建教室时间表的分支定界求解器

github.com](https://github.com/thomasnield/optimized-scheduling-demo/tree/master/kotlin_from_scratch_solution)

糖、花、鱼还是沙砾——现在是一场混战

原文:https://towardsdatascience.com/sugar-flower-fish-or-gravel-now-a-kaggle-competition-8d2b6b3b118?source=collection_archive---------19-----------------------

我非常高兴地宣布我们的 Kaggle 竞赛“从卫星图像中了解云”开始了。这场比赛是几十名科学家数百个小时的辛勤劳动的结晶。挑战在于将卫星图像分成四类。通常,当我们想到不同类型的云时,我们会想到积云、层云和卷云。然而,这个挑战中的四个类别被称为糖、花、鱼和砾石。那么,这些到底是什么?

这一切都始于大约两年前的一个研讨会,12 名云专家聚在一起讨论海洋上空的浅云。与大雷暴相比,这些云看起来是良性的,但事实上,它们对地球的气候起着巨大的作用。原因是它们将大量的阳光反射回太空,从而使我们的星球变冷,同时对温室效应的影响很小。这意味着弄清楚这些云将如何随着我们的星球变暖而变化非常重要。然而,目前的气候模型却难以应对。他们甚至不同意这些浅云是多还是少。

部分原因是浅云不仅仅是全球大气环流的结果。相反,他们有自己的生活,并以各种方式安排自己。对于其中的许多模式,其背后的基本机制知之甚少。这让我们回到我们的科学家小组。当他们浏览数百张类似本页所示的卫星图像时,他们注意到一些结构比其他结构出现得更频繁。经过一番讨论,他们商定了四种常见的图案,并分别命名为糖、花、鱼和砾石。

为了找到更多关于这四种模式的信息,我们需要更多的数据。为了获得这些数据,我们在 Zooniverse 上建立了一个众包项目,科学家可以在这个*台上创建自己的标签界面。为了我们的项目,我们去了 NASA Worldview ,下载了来自大西洋和太*洋三个地区的 10,000 幅卫星图像,这些地区的云型经常出现。在 Zooniverse 界面上,用户会看到一幅随机图像,并被要求在云结构周围画出方框。

2018 年 11 月,我们在汉堡的马克斯·普朗克气象学研究所和巴黎的气象动态实验室组织了云标签日。在那里,整个部门,总共大约 70 名科学家,花了一整天的时间标记总共超过 30,000 张图片。这意味着,对于每张图片,我们都有来自三个人的标签。

这个项目有趣的部分原因是标签是主观的。一个人的糖可能是另一个人的沙砾。换句话说,不存在客观真实。我们可以问的第一个问题是,人们在多大程度上同意这些课程。事实证明,人们对大约 40%的标签表示赞同。乍一看,这似乎并不多,但是请记住,这是一个非常主观的任务。从另一个角度来看,有 80%的可能性,至少有三分之一的人同意你的判断。

现在我们有了这个大的手绘数据集,我们可以用它做什么呢?首先,我们可以通过检查它们的出现如何与大规模流动相关联来分析云模式背后的物理机制。但是,尽管累计花费了 250 个小时进行标记,这些数据只覆盖了全球一小部分时间的一小部分。我们希望扩大我们的分析规模,深度学习是实现这一目标的完美工具。

出于这个原因,我们现在向 Kaggle 社区提出挑战,要求建立一个基于人类标签的机器学习模型。有了这样的算法,我们就能够将我们的分析扩展到世界的不同地方。我们真的很期待看到 Kagglers 会选择什么样的预处理和模型构建方法。

除了获得一个好的预测模型,我们还希望提高对气候科学家日常处理的问题类型的认识。最后,我们希望做出更好的预测,但首先需要更好地理解地球系统的物理过程。理解云是如何组织的就是这样一个例子。我们希望现代机器学习技术能够以前所未有的方式加速我们的研究。

最后,我要感谢让这一切成为可能的每一个人:Hauke Schulz,Sandrine Bony,Bjorn Stevens,当然还有所有的云贴标机!

要获得描述众包活动的论文预印本和更多关于科学背景的信息,请点击 此处

众包*台仍在运行。所以如果你想自己尝试给一些云贴标签,点击 这里

最后, 这个 就是 Kaggle 比赛了。

糖滑翔机,自闭症,枪支暴力和牙膏

原文:https://towardsdatascience.com/sugar-gliders-autism-gun-violence-and-toothpaste-why-every-writer-needs-a-basic-understanding-a43b8514bf0a?source=collection_archive---------26-----------------------

为什么每个作家都需要对统计学有一个基本的了解

统计数据讲故事。人们喜欢故事。

这就是为什么作家喜欢在他们的作品中加入统计数据——统计数据可以用一种可量化的、可捕捉的、有感染力的方式捕捉有趣的事实。就像我告诉你的,在 2014 年的一项研究中,11%的人认为网络语言 HTML 是一种性病。

添加到你工作中的天赋和可信度的因素可能是好的也可能是坏的。这完全取决于你的统计数据有多准确。

如果您不正确地使用统计数据,或者如果统计数据一开始就是错误的,您可能会误导读者。当涉及到引用统计数据时,我也有过自己的混乱——对此我已经得到了纠正。我希望保持这种状态。

但对于作家来说,驾驭统计语言并非易事。我在大学里上过统计学课,真是太幸运了:)。这里有一些在引用统计数据时需要注意的事情,这样你就不会把键盘放在嘴里。

1.知道你的百分比

我已经纠正了百分比变化和百分点变化之间令人困惑的区别。你可能犯了同样的错误。让我们考虑一个假设的研究来梳理我们的错误。

假设科学家们正试图确定在项链袋中携带一架糖滑翔机是否有益于心理健康。我们想象中的科学家发现,82%的玩了一天糖滑翔机的人认为自己是快乐的,相比之下,50%的人没有在脖子上挂着可爱的哺乳动物闲逛。(让我们假设研究人员完成了所有关于统计意义的花哨计算,一切都一清二楚)。

在这种情况下,说有人拥有一架糖滑翔机会快乐 32%准确吗?

不。这些百分比是概率的指示。本质上,科学家们说,基于这个实验,携带糖滑翔机的人有更高的概率认为自己快乐(82%的概率对 50%)。

所以因为我们在谈论概率,我们可以说如果一个人随身携带一架糖滑翔机,他快乐的可能性会增加 32%?

也没有。

“什么?!"让我解释一下。

百分比增长和百分比点的增长是有区别的。百分点的增加更直观,在这种情况下,我们看到了 32 个百分点的增加。

另一方面,百分比增长指的是从原始状态的度量(在本例中是一个比例,50%)到一个新值(82%)的变化。假设我们说快乐的原始可能性是 50%(对于那些没有糖滑翔机的悲伤的人来说),32 个百分点的增加实际上是 64%的增加,因为 32%是 50%的 64%。

很多官样文章,我知道。有一种更好的方式来思考这个问题——不是从比例的变化来看(例如,50%的人说他们很快乐),而是从数量变量的变化来看(例如,每个人在 1-10 的范围内给自己的快乐评分)。

如果在携带糖滑翔机时,*均幸福指数(从 1 到 10)从 6 到 9,3 的变化将增加 3 个评价点,代表幸福指数增加 50%(变化/原始测量值 3/6 = 0.5 或 50%)。

在这种情况下,可以准确地说,*均而言,带着糖滑翔机的人要快乐 50%,因为测量结果量化了快乐。在这种情况下,50%的增长更直观。

这是我最*在的一份销售支持报告中遇到的一个极好的例子:

2.不要引用引用者

统计数据很有趣,所以我们喜欢在写作中加入它们。所以我们跳到谷歌上,搜索“ x 统计”,试图找到关于 x 话题的有趣信息。这是一个完全合法的做法,但有一些事情你需要注意。

我称之为:引用引语。

其他像你一样的作家在他们的作品中引用统计数据。当你在谷歌上搜索的时候,你可能会找到他们的一些作品,并在这里或那里微妙地加入一些统计数据。虽然作者的统计数据可能是准确的,但你应该避免直接引用它们。这里有几个原因。

1.电话效应

统计数据在上下文中是强大的,但是当你把它们从上下文中移走时,它们就会失去一些意义。想想我们在小学玩的电话游戏:当一个基本短语被传来传去时,它会被无意地(或者有时是有意地)改变,最终产生一个有趣的新短语。

有了统计数据,这种变化就没那么有趣了。

就像电话游戏一样,你离原始来源越远,就越有可能得到原始统计数据的错误版本。

2.统计数据可能已经过时了

很少看到日期贴在统计数据旁边。因此,如果你引用报价者,你就冒着处于报价者引用报价者的菊花链末端的风险。因此,您可能会引用已经过时并且已经被揭穿的统计数据。2018 年发表的文章不代表其统计数据来自同一年。

这里有一个例子《福布斯》2018 年的一篇文章引用了他们说是 2017 年的一项统计数据,但他们链接的文章是 2015 年的。

如果一定要引用报价者,尽量离数据源只有一步之遥。这可能是你的最佳选择,因为实际的研究可能只是原始数据,然后其他人会获取数据并使用它。因为你是作家,不是统计学家,这可能是你最好的事实来源。

3.正偏压

疫苗会导致自闭症吗?有人说是,有人说不是,科学家怎么说?没有。

但是,尽管自 2010 年撤回伪造的 1998 年研究表明 MMR 疫苗和自闭症之间的联系已经过去了几年,但并不是每个父母都相信。

为什么?因为正偏。

积极偏见指的是“对发表有积极(重大)结果的研究的偏好,而不是*淡或消极的结果。”出版商和读者希望分享看似多事之秋的事情。由于这种偏好,积极的偏见可以创造一个分享循环,在这个循环中,重要的信息——尽管可能不是真的——可以迅速获得大量的宣传。

所以作家需要小心。特别是在为有议程的客户写作时,很容易只找到与我们的信息相匹配的统计数据(这正是前任——强调“前任”——研究员安德鲁·韦克菲尔德在他的自闭症研究中所做的)。

这是一个危险的游戏。每个人都有权利提出论点,但是一个有道德的作者会考虑各种各样的研究,或者至少在做出一个有潜在严重后果的大胆断言之前限定他们的陈述。

4.统计数据可能会误导人

拷问数据,它会告诉你任何你想要的东西。作者需要警惕潜在的数据滥用,统计数据可能是真实的,但结果可能完全是误导。这里有一些例子。

抽样误差

统计学的美妙之处在于,你不需要从一个群体中的每个个体那里获得信息,就能知道一个群体的特征。相反,您可以提取一个样本,并基于该样本对总体进行推断。

这里的技巧是,为了具有代表性,样本应该相对较大并且是随机选择的。下面是一些你应该注意的错误的采样方法。

错误的采样方式

方便取样。使用公司的电子邮件列表进行调查是一个便利示例。这并不意味着你不能使用电子邮件列表来了解消费者的偏好。但是如果你打算公布这些信息,你需要明确研究的范围。

例如,如果你的公司调查中有 51%的受访者说他们更喜欢巧克力冰淇淋,你不能说所有人中有 51%喜欢巧克力。只有你的观众。

配额抽样。像便利抽样一样,配额抽样发生在研究者不随机选择受试者的时候。相反,研究人员选择第一个进门的,并(错误地)假设这将产生一个有代表性的样本。

志愿者取样。当人们自愿参加一项研究时,你需要对结果保持警惕。自愿提供信息的人可能与不提供信息的人有很大不同,所以你的样本可能不具有代表性。

如果你曾经遇到过任何关于抽样的问题,请忽略这些信息。

*均值与中间值

均值和中位数是小学的话题。然而,这些简单的概念是误导读者的最佳方式,并且经常被故意用来误导读者。

简单回顾一下,均值和中位数表示数据集的中心。A *均值是*均值:将一组中每个个体的某个特定特性的所有值相加,然后除以个体数量。中值是中间值:根据一个定量变量将每个人排序,然后找到正好在中间的人。

数据的分布方式将决定是*均值还是中间值更适合测量中心。

分布:正态、右偏、左偏

一个正态分布是你的标准钟形曲线,其中大多数数据点聚集在*均值周围,然后它们随着远离*均值而减弱。

Courtesy of Data Science Central

当数据呈正态分布时,*均值或中值将是中心的良好度量(因为它们应该大致相同)。但是当数据不是正态分布时(意味着它是右偏或左偏的),你就需要小心了。

Courtesy of Data Science Central

右偏数据集是指其大部分数据聚集在左侧的数据集,其中一些数据偏右,使*均值向更高的值倾斜。

右偏数据的一个好例子是美国的收入。大多数人挣不到 10 万美元,但有些人挣得更多,少数人挣得更多。由于存在异常值,使用*均值无法精确测量中心值,因此中值更可取。在收入报告中,美国人口普查局甚至没有提供*均值,只有中位数(2016 年为 59039 美元)。在这种情况下,*均收入会产生误导。

一个左偏数据集是一个其大部分数据聚集在右侧的数据集,其中一些数据远离左侧,使*均值向较低值倾斜。

左偏数据的一个例子是退休年龄。随着年龄的增长,人们越来越倾向于退休,但也有少数幸运者早早地发了财,早早地退休到他们在加勒比海的私人岛屿上。在美国,*均退休年龄和中位退休年龄之间的差别并不大:*均退休年龄是 59.88 岁,中位退休年龄是 62 岁。很接*,但仍然是不同的故事。

(注意:以上是引用者的一级引用示例,其中我依赖其他人查看原始数据并进行他们自己的评估;)).

5.研究与实验

你可能听说过“相关性并不意味着因果关系”的说法(也许是在政治舞台上)这到底是什么意思?

当研究人员得出结论,两个定量变量往往一起波动,这种关系被认为是一种相关性。例如,冰淇淋销售往往与温度成正相关——温度越高,冰淇淋销售越多。

这个简单的例子可能意味着更高的温度会导致更高的冰淇淋销量(事实很可能如此)。但是一个统计学家不能仅凭数据研究就这么说。仅仅因为两个变量相关,并不意味着一个导致另一个。

例如,掉进游泳池淹死的人数与尼古拉斯·凯奇每年出演的电影数量相关:

Courtesy of Spurious Correlations

你认为你能证明是一个导致了另一个吗?大概不会。

但是还有不太明显的例子。一篇文章(错误地)引用了一项研究,该研究发现教师工资和学生表现之间存在关联,认为提高工资会导致教师表现的提高。

虽然这可能是真的,但也可能不是——因为相关性并不意味着因果关系。有没有可能存在一些未知的变量——也许收入更高的教师生活在更先进的国家,因此更有可能教出更好的学生?一些值得思考的事情。(更不用说这篇文章是引用引用者的教科书式的例子了。随便说说。)

6.错误的调查结构

糟糕的调查结构也会产生误导性的统计数据。一个众所周知的罪魁祸首是高露洁。

一则高露洁广告称 80%的牙医推荐高露洁。这是一个相当可观的数字——所以只有 20%的牙医推荐高露洁以外的牙膏?

没有。调查的方式是,牙医被允许选择他们推荐的多种牙膏。因此,推荐高露洁的牙医也可以推荐佳洁士、Aquafresh、Pepsodent、Aim 和其他产品。

80%的牙医可能会推荐任何对你有益的产品,所以这不是一个很有帮助的数字。完全准确,只是没什么帮助。如果可能的话,对调查是如何进行的保持警惕。

7.误导性措辞

一项统计数据的措辞方式可能会使其误导,但不会是虚假的。

一个例子是联邦调查局的尼克·施罗尔在引用的话,他说 2016 年联邦调查局制服犯罪报告显示,“被刺死的人数是被任何类型的步枪杀死的人数的四倍多。”我不确定这里的数字(因为我引用了引用者的话),但不管怎样,措辞值得一看。

第一印象?除非你意识到“任何种类的步枪”和“枪支”之间的微妙区别,否则你可能会将这些说法解读为人们死于枪支暴力的可能性低于死于刺伤的可能性。推而广之,你可能会得出这样的结论:我们应该把精力重新放在遏制持刀暴力上,而不是枪支暴力上,如果你只看数字,这不是一个合理的决定。

把你的数据弄清楚

这可能比你作为一个作家所希望看到的更多的统计信息。但是我希望这个信息能被理解:数据是强大的,不管是好的还是不好的。

好好使用它们,不仅仅是因为你想让你的内容看起来更好或者表达一个观点。

用错了,可能会适得其反。

如果你看过任何糟糕的统计数据,请在下面评论。我很想看看他们!

暗示性计算机辅助设计

原文:https://towardsdatascience.com/suggestive-computer-aided-design-a9c7698c1cc9?source=collection_archive---------16-----------------------

通过机器学习辅助设计

斯塔尼斯拉斯 ChaillouT4T8 |哈佛设计研究院| 2018 年春季

协同 托马斯·特雷诺

T 基于机器的推荐已经在无数行业得到了应用,从网络上的暗示性搜索到图片股票图像推荐。作为推荐引擎的核心,它可以在海量数据库中查询相关信息文本、图像等,并在用户与给定界面交互时呈现给用户。随着当今大型 3D 数据仓库的聚合,架构&设计可以从类似实践中受益。

实际上,我们专业的设计过程大多是通过 3D 软件rhino 3D、Maya、3DSmax、AutoCAD* 等进行的。建筑师无论是通过 CAD 软件计算机辅助设计还是如今的 BIM 引擎建筑信息建模不断地将自己的意图转化为三维空间中的线和面。建议相关的 3D 对象,取自外部数据源,可能是一种方式,以加强他们的设计过程。*

这就是本文的目的:**研究并提出一种辅助设计师的方法,通过暗示造型。**随着建筑师在 3D 空间中作画,一系列基于机器学习的分类器将能够搜索相关建议并提出替代、相似或互补的设计选项。

为此,我们从 3D 形状识别与分类领域的先例中汲取灵感,建立了一套能够在设计者绘图时向他们推荐模型的方法和工具集。实际上,我们的目标有两个: (1)利用预先建模的建议加快 3D 建模过程,而则通过替代或互补的设计选项激励设计师

卷积神经网络

Figure 1: Convolutional Neural Network Architecture | Source: 3b1b

能够查询与用户绘制的设计特征相匹配的 3D 对象依赖于特征比较。远离标准的几何描述性度量,卷积神经网络(CNN)提供了一种简化且更全面的比较形状的选项。

CNN 不是匹配简单的指标——也称为特征提取——而是将图像作为输入,将像素表示传递给一连串的“神经元”(图 1* )。CNN 模型调整每个神经元的权重,同时在其最后一层输出预测。通过训练和验证的连续阶段,我们能够估计模型的准确性,并进一步调整权重以最大化准确性。一旦充分训练,CNN 模型将预测给定对象图像表示的“”或类别。*

这种类型的网络是机器学习的标准实践,本身并不代表突破或复杂的架构。然而,它仅基于空间特征建立一定数量的直觉的能力比我们的应用更相关:公开可用的 3D 对象的格式异构性使得特征提取和元数据比较成为一个具有挑战性的过程。能够使用图像简单地从它们的拓扑特征来考虑对象,为我们提供了一个用于 3D 形状比较和检索的健壮的统一框架。

一.先例

我们的工作建立在 3 个主要研究项目之上,这些项目最*构建了 3D 对象识别和分类领域。这些论文揭示了卷积作为理解&描述 3D 形状的理想工具的相关性。

【1】用于 3D 形状识别的多视角卷积神经网络

这第一篇论文【1】提出了一个标准的 CNN 架构,该架构被训练来识别彼此独立的形状的渲染视图,并表明甚至可以以远高于使用最先进的 3D 形状描述符的准确度从单个视图识别 3D 形状。当提供形状的多个视图时,识别率进一步增加。

Figure 2: Multi-view CNN for 3D shape recognition | Source: link

此外,还引入了一种新颖的 CNN 架构,它将来自 3D 形状的多个视图的信息组合到一个紧凑的形状描述符中,提供了更好的识别性能。

【2】vox net:用于实时物体识别的 3D 卷积神经网络

Figure 3: The VoxNet Architecture | Source: link

为了利用因激光雷达和 RGBD 扫描仪的可用性增加而导致的点云数据库数量的增长,本文【2】提出了一个“VoxNet”。该模型的架构旨在通过将体积占用网格表示与受监督的 3D 卷积神经网络(3D CNN)集成来解决海量点云处理和标记的问题。

使用 LiDAR、RGBD 和 CAD 数据在公开可用的基准上评估结果。VoxNet 最终实现了超越现有技术水*的准确性,同时每秒标记数百个实例。

【3】设计中的体积表示和机器学习

这最后一篇论文【3】探讨了体素建模与机器学习的机会。

Figure 4: Summary of Work Flow | Source: link

首先介绍了体素建模的概念,并与传统建模技术进行了比较。解释了像像素图和图形表示这样的概念,以最终检查基于从空间和几何光栅化到机器学习的过程的拟议设计系统或工作流的原型实现。

二。模型定义

在这个项目中,我们的方法是识别用户正在绘制的对象,并通过简单地使用对象的形状作为代理来提供相似的对象。

简而言之,我们在这里设计的模型处理两个主要任务:

  • (1)分类:识别用户正在绘制的对象的类型,即找到合适的标签(“椅子”、“长凳”、“床”等)。)对于任何给定的图像输入,结合预测置信度得分。
  • (2)匹配:在 3D 对象的数据库中查询与用户的模型化输入的方面最匹配的一些形状,即返回在我们的数据库中找到的对象列表,从最相似到最不相似排序。

Figure 5: Typical Pipeline | Source: Author

如图图 5* 所示,通过嵌套两个不同层次的模型(一个分类器和一个匹配器),我们也许能够执行这个两步过程。每个模型将在 3D 对象的图像上被训练,然后将在由用户建模的对象的图像上被测试。*

A.数据来源和生成

第一步是生成一个数据库来训练我们的模型。由于我们的方法是为了共享,我们想在此详述这一关键步骤,并分享我们为实现这一目标而使用和构建的资源。

我们首先从现有的公共 3D 对象仓库中提取信息,例如:

  • ShapeNet | 链接
  • 谷歌 3D 仓库| 链接
  • ModelNet | 链接

ShapeNet 数据库中,我们可以下载多达 2.330 个带标签的 3D 模型,分为 14 个特定类别(图 6* )。*

Figure 6: Training Set Classes | Source: Author

使用犀牛 蚱蜢 ,我们然后编写一个工具来创建我们的训练集和验证集。在这个脚本中,围绕每个连续对象旋转的照相机以特定的角度拍摄对象,并将 JPG 图像保存在给定的目录中。

图 7 显示了典型的摄像机路径(左图)和拍摄的最终图像(右图)。

Figure 7: Image Capture Path, and Resulting Images | Source: Author

对于每个对象,我们拍摄 30 幅图像用于训练,10 幅用于验证,同时保持白色背景/中性背景。

用于捕捉图像的数据生成器可从以下地址下载。

我们最终获得一个标记图像库,每类 10 个对象,总共有 14 个不同的类。图 8 中显示了一个子集。

Figure 8: Subset of Training Set | Source: Author

B.分类

一旦我们的数据集准备就绪,我们的目标是在大量的 3D 对象图像上训练我们的第一个模型,即分类器,同时在属于类似类别的其他对象图像集上验证其性能。

迭代次数

几个参数严重影响训练好的分类器的准确性:

  • 训练和验证集的大小
  • 班级人数
  • 每类对象的数量
  • 每个对象的图像数量
  • 两组中图像的尺寸 s
  • 物体周围摄像机的拍摄路径

在这一点上,我们在不同的选项之间迭代,目的是增加模型在验证集上的整体准确性。由于资源有限,我们负担不起从头开始培训的费用。使用一些迁移学习很方便,因为它提供了提高我们模型准确性的可能性,同时绕过了数天的培训。我们添加了一个 VGG16 预训练模型作为模型的第一层,这反过来提高了我们 32%的准确度。

这个训练过程的一个重要收获是,摄像机路径实际上会显著影响最终的精度。在我们尝试过的许多版本中,我们在下面的图 9* 中展示了两种不同摄像机路径的性能对比:圆形球形。*

Figure 9: Training Performance Under Different Image Capture Technics | Source: Author

结果

最终,我们满足于使用 200200 px 图像的分类器,具有球形相机路径,每个对象 30 个图像用于训练,10 个用于验证。在 30 个时期之后,我们最终在验证集上获得了 93%的准确度。现在似乎很清楚,以下参数对整个模型的性能有很大影响:*

  • 增加图像尺寸可以提高精确度。在我们的机器上,速度和精度之间的*衡在 200x200 px 左右找到了*衡点。
  • 摄像机捕捉路径也直接影响精度。通过使用球形捕获路径,而不是圆形路径(见图 9* ),我们显著提高了模型性能:在更少的历元之后,精确度更高。使用球形路径似乎是一种更全面的捕捉给定形状的方式。*

图 10 显示了分类器对四种不同用户输入的典型结果。

Figure 10: Results of Classifier Model, User Input (left) to Predicted Class (right) | Source: Author

  • 更有趣的是在给定用户的 3D 建模过程中运行的相同模型的性能。当一个对象被建模时,少到几个表面就足以将分类器推向正确的方向。因此,在建模过程的早期,我们能够识别建模对象的类。作为回报,我们可以从我们的数据库向用户建议模型,如果用户在建议中找到匹配,可能会减少 3D 建模时间。图 11* 显示了在建模过程的五个不同步骤中分类器的结果。*

Figure 11: Classification During Modeling Process | Source: Author

更多关于 GitHub。

C.相称的

Figure 12: Matching: Finding Best Matches Among Database Through a Convolutional Model | Source: Author

第二步,我们的模型试图在庞大的 3D 模型数据库中寻找理想的匹配。如果分类模型有助于缩小搜索范围,则匹配模型将给定类别的所有 3D 模型从“最相似”到“最不相似”进行排序。

更上 GitHub

我们的匹配模型是另一个卷积神经网络,根据给定类别的对象的图像进行训练,并根据从不同角度拍摄的视图对相同的对象进行验证。对于测试,我们的输入将是一个用户建模的 3D 对象的图像,输出将是我们的数据库中所有对象的列表,按照相似性的顺序排列。

结果

当我们为每个单独的类训练匹配模型时,我们现在能够将分类模型和匹配模型嵌套为一个单独的管道。我们现在可以处理输入图像,首先对其进行分类,最后与数据库中的相似对象进行匹配。同时,我们的模型输出一些预测置信度,帮助我们衡量原始模型和实际匹配之间的相似程度。

已经对不同类别的 7 个对象进行了测试,如图 13 所示。

更多关于 GitHub。

Figure 13: Full Pipeline With Functional Classifying & Matching Model | Source: Author

三。结论

首先,我们鼓励在我们的行业内进一步发展和改进上述理念。在这方面已经做了很多工作,并为邻*领域带来了解决方案。让这些技术渗透到我们的学科中,将会真正有益于我们日常的建筑实践。此外,像我们这样嵌套 CNN 模型只是一个更大概念的一个可能版本: 3D 形状识别和建议。可以部署其他方法和模型,将公开可用数据的广度&丰富性带到架构师&设计者的能力范围内。

事实上,除了本文开发的简单管道,还有一个更基本的想法 : 架构形式的资格。正如在之前的一篇文章中所描述的,能够构建框架,包括现有形状的异质性和复杂性,将很快对我们的学科至关重要。随着数字数据量的增加,并汇集在大型公共存储库中,我们对这些共享知识的访问将与我们的查询智能一样好。正如我们在这里展示的,我们可以依靠在某种程度上依靠机器学习来找到一种共同语言,从而能够比较不同的&复杂形状。

在一个更基本的层面上,这项工作只是显示了暗示性设计的潜力。通过在创意过程中为设计师带来相关的选择,我们有机会拓宽他们的工作范围。随着这种方法扩展到比简单的离散对象更大的分类法,它最终会将被动的集体知识转化为主动的灵感来源。

更多文章,点击这里。

文献学

【1】用于 3D 形状识别的多视角卷积神经网络**,苏航、苏卜兰苏·马吉、伊万杰洛斯·卡罗格拉基斯、埃里克·博学-米勒、马萨诸塞大学阿姆赫斯特分校| 链接

【2】vox net:用于实时物体识别的 3D 卷积神经网络**,丹尼尔·马图拉纳和塞巴斯蒂安·舍雷尔| 链接

【3】三维对象的再混合和重采样在设计中使用体积表示和机器学习**,NJ Namju Lee,哈佛 GSD,2017 | 链接

21 世纪的自杀(上)

原文:https://towardsdatascience.com/suicide-in-the-21st-century-part-1-904abe8e1f5c?source=collection_archive---------12-----------------------

Photo by Gabriel on Unsplash

自杀是英国 20-34 岁年轻人的主要死因,自杀的男性是女性的三倍。令人担忧的是,在这成千上万的男性和女性中,最*的统计数据显示,在 2005 年至 2015 年期间,只有 27%的自杀受害者被归类为患者自杀,即个人在去世前一年曾接触过心理健康服务。

在这篇文章的第一部分,我们将对世界各地的自杀率进行一些基本分析,在第二部分,我们将更深入地研究一些机器学习,特别是 K-means。

我们开始吧!

本项目使用的数据集取自 Kaggle ,以大型表格的形式发布为“1985 年至 2016 年自杀率概览”。csv 文件。该数据集包含 27820 行,分为 12 列:“国家”、“年份”、“性别”、“年龄”、“自杀人数”、“人口”、“自杀人数/10 万人口”、“国家-年份”、“人类发展指数代表年份”、“gdp 代表年份(\()”、“人均 GDP(\))”、“世代”。

数据预处理

数据预处理是数据挖掘过程中最关键的步骤之一,处理初始数据集的准备和转换。尽管数据集本身相对干净,但仍有必要删除此分析不需要的任何冗余数据。

在我的项目的 Github 资源库中可以获得数据预处理的所有步骤,但是,我们将讨论几个最重要的步骤。

首先,检查是否有丢失的数据是有用的,因为对丢失数据的帧进行分析很可能会导致错误。正如我们在下面看到的,HDIForYear 列有许多空条目。填充缺失数据的方法有很多,但是,大多数方法都假设该列的大多数行都被填充。但是,在这种情况下,总共 27820 行中有 19456 行缺少该属性的数据,因此最好将该列完全删除。

df.isnull().sum()

Missing values in HDIForYear

df.drop('HDIForYear', axis=1, inplace = True)

开始分析之前,务必确保数据框仅包含与其相关的数据。由于该分析将关注 21 世纪年轻男性自杀,我们希望删除性别= '女性'的任何行、年份不> = 2000 的任何行以及不在我们希望分析的年龄范围内的任何行。这些过滤器可以很简单地在熊猫身上实现,概述如下。

df = df[df.Year >= 2000]
df = df[df.Gender =='male']criteria_1 = df['Age'] == '15-24 years'
criteria_2 = df['Age'] == '25-34 years'
criteria_all = criteria_1 | criteria_2
df= df[criteria_all]

既然数据集更像我们分析所需要的,数据框可以按年份和总和分组,以显示每年的自杀人数。运行该图可以看出,2016 年的数据非常少,因为数据比往年低 10 倍以上,这是不正确的。所以,为了准确起见,有必要去掉 2016 年的数据。

#create new data frame grouped by year to check
yearlyStats = df.groupby('Year').sum()
yearlyStats

Suicide statistics by year

df = df[df.Year != 2016]

删除这个数据只删除了 32 行,可见 2016 年的数据是多么的不完整。使用相同的 groupby 方法,很容易按年份显示数据,因此我们可以了解哪些国家报告的数据很少。以下国家被删除,因为对它们的任何分析都是不准确的:安提瓜、巴巴多斯、格林纳达、马尔代夫、黑山和圣文森特。

数据聚合

我们知道数据集有一个 Country 列,但是如果我们希望对更大的组(如大洲)进行分析,该怎么办呢?在 Python/Pandas 中,这同样可以通过三个相当简单的步骤来完成。

  1. 根据联合国统计司的数据,创建大陆阵列并给它们分配国家
  2. 把这些移到字典里
  3. 使用 Pandas 中的 Map 函数将各大洲映射到各个国家。请注意,可以跳过步骤 1,直接将国家放入字典中,但是首先将它们移动到一个数组中,这样在将来会更容易,例如,如果要将一个国家添加到数据集中。
#create lists of countries per continenteurope = ['Albania', 'Austria', 'Azerbaijan', 'Belarus', 'Belgium', 'Bosnia and Herzegovina', 'Bulgaria', 'Croatia', 'Cyprus', 'Czech Republic', 'Denmark', 'Estonia', 'Finland', 'France', 'Georgia', 'Germany', 'Greece', 'Hungary', 'Iceland', 'Ireland', 'Italy', 'Latvia', 'Lithuania', 'Luxembourg', 'Malta', 'Montenegro', 'Netherlands', 'Norway', 'Poland', 'Portugal', 'Romania', 'Russian Federation', 'San Marino', 'Serbia', 'Slovakia', 'Slovenia', 'Spain', 'Sweden', 'Switzerland', 'Ukraine', 'United Kingdom']asia = ['Armenia', 'Bahrain', 'Israel', 'Japan', 'Kazakhstan', 'Kuwait', 'Kyrgyzstan', 'Macau', 'Maldives', 'Mongolia', 'Oman', 'Philippines', 'Qatar', 'Republic of Korea', 'Singapore', 'Sri Lanka', 'Thailand', 'Turkey', 'Turkmenistan', 'United Arab Emirates', 'Uzbekistan']northamerica = ['Antigua and Barbuda', 'Bahamas', 'Barbados', 'Belize', 'Canada', 'Costa Rica', 'Cuba', 'Dominica', 'El Salvador', 'Grenada', 'Guatemala', 'Jamaica', 'Mexico', 'Nicaragua', 'Panama', 'Puerto Rico', 'Saint Kitts and Nevis', 'Saint Lucia', 'Saint Vincent and Grenadines', 'United States']southamerica =  ['Argentina', 'Aruba', 'Brazil', 'Chile', 'Colombia', 'Ecuador', 'Guyana', 'Paraguay', 'Suriname', 'Trinidad and Tobago', 'Uruguay']africa = ['Cabo Verde', 'Mauritius', 'Seychelles', 'South Africa'] australiaoceania = ['Australia', 'Fiji', 'Kiribati', 'New Zealand']#move these to a dictionary of continentscontinents = {country: 'Asia' for country in asia}
continents.update({country: 'Europe' for country in europe})
continents.update({country: 'Africa' for country in africa})
continents.update({country: 'North_America' for country in northamerica})
continents.update({country: 'South_America' for country in southamerica})
continents.update({country: 'Australia_Oceania' for country in australiaoceania})

然后,我们可以简单地将各大洲映射到我们的国家

df['Continent'] = df['Country'].map(continents)

既然数据已经过预处理,数据框已经从 27820 行 12 列变成了 2668 行 10 列,现在可以进行分析了。

探索性数据分析

首先,让我们为我们的绘图定义一个好的调色板。

flatui = ["#6cdae7", "#fd3a4a", "#ffaa1d", "#ff23e5", "#34495e", "#2ecc71"]
sns.set_palette(flatui)
sns.palplot(sns.color_palette())

Seaborn Colour Palette

首先,我们将展示一些以图形形式显示有趣数据的基本图表。通过按年份对数据进行分组并执行. sum(),我们能够创建一个包含全球每年自杀总人数的临时数据框架。采用这个框架,应用 Matplotlib 代码和 Seaborn 美学,我们可以显示全球自杀率,同时还可以绘制一条*均线。

data_per_year['SuicidesNo'].plot()
plt.title('Total No. of Suicides per Year: 2000 To 2015', fontsize = 22)
plt.axhline(y=52720, color='black', linestyle='--')
plt.ylabel('No. Suicides', fontsize = 20)
plt.xlabel('Year', fontsize = 20)

Global suicides (2000–2015)

这里我们可以看到有下降的趋势,全球自杀率在逐年下降。可以推测,这是因为意识的提高或资金等原因。,但这是以后可以深入探讨的事情。

接下来,我们可以使用 Matplotlib 中的条形图来显示各大洲每年每 10 万人口的*均自杀人数。使用按洲分组创建新的数据框。意思是()这次。该数据框表示如下:

data_per_continent = df.groupby('Continent').mean()
data_per_continentax = data_per_continent['Suicides/100kPop'].plot(kind='bar', figsize=(15, 10), fontsize=14)
plt.title('Mean Suicides/Year by Continent', fontsize = 22)
ax.set_xlabel("Continent", fontsize=20)
ax.set_ylabel("Suicides/100k Population", fontsize=20)
plt.show()

Suicides by Continent

有趣的是,我们可以看到南美洲是年轻男性自杀率最高的大陆,其次是欧洲。虽然有用,但它并没有显示这些大陆的自杀率随时间的变化。使用“洲”和“年”对数据进行分组,并执行以下代码后,我们能够绘制出各洲每 10 万人口的自杀率变化率:

dfAgg = dftesting.groupby(['Continent','Year'],sort=True,as_index=False)['Suicides/100kPop'].mean()by_cont = dfAgg.groupby('Continent')for name, group in by_cont:plt.plot(group['Year'], group['Suicides/100kPop'], label=name, linewidth=6.0)plt.title('Mean Suicide/100k, Year by Year, per Continent', fontsize = 22)
plt.ylabel('Suicides/100k', fontsize = 20)
plt.xlabel('Year', fontsize = 20)
leg = plt.legend(fontsize = 12)
for line in leg.get_lines():line.set_linewidth(10)
plt.show

Suicide rate by Continent over the years

可以看出,该图显示了总体下降趋势,但也显示了南美和非洲等大陆的恶性飙升(后者可能是由于报告数据的不一致)。接下来,我们希望找出哪些国家的自杀率最高。我们也可以找出最低的。然而,由于报告发生率低的国家等原因,这可能会有所偏差。(主要是非洲国家)。在 Python 中,我们能够通过创建数据框来创建可视化绘图,该数据框根据每个国家的*均自杀人数对数据进行分组,通过降序对值进行排序并绘制。数据帧的 head()作为条形图。

data_suicide_mean = df['Suicides/100kPop'].groupby(df.Country).mean().sort_values(ascending=False)
f,ax = plt.subplots(1,1,figsize=(15,4))
ax = sns.barplot(data_suicide_mean.head(10).index,data_suicide_mean.head(10))
plt.ylabel('Suicides/100k', fontsize = 20)
plt.xlabel('Country', fontsize = 20)

Countries with the highest suicide rates

多年来,立陶宛的自杀率最高,紧随其后的是俄罗斯和哈萨克斯坦,这三个国家的*均自杀率都超过了每 10 万人中 50 人。有趣的是,立陶宛和哈萨克斯坦都与俄罗斯接壤。

由于 2016 年的数据因不完整而被删除,我们可以运行分析的最*年份是 2015 年。Matplotlib 允许使用散点图,能够绘制自杀率与 GDP 的关系,以国家为单位。同样,准备数据框架很重要,例如排除任何非 2015 年的数据和不相关的列。按洲和国家分组,同时包括自杀率和 GDP.sum()给出了所需数据框架的正确形状。为该数据框绘制自杀率与 GDP 的关系图会将数据分散到各个国家,显示该数据框中每个国家的 GDP 与自杀率的关系。此外,将 hue =“Continent”添加到散点图参数中会显示根据国家所在的洲进行着色的数据。

#plot suicide rate vs gdp
plt.figure(figsize=(20,16))
sns.scatterplot(x='GdpPerCapital($)',s=300, y='Suicides/100kPop',data=dfcont, hue='Continent') 
plt.title('Suicide Rates: 2015', fontsize= 30)
plt.ylabel('Suicide Rate /100k Population', fontsize = 22)
plt.xlabel('GDP ($)', fontsize = 22)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.legend(loc=1, prop={'size': 30})plt.show()

Suicide rates vs GDP, coloured by Continent

有趣的是,似乎有很多国家的 GDP 很低,自杀率也很低,这有点出乎意料。然而,这可能是因为较贫穷国家报告的自杀率较低,而实际上自杀率可能要高得多。尽管如此,GDP 似乎对自杀率有着有趣的影响。

观察一个国家的总体幸福感是否会影响其年轻男性的自杀率也是一件有趣的事情。以 2015 年世界幸福报告 10]为例,可以为数据框中的国家创建一个所有幸福得分的列表;这可以简单地读入一个新列“HappinessScore ”,并将值转换为 Float。在这张图中,幸福指数低于或等于 5.5 的国家被移除了——这是因为许多得分低的国家自杀率低,这可能是由于数据不完整、没有报告自杀或自杀分类不同。然后可以使用 Matplotlib/Seaborn 中的散点图绘制该数据,以给出以下可视化效果,同样使用 hue =“continental”:

#plot suicide rates vs happiness score
plt.figure(figsize=(20,16))
sns.scatterplot(x='HappinessScore',s=300, y='Suicides/100kPop',data=dfcont, hue='Continent') 
plt.title('Suicide Rates: 2015', fontsize= 30)
plt.ylabel('Suicide Rate /100k Population', fontsize = 22)
plt.xlabel('HappinessScore', fontsize = 22)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.legend(loc=1, prop={'size': 30})plt.show()

Suicide rates vs HappinessScore, coloured by Continent

同样,很难判断一个国家的自杀率和它的幸福指数之间是否有真正的关系;因此,将进一步探讨这种关系。我们可以通过应用双变量分析来做到这一点,在 Pandas 中绘制一个相关矩阵,它计算列的成对相关。

dfcont.corr(method = 'pearson')

Pearson correlation matrix

可以观察到,在该数据帧中,使用皮尔逊方法,GdpPerCapita($)和硅化物/100kPop 之间存在-0.175131 的相关性,这意味着两者之间存在关系,但不是很强的关系,负值表示相关关系成反比,即一个增加,另一个减少。这也可以用 Seaborn 可视化为热图,给出一个更令人愉快的相关矩阵视图。

sns.heatmap(dfcont.corr(method = 'pearson'),cmap='YlGnBu',annot=True)

Seaborn heatmap matrix

感谢阅读!

请继续关注将于下周发布的第二部分。我们将坚持使用这个数据集,并进入一些机器学习。

21 世纪的自杀(下)

原文:https://towardsdatascience.com/suicide-in-the-21st-century-part-2-d8f9c4b9e588?source=collection_archive---------17-----------------------

Photo by Paola Chaaya on Unsplash

欢迎回来!如果您没有了解第 1 部分,可以在下面找到:

[## 21 世纪的自杀(上)

自杀不会传染,我们需要谈论它。

towardsdatascience.com](/suicide-in-the-21st-century-part-1-904abe8e1f5c)

如前所述,第 2 部分将包含机器学习,或者更具体地说,使用 python 中的 K-Means 进行机器学习。

在我们开始之前,如果您错过了第 1 部分,这里有一个快速回顾。

概述

在第一部分中,我们主要做了数据预处理和一些 EDA(探索性数据分析)。使用的数据是来自 Kaggle 的全球自杀率数据集。我们清理了数据,然后增加了一个额外的栏目,快乐得分,摘自联合国每年发布的《世界快乐报告》。然后,我们以图表的形式进行了一些基本的视觉数据分析,其中一些可以在下面看到:

Plots taken from Part 1

现在我们已经概括了,我们可以继续进行一些机器学习!

k 均值

K-Means 是一种广泛使用且相对简单的无监督聚类机器学习技术。该算法迭代地工作,并试图将数据集划分为 K 个预定义的子组(或聚类),由此每个数据点属于一个组。它旨在使聚类间的数据点尽可能相似,同时也试图使聚类尽可能远离。该算法的工作原理如下:

  1. 初始化——首先,K-Means 从数据集中随机选择 K 个数据点作为初始质心(质心是一个聚类的中心)。注意,该算法还不知道聚类的正确位置。
  2. 聚类分配-计算每个数据点和聚类中心之间的欧几里德距离,然后将数据点分配给与聚类中心的距离最小的聚类。
  3. 移动质心——使用以下公式重新计算新的聚类中心,其中 Ci 代表第和第个聚类中的数据点数量。

Recalculating Cluster Centres

准备

在实现任何类型的机器学习之前,确保数据准备正确是至关重要的。否则,算法极有可能会出错。

作为准备工作的第一步,在先前使用的数据框架中增加了一个额外的列:基尼系数。基尼指数是由科拉多·基尼在 1912 年发展起来的一种衡量收入分配的方法;该指数(或系数)被用作衡量经济不*等的标准。系数用 0 到 1 之间的值来度量,其中 0 表示完全相等,1 表示完全不相等。基尼指数的数据是从中央情报局公共图书馆中提取的,并以与之前用于幸福指数相同的方式添加;创建一个所有基尼指数值的列表,然后读入新列,再次转换为浮点值。

如前所述,K-Means 使用欧几里德距离,当面对比例/单位非常不同的要素时,这可能会成为问题。例如,GDP 通常是几万,而幸福指数通常是一个小于 10 的浮动值,这意味着 K 均值将是非常次优的。为了避免这一障碍,将最小-最大缩放器应用于数据帧。在此缩放中,从所有值中减去最小值。然后,将这些值除以最小值和最大值之间的差值,得到值在 0 和 1 之间的完整数据集。两个字符串列(国家和大陆)被删除,因为 MinMaxScaling 不能应用于字符串。然后应用定标器,产生一个新的数据帧— dfscaled —包含 sizes/100k pop、GdpPerCapita($)、HappinessScore 和 GiniIndex。

from sklearn import preprocessing
dfcontpre =  dfcont.drop('Country', axis=1)
dfcontpre = dfcontpre.drop('Continent', axis=1)
minmax_processed = preprocessing.MinMaxScaler().fit_transform(dfcontpre)
dfscaled = pd.DataFrame(minmax_processed, index=dfcontpre.index, columns=dfcontpre.columns)

在实现该算法之前,选择最佳数量的 K 个簇是很重要的。这在理论上可以通过反复试验来实现;然而,绘制肘形曲线更有效。这种方法的思想是对一系列值 k (在这种情况下,1–20)的数据集运行 K 均值,并对每 K 次迭代计算和绘制误差*方和(SSE)。理想情况下,这个线图看起来像一只手臂,肘部显示了数据集中聚类的最佳数量 k

首先,让我们定义一个好的调色板

flatui = ["#6cdae7", "#fd3a4a", "#ffaa1d", "#ff23e5", "#34495e", "#2ecc71"]
sns.set_palette(flatui)
sns.palplot(sns.color_palette()

Our Palette for future plots

现在我们可以绘制肘部曲线:

from sklearn.cluster import KMeans
from sklearn.decomposition import PCA#plotting elbow curve for ideal number of clusters
Nc = range(1, 20)
kmeans = [KMeans(n_clusters=i) for i in Nc]
score = [kmeans[i].fit(Y).score(Y) for i in range(len(kmeans))]
pl.plot(Nc,score)
plt.xlabel('Number of Clusters')
plt.ylabel('Score')
plt.title('Elbow Curve')
plt.show()

Plotted elbow curve

从肘图中可以看出,3 将是最优的聚类数,虽然肘图并没有过分的与众不同,但足以决定最优的 k 个聚类。

现在我们已经决定了要使用的最佳聚类数,我们可以开始实现 K-Means 了。

履行

自杀率/100k pop vs GdpPerCapita($)

首先,将两列的数据放入 1D NumPy 数组中。然后将这些数组压缩在一起,形成一个 2D NumPy 数组,其示例如下所示:

print X[0:5]

A sample of the scaled 2D NumPy array (Note that all values are between 0 and 1)

然后,使用前面提到的三个集群,在 2D 阵列 X 上运行 K-Means。然后创建一个散点图,X 轴和 Y 轴分别为硅化物/100kPop 和 GdpPerCapita($)。然后使用 kmeans.labels_,通过颜色将这些分散的数据分开,这意味着它们是根据 kmeans 分配的聚类进行分离的。然后使用 cmap 选择“viridus”配色方案绘制颜色(颜色对比比我们自定义的调色板更好)。最后,使用 kmeans.cluster_centres_ 绘制聚类中心,生成以下图:

#k-means plot suicide rate vs gdp, 3 clusters
kmeans = KMeans(n_clusters = 3, random_state = 0)                   
kmeans.fit(X) 
plt.figure(figsize=(20,16))
plt.scatter(X[:, 0], X[:, 1],c = kmeans.labels_,cmap='viridis', s = 300)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s = 300, c = 'red')

GDP vs Suicide Rates using K-Means

这个图显示了一个有趣的结果。可以看出,不存在 x 和 y 都为高的数据,当回头参考图 14 时,这是有意义的。因此,我们可以将这些集群分类如下:

  • 深紫色:高 GDP 低自杀风险国家
  • 黄色:低 GDP 低自杀风险国家
  • 提尔:低 GDP 高自杀风险国家
  • 相当令人惊讶的是,K-Means 成功地将这些群体有效地聚类,主要是因为当看起来人均 GDP 和每 10 万人口自杀率之间的相关性相当低。

如果我们希望看到哪个国家被分配到哪个集群,我们也可以运行下面的代码:

cluster_map = pd.DataFrame()
cluster_map['data_index'] = dfscaled.index.values
cluster_map['cluster'] = kmeans.labels_
cluster_map.head(50)

自杀/100kPop vs .快乐得分

将 K-Means 应用于自杀/100kPop 和快乐核心的管理方式大致相同;两个一维 NumPy 数组被压缩成一个二维数组,然后 K-Means 对其进行处理以创建必要的聚类。然后绘制颜色并添加聚类质心。

#1d numpy arrays zipped to 2d
f1 = dfscaled['Suicides/100kPop'].values
f2 = dfscaled['HappinessScore'].values
X = np.array(list(zip(f1, f2)))
#k-means suicide rate vs happiness score
kmeans = KMeans(n_clusters = 3, random_state = 0)                   
kmeans.fit(X) 
plt.figure(figsize=(20,16))
plt.scatter(X[:, 0], X[:, 1],c = kmeans.labels_,cmap='viridis', s = 300)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s = 300, c = 'red')

HappinessScore vs Suicide Rates using K-Means

同样,从算法中可以看到三个相当不同的集群,它们可以分类如下:

  • 黄色:低风险的“快乐”国家
  • 深紫色:低风险的“幸福”国家
  • 缇尔:高风险“不快乐”国家

同样,当看到低相关性(-0.24)(来自第 1 部分)时,数据被有效地聚类是令人惊讶的

自杀率/100kPop vs .基尼指数

将 K-Means 应用于自杀率/100kPop 和基尼系数的方法与之前相同。

#1d numpy arrays zipped to 2d
f1 = dfscaled['Suicides/100kPop'].values
f2 = dfscaled['GiniIndex'].values
X = np.array(list(zip(f1, f2)))
#plot k-means  suicide rate vs gini index
kmeans = KMeans(n_clusters = 3, random_state = 0)                   
kmeans.fit(X) 
plt.figure(figsize=(20,16))
plt.scatter(X[:, 0], X[:, 1],c = kmeans.labels_,cmap='viridis', s = 300)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s = 300, c = 'red')

GiniIndex vs Suicide Rates using K-Means

此外,该算法显示了三个不同的聚类,与之前的结果非常相似,右上角没有数据点(高 X 值和高 Y 值)。这些数据可以分类如下:

  • 深紫色:低风险的“不*等”国家
  • 缇尔:低风险的“*等”国家
  • 黄色:高风险“*等”国家

这是一个非常令人惊讶的结果,因为高基尼指数意味着更高的财富不*等,而且没有一个国家既有非常高的基尼指数,又有非常高的自杀率。这可以用多种因素来解释,例如财富不*等的国家的自杀率可能比报道的数字高得多。虽然这个数据的含义的表述本身就令人惊讶,但可以通过数据相关性来解释。

在纳入新栏的同时再次关联数据显示,自杀率/100 千人口与基尼系数之间的相关性为-0.17,这意味着存在轻微的反比关系,即随着基尼系数的增加,自杀率/100 千人口下降。为了显示这些特征对自杀/100kPop 结果的重要性,可以应用通过随机森林的排列重要性。

排列重要性

要素重要性是一种计算哪些要素对预测影响最大的方法。有许多方法可以实现这一点;然而,排列的重要性是最快的和广泛使用的。
排列重要性的工作原理是,当一个特性变得不可用时,可以通过观察分数或准确度降低多少来测量特性的重要性。理论上,这可以通过删除一个特性,重新训练估计器,然后检查结果得分,并对每个特性重复进行测试。这将花费大量时间,并且计算量相当大。相反,从数据集的测试部分“移除”了一个特征。估计者会期望该特征存在,因此完全移除该特征会导致误差;因此,特征值被混洗所有特征值产生的噪声所取代。

还应该注意的是,排列重要性与大量的列进行斗争,因为它会变得非常耗费资源。然而,对于本文中使用的数据集来说,这不是问题,因为列很少。

因此,项目中引入了必要的模块——排列重要性和随机森林回归量。移除索引列时,从 dfscaled 创建了一个新的数据框 dfrfr。目标变量(自杀/100kPop)存储在 y 中,而其余的列存储在 x 中。然后实施使用随机森林的排列重要性,并显示结果权重和特征。

#import modules for permutation importance, and show output
import eli5
from eli5.sklearn import PermutationImportance
from sklearn.ensemble import RandomForestRegressordfrfr = dfscaled.drop("index", axis = 1)
rfr = RandomForestRegressor(random_state=42)y = dfrfr[['Suicides/100kPop']].values
X = dfrfr.drop('Suicides/100kPop',axis=1).valuesperm = PermutationImportance(rfr.fit(X,y), random_state=42).fit(X, y)
eli5.show_weights(perm, feature_names = dfrfr.drop('Suicides/100kPop',axis=1).columns.tolist())

Permutation Importance using Random Forest

当回头参考特征相关性并看到 HappinessScore 与自杀/100kPop 的相关性最高时,这个结果是有意义的,其次是 GdpPerCapita($),最后是 GiniIndex。

结论

总体而言,尽管数据没有显示预期的某些特征的影响,但它仍然显示了这些影响的一个非常有趣的结论,例如收入不*等对各国自杀率的影响似乎无关紧要——这是以前被认为有显著影响的。

由于缺乏预期紧密相关的特征之间的相关性,该数据受到限制,例如,幸福感得分和自杀率/100k,因为普遍不幸福被认为会增加自杀率。它还受到缺乏某些国家和某些年份的数据的限制,这意味着必须对 2015 年而不是 2018/19 年的数据进行主要分析。

在未来的分析中,最好有一个特征被证实对各国的自杀率有很大影响。这将允许更精确的图,也允许更有意义的 K-均值聚类。

这篇文章的完整代码可以在下面的我的 github 上找到:

[## 哈里比特/自杀率分析

通过在 GitHub 上创建一个帐户,为 Harry bitten/自杀率分析开发做出贡献。

github.com](https://github.com/HarryBitten/Suicide-Rates-Analysis)

感谢阅读!我对这一切都很陌生,但我打算继续发布许多有趣的项目,主要是在数据科学/机器学习方面

用数据科学洞察自杀预防

原文:https://towardsdatascience.com/suicide-prevention-insights-with-data-science-2fb2636a6d82?source=collection_archive---------12-----------------------

宗教是一种强有力的抗抑郁药

我相信我第一次经历强烈的情感冲击是在大约 11 岁的时候,当时我发现我认识的、钦佩的、被认为成功和幸福的人突然决定以自杀来结束自己的生命。短短几年内,我的两个童年好友的爸爸就发生了这样的事情。这两个人看起来都像慈爱的父母和模范公民,所以这个消息对我和他们各自的社区来说都是一个巨大的冲击。同样的悲剧故事在我青少年时期的三个主要英雄身上重演——柯特·科本、罗宾·威廉姆斯和安东尼·鲍代恩。这些年来,我度过了无数个不眠之夜,试图找出是什么可能将我所热爱和钦佩的人推向如此极端,这些人乍一看似乎拥有成功和幸福的生活。受所有这些未解问题的驱使,我决定与我的同学 Brian Srebrenik 合作,尝试用数据科学来研究自杀之谜,这些问题可能折磨过任何一个*距离接触过亲密朋友、家庭成员或明星偶像令人震惊的自杀事件的人。

这个项目的目标是利用 200 个国家的一些社会经济和心理健康指标建立一个机器学习监督的回归模型,并试图确定哪些因素可能与国家自杀率有统计上的显著相关性。

在对之前在这个问题上所做的工作做了一些研究后,我们收集了以下自变量的数据,我们认为这些数据将有助于建立我们的模型。我们使用了 2016 年的数据。

  1. 抑郁率
  2. 精神分裂症发病率
  3. 焦虑率
  4. 躁郁症
  5. 饮食失调
  6. 酒精使用障碍
  7. 药物使用障碍
  8. GDP
  9. 人均医疗支出
  10. 失业率
  11. 居住在拥有> 10 万人口的城市的人口比例
  12. 上网人口的百分比
  13. 信教人口百分比的分类数据

注:如果您对我们如何构建和优化模型的技术细节不感兴趣,请跳至“模型总结和最终见解及结论”部分,了解我们研究结果的详细总结。

P 修复数据并检查多重共线性

首先,我们从世界卫生组织 API 和其他几个网站收集了 2016 年的年度社会经济数据。在清理所有数据并将其合并到一个 pd 中之后。数据框架我们使用 SeaBorn 关联热图检查了独立变量多重共线性:

Colinearity Heatmap using sns.heatmap(final_table.corr(), center = 0)

热图告诉我们,双相情感障碍%与其他三种精神健康问题有很高的相关性,因此我们决定在运行模型之前删除该变量,以避免由严重的多重共线性引起的额外噪声。

检查每个独立变量和自杀率之间的线性关系

接下来,我们创建了每个自变量与因变量自杀率相关性的成对散点图:

Scatter pair-plots using seaborn.pairplot()

从上面的图表中我们可以看到,在抑郁、焦虑、精神分裂症、酗酒的比率和一个国家的宗教程度之间存在某种程度上的线性关系。所以,我们最初的期望是,我们的机器学习模型应该给这些类别分配更多的权重。

缩放我们的独立变量,并在模型中引入变量组合和多项式

由于我们的一些自变量以千为单位,而另一些以百分比为单位,因此我们决定调整所有自变量,以确保我们的模型不会为某些变量分配过大的系数。

Scaling variables using sklearn.preprocessing.scale

下一步是通过二次多项式函数引入交互项,以帮助我们的模型进行特征选择,提高其最终预测精度,并降低其均方根误差。下面的关联热图有助于我们识别所有相关的新变量:

对每个回归模型应用 RFE 和交叉验证,以选择最小化 RMSE 的最佳模型

既然我们的数据已经清理、缩放和预处理,现在是最后一步的时候了——根据我们的训练数据训练我们的机器学习模型,以提高其对测试数据的预测准确性。我们使用三个模型优化子步骤来创建我们自己的定制 GridSearch 函数:

  1. 我们使用下面的函数运行线性、套索和岭回归,以确定哪一个生成的模型误差最小。对于这个特定的数据集,我们发现岭回归有最好的结果。我们对训练数据-测试数据比率采用了 80–20 的比例。
  2. 我们使用 RFE(递归特征消除)将所有独立变量逐个输入每个模型,并选择最小化 RMSE 的变量数量和组合。
  3. 我们使用 K-Fold 交叉验证来优化每个模型在测试数据上准确预测的能力,这是它以前从未见过的。(代码如下)

Our custom GridSearch algorithm

下图显示了我们的 RMSE 函数,以及我们如何训练我们的模型来挑选产生最低误差的独立变量的数量:

22 Variables were chosen with an RMSE = 3.54

模型总结和最终见解和结论

现在大部分繁重的工作已经完成,是时候分析我们的结果了。首先,我们用训练数据与测试数据的模型统计绘制散点图,以确保没有太多的训练数据偏差或过度拟合。正如我们从下图中看到的,测试和训练样本的 RMSE、z 分数和 R *方非常相似,这正是我们所希望的。0.66 的 R_squared 分数并不惊人,但是考虑到我们只有大约 150-200 个例子(国家),我们对模型的表现相当满意。我们相信,如果我们能够将 500 多个观察值输入到我们的训练集中,模型的预测准确性将会显著提高。

Model performance on test_data versus train_data

我们还想看看实际的独立变量及其系数,并试图从它们的分布中得出一些见解和结论。以下是最终模型方程和每个独立变量的条形图及其在最终模型中的权重:

**Suicide_Rate** = 10.28 + 3.58***Depression**  +  2.74***Alcohol_use**  -  1.87***Rel_High ** -  2.24***Schizophrenia Depression**  +  0.65***Schizophrenia health_spend_perca**  +  1.23***Schizophrenia Rel_Low**  -  1.56***Eating_disorders Drug_use**  +  1.04***Eating_disorders Depression**  -  2.05***Eating_disorders Alcohol_use**  +  1.49***Eating_disorders urban_population**  +  0.72***Anxiety^2**  -  1.17***Anxiety Depression**  -  1.37***Anxiety GDP**  -  2.89***Anxiety Rel_High**  +  1.67***Drug_use** **Unem_rate**  +  1.58***Drug_use GDP ** -  2.48***Depression Rel_High**  -  1.76***Depression Rel_Low**  -  0.92***Alcohol_use^2**  +  0.71***Alcohol_use GDP**  +  2.16***Alcohol_use urban_population**  -  1.42***Alcohol_use Rel_High**  -  2.23***Unem_rate GDP**  +  0.91***Unem_rate health_spend_perca**  -  0.45***Unem_rate Internet_access_percap**  -  0.82***GDP urban_population**  +  1.02***GDP Rel_High**  +  2.14***urban_population Rel_Low**

结论:

根据下面的方程系数和柱状图,我们可以假设以下假设,并可以进一步检验:

  1. 倾向于增加一个国家自杀率的变量:
  • 抑郁率
  • 酒精使用障碍率
  • 城市人口比例结合与低水*的宗教信仰
  • 城市人口% 结合与高酒精使用
  • 精神分裂症的比率结合了低宗教信仰的比率
  • 吸毒紊乱与高失业率结合在一起
  • 与国内生产总值水*相结合的药物使用

2。倾向于降低一个国家自杀率的变量:

  • 人口的高度宗教性
  • 抑郁率结合与高宗教信仰
  • 焦虑率结合与高度宗教性
  • 酒精使用障碍率结合与高度宗教性
  • 药物使用率结合高宗教性
  • 饮食失调率结合与酒精使用率
  • 进食障碍率结合与药物使用率

调查一个国家的宗教信仰和自杀率之间的反比关系

当谈到对自杀率的影响时,我很好奇也很惊讶地发现我们的模型很重视一个国家的宗教程度。如果我们仔细观察上面的系数图,我们可以看到,大多数似乎对高自杀率有很强直接影响的特征,如抑郁症、酗酒和精神分裂症,在宗教人口高度密集的国家往往会失去它们的负面影响。这一有趣的现象在下面的两个图表中得到了证明:

Most High suicide rates fall inside the range of countries where less than 50% of the population is religious

Countries with the lowest level of religiousness have a much higher AVG Suicide Rate

最后的个人想法

尽管我们没有分析足够的数据来得出任何有力的结论,但我们的发现促使我进一步思考这个话题,并试图提出有效的解释,说明宗教如何能够否定一些似乎导致高自杀率的因素的影响,如抑郁、焦虑和吸毒。我对患有抑郁症和自杀想法的人的主要症状做了一些研究,如下所列:

  • 对未来有一种深深的绝望感,对情况会有所改善不抱太大希望
  • 孤独感和逃避朋友或社交活动的倾向
  • 一种的感觉情感空虚、缺乏爱或人际关系
  • 增加使用药物和/或酒精
  • 经历了最*的创伤或生活危机

宗教是如何对抗这些症状,成为精神上的抗抑郁药物的?

  • 宗教经常围绕着信仰和希望
  • 宗教经常试图赋予苦难以意义,并试图教导人们如何克服个人创伤(解决创伤的痛苦)
  • 宗教机构倾向于提供一个支持系统和一种社区感(解决孤独感和反社会行为)
  • 许多宗教对毒品和酒精持保守观点(解决高毒品/酒精使用障碍)
  • 许多宗教教导说上帝是爱上帝无条件地爱所有的生命(解决爱的缺乏和填补情感的空虚)

因此,有意或无意地,宗教似乎充当了一种强效抗抑郁药物,它可以填补许多患有抑郁症和有自杀想法的人似乎会经历的情感和社会空白。对我个人来说,这是我们项目中最有趣的发现,我可以有把握地说,我将带着在这次调查中学到的许多其他宝贵经验,并试图在未来用它们来帮助有需要的人。我真诚地希望这篇文章也能让世界各地的许多人受益,他们能以这样或那样的方式从我们的发现中受益!和*和爱给所有的生命❤

指数随机变量的和

原文:https://towardsdatascience.com/sum-of-exponential-random-variables-b023b61f0c0f?source=collection_archive---------2-----------------------

推导埃尔兰分布的概率密度函数

X1X2独立的指数随机变量,速率为 λ

X1~EXP(λ)
X2~EXP(λ)

Y=X1+X2

问题: Y 的 PDF 是什么?
我们在哪里使用Y 的分布

要找到任何发行版的 PDF,我们使用什么技术?

👉我们找到 CDF 并对其进行微分。
(我们在之前的帖子中已经多次使用过这种技巧。)

好,那我们来找 (X1 + X2) 的 CDF。

但是我们不知道 (X1+X2) 的 PDF。事实上,这正是我们想要计算的东西。

嗯…我们可以说…

**∫ PDF(X1+ X2) = ∫ PDF(X1) + ∫ PDF(X2) ???!?!?**

不,当然不是。

如果这样做的话, (X1+X2) 的 PDF 总和将为 2。(任何 PDF 的积分总和应始终为 1。)

我如何在不知道 PDF 的情况下找到任何发行版的 CDF?

我们可以用于概率计算的技术:边缘化和独立性。

在上面的 CDF 推导中使用了两个主要技巧。
一种是将 X1 边缘化(这样我们就可以将其整合到 𝒙1 )另一种是利用独立的定义,即p(𝐗1+𝐗2≤𝒙|𝐗1)= p(𝐗1+𝐗2≤𝒙)。这些技巧简化了推导过程,并根据 𝒙 得出结果。

𝐗和𝒙有什么不同?

这些是数学惯例。 𝐗 是随机的,𝒙是确定性的。例如,让我们说 𝐗 是我们从掷骰子中得到的数字。所以 𝐗 可以取{1,2,3,4,5,6}中的任意一个数。但是一旦我们滚动骰子,𝐗的值就确定了。符号 𝐗 = 𝒙 表示随机变量 𝐗 取特定值 𝒙

  • 𝐗是一个随机变量和大写字母被使用。
  • 𝒙是随机变量可以取的某个固定值。例如, 𝒙1,𝒙2,…,𝒙n 可能是随机变量 x 对应的一个样本。
  • 因此,一个累积概率 P(𝐗 ≤ 𝒙) 是指函数 𝐗 的值域t5】小于某个值 𝒙 的概率。 𝒙 可以是任意标量,如 𝐗 ≤ 1𝐗 ≤ 2.5𝐗 ≤ 888等。
  • 波浪号(~)表示“具有的概率分布”,例如 X1~EXP(λ)

现在,让我们区分 CDF 得到 PDF。

这是一个 Erlang (2,λ)分布。

Erlang 分布用在哪里?

在速率为 λ 的泊松过程中, X1+X2 将代表第二个事件发生的时间。

在我们的博客鼓掌👏例,如果你在单位时间内以 λ 的速率获得鼓掌,那么你等到看到第一个鼓掌粉丝的时间就以 λ 的速率呈指数分布。

如果你等待其他粉丝鼓掌更多的时间单位,那么你可以看到 0,1,2,…个粉丝。

然后使用 Erlang 分布来回答这个问题:

“我还要等多久才能看到 n 粉丝为我鼓掌?”

答案是独立指数分布随机变量的和,是一个 Erlang(n,λ) 分布。Erlang 分布是 Gamma 分布的一个特例。Erlang 和 Gamma 的区别在于,在 Gamma 分布中, n 可以是非整数。

锻炼🔥

a)什么分布等价于 Erlang(1,λ)?

简单。指数增长。

b)【排队论】你去了 Chipotle,和排在你前面的两个人一起排队。一个在被服务,另一个在等待。他们的服务时间 S1S2 是独立的指数随机变量,*均值为 2 分钟。(因此,*均服务速率为. 5/分钟。如果这个“速率对时间”的概念让你感到困惑,阅读这个来澄清。)

你在队列中的条件时间是 T = S1 + S2,给定系统状态 N = 2T是二郎配。

你排队等 5 分钟以上的概率有多大?

让我们把 λ = 0.5 代入我们已经导出的 CDF。

我在 Chipotle 等待超过 5 分钟的几率不到 30%,听起来不错!

爱荷华大学的博格纳博士建造了这个尔朗(伽马)分布计算器,我觉得它很有用,也很漂亮:

See the numbers are matching with our derivation!

用自然语言处理技术总结《了不起的盖茨比》

原文:https://towardsdatascience.com/summarizing-the-great-gatsby-using-natural-language-processing-9248ab8e9483?source=collection_archive---------9-----------------------

使用自然语言处理、马尔可夫链、邻接矩阵和机器学习的自动摘要介绍

如果在ᵗʰ10 个年级的英语课上有一个一致的任务,那就是写一篇《了不起的盖茨比》(TGG)的摘要(T3)。《TGG》是一部引人入胜、激动人心的文学作品。它有贯穿整部小说的中心主题——社会和阶级、财富和地位、现在和过去的主题。对于 10ᵗʰ的评分者来说,一个有说服力的简明摘要不是一件容易的事情。

在本文中,我们将使用自然语言处理(NLP)中的一些方法来总结 TGG。 NLP 是人工智能和机器学习的一个子领域,分析计算机如何处理和理解有机的交流方法(如书面语言)。虽然这些流行语可能令人生畏,但其背后的概念却并非如此。

清理和聚集 TGG

在我们做任何总结之前,我们需要实际得到这本书。我们从澳大利亚古登堡计划提供的副本开始。首先,我们需要删除停用词。停用词是像 the,and,in,for,an 等这样的词。这些单词对于创建结构良好的句子是必要的,但它们不会添加容易辨别的含义,并且会扭曲词频分析。我们将在这里使用停用词列表。其次,我们将把 TGG 分解成(键,值)对的映射。我们地图中的关键字将是完整的句子(包含停用词和所有内容)。这些值将是表示句子的干净版本的数组。

余弦相似马氏链

对于那些不熟悉图论的人来说,这非常简单。基本图有两部分:节点和边。一个节点代表一个真实世界的概念,比如人、电话号码或城市。一条是两个节点之间的连接。图形的一个常见例子是脸书。这些节点将是脸书用户。如果这两个脸书用户是朋友,则两个节点之间会有边。这里有更多关于图论的内容。

出于我们的目的,我们将把 TGG 表示为一个图形。我们每个句子都会有一个节点。两个节点之间有一条边,这条边等于它们的句子相似度(我们一会儿会讲到)。但是,在此之前,为什么这种表示是有帮助的呢?

这允许我们将 TGG 表示为一个马尔可夫链。马尔可夫链是一种概率模型,通过定义从一种状态转移到另一种状态的概率来描述一系列状态。

假设我想把我开车去的地方表示成马尔可夫链。假设我只开车往返于 4 个地方:家、工作单位、商店和健身房。对于每个可能的地点,我都有可能开车去不同的地点。下图对此进行了说明。如果节点没有连接,有 0%的概率。在下面的图表中,我从来没有在没有先回家的情况下在商店和健身房之间开车。

我们可以用这个马尔可夫链找到我在任何给定位置的*稳概率。在上图中,我很可能在任何给定的时间都在家,这很直观。这是因为有很多节点大概率指向 home。

现在,回到盖茨比身上!让我们将两个句子之间的转移概率定义为等于两个句子之间的余弦相似度。然后我们会找到马尔可夫链的*稳概率分布。具有最高固定概率的句子是在我们的图中连接得最好的节点。在下面的例子中,节点 A 可能具有最高的稳定概率。

高度连接的节点将具有高的稳定概率。这些节点应该代表一个关键主题的摘要,因为这些节点与许多其他句子最相关。但是,在我们走得太远之前,我们需要定义余弦相似度

假设我们有两个句子——“杰克和吉尔上山了”和“吉尔和杰克跑下山了”。余弦相似度将这些句子视为词的向量,并使用下面的公式测量它们的重叠。余弦相似度计算两个单词向量的点积,并将其除以每个向量的幅度的的乘积。

现在我们都准备好了。我们将用矩阵来表示我们的图形。索引 (X,Y) 处的值将是句子 X句子Y 之间的余弦相似度。该值是句子 X 和句子 Y 之间的转移概率。我们将使用这些转移概率来找到每个节点的稳定概率。

在马尔可夫链中,寻找*稳概率是相对简单的。我们可以重复地将转移概率矩阵乘以自身,直到我们达到一个稳定状态——此时所有的转移概率都收敛到一个单一值。更有效的解决方案是使用左特征向量。对这个方法感兴趣的,看这里。

现在我们有了一个稳态,我们可以寻找最高的概率。稳态概率最高的句子如下。

**"I'm Gatsby," he said suddenly.** 
--------------------------------------------------------------------
**"You two start on home, Daisy," said Tom. "In Mr. Gatsby's car."** 
--------------------------------------------------------------------
**"I told you I went there," said Gatsby.** 
--------------------------------------------------------------------
**"I want you and Daisy to come over to my house," he said, "I'd like to show her around."** 
--------------------------------------------------------------------
**She had told him that she loved him, and Tom Buchanan saw. He was astounded. His mouth opened a little and he looked at Gatsby and then back at Daisy as if he had just recognized her as some one he knew a long time ago.**

现在,数据科学最有趣的部分来了——得出我们的数据不支持的结论。下面来评价一下我们的总结。

在我们的最后一句话中,黛西告诉盖茨比她爱他,她丈夫汤姆·布坎南看到了。这句话抓住了盖茨比、黛西和汤姆之间的复杂关系。在第四句中,我们看到盖茨比想带黛西参观他的房子。他确信,如果黛西看到他现在富有而成功,她会想和他在一起。这抓住了盖茨比努力用他目前的成功掩盖他的过去,这是小说的中心主题。我们的第一句话抓住了盖茨比自我介绍的标志性时刻。我们的模特做到了!我们已经总结了了不起的盖茨比!

Credit: The Great Gatsby, Warner Brothers, 2013

从我们的分析中有一个简单的方法可以得出上面的段落。它只需要一跳,一跳,一跳。我们的数据绝不意味着上述情况。我们的方法是强有力的,我们的分析是周到的。但是我引入了很多外界的知识来得出上面的结论。

我们强调这一点并不是要减少这种方法,而是要认识到我们方法的局限性。我们可以合理地推断出盖茨比黛西汤姆是相关的角色,并且盖茨比黛西之间存在某种关系。我们当然已经找到了一些关键的想法,但我们还远远没有形成一个完整而全面的总结。

展望未来

当然,我们可以做一些事情来改进我们的方法,主要围绕句子相似性的确定。我们可以使用 TF*IDF 来查看哪些单词在一个句子中最相关,并相应地对它们进行加权。当测量余弦相似性时,我们不需要只考虑严格相等。我们可以考虑词义相*但拼写不相似的词(如 happy 和 ealthed)。如果我们想变得更强烈,我们可以使用高级主题模型,如潜在狄利克雷分配(LDA) 。

自动摘要被分为两个主要的领域— 提取方法和抽象方法。我们在这里谈论的一切都是一种提取方法。我们正试图从文本本身提取相关信息。但是没有人会写这样的摘要。人类接受概念,概括它们,考虑模式,并产生一个结果。这是一个抽象的方法。为此,我们需要计算机科学中最热门的三个词:深度神经网络

我们很快就会使用这种方法,所以请留意那篇文章。

密码

对于那些感兴趣的人来说,运行它所需的所有代码都可以在 Github repo 这里找到。有 Python 代码和 Jupyter 笔记本。清理数据和计算邻接矩阵确实需要一点时间。使用 Jupyter Notebook,您只需运行这些方法一次。方法定义和代码结构与本文类似,因此很容易理解。

感谢阅读!

疑问?评论?在andrew.oliver.medium@gmail.com给我发邮件。我很想收到你的来信!

“阳光是最好的数据消毒剂”

原文:https://towardsdatascience.com/sunlight-is-the-best-data-disinfectant-49d6fb01febc?source=collection_archive---------30-----------------------

人在回路中的机器学习专家轶事

我正在分享我的书《人在回路中的机器学习》中的第二个专家轶事。我有幸与机器学习社区的许多领导者聊过他们的经历。许多人和我分享了值得更多人关注的个人趣闻。

对于书中提到的每个领导者,有两个选择标准:

  1. 他们早期的职业是工程师或科学家。书中所有的专家都是软件工程师、物理学家、语言学家或类似的人,在他们职业生涯的早期阶段。因此,他们知道注释数据和/或构建机器学习模型是什么样的。
  2. 他们成立了一家使用机器学习的公司。因此,专家们也知道考虑推出能够影响现实世界的机器学习产品意味着什么。

对于想在数据科学领域发展的人来说,所有的领导者都是很好的榜样。

这个轶事伴随着本书的第二章,在那里,读者建立了他们的第一个人在回路系统,我强调了查看你试图建立一个机器学习模型来处理的数据的重要性。

这位专家是 SkipFlag(已被 WorkDay 收购)的前首席执行官彼得·斯科莫罗奇(Peter Skomoroch),他曾在 LinkedIn 的团队中担任首席数据科学家,发明了这个“数据科学家”的头衔:

“并非所有数据都是*等的”

你需要深入查看真实数据,才能准确知道要建立什么模型。除了高级图表和聚合统计数据,我建议数据科学家定期检查大量随机选择的粒度数据,让这些示例“冲刷你”。就像高管每周查看公司层面的图表,网络工程师查看系统日志中的统计数据一样,数据科学家应该对他们的数据及其变化有一种直觉。

当我构建 LinkedIn 的技能推荐功能时,我构建了一个简单的 web 界面,其中有一个“随机”按钮,可以显示个人推荐示例以及相应的模型输入,这样我就可以快速查看数据,并直观地了解可能最成功的算法和注释策略。这是确保您发现潜在问题并获得高质量输入数据的最佳方式,这是至关重要的:您正在照亮您的数据,阳光是最好的消毒剂。

彼得·斯科莫洛赫,《人在回路中的机器学习》,罗伯特·芒罗,曼宁出版社

The best way to explore a forest is to take as much time as possible, with sunlight shining on it. The same is true for your data.

我非常感谢 Peter 与我以及我的书和这篇文章的读者分享她的专业知识!

另一个专家摘录,见第一个,“不是所有的数据都是*等的”,作者 Jennifer Prendki:

[## “并非所有数据都是*等的”

Jennifer Prendki 的《人在回路中的机器学习专家轶事》

towardsdatascience.com](/not-all-data-is-equal-63ad1b53b086)

总是注释你自己的数据

太多的数据科学家把数据标注当成别人的问题。他们在大学里只学到了机器学习算法,当他们开始构建现实世界的机器学习系统时,他们会感到震惊,他们会发现他们将花更多的时间来管理数据,而不是构建算法。

继续类比,如果你把数据当成别人的问题,你会被蒙在鼓里。除了定期查看随机数据之外,您还应该查看那些让您当前的模型感到困惑并且与您过去所见不同的项目。

如果您担心您的模型中的真实世界偏差(您可能应该担心),那么您还应该查看根据可能有偏差的人口统计数据分层的数据样本。您可能会注意到您的模型遗漏了数据中的一些差异,因为您的模型没有优化人口统计的公*性。

我建议尽可能在您的组织中运行常规注释系统。这是一个很好的均衡器:组织中的每个人都可以参与,因为您不需要技术知识来注释数据。然后每个人都可以说他们为提高你的组织的机器学习准确性做出了贡献!

罗伯特·芒罗

2019 年 11 月

超级碗预测模型

原文:https://towardsdatascience.com/super-bowl-prediction-model-99048f366fed?source=collection_archive---------21-----------------------

根据 1966 年至 2019 年的常规赛数据预测 2019 年超级碗的冠军

NFL Super Bowl Trophy (Lombardi Trophy) image source: Wikipedia

作者:

Matthew Littman 商业分析硕士

UCI 艾迪·达姆商业分析硕士

撰稿人:韦丹克希尔萨加尔,UCI 商业分析硕士

介绍

超级碗是一项非常受欢迎的体育赛事,每年举行一次,以确定国家橄榄球联盟(NFL)的冠军球队。在二月的一个星期天,数百万球迷聚集在电视机前,庆祝这个事实上的全国性节日。超级碗在 170 多个国家播出,是世界上最受关注的体育赛事之一。以精心制作的中场表演、名人亮相和令人捧腹的商业广告为特色,增加了吸引力。经过 50 多年的存在,超级碗已经成为美国文化的传奇象征。

随着常规赛在九月开始,超级碗结束了赛季。去年 LIII 超级碗的电视转播吸引了全球约 9820 万电视观众。这使得它成为今年最流行的话题之一。出于这个原因,我们的团队决定建立一个预测模型,利用国家足球联盟官方网站 nfl.com 和其他几个网站上发布的数据来预测超级碗 LIV (54 岁)的冠军。

超级碗对美国人来说是一场盛大的庆祝派对。全球有 9820 万观众,这使得超级碗成为美国最受关注的体育赛事。各大商家为一个 30 秒的广告支付了 500 万到 550 万美元,而且价格还在竞相上涨。这些巨大的数字和对游戏的热情吸引了我们对这个项目的关注。今年也是这项美国最受欢迎的运动的 100 周年纪念。

NFL 100 year anniversary logo. image source: Wikipedia

数据汇总

我们使用了 3 个不同的网站来收集我们所有的数据:NFL.com,pro-football-reference.com 和 topendsports.com。利用 Python 中漂亮的汤包,我们开始刮。我们希望收集过去的所有数据,从 1966 年的第一届超级碗开始,一直到现在(NFL 的第 13 周)。从 NFL.com 开始,统计数据分为进攻和防守两类,进攻有 11 张表,防守有 8 张表。NFL.com,NFL 的官方网站,是我们收集历史数据的主要资源,因为他们有着广泛的数据记录和整洁。该网站的一个缺点是,它不包含每个团队的赢、输和*局记录。我们的项目需要这些重要的指标,所以我们包含了来自一个名为“职业足球参考”的网站的数据。在搜集了 1966 年以来每支球队的记录后,我们最不需要的就是知道哪些球队在过去赢得了超级碗。在收集了所有这些数据之后,我们合并了基于球队和年份的信息,以便让每一行都成为一个球队和他们所有相应的统计数据。按照年份升序排序后,我们的数据集包含 1579 行、242 列和* 40 万个数据点。它已经准备好清洗了。

Figure 1. Scraped data sources

清洁

  • 列名不直观,需要反映信息的来源。
  • 需要将包含多条信息的列分成多列。
  • 许多数据类型不正确,需要调整。
  • 重新排列各列以确保可读性。
  • 需要手动更改与其他表同名的列,以避免混淆。
  • 同时,我们用“-99999”替换了缺失的值或 NAs
  • 最重要的问题是许多列包含缺失的数据。

经过进一步的探索,很明显,某些统计数据直到某些年份才被记录下来。例如,大多数防守和踢腿的数据直到 1991 年才被记录下来。进攻线的数据直到 2009 年才被记录下来。在我们的 242 列中,有 89 列包含所有不同年份的缺失数据。

每个团队的统计数据都是特定年份中与该团队相关的独立事件。这意味着所有的计算或比较都必须在按年份分组后进行。我们还没有删除任何列,因为我们计划构建模型来只选择最重要的变量。

探索性分析

我们首先关注的是从 1966 年到 2018 年这 53 年间的超级碗冠军。图 2 显示匹兹堡钢人队和新英格兰爱国者队各以 6 胜领先,其次是旧金山 49 人队和达拉斯牛仔队,各以 5 胜领先;纽约巨人队和绿湾包装工队以 4 胜紧随其后。华盛顿红人队和丹佛野马队各有 3 胜,其次是奥克兰突击者队、迈阿密海豚队和巴尔的摩乌鸦队,各有 2 胜,排名最后的 11 支球队各有 1 胜。

Figure 2. Ranking of Super Bowl winners from 1966 to 2018

下面的图 3 显示了过去 53 年中所有球队的输赢分布。每个红圈代表一个球队的常规赛记录,没有超级碗冠军,而绿圈代表超级碗冠军。请注意,其中一些是堆叠的,因为团队可以有相同的记录。请注意,除了 1982 年的红人队,没有哪支球队赢得超级碗的胜场数少于 9 场,但由于罢工,那个赛季只有 9 场比赛。图 3 中标出了两个关键点;1972 年迈阿密海豚队和 2007 年新英格兰爱国者队。1972 年,迈阿密海豚队在常规赛中保持不败,赢得了超级碗。在令人印象深刻的赛季之后,海豚队想出了一个传统,当所有球队在整个赛季中至少输了一次时,就庆祝一下,这意味着他们将成为唯一一支不败的球队。2007 年,新英格兰爱国者队几乎打破了 35 年的传统,他们赢得了所有 16 场比赛,但不幸的是输掉了超级碗。需要注意的是,以前常规赛只有 14 场,1978 年这改成了 16 场。

Figure 3. Super Bowl wins and losses from 1966 to 2018

看触地得分统计,足球比赛中有 8 种方式可以触地得分;4 个来自进攻,4 个来自防守。如图 4 所示,在 NFL 的整个历史中,接发球和抢攻触地得分占所有触地得分的大部分,分别占总数的 55%和 36%。这是所有球队的*均值,不管超级碗的赢家还是输家。有趣的是,当看具体的超级碗冠军球队和他们的*均水*时,中心趋势是 55%和 36%左右,但范围变化很大。这让我们相信,在那些年获胜的球队正在做一些与其他人不同的事情,根据年份的不同,他们要么跑得更多,要么扔得更多。这一探索向我们表明,一个球队抢断或接球的达阵率将是超级碗冠军的重要预测因素。

Figure 4. Distribution of 8 types of touchdowns

我们看了几个区分超级碗赢家和其他人的统计数据。很自然,常规赛的胜利数是决定谁将赢得超级碗的一个重要因素。历史上,超级碗冠军*均每场比赛多 3.18 次进攻冲刺。这表明球队应该尝试更多的跑动进攻。超级碗赢家的*均传球距离也比非赢家高 0.75 码。建议球队应该把球扔得更远,以增加获胜的机会。

赢家和输家在进攻比赛数据失误方面的明显差异表明,失误是谁赢得超级碗的一个巨大差异。最后,超级碗冠军的防守传球比其他人高出 7.15 分。强大的防守导致更多的盖帽,这可能会导致更多的失误!

Table 1. Comparison of key statistics between Super Bowl winners and losers

在研究了所有数据后,由于数量庞大,很难找到所有变量之间的趋势或相关性。拥有超过 240 个统计数据,可以获得的洞察力大多是基于这项运动的先验知识。这种游戏意识有助于将我们的注意力引向这些领域。

建模

我们的数据集中需要解决的第一个问题是缺失数据。删除那些包含缺失值的列的问题是,它们中的许多捕获了游戏的非常重要的方面,这否定了我们有价值的年份的信息。用各自列的*均值填充这些值没有意义,因为有些列包含大约一半缺失值和一半现有值。这取决于 NFL 何时开始记录它们。使用*均值会严重扭曲这些列的结果,但最重要的是,团队绩效在这些年中变化很大,*均值不能反映这种变化。缺失的统计数据应该反映出团队当年的表现,这使得我们使用更先进的预测技术来填补缺失的数据。

数据插补

线性回归

第一种技术使用线性回归,其中因变量是包含缺失数据的列之一,自变量是其他列。该模型基于这些列的现有数据进行训练,因此,将根据该团队和该年的其他列来预测每个缺失的观察值。应该指出的是,对于所有的预测插补方法,数据都在每年内进行了标准化,以便在预测时调整比例问题。为了进一步提高预测准确性,对每一列都执行了一种称为递归特征消除的技术。递归特征消除(或 RFE)是一种将列数减少到仅相关列的方法。它通过获取所有列的子集来做到这一点,然后允许您分配一个决策函数来决定该子集中的哪些列是最重要的列。在我们的案例中,我们使用了逻辑回归,它基于返回那些具有最高系数的变量。这些系数衡量该变量对因变量的总体影响。在删除该子集中影响最小的列之后,通过选取不同的子集来重复该过程。它重复这个过程,直到剩下的重要列数等于用户指定的列数,在我们的例子中是 20。这意味着要预测的丢失数据的每一列都使用特定于该列的一组不同的列来进行线性预测。在预测了所有缺失的数据点之后,这些点必须与以前的数据框架重新聚合。不幸的是,在将现有值与预测值进行比较后,很明显预测结果与现有值不符,因此无法使用。

k-最*邻

在咨询了之前的统计学教授 Mohamed Abdelhamid 之后,有人建议使用K-最*邻(或 KNN)技术。这种技术将每个观察值视为其所有属性的集合,并在 n 维空间中绘制每个观察值,其中 n 是列数。对于缺失值,KNN 试图通过查找缺失值的当前观测值与其 K 个最*邻点之间的最小距离来解决这一问题,其中 K 是要查找的相邻点的数量。图 5 显示了一个例子,其中黑色值是我们希望估算的观察值。

Figure 5. KNN visual for classification in order to impute missing values.

一旦设置了相邻要素的数量,该算法会将所有相邻要素值的*均值作为您尝试替换的值。在我们的例子中,我们使用了 5 个最*的邻居。如果多个列需要估算值,就像我们的例子一样,该算法将需要替换的列从最少的值到最多的值进行排序。这种算法只有在列缺少的值越少时才会越好,因此这种排序通过首先进行最佳预测来提供帮助。这种方法在理论上非常有效,但同样不能使用,因为预测值与已经存在的值不一致。

链式方程的多重插补

之前的两种插补方法都不起作用,最后尝试了名为多重插补的链式方程(或 MICE)法。这种方法也被称为“完全条件说明”或“序贯回归多重插补”。在 Azur Melissa 关于老鼠的文章(2011)中,她解释说这种技术已经用于随机缺失的数据。我们的数据不是随机缺失的(MNAR),但是进一步的研究表明它依赖于数据集,并且其他人已经将它用于 MNAR 的数据。python 包“fancyimpute”被用于这个项目的 MICE 算法。

MICE 可以被认为是我们之前提出的线性回归方法和 KNN 算法的结合。它将每一列作为因变量,并运行回归,在这种情况下,贝叶斯岭回归。这样做是为了使用与该行相关的其他属性来预测该值。用户指定他们希望算法循环多少次,然后每个循环创建一个数据帧。具体来说,该算法工作如下:

  • 取每一列缺失的数据(89 列中的一列),对每一列运行 MICE 算法。
  • 首先用中位数填充该列的缺失数据。
  • 对第一列中缺少值每一行运行回归。
  • 使用 4 个(用户指定的数量)最*邻回归值的*均值作为该行的缺失值。
  • 填充完所有值后,检查用户指定的最大循环次数(在我们的例子中是 1000)。
  • 每个周期产生 1 个数据帧,包含该列的填充值。
  • 根据以下两个选项中先出现的一个,算法停止处理它正在处理的列:
  • 如果值已经收敛,并且没有根据用户指定的停止容差从一个周期到另一个周期发生变化,则使用该收敛值作为该行的缺失值。
  • 否则重复前面的过程,直到创建了 1000 个数据帧。
  • 如果这些值没有收敛,该算法将汇集/收集该特定行中已创建的所有 1000 个数据框的结果。
  • 基于这些值创建分布。
  • 最可能的值(分布的最高峰)用作该行的缺失值。
  • 该列的所有值现在都应该被填充,并对其余的列重复

图 6 直观地展示了该算法的工作原理。循环的数量被设置为 3,从而创建了 3 个数据帧,而不是我们示例中的最大值 1000。

Figure 6. Visual representation of MICE algorithm with cycles = 3 for one column (Stef Van Buuren, 2011)

评估这种方法的结果证明是非常有希望的。大多数值在其各自的行中都是有意义的,因为数据在输入到算法之前是标准化的,所以结果输出遵循基本的正态分布。预测值大多落在*均值左右 1 个标准偏差内或在 0.3 和 0.7 之间。

Figure 7. Shows the normal distribution of the output prediction imputations. image source: statisticshowto.datasciencecentral.com

处理不*衡数据

既然丢失的数据已经得到处理,现在是处理不*衡数据问题的时候了。过去的超级碗冠军只有 53 支,每个赛季有 32 支球队(早些年的球队更少),这导致了 1525 支球队“非冠军”和 53 支球队冠军的不*衡。由于我们总人口中只有大约 3%的人是赢家,很难有一个模型在没有干预的情况下预测这些值。这类似于将交易标记为欺诈的问题,其中大多数交易是真实的,只有少数是欺诈的。当然,预测一个超级碗冠军作为一个非超级碗冠军不会有巨大的成本,就像交易一样。这种不*衡使得建模困难。以下是处理不*衡数据的一些方法及其功效:

Table 2. Summary table of sampling methods described in original SMOTE research paper (Chawla,Bowyer,Hall,Kegelmeyer, 2002)

在研究了可能的采样方法后,无论是对少数进行过采样(不会导致更好的少数检测)还是对多数进行欠采样,或者是两者的某种组合,合成少数过采样技术(或 SMOTE)被证明是最佳选择。

SMOTE 如何工作

除了(Chawla 等人,2002)中提到的对多数采样不足之外,少数过采样方法是这种采样方法背后的真正天才之处。第一项是决定需要进行多少过采样。在我们的案例中,我们希望“赢家”和“非赢家”各占一半。SMOTE 是用 Python 中的“imblearn”包实现的。

出于示例目的,我们将对少数部分进行 200%的过采样。这意味着每个少数民族点将负责创建 2 个额外的合成点,以便将我们的少数民族数据点计数增加三倍。接下来,用户必须决定使用多少个最*邻进行生成,在(Chawla 等人,2002 年)中,他们使用了 5 个。做出这些决定后,算法会执行以下操作:

  • 选择要使用的第一个少数点。
  • 找到用户指定的 K 个最*邻(在我们的例子中是 5 个)。

(注意,这些最*的邻居只是少数邻居,而不是所有的点)

  • 在这 5 个点之间画边。
  • 检查需要执行的过采样量(如果是 500%,您将为所有 5 条边的每条边创建一个新点)
  • 因为我们的例子百分比是 200%,随机选择 5 个创建的边中的 2 个来创建新点。
  • 随机选择一个介于 0 和 1 之间的数字,该数字将确定沿已创建的边的距离。(其中 1 将位于相邻点的正上方)。
  • 对所有少数点数重复该过程,以获得开始时的三倍金额。

Figure 8. Synthetic samples visual from Kaggle sampling technique article (Rafjaa, 2017)

Table 3. SMOTE results before and after

特征选择

如上文数据插补-线性回归部分所述,递归特征消除(RFE)是一种将列数减少到最重要的列数的便捷方法。现在,缺失的数据已经被填充,不*衡的少数已经被*衡,我们进行了 RFE 筛选出谁将赢得超级碗的前 20 个最有影响力的专栏。它们如下:

Figure 9. Top 20 most impactful columns after using RFE

选择了 20 个最有影响力的专栏,所有的系数都有意义,除了进攻线统计。这些数据在 2009 年才开始被记录,因此缺少的数据最多。当这些柱子被取出时;然而,其他列的系数不再有意义。胜率变成了负数,正如我们之前在探索性分析中提到的,考虑到胜率越多,进入超级碗的可能性就越大,这显然应该是一个正系数。我们的假设是,这 3 列被用作添加的噪声,以便其他列做得更好并避免过度拟合,因此我们将它们留在我们的模型中。为了验证,我们检查了相关表,以确保变量之间没有多重共线性。虽然赢和输之间有很强的负相关性,但我们决定将这两者作为我们的模型正确运行的指标。这个相关表可以在下面找到。

Figure 10. Correlation table with 20 columns used for model

使用 RFE 后,我们回过头来在超级碗赢家和非赢家之间进行了两个样本的独立 T 检验,并选择了它标记为重要的列。我们只在模型中运行这些选定的列,并通过这些列过滤数据集,然后对 T-test 过滤结果执行 RFE。总的来说,就准确性和召回率而言,最好的方法是使用 RFE。

预测算法

我们已经修复了所有缺失的数据,我们不*衡的少数,并选择了 20 个最有影响的列,我们希望输入到预测算法中。我们选择使用逻辑回归,因为它的可解释性和易用性,尽管神经网络可能有潜力给定我们拥有的数字数据量。这有可能在未来进行探索。

我们使用了 20-80%的训练验证分割,其中我们在 1966-2018 年的 80%随机样本上进行训练,然后在另外 20%上验证我们的模型。这产生了 95%的测试准确度。

Table 4. Confusion Matrix from Logistic Regression showing actual versus predicted results

Table 5. Classification report from Logistic Regression validating accuracy, recall, and precision

非赢家的召回率为 89%,赢家的召回率为 100%,总体准确率为 95%,当赢家实际上不是赢家时,我们的模型在预测赢家方面的误差更大。它还预测 0 非赢家为赢家,这意味着我们的模型实际上更有可能说某人是赢家,而他们不是。这实际上是有利的,当考虑到一个球队在赛季中的实际预测。我们宁愿让我们的模式给更多的人一个“潜在”机会,而不是把每个人都贴上非赢家的标签。利用一个非常有前途的混淆矩阵,我们绘制了我们的 ROC 曲线,显示曲线下的面积为 95%。

Figure 11. ROC curve shows an AUC of .95

结果

预测赢家

在训练和验证之后,是时候通过尝试预测当前的 2019 赛季来测试我们的模型了。如图 12 所示,我们的模型能够根据获胜的机会对每支球队赢得超级碗的机会进行排名,最高百分比的球队位于顶部。预计旧金山 49 人队和新英格兰爱国者队分别有 96%和 76%的机会赢得超级碗。在当前的 2019 年 NFL 季后赛中,49 人队将被列入外卡名单,战绩为 10 胜 2 负。爱国者队是分区领先者之一,也有 10 胜 2 负的记录。此外,所有我们的模型给了百分之十机会的球队,都是预定进入季后赛的球队,或者有很大机会进入季后赛的球队。唯一的例外是卡罗莱纳黑豹队。

Figure 12. Winners that our model predicts vs. current NFL results

预测失败者

我们的模型不仅以惊人的准确性预测了球队成为冠军的可能性,还预测了赢得超级碗的可能性低到零的球队。如图 13 所示,我们的模型预测狮子队、红雀队、猎鹰队、巨人队、海豚队和孟加拉队没有机会赢得超级碗,考虑到他们甚至已经被淘汰出季后赛,这是有道理的。我们的模型还预测其他几个团队的机会为零,这些团队被称为“在狩猎中”。这意味着如果他们能在赛季的最后 4 场比赛中提高他们的记录,他们仍然有机会进入季后赛。我们的模型认为这些团队做不到。在图 12 中,底部的团队被剪掉以提高可视性,而在图 13 中,中间的团队被剪掉。这解释了每个图中列出的不同团队名称。

Figure 13. Losers that our model predicts vs. current eliminated NFL teams

结论

总之,为我们的模型提供最高预测准确性的最佳方法是使用 MICE、SMOTE、RFE 和逻辑回归的顺序技术。这种方法给我们的曲线下面积为 0.95,非获胜者的召回率为 0.89,获胜者的召回率为 1.00。此外,F1 的非获胜者分数为 0.94,获胜者分数为 0.95。这个统计数据代表了精确度和召回率的调和*均值

预测 2019 年超级碗冠军的一些最重要的属性是:

  1. 接受触地得分的进攻百分比
  2. 每场比赛进攻抢攻次数
  3. 每场比赛*均进攻传球码数
  4. *均防守传球码数
  5. 周转差额
  6. 防御袋
  7. 防守触地得分总数

对于未来的项目,我们希望探索利用我们的数据使用神经网络的可行性,以及利用球员统计数据、天气数据、主场比赛还是客场比赛以及球队比赛历史来预测比赛水*的比赛。

此外,我们认为受伤预测的定量方法,使预防措施成为可能,对球员和球队管理都是有益的。考虑到许多伤害是作为事故而不是退化发生的,这将是具有挑战性的,并且可能是不可能的。

使用相同的数据集,发现好的防守和好的进攻哪个对赢得超级碗更重要会很有趣。

最后,我们认为为购买/交易球员或建立梦幻足球队建立一个推荐系统,类似于网飞的高级推荐系统可能是非常有价值的。像这样的模型必须捕捉团队动态,以及什么标准构成好的团队,然后评估当前的团队,并根据团队的弱点推荐球员。

我们所有的代码都可以在

github:https://github.com/kelandrin/NFL-Superbowl-Prediction

(目前正在制作一个可以使用该代码的 web 应用程序)

相关作品/参考文献

超级碗历史

History.com 编辑。"超级碗历史"History.com,A&E 电视网,2018 年 5 月 11 日,https://www.history.com/topics/sports/super-bowl-history.

超级碗收视率

佩雷斯莎拉。"超级碗 LIII 创下流媒体记录,而电视收视率大幅下降."TechCrunch,TechCrunch,2019 年 2 月 5 日,https://TechCrunch . com/2019/02/05/super-bowl-liii-set-streaming-records-while-TV-viewership-saw-massive-drop/。

通过链式方程进行多重插补

圣乔治的德拉科斯。"处理机器学习中的缺失值:第 2 部分."中,走向数据科学 2018 年 10 月 5 日https://Towards Data Science . com/handling-missing-values-in-machine-learning-part-2-222154 B4 b 58 e

《链式方程的多重插补:它是什么?它是如何工作的?》国际精神病学研究方法杂志,美国国家医学图书馆,2011 年 3 月,https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3074241/#R8.

Buuren、S. van 和 K. Groothuis-Oudshoorn。“小鼠:r .Stef Van Buuren,2011 年 12 月 1 日,https://stefvanbuuren . name/publication/2011-01-01 _ vanbuuren 2011 a/。

合成少数过采样技术

《SMOTE:合成少数过采样技术》对 SMOTE 的看法:合成少数过采样技术,人工智能研究杂志,2002 年 6 月,https://www . Jair . org/index . PHP/Jair/article/view/10302/24590。

拉夫贾。"不*衡数据集的重采样策略."Kaggle,Kaggle,2017 年 11 月 15 日,https://www . ka ggle . com/RAF jaa/重采样-不*衡数据集策略。

递归特征消除

李,苏珊。"用 Python 一步一步地构建逻辑回归."中,走向数据科学,2019 年 2 月 27 日,https://Towards Data Science . com/building-a-logistic-regression-in-python-step-by-step-becd 4d 56 c 9 c 8

Keng,Brian 等人,深入研究数据,2014 年 12 月 20 日,https://blog . Data dive . net/selecting-good-features-part-iv-stability-selection-rfe-and-everything-side-by-side/

超级计算

原文:https://towardsdatascience.com/super-computing-168be247335b?source=collection_archive---------24-----------------------

随着我们文明的进步,对越来越强大的计算机的需求与日俱增。科技进步越来越快。计算能力的提高使这成为可能。超级计算机的功能和计算机一样强大。

什么是超级计算机?

超级计算机是高功率和高性能的计算机,用于执行非常特殊的任务,需要大量的计算。这种计算由强大的 CPU 提供,但大部分来自称为 GPU 的特殊处理设备,与 CPU 中的 4、8 或 16 个核心相比,GPU 可能由数千个核心组成。

GPU 是图形处理单元,顾名思义,它们是用来渲染图形和其他图像处理任务的。这需要大量的计算,但是大部分计算可能是重复的。GPU 广泛用于 3D 图形渲染、游戏、模拟等。

GPU 和我们正常的 CPU 有什么不同。他们在核心上是一样的(懂了!)但它们仍然非常不同。CPU 和 GPU 都旨在执行数学计算,但有些任务 GPU 比 CPU 做得更有效。

如果你有一个顺序计算,也就是说,每一步都依赖于前一步,那么 GPU 就不行,你需要一个 CPU。但是,如果你有相互独立或重复的计算,那么 GPU 会做得更好,因为 GPU 只是为了做这些而优化。

GPU 非常适合机器学习任务,因为大多数神经网络架构都是令人尴尬的并行。这意味着它们可以彼此独立运行,最终结果不会受到影响。这是 GPU 肯定能打败 CPU 的一件事。

下面是来自维基百科的 GPU 的正式定义:

一个图形处理单元 ( GPU )是一个专门的电子电路,设计用于快速操作和改变存储器,以加速帧缓冲器中图像的创建,用于输出到显示设备。GPU 用于嵌入式系统、手机、个人电脑、工作站、游戏机。现代图形处理器在处理计算机图形和图像处理方面效率很高。

如果您曾经玩过高端游戏或执行过任何计算密集型任务,如运行繁重的软件,您可能会注意到您的系统变热,并且您会听到风扇的声音变快,但为什么会这样呢?

当处理器进行计算时,它需要能量,这种能量可能会以热量的形式消耗掉,我们需要移除这些热量,否则它会损坏我们的处理器。为此,我们需要风扇和/或散热器来散热。一些游戏电脑更进一步,还包括水/油冷却系统,在冷却处理器方面效率更高。

这个问题在超级计算机上更加突出。超级计算机需要大量的能量,因此会消耗大量的热量。为了冷却这种热度,我们需要做大量的安排,这使得安装超级计算机相当困难和昂贵。

他们能做什么?

但是,当我们可以在 1000 美元的机器上同样良好地浏览时,我们为什么要使用超级计算机呢?答案很简单——它们不适合日常使用。它们的主要目的是执行我们的普通计算机甚至大型计算机组无法执行的计算。

超级计算机最重要的用途之一是为事物提供模拟模型,如根据天气数据进行天气预测或模拟药物、分子等。更多地了解它们的内部结构。

在计算机环境中,模拟可以被认为是真实世界的数学模型。但是模拟的理解和定义要复杂得多。如此复杂,以至于有些人甚至无法区分模拟和现实,因为这两个术语似乎都没有非常明确的定义。因此,许多人认为我们可能生活在一个模拟世界中,很可能是由某个高级文明所运行的。一些人还认为,如果有足够的计算能力,你可以模拟整个宇宙。

模拟非常有用,因为我们可以在模拟中做一些在现实生活中可能做不到的事情,比如改变一些条件/变量,并测量它们的影响。例如,爱德华·洛伦茨发现,即使是自然条件的微小变化也可能对天气产生巨大影响。这种现象被称为蝴蝶效应。他的理论为“混沌理论奠定了基础。

模拟分子需要大量的计算能力,因为粒子之间的相互作用数量巨大,数学建模相当费力。但是,如果我们能做到这一点,我们应该能够模拟分子的组合,并找出它们是否对某些疾病有效。这可以彻底改变医疗行业和药物的生产方式。尽管超级计算机功能强大,但这仍然是不可能的。我们需要被称为量子计算机的不同种类的计算机来做这件事。

我们还可以使用超级计算机进行流体模拟,模拟宇宙中的一些事件,或者根据从遥远的星系获得的数据重建一幅可能发生的画面。

超级计算机今天被广泛应用,如模拟量子计算机以检查量子计算机给出的答案是否正确,预测地震,模拟黑洞,模拟蛋白质折叠,模拟人脑等。

这场比赛

但是,我们如何比较哪台超级计算机更好,即哪台具有更高的计算能力?为了测量超级计算机的能力,我们使用 FLOPS 或每秒浮点运算。

例如,现代超级计算机的性能是以 petaflops 来衡量的,我们普通的计算机可以执行 gigaflops。超级计算机在 80 年代也是这个速度。因此,超级计算机不是用绝对术语定义的,而是用相对术语定义的,即当时最强大的计算机。

计算能力越来越成为权力的象征。例如,挖掘比特币等加密货币需要巨大的计算能力。如果你有这种能力,你可能什么都不做就能赚几百万。如果有足够的计算能力,你也许能够破解加密或者攻击另一个国家的军队。因此,计算能力在现实世界中变得越来越强大,谁拥有大量的计算能力,谁就一定有优势。

这导致各国建造自己的越来越强大的超级计算机(当然是为了有用的目的),人们不断比较它们,看看哪个国家在这场竞赛中领先。Top500 是一个列出并排列世界上 500 个最强大的非分布式计算机系统的项目。

超级计算机也可能表明一个国家实力的增强。例如,在 2005 年,中国没有超级计算机进入 500 强,但今天他们有一些最快的超级计算机,不仅如此,他们有 200 多台超级计算机进入 500 强,这也是任何国家拥有的最高水*。

摘要

计算机从机械计算器到机电设备再到我们今天知道的电子计算机的发展方式令我着迷。这些不可思议的机器背后的进化和丰富的历史令人着迷,并促使我们相信看似未来和不可能的事情可能是可能的。超级计算机是计算机能力的一个极端例子。

在这篇博客中,我们深入研究了超级计算机。我们看了超级计算机的构建模块,GPU 以及超级计算机可以用来做什么,特别是模拟。然后,我们看到了如何进行一场竞赛,以积聚尽可能多的计算能力。

计算的未来看起来令人兴奋,不同种类的材料,从水到碳到用于计算的 DNA,以及应用于计算的各种方法,如量子力学的使用。不同研究和计算分支的结合似乎为各种令人兴奋的应用铺*了道路。

使用 Python 中的 fastText 实现句子嵌入的超级简单的方法

原文:https://towardsdatascience.com/super-easy-way-to-get-sentence-embedding-using-fasttext-in-python-a70f34ac5b7c?source=collection_archive---------15-----------------------

Photo by Patrick Tomasso on Unsplash

通过 tofunlp/sister 获得单词嵌入的超级简单的方法。

当您在使用包含一些 NLP 技术的应用程序时,通常会希望文本数据中嵌入单词。这样你就可以做各种各样的事情,比如计算句子的距离,分类或者很酷的可视化。

但是下载预先训练好的单词嵌入(例如, word2vec , fastText )并以某种方式加载它们通常需要一些时间。而且这些过程不是很有趣(至少对我来说),也不容易管理和保持这些代码的整洁。

所以在本文中,我要介绍一个小 python 库,命名为姐姐(简单句嵌入器)。(是的,我喜欢给我的项目取奇怪的名字)。这个 pip 可安装的库允许你做两件事,1)下载预先训练的单词嵌入,2)提供一个简单的界面来使用它嵌入你的文本。作为一个额外的功能,因为我写这个库是为了易于扩展,所以支持新的语言或算法来嵌入文本应该是简单和容易的。

现在,让我告诉你它有多容易使用。只需 4 行代码就可以完成。

看到了吗?非常容易。

你不需要做任何下载或构建,当你第一次使用 MeanEmbedding 时,它会自动下载预先训练好的Facebook research/fast textvector。

目前,该库仅支持英语和日语。不过,由于实现是可扩展的,只需在这里的给预先训练好的向量添加 URL,就可以轻松添加自己喜欢的语言。或者您可以为请求创建一个问题,以便我可以添加它。

下面展示了 MeanEmbedding 创建句子向量的方式,这是一个非常简单但也非常有效的方法(参考:我最喜欢的论文之一)。

How it gets sentence vector from sequence of words.

正如您在上图中看到的,它首先将所有给定的单词转换成单词嵌入,然后获取它们在元素方面的含义。因此,句子向量的大小与每个单词嵌入的大小相同(在前面的示例代码中为 300-dim)。

在本文中,我们介绍了如何使用单词嵌入来获得句子嵌入。希望你喜欢,自己嵌入一堆句子!

Pytorch 闪电的 36 种方式可以增强你的人工智能研究

原文:https://towardsdatascience.com/supercharge-your-ai-research-with-pytorch-lightning-337948a99eec?source=collection_archive---------14-----------------------

Come at me AGI

AGI 不会自己解决问题(在内心深处你知道我们是另一个人工智能的 AGI🤯).

但是让我们假设它做到了…

想象一下,翻开你的笔记本电脑,你会发现一个为你编写的这样的算法。

def AGI(data):data = clean(data)agi = magic(data)return agi

嗯好的🤔。让我们看看这是怎么回事。你说服你的研究小组你需要对此进行一些试验。

但是 obvs 这不会像写的那样运行。首先,我们需要一个训练循环:

for epoch in range(10):for batch in data:agi = AGI(batch)agi.backward()...

好了,现在我们算是训练了。但是我们仍然需要添加一个验证循环…

def validate(dataset):# more magic

毒品。但是 LOL AGI 在一个 CPU 上?

你想得美。

让我们在多个 GPU 上运行这个…但是等等,你也已经读到过16 位可以加速你的训练。天哪,但是有 3 种方法可以进行 GPU 分布式训练。

所以你花了一周的时间编写代码。但是仍然很慢,所以您决定使用计算集群。现在事情变得有点复杂了。

Sad times

与此同时,你的 AGI 有一个 bug,但你不确定这是你的 GPU 分配代码,还是你如何加载你的数据,或者其他任何你可能编码错误的事情。

你决定你不太想处理所有的训练细节,你尝试 Keras,但是它不能让你很好地实现 AGI 函数,因为你需要对训练有更多的控制。Fast.ai 也是不可能的,因为这不是现成的算法。

好吧,那太糟糕了,现在你已经自己编码了…

没有。

Pytorch 闪电

How you feel when running a single model on 200 GPUs

Pytorch Lightning 已经为你编写了所有这些代码,包括测试到保证程序的那部分没有错误。

这意味着你可以专注于研究的核心,而不必担心所有繁琐的工程细节,如果你不必专注于核心研究理念,处理这些细节会很有趣。

这里有一个清晰的图表,显示了什么是自动化的。灰色部分是自动化的,通过教练旗控制。你可以使用你想要的任何底层模型(你自己的、预训练的东西、fast.ai 架构等等),将蓝色部分定义为你想要的任意复杂。

You own the blue. Lightning owns the rest.

闪电模型

Lightning 的核心是两件事,一个 LightningModel,一个 Trainer。LightningModel 是你 90%的时间花在这里的地方。

Lightning Module Template

请注意,您正在定义培训循环中发生的事情

for epoch in range(10):for batch in data:# training_step above is what happens here# lightning handles the rest (backward, gradient clip, etc...)

验证也是一样

for val_batch in data:# validation_step above is what happens here# with no grad, eval, etc... all handled for you automatically

上面这两个函数会变得非常复杂。事实上,您可以在这两个函数中定义一个完整的 transformer,seq-2-seq,fairseq 模型。

培训师

培训师处理您不想编码的东西的所有核心逻辑,但是您需要保证它被正确地完成并且使用最新的最佳实践。

只需设置几个标志,你就可以在 CPU、多 GPU或多节点集群上训练你的 AGI。不仅如此,您还可以启用渐变裁剪、累积渐变、 16 位精度、自动聚类保存、超参数快照、张量板可视化等

你明白了。

你不仅可以获得训练人工智能系统的最新和最棒的技巧,还可以保证它们能够正常工作并且经过正确的测试。

这意味着你只需要担心你的部分——新算法——是否正确。如何加载数据以及在培训的核心部分做些什么由你决定。

那么,Pytorch 闪电的 36 种帮助方式呢?大约有 36 个你通常自己实现的东西可能会有 bug。Lightning 会做并测试它,所以您不必这样做!

点击这里查看完整列表

恭喜你。你可以利用刚刚回来的所有空闲时间来完成你正在做的兼职项目(可能是你小狗的聊天机器人,或者是优步的瑜伽裤)。

利用 PowerBI 为创业分析提供超强的 Excel

原文:https://towardsdatascience.com/supercharged-excel-for-startup-analytics-with-powerbi-46a15c436eba?source=collection_archive---------18-----------------------

如何将 Excel 用作数据分析师而不是数据猴子

Excel 似乎是我遇到过的最讨厌的工具。这是一个遗憾,因为如果你忽略这个坏名声,它是你腰带上最好的分析工具之一。

根据我的经验,Excel 有两个用途:高级报告和数据分析。

高层次的报告正在把握你的业务脉搏。您可以在文章【insight 的启动报告模板中查看更多详细信息。它不是那种有数百个 KPI(关键绩效指标)和多达一百页、只有少数人阅读、没有人采取行动的每日报告。对于这些,任何商业智能报告都可以。高水*的报告是你想看的那种报告,因为它讲述了一个重要的故事(企业如何运作,为什么会这样,你应该另找工作吗?).即使大多数网飞的决定是基于分析,它有助于增加一点工艺。对于这样的报告,可能只是在图表中添加一个标签,以记住某个特定产品由于库存问题正在下降,或者通知下降位于特定区域。数字很好,但有一点解释会有所帮助。

对于高级报告来说,Excel 很好,因为它让您自动完成大部分工作,同时让您添加最后的润色。

数据分析使商业人士能够理解高层报告下发生的事情。它在构建一个你是英雄的故事。销售数字下降,没有人知道为什么,找到罪魁祸首夏洛克。

Excel 给你提供了很棒的数据透视表,到处添加了一些公式,很好的单元格条件格式。您可能更喜欢使用代码(SQL、Python 或其他什么)进行干净的处理,但要突出显示数据中的内容,Excel 是最好的。

1-将数据、计算和呈现分开,以保持理智

你的 Excel 表格反映了你的精神状态。可以干净,也可以混乱。不要让它是后者。

受 webapps 的模型-视图-控制器的启发,我把我的电子表格分成三种标签。

第一类是演示表,它将仪表板和分析表重新组合在一起。仪表板显然是整洁的部分(你在启动报告文章中看到的部分)。我还添加了一个分析表,在那里我放了一个大的动态交叉表,如果仪表板部件中的某些东西需要更仔细的检查,用户可以在那里更深入地挖掘。

第二种是数据层。在这些表中(每个数据源一个表),有数据并且只有原始数据。没有公式。我给它们贴上数据标签,并总是把它们标为黄色。

最后一种表是计算表。这是我放置业务逻辑(以及所有那些 Excel 公式)的地方。这些被标记为隐藏和灰色,因为没有用户应该去那里(他们大部分时间是隐藏的)。

这种简单的关注点分离会让你内心*静。如果有问题,你知道你应该首先检查相关的数据表,然后,如果错误不存在,相关的隐藏表。你应该有一个简单的数据血统。

在下一步中,我们将看到如何自动更新数据层。

2 —数据连接是自动化的关键—停止复制/粘贴

人们讨厌 Excel 的一个原因是,大多数人最终会花费数小时复制/粘贴。事实上,没有一个 Excel 报表需要点击一次才能刷新。

让我们假设您有一个 Postgresql 作为数据集市,它每天晚上都会转储一些生产数据(可以是一个共享目录,但数据库更有效)。使用右 ODBC 驱动(Excel 理解的常用中间件),可以直接从 Excel 中读取数据库。您可以选择一个表,甚至可以编写一个合适的 SQL 查询。这个不错的工具在 Get Data->From Other Sources->From ODBC(From Database 应该是从微软数据库中读取的)。

只需按下 Load,数据将从数据库中加载。好的方面是它将打开一个查询面板,您可以在其中随意刷新数据(注意:数据面板中的 Refresh All 按钮也可以工作)。

因此,我们只需点击几下鼠标,就能看到带有条件格式的数据透视表,在那里,您可以很容易地发现 2 月份存在季节性效应,2013 年 7 月开始会有大幅提升。

使用这样的工具,您可以轻松创建一个高级报告,就像我们为 Brewnation 所做的那样。请记住为每个数据连接创建一张表,一张或多张用于计算,一张用于演示。

说到计算,使用 Excel 公式会很痛苦并且容易出错。好消息,有了 PowerBI 有了更好的方法。

3 — PowerBI for Excel 是获得超能力的关键

Excel 的超能力还有一层。被微软巧妙隐藏。我称之为 PowerBI for Excel,但 PowerBI 现在是一个独立的产品线,采用不同的方法(但核心是相同的)。在过去,它被称为权力中枢和权力查询,但它早已不复存在。在那些日子里,这只是 Excel 很少有人知道一个功能。

在上一节中,我们建立了 Excel 和数据源之间的链接。让我们将这些数据加载到 PowerBI 引擎中,而不是加载到工作表中。使用“加载到”打开“导入数据”对话框,而不是“加载”按钮。在这里,我们将创建连接并将数据添加到数据模型中。

数据模型是 PowerBI 的存储部分。您不再受限于 Excel 的一百万行。这种列压缩存储也非常擅长于只占用很小的空间。

要显示此数据模型中的内容,请使用数据功能区中的“管理数据模型”按钮。

可以通过添加新的计算列和聚合度量来增强整个模型。事实上,您的大部分计算层都可以放入 PowerBI 引擎。

如你所见,一旦你知道如何使用它,Excel 真的很强大。它是主流的分析工具。

原载于 2019 年 5 月 10 日【https://dataintoresults.com

超级 Jupyter 笔记本

原文:https://towardsdatascience.com/supercharging-jupyter-notebooks-e22f5ad7ca18?source=collection_archive---------8-----------------------

Jupyter 笔记本目前是全世界 Pythonistas 最热门的编程环境,尤其是那些对机器学习和数据科学感兴趣的人。几个月前,当我开始认真研究机器学习时,我发现了 Jupyter 笔记本。最初,我只是惊讶,喜欢我的浏览器里面的一切。然而,我很快就失望了,发现 stock Jupyter 笔记本界面非常简单,缺少几个有用的功能。那时,我决定去寻找一些 Jupyter 笔记本电脑黑客。

在这篇文章中,我介绍了几个 jupyter 笔记本插件/扩展和几个 Jupyter 命令,它们将增强您的 Jupyter 笔记本并提高您的工作效率。简而言之,为你的 Jupyter 笔记本充能。

一旦您按照下面的说明操作,您的 Jupyter 笔记本将拥有以下出色的功能(如果您愿意,还可以有更多功能):

  1. 能够在多个 Conda 环境之间动态切换,无需重启 Jupyter 笔记本。
  2. 1-click 可点击目录代(你会喜欢这个的!)
  3. 一个超级有用的弹出便笺本(我最喜欢的功能!),您可以在那里试验和测试您的代码,而无需更改主笔记本中的任何内容。
  4. 代码单元内的代码折叠。我想知道为什么 Jupyter 笔记本没有这个功能。
  5. 1-click 代码单元格隐藏,这是您通过可视化讲述数据故事时的一个重要功能…人们通常对你的图表感兴趣,而不是代码!
  6. 一个超级酷的变量检查员!
  7. 用于降价单元格的拼写检查器
  8. 那些深夜的编码会议。
  9. 一个代码片段菜单,用于添加常用的 python 构造,比如动态的列表理解
  10. 最后,绝对最棒的功能, 舒缓美丽的午夜蓝配色拯救你的眼睛

是时候充能了!

首先,我们将确保我们的笔记本有一个很好的黑色主题,可以舒缓眼睛。如果你每天长时间工作,白色的背景会让你的眼睛出血。无论如何,一旦你陷入黑暗,你就再也无法切换回来😉

使用以下命令安装黑暗主题,

# Kill and exit the Notebook server
# Make sure you are in the base conda environment
conda activate base# install jupyterthemes
pip install jupyterthemes# upgrade to latest version
pip install --upgrade jupyterthemes

一旦软件包被安装和升级,运行下面的命令,把你的股票白色主题 Jupyter 笔记本变成可爱的深蓝色午夜主题。你的眼睛会因此爱上你的。

# Enable Dark Mode
jt -t onedork -fs 95 -altp -tfs 11 -nfs 115 -cellw 88% -T

接下来,让我们看看是否可以将在 Anaconda 中创建的所有自定义环境作为内核添加到 Jupyter 笔记本中。这将确保我们可以通过简单地在内核菜单中选择它们来切换环境。切换内核时无需重启笔记本。

假设您已经在 Anaconda 中创建了两个定制环境, my_NLP,gym 。要将这些添加到您的 Jupyter 笔记本中,请按照以下步骤操作,

# Stop and exit your Jupyter Notebook server first
# Activate your environment in the terminal 
conda activate my_NLP
# Install the IPython Kernel 
pip install ipykernel
# Link your environment with Jupyter 
python -m ipykernel install --user --name=my_NLP# Repeat steps for the other environment, gym. 
conda activate gym
pip install ipykernel 
python -m ipykernel install --user --name=gym

现在打开你的 Jupyter 笔记本,进入内核菜单中的改变内核选项,然后…嘣!你应该可以看到所有的内核都列在那里,你现在可以通过点击它们来激活它们。

This is where the newly added Kernels should show up. Notice the soothing midnight blue theme.

对于我上面提到的所有其他酷功能,我们需要安装一个叫做nb extensions for Jupyter Notebooks的东西。安装 nbextensions 很容易,只需按照以下步骤操作,

# Stop and exit your Jupyter Notebook server 
# Make sure you are in the base environment
conda activate base# Install the nbextensions 
pip install jupyter_contrib_nbextensions
# Install the necessary JS and CSS files 
jupyter contrib nbextension install --system

启动 Jupyter 笔记本服务器,您应该会在开始页面看到第四个选项,名为 Nbextensions 。点击它,查看您一直想要的 Jupyter 笔记本电脑的强大功能。

The Nbextensions tab!

正如你在上面看到的,扩展列表非常庞大,甚至乍一看有点吓人。不是所有的都有用,这里是我用的一些,

  1. 目录(2) — 只需点击一下鼠标,即可为整个笔记本生成一个目录,其中包含指向各个部分的超链接。
  2. Scratchpad — 在我看来绝对是最好的扩展。一个单独的空间,让你在不干扰笔记本其他部分的情况下试验代码。
  3. 代码折叠— 这里不需要任何解释。
  4. 隐藏所有输入— 隐藏所有代码单元格,同时保持输出和降价单元格可见。如果你试图向非技术人员解释你的结果,这是一个非常有用的功能。
  5. 变量检查器— 将您从调试中解救出来,类似于 Spyder IDE 中的变量检查器窗口。
  6. 拼写检查器— 对减价单元格中的内容进行拼写检查。
  7. Zenmode — 去除屏幕上多余的杂乱,这样你就可以专注于重要的东西,即代码。
  8. 代码片段菜单— 一个很酷的常用代码片段的集合,从列表理解到熊猫以及任何介于两者之间的东西。最棒的部分?您可以修改小部件并添加您的自定义片段。

上面的列表包含了我最常用的扩展,但是我们鼓励您尝试其他的扩展。有意思的有 ScrollDown、**table _ beautiier、腹地。

The Snippets extension in action along with the Table of Contents generation extension at work.

The Scratchpad extension

请告诉我您对 Jupyter 笔记本电脑的这些增强功能有何看法。如果您在安装扩展时遇到任何错误,请随时发表评论。

编辑:

  1. 如果您的系统上没有安装 Anaconda,只需忽略包含 conda 的命令。此外,忽略我们讨论将 Anaconda 环境添加到 Jupyter 笔记本的部分。
  2. 您可能需要管理员权限才能在您的系统上安装所有这些扩展。
  3. 如果你不喜欢笔记本上的午夜蓝主题,只需在终端中执行 jt -r 即可将一切恢复正常。你将不得不重启你的 Jupyter 笔记本,你也可能不得不清除你的浏览器缓存,以防重启后你仍然看到午夜蓝主题。

超创造力

原文:https://towardsdatascience.com/supercreativity-b4114ebd0357?source=collection_archive---------7-----------------------

Opal Butterfly VR, courtesy of Pamela Davis Kivelson

人工智能可能很快会超越人类的艺术创造力

塞拉菲姆 塞奥多罗斯

总结。我们对艺术的体验——绘画、音乐、雕塑、诗歌——触及多种感官、联想、记忆和情感,并涉及人们可能称之为意识的部分。今天的人工智能(AI)缺乏主观经验和多模态,但开始获得艺术创造力。创造力需要意识体验的能力吗?我们断言答案是否定的。专业化的人工智能可能很快就会变得比人类更具创造力,更擅长捕捉和表现集体经验,因为多模态、监督学习和与人类的合作将显著增强今天的创意机器人。许多艺术是关于识别和操纵复杂的感觉模式和联想,这是人工智能擅长的任务;因此,超创造力——远远超过人类能力的创造性过程和结果——可能就在眼前。

“哦,这是毫无疑问的。是的,是的,一百万次是的。创意简单;意识,智力,那些都很难。”大卫·柯普

AI generated work based on Napoleon Crossing the Alps. By u/vic8760 in Reddit.

我们对艺术的体验包含多种感官、联想、记忆和情感。它利用了有意识和无意识的过程。想象一下听你最喜欢的音乐:每一个旋律主题、和声延续和节奏都与不同的情绪有微妙的联系,如兴奋、宁静、怀旧、嬉戏等等。音乐激发的图像、场景或思想流在你的脑海中跳跃。与历史事件和文化参考的关系可能跃入脑海。音乐具有很强的暗示性,并能改变伴随体验的情感诠释。电影制作人很清楚这一点,并使用合适的配乐来操纵你对每个场景的情绪反应。同样,绘画、雕塑、故事和诗歌会引发情感、记忆和其他感官联想。公*地说,不能引发多感官情感体验和丰富联想的艺术不是好艺术。

尚不清楚的是,人类水*的体验艺术的能力在多大程度上需要创造艺术。尽管缺乏像人类一样体验艺术和现实的能力,人工智能能创造出与人类作曲家或画家一样的艺术吗?越来越多的经验证据,特别是在绘画和音乐领域,表明艺术创造力可能不需要主观经验的能力,而是可以通过人工智能从人类创造的艺术和反馈中学习。我们相信,随着人工智能在模式和关联学习方面变得更好,随着它从人们那里获得更多反馈,它将创造出能够引发越来越丰富的多感官和情感人类 体验日益复杂的关联的艺术:也就是说,越来越好的艺术,可能超越人类创造的艺术。

艺术创意可能不需要主观经验的能力

科技一直使人类的创造力得以发挥:将史前洞穴中用原始工具制作的画与几个世纪后用画笔和丰富色彩制作的画进行比较,或者考虑钢琴的发明或电影的发展,被称为“第七艺术”。人类和机器之间的合作即将成为艺术领域的下一次技术飞跃,并创造出我们从未体验过的艺术品。

人工智能与今日艺术

深度学习的应用已经产生了不可否认的艺术质量的绘画,要么是模仿人类画家的风格——通过卷积神经网络的风格转移将与大师风格相关的模式编码为低级笔触,一直到空间感知和构图——要么是原创作品——其中生成对抗网络(GANs) 生成写实绘画,如肖像或抽象裸体。第一幅被拍卖的人工智能画作,使用最初由 19 岁的斯坦福大学研究员 Robbie Barrat 在佳士得拍出了 432,500 美元。Barrat 和 Mario Klingemann 这样的艺术家仍然做出大多数创造性的选择,如策展输入、训练人工智能和选择最佳结果艺术。然而,基于人工智能的艺术往往很难与人类艺术区分开来,越来越独立的人工智能画家可能即将出现。

The Butcher’s Son, winner of the Lumen Prize, 2018, Mario Klingemann

在音乐方面,作曲家、UCSC 大学音乐教授大卫·柯普的开创性工作远远早于现代深度学习。自 1981 年以来,Cope 一直致力于在算法中提取音乐作品的精髓,这些算法被输入给特定作曲家的音乐,解构它,识别模式,并在相同风格的新作品中重新组合这些模式。他的第一个重大成功是《艾美奖》(EMI,音乐智力实验,如尤瓦尔·赫拉利的《德乌斯人》中所讨论的)产生了巴赫、、维瓦尔第、肖邦等风格的令人信服的音乐,而早在 1997 年就愚弄了现场观众。最*,索尼的流动机器产生了高度可听的歌曲(例如,听听爸爸的车、影子先生或一个 Mon Sujet——你能说出它们是由人工智能产生的吗?),而初创公司 Aiva 和 Amper 开发深度学习方法来按需生成音乐,并可能很快实现个性化音乐。在不久的将来,即使人类音乐家围绕某些歌词创作主要的音乐主题和歌曲进展,伴奏的整个配器和创作也是一个充满挑战和艰巨的过程,很可能由 AI 接管。随着我们学习如何更好地设计这种人机合作,我们可能会提高人类和人工智能的创造力。

即使没有人类的经验,诗歌也是可能的:已经出现了产生巧妙俳句的机器人,因为诗歌的质量部分来自语言的美和节奏——这可能是可以学习的——部分来自读者赋予它的意义,诗歌机器人早在 2010 年就已经愚弄了文学期刊。如果你认为你能从机器人诗歌中分辨出人类,欢迎你在机器人或中挑战自己。

除了音乐、绘画和诗歌,人工智能在许多其他艺术形式和创造性任务中的应用以及用于产生艺术的人工智能工具开始出现。麻省理工学院的一个创新团队将展示人类和人工智能之间的合作可以产生新的艺术和手工艺人类独自无法想象:音乐、产品和产品设计、时尚、香水、巧克力松露、珠宝、鸡尾酒和戏剧。斯坦福大学讲师兼沃尔沃集团驻校艺术家 Pamela Davis Kivelson 创新性地将包括摄影、人工智能风格转移绘画、肖像视频甚至人工智能诗歌在内的艺术形式与硅谷正在开展的活动的技术主题相结合。她说,“人工智能艺术让我能够[[……]]创造一种基于 NLI 或‘非线性身份’的新颖视觉语言。[[……]]一个物理学家实际上可以被描述成费米液体中的一组电子,或者是量子隧道,或者是一个量子比特。我想重新设想这幅画像——挑战我们集体的无意识偏见和推论。这些隐藏的偏见影响着我们的行为。

通往超级创造力的道路

在斯坦尼斯拉夫·莱姆(Stanislav Lem)1965 年的科幻小说《赛博亚》(Cyberiad)中,“构造者”特鲁尔(Trurl)着手开发一台诗歌机器,并意识到诗人的心灵包含了诗人文明和文化的所有经验。为了将所有这些编程到机器中,Trurl 建造了一台超级计算机,可以模拟整个宇宙的进化,一直到诗人的出生和文化教养。他由此产生的人工智能诗人是天才;人类诗人首先不理会它,但最终却因为失去了生活的主要目标而集体自杀。Trurl 的人工创造的工程化道路有些不切实际;新兴的实践路径避开而不是复制人类的创造过程。

那么,假设人工通用智能还在遥远的未来,专业化的 AI 能变得有多有创造力呢?沿着三条尚未探索的道路,专业人工智能还有很大的改进空间:训练、多模态和人-人工智能合作。

“We made our own artificial intelligence art and so can you”, WIRED magazine, Tom Simonite

持续的反馈和培训。迄今为止,人工智能在绘画和音乐方面的进步还没有利用太多的人类反馈。相比之下,作为一个人类艺术家体验艺术,她是一个即时的——尽管有偏见的——对其作品的批评家。机器可能没有自己的主观经验来指导它们,但它们可以通过人类生成的训练数据和反馈来利用人类的经验——例如,随着乐谱或绘画草图的进展,通过评级或点击“心”(以潜望镜的风格)。来自许多艺术家——或艺术评论家,或普通大众——的反馈可能比一位艺术家的主观体验更好。此外,这样的反馈过程可能会产生新的艺术风格、社区和前卫作品。

多模态和联想学习。当我们听自己喜欢的音乐或沉浸在一幅画中时,我们经历的是复杂的多模态感觉和联想,这将我们提升到一个由图像、记忆、解释、分析思维、历史和文化联系以及感官运动体验组成的精神世界,我们将这些都归功于最高形式的艺术。

“画是看到的而不是感受到的诗,诗是感受到的而不是看到的画。”达芬奇

人工智能能创造出具有“规模和亲密度、增强的[…]色彩和感官客观性”的音乐吗?它能像音乐家、画家、雕塑家、歌词作者、诗人和作家莱拉·奥尔巴赫一样,以相互影响的方式创作音乐、绘画、诗歌和文学吗?我们如何教授人工智能协会跨越形态,艺术形式,事件和社会趋势?

大量的训练数据已经存在:有配乐的电影、有歌词的歌曲、绘画评论、音乐专辑、电影和表演。作为补充,众包活动可以设计成大规模的多模态关联标签。看书时挑选音轨,听音乐时浏览 wordnets,选择与给定曲调最匹配的图像,听音乐或观看绘画时回忆事件,将当前或过去的事件或新闻文章与特定的艺术作品相链接。由此产生的概念网络可以是高度个性化的,并且反映了具有重要历史价值的文化和世代关联——很像艺术家的作品。这种网络还将具有巨大的商业价值——例如,音乐制作人可以根据流行的网飞系列开发音乐,产品设计师可以根据热门趋势和文化开发创新。

通过大规模训练和多模态关联地图,人工智能还可以学会准确预测人类对艺术的感官和情感反应,并在创造音乐、绘画、诗歌和多模态体验的沉浸式作品方面远远超过人类的能力。

Study of Quantum Materials, artist Pamela Davis Kivelson; scientific imagery courtesy of Robert Cava

人机协作。当部署大规模培训和多模态联想学习时,迄今为止在人-AI 艺术合作方面的开创性工作将得到扩展。众包音乐可能涉及艺术家创作一个基本曲调,人工智能根据在线反馈对其进行改进和编排。同时,学习的多模态地图可以通过艺术形式和体验被例如推荐伴随图像的人遍历,并且这些图像反过来影响乐谱的发展。类似的反馈回路可以让人们与几乎任何艺术形式的人工智能进行合作——甚至是文学,因为人工智能正在迅速获得产生类似人类文本的能力。

人类和机器之间的新协作流程有望催化新人工智能能力的发展,并最终促进人类和机器的创造力。Kivelson 设想了一个未来,在这个未来中,集体创造性的人工智能扩展了我们的全球联系,重新定义了工作室实践的性质,同时挑战身份政治,并扩展了我们对新思想的自由和开放的访问。

人工智能生成的艺术可能成为社会最有效的镜子,有可能重新定义我们的身份概念

此外,就像人类艺术经常从其历史和社会背景中获得价值一样,人工智能生成的艺术可以结合来自人群、其他艺术品和背景信息的输入,并有可能成为社会最有效的镜子,捕捉我们的集体经历,并有可能重新定义我们的身份概念。

最后,人工智能可以超越人性对创造力的限制。考虑一首赋格曲。约翰·塞巴斯蒂安·巴赫的《音乐祭》中的六声部乐曲号称是有史以来最好的作品,并且是一首极其复杂的作品。为什么用六种以上的声部创作一首音乐效果很好的赋格曲很有挑战性?人类作曲家在身体上受到限制,只能用十个手指来弹奏键盘,一个工作记忆最多只能容纳四到七个独立的项目。人类画家、雕塑家和诗人同样受到限制。机器没有这样的限制,因此可能会将艺术的界限推到人类无法企及的地方。

Faceless Portrait #1, Artrendex Inc.

意识体验对模仿

当我们享受艺术时,我们参与了当今人工智能中所缺乏的神经机制:一个连接我们大脑和神经内分泌系统的复杂情感系统,该系统释放控制我们感觉和行为的激素;物理感觉绑定,如鸡皮疙瘩、欣快、心跳和呼吸的变化;对个人经历或历史事件的记忆,是感官和概念联想的桥梁。许多人认为艺术需要体现。Kivelson 说"舞者在身体的特定部位感受运动。当我们看他们跳舞时,我们感觉到他们发自内心地表达情感[[……]],随着我们集体体现的创造性智能的发展,使用人工智能艺术的新形式的创造力将会出现。

把意识的难题留到将来讨论,没有这个体现机制,今天的人工智能完全缺乏我们对艺术的主观体验,即使它获得了创造力。从本质上来说,创造力正在从为创作过程提供反馈所需的意识中分离出来 : Trurl 的人工智能诗人通过吸收人类的艺术作品和反馈,将意识体验外包给人类。它挖掘了人类的集体意识。

此外,不久的将来,计算艺术家将创造艺术,以便优化预先指定的功能,如体验者的沉浸水*,而不是为了满足表达其内心世界的(不存在的)愿望。人工智能的创作动力将与人类艺术家完全不同。这指出了有意识的经验驱动的创造力和模仿之间的明显区别。很像动物拟态,AI 将学习引发人类期望的感官-情感反应的模式,而无需获得化身和有意识的主观经验。

Inverse collage, courtesy of Mario Klingemann

我们能否设计一种测试——对抗过程——来区分人类创作的艺术和计算机创作的艺术?如果人工智能完全通过这样一个类似图灵的测试,那么无意识人工智能对人类艺术家的完美模仿是可能的,创造力不需要经验和感觉的能力。

创造性人工智能将成为一种强大的工具——一种新的显微镜——用于对人类的创造力和沉浸式体验进行定量测量

创造性人工智能将成为一种强大的工具——一种新的显微镜——用于对人类的创造力和沉浸式体验进行量化测量。它可以帮助我们回答一些难以捉摸的问题,比如什么影响人类的创造力,什么影响我们的艺术体验,以及一件创造性作品的各个方面如何改变体验者的精神和心理反应水*。随着我们更好地理解这些问题,我们也可能在今天看来是一个遥远的目标上取得进展:未来的人工智能+群体超级创造实体能够拥有自己的意识体验吗?我们如何才能设计它,并在这个过程中理解人类意识是什么?

具体来说,需要复制什么样的人类神经过程才能使计算机,尽管它们的物理组成不同,达到人类体验艺术的能力?毕竟,艺术的主观体验恰恰是艺术的目标。我们尚未理解导致意识体验的物理过程或一系列计算:理论从“意识是一种幻觉”到“一切都是有意识的”,再到介于两者之间的一切,如基于物理学的理论(“意识是一种物质状态”), "意识产生于量子波函数")的坍缩,它区分了计算 I/O 和主观体验,也假设了潜在的 计算的物理基础 的重要性。 这是有意义的:有意识的体验比计算 I/O 更重要,一个有能力的人工智能艺术家的例子证明了这一点,他没有用于有意识体验的机器;没有证据表明计算可以独立于物质基础而有意识,就像没有证据表明灵魂独立于物质而存在一样。

创造性人工智能可能是人工通用智能的下一个里程碑,它推动了多模态和联想学习工程以及有效的人-人工智能协作流程的发展

就像国际象棋、围棋和图像识别被证明是导致专业人工智能进步的重要挑战一样,创造性人工智能可能是人工通用智能的下一个里程碑,它推动了多模态和关联学习的工程以及有效的人-人工智能协作过程的发展。正如巴斯蒂安·特龙所说,“我们甚至还没有开始理解人工智能会变得多么有创造力。如果你把世界上所有的知识和创造力都放进一个瓶子里,你会对瓶子里的东西感到惊讶。

Unnamed pastel portrait, courtesy of Mario Klingemann

承认

我们感谢凯特·巴兹、莉莉娅·叶夫根尼欧、沃洛季米尔·库里肖夫、帕特里克·西格勒·拉斯罗普、尼克·纳苏菲斯和巴斯蒂安·特龙的反馈和编辑,以及马里奥·克林格曼允许展示他的作品。我们特别感谢艺术家 Pamela Davis Kivelson 对“蛋白石蝴蝶 VR”和“量子材料研究”的评论、反馈和图像。

具有深度学习的超人“细胞视觉”

原文:https://towardsdatascience.com/superhuman-cell-sight-with-deep-learning-12003e309a01?source=collection_archive---------21-----------------------

使用“电子标记”来预测未标记图像中的荧光标记以及细胞形态、成分和结构。

一篇论文的分析:在《细胞》杂志上发表的未标记图像中预测荧光标记。

Fluorescently tagged neuronal cell culture. Source

看看这张图片,告诉我你看到了什么。

Figure 1. Source: Finkbeiner lab at the Gladstone Institutes. Bottom pictures are Outset 1, 2, 3 and 4.

如果你是一个相当聪明的人,有一些生物学背景(或者没有),你可能会猜到“一些细胞?”

恭喜你。你现在是生物学家了。

开玩笑,不是相当于。更具体地说,这一个人的运动神经元培养来源于诱导多能干细胞。

如果你设法猜到了,让我再问你一些问题。

  1. 开头 1 的群集中有多少个单元?
  2. 你能清楚地识别出开头 2 和 3 中的神经突和下面的细胞吗
  3. 开头 4 中的细胞是活的还是死的?

如果你是一名训练有素的生物学家,你可能会回答第三个问题,也可能是第一个问题。如果你真的很努力地试了试,也许你能回答所有的问题,只是非常错误。

现在去问问你其他的生物学家朋友。他们可能同意你的第三个答案,但不同意第一个。否则他们两个都会不同意。或者三者都有。啊,人类的判断——总是主观的,有时不可靠。

事实是,与生物技术的发展速度相比,我们的显微镜技术已经落后了。

想想看,我们的智能手机上有 DSLR 质量的相机,我们的手机图像看起来仍然像…这个?

真的吗?

我们可以升级显微镜方法。

上图使用的是所谓的透射光 显微镜,当样品的一面被照亮时,样品被成像——非常简单的技术。它对生物体相对无害,但至少可以说,解释实际图像是相当困难的。

具体来说,图 1 来自于相衬显微镜——像素的强度(有多亮/多暗)显示了当光通过样品时有多少光发生了相移。

现在,透射光显微镜有一个巧妙的技巧,可以让我们更好地观察实际细胞,称为 Z-stack。

Z 堆栈中的 Z 代表( x,y,z )三维坐标系中的 z 。这组图像被记录在(x,y)中,因为它们是 2D,而 z 是离相机的距离。由于你(系统地)改变了与相机的距离,你得到的多幅 2D 图像会略有不同,因为不同的部分进入和离开焦点。

Z-stack of a sphere. Source

这给了我们一个 更好的 三维表示,但是它的仍然很难理解。科学家还是要靠目测手动分析这些图像。

Figure 2: phase contrast z-stack of Figure 1. Source

回到我之前问你的问题,看看你能否使用 z-stack回答其中的一些问题。大概现在比较容易*回答了,但是你还是没有一个明确的答案。

*(请注意,您现在可以推断出开头 4 中的突出细胞可能经历了细胞凋亡,这是一种非常酷的程序性细胞收缩死亡机制)

现在我们来介绍一下 荧光显微镜 。样本经过荧光分子处理,这使得某些细胞结构(如细胞核)的可视化变得更加容易。

This is the SAME culture of human motor neurons as above! Source. Blue fluorescent labels detect DNA, thereby highlighting cell nuclei. Green labels detect a type of protein only found in dendrites. Red labels show axons.

现在,这种形象从翻盖手机的质量变成了布兰登·沃尔费尔的 Instagram feed 真快

虽然生动的图像看起来像是属于好莱坞科幻电影,但它确实需要像好莱坞电影一样长的准备时间(这只是稍微有点夸张)。也像好莱坞电影一样,它被许多许多问题所困扰。

  • 样品制备耗时复杂

  • 您需要特殊试剂(材料),由于抗体交叉反应性,这些试剂经常产生 非特异性 信号*

  • 标记协议(程序)可以 潜在地杀死细胞 !甚至活细胞协议都可以 光毒性 **

  • 不同 不同不同批次(还有人对人!)

  • 不会永远 !最终,它们停止表达荧光信号。

  • 不同颜色的标记可以彼此重叠 (光谱重叠),使得很难看出哪种颜色属于哪种标记(这限制了研究人员在每个样品中同时使用 3 或 4 种荧光标记)

  • 测量标记(即荧光标记信号有多强)需要一个光学系统——这样它可以在样品中的和其他标记之间进行分离,并检测荧光团漂白 ***

  • 抗体交叉反应是当不同的抗原出现类似于免疫系统。

当荧光标记的细胞持续暴露在激光和高强度灯的照射下时,会发生光毒性*。

*** 荧光团漂白基本上是褪色— 是指细胞因化学损伤而失去表达荧光信号的能力

更好的(深度)选择!

所以问题是,计算机能否预测未标记的图像中找到以前不知道的特征(例如。荧光)?

换句话说,我们能在没有标签的情况下突出显示单元格的某些部分吗?

正如你可能从我的标题中知道的——是的!

科学家们创造了一种称为 的新方法,即电子标记(ISL) ,它可以从样本的未标记 z 堆叠中推断出荧光标记。它还可以预测其他标签(例如细胞类型(神经、肝脏)和细胞状态(死亡或存活))。

它是一致的,不受光谱重叠的限制,并且不涉及改变或接触样品。它还可以产生某些生物测量值,这些测量值在以前是很难甚至不可能被 T42 获得的。

这是对电子贴标的概述。

Overview of a System to Train a Deep Neural Network to Make Predictions of Fluorescent Labels from Unlabeled Images. Source: [1]

该网络由许多 z 叠堆(图 1 左上)及其相应的荧光标签(图 1 左下)训练而成。

理想情况下,我们希望模型:

取一个看不见的 z-stack →预测不同荧光标记的归属

输出图像的每个像素在 256 个强度值(8 位像素)上有一个离散概率分布——这意味着每个像素都有可能是某个标签(例如,这个特定像素是 x% 可能是轴突)。为了制作图像,你取每个像素的预测分布的中值

在评估模型时,我们可以通过比较荧光标签与荧光样本的实际图像的相似程度来衡量性能(这是通过定性(观察)和定量(使用统计)来完成的)。

网络体系结构

该模型的网络架构类似于 Google 的 Inception 网络(通过重复模块的使用)并受到 U-Net (一种用于生物医学图像分割的卷积网络)的启发。

Each individual module. Red: expanding/reducing convolutions. Source [1].

在右侧路径上,输入通过卷积扩展特征尺寸,然后减小特征尺寸。在左侧,从输入复制特征值,形成一个剩余连接。下一个模块的输入是两个路径相加的和。

残余连接基本上防止了渐变消失的问题,当你添加更多的层时,渐变会逐渐变小。欲了解更多信息,请查看。

宏观架构类似于《盗梦空间》的模块。

Model Architecture. Source: [1]

如你所见,它有一个多刻度输入。z 堆栈中同一图像的多个“裁剪”(具有相同的焦点)—红框、蓝框、绿框等。计算多个特征。这允许模型学习上下文细节

Same center, different sizes.

最小的“裁剪”处理小规模的精细细节(上图左侧,建筑的紫色路径),而最大的裁剪处理粗略背景*和广泛特征(上图右侧,建筑的多色路径)——以及它们之间的三条中间路径。

Each color corresponds to a different computational path/tower.

与其他图像分类模型相比,这种架构的独特之处在于,这种不包含空间缩减 ,而空间缩减 会破坏精细细节,例如盗梦空间。

这是因为它部分受到了 U-Net 、的启发,其中最左边的路径保持输入的原始长度比例,因此信息可以从输入流到输出而不会模糊——允许网络学习细节!

特征拼接之后,五条路径合并成一条路径,输出预测。

The final path splits into the separate labels. Outputs a probability distribution for the intensity values per pixel, and the median is taken to form the final image.

这是模型的整体机器学习工作流程:

Machine-Learning Workflow for Network Development. Notice how the different Towers correspond to the 5 different computational paths in the model architecture above. They all then merge into a final path (the middle Tower @ Scale 1) and then split into multiple heads. Source: [1]

有了这组特定的训练图像,模型可以

  • 几乎相同地预测细胞核的位置

Input images/true labels/predicted labels. Source

  • 识别细胞是死是活 98% 的时候(相比人类 80%的准确率——即使是经验丰富的生物学家也能对同一张图像给出两种不同的答案)。它甚至在大量死亡细胞中检测出一个活细胞
  • 生成精确的细胞大小测量值
  • 能否区分某些细胞成分 与人类的准确度相匹配(如树突和轴突)

未来影响

通过这个实验,ISL 已经显示出它展示了迁移学习 —它可以将它在以前的映像上所学到的东西应用到全新的映像上!通过进一步的训练,我们可以教会这个模型分析 各种细胞

但是真正的问题是,我们能发现在之前我们不能发现的细胞特征吗?

机器有可能发现关于细胞的事实,从而导致下一个癌症疗法的发现吗?

这个模型已经差不多达到人类视力的水*了。

谁知道呢,它最终会被训练得足以拥有人类的超级视力。

关键要点

  • 目前的显微镜方法要么难以分析要么潜在危险
  • 一种标记图像的深度学习方法,“在计算机上标记的”可以预测细胞的看不见的图像上的荧光标记
  • 电子标记还可以预测细胞结构的位置细胞长度细胞是死是活
  • 迁移学习允许该模型用于其他细胞并预测新特征

来源

[1] E. Christiansen,S. Yang,D. Ando,L. Rubin,P. Nelson,S. Finkbeiner, In Silico Labeling:预测未标记图像中的荧光标记(2018),

如果您有任何问题,请随时联系:

  • 电子邮件:gracelyn.shi@gmail.com
  • 领英:https://www.linkedin.com/in/gracelynshi/
  • 推特:https://twitter.com/GracelynShi

监督学习:分类基础和主要算法

原文:https://towardsdatascience.com/supervised-learning-basics-of-classification-and-main-algorithms-c16b06806cd3?source=collection_archive---------5-----------------------

Picture from Unsplash

介绍

正如本系列第一篇文章所述,分类是监督学习的一个子类,其目标是基于过去的观察预测新实例的类别标签(离散、无序值、组成员)。

分类问题主要有两种类型:

  • 二元分类:典型的例子是邮件垃圾邮件检测,其中每封邮件都是垃圾邮件→ 1 封垃圾邮件;或者不是→ 0。
  • 多类分类:像手写字符识别(类从 0 到 9)。

下面的例子很有代表性地解释了二元分类法:

有两个类别,圆和十字,以及两个特征,X1 和 X2。该模型能够找到每个数据点的特征与其类别之间的关系,并在它们之间设置边界线,因此当提供新数据时,它可以估计其所属的类别,给定其特征。

Figure by Author

在这种情况下,新数据点落入圆形子空间,因此,模型将预测其类别为圆形。

不同的阶层

值得注意的是,并非每个分类模型都有助于从数据集中正确分离不同的类。一些算法,如感知器(基于基本的人工神经网络),如果类不能被线性决策边界分开,则在学习模型的权重时不会收敛。

下图展示了一些最典型的案例:

Figure by Author

因此,选择一个合适的算法的任务在分类问题中变得至关重要,这将是整篇文章中讨论的主要话题之一。

实践中的分类

在实践中,总是建议尝试和比较不同算法的性能,以便选择最合适的方法来解决问题。这种性能会受到可用数据、特征和样本数量、不同类别以及它们是否线性可分的影响。

提醒我们自己开发机器学习模型的六个主要步骤:

  1. 收集数据。
  2. 选择衡量成功的标准。
  3. 设置评估协议。
  4. 准备数据
  5. 开发基准模型
  6. 开发更好的模型并调整其超参数

接下来,我们将继续探索不同的分类算法,并了解哪种算法更适合执行每项任务。

逻辑回归

分类问题中的一个主要问题是在训练过程中,算法在权值更新时不收敛。

当类不是完全线性可分的时候就会发生这种情况。因此,为了解决二元分类问题,逻辑回归是最常用的算法之一。

逻辑回归是一个简单但强大的分类算法(尽管它的名字)。它在线性可分类上工作得非常好,并且可以通过 OvR 技术扩展到多类分类。

优势比

为了理解逻辑回归背后的思想,比值比是一个重要的概念。

比值比是某一事件发生的概率。它可以写成:

其中 P 代表积极事件(我们试图预测的事件)的概率。

由此我们可以定义 logit 函数。

Logit 功能

logit 函数就是比值比的对数(log-odds)。该函数将范围[0,1]内的值作为 am 输入值,并将其转换为整个实数范围[-∞,∞]内的值。

我们将使用它来表达特征值和对数优势之间的线性关系。

其中 P(y=1|x)是给定其特征 x,特定样本属于类别 1 的条件概率。

我们背后的真正动机是预测样本属于某一类的概率。这是 logit 函数的逆函数,通常称为 sigmoid 函数。

s 形函数

sigmoid 函数的公式为:

z 是净输入,它是权重和样本特征的线性组合,可计算如下:

当用图形表示时,它采用以下形状:

Figure by Author

我们可以看到,在等于 1 和 0 的(z)值中有两个极限。这意味着,如果 z 趋于无穷大,函数就接* 1,如果 z 趋于负无穷大,函数就接* 0。

因此,它采用实数值并将其转换到[0,1]范围,截距为(z) = 0.5。

Figure by Author

总之,这就是逻辑回归模型在被训练时所做的事情。sigmoid 函数的输出被解释为某个样本属于类别 1 的概率,假设其特征 x 由权重 w 参数化为,ψ(z)= P(y = 1 | x;w)。

预测概率可以通过单位阶跃函数(量化器)转换成二进制结果:

查看前面的 sigmoid 图,等价关系为:

这是逻辑回归算法如此受欢迎的主要原因之一,因为它返回某个样本属于某个特定类别的概率(0 到 1 之间的值)。

这在天气预报等情况下非常有用,在这种情况下,你不仅想知道是否会下雨,还想知道下雨的可能性。或者预测病人患某种疾病的几率。

支持向量机(SVM)

这个算法可以认为是感知器算法的的扩展。在 SVM 中,优化目标是通过最大化该线和最接*该超*面的样本点之间的余量来设置分隔类别的决策线。这些点被称为支持向量。

Figure by Author

最大保证金

为了设置最大边距,添加了两条*行线(边距),我们试图最大化它们到原始决策线的距离。我们将考虑错误分类的点(错误)以及页边空白和线条之间的点。

通常,具有较大边距的决策线往往具有较低的泛化误差。另一方面,利润率小的模型往往不太容易过度拟合。

最大化函数(误差余量)计算如下:

  1. 正负超*面可以表示为:

2.将(1)和(2)相减:

3.通过 w 向量的长度归一化前面的等式,其中:

4.我们得出边际误差方程:

哪个左侧被解释为正超*面和负超*面之间的距离,换句话说,就是我们试图最大化的边距。

在实践中,更容易最小化倒数项,这可以用二次规划来解决。

松弛变量:处理非线性可分离类

松弛变量ξ it 用于软边分类。其动机是需要放松线性约束,以便在处理非线性可分离数据时允许优化过程的收敛。

它被添加到线性约束中,新的最小化函数变成:

通过改变函数的 C 变量,我们可以控制错误分类的惩罚,并控制边缘的宽度。以这种方式调整偏差-方差权衡。

最佳的界限将取决于我们试图解决的问题。如果我们正面临一个医疗问题,我们不希望出现任何差错。而在面对其他类型的问题时,我们可以处理一些错误。

这是 C 值发挥作用的时候。

  • 大的 C 值对应于大的误差损失。
  • 较小的 C 值意味着我们对误分类错误不太严格。

Figure by Author

多项式核 SVM

SVM 是一个非常流行的算法分支,因为它可以用来解决非线性分类问题。这是通过一种叫做内核化的方法来实现的。

当处理原始特征的非线性组合时,使用核的基本思想是通过映射函数将它们投影到更高维的空间,因此数据变成线性可分的。

直观地说,原始数据集被转换到一个更高维的数据集,然后应用一个投影使类别可分离。

然后应用该算法,分类被分割,并应用投影函数的逆来返回数据的原始分布。

Figure by Author

RBF 内核

也用于处理非线性可分数据,如下所示:

Figure by Author

Figure by Author

这个想法是定位与每个类相一致的山脉和山谷。投影线分开两个类,也切断山谷线,原始线:

Figure by Author

投影将有效地分离原始数据集中的每个类。

为了改变山脉和山谷的宽度,我们将使用伽马参数γ。

gamma 参数是一个超参数,我们在训练期间对其进行调整,用于:

  • 较大的γ值→将产生狭窄的山脉/山谷,这将倾向于过度拟合。
  • 较小的值→将产生宽阔的山脉/山谷,这些山脉/山谷往往会被淹没。

此参数来自正态分布的公式:

Figure by Author

决策树算法

决策树算法通过提问来分解数据集,直到它们将数据缩小到足以做出预测。

这是一个决策树示例,用于决定是否将汽车借给某人:

Figure by Author

基于训练集的特征,决策树学习一系列问题来推断样本的类别标签。

起始节点称为树根,算法将在包含最大信息增益的要素上迭代拆分数据集,直到叶子(最终节点)是纯的。

决策树超参数

a)最大深度:

最大深度是从根部到叶子的最大长度。大深度会导致过度拟合,小深度会导致欠拟合。为了避免过度拟合,我们将通过设置具有最大深度的超参数来修剪决策树。

b)最大样本数量:

当分割一个节点时,可能会遇到这样的问题:一个分割中有 99 个样本,另一个分割中有 1 个样本。这将是一种资源浪费,为了避免这种情况,我们可以为每片叶子设置一个最大的样本数。它可以被指定为整数或浮点数。

样本数量少会导致过度拟合,而数量多则会导致欠拟合。

c)最小样本数量:

类似于前一个,但具有最小值。

d)最大特征数量:

很多时候,我们需要很多特征来构建一棵树。在每次分割中,我们必须检查每个要素的整个数据集,这可能非常昂贵。

这个问题的解决方案是限制在每次分割中寻找的特征的数量。如果这个数字足够高,我们很可能会在我们寻找的特征中找到一个好的特征(尽管它可能不是完美的)。然而,如果它没有特征的数量大,它将显著地加速计算。

随机森林

如果我们有一个包含许多特征(列)的数据集,决策树算法通常会过度拟合,使模型和学习过程变得过于复杂。

我们可以通过随机选择每个列并为每批列制作决策树来解决这个问题。

Original picture from this article

因此,我们的想法是开发一种集成学习算法,将一些较弱的模型结合起来,建立一个更健壮的模型。

该算法将执行以下步骤:

  • 抽取大小为 n 的随机 bootstrap 样本
  • 从 bootstrap 样本生成决策树。在每个节点:将随机选择 d 个特征而不替换,节点将被分裂以最大化信息增益。
  • 前面的过程将重复 k 次。
  • 同意每棵树所做的预测,通过多数投票指定类别标签。

这种方法的主要优点是,我们通常不需要修剪随机森林(因为模型对噪声相当鲁棒)。然而,它们比决策树更难理解。

我们需要调整的唯一超参数是树的数量。通常情况下, K 越大,模型的性能越好,但这会大幅增加计算成本。

k-最*邻(KNN)

k-最*邻算法或 KNN,属于一种特殊类型的机器学习模型,通常被称为“懒惰算法”。

他们之所以得到这个名字,是因为他们没有学会如何用优化函数来区分数据集,而是记住了数据集。

“懒惰算法”这个名字也指一种叫做非参数的算法。这些是基于实例的算法,它们的特点是记忆训练数据集,而懒惰学习是这些算法的一个特例,与学习期间的零计算成本相关。

算法

该算法遵循的总体过程是:

  1. 选择 k 的数量和距离度量。
  2. 找到要分类的样本的 k 个最*邻
  3. 通过多数投票分配类别标签

Figure by Author

该算法基于其对距离度量的预测,找到最接*要分类的点的 k 个样本。

主要的优点是,由于它是基于记忆的算法,它适应新的训练数据。不利的一面是计算成本随着训练数据的大小而线性增加。

需要考虑的事情

  • 在算法面临*局的情况下,它将优先选择与分类样本距离较*的邻居。在距离相似的情况下,KNN 将选择数据集中最先出现的分类标注。
  • 为了在过拟合和欠拟合之间取得良好的*衡,选择正确的 k 值是非常重要的。
  • 建立适当的距离度量也很重要。通常使用“闵可夫斯基”距离,它是欧几里德距离和曼哈顿距离的推广。该距离定义如下:

结论

在本文中,我们学习了分类的基础和主要算法,以及如何根据所面临的问题来调整它们。

在下一篇文章中,我们将探索其他非常常见的分类算法,称为“朴素贝叶斯”,我们将在一个项目中执行一个实现,在这个项目中,我们将建立一个分类模型,根据它的单词正确预测电子邮件是否是垃圾邮件。

感谢阅读,敬请关注!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/71091.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

TowardsDataScience-博客中文翻译-2016-2018-三十一-

TowardsDataScience 博客中文翻译 2016~2018(三十一)原文:TowardsDataScience Blog 协议:CC BY-NC-SA 4.0主成分分析:你的教程和代码原文:https://towardsdatascience.com/principal-component-analysis-your-tutorial-and-code-9719d3d3f376?source=collection_archive-…

TowardsDataScience-博客中文翻译-2016-2018-三十八-

TowardsDataScience 博客中文翻译 2016~2018(三十八)原文:TowardsDataScience Blog 协议:CC BY-NC-SA 4.0Python 属性的原因和方式原文:https://towardsdatascience.com/the-why-and-how-of-python-properties-b791817cf4b9?source=collection_archive---------3--------…

2024-2025-1 20241327 《计算机基础与程序设计》第三周学习总结

作业信息 |2024-2025-1-计算机基础与程序设计)| |-- |- |2024-2025-1计算机基础与程序设计第二周作业)| |快速浏览一遍教材计算机科学概论(第七版),课本每章提出至少一个自己不懂的或最想解决的问题并在期末回答这些问题 |作业正文|https://www.cnblogs.com/shr060414/p/18…

『模拟赛』多校A层冲刺NOIP2024模拟赛06(更新 T4)

『模拟赛记录』多校A层冲刺NOIP2024模拟赛06Rank 比较还行A. 小 Z 的手套(gloves) 签。 最大值最小,一眼二分答案。双指针 check 一下就完了,复杂度 \(\mathcal{O(n\log n)}\)。点击查看代码 #include<bits/stdc++.h> #define fo(x, y, z) for(register int (x) = (y…

Grafana学习笔记1

安装 Grafana容器镜像拉取 docker pull grafana/grafana启用Grafana容器 命名为Grafa,再把主机端口3000映射到容器端口3000,把主机上的目录/path/to/your/grafana/data(这个路径自己定义)挂载到容器内的目录/var/lib/grafana,设置管理员密码为admin,使用已经拉取的镜像grafan…

4.漏洞挖掘(长期)

具体漏洞复现,见奇安信攻防社区的帖子。 国庆假期,试挖漏洞算是揭开的漏洞挖掘的面纱。第一个练手的漏洞是敏感信息漏洞。一开始,手工查找,google搜索,后来在chatGPTd 帮助下,学习研究脚本进行扫描。 但现在了,脚本不太好研究下去了,并且没太大兴趣继续,感觉太low了,…

Mysql(1)—简介及Windows环境下载安装

MySQL是一个流行的关系型数据库管理系统(RDBMS),它基于结构化查询语言(SQL)进行操作。MySQL由瑞典MySQL AB公司开发,后来被Sun Microsystems收购,最终成为Oracle公司的产品。它是最广泛使用的开源数据库之一,通常用于Web应用程序、数据仓库和企业应用。Mysql(1)—简介及…

linux练习题(二)

习题练习前预备知识(如下图):## linux练习题(二)习题以及参考答案 1、将/etc/passwd 拷贝到/home下并更名为test。cp /etc/passwd /home/test 2、在/tmp下建立test1到test9父子级目录,mkdir -p /tmp/test1/test2/test3/test4/test5/test6/test7/test8/test9 如果说该条命…